diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 000000000..d13a8592a --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_JOBS: "4" diff --git a/.ruby-version b/.ruby-version index bff6ce5c1..7bde84d06 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.7.1 +ruby-3.1.2 diff --git a/Gemfile b/Gemfile index b7e8b4cc5..074faaf0a 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -ruby '2.7.1' +ruby '3.1.2' gem 'activesupport', '~> 6.0', '>= 6.0.3.2', require: 'active_support/all' gem 'minitest', '~> 5.14', '>= 5.14.1' diff --git a/Gemfile.lock b/Gemfile.lock index dd4e2a4e5..a557ba4b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,8 @@ GIT remote: https://github.com/kern/minitest-reporters.git - revision: 9cb9e78aed69bfe4eed6c27b5b795e8bb4ad708f + revision: 466b060a906298148836e368916aee930d28f618 specs: - minitest-reporters (1.4.2) + minitest-reporters (1.5.0) ansi builder minitest (>= 5.0) @@ -11,29 +11,28 @@ GIT GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.2) + activesupport (6.1.6) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) ansi (1.5.0) builder (3.2.4) coderay (1.1.3) - concurrent-ruby (1.1.6) - i18n (1.8.3) + concurrent-ruby (1.1.10) + i18n (1.10.0) concurrent-ruby (~> 1.0) method_source (1.0.0) - minitest (5.14.1) + minitest (5.15.0) pry (0.13.1) coderay (~> 1.1) method_source (~> 1.0) - rake (13.0.1) - ruby-progressbar (1.10.1) - thread_safe (0.3.6) - tzinfo (1.2.7) - thread_safe (~> 0.1) - zeitwerk (2.4.0) + rake (13.0.6) + ruby-progressbar (1.11.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + zeitwerk (2.5.4) PLATFORMS mswin64 @@ -48,7 +47,7 @@ DEPENDENCIES rake (~> 13.0, >= 13.0.1) RUBY VERSION - ruby 2.7.1p83 + ruby 3.1.2p20 BUNDLED WITH 2.1.4 diff --git a/lib/compiler.rb b/lib/compiler.rb index 1839f95ff..1ce544861 100644 --- a/lib/compiler.rb +++ b/lib/compiler.rb @@ -487,7 +487,7 @@ def log(message = nil) warn message end - def stuff(library, &block) + def stuff(library, &) source = File.join PRJ_ROOT, 'vendor', library target = File.join @options[:tmpdir], library @@ -498,7 +498,7 @@ def stuff(library, &block) log "=> Stuffing #{library}..." @utils.capture_run_io "stuff_#{library}" do - @utils.chdir(target, &block) + @utils.chdir(target, &) end log "=> Stuffed #{library}" @@ -789,7 +789,7 @@ def local_toolchain_env { 'CI' => 'true', 'GEM_PATH' => File.join(@ruby_install, 'lib', 'ruby', 'gems', self.class.ruby_api_version), - 'PATH' => "#{File.join(@ruby_install, 'bin')}:#{ENV['PATH']}", + 'PATH' => "#{File.join(@ruby_install, 'bin')}:#{ENV.fetch('PATH', nil)}", 'ENCLOSE_IO_USE_ORIGINAL_RUBY' => 'true', 'ENCLOSE_IO_RUBYC_1ST_PASS' => 'true', 'ENCLOSE_IO_RUBYC_2ND_PASS' => nil diff --git a/lib/compiler/utils.rb b/lib/compiler/utils.rb index 00a1a024f..9ff39ca70 100644 --- a/lib/compiler/utils.rb +++ b/lib/compiler/utils.rb @@ -77,9 +77,9 @@ def run_allow_failures(*args) status end - def chdir(path, &block) + def chdir(path, &) warn "-> cd #{path}" unless @options[:quiet] - Dir.chdir(path, &block) + Dir.chdir(path, &) warn "-> cd #{Dir.pwd}" unless @options[:quiet] end @@ -90,7 +90,7 @@ def cp(from, to) def cp_r(from, to, options = {}) warn "-> cp -r #{from.inspect} #{to.inspect}" unless @options[:quiet] - FileUtils.cp_r(from, to, options) + FileUtils.cp_r(from, to, **options) end def rm(path) diff --git a/ruby/.appveyor.yml b/ruby/.appveyor.yml new file mode 100644 index 000000000..9ebe41e1c --- /dev/null +++ b/ruby/.appveyor.yml @@ -0,0 +1,104 @@ +--- +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' +environment: + ruby_version: "24-%Platform%" + zlib_version: "1.2.11" + matrix: + - build: vs + vs: 120 + ssl: OpenSSL + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + GEMS_FOR_TEST: "" + - build: vs + vs: 140 + ssl: OpenSSL-v111 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + GEMS_FOR_TEST: "" + RELINE_TEST_ENCODING: "UTF-8" +for: +- + matrix: + only: + - build: vs + install: + - ver + - chcp + - SET BITS=%Platform:x86=32% + - SET BITS=%BITS:x=% + - SET OPENSSL_DIR=C:\%ssl%-Win%BITS% + - 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 + - SET ZLIB_ZIP=.downloaded-cache\zlib%zlib_version:.=%.zip + - if not exist %ZLIB_ZIP% curl -fsSL -o %ZLIB_ZIP% --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip + - 7z x -aos -o%APPVEYOR_BUILD_FOLDER%\ext\zlib %ZLIB_ZIP% + - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I + - attrib +r /s /d + - mkdir %Platform%-mswin_%vs% + build_script: + - cd %APPVEYOR_BUILD_FOLDER% + - cd %Platform%-mswin_%vs% + - ..\win32\configure.bat --without-ext=+,dbm,gdbm,readline --with-opt-dir=/usr/local --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=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor -j%JOBS% --exclude readline --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=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" test-all 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" + - nmake -l test-spec MSPECOPT=-fs # 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 / 2015", + "url": "{{buildUrl}}", + "commit": "{{commitId}}", + "branch": "{{branch}}" + } + {{/isPullRequest}} + on_build_success: false + on_build_failure: true + on_build_status_changed: false diff --git a/ruby/.cirrus.yml b/ruby/.cirrus.yml new file mode 100644 index 000000000..c8fb326c8 --- /dev/null +++ b/ruby/.cirrus.yml @@ -0,0 +1,64 @@ +# 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 + LANG: C.UTF-8 + +task: + name: Arm64 Graviton2 / $CC + skip: "changesIncludeOnly('doc/**', '**.{md,rdoc}')" + arm_container: + # We use the arm64 images at http://ghcr.io/ruby/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 + env: + CIRRUS_CLONE_DEPTH: 50 + optflags: '-O1' + debugflags: '-ggdb3' + RUBY_PREFIX: /tmp/ruby-prefix + RUBY_DEBUG: ci rgengc + RUBY_TESTOPTS: >- + -q + --color=always + --tty=no + matrix: + CC: clang-12 + CC: gcc-11 + id_script: id + set_env_script: + # Set `GNUMAKEFLAGS`, because the flags are GNU make specific. Note using + # the `make` environment variable used in compilers.yml causes some rubygems + # tests to fail. + # https://github.com/rubygems/rubygems/issues/4921 + - echo "GNUMAKEFLAGS=-s -j$((1 + $CIRRUS_CPU))" >> $CIRRUS_ENV + print_env_script: + - echo "GNUMAKEFLAGS=$GNUMAKEFLAGS" + # 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" + make_extract-extlibs_script: make extract-extlibs + make_incs_script: make incs + make_script: make + make_leaked-globals_script: make leaked-globals + 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 diff --git a/ruby/.dir-locals.el b/ruby/.dir-locals.el index 7c32d1f7e..8f4b96445 100644 --- a/ruby/.dir-locals.el +++ b/ruby/.dir-locals.el @@ -24,6 +24,8 @@ (c-mode . ((c-file-style . "ruby"))) + (c++-mode . ((c-file-style . "ruby"))) + (change-log-mode . ((buffer-file-coding-system . us-ascii) (indent-tabs-mode . t) diff --git a/ruby/.document b/ruby/.document index 8a418e5d4..6e08f4269 100644 --- a/ruby/.document +++ b/ruby/.document @@ -11,10 +11,18 @@ prelude.rb rbconfig.rb +array.rb ast.rb +dir.rb gc.rb io.rb +kernel.rb +marshal.rb +numeric.rb +nilclass.rb pack.rb +ractor.rb +timev.rb trace_point.rb warning.rb @@ -25,7 +33,7 @@ lib ext # rdoc files -NEWS +NEWS.md README.md README.ja.md diff --git a/ruby/.gdbinit b/ruby/.gdbinit index 0d4462269..8979e8b47 100644 --- a/ruby/.gdbinit +++ b/ruby/.gdbinit @@ -136,7 +136,7 @@ define rp printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len if ($flags & RUBY_FL_USER2) printf "(shared) shared=" - output/x ((struct RArray*)($arg0))->as.heap.aux.shared + output/x ((struct RArray*)($arg0))->as.heap.aux.shared_root printf " " else printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa @@ -156,12 +156,12 @@ define rp else 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) + if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG) printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries 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) + ((((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) end print (struct RHash *)($arg0) else @@ -264,6 +264,10 @@ define rp if ($flags & RUBY_T_MASK) == RUBY_T_ZOMBIE printf "%sT_ZOMBIE%s: ", $color_type, $color_end print (struct RData *)($arg0) + else + if ($flags & RUBY_T_MASK) == RUBY_T_MOVED + printf "%sT_MOVED%s: ", $color_type, $color_end + print *(struct RMoved *)$arg0 else printf "%sunknown%s: ", $color_type, $color_end print (struct RBasic *)($arg0) @@ -300,6 +304,7 @@ define rp end end end + end end document rp Print a Ruby's VALUE. @@ -1097,11 +1102,11 @@ define print_id set $arylen = $ary->as.heap.len end set $result = $aryptr[($serial % ID_ENTRY_UNIT) * ID_ENTRY_SIZE + $t] - if $result != RUBY_Qnil + if $result != RUBY_Qnil print_string $result - else - echo undef - end + else + echo undef + end end end end @@ -1274,7 +1279,7 @@ document rb_count_objects Counts all objects grouped by type. end -# Details: https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MachineInstructionsTraceWithGDB +# Details: https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB define trace_machine_instructions set logging on set height 0 @@ -1319,8 +1324,7 @@ define print_flags 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_FINALIZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FINALIZE ? "1" : "0" - printf "RUBY_FL_TAINT : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_TAINT ? "1" : "0" - printf "RUBY_FL_UNTRUSTED : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_UNTRUSTED ? "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" printf "RUBY_FL_FREEZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FREEZE ? "1" : "0" diff --git a/ruby/.gitattributes b/ruby/.gitattributes new file mode 100644 index 000000000..d0c2d266b --- /dev/null +++ b/ruby/.gitattributes @@ -0,0 +1,8 @@ +*.gemspec diff=ruby +*.rb diff=ruby +bin svn-properties=svn:ignore=ruby +bin/* diff=ruby +tool/update-deps diff=ruby +tool/make-snapshot diff=ruby +tool/format-release diff=ruby +tool/leaked-globals diff=ruby diff --git a/ruby/.github/CODEOWNERS b/ruby/.github/CODEOWNERS new file mode 100644 index 000000000..15abc79af --- /dev/null +++ b/ruby/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. +# Code owners will be automatically tagged as reviewers when a pull request is opened + +# YJIT sources and tests +yjit* @maximecb @xrxr @tenderlove +doc/yjit/* @maximecb @xrxr @tenderlove +bootstraptest/test_yjit* @maximecb @xrxr @tenderlove +test/ruby/test_yjit* @maximecb @xrxr @tenderlove +.github/workflows/yjit* @maximecb @xrxr @tenderlove diff --git a/ruby/.github/SECURITY.md b/ruby/.github/SECURITY.md new file mode 100644 index 000000000..56baa2994 --- /dev/null +++ b/ruby/.github/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Supported Versions + +See . + +## Reporting a Vulnerability + +See . diff --git a/ruby/.github/codeql/codeql-config.yml b/ruby/.github/codeql/codeql-config.yml new file mode 100644 index 000000000..91f82b842 --- /dev/null +++ b/ruby/.github/codeql/codeql-config.yml @@ -0,0 +1,3 @@ +name: "CodeQL config for the Ruby language" + +languages: cpp diff --git a/ruby/.github/workflows/baseruby.yml b/ruby/.github/workflows/baseruby.yml new file mode 100644 index 000000000..cf86c2d7d --- /dev/null +++ b/ruby/.github/workflows/baseruby.yml @@ -0,0 +1,65 @@ +name: BASERUBY Check + +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + baseruby: + name: BASERUBY + runs-on: ubuntu-20.04 + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + strategy: + matrix: + ruby: + - ruby-2.2 +# - ruby-2.3 +# - ruby-2.4 +# - ruby-2.5 +# - ruby-2.6 + - ruby-2.7 + - ruby-3.0 + + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: .downloaded-cache + key: downloaded-cache + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler: none + - run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: sudo apt-get install build-essential autoconf bison + - run: ./autogen.sh + - run: ./configure --disable-install-doc + - run: make common-srcs + - run: make incs + - run: make all + - run: make test + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / BASERUBY @ ${{ matrix.ruby }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/ruby/.github/workflows/bundled_gems.yml b/ruby/.github/workflows/bundled_gems.yml new file mode 100644 index 000000000..12fb2b06e --- /dev/null +++ b/ruby/.github/workflows/bundled_gems.yml @@ -0,0 +1,131 @@ +name: bundled_gems + +on: + push: + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + pull_request: + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + schedule: + - cron: '45 6 * * *' + +jobs: + update: + if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }} + name: update ${{ github.workflow }} + runs-on: ubuntu-latest + steps: + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + echo "TODAY=$(date +%F)" >> $GITHUB_ENV + + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: .downloaded-cache + key: downloaded-cache-${{ github.sha }} + restore-keys: | + downloaded-cache + + - 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 + + - name: Update bundled gems list + run: | + ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems + + - name: Maintain updated gems list in NEWS + run: | + require 'json' + news = File.read("NEWS.md") + prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1] + prevs = [prev, prev.sub(/\.\d+\z/, '')] + %W[bundled].each do |type| + last = JSON.parse(File.read("#{type}_gems.json"))['gems'].filter_map do |g| + v = g['versions'].values_at(*prevs).compact.first + g = g['gem'] + g = 'RubyGems' if g == 'rubygems' + [g, v] if v + end.to_h + changed = File.foreach("gems/#{type}_gems").filter_map do |l| + next if l.start_with?("#") + g, v = l.split(" ", 3) + [g, v] unless last[g] == v + end + changed, added = changed.partition {|g, _| last[g]} + news.sub!(/^\*\s+The following #{type} gems? are updated\.(\n\s+\*\s+)\K.*(?:\1.*)*/) do + changed.map {|g, v|"#{g} #{v}"}.join($1) + end or exit + news.sub!(/^\*\s+The following default gems are now bundled.*(\n\s+\*\s+)\K.*(?:\1.*)*/) do + added.map {|g, v|"#{g} #{v}"}.join($1) + end if added + File.write("NEWS.md", news) + end + shell: ruby {0} + + - 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 + + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + if: ${{ steps.diff.outcome == 'failure' }} + + - name: Build + run: | + ./autogen.sh + ./configure -C --disable-install-doc + make + if: ${{ steps.diff.outcome == 'failure' }} + + - 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 + + - 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]" + else + git commit --message="${message}${TODAY}" + fi + 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.show.outcome == 'failure' }} diff --git a/ruby/.github/workflows/check_dependencies.yml b/ruby/.github/workflows/check_dependencies.yml new file mode 100644 index 000000000..6c7e8e578 --- /dev/null +++ b/ruby/.github/workflows/check_dependencies.yml @@ -0,0 +1,65 @@ +name: Check Dependencies +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + update-deps: + strategy: + matrix: + os: [ubuntu-20.04] + fail-fast: true + runs-on: ${{ matrix.os }} + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + if: ${{ contains(matrix.os, 'ubuntu') }} + - name: Install libraries + run: | + brew upgrade + brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline + if: ${{ contains(matrix.os, 'macos') }} + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: .downloaded-cache + key: downloaded-cache + - run: ./autogen.sh + - 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: ruby tool/update-deps --fix + - run: git diff --no-ext-diff --ignore-submodules --exit-code + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / Dependencies need to update", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/ruby/.github/workflows/codeql-analysis.yml b/ruby/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..f81c79902 --- /dev/null +++ b/ruby/.github/workflows/codeql-analysis.yml @@ -0,0 +1,61 @@ +name: "Code scanning - action" + +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + schedule: + - cron: '0 12 * * 4' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + CodeQL-Build: + + # CodeQL runs on ubuntu-latest and windows-latest + runs-on: ubuntu-latest + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + + env: + enable_install_doc: no + + steps: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + + - name: Checkout repository + uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: .downloaded-cache + key: downloaded-cache + + - name: Remove an obsolete rubygems vendored file + run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + config-file: ./.github/codeql/codeql-config.yml + + - name: Set ENV + run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/ruby/.github/workflows/compilers.yml b/ruby/.github/workflows/compilers.yml new file mode 100644 index 000000000..2af9fa55d --- /dev/null +++ b/ruby/.github/workflows/compilers.yml @@ -0,0 +1,247 @@ +name: Compilations + +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +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-14 + append_cc: '' + crosshost: '' + + # -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 + + UPDATE_UNICODE: >- + UNICODE_FILES=. + UNICODE_PROPERTY_FILES=. + UNICODE_AUXILIARY_FILES=. + UNICODE_EMOJI_FILES=. + CONFIGURE_TTY: never + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUBY_DEBUG: ci rgengc + RUBY_TESTOPTS: >- + -q + --color=always + --tty=no + +jobs: + compile: + strategy: + fail-fast: false + matrix: + entry: + - { key: default_cc, name: gcc-11, value: gcc-11, container: gcc-11 } + - { key: default_cc, name: gcc-10, value: gcc-10, container: gcc-10 } + - { key: default_cc, name: gcc-9, value: gcc-9, container: gcc-9 } + - { key: default_cc, name: gcc-8, value: gcc-8, container: gcc-8 } + - { key: default_cc, name: gcc-7, value: gcc-7, container: gcc-7 } + - { key: default_cc, name: gcc-6, value: gcc-6, container: gcc-6 } + - { key: default_cc, name: gcc-5, value: gcc-5, container: gcc-5 } + - { key: default_cc, name: gcc-4.8, value: gcc-4.8, container: gcc-4.8 } + - key: default_cc + name: 'gcc-11 LTO' + value: 'gcc-11 -O2 -flto=auto -ffat-lto-objects' + container: gcc-11 + shared: '--disable-shared' + # check: true + - { key: default_cc, name: clang-14, value: clang-14, container: clang-14 } + - { key: default_cc, name: clang-13, value: clang-13, container: clang-13 } + - { key: default_cc, name: clang-12, value: clang-12, container: clang-12 } + - { key: default_cc, name: clang-11, value: clang-11, container: clang-11 } + - { key: default_cc, name: clang-10, value: clang-10, container: clang-10 } + - { key: default_cc, name: clang-9, value: clang-9, container: clang-9 } + - { key: default_cc, name: clang-8, value: clang-8, container: clang-8 } + - { key: default_cc, name: clang-7, value: clang-7, container: clang-7 } + - { key: default_cc, name: clang-6.0, value: clang-6.0, container: clang-6.0 } + - { key: default_cc, name: clang-5.0, value: clang-5.0, container: clang-5.0 } + - { key: default_cc, name: clang-4.0, value: clang-4.0, container: clang-4.0 } + - { key: default_cc, name: clang-3.9, value: clang-3.9, container: clang-3.9 } + - key: default_cc + name: 'clang-14 LTO' + value: 'clang-14 -O2 -flto=auto' + container: clang-14 + shared: '--disable-shared' + # check: true + + - { key: crosshost, name: aarch64-linux-gnu, value: aarch64-linux-gnu, container: crossbuild-essential-arm64 } +# - { key: crosshost, name: arm-linux-gnueabi, value: arm-linux-gnueabi } +# - { key: crosshost, name: arm-linux-gnueabihf, value: arm-linux-gnueabihf } +# - { key: crosshost, name: i686-w64-mingw32, value: i686-w64-mingw32 } +# - { key: crosshost, name: powerpc-linux-gnu, value: powerpc-linux-gnu } + - { key: crosshost, name: powerpc64le-linux-gnu, value: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el } + - { key: crosshost, name: s390x-linux-gnu, value: s390x-linux-gnu, container: crossbuild-essential-s390x } + - { key: crosshost, name: x86_64-w64-mingw32, value: x86_64-w64-mingw32, container: mingw-w64 } + + - { key: append_cc, name: c99, value: '-std=c99 -Werror=pedantic -pedantic-errors' } +# - { key: append_cc, name: c11, value: '-std=c11 -Werror=pedantic -pedantic-errors' } +# - { key: append_cc, name: c17, value: '-std=c17 -Werror=pedantic -pedantic-errors' } + - { key: append_cc, name: c2x, value: '-std=c2x -Werror=pedantic -pedantic-errors' } + - { key: CXXFLAGS, name: c++98, value: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } +# - { key: CXXFLAGS, name: c++11, value: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } +# - { key: CXXFLAGS, name: c++14, value: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } +# - { key: CXXFLAGS, name: c++17, value: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } + - { key: CXXFLAGS, name: c++2a, value: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } + + - { key: optflags, name: '-O0', value: '-O0 -march=x86-64 -mtune=generic' } +# - { key: optflags, name: '-O3', value: '-O3 -march=x86-64 -mtune=generic', check: true } + + - { key: append_configure, name: gmp, value: '--with-gmp' } + - { key: append_configure, name: jemalloc, value: '--with-jemalloc' } + - { key: append_configure, name: valgrind, value: '--with-valgrind' } + - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' } + - { key: append_configure, name: 'coroutine=pthread', value: '--with-coroutine=pthread' } + - { key: append_configure, name: disable-jit-support, value: '--disable-jit-support' } + - { key: append_configure, name: disable-dln, value: '--disable-dln' } + - { key: append_configure, name: disable-rubygems, value: '--disable-rubygems' } + + - { key: cppflags, name: OPT_THREADED_CODE=1, value: '-DOPT_THREADED_CODE=1' } + - { key: cppflags, name: OPT_THREADED_CODE=2, value: '-DOPT_THREADED_CODE=2' } + - { key: cppflags, name: OPT_THREADED_CODE=3, value: '-DOPT_THREADED_CODE=3' } + + - { key: cppflags, name: NDEBUG, value: '-DNDEBUG' } + - { key: cppflags, name: RUBY_DEBUG, value: '-DRUBY_DEBUG' } +# - { key: cppflags, name: ARRAY_DEBUG, value: '-DARRAY_DEBUG' } +# - { key: cppflags, name: BIGNUM_DEBUG, value: '-DBIGNUM_DEBUG' } +# - { key: cppflags, name: CCAN_LIST_DEBUG, value: '-DCCAN_LIST_DEBUG' } +# - { key: cppflags, name: CPDEBUG=-1, value: '-DCPDEBUG=-1' } +# - { key: cppflags, name: ENC_DEBUG, value: '-DENC_DEBUG' } +# - { key: cppflags, name: GC_DEBUG, value: '-DGC_DEBUG' } +# - { key: cppflags, name: HASH_DEBUG, value: '-DHASH_DEBUG' } +# - { key: cppflags, name: ID_TABLE_DEBUG, value: '-DID_TABLE_DEBUG' } +# - { key: cppflags, name: RGENGC_DEBUG=-1, value: '-DRGENGC_DEBUG=-1' } +# - { key: cppflags, name: SYMBOL_DEBUG, value: '-DSYMBOL_DEBUG' } +# - { key: cppflags, name: THREAD_DEBUG=-1, value: '-DTHREAD_DEBUG=-1' } + +# - { key: cppflags, name: RGENGC_CHECK_MODE, value: '-DRGENGC_CHECK_MODE' } +# - { key: cppflags, name: TRANSIENT_HEAP_CHECK_MODE, value: '-DTRANSIENT_HEAP_CHECK_MODE' } +# - { key: cppflags, name: VM_CHECK_MODE, value: '-DVM_CHECK_MODE' } + + - { key: cppflags, name: USE_EMBED_CI=0, value: '-DUSE_EMBED_CI=0' } + - { key: cppflags, name: USE_FLONUM=0, value: '-DUSE_FLONUM=0' } +# - { key: cppflags, name: USE_GC_MALLOC_OBJ_INFO_DETAILS, value: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } + - { key: cppflags, name: USE_LAZY_LOAD, value: '-DUSE_LAZY_LOAD' } +# - { key: cppflags, name: USE_RINCGC=0, value: '-DUSE_RINCGC=0' } +# - { key: cppflags, name: USE_SYMBOL_GC=0, value: '-DUSE_SYMBOL_GC=0' } +# - { key: cppflags, name: USE_THREAD_CACHE=0, value: '-DUSE_THREAD_CACHE=0' } +# - { key: cppflags, name: USE_TRANSIENT_HEAP=0, value: '-DUSE_TRANSIENT_HEAP=0' } +# - { key: cppflags, name: USE_RUBY_DEBUG_LOG=1, value: '-DUSE_RUBY_DEBUG_LOG=1' } + + - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' } + - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' } +# - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' } + + - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' } +# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' } +# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' } +# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' } + +# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' } +# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' } + +# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } + +# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' } +# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' } +# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' } +# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' } +# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' } + +# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' } +# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } + + - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' } + - { key: cppflags, name: YJIT_FORCE_ENABLE, value: '-DYJIT_FORCE_ENABLE' } + + name: ${{ matrix.entry.name }} + runs-on: ubuntu-latest + container: + image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || 'clang-14' }} + options: --user root + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: id + working-directory: + - run: mkdir build + working-directory: + - name: setenv + run: | + echo "${{ matrix.entry.key }}=${{ matrix.entry.value }}" >> $GITHUB_ENV + echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: > + ../src/configure -C ${default_configure} ${append_configure} + ${{ matrix.entry.key == 'crosshost' && '--host="${crosshost}"' || '--with-gcc="${default_cc} ${append_cc}"' }} + ${{ matrix.entry.shared || '--enable-shared' }} + - run: make extract-extlibs + - run: make incs + - run: make + - run: make leaked-globals + - run: make test + - run: make install + if: ${{ matrix.entry.check }} + - run: make prepare-gems + 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 + if: ${{ matrix.entry.check }} + + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.entry.name }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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/ruby/.github/workflows/mingw.yml b/ruby/.github/workflows/mingw.yml new file mode 100644 index 000000000..0d7eef67c --- /dev/null +++ b/ruby/.github/workflows/mingw.yml @@ -0,0 +1,148 @@ +name: MinGW +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +# Notes: +# Actions console encoding causes issues, see test-all & test-spec steps +# +jobs: + make: + runs-on: windows-2022 + name: ${{ github.workflow }} (${{ matrix.msystem }}) + env: + MSYSTEM: ${{ matrix.msystem }} + MSYS2_ARCH: x86_64 + CHOST: "x86_64-w64-mingw32" + CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong" + CXXFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe" + CPPFLAGS: "-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048" + LDFLAGS: "-pipe -fstack-protector-strong" + UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=." + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + strategy: + matrix: + include: + - msystem: "MINGW64" + base_ruby: 2.6 + test_task: [ "check" ] # to make job names consistent + - msystem: "UCRT64" + base_ruby: head + test_task: [ "check" ] # to make job names consistent + fail-fast: false + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: git config + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Set up Ruby & MSYS2 + uses: MSP-Greg/ruby-setup-ruby@win-ucrt-1 + with: + ruby-version: ${{ matrix.base_ruby }} + - name: set env + run: | + echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV + echo "TEST_JOBS=$((15 * NUMBER_OF_PROCESSORS / 10))" >> $GITHUB_ENV + + - name: where check + run: | + # show where + result=true + for e in gcc.exe ragel.exe make.exe bison.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do + echo '##['group']'$'\033[93m'$e$'\033[m' + where $e || result=false + echo '##['endgroup']' + done + $result + + - name: autogen + run: | + ./autogen.sh + working-directory: src + + - name: configure + run: > + ../src/configure --disable-install-doc --prefix=/. + --build=$CHOST --host=$CHOST --target=$CHOST + + - name: update + run: | + make incs + + - name: download gems + run: | + make update-gems + + - name: make all + timeout-minutes: 20 + run: | + make + + - run: make leaked-globals + + - name: make install + run: | + make DESTDIR=../install install-nodoc + + - name: test + timeout-minutes: 5 + run: | + make test + + - name: test-all + timeout-minutes: 45 + run: | + # Actions uses UTF8, causes test failures, similar to normal OS setup + chcp.com 437 + make test-all + env: + RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --retry --job-status=normal --show-skip --timeout-scale=1.5 + BUNDLER_VERSION: + + - name: test-spec + timeout-minutes: 10 + run: | + make test-spec + + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.test_task }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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 + shell: sh diff --git a/ruby/.github/workflows/mjit.yml b/ruby/.github/workflows/mjit.yml new file mode 100644 index 000000000..75e5b1088 --- /dev/null +++ b/ruby/.github/workflows/mjit.yml @@ -0,0 +1,97 @@ +name: MJIT +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + make: + strategy: + matrix: + test_task: [ "check" ] # to make job names consistent + jit_opts: [ "--mjit", "--mjit-wait" ] + fail-fast: false + runs-on: ubuntu-latest + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + env: + TESTOPTS: '-q --tty=no' + RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --mjit-debug=-ggdb3' + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + steps: + - run: mkdir build + working-directory: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc cppflags=-DVM_CHECK_MODE + - run: make incs + - run: make + - run: sudo make -s install + - run: sudo apt-get install gdb # used by test / test-all failure + - name: Run test + run: | + ulimit -c unlimited + make -s test RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + - name: Run test-all + run: | + ulimit -c unlimited + make -s test-all RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + - name: Run test-spec + run: | + ulimit -c unlimited + make -s test-spec RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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/ruby/.github/workflows/spec_guards.yml b/ruby/.github/workflows/spec_guards.yml new file mode 100644 index 000000000..3f829650d --- /dev/null +++ b/ruby/.github/workflows/spec_guards.yml @@ -0,0 +1,53 @@ +name: Rubyspec Version Guards Check + +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + rubyspec: + name: Rubyspec + runs-on: ubuntu-20.04 + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + strategy: + matrix: + # 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-2.7 + - ruby-3.0 + + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler: none + - run: gem install webrick + - run: ruby ../mspec/bin/mspec + working-directory: spec/ruby + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }} / rubyspec @ ${{ matrix.ruby }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() && github.event_name == 'push' }} diff --git a/ruby/.github/workflows/ubuntu.yml b/ruby/.github/workflows/ubuntu.yml new file mode 100644 index 000000000..ff79dad88 --- /dev/null +++ b/ruby/.github/workflows/ubuntu.yml @@ -0,0 +1,129 @@ +name: Ubuntu +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + make: + strategy: + matrix: + test_task: ["check", "test-bundler-parallel", "test-bundled-gems"] + os: + - ubuntu-20.04 +# - ubuntu-18.04 + configure: ["", "cppflags=-DRUBY_DEBUG"] + include: + - test_task: "check" + os: ubuntu-20.04 + configure: "--host=i686-$OSTYPE" + - test_task: "test-all TESTS=--repeat-count=2" + os: ubuntu-20.04 + configure: "" + fail-fast: false + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUBY_DEBUG: ci + runs-on: ${{ matrix.os }} + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: Set ENV + env: + configure: ${{matrix.configure}} + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + arch=`echo " $configure" | sed '/.* --host=/!d;s///;s/[- ].*//'` + echo "SETARCH=${arch:+setarch $arch}" >> $GITHUB_ENV + - name: Install libraries + run: | + set -x + arch="${SETARCH##* }" + arch=${arch:+:${arch/i[3-6]86/i386}} + ${arch:+sudo dpkg --add-architecture ${arch#:}} + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y \ + ${arch:+cross}build-essential${arch/:/-} \ + libssl-dev${arch} libyaml-dev${arch} libreadline6-dev${arch} \ + zlib1g-dev${arch} libncurses5-dev${arch} libffi-dev${arch} \ + bison autoconf ruby + sudo apt-get install -q -y pkg-config${arch} || : + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - run: ./autogen.sh + working-directory: src + - name: Run configure + env: + arch: ${{matrix.arch}} + run: >- + $SETARCH ../src/configure -C --disable-install-doc ${{ matrix.configure }} + ${arch:+--target=$arch-$OSTYPE} + - run: $SETARCH make incs + - run: $SETARCH make + - run: $SETARCH make leaked-globals + if: ${{ matrix.test_task == 'check' }} + - run: $SETARCH make prepare-gems + if: ${{ matrix.test_task == 'check' }} + - name: Create dummy files in build dir + 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' }} + - name: make ${{ matrix.test_task }} + run: | + $SETARCH make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + timeout-minutes: 40 + env: + RUBY_TESTOPTS: "-q --tty=no" + TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + - name: make skipped tests + run: | + $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$/ -n/|g;s|^|-n/|;s|$|$$/|'` + env: + GNUMAKEFLAGS: "" + RUBY_TESTOPTS: "-v --tty=no" + TESTS: ${{ matrix.skipped_tests }} + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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/ruby/.github/workflows/windows.yml b/ruby/.github/workflows/windows.yml new file mode 100644 index 000000000..574bfbf47 --- /dev/null +++ b/ruby/.github/workflows/windows.yml @@ -0,0 +1,135 @@ +name: Windows +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + make: + strategy: + matrix: + include: + - vs: 2019 + os: windows-2019 + vcvars: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"' + # - vs: 2022 + # os: windows-2022 + # vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"' + fail-fast: false + runs-on: ${{ matrix.os }} + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + name: VisualStudio ${{ matrix.vs }} + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + VCVARS: ${{ matrix.vcvars }} + PATCH: C:\msys64\usr\bin\patch.exe + steps: + - run: md build + working-directory: + - uses: msys2/setup-msys2@v2 + id: setup-msys2 + with: + update: true + install: >- + patch + if: ${{ matrix.os != 'windows-2019' }} + - name: patch path + shell: msys2 {0} + run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV + if: ${{ steps.setup-msys2.outcome == 'success' }} + - uses: actions/cache@v2 + with: + path: C:\vcpkg\downloads + key: ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-vcpkg-download-${{ matrix.os }}- + ${{ runner.os }}-vcpkg-download- + - name: Install libraries with vcpkg + run: | + vcpkg --triplet x64-windows install readline zlib + - uses: actions/cache@v2 + with: + path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey + key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-chocolatey-${{ matrix.os }}- + ${{ runner.os }}-chocolatey- + - name: Install libraries with chocolatey + run: | + # Using Choco-Install for retries, but it doesn't detect failures properly + # if you pass multiple package names in a single command. + Choco-Install -PackageName openssl + Choco-Install -PackageName winflexbison3 + shell: pwsh + - name: git config + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: setup env + # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent. + # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302 + run: | + set | C:\msys64\usr\bin\sort > old.env + call %VCVARS% + set TMP=%USERPROFILE%\AppData\Local\Temp + set TEMP=%USERPROFILE%\AppData\Local\Temp + 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% + del *.env + - name: Configure + run: | + ../src/win32/configure.bat --disable-install-doc --enable-bundled-libffi --with-opt-dir=C:/vcpkg/installed/x64-windows --with-openssl-dir="C:/Program Files/OpenSSL-Win64" + - run: nmake incs + - run: nmake extract-extlibs + - run: nmake + env: + YACC: win_bison + - run: nmake test + timeout-minutes: 5 + - run: nmake test-all + env: + RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --job-status=normal + timeout-minutes: 60 + continue-on-error: ${{ matrix.continue-on-error || false }} + - run: nmake test-spec + timeout-minutes: 10 + continue-on-error: ${{ matrix.continue-on-error || false }} + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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 + shell: cmd diff --git a/ruby/.github/workflows/yjit-ubuntu.yml b/ruby/.github/workflows/yjit-ubuntu.yml new file mode 100644 index 000000000..c479b8a62 --- /dev/null +++ b/ruby/.github/workflows/yjit-ubuntu.yml @@ -0,0 +1,112 @@ +name: YJIT Ubuntu +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + make: + strategy: + matrix: + test_task: ["check"] # "test-bundler-parallel", + os: + - ubuntu-20.04 +# - ubuntu-18.04 + yjit_opts: [ + "--yjit", + "--yjit --yjit-call-threshold=1", + ] + configure: ["", "cppflags=-DRUBY_DEBUG"] + include: + - test_task: "test-all TESTS=--repeat-count=2" + os: ubuntu-20.04 + configure: "" + yjit_enable_env: RUBY_YJIT_ENABLE + - test_task: "test-bundled-gems" + os: ubuntu-20.04 + configure: "cppflags=-DRUBY_DEBUG" + yjit_enable_env: RUBY_YJIT_ENABLE + fail-fast: false + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + RUN_OPTS: ${{ matrix.yjit_opts }} + RUBY_DEBUG: ci + runs-on: ${{ matrix.os }} + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - run: mkdir build + working-directory: + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - uses: actions/cache@v2 + with: + path: src/.downloaded-cache + key: downloaded-cache + - name: Fixed world writable dirs + run: | + chmod -v go-w $HOME $HOME/.config + sudo chmod -R go-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + - name: Set ENV + run: | + echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - run: ./autogen.sh + working-directory: src + - name: Run configure + run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + - run: make incs + - run: make + - run: make leaked-globals + if: ${{ matrix.test_task == 'check' }} + - run: make prepare-gems + if: ${{ matrix.test_task == 'check' }} + - name: Create dummy files in build dir + 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' }} + - name: Enable YJIT through ENV + run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + if: ${{ matrix.yjit_enable_env }} + - run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: "-q --tty=no" + TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" + - uses: k0kubun/action-slack@v2.0.0 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref }}".split('/').reverse()[0] + } + env: + 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/ruby/.github/workflows/yjit_asm_tests.yml b/ruby/.github/workflows/yjit_asm_tests.yml new file mode 100644 index 000000000..8a9052dd4 --- /dev/null +++ b/ruby/.github/workflows/yjit_asm_tests.yml @@ -0,0 +1,38 @@ +name: YJIT x86 assembler tests + +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +jobs: + test: + runs-on: ubuntu-latest + if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }} + steps: + - name: Install dependencies + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential + - name: git config + run: | + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + - uses: actions/checkout@v2 + with: + path: src + - name: Run ASM tests + run: ./misc/test_yjit_asm.sh + working-directory: src diff --git a/ruby/.gitignore b/ruby/.gitignore new file mode 100644 index 000000000..31bfd787a --- /dev/null +++ b/ruby/.gitignore @@ -0,0 +1,234 @@ +*-*-*.def +*-*-*.exp +*-*-*.lib +*.a +*.bak +*.bc +*.bundle +*.dSYM +*.dmyh +*.dylib +*.elc +*.i +*.ii +*.inc +*.log +*.o +*.obj +*.old +*.orig +*.pch +*.pdb +*.rbinc +*.rej +*.s +*.sav +*.sl +*.so +*.swp +*.yarb +*~ +.*.list +.*.time +.DS_Store +.bundle +.ccmalloc +.ext +.pc +.ppack +.svn +.time +.ruby-version +Makefile +cygruby*.def +extconf.h +y.output +y.tab.c +*.gcda +*.gcno +*.gcov +*.vscode +lcov*.info + +# / +/*-fake.rb +/*.dll +/*.exe +/*.res +/*.pc +/*.rc +/*_prelude.c +/.downloaded-cache +/.top-enc.mk +/build*/ +/COPYING.LIB +/ChangeLog +/Doxyfile +/GNUmakefile +/README.atheos +/README.fat-patch +/README.v6 +/TAGS +/archive +/autom4te*.cache +/automake +/benchmark/benchmark-driver +/beos +/bmlog-* +/breakpoints.gdb +/config.cache +/config.h +/config.h.in +/config.status +/config.status.lineno +/configure +/coverage/simplecov +/coverage/simplecov-html +/coverage/doclie +/coverage/.last_run.json +/coverage/.resultset.json* +/coverage/assets +/coverage/index.html +/doc/capi +/enc.mk +/encdb.h +/exts.mk +/goruby +/id.[ch] +/largefile.h +/lcov-c-out +/lcov-rb-out +/lcov-out +/lex.c +/libruby*.* +/miniprelude.c +/miniruby +/newdate.rb +/newline.c +/newver.rb +/parse.c +/parse.h +/patches +/patches-master +/pitest.rb +/ppack +/prelude.c +/preview +/probes.dmyh +/probes.h +/rbconfig.rb +/rename2.h +/repack +/revision.h +/revision.tmp +/riscos +/rubicon +/ruby +/ruby-runner +/ruby-runner.h +/ruby-man.rd.gz +/run.gdb +/sizes.c +/static-ruby +/test.rb +/test-coverage.dat +/tmp +/transdb.h +/uncommon.mk +/verconf.h +/verconf.mk +/web +/yasmdata.rb + +# /bin/ + +/bin/*.exe +/bin/*.dll + +# /benchmark/ +/benchmark/bm_require.data +/benchmark/bmx_*.rb +/benchmark/fasta.output.* +/benchmark/wc.input + +/enc/*.def +/enc/*.exp +/enc/*.lib +/enc/jis/props.h +/enc/unicode/data + +# /coroutine/ +!/coroutine/**/*.s + +# /enc/trans/ +/enc/trans/*.c +/enc/trans/*.def +/enc/trans/*.exp +/enc/trans/*.lib + +# /exe/ +/exe/goruby +/exe/ruby + +# /ext/ +/ext/extinit.c +/ext/configure-ext.mk +/ext/*/exts.mk + +# /ext/-test-/cxxanyargs +/ext/-test-/cxxanyargs/failure*.failed + +# /ext/-test-/win32/dln/ +/ext/-test-/win32/dln/dlntest.dll +/ext/-test-/win32/dln/dlntest.exp +/ext/-test-/win32/dln/dlntest.lib + +# /ext/-test-/gems +/ext/-test-/gems + +# /ext/etc/ +/ext/etc/constdefs.h + +# /ext/fiddle/ +/ext/fiddle/libffi-* + +# /ext/rbconfig/ +/ext/rbconfig/sizeof/sizes.c +/ext/rbconfig/sizeof/limits.c + +# /ext/ripper/ +/ext/ripper/eventids1.c +/ext/ripper/.eventids2-check +/ext/ripper/eventids2table.c +/ext/ripper/ripper.* +/ext/ripper/ids1 +/ext/ripper/ids2 + +# /ext/socket/ +/ext/socket/constants.h +/ext/socket/constdefs.h +/ext/socket/constdefs.c + +# /gems +/gems/*.gem +/gems/src +/gems/*-* + +# /lib/ +/lib/ruby/[1-9]*.* +/lib/ruby/vendor_ruby + +# /spec/bundler +/.rspec_status + +# /tool/ +/tool/config.guess +/tool/config.sub + +# /win32/ +/win32/*.ico + +# MJIT +/rb_mjit_header.h +/mjit_config.h +/include/ruby-*/*/rb_mjit_min_header-*.h diff --git a/ruby/.travis.yml b/ruby/.travis.yml index 71945e349..f8c66f715 100644 --- a/ruby/.travis.yml +++ b/ruby/.travis.yml @@ -6,22 +6,16 @@ # conditions mentioned in the file COPYING are met. Consult the file for # details. -# This is a Travis-CI build configuration file. The list of configurations -# available is located in -# -# http://about.travis-ci.org/docs/user/build-configuration/ -# -# and as Ruby itself is a project written in C language, -# -# http://about.travis-ci.org/docs/user/languages/c/ -# -# is also a good place to look at. +# We only manage non-amd64 free pipelines. +# https://docs.travis-ci.com/user/billing-overview/ language: c os: linux -dist: xenial +if: commit_message !~ /^\[DOC\]/ + +dist: focal git: quiet: true @@ -34,6 +28,10 @@ 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 @@ -46,415 +44,118 @@ env: - SETARCH= - RUBY_PREFIX=/tmp/ruby-prefix - GEMS_FOR_TEST='timezone tzinfo' - - UPDATE_UNICODE="UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=." # 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. + - debugflags=-ggdb3 .org.ruby-lang.ci.matrix-definitions: - - &cron-only - if: (type = cron) AND (branch = master) AND (fork = false) - - - &make-test-only - script: - - $SETARCH make -s test TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}" - - - &gcc-8 - compiler: gcc-8 - # # Not using addon to control retries - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - before_install: - - tool/travis_retry.sh sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq" - - |- - ${BEFORE_INSTALL} - tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install \ - ccache \ - gcc-8 \ - g++-8 \ - libffi-dev \ - libgdbm-dev \ - libgmp-dev \ - libjemalloc-dev \ - libncurses5-dev \ - libncursesw5-dev \ - libreadline6-dev \ - libssl-dev \ - libyaml-dev \ - openssl \ - valgrind \ - zlib1g-dev - - - &clang-8 - compiler: clang-8 - addons: - apt: - # Not doing this manually unlike other sources, because it has been stable. - sources: - - llvm-toolchain-xenial-8 - config: - retries: true + - &gcc-10 + compiler: gcc-10 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 \ - clang-8 \ - llvm-8-tools \ - libffi-dev \ - libgdbm-dev \ - libgmp-dev \ - libjemalloc-dev \ - libncurses5-dev \ - libncursesw5-dev \ - libreadline6-dev \ - libssl-dev \ - libyaml-dev \ - openssl \ - valgrind \ - zlib1g-dev + - >- + tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install + ccache + gcc-10 + g++-10 + libffi-dev + libgdbm-dev + libncurses-dev + libncursesw5-dev + libreadline-dev + libssl-dev + libyaml-dev + openssl + zlib1g-dev # -------- - - &x86_64-linux - name: x86_64-linux - <<: *gcc-8 - - &arm64-linux name: arm64-linux arch: arm64 - <<: *gcc-8 + <<: *gcc-10 + + - &ppc64le-linux + name: ppc64le-linux + arch: ppc64le + <<: *gcc-10 - &s390x-linux name: s390x-linux arch: s390x - <<: *gcc-8 - - - &jemalloc - name: --with-jemalloc - <<: *gcc-8 - <<: *cron-only - env: - - CONFIG_FLAG='--with-gmp --with-jemalloc --with-valgrind' - - - &assertions - name: RUBY_DEBUG=1 - <<: *gcc-8 - #<<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cppflags='-DRUBY_DEBUG -DVM_CHECK_MODE=1 -DTRANSIENT_HEAP_CHECK_MODE -DRGENGC_CHECK_MODE -DENC_DEBUG' - - - &VM_CHECK_MODE - name: VM_CHECK_MODE=3 - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cppflags=-DVM_CHECK_MODE=0x0003 - - - &SUPPORT_JOKE - name: SUPPORT_JOKE - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - BEFORE_INSTALL="sed vm_opts.h -e 's/OPT_SUPPORT_JOKE *0/OPT_SUPPORT_JOKE 1/' -i" - - - &CPDEBUG - name: CPDEBUG - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - cppflags=-DCPDEBUG - - - &WITH_COROUTINE_UCONTEXT - name: COROUTINE=ucontext - <<: *gcc-8 - <<: *cron-only - env: - - CONFIG_FLAG='--with-coroutine=ucontext' - - - &WITH_COROUTINE_COPY - name: COROUTINE=copy - <<: *gcc-8 - <<: *cron-only - env: - - CONFIG_FLAG='--with-coroutine=copy' - - - &TOKEN_THREADED_CODE - name: TOKEN_THREADED_CODE - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cppflags=-DOPT_THREADED_CODE=1 - - - &CALL_THREADED_CODE - name: CALL_THREADED_CODE - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cppflags=-DOPT_THREADED_CODE=2 - - - &NO_THREADED_CODE - name: NO_THREADED_CODE - <<: *gcc-8 - <<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cppflags=-DOPT_THREADED_CODE=3 - - - &ASAN - name: -fsanitize=address - <<: *clang-8 - #<<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - ASAN_OPTIONS=detect_leaks=0 - - cflags='-U_FORTIFY_SOURCE -march=native -fsanitize=address -fno-omit-frame-pointer -fPIC' - - debugflags=-ggdb3 - - optflags=-O1 - - LD=clang-8 - - LDFLAGS='-fsanitize=address -fPIC' - - CONFIG_FLAG='--with-out-ext=openssl --without-gmp --without-jemalloc --without-valgrind' - - - &MSAN - name: -fsanitize=memory - <<: *clang-8 - #<<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cflags='-U_FORTIFY_SOURCE -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fPIC' - - optflags=-O1 - - LD=clang-8 - - LDFLAGS='-fsanitize=memory -fPIC' - - CONFIG_FLAG='--with-out-ext=openssl --without-gmp --without-jemalloc --without-valgrind' - - - &UBSAN - name: -fsanitize=undefined - <<: *clang-8 - #<<: *cron-only - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - cflags='-U_FORTIFY_SOURCE -fsanitize=undefined,integer,nullability -fno-sanitize=implicit-integer-sign-change,unsigned-integer-overflow' - - cppflags=-DUNALIGNED_WORD_ACCESS=0 - - debugflags=-ggdb3 - - optflags='-O1 -march=native' - - LD=clang-8 - - LDFLAGS='-fsanitize=undefined,integer,nullability -fno-sanitize=implicit-integer-sign-change,unsigned-integer-overflow' - - - &i686-linux - name: i686-linux - compiler: gcc-8 - env: - - GCC_FLAGS=-m32 - - CXX='g++-8 -m32' - - debugflags=-g0 - - SETARCH='setarch i686 --verbose --3gb' - # # Not using addon to control retries - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - before_install: - - tool/travis_retry.sh sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - - 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 \ - gcc-8-multilib \ - g++-8 \ - g++-8-multilib \ - libstdc++-8-dev:i386 \ - libffi-dev:i386 \ - libffi6:i386 \ - libgdbm-dev:i386 \ - libgdbm3:i386 \ - libncurses5-dev:i386 \ - libncurses5:i386 \ - libncursesw5-dev:i386 \ - libreadline6-dev:i386 \ - libreadline6:i386 \ - libssl-dev:i386 \ - libssl1.0.0:i386 \ - linux-libc-dev:i386 \ - zlib1g-dev:i386 \ - zlib1g:i386 + <<: *gcc-10 - &arm32-linux name: arm32-linux arch: arm64 - # https://packages.ubuntu.com/xenial/crossbuild-essential-armhf + # https://packages.ubuntu.com/focal/crossbuild-essential-armhf compiler: arm-linux-gnueabihf-gcc env: - - debugflags=-g0 - 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++-5-dev:armhf \ - libffi-dev:armhf \ - libffi6:armhf \ - libgdbm-dev:armhf \ - libgdbm3:armhf \ - libncurses5-dev:armhf \ - libncurses5:armhf \ - libncursesw5-dev:armhf \ - libreadline6-dev:armhf \ - libreadline6:armhf \ - libssl-dev:armhf \ - libssl1.0.0:armhf \ - linux-libc-dev:armhf \ - zlib1g-dev:armhf \ - zlib1g:armhf - - - &pedanticism - name: -std=c99 -pedantic - compiler: clang - <<: *make-test-only - env: - - GEMS_FOR_TEST= - - GCC_FLAGS='-std=c99 -Werror=pedantic -pedantic-errors' - - CONFIG_FLAG= - - JOBS= - >- - warnflags=' - -Wall - -Wextra - -Werror=deprecated-declarations - -Werror=division-by-zero - -Werror=extra-tokens - -Werror=implicit-function-declaration - -Werror=implicit-int - -Werror=pointer-arith - -Werror=shorten-64-to-32 - -Werror=write-strings - -Wmissing-noreturn - -Wno-constant-logical-operand - -Wno-missing-field-initializers - -Wno-overlength-strings - -Wno-parentheses-equality - -Wno-self-assign - -Wno-tautological-compare - -Wno-unused-local-typedef - -Wno-unused-parameter - -Wunused-variable' - - LDFLAGS=-Wno-unused-command-line-argument - - - &rubyspec - name: Check ruby/spec version guards on Ruby 2.4 - language: ruby - rvm: 2.4.6 - before_install: - install: - before_script: chmod -R u+w spec/ruby - # -j randomly hangs. - script: ruby -C spec/ruby ../mspec/bin/mspec . - after_failure: - - echo "ruby/spec failed on Ruby 2.4. This is likely because of a missing ruby_version_is guard, please add it. See spec/README.md." - - - &baseruby - name: "BASERUBY: Ruby 2.2" - <<: *gcc-8 - <<: *make-test-only - language: ruby - rvm: 2.2 - - - &dependency - name: Check dependencies in makefiles - language: ruby - before_install: - install: - before_script: - - |- - ruby -e 'new = [] - Dir.glob("ext/**/extconf.rb") {|ex| - unless File.exist?(dep = File.dirname(ex)+"/depend") - puts "Adding "+dep - File.copy_stream("template/depend.tmpl", dep) - new << dep - end - } - exec("git", "add", *new) unless new.empty?' - - git diff --cached - - "> config.status" - - "> .rbconfig.time" - - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile - - make touch-unicode-files - - make -s $JOBS $UPDATE_UNICODE up - - make -s $JOBS srcs - - rm -f config.status Makefile rbconfig.rb .rbconfig.time - - $SETARCH ./configure -C --disable-install-doc --prefix=$RUBY_PREFIX --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g' - - ruby tool/update-deps --fix - script: - - git diff --no-ext-diff --ignore-submodules --exit-code - after_failure: - - echo "Dependencies need to update" - env: - - CONFIG_FLAG= + 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 + libgdbm-dev:armhf + libncurses-dev:armhf + libncursesw5-dev:armhf + libreadline-dev:armhf + libssl-dev:armhf + linux-libc-dev:armhf + zlib1g-dev:armhf matrix: include: - # Build every commit: - - <<: *x86_64-linux - - <<: *arm64-linux - - <<: *i686-linux + # Build every commit (Allowed Failures): - <<: *arm32-linux + # Comment out as the 2nd arm64 pipeline is unstable. + # - <<: *arm64-linux + - <<: *ppc64le-linux - <<: *s390x-linux - - <<: *pedanticism - - <<: *assertions - - <<: *baseruby - - <<: *rubyspec - - <<: *dependency - # Build every commit (Allowed Failures): - - <<: *ASAN - - <<: *MSAN - - <<: *UBSAN - # Cron only: - - <<: *jemalloc - - <<: *VM_CHECK_MODE - - <<: *SUPPORT_JOKE - - <<: *CPDEBUG - - <<: *WITH_COROUTINE_UCONTEXT - - <<: *WITH_COROUTINE_COPY - - <<: *TOKEN_THREADED_CODE - - <<: *CALL_THREADED_CODE - - <<: *NO_THREADED_CODE 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 - - name: -fsanitize=address - - name: -fsanitize=memory - - name: -fsanitize=undefined fast_finish: true before_script: - - date # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759 - - dpkg --print-architecture - - dpkg --print-foreign-architectures - - setarch --list - - echo JOBS=${JOBS} SETARCH=${SETARCH} - - $SETARCH uname -a - - $SETARCH uname -r + - . 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 - - echo $TERM - |- [ -d ~/.downloaded-cache ] || mkdir ~/.downloaded-cache @@ -462,9 +163,8 @@ before_script: - "> config.status" - "> .rbconfig.time" - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile - - date; make touch-unicode-files - - date; make -s $JOBS $UPDATE_UNICODE up - - date; make -s $JOBS srcs + - make -s $JOBS up + - make -s $JOBS srcs - rm -f config.status Makefile rbconfig.rb .rbconfig.time - |- if [ -d ~/config_2nd ]; then @@ -476,7 +176,6 @@ before_script: - chmod -R a-w . - chmod -R u+w build config_1st config_2nd - cd build - - ccache --show-stats - |- case "$CC" in gcc*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-diagnostics-color";; @@ -496,20 +195,7 @@ before_script: - mv ../config_2nd ~ - chmod u-w .. - $SETARCH make -s $JOBS - - |- - date; : # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759 - if ! make install; then - if [ "$(uname)" = Darwin ]; then - # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759 - set -x - date - ./miniruby -e 'ARGV.map{|path|[path,File.stat(path)]}.sort_by{|path,st|st.mtime}.each{|path,st|p mtime:st.mtime.to_f, ctime:st.ctime.to_f, path:path}' .ext/.timestamp/.RUBYCOMMONDIR*time .ext/common/bigdecimal/*.rb ../ext/bigdecimal/lib/bigdecimal/*.rb . .. .ext .ext/common .ext/common/bigdecimal ext/bigdecimal ../ext ../ext/bigdecimal ../ext/bigdecimal/lib ../ext/bigdecimal/lib/bigdecimal - make COPY='cp -f' install - else - exit 1 - fi - fi - - ccache --show-stats + - make -s install - |- [ -z "${GEMS_FOR_TEST}" ] || $RUBY_PREFIX/bin/gem install --no-document $GEMS_FOR_TEST @@ -517,17 +203,18 @@ before_script: script: - $SETARCH make -s test -o showflags TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}" - - travis_wait 50 $SETARCH make -s test-all -o exts TESTOPTS="${TESTOPTS} ${TEST_ALL_OPTS}" RUBYOPT="-w" + - ../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 MSPECOPT=-ff # not using `-j` because sometimes `mspec -j` silently dies - $SETARCH make -s -o showflags leaked-globals -# Branch matrix. Not all branches are Travis-ready so we limit branches here. -branches: - only: - - master - - ruby_2_4 - - ruby_2_5 - - ruby_2_6 +# 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 # We want to be notified when something happens. notifications: @@ -539,12 +226,11 @@ notifications: template: - "%{message} by @%{author}: See %{build_url}" - slack: - rooms: - - secure: ah7UEHBvncXT7bM5mvYIQAO+tIyV/wl7nXLb7wQD16dO2v8Gragy0mWjB79Q09hrrMGmp6H9bCDpdGS80boIA5EHaHoG4QaP0i9bsSt8U2AMWgZtfyIgQKJ4H2kXkGlrjO+AXTgnIkP7LNjdgAVUUTGQPb26T3QmoN2Splt+fIQ= # ruby:#alerts - on_pull_requests: false - on_success: change + webhooks: + urls: + - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= # ruby-lang slack: ruby/simpler-alerts-bot (travis) + on_success: never on_failure: always email: - - ko1c-failure@atdot.net + - jaruga@ruby-lang.org diff --git a/ruby/BSDL b/ruby/BSDL index a009caefe..66d93598a 100644 --- a/ruby/BSDL +++ b/ruby/BSDL @@ -4,10 +4,10 @@ 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. + 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. + 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 diff --git a/ruby/CONTRIBUTING.md b/ruby/CONTRIBUTING.md index ffdf2dd4b..7363c106a 100644 --- a/ruby/CONTRIBUTING.md +++ b/ruby/CONTRIBUTING.md @@ -1,4 +1,5 @@ -Please see the [official issue tracker] and wiki [HowToContribute]. +Please see the [official issue tracker], [doc/contributing.rdoc] and wiki [HowToContribute]. [official issue tracker]: https://bugs.ruby-lang.org +[doc/contributing.rdoc]: contributing.rdoc [HowToContribute]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToContribute diff --git a/ruby/ChangeLog b/ruby/ChangeLog deleted file mode 100644 index ba9e2921a..000000000 --- a/ruby/ChangeLog +++ /dev/null @@ -1,55893 +0,0 @@ --*- coding: utf-8 -*- - -commit a0c7c23c9cec0d0ffcba012279cd652d28ad5bf3 - Author: NARUSE, Yui - Date: 2020-03-31 19:27:41 +0900 - - v2.7.1p83 - -commit f832d957b837d5167058a3f8579d66e5b5d3472e - Author: NARUSE, Yui - Date: 2020-03-31 19:26:10 +0900 - - ext/socket/init.c: do not return uninitialized buffer - - BasicSocket#read_nonblock and some methods changes the size of a buffer - string, but when no data is available, the buffer is returned as - uninitialized. - - Co-Authored-By: Samuel Williams - -commit 5caee29164de6477b5cad1328b56e696a41d5025 - Author: git - Date: 2020-03-31 16:31:53 +0900 - - * 2020-03-31 [ci skip] - -commit bb93659fefd7f4557129043742771a33bd30c255 - Author: Jeremy Evans - Date: 2020-03-31 16:10:57 +0900 - - Fix pp when passed a empty ruby2_keywords-flagged hash as array element (#2966) - - This causes problems because the hash is passed to a block not - accepting keywords. Because the hash is empty and keyword flagged, - it is removed before calling the block. This doesn't cause an - ArgumentError because it is a block and not a lambda. Just like - any other block not passed required arguments, arguments not - passed are set to nil. - - Issues like this are a strong reason not to have ruby2_keywords - by default. - - Fixes [Bug #16519] - - This backports 28d31ead34baff1c4abc0d7d902ef4bc1d576fb2 and - 0ea759eac9234afc47e8fb1bcacfe9ee12c8ffb6, but needed to be modified - for 2.7 as 2.7 will perform empty keyword to positional hash - conversion for required arguments, which will happen if "v" in the - seplist method is empty when yielded. - - Co-authored-by: NARUSE, Yui - -commit d04856bdc502eec4055da1e5cf717639c314e189 - Author: git - Date: 2020-03-30 19:15:42 +0900 - - * 2020-03-30 [ci skip] - -commit b5fa156b7907b8ea1baf8b9f0cb6a66b0fecb3d4 - Author: Alan Wu - Date: 2020-03-11 23:37:14 +0900 - - Clear all trace events during teardown - - Since 0c2d81dada, not all trace events are cleared during VM teardown. - This causes a crash when there is a tracepoint for - `RUBY_INTERNAL_EVENT_GC_EXIT` active during teardown. - - The commit looks like a refactoring commit so I think this change was - unintentional. - - [Bug #16682] - - (cherry picked from commit b385f7670ffa420790bc548747fa4b58c4c5d8f6) - -commit 0057fe4063b57b445d6ffc893e442f362e3a19e0 - Author: aycabta - Date: 2020-03-30 19:09:50 +0900 - - Ruby 2.7 backport about IRB (#2990) - - * [ruby/reline] Sort completion list - - #### Legacy mode: - - ```console - $ irb --legacy - irb(main):001:0> l[TAB][TAB] - lambda load local_variables loop - ``` - - #### Before this patch: - - ```console - $ irb - irb(main):001:0> l[TAB][TAB] - local_variables - loop - lambda - load - ``` - - #### After this patch: - - ```console - $ irb - irb(main):001:0> l[TAB][TAB] - lambda - load - local_variables - loop - ``` - - https://github.com/ruby/reline/commit/6074069c7d - - * Drop an invalid char as UTF-8 - - * Add test_completion_with_indent_and_completer_quote_characters - - This is for 8a705245e55575d4d310a2e956b89a36a5931971. - - * [ruby/irb] Add tests for RubyLex - - The set_auto_indent method calculates the correct number of spaces for - indenting a line. We think there might be a few bugs in this method so - we are testing the current functionality to make sure nothing breaks - when we address those bugs. - - Example test failure: - - ``` - 1) Failure: - TestIRB::TestRubyLex#test_auto_indent [/Users/Ben/Projects/irb/test/irb/test_ruby_lex.rb:75]: - Calculated the wrong number of spaces for: - def each_top_level_statement - initialize_input - catch(:TERM_INPUT) do - loop do - begin - prompt - unless l = lex - throw :TERM_INPUT if @line == '' - else - . - <10> expected but was - <12>. - ``` - - https://github.com/ruby/irb/commit/752d5597ab - - * [ruby/reline] Degenerate the terminal size to [$LINES, $COLUMNS] if it is unknown - - This is a workaround for https://github.com/ruby/irb/issues/50 - - https://github.com/ruby/reline/commit/5725677d1a - - * [ruby/irb] Fix newline depth with multiple braces - - This commit fixes the check_newline_depth_difference method to multiple - open braces on one line into account. Before this change we were - subtracting from the depth in check_newline_depth_difference on - every open brace. This is the right thing to do if the opening and - closing brace are on the same line. For example in a method definition we - have an opening and closing parentheses we want to add 1 to our depth, - and then remove it. - - ``` - def foo() - end - ``` - - However this isn't the correct behavior when the brace spans multiple - lines. If a brace spans multiple lines we don't want to subtract from - check_newline_depth_difference and we want to treat the braces the same - way as we do `end` and allow check_corresponding_token_depth to pop the - correct depth. - - Example of bad behavior: - - ``` - def foo() - [ - ] - puts 'bar' - end - ``` - - Example of desired behavior: - - ``` - def foo() - [ - ] - puts 'bar' - end - ``` - - https://github.com/ruby/irb/commit/7dc8af01e0 - - * text/readline/test_readline.rb - fix skip on Reline (#2743) - - TestRelineAsReadline#test_input_metachar passes on MinGW - - * Add "require 'openstruct'" what is forgotten - - * [ruby/irb] Fix lib name of OpenStruct - - https://github.com/ruby/irb/commit/1f3a84ab6b - - * Add load path and require for ruby/ruby - - * Rescue EOFError - - If C-d is pressed before IRB is ready, IRB crashes because EOFError occurs. - - * Complete indented and quoted string correctly - - def foo - ''.upca[TAB] - - This will be completed to be: - - def foo - ''.upcase - - The indent was gone. This commit fixes the bug. - - * [ruby/irb] Fix crashing when multiple open braces per line - - https://github.com/ruby/irb/issues/55 - - If we had put multiple open braces on a line the with no closing brace - spaces_of_nest array keeps getting '0' added to it. This means that when - we pop off of this array we are saying that we should be in position zero - for the next line. This is an issue because we don't always want to be - in position 0 after a closing brace. - - Example: - ``` - [[[ - ] - ] - ] - ``` - In the above example the 'spaces_of_nest' array looks like this after - the first line is entered: [0,0,0]. We really want to be indented 4 - spaces for the 1st closing brace 2 for the 2nd and 0 for the 3rd. i.e. - we want it to be: [0,2,4]. - - We also saw this issue with a heredoc inside of an array. - - ``` - [<") - it fails with: - irb/completion.rb:206:in `<<': wrong number of arguments (given 3, expected 1) (ArgumentError) - - Using Array#push instead of Array#append fixes compatibility. - - https://github.com/ruby/irb/commit/5b7bbf9c34 - - * Reline: Use a more robust detection of MinTTY - - The previous detection per get_screen_size fails when stdout is passed - to a pipe. That is the case when running ruby tests in parallel ("-j" switch). - In this case Reline believes that it's running on MinTTY and the tests - are running with ANSI IOGate instead of the Windows adapter on MINGW. - So parallel test results were different to that of a single process. - This commit fixes these differencies. - - The code is taken from git sources and translated to ruby. - NtQueryObject() is replaced by GetFileInformationByHandleEx(), because - NtQueryObject() is undocumented and is more difficult to use: - https://github.com/git-for-windows/git/blob/c5a03b1e29c69f3f06c8fabd92493edb73469176/compat/winansi.c#L558 - - * Reline: Fix changed test results due to change to UTF-8 on Windows - - In commit f8ea2860b0cac1aec79978e6c44168802958e8af the Reline encoding - for native windows console was changed to hardcoded UTF-8. - This caused failures in reline and readline tests, but they were hidden, - because parallel ruby tests incorrectly used Reline::ANSI as IOGate. - Tests failures were raised in single process mode, but not with -j switch. - - This patch corrects encodings on native Windows console. - - * [ruby/irb] [ruby/irb] Rewrite an expression to detect multiline - - https://github.com/ruby/irb/commit/ed5cf375a6 - - https://github.com/ruby/irb/commit/5b7bbf9c34 - - * [ruby/reline] Implement vi_change_meta - - https://github.com/ruby/reline/commit/8538e0e10f - - * Always refer to Reline::IOGate.encoding - - * Always use UTF-8 for Reline::GeneralIO on Windows - - * Use test_mode on Reline::History::Test for encoding - - * [ruby/reline] Support GNOME style Home/End key sequences [Bug #16510] - - https://github.com/ruby/reline/commit/788f0df845 - - * [ruby/irb] Add a new easter egg: dancing ruby - - https://github.com/ruby/irb/commit/e37dc7e58e - - * [ruby/irb] Exclude useless files from RDoc - - https://github.com/ruby/irb/commit/8f1ab2400c - - * [ruby/irb] Exclude useless files from RDoc - - * Fix inaccuracy in encoding tests - - These tests assume - Encoding.find('locale') == Encoding.find('external') - and fail if they are distinct. - - * [ruby/reline] Fix Reline::Windows#scroll_down - - I mistook Right and Bottom. - - https://github.com/ruby/reline/commit/8be401c5f5 - - * [ruby/reline] Bypass cursor down when a char is rendered at eol on Windows - - A newline is automatically inserted if a character is rendered at eol on - Windows command prompt. - - https://github.com/ruby/reline/commit/4bfea07e4a - - * [ruby/reline] Organize special keys escape sequences - - https://github.com/ruby/reline/commit/41deb1a3d9 - - * [ruby/readline-ext] Remove unnecessary -I$(top_srcdir) when it's an individual gem - - https://github.com/ruby/readline-ext/commit/efaca4a5f4 - - * [ruby/readline-ext] Check TestRelineAsReadline existance - - https://github.com/ruby/readline-ext/commit/c0a6303168 - - * [ruby/readline-ext] The ruby/assert.h is adopted by Ruby 2.7 or later - - https://github.com/ruby/readline-ext/commit/106c31fc1b - - * Revert "[ruby/readline-ext] Include ruby/assert.h in ruby/ruby.h so that assertions can be there" - - This reverts commit 425b2064d394639101854c83a061a0918b33b857. - - This cherry-pick was a mistake. - - * [ruby/readline-ext] Use require check instead of DONT_RUN_RELINE_TEST env - - https://github.com/ruby/readline-ext/commit/1df99d1481 - - * [ruby/readline-ext] Add spec.extensions - - https://github.com/ruby/readline-ext/commit/8c33abb13c - - * [ruby/readline-ext] Use rake/extensiokntask to build - - https://github.com/ruby/readline-ext/commit/b0b5f709bd - - * Fix readline build dependency - - * [ruby/irb] Add test_complete_symbol - - https://github.com/ruby/irb/commit/dbbf086c1f - - * [ruby/irb] Check doc namespace correctly - - IRB::InputCompletor::PerfectMatchedProc crashes when doc not found because a - variable name was incorrect. - - https://github.com/ruby/irb/commit/889fd4928f - - * [ruby/irb] Fix auto indent with closed brace - - A closed brace in auto-indent shouldn't affect the next brace in the same line, - but it behaves like below: - - p() { - } - - It's a bug. - - https://github.com/ruby/irb/commit/fbe59e344f - - * [ruby/irb] Use 0.step instead of (..0).each for Ruby 2.5 - - https://github.com/ruby/irb/commit/5d628ca40e - - * Revert "[ruby/irb] Add test_complete_symbol" - - This reverts commit 3af3431c2c145134996e66f3d8d9ade8ad81bde0. - - * [ruby/irb] fix reserved words and completion for them - - https://github.com/ruby/irb/commit/6184b227ad - - * Add test_complete_symbol - - The previous version of the test method used a symbol, ":abcdefg" to complete - but longer symbols that can be completed are defined by other test methods of - other libs. - - * test/irb/test_completion.rb: suppress a warning: unused literal ignored - - * [ruby/reline] Use IO#write instead of IO#print - - IO#print always adds a string of $\ automatically. - - https://github.com/ruby/reline/commit/a93119c847 - - * [ruby/irb] Version 1.2.2 - - https://github.com/ruby/irb/commit/a71753f15a - - * [ruby/reline] Version 0.1.3 - - https://github.com/ruby/reline/commit/ea2b182466 - - * [ruby/irb] Include easter-egg.rb in gemspec - - `irb` doesn't run because this file isn't included in the gem. - https://github.com/ruby/irb/commit/73cda56d25 - - * [ruby/irb] Version 1.2.3 - - https://github.com/ruby/irb/commit/dd56e06df5 - - * support multi-run test for test_readline.rb - - * [ruby/irb] `yield` outside method definition is a syntax error - - https://github.com/ruby/irb/commit/dbc7b059c7 - - * test/readline - allow ENV control of test class creation - - In ruby/ruby, the tests run on both readline & reline by creating four test classes: - ``` - TestReadline - TestReadlineHistory - - TestRelineAsReadline - TestRelineAsReadlineHistory - ``` - - Reline inports the test files and uses them in its CI. Adding the ENV control allows it to only run the `TestRelineAsReadline` classes. - - * Omit test_using_quoting_detection_proc_with_multibyte_input temporarily for random order test - - * support random order test. - - test_readline: - HISTORY should be empty. - - test_using_quoting_detection_proc: - test_using_quoting_detection_proc_with_multibyte_input: - Readline.completer_quote_characters= and - Readline.completer_word_break_characters= doesn't accept nil, - so skip if previous values are nil. - - * Set Readline.completion_append_character = nil always - - GNU Readline add a white space when Readline.completion_append_character is - not initialized. - - * Fix a typo [ci skip] - - * skip test if Reline.completion_proc is nil. - - Some other tests can set Reline.completion_proc, so if it is nil, - simply skip this test. - - * Reset Reline.point - - TestRelineAsReadline#test_insert_text expects Readline.point == 0 - at the beginning of the test, but a test violate this assumption. - - * Convert incompatible encoding symbol names - - * Ignore incompatible convert of symbols - - * Add workaround for test-bundler failure - - https://github.com/ruby/actions/runs/500526558?check_suite_focus=true#step:16:127 - ``` - Failures: - - 1) Bundler.setup when Bundler is bundled doesn't blow up - Failure/Error: expect(err).to be_empty - - expected `"fatal: not a git repository (or any of the parent directories): .git\nfatal: not a git repository (o...the parent directories): .git\nfatal: not a git repository (or any of the parent directories): .git".empty?` to return true, got false - - Commands: - $ /home/runner/work/actions/actions/snapshot-master/ruby \ - -I/home/runner/work/actions/actions/snapshot-master/lib:/home/runner/work/actions/actions/snapshot-master/spec/bundler \ - -rsupport/hax -rsupport/artifice/fail \ - /home/runner/work/actions/actions/snapshot-master/libexec/bundle install --retry 0 - Resolving dependencies... - Using bundler 2.1.4 - Bundle complete! 1 Gemfile dependency, 1 gem now installed. - Use `bundle info [gemname]` to see where a bundled gem is installed. - fatal: not a git repository (or any of the parent directories): .git - fatal: not a git repository (or any of the parent directories): .git - fatal: not a git repository (or any of the parent directories): .git - # $? => 0 - - $ /home/runner/work/actions/actions/snapshot-master/ruby \ - -I/home/runner/work/actions/actions/snapshot-master/lib:/home/runner/work/actions/actions/snapshot-master/spec/bundler \ - -rsupport/hax -rsupport/artifice/fail \ - /home/runner/work/actions/actions/snapshot-master/libexec/bundle exec ruby -e \ - require\ \'bundler\'\;\ Bundler.setup - fatal: not a git repository (or any of the parent directories): .git - fatal: not a git repository (or any of the parent directories): .git - fatal: not a git repository (or any of the parent directories): .git - # $? => 0 - # ./spec/bundler/runtime/setup_spec.rb:1056:in `block (3 levels) in ' - # ./spec/bundler/spec_helper.rb:111:in `block (3 levels) in ' - # ./spec/bundler/spec_helper.rb:111:in `block (2 levels) in ' - # ./spec/bundler/spec_helper.rb:78:in `block (2 levels) in ' - make: *** [yes-test-bundler] Error 1 - ``` - - * [ruby/irb] Unnamed groups are not captured when named groups are used - - https://github.com/ruby/irb/commit/0a641a69b0 - - * [ruby/reline] Work with wrong $/ value correctly - - https://github.com/ruby/reline/commit/962ebf5a1b - - * [ruby/irb] Detect multiple lines output simplify - - The old implementation performance test code: - - require 'objspace' - puts "%.5g MB" % (ObjectSpace.memsize_of_all * 0.001 * 0.001) - /\A.*\Z/ !~ ('abc' * 20_000_000) - puts "%.5g MB" % (ObjectSpace.memsize_of_all * 0.001 * 0.001) - - and run `time test.rb`: - - 2.5868 MB - 62.226 MB - - real 0m1.307s - user 0m0.452s - sys 0m0.797s - - The new implementation performance test code: - - require 'objspace' - puts "%.5g MB" % (ObjectSpace.memsize_of_all * 0.001 * 0.001) - ('abc' * 20_000_000).include?("\n") - puts "%.5g MB" % (ObjectSpace.memsize_of_all * 0.001 * 0.001) - - and run `time test.rb`: - - 2.5861 MB - 62.226 MB - - real 0m0.132s - user 0m0.088s - sys 0m0.042s - - https://github.com/ruby/irb/commit/40d6610baf - - * [ruby/reline] Suppress error in case INPUTRC env is empty - - https://github.com/ruby/reline/commit/bce7e7562b - - * [ruby/reline] Add yamatanooroti rendering test - - https://github.com/ruby/reline/commit/f092519525 - - * [ruby/reline] Rename test suite name of yamatanooroti test - - https://github.com/ruby/reline/commit/b0f32f5de4 - - * [ruby/reline] Add a comment why rescue yamatanooroti loading error on the test - - https://github.com/ruby/reline/commit/2a8061daec - - * [ruby/irb] Suppress crashing when EncodingError has occurred without lineno - - https://github.com/ruby/irb/commit/13572d8cdc - - * [ruby/reline] Suppress error when check ambiguous char width in LANG=C - - https://github.com/ruby/reline/commit/623dffdd75 - - * [ruby/io-console] Enable only interrupt bits on `intr: true` - - https://github.com/ruby/io-console/commit/baaf929041 - - * [ruby/io-console] bump up to 0.5.4 - - * [ruby/io-console] Update the minimum requirement of Ruby version - - https://github.com/ruby/io-console/commit/73e7b6318a - - * [ruby/io-console] Filter Ruby engine name rather than just /ruby/ - - This breaks tests using this path on JRuby because the `jruby` - executable turns into `jjruby` after the sub. - - https://github.com/ruby/io-console/commit/e5951aa34c - - * [ruby/io-console] bump up to 0.5.5 - - * [ruby/io-console] Prefer keyword arguments - - https://github.com/ruby/io-console/commit/5facbfc4c8 - - * [ruby/io-console] [DOC] Improved about `intr:` - - https://github.com/ruby/io-console/commit/82b630cd79 - - * [ruby/io-console] Just ignore the extension on other than CRuby - - https://github.com/ruby/io-console/commit/41b6f09574 - - * [ruby/io-console] bump up to 0.5.6 - - Co-authored-by: KOBAYASHI Shuji - Co-authored-by: Ben - Co-authored-by: Yusuke Endoh - Co-authored-by: MSP-Greg - Co-authored-by: Nobuyoshi Nakada - Co-authored-by: Kenta Murata - Co-authored-by: Lars Kanis - Co-authored-by: Lars Kanis - Co-authored-by: Alan Wu - Co-authored-by: Hiroshi SHIBATA - Co-authored-by: Nobuhiro IMAI - Co-authored-by: Nick Lewis - Co-authored-by: S-H-GAMELINKS - Co-authored-by: Koichi Sasada - Co-authored-by: Kazuhiro NISHIYAMA - Co-authored-by: Charles Oliver Nutter - -commit ecf874edea92796c63cc2b50b36b1179de5114c6 - Author: git - Date: 2020-03-28 06:14:02 +0900 - - * 2020-03-28 [ci skip] - -commit 22c3014e36219b072fd6b1e963c4c64c7015a3cd - Author: Yusuke Endoh - Date: 2020-03-03 20:54:31 +0900 - - Suppress an "assigned but unused variable" warning - - (cherry picked from commit 501f2c44e6ae79c02a5c4d0f872fc7fa77258fcf) - -commit 44f7e3883e49d287a96f7ef36b5c935d833300e5 - Author: Nobuyoshi Nakada - Date: 2020-03-03 15:48:53 +0900 - - Preserve `kwarg` flag and fix up f5c904c2a9 - - (cherry picked from commit c8d0bf0156878df03a71fffc97c44abf7333d5d7) - -commit aeda3a7f036aa7c768abffd1965972c658f49c22 - Author: Yusuke Endoh - Date: 2020-03-02 22:37:04 +0900 - - Suppress "assigned but unused variable" warnings - - (cherry picked from commit 65dd50fc25f6522536d5c4749055384bde1f9371) - -commit 004c298738dc0924e7483b0c3f41c798dabe9e5b - Author: Nobuyoshi Nakada - Date: 2020-03-02 15:49:03 +0900 - - Allow newlines inside braced pattern - - (cherry picked from commit f5c904c2a907013e22ff74bc3686952c5448d493) - -commit 93aaa0bcce829b880d8f52a9168d17c93ecde85b - Author: Kazuki Tsujimoto - Date: 2020-03-01 14:23:51 +0900 - - Allow trailing comma in hash pattern - - (cherry picked from commit d25a4f413dce6ad3a8baaf61591415b9a8cce082) - -commit 5ccf57f23eb7a35ac699edc2fc598c47fa1844a0 - Author: Nobuyoshi Nakada - Date: 2020-03-25 22:00:15 +0900 - - Make RbConfig::CONFIG values mutable [Bug #16738] - - As `RbConfig.expand` modifies the argument and involved `CONFIG` - values, its values should be mutable. - - (cherry picked from commit 4adb2d655dcd54b28366b4d17e86b21e2b622cd1) - -commit 7b5133801340cfa7e4e4e5dd61384cb90c3f6085 - Author: Hiroshi SHIBATA - Date: 2020-01-08 16:11:52 +0900 - - Merge bundler-2.1.4 - -commit 572021c6e4e01c3b8ece90ad42fdd4ee71b8acc5 - Author: git - Date: 2020-03-26 23:51:12 +0900 - - * 2020-03-26 [ci skip] - -commit c9a7643a7e5993975e7e8c985df157d73b16a490 - Author: Yusuke Endoh - Date: 2020-03-21 15:46:33 +0900 - - test/openssl/test_ssl.rb: ignore SSLError when the connection is closed - - "test_close_after_socket_close" checks if ssl.close is no-op even after - the wrapped socket is closed. The test itself is fair, but the other - endpoint that is reading the SSL connection may fail with SSLError: - "SSL_read: unexpected eof while reading" in some environments: - - https://github.com/ruby/ruby/actions/runs/60085389 (MinGW) - https://rubyci.org/logs/rubyci.s3.amazonaws.com/android28-x86_64/ruby-master/log/20200321T034442Z.fail.html.gz - ``` - 1) Failure: - OpenSSL::TestSSL#test_close_after_socket_close [D:/a/ruby/ruby/src/test/openssl/utils.rb:299]: - exceptions on 1 threads: - SSL_read: unexpected eof while reading - ``` - - This changeset rescues and ignores the SSLError in the test. - - (cherry picked from commit be76e86e69106c6906322dc30aa75c3ff65da63c) - -commit 897d4e31b0e5b29405480ed3236bc8c5c6cac3fa - Author: Koichi Sasada - Date: 2020-03-07 03:55:54 +0900 - - check ar_table first. - - RHASH_AR_TABLE_SIZE() has assertion that it is a ar_talbe. - The last commit breaks this assumption so check ar_table first. - - (cherry picked from commit c3584dfacce4d0f2058d8403de6fdce4fd4d686b) - -commit ab6f78bc926f6fc12dc8d7846056fc9c04d63ead - Author: Koichi Sasada - Date: 2020-03-07 03:32:15 +0900 - - check ar_table after `#hash` call - - ar_table can be converted to st_table just after `ar_do_hash()` - function which calls `#hash` method. We need to check - the representation to detect this mutation. - [Bug #16676] - - (cherry picked from commit 4c019f5a626523e99e2827ed917802e3097c380d) - -commit e4efca87ba1aa5b6a94b9007040ac3e783c26b43 - Author: Koichi Sasada - Date: 2020-03-26 01:16:50 +0900 - - check flags passed to rb_nogvl() - - RB_NOGVL_UBF_ASYNC_SAFE is wrongly specified because flags - is not checked. - [Bug #15499] 23444302 - - (cherry picked from commit ff98931daca1265e5bd33025d160c77e452c399e) - -commit 2a3027b7b54a3118731f70c9e88aabbd495bb9fe - Author: Alan Wu - Date: 2020-03-14 09:59:55 +0900 - - Add missing write barrier for Hash#transform_values{,!} - - 21994b7fd686f263544fcac1616ecf3189fb78b3 removed the write barrier that - was present in rb_hash_aset(). Re-insert it to not crash during GC. - - [Bug #16689] - - (cherry picked from commit 713dc619f5372a645b66bef9dacee217c4101cb4) - -commit 95c3bb6c426a11253644a86137bb67c542fd5799 - Author: Nobuyoshi Nakada - Date: 2020-03-16 17:26:10 +0900 - - Do not make disabled directories at installation [Bug #12392] - - (cherry picked from commit 8a6ba10f9dd456cf54de800203cf04bbe42271fb) - -commit 1853efc46dba862c50df7710cfbacded999ae2ec - Author: NARUSE, Yui - Date: 2020-03-26 21:17:07 +0900 - - Use power_assert 1.1.7 - - Mainly for pry compatibility in test - https://github.com/k-tsj/power_assert/commit/dcc14cbef48d9790187fa400a5df7531d81a5971 - - Also include "Show full_message if available" - https://github.com/k-tsj/power_assert/commit/53ce0400bf47f722830d6604be0a2e30cccabf34 - -commit 47b08728cf3d0441a3da4dc1dcdd578817b0e036 - Author: Jean Boussier - Date: 2020-03-12 21:55:20 +0900 - - [ruby/stringio] StringIO#initialize default to the source string encoding - - [Bug #16497] - - https://github.com/ruby/stringio/commit/4958a5ccab - (cherry picked from commit e257c08f2ec27e2d66cdfa7e2415deb492522e22) - -commit 3efbd527a86203406664a01126784a10eb136405 - Author: Jeremy Evans - Date: 2020-01-25 05:13:41 +0900 - - Do not autosplat when calling proc with empty keyword splat - - With the removal of the splatted argument when using an empty - keyword splat, the autosplat code considered an empty keyword - splat the same as no argument at all. However, that results - in autosplat behavior changing dependent on the content of - the splatted hash, which is not what anyone would expect or - want. This change always skips an autosplat if keywords were - provided. - - Fixes [Bug #16560] - - (cherry picked from commit c1d8829ef515ee51fadeadd7dd022b5c47a71cdd) - -commit c858a10ce87033beec63516fe6407b50c6539177 - Author: git - Date: 2020-03-15 19:35:48 +0900 - - * 2020-03-15 [ci skip] - -commit a36ead3f4fe801ddaebe6d1ed905e9e3276dbac7 - Author: Takashi Kokubun - Date: 2020-02-29 16:58:33 +0900 - - Prevent unloading methods used in root_fiber while calling another Fiber (#2939) - - Fixing SEGVs like: - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2744905 - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2744420 - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2741400 - [Bug #16664] - - (cherry picked from commit adcf0316d1ecedae2a9157ad941550e0c0fb510b) - -commit 17e925b9917f4877f2da8c64316feb3ce1ca2932 - Author: Takashi Kokubun - Date: 2020-02-29 16:20:44 +0900 - - Avoid infinite loop on --jit-wait - - (cherry picked from commit a8dcab723316997d9e01c89d6df969edce75bdca) - -commit c6944377d798e088042f2944b81aa3fa8a4e5411 - Author: Jean Boussier - Date: 2020-02-03 20:29:37 +0900 - - Fix SimpleDelegator respond_to? regression - - In 2.6, SimpleDelegator would always use the target `respond_to?` - - In 2.7.0 it doesn't if the target does not inherit from Object. - - This breaks compatibility for delegated objects that inherit - from BasicObject and redefine `respond_to?`. [Bug #16606] - - (cherry picked from commit f2552216d43040cd42bbb9fd484eab6c70856fe6) - -commit d07a6dc10efa71123b36a4a3ff7d2ec6e52804d7 - Author: Nobuyoshi Nakada - Date: 2020-01-21 11:47:04 +0900 - - delegate.rb: fixed keyword arguments in DelegateClass - - `Delegator.delegating_block` should delegate keyword arguments - separately. [ruby-core:96949] - - (cherry picked from commit 9bcf4f3db26249772c983896ebbc9ff41f4614db) - -commit e70d52b0c377f8b2ed04311710c0ca9f4ebabd90 - Author: Jeremy Evans - Date: 2020-02-25 06:19:37 +0900 - - Make ruby2_keywords methods correctly handle **{} optimization - - Previously, this code: - - ruby2_keywords def foo(*a) a.last end - foo(**{}) - - Returned an empty frozen hash. However, the final hash should - not be frozen in this case, as it wouldn't be if foo accepted - a keyword splat. - - Use a new unfrozen empty hash instead of reusing the frozen empty - hash in this case. - - Fixes [Bug #16642] - -commit b3fabedc7043593812c9ad507b4648a55d74df99 - Author: git - Date: 2020-03-14 20:27:57 +0900 - - * 2020-03-14 [ci skip] - -commit e7555d467b882fa8213f17643b00557ed420b640 - Author: Takashi Kokubun - Date: 2019-12-31 16:20:17 +0900 - - Drop MinGW build from AppVeyor - - in favor of #2791 - - (cherry picked from commit b00418732c89ce42c1c4cef57d08344659fbdd2b) - -commit 0d24fb774d84d4a99454ce10fd343da00049a588 - Author: Jeremy Evans - Date: 2020-03-09 23:57:16 +0900 - - Don't display singleton class in Method#inspect unless method defined there - - Previously, if an object has a singleton class, and you call - Object#method on the object, the resulting string would include - the object's singleton class, even though the method was not - defined in the singleton class. - - Change this so the we only show the singleton class if the method - is defined in the singleton class. - - Fixes [Bug #15608] - - (cherry picked from commit e02bd0e713ef920e6d12c27f16548f48ec5c2cf0) - -commit eabf35a5d298c68f45dc600477fc586d7b868788 - Author: Nobuyoshi Nakada - Date: 2020-02-10 12:15:48 +0900 - - Fixed duplicated warning - - As `command_rhs` is always a "value expression", `command_asgn` - does not need the same check. [Bug #16619] - - (cherry picked from commit 6e6844320de989cb88a154e2ac75066ccea1bba2) - -commit fa48a26d886d86469a0075d91d152252e9fc0c8c - Author: Nobuyoshi Nakada - Date: 2020-02-24 15:33:50 +0900 - - Fixed symbol misused as ID - - `rb_funcallv_public` and `rb_respond_to` require an `ID`, not a - `Symbol`. [Bug #16649] - - (cherry picked from commit 8b6e2685a4b7c7de905f7ed60c02ef85e0724754) - -commit 3e7e1b965b06f3c843972d7e2f6e3d040374d67f - Author: Nobuyoshi Nakada - Date: 2020-02-18 14:34:26 +0900 - - Pass keyword arguments to IOs properly [Bug #16639] - - (cherry picked from commit 041c2932e336b509b0ddc1fdbd9f160bce8d4893) - -commit 2339be74e737b4c5f5330f845af2e7db0c7450e1 - Author: Yusuke Endoh - Date: 2020-02-15 16:27:03 +0900 - - lib/drb/drb.rb: Use ruby2_keywords for keyword separation - - [Bug #16634] - - (cherry picked from commit fb472ca7adbaceb35aae1b3a6b948720ffc9eb53) - -commit c7e0ce67430b5e312eb626a2c2f4b6a810b3b68b - Author: Nobuyoshi Nakada - Date: 2020-02-04 15:21:49 +0900 - - Add the loaded feature after no exception raised - - Retrying after rescued `require` should try to load the same - library again. [Bug #16607] - - (cherry picked from commit 7d6903dc476f982e7b432adbeef3a3d9372a309f) - -commit 7518b4e945675df9aca223c30ca711e1d82341ec - Author: NARUSE, Yui - Date: 2020-03-13 22:31:29 +0900 - - fix the order of definition - -commit fcaa00e58fd3a4cbaa19c6558783b43ee324d19e - Author: Hiroshi SHIBATA - Date: 2020-03-07 20:42:44 +0900 - - Use osuosl instead of GitHub releases - - Because the package provided by GitHub releases is different from sourceware. - - (cherry picked from commit 47a1872cd8b901b8aab6dedce7fa3807c97d290d) - -commit 6a2d779027818eda418c9118f700b36816e833a5 - Author: Hiroshi SHIBATA - Date: 2020-03-07 19:57:28 +0900 - - Switch to download libffi source package to github releases from sourceware.org - - [Bug #16681] - (cherry picked from commit 86022167461dc90b70164e2bb23316959bbfd6ba) - -commit 60d98fad86da1ada204c53789431ac0f5f3390ff - Author: Nobuyoshi Nakada - Date: 2020-01-17 23:49:26 +0900 - - [ruby/io-console] Set `OPOST` when `intr` is true - - To enable implementation-defined output processing, for the - compatibility with readline. [Bug #16509] - - https://bugs.ruby-lang.org/issues/16509 - - https://github.com/ruby/io-console/commit/8c8b0b6757 - (cherry picked from commit 4e56ec4ef74cf77dbcb4ce7c669e0595cd0d12fa) - -commit 9f504bb474770f1cac68988eac2a410e41c4bbb8 - Author: Nobuyoshi Nakada - Date: 2020-02-09 16:56:40 +0900 - - Separate objspace argument for rb_gc_disable and rb_gc_enable - - (cherry picked from commit aeaf0dc55595b8a5bfdd92007fb85ef13855c632) - -commit 047dfbdf69e1a300109c729c66b6a761032402dd - Author: Nobuyoshi Nakada - Date: 2020-01-28 09:18:12 +0900 - - Skip empty directories to install [Bug #16596] - - (cherry picked from commit 33d02e6bc7502c5a3f09c59908a8c9f08a474b8d) - -commit 5bdbee96e479f714c7f9b6b98f012268cbd9051b - Author: NARUSE, Yui - Date: 2020-03-13 21:43:44 +0900 - - Squashed commit of the following: [Backport #16516] - - commit c98c492578d898dc07a04b8240d8d5b1508ffafa - Author: Nobuyoshi Nakada - Date: Fri Jan 17 16:56:53 2020 +0900 - - Added test for f38b3e8c707ebdcad05aa9485cf1760640b74fbb - - commit f38b3e8c707ebdcad05aa9485cf1760640b74fbb - Author: Nobuyoshi Nakada - Date: Thu Jan 16 18:34:31 2020 +0900 - - Fixed the location of args node with numbered parameter - -commit a9284ecb90176b4d8e9aa264da14ea08931be48f - Author: Nobuyoshi Nakada - Date: 2020-02-09 16:41:56 +0900 - - Disable GC until VM objects get initialized [Bug #16616] - -commit 215eb86a7729bf0db487f399031ad55a1062fada - Author: Jean Boussier - Date: 2020-01-15 22:40:01 +0900 - - Increase the frozen_strings table initial size - - It was set to 1000 in a4a2b9be7a55bb61d17cf9673ed0d2a93bb52d31. - - However on ruby-2.7.0p0, there are much more than 1k frozen string right after boot: - - ``` - $ ruby -robjspace -e 'p ObjectSpace.each_object(String).select { |s| s.frozen? && ObjectSpace.dump(s).include?(%{"fstring":true})}.uniq.count' - 5948 - ``` - -commit 8a54630a6608d9b1a9d32db2ba33289a5454810d - Author: git - Date: 2020-03-13 21:32:13 +0900 - - * 2020-03-13 [ci skip] - -commit 3c93ed59773ca547239850d16f06451afbb0aeec - Author: Adam Isom - Date: 2020-01-17 06:42:36 +0900 - - Update documentation for Array/Hash Argument section of methods.rdoc - - [Bug #16514] - -commit c3cd92582f970812be51310e377c82b6d9e7be92 - Author: Kazuhiro NISHIYAMA - Date: 2020-02-20 00:13:44 +0900 - - Use `brew upgrade` instead of `brew update` - -commit 0149863dff42e0b7b6876cc3669aa3efcab6776e - Author: git - Date: 2020-02-20 16:36:30 +0900 - - * 2020-02-20 [ci skip] - -commit eaee631d5eda03f77ec39ec6fc1826a06ab06205 - Author: Takashi Kokubun - Date: 2020-02-19 16:16:19 +0900 - - Avoid jumping to a wrong destination - - when the next insn is already compiled by former branches. - -commit ccc3b9119c39a6cb08a643ab3d15a9c07ec28b1a - Author: git - Date: 2020-02-18 15:30:37 +0900 - - * 2020-02-18 [ci skip] - -commit 789c1df10a13a53d0504d4ba87c4e246692b1973 - Author: NARUSE, Yui - Date: 2020-02-18 15:30:00 +0900 - - increment teeny - -commit 0643eb2e59dbd80f9be001c2ec77c980e8aeff3f - Author: Ryuta Kamizono - Date: 2020-01-19 12:49:40 +0900 - - Fix typo s/test_ruby2_keywords_hash!/test_ruby2_keywords_hash/ - - In #2818, `Hash.ruby2_keywords!` has renamed to `Hash.ruby2_keywords_hash`. - -commit 9820f9ee0aaccd78e6e0489e8915d3925c6ee97c - Author: Yusuke Endoh - Date: 2020-01-06 18:22:43 +0900 - - hash.c: Add a feature to manipulate ruby2_keywords flag - - It was found that a feature to check and add ruby2_keywords flag to an - existing Hash is needed when arguments are serialized and deserialized. - It is possible to do the same without explicit APIs, but it would be - good to provide them as a core feature. - - https://github.com/rails/rails/pull/38105#discussion_r361863767 - - Hash.ruby2_keywords_hash?(hash) checks if hash is flagged or not. - Hash.ruby2_keywords_hash(hash) returns a duplicated hash that has a - ruby2_keywords flag, - - [Bug #16486] - -commit 420a88d3da6deb5f7d4d8e088cb3737b9a23d29d - Author: git - Date: 2020-02-13 15:23:02 +0900 - - * 2020-02-13 [ci skip] - -commit 78cbe7106b67d007ffdcc1276b352212eaaef4b2 - Author: Nobuyoshi Nakada - Date: 2020-01-31 12:52:22 +0900 - - Return the makefile content - - Block for `create_makefile` is expected to return the content of - the makefile. - -commit b8e62ccaecf49372833d7eeeb3fdfded4bb2f042 - Author: NARUSE, Yui - Date: 2020-01-31 08:00:56 +0900 - - Move .IGNORE in extconf.rb - -commit a89821243da3c80e08bf46669e16ae46d687c80b - Author: NARUSE, Yui - Date: 2020-01-31 06:34:49 +0900 - - Support nmake - -commit a930174d798b58ee10493bf192d277ffe08518a7 - Author: NARUSE, Yui - Date: 2020-01-31 02:46:05 +0900 - - Ignore expected errors on compiling C++ source [Bug #16331] - - BSD make can run parallel more aggressively than GNU make. It communicate - with other make process through -J option in MAKEFLAGS environment variable - to notify a build failure happend in an other pararell make process. - https://www.freebsd.org/cgi/man.cgi?make - - It usually works well but ext/-test-/cxxanyargs/Makefile has two targets - which are expected to fail (failure.o and failurem1.o). - - Additional note: - To test and debug this issue, following command will speed up it. - `make -f exts.mk -j8 clean all` - -commit 95ab9cd8f453099d7649dc0e0eec55ea891340f5 - Author: Nobuyoshi Nakada - Date: 2020-02-11 15:52:25 +0900 - - Restart timer thread even after preparation failed - - If the timer thread is left stopped, memory crash or segfault can - happen. [Bug #16624] - -commit 9c07f803db1c20241fa73e91a8a959d6cbb82e8b - Author: NARUSE, Yui - Date: 2020-01-30 13:36:47 +0900 - - check ruby_2_7 branch - -commit 49430aa4e5bf4020dbdb1cce3bc547cffad6ffae - Author: Nobuyoshi Nakada - Date: 2020-01-19 11:02:18 +0900 - - Allow rexml to fail on macOS of Github Actions - - And revert "Stop test-bundled-gems on macOS for now", - 28b290f7f4cb332dab3ddf3132e1916d413ea65c. - -commit 30a9dc4aa9cb1985cfe5bd318b8b35dacc103127 - Author: Nobuyoshi Nakada - Date: 2020-01-19 09:48:33 +0900 - - Stop test-bundled-gems on macOS for now - -commit 095a937dc2c0924dbfda7f7625ac2921a10de231 - Author: Yusuke Endoh - Date: 2020-01-17 17:25:05 +0900 - - .github/workflows/cygwin.yml: Removed - - There is no active maintainer for cygwin. The CI failure is too noisy. - - [Misc #16407] - -commit 5eced3c030f39d10e193c5e33a70365d8e011bb1 - Author: Nobuyoshi Nakada - Date: 2020-01-13 10:02:04 +0900 - - Checkout with git on cygwin for EOL code - - `shell: bash` runs bash on msys which prefers git on msys too, - then checked out in CRLF mode. Cygwin sed doesn't consider the CR - a part of EOL code, though. - -commit 6ec6acd76ed7c718a469841afe4f32571e757c9d - Author: Hiroshi SHIBATA - Date: 2020-01-12 09:59:10 +0900 - - Allow failures with rss tests on test-bundled-gems - -commit 504b082f364e35516b2727c11713c28b684b5af0 - Author: Kazuhiro NISHIYAMA - Date: 2020-01-11 16:24:16 +0900 - - Add branch option to checkout on push - -commit 5dc82455aef4a42817208e11fbfbcdc1351f0734 - Author: Takashi Kokubun - Date: 2020-01-06 18:52:19 +0900 - - Slightly change the job wording [ci skip] - - mame-san said it's weird - -commit 7d4243254629004007a390f7f1afc4a570a1fd00 - Author: Takashi Kokubun - Date: 2020-01-06 18:45:47 +0900 - - Support running Actions on a fork - - Since 8c9450e7b875db846b19cc631af0d7fee66db5c6, we increased the chance - to run GitHub Actions on a fork, as we usually use a topic branch - instead of master when filing a pull request. - - This patch makes it possible to reuse the same GitHub Actions config on - a fork repository. - -commit bd48a28b1cb9848d194a82139d018f87dd689f99 - Author: Takashi Kokubun - Date: 2020-01-06 18:42:30 +0900 - - Directly refer to GitHub events - - instead of unnecessarily defining env vars - -commit 48f82ad28961c0998b1d426493614875bb487d29 - Author: Takashi Kokubun - Date: 2020-01-01 15:03:07 +0900 - - Remove code to prevent double build on trunk - - trunk branch was deleted. - -commit fdd9d7cd41cde130889d84414395da22706972c8 - Author: Takashi Kokubun - Date: 2020-01-01 14:26:39 +0900 - - More consistent failure notifications - - The format is the same as Travis / AppVeyor now. - -commit 531bbec111d588ad497dd528eae3ac36e2af2632 - Author: Takashi Kokubun - Date: 2020-01-01 08:27:40 +0900 - - Make test run condition consistent with other jobs - - When `make all` fails, we should not run tests and output of such run is - confusing. - -commit 4d04b32986bb73bfd5d5e56bcd17cfa82c90885c - Author: Takashi Kokubun - Date: 2020-01-01 03:24:00 +0900 - - Run tests in the consistent order - - `make check` runs test -> test-all -> test-spec, and other CIs follow that too. - -commit 24621f23e5cc9403910b82e671c2b299ec65bd67 - Author: Takashi Kokubun - Date: 2020-01-01 02:37:03 +0900 - - Fix an outdated comment - - We're actually using it for PR :p - -commit e3dfd9f2b5729d4d8ac4541110af409ee218aadd - Author: MSP-Greg - Date: 2020-01-01 02:35:43 +0900 - - Actions MinGW - fix test-all (#2803) - -commit a24d2f3b8cf98d067f6648a0609b6251d3e0a464 - Author: Takashi Kokubun - Date: 2020-01-01 02:34:29 +0900 - - Use actions/checkout for PR (#2804) - -commit 77dfa520d476143b8be6c4805354838012b4d335 - Author: Takashi Kokubun - Date: 2019-12-31 18:49:08 +0900 - - Official actions/checkout is useless - - It died again https://github.com/ruby/ruby/runs/368837347 - -commit 124878c6aad7c708d7121199bea29962713d319a - Author: Takashi Kokubun - Date: 2019-12-31 16:46:17 +0900 - - Make Slack notifications consistent - -commit 110b4e974ddb74472a0eb3ce181705b47eb28d50 - Author: Takashi Kokubun - Date: 2019-12-31 16:42:20 +0900 - - There's no such target - -commit 4d9f106eaefeee4b160d3c5580039c64ff9c01ae - Author: Takashi Kokubun - Date: 2019-12-31 16:30:34 +0900 - - Make all Actions job names consistent - - like "{platform} / make ({make target}, ...)" - -commit ca48fa8e81ca19f4d0c24017662245c933be86eb - Author: Takashi Kokubun - Date: 2019-12-31 16:23:25 +0900 - - Do not doubly build on trunk - -commit 44ef8af4fb0a793f020147e3f077cd061953c8fa - Author: MSP-Greg - Date: 2019-12-31 16:19:31 +0900 - - MinGW on Actions (#2791) - - * MinGW - skip spec in spec/ruby/optional/capi/thread_spec.rb - - C-API Thread function rb_thread_call_without_gvl - -- runs a C function with the global lock unlocked and unlocks IO with the generic RUBY_UBF_IO - - stops/freezes spec tests - - See https://bugs.ruby-lang.org/issues/16265 - - * MinGW - skip test test/resolv/test_dns.rb - - Test times out in CI (both AppVeyor & Actions), cannot repo locally - - * MinGW - skip test test/ruby/test_thread_queue.rb - - * Add Actions mingw.yml - -commit 6646c2b2ab7efd389075ad5f187b458c4bc138cc - Author: Takashi Kokubun - Date: 2019-12-31 16:09:24 +0900 - - Revert "Remove TEST_BUNDLED_GEMS_ALLOW_FAILURES" - - This reverts commit 75e8dd58f69c190c9698d0133942032903fb2f07. - - We seem to randomly hit another issue these days: - https://github.com/ruby/ruby/runs/368756135 - https://github.com/ruby/ruby/runs/368756191 - -commit 716e05b82338d75452e86c999ae3e5874a642ecd - Author: Nobuyoshi Nakada - Date: 2020-01-27 10:46:57 +0900 - - Fixed a segfault `GC.verify_compaction_references` - - Which is by coercion of `Qundef`, when any keyword argument - without `toward:` option is given. [Bug #16598] - -commit 52bb32d6b71365cb24273de3eed5a712206815f3 - Author: Alan Wu - Date: 2019-12-31 08:13:55 +0900 - - Fix Proc#<< spec - - [Bug #16406] - -commit db4d136889afbf59e69efcfd495fd91cd401f378 - Author: Nobuyoshi Nakada - Date: 2020-01-16 11:25:43 +0900 - - `Regexp` in `MatchData` can be `nil` - - `String#sub` with a string pattern defers creating a `Regexp` - until `MatchData#regexp` creates a `Regexp` from the matched - string. `Regexp#last_match(group_name)` accessed its content - without creating the `Regexp` though. [Bug #16508] - -commit 8e8841f6bf58031a1fe5b0dbacb5a1fb442102df - Author: Koichi Sasada - Date: 2020-01-13 03:36:47 +0900 - - reload AR table body for transient heap. - - ar_talbe (Hash representation for <=8 size) can use transient heap - and the memory area can move. So we need to restore `pair' ptr after - `func` call (which can run any programs) because of moving. - [Bug #16503] - -commit 48f324e92f9b36edc267f9871e35039cbd1c2eb9 - Author: Yusuke Endoh - Date: 2020-01-09 08:21:42 +0900 - - lib/net/imap.rb: use `&blk` instead of Kernel#proc with no block - - [Bug #16488] - -commit 580edc25aa00930bdb71b244d70a2007905f5fec - Author: Koichi Sasada - Date: 2020-01-06 11:36:51 +0900 - - script_compiled event on compile error. - - script_compiled event for TracePoint should not be invoked on - compile error (SyntaxError) because it is not "compiled". - [Bug #16459] - -commit 647ee6f091eafcce70ffb75ddf7e121e192ab217 - Author: aycabta - Date: 2019-12-25 18:46:39 +0900 - - [ruby/reline] Version 0.1.2 - - https://github.com/ruby/reline/commit/b41024e317 - -commit 1341a279a4becd91f35b23eca6d129990eccc8bb - Author: aycabta - Date: 2019-12-25 18:45:02 +0900 - - Save last breaking point to complete - -commit a52e364e6541a6e234718ac63aa7eb5c3f2c832f - Author: NARUSE, Yui - Date: 2019-12-25 18:02:53 +0900 - - fix version regexp - -commit ecbf7fe27ce444782f0a48fc41f8043a25078666 - Author: NARUSE, Yui - Date: 2019-12-25 17:01:26 +0900 - - fix typo - -commit a65e8644fb97491314387e4138cabf6378a8e8d5 - Author: NARUSE, Yui - Date: 2019-12-25 15:48:56 +0900 - - v2.7.0p0 - -commit 75dca097b873222eaf3c70b7f43e3ffb98b7f2ed - Author: Yusuke Endoh - Date: 2019-12-25 14:13:15 +0900 - - [bundler/bundler] Do `require "rubygems"` only when needed - - This require causes circular require. - - ``` - $ touch empty_file - - $ RUBYGEMS_GEMDEPS=empty_file ./local/bin/ruby -w -e '' - /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92: warning: /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92: warning: loading in progress, circular require considered harmful - /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems.rb - from :1:in `' - from :1:in `require' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems.rb:1417:in `' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems.rb:1203:in `use_gemdeps' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/user_interaction.rb:47:in `use_ui' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems.rb:1204:in `block in use_gemdeps' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/bundler.rb:11:in `' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/bundler.rb:11:in `require_relative' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/bundler/rubygems_integration.rb:3:in `' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' - from /home/mame/work/ruby/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' - ``` - - https://github.com/bundler/bundler/commit/c7c5bcea92 - -commit 27453b04c85249372950b6b12fabbef8c0d1a80b - Author: Kenta Murata - Date: 2019-12-25 15:21:50 +0900 - - Update the version of bigdecimal to 2.0.0 (#2784) - - Notes: - Merged-By: mrkn - -commit 56e002981fab73a94c6038cb9de82aba6ff84eb4 - Author: Nobuyoshi Nakada - Date: 2019-12-25 14:47:31 +0900 - - Show the error line only when same as the current - -commit 9808e010907bb16068497d9f0f8593a7165fa42d - Author: Koichi Sasada - Date: 2019-12-25 14:37:53 +0900 - - export a function for MJIT. - - rb_iseq_complete() can be used by MJIT. - -commit d9bf9c572f461c282fa6e65833e98bc7d453a66f - Author: Koichi Sasada - Date: 2019-12-25 14:10:35 +0900 - - take care of USE_LAZY_LOAD=1. - - On USE_LAZY_LOAD=1, the iseq should be loaded. So rb_iseq_check() - is needed. Furthermore, now lazy loading with builtin_function_table - is not supported, so it should cancel lazy loading. - -commit 81e377023c490998a3fec245ca2fb2b3c710c2c6 - Author: Yusuke Endoh - Date: 2019-12-25 13:35:22 +0900 - - range.c: Range#min with a beginless one now raises an explicit exception - - [Bug #16450] - -commit cd6c013b075c9c27437f30efcee9d4dd9e0ee1c5 - Author: aycabta - Date: 2019-12-25 12:55:31 +0900 - - Add readline and readline-ext to default gems list in NEWS - -commit 227c3d642631262acfbf140c566a7841c32b372f - Author: Koichi Sasada - Date: 2019-12-25 12:06:02 +0900 - - add ref to NEWS entry - -commit 3345eab934073bdd8394ee8a46fc18954999af76 - Author: Yusuke Endoh - Date: 2019-12-25 11:37:27 +0900 - - NEWS: add a ticket reference - -commit b9e35d27096290f9544dca685fb4cf5bd0e09397 - Author: Yusuke Endoh - Date: 2019-12-25 11:31:44 +0900 - - NEWS: add a ticket reference - -commit e0929c44ddc7490dc97cabf12c7505173316a623 - Author: Yusuke Endoh - Date: 2019-12-25 11:27:13 +0900 - - NEWS: add ticket references - -commit eb3f19b9b896094ae9754de1b48fed86fb35fe39 - Author: Nobuyoshi Nakada - Date: 2019-12-25 11:17:24 +0900 - - update-bundled_gems: drop branch name on github [ci skip] - -commit 00710d10761ad1aa752cf2c035e3bfbde40092b6 - Author: aycabta - Date: 2019-12-25 10:47:53 +0900 - - [ruby/readline] Version 0.0.2 - - https://github.com/ruby/readline/commit/42b71f3fc0 - -commit e51a34511c9e4394467cde24deee19cf8536a3e7 - Author: aycabta - Date: 2019-12-25 10:47:34 +0900 - - [ruby/readline] Use a box to make easier to see the message - - https://github.com/ruby/readline/commit/e49e942053 - -commit 57c74841c7bc2bb2ffbb8ed89597e993116e26a8 - Author: aycabta - Date: 2019-12-25 10:44:52 +0900 - - [ruby/readline] Fix any wrong in messages - - https://github.com/ruby/readline/commit/a2cf437c8f - -commit de0f4f2fd7620e2486f5aef031dad18324437c2b - Author: aycabta - Date: 2019-12-25 10:30:24 +0900 - - [ruby/readline] Version 0.0.1 - - https://github.com/ruby/readline/commit/d2363cad33 - -commit 5d20865708552a522d5eb39c4d9238f96693f8f2 - Author: aycabta - Date: 2019-12-25 10:25:15 +0900 - - [ruby/readline] Add post_install_message - - https://github.com/ruby/readline/commit/03126372b5 - -commit 999a2819a75e40aec405e088d01b12eda341025d - Author: aycabta - Date: 2019-12-25 10:31:03 +0900 - - [ruby/readline-ext] Version 0.1.0 - - https://github.com/ruby/readline-ext/commit/f5abaf5be1 - -commit 246242700867ed3fdce8288897d74bd261379018 - Author: aycabta - Date: 2019-12-25 10:08:06 +0900 - - [ruby/reline] Version 0.1.1 - - https://github.com/ruby/reline/commit/923f97d068 - -commit ed5b4bae6a4f991a0c5299581bd0b137a98d3723 - Author: aycabta - Date: 2019-12-25 09:52:25 +0900 - - The behavior of vi_end_of_transmission should be the same of vi_list_or_eof - -commit 03c504ac59a2bf78bab925379e93184d81296e96 - Author: Hiroshi SHIBATA - Date: 2019-12-25 09:38:12 +0900 - - Commented-out btest on cygwin environment of GitHub Actions - -commit 622e47a1dbeee52fb218b816943b69cb88e17ae6 - Author: aycabta - Date: 2019-12-25 09:29:46 +0900 - - ^D on non-empty line in vi mode behaves like Enter - -commit 8e6d51e09a93ae2c57d56105a5fd39fb92855394 - Author: Yuki Nishijima - Date: 2019-12-25 08:41:26 +0900 - - Sync did_you_mean - -commit 2b2be71cabf987effd2783747eedf573af1400cf - Author: Yuki Nishijima - Date: 2019-12-25 08:23:59 +0900 - - Add did_you_mean's promotion to the NEWS - - Notes: - Merged: https://github.com/ruby/ruby/pull/2782 - -commit 1857b4427817755bb0879ca67e1b2f3276f95d4c - Author: Hiroshi SHIBATA - Date: 2019-12-25 07:28:02 +0900 - - Merge Bundler 2.1.2 from bundler/bundler. - - [Misc #16449][ruby-core:96458] - -commit da0a0bae8b50087d140309b27eb4d4b4776c27e4 - Author: Marcus Stollsteimer - Date: 2019-12-25 06:13:49 +0900 - - NEWS: add meaning of "CoW" ("copy-on-write") - -commit ceba5b70889666b82b80910a441cf4a92b5c7160 - Author: Marcus Stollsteimer - Date: 2019-12-25 05:50:27 +0900 - - [DOC] Fix typo in Time#inspect - -commit f3067deb88badf8d15e49d13f082284f58b2c62b - Author: Alan Wu - Date: 2019-12-25 04:54:20 +0900 - - Revert "Add NEWS entry about Module#name performance (#2779)" (#2781) - - This reverts commit 3e9221d94a12b54c1285923b642364acdbc31c7e. - - Notes: - Merged-By: XrXr - -commit 3e9221d94a12b54c1285923b642364acdbc31c7e - Author: Alan Wu - Date: 2019-12-25 04:02:50 +0900 - - Add NEWS entry about Module#name performance (#2779) - - Notes: - Merged-By: XrXr - -commit 5220145ea289d9eb955b373f31773fab2d4f0271 - Author: Koichi Sasada - Date: 2019-12-25 01:32:37 +0900 - - add debug_counter access functions. - - These functions are enabled only on USE_DEBUG_COUNTER=1. - -commit 9b617ffa8884f9f80a0b1bdb89169d8139ba5001 - Author: git - Date: 2019-12-25 01:00:40 +0900 - - * 2019-12-25 [ci skip] - -commit 3679023df822d8bf3f88b9b2e4b849318d2c409e - Author: Marcus Stollsteimer - Date: 2019-12-25 00:57:30 +0900 - - [DOC] Fix typo and language - -commit 8c017824c8eeffe11070ce69c914725af314d9f6 - Author: Hiroshi SHIBATA - Date: 2019-12-24 22:31:38 +0900 - - Added entry for json-2.3.0 - -commit 1cd2ebed616473ed56730292879e8bc9d6dfd060 - Author: Hiroshi SHIBATA - Date: 2019-12-24 21:39:37 +0900 - - Update the news entries for RubyGems and Bundler - -commit 05b0410f91360e15511903580f0401b123f3abce - Author: Marcus Stollsteimer - Date: 2019-12-24 21:17:00 +0900 - - [ruby/irb] Fix typo - - https://github.com/ruby/irb/commit/4bb1340687 - -commit 54083fd41bf876b42e1a97acdc7574c8edbb87ed - Author: Marcus Stollsteimer - Date: 2019-12-24 21:01:47 +0900 - - [DOC] Fix grammar in Process module docs - -commit 66e518f7b3e0bf307f86a51e6db02c3d1ec8df84 - Author: Marcus Stollsteimer - Date: 2019-12-24 21:01:24 +0900 - - [DOC] Fix typo - -commit 4ba9347554ab1ac79fdaf1d5b3320776a2b10615 - Author: Nobuyoshi Nakada - Date: 2019-12-24 18:49:57 +0900 - - `Object#=~` warning also obeys `Warning[:deprecated]` - -commit a3c5dbf29191aa8622d8be7d990c4ac2f9392427 - Author: Nobuyoshi Nakada - Date: 2019-12-24 14:56:17 +0900 - - Scale sleeping times to wait for the OS operations - -commit 7758849cb5432ae974f616668f9c9bab415bb18a - Author: aycabta - Date: 2019-12-24 18:39:48 +0900 - - Remove unused variable - -commit 42e2a322f100c7c798fcfbcbbfe0b4cdaf3f5855 - Author: aycabta - Date: 2019-12-24 18:32:50 +0900 - - The delete-char-or-list shows completed list when called at end of line - - It doesn't behave the same as the delete-char. - -commit b03aea62abfbdc7c8ee53c30a27127c3c394a6ba - Author: Marcus Stollsteimer - Date: 2019-12-24 18:02:22 +0900 - - NEWS: fix method references for Range#{cover?,include?} - -commit 44a1f51695058159ff2f191c97a082bed9665137 - Author: Marcus Stollsteimer - Date: 2019-12-24 17:49:22 +0900 - - NEWS: improve sections for warning option / Warning - -commit 27b4f477d960c75f3ff5cd5e045b307cad314ec7 - Author: Marcus Stollsteimer - Date: 2019-12-24 17:03:42 +0900 - - [DOC] Improve docs for Enumerator.produce, Enumerator.new - -commit 81504e83e72bf125476528e5f119604d9697f682 - Author: Nobuyoshi Nakada - Date: 2019-12-24 15:47:59 +0900 - - Synchronize with a Queue instead of sleeping - -commit 47ad57f2450251f47b3f8e1f744d782269bbcdeb - Author: Koichi Sasada - Date: 2019-12-24 15:38:46 +0900 - - Revert "Scale sleeping times" - - This reverts commit e57d6194218efc73c30f3fed9dd321d2e357030b. - - Test fails: - http://ci.rvm.jp/results/trunk-gc-asserts@ruby-sky1/2518563 - http://ci.rvm.jp/results/trunk-gc_compact@silicon-docker/2518533 - -commit c47106699cf2bcf426285efcd795223c200a3120 - Author: Nobuyoshi Nakada - Date: 2019-12-24 14:57:55 +0900 - - NEWS: added references to warning option [ci skip] - -commit e57d6194218efc73c30f3fed9dd321d2e357030b - Author: Nobuyoshi Nakada - Date: 2019-12-24 14:56:17 +0900 - - Scale sleeping times - -commit adf498b84f56e57b74b72a3ddcc512f6d2078cef - Author: Nobuyoshi Nakada - Date: 2019-12-24 13:24:41 +0900 - - Moved warning option section and added a reference [ci skip] - -commit 302e896833bc611ba39c8697712313fd2dbd70cc - Author: Nobuyoshi Nakada - Date: 2019-12-24 13:12:28 +0900 - - Added warning.rb to .document - -commit 3739ddc36f462b794ec05c0cfc36458a8d1e17a7 - Author: Nobuyoshi Nakada - Date: 2019-12-24 12:11:42 +0900 - - Added `-W:experimental` to `--help` [Feature #16420] - -commit d0f1eb3e4ef7cde2d78b493b3ba1561eee79b18f - Author: Nobuyoshi Nakada - Date: 2019-12-24 11:28:18 +0900 - - Separated command line option in NEWS [ci skip] - -commit 5a62fb1277fb351a1a11b89b0f8510c8f1a0cdff - Author: Nobuyoshi Nakada - Date: 2019-12-24 11:14:13 +0900 - - Mentioned `-W:` command option in NEWS [ci skip] - -commit f2e1e6cba451375d8eb839bf2e7c9a39bccc044c - Author: zverok - Date: 2019-12-22 06:23:20 +0900 - - Enhance explanations for beginless range and #clamp, and add missing feature - - Notes: - Merged: https://github.com/ruby/ruby/pull/2769 - -commit e954be14d07e54b8dbf71c0fa227e5818eaa01e6 - Author: Nobuyoshi Nakada - Date: 2019-12-24 10:27:18 +0900 - - Get rid of false positive misspellings - - [Bug #16437] - -commit 992aa2cda50140abbca165024682eae998756e2d - Author: Nobuyoshi Nakada - Date: 2019-12-24 10:24:45 +0900 - - enc/x_emoji.h: fixed dead-links [ci skip] - - English version pages seem no longer provided. - -commit f09a4ff265093742c356c69bcf56db68bd6cf064 - Author: manga_osyo - Date: 2019-12-24 09:53:36 +0900 - - Added NEWS for Feature 15373 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2777 - -commit 360f153fcaab637486aa2669d354d53e0eb1c3d2 - Author: Koichi Sasada - Date: 2019-12-24 10:23:38 +0900 - - remove "experimental" from numbered parameter. - - Numbered parameter is not an experimental feature, - confirmed by Matz. - https://twitter.com/yukihiro_matz/status/1209271452798607361 - -commit 5e17834fc900a699241764ef0baacd53992d7f07 - Author: aycabta - Date: 2019-12-24 09:55:05 +0900 - - [ruby/reline] Version 0.1.0 - - https://github.com/ruby/reline/commit/55d4dfec1e - -commit 8316b330fb04413bb480462941cb6b14c5352e2e - Author: aycabta - Date: 2019-12-24 09:54:38 +0900 - - [ruby/irb] Version 1.2.1 - - https://github.com/ruby/irb/commit/8da0c74640 - -commit 0e528ae9cb5c1078e4d07287e403cb548e97f0a3 - Author: aycabta - Date: 2019-12-24 09:53:43 +0900 - - [ruby/irb] Remove warning message to bundle on Ruby 2.7.0 - - https://github.com/ruby/irb/commit/d9a7844f50 - -commit 0231661939310951c8ed339d8600a53a21015918 - Author: Marcus Stollsteimer - Date: 2019-12-24 08:13:46 +0900 - - [DOC] Fix wording in Math::E documentation - -commit 30c5e8c4b9353dfb716033901cec7529eace3922 - Author: aycabta - Date: 2019-12-24 08:03:00 +0900 - - [ruby/rdoc] Version 6.2.1 - - https://github.com/ruby/rdoc/commit/c65e14d112 - -commit 2bf0743edcf6fd70cd73952e1e023821c4549a9e - Author: aycabta - Date: 2019-12-24 07:58:49 +0900 - - Update parsers of RDoc that are generated by Racc - -commit adc9b3ca7f4e75e368731fe8a7092ce078bcec04 - Author: aycabta - Date: 2019-12-24 07:41:37 +0900 - - [ruby/rdoc] Support newline in the middle of constant definition - - https://github.com/ruby/rdoc/commit/74d3984324 - -commit e50e55269358520dc55595a9c3e074d351d96b66 - Author: aycabta - Date: 2019-12-24 07:00:35 +0900 - - [ruby/rdoc] Treat Proc#call syntax sugar for constant correctly - - https://github.com/ruby/rdoc/commit/957d041ae0 - -commit 819b604037c317d2b53a1aaca67aef25da2d5ec9 - Author: Marc-Andre Lafortune - Date: 2019-12-23 16:34:16 +0900 - - Reword keyword arguments warning messages to convey these are deprecation warnings - -commit df6f5c44af1f261fa940ec3954468be8b820450e - Author: Marcus Stollsteimer - Date: 2019-12-24 06:41:58 +0900 - - [DOC] Fix invalid code to make it syntax highlighted - -commit a7b5018495c4a6b82d779958b086647226ce61e7 - Author: Marcus Stollsteimer - Date: 2019-12-24 06:07:02 +0900 - - [DOC] Use capitalized "Ruby" - -commit ba9ccef81811e9387c0189d596189236b25d0dba - Author: Marcus Stollsteimer - Date: 2019-12-24 06:04:59 +0900 - - [DOC] Various fixes in bug triaging guide - -commit aa01441fd29be8be28644db7abac9f7940fcc814 - Author: git - Date: 2019-12-24 04:17:11 +0900 - - * 2019-12-24 [ci skip] - -commit f201700051cc107b55c425bf331ce6d7ad3ef22b - Author: Koichi Sasada - Date: 2019-12-24 04:16:40 +0900 - - move a NEWS entry about inline method cache - -commit 16fddfe352828d26aaa6cdbce696e62de04511ce - Author: Marcus Stollsteimer - Date: 2019-12-23 23:02:59 +0900 - - [DOC] Improve readability of requirements for <=> - -commit 9a42e0c7ed4dcc57043a8a35a50686625adba686 - Author: Marcus Stollsteimer - Date: 2019-12-23 22:46:58 +0900 - - NEWS: add reference for [Feature #14405] - -commit de1a462454f4196490263c9be8be16a44513f5a0 - Author: Marcus Stollsteimer - Date: 2019-12-23 22:45:24 +0900 - - NEWS: revise grammar, language, markup, etc. - -commit bbde77cd2694e87646842777e873d849bbf5703e - Author: Marcus Stollsteimer - Date: 2019-12-23 17:46:08 +0900 - - NEWS: fix some typos, grammar, and language - -commit 100fc2750b8f2c4dbe0aaa6c622bbf5f6d61e3c0 - Author: Koichi Sasada - Date: 2019-12-23 17:04:31 +0900 - - fix wmap_finalize. - - wmap_finalize expects id2ref() returns a corresponding object - even if the object is dead. Make id2ref_obj_tbl() for this - purpose. - -commit 9eeaae432b9a894e28e3906435f3d454d8fd025c - Author: Koichi Sasada - Date: 2019-12-23 16:30:45 +0900 - - add more debug counters to count numeric objects. - -commit 7779ade48c2786992e41c0ab87761ab467f4be49 - Author: Marc-Andre Lafortune - Date: 2019-12-23 15:59:17 +0900 - - NEWS: Fix issue reference [#15807] [DOC] - -commit dadf1255b6e13578f888c239f0dc6fb201fd40bb - Author: Marc-Andre Lafortune - Date: 2019-12-23 15:55:39 +0900 - - README: Add Range#minmax to the list of potential incompatibilities [#15929] [DOC] - -commit 3e1adf573110ddce8f900d9473dde7fa7de9c0e2 - Author: Marc-Andre Lafortune - Date: 2019-12-23 15:48:38 +0900 - - README: Improve wording [DOC] - -commit 7df2503b7770147a8589a594bf30726f733b1d86 - Author: Marc-Andre Lafortune - Date: 2019-12-23 15:37:45 +0900 - - NEWS: Hint at potential incompatibility with Range#minmax [#15807] - -commit a96f8cecc2488126d7298ea304da8bad3dde1792 - Author: Koichi Sasada - Date: 2019-12-23 15:02:14 +0900 - - ObjectSpace._id2ref should check liveness. - - objspace->id_to_obj_tbl can contain dead objects because of lazy - sweep, so that it should check liveness. - -commit 672a61b97fe0cdb256611c707e7cc69856208467 - Author: Yuki Nishijima - Date: 2019-12-23 14:47:03 +0900 - - Port https://github.com/ruby/did_you_mean/commit/dd1dd86e6c3188c36224d5dd4389676e6653a727 - -commit 92d0958257965adf426e6f6c654c5935a690bf5b - Author: Kazuhiro NISHIYAMA - Date: 2019-12-23 13:23:08 +0900 - - FrozenError.new accepts :receiver instead of 2nd argument [ci skip] - - [ruby-core:96227] [Feature #16419] - -commit 3142a6beb28db36dc9150f1ad6752cd1e19a8712 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-23 12:07:15 +0900 - - Revert "Changed behavior on windows platforms too [ci skip]" - - This reverts commit 1bf8d5e9797f6304b2e27cb7f42d467f84de0ff4. - - Because 204dc3f39f12b4e2640555306bd1dd4530344277 reverts 61aff0cd189e67fa6f2565639ad0128fa33b88fc - -commit 204dc3f39f12b4e2640555306bd1dd4530344277 - Author: NAKAMURA Usaku - Date: 2019-12-23 11:54:25 +0900 - - Revert "Should return "." for File.extname("file.") also on Windows" - - We want to introduce consistency and better compatibility with unixen, - but the Windows APIs do not have consistency fundamentally and - we can not found any logical way... - - This reverts commit 61aff0cd189e67fa6f2565639ad0128fa33b88fc. - -commit 048f797bf019cdf303d70494fba63d4a4e606462 - Author: Marc-Andre Lafortune - Date: 2019-12-23 10:54:50 +0900 - - [ruby/prime] Bump version - -commit 446c243da35831de701ff6dd6c3c6da8252b6a10 - Author: Marc-Andre Lafortune - Date: 2019-12-23 09:44:43 +0900 - - [ruby/ostruct] Bump version - -commit 9be3295d53b6fd9f8a3ad8157aa0655b1976d8ac - Author: Marc-Andre Lafortune - Date: 2019-12-23 09:40:32 +0900 - - [ruby/ostruct] Create OpenStruct::VERSION - -commit 49d94248ebfb7a51e342f8102d21ad132a40f91a - Author: Marc-Andre Lafortune - Date: 2019-12-23 09:34:42 +0900 - - [ruby/ostruct] Move gemspec - -commit 48d1acdf25b13bd9e28bf6baa3f74ec082a27a00 - Author: Marc-Andre Lafortune - Date: 2019-12-23 08:33:19 +0900 - - [ruby/matrix] Bump version - -commit 1ed87dd3c4fb085955bb3848579a3ed7aba38507 - Author: Nobuyoshi Nakada - Date: 2019-12-22 13:56:20 +0900 - - Add NEWS about Warning.[] [Feature #16345] [ci skip] - -commit 5de284ec78220e75643f89b454ce999da0c1c195 - Author: Nobuyoshi Nakada - Date: 2019-12-23 10:37:30 +0900 - - Fixed a typo in an exception class name - -commit 5f18635a800eee29fd051ea758a2ec561f090ebe - Author: Nobuyoshi Nakada - Date: 2019-12-23 10:10:23 +0900 - - make-snapshot: fixed mode - - "X" must be used in conjunction with "+". - -commit 80d5d220b948517306e23b18260768ab8fe008bc - Author: Nobuyoshi Nakada - Date: 2019-12-23 08:42:53 +0900 - - Fix typo in commit logs by log-fix notes - -commit 4de2297d74fbc0a0e69ac8bcc2aad5b192fd11b6 - Author: Takashi Kokubun - Date: 2019-12-23 09:07:07 +0900 - - Re-apply f85e8d2a8b keeping characters < 80 - -commit f156f70b3192ddab41e432e743936a09a5aaae09 - Author: Yusuke Endoh - Date: 2019-12-23 09:02:49 +0900 - - Revert "Fixed misspellings" - - This reverts commit f85e8d2a8b2a37740334db4fd92ef820f05ddbc5. - - It violated the limit of width (> 80) and caused the test failure - -commit f85e8d2a8b2a37740334db4fd92ef820f05ddbc5 - Author: Nobuyoshi Nakada - Date: 2019-12-23 08:31:46 +0900 - - Fixed misspellings - - Fixed misspellings reported at [Bug #16437] - -commit a4b99f97642d31fc8ddd537155ff6cf61be6a43c - Author: zverok - Date: 2019-12-23 05:56:44 +0900 - - Fix typos of previous docs PR - - In #2612 I made two typos (extra ,, and copy-pasted - same line of code instead of showing two different - ones), fixing them. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2771 - -commit c1bd1bf27236b33965dd92c1b2297edc91327cfb - Author: zverok - Date: 2019-12-14 01:59:23 +0900 - - Document Module#const_source_location - - Notes: - Merged: https://github.com/ruby/ruby/pull/2750 - -commit ade6543f4cf7dfb1ab4585a1bfca20f3d64d5add - Author: Alan Wu - Date: 2019-12-23 08:21:13 +0900 - - Adjust sentence in doc [ci skip] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2773 - - Merged-By: XrXr - -commit bb05cdcd78b3e3d54f0ad9afc01de383ed33dc1c - Author: Marcus Stollsteimer - Date: 2019-12-23 06:36:14 +0900 - - [DOC] Improve documentation for Enumerable#tally - -commit 7c37f2cb1ad248a1db327f3522a8e3ffa5c5412f - Author: Marcus Stollsteimer - Date: 2019-12-23 03:46:24 +0900 - - Some fixes in Enumerator::Lazy docs - - * fix list in #flat_map - * fix wrong indentation in #filter_map and #with_index - * other small fixes - -commit 679bc4f9cb6a5471df903436c6240ca2157986dd - Author: Nobuyoshi Nakada - Date: 2019-09-08 21:04:46 +0900 - - [ruby/reline] Use IO#raw to read one byte - - https://github.com/ruby/reline/commit/be17740e82 - -commit 3a18e43caac4ce31702c9b79de3b6e8af05ef173 - Author: git - Date: 2019-12-23 00:17:25 +0900 - - * 2019-12-23 [ci skip] - -commit 1bf8d5e9797f6304b2e27cb7f42d467f84de0ff4 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-23 00:16:51 +0900 - - Changed behavior on windows platforms too [ci skip] - - at 61aff0cd189e67fa6f2565639ad0128fa33b88fc [Bug #15267] - -commit d339de9d1a11923cd6d435d995ee479d08791720 - Author: zverok - Date: 2019-12-22 06:05:45 +0900 - - Enhance docs for Module#deprecate_constant - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit 5a0102cb615f27f2daef8af6d9ae996926b2d167 - Author: zverok - Date: 2019-12-22 05:58:14 +0900 - - Enhance Range docs - - * Change === docs to mention it uses cover? - * Add different example to === docs to showcase - behavior better - * Change include? docs to mention cover? - and clarify the difference - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit 4988843188c7a1666b11e1390acd7b991941c3a8 - Author: zverok - Date: 2019-12-22 05:37:35 +0900 - - Actualize Time#inspect docs - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit 5fa9c2eeb04a2e44a2a028d933bc95f219a6a282 - Author: zverok - Date: 2019-12-22 05:31:30 +0900 - - Actualize Method#inspect docs - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit d78fcfb7ab351fd4861e42985db34e9bda3509a7 - Author: zverok - Date: 2019-12-22 05:21:20 +0900 - - Fix FrozenError#receiver and #initialize docs - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit e568bb5649a93c60aaa51c1e5308054079815bcc - Author: zverok - Date: 2019-12-22 05:17:35 +0900 - - Update private visibility explanation - - Notes: - Merged: https://github.com/ruby/ruby/pull/2768 - -commit 03b983d54c17615e36d56d2937a685fc8c3f2cdb - Author: zverok - Date: 2019-12-21 05:51:22 +0900 - - Document numbered block parameters - - Notes: - Merged: https://github.com/ruby/ruby/pull/2767 - -commit 890c834ec6bb03fab4fee6f5b14f99660a64d207 - Author: BurdetteLamar - Date: 2019-12-17 07:58:53 +0900 - - Enhancements for ENV doc - - Notes: - Merged: https://github.com/ruby/ruby/pull/2757 - -commit 54be15f3256fd2dbb0d5d7962e9dfac2b87c797b - Author: QuestionDriven - Date: 2019-12-17 16:11:02 +0900 - - [Doc] Fix sample in Encoding#names - - Notes: - Merged: https://github.com/ruby/ruby/pull/2760 - -commit 9654241d5d5717b7cd6ddedb6c192e971f9d473a - Author: QuestionDriven - Date: 2019-12-17 16:05:17 +0900 - - [Doc] Fix wrong example in Encoding.aliases - - Notes: - Merged: https://github.com/ruby/ruby/pull/2760 - -commit cc87037f1c5a143af8089555e704505fcf0b2879 - Author: Nobuyoshi Nakada - Date: 2019-12-22 22:49:17 +0900 - - Fixed misspellings - - Fixed misspellings reported at [Bug #16437], missed and a new - typo. - -commit 7c33ee5ddfafe737add2a7f4c4975108f9196dbd - Author: Benoit Daloze - Date: 2019-12-22 19:39:22 +0900 - - Move version guard outside to make it clear the method was added in Ruby 2.5 - -commit d76c8cfecdaa2960153b5b24ccd0d61f9af60abd - Author: Nobuyoshi Nakada - Date: 2019-12-22 15:18:22 +0900 - - RDoc of Warning.[] and .[]= [Feature #16345] [ci skip] - -commit d2ac6d4d9f57b34eeb94bd6302b54a632051ce64 - Author: Nobuyoshi Nakada - Date: 2019-12-22 14:45:42 +0900 - - Manage deprecation warning by the flag - -commit 58527a79263c6572bd4f97d0a0e0359c0ace6f3c - Author: Nobuyoshi Nakada - Date: 2019-12-22 13:52:59 +0900 - - [ruby/io-console] bump up to 0.5.3 - -commit ced4c5dace63dcb5aabe4d9c480e02e7581b8816 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-22 11:40:07 +0900 - - add NEWS about cache improvement [ci skip] - -commit efd4a11ada731ce18f5eb1500c76f77b4d0f313f - Author: Nobuyoshi Nakada - Date: 2019-12-22 11:46:09 +0900 - - Support multibyte input - -commit cf59e1476d01be27dc88cbee5f6c6cf87f007043 - Author: Koichi Sasada - Date: 2019-12-22 06:28:13 +0900 - - fix a thread test. - - * Use Queue for synchronization. - * Don't use `sleep 0.2` and use `th.join` because created thread - can raise an exception after 0.2 seconds. - -commit fa1bf8ab37caad5fa0679adc0ecb8f6f5cec2eea - Author: Yusuke Endoh - Date: 2019-12-19 23:13:21 +0900 - - [ruby/reline] Support Ctrl+right as em_next_word, and Ctrl+left as ed_prev_word - - https://github.com/ruby/reline/commit/e98ad3b486 - -commit 644336eef54c8ee2aeb7fd6c55fcd5620bcfa5b4 - Author: Koichi Sasada - Date: 2019-12-22 05:20:08 +0900 - - add a NEWS entry for [Feature #16163] - -commit 75acbd5f0076970d48bc423c2b058adbdb5da9e8 - Author: Yusuke Endoh - Date: 2019-12-22 03:31:27 +0900 - - compile.c: avoid newarraykwsplat for arguments - - `foo(*rest, post, **empty_kw)` is compiled like - `foo(*rest + [post, **empty_kw])`, and `**empty_kw` is removed by - "newarraykwsplat" instruction. - However, the method call still has a flag of KW_SPLAT, so "post" is - considered as a keyword hash, which caused a segfault. - Note that the flag cannot be removed if "empty_kw" is not always empty. - - This change fixes the issue by compiling arguments with "newarray" - instead of "newarraykwsplat". - - [Bug #16442] - -commit 3a29f05ba5ba7ed4b821ba5f566eeb3ff3c5c3b1 - Author: NARUSE, Yui - Date: 2019-12-22 01:39:17 +0900 - - Move stats under a dict - -commit 61aff0cd189e67fa6f2565639ad0128fa33b88fc - Author: NAKAMURA Usaku - Date: 2019-12-22 02:36:55 +0900 - - Should return "." for File.extname("file.") also on Windows - - But not changes another cases, such as "file.rb." - [Bug #15267] - -commit 29ea228efc5af08a0e91fafe155617f20e22976b - Author: git - Date: 2019-12-22 01:58:02 +0900 - - * 2019-12-22 [ci skip] - -commit 0835a971ef84dfebefbc73ddd468450cbfb90974 - Author: aycabta - Date: 2019-12-18 22:57:25 +0900 - - Remove TODO comment - -commit 616f1357c3030fad73c42ea061a7f21b0df57fb5 - Author: Yusuke Endoh - Date: 2019-12-14 16:14:43 +0900 - - [ruby/irb] Make nesting level up for `1.times do` - - Follow up of the previous commit - - https://github.com/ruby/irb/commit/ab207353d3 - -commit a3cc2a2fbde23637fb924f75e977599b7a475118 - Author: Yusuke Endoh - Date: 2019-12-14 16:07:21 +0900 - - [ruby/irb] Fix auto-indent for `1.times do` - - Fixes #47 - - https://github.com/ruby/irb/commit/6b8eca4635 - -commit ec1de789a98923417cf983cb3cdaed003c0f8be6 - Author: Yusuke Endoh - Date: 2019-12-14 15:46:42 +0900 - - [ruby/reline] Preserve the input buffer across cursor_pos - - The old version of cursor_pos discards the input buffer, which made IRB - ignore the input immediately after IRB is invoked. - - This change keeps the input before cursor_pos by using ungetc. - - https://github.com/ruby/reline/commit/4a8cca331f - -commit 7fd6077d9896cc10244fb9416ef87ae461c079db - Author: Nobuyoshi Nakada - Date: 2019-12-14 11:01:49 +0900 - - [ruby/reline] Consider Reline::ANSI.input at prep - - https://github.com/ruby/reline/commit/b111cde3c3 - -commit 85a337f986fe6da99c7f8358f790f17b122b3903 - Author: Alan Wu - Date: 2019-07-14 01:04:01 +0900 - - Kernel#lambda: return forwarded block as non-lambda proc - - Before this commit, Kernel#lambda can't tell the difference between a - directly passed literal block and one passed with an ampersand. - - A block passed with an ampersand is semantically speaking already a - non-lambda proc. When Kernel#lambda receives a non-lambda proc, it - should simply return it. - - Implementation wise, when the VM calls a method with a literal block, it - places the code for the block on the calling control frame and passes a - pointer (block handler) to the callee. Before this commit, the VM - forwards block arguments by simply forwarding the block handler, which - leaves the slot for block code unused when a control frame forwards its - block argument. I use the vacant space to indicate that a frame has - forwarded its block argument and inspect that in Kernel#lambda to detect - forwarded blocks. - - This is a very ad-hoc solution and relies *heavily* on the way block - passing works in the VM. However, it's the most self-contained solution - I have. - - [Bug #15620] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2289 - -commit ddb6023d64a8c96348b4e67603753e2916a04f28 - Author: Alan Wu - Date: 2019-07-15 13:35:30 +0900 - - Add spec for capturing Kernel#lambda with Kernel#method - - Notes: - Merged: https://github.com/ruby/ruby/pull/2289 - -commit e0b336c8ce84e1456fc6126ca232289667db3e19 - Author: Alan Wu - Date: 2019-07-15 12:41:43 +0900 - - Add specs for calling into Kernel#lambda with super - - Notes: - Merged: https://github.com/ruby/ruby/pull/2289 - -commit ea405ee8ed00c03e0521ff4b852d8f3bea849243 - Author: Yusuke Endoh - Date: 2019-12-21 10:06:14 +0900 - - test/ruby/test_pattern_matching.rb: suppress "unused variable" warning - -commit 9eded02446e34d4db1051f5f18c2d7d554e792d3 - Author: Jeremy Evans - Date: 2019-12-21 03:47:56 +0900 - - Add Array#minmax, Range#minmax, and Proc#ruby2_keywords to NEWS - -commit 63ce77929ab0ebe992e91a1bad436a5d8e6488a9 - Author: git - Date: 2019-12-21 00:07:13 +0900 - - * 2019-12-21 [ci skip] - -commit 484c1be8956b7bb7a0253c6d6c7a740c341487fa - Author: Nobuyoshi Nakada - Date: 2019-12-20 23:51:17 +0900 - - Added `-W:experimental` command line option - - [Feature #16420] - -commit 07e595fdbd75ed44473073cdf8cd758572d11709 - Author: Nobuyoshi Nakada - Date: 2019-12-20 23:48:15 +0900 - - Added `experimental` warning category - - [Feature #16420] - -commit dd7f0c87c9da8e695c38a6529deb6e0f24f6d06c - Author: Nobuyoshi Nakada - Date: 2019-12-20 23:36:19 +0900 - - Hoisted out new_case3 - -commit a84ad24386d27269b90794146c2a351c1d79471b - Author: Nobuyoshi Nakada - Date: 2019-12-20 23:05:22 +0900 - - Added -W: command line option - - To manage `Warning[category]` flags. Only `-W:deprecated` and - `-W:no-deprecated` are available now. [Feature #16345] - -commit 6876aa38f607cdd6fb24910e54143d9110d025c9 - Author: Nobuyoshi Nakada - Date: 2019-12-20 22:50:46 +0900 - - Added `FEATURE_SET_RESTORE` macro - -commit 1fea3a7636cfaf25baba1e9f208c68a8a8ba52cc - Author: Yusuke Endoh - Date: 2019-12-20 21:37:46 +0900 - - NEWS: Update the explanation of pattern matching - - Add an example of " in ", an example of - NoMatchingPatternError, and mention that the slides are slightly - obsolete. - -commit f7aee584987e24768670e96b1455ed1193f91ef2 - Author: Yusuke Endoh - Date: 2019-12-20 19:41:15 +0900 - - vm_args.c: rephrase the warning message of keyword argument separation - - (old) - test.rb:4: warning: The last argument is used as the keyword parameter - test.rb:1: warning: for `foo' defined here; maybe ** should be added to the call? - - (new) - test.rb:4: warning: The last argument is used as keyword parameters; maybe ** should be added to the call - test.rb:1: warning: The called method `foo' is defined here - -commit 2b2030f265e4ec0782de9c8dd9f8828a1a0af1b5 - Author: Nobuyoshi Nakada - Date: 2019-12-20 15:05:10 +0900 - - Refined the warning message for $, and $; - - [Bug #16438] - -commit 7a94225e7d04f17ddd37433c3904b04fec97f281 - Author: Nobuyoshi Nakada - Date: 2019-12-20 14:54:44 +0900 - - Refined the warning message for numbered-parameter like variables - - [Bug #16438] - -commit a8bddb3a189545a2bef8ee7cffdb328d8de7974c - Author: Nobuyoshi Nakada - Date: 2019-12-20 14:29:42 +0900 - - Refined the warning message for numbered-parameter like variables - - [Bug #16438] - -commit 435a4ca2a38f3be1f5d2db0f71487a52c8285e9c - Author: Nobuyoshi Nakada - Date: 2019-12-20 14:14:07 +0900 - - Makes the receiver to FrozenError.new a keyword parameter - - [Feature #16419] - -commit 216b62aa87f069c51085e9f9abb548930370bc53 - Author: NARUSE, Yui - Date: 2019-12-20 14:10:37 +0900 - - use UTC to use previous day in midnight - -commit e68999c82c4863d33a6f893661fba1b7538c5671 - Author: Nobuyoshi Nakada - Date: 2019-12-20 12:19:45 +0900 - - Fixed misspellings - - Fixed misspellings reported at [Bug #16437], for default gems. - -commit e672494cd737b8fea3a186aeb5c2c17d1a18cb96 - Author: Hiroshi SHIBATA - Date: 2019-12-20 11:50:32 +0900 - - Merge RubyGems 3.1.2 - -commit fac60be324260cd834478fedf934e59b97935dbf - Author: Nobuyoshi Nakada - Date: 2019-12-20 09:39:50 +0900 - - shell.rb is no longer bundled [ci skip] - -commit db166290088fb7d39d01f68b9860253893d4f1a7 - Author: Nobuyoshi Nakada - Date: 2019-12-20 09:19:39 +0900 - - Fixed misspellings - - Fixed misspellings reported at [Bug #16437], only in ruby and rubyspec. - -commit 2898367b3a1de00ca78067cc17dd4d1f8df37778 - Author: Nobuyoshi Nakada - Date: 2019-12-20 08:18:19 +0900 - - Warn also numbered parameter like methods - -commit 3816cd945d68eac7ca8fecbc9d71f878ff3e7b3d - Author: Kazuhiro NISHIYAMA - Date: 2019-12-20 01:40:00 +0900 - - Add `URI#open` to warning message - -commit 844f1fada6f364dc26bd6eb6de2c4299a69e272a - Author: git - Date: 2019-12-20 01:37:11 +0900 - - * 2019-12-20 [ci skip] - -commit 27ddb6e99848c397a415b785315896ab50308076 - Author: Nobuyoshi Nakada - Date: 2019-12-20 01:01:17 +0900 - - Warn also numbered parameter like parameters - - [Feature #16433] - -commit c6c67254fb17b3196a7b0d3fda4650f6b20a467d - Author: Nobuyoshi Nakada - Date: 2019-12-17 17:17:07 +0900 - - Added rb_warn_deprecated - -commit 7aa8a786740fd84bd718b0c055f190b25a8f0277 - Author: Nobuyoshi Nakada - Date: 2019-12-17 17:16:12 +0900 - - Manage deprecation warnings about keyword argument - -commit 9bf9de3d9d2f67bc401151fb94abf75b5eff5913 - Author: Nobuyoshi Nakada - Date: 2019-12-17 14:52:15 +0900 - - Made the warning for deprecated constants follow the category flag - -commit 76035e5bb6a5b44621fd1c11a0553780474d1c01 - Author: Nobuyoshi Nakada - Date: 2019-12-16 18:19:01 +0900 - - Adjusted the format - -commit e732e0074e53e7ddbaf863197ec3775d7e9d4516 - Author: git - Date: 2019-12-19 02:08:51 +0900 - - * 2019-12-19 [ci skip] - -commit 1e88f6eb95672cae2b0628895a9ee9a5d384e048 - Author: Aaron Patterson - Date: 2019-12-18 10:26:11 +0900 - - Refactor free page insertion - - I am trying to fix this error: - - http://ci.rvm.jp/results/trunk-gc_compact@silicon-docker/2491596 - - Somehow we have a page in the `free_pages` list that is full. This - commit refactors the code so that any time we add a page to the - `free_pages` list, we do it via `heap_add_freepage`. That function then - asserts that the free slots on that page are not 0. - -commit efbc0d499c0dc5b74698418c76e58098c6c113e1 - Author: Hiroshi SHIBATA - Date: 2019-12-18 14:53:19 +0900 - - Merge bundler-2.1.1 from bundler/bundler - -commit fa7fa5c86b0674eca233922045e4d3dd4ee49cb7 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-18 13:03:54 +0900 - - delete rb_vm_call() - - Nobody uses it any longer. - -commit dcb603bbdbe3a8ea6f6d07198c8711cf9a44a4d2 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-18 12:57:46 +0900 - - describe mc_miss_reuse_call [ci skip] - -commit fcd8bafd086a7105b535ec1691f960e37d5c911b - Author: Nobuyoshi Nakada - Date: 2019-12-18 13:35:58 +0900 - - Use a temporary file for chown test - - Errno::EROFS may occur when the source tree is placed in a - read-only filesystem. - -commit c147eeff7c2b8d4b8864c8be6496abf7f622a983 - Author: Nobuyoshi Nakada - Date: 2019-12-18 13:29:55 +0900 - - [ruby/io-console] Skip Interrupt test on Linux - - Hangs up only in ruby/ruby on Travis-CI. - - https://github.com/ruby/io-console/commit/de39aa6dd6 - -commit f054f11a38f66af17a0aed8e0d2d46731eaab27d - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-17 15:49:41 +0900 - - per-method serial number - - Methods and their definitions can be allocated/deallocated on-the-fly. - One pathological situation is when a method is deallocated then another - one is allocated immediately after that. Address of those old/new method - entries/definitions can be the same then, depending on underlying - malloc/free implementation. - - So pointer comparison is insufficient. We have to check the contents. - To do so we introduce def->method_serial, which is an integer unique to - that specific method definition. - - PS: Note that method_serial being uintptr_t rather than rb_serial_t is - intentional. This is because rb_serial_t can be bigger than a pointer - on a 32bit system (rb_serial_t is at least 64bit). In order to preserve - old packing of struct rb_call_cache, rb_serial_t is inappropriate. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2759 - -commit 77e3078ede833e86a1ee0e2ce745b15e892bdbf6 - Author: Nobuyoshi Nakada - Date: 2019-12-18 10:25:18 +0900 - - [ruby/io-console] Set raw mode strictly same as cfmakeraw - - * Default VMIN and VTIME to minimum input. - * Disable parity check bits explicitly. - * Disable all bits for flow control on input. - - Co-Authored-By: NARUSE, Yui - - https://github.com/ruby/io-console/commit/5ce201a686 - -commit 254477248cde5bf82c4f256dca05b13d01c9774c - Author: John Hawthorn - Date: 2019-12-13 08:47:59 +0900 - - Skip optimized method check for most method IDs - - Previously every time a method was defined on a module, we would - recursively walk all subclasses to see if the module was included in a - class which the VM optimizes for (such as Integer#+). - - For most method definitions we can tell immediately that this won't be - the case based on the method's name. To do this we just keep a hash with - method IDs of optimized methods and if our new method isn't in that list - we don't need to check subclasses at all. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2752 - -commit 9245462499e7c3216a468aadccdc11e69de8cd54 - Author: John Hawthorn - Date: 2019-12-13 15:43:00 +0900 - - Replace debug test with assertion - - It's a Ruby bug if this ever happens check it as an assertion instead of - paying the cost of the check every time. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2752 - -commit a01d22b8c16d9bd44767cced8d45398493af0a7c - Author: John Hawthorn - Date: 2019-12-12 08:47:49 +0900 - - Check type with BUILTIN_TYPE in method cache clear - - We know that this is a heap-allocated object (a CLASS, MODULE, or - ICLASS) so we don't need to check if it is an immediate value. This - should be very slightly faster. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2752 - -commit 8e56d3a6ab7cc05be586010acd9f85384d53403a - Author: John Hawthorn - Date: 2019-12-13 09:42:34 +0900 - - Define PREV_CLASS_SERIAL - - Avoids generating a "throwaway" sentinel class serial. There wasn't any - read harm in doing so (we're at no risk of exhaustion and there'd be no - measurable performance impact), but if feels cleaner that all class - serials actually end up assigned and used (especially now that we won't - overwrite them in a single method definition). - - Notes: - Merged: https://github.com/ruby/ruby/pull/2752 - -commit d7a50a5cc694ab28608a9d5a2e39c2766330ffe6 - Author: John Hawthorn - Date: 2019-12-12 06:10:39 +0900 - - Avoid revisiting seen nodes clearing method cache - - rb_clear_method_cache_by_class calls rb_class_clear_method_cache - recursively on subclasses, where it will bump the class serial and clear - some other data (callable_m_tbl, and some mjit data). - - Previously this could end up taking a long time to clear all the classes - if the module was included a few levels deep and especially if there - were multiple paths to it in the dependency tree (ie. a class includes - two modules which both include the same other module) as we end up - revisiting class/iclass/module objects multiple times. - - This commit avoids revisiting the same object, by short circuiting when - revisit the same object. We can check this efficiently by comparing the - class serial of each object we visit with the next class serial at the - start. We know that any objects with a higher class serial have already - been visited. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2752 - -commit 8a40dce0ff2964df22e06ae9a08f50592d17caf0 - Author: git - Date: 2019-12-18 00:08:43 +0900 - - * 2019-12-18 [ci skip] - -commit bcec03af05649a8132f5e4e49c2c64762e60b605 - Author: Nobuyoshi Nakada - Date: 2019-12-18 00:08:21 +0900 - - Revert "Skip interruptible raw mode test on Travis-CI" - - This reverts commit 65731a1330ed02691e3c343d2feeb8d0a72af3fd. - -commit 07ed8f2f916a512b35bc69b49f1c482a2ea6e9dd - Author: Nobuyoshi Nakada - Date: 2019-12-17 23:26:07 +0900 - - [ruby/io-console] Skip interrupt - - https://github.com/ruby/io-console/commit/8ed5a2bcc3 - -commit 905a926ea84e199478e32e6da5cd0e8d756132f1 - Author: Nobuyoshi Nakada - Date: 2019-12-17 18:20:37 +0900 - - [ruby/io-console] Timeout in the child process - - https://github.com/ruby/io-console/commit/b8411689a5 - -commit 4b7d27ca0de5e1294fa2072d948953ef49753fc5 - Author: Nobuyoshi Nakada - Date: 2019-12-17 17:24:21 +0900 - - [ruby/io-console] Use IO.console instead of STDIN - - https://github.com/ruby/io-console/commit/9e3ec5b936 - -commit 1b86309b04709ce0a64a9206ca638eccda9d4fec - Author: Nobuyoshi Nakada - Date: 2019-12-17 23:38:18 +0900 - - Squelch filter-branch warning and sleeping - -commit ffa7ceceaf7d9f0268db9021eb0df6f197dcb3c8 - Author: mihaibuzgau - Date: 2019-12-17 19:47:15 +0900 - - [rubygems/rubygems] Move `require uri` to source_list - - https://github.com/rubygems/rubygems/commit/c6b4df5bfc - -commit 299db379575da122bc20745811fc1e20ba01f3ce - Author: Kazuhiro NISHIYAMA - Date: 2019-12-17 09:46:45 +0900 - - Use while instead of loop - - Notes: - Merged: https://github.com/ruby/ruby/pull/2758 - -commit 9d3ffcfbfc742ed5053b59678dbf97773a7dddc1 - Author: Koichi Sasada - Date: 2019-12-17 20:22:00 +0900 - - disable assertion. - - This assertion is not needed because we found the bug. - ba11a74745. - -commit 65731a1330ed02691e3c343d2feeb8d0a72af3fd - Author: Nobuyoshi Nakada - Date: 2019-12-17 17:18:42 +0900 - - Skip interruptible raw mode test on Travis-CI - -commit b226a68141bd60db4b14264cb579e3eab9b6bcbd - Author: mihaibuzgau - Date: 2019-12-16 21:42:34 +0900 - - [rubygems/rubygems] require `uri` in source.rb - - https://github.com/rubygems/rubygems/commit/8de4d0272e - -commit ea717d1ce1199bbd2e6532f1607bab6e1a1f9274 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-17 13:22:24 +0900 - - convert macros into inline functions - - For better readability. - -commit d616926af916d140f0bd1be3cdc232193d46286a - Author: aycabta - Date: 2019-12-17 14:20:51 +0900 - - Remove an unnecessary variable - -commit 8f52604b478fee5243080116b8e62f0c1f5cb9a0 - Author: Masataka Pocke Kuwabara - Date: 2019-12-09 00:48:13 +0900 - - Remove unnecessary double bangs from Pathname#root? - - Notes: - Merged: https://github.com/ruby/ruby/pull/2732 - -commit 9421c7804191b73aa9fde8f14235b3a1f37ffd4b - Author: Nobuyoshi Nakada - Date: 2019-12-16 12:33:13 +0900 - - [ruby/logger] Fixed leaked tempfile - - https://github.com/ruby/logger/commit/fb3eff153f - -commit 4f9a4c1a8f6a31def5fdf58582f064cf644a5828 - Author: aycabta - Date: 2019-12-17 13:47:06 +0900 - - Remove unnecessary branches - -commit e36319249b1a9967a83e66df2661769c136594ad - Author: Nobuyoshi Nakada - Date: 2019-12-17 13:57:58 +0900 - - [ruby/io-console] bump up to 0.5.2 - -commit b39d5da97426c6f65e2b39b307ce19d774d93ddd - Author: Yusuke Endoh - Date: 2019-12-14 19:15:02 +0900 - - [ruby/io-console] Use TCSANOW to prevent from discarding the input buffer - - TCSAFLUSH discards the buffer read before the mode change, which makes - IRB ignore the buffer input immediately after invoked. TCSANOW - preserves the buffer. - - https://github.com/ruby/io-console/commit/b362920182 - -commit 81eb2d16efcb29899e88e30a25ca5440195e2393 - Author: Nobuyoshi Nakada - Date: 2019-12-13 11:41:31 +0900 - - [ruby/io-console] Disable implementation-defined special control characters - - In raw mode with interrupt enabled. - - https://github.com/ruby/io-console/commit/e9e8e3ff17 - -commit ec89a0f8033215817d9c6f9300d9513178e785b7 - Author: Nobuyoshi Nakada - Date: 2019-12-13 12:14:10 +0900 - - [ruby/io-console] Added the test for intr option - - https://github.com/ruby/io-console/commit/4f01db102d - -commit a9d17af242748c160cb79909fd881e06141fe428 - Author: Nobuyoshi Nakada - Date: 2019-12-10 10:07:00 +0900 - - [ruby/io-console] Removed dead code - - https://github.com/ruby/io-console/commit/a49462ed97 - -commit 64ce658ec5a6d6fc6eb969f607e703fd9372287a - Author: aycabta - Date: 2019-12-17 13:30:54 +0900 - - Fix return condition according to the condition to skip - -commit a1713bedb1de676fdd7d9bf3458b931c4702a1af - Author: Thomas Leitner - Date: 2019-10-04 17:03:32 +0900 - - [ruby/reline] Implement completion_append_character - - There is already the possibility to set Reline.completion_append_character. - However, it is not used by the line editor. - - https://github.com/ruby/reline/commit/ab798931b9 - -commit 11db4d3a3b315ed2495ec0cdde4449554c002bff - Author: Nobuyoshi Nakada - Date: 2019-12-14 11:05:16 +0900 - - [ruby/reline] Disable any implementation-defined special control characters - - Including dsusp, lnext, and so on. - - https://github.com/ruby/reline/commit/a44abe586b - -commit fbe229906b6e55c2e7bb1e68452d5c225503b9ca - Author: Koichi Sasada - Date: 2019-12-17 13:14:52 +0900 - - add debug counter to count `call` reusing cases. - -commit 618d09115185efa05f6948247d86087f4aa96118 - Author: aycabta - Date: 2019-12-17 13:10:39 +0900 - - Support change search direction - -commit a14a0244b48c422e392547b198af6fb57f7ca568 - Author: aycabta - Date: 2019-12-17 12:47:09 +0900 - - Support forward-search-history by C-s - -commit c687be4bc01c9ce52ea990945d9304d6fe59fe9b - Author: Nobuyoshi Nakada - Date: 2019-12-17 11:53:30 +0900 - - Added a test for [Bug #16159] - -commit ebe5b66ca8e639468e14c4134a415403d949385e - Author: Nobuyoshi Nakada - Date: 2019-12-17 10:48:17 +0900 - - Reduce tzset calls - - Set up-to-date flag always when calling tzset(). - -commit d6a2bce64a7fa1099e507e1d36b5f1533f42f60f - Author: Yusuke Endoh - Date: 2019-12-17 10:31:20 +0900 - - time.c (find_time_t): fix round-to-zero bug - - `find_time_t` did not work correctly for year older than the Epoch - because it used C's integer division (which rounds negative to zero). - - For example, `TIme.new(1933)` returned a wrong time whose year is 1922 - in Asia/Kuala_Lumpur because there is no 00:00:00 1st Jan. 1933 in the - time zone. - - ``` - $ TZ=Asia/Kuala_Lumpur ruby -e 'p Time.new(1933)' - 1932-12-31 00:00:00 +0700 - ``` - - This change fixes the issue by using `DIV` macro instead of `/`. - Now `Time.new(1933)` returns a time in 1933. - - ``` - $ TZ=Asia/Kuala_Lumpur ruby -e 'p Time.new(1933)' - 1933-01-01 00:20:00 +0720 - ``` - - [Bug #16159] - -commit 5da4a310ccf7f4131c1814a2c9279a5682777f1b - Author: NARUSE, Yui - Date: 2019-12-17 00:49:17 +0900 - - close datasocket on stor of server side - -commit 5be34d6a3310065850c0c530db6936415124b5d9 - Author: NARUSE, Yui - Date: 2019-12-10 19:25:00 +0900 - - ensure to close the data connection [Bug #16413] - -commit 95213f6df6a23918d57a743975708c638da42aae - Author: aycabta - Date: 2019-12-15 10:29:44 +0900 - - Check whether Readline.completion_append_character= exists - -commit b12bc3b0461f7331db6e27865fa7a8ef29a0f652 - Author: Eric Wong - Date: 2019-12-17 03:28:44 +0900 - - thread.c: avoid needless read after select|ppoll - - We do not need to issue pipe|eventfd read(2) syscall - unless select, ppoll|poll declares the FD needs reading. - -commit bba6386d9568123a7c76693e3a5fa5e33562a640 - Author: Yusuke Endoh - Date: 2019-12-17 00:44:32 +0900 - - test/ruby/test_process.rb: suppress "unused variable" warning - -commit c6b1342d29a71e44c0275516d4f8408ce07bf397 - Author: git - Date: 2019-12-17 00:01:56 +0900 - - * 2019-12-17 [ci skip] - -commit 6a75a460536a32fb62184dc5d8d66ddd737a9bad - Author: Richard Viney - Date: 2017-01-22 10:50:08 +0900 - - Make prettyprint’s cycle detection aware of Delegator instances - - Fixes [Bug #13144] - - Co-Authored-By: Nobuyoshi Nakada - -commit 251f5d8226dbde06ba06e980e3b741b45ae3826d - Author: Yusuke Endoh - Date: 2019-12-16 23:39:10 +0900 - - Revert "lib/net/http/response.rb: support raw deflate correctly" - - This reverts commit 5105240b1e851410020b3b3f1a2bead7ffdd4291. - - In RFC 2616: - - ``` - deflate - The "zlib" format defined in RFC 1950 [31] in combination with - the "deflate" compression mechanism described in RFC 1951 [29]. - ``` - - So "Content-Encoding: deflate" means zlib format, not raw deflate. - - [Bug #11268] - -commit 5105240b1e851410020b3b3f1a2bead7ffdd4291 - Author: Yusuke Endoh - Date: 2019-12-16 23:20:42 +0900 - - lib/net/http/response.rb: support raw deflate correctly - - Net::HTTP had used `Zlib::Inflate.new(32 + Zlib::MAX_WBITS)` for all - content encoding (deflate, zlib, and gzip). - But the argument `32 + Zlib::MAX_WBITS` means zlib and gzip decoding - with automatic header detection, so (raw) deflate compression had not - been supported. - - This change makes it support raw deflate correctly by passing an - argument `-Zlib::MAX_WBITS` (which means raw deflate) to - `Zlib::Inflate.new`. All deflate-mode tests are fixed too. - - [Bug #11268] - -commit d6fd39030d8b14eef117c1e5e265e0b769a9f4fd - Author: BurdetteLamar - Date: 2019-12-14 04:46:54 +0900 - - Enhancements for ENV doc - - Notes: - Merged: https://github.com/ruby/ruby/pull/2751 - -commit d8db343a21b175563fa58a7d33c600ae7c7973cc - Author: Hiroshi SHIBATA - Date: 2019-12-16 20:47:02 +0900 - - Merge RubyGems 3.1.1 and update the NEWS entry for RubyGems - -commit ba11a74745e10fac88a74c2da2e0032ccf254265 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-16 17:38:41 +0900 - - ensure cc->def == cc->me->def - - The equation shall hold for every call cache. However prior to this - changeset cc->me could be updated without also updating cc->def. Let's - make it sure by introducing new macro named CC_SET_ME which sets cc->me - and cc->def at once. - -commit 6545d5bbb9517a9364bd59a12a98d3e00516e07e - Author: Kazuhiro NISHIYAMA - Date: 2019-12-16 16:59:23 +0900 - - Use CDN instead of raw.githubusercontent.com - -commit 8b921813aa8d5ea8f4e6c1e700ad48a120c500ab - Author: Kazuhiro NISHIYAMA - Date: 2019-12-16 16:58:21 +0900 - - Fix open without close [ci skip] - -commit 04e95f8985066b4ae1e97b045efda98bdefa07bd - Author: Nobuyoshi Nakada - Date: 2019-12-16 11:19:59 +0900 - - Get rid of infinite recursion at loading transcoder - - Disable encoding US-ASCII path to filesystem on Windows too. - [Bug #16392] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2755 - -commit d2f04d332f2ff04f25202ed38e23de526a9aea46 - Author: Nobuyoshi Nakada - Date: 2019-12-16 09:44:01 +0900 - - Kernel#abort without arguments should print error info - - [Bug #16424] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2754 - -commit 1e80a208cc44cbbdd4e49d6146eea29cde5cd42a - Author: Hiroshi SHIBATA - Date: 2019-12-16 10:09:13 +0900 - - Update the NEWS entry for Bundler 2.1.0 - -commit 2344d8ac9aefae6258b1967014d17564cf2d2e43 - Author: git - Date: 2019-12-16 10:05:44 +0900 - - * 2019-12-16 [ci skip] - -commit f47c38245ff6976c5d1fc27a79f239bba00fc333 - Author: Breno Leitao - Date: 2019-12-16 10:05:21 +0900 - - gc.h: Add SET_MACHINE_STACK_END specific for Powerpc64 (#1767) - - Currently we are not able to grab the correct end/top of the stack on - powerpc64 due to the fact that it uses the fallback function. - - The fallback function does not return the correct top of the stack - because it adds a new frame and the returned top of the stack contains - this frame overhead that could be something around 112 bytes on - Powerpc64. - - This patch simply gets the correct top of the stack pointer, which is - always on r1 register according to both ABI v1 and ABI v2 (Little - endian). - - Signed-off-by: Breno Leitao - -commit e8c62836a6292bf2f691de458b24ea50c51b452a - Author: Nobuyoshi Nakada - Date: 2019-12-15 23:13:16 +0900 - - IO#set_encoding_by_bom should err when encoding is already set - - Except for ASCII-8BIT. [Bug #16422] - -commit eeb99fb52500b571b1239442a7d17d335cfde060 - Author: Yusuke Endoh - Date: 2019-12-15 22:19:45 +0900 - - tool/gen-mailmap.rb: odaira is removed as he is added in upstream - - https://github.com/ruby/ruby-commit-hook/commit/ddc83bea6fe6f4696e140b605db10ef0c922bba6 - -commit 48bab6fe1eb77b481bffbc97fdbf5ba74c45a07a - Author: Yusuke Endoh - Date: 2019-12-15 21:59:30 +0900 - - tool/gen-mailmap.rb: Added for generating git `.mailmap` file - - `.mailmap` can be used To show canonical names and email addresses. - It is helpful for statistics of committers. - -commit a83c46e3fd1e3480404c6dda4c4cda73533a6a1d - Author: Kazuhiro NISHIYAMA - Date: 2019-12-15 20:03:47 +0900 - - Add more debug info - - closed server doesn't have useful info. - So call inspect before close. - And add local debug code in comment. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20191215T092405Z.fail.html.gz - ``` - 1) Failure: - IMAPTest#test_connection_closed_without_greeting [/export/home/rubyci/chkbuild-tmp/tmp/build/20191215T092405Z/ruby/test/net/imap/test_imap.rb:483]: - [Net::IMAP::Error] exception expected, not ##, :server=>#, :port=>41748, :server_addr=>"::1"}>. - ``` - -commit 980ddca47e892535c1da897b33ac7bc727efd52d - Author: Hiroshi SHIBATA - Date: 2019-12-15 16:48:40 +0900 - - Prepare to release rubygems-3.1.0 - -commit 9f43160014905db159ec67e3ee2b485d870de05d - Author: David Rodríguez - Date: 2019-12-14 22:15:43 +0900 - - Delegate should be supported now - - Since `did_you_mean` dropped its dependency on it. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2753 - -commit 286cb3395f8be493b21d0bdf13bcf40fe5c3ab50 - Author: Hiroshi SHIBATA - Date: 2019-12-14 21:19:28 +0900 - - Fixed test failures with gem command path on ruby core repo. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2753 - -commit 0fab9005387549d5c5b13cf330012d02e5312bc2 - Author: David Rodríguez - Date: 2019-12-14 04:41:13 +0900 - - Vendor thor 1.0.0 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2753 - -commit 38002a8adbd98266426940d829429a30af0622a4 - Author: Hiroshi SHIBATA - Date: 2019-12-14 19:49:16 +0900 - - Prepare to release bundler-2.1.0 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2753 - -commit e2b192f7d5b4f0e2133bb6cf03cfc609258826be - Author: Kazuhiro NISHIYAMA - Date: 2019-12-15 14:47:36 +0900 - - rand(beginless_range) raise Errno::EDOM instead of TypeError - - same as `rand(endless_range)` - - Before: - ``` - $ ruby -e 'rand(..1)' - Traceback (most recent call last): - 2: from -e:1:in `
' - 1: from -e:1:in `rand' - -e:1:in `-': nil can't be coerced into Integer (TypeError) - ``` - - After: - ``` - $ ruby -e 'rand(..1)' - Traceback (most recent call last): - 1: from -e:1:in `
' - -e:1:in `rand': Numerical argument out of domain (Errno::EDOM) - ``` - -commit db2ea9b0c5fb49a04af1b299a37e92f81d7cccd2 - Author: Nobuyoshi Nakada - Date: 2019-12-15 00:21:19 +0900 - - [DOC] Fixed the class name in FrozenError#receiver - -commit 38b9d213f1fc474549d7ca6858ed4f1d1436d1ee - Author: Nobuyoshi Nakada - Date: 2019-12-15 00:18:09 +0900 - - Revert "[DOC] Fixed the class name in FrozenError#receiver" - - This reverts commit 5f56a5fc9be9ea7b088795c2d3871c2352a020c2. - `FrozenError.new(mesg, nil).receiver` should not raise an - ArgumentError. - -commit 52b1ba0b0242dc8b10b24df716ec439cd4b2bd88 - Author: git - Date: 2019-12-15 00:15:23 +0900 - - * 2019-12-15 [ci skip] - -commit 5f56a5fc9be9ea7b088795c2d3871c2352a020c2 - Author: Nobuyoshi Nakada - Date: 2019-12-14 23:57:44 +0900 - - [DOC] Fixed the class name in FrozenError#receiver - -commit 33f0ef44fde7b042d15056cea9af49d160268537 - Author: Nobuyoshi Nakada - Date: 2019-12-14 23:56:28 +0900 - - [DOC] Fixed the FrozenError.new result [ci skip] - -commit 9e0256836370d6294114320f1b5fa9b3b16b8ae2 - Author: Benoit Daloze - Date: 2019-12-14 20:26:30 +0900 - - Improve highlighting in RubyVM::AbstractSyntaxTree docs when using `ri` - -commit b4b22b9278007b106fe40c0191f8dcf5e7e8c0f2 - Author: Benoit Daloze - Date: 2019-12-14 20:16:58 +0900 - - Clarify in the documentation that RubyVM::AbstractSyntaxTree is not stable API - - * See [Feature #14844]. - -commit 4cc83f9ac60d18ba330dc7f8e92eae1ffce67322 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-14 16:05:49 +0900 - - [Feature #13083] is already reverted - -commit 90cdcefa78ee9f3c7c78db2c5f3df0fdba25d83f - Author: Kazuhiro NISHIYAMA - Date: 2019-12-14 16:05:15 +0900 - - Update warnings in NEWS - -commit e2708068ad65f7f9986adf4fb3a4fa660f430a5a - Author: Yuki Nishijima - Date: 2019-12-14 11:39:58 +0900 - - Drop delegate dependency - - Original comment: - https://github.com/ruby/did_you_mean/commit/2f26c9ee770f28da0942c42cbc9e5800535b75e1 - -commit f3240eb67dc4c807f6489a8a5ccb6eeec239efe5 - Author: Marcus Stollsteimer - Date: 2019-12-14 06:07:59 +0900 - - NEWS: fix pattern matching example - -commit 835703c69f2b1b770b1e3c8c9dd73aca4ed734e6 - Author: git - Date: 2019-12-14 00:40:25 +0900 - - * 2019-12-14 [ci skip] - -commit 84b873e381c6928965e36d0a83c899a01b65e646 - Author: Nobuyoshi Nakada - Date: 2019-12-13 14:35:11 +0900 - - [ruby/irb] Restore environment variables - - https://github.com/ruby/irb/commit/236590882c - -commit ab1f3d63b0b08fcb8e90557a0d8d72e624221557 - Author: Hiroshi SHIBATA - Date: 2019-12-13 22:10:28 +0900 - - Fixed a typo - -commit 2ef5f012c1d1dcef18d3c4c56d0d07fc72362be7 - Author: Hiroshi SHIBATA - Date: 2019-12-13 22:00:28 +0900 - - Added explicitly loading `Gem::Command` class - -commit eb512c5a9530322280991441954b0405cadeebf1 - Author: Nobuyoshi Nakada - Date: 2019-12-13 21:38:50 +0900 - - warn should be a global function - -commit a2e87123499f6eef9c03089f61f174dd4b3cc673 - Author: Nobuyoshi Nakada - Date: 2019-12-13 20:51:58 +0900 - - Fix visibility as module_function - -commit 6183addf6a4b94db7fe5b9187ac66fa11c8d2825 - Author: Nobuyoshi Nakada - Date: 2019-11-12 18:34:49 +0900 - - Add `Warning.[]` and `Warning.[]=` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2739 - -commit f3b1b645edfc5a8c938da74a5ed44564b9e2fc08 - Author: Nobuyoshi Nakada - Date: 2019-12-10 20:54:01 +0900 - - Create backtrace location array directly - - Notes: - Merged: https://github.com/ruby/ruby/pull/2739 - -commit 0b5268afbcf11c299e11102c366e836ae55cc39f - Author: Nobuyoshi Nakada - Date: 2019-12-10 20:22:42 +0900 - - Moved Kernel#warn to warning.rb - - Notes: - Merged: https://github.com/ruby/ruby/pull/2739 - -commit 82cc2843a92b286cc13afd0860a4e111d4ea2a0b - Author: Hiroshi SHIBATA - Date: 2019-12-13 20:19:08 +0900 - - Prepare to release RubyGems 3.1.0 final version. - -commit 26774351dc5f494253ba031e4bc453dc4dddb2cf - Author: Kazuhiro NISHIYAMA - Date: 2019-12-13 18:06:36 +0900 - - Ignore error of `apt-get update` in MJIT workflow too - -commit d5c73681f8fd9e17b5378cb029fc88e98d7b6abb - Author: Kazuhiro NISHIYAMA - Date: 2019-12-13 18:04:21 +0900 - - Ignore error of `apt-get update` on GitHub Actions - -commit 97a17a51b8e6eca31fd6421511f1907e6e95b415 - Author: Koichi Sasada - Date: 2019-12-13 17:26:12 +0900 - - readable function names for inline functions. - - Now, C functions written by __builtin_cexpr!(code) and others are - named as "__builtin_inline#{n}". However, it is difficult to know - what the function is. This patch rename them into - "__builtin_foo_#{lineno}" when cexpr! is in 'foo' method. - -commit 1140625cd31f7ad74c42dc625b9dab389b12653c - Author: Matt Valentine-House - Date: 2019-12-12 22:37:31 +0900 - - Allow more than one major version number in target_os - -commit c2dfc6d869979124a46fb0c5404956891c27575f - Author: aycabta - Date: 2019-12-13 03:57:32 +0900 - - Show a menu before a document - - IRB should show a menu first if a completed list has plural items. But just - shows document without menu if a completed list with plural items includes a - perfect matched item. The behavior is a bug. This commit fixes it. - -commit b8d6c883b3f49e6339da4fa5111dbdbe7d3c6df5 - Author: Nobuyoshi Nakada - Date: 2019-12-13 08:52:07 +0900 - - Improved the test for Thread#inspect [Feature #16412] - -commit fa5f7a8f7ef0d03b8ac97d25a0460c0dc6bb33f3 - Author: git - Date: 2019-12-13 00:05:20 +0900 - - * 2019-12-13 [ci skip] - -commit 69b6f8fd047c5c9e0fa6f65656fda762f8ecfc5e - Author: aycabta - Date: 2019-12-13 00:04:01 +0900 - - Check whether TestReadline is defined - -commit 93b27c69cc65b5019df061bb8fefaa097bf8a33d - Author: Nobuyoshi Nakada - Date: 2019-12-12 23:26:29 +0900 - - Show the failed message too - -commit 68321dd1fa6f55e578bc9776f906ee1f948c7095 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-12 22:04:07 +0900 - - Move `rescue` for debug into block of assert_raise - -commit dd60856f8ddaa0652bf019589f05705e00279b8c - Author: Nobuyoshi Nakada - Date: 2019-12-12 20:53:59 +0900 - - [cygwin] fix File.absolute_path? test - - Paths start with the root are absolute on cygwin, regardless the - drive letter. - -commit b6f25318c5a1efca0ab963b49ae69db82787e783 - Author: Nobuyoshi Nakada - Date: 2019-12-12 20:50:01 +0900 - - Cygwin path cannot be mapped to a UNC as-is - -commit c20dd2f75491fc6e78dab55b492c507ee3bb670d - Author: Kazuhiro NISHIYAMA - Date: 2019-12-12 17:38:27 +0900 - - Add more debug info when Errno::EINVAL - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20191212T072406Z.fail.html.gz - -commit 54e089df9e37d438687effd092feda2442116c62 - Author: Koichi Sasada - Date: 2019-12-12 17:02:36 +0900 - - show self on control frame dump. - - control frame detailed info on RUBY_DEBUG=ci should also show - self information. - -commit 55b7ba368696033f2e89b77cbcd4a05dec97b139 - Author: Jeremy Evans - Date: 2019-08-22 05:59:36 +0900 - - Make super in instance_eval in method in module raise TypeError - - This makes behavior the same as super in instance_eval in method - in class. The reason this wasn't implemented before is that - there is a check to determine if the self in the current context - is of the expected class, and a module itself can be included - in multiple classes, so it doesn't have an expected class. - - Implementing this requires giving iclasses knowledge of which - class created them, so that super call in the module method - knows the expected class for super calls. This reference - is called includer, and should only be set for iclasses. - - Note that the approach Ruby uses in this check is not robust. If - you instance_eval another object of the same class and call super, - instead of an TypeError, you get super called with the - instance_eval receiver instead of the method receiver. Truly - fixing super would require keeping a reference to the super object - (method receiver) in each frame where scope has changed, and using - that instead of current self when calling super. - - Fixes [Bug #11636] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2717 - -commit 1a4a9bdb5da973f8a89e699ce6d0fb1ca21090bd - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-12 13:59:52 +0900 - - proper initialization of struct RVALUE - - This changeset makes no difference unless GC_DEBUG is on. When that flag is - set, struct RVALUE is bigger than struct RObject. We have to take care of the - additional fields. Otherwise we get a SIGSEGV like shown below. - - The way obj is initialized in this patch works for both GC_DEBUG is on and off. - See also ISO/IEC 9899:1999 section 6.7.8 paragraph #21. - - ``` - Program received signal SIGSEGV, Segmentation fault. - __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62 - 62 ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory - (gdb) bt - #0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62 - #1 0x00005555557dd9a7 in BSD_vfprintf (fp=0x7fffffff6be0, fmt0=0x5555558f3059 "@%s:%d", ap=0x7fffffff6dd0) at vsnprintf.c:1027 - #2 0x00005555557db6f5 in ruby_do_vsnprintf (str=0x555555bfc58d "", n=211, fmt=0x5555558f3059 "@%s:%d", ap=0x7fffffff6dd0) at sprintf.c:1022 - #3 0x00005555557db909 in ruby_snprintf (str=0x555555bfc58d "", n=211, fmt=0x5555558f3059 "@%s:%d") at sprintf.c:1040 - #4 0x0000555555661ef4 in rb_raw_obj_info (buff=0x555555bfc560 "0x0000555555d2bfa0 [0 ] T_STRING (String)", buff_size=256, obj=93825000456096) at gc.c:11449 - #5 0x000055555565baaf in obj_info (obj=93825000456096) at gc.c:11612 - #6 0x000055555565bae1 in rgengc_remembered (objspace=0x555555c0a1c0, obj=93825000456096) at gc.c:6618 - #7 0x0000555555666987 in newobj_init (klass=93824999964192, flags=5, v1=0, v2=0, v3=0, wb_protected=1, objspace=0x555555c0a1c0, obj=93825000456096) at gc.c:2134 - #8 0x0000555555666e49 in newobj_slowpath (klass=93824999964192, flags=5, v1=0, v2=0, v3=0, objspace=0x555555c0a1c0, wb_protected=1) at gc.c:2209 - #9 0x0000555555666b94 in newobj_slowpath_wb_protected (klass=93824999964192, flags=5, v1=0, v2=0, v3=0, objspace=0x555555c0a1c0) at gc.c:2220 - #10 0x000055555565751b in newobj_of (klass=93824999964192, flags=5, v1=0, v2=0, v3=0, wb_protected=1) at gc.c:2256 - #11 0x00005555556575ca in rb_wb_protected_newobj_of (klass=93824999964192, flags=5) at gc.c:2272 - #12 0x00005555557f36ea in str_alloc (klass=93824999964192) at string.c:728 - #13 0x00005555557f2128 in rb_str_buf_new (capa=0) at string.c:1317 - #14 0x000055555578c66d in rb_reg_preprocess (p=0x555555cc8148 "^-(.)(.+)?", end=0x555555cc8152 "", enc=0x555555cc7c80, fixed_enc=0x7fffffff74e8, err=0x7fffffff75f0 "") at re.c:2682 - #15 0x000055555578ea13 in rb_reg_initialize (obj=93825000046736, s=0x555555cc8148 "^-(.)(.+)?", len=10, enc=0x555555cc7c80, options=0, err=0x7fffffff75f0 "", sourcefile=0x555555d1a5c0 "lib/optparse.rb", sourceline=1460) at re.c:2808 - #16 0x000055555578e285 in rb_reg_initialize_str (obj=93825000046736, str=93825000046904, options=0, err=0x7fffffff75f0 "", sourcefile=0x555555d1a5c0 "lib/optparse.rb", sourceline=1460) at re.c:2869 - #17 0x000055555578ee02 in rb_reg_compile (str=93825000046904, options=0, sourcefile=0x555555d1a5c0 "lib/optparse.rb", sourceline=1460) at re.c:2958 - #18 0x0000555555748dfb in rb_parser_reg_compile (p=0x555555d1f760, str=93825000046904, options=0) at parse.y:12157 - #19 0x00005555557581c3 in parser_reg_compile (p=0x555555d1f760, str=93825000046904, options=0) at parse.y:12151 - #20 0x00005555557580ac in reg_compile (p=0x555555d1f760, str=93825000046904, options=0) at parse.y:12167 - #21 0x0000555555746ebb in new_regexp (p=0x555555d1f760, node=0x555555dece68, options=0, loc=0x7fffffff89e8) at parse.y:10072 - #22 0x000055555573d1f5 in ruby_yyparse (p=0x555555d1f760) at parse.y:4395 - #23 0x000055555574a582 in yycompile0 (arg=93825000404832) at parse.y:5945 - #24 0x00005555558c6898 in rb_suppress_tracing (func=0x55555574a470 , arg=93825000404832) at vm_trace.c:427 - #25 0x0000555555748290 in yycompile (vparser=93824999283456, p=0x555555d1f760, fname=93824999283624, line=1) at parse.y:5994 - #26 0x00005555557481ae in rb_parser_compile_file_path (vparser=93824999283456, fname=93824999283624, file=93824999283400, start=1) at parse.y:6098 - #27 0x00005555557cdd35 in load_file_internal (argp_v=140737488331760) at ruby.c:2023 - #28 0x00005555556438c5 in rb_ensure (b_proc=0x5555557cd610 , data1=140737488331760, e_proc=0x5555557cddd0 , data2=140737488331760) at eval.c:1128 - #29 0x00005555557cb68b in load_file (parser=93824999283456, fname=93824999283624, f=93824999283400, script=0, opt=0x7fffffffa468) at ruby.c:2142 - #30 0x00005555557cb339 in rb_parser_load_file (parser=93824999283456, fname_v=93824999283624) at ruby.c:2164 - #31 0x00005555556ba3e1 in load_iseq_eval (ec=0x555555c0a650, fname=93824999283624) at load.c:579 - #32 0x00005555556b857a in require_internal (ec=0x555555c0a650, fname=93824999284352, exception=1) at load.c:1016 - #33 0x00005555556b7967 in rb_require_string (fname=93824999284464) at load.c:1105 - #34 0x00005555556b7939 in rb_f_require (obj=93824999994824, fname=93824999284464) at load.c:811 - #35 0x00005555558b7ae0 in call_cfunc_1 (recv=93824999994824, argc=1, argv=0x7ffff7ecd0a8, func=0x5555556b7920 ) at vm_insnhelper.c:2348 - #36 0x00005555558a8889 in vm_call_cfunc_with_frame (ec=0x555555c0a650, reg_cfp=0x7ffff7fccfa0, calling=0x7fffffffaab0, cd=0x555555d76a10, empty_kw_splat=0) at vm_insnhelper.c:2513 - #37 0x000055555589fb5c in vm_call_cfunc (ec=0x555555c0a650, reg_cfp=0x7ffff7fccfa0, calling=0x7fffffffaab0, cd=0x555555d76a10) at vm_insnhelper.c:2538 - #38 0x000055555589f22e in vm_call_method_each_type (ec=0x555555c0a650, cfp=0x7ffff7fccfa0, calling=0x7fffffffaab0, cd=0x555555d76a10) at vm_insnhelper.c:2924 - #39 0x000055555589ef47 in vm_call_method (ec=0x555555c0a650, cfp=0x7ffff7fccfa0, calling=0x7fffffffaab0, cd=0x555555d76a10) at vm_insnhelper.c:3038 - #40 0x0000555555866dbd in vm_call_general (ec=0x555555c0a650, reg_cfp=0x7ffff7fccfa0, calling=0x7fffffffaab0, cd=0x555555d76a10) at vm_insnhelper.c:3075 - #41 0x00005555558ae557 in vm_sendish (ec=0x555555c0a650, reg_cfp=0x7ffff7fccfa0, cd=0x555555d76a10, block_handler=0, method_explorer=0x5555558ae5d0 ) at vm_insnhelper.c:4021 - #42 0x000055555587745b in vm_exec_core (ec=0x555555c0a650, initial=0) at insns.def:801 - #43 0x0000555555899b9c in rb_vm_exec (ec=0x555555c0a650, mjit_enable_p=1) at vm.c:1907 - #44 0x000055555589aaf0 in rb_iseq_eval_main (iseq=0x555555c1da80) at vm.c:2166 - #45 0x0000555555641f0b in rb_ec_exec_node (ec=0x555555c0a650, n=0x555555c1da80) at eval.c:277 - #46 0x0000555555641d62 in ruby_run_node (n=0x555555c1da80) at eval.c:335 - #47 0x000055555557a188 in main (argc=11, argv=0x7fffffffc848) at main.c:50 - (gdb) fr 7 - #7 0x0000555555666987 in newobj_init (klass=93824999964192, flags=5, v1=0, v2=0, v3=0, wb_protected=1, objspace=0x555555c0a1c0, obj=93825000456096) at gc.c:2134 - 2134 if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj)); - (gdb) p ((struct RVALUE*)obj)->file - $1 = 0x65a5992b0fb25ce7 - (gdb) - ``` - -commit 35eb12c06397e770392a41343cbffc4b204e15c9 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-12 12:39:24 +0900 - - add casts - - %p is for void *. Because fprintf is a function with variadic arguments - automatic cast from any pointer to void * does not work. We have to be - explicit. - -commit f40143fe7c55e3b2209f57e7ec4b3ad1d9468a1e - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-12 12:37:58 +0900 - - fix arity mismatch - - I missed this in bc3e7924bc66d3ef77b219c72f3e59cc154550a3 because the - function is inside of a #ifdef. - -commit 12de92a3682f7a54941c511e6394068df2adefb3 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-12 11:11:39 +0900 - - implement make test-all TESTS=--gc-compact - - 79eb5e1acac2339c6ec71db723298bdfcd92b233 implemented - RUBY_TEST_GC_COMPACT=1 so why not make it also possible via the command - line argument. - -commit 53e8589c69d1345235d9f02ecbcf6aa32fa9d39c - Author: Hiroshi SHIBATA - Date: 2019-12-12 09:14:09 +0900 - - Import json-2.3.0 from flori/json - -commit 7d991a0571ab33f44c00fdc227f076d1eaf5fb2b - Author: aycabta - Date: 2019-12-12 08:40:44 +0900 - - Suppress to crash IRB if completed list has nil - -commit 50ae8895f32f5fc620f0a0f288dae62815cb2a6f - Author: Rei Odaira - Date: 2019-12-12 04:31:38 +0900 - - debug_counter.c: include ruby/config.h before stdio.h - to define _LARGE_FILES - -commit 27ac034f196967f54edf00474880886624d30245 - Author: Koichi Sasada - Date: 2019-12-12 04:26:03 +0900 - - support gc_compact_checker on parallel test. - -commit 7dbbba38a0a6acd41a43eb0c4fc416fe35e2345a - Author: Aaron Patterson - Date: 2019-10-12 09:13:02 +0900 - - Make sure we don't push MOVED or NONE on the stack - -commit 79eb5e1acac2339c6ec71db723298bdfcd92b233 - Author: Koichi Sasada - Date: 2019-12-12 03:31:13 +0900 - - call GC.compact after each test. - - RUBY_TEST_GC_COMPACT=1 enables GC.compact checker which calls - GC.compact after each test. - -commit 51cc5a26df5f47ecdd88398ba1a50a8e62182649 - Author: aycabta - Date: 2019-12-12 03:18:44 +0900 - - Some tests failed with before GNU Readline 6.0 on Windows - -commit fe4502336680270d886b502e4b35ecb3de2f2164 - Author: git - Date: 2019-12-12 03:13:32 +0900 - - * 2019-12-12 [ci skip] - -commit 0f90630983db3257c544c698761a00456af81d85 - Author: Aaron Patterson - Date: 2019-12-12 03:12:14 +0900 - - Update method tables only if there is a class ext pointer - - This makes reference updating look similar to marking, and may avoid - dereferencing a wrong pointer. - -commit cae657c32492a9b4e72b5e290c143e2c84d4c42d - Author: Yusuke Endoh - Date: 2019-12-11 21:54:18 +0900 - - Fix .travis.yml to keep s390x-linux as allow_features - - [Misc #16360] - -commit 47a365dd580f2dfe0f0d56155587dfdf2fc7afb7 - Author: Yusuke Endoh - Date: 2019-12-11 20:44:39 +0900 - - Move s390x-linux to allow_failures matrix - - ref [Misc #16360] - -commit 49ffae7ca66f3e0bc3e2d87092197d3514d5925e - Author: Jeremy Evans - Date: 2019-12-02 12:59:07 +0900 - - [ruby/forwardable] Bump version to 1.3.1 - - https://github.com/ruby/forwardable/commit/aa07c55f3f - -commit 0dcd3340fb5f91112ce66c53315eff92b9f10fb7 - Author: Jeremy Evans - Date: 2019-12-02 12:57:06 +0900 - - [ruby/forwardable] Make def_*_delegator return name of method defined (Fixes #10) - - This restores compatibility with previous versions. This behavior - was previously undefined, but it makes sense for the name of the - defined method to be returned. - - https://github.com/ruby/forwardable/commit/a52ef3451e - -commit c2f6aa4e4810f8f2aabc35bf4c98ee030ff504b9 - Author: aycabta - Date: 2019-12-11 19:39:37 +0900 - - The result of Readline.completion_proc should have the same encoding of Encoding.default_external - -commit 3098798044ada5a81862aa4668aaf7548f9b1c99 - Author: Nobuyoshi Nakada - Date: 2019-12-11 16:41:37 +0900 - - Test `Thread#to_s` when used from to_s_spec.rb - -commit d2d42081ce76954ff55392a6e07e3eb4f26c696c - Author: Nobuyoshi Nakada - Date: 2019-12-11 16:19:49 +0900 - - `Thread#to_s` has been added at ruby 2.5 - -commit eb9c0070535bc088ab2921613830ba983bfe07a1 - Author: Koichi Sasada - Date: 2019-12-11 16:48:19 +0900 - - skip continuous failure test. - - On mingw this test fails and not solved long time, so skip it. - Please revert it when it solved. - - https://ci.appveyor.com/project/ruby/ruby/builds/29458671/job/9nbcjnfe6p0xnxoe - -commit 1269157a6e46895c0eda2ea202d44790bbe815c8 - Author: Koichi Sasada - Date: 2019-12-11 16:10:26 +0900 - - Thread#to_s is not same as #inspect on old version. - - Thread#to_s returns simple Object#to_s until Ruby 2.4. - -commit 7f5014e6e884d7fa091e3e6462827b910417267c - Author: Koichi Sasada - Date: 2019-12-11 15:45:23 +0900 - - rely on sorted compiled binary array. - - `builtin_binary` is sorted by miniruby loading order and this - loading order should be same on ruby. So we can believe sorted - order of `builtin_binary` on boot time. - -commit 0afee4d80355dd03f0dfefe6120e2e1808d9cb50 - Author: Nobuyoshi Nakada - Date: 2019-12-11 14:27:21 +0900 - - Show the failed message - -commit 7fa821a80d60992f019c98ac813e2fc6e9775031 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-11 14:01:23 +0900 - - Try to use `set-output` - - because commit info are not necessary in env. - -commit 6025783a3b0b37517728c635250669449bb21a53 - Author: Koichi Sasada - Date: 2019-12-11 14:00:32 +0900 - - fix for old MRI versions - -commit fe8caf0ab93e69b743470d16f6cf7416fe9c98da - Author: Koichi Sasada - Date: 2019-12-11 13:37:00 +0900 - - add dependency pointed by update-deps - -commit 35adc47e7eb1640d35e4d294af7e9651d918608d - Author: Kazuhiro NISHIYAMA - Date: 2019-12-11 13:08:21 +0900 - - Create dummy files when check only - - because foo.rb in build directory breaks test-bundler - https://github.com/ruby/ruby/runs/343168046#step:20:125 - -commit cf948a3d3f37c4a786611f5b48c9c020f6020161 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-10 23:01:23 +0900 - - Do not load q.rb in build directory - - Notes: - Merged: https://github.com/ruby/ruby/pull/2736 - -commit 4f5dc15b049eacb9070e2c941183fed68c41f81e - Author: Kazuhiro NISHIYAMA - Date: 2019-12-10 21:44:34 +0900 - - Create more dummy files in build directory - - Notes: - Merged: https://github.com/ruby/ruby/pull/2736 - -commit 1ed0212bcf76ec244ca5b75c65f09e5b04158377 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-10 18:31:01 +0900 - - Do not load files in build directory - - related https://bugs.ruby-lang.org/issues/16177 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2736 - -commit 85e43e1dfecef69b935c48c235cc20f21bd4f0d4 - Author: Jeremy Evans - Date: 2019-12-11 06:38:12 +0900 - - Fix Enumerator::Lazy#with_index - - * Make it correctly handle lambdas - * Make it iterate over the block if block is given - - The original implementation was flawed, based on lazy_set_method - instead of lazy_add_method. - - Note that there is no implicit map when passing a block, the return - value of the block passed to with_index is ignored, just as it - is for Enumerator#with_index. Also like Enumerator#with_index, - when called with a block, the return value is an enumerator without - the index. - - Fixes [Bug #16414] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2742 - -commit 8a80bfcfd4d510a20a62e21d8d2f4119cb823d4f - Author: Jean byroot Boussier - Date: 2019-12-10 19:49:39 +0900 - - Make Thread#to_s consistent with Method and Proc to_s - - Notes: - Merged: https://github.com/ruby/ruby/pull/2738 - -commit 6a7af800dbd45946caaadfc4a1212fc523afe58b - Author: aycabta - Date: 2019-12-11 11:36:21 +0900 - - Add a message for CompatibilityError - -commit 7e9b1609dae0998a4418179f40dc488842c56e5d - Author: Eli Sadoff <9064062+snood1205@users.noreply.github.com> - Date: 2019-12-11 11:25:54 +0900 - - Added documentation for integer range sums (#1593) - -commit 86e2c013d7ade7c93077d599e155aae0f3b632e8 - Author: git - Date: 2019-12-11 11:25:00 +0900 - - * remove trailing spaces. [ci skip] - -commit bbbf451bffbc5605b53726c5977d96bffc10d162 - Author: Koichi Sasada - Date: 2019-12-11 11:22:27 +0900 - - Update tool/mk_builtin_binary.rb - - Co-Authored-By: Sutou Kouhei - - Notes: - Merged: https://github.com/ruby/ruby/pull/2735 - -commit 40026a408df5e3576380f6c1d8bf6c119fa2e32b - Author: Koichi Sasada - Date: 2019-12-10 17:39:04 +0900 - - support cross-compilation. - - On cross-compilation, compiled binary can no be created because - compiled binary should be created by same interpreter (on cross- - compilation, host ruby is used to build ruby (BASERUBY)). - So that cross-compilation system loads required scripts in text. - It is same as miniruby. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2735 - -commit 9c2807b2df14984e3c81d72a381d9a4d288b3fbe - Author: Koichi Sasada - Date: 2019-12-10 17:13:42 +0900 - - remove prelude.c - - prelude.c is an automatically generated file by template/prelude.c.tmpl. - However it does not contain any required functions. So remove it from - dependency. - - Also miniprelude.c is included by mini_builtin.c and does not need - to make miniprelude.o. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2735 - -commit 2c5c60754cafe9895b7a7421cd0552eaa2ae8b09 - Author: Koichi Sasada - Date: 2019-12-10 16:19:13 +0900 - - use compiled binary for gem_prelude.rb. - - `gem_prelude.rb` is not compiled yet. This patch compile it to - compiled binary. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2735 - -commit 943f3e5fd463bf2a4a3a4e92b5134e238b9c931d - Author: Koichi Sasada - Date: 2019-12-09 16:20:35 +0900 - - add include guard - - Notes: - Merged: https://github.com/ruby/ruby/pull/2735 - -commit 69aa927a40618591082085fe04c010d516dd50d3 - Author: Corey Farwell - Date: 2017-04-18 06:58:51 +0900 - - Indicate `find_all` and `select` methods are aliases. - - This matches the documentation for `Enumerable::inject` and `Enumerable::reduce` which are also aliases. - -commit 0fafb83b3878b11de18de7a2d09927842eaf5fb7 - Author: git - Date: 2019-12-11 11:13:28 +0900 - - * 2019-12-11 [ci skip] - -commit ec54ac938104517dd61887006ef8cc324b3b1b35 - Author: aycabta - Date: 2019-12-11 11:12:54 +0900 - - Support Readline.completion_quote_character by Reline - -commit 8e49ef5a691cc9a249acae8c7335ec53bf445dc3 - Author: Nobuyoshi Nakada - Date: 2019-12-10 23:13:40 +0900 - - [ruby/io-console] update depend for f9c0fe77c0e - -commit 2a2a707829168b898508ae27a0458719a36bd316 - Author: Hiroshi SHIBATA - Date: 2019-12-10 21:21:19 +0900 - - Followed up 38722fa179fcec549300b2f35206f4eb168f202e - -commit 95f570d0d349a7fd86c6425c9c5d7d87cc5ecd46 - Author: Hiroshi SHIBATA - Date: 2019-12-10 20:56:09 +0900 - - [ruby/logger] bump version to 1.4.2 - - https://github.com/ruby/logger/commit/d6c01cc652 - -commit 0b10d46a577bb6b0e8e177f5c3f17f8d61007d6c - Author: Jeremy Evans - Date: 2019-08-21 13:28:14 +0900 - - [ruby/logger] Enable more timezone tests on OpenBSD - - https://github.com/ruby/logger/commit/bcd7e227e8 - -commit 7a1c56f978907d03876772d942619ec90cbbfa6b - Author: Jeremy Evans - Date: 2019-11-18 10:34:56 +0900 - - [ruby/logger] Document that shift_age of 0 disables log file rotation - - Fixes Ruby Bug 16349. - - https://github.com/ruby/logger/commit/b1b6d06f2d - -commit 38722fa179fcec549300b2f35206f4eb168f202e - Author: Jeremy Evans - Date: 2019-10-15 10:08:10 +0900 - - [ruby/logger] Raise ArgumentError for invalid shift_age - - Consider 'now' and 'everytime' as valid values for the previous - behavior of rotating every time. - - Fixes Ruby Bug 15977 - - https://github.com/ruby/logger/commit/f92979a376 - -commit eb18cb3e476db3bc44d489e090e1535237c4c6c9 - Author: George Claghorn - Date: 2019-09-07 07:28:05 +0900 - - [ruby/logger] Honor Logger#level overrides - - https://github.com/ruby/logger/commit/7365c995bf - -commit af11efd377965b6601bb54aa79072ef0789dc525 - Author: NARUSE, Yui - Date: 2019-12-10 19:06:13 +0900 - - fix ipaddr parameter of Net::HTTP.start to support proxy - - 54072e329cab7207fba133caba4fc12b45add8f9 - -commit aedbee52c0e21358c33e775eab41c634905f63c3 - Author: Nobuyoshi Nakada - Date: 2019-12-10 18:49:53 +0900 - - Prefer $(CHDIR) for the case srcdir contains symlinks - -commit 79d2a1b004b06692279bb647e0eee712e55d14c4 - Author: Hiroshi SHIBATA - Date: 2019-12-10 18:41:05 +0900 - - Update regression tests for 1.4.16 - -commit 8299bcd9465b98bd40711bb9c0d4488aba0b72e1 - Author: Yusuke Endoh - Date: 2019-12-10 18:18:04 +0900 - - .indent.pro: Removed because it is no longer used - -commit c596e01a49d8c77b6dacc931a24eb4b7876617b7 - Author: Yusuke Endoh - Date: 2019-12-10 18:05:51 +0900 - - Move SECURITY.md into .github/ to reduce the files on the top directory - -commit fe0df7dcfc92b81d3508473a08584f8372418323 - Author: aycabta - Date: 2019-12-10 17:27:43 +0900 - - Change encoding of completion strings - -commit 60c53ff6ee1eed054fc3d78ad6c06cbfc56900d6 - Author: Yusuke Endoh - Date: 2019-12-10 17:10:23 +0900 - - vm_core.h (iseq_unique_id): prefer uintptr_t instead of unsigned long - - It produced a warning about type cast in LLP64 (i.e., windows). - -commit e27d2013db18d124d1362b6cc81ecec806ef1a0d - Author: Hiroshi SHIBATA - Date: 2019-12-10 17:03:46 +0900 - - Import racc-1.4.1 from ruby/racc. - -commit 43544f8617a81fbaef03d926777df4a5311cdb74 - Author: Hiroshi SHIBATA - Date: 2019-12-10 17:03:13 +0900 - - Added the missing gemspec of racc - -commit 58e5ab78d0a88d9153770a82cff9b553f53dd5d5 - Author: Nobuyoshi Nakada - Date: 2019-12-10 15:26:14 +0900 - - [ruby/io-console] bump up to 0.5.1 - -commit 2419b3dba6d86ea40a148f7547ff87b2074ca582 - Author: Nobuyoshi Nakada - Date: 2019-12-10 10:44:21 +0900 - - [ruby/io-console] Suppress an unused-variable warning - - https://github.com/ruby/io-console/commit/ae5c72e481 - -commit f9c0fe77c0ef6c5da1d8454bf6be6841c984d606 - Author: Nobuyoshi Nakada - Date: 2019-12-10 10:09:33 +0900 - - [ruby/io-console] Use rb_thread_call_without_gvl instead of the deprecated function - - https://github.com/ruby/io-console/commit/21338ab287 - -commit 09723b98f7a8db4ce6d22cd282525275154736fe - Author: Nobuyoshi Nakada - Date: 2019-12-10 10:08:43 +0900 - - [ruby/io-console] Warn vtime option without intr flag - - https://github.com/ruby/io-console/commit/499ff3de48 - -commit 0c2787b9b29d839876ac68afbd6209a8407fcb30 - Author: Nobuyoshi Nakada - Date: 2019-12-10 10:05:25 +0900 - - [ruby/io-console] bump up to 0.5.0 - -commit 1bdabaa6b13344c195698ca5b0ced323cb93e2e1 - Author: Konstantin Papkovskiy - Date: 2017-08-15 23:35:58 +0900 - - base64.rb: improve performance of Base64.urlsafe_encode64 - - * lib/base64.rb: avoid unnecessary memory allocations - -commit 3ca3c8d768f6d81da72df4798736c2e0059d19f9 - Author: Yusuke Endoh - Date: 2019-12-10 14:15:35 +0900 - - lib/net/http.rb: align the indentation - -commit 7be550d046c726c2a3aa625ceb260d9b2268fb5a - Author: Kazuhiro NISHIYAMA - Date: 2019-12-10 12:41:09 +0900 - - Stop Thread.new in `DRb::TimerIdConv::TimerHolder2#on_gc` - - and add more stop_pool after stop_service - -commit 129c3216d966fc25209a7e50418413ffecd25281 - Author: Nobuyoshi Nakada - Date: 2019-12-10 12:11:56 +0900 - - [cygwin] Removed unnecessary packages - - Notes: - Merged: https://github.com/ruby/ruby/pull/2734 - -commit cd35c0954085758ec1fb5a5fcfb7d6d9d5e71a90 - Author: Nobuyoshi Nakada - Date: 2019-12-10 12:11:37 +0900 - - [cygwin] Removed unnecessary `-c` options - - Notes: - Merged: https://github.com/ruby/ruby/pull/2734 - -commit ec931ee9e13b939f6693032564ee9beeec5a4a1f - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-10 11:42:29 +0900 - - forward declare struct timespec - - ... like we do so for struct timeval at several hundreds of lines above. - Depending on OS/Compiler, this can be the first place for the struct to - appear. To make sure the struct is global, we need a forward - declaration at this point. - -commit c50d9dc67d350ad4e21ff1af39635bb5a6114282 - Author: Yusuke Endoh - Date: 2019-12-10 11:26:22 +0900 - - test/ruby/test_keywords.rb: suppress a warning - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu1604/ruby-master/log/20191210T003005Z.log.html.gz - ``` - .../test/ruby/test_keyword.rb:2711: warning: `*' interpreted as argument prefix - ``` - -commit 660388f6c5b148ea6f84d589482391bf78f35c6b - Author: Yusuke Endoh - Date: 2019-12-10 09:41:33 +0900 - - test/net/http/test_https.rb (test_get_SNI_failure): stop proxy settings - - Because the test fails under HTTP proxy settings. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris10-gcc/ruby-master/log/20191210T000004Z.fail.html.gz - ``` - 1) Failure: - TestNetHTTPS#test_get_SNI_failure [/export/home/users/chkbuild/cb-gcc/tmp/build/20191210T000004Z/ruby/test/net/http/test_https.rb:81]: - [OpenSSL::SSL::SSLError] exception expected, not #. - ``` - - The new SNI feature introduced at 54072e329c may need to be improved for - HTTP proxy environment. - -commit 6a22b2a091eda81a473eb1b0cc69fe0792560e27 - Author: aycabta - Date: 2019-12-10 07:01:26 +0900 - - Support completion with case-insensitive fashion - - Reline performs completion in a case-insensitive fashon if - Readline.completion_case_fold or completion-ignore-case of .inputrc are set - "on". - -commit 562fd754b55aaaf794fa8eb5461eb0ee87725464 - Author: git - Date: 2019-12-10 00:10:44 +0900 - - * 2019-12-10 [ci skip] - -commit f45c0dc23980d7fd8167d290ea7c354cf2cdb500 - Author: Jeremy Evans - Date: 2019-12-06 04:01:20 +0900 - - Add Proc#ruby2_keywords - - This allows passing keywords through a normal argument splat in a - Proc. While needing ruby2_keywords support for methods is more - common, there is code that delegates keywords through normal - argument splats in procs, including code in Rails. For that - reason, it makes sense to expose this for procs as well. - - Internally, ruby2_keywords is not tied to methods, but iseqs, - so this just allows for setting the ruby2_keywords for the iseq - related to the proc. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2728 - -commit c2dc27d6435f40ff24f553cf47816a1c696bbbba - Author: NARUSE, Yui - Date: 2019-12-09 20:48:35 +0900 - - fix typo of 54072e329cab7207fba133caba4fc12b45add8f9 - -commit 54072e329cab7207fba133caba4fc12b45add8f9 - Author: NARUSE, Yui - Date: 2019-12-09 20:19:11 +0900 - - Add ipaddr optional parameter to Net::HTTP#start - - to replace the address for TCP/IP connection [Feature #5180] - - There're 3 layers of hostname: - * host address for TCP/IP - * TLS server name - * HTTP Host header value - To test DNS round robin or check server certificate from server local, - people sometimes want to connect server with given IP address but keep - TLS server name and HTTP Host header value. - - closes [Feature #15215] - closes https://github.com/ruby/ruby/pull/1893 - closes https://github.com/ruby/ruby/pull/1977 - -commit 194327942690a7997c7b48d34cc105c6ec8b8d40 - Author: Hiroshi SHIBATA - Date: 2019-12-09 19:16:51 +0900 - - Added workaround for CoreAssertions used by ruby/logger. - -commit 4b36832ba64a8879a4b0702d6d5079ddd9d3078e - Author: Hiroshi SHIBATA - Date: 2019-12-09 19:11:18 +0900 - - Merge the upstream changes for test-unit on ruby/logger. - - This commits are based with: - https://github.com/ruby/logger/commit/f067f7d1aa743b467d633ec6d1790bd93ed9e25b - https://github.com/ruby/logger/commit/86058f420d8f6909500cccceb24f58bef0597b4d - https://github.com/ruby/logger/commit/02db6e8ed85d1f4ba974f08fee292bad400d9fc2 - -commit ff7cc0dc34832a074ce42e383439b87ea63b42f7 - Author: sonots - Date: 2019-08-20 21:10:08 +0900 - - [ruby/logger] 1.4.1 - - https://github.com/ruby/logger/commit/5987f518d1 - -commit 895f86c81b95143ecdcca6a8cd4e9367a33b0aaa - Author: Hiroshi SHIBATA - Date: 2019-08-20 16:39:38 +0900 - - [ruby/logger] Fixes #38 - - https://github.com/ruby/logger/commit/31efbb29ff - -commit 0fe1b0508249bc6d64a67c17307a0037f29add74 - Author: sonots - Date: 2019-08-20 03:02:21 +0900 - - [ruby/logger] 1.4.0 - - https://github.com/ruby/logger/commit/8127ce0b56 - -commit 6158e28f8d02026e21317d8a0c2cb2115b3a0660 - Author: Akira Matsuda - Date: 2019-07-31 14:38:38 +0900 - - [ruby/logger] Avoid creating [] and "" when logging an Exception that has no backtrace - - https://github.com/ruby/logger/commit/75fd308053 - -commit 0aafc32995b935b6c46c8439a3e2da008cd683fc - Author: sonots - Date: 2019-03-22 01:14:14 +0900 - - [ruby/logger] frozen_string_literal: true - - https://github.com/ruby/logger/commit/a057eede7b - -commit 22548195d59d8b5e421c586bec81615a0a1091bc - Author: Alan Wu - Date: 2019-07-15 14:52:06 +0900 - - [ruby/logger] Fix typo - - https://github.com/ruby/logger/commit/5f70168ac5 - -commit 8395a6a9a0696d1a0a6aa6a019a1a919ee2c854f - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 15:05:17 +0900 - - Add badge of Cygwin - - Notes: - Merged: https://github.com/ruby/ruby/pull/2733 - -commit a5e6a50cb8e4acd4feee2ad3a61eac568f2c62b6 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 15:04:59 +0900 - - Add cache of cygwin packages - - Notes: - Merged: https://github.com/ruby/ruby/pull/2733 - -commit ea8f03e86c57ff28154345865a2560b8895f3e68 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 15:03:10 +0900 - - Remove unused branch name - - Notes: - Merged: https://github.com/ruby/ruby/pull/2733 - -commit 801eafcc146808399f9ca53b3f3b730b81235abb - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 14:29:38 +0900 - - Split cygwin-chocolatey cache - - Notes: - Merged: https://github.com/ruby/ruby/pull/2733 - -commit c19e62ddc9d7160d470f76dae823e9546d0a7bf3 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 14:06:06 +0900 - - Remove debug print - - Notes: - Merged: https://github.com/ruby/ruby/pull/2733 - -commit 156fb72d7015b420c57b0bd230693f52d8d75b32 - Author: Yusuke Endoh - Date: 2019-12-09 15:22:48 +0900 - - vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointer - - (This is the second try of 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e.) - - If iseq is GC'ed, the pointer of iseq may be reused, which may hide a - deprecation warning of keyword argument change. - - http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 - - ``` - 1) Failure: - TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: - --- expected - +++ actual - @@ -1 +1 @@ - -/The keyword argument is passed as the last hash parameter.* for `m'/m - +"" - ``` - - This change ad-hocly adds iseq_unique_id for each iseq, and use it - instead of iseq pointer. This covers the case where caller is GC'ed. - Still, the case where callee is GC'ed, is not covered. - - But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it - just hides some warnings. It's no big deal. - -commit 07664f3aec1b80f6ffe3929258c9a246f0bdcc48 - Author: aycabta - Date: 2019-12-09 14:21:05 +0900 - - Remove workaround encoding modification - -commit a14c01441b12552386c69233b0bcc53d06ed0b92 - Author: aycabta - Date: 2019-12-09 14:20:25 +0900 - - Fix encoding compatibility checking of completion correctly - -commit 3cdb37d9db9b7776f6adf96c70eacc39773718b4 - Author: Yusuke Endoh - Date: 2019-12-09 13:49:24 +0900 - - Revert "vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointer" - - This reverts commit 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e. - - This caused a failure on iseq_binary mode. - http://ci.rvm.jp/results/trunk-iseq_binary@silicon-docker/2474587 - - Numbering iseqs is not trivial due to dump/load. - -commit 39c7230a7a7a039639d2cb3587c054554a1beb18 - Author: Yusuke Endoh - Date: 2019-12-09 13:49:17 +0900 - - Revert "vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_id" - - This reverts commit 751a9b32e5a53336768eb878de1827245a3292bf. - -commit 8b07c122b7785fde6b06dd31b09f59a7cbdac2cd - Author: Kazuhiro NISHIYAMA - Date: 2019-12-09 13:46:23 +0900 - - Stop pool threads in test/rinda too - -commit 751a9b32e5a53336768eb878de1827245a3292bf - Author: Yusuke Endoh - Date: 2019-12-09 12:30:00 +0900 - - vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_id - - The function assumed that the LSB of `callee` was 0. - -commit 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e - Author: Yusuke Endoh - Date: 2019-12-09 12:04:58 +0900 - - vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointer - - If iseq is GC'ed, the pointer of iseq may be reused, which may hide a - deprecation warning of keyword argument change. - - http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 - - ``` - 1) Failure: - TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: - --- expected - +++ actual - @@ -1 +1 @@ - -/The keyword argument is passed as the last hash parameter.* for `m'/m - +"" - ``` - - This change ad-hocly adds iseq_unique_id for each iseq, and use it - instead of iseq pointer. This covers the case where caller is GC'ed. - Still, the case where callee is GC'ed, is not covered. - - But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it - just hides some warnings. It's no big deal. - -commit 0e71fbc18e97007ac9a9b242b800f34057f5f287 - Author: git - Date: 2019-12-09 00:13:07 +0900 - - * 2019-12-09 [ci skip] - -commit 963b84a51bf0b80da44ab775d788a911b676a6a9 - Author: Nobuyoshi Nakada - Date: 2019-12-08 23:37:04 +0900 - - Separate steps - - Notes: - Merged: https://github.com/ruby/ruby/pull/2731 - -commit 5e65e65bd935954190a5d481def788524c4ae169 - Author: Nobuyoshi Nakada - Date: 2019-12-08 23:00:46 +0900 - - Set PATH at once - - Notes: - Merged: https://github.com/ruby/ruby/pull/2731 - -commit d00349f99470cfddd522ee1e7fa9a5f6dc126771 - Author: Nobuyoshi Nakada - Date: 2019-12-08 23:09:39 +0900 - - Fixed the checking out source - - Notes: - Merged: https://github.com/ruby/ruby/pull/2731 - -commit 689e74485598d2c023fc2a00fac80b717b6f29b7 - Author: Daisuke Fujimura (fd0) - Date: 2019-12-06 23:53:25 +0900 - - Add .github/workflows/cygwin.yml - - Notes: - Merged: https://github.com/ruby/ruby/pull/2731 - -commit 0d63a2104777e467568a31037a6573e1879870c7 - Author: aycabta - Date: 2019-12-08 18:29:39 +0900 - - Skip completion tests for Editline - -commit c38bc172bee99ff71440a1ebb4c38e6d092e0807 - Author: aycabta - Date: 2019-12-08 08:35:31 +0900 - - Fix encoding of completed list - -commit 2eb674377371d276b9de5ce06a591419f00f7c42 - Author: git - Date: 2019-12-08 08:10:50 +0900 - - * 2019-12-08 [ci skip] - -commit c9b06d4a4e52b6ae705ebb16cafe455671780770 - Author: aycabta - Date: 2019-12-08 08:01:27 +0900 - - Add test_simple_completion for Readline - -commit be13b897ead62debd6d2e7696e5d28a8e8781620 - Author: aycabta - Date: 2019-12-07 22:02:24 +0900 - - Show failed commits only when exists - -commit 0ff84eda4e130ae17abccbb8aa92ad47e83d151d - Author: aycabta - Date: 2019-12-07 20:28:23 +0900 - - [ruby/irb] Version 1.2.0 - - https://github.com/ruby/irb/commit/da6577a88c - -commit 2e595c2d780814cc4d1357c687b44fd7208ff313 - Author: aycabta - Date: 2019-12-07 20:26:01 +0900 - - [ruby/irb] New IRB needs Ruby 2.5 or later - - https://github.com/ruby/irb/commit/4be3158358 - -commit ad6837dd609654b02885199b25f7d79b1122b64a - Author: aycabta - Date: 2019-12-07 20:21:08 +0900 - - [ruby/irb] Revert "Reidline mode needs Reline what needs String#grapheme_clusters" - - This reverts commit 2b0b19b87c60d2cdb329979acbb96e12a1f940e7. - - New IRB parser needs new Ripper what has lex_state too. The new Ripper is - adopted by Ruby 2.5 or later. - - https://github.com/ruby/irb/commit/9ab6e35a2c - -commit c2afddccb36c10ac0eb530bfc3b38765882126d8 - Author: aycabta - Date: 2019-12-07 19:51:03 +0900 - - [ruby/irb] Reidline mode needs Reline what needs String#grapheme_clusters - - https://github.com/ruby/irb/commit/2b0b19b87c - -commit e72ffc55ba3cc9bf20c892d2d090a77f40c49ada - Author: aycabta - Date: 2019-12-07 12:11:55 +0900 - - [ruby/reline] Support Ruby 2.5 or later for String#grapheme_clusters - - https://github.com/ruby/reline/commit/33e8c8f15b - -commit ebbc77836b74a74d7c07a9b91fff886219956e3c - Author: Yusuke Endoh - Date: 2019-12-07 13:15:47 +0900 - - test/ruby/test_file_exhaustive.rb: shorten the name of temporary dir - - ``` - 1) Error: - TestFileExhaustive#test_socket_p: - ArgumentError: too long unix socket path (109bytes given but 108bytes max) - /export/home/users/chkbuild/cb-sunc/tmp/build/20191207T024036Z/ruby/test/ruby/test_file_exhaustive.rb:155:in `initialize' - ``` - -commit dcf89b20d7b79b51e268ea3ffcfdc0829edf7643 - Author: git - Date: 2019-12-07 01:28:20 +0900 - - * 2019-12-07 [ci skip] - -commit 544431e028e9d678f2989c35876a05c53f07e0ec - Author: Namrata Bhave - Date: 2019-12-07 01:27:58 +0900 - - Adding s390x support (#2727) - -commit 2f6a8baac6a84935cef1f10adbba2f47df4a2346 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-06 15:56:14 +0900 - - Test interfaces include localhost - - When interfaces do not include localhost, - some other tests may fail. - -commit 2c8d186c6e4fd03ea57466fa6dce6bad40d09401 - Author: Aaron Patterson - Date: 2019-10-12 09:06:41 +0900 - - Introduce an "Inline IVAR cache" struct - - This commit introduces an "inline ivar cache" struct. The reason we - need this is so compaction can differentiate from an ivar cache and a - regular inline cache. Regular inline caches contain references to - `VALUE` and ivar caches just contain references to the ivar index. With - this new struct we can easily update references for inline caches (but - not inline var caches as they just contain an int) - -commit 38b7f947a2c76aad29a2e42f3bd0848854d96519 - Author: git - Date: 2019-12-06 00:13:22 +0900 - - * 2019-12-06 [ci skip] - -commit 693cba1a136aafb0faa25f93434a2e8dbad320de - Author: Kazuhiro NISHIYAMA - Date: 2019-12-06 00:11:11 +0900 - - Detect started threads when require only - -commit 173b864668777ef157a0c82b6e6f1a6aa0f06ac9 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-05 23:56:14 +0900 - - Do not start thread when `require 'drb/drb'` only - -commit 6477d98e49dbe04deb03caee1a58a34c3b79d4e4 - Author: Yusuke Endoh - Date: 2019-12-05 23:46:42 +0900 - - test/lib/jit_support.rb: Update the regexp for icc - - MJIT_CC is always an absolute path. - -commit d43b9eb22de1b1cd8de09a161cc836413cc158a1 - Author: Yusuke Endoh - Date: 2019-12-05 22:37:08 +0900 - - lib/drb/drb.rb: suppress warning: instance variable @pool_proxy not initialized - -commit f4d9daf2b6f23af08296c7ccb770e1de1bc723bd - Author: Yusuke Endoh - Date: 2019-12-05 22:24:58 +0900 - - coroutine/ucontext/Context.c: define __EXTENSIONS__ explicitly - - instead of ruby/config.h, per samuel's request. - - https://github.com/ruby/ruby/commit/dbfd4b780e3914a3f27e92c2248254452bf0fd6b#diff-7fd78c3cc8a19b7e0637502983ec26ff - -commit c3abbc1b2f52015dc839fd96545380dbc11c77a9 - Author: Nobuyoshi Nakada - Date: 2019-12-05 16:18:22 +0900 - - ext/openssl/extconf.rb: check with -Werror=deprecated-declarations - - This reverts commit 0d7d8b2989e1738dd902d354cc41186899e6b71e, - but restore `$warnflags` without the flag, to get rid of using - deprecated functions. - -commit 4c88107c54b06c1a3e89970eb243c8ac887d84e1 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-05 18:14:31 +0900 - - Fix `warning: already initialized constant DidYouMean::VERSION` - - ``` - .../gems/did_you_mean-1.3.1/lib/did_you_mean/version.rb:2: warning: already initialized constant DidYouMean::VERSION - .../lib/did_you_mean/version.rb:2: warning: previous definition of VERSION was here - ``` - -commit 75b644350a80bc31449b7cee741d309643dc27e1 - Author: Nobuyoshi Nakada - Date: 2019-12-05 17:57:05 +0900 - - ext/psych/extconf.rb: braced VPATH is for nmake only - -commit 0bca34ddaaf15caa852007f401707c1785aa8ed6 - Author: Yusuke Endoh - Date: 2019-12-05 16:55:31 +0900 - - test/io/console/test_io_console.rb: add a memo for the mysterious hack - -commit 264d5aff5afecb08b0a2ccafedc0a43de4f8d16a - Author: aycabta - Date: 2019-12-05 16:28:54 +0900 - - Change encoding of completion list...for more tests - -commit ee579200082329db66e153c465cb8332e55bacb2 - Author: Koichi Sasada - Date: 2019-12-05 15:01:37 +0900 - - move an interrupt point. - - `args_ptr` can be corrupted by interrupt handlers. - Pointed by nagachika . - -commit b40bb27e3594bbc2e9c9ac00dfa5612ebae3151b - Author: Yusuke Endoh - Date: 2019-12-05 15:38:29 +0900 - - test/io/console/test_io_console.rb: Try the hack for Solaris - - I'm not entirely sure why, but test_set_winsize_console gets stuck on - Solaris (and if I recall, macOS). I found a hack for FreeBSD, so I want - to give it a try on Solaris too. - -commit fa1db8f938c083ce1416f999fe8b3cf33f9f18f1 - Author: Takashi Kokubun - Date: 2019-12-05 15:25:11 +0900 - - Add missing dependency - - https://travis-ci.org/ruby/ruby/jobs/620972117 - -commit 72cff5f3af47ec8d694feef97516089e86d89673 - Author: Takashi Kokubun - Date: 2019-12-05 15:18:42 +0900 - - MJIT_CC and MJIT_SUPPORT are not a prefix - - 0b19e15a1239bff9ae854f522f954206ec910cf8 was also for "MJIT_SUPPORT" - too. - -commit 5fbb4555b427909aed4fe2376c4c583849c1d51c - Author: Takashi Kokubun - Date: 2019-12-05 15:16:07 +0900 - - Prefer using MJIT_CC for JIT support check - - because Solaris might have CC=cc and we'd like to check full path - MJIT_CC=/opt/developerstudio12.5/bin/cc instead. - -commit 199bd851e40438380b2e0f57662a212200e3ba1a - Author: Yusuke Endoh - Date: 2019-12-05 14:51:07 +0900 - - parse.y: suppress "set but not used" warnings on ripper.y - -commit edb80dfe3e6086fb9d5d905a40cdd6ec61a2e1ee - Author: Koichi Sasada - Date: 2019-12-05 14:39:03 +0900 - - add additional CF info for CI env - - Introduce new RUBY_DEBUG option 'ci' to inform Ruby interpreter - that an interpreter is running on CI environment. - - With this option, `rb_bug()` shows more information includes - method entry information, local variables information for each - control frame. - -commit c88afd532895a8527f7c9fffb2c635805d01f626 - Author: Koichi Sasada - Date: 2019-12-05 14:38:46 +0900 - - fix parameter - -commit 0d7d8b2989e1738dd902d354cc41186899e6b71e - Author: Yusuke Endoh - Date: 2019-12-05 14:41:38 +0900 - - ext/openssl/extconf.rb: do not use -Werror=deprecated-declarations - - It fails to build on Solaris: - - ``` - ossl_cipher.c: 関数 ‘ossl_cipher_init’ 内: - ossl_cipher.c:228:2: エラー: ‘EVP_md5’ is deprecated [-Werror=deprecated-declarations] - 228 | EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, - | ^~~~~~~~~~~~~~ - In file included from /usr/include/openssl/x509.h:73, - from /usr/include/openssl/x509v3.h:63, - from ossl.h:23, - from ossl_cipher.c:10: - /usr/include/openssl/evp.h:732:26: 備考: ã“ã“ã§å®£è¨€ã•れã¦ã„ã¾ã™ - 732 | DEPRECATED const EVP_MD *EVP_md5(void); - | ^~~~~~~ - ``` - - I agree that `-Werror=` is a good habit, but adding it by default is too - aggressive. - -commit c0d118f41a3a66ab76a553f184efe431524b952d - Author: Jun Aruga - Date: 2019-12-05 14:17:16 +0900 - - Fix "cannot find the function: strcpy()" error on arm32 on Travis CI. (#2686) - - This issue happened when `libc.so` and `libm.so` path were not found - and `ldd ruby` command also failed to print the shared dependencies - in `test/fiddle/helper.rb`. - - See https://travis-ci.org/ruby/ruby/jobs/611483288#L3018 - /home/travis/build/ruby/ruby/build/.ext/common/fiddle/import.rb:299:in `import_function': cannot find the function: strcpy() (Fiddle::DLError) - - * Set libc6:armhf as a installing dependency explicitly. - * Remove arm32 from allow_failures. - -commit ed5d032ea33a465fd7152a236a4aca0ff5653bf3 - Author: Antonio Terceiro - Date: 2019-11-26 09:25:53 +0900 - - debug.rb: expand filenames in breakpoints - - When debugging some local code, specifying a breakpoint to a local - filename does not work, i.e. - - break lib/foo.rb:10 - - Expanding the filename makes it work. FWIW byebug has the same behavior. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2694 - -commit 20031f8b74a224bed88bfd149d59d6176c4f58e2 - Author: aycabta - Date: 2019-12-05 13:06:08 +0900 - - Change encoding of completion list - -commit df76f2c577b6567b617be2df9451123cc450d1cc - Author: Alan Wu - Date: 2019-12-05 11:02:21 +0900 - - Make TracePoint.stat a singleton method again (#2726) - - [Bug #16399] - - Notes: - Merged-By: XrXr - -commit e4db0443bcfc94f9183e8ea72fb4ab560aa005bf - Author: Jeremy Evans - Date: 2019-07-23 11:56:02 +0900 - - Make rb_eval_string_wrap specify a cref so constant setting works correctly - - Fixes [Bug #10466] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2722 - -commit 18d3b5a93a2d52412f8f563d58db682b41d5c98c - Author: Yuki Nishijima - Date: 2019-12-05 09:55:01 +0900 - - Do not attempt to call methods on the receiver if it is a basic object - -commit 88ee375dd6c93523bd5d8f9517e49215b9d8cf67 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-05 09:43:45 +0900 - - Revert "Add debug option to check ci failures on solaris" - - This reverts commit f289e3994bbc6560e2e4e5905b52c35c829c972d. - -commit fbf10ed5b3f37b7cd9950ac8d1f1c81255525d36 - Author: git - Date: 2019-12-05 09:03:49 +0900 - - * 2019-12-05 [ci skip] - -commit e3587ed8498dcf7a3a8178030f7ae66cd0719c57 - Author: aycabta - Date: 2019-12-04 22:32:12 +0900 - - Support disable-completion - -commit ad8fbf444abdf1480d87c95b2868741f98eb953f - Author: aycabta - Date: 2019-12-04 22:26:40 +0900 - - Fix variable catch - -commit fb11e6089dbe9d995510977def038a21882bcffe - Author: Nobuyoshi Nakada - Date: 2019-12-04 21:52:29 +0900 - - [DOC] Added File::FNM_SYSCASE example [Bug #16391] [ci skip] - -commit dbfd4b780e3914a3f27e92c2248254452bf0fd6b - Author: Yusuke Endoh - Date: 2019-12-04 20:59:39 +0900 - - coroutine/ucontext/Context.c: Include "ruby/config.h" for Solaris - - getcontext, makecontext, and swapcontext seem to be available only when - `__EXTENSION__` is defined on Solaris. - -commit a0bc0e1ba15e83c72426ac243ea96e6497c49859 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-04 18:43:19 +0900 - - Fix thread leak in drb - - Notes: - Merged: https://github.com/ruby/ruby/pull/2724 - -commit 00bbdf4451d0e66f0f7823e77c47ac310614c1c3 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-12-04 15:31:51 +0900 - - implement Range#count - - As matz requested in [Bug #16366]. - -commit c6e3db0c66312af1e932c21006437419efa9ac75 - Author: Koichi Sasada - Date: 2019-12-04 13:36:41 +0900 - - new_cond before mon_initialize - - MonitorMixin#new_cond can be called before mon_initialize, so we - need to initialize `@monitor` before it. - - https://bugs.ruby-lang.org/issues/16255#note-4 - -commit f9e5c74cd24025a5aa19e318e8fecabf207f1b7b - Author: Yusuke Endoh - Date: 2019-12-04 10:33:35 +0900 - - compile.c: stop wrong peephole optimization when covearge is enabled - - jump-jump optimization ignores the event flags of the jump instruction - being skipped, which leads to overlook of line events. - - This changeset stops the wrong optimization when coverage measurement is - neabled and when the jump instruction has any event flag. - - Note that this issue is not only for coverage but also for TracePoint, - and this change does not fix TracePoint. - However, fixing it fundamentally is tough (which requires revamp of - the compiler). This issue is critical in terms of coverage measurement, - but minor for TracePoint (ko1 said), so we here choose a stopgap - measurement. - - [Bug #15980] [Bug #16397] - - Note for backporters: this changeset can be viewed by `git diff -w`. - -commit 5a404efd29d255402e30f4f23a09d4e5398600b8 - Author: Nobuyoshi Nakada - Date: 2019-12-04 10:06:54 +0900 - - [ruby/io-console] Fixed `intr: false` mode on Windows - - https://github.com/ruby/io-console/commit/4c172c01aa - -commit 447d583536274a2489efc8792653ad35d6f7128a - Author: Jeremy Evans - Date: 2019-08-28 03:48:50 +0900 - - Silence incorrect assigned but unused variable warnings in ripper - - To only emit the warnings in correct cases would require tracking - local variable usage in ripper, which ripper currently does not do. - - Fixes [Bug #15188] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2719 - -commit a91637c516779d9ecee5f323e211f0ed71eb06ad - Author: Jeremy Evans - Date: 2019-10-03 07:20:10 +0900 - - Make {Method,UnboundMethod}#super_method handle clone/bind/unbind - - This wasn't working previously because the iclass entry wasn't - being copied, and without an iclass entry, super_method returns - nil. - - Fixes [Bug #15629] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2723 - -commit f9754f0ea08e0d4fb28681a86cbc6ec2d884dba5 - Author: Yusuke Endoh - Date: 2019-12-04 08:22:48 +0900 - - compile.c: trivial refactoring - - Use `for` instead of `while` to make it explicit that it is a traverse - of bytecode. - -commit 8852fa876039ed177fd5e867f36177d8a9ff411c - Author: NARUSE, Yui - Date: 2019-12-04 01:26:29 +0900 - - Revert "Regexp#match{?} with nil raises TypeError as String, Symbol (#1506)" - - This reverts commit 2a22a6b2d8465934e75520a7fdcf522d50890caf. - Revert [Feature #13083] - -commit 08074eb71229b4c9f669f7bfb215bbb43525bfc0 - Author: NARUSE, Yui - Date: 2019-12-04 01:26:28 +0900 - - Revert "Revert nil error and adding deprecation message" - - This reverts commit 452bee3ee8d68059fabd9b1c7a75661b14e3933e. - -commit a705f6472c3e34422776d886bbc9f98676d8c0eb - Author: NARUSE, Yui - Date: 2019-12-04 01:26:27 +0900 - - Revert "Improve warning message" - - This reverts commit 31110d820cc1258cbc84b46ecc65b254c7d5529a. - -commit 34a66b1f36e9a065cf8433598b3fce03ce2c711e - Author: NARUSE, Yui - Date: 2019-12-04 01:26:24 +0900 - - Revert "Fix warnings in Regexp#{match,match?} specs" - - This reverts commit 782d1b8fb0a039cedef9ad9c94f432dad51901e6. - -commit a029b54ec716812ade37fef1f857c49f821a8cc8 - Author: Jeremy Evans - Date: 2019-08-29 08:41:39 +0900 - - Make Enumerator::Chain#each treat lambdas as lambda - - Previously, lambdas were converted to procs because of how - rb_block_call works. Switch to rb_funcall_with_block, which - handles procs as procs and lambdas as lambdas. - - Fixes [Bug #15613] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2720 - -commit 47c97e1e843159c3c4d57f8c5e22daea57c3ffe1 - Author: Jeremy Evans - Date: 2019-08-12 12:53:37 +0900 - - Do not lose existing constant visibility when autoloading - - This copies the private/deprecate constant visibility across the - autoload. It still is backwards compatible with setting the - private/deprecate constant visibility in the autoloaded file. - However, if you explicitly set public constant in the autoloaded - file, that will be reset after the autoload. - - Fixes [Bug #11055] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2716 - -commit b96d559c696c5141bdb6717442818f1206ff9d2e - Author: git - Date: 2019-12-04 00:27:58 +0900 - - * 2019-12-04 [ci skip] - -commit 5c2c3966851ed074eb468ad36d8d75e53b8eab6c - Author: Jeremy Evans - Date: 2019-08-26 04:09:19 +0900 - - Check interrupts before starting thread - - Fixes a hang when Thread.new calls Thread.new in a loop. - - Fixes [Bug #13688] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2715 - -commit 7f2cd2ae6fea76ff3a2b95b69e6e2f749e8a249f - Author: KOSAKI Motohiro - Date: 2019-12-03 19:50:16 +0900 - - fix typo - -commit a1f98cd4c1d55efe4998ecd3d94508634baefc23 - Author: Yusuke Endoh - Date: 2019-12-03 17:56:50 +0900 - - vm_args.c: make the keyword deprecation message helpful - - ``` - $ ./miniruby -e 'def foo(kw: 1); end; h = {kw: 1}; foo(h)' - -e:1: warning: The last argument is used as the keyword parameter - -e:1: warning: for `foo' defined here; maybe ** should be added to the call? - ``` - -commit 409e4ab740de3852c3667217bcf41b55040f638f - Author: Yusuke Endoh - Date: 2019-12-03 17:05:07 +0900 - - tool/lib/test/unit/parallel.rb: fail explicitly when failing to get io - - `(ulimit -n 30; make test-tool)` fails with unexplicit message: - "undefined method `write' for nil:NilClass" due to lack of stdout. - - This change makes it explicit. [Bug #5577] - -commit e42d9d8df87f58b9bfa65647249822df25851375 - Author: Nobuyoshi Nakada - Date: 2019-12-03 14:51:14 +0900 - - Fixed the inverted condition - -commit 9165fcdfa309052a2adc3c6100ab24204de6c2d1 - Author: Nobuyoshi Nakada - Date: 2019-12-03 14:46:49 +0900 - - Wrap statements in AS_IF properly - -commit 027e847cd2540553c9ddcf1b39028c43258a3fb4 - Author: aycabta - Date: 2019-12-03 13:02:01 +0900 - - Fix auto-indent behavior correctly - -commit 14a17063a11a01d518b4bbaf0eb967330aec3984 - Author: Nobuyoshi Nakada - Date: 2019-12-03 08:12:57 +0900 - - Fixed stack overflow [Bug #16382] - - Get rid of infinite recursion in expanding a load path to the real - path while loading a transcoder. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2714 - -commit 8bddf1bc9bdd1db7ce2e3fec15f2f06ff355b0a7 - Author: Yusuke Endoh - Date: 2019-12-03 08:02:38 +0900 - - mjit.c: fix a mismatch of malloc'ed type - - Coverity Scan found this issue. - -commit 424ad9a49360be56244609c02678e8f055d92073 - Author: Benoit Daloze - Date: 2019-12-03 05:23:10 +0900 - - Make more attempts to check for the precision of Process.times - - * Process.clock_getres specs use 10_000 but that's quite slow for - the Process.times spec. - -commit c688487fae22e0f73b4e2a9ea5749cb224c25e48 - Author: git - Date: 2019-12-03 01:41:22 +0900 - - * 2019-12-03 [ci skip] - -commit a92560132b1bff6a01782cfeacd62756b4b34d21 - Author: aycabta - Date: 2019-12-03 01:17:07 +0900 - - Support incremental search by last determined word - - In the incremental search by C-r, search word is saved when it's determined. In - the next incremental search by C-r, if a user presses C-r again with the empty - search word, the determined previous search word is used to search. - -commit bce38f706e9c434d8fd7c0e2e14bb4acdd085777 - Author: aycabta - Date: 2019-12-02 09:15:07 +0900 - - The C-r in vi command mode is also incremental search - -commit a47d6c256ff684392f00516a917735a14aec64b0 - Author: Takashi Kokubun - Date: 2019-12-02 17:12:29 +0900 - - Fix random failure on getusage-missing environments - - `* 1e6` makes a spurious result about floating point number's precision. - - ``` - irb(main)[01:0]> 16.028 - => 16.028 - irb(main)[02:0]> (16.028 * 1e6) - => 16027999.999999998 - ``` - -commit 1a88adcd75d92cb36ef5b1d5f4aeb40e6fe4dcb7 - Author: Kazuhiro NISHIYAMA - Date: 2019-12-02 15:21:15 +0900 - - Fix Leaked file descriptor in test/did_you_mean - - https://github.com/ruby/ruby/commit/de74d2c3b0005048a2c4433bde68b9be10c86f01/checks?check_suite_id=336910877#step:19:131 - ``` - Leaked file descriptor: NameErrorExtensionTest#test_correctable_error_objects_are_dumpable: 7 : # - ``` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2712 - -commit 185f7608737a550a0891a7fc5a6a4ee32721bce3 - Author: Takashi Kokubun - Date: 2019-12-02 16:23:40 +0900 - - Debug random failure of ruby-spec on ci.rvm.jp - -commit 9afaf139f232e8b2c697d33e984945464744def1 - Author: Nobuyoshi Nakada - Date: 2019-12-02 14:15:42 +0900 - - Revert "builtin_binary.inc needs miniruby itself for RubyVM.each_builtin" - - This reverts commit 2615030c521afc822c66a7e139ccba3d2365ab56, - which doesn't work when cross compiling, except for mingw. - -commit 2615030c521afc822c66a7e139ccba3d2365ab56 - Author: Nobuyoshi Nakada - Date: 2019-12-02 14:03:46 +0900 - - builtin_binary.inc needs miniruby itself for RubyVM.each_builtin - -commit a7b9f085ff952fcb18f82de39b3bf9ab7e5ba3e7 - Author: Nobuyoshi Nakada - Date: 2019-12-02 13:20:00 +0900 - - Disable _FORTIFY_SOURCE on mingw for now - - It causes a link error due to some `__*_chk` functions on mingw. - -commit b1c92363a74b0e649a685ae47ae400fbaab7b29d - Author: Nobuyoshi Nakada - Date: 2019-12-02 13:16:55 +0900 - - Wait for the main thread to start reading by Queue - - Otherwise, the written data to pty before the reading started may - be just lost. - -commit de74d2c3b0005048a2c4433bde68b9be10c86f01 - Author: Takashi Kokubun - Date: 2019-12-02 10:32:50 +0900 - - Simplify variable declaration by C99 - -commit 103b04128f4e40b87bb9c7fb2916d2a800bfd94f - Author: aycabta - Date: 2019-12-02 04:17:47 +0900 - - Support incremental search again by C-r in incremental search - -commit b3ea0980db87404c2b7763a3fdbe898c3812843d - Author: Takashi Kokubun - Date: 2019-12-02 03:53:58 +0900 - - Check MJIT support in one place - - to fix test failure on trunk-no-mjit - https://gist.github.com/ko1/32ab982ffd7555988818773c08f97123 - -commit 6bc8b4d8ea6cb8865225c0afcf1abd9e4b725376 - Author: Takashi Kokubun - Date: 2019-12-02 03:51:04 +0900 - - Skip --jit-debug= test on mswin - - it fails like - https://ci.appveyor.com/project/ruby/ruby/builds/29235837/job/v0apdjj4qx8afars - -commit c7f05310a248e44ef9747a159a0e9bc289bb7090 - Author: aycabta - Date: 2019-12-02 03:30:38 +0900 - - Process Backspace key in incremental search correctly - -commit e15b0313a78a6f381720cf362a1a94bda49f62ff - Author: aycabta - Date: 2019-12-02 03:05:10 +0900 - - Search history to back in the middle of histories - -commit 4d7a6d04b2c71aabb9d6e619f4405887806a5be8 - Author: KOSAKI Motohiro - Date: 2019-12-02 01:21:05 +0900 - - Avoid unnecessary tzset() call - - Akatsuki reported ENV['TZ'] = 'UTC' improved 7x-8x faster on following code. - t = Time.now; 100000.times { Time.new(2019) }; Time.now - t - https://hackerslab.aktsk.jp/2019/12/01/141551 - - commit 4bc1669127(reduce tzset) dramatically improved this situation. But still, - TZ=UTC is faster than default. - - This patch removs unnecessary tzset() call completely. - - Performance check - ---------------------- - test program: t = Time.now; 100000.times { Time.new(2019) }; Time.now - t - before: 0.387sec - before(w/ TZ): 0.197sec - after: 0.162sec - after(w/ TZ): 0.165sec - - OK. Now, Time creation 2x faster *and* TZ=UTC doesn't improve anything. - We can forget this hack completely. :) - - Side note: - This patch slightly changes Time.new(t) behavior implicitly. Before this patch, it might changes - default timezone implicitly. But after this patch, it doesn't. You need to reset TZ - (I mean ENV['TZ'] = nil) explicitly. - But I don't think this is big impact. Don't try to change /etc/localtime on runtime. - - Side note2: following test might be useful for testing "ENV['TZ'] = nil". - ----------------------------------------- - % cat <<'End' | sudo sh -s - rm -f /etc/localtime-; cp -a /etc/localtime /etc/localtime- - rm /etc/localtime; ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime - ./ruby -e ' - p Time.new(2000).zone # JST - File.unlink("/etc/localtime"); File.symlink("/usr/share/zoneinfo/America/Los_Angeles", "/etc/localtime") - p Time.new(2000).zone # JST (ruby does not follow /etc/localtime modification automatically) - ENV["TZ"] = nil - p Time.new(2000).zone # PST (ruby detect /etc/localtime modification) - ' - rm /etc/localtime; cp -a /etc/localtime- /etc/localtime; rm /etc/localtime- - End - -commit 43811cc3b36739816788cbbac7a49b9bbf756293 - Author: git - Date: 2019-12-02 00:05:20 +0900 - - * 2019-12-02 [ci skip] - -commit 7f0d51704a5cb789c16a6c05db455469f0b2601d - Author: aycabta - Date: 2019-12-02 00:03:59 +0900 - - Remove obsolete code - -commit 8cb3f29abf9290838bdc3b9904868c78752427e8 - Author: aycabta - Date: 2019-12-01 23:53:59 +0900 - - The ed_search_prev_history should always search to backward - -commit f1cfc7da180a8cf26f758fbe553e6653e4a4dc53 - Author: aycabta - Date: 2019-12-01 22:11:59 +0900 - - Reline::HISTORY can take Range object - -commit 617a3735aedc12fe82b6806d6d3a37c3f977fef1 - Author: Benoit Daloze - Date: 2019-12-01 22:11:42 +0900 - - Update to ruby/spec@dcf4955 - -commit 60d362b0bb0fb56bd3ef61c93f71bff997ccb824 - Author: Benoit Daloze - Date: 2019-12-01 22:11:40 +0900 - - Update to ruby/mspec@aa28e95 - -commit ab516e263c06fbd755d4805ad529c32b1b8292b5 - Author: Nobuyoshi Nakada - Date: 2019-12-01 21:14:58 +0900 - - [ruby/spec] Fix failures with LC_ALL=C - - https://github.com/ruby/spec/commit/51047687c0 - https://github.com/ruby/spec/commit/2b87b467cc - -commit 4e03a7298b3a99de9c57f9a4934d38445cad1b10 - Author: Nobuyoshi Nakada - Date: 2019-12-01 20:26:28 +0900 - - Constified mjit_init - -commit cb760f36aae42a63738394f170444b6ae4405b82 - Author: Nobuyoshi Nakada - Date: 2019-12-01 19:29:04 +0900 - - Constified - -commit 91af5542b503054ea059b6c4faa5cd821784774a - Author: Takashi Kokubun - Date: 2019-12-01 19:00:08 +0900 - - Fix a mistake excluding NULL in the end - -commit 8a677a6e80b3b7e1f52073b362083a78eb87397f - Author: Takashi Kokubun - Date: 2019-12-01 18:35:30 +0900 - - Workaround missing strndup on Windows - - https://ci.appveyor.com/project/ruby/ruby/builds/29230976/job/c910t37313edb97k - -commit 3e2753ad2e0b643f5c731fb162f5805d82435032 - Author: Takashi Kokubun - Date: 2019-12-01 18:25:54 +0900 - - Use build dir for testing --jit-debug - - to fix failure like https://github.com/ruby/ruby/runs/327745536 - -commit a19d625e667024fe27dcee04dd748e914bc24762 - Author: Takashi Kokubun - Date: 2019-12-01 17:56:27 +0900 - - Allow specifying arbitrary MJIT flags by --jit-debug - - This is a secret feature for me. It's only for testing and any behavior - with this flag override is unsupported. - - I needed this because I sometimes want to add debug options but do not - want to disable optimizations, for using Linux perf. - -commit bdc62dfc8ecffd27dd5ad6756cce88eac5c993f5 - Author: Nobuyoshi Nakada - Date: 2019-12-01 14:38:33 +0900 - - Fixed type of an index variable - -commit 9914d6e992a69587e6d43ba7eaa6cdda9f178f8e - Author: Yuki Nishijima - Date: 2019-12-01 13:26:09 +0900 - - Relax test strictness for error message from KeyError - -commit cc7455dd1e98e297dbea2fd92e491bd36f1b473e - Author: Yuki Nishijima - Date: 2019-12-01 12:29:02 +0900 - - Relax test requirements for DYM's verbose formatter - -commit 56faa13a1c5261a0d046a4c0203e88fccfafae17 - Author: Koichi Sasada - Date: 2019-12-01 12:24:50 +0900 - - remove spaces to pass a test. - - 23d7f4c5e1ce164e78d77de694dccc0c41f6de3d breaks a test which expect - to match error message. To avoid this failure, use #strip for expect - and actual results. - -commit 23d7f4c5e1ce164e78d77de694dccc0c41f6de3d - Author: git - Date: 2019-12-01 11:08:39 +0900 - - * remove trailing spaces. [ci skip] - -commit 0fef526606c72e7d2a3c83aebd9204da34016d96 - Author: Yuki Nishijima - Date: 2019-11-30 11:40:07 +0900 - - Do not call 'gem "did_you_mean"' for now - - This will slow down the time that the +require+ method takes to load DYM, - but this has caused a build failure in a certain situation: - - https://ci.appveyor.com/project/ruby/ruby/builds/29214253/job/r9u9c8p95tnlftt3#L24965 - - which is reported as a separate bug: - - https://bugs.ruby-lang.org/issues/16382?next_issue_id=16381 - - For now this commit should fix the builds, but we should come back and - add back the 'gem' call. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2689 - -commit 171803d5d34feb1b4244ca81b9db0a7bc2171c85 - Author: Kevin Deisz - Date: 2019-10-29 23:08:37 +0900 - - Promote did_you_mean to default gem - - At the moment, there are some problems with regard to bundler + did_you_mean because of did_you_mean being a bundled gem. Since the vendored version of thor inside bundler and ruby itself explicitly requires did_you_mean, it can become difficult to load it when using Bundler.setup. See this issue: https://github.com/yuki24/did_you_mean/issues/117#issuecomment-482733159 for more details. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2689 - -commit a2fc6a51dd2e1a153559038795e1e2509f9c6a94 - Author: David Rodríguez - Date: 2019-11-30 22:03:12 +0900 - - [ruby/fileutils] Fix test failure under ruby 2.4 - - `Exception#full_message` is only defined on ruby 2.5.0 and above. - - https://github.com/ruby/fileutils/commit/a8968f41ed - -commit fa0f3eff228bb26de6d5b0e1238b1f358165dbd0 - Author: David Rodríguez - Date: 2019-11-30 22:01:18 +0900 - - [ruby/fileutils] Fix error printing test failure - - `exception_details` is not defined anywhere. - - This commit fixes the following test crash in ruby 2.4 - - ``` - Error: test_assert_output_lines(TestFileUtils): NoMethodError: undefined method `exception_details' for # - ``` - - And replaces it with an actual test failure: - - ``` - [Test::Unit::CoreAssertions::MiniTest::Assertion] exception expected, not # - Did you mean? message>. - ``` - - https://github.com/ruby/fileutils/commit/2f38ba6e82 - -commit 5b1f7f26b4ff3b05e1c184ae87154a323b1be915 - Author: Takashi Kokubun - Date: 2019-12-01 06:29:00 +0900 - - Skip if getrusage is not supported - - 1243255c3a36433041012b6107a5ac48658a0895 broke ci.rvm.jp tests like - http://ci.rvm.jp/results/trunk_clang_39@silicon-docker/2445098. - - 253232c028a5565dbeecc05fab5e81b35ab58bcc works only if getrusage is supported. - -commit 1243255c3a36433041012b6107a5ac48658a0895 - Author: Benoit Daloze - Date: 2019-12-01 05:26:52 +0900 - - Update to ruby/spec@4eec3dc - -commit ab8345271eb87ff155d8bd5f22f53a4cf2902c26 - Author: Benoit Daloze - Date: 2019-12-01 05:26:49 +0900 - - Update to ruby/mspec@a401f63 - -commit 93a512414cbe3713f478038f6d4f5fe81c4eb62a - Author: git - Date: 2019-12-01 02:18:45 +0900 - - * 2019-12-01 [ci skip] - -commit 5e0479f26afe1505afd9014ea96a206a88845828 - Author: Nobuyoshi Nakada - Date: 2019-10-01 12:23:25 +0900 - - ENV.update should not call block on existing keys - - [Bug #16192] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2512 - -commit b94d06096b8f2a375719ce09370e004fcb277b25 - Author: Hiroshi SHIBATA - Date: 2019-11-30 18:20:02 +0900 - - [ruby/zlib] Bump version to 1.1.0 - - https://github.com/ruby/zlib/commit/5af77c1ee8 - -commit 7ebcee6b7634889f0bd92aaedf079845065ac797 - Author: Hiroshi SHIBATA - Date: 2019-11-30 18:13:16 +0900 - - [ruby/gdbm] Bump version to 2.1.0 - - https://github.com/ruby/gdbm/commit/ffb2b063a3 - -commit 56567c76487d42f12283ecf074d45adae96ca5f0 - Author: Hiroshi SHIBATA - Date: 2019-11-30 18:03:57 +0900 - - [ruby/etc] Bump version to 1.1.0 - - https://github.com/ruby/etc/commit/78987ce56a - -commit 08c866d5281777e1f8f8503f7ebdec9aee62ed63 - Author: Hiroshi SHIBATA - Date: 2019-11-30 18:05:51 +0900 - - [ruby/fileutils] Bump version to 1.4.1 - - https://github.com/ruby/fileutils/commit/da15e3ce06 - -commit 06b9b78e21f5da5f348a932c3e7f21468674e4f1 - Author: Hiroshi SHIBATA - Date: 2019-11-30 17:54:44 +0900 - - [ruby/dbm] Bump version to 1.1.0 - - https://github.com/ruby/dbm/commit/163078359d - -commit 32e547954fbbcbdd6f4468bf3be9e7eaa5d32f0f - Author: Hiroshi SHIBATA - Date: 2019-11-30 17:58:39 +0900 - - Revert "[ruby/fileutils] Fix #install with "X" mode option" - - This reverts commit eab88d20eaa925d5e61a2a65820a099b46ccf3f8. - - The some CI was broken with this. - -commit 5e9f08647cead8b7fa303a5da88c5e96035f3497 - Author: Nobuyoshi Nakada - Date: 2019-08-28 21:58:25 +0900 - - [ruby/webrick] Check the feature by itself, instead of the version number - - https://github.com/ruby/webrick/commit/79d7922de9 - -commit a98632d5c20e41e05074384b8f760af407e6d52a - Author: Jeremy Evans - Date: 2019-08-12 04:57:11 +0900 - - [ruby/webrick] Enabled chunked encoding if Transfer-Encoding: chunked header is set - - Patch from Leonard Garvey. - - Fixes Ruby Bug 9986. - - https://github.com/ruby/webrick/commit/8cff7f3995 - -commit edfbffb241a894eece57155a22a89637b33cfe58 - Author: Hiroshi SHIBATA - Date: 2019-11-30 17:39:58 +0900 - - [ruby/webrick] Bump version to 1.6.0 - - https://github.com/ruby/webrick/commit/c5635fa5e2 - -commit c75100d00401c32b3245ce8da5b8a045976216ca - Author: Jeremy Evans - Date: 2019-08-27 13:41:27 +0900 - - [ruby/webrick] Allow WEBrick::HTTPServlet::CGIHandler :CGIInterpreter option to be array - - This way you don't need to escape each entry. - - Implements Ruby Feature 15170. - - https://github.com/ruby/webrick/commit/d8086e600c - -commit f7cf5416e471cd34153058952063da3457468e58 - Author: zverok - Date: 2019-10-26 19:27:17 +0900 - - [ruby/webrick] Document HTTPResponse#body callable option - - https://github.com/ruby/webrick/commit/d51836d03d - -commit ea4272d02b02719e266c7cf30141e6275e38f9a7 - Author: Hiroshi SHIBATA - Date: 2019-11-30 17:23:13 +0900 - - [ruby/fileutils] Bump version to 1.4.0 - - https://github.com/ruby/fileutils/commit/f92145b10b - -commit 3b9e1c0b2e5b3c507c94fd36c87288e789ee9c2a - Author: Hiroshi SHIBATA - Date: 2019-11-30 17:32:38 +0900 - - Move gemspec of fileutils under the toplevel of lib directory. - -commit eab88d20eaa925d5e61a2a65820a099b46ccf3f8 - Author: Nobuyoshi Nakada - Date: 2019-10-03 01:39:02 +0900 - - [ruby/fileutils] Fix #install with "X" mode option - - `FileUtils#install` methed raises an unexpected `TypeError`, when - called with `mode:` option which has `"X"`. - - ``` - $ ruby -rfileutils -e 'FileUtils.install("tmp/a", "tmp/b", mode: "o+X")' - /opt/local/lib/ruby/2.7.0/fileutils.rb:942:in `directory?': no implicit conversion of File::Stat into String (TypeError) - from /opt/local/lib/ruby/2.7.0/fileutils.rb:942:in `block (3 levels) in symbolic_modes_to_i' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:933:in `each_char' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:933:in `each' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:933:in `inject' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:933:in `block (2 levels) in symbolic_modes_to_i' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:931:in `each' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:931:in `each_slice' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:931:in `block in symbolic_modes_to_i' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:926:in `each' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:926:in `inject' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:926:in `symbolic_modes_to_i' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:973:in `fu_mode' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:883:in `block in install' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:1588:in `block in fu_each_src_dest' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:1604:in `fu_each_src_dest0' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:1586:in `fu_each_src_dest' - from /opt/local/lib/ruby/2.7.0/fileutils.rb:877:in `install' - from -e:1:in `
' - ``` - - In spite of that `symbolic_modes_to_i` considers the `File::Stat` - `path` case at the beginning, in `"X"` case, `path` is passed to - `FileTest.directory?` method which requires a `String`. In such - case, the mode in `path` should be examined instead. - - https://github.com/ruby/fileutils/commit/2ea54ade2f - -commit aab74fc938453233a5f11a093ad6129a0be230d1 - Author: Nobuyoshi Nakada - Date: 2019-10-03 01:17:26 +0900 - - [ruby/fileutils] Added `test_install_mode_option` - - https://github.com/ruby/fileutils/commit/bb10efe104 - -commit 0a7d26bea1b2d7ab4c36e471d387d1a9907a486d - Author: Nobuyoshi Nakada - Date: 2019-10-03 00:55:19 +0900 - - [ruby/fileutils] Remove version.rb - - Loading separate version.rb unnecessary increases every start-up - time. In the other hand, the gemspec file is parsed only when - building the gem file. - - https://github.com/ruby/fileutils/commit/8359cf7cce - -commit c064018a7584fe03403a3b175ac25dbbb1162c8c - Author: Kazuhiro NISHIYAMA - Date: 2019-11-19 15:13:35 +0900 - - Make extract-gems only if test_task is check - - Notes: - Merged: https://github.com/ruby/ruby/pull/2678 - -commit bb3542cc6b3db5477c2a9efd76905a4133545da1 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 21:28:53 +0900 - - Add update-gems before extract-gems - - (windows.yml used `nmake up`) - - Notes: - Merged: https://github.com/ruby/ruby/pull/2678 - -commit 2eb4afb10bd9a3849eb34292f33240ac3ef19905 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 19:45:14 +0900 - - Add extract-gems to GitHub Actions CI - - Notes: - Merged: https://github.com/ruby/ruby/pull/2678 - -commit cf14592872684956df7c014de0f9808c8aaf0e22 - Author: Hiroshi SHIBATA - Date: 2019-11-30 16:01:23 +0900 - - [ruby/readline-ext] Prepare to gem release - - https://github.com/ruby/readline-ext/commit/e5b969215a - -commit 856f9990a90e601ec5245a934d1da153591fcf3b - Author: Hiroshi SHIBATA - Date: 2019-11-30 15:50:57 +0900 - - [ruby/forwardable] Bump version to 1.3.0 - - https://github.com/ruby/forwardable/commit/e56f0f83c6 - -commit 9fa0166a580e72adf02562b7d60672c6c362d4b7 - Author: Jeremy Evans - Date: 2019-09-08 04:41:16 +0900 - - [ruby/forwardable] Fix keyword argument separation warnings on Ruby 2.7+ - - Do so in a way that is also compatible with previous versions. - - https://github.com/ruby/forwardable/commit/b2dd340988 - -commit af4b3f16ceed36f8b18856120940c9de6e6a0eee - Author: Hiroshi SHIBATA - Date: 2019-11-30 15:26:01 +0900 - - [ruby/stringio] Bump version to 0.1.0 - - https://github.com/ruby/stringio/commit/4c1e267e1a - -commit 990025cf60eb6586c13f5f055880ac60afbac646 - Author: Hiroshi SHIBATA - Date: 2019-11-30 15:16:13 +0900 - - [ruby/stringio] RbConfig::LIMITS only provide after Ruby 2.5 - - https://github.com/ruby/stringio/commit/1fed3aacd3 - -commit e764dff3641fd66fda1b9cf33cb7ddeb30e0b38a - Author: Hiroshi SHIBATA - Date: 2019-11-30 14:31:00 +0900 - - [ruby/date] Bump version to 3.0.0 - - https://github.com/ruby/date/commit/202b2dad93 - -commit 80705e2c4fe7c1e968830880ea4408990e3f3c39 - Author: Hiroshi SHIBATA - Date: 2019-11-30 14:48:26 +0900 - - Add to support the single commit for sync_default_gems.rb - -commit f8cc05dec37f78b15814d0b936786d4e84d7d448 - Author: aycabta - Date: 2019-11-30 11:14:35 +0900 - - Use @eof variable for ReidlineInputMethod#eof? - - "IRB::InputMethod#eof?" requires eof status each user input but - "ReidlineInputMethod#eof?" used "Reline.eof?" what is singleton data. - "ReidlineInputMethod#eof?" is changed to use the result of user input. - -commit 0b1b2f2442744f0add4dec47e475e25cde602dcf - Author: Hiroshi SHIBATA - Date: 2019-11-29 21:31:55 +0900 - - Remove e2mmap from sync_default_gems.rb - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit c50d30f659ff22981444b3e4684fe9e6f2809055 - Author: Hiroshi SHIBATA - Date: 2019-11-29 17:48:43 +0900 - - Simplified ErrDimensionMismatch class - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 2f66c443d79bb3a2d5518dbe58ca86885bc23d5c - Author: Hiroshi SHIBATA - Date: 2019-11-29 17:46:13 +0900 - - Support argument for ErrNotRegular - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 0c59bfae0a3a9f5a3420a1eac42753480d8d95f7 - Author: Hiroshi SHIBATA - Date: 2019-11-29 17:29:21 +0900 - - Also replace E2MM to standard exception class - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 0950ef9a9a8e14dce44c36cf1ecaad187716a059 - Author: Hiroshi SHIBATA - Date: 2019-11-29 17:15:56 +0900 - - Remove e2mmap entries from docs - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit c1059e99d3f74fdd5d9a9792544a9ebc8a10edf7 - Author: Hiroshi SHIBATA - Date: 2019-11-29 17:11:11 +0900 - - Support existence usecase for the custom exception classes - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 5044260dcd1d1b51f2e217ca519431ab5a1cf8c2 - Author: Hiroshi SHIBATA - Date: 2019-11-29 16:50:54 +0900 - - replace raise method from e2mmap on Scalar class - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 9b950310be874753935a6ef4e8f94b3686f70540 - Author: Hiroshi SHIBATA - Date: 2019-11-29 16:35:51 +0900 - - raise method accepts 3 argument with exception class - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit f47f2076fed1546d993a376ce3c35ca81b1f0c6a - Author: Hiroshi SHIBATA - Date: 2019-11-27 12:17:03 +0900 - - Retire to maintain e2mmap on ruby core - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 04511b994e19de65fff84dd55a246842a2f9ad29 - Author: Hiroshi SHIBATA - Date: 2019-11-27 12:11:34 +0900 - - Remove re-define embedded error classes and extract argument on custom error classes - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit d82c541ae439b3c28ec71e9d6b839c2f304df273 - Author: Hiroshi SHIBATA - Date: 2019-11-27 11:48:04 +0900 - - Use simple exception classes instead of e2mmap - - Notes: - Merged: https://github.com/ruby/ruby/pull/2699 - -commit 0c273b2279e65c57161e0859f2d4e9f6e649b751 - Author: Jeremy Evans - Date: 2019-11-29 10:28:13 +0900 - - Suppress class variable overtaken warning when original modules are the same - - This issue was exposed by recent commits to better support including - refined modules. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2709 - -commit 8a1f313e2e6ecf43a1ccad6cca35f738c6052b3c - Author: git - Date: 2019-11-30 00:21:48 +0900 - - * 2019-11-30 [ci skip] - -commit d1ef4fd08e60adcbcb4feeb55f767ff3d80b65a0 - Author: Nobuyoshi Nakada - Date: 2019-11-30 00:15:29 +0900 - - Make single line pattern matching void expression - - Instead of returning `nil`, raise a syntax error if its value is - used. [Feature #16355] - -commit 36da0b3da1aed77e0dffb3f54038f01ff574972b - Author: Koichi Sasada - Date: 2019-11-29 17:39:06 +0900 - - check interrupts at each frame pop timing. - - Asynchronous events such as signal trap, finalization timing, - thread switching and so on are managed by "interrupt_flag". - Ruby's threads check this flag periodically and if a thread - does not check this flag, above events doesn't happen. - - This checking is CHECK_INTS() (related) macro and it is placed - at some places (laeve instruction and so on). However, at the end - of C methods, C blocks (IMEMO_IFUNC) etc there are no checking - and it can introduce uninterruptible thread. - - To modify this situation, we decide to place CHECK_INTS() at - vm_pop_frame(). It increases interrupt checking points. - [Bug #16366] - - This patch can introduce unexpected events... - -commit c4686b92359d298f281f3943ba205858e183e7af - Author: aycabta - Date: 2019-11-29 17:36:54 +0900 - - Revert "Treat :@1, :@@1, @1, and @@1 correctly to check termination" - - This reverts commit 5e275dd2af4d9d24cdb1cfc0f232f348dae9c2cd. - - ...The @1 type numberd parameter is reverted from Ruby syntax. - -commit bbbe481dc36b2bbd33f2d1062e149d5db7602bc1 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-29 17:32:52 +0900 - - Add SECURITY.md [ci skip] - - for https://github.com/ruby/ruby/security/policy - -commit 191ce5344ec42c91571f8f47c85be9138262b1c7 - Author: Yusuke Endoh - Date: 2019-09-13 17:02:08 +0900 - - Reduce duplicated warnings for the change of Ruby 3 keyword arguments - - By this change, the following code prints only one warning. - - ``` - def foo(**opt); end - 100.times { foo({kw:1}) } - ``` - - A global variable `st_table *caller_to_callees` is a map from caller to - a set of callee methods. It remembers that a warning is already printed - for each pair of caller and callee. - - [Feature #16289] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2458 - -commit 3a87826d0c3dd4c42e327e0cd4fb0806d898497f - Author: Yusuke Endoh - Date: 2019-11-29 16:51:13 +0900 - - vm_method.c: add top-level ruby2_keywords - - This is a top-level version of Module#ruby2_keywords. - It can be used for functions (top-level methods) that delegates - arguments. [Feature #16364] - -commit 5ad32d5504499f1a915d5d30e59dfd98da6759c6 - Author: Nobuyoshi Nakada - Date: 2019-11-29 11:25:23 +0900 - - `LoadError` is not a subclass of `StandardError` - -commit f83bebdf7a76e1ade3c5dc9d54cbffb9f761b453 - Author: Nobuyoshi Nakada - Date: 2019-11-29 11:19:09 +0900 - - Skip useless test - - `JSONGeneratorTest#test_remove_const_seg` is meaningful only for - the extension library version, but nonsense for pure ruby version. - -commit ba1cb388a9b29856ff1e1127a10c2ac727dabfc4 - Author: Nobuyoshi Nakada - Date: 2019-11-29 11:17:27 +0900 - - Fixed the position in NEWS [Feature #16348] - - [ci skip] - -commit a593186a02714cb92ae2748c2b7c46a6c50b0977 - Author: Nobuyoshi Nakada - Date: 2019-11-29 11:09:08 +0900 - - Nmake needs `VPATH` - -commit 98006cea4fd517671dae508fade13203bc18301a - Author: Nobuyoshi Nakada - Date: 2019-11-29 10:16:33 +0900 - - Add dependency on bundled yaml.h when using - -commit 6b460a79489bf65dee0a4c9f42324d3836888dd3 - Author: Koichi Sasada - Date: 2019-11-29 03:24:30 +0900 - - export func for MJIT - -commit f38b6d197f84ba8890daf4d708c0d17c1d339700 - Author: Koichi Sasada - Date: 2019-11-29 03:22:24 +0900 - - Revert "export for MJIT" - - This reverts commit 2e6f1cf8b264f4c8499c4e5f18bf662fdade04ff. - -commit e4e41840ad378ccd3144fe84ffd3aa55f6610ca5 - Author: Koichi Sasada - Date: 2019-11-29 03:22:13 +0900 - - Revert "* remove trailing spaces. [ci skip]" - - This reverts commit 27d0d7c0d39076d4bbacd3c3f3864322699db7b4. - -commit 27d0d7c0d39076d4bbacd3c3f3864322699db7b4 - Author: git - Date: 2019-11-29 03:18:19 +0900 - - * remove trailing spaces. [ci skip] - -commit 2e6f1cf8b264f4c8499c4e5f18bf662fdade04ff - Author: Koichi Sasada - Date: 2019-11-29 03:17:34 +0900 - - export for MJIT - -commit e5705c351c82f43bfa0c45903c72a69f307cce60 - Author: git - Date: 2019-11-29 03:11:40 +0900 - - * 2019-11-29 [ci skip] - -commit d104ebf2c4fef4751e067ea7a2c7e664a843e088 - Author: git - Date: 2019-11-29 03:11:28 +0900 - - * remove trailing spaces. [ci skip] - -commit dd723771c118da71aa58bb74537cacaec425542a - Author: Koichi Sasada - Date: 2019-11-29 03:02:44 +0900 - - fastpath for ivar read of FL_EXIVAR objects. - - vm_getivar() provides fastpath for T_OBJECT by caching an index - of ivar. This patch also provides fastpath for FL_EXIVAR objects. - FL_EXIVAR objects have an each ivar array and index can be cached - as T_OBJECT. To access this ivar array, generic_iv_tbl is exposed - by rb_ivar_generic_ivtbl() (declared in variable.h which is newly - introduced). - - Benchmark script: - - Benchmark.driver(repeat_count: 3){|x| - x.executable name: 'clean', command: %w'../clean/miniruby' - x.executable name: 'trunk', command: %w'./miniruby' - - objs = [Object.new, 'str', {a: 1, b: 2}, [1, 2]] - - objs.each.with_index{|obj, i| - rep = obj.inspect - rep = 'Object.new' if /\#/ =~ rep - x.prelude str = %Q{ - v#{i} = #{rep} - def v#{i}.foo - @iv # ivar access method (attr_reader) - end - v#{i}.instance_variable_set(:@iv, :iv) - } - puts str - x.report %Q{ - v#{i}.foo - } - } - } - - Result: - - v0.foo # T_OBJECT - - clean: 85387141.8 i/s - trunk: 85249373.6 i/s - 1.00x slower - - v1.foo # T_STRING - - trunk: 57894407.5 i/s - clean: 39957178.6 i/s - 1.45x slower - - v2.foo # T_HASH - - trunk: 56629413.2 i/s - clean: 39227088.9 i/s - 1.44x slower - - v3.foo # T_ARRAY - - trunk: 55797530.2 i/s - clean: 38263572.9 i/s - 1.46x slower - -commit b5fbefbf2c14742f6d46ecdf3ce712062dfb1d0a - Author: NARUSE, Yui - Date: 2019-11-17 23:24:59 +0900 - - Added Symbol#start_with? and Symbol#end_with? method. [Feature #16348] - -commit 76871dea6b05ee441f25c6f694ac21525ed25f93 - Author: NARUSE, Yui - Date: 2019-11-28 23:31:01 +0900 - - Use more template feature of w.r-l.o - -commit 0b453e2a55eefbe1bbb0b76faf61b9b6ab121d48 - Author: Nobuyoshi Nakada - Date: 2019-11-28 21:45:43 +0900 - - Get rid of inadvertent label [ci skip] - -commit 2fa3b4565ad904b09419dc77f4fff03aee1a8358 - Author: Nobuyoshi Nakada - Date: 2019-11-28 21:31:53 +0900 - - Merged common statements [Bug #16242] - -commit f0a5a07fa5b98a2e7fcd028cebd7770c6d8916a7 - Author: Nobuyoshi Nakada - Date: 2019-11-28 18:12:38 +0900 - - Removed unused variable [Bug #16242] - -commit a0579f3606561a74e323f6193b9504c06845236c - Author: Jeremy Evans - Date: 2019-10-12 17:02:51 +0900 - - Make prepending a refined module after inclusion not break refinements - - After the previous commit, this was still broken. The reason it - was broken is that a refined module that hasn't been prepended to - yet keeps the refined methods in the module's method table. When - prepending, the module's method table is moved to the origin - iclass, and then the refined methods are moved from the method - table to a new method table in the module itself. - - Unfortunately, that means that if a class has included the module, - prepending breaks the refinements, because when the methods are - moved from the origin iclass method table to the module method - table, they are removed from the method table from the iclass - created when the module was included earlier. - - Fix this by always creating an origin class when including a - module that has any refinements, even if the refinements are - not currently used. I wasn't sure the best way to do that. - The approach I choose was to use an object flag. The flag is - set on the module when Module#refine is called, and if the - flag is present when the module is included in another module - or class, an origin iclass is created for the module. - - Fixes [Bug #13446] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2550 - -commit 5069c5f5214ce68df8b3954321ad9114c5368dc3 - Author: Jeremy Evans - Date: 2019-10-12 16:01:37 +0900 - - Honor refinements for modules that prepend other modules - - This previously did not work, and the reason it did not work is - that: - - 1) Refining a module or class that prepends other modules places - the refinements in the class itself and not the origin iclass. - - 2) Inclusion of a module that prepends other modules skips the - module itself, including only iclasses for the prepended modules - and the origin iclass. - - Those two behaviors combined meant that the method table for the - refined methods for the included module never ends up in the - method lookup chain for the class including the module. - - Fix this by not skipping the module itself when the module is - included. This requires some code rearranging in - rb_include_class_new to make sure the correct method tables and - origin settings are used for the created iclass. - - As origin iclasses shouldn't be exposed to Ruby, this also - requires skipping modules that have origin iclasses in - Module#ancestors (classes that have origin iclasses were already - skipped). - - Fixes [Bug #16242] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2550 - -commit 4325f080862b36a3e3ddee472169f65758612ad3 - Author: aycabta - Date: 2019-11-28 15:32:21 +0900 - - Add require "irb" to test/irb/test_completion.rb - -commit 7d75e94ea967a47e1ca1083f6d1090eaac7ca58e - Author: aycabta - Date: 2019-11-28 15:15:41 +0900 - - Fix regexp to complete complex literal - - IRB completion logic always needed exponential notation for complex literal - such as 3e6i but it's bug. I fixed to support complex literal without - exponential notation such as 3i. - -commit 8b4ee5d6ba92a385eedc9235ce0a2d5618deecf0 - Author: Nobuyoshi Nakada - Date: 2019-11-28 13:44:25 +0900 - - Raise `NoMatchingPatternError` when expr `in` pat doesn't match - - * `expr in pattern` should raise `NoMatchingError` when unmatched - * `expr in pattern` should return `nil`. (this is unspecified, but - this feature is experimental, at all) - - [Feature #16355] - -commit 18953416def52824c46a68370c4b34f5b720ee3f - Author: y-yagi - Date: 2019-11-28 13:24:01 +0900 - - Fix documentation of `MonitorMixin#new_cond` [ci skip] (#2707) - - Since https://github.com/ruby/ruby/pull/2576, - `new_cond` uses the Monitor object, not the receiver. - -commit c688026455a3a37b233333aa90bdd4633b3e6a91 - Author: Nobuyoshi Nakada - Date: 2019-11-28 10:52:33 +0900 - - Suppress strict-aliasing warning by x86_64-w64-mingw32-gcc 7.4.0 - -commit abe8fb49f0365c23df06857549b7a3a32d212ed5 - Author: aycabta - Date: 2019-11-28 09:32:51 +0900 - - Delete newline when C-k on emacs mode at EOL - -commit 7769975c3ccf1f08c15f4c6de8451783683e281d - Author: aycabta - Date: 2019-11-28 08:26:10 +0900 - - Remove two removed constants - -commit 2d0a1a1869e601dc0d50a86a89fe98edcbd24f09 - Author: aycabta - Date: 2019-11-27 11:58:38 +0900 - - Fix ghost method line no - -commit f9debf343788a6460e1e67bd7efc470d73e69f21 - Author: Jeremy Evans - Date: 2019-11-28 08:13:35 +0900 - - Update documentation for ruby2_keywords [ci skip] - -commit 416cccc6ec4fde7220edbf848424514f5d5b5743 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-27 19:09:47 +0900 - - Drop windows-2016 on GitHub Actions - - https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners#windows-server-2016 - > Note: The Windows Server 2016 virtual environment will be removed on December 3, 2019. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2704 - -commit cdcaf041127430b30ee4b32452762666495a732a - Author: git - Date: 2019-11-28 03:03:51 +0900 - - * 2019-11-28 [ci skip] - -commit 299a13612e54accd9d3661bafde8f67142a78d54 - Author: Jeremy Evans - Date: 2019-11-28 02:03:00 +0900 - - Don't modify rest array when using ruby2_keywords - - Previously, the rest array was modified, but it turns out that is - not necessary. Not modifying the rest array fixes cases when the - rest array is used more than once. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2706 - -commit 6f27fa4f7d52bfaea4fd1bd7605bda28e302e74c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-27 14:42:30 +0900 - - prefer class_serial over m_tbl - - Decades ago, among all the data that a class has, its method - table was no doubt the most frequently accessed data. Previous - data structures were based on that assumption. - - Today that is no longer true. The most frequently accessed field - moved to class_serial. That field is not always as wide as VALUE - but if it is, let us swap m_tbl and class_serial. - - Calculating ------------------------------------- - ours trunk - Optcarrot Lan_Master.nes 47.363 46.630 fps - - Comparison: - Optcarrot Lan_Master.nes - ours: 47.4 fps - trunk: 46.6 fps - 1.02x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/2701 - -commit 177bc652a8110c1350c0e6df8cb17158e44e18dd - Author: git - Date: 2019-11-27 03:57:46 +0900 - - * 2019-11-27 [ci skip] - -commit a3e6f52c17061f012c4e638b3343b57752ed7603 - Author: Koichi Sasada - Date: 2019-11-26 12:20:53 +0900 - - rename __builtin_inline!(code) and introduce others. - - rename __builtin_inline!(code) to __builtin_cstmt(code). - Also this commit introduce the following inlining C code features. - - * __builtin_cstmt!(STMT) - - (renamed from __builtin_inline!) - - Define a function which run STMT implicitly and call this function at - evatuation time. Note that you need to return some value in STMT. - If there is a local variables (includes method parameters), you can - read these values. - - static VALUE func(ec, self) { - VALUE x = ...; - STMT - } - - Usage: - def double a - # a is readable from C code. - __builtin_cstmt! 'return INT2FIX(FIX2INT(a) * 2);' - end - - * __builtin_cexpr!(EXPR) - - Define a function which invoke EXPR implicitly like `__builtin_cstmt!`. - Different from cstmt!, which compiled with `return EXPR;`. - (`return` and `;` are added implicitly) - - static VALUE func(ec, self) { - VALUE x = ...; - return EXPPR; - } - - Usage: - def double a - __builtin_cexpr! 'INT2FIX(FIX2INT(a) * 2)' - end - - * __builtin_cconst!(EXPR) - - Define a function which invoke EXPR implicitly like cexpr!. - However, the function is called once at compile time, not evaluated time. - Any local variables are not accessible (because there is no local variable - at compile time). - - Usage: - GCC = __builtin_cconst! '__GNUC__' - - * __builtin_cinit!(STMT) - - STMT are writtein in auto-generated code. - This code does not return any value. - - Usage: - - __builtin_cinit! '#include ' - def no_compression? - __builtin_cconst! 'Z_NO_COMPRESSION ? Qtrue : Qfalse' - end - -commit 9e01fcd0cb79a05daa50d99c888cc7eeb9c79426 - Author: Nobuyoshi Nakada - Date: 2019-11-26 22:54:35 +0900 - - [ripper] Fixed unique key check in pattern matching - - Check keys - * by an internal table, instead of unstable dispatched results - * and by parsed key values, instead of escaped forms in the source - -commit 22dfd14c179632d773b97e708255b6c183a740aa - Author: Nobuyoshi Nakada - Date: 2019-11-26 15:40:34 +0900 - - Hoisted out `push_pvtbl`/`pop_pvtbl` - -commit 497f13aea6bae0e2443f21b4eb35fee9df3424d7 - Author: Nobuyoshi Nakada - Date: 2019-11-26 15:33:40 +0900 - - Wrap `p_kw` in an array at `p_kwarg` - - Not in `p_kw` itself, which makes key and variable/expr pair only - now. - -commit 265b5382b21db28e52d0314ef47025f881dcbf0f - Author: Nobuyoshi Nakada - Date: 2019-11-26 14:00:08 +0900 - - Allow `$10` and more in the Ripper DSL - -commit 7db719c51652f0de6cae079c6ce0723dd00a9939 - Author: Nobuyoshi Nakada - Date: 2019-11-26 19:08:56 +0900 - - Write rbinc files to the source directory - - Update the target file itself of the dependency on this script. - Fall back to the current working directory if unwritable. - -commit 8b208293963cafa1469947a9957b59ce68895af1 - Author: aycabta - Date: 2019-11-26 19:07:29 +0900 - - Remove an unnecessary variable - -commit 82525fcce192aa5582480164f5c109f9f2fe621b - Author: Hiroshi SHIBATA - Date: 2019-11-26 18:25:56 +0900 - - Add sync task for ruby/openssl - -commit 1fe31737d826bcc0a875419f5451679ae7ec04eb - Author: Takashi Kokubun - Date: 2019-11-26 18:20:19 +0900 - - Slightly fix the warning message [ci skip] - - I'm not sure, but maybe it was grammatically incorrect? - -commit 958641d9919f19a1e37c633e9dc44d2986904628 - Author: Takashi Kokubun - Date: 2019-11-26 18:17:56 +0900 - - Suggest an alternative to suppress the irb warning - -commit 5a6e3e7552382a4863ef5a8833798edb22abb3c7 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-26 16:19:18 +0900 - - Add `--with-openssl-dir` to windows on GitHub Actions - - https://github.com/ruby/ruby/commit/7bd7a013b14fb6c4403ff243ec5db13c5c71f552/checks?check_suite_id=328682567#step:10:1634 - ``` - *** Following extensions are not compiled: - openssl: - Could not be configured. It will not be installed. - " d:/a/ruby/ruby/src/ext/openssl/extconf.rb:97: OpenSSL library could not be found. You might want to use --with-openssl-dir= option to specify the prefix where OpenSSL is installed." - ``` - -commit 307e899d78057f7b5b504034eea103f4a8a89ba3 - Author: git - Date: 2019-11-26 11:46:22 +0900 - - * 2019-11-26 [ci skip] - -commit 7bd7a013b14fb6c4403ff243ec5db13c5c71f552 - Author: NAKAMURA Usaku - Date: 2019-11-26 11:44:11 +0900 - - Fix `$(RMALL) -r` on Windows - - `set recursive=1 &` sets `1 ` to `recursive`, not `1`. - -commit 26625bc33c32e0945bf727234a3ce6da1eb0ddc4 - Author: Nobuyoshi Nakada - Date: 2019-11-19 17:17:00 +0900 - - [ripper] Quoted label without expression must be a local variable - - The difference from 0b8c73aa65add5c57b46b0cfdf4e661508802172 is to - add the result of `string_add` event to marking objects. - - ```C - RNODE($1)->nd_rval = add_mark_object(p, $$); - ``` - -commit 86461fc28cd9c05670ece440d337f255b33e6def - Author: Nobuyoshi Nakada - Date: 2019-11-25 16:52:50 +0900 - - lldb_cruby.py: improved dump of Symbol - - [ci skip] - -commit 09e76e982801a838688ea80be29844ed91c23f46 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-25 15:05:53 +0900 - - Improve consistency of bool/true/false - -commit e27acb61485189fd7647741b6ca19920989dec03 - Author: Koichi Sasada - Date: 2019-11-25 14:02:15 +0900 - - add fast path for argc==0. - - If calling builtin functions with no arguments, we don't need to - calculate argv location. - -commit 5c6235a83cc6a20c27f3e3a94381b4efcad4c3fc - Author: Kazuhiro NISHIYAMA - Date: 2019-11-25 12:10:05 +0900 - - Set TRUE/FALSE to `bool ruby_tz_uptodate_p` instead of 1/FALSE - -commit 714a0cefc10b8f0a2a89e6cfb06723d72f2a5b99 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-25 10:54:09 +0900 - - Fix a typo [ci skip] - -commit a5f0d1d71598451dd8461ba52a3a143cb33afdd3 - Author: Junichi Ito - Date: 2019-11-25 10:16:59 +0900 - - Remove duplicated line in NEWS [ci skip] - - [ruby-core:95935] [Misc #16365] - -commit 9af52c0d099083fb6b56f39584a0909baa9e7a10 - Author: Nobuyoshi Nakada - Date: 2019-11-25 09:19:42 +0900 - - lldb_cruby.py: fixed dump of embedded RArray - - [ci skip] - -commit ce50af21af3d23e292b73f955a8b12ea9c2038e3 - Author: PaweÅ‚ Przeniczny - Date: 2019-11-25 07:08:16 +0900 - - Fix the docs for Proc#>>. - - The docs are wrong about the behaviour of `#>>` (looks like it was copied from `#<<`) - In `(prc >> g).call(n)` _prc_ is called first (with _n_), *then* _g_ is called with the result. - - Code examples are OK. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2691 - -commit fd956c72eaeb07d26d61310a9e4b55b500237c02 - Author: aycabta - Date: 2019-11-25 07:27:15 +0900 - - Cache loaded module to suppress method redefined warnings - -commit 90872520674dcc070d693430ee139042ba514591 - Author: git - Date: 2019-11-25 06:50:27 +0900 - - * 2019-11-25 [ci skip] - -commit 51ea1abb5f2ed70387dda28a5d0d9ee817367d61 - Author: aycabta - Date: 2019-11-25 05:38:09 +0900 - - Remove e2mmap dependency - -commit efbca15116d4aea1588c6ba4ef0eb72c3c55c1db - Author: aycabta - Date: 2019-11-25 03:10:35 +0900 - - Remove lib/irb/slex.rb - -commit 1aeb201d28ae2a10f7856be72ac6d705982b67ab - Author: aycabta - Date: 2019-11-24 23:29:09 +0900 - - Remove debug code... - -commit 411644186b3bc9515fe7f60627bc1dea5d89cc36 - Author: git - Date: 2019-11-24 23:15:25 +0900 - - * 2019-11-24 [ci skip] - -commit 745ab168185fc8f3c9d9dbd3a2355738776aee6d - Author: aycabta - Date: 2019-11-24 22:42:08 +0900 - - Disable tracer ext of IRB when tracer doesn't found - -commit b563439274a402e33541f5695b1bfd4ac1085638 - Author: Nobuyoshi Nakada - Date: 2019-11-23 16:00:39 +0900 - - Show include directive differences only when under git - - When building from tarballs, the source directory is not a git - repository. - -commit 9318e1ff3e700250dba277924672634c6ecf2940 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-23 11:41:27 +0900 - - Use realpath to try to fix failures with symlinks - -commit 818708edab6e950a8c1828816b73d36f05585f9f - Author: Takashi Kokubun - Date: 2019-11-23 07:22:33 +0900 - - Stop using undefined matrix.os for macOS - - and use github.workflow instead. Applied a similar change to MJIT too. - -commit b0614a0f968d40fb1bad31592fc9a607dbac447d - Author: aycabta - Date: 2019-11-23 05:44:35 +0900 - - Tracer.set_get_line_procs should support block and Proc object - - Original Tracer.set_get_line_procs is implemented by - "def set_get_line_procs(p = proc)". It means that original - Tracer.set_get_line_procs supports block and Proc object. - -commit 1ee010a3171978007a4550e8077f1e4b646bd80a - Author: aycabta - Date: 2019-11-23 05:20:23 +0900 - - Tracer.add_filter should support block and Proc object - - Original Tracer.add_filter is implemented by "def add_filter(p = proc)". It - means that original Tracer.add_filter supports block and Proc object. - -commit 8e743fad4e9124bd59bb5f14473cb188db9d3c34 - Author: John Hawthorn - Date: 2019-11-22 04:05:48 +0900 - - Count pinned slots using only bitmap - - This is significantly faster than checking BUILTIN_TYPEs because we - access significantly less memory. We also use popcount to count entire - words at a time. - - The only functional difference from the previous implementation is that - T_ZOMBIE objects will no longer be counted. However those are temporary - objects which should be small in number, and this method has always been - an estimate. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2688 - -commit 26fd8d962ce42b7eb8d1c1eb43ddfa1ff24dc3aa - Author: John Hawthorn - Date: 2019-11-21 07:18:40 +0900 - - Optimize pinned page sorting - - Previously we would count the pinned objects on each comparison. Since - sorting is O(N log N) and we calculated this on both left and right - pages on each comparison this resulted in a extra iterations over the - slots. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2688 - -commit 3f4199b0af791572b7abf63f33bb3b0b9b53d08f - Author: John Hawthorn - Date: 2019-11-21 07:07:20 +0900 - - Use value of use_verifier in gc_compact - - Notes: - Merged: https://github.com/ruby/ruby/pull/2688 - -commit 144bff43fc0b69361f6aa29448d24dd161b7d359 - Author: git - Date: 2019-11-23 01:58:08 +0900 - - * 2019-11-23 [ci skip] - -commit 271cb9acd268c6074b86426e25ee61b5987e5fb3 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-23 01:55:29 +0900 - - Suppress git error message - - `fatal: not a git repository (or any of the parent directories): .git` - -commit d7f100226d41df364b048c7956b5140922970e9a - Author: Kazuhiro NISHIYAMA - Date: 2019-11-23 01:29:53 +0900 - - Skip test_validate_gemspec when tarball and git installed too - - `git --version` failed as expected when git is not installed, - but unexpectedly pass when git installed and pwd is not in git working directory. - So use `git rev-parse` instead, and it failed when git installed too. - -commit 053f78e13988e9253d1f207bf5e23d9505112b32 - Author: Yusuke Endoh - Date: 2019-11-22 23:56:18 +0900 - - internal.h: Add a prototype declaration for rb_gvar_readonly_setter - - emscripten fails to compile ruby due to lack of this. - -commit 994435d0efa9931d0475de923c4e6c227d03e398 - Author: Vít Ondruch - Date: 2019-11-22 17:47:30 +0900 - - Revert "Update dependencies" - - This reverts commit e1b234148829f65bea9f5ecc7018beb782ea6023. - - This allows to build Psych against system libyaml again on Fedora. - - [Bug #16359] - -commit 35608760ffae00e0daebecd260191019a9b32648 - Author: NARUSE, Yui - Date: 2019-11-22 19:05:58 +0900 - - Add github repo to remove_tag - -commit a93d0a4e62c50a53ccdc3b2bc114f75a25bfc40f - Author: Nobuyoshi Nakada - Date: 2019-11-22 18:39:39 +0900 - - Check -1 arity for C++ - -commit f9d20a1bf157885975aacffdcb22f2b210f1258d - Author: git - Date: 2019-11-22 13:58:32 +0900 - - * 2019-11-22 [ci skip] - -commit 8eb0a9e5668032e750b91739cc40f3180278728d - Author: Kazuhiro NISHIYAMA - Date: 2019-11-22 13:55:59 +0900 - - Use jsDelivr instead of raw.githubusercontent.com - - Try to fix download error on Solaris CI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20191121T162422Z.fail.html.gz - ``` - tool/downloader.rb:243:in `rescue in download': failed to download config.guess (RuntimeError) - Net::HTTPFatalError: 503 "Service Unavailable": https://raw.githubusercontent.com/gcc-mirror/gcc/master/config.guess - ``` - -commit 88d6009d91c197049da9d6efeb406aec5eb5d551 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-21 23:10:30 +0900 - - Use more strict regexp to avoid to match naninanirb.rb - -commit ffab1bfdfcb9f1448c063e93f04209c90327ad9c - Author: Nobuyoshi Nakada - Date: 2019-11-21 15:17:34 +0900 - - Fixed for old git - -commit 97a5af62a318fcd93a4e5e4428d576c0280ddbae - Author: Nobuyoshi Nakada - Date: 2019-11-21 10:57:36 +0900 - - Skip updating revision.h when the revision is unchanged - - note: GNU make only. - -commit a9d4f2d03c847ec1c89dc03a5076a9fa29ffa61f - Author: Jeremy Evans - Date: 2019-06-22 02:33:06 +0900 - - Support %U/%u/%W/%w/%V/%g/%G formats in Time.strptime - - Most of these formats were documented as supported, but were not - actually supported. Document that %g and %G are supported. - - If %U/%W is specified without yday and mon/mday are not specified, - then Date.strptime is used to get the appropriate yday. - - If cwyear is specifier without the year, or cwday and cweek are - specified without mday and mon, then use Date.strptime and convert - the resulting value to Time, since Time.make_time cannot handle - those conversions - - Fixes [Bug #9836] - Fixes [Bug #14241] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2685 - -commit 8f1062127e40767240aa0a0fe18fd48687bc04e9 - Author: aycabta - Date: 2019-11-21 07:28:18 +0900 - - Add test/reline/test_string_processing.rb - -commit 9131e62f1862a1736d37d934cda603dc91b2c831 - Author: aycabta - Date: 2019-11-21 07:05:27 +0900 - - [ruby/reline] Version 0.0.7 - - https://github.com/ruby/reline/commit/09d370bdc19e62f0a27c2240e19b07963afd922f - -commit f30f78e2e054d72d4997db8c14eda81479270ee8 - Author: aycabta - Date: 2019-11-21 05:21:31 +0900 - - Version 0.0.6 - -commit e4127cdd3e2597d1814c59cb842d4dff0ba73921 - Author: aycabta - Date: 2019-11-21 05:25:01 +0900 - - Version 1.1.0 - -commit 95f20f463aa07fbb2e5efbdb89a93d94861cdc49 - Author: aycabta - Date: 2019-11-21 07:00:01 +0900 - - Consider escape sequence to calculate prompt width - -commit 1197a036ae1c48ac0842bb2a0dc8af213def47d7 - Author: Koichi Sasada - Date: 2019-11-21 04:37:29 +0900 - - Add a proper cast to pass JIT tests on mswin. - - https://ci.appveyor.com/project/ruby/ruby/builds/29001248/job/ye80bsrmewdgw294 - -commit eee70b41d4c04caa06a68cc4847a600eb7322cb8 - Author: aycabta - Date: 2019-11-21 02:44:15 +0900 - - Add a warning message and --legacy of an alias of --singleline - -commit 9d6f78822c61348989802848150f103f0a4ef7d0 - Author: Y. Ushiki - Date: 2019-10-30 08:49:03 +0900 - - Refactor filter_backtrace - -commit 04d0d93ebf8692170218fa9d55216aaca74be30b - Author: Y. Ushiki - Date: 2019-10-30 08:43:19 +0900 - - Fix filter_backtrace for context-mode 0 - -commit 91bf3b7a77e187794cc84549f330e5675fb5d367 - Author: aycabta - Date: 2019-10-30 09:32:16 +0900 - - Use singleline/multiline instead of readline/reidline - -commit 9b52bacc62c3db13ea18fa5ea4d9b9a92b5fcb86 - Author: Nobuyoshi Nakada - Date: 2019-11-21 02:14:20 +0900 - - Refined inspection of argument forwarding - -commit f835a74da45f95073d12f84c3b8de9fb2f1e9ff6 - Author: git - Date: 2019-11-21 00:48:59 +0900 - - * 2019-11-21 [ci skip] - -commit 6723aa07e591a13996b5af205c589200d44c5249 - Author: manga_osyo - Date: 2019-11-20 09:13:42 +0900 - - Change argument `Proc` to `#call` defined object. - This is the same as the behavior of Readline. - -commit 81586a4d9fd6afe1c39f737a704c5010faf22192 - Author: manga_osyo - Date: 2019-11-16 11:13:19 +0900 - - Add keys. - -commit 777973084e599cf9efa490173709b187fb507f90 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-20 17:56:59 +0900 - - Add tests of argument forwarding's parameters and inspect - -commit 633625a083c5f02e78355cb12818056e54330e88 - Author: aycabta - Date: 2019-11-20 17:55:03 +0900 - - Mintty on Cygwin isn't a kind of command prompt, can process ANSI escape code - -commit ae818b589efcb5dca47d9ceb888cb658ef56e286 - Author: Koichi Sasada - Date: 2019-11-20 17:21:38 +0900 - - add a NEWS entry for Method#inspect - -commit fc22b0eaa3fa073f622917364cbb573cd6ba2bfc - Author: Nobuyoshi Nakada - Date: 2019-11-20 16:27:57 +0900 - - Always forward declaration is needed - - `rb_resolve_refined_method_callable` is referenced in - `refine_sym_proc_call`, even when pre-compiling mjit header on - mswin. - -commit 83900528ad6a2cf37360abe2bcebb16787177838 - Author: Nobuyoshi Nakada - Date: 2019-11-20 16:23:59 +0900 - - Turn C4047 warning into error - - Warned at making precompiled header on mswin. - - ``` - building rb_mjit_header-2.7.0.pch - vm.c - d:\a\ruby\ruby\src\vm_args.c(1117): warning C4047: '=': 'const rb_callable_method_entry_t *' differs in levels of indirection from 'int' - rb_mjit_header-2.7.0.pch updated - ``` - -commit 7608baf92ae2f3b29786e7fca021c8c8d24016f8 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-20 15:51:10 +0900 - - re-add function prototypes - - This commit reverts a part of 0e8219f591f3f17cb7ee361e8a60dbef08145883 - which broke icc. See also https://rubyci.org/logs/rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20191120T010006Z.fail.html.gz - -commit f90b22e3dc99fd8eff2235e847e52266d20e8488 - Author: Nobuyoshi Nakada - Date: 2019-11-20 15:37:05 +0900 - - Revert the line for nextafter.c for FreeBSD make - -commit 50cc9341450cfbdf9a40df3d38600d8d2854a0a3 - Author: zverok - Date: 2019-11-20 09:33:20 +0900 - - Update representation (discussed on ruby tracker) - - Notes: - Merged: https://github.com/ruby/ruby/pull/2618 - -commit baf482bab4776f781c3569d9f581e38bbf0548e1 - Author: zverok - Date: 2019-10-27 20:32:17 +0900 - - Fix test_module.rb - - Notes: - Merged: https://github.com/ruby/ruby/pull/2618 - -commit 4b583cff97025394fab4a014a2a8606dfb557475 - Author: zverok - Date: 2019-10-27 19:39:33 +0900 - - Method parameters inspect - - Example: - - def m(a, b=nil, *c, d:, e: nil, **rest, &block) - end - p method(:m) - #=> #, *c, d:, e: , **rest, &block) ...> - - Notes: - Merged: https://github.com/ruby/ruby/pull/2618 - -commit da0d7211aa85b90f2246e2d9abfe08105f7ddedb - Author: aycabta - Date: 2019-11-20 10:04:41 +0900 - - Fix indent of a line when a newline is inserted to the next - -commit 9306602f24e5c9be4cdae5ed7e69e746ae9e175e - Author: aycabta - Date: 2019-11-20 09:58:33 +0900 - - Replace typo "bock" with "block" - -commit 19a310b0ac6bfc78340d37963ea2655783760bee - Author: aycabta - Date: 2019-11-20 09:56:13 +0900 - - A preceding token of "do" of block has EXPR_CMDARG or EXPR_ENDFN - - meth do # the preceding token of "do" has EXPR_CMDARG - end - - meth() do # the preceding token of "do" has EXPR_ENDFN - end - -commit 49b4507fd3caed356e4039da5820a7c843c6b05a - Author: aycabta - Date: 2019-11-20 08:39:43 +0900 - - Number sign comment (# bla bla) is a kind of newline character - -commit bc0da8e3ff409f09888ffe98e6e66b503ebc8083 - Author: aycabta - Date: 2019-11-19 20:58:11 +0900 - - Generate history file path correctly when $HOME/.irbrc doesn't exist - -commit ff41663403d3eb76d95f465cb94e14d2faaa04d1 - Author: Kazuki Tsujimoto - Date: 2019-11-20 00:35:47 +0900 - - Fix memory corruption in Enumerable#reverse_each [ruby-dev:50867] [Bug #16354] - -commit 61131edba7c885a6d12c4d6f0e502fb40381f184 - Author: Nobuyoshi Nakada - Date: 2019-11-20 00:55:14 +0900 - - Revert "[ripper] Quoted label without expression must be a local variable" - - This reverts commit 0b8c73aa65add5c57b46b0cfdf4e661508802172, which - seems breaking RVALUE consistency check. - -commit f3c9803528d429a7b5e47f400caa33dfadd94da7 - Author: git - Date: 2019-11-20 00:07:26 +0900 - - * 2019-11-20 [ci skip] - -commit 2439948bcc0ec9daf91cf79301195e59bad49aff - Author: Kazuki Tsujimoto - Date: 2019-11-19 23:53:01 +0900 - - Avoid needless object allocation - -commit 822d7ae31659e4ab60c4d1aa6d088577d6bc74b0 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-19 17:34:43 +0900 - - Add a test - - and rename from b.rb - - [ruby-core:95055] [Bug #16177] - -commit 0b8c73aa65add5c57b46b0cfdf4e661508802172 - Author: Nobuyoshi Nakada - Date: 2019-11-19 17:17:00 +0900 - - [ripper] Quoted label without expression must be a local variable - -commit a5fe08fdd9d11f12a6837291ee588ab933a823b6 - Author: Koichi Sasada - Date: 2019-11-19 16:56:56 +0900 - - care about TAG_FATAL. - - TAG_FATAL represents interpreter closing state and ec->errinfo - contains FIXNUM (eTerminateSignal, etc). If we need to change the - state, then errinfo is also changed because TAG_RAISE assumes that - ec->errinfo contains a Exception object. - - Without this patch, TAG_FATAL is ignored and no ec->errinfo change - so that it causes critical issue. - [Bug #16177] - -commit c53aec73ddf94bb9a06bead62c3bf58c5ba49bd3 - Author: Nobuyoshi Nakada - Date: 2019-11-19 15:06:11 +0900 - - Configure static extensions only if in charge - - Get rid of races in parallel configuration when using the - ext/Setup file. - -commit f6239ce0fc906c9d407e7da33f447575670a79bd - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-19 13:16:04 +0900 - - peep-hole optimize VM instructions - - Some minor optimizations. - - Calculating ------------------------------------- - ours trunk - vm2_regexp 8.479M 8.346M i/s - 6.000M times in 0.707612s 0.718916s - vm2_regexp_invert 8.605M 8.350M i/s - 6.000M times in 0.697298s 0.718576s - - Comparison: - vm2_regexp - ours: 8479223.3 i/s - trunk: 8345893.8 i/s - 1.02x slower - - vm2_regexp_invert - ours: 8604647.4 i/s - trunk: 8349852.8 i/s - 1.03x slower - - Calculating ------------------------------------- - ours+jit trunk+jit - Optcarrot Lan_Master.nes 68.603 64.167 fps - - Comparison: - Optcarrot Lan_Master.nes - ours+jit: 68.6 fps - trunk+jit: 64.2 fps - 1.07x slower - -commit 75e8dd58f69c190c9698d0133942032903fb2f07 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-19 13:06:00 +0900 - - Remove TEST_BUNDLED_GEMS_ALLOW_FAILURES - - https://github.com/seattlerb/minitest/pull/798 is closed - -commit 0e8219f591f3f17cb7ee361e8a60dbef08145883 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-18 12:13:08 +0900 - - make functions static - - These functions are used from within a compilation unit so we can - make them static, for better binary size. This changeset reduces - the size of generated ruby binary from 26,590,128 bytes to - 26,584,472 bytes on my macihne. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2682 - -commit 78e266da1dede1c81e634982e76a129c5720d80e - Author: Samuel Williams - Date: 2019-11-19 11:40:00 +0900 - - Clarify documentation for `InstructionSequence#compile`. - - We incorrectly assumed that the `file` argument should be the file name and - caused https://github.com/scoutapp/scout_apm_ruby/issues/307 because - exception backtrace did not contain correct path. This documentation - clarifies the role of the different arguments and provides extra - examples. - -commit cef9ebfbd3565f9feb25d0140da3176ea26bf4a9 - Author: Nobuyoshi Nakada - Date: 2019-11-13 15:28:12 +0900 - - Suppress `stty` error on Apple Terminal - - `stty` called in `Reline::ANSI.deprep` command shows the following - error message on macOS Apple Terminal, with some settings. - - ``` - $ LANG=C irb - irb(main):001:0> - stty: 'standard input': unable to perform all requested operations - stty: 'standard input': unable to perform all requested operations - ``` - -commit 473e314791964019e017410fb761b873d61e591c - Author: Nobuyoshi Nakada - Date: 2019-11-13 15:22:39 +0900 - - Prefer dedecated assertions - -commit 0be0d90ab0566df186ad7dc3b9e5ec9e06e296a3 - Author: Takashi Kokubun - Date: 2019-11-19 02:31:36 +0900 - - pack is not using invokebuiltin anymore - -commit fea24bbfdbe17da1038355fe7e0f7063f8c26c87 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-18 23:41:26 +0900 - - Fix glob base in bundler.gemspec - - Notes: - Merged: https://github.com/ruby/ruby/pull/2683 - -commit 9aa75795f9f438d5c874d8e418c3c7cdd63024fa - Author: Kazuhiro NISHIYAMA - Date: 2019-11-18 23:39:57 +0900 - - Skip some tests if extracted from tarball - - Notes: - Merged: https://github.com/ruby/ruby/pull/2683 - -commit e9992bcab03b1646d18b4a417643273a7bbb6158 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-18 23:36:51 +0900 - - Allow unknown if ruby core - - Notes: - Merged: https://github.com/ruby/ruby/pull/2683 - -commit 9067f43c0ae6d42222a0dd2cd55380b11343ddd1 - Author: git - Date: 2019-11-19 00:27:05 +0900 - - * 2019-11-19 [ci skip] - -commit 0c0278b90a6fe1e71e0e5c27069b8b2976e2a7cf - Author: Yusuke Endoh - Date: 2019-11-19 00:25:49 +0900 - - test/-ext-/string/test_fstring.rb: suppress a warning for taint - -commit 373769c93995abeeb546bdcd9e6527c77aefa1d4 - Author: Yusuke Endoh - Date: 2019-11-19 00:12:50 +0900 - - NEWS: Add an example for the warning of "yield in singleton class" - -commit f09fc1b0344e65aeb9c11aaeb23c99954265fe4d - Author: Nobuyoshi Nakada - Date: 2019-11-18 23:14:13 +0900 - - Dependents on probes.h need the dummy header too - -commit e1b234148829f65bea9f5ecc7018beb782ea6023 - Author: Nobuyoshi Nakada - Date: 2019-08-07 23:22:06 +0900 - - Update dependencies - -commit 39492d6ce6ee11cbb275dc6f48c73de93f8549ce - Author: Nobuyoshi Nakada - Date: 2019-08-10 00:02:17 +0900 - - Build ruby-runner - -commit 227220b25aad9841eb979c18a0251b71de824e88 - Author: Nobuyoshi Nakada - Date: 2019-08-10 00:02:17 +0900 - - Skip dependencies on timestamp files - -commit 209164e44f0bd0bbd938bf726e88d0dd29f84d55 - Author: Nobuyoshi Nakada - Date: 2019-11-18 18:42:22 +0900 - - Renamed assembly file like as e64f71f812324d098bed12ed68c2bc1d6e780c90 - -commit 7a9b2039b7b82f081f2cab40a4fbbc8b01231ca4 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-18 12:00:19 +0900 - - delete unused codes - - Suppress compiler warnings. - -commit 57cd4623cfb56d12eb308eaf5fb09612e4572c19 - Author: Koichi Sasada - Date: 2019-11-18 13:36:34 +0900 - - should not use __func__ - -commit 22c9504905114cfb58ebc0aa631200f0caafd4e0 - Author: Nobuyoshi Nakada - Date: 2019-11-18 11:05:08 +0900 - - rb_tainted_str_new_with_enc is no longer used - -commit 5e34ab5406942d43b4c0fbccfc153409d0386d1e - Author: Koichi Sasada - Date: 2019-11-18 10:36:48 +0900 - - add casts. - - add casts to avoid compile error. - http://ci.rvm.jp/results/trunk_clang_39@silicon-docker/2402215 - -commit c3693bbaaa39d36210060fb4478751d66c0052ad - Author: Koichi Sasada - Date: 2019-11-18 10:24:38 +0900 - - catch up last commit. - - Array#pack uses `opt_invokebuiltin_delegate_leave` now. - -commit 71fee9bc720ba7a117062bf3f78b6086527b656c - Author: Koichi Sasada - Date: 2019-11-15 17:49:49 +0900 - - vm_invoke_builtin_delegate with start index. - - opt_invokebuiltin_delegate and opt_invokebuiltin_delegate_leave - invokes builtin functions with same parameters of the method. - This technique eliminate stack push operations. However, delegation - parameters should be completely same as given parameters. - (e.g. `def foo(a, b, c) __builtin_foo(a, b, c)` is okay, but - __builtin_foo(b, c) is not allowed) - - This patch relaxes this restriction. ISeq has a local variables - table which includes parameters. For example, the method defined - as `def foo(a, b, c) x=y=nil`, then local variables table contains - [a, b, c, x, y]. If calling builtin-function with arguments which - are sub-array of the lvar table, use opt_invokebuiltin_delegate - instruction with start index. For example, `__builtin_foo(b, c)`, - `__builtin_bar(c, x, y)` is okay, and so on. - -commit 93ce4f1cd7c96f0fdbeebc87a9fa64d07cede729 - Author: Koichi Sasada - Date: 2019-11-18 10:14:56 +0900 - - update deps. - - https://travis-ci.org/ruby/ruby/jobs/613242256#L2205 - -commit b753929806d0e42cdfde3f1a8dcdbf678f937e44 - Author: git - Date: 2019-11-18 08:00:52 +0900 - - * remove trailing spaces. [ci skip] - -commit 4c7dc9fbe604cc0c8343b1225c96d4e5219b8147 - Author: Jeremy Evans - Date: 2019-11-15 05:15:01 +0900 - - Update NEWS for $SAFE/taint changes - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 3a0de05beeb997ec77d35755d9d303e1ca858cb7 - Author: Jeremy Evans - Date: 2019-10-05 00:44:33 +0900 - - Remove mention of $SAFE and taint from doc [ci skip] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit c257303ae78d0e307a80dbe5ccd405abc6e8d44d - Author: Jeremy Evans - Date: 2019-09-26 07:49:21 +0900 - - Deprecate rb_eval_cmd, add rb_eval_cmd_kw - - rb_eval_cmd takes a safe level, and now that $SAFE is deprecated, - it should be deprecated as well. - - Replace with rb_eval_cmd_kw, which takes a keyword flag. Switch - the two callers to this function. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit d03da13b17484cb3f8697e9125e028eb65ef7a39 - Author: Jeremy Evans - Date: 2019-11-15 09:56:02 +0900 - - [ruby/strscan] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit afbd8f384a54b934debe6e48cfc299fb2c7669e9 - Author: Jeremy Evans - Date: 2019-10-19 04:28:44 +0900 - - [ruby/openssl] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 17e8a6eff4954a37966c10f35db6551fce1d80a7 - Author: Jeremy Evans - Date: 2019-10-19 04:25:15 +0900 - - [ruby/io-console] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 398cd3cc7dda375c2d21355057c11ecb4abeda70 - Author: Jeremy Evans - Date: 2019-10-19 04:10:03 +0900 - - [ruby/etc] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - Still untaint the tmpdir object on Ruby <2.7, as returning - a tainted string there could cause problems. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 23f1fb066303838a0d045b5981fe3c4ad077399e - Author: Jeremy Evans - Date: 2019-11-15 05:30:56 +0900 - - [ruby/rss] Only check taint on Ruby <2.7 - - Ruby 2.7 deprecates taint and it no longer has an effect. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 50013f7ebcafeea7f5163dc6ed1b1bf58c465ac7 - Author: Jeremy Evans - Date: 2019-10-19 03:33:09 +0900 - - [ruby/rexml] Only taint on Ruby <2.7 - - Ruby 2.7 deprecates taint and it no longer has an effect. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit ab42e5a486a5b27107296fa34056f03ac878e306 - Author: Jeremy Evans - Date: 2019-11-15 11:54:13 +0900 - - More fixes for $SAFE/taint post merging - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit ffd0820ab317542f8780aac475da590a4bdbc7a8 - Author: Jeremy Evans - Date: 2019-09-25 12:59:12 +0900 - - Deprecate taint/trust and related methods, and make the methods no-ops - - This removes the related tests, and puts the related specs behind - version guards. This affects all code in lib, including some - libraries that may want to support older versions of Ruby. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit c5c05460ac20abcbc0ed686eb4acf06da7a39a79 - Author: Jeremy Evans - Date: 2019-09-21 11:06:22 +0900 - - Warn on access/modify of $SAFE, and remove effects of modifying $SAFE - - This removes the security features added by $SAFE = 1, and warns for access - or modification of $SAFE from Ruby-level, as well as warning when calling - all public C functions related to $SAFE. - - This modifies some internal functions that took a safe level argument - to no longer take the argument. - - rb_require_safe now warns, rb_require_string has been added as a - version that takes a VALUE and does not warn. - - One public C function that still takes a safe level argument and that - this doesn't warn for is rb_eval_cmd. We may want to consider - adding an alternative method that does not take a safe level argument, - and warn for rb_eval_cmd. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2476 - -commit 7b6a8b5b54448235e17ed187d9d73f56893e1b6f - Author: git - Date: 2019-11-18 03:25:17 +0900 - - * 2019-11-18 [ci skip] - -commit 7c6bedfe5c8a3a36d79bdc63f04d7ccb0a82234e - Author: aycabta - Date: 2019-11-18 03:23:45 +0900 - - Remove unnecessary check - -commit e7c5c60095537dabda7be5102ae66bd39a1ad133 - Author: aycabta - Date: 2019-11-17 23:25:37 +0900 - - [ruby/irb] Remove ruby-token.rb from spec.files - - https://github.com/ruby/irb/commit/0180dc74bc - -commit be95d591609ffea7727628a8af6f4c0a6b75d849 - Author: aycabta - Date: 2019-11-17 23:11:58 +0900 - - [ruby/irb] Version 1.1.0.pre.4 - - https://github.com/ruby/irb/commit/4945d0e676 - -commit 910f9b833855089802ff86a2ca00d43c9a0b618c - Author: aycabta - Date: 2019-11-17 23:12:18 +0900 - - [ruby/reline] Version 0.0.5 - - https://github.com/ruby/reline/commit/d57c7ea252 - -commit a8e4a9f03ade7fd67fbd8ab1271750dd45eca282 - Author: git - Date: 2019-11-17 13:12:06 +0900 - - * 2019-11-17 [ci skip] - -commit 449b2b9214256b059ed883770222382d3bc90578 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-17 13:11:25 +0900 - - Fix typos - -commit 11ae47c2669b64b64e2b34dd6dff02e72fd60881 - Author: aycabta - Date: 2019-11-15 16:50:11 +0900 - - [ruby/reline] Restore left cursor key support on Unix like OSes... - - https://github.com/ruby/reline/commit/98b72af751 - -commit fa7618e4c1b382cb5863161017ef89116af3e24f - Author: aycabta - Date: 2019-11-15 16:50:11 +0900 - - Implement em_set_mark and em_exchange_mark - -commit 6744593b8cd836967b40a4d76a9ac301b9e0f973 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-15 11:01:06 +0900 - - Fix a typo [ci skip] - -commit 018be445e9e9061364e8ba20dee9d25cb6f20e55 - Author: git - Date: 2019-11-15 03:56:58 +0900 - - * 2019-11-15 [ci skip] - -commit 9c1abe2a6c5e6288ed208000fbf811d145af9355 - Author: Koichi Sasada - Date: 2019-11-15 03:51:06 +0900 - - load prelude.rb by builtin features. - - The script in prelude.rb was embed in MRI to load it (eval this - script at everyboot). - This commit change the loading process of prelude.rb. MRI doesn't - eval a script, but load from compiled binary with builtin feature. - - So that Init_prelude() does not load `prelude.rb` now. - -commit c9ffe751d126a302d0e7e53e645e44084e339dde - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-13 12:41:39 +0900 - - delete unused functions - - Looking at the list of symbols inside of libruby-static.a, I found - hundreds of functions that are defined, but used from nowhere. - - There can be reasons for each of them (e.g. some functions are - specific to some platform, some are useful when debugging, etc). - However it seems the functions deleted here exist for no reason. - - This changeset reduces the size of ruby binary from 26,671,456 - bytes to 26,592,864 bytes on my machine. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2677 - -commit 4d615a0c8f4759ce4f6b96b643ef957837bdf20e - Author: Nobuyoshi Nakada - Date: 2019-11-14 16:37:25 +0900 - - `#@1` is no longer an embedded variable - -commit 703e05b0eee3017a63690155e55a97d678f073cb - Author: Hiroshi SHIBATA - Date: 2019-11-14 16:09:36 +0900 - - Added default gems entry to NEWS - -commit 3b614ec48a283e61334c70806f076cea3b2192ca - Author: Hiroshi SHIBATA - Date: 2019-11-14 16:07:48 +0900 - - Update RubyGems and Bundler entries on NEWS - -commit 48edaf8b8a03ef7a1c4f936c8c92e9dcf4271872 - Author: Yusuke Endoh - Date: 2019-11-14 13:00:25 +0900 - - test/ruby/test_proc.rb: suppress "method redefined" warnings - -commit 179062dd808c0a48e16269a2c42b10235cbbacd8 - Author: Koichi Sasada - Date: 2019-11-14 04:18:41 +0900 - - move rb_vm_lvar_exposed() correctly. - - rb_vm_lvar_exposed() is prepared for __builtin_inline!(), needed for - mini_builtin.c and builtin.c. However, it's only on builtin.c. - So move it to make it as a part of VM. - -commit a8f9e25ca8cc160683711baed00008461db2ad16 - Author: Takashi Kokubun - Date: 2019-11-14 02:37:25 +0900 - - Suspend many fibers test on JIT for now - - https://github.com/ruby/ruby/runs/301411717 - - No C backtrace information and this is hard to fix immediately. - As CI doesn't provide helpful information, this should be debugged - locally or at least have more logs there. - -commit afc93e96ffa93aa02b3e432037b3f88d002f5eea - Author: Takashi Kokubun - Date: 2019-11-14 02:30:53 +0900 - - Make GitHub Actions notification more like Travis - - Build's sequential number is a link in Travis, and also YYYY-MM-DD-XX is - a little hard to parse. - -commit a102bcab418dc61ccfe6a49870393c42305d2895 - Author: git - Date: 2019-11-14 01:48:41 +0900 - - * 2019-11-14 [ci skip] - -commit 3a408aff578bcde428ebdd4560d819c1ba792f2c - Author: Koichi Sasada - Date: 2019-11-14 01:48:08 +0900 - - try to remove vm_core.h - -commit 7f2c98b11d9eedd7028a1ccb2c1f88db71db28ca - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 19:56:33 +0900 - - Use shallow-since instead of depth - - commit number of today requires log since 0:00 UTC. - So commits of 24 hours are enough. - - https://www.git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt - > Implies --single-branch unless --no-single-branch is given to fetch the histories near the tips of all branches. - - So I add `--single-branch` too. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2680 - -commit 990728170c5e4d6b763fa42c48ce82473d753aad - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 19:49:07 +0900 - - Add commit number of today to notification of mjit CI too - - Notes: - Merged: https://github.com/ruby/ruby/pull/2679 - -commit e7ea6e078fecb70fbc91b04878b69f696749afac - Author: Nobuyoshi Nakada - Date: 2019-11-13 16:53:12 +0900 - - Check more likely condition first [Feature #16335] - -commit 3324bc9d172e52114add3a0cdd426b5648cdc33b - Author: Takashi Kokubun - Date: 2019-11-13 16:09:59 +0900 - - Skip tailcall test for MJIT - - failing in https://github.com/ruby/ruby/runs/300579218 - -commit bdf71a3ef032ed4675a6f3217cf5c9efb062c0b1 - Author: Takashi Kokubun - Date: 2019-11-13 16:04:25 +0900 - - Fix MJIT test's Slack notification - -commit 57dc3ff73dcc5ef5ca080e841db58862c89b03d8 - Author: Hiroshi SHIBATA - Date: 2019-11-13 13:34:06 +0900 - - Removed sync library from sync tool - -commit 7913daf36c25cefd66887993e0946c54b7d7d294 - Author: Dylan Thacker-Smith - Date: 2019-11-08 01:14:47 +0900 - - Add missing Makefile dependencies for the tool/insns2vm.rb script - - Notes: - Merged: https://github.com/ruby/ruby/pull/2657 - -commit ac112f2b5dc7e16ccde8f048be80946187a033b0 - Author: Dylan Thacker-Smith - Date: 2019-11-06 15:47:32 +0900 - - Avoid top-level search for nested constant reference from nil in defined? - - Fixes [Bug #16332] - - Constant access was changed to no longer allow top-level constant access - through `nil`, but `defined?` wasn't changed at the same time to stay - consistent. - - Use a separate defined type to distinguish between a constant - referenced from the current lexical scope and one referenced from - another namespace. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2657 - -commit a5b6d7bca84fce6e13c68e8753893c4697960e3a - Author: aycabta - Date: 2019-11-13 15:10:05 +0900 - - Suppress warnings except for when last evaluation - - Co-authored-by: Kazuhiro NISHIYAMA - -commit c33d29fba5a04bd31242eb51e54d2ec198c34ba3 - Author: Takashi Kokubun - Date: 2019-11-13 15:13:49 +0900 - - We're not using Azure Pipelines anymore - -commit dca2eb350c13de4446df92b958a40f14d67c97b8 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 15:11:34 +0900 - - Update badges of GitHub Actions - -commit d336db6568cc96dfee503c053e8f444dc7243858 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 15:04:49 +0900 - - Fix a typo - -commit 68ea892daf6e4073919d58ae83c7ff7389fbf184 - Author: Takashi Kokubun - Date: 2019-11-13 14:55:03 +0900 - - Remove obsoleted Wercker status badge - -commit 331655cbe7139a287267c90b3ab46ed856aebb5b - Author: Takashi Kokubun - Date: 2019-11-13 14:48:05 +0900 - - Migrate Wercker MJIT tests to Actions (#2676) - - * Migrate Wercker MJIT tests to Actions - - * Support pull request for testing - - * Capitalize other jobs too - - * Make it a command name for consistency [ci skip] - - * Remove wercker.yml - - * Add --jit-verbose=2 for debugging - - * Install MJIT headers - - * Separate install for sudo - - * Trigger build - - Notes: - Merged-By: k0kubun - -commit c4064aef7f48c51add6c24467da64528d5a2a2a5 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 13:22:46 +0900 - - Add commit number of today to notification of GitHub Actions - - Notes: - Merged: https://github.com/ruby/ruby/pull/2675 - -commit 245977b2861f5fa6a7341333ca9b1897e959489b - Author: Takashi Kokubun - Date: 2019-11-13 13:56:52 +0900 - - Stop debugging the same thing twice - - See L25-28 - -commit 9ee88a070f797d5eb9516c6a17359463fb5c37b9 - Author: Takashi Kokubun - Date: 2019-11-13 13:56:15 +0900 - - Remove MSPECOPT formerly for debugging - - At least the comment looks obsoleted. Aren't we using $JOBS already? - -commit 02b6451c17cf81d138cd653fa989080246a1a63a - Author: Takashi Kokubun - Date: 2019-11-13 13:44:00 +0900 - - Improve Actions job name shown on toolip - - Hoping to make it like `make (check, ...)`, `make (test-bundler, ...)` - instead of `latest (...)` because some of the jobs are already not - running on a latest platform. - -commit 3118c7a2d20c6894a53480501d53daa4e6d3a743 - Author: Takashi Kokubun - Date: 2019-11-13 13:38:05 +0900 - - Run test-bundler / test-bundled-gems for Ubuntu - - only once. Doing it on multiple Ubuntu versions may not worth it. - -commit 9980728ad61dc544d2ce5b981b54af36fa6e2a82 - Author: Takashi Kokubun - Date: 2019-11-13 13:22:33 +0900 - - Remove Drone CI in favor of Travis arm32 - -commit 3ad78264dc7e680a004a8ea1397d4ac9297134ba - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 13:13:52 +0900 - - Use style of set-env - - https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#set-an-environment-variable-set-env - -commit 546e50c2fb1fc749399b1a6cf3ce9e01c27b9398 - Author: Hiroshi SHIBATA - Date: 2019-11-13 10:35:52 +0900 - - Merge released version of RubyGems 3.1.0.pre3 - -commit 63f363b70dc08efd6b2d3f59183d4de1e882ef81 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 10:31:02 +0900 - - Update dependencies - - patch from https://travis-ci.org/ruby/ruby/jobs/611152175#L2204 - -commit bb9ecd026a6cadd5d0f85ac061649216806ed935 - Author: Hiroshi SHIBATA - Date: 2019-11-13 07:57:02 +0900 - - Merge Bundler 2.1.0.pre3 released version - - Notes: - Merged: https://github.com/ruby/ruby/pull/2674 - -commit 00d56bdf66a3aeaadbc84196aacbd8d4e698cf79 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-13 09:55:54 +0900 - - Try to fix error on solaris - - Add vm_core.h before builtin.h to pack.c for VM_CORE_H_EC_DEFINED. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20191112T102505Z.fail.html.gz - ``` - compiling dmyenc.c - linking miniruby - Undefined first referenced - symbol in file - rb_vm_lvar_exposed pack.o - ld: fatal: symbol referencing errors - gmake: *** [miniruby] Error 2 - ``` - -commit ae33f93836b556f36d5ffc4a7bca2c1b379c56d8 - Author: Yuichiro Kaneko - Date: 2019-11-13 09:50:58 +0900 - - Update comment of Ripper.lex - - This is follow up of 1f7cb4bee9. - -commit 4bbfe1f7c42300e2212b8f6794d5254b4db8df1c - Author: Jun Aruga - Date: 2019-10-16 00:08:00 +0900 - - Add arm32 case on Travis. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2673 - -commit a5448c46bdde27cb5ba8a800b29a84ced8047e94 - Author: git - Date: 2019-11-13 02:29:13 +0900 - - * 2019-11-13 [ci skip] - -commit 4334c9315af972337fcad82c0056152c45808348 - Author: Takashi Kokubun - Date: 2019-11-07 02:10:27 +0900 - - Remove arm64 from allow_failures - - Notes: - Merged: https://github.com/ruby/ruby/pull/2672 - -commit bf34ade7ef32f89aa5ba238d0a780f23eacb0487 - Author: Nobuyoshi Nakada - Date: 2019-11-12 22:58:09 +0900 - - Show the name `Kernel#proc` in the warning message - -commit 3816622fbedd034d338fcb1bbdc80d163e302ae6 - Author: manga_osyo - Date: 2019-11-11 14:59:17 +0900 - - Fixed `assert_equal` first argument to be expected. - -commit fe45bee09312a233466171f40d6826e5e4f1f2f0 - Author: osyo-manga - Date: 2019-11-10 16:00:41 +0900 - - Reline#readline and Reline#readmultiline to private. - -commit f36a53d03821624d30b3e91a7a75307b06e3a03c - Author: Hiroshi SHIBATA - Date: 2019-11-12 15:44:19 +0900 - - Only enabled mon_owned condition with Ruby 2.5+ - -commit 3bf8ffad714efa98949e25095f1c5e2844318958 - Author: Nobuyoshi Nakada - Date: 2019-11-12 18:02:28 +0900 - - Added assertions for realpath and realdirpath - - It is said that realpath(3) and realdirpath(3) on some platforms - may return a relative path. - -commit 0f2837847d5bfb65d20a89d196393212635fbe9e - Author: Kazuhiro NISHIYAMA - Date: 2019-11-12 17:46:39 +0900 - - Add ticket number of `FrozenError#receiver` [ci skip] - -commit fb6a489af2765a3b56e301adf0019af6bbad6156 - Author: Nobuyoshi Nakada - Date: 2019-10-24 01:06:59 +0900 - - Revert "Method reference operator" - - This reverts commit 67c574736912003c377218153f9d3b9c0c96a17b. - [Feature #16275] - -commit b41a19f92fdd9c8567e0650ceebb72386a96e395 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-12 17:22:19 +0900 - - Add matrix.os to cache key (#2671) - - * Add matrix.os to cache key - * Use multi-line string instead of array - ref https://github.com/actions/cache/issues/44 - - Notes: - Merged-By: znz - -commit a58b4eee25b79432d98a1c665edaf5ec0a054b2e - Author: Nobuyoshi Nakada - Date: 2019-11-12 17:14:10 +0900 - - Warn on `...` at EOL - -commit d1ae2bc27fd4183e6abb9e83691e192bfe1e5316 - Author: Yusuke Endoh - Date: 2019-11-12 17:04:11 +0900 - - NEWS: Make it clear that delegation syntax `(...)` requires parentheses - - Ref [Feature #16253] - -commit fb02e3192cef96284501c82dfa024ea8a2b0ea80 - Author: Nobuyoshi Nakada - Date: 2019-11-12 16:35:01 +0900 - - Create `RUBYCOMMONDIR` directory in advance - - As well as the directory per architecture. - - Closes https://github.com/ruby/ruby/pull/2669 - -commit 14db635097ef89a299531770ba8ed5800a58ab8f - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-12 16:15:58 +0900 - - add NEWS about _1 as a local variable [ci skip] - -commit b0fb9bda9ade532da9012c375c0026470484a346 - Author: Nobuyoshi Nakada - Date: 2019-11-12 00:09:34 +0900 - - Strip the last line which become trailing spaces - -commit dd0217a8696667960e834ba95534ac5731997f3d - Author: Nobuyoshi Nakada - Date: 2019-11-12 00:07:26 +0900 - - Inline function should be static - -commit 2de3feab44c928c30f35a4a3a445b4fdfc225024 - Author: Nobuyoshi Nakada - Date: 2019-11-12 00:08:39 +0900 - - Get rid of `__` prefix which is presereved by C standard - -commit 7c22898a3a5a10c8c71683918b53ec2d17fdc621 - Author: Nobuyoshi Nakada - Date: 2019-11-12 15:42:53 +0900 - - Disable tOROP at EXPR_BEG - - Both cannot appear there anyway. - -commit dbaf589fb84a5b42111c85f993430133d8cae32f - Author: Hiroshi SHIBATA - Date: 2019-11-12 12:49:05 +0900 - - Update Rake 13.0.1 - -commit 593f0b88533c9d327b33d098bb6b3b51df871966 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-12 11:27:55 +0900 - - Try to use actions/cache on windows - - Notes: - Merged: https://github.com/ruby/ruby/pull/2670 - -commit b38b26c62dc12da1d4fcee39de0c0cad598f5995 - Author: Jeremy Evans - Date: 2019-10-19 03:44:47 +0900 - - [ruby/bigdecimal] Remove taint checking - - This removes the taint checking. Taint support is deprecated in - Ruby 2.7 and has no effect. I don't think removing the taint - checks in earlier ruby versions will cause any problems. - - https://github.com/ruby/bigdecimal/commit/1918d466f3 - -commit db33ab470cb4765f1b54384b51850e0db80f5aad - Author: Aaron Patterson - Date: 2019-10-18 05:48:24 +0900 - - [ruby/psych] Add a note about safe_load - - https://github.com/ruby/psych/commit/0910ae5575 - -commit 30fdee65d96924e0793ec702fcda909a2cac71ea - Author: Jeremy Evans - Date: 2019-10-19 04:34:59 +0900 - - [ruby/psych] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - I'm not sure if the untaint calls in deduplicate are still needed - after the removal of tainting in the parser. If they are not - needed, they should be removed. - - https://github.com/ruby/psych/commit/73c1a2b4e0 - -commit 5ef41c91f0a1bca1617aaa4367ccf8e32c04b2d9 - Author: Jean Boussier - Date: 2019-07-25 05:08:59 +0900 - - [ruby/psych] Set required_ruby_version to 2.4.0 - - https://github.com/ruby/psych/commit/4f1746a3c6 - -commit fd6445b7e8bab9d340be6f76688a8b96f1b52029 - Author: Koichi Sasada - Date: 2019-11-12 10:02:47 +0900 - - Monitor#exit: check monitor ownership. - - Monitor#exit should be called by only onwer Thread. However, there - is not check for it. - -commit fef4370b409c990228cded2c425a6afb3bec2906 - Author: Koichi Sasada - Date: 2019-11-12 09:48:49 +0900 - - check more. - -commit ed90ec3e0d8ff7789569b40ba36d3b3ce0e706e6 - Author: Nobuyoshi Nakada - Date: 2019-11-12 09:11:16 +0900 - - Clear current argument name at empty block argument [Bug #16343] - -commit 4a30fabfcfd72bd61bf1dad61f168eaba6100f12 - Author: Koichi Sasada - Date: 2019-11-12 09:35:26 +0900 - - Monitor owner state check correctly. - - Monitor can be owned at the beginning of this method. - -commit 2407e8972561143b34970fb5d9095be32676c685 - Author: Yusuke Endoh - Date: 2019-11-12 08:39:38 +0900 - - Revert "Use untaint for File.symlink in kernel_require.rb" - - This reverts commit d9978ce5d397866afae536db2aa708af3b7a4b2f. - - Untaint was tentatively restored due to test failures. But now, the - failed tests have been removed, so we can revert the tentative fix. - -commit 9594f57f3df6c2538f96f018fa5f9a775ac7dde1 - Author: Yusuke Endoh - Date: 2019-11-12 08:31:13 +0900 - - test/ruby/test_require.rb: Remove the tests of require with $SAFE - - The taint mechanism is decided to be removed at 2.7. [Feature #16131] - So, this change removes the tests that expects a SecurityError when - requiring a file under $SAFE >= 1. - - The reason why they should be removed in advance is because the upstream - of rubygems has already removed a call to "untaint" method, which makes - the tests fail. - -commit d9978ce5d397866afae536db2aa708af3b7a4b2f - Author: Hiroshi SHIBATA - Date: 2019-11-12 08:03:26 +0900 - - Use untaint for File.symlink in kernel_require.rb - - Partly reverted 7d463e360b9c4718b17378eb52783116a01b884b - -commit b8d242d221641752a495ca43f8f211a3ad73d467 - Author: Koichi Sasada - Date: 2019-11-12 04:33:28 +0900 - - release RUBYGEMS_ACTIVATION_MONITOR correctly. - - `File.symlink? safe_lp` can raise SecurityError and raising an - exception can leave RUBYGEMS_ACTIVATION_MONITOR locking. This - patch release it correctly. - -commit 4be1e84d7894751799cc9d8ae2dec720952a02a3 - Author: Koichi Sasada - Date: 2019-11-12 04:13:54 +0900 - - more messages - -commit a815053a3ea16382bea8b420a3070b4da3c3bb94 - Author: Koichi Sasada - Date: 2019-11-12 04:03:33 +0900 - - check monitor is owning for debug - -commit 99be207c2acabe0030c376fd731608d9cd7c69b6 - Author: Koichi Sasada - Date: 2019-11-11 17:17:26 +0900 - - add a NEWS entry about builtin features. - -commit c02de30efbca2a2d89cdf188a27991f7ae15b9da - Author: Yusuke Endoh - Date: 2019-11-12 01:30:42 +0900 - - tool/lib/leakchecker.rb: show the code location that allocated leaked fd - - by using ObjectSpace.trace_object_allocations. - - `make test-all LEAK_CHECKER_TRACE_OBJECT_ALLOCATION=true` will print not - only leaked fds but also where it was created. - -commit b72eda3c59cd0a15ed3536a3c0cd8aebd225f16b - Author: Yusuke Endoh - Date: 2019-11-12 01:25:42 +0900 - - lib/rubygems.rb: Suppress "Resolving dependencies..." - - And suppress "Leaked file descriptor" again. - -commit 14b5c4cb66175553bda1cab70715d54fe46bffc7 - Author: git - Date: 2019-11-12 01:23:23 +0900 - - * 2019-11-12 [ci skip] - -commit b2b12792720fe83afc1a64b41ca76fde6b7d74c5 - Author: NARUSE, Yui - Date: 2019-11-12 01:22:09 +0900 - - format-release uses the result of GitHub Actions - -commit 0ba1ea7fbfc059e0e0114b4fc0bd66f3058d8b48 - Author: NARUSE, Yui - Date: 2019-11-12 01:00:22 +0900 - - Always use git.ruby-lang.org as origin - - naruse sets remote.origin.pushUrl = nonexistent as fail-safe - configuration to avoid accidentally push a new branch to origin. - -commit 45bb6f28db04a1f267f5b8d79392cb35087510d8 - Author: aycabta - Date: 2019-11-11 22:55:32 +0900 - - Remove ruby-token.rb - -commit bcfe94b7f20fa3a581fc5d6f2aef837327bfb770 - Author: Hiroshi SHIBATA - Date: 2019-11-11 22:17:50 +0900 - - Revert "Revert "Promote uri to default gems"" - - This reverts commit fdfad905227a0e2e4c224d87181041fb75d5082e. - - f1f27da6c457684fdbfc0352297e6847f675ce4c resolved this. - -commit f1f27da6c457684fdbfc0352297e6847f675ce4c - Author: Hiroshi SHIBATA - Date: 2019-11-11 21:49:21 +0900 - - Revert "Try to revert the test failure with Ruby CI" - - This reverts commit 8b27c23b5d55bd707a89bb5d95d2bdba9e132c1a. - -commit 8b27c23b5d55bd707a89bb5d95d2bdba9e132c1a - Author: Hiroshi SHIBATA - Date: 2019-11-11 20:19:29 +0900 - - Try to revert the test failure with Ruby CI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian9/ruby-master/log/20191111T093005Z.fail.html.gz - -commit 9d3213ac856e1f5930bda555d4d65b173c6cdf83 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-11 19:03:43 +0900 - - Skip test_validate_gemspec unless git installed - -commit 7585bc31877d4f9725f8de51b4a2faf47acb6f34 - Author: Hiroshi SHIBATA - Date: 2019-11-11 17:57:45 +0900 - - Merge Bundler 2.1.0.pre.3 - - Features: - - Add caller information to some deprecation messages to make them easier to fix [#7361](https://github.com/bundler/bundler/pull/7361) - - Reconcile `bundle cache` vs `bundle package` everywhere. Now in docs, CLI help and everywhere else `bundle cache` is the preferred version and `bundle package` remains as an alias [#7389](https://github.com/bundler/bundler/pull/7389) - - Display some basic `bundler` documentation together with ruby's RDoc based documentation [#7394](https://github.com/bundler/bundler/pull/7394) - - Bugfixes: - - Fix typos deprecation message and upgrading docs [#7374](https://github.com/bundler/bundler/pull/7374) - - Deprecation warnings about `taint` usage on ruby 2.7 [#7385](https://github.com/bundler/bundler/pull/7385) - - Fix `--help` flag not correctly delegating to `man` when used with command aliases [#7388](https://github.com/bundler/bundler/pull/7388) - - `bundle add` should cache newly added gems if an application cache exists [#7393](https://github.com/bundler/bundler/pull/7393) - - Stop using an insecure folder as a "fallback home" when user home is not defined [#7416](https://github.com/bundler/bundler/pull/7416) - - Fix `bundler/inline` warning about `Bundler.root` redefinition [#7417](https://github.com/bundler/bundler/pull/7417) - - Notes: - Merged: https://github.com/ruby/ruby/pull/2668 - -commit fd69f82675bf93a848e5aa58d117bf8bbf604188 - Author: NARUSE, Yui - Date: 2019-11-11 17:37:21 +0900 - - Revert "Warn EOF char in comment" - - This reverts commit 69ec3f70fab0c1c537c68fb135cc315181b1d750. - -commit ba5b51ca5968314f5ca92fee0afaea44a78eb0b1 - Author: NARUSE, Yui - Date: 2019-11-11 17:37:14 +0900 - - Revert "Elaborated EOF char message a little" - - This reverts commit 6eaac7cfac668d6669be694fd7b723c4982ed218. - -commit 7d463e360b9c4718b17378eb52783116a01b884b - Author: Hiroshi SHIBATA - Date: 2019-11-11 15:03:57 +0900 - - Merge RubyGems 3.1.0.pre3 - - * Fix gem pristine not accounting for user installed gems. Pull request - #2914 by Luis Sagastume. - * Refactor keyword argument test for Ruby 2.7. Pull request #2947 by - SHIBATA Hiroshi. - * Fix errors at frozen Gem::Version. Pull request #2949 by Nobuyoshi - Nakada. - * Remove taint usage on Ruby 2.7+. Pull request #2951 by Jeremy Evans. - * Check Manifest.txt is up to date. Pull request #2953 by David Rodríguez. - * Clarify symlink conditionals in tests. Pull request #2962 by David - Rodríguez. - * Update command line parsing to work under ps. Pull request #2966 by - David Rodríguez. - * Properly test `Gem::Specifications.stub_for`. Pull request #2970 by - David Rodríguez. - * Fix Gem::LOADED_SPECS_MUTEX handling for recursive locking. Pull request - #2985 by MSP-Greg. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2666 - -commit 31416423809f64d4b5ea6b9651cced3179cc5ced - Author: Koichi Sasada - Date: 2019-11-11 16:38:46 +0900 - - __builtin_inline! - - Add an experimental `__builtin_inline!(c_expression)` special intrinsic - which run a C code snippet. - In `c_expression`, you can access the following variables: - * ec (rb_execution_context_t *) - * self (const VALUE) - * local variables (const VALUE) - Not that you can read these variables, but you can not write them. - You need to return from this expression and return value will be a - result of __builtin_inline!(). - - Examples: - `def foo(x) __builtin_inline!('return rb_p(x);'); end` calls `p(x)`. - `def double(x) __builtin_inline!('return INT2NUM(NUM2INT(x) * 2);')` - returns x*2. - -commit 05a5c69e1a06a3853afb3744fa9925910b78904f - Author: Koichi Sasada - Date: 2019-11-10 07:16:56 +0900 - - add deps for miniprelude.c - -commit 9142f802f1126d65abb1aad5e2bc91b5b833fe7e - Author: Koichi Sasada - Date: 2019-11-10 02:25:57 +0900 - - rewrite comment. - - Pointed by nagachika-san. - https://ruby-trunk-changes.hatenablog.com/entry/ruby_trunk_changes_20191109 - -commit 65f7e3156f66bb4eba944c8ad2a463b9452b1a29 - Author: Nobuyoshi Nakada - Date: 2019-11-11 15:56:59 +0900 - - Removed duplicate file - - "./tests/test_helper.rb" and "tests/test_helper.rb" in `s.files` - are same. - -commit 31ee6f6f5d7f562f065dfe364bb9afb09274948c - Author: Nobuyoshi Nakada - Date: 2019-11-11 13:10:55 +0900 - - Extract gem files after update - - So that test/optparse/test_did_you_mean.rb can find did_you_mean.rb. - -commit 6eaac7cfac668d6669be694fd7b723c4982ed218 - Author: Nobuyoshi Nakada - Date: 2019-11-11 12:57:40 +0900 - - Elaborated EOF char message a little - -commit 390293525a8c8564c62f7691414194705a193b40 - Author: Nobuyoshi Nakada - Date: 2019-11-11 12:19:40 +0900 - - Remove binary data at installation - - And revert "Relaxed warning assertions", - 6f9be8505d172b110ec449478a791d70b9b74afb. - -commit 6f9be8505d172b110ec449478a791d70b9b74afb - Author: Nobuyoshi Nakada - Date: 2019-11-11 12:09:19 +0900 - - Relaxed warning assertions - -commit 69ec3f70fab0c1c537c68fb135cc315181b1d750 - Author: Nobuyoshi Nakada - Date: 2019-11-11 09:59:40 +0900 - - Warn EOF char in comment - -commit ade038889468e7755d7ebfe75975e0e77d1e1dec - Author: Nobuyoshi Nakada - Date: 2019-11-11 09:35:37 +0900 - - Fixed embedded document with EOF char - -commit b42656b9c403da1bac8e1dd7534f0a7a09df67b0 - Author: Yuichiro Kaneko - Date: 2019-11-11 09:22:46 +0900 - - Ignore *.rbinc files - -commit b5dff926e710a4fb069596f1911c998a28e3262a - Author: Nobuyoshi Nakada - Date: 2019-11-11 09:16:00 +0900 - - Prefer assert_syntax_error and assert_valid_syntax - -commit a73389393906939ed9208562e6ec5eb3d21775e3 - Author: Takashi Kokubun - Date: 2019-11-11 07:12:13 +0900 - - Fix uplevel of test_jit - -commit fcd9bc28e3d7d301bcdf6eea8ffa25c0c3ec184f - Author: Takashi Kokubun - Date: 2019-11-11 06:54:44 +0900 - - qsymbols and symbols should be colored as Symbol - -commit 25c53a8eec4f73f4d0d127144b24bf68218149e3 - Author: Takashi Kokubun - Date: 2019-11-11 06:41:34 +0900 - - Colorize on_symbols_beg (%I) - -commit 958d954a1909edc1e297c54db7bbab53a289a0b8 - Author: git - Date: 2019-11-11 06:34:25 +0900 - - * 2019-11-11 [ci skip] - -commit b5996b25ae8ff7e7961fea245c5ea8476b029134 - Author: Takashi Kokubun - Date: 2019-11-11 06:33:23 +0900 - - Colorize string quotes as bold - - like pry - -commit 6e70fa49b111e2a2839297b057a3df354cae265a - Author: Kazuki Tsujimoto - Date: 2019-11-10 22:34:49 +0900 - - Disallow omission of parentheses/brackets in single line pattern matching [Feature #16182] - -commit ef03d48cb20aa7739a4ac8eb4e109525a47fcc9f - Author: Yuichiro Kaneko - Date: 2019-11-10 22:18:08 +0900 - - Fix a typo - -commit 4570284ce14c9f00114039e9b619584a8cad6a50 - Author: Takashi Kokubun - Date: 2019-11-10 14:56:38 +0900 - - Test opt_invokebuiltin_delegate_leave in test_jit - -commit 5c168c7e7f73d400db45980115dedab4deefcda7 - Author: Takashi Kokubun - Date: 2019-11-10 14:40:38 +0900 - - Support RB_BUILTIN in ISeq#to_a - -commit 0483d01f6bdd3d16b31244a7aaadb4c31f6ecee7 - Author: Takashi Kokubun - Date: 2019-11-10 14:16:10 +0900 - - Test invokebuiltin in test_jit - - ISeq#to_a is commented out because it's broken now - -commit 11aa07c27071878d9f7748995febe7df96f0405d - Author: Nobuyoshi Nakada - Date: 2019-11-10 10:52:12 +0900 - - Define NULLCMD as printing NUL [Bug #16331] - -commit 2c55ba7191a69dd4db34572754162308f0a9acdd - Author: Nobuyoshi Nakada - Date: 2019-11-10 10:09:26 +0900 - - Define NULLCMD as an empty label [Bug #16331] - -commit faa4f4f23fbb6b48b158cc38d9b509fd00838976 - Author: Nobuyoshi Nakada - Date: 2019-11-10 09:15:12 +0900 - - Get rid of FreeBSD make incompatibility [Bug #16331] - - FreeBSD make works differently with `-j` option. - - > -j max_jobs - > Specify the maximum number of jobs that `make` may have running - > at any one time. The value is saved in `.MAKE.JOBS.` Turns - > compatibility mode off, unless the `B` flag is also specified. - > When compatibility mode is off, all commands associated with a - > target are executed in a single shell invocation as opposed to - > the traditional one shell invocation per line. This can break - > traditional scripts which change directories on each command - > invocation and then expect to start with a fresh environment on - > the next line. It is more efficient to correct the scripts - > rather than turn backwards compatibility on. - - Stop using exit, cd, exec in middle of commands. - -commit ff767dd914d0aa91e2c6ec29bba7ff3739225b0c - Author: git - Date: 2019-11-10 06:23:55 +0900 - - * 2019-11-10 [ci skip] - -commit e0094df29d2175b8163027687671bc638a993c72 - Author: Takashi Kokubun - Date: 2019-11-10 06:22:51 +0900 - - Extend sleep duration for Solaris - -commit 03fdf02321d4ac3123fb6908e7be53e232a92b67 - Author: Nobuyoshi Nakada - Date: 2019-11-09 23:00:32 +0900 - - Removed trial and errors - -commit a68205c5c19277e9ece8409b1f6af7e226989dff - Author: Nobuyoshi Nakada - Date: 2019-11-09 22:40:14 +0900 - - Specify the permission - - To make the temporary directory non-writable by group and others. - -commit 774cfb065567d07c4cf172cbb1708acda5e0fde4 - Author: Nobuyoshi Nakada - Date: 2019-11-09 22:15:15 +0900 - - Fixed the debug print - -commit 20bc038ea31ee799103bb89068537ed4e4f699b4 - Author: Nobuyoshi Nakada - Date: 2019-11-09 21:58:55 +0900 - - Debug-print tmpdir info - -commit f48655d04d463a89b7ac15bc3942ec6c574c6cd9 - Author: David Rodríguez - Date: 2019-11-08 23:03:02 +0900 - - Remove unneeded exec bits from some files - - I noticed that some files in rubygems were executable, and I could think - of no reason why they should be. - - In general, I think ruby files should never have the executable bit set - unless they include a shebang, so I run the following command over the - whole repo: - - ```bash - find . -name '*.rb' -type f -executable -exec bash -c 'grep -L "^#!" $1 || chmod -x $1' _ {} \; - ``` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2662 - -commit fcf37ca2fef8248966dcd9143aaea569fc87953c - Author: Nobuyoshi Nakada - Date: 2019-11-09 20:02:28 +0900 - - Fix builtin script paths - - Do not search builtin scripts by using VPATH, to get rid of weird - nmake VPATH. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2665 - -commit 79f0e7aafd0532666a00a49ef8feb838b5e9e208 - Author: Kazuki Tsujimoto - Date: 2019-11-09 21:12:29 +0900 - - Fix typos - -commit fdfad905227a0e2e4c224d87181041fb75d5082e - Author: Hiroshi SHIBATA - Date: 2019-11-09 20:14:17 +0900 - - Revert "Promote uri to default gems" - - This reverts commit c5b4d2a2592942766dc2789f46105b91eba7026a. - - This commit affects with activation feature of RubyGems. - [Bug #16337][ruby-core:95768] - -commit 4dd1caa12964c6932009a3548de121a861435b8e - Author: Nobuyoshi Nakada - Date: 2019-11-09 20:08:01 +0900 - - Updated miniprelude.o dependency - -commit e3c852441177caa4b251fa33c83a65e4263a4146 - Author: Nobuyoshi Nakada - Date: 2019-11-09 19:43:14 +0900 - - Full-path of builtin scripts no longer needed - -commit dfaac2b37253ff25ec873c2fbd93abfa7f789248 - Author: Nobuyoshi Nakada - Date: 2019-11-09 19:28:45 +0900 - - Embed builtin ruby scripts in miniprelude.c - - Instead of reading from the files by the full-path at runtime. As - rbinc files need to be included in distributed tarballs, the - full-paths at the packaging are unavailable at compilation times. - -commit 4dc4b1890499d6a836655957e78908ee891a42ce - Author: Nobuyoshi Nakada - Date: 2019-11-09 19:15:10 +0900 - - Fixed commit miss - -commit 95aed94d2aba5ff93425f26ae6181607996d8ca3 - Author: Nobuyoshi Nakada - Date: 2019-11-09 18:44:06 +0900 - - Fixed `#line` directives in miniprelude.c - -commit 352096ef6047538bfedb974a7c1b1156f5a0e811 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-09 16:43:47 +0900 - - Add debug print - -commit 43ceedecc0b9990b5bac2e65de5e439c41a9996b - Author: Koichi Sasada - Date: 2019-11-09 16:15:17 +0900 - - use STACK_ADDR_FROM_TOP() - - vm_invoke_builtin() accesses VM stack via cfp->sp. However, MJIT - can use their own stack. To access them appropriately, we need to - use STACK_ADDR_FROM_TOP(). - -commit 50bc7e7e9f0da6b27db06ac063257de0b97ed9b3 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-09 15:20:52 +0900 - - Add debug print - - http://ci.rvm.jp/results/trunk-mjit@silicon-docker/2380788 - ``` - test_all # terminated with exception (report_on_exception is true): - :134:in `pack': no implicit conversion of false into String (TypeError) - from /tmp/ruby/v2/src/trunk-mjit/tool/lib/test/unit/parallel.rb:160:in `_report' - from /tmp/ruby/v2/src/trunk-mjit/tool/lib/test/unit/parallel.rb:45:in `block in _run_suite' - ``` - -commit 352887b731f02c42abf6b905cde1737cc2249290 - Author: Hiroshi SHIBATA - Date: 2019-11-09 11:08:24 +0900 - - Remove YAML::VERSION because it conflicts with Psych::VERSION - -commit 21f7cca2c6394aaaec9189a7cb08a9ad8a2196e3 - Author: Koichi Sasada - Date: 2019-11-09 09:59:32 +0900 - - initialize kw special local var. - - A method which has keyword parameters has an implicit local variable - to specify which keywords are (un)specified. - - vm_call_iseq_setup_kwparm_nokwarg() is special function to invoke - a ISeq method without any keyword arguments. However, it should - also initialize the special local var. Without this initialization, - the implicit lvar can points a freed (T_NONE) object. - -commit c5b4d2a2592942766dc2789f46105b91eba7026a - Author: Hiroshi SHIBATA - Date: 2019-11-08 20:26:33 +0900 - - Promote uri to default gems - -commit 8c9438d219885fb26ca2e7cfc6ca38dd0bcb3db6 - Author: Hiroshi SHIBATA - Date: 2019-11-08 20:18:08 +0900 - - Promote yaml to default gems - -commit 2a0ed5691efbc602a4403ec09e6f91e89baa5507 - Author: Hiroshi SHIBATA - Date: 2019-11-08 19:21:47 +0900 - - Promote timeout to default gems - -commit 9a90a4d953a4d1f8e5977cd8d2bab59637de5348 - Author: Hiroshi SHIBATA - Date: 2019-11-08 15:47:46 +0900 - - Fixup 368ee984ed52f6abe1fdf8360ad72e6cf1cbfa66 - -commit 5f206cebb995ec3b0ff279c6a78c2a952b3c1be7 - Author: Hiroshi SHIBATA - Date: 2019-11-08 15:47:18 +0900 - - Promote observer to default gems. But not yet released - -commit 3d731c3694ac793ee525922fd902757d50b06702 - Author: Hiroshi SHIBATA - Date: 2019-11-08 15:39:39 +0900 - - Promote readline to default gems named readline-ext - -commit fc1d06b25d0ba3b1fb14b55cbff0218d8298bcf0 - Author: Hiroshi SHIBATA - Date: 2019-11-08 14:31:43 +0900 - - Added gemspec for readline gem that is wrapper library for reline and readline extension - -commit b5d884922053962c955df1ce54d9dabc98888272 - Author: Koichi Sasada - Date: 2019-11-09 07:09:01 +0900 - - Revert "don't embed full-path." - - This reverts commit dfac2e9eb3d697e56d91151584f1d3cf9d2c79c9. - - It does not work if cwd is different from builddir... - -commit dfac2e9eb3d697e56d91151584f1d3cf9d2c79c9 - Author: Koichi Sasada - Date: 2019-11-09 06:55:38 +0900 - - don't embed full-path. - - miniruby load *.rb from srcdir. To specify file path, - tool/mk_builtin_loader.rb embed full path of each *.rb file. - However it prevent to pre-generation of required files for tarball. - This patch generate srcdir/*.rb from __FILE__ information. - -commit 3b6954f8b9189f599e1f17636f8667a95ee94193 - Author: John Hawthorn - Date: 2019-11-08 07:50:05 +0900 - - Fix passing actual object_id to finalizer - - Previously we were passing the memory_id. This was broken previously if - compaction was run (which changes the memory_id) and now that object_id - is a monotonically increasing number it was always broken. - - This commit fixes this by deferring removal from the object_id table - until finalizers have run (for objects with finalizers) and also copying - the SEEN_OBJ_ID flag onto the zombie objects. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2658 - -commit 9deca1a3b91271159e164188367f003978737f42 - Author: Yusuke Endoh - Date: 2019-11-09 00:22:25 +0900 - - Try to fix test-spec failure on macOS - - Not sure what is happening, but spec/ruby/security/cve_2018_6914_spec.rb - fails on macOS. - https://github.com/ruby/ruby/runs/294462511#step:10:134 - - I suspect that the state of a directory is weird immediately after it is - created (not writable or even world writable?). This change tries to - make sure that ENV["TMPDIR"] is actually used by Dir.tmpdir. - -commit 88b9a0f7fe664098177f4d2f10aed08c4a42b03e - Author: Nobuyoshi Nakada - Date: 2019-11-09 00:20:42 +0900 - - Prettify builtin_binary format - -commit cd706c52168222e3badab82c24df22008d264ca9 - Author: git - Date: 2019-11-09 00:04:07 +0900 - - * 2019-11-09 [ci skip] - -commit 579aa4dc52b87510190a8d4bd2aaaf36fd49f3b6 - Author: Nobuyoshi Nakada - Date: 2019-11-09 00:03:29 +0900 - - Fixed the dependency - -commit 248d0008db6d3bfeadce0861a8902a4f8e45f07e - Author: Nobuyoshi Nakada - Date: 2019-11-08 23:59:22 +0900 - - Added pack.rb to BUILTIN_RB_SRCS - -commit a3141e3c76ef057080d5aab22130a326378094e2 - Author: Yusuke Endoh - Date: 2019-11-08 11:54:39 +0900 - - Rubified the APIs of pack.c - - Notes: - Merged: https://github.com/ruby/ruby/pull/2659 - -commit 882179a0ecc0dfb1f212334f3c92f90ffc817167 - Author: Yusuke Endoh - Date: 2019-11-08 12:58:17 +0900 - - tool/mk_builtin_loader.rb: check if op is an array or not - - The insn array includes not only an array but also some literal objects. - -commit 11e21f1982cbe41860b3f6755505ce063b74fc33 - Author: Nobuyoshi Nakada - Date: 2019-11-08 23:00:36 +0900 - - Make prefix static - -commit ff2d99406db4cd8aa0164c86525eedf627acffbe - Author: Nobuyoshi Nakada - Date: 2019-11-08 22:21:13 +0900 - - Update builtin include files - -commit 7acf7a4f9036a176f0b09cb23646e6bfb1af1c2f - Author: Nobuyoshi Nakada - Date: 2019-11-08 18:18:05 +0900 - - Add VPATH to rbinc rule for nmake - - Notes: - Merged: https://github.com/ruby/ruby/pull/2660 - -commit e02b819482f4e78b47599a6ce7624d4d9a13eb09 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-08 13:56:10 +0900 - - delete cc->aux.inc_sp - - Nobody uses it. - -commit 2e29b651093d158c23f6553972769c8ccb7dbd94 - Author: Nobuyoshi Nakada - Date: 2019-11-08 16:37:42 +0900 - - Add file mode to generated files [ci skip] - -commit 99b1c19be44d229f9ad0a84fd5963b0a810865c9 - Author: Nobuyoshi Nakada - Date: 2019-11-08 14:26:21 +0900 - - builtin.h must be included *AFTER* vm_core.h - -commit 20971799f26c6466f63ab179ce2d3384155b9760 - Author: Nobuyoshi Nakada - Date: 2019-11-08 16:24:24 +0900 - - Renamed `load_*.inc` as `*.rbinc` to utilize a suffix rule - -commit 6e72b72881b42e28d2f97ee023587e3d071fb64b - Author: aycabta - Date: 2019-11-08 16:17:53 +0900 - - Suppress "shadowing outer local variable" warning in 2.5 - -commit 83c563cfa403af1141fc0080d2b6eec344db6726 - Author: Koichi Sasada - Date: 2019-11-08 16:16:25 +0900 - - cstr -> bytes - - rb_iseq_ibf_load_cstr() accepts bytes, but not NUL-terminate - C string. To make it clear, rename it to _bytes. - -commit 0b29662606bb80762d58938e847441020301406f - Author: Koichi Sasada - Date: 2019-11-08 15:32:01 +0900 - - fix line break code (fix to LF) - -commit 054cb6d389da6a260830e4bd262aab2ee8fe2cb2 - Author: Koichi Sasada - Date: 2019-11-08 15:29:59 +0900 - - forget to add gc.rb - -commit 8fa41971c204555b889c9722586b8baee55a0ca8 - Author: Koichi Sasada - Date: 2019-11-08 15:27:32 +0900 - - use builtins for GC. - - Define a part of GC in gc.rb. - -commit 2eb02dfd3b650b54d6f3f5a63541e8165c997edd - Author: Koichi Sasada - Date: 2019-11-08 15:13:24 +0900 - - Stop compiling if type mismatch was found. - - If there is a type mismatch between expected builtin function type - and actual function type, C compiler shows warning. - - For example, `__builtin_func(1, 2)` expects - `func(rb_ec_t*, VALUE self, VALUE p1, VALUE p2)` function definition. - - However, it is easy to overlook "warning" messages. So this patch - changes to stop compiling as an error if there is a mismatch. - -commit 0ad0a8ff580a298dedc73c6679dd74d98c845ba9 - Author: Nobuyoshi Nakada - Date: 2019-11-08 14:26:21 +0900 - - builtin.h must be included *AFTER* vm_core.h - -commit 61cff5c51c63358148d33bf3b6be678d44b9df76 - Author: Nobuyoshi Nakada - Date: 2019-11-08 13:21:29 +0900 - - Removed BOM [ci skip] - -commit cfccd59cb1adfee7b1f402609a4ee32298a26d87 - Author: Kazuki Tsujimoto - Date: 2019-11-08 12:44:31 +0900 - - Fix typo - -commit 90fc5552580b8d6223a513dfa6ee5d0f8532b22a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-08 12:07:03 +0900 - - name the result of calccall - - This is a pure refactoring for better understanding of what is - happening here. Should change nothing but readability. - -commit d4da74ea786da7906fdb85e593593a9c6c11fe96 - Author: Kazuki Tsujimoto - Date: 2019-11-08 11:37:07 +0900 - - Define Struct#deconstruct_keys - -commit 766115010932d977142097f60c76dd20af73196e - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-08 11:11:21 +0900 - - revival of __func__ - - dad2abc69fdd1af52df353b8604017bd6a5c6a99 deleted __func__ but ruby - already use this feature under RUBY_FUNCTION_NAME_STRING macro. - Use it. - -commit a1a08ac9aabdde2cc8406f5210848a4885d14b52 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-08 10:24:57 +0900 - - describe vm_cache_check_for_class_serial [ci skip] - - Added comments describing what it is. Requested by ko1. - -commit eaa011ffdb55a315a6b35a52c3636c673f9ea836 - Author: Koichi Sasada - Date: 2019-11-08 10:10:37 +0900 - - Change requirements of BASERUBY. - - "BASERUBY: Ruby 1.9.3" test on Travis-CI checks builds on Ruby 1.9.3. - However this version is too old and 46acd0075d requires Ruby 2.2 and - later. - -commit 365557f111b453289a5e2ce0cdda0899ae248c71 - Author: Koichi Sasada - Date: 2019-11-08 09:39:28 +0900 - - Define IO#read/write_nonblock with builtins. - - IO#read/write_nonblock methods are defined in prelude.rb with - special private method __read/write_nonblock to reduce keyword - parameters overhead. We can move them into io.rb with builtin - functions. - -commit dad2abc69fdd1af52df353b8604017bd6a5c6a99 - Author: Koichi Sasada - Date: 2019-11-08 10:02:21 +0900 - - do not use __func__. - - Microsoft Visual Studio 12.0 doesn't support it. - -commit 08ff9edb533301cf1622d541832938577dbcd993 - Author: Koichi Sasada - Date: 2019-11-08 09:30:11 +0900 - - fix line break code (fix to LF) - -commit 46b9ca6c54ad7c4bb43df6a45854c5ffed980168 - Author: Koichi Sasada - Date: 2019-11-08 09:26:16 +0900 - - fix type - -commit 4c00b9e8eb0390c398eb67ba3762a26380d180c3 - Author: git - Date: 2019-11-08 09:09:47 +0900 - - * remove trailing spaces. [ci skip] - -commit a47d058ebf6890f4ad81c9c3419e767b4f093815 - Author: Koichi Sasada - Date: 2019-11-07 18:29:20 +0900 - - use builtin for RubyVM::AbstractSyntaxTree. - - Define RubyVM::AbstractSyntaxTree in ast.rb - with __builtin functions. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2655 - -commit e2a45cb984ba75083a577b38ee9643800579a280 - Author: Koichi Sasada - Date: 2019-11-07 18:22:08 +0900 - - use builtin for TracePoint. - - Define TracePoint in trace_point.rb and use __builtin_ syntax. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2655 - -commit 46acd0075d80c2f886498f089fde1e9d795d50c4 - Author: Koichi Sasada - Date: 2019-11-07 16:58:00 +0900 - - support builtin features with Ruby and C. - - Support loading builtin features written in Ruby, which implement - with C builtin functions. - [Feature #16254] - - Several features: - - (1) Load .rb file at boottime with native binary. - - Now, prelude.rb is loaded at boottime. However, this file is contained - into the interpreter as a text format and we need to compile it. - This patch contains a feature to load from binary format. - - (2) __builtin_func() in Ruby call func() written in C. - - In Ruby file, we can write `__builtin_func()` like method call. - However this is not a method call, but special syntax to call - a function `func()` written in C. C functions should be defined - in a file (same compile unit) which load this .rb file. - - Functions (`func` in above example) should be defined with - (a) 1st parameter: rb_execution_context_t *ec - (b) rest parameters (0 to 15). - (c) VALUE return type. - This is very similar requirements for functions used by - rb_define_method(), however `rb_execution_context_t *ec` - is new requirement. - - (3) automatic C code generation from .rb files. - - tool/mk_builtin_loader.rb creates a C code to load .rb files - needed by miniruby and ruby command. This script is run by - BASERUBY, so *.rb should be written in BASERUBY compatible - syntax. This script load a .rb file and find all of __builtin_ - prefix method calls, and generate a part of C code to export - functions. - - tool/mk_builtin_binary.rb creates a C code which contains - binary compiled Ruby files needed by ruby command. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2655 - -commit dddf5afb7947f5aba1ff875e9f5eb163f8c3d6c7 - Author: Aaron Patterson - Date: 2019-11-08 05:46:14 +0900 - - Add a counter for compaction - - Keep track of the number of times the compactor ran. I would like to - use this as a way to keep track of inline cache reference updates. - -commit 597ec4354333573d69f57dad931cb8ef477d191a - Author: git - Date: 2019-11-08 02:31:29 +0900 - - * 2019-11-08 [ci skip] - -commit b99833baec2e567e38758f4fd017c90c7ce57d75 - Author: John Hawthorn - Date: 2019-11-01 09:21:01 +0900 - - Use a monotonically increasing number for object_id - - This changes object_id from being based on the objects location in - memory (or a nearby memory location in the case of a conflict) to be - based on an always increasing number. - - This number is a Ruby Integer which allows it to overflow the size of a - pointer without issue (very unlikely to happen in real programs - especially on 64-bit, but a nice guarantee). - - This changes obj_to_id_tbl and id_to_obj_tbl to both be maps of Ruby - objects to Ruby objects (previously they were Ruby object to C integer) - which simplifies updating them after compaction as we can run them - through gc_update_table_refs. - - Co-authored-by: Aaron Patterson - -commit d62abc47c83a79687a41f375338564ece0f403ce - Author: Nobuyoshi Nakada - Date: 2019-11-07 23:33:45 +0900 - - Suppress unused variable warning - -commit 6aa80d5583daf71a4d45400af7e23e9d6151b1a3 - Author: NARUSE, Yui - Date: 2019-11-07 18:53:51 +0900 - - Use FIX2LONG instead of FIX2INT like 26843cbcd0 - -commit 26843cbcd0b97489f98aa123e700c4e893b1da5e - Author: NARUSE, Yui - Date: 2019-11-07 18:48:51 +0900 - - Use FIX2LONG to avoid unexpected exception - - Though it won't happen in the real world in this context, FIX2INT may - raise an exception and it cause to generate extra code. - -commit d45a013a1a3bcc860e6f7f303220b3297e2abdbc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-07 12:59:57 +0900 - - extend rb_call_cache - - Prior to this changeset, majority of inline cache mishits resulted - into the same method entry when rb_callable_method_entry() resolves - a method search. Let's not call the function at the first place on - such situations. - - In doing so we extend the struct rb_call_cache from 44 bytes (in - case of 64 bit machine) to 64 bytes, and fill the gap with - secondary class serial(s). Call cache's class serials now behavies - as a LRU cache. - - Calculating ------------------------------------- - ours 2.7 2.6 - vm2_poly_same_method 2.339M 1.744M 1.369M i/s - 6.000M times in 2.565086s 3.441329s 4.381386s - - Comparison: - vm2_poly_same_method - ours: 2339103.0 i/s - 2.7: 1743512.3 i/s - 1.34x slower - 2.6: 1369429.8 i/s - 1.71x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/2583 - -commit 3c252651e1ee28d015dbe1648dfdf0140232b733 - Author: Hiroshi SHIBATA - Date: 2019-11-07 17:09:22 +0900 - - Fixed test failure related Net::Protocol - -commit c916f9600b39e9363af782cb4dddef36264bd82b - Author: Hiroshi SHIBATA - Date: 2019-11-07 16:44:38 +0900 - - SMTP is not module - -commit fc85bdeb77ae642348bb797ef9ffb65913dfc77c - Author: Hiroshi SHIBATA - Date: 2019-11-07 16:34:03 +0900 - - Promote cgi to default gems - -commit 223d3c460a25e47577b6414e3ed141e54864c8dd - Author: Hiroshi SHIBATA - Date: 2019-11-07 15:38:40 +0900 - - Promote net-smtp to default gems - -commit eb0b13596d9130683937f11b207baf258b266edc - Author: Hiroshi SHIBATA - Date: 2019-11-07 15:24:59 +0900 - - Promote net-pop to default gems - -commit 77c94e0dd80019fe78e299dd1981ba9992ad7a46 - Author: Hiroshi SHIBATA - Date: 2019-11-07 13:53:05 +0900 - - Promote benchmark to default gems - -commit 1159dbf305603b60a1e5d2b9ff77a9cf30775296 - Author: Hiroshi SHIBATA - Date: 2019-11-07 13:21:46 +0900 - - Promote delegate to default gems - -commit 3b0bd34001bbb7ba98e9594278a8fcbb7b734af9 - Author: Hiroshi SHIBATA - Date: 2019-11-07 11:17:12 +0900 - - Promote pstore to default gems - -commit 6797c3e371c3e91a2796f2ec1f3b4a3f24edf1d6 - Author: Hiroshi SHIBATA - Date: 2019-11-07 08:48:45 +0900 - - Promote getoptlong to default gems - -commit 478f6e2b34c985bd2305895b9eec6918338e8ee2 - Author: Hiroshi SHIBATA - Date: 2019-11-07 08:43:10 +0900 - - Fixed an Errno::ENOENT with non-test libraries - -commit a396bef8d8b72328d411abe7a275736ad995fbcb - Author: Kazuki Tsujimoto - Date: 2019-11-07 14:00:59 +0900 - - Disallow duplicated pattern variable - -commit 1e620c67af3d37b6f120765daf29e96a643325ab - Author: Kazuki Tsujimoto - Date: 2019-11-07 13:20:11 +0900 - - Add missing semicolon - -commit d0d743ad4558a572769f0f11ece11fda068652b3 - Author: Aaron Patterson - Date: 2019-11-07 09:29:09 +0900 - - Remove duplicate code - - These functions are the same, so remove one. - - Co-authored-by: John Hawthorn - -commit e58814d150b0652f5e11958b36b85d977fdd0426 - Author: Aaron Patterson - Date: 2019-11-07 08:12:28 +0900 - - Revert "Use a monotonically increasing number for object_id" - - This reverts commit bd2b314a05ae9192b3143e1e678a37c370d8a9ce. - -commit bd2b314a05ae9192b3143e1e678a37c370d8a9ce - Author: John Hawthorn - Date: 2019-11-01 09:21:01 +0900 - - Use a monotonically increasing number for object_id - - This changes object_id from being based on the objects location in - memory (or a nearby memory location in the case of a conflict) to be - based on an always increasing number. - - This number is a Ruby Integer which allows it to overflow the size of a - pointer without issue (very unlikely to happen in real programs - especially on 64-bit, but a nice guarantee). - - This changes obj_to_id_tbl and id_to_obj_tbl to both be maps of Ruby - objects to Ruby objects (previously they were Ruby object to C integer) - which simplifies updating them after compaction as we can run them - through gc_update_table_refs. - - Co-authored-by: Aaron Patterson - - Notes: - Merged: https://github.com/ruby/ruby/pull/2638 - -commit d1630d41adb13c646a9d76cf541d3c26b6bbb10f - Author: Hiroshi SHIBATA - Date: 2019-11-06 22:17:03 +0900 - - Promote open3 to default gems - -commit fb7fe7f16c53b0633ba9dcea11dd07da708e0275 - Author: Hiroshi SHIBATA - Date: 2019-11-06 22:05:24 +0900 - - Added rubygems url for published gem - -commit ec2603c353680762960d76129a21225e8f1434da - Author: Hiroshi SHIBATA - Date: 2019-11-06 11:33:03 +0900 - - fallback standard structure library to sync_lib_gem method - -commit 91135f6d2900b1b8ae41998a921b6382ebba395c - Author: Hiroshi SHIBATA - Date: 2019-11-06 11:29:51 +0900 - - Promote singleton to default gems - -commit 40e161a61238625e1ef021311759b2159be5b50a - Author: Benoit Daloze - Date: 2019-11-07 07:10:15 +0900 - - Exclude some clocks on armv8 too - - * See https://bugs.ruby-lang.org/issues/16234#note-16 - -commit a1be11eb122cadc27ae597b9e0db66abfdca2c27 - Author: Takashi Kokubun - Date: 2019-11-07 02:52:45 +0900 - - Revert "Remove arm64 from allow_failures" - - This reverts commit 212f4d49bac844b3c0fa52f2185b3df30aa62e75. - - It worked on PR, but master branch builds have another build issue. - https://travis-ci.org/ruby/ruby/jobs/608303393 - -commit 212f4d49bac844b3c0fa52f2185b3df30aa62e75 - Author: Takashi Kokubun - Date: 2019-11-07 02:10:27 +0900 - - Remove arm64 from allow_failures - -commit 7750edd1e6822d4d5ee809d55691478af712ad95 - Author: git - Date: 2019-11-07 02:09:00 +0900 - - * 2019-11-07 [ci skip] - -commit f5c7fc495a4b33db985f0d5286db2ec230e1ffb9 - Author: Jun Aruga - Date: 2019-11-02 00:27:34 +0900 - - Fix spawn_spec.rb for Travis arm64 environment. - - The process group id (/proc/[pid]/stat 5th field) is 0 - in the Travis arm64 environment. - - This is a case where it is available. - - $ cat /proc/4543/stat - 4543 (ruby) S 4525 4525 1384 34818 4525 4194304 37443 1754841 0 0 366 105 2291 391 20 0 3 0 1381328 1428127744 11475 18446744073709551615 94195983785984 94195986670225 140728933833312 0 0 0 0 0 1107394127 0 0 0 17 2 0 0 1 0 0 94195987686512 94195987708942 94196017770496 140728933835483 140728933835595 140728933835595 140728933842904 0 - - This is a case where it is not available in Travis arm64 environment. - - $ cat /proc/19179/stat - 19179 (ruby) S 19160 0 0 0 -1 4194560 37618 1710547 313 163 770 665 5206 1439 20 0 2 0 17529566 1196347392 10319 18446744073709551615 187650811428864 187650815023116 281474602721280 0 0 0 0 4096 1107390031 0 0 0 17 22 0 0 0 0 0 187650815091456 187650815114064 187651414974464 281474602725080 281474602725211 281474602725211 281474602729420 0 - - See "man proc" for detail. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2653 - -commit 2fd465540f6dacaf16a8b679b6da000e90845a00 - Author: Nobuyoshi Nakada - Date: 2019-11-06 12:45:11 +0900 - - Numbered parameter is an ID_LOCAL now [Bug #16293] - -commit 82e840ad15bba42b399a21de746967a731240ec2 - Author: Nobuyoshi Nakada - Date: 2019-11-06 12:41:55 +0900 - - Numbered parameter cannot appear outside block now [Bug #16293] - -commit f72dc407f2f682063cf3d7683b879b430481b4ce - Author: Nobuyoshi Nakada - Date: 2019-11-06 11:17:09 +0900 - - Prohibit calling undefined allocator [Bug #16297] - -commit 5251d189829abc405a5f0422b8874bab7cd79c46 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-06 09:45:27 +0900 - - Time#strftime does not support `%Q` - - ``` - % ruby -r date -e 't=Time.utc(2001,2,3,4,5,6,7);p t; p [t, t.to_date, t.to_datetime].map{|d|d.strftime("%Q")}' - 2001-02-03 04:05:06.000007 UTC - ["%Q", "981158400000", "981173106000"] - ``` - -commit aa94245a09887f95bc0cd353b3462108d76d13ed - Author: Nobuyoshi Nakada - Date: 2019-11-06 08:54:32 +0900 - - Undefine MatchData.allocate [Feature #16294] - -commit 7460c884fb06a2c50a4a771761003ed78c8b28ce - Author: Aaron Patterson - Date: 2019-11-05 09:04:58 +0900 - - Use an identity hash for pinning Ripper objects - - Ripper reuses parse.y for its implementation. Ripper changes the - grammar productions to sometimes return Ruby objects. This Ruby objects - are put in to the parser's stack, so they must be kept alive. This is - where the "mark_ary" comes in. The mark array ensures that Ruby objects - created and pushed on the stack during the course of parsing will stay - alive for the life of the parsing functions. - - Unfortunately, Arrays do not prevent their contents from moving. If the - compactor runs, objects on the parser stack could move because the array - won't prevent them from moving. But the GC doesn't know about the - parser stack, so it can't update references in that stack (it will - update them in the array). - - This commit changes the mark array to be an identity hash. Since the - identity hash relies on memory addresses for the definition of identity, - the GC will not allow keys in an identity hash to move. We can prevent - movement of objects in the parser stack by sticking them in an identity - hash. - -commit d47b643428a5c19d5a0c2f2213c95ab03d63a24c - Author: git - Date: 2019-11-06 00:39:55 +0900 - - * 2019-11-06 [ci skip] - -commit 07f2062c8ffecc774a4ebc1f39ff2c4940592be4 - Author: Mark Abraham - Date: 2019-11-05 22:31:52 +0900 - - Improve string literal concatenation for C++11 - - Downstream C++ projects that compile with C++11 or newer and include - the generated config.h file issue compiler warnings. Both C and C++ - compilers do string-literal token pasting regardless of whitespace - between the tokens to paste. C++ compilers since C++11 require such - spaces, to avoid ambiguity with the new style of string literals - introduced then. This change fixes such projects without affecting - core Ruby. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2650 - -commit 6aacef49483ed83697dc013a4b33606338dffd39 - Author: aycabta - Date: 2019-11-05 21:06:29 +0900 - - Assert return value of Readline.readline only if Ruby is before 2.7 - -commit c4b627e2daf76e2f8922c62c8e0a6c2a10c8b435 - Author: Jeremy Evans - Date: 2019-10-19 01:53:59 +0900 - - Only taint on Ruby <2.7 - - Ruby 2.7 deprecates taint and it no longer has an effect. - -commit 652800cc09788805368983730c6b25183ae60d92 - Author: Jeremy Evans - Date: 2019-10-19 01:50:07 +0900 - - Only untaint line on Ruby <2.7 - - Untaint is deprecated and has no effect on Ruby 2.7+. - -commit c6a52cffd13a42b4c95ccbdf7e32a7da25e494b7 - Author: Nobuyoshi Nakada - Date: 2019-11-05 17:08:51 +0900 - - Separated `@counter` and `@tally` so that "-ft" works with "-j" - -commit fa52a924aa418e363b191179b2ad3eba2506d559 - Author: Nobuyoshi Nakada - Date: 2019-11-05 16:14:03 +0900 - - Enable "-f" option in multi_exec mode - - Make `MultiFormatter` a module and extend the formatter specified - by "-f" option. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2649 - -commit 19f91f788016ef98e30ead047e53edeb7a5f2566 - Author: Nobuyoshi Nakada - Date: 2019-11-05 15:50:28 +0900 - - `DottedFormatter#finish` consistency - - Removed optional parameter `printed_exceptions`, and clear - `exceptions` just after printing each exception, instead. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2649 - -commit dfb3322d27aa05f506818209ab6a10a77221b86d - Author: Nobuyoshi Nakada - Date: 2019-11-05 15:47:25 +0900 - - `DottedFormatter#state` consistency - - Let the method of `DottedFormatter` subclasses have the same - arity. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2649 - -commit bea322a352d820007dd4e6cab88af5de01854736 - Author: NARUSE, Yui - Date: 2019-11-05 17:30:54 +0900 - - Revert "[EXPERIMENTAL] Make Symbol#to_s return a frozen String [Feature #16150]" - - This reverts commit 6ffc045a817fbdf04a6945d3c260b55b0fa1fd1e. - -commit 853d91a04a4d133fc90b35c90570dc1c656a7922 - Author: Lars Kanis - Date: 2019-11-04 19:00:13 +0900 - - Fix coroutine support on win32 - - Ruby master branch currently fails on win32 MINGW at this spec: - https://github.com/ruby/spec/blob/master/core/thread/element_set_spec.rb - - MINGW makes use of setjmp3() implemented in MSVCRT.DLL. - This function traverses the SEH list up to a terminating pointer 0xFFFFFFFF. - It therefore currently segfaults on NULL. - The SEH linked list must be terminated by 0xFFFFFFFF instead of NULL. - - This fixes the issue mentioned here: - https://github.com/ruby/ruby/pull/2279#issuecomment-509508810 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2645 - -commit 7c07300491de502cd94e07fcbf9b30f2df31a0d5 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-05 13:46:08 +0900 - - let the .bss section initialize static variables - - ISO/IEC 9899:1999 section 6.7.8 specifies the values of static - storage which are not explicitly initialized. According to that - these initializers can be omitted. Doing so improvoes future - compatibility against addition / deletion of the fields of this - struct. - -commit 6ff1250739c57ce7f234a2148d3f6214da01b7e5 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-29 11:37:25 +0900 - - rb_method_basic_definition_p with CC - - Noticed that rb_method_basic_definition_p is frequently called. - Its callers include vm_caller_setup_args_block(), - rb_hash_default_value(), rb_num_neative_int_p(), and a lot more. - - It seems worth caching the method resolution part. Majority of - rb_method_basic_definion_p() usages take fixed class and fixed - method id combinations. - - Calculating ------------------------------------- - ours trunk - so_matrix 2.379 2.115 i/s - 1.000 times in 0.420409s 0.472879s - - Comparison: - so_matrix - ours: 2.4 i/s - trunk: 2.1 i/s - 1.12x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/2629 - -commit 1390d56ecfac2e430df94c4d4a60d8fa80d11166 - Author: Nobuyoshi Nakada - Date: 2019-11-05 10:28:44 +0900 - - Set $JOBS to Tests for parallel tests - -commit 8869384367a1b5e856b2f4b7b7d56296c71a572c - Author: Nobuyoshi Nakada - Date: 2019-11-05 10:28:01 +0900 - - Moved Init_encoding from wrong place [Bug #16292] - -commit 30a74aaef00a99364f5423439ac44babf5066dc0 - Author: Kazuhiro NISHIYAMA - Date: 2019-11-05 10:09:44 +0900 - - Fix a typo in WARN_EOL - -commit c7632fa80cd693be27b9bf85f1402b9c8812f325 - Author: Nobuyoshi Nakada - Date: 2019-11-05 08:26:10 +0900 - - Do not occupy `ARGV` by XRUBY command - - Instead run test-bundled-gems.rb by `ENV['RUBY']`, which should be - set by runruby.rb. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2646 - -commit ebbe396d3c89345a1c36c0b5154e314cc33e19b7 - Author: John Hawthorn - Date: 2019-11-04 13:51:30 +0900 - - Use ident hash for top-level recursion check - - We track recursion in order to not infinite loop in ==, inspect, and - similar methods by keeping a thread-local 1 or 2 level hash. This allows - us to track when we have seen the same object (ex. using inspect) or - same pair of objects (ex. using ==) in this stack before and to treat - that differently. - - Previously both levels of this Hash used the object's memory_id as a key - (using object_id would be slow and wasteful). Unfortunately, prettyprint - (pp.rb) uses this thread local variable to "pretend" to be inspect and - inherit its same recursion behaviour. - - This commit changes the top-level hash to be an identity hash and to use - objects as keys instead of their object_ids. - - I'd like to have also converted the 2nd level hash to an ident hash, but - it would have prevented an optimization which avoids allocating a 2nd - level hash for only a single element, which we want to keep because it's - by far the most common case. - - So the new format of this hash is: - - { object => true } (not paired) - { lhs_object => rhs_object_memory_id } (paired, single object) - { lhs_object => { rhs_object_memory_id => true, ... } } (paired, many objects) - - We must also update pp.rb to match this (using identity hashes). - - Notes: - Merged: https://github.com/ruby/ruby/pull/2644 - -commit 7c3bc0aa13abf3d46382860f76abb609a60376d6 - Author: Nobuyoshi Nakada - Date: 2019-11-05 08:07:59 +0900 - - Put an empty line [ci skip] - -commit 74bb8fb3480d0b0acaa6ef0bb93cc990cc7bf639 - Author: Burdette Lamar - Date: 2019-11-05 08:03:01 +0900 - - More rdoc for ENV - - Notes: - Merged: https://github.com/ruby/ruby/pull/2641 - -commit 9d04fa71fcd5352aadcdff43636ee915666bf749 - Author: Nobuyoshi Nakada - Date: 2019-11-05 02:14:31 +0900 - - Updated minitest to 5.13.0 - -commit c0c9a00f8301e100e2e05ffd101e2b8ff2bfe2ec - Author: Nobuyoshi Nakada - Date: 2019-11-05 00:48:22 +0900 - - Simplify test tasks - - Removed `if` conditions separating `test-bundled-gems`, and pass - `TESTOPTS` and `TEST_BUNDLED_GEMS_ALLOW_FAILURES` via `env`. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2643 - -commit 929a4aa722524f4567eed0d8b27d644f912c22f7 - Author: Nobuyoshi Nakada - Date: 2019-11-05 02:02:14 +0900 - - Adjust a function signature - -commit ec54261b01b1c744c22bacffd1e880f17db9df0b - Author: Aaron Patterson - Date: 2019-10-31 08:28:21 +0900 - - Fix zero free objects assertion - - This commit is to attempt fixing this error: - - http://ci.rvm.jp/results/trunk-gc-asserts@ruby-sky1/2353281 - - Each non-full heap_page struct contains a reference to the next page - that contains free slots. Compaction could fill any page, including - pages that happen to be linked to as "pages which contain free slots". - - To fix this, we'll iterate each page, and rebuild the "free page list" - depending on the number of actual free slots on that page. If there are - no free slots on the page, we'll set the free_next pointer to NULL. - - Finally we'll pop one page off the "free page list" and set it as the - "using page" for the next allocation. - -commit a087e027bf7cf0fbb825f1d55668f85ab1f3c9e6 - Author: Nobuyoshi Nakada - Date: 2019-11-05 01:32:26 +0900 - - Fixed conditional expressions with only one void side - -commit bd3463ee3591ab18dc06a4024ef6f78cc485d053 - Author: git - Date: 2019-11-05 00:07:22 +0900 - - * 2019-11-05 [ci skip] - -commit 4e8336bae853e712eb884b87560621c2da4c4743 - Author: Nobuyoshi Nakada - Date: 2019-11-04 23:58:36 +0900 - - Share test-bundled-gems-run in common.mk - -commit e91e3274bebc803b97971ad0a6f4ee3a8c646a60 - Author: Nobuyoshi Nakada - Date: 2019-11-04 23:37:53 +0900 - - Keep `lex.pcur` after `looking_at_eol_p` - -commit 26316cc350109ba71d42f944f3b976985627c042 - Author: Nobuyoshi Nakada - Date: 2019-11-04 21:23:11 +0900 - - Warn `if` and `elsif` at EOL [EXPERIMENTAL] - - It is unnatural and probably a typo. - -commit c303854e134043d905baff2385add44cc2c28756 - Author: Yusuke Endoh - Date: 2019-11-04 22:27:37 +0900 - - Revert "Warn `if` and `elsif` at EOL [EXPERIMENTAL]" - - This reverts commit ba35c14325ebbf1da8f200df83c45ee9937ff8a1. - This is because ripper fails symbol lookup error. - -commit ba35c14325ebbf1da8f200df83c45ee9937ff8a1 - Author: Nobuyoshi Nakada - Date: 2019-11-04 21:23:11 +0900 - - Warn `if` and `elsif` at EOL [EXPERIMENTAL] - - It is unnatural and probably a typo. - -commit cf377c5556cb03f180a8bbc200fab0f04a540edb - Author: Kazuhiro NISHIYAMA - Date: 2019-11-04 17:12:18 +0900 - - Fix a typo [ci skip] - -commit ffa9298076c4bfd1443b1231e1d7e7965ede5db9 - Author: Nobuyoshi Nakada - Date: 2019-11-04 16:38:36 +0900 - - Fixed a typo - -commit 823f25bb969a19c6c7055dabc5b33cd1fa709ac8 - Author: Nobuyoshi Nakada - Date: 2019-11-04 09:38:34 +0900 - - sync_default_gems.rb: Show the progress at fetching - - It looks like hanging up when fetching from a remote first time. - -commit cbbdb4e5a2eb46750d3c455def99486d23fc625b - Author: Nobuyoshi Nakada - Date: 2019-10-31 00:54:50 +0900 - - [ruby/racc] Strip trailing whitespaces at the last line of actions - - https://github.com/ruby/racc/commit/a887ebe529 - -commit 046be65c08e10973fccc19a04b95a9422a2dae65 - Author: git - Date: 2019-11-04 09:18:29 +0900 - - * 2019-11-04 [ci skip] - -commit df62d6522a6f679642e9b10dbf1edb1d9b646e91 - Author: Nobuyoshi Nakada - Date: 2019-11-04 09:14:18 +0900 - - Use the dedicated function `rb_io_check_io` - -commit 5a7487bdcd96ac7c66e773f1458691ff8fc41265 - Author: Nobuyoshi Nakada - Date: 2019-11-03 23:20:01 +0900 - - Added assertions for linebreak - -commit 7b2cd548aa52fa434006dccff62a6050ed5fd881 - Author: Nobuyoshi Nakada - Date: 2019-11-03 23:18:01 +0900 - - [DOC] mentioned `\R` [ci skip] - -commit f8b3d7d1599ecaa6760d947609f966a7a5b22e2c - Author: Nobuyoshi Nakada - Date: 2019-11-03 22:53:17 +0900 - - [DOC] \s in regexp is not same as in string [ci skip] - -commit 782d1b8fb0a039cedef9ad9c94f432dad51901e6 - Author: Benoit Daloze - Date: 2019-11-03 19:25:42 +0900 - - Fix warnings in Regexp#{match,match?} specs - -commit fbacfe6820cf4f7e115103057b6263cd038da175 - Author: Benoit Daloze - Date: 2019-11-03 19:11:20 +0900 - - Update NEWS entry for Feature #13083 - -commit 4a166237074edeaf5b7c1a0fb3c0bb4489c0dbf4 - Author: Benoit Daloze - Date: 2019-11-03 19:08:58 +0900 - - Remove incorrect NEWS entry, only Regexp#match and #match? changed - -commit 985e6ced9945df943a595aafc0a12faec125e853 - Author: git - Date: 2019-11-03 19:03:24 +0900 - - * 2019-11-03 [ci skip] - -commit 31110d820cc1258cbc84b46ecc65b254c7d5529a - Author: Kenichi Kamiya - Date: 2019-11-03 09:24:55 +0900 - - Improve warning message - - https://github.com/ruby/ruby/pull/2637#discussion_r341812475 - -commit 452bee3ee8d68059fabd9b1c7a75661b14e3933e - Author: Kenichi Kamiya - Date: 2019-11-02 00:54:36 +0900 - - Revert nil error and adding deprecation message - - Notes: - Merged: https://github.com/ruby/ruby/pull/2637 - -commit 772b0613c583773cd2eda23bce8275926a351e79 - Author: Burdette Lamar - Date: 2019-11-02 15:32:49 +0900 - - Correct documented return values for certain ENV methods (#2620) - -commit e6f0fd8af4a326f97bf886c6c9911463ac12dc0c - Author: git - Date: 2019-11-02 00:15:05 +0900 - - * 2019-11-02 [ci skip] - -commit ea97933645ad507c3015c7b2ca17035cf3008f96 - Author: aycabta - Date: 2019-11-01 23:45:07 +0900 - - Use prompt_list to calculate height by lines - -commit 10c2a085480eb8694750e55a613dbbe3eb22a999 - Author: Justin McNally - Date: 2019-10-08 12:12:17 +0900 - - Clean up implementation of SOCKSSocket, its confusing and undocumented - - Notes: - Merged: https://github.com/ruby/ruby/pull/2539 - -commit 68e0bfcd4a7add4140832f156a11f5aa3fbca41d - Author: Justin McNally - Date: 2019-10-08 12:36:22 +0900 - - Prefer libsocksd over libsocks - - Notes: - Merged: https://github.com/ruby/ruby/pull/2538 - -commit b8004103873f4e18bfaefea8e2f540f451c4ae68 - Author: Justin McNally - Date: 2019-10-08 12:04:27 +0900 - - Support libsocksd socks library for SOCKSSocket - - Notes: - Merged: https://github.com/ruby/ruby/pull/2538 - -commit c56d8deaff7dede58e7017bee58f40b86dcda3f4 - Author: Alan Wu - Date: 2019-10-25 03:43:04 +0900 - - Mention correct class name in uninitialized error - - I think this meant to mention `MatchData`? This is a breaking change, but - should be a minor one. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2608 - -commit cc8116b03e89b9c5fca5ace90a8141cff58d549b - Author: Kazuhiro NISHIYAMA - Date: 2019-09-30 18:03:30 +0900 - - Fix a typo [ci skip] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2510 - -commit 6abf4c4802c15c54742e3e8db9bfcab4207704b9 - Author: Nobuyoshi Nakada - Date: 2019-11-01 17:24:52 +0900 - - [ruby/date] Added update-zonetab target - - https://github.com/ruby/date/commit/9bc6e30a82 - -commit b2126d3fcfd2a946fe95947506620bb5e6c1f424 - Author: Jeremy Evans - Date: 2019-11-01 12:55:57 +0900 - - [ruby/date] Remove unneeded line in update-abbr - - https://github.com/ruby/date/commit/ae14e5f293 - -commit 469545307f7b688d0b7a15a5cfd33bcecb775123 - Author: Jeremy Evans - Date: 2019-11-01 03:29:37 +0900 - - [ruby/date] Add more timezone abbreviations - - This gets the time zone abbreviations from - https://www.timeanddate.com/time/zones/, and adds unambiguous time - zones not already present in zonetab.list. See bin/update-abbr - for the program used. - - This regenerates zonetab.h using prereq.mk (requires gperf). - - Only one test line is added, just to make sure a new time zone - abbreviation is picked up. - - Fixes Ruby Bug 16286 - - https://github.com/ruby/date/commit/702e8b3033 - -commit 51825c04db26c26ad43a76daaecf13a767ce34ea - Author: git - Date: 2019-11-01 16:59:02 +0900 - - * 2019-11-01 [ci skip] - -commit 72f997edf66cb766b97feac709888c57852be084 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-01 16:48:31 +0900 - - mark functions that do not return NULL as such. - - Apply __attribute__((__returns_nonnull__)) when available. - -commit f5e406327200672f95d61c4ca4ffc9de03e6a5a7 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-01 15:56:02 +0900 - - ruby_mimmalloc can return NULL - - malloc can fail. Should treat such situations. - -commit fb495b2928545e44cc9859f7cc743032d92ca9ee - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-01 14:33:44 +0900 - - rb_aligned_malloc can return NULL - - Looking at gc.c, rb_aligned_malloc contains `return NULL;` so it - has to be taken care of. Note however that posix_memalign(3posix) - does _not_ set errno. - -commit 2c889e9b05e2d2902096af02687cc6e3c7424c30 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-11-01 14:32:05 +0900 - - RUBY_ATTR_ALOC_SIZE for clang - - clang also supports __attribute__((__alloc_size__)) so why not use - it when the compiler says it does. - -commit 63f70eb65160a53443ec76365e78a80948b54824 - Author: Nobuyoshi Nakada - Date: 2019-10-31 22:21:11 +0900 - - [ruby/zlib] Removed no longer used variables - - https://github.com/ruby/zlib/commit/3e98e4cac3 - -commit 0aaa15f6362e307c9ef636e9625027b96e577dfb - Author: Alan Wu - Date: 2019-10-26 08:15:24 +0900 - - [ruby/zlib] Fix setting mtime to zero in GzipWriter - - Before this change, it was not possible to write out zero for the - timestamp part of a Gzip file's header, as calling GzipWriter#mtime with - zero was ignored. - - Judging from the docs for `GzipWriter#mtime=`, it should be possible to - indicate that no timestamp is available by calling the method with zero. - - https://github.com/ruby/zlib/commit/310be39cac - -commit d6ed7a984c8fd991ce2614d2f228239f8eb490b5 - Author: Jeremy Evans - Date: 2019-10-28 07:23:05 +0900 - - Fix verbose warning being emitted - - Fixes Ruby Bug 16281. - -commit 5f6fbf8725b6e4bc026480d7b95f7ac21198c591 - Author: Yusuke Endoh - Date: 2019-10-31 17:11:23 +0900 - - spec: Fix syntax errors - - Follow up of 473882e01f7e55753733e2607ace633b5041f11f - -commit 473882e01f7e55753733e2607ace633b5041f11f - Author: Hiroshi SHIBATA - Date: 2019-10-31 16:50:00 +0900 - - Skip tainted examples for stringio - -commit ebc884461b0d8c3144c05abeb793e381903de6b2 - Author: Jeremy Evans - Date: 2019-10-19 04:39:49 +0900 - - [ruby/stringio] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - https://github.com/ruby/stringio/commit/60ee9ccd95 - -commit 3895e548bd2d75cdf47cd247e84d6071247dd3b3 - Author: Jeremy Evans - Date: 2019-10-27 10:20:46 +0900 - - [ruby/date] Revert "Simplify #inspect" - - This reverts commit af01edd7d8575f544f647dbe8cde5b6ae535d459. - - Revert requested by Yui Naruse. - - https://github.com/ruby/date/commit/875d563557 - -commit fce940aac722575a78cd4cbe5f86dd3f3b40d13c - Author: glaszig - Date: 2019-08-09 09:41:47 +0900 - - [ruby/date] introduce Date::Error, raise Date::Error for every - "invalid " type of exception - - https://github.com/ruby/date/commit/3e55c09ba4 - -commit e4cd0d72876bae43b9369c1305db52370db47215 - Author: Jeremy Evans - Date: 2019-10-19 01:36:11 +0900 - - [ruby/fileutils] Remove use of untaint on Ruby 2.7 to avoid deprecation warnings - - https://github.com/ruby/fileutils/commit/5ac9a8a1f7 - -commit 39281d57743ebe5c1cdcc226399845dc7b17663a - Author: Hiroshi SHIBATA - Date: 2019-08-03 19:37:07 +0900 - - [ruby/gdbm] Use Gemfile instead of Gem::Specification#add_development_dependency. - - https://github.com/ruby/gdbm/commit/bd2e7f6647 - -commit b93ab7d693f5a4bec5d0e7c7ea282a6e24fe5a93 - Author: Jeremy Evans - Date: 2019-10-19 04:22:03 +0900 - - [ruby/gdbm] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - https://github.com/ruby/gdbm/commit/f9aaa1a08d - -commit 290903dba01d97bc6869886eccef0378dcdd5e0c - Author: Jeremy Evans - Date: 2019-10-19 04:45:15 +0900 - - [ruby/zlib] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - https://github.com/ruby/zlib/commit/21711ed0ce - -commit bc7fbb6f02f47f2e1ac2bcb3175324bb96c08247 - Author: Martin Dürst - Date: 2019-10-31 15:19:59 +0900 - - Mention update to Unicode Emoji version 12.1 in NEWS. - - Also fixed some grammatical errors. [ci skip] - -commit c38ba75780c4641816a8090629d1b5eea22fd137 - Author: Hiroshi SHIBATA - Date: 2019-10-31 10:18:57 +0900 - - Fixed the sync task for json - - * Ignode to change ext/json/depend - * Fixed to ignore json_pure files - -commit 79d96b42df8850b7ba5dd3a78cb72c23cf8cbe91 - Author: Aaron Patterson - Date: 2019-10-31 10:05:32 +0900 - - Revert "Fix zero free objects assertion" - - This reverts commit e1bf29314feee6aaf535917da0178e868e7ff3fa. - - I'm not sure why this broke stuff, I need to investigate later. - -commit e1bf29314feee6aaf535917da0178e868e7ff3fa - Author: Aaron Patterson - Date: 2019-10-31 08:28:21 +0900 - - Fix zero free objects assertion - - This commit is to attempt fixing this error: - - http://ci.rvm.jp/results/trunk-gc-asserts@ruby-sky1/2353281 - - Each non-full heap_page struct contains a reference to the next page - that contains free slots. Compaction could fill any page, including - pages that happen to be linked to as "pages which contain free slots". - - To fix this, we'll iterate each page, and rebuild the "free page list" - depending on the number of actual free slots on that page. If there are - no free slots on the page, we'll set the free_next pointer to NULL. - - Finally we'll pop one page off the "free page list" and set it as the - "using page" for the next allocation. - -commit e08f2e47e302db71621cfe2e770c087a5cf5146d - Author: Hiroshi SHIBATA - Date: 2019-10-31 06:57:06 +0900 - - Also ignore mswin platform - - Notes: - Merged: https://github.com/ruby/ruby/pull/2635 - -commit 8540efd3429c51682d2d0822935163f0930826b9 - Author: Hiroshi SHIBATA - Date: 2019-10-30 22:17:01 +0900 - - Ignore test_racc_command with linux platform - - Notes: - Merged: https://github.com/ruby/ruby/pull/2635 - -commit 1c03026ea3cd90cbc37eb4c612aca3c6129032c8 - Author: Hiroshi SHIBATA - Date: 2019-10-30 21:38:55 +0900 - - Try to run assert_output_unchanged with racc tests - - Notes: - Merged: https://github.com/ruby/ruby/pull/2635 - -commit 5f8795a07b163fe3f373ad443db1949de21c747b - Author: git - Date: 2019-10-31 00:38:16 +0900 - - * 2019-10-31 [ci skip] - -commit 4c7f789e942e78ebd3a7e3bf458c6cbe2133d692 - Author: Alan Wu - Date: 2019-10-30 09:08:01 +0900 - - Allow only one argument for keyword_init struct - - ``` - irb(main):001:0> RUBY_VERSION - => "2.6.5" - irb(main):002:0> S = Struct.new(:foo, keyword_init: true) - => S(keyword_init: true) - irb(main):003:0> S.new({foo: 23424}, 234) # I don't think this is intentional - => # - irb(main):004:0> - ``` - - Tightening this up should inform users when they are confused about - whether a struct is `keyword_init`. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2634 - -commit 6c3ed0d71cb1b59be5b2fbc886b5dd962ab74d35 - Author: Hiroshi SHIBATA - Date: 2019-10-30 21:36:59 +0900 - - Update the latest versions from upstream repository of racc - -commit e6d611ad37ab1a8eb04fceecdfe3a61967383256 - Author: Hiroshi SHIBATA - Date: 2019-10-30 21:01:30 +0900 - - Regenerate the output results for test fixtures of racc - -commit d3272fcba3196738403def453ef0a5119ce16953 - Author: Hiroshi SHIBATA - Date: 2019-10-30 21:00:01 +0900 - - Update the latest structure for racc upstream - -commit c54635c08b89612bbf2faa50b86fd6d5c8758506 - Author: Martin Dürst - Date: 2019-10-30 08:25:45 +0900 - - Update Unicode Emoji version from 12.0 to 12.1. - - This update does not add any new codepoint assignments, it just - expands the range of emoji codepoint sequences recommended for - public interchange. - - Depending on how emoji data files are cached, this commit may - require manual intervention in some build environments - (including some CI systems). - -commit 92c13380e853a8996574fadc8a498c96156674fe - Author: git - Date: 2019-10-30 00:14:03 +0900 - - * 2019-10-30 [ci skip] - -commit 22dbbbeb32b88708b9ea371e856c48c5d9ad3e63 - Author: Aaron Patterson - Date: 2019-10-30 00:13:38 +0900 - - Compacting the heap can cause GC, so disable it - - When we compact the heap, various st tables are updated, particularly - the table that contains the object id map. Updating an st table can - cause a GC to occur, and we need to prevent any GC from happening while - moving or updating references. - -commit fee5cde00be7342dc6c00d0b0a0276d09e5252e3 - Author: Nobuyoshi Nakada - Date: 2019-10-29 22:39:30 +0900 - - Fix tests for CVE-2018-6914 - - Since the current working directory is not involved in `Tempfile` - and `Dir.mktmpdir` (except for the last resort), it is incorrect - to derive the traversal path from it. Also, since the rubyspec - temporary directory is created under the build directory, this is - not involved in the target method. Fixed sporadic errors in - test-spec. - -commit ad4da86669454dee86844b3e0a3ecf9177084db3 - Author: Nobuyoshi Nakada - Date: 2019-10-29 12:12:07 +0900 - - Check for nonnull attribute in configure - -commit 9195ed18cacb0d448c818d2a80db105d8b3cea3c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-29 16:05:39 +0900 - - Revert "Check for nonnull attribute in configure" - - This reverts commit 54eb51d72bc43f90b595f0d7ffb5069ebf1a56d9. - - Windows build failure. See also https://github.com/ruby/ruby/runs/278718805 - -commit 7bf51ced5571d6180722f2be1b50c048a02b2e70 - Author: Yusuke Endoh - Date: 2019-10-29 14:34:31 +0900 - - test/rubygems/test_gem.rb: early failure when there is /tmp/Gemfile - - Some test cases in rubygems assume that /tmp/Gemfile does not exist. - If it does, they fail with very difficult-to-understand message: - - ``` - [ 149/2108] TestGemBundlerVersionFinder#test_bundler_version_with_bundle_update_bundler = 0.00 - 1) Failure: - TestGemBundlerVersionFinder#test_bundler_version_with_bundle_update_bundler [/home/mame/work/ruby/test/rubygems/test_gem_bundler_version_finder.rb:38]: - Expected Gem::Version.new("2.0.2") to be nil. - ``` - - I spent one hour to debug this issue. To prevent the same accident, - this change makes the test suite stop when /tmp/Gemfile explicitly. - -commit 79a7fd91208989d180027a9fed63db76b0a08cc1 - Author: Yusuke Endoh - Date: 2019-10-29 13:16:31 +0900 - - Revert "Revert "[ruby/rdoc] Use omit of test-unit instead of skip of minitest"" - - This reverts commit ca5812fe4516a10cc687281f9e47e1a08449f1ab. - - Now tool/lib/minitest provides "omit", so it should work. - -commit 1820aeeeb209420e80851d65a42acf188893069b - Author: Yusuke Endoh - Date: 2019-10-29 13:15:09 +0900 - - tool/lib/minitest/unit.rb: add "omit" as an alias to "skip" - - According to rdoc, test-unit provides omit instead of skip. - This is a compatibility layer to make it work with both test-unit and - tool/lib/minitest. - -commit ca5812fe4516a10cc687281f9e47e1a08449f1ab - Author: Yusuke Endoh - Date: 2019-10-29 12:57:31 +0900 - - Revert "[ruby/rdoc] Use omit of test-unit instead of skip of minitest" - - This reverts commit b4da6fc1c277190bbd10e795ebf3be45772038e8. - - `make test-all` uses minitest, which led to "undefined method `omit'" - -commit 9525541d022c67f4a162f8221bae7de2a172f371 - Author: aycabta - Date: 2019-10-28 13:39:37 +0900 - - [ruby/rdoc] Use Dir.glob to convert short path of Dir.tmpdir to long path - - https://github.com/ruby/rdoc/commit/ba16e44572 - -commit c8ce37d4271a58132fb7fc5548e0ba7d85419152 - Author: aycabta - Date: 2019-10-28 01:44:09 +0900 - - [ruby/rdoc] Support different drive latters in include paths - - https://github.com/ruby/rdoc/commit/946d2592e2 - -commit b4da6fc1c277190bbd10e795ebf3be45772038e8 - Author: aycabta - Date: 2019-10-27 02:28:25 +0900 - - [ruby/rdoc] Use omit of test-unit instead of skip of minitest - - https://github.com/ruby/rdoc/commit/1c5bf2ae1d - -commit 54eb51d72bc43f90b595f0d7ffb5069ebf1a56d9 - Author: Nobuyoshi Nakada - Date: 2019-10-29 12:12:07 +0900 - - Check for nonnull attribute in configure - -commit b86e5c9fec9d9ea0f9c70d9b20456680607399b3 - Author: John Hawthorn - Date: 2019-10-29 09:24:07 +0900 - - Clang can also use C call cache - - Previously this was restricted to only gcc because of the - GCC_VERSION_SINCE check (which explicitly excludes clang). - - GCC 3.3.0 is quite old so I feel relatively safe assuming that all - reasonable versions of clang support this. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2628 - -commit 85b88c1d89924d00ecd893cea696d2a94232745c - Author: Lourens Naudé - Date: 2019-10-22 08:18:37 +0900 - - Let the arrays for the singleton and instance method reflection helpers be initialized to the methods count - - Notes: - Merged: https://github.com/ruby/ruby/pull/2595 - -commit fecaa6e946fc87df28682c96fea67c1535825cd5 - Author: Lourens Naudé - Date: 2019-10-22 08:03:05 +0900 - - Let the backtrace array constructed in backtrace_collect be initialized with the size already given - - Notes: - Merged: https://github.com/ruby/ruby/pull/2593 - -commit 0095362918375fb694345133e33199b01911e594 - Author: Lourens Naudé - Date: 2019-10-22 07:49:54 +0900 - - Right size the vm_default_params hash - - Notes: - Merged: https://github.com/ruby/ruby/pull/2592 - -commit 0e68913f81eb35ae615592986a23b0f8f22501c6 - Author: Lourens Naudé - Date: 2019-10-22 07:31:46 +0900 - - Right size the Enumerator internal lazy_use_super_method hash - - Notes: - Merged: https://github.com/ruby/ruby/pull/2591 - -commit 4480d68931f3c7b25e194b30dea304b294744c92 - Author: Lourens Naudé - Date: 2019-10-22 07:28:41 +0900 - - Right size the compile option hash - - Notes: - Merged: https://github.com/ruby/ruby/pull/2590 - -commit 65744fb19efa7786c6b528d81328b641ea2e7cd5 - Author: Lourens Naudé - Date: 2019-10-22 06:31:44 +0900 - - Right size the iseq coverage branches tmp array - initializes with 5 elements - - Notes: - Merged: https://github.com/ruby/ruby/pull/2589 - -commit 0547627705ba2afd9b782ac511c825bfe36f052f - Author: aycabta - Date: 2019-10-29 10:34:32 +0900 - - Version 0.0.4 - -commit b4229c0a90ef902328e09a92fc5c6e884d01c542 - Author: Nobuyoshi Nakada - Date: 2019-10-29 08:58:39 +0900 - - Restore `in_kwarg` flag properly - -commit da3774e5eb6de9dfe5c2ec6f3444c81d22c0e00a - Author: Aaron Patterson - Date: 2019-10-29 08:14:50 +0900 - - Revert "Protect finalizer references during execution" - - This reverts commit 60a7f9f446604571f8a81499080c57c47baf0e6b. - - We can't have Ruby objects pointing at T_ZOMBIE objects otherwise we get - an error in the GC. We need to find a different way to update - references. - -commit 60a7f9f446604571f8a81499080c57c47baf0e6b - Author: Aaron Patterson - Date: 2019-10-18 03:37:32 +0900 - - Protect finalizer references during execution - - When we run finalizers we have to copy all of the finalizers to a new - data structure because a finalizer could add another finalizer and we - need to keep draining the "real" finalizer table until it's empty. - We don't want Ruby programs to mutate the finalizers that we're - iterating over as well. - - Before this commit we would copy the finalizers in to a linked list. - The problem with this approach is that if compaction happens, the linked - list will need to be updated. But the GC doesn't know about the - existence of the linked list, so it could not update references. This - commit changes the linked list to be a Ruby array so that when - compaction happens, the arrays will automatically be updated and all - references remain valid. - -commit 6147fa82a923e7318f493857023006801ed25eb5 - Author: Aaron Patterson - Date: 2019-10-15 06:52:58 +0900 - - Fix continuation mark / compact - -commit bbf3de22b6654642c923884b9e186e6412f1ba6a - Author: Aaron Patterson - Date: 2019-10-09 05:35:24 +0900 - - Pin labels during disassembly - - We need to ensure that labels are pinned while disassembling. If the - compactor runs during disassembly, references to these labels could go - bad, so this commit just ensures that the labels can't move until we're - done. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2625 - -commit 339a891c7d9c56f27f10ed9a9e60f511f75da934 - Author: Aaron Patterson - Date: 2019-10-09 05:15:44 +0900 - - Pin keys of this st_table - -commit a51583b678945ec2ba7ea355dab2c097c47f4b08 - Author: git - Date: 2019-10-29 03:19:25 +0900 - - * 2019-10-29 [ci skip] - -commit aec16b754055f5436b2770695ce6f579ed2fc248 - Author: Aaron Patterson - Date: 2019-10-08 09:41:26 +0900 - - Marshal is calling functions that should pin things - -commit 6e0b40af3da4941b618f018b2c04cee0110ce50c - Author: Nobuyoshi Nakada - Date: 2019-10-28 18:31:00 +0900 - - Try out-of-place build - - Notes: - Merged: https://github.com/ruby/ruby/pull/2622 - -commit 48f982aba7ab5b23af168d3c108e71e3a27c0648 - Author: Nobuyoshi Nakada - Date: 2019-10-28 19:14:38 +0900 - - test-bundled-gems.rb: fixed for out-of-place build - -commit 07b5fec008f33e4a5e03def56d5650ba8d897b1f - Author: Nobuyoshi Nakada - Date: 2019-10-28 18:15:12 +0900 - - Clean mjit and timestamp directories - -commit 3e83f1f00ae89f3391ceed8ea6192cc23257536e - Author: Kazuhiro NISHIYAMA - Date: 2019-10-28 15:34:42 +0900 - - Add more matrix info to slack payload - - Notes: - Merged: https://github.com/ruby/ruby/pull/2621 - -commit cc5580f175bb55c9a1d7574c1861f405ee972617 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-28 14:36:28 +0900 - - fix bug in keyword + protected combination - - Test included for the situation formerly was not working. - -commit a72cb6b11d777c2268831df4f21ab56851db425c - Author: git - Date: 2019-10-28 12:20:36 +0900 - - * 2019-10-28 [ci skip] - -commit d8d581bfc4cee87a59e40eac20e51fe199eb44bf - Author: Koichi Sasada - Date: 2019-10-28 12:19:18 +0900 - - add assertion for mutex_lock. - - After do_mutex_lock(mutex), the mutex should be owned by the current - thread. Adding an assertion for this assumption. - -commit 85d966af21ce834ddefe13861bcb42abae244d25 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-27 09:59:56 +0900 - - Add ubuntu-16.04 to matrix of GitHub Actions - - Notes: - Merged: https://github.com/ruby/ruby/pull/2617 - -commit 417369e0cd6ec96950d2d48f2c94e7b1eb012076 - Author: zverok - Date: 2019-10-26 20:02:59 +0900 - - Improve Enumerator.produce docs - - * Add to NEWS; - * Add examples of while-alike cycles with practical tasks. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2616 - -commit aba23d83f2697247488a2e770fcb9ce5abfcd16c - Author: Jeremy Evans - Date: 2019-10-27 10:41:35 +0900 - - Fix documentation for Fiber#transfer [ci skip] - - Fiber#transfer prevents calling Fiber#resume on the receiver of the - transfer method, not the fiber calling transfer. - - Transferring back to a fiber does not allow later calling resume on - the fiber. Once transfer has been called on a fiber, you can never - call resume on the fiber. - - Calling resume on a transferred fiber is not a double resume error, - it is a different FiberError (cannot resume transferred Fiber). - - For details on the differences between transferred fibers and - regular fibers, see Sasada-san's RubyKaigi 2017 presentation (in - short, Fiber#transfer is for coroutine, Fiber#resume is for - semi-coroutine). - -commit 4fe89e08217446de3b540088a5ef5af37d17b3c9 - Author: Benoit Daloze - Date: 2019-10-27 05:33:43 +0900 - - Add entry for Feature #13083 in NEWS - - * Move Unicode changes under String / Unicode for consistency with the rest. - -commit 664e96b1de816c813c29f61e16a2031a7af7ba86 - Author: Benoit Daloze - Date: 2019-10-27 03:53:01 +0900 - - Update to ruby/spec@28a728b - -commit 3eb0d50c0baae916f4486c264605b18e77bee0dc - Author: Benoit Daloze - Date: 2019-10-27 03:52:59 +0900 - - Update to ruby/mspec@e171725 - -commit 9c5a962354c7630d4fa2326574df3d3ce568ed5c - Author: git - Date: 2019-10-27 02:24:50 +0900 - - * 2019-10-27 [ci skip] - -commit 62212482947066d2cbf4dad6ebe60facf35ef223 - Author: zverok - Date: 2019-10-26 18:21:33 +0900 - - Improve Net::HTTP docs: - - * Make links from Net::GenericHTTPRequest work; - * Document +dest+ param of HTTPResponse#read_body; - * Slightly improve reference to particular response - classes from HTTPResponse class docs. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit f93cb6904c69de51bf14b1bcf9fcfc483584f4d3 - Author: zverok - Date: 2019-10-26 17:46:54 +0900 - - OptionParser: document into: argument - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit a24bff461d67e8d5e1f076a9ce773bc876a8b3d4 - Author: zverok - Date: 2019-10-26 17:29:43 +0900 - - open-uri: change global docs to reflect that URI.open syntax is preferred - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit de147bb721ec10675556ef4e93c4480856089ba5 - Author: zverok - Date: 2019-10-26 17:15:18 +0900 - - Net::FTP: fix formatting problems for #status method - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit 4fe06f46675801c5be392551813baabadf43c87c - Author: zverok - Date: 2019-10-26 17:04:24 +0900 - - IRB: Document command evaluation history. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit 2746fd5d50429994b0d66bb49c2e09089beb1b3f - Author: zverok - Date: 2019-10-26 16:03:24 +0900 - - Update StringIO docs: - - * More explanations/examples in class docs; - * Fix links to other methods (remove tag); - * Fix wording of method docs (remove *stringio* - receiver name, as it is not rendered by modern - RDoc); - * Add option mention to linereading - methods (added in 2.4); - * Several other small fixes. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit f6f1377a4ec187579a7dd0249be1166b42bf668b - Author: zverok - Date: 2019-10-26 15:34:14 +0900 - - Update ERB docs - - * Actualize Notes about other templating engines; - * Document #location= method. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2615 - -commit ad9c7137282009bbecae8df8bd5a601311282d62 - Author: aycabta - Date: 2019-10-26 16:26:48 +0900 - - Make `(#methodname)` a link with --hyperlink-all option - -commit d70fdeedf0a2fc942d91b82f564b78a54ff48d7c - Author: Nobuyoshi Nakada - Date: 2019-10-25 15:03:18 +0900 - - Make `(#methodname)` a link - -commit 5aacb304551aa29f86e4c59bef5136bf9d20726a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-26 15:33:16 +0900 - - refactor assign variables - - For readability. Requested by ko1. - - See: https://github.com/ruby/ruby/commit/356e203a3acd4d3d20ba12f956fd22e17b6363e9#r35661401 - -commit bddb31bb37f878cf171f89ac54f7e43d7d59c444 - Author: zverok - Date: 2019-10-25 01:35:36 +0900 - - Documentation improvements for Ruby core - - * Top-level `return`; - * Documentation for comments syntax; - * `rescue` inside blocks; - * Enhance `Object#to_enum` docs; - * Make `chomp:` option more obvious for `String#each_line` and - `#lines`; - * Enhance `Proc#>>` and `#<<` docs; - * Enhance `Processs` class docs. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2612 - -commit cf9344131c3d0f5993c6d999c427a4c656df30a2 - Author: Nobuyoshi Nakada - Date: 2019-10-26 02:15:18 +0900 - - Raise on end-exclusive ranges [Feature #14784] - - Raises an error on end-exclusive ranges unless endless, regardless - the receiver. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2613 - -commit f14b754151c8b6a006871cff8f590b9b608a7697 - Author: Hiroshi SHIBATA - Date: 2019-08-12 22:16:21 +0900 - - [ruby/forwardable] Use Gemfile instead of Gem::Specification#add_development_dependency. - - https://github.com/ruby/forwardable/commit/1e7123a81b - -commit f625a4be3c8f159e97f859785d95d50550b3edca - Author: Kazuhiro NISHIYAMA - Date: 2019-10-10 11:33:44 +0900 - - [ruby/forwardable] Fix NoMethodError on ruby 2.4 or earlier - - https://github.com/ruby/forwardable/runs/242918994#step:5:12 - ``` - Error: test_obj_single_delegators_send_id(TestForwardable): NoMethodError: private method `attr_reader' called for #> - ``` - - https://github.com/ruby/forwardable/commit/711bbb2466 - -commit 00989770535cfe69e618a2c556dad44610042e13 - Author: Jeremy Evans - Date: 2019-08-21 23:33:28 +0900 - - [ruby/forwardable] Remove string allocation in def_{instance,single}_delegators - - https://github.com/ruby/forwardable/commit/1a994c90e1 - -commit d00551a7bb1d5dbabb0a8c95d6bd2d9d4e86934a - Author: Jeremy Evans - Date: 2019-08-16 07:21:55 +0900 - - [ruby/forwardable] Make def_{instance,single}_delegators skip :__send__ and :__id__ - - Previously, __send__ and __id__ were skipped if provided as strings, - but not skipped if provided as symbols. - - Fixes Ruby Bug 8855. - - https://github.com/ruby/forwardable/commit/2e61c8c66c - -commit b15e0983f7504c4688afce0ee29a2f4746b6631a - Author: Hiroshi SHIBATA - Date: 2019-08-12 22:28:03 +0900 - - [ruby/forwardable] Update spec.files - - https://github.com/ruby/forwardable/commit/1b6991e589 - -commit b25ab3832f75f9257d3ea2e450af8a00a28e1acd - Author: Hiroshi SHIBATA - Date: 2019-08-12 22:27:13 +0900 - - [ruby/forwardable] Extracted VERSION constant for gemspec - - https://github.com/ruby/forwardable/commit/387758d45a - -commit 0c579b0a97bdec40ed58e15ab611ec00bb83d48d - Author: Jeremy Evans - Date: 2019-10-19 04:02:38 +0900 - - [ruby/dbm] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - - https://github.com/ruby/dbm/commit/1f0ff0bce1 - -commit 41d52945063e671d34324dc0acefae1534ff7835 - Author: git - Date: 2019-10-26 02:56:12 +0900 - - * 2019-10-26 [ci skip] - -commit 84b69c520e8c7cadf510f21f6e1552d063b1dff3 - Author: Nobuyoshi Nakada - Date: 2019-10-26 02:54:29 +0900 - - Edit vm_opts.h for VM options - - Revert 46f175ed5c8560b3c9da5ab7b4fa73287f1eb1c5 partially. - - Also tool/ruby_vm scripts refer the options in vm_opts.h. - -commit 42c652d1959564bc5fb5147c8c343d8c0589583c - Author: Nobuyoshi Nakada - Date: 2019-10-25 22:09:38 +0900 - - Fixed range argument condition [Feature #14784] - - Allows a beginless/endless range, and an end-exclusive range - unless the receiver is smaller than its end. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2611 - -commit 88135845f10f4b8ea3b67584a2c899ad365fd6bb - Author: Koichi Sasada - Date: 2019-10-25 17:58:54 +0900 - - enable assertion for debug. - - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/2340856 - -commit f3f1d89d469e3cc18f868a17fc0362c34318cedc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-25 16:44:15 +0900 - - skip tests that do not work on GC.stress - - These tests rely on GC.stat and GC.last_gc_info, which are not - stable when GC.stress is true. Skip them for that case. - -commit 356e203a3acd4d3d20ba12f956fd22e17b6363e9 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-24 18:08:52 +0900 - - more on struct rb_call_data - - Replacing adjacent struct rb_call_info and struct rb_call_cache - into a struct rb_call_data. - -commit a7ec88ad61eba8cda3f99805e6077cb515c0ad08 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-25 10:45:46 +0900 - - Add `shell: cmd` - - Use cmd instead of new default shell for `call`. - https://github.blog/changelog/2019-10-17-github-actions-default-shell-on-windows-runners-is-changing-to-powershell/ - - https://github.com/ruby/ruby/commit/7bcc639c720b59eb2199601963bcfa720168185b/checks#step:6:5 - ``` - call : The term 'call' is not recognized as the name of a cmdlet, function, script file, or operable program. - ``` - -commit 7bcc639c720b59eb2199601963bcfa720168185b - Author: aycabta - Date: 2019-10-25 10:07:17 +0900 - - Rename old var name with new name - -commit 09936d1d74c51d2afa9bd52e5681b6edf00aef6d - Author: Hiroshi SHIBATA - Date: 2019-08-03 18:56:41 +0900 - - [ruby/tracer] Use Gemfile instead of Gem::Specification#add_development_dependency. - - https://github.com/ruby/tracer/commit/9df7d7937b - -commit fb15e79403181098c969b4a8b7e4dd69f820955d - Author: Jeremy Evans - Date: 2019-10-25 04:36:49 +0900 - - Handle case where ruby2_keywords method splats to ruby2_keywords method - - Previously, the keyword hash was duped (which results in a regular - hash), but the dup was not marked as a keyword hash, causing the - hash not to be marked as keyword hash even though it should be. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2609 - -commit 5040eea959300ecb183d79f9539151239c281aa6 - Author: Nobuyoshi Nakada - Date: 2019-10-25 08:53:03 +0900 - - Do not show progress at chocolatey - -commit 4ff2c58f919153b9a47f69f855a0b9d2bb0e0bbe - Author: wanabe - Date: 2019-10-25 04:40:39 +0900 - - retry tailcall optimization (#2529) - - Sorry, f62f90367fc3bce6714e7c34cbd040e14e43fe07 is push miss. - -commit 58b363bf0d1f31ae9bcbaf301f9abedb99fa90f6 - Author: Koichi Sasada - Date: 2019-10-25 04:37:46 +0900 - - respect `param.flags.ruby2_keywords` at to_binary. - - `param.flags.ruby2_keywords` is not store/load correctly at to_binary - so restore this flag correctly. - -commit d6a2507e494f0fffca375c9e2eede38b6a777874 - Author: Jeremy Evans - Date: 2019-10-25 01:47:30 +0900 - - Duplicate hash when converting keyword hash to keywords - - This mirrors the behavior when manually splatting a hash. This - mirrors the changes made in setup_parameters_complex in - 6081ddd6e6f2297862b3c7e898d28a76b8f9240b, so that splatting to a - non-iseq method works the same as splatting to an iseq method. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2606 - -commit 8c59b9250c25c66d6ed16429da139558295a4517 - Author: Jeremy Evans - Date: 2019-10-25 01:35:48 +0900 - - Update date specs - - Allow Date.new spec to run on 2.7. - - Separate Date.valid_jd? specs, since 2.7 is now stricter and - requires numeric value for the first argument. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2605 - -commit 5fe8943fdaf765dc01d986abafe85bd3eafb7814 - Author: Jeremy Evans - Date: 2019-10-25 01:35:02 +0900 - - Fix typo causing Date.new(year, month) to fail - - Add a test for this case. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2605 - -commit e8f90e73978c0321021c177fe3fa2623a8b3a4de - Author: Koichi Sasada - Date: 2019-10-25 04:01:02 +0900 - - check T_ICLASS for Method#inspect. - - METHOD::klass can contain T_ICLASS so inspect should respect it. - -commit b7c8874b6290d17f6f8ebd4b2fa72c231121c714 - Author: Nobuyoshi Nakada - Date: 2019-10-25 02:24:42 +0900 - - Install openssl with chocolatey - - OpenSSL in chocolatey is 1.1.1d but outdated 1.0.2s is in vcpkg. - -commit 826bbf9837e1e763c9200bb81e63560b194533dd - Author: Nobuyoshi Nakada - Date: 2019-10-25 02:24:00 +0900 - - Split by `&&` - -commit 967b924aa0b8385b2f8effd96c006fb3eeca7802 - Author: Nobuyoshi Nakada - Date: 2019-10-25 02:08:03 +0900 - - Expanded an environment variable - - PowerShell does not expand by `%varname%` syntax. - -commit b86af95c5b4e035f5dc14018a7ff8861e6dc203d - Author: Nobuyoshi Nakada - Date: 2019-10-25 02:04:14 +0900 - - Get rid of control flow by cmd.exe - - Github workflow stopped using cmd.exe suddenly, and `||` and `&&` - seem not working in PowerShell. - -commit b609bdeb5307e280137b4b2838af0fe4e4b46f1c - Author: Nobuyoshi Nakada - Date: 2019-10-25 01:16:05 +0900 - - Define arguments forwarding as `ruby2_keywords` style - - Get rid of these redundant and useless warnings. - - ``` - $ ruby -e 'def bar(a) a; end; def foo(...) bar(...) end; foo({})' - -e:1: warning: The last argument is used as the keyword parameter - -e:1: warning: for `foo' defined here - -e:1: warning: The keyword argument is passed as the last hash parameter - -e:1: warning: for `bar' defined here - ``` - -commit 4b3e007e0778415e75ec2f0afcdc559eea43fdf8 - Author: Nobuyoshi Nakada - Date: 2019-10-25 01:03:08 +0900 - - Assert no-kwrest case - -commit ed65e2d5ae700afe8408836a8774becf5c87f76b - Author: Nobuyoshi Nakada - Date: 2019-10-25 00:56:27 +0900 - - Assert no-block case - -commit 8d0c5eb805a0a9afeb6e87c939c9b6f7f22df013 - Author: Nobuyoshi Nakada - Date: 2019-10-25 00:54:24 +0900 - - Set method locations - -commit 2ea698969ec92e6442e9a4cf93217d5a690cb559 - Author: git - Date: 2019-10-25 00:16:26 +0900 - - * 2019-10-25 [ci skip] - -commit 6279e45cdefa3e61ca1c9c8085b15727cb2f4a60 - Author: Nobuyoshi Nakada - Date: 2019-10-25 00:06:43 +0900 - - Arguments forwarding is not allowed in lambda [Feature #16253] - -commit 1fb45848257e3a599809c6cac52338999e604da0 - Author: Jeremy Evans - Date: 2019-10-22 05:08:22 +0900 - - Remove unused output_method argument - - Fixes Ruby Bug 9876. - -commit 8439caab0ac91aa33176060bb81cb4197ab21069 - Author: Nobuyoshi Nakada - Date: 2019-10-24 23:37:19 +0900 - - Refined `rp` output [ci skip] - - So that the result structure can be accessed as `$number` - variables, not a mere `VALUE`. - -commit dc44ab2913719a7d9b78012f277b9fe02868c172 - Author: Hiroshi SHIBATA - Date: 2019-10-24 19:53:33 +0900 - - Revert "[ruby/fiddle] Fix a failing test (#13)" - - This reverts commit 5ebb0d50f6560b35bc03deb79341a115c5f782ee. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2603 - -commit de5ee47c3da9d06e8dcffa35e4e7f9b5a3122907 - Author: Hiroshi SHIBATA - Date: 2019-10-24 19:53:26 +0900 - - Revert "[ruby/fiddle] test: use env Hash" - - This reverts commit 4d844cbaed518743776594fa5ae33b86fe176ad1. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2603 - -commit efd641ffab34e433a8d8a7d78914576f2425aa90 - Author: Hiroshi SHIBATA - Date: 2019-10-24 19:52:54 +0900 - - Revert "[ruby/fiddle] Use ffi_closure_free by default. (#20)" - - This reverts commit ce6caade7c57a505f73086ccd7b33c14f7715f22. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2603 - -commit f126d80b1e4f42e854555e728cd4478fc7ff56db - Author: Jeremy Evans - Date: 2019-10-19 03:40:36 +0900 - - [ruby/webrick] Don't check tainting in access log escaping - - Only untaint result on Ruby <2.7, as taint support is deprecated - in Ruby 2.7+ and no longer has an effect. - - https://github.com/ruby/webrick/commit/4c430f9410 - -commit c28d50a753615dff9bd721f608846d4ef541feb1 - Author: Jeremy Evans - Date: 2019-08-27 14:22:00 +0900 - - [ruby/webrick] Support literal IPv6 addresses in X-Forwarded-Host - - https://github.com/ruby/webrick/commit/6b6990ec81 - -commit 37c266aa57fc2c6798a7b6002867643ef0424fa1 - Author: Jeremy Evans - Date: 2019-08-07 07:48:18 +0900 - - [ruby/webrick] Remove the squishing of whitespace in header values - - While the stripping of header values is required by RFC 2616 4.2 and - RFC 7230 3.2.4, the squishing is not and can break things, such as - when one header contains an HMAC of another header. - - Fixes Ruby Bug 7021. - - https://github.com/ruby/webrick/commit/8b96088a86 - -commit 84ed4c3d59a3317c6aff017e88f0ea897dbf8410 - Author: Hiroshi SHIBATA - Date: 2019-10-04 22:51:39 +0900 - - [ruby/webrick] bump version to 1.5.0 - - https://github.com/ruby/webrick/commit/00c281caa7 - -commit 8189d496dff2e3f892338eed13e15816684bb220 - Author: Jeremy Evans - Date: 2019-07-08 11:17:10 +0900 - - [ruby/webrick] Remove Webrick::HTTPResponse#to_s - - It is currently broken, and even if it worked, it can cause problems - when debugging. See Ruby Bug 10715. - - https://github.com/ruby/webrick/commit/575dea8656 - -commit f0452574b16462d0edea16e9b22e55e21e146a49 - Author: thekuwayama - Date: 2019-07-05 23:25:47 +0900 - - [ruby/webrick] after ruby-2.6.0, set Net::HTTP#write_timeout - - https://github.com/ruby/webrick/commit/3b51f6b4d2 - -commit b809784817649817c3e53fa000f57504446caef9 - Author: Jeremy Evans - Date: 2019-10-20 08:10:47 +0900 - - [ruby/fiddle] Remove taint support (#21) - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous Ruby versions. - https://github.com/ruby/fiddle/commit/18d6fb6915 - -commit ce6caade7c57a505f73086ccd7b33c14f7715f22 - Author: Vít Ondruch - Date: 2019-07-11 06:19:32 +0900 - - [ruby/fiddle] Use ffi_closure_free by default. (#20) - - * Use ffi_closure_free unconditionally. - - The current conditionals reflect historic heritage of FFI. Usage of - ffi_closure_free should be better default nowadays, because libffi 3.0.5 - fixing issues of ffi_closure_free should be widely available. - - * RUBY_LIBFFI_MODVERSION is not used anymore. - - Because `ffi_closure_free()` is not used unconditionally, there is no - other use for RUBY_LIBFFI_MODVERSION define, so drop its usage. - - * Use more meaningful variable name. - - `ver` variable used to be used to pupulate RUBY_LIBFFI_MODVERSION - define. Since the define was removed, the `libffi_dir` variable name - should better describe the remaining usage of the variable. - - https://github.com/ruby/fiddle/commit/c49cc79eb8 - -commit 30d46966a97968d166f2f1440f227c2b52483780 - Author: Nobuyoshi Nakada - Date: 2019-06-13 16:08:22 +0900 - - [ruby/fiddle] Use RbConfig::SIZEOF (#19) - - - https://github.com/ruby/fiddle/commit/ea06b28db8 - -commit 4d844cbaed518743776594fa5ae33b86fe176ad1 - Author: Sutou Kouhei - Date: 2019-05-28 06:04:19 +0900 - - [ruby/fiddle] test: use env Hash - - https://github.com/ruby/fiddle/commit/a01a962342 - -commit 5ebb0d50f6560b35bc03deb79341a115c5f782ee - Author: Kenta Murata - Date: 2019-05-27 18:53:33 +0900 - - [ruby/fiddle] Fix a failing test (#13) - - * Fix a failing test - - This commit fixes the following failure: - - ``` - 1) Failure: - Fiddle::TestImport#test_no_message_with_debug [/Users/mrkn/src/github.com/ruby/fiddle/test/fiddle/test_import.rb:152]: - - 1. [2/2] Assertion for "stderr" - | <[]> expected but was - | <["Exception `NameError' at /Users/mrkn/.rbenv/versions/2.5.1/lib/ruby/2.5.0/fiddle/import.rb:157 - uninitialized constant Fiddle::Function::STDCALL"]>. - ``` - - * Stop using Bundler.with_clean_env - - * Clear existing Ruby environment variables on test_no_message_with_debug - - https://github.com/ruby/fiddle/commit/13133ddec8 - -commit 7733db665ad07980afcaa5bc3fadebc0128fbdf2 - Author: Aaron Patterson - Date: 2019-01-10 09:22:26 +0900 - - [ruby/fiddle] Fiddle::Function must maintain a reference to the closure - - If the first parameter to Fiddle::Function is a closure object (rather - than an integer), `rb_Integer` will cast it to an integer but not - maintain a reference to the closure. Then if the closure gets GC'd, we - have a segv. This commit keeps a reference to the original parameter to - initialize so that the object will not be GC'd. - - Fixes: https://bugs.ruby-lang.org/issues/13286 - - https://github.com/ruby/fiddle/commit/0fc697bbc5 - -commit 70ca56dedaa7ced969269ed70112ebb8da653ec2 - Author: Hiroshi SHIBATA - Date: 2019-10-24 18:50:57 +0900 - - Temporarily skipped with upstream changes of Date library. - -commit 487d96c6b1cd7f5d415dba27a9684b30dfa9afed - Author: Hiroshi SHIBATA - Date: 2019-08-03 20:37:51 +0900 - - [ruby/date] Use Gemfile instead of Gem::Specification#add_development_dependency. - - https://github.com/ruby/date/commit/13c94362c2 - -commit 9d3a4ab05bc74d880ca25c2bf0ef48e60f8199af - Author: zverok - Date: 2019-08-11 19:56:41 +0900 - - [ruby/date] Update docs - - https://github.com/ruby/date/commit/8c02586a98 - -commit 913807bd6ce98d3d362d27caef4f5e2aef0e5d79 - Author: zverok - Date: 2019-08-11 19:50:20 +0900 - - [ruby/date] Simplify #inspect - - https://github.com/ruby/date/commit/af01edd7d8 - -commit 2e37c1960a0b84a9018dc0202a36daf4e692ed46 - Author: Jeremy Evans - Date: 2019-10-19 03:56:05 +0900 - - [ruby/date] Remove taint support - - Ruby 2.7 deprecates taint and it no longer has an effect. - The lack of taint support should not cause a problem in - previous versions. - - https://github.com/ruby/date/commit/519470dc3b - -commit fc0e8d00bc50ac8646b37adee3b599c83ce84a41 - Author: Jeremy Evans - Date: 2019-08-26 02:01:13 +0900 - - [ruby/date] Support -Float::INFINITY...date ranges - - Fixes Ruby Bug 12961 - - https://github.com/ruby/date/commit/7f533c2552 - -commit 4e40ca301cca692361627ac6db06c0f0074636f0 - Author: Jeremy Evans - Date: 2019-07-25 00:03:27 +0900 - - [ruby/date] Check for numeric arguments in constructors - - Previously, the type of these arguments were not checked, leading to - NoMethodErrors in some cases, and TypeErrors in other cases, but not - showing what field was having the problems. This change makes it so - the field with the problem is included in the error message. - - For the valid_*? methods, this changes them to return false if one - of the arguments that should be numeric is not. - - Fixes Ruby Bug 11935 - Fixes Ruby Misc 15298 - - https://github.com/ruby/date/commit/a2f4b665f8 - -commit 9eb798a3f1de6a9e08e510904d376952d5e94d50 - Author: Jeremy Evans - Date: 2019-07-18 06:53:55 +0900 - - [ruby/date] Make julian dates roundtrip through to_time.to_date - - Previously, julian dates would not round trip through to_time.to_date, - because Time is always considered gregorian. This converts the Date - instance from julian to gregorian before converting to Time, ensuring - that an equal date object will be returned if converting that Time - back to Date. - - This does result in julian Date objects showing different day values - if converting to Time. - - Fixes Ruby Bug 8428. - - https://github.com/ruby/date/commit/d8df64555e - -commit f1de438380893682257b8648784a0fe7714b1f9f - Author: Alan Wu - Date: 2019-10-22 01:56:44 +0900 - - Use CPDEBUG for debug code - - Notes: - Merged: https://github.com/ruby/ruby/pull/2564 - -commit 89e7997622038f82115f34dbb4ea382e02bed163 - Author: Alan Wu - Date: 2019-07-31 10:36:05 +0900 - - Combine call info and cache to speed up method invocation - - To perform a regular method call, the VM needs two structs, - `rb_call_info` and `rb_call_cache`. At the moment, we allocate these two - structures in separate buffers. In the worst case, the CPU needs to read - 4 cache lines to complete a method call. Putting the two structures - together reduces the maximum number of cache line reads to 2. - - Combining the structures also saves 8 bytes per call site as the current - layout uses separate two pointers for the call info and the call cache. - This saves about 2 MiB on Discourse. - - This change improves the Optcarrot benchmark at least 3%. For more - details, see attached bugs.ruby-lang.org ticket. - - Complications: - - A new instruction attribute `comptime_sp_inc` is introduced to - calculate SP increase at compile time without using call caches. At - compile time, a `TS_CALLDATA` operand points to a call info struct, but - at runtime, the same operand points to a call data struct. Instruction - that explicitly define `sp_inc` also need to define `comptime_sp_inc`. - - MJIT code for copying call cache becomes slightly more complicated. - - This changes the bytecode format, which might break existing tools. - - [Misc #16258] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2564 - -commit 38e931fa2ceac6d922f3eabedb8f35f211de0bdb - Author: Koichi Sasada - Date: 2019-10-24 16:28:15 +0900 - - show "transferred" attribute on Fiber#to_s - - If a fiber is invoked with transfer method (such as "f.transfer"), - then the invoked fiber ("f") is labeled as "transferred" and this - fiber can not be invoked with Fiber#resume. This patch adds - transferred attribute for "Fiber#to_s" (and inspect). - -commit 4c3e3b8028ca76fcaedc0e40d9ac678e3ac79ee9 - Author: Koichi Sasada - Date: 2019-10-24 15:03:26 +0900 - - Revert "Fix Fiber#transfer" - - This reverts commit fa8ac91e957a076f6df1adaecad7896817138009. - - Previous behavior is intentional. - -commit 65e8267938a260620bbfe1c1d97e67dde8c31f6c - Author: Hiroshi SHIBATA - Date: 2019-10-24 16:17:17 +0900 - - Revert "Fixed the require path for e2mmap version file." - - This reverts commit ff953a003e03f5f070112ececefab4c07ff4cb0e. - -commit ff953a003e03f5f070112ececefab4c07ff4cb0e - Author: Hiroshi SHIBATA - Date: 2019-10-24 16:12:34 +0900 - - Fixed the require path for e2mmap version file. - -commit 2791989a311d14fbd69dd1ea0c1eeac521382427 - Author: Hiroshi SHIBATA - Date: 2019-10-24 16:11:01 +0900 - - Fixed sync path of e2mmap structure for gemspec. - -commit 281f754126a9edf003e347f28ab20e154e22464d - Author: Yusuke Endoh - Date: 2019-10-24 08:30:33 +0900 - - include/ruby/backward/cxxanyargs.hpp: call `va_end` before return - - Coverity Scan complains it. - -commit f26f0f41096c026e4874bf1af8d500a7aaa69e59 - Author: Yusuke Endoh - Date: 2019-10-24 08:04:45 +0900 - - hash.c: Do not use Unicode double-quotes - - It made rdoc fail. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu1804/ruby-master/log/20191023T183005Z.fail.html.gz - ``` - RDoc is not a full Ruby parser and will fail when fed invalid ruby programs. - - The internal error was: - - (ArgumentError) invalid byte sequence in US-ASCII - - uh-oh! RDoc had a problem: - invalid byte sequence in US-ASCII - ``` - -commit df91896f32fdf78c26fc38466927c0bd87444185 - Author: BurdetteLamar - Date: 2019-10-21 02:28:22 +0900 - - More rdoc for ENV#[] and ENV#fetch - - Notes: - Merged: https://github.com/ruby/ruby/pull/2579 - -commit 6df6611ce77d1bb7d50375a1399e1d5101a3a616 - Author: aycabta - Date: 2019-10-24 02:45:15 +0900 - - Treat only left alt key as meta-key on Windows - - On German keyboard, right alt key acts as like shift key. - - Ex. right-alt-8 is just "[". This input doesn't have meta-key statement. - -commit f1d4216bd9b89835a8aa7b4e087549dc35279a7f - Author: Nobuyoshi Nakada - Date: 2019-10-24 01:42:31 +0900 - - Added refresh-gems - - Refreshes bundled gems to the latest version, and extracts them. - -commit 7391db4ab320ef66ff4b0ec7e59ec91daede2373 - Author: Nobuyoshi Nakada - Date: 2019-10-24 01:18:19 +0900 - - Updated minitest to 5.12.2 - -commit 7bc787fa06e20f26fae875c9aac2675fc056e16d - Author: aycabta - Date: 2019-10-24 00:12:52 +0900 - - Support forced enter insertion by Ctrl+Enter on Windows - -commit 659f7c0aeb46b75fec913b33fc6daa39c2f6b611 - Author: git - Date: 2019-10-24 00:00:59 +0900 - - * 2019-10-24 [ci skip] - -commit 039faecdb88546a7ad43594a870900b0b370aa9c - Author: aycabta - Date: 2019-10-23 23:58:59 +0900 - - Suppress duplicated "require 'reline'" - -commit 1d91feaf13e0ffe04b2dabc6e77e4101b6d0bb07 - Author: Nobuyoshi Nakada - Date: 2019-10-23 20:13:34 +0900 - - Limit strict RUBY_METHOD_FUNC in C++ - - Limit strict function signature check with RUBY_METHOD_FUNC in C++ - to bundled libraries only. [Bug #16271] - -commit 8bb716ab91577f2b1e21e833fb3f3170032ba881 - Author: aycabta - Date: 2019-10-22 20:42:03 +0900 - - Fix indent... - -commit 67f010af9bd08581caa474831b7ed7f21ae00f6d - Author: Nobuyoshi Nakada - Date: 2019-10-23 15:09:44 +0900 - - name2ctype.h depends on also Emoji data - -commit cbec533677654f9cb5e2a4c21c2f11ae6928bc20 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-23 13:23:43 +0900 - - Add gem names [ci skip] - -commit 5d7aef20dd972a4398ad2f047710391334b14ac3 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-23 13:18:48 +0900 - - Trivial fixes [ci skip] - -commit 959ddf44b3613e504897239e76860aae11eed635 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-23 12:00:44 +0900 - - Fix typos [ci skip] - -commit 46f175ed5c8560b3c9da5ab7b4fa73287f1eb1c5 - Author: Nobuyoshi Nakada - Date: 2019-10-23 02:53:36 +0900 - - Use cppflags to pass preprocessor options - -commit d5d58447444109a75ceb86e239827f001da6214d - Author: Nobuyoshi Nakada - Date: 2019-10-23 02:30:14 +0900 - - Use dedicated assertion methods for warning and syntax error - -commit 601f1fb456c291b5eb4d20e97d8b151bb04ffda2 - Author: Nobuyoshi Nakada - Date: 2019-10-23 02:05:28 +0900 - - Catch syntax error even if fatal - -commit afab8122c339586ccb120861cc700aa8eee7402c - Author: Nobuyoshi Nakada - Date: 2019-10-23 02:04:36 +0900 - - Fix the exception when CPDEBUG - -commit 801a11d0ab3e1d387b5aaed92d1965fbdf675780 - Author: Nobuyoshi Nakada - Date: 2019-10-23 01:05:14 +0900 - - Relaxed tests for CPDEBUG mode - -commit 1a80ee4573eef24ed7465b5c5d72dc085c74c4ff - Author: git - Date: 2019-10-23 00:42:44 +0900 - - * 2019-10-23 [ci skip] - -commit 51bab75f493d59b07382e99d54c9dd1b0b1bbdf8 - Author: Nobuyoshi Nakada - Date: 2019-10-23 00:19:25 +0900 - - Provides ruby2_keywords - - So that requiring it succeeds even if that forward compatibility - gem is not installed. - -commit 8390057d1ee9acd67ac9f36dee59f500b1f1bc5f - Author: Nobuyoshi Nakada - Date: 2019-10-22 22:49:41 +0900 - - Benchmark for [Feature #16155] - -commit 99ca5705a24d540b95fb7069707514c1510f1a81 - Author: NARUSE, Yui - Date: 2019-10-22 22:15:52 +0900 - - tool/release.sh uses ruby-actions' result - - https://github.com/ruby/actions - -commit d736511e4253c924bcfaa7125da3b07a67b6ecbf - Author: NARUSE, Yui - Date: 2019-10-22 21:37:49 +0900 - - Move format-release to tool and fix bugs - -commit 04075305d3fd2806400235dfc744b6a0c70ef738 - Author: Nobuyoshi Nakada - Date: 2019-10-22 21:33:11 +0900 - - Ignore timestamp file for the expected failure [ci skip] - -commit aec0a293a4f9d2f8f8d085f57023ec3ba4bf6525 - Author: NARUSE, Yui - Date: 2019-10-22 21:12:50 +0900 - - Add a tool to generate a patch for www from log - - Receives an output of `tool/make-snapshot` and genarete - * Markdown format for release note - * a patch for branches.yml, downloads.yml, and releases.yml of w.r-l.o - -commit ed3333f8736e054a2199a3b77e553b858c5fc7e6 - Author: Nobuyoshi Nakada - Date: 2019-10-22 21:05:52 +0900 - - make-snapshot: Regexp#match raises on nil now - -commit 501b517dfbab2a552e68da2da30682261b134156 - Author: Yusuke Endoh - Date: 2019-10-22 20:06:07 +0900 - - NEWS: add a URL about the performance improvement of CGI.escapeHTML - -commit 02aadf1032d71a3f81653a955f2635c8853b0aca - Author: Yusuke Endoh - Date: 2019-10-22 19:46:44 +0900 - - NEWS: Fix the example of Lazy#eager - -commit fac4339a1273df64fe764579f0d3ccccf64b74b4 - Author: Yusuke Endoh - Date: 2019-10-22 19:39:42 +0900 - - NEWS: add an example for Lazy#eager - -commit 0e735b218fbf0d329c4e76e79dbabda27a32d9c7 - Author: Yusuke Endoh - Date: 2019-10-22 19:32:04 +0900 - - NEWS: Make Net::FTP#features and #option more informative - -commit 22845176d70576ea9a331dca019c46d3c0605f12 - Author: MSP-Greg - Date: 2019-10-22 06:36:38 +0900 - - test/ruby/test_exception typo fix - -commit 5e0d33a85675663f47956815a0b70f3e4d1d9bc1 - Author: MSP-Greg - Date: 2019-10-22 06:36:10 +0900 - - appveyor.yml - remove timezone & tzinfo gems from MSVC builds - - Not compatible with concurrent-ruby dependency - -commit 97a03a035695e948ce6b3a0f91bfd0302fbc30de - Author: Alan Wu - Date: 2019-10-22 01:44:16 +0900 - - Add a cron job to keep CPDEBUG working - - Notes: - Merged: https://github.com/ruby/ruby/pull/2586 - -commit 9c553139ae7275f7f24694e54a35266c5c5d5e1c - Author: Alan Wu - Date: 2019-10-22 01:29:47 +0900 - - Fix build for CPDEBUG=1 - - The declarations went out-of-sync in dcfb7f6. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2586 - -commit fa8ac91e957a076f6df1adaecad7896817138009 - Author: Jeremy Evans - Date: 2019-10-22 08:54:58 +0900 - - Fix Fiber#transfer - - Fiber#transfer previously made it impossible to resume the fiber - if it was transferred to (no resuming the target of Fiber#transfer). - However, the documentation specifies that you cannot resume a fiber - that has transferred to another fiber (no resuming the source of - Fiber#transfer), unless control is transferred back. - - Fix the code by setting the transferred flag on the current/source - fiber, and unsetting the transferred flag on the target fiber. - - Fixes [Bug #9664] - Fixes [Bug #12555] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2588 - - Merged-By: jeremyevans - -commit f37cc1c719f12d2cad6032aa4e6f4236f0604992 - Author: Jeremy Evans - Date: 2019-07-08 10:51:42 +0900 - - Fallback to TCP in resolv if UDP bind raises EACCES - - Original patch from Andy Grimm. - - Fixes [Bug #10747] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2587 - -commit 62d43828770211470bcacb9e943876f981b5a1b4 - Author: Nobuyoshi Nakada - Date: 2019-10-19 03:05:03 +0900 - - Arguments forwarding [Feature #16253] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2575 - -commit 35f90bf1b9b06f93e919af3c4095b7aff903d799 - Author: Nobuyoshi Nakada - Date: 2019-10-22 01:27:49 +0900 - - NEWS: fixed method names [ci skip] - -commit 6067c0a220181a3627e60264907fd321e417ac04 - Author: Nobuyoshi Nakada - Date: 2019-10-22 01:27:26 +0900 - - NEWS: fixed mark-up [ci skip] - -commit 349ad6178c1ba5674a132dce05c7a8264b4d50c6 - Author: git - Date: 2019-10-22 01:07:35 +0900 - - * 2019-10-22 [ci skip] - -commit ee302f54a0b32352faac30758cf91f502997fe1f - Author: Koichi Sasada - Date: 2019-10-21 17:09:52 +0900 - - add an NEWS entry about [Feature #15575] - -commit 9bbc28340e62a732d1fad3676b7a81019bda2db6 - Author: Koichi Sasada - Date: 2019-10-21 17:00:16 +0900 - - add a NEWS entry about Proc#to_s change - -commit 0f0d05a3b11e6fe933c52e018900bac2bb6c9fc6 - Author: Koichi Sasada - Date: 2019-10-21 16:59:52 +0900 - - fix NEWS entry about unbundled gems - -commit ec2da08e2b65902168d7f4a6bed86c6c8842aa02 - Author: Nobuyoshi Nakada - Date: 2019-10-21 21:30:47 +0900 - - NEWS: fixed indents [ci skip] - -commit 228ebdbf2fe65c673be8b6240cdec4f1b266eb2f - Author: Yusuke Endoh - Date: 2019-10-21 21:26:47 +0900 - - NEWS: fix a typo - -commit f364564e66d1db1de8e80d669287386595c8bc46 - Author: Yusuke Endoh - Date: 2019-10-21 21:22:53 +0900 - - bignum.c (estimate_initial_sqrt): prevent integer overflow - - `Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)` caused assertion failure - because of integer overflow. [ruby-core:95453] [Bug #16269] - -commit c8f97d16202a953a66a326b450a82d926f0fea9c - Author: Yusuke Endoh - Date: 2019-10-21 18:46:54 +0900 - - NEWS: structured the "Language changes" section - - There were too many items in the section in somewhat random order. - This change creates the following five subsections: - - * Pattern matching - * The spec of keyword arguments is changed towards 3.0 - * Numbered parameter - * proc/lambda without no block is deprecated - * Other miscellaneous changes - - Also it adds a handful of example code. - -commit 5d63a9da40b452d0455923b6838a961224c933bc - Author: Nobuyoshi Nakada - Date: 2019-10-21 17:45:27 +0900 - - [Bug #16121] adjusted indent [ci skip] - -commit b9702590445dfea62d271d0a5c942b7adfaaacdd - Author: Dylan Thacker-Smith - Date: 2019-10-21 17:29:21 +0900 - - Stop making a redundant hash copy in Hash#dup (#2489) - - * Stop making a redundant hash copy in Hash#dup - - It was making a copy of the hash without rehashing, then created an - extra copy of the hash to do the rehashing. Since rehashing creates - a new copy already, this change just uses that rehashing to make - the copy. - - [Bug #16121] - - * Remove redundant Check_Type after to_hash - - * Fix freeing and clearing destination hash in Hash#initialize_copy - - The code was assuming the state of the destination hash based on the - source hash for clearing any existing table on it. If these don't match, - then that can cause the old table to be leaked. This can be seen by - compiling hash.c with `#define HASH_DEBUG 1` and running the following - script, which will crash from a debug assertion. - - ```ruby - h = 9.times.map { |i| [i, i] }.to_h - h.send(:initialize_copy, {}) - ``` - - * Remove dead code paths in rb_hash_initialize_copy - - Given that `RHASH_ST_TABLE_P(h)` is defined as `(!RHASH_AR_TABLE_P(h))` - it shouldn't be possible for a hash to be neither of these, so there - is no need for the removed `else if` blocks. - - * Share implementation between Hash#replace and Hash#initialize_copy - - This also fixes key rehashing for small hashes backed by an array - table for Hash#replace. This used to be done consistently in ruby - 2.5.x, but stopped being done for small arrays in ruby 2.6.x. - - This also bring optimization improvements that were done for - Hash#initialize_copy to Hash#replace. - - * Add the Hash#dup benchmark - -commit 8b8b9c1a1fdb26f9b0470391234d8c935b083577 - Author: Koichi Sasada - Date: 2019-10-21 16:48:37 +0900 - - add a NEWS entry about [Feature #15602] - -commit 431132f037aecc8c9bc783fea257db653c4f8cb0 - Author: Nobuyoshi Nakada - Date: 2019-10-21 12:20:19 +0900 - - Pass the called keyword arguments if `keyword_init` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2582 - -commit 215e4b8721d968b83c66c253e6da15b90520f679 - Author: git - Date: 2019-10-21 11:50:44 +0900 - - * expand tabs. [ci skip] - - Tabs were expanded because previously the file did not have any tab indentation. - Please update your editor config, and use misc/expand_tabs.rb in the pre-commit hook. - -commit 44da5a1c872879b05acab045263d0d4f906f04ba - Author: Nobuyoshi Nakada - Date: 2019-10-21 11:45:54 +0900 - - Look up event ID offsets by token as index - -commit 375124be51c796a53cce9716e83003ef37c7bcf5 - Author: K.Takata - Date: 2019-07-30 12:08:33 +0900 - - st: Do error check only on non-Ruby - - Notes: - Merged: https://github.com/ruby/ruby/pull/2304 - -commit e70e81b54e10f1882874884564454f566c41b0dd - Author: K.Takata - Date: 2019-07-29 21:38:05 +0900 - - st: Add NULL checking - - These are found by Coverity. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2304 - -commit 263ee6639d6f9f599613a20731c0646d125e0813 - Author: Nobuyoshi Nakada - Date: 2019-10-21 09:12:38 +0900 - - Make suggestions order stable [Bug #16263] - - As the result order of `DidYouMean::SpellChecker#correct` is - undefined, keep the order of the original candidates. - -commit 71ffe40a447a17a1c3388374b7c9979c826b131d - Author: MSP-Greg - Date: 2019-10-21 08:30:42 +0900 - - test/optparse/test_did_you_mean.rb - fix suggestion order - - Notes: - Merged: https://github.com/ruby/ruby/pull/2581 - -commit 27261007eb45adae4d5b30cbafa2ef27a2345b3f - Author: Nobuyoshi Nakada - Date: 2019-10-21 09:27:25 +0900 - - DidYouMean can be an empty stub module [Bug #16263] - -commit 1d29c9bd4601ef2783b5bb7de78ebf43cb282607 - Author: git - Date: 2019-10-21 09:11:47 +0900 - - * 2019-10-21 [ci skip] - -commit 92234667526dfb66cfeff0eab49fa3e7588ff73e - Author: MSP-Greg - Date: 2019-10-20 07:23:18 +0900 - - test_exception - fix with & w/o did_you_mean - - See Ruby issue 16263 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2577 - -commit ca7de0334d26b28eb8fd731b130404beb5cf5c12 - Author: Nobuyoshi Nakada - Date: 2019-10-20 20:45:56 +0900 - - Also BDOT2 and BDOT3 are operators - -commit 9e07dfd253f5086b306d5e32d3ef4238a8510bc2 - Author: Koichi Sasada - Date: 2019-10-20 16:16:54 +0900 - - show BASERUBY version at configure. - -commit a236eaa762137d7cb32b8311e0ef9a74bbb0f385 - Author: Koichi Sasada - Date: 2019-10-20 15:45:30 +0900 - - Native MonitorMixin::ConditionVariable#wait - - MonitorMixin::ConditionVariable#wait can be interrupted just after - Monitor#exit_for_cond. So implementation in C. - -commit a0a3c701816c2fe4ab6e940c6cf5638756ceb6dc - Author: Koichi Sasada - Date: 2019-10-20 14:21:04 +0900 - - delegate synchronize method - - Delegate MonitorMixin#synchronize body to Monitor#synchronize. - It makes guarantee interrupt safe (because Monitor#synchronize is - written in C). I thought Ruby implementation is also safe, but I - got stuck failure - so that I introduce this fix to guarantee interrupt safe. - -commit caac5f777ae288b5982708b8690e712e1cae0cf6 - Author: Koichi Sasada - Date: 2019-10-20 04:52:20 +0900 - - make monitor.so for performance. (#2576) - - Recent monitor.rb has performance problem because of interrupt - handlers. 'Monitor#synchronize' is frequently used primitive - so the performance of this method is important. - - This patch rewrite 'monitor.rb' with 'monitor.so' (C-extension) - and make it faster. See [Feature #16255] for details. - - Monitor class objects are normal object which include MonitorMixin. - This patch introduce a Monitor class which is implemented on C - and MonitorMixin uses Monitor object as re-entrant (recursive) - Mutex. This technique improve performance because we don't need - to care atomicity and we don't need accesses to instance variables - any more on Monitor class. - - Notes: - Merged-By: ko1 - -commit 434966bffddd4299d34f5d1f7f225bf7396d0807 - Author: git - Date: 2019-10-20 02:58:58 +0900 - - * 2019-10-20 [ci skip] - -commit f2ed8466d3fd3c80b6ad88791c9e92c2f95efa0b - Author: Nobuyoshi Nakada - Date: 2019-10-20 02:58:24 +0900 - - Fixed a typo [ci skip] - -commit 1d435bd51aeca75f6e437bc92de2271a716a1ced - Author: Nobuyoshi Nakada - Date: 2019-10-19 15:57:25 +0900 - - Extend Ripper DSL to set to pseudo variables other than `$$` - -commit 5c81e19b196e940b3233781b7ef0c5bfcbdee4f5 - Author: MSP-Greg - Date: 2019-10-19 03:03:54 +0900 - - appveyor.yml - MinGW - update for MSYS2 / Mingw-w64 (#2573) - - MSYS source code comes from both gcc.gnu.org & Mingw-w64. Updates to the Mingw-w64 source broke the MinGW build step. - - Fixes the issue until Mingw-w64 updates their source, then it should be reverted, see comments in code. - -commit 7dcc24fd81d841718ab2f3b616be084b70adaa89 - Author: git - Date: 2019-10-19 00:51:37 +0900 - - * 2019-10-19 [ci skip] - -commit bf934e48128774717997b036301e27e5fbccc3ce - Author: Nobuyoshi Nakada - Date: 2019-10-19 00:50:17 +0900 - - Fixed passing idNil as a Symbol - -commit 9cb809cfefafc58cc0bf56184ecc94aec3c41c1d - Author: Nobuyoshi Nakada - Date: 2019-10-18 22:17:06 +0900 - - Verbatim texts need more indent [ci skip] - - And separate ruby script and executed example. - -commit 58e2ca31dbbae9bb54917c9b3cc88fc138454eeb - Author: Kazuhiro NISHIYAMA - Date: 2019-10-18 20:24:36 +0900 - - Use `_` instead of `_n_` - -commit ddad1fb229421be3dc4b0a3031cb410b62a233a9 - Author: Yusuke Endoh - Date: 2019-10-18 17:53:17 +0900 - - NEWS: Mention that optparse now supports did_you_mean for unknown option - -commit e2b719bed640d4813fd5f753c80d33d01c612078 - Author: Nobuyoshi Nakada - Date: 2019-10-18 17:46:53 +0900 - - Support DidYouMean by AmbiguousOption too - -commit b4d308b41939659fe8a4df28afc82eb5205709d1 - Author: Nobuyoshi Nakada - Date: 2019-10-18 17:39:16 +0900 - - Defer adding additional info until getting the message of an error - -commit e29e49abf018730d8419b4797ff17942e00d810b - Author: Nobuyoshi Nakada - Date: 2019-10-18 16:43:40 +0900 - - Default DidYouMean.formatter to PlainFormatter - -commit d4e52f672cf520d6929d22310a340e09fcb0e35d - Author: Nobuyoshi Nakada - Date: 2019-10-18 15:19:26 +0900 - - Added no suggestion test case - -commit 46fa301e82d50161fc7ec8e455d9d498b15b2c7a - Author: Nobuyoshi Nakada - Date: 2019-10-18 15:15:59 +0900 - - Use DidYouMean.formatter - - Instead of building messages separately. - -commit e50b8949fad96a30226e4122172822a2a4c7301d - Author: Nobuyoshi Nakada - Date: 2019-10-18 14:59:26 +0900 - - Suppress numbered parameter warnings - -commit 095cdca15b430fb5973b1540d92a29598552adba - Author: Nobuyoshi Nakada - Date: 2019-10-18 14:03:28 +0900 - - Make weakmap finalizer an ifunc lambda - - Simple comparison between proc/ifunc/method invocations: - - ``` - proc 15.209M (± 1.6%) i/s - 76.138M in 5.007413s - ifunc 15.195M (± 1.7%) i/s - 76.257M in 5.020106s - method 9.836M (± 1.2%) i/s - 49.272M in 5.009984s - ``` - - As `proc` and `ifunc` have no significant difference, chosen the - latter for arity check. - -commit ce7942361d1f1f9a1ca958b6979a432da2014683 - Author: Nobuyoshi Nakada - Date: 2019-10-18 02:51:15 +0900 - - Use identhash as WeakMap - - As ObjectSpace::WeakMap allows FLONUM as a key, needs the special - deal for its hash. [Feature #16035] - -commit c3b64a86bcd7773c081f5049115c57ec73d7a76a - Author: Yusuke Endoh - Date: 2019-10-16 16:31:41 +0900 - - lib/optparse.rb: Show a did_you_mean hint for unknown option - - ``` - require 'optparse' - - OptionParser.new do |opts| - opts.on("-f", "--foo", "foo") {|v| } - opts.on("-b", "--bar", "bar") {|v| } - opts.on("-c", "--baz", "baz") {|v| } - end.parse! - ``` - - ``` - $ ruby test.rb --baa - Traceback (most recent call last): - test.rb:7:in `
': invalid option: --baa (OptionParser::InvalidOption) - Did you mean? baz - bar - ``` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2561 - -commit 5ca5529d223ee962451685badc9e928ea87dbb44 - Author: Seiei Miyagi - Date: 2019-10-18 01:34:18 +0900 - - Fix warning of generated parser for nested module - - Notes: - Merged: https://github.com/ruby/ruby/pull/2571 - -commit 1d564acedc820e91c585cb4850844a09f9a6af96 - Author: Aaron Patterson - Date: 2019-10-18 05:35:26 +0900 - - Remove unused constant. - - This constant isn't used, so lets remove it. - -commit 9026e12f93bb0f3f63d7449cdb5eabb2e660088f - Author: Aaron Patterson - Date: 2019-10-18 05:30:09 +0900 - - Look up constant instead of caching in a global - - The global can go bad if the compactor runs, so we need to look up the - constant instead of caching it in a global. - -commit ee821e90741ebedc6c7a3bb0e8b67e59f3a44022 - Author: Jeremy Evans - Date: 2019-10-18 02:16:32 +0900 - - Update test to handle x32 ABI compiled Ruby on Linux - - Suggestion from Laurence Parry. - - Fixes [Bug #16030] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2572 - -commit 8c0629ba58c5c95b970a657493d261356eedea1d - Author: aycabta - Date: 2019-10-18 02:51:12 +0900 - - Treat key sequences from getwch() that start from 0 or 0xE0 correctly - -commit 58657fa134852311ce6ce2827f72ba2d1b29a8bb - Author: aycabta - Date: 2019-10-18 02:31:17 +0900 - - Add numeric keypad key sequences on Windows - -commit 53c05a6cf4bb1713d9db63b6e292644bead16da6 - Author: aycabta - Date: 2019-10-18 02:29:13 +0900 - - Remove freeze - -commit 13b106a19c9c819fb0c887beb4787ab894cdba6c - Author: aycabta - Date: 2019-10-18 02:15:53 +0900 - - Ignore the input method key sequence from getwch() correctly - - The function getwch() returns some key sequences which start from 0 or 0xE0 - with a following key code. Alt+` that is on/off key for input methods gives 0 - and 41 so Reline was always ignoring 0 and following keys but numeric keypad - keys give 0 and following actual keys. This commit changes the behavior to be - ignoring only the 0 and 41 sequence. - -commit 0162e7e6471b639dfeeded29943e9e27c9519826 - Author: Jeremy Evans - Date: 2019-08-12 08:22:58 +0900 - - Make circular argument reference a SyntaxError instead of a warning - - Fixes [Bug #10314] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2569 - -commit fdfb5100b9e74cfb89b6de3649e98cb1ad85497a - Author: git - Date: 2019-10-18 00:46:02 +0900 - - * 2019-10-18 [ci skip] - -commit d1a7305848969128d3eb175a4a3b2d7f7929376a - Author: aycabta - Date: 2019-10-18 00:41:17 +0900 - - Insert multiline incremental search result correctly - -commit 4f13927f1fe06a5fe23e25448d9adc80031e0bad - Author: Nobuyoshi Nakada - Date: 2019-10-17 19:42:25 +0900 - - [DOC] no change on Windows [Bug #15267] [ci skip] - -commit e169ad93f44e1944ecf7bb65133fd34e8b868ea8 - Author: Nobuyoshi Nakada - Date: 2019-10-17 14:42:38 +0900 - - Fixed File.extname at a name ending with a dot - - File.extname now returns a dot string at a name ending with a dot. - [Bug #15267] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2565 - -commit 2a261909cc6d0767d584c0555a1c6594aacf567a - Author: git - Date: 2019-10-17 17:45:02 +0900 - - * remove trailing spaces. [ci skip] - -commit 2a22a6b2d8465934e75520a7fdcf522d50890caf - Author: Kenichi Kamiya - Date: 2019-10-17 17:44:46 +0900 - - Regexp#match{?} with nil raises TypeError as String, Symbol (#1506) - - * {String|Symbol}#match{?} with nil returns falsy - - To improve consistency with Regexp#match{?} - - * String#match(nil) returns `nil` instead of TypeError - * String#match?(nil) returns `false` instead of TypeError - * Symbol#match(nil) returns `nil` instead of TypeError - * Symbol#match?(nil) returns `false` instead of TypeError - - * Prefer exception - - * Follow empty ENV - - * Drop outdated specs - - * Write ruby/spec for above - - https://github.com/ruby/ruby/pull/1506/files#r183242981 - - * Fix merge miss - -commit 41457dcbe050a698c357b516d0a012b1b584643a - Author: aycabta - Date: 2019-10-17 16:54:06 +0900 - - Remove unused variable - -commit 60a0c20cb637ac3b2edc561dbc5888fae290b0e6 - Author: aycabta - Date: 2019-10-17 16:35:11 +0900 - - Refactor prompt generation logic - -commit 37457117c941b700b150d76879318c429599d83f - Author: Kazuhiro NISHIYAMA - Date: 2019-10-17 12:51:29 +0900 - - Use `\&` instead of `\1` with capture - -commit d5744aff3a164c358f92ef9dc2cda5c7a7612d97 - Author: Jeremy Evans - Date: 2019-10-15 01:00:42 +0900 - - Fix DRbServer#any_to_s - - My previous fix in d0ed935d5bf8c3fce9800742a36e44fb7f63dda4 was - not correct, as pointed out by cremno on GitHub. - - This simplifies things by just using Kernel#to_s. Also switch to - bind_call(obj) instead of bind(obj).call for better performance. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2554 - -commit 567e312d1f56c27ecb4fa20deac4311f05ee5507 - Author: Jeremy Evans - Date: 2019-08-09 07:44:26 +0900 - - Do not raise an exception on a closed DRb socket - - This rescues some exceptions that could happen with a closed or - shutdown DRb socket. This can prevent the server from - exiting if an client socket is closed directly after it is - accepted. - - Fixes [Bug #8039] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2554 - -commit 50b8033d6b7404670ee985de1473fffc10dd7d9c - Author: Jeremy Evans - Date: 2019-08-15 08:44:11 +0900 - - Handle subclasses of Exception in drb - - This makes it so that client instances that call a method on a - server-side object that raise a subclass of Exception are handled - similarly to those that raise a subclass of StandardError. - - Only reraise exceptions that we are fairly sure we don't want to - rescue. - - Fixes [Bug #5618] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2554 - -commit 2993b24a1ecc5fa3cc9f140bfd80669c3a3b7b9c - Author: Jeremy Evans - Date: 2019-08-25 09:11:06 +0900 - - Warn for calling public/protected/private/module_function without arguments inside method - - Calling these methods without an argument does not have the - desired effect inside a method. - - Fixes [Bug #13249] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2562 - -commit db84123600a2112063441dec4411ab5af6c3a78e - Author: aycabta - Date: 2019-10-17 02:19:01 +0900 - - Calculate prompt width correctly - -commit e26c6d4ab840c100c4f3ad20d0399598ef427c13 - Author: aycabta - Date: 2019-10-17 01:51:29 +0900 - - Collect multiline prompt logic into a method - -commit 3fea2d91ad7a1c493a25a531fcbd3f90f5a6406e - Author: Benoit Daloze - Date: 2019-10-17 01:21:18 +0900 - - Use an even indent in NEWS for code - - * Makes it easier to copy-paste and add code backticks. - -commit e003f29e2114549c7488be4440439669797e78a9 - Author: git - Date: 2019-10-17 00:29:39 +0900 - - * 2019-10-17 [ci skip] - -commit 5c80dffd0555a36a31f0da51696609a6af5e34ea - Author: Takashi Kokubun - Date: 2019-10-17 00:28:53 +0900 - - Revert "Disable ccache on arm64 build" - - This reverts commit e8124729fbeaf159ae615f61980ee10018ed5134. - - It worked once, but soon after that it stopped working again - https://travis-ci.org/ruby/ruby/jobs/598491972 - -commit 7df227804af8eefac9d82cf449cab09c086aea60 - Author: aycabta - Date: 2019-10-16 22:34:58 +0900 - - Support multiline history in incremental search - -commit f8fb51c976313b8053412c80f3f7474cdd89b4b3 - Author: Nobuyoshi Nakada - Date: 2019-10-16 21:00:36 +0900 - - Revert "alias assert_raise_message for compatibility with test-unit" - - This reverts commit 43015275b9a7f2833c93ad11ea96ae4cb3b7acd7. - - `assert_raise_message` in test-unit is different from - `assert_raise_with_message`. It checks the exception message - only, but not the exception class, - -commit 43015275b9a7f2833c93ad11ea96ae4cb3b7acd7 - Author: Nobuyoshi Nakada - Date: 2019-10-16 17:22:31 +0900 - - alias assert_raise_message for compatibility with test-unit - -commit 5437d7c879585fbdb0c294298eb76cc563e01c69 - Author: Takashi Kokubun - Date: 2019-10-16 16:11:05 +0900 - - Temporarily drop test_jit_debug.rb - - Still some CIs are failing: - https://ci.appveyor.com/project/ruby/ruby/builds/28141041/job/v4hfc99sjefqabkk - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/2317313 - - I'll fix them later. - -commit d70855c72584f303228b7821889c0b68813ec06f - Author: Nobuyoshi Nakada - Date: 2019-10-16 15:16:51 +0900 - - Added test for rdoc `--force-update` option - -commit 17ee01e3f618f15f2bec794238874a62dc60deb6 - Author: Nobuyoshi Nakada - Date: 2019-10-16 15:16:07 +0900 - - Removed an unused assignment - -commit c15856d76dd46030c805523b05808d32ead15162 - Author: Takashi Kokubun - Date: 2019-10-16 15:14:55 +0900 - - Do not test --jit-debug on -DVM_CHECK_MODE - -commit eef25f95b75f2d8312753002c4f91febaa7c866f - Author: Takashi Kokubun - Date: 2019-10-16 15:04:34 +0900 - - Maintain the intention of comment in Travis matrix - -commit 006d9013ea29ed8fe837f41796067b10df7a49ee - Author: Takashi Kokubun - Date: 2019-10-16 14:56:19 +0900 - - Remove arm64 build from Drone - - because it started to run on Travis. - -commit e8124729fbeaf159ae615f61980ee10018ed5134 - Author: Takashi Kokubun - Date: 2019-10-16 14:54:43 +0900 - - Disable ccache on arm64 build - - Follow up https://github.com/ruby/ruby/pull/2559 - - According to experiments in https://github.com/ruby/ruby/pull/2560, - disabling cache seems to make arm64 build succeed. - -commit 4ccb49bad31b3c4a9cc7c6138cae93bd60a7bec4 - Author: Takashi Kokubun - Date: 2019-10-16 14:47:20 +0900 - - Enforce --jit-debug test by another way - -commit 759576a03f0a39f3190e79526d138adc3a3f0a62 - Author: Takashi Kokubun - Date: 2019-10-16 14:01:25 +0900 - - Fix test path on travis build - -commit 2679e10942c8cebc11423cac8303bea7b4c1522a - Author: Takashi Kokubun - Date: 2019-10-16 13:37:00 +0900 - - Test without --jit-debug by default - - and let RUBY_DEBUG=1 job test it. - - We usually don't use --jit-debug and we should test no --jit-debug by - default. - -commit d97229de5c03fb3b824c6ed263de6e005fa3a86e - Author: Jun Aruga - Date: 2019-10-16 12:59:40 +0900 - - Add arm64 case on Travis. (#2559) - - misc-16234 - -commit 6081ddd6e6f2297862b3c7e898d28a76b8f9240b - Author: Jeremy Evans - Date: 2019-10-16 04:46:24 +0900 - - Dup hash with keyword flag when converted to keywords - - When ruby2_keywords is used on a method, keywords passed to the method - are flagged. When the hash is passed as the last element of an - argument splat to another method, the hash should be treated as a - keyword splat. When keyword splatting a hash, a duplicate of the - hash is made. So when auto-splatting the hash with the keyword - flag, a duplicate of the hash should also be made. - - This fixes cases where the hash is later passed to another method - and would be treated as keywords there: - - class Object - ruby2_keywords def foo(*a) bar(*a) end - def bar(*a) baz(*a) end - def baz(*a, **kw) [a, kw] end - end - foo(:a=>1) - - Previously, this would pass the :a=>1 as keywords to bar and also as - keywords to baz. Now it only passes :a=>1 as keywords to bar, but bar - passes :a=>1 as a positional hash to baz (which in this case - generates a warning in 2.7). - -commit 259601ab578885418b36138e457c2a93dd281896 - Author: aycabta - Date: 2019-10-16 02:55:45 +0900 - - Support backspace in incremental search - -commit a5245c165808b9ac0a492e218b0603e93262b449 - Author: aycabta - Date: 2019-10-16 02:08:44 +0900 - - C-r is incremental history search in vi insert mode - -commit 1c50ce2cf8347d0ecc29245cd0a2c7ede5b838dd - Author: git - Date: 2019-10-16 01:42:52 +0900 - - * 2019-10-16 [ci skip] - -commit 929d5fd3b99c1413f737ff16cf0680698036e60f - Author: Nobuyoshi Nakada - Date: 2019-10-15 22:32:10 +0900 - - Comparable#clamp with a range [Feature #14784] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2556 - -commit 375cf129189f32f7be76ac525035bcde691a63e7 - Author: Yusuke Endoh - Date: 2019-10-15 23:29:49 +0900 - - test/csv/write/test_general.rb: suppress warnings - - of "setting Encoding.default_internal". - -commit c01df7e58f34eb81bf569614091a4db428c61282 - Author: Nobuyoshi Nakada - Date: 2019-10-15 23:13:49 +0900 - - Fixed the key to delete [Bug #16250] - - https://github.com/ruby/ruby/commit/f94202fcc228d0348ca050a7b18a8f8a538a7305#commitcomment-35505076 - - Co-Authored-By: Ary Borenszweig - -commit 81176095f45a5c9f14fc61dfce041735094f893f - Author: Nobuyoshi Nakada - Date: 2019-10-15 22:38:39 +0900 - - [DOC] fixed a variable name [ci skip] - - replaced "anObject" with "obj". also marked up with simple `_`s - instead of ``. - -commit e0e93a199d28446a5d1b1289ee9466f7af01e62e - Author: Hiroshi SHIBATA - Date: 2019-10-15 20:15:28 +0900 - - [rubygems/rubygems] Bump version to 3.1.0.pre2 - - https://github.com/rubygems/rubygems/commit/a7a673ce22 - -commit 51a31b86e9d60643526980830d44f7b5134f39c0 - Author: Hiroshi SHIBATA - Date: 2019-10-15 20:21:09 +0900 - - [rubygems/rubygems] Also bump test variable - - https://github.com/rubygems/rubygems/commit/97e9768612 - -commit d2982bea679b494712f7c19afc0308be0aa2246b - Author: Kazuhiro NISHIYAMA - Date: 2019-10-15 20:18:06 +0900 - - Remove duplicated `.` [ci skip] - -commit f94202fcc228d0348ca050a7b18a8f8a538a7305 - Author: Nobuyoshi Nakada - Date: 2019-10-15 09:54:23 +0900 - - Use compare_by_identity hash [Bug #16250] - -commit b7079e538437aacf079d82c21504e44d7396926a - Author: Kazuhiro NISHIYAMA - Date: 2019-10-15 18:50:46 +0900 - - Try to avoid random failure - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20191015T070011Z.fail.html.gz - ``` - 1) Failure: - TestProcess#test_kill_at_spawn_failure [/home/chkbuild/chkbuild/tmp/build/20191015T070011Z/ruby/test/ruby/test_process.rb:2276]: - [ruby-core:69304] [Bug #11166]. - <#> expected but was - . - `` - -commit c800967acd35a763a6f09fe2b2e29870f064c22e - Author: Takashi Kokubun - Date: 2019-10-15 13:58:13 +0900 - - Simplify circular reference check of IRB::Color - -commit 96617ad1d57a13e9a282fb663ea73e4801519389 - Author: Ary Borenszweig - Date: 2019-10-15 13:25:05 +0900 - - IRB colorize: take into account recursive arrays and hashes (#2555) - - [Bug #16250] - -commit ddd42d8ebdefc520b0c7d6ada4fb0de6969a49f8 - Author: git - Date: 2019-10-15 09:55:44 +0900 - - * 2019-10-15 [ci skip] - -commit 978276a7d9249535f855088f866551b6557f321f - Author: Jeremy Evans - Date: 2019-10-15 09:43:11 +0900 - - Update documentation for File#{readable,writable,executable}{,_real}? [ci skip] - - Some OS-level security features cause these methods to not return - expected results. For example fs.protected_regular sysctl on Linux, - or pledge(2)/unveil(2) on OpenBSD. - - Fixes [Bug #16002] - -commit c3a626030235c0349e14c6bc07177810daee841c - Author: Masatoshi SEKI - Date: 2019-10-14 22:56:37 +0900 - - add require "monitor" - -commit 8488d5b5b6cc9205e8e0641c514f1f2e38bf7d1e - Author: Masatoshi SEKI - Date: 2019-10-14 20:30:22 +0900 - - Automatically close fds on fork (and GC). The connection pools are maintained at thread scope. - -commit a4cf11c10fcaadfab738d8e98712551f701eef5a - Author: Florian Frank - Date: 2017-12-21 17:57:16 +0900 - - [flori/json] fix test as reported in #343 - - https://github.com/flori/json/commit/565c72ba9e - -commit 308bbb4e10d247063889ebd9ba957e62f17978a5 - Author: Sho Hashimoto - Date: 2019-01-08 09:12:05 +0900 - - [flori/json] Add ascii_only option to JSON::Ext::Generator::State.new. - - https://github.com/flori/json/commit/0e99a9aac5 - -commit 98a9445db943c747e8d98cf7236e891eb48b5be0 - Author: Watson - Date: 2018-03-02 00:45:28 +0900 - - [flori/json] Add shortcut converting to String - - In where to convert Hash key to String for json, this patch will add shortcut for String/Symbol in Hash key. - - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 65.000 i/100ms - Calculating ------------------------------------- - json 659.576 (± 1.5%) i/s - 3.315k in 5.027127s - ``` - - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 78.000 i/100ms - Calculating ------------------------------------- - json 789.781 (± 2.7%) i/s - 3.978k in 5.041043s - ``` - - ``` - require 'json' - require 'benchmark/ips' - - obj = [] - - 1000.times do |i| - obj << { - "id" => i, - :age => 42, - } - end - - Benchmark.ips do |x| - x.report "json" do |iter| - count = 0 - while count < iter - JSON.generate(obj) - count += 1 - end - end - end - ``` - - https://github.com/flori/json/commit/38c0f6dbe4 - -commit a2f9c38a718eecef6795b4a8667589c0ef68b737 - Author: Watson - Date: 2018-03-02 00:33:18 +0900 - - [flori/json] Convert Hash object using rb_hash_foreach() - - To convert Hash convert, this part was using following pseudo code - - ``` - obj.keys.each do |key| - value = obj[key] - ... - end - ``` - - and `rb_funcall()` was called for `obj.keys`. - It might be slightly heavy to call the Ruby method. - This patch will iterate to convert Hash object about key/value using `rb_hash_foreach()` Ruby API instead of `rb_funcall()`. - - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 55.000 i/100ms - Calculating ------------------------------------- - json 558.501 (± 1.1%) i/s - 2.805k in 5.022986s - ``` - - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 65.000 i/100ms - Calculating ------------------------------------- - json 659.576 (± 1.5%) i/s - 3.315k in 5.027127s - ``` - - ``` - require 'json' - require 'benchmark/ips' - - obj = [] - - 1000.times do |i| - obj << { - "id" => i, - :age => 42, - } - end - - Benchmark.ips do |x| - x.report "json" do |iter| - count = 0 - while count < iter - JSON.generate(obj) - count += 1 - end - end - end - ``` - - https://github.com/flori/json/commit/a73323dc5e - -commit 2003755a2c491fd81496308cad97ce6304c51fe8 - Author: Nobuyoshi Nakada - Date: 2019-10-14 19:13:20 +0900 - - [flori/json] Fixed unexpected illegal/malformed utf-8 error - - flori/json@c34d01ff6a18dac04a90b2e0f820cdb1d5c7e1b2 does not - consider US-ASCII compatible but non-UTF-8 encodings, and causes - an error in RDoc tests. - - https://github.com/flori/json/commit/4f471bf590 - -commit d7fa7e2c860430a3dfa1b08be96734925b6c81d8 - Author: Watson - Date: 2018-03-03 01:16:34 +0900 - - [flori/json] Convert string encoding to UTF-8 only when needed - - ## Before - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 129.000 i/100ms - Calculating ------------------------------------- - json 1.300k (± 2.3%) i/s - 6.579k in 5.064656s - ``` - - ## After - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 189.000 i/100ms - Calculating ------------------------------------- - json 1.964k (± 3.3%) i/s - 9.828k in 5.011237s - ``` - - ## Code - ``` - require 'json' - require 'benchmark/ips' - - obj = [] - - 1000.times do |i| - obj << { - "id" => i, - :age => 42, - } - end - - Benchmark.ips do |x| - x.report "json" do |iter| - count = 0 - while count < iter - JSON.generate(obj) - count += 1 - end - end - end - ``` - - https://github.com/flori/json/commit/c34d01ff6a - -commit 40724d7d10e9902fcdc4149326acbfe4dd95d3c7 - Author: Watson - Date: 2018-03-02 00:51:30 +0900 - - [flori/json] Convert String encoding using `rb_str_encode()` - - `rb_funcall` might be slightly heavy to call the Ruby method. - This patch will convert String encoding using `rb_str_encode()` instead of `rb_funcall()`. - - ## Before - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 78.000 i/100ms - Calculating ------------------------------------- - json 789.781 (± 2.7%) i/s - 3.978k in 5.041043s - ``` - - ## After - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 129.000 i/100ms - Calculating ------------------------------------- - json 1.300k (± 2.3%) i/s - 6.579k in 5.064656s - ``` - - ## Code - ``` - require 'json' - require 'benchmark/ips' - - obj = [] - - 1000.times do |i| - obj << { - "id" => i, - :age => 42, - } - end - - Benchmark.ips do |x| - x.report "json" do |iter| - count = 0 - while count < iter - JSON.generate(obj) - count += 1 - end - end - end - ``` - - https://github.com/flori/json/commit/9ae6d2969c - -commit 641136c4af89ec2bc1f2c80aeefc7a38f3bc48df - Author: Watson - Date: 2018-03-04 23:34:26 +0900 - - [flori/json] Does not check whether illegal utf-8 if string has ascii only. - - ## Before - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 25.000 i/100ms - Calculating ------------------------------------- - json 250.478 (± 4.8%) i/s - 1.250k in 5.002238s - ``` - - ## After - ``` - $ ruby bench_json_generate.rb - Warming up -------------------------------------- - json 32.000 i/100ms - Calculating ------------------------------------- - json 360.652 (± 3.6%) i/s - 1.824k in 5.064511s - ``` - - ## Test code - ``` - require 'json' - require 'benchmark/ips' - - obj = [] - - 1000.times do |i| - obj << { - :string => "x" * 100, - :utf8 => "ã‚" * 100 - } - end - - Benchmark.ips do |x| - x.report "json" do |iter| - count = 0 - while count < iter - JSON.generate(obj) - count += 1 - end - end - end - ``` - - https://github.com/flori/json/commit/91a24ecac3 - -commit d9e50fcbeb34534d065f3662b6b952bc57994b43 - Author: Sho Hashimoto - Date: 2019-01-15 22:16:05 +0900 - - [flori/json] Pass args all #to_json in json/add/*. - - https://github.com/flori/json/commit/36a7ef6790 - -commit 7376d70cb0817158a9ce0ef433872be5ca7af56b - Author: Florian Frank - Date: 2019-04-29 22:56:14 +0900 - - [flori/json] Only attempt to resize strings not other objects - - https://github.com/flori/json/commit/167ada8da7 - -commit ede1a3dc110d3cfc094ce4cd5b27f92cab8b7b6c - Author: Kazuhiro NISHIYAMA - Date: 2019-10-14 17:30:04 +0900 - - Fix typos [ci skip] - -commit 0195966ba26b9cec9a8b32a2dc502ad753764d2a - Author: Nobuyoshi Nakada - Date: 2019-10-14 15:42:27 +0900 - - Suppress warnings for Thread.exclusive - -commit 3e763883eab8435c6ebf9427b9bc49b95a1c7175 - Author: Nobuyoshi Nakada - Date: 2019-10-14 15:10:33 +0900 - - Fixed overflow at onig_region_set - - To get rid of a bug of `onig_region_set` which takes `int`s - instead of `OnigPosition`s, set elements of `beg` and `end` - members directly, for the time being. - -commit d0ed935d5bf8c3fce9800742a36e44fb7f63dda4 - Author: Jeremy Evans - Date: 2019-10-14 14:20:32 +0900 - - Fix some DRb issues (#2552) - - * Handle BasicObject in drb - - Also fix a bug in rescue clause of any_to_s because sprintf - does not handle the %l modifier. - - Fixes [Bug #7833] - - * Do not send a reply to the client if there is a connection error - - This allows for normal TCP shutdown (fin-ack-fin-ack instead of - fin-ack-push-rst). - - Patch from pierre@mouraf.org (Pierre-Alexandre Meyer). - - Fixes [Bug #2339] - - * Detect fork and do not reuse forked connections in drb - - This associates each DRbConn with a pid, and if the pid changes, - it closes any DRbConns in the pool with a pid that no longer - matches. This fixes DRb servers from sending messages intended - for one client to another client after forking. - - Fixes [Bug #2718] - Fixes [Bug #14471] - -commit 95c420c4a65ca2e7f3edf27134ad33691959296c - Author: Sutou Kouhei - Date: 2019-10-14 12:40:50 +0900 - - Import StringScanner 1.0.3 (#2553) - - Notes: - Merged-By: kou - -commit 6fa3492362dc91cfec7eb4fd55918791da5a34fb - Author: Takashi Kokubun - Date: 2019-10-14 11:29:46 +0900 - - Eliminate the possibility to leave freed ISeq - - in active_units - - Hoping to fix: - http://ci.rvm.jp/results/trunk-mjit@silicon-docker/2311375 - -commit 183b42150962e507cd69ceddb64ad2a10f02fdfa - Author: Takashi Kokubun - Date: 2019-10-14 06:11:02 +0900 - - Delay the free until we stop referring to a unit - - `if (unit->iseq)` might have referred to a freed unit. Therefore this - commit delays its free. - -commit 673f3842dd520ac872bb003de393ba7ae558840a - Author: git - Date: 2019-10-14 02:05:30 +0900 - - * 2019-10-14 [ci skip] - -commit 26fae9aa9db59fdee7422a276662b45611e98a22 - Author: Takashi Kokubun - Date: 2019-10-14 01:59:43 +0900 - - Remove the quick stop path after convert_unit_to_func - - Now I'm not exactly sure why I needed to check `stop_worker_p` after - `mjit_copy_cache_from_main_thread` of `convert_unit_to_func` - in 4161674b2fbea6bdd01783ac5d3b39d88db22972. - If it's for avoiding deadlock under `in_gc` condition, we should keep it. - - However, if it's not the case and it's just for retrying accidental - compilation failure or just to avoid `MJIT_ATOMIC_SET` and - `compact_all_jit_code`, I think this quick stop path is not mandatory. - - Because this path is somewhat problematic in my upcoming fix in - mjit_worker, let me try to remove this first and see how CI goes. - -commit 6a1809e2e1a95c14cfb72701df480e3ebccd4b24 - Author: Burdette Lamar - Date: 2019-10-13 09:48:20 +0900 - - Enhance doc for ENV.delete - - Notes: - Merged: https://github.com/ruby/ruby/pull/2542 - -commit 6ee2fb5021c4c09b718b88089c83073997d5412f - Author: git - Date: 2019-10-13 00:54:04 +0900 - - * 2019-10-13 [ci skip] - -commit a5ecf7e0a165dff1b4604f1ed75a677c690488df - Author: Yusuke Endoh - Date: 2019-10-13 00:51:50 +0900 - - dir.c (join_path_from_pattern): check NULL from malloc - - Coverity Scan points out that all the return values of GLOB_ALLOC_N are - NULL-checked except this call. - -commit 90b9900dc159efb63feee9b0995cc5d56aef6d75 - Author: Yusuke Endoh - Date: 2019-10-13 00:49:18 +0900 - - io.c (rb_update_max_fd): fail with a negative file descripter - - Coverity Scan points out that ext/socket/unixsocket.c may pass -1 to - rb_update_max_fd. I'm unsure whether it can happen actually or not, but - it would be good for the function to reject a negative value. - -commit ebc2198d9f0292fee97e623b5e2a545fccb91d2a - Author: Yusuke Endoh - Date: 2019-10-12 22:43:34 +0900 - - re.c (match_set_string): add a check for memory allocation - - Found by Coverity Scan - -commit 7ebf9da78830cd13895a38809b0c6f1fc6797620 - Author: Nobuyoshi Nakada - Date: 2019-10-12 22:08:50 +0900 - - Also moved fallback definition of __has_attribute - -commit cb14c4a535ca95bb87d47be284f447c9325733fd - Author: Yusuke Endoh - Date: 2019-10-12 21:10:49 +0900 - - missing/setproctitle.c: remove nonsense NULL check - - If fmt is NULL, ptitle is uninitialized and used. - SETPROCTITLE(3bsd) says "If fmt is NULL, the process title is restored", - but looks like the feature is not implemented in missing/setproctitle.c. - At least the source code of ruby does not pass NULL to the function. - So I assume this function requires non-NULL fmt. - - This issue was found by Coverity Scan. - -commit f4055647115f2003ce614dd16cf68d2933f811fe - Author: Nobuyoshi Nakada - Date: 2019-10-12 18:47:06 +0900 - - Suppress deprecation warnings of MD5 from Xcode 11.1 - -commit 04333da7beb3e50daf5f53ef7fe24b253a1a26ef - Author: Nobuyoshi Nakada - Date: 2019-10-12 18:14:15 +0900 - - Suppress "clobbered" warnings by gcc 9.2.0 - -commit 710bc003791b90adf3970e137c69f283c88234cd - Author: Nobuyoshi Nakada - Date: 2019-10-12 17:21:05 +0900 - - Moved RB_METHOD_DEFINITION_DECL to intern.h - - This macro is used here before defined in ruby.h. - -commit 6333020fc924d3ae63775c032bbe8f57364cd42e - Author: Nobuyoshi Nakada - Date: 2019-10-12 14:55:55 +0900 - - atime may not updated unless strictatime is set on macOS Catalina - - Cited from mount(8): - - ``` - strictatime - Always update the file access time when reading from a - file. Without this option the filesystem may default to a - less strict update mode, where some access time updates - are skipped for performance reasons. This option could be - ignored if it is not supported by the filesystem. - ``` - -commit 92df7d98b62f48cf21cdec522f2e7b34380fd718 - Author: Sutou Kouhei - Date: 2019-10-12 14:03:21 +0900 - - Import CSV 3.1.2 (#2547) - - Notes: - Merged-By: kou - -commit d6e68bb263e79cb802fa683d9c4139ddca2fd4f5 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-12 13:25:52 +0900 - - Use `warn` with `uplevel:` instead of `caller` - -commit f6a666a1fcbb7076b57fe08bba758719cb68bdea - Author: git - Date: 2019-10-12 12:07:36 +0900 - - * 2019-10-12 [ci skip] - -commit 412cd56766a4822c48117a16d79303d3d915b28a - Author: Sutou Kouhei - Date: 2019-10-12 12:07:15 +0900 - - Import REXML 3.2.3 (#2548) - - Notes: - Merged-By: kou - -commit c866663784ea5a8f16e7fe5127127fb46ae90e6e - Author: Yusuke Endoh - Date: 2019-10-11 21:43:18 +0900 - - io.c (NUM2IOCTLREQ): Accept a value more than INT_MAX - - ioctl accepts int as request arguments on some platforms, but some - requests are more than INT_MAX, e.g., RNDGETENTCNT(0x80045200). - Passing (0x80045200 | (-1 << 32)) may work around the issue, but it may - not work on a platform where ioctl accepts unsigned long. So this - change uses NUM2LONG and then casts it to int. - -commit 9e4a53fe13d8e3ad2e284dea8034bdd6a0561d97 - Author: Yusuke Endoh - Date: 2019-10-11 21:39:21 +0900 - - test/ruby/test_rubyoptions.rb (test_encoding): skipped on Android - - On Android, nl_langinfo() always returns UTF-8 even when LANG is C. - -commit f3c4e620ac612eab6370b1fb82feaa4e651542bb - Author: Yusuke Endoh - Date: 2019-10-11 21:13:52 +0900 - - test/test_syslog.rb (test_log): skipped on Android - - On Android 28, LOG_PERROR is defined, but not implemented yet. - This change skips Syslog#log explicitly. - -commit d6c80876b7aae5b3f44abe7cf1b64161354b8ebd - Author: Kazuhiro NISHIYAMA - Date: 2019-10-11 13:50:27 +0900 - - Use `bind_call` instead of `bind` and `call` - -commit ddfb306e8e98282174cb078aa8e55aca223973ab - Author: Gabriel Nagy - Date: 2019-10-11 13:48:02 +0900 - - win32.c: Remove unused calls to StartSockets (#2312) - - NtSocketsInitialized behavior changed in e33b1690, requiring - a call to rb_w32_sysinit for starting Windows Sockets. - - This commit removes NtSocketsInitialized entirely to avoid confusion. - - Signed-off-by: Gabriel Nagy - -commit 7cc1cd3d1ed1d482ea2ec247fa6a4ad0f044418a - Author: ksss - Date: 2016-10-24 11:42:31 +0900 - - Module#define_method: Add UnboundMethod to expected classes - - Notes: - Merged: https://github.com/ruby/ruby/pull/1465 - -commit 9c24ce551d19ac0f5cac4bc9ff5ef5a7a980909d - Author: Lourens Naudé - Date: 2019-04-26 06:35:43 +0900 - - Reduce the minimum string buffer size from 127 to 63 bytes - - Notes: - Merged: https://github.com/ruby/ruby/pull/2151 - -commit 0ca4f74967bb5a439b1f3d322ae7729265b917a4 - Author: Lourens Naudé - Date: 2019-09-11 08:18:41 +0900 - - Right size the numtable in insn_make_insn_table to VM_INSTRUCTION_SIZE - - Notes: - Merged: https://github.com/ruby/ruby/pull/2447 - -commit 87958520f3fd7fdec18c3508888b3d2a4e5c27a4 - Author: takkanm - Date: 2018-06-19 20:49:09 +0900 - - set real path to __FILE__ and __dir__ in Binding#irb - - When reading Binding#irb, the file of the calling source is reflected in __FILE__ and __dir__. - - Notes: - Merged: https://github.com/ruby/ruby/pull/1896 - -commit 29c1e9a0d4c855781853f0ad41b0125f42cf504d - Author: Jeremy Evans - Date: 2019-10-11 03:25:54 +0900 - - Document the difference between expressions and statements [ci skip] - - In the grammar, all expressions are statements, but not all - statements are expressions. Some parts of the grammar accept - expressions and not other types of statements, which causes - similar looking code to parse differently due to operator - precedence. - - Mostly from Dan0042 (Daniel DeLorme). - - Fixes [Bug #16092] - -commit ddb0267e76d4127e66fec9b5865d053c6ed9721a - Author: git - Date: 2019-10-11 05:15:28 +0900 - - * 2019-10-11 [ci skip] - -commit 2322c94dd65c0247b103e2f91411e37458e1466d - Author: Jeremy Evans - Date: 2019-08-25 16:04:14 +0900 - - Support delegates for BasicObject - - For BasicObject, bind the Kernel respond_to? instance method to the - object and call it instead of calling the method directly. - - Also, use bind_call(recv, ...) for better performance. - - Fixes [Bug #16127] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2546 - -commit 41719096957aa3d80e2e23d04ae288d2dee5328e - Author: Yusuke Endoh - Date: 2019-10-10 23:22:37 +0900 - - mjit_worker.c: Add `-lm` to the C compiler in MJIT on Android - - To avoid: - - cannot locate symbol "modf" referenced by .../_ruby_mjit_XXX.so" - -commit f845e1bc9951ef40f2b3672d825aa67f6d6f8368 - Author: Yusuke Endoh - Date: 2019-10-10 23:21:24 +0900 - - ext/syslog/extconf.rb: add -llog for Android - - Otherwise, requiring syslog results in: - - cannot locate symbol "__android_log_print" referenced by "syslog.so" - -commit a886d5cb79e2440eb6cf422723e08447ee4735db - Author: Yusuke Endoh - Date: 2019-10-10 23:18:44 +0900 - - test/ruby/test_file_exhaustive.rb: check the owner of the root directory - - The root directory may be owned by the current user, for example, in - chroot environment. - -commit c144d7215b3444fa36d28d540b60170a5b30743d - Author: Nobuyoshi Nakada - Date: 2019-10-10 21:02:45 +0900 - - Skip very time consuming test [Bug #16196] - -commit 9c0cd5c569ba22bc68d1a77ad6580a275cd99639 - Author: Nobuyoshi Nakada - Date: 2019-10-10 19:38:37 +0900 - - Prefer rb_gc_register_mark_object - - * ext/openssl/ossl_asn1.c (Init_ossl_asn1): prefer - `rb_gc_register_mark_object`, which is better for constant - objects, over `rb_gc_register_address` for global/static - variables which can be re-assigned at runtime. [Bug #16196] - -commit 0131fab749fb76800de09e49a6abf910201c5b58 - Author: Nobuyoshi Nakada - Date: 2019-10-10 19:56:51 +0900 - - Slimed down test runtime by stressing openssl.so only [Bug #16196] - -commit 3f413896c3e71e4d2ed61bcd969f2ed3fc35ea4a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 18:15:33 +0900 - - forgot to delete unused #include line - -commit 2d393bf1255864706cabdd9375dd26e33bdf40b9 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 17:49:31 +0900 - - guard rb_fatal against non-GVL call - - Suggested by ko1. rb_fatal requires GVL so just in case one lacks, - print that information and let the process die. As commented, - we cannot print the given messages on such situations. - -commit f1ce4897f2eaf9a99c250e4707e3ab6f6bdacb74 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 17:04:59 +0900 - - make rb_raise a GVL-only function again - - Requested by ko1 that ability of calling rb_raise from anywhere - outside of GVL is "too much". Give up that part, move the GVL - acquisition routine into gc.c, and make our new gc_raise(). - -commit d96f04d73a5feb15b9d27bd23af2f7325732bb03 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 16:10:58 +0900 - - add "[FATAL]" marker on abort - - Indicate that the situation is fatal. - -commit 0b26f56a77a6dabe2b1c09c4569ed846798afcdc - Author: Kazuhiro NISHIYAMA - Date: 2019-10-10 16:48:26 +0900 - - Remove unreachable step level `[ci skip]` - -commit 203b7fa1ae8cc40d41c38d684f70b3fea7fae813 - Author: Nobuyoshi Nakada - Date: 2019-10-10 16:08:39 +0900 - - Guard static variable first - - * ext/openssl/ossl_asn1.c (Init_ossl_asn1): register the static - variable to grab an internal object, before creating the object. - otherwise the just-created object could get collected during the - global variable list allocation. [Bug #16196] - -commit 6f522455bf801acefcd2ade0b2e4a2fef3cb70a4 - Author: Nobuyoshi Nakada - Date: 2019-10-07 00:12:18 +0900 - - [rubygems/rubygems] Do not compare with unreliable Gem::Specification::TODAY - - https://gist.github.com/ko1/a88834d744a0682711dab53fd9015a04#file-brlog-trunk-nopara-20191005-235153-L393-L472 - - https://github.com/rubygems/rubygems/commit/707408d8e7 - -commit dc2b301994ed9de75477ece30111553d4f1ee2e3 - Author: Nobuyoshi Nakada - Date: 2019-10-07 00:08:32 +0900 - - [rubygems/rubygems] Restrict possible date range - - https://github.com/rubygems/rubygems/commit/1bd77f53df - -commit 717b72a8af6b99ca79fd5bbe52ba4bd16b038bf6 - Author: Jean Boussier - Date: 2019-10-01 20:16:32 +0900 - - [rubygems/rubygems] Optimize Gem::Package::TarReader#each - - https://github.com/rubygems/rubygems/commit/1de8f39ac4 - -commit 495ebd6e9555bdd220a74c96cda7a7d6fe40209b - Author: Nobuyoshi Nakada - Date: 2019-10-10 14:21:29 +0900 - - Now error.o needs thread.h - -commit c2065c64cb198d5b53a5ecdf9638d064f6fec2e2 - Author: Nobuyoshi Nakada - Date: 2019-10-10 13:50:13 +0900 - - Fixed numbered parameter check - - * parse.y (struct local_vars): moved numbered parameter NODEs for - nesting check to separate per local variable scopes, as numbered - parameters should belong to local variable scopes. [Bug #16248] - -commit a23b639050792c74cbf585aff6742c6ee3931f5f - Author: Nobuyoshi Nakada - Date: 2019-10-10 14:07:27 +0900 - - negative_size_allocation_error never returns - -commit 9c3153e0da991e1a7df9b4cf91d6830effc79b22 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 11:55:43 +0900 - - allow rb_raise from outside of GVL - - Now that allocation routines like ALLOC_N() can raise exceptions - on integer overflows. This is a problem when the calling thread - has no GVL. Memory allocations has been allowed without it, but - can still fail. - - Let's just relax rb_raise's restriction so that we can call it - with or without GVL. With GVL the behaviour is unchanged. With - no GVL, wait for it. - - Also, integer overflows can theoretically occur during GC when - we expand the object space. We cannot do so much then. Call - rb_memerror and let that routine abort the process. - -commit 25100c469758dd3676ec608ed27fd89248980666 - Author: Nobuyoshi Nakada - Date: 2019-10-10 08:53:46 +0900 - - lhs of pattern matching expression of should have a value - -commit 42edb056268303e8d2a1772cda0e46e1ba1a14bb - Author: Nobuyoshi Nakada - Date: 2019-10-10 01:08:42 +0900 - - extracted declare_under - -commit 8dc5fe6e89cb86bd92628b5f34ba5f549a241c2d - Author: Alan Wu - Date: 2019-10-10 00:34:03 +0900 - - Simplify rb_define_module_id - - Notes: - Merged: https://github.com/ruby/ruby/pull/2544 - -commit ecf6c0402eb8706001831e0464b47cbed8e82fa0 - Author: git - Date: 2019-10-10 00:14:36 +0900 - - * 2019-10-10 [ci skip] - -commit 9b919885a08d6cf3c68cb1bce992feb43a8fad0c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-10 00:10:14 +0900 - - fix memory corruption in old GCC - - This typo introduced memory corruption when __builtin_add_overflow - is not available but uint128_t is. GCC before 5 are one of such - situatins. - - See also https://rubyci.org/logs/rubyci.s3.amazonaws.com/opensuseleap/ruby-master/log/20191009T120004Z.log.html.gz - -commit bb71a128eb6e901d3d7deb895971a6706eb7110d - Author: Ben Woosley - Date: 2017-05-19 07:59:38 +0900 - - Prefer st_is_member over st_lookup with 0 - - The st_is_member DEFINE has simpler semantics, for more readable code. - - Notes: - Merged: https://github.com/ruby/ruby/pull/1622 - -commit 29e6782f5dbf127dc20156938af374eea9e2d74e - Author: Nobuyoshi Nakada - Date: 2019-10-09 23:39:58 +0900 - - Share ruby_sighandler_t definition - -commit 891cbd66a411725d7300a28b1a95619c2902f0eb - Author: Yusuke Endoh - Date: 2019-10-09 23:13:59 +0900 - - signal.c: save the original sighandlers for fatal signals - - On Android, a signal handler that is not SIG_DFL is set by default for - SIGSEGV. Ruby's install_sighandler inserts Ruby's handler only when the - signal has no handler, so it does not insert Ruby's SEGV report handler, - which caused some test failures. - - This changeset forces to install Ruby's handler for some fatal signals - (sigbus, sigsegv, and sigill). They keep the original handlers, and - call them when the interpreter receives the signals. - -commit dd477df411691803fc5a83c7daa64faac112a0e4 - Author: Yusuke Endoh - Date: 2019-10-09 23:02:22 +0900 - - error.c (rb_bug_for_fatal_signal): renamed from rb_bug_context - - Just refactoring. - - The name "rb_bug_context" is completely unclear for me. - (Can you see that "context" means "machine register context"?) - The context is available only when a fatal signal (sigbus, sigsegv, or - sigill) is received; in fact, the function is used only for fatal - signals. So, I think the name should be changed. - -commit b9cf58d2b2deca7d5b204080c2fe04d68cc50ab1 - Author: Yusuke Endoh - Date: 2019-10-09 22:57:19 +0900 - - signal.c (ruby_abort): move the definition for refactoring - - The three functions for fatal signals, sigbus, sigsegv, and sigill, are - a family. The definition of ruby_abort had interrupted them for no - reason. This change just moves the definition after the family. - -commit 6f11c3b3354bef107f894f112ff7698414c7bae5 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-09 17:46:05 +0900 - - Check '[ci skip]' at job level - -commit d0e30fc955a3a91952c6d63c56d900b72d657a3a - Author: Yusuke Endoh - Date: 2019-10-09 14:03:04 +0900 - - vm_eval.c (rb_adjust_argv_kw_splat): avoid memcpy with zero length - - A method call is often with `argc = 1` and `argv = &v` where v is a - VALUE, and some functions shift the arguments by `argc-1` and `argv+1` - (for example, rb_sym_proc_call). I'm unsure whether it is safe or not - to pass a pointer `argv+1` to memcpy with zero length, but Coverity Scan - complains it. So this attempts to suppress the warning by explicit - check of the length. - -commit b439ee1b8fa8d8a99f3f519af946ead94917edb2 - Author: Pavel Valena - Date: 2019-09-25 22:35:56 +0900 - - Remove uselsess shebang - - as the file is not executable anyway. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2483 - -commit 12d05537d73325d60902feaf0da323ef20ace74b - Author: aycabta - Date: 2019-09-18 18:51:02 +0900 - - Update required_ruby_version to 2.4.0 - -commit 2d001003e4b3a6c20ead09ed54b6726a7669f457 - Author: Watson - Date: 2019-10-09 12:25:08 +0900 - - Improve performance of Array#sum with float elements (#1555) - - The declaration of local variable in loop, it will initialize local variable for each run of the loop with clang generated code. - So, it shouldn't declare the local variable in heavy loop. - - Array#sum with float elements will be faster around 30%. - - * Before - user system total real - 3.320000 0.010000 3.330000 ( 3.336088) - - * After - user system total real - 2.590000 0.010000 2.600000 ( 2.602399) - - * Test code - require 'benchmark' - - Benchmark.bmbm do |x| - ary = [] - 10000.times { ary << Random.rand } - - x.report do - 50000.times do - ary.sum - end - end - - end - -commit a14cc07f2ffc704b73ba4b96543e2f85c3ed1921 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-08 16:07:31 +0900 - - avoid returning NULL from xrealloc - - This changeset is to kill future possibility of bugs similar to - CVE-2019-11932. The vulnerability occurs when reallocarray(3) - (which is a variant of realloc(3) and roughly resembles our - ruby_xmalloc2()) returns NULL. In our C API, ruby_xmalloc() - never returns NULL to raise NoMemoryError instead. ruby_xfree() - does not return NULL by definition. ruby_xrealloc() on the other - hand, _did_ return NULL, _and_ also raised sometimes. It is very - confusing. Let's not do that. x-series APIs shall raise on - error and shall not return NULL. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2540 - -commit 7e0ae1698d4db0baec858a46de8d1ae875360cf5 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-07 16:56:08 +0900 - - avoid overflow in integer multiplication - - This changeset basically replaces `ruby_xmalloc(x * y)` into - `ruby_xmalloc2(x, y)`. Some convenient functions are also - provided for instance `rb_xmalloc_mul_add(x, y, z)` which allocates - x * y + z byes. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2540 - -commit a220410be70264a0e4089c4d63a9c22dd688ca7c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-07 13:16:42 +0900 - - annotate malloc-ish functions - - Make them gcc friendly. Note that realloc cannot be __malloc__ - attributed, according to the GCC manual. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2540 - -commit 2f3b4029da1b64ffb989916a8b74e17c366e45b0 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-07 13:46:24 +0900 - - fix arity mismatch - - Seems nobody has actually used this macro. Such an obvious typo. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2540 - -commit 59cfa2d1871c0b74d39d9eee6241f3e950eff42e - Author: git - Date: 2019-10-09 09:08:53 +0900 - - * 2019-10-09 [ci skip] - -commit e078352a787ce3d52b5147a5fdf69b89a9d60cff - Author: Nobuyoshi Nakada - Date: 2019-10-09 09:04:37 +0900 - - lldb_cruby.py: fixed inspecting string [ci skip] - - Show the size of String. - - To see the whole contents even after NUL char: - - ``` - (lldb) rp str - (const char [5]) $1 = "x" - (lldb) memory read -s1 --format x --count `sizeof($1)` -- &$1 0x1010457a8: 0x78 0x00 0x61 0x61 0x61 - ``` - -commit 98131f148f057b1364ae080f99b1efb2dc72002a - Author: Nobuyoshi Nakada - Date: 2019-10-09 09:01:11 +0900 - - lldb_cruby.py: fixed embedded string ptr [ci skip] - - Use GetLocation to get the address of embedded array. - -commit 7909f06212ae8df6ba7203f8152292a190b2b33a - Author: Jeremy Evans - Date: 2019-07-06 06:45:19 +0900 - - Check for invalid hex escapes in URI#query= - - Fixes [Bug #11275] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2535 - -commit 8feb8c9bb7e9036ee2014b0f532677635a16893e - Author: Nobuyoshi Nakada - Date: 2019-10-08 09:13:58 +0900 - - Packed delayed token elements - -commit 11b6ff12af99b177979c7a4f57f49b91a50fcc0c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-08 11:21:20 +0900 - - more use of RbConfig::LIMITS - - `8 * RbConfig::SIZEOF` ... is not straight. - -commit dd0c75fdc2104a6ba38b68d4431a572504a3bbc2 - Author: Kenta Murata - Date: 2019-10-08 09:06:28 +0900 - - Import changes from ruby/bigdecimal (#2531) - - Sync to ruby/bigdecimal@92356ba71c6bd325b0ab618c634a7aecf8cdc767 - - Notes: - Merged-By: mrkn - -commit 59c3b1c9c843fcd2d30393791fe224e5789d1677 - Author: Jeremy Evans - Date: 2019-10-08 05:45:40 +0900 - - Add section to extension.rdoc for backwards compatibility macros [ci skip] - - These macros should make it easier to C extensions to switch to - the Ruby 2.7 C-API *_kw functions, but still have the code work - correctly on older Ruby versions. - -commit c0eae130b1d9fde5716c2340141d78ebc48c82a5 - Author: Jeremy Evans - Date: 2019-10-08 05:16:33 +0900 - - Note RB_PASS_EMPTY_KEYWORDS and RB_SCAN_ARGS_EMPTY_KEYWORDS will be removed - - There is no need for these in Ruby 3.0, and the plan is to - remove them. - -commit 055a85d3d9ab5850b1269089f28385158d969d18 - Author: Jeremy Evans - Date: 2019-10-08 04:55:22 +0900 - - Update NEWS with Module#ruby2_keywords and a few other things - -commit 6abcd35762db4bf49cd6c62a8c624e2a013e5dc1 - Author: Aaron Patterson - Date: 2019-10-08 04:28:21 +0900 - - Do not free too many pages. - - Sweep step checks `heap_pages_freeable_pages`, so compaction should do - the same. - -commit 058db33c5ec881271d028b7490d88b3baed74acb - Author: Aaron Patterson - Date: 2019-10-08 04:10:24 +0900 - - Move empty pages to the tomb - - I think we need to be moving empty pages to the tomb after they become - empty. - -commit 0a2f04e156cb717dcf78f2ea9bfe26f864a24616 - Author: Aaron Patterson - Date: 2019-10-08 02:14:13 +0900 - - Eliminate second GC pass for eliminating T_MOVED - - `T_MOVED` is a linked list, so we can just iterate through the `T_MOVED` - objects, clearing them out and adding them to respective free lists. - -commit d8b6f585027a5657c6921f97513a8cf70a031c94 - Author: git - Date: 2019-10-08 00:00:54 +0900 - - * 2019-10-08 [ci skip] - -commit 7abb02771a188671a6ddc3ccbe87dcecc4fe645f - Author: Kazuhiro NISHIYAMA - Date: 2019-10-08 00:00:24 +0900 - - Fix typo [ci skip] - - pointed out by ruby-trunk-changes - -commit 468184a996c99d1f94f94d7468f65e386cf13564 - Author: Jeremy Evans - Date: 2019-10-07 13:18:20 +0900 - - Allow ruby2_keywords to be used with bmethods - - There are libraries that use define_method with argument splats - where they would like to pass keywords through the method. To - more easily allow such libraries to use ruby2_keywords to handle - backwards compatibility, it is necessary for ruby2_keywords to - support bmethods. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2532 - -commit 3374e1450c18c33420f616f41ad7f884fdb4df21 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-07 19:33:33 +0900 - - Write yaml and json under destdir and print to stdout - -commit 96753e8475ee69537134ab3d966c3d25cb5c467c - Author: Kazuhiro NISHIYAMA - Date: 2019-10-07 19:05:42 +0900 - - Create info.yml and info.json - - - `info.yml` is for ruby/www.ruby-lang.org/_data/releases.yml - - `info.json` is meta data for users of snapshot - -commit bb86611c9b61b47ba7ff65c3b0a0737a20183460 - Author: Kazuhiro NISHIYAMA - Date: 2019-10-07 19:03:06 +0900 - - Remove `-s3` option - - It will not use in `ruby/actions`, and `default=tmp` is not correct. - -commit f4252f64964f3b66171cc0c81bda4c1b2d028601 - Author: aycabta - Date: 2019-10-07 14:21:38 +0900 - - Version 0.0.3 - -commit c8542ab484efb6ee0009cd081789d9a68f482483 - Author: Prajjwal Singh - Date: 2019-10-07 14:12:29 +0900 - - Add: Array#intersection method - - Notes: - Merged: https://github.com/ruby/ruby/pull/2533 - -commit d4ec37f69e3bd6f88725fe1075daa2e5f58c2aec - Author: git - Date: 2019-10-07 14:16:12 +0900 - - * 2019-10-07 [ci skip] - -commit a9e9cd20369ea110333deb2ef7c23b5ed7d09773 - Author: aycabta - Date: 2019-10-06 00:52:20 +0900 - - Flush console just after printing - -commit 136116819eea66c5a053971efb9aba403a44e38a - Author: aycabta - Date: 2019-10-05 23:46:16 +0900 - - Use built-in Win32API on JRuby - - It's fixed for JRuby dedicatedly. - -commit 309f6a772692e696b79f6bd213680e534551cca3 - Author: aycabta - Date: 2019-10-02 19:56:55 +0900 - - Swap expected and actual correctly - -commit ddf5020e4fcae5ed28a064af10124a032590452f - Author: Koichi Sasada - Date: 2019-10-06 17:01:00 +0900 - - Revert "tailcall optimization again (#2528)" - - This reverts commit f62f90367fc3bce6714e7c34cbd040e14e43fe07. - -commit f62f90367fc3bce6714e7c34cbd040e14e43fe07 - Author: wanabe - Date: 2019-10-06 16:52:09 +0900 - - tailcall optimization again (#2528) - - This is follow up of r67315. - -commit 6525d3bcc7d0be65e2ff97d6785d9f36b5e4988a - Author: Yusuke Endoh - Date: 2019-10-06 15:22:12 +0900 - - test/dtrace/helper.rb: Etc.getgrnam may return nil on some platforms - -commit 2ca353c2e0785056fea551d78e957bd753b17586 - Author: git - Date: 2019-10-06 11:49:27 +0900 - - * 2019-10-06 [ci skip] - -commit 2409667aa2e03b6008ed7a4ccce48a8b288cc0fd - Author: Yusuke Endoh - Date: 2019-10-06 11:39:01 +0900 - - time.c: Fix some bugs about WIDEVALUE - - WIDEVALUE differs from VALUE in 32bit platform, but some codes assume - that they are the same. - - There is `#define STRUCT_WIDEVAL` mode to check the consistency. - This change allows to build with STRUCT_WIDEVAL. - -commit 06a04a1aa3fbf9132c61f4ced9582c36c96d3f65 - Author: Yusuke Endoh - Date: 2019-10-05 19:08:23 +0900 - - ext/openssl/ossl_ssl.c: Use const declaration if LibreSSL >= 2.8.0 - - to suppress a warning in OpenBSD. - - ``` - ossl_ssl.c:938:31: warning: incompatible pointer types passing 'SSL_SESSION *(SSL *, unsigned char *, int, int *)' (aka 'struct ssl_session_st *(struct ssl_st *, unsigned char *, int, int *)') to parameter of type 'SSL_SESSION *(*)(struct ssl_st *, const unsigned char *, int, int *)' (aka 'struct ssl_session_st *(*)(struct ssl_st *, const unsigned char *, int, int *)') [-Wincompatible-pointer-types] - SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - /usr/include/openssl/ssl.h:738:20: note: passing argument to parameter 'get_session_cb' here - SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, - ^ - 1 warning generated. - ``` - -commit 96452373fd192ada49c831386e033531e2263a52 - Author: Yusuke Endoh - Date: 2019-10-05 18:28:19 +0900 - - ext/json/parser/prereq.mk: use `if $. == 1` instead of a hacky code - -commit 70e3fda2eb45c841e5fb4574273d20f8df5455e5 - Author: Yusuke Endoh - Date: 2019-10-05 17:54:36 +0900 - - ext/json/parser/prereq.mk: keep line numbers of ext/json/parser/parser.c - - Follow up of 5717e55e9a7790c938afa694a9bf558c0e54bb83. - Adding a header with newline broke linenos. - -commit 3e3cc0885a9100e9d1bfdb77e136416ec803f4ca - Author: Nobuyoshi Nakada - Date: 2019-10-05 11:28:53 +0900 - - Now keyword parameter warnings are suppressed by 871005bdd204 - - This reverts commits: - - * 2a490d5660ac869f8f2bbcec4887b1dc2950643f - Suppress assert_match warnings. - - * d4a86e407ec2057c2c7ad757aa76dad757f34c3a - Assert warnings message for the last argument is keyword parameter. - -commit 212da9a6aec5da26f97b8312b7e8fd3d9b1eef47 - Author: Nobuyoshi Nakada - Date: 2019-10-05 11:04:23 +0900 - - Added dependencies on prerequisite makefiles - -commit 6dfe0c9dcd8327dfce5f689d6a184c0f3a146a24 - Author: Nobuyoshi Nakada - Date: 2019-10-01 10:41:10 +0900 - - [rubygems/rubygems] The date might have advanced since TODAY has been set - - https://bugs.ruby-lang.org/issues/16189 - - https://github.com/rubygems/rubygems/commit/e331222163 - -commit 7d4ab8bbe70c92410d35270be9030775b9ee31ac - Author: bronzdoc - Date: 2019-09-29 23:43:17 +0900 - - [rubygems/rubygems] Use dependency.identity in available_specs - - https://github.com/rubygems/rubygems/commit/bde88f00a1 - -commit b659c1b92f3d5f251a3436073cd60d955d5fc457 - Author: bronzdoc - Date: 2019-09-29 23:41:49 +0900 - - [rubygems/rubygems] Add Gem::Dependency#identity method - - https://github.com/rubygems/rubygems/commit/05146bb2fd - -commit 871005bdd2044ef7bd532a7cc4f0756217161f97 - Author: Nobuyoshi Nakada - Date: 2019-09-26 20:11:24 +0900 - - [rubygems/rubygems] Suppress keywords warning in ruby 2.7 - - https://github.com/rubygems/rubygems/commit/892bfc11fe - -commit caa9d0bd7851c3b8cc9064987109eed9952a7c90 - Author: Nobuyoshi Nakada - Date: 2019-09-26 20:01:03 +0900 - - [rubygems/rubygems] Always pass an encoding option to Zlib::GzipReader.wrap - - The arity of this method has been -1 since the import, so the - option has been passed always, even if Zlib::GzipReader#initialize - does not take the option. Actually it takes the option since 1.9. - - https://github.com/rubygems/rubygems/commit/2fcde0f4e0 - -commit 39e8d5e1cdc25ca17f74da5e72ba87dcdfa4a602 - Author: Nobuyoshi Nakada - Date: 2019-09-26 19:47:22 +0900 - - [rubygems/rubygems] Use dedicated assertion methods - - For better messages at failures. - - https://github.com/rubygems/rubygems/commit/971455b16e - -commit f8104d9e9f1a9b378dde08e806f4aadf9b17200b - Author: Nobuyoshi Nakada - Date: 2019-09-26 19:38:56 +0900 - - [rubygems/rubygems] Fixed assertion arguments - - It is `assert_eqal(expected, actual)`. - - https://github.com/rubygems/rubygems/commit/1d6197a090 - -commit 170d1540596c72c9197732d051d8d9302b87f033 - Author: Yusuke Endoh - Date: 2019-10-05 07:37:19 +0900 - - signal.c: Use MINSIGSTKSZ by casting to int - - MINSIGSTKSZ is unsigned int in OpenBSD, which makes a warning of - comparison: - - ``` - signal.c:535:14: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare] - if (size < MINSIGSTKSZ) - ~~~~ ^ ~~~~~~~~~~~ - 1 warning generated. - ``` - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20191004T200009Z.log.html.gz - -commit 417c64b9a8c4815a54f9bbef37f4438ee5c2f4fc - Author: Yusuke Endoh - Date: 2019-10-05 07:00:57 +0900 - - ext/json/parser/parser.rl: Use "signed" char to contain negative values - - char is not always signed. In fact, it is unsigned in arm. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20191004T181708Z.log.html.gz - ``` - compiling parser.c - parser.rl: In function ‘unescape_unicode’: - parser.rl:50:5: warning: comparison is always false due to limited range of data type [-Wtype-limits] - if (b < 0) return UNI_REPLACEMENT_CHAR; - ^ - ``` - -commit 5717e55e9a7790c938afa694a9bf558c0e54bb83 - Author: Yusuke Endoh - Date: 2019-10-05 07:00:07 +0900 - - ext/json/parser/prereq.mk: Add a "automatically generated" header - - to parser.c. - -commit 076d3d758b0df47d3dceb3ba0930486f3dd0cc2d - Author: Yusuke Endoh - Date: 2019-10-05 06:30:27 +0900 - - ext/json/parser/parser.rl: Update the source code of parser.c - - There have been some direct changes in parser.c which is automatically - generated from parser.rl. This updates parser.rl to sync the changes: - - * 91793b8967e0531bd1159a8ff0cc7e50739c7620 - * 79ead821dd4880725c9c6bb9645b3fad71715c5b - * 80b5a0ff2a7709367178f29d4ebe1c54122b1c27 - -commit bd4b65f4b05ff7dcb5c7e16f174c57885bf27e40 - Author: Aaron Patterson - Date: 2019-10-05 03:17:43 +0900 - - IMEMO objects don't have a class, so return early - - IMEMO objects don't have a class field to update, so we need to return - early, otherwise it can cause a segv. - -commit a20ed0565efd2f47845c890d1ebea341d43ee5e6 - Author: Aaron Patterson - Date: 2019-10-04 09:52:00 +0900 - - Don't allocate objects in `gc_compact` - - I'd like to call `gc_compact` after major GC, but before the GC - finishes. This means we can't allocate any objects inside `gc_compact`. - So in this commit I'm just pulling the compaction statistics allocation - outside the `gc_compact` function so we can safely call it. - -commit cbf88064f5bd433c13345bbc2ce509b4e8509c7a - Author: git - Date: 2019-10-05 03:07:31 +0900 - - * 2019-10-05 [ci skip] - -commit cbbe198c89fa25a80ec0a5f0592ea00132eacd01 - Author: Nobuyoshi Nakada - Date: 2019-10-05 02:08:07 +0900 - - Fix potential memory leaks by `rb_imemo_tmpbuf_auto_free_pointer` - - This function has been used wrongly always at first, "allocate a - buffer then wrap it with tmpbuf". This order can cause a memory - leak, as tmpbuf creation also can raise a NoMemoryError exception. - The right order is "create a tmpbuf then allocate&wrap a buffer". - So the argument of this function is rather harmful than just - useless. - - TODO: - * Rename this function to more proper name, as it is not used - "temporary" (function local) purpose. - * Allocate and wrap at once safely, like `ALLOCV`. - -commit c8a18e25c1cc9a44231b97e12f30a98cf9d979bb - Author: Yusuke Endoh - Date: 2019-10-04 21:30:32 +0900 - - iseq.c (rb_iseq_compile_on_base): Removed - - ko1 cannot remember why he introduced the function. And it is not used. - - After it is removed, the argument "base_block" of - rb_iseq_compile_with_option is always zero. - -commit 113bef697633803a33a547914b16ba5fbef165b8 - Author: Yusuke Endoh - Date: 2019-10-04 16:07:46 +0900 - - array.c (rb_mem_clear): remove "register" from arguments - - to suppress the following warning: - - ``` - compiling cxxanyargs.cpp - In file included from cxxanyargs.cpp:1: - In file included from ../../.././include/ruby/ruby.h:2150: - ../../.././include/ruby/intern.h:56:19: warning: 'register' storage class specifier is deprecated and incompatible with C++17 [-Wdeprecated-register] - void rb_mem_clear(register VALUE*, register long); - ^~~~~~~~~ - ../../.././include/ruby/intern.h:56:36: warning: 'register' storage class specifier is deprecated and incompatible with C++17 [-Wdeprecated-register] - void rb_mem_clear(register VALUE*, register long); - ^~~~~~~~~ - ``` - -commit 5be2af5f9052e7f799b2c576d78a373c57069771 - Author: Alan Wu - Date: 2019-10-04 10:15:24 +0900 - - Remove call-seq for method that doesn't exist (#2521) - - ``` - $ ruby -ve 'IO.popen("ls"){}; $?.to_int' - ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-darwin18] - Traceback (most recent call last): - -e:1:in `
': undefined method `to_int' for # (NoMethodError) - Did you mean? to_i - taint - ``` - - Process::Status#to_int was removed at 7ba5c4e. - -commit 7db83b04d0e170a6b9ed56597a1327c68c04bfec - Author: Takashi Kokubun - Date: 2019-10-04 07:58:20 +0900 - - Revert "Simplify bin_path_spec.rb guard" - - This reverts commit a56d742e69aa8a3a1fe92fc515d93f6e51cf5fbc. - - I was checking the CI result of the wrong revision. It actually worked - fine https://ci.appveyor.com/project/ruby/ruby/builds/27866303. Never - mind... - -commit a56d742e69aa8a3a1fe92fc515d93f6e51cf5fbc - Author: Takashi Kokubun - Date: 2019-10-04 07:33:10 +0900 - - Simplify bin_path_spec.rb guard - - For some reason the guard_not seems not working as expected - https://ci.appveyor.com/project/ruby/ruby/builds/27866153/job/v6wa6q6p7b7n7r37 - -commit ac69a051cf00e3fda3cb7e8d7377558d84ef880f - Author: Takashi Kokubun - Date: 2019-10-04 07:15:05 +0900 - - Ignore arm32 failure for now - -commit 182336ccb5a8d46fbcddbdad9e7bbca6d5d5d63f - Author: Takashi Kokubun - Date: 2019-10-04 06:24:57 +0900 - - bin_path_spec.rb has failed from the beginning - - for mswin. This spec is not valid for mswin platform. - https://ci.appveyor.com/project/ruby/ruby/builds/27748774/job/85khngfpc806m5lj - -commit 804672e7b452c4d0dcb653e14cb9900513bfa8de - Author: Takashi Kokubun - Date: 2019-10-04 06:17:36 +0900 - - Try disabling build on trunk - -commit 9f24e8fdbb6a579fe00f4449c79417a418d67a87 - Author: Jeremy Evans - Date: 2019-10-04 06:07:32 +0900 - - Document *_kw functions added to include/ruby/ruby.h [ci skip] - - Also documents the non-*_kw functions if they were not already - documented. - -commit c7715a4936a298ff9bcce97e65dfd3dc6f32f906 - Author: Jeremy Evans - Date: 2019-10-04 05:14:45 +0900 - - Add documentation regarding keyword argument separation [ci skip] - -commit 12e27a411c394366b3c701153040d63390d314cc - Author: Jeremy Evans - Date: 2019-10-04 05:14:08 +0900 - - Minor updates to methods and calling_methods documentation [ci skip] - -commit bdbf8de4980ef54f466809ee27a9f2a00614b0f0 - Author: Jun Aruga - Date: 2019-10-04 06:12:58 +0900 - - Enable Drone CI for ARM 64/32-bit cases. (#2520) - - https://bugs.ruby-lang.org/issues/16234 - -commit c3dd3b95538a641bbffb02993985ce0cbac1b9d6 - Author: Yusuke Endoh - Date: 2019-10-04 02:35:10 +0900 - - iseq.c (rb_iseq_compile_with_option): dummy parent_iseq for the parser - - The parsing of `RubyVM::InstructionSequence.compile` does not support an - outer scope currently. So it specified NULL as parent_iseq for the - parser. However, it resulted in the following false-positive warning. - - ``` - RubyVM::InstructionSequence.compile(< :2: warning: possibly useless use of a variable in void context - END - ``` - - This change specifies a dummy empty parent_iseq instead of NULL, which - suppresses the false positive. - -commit b732a9f8a0f694d8668bb1d42e94435c47e05df3 - Author: Yusuke Endoh - Date: 2019-10-04 02:33:39 +0900 - - parse.y: use "struct rb_iseq_struct" instead of rb_iseq_t - - typedef was not declared in parse.y. Sorry. - -commit bb9604e18c73558709b49962bdcec59613dbf014 - Author: git - Date: 2019-10-04 02:30:54 +0900 - - * 2019-10-04 [ci skip] - -commit b43afa0a8f82a5d806adc24afa2eaf41479da1a3 - Author: Yusuke Endoh - Date: 2019-10-04 01:48:31 +0900 - - Make parser_params have parent_iseq instead of base_block - - The parser needs to determine whether a local variable is defined or - not in outer scope. For the sake, "base_block" field has kept the outer - block. - - However, the whole block was actually unneeded; the parser used only - base_block->iseq. - - So, this change lets parser_params have the iseq directly, instead of - the whole block. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2519 - -commit 711c40ebdcd0974ef3e6ac6870412dc88ae25f3e - Author: Yusuke Endoh - Date: 2019-10-04 01:29:21 +0900 - - Refactor parser_params by removing "in_main" flag - - The relation between parser_param#base_block and #in_main were very - subtle. - A main script (that is passed via a command line) was parsed under - base_block = TOPLEVEL_BINDING and in_main = 1. - A script loaded by Kernel#require was parsed under - base_block = NULL and in_main = 0. - If base_block is non-NULL and in_main == 0, it is parsed by Kernel#eval - or family. - - However, we know that TOPLEVEL_BINDING has no local variables when a - main script is parsed. So, we don't have to parse a main script under - base_block = TOPLEVEL_BINDING. - - Instead, this change parses a main script under base_block = 0. - If base_block is non-NULL, it is parsed by Kernel#eval or family. - By this simplication, "in_main" is no longer needed. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2519 - -commit 8f7fca784a46c4d4213ed7b166945f5b9143062d - Author: Nobuyoshi Nakada - Date: 2019-10-03 19:13:05 +0900 - - make-snapshot: touch updated files after prepared - - Align mtime of files updated by `make prepare-package` to make - packages reproducible. - -commit 8142a9b43dfc3e141fd7cb3fc255fc102523f6df - Author: Nobuyoshi Nakada - Date: 2019-10-03 19:12:03 +0900 - - make-snapshot: suppress make error messages unless failed - -commit 47d143be17819bed6dda08e24069d755ef34530b - Author: Nobuyoshi Nakada - Date: 2019-10-03 16:47:57 +0900 - - make-snapshot: copy cache files instead of linking - - To get rid of setting mode and mtime of the original cache files. - -commit b7ae26e2eec9efb826e4a2d913a67341531c6342 - Author: Nobuyoshi Nakada - Date: 2019-10-03 16:47:05 +0900 - - vcs.rb: fix to export git-svn version - - * Use the given branch name instead of implicit 'HEAD". - * Format like as git-svn when `from` or `to` is SVN revision - number. - -commit ad67adb5f942d463ab378fea21cc21cb15466cbc - Author: Hiroshi SHIBATA - Date: 2019-10-03 14:47:18 +0900 - - [ruby/fileutils] Use pend instead of skip - - https://github.com/ruby/fileutils/commit/ba2c24e2d7 - -commit c14755e9ca8f2cf8fea5b0232d846bd57193ea53 - Author: Hiroshi SHIBATA - Date: 2019-10-03 18:32:21 +0900 - - [ruby/fileutils] improve the compatibility of minitest - - https://github.com/ruby/fileutils/commit/f16f5a0dd6 - -commit 3ffd98c5cd040a4081617b3bc6f9062237937b9b - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-01 16:45:14 +0900 - - add debug counters for vm_search_method_slowpath() - - Implemented fine-grained inspection of cache misshits. Handy for - counting the reasons why an inline method cache was evicted. - -commit 84fc1de5125a6f7c61609bf153f0359b3da55d8d - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-03 14:56:35 +0900 - - use bind_call for test-all --gc-stress - - This one allocation of Method object is worth avoiding. We don't - want to test UnboundMethod#bind right here. GC need not run. - -commit 1c999952e74e9b5f1e882501580d5f2f5a92f142 - Author: Romain Tartière - Date: 2019-10-03 05:26:39 +0900 - - Resolve unused local variable reported by LGTM - - LGTM reports that the value assigned to local variable 'shared' is never - used: - https://lgtm.com/projects/g/ruby/ruby/snapshot/f319a5d064627c6641817ec2ed16b97b4d215148/files/misc/lldb_cruby.py#x6512c0281581a470:1 - - This problem was introduced in by the refactoring that took place in - 7c496b6624f720d539e3c0b40f122a9422a13b99. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2517 - -commit a515e3f99ea50358afbfc94a53d54a390096626d - Author: git - Date: 2019-10-03 12:48:30 +0900 - - * 2019-10-03 [ci skip] - -commit 7e060d50183712b7ab11f5887af6a3ce69df4a57 - Author: git - Date: 2019-10-03 12:48:20 +0900 - - * expand tabs. [ci skip] - - Tabs were expanded because previously the file did not have any tab indentation. - Please update your editor config, and use misc/expand_tabs.rb in the pre-commit hook. - -commit eb92159d72fc711387f7e17ffbaca1678f23fd47 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-10-03 12:26:41 +0900 - - Revert https://github.com/ruby/ruby/pull/2486 - - This reverts commits: 10d6a3aca7 8ba48c1b85 fba8627dc1 dd883de5ba - 6c6a25feca 167e6b48f1 7cb96d41a5 3207979278 595b3c4fdd 1521f7cf89 - c11c5e69ac cf33608203 3632a812c0 f56506be0d 86427a3219 . - - The reason for the revert is that we observe ABA problem around - inline method cache. When a cache misshits, we search for a - method entry. And if the entry is identical to what was cached - before, we reuse the cache. But the commits we are reverting here - introduced situations where a method entry is freed, then the - identical memory region is used for another method entry. An - inline method cache cannot detect that ABA. - - Here is a code that reproduce such situation: - - ```ruby - require 'prime' - - class << Integer - alias org_sqrt sqrt - def sqrt(n) - raise - end - - GC.stress = true - Prime.each(7*37){} rescue nil # <- Here we populate CC - class << Object.new; end - - # These adjacent remove-then-alias maneuver - # frees a method entry, then immediately - # reuses it for another. - remove_method :sqrt - alias sqrt org_sqrt - end - - Prime.each(7*37).to_a # <- SEGV - ``` - -commit ef697388becedf36966a2edcdcf88baca342b9e2 - Author: Jeremy Evans - Date: 2019-10-02 23:56:28 +0900 - - Treat return in block in class/module as LocalJumpError (#2511) - - return directly in class/module is an error, so return in - proc in class/module should also be an error. I believe the - previous behavior was an unintentional oversight during the - addition of top-level return in 2.4. - - Notes: - Merged-By: jeremyevans - -commit 9759e3c9f09ec442b2aa0d0cc299ac791e516a01 - Author: Koichi Sasada - Date: 2019-10-02 17:16:04 +0900 - - fix assertion number. - - On parallel test, there are additional tests because of implicit - checkers which are enabled on 84cbce3d88. - -commit 4ed51b39563df23ad9a9c1fa192ee213cb958991 - Author: Nobuyoshi Nakada - Date: 2019-10-02 15:00:17 +0900 - - Fixed failure message for `clean-cache` - -commit 84cbce3d880f0d6a51ccf3622b8d1e79132b9a0e - Author: Koichi Sasada - Date: 2019-10-02 16:02:00 +0900 - - Enable checkers on parallel test. - - parallel test (`make test-all TESTS=-j8`) runs tests on specified - number of processes. However, some test checkers written in - `runner.rb` are not loaded. This fix enable these checkers on - parallel tests. - - See also: https://github.com/ruby/ruby/pull/2508 - -commit 99d3043bd8e7705cb5ec1772080667981bd07a36 - Author: Alan Wu - Date: 2019-10-02 16:05:40 +0900 - - Iseq#to_binary: dump flag for **nil (#2508) - - RUBY_ISEQ_DUMP_DEBUG=to_binary and the attached test case was failing. - Dump the flag to make sure `**nil` can round-trip properly. - -commit 4946d83a1cbfe23369bdbc8057592b48c673d94b - Author: git - Date: 2019-10-02 13:00:56 +0900 - - * 2019-10-02 [ci skip] - -commit a61ae414b6f8310c9dff9a6f18b6064499167513 - Author: NAKAMURA Usaku - Date: 2019-10-02 13:00:17 +0900 - - Fix the order of executing `after-update` task - -commit 5af2c8735a22e6b54acf4164b1f1f7bac98e7111 - Author: NAKAMURA Usaku - Date: 2019-10-02 12:59:59 +0900 - - Should fail if `system` failed - -commit 15606963de0c818c549aef2352da45d749e4b0db - Author: Hiroshi SHIBATA - Date: 2019-10-01 20:53:16 +0900 - - expose assert_raise and assert_join_threads - - Notes: - Merged: https://github.com/ruby/ruby/pull/2516 - -commit 55de0282da1ae0a16c857fb4b160dea04579b36c - Author: Kazuhiro NISHIYAMA - Date: 2019-10-01 21:26:54 +0900 - - Remove draft-release.yml [ci skip] - - I thought default branch's workflow runs on any tags, - but it does not run for stable branches without draft-release.yml. - So I abandoned, and use workflow in ruby/actions instead. - -commit 3ce238b5f9795581eb84114dcfbdf4aa086bfecc - Author: Yusuke Endoh - Date: 2019-10-01 12:29:18 +0900 - - WEBrick: prevent response splitting and header injection - - This is a follow up to d9d4a28f1cdd05a0e8dabb36d747d40bbcc30f16. - The commit prevented CRLR, but did not address an isolated CR or an - isolated LF. - - Co-Authored-By: NARUSE, Yui - -commit 36e057e26ef2104bc2349799d6c52d22bb1c7d03 - Author: Nobuyoshi Nakada - Date: 2019-08-13 12:14:28 +0900 - - Loop with String#scan without creating substrings - - Create the substrings necessary parts only, instead of cutting the - rest of the buffer. Also removed a useless, probable typo, regexp. - -commit a0a2640b398cffd351f87d3f6243103add66575b - Author: Nobuyoshi Nakada - Date: 2018-12-12 14:38:09 +0900 - - Fix for wrong fnmatch patttern - - * dir.c (file_s_fnmatch): ensure that pattern does not contain a - NUL character. https://hackerone.com/reports/449617 - -commit a38fe1fbf068d05177e6e6fac2b8ec7704873e63 - Author: Yusuke Endoh - Date: 2019-10-01 08:57:50 +0900 - - ext/-test-/enumerator_kw/enumerator_kw.c: remove unused variable - -commit 01e75b6be9987bf9ce0793643470e47a32871c38 - Author: git - Date: 2019-10-01 01:14:45 +0900 - - * 2019-10-01 [ci skip] - -commit 671ca21254a60d967570c8c973f5f2f17beb4931 - Author: Koichi Sasada - Date: 2019-10-01 01:14:19 +0900 - - remove `unused var` warning - -commit a8c436d9a1d333e9391c78d4ffd32568a56534a6 - Author: Jeremy Evans - Date: 2019-09-30 14:49:43 +0900 - - Issue keyword flag warning even with no arguments - - If the keyword flag is set, there should be at least one argument, - if there isn't, that is a sign the keyword flag was passed when it - should not have been. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2509 - -commit 3073404e741df19ae16248126640777ed36110e8 - Author: Jeremy Evans - Date: 2019-09-30 13:33:59 +0900 - - Add rb_enumeratorize_with_size_kw and related macros - - Currently, there is not a way to create a sized enumerator in C - with a different set of arguments than provided by Ruby, and - correctly handle keyword arguments. This function allows that. - - The need for this is fairly uncommon, but it occurs at least in - Enumerator.produce, which takes arguments from Ruby but calls - rb_enumeratorize_with_size with a different set of arguments. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2509 - -commit 5ddc2ba13ed6964a0383894e3728dc1bc708c404 - Author: Yusuke Endoh - Date: 2019-09-30 20:24:26 +0900 - - test/ruby/test_io.rb: suppress a "method redefined" warning - - by explicitly removing the old definition. - -commit fc66947c61fe20f6f584ab3b1f7a5f10982af87e - Author: Yusuke Endoh - Date: 2019-09-30 20:22:29 +0900 - - test/-ext-/string/test_fstring.rb: suppress "possibly useless use of -@" - - "in void context" by assigning the result to a dummy variable. - -commit 945560008ffbb768df3a6e9f0814f2d117993a5e - Author: Koichi Sasada - Date: 2019-09-30 17:59:10 +0900 - - Revert "introduce debug check." - - This reverts commit c3b84f2de83a27acc638f99743bfa2c44bac621c. - Backtrace shows it is before running tests and debug check was - nonsense. - -commit 10d6a3aca78771d0a7bfaecce982aac148152f35 - Author: Nobuyoshi Nakada - Date: 2019-09-30 17:43:11 +0900 - - Fix assertion - - callable_method_entry_p is for rb_callable_method_entry_t. - -commit 771fd915a453d1cbc809189a57520675f2fa3fd4 - Author: Nobuyoshi Nakada - Date: 2019-09-30 17:39:38 +0900 - - Use assert_operator instead of mere assert - -commit 1722c156dd45618cea712f017ca744d6f3b55be8 - Author: Nobuyoshi Nakada - Date: 2019-09-30 17:35:29 +0900 - - Now `use_symbol` is always true - -commit c3b84f2de83a27acc638f99743bfa2c44bac621c - Author: Koichi Sasada - Date: 2019-09-30 17:23:36 +0900 - - introduce debug check. - - There are random failures: - - > lib/rubygems/core_ext/kernel_require.rb:61:in `require': - > wrong number of arguments (given 1, expected 0) (ArgumentError) - http://ci.rvm.jp/results/trunk-jemalloc@silicon-docker/2275159 - - To check this failure, I added a small check code. - -commit 88f38c187e3171f8f351f3198247d20ea9f016ee - Author: Koichi Sasada - Date: 2019-09-30 15:36:19 +0900 - - Emulate method_list (chkbuild) on test-all. - - chkbuild (CI process) shows methods list before - running tests and sometimes it can fails. This - commit a code part to emulate this method listing - feature. - -commit bf8d7d9c1d89a62537566ea6dd43db175a892dbd - Author: Koichi Sasada - Date: 2019-09-30 15:35:22 +0900 - - show RUBY_ISEQ_DUMP_DEBUG envval if given. - -commit 8ba48c1b8509bc52c2fc1f020990c8a3a8eca2c9 - Author: Koichi Sasada - Date: 2019-09-30 14:27:02 +0900 - - rb_method_attr_t::location should be 0 or others. - - method_def_location() expects that rb_method_attr_t::location - is 0 (Qfalse) or not. - -commit 649a64ae29318501472f74798a12eb60871ab990 - Author: Jeremy Evans - Date: 2019-09-30 09:47:17 +0900 - - Add three more C-API functions for handling keywords - - This adds rb_funcall_passing_block_kw, rb_funcallv_public_kw, - and rb_yield_splat_kw. This functions are necessary to easily - handle cases where rb_funcall_passing_block, rb_funcallv_public, - and rb_yield_splat are currently used and a keyword argument - separation warning is raised. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2507 - -commit fba8627dc1c5b191713edeb5fc21cbe0ddde9e3c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-26 13:44:51 +0900 - - delete unnecessary branch - - At last, not only myself but also your compiler are fully confident - that the method entries pointed from call caches are immutable. We - don't have to worry about silent updates. Just delete the branch - that is now always false. - - Calculating ------------------------------------- - ours trunk - vm2_poly_same_method 2.142M 2.070M i/s - 6.000M times in 2.801148s 2.898994s - - Comparison: - vm2_poly_same_method - ours: 2141979.2 i/s - trunk: 2069683.8 i/s - 1.03x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit dd883de5ba311c38818d0f638a94b4fbc63f5ee5 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-26 10:22:01 +0900 - - refactor constify most of rb_method_entry_t - - Now that we have eliminated most destructive operations over the - rb_method_entry_t / rb_callable_method_entry_t, let's make them - mostly immutabe and mark them const. - - One exception is rb_export_method(), which destructively modifies - visibilities of method entries. I have left that operation as is - because I suspect that destructiveness is the nature of that - function. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 6c6a25feca8752205d81c5247f85d8ae8fb880d8 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-25 17:00:25 +0900 - - refactor add rb_method_entry_from_template - - Tired of rb_method_entry_create(..., rb_method_definition_create( - ..., &(rb_method_foo_t) {...})) maneuver. Provide a function that - does the thing to reduce copy&paste. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 167e6b48f1b321d671998728adf5a0db06d24445 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-25 15:52:02 +0900 - - refactor reduce METHOD_ENTRY_FLAGS_COPY - - Make things more immutable. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 7cb96d41a52d5ce4b2485ff542edc88fa246bc1a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-25 13:51:06 +0900 - - refactor delete rb_method_entry_copy - - The deleted function was to destructively overwrite existing method - entries, which is now considered to be a bad idea. Delete it, and - assign a newly created method entry instead. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 3207979278bea11c50cb84f4044047b9c503230b - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-24 15:41:52 +0900 - - refactor delete rb_method_definition_set - - Instead of destructively write fields of method entries, create a - new entry and let it overwrite its owner. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 595b3c4fddc5cde58add2fa2637acb2664694194 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-23 17:42:27 +0900 - - refactor rb_method_definition_create take opts - - Before this changeset rb_method_definition_create only allocated a - memory region and we had to destructively initialize it later. - That is not a good design so we change the API to return a complete - struct instead. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 1521f7cf89fe3cf356a589c45bce4ccb57dce7fd - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-20 17:16:44 +0900 - - refactor delete vm_cref_dump - - No longer used. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit c11c5e69ac66ae10255a20a6b84e481f0423703d - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-20 17:01:53 +0900 - - refactor split rb_method_definition_set - - Did you know that C functions can return structs? That has been - true since the beginning, but not that very useful until C99. Now - that we can write compound literals, this feature is much easier - to use. By allowing struct-returning functions, some formerly big - functions can be split into smaller ones, like this changeset. - - At least GCC is smart enough to inline the split functions back - into one. No performance penalty is observed. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit cf336082039ae84b5001908f6bb7e04bdda8893e - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-20 14:12:51 +0900 - - refactor constify most of rb_method_definition_t - - Most (if not all) of the fields of rb_method_definition_t are never - meant to be modified once after they are stored. Marking them const - makes it possible for compilers to warn on unintended modifications. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 3632a812c0b1e0bd1c75b2426cbfe9ec1715bb56 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-25 13:00:56 +0900 - - refactor add rb_id_table_foreach_with_replace_with_key - - This is a pure refactoring to reduce copy & paste. Also the new - function is made visible from other parts of the interpreter, to - be used later. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit f56506be0dc7f1a9cb35d8371b04720bef50fd9b - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-25 13:11:28 +0900 - - refactor delete ID_TABLE_ITERATOR_RESULT_END - - Not used from anywhere. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 86427a321997b733bf8ebb6036157c341a52edfc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-26 10:26:40 +0900 - - refactor delete METHOD_ENTRY_COMPLEMENTED flag - - Because rb_method_definition_t tracks its own complemented_count, - we no longer have to check it in rb_method_entry_t side. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2486 - -commit 6fdd701472af5355562cb2394167b26a4c3a2a97 - Author: Jeremy Evans - Date: 2019-09-30 08:41:00 +0900 - - Remove VM_NO_KEYWORDS, replace with RB_NO_KEYWORDS - - VM_NO_KEYWORDS was introduced first in vm_core.h, but it is best - to only use a single definition for this. - -commit 58dfea0c8de29cbad35621847c04372b779c5f5d - Author: Jeremy Evans - Date: 2019-09-30 05:15:04 +0900 - - Make direct calls to rb_{obj_instance,mod_module}_{eval,exec} not pass keywords - - In general RB_PASS_CALLED_KEYWORDS should only be set if we are - sure the arguments passed come directly from Ruby. For direct calls - to these C functions, we should not assume that keywords are passed. - Add static *_internal versions of these functions that - Kernel#instance_{eval,exec} and Module#{class,module}_{eval,exec} - call that set RB_PASS_CALLED_KEYWORDS. - - Also, change struct.c back to calling rb_mod_module_eval, now that - the call is safe. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2505 - -commit 59060aadea28d3a6cd0ebbcc17c10a3628e6e867 - Author: Benoit Daloze - Date: 2019-09-30 06:43:15 +0900 - - Run test-unit tests in CI - - Notes: - Merged: https://github.com/ruby/ruby/pull/2506 - -commit 2740b869051f773147bd1e26d7b489eab9037c04 - Author: Benoit Daloze - Date: 2019-09-30 06:42:51 +0900 - - Update to latest test-unit - - * See https://github.com/test-unit/test-unit/issues/165 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2506 - -commit 54d49aeb52fd1a8699004eb5065779cd8c6eb3a9 - Author: Benoit Daloze - Date: 2019-09-30 02:56:15 +0900 - - Update to ruby/spec@2699ea4 - -commit 869e4f6e4c683bf8e76ae7db54a26b33fb925410 - Author: Jeremy Evans - Date: 2019-09-30 01:15:43 +0900 - - Fix or suppress keyword argument separation warnings in util_spec - - Some warnings are because the @o.rb_scan_args call doesn't - include keyword arguments, but the first argument is passed to - rb_scan_args may have a last hash treated as keywords. Those - should be handled using rb_scan_args_kw on Ruby 2.7. - - Other warnings are for the deprecated rb_scan_args behavior to - split option hashes or treat a nil argument as an option hash. - Those warnings should just be suppressed. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2504 - -commit 070cbe22b70ec2bec36c7cfc84b726510afa306f - Author: Benoit Daloze - Date: 2019-09-30 02:13:37 +0900 - - Update to ruby/spec@34e6246 - -commit d51b4e34fbdbe1a845aa2251b1fa3304de809b32 - Author: Benoit Daloze - Date: 2019-09-30 02:13:35 +0900 - - Update to ruby/mspec@5dda9fb - -commit 2d41c712a73a1b5d85dd8d5bf9134ed1be0e94eb - Author: Benoit Daloze - Date: 2019-09-30 01:34:12 +0900 - - Skip default gemspecs spec if the default_specifications_dir cannot be found - -commit 59648af296ab15a2e34ebce62a7cc14deb889e7b - Author: Nobuyoshi Nakada - Date: 2019-09-30 01:08:32 +0900 - - Suppress keyword argument warning from #step - - * numeric.c (num_step): pass the extracted argument from keyword - argument, not the last argument itself which should have been - warned already. - -commit f39314a98ac6e762e8f5d72d80923038b0b5f01a - Author: git - Date: 2019-09-30 01:02:54 +0900 - - * 2019-09-30 [ci skip] - -commit a17bc04d159ec9839cc8cfb02dc0cdd2802110f4 - Author: Benoit Daloze - Date: 2019-09-30 01:01:32 +0900 - - Update to ruby/spec@e69a14c - -commit f9a9f3c7c6cf3fe534d4934dd3b502d721151b81 - Author: Benoit Daloze - Date: 2019-09-30 01:01:30 +0900 - - Update to ruby/mspec@8cabcef - -commit 1c938a72aa9378f982dbc55327e86150c47b8707 - Author: Benoit Daloze - Date: 2019-09-29 23:03:58 +0900 - - Update to ruby/spec@519df35 - -commit 31bb66a19df26409c9d47afcf37919c9a065516a - Author: Benoit Daloze - Date: 2019-09-29 23:03:47 +0900 - - Update to ruby/mspec@8106083 - -commit a27dc83113afa9831dcdf919138666b09a73ccf6 - Author: Benoit Daloze - Date: 2019-09-29 19:38:21 +0900 - - Pass $(XRUBY) to test-bundled-gems.rb since RbConfig.ruby is incorrect for miniruby - - Notes: - Merged: https://github.com/ruby/ruby/pull/2503 - -commit 4096e4b08c46dddb8edc9dabf70e737946ac6df8 - Author: Benoit Daloze - Date: 2019-09-29 19:16:10 +0900 - - Move the logic to test bundled gems to Ruby code - - * Writing shell scripts in a Makefile is very error-prone. - * TEST_BUNDLED_GEMS_ALLOW_FAILURES seemed to not work before. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2503 - -commit d090e449ef4e92b2020e51fe495cd039e4f6fdda - Author: Benoit Daloze - Date: 2019-09-29 19:18:49 +0900 - - Exclude the test-unit bundled gem tests since they also fail since the Time#inspect change - - * See https://github.com/test-unit/test-unit/issues/165 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2503 - -commit e3b11566bfbb6ddcdd9f3483a6bdeb501a610fa9 - Author: Benoit Daloze - Date: 2019-09-28 18:45:23 +0900 - - Remove continue-on-error for test-bundled-gems - - * Otherwise, it takes a very long time to notice those tests broke. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2503 - -commit f6f03dcad60d38868d345172ad5c5d2ce44bd004 - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:07:51 +0900 - - [ruby/stringio] Bump up the version - - https://github.com/ruby/stringio/commit/f0e5027279 - -commit 7fe253f47f55f69069fc0e03879a3a2b55aee408 - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:06:02 +0900 - - [ruby/stringio] Use rb_funcallv_kw when delegating arguments - - https://github.com/ruby/stringio/commit/5892663e32 - -commit 68ab4a5e35d30a8f1c4620dfa8f5132f4996f2fc - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:02:00 +0900 - - [ruby/stringio] Replaced rb_funcall2 with rb_funcallv - - https://github.com/ruby/stringio/commit/a37ab7c419 - -commit ef795f9abdb1db1bfa061dbc97d294db4f87756f - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:13:41 +0900 - - [ruby/stringio] Dropped older ruby versions - - https://github.com/ruby/stringio/commit/e8065153b8 - -commit 7f30783af73bb484912365c28da4e7292f1d8211 - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:13:00 +0900 - - [ruby/stringio] Get rid of String#undump for ruby 2.4 or earlier - - https://github.com/ruby/stringio/commit/4dfd997e0a - -commit 94db8cda9b4eeee4736d089570a343fdf5ef86c0 - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:52:31 +0900 - - [ruby/zlib] Fix for older ruby 2.6 or earlier - - https://github.com/ruby/zlib/commit/00ead8cb2c - -commit f10c9cb1f2dfca024937bc48137168124d8511aa - Author: Nobuyoshi Nakada - Date: 2019-09-29 18:21:17 +0900 - - [ruby/zlib] Search zlib.c as a gem - - https://github.com/ruby/zlib/commit/8f43b264cd - -commit ce477089f690d3bedcaef088158b429db8a97d64 - Author: Benoit Daloze - Date: 2019-09-29 18:04:28 +0900 - - [DOC] Fix typos in Array#{to_s,inspect} doc [ci skip] - -commit e2d97cffe5aecc88f3fc4dc7be9a7b3a57bede87 - Author: Nobuyoshi Nakada - Date: 2019-09-29 17:28:58 +0900 - - [DOC] stated that Array#to_s calls #inspect [ci skip] - - [ruby-list:50826] - -commit 289cad501d7a5219568450333d440364674441b0 - Author: git - Date: 2019-09-29 13:17:05 +0900 - - * 2019-09-29 [ci skip] - -commit 6e1b72ae4afca7c7726e3f03171b597c2d0f12b0 - Author: Yuki Nishijima - Date: 2019-09-29 13:15:09 +0900 - - Upgrade to the latest did_you_mean 1.3.1 - -commit 550a6a6bc1be4ff9aa6b65f6ad9b45c3fa2d1344 - Author: Nobuyoshi Nakada - Date: 2019-09-28 13:51:27 +0900 - - NEWS: marked up `**nil` [ci skip] - -commit d474243e8c635a011ce2789660cb71b3f6815317 - Author: Nobuyoshi Nakada - Date: 2019-09-28 13:49:49 +0900 - - NEWS: Added module name to proc and lambda [ci skip] - - RDoc cannot know if bare words are method name or not. - -commit d53cf854741bbf496298c5a722988d2dd84314a1 - Author: Jeremy Evans - Date: 2019-09-28 00:07:49 +0900 - - Fix warning when doing Struct.new(:x, keyword_init: true){} - - This is due to calling rb_mod_module_eval directly instead of using - rb_funcall_passing_block. - - The problem with calling directly is it does not create a new VM - frame, so rb_mod_module_eval was called with no arguments, but with - the keyword given VM frame flag set, which causes problems - internally. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2500 - -commit 7814b6c6572446a6b64614e524d13dd423577004 - Author: Jeremy Evans - Date: 2019-09-28 01:35:51 +0900 - - Correctly issue ArgumentError when calling method that accepts no keywords - - If a method accepts no keywords and was called with a keyword, an - ArgumentError was not always issued previously. Force methods that - accept no keywords to go through setup_parameters_complex so that - an ArgumentError is raised if keywords are provided. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2501 - -commit fd0e2141835a0ef98b31d0a6b23924413f8452d3 - Author: Jeremy Evans - Date: 2019-09-28 01:43:31 +0900 - - Update NEWS section on keyword argument separation [ci skip] - - This may be too verbose, if so, maybe it should be moved lower in - the document, or to a separate document. - -commit 707c48859e30760712a6a57d1f3df5e8a9d4ea33 - Author: git - Date: 2019-09-28 01:24:51 +0900 - - * 2019-09-28 [ci skip] - -commit a1fda16b238f24cf55814ecc18f716cbfff8dd91 - Author: Dylan Thacker-Smith - Date: 2019-09-28 01:24:25 +0900 - - Optimize Array#flatten and flatten! for already flattened arrays (#2495) - - * Optimize Array#flatten and flatten! for already flattened arrays - * Add benchmark for Array#flatten and Array#flatten! - - [Bug #16119] - -commit 869e2dd8c8efc1e7a043c9eee82d97c47befbcc7 - Author: Jeremy Evans - Date: 2019-06-27 05:20:22 +0900 - - Warn for URI.{,un}{escape,encode}, even if not in verbose mode - - The verbose mode warning has been present for almost 10 years. - If we ever plan to remove these methods, we should make the warning - a regular deprecation warning so that people are aware. - - Implements [Feature #15961] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2494 - -commit a2c26fe1c6d49b54494b7c6301cc4c77596eec0c - Author: Jeremy Evans - Date: 2019-06-21 06:47:15 +0900 - - Fix fallback in URI.encode_www_form_component to include # - - Patch from Matthew Kerwin. - - Fixes [Bug #14358] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2494 - -commit 43a16c98df392e726040f0331a3e09d00c53d513 - Author: Jeremy Evans - Date: 2019-06-21 05:19:48 +0900 - - Do not escape + in Shellwords.escape - - + is not a character that requires escaping in Bourne sh. - - Fixes [Bug #14429] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2494 - -commit 2b6a9f3a1ffcdb00bf89798979d475c6d189d419 - Author: Jeremy Evans - Date: 2019-06-21 04:59:29 +0900 - - Ignore Errno::EPIPE when sending requests in net/http - - An EPIPE when sending the request should be ignored. Even if you - cannot write more data, you may still be able to read the server's - response. - - Fixes [Bug #14466] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2494 - -commit 80d0b6f132e6475c0b9c78ff857e7bb81c93df0d - Author: Nobuyoshi Nakada - Date: 2019-09-27 21:54:26 +0900 - - Updated bundled_gems - -commit 79d5332a2da0e2743a77480aebfca256a54a962e - Author: Nobuyoshi Nakada - Date: 2019-09-27 21:12:27 +0900 - - Drop eliminated catch-entries - - Drop catch table entries used in eliminated block, as well as - call_infos. [Bug #16184] - -commit 03284fb91151bff5e12f1b7d5cdb0589f1ee43fb - Author: Nobuyoshi Nakada - Date: 2019-09-27 21:07:53 +0900 - - assert_in_out_err should use FailDesc too - -commit 8d0ff887274fdc73415035d652551d1fa0768c7b - Author: Nobuyoshi Nakada - Date: 2019-09-27 14:06:07 +0900 - - Adjusted spaces [ci skip] - -commit 4d3502d57f53d5cd54452d9b19475944055989f4 - Author: Nobuyoshi Nakada - Date: 2019-09-27 14:01:37 +0900 - - More tests for [Feature #16150] - -commit eff15a269fdc37d2b09cf1dfe8c1b1bf6e377a32 - Author: Jean Boussier - Date: 2019-09-27 00:27:47 +0900 - - [EXPERIMENTAL] Make NilClass#to_s, TrueClass#to_s and FalseClass#to_s return a frozen String - - * Always the same frozen String for each of these values. - * Avoids extra allocations whenever calling these 3 methods. - * See [Feature #16150] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2492 - -commit 2082a26dc75da7cb76150b51cd5b8f7636ad0fa2 - Author: Hiroshi SHIBATA - Date: 2019-09-26 18:32:26 +0900 - - [ruby/fileutils] Bump version to 1.3.0. - - https://github.com/ruby/fileutils/commit/ba3bd6fdfd - -commit 49b7805e9acd181838c17d5aa9e14244a4cce365 - Author: Hiroshi SHIBATA - Date: 2019-08-12 21:05:53 +0900 - - [ruby/fileutils] Use Gemfile instead of Gem::Specification#add_development_dependency. - - https://github.com/ruby/fileutils/commit/17a9de6d9b - -commit d5355123ccf41c05766b1d58b75419bece61b8ea - Author: Kazuhiro NISHIYAMA - Date: 2019-08-24 21:19:31 +0900 - - [ruby/fileutils] Reduce global variables - - https://github.com/ruby/fileutils/commit/ba81f024cf - -commit 06c35cfa65ed5e023bb8b82af93a3d711e550913 - Author: Jeremy Evans - Date: 2019-08-24 06:52:12 +0900 - - [ruby/fileutils] Fix cp_r with symlink root on Windows - - Previously this would copy the symlink root as a symlink instead - of creating a new root directory. This modifies the source - to expand it using File.realpath before starting the copy. - - Fixes Ruby Bug 12123 - - https://github.com/ruby/fileutils/commit/7359cef359 - -commit 9792c9d183ccc0e80230858c910c74cfef5ddc32 - Author: Jeremy Evans - Date: 2019-08-24 06:50:34 +0900 - - [ruby/fileutils] Fix test_cp_r_dev on Windows or other systems without character/block device in /dev - - Previously this would give an error such as: - - TestFileUtils#test_cp_r_dev [c:/fileutils/test/fileutils/test_fileutils.rb:455]: - [RuntimeError] exception expected, not. - Class: - Message: <"no implicit conversion of nil into String"> - - https://github.com/ruby/fileutils/commit/0ce0fefbeb - -commit 9494ef8b2de3a7224eb85800606e7c046964cbd2 - Author: Jeremy Evans - Date: 2019-08-01 04:57:21 +0900 - - [ruby/fileutils] Do not break in verbose mode if using FileUtils with a frozen object - - If FileUtils is included into another object, and verbose mode is - used, a FrozenError is currently raised unless the object has the - @fileutils_output and @fileutils_label instance variables. - - This fixes things so that it does not attempt to set the instance - variables, but it still uses them if they are present. - - https://github.com/ruby/fileutils/commit/689cb9c56a - -commit 02cd42050515b3af67396a25e78d948adcac6cdf - Author: Jeremy Evans - Date: 2019-07-15 02:17:57 +0900 - - [ruby/fileutils] Skip test_cp_r_socket on JRuby - - https://github.com/ruby/fileutils/commit/20bb9ec789 - -commit 1d99163aa59b637f1c14287135f26480df447e49 - Author: Jeremy Evans - Date: 2019-07-10 12:41:51 +0900 - - [ruby/fileutils] Make copy methods handle FIFOs and UNIX sockets - - Previously, this was broken. Trying to copy a FIFO would raise a - NoMethodError if File.mkfifo was defined. Trying to copy a UNIX - socket would raise a RuntimeError as File.mknod is not something - Ruby defines. - - Handle the FIFO issue using File.mkfifo instead of mkfifo. - - Handle the UNIX Socket issue by creating a unix socket. - - Continue to not support character or block devices, raising a - RuntimeError for both. - - Add tests for FIFO, UNIX Socket, and character/block devices. - - https://github.com/ruby/fileutils/commit/123903532d - -commit 366dd9d80308e6526502ef636b63893b3fb41af2 - Author: zverok - Date: 2019-03-10 20:09:59 +0900 - - [ruby/fileutils] Update the documentation content and formatting - - https://github.com/ruby/fileutils/commit/b701353c53 - -commit 660c7e050f6cb050fd5618f812129c211af29810 - Author: Jeremy Evans - Date: 2019-09-27 09:25:54 +0900 - - Fix more keyword separation issues - - This fixes instance_exec and similar methods. It also fixes - Enumerator::Yielder#yield, rb_yield_block, and a couple of cases - with Proc#{<<,>>}. - - This support requires the addition of rb_yield_values_kw, similar to - rb_yield_values2, for passing the keyword flag. - - Unlike earlier attempts at this, this does not modify the rb_block_call_func - type or add a separate function type. The functions of type - rb_block_call_func are called by Ruby with a separate VM frame, and we can - get the keyword flag information from the VM frame flags, so it doesn't need - to be passed as a function argument. - - These changes require the following VM functions accept a keyword flag: - - * vm_yield_with_cref - * vm_yield - * vm_yield_with_block - - Notes: - Merged: https://github.com/ruby/ruby/pull/2493 - -commit 0c6f36668a11902903d85ada61a812d297d02de5 - Author: Nobuyoshi Nakada - Date: 2019-09-27 10:20:56 +0900 - - Adjusted spaces [ci skip] - -commit 293c6c8cc3cd9a9cb2910672589ee3631e1f1653 - Author: Aaron Patterson - Date: 2019-09-10 07:46:07 +0900 - - Add compaction support to `rb_ast_t` - - This commit adds compaction support to `rb_ast_t`. - -commit 37f9213f8957e0c6dffee7d8803890907f97bdbb - Author: Jeremy Evans - Date: 2019-09-27 01:10:42 +0900 - - Fix keyword argument separation issues in Enumerator::Generator#each - - This requires adding rb_proc_call_kw to pass the keyword flag. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2491 - -commit dd2068ac8d4016f43c1f3cc1aa81decb504db5b6 - Author: Jeremy Evans - Date: 2019-09-27 01:09:30 +0900 - - Add rb_adjust_argv_kw_splat to internal.h - - We are calling this in a few other files, it is better to have it - in a header than adding prototypes to the other files. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2491 - -commit 31339ef4f2af9c7dad2a81eaa9470ee4574181a0 - Author: George Claghorn - Date: 2019-09-12 04:47:20 +0900 - - Honor Syslog::Logger#level overrides - - Notes: - Merged: https://github.com/ruby/ruby/pull/2453 - -commit f5e8d33761aa2c0d8bec18ba21aeef4bb6940640 - Author: Aaron Patterson - Date: 2019-09-27 06:57:45 +0900 - - Fix clang errors when pedantic errors enabled - - I've been compiling with: - - ``` - set -lx cflags '-std=c99 -Werror=pedantic -pedantic-errors' - ``` - - But compilation would fail with the following: - - ``` - cont.c:296:90: error: format specifies type 'void *' but the argument has type 'struct fiber_pool_stack *' [-Werror,-Wformat-pedantic] - if (DEBUG) fprintf(stderr, "fiber_pool_stack_alloca(%p): %"PRIuSIZE"/%"PRIuSIZE"\n", stack, offset, stack->available); - ~~ ^~~~~ - cont.c:467:24: error: format specifies type 'void *' but the argument has type 'struct fiber_pool *' [-Werror,-Wformat-pedantic] - count, fiber_pool, fiber_pool->used, fiber_pool->count, size, fiber_pool->vm_stack_size); - ^~~~~~~~~~ - cont.c:588:83: error: format specifies type 'void *' but the argument has type 'struct fiber_pool_vacancy *' [-Werror,-Wformat-pedantic] - if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", fiber_pool->vacancies, fiber_pool->used); - ~~ ^~~~~~~~~~~~~~~~~~~~~ - cont.c:736:76: error: format specifies type 'void *' but the argument has type 'rb_fiber_t *' (aka 'struct rb_fiber_struct *') - [-Werror,-Wformat-pedantic] - if (DEBUG) fprintf(stderr, "fiber_stack_release: %p, stack.base=%p\n", fiber, fiber->stack.base); - ``` - - This commit just fixes the pedantic errors - -commit 4808afb360c58e26669fec5a60a55088e16fdb4a - Author: Aaron Patterson - Date: 2019-09-27 05:19:11 +0900 - - Replace `freeze_string` with `rb_fstring` - -commit 0846d48853d460de50dda477d8c75024ba96679b - Author: Aaron Patterson - Date: 2019-09-27 05:16:33 +0900 - - Remove `iseq_add_mark_object_compile_time` - - This function is just a synonym for RB_OBJ_WRITTEN, so we can just - directly call that. - -commit 9b6460caccc125be6ba9f2dace9eaafbbe5bc438 - Author: Aaron Patterson - Date: 2019-09-26 06:57:25 +0900 - - Remove mark array - - We don't use this array anymore so we can remove it - -commit e197d9ca71570c980274ddd2cb6a32af6c00d95e - Author: Aaron Patterson - Date: 2019-09-26 06:08:11 +0900 - - Execute write barrier instead of adding to array - - We can mark everything via the instruction objects, so just execute the - write barrier instead of appending to the array - -commit 98d7583bfcf1442c01ebe0288726cacef138d349 - Author: Aaron Patterson - Date: 2019-09-26 05:59:54 +0900 - - Pull `iseq_add_mark_object_compile_time` out of `freeze_string` - - `freeze_string` essentially called iseq_add_mark_object_compile_time. I - need to know where all writes occur on the `rb_iseq_t`, so this commit - separates the function calls so we can add write barriers in the right - place. - -commit f639e046992d8d757b9745bfc02918f2acb8b23c - Author: Aaron Patterson - Date: 2019-09-24 04:10:33 +0900 - - Pull "mark object" up - - Move the "add mark object" function to the location where we should be - calling RB_OBJ_WRITTEN. I'm going to add verification code next so we - can make sure the objects we're adding to the array are also reachable - from the mark function. - -commit 50fadefb7ed275148b2266712b923b8cca1ed785 - Author: Aaron Patterson - Date: 2019-09-17 09:19:44 +0900 - - Scan the ISEQ arena for markables and mark them - - This commit scans the ISEQ arena for objects that can be marked and - marks them. This should make the mark array unnecessary. - -commit a618d6408653b7f2459acb5af6205c42ad3aad87 - Author: Aaron Patterson - Date: 2019-09-17 08:09:46 +0900 - - Allocate `INSN *` out of a separate arena - -commit 3cd8f76f7f1bc09f9dd6b65eaafe2fd3a990ac60 - Author: Aaron Patterson - Date: 2019-09-13 07:21:18 +0900 - - Introduce a secondary arena - - We'll scan the secondary arena during GC mark. So, we should only - allocate "markable" instruction linked list nodes out of the secondary - arena. - -commit bd017c633da4fe27c85b5dfc059b85d44a3b7afe - Author: Aaron Patterson - Date: 2019-09-13 07:15:43 +0900 - - Extract allocation and free functions - - Now we can allocate and free a secondary arena. - -commit 451776f13d24b0121b2bdfbe4eaafe7c74069c72 - Author: Aaron Patterson - Date: 2019-09-13 07:02:23 +0900 - - Pass in arena to allocator - - This is so we can configure a new arena later - -commit dd1e047fcb2a6429dd960b38a9ce03f86bb828fa - Author: Nobuyoshi Nakada - Date: 2019-09-27 02:31:39 +0900 - - NEWS: fixed markups and indent [ci skip] - - C API updates: - - * adjusted indent. - * marked up ANYARGS as RDoc. - -commit 81191afe8a9b40e6dd6cc8e0d1a9899938840073 - Author: Nobuyoshi Nakada - Date: 2019-09-27 01:13:10 +0900 - - Kernel#open may be redefined - -commit 617fa3049a151d773bb26151ae774a8f6a60bc2a - Author: Nobuyoshi Nakada - Date: 2019-09-27 00:48:48 +0900 - - NEWS: fixed markups and formatting [ci skip] - - * got rid of inadvertent label lists. - * marked up resolve_feature_path method names. - * fixed indentation of UnboundMethod#bind_call and marked up as - RDoc. - -commit 876c5fe1b2ba38fd893a81f91769b11f78cf4e92 - Author: Nobuyoshi Nakada - Date: 2019-09-27 00:37:54 +0900 - - Check the argument size - - Ensure that argument array size does not overflow as `int`, before - cast in thread_do_start after new thread created. - -commit 3b9cdc59ce7c992f1906638be6acf2a9eeb6d58b - Author: git - Date: 2019-09-27 00:02:18 +0900 - - * 2019-09-27 [ci skip] - -commit 955634283862d9d1966de43c73ece15714afdae2 - Author: Jeremy Evans - Date: 2019-09-26 09:59:41 +0900 - - Fix shorten-64-to-32 compile warnings/errors - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit b193041b992e5ce0ae1a07735fbdc53a739b5434 - Author: Jeremy Evans - Date: 2019-09-26 09:57:00 +0900 - - Fix keyword argument separation issues in Fiber#resume - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 6b52959ef76f6f19e50c6f80f00c08bb0daf5c7c - Author: Jeremy Evans - Date: 2019-09-26 09:14:17 +0900 - - Fix keyword argument separation issues in Thread.new - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 47d44510a3f5c6cfca69b3fc05d7f5f35b1b2784 - Author: Jeremy Evans - Date: 2019-09-26 07:32:35 +0900 - - Fix more keyword argument separation issues in Pathname - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 3959469f240edb6c1f43976bbb72a0ba9105a6b1 - Author: Jeremy Evans - Date: 2019-09-26 07:03:09 +0900 - - Fix keyword argument separation issues in OpenSSL::SSL::SSLSocket#sys{read,write}_nonblock - - It's unlikely anyone would actually hit these. The methods are - private, you only hit this code path if calling these methods - before performing the SSL connection, and there is already a - verbose warning issued. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 760893d2f85682a3c8c00be4b29dea0f6b2bb4f8 - Author: Jeremy Evans - Date: 2019-09-26 03:22:14 +0900 - - Fix keyword argument separation issues in Proc#{<<,>>} - - This requires adding rb_proc_call_with_block_kw. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 0aa267f985084e69c3e45cc3e94698eaacab5c36 - Author: Jeremy Evans - Date: 2019-09-26 03:02:40 +0900 - - Fix keyword argument sepration issues when IO#open calls #to_open - - Notes: - Merged: https://github.com/ruby/ruby/pull/2484 - -commit 5b9d646944fe3a2f92682be906b0e9c7beae323c - Author: Jean Boussier - Date: 2019-09-26 20:41:41 +0900 - - Fix Module#name news and add a test - - Notes: - Merged: https://github.com/ruby/ruby/pull/2488 - -commit b29c68e6876976b22f64318bf390f05447e4ca01 - Author: Nobuyoshi Nakada - Date: 2019-09-26 22:57:25 +0900 - - Restore ENV, rubygems always sets SOURCE_DATE_EPOCH now - -commit c4ec817a7a6bc104dc1caf9018bc97a2dbfd324e - Author: Nobuyoshi Nakada - Date: 2019-09-26 22:56:32 +0900 - - Gem::Specification#to_ruby needs OpenSSL - -commit 41e3c204fd83660a243fa61f91aeda2a78817a97 - Author: Takashi Kokubun - Date: 2019-09-26 22:13:24 +0900 - - Reduce ISeq size of mjit_exec benchmark - - to avoid unwanted memory pressure - -commit 1070456bb8ddf48be7b601daa024fe372c3c25c1 - Author: git - Date: 2019-09-26 20:25:42 +0900 - - * remove trailing spaces. [ci skip] - -commit 9d0866c7d7b9cbe36a851744a37806e747e0e7a8 - Author: Jean Boussier - Date: 2019-09-26 17:41:43 +0900 - - [EXPERIMENTAL] Make Module#name return a frozen String - - * Always the same frozen String for a given Module or Class. - * Avoids extra allocations whenever calling Module#name. - * See [Feature #16150] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2487 - -commit c8f71686533cf068ad2f7a2e9fbb95a5c9f44642 - Author: Hiroshi SHIBATA - Date: 2019-09-26 19:22:30 +0900 - - Revert the accidentally commits related GitHub Actions - -commit 2a490d5660ac869f8f2bbcec4887b1dc2950643f - Author: Hiroshi SHIBATA - Date: 2019-09-26 18:24:20 +0900 - - Suppress assert_match warnings. - -commit d4a86e407ec2057c2c7ad757aa76dad757f34c3a - Author: Hiroshi SHIBATA - Date: 2019-09-26 18:07:17 +0900 - - Assert warnings message for the last argument is keyword parameter. - -commit a2af47301834ede4892dbbe1b7da28317202657e - Author: David Rodríguez - Date: 2019-09-12 16:44:22 +0900 - - [rubygems/rubygems] Make sure our modifications to kernel.warn work - - And test the fix we're adding. - - https://github.com/rubygems/rubygems/commit/6f86637b98 - -commit 54839f01736a8827be64c7f1720d226d37fa17d3 - Author: David Rodríguez - Date: 2019-09-12 17:19:11 +0900 - - [rubygems/rubygems] Fix jruby build - - https://github.com/rubygems/rubygems/commit/cc255b774a - -commit 966915d807f4d9ce8b9efaf5fedcceada05528c0 - Author: Hiroshi SHIBATA - Date: 2019-09-26 14:06:37 +0900 - - [rubygems/rubygems] indent - - https://github.com/rubygems/rubygems/commit/8cdb2fd66f - -commit 1eb503373e808b9cd2e1dbff5ec72d151a74d981 - Author: Hiroshi SHIBATA - Date: 2019-09-25 21:34:55 +0900 - - [rubygems/rubygems] filter dependency type and name strictly. - - Co-authored-by: Yusuke Endoh - - https://github.com/rubygems/rubygems/commit/92892bbc3a - -commit 0b65a7a19e949eece72a6a961a2642c0e5e19eb0 - Author: bronzdoc - Date: 2019-09-26 10:31:57 +0900 - - [rubygems/rubygems] Fix test_gem_attr - - https://github.com/rubygems/rubygems/commit/7c5b66f9ef - -commit 4f87a1583dce25749c0492146ef78fcb0319ccd2 - Author: David Rodríguez - Date: 2019-09-25 00:35:00 +0900 - - [rubygems/rubygems] Introduce default prerelease requirement - - https://github.com/rubygems/rubygems/commit/506c5bce49 - -commit 6134fd7a646842ca67081cd07a182642307138bd - Author: David Rodríguez - Date: 2019-09-25 00:27:27 +0900 - - [rubygems/rubygems] Remove comment not adding much - - https://github.com/rubygems/rubygems/commit/b3b5c2d379 - -commit 73633683c5a880af0207a55c6f3ea42c13cb5de1 - Author: f - Date: 2019-09-21 00:54:48 +0900 - - [rubygems/rubygems] add tests - - https://github.com/rubygems/rubygems/commit/8a7e27381c - -commit 1fb44d2b8c324afdb969c37df48b0ff5856fa65f - Author: f - Date: 2019-09-20 22:38:10 +0900 - - [rubygems/rubygems] Detect libc version, closes #2918 - - https://github.com/rubygems/rubygems/commit/1d18b12a26 - -commit ea5b1361557690569a33204c122a08f2faefdf91 - Author: David Rodríguez - Date: 2019-09-10 18:07:03 +0900 - - [rubygems/rubygems] Fix underscore version for bundler itself - - Previously it wouldn't play nice with the bundler version finder. - - https://github.com/rubygems/rubygems/commit/d8bb81556d - -commit ad638a713a953f62ff598fd820b44a3318f4241e - Author: Hiroshi SHIBATA - Date: 2019-09-17 18:06:50 +0900 - - [rubygems/rubygems] Added jruby to matrix - - https://github.com/rubygems/rubygems/commit/0832c079c8 - -commit 769a28d7dc913740d864e7478bbc7f9b3a188a5b - Author: Hiroshi SHIBATA - Date: 2019-09-15 14:32:30 +0900 - - [rubygems/rubygems] Removed 2.2 - - https://github.com/rubygems/rubygems/commit/7fd2460f76 - -commit ba8fb735cb3151ce48e388878da0565119222e95 - Author: Hiroshi SHIBATA - Date: 2019-09-15 14:13:00 +0900 - - [rubygems/rubygems] Added rvm workflow for Ruby 2.2 and 2.7 - - https://github.com/rubygems/rubygems/commit/d4ba75dfd2 - -commit 01c90f17d974c002c054ff2d82ec3982b665b01a - Author: Hiroshi SHIBATA - Date: 2019-09-15 11:37:30 +0900 - - [rubygems/rubygems] Removed the needless configurations - - https://github.com/rubygems/rubygems/commit/7134c49179 - -commit f5248f6f504701960a2bbb7a51117060f7d66613 - Author: Hiroshi SHIBATA - Date: 2019-08-09 16:20:50 +0900 - - [rubygems/rubygems] Added the initial workflow file. - - https://github.com/rubygems/rubygems/commit/6405a1e51a - -commit 5c872b297c11394cc436885400c295f7dccff039 - Author: bronzdoc - Date: 2019-06-22 10:37:09 +0900 - - [rubygems/rubygems] Avoid adding OpenSSL::PKey::RSA instances - - https://github.com/rubygems/rubygems/commit/ba021fb4be - -commit d1c97ceb86bb39d411d88563e17daebe0a764d00 - Author: bronzdoc - Date: 2019-06-22 10:30:37 +0900 - - [rubygems/rubygems] Update expectation in test_to_ruby_with_rsa_key - - https://github.com/rubygems/rubygems/commit/2e65f7d4ae - -commit 2e9c078707b8c87511c9fe45b7057086e214f6fb - Author: bronzdoc - Date: 2019-05-30 11:23:59 +0900 - - [rubygems/rubygems] Fix indentation in case statement - - https://github.com/rubygems/rubygems/commit/8ac0647659 - -commit 8f2379b0c5e182eb6e417431cbdcf2a0edfba71a - Author: bronzdoc - Date: 2019-05-30 11:22:52 +0900 - - [rubygems/rubygems] Make ruby_code method handle OpenSSL::PKey::RSA objects - - https://github.com/rubygems/rubygems/commit/b1d825ab3a - -commit 508afe2c26737e0be60a72faa9d6740a06b0914c - Author: Ellen Marie Dash - Date: 2019-08-17 13:45:09 +0900 - - [rubygems/rubygems] Set SOURCE_DATE_EPOCH env var if not provided. - - Fixes #2290. - - 1. `Gem::Specification.date` returns SOURCE_DATE_EPOCH when defined, - 2. this commit makes RubyGems set it _persistently_ when not provided. - - This combination means that you can build a gem, check the build time, - and use that value to generate a new build -- and then verify they're - the same. - - https://github.com/rubygems/rubygems/commit/d830d53f59 - -commit 8436b2717c458a554dd81456a8e6e030e2c3e038 - Author: Daniel Berger - Date: 2019-07-11 22:20:43 +0900 - - [rubygems/rubygems] Add a gem attr to the Gem::Package class. - - https://github.com/rubygems/rubygems/commit/5b81f364ae - -commit 6ffc045a817fbdf04a6945d3c260b55b0fa1fd1e - Author: Benoit Daloze - Date: 2019-09-08 18:53:27 +0900 - - [EXPERIMENTAL] Make Symbol#to_s return a frozen String - - * Always the same frozen String for a given Symbol. - * Avoids extra allocations whenever calling Symbol#to_s. - * See [Feature #16150] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2437 - -commit 4a4c5028258e53f3395af29655a66bcef796fd73 - Author: Takashi Kokubun - Date: 2019-09-26 12:57:43 +0900 - - Add special runner to benchmark mjit_exec - - I wanted to dynamically generate benchmark cases to test various number - of methods. Thus I added a dedicated runner of benchmark-driver. - -commit 5d8f112505fbc3f9b008ce4ec40fc74f9f623c4a - Author: Takashi Kokubun - Date: 2019-09-26 12:53:41 +0900 - - RubyVM::MJIT.pause(wait: true) should wait - - for all compilations and compaction. - - Prior to this commit, the last-compiled code has not been used because - MJIT worker is stopped before setting the code, and compaction has also - been skipped. - - But it was not intentional and `wait: true` pause should wait until - those two things by its feature. - -commit 47a234954a119c6957e947f5769c55d0b40c6004 - Author: Alan Wu - Date: 2019-09-23 05:09:32 +0900 - - Rename STR_IS_SHARED_M to STR_BORROWED - - Since the introduction of STR_SHARED_ROOT, the word "shared" - has become very overloaded with respect to String's internal - states. Use a different name for STR_IS_SHARED_M and explain - its purpose. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2480 - -commit 93faa011d393bb4b5cf31a0cbb46922f0a5e7cdc - Author: Alan Wu - Date: 2019-09-23 04:36:00 +0900 - - Tag string shared roots to fix use-after-free - - The buffer deduplication codepath in rb_fstring can be used to free the buffer - of shared string roots, which leads to use-after-free. - - Introudce a new flag to tag strings that at one point have been a shared root. - Check for it in rb_fstring to avoid freeing buffers that are shared by - multiple strings. This change is based on nobu's idea in [ruby-core:94838]. - - The included test case test for the sequence of calls to internal functions - that lead to this bug. See attached ticket for Ruby level repros. - - [Bug #16151] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2480 - -commit 3cee99808d629c0ec493955ce8ea019d1f8a637b - Author: Nobuyoshi Nakada - Date: 2019-05-21 10:29:34 +0900 - - [EXPERIMENTAL] Expression with modifier `in` - - [Feature #15865] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2485 - -commit 1fe73dc8609c4bac9e517dc70f602a16dae556cc - Author: Yusuke Endoh - Date: 2019-09-26 11:35:01 +0900 - - include/ruby/ruby.h: suppress a false-positive warning of GCC - - GCC emits a lot of false positives for rb_scan_args because: - - * `rb_scan_args(argc, argv, "*:", NULL, &opts);` makes `n_mand == 0`, - * `n_mand == argc + 1` implies `argc == -1`, and - * `memcpy(ptr, argv, sizeof(VALUE)*argc);` explodes - - However, we know that argc is never so big, thus this is a false - positive. This change suppresses it by adding a condition `n_mand > 0`. - - ``` - In file included from /usr/include/string.h:494, - from ./include/ruby/defines.h:145, - from ./include/ruby/ruby.h:29, - from ./include/ruby/encoding.h:27, - from dir.c:14: - In function 'memcpy', - inlined from 'ruby_nonempty_memcpy.part.0' at ./include/ruby/ruby.h:1763:17, - inlined from 'ruby_nonempty_memcpy' at ./include/ruby/ruby.h:1760:1, - inlined from 'rb_scan_args_set' at ./include/ruby/ruby.h:2594:9, - inlined from 'dir_s_aref' at dir.c:2774:12: - /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:10: warning: '__builtin___memcpy_chk' pointer overflow between offset 0 and size [-8, 9223372036854775807] [-Warray-bounds] - return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest)); - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:10: warning: - '__builtin___memcpy_chk' specified size 18446744073709551608 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=] - ``` - -commit 5357ceb1ca454e2b3c5c173c638054cf705e4752 - Author: Nobuyoshi Nakada - Date: 2019-09-26 09:54:24 +0900 - - [ruby/io-console] Defer creating VT query string - - https://github.com/ruby/io-console/commit/3d69c577a4 - -commit 9b106987050b06e3495e6ec5d3da152557fad8a0 - Author: Nobuyoshi Nakada - Date: 2019-09-26 09:53:16 +0900 - - [ruby/io-console] Added IO#console_mode - - https://github.com/ruby/io-console/commit/77ed8d5a06 - -commit 3b302ea8c95d34d5ef072d7e3b326f28a611e479 - Author: Jeremy Evans - Date: 2019-09-22 01:03:36 +0900 - - Add Module#ruby2_keywords for passing keywords through regular argument splats - - This approach uses a flag bit on the final hash object in the regular splat, - as opposed to a previous approach that used a VM frame flag. The hash flag - approach is less invasive, and handles some cases that the VM frame flag - approach does not, such as saving the argument splat array and splatting it - later: - - ruby2_keywords def foo(*args) - @args = args - bar - end - def bar - baz(*@args) - end - def baz(*args, **kw) - [args, kw] - end - foo(a:1) #=> [[], {a: 1}] - foo({a: 1}, **{}) #=> [[{a: 1}], {}] - - foo({a: 1}) #=> 2.7: [[], {a: 1}] # and warning - foo({a: 1}) #=> 3.0: [[{a: 1}], {}] - - It doesn't handle some cases that the VM frame flag handles, such as when - the final hash object is replaced using Hash#merge, but those cases are - probably less common and are unlikely to properly support keyword - argument separation. - - Use ruby2_keywords to handle argument delegation in the delegate library. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2477 - -commit 80b5a0ff2a7709367178f29d4ebe1c54122b1c27 - Author: Jeremy Evans - Date: 2019-09-26 03:18:49 +0900 - - Make rb_scan_args handle keywords more similar to Ruby methods (#2460) - - Cfuncs that use rb_scan_args with the : entry suffer similar keyword - argument separation issues that Ruby methods suffer if the cfuncs - accept optional or variable arguments. - - This makes the following changes to : handling. - - * Treats as **kw, prompting keyword argument separation warnings - if called with a positional hash. - - * Do not look for an option hash if empty keywords are provided. - For backwards compatibility, treat an empty keyword splat as a empty - mandatory positional hash argument, but emit a a warning, as this - behavior will be removed in Ruby 3. The argument number check - needs to be moved lower so it can correctly handle an empty - positional argument being added. - - * If the last argument is nil and it is necessary to treat it as an option - hash in order to make sure all arguments are processed, continue to - treat the last argument as the option hash. Emit a warning in this case, - as this behavior will be removed in Ruby 3. - - * If splitting the keyword hash into two hashes, issue a warning, as we - will not be splitting hashes in Ruby 3. - - * If the keyword argument is required to fill a mandatory positional - argument, continue to do so, but emit a warning as this behavior will - be going away in Ruby 3. - - * If keyword arguments are provided and the last argument is not a hash, - that indicates something wrong. This can happen if a cfunc is calling - rb_scan_args multiple times, and providing arguments that were not - passed to it from Ruby. Callers need to switch to the new - rb_scan_args_kw function, which allows passing of whether keywords - were provided. - - This commit fixes all warnings caused by the changes above. - - It switches some function calls to *_kw versions with appropriate - kw_splat flags. If delegating arguments, RB_PASS_CALLED_KEYWORDS - is used. If creating new arguments, RB_PASS_KEYWORDS is used if - the last argument is a hash to be treated as keywords. - - In open_key_args in io.c, use rb_scan_args_kw. - In this case, the arguments provided come from another C - function, not Ruby. The last argument may or may not be a hash, - so we can't set keyword argument mode. However, if it is a - hash, we don't want to warn when treating it as keywords. - - In Ruby files, make sure to appropriately use keyword splats - or literal keywords when calling Cfuncs that now issue keyword - argument separation warnings through rb_scan_args. Also, make - sure not to pass nil in place of an option hash. - - Work around Kernel#warn warnings due to problems in the Rubygems - override of the method. There is an open pull request to fix - these issues in Rubygems, but part of the Rubygems tests for - their override fail on ruby-head due to rb_scan_args not - recognizing empty keyword splats, which this commit fixes. - - Implementation wise, adding rb_scan_args_kw is kind of a pain, - because rb_scan_args takes a variable number of arguments. - In order to not duplicate all the code, the function internals need - to be split into two functions taking a va_list, and to avoid passing - in a ton of arguments, a single struct argument is used to handle - the variables previously local to the function. - - Notes: - Merged-By: jeremyevans - -commit 4755e23d2e43a0a16ae70be83097dcae050bc0c8 - Author: git - Date: 2019-09-26 00:27:40 +0900 - - * 2019-09-26 [ci skip] - -commit ae83dbe28d35f43ec60d913fbae5d3a95ae2af05 - Author: Nobuyoshi Nakada - Date: 2019-09-24 09:03:38 +0900 - - Get rid of `IO.select` to fix multiline paste - -commit 5b1fd79ad90899adc71a1f34a722b26ba22a9c8a - Author: Nobuyoshi Nakada - Date: 2019-09-25 20:51:20 +0900 - - [DOC] fixed the return value of IO#ready? [ci skip] - - IO#ready? returns true or false only, since r50262(1baa57b0033). - -commit 6d578164f5da815fb71d23ad186e841359384f25 - Author: Koichi Sasada - Date: 2019-09-25 17:12:55 +0900 - - check `ARY_SHARED_ROOT_P()`. - - ARY_SHARED_ROOT_P(ary) is true, ARY_HEAP_CAPA(ary) should not - be called. - -commit 3deeb3fd914bc5604e84e7a41ec2b5193a560479 - Author: Koichi Sasada - Date: 2019-09-25 16:55:54 +0900 - - introduce `obj_ary_extracapa`. - - Introduce a new debug counter `obj_ary_extracapa` which counts - arrays which are `len < capa`. - -commit 112c9f1430ce495e76aef73221578adc9b240a3b - Author: Nobuyoshi Nakada - Date: 2019-09-25 16:58:24 +0900 - - lldb_inspect: removed unnecessary newline and `end` option - -commit 33c5ad3154099769cec7f77b6d95cbf4b8d52bb0 - Author: Nobuyoshi Nakada - Date: 2019-09-25 13:51:49 +0900 - - Removed idNUMPARAM_0 - -commit 55e1e22b2d44a8a1eca0f6ed2b11dc0f564f7192 - Author: Nobuyoshi Nakada - Date: 2019-09-25 13:01:03 +0900 - - Changed numbered parameters semantics - - * `_1` (and no other numbered parameters) to work as `|x|`. - * giving up `_0`. - - [ruby-core:95074] [Bug #16178] - -commit e663299a5f7a980aae39f3e87cec064ae19a870c - Author: Nobuyoshi Nakada - Date: 2019-09-25 10:14:36 +0900 - - Simplified duplicate code - -commit c99fb0f41e7bb88a4d5891e86bd54def2fca1de4 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-25 09:48:34 +0900 - - Revert "[ruby/io-console] Skip cursor position test on Solaris" - - This reverts commit 5294ded681992ced2ecbd31c814b63265d2f591e. - -commit ca58e834007199929e41fca97f3c103dfbab4bb1 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-25 09:48:02 +0900 - - Do not use of non-standard escape character '\e' - -commit c60451d9cd8ff69095acf826b11ea01557cc9b8b - Author: Nobuyoshi Nakada - Date: 2019-09-25 09:42:35 +0900 - - [ruby/io-console] Unique paths to be added - - https://github.com/ruby/io-console/commit/a3ad851b6c - -commit fc9eb5b9c1b0a6f61735ace45ab39c281a55e8a3 - Author: Nobuyoshi Nakada - Date: 2019-09-25 09:33:10 +0900 - - [ruby/io-console] Load the current libraries - - https://github.com/ruby/io-console/commit/ab7653c543 - -commit 8e8dd88c80e43c0d10857a3394df7cf0fb6e2cb2 - Author: git - Date: 2019-09-25 08:24:44 +0900 - - * 2019-09-25 [ci skip] - -commit 5294ded681992ced2ecbd31c814b63265d2f591e - Author: Nobuyoshi Nakada - Date: 2019-09-25 08:23:18 +0900 - - [ruby/io-console] Skip cursor position test on Solaris - - It results in a mysterious failure. - - https://github.com/ruby/io-console/commit/e3543c3da4 - -commit 0e84eecc1764ec6e2a28654b3e66b8c006f73432 - Author: Nobuyoshi Nakada - Date: 2019-09-24 18:25:32 +0900 - - Make numbered parameters exclusive in a scope - - Notes: - Merged: https://github.com/ruby/ruby/pull/2431 - -commit ea68bb914a3c806a1c5188993b96791a76ab0849 - Author: Nobuyoshi Nakada - Date: 2019-09-04 00:07:50 +0900 - - Changed numbered parameter prefix - - Notes: - Merged: https://github.com/ruby/ruby/pull/2431 - -commit e73cc3eead75b27eabf93a7163bed511f2bb3b17 - Author: Nobuyoshi Nakada - Date: 2019-08-24 02:21:30 +0900 - - Added implicit block parameter - - Notes: - Merged: https://github.com/ruby/ruby/pull/2431 - -commit a1dcb9daa56874ff11e717ad141d36f26e0b9c13 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-24 21:52:23 +0900 - - Rename from ruby-x.y.z.ext.draft to ruby-x.y.z-draft.ext [ci skip] - -commit c5a97d995ae06e0ae420d7529085ae94695c7593 - Author: Nobuyoshi Nakada - Date: 2019-09-24 21:05:29 +0900 - - misc/lldb_cruby.py: update for python3 [ci skip] - - lldb module bundled with Xcode is for Python 3 now. - -commit 052636603377a793dcbd7169d7483a72833d6721 - Author: Nobuyoshi Nakada - Date: 2019-09-24 20:59:47 +0900 - - misc/lldb_cruby.py: removed unused module `commands` [ci skip] - -commit 10e3267c31c4c976d79e00bca484094f1a87dc65 - Author: Nobuyoshi Nakada - Date: 2019-09-24 15:53:58 +0900 - - [ruby/io-console] Made cursor position 0-origin - - https://github.com/ruby/io-console/commit/9377e37295 - -commit 244f7ec204e2b3fd54ca68740587b5be6d9defc4 - Author: Nobuyoshi Nakada - Date: 2019-09-24 15:48:58 +0900 - - [ruby/io-console] Made cursor position consistent with `winsize` - - To be consistent with `winsize`, changed the cursor position - format from `[x, y]` to `[row, column]`. - - https://github.com/ruby/io-console/commit/d1f5ae9286 - -commit 2366c681166a1dab95de6b9ca8ffcaae18aadd39 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-24 11:47:04 +0900 - - suppress meddlesome clang10 warrning - - It says: - - vm.c:2519:34: warning: expression does not compute the number of elements in this array; element type is 'const struct __jmp_buf_tag', not 'VALUE' (aka 'unsigned long') [-Wsizeof-array-div] - sizeof(ec->machine.regs) / sizeof(VALUE)); - ~~~~~~~~~~~~~~~~ ^ - vm.c:2519:34: note: place parentheses around the 'sizeof(VALUE)' expression to silence this warning - -commit 14ba62d4881061a1d54b6204b0c4f0b4811ac921 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-24 11:44:41 +0900 - - refactor delete unused variable - - cadfaacb2533d47d52dbb5dbefe724d7bf11112e missed it. - -commit e561e4a8f390b3e46e45787931f75ee5c237a0c2 - Author: git - Date: 2019-09-24 01:28:48 +0900 - - * 2019-09-24 [ci skip] - -commit 74e33662fe987e5418fc277c8a7ba1f9805f8673 - Author: Jeremy Evans - Date: 2019-09-24 00:44:38 +0900 - - Make public_send and rb_f_send handle keyword argument separation - - Kernel#send takes a different optimized code path that was already - handled. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2481 - -commit 9e4be78ea88f882e1562dbb3eeb24304d0049b8d - Author: Nobuyoshi Nakada - Date: 2019-09-23 19:27:18 +0900 - - [ruby/io-console] Try fallback to stdout when stdin - - https://github.com/ruby/io-console/commit/b8017509ef - -commit 8487193b109ab8cecea74ff383b01b5ecce172c4 - Author: Nobuyoshi Nakada - Date: 2019-09-23 19:22:31 +0900 - - [ruby/io-console] Try to write DSR query to writable IO - - https://github.com/ruby/io-console/commit/a54b6e4dd1 - -commit b443bdbdb997a6b5c0d6f06cada146f523361980 - Author: aycabta - Date: 2019-09-23 17:31:41 +0900 - - Use short wait for select(2) - - It is one of the reasons why paste to IRB is slow. - -commit 934507472c92ccada3f30be183fea5066427efda - Author: aycabta - Date: 2019-09-23 17:26:38 +0900 - - Retrieve key-buffer that was supposed to lose - -commit 142efba93e91209a7f336863974d4c84a969e2a3 - Author: Nobuyoshi Nakada - Date: 2019-09-23 02:20:43 +0900 - - Adjusted directives order of a function [ci skip] - -commit cadfaacb2533d47d52dbb5dbefe724d7bf11112e - Author: Lourens Naudé - Date: 2019-07-20 10:42:10 +0900 - - Lazy init thread local storage - - Notes: - Merged: https://github.com/ruby/ruby/pull/2295 - -commit 642dbb962cafc39e9e44eef212435e50a01190ec - Author: Nobuyoshi Nakada - Date: 2019-09-23 01:25:17 +0900 - - make-snapshot: store timestamps in UTC for zip which lacks timezone - -commit 2afe86e4bedeffd65c8e5cbbf08b0cce76669d40 - Author: git - Date: 2019-09-23 01:04:25 +0900 - - * 2019-09-23 [ci skip] - -commit d8221a54f2c5729573ddb03cb51d638ae74cc876 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-23 00:55:48 +0900 - - Add `-mtc=off` to `7z` not to store NTFS timestamps - - https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm - -commit b0d24e262f2ca3ba4f8d3f60248d30209b0a39a2 - Author: Nobuyoshi Nakada - Date: 2019-09-22 22:26:07 +0900 - - make-snapshot: Added -no7z option - - It disables 7z, which seems not to have an option to stop saving - extra file attributes (uid/gid and atime), in order to make zip - packages stable. - -commit 7fe7dec7e5f7cefae986fe6475805198ec4dbada - Author: Nobuyoshi Nakada - Date: 2019-09-22 21:56:58 +0900 - - make-snapshot: Do not save extra file attributes - - Extra file attributes (uid/gid and atime) make the packaged zip - file unstable. - -commit 5f35b8ca30cba69968d4d0c885a4bf5c48b03e17 - Author: Yusuke Endoh - Date: 2019-09-22 22:12:18 +0900 - - st.c: Use rb_st_* prefix instead of st_* (#2479) - - The original st.c was public domain hash table implementation, but - Ruby's st.c is highly modified, and its data structure is not - compatiblie with the original one. - - Therefore, when creating an extension library to wrap C code that uses - the original st.c, the symbols conflict, which leads to segfault. - - This changes the prefix `st_*` of st.c functions to `rb_st_*` for - reflecting that they are specific to Ruby's, and avoid symbol conflicts. - - Notes: - Merged-By: mame - -commit 2272efa4632a845ead37377a22ad9e24b45ebf27 - Author: Yusuke Endoh - Date: 2019-09-22 16:35:50 +0900 - - st.c (st_add_direct_with_hash): make it "static inline" - - It was originally static inline, but seemed to be accidentally published - at 8f675cdd00e2c5b5a0f143f5e508dbbafdb20ccd. - -commit 28eefb33c8d27e5711319873d065e5414d7ffe25 - Author: Yusuke Endoh - Date: 2019-09-22 16:21:26 +0900 - - variable.c: Rename rb_st_copy to rb_iv_tbl_copy - - This function was created as a variant of st_copy with firing write - barrier. - It should have more explicit name, such as st_copy_with_write_barrier. - But because it is used only for copying iv_tbl, so I rename it to - rb_iv_tbl_copy now. If we face other use case than iv_tbl, we may want - to rename it to more general name. - -commit b4c328bebcf45b7a983f7e5ce29ba6ec57ed1a1a - Author: Yusuke Endoh - Date: 2019-09-22 11:55:00 +0900 - - test/bigdecimal/test_bigdecimal.rb: Use BigDecimal() - - instead of deprecated BigDecimal.new. - -commit a0ce0b6297852f64f6a05593e1364619da7a831d - Author: Kazuhiro NISHIYAMA - Date: 2019-09-22 10:11:06 +0900 - - Add `if: always()` because 2.4.x's `make check` failed on snapshot [ci skip] - - `check-snapshot-ruby_2_4` uses `make test` instead of `make check`. - https://github.com/ruby/actions/blob/95692e54f4263501db1508d51c1fb67c03b4f575/.github/workflows/snapshot.yml#L448-L449 - - `draft-release` use `make check` to make it simple, and - actions is required regardless of success or failure. - - On the other hand, snapshot success can be ignored, - so normally it should not fail. - -commit c020fd6aa8a356b1ae9d3db5b99c7e29a1fddae0 - Author: git - Date: 2019-09-22 08:10:56 +0900 - - * 2019-09-22 [ci skip] - -commit 2e551356a7a6e74ba07283e000ff16f5d1ea6506 - Author: Jeremy Evans - Date: 2019-08-08 01:01:33 +0900 - - Make Kernel#{Pathname,BigDecimal,Complex} return argument if given correct type - - This is how Kernel#{Array,String,Float,Integer,Hash,Rational} work. - BigDecimal and Complex instances are always frozen, so this should - not cause backwards compatibility issues for those. Pathname - instances are not frozen, so potentially this could cause backwards - compatibility issues by not returning a new object. - - Based on a patch from Joshua Ballanco, some minor changes by me. - - Fixes [Bug #7522] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2473 - -commit 7470f965650bf17875632f0c5f9e5a4d9de9fc3f - Author: Jeremy Evans - Date: 2019-08-10 08:44:43 +0900 - - Fix Module#class_variables for singleton classes of classes/modules - - Module#class_variables should reflect class variable lookup. For - singleton classes of classes/modules, this means the lookup should - be: - - * Singleton Class - * Class - * All Ancestors of Class - - Note that this doesn't include modules included in the singleton - class, because class variable lookup doesn't include those. - - Singleton classes of other objects do not have this behavior and - always just search all ancestors of the singleton class, so do not - change the behavior for them. - - Fixes [Bug #8297] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2478 - -commit 5cb283217b713605c6bddc527f96bbc773fd1fb9 - Author: Yusuke Endoh - Date: 2019-09-21 19:23:47 +0900 - - test/ruby/test_assignment.rb: use bug number for assert message - - to suppress variable unused warning - -commit b4149993709169b9a67373095593da385e7d48e5 - Author: Takashi Kokubun - Date: 2019-09-21 16:09:45 +0900 - - Add a benchmark for JIT-ed code dispatch - -commit e006b992c29decb01865b0749e35a4cfc872bdaf - Author: Fangrui Song - Date: 2019-09-19 16:04:29 +0900 - - typedef rb_jmpbuf_t to void *[5] if __builtin_setjmp is used - - The built-in version operates on a buffer of 5 words, much smaller than - the size of jmp_buf defined in libc. - Note, powerpc requires 5 words, while arm and x86_64 just require 3. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2471 - -commit 27144de2bd95c5886c3d4400c3b8aea932b856f1 - Author: Jeremy Evans - Date: 2019-09-21 04:18:07 +0900 - - Fix documentation for ENV.each to return ENV - - Also have spec check that it returns ENV. - - Mostly from burdettelamar@yahoo.com (Burdette Lamar). - - Fixes [Bug #16164] - -commit 7aeacb213bdf40bab4393448023930eac35d127a - Author: Nobuyoshi Nakada - Date: 2019-09-21 01:57:15 +0900 - - Revert eval.c in e81a3e6df54842b5a836dad7055a4295cf4155bc - - Inadvertently merged change to suppress warnings by gcc 9.2. - Pointed out by Alan Wu. - -commit 990e714fd3f4e9b28e007ff1bd2bcf4217269776 - Author: git - Date: 2019-09-21 00:48:46 +0900 - - * 2019-09-21 [ci skip] - -commit daa4ad8ed7f73e8d5e2a2047fe92e5fe08227627 - Author: Nobuyoshi Nakada - Date: 2019-09-21 00:48:24 +0900 - - Disable method definition type checks on Windows - -commit fe1e623faea75952f27baa949a7468021443c12a - Author: Nobuyoshi Nakada - Date: 2019-09-20 23:25:18 +0900 - - Fixed format specifiers - - Use PRIdPTRDIFF for the platforms where a pointer is larger than a long. - -commit e47b111627d5c68b8900f57364fecd51cbcd0268 - Author: Jeremy Evans - Date: 2019-09-19 07:30:59 +0900 - - Call rb_vm_call_kw instead of rb_vm_call0 in a few cases - - rb_vm_call_kw handles the tmp buffer for you. - - Also, change method_missing so it also calls rb_vm_call_kw to - handle the kw_splat flag, instead of requiring callers to handle - kw_splat flag before calling method_missing. This may fix other - cases where method_missing is currently called without the kw_splat - being handled. - -commit c9f2b790adcff8df48e3192d18ee8afa02f5530c - Author: Jeremy Evans - Date: 2019-09-19 04:59:01 +0900 - - Handle keyword argument separation for Enumerator#size - - When Object#to_enum is passed a block, the block is called to get - a size with the arguments given to to_enum. This calls the block - with the same keyword flag as to_enum is called with. - - This requires adding rb_check_funcall_kw and - rb_check_funcall_default_kw to handle keyword flags. - -commit 27b67468724dc48ed8305d8cb33484a4af98fc05 - Author: Jeremy Evans - Date: 2019-09-19 04:08:14 +0900 - - Make passing empty keywords to dig pass empty keywords to next dig method - - If defined in Ruby, dig would be defined as def dig(arg, *rest) end, - it would not use keywords. If the last dig argument was an empty - hash, it could be treated as keyword arguments by the next dig - method. Allow dig to pass along the empty keyword flag if called - with an empty keyword, to suppress the previous behavior and force - treating the hash as a positional argument and not keywords. - - Also handle the case where dig calls method_missing, passing the - empty keyword flag to that as well. - - This requires adding rb_check_funcall_with_hook_kw functions, so - that dig can specify how arguments are treated. It also adds - kw_splat arguments to a couple static functions. - -commit e81a3e6df54842b5a836dad7055a4295cf4155bc - Author: Nobuyoshi Nakada - Date: 2019-09-20 22:03:37 +0900 - - Allows calling a private method only with bare `self` - -commit 9e171b1fa0b4e2e5b0bf82da11b4b511c602c336 - Author: Takashi Kokubun - Date: 2019-09-20 21:50:00 +0900 - - Fix wrong allocation failure handling - - `iseq->body->jit_unit->compile_info` should not be referenced before - the null check of `iseq->body->jit_unit`. - -commit 6e0dd3e7c1786e33c3193d0b4dd9579655c4e842 - Author: Takashi Kokubun - Date: 2019-09-20 21:06:07 +0900 - - Use RUBY_VM_NEXT_CONTROL_FRAME macro - - in vm_push_frame and limit scope of i. - Just a minor maintainability improvement. - -commit 740a98fe108305324a66edb16f0acb8521a53da7 - Author: Nobuyoshi Nakada - Date: 2019-09-20 19:03:43 +0900 - - Fix for explicit cast without RUBY_METHOD_FUNC - -commit cb1f9fe9184c67f9a99f6a9702559293613b7e80 - Author: Nobuyoshi Nakada - Date: 2019-09-20 16:48:42 +0900 - - Check various method definitions in C++ - -commit 4ffcadd39cb7061ff501478ed436a56e7f99f3dc - Author: Takashi Kokubun - Date: 2019-09-20 17:44:16 +0900 - - Fix rb_define_singleton_method warning - - for debug counters - - ``` - ../include/ruby/intern.h:1175:137: warning: passing argument 3 of 'rb_define_singleton_method0' from incompatible pointer type [-Wincompatible-pointer-types] - #define rb_define_singleton_method(klass, mid, func, arity) rb_define_singleton_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); - ^ - ../vm.c:2958:5: note: in expansion of macro 'rb_define_singleton_method' - rb_define_singleton_method(rb_cRubyVM, "show_debug_counters", rb_debug_counter_show, 0); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - ../include/ruby/intern.h:1139:99: note: expected 'VALUE (*)(VALUE) {aka long unsigned int (*)(long unsigned int)}' but argument is of type 'VALUE (*)(void) {aka long unsigned int (*)(void)}' - __attribute__((__unused__,__weakref__("rb_define_singleton_method"),__nonnull__(2,3)))static void rb_define_singleton_method0 (VALUE,const char*,VALUE(*)(VALUE),int); - ``` - -commit 04c53a1d03130b5cd4a1eea35cab92003a4d0909 - Author: Nobuyoshi Nakada - Date: 2019-09-20 17:05:52 +0900 - - Get rid of embedding make command line - - NMAKE sets MAKE to the full path name, which includes spaces by - the default installation. - -commit d56a3c063532906158cc0427a42133fadda75cde - Author: Nobuyoshi Nakada - Date: 2019-09-20 16:55:16 +0900 - - Fixed cxxanyargs/depend - - * Removed excess backslashes - * Fixed the target name to try failure.cpp - -commit 26831719948f4ab6fdffdfcd8083be23aa300436 - Author: Nobuyoshi Nakada - Date: 2019-09-20 15:50:42 +0900 - - [DOC] DOT is not a part of a receiver [ci skip] - - [Feature #11297] [Feature #16123] - -commit 1de242de0fdec873eb5138ebdf09eaf0f6297967 - Author: Hiroshi SHIBATA - Date: 2019-09-20 14:22:32 +0900 - - Fixed up 37c083942509dd7e0d8b7ccd3575936a2017c400 - -commit 9d25c652a98f0a5bc552f81846c6dc975dc2f307 - Author: Hiroshi SHIBATA - Date: 2019-09-20 14:21:04 +0900 - - Removed ThreadsWait from the ruby repository - -commit 37c083942509dd7e0d8b7ccd3575936a2017c400 - Author: Hiroshi SHIBATA - Date: 2019-09-20 14:06:22 +0900 - - Removed Synchronizer from the ruby repository. - -commit 3b56a0934fa503b518e8302ed32f9124740d896b - Author: Hiroshi SHIBATA - Date: 2019-09-20 12:56:18 +0900 - - Removed Shell from the ruby repository. - -commit 67a6662032d0a7c4af07f44c2046cd0ed2d7d253 - Author: Hiroshi SHIBATA - Date: 2019-09-20 12:42:53 +0900 - - Removed Scanf from the ruby repository. - -commit a3b85016149f4f73f08c739626b2f02badd5ad17 - Author: Hiroshi SHIBATA - Date: 2019-09-20 12:12:37 +0900 - - Removed CMath from the ruby repository. - -commit 422ae594d97e803e829e65716e85483f5942e0c3 - Author: Nobuyoshi Nakada - Date: 2019-09-20 10:29:24 +0900 - - Fixed memory leak - - * array.c (flatten): fix a memory leak in the case of an exception - at conversion of an element to Array. - -commit 45bac6284595834b68a34f4f4efe5880436fce11 - Author: Nobuyoshi Nakada - Date: 2019-09-20 09:31:55 +0900 - - Added the target to run a benchmark - -commit d3c6fe65e3ce017e62deaca7344fa90adfb314a9 - Author: Nobuyoshi Nakada - Date: 2019-09-20 09:25:30 +0900 - - Fixed a variable in checkout-github-% - -commit b80df6e8e0a59207545822d92c0a4f78cd64ef5e - Author: Nobuyoshi Nakada - Date: 2019-09-20 02:32:50 +0900 - - Update NEWS and documents [ci skip] - - [Feature #11297] [Feature #16123] - -commit e6378cdcd8246697be652b74442f9c07503e0ba6 - Author: Nobuyoshi Nakada - Date: 2019-09-20 02:17:58 +0900 - - Allow calling a private accessor with `self.` - - [Feature #11297] [Feature #16123] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2474 - -commit d583df525922ca14ecfab7a39f0c617eb86bc804 - Author: Nobuyoshi Nakada - Date: 2019-09-20 02:16:17 +0900 - - Added version guard - - [Feature #11297] [Feature #16123] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2474 - -commit 7fbd2f7cc247ee66e877ab3c88f0274834c6b6c7 - Author: Dylan Thacker-Smith - Date: 2019-07-02 23:06:54 +0900 - - Allow calling a private method with `self.` - - This makes it consistent with calling private attribute assignment - methods, which currently is allowed (e.g. `self.value =`). - - Calling a private method in this way can be useful when trying to - assign the return value to a local variable with the same name. - - [Feature #11297] [Feature #16123] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2474 - -commit 17a13663998a98ff75fcc838d1cea95c879fbb88 - Author: Nobuyoshi Nakada - Date: 2019-09-18 22:52:41 +0900 - - Overload variable definition functions - - Define overloading functions of rb_define_virtual_variable and - rb_define_hooked_variable, for combinations with and without - ANYARGS casts. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2461 - -commit 9c0d5e51cb3726455560c34ad595ab82f651da48 - Author: Nobuyoshi Nakada - Date: 2019-09-15 23:28:26 +0900 - - Check method functions in C++ - - By using template and overloading, instead of transparent union. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2461 - -commit 5e3771aad4228ac18cec7be4ccb93866c81744fa - Author: git - Date: 2019-09-20 00:20:35 +0900 - - * 2019-09-20 [ci skip] - -commit e13b09c450eb4ffc0ffc86d479e5b0c75599ad9c - Author: Nobuyoshi Nakada - Date: 2019-09-19 23:45:09 +0900 - - Use EXPECT_NODE_NONULL - -commit 82f25404ffe2ad910ac61e436f02cad312755b2f - Author: Nobuyoshi Nakada - Date: 2019-09-19 23:44:37 +0900 - - Check COMPILE_RECV result - -commit e0c56b45a41f052223e23d222ca49c7e0225923e - Author: Nobuyoshi Nakada - Date: 2019-09-19 22:09:43 +0900 - - Moved unmatch arity check to depend file - - To substitute suffixes and VPATH for nmake. - -commit a3daf8e49a36dc5501b020a882d611676a6ad264 - Author: Nobuyoshi Nakada - Date: 2019-09-19 20:07:24 +0900 - - Ensure that unmatched arity fails in C++ - -commit b3ddeac33e299f36084339aceaaa0a29cf8b7498 - Author: Nobuyoshi Nakada - Date: 2019-09-19 20:31:15 +0900 - - Revert "DEBUG: dump mkmf.log" - - This reverts commit 69e209a3450bd6b281dcad1d96a34e9cab184845. - - The debug has finishted. - -commit cbf405fec4ea3c93640b0b7072cf6205442100e5 - Author: NARUSE, Yui - Date: 2019-09-19 20:45:24 +0900 - - Specify encoding explicitly for sprintf - -commit 5208c431bef3240eb251f5da23723b324431a98e - Author: NARUSE, Yui - Date: 2019-09-19 19:49:12 +0900 - - Separate Time#inspect from to_s and show subsec [Feature #15958] - -commit 2698f13a1f0cc07ef97b7f20502c420b51e9c57d - Author: Nobuyoshi Nakada - Date: 2019-09-19 19:40:44 +0900 - - Fixed reserved numbered parameter warning - -commit 6180f1fede487bf5dfdd00cbae2ee7f2b4613a7e - Author: Nobuyoshi Nakada - Date: 2019-09-19 19:06:18 +0900 - - Added link_command for C++ - -commit 6045ff64e3c310cd24f5e49e088610249d4cf24f - Author: Takashi Kokubun - Date: 2019-09-19 18:04:46 +0900 - - Use benchmark-driver v0.15.6 - - to fix another keyword argument warning which was added recently. - -commit 20baa08d652b844806fab424a2a590408ab613ef - Author: NagayamaRyoga <38316184+NagayamaRyoga@users.noreply.github.com> - Date: 2019-09-19 17:35:32 +0900 - - Improve the output of `RubyVM::InstructionSequence#to_binary` (#2450) - - The output of RubyVM::InstructionSequence#to_binary is extremely large. - We have reduced the output of #to_binary by more than 70%. - - The execution speed of RubyVM::InstructionSequence.load_from_binary is about 7% slower, but when reading a binary from a file, it may be faster than the master. - - Since Bootsnap gem uses #to_binary, this proposal reduces the compilation cache size of Rails projects to about 1/4. - - See details: [Feature #16163] - -commit f84efe4b9da8e16b0986b75ca24352639bc502ec - Author: Takashi Kokubun - Date: 2019-09-19 17:30:31 +0900 - - Avoid unneeded casts in INSN_ENTRY_SIG - -commit 7202bf9ed899677f43a01ecf9f671082268d2d88 - Author: Takashi Kokubun - Date: 2019-09-19 17:19:21 +0900 - - Drop PREFETCH macro unused since 6b534134a7 - -commit fcfe36b7332a29fd6835ba65984448477acc5bcc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-19 10:37:30 +0900 - - fix spec failure - - See also https://travis-ci.org/ruby/ruby/jobs/586452224 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2468 - -commit d74fa8e55ce64904f2f99dfef4cbdff94e290672 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-18 17:18:48 +0900 - - reuse cc->call - - I noticed that in case of cache misshit, re-calculated cc->me can - be the same method entry than the pevious one. That is an okay - situation but can't we partially reuse the cache, because cc->call - should still be valid then? - - One thing that has to be special-cased is when the method entry - gets amended by some refinements. That happens behind-the-scene - of call cache mechanism. We have to check if cc->me->def points to - the previously saved one. - - Calculating ------------------------------------- - trunk ours - vm2_poly_same_method 1.534M 2.025M i/s - 6.000M times in 3.910203s 2.962752s - - Comparison: - vm2_poly_same_method - ours: 2025143.9 i/s - trunk: 1534447.2 i/s - 1.32x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/2468 - -commit 9fb9f2d318520ddfdbe73809eea85847550b42ae - Author: Kazuhiro NISHIYAMA - Date: 2019-09-19 12:39:52 +0900 - - Add draft-release.yml [ci skip] - - Make draft release packages. (Release packages are official after tests and release announce.) - - - Copy from ruby/actions - - Change trigger tags from `draft/v*` to `v*` (I use `draft/v*` on ruby/actions because I want to avoid to cause trouble with shell history on working directory of ruby/ruby.) - - Change secrets names because secrets are repository local and use different names between ruby/ruby and ruby/actions. - -commit e2aac6a611f4924e4bed2a38e063d65c731aa33a - Author: Nobuyoshi Nakada - Date: 2019-09-19 12:25:34 +0900 - - Separate @have_devel for C++ - -commit df3fd5071742397c7c5b908d0632f17aa79c2b51 - Author: Nobuyoshi Nakada - Date: 2019-09-19 12:23:55 +0900 - - Removed mkmf.log dump in Makefile - -commit 66c644da5e80258bb3217941223d923f923c3548 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-19 12:15:53 +0900 - - refactor reuse existing on-stack structs - - rb_vm_call0 allocates its own struct call_info etc. But they are - already there in case of rb_funcallv_with_cc. Let's just pass the - existing ones, instead of re-creation. - -commit 69e209a3450bd6b281dcad1d96a34e9cab184845 - Author: Nobuyoshi Nakada - Date: 2019-09-19 12:03:58 +0900 - - DEBUG: dump mkmf.log - -commit 2d1e3bd8f1448ef55d3e1bda8dc0855ae995d659 - Author: Nobuyoshi Nakada - Date: 2019-09-19 11:25:09 +0900 - - DEBUG: cxxanyargs - -commit a98181eb11ab3d0a643a5fb50e731c3fe50960d9 - Author: Nobuyoshi Nakada - Date: 2019-09-19 10:46:52 +0900 - - DEBUG: cxxanyargs - -commit 70fd022a2ae03d237ee9045db9834f253f3d843f - Author: Nobuyoshi Nakada - Date: 2019-09-19 09:47:11 +0900 - - DEBUG - -commit a9cdaaada4ade22f2f85fbc1f8bd41a8579528b0 - Author: Nobuyoshi Nakada - Date: 2019-09-19 08:46:49 +0900 - - DEBUG - -commit 5177dd8ba081dd25bf8ceb0f1c861ea8f83884c3 - Author: Jeremy Evans - Date: 2019-09-19 03:16:00 +0900 - - Add and fix some keyword tests - - Replace [arg=1, args] with [arg, args] so we can actually test - the value correctly. - - Add some missing tests for **h3 when method accepts (**args). - - Add tests for passing positional hashes to (**args) methods and - check for the expected warnings/errors. - -commit 2b708ab7238fc1f904f66d9a3999ca1c8ae165fe - Author: git - Date: 2019-09-19 00:11:31 +0900 - - * 2019-09-19 [ci skip] - -commit 842f600a93deca71e908ef5bb16e4e6aed519890 - Author: Nobuyoshi Nakada - Date: 2019-09-18 23:31:53 +0900 - - Look up the language module - - Look up language module with `MakeMakefile.[]`, instead of a - accessing constant under that module directly, to get rid of - expose the constant to the toplevel inadvertently. - -commit 15d5de59fb089eb47ca18dd4a7296fa2e7e73709 - Author: Nobuyoshi Nakada - Date: 2019-09-19 00:02:34 +0900 - - Removed unused keyword argument [ci skip] - -commit f9d0778fca8fd9ff0243062726ed4a6186da1cde - Author: Nobuyoshi Nakada - Date: 2019-09-18 22:51:56 +0900 - - Removed MakeMakefile::C - - It is exposed to the topleven namespace via included MakeMakefile. - -commit 9bd77d7cf3d817fab24b1a10550eae6abb2e341d - Author: Nobuyoshi Nakada - Date: 2019-09-18 19:25:58 +0900 - - Removed a debug print [ci skip] - -commit a491159a6e91976b026f8c968549acd1288d3af2 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-18 22:45:34 +0900 - - Add badges of GitHub Actions [ci skip] - -commit 38069a3a55325757d2bba84191b006361a284cb0 - Author: Takashi Kokubun - Date: 2019-09-18 18:54:07 +0900 - - Try using Ruby 1.9.3 on Travis xenial - - Isn't it there? http://rubies.travis-ci.org/ - - Notes: - Merged: https://github.com/ruby/ruby/pull/2469 - -commit c3f03da4944241f46233ce159068f35c5bd5f9b2 - Author: Nobuyoshi Nakada - Date: 2019-09-18 15:38:24 +0900 - - [EXPERIMENTAL] MakeMakefile::CXX for C++ - -commit 7d354175d7dcabc317030194f503d69a8a7892f5 - Author: Hiroshi SHIBATA - Date: 2019-09-18 17:39:51 +0900 - - Fixed up ccbfb054b1dcd06d30924c4a83af1bac75d78c31 - -commit ba86353446f6c1ce9b2c95d03bf16cfed3a532d2 - Author: Hiroshi SHIBATA - Date: 2019-09-18 15:28:08 +0900 - - Update the latest documentation of bundler - -commit 2da8574930f14950ce78892fe65f383fcaf8a71b - Author: Hiroshi SHIBATA - Date: 2019-09-18 15:05:38 +0900 - - Fixed the rubocop warnings - -commit effacde2c0104935fd7258eac77f17684f724cd0 - Author: David Rodríguez - Date: 2019-08-16 21:30:39 +0900 - - [bundler/bundler] Merge all `bundle check --path` specs - - And skip them all for bundler 3. - - https://github.com/bundler/bundler/commit/b88936cdc2 - -commit 434af7303ceed8ee5318a31eb7da02b0ed557965 - Author: Bundlerbot - Date: 2019-09-05 01:20:09 +0900 - - [bundler/bundler] Merge #7340 - - 7340: Fix bundle clean issue r=deivid-rodriguez a=deivid-rodriguez - - ### What was the end-user problem that led to this PR? - - The problem was that `bundle clean` is crashing under some conditions. - - ### What was your diagnosis of the problem? - - My diagnosis was that sometimes (when the bundle includes git sourced gems with extensions), it assumes that some paths exist, but they don't. - - ### What is your fix for the problem, implemented in this PR? - - My fix is to ignore those paths. - - ### Why did you choose this fix out of the possible options? - - I chose this fix because it fixes the issue. - - Fixes #7338. - - Co-authored-by: David Rodríguez - (cherry picked from commit b007fde67c77c1f15f13b97eda186644c2a2be04) - - https://github.com/bundler/bundler/commit/3766053507 - -commit e6ad9452b6cf1cf118ead0cbd0cf86e2c0fb61e0 - Author: David Rodríguez - Date: 2019-08-16 19:07:55 +0900 - - [bundler/bundler] Fix remembered flag deprecation message - - It was suggested a deprecated command as a fix. - - https://github.com/bundler/bundler/commit/e330a9a34f - -commit 1cb8cf5df0b2a7dbf8b1d616ac5268d76140aab6 - Author: David Rodríguez - Date: 2019-09-15 16:42:48 +0900 - - [bundler/bundler] Version 2.1.0.pre.2 - - https://github.com/bundler/bundler/commit/6e9774b377 - -commit 4f2f6aeb5fa65a10c633d92fcdd1980d42a6d745 - Author: Samuel Giddins - Date: 2017-10-21 03:55:04 +0900 - - [bundler/bundler] Add a spec for installing git deps after packaging w/o git - - https://github.com/bundler/bundler/commit/65351c58b8 - -commit 0c6529bac2c38c536567e443b7da851144e84be8 - Author: David Rodríguez - Date: 2019-08-22 03:53:36 +0900 - - [bundler/bundler] Revert "Add all platforms to lockfile by default" - - This reverts commit 3dc509e645abb497e4dc92a7c42be471ff87db0b. - - https://github.com/bundler/bundler/commit/b5766564fb - -commit 6f16ededdd5eed8bab9e4f4cb70032a151fbc405 - Author: David Rodríguez - Date: 2019-08-22 03:52:35 +0900 - - [bundler/bundler] Revert "Remove now meaningless warning" - - This reverts commit 00b095b98fe4bd44950beaf3bc9f1d91eac7b69e. - - https://github.com/bundler/bundler/commit/e93bce3b20 - -commit f18d88b5356d347304245c703329b82293f56efc - Author: David Rodríguez - Date: 2019-08-22 03:52:25 +0900 - - [bundler/bundler] Revert "Remove now meaningless setting" - - This reverts commit 52c5a0eedec34b5d86464b3cf135dc2002486f1d. - - https://github.com/bundler/bundler/commit/b4cc36deb9 - -commit 399501cdfe957325631e70efa6afffca6b56db6e - Author: David Rodríguez - Date: 2019-08-22 03:52:17 +0900 - - [bundler/bundler] Revert "Remove now unused method" - - This reverts commit 3a2d2f025081755bdb38af660897e7b2f749a33a. - - https://github.com/bundler/bundler/commit/13cef81582 - -commit c27aaf1a8f6f4240dadeaa9b203cce640b56e3db - Author: Takayuki Nakata - Date: 2019-08-21 23:46:46 +0900 - - [bundler/bundler] Fix comments and messages to refer to https url - - https://github.com/bundler/bundler/commit/a86b49f1b9 - -commit b9996803f7278f3a6d30360f1b7220070a9208d3 - Author: David Rodríguez - Date: 2019-08-16 21:25:37 +0900 - - [bundler/bundler] Remove duplicated spec filter - - https://github.com/bundler/bundler/commit/b7fc6f4187 - -commit c92e098781470c84a497a1d430f425aca897f895 - Author: David Rodríguez - Date: 2019-08-16 18:59:39 +0900 - - [bundler/bundler] Fix --path option descriptions - - To not mention that the flag is remembered when it's not. - - https://github.com/bundler/bundler/commit/82f0b95854 - -commit a29ead52e169cf702a61ba91cdf301a3bd87d713 - Author: David Rodríguez - Date: 2019-08-16 19:08:22 +0900 - - [bundler/bundler] Deprecate `--path` flag to `bundle check` - - https://github.com/bundler/bundler/commit/0a0e7cf5ec - -commit 9118cb242b141c380a0180f64ffeb0c9fdae0c8b - Author: Kenichi Kamiya - Date: 2019-09-18 17:24:24 +0900 - - Fix typos - - Notes: - Merged: https://github.com/ruby/ruby/pull/2467 - -commit bcd5f2e9d30d2bb34912e56b2e766ae952dd12dc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-18 11:06:24 +0900 - - delete unused variable - -commit c170e23d8118edba08981fd1c5d7f03652b543a4 - Author: git - Date: 2019-09-18 08:23:06 +0900 - - * 2019-09-18 [ci skip] - -commit 775365cbd2bf17195e694771fc1c15698273a640 - Author: Jeremy Evans - Date: 2019-09-18 06:32:19 +0900 - - Fix keyword argument separation issues with sym procs when using refinements - - Make sure that vm_yield_with_cfunc can correctly set the empty keyword - flag by passing 2 as the kw_splat value when calling it in - vm_invoke_ifunc_block. Make sure calling.kw_splat is set to 1 and not - 128 in vm_sendish, so we can safely check for different kw_splat values. - - vm_args.c needs to call add_empty_keyword, and to make JIT happy, the - function needs to be exported. Rename the function to - rb_adjust_argv_kw_splat to more accurately reflect what it does, and - mark it as MJIT exported. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2462 - -commit 9b35dc38644c10eed008f9ba19a7224f2fb49af2 - Author: Jeremy Evans - Date: 2019-09-17 05:19:06 +0900 - - Pass keyword argument flag when rb_call_super_kw calls method_missing - - This makes method_missing take a flag for whether keyword arguments - were passed. - - Adds tests both for rb_call_super_kw usage as well as general usage - of super calling method_missing in Ruby methods. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2462 - -commit 0785469a400b00eb4576fedbf93b614c70eaf760 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-17 16:59:47 +0900 - - `brew install` may fail, so try to use `tool/travis_retry.sh` - - https://github.com/ruby/ruby/runs/224877570#step:3:1008 - ``` - Error: No such file or directory @ dir_s_rmdir - /Users/runner/Library/Caches/Homebrew/downloads/ca756e367eb98d2b525e72b311633c27ffc74eca825a5392153b3488d1adb732--libssh2-1.9.0.mojave.bottle.tar.gz - ``` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2464 - -commit 68ffb679d461722da6ef0bcdb2f18d8929d98204 - Author: Nobuyoshi Nakada - Date: 2019-09-14 00:41:04 +0900 - - Undefine DSUSP key - - Enable `Ctrl+Y`, which is bound with it by default on BSD-like - systems, for editing. - -commit b49c1380c10bc3c13814a818a6c860f0f82bba79 - Author: git - Date: 2019-09-17 15:15:43 +0900 - - * 2019-09-17 [ci skip] - -commit f9332ad8333bffd9a0d34d5c5e10a2f7323cbde5 - Author: Adam Cammack - Date: 2019-09-14 01:03:34 +0900 - - Fix previous history in vi_insert mode - -commit a3533bc90493cf84e6c9d6cc0356bbbd694cd6da - Author: Adam Cammack - Date: 2019-09-08 05:56:29 +0900 - - Fix history navigation in vi_insert mode - -commit 3bb1162cacf951794af7c9124dde002ceaed5b38 - Author: Nobuyoshi Nakada - Date: 2019-09-16 20:01:42 +0900 - - Folded files in gemspec - -commit 2a39de193cc1e40b2e73cdbd24df280cb81638dd - Author: git - Date: 2019-09-16 21:37:37 +0900 - - * 2019-09-16 [ci skip] - -commit 70f57287cfaab470b6e24c6bbc47c7e3890ec7e5 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-16 21:35:38 +0900 - - Fix a typo [ci skip] - -commit 4a403e3f9850901eaeaf3a261bf810bc18516ca6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-15 23:19:01 +0900 - - oops [ci skip] - - Fixing typo. It seems I failed to press the shift key. - -commit 3a3f48fb8fbdbb810d9b675159529970015316b9 - Author: Nobuyoshi Nakada - Date: 2019-09-15 23:12:24 +0900 - - Comment lines can be placed between fluent dot now - -commit 751d4ab9c2382d60868446cc69fdac0a9f6cdf4a - Author: Nobuyoshi Nakada - Date: 2019-07-27 13:56:54 +0900 - - Refine Timezone fixture - -commit 6cad0644248d5acbaf3a2e8de4ff6d88b3dd2cb4 - Author: Nobuyoshi Nakada - Date: 2019-09-15 16:23:33 +0900 - - Try to fetch commits notes to the source tree automatically - - [Bug #16167] - -commit 44d594189aa2b1365b9b765cb272906b9561cc1d - Author: Nobuyoshi Nakada - Date: 2019-09-15 13:29:12 +0900 - - rb_scan_args_count_lead: use arguments instead of magic numbers - -commit 585b15d75df525054cf46b79baf16498472a0e65 - Author: Nobuyoshi Nakada - Date: 2019-09-15 03:21:41 +0900 - - make-snapshot: no merge commits in ChangeLog - - Parents commit hashes in logs of merge commits are abbreviated to - necessary length depending on the repositories. Exclude merge - commits from ChangeLog to make it stable. - -commit df4a4bd88c98a0b966d88ae825c14e891c5cfba2 - Author: Nobuyoshi Nakada - Date: 2019-09-15 02:16:15 +0900 - - make-snapshot: export ChangeLog from srcdir - -commit 1edcfd610703fb6f773e8f31f88f8ca920bda1ac - Author: Jeremy Evans - Date: 2019-09-15 05:57:39 +0900 - - Issue a warning if invalid kw_splat is passed to *_kw function - - This should only happen if the API is misused. It's much better - to warn here and fix the problem, versus to try to debug TypeErrors - or segfaults later. - -commit 395e5f510cb3788dd2b57f1f9fa9be8980564af8 - Author: git - Date: 2019-09-15 02:15:29 +0900 - - * 2019-09-15 [ci skip] - -commit 1ad4be13cb75c5f039f5732d2149f0b84bcf5f8e - Author: Nobuyoshi Nakada - Date: 2019-09-15 02:07:00 +0900 - - make-snapshot: deprecated -exported option [Bug #16167] - -commit e9c7fc7ca9bc15a9f84bdc356f7b6fac12988ccb - Author: Nobuyoshi Nakada - Date: 2019-09-14 23:47:33 +0900 - - Continue to export even if no notes/commits - - Just exporting may not imply exporting ChangeLog which needs - notes/commits. [Bug #16167] - -commit 6d2dcf96323189402ea551ed86de6c2766659593 - Author: Nobuyoshi Nakada - Date: 2019-09-14 22:24:44 +0900 - - [ruby/io-console] Added `intr:` option to IO#raw - - Enters raw-mode but enable interrupts. - - https://github.com/ruby/io-console/commit/7cba76561a - - Notes: - Merged: https://github.com/ruby/ruby/pull/2459 - -commit 8263459627b20d4383978b3d1471298bf52bde05 - Author: Takashi Kokubun - Date: 2019-09-14 21:36:41 +0900 - - Keep the reference of imemo while argv may be used - - To prevent the `v` reference from being eliminated before argv is used, - calling `rb_free_tmp_buffer` against `v` explicitly. - -commit f41cd4ba43771139dacf2c9d3e3ebd490a2619c0 - Author: Nobuyoshi Nakada - Date: 2019-09-14 21:09:39 +0900 - - Fixed one-off error - - Needs another room to append an empty hash. - -commit 9699a5c5bcb9e1483f21efdf7e5cb9bf0a6279fb - Author: Samuel Williams - Date: 2019-09-14 19:43:51 +0900 - - Update news regarding `Fiber#raise`. - -commit 39c37acf86960ae745c4d690fe2d9dd38cd96fba - Author: Jeremy Evans - Date: 2019-09-14 18:21:37 +0900 - - Fix memory leak when adding empty keyword hashes - - nagachika pointed out that ALLOC_N is actually just malloc, so - this memory wasn't being freed. This shouldn't be a performance - sensitive code path, and will be going away after 2.7, so just - allocate a temp buffer that will be freed later by Ruby GC. - -commit b78a345bd63ff2b52ea0f84754ab0988748a9bd0 - Author: Jeremy Evans - Date: 2019-09-14 17:49:33 +0900 - - Only set RB_PASS_CALLED_KEYWORDS in C functions called directly from Ruby - - It is not safe to set this in C functions that can be called from - other C functions, as in the non argument-delegation case, you - can end up calling a Ruby method with a flag indicating keywords - are set without passing keywords. - - Introduce some new *_kw functions that take a kw_splat flag and - use these functions to set RB_PASS_CALLED_KEYWORDS in places where - we know we are delegating methods (e.g. Class#new, Method#call) - -commit b2c29bbab6e88253f497fc3e66a43cb7b4d425b5 - Author: git - Date: 2019-09-14 08:54:08 +0900 - - * remove trailing spaces. [ci skip] - -commit 3cfbfa9628435e3b09316a18c2db9e4f250fdd77 - Author: Jeremy Evans - Date: 2019-09-14 08:42:27 +0900 - - Consolidate empty keyword handling - - Remove rb_add_empty_keyword, and instead of calling that every - place you need to add empty keyword hashes, run that code in - a single static function in vm_eval.c. - - Add 4 defines to include/ruby/ruby.h, these are to be used as - int kw_splat values when calling the various rb_*_kw functions: - - RB_NO_KEYWORDS :: Do not pass keywords - RB_PASS_KEYWORDS :: Pass final argument (which should be hash) as keywords - RB_PASS_EMPTY_KEYWORDS :: Add an empty hash to arguments and pass as keywords - RB_PASS_CALLED_KEYWORDS :: Passes same keyword type as current method was - called with (for method delegation) - - rb_empty_keyword_given_p needs to stay. It is required if argument - delegation is done but delayed to a later point, which Enumerator - does. - - Use RB_PASS_CALLED_KEYWORDS in rb_call_super to correctly - delegate keyword arguments to super method. - -commit 24b1b339757ecab4539a2cb00a545bfcf885d3ef - Author: Jeremy Evans - Date: 2019-09-14 01:31:13 +0900 - - Correctly handle keywords for Method#call for cfuncs, send, and attr_* - - This sets the correct VM frame flags when using Method#call to - call funcs, and handles empty keyword hashes for cfuncs, - attr_reader, and attr_writer. It also fixes calls to send through - Method#call. It adds tests for all of those, as well as tests for - using Method#call to call define_method, lambda, and sym_procs - (which didn't require code changes). - -commit 98f919ed47a136c9a51c7ab5fa39ffb4965a1687 - Author: aycabta - Date: 2019-09-14 00:16:08 +0900 - - The stdlib readline should raise Interrupt when pressing C-c - -commit 70fe473c7dfee70d0e9ee7346c260493e3aceaf2 - Author: git - Date: 2019-09-14 00:12:12 +0900 - - * 2019-09-14 [ci skip] - -commit 83ef23bd75bfee481ea259473742d99d95d2f954 - Author: aycabta - Date: 2019-09-14 00:11:01 +0900 - - Revert "Use IO#getch to read one char in raw mode" - - This reverts commit 805b0a481132938638dbd32830cf5dca3910efb1. - -commit e8fff0ec9cf16487986856c83354c9427e358d1d - Author: aycabta - Date: 2019-09-14 00:10:45 +0900 - - Revert "Use IO#getbyte" - - This reverts commit 685f12bbca50ff9b7a16b3016b3b8b3f2ac8b796. - -commit 06bbacc086d9a63c4443aafb19903b792c41c2e0 - Author: aycabta - Date: 2019-09-14 00:10:34 +0900 - - Revert "Support multibyte input" - - This reverts commit 6d9e54816f828983bcf383ce6fce287bd3ca05b9. - -commit 7e0f56fb3dfcbc1b48f40c6c3b2c23c8e46a2341 - Author: Nobuyoshi Nakada - Date: 2019-09-13 19:48:44 +0900 - - Name dynamically defined methods with line numbers - -commit 5f5aca1b5fb95013f5b805f74ead4cfa143dc1d8 - Author: Nobuyoshi Nakada - Date: 2019-09-13 17:17:21 +0900 - - Moved ruby_node_name declaration to node.h - -commit 2da6b328bb5124793a6420c55325f3106b615bb4 - Author: Koichi Sasada - Date: 2019-09-13 16:24:28 +0900 - - introduce IBF_(MAJOR|MINOR)_VERSION. - - RubyVM::InstructionSequence.to_binary generates a bytecode binary - representation. To check compatibility with binary and loading - MRI we prepared major/minor version and compare them at loading - time. However, development version of MRI can change this format - but we can not increment minor version to make them consistent - with Ruby's major/minor versions. - - To solve this issue, we introduce new minor version scheme - (binary's minor_version = ruby's minor * 10000 + dev ver) - and we can check incompatibility with older dev version. - -commit 3c162df9d4a80bc09d88eeb36db7d59ea0034b1d - Author: Kazuhiro NISHIYAMA - Date: 2019-09-13 11:15:52 +0900 - - Dump some information - - Notes: - Merged: https://github.com/ruby/ruby/pull/2457 - -commit 69acf40b45823e6cc7d12476349a9251a307d1f0 - Author: git - Date: 2019-09-13 00:35:29 +0900 - - * 2019-09-13 [ci skip] - -commit bcd49a4669bd88ab374f9eabdf15aec4f6fff917 - Author: Takashi Kokubun - Date: 2019-09-13 00:34:53 +0900 - - Upgrade benchmark_driver to v0.15.5 - - Fixed new Struct-related keyword argument warnings - -commit ac3e8834e030f62d2d313ec60cd7ed3c14c9ea5e - Author: Akinori MUSHA - Date: 2019-09-12 20:15:03 +0900 - - Document and test Enumerator.produce - - Co-authored-by: Victor Shepelev - -commit 775037613bffe6f90e7af510b7f46a2ac10610be - Author: Akinori MUSHA - Date: 2019-08-29 20:05:10 +0900 - - Implement Enumerator.produce [Feature #14781] - -commit 9f86e5ecb6c66226252bda0d8bdf304d64e69ee3 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-12 18:28:46 +0900 - - Moved coverage.yml to https://github.com/ruby/actions [ci skip] - -commit 515b1989b1093a4dddef83d0cda763c9ae6760e3 - Author: Aaron Patterson - Date: 2019-09-12 06:02:05 +0900 - - Make NODE_ARYPTN layout consistent between Ripper and AST - - We are seeing SEGVs in CI: - - http://ci.rvm.jp/results/trunk-gc-asserts@ruby-sky1/2253563 - - This is happening because Ripper constructs AST nodes differently than - parse.y normally does. Specifically in this case Ripper is assigning 3 - `VALUE` objects: - - https://github.com/ruby/ruby/blob/1febb6f4a14f7222c6d30250bfdc252d34238187/parse.y#L757-L761 - - Where parse.y will normally assign other things: - - https://github.com/ruby/ruby/blob/1febb6f4a14f7222c6d30250bfdc252d34238187/parse.y#L11258-L11260 - - The important one is the last one, the `struct rb_ary_pattern_info`. The - mark function assumed that `NODE_ARYPTN` have a pointer to `struct - rb_ary_pattern_info`, and used it: - - https://github.com/ruby/ruby/blob/1febb6f4a14f7222c6d30250bfdc252d34238187/node.c#L1269-L1274 - - In the case of Ripper, `NODE_ARYPTN` doesn't point to an - `rb_ary_pattern_info`, so the mark function would SEGV. This commit - changes Ripper so that its `NODE_ARYPTN` nodes also point at an - `rb_ary_pattern_info`, and the mark function can continue with the same - assumption. - -commit 21994b7fd686f263544fcac1616ecf3189fb78b3 - Author: John Hawthorn - Date: 2019-09-12 01:02:22 +0900 - - Avoid rehashing keys in transform_values - - Previously, calling transform_values would call rb_hash_aset for each - key, needing to rehash it and look up its location. - - Instead, we can use rb_hash_stlike_foreach_with_replace to replace the - values as we iterate without rehashing the keys. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2452 - -commit 14e3731059246fcd093daa36fd0139d0287e633f - Author: Aaron Patterson - Date: 2019-09-12 03:57:57 +0900 - - Make sure WB executes after object is reachable - -commit 1febb6f4a14f7222c6d30250bfdc252d34238187 - Author: git - Date: 2019-09-12 03:21:40 +0900 - - * 2019-09-12 [ci skip] - -commit ed96c9f270829c7c07852f0aadcd88a58a13875b - Author: Jeremy Evans - Date: 2019-09-12 03:17:35 +0900 - - Emit missing keyword argument separation warnings for define_method - - Previously, the warning functions skipped warning in these cases. - This removes the skipping, and uses a less descriptive warning - instead. - - This affected both last argument to keyword warnings and keyword - split warnings. - -commit fba5bbc69545f6d45f7a2c649321a61f43a0b1a0 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-11 23:38:05 +0900 - - Moved doxygen.yml to https://github.com/ruby/actions [ci skip] - -commit fc3bfd521d4b2354e18bfe403a3b02bd00251d15 - Author: Nobuyoshi Nakada - Date: 2019-09-11 21:36:00 +0900 - - Fixed the function signature to rb_rescue2 - -commit 343b0a281d1dd6e1ab7e6af4c48ad2e6d09a0071 - Author: Nobuyoshi Nakada - Date: 2019-09-11 16:17:04 +0900 - - Made a short-circuit expression w/o result into an `if`-statement - -commit 655c65d65b75a6ac733dfb8e42437e7c43b7cfe1 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-10 16:41:34 +0900 - - &$$->nd_lit is uninitialized at this point - - See also https://travis-ci.org/ruby/ruby/jobs/583031687#L1874 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2444 - -commit 489676bd2049c0a8c9949bf09d3dfb2730a29736 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-11 09:35:06 +0900 - - Add `--no-progress` to `aws s3` [ci skip] - - https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html - > --no-progress (boolean) File transfer progress is not displayed. This flag is only applied when the quiet and only-show-errors flags are not provided. - -commit 91ee9584f9a3e8b8e5e0e9c2f1f2b229ca10323e - Author: Aaron Patterson - Date: 2019-09-11 06:00:48 +0900 - - Macros can't be expressions, so make a function - - Macros can't be expressions, that is a GNU extension (I didn't know - that). This commit converts the macro to a function so that everything - will compile correctly on non-GNU compatible compilers. - -commit 139510238bcbb8d7fd8022c23a603c51d2acbe2e - Author: Aaron Patterson - Date: 2019-09-11 03:27:40 +0900 - - WB needs to be executed after object is reachable - -commit 721cab470606294e5b49ef75793a62becdf5cfb7 - Author: git - Date: 2019-09-11 02:45:56 +0900 - - * 2019-09-11 [ci skip] - -commit 414a80d242796059d69e8980073b5420910cab50 - Author: Aaron Patterson - Date: 2019-09-11 02:44:49 +0900 - - `NODE_MATCH` needs to be marked / allocated from marking bucket - - Fixes a test in RubySpec - -commit 83ef58f264964f86e7276fdb146c108cc0d6abc0 - Author: Nobuyoshi Nakada - Date: 2019-09-10 17:27:07 +0900 - - [ruby/io-console] Suppress yet another warning on Windows - - https://github.com/ruby/io-console/commit/4e17c90788 - -commit b5ab918d0c7cdeac8f1b1d45842383ea5413699f - Author: Nobuyoshi Nakada - Date: 2019-09-10 17:22:06 +0900 - - [ruby/io-console] Suppress warnings on Windows - - About unused variables and a function. - - https://github.com/ruby/io-console/commit/32baf54e7a - -commit ad6cbc1d33d6013ef9b1d2ff9deb286956d9bcbc - Author: Nobuyoshi Nakada - Date: 2019-09-10 17:20:12 +0900 - - Unused LONG_MAX_as_double - - LONG_MAX_as_double is not needed when long is small enough to be - exactly representable as a double, e.g., IL32LLP64 platforms. - -commit 487d290044c5876991d0b9c577bf77a667ec6b93 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-10 16:03:30 +0900 - - oops - - Silly typo. - -commit df1721c668cfd20a08ec6369de89ea314c1d4d19 - Author: Nobuyoshi Nakada - Date: 2019-09-10 14:37:17 +0900 - - Fixed GCC version for diagnostic-pragmas - - "GCC diagnostic push/pop" seems appeared at gcc 4.6. - -commit f5024de002fa82dfe5730b245ad24b8fc3a68424 - Author: Masaki Matsushita - Date: 2019-09-10 12:39:49 +0900 - - Remove check of ai.protocol - - Solaris 10 returns addrinfo.ai_protocol as 0, not 6. - -commit 20e428ec40ee1c83708b3ade6a0007ab2a435f83 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-10 12:22:26 +0900 - - fix CentOS 6 compile error - - See also https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos6/ruby-master/log/20190910T003005Z.fail.html.gz - -commit 8d3db4f26cbbc920c717dfa2784a467014b954a6 - Author: Jeremy Evans - Date: 2019-09-10 08:19:26 +0900 - - Default to cc/c++ instead of gcc/g++ on OpenBSD - - Notes: - Merged: https://github.com/ruby/ruby/pull/2443 - -commit 0e9d56f5e73ed2fd8e7c858fdea7b7d5b905bb64 - Author: Masaki Matsushita - Date: 2019-09-10 09:57:31 +0900 - - Support timeout for Addrinfo - - Addrinfo.getaddrinfo and .foreach now accepts :timeout in seconds as - a keyword argument. If getaddrinfo_a(3) is available, the timeout will be - applied for name resolution. Otherwise, it will be ignored. - - Socket.tcp accepts :resolv_timeout to use this feature. - - This commit is retry of 6382f5cc91ac9e36776bc854632d9a1237250da7. - Test was failed on Solaris machines which don't have "http" in - /etc/services. In this commit, use "ssh" instead. - -commit 3678c371199d9a048589bf3da37f06223912dea5 - Author: Nobuyoshi Nakada - Date: 2019-09-10 01:04:47 +0900 - - [ruby/io-console] Added IO#check_winsize_changed on Windows - - https://github.com/ruby/io-console/commit/ee648fa8bb - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 74790e2dc429daddc6996bc46cb2a0aae2a176e9 - Author: Nobuyoshi Nakada - Date: 2019-09-10 00:01:06 +0900 - - [ruby/io-console] Added scroll methods - - https://github.com/ruby/io-console/commit/83e70de8ab - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit c1412bd6d95805dea7335ef3cb60ac942b4773bf - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:55:45 +0900 - - [ruby/io-console] Added line/screen erase methods - - https://github.com/ruby/io-console/commit/e6344108a1 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 9844a349bfdd5a97ae639e7798cc51aa897846fb - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:53:05 +0900 - - [ruby/io-console] Added IO#goto_column - - https://github.com/ruby/io-console/commit/143a9d5764 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit e8be056af92b2f13162567c057322a2c16797b79 - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:51:44 +0900 - - [ruby/io-console] Added relative cursor move methods - - https://github.com/ruby/io-console/commit/21d340e4a2 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 3d9c7c28358110076abb2d77365eef805ddb896c - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:48:47 +0900 - - [ruby/io-console] Added IO#goto and IO#cursor= for VT - - https://github.com/ruby/io-console/commit/7f2b1b473d - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 53ed4fb37632789db69815bb9b9df0e3572779ef - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:17:38 +0900 - - [ruby/io-console] Added IO#cursor for VT - - https://github.com/ruby/io-console/commit/41a6a6cace - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 803dc9e1e48325515bf7c5ce176cf2b5bc0792a9 - Author: Nobuyoshi Nakada - Date: 2019-09-09 23:14:30 +0900 - - [ruby/io-console] Added console_vt_response - - A function to query console info. - - https://github.com/ruby/io-console/commit/db75a07fa3 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit f4aa06c0ffbf23d68aaed46ce21208f431894eda - Author: Nobuyoshi Nakada - Date: 2019-07-25 05:05:39 +0900 - - [ruby/io-console] Drop fat gem support - - https://github.com/ruby/io-console/commit/972ceb081d - - Notes: - Merged: https://github.com/ruby/ruby/pull/2440 - -commit 00744a03d576f308d7fa586c2d04b5c1cb8fe3f4 - Author: Jeremy Evans - Date: 2019-09-10 07:20:54 +0900 - - Update documentation for Exception [ci skip] - - Mostly from burdettelamar@yahoo.com (Burdette Lamar). - - Implements [Misc #16156] - -commit d8a4af47a5e5f72be2cd2897712d1718013b2e4c - Author: Aaron Patterson - Date: 2019-09-10 02:15:07 +0900 - - Only use `add_mark_object` in Ripper - - This patch changes parse.y to only use `add_mark_object` in Ripper. - Previously we were seeing a bug in write barrier verification. I had - changed `add_mark_object` to execute the write barrier, but the problem - is that we had code like this: - - ``` - NEW_STR(add_mark_object(p, obj), loc) - ``` - - In this case, `add_mark_object` would execute the write barrier between - the ast and `obj`, but the problem is that `obj` isn't actually - reachable from the AST at the time the write barrier executed. - `NEW_STR` can possibly call `malloc` which can kick a GC, and since - `obj` isn't actually reachable from the AST at the time of WB execution, - verification would fail. - - Basically the steps were like this: - - 1. RB_OBJ_WRITTEN via `add_mark_object` - 2. Allocate node - 3. *Possibly* execute GC via malloc - 4. Write obj in to allocated node - - This patch changes the steps to: - - 1. Allocate node - 2. *Possibly* execute GC via malloc - 3. Write obj in to allocated node - 4. RB_OBJ_WRITTEN - -commit 4524780d1795e750e23896866eb447be2670ddcd - Author: Aaron Patterson - Date: 2019-09-10 01:37:06 +0900 - - Revert "Reverting node marking until I can fix GC problem." - - This reverts commit 092f31e7e23c0ee04df987f0c0f979d036971804. - -commit 9b53a69d57ae64a28b4c7904a4590b04d91bbbf3 - Author: git - Date: 2019-09-10 00:57:34 +0900 - - * 2019-09-10 [ci skip] - -commit 6d9e54816f828983bcf383ce6fce287bd3ca05b9 - Author: Nobuyoshi Nakada - Date: 2019-09-08 22:34:01 +0900 - - Support multibyte input - -commit 685f12bbca50ff9b7a16b3016b3b8b3f2ac8b796 - Author: Nobuyoshi Nakada - Date: 2019-09-08 22:19:10 +0900 - - Use IO#getbyte - -commit 805b0a481132938638dbd32830cf5dca3910efb1 - Author: Nobuyoshi Nakada - Date: 2019-09-08 21:04:46 +0900 - - Use IO#getch to read one char in raw mode - -commit 89c5d5a64e12cea23b230913b79c3d499bf30b12 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-09 13:19:33 +0900 - - add minimaist C++ check - - This is a test extension so we basically want test failures rather - than a configure breakage but if there is no C++ compiler, we need - no test at all because there will be no chance for the tested - header file to be used later. - - This makes it possible to build the ruby binary without any C++ - compiler installed in a build environment. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2434 - -commit 150f514e19125ce8239602dc9266c7f68166d671 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-09 11:13:31 +0900 - - workaround for C++ 98 const union problem. - - Not the case of recent compilers, but compilers before C++11 - rejected ruby.h, like https://ci.appveyor.com/project/ruby/ruby/builds/27225706/job/qjca7dpe204dytbd - - This is supposedly because a struct with a member qualified with - a const effectively deletes its default copy constructor, which - is considered as being user-defined somehow. Not sure where - exactly is the phrase in the C++98 standard who allows such C / - C++ incompatibility though. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2434 - -commit 042c436cd9cfaeee7a0d7b8e35bee8dec90e972d - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-07 18:46:37 +0900 - - static member variables must explicitly be initialized - - These variables then get their room for storage. - - See also https://github.com/ruby/ruby/runs/214042030 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2434 - -commit 1364217bcdcf128de4586527042035d833349c15 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-07 18:41:34 +0900 - - add missing dependency for .travis.yml - - Notes: - Merged: https://github.com/ruby/ruby/pull/2434 - -commit 92a87269945154344ba3fc96c0de63493e2fe6a1 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-07 17:48:02 +0900 - - Revert "save committers' weekend from CI failures" - - This reverts commit 53d21087da078cf999cc4757b03b2ff0fab4c2cf. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2434 - -commit c4efbf663ea1849986383ca97bfc8c2609142c68 - Author: Masaki Matsushita - Date: 2019-09-09 20:30:45 +0900 - - Revert "Support timeout for Addrinfo" - - This reverts commit 6382f5cc91ac9e36776bc854632d9a1237250da7. - test failed on Solaris. - -commit cce6cfbe486984c2c41d6b772a692ea87ad0222a - Author: Yusuke Endoh - Date: 2019-09-09 20:24:03 +0900 - - Make test-all and test-spec runnable on Android - - Calling some syscall functions such as Dir.chroot causes SIGSYS instead - of EPERM on Android. - This change skips all tests that stops the test-suite run. - -commit 0691a748b6406670ef4cb52d0791b45033b7064e - Author: Kazuhiro NISHIYAMA - Date: 2019-09-09 20:06:00 +0900 - - Fix a typo [ci skip] - -commit 551edf64bcbbbc84af59b5ae44a0820314b72777 - Author: Lars Kanis - Date: 2019-09-09 01:24:48 +0900 - - Reline: Fix wrong variable name - - This raised a NameError before. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2438 - -commit 8c09de38c5f2dab324bcb30ab4a8db9bd55357b2 - Author: Masaki Matsushita - Date: 2019-09-09 18:44:42 +0900 - - Fix expected ip_port - -commit 0fb2457d794ee49701873584c80a6e1cace94b83 - Author: Masaki Matsushita - Date: 2019-09-09 18:35:19 +0900 - - Fix service name for test - - change service name to fix failed test on Solaris - -commit 461663f52a87bbae7f3713862a20a4aa6bd63e4c - Author: Masaki Matsushita - Date: 2019-09-09 15:05:05 +0900 - - Fix domain name for test - -commit 61d90da25c027f896ddc0e71c7b17c67d4b12a97 - Author: Jeremy Evans - Date: 2019-09-09 12:51:56 +0900 - - Fix invalid keyword argument separation warning for delegating calls - - This removes an invalid keyword argument separation warning for - code such as: - - ```ruby - def foo(arg) - arg - end - kw = {} - foo(*[1], **kw) - ``` - - This warning was caused because the remove_empty_keyword_hash - was set based on a comparison with two variables, and in this - case, one of the variables was updated after the check and we - need to use the updated variable. - - Simplify things by just inlining the comparison. - -commit 6382f5cc91ac9e36776bc854632d9a1237250da7 - Author: Masaki Matsushita - Date: 2018-12-31 12:17:39 +0900 - - Support timeout for Addrinfo - - Addrinfo.getaddrinfo and .foreach now accepts :timeout in seconds as - a keyword argument. If getaddrinfo_a(3) is available, the timeout will be - applied for name resolution. Otherwise, it will be ignored. - - Socket.tcp accepts :resolv_timeout to use this feature. - -commit fa79219356715e28529b721e81056ec69a998c4e - Author: Jeremy Evans - Date: 2019-09-09 02:34:34 +0900 - - Add keyword argument separation tests for implicit/explicit super calls - - No code changes are necessary, but we didn't have as extensive - tests for these calls previously. - -commit d636feb6a6e1a2ff7ca39b7735514a06843e7aae - Author: git - Date: 2019-09-09 00:27:05 +0900 - - * 2019-09-09 [ci skip] - -commit 8d53b2cdf8e4f175876f184e4f74fb6125204cc8 - Author: Nobuyoshi Nakada - Date: 2019-09-09 00:21:40 +0900 - - Use target-specific variable instead of a conditional [ci skip] - - And test-rubyspec is deprecated. - -commit 3ef76ce44a3308871e7b4d6158cc880a8dfa9949 - Author: Nobuyoshi Nakada - Date: 2019-09-08 21:22:25 +0900 - - make-snapshot: -git option is no longer provided [ci skip] - -commit b10940a839636cbd990cb2f8a6430fb39c50fb04 - Author: Benoit Daloze - Date: 2019-09-08 19:41:14 +0900 - - Improve Proc#to_s specs - -commit aedf6946a7e958dd00a272c08550790be9dd1c0d - Author: Nobuyoshi Nakada - Date: 2019-09-08 12:54:06 +0900 - - Removed useless braces to suppress a warning - -commit e9bc8b35c6c860e227627e3b0aab86b4f51c59af - Author: aycabta - Date: 2019-09-08 03:26:09 +0900 - - Behave ESC key correctly when vi command mode - -commit 46bfe907f1d61217215bcd1a7da9dff258c63294 - Author: Yusuke Endoh - Date: 2019-09-08 03:06:38 +0900 - - compile.c (compile_hash): rewrite keyword splat handling - - and add some comments. - (I confirm that `foo(**{})` allocates no hash object.) - -commit 95297a15f19743db690d330d082636638313542b - Author: Yusuke Endoh - Date: 2019-09-08 02:54:56 +0900 - - compile.c (compile_hash): rewrite the compilation algorithm - - This is a similar refactoring to 8c908c989077c74eed26e02912b98362e509b8a3, - but the target is compile_hash. - -commit 35680298239f1cd02c19ab742a2116be37d24d90 - Author: aycabta - Date: 2019-09-07 22:06:58 +0900 - - Remove .document and .gitignore from file list of rdoc.gemspec - -commit 4f63634af1fdce87c842f79fcb489ff2f7e4fee8 - Author: Yusuke Endoh - Date: 2019-09-08 01:21:19 +0900 - - compile.c (NODE_OP_ASGN1): Remove unneeded DECL_ANCHOR - -commit 2d017d612657ab2cffc320dcad679a8854b14a6b - Author: Nobuyoshi Nakada - Date: 2019-09-08 00:48:18 +0900 - - make-snapshot: default to the toplevel directory - - As this tool has been intended to use in a working directory, - assume that the toplevel directory is under the VCS, and SVN will - no longer be canonical. - -commit a3f5265fd104ec3812af6a918f375e23aa05a251 - Author: Yusuke Endoh - Date: 2019-09-08 00:22:26 +0900 - - parse.y: Use the correct alias for brace flag of hash literal - - nd_alen and nd_brace is the same field, but nd_brace is more suitable - for this case. - -commit 95f9d7c76d9e808099f89e5cf160306680dc5994 - Author: Yusuke Endoh - Date: 2019-09-08 00:21:23 +0900 - - compile.c (keyword_node_p): Refactor out keyword node checks - -commit 86b74d1a7389ceaccdc2822b1bbe0a91dc50db99 - Author: Yusuke Endoh - Date: 2019-09-08 00:11:50 +0900 - - compile.c (compile_hash): Remove redundant check for NODE_ZLIST - - NODE_ZLIST case is handled in compile_hash, so iseq_compile_each0 - doesn't have to do the same check redundantly. - -commit 050f67c9c634fc0064c49f79ecb49588676028ec - Author: Yusuke Endoh - Date: 2019-09-07 23:57:37 +0900 - - compile.c (compile_hash): Simplify the keyword handling - - The length of NODE_LIST chain in NODE_HASH is always even because it - represents key-value pairs. There is no need to check for the - odd-length case. - -commit bb78c8367802335ec17c39b228e0f535b6e23cb4 - Author: Yusuke Endoh - Date: 2019-09-07 23:56:19 +0900 - - compile.c (compile_hash): don't add a temporal array to mark_ary - - The array is just for a temporal buffer to create a hash, not stored in - the final iseq. - -commit 7cba9a84068e26d798bfe579607c27587302d67f - Author: Yusuke Endoh - Date: 2019-09-07 23:55:51 +0900 - - compile.c (compile_array): undef a temporal macro - -commit b543f5b20fa992dfb62e65525394ee079ea5de57 - Author: git - Date: 2019-09-08 00:23:56 +0900 - - * 2019-09-08 [ci skip] - -commit f3bae2c6cff8eff83114df0e96fd6c338c90ee91 - Author: Nobuyoshi Nakada - Date: 2019-09-08 00:21:42 +0900 - - Touch copied cache files to make tarballs stable - -commit 5a6954ba74adf190a64f91598667520135284a1c - Author: Nobuyoshi Nakada - Date: 2019-09-07 17:28:05 +0900 - - Suppress detached head warning - -commit ae8b9777424f11cbcb962db94958f1e8a3c11acd - Author: Takashi Kokubun - Date: 2019-09-07 23:13:46 +0900 - - Avoid defining DISPATCH_ARCH_DEPEND_WAY macro - - when it's not used. This macro is not used when it's direct threaded code. - - This patch is purely for readability and has no impact for any behavior. - -commit a9b63db3b6cd7cdf5ca48eafc784d4ed37b5fdac - Author: git - Date: 2019-09-07 22:22:30 +0900 - - * remove trailing spaces. [ci skip] - -commit 8c908c989077c74eed26e02912b98362e509b8a3 - Author: Yusuke Endoh - Date: 2019-09-07 22:08:39 +0900 - - compile.c (compile_array): rewrite the compilation algorithm - - The original code looks unnecessarily complicated (to me). - Also, it creates a pre-allocated array only for the prefix of the array. - - The new code optimizes not only the prefix but also the subsequence that - is longer than 0x40 elements. - - # not optimized - 10000000.times { [1+1, 1,2,3,4,...,63] } # 2.12 sec. - # (1+1; push 1; push 2; ...; puts 63; newarray 64; concatarray) - - # optimized - 10000000.times { [1+1, 1,2,3,4,...,63,64] } # 1.46 sec. - # (1+1; newarray 1; putobject [1,2,3,...,64]; concatarray) - -commit 07876bf6dbdab5a8a633173f91ee1603d617afb0 - Author: Yusuke Endoh - Date: 2019-09-07 20:24:24 +0900 - - compile.c (compile_hash): refactoring - - The same refactoring as to b601b13c7267889bf394146353c5f2b0eb488278. - -commit 187328b7037e54f1f5c2558d84215f3d5d3fbdee - Author: Yusuke Endoh - Date: 2019-09-07 18:54:01 +0900 - - compile.c (compile_array): refactoring - - "popped" case can be so simple, so this change moves the branch to the - first, instead of scattering `if (popped)` branches to the main part. - Also, the return value "len" is not used. So it returns just 0 or 1. - -commit 324dd9d01f0c97631a2588f63231bcb651844cca - Author: Benoit Daloze - Date: 2019-09-07 19:53:07 +0900 - - armv7l and armv7l are the same platform, generalize to armv7 - - [Bug #16007] - -commit 5511213487f9e6c6bd23a227ee64f9c541680f02 - Author: Nobuyoshi Nakada - Date: 2019-09-07 17:25:52 +0900 - - Exit gently if no VCS found but --suppress_not_found is given - -commit 5b5c9b61015434a253bf1eee65c7f05dc870b105 - Author: Nobuyoshi Nakada - Date: 2019-09-07 17:23:42 +0900 - - Removed no longer used variable - -commit a2260bd636646cde486afeebe5a0a7ef5ec78a4e - Author: Yusuke Endoh - Date: 2019-09-07 16:45:49 +0900 - - compile.c: Separate compile_list to two functions for Array and Hash - - compile_list was for the compilation of Array literal and Hash literal. - I guess it was originally reasonable to handle them in one function, but - now, compilation of Array is very different from Hash. So the function - was complicated by many branches for Array and Hash. - - This change separates the function to two ones for Array and Hash. - -commit 2f2f8107d0d21f5ebaaaf3b2d7ed6d09dfec91d5 - Author: Yusuke Endoh - Date: 2019-09-07 16:26:38 +0900 - - compile.c (compile_list): allow an odd-length hidden array literal - - An array literal [1,2,...,301] was compiled to the following iseq: - - duparray [1,2,...,300] - putobject [301] - concatarray - - The Array literal optimization took every two elements maybe because it - must handle not only Array but also Hash. - Now the optimization takes each element if it is an Array literal. So - the new iseq is: duparray [1,2,...,301]. - -commit 1e008105bc4576af46036f1c73f96f7f93bee319 - Author: Yusuke Endoh - Date: 2019-09-07 16:01:16 +0900 - - compile.c (compile_list): emit newarraykwsplat only at the last chunk - - `[{}, {}, {}, ..., {}, *{}]` is wrongly created. - - A big array literal is created and concatenated for every 256 elements. - The newarraykwsplat must be emitted only at the last chunk. - -commit c725a4e48fc30cb60e539e86c917698209184345 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-07 14:02:35 +0900 - - Check github.repository in doxygen.yml [ci skip] - -commit a7a2be7a31b66b05a118fb41dabf0cb965f4a9c0 - Author: Yusuke Endoh - Date: 2019-09-07 13:51:18 +0900 - - Rename some function/definition names that handles NODE_LIST - - from array to list. - Follow up to ac50ac03aeb210763730cdc45f230e236519223d - -commit 99c9431ea1cc538489c3da70f52121aa8bc0800b - Author: Yusuke Endoh - Date: 2019-09-07 10:42:00 +0900 - - Rename NODE_ARRAY to NODE_LIST to reflect its actual use cases - - and NODE_ZARRAY to NODE_ZLIST. - - NODE_ARRAY is used not only by an Array literal, but also the contents - of Hash literals, method call arguments, dynamic string literals, etc. - In addition, the structure of NODE_ARRAY is a linked list, not an array. - - This is very confusing, so I believe `NODE_LIST` is a better name. - -commit f223ab47e6e41e4a5f0307a5202b4f5c534a3596 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-07 13:49:47 +0900 - - [DOC] Update output of Ripper.sexp [ci skip] - -commit 8bfc46a9a3ba16f58aa68d8191048df7f0720f04 - Author: Nobuyoshi Nakada - Date: 2019-09-07 11:59:19 +0900 - - Fixed wrong usage of file2lastrev.rb - -commit 8b290448e3233e03b01288c179eb49bee63d1302 - Author: Nobuyoshi Nakada - Date: 2019-09-07 11:56:23 +0900 - - Assign to vcs in new_vcs block not to use rescue result - -commit 59e29389a8c3501e71444fed2c10ba6821e63625 - Author: Nobuyoshi Nakada - Date: 2019-09-07 11:47:21 +0900 - - Fixed wrong method at 71f7b0421ac - -commit 146677a1e76fd33d86894d0430ea137dbc63579a - Author: Jeremy Evans - Date: 2019-09-07 05:37:31 +0900 - - Fix keyword argument warnings in the tests from Class#new - - This were previously hidden because calls from C were not warned. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2432 - -commit 434582d888ad2982ec01d9b5a1e1afe8480312ab - Author: Jeremy Evans - Date: 2019-09-07 05:37:09 +0900 - - Fix Tempfile.open to correctly pass keywords to Tempfile.new - - Notes: - Merged: https://github.com/ruby/ruby/pull/2432 - -commit 56036815207b803151b0c7215da3a880bbad6df1 - Author: Jeremy Evans - Date: 2019-09-07 05:35:50 +0900 - - Enable keyword argument warnings when called from C - - Previously, Ruby did not warn in these cases, and in some cases - did not have the same behavior. This makes calls from C handled - the same way as calls from Ruby. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2432 - -commit 80e679ef2d6f370e853e37053c73930c65b5e76c - Author: Jeremy Evans - Date: 2019-09-07 05:33:19 +0900 - - Fix keyword argument separation warnings for enumerators - - This makes objects created via #to_enum and related methods pass - keyword arguments as keywords. - - To implement this, add a kw_splat member of struct enumerator and - struct iter_method_arg, and add rb_block_call_kw, which is the - same as rb_block_call_kw with a flag for whether the last argument - is keyword options. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2432 - -commit 37a2c660aa4f4aacfd6a56651b10124e3ac01321 - Author: Jeremy Evans - Date: 2019-09-06 11:25:34 +0900 - - Convert keyword argument to required positional hash argument for Class#new, Method#call, UnboundMethod#bind_call - - Also add keyword argument separation warnings for Class#new and Method#call. - - To allow for keyword argument to required positional hash conversion in - cfuncs, add a vm frame flag indicating the cfunc was called with an empty - keyword hash (which was removed before calling the cfunc). The cfunc can - check this frame flag and add back an empty hash if it is passing its - arguments to another Ruby method. Add rb_empty_keyword_given_p function - for checking if called with an empty keyword hash, and - rb_add_empty_keyword for adding back an empty hash to argv. - - All of this empty keyword argument support is only for 2.7. It will be - removed in 3.0 as Ruby 3 will not convert empty keyword arguments to - required positional hash arguments. Comment all of the relevant code - to make it obvious this is expected to be removed. - - Add rb_funcallv_kw as an public C-API function, just like rb_funcallv - but with a keyword flag. This is used by rb_obj_call_init (internals - of Class#new). This also required expected call_type enum with - CALL_FCALL_KW, similar to the recent addition of CALL_PUBLIC_KW. - - Add rb_vm_call_kw as a internal function, used by call_method_data - (internals of Method#call and UnboundMethod#bind_call). Add tests - for UnboundMethod#bind_call keyword handling. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2432 - -commit 3fafc549ba909e986917f2b6b96eb14624c26329 - Author: Nobuyoshi Nakada - Date: 2019-09-07 11:35:00 +0900 - - Fix error when checking file modified with git-svn - -commit d783609ac3b2901eb664dd37f964c8fd805dca40 - Author: Nobuyoshi Nakada - Date: 2019-09-07 11:33:26 +0900 - - Get rid of overwriting revision.h and creating .revision.time - -commit 5118aa2d58f70a2f1349daa784705d20b2928869 - Author: Nobuyoshi Nakada - Date: 2019-09-07 01:02:37 +0900 - - Use `git describe --contains` for tags - -commit 3890c9eeee2322b8bf81c04517a4714de77e49ff - Author: Nobuyoshi Nakada - Date: 2019-09-07 01:01:52 +0900 - - Added more debug outputs from VCS::GIT - -commit 71f7b0421acff068b94953f4d3f5b4d987ce5350 - Author: Nobuyoshi Nakada - Date: 2019-09-07 01:00:14 +0900 - - Refined file2lastrev.rb options - - * check --srcdir if given twice or more - * falls back to the current working directory if no --srcdir - option is given. - * define common VCS options. - -commit 799de9122e2bd9c2f4cc7e0611f6f8313876ca1d - Author: Nobuyoshi Nakada - Date: 2019-09-07 00:36:08 +0900 - - Separated VCS.define_options for common VCS options - -commit 4068be1d9f60d8a9ac063c4871986dc26bdd0d56 - Author: MSP-Greg - Date: 2019-09-07 09:14:15 +0900 - - appveyor.yml - msys2 update code - - As AppVeyor's MSYS2 install gets out of date, this may require 'special' code... - - This code also adds updating the database, which currently updates gcc from 9.1.0 to 9.2.0. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2433 - -commit 3bb3fa4051c754af1a26f023a902d1ce67fe964e - Author: Yusuke Endoh - Date: 2019-09-07 09:18:38 +0900 - - eval.c (rb_rescue2): fix a probably wrong return - - This return skips `va_end(ap)`, which is not intended, I guess. - Coverity Scan found this. - -commit 9c0626fa909b57e43a476aa78171e140ae09d31f - Author: Takashi Kokubun - Date: 2019-09-07 09:14:32 +0900 - - Upgrade benchmark-driver to v0.15.4 - - Fixing a bug on Windows introduced in v0.15.0 - -commit 258843106f343d05732499dd1832958eb1bf64f0 - Author: Jeremy Evans - Date: 2019-06-05 11:08:54 +0900 - - Fix SortedSet subclasses that override initialize - - The first time SortedSet#initialize is called, it overwrites - itself, then recalls #initialize, which results in calling the - subclass's initialize, not the current initialize. - - Just inline the default initialize behavior to avoid this issue. - - No test for this as it can only be triggered the very first time - that SortedSet#initialize is called. - - Fixes [Bug #15830] - -commit 2d076dd5ac8fc1102939f04236878446348599d0 - Author: git - Date: 2019-09-07 00:45:44 +0900 - - * 2019-09-07 [ci skip] - -commit bb53ddfe0e826bcb6a7ff823c20ac3e7599500b1 - Author: Takashi Kokubun - Date: 2019-09-07 00:43:26 +0900 - - Upgrade benchmark-driver to v0.15.3 - - It got some nice features for better support of - benchmark_driver-output-charty, Windows, ridk, and rbenv. - -commit ade1283ca276f7d589ffd3539fbc7b9817f682d5 - Author: Yusuke Endoh - Date: 2019-09-06 23:18:26 +0900 - - Fix a use-after-free bug by avoiding rb_str_new_frozen - - `str2 = rb_str_new_frozen(str1)` seems to make str1 a shared string that - refers to str2, but str2 is not marked as STR_IS_SHARED_M nor - STR_NOFREE. - `rb_fstring(str2)` frees str2's ptr because it is not marked, and the - free'ed pointer is the same as str1's ptr. - After that, accessing str1 may cause use-after-free memory corruption. - - I guess this is a bug of rb_str_new_frozen, but I'm completely unsure - what it should be; the string states and flags are not documented. - So, this is a workaround for [Bug #16136]. I confirmed that rspec of - activeadmin runs gracefully. - -commit 055b44109316bfc5461d6ac820619f893cea536c - Author: Nobuyoshi Nakada - Date: 2019-09-06 22:15:36 +0900 - - VCS::GIT no longer accepts remote repository - -commit 733aa2f8b578d03bbcb91d2f496b01e3b990c7e8 - Author: Nobuyoshi Nakada - Date: 2019-09-06 18:43:10 +0900 - - Stop setting same flags as cflags to cxxflags - -commit dd26c9f333b9681b3b14cf01969cda9d77368cbc - Author: Nobuyoshi Nakada - Date: 2019-09-06 18:35:37 +0900 - - Check clang++ as CXX when CXX is bare clang without suffix - -commit 53d21087da078cf999cc4757b03b2ff0fab4c2cf - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 18:17:47 +0900 - - save committers' weekend from CI failures - - Kill the failing tests. - -commit 99bfa6c16562f7af7fb6daf3cf89680ef30d4163 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-06 17:47:24 +0900 - - Try to fix compile error on win32 - - https://github.com/ruby/ruby/runs/213995386#step:7:810 - ``` - cxxanyargs.cpp - C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\corecrt_malloc.h(54): error C2485: '__restrict': unrecognized extended attribute - ``` - -commit 1851dc269cb7a957fcb1fe2e97b7b76c2a52d096 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 16:50:57 +0900 - - avoid name mangling - - Otherwise the dynamic linker cannot find this function. - See also https://ci.appveyor.com/project/ruby/ruby/builds/27224231/job/4pg6lxlsnsjotu2l - -commit 2aa4fb57d103b8deec43de6735e23a1c9b8c8fa0 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 16:42:45 +0900 - - nullptr is a C++11ism. - - Should use numeric 0 for maximum portability. - See also https://travis-ci.org/ruby/ruby/jobs/581543798 - -commit 7516c48b2744b563a6cb420c23c1ff8bdea72da6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 16:33:30 +0900 - - fix Visual Studio compilation error - - See also https://github.com/ruby/ruby/runs/213964487 - -commit 04f570e266ba7f9d155ceea943043532a7e2f859 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 15:50:23 +0900 - - add test for cxxanyargs.hpp - -commit a569bc09e25a2ba813d0bec1228d9ff65330a3db - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-05 23:50:45 +0900 - - add include/ruby/backward/cxxanyargs.hpp - - Compilation of extension libraries written in C++ are reportedly - broken due to https://github.com/ruby/ruby/pull/2404 - - The root cause of this issue was that the definition of ANYARGS - differ between C and C++, and that of C++ is incompatible with the - updated ones. - - We are using the incompatibility against itself. In C++ two distinct - function prototypes can be overloaded. We provide the old, ANYARGSed - prototypes in addition to the current granular ones; and let the - older ones warn about types. - -commit d6a94cffda6763c7ad3ac3830dcfe6a87e405fe4 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-06 10:38:40 +0900 - - doxygen update [ci skip] - -commit 41b7c335d3ede90e7bc1b469de242df392dc6adc - Author: Yusuke Endoh - Date: 2019-09-06 13:04:36 +0900 - - Revert "Add a temporal stack dumper for debugging on trunk-mjit" - - This reverts commit 433c9c00d96124e3b416d0a20ff795b0ad4273fa. - - Successfully captured some traces, and - 3b60e5e6bc2c84b971bea9c8312eb5d33ada2ff5 seems to fix the issue. - -commit 3b60e5e6bc2c84b971bea9c8312eb5d33ada2ff5 - Author: Takashi Kokubun - Date: 2019-09-06 10:34:33 +0900 - - Try shrinking tested VM stack max - -commit dd81af7b6a7539473b6d7a7e35637b4a7d986523 - Author: git - Date: 2019-09-06 09:50:59 +0900 - - * remove trailing spaces. [ci skip] - -commit d3cf0eb2142902245b7d45b557f73bbb1f02ba5a - Author: Jeremy Evans - Date: 2019-09-06 08:06:38 +0900 - - Mark rb_warn_keyword_to_last_hash as static inline - - mame pointed out that vm_args.c is included in vm_insnhelper.c. - -commit 5045fe6017996a9ce2562667284b392e01b5759e - Author: Jeremy Evans - Date: 2019-09-06 08:02:45 +0900 - - Mark rb_warn_keyword_to_last_hash at MJIT_FUNC_EXPORTED - - Hopefully this fixes MJIT errors on AppVeyor. - -commit 729de9ee68b868b43375eb4339b2d59f0bb8e7e8 - Author: Jeremy Evans - Date: 2019-09-06 05:07:28 +0900 - - Convert empty keyword hash to required positional argument and warn for method_missing - - This is the same as the bmethod, sym proc, and send cases, - where we don't remove the keyword splat, so later code can - move it to a required positional parameter and warn. - -commit e220b467ef3faf24140cba572b2d67973391aaa5 - Author: Jeremy Evans - Date: 2019-09-06 05:03:09 +0900 - - Convert empty keyword hash to required positional argument and warn for sym procs - - This is the same as the bmethod and send cases, where we don't - remove the keyword splat, so later code can move it to to a - a required positional parameter and warn. - -commit e2878a96f77978b224f8461244cd3e1efc248d83 - Author: Jeremy Evans - Date: 2019-09-06 04:43:06 +0900 - - Convert empty keyword hash to required positional argument and warn for lambda and bmethod - - The lambda case is similar to the attr_writer case, except we have - to determine the number of required parameters from the iseq - instead of being able to assume a single required parameter. - - This fixes a lot of lambda tests which were switched to require - warnings for all usage of keyword arguments. Similar to method - handling, we do not warn when passing keyword arguments to - lambdas that do not accept keyword arguments, the argument is - just passed as a positional hash in that case, unless it is empty. - If it is empty and not the final required parameter, then we - ignore it. If it is empty and the final required parameter, then - we pass it for backwards compatibility and emit a warning, as in - Ruby 3 we will not pass it. - - The bmethod case is similar to the send case, in that we do not - want to remove empty keyword splats in vm_call_bmethod, as that - prevents later call handling from moving them to required - positional arguments and warning. - -commit e7274a8ec43b5b20e42842e730dbabae58d2e6a2 - Author: Jeremy Evans - Date: 2019-09-06 04:25:14 +0900 - - Convert empty keyword hash to required positional argument and warn - - In general, we want to ignore empty keyword hashes. The only case - where we want to allow them for backwards compatibility is when - they are necessary to satisfy the final required positional argument. - In that case, we want to not ignore them, but we do want to warn, - as that will be going away in Ruby 3. - - This commit implements this support for regular methods and - attr_writer methods. - - In order to allow send to forward arguments correctly, send no - longer removes empty keyword hashes. It is the responsibility of - the final method to remove the empty keyword hashes now. This - change was necessary as otherwise send could remove the empty - keyword hashes before the regular or attr_writer methods could - move them to required positional arguments. - - For completeness, add tests for keyword handling regular - methods calls. - - This makes rb_warn_keyword_to_last_hash non-static in vm_args.c - so it can be reused in vm_insnhelper.c, and also moves declarations - before statements in the rb_warn_* functions in vm_args.c. - -commit d1ef73b59cede58f2173fa0f4ff7480a820f25d6 - Author: Jeremy Evans - Date: 2019-09-06 02:36:28 +0900 - - Always remove empty keyword hashes when calling methods - - While doing so is not backwards compatible with Ruby 2.6, it is - necessary for generic argument forwarding to work for all methods: - - ```ruby - def foo(*args, **kw, &block) - bar(*args, **kw, &block) - end - ``` - - If you do not remove empty keyword hashes, and bar does not accept - keyword arguments, then a call to foo without keyword arguments - calls bar with an extra positional empty hash argument. - -commit 55b96c5d2d7d8bcc2953484bd2f9c9519b252dae - Author: Yusuke Endoh - Date: 2019-09-05 19:29:25 +0900 - - Add a keyword-to-last-hash warning for some case of define_method method - - and lambda. - - When define_method is a simple iseq (`define_method(:m) {|x| ... }`), - passing keywords to it (`m(**kw)`) didn't print a warning. - -commit dd83f7bf98764b27385735f6f39dd090dc4854f9 - Author: Yusuke Endoh - Date: 2019-09-05 19:07:05 +0900 - - define_method should not drop the empty keyword hash - - Similar to 38e9c1bc35d5549575fbb263afff560e97db068e - -commit 70f2780892330f8d1b612002c437fc2ca739fc7f - Author: Yusuke Endoh - Date: 2019-09-05 18:57:19 +0900 - - vm_call_bmethod should not drop the empty keyword hash - - Similar to 38e9c1bc35d5549575fbb263afff560e97db068e - -commit 252e2990099557a54577ad8915b689761117cd7a - Author: Yusuke Endoh - Date: 2019-09-05 18:54:26 +0900 - - vm_call_opt_send should not drop the empty keyword hash - - Now the mechanism that conveys kw_splat flag is gradually established, - so the hack to drop the empty keyword hash is not needed for - vm_call_opt_send. - -commit 4615886c76c0e906a349440ac7e232ad0ba5ce30 - Author: Yusuke Endoh - Date: 2019-09-05 18:52:22 +0900 - - test_method_missing_kwsplat should call the target directly - - not via Object#send which uses a fast path vm_call_opt_send. - -commit acee6302419f02792ec331d384f430c5fc6bdb70 - Author: Yusuke Endoh - Date: 2019-09-05 18:34:07 +0900 - - vm_insnhelper.c: Do not read `ci->flag` after CALLER_SETUP_ARG - - Actually, the following call is wrongly warned without this change. - - ``` - class C - def method_missing(x, *args, **opt) - end - end - C.new.foo(k: 1) - # warning: The last argument is used as the keyword parameter - # warning: for `method_missing' defined here - ``` - -commit eda8dcea164b561359f638b1489d0ab12659c9a2 - Author: Yusuke Endoh - Date: 2019-09-05 17:31:00 +0900 - - Add a comment that some ci->flag is inconsistent after CALLER_SETUP_ARG - -commit 0bfe3bf4d1a2cf6659a99c7466c733cf922ee0e0 - Author: Yusuke Endoh - Date: 2019-09-05 17:03:38 +0900 - - Ignore an empty keyword splat for attr_reader/writer methods - -commit 437ff408790d5426e0ee03a4b22171bf745471a7 - Author: Yusuke Endoh - Date: 2019-09-05 16:54:43 +0900 - - C method should accept a keyword hash (for compatibility with 2.6) - -commit c5555e2eb8631e649cc9377f0bd75ebc2788cc7d - Author: Yusuke Endoh - Date: 2019-09-05 16:27:26 +0900 - - CALLER_SETUP_ARG removes an empty keyword hash from argv - - ...only when a "remove_empty_keyword_hash" flag is specified. - - After CALLER_SETUP_ARG is called, `ci->flag & VM_CALL_KW_SPLAT` must not - be used. Instead. use `calling->kw_splat`. This is because - CALLER_SETUP_ARG may modify argv and update `calling->kw_splat`, and - `ci->flag & VM_CALL_KW_SPLAT` may be inconsistent with the result. - -commit a23ddf7ff58ec77548d2ecd7f9f202aa3eff9fc7 - Author: Yusuke Endoh - Date: 2019-09-05 16:24:46 +0900 - - vm_argc.c (vm_caller_setup_arg_kw): "cfunc" argument is no longer used - -commit 030b8e5edf1056e59c37bc52ed6f4deca7e8ac41 - Author: Yusuke Endoh - Date: 2019-09-05 12:28:36 +0900 - - Set calling->kw_splat = 1 in vm_caller_setup_arg_kw - - There are two styles that argv contains keyword arguments: one is - VM_CALL_KWARG which contains value elements in argv (to avoid a hash - object creation if possible), and the other is VM_CALL_KW_SPLAT which - contains one last hash in argv. - - vm_caller_setup_arg_kw translates argv from the VM_CALL_KWARG style to - the VM_CALL_KW_SPLAT style. - `calling->kw_splat` means that argv is the VM_CALL_KW_SPLAT style. - - So, instead of setting `calling->kw_splat` at many places, it would be - better to do so when vm_caller_setup_arg_kw is called. - -commit 1fffd33189ddb4dfdefe2ada09ec884f89e305ce - Author: Jeremy Evans - Date: 2019-09-05 07:47:53 +0900 - - Fix passing keywords without splats to sym procs, define_method, and method_missing - -commit 6f9b86616a8ad60cfed2979e2a0f8398a12e7c85 - Author: Jeremy Evans - Date: 2019-09-04 06:54:37 +0900 - - Make Symbol#to_proc calls handle keyword arguments - - Make rb_sym_proc_call take a flag for whether a keyword argument - is used, and use the new rb_funcall_with_block_kw function to - pass that information. - -commit 38dae1d510b931516ba1229a1ffbe5f6e470e292 - Author: Jeremy Evans - Date: 2019-09-04 06:53:16 +0900 - - If removing an empty keyword splat hash, unset the kw_splat flag - - Otherwise the last positional hash could be considered as the - keyword arguments. - -commit 7fc874bf4cbdd87b3d6fe05dc5959175f3fe94b8 - Author: Jeremy Evans - Date: 2019-09-04 06:49:03 +0900 - - Add rb_funcall_with_block_kw - - This is needed for C functions to call methods with keyword arguments. - This is a copy of rb_funcall_with_block with an extra argument for - the keyword flag. - - There isn't a clean way to implement this that doesn't involve - changing a lot of function signatures, because rb_call doesn't - support a way to mark that the call has keyword arguments. So hack - this in using a CALL_PUBLIC_KW call_type, which we switch for - CALL_PUBLIC later in the call stack. - - We do need to modify rm_vm_call0 to take an argument for whether - keyword arguments are used, since the call_type is no longer - available at that point. Use the passed in value to set the - appropriate keyword flag in both calling and ci_entry. - -commit e3cb3e11af4323aba002a84044375180dd24248c - Author: Jeremy Evans - Date: 2019-09-04 03:55:32 +0900 - - Set VM_FRAME_FLAG_CFRAME_KW if kw_splat set in vm_yield_with_cfunc - -commit fd2ef1a9bfa489842472d183ea10b6fd9838c460 - Author: Jeremy Evans - Date: 2019-09-04 03:50:46 +0900 - - Add VM_NO_KEYWORDS - - I think this is easier to read than using literal 0 with comments - in every case where it is used. - -commit ce04392d8d4f8cf14c70bbf1ad3544c7db4e1671 - Author: Yusuke Endoh - Date: 2019-09-04 01:32:42 +0900 - - Propagate kw_splat information - - The kw_splat flag is whether the original call passes keyword or not. - Some types of methods (e.g., bmethod and sym_proc) drops the - information. This change tries to propagate the flag to the final - callee, as far as I can. - -commit 3754e155309ed430250781c616a6e52b54ef511d - Author: Nobuyoshi Nakada - Date: 2019-08-29 22:07:45 +0900 - - Warn local variables which conflict with new numbered parameters - -commit 092f31e7e23c0ee04df987f0c0f979d036971804 - Author: Aaron Patterson - Date: 2019-09-06 04:44:23 +0900 - - Reverting node marking until I can fix GC problem. - - Looks like we're getting WB misses during stressful GC on startup. I am - investigating. - -commit f211ab20157a840770567ea182b1372e339cd82a - Author: Aaron Patterson - Date: 2019-09-06 03:37:03 +0900 - - I forgot to add `break` in my case statements - - Give me a break. - -commit 8f096226e1b76f95f4d853d3dea2bc75eeeb5244 - Author: Aaron Patterson - Date: 2019-09-06 03:04:43 +0900 - - Stash tmpbuffer inside internal structs - - I guess those AST node were actually used for something, so we'd better - not touch them. Instead this commit just puts the tmpbuffer inside a - different internal struct so that we can mark them. - -commit 8cd845aa5b69e49c1092a482f8c14f85f899e038 - Author: Aaron Patterson - Date: 2019-09-05 09:00:09 +0900 - - add debugging code to the mark function - -commit 01aa2462b5abb6833af83f47961932ebca587573 - Author: Aaron Patterson - Date: 2019-09-05 08:21:05 +0900 - - lazily allocate the mark array - -commit 429ed8d587423414fbbf2f562479c69562d52598 - Author: Aaron Patterson - Date: 2019-09-05 06:37:13 +0900 - - Don't change DSTR nodes to ARRAY nodes - - DSTR nodes are allocated in to the "markable" bucket where ARRAY nodes - are not. Switching buckets can cause errors during GC. - -commit 545b6db3fb367944f72cee5d41892eed63574634 - Author: Aaron Patterson - Date: 2019-09-05 01:38:17 +0900 - - Create two buckets for allocating NODE structs - - This commit adds two buckets for allocating NODE structs, then allocates - "markable" NODE objects from one bucket. The reason to do this is so - when the AST mark function scans nodes for VALUE objects to mark, we - only scan NODE objects that we know to reference VALUE objects. If we - *did not* divide the objects, then the mark function spends too much - time scanning objects that don't contain any references. - -commit f0fd1c0cd8d34b870a3011a36f5179d1b5f3547d - Author: Aaron Patterson - Date: 2019-09-05 08:00:19 +0900 - - Stash the imemo buf at the end of the ID list - - Now we can reach the ID table buffer from the id table itself, so when - SCOPE nodes are marked we can keep the buffers alive. This eliminates - the need for the "mark array" during normal parse / compile (IOW *not* - Ripper). - -commit 64817a7cfd4a258b45356e6da8fbdd0040b3231b - Author: Aaron Patterson - Date: 2019-09-04 06:01:07 +0900 - - Mark some tmpbufs via node objects - - This way we don't need to add the tmpbufs to a Ruby array for marking - -commit 581fcde0884e493206b04b3e6b7a069b941dfe46 - Author: Aaron Patterson - Date: 2019-08-30 07:22:41 +0900 - - Directly mark node objects instead of using a mark array - - This patch changes the AST mark function so that it will walk through - nodes in the NODE buffer marking Ruby objects rather than using a mark - array to guarantee liveness. The reason I want to do this is so that - when compaction happens on major GCs, node objects will have their - references pinned (or possibly we can update them correctly). - -commit 70d3596a4a2ef023243bf4805ce2a9cd6fdc0487 - Author: git - Date: 2019-09-06 01:58:03 +0900 - - * 2019-09-06 [ci skip] - -commit c6464c44c02fdbb597ca8027af0bc0db28d56f66 - Author: Jeremy Evans - Date: 2019-09-05 04:00:25 +0900 - - Fix code locations of array node inside hash node when multiple kw splats - - This is broken at least since 2.5 (I didn't check earlier versions). - It resulted in failure in test_ast.rb when the tests were added before - the parser change. - - Basically, in remove_duplicate_keys, if the node is modified, set - the location information to the previous location information. The - removal of keys should not affect the location in the code. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2428 - -commit 1d5066efb08cbb328ba528a5f8be1708584b659f - Author: Jeremy Evans - Date: 2019-09-05 02:54:12 +0900 - - Make m(**{}) mean call without keywords - - Previously, **{} was removed by the parser: - - ``` - $ ruby --dump=parse -e '{**{}}' - @ NODE_SCOPE (line: 1, location: (1,0)-(1,6)) - +- nd_tbl: (empty) - +- nd_args: - | (null node) - +- nd_body: - @ NODE_HASH (line: 1, location: (1,0)-(1,6))* - +- nd_brace: 1 (hash literal) - +- nd_head: - (null node) - ``` - - Since it was removed by the parser, the compiler did not know - about it, and `m(**{})` was therefore treated as `m()`. - - This modifies the parser to not remove the `**{}`. A simple - approach for this is fairly simple by just removing a few - lines from the parser, but that would cause two hash - allocations every time it was used. The approach taken here - modifies both the parser and the compiler, and results in `**{}` - not allocating any hashes in the usual case. - - The basic idea is we use a literal node in the parser containing - a frozen empty hash literal. In the compiler, we recognize when - that is used, and if it is the only keyword present, we just - push it onto the VM stack (no creation of a new hash or merging - of keywords). If it is the first keyword present, we push a - new empty hash onto the VM stack, so that later keywords can - merge into it. If it is not the first keyword present, we can - ignore it, since the there is no reason to merge an empty hash - into the existing hash. - - Example instructions for `m(**{})` - - Before (note ARGS_SIMPLE): - - ``` - == disasm: #@-e:1 (1,0)-(1,7)> (catch: FALSE) - 0000 putself ( 1)[Li] - 0001 opt_send_without_block , - 0004 leave - ``` - - After (note putobject and KW_SPLAT): - - ``` - == disasm: #@-e:1 (1,0)-(1,7)> (catch: FALSE) - 0000 putself ( 1)[Li] - 0001 putobject {} - 0003 opt_send_without_block , - 0006 leave - ``` - - Example instructions for `m(**h, **{})` - - Before and After (no change): - - ``` - == disasm: #@-e:1 (1,0)-(1,12)> (catch: FALSE) - 0000 putself ( 1)[Li] - 0001 putspecialobject 1 - 0003 newhash 0 - 0005 putself - 0006 opt_send_without_block , - 0009 opt_send_without_block , - 0012 opt_send_without_block , - 0015 leave - ``` - - Example instructions for `m(**{}, **h)` - - Before: - - ``` - == disasm: #@-e:1 (1,0)-(1,12)> (catch: FALSE) - 0000 putself ( 1)[Li] - 0001 putspecialobject 1 - 0003 newhash 0 - 0005 putself - 0006 opt_send_without_block , - 0009 opt_send_without_block , - 0012 opt_send_without_block , - 0015 leave - ``` - - After (basically the same except for the addition of swap): - - ``` - == disasm: #@-e:1 (1,0)-(1,12)> (catch: FALSE) - 0000 putself ( 1)[Li] - 0001 newhash 0 - 0003 putspecialobject 1 - 0005 swap - 0006 putself - 0007 opt_send_without_block , - 0010 opt_send_without_block , - 0013 opt_send_without_block , - 0016 leave - ``` - - Notes: - Merged: https://github.com/ruby/ruby/pull/2428 - -commit 433c9c00d96124e3b416d0a20ff795b0ad4273fa - Author: Yusuke Endoh - Date: 2019-09-05 22:14:01 +0900 - - Add a temporal stack dumper for debugging on trunk-mjit - - This must be definitely removed after we collect the stack traces :-) - http://ci.rvm.jp/results/trunk-mjit@silicon-docker/2245710 - -commit 0036aa35321b036be6e49e07b19f92c061ca4135 - Author: yuuji.yaginuma - Date: 2019-09-05 08:33:43 +0900 - - Add version that FreeBSD supports `CLOCK_PROCESS_CPUTIME_ID` [ci skip] - - Seems FreeBSD already supported `CLOCK_PROCESS_CPUTIME_ID`. - That added by https://reviews.freebsd.org/rS239347 and the doc was updated - by https://reviews.freebsd.org/rS315694. - - I confirmed `CLOCK_PROCESS_CPUTIME_ID` constant exists in 9.3.0 branch. - https://github.com/freebsd/freebsd/blob/release/9.3.0/sys/sys/time.h#L269 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2429 - -commit 1c4af1a77fb2dad27d523fe5d97ea4a27b145e3c - Author: David Rodríguez - Date: 2019-05-23 18:40:27 +0900 - - Add tests for `File.absolute_path?` - - [Feature #15868] - -commit 2a166cfea22b90e39e3fe9bafab6b806ed4813f6 - Author: David Rodríguez - Date: 2019-09-05 20:00:50 +0900 - - Add `File.absolute_path?` (#2198) - - In order to check whether a path is absolute or not in a portable way. - - [Feature #15868] - -commit d9e6315177be2a1264213a1e7cb215312a23384a - Author: David Rodríguez - Date: 2019-08-23 00:36:29 +0900 - - [rubygems/rubygems] Bump rubocop to 0.74.0 and fix new offenses - - https://github.com/rubygems/rubygems/commit/d4fc383497 - -commit 0b9b0774c3dc0c4113335a57717bbc9d3d9595e8 - Author: Alexander Pakulov - Date: 2019-09-03 03:36:08 +0900 - - [rubygems/rubygems] Minor fix - - https://github.com/rubygems/rubygems/commit/95c1f4e179 - -commit 565828a778ab57affad9216721659a489176bf2d - Author: bronzdoc - Date: 2019-08-24 07:41:44 +0900 - - [rubygems/rubygems] Fix Layout/SpaceAroundOperators: Operator = should be surrounded by a single space. - - https://github.com/rubygems/rubygems/commit/eaa38ebeb1 - -commit 73574756f944280b920322d0034772c9aeb2bdac - Author: bronzdoc - Date: 2019-08-24 06:21:57 +0900 - - [rubygems/rubygems] Add missing parentheses - - https://github.com/rubygems/rubygems/commit/f5972338e0 - -commit 92be07b1e1a9ca3b0e2588817629c23ab1201701 - Author: bronzdoc - Date: 2019-08-24 06:19:54 +0900 - - [rubygems/rubygems] Remove unnecessary gem_name method - - https://github.com/rubygems/rubygems/commit/d1bb122651 - -commit b11cfed4c4fae51f7111c6cc0a3ec436a9c8faa3 - Author: bronzdoc - Date: 2019-08-22 14:35:39 +0900 - - [rubygems/rubygems] Error out if there are multiple gemspecs and no gemspec is specified - - https://github.com/rubygems/rubygems/commit/547947bbf0 - -commit 400d693863cc8b500d9bcaee9529a395f3fe6da7 - Author: bronzdoc - Date: 2019-08-19 06:25:29 +0900 - - [rubygems/rubygems] Remove useless gem setup - - https://github.com/rubygems/rubygems/commit/c8913e37a7 - -commit 6cacbf542caa9954bf760dd10a6ae3c92c9f15e4 - Author: bronzdoc - Date: 2019-08-19 06:19:52 +0900 - - [rubygems/rubygems] Test building a gem with multiple gemspec without a gem name specified - - https://github.com/rubygems/rubygems/commit/38c72fd145 - -commit a02da1012bb391ae01affac7454ea28996fd7dbf - Author: bronzdoc - Date: 2019-08-19 05:57:41 +0900 - - [rubygems/rubygems] Build the first gemspec we found if no gemspec is specified - - https://github.com/rubygems/rubygems/commit/ab186266b7 - -commit bcf51dd76332bc28ee75494c51828a36774ff99f - Author: bronzdoc - Date: 2019-08-19 05:04:08 +0900 - - [rubygems/rubygems] Improve gemspec assignment and error message - - https://github.com/rubygems/rubygems/commit/dc70c5a192 - -commit 68937fe0e4bf6e0943fe165e0a157058cff760fe - Author: bronzdoc - Date: 2019-08-19 04:53:41 +0900 - - [rubygems/rubygems] Make passing a gem name to be optional - - https://github.com/rubygems/rubygems/commit/4ba4ffebbe - -commit 95326150faa0854ed6cd0877e0069d2080bc5005 - Author: bronzdoc - Date: 2019-08-17 23:54:17 +0900 - - [rubygems/rubygems] Move build gem logic to its own method - - https://github.com/rubygems/rubygems/commit/a16eacd650 - -commit fea91d69a3b4aebd5e69058f9ec51adf2896cdfd - Author: David Rodríguez - Date: 2019-08-22 03:17:11 +0900 - - [rubygems/rubygems] Don't fail when `uninstall --all` with default gem - - Instead, display an informative message saying that uninstallation of - specific versions is being skipped because of being default gems. - - https://github.com/rubygems/rubygems/commit/b44845aa1d - -commit f9f6a3d793186bd4b8897f775dcdcc9719361c11 - Author: David Rodríguez - Date: 2019-08-23 00:32:47 +0900 - - [rubygems/rubygems] Little refactor to avoid rubocop's false positive - - Otherwise it detects duplicate methods here, because it doesn't see that - we are reopening the class in two different places. - - https://github.com/rubygems/rubygems/commit/ae3fb47f5f - -commit d84b9b6d0a938cec9f0c1266702d9c4aecc0423a - Author: Alexander Pakulov - Date: 2019-08-22 07:19:10 +0900 - - [rubygems/rubygems] Use IAM role to extract security-credentials for EC2 instance - - https://github.com/rubygems/rubygems/commit/9a401646e1 - -commit d219be4a1c237356670ebafd415e983433362e72 - Author: David Rodríguez - Date: 2019-08-22 03:05:24 +0900 - - [rubygems/rubygems] Move empty check earlier - - https://github.com/rubygems/rubygems/commit/fc224e9717 - -commit 7a2bd91ed24cceecc627df574fc109cdd6b258dd - Author: Kazuhiro NISHIYAMA - Date: 2019-09-05 17:51:02 +0900 - - Try to fix `invalid option` - - https://github.com/ruby/ruby/runs/212727409#step:11:67 - ``` - invalid option: -j5 - ``` - -commit f4df9fb46b35335530fd99fabfa65772e6aaf1df - Author: Kazuhiro NISHIYAMA - Date: 2019-09-05 17:47:51 +0900 - - Change name to `Tests (test-bundled-gems)` in macos.yml too - -commit 436099ee0459ee51ceccb3eb343a5f281556bf61 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-05 15:02:07 +0900 - - add tests - - Some coverage improvements. - -commit 8a608f1b1f9812d0bd1d7589a03e8abd653b8364 - Author: Nobuyoshi Nakada - Date: 2019-09-05 14:37:05 +0900 - - Removed -git option of make-snapshot - - Git is not for direct access to a remote repository. - Most of its operations need a local clone. - -commit 41bc766763dba63ae2529f2f9070b8e26399745c - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-05 14:29:11 +0900 - - interesting (but annoying) tidbit warning suppressed - - This changeset is to suppress clang's -Wimplicit-int-float-conversion - warning. - - In 64 bit signed long and IEEE 754 double combination (== almost - everyone these days), LONG_MAX is 9,223,372,036,854,775,807. This - value is _not_ exactly representable by double. The nearest value - that a double can represent is 9,223,372,036,854,775,808. It is one - greater than LONG_MAX. Let's call this value the "x". - - The expression `LONG_MAX < yi` is a long versus double comparison. - According to ISO/IEC 9899:1999 Section 6.3.1.8 (that defines the - "usual rithmetic conversions"), The long value must first be casted - into double. Because FLT_ROUNDS is typically 1 ("round to the - nearest" mode), the conversion yields the "x" value shown above. So - the comparison is in fact `x < yi`. - - This comparison is false for yi == x situation, i.e. yi is still - bigger than LONG_MAX. On such situation the `yn = (long)yi;` - statement that appear several lines below renders underfined - behaviour, as per ISO/IEC 9899:1999 Section 6.3.1.3. - - To remedy, we just change the comparison from `<` to `<=` so that - yi == x situation can properly be handled. - -commit dd2b9d4a96e6c9784daf645efc79bef11eb1decb - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-04 15:55:02 +0900 - - hide rb_funcallv_with_cc from public - - Requested by ko1. Also, because now that this function is internal - use only, why not just directly use struct rb_call_cache to purge - the ZALLOC. - -commit b005d7c2e208790b89b332d5f8ca56334039d6ae - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-04 15:10:10 +0900 - - use existing vm_search_method() - - Ko1 plans to implement Guild. That can interface the caching - mechanism introduced here. To prevent future breakage we would - better avoid rolling our own code here. Instead use the existing - vm_search_method() which would be modified by him. - - This commit deletes some asserions, but they are in fact checked - inside of vm_search_method(). - -commit 7a1f650c130768eee07b8f64e73e218a9d9f8638 - Author: git - Date: 2019-09-05 08:33:02 +0900 - - * 2019-09-05 [ci skip] - -commit 9f59d30daa0d2fba5c98a9b6148b935baaae67da - Author: Nobuyoshi Nakada - Date: 2019-09-04 23:54:41 +0900 - - Separate VCS::DEBUG_OUT - -commit f6da4a544760e00d932fea9a586bd869e82ad339 - Author: Akinori MUSHA - Date: 2019-09-04 16:07:40 +0900 - - Describe #eager in the Enumerator::Lazy section - -commit 1d4bd229b898671328c2a942b04f08065c640c28 - Author: Akinori MUSHA - Date: 2019-06-05 20:39:21 +0900 - - Implement Enumerator::Lazy#eager [Feature #15901] - -commit 2a6457b5b7d67378528235cee7b9cb93fed00204 - Author: Urabe, Shyouhei - Date: 2018-10-11 11:47:49 +0900 - - add rb_funcallv_with_cc() - - Why not cache the method entry at each caller site. The void** - is in fact a method entry, but this struct is hidden from ruby.h - so intentionally left opaque. - - Notes: - Merged: https://github.com/ruby/ruby/pull/1981 - -commit ccad34f4533ffe532fea796def06808dc5a85877 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-04 12:51:39 +0900 - - Add TEST_BUNDLED_GEMS_ALLOW_FAILURES=minitest - -commit 967ef0d4f6c84b5c204247a8a960656d6264ef49 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-04 12:36:45 +0900 - - Use `git pull` instead of `git fetch` if master branch - -commit 1e30d0af7d0258bd3a9e6b072e6517f8db78f853 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-04 12:03:28 +0900 - - `$JOBS` does not set in `env:` - -commit b0d0b850bc61e158fb7caac4123af824b12938f1 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-04 11:50:37 +0900 - - Use RUBY_TESTOPTS instead of TESTOPTS - - https://github.com/ruby/ruby/pull/2417#issuecomment-526884646 - > `TESTOPTS` is defaulted to `$(RUBY_TESTOPTS)` in `common.mk` file. - > Use the latter name to pass options via an environment variable. - -commit c14b67b2a8cf60b37cfb221d8b97c6eb91833522 - Author: Takashi Kokubun - Date: 2019-09-04 10:53:20 +0900 - - Check frozen flag on MJIT setinstancevariable - - It does not seem to have a significant performance impact, hopefully? - - ``` - $ benchmark-driver -v benchmark.yml --rbenv 'before --jit;after --jit' --repeat-count=24 --output=all - before --jit: ruby 2.7.0dev (2019-09-03T21:02:24Z master 77596fb7a9) +JIT [x86_64-linux] - after --jit: ruby 2.7.0dev (2019-09-04T01:54:44Z master 7363e22d79) +JIT [x86_64-linux] - Calculating ------------------------------------- - before --jit after --jit - Optcarrot Lan_Master.nes 48.44054595799523 71.67010255902900 fps - 71.32797692837639 71.97846863769546 - 72.51921961607691 78.87360980544105 - 73.54082925611047 79.80408132389941 - 74.03503843709451 79.85739528572826 - 74.04863857926493 79.89850834901381 - 75.30266276129467 80.34607233076015 - 75.69063990896244 80.88474397425360 - 75.70458132587405 81.09234267781642 - 77.39842764662852 82.13766823612643 - 77.76922944068329 82.20398304840373 - 81.17984044023393 82.26722630628272 - 82.85235776076533 82.71375902781254 - 83.04906099135320 82.75893420702198 - 83.10214168136230 82.79668965325972 - 83.71456007558125 82.85131667916379 - 84.06658306760725 82.95676565411722 - 84.25690684305728 83.19972846225775 - 84.27938663923503 83.28510503845854 - 84.45467716218090 83.41003730434703 - 84.51563186125925 83.67773614721280 - 84.56139892968321 84.02082201151110 - 84.69819452180658 84.10495346787033 - 84.78125989622576 84.47867803506055 - ``` - - Note for backporter: - test_jit's `success_count` would be 1 in Ruby 2.6, since 2.7 introduced - "MJIT recompile" on JIT-ed code cancel. - - [Bug #16139] - -commit 77596fb7a91cc119b25ac9e19b3c8682709765b4 - Author: Jeremy Evans - Date: 2019-09-04 06:02:24 +0900 - - Do not turn on keyword_init for Struct subclass if keyword hash is empty - - This was accidentally turned on because there was no checking for - Qundef. - - Also, since only a single keyword is currently supported, simplify - the rb_get_kwargs call. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2423 - - Merged-By: jeremyevans - -commit 39c3252cd175074581855e5f9681cc723c15ff72 - Author: Jeremy Evans - Date: 2019-09-04 03:32:02 +0900 - - Merge pull request #2422 from jeremyevans/rb_keyword_given_p - - Add rb_keyword_given_p to the C-API - - Notes: - Merged-By: jeremyevans - -commit f702cd6ace7e134714d42ffb1606c25b5ded24c7 - Author: git - Date: 2019-09-04 03:31:11 +0900 - - * 2019-09-04 [ci skip] - -commit a7d7a0df91805e59fe6b383ea7ecdad509222966 - Author: Jeremy Evans - Date: 2019-09-03 05:22:26 +0900 - - Fix Enumerator::Lazy#{to_enum,enum_for} where method is defined in Lazy - - Previously, passing to_enum/enum_for a method that was defined in - Lazy itself returned wrong results: - - [1,2,3].to_enum(:map).to_a - # => [1, 2, 3] - [1,2,3].lazy.to_enum(:map).to_a - # => [] - - I'm not sure why methods that are designed to be lazy do not work - with to_enum/enum_for. However, one possible way to work around - this bug is to have to_enum/enum_for use the implementation found - in Enumerable/Enumerator, which is what this commit does. - - While this commit works around the problem, it is a band-aid, not a - real fix. It doesn't handle aliases of Enumerable::Lazy methods, - for instance. A better fix would be appreciated. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2421 - -commit 4a3972c2612c3e3695d7f67b096b2ef8cbb6649a - Author: Jeremy Evans - Date: 2019-09-03 05:20:44 +0900 - - Remove bad expectation in spec - - This spec should not be checking where methods are defined, only - that the method works as expected (returns a Lazy instance). - - Notes: - Merged: https://github.com/ruby/ruby/pull/2421 - -commit e94ac03eb0d07af3cbff20194acf479bf8851c39 - Author: Jeremy Evans - Date: 2019-08-09 05:09:17 +0900 - - Make Enumerator::Lazy#with_index be lazy - - Previously, Enumerator::Lazy#with_index was not defined, so it - picked up the default implementation from Enumerator, which was - not lazy. - - Based on earlier patch from nobu. - - Fixes [Bug #7877] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2421 - -commit fb67d4fc77f211cfec6b2065787d9212f4e2154b - Author: Takashi Kokubun - Date: 2019-09-03 21:49:51 +0900 - - Move an unstable bootstraptest to pending - - This has been unstable on AppVeyor mswin since the introduction - 3fd83cb6fcc483d2eac0795bc139c521a3a59bd2. - https://ci.appveyor.com/project/ruby/ruby/builds/27103307/job/j7xwjmsos2k22cck - - Let's have it in pending.rb to be fixed. - -commit ecc37ee67b90426198bd768d0bf036663e301d06 - Author: Takashi Kokubun - Date: 2019-09-03 21:38:32 +0900 - - Stop testing inexistent instructions - -commit beaabd23087a54364bc8fc8aa7a45dd9f425e19b - Author: Takashi Kokubun - Date: 2019-09-03 21:08:07 +0900 - - Unify SUPPORT_JOKE and OPT_SUPPORT_JOKE - - for simplicity and consistency. - - Now SUPPORT_JOKE needs to be prefixed with OPT_ to make the config - visible in `RubyVM::VmOptsH`, and the inconsistency was introduced. - - As it has never been available for override in configure (no #ifndef - guard), it should be fine to rename the config. - -commit 7cb19b3f5bf0a5dcee0e8444b920e01e7d4e7fae - Author: Takashi Kokubun - Date: 2019-09-03 21:03:10 +0900 - - Roughly retry choco install commands - - to deal with random failures: - https://github.com/ruby/ruby/runs/210617845 - -commit afe8bf24894d742fa43bba3331470f428d819eb0 - Author: Takashi Kokubun - Date: 2019-09-03 20:33:46 +0900 - - Try extending timeout of IO.select - - hoping to stabilize: - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5d6df8a8a952c20008acf75b?step=5d6df90e4971a6000714c627 - -commit 36a0c668b69d90c881246324e76cdb8889047026 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-03 18:36:08 +0900 - - Remove SKIP_DOXYGEN because job.env does not set in `if:` - -commit 83889292f5e0944d6762228c9ca81318f618aa4e - Author: Naohisa Goto - Date: 2019-09-03 16:51:01 +0900 - - Examine TestIO#test_select_exceptfds on Solaris with 1 byte data - - On Solaris, it seems that the select(3C) in this test works only - when sending 1 byte out-of-band data, though I cannot investigate - the cause. The behavior is observed on a Solaris 10 server in - addition to Solaris 11 on which the test had been skipped. - -commit e913fa94d30e5d3007fe52f5d7840576c0f86c78 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-09-03 12:18:36 +0900 - - delete ruby_eval_string_from_file_protect - - Not used from anywhere. - -commit 1a9cc3b27c020c33c87d8b4fe659243aacfeedf3 - Author: Takashi Kokubun - Date: 2019-09-03 02:51:48 +0900 - - Avoid defining unused instructions - - Notes: - Merged: https://github.com/ruby/ruby/pull/2420 - -commit 355ccdeae52cde250f09675e9d5e65b3ddc41f2e - Author: d0 (Daisuke Fujimura) - Date: 2019-09-03 12:52:04 +0900 - - Disable method definition type checks on Cygwin too - - [Bug #16134] - -commit 547887138f19959f649b1c0dbcde5659ae3878ed - Author: Yusuke Endoh - Date: 2019-09-03 12:27:53 +0900 - - test/ruby/test_fiber.rb: reduce the count of object creation to cause GC - - The test consistently fails on OpenBSD. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20190903T010009Z.fail.html.gz - ``` - 1) Failure: - TestFiber#test_fork_from_fiber [/home/chkbuild/chkbuild/tmp/build/20190903T010009Z/ruby/test/ruby/test_fiber.rb:327]: - [ruby-core:41456]. - <0> expected but was - <1>. - ``` - -commit e6c4ea22d62c95ce0590849219da505fef5a538e - Author: Nobuyoshi Nakada - Date: 2019-09-03 12:28:00 +0900 - - Touch tar file itself to make gz file hash stable - -commit b0a7221dcf998d72efe57cd7ab75260d80941109 - Author: Nobuyoshi Nakada - Date: 2019-09-03 11:43:38 +0900 - - Touch the toplevel directory too - -commit 542a1ade8033d03513647ace64e50dbf31cb5e68 - Author: Nobuyoshi Nakada - Date: 2019-09-03 11:31:14 +0900 - - --date=iso-local does not work with old git - -commit 703f0cd3d007f1ada69957a529870b07fa053230 - Author: Nobuyoshi Nakada - Date: 2019-09-03 11:30:40 +0900 - - Do not keep tar file by the default - -commit c181ecc161c5482426f045322cf00d00b15d96c6 - Author: Nobuyoshi Nakada - Date: 2019-09-03 11:14:07 +0900 - - Align timestamps to make tarball stable - -commit 1994adf938afcdc562f87497156e6d4900f3f06b - Author: Jeremy Evans - Date: 2019-07-16 06:03:28 +0900 - - Make Array#uniq return subclass instance if called on subclass instance - - Previously, Array#uniq would return subclass instance if the - length of the array were 2 or greater, and would return Array - instance if the length of the array were 0 or 1. - - Fixes [Bug #7768] - -commit a848b62819c78e12c420b1ed29605242e292358b - Author: Takashi Kokubun - Date: 2019-09-03 01:53:47 +0900 - - Make the rb_vmdebug_debug_print_post declaration - - consistent with the definition - -commit 1a5a01e9ce9bf69944e4e37a33c8b044657a200a - Author: Takashi Kokubun - Date: 2019-09-03 01:39:00 +0900 - - Add insn tests for newarraykwsplat - -commit e13da00824e0979b2417bcffe94a8668cab7532c - Author: Takashi Kokubun - Date: 2019-09-03 01:25:58 +0900 - - Explain how to run an individual btest in help - -commit 6c3ab99eae1fa84dc28635eb90170b03408b94fb - Author: Takashi Kokubun - Date: 2019-09-03 01:11:18 +0900 - - Now it's always os: linux - -commit 52f0c31558f0870c16da86b8abe524bd7040ea27 - Author: Takashi Kokubun - Date: 2019-09-03 01:06:29 +0900 - - Fix accidental leftover for Linux - - In 91aa8bfff8, my understanding of the branch was inverted. - -commit 91aa8bfff8a9f9c0af96915c120d863fc474e8d5 - Author: Takashi Kokubun - Date: 2019-09-03 01:01:47 +0900 - - Drop unstable Travis osx in favor of GitHub Actions - - For some reason, the Travis osx environment has been really unstable. - It failed on today's cron too: - https://travis-ci.org/ruby/ruby/builds/579843163 - - As we have almost the same test environment (including OpenSSL version) - in GitHub Actions and it seems to be more stable and faster, I think - there's no motivation to maintain Travis osx CI environment. - - By removing this, we'd be able to simplify .travis.yml as well. - -commit 1d68d29c143231303504e28833089485a2355aec - Author: Takashi Kokubun - Date: 2019-09-03 00:36:18 +0900 - - Drop obsoleted IRC channel reference - - travis-ci user does not live in #ruby-ja. Therefore the notification - isn't working anymore. - -commit f1d8d0f47b8018a15d024e1beb5c06f9c4b901d7 - Author: Takashi Kokubun - Date: 2019-09-03 00:30:17 +0900 - - Drop obsoleted branch references - - We don't have topic branches on ruby.git anymore. - -commit d83ade1db59a21b675b6386b94b56eabb90ae83e - Author: Nobuyoshi Nakada - Date: 2019-09-02 23:42:21 +0900 - - Use -z option for git-log - -commit f560609d66502101264706877577220e3ebf5a38 - Author: Jeremy Evans - Date: 2019-09-03 00:21:30 +0900 - - Merge pull request #2418 from jeremyevans/array-empty-kwsplat - - Ignore empty keyword splats in arrays - - Notes: - Merged: https://github.com/ruby/ruby/pull/2418 - - Merged-By: jeremyevans - -commit be86591458c5f29db0d97601f29e15e43d5fe23c - Author: git - Date: 2019-09-03 00:08:39 +0900 - - * 2019-09-03 [ci skip] - -commit 60a49a6ff95ece1a13004a53db001bfde2373afc - Author: Takashi Kokubun - Date: 2019-09-03 00:07:36 +0900 - - Fix SUPPORT_JOKE CI on Travis - - It looks like a flag which cannot be enabled on configure. - -commit 834e77186086a4ae1fc73edbe035e90157d79fab - Author: Takashi Kokubun - Date: 2019-09-02 23:48:38 +0900 - - Run daily cron against SUPPORT_JOKE - -commit ca8ae759d0dee6840aa446499a9e1752f74da500 - Author: Takashi Kokubun - Date: 2019-09-02 23:35:51 +0900 - - Fix compilation error in SUPPORT_JOKE - - This seems to have been broken since 4e15be8bade. - -commit 6a9c5ef186db70dc60fcd42ec820767d9a75543a - Author: Nobuyoshi Nakada - Date: 2019-09-02 23:10:58 +0900 - - Extract git commit log as raw format like git-svn for ChangeLog - -commit 53a7abe2cd6bd07b816a7a7e2235befd5e1b4446 - Author: Yusuke Endoh - Date: 2019-09-02 22:30:12 +0900 - - test/drb/drbtest.rb: Skip test_06_timeout on Solaris10s - - The test seems to have a race condition, which fails on very slow - machine like Solaris10s. So skip it. - - In addition, this change restores timeout guard that was removed at - 0660d7cb538cf5284d50f66adfcbd78609839715. This is because the test gets - stuck forever when something wrong occurs. It is better to fail the - test than stuck. - -commit 8b2e1ca10ecf92ad402decd6b1eab586eded0ddb - Author: Nobuyoshi Nakada - Date: 2019-09-02 16:47:12 +0900 - - Do not clear backtrace in Exception#exception - - [Bug #15558] - -commit 8e38d4c78c1a9b45f604963f85995e9a817ee72c - Author: Nobuyoshi Nakada - Date: 2019-09-02 16:46:28 +0900 - - Rewrote using assert_separately - -commit 6f206b8ec6f945804c56cf8249739c6e94ed65f6 - Author: Nobuyoshi Nakada - Date: 2019-09-02 15:08:53 +0900 - - Prohibit nul-separated glob pattern [Feature #14643] (#2419) - - Notes: - Merged-By: nobu - -commit 633ae3278ecce7c2b98fa1aa6106f963894c538a - Author: Shugo Maeda - Date: 2019-09-02 14:43:35 +0900 - - Add Net::FTP#features and Net::FTP#option - - Patch by darkphnx (Dan Wentworth) . Thanks! - [Feature #15964] - -commit e9b271d1e2251a2e2f613431ae2d9eb2a14ba0a9 - Author: Nobuyoshi Nakada - Date: 2019-09-02 14:31:22 +0900 - - Get rid of interpreting BTS references as label-list [ci skip] - -commit 6724b1f83d2cad57bbcbcdc9756532d825b0c592 - Author: Jeremy Evans - Date: 2019-09-02 14:35:38 +0900 - - Revert "Make Enumerator::Lazy#with_index be lazy" - - This reverts commit 83498854eb5a824f1f83c31fac18c9279f9ee10d. - - This didn't pass rubyspec. - -commit c69545ae32a5ddf928e8992a0d2cf39648c2b555 - Author: Takashi Kokubun - Date: 2019-09-02 14:33:29 +0900 - - Fix opt_regexpmatch1 references - -commit 83498854eb5a824f1f83c31fac18c9279f9ee10d - Author: Jeremy Evans - Date: 2019-08-09 05:09:17 +0900 - - Make Enumerator::Lazy#with_index be lazy - - Previously, Enumerator::Lazy#with_index was not defined, so it - picked up the default implementation from Enumerator, which was - not lazy. - - Based on earlier patch from nobu. - - Fixes [Bug #7877] - -commit 79e3d6bb9e007fc97153c1097daf78e9a201a642 - Author: Urabe, Shyouhei - Date: 2018-09-19 16:46:44 +0900 - - fix shortcut condition - - rb_reg_match expects its first argument to be a Regexp instance. - Should check that. - - Notes: - Merged: https://github.com/ruby/ruby/pull/1959 - -commit ec80d5c4f322b9ae02babd32a491bd05807a8155 - Author: Urabe, Shyouhei - Date: 2018-09-19 11:46:21 +0900 - - delete unused function - - Notes: - Merged: https://github.com/ruby/ruby/pull/1959 - -commit 8ad7fafcddece2096b748178df9a3318cb1ba3ae - Author: Urabe, Shyouhei - Date: 2018-09-19 10:41:56 +0900 - - opt_regexpmatch1 is actually making things slower. - - ---- - - trunk: ruby 2.6.0dev (2018-09-18 trunk 64767) [x86_64-darwin15] - ours: ruby 2.6.0dev (2018-09-18 opt_regexpmatch 64775) [x86_64-darwin15] - last_commit=opt_regexpmatch1 is actually making things slower. - Calculating ------------------------------------- - trunk ours - Optcarrot Lan_Master.nes 33.877 35.282 fps - - Comparison: - Optcarrot Lan_Master.nes - ours: 35.3 fps - trunk: 33.9 fps - 1.04x slower - - Notes: - Merged: https://github.com/ruby/ruby/pull/1959 - -commit ff462bc6c3d88bab9df4c8d17b420f21223984c2 - Author: Takashi Kokubun - Date: 2019-09-02 13:46:29 +0900 - - Add a benchmark for opt_regexpmatch2 - - vm2_regexp was for opt_regexpmatch1. - -commit 1f636e74e661e8976d8884a1dcb7027a97cb6a83 - Author: Nobuyoshi Nakada - Date: 2019-09-02 12:15:35 +0900 - - Set mtime of checked out files to past time - - instead of waiting 2 seconds, if possible. - -commit 63ab7046a1a5c374a52dfa79406fe52d92d80344 - Author: Kazuhiro NISHIYAMA - Date: 2019-09-02 10:02:17 +0900 - - Skip POINTOPOINT of IPv4 too instead of IPv6 only - - Fix following error on `utun*`: - ``` - 1) Error: - TestSocket#test_udp_server: - Errno::ECONNREFUSED: Connection refused - recvmsg(2) - ``` - -commit f58db5a6f5c7b5c2f5f8471adcf8b1fe9577c01a - Author: Jeremy Evans - Date: 2019-09-02 11:46:19 +0900 - - Simplify setting of VM_CALL_KW_SPLAT in vm_call_method_missing - - Pointed out by ko1. - -commit ca11a7d74e5e992cf4b84180727259095f4c1e75 - Author: Jeremy Evans - Date: 2019-09-02 10:54:30 +0900 - - Fix method name in test to not override existing method name - -commit 3fde9ef93781585a675b3e7184ad3a51072fb95f - Author: Jeremy Evans - Date: 2019-09-02 08:08:42 +0900 - - Fix keyword argument separation warning in method_missing - - vm_call_method_missing was dropping VM_CALL_KW_SPLAT, so this just - makes it not drop it, to get the same behavior as calling the method - directly. - -commit 85dc89c90747d492e5ecbbbfc631a55088195f61 - Author: aycabta - Date: 2019-09-02 06:37:25 +0900 - - Treat Japanese IME on/off code correctly - -commit b0d885da765d3212f807ae83968082800df6422e - Author: git - Date: 2019-09-02 00:42:54 +0900 - - * 2019-09-02 [ci skip] - -commit f82cf05626a3020e01b2551fc0cc78a9365fe7b5 - Author: Nobuyoshi Nakada - Date: 2019-09-02 00:41:45 +0900 - - Fixed the directory to be removed - -commit 007d6d15f4aeea266d4d88e0541ab45a34a1dcd4 - Author: Yusuke Endoh - Date: 2019-09-01 23:29:39 +0900 - - test/drb/drbtest.rb: Use EnvUtil.timeout for timeout scale factor - -commit 188c2b67c9365fcf75a595186d95c325f06b9182 - Author: Yusuke Endoh - Date: 2019-09-01 23:27:44 +0900 - - Revert "Revert "Revert "Skip BUGs on Solaris""" - - This reverts commit 3be3948870f6589343c4aecb541e22fae7751b47. - - The Solaris environment couldn't lookup the hostname itself by a wrong - setting. Now it is fixed, so try again. - -commit bd785ca07779bacf78b9678b3d19eef4754fcbae - Author: Nobuyoshi Nakada - Date: 2019-09-01 23:24:05 +0900 - - Restore pwd for each version - -commit fd4aad6d41da016f3a7aa7d3f130c39fe7bf082b - Author: Nobuyoshi Nakada - Date: 2019-09-01 22:16:18 +0900 - - Support packaging different branch/tag - -commit d8260bc872c8c562fff90278bb21815b9e7946e5 - Author: Nobuyoshi Nakada - Date: 2019-09-01 19:01:19 +0900 - - Fetch commit notes - -commit b578c63f8398d4203c27a012f60b99d14910007d - Author: Nobuyoshi Nakada - Date: 2019-09-01 18:15:02 +0900 - - Resolve symlinks to cache directory under gems - -commit ff7c95dfd9b6aa1b4a83c18172e2845f7e6a4e7f - Author: Nobuyoshi Nakada - Date: 2019-09-01 18:10:50 +0900 - - Support git tags - -commit 04c3e344562eed9892409643bb4cfd6a2317e647 - Author: Takashi Kokubun - Date: 2019-09-01 19:26:22 +0900 - - Upgrade benchmark-driver for keyword args warnings - -commit 3be3948870f6589343c4aecb541e22fae7751b47 - Author: Yusuke Endoh - Date: 2019-09-01 18:57:40 +0900 - - Revert "Revert "Skip BUGs on Solaris"" - - This reverts commit 84dca8eff0cbcb1c23623b47fb78b0daf5c76e35. - - "execution expired" occurred on Solaris. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20190901T072504Z.fail.html.gz - -commit 94d6ec1d90bb28e5f303867b048e6322d8781cb1 - Author: Kazuki Tsujimoto - Date: 2019-09-01 16:39:34 +0900 - - Make pattern matching support **nil syntax - -commit cda5745c1bacdb3be8384d21ee0dd70a9d95af5b - Author: Takashi Kokubun - Date: 2019-09-01 16:31:09 +0900 - - Automatically detect missing symbols - - which are usually optimized away by -O3. - - This CI can detect missing exports like - ea84a680755b5a7fa700618cbe78e3b2fc7be01d which was needed for - 761346a9604ca2c79777d1d67fb5dcc3c30dbf69. - -commit ea84a680755b5a7fa700618cbe78e3b2fc7be01d - Author: Kazuki Tsujimoto - Date: 2019-09-01 16:25:01 +0900 - - Export rb_const_source_location_at for MJIT - -commit 02dfa0f16361c498e0f529054b00e3e09730892b - Author: Yusuke Endoh - Date: 2019-09-01 15:24:37 +0900 - - test/ruby/test_keyword.rb: Add remove_method before method redefinition - - to suppress redefinition warnings. - -commit 84dca8eff0cbcb1c23623b47fb78b0daf5c76e35 - Author: Yusuke Endoh - Date: 2019-09-01 15:14:27 +0900 - - Revert "Skip BUGs on Solaris" - - This reverts commit 8adefd4cf29288f6e43f20efbdd44b215ae16c7a. - - I couldn't see any failure on Solaris if the guard is removed. - Give it a try. - -commit d646a292cddabfd41593d0b58fd5270e3aeefbb4 - Author: Jeremy Evans - Date: 2019-09-01 15:05:02 +0900 - - Fix keyword argument separation warning when using send - - vm_call_opt_send was dropping VM_CALL_KW_SPLAT, so this just makes - it not drop it, to get the same behavior as calling the method - directly. - -commit e13c0bb82018197d906b8f11eccf2cd90d142e41 - Author: Takashi Kokubun - Date: 2019-09-01 14:54:04 +0900 - - Note about ANYARGS in NEWS - - Since 50f5a0a8d6e7ad89d6caff695a08dbd38edb7a6e, some C++ extensions - needed fixes like https://github.com/eagletmt/faml/pull/49 to make their - build succeed. - - Thus it's worth noting that C API declarations are changed. - -commit 15757390fff14071f3d77fa75934b741723eb92a - Author: Jeremy Evans - Date: 2019-09-01 13:51:02 +0900 - - Don't pass an empty keyword hash when double splatting empty hash when calling cfunc - - This mirrors earlier changes in keyword argument separation for - calling Ruby methods and calling procs/lambdas, so that behavior - is kept the same. - -commit e80a6f65c873fb01c98f71fa94085264dbb1dbf0 - Author: Nobuyoshi Nakada - Date: 2019-09-01 13:37:28 +0900 - - Made :nil static ID - -commit e5dd63ba8c854d8dce9537adb730658aded6bc8d - Author: aycabta - Date: 2019-09-01 11:19:17 +0900 - - IRB 1.1.0.pre.3 - -commit 11d6094cbe2965563942152bebca5ba4b54a7004 - Author: aycabta - Date: 2019-09-01 11:08:09 +0900 - - Reline 0.0.2 - -commit c5bb074fe731832b64143372986197c83201d2f3 - Author: aycabta - Date: 2019-09-01 11:02:14 +0900 - - Re-calculate state variables of screen when screen size changes - -commit 1756ec2065d5219659b585f3fe3ce666861acd3a - Author: Hiroshi SHIBATA - Date: 2019-09-01 08:56:00 +0900 - - Ignore the all of warnings with inline_spec.rb of bundler examples. - -commit a060629e66899a02d01760ee249df84754c8e445 - Author: git - Date: 2019-09-01 01:56:24 +0900 - - * 2019-09-01 [ci skip] - -commit 431a99b5569e90dd76677be273ad81640ce7e757 - Author: Nobuyoshi Nakada - Date: 2019-09-01 01:44:36 +0900 - - Split warning messages for tag-jump - -commit d4eef04883104c6b4618a843651584cb65c9428d - Author: aycabta - Date: 2019-08-31 20:55:35 +0900 - - Use double splat for keyword args by a hash object in lib/un.rb - -commit 602fbd4338a875aa26c6248338a3df97e08a6b72 - Author: Takashi Kokubun - Date: 2019-08-31 17:34:23 +0900 - - Limit the apt addon enablement to trusty - - 8897fa60fdbc83f9cce7df384893e902c17c1bf2 worked. - But we want to retry that part and this commit is trying to fix the - problem. - -commit 8897fa60fdbc83f9cce7df384893e902c17c1bf2 - Author: Takashi Kokubun - Date: 2019-08-31 17:18:00 +0900 - - Try using built-in apt source for gcc-8 - - 58a373e9ed54556e18a13825dfe72d3f7a86b833 and - 3868df83330bb897be996604df3862639abbf002 - didn't work. - -commit 3868df83330bb897be996604df3862639abbf002 - Author: Takashi Kokubun - Date: 2019-08-31 17:03:26 +0900 - - Try to fix apt-get update error for trusty (take 2) - - https://travis-ci.org/ruby/ruby/jobs/579116510 - -commit 58a373e9ed54556e18a13825dfe72d3f7a86b833 - Author: Takashi Kokubun - Date: 2019-08-31 16:44:41 +0900 - - Try to suppress errors in BASERUBY Travis - - https://travis-ci.org/ruby/ruby/jobs/579108692 - -commit 1f18b578ce300a3ba71a9525e680037122bb81d3 - Author: Jeremy Evans - Date: 2019-08-31 15:50:50 +0900 - - Don't pass an empty keyword hash when double splatting empty hash - -commit 4868ad7e5b3065f9d94cc7e70889c9d31ebe88cc - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-31 13:31:21 +0900 - - fix CI failures in x64-mingw32 - - For insatnce - https://ci.appveyor.com/project/ruby/ruby/builds/27086475/job/mb9whkiygemlfy93 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2413 - -commit d7aa1260b6c378b2f540a06eb770bc07db0ebb53 - Author: Nobuyoshi Nakada - Date: 2019-08-31 14:44:57 +0900 - - Remove files/directories for git/github which are committed [ci skip] - -commit 60a08d9a6c11fda25bb73ded9e26aabc57af9433 - Author: Jeremy Evans - Date: 2019-08-31 14:11:00 +0900 - - Add rb_iseq_location - - This wraps iseq_location and should fix the leaked global test. - -commit ec6206a81a1d61efe5bda69ab704c09e75033c01 - Author: Jeremy Evans - Date: 2019-08-31 13:56:50 +0900 - - Use more accurate source location in keyword argument separation warnings - - This shows locations in places it didn't before, such as for - proc calls, and fixes the location for super calls. - - This requires making iseq_location non-static and MJIT exported, - which I hope will not cause problems. - -commit 3463e83192215c36bdcebad8be907eaa09593a41 - Author: Jeremy Evans - Date: 2019-08-31 11:23:10 +0900 - - Warn for keyword to last hash parameter when method has no optional/rest parameters - - Previously, there was no warning in this case, even though we will - be changing the behavior in Ruby 3. - - Fixes [Bug #14130] - -commit 6424d316b993ecceb6f583ae476096274e304788 - Author: Jeremy Evans - Date: 2019-08-31 09:33:33 +0900 - - Remove a verbose warning that is no longer needed - - This warns about a case that we will continue to support. - -commit 8cb9efbbe62a9a544bff2cd6571fc756ce92a738 - Author: Yusuke Endoh - Date: 2019-08-31 07:17:46 +0900 - - tool/rbinstall.rb: remove a keyword-argument warning - -commit a1e588d1a73e3d72cd9ce6a2516ada9baeb77861 - Author: Yusuke Endoh - Date: 2019-08-31 07:03:27 +0900 - - NEWS: Hash-to-keywords automatic conversion is now warned - - A follow up for 16c6984bb9..b5b3afadfa. [Feature #14183] - -commit 38e08db48e9d8cf34b2362df24afa97ba1e2ff4b - Author: git - Date: 2019-08-31 04:39:56 +0900 - - * 2019-08-31 [ci skip] - -commit b5b3afadfab4072f55320075ccac6afe333a140c - Author: Jeremy Evans - Date: 2019-08-31 03:52:46 +0900 - - Fix a couple of bundler issues with keyword argument separation - - There are more issues than this, but hopefully this is enough - to get make test-bundler passing in CI. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 856bb3c35d5d81481b2e5dd00353298e8a0c2ee7 - Author: Jeremy Evans - Date: 2019-08-21 04:29:51 +0900 - - Fix remaining warning issues in the tests due to keyword argument separation - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 42adc5bc6bb532e20bf2191ad99781ee701dea36 - Author: Jeremy Evans - Date: 2019-08-21 04:28:04 +0900 - - Add back missing warning for duplicate keys in splatted hashes - - This reverts the changes to parse.y in - a5b37262524ac39d2af13eea174486370a581c23 as they are not actually - needed and cause the warning for duplicate hash keys to not be - emitted. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit a810f6cbefb5726c626b0c490522865588f4480e - Author: Jeremy Evans - Date: 2019-08-18 14:49:04 +0900 - - Update specs to handle non-Symbols for keyword splats in 2.7 - - Also handle some warnings for behavior that will change in 3.0. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 16cd0de6ec8464129041c52174f5608e32512ca1 - Author: Jeremy Evans - Date: 2019-08-18 14:47:43 +0900 - - When splitting a keyword hash, dup it first to not mutate it - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 5c507db467f20a6981ce6b282a607d4d975bcb07 - Author: Jeremy Evans - Date: 2019-08-18 14:43:26 +0900 - - Implement keyword argument to last positional hash emulation - - For methods that accept keyword arguments but do not accept a - keyword splat, if a keyword splat is passed, or keywords are - used with a non-symbol key, check the hash. If the hash contains - all symbols, keep the same behavior as before. If the hash - contains all non-symbols, move the hash to the last positional - hash and warn. If the hash contains symbols and non-Symbols, split - the hash and use the symbol keys for the keyword hash and non-symbol - keys for the positional hash and warn. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 8399609e5a27d3d993c9fbb08f9d88051f26d455 - Author: Jeremy Evans - Date: 2019-08-17 04:43:13 +0900 - - Make keyword_hash_split static - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 3a23b71f0ac76d52f334643ab3152017c7a10b39 - Author: Jeremy Evans - Date: 2019-04-25 04:06:39 +0900 - - Make Method/Proc#parameters handle **nil syntax - - Use a [:nokey] entry in this case. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit fa41a7b2608523a89d4eb1c9309d39a140e839ef - Author: Jeremy Evans - Date: 2019-04-25 03:40:02 +0900 - - Make RubyVM::AbstractSyntaxTree handle **nil syntax - - Use false instead of nil for the keyword and keyword rest values - in that case. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 4d64693c703edbccc5b155072276ce7b8c3becdb - Author: Jeremy Evans - Date: 2019-04-25 02:34:02 +0900 - - Make ripper support **nil syntax - - The on_params hook will use :nil as the keyword rest argument. - There is a new on_nokw_param hook as well. - - This fixes a type issue in the previous code, where an ID was - passed where a VALUE was the declared type. The symbol :nil is - passed instead of the id. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 6a9ce1fea89bc5c6518dd6bb7ff3b824a9321976 - Author: Jeremy Evans - Date: 2019-04-19 22:19:41 +0900 - - Support **nil syntax for specifying a method does not accept keyword arguments - - This syntax means the method should be treated as a method that - uses keyword arguments, but no specific keyword arguments are - supported, and therefore calling the method with keyword arguments - will raise an ArgumentError. It is still allowed to double splat - an empty hash when calling the method, as that does not pass - any keyword arguments. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit afae8555da07b2349a245d6646e3b36a49f027d5 - Author: Jeremy Evans - Date: 2019-04-09 11:45:54 +0900 - - Set symbol export for rb_hash_stlike_foreach - - This fixes MJIT after rb_hash_stlike_foreach used vm_args.c. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 896e42d93f52966644c2700ed9fd18f2a1988dd3 - Author: Jeremy Evans - Date: 2019-04-09 10:45:50 +0900 - - Restore splitting of hashes into positional and keyword arguments, add warning - - This restores compatibility with Ruby 2.6, splitting the last - positional hash into positional and keyword arguments if it - contains both symbol and non-symbol keys. However, in this case - it will warn, as the behavior in Ruby 3 will be to not split the - hash and keep it as a positional argument. - - This does not affect the handling of mixed symbol and non-symbol - keys in bare keywords. Those are still treated as keywords now, - as they were before this patch. This results in different - behavior than Ruby 2.6, which would split the bare keywords and - use the non-Symbol keys as a positional arguments. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 15bca0d4d373820fa648c351dc13c2131849d9b3 - Author: Jeremy Evans - Date: 2019-04-08 10:49:55 +0900 - - Fix test after keyword argument separation - - Now that keyword splats accept non-Symbols, the type of exception - changes. - - Previously, a TypeError (hash key "k1" is not a Symbol) was raised - for this test, but now an ArgumentError (unknown keyword: "k1") is - raised. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 03697ddf63eb9acd41e4f2185a019d39d1ead3cf - Author: Jeremy Evans - Date: 2019-04-08 10:48:43 +0900 - - Update tests to fix warning message changes - - Now that keyword splats accept non-Symbols, the inspect value of - the keyword is used instead of the string value. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 9c2e165f7dbb63dd1921eacae58c4305d3e9e5b6 - Author: Jeremy Evans - Date: 2019-04-08 10:45:26 +0900 - - Only promote last hash to keyword if all keys are symbols - - If all keys are not symbols, then the non-symbol keys would not - be treated as keywords in previous versions. It doesn't make - sense to treat these hashes as keywords to break compatibility and - warn about behavior changes in Ruby 2.7 when the Ruby 3.0 behavior - will be the same as the Ruby 2.6 for these hashes. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit e0b4599bba6bea744e0e90b7640dcc21d695c434 - Author: Jeremy Evans - Date: 2019-04-08 08:55:34 +0900 - - Fix keyword argument separation warnings in test - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit d08e1004e0ee1286e4513de2a170391a4d0a0116 - Author: Jeremy Evans - Date: 2019-04-08 08:44:49 +0900 - - Fix keyword argument separation issues in lib - - Mostly requires adding ** in either calls or method definitions. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 3f67fcd3d5ca5e2907790eb5bb16d03f5884ece8 - Author: Jeremy Evans - Date: 2019-04-08 03:38:21 +0900 - - Fix hash to keyword warning to apply in all cases - - Previously, it only applied if the call had more positional - arguments than the method it was calling accepted. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 334b41a46b2a1a72965494dcecc6fe73a83f4490 - Author: Jeremy Evans - Date: 2019-04-02 04:15:01 +0900 - - Allow ** syntax to be used for calling methods that do not accept keywords - - Treat the ** syntax as passing a copy of the hash as the last - positional argument. If the hash being double splatted is empty, do - not add a positional argument. - - Remove rb_no_keyword_hash, no longer needed. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit 16c6984bb97409029e213154ac4f633ae04af3d8 - Author: Yusuke Endoh - Date: 2019-03-18 14:25:47 +0900 - - Separate keyword arguments from positional arguments - - And, allow non-symbol keys as a keyword argument - - Notes: - Merged: https://github.com/ruby/ruby/pull/2395 - -commit b0a291f6f6a5834fd84807eb48be906ade429871 - Author: Takashi Kokubun - Date: 2019-08-30 22:16:32 +0900 - - Split CC_LINKER_ARGS from CC_DLDFLAGS_ARGS - - to drop MJIT_DLDFLAGS from compile_c_to_o for OpenBSD failure - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd65/ruby-master/log/20190830T110008Z.fail.html.gz. - - 8c7f4e8f8b7f9e74195ea0eb51f39014fec342c0 did not work for i686-linux - https://travis-ci.org/ruby/ruby/jobs/578808112. - -commit 8c7f4e8f8b7f9e74195ea0eb51f39014fec342c0 - Author: Takashi Kokubun - Date: 2019-08-30 22:03:36 +0900 - - Try dropping DLDFLAGS from compile_c_to_o - - I think this did not work for some environments, but this seems to fix - OpenBSD RubyCI failure: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd65/ruby-master/log/20190830T110008Z.fail.html.gz - - Let me check RubyCI impact by this. - -commit c45dd4d4826704471cf9ff2c7869065236dd174e - Author: Maciej Mensfeld - Date: 2019-08-30 18:24:33 +0900 - - Make the dot-colon method reference frozen - - [Feature #16103] - - Close: https://github.com/ruby/ruby/pull/2267 - -commit 998ee350b9b2cb3659c442d68447aa8bfc54d101 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-30 16:09:08 +0900 - - Revert "require 'pp' before use PP" - - of lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb. - This reverts commit 500149709b92ccb36396589a0c39afb3ff77bfb6 partially. - -commit 631db0de274ff3d00d47c3d3581d8af5592f8a14 - Author: Nobuyoshi Nakada - Date: 2019-08-30 16:00:18 +0900 - - Removed debug print - - It seems to be fixed by b870ca58791e576f5dbb263f54ae433a7f6d65ee. - -commit b870ca58791e576f5dbb263f54ae433a7f6d65ee - Author: Kazuhiro NISHIYAMA - Date: 2019-08-30 12:49:27 +0900 - - Add guard as same as `==` - - Try to fix failure at https://github.com/ruby/ruby/runs/207580232#step:10:382 - ``` - undefined method `name' for "Gemfile.lock":String - /home/runner/work/ruby/ruby/lib/bundler/resolver/spec_group.rb:65:in `eql?' - ``` - -commit 896d9f967b535a6ecb9ff5d3c08f1a37bcb8d1f9 - Author: Nobuyoshi Nakada - Date: 2019-08-27 13:43:16 +0900 - - Constified local variable `translator` - -commit e9da4f57b35afe40b74c32e8f95e39aaaecc11b5 - Author: Nobuyoshi Nakada - Date: 2019-08-27 13:42:53 +0900 - - Adjust indent [ci skip] - -commit 1680bd4e4f63901ff8ab119540850e7e63f1b7a2 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-30 12:01:45 +0900 - - [DOC] Return obj may be different from 1st argument [ci skip] - -commit ba9adcc1759cda3cb7838b650be1fe197d9ba3ba - Author: Yusuke Endoh - Date: 2019-08-30 11:49:14 +0900 - - spec/ruby/core/unboundmethod/bind_call_spec.rb: Add ruby_version_is guard - -commit 96b32aad93a0eb36770a9b1339e204f00f44f0b3 - Author: Nobuyoshi Nakada - Date: 2019-08-30 11:26:48 +0900 - - Exclude ripper y.output from packages [ci skip] - -commit 98ccdd744ab46554e7f0e1d0a89f2ed24d365e53 - Author: Nobuyoshi Nakada - Date: 2019-08-30 11:23:06 +0900 - - Export the last modified revision for tags [ci skip] - -commit e593d5b31a13c59f9af07a2a6012c09bae7477d1 - Author: Nobuyoshi Nakada - Date: 2019-08-30 11:18:23 +0900 - - Suppress uninitialized instance variable warnings [ci skip] - -commit 55f496c89b820f57d9e07c744675da8c43d6aa46 - Author: Nobuyoshi Nakada - Date: 2019-08-30 10:14:15 +0900 - - Support revision in git-svn log - -commit 1191049436556955893d7f6037eb626e6f51a004 - Author: Nobuyoshi Nakada - Date: 2019-08-30 10:13:45 +0900 - - Updated comment of VCS#get_revisions [ci skip] - -commit 43ab88c73706f4ffca2d01b149f5d7092b46000b - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-30 11:20:43 +0900 - - Workaround for https://reviews.llvm.org/D25824 - - This changeset make it possible to use very old clang. - -commit c9fc82983ccf624ccec88ffafe6f4e3eb8e7abc4 - Author: Yusuke Endoh - Date: 2019-08-30 11:11:55 +0900 - - lib/pp.rb: Use UnboundMethod#bind_call instead of .bind(obj).call(...) - - Related to [Feature #15955]. - -commit 09c940b17fcbaec2f7d04e528b8869c8c51ff336 - Author: Yusuke Endoh - Date: 2019-08-30 11:10:29 +0900 - - spec/ruby/core/unboundmethod/bind_call_spec.rb: Added - - For UnboundMethod#bind_call [Feature #15955] introduced in - 002e592e0d67bb0271d16314a32380ad947c9ae9. - -commit 83c6a1ef454c51ad1c0ca58e8a95fd67a033f710 - Author: Yusuke Endoh - Date: 2019-08-30 11:01:25 +0900 - - proc.c: Add UnboundMethod#bind_call - - `umethod.bind_call(obj, ...)` is semantically equivalent to - `umethod.bind(obj).call(...)`. This idiom is used in some libraries to - call a method that is overridden. The added method does the same - without allocation of intermediate Method object. [Feature #15955] - - ``` - class Foo - def add_1(x) - x + 1 - end - end - class Bar < Foo - def add_1(x) # override - x + 2 - end - end - - obj = Bar.new - p obj.add_1(1) #=> 3 - p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2 - p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2 - ``` - -commit 500149709b92ccb36396589a0c39afb3ff77bfb6 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-30 10:18:32 +0900 - - require 'pp' before use PP - - `Kernel#pp` has wrapper, but `PP` does not. - - https://github.com/ruby/ruby/runs/207405029#step:10:141 - `NameError: uninitialized constant Bundler::Molinillo::Resolver::Resolution::PP` - -commit 0a9d74f8cf1c01300d0396ce3cb4da81d3652d5a - Author: Charles Oliver Nutter - Date: 2019-08-30 06:15:45 +0900 - - Move pread + pwrite tests out of RUBY_ENGINE block - - These tests were guarded by a RUBY_ENGINE of "ruby" even though they test an official Ruby feature (pread/pwrite added in Ruby 2.5). This commit moves them to the top level of the test case so they will run on other implementations. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2412 - -commit bdc36094e3e11c045b26b2831a3a7e69b937ec61 - Author: Aaron Patterson - Date: 2019-08-30 06:51:34 +0900 - - Add some NODE information for lldb - - Just adds a conditional in the lldb scripts so we can more easily debug - NODE objects. - -commit 94b79bffb108ccacb6d165f31e177fa24d392774 - Author: schneems - Date: 2019-08-30 03:01:43 +0900 - - Add word "Euler's number" to Math::E docs - - When searching for this constant, I landed on the correct page https://ruby-doc.org/core-2.6.4/Math.html however I was using CMD+f to search for "Euler" and did not find it. If we add the full name for this constant then it will be easier to search for and find. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2411 - -commit a8b310e14c2816f686b2e0b1cd1dca72f02fdf0d - Author: Kazuhiro NISHIYAMA - Date: 2019-08-30 00:35:18 +0900 - - 7z does not accept gzip's options - - e.g. `GZIP=-9` - -commit c52d38b7b6fa8383977a3629bc7331a45598259a - Author: git - Date: 2019-08-30 00:23:35 +0900 - - * 2019-08-30 [ci skip] - -commit e51dca2596db9567bd4d698b18b4d300575d3881 - Author: Jeremy Evans - Date: 2019-07-06 02:01:06 +0900 - - Disallow use of attrset symbols as Struct members - - Fixes [Bug #11326] - -commit 01b723ba6dd48a0954765e43cff6bd9212afe259 - Author: Nobuyoshi Nakada - Date: 2019-08-29 23:06:27 +0900 - - Refined warnings against literal in flip-flop - -commit 79117d4a9b794fba68c3d7ac699ad8a989bd29dc - Author: Nobuyoshi Nakada - Date: 2019-08-29 22:06:05 +0900 - - NEWS: [Feature #16035] [ci skip] - -commit 2c1e902cba710eb5a83412a98984711e5fe8aad7 - Author: aycabta - Date: 2019-08-29 21:49:19 +0900 - - Don't pick up lib/readline.rb from ruby/reline - -commit a39b26b5947f19c4ec1d410e0d0869b5ab839c65 - Author: aycabta - Date: 2019-08-29 21:11:53 +0900 - - Check events that console window size changed on Windows - -commit 3a425c7623d2062ae931dc83050c00a12873217b - Author: aycabta - Date: 2019-08-29 21:05:19 +0900 - - Fix alignment of a SHORT variable - - typedef struct _COORD { - SHORT X; - SHORT Y; // I wanted to take this... - } COORD, *PCOORD; - - typedef struct _CONSOLE_SCREEN_BUFFER_INFO { - COORD dwSize; - COORD dwCursorPosition; // ...of this one - WORD wAttributes; // But it's combined with first 2bytes of this - SMALL_RECT srWindow; - COORD dwMaximumWindowSize; - } CONSOLE_SCREEN_BUFFER_INFO; - - If wAttributes has non-zero value, the code breaks. - -commit b74dd665c0e9558f355cbe1a625beb444c2a2ab4 - Author: aycabta - Date: 2019-08-29 20:59:29 +0900 - - CONSOLE_SCREEN_BUFFER_INFO is 22bytes - - typedef struct _CONSOLE_SCREEN_BUFFER_INFO { - COORD dwSize; // 4(SHORT X, Y) - COORD dwCursorPosition; // 4 - WORD wAttributes; // 2 - SMALL_RECT srWindow; // 8(SHORT Left, Top, Right, Bottom) - COORD dwMaximumWindowSize; // 4 - } CONSOLE_SCREEN_BUFFER_INFO; - -commit a4a19b114ba94b8f28d5a91aee5d595a516006d5 - Author: Jean Boussier - Date: 2019-08-02 03:41:21 +0900 - - Allow non-finalizable objects in ObjectSpace::WeakMap - - [feature #16035] - - This goes one step farther than what nobu did in [feature #13498] - - With this patch, special objects such as static symbols, integers, etc can be used as either key or values inside WeakMap. They simply don't have a finalizer defined on them. - - This is useful if you need to deduplicate value objects - - Notes: - Merged: https://github.com/ruby/ruby/pull/2313 - -commit e4be2fda3dbbfdb1f2ace697c96cf6bdd7dfef21 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 15:47:33 +0900 - - Rule out gcc on Windows - - It seems the combination fails at the moment. Don't know exactly - why but I suspect there can be issues in resolving weak references. - Let's rule them out for now. - - https://ci.appveyor.com/project/ruby/ruby/builds/27036383/job/x3c5d54839aacoyt - -commit 3df37259d81d9fc71f8b4f0b8d45dc9d0af81ab4 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 11:47:20 +0900 - - drop-in type check for rb_define_singleton_method - - We can check the function pointer passed to - rb_define_singleton_method like how we do so in rb_define_method. - Doing so revealed many arity mismatches. - -commit bfe5d22f89a871b6c1cb556c0115145ade9fe286 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 10:57:48 +0900 - - drop-in type check for rb_define_private_method - - We can check the function pointer passed to rb_define_private_method - like how we do so in rb_define_method. Doing so revealed some - problematic usages of rb_obj_dummy. They had to be split according - to their arity. - -commit 9b429eb3b15321115d9a217c91c5510fe43777a7 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 10:45:09 +0900 - - drop-in type check for rb_define_protected_method - - We can check the function pointer passed to - rb_define_protected_method like how we do so in rb_define_method. - This changeset revealed no prototypes mismatches. - -commit 0b81e7d6e2810adac081965f0da1d8064888c0bd - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 10:40:40 +0900 - - drop-in type check for rb_define_method_id - - We can check the function pointer passed to rb_define_method_id - like how we do so in rb_define_method. This method is relatively - rarely used so there are less problems found than the other APIs. - -commit 0766f67168cf248b698a8b2cde1c22c526374be7 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-29 10:23:14 +0900 - - move docs around [ci skip] - - To properly generate documents. - -commit 7bcfd9189a6a0b2ad58fed988faaf795a4987893 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-28 18:19:11 +0900 - - drop-in type check for rb_define_global_function - - We can check the function pointer passed to rb_define_global_function - like we do so in rb_define_method. It turns out that almost anybody - is misunderstanding the API. - -commit 7b6fde4258e700c0e0292bb091aa84a5e473342e - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-28 17:48:48 +0900 - - drop-in type check for rb_define_module_function - - We can check the function pointer passed to rb_define_module_function - like how we do so in rb_define_method. The difference is that this - changeset reveales lots of atiry mismatches. - -commit 9ef51b0b89a10c8c401cb9f2337e47a25be72cbe - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-28 17:11:23 +0900 - - drop-in type check for rb_define_method - - The rb_define_method function takes a pointer to ANYARGS-ed functions, - which in fact varies 18 different prototypes. We still need to - preserve ANYARGS for storages but why not check the consistencies if - possible. - - Q&As: - - Q: Where did the magic number "18" came from in the description above? - - A: Count the case branch of vm_method.c:call_cfunc_invoker_func(). - Note also that the 18 branches has lasted for at least 25 years. - See also 200e0ee2fd3c1c006c528874a88f684447215524. - - Q: What is this __weakref__ thing? - - A: That is a kind of function overloading mechanism that GCC provides. - In this case for instance rb_define_method0 is an alias of - rb_define_method, with a strong type. - - Q: What is this __transparent_union__ thing? - - A: That is another kind of function overloading mechanism that GCC - provides. In this case the attributed function pointer is either - VALUE(*)(int,VALUE*,VALUE) or VALUE(*)(int,const VALUE*,VALUE). - - This is better than void* or ANYARGS because we can reject all - other possibilities than the two. - - Q: What does this rb_define_method macro mean? - - A: It selects appropriate alias of the rb_define_method function, - depending on the arity. - - Q: Why the prototype change of rb_f_notimplement? - - A: Function pointer to rb_f_notimplement is special cased in - vm_method.c:rb_add_method_cfunc(). That should be handled by the - __builtin_choose_expr chain inside of rb_define_method macro - expansion. In order to do so, comparison like (func == - rb_f_notimplement) is inappropriate for __builtin_choose_expr's - expression (which must be a compile-time integer constant but the - address of rb_f_notimplement is not fixed until the linker). So - instead we are using __builtin_types_compatible_p, and in doing so - we need to distinguish rb_f_notimplement from others, by type. - -commit 48e346a088395924298163941d4b4cdd8243e377 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-28 17:33:07 +0900 - - fix arity of bug_start - - This is just a trivial mistake introduced in - 0f36e8fc03a5c6433972d6bb5f177d5f6e106bac. - -commit 69683968a99a8281c28e46c1e6cb3736694a1ba6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-28 16:18:58 +0900 - - fix arity of rb_mutex_synchronize_m - - This is just a trivial mistake introduced in - 6c56dae4b23c5c50e351758538141ca26b9aba40. - -commit abe12d8b96be3c12618811f22ca01788366f99f8 - Author: Nobuyoshi Nakada - Date: 2019-08-29 16:58:21 +0900 - - Freeze method reference operator object - - [Feature #16103] - -commit 2ed68d0ff9a932efbc4393c869534040dec8f647 - Author: Nobuyoshi Nakada - Date: 2019-08-29 15:09:43 +0900 - - Revert "Add pipeline operator [Feature #15799]" - - This reverts commits: - * d365fd5a024254d7c105a62a015a7ea29ccf3e5d - * d780c3662484d6072b3a6945b840049de72c2096 - * aa7211836b769231a2a8ef6b6ec2fd0ec882ef29 - * 043f010c28e82ea38978bf8ed885416f133b5b75 - * bb4dd7c6af05c7821d572e2592ea3d0cc748d81f - * 043f010c28e82ea38978bf8ed885416f133b5b75 - * f169043d81524b5b529f2c1e9c35437ba5bc3a7a - - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/94645 - -commit 893900dc7876596fab0e488affddf3abcb510445 - Author: aycabta - Date: 2019-08-29 15:21:00 +0900 - - Add stub set_screen_size for other platforms - -commit 07f9cd96f3e99537ee47ceed07706338ab08c1f0 - Author: git - Date: 2019-08-29 15:12:37 +0900 - - * 2019-08-29 [ci skip] - -commit 0f405541bfe5186c068c4521d815b64b82e1ae5e - Author: aycabta - Date: 2019-08-29 14:36:45 +0900 - - Support SIGWINCH - -commit 682aaf6af5ff345897a9128bb19e0b17b71426a6 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-29 14:32:24 +0900 - - Replace numbered parameters with named parameters [ci skip] - -commit 761346a9604ca2c79777d1d67fb5dcc3c30dbf69 - Author: Nobuyoshi Nakada - Date: 2019-07-04 16:54:34 +0900 - - Show the previous definition location, - - when reopened class/module redefinition mismatched the previous - definition. [Feature #11460] - -commit d3e0bc07e2909f1105dcde4febb0e120eaea30b6 - Author: Nobuyoshi Nakada - Date: 2019-08-29 11:20:34 +0900 - - Fixed a comment [ci skip] - - A range literal in conditional expression is turned into a - flip-flop, as a Range object is never falsy and does not make a - sense. - -commit 1cf5a31e7a00c3900bb8bdc358606f66a729d4f7 - Author: Nobuyoshi Nakada - Date: 2019-08-29 11:16:17 +0900 - - Aseert exception at negative step for non-endless range too - -commit d92289cd8d5cac784ae856fb777f10dbc9f91b62 - Author: Nobuyoshi Nakada - Date: 2019-08-29 11:09:22 +0900 - - Revert "Remove warnings of flip-flop deprecation from tests and specs" - - This reverts commit bf7a32d22079cc44eb19794e41d82b886d5d17b3. - - flip-flop is no longer deprecated. - - [Feature #5400] - -commit cd0e208963bdf9ee2fec30e83bdc8f6bc77a7b8d - Author: Jeremy Evans - Date: 2019-08-29 03:40:56 +0900 - - Document {n}? regexp pattern is optional and not non-greedy [ci skip] - - While not consistent with {n,}?, {,m}?, and {n,m}?, it is arguably - more useful, as otherwise the ? would have no effect. - - Fixes [Bug #15583] - -commit e82719c6511cf00bd4b92759ba0197108cfad0cc - Author: aycabta - Date: 2019-08-28 19:45:27 +0900 - - Remove jquery.js from file list of rdoc.gemspec - -commit c1d0b6adfcbc219db3348b2b2cc4817db21e4b76 - Author: Nobuyoshi Nakada - Date: 2019-08-28 16:34:17 +0900 - - Revert "Treat RUBY_REVISION as an integer on old rubies" - - This reverts commit 6454808c52fff445ff09fefb0fb96988f82aaa3c. - - It is no longer needed, as `VCS::SVN#get_revisions` now returns - `Integer` as revision numbers, and `short_revision` should deal - with it. - -commit b11d739444e312e3284dc5daf8354a3067606f2d - Author: Nobuyoshi Nakada - Date: 2019-08-28 16:40:57 +0900 - - Fix warnings - - `_FILE_OFFSET_BITS` should be defined before system headers. - -commit a506b7f35a65a1ecee09fbff0372dc354255dd77 - Author: Nobuyoshi Nakada - Date: 2019-08-28 01:07:27 +0900 - - Adjusted indents and supplied last commas - - Fixed unmatched indent of the closing bracket for - `:irb_current_working_workspace`, and adjusted following elements. - -commit 2b55df7315ad78a138d877a3a319f86a3d3bfc24 - Author: NAKAMURA Usaku - Date: 2019-08-28 15:57:30 +0900 - - `revision` might be an Integer - -commit ed8d2e1cfdc57bba03065e96424e4ba7df45682e - Author: nagachika - Date: 2019-08-28 14:50:21 +0900 - - tool/merger.rb: fix tag existence check with subversion. - -commit c9dc569a94e568de19a39c08d69cf4ea9bd159dd - Author: Nobuyoshi Nakada - Date: 2019-08-28 12:32:43 +0900 - - Ensure the last and changed revisions as Integers - -commit 8e13da1ee83028000e5d7f9f9526379e32765a81 - Author: pavel - Date: 2019-07-19 23:23:00 +0900 - - optimize get_power2 [Feature #15631] - - Merged: https://github.com/ruby/ruby/pull/2292 - -commit 989e8ad322afdfa3aa06e74b89fc42aef42895d0 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 10:34:56 +0900 - - Remove debug print [ci skip] - -commit 624a0ad44db1f2f5f70ef1726e0c5d4be4d854fb - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 10:06:43 +0900 - - Use `set-env` instead of `grep` in each step - -commit 108dbb389b0a47199c8d0f271c34a22dd2406f2e - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:45:31 +0900 - - Use JOBS again like macos.yml - -commit 330c2f7597a132281d37eeca999a4a069c8bc11a - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:41:14 +0900 - - Change name to `Tests (test-bundled-gems)` - -commit 230f4054792c624d36c043ee0acfa19eeef29f31 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:38:52 +0900 - - Add name to autoconf - -commit 17c0ce379877fa3f8f79e84c5652bc2b74b9e08e - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:20:07 +0900 - - Remove GITHUB_SHA from jobs..steps.env - - because default value overrides it. - https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - -commit 767992329ea335546bbdc98812b5a16be720a415 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:15:40 +0900 - - Allow missing projectnumber [ci skip] - -commit d4de5e645913ae8cacb372f5d405d62de817b6a2 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 09:13:43 +0900 - - Show projectnumber in current index.html and GITHUB_SHA - -commit 932a471d3811d6d44764ce42b1b140a04961a763 - Author: Aaron Patterson - Date: 2019-08-17 08:04:26 +0900 - - Directly mark compile options from the AST object - - `rb_ast_t` holds a reference to this object, so it should mark the - object. Currently it is relying on the `mark_ary` on `node_buffer` to - ensure that the object stays alive. But since the array internals can - move, this could cause a segv if compaction impacts the array. - -commit cbcad66741507daea5f5037510404848720e347f - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 02:16:28 +0900 - - Fix doxygen action - - - Fix checkout error: `fatal: destination path '.' already exists and is not an empty directory.` - - Remove `GITHUB_SHA` in env, because set automatically - https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - - Change minute from 0 to 20 for test soon - -commit 71e5871c3be6df6a02b0af2cdb78b3fb35b24918 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-28 01:47:56 +0900 - - Run on schedule only and skip if not modified - -commit f308ab2131ee675000926540cbb8c13c91dc3be5 - Author: aycabta - Date: 2019-08-28 01:09:15 +0900 - - Remove jquery.js - -commit 88a37dc62099b49e71a05342460da4061d5f23dd - Author: Takashi Kokubun - Date: 2019-08-28 00:45:21 +0900 - - Stop passing CC_LIBS in compile_c_to_o - - To fix "gcc: -lgcc: linker input file unused because linking not done" in - https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd65/ruby-master/log/20190826T200009Z.log.html.gz - - Still I'm intentionally leaving CC_DLDFLAGS_ARGS because making compiler - options different might result in compile/link failure. (Of course - CC_DLDFLAGS_ARGS usually should not have compiler options, but it might - include by bad configure setup) - - The same problem may exist in MJIT_LIBS used inside CC_LIBS as well, but - I just ignored that case because it impacts only MinGW / cygwin, hoping - that their users do not perform a wrong configure. - - Notes: - s/might include/might be included/ - -commit d8fa88294fbbd04b218b7e9724bec2553dab72b8 - Author: aycabta - Date: 2019-08-27 21:56:04 +0900 - - Version 6.2.0 - -commit 39810b4035beb2a4a3e3b993224eb20ead26e40c - Author: aycabta - Date: 2019-08-27 21:55:51 +0900 - - Good bye jQuery - -commit 6454808c52fff445ff09fefb0fb96988f82aaa3c - Author: NAKAMURA Usaku - Date: 2019-08-28 00:19:25 +0900 - - Treat RUBY_REVISION as an integer on old rubies - -commit dd032a5fb4dd8da59c685910b3c673439edc8c42 - Author: Takashi Kokubun - Date: 2019-08-28 00:13:54 +0900 - - Make doxygen / coverage torelant to clone race - - a little. - - Doing both `git clone --depth=1` and `git reset --hard ${sha}` does not - make sense (the latter command either does nothing or just fails), so I - added non-1 value as a depth. - - Maybe we don't need depth=50 for pull_request and schedule, so it's 10 - for now. - -commit 9928a6a3670fff8c87d1def74c719987acae8cf0 - Author: git - Date: 2019-08-28 00:12:01 +0900 - - * 2019-08-28 [ci skip] - -commit 6a0d2bc2af7597e3e308c949e01c8e6329107b47 - Author: Nobuyoshi Nakada - Date: 2019-08-28 00:09:01 +0900 - - Follows callback declaration updates - -commit 4209066f0e2be775357d09cb513c89a2f064a335 - Author: Takashi Kokubun - Date: 2019-08-27 23:52:31 +0900 - - Drop more unused configs from doxygen and coverage - - workflows, because mame said he has never seen it. - -commit 3bed468e8864f3ac4332a08b6c95b1a542aa23dd - Author: Takashi Kokubun - Date: 2019-08-27 23:49:24 +0900 - - Omit unused matrix strategy from doxygen workflow - -commit 2cd68a38d97c8f2633c88d0d94e9aa1724261f9f - Author: Nobuyoshi Nakada - Date: 2019-08-27 23:42:56 +0900 - - Short revision of SVN should be an Integer - -commit eaff19de2b31dc2133ba477291498d66bf3448bd - Author: Takashi Kokubun - Date: 2019-08-27 23:41:51 +0900 - - Fix rb_thread_create argument type - - in response to the declaration change in - e3fc30564e9466d6926f9d25a090dcf787bd5c33. - - Fixing the AppVeyor mswin CI failure: - https://ci.appveyor.com/project/ruby/ruby/builds/26980881/job/2j6h1qwjnbc8cpop - - ref: https://github.com/ruby/ruby/pull/2404 - -commit d8060782373c181bc689ce9bc73f6cb8b74de44d - Author: Kazuhiro NISHIYAMA - Date: 2019-08-27 18:46:16 +0900 - - Add graphviz for dot command - -commit 3ac0b75c456fa1d16c133cef2f47b7361cf651c5 - Author: Yusuke Endoh - Date: 2019-08-27 16:39:42 +0900 - - Doxygen in GitHub Actions (#2406) - - * .github/workflows/doxygen.yml: add a workflow for doxygen in Actions - - Notes: - Merged-By: mame - -commit 1663d347c993debf7ed83e11e291e7a21e14ed03 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 14:21:18 +0900 - - delete `$` sign from C identifiers - - They lack portability. See also - https://travis-ci.org/shyouhei/ruby/jobs/577164015 - -commit 19b6678132acc56460432d8c2d6246f399b27160 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 12:40:06 +0900 - - rb_uninterruptible now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This function has only one call site - so adding appropriate prototype is trivial. - -commit bd8dc2561d4983df7bf44dbc6ca194930532adc7 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 12:29:00 +0900 - - struct MEMO now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. There is only one usage of - MEMO::u3::func in load.c (where void Init_Foobar(vodi) is registered) - so why not just be explicit. - -commit 79d280a5e855d623957638b6d73f530995e03cae - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 12:08:32 +0900 - - rb_ivar_foreach now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit adds a function - prototype for rb_ivar_foreach. Luckily this change revealed no - problematic usage of the function. - -commit 50f5a0a8d6e7ad89d6caff695a08dbd38edb7a6e - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 11:53:39 +0900 - - rb_hash_foreach now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit adds function prototypes - for rb_hash_foreach / st_foreach_safe. Also fixes some prototype - mismatches. - -commit ae2dc3f217ba9f181471f39a7e5ce72a28b27c2a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 11:16:52 +0900 - - rb_define_hooked_variable now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit uses rb_gvar_getter_t / - rb_gvar_setter_t for rb_define_hooked_variable / - rb_define_virtual_variable which revealed lots of function prototype - inconsistencies. Some of them were literally decades old, going back - to dda5dc00cff334cac373096d444a0fd59e716124. - -commit 78628618da98236fc1bf702079185b36ed394e2a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 12:21:36 +0900 - - struct st_hash_type now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit adds function prototypes - for struct st_hash_type. Honestly I don't understand why they were - commented out at the first place. - -commit 6dd60cf114701f1ff3526381c0e742c588af2f91 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 16:06:40 +0900 - - st_foreach now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - st_foreach. I strongly believe that this commit should have had come - with b0af0592fdd9e9d4e4b863fde006d67ccefeac21, which added extra - parameter to st_foreach callbacks. - -commit e3fc30564e9466d6926f9d25a090dcf787bd5c33 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 15:53:57 +0900 - - rb_thread_create now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - rb_thread_create, which seems very safe to do. - -commit bc3e7924bc66d3ef77b219c72f3e59cc154550a3 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 15:35:28 +0900 - - rb_proc_new / rb_fiber_new now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - rb_proc_new / rb_fiber_new, and applies RB_BLOCK_CALL_FUNC_ARGLIST - wherever necessary. - -commit af5e2566405e4808a6d0a29c5b7d305d6fc0aada - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 15:27:48 +0900 - - rb_catch now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - rb_catch, and fixes some bugs revealed by that. - -commit 703783324c16b8b2b50210d1a7d1119902abbb8b - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 15:20:15 +0900 - - rb_ensure now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - rb_ensure, which also revealed many arity / type mismatches. - -commit 5c7c2d9951f2512ca10ea38fecc48d8ac67502e6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 14:51:00 +0900 - - rb_rescue / rb_rescue2 now free from ANYARGS - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - rb_rescue / rb_rescue2, which revealed many arity / type mismatches. - -commit 3cae73133cfec7d5ec3f8058ec647d5163578003 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 14:42:08 +0900 - - rb_iterate now takes rb_block_call_func_t - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit makes rb_iterate free - from ANYARGS. - -commit b8fd2e83e7b18fe3c70fc342388b1cb054b22e42 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 14:25:53 +0900 - - decouple compile.c usage of imemo_ifunc - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. This commit deletes ANYARGS from - struct vm_ifunc, but in doing so we also have to decouple the usage - of this struct in compile.c, which (I think) is an abuse of ANYARGS. - -commit 7329b3339adab12092056bd8159513645d4f9e8a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-26 13:30:04 +0900 - - #define RB_BLOCK_CALL_FUNC_STRICT 1 - - After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is - dangerous and should be extinct. Let's start from making - rb_block_call_func_t strict, and apply RB_BLOCK_CALL_FUNC_ARGLIST liberally. - -commit 0c8592b9af304dfcac0d08ba96d5f22ad8312e1a - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 14:11:02 +0900 - - fix function prototype mismatch of rb_block_call - - Nobu missed it in f0e73fc9862c8d2c57a89349fb79012b826b8245. - -commit 6007c7c3663fd1b92020cf60e806cc9634947d5d - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-27 13:03:47 +0900 - - delete rb_method_defined_by declaration. - - Ko1 missed this in d5893b91faa7dc77ca6c9728d1054dabd757aead. - -commit 2fb723b8af8dbcc2afc0fae7d434e66c2258dece - Author: Nobuyoshi Nakada - Date: 2019-08-27 15:11:01 +0900 - - Revert "Explain which test task" - - This reverts commit 9bc1667a188392b94971b9b96507af76cbd5f413. - - `name` lines are not expanded. - -commit 0c8525ecc987615f59fc68f2f767fc12217a7e4e - Author: Yusuke Endoh - Date: 2019-08-26 17:26:39 +0900 - - .github/workflows/coverage.yml: add a cron job for coverage in Actions - - Notes: - Merged: https://github.com/ruby/ruby/pull/2401 - -commit 9bc1667a188392b94971b9b96507af76cbd5f413 - Author: Nobuyoshi Nakada - Date: 2019-08-27 14:30:52 +0900 - - Explain which test task - -commit 2789bdddc7602fbc2089242d12e5cc4deed181c4 - Author: Nobuyoshi Nakada - Date: 2019-08-27 14:20:07 +0900 - - Use array indexing with considering clang's feeling - - ``` - In file included from sprintf.c:1256: - ./vsnprintf.c:833:8: warning: adding 'int' to a string does not append to the string [-Wstring-plus-int] - IS_PRI_EXTRA_MARK(fmt)) { - ^~~~~~~~~~~~~~~~~~~~~~ - ./vsnprintf.c:826:34: note: expanded from macro 'IS_PRI_EXTRA_MARK' - strncmp((s)+1, PRI_EXTRA_MARK+1, \ - ~~~~~~~~~~~~~~^~ - ./vsnprintf.c:833:8: note: use array indexing to silence this warning - ./vsnprintf.c:826:34: note: expanded from macro 'IS_PRI_EXTRA_MARK' - strncmp((s)+1, PRI_EXTRA_MARK+1, \ - ^ - 1 warning generated. - ``` - -commit d53b669948af29ca086d915c8bded0d1963e2c98 - Author: Yusuke Endoh - Date: 2019-08-27 14:05:20 +0900 - - compile.c: remove const from the first argument of dladdr - - Unfortunately, dladdr accepts void*, not const void*, in Solaris. - -commit 8eee3f3a3623d728c160c41546513594793fb7fb - Author: Yusuke Endoh - Date: 2019-08-27 13:57:25 +0900 - - signal.c: Don't mark ruby_abort as NORETURN on Solaris - - to suppress a warning. - - ``` - signal.c: In function 'ruby_abort': - signal.c:987:1: warning: 'noreturn' function does return - } - ^ - ``` - -commit 76abd79629bb4ed1e2811f4c9dcccf3165a8af3e - Author: Kazuhiro NISHIYAMA - Date: 2019-08-27 10:38:58 +0900 - - Fix the appropriate C++ compiler in OS X selection - - Merge space and slash to character class and add missing `CXX=` before `=g++-4.2` - at 5e10cb04e88c8a95ee44f6cad2bdf264e0dff92a - -commit 22834112650e33e16dd15529a260c0a42745168e - Author: Nobuyoshi Nakada - Date: 2019-08-27 07:59:10 +0900 - - Added license comment [Bug #12230] [ci skip] - -commit 744be55fad44f73e4966c1c6a2d601f1d31354b2 - Author: aycabta - Date: 2019-08-27 06:30:32 +0900 - - Remove duplicated delegation - -commit fd0a4a64a38d003621f6b11b5581bd453b12ed00 - Author: aycabta - Date: 2019-08-27 05:59:46 +0900 - - Delegete an instance method to a class method correctly - -commit 9f0f77717368783bfded08875ade2ea46b75fab7 - Author: Aaron Patterson - Date: 2019-08-27 05:41:54 +0900 - - this iv table should also use the new update function - -commit f13db4adde53299868b7523525e5aa2fe0a4b157 - Author: aycabta - Date: 2019-08-27 05:33:27 +0900 - - Save value to @ambiguous_width because of a accessor - -commit 978ff1ff3a0db5455d591e151f212f4eff0f86c0 - Author: aycabta - Date: 2019-08-27 05:24:13 +0900 - - Pick lib/readline.rb from ruby/reline - -commit f2a5c50f94cb53a418c09e53657292ab56347c2d - Author: aycabta - Date: 2019-08-27 05:10:25 +0900 - - The "private" doesn't make sense for class methods and a constant - -commit 68207bb4fc35c2f92ba8b5d5b091d6f93f580850 - Author: aycabta - Date: 2019-08-27 05:08:58 +0900 - - Use preposing "private" to define methods - -commit d8bcede9c357c5f0e743e736f698d1ebdada8f14 - Author: aycabta - Date: 2019-08-27 05:07:55 +0900 - - Adjust method forwardings of Reline - -commit 09d8e06b335d7647fa5e0385980ba3f1a67a592b - Author: Aaron Patterson - Date: 2019-08-27 03:31:52 +0900 - - Try only updating hash value references - - I'm afraid the keys to this hash are just integers, and those integers - may look like VALUE pointers when they are not. Since we don't mark the - keys to this hash, it's probably safe to say that none of them have - moved, so we shouldn't try to update the references either. - -commit d9bfbe363d14f8258d239eb702729926571b88e7 - Author: Aaron Patterson - Date: 2019-08-27 03:14:03 +0900 - - Make `gc_update_table_refs` match `mark_tbl_no_pin` a little more closely - - This commit just makes `gc_update_table_refs` match `mark_tbl_no_pin` - more closely. - -commit 3a4a58e2ccf13be874cc81e9c663bd39e687acd3 - Author: aycabta - Date: 2019-08-27 01:42:41 +0900 - - Fix use_lib_reline for test/readline - -commit 344f507e4e7f74477f29a8f72d1042a468ce8a42 - Author: manga_osyo - Date: 2019-08-24 01:34:00 +0900 - - Remove .freeze. - -commit 50d4a77041db71ce3110038109b65c3f059c0676 - Author: manga_osyo - Date: 2019-08-18 16:07:20 +0900 - - Add test with encoding. - -commit 0295bffc9645d8e6b40f60d285c69e861f439967 - Author: manga_osyo - Date: 2019-08-18 15:59:42 +0900 - - Change to test file path. - -commit 1ee9299bcab5c9a685fbf0b8b34d6abab157b2bc - Author: manga_osyo - Date: 2019-08-18 15:51:18 +0900 - - Add support Windows in CI. - -commit f33117fbc6a8fb90f94bb9ff2a4d948a19933c2a - Author: manga_osyo - Date: 2019-07-16 21:26:30 +0900 - - Add test reline. - -commit 195f545c14857d7eb76c2f7a76e6623f5285014f - Author: manga_osyo - Date: 2019-07-16 21:05:27 +0900 - - Fix `Reline::Windows`. - -commit 298ac047102f8651970b50a0096989a0b7df88ca - Author: manga_osyo - Date: 2019-07-15 03:10:26 +0900 - - Refactoring Reline. - -commit afed2668a6f6675536e967f053d7dec0b2026e2f - Author: manga_osyo - Date: 2019-07-15 03:08:36 +0900 - - Fix reference core method. - -commit f60e5a1f99088849fdc8ddfa84d594179c197a54 - Author: manga_osyo - Date: 2019-07-15 01:32:17 +0900 - - Remove test_mode in `lib/reline`. - -commit 9c0cd6a09eff793356ddc65a76b3fc72c61fee05 - Author: manga_osyo - Date: 2019-07-14 21:05:02 +0900 - - Refactoring Reline accessor. - -commit d5b237325b631e06775c2c7b5a8012b61ca5bccf - Author: git - Date: 2019-08-27 00:11:32 +0900 - - * 2019-08-27 [ci skip] - -commit 7d9c3a5712b00ebe059a63954674c10d247d1ec3 - Author: Jeremy Evans - Date: 2019-08-25 15:18:23 +0900 - - Handle binding.irb for frozen objects and BasicObjects using a delegate - - Fixes Ruby Bug 13264 - -commit caeafbe8252d13624a16acac703e4d04fcb19062 - Author: Jeremy Evans - Date: 2019-08-25 09:16:11 +0900 - - Move private call without arguments inside method - - This code did not have the desired effect. I'm not sure if - irb_binding is supposed to be private or not. If not, the private - call can just be removed. - -commit ccc5b22a7f4302a286cb16a797e8dccf422e8279 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-26 21:09:02 +0900 - - Expand JOBS instead of meaningless export (#2402) - - * Expand JOBS instead of meaningless export - - * Remove -j option in TESTOPTS of test-bundled-gems - - https://github.com/ruby/ruby/runs/203129516#step:10:167 - > invalid option: -j3 - - Notes: - Merged-By: znz - -commit 48f1a38f23f9a544e71c5656c83c419c064509fd - Author: Nobuyoshi Nakada - Date: 2019-08-26 18:21:04 +0900 - - Limit ChangeLog entries - - Since the previous release date, when the starting message is not - found. - -commit 972222c039bc5f5aa4a0d5bd6ec48ff4629e0fff - Author: Kazuhiro NISHIYAMA - Date: 2019-08-26 17:45:18 +0900 - - Show MFLAGS to check `Set ENV` in .github/workflows/ubuntu.yml - -commit 44bead391f32ece837e741c34474aa281c45ec94 - Author: Nobuyoshi Nakada - Date: 2019-08-26 16:38:08 +0900 - - CPPFLAGS is not needed for link - -commit 261465362222a2de6528c03aa8cc6d237f8435bb - Author: Nobuyoshi Nakada - Date: 2019-08-26 16:30:45 +0900 - - Moved INCFLAGS to XCFLAGS from CPPFLAGS as well as mswin - - Rules which have used CPPFLAGS will need XCFLAGS or INCFLAGS now. - -commit fafabe2f43ecd58588ac89edc5c177dd956825ad - Author: Nobuyoshi Nakada - Date: 2019-08-26 16:11:53 +0900 - - Add INCFLAGS for fake.rb - - INCFLAGS is not included in CPPFLAGS on mswin, not to be exported - to rbconfig.rb. - -commit b4d6d9c167a096c8647f989ae74e21c1929d227f - Author: Nobuyoshi Nakada - Date: 2019-08-26 13:14:01 +0900 - - Removed unnecessary flags for fake.rb - - Flags for ruby core such as warning and `_FORTIFY_SOURCE` macro - are not necessary to make fake.rb, except for `RUBY_EXPORT` macro - which prevents to include ruby/backward.h. - -commit 1581249de369e4d3e4ac09856bd10fb98cd4addb - Author: Nobuyoshi Nakada - Date: 2019-08-26 13:09:48 +0900 - - Added in-srcdir macro [ci skip] - -commit 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-23 12:14:06 +0900 - - uid_t and gid_t are narrower than VALUE. - - Often uid / gid are 16 bit or 32 bit integers, while VALUE are 32 - to 64 bits. They tend to differ in size. Because rb_ensure expects - its callbacks to take VALUE arguments, narrowing must be done by - hand, otherwise data corruption can happen depending on machine ABI. - -commit 48131a46730b76bdb252d24507980ea90c0166ad - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-23 10:10:59 +0900 - - rb_mjit_header.h is not worth documenting [ci skip] - - This is an auto-generated header file that does not include anything - interesting. Should skip generating CAPI documents. - -commit fa6c1b06ad65e18bd187b643c045e700f7081c2d - Author: Nobuyoshi Nakada - Date: 2019-08-26 11:58:55 +0900 - - Suppress a "clobbered" warning - -commit 4448d5864237de5d570f3d0ea80ddc53cf6f57fe - Author: git - Date: 2019-08-26 11:08:30 +0900 - - * 2019-08-26 [ci skip] - -commit 5e10cb04e88c8a95ee44f6cad2bdf264e0dff92a - Author: Nobuyoshi Nakada - Date: 2019-08-26 11:04:11 +0900 - - Refined the appropriate C++ compiler in OS X selection - - Allows CC to be prefixed another path or command, e.g., ccache. - -commit b4dfac2c125605881239fd62b7f458f52efff7ed - Author: Jeremy Evans - Date: 2019-08-26 04:53:15 +0900 - - Fix ArgumentError in expand_tabs.rb - - This fixes the following in my environment: - - misc/expand_tabs.rb:29:in `=~': invalid byte sequence in US-ASCII (ArgumentError) - - This switches from =~ to start_with? as a regular expression is - not actually needed here. - -commit e496e96547b64c3a2fa6f285c3bc9bd21a245ac6 - Author: Jeremy Evans - Date: 2019-08-26 04:50:19 +0900 - - Document that Enumerable#sum may not respect redefinition of Range#each - - It already documented that it may not respect redefinition - of Integer#+. - - Fixes [Bug #13700] - -commit 71d97a5ef80a23b0bb1005570ed059580981a467 - Author: Jeremy Evans - Date: 2019-08-26 02:52:58 +0900 - - Fix sample/drb/http0serv.rb - - Previously, trying to use this would result in: - - undefined method `uri' for # (NoMethodError) - - Also, use a relative require to load sample/drb/http0.rb. - - Fixes [Bug #13431] - -commit 365e5b38a9ca24116a9c3133e0a0e8ce230ccb02 - Author: Yusuke Endoh - Date: 2019-08-25 23:08:13 +0900 - - configure.ac: Improve icc_version guessing for non-icc environment - - icc_version was wrongly defined as "__ICC" on non-icc C compiler, which - caused a warning: - - ``` - ./configure: line 8211: test: __ICC: integer expression expected - ``` - - This change adds a sed command to delete "__ICC". - -commit 11f7c30fa7812388b8919453b92fdf5613db22dd - Author: Yusuke Endoh - Date: 2019-08-25 22:11:49 +0900 - - configure.ac: fix the guess of icc_version - - The icc_version guessing was accidentally disabled because of - 61885c9b7ca8ccdaf53d7c365fbb86bad3294d88; `AC_PROG_CC_C99` changes - CC like "icc -std=c99", and `AS_CASE(["x$CC"], [xicc],` does not match. - - The variable `icc_version` is eventually defined, so the `AS_CASE` is - not needed. This change removes the `AS_CASE`. - -commit fa5f7771f2312147d4b628205fdaf90afc3527e6 - Author: Takashi Kokubun - Date: 2019-08-25 20:10:24 +0900 - - Drop duration from AppVeyor notification - - The format is a little weird, and not so helpful either. - -commit 6944a1aa4f805c19faa3340f841a459f907f840e - Author: Yusuke Endoh - Date: 2019-08-25 19:29:52 +0900 - - lib/webrick.rb: use require_relative for webrick/utils.rb - - `require "webrick/utils.rb"` should load `lib/webrick/utils.rb`, but on - some CI machines, it wrongly loads `test/webrick/utils.rb`, which caused - circular require warning: - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu/ruby-master/log/20190825T093007Z.log.html.gz - ``` - /data/chkbuild/tmp/build/20190825T093007Z/ruby/lib/rubygems/core_ext/kernel_require.rb:61: warning: /data/chkbuild/tmp/build/20190825T093007Z/ruby/lib/rubygems/core_ext/kernel_require.rb:61: warning: loading in progress, circular require considered harmful - /data/chkbuild/tmp/build/20190825T093007Z/ruby/lib/webrick.rb - ``` - -commit c775ab5e2892a86e89cebc2c2d16e7b0fd190f19 - Author: Nobuyoshi Nakada - Date: 2019-08-25 18:27:57 +0900 - - `local_path?` is a class method [ci skip] - -commit cc6fe1524122ba7d890129c7fdbfd28edba198bf - Author: Yusuke Endoh - Date: 2019-08-25 16:59:45 +0900 - - tool/lib/vcs.rb: explicitly fail when notes/commits is not available - -commit 1b03d2d76be48039e8a4d609f36d221077a1daa9 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-25 13:58:30 +0900 - - Revert workaround - -commit 5decf66ab3395193160673ddd80395a5b3b86223 - Author: Nobuyoshi Nakada - Date: 2019-08-25 07:39:57 +0900 - - Inspect dynamic symbol as well as static symbol - -commit b341e98b041e5e0f1fd2f40145b0b3d9cd8fdc3f - Author: Nobuyoshi Nakada - Date: 2019-08-25 11:38:15 +0900 - - Simplified f13a00f5b4 [ci skip] - -commit f13a00f5b471f0f637c3f165daba235f24083bfc - Author: Nobuyoshi Nakada - Date: 2019-08-25 11:24:53 +0900 - - Export all commits as ChangeLog when no starting commit is found [ci skip] - -commit 04735c48ab44c97cbfd5a5cd37f9a1696e2f5a2b - Author: Jeremy Evans - Date: 2019-08-25 06:05:19 +0900 - - Minor documentation fixes [ci skip] - - From zverok (Victor Shepelev) - - Fixes [Misc #16126] - -commit e1c991f8d783440411e5bf4faf3f0923cef4a0e1 - Author: Jeremy Evans - Date: 2019-08-25 01:09:53 +0900 - - Move Object#hash rdoc to hash.c [ci skip] - - This gets RDoc to pick up the documentation correctly. - - Problem pointed out by zverok (Victor Shepelev). - -commit cf5516de7bff474030a820b63788e12f0b8b93d6 - Author: git - Date: 2019-08-25 00:51:59 +0900 - - * 2019-08-25 [ci skip] - -commit 03ee12a3b83ff9d56f3a993850cb134c2e16f846 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-25 00:50:34 +0900 - - Add workaround (2nd try) - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/gentoo/ruby-master/log/20190824T153002Z.fail.html.gz - ``` - /home/gentoo/chkbuild/tmp/build/20190824T153002Z/ruby/tool/lib/vcs.rb:577:in `export_changelog': cannot find the beginning revision of the branch (RuntimeError) - from ./tool/make-snapshot:353:in `block in package' - from ./tool/make-snapshot:351:in `chdir' - from ./tool/make-snapshot:351:in `package' - from ./tool/make-snapshot:523:in `block in
' - from ./tool/make-snapshot:523:in `collect' - from ./tool/make-snapshot:523:in `
' - ``` - -commit df348310dc2ba0b01f7dd7277184c688a5d430fe - Author: Kazuhiro NISHIYAMA - Date: 2019-08-24 23:17:12 +0900 - - Add workaround for some CIs - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian8/ruby-master/log/20190824T093005Z.fail.html.gz - ``` - branches: - * trunk - remotes/origin/trunk - ``` - and - ``` - fatal: Remote branch master not found in upstream origin - ``` - -commit 5d5502dc852cc7588c75c519f5c881ead577e827 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-24 21:26:24 +0900 - - Fix typos - -commit 571ffcd6094ccf1c68d4bfc36e425e0ee524e8b4 - Author: Yusuke Endoh - Date: 2019-08-24 20:31:16 +0900 - - ext/psych/yaml/api.c: Suppress a "variable set but not used" warning - - ``` - compiling ../.././ext/psych/yaml/api.c - ../.././ext/psych/yaml/api.c: In function 'yaml_document_delete': - ../.././ext/psych/yaml/api.c:1122:7: warning: variable 'context' set but not used [-Wunused-but-set-variable] - } context; - ^~~~~~~ - ``` - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu1604/ruby-master/log/20190824T093004Z.log.html.gz - -commit 97ad7862d5f65c48409a5301609af8448aaae16d - Author: Kazuhiro NISHIYAMA - Date: 2019-08-24 16:22:37 +0900 - - Add debug print - - master branch not found on some CIs - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian9/ruby-master/log/20190824T063005Z.fail.html.gz - ``` - fatal: Remote branch master not found in upstream origin - ``` - -commit fe83ed47e7e79208c0129a0005dcb9d569543893 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-24 10:20:44 +0900 - - Try to fix `make dist` error on chkbuild - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian9/ruby-master/log/20190823T213004Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian8/ruby-master/log/20190824T003006Z.fail.html.gz - -commit b38ab0a3a928939daf7c1772bf49065a3184b88a - Author: git - Date: 2019-08-24 01:41:09 +0900 - - * 2019-08-24 [ci skip] - -commit d5b917d50062559efb5b90ed093293d37e8a40b9 - Author: Nobuyoshi Nakada - Date: 2019-08-24 01:10:42 +0900 - - Named numbered parameter indexes - -commit 2e28b3678fc1b48f7dbca751d2a65d3fe0018789 - Author: Nobuyoshi Nakada - Date: 2019-08-23 20:43:15 +0900 - - [ruby/stringio] Fixed a typo - - https://github.com/ruby/stringio/commit/b249631c433f800c979be2705bf63555075db2fc#commitcomment-34804150 - - https://github.com/ruby/stringio/commit/998d6257fb - -commit d9b73dcc0d5e4c4613a89a1d58727b52bb5d1d10 - Author: Hiroshi SHIBATA - Date: 2019-08-23 17:18:37 +0900 - - Remove github_action_linux tag from bundler examples. - - Maybe it has fixed at 5a384e2c08704dc7af9d8d3bdfc475eb8c0723aa - - Notes: - Merged: https://github.com/ruby/ruby/pull/2399 - -commit 3b55394b07f29fac2717bb82fdc92140b2b302fe - Author: David Rodríguez - Date: 2019-02-19 20:57:41 +0900 - - Ensure all default gems have an gem folder - - Even if they don't ship with any executables. This makes rbinstall - behaviour consistent with rubygems `gem install --default` command. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2085 - -commit 1c5a2682392ece013ae95215d97f0561591b6dc6 - Author: Takashi Kokubun - Date: 2019-08-23 13:57:19 +0900 - - Simplify expand_tabs.rb file selection - -commit a5b809e994ce10d265e73f8c9d7c042e5e84d171 - Author: Nobuyoshi Nakada - Date: 2019-08-23 13:00:17 +0900 - - Check metadata a bit more - -commit 650cd245552d5c1abb244398b98d46ee280c4cd0 - Author: Nobuyoshi Nakada - Date: 2019-08-22 20:14:59 +0900 - - Hoisted out get_digest_obj_metadata - -commit 9ffb0548bf95e1113f5657453c64477e792d1230 - Author: git - Date: 2019-08-23 09:46:17 +0900 - - * 2019-08-23 [ci skip] - -commit 1d6a31f3d5b1e608dd6726918b64d2369e8df8b1 - Author: Takashi Kokubun - Date: 2019-08-23 09:45:46 +0900 - - Make AppVeyor notification similar to Travis - -commit fd20b32130f52f4a7799a8d7a367f5b39636bc6a - Author: Takashi Kokubun - Date: 2019-08-22 23:10:54 +0900 - - Make GitHub Actions Slack notification consistent - - with Travis, rather than AppVeyor. - - Formerly it was made similar to AppVeyor to provide some normal set of - CI failure notification. But for some reason people preferred a shorter - variant and introduced a1d606c079f6c3d1779d885e0bf2e3991251609e and - d8d8015b93c6daa8d8433895464db3493a2056e2. - - Instead of AppVeyor format, this commit chose Travis-like format to achieve - consistency and to include usual CI-failure information, while keeping - it one-liner for people who prefer short notifications. - - Note that this shrinks the 40-char sha to 10-char, using the new feature - of k0kubun/action-slack@v2.0.0: - https://github.com/k0kubun/action-slack/commit/1c88a05dac664cbafa1c99a37f292ed23ac1c289 - -commit efc89703365fa787c012370c18803bae67924526 - Author: git - Date: 2019-08-22 22:47:05 +0900 - - * expand tabs. [ci skip] - - Tabs are expanded because previously the file did not have any tab indentation. - Please update your editor config, and use misc/expand_tabs.rb in the pre-commit hook. - -commit a4d389d8fe87b6af9e5fac0e430d56a4ee9b8470 - Author: Takashi Kokubun - Date: 2019-08-22 22:46:29 +0900 - - Improve the description of MJIT cancel-all [ci skip] - -commit 15eaedf805fb2727c79a6c59af6d5f6c2a6d634b - Author: Takashi Kokubun - Date: 2019-08-22 21:13:34 +0900 - - Add misc/expand_tabs.rb ported from auto-style.rb - - This is implemented to close [Misc #16112] because all other options got - at least one objection, and nobody has objected to this solution. - - This code is a little complicated for the purpose, but that's just - because it includes some historical code for auto-style.rb: - https://github.com/ruby/ruby-commit-hook/blob/918a7c31b69ad2f7b125608c1c6a1f4fd01ec15a/bin/auto-style.rb - - Please feel free to improve this file as you like. - - [Misc #16112] - -commit d8d8015b93c6daa8d8433895464db3493a2056e2 - Author: aycabta - Date: 2019-08-22 09:24:35 +0900 - - Remove footer from message to Slack - -commit a1d606c079f6c3d1779d885e0bf2e3991251609e - Author: aycabta - Date: 2019-08-22 07:57:06 +0900 - - Show short message to Slack - -commit 1940347fdfe44a515a4d4ba31f068a245570b70d - Author: Hiroshi SHIBATA - Date: 2019-08-22 07:21:43 +0900 - - Use () instead of {} for nmake - -commit 2d8d6345ffba384c2825225c0b9c972629ff0d5b - Author: Hiroshi SHIBATA - Date: 2019-08-22 07:03:54 +0900 - - `--fomart progress` is default. It's duplicated. - -commit 0b0fedad7098b70686ef9f3c931a8c9c93d5b00c - Author: Hiroshi SHIBATA - Date: 2019-08-22 07:02:48 +0900 - - Introduce test-bundler-parallel task. - -commit 800821831d6b4319e82d23291d3127212a2e7334 - Author: aycabta - Date: 2019-08-22 06:02:21 +0900 - - Always check multiline termination - -commit 8d804e41a013ab1967a703a0ce388b579f735ac8 - Author: Fernando Wolf Bona - Date: 2019-08-22 05:36:39 +0900 - - Add abs to Matrix (#2199) - -commit 48fdc37ad52d9a59763da4c1c22683713b7ddea8 - Author: aycabta - Date: 2019-08-22 05:07:59 +0900 - - IRB's multiline history is enable only when Reidline mode - -commit 6bdb65c0e6383f2ef845b8f4b0cc3c03e8aec118 - Author: git - Date: 2019-08-22 00:20:27 +0900 - - * 2019-08-22 [ci skip] - -commit a9638511009bb8847dfb037d05bdbbdd685066e7 - Author: Nobuyoshi Nakada - Date: 2019-08-21 16:41:06 +0900 - - Hoisted out rb_id_metadata - -commit 74c6662af5d9748baff7c32e8f0baf7996dd898e - Author: Nobuyoshi Nakada - Date: 2019-08-21 16:31:26 +0900 - - Hoisted out rb_digest_namespace - -commit c030cec7cac3bacd230b87c9610bc67d8b89ab26 - Author: Takashi Kokubun - Date: 2019-08-21 23:13:20 +0900 - - Debug GitHub context on broken notification - - sometimes Slack notification footer becomes just " at ". - It seems like `github.event.head_commit` is missing. Let me debug the - context. - -commit 3df9f3cc13b126cb270743c82f2c037c30a98103 - Author: Nobuyoshi Nakada - Date: 2019-08-21 16:20:31 +0900 - - Separated initializing IDs - -commit 4419b5dbc2e3fe4ec3ac27e3d8b8a2b357f27426 - Author: Nobuyoshi Nakada - Date: 2019-08-21 13:30:43 +0900 - - The investigation is going on... - -commit 81dfe3c47bb397a0a54ee10c6913112181a8466d - Author: Jeremy Evans - Date: 2019-08-21 13:26:12 +0900 - - Enable more Time TZ tests on OpenBSD - -commit a230e65e8b08003c6b346e6ef177bc8655de55b7 - Author: lolwut - Date: 2019-08-16 22:12:40 +0900 - - [bundler/bundler] Freeze time to avoid failures at midnight - - Specify just a string - - set @built_at as nil before testing - - https://github.com/bundler/bundler/commit/578ec96c9c - -commit 1c2774526eef733ea95e5dda576c95169341ba7e - Author: Hiroshi SHIBATA - Date: 2019-08-19 12:51:19 +0900 - - [bundler/bundler] Share test fixtures with parallel_tests - - https://github.com/bundler/bundler/commit/a38161c5be - -commit 10011f4371c4d6f9a5e49b210800beba1e3e3722 - Author: Hiroshi SHIBATA - Date: 2019-08-19 11:36:17 +0900 - - [bundler/bundler] Try to use RunTimeLogger for parallel_tests - - https://github.com/bundler/bundler/commit/faccc522d1 - -commit ace88852f2c2dae52118d80cbf5800ea99e409e6 - Author: David Rodríguez - Date: 2019-01-25 01:28:02 +0900 - - [bundler/bundler] Parallelize test suite - - https://github.com/bundler/bundler/commit/23007cb107 - -commit ede77d82e709956cd1d3c849840107c84cd2e911 - Author: David Rodríguez - Date: 2019-08-15 23:47:18 +0900 - - [bundler/bundler] Fix a couple of typos - - https://github.com/bundler/bundler/commit/52b6b94068 - -commit 1120bacd8b8656b45a56487ee62fd48095aca019 - Author: David Rodríguez - Date: 2019-08-18 06:11:38 +0900 - - [bundler/bundler] Remove the :ruby exclusion tag - - Our current set of specs is the same for all supported rubies, and we - should keep it that way. - - https://github.com/bundler/bundler/commit/c9dc0f6f2c - -commit bcc4ac924d495d74d5ce56c7d4c735a1df320220 - Author: David Rodríguez - Date: 2019-08-18 05:03:26 +0900 - - [bundler/bundler] Remove another 1.8.7 specific bit - - https://github.com/bundler/bundler/commit/8c7942d2c6 - -commit 5ea08883cfc90e05e5fb76e1e10cee1818a40c9e - Author: David Rodríguez - Date: 2019-08-18 05:00:52 +0900 - - [bundler/bundler] Remove old rubies stuff no longer needed - - https://github.com/bundler/bundler/commit/36fb3287f4 - -commit 864f23a457291e64cb6a0703dcc0b3e26e4cf109 - Author: git - Date: 2019-08-21 01:04:27 +0900 - - * 2019-08-21 [ci skip] - -commit 88b1f2dac430d7b10fc98c5a072c4edfeb51b27a - Author: Koichi Sasada - Date: 2019-08-21 01:04:08 +0900 - - `rp(obj)` shows func, file and line. (#2394) - - rp() macro for debug also shows file location and function name - such as: - - [OBJ_INFO:rb_call_inits@inits.c:73] 0x000056147741b248 ... - - Notes: - Merged-By: ko1 - -commit d10e28b875a58e2c4422b8df8f4bbcc2fb0362d0 - Author: Takashi Kokubun - Date: 2019-08-20 23:58:36 +0900 - - Skip tests on Actions if [ci skip] - - It seems that we cannot easily apply job-level [ci skip]. - Therefore this commit skips only Tests step if it's [ci skip]. - -commit 235d810c2ecd1289c963f6dc6cce78ae2572d034 - Author: Takashi Kokubun - Date: 2019-08-20 22:31:41 +0900 - - Deprecate alerting multiple channels - - Some CIs report to two channels, and some others report to only one. - This makes it consistent. Only alert channel should be alerted. - -commit 9557069299ac3b96691040a541afa65761a724ad - Author: Akira Matsuda - Date: 2019-08-20 22:08:41 +0900 - - Avoid creating Hash objects per each mon_synchronize call (#2393) - - Notes: - Merged-By: amatsuda - -commit af121720357e3bcf3d45c0f578d262770c7f45c9 - Author: Nobuyoshi Nakada - Date: 2019-08-20 19:26:12 +0900 - - Removed unused literal assignments [ci skip] - -commit 7a07c54bef599b7b0ce1dd8a6c13021f03a8220d - Author: Nobuyoshi Nakada - Date: 2019-08-20 19:20:22 +0900 - - Subjects may contain a comma [ci skip] - -commit 73af1c4d0078dc3be0cbeca2445047be5c0d852b - Author: Nobuyoshi Nakada - Date: 2019-08-20 13:56:04 +0900 - - [rubygems/rubygems] Use `RbConfig::CONFIG['rubylibprefix']` - - It is defined since ruby 1.9.2. - - https://github.com/rubygems/rubygems/commit/84981ca908 - -commit dd58c4ba3576d5dc1489767a25de9540b79b0ef9 - Author: Nobuyoshi Nakada - Date: 2019-08-20 16:07:43 +0900 - - Investigation of a sporadic error at Github Actions - -commit 5a384e2c08704dc7af9d8d3bdfc475eb8c0723aa - Author: David Rodríguez - Date: 2019-08-20 09:46:31 +0900 - - Fix some bundler specs (#2380) - - * These seem to consistently pass already - - * Show actual command when running `make test-bundler` - - Current the setup command that installs the necessary gems for testing - bundler was printed, but not the actual command that runs the tests. - That was a bit confusing. - - * Borrow trick from setproctitle specs - - * A title that long doesn't get set sometimes - - No idea why, but the test doesn't need that the title is that long. - - * Fix most gem helper spec ruby-core failures - - * Fix the rest of the gem helper failures - - * Fix version spec by improving the assertion - - * Remove unnecessary `BUNDLE_RUBY` environment var - - We can use `RUBY` when necessary, and `BUNDLE_RUBY` is not a good name - because bundler considers `BUNDLE_*` variables as settings. - - * Rename `BUNDLE_GEM` to `GEM_COMMAND` - - This is more descriptive I think, and also friendlier for bundler - because `BUNDLE_` env variables are interpreted by bundler as settings, - and this is not a bundler setting. - - This fixes one bundler spec failure in config specs against ruby-core. - - * Fix quality spec when run in core - - Use the proper path helper. - - * Fix dummy lib builder to never load default gems - - If a dummy library is named as a default gem, when requiring the library - from its executable, the default gem would be loaded when running from - core, because in core all default gems share path with bundler, and thus - they are always in the $LOAD_PATH. We fix the issue by loading lib - relatively inside dummy lib executables. - - * More exact assertions - - Sometimes I have the problem that I do some "print debugging" inside - specs, and suddently the spec passes. This happens when the assertion is - too relaxed, and the things I print make it match, specially when they - are simple strings like "1.0" than can be easily be part of gem paths - that I print for debugging. - - I fix this by making a more exact assertion. - - * Detect the correct shebang when ENV["RUBY"] is set - - * Relax assertion - - So that the spec passes even if another paths containing "ext" are in - the load path. This works to fix a ruby-core issue, but it's a better - assertion in general. We just want to know that the extension path was - added. - - * Use folder structure independent path helper - - It should fix this spec for ruby-core. - - * Fix the last failing spec on ruby-core - - * Skip `bundle open ` spec when no default gems - -commit aa03de8ba13e5ffa7049d3a881d2f5fe70dd4092 - Author: aycabta - Date: 2019-08-20 08:24:50 +0900 - - Treat two types "do" correctly - - A "do" what has followed a token what has EXPR_CMDARG is for a block, - and in other cases "do" is for "while", "until" or "for". - -commit dc0e45e39b37556af8abf6cdb0180e2973041931 - Author: Alan Wu - Date: 2019-08-19 13:42:29 +0900 - - Update moved objects in original_iseq - - Without doing this, enabling a TracePoint on a method could lead to use - of moved objects. This was found by running - `env RUBY_ISEQ_DUMP_DEBUG=to_binary make test-all`, which sets - orignal_iseq then runs the compaction tests and the tracepoint tests. - - Please excuse the lack of tests. I was not able to figure out how to - reliably trigger a move on a specific iseq imemo to make a good - regression test. - - To manually confirm the problem and this fix, you can run: - ``` - env RUBY_ISEQ_DUMP_DEBUG=to_binary make test-all \ - TESTOPTS="test/ruby/test_gc_compact.rb \ - test/gdbm/test_gdbm.rb \ - test/ruby/test_settracefunc.rb" - ``` - - Or the following script: - - ```ruby - tp = TracePoint.new(:line) {} - 1.times do # put it in a block to not keep these objects alive - objects = 10_000.times.map { Object.new } - objects.hash - end - - 1.times do - # this allocation pattern can realistically happen in an app - # at load time - beek = 10_000.times.map do - eval(<<-RUBY) - def foo - a + b - 1.times { - 4 + 234234 - } - nil + 234 - end - RUBY - Object.new - Object.new - end - beek.hash - end - - tp.enable(target: self.:foo) { 234 } # allocate original iseq - - GC.verify_compaction_references(toward: :empty) - GC.compact - - tp.enable(target: self.:foo) { 234234 } # crash - ``` - - [Bug #16098] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2391 - -commit 19b0161b851ba32d5bc6c367db5b520d35905d6b - Author: Nobuyoshi Nakada - Date: 2019-08-20 01:58:45 +0900 - - Check whether syscall(2) is deprecated by actual warnings - -commit 588b74e8d84532d3eb0e4aa06372b7a6b171b9cd - Author: Nobuyoshi Nakada - Date: 2019-08-20 01:11:28 +0900 - - Check for minimum required OSX version earlier - -commit 9ee770a2ce57fce9a5dedf6c6c35ca8e02fd044b - Author: Nobuyoshi Nakada - Date: 2019-08-20 00:39:06 +0900 - - Bail out if unsupported old MacOSX is required - -commit af2c8d283665f741f82b4e16b06c520e702c012b - Author: Nobuyoshi Nakada - Date: 2019-08-20 00:18:07 +0900 - - Fixed the check for OSX version - - Should compare minimum required version, and with the particular - macro defined for each version. Also made the error messages - consistent. - -commit e6b72e8cae786c9752cc34541b58b5635d5c76bb - Author: David Carlier - Date: 2019-08-19 23:36:47 +0900 - - retrieve current path on macOS - - Notes: - Merged: https://github.com/ruby/ruby/pull/2390 - -commit 1408f15921a8a051055a68fb96e050a7d4cd35fb - Author: git - Date: 2019-08-20 00:21:17 +0900 - - * 2019-08-20 [ci skip] - -commit 8df25214de1a240ec6859415692b29955d2d423a - Author: Yusuke Endoh - Date: 2019-08-20 00:17:26 +0900 - - io.c: make ioctl_req_t int in Android - - The second argument of ioctl seems to be int in Android. - Android is not a supported platform, but this one-line change allows - ruby to build by Android NDK r20. - -commit 45bed2850e5bf31c3528cf3559e76c3823bb4340 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-19 19:37:07 +0900 - - Reduce sub-shell and use `&&` instead of `;` - -commit 8882986d9701ef8be4cdd87e64a30321f1738cee - Author: Kenichi Kamiya - Date: 2019-08-19 18:43:23 +0900 - - Drop duplicated sample code (#2389) [ci skip] - - * Drop duplicated sample code - - * Drop another style sample - - https://github.com/ruby/ruby/pull/2389#issuecomment-522489520 - - * Update sample list - -commit 209ea85b54c9229f0c1e5c730dee05a096599eb0 - Author: Hiroshi SHIBATA - Date: 2019-08-19 18:37:22 +0900 - - Make portable for standalone test-unit gem. - - * It can invoke test-unit with envutil.rb - * refute_match of test-unit couldn't handle String instance. - -commit 9b330200f8e180ca393cac25f811f6194990aaa4 - Author: Kenichi Kamiya - Date: 2019-08-19 18:16:45 +0900 - - Remove unused variable to suppress warning (#2388) [ci skip] - - ``` - sample/observe.rb:30: warning: assigned but unused variable - clock - ``` - -commit 97c377e2b1954b977b015f11183b201ad4a88bd6 - Author: Takashi Kokubun - Date: 2019-08-19 18:11:51 +0900 - - Mark Travis osx cron-only - - because it has often hanged like - https://travis-ci.org/ruby/ruby/jobs/573691637, - and we also have almost the same test suite on GitHub Actions now, which - seems to be stable in `make check` so far. - -commit cda8664471b5c2adb9d1ea9563ac38378621d0fd - Author: Kenichi Kamiya - Date: 2019-08-19 18:00:29 +0900 - - Update a sample code (#2387) - - Kernel#inspect does not call #to_s now - - To follow https://github.com/ruby/ruby/commit/fd7dc23d281f38a71fa7f9c32812cd468c4b1788 - -commit 355acbafde40c04b8586e1d9185b4965552e00fd - Author: Hiroshi SHIBATA - Date: 2019-08-19 17:52:13 +0900 - - Update the canonical repository url - -commit 6dd9736c3a73ecd9b0dcf47348a81fb934eb88b3 - Author: David CARLIER - Date: 2019-08-19 17:36:28 +0900 - - crash report on mac little update - - displaying vm info as Linux and FreeBSD. - checking libproc as it is present only from 10.5 version. - - https://github.com/ruby/ruby/pull/2384 - -commit 605d2ce9b98c4306505c8be05483e3d296db5f1e - Author: Kenichi Kamiya - Date: 2019-08-19 17:30:59 +0900 - - Accurate a sample to show having some ext (#2385) - -commit 45454bdb8b25def782677dceb92cfd7b2d8b83c1 - Author: Nobuyoshi Nakada - Date: 2019-08-19 16:37:29 +0900 - - Prefer Regexp#=~ to Regexp#match when the RHS may be nil - -commit b4daa442704204b93a586fb7b696998f33b29c72 - Author: Nobuyoshi Nakada - Date: 2019-08-19 16:32:57 +0900 - - Use modifier for pid_t - -commit 8108594f4701b02bfb7b90b7c2585a8214d8e64d - Author: Nobuyoshi Nakada - Date: 2019-08-19 16:18:54 +0900 - - unsigned int should have enough bits for rb_thread_shield_waiting - -commit 1bd60c66d385142d08f678f8a9563c311cfc3fe8 - Author: Nobuyoshi Nakada - Date: 2019-08-19 15:55:53 +0900 - - Fix FL_USER19 - - * include/ruby/ruby.h: cast via `unsigned int` explicitly, to get - rid of signed extension by implicit integer promotion. - -commit 4515bcc922376771c56733745c7595e14449b6d8 - Author: NAKAMURA Usaku - Date: 2019-08-19 15:37:28 +0900 - - Omit version.h when merging - -commit c5db4c28f9349eb296a360dc08d6b88be66916d1 - Author: Yusuke Endoh - Date: 2019-08-19 15:01:48 +0900 - - cont.c: remove unused STACK_GROW_DIR_DETECTION - - to suppress a warning for "unused variable" - -commit 6c2aa8689ade82578e9e16be37e21e16eb7ce069 - Author: Takashi Kokubun - Date: 2019-08-19 14:59:58 +0900 - - Roughly retry `brew update` - - as it failed randomly https://github.com/ruby/ruby/runs/196712109 - -commit 39a43d9cd09f8c880d0a70d9cb8ede6d7e6ef583 - Author: Benoit Daloze - Date: 2019-08-19 14:51:00 +0900 - - Make it as clear as possible that RubyVM is MRI-specific and only exists on MRI (#2113) [ci skip] - - * Make it clear as possible that RubyVM is MRI-specific and only exists on MRI - - * See [Bug #15743]. - * Use "CRuby VM" instead of "Ruby VM" for clarity. - - * Use YARV rather than "CRuby VM" for documenting RubyVM::InstructionSequence - - * Avoid introducing a new "CRuby VM" term in documentation - -commit d76be10df11cf24d7a5a1f88a4aadc6d817db4a7 - Author: Yusuke Endoh - Date: 2019-08-19 14:43:15 +0900 - - missing/memcmp.c: suppress a `-Wparentheses` warning - -commit 1f3f50fb5eb08ede6cfaf450e0d7db797ec46c95 - Author: git - Date: 2019-08-19 14:34:29 +0900 - - * expand tabs. [ci skip] - -commit 574a9edfb3c20165c919d447902d1052165b2132 - Author: Nobuyoshi Nakada - Date: 2019-08-19 14:34:13 +0900 - - Set flag to allow unprivileged users to create symlinks (#2381) - - * [Win32] set flag to allow unprivileged users to create symlinks - - Notes: - Merged-By: nobu - -commit bc1e2271af54087cb3b9e4a0cdceeead56ee3a1a - Author: Yusuke Endoh - Date: 2019-08-19 09:45:41 +0900 - - lib/rdoc/markup/parser.rb: remove a unused variable initialization - -commit 4c13368972366507b741be60602f314b85861f52 - Author: Takashi Kokubun - Date: 2019-08-19 09:46:55 +0900 - - Make AppVeyor notification colors consistent - - It was using the same one as original AppVeyor's notification, but it's - just inconsistent with others like Travis and GitHub Actions. - -commit d106f082915cbab454d5a7dc3661cea5136f42cf - Author: Takashi Kokubun - Date: 2019-08-19 09:41:51 +0900 - - Stop reporting test-bundled-gems results - - by marking continue-on-error. - - I dropped it to test Slack notification, and I finished to test it. - -commit c100e3856a624f10b461d202f07f49791aa29c89 - Author: Takashi Kokubun - Date: 2019-08-19 03:40:33 +0900 - - Workaround errors on multi-line commit message - - by using toJson with fields. - -commit e139d27748a0548c0ae10fb483c7389caacd4b3d - Author: Takashi Kokubun - Date: 2019-08-19 03:14:18 +0900 - - Make Slack notification available - - for macOS / Windows as well. - - Docker-based GitHub Action does not work on these OSes. - -commit aa5fbb5a7661fa5329881415e65a24151507e69a - Author: git - Date: 2019-08-19 01:50:18 +0900 - - * 2019-08-19 [ci skip] - -commit 2f6c8ed26eec4ad2d2fdaa0823cc63ba32f4c7a2 - Author: Takashi Kokubun - Date: 2019-08-19 01:49:51 +0900 - - Implement Slack notification for Actions - -commit e4c43207f9c7c56ecc76bb941c08a686a242b1de - Author: Takashi Kokubun - Date: 2019-08-18 23:32:49 +0900 - - Revert "Try notifying Slack from Actions" - - This reverts commit d8807e8b1a9d09ee1543e18618b4ef7e8203c616. - - We'd need more features. Reverting to customize this later. - -commit d8807e8b1a9d09ee1543e18618b4ef7e8203c616 - Author: Takashi Kokubun - Date: 2019-08-18 23:19:09 +0900 - - Try notifying Slack from Actions - - https://github.com/8398a7/action-slack - https://github.com/marketplace/actions/action-slack - -commit 829b800c10086ee504995c6e088d87370c552c40 - Author: Takashi Kokubun - Date: 2019-08-18 19:09:40 +0900 - - Reorder Travis matrix.include - - to clarify what's running for every commit. - -commit 51edcbad5be46af800961aabc7b45f0ce6509990 - Author: Hiroshi SHIBATA - Date: 2019-08-18 18:08:38 +0900 - - Use master branch instead of trunk. - -commit 9132153930b88b5ffeb95d42081c05d5eceb2d90 - Author: Hiroshi SHIBATA - Date: 2019-08-18 17:40:01 +0900 - - Ignore tags on default gems from ruby core repository. - -commit ad0ea708caec880c3f357fe761c215efc169fa55 - Author: Takashi Kokubun - Date: 2019-08-18 15:48:52 +0900 - - Drop before_test for mswin too - - for consistency. In the pull request, `before_test` was dropped only for - msys2 to fix msys2-only failure. But there's no need to keep it - inconsistent now. - -commit cba8166cc198509f236e1e8ed2feb7a1304f6718 - Author: MSP-Greg - Date: 2019-08-18 15:47:19 +0900 - - Appveyor - vc120 use OpenSSL 1.0.2, vc140 use 1.1.1 (#1998) - - * appveyor.yml - OpenSSL vc120 -> 1.0.2, vc140 -> 1.1.1 - - * Try just using build_script - -commit 6b42b0c60ce51cc8228892e6a99c83fefb19f131 - Author: Masataka Pocke Kuwabara - Date: 2019-08-18 15:39:19 +0900 - - Fix document of `GC.start` (#2382) - -commit d3da1d57d3c184298b7f6fb5083a39bd22cc9a4f - Author: Hiroshi SHIBATA - Date: 2019-08-18 15:02:21 +0900 - - Skip open_spec.rb:L95 because ruby repo doesn't have json as default gems. - -commit a77b3b4476241b6b4246fc805ac5fc357f8c4e57 - Author: David Rodríguez - Date: 2019-08-17 20:39:56 +0900 - - [bundler/bundler] Remove unnecessary require - - https://github.com/bundler/bundler/commit/8ef571ed4e - -commit 683f9e1dbf42aa4b326b244f1d4dbbbdcb9e8ceb - Author: David Rodríguez - Date: 2019-08-17 00:45:00 +0900 - - [bundler/bundler] No need to activate the `fileutils` default gem - - The version we're vendoring actually relaxed this restriction back to - 2.3.0+, so we can always use the vendored version. - - https://github.com/bundler/bundler/commit/d366cbfe5d - -commit 4756c5f7e79642484d01a7dbca17357eb8b08ef1 - Author: David Rodríguez - Date: 2019-07-24 01:44:21 +0900 - - [bundler/bundler] Remove unnecessary rubygems monkeypatch - - Instead, make sure we always load the local copy of bundler during - specs, and never end up using the default copy. - - https://github.com/bundler/bundler/commit/ac655ffeda - -commit 5a69a23afcc39a87bf808f484fa476978a9a0b4d - Author: David Rodríguez - Date: 2019-08-17 00:54:12 +0900 - - [bundler/bundler] Don't use system bundler on this spec - - If we use system bundler, when booting the "outermost" bundler process, - bundler will save the path to the system bundler in BUNDLE_BIN_PATH, and - use it again when booting the "innermost" bundler process (`bundle exec - echo foo`). - - That means that second process will use the system bundler path again. - However, we have `-rsupport/hax` in RUBYOPT, so that file will load from - the local copy of bundler, and that file will load `bundler/version` - from the project (not from system), because -Ilib is in the LOAD_PATH. - - That will end up causing redefinition errors because the same constant - will be loaded from two different locations. - - In general, this is expected behavior, normally you will wrap the - process with `Bundler.with_original_env` to reset the environment. - However, the easiest fix here is to not use system bundler, because it's - not really necessary and thus doesn't help the readability of the spec. - - https://github.com/bundler/bundler/commit/a3d72a34ab - -commit 0653d8c6018dc9f52856c7b38188c88669be2c83 - Author: David Rodríguez - Date: 2019-08-17 00:51:18 +0900 - - [bundler/bundler] Fix spec using the deprecated `bundle config` mode - - https://github.com/bundler/bundler/commit/789dd1864f - -commit c50c2354cf9a43978626e5573e72574516b28da9 - Author: David Rodríguez - Date: 2019-08-02 21:08:28 +0900 - - [bundler/bundler] Require relatively from exe/ when possible - - https://github.com/bundler/bundler/commit/e4cbb91b7d - -commit 998204882b25f0cee5db1749a877ef9780c8925f - Author: David Rodríguez - Date: 2019-08-02 20:23:20 +0900 - - [bundler/bundler] Last relative requires - - https://github.com/bundler/bundler/commit/fb587b9ebb - -commit f753961611d286332e968f3b30f9b55b8590ef7d - Author: David Rodríguez - Date: 2019-08-03 19:22:36 +0900 - - [bundler/bundler] Remove a bunch of unneeded rubygems requires - - https://github.com/bundler/bundler/commit/f9cb39e614 - -commit 7659f00a8dd1df0e823cd5a47c6b4036c94e1321 - Author: David Rodríguez - Date: 2019-08-16 22:56:19 +0900 - - [bundler/bundler] Move local variable to only branch where it's used - - https://github.com/bundler/bundler/commit/3995b3345d - -commit d80f5399adc3564d05339e6dff92ea1e95fb280a - Author: Zehan Zhao - Date: 2016-08-15 23:44:19 +0900 - - [bundler/bundler] Fix open default gem error - - https://github.com/bundler/bundler/commit/792d724752 - -commit 98841b2b19fc2d5c6aacda26019ff07d48d971ec - Author: David Rodríguez - Date: 2019-08-10 04:48:38 +0900 - - [bundler/bundler] Wrap `open` specs with a context - - So I can add another context that doesn't run the `before` block. - - https://github.com/bundler/bundler/commit/06d0acc45a - -commit e6e8d2d8c06336bfcd030a2d8cf69b980446dd40 - Author: David Rodríguez - Date: 2019-08-10 04:47:09 +0900 - - [bundler/bundler] Prefer `before` to `before :each` - - https://github.com/bundler/bundler/commit/6678747fae - -commit cc644c7116c7e540809e381be9d16a2f29a45f43 - Author: David Rodríguez - Date: 2019-08-16 21:02:03 +0900 - - [bundler/bundler] Fix `bundle doctor` command - - Previously `bundle doctor` would fail on any bundle that does not - include git gems or plugins. This is because the previously used - `Bundler.home` does not exist unless the bundle includes git gems or - plugins. For example, with `bundle config set path .bundle`, it points - to which does not exist unless this kind of gems exist in the Gemfile. - - The name `Bundler.home` is really unfortunate, it should probably be - have more descriptive name, and be private. But for now I just want to - make `bundle doctor` usable. - - https://github.com/bundler/bundler/commit/5531a18c1e - -commit a02dbcecb15bff9c2a21f5d5e021707a3b150a57 - Author: David Stosik - Date: 2019-08-15 14:47:57 +0900 - - [bundler/bundler] Bundler displays a duplicate gem entries warning even if gems only appear once per group - - https://github.com/bundler/bundler/commit/d18a83109e - -commit 3ecb5125c62bf68a7b74c5c48c659c0d165e624f - Author: Hiroshi SHIBATA - Date: 2019-08-18 13:25:13 +0900 - - Gem::ConfigMap is deprecated now - -commit a0e80c7cb75d9688a23872ce87ac0354a7b985ad - Author: Takashi Kokubun - Date: 2019-08-18 09:30:33 +0900 - - Drop continue-on-error for make check - - Like macos.yml, we don't need to ignore `make check` failure. - -commit 50623f3df0c1c82d6995053000285c208835efe8 - Author: aycabta - Date: 2019-08-18 08:04:06 +0900 - - Remove commented out debug print - -commit 113a5c1e1dc8a16e4c8d19af3c9d091eb90826f3 - Author: aycabta - Date: 2019-08-18 08:03:32 +0900 - - The "exe" dir doesn't exist in this repostiroy - -commit 0bbbe8298629a3acbf6c3dd84a302ff71edc80e8 - Author: aycabta - Date: 2019-08-18 07:52:49 +0900 - - Fix copy path of ruby/reline's test - -commit e9f82585eed414ff090d9ef7b667d0f3c1561a01 - Author: Alan Wu - Date: 2019-08-09 07:38:40 +0900 - - Don't crash when deleting at the end of the line - - To reproduce this bug, type one character into irb, then press the - delete key on your keyboard. - -commit 7bb0a7d7cba7bbeb03d531c13ccf73b6d4e688f6 - Author: Nobuyoshi Nakada - Date: 2019-08-17 23:35:35 +0900 - - Prefer exact ITEM to benchmark - -commit 74ca6b88dd9673d2a47ce4bbfd9214dcea5ee366 - Author: Nobuyoshi Nakada - Date: 2019-08-17 23:33:12 +0900 - - Omit a tag unless loading with a wrapper module - -commit 1d11a8b1938d3310d6b573c2feb173661a82b6a6 - Author: Nobuyoshi Nakada - Date: 2019-08-17 23:29:54 +0900 - - Ensure non-OPT_GLOBAL_METHOD_CACHE code valid - -commit 6db3051fcc08440fb1d80617dae90ae3f97db95c - Author: Nobuyoshi Nakada - Date: 2019-08-17 23:28:46 +0900 - - Ensure VM_DEBUG_VERIFY_METHOD_CACHE code valid - -commit aa00f7b8ec97b8ca6e2e2b8f31825dca4a2ae91b - Author: git - Date: 2019-08-18 00:33:13 +0900 - - * 2019-08-18 [ci skip] - -commit 8b8e7e6e9ec785ff49b3045ce06fa38b9f5cf809 - Author: Nobuyoshi Nakada - Date: 2019-08-18 00:25:48 +0900 - - $LOAD_PATH elements should be real paths - - Installed path may contain symbolic links. - -commit 765eb18a45c6fa8ebc55203bfe477e61c6a12490 - Author: Nobuyoshi Nakada - Date: 2019-08-17 23:14:52 +0900 - - Make VM_DEBUG_VERIFY_METHOD_CACHE derived from VMDEBUG - - VM_DEBUG_MODE has been used only here. - -commit 2a65498ca2311d8c632d4c7f925f17083347ed93 - Author: aycabta - Date: 2019-08-17 00:14:28 +0900 - - Remove CI files from list - -commit 15da2aad766616237c8cd798542a70a61b6a23a4 - Author: aycabta - Date: 2019-08-17 00:15:07 +0900 - - Remove Travis CI workaround - -commit e095803c379a3db3de4edd229dc4593a345d1cdb - Author: Hiroshi SHIBATA - Date: 2019-08-14 21:21:45 +0900 - - Removed formatter_test_case and text_formatter_test_case from Gem::Specification#files. - -commit 3a06c11a7d913d824508f3d7e230703eb411db5a - Author: Hiroshi SHIBATA - Date: 2019-08-14 21:15:43 +0900 - - Removed autoload from Markup. - -commit 79fe84edf5da875daf240c9c11220ba89f3d49af - Author: Hiroshi SHIBATA - Date: 2019-08-14 21:12:15 +0900 - - Removed test_case files from lib directory. - -commit 37d0e6e4711a2de9b4b460731fc3fd98799ce21c - Author: Hiroshi SHIBATA - Date: 2019-08-17 18:18:20 +0900 - - Skip teardown with JRuby - -commit 08c58e3c0db8aaa6b573fe6c34a6318a17a83c68 - Author: David Rodríguez - Date: 2019-08-16 15:45:11 +0900 - - [bundler/bundler] Extract a `gemspec_dir` helper - - https://github.com/bundler/bundler/commit/71a29e286a - -commit a2d7c97a9187f3d88230e273756ed4836fa8ac19 - Author: David Rodríguez - Date: 2019-08-16 01:58:07 +0900 - - [bundler/bundler] Extract yet another helper method - - https://github.com/bundler/bundler/commit/948a863bd8 - -commit 43184056094af2495f05964c78bc517e07721802 - Author: David Rodríguez - Date: 2019-08-16 01:54:15 +0900 - - [bundler/bundler] Extract a `root_gemspec` local variable - - https://github.com/bundler/bundler/commit/a4beba4cbf - -commit 09455301ef81bc6207e6d3ba1034c35851575e18 - Author: David Rodríguez - Date: 2019-08-16 01:53:51 +0900 - - [bundler/bundler] Extract a `with_root_gemspec` helper - - https://github.com/bundler/bundler/commit/f20c2bdf6a - -commit 20c5154f0b79faf83c9c889f12da7da1ba9d6eb1 - Author: David Rodríguez - Date: 2019-08-16 01:48:09 +0900 - - [bundler/bundler] Only chdir when necessary - - https://github.com/bundler/bundler/commit/07161ebc1a - -commit 580e093fddc2c10ff4e6cd33bfa0a7bfab76395c - Author: David Rodríguez - Date: 2019-08-16 01:46:42 +0900 - - [bundler/bundler] Make sure gem has been built before deleteng it - - https://github.com/bundler/bundler/commit/32520c7020 - -commit a56bf5bfdea991f3fb16a002da6284817e7867b8 - Author: David Rodríguez - Date: 2019-08-16 01:29:23 +0900 - - [bundler/bundler] Cleanup in a location independent way - - https://github.com/bundler/bundler/commit/5b503a4bf1 - -commit 9c0fcd1d0fc6287795f957465b596a288708ab90 - Author: David Rodríguez - Date: 2019-08-16 01:29:15 +0900 - - [bundler/bundler] Remove obvious comment - - https://github.com/bundler/bundler/commit/91e7fe1b2f - -commit adfca752d6aa8f1828392cc1ae88063597376b5a - Author: David Rodríguez - Date: 2019-08-16 01:41:55 +0900 - - [bundler/bundler] Remve another unneeded `to_s` - - `FileUtils.rm` supports a `Pathname` argument. - - https://github.com/bundler/bundler/commit/7d982a5be9 - -commit 9925e1a10f94f2a8c6d1b513d4546157ccecdc3f - Author: David Rodríguez - Date: 2019-08-16 01:25:56 +0900 - - [bundler/bundler] Remove unneeded `to_s` calls - - They are implicit inside `gem_command!`. - - https://github.com/bundler/bundler/commit/6bdb13c899 - -commit f88237623f9131a9a07a4dd7ffde8c758e63e32c - Author: David Rodríguez - Date: 2019-08-16 00:26:51 +0900 - - [bundler/bundler] Consistently use `Path` over `Spec::Path` - - https://github.com/bundler/bundler/commit/a4cca66b79 - -commit aef5509139abd34f9983fa00895f91ea2801f088 - Author: David Rodríguez - Date: 2019-08-16 00:07:48 +0900 - - [bundler/bundler] Extract single gem installation logic - - https://github.com/bundler/bundler/commit/7888d621c8 - -commit 20af44c27727333b4cd3eef9d5b18daaa0445f0e - Author: David Rodríguez - Date: 2019-08-16 00:03:26 +0900 - - [bundler/bundler] Unalias `install_gem` - - Since I plan to reuse it for something else. - - https://github.com/bundler/bundler/commit/5379382198 - -commit 6506993462af4f6c4f7ee2e0d3bc27deee989069 - Author: David Rodríguez - Date: 2019-08-16 00:01:36 +0900 - - [bundler/bundler] Use `join` consistently - - https://github.com/bundler/bundler/commit/096e53dfe6 - -commit 6a299906b4bebe1c86bc50a565f47348e735cb8e - Author: David Rodríguez - Date: 2019-08-15 23:59:08 +0900 - - [bundler/bundler] Extract a `lib_tracked_files` path helper - - https://github.com/bundler/bundler/commit/028dc46f5a - -commit 19dabfbe574f9a8298054eb417d299ec5fc18412 - Author: David Rodríguez - Date: 2019-08-16 02:24:56 +0900 - - [bundler/bundler] Rename a variable - - Otherwise I get conflicts when extracting the helper. - - https://github.com/bundler/bundler/commit/314c64cd07 - -commit c896f71577e17e7b89ad39463b82d8936f000480 - Author: David Rodríguez - Date: 2019-08-15 23:48:42 +0900 - - [bundler/bundler] Extract a `tracked_files` path helper - - https://github.com/bundler/bundler/commit/d35e31d2e0 - -commit b43f4bd2184989c5f47ee539e583c785dfadb8d0 - Author: David Rodríguez - Date: 2019-08-16 02:18:01 +0900 - - [bundler/bundler] Rename some variables - - I want to extract these to path helper methods, but the name `files` - conflict with some builder methods that are also available at the same - level. - - https://github.com/bundler/bundler/commit/7844096af0 - -commit 334e6150222703712ae6360de14f9a04b83daea9 - Author: David Rodríguez - Date: 2019-08-15 23:47:44 +0900 - - [bundler/bundler] Reconcile test - - The `:bundler` gem is not needed in the regular repo either. - - https://github.com/bundler/bundler/commit/ca5ce01a9b - -commit 122bc65042bb53cd66ff681513ea7f5152536875 - Author: David Rodríguez - Date: 2019-08-16 01:13:36 +0900 - - [bundler/bundler] Reuse `gem_bin` helper inside `gem_command` - - The logic for choosing `gem_bin` should work here too even if it's not - identical. - - https://github.com/bundler/bundler/commit/6ca0271b27 - -commit 30a4ec1fee1363f31f93970c3cd809a6fc139140 - Author: David Rodríguez - Date: 2019-08-16 01:13:06 +0900 - - [bundler/bundler] Always use `--backtrace` when invoking `gem` CLI - - For debuggability. - - https://github.com/bundler/bundler/commit/ac3e8db658 - -commit 91c63828f7b841df6b7b124acb752c0a3bca66c0 - Author: David Rodríguez - Date: 2019-08-16 01:12:34 +0900 - - [bundler/bundler] Extract a `gem_bin` path helper - - https://github.com/bundler/bundler/commit/8eedbecac0 - -commit e38994d2f70ac714f749f69833fce5c5e8461513 - Author: David Rodríguez - Date: 2019-08-15 23:45:04 +0900 - - [bundler/bundler] Reuse `gem_command!` helper - - https://github.com/bundler/bundler/commit/37d5dedffe - -commit 63d78afc2d0520cff300494fd875c905349c12a0 - Author: David Rodríguez - Date: 2019-08-16 00:59:48 +0900 - - [bundler/bundler] Remove more dead code - - https://github.com/bundler/bundler/commit/17d4d0de8e - -commit 2e6509498c1daf3335ac6343bf59441d42011b64 - Author: David Rodríguez - Date: 2019-08-16 00:58:56 +0900 - - [bundler/bundler] Remove dead code - - https://github.com/bundler/bundler/commit/cae948f514 - -commit 3bebdda649e60edb9df0728aa1859590693db335 - Author: David Rodríguez - Date: 2019-08-16 00:58:34 +0900 - - [bundler/bundler] Remove unnecessary rubygems require - - https://github.com/bundler/bundler/commit/039604ff95 - -commit 7af12a92c8593fffee42004a04d6886bbd863ff5 - Author: David Rodríguez - Date: 2019-08-15 23:41:52 +0900 - - [bundler/bundler] Use path helpers to find bundle bin - - https://github.com/bundler/bundler/commit/7985bb8e92 - -commit 63575409458f6b7b1bdaf038a562bc3f011e231e - Author: David Rodríguez - Date: 2019-08-15 23:40:33 +0900 - - [bundler/bundler] Fix bundle bin location in core repo - - https://github.com/bundler/bundler/commit/9437568ab4 - -commit 7551117c70cdc33f4dd8a72a1a9151f23c73f902 - Author: David Rodríguez - Date: 2019-08-08 17:41:56 +0900 - - [bundler/bundler] Reuse more shared path helpers - - https://github.com/bundler/bundler/commit/79fdebd868 - -commit 9995ce64a251e51eabc6300d38980c4139f92d86 - Author: David Rodríguez - Date: 2019-08-15 23:37:18 +0900 - - [bundler/bundler] Remove unnecessary assignment - - https://github.com/bundler/bundler/commit/e483322519 - -commit a2ca3a12ba35d8991099cb23be4bdeb15e5cd459 - Author: David Rodríguez - Date: 2019-08-06 20:16:44 +0900 - - [bundler/bundler] Remove unnecessary `let` - - Use shared helper instead. - - https://github.com/bundler/bundler/commit/ef55470cc6 - -commit 745b2861617c62413357e27de9ded8098fcc031d - Author: David Rodríguez - Date: 2019-08-06 20:16:15 +0900 - - [bundler/bundler] Move `lib` helper together with path helpers - - https://github.com/bundler/bundler/commit/f2df73bdb4 - -commit 50a91fcd1061527a3543e3e713fc4222da68e438 - Author: David Rodríguez - Date: 2019-08-03 21:07:11 +0900 - - [bundler/bundler] Reuse `lib` method - - https://github.com/bundler/bundler/commit/4589a57852 - -commit ef2d4158028ab253fbd4b27d3cd3ffb4df5bffb7 - Author: David Rodríguez - Date: 2019-08-03 21:06:58 +0900 - - [bundler/bundler] Remove duplicated method - - https://github.com/bundler/bundler/commit/afdacd62ac - -commit 7664b5cb6549d09935c4bf0fe67392708a9c19c2 - Author: Hiroshi SHIBATA - Date: 2019-08-17 16:22:27 +0900 - - Support the current stable version of Ruby like 2.5 and 2.6. - -commit 221ba9b66c022a99227de8bf21db618666e17c42 - Author: Hiroshi SHIBATA - Date: 2019-08-17 17:01:19 +0900 - - Revert "`Gem.load_path_insert_index always returns non-nil index after Ruby 1.9" - - This reverts commit 260ef51a73c067599826c8ab110c53994c1b6226. - - This broke the stable versions of Ruby like 2.4 and 2.5 - -commit d041c6cebbe7fe973789616bef43200213e1a001 - Author: Hiroshi SHIBATA - Date: 2019-08-17 12:35:30 +0900 - - Added comments for extended require by RubyGems - -commit 260ef51a73c067599826c8ab110c53994c1b6226 - Author: Hiroshi SHIBATA - Date: 2019-08-17 12:33:38 +0900 - - `Gem.load_path_insert_index always returns non-nil index after Ruby 1.9 - -commit 06fcf88d695c8bfb6703966dd26629642ff7bf2d - Author: Hiroshi SHIBATA - Date: 2019-08-17 12:19:49 +0900 - - Use the original require for test_race_exception - - The extension for require method with rubygems affects this test - case. We need to keep this test for the original method. - -commit d8148650f6b5d7855845cfa0d53b363366b5c460 - Author: Hiroshi SHIBATA - Date: 2019-08-17 11:30:01 +0900 - - Try to continue on LoadError with gem_original_require - -commit 22d9bd944d4aae1b682e0bd4eafab706ff5a981e - Author: Hiroshi SHIBATA - Date: 2019-08-17 11:05:29 +0900 - - Keep the existence behavior with symlink path - -commit 273f1f44982475f8c93805c9b9ec604846f3a5de - Author: Hiroshi SHIBATA - Date: 2019-08-17 10:11:05 +0900 - - Move fixture path to last path - -commit dd16f8524c44f8802e634af2577fe5a149cd740e - Author: Hiroshi SHIBATA - Date: 2019-08-17 08:54:05 +0900 - - Revert "Revert "[rubygems/rubygems] [Require] Ensure -I beats a default gem"" - - This reverts commit 75d29db8f965893bb6ab38b9008abc80cdda246e. - -commit 9d20d2b0f5096fab210464f9e16d876f9c5d319f - Author: Kenichi Kamiya - Date: 2019-08-17 15:03:00 +0900 - - Clean sample code biorhythm (#2375) - - * Standardize to load date library code - - > git grep 'require .date.' | wc -l - 179 - > git grep 'require .date\.rb' | wc -l - 1 - - * Simplify - -commit 72adc6cffbc41988aee728d74ab0bed2c5159948 - Author: Kenichi Kamiya - Date: 2019-08-17 14:56:57 +0900 - - Simplify a sample code (#2374) - -commit dce1e14e80c9c6d1e25c8aaf9075c80df610ddc3 - Author: Iain Barnett - Date: 2019-08-17 14:24:45 +0900 - - Use more different arguments in Fiber.yield documentation to make it clear (#2170) - - https://github.com/ruby/ruby/pull/2170#issuecomment-489880700 - - Documentation is for those who don't know, remember, or understand (to any degree) the language, it should attempt to be clear above all other things. The example given is needlessly unclear because if you use a block it's common for arguments to be reused on every entry to the block. In Fiber's case this is not so. - - First time round 10 goes in, 12 comes out. - Second time round 14 goes in, 14 comes out… was that because 14 is 12 + 2 or because it's "the return value of the call to Fiber.yield". It's the latter because it says so but why does the example need to make anyone think the former? - - Using different numbers makes it immediately clear what's happening whether the description is there or not. - -commit 28267cea083408185de3e0aaafd14ec76c9a3157 - Author: David CARLIER - Date: 2019-08-17 14:17:30 +0900 - - NetBSD native support of explicit_bzero's like feature (#2145) - -commit ccbfb054b1dcd06d30924c4a83af1bac75d78c31 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-17 13:57:12 +0900 - - Fix typos - -commit 2468466a1ae45944238901b532646a6cf3385815 - Author: Hiroshi SHIBATA - Date: 2019-08-17 12:08:07 +0900 - - Added missing condition for test-bundler and test-bundled-gems. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2379 - -commit ea496e9fb2c930ac0c5ff8c12c4a10fac0ec3c7b - Author: Hiroshi SHIBATA - Date: 2019-08-17 11:36:12 +0900 - - Added test check to ubuntu on GitHub Actions - - Notes: - Merged: https://github.com/ruby/ruby/pull/2379 - -commit dc020b06ffc85f3484fad0c5a014cbcae197bc40 - Author: Nobuyoshi Nakada - Date: 2019-08-17 12:32:29 +0900 - - Hoisted out search_refined_method - - [Bug #16107] - -commit 11a9f7ab9431b0f361e43b4ac2bd6ee44827d88b - Author: Nobuyoshi Nakada - Date: 2019-08-17 00:17:15 +0900 - - Search refinement module along nested usings - - [Bug #16107] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2373 - -commit 042be439d92ea0910fe3bd0d5e9a1d4135257d2d - Author: OKURA Masafumi - Date: 2019-08-16 22:56:30 +0900 - - Improve the doc example of `method_missing` - - Improvements are: - * Use `symbol` instead of `methId`, described in doc - * Add `*args` following method signature - * Rescue error in `roman_to_int` and calls `super`, recommended in doc - * Call invalid `foo` method to Roman object to raise NoMethodError - - Notes: - Merged: https://github.com/ruby/ruby/pull/2372 - -commit 045152df9e91c34a2785cb95e5964d7fc1b14df5 - Author: Takashi Kokubun - Date: 2019-08-17 09:43:05 +0900 - - Disable fail-fast of GitHub Actions - - This is default: true - https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategyfail-fast - - When `make check` fails, we do not want to cancel `make test-bundler`. - -commit 75d29db8f965893bb6ab38b9008abc80cdda246e - Author: Hiroshi SHIBATA - Date: 2019-08-17 08:52:13 +0900 - - Revert "[rubygems/rubygems] [Require] Ensure -I beats a default gem" - - This reverts commit 00cd5d74cecb6aa4a184e57e2b8246ef6e45d458. - -commit efd37f8fc3e021c93f37d1f7f08fcb6b909d6ecf - Author: OKURA Masafumi - Date: 2019-08-17 08:52:23 +0900 - - Remove redundant each from `sum` example (#2190) [ci skip] - - It used to be `Enumerator#sum`, now it's range of string which calls - `Enumerable#sum` and causes TypeError. - -commit 7624154595eb71333a61b37f4c7388b6c031e878 - Author: Hiroshi SHIBATA - Date: 2019-08-17 08:44:31 +0900 - - Fixed Insecure Operation in require - - Caused by 00cd5d74ce - -commit e0fc9b7ccd9e14bd925cd46606ad201d0b57a423 - Author: git - Date: 2019-08-17 07:49:00 +0900 - - * 2019-08-17 [ci skip] - -commit f30d38bdd08d241f8c3c1768069911e627f955f8 - Author: Hiroshi SHIBATA - Date: 2019-08-16 21:30:32 +0900 - - Move lib directory to the last of $LOAD_PATH on ruby repository. - - https://github.com/rubygems/rubygems/pull/1868 changes the behavior - of require when it used with -I options. Therefore, the options of - ruby repository was different from rubygems/rubygems. - -commit ae3002b5401fb8b38d9a3a9b9e27e6a36ac79ff2 - Author: Hiroshi SHIBATA - Date: 2019-08-16 16:02:32 +0900 - - [rubygems/rubygems] Fixup #2844 - - https://github.com/rubygems/rubygems/commit/5924286ae2 - -commit 56a28a8728dceb4bbcd6269c7ae3cb894c4ce512 - Author: MSP-Greg - Date: 2019-08-16 01:43:50 +0900 - - [rubygems/rubygems] installer.rb - fix #windows_stub_script - - use ruby_exe in heredocs instead of ruby.exe - - https://github.com/rubygems/rubygems/commit/9f1b7d6590 - -commit 25a327d41bcb881f27acfcc58f262986a8f4e5b4 - Author: Alexander Pakulov - Date: 2019-08-15 04:00:27 +0900 - - [rubygems/rubygems] Do not mutate uri.query during s3 signature creation - - https://github.com/rubygems/rubygems/commit/c0275ee537 - -commit c4f7c260f995778a40c6fc15107090fdb51d49a8 - Author: Hiroshi SHIBATA - Date: 2019-07-31 12:46:09 +0900 - - [rubygems/rubygems] Make deprecate Gem::RubyGemsVersion and Gem::ConfigMap. - - https://github.com/rubygems/rubygems/commit/1133c2f700 - -commit c78839902b47bf6a91226fbef00443e7d344033d - Author: David Rodríguez - Date: 2019-01-11 01:08:59 +0900 - - [rubygems/rubygems] Return `nil` to clarify return value is ignored - - https://github.com/rubygems/rubygems/commit/8702f59d32 - -commit 5998012a0c7244fe217c2d4f494e50f32ec85d29 - Author: David Rodríguez - Date: 2019-01-07 20:00:35 +0900 - - [rubygems/rubygems] Autoswitch to exact bundler version if present - - https://github.com/rubygems/rubygems/commit/bb02953a97 - -commit 3587824d710ffcfd1270be0a354a770a49312b6f - Author: David Rodríguez - Date: 2019-04-25 18:48:40 +0900 - - [rubygems/rubygems] Don't unregister default specifications - - I think this should be more efficient? - - https://github.com/rubygems/rubygems/commit/a1de78104f - -commit 1ac6890bd05a48e385f564d212765a3a60899659 - Author: David Rodríguez - Date: 2019-04-25 22:58:45 +0900 - - [rubygems/rubygems] Fix removing unresolved default spec files from map - - https://github.com/rubygems/rubygems/commit/7964917bbc - -commit f42ad4a4250620ca64b2f668fed91d475934eaa7 - Author: David Rodríguez - Date: 2019-04-25 22:57:41 +0900 - - [rubygems/rubygems] Little refactor - - There's already a method called `suffix_pattern`, that's different from - this local variable. So, move the local variable to a `suffix_regexp` - that clearly differentiates from `suffix_pattern`. - - https://github.com/rubygems/rubygems/commit/4ec69c48b9 - -commit 89ad5df979727ab50eee6106550bf58b1888486e - Author: bronzdoc - Date: 2019-07-26 14:54:06 +0900 - - [rubygems/rubygems] Replace domain parameter in Gem::Command#show_lookup_failure with a parameter to suppress suggestions - - https://github.com/rubygems/rubygems/commit/760b7d834f - -commit b8984370daaff4809b04330a6d7098f171568f79 - Author: David Rodríguez - Date: 2019-05-20 00:31:17 +0900 - - [rubygems/rubygems] Fix jruby issue - - https://github.com/rubygems/rubygems/commit/fc3f722164 - -commit 37abd2c390bb93fe1a306465bb5de35feb70a82a - Author: David Rodríguez - Date: 2019-04-04 01:00:02 +0900 - - [rubygems/rubygems] Fix old rubies compat - - https://github.com/rubygems/rubygems/commit/41e60cdb6b - -commit 00cd5d74cecb6aa4a184e57e2b8246ef6e45d458 - Author: Samuel Giddins - Date: 2017-03-15 02:34:03 +0900 - - [rubygems/rubygems] [Require] Ensure -I beats a default gem - - https://github.com/rubygems/rubygems/commit/6fbda98eb3 - -commit d4feeb19361a4d7addf4779fb6bdc8e8c072093b - Author: David Rodríguez - Date: 2019-04-03 22:11:14 +0900 - - [rubygems/rubygems] Make test also assert the gems that it should load - - https://github.com/rubygems/rubygems/commit/a6375920bf - -commit bb2a65800d857149bbbacace7ed5dfbf7d20ecc2 - Author: David Rodríguez - Date: 2019-04-03 22:06:29 +0900 - - [rubygems/rubygems] Use `assert_require` - - For consistency with the other specs. - - https://github.com/rubygems/rubygems/commit/44b93aec4c - -commit 229ae3269d622954295e4220fa7bc3298cad8b1d - Author: Yusuke Endoh - Date: 2019-08-16 21:27:05 +0900 - - lib/rdoc/store.rb: Use `Marshal.dump(obj, io)` - - instead of dumping obj to a string and then saving the string. - It omits object creation. - -commit 619f82bb6bd913d8dbb8ca5da15ca1fbb4508629 - Author: Nobuyoshi Nakada - Date: 2019-08-16 17:36:09 +0900 - - Hoisted out unixsocket_len, trimming NUL chars from sun_path - -commit 03f4a0b18e9417a82e23523be40ebf0c505faee9 - Author: Nobuyoshi Nakada - Date: 2019-08-16 16:47:09 +0900 - - [ruby/rdoc] Use assert_raise - - https://github.com/ruby/rdoc/commit/f2c63549f7 - -commit 02d0d424be04cb05ce56b7d21cc843345b0d9a2c - Author: Hiroshi SHIBATA - Date: 2019-08-16 14:52:03 +0900 - - Revert "[bundler/bundler] Fixup #7297" - - This reverts commit b8d759806ff825e1b9344ba34b1a2bc4809d0988. - - It's accidentally picked from the upstream repository. - -commit b8d759806ff825e1b9344ba34b1a2bc4809d0988 - Author: Hiroshi SHIBATA - Date: 2019-08-16 10:05:15 +0900 - - [bundler/bundler] Fixup #7297 - - https://github.com/bundler/bundler/commit/1a0161b970 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 8cf90a2f80866449a555c76eae6189b687fda7d6 - Author: Hiroshi SHIBATA - Date: 2019-08-16 07:11:14 +0900 - - [bundler/bundler] Fixed rubocop error - - https://github.com/bundler/bundler/commit/9256177446 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit e8fd720434e270d1021a57607a377b0f0c7517dd - Author: David Rodríguez - Date: 2019-08-14 22:58:18 +0900 - - [bundler/bundler] Remove mention to remembered options - - And instead educate users on the preferred, non deprecated, way. - - https://github.com/bundler/bundler/commit/9cd6238da2 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 502ad4d39103f91bea96be5c8247057dd39f21e2 - Author: Tomoki Aonuma - Date: 2019-07-10 23:19:14 +0900 - - [bundler/bundler] Document upcoming changes to remembered options - - https://github.com/bundler/bundler/commit/a1c97fd7c3 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 3b61019a89c366e50db908ccf25a9156bc500a5f - Author: tommy - Date: 2019-08-13 22:53:33 +0900 - - [bundler/bundler] Add initial Bundler::BuildMetadata Spec - - https://github.com/bundler/bundler/commit/c6458b2727 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit b587e8c7f1cd56f1c53156d7893ee0e581128a0a - Author: David Rodríguez - Date: 2019-07-24 19:24:55 +0900 - - [bundler/bundler] Add `--[no-]git` option to `bundle gem` - - I think using `--no-git` can be useful when creating gems inside - monorepos. - - https://github.com/bundler/bundler/commit/154c687310 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit cb71930351f8978d3c0b06acc14c98a8978f3abe - Author: David Rodríguez - Date: 2019-08-08 19:06:44 +0900 - - [bundler/bundler] Remove unexistent folder from exemptions - - https://github.com/bundler/bundler/commit/0b6d973543 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit f48a61fb46304d35043d013c8cf4539c5be1ecab - Author: David Rodríguez - Date: 2019-07-11 00:26:55 +0900 - - [bundler/bundler] Commit man pages to source control - - This has the benefit that: - - * Allows the installation of bundler as a default gem from rubygems to - include man pages. - * Removes the need to build man pages during our tests. - * Makes working with the manifest easier, because we only have source - controlled files, and not a mix of source control and generated files. - - To make sure they never fall out of sync, we replace the previous - `man:build` CI task with a `man:check` task that makes sure the - generated man pages are up to date. - - https://github.com/bundler/bundler/commit/23de1d0177 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 8f28ae65a861ba714be824ea3122817abe9f862d - Author: David Rodríguez - Date: 2019-07-11 00:23:29 +0900 - - [bundler/bundler] Remove misleading comment in Gemfile - - Since we no longer use `git` to find out the list of files, the comment - is misleading. - - https://github.com/bundler/bundler/commit/54d85d5349 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit cd15d27d10d4f041cf4e60064dae96562c9bd83f - Author: David Rodríguez - Date: 2019-08-07 00:23:06 +0900 - - [bundler/bundler] Stop printing deprecation messages during specs - - Previously under some circumstances (met during some specs), bundler - would print deprecations to a separate UI different from "bundler's UI". - This UI would not be captured by the specs, and thus would be printed to - screen during the specs. - - This commit fixes that by making sure all deprecation messages always go - through bundler's UI. - - https://github.com/bundler/bundler/commit/220c54b7fa - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 4af3665fd91aae87c9fe014778ed7c54245e2f9b - Author: David Rodríguez - Date: 2019-08-08 19:08:53 +0900 - - [bundler/bundler] Use a newer debugging gem in docs - - So that the examples work in currently supported rubies. - - https://github.com/bundler/bundler/commit/b7d4556cde - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 4913c9b6bf78ae697689f89b99754e346603c68a - Author: David Rodríguez - Date: 2019-08-08 19:07:07 +0900 - - [bundler/bundler] Remove unexistent file from exemptions - - https://github.com/bundler/bundler/commit/8601575490 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 6412121b0077cdad8f1fff3da75c2532cd67cd99 - Author: Masato Ohba - Date: 2019-08-10 09:24:30 +0900 - - [bundler/bundler] Fix typo in comment: attributes -> attributes - https://github.com/bundler/bundler/commit/876545805e - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 94e26a97a153950e160445c7afc1e4c62e522740 - Author: David Rodríguez - Date: 2019-08-09 00:27:23 +0900 - - [bundler/bundler] Bump rspec dependency to 3.8 - - Because we're using `config.bisect_runner` which is only available from - 3.8. - - https://github.com/bundler/bundler/commit/304a187f72 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 521a2d2beb945a2ce22b4788409f5fb475fea17a - Author: David Rodríguez - Date: 2019-07-26 20:37:51 +0900 - - [bundler/bundler] Revert "make system_bundle_bin_path helper and resolve failing tests for ruby < 2.6" - - This reverts commit e63e844bc7444c6a489fcde0dc7011c6c4807edd. - - It was introduced to resolve some failing tests at the cost of making - the intention of the spec much less clear. - - Thanks to the previous fixes we have added to this spec, we can revert - that patch now. - - https://github.com/bundler/bundler/commit/b29a40820f - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 5bff72c912099bc9ac866d0c699ad4a2945d5827 - Author: David Rodríguez - Date: 2019-08-08 03:37:50 +0900 - - [bundler/bundler] Make sure spec fails if `bundle install` fails - - https://github.com/bundler/bundler/commit/2ed2bbfdec - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 7ff0b4fec4cbd763e9bb7be597b54217176a8d86 - Author: David Rodríguez - Date: 2019-08-08 03:35:28 +0900 - - [bundler/bundler] Fix installation of system bundler - - Previously it was being installed to the :bundle_path - (`/tmp/bundled_app/.bundle`), but the `bundle` helper uses the - `system_gem_path("bin/bundle")`. That means the first `bundle install`in - the spec was actually failing, but not affecting the test status because - of not being called as `bundle!`. - - https://github.com/bundler/bundler/commit/ad75f75539 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 6c6c4c7388c2f1c0f579de363bb0ec66ad851b5b - Author: David Rodríguez - Date: 2019-08-08 03:33:04 +0900 - - [bundler/bundler] Use non deprecated way of setting bundler path - - https://github.com/bundler/bundler/commit/6013c93e81 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit ee1f3038f1657aa90d75e735e4262fe8d9b3d745 - Author: David Rodríguez - Date: 2019-05-25 00:46:26 +0900 - - [bundler/bundler] Clarify spec description - - https://github.com/bundler/bundler/commit/b2abde04aa - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 0aed0bd9ed521799c5d92c6c10ca8fa4476f8b66 - Author: David Rodríguez - Date: 2019-08-06 23:59:02 +0900 - - [bundler/bundler] Bump rack and sinatra to latest versions - - https://github.com/bundler/bundler/commit/09ecaf04fa - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 129657ab6aa3cc9496746a6eb780c0dc748e3d20 - Author: David Rodríguez - Date: 2019-08-06 23:56:01 +0900 - - [bundler/bundler] Normalize style with other artifice files - - https://github.com/bundler/bundler/commit/f11c9a2b3f - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 41534ce327efb56f3ddb136b5617fe47a89212b5 - Author: David Rodríguez - Date: 2019-08-06 01:43:47 +0900 - - [bundler/bundler] Make spec pass more resiliently - - Previously, if bundler-2.1.0.pre.1 would be installed globally, it would - fail. Now we force that a locally installed version of bundler is used, - so it always passed regardless of which bundler is installed globally. - - https://github.com/bundler/bundler/commit/764d8e8fd1 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 3c23bb29ecbc0c736e99d23a3c47892d67f3a322 - Author: David Rodríguez - Date: 2019-08-06 20:59:39 +0900 - - [bundler/bundler] Remove unnecessary exclusions - - https://github.com/bundler/bundler/commit/c189dfdde0 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 3f0e19c9fa566de3691b994ef6c2bea8cb5fdb83 - Author: David Rodríguez - Date: 2019-08-06 00:20:34 +0900 - - [bundler/bundler] Enable retries on flaky spec - - https://github.com/bundler/bundler/commit/da360659f7 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 2b0f3aa095a410902b9b2e4fb14f909e0630c1a1 - Author: Benoit Daloze - Date: 2019-08-04 21:52:15 +0900 - - [bundler/bundler] Use the standard RUBY_ENGINE_VERSION instead of JRUBY_VERSION - - * RUBY_ENGINE and RUBY_ENGINE_VERSION are defined on every modern Ruby. - * There is no such constant as TRUFFLERUBY_VERSION or RBX_VERSION. - - https://github.com/bundler/bundler/commit/f9d910403b - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 6711343d5a630cc857f0fa503b403edb68415f48 - Author: David Rodríguez - Date: 2019-07-25 02:46:19 +0900 - - [bundler/bundler] Fix inconsistent lockfile order - - When Gemfile would specify path sources as relative paths starting with - "./", the lockfile would have inconsistent order on `bundle install` and - `bundle update`. - - https://github.com/bundler/bundler/commit/c7532ced89 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit c11c8b69ea98e698e855b4b1f122a54929582dc7 - Author: David Rodríguez - Date: 2019-07-25 02:48:10 +0900 - - [bundler/bundler] Indentation tweak - - https://github.com/bundler/bundler/commit/5978a88f33 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit 500c3cb6a59eb991567714311e9301eeb377be9d - Author: David Rodríguez - Date: 2019-07-25 02:45:53 +0900 - - [bundler/bundler] Reuse `root` method - - https://github.com/bundler/bundler/commit/42363091da - - Notes: - Merged: https://github.com/ruby/ruby/pull/2366 - -commit cd41378ef906c279ee925a0f5d6ba3bf606953db - Author: Yusuke Endoh - Date: 2019-08-16 11:36:47 +0900 - - lib/rdoc/parser/ruby.rb: Avoid `.chars.to_a.last` - - The code creates a lot of useless objects. - Instead, using a regexp is shorter and faster. - -commit 64bffddda1d57072a7879dfab9e5bc0286c1395d - Author: Nobuyoshi Nakada - Date: 2019-08-16 02:08:40 +0900 - - exit accepts true and false [ci skip] - -commit 12074ad01c02b4a6912fff64d69b659351bdf9e8 - Author: Nobuyoshi Nakada - Date: 2019-08-16 02:08:02 +0900 - - Use GNU make built-in function [ci skip] - -commit 1b02f6c020e5d73cbe8e759ada7da908ce6a3f15 - Author: aycabta - Date: 2019-08-16 07:10:45 +0900 - - Set IRB::Context#return_format on test clarify - -commit a458317b914579c8a042ed02592af3a92aa41d1b - Author: aycabta - Date: 2019-08-16 06:45:36 +0900 - - Use assert_raise and skip for test/unit - -commit f71bd7477e84eb1cd10fa27e79b1e081ee51793a - Author: Yusuke Endoh - Date: 2019-08-07 02:14:39 +0900 - - RDoc::Parser::C: Integrate do_classes and do_modules by one regexp match - - The full scan of the C source code (`@content.scan`) is very slow. - The old code invokes the scan six times in `do_classes` and - `do_modules`. - - This change integrates the six scans into one by merging the regexps. - The integrated regexp is a bit hard to maintain, but the speed up is - significant: approx. 30 sec -> 20 sec in Ruby's `make rdoc`. - - In addition, this change omits `do_boot_defclass` unless the file name - is `class.c`. `boot_defclass` is too specific to Ruby's source code, so - RDoc should handle it as a special case. - - Before this change: - - TOTAL (pct) SAMPLES (pct) FRAME - 858 (13.6%) 858 (13.6%) (garbage collection) - 292 (4.6%) 264 (4.2%) RDoc::Parser::C#do_define_class - 263 (4.2%) 250 (3.9%) RDoc::Parser::C#do_define_module - 275 (4.3%) 241 (3.8%) RDoc::Parser::C#do_define_class_under - 248 (3.9%) 237 (3.7%) RDoc::Parser::C#do_define_module_under - 234 (3.7%) 234 (3.7%) RDoc::Parser::C#gen_body_table - 219 (3.5%) 219 (3.5%) Ripper::Lexer#state_obj - 217 (3.4%) 216 (3.4%) RDoc::Parser::C#do_struct_define_without_accessor - 205 (3.2%) 205 (3.2%) RDoc::Parser::C#do_boot_defclass - 205 (3.2%) 205 (3.2%) RDoc::Parser::C#do_singleton_class - - The six methods take approx. 22.2%. - `do_define_class` (4.2%) + `do_define_class_under` (3.8%) + - `do_define_module` (3,9$) + `do_define_module_under` (3.7%) + - `do_struct_define_without_accessor` (3.4%) + `do_singleton_class` (3.2%) - - After this change, the methods are integrated to `do_classes_and_modules` - which takes only 5.8%. - - TOTAL (pct) SAMPLES (pct) FRAME - 812 (16.7%) 812 (16.7%) (garbage collection) - 355 (7.3%) 284 (5.8%) RDoc::Parser::C#do_classes_and_modules - 225 (4.6%) 225 (4.6%) RDoc::Parser::C#gen_body_table - 429 (8.8%) 210 (4.3%) RDoc::Parser::RubyTools#get_tk - 208 (4.3%) 208 (4.3%) RDoc::TokenStream#add_tokens - -commit b64911f4e262bef582557f6d11dc5cb35dae669c - Author: aycabta - Date: 2019-08-14 19:06:27 +0900 - - Parser was replaced - -commit bad937b00b328bbc3c2e374e40880f835d88f1af - Author: Hiroshi SHIBATA - Date: 2019-08-11 12:53:49 +0900 - - Gem::TestCase is based on Minitest - -commit daf5ce3ba1545e295ba2efd0ee153638ae446e6e - Author: Hiroshi SHIBATA - Date: 2019-08-11 12:50:54 +0900 - - Use omit instead of skip for test-unit. - -commit e87e10e5e7b7bbb6f4e703981a75b9aaae588816 - Author: Hiroshi SHIBATA - Date: 2019-08-11 12:39:11 +0900 - - Use test/unit instead of test-unit. Because test-unit is only provided standalone gem. - -commit 2066dae991d89c481ab92586d1b2e9589211dde6 - Author: Hiroshi SHIBATA - Date: 2019-08-11 12:37:05 +0900 - - Cleanup commented-out code. - -commit 92186556602c10ce38197757402b2e06a8fc1f06 - Author: Hiroshi SHIBATA - Date: 2019-08-11 12:35:54 +0900 - - Removed needless alias for capture_io. - -commit 8a18a639b7497dd9f1929a38fc8449e8037e26c6 - Author: Hiroshi SHIBATA - Date: 2019-08-10 18:01:08 +0900 - - Use Gemfile instead of add_development_dependency. - -commit 71fd26b1957134588e150d1bfd7b831dc7864e8a - Author: Nobuyoshi Nakada - Date: 2019-08-09 01:43:51 +0900 - - Fallback for older Rubygems - -commit 787b437a2aaf8bfd60a9ac151f52cdb2638b7d8d - Author: Nobuyoshi Nakada - Date: 2019-08-08 23:04:32 +0900 - - Use Gem.default_specifications_dir - - Gem::Specification.default_specifications_dir is deprecated. - -commit 5555e3ef5777178a81625b54958c1fa14e3ef38e - Author: Nobuyoshi Nakada - Date: 2019-08-08 23:09:24 +0900 - - Renamed minitest_helper.rb as helper.rb - -commit 8045ebbf780d4eb35154111cb0d177b5fc7c486b - Author: Nobuyoshi Nakada - Date: 2018-12-02 11:46:13 +0900 - - Use locale directory for the tests - -commit 1a5304228a03139b55821985856628cfe7362966 - Author: Nobuyoshi Nakada - Date: 2018-12-02 11:36:45 +0900 - - Use test-unit instead of minitest - - Minitest 6 will err `assert_equal` with `nil`. - https://github.com/seattlerb/minitest/issues/779 - -commit 64f9f512c5837207436203c0ca47523cca2ecc62 - Author: aycabta - Date: 2019-08-08 16:35:34 +0900 - - Treat linking to Markdown label correctly - -commit 723a37d0386bc20efedf516656c2ccafa889c89d - Author: Yusuke Endoh - Date: 2019-08-07 02:32:03 +0900 - - Separate RDoc::TokenStream#add_tokens and #add_token - - The old version of `add_tokens` accepts an array of tokens, and - multiple arguments of tokens by using `Array#flatten`. - And `add_token` was an alias to `add_tokens`. - - I think it is unnecessarily flexible; in fact, all callsites of - `add_tokens` (except test) passes only an array of tokens. - And the code created a lot of temporal arrays. - - This change makes `add_tokens` accept only one array of tokens, - and does `add_token` accept one token. It is a bit faster (about - 1 second in Ruby's `make rdoc`), and it ls also cleaner in my point of - view. - -commit 0a0760aa632f05bc04df395d0173580042d9f730 - Author: Yusuke Endoh - Date: 2019-08-07 01:53:56 +0900 - - Refactor and improve performance of RDoc::Markup::Parser - - This change introduces a wrapper of StringScanner that is aware of the - current position (column and lineno). - It has two advantages: faster and more modular. - - The old code frequently runs `@input.byteslice(0, byte_offset).length` - to get the current position, but it was painfully slow. This change - keeps track of the position at each scan, which reduces about half of - time of "Generating RI format into ..." in Ruby's `make rdoc` - (5.5 sec -> 3.0 sec). - - And the old code used four instance variables (`@input`, `@line`, - `@line_pos`, and `@s`) to track the position. This change factors them - out into MyStringScanner, so now only one variable (`@s`) is needed. - -commit 9d2fed2ccd1724d1cf42a3075c20dcc418082761 - Author: Steven Willis - Date: 2019-03-21 03:50:05 +0900 - - Don't echo results of assignment expressions - -commit 74726691bada2f2061c57169f4c36a50a9f500ab - Author: OKURA Masafumi - Date: 2019-08-16 02:21:17 +0900 - - Add details about parameters to define_method doc (#2165) - - When we use `define_method` and `define_singleton_method`, - if we supply block parameters to a block then a generated - method has corresponding parameters. - However, the doc doesn't mention it, so this info has been added. - -commit 409ce8c3da966ac8fb809bc6317990f2b5b6479d - Author: Takashi Kokubun - Date: 2019-08-16 01:51:22 +0900 - - Also clean up branch for worktree - -commit d21616eeb0616095bb96408036a7548a30987e02 - Author: Takashi Kokubun - Date: 2019-08-16 01:45:00 +0900 - - Clean up temporary git resources - - after `make update-github` - -commit 2665e5858f76e07ea8748a1931f500f961c5ceae - Author: Espartaco Palma - Date: 2019-08-16 01:38:46 +0900 - - Adding missing test for Net::HTTPGenericRequest initializer (#1835) - - A new exception is raised if an URI::HTTP is received and that object doesn't - have a hostname property. - Complementary to #1278 - -commit 2f919a92ba45d1174aa72498585ff7025142d9e3 - Author: Takashi Kokubun - Date: 2019-08-16 01:34:51 +0900 - - Improve `make update-github` to avoid configure - - after doing it once. - -commit 789f17665e87ddfe76ef2f7bf344163d7cbf98cf - Author: Takashi Kokubun - Date: 2019-08-16 01:18:26 +0900 - - Make `make update-github` idempotent - -commit d013d8e02e895e08f7feb0977c0ea88e6f00b580 - Author: Takashi Kokubun - Date: 2019-08-16 01:11:18 +0900 - - Fix crash on $(PULL_REQUEST) expansion - - by directly passing it to Ruby without passing a shell. - Formerly it was broken when $(PULL_REQUEST) included quotes. - -commit 7c46aa6911a859877522cd61a2805adca6f65b9c - Author: Olivier Lacan - Date: 2019-08-16 00:42:17 +0900 - - Avoid confusion in Array#- and Array#difference docs (#2070) - - My previous attempt to correct #2068 apparently failed and the confusing - wording ("instances") was merged into trunk instead. - - This should address any potential confusion. - -commit 7704bbd6401ad2261652fa8bf6f4bd45a0964ef7 - Author: Nobuyoshi Nakada - Date: 2019-08-16 00:28:16 +0900 - - Marked up command line options [ci skip] - -commit d2070f2e454a6d2207fedf48525269ec04fbfa0e - Author: songhuangcn - Date: 2019-08-16 00:20:52 +0900 - - Fix doc in Object#respond_to_missing? (#2239) - -commit 715218c4306140ed9a62d993890de13e1d2ec572 - Author: git - Date: 2019-08-16 00:02:38 +0900 - - * 2019-08-16 [ci skip] - -commit 40806793a97ef3efd4f249682c9cb397962a8cee - Author: Nobuyoshi Nakada - Date: 2019-08-16 00:00:50 +0900 - - Fixed class, module and method references [ci skip] - -commit b1003301aff42a8c1d60bc435839502c4aa549ab - Author: Nobuyoshi Nakada - Date: 2019-08-15 23:59:28 +0900 - - Fixed a markup in different format [ci skip] - -commit d5c33364e3c0efb15e11df417c925afee2cdb9c9 - Author: Nobuyoshi Nakada - Date: 2019-08-15 23:25:37 +0900 - - Fixed heap-use-after-free - - * string.c (rb_str_sub_bang): retrieves a pointer to the - replacement string buffer just before using it, for the case of - replacement with the receiver string itself. [Bug #16105] - -commit c4152b11a7fbc849a545b34e5b9d85f1fdc1a21f - Author: Nobuyoshi Nakada - Date: 2019-08-15 21:34:34 +0900 - - Prepare to pull commits notes [ci skip] - -commit fff2b231a31f1213d5bc1604ac5e12d8f1e82e57 - Author: Nobuyoshi Nakada - Date: 2019-08-15 21:26:32 +0900 - - Simplified GITHUB_TOKEN argument [ci skip] - -commit 53a55aeff3d409b4894d077f2b3b874fac53e387 - Author: Koichi Sasada - Date: 2019-08-15 13:48:58 +0900 - - introduce RUBY_ON_BUG envval. (#2331) - - `rb_bug()` is called at critical bug, MRI can't run anymore. - To make debug easy, this patch introduces RUBY_ON_BUG environment - variable to specify the process which is called with pid. - [Feature #16090] [GH #2331] - - RUBY_ON_BUG='gdb -p' ruby xxx.rb - - In this case, if ruby interpreter causes critical bug, and call - rb_bug(), then "gdb -p [PID]' is called by system(3). You can - debug on invoked gdb. - - This feature is limited on RUBY_DEVEL build. - - Notes: - Merged-By: ko1 - -commit 132b7eb104ed2f5d9966adb2f0edacb2406f40fb - Author: git - Date: 2019-08-15 08:16:14 +0900 - - * expand tabs. [ci skip] - -commit 6954ff1dcb538ee6c042872088b64464a1ef6089 - Author: Jeremy Evans - Date: 2019-07-30 08:22:00 +0900 - - Make Range#=== operate like cover? instead of include? for string ranges - - Previously, Range#=== treated string ranges that were not endless or - beginless the same as include?, instead of the same as cover?. - I think this was an oversight in 989e07c0f2fa664a54e52a475c2fcc145f06539d, - as the commit message did not indicate this behavior was desired. - - This also makes some previously dead code no longer dead. Previously, - the conditionals were doing this: - - if (RB_TYPE_P(beg, T_STRING) - if (NIL_P(beg)) # can never be true - - This restructures it so at the NIL_P(beg) check, beg could possibly - be nil (beginless ranges). - - Fixes [Bug #15449] - -commit 082424ef58116db9663a754157d6c441d60fd101 - Author: Jeremy Evans - Date: 2019-05-09 12:35:56 +0900 - - Fold to lowercase instead of uppercase for String#casecmp - - strcasecmp(3) and String#casecmp? both fold to lowercase. - -commit d5c60214c45bafc1cf2a516f852394986f9c84bb - Author: Jeremy Evans - Date: 2019-06-08 14:03:02 +0900 - - Implement Range#minmax - - Range#minmax was previous not implemented, so calling #minmax on - range was actually calling Enumerable#minmax. This is a simple - implementation of #minmax by just calling range_min and range_max. - - Fixes [Bug #15867] - Fixes [Bug #15807] - -commit 661927a4c55232bd070992d47670a7d411820111 - Author: Jeremy Evans - Date: 2019-08-15 03:19:16 +0900 - - Switch to using a VM stack argument instead of 2nd operand for getconstant - - Some tooling depends on the current bytecode, and adding an operand - changes the bytecode. While tooling can be updated for new bytecode, - this support doesn't warrant such a change. - -commit 6ac6de84ac3a5bc4fae8e04d03084696080e1ab2 - Author: Jeremy Evans - Date: 2019-08-15 01:59:27 +0900 - - Use Qtrue/Qfalse instead of 1/0 for 2nd operand to getconstant - - Fixes error when using -Werror,-Wshorten-64-to-32. - -commit d053a570141d3f60eb458a233ca964cf5aca8430 - Author: git - Date: 2019-08-15 01:51:19 +0900 - - * expand tabs. [ci skip] - -commit fbcd0652944568c43a6ae427960d909d62ce6a8d - Author: Jeremy Evans - Date: 2019-08-14 14:44:36 +0900 - - Remove support for nil::Constant - - This was an intentional bug added in 1.9. - - The approach taken here is to add a second operand to the - getconstant instruction for whether nil should be allowed and - treated as current scope. - - Fixes [Bug #11718] - -commit 7d32cb7631677172d12010233432b7470046ec2a - Author: git - Date: 2019-08-15 01:00:46 +0900 - - * 2019-08-15 [ci skip] - -commit 938e075273feab804d0de840adec48ebe7508a60 - Author: Takashi Kokubun - Date: 2019-08-15 01:00:26 +0900 - - Add `make update-github PR=1234` to refresh PR (#2368) - - Notes: - Merged-By: k0kubun - -commit e173012f44dfef513c18d69abbd01b3354e897ed - Author: Takashi Kokubun - Date: 2019-08-14 23:41:30 +0900 - - Drop obsoleted `make merge-github` task - -commit 7da40d74e12cee72b96554a2d201965f1c7dedd7 - Author: Steven Harman - Date: 2019-08-14 23:35:47 +0900 - - backtrace and backtrace_locations can be nil (#2358) - - Exception#backtrace and Exception#backtrace_locations can both be nil if - not set. The former can be set via `Exception#set_backtrace`, but the - later is only ever set at runtime via `setup_backtrace`. - -commit 48e9155e659f332a82234831e1aa0d93a8b83a2a - Author: Nikolai B - Date: 2019-08-14 18:16:07 +0900 - - Remove strange formatting from English [ci skip] - - \vref is not valid doc syntax - - Notes: - Merged: https://github.com/ruby/ruby/pull/2364 - -commit 9874dca3e7c03bcf6969747f06f5c696e518b332 - Author: Takashi Kokubun - Date: 2019-08-14 23:00:09 +0900 - - Mark bundler / bundled-gems as continue-on-failure - - because these tests have failed too often and it's false-positive for - checking healthiness of the master branch. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2367 - -commit bf77f43b3991b63b832ff72cfc91b9761a32bdf8 - Author: Takashi Kokubun - Date: 2019-08-14 22:36:41 +0900 - - Update the description of check_branch - -commit 8be521662d1b1b0e6f791f6d9d29d529bdc427e1 - Author: Takashi Kokubun - Date: 2019-08-14 22:21:15 +0900 - - Rename check_branch.master to pull_request.check_branch - - because it's shown as just "master" on a pull request which does not - have the check_branch.master job yet. - - "check_branch" would be easier to understand and now we can grep it from - master branch. - -commit c8f97596b7dd6ffbeb98970f9cc664b0a8a2336e - Author: Alan Wu - Date: 2019-08-11 06:32:49 +0900 - - Don't accidentally name anonymous module/class - - b00f280d4b9569e7153365d7e1c522b3d6b3c6cf introduced - an accidental behavior change in that defining a module/class under - `m` gives `m` a name when `m` is anonymous. - - `ruby -ve 'Module.new { class self::A; end; p name }'` outputs a name - similar to `Module#inspect` when it should output `nil` like in Ruby - 2.6.x. - - * variable.c: Use `make_temporary_path` instead of `save_temporary_path` - when getting the name of the parent module. - - * variable.c (rb_set_class_path): Delegate to `rb_set_class_path_string` - instead of duplicating the logic. - - [Bug #16097] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2337 - -commit 1cffd5b4f0b88669bc2daff025ab0b1650961a43 - Author: Koichi Sasada - Date: 2019-08-14 16:30:30 +0900 - - fix last commit. - -commit 0971460e3113ea7dc3fd2a4ae80dd5947fd2dc55 - Author: git - Date: 2019-08-14 16:25:32 +0900 - - * expand tabs. - -commit 182a408c2c4113eb316c2a87e35880144afb4498 - Author: Koichi Sasada - Date: 2019-08-14 16:25:15 +0900 - - change Proc#to_s format ('@...' -> ' ...') (#2362) - - Now Proc#to_s returns - "#". - However, it is convenient to select a file name by (double-)clicking - on some terminals by separating ' ' instead of '@' like - "#" - [Feature #16101] - -commit 0623e2b7cc621b1733a760b72af246b06c30cf96 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-14 11:44:20 +0900 - - Suppress Uninitialized variables by Coverity Scan - - Coverity Scan says: - ``` - ** CID 1452284: Uninitialized variables (UNINIT) - /eval.c: 223 in rb_ec_cleanup() - ``` - - ``` - >>> CID 1452284: Uninitialized variables (UNINIT) - >>> Using uninitialized value "errs[1]". - ``` - -commit c744b626985f5d78c6d8d8830b9aee2898412d7c - Author: Nobuyoshi Nakada - Date: 2016-06-10 08:01:39 +0900 - - io.c: export rb_io_extract_modeenc - - * include/ruby/io.h (rb_io_enc_t): add typedef. - - * io.c (rb_io_extract_modeenc): export. - -commit cad41bb6d35c09b0e5d9e50280e3bfcd1bd9bcc0 - Author: Nobuyoshi Nakada - Date: 2019-08-14 10:43:46 +0900 - - [ruby/stringio] Supported BOM - - https://github.com/ruby/stringio/commit/b249631c43 - -commit 22e942deb2580faae44176064a569a84bccb5028 - Author: Nobuyoshi Nakada - Date: 2019-08-14 10:42:46 +0900 - - [ruby/stringio] Supported `mode:` option - - https://github.com/ruby/stringio/commit/53def32ba0 - -commit 8b44307894c3da6219e14693dc355ebb702310e0 - Author: Nobuyoshi Nakada - Date: 2019-08-14 10:42:14 +0900 - - [ruby/stringio] Allow bignum mode - - https://github.com/ruby/stringio/commit/d28927b561 - -commit e54d349a01043082169a88a2782e6739bdd52c4f - Author: Nobuyoshi Nakada - Date: 2019-08-14 03:02:30 +0900 - - [ruby/stringio] Added support for older versions - - https://github.com/ruby/stringio/commit/c4a13d41cd - https://github.com/ruby/stringio/commit/359c9f395c - -commit c8f9e9a2a0788fff08824985a74748dbe7ff7b18 - Author: Nobuyoshi Nakada - Date: 2016-06-10 14:18:14 +0900 - - [ruby/stringio] stringio: encoding support - - https://github.com/ruby/stringio/commit/7b20075ab0 - -commit 765d60315312a6a7068d9b24d7c6f38b778c4604 - Author: Takashi Kokubun - Date: 2019-08-14 10:52:15 +0900 - - Try to fix variable reference on Windows (#2361) - - https://github.com/ruby/ruby/runs/192869165 - - Notes: - Merged-By: k0kubun - -commit 8a687b8a4ff4096d7783bed58642112cfa3256a0 - Author: Takashi Kokubun - Date: 2019-08-14 09:23:57 +0900 - - Stop using official actions/checkout - - because it has been unstable, and also it sometimes does not work for a - pull request like: - https://github.com/ruby/ruby/pull/2358/checks?check_run_id=192685048#step:4:17 - - Notes: - Merged: https://github.com/ruby/ruby/pull/2360 - -commit 216d23008098c358d3a57cddc6f5d44e0b2f1602 - Author: SHIBATA Hiroshi - Date: 2019-08-14 07:44:26 +0900 - - Move some assertions to CoreAssertions. (#2354) - - They are used by default gems like forwardable. - - * assert_raise_with_message - * assert_warning - * assert_warn - - Notes: - Merged-By: hsbt - -commit 930e637c0e2ffd6fcb46205d473b6f4c05607471 - Author: git - Date: 2019-08-14 00:23:38 +0900 - - * 2019-08-14 - -commit 8827697ec42ee3a6bac1a73ee6b59d869dc152c2 - Author: Nobuyoshi Nakada - Date: 2019-08-14 00:23:19 +0900 - - Compare actual result - -commit 5b1bf8dd2d08ae7371ecf025967376bb794ed651 - Author: Nobuyoshi Nakada - Date: 2019-08-13 23:23:43 +0900 - - UTF LE is fixed at least the first 2 bytes - - * io.c (io_strip_bom): if the first 2 bytes are 0xFF0xFE, it - should be a little-endian UTF, 16 or 32. [Bug #16099] - -commit 79f9c626b63c2ce6ed1f3e767838a02a668145ba - Author: Takashi Kokubun - Date: 2019-08-13 23:36:31 +0900 - - Use the official actions/checkout again (#2357) - - because clone does not checkout exact commit sha, and also we'd need to handle - pull_request on fork, so I tentatively stopped to do this. - - Notes: - Merged-By: k0kubun - -commit c393734c95cea944d3d37da15b5600e41f75a740 - Author: git - Date: 2019-08-13 23:00:56 +0900 - - * expand tabs. - -commit dd1344b81eeff9805067e633f60107f4019fa019 - Author: Aaron Patterson - Date: 2019-08-13 06:00:34 +0900 - - Add compaction callbacks for Enumerator - - This commit gives Enumerator compaction support - -commit 94ca848ca19081e47852dddb1a4ae09688d18c29 - Author: Takashi Kokubun - Date: 2019-08-13 22:56:44 +0900 - - Update the comment in check_branch [ci skip] (#2355) - - Notes: - Merged-By: k0kubun - -commit e75e548cf9ee57f4504eb75aa584e587c470c218 - Author: Nobuyoshi Nakada - Date: 2019-08-13 21:11:58 +0900 - - spec/bundler needs the specific command [ci skip] - -commit d0b2e6412e58fef052034962c047ce4dafbf88eb - Author: Nobuyoshi Nakada - Date: 2019-08-13 15:39:49 +0900 - - Pass rb_execution_context_t* in ruby_run_node - -commit ffab84fa3ee7c0a0c2919664113caae6fac02403 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-13 15:27:46 +0900 - - Fix a typo [ci skip] - -commit 75d9fa8b079c27c66ac1eabfae366df465244fc4 - Author: Nobuyoshi Nakada - Date: 2019-08-13 12:24:55 +0900 - - Detect VCS from the current directory by default [ci skip] - -commit 0d1af9f942e391d8bf50a7ae2e6bb931542d541a - Author: Nobuyoshi Nakada - Date: 2019-08-13 12:24:15 +0900 - - Push commits notes too [ci skip] - -commit f78916e3c1fc10a7f9555129961194c7d6ba4f2d - Author: git - Date: 2019-08-13 11:20:39 +0900 - - * expand tabs. - -commit c215a6f2822d2d0c09e90867baadb250fd31206c - Author: Nobuyoshi Nakada - Date: 2019-08-13 11:03:54 +0900 - - Removed non-VM_OBJSPACE code - - It has not been used for 4 years, since r60856, - e33b1690d06f867e45750bd8e3e8b06d78b5bc26. - -commit 2f744f53c17cd1534c685d6c5f57af66ac5f8322 - Author: Nobuyoshi Nakada - Date: 2019-08-13 10:56:21 +0900 - - Refactored `objspace_each_objects` - - As `rb_objspace_each_objects_without_setup` doesn't reset and - restore `dont_incremental` flag, renamed the bare iterator as - `objspace_each_objects_without_setup`. `objspace_each_objects` - calls it when called with the flag disabled, wrap the arguments - otherwise only. - -commit 0c1c42c43a8609e212db9ef64e43d5ca04101694 - Author: Nobuyoshi Nakada - Date: 2019-08-13 10:33:19 +0900 - - Move rb_objspace_t* in objspace_reachable_objects_from_root to an argument - -commit aec93417f04a1726ac4491dd33821a383e4bdb5c - Author: git - Date: 2019-08-13 09:50:34 +0900 - - * expand tabs. - -commit ac656bc2bda6c7879b4b2170b7c2386a08112689 - Author: Nobuyoshi Nakada - Date: 2019-08-13 09:43:11 +0900 - - Hoisted out GPR_DEFAULT_REASON - -commit 917d766508707ebf894244fe4624b064315a7ad7 - Author: Nobuyoshi Nakada - Date: 2019-08-12 22:33:46 +0900 - - Move rb_objspace_t* in gc_verify_internal_consistency to an argument - -commit 0c2d81dada88b5a3946c3162187df4223bfe6b4f - Author: Nobuyoshi Nakada - Date: 2019-08-12 17:44:30 +0900 - - Renamed ruby_finalize_{0,1} - - And pass rb_execution_context_t as an argument. - -commit aac4d9d6c7e6b6b0742f3941b574f6006ccb5672 - Author: Aaron Patterson - Date: 2019-08-13 05:09:21 +0900 - - Rename rb_gc_mark_no_pin -> rb_gc_mark_movable - - Renaming this function. "No pin" leaks some implementation details. We - just want users to know that if they mark this object, the reference may - move and they'll need to update the reference accordingly. - -commit 404850e13446c79fb6142f1b32b219753e5cd726 - Author: Jeremy Evans - Date: 2019-08-12 11:42:59 +0900 - - Remove documentation that fatal cannot be rescued [ci skip] - - You can rescue it: - - f = ObjectSpace.each_object(Class){|c| break c if c.name == 'fatal'} - begin - raise f - rescue f - 2 - end # => 2 - - It's not a good idea to rescue fatal exceptions you didn't generate - yourself, though. - - Fixes [Bug #10691] - -commit 3979f22cc1a224bad5b8f14610db253660aa974c - Author: Takashi Kokubun - Date: 2019-08-13 01:45:10 +0900 - - Explain the current status of branches [ci skip] (#2350) - - Notes: - Merged-By: k0kubun - -commit e688ab26c71c124ca1c466d9c5c669bd1ce61e6e - Author: git - Date: 2019-08-13 01:34:36 +0900 - - * expand tabs. - -commit 6749682f8225b50bc91a45af0f27f20ff68d473c - Author: Aaron Patterson - Date: 2019-08-10 08:27:43 +0900 - - also unpin `final` on weak maps - -commit 76a928bac2f37e7aa631a6b6dd5320920d6c1b42 - Author: Aaron Patterson - Date: 2019-08-10 08:05:42 +0900 - - Unpin default value objects - - We're already updating the location of default values, so we may as well - unpin them. - -commit 4e418a6c0676271da3176116a62a2fc913ac4548 - Author: Takashi Kokubun - Date: 2019-08-13 01:29:37 +0900 - - Update check_branch description a little [ci skip] - -commit 957bdfbab8e8095bab82fa2e32571196e1777e10 - Author: Aaron Patterson - Date: 2019-08-13 01:21:37 +0900 - - Update docs to use more natural English - - Just a few updates to make the English sound a bit more natural - -commit 0f10828fcfe4a0d082398da71992a7535a4fab52 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-13 01:03:14 +0900 - - Fix a typo [ci skip] - -commit 4d3fb247364a13e12ea41885511b944b0e37917d - Author: git - Date: 2019-08-13 00:51:04 +0900 - - * 2019-08-13 - -commit b8b5e7d5bea99190cf62190e020fea7f82209f0e - Author: Nobuyoshi Nakada - Date: 2019-08-12 19:39:04 +0900 - - Stop rewriting message to include PR URL - - Notes: - Merged: https://github.com/pull/2347 - -commit edd25382687c840f10eec23d72fa08ebd3515fbf - Author: Takashi Kokubun - Date: 2019-08-12 23:36:42 +0900 - - Add a quick job to be used for branch protection - -commit 8d302c914c15af4a29c8b8af801281fa117a7ad2 - Author: Yusuke Endoh - Date: 2019-08-12 23:12:27 +0900 - - string.c (rb_str_sub, _gsub): improve the rdoc - - This change: - - * Added an explanation about back references except \n and \k - (\` \& \' \+ \0) - * Added an explanation about an escape (\\) - * Added some rdoc references - * Rephrased and clarified the reason why double escape is needed, added - some examples, and moved the note to the last (because it is not - specific to the method itself). - -commit 3fc10eff1e6dd63bc0daa753108072954adc89ac - Author: Nobuyoshi Nakada - Date: 2016-09-30 20:49:58 +0900 - - date_parse.c: trim off - - * ext/date/date_parse.c (date_zone_to_diff): trim off by zone name - length. - -commit d96feee37c2d109d0103f08985e85641a23108bf - Author: Nobuyoshi Nakada - Date: 2016-09-30 20:38:23 +0900 - - date_parse.c: avoid copying - - * ext/date/date_parse.c (date_zone_to_diff): get rid of copying - the whole argument string. - -commit e6a0a954c9ef5170b8b25088455106b3748c2187 - Author: Takashi Kokubun - Date: 2019-08-12 20:40:13 +0900 - - Add another test for frame omitted inlining - -commit a5f9306065b8a50cca6cdb65003d0c36d1180c09 - Author: Takashi Kokubun - Date: 2019-08-12 20:20:37 +0900 - - Simplify sudo specification - -commit 188381053cadc06c7c08dd03acb3fdff8de0e472 - Author: Hiroshi SHIBATA - Date: 2019-08-12 19:40:46 +0900 - - added --disable-install-doc to Windows workflow of GitHub Actions - - Closes: https://github.com/ruby/ruby/pull/2346 - -commit ab3ab07b28ac58333d7bbf898ec7cf5973bd02a6 - Author: Hiroshi SHIBATA - Date: 2019-08-12 19:12:29 +0900 - - Removed configuration of Azure Pipelines - -commit 8d50bf40d9fc7015c0a8d52d9e4cf9efbf57ae3c - Author: Hiroshi SHIBATA - Date: 2019-08-12 19:08:51 +0900 - - Try to nmake test - -commit 0fd0f74508e1b6d26605a85066e18a4d00a02d84 - Author: Hiroshi SHIBATA - Date: 2019-08-12 18:56:01 +0900 - - Try to merge windows 2016 and 2019 - -commit 040bf4c0a69cfcc4df6250f0241b9c7cc4a42ab6 - Author: Hiroshi SHIBATA - Date: 2019-08-12 18:33:22 +0900 - - Added windows-2019 workflow - -commit 981f0be6ffd082e9954263323ac149fbfa2e8c01 - Author: Hiroshi SHIBATA - Date: 2019-08-12 18:17:57 +0900 - - Try to nmake - -commit bbc5e97b959ba526036f0f6c95682c1721a87130 - Author: Hiroshi SHIBATA - Date: 2019-08-12 18:06:06 +0900 - - Migrate Windows 2016 env to GitHub Actions from AzurePipelines - -commit 1bec27f05bd40b03b6b7c8cd16a74d9096491e37 - Author: Takashi Kokubun - Date: 2019-08-12 19:52:37 +0900 - - Add exec to apt-get update - - to propagate exit status to travis_retry properly. - -commit f9149c5596e1317687d6f58b14e6f3ee89bc7f2e - Author: Takashi Kokubun - Date: 2019-08-12 19:13:30 +0900 - - Minor wording fix in NEWS [ci skip] - - pushing a trivial commit for testing post-receive hook - -commit 066a3498c6b7d1218b51f19c4b26447a56523aef - Author: Nobuyoshi Nakada - Date: 2019-08-12 19:01:57 +0900 - - Include commits notes in ChangeLog - -commit 5edf921e9bce453b6a68040340940489bf350cc4 - Author: Takashi Kokubun - Date: 2019-08-12 17:55:57 +0900 - - Revert "Roughly retry `brew update` on GitHub Actions" - - This reverts commit 5ee11a95ffbf194a73d1bea300a35f5d6250d203. - - Sorry, timeout(1) was missing. - -commit 927a43a503bd846ab706ff40990ab4ecae8abdc3 - Author: Takashi Kokubun - Date: 2019-08-12 17:46:11 +0900 - - Drop unused ccache - - unlike Travis, it seems not used. - -commit 5ee11a95ffbf194a73d1bea300a35f5d6250d203 - Author: Takashi Kokubun - Date: 2019-08-12 17:44:02 +0900 - - Roughly retry `brew update` on GitHub Actions - - because it has failed often on Travis. - -commit d5250808e1e06c4af7d441971e29096426611ab0 - Author: Takashi Kokubun - Date: 2019-08-12 16:36:56 +0900 - - Try testing openssl@1.1 on GitHub Actions - - because somebody may want to remove the duplicated Travis osx usage - later. - - Notes: - Merged: https://github.com/ruby/ruby/pull/2343 - -commit 765cc17c086024540bc09124bd3628c539faa7b0 - Author: Sho Ito - Date: 2019-08-12 00:11:34 +0900 - - Update IRB man page - - Notes: - Merged: https://github.com/ruby/ruby/pull/2341 - -commit 0d0ff8277fcea4584aa33b8b180a4ade7b90590e - Author: Nobuyoshi Nakada - Date: 2019-08-12 15:13:09 +0900 - - rb_trap_exec has been removed since 1.9 - -commit b1ef14176b3716e3900672a9563b94aa3abedb2d - Author: Takashi Kokubun - Date: 2019-08-12 14:35:49 +0900 - - We did not have tool/ before checkout - - anyway we don't need authorization here. - Also retry does not seem to work in the original version, so let's - extend this with retries as a separate github action later. - -commit 4f10a61eaaf5bfe7e4c53edc79c5e27a7bd1ae33 - Author: Takashi Kokubun - Date: 2019-08-12 14:30:42 +0900 - - Stop relying on actions/checkout - - because it randomly fails on authorization like: - https://github.com/ruby/ruby/runs/190887455 - Also the backoff seems too short. Maybe we need tool/travis_retry.sh for - this too. - - Cloning ruby/ruby does not need authorization. We don't need to use - actions/checkout. - -commit 2b3d84d584e4a4cec5fe452db422c76048826c2b - Author: Nobuyoshi Nakada - Date: 2019-08-12 01:04:21 +0900 - - Use rev-parse - - Use simpler rev-parse to check if pull request was fetched. - -commit b1ad628cdfaef8da8d79d425b5012eb699ff9c1b - Author: Takashi Kokubun - Date: 2019-08-12 13:45:55 +0900 - - Resurrect travis_wait for test-all - - as we dropped -v. - -commit 63d3c4fecd074790c7d9c6e561401cf512bd1d22 - Author: git - Date: 2019-08-12 12:59:08 +0900 - - * 2019-08-12 - -commit bf1f872991bcfcb86472873794bcef88749b95d0 - Author: Hiroshi SHIBATA - Date: 2019-08-12 12:08:42 +0900 - - Removed duplicated jobs with GitHub Actions. - - Closes: https://github.com/ruby/ruby/pull/2340 - -commit ed9d59afc811ff738c4218a2edf71b3c9c49e370 - Author: Hiroshi SHIBATA - Date: 2019-08-12 09:01:00 +0900 - - Added example filter for Linux of GitHub Actions. - -commit 8a8f680f017d0d4c410f17ec74e06d0436dcbe83 - Author: Hiroshi SHIBATA - Date: 2019-08-12 08:23:27 +0900 - - Re-use GITHUB_ACTION variables for filtering bundler examples. - -commit e96321d006f822766bb4be969028f68096d76b39 - Author: Hiroshi SHIBATA - Date: 2019-08-12 07:25:11 +0900 - - Removed make check - -commit fc97aa93132de82a02f4f115de14e6478ec7a7b3 - Author: Hiroshi SHIBATA - Date: 2019-08-12 07:07:54 +0900 - - Fixed the world writable dirs on Ubuntu environment. - -commit cfb192a7b9b00c479abbbbe35d396cc5295285e5 - Author: Hiroshi SHIBATA - Date: 2019-08-11 19:33:03 +0900 - - Added test-bundled-gems to GitHub Actions - -commit 11a09d78c185848a179028a292f583bc356f6b25 - Author: Hiroshi SHIBATA - Date: 2019-08-11 19:12:38 +0900 - - Port ubuntu workflow based on macos - -commit 9fe7e042f50ba7bcd7b64e48b4e6077eeead2861 - Author: Nobuyoshi Nakada - Date: 2019-08-11 16:19:31 +0900 - - Note the reference to the pull request [ci skip] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2339 - -commit 51d9d0f8887820ce52234c80d78388b002e6e628 - Author: Nobuyoshi Nakada - Date: 2019-08-11 15:42:16 +0900 - - Use already fetched pull request [ci skip] - - Notes: - Merged: https://github.com/ruby/ruby/pull/2338 - -commit 1c7eadf75447f10b62e6a93a9c0a90b01bf126e1 - Author: Takashi Kokubun - Date: 2019-08-11 14:15:48 +0900 - - Debug which test hangs on mswin - - debugging failure of - https://ci.appveyor.com/project/ruby/ruby/builds/26613960/job/nemi6pvc5s5843io - -commit 053bee64cb872398c25467a77169853d8ce539d2 - Author: Hiroshi SHIBATA - Date: 2019-08-11 10:49:22 +0900 - - Cleanup the duplicated tasks on Azure Pipelines. - - Closes: https://github.com/ruby/ruby/pull/2336 - -commit 91fcd87f5c0375e36c22c1187edf3f5507572075 - Author: Hiroshi SHIBATA - Date: 2019-08-11 06:55:31 +0900 - - Increase fetch-depth - -commit bb2f24251f011d64d369d78f344e298cc9486473 - Author: Hiroshi SHIBATA - Date: 2019-08-11 08:10:40 +0900 - - GitHub Actions does not support ANSI color code. Skip failing examples. - -commit c685679e25f6a4547c3b48c290bfb905cde0b4ef - Author: Hiroshi SHIBATA - Date: 2019-08-11 07:32:30 +0900 - - Use check. - -commit e7996e0fd6718fa13b5cd5328f1bb6393a45392c - Author: Hiroshi SHIBATA - Date: 2019-08-11 06:26:17 +0900 - - Try to migrate test-bundler to Actions. - -commit 6017e81b033d9eb8ab66dc1bd3402f51155761f1 - Author: Kazuki Tsujimoto - Date: 2019-08-11 11:00:24 +0900 - - Update power_assert to 1.1.5 - -commit f731cc0984560d8dabd211e7b827617fe078cca1 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-11 10:15:05 +0900 - - Use `end_with?` instead of Regexp with missing escape - -commit 2990c2cc3e5a105013b829dad00fa43a26da8682 - Author: Hiroshi SHIBATA - Date: 2019-08-11 06:12:46 +0900 - - Use capture_output instead of capture_io. - - It's preparation for migrating test-unit on upstream. - -commit 7ee948c3a11c5fb79d6f3ec2878a64387e29ba7a - Author: git - Date: 2019-08-11 00:45:23 +0900 - - * 2019-08-11 - -commit d29bccb39bfd2890b33a3fd943916d62527b6e6e - Author: Nobuyoshi Nakada - Date: 2019-08-10 23:47:31 +0900 - - Adjust indent [ci skip] - -commit 46df7fe91f84ce2b2033a784402d3e451d1ff1db - Author: Nobuyoshi Nakada - Date: 2019-08-10 23:45:49 +0900 - - prereq.status deals with removal of nmake VPATH notations [ci skip] - -commit 0609087a6bac37b7fbf7a56db670094b214f7359 - Author: Takashi Kokubun - Date: 2019-08-10 23:57:20 +0900 - - Parallelize osx test-all too - -commit c21c00173349cd9b0aeb899dd9fea5cfba984af4 - Author: Nobuyoshi Nakada - Date: 2019-08-10 16:36:10 +0900 - - Re-enable parallel build/test on OSX - -commit 52bd4716b482337bd8f9f8389c5ab9d168fb11f8 - Author: Nobuyoshi Nakada - Date: 2019-08-10 23:19:24 +0900 - - rb_numeric_quo: support Complex - -commit c1c8577088b1fa36a34ca8b885db441365b27aa7 - Author: Takashi Kokubun - Date: 2019-08-10 20:25:58 +0900 - - Fix wrong pull_request filter - - The specification was not triggered on a pull request. - -commit 00e7ef7e8d1a31d12f7117c07370d6d00cc5eaa2 - Author: Nobuyoshi Nakada - Date: 2019-08-10 19:49:21 +0900 - - Suppress flags messages [ci skip] - -commit a6c5ce7a9bbf584a8b4b39d2ae51fb9b4a5b7f1f - Author: Takashi Kokubun - Date: 2019-08-10 19:39:00 +0900 - - Increase the fetch-depth of GitHub Actions - - because small numbers had made Azure Pipelines in the past and it's - using 20 now. I heard GitHub Actions has more parallelism, so it should - be okay. - -commit b3903ef2a156a19de0c27a3e95cd7a4467cdce59 - Author: Takashi Kokubun - Date: 2019-08-10 19:38:27 +0900 - - Set more descriptive labels to workflow - -commit 59a8003ac5273d65c1d7f39c158c675ce48f25ad - Author: Takashi Kokubun - Date: 2019-08-10 19:33:11 +0900 - - Drop confusing label from workflow - - because it's doing more than test-all - -commit 6205f95539f257adc6b3ab904ff26ff5ed2ff9d3 - Author: Takashi Kokubun - Date: 2019-08-10 19:29:39 +0900 - - Escape asterisk on pull request paths - -commit e43b3bb442836c8064637a7d46c05ad16a4e0115 - Author: Takashi Kokubun - Date: 2019-08-10 19:28:07 +0900 - - Skip running GitHub Actions on trunk - -commit 9b203959d51b597075fe8bfcc07a24845bca4876 - Author: Takashi Kokubun - Date: 2019-08-10 19:19:22 +0900 - - Rename workflow.yml to macos.yml - - to allow having other workflows separately, and configure `name` to - simplify a tooltip label on GitHub. - -commit 5e3fb0b3572d64a82ed86af15d4adca50d71fd6b - Author: Nobuyoshi Nakada - Date: 2019-08-10 16:33:32 +0900 - - Touch the checked out source to fix clock skew on all platform - -commit c5fbe2a19fb8ffe8c64fc8f3810693dd3b4f7edd - Author: Nobuyoshi Nakada - Date: 2019-08-10 15:48:39 +0900 - - Moved options to $travis_apt_get_options - -commit d69ffa4d93b12ddfb0d77f146921eb5d2fd62919 - Author: Nobuyoshi Nakada - Date: 2019-08-10 14:30:34 +0900 - - Expanded f_quo - -commit 98c22c78e40d84678e7bac187236e049e9d8c211 - Author: Nobuyoshi Nakada - Date: 2019-08-10 13:56:18 +0900 - - Expanded f_real_p - -commit ffdef3674af921d7ddd550dc492dcdbed97f7ba5 - Author: Nobuyoshi Nakada - Date: 2019-08-10 13:18:41 +0900 - - Warn instance variable `E` - - It is not dumped, as it is a short alias for `:encoding`. - -commit 3c3783ac88f8f8fbbad016a2daf3e35a682c4b3e - Author: git - Date: 2019-08-10 11:43:07 +0900 - - * expand tabs. - -commit ab31693af109022ecc0a01107067d5c84675807a - Author: Nobuyoshi Nakada - Date: 2019-08-10 11:38:49 +0900 - - Share caches for short encoding ivar name. - -commit 07e42e88d9f2b7756dde0a2377990ebf3c5e1973 - Author: Nobuyoshi Nakada - Date: 2019-08-10 11:26:23 +0900 - - Close created files [ci skip] - -commit 690282472960ff070883bd2151a0728ee5a01eea - Author: Masato Ohba - Date: 2019-08-10 09:28:37 +0900 - - Fix typo in comment [ci skip] - - s/Thtread/Thread - -commit 49f88eb2f1e8c46a4a3b5f6ea3dfa5a5f9d32988 - Author: Takashi Kokubun - Date: 2019-08-10 09:34:13 +0900 - - Try building workflow on push - -commit 789776be08830b53499db86ab33ade9db1111a79 - Author: iain barnett - Date: 2019-08-04 13:37:54 +0900 - - Added some examples to the documentation for String#unpack1 because - there are currently no examples and to contrast with String#unpack. - -commit 9d298b9dab831f966ea4bf365c712161118dd631 - Author: John Hawthorn - Date: 2019-06-27 01:52:30 +0900 - - Allow Array#join to allocate smaller strings - - rb_str_buf_new always allocates at least 127 bytes of capacity, even - when less is requested. - - > ObjectSpace.dump(%w[a b c].join) - {"address":"0x7f935f06ebf0", "type":"STRING", "class":"0x7f935d8b7bb0", "bytesize":3, "capacity":127, "value":"abc", "encoding":"UTF-8", "memsize":168, "flags":{"wb_protected":true}} - - Instead, by using rb_str_new and then setting the length to 0, we can - allocate the exact amount of memory needed, without extra capacity. - - > ObjectSpace.dump(%w[a b c].join) - {"address":"0x7f903fcab530", "type":"STRING", "class":"0x7f903f8b7988", "embedded":true, "bytesize":3, "value":"abc", "encoding":"UTF-8", "memsize":40, "flags":{"wb_protected":true}} - -commit b1678338e545589540b1dd85dee6a18fd98aa8ed - Author: ohbarye - Date: 2019-08-10 01:56:40 +0900 - - Fix typo: duplicated the [skip-ci] - -commit 162cf2879af592f8aa458311486749bed9a6bf55 - Author: Nobuyoshi Nakada - Date: 2019-08-10 01:39:36 +0900 - - Init function is need to link statically - -commit 53b3be5d58a9bf1efce229b3dce723f96e820c79 - Author: Jeremy Evans - Date: 2019-08-09 12:02:54 +0900 - - Fix parsing of multiple assignment with rescue modifier - - Single assignment with rescue modifier applies rescue to the RHS: - - a = raise rescue 1 # a = (raise rescue 1) - - Previously, multiple assignment with rescue modifier applied rescue - to the entire expression: - - a, b = raise rescue [1, 2] # (a, b = raise) rescue [1, 2] - - This makes multiple assignment with rescue modifier consistent with - single assignment with rescue modifier, applying rescue to the RHS: - - a, b = raise rescue [1, 2] # a, b = (raise rescue [1, 2]) - - Implements [Feature #8239] - Fixes [Bug #8279] - -commit cecae8593abb79213f818078ee0361277401f86c - Author: Nobuyoshi Nakada - Date: 2019-08-10 01:05:09 +0900 - - Removed unnecessary headers - -commit 88db6fa4793da3724c0128e53cfe1abead1774f8 - Author: Nobuyoshi Nakada - Date: 2019-08-10 01:04:39 +0900 - - Use ENC_REPLICATE to copy an encoding - -commit 8d7e0159c0c9fa1a546b4fa324837beae5eea3ee - Author: git - Date: 2019-08-10 00:04:06 +0900 - - * 2019-08-10 - -commit a8ba22cd323d481eb8bd08ebca0fab8f1dbfc2f9 - Author: Yusuke Endoh - Date: 2019-08-10 00:01:36 +0900 - - Revert "Removed unused includes" - - This reverts commit c9eb8f82e9febeb634a23bec6aeea915eb25fe26. - - The change caused "implicit declaration" warning and actual segfault. - - ``` - /tmp/ruby/v2/src/trunk-gc-asserts/enc/gb2312.c: In function ‘Init_gb2312’: - /tmp/ruby/v2/src/trunk-gc-asserts/enc/gb2312.c:6:31: warning: implicit declaration of function ‘rb_enc_find’ [-Wimplicit-function-declaration] - rb_enc_register("GB2312", rb_enc_find("EUC-KR")); - ^~~~~~~~~~~ - /tmp/ruby/v2/src/trunk-gc-asserts/enc/gb2312.c:6:31: warning: passing argument 2 of ‘rb_enc_register’ makes pointer from integer without a cast [-Wint-conversion] - :0:19: note: expected ‘OnigEncoding {aka const struct OnigEncodingTypeST *}’ but argument is of type ‘int’ - /tmp/ruby/v2/src/trunk-gc-asserts/regenc.h:231:12: note: in expansion of macro ‘ONIG_ENC_REGISTER’ - extern int ONIG_ENC_REGISTER(const char *, OnigEncoding); - ^~~~~~~~~~~~~~~~~ - ``` - -commit 314b50d7c05e946e4e9bbc5fdb38ecb67180c139 - Author: Nobuyoshi Nakada - Date: 2019-08-09 23:10:06 +0900 - - #include <> for system headers - -commit c9eb8f82e9febeb634a23bec6aeea915eb25fe26 - Author: Nobuyoshi Nakada - Date: 2019-08-09 20:20:36 +0900 - - Removed unused includes - -commit 3ddbba84b5b1f001cd575a48cec56d7ce8e5fbb2 - Author: Yusuke Endoh - Date: 2019-08-09 22:48:20 +0900 - - gc.c: Double STACKFRAME_FOR_CALL_CFUNC (1024->2048) - - ef64ab917eec02491f6bf7233a4031a8c35385e3 didn't fix the issue, so the - size seems not enough yet. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/osx1014/ruby-master/log/20190809T114503Z.fail.html.gz - -commit 63384591e2c72b89f9d69d9acc6c8b80ca8432c3 - Author: Koichi Sasada - Date: 2019-08-09 17:48:47 +0900 - - restore timeout - -commit ef64ab917eec02491f6bf7233a4031a8c35385e3 - Author: Yusuke Endoh - Date: 2019-08-09 17:31:19 +0900 - - gc.c: Increase STACKFRAME_FOR_CALL_CFUNC - - On macOS Mojave, the child process invoked in TestFiber#test_stack_size - gets stuck because the stack overflow detection is too late. - (ko1 figured out the mechanism of the failure.) - - This change attempts to detect stack overflow earlier. - -commit a4a2dd79420d1061ab1615a50b830f567e043d34 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-09 16:29:43 +0900 - - Revert a6e32855d079e8f3806d8be8a5f5cf7b3a967133 partially - - Fix TypeError when typing `''.[TAB]` - -commit 3cbd56d574a3ce6d5ddeb748462eb4dcdce4d166 - Author: Koichi Sasada - Date: 2019-08-09 16:08:15 +0900 - - complement `test_` prefix. - - `make test-all TESTS=name` can specify running test files by name. - name can be dirname ('dir/') or a file ('.../test_foo.rb'). This - patch complement `test_` prefix for a test. So we only need to - specify `TESTS=ruby/hash` which means `TESTS=ruby/test_hash.rb`. - -commit 26cf4c91ad357fe6c8fc2247abe980dbf9a5b331 - Author: Koichi Sasada - Date: 2019-08-09 15:23:35 +0900 - - extend timeout to debug. - -commit 3b39cc6b038d419081a3d302a3cd73c3859613c7 - Author: Koichi Sasada - Date: 2019-08-09 14:11:24 +0900 - - gc.h is required on mswin build. - - thread.c requires gc.h on mswin build. Sorry. - -commit 6bf8db9a07e95820705f7ec119f4038a529182ef - Author: Koichi Sasada - Date: 2019-08-09 13:57:47 +0900 - - add rp() and bp() in internal.h. - - debug utility macro rp() (rp_m()) and bp() are introduced. - * rp(obj) shows obj information w/o any side-effect to STDERR. - * rp_m(m, obj) is similar to rp(obj), but show m before. - * bp() is alias of ruby_debug_breakpoint(), which is registered - as a breakpoint in run.gdb (used by `make gdb` or make gdb-ruby`). - -commit cb390e87dc682a277579f44fac6aea57e16e5f7a - Author: Aaron Patterson - Date: 2019-08-09 05:29:02 +0900 - - Add more runners - - Closes: https://github.com/ruby/ruby/pull/2327 - -commit 54bdfe27f361c0cccb9d16f32e5796b47d017134 - Author: Aaron Patterson - Date: 2019-08-09 00:28:49 +0900 - - Run macOS tests on GitHub Actions - - This commit sets up the CI integration on GitHub Actions. We should - give it a try because queue times are lower and I think we get more - CPUs. - - Closes: https://github.com/ruby/ruby/pull/2327 - - Co-Authored-By: John Hawthorn - -commit 37eefb11fbadca6198b081a0a89d5b265fe45de4 - Author: Koichi Sasada - Date: 2019-08-09 13:08:01 +0900 - - remove useless include and dependency - -commit a9fd57056cdbf041f8f0ad1350846a175028542a - Author: Koichi Sasada - Date: 2019-08-09 13:02:31 +0900 - - double memory limit on MJIT. - - On test with MJIT, sometimes it fails like: - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2189967 - -commit 0176e74d6c3de4a71424d9bc0bc63c408550b488 - Author: Takashi Kokubun - Date: 2019-08-09 11:39:20 +0900 - - Add missing dependency - - just fix CI failure - https://travis-ci.org/ruby/ruby/jobs/569625233 - -commit 4e9382a82756ff92032b85f8ec0256b1cf5ac6ad - Author: git - Date: 2019-08-09 11:11:18 +0900 - - * expand tabs. - -commit 71efad1ed391ee0c5398a76306fdbaaadd4dc52e - Author: Koichi Sasada - Date: 2019-08-09 11:00:34 +0900 - - introduce RCLASS_CLONED flag for inline cache. - - Methods on duplicated class/module refer same constant inline - cache (IC). Constant access lookup should be done for cloned - class/modules but inline cache doesn't check it. - To check it, this patch introduce new RCLASS_CLONED flag which - are set when if class/module is cloned (both orig and dst). - [Bug #15877] - -commit c7acb37248d4cef76647f8bc7ebd7dc291d9a853 - Author: Aaron Patterson - Date: 2019-08-09 03:29:15 +0900 - - Enable GitHub Actions on Ruby - - This just enables GitHub actions on our repository so we can try it out. - -commit 57288f5dbd9a13c00a0ec5860b46c027f34df1ae - Author: git - Date: 2019-08-09 01:32:30 +0900 - - * expand tabs. - -commit 050b932152fb3004c78af223186afe1aa397f06f - Author: Alan Wu - Date: 2019-08-08 11:15:45 +0900 - - Iseq#to_binary: Add support for NoMatchingPatternError and TypeError - - Binary dumping the iseq for `case foo in []; end` used to crash as - there was no handling for these exception classes. - - Pattern matching generates these classes as operands to `putobject`. - - [Bug #16088] - Closes: https://github.com/ruby/ruby/pull/2325 - -commit 830fd0418170843f234ed82e07d2fd61d86153e7 - Author: Nobuyoshi Nakada - Date: 2019-08-09 01:27:52 +0900 - - C99 allows trailing comma in enum - -commit c0f4943840948100b057ebb0ef6764ffd252cd5e - Author: git - Date: 2019-08-09 00:16:24 +0900 - - * 2019-08-09 - -commit ad3f7a3667d79a7d23c78e026d3eb5a42bd0b7b3 - Author: Nobuyoshi Nakada - Date: 2019-08-09 00:06:08 +0900 - - Should require without wrapper module - -commit a206738762ea788830e8b3ac58b37d705595a6fb - Author: Nobuyoshi Nakada - Date: 2019-08-08 22:40:09 +0900 - - Remove temporary directory [ci skip] - -commit a9b9f9d157ac28e4818b3e6db0e4d924faf97649 - Author: Takashi Kokubun - Date: 2019-08-08 22:35:11 +0900 - - Revert "Drop -j from msys2 build for debugging" - - This reverts commit b1594ca3d6b72edb60927418482652ce93209499. - - Revert "Debug appveyor mingw failure" - - This reverts commit fa29f65416f1fb3d734a279855728bb0616dbb34. - - Though I preserved V=1 for future debugging. - -commit 995c2e9536a7c0f0476d1f62ac3c9bcb68513c59 - Author: Nobuyoshi Nakada - Date: 2019-08-08 22:17:22 +0900 - - Reduce unnecessary EXEC_TAG in require - -commit 2a6d7fad133cd6e1e50de6b8627d19eecee5ed8f - Author: Takashi Kokubun - Date: 2019-08-08 22:03:00 +0900 - - Arrange installed packages like ruby-loco - - to fix a build error like: - https://ci.appveyor.com/project/ruby/ruby/builds/26547644/job/4j7n41e7in97a9kx - - Basically copy-pasted what's currently done in MSP-Greg/ruby-loco. - - Co-Authored-By: MSP-Greg - -commit 76bd0714cf1140ffd64bf564446c76c54f2c4870 - Author: Nobuyoshi Nakada - Date: 2019-08-08 21:26:31 +0900 - - solve "duplicate :raise event" in require too [Bug #15877] - -commit 3d87b774c4e38e0dbe3ef181183565c5987cd05f - Author: Nobuyoshi Nakada - Date: 2019-08-08 21:08:00 +0900 - - Use `ec` instead of `th->ec` where the `th` came from the `ec` - -commit b1594ca3d6b72edb60927418482652ce93209499 - Author: Takashi Kokubun - Date: 2019-08-08 20:37:12 +0900 - - Drop -j from msys2 build for debugging - -commit 29bdfeb0c6d3490fbd7e5a7cc89598ca7340176e - Author: git - Date: 2019-08-08 17:59:38 +0900 - - * expand tabs. - -commit b004d3e8300ba803d4a499148fa4fc6a690149e6 - Author: Koichi Sasada - Date: 2019-08-08 17:53:36 +0900 - - solve "duplicate :raise event" [Bug #15877] - - Without this patch, "raise" event invoked twice when raise an - exception in "load"ed script. - This patch by danielwaterworth (Daniel Waterworth). - [Bug #15877] - -commit 20cb8e8aeab916d659c0359a35687bb8df1f31a6 - Author: Yusuke Endoh - Date: 2019-08-08 17:34:50 +0900 - - main.c: Add doxygen mainpage - - The document is experimentally produced in: - https://rubyci.s3.amazonaws.com/doxygen/modules.html - -commit b39efb163dd97a6b2c92cac3d2b1c19f898d0c04 - Author: Hiroshi SHIBATA - Date: 2019-08-08 17:19:23 +0900 - - Aliases capture_output to capture_io for test-unit compatibility. - -commit 1ad0f4e593563d460e3015fc4a2542ce1bb80d6e - Author: Gannon McGibbon - Date: 2019-08-07 07:38:55 +0900 - - Add *_clear methods to VM_COLLECT_USAGE_DETAILS API - - Add RubyVM::USAGE_ANALYSIS_INSN_CLEAR, RubyVM::USAGE_ANALYSIS_OPERAND_CLEAR, - and RubyVM::USAGE_ANALYSIS_REGISTER_CLEAR to clear VM instruction hash constants. - - Closes: https://github.com/ruby/ruby/pull/2258 - -commit 1c7d3a13caa718ef52ec6b55988b1459a002f965 - Author: Gannon McGibbon - Date: 2019-03-12 04:07:52 +0900 - - Add *_start and *_running methods to VM_COLLECT_USAGE_DETAILS API - - Add RubyVM::USAGE_ANALYSIS_INSN_START, RubyVM::USAGE_ANALYSIS_OPERAND_START, - and RubyVM::USAGE_ANALYSIS_REGISTER_START to begin collecting VM instructions. - - Add RubyVM::USAGE_ANALYSIS_INSN_RUNNING, RubyVM::USAGE_ANALYSIS_OPERAND_RUNNING, - and RubyVM::USAGE_ANALYSIS_REGISTER_RUNNING to check if VM instructions - are being collected. - - Closes: https://github.com/ruby/ruby/pull/2258 - -commit 70fd099220446e39bb80eb0bb32870ce12134619 - Author: Aaron Patterson - Date: 2019-08-07 04:23:30 +0900 - - Add a way to print debug counters without exiting - - I am trying to study debug counters inside a Rails application. - Accessing debug counters by killing the process is hard because child - processes don't get the same TRAP as the parent, and Rails seems to - intercept calls to `exit`. Adding this method lets me print the debug - counters when I want (at the end of requests for example) - -commit 2f3795113df23006f1f99dd5879a8a9acbc29c5c - Author: git - Date: 2019-08-08 00:11:34 +0900 - - * 2019-08-08 - -commit fa29f65416f1fb3d734a279855728bb0616dbb34 - Author: Takashi Kokubun - Date: 2019-08-08 00:10:26 +0900 - - Debug appveyor mingw failure - - It has been unstable for recent builds: - https://ci.appveyor.com/project/ruby/ruby/builds/26531442/job/0ycp7woekqqx97x9 - https://ci.appveyor.com/project/ruby/ruby/builds/26531687/job/xui3rctcvi7r49iv - https://ci.appveyor.com/project/ruby/ruby/builds/26532019/job/1q0n46ci4g8dplwx - -commit f82633b6a6053e6273e8795d3e91c50ab5c260d8 - Author: Yusuke Endoh - Date: 2019-08-07 22:56:52 +0900 - - array.c: gc.h is not needed - -commit 3229e0583fba6a7f1c58a1dd8aa7d4ca9c5155d9 - Author: Yusuke Endoh - Date: 2019-08-07 22:54:38 +0900 - - hash.c: gc.h is needed when HASH_DEBUG mode - -commit 0cf6bfca7866a0205ba6d603cca7c87f4db0065e - Author: Yusuke Endoh - Date: 2019-08-07 22:42:42 +0900 - - hash.c: gc.h is no longer needed - -commit f5481e35abfc8d53cffe33246b4d5736798f4241 - Author: Hiroshi SHIBATA - Date: 2019-08-07 22:30:10 +0900 - - Added separator for failing commits from default gems. - -commit 67cde179c5b23f1e8da3cb7554d26c79ed1c3b97 - Author: Hiroshi SHIBATA - Date: 2019-08-07 22:29:02 +0900 - - Skip merge commit created by bundlerbot. - -commit 82527d9b50207607b2adb7fb6dded91d23749feb - Author: Daniel Radetsky - Date: 2019-08-07 10:21:32 +0900 - - fix spelling - - Closes: https://github.com/ruby/ruby/pull/2323 - -commit 58dec9625cc705fd9be6dc1ea20e232303e9c32d - Author: Yusuke Endoh - Date: 2019-08-07 22:22:52 +0900 - - enum.c: Remove unused #include - - transient_heap.h is no longer needed. - -commit 0d2aa6fec952e78739e7f379df5a3f7547ce4f27 - Author: Takashi Kokubun - Date: 2019-08-07 22:11:52 +0900 - - Upgrade benchmark-driver version - - as I already started to use --runner=block introduced in v0.14.20 like: - https://github.com/ruby/ruby/pull/2321#issuecomment-518638663 - -commit 330e3f19c32dc6b0c287b7845c796e7e4a3ed575 - Author: Takashi Kokubun - Date: 2019-08-07 21:47:03 +0900 - - Refactor .travis.yml by introducing travis_retry.sh - - Not using official travis_retry.bash, because it's not supporting to - modify backoff seconds. - https://github.com/travis-ci/travis-build/blob/0ad8f1886b2c31994d847e126dc5842b7b3513e3/lib/travis/build/bash/travis_retry.bash - - Not using official `travis_apt_get_update` function because it does not - propagate exit status to be used by retries. - https://github.com/travis-ci/travis-build/blob/0ad8f1886b2c31994d847e126dc5842b7b3513e3/lib/travis/build/bash/travis_apt_get_update.bash - - Co-Authored-By: Nobuyoshi Nakada - -commit e6901cea741931906bacbb7c6afdafa621e50c0b - Author: Nobuyoshi Nakada - Date: 2019-08-07 10:41:12 +0900 - - Fixed deprecation message - -commit 1bf796c69dcc61977a105474d08bbe2a51c88e0e - Author: Nobuyoshi Nakada - Date: 2019-08-07 08:57:22 +0900 - - Fix Date#step test - - The document states that "the limit should be a date object". - -commit a0fe396555b164562f69e08e67b62d9904bcfaaa - Author: Takashi Kokubun - Date: 2019-08-07 09:39:46 +0900 - - Simplify break logic of Travis retries - - Co-Authored-By: Nobuyoshi Nakada - -commit b839721ae7814a6e74de59eb40586a32a398545f - Author: Kazuhiro NISHIYAMA - Date: 2019-08-07 09:03:08 +0900 - - .travis.yml: Use `-eq` instead `=` to compare integers - -commit 8877dbe400d84c1f595cb4aa8a06fc71640a43c0 - Author: Yusuke Endoh - Date: 2019-08-07 03:13:17 +0900 - - ext/ripper/lib/ripper/lexer.rb: Consistently use `Array#push` - - instead of <<. All the other callsites use `push`. - -commit ef8c5161b4422783c8f736a099d97a9c868fe287 - Author: Yusuke Endoh - Date: 2019-08-07 03:12:10 +0900 - - ext/ripper/lib/ripper/lexer.rb: fix a wrong delegation - - The target method name is a typo. - -commit 2d6b92c5f6b6343f34bb363604339f4bd7b951ac - Author: Takashi Kokubun - Date: 2019-08-07 01:26:02 +0900 - - Retry ubuntu-toolchain-r-test apt source setup - - In 614c90fe21cf1d9cf6fb18684187d8c7e2f61de6, I assumed - apt-add-repository has been stable recently, but I saw PR randomly - failed for it today. - - This commit only deals with "ubuntu-toolchain-r-test" and does NOT deal - with `llvm-toolchain-xenial-8` intentionally, because what it does - (mainly curl from build.travis-ci.org) seems to be more reliable than - "ubuntu-toolchain-r-test". Also `&clang-8` jobs are basically - allow_failures and it's less important to be stabilized. - -commit 66a13413eee3c4985e62e87addcdce84fc4540fe - Author: git - Date: 2019-08-07 00:07:06 +0900 - - * 2019-08-07 - -commit e89d9f3debab353d1c5a5162752af8f201d98d49 - Author: Nobuyoshi Nakada - Date: 2019-08-07 00:02:21 +0900 - - Deprecate Float::ROUNDS, which should not be a constant - - [Bug #16044] - -commit 0ed298f382e0fc0f119f4896394aacf3b74f6687 - Author: Nobuyoshi Nakada - Date: 2019-08-06 23:39:14 +0900 - - Refine time_to_r - - * time.c (time_to_r): get rid canonicalize and uncanonicalize - one-denominator rational, by rb_time_unmagnify_to_rational. - -commit a04e3585d3cd1d76c4ec61a39bd4f2bdcd6517a1 - Author: Nobuyoshi Nakada - Date: 2019-08-06 23:00:29 +0900 - - Extracted wmap_live_p - -commit 3e6b9926b70d7df9424cf2a6472ba0cd33e61f48 - Author: git - Date: 2019-08-06 20:59:41 +0900 - - * expand tabs. - -commit b5146e375aca25a15ec46978711cde28e5f761d6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-06 12:56:18 +0900 - - leafify opt_plus - - Inspired by 346aa557b31fe96760e505d30da26eb7a846bac9 - - Closes: https://github.com/ruby/ruby/pull/2321 - -commit 43b52ac0a52807c415e9d24d25954f5055567c5e - Author: aycabta - Date: 2019-08-06 20:28:48 +0900 - - Revert "Don't echo results of assignment expressions" - - This reverts commit 1ee88c51b3c319b74b69540e111e4a1c24833cad. - -commit 1ee88c51b3c319b74b69540e111e4a1c24833cad - Author: Steven Willis - Date: 2019-03-21 03:50:05 +0900 - - Don't echo results of assignment expressions - -commit 842364792f03f99f4347d7dbce2a7bd39d1fcc33 - Author: Charles Oliver Nutter - Date: 2019-07-27 15:18:39 +0900 - - Use host_os from RbConfig to detect host OS. - - RUBY_PLATFORM on JRuby is always "java", so it will not reflect - the host operating system. This regex appears to be the consensus - way to detect Windows based on a search of Ruby code on Github: - - https://github.com/search?q=%2Fmswin%7Cmsys%7Cmingw%7Ccygwin%7Cbccwin%7Cwince%7Cemc%2F&type=Code - -commit d626ca1e98d32b67987adb64637a15adf0c977f0 - Author: aycabta - Date: 2019-07-31 02:13:21 +0900 - - Remove obsolete TODO comment - -commit 81a15d636efafaeebe084dc03dae54264d91b875 - Author: aycabta - Date: 2019-08-01 00:39:30 +0900 - - Update Unicode URL to 12.1.0 - -commit 4daff3a603d1a8b2656e82108e2f7d0abf8103c9 - Author: Nobuyoshi Nakada - Date: 2019-08-06 11:56:37 +0900 - - The value of rb_scan_args_verify is never used - -commit 5cff9968aefe2f407731df705830888d9d61409d - Author: Nobuyoshi Nakada - Date: 2019-08-06 11:52:17 +0900 - - Distinguish bad scan format from no argument variables - -commit 146cf2f444c271cb2d4be9efa04053f4d66d16e6 - Author: Espartaco Palma - Date: 2018-10-14 14:36:57 +0900 - - Removing duplicated assertions on test_array.rb - MINUS method - - Closes: https://github.com/ruby/ruby/pull/1790 - -commit 4f1a00a746b8c47dd32f06b249aad8c4d27cb934 - Author: Justin Collins - Date: 2016-09-11 18:09:43 +0900 - - Improve same directory detection in FileUtils - - Closes: https://github.com/ruby/ruby/pull/1425 - -commit 96cec6b27741cbdeb51ea3acdeba0e813d51035f - Author: Jeremy Evans - Date: 2019-07-15 11:39:57 +0900 - - Document that RubyVM::InstructionSequence methods are implementation and version dependent - - Fixes [Bug #6785] - -commit 2b6441196ef32d93c7898764610a913f54f8bc32 - Author: Jeremy Evans - Date: 2019-08-06 08:10:25 +0900 - - Remove documentation of %m in Syslog - - Fixes [Bug #6726] - -commit 81252c5ccd15295155a8fe30b0b56117ba7c79e7 - Author: Aaron Patterson - Date: 2019-08-06 03:32:42 +0900 - - Let prev EP move again - - The last time we committed this, we were asking the VM to write to the - ep. But VM assertions check if the ENV data is the correct type, which - if it's a T_MOVED pointer it's not the correct type. So the vm - assertions would fail. This time we just directly write to it from the - GC and that bypasses the vm assertion checks. - -commit c9192ef2e8793fd870a4af40f422bc939a135ef9 - Author: git - Date: 2019-08-06 00:56:05 +0900 - - * expand tabs. - -commit 33d7a58ffb193cb2ca200ff5b3c649a72d190d21 - Author: Aaron Patterson - Date: 2019-08-02 05:44:54 +0900 - - add compaction support to weak maps - -commit 255e22a8272cd951a6cf8983b7720546e859d1eb - Author: Takashi Kokubun - Date: 2019-08-06 00:49:41 +0900 - - Use gcc-8 for BASERUBY test - - as it failed https://travis-ci.org/ruby/ruby/jobs/567942969, unlike my - fork CI. - - This just rollbacks a minor change in - 798474deaf10dbea70c02724b5acf4487bbed660. - -commit e80f407ed4eafad4c544d7b2de507a0f4386f0a7 - Author: Takashi Kokubun - Date: 2019-08-06 00:43:46 +0900 - - Give up stabilizing TestProcess on Travis osx - - They have been too unstable. - - Revert "Extend sleep before sending USR1 in TestProcess" - This reverts commit aaf69a8ba866193863a7eafe5c6044844bd71bc3. - - Revert "Extend sleep before sending USR1 in TestProcess" - This reverts commit 076f3fcf11a061394d3d5f8c671512df1e983023. - -commit 48d460d9a6d326f4084dec0fd5d90b1cc4331e78 - Author: git - Date: 2019-08-06 00:34:06 +0900 - - * 2019-08-06 - -commit 614c90fe21cf1d9cf6fb18684187d8c7e2f61de6 - Author: Takashi Kokubun - Date: 2019-08-06 00:01:05 +0900 - - Control Travis apt retries on our own - - because Travis team does not do it for us: - https://github.com/travis-ci/travis-build/pull/1712 - - The retried part has failed often even in one day: - https://travis-ci.org/ruby/ruby/jobs/567802384 - https://travis-ci.org/ruby/ruby/jobs/567802388 - https://travis-ci.org/ruby/ruby/jobs/567695879 - https://travis-ci.org/ruby/ruby/jobs/567666931 - - For doing it easily, this also changes major aliases to - compiler-specific ones, because partially updating `before_install` - logic using `env` key was too hard and we needed to directly write - `before_install` for each package set. As a bonus of it, it may also - skip installing unnecessary packages when just `os: linux` is needed. - - I'll revert this if this patch does not contribute to stabilize CI. - -commit fb9dd6182af1b0c1275d6d579cb53d6dac5eda5c - Author: Nobuyoshi Nakada - Date: 2019-08-05 13:43:22 +0900 - - Use negative-sized array instead of zero-division - -commit 4c15b241f8e83696ae104ad141ba990adf833309 - Author: Nobuyoshi Nakada - Date: 2019-08-05 13:29:53 +0900 - - Unused macro argument `varc` - -commit 86ac51c301e62abb4eb0962e04e587ba8298bf80 - Author: Benoit Daloze - Date: 2019-08-04 21:39:55 +0900 - - [rubygems/rubygems] Use the standard RUBY_ENGINE_VERSION instead of JRUBY_VERSION - - * RUBY_ENGINE and RUBY_ENGINE_VERSION are defined on every modern Ruby. - * There is no such constant as TRUFFLERUBY_VERSION or RBX_VERSION. - - https://github.com/rubygems/rubygems/commit/431d0aefdd - -commit 2ea2108a9fb1460342226f54cbf54ddd79ea1cc2 - Author: Benoit Daloze - Date: 2019-08-04 21:16:42 +0900 - - [rubygems/rubygems] Fix error handling of #with_engine_version - - * If settings constants fail, show that exception instead of getting - another one due to variables being unset and hiding the real cause. - - https://github.com/rubygems/rubygems/commit/f38cd67874 - -commit f9dac1bd54af384e99fecf949cad9df9ceb09f0d - Author: David Rodríguez - Date: 2019-08-01 20:20:58 +0900 - - [rubygems/rubygems] Cleanup after testing `rake package` - - Sometimes it happens to me that my local tests start failing because I - pull some file removals or renames into my local copy, and those are - still present on my last copy of pkg/. In those cases, the test about - `rake package` will fail with something like the following: - - ```` - - Failure: - TestRakePackage#test_builds_ok [/home/deivid/Code/rubygems/test/rubygems/test_rake_package.rb:13]: - Expected `rake package` to work, but got errors: - - ``` - cd pkg/rubygems-update-3.1.0.pre1 - WARNING: See http://guides.rubygems.org/specification-reference/ for help - rake aborted! - Gem::InvalidSpecificationException: ["test/rubygems/test_rake_package.rb"] are not files - - Tasks: TOP => package => gem => pkg/rubygems-update-3.1.0.pre1.gem - (See full trace by running task with --trace) - - ``` - - If you have added or removed files, make sure you run `rake update_manifest` to update the `Manifest.txt` accordingly. - Expected: true - Actual: false - ```` - - So, make sure, package is always built from scratch. - - https://github.com/rubygems/rubygems/commit/4e2cc9eb26 - -commit 42a9e27d845271002e09caf68d977990bd06a867 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-01 18:00:32 +0900 - - [rubygems/rubygems] Use gsub with Hash - - https://github.com/rubygems/rubygems/commit/83eced0b39 - -commit 87bc29fe28654ed6b42e87337806ce40cecbe513 - Author: bronzdoc - Date: 2019-07-31 21:33:40 +0900 - - [rubygems/rubygems] Revert cadb66037d9b58c80fc795f39384d533229a1f73 - - https://github.com/rubygems/rubygems/commit/5c3158d975 - -commit 8eb2921f568f0ebc1a0f61b45297c77516f602b5 - Author: Hiroshi SHIBATA - Date: 2019-07-31 08:54:45 +0900 - - [rubygems/rubygems] Fixed to warn with shadowing outer local variable. - - https://github.com/rubygems/rubygems/commit/b0588a87b1 - -commit 5a8d848849bf96de2d2a26db1d6c0cd0999b2078 - Author: bronzdoc - Date: 2019-07-30 09:39:17 +0900 - - [rubygems/rubygems] Remove FIXME comment - - https://github.com/rubygems/rubygems/commit/5a1d3d618d - -commit 58a478bce4a81e619dcef4436f437453d1a3cd89 - Author: Yusuke Endoh - Date: 2019-08-05 14:37:53 +0900 - - ext/psych/yaml/loader.c: Cast the difference of pointers to int - - instead of casting a pointer to int. - Follow up of 39622232c7542d062f79277a11f6b8b6b6cfd994. - -commit 2403f9ac3af170ce0107a709a9cb510fe0501648 - Author: NAKAMURA Usaku - Date: 2019-08-05 12:52:14 +0900 - - Expand the timeout of `test_pstore_files_are_accessed_as_binary_files` - - Sometimes causes timeout error on mswin CI - -commit 6a265278b56eb3f0bab84fbed0c302f4c5ea8c6d - Author: Nobuyoshi Nakada - Date: 2019-08-05 12:16:03 +0900 - - Check if signaled - -commit dc0c04764fbd65c28337c37f70cbf71c0cadffe1 - Author: Nobuyoshi Nakada - Date: 2019-08-05 11:55:21 +0900 - - Refined assertion messages - -commit 521e25baa42c31cc40e60c1da3a5e8e147255ef9 - Author: Nobuyoshi Nakada - Date: 2019-08-05 11:47:25 +0900 - - Fixed assertion - - The regexp should be expected to match the error message. - -commit 8cfa3d861c393b7f2f35eaf30132edd8423ba59a - Author: Nobuyoshi Nakada - Date: 2019-08-05 10:51:52 +0900 - - Do not expect RSTRING_PTR valid after rb_fstring - -commit 29092d35d33d3a879634e173604edc9d201aa87a - Author: Nobuyoshi Nakada - Date: 2019-08-05 10:47:36 +0900 - - Moved FailDesc to EnvUtil.failure_description - - So EnvUtil does not depends on test/unit. - -commit 548cd6e2b51ee0ed7b59799950681d46a43c6c85 - Author: Takashi Kokubun - Date: 2019-08-05 09:16:12 +0900 - - Drop default leaf definition and obsoleted comments - - leaf is true by default. Other insns are not specifying it explicitly. - Also the comment describing why it was not leaf is outdated. - -commit 6bb3618f281e1cdbb28fe38ee88287da9b1838e8 - Author: Yaw Boakye - Date: 2018-10-12 09:04:46 +0900 - - n+1 to include n in range - - Python's range stop right before n, which means factL never returns the correct result. - - Closes: https://github.com/ruby/ruby/pull/1982 - -commit 253da5b2196ccef2a2bf66ca4e7305118f79198a - Author: git - Date: 2019-08-05 09:00:13 +0900 - - * 2019-08-05 - -commit d6ac5c53d481b109cb684d818b14ff24afb5b4bb - Author: Nobuyoshi Nakada - Date: 2019-08-05 08:55:09 +0900 - - Revert "Always evaluate the expression RUBY_ASSERT_MESG_WHEN just once" - - It caused a significant benchmark fall. Some assertions seem to - use expressions with side-effects which cannot be inlined. - - This reverts commit b452c03a14f943ae25338547bd680fce67399d85. - -commit aaf69a8ba866193863a7eafe5c6044844bd71bc3 - Author: Takashi Kokubun - Date: 2019-08-04 23:41:33 +0900 - - Extend sleep before sending USR1 in TestProcess - - just like 076f3fcf11a061394d3d5f8c671512df1e983023. - - This test also hanged on Travis osx - https://travis-ci.org/ruby/ruby/jobs/567547060 - -commit 164f1ac0e994b3b2937ace5c77192c63a489a962 - Author: Takashi Kokubun - Date: 2019-08-04 23:08:22 +0900 - - Revert "Skip test_race_exception on MJIT for now" - - This reverts commit 7a75baa6e294473f02da512c99f7ef1f76b2d83c. - - Revert "Defer skip to avoid errors on ensure" - - This reverts commit adfc8d6dbadbccef27d6ec78022650840c7604cc. - - because 76e2370f132f83c16c9de39a0a9356579f364527 is hoped to fix the - problem. - -commit 7817a6fa09db7cbe2d79b3b6fc86aa4e7fea6d28 - Author: git - Date: 2019-08-04 22:27:17 +0900 - - * expand tabs. - -commit 76e2370f132f83c16c9de39a0a9356579f364527 - Author: Nobuyoshi Nakada - Date: 2019-08-04 22:19:18 +0900 - - Fix dangling path name from fstring - - * load.c (rb_require_internal): make sure in advance that the path - to be loaded shares a fstring, to get rid of dangling path name. - Fixed up 5931857281ce45c1c277aa86d1588119ab00a955. [Bug #16041] - -commit 346aa557b31fe96760e505d30da26eb7a846bac9 - Author: Takashi Kokubun - Date: 2019-08-04 20:11:00 +0900 - - Make opt_eq and opt_neq insns leaf - - # Benchmark zero? - - ``` - require 'benchmark/ips' - - Numeric.class_eval do - def ruby_zero? - self == 0 - end - end - - Benchmark.ips do |x| - x.report('0.zero?') { 0.ruby_zero? } - x.report('1.zero?') { 1.ruby_zero? } - x.compare! - end - ``` - - ## VM - No significant impact for VM. - - ### before - ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) [x86_64-linux] - - 0.zero?: 21855445.5 i/s - 1.zero?: 21770817.3 i/s - same-ish: difference falls within error - - ### after - ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] - - 1.zero?: 21958912.3 i/s - 0.zero?: 21881625.9 i/s - same-ish: difference falls within error - - ## JIT - The performance improves about 1.23x. - - ### before - ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) +JIT [x86_64-linux] - - 0.zero?: 36343111.6 i/s - 1.zero?: 36295153.3 i/s - same-ish: difference falls within error - - ### after - ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] - - 0.zero?: 44740467.2 i/s - 1.zero?: 44363616.1 i/s - same-ish: difference falls within error - - # Benchmark str == str / str != str - - ``` - # frozen_string_literal: true - require 'benchmark/ips' - - Benchmark.ips do |x| - x.report('a == a') { 'a' == 'a' } - x.report('a == b') { 'a' == 'b' } - x.report('a != a') { 'a' != 'a' } - x.report('a != b') { 'a' != 'b' } - x.compare! - end - ``` - - ## VM - No significant impact for VM. - - ### before - ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) [x86_64-linux] - - a == a: 27286219.0 i/s - a != a: 24892389.5 i/s - 1.10x slower - a == b: 23623635.8 i/s - 1.16x slower - a != b: 21800958.0 i/s - 1.25x slower - - ### after - ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] - - a == a: 27224016.2 i/s - a != a: 24490109.5 i/s - 1.11x slower - a == b: 23391052.4 i/s - 1.16x slower - a != b: 21811321.7 i/s - 1.25x slower - - ## JIT - The performance improves on JIT a little. - - ### before - ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) +JIT [x86_64-linux] - - a == a: 42010674.7 i/s - a != a: 38920311.2 i/s - same-ish: difference falls within error - a == b: 32574262.2 i/s - 1.29x slower - a != b: 32099790.3 i/s - 1.31x slower - - ### after - ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] - - a == a: 46902738.8 i/s - a != a: 43097258.6 i/s - 1.09x slower - a == b: 35822018.4 i/s - 1.31x slower - a != b: 33377257.8 i/s - 1.41x slower - - This is needed towards Bug#15589. - Closes: https://github.com/ruby/ruby/pull/2318 - -commit 39622232c7542d062f79277a11f6b8b6b6cfd994 - Author: Hiroshi SHIBATA - Date: 2019-08-04 20:12:43 +0900 - - Suppress warnings of bundled libyaml. - -commit 2d8c037e97e8120de254006f7d60ec9e42a7b6ae - Author: Sutou Kouhei - Date: 2019-05-26 05:32:41 +0900 - - [ruby/rexml] gemspec: update - - https://github.com/ruby/rexml/commit/404bd99a7c - -commit 310a2a98601168aae8c071749b5cb572b55d5046 - Author: Kouhei Sutou - Date: 2019-05-25 18:28:00 +0900 - - [ruby/rexml] xpath: add missing value conversions for equality and relational expressions - - GitHub: fix #18 - - Reported by Mirko Budszuhn. Thanks!!! - - https://github.com/ruby/rexml/commit/0dca2a2ba0 - -commit 39f275edf7284ef0c0f9b9391038ae9f2c019731 - Author: Kouhei Sutou - Date: 2019-05-25 18:25:37 +0900 - - [ruby/rexml] xpath number: fix a bug that false is converted to NaN - - GitHub: fix #18 - - It must be 0. - - Reported by Mirko Budszuhn. Thanks!!! - - https://github.com/ruby/rexml/commit/b48f3afa3b - -commit 643344dc9460626617c9ce88f07b3ae0fed49150 - Author: Kouhei Sutou - Date: 2019-05-25 17:58:49 +0900 - - [ruby/rexml] xpath local_name: fix a bug that nil is returned for nonexistent case - - It must be an empty string. - - https://github.com/ruby/rexml/commit/81bc7cd4f5 - -commit 5f78b138b10a6732676689f0f8690c1db16c1355 - Author: Kouhei Sutou - Date: 2019-05-25 17:47:41 +0900 - - [ruby/rexml] xpath boolean: implement - - https://github.com/ruby/rexml/commit/feb8ddb1ec - -commit 6ef82943978ea5816a91c32e9ff822c73d1935f9 - Author: Kouhei Sutou - Date: 2019-05-25 17:06:53 +0900 - - [ruby/rexml] xpath: fix a bug for equality or relational expressions - - GitHub: fix #17 - - There is a bug when they are used against node set. They should return - boolean value but they returned node set. - - Reported by Mirko Budszuhn. Thanks!!! - - https://github.com/ruby/rexml/commit/a02bf38440 - -commit c46ba8e9a3b1b6c13232c1af3e9f2efd4a3eec98 - Author: Kouhei Sutou - Date: 2019-05-25 15:54:02 +0900 - - [ruby/rexml] Use PP - - https://github.com/ruby/rexml/commit/185062a4a4 - -commit 54525fbfd4bada3eb39428a83e9c337efcbeb4ce - Author: Kouhei Sutou - Date: 2019-05-25 15:14:05 +0900 - - [ruby/rexml] xpath: add support for changing to debug mode by environment variable - - https://github.com/ruby/rexml/commit/59378a16ea - -commit de55e0a008768b0b7c2ddb8d486f4e5a5e09e2fa - Author: Kouhei Sutou - Date: 2019-05-04 14:02:34 +0900 - - [ruby/rexml] Bump version - - https://github.com/ruby/rexml/commit/54452c103a - -commit f85caf40a69d322bde80a547e4b17568604746ff - Author: ujihisa - Date: 2019-02-21 17:42:08 +0900 - - [ruby/rexml] Message less confusing error to human (#16) - - * Message less confusing error to human - - * Problem: Following error message is not helpful, because you have to reason - that '' actually means it's in the top-level, and the 'div' (not '') is - an end tag - - require "rexml/parsers/lightparser" - REXML::Parsers::LightParser.new('').parse - #=> Missing end tag for '' (got 'div') - - * Solution: add a special case in error handling just to change the error message - - require "rexml/parsers/lightparser" - REXML::Parsers::LightParser.new('').parse - #=> Unexpected top-level end tag (got 'div') - - * Refactor by removing unnecessary `md` check - - * Thanks @a_matsuda to review this at asakusa.rb! - - https://github.com/ruby/rexml/commit/f6528d4477 - -commit 33e4a59b4a051b853bc412cf8badfc26a7cb391a - Author: Kouhei Sutou - Date: 2019-02-10 05:37:28 +0900 - - [ruby/rexml] test: compare with real element - - https://github.com/ruby/rexml/commit/9f2908de2e - -commit ee8985ef0e35183d606af3a7360cd4713069e9b2 - Author: Alyssa Ross - Date: 2019-02-10 05:33:06 +0900 - - [ruby/rexml] Fix crash with nil XPath variables (#13) - - Patch by Alyssa Ross. Thanks!!! - https://github.com/ruby/rexml/commit/2a53c54f58 - -commit 982208c65069423b1bc90dafde7589872c452c21 - Author: FUJI Goro (gfx) - Date: 2019-01-05 22:34:03 +0900 - - [ruby/rexml] use #inspect to print meta-characters in error messages - - https://github.com/ruby/rexml/commit/a124a19b9a - -commit 81354bbd1b2ef5f4660c9255eea1f99b26688efa - Author: Kouhei Sutou - Date: 2019-01-01 06:52:24 +0900 - - [ruby/rexml] Bump version - - https://github.com/ruby/rexml/commit/c0e3f14564 - -commit 0f18bc7fca0668aa2ffeb15106525526e4f018ba - Author: Kouhei Sutou - Date: 2019-01-01 06:32:18 +0900 - - [ruby/rexml] Fix attribute's default namespace behavior - - NOTE: It's a backward incompatible change. If we have any serious - problems with this change, we may revert this change. - - The XML namespace specification says the default namespace doesn't - apply to attribute names but it does in REXML without this change: - - https://www.w3.org/TR/xml-names/#uniqAttrs - - > the default namespace does not apply to attribute names - - REXML reports a parse error for the following XML that is described as - a valid XML in the XML nsmaspace specification without this change: - - - - - - - - If attribute doesn't have prefix, the attribute should return "" for - both #prefix and #namespace. - - https://github.com/ruby/rexml/commit/9e4fd552bc - -commit 9b36f0a787dfb1a2a3875b827b455b5a9a2f2680 - Author: Kouhei Sutou - Date: 2019-01-01 06:02:37 +0900 - - [ruby/rexml] Format - - https://github.com/ruby/rexml/commit/2384586811 - -commit 84c3742466fa78b48902d340345cddd04569b81f - Author: Kouhei Sutou - Date: 2019-01-01 05:39:37 +0900 - - [ruby/rexml] Revert "xpath: remove needless nil check" - - This reverts commit 61b73c1bf8dc64d97fba7f0a8c503c24b11313f5. - - "*:local_name" becomes prefix=nil. - - https://github.com/ruby/rexml/commit/9e7dd4cd4e - -commit 096e766355f36983676883b7cb83a1b5862be49a - Author: Kouhei Sutou - Date: 2019-01-01 05:36:39 +0900 - - [ruby/rexml] xpath: remove needless nil check - - It must not be nil. - - https://github.com/ruby/rexml/commit/61b73c1bf8 - -commit 27c11892c829a249b997f896b29cdf26ac9f38f2 - Author: Kouhei Sutou - Date: 2018-12-31 07:24:25 +0900 - - [ruby/rexml] Add a TODO for Attribute#namespace - - https://github.com/ruby/rexml/commit/70310a06e5 - -commit 3583fa166c52aff1ac6fab310e9133c553efcc4a - Author: Kouhei Sutou - Date: 2018-12-31 07:21:37 +0900 - - [ruby/rexml] xpath: fix a bug that no namespace attribute isn't matched with prefix - - [ruby-list:50733] - - Reported by Yasuhiro KIMURA. Thanks!!! - - https://github.com/ruby/rexml/commit/8f3c5c176a - -commit f76cfb55d7612f1bb1648112e159646321d2aa2c - Author: Kouhei Sutou - Date: 2018-12-25 11:20:27 +0900 - - [ruby/rexml] Bump version - - https://github.com/ruby/rexml/commit/0f79e71210 - -commit adfc8d6dbadbccef27d6ec78022650840c7604cc - Author: Takashi Kokubun - Date: 2019-08-04 11:05:50 +0900 - - Defer skip to avoid errors on ensure - -commit 7a75baa6e294473f02da512c99f7ef1f76b2d83c - Author: Takashi Kokubun - Date: 2019-08-04 10:49:03 +0900 - - Skip test_race_exception on MJIT for now - - somehow the test fails only on Wercker in CIs triggered by GitHub. - Actually rubyci and ci.rvm.jp also have issues too, though. - -commit a3188f43a812a8c3954391af66ed54352423ef60 - Author: Takashi Kokubun - Date: 2019-08-04 10:08:17 +0900 - - Revert "Revert "Fix dangling path name from fstring"" - - This reverts commit 326c00b6f89e1c86e6fe29ab60da593eb6883a88. - - We also confirmed that test_gced_eval_location fails without the changes: - https://travis-ci.org/ruby/ruby/builds/567417818 - https://rubyci.org/logs/rubyci.s3.amazonaws.com/arch/ruby-master/log/20190804T000003Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu1604/ruby-master/log/20190804T003005Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20190804T000007Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10x/ruby-master/log/20190804T001806Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian9/ruby-master/log/20190804T003005Z.fail.html.gz - -commit 2d189a6721c5e88973a53e385c0fb9eeb55fece9 - Author: David Carlier - Date: 2019-07-10 06:08:31 +0900 - - yaml few build warning fixes - - Closes: https://github.com/ruby/ruby/pull/2283 - -commit b6cfacc85d7607a86cb22e1f8eb00b82860014fe - Author: Dmitry Petrashko - Date: 2019-05-30 06:16:06 +0900 - - Remove dependency on `openssl/conf_api.h` - - None of the functions defined in this header are actually used in Ruby. - Fixes build against boringssl that does not have this file. - Closes: https://github.com/ruby/ruby/pull/2210 - -commit 0f601df22c258c568f0c6f8263903eafa14ae238 - Author: Kenichi Kamiya - Date: 2019-06-24 17:03:49 +0900 - - [Doc] Fix Array#to_h call-seq - - Closes: https://github.com/ruby/ruby/pull/2254 - -commit 84829392f5bb094b2cac117a67d37307ecc3640b - Author: Kenichi Kamiya - Date: 2019-06-24 17:33:30 +0900 - - [Doc] Fix Array#difference call-seq - - Closes: https://github.com/ruby/ruby/pull/2255 - -commit 4173258fd0413c49ef07d54bc9654bba7e497e89 - Author: Semyon Pupkov - Date: 2017-11-13 18:48:29 +0900 - - change call CGI methods from :: to . - - Closes: https://github.com/ruby/ruby/pull/1749 - -commit 8e7df4bbf991b9d605784225db0750bbfe681f23 - Author: Olivier Lacan - Date: 2019-03-20 02:46:27 +0900 - - Use the word heredocs in Here Documents docs - - Two advantages: - - higher relevance of the extremely common word "heredocs" which may - help people find this page when searching for "ruby heredocs" - - the anchor link becomes `#label-Here+Documents+-28heredocs-29`, which is - ugly due to the parentheses but includes the word "heredocs" in the URL to - this section - - If anyone knows a way to prevent RDoc from turning invalid characters into - ugly and meaningless ASCII codes, I'm listening. I don't want to break existing - anchor links but RDoc should really ignore these characters or turn them into - dashes. - - Closes: https://github.com/ruby/ruby/pull/2103 - -commit 93116569145bbff34355e08722c6689487d8b858 - Author: Lars Kanis - Date: 2017-05-12 03:40:57 +0900 - - Better wording for __ENCODING__ - - "locale encoding" is misleading since it doesn't mean Encoding.find("locale") - but the encoding used to interpret the script file. It's therefore better to - call it "script encoding" as in the paragraphs above. - Closes: https://github.com/ruby/ruby/pull/1611 - -commit 636a4fad1617699350ec70d5523a92e8148d5c35 - Author: Will Binns - Date: 2019-06-14 13:18:01 +0900 - - README: Add smart URL for joining mailing list - - This adds a couple of parameters to the mailing list link in the README - so that the subject line and body are automatically populated. The body - is populated with the `subscribe` string so that all an individual has - to do is perform the send action in their mail client. - - Closes: https://github.com/ruby/ruby/pull/2236 - -commit 7614cc5b241144bc47e8062e335fcf15dbf04e51 - Author: Marcus Stollsteimer - Date: 2019-04-21 22:38:10 +0900 - - Fix release post output for tool/format-release - - Different entries should be separated by an empty line. - - Closes: https://github.com/ruby/ruby/pull/2137 - -commit 326c00b6f89e1c86e6fe29ab60da593eb6883a88 - Author: Takashi Kokubun - Date: 2019-08-04 08:38:37 +0900 - - Revert "Fix dangling path name from fstring" - - This reverts commit 5931857281ce45c1c277aa86d1588119ab00a955 temporarily, - leaving `TestEval#test_gced_eval_location` to see the impact for missing - the changes. - - That's because too many CIs are failing for `require` behaviors: - http://rubyci.s3.amazonaws.com/freebsd11zfs/ruby-master/log/20190803T063004Z.fail.html.gz - http://rubyci.s3.amazonaws.com/unstable10x/ruby-master/log/20190803T051806Z.fail.html.gz - http://rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20190803T052406Z.fail.html.gz - http://rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190803T111909Z.fail.html.gz - http://rubyci.s3.amazonaws.com/unstable11s/ruby-master/log/20190803T062506Z.fail.html.gz - http://rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20190803T052505Z.fail.html.gz - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5d4512c921ca08000857936a?step=5d451305c2809c0008a3da76 - https://app.wercker.com/ruby/ruby/runs/mjit-test2/5d4512c921ca080008579371?step=5d4513000421020007ca122d - http://ci.rvm.jp/results/trunk_gcc4@silicon-docker/2177591 - http://ci.rvm.jp/results/trunk_gcc6@silicon-docker/2177596 - http://ci.rvm.jp/results/trunk_clang_60@silicon-docker/2178802 - http://ci.rvm.jp/results/trunk-theap-asserts@silicon-docker/2177555 - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2178747 - - Mostly `TestRequire#test_race_exception` failures, but in ci.rvm.jp - `require` inside rubyspec hangs very often. - -commit 7adc8c79eaf40521a290ecdc7aa0a8490a95f87a - Author: Nobuyoshi Nakada - Date: 2019-08-04 08:15:05 +0900 - - [DOC] "nmake check" is preferable to "nmake exam" now [ci skip] - - [Feature #14187] - -commit 9b38c845508a4184882580abb3b6cc4fcd1dd57f - Author: Nobuyoshi Nakada - Date: 2019-08-04 08:07:06 +0900 - - [DOC] updated about icons in win32/README.win32 [ci skip] - - [Bug #13348] - -commit 586e23c97de57d0d1779b957806d4188364df727 - Author: git - Date: 2019-08-04 07:15:25 +0900 - - * 2019-08-04 - -commit 9733b47eb80699e04a28dfee6fae727bfb27bc41 - Author: Nobuyoshi Nakada - Date: 2019-08-04 07:13:31 +0900 - - [DOC] "nmake check" is preferable to "nmake exam" now [ci skip] - - [Feature #14187] - -commit 6a1458caf2e4d15215e094cc4863e3a6f2648f6b - Author: Nobuyoshi Nakada - Date: 2019-08-04 07:12:16 +0900 - - [DOC] Mark up path names to show a backslash [ci skip] - -commit d569d721f978d2e0b5b331b3c3aa69c89f94d70b - Author: Hiroshi SHIBATA - Date: 2019-08-03 22:17:45 +0900 - - Move assert_ruby_status and assert_throw to CoreAssertions for default gems. - -commit 954223ebd4229d4ca18ee5b78249c4330473910e - Author: Nobuyoshi Nakada - Date: 2019-08-03 14:56:41 +0900 - - [DOC] mentioned minimum versions of tools [ci skip] - -commit 6623cde731c7624e26e0e1e1e51eada911783629 - Author: Nobuyoshi Nakada - Date: 2019-08-03 14:56:07 +0900 - - Added more attributes [ci skip] - -commit 4d75346187557ae59736ca5739bfae312c285e08 - Author: Nobuyoshi Nakada - Date: 2019-08-03 14:20:36 +0900 - - Refine error message - - Highlight failed command and suggest installing the command. - [Bug #16042] - -commit ec0d742dd744b13e89d82ffc88d193f165942acf - Author: Nobuyoshi Nakada - Date: 2019-08-03 14:06:56 +0900 - - Suppress warnings against locations in eval - -commit cee394eb228efa4160501ef02a1cd6a696909972 - Author: git - Date: 2019-08-03 13:51:23 +0900 - - * expand tabs. - -commit 5931857281ce45c1c277aa86d1588119ab00a955 - Author: Nobuyoshi Nakada - Date: 2019-08-03 13:41:55 +0900 - - Fix dangling path name from fstring - - * parse.y (yycompile): make sure in advance that the `__FILE__` - object shares a fstring, to get rid of dangling path name. - Fixed up 53e9908d8afc7f03109b0aafd1698ab35f512b05. [Bug #16041] - - * vm_eval.c (eval_make_iseq): ditto. - -commit 688a59f8ac984a2f1d4d53005dbe0679dcd59ac3 - Author: Nobuyoshi Nakada - Date: 2019-08-03 11:31:40 +0900 - - Show the location of `eval` which uses `__FILE__`/`__LINE__` - -commit fb96bea7ed8ed6765fda2a1db90a2cfce14e59b7 - Author: git - Date: 2019-08-03 10:25:20 +0900 - - * expand tabs. - -commit 4ea5c5610aeadecf78fdd2b7d6faad8574953620 - Author: Nobuyoshi Nakada - Date: 2019-08-03 08:37:08 +0900 - - Predefine some IDs - -commit 0bd1cd677f769ac6128989bf1d021753698fdaac - Author: Hiroshi SHIBATA - Date: 2019-08-01 09:46:32 +0900 - - [bundler/bundler] Remove Bundler.rubygems.config_map because it was deprecated. - - https://github.com/bundler/bundler/commit/5215ae7fa3 - -commit b3b2b55f7b7ab035851176d28ecee4afaa3fe0cc - Author: Hiroshi SHIBATA - Date: 2019-08-01 09:44:46 +0900 - - [bundler/bundler] The keys for RbConfig::CONFIG was String. - - https://github.com/bundler/bundler/commit/ffc5e76335 - -commit aad7443e168880e382680d4c0be1757840b23c18 - Author: Adam Wanninger - Date: 2019-07-09 07:43:42 +0900 - - [bundler/bundler] Point to CoC which contains the contributor covenant - - https://github.com/bundler/bundler/commit/a94f74682e - -commit 220f6aa01c4b2552af0bdcbbc46518c1118ee91f - Author: Hiroshi SHIBATA - Date: 2019-08-03 07:23:58 +0900 - - Explicitly ignored GEMRC environmental variable. - -commit 4c72ca195d17fdbcb656e67c1c6ee7f591d306f2 - Author: Hiroshi SHIBATA - Date: 2019-08-03 07:09:59 +0900 - - Fixed up 365ee22d73ec73c119a842de271504e04bed6f45 - -commit 01d141938cfdc8cb0d370c659d976af7ed9623ae - Author: Hiroshi SHIBATA - Date: 2019-08-03 06:29:36 +0900 - - Fixed the broken example with ruby core structure. - -commit 7ed1fc527e029f47c4ed17136fb1492c9fbdfdc9 - Author: David Rodríguez - Date: 2019-08-01 06:56:05 +0900 - - [bundler/bundler] Bump rubocop to 0.74.0 - - And re-enable exclusion because the bug why we added them has been fixed. - See https://github.com/rubocop-hq/rubocop/issues/6861. - - https://github.com/bundler/bundler/commit/bda63fcffc - -commit dab944e6ca9ed92ce72d1db4834b32e924d87015 - Author: David Rodríguez - Date: 2019-07-25 15:45:39 +0900 - - [bundler/bundler] net-http-persistent 3.1.0 has been released - - https://github.com/bundler/bundler/commit/ffb7d6fa53 - -commit fcb58f65b1ff6204845b47ac810c32ee7a1aafe2 - Author: David Rodríguez - Date: 2019-06-26 17:42:44 +0900 - - [bundler/bundler] Adapt to the way my automatiek patch works - - https://github.com/bundler/bundler/commit/b8ee4aec0b - -commit 1e63683795bf782db745dbad7889b2779f0573a5 - Author: David Rodríguez - Date: 2019-06-25 23:55:35 +0900 - - [bundler/bundler] Bump automatiek to 0.2.0 - - https://github.com/bundler/bundler/commit/cd1abf8b3f - -commit 97f3ceeaa5c66ad6a6a5f3f37339c4b1cbe71677 - Author: David Rodríguez - Date: 2019-06-11 19:48:34 +0900 - - [bundler/bundler] Bump net-http-persistent to 3.0.1 - - * Adds an extra artifice task to vendorize new `connection_pool` - dependency. - - * Cherry-pick's needed Windows fix not yet merged into master branch of - `net-http-persistent`. - - * Update bundler usages to be compatible with the new version, and fix - unit specs. - - https://github.com/bundler/bundler/commit/0575baa6bb - -commit 2b7e39f364d76c74af6e04aa3d96888a6aeef1cd - Author: David Rodríguez - Date: 2019-07-24 00:32:33 +0900 - - [bundler/bundler] Always set `cache_all` via config during tests - - So that the behavior is the same regardless of the tested bundler - version. - - https://github.com/bundler/bundler/commit/664549427a - -commit 267a72be800da0ec47f441d7d8210dc6aec137af - Author: David Rodríguez - Date: 2019-07-24 02:19:31 +0900 - - [bundler/bundler] Enable `Style/UnneededInterpolation` cop - - https://github.com/bundler/bundler/commit/4c6a3c3cf7 - -commit e84e63230bd024b652451cb7d1a44b9d9e0449ae - Author: David Rodríguez - Date: 2019-03-29 00:46:13 +0900 - - [bundler/bundler] Check for straneous quotes - - And use single quotes consistently. - - https://github.com/bundler/bundler/commit/8b9fbbb2df - -commit 4dea1356c3ea97e9d0e98b1fbca69b01a6df2647 - Author: Samuel Giddins - Date: 2018-11-25 22:25:17 +0900 - - [bundler/bundler] [CurrentRuby] Say we are ruby? when the generic local platform is Gem::Platform::RUBY - - This allows us to always say we're ruby? when force_ruby_platform is - set, and fixes using gemspec & force_ruby_platform on windows. - - https://github.com/bundler/bundler/commit/3cb89b7e5c - -commit 6fb73e6043015fcd999a2c4b9a52b9bb1d9c4173 - Author: David Rodríguez - Date: 2019-03-22 00:32:35 +0900 - - [bundler/bundler] Fully remove compatibility guard - - https://github.com/bundler/bundler/commit/2a7a5daba0 - -commit 452516f50f80e3bbb6dc9911dcdb133a2e16c170 - Author: David Rodríguez - Date: 2019-07-08 22:32:18 +0900 - - [bundler/bundler] Remove development dependencies from gemspec - - And refactor development setup. - - https://github.com/bundler/bundler/commit/f288806d02 - -commit 7255f55dba83aacbde76184aff965162e339ba2a - Author: David Rodríguez - Date: 2019-04-13 02:05:26 +0900 - - [bundler/bundler] RUBY_ENGINE should always be defined after 1.8.7 - - https://github.com/bundler/bundler/commit/d6c9196d18 - -commit d2d6d5c988b66cb110dbb07f92e08f231a31d6bc - Author: Scott Tesler - Date: 2019-07-30 05:15:37 +0900 - - [bundler/bundler] Fix typo in binstubs documentation - https://github.com/bundler/bundler/commit/88dbfa18b4 - -commit 56229c4e5d9856abdd39a51a5875a7d4d0076ce0 - Author: David Rodríguez - Date: 2019-07-26 18:39:41 +0900 - - [bundler/bundler] Fix `git` options examples - - https://github.com/bundler/bundler/commit/bda0fa02c4 - -commit 6015bbeeaf897c75065d0b18e119e2614e1d1f44 - Author: David Rodríguez - Date: 2019-07-25 17:43:36 +0900 - - [bundler/bundler] Fix incorrect sectioning in `gemfile` man page - - https://github.com/bundler/bundler/commit/428f53bef0 - -commit d4b1804b11310a3c2303367dcd4ec73aae419ee1 - Author: Hiroshi SHIBATA - Date: 2019-07-19 17:23:42 +0900 - - [bundler/bundler] Removed the environmental variables that are BUNDLE_USER_*. - - It's affect with rspec examples and broke them. - - https://github.com/bundler/bundler/commit/355a922073 - -commit b855e33b655d9c0cfa07aab8e8622d68f0402ea0 - Author: David Rodríguez - Date: 2019-07-24 20:00:46 +0900 - - [bundler/bundler] Add exclamation mark to method - - To indicate that it can raise. - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/584e841624 - -commit 1fbd6a1fe0e298aef006cf1aa41e6e6f1ce7c7c5 - Author: David Rodríguez - Date: 2019-07-24 20:00:30 +0900 - - [bundler/bundler] Move `strict` to an attribute - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/7b68d86bdd - -commit 1069139a339a6a7d0d6169c634e572659f749ea9 - Author: David Rodríguez - Date: 2019-07-24 23:09:35 +0900 - - [bundler/bundler] Extract some methods - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/027aba0cff - -commit ee7ec87007862118cdf13815808999e73b9b98d3 - Author: David Rodríguez - Date: 2019-07-24 23:03:46 +0900 - - [bundler/bundler] Unfold message to single line for readability - - https://github.com/bundler/bundler/commit/d845a213ca - -commit e1ccaa8782fa722b842ba59c955a212697afde9c - Author: Guillermo Guerrero - Date: 2019-04-13 01:59:35 +0900 - - [bundler/bundler] Extract a `print_gems` method - - https://github.com/bundler/bundler/commit/0d8c8d207e - -commit 759930dd11aedfd563d11bdef4b0a562b0f00ad9 - Author: Guillermo Guerrero - Date: 2019-04-13 01:52:52 +0900 - - [bundler/bundler] Less complexity - - https://github.com/bundler/bundler/commit/be9d6e7cfc - -commit fd3411c73f35e3e8c0e1cd72eea434ca6e8d1744 - Author: David Rodríguez - Date: 2019-07-24 20:38:47 +0900 - - [bundler/bundler] Move more locals to attributes - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/4335df3e4c - -commit a42478502c923978a0cf14e7e00efbc0149b07a9 - Author: David Rodríguez - Date: 2019-07-24 20:34:52 +0900 - - [bundler/bundler] Move `any?` logic to the attribute - - It's the only usage of the `options_include_groups` attribute and its - name suggests a boolean, so it fits better now. - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/53c0fae760 - -commit 4e76aef280f8440a9e499a05a2d74e6f2ba7cdd6 - Author: David Rodríguez - Date: 2019-07-24 20:30:56 +0900 - - [bundler/bundler] Move `options_include_groups` to an attribute - - Co-authored-by: Guillermo Guerrero - Co-authored-by: David Rodríguez - - https://github.com/bundler/bundler/commit/832fb900f0 - -commit e33dd659d43ec2302648c04fcec208b1c0f98ed9 - Author: Guillermo Guerrero - Date: 2019-04-13 01:32:42 +0900 - - [bundler/bundler] Move duplicated code to `before` blocks - - https://github.com/bundler/bundler/commit/69bee117fb - -commit c4a2a9a38165e6a4b54798d5d8edb6297275efaa - Author: David Rodríguez - Date: 2019-07-24 00:33:27 +0900 - - [bundler/bundler] Remove now unused logic - - https://github.com/bundler/bundler/commit/5b285685a4 - -commit 322d4fe98dd5db50ed4088dc9966dfc8813d6672 - Author: David Rodríguez - Date: 2019-07-24 02:03:19 +0900 - - [bundler/bundler] Remove unnecessary indirections - - These specs are only run on bundler 2, so the compatibility method is - not needed. - - https://github.com/bundler/bundler/commit/6cb28e3aeb - -commit 30d10be036c2f57f6ba4d605f73c2ab9a07075b8 - Author: David Rodríguez - Date: 2019-07-23 23:23:45 +0900 - - [bundler/bundler] Prefer feature flag to hardcoded check - - https://github.com/bundler/bundler/commit/8c83921d08 - -commit 76d205c84041d8d186b632ec5f8f479be4e730aa - Author: David Rodríguez - Date: 2019-07-23 23:23:26 +0900 - - [bundler/bundler] Restore `cache_all` flag removal - - https://github.com/bundler/bundler/commit/04a04719f0 - -commit 640dbdd155625cfbd30c3a00c702dd04ec66c8bc - Author: David Rodríguez - Date: 2019-07-24 02:48:20 +0900 - - [bundler/bundler] Better info about spec exclusions - - https://github.com/bundler/bundler/commit/1ee77d9c55 - -commit 51aaed128a7949fffdc5847ee1949e4b2acc86ff - Author: David Rodríguez - Date: 2019-07-23 20:56:01 +0900 - - [bundler/bundler] Skip specs using `Process.fork` on Windows - - https://github.com/bundler/bundler/commit/ebcb25a3c3 - -commit d7487d6c0845f89b0d640d1e22a4a10d1ffdb1a3 - Author: David Rodríguez - Date: 2019-07-23 20:11:33 +0900 - - [bundler/bundler] Try make some specs platform independent - - https://github.com/bundler/bundler/commit/b5900e57a4 - -commit 9d82962af3bc1c308ae0c2530b9fb162da825da2 - Author: David Rodríguez - Date: 2019-07-23 20:01:33 +0900 - - [bundler/bundler] Check for generic lockfiles - - https://github.com/bundler/bundler/commit/344a881592 - -commit bb50f87b69049d80117d40e194e91cb650a94f64 - Author: David Rodríguez - Date: 2019-07-23 22:25:28 +0900 - - [bundler/bundler] Add workaround from old rubygems - - In these versions, the `approximate_recommendation` method doesn't - include the prerelease logic. - - https://github.com/bundler/bundler/commit/caf13e9e4f - -commit cb6abf551ab091760ec2c834ff3718f83efd5426 - Author: David Rodríguez - Date: 2019-07-16 20:34:57 +0900 - - [bundler/bundler] Update error messages to be more precise - - https://github.com/bundler/bundler/commit/9ddeeb1fe1 - -commit f40914e3cf99181ccf69987fa8edded175a1019c - Author: David Rodríguez - Date: 2019-07-16 18:50:56 +0900 - - [bundler/bundler] Remove unnecessary method parameter - - https://github.com/bundler/bundler/commit/72194d1aac - -commit a1c69991a5c618b4002a6222fca8cfe1f4718879 - Author: David Rodríguez - Date: 2019-07-16 18:52:14 +0900 - - [bundler/bundler] Use a consistent requirement in binstub - - https://github.com/bundler/bundler/commit/50ccdb32c2 - -commit bb6b9b49293378cb48510e27a98db152824658cd - Author: David Rodríguez - Date: 2019-07-16 19:42:39 +0900 - - [bundler/bundler] Remove redundant begin-end block - - https://github.com/bundler/bundler/commit/1d017c3f36 - -commit bd0f19f137a952f5f8b838537f473385b204ed78 - Author: David Rodríguez - Date: 2019-07-16 18:31:38 +0900 - - [bundler/bundler] Don't need 1.8 compatibility - - https://github.com/bundler/bundler/commit/7ca4d4e83c - -commit 3e10b4a0be0de22fc0871a6fab65139c43c69180 - Author: David Rodríguez - Date: 2019-07-23 20:01:13 +0900 - - [bundler/bundler] Indentation fixes - - https://github.com/bundler/bundler/commit/2a44090cb6 - -commit 3e83fbddfacafd1467bfcae818d595c6e29fca5c - Author: David Rodríguez - Date: 2019-07-23 15:16:17 +0900 - - [bundler/bundler] Add a comment to explain the initial reset - - https://github.com/bundler/bundler/commit/6d0a8f4128 - -commit 55831647fbea0005449f714eec7672fab50cf9d3 - Author: David Rodríguez - Date: 2019-07-23 15:14:02 +0900 - - [bundler/bundler] Move environment reset to the only test needing it - - https://github.com/bundler/bundler/commit/6d3b809695 - -commit 679472454832f4e9b5c72f282b2933c44ef35ffa - Author: David Rodríguez - Date: 2019-07-23 15:15:29 +0900 - - [bundler/bundler] Remove unneeded bundler key - - It sounds like this was mistankenly added in - 4337a499d0108fc3748084934aaed7591b355a26. Then the forgotten MANPATH key - was added in bf5bf106230772934602768bb31a68dc925691f0, but this one - should've been removed I think. - - https://github.com/bundler/bundler/commit/a82ad111e5 - -commit 1b081cdd650964708c700a8051d37bf70e1a3880 - Author: David Rodríguez - Date: 2019-07-23 15:15:15 +0900 - - [bundler/bundler] Improve test to make it more independent from env - - https://github.com/bundler/bundler/commit/038f0d7c37 - -commit 26f651796c06c232b9887d2401f5e998d6dc654f - Author: David Rodríguez - Date: 2019-07-23 01:21:59 +0900 - - [bundler/bundler] Remove unnecessary assignments - - https://github.com/bundler/bundler/commit/3e5d4b2c42 - -commit d6a2e082e647258400d0a9f75ebbd167aaa44848 - Author: MSP-Greg - Date: 2019-07-21 11:59:43 +0900 - - [bundler/bundler] spec/bundler/shared_helpers_spec.rb - fixup after 7248 - - PR 7248 incorrectly changed a path calculation. This reverts. - - After running Azure Pipelines CI in my ruby/ruby fork and checking the 'bundler' jobs, the error was apparent... - - https://github.com/bundler/bundler/commit/811755b413 - -commit 432285c0040d547c24294611725edddb78560ac2 - Author: MSP-Greg - Date: 2019-07-13 22:20:12 +0900 - - [bundler/bundler] fix nested bundle exec's when bundler is a default gem - - https://github.com/bundler/bundler/commit/537c0ab712 - -commit 24062bd323ec9c5311bbf2c5f8f2822f15a38c62 - Author: MSP-Greg - Date: 2019-07-17 01:39:24 +0900 - - [bundler/bundler] build_metadata.rb - fix 'warning: instance variable @git_commit_sha not initialized' - - https://github.com/bundler/bundler/commit/37a1eec8c8 - -commit 7b7caf9b556aa026c732403d7b18910ebc070123 - Author: MSP-Greg - Date: 2019-07-16 08:00:22 +0900 - - [bundler/bundler] dsl_spec.rb - fix for Ruby core - - https://github.com/bundler/bundler/commit/33892e1ed2 - -commit a1549fba833d99590c128444ff5c4ac910b15870 - Author: David Rodríguez - Date: 2019-07-16 03:48:05 +0900 - - [bundler/bundler] Alias `cache` to `package` now - - The additions of the `package` command are not actually backwards - incompatible, so we can do this transition without further care. All - existing specs of `bundle cache` pass when using the `bundle package` - implementation for it. - - https://github.com/bundler/bundler/commit/69497adf90 - -commit 4f5e1b6ebf4a122fe935c55224ce8e9937288582 - Author: David Rodríguez - Date: 2019-07-16 02:17:11 +0900 - - [bundler/bundler] Remove `cache_command_is_package` feature flag - - So that we handle the removal of `bundle cache` just like we'll handle - the removal of `bundle show` and `bundle console`. - - https://github.com/bundler/bundler/commit/ff1a669efb - -commit f73020d493ec2bf7c79fc118f83f328caee701d7 - Author: David Rodríguez - Date: 2019-07-16 02:31:51 +0900 - - [bundler/bundler] Always keep `bundle package --all` option - - Just change the default. The reason to do this is that the deprecation - message talks about the default being changed, not the option being - removed. - - https://github.com/bundler/bundler/commit/eca1757792 - -commit 33ce42dd5dd10cb86258e78010563f86f412ce01 - Author: David Rodríguez - Date: 2019-07-16 02:31:10 +0900 - - [bundler/bundler] Fix incorrect flag usage - - https://github.com/bundler/bundler/commit/4df9edef95 - -commit ad3cba02cfa9140e2318632e6cc40dad4e79f959 - Author: David Rodríguez - Date: 2019-03-30 19:21:54 +0900 - - [bundler/bundler] Remove redundant condition - - This is inside a code branch where the condition is already met. - - https://github.com/bundler/bundler/commit/8cdd6c37e6 - -commit 31541d738924e714e9b580b33eb44608ea248486 - Author: David Rodríguez - Date: 2019-07-11 18:33:03 +0900 - - [bundler/bundler] Drop rubygems 2.5.0 and 2.5.1 support - - https://github.com/bundler/bundler/commit/8ecd722b9f - -commit fc42423b8df652e3f75436200e5bdfbacd167959 - Author: David Rodríguez - Date: 2019-07-11 18:32:03 +0900 - - [bundler/bundler] Correct a rubygems test filter - - It seems to pass under rubygems 2.5.2. - - https://github.com/bundler/bundler/commit/062cd2be7c - -commit f5cd02f362142dcb3211e2e820b414c0eb2b4e2c - Author: David Rodríguez - Date: 2019-07-11 18:31:19 +0900 - - [bundler/bundler] Remove unnecessary test filter - - Since it covers the whole range we support. - - https://github.com/bundler/bundler/commit/c0b9d4e6c6 - -commit a6ce001babc5728cd3c29df91ef29e0e57d4f012 - Author: David Rodríguez - Date: 2019-07-11 18:02:49 +0900 - - [bundler/bundler] Change the refresh spec to not use `stubs_for` - - We plan to incrementally populate this array in rubygems, so that will - break the test because the first time `find_by_name("rack")` is called - will make the `rack` gem available in the array. - - We can test the same thing using some other way, which is more - appropriate anyways, because `Bundler.rubygems.find_name` is only used - inside `bundler` to look for the `bundler` gem itself whereas - `Bundler.rubygems.all_specs` is used in more places. - - https://github.com/bundler/bundler/commit/49c519ef47 - -commit a181df75429a3c3db2eef387f7476b18c3893615 - Author: David Rodríguez - Date: 2019-07-11 18:02:35 +0900 - - [bundler/bundler] No need to make `Gem.refresh` a noop - - The rubygems integration sets up a `post_reset` hook that resets the - specs back to what bundler knows after `Gem::Specification.reset` is - called (which is what `Gem.refresh` calls under the hood). - - https://github.com/bundler/bundler/commit/3810f9945c - -commit f399a2b7964dac890fd08bd78b62fbe8313319ea - Author: David Rodríguez - Date: 2019-03-29 00:45:31 +0900 - - [bundler/bundler] Remove unnecessary line - - It contains a typo, so it can't be needed. - - https://github.com/bundler/bundler/commit/ef38c97fbf - -commit 56fd027aa6cecaa6910ec6b96270299937f124c8 - Author: David Rodríguez - Date: 2019-03-29 00:41:43 +0900 - - [bundler/bundler] Tweak some quality specs to check more files - - https://github.com/bundler/bundler/commit/98023e25de - -commit 812dfa44f0b35b6ee6446417e0e72f04270bdf85 - Author: David Rodríguez - Date: 2019-06-27 20:01:30 +0900 - - [bundler/bundler] Refactor setting the encoding in quality specs - - Instead of setting the encoding globally, set it when reading the files. - - https://github.com/bundler/bundler/commit/e2a5c45e4d - -commit 6cbe818c668c07c0700b1281d629b92a9101c976 - Author: David Rodríguez - Date: 2018-12-07 02:05:01 +0900 - - [bundler/bundler] This seems to pass for me - - https://github.com/bundler/bundler/commit/e31880b1ea - -commit d0c19d1f87afeb9459644f2b348354d19f3285c3 - Author: David Rodríguez - Date: 2019-07-06 00:26:02 +0900 - - [bundler/bundler] Use `tap` for `current_platforms` - - https://github.com/bundler/bundler/commit/78608acf83 - -commit 6e0dc5594ced353aabdb3f118667ca987720e624 - Author: David Rodríguez - Date: 2019-06-20 01:44:44 +0900 - - [bundler/bundler] Remove now unused method - - https://github.com/bundler/bundler/commit/3a2d2f0250 - -commit 6492f23d919589745fc90fd151b1ce7f5478d776 - Author: David Rodríguez - Date: 2019-06-20 00:03:58 +0900 - - [bundler/bundler] Remove now meaningless setting - - https://github.com/bundler/bundler/commit/52c5a0eede - -commit dae6d303d5aa13eeeb482398eb748b3a8f4edcfa - Author: David Rodríguez - Date: 2019-06-20 00:02:55 +0900 - - [bundler/bundler] Remove now meaningless warning - - https://github.com/bundler/bundler/commit/00b095b98f - -commit c1ca77281d60e5b81dd4ba0df36f7ea6abf3f92a - Author: David Rodríguez - Date: 2019-06-20 00:01:36 +0900 - - [bundler/bundler] Add all platforms to lockfile by default - - https://github.com/bundler/bundler/commit/3dc509e645 - -commit d8cd45cb1a459f8e82f055d8c2d335f57962dc31 - Author: David Rodríguez - Date: 2019-06-19 22:49:39 +0900 - - [bundler/bundler] Refactor some specs - - https://github.com/bundler/bundler/commit/785c7af1f3 - -commit ff908983be80f718497e32e60d24ac9b820df52c - Author: David Rodríguez - Date: 2019-06-19 22:31:40 +0900 - - [bundler/bundler] Extract `expanded_platforms` - - https://github.com/bundler/bundler/commit/60d720eb06 - -commit 3af9d8bb671cfdc474110af3f2db24e36954d38d - Author: David Rodríguez - Date: 2019-06-19 22:29:02 +0900 - - [bundler/bundler] Extract `current_platforms` - - https://github.com/bundler/bundler/commit/9f07207d64 - -commit ead2dc0ec998ef0453f99e24971a1d598f7522fe - Author: Samuel Giddins - Date: 2018-11-25 22:23:55 +0900 - - [bundler/bundler] [GemHelpers] Remove the special code path for ruby platform being its own generic - - https://github.com/bundler/bundler/commit/3b9abc8932 - -commit cef81eb8ccb38deaf5d0bd3c5d6c5fdbcc920d38 - Author: David Rodríguez - Date: 2019-06-25 23:50:20 +0900 - - [bundler/bundler] Make some specs more explicit - - https://github.com/bundler/bundler/commit/5e08e849ec - -commit b2baf6bb0223bb52f9e5f861f860c61c3b6a5df1 - Author: David Rodríguez - Date: 2019-07-08 19:58:24 +0900 - - [bundler/bundler] Remove unnecessary begin-end block - - And freeze the resulting hash to appease rubocop. - - https://github.com/bundler/bundler/commit/f38ebff92f - -commit f8c03b24ca6bb7e891a2303bd7c3d6094f3bd34c - Author: David Rodríguez - Date: 2019-07-05 20:21:53 +0900 - - [bundler/bundler] Bump rubocop to 0.72.0 - - https://github.com/bundler/bundler/commit/babbc112c6 - -commit 0dad89c0fed944b3a4cb531a3ecb75586c40b057 - Author: David Rodríguez - Date: 2019-03-28 02:22:09 +0900 - - [bundler/bundler] Fix typos - - https://github.com/bundler/bundler/commit/1bd9660780 - -commit 8d9fc8466f639eb2740ac406947a047505fcdea6 - Author: David Rodríguez - Date: 2019-07-05 05:14:19 +0900 - - [bundler/bundler] Reuse `lockfile` spec helper - - https://github.com/bundler/bundler/commit/e6a03f1102 - -commit 2f1d52c266eae479576aa2accf6e13c8aa18e264 - Author: David Rodríguez - Date: 2019-05-25 01:57:46 +0900 - - [bundler/bundler] Remove unused filter - - https://github.com/bundler/bundler/commit/102d6229d4 - -commit aae244569b426367426b83ef3272810282f48ee5 - Author: David Rodríguez - Date: 2018-09-26 03:36:56 +0900 - - [bundler/bundler] Reuse `gemfile` spec helper - - https://github.com/bundler/bundler/commit/22de94d3b4 - -commit 05c3b7c8a9238186c4073f5ebb8c5ce6da7495f2 - Author: David Rodríguez - Date: 2019-04-27 02:02:19 +0900 - - [bundler/bundler] More specific assertion - - 1.0.0 is such a common output, and it was hiding a crash in the test. - - https://github.com/bundler/bundler/commit/c688337e24 - -commit 13e5bf3454c1b13fdbb0c583fe68a73238cdffa2 - Author: David Rodríguez - Date: 2019-04-27 02:02:03 +0900 - - [bundler/bundler] Remove redundant assertion - - https://github.com/bundler/bundler/commit/7ac854dea1 - -commit 2c262d137c4f679ad1b6305d747e4d116b7c6959 - Author: David Rodríguez - Date: 2019-04-27 00:09:06 +0900 - - [bundler/bundler] Make spec easier to debug - - https://github.com/bundler/bundler/commit/156629291e - -commit 81a84076c21e89d9e0e1df1b4cea8bf2047b960d - Author: David Rodríguez - Date: 2019-06-21 00:45:12 +0900 - - [bundler/bundler] Don't persist the cache_all_platforms setting - - We only want it temporarily during the duration of the cache saving. - - https://github.com/bundler/bundler/commit/1e9818c0da - -commit 82bf064375361f3d662389a634ef0541a0a1fc3b - Author: Samuel Giddins - Date: 2017-10-21 04:36:52 +0900 - - [bundler/bundler] [Package] Ensure uninstallable gems are _never_ installed - - https://github.com/bundler/bundler/commit/899aeeebb0 - -commit 215d846ea59ef0a20558ac7056f35998e9dc053e - Author: Samuel Giddins - Date: 2017-10-21 04:24:48 +0900 - - [bundler/bundler] [Package] Dont always update on --all-platforms - - https://github.com/bundler/bundler/commit/723611f6ee - -commit d761a0f6ffd443b3440ac5144edcdd8054db9c7c - Author: Samuel Giddins - Date: 2017-10-21 04:19:32 +0900 - - [bundler/bundler] [Package] Always resolve remotely for --all-platforms - - https://github.com/bundler/bundler/commit/e45d2272ea - -commit 2ccb3db5fbd642f7e70c38aca946b2e010ce338b - Author: David Rodríguez - Date: 2018-09-06 07:08:46 +0900 - - [bundler/bundler] Add missing mock - - I'm not sure this test is useful but since it's there, it should be - complete. - - https://github.com/bundler/bundler/commit/3e350089db - -commit 5a56f4a541a07bb8eb600078236727e6837082e3 - Author: David Rodríguez - Date: 2018-11-21 19:18:10 +0900 - - [bundler/bundler] Remove unnecessary `order_matters` param - - https://github.com/bundler/bundler/commit/0b40b5b784 - -commit a375a4518f95dbd8f6c32840041d2847c79c3e98 - Author: Ivo Wever - Date: 2019-07-03 18:33:42 +0900 - - [bundler/bundler] Correct default cache path - - The default cache path is `vendor/cache`, not `vendor/bundle`. - https://github.com/bundler/bundler/commit/49256bb3d2 - -commit e6dc7b5b5b8e73f01b24d86a9c7b6026ae012b76 - Author: David Rodríguez - Date: 2019-06-28 18:06:03 +0900 - - [bundler/bundler] Improve spec to be more realistic - - https://github.com/bundler/bundler/commit/ca96316b97 - -commit 4b1395ab4ae7b6b9e22362ccb08d103bdec744f4 - Author: David Rodríguez - Date: 2019-04-10 18:58:30 +0900 - - [bundler/bundler] Clearer MissingRevision git errors - - https://github.com/bundler/bundler/commit/b47d23edf5 - -commit e405aede09c090c7356bd2986793e0328f498e04 - Author: David Rodríguez - Date: 2019-06-26 23:37:19 +0900 - - [bundler/bundler] Not sure how much this buys us, remove it - - https://github.com/bundler/bundler/commit/f8584fb864 - -commit ed37de1c8201a00eeb40468543313f078469e6af - Author: David Rodríguez - Date: 2019-06-26 23:42:38 +0900 - - [bundler/bundler] Inline `expanded_deps` - - It's now only used once, and doing it like this is consistent with the - previous line. - - https://github.com/bundler/bundler/commit/7d27330fc7 - -commit bdcd1990adbbbdb7baa26ca7a0fd6e56efb05143 - Author: David Rodríguez - Date: 2019-06-26 23:35:49 +0900 - - [bundler/bundler] Generate new gem development dependencies in Gemfile - - https://github.com/bundler/bundler/commit/02177d0e10 - -commit 86757abd250bc84c7eedbd3bd65176b9f979f667 - Author: David Rodríguez - Date: 2019-06-26 23:35:37 +0900 - - [bundler/bundler] Fix local variable name - - https://github.com/bundler/bundler/commit/3df138318f - -commit f2cc018adbcd054977e3e7b2410bd289f530684e - Author: David Rodríguez - Date: 2019-03-20 01:08:17 +0900 - - [bundler/bundler] Reuse `execute_bundle_gem` method - - https://github.com/bundler/bundler/commit/773203ec5a - -commit 27717893020d8d3e1bb8e40f30c1c78f4cb23bde - Author: David Rodríguez - Date: 2019-06-18 21:36:58 +0900 - - [bundler/bundler] Don't re-resolve locked platform specific gems - - https://github.com/bundler/bundler/commit/7da2bf75f5 - -commit 33fdd87227ac90063f8ed08de8cf36c8a257b461 - Author: David Rodríguez - Date: 2019-06-20 19:37:26 +0900 - - [bundler/bundler] Revert "Migrate requires from exe/ to also be relative" - - This reverts commit d9d2bf6d522dd36d1ef2732e87cef8b7cba729fd. - - https://github.com/bundler/bundler/commit/eeb2ff1561 - -commit df011b02384a85de17ae73b0aa20799c0632d18c - Author: David Rodríguez - Date: 2019-06-20 20:27:31 +0900 - - [bundler/bundler] Lock rubocop-performance to 1.4.0 - - https://github.com/bundler/bundler/commit/595dd6af6c - -commit 1a8d9a0d5dbce163fce3bed54265d6e3dad65ee7 - Author: David Rodríguez - Date: 2019-06-20 20:26:23 +0900 - - [bundler/bundler] Bump rubocop to 0.71 - - https://github.com/bundler/bundler/commit/efa69583dd - -commit 72daf37deefd1a798577be9b05bbb9406245ee89 - Author: David Rodríguez - Date: 2019-06-20 19:35:55 +0900 - - [bundler/bundler] Fix a typo on a spec comment - - https://github.com/bundler/bundler/commit/1a853ad6ac - -commit 884f948a90389782c29bab8a0d28f8f2b58286d6 - Author: robuye - Date: 2019-05-02 09:00:21 +0900 - - [bundler/bundler] bundler/inline should always install gems to system path - - As discussed in the P/R, when `BUNDLE_PATH` env is set Bundler should - still install gems to the system path. `GEM_HOME` can be used to provide - different location if needed. - - The test is added to document expected behavior of `bundler/inline`. - - https://github.com/bundler/bundler/commit/ae419fd6f8 - -commit 4089f8df1e985ec9b5347078214646be946229cc - Author: David Rodríguez - Date: 2019-06-17 20:17:54 +0900 - - [bundler/bundler] Use real paths for `bundle clean` - - https://github.com/bundler/bundler/commit/0646f9e286 - -commit e59b57a3a7d7d22baf80754e1ec069cc8cd4d561 - Author: David Rodríguez - Date: 2019-06-13 16:48:23 +0900 - - [bundler/bundler] Fix thread leak in compact index specs - - This spec was not stopping threads after itself. That would cause the - previous spec in the file (that checks that no threads are left behind) - to fail. - - https://github.com/bundler/bundler/commit/81ad85b92d - -commit a12557dbfdb63282b844f35ad0c8804bf182dfbf - Author: Miklos Fazekas - Date: 2016-03-26 19:47:43 +0900 - - [bundler/bundler] Add `required_ruby_version` to gemspec template - - https://github.com/bundler/bundler/commit/f47421f92d - -commit b014a2157f3b43d7ac85b27ad2cc47705487251e - Author: David Rodríguez - Date: 2019-06-17 17:23:47 +0900 - - [bundler/bundler] Factor out gemspec call inside `let` - - https://github.com/bundler/bundler/commit/ae0ac190aa - -commit 10c0271f970d1133685d91e786cf25f7160ffd50 - Author: David Rodríguez - Date: 2019-06-17 17:23:24 +0900 - - [bundler/bundler] Remove duplicated `let`'s - - https://github.com/bundler/bundler/commit/43ffaab796 - -commit cad71f70892f262b6912f4087d3800aa772cb117 - Author: David Rodríguez - Date: 2019-03-20 15:52:08 +0900 - - [bundler/bundler] Migrate git proxy helpers to use Open3 - - https://github.com/bundler/bundler/commit/4a37d66f3f - -commit a685a8643f3897913aa0aeeca3f1392bb9da1cf8 - Author: David Rodríguez - Date: 2019-06-11 18:45:09 +0900 - - [bundler/bundler] Fix `rake release` not prompting for OTP code - - Co-authored-by: Colby Swandale - Co-authored-by: Kevin Deisz - - https://github.com/bundler/bundler/commit/1b2bbc7364 - -commit 51bdc9433b92b60806ac535e291bf3fffd243e47 - Author: David Rodríguez - Date: 2019-05-28 18:41:47 +0900 - - [bundler/bundler] Normalize usages of `Gem::Util` in rubygems integration - - https://github.com/bundler/bundler/commit/b35d7fc74a - -commit 81779e22469d89c38ee653e3de032144af0891f7 - Author: David Rodríguez - Date: 2019-05-28 15:45:27 +0900 - - [bundler/bundler] Use rubygems utility if available - - https://github.com/bundler/bundler/commit/7eccba0e52 - -commit e111f38f34ea6b48446a0c29e142ccf44cfff282 - Author: David Rodríguez - Date: 2019-05-06 02:00:47 +0900 - - [bundler/bundler] Fix file:// handling under Windows - - Windows paths do not start with a slash, so we add an extra slash to - separate the host from the path in file:// urls. Otherwise "D:" is - parsed as the host segment in the URI. - - The path for those URLs now starts with "/", so we ignore that leading - character when using the URI's path. - - This reduces Windows CI spec failures from 429 to 355. - - https://github.com/bundler/bundler/commit/1b7e274cbc - -commit c3ddd47ce7b546530e2241b0ea6a96817977886a - Author: David Rodríguez - Date: 2019-05-07 01:06:21 +0900 - - [bundler/bundler] Normalize file:// handling in specs - - https://github.com/bundler/bundler/commit/5946d62ad0 - -commit d8d5e16305ee071f7cf16980788cabcc44799c2e - Author: David Rodríguez - Date: 2019-05-31 18:03:11 +0900 - - [bundler/bundler] Use a clean gemspec for gem helper specs - - https://github.com/bundler/bundler/commit/f694fe7f67 - -commit 1c070c9c2908736d610773a980a73395f5188cf2 - Author: David Rodríguez - Date: 2019-06-11 18:44:19 +0900 - - [bundler/bundler] Move "on releasing" to a RSpec context - - So we can later add more tests with the same setup. - - https://github.com/bundler/bundler/commit/21b4b6c49c - -commit a27198f64850441688ae77d329eab66049d0f5e5 - Author: David Rodríguez - Date: 2019-06-09 04:41:04 +0900 - - [bundler/bundler] Migrate requires from exe/ to also be relative - - https://github.com/bundler/bundler/commit/d9d2bf6d52 - -commit 9596f432505a8282473b5a011eaaa5de6fa101ef - Author: David Rodríguez - Date: 2019-06-09 04:30:30 +0900 - - [bundler/bundler] Migrate two more requires to be relative - - https://github.com/bundler/bundler/commit/80217bfe0b - -commit c5737a9ae19509de56c04a587756c0b9831cadca - Author: David Rodríguez - Date: 2019-06-09 04:29:44 +0900 - - [bundler/bundler] Migrate thor to use relative requires - - https://github.com/bundler/bundler/commit/ca28a04668 - -commit 1a4bb80cd79dcae1b2be418e70e1f5a5bcd36887 - Author: David Rodríguez - Date: 2019-05-25 03:32:45 +0900 - - [bundler/bundler] Skip specs that need coloring on Windows - - ANSI codes don't work there. - - https://github.com/bundler/bundler/commit/4f05417ca7 - -commit 38df9e18da1bbb4c74b572c51db64745e6bee853 - Author: David Rodríguez - Date: 2019-05-25 03:31:19 +0900 - - [bundler/bundler] Add missing no-color source specs - - For consistency. - - https://github.com/bundler/bundler/commit/279603ab42 - -commit 214e992556bffa1443e024e63385c5c76ac2f15f - Author: David Rodríguez - Date: 2019-05-25 03:30:43 +0900 - - [bundler/bundler] Be explicit about coloring in specs that need that - - https://github.com/bundler/bundler/commit/a4d04506ab - -commit 580e165873c727b9248e1ba7d3ac0af9b121a235 - Author: David Rodríguez - Date: 2019-05-25 03:28:25 +0900 - - [bundler/bundler] Respect color option when instantiating shells - - Thor's base shell will be memoized the first time it is set. So if we - instantiate a no-color shell first, further instantiations of a bundler - shell will be initialized with a no-color shell by default. This is - caused some sources specs to fail, depending on the order they run. - - See for example https://travis-ci.org/bundler/bundler/builds/500328994. - - What we do to fix it is to reset the shell unless no-color is explicitly - specified. That way, further instantiations will rerun thor's internal - logic to choose the default shell. - - https://github.com/bundler/bundler/commit/786b5d9894 - -commit b95756c7a998311a2d4bbee94530c6ad83ab7d06 - Author: David Rodríguez - Date: 2019-05-25 03:27:09 +0900 - - [bundler/bundler] Remove unnecessary condition - - The builtin thor's color shell already checks this before printing, and - if not a tty, prints just the string without added color codes. - - https://github.com/bundler/bundler/commit/4f62611c87 - -commit 4c2255fd5cd83799bd88ca3b8002000df54a5431 - Author: Hiroshi SHIBATA - Date: 2019-05-02 19:24:30 +0900 - - [bundler/bundler] Added Ruby 2.6 to dsl. - - https://github.com/bundler/bundler/commit/1892626858 - -commit c6837638657429034825d5c9e2a29c340898afb8 - Author: Yusuke Endoh - Date: 2019-08-03 07:44:44 +0900 - - Use source_location instead of eval(__FILE__,binding) in Binding#irb - - e9e17cbc051e894dfd27eda5feca2939f65552db (enabling the warning by - default) caused a warning in test-spec: - ``` - /data/chkbuild/tmp/build/20190802T213005Z/ruby/spec/ruby/core/binding/irb_spec.rb - Binding#irb - - creates an IRB session with the binding in scope/data/chkbuild/tmp/build/20190802T213005Z/ruby/spec/ruby/core/binding/fixtures/irb.rb:3: warning: __FILE__ in eval may not return location in binding; use Binding#source_location instead - ``` - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian/ruby-master/log/20190802T213005Z.log.html.gz - - ref: [Bug #4352] - -commit 44ddfec0bd366cd2337fd34847cddedd0a7b6775 - Author: Takashi Kokubun - Date: 2019-08-03 01:07:40 +0900 - - Add missing backslash - -commit 60ac8ad194075d5a2e8ea790c79087460fa7973d - Author: git - Date: 2019-08-03 00:55:56 +0900 - - * 2019-08-03 - -commit 4eb54c49f762031df71addd525f015e5e25ffa0c - Author: Takashi Kokubun - Date: 2019-08-03 00:55:11 +0900 - - Stop using homebrew addon - - to control errors on our own. - -commit 536ba7c81e72c365e92b9db3a80065b89b8b535b - Author: Yusuke Endoh - Date: 2019-08-02 23:29:58 +0900 - - Revert "Remove opt_nil_p test to remove warning for now" - - This reverts commit a1727e43af18c122c4d7adfa603f895fdc8f3df1. - -commit 086ffe72c711179c30a773027e0b4113e908d399 - Author: Yusuke Endoh - Date: 2019-08-02 23:25:38 +0900 - - Revert "Revert "Add a specialized instruction for `.nil?` calls"" - - This reverts commit a0980f2446c0db735b8ffeb37e241370c458a626. - - Retry for macOS Mojave. - -commit e9e17cbc051e894dfd27eda5feca2939f65552db - Author: Yusuke Endoh - Date: 2019-08-02 23:16:02 +0900 - - parse.y: make a warning for __FILE__ in eval by default - - [Bug #4352] - -commit 247b06d40095e3dfe16b94ea88976e39e83e2463 - Author: Takashi Kokubun - Date: 2019-08-02 23:01:54 +0900 - - Revert "Give up `brew update` on Travis" - - This reverts commit e05f397f08e98fb170e3aca885d6028b344e833c. - Failed... https://travis-ci.org/ruby/ruby/jobs/566961111 - - We should talk to Travis people instead... - -commit a1727e43af18c122c4d7adfa603f895fdc8f3df1 - Author: Takashi Kokubun - Date: 2019-08-02 22:46:15 +0900 - - Remove opt_nil_p test to remove warning for now - -commit eb638b75b33c7be30021d1de57f44498c6b5f6d6 - Author: Hiroshi SHIBATA - Date: 2019-07-23 16:09:46 +0900 - - It can be share to use CoreAssertions for default gems. - - ref. https://github.com/ruby/logger/pull/35 - -commit 9921b63ac48ca7c195bc8b9db96eb1f434ce9e8a - Author: Nobuyoshi Nakada - Date: 2019-08-02 19:04:38 +0900 - - Make float_decode_internal mantissa int - -commit 6640eeb6dbcf2c5d721ebd005001f3f43f03ab53 - Author: Nobuyoshi Nakada - Date: 2019-08-02 18:11:05 +0900 - - Deduplicate common code - -commit ee1334189b95cb5e7785e3415b332a7a76879ac3 - Author: Nobuyoshi Nakada - Date: 2019-08-02 17:51:45 +0900 - - Fix uplevel - -commit e03b3b4ae046785278b9188c83b2338f0f550526 - Author: Koichi Sasada - Date: 2019-08-02 14:59:29 +0900 - - add debug_counters to check details. - - add debug_counters to check the Hash object statistics. - -commit a0980f2446c0db735b8ffeb37e241370c458a626 - Author: Yusuke Endoh - Date: 2019-08-02 15:03:34 +0900 - - Revert "Add a specialized instruction for `.nil?` calls" - - This reverts commit 9faef3113fb4331524b81ba73005ba13fa0ef6c6. - - It seemed to cause a failure on macOS Mojave, though I'm unsure how. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/osx1014/ruby-master/log/20190802T034503Z.fail.html.gz - - This tentative revert is to check if the issue is actually caused by the - change or not. - -commit 19006b711d8649b69d6f9dafad073a2f57201dd7 - Author: Nobuyoshi Nakada - Date: 2019-08-02 11:28:24 +0900 - - Expanded f_quo - -commit f9a0492b76956b545c746ab0d3ec0e555e77dfcd - Author: Nobuyoshi Nakada - Date: 2019-08-02 11:25:41 +0900 - - Expanded f_ceil - -commit ffe4a6ebf93166544c4265271f7b8cffa2208af6 - Author: Nobuyoshi Nakada - Date: 2019-08-02 11:22:56 +0900 - - Use RB_INTEGER_TYPE_P - -commit 6de61fb9edf77d69e93cca8e4166b51b07c71c06 - Author: Nobuyoshi Nakada - Date: 2019-08-02 11:19:29 +0900 - - Expanded f_mod - -commit 8ba8ccc3ccdea943acbb12149578edd92e5164d4 - Author: git - Date: 2019-08-02 00:55:03 +0900 - - * 2019-08-02 - -commit ef45a57801a2ae8621b0cde59f11159f89f0a8dc - Author: Jeremy Evans - Date: 2019-08-01 09:03:11 +0900 - - Make attr* methods define public methods if self in caller is not same as receiver - - Previously, attr* methods could be private even if not in the - private section of a class/module block. - - This uses the same approach that ruby started using for define_method - in 1fc33199736f316dd71d0c551edbf514528ddde6. - - Fixes [Bug #4537] - -commit b8e351a1b9a16ce27f53d15051a1d1f83911b8cb - Author: Yusuke Endoh - Date: 2019-08-01 21:09:59 +0900 - - ext/-test-/bug-14834/bug-14384.c: fallback for MAYBE_UNUSED - - __unused__ is unavailable on Sun C. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20190801T112505Z.fail.html.gz - -commit 8b162ce9d1003e4e469d8f48cb9a2076fd45b47c - Author: Nobuyoshi Nakada - Date: 2019-08-01 20:08:22 +0900 - - Fix assertion failure when VM_CHECK_MODE - - Some VM frames (dummy and top pushed by `rb_vm_call_cfunc`) has - iseq but has no pc. - -commit 2eec526053186f05e8b73003d5212c871724a309 - Author: Kazuhiro NISHIYAMA - Date: 2019-08-01 20:34:10 +0900 - - bootstraptest/test_insns.rb: test opt_nil_p - -commit 076f3fcf11a061394d3d5f8c671512df1e983023 - Author: Takashi Kokubun - Date: 2019-08-01 20:19:18 +0900 - - Extend sleep before sending USR1 in TestProcess - - because the test seems to hang there forever: - https://travis-ci.org/ruby/ruby/jobs/566409880 - -commit cb84824481f205d5c057fe2e31776d40a6b06c7c - Author: Takashi Kokubun - Date: 2019-08-01 19:42:48 +0900 - - Add a test for opt_nil_p - -commit 1549fbfda561759879f16e5d7b2451fe9ac03147 - Author: Nobuyoshi Nakada - Date: 2019-08-01 16:40:03 +0900 - - Use predefined idTo_proc - -commit d488464106c0a65c892a8785d577ce8011e6e277 - Author: Nobuyoshi Nakada - Date: 2019-08-01 15:17:52 +0900 - - Use predefined idOr - -commit fd0e3bd2497d4e796b719c7b7154dc3c945f87b1 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-08-01 16:18:45 +0900 - - fix VC 2013 compile error - - It seems the compiler does not support VLAs. - See also: https://ci.appveyor.com/project/ruby/ruby/builds/26392589/job/px6nuiuw4e78weg1 - -commit 3a6f51ee35da5d49973aba8f7d8128a65a9d8c4a - Author: Koichi Sasada - Date: 2019-08-01 16:04:40 +0900 - - introduce ar_hint_t. - - Hash hint for ar_array is 1 byte (unsigned char). This patch introduce - ar_hint_t which represents hint type. - -commit e18e7852536a42434b7b25fa08846fe161290d46 - Author: git - Date: 2019-08-01 16:04:09 +0900 - - * expand tabs. - -commit 19d3c80e8136402a26b52c8da46eee071ec413d6 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-07-31 23:15:56 +0900 - - calc_lineno(): add assertions - - This function has a lot of assumptions. Should make them sure. - -commit 5d33f787169bcc3594d2264726695d58c4a06899 - Author: åœéƒ¨æ˜Œå¹³ - Date: 2019-07-31 23:00:15 +0900 - - fix tracepoint + backtrace SEGV - - PC modification in gc_event_hook_body was careless. There are (so - to say) abnormal iseqs stored in the cfp. We have to check sanity - before we touch the PC. - - This has not been fixed because there was no way to (ab)use the - setup from pure-Ruby. However by using our official C APIs it is - possible to touch such frame(s), resulting in SEGV. - - Fixes [Bug #14834]. - -commit d2f8e03f346424553f3081896c91dd7d6fdf5db0 - Author: git - Date: 2019-08-01 14:27:19 +0900 - - * expand tabs. - -commit f45bb760fb0a751915a9eac5f7dc4075e88e0cfc - Author: Yusuke Endoh - Date: 2019-08-01 14:25:15 +0900 - - signal.c: make signame_prefix a nul-terminated string - - gcc 9.1.0 warns this. - - ``` - signal.c:258:46: warning: '%.*s' directive argument is not a nul-terminated string [-Wformat-overflow=] - 258 | rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'", - | ^~~~ - 259 | prefix, signame_prefix, vsig); - | ~~~~~~~~~~~~~~ - signal.c:200:19: note: referenced argument declared here - 200 | static const char signame_prefix[3] = "SIG"; - | ^~~~~~~~~~~~~~ - ``` - https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu/ruby-master/log/20190801T033009Z.log.html.gz - -commit 746386710646f93a5b9e0c408b00408041645091 - Author: Koichi Sasada - Date: 2019-08-01 11:20:37 +0900 - - use internal_id. - - "hash_iter_lev" can be exported by Marshal.dump and it will - introduce inconsistency. To avoid this issue, use internal_id - instead of normal ID. This issue is pointed out by Chikanaga-san. - -commit 67f7e5a224bc31e1625023ce1ed5cfbd54ea1d8f - Author: Kazuhiro NISHIYAMA - Date: 2019-08-01 09:12:08 +0900 - - Compact ensure clause and rename variables to fix alignment - -commit 31ec475ad8ac13b1390ce09f74f577fff13c65b1 - Author: Aaron Patterson - Date: 2019-06-08 01:11:33 +0900 - - Update object.c - - Co-Authored-By: Takashi Kokubun - -commit 714924fd34c025f151aba6833009a5733bf4ccf9 - Author: git - Date: 2019-08-01 08:21:58 +0900 - - * expand tabs. - -commit 9faef3113fb4331524b81ba73005ba13fa0ef6c6 - Author: Aaron Patterson - Date: 2019-06-05 08:29:08 +0900 - - Add a specialized instruction for `.nil?` calls - - This commit adds a specialized instruction for called to `.nil?`. It is - about 27% faster than master in the case where the object is nil or not - nil. In the case where an object implements `nil?`, I think it may be - slightly slower. Here is a benchmark: - - ```ruby - require "benchmark/ips" - - class Niller - def nil?; true; end - end - - not_nil = Object.new - xnil = nil - niller = Niller.new - - Benchmark.ips do |x| - x.report("nil?") { xnil.nil? } - x.report("not nil") { not_nil.nil? } - x.report("niller") { niller.nil? } - end - ``` - - On Ruby master: - - ``` - [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 429.195k i/100ms - not nil 437.889k i/100ms - niller 437.935k i/100ms - Calculating ------------------------------------- - nil? 20.166M (± 8.1%) i/s - 100.002M in 5.002794s - not nil 20.046M (± 7.6%) i/s - 99.839M in 5.020086s - niller 22.467M (± 6.1%) i/s - 112.111M in 5.013817s - [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 449.660k i/100ms - not nil 433.836k i/100ms - niller 443.073k i/100ms - Calculating ------------------------------------- - nil? 19.997M (± 8.8%) i/s - 99.375M in 5.020458s - not nil 20.529M (± 7.0%) i/s - 102.385M in 5.020689s - niller 21.796M (± 8.0%) i/s - 108.110M in 5.002300s - [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 402.119k i/100ms - not nil 438.968k i/100ms - niller 398.226k i/100ms - Calculating ------------------------------------- - nil? 20.050M (±12.2%) i/s - 98.519M in 5.008817s - not nil 20.614M (± 8.0%) i/s - 102.280M in 5.004531s - niller 22.223M (± 8.8%) i/s - 110.309M in 5.013106s - - ``` - - On this branch: - - ``` - [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 468.371k i/100ms - not nil 456.517k i/100ms - niller 454.981k i/100ms - Calculating ------------------------------------- - nil? 27.849M (± 7.8%) i/s - 138.169M in 5.001730s - not nil 26.417M (± 8.7%) i/s - 131.020M in 5.011674s - niller 21.561M (± 7.5%) i/s - 107.376M in 5.018113s - [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 477.259k i/100ms - not nil 428.712k i/100ms - niller 446.109k i/100ms - Calculating ------------------------------------- - nil? 28.071M (± 7.3%) i/s - 139.837M in 5.016590s - not nil 25.789M (±12.9%) i/s - 126.470M in 5.011144s - niller 20.002M (±12.2%) i/s - 98.144M in 5.001737s - [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb - Warming up -------------------------------------- - nil? 467.676k i/100ms - not nil 445.791k i/100ms - niller 415.024k i/100ms - Calculating ------------------------------------- - nil? 26.907M (± 8.0%) i/s - 133.755M in 5.013915s - not nil 25.319M (± 7.9%) i/s - 125.713M in 5.007758s - niller 19.569M (±11.8%) i/s - 96.286M in 5.008533s - ``` - - Co-Authored-By: Ashe Connor - -commit 117241b3c73f8f7f1bcfee34e9d627c41bb19cc9 - Author: Koichi Sasada - Date: 2019-08-01 05:59:04 +0900 - - make inline functions from macros. - -commit bd1052d55da94b5503ff00c10e1cdcc04a6f9608 - Author: Koichi Sasada - Date: 2019-08-01 05:50:58 +0900 - - use hash_ar_table_set() directly - -commit deddc8047647792e27e1b9829bc917ef73504320 - Author: Koichi Sasada - Date: 2019-08-01 05:48:22 +0900 - - HASH_ASSERT() respects HASH_DEBUG - -commit 43d74776a1465095ab6b420809cc278d4f95f7bc - Author: Koichi Sasada - Date: 2019-08-01 05:21:42 +0900 - - check hash_hint is different. - -commit a1a198d03af6b285dbee552da5e40e7c3061e6c9 - Author: Koichi Sasada - Date: 2019-07-31 18:00:33 +0900 - - File.realpath can raise ENOTDIR - -commit 5ad2dfd8dce00f9fb4908adc786f12baaaf2b273 - Author: Aaron Patterson - Date: 2019-08-01 02:34:23 +0900 - - Revert "Let prev EP move" - - This reverts commit e352445863588b90f7af6cdf6c1b6dc432ee33ab. - - This is breaking CI and I'm not sure why yet, so I'll revert for now. - -commit 8d138e9702e814353574cf6092b0929879e110af - Author: git - Date: 2019-08-01 01:43:23 +0900 - - * 2019-08-01 - -commit e352445863588b90f7af6cdf6c1b6dc432ee33ab - Author: Aaron Patterson - Date: 2019-07-02 19:02:11 +0900 - - Let prev EP move - - This commit allows the previous EP pointer to move, then updates its - location - -commit c94cc6d968a7241a487591a9753b171d8081d335 - Author: Nobuyoshi Nakada - Date: 2019-07-31 20:46:01 +0900 - - run single spec [ci skip] - -commit 835fa9e54ac1d3bbee9b816275e7ea28e9dac313 - Author: Yusuke Endoh - Date: 2019-07-31 19:55:16 +0900 - - test/ruby/test_hash.rb: remove a unused vrible - - to suppress a warning - -commit 4562c1309333ab08c2fa5e975ded8524122a2b55 - Author: Yusuke Endoh - Date: 2019-07-31 19:51:58 +0900 - - lib/bundler/shared_helpers.rb: remove require "rubygems" - - Because it causes circular require. - -commit e432f5dafd3ec777e552631a2d3f14887b0562df - Author: Benoit Daloze - Date: 2019-07-31 18:06:54 +0900 - - Split in two spec examples - -commit eab6c534adb381b81291e871cd57c957cf786503 - Author: Benoit Daloze - Date: 2019-07-31 18:04:35 +0900 - - Attempt to fix Hash#rehash spec - -commit 14eede6e530f58bc22fb6d89ecf910eb1cfcf240 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-31 17:45:43 +0900 - - Fix `Leaked thread` - - Sometimes `Leaked thread: Rinda::TestRingServer#test_ring_server_ipv6_multicast` happens - because `Rinda::TupleSpace#start_keeper` runs after stopping `@keeper`. - -commit 40651cf1f567ae728c8d2cc908017c31e1000b6e - Author: Koichi Sasada - Date: 2019-07-31 15:12:57 +0900 - - delete a check on bad assumption. - - If object was modified, but there is a case that - hash values (#hash) are same between before modified - and after modified objects. - -commit 5f95edb7af68ce03732da4d49eee8d6ee87ef544 - Author: Koichi Sasada - Date: 2019-07-31 15:10:16 +0900 - - check SystemStackError - - This recursive iteration test can cause SystemStackError so - check it correctly. - -commit cac44def0b0f0fdcd1aa8cf610e16a5506d2726b - Author: Koichi Sasada - Date: 2019-07-31 15:01:19 +0900 - - backtrace can be nil. - - Surprisingly, on SystemStackError#backtrace can return nil. - -commit efac0a2384ed6cb1572490b36566e2e37509d7df - Author: Koichi Sasada - Date: 2019-07-31 14:53:14 +0900 - - Revert "add debug code" - - This reverts commit e83ec207cd5fda973c41d6629d8504b515522b12. - -commit 06574ad945dcce0bf626b3af020810230b169b56 - Author: Yusuke Endoh - Date: 2019-07-31 14:35:21 +0900 - - test/ruby/test_float.rb: suppress an overflow warning - - ``` - warning: Float 0xf.fp10000000000000... out of range - ``` - -commit e83ec207cd5fda973c41d6629d8504b515522b12 - Author: Koichi Sasada - Date: 2019-07-31 12:46:15 +0900 - - add debug code - -commit 816e5055c90de327d99fe7f1d2cc4cfe86acd887 - Author: Yusuke Endoh - Date: 2019-07-31 11:52:59 +0900 - - test/ruby/test_io.rb (test_binmode_pipe): close all pipes explicitly - - to suppress the leak checker. - -commit 1d02832bcff7ea45604da3a626b7983f9efe484d - Author: Yusuke Endoh - Date: 2019-07-31 11:45:28 +0900 - - test/rdoc/test_rdoc_rubygems_hook.rb: suppress deprecation warning - -commit 823adea954b7d197301867e70c1aae74e4d81eff - Author: Yusuke Endoh - Date: 2019-07-31 11:44:20 +0900 - - test/ruby/test_file_exhaustive.rb: suppress method-redefined warning - -commit 312879693ffa88c0778baba2b6697f6e5f2f6116 - Author: Koichi Sasada - Date: 2019-07-31 11:30:23 +0900 - - move macro to internal.h for documentation. - - 13e84d5c0a changes enum to macro, but the flags usage information - are lost in internal.h. It should be same place with other flags - information. - -commit 4979ba38fa070b4b9480f0da4b7c827e9eb768ab - Author: Yusuke Endoh - Date: 2019-07-31 11:27:59 +0900 - - test/rubygems/test_gem_remote_fetcher.rb: suppress deprecation warnings - -commit 13e84d5c0a53ad013aa0093f179115bcf88417e9 - Author: Nobuyoshi Nakada - Date: 2019-07-31 11:08:05 +0900 - - Moved RHASH_LEV_MASK and turned into a macro - - Get rid of "ISO C restricts enumerator values to range of 'int'" - error. - -commit e315f3a1341f123051b75e589b746132c3510079 - Author: git - Date: 2019-07-31 10:22:47 +0900 - - * expand tabs. - -commit 72825c35b0d8b9d566663de961fddbf4f010fff7 - Author: Koichi Sasada - Date: 2019-01-18 01:53:10 +0900 - - Use 1 byte hint for ar_table [Feature #15602] - - On ar_table, Do not keep a full-length hash value (FLHV, 8 bytes) - but keep a 1 byte hint from a FLHV (lowest byte of FLHV). - An ar_table only contains at least 8 entries, so hints consumes - 8 bytes at most. We can store hints in RHash::ar_hint. - - On 32bit CPU, we use 4 entries ar_table. - - The advantages: - * We don't need to keep FLHV so ar_table only consumes - 16 bytes (VALUEs of key and value) * 8 entries = 128 bytes. - * We don't need to scan ar_table, but only need to check hints - in many cases. Especially we don't need to access ar_table - if there is no match entries (in many cases). - It will increase memory cache locality. - - The disadvantages: - * This technique can increase `#eql?` time because hints can - conflicts (in theory, it conflicts once in 256 times). - It can introduce incompatibility if there is a object x where - x.eql? returns true even if hash values are different. - I believe we don't need to care such irregular case. - * We need to re-calculate FLHV if we need to switch from ar_table - to st_table (e.g. exceeds 8 entries). - It also can introduce incompatibility, on mutating key objects. - I believe we don't need to care such irregular case too. - - Add new debug counters to measure the performance: - * artable_hint_hit - hint is matched and eql?#=>true - * artable_hint_miss - hint is not matched but eql?#=>false - * artable_hint_notfound - lookup counts - -commit ebd398ac5a4147a1e652d6943c39a29a62f12e66 - Author: Koichi Sasada - Date: 2019-01-16 19:48:30 +0900 - - remove RHash::iter_lev. - - iter_lev is used to detect the hash is iterating or not. - Usually, iter_lev should be very small number (1 or 2) so - `int` is overkill. - - This patch introduce iter_lev in flags (7 bits, FL13 to FL19) - and if iter_lev exceeds this range, save it in hidden attribute. - We can get 1 word in RHash. - - We can't modify frozen objects. Therefore I added new internal API - `rb_ivar_set_internal()` which allows us to set an attribute - even if the target object is frozen - if the name is hidden ivar (the name without `@` prefix). - -commit 4afd8975242917d319cfb20c7ed635b979ad48d5 - Author: Hiroshi SHIBATA - Date: 2019-07-30 22:38:00 +0900 - - File.exists? is deprecated. - -commit 3e4e8dbe20da5de9d26665159626f553318b39a8 - Author: Hiroshi SHIBATA - Date: 2019-07-30 21:40:37 +0900 - - Uninstall ntlm-http and plist for failure of osx test. - - It contains too old configuration that is autorequire. It will be - removed at the RubyGems 3.1.0. - -commit 77c0e23b0c28f543e1fb4fbf20cae216be0398f9 - Author: Hiroshi SHIBATA - Date: 2019-07-28 10:59:07 +0900 - - [rubygems/rubygems] Partly reverted be962ca0c411f3b4bcfebfb6e714c78cbad12775 - - * `Gem::ConfigMap` is still used by Bundler. - * `Gem::RubyGemsVersion` is also still referred by the old gems. - - https://github.com/rubygems/rubygems/commit/249c3ff44f - -commit 2a81d3a26a1b9512efb394ec87f73463496d830d - Author: Hiroshi SHIBATA - Date: 2019-07-27 16:45:45 +0900 - - [rubygems/rubygems] Skip integration test for rake package task. - - https://github.com/rubygems/rubygems/commit/ca8afc01a3 - -commit ab8d9a53250acfab04bed322c9c9b342d95195fb - Author: bronzdoc - Date: 2019-07-28 23:37:02 +0900 - - [rubygems/rubygems] Initialize '@ran_rake' correctly, so we don't have to set it up later and cause confusion - - https://github.com/rubygems/rubygems/commit/6ec3ba983c - -commit 5824981d98a61b071c216749c7dcdd40fdf61673 - Author: bronzdoc - Date: 2019-07-28 23:06:01 +0900 - - [rubygems/rubygems] Remove extension 'double pipe equals' assignment since is not needed anymore - - https://github.com/rubygems/rubygems/commit/930de86a24 - -commit b73ad4999a1182fe5f06501f81cb58b44ae7e9c2 - Author: bronzdoc - Date: 2019-07-28 23:03:01 +0900 - - [rubygems/rubygems] Move 'build_for' to handle extension type before the extension is used - - https://github.com/rubygems/rubygems/commit/2a32c5ef0a - -commit 9dc0f39de556c384783fb112d0561c0df391dcc4 - Author: bronzdoc - Date: 2019-07-28 22:58:03 +0900 - - [rubygems/rubygems] Do not pass +build_dir+ argument to build_error - - https://github.com/rubygems/rubygems/commit/107fea3432 - -commit d97fc48e92dbee041a476f7dca65f3d466c8ca91 - Author: bronzdoc - Date: 2019-07-28 22:50:11 +0900 - - [rubygems/rubygems] Remove useless param +build_dir+ - - https://github.com/rubygems/rubygems/commit/0402974149 - -commit a51661d378c26ae5bd4b608de4948887e70bcacc - Author: bronzdoc - Date: 2019-07-10 22:16:57 +0900 - - [rubygems/rubygems] Drop support for 'gem env packageversion' - - https://github.com/rubygems/rubygems/commit/be962ca0c4 - -commit 62e2b2e66f4fefa493c4ac91c121c7484f67b7be - Author: David Rodríguez - Date: 2019-06-27 22:32:21 +0900 - - [rubygems/rubygems] Improve `rake package` test error message - - https://github.com/rubygems/rubygems/commit/be962ca0c4 - -commit 61893ddf75760c35d5c676914cc50c7e4f9a64ae - Author: David Rodríguez - Date: 2019-06-05 00:32:45 +0900 - - [rubygems/rubygems] Get `rake package` tested - - https://github.com/rubygems/rubygems/commit/006cdd4084 - -commit bb6bd7e9855cd17f004fd4ef3300a4c0b529f45f - Author: David Rodríguez - Date: 2019-06-04 17:40:54 +0900 - - [rubygems/rubygems] Generate a licenses.rb file with correct style - - https://github.com/rubygems/rubygems/commit/469fceeb2f - -commit 497efa0ec924b5124309b99a5c5b8f848fc5a632 - Author: David Rodríguez - Date: 2019-06-04 17:40:30 +0900 - - [rubygems/rubygems] Enable `Layout/AlignArray` cop - - https://github.com/rubygems/rubygems/commit/1ea674d8f7 - -commit 0817d95714bc73cef7a4eb6cdfc50a1c5ea4a6c1 - Author: David Rodríguez - Date: 2019-06-04 17:21:14 +0900 - - [rubygems/rubygems] Enable `Layout/EmptyLinesAroundAccessModifier` - - https://github.com/rubygems/rubygems/commit/41b1cebc33 - -commit 3cc814bdf629c457cc3899675c4cb1418594d47e - Author: bronzdoc - Date: 2019-07-26 14:02:46 +0900 - - [rubygems/rubygems] Remove warning: shadowing outer local variable - spec - - https://github.com/rubygems/rubygems/commit/70c5c17a5f - -commit 33025d976865859744535edb63063a102bec73f5 - Author: bronzdoc - Date: 2019-07-26 13:11:37 +0900 - - [rubygems/rubygems] Make error code a constant and remove TODO comment - - https://github.com/rubygems/rubygems/commit/3d6c7c92e4 - -commit a3b784b3a068ddd9a395b8951e9977035eca5066 - Author: Vít Ondruch - Date: 2019-07-22 21:31:10 +0900 - - [rubygems/rubygems] Move default specifications dir definition out of BasicSpecification. - - This was never the right place. The method got there just by evolution, - not by design. Move it within default methods, where it suits better. - - Since this method is presumably used just internally, it should be safe - to deprecate it and remove later. - - https://github.com/rubygems/rubygems/commit/0c0dd9458a - -commit d1806bd8da963c597ccd8c0b63ceac4dbe3ff3ae - Author: Hiroshi SHIBATA - Date: 2019-07-21 10:17:26 +0900 - - [rubygems/rubygems] There is no usage of @orig_env_* variables in test suite. - - https://github.com/rubygems/rubygems/commit/2adef51dc9 - -commit a3c0ea55f8cfd634db6ce623599ea3ad9750f11e - Author: Hiroshi SHIBATA - Date: 2019-07-21 09:58:41 +0900 - - [rubygems/rubygems] Ignore GEMRC variable for test suite. It affects with some test case. - - https://github.com/rubygems/rubygems/commit/4a0ca2583a - -commit 1eaacb1ef538fe5af2fe231bb340fc39fef67547 - Author: bronzdoc - Date: 2019-07-17 09:50:36 +0900 - - [rubygems/rubygems] Use File#open instead of Kernel#open - - https://github.com/rubygems/rubygems/commit/bfb3f67494 - -commit 41dd9f7e67c1d767a7d040cd79f26985e3996821 - Author: bronzdoc - Date: 2019-07-17 09:39:40 +0900 - - [rubygems/rubygems] Deprecate Gem::RemoteFetcher#fetch_size - - https://github.com/rubygems/rubygems/commit/c2049c3276 - -commit a34168f2ac674b2660fa895271faea258389a614 - Author: bronzdoc - Date: 2019-07-17 09:07:07 +0900 - - [rubygems/rubygems] Autorequire was used by old RubyGems, it is neither supported nor functional. - - https://github.com/rubygems/rubygems/commit/cadb66037d - -commit a2f0331c4e1c47425ec6042f41f4f4b1b63e557f - Author: Nobuyoshi Nakada - Date: 2019-07-11 10:24:01 +0900 - - [rubygems/rubygems] Simplify #to_ruby code - - Separate #add_runtime_dependency and #add_development_dependency - availability condition from #specification_version availability, - which is not related to directly. - Also check if the former method is available, instead of comparing - the version. - - https://github.com/rubygems/rubygems/commit/5cccc2b836 - -commit 5947ea31ca7cd6a5aa7969088ef38ff9eb9be2da - Author: Alexander Pakulov - Date: 2019-07-10 11:14:29 +0900 - - [rubygems/rubygems] Missing dependency - - https://github.com/rubygems/rubygems/commit/79b62c233a - -commit 0d596c1ab2013f0db2a374adc71c25ba886ed49b - Author: Alexander Pakulov - Date: 2019-07-10 10:52:54 +0900 - - [rubygems/rubygems] Making Gem::S3URISigner.sign method smaller with helper methods - - https://github.com/rubygems/rubygems/commit/2a96494d91 - -commit 74419711ad548c7f38c247ab1d8d1fbb9087b8ba - Author: Alexander Pakulov - Date: 2019-07-07 05:05:43 +0900 - - [rubygems/rubygems] Use default value for expiration in the method signature - - https://github.com/rubygems/rubygems/commit/1372e50c17 - -commit aa9015dd8430522318714eee0de562ade845ce7c - Author: Alexander Pakulov - Date: 2019-07-05 09:16:25 +0900 - - [rubygems/rubygems] Moving rubygems/request dependencies into ec2_metadata - - https://github.com/rubygems/rubygems/commit/6a1856517f - -commit 4a8c2dd4192517fa030b6585ae82bf925c80516a - Author: Alexander Pakulov - Date: 2019-07-04 08:35:59 +0900 - - [rubygems/rubygems] Extracting sign_s3_url & s3_source_auth into a separate S3URISigner class - - https://github.com/rubygems/rubygems/commit/c30d21ec7a - -commit 1dfe132aa5138a5664b353739fc2ad32d6cd68dd - Author: bronzdoc - Date: 2019-06-30 14:59:31 +0900 - - [rubygems/rubygems] Move TODO comment to an information comment - - https://github.com/rubygems/rubygems/commit/853ecdd417 - -commit 7081185664d438661a312eb3a12adcc84568b07e - Author: bronzdoc - Date: 2019-06-30 14:50:40 +0900 - - [rubygems/rubygems] Remove unused 'raise' from test_case - - https://github.com/rubygems/rubygems/commit/2481efcb37 - -commit eb35124ccac0f3498c4152349f71978ad86ffad5 - Author: bronzdoc - Date: 2019-06-30 14:38:46 +0900 - - [rubygems/rubygems] Remove TODO comment, there's no Gem::Dirs constant - - https://github.com/rubygems/rubygems/commit/4bacf577f1 - -commit 60d3f9ef9f9385f09a52584b74cc04adf48a25d1 - Author: bronzdoc - Date: 2019-06-30 14:23:44 +0900 - - [rubygems/rubygems] Remove useless TODO comment - - https://github.com/rubygems/rubygems/commit/44bc809dc8 - -commit bd78eabcf37f498d41939716cc4cba39bf3e509e - Author: Alexander Pakulov - Date: 2019-06-29 02:21:12 +0900 - - [rubygems/rubygems] Addressing PR comments - - https://github.com/rubygems/rubygems/commit/fb62d3043c - -commit b2a54744f252f18bc5a8b04fca9a2cb18132e1a8 - Author: bronzdoc - Date: 2019-06-27 08:51:22 +0900 - - [rubygems/rubygems] check_version_conflict don't have a 'dep' variable available for use - - https://github.com/rubygems/rubygems/commit/1783cf0fd3 - -commit 56801d4532f55e09ec1947c336934917c04af7b3 - Author: bronzdoc - Date: 2019-06-26 07:42:47 +0900 - - [rubygems/rubygems] Remove misleading comment, no reason to move Gem.host to Gem::Util - - https://github.com/rubygems/rubygems/commit/e12c98aa72 - -commit ff214e92321b2dab169f23e7996500ec8505b59b - Author: bronzdoc - Date: 2019-06-25 10:01:33 +0900 - - [rubygems/rubygems] Remove useless comment in exceptions.rb - - https://github.com/rubygems/rubygems/commit/d7ad696fa2 - -commit 6bd7772361685f861c6917462f9dead6254f2216 - Author: bronzdoc - Date: 2019-06-24 11:08:34 +0900 - - [rubygems/rubygems] Rename Gem::Package.metadata to Gem::Package.raw_spec - - https://github.com/rubygems/rubygems/commit/a76f25dff0 - -commit 38daeded66afb4a7beafa47d82625a4eb40c112b - Author: Alexander Pakulov - Date: 2019-06-25 09:36:31 +0900 - - [rubygems/rubygems] Upgrading S3 source signature to AWS SigV4 - - https://github.com/rubygems/rubygems/commit/f289788ca5 - -commit 688ccc96020258acb4c02a2f8c5ff6e5a0bbc966 - Author: bronzdoc - Date: 2019-06-24 11:03:50 +0900 - - [rubygems/rubygems] Move metadata method to Gem::Package - - https://github.com/rubygems/rubygems/commit/2c9cfcb666 - -commit 8103d46a4d9591ae95f9a3c31619d1b12031cf3c - Author: Daniel Berger - Date: 2019-06-19 21:39:39 +0900 - - [rubygems/rubygems] Add a package attr_reader to Gem::Installer. - - Add some basic specs for the package attr_reader. - - https://github.com/rubygems/rubygems/commit/68af2a0ee3 - -commit 6be927ff4abd9cbcad545d05d8e93810ffa2da9e - Author: bronzdoc - Date: 2019-06-23 22:43:23 +0900 - - [rubygems/rubygems] Remove misleading TODO comment. Can't use @parser.accept since not - every class where this is used has a parser available. i.e lib/rubygems/install_update_options.rb - - https://github.com/rubygems/rubygems/commit/519fd4dcc0 - -commit c421ef11423742b62a22efa8d0df449cb7364491 - Author: bronzdoc - Date: 2019-06-23 14:42:21 +0900 - - [rubygems/rubygems] Move gemcutter utilities code to Gem::Command - - https://github.com/rubygems/rubygems/commit/f296645033 - -commit 5eacb4c52ed52185d78aa1437c0a69ed986a95f6 - Author: bronzdoc - Date: 2019-06-23 07:58:55 +0900 - - [rubygems/rubygems] Remove conflict.rb code that was supposed to be removed in Rubygems 3 - - https://github.com/rubygems/rubygems/commit/6d5f743a89 - -commit a7bce01175762ba763148fe29f5cbadf5d0f6250 - Author: bronzdoc - Date: 2019-06-23 07:41:07 +0900 - - [rubygems/rubygems] Remove unnecessary &&= operator - - https://github.com/rubygems/rubygems/commit/a10b5265d7 - -commit 8b91a6d0a0b8b2f1aaebf9636139f3f933c6f86d - Author: bronzdoc - Date: 2019-06-23 07:39:17 +0900 - - [rubygems/rubygems] Remove unnecessary TODO comment - - https://github.com/rubygems/rubygems/commit/ad7e379f79 - -commit df0b41fc7219f9f4900e117591dd8331dc4a10b0 - Author: David Rodríguez - Date: 2019-06-20 19:16:58 +0900 - - [rubygems/rubygems] Explicitly deprecate `rubyforge_project` - - https://github.com/rubygems/rubygems/commit/9094740109 - -commit 0ca494fc80ad66a299e012378794632b6734ee5c - Author: David Rodríguez - Date: 2019-06-20 20:10:06 +0900 - - [rubygems/rubygems] Silence deprecations when gemdeps is used in tests - - Because we can't control 3rd party gems using deprecated rubygems - behavior, and thus outputting warnings to the screen. - - https://github.com/rubygems/rubygems/commit/6912ebf20a - -commit 05ae2c11fa0464b258d40ff330839a303fbdfd67 - Author: Benoit Daloze - Date: 2019-06-06 22:54:17 +0900 - - [rubygems/rubygems] Do not replace the cache entry if there is already one - - * That way, multiple lookups for the same file always return the same object. - - https://github.com/rubygems/rubygems/commit/50a431b6db - -commit 2453d16f5e44f67a50e1be9b08504a14960610ef - Author: Benoit Daloze - Date: 2019-06-06 22:52:44 +0900 - - [rubygems/rubygems] Synchronize access to the Gem::Specification::LOAD_CACHE Hash - - * It's accessed concurrently, notably when installing a gem with a C extension. - - https://github.com/rubygems/rubygems/commit/543294d7dd - -commit 89bd1df895265a3756928b0ab863f01ecb3abd71 - Author: bronzdoc - Date: 2019-06-05 10:51:08 +0900 - - [rubygems/rubygems] Add a blank line after private to be consistent with the current style - - https://github.com/rubygems/rubygems/commit/df7c0e4223 - -commit 673ef894ac7318a7e078ed43629a6473cfa36067 - Author: bronzdoc - Date: 2019-06-01 06:37:12 +0900 - - [rubygems/rubygems] Return early if filename is empty - - https://github.com/rubygems/rubygems/commit/1b9ab33083 - -commit d74ea2eeb22e9db8a8003804ca48bd84629e72c7 - Author: bronzdoc - Date: 2019-05-31 11:34:44 +0900 - - [rubygems/rubygems] Simplify config_file_name assignment - - https://github.com/rubygems/rubygems/commit/1b3154f905 - -commit 6c5170634af21ff90c2d80604ae5c2808a597a9e - Author: bronzdoc - Date: 2019-05-30 08:34:47 +0900 - - [rubygems/rubygems] Lazy require stringio - - https://github.com/rubygems/rubygems/commit/82f0d4ca69 - -commit 7990d8dc50007b04118cb36c9f200efcddb0295f - Author: bronzdoc - Date: 2019-05-29 14:07:01 +0900 - - [rubygems/rubygems] Set config_file_name to the value of ENV["GEMRC"] if available - - https://github.com/rubygems/rubygems/commit/471239f1fa - -commit 6f60ead7565e02901db63f005008860b65b4a15e - Author: bronzdoc - Date: 2019-05-29 13:41:54 +0900 - - [rubygems/rubygems] Move config_file_name logic to its own method - - https://github.com/rubygems/rubygems/commit/ac4596aace - -commit d64cc80b660c30577945f3cac452ca16db44ce9f - Author: David Rodríguez - Date: 2019-04-29 16:07:16 +0900 - - [rubygems/rubygems] Migrate extension builder to use Open3 - - Since it works on jruby. - - https://github.com/rubygems/rubygems/commit/5229e00df4 - -commit 4e27319c2c0a58ed5ee7276f5f69946161fb6367 - Author: David Rodríguez - Date: 2019-04-29 08:45:18 +0900 - - [rubygems/rubygems] Remove unused method - - https://github.com/rubygems/rubygems/commit/f2dbf242ea - -commit a4c09342a2219a8374240ef8d0ca86abe287f715 - Author: git - Date: 2019-07-31 05:49:04 +0900 - - * expand tabs. - -commit ebc99e026d0ae770b297a93d1f1c1ceeffd13bfc - Author: Jeremy Evans - Date: 2019-07-26 05:47:08 +0900 - - Do not change IO.pipe encodings if encodings explicitly given - - This commit makes it so that if the binmode option is given with - any encoding arguments, the reader and writer IO objects are - not set to binary encoding. - - Fixes [Bug #12989] - -commit d8562ab2a40658db0e6a44ce07cfbe616b9b4078 - Author: Aaron Patterson - Date: 2016-11-29 07:22:12 +0900 - - Passing `binmode: true` to `IO.pipe` should behave like `binmode` - - When passing `binmode: true` to `IO.pipe`, it should behave the same way - as calling `binmode` on each of the file handles. It should set the - file to binmode *and* set the encoding to binary on the file. - - Before this commit, passing `binmode: true` to `IO.pipe` would make - `binmode?` return `true`, but the file's encoding would remain the same - as the default encoding. Passing `binmode: true` should make `binmode?` - return `true` *and* set the encoding to binary. - -commit 369c36ef15c15ddc297e216522cc21599ed6a8e1 - Author: git - Date: 2019-07-31 04:00:46 +0900 - - * 2019-07-31 - -commit a50bc9f3c8e0696ede25305c03eadecc543b863b - Author: Jeremy Evans - Date: 2019-06-21 03:50:22 +0900 - - Do not always taint the result of File#path - - The result should only be tainted if the path given to the method - was tainted. - - The code to always taint the result was added in - a4934a42cbb84b6679912226581c71b435671f55 (svn revision 4892) in - 2003 by matz. However, the change wasn't mentioned in the - commit message, and it may have been committed by accident. - - Skip part of a readline test that uses Reline. Reline in general - would pass the test, but Reline's test mode doesn't raise a - SecurityError if passing a tainted prompt and $SAFE >= 1. This - was hidden earlier because File#path was always returning a - tainted string. - - Fixes [Bug #14485] - -commit ceb9e276b934a8a63299b0b96d2c430c9854de7f - Author: Nobuyoshi Nakada - Date: 2019-07-30 21:15:49 +0900 - - Shorten dependency hint [ci skip] - -commit f3b0ed3f264201137c5841c46ec3ee61d3b14034 - Author: Takashi Kokubun - Date: 2019-07-30 21:15:10 +0900 - - Try giving up `brew update` in Azure as well - - homebrew-cask fetch fails too often. - https://dev.azure.com/rubylang/ruby/_build/results?buildId=1917 - -commit e25088488bbf7b4bf1be19e57ee5fba41ad6f21c - Author: Nobuyoshi Nakada - Date: 2019-07-30 17:23:42 +0900 - - Hint for the dependency update [Bug #16000] - -commit 47144f91a176f263f870e05347d5b426efc40293 - Author: Nobuyoshi Nakada - Date: 2019-07-30 16:44:29 +0900 - - Separate VCS::GIT#upstream - -commit 2e6f777f9efa8ba15dcd1b7c1bb1917e5d31d6f8 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-30 12:44:38 +0900 - - `/o` should not use with instance variable - - for example: - ``` - class C;def initialize(pat);@pat=pat;end;def re;/#{@pat}/o;end;end - C.new('1').re #=> /1/ - C.new('2').re #=> /1/ - ``` - -commit 3805ef7fb57136be46fceb693340981c75eb8ec1 - Author: Nobuyoshi Nakada - Date: 2019-07-30 12:39:28 +0900 - - Separate test_set_lineno_gets - -commit 1da3a31a5f0211db121e0df4ca456838a437537f - Author: Tanaka Akira - Date: 2019-07-30 11:59:54 +0900 - - Use lowercase letters for IPv6 addresses. - - Reported by chucke (Tiago Cardoso). - Patch by jeremyevans0 (Jeremy Evans). - [Bug #14612] - -commit 6eab49a40abcc743ddffcd5fc7103acbea06b215 - Author: Jeremy Evans - Date: 2019-07-30 04:10:15 +0900 - - Revert "Do not always taint the result of File#path" - - This reverts commit 1a759bfe5d554c22571d2e6e4e5998cf06a7b98f. - - This fails on some operating systems. - -commit 177731aadf0d2b2fb293e221728252c73446235a - Author: Jeremy Evans - Date: 2019-07-30 03:03:32 +0900 - - Document that Timezone argument for Time uses dst? if available [ci skip] - -commit 9170646f130be8a66bd1ea84a7bed59a353afd12 - Author: git - Date: 2019-07-30 02:48:25 +0900 - - * 2019-07-30 - -commit 1a759bfe5d554c22571d2e6e4e5998cf06a7b98f - Author: Jeremy Evans - Date: 2019-06-21 03:50:22 +0900 - - Do not always taint the result of File#path - - The result should only be tainted if the path given to the method - was tainted. - - The code to always taint the result was added in - a4934a42cbb84b6679912226581c71b435671f55 (svn revision 4892) in - 2003 by matz. However, the change wasn't mentioned in the - commit message, and it may have been committed by accident. - - Skip part of a readline test that uses Reline. Reline in general - would pass the test, but Reline's test mode doesn't raise a - SecurityError if passing a tainted prompt and $SAFE >= 1. This - was hidden earlier because File#path was always returning a - tainted string. - - Fixes [Bug #14485] - -commit aa97410b0a85cb4ceb956ab943b5eee92a128411 - Author: Jeremy Evans - Date: 2019-07-27 07:14:49 +0900 - - Warn if using return at top-level with an argument - - Fixes [Bug #14062] - -commit c2428b8bf6f3646f575c21d0c89192d79130f7cc - Author: Nobuyoshi Nakada - Date: 2019-07-29 23:04:04 +0900 - - Erase only on tty - -commit e62a60927e5477380db34c381e142bce812232dd - Author: Nobuyoshi Nakada - Date: 2019-07-29 22:56:48 +0900 - - Should match the beginning/end of string - -commit 3ee63cfe881c9ac52a52344ea83131b88875d14c - Author: Nobuyoshi Nakada - Date: 2019-07-29 22:54:58 +0900 - - Match suffix for content type more precisely - - Suffix needs a dot and should match the end of string. - -commit bef398eb87ac14fffc7fe19df9ec6b07ddff17cd - Author: Nobuyoshi Nakada - Date: 2019-07-29 22:51:01 +0900 - - Chomp html suffix literally - - Unescaped dot does not mean a suffix. - -commit 968c7b4398ea82f764ced57f1d38606ef4b0c8e6 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-29 23:03:59 +0900 - - Fix unused variable - -commit a5ea55feb4ef8c482b4639936dd828e0ec27262f - Author: Takashi Kokubun - Date: 2019-07-29 20:57:57 +0900 - - Actually remove travis_wait - - I forgot to amend again... Details are explained in - f6a6b21f09b24955a44622e1767bf5b6630525be - -commit f6a6b21f09b24955a44622e1767bf5b6630525be - Author: Takashi Kokubun - Date: 2019-07-29 20:55:18 +0900 - - `travis_wait` silences any output - - and thus it does not work with `-v` for investigating hangs well. - This seems to be by design: https://github.com/travis-ci/travis-ci/issues/4190 - - Also I simplified a comment about `homebrew.update`. - I had this in-flight change while editing e05f397f08e98fb170e3aca885d6028b344e833c - but forgot to amend this. - -commit e05f397f08e98fb170e3aca885d6028b344e833c - Author: Takashi Kokubun - Date: 2019-07-29 20:25:22 +0900 - - Give up `brew update` on Travis - - No `brew update` causes "Error: Your Homebrew is outdated" like https://travis-ci.org/ruby/ruby/jobs/547485832, - but doing `brew update` is also problematic like https://travis-ci.org/ruby/ruby/jobs/564916879. - - Hoping that the former case is more rare, let's try no `brew update` - again. - -commit 5af28fec2f2f75be70d0c40a92ac9d8b77c8e822 - Author: Takashi Kokubun - Date: 2019-07-29 19:49:19 +0900 - - Resurrect -v to debug osx problems - - Formerly we did f432fd6ea595ef854e15d6dd65ef0ccb24a70456, but it did not - eliminate our problems: https://travis-ci.org/ruby/ruby/jobs/564804923 - -commit 4b4d8a662b4b5125ada85720f26cead3180a3f06 - Author: Takashi Kokubun - Date: 2019-07-29 19:45:25 +0900 - - Stop isolating test_gc_compact on CI - - I think it's been stable these days. - -commit 8c6f1715f03e0322c96d614a42c30bee0b7790eb - Author: Nobuyoshi Nakada - Date: 2019-07-29 13:29:42 +0900 - - Removed unused variables and methods - -commit 630eb04bc4e275b6eaea6fffd35d72ad974f56ed - Author: Nobuyoshi Nakada - Date: 2019-07-29 13:29:35 +0900 - - [ruby/rdoc] Removed unused variable - -commit f811a5e9109ff25e485edfcaddce68fa8f3c5262 - Author: git - Date: 2019-07-29 12:06:13 +0900 - - * 2019-07-29 - -commit 61f0f71e5bd60bd6ea6153034e72b723dddcbe2e - Author: Nobuyoshi Nakada - Date: 2019-07-29 11:38:15 +0900 - - Moved osx_image - - Set osx_image under each configuration, as it decides the OS (and - kernel) version not only Xcode version, and the configuration name - contains the kernel version. - -commit b40589802b6fe6ba5cbb783a43f513cb2e597844 - Author: Nobuyoshi Nakada - Date: 2019-07-28 09:52:07 +0900 - - [reline] Do not compile regexp for each line - -commit a6e32855d079e8f3806d8be8a5f5cf7b3a967133 - Author: Nobuyoshi Nakada - Date: 2019-07-28 09:43:26 +0900 - - [reline] Do not escape and compile regexp for each byte - -commit bce348204f7f4105500397cacb709498e15d9857 - Author: git - Date: 2019-07-28 07:37:35 +0900 - - * 2019-07-28 - -commit 1d1f98d49c9908f4e3928e582d31fd2e9f252f92 - Author: Nobuyoshi Nakada - Date: 2019-07-28 07:33:21 +0900 - - Reuse match data - - * string.c (rb_str_split_m): reuse occupied match data. [Bug #16024] - -commit adf13625aeb86961123911cba85c993417a5762a - Author: Takashi Kokubun - Date: 2019-07-27 23:46:39 +0900 - - Extend travis_wait to 50min for osx - - but shorten --timeout-scale for now to avoid finishing with timeout - if possible. - - timeout: https://travis-ci.org/ruby/ruby/jobs/564370175 - -commit f1b76ea63ce40670071a857f408a4747c571f1e9 - Author: Nobuyoshi Nakada - Date: 2019-07-27 21:54:34 +0900 - - Occupy match data - - * string.c (rb_str_split_m): occupy match data not to be modified - during yielding the block. [Bug #16024] - -commit e3b613a66986306950fc69d426d947a349b9fc8b - Author: Takashi Kokubun - Date: 2019-07-27 21:34:34 +0900 - - Include travis osx timeout - - for failures like https://travis-ci.org/ruby/ruby/jobs/564351066 - -commit 73530a961918c4039a4c44865a89742b7b693a0b - Author: nagachika - Date: 2019-07-27 20:15:53 +0900 - - tool/merger.rb: execute 'svn update' after 'svn ci' to update revision info on working copy. - -commit 7b727e30fcbdf6ae4ac0b0b84f1d32c747d8525a - Author: Benoit Daloze - Date: 2019-07-27 19:57:46 +0900 - - Update to ruby/spec@0526d8f - -commit 5c276e1cc91c5ab2a41fbf7827af2fed914a2bc0 - Author: Benoit Daloze - Date: 2019-07-27 19:40:09 +0900 - - Update to ruby/spec@875a09e - -commit a06301b103371b0b7da8eaca26ba744961769f99 - Author: Jeremy Evans - Date: 2019-06-25 03:13:09 +0900 - - Ignore history file without saving if permissions cannot be changed - - Fixes [Ruby Bug 13907] - -commit f9f02e82166643c1e12f10ac51a0d367ee26ac31 - Author: Charles Oliver Nutter - Date: 2019-07-26 14:37:11 +0900 - - Use JRuby equivalent of RubyVM.compile. - - RubyVM is specific to CRuby and not supported on JRuby. This is - the equivalent operation. - -commit 58bb7f0ca1468629a379c74f637bdb04e1e5dfe7 - Author: Hiroshi SHIBATA - Date: 2019-07-27 12:31:07 +0900 - - Skip the some of commits when sync default gems from upstream. - - * Skip failed to sync commits because it needs to pick manually. - * Skip empty commit. - -commit 012d39c4e658f251f691c8a1dba462c937dbac67 - Author: Hiroshi SHIBATA - Date: 2019-07-27 11:23:47 +0900 - - Added ignore files to sync_default_gems_with_commits and make constant them. - -commit 149e414ed529d27aaeb0543bc133e08c782d8d41 - Author: Nobuyoshi Nakada - Date: 2019-04-23 13:09:34 +0900 - - Initialize DST flag - - * time.c (zone_timelocal): initialize DST flag by asking the - timezone object. [Bug #15988] - -commit 8bccbf3cfea8c1059d40db5b5e61900cf6cf29d3 - Author: Jeremy Evans - Date: 2019-07-27 09:04:13 +0900 - - Add more documentation on #eql?/#hash relationship [ci skip] - - Fixes [Bug #14263] - -commit 6279cf8b2b2a683cb9e4f6422e6f6f9351cff37b - Author: Jeremy Evans - Date: 2019-07-27 08:57:42 +0900 - - Restore documentation for Object#hash [ci skip] - - Object#hash documentation was removed (probably by accident) in - 7b19e6f3fdf8b0238752cb1561dfe42a283f5308. - -commit bd3283338250827e0f9e2fd1785bd1fd4151e66d - Author: Jeremy Evans - Date: 2019-07-27 06:26:59 +0900 - - Document behavior when mixing named captures with parentheses [ci skip] - - Fixes [Bug #13716] - -commit 5fef46ae0dedaab359f55bc3680f4278eb7da98d - Author: Jeremy Evans - Date: 2019-07-27 01:56:53 +0900 - - Test SecureRandom.uuid format - - SecureRandom uses v4 UUIDs, which are completely random except for - 6 bits, 4 in the version field and 2 in the clk_seq_hi_res field. - Add a test that those bit patterns are set correctly for v4 UUIDs, - per RFC 4122 section 4.4. - - Fixes [Bug #13603] - -commit 4f978a1c995ec565f72095415f4d2fb298188fae - Author: git - Date: 2019-07-27 00:18:35 +0900 - - * 2019-07-27 - -commit b1a2eddbfcb883c363bd67858a4dc739f4755775 - Author: Jeremy Evans - Date: 2019-07-27 00:13:34 +0900 - - Document acceptance of negative pid in Process.kill [ci skip] - - Fixes [Bug #13501] - -commit 4b7d7d007fa5a06d237be6f379106feea25fca79 - Author: Jeremy Evans - Date: 2019-06-25 07:07:00 +0900 - - Document and add spec for delegating to constants in Forwardable - - Fixes [Bug #13142] - -commit 21ce8b3298bd3b2c8afa7fd747a958e70b55b708 - Author: Maxime Lapointe - Date: 2019-05-15 00:52:36 +0900 - - [ruby/rdoc] Fix image links in rdoc.css - - Every image in the rdoc.css that use url has the wrong one. They end up pointing to `css/images/zoom.png` instead of `images/zoom.png`. - - Just open this page https://ruby.github.io/rdoc/RDoc/CodeObject.html on chrome and you can see in the console the spam of the failed GET queries. - - This fixes it. - https://github.com/ruby/rdoc/commit/daf36f9894 - -commit 8bb48923761e0e3689ea61fec05b2c36faf9d899 - Author: aycabta - Date: 2019-04-01 17:16:57 +0900 - - [ruby/rdoc] Update jQuery to 3.3.1 - - https://github.com/ruby/rdoc/commit/17df871ee - -commit 3b0f952ec810c08eac01ce2377dfbb252026760b - Author: aycabta - Date: 2019-01-25 23:58:30 +0900 - - [ruby/rdoc] Support nesting text page URL - - RDoc::Servlet#documentation_page replaces "/" in URL with "::" for class - or module but it's also used for the replaced name on text pages. This - causes a bug when text pages are in nesting directory. - - This commit fixes #615. - - https://github.com/ruby/rdoc/commit/d73b915b1e - -commit a86d4eef4b4551a48a5329bb993c3c6c39a1b1f3 - Author: aycabta - Date: 2019-01-22 04:46:46 +0900 - - [ruby/rdoc] Normalization of comment should check language - - RDoc::Text#normalize_comment that is included RDoc::Comment always - remove Ruby style comment indicator "#" and C style comment indicator - "/**/", but should check language and remove only the language's comment - indicator. - - https://github.com/ruby/rdoc/commit/ca68ba1e73 - -commit f7cbbc707413f7e1c71ac1839b0c8834550451e6 - Author: aycabta - Date: 2019-01-20 13:18:22 +0900 - - [ruby/rdoc] ClassModule#add_comment should receive RDoc::Comment - - https://github.com/ruby/rdoc/commit/3fb03bf399 - -commit 95aa60f6cde1ab7bc5cfe33c95c4fd2d2154cd52 - Author: Hiroshi SHIBATA - Date: 2019-07-26 18:14:32 +0900 - - Ignore Merge commit and insufficiency commit for ruby core repository. - -commit 071bf889706d13879c323d61fd2e757ff32c8bda - Author: Hiroshi SHIBATA - Date: 2019-07-26 17:06:54 +0900 - - Improve the commits list for cherry-picking from default gems. - - * Ignore Merge commit from the commit lists before trying to - pick commit. - * Show the commits list at first. - -commit 348c9687bf0454fce787e0d4886fe244831b0a84 - Author: Hiroshi SHIBATA - Date: 2019-07-26 16:45:18 +0900 - - Escape parentheses for syntax highlighting for VScode. - -commit 51f22deadba35ed57b794339fd19889ed0cc8dc8 - Author: Hiroshi SHIBATA - Date: 2019-07-26 16:34:15 +0900 - - Adjust the test directory structure of rdoc. - -commit 82b02c131ee1a87ac1b95443c85c6c8f7b30644f - Author: Koichi Sasada - Date: 2019-07-26 11:37:02 +0900 - - pass to obj_info(). - - obj_info() has a routine to show SPECIAL_CONST_P() objects so - we don't need to check it here. - -commit 300de6aec29b1d220b961a287820a32a89940882 - Author: git - Date: 2019-07-26 10:46:31 +0900 - - * 2019-07-26 - -commit 957a29fc6eb5e4e4ad562d5cafb393f62c9f05db - Author: Nobuyoshi Nakada - Date: 2019-07-26 09:03:34 +0900 - - Bump osx_image on Travis CI to xcode11 - - Also Homebrew is up-to-date and "Updating Homebrew" takes less - than one minute. - -commit 7e33f324e1d1de31a69d16dc9f27ec223523c6e8 - Author: Nobuyoshi Nakada - Date: 2019-07-25 20:57:32 +0900 - - Get rid of failures about coverage - - Run test suites explicitly instead of auto-running, to get rid of - failures when simplecov is not installed but COVERAGE is set. - -commit a50c844645c337742584560abc2e2b63bf566e79 - Author: Nobuyoshi Nakada - Date: 2019-07-25 17:15:48 +0900 - - Initialize vm_throw_data::throw_state as int - - As `struct vm_throw_data::throw_state` is initialized as `VALUE` - by rb_imemo_new, extended MSW part is assigned to it on LP64 - big-endian platforms. - - Fix up 1feda1c2b091b950efcaa481a11fd660efa9e717 - -commit 0f9ec4a877496278534e5956b640ed43a02229ad - Author: aycabta - Date: 2019-07-25 17:19:11 +0900 - - Check whether multibyte character is split - -commit 8e53d18e6724211bd0597ec5852869e6bf9679f1 - Author: Nobuyoshi Nakada - Date: 2019-07-24 11:07:15 +0900 - - Separated tool/test/runner.rb and test/runner.rb - - As `make test-tool` does not use gems, and no Rubygems stuffs is - needed, so moved such things to test/runner.rb. Also no longer - needs `--test-target-dir` option. - -commit 46771abfe53d95e8cecf917a5c999e32388be184 - Author: Nobuyoshi Nakada - Date: 2019-07-25 16:52:03 +0900 - - Use libraries in the base directory if given - -commit 4c1db84d1748b56334da8293ee328186fcb08162 - Author: Nobuyoshi Nakada - Date: 2019-07-25 16:45:18 +0900 - - Added --base-directory option - -commit f5ea05481017d34a1ebdc0eec32ef10254420ee5 - Author: Nobuyoshi Nakada - Date: 2019-07-25 14:29:15 +0900 - - Moved NoMemoryError hook - - Moved NoMemoryError hook from AutoRunner.run to Runner#run, so - it will work even in non-autorunning mode. - -commit d8e90f555817146d17ec82a55360b6d69c649d67 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-25 16:39:28 +0900 - - Fix a typo in inspect - -commit a850be68a57dce65449766654aa1912b5fa660cb - Author: Nobuyoshi Nakada - Date: 2019-07-24 11:04:26 +0900 - - Moved NoMemoryError hook to Test::Unit::AutoRunner - -commit 82ae46211341f926d79c6e2e26f4b9097625443c - Author: Nobuyoshi Nakada - Date: 2019-07-25 08:19:03 +0900 - - Do not fetch remote tags - -commit 077c28887a68c08f84d91e104fd9ac9c39810482 - Author: Nobuyoshi Nakada - Date: 2019-07-25 05:00:33 +0900 - - [ruby/io-console] Do not use add_development_dependency - - https://github.com/ruby/io-console/commit/bc77f46391 - -commit 414d6cf1d310de8f9eed1263116ad568b05a98ec - Author: Nobuyoshi Nakada - Date: 2019-07-25 03:29:41 +0900 - - [ruby/psych] Get rid of C90 feature - - For ruby 2.6 and earlier. - - https://travis-ci.org/ruby/psych/jobs/562435717#L245-L248 - - ``` - ../../../../ext/psych/psych_parser.c: In function ‘make_exception’: - ../../../../ext/psych/psych_parser.c:87:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] - VALUE ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError")); - ^ - ``` - - https://github.com/ruby/psych/commit/aa457443b8 - -commit 698dde525ad3df1444276ccd28c6349c81af2a19 - Author: Nobuyoshi Nakada - Date: 2019-07-24 22:21:49 +0900 - - [ruby/psych] Suppress uninitialized instance variable warnings - - In verbose mode, `test_delegator` in `test/psych/visitors/test_yaml_tree.rb` shows following warning. - - https://travis-ci.org/ruby/psych/jobs/562435717#L268 - ``` - /home/travis/build/ruby/psych/test/psych/visitors/test_yaml_tree.rb:10: warning: instance variable @obj not initialized - ``` - - This is because `Psych.load` bypasses #initialize with the #init_with method. - - https://github.com/ruby/psych/commit/f99523388f - -commit 6ca7dc69effddeb63a8fb8f759e29ff8649907ec - Author: Jean Boussier - Date: 2019-07-22 19:02:23 +0900 - - [ruby/psych] Deduplicate hash keys if they're strings - - https://github.com/ruby/psych/commit/0414982ffd - -commit 50076903ab06e2301051e459925afea20325ba7c - Author: Hiroshi SHIBATA - Date: 2019-07-21 12:21:27 +0900 - - [ruby/psych] Drop to support fat gem support. - - ref. https://github.com/ruby/bigdecimal/pull/149 - - https://github.com/ruby/psych/commit/25ae263252 - -commit 938032a790b22a1b49c1b112ede2da4597b4e75c - Author: Hiroshi SHIBATA - Date: 2019-07-21 12:16:56 +0900 - - [ruby/psych] Do not use add_development_dependency. - - https://github.com/ruby/psych/commit/939754237f - -commit 0a63c4d5fbbbfae9aba92c78e39b1521b90f1b06 - Author: Nobuyoshi Nakada - Date: 2019-07-25 06:39:40 +0900 - - Fix errno at seeking socket/pipe on Windows - - [Bug #12230] - -commit efa380b006aeafbad90b2d4e795a602404fec3c5 - Author: Nobuyoshi Nakada - Date: 2019-07-25 05:54:38 +0900 - - Use PRIuSIZE instead of "%zu" - -commit da76c4460f754baabc7a8db16d2e1b5f1c3eb264 - Author: Jeremy Evans - Date: 2019-07-25 03:54:07 +0900 - - Clarify Thread exception handling documentation [ci skip] - - From djellemah (John Anderson). - - Fixes [Bug #12252] - -commit 48b4deb418b374c6433fb346ea4550db46843fca - Author: git - Date: 2019-07-25 02:36:25 +0900 - - * 2019-07-25 - -commit 3556cba5038530e728eb6309dcf5d4d1a96a02ac - Author: Jeremy Evans - Date: 2019-07-25 02:30:56 +0900 - - Document that Range#cover? returns false if <=> returns nil - - Fixes [Bug #12090] - -commit 1cce4303247110d94eab8326f187a2a80130b324 - Author: Nobuyoshi Nakada - Date: 2019-07-24 22:07:10 +0900 - - Suppress deflateParams() warnings - -commit 538ba984c8e3c6ae33cbc87a5090725af24caf2e - Author: Nobuyoshi Nakada - Date: 2019-07-24 21:07:12 +0900 - - Split ls line - -commit 96b0d7cd6fcff7cb2f42315e39a961d84c630e9d - Author: Nobuyoshi Nakada - Date: 2019-07-24 21:03:01 +0900 - - GNU ls -T has different meaning - -commit 65a9d4b0f7ae07c026622392e06fc70dbcc5bfc1 - Author: Takashi Kokubun - Date: 2019-07-24 20:51:29 +0900 - - Fix typo [ci skip] - -commit 7b1893c771d21876884e17e8281c737bfc1c4643 - Author: Takashi Kokubun - Date: 2019-07-24 20:50:50 +0900 - - Resurrect timestamp debug log - - because it failed again https://travis-ci.org/ruby/ruby/jobs/563026412 - even after 676df311d90990a4666adb5b1db4c7aa6b080e57. - -commit dc954cbb75381149970e45927153829a88cbe0b5 - Author: Nobuyoshi Nakada - Date: 2019-07-24 20:08:40 +0900 - - @@project_dir in Gem::TestCase is no longer used - -commit 99fb637c41c6301286042afbc9edaea71cd7643b - Author: Nobuyoshi Nakada - Date: 2019-07-24 13:57:59 +0900 - - [rubygems/rubygems] Make `@@project_dir` constants per files - - https://github.com/rubygems/rubygems/commit/955174658f - -commit 99680f81e832506792cf32d830d09954acd220fc - Author: Nobuyoshi Nakada - Date: 2019-07-24 13:24:18 +0900 - - [rubygems/rubygems] Resolve `@@project_dir` from test file paths - - `Dir.pwd` may differ from the source path. Test directories and - files should be resolved from test file paths. - - https://github.com/rubygems/rubygems/commit/e18e7c81b4 - -commit 3a227b99e78927cdd53e4c1b6b1e5f1af004ca41 - Author: Nobuyoshi Nakada - Date: 2019-07-24 12:25:02 +0900 - - Adjusted test runner - -commit 5108a5dd7f8d29043354f7ad923f3d670a01d0a5 - Author: Nobuyoshi Nakada - Date: 2019-07-24 12:13:07 +0900 - - test-bundled-gems-run: Respect -k option - -commit a39f218f22e8ec205291022f9b748d51daa8df3b - Author: Nobuyoshi Nakada - Date: 2019-07-24 11:51:04 +0900 - - Reduced duplicate commands in test-bundled-gems-run - -commit df317151a5b4e0c5a30fcc321a9dc6abad63f7ed - Author: Koichi Sasada - Date: 2019-07-24 05:32:09 +0900 - - should not free local hook_list here. - - exec_hooks_postcheck() clean executed hook_list if it is needed. - list_exec is freed if there are no events and this list is local - event (connected to specific iseq). However, iseq keeps to point - this local hook_list, freed list. To prevent this situation, - do not free hook_list here even if it has no events. - - This issue is reported by @joker1007. - https://twitter.com/joker1007/status/1153649170797830144 - -commit a4e5690760c9177bc4234fdc5152d82ba73d26d0 - Author: Yusuke Endoh - Date: 2019-07-24 04:49:51 +0900 - - transcode.c (rb_econv_open0): remove unused code - - Coverity Scan found this. - -commit 9aba971e42c78bb9e446f28c0402bad55147a863 - Author: Jeremy Evans - Date: 2019-07-08 09:58:25 +0900 - - Make Object#singleton_methods work correctly for singleton classes of objects - - Fixes [Bug #10901] - -commit 11662c70b073da21dcd5213b61434bce2ed6af8f - Author: Nobuyoshi Nakada - Date: 2019-07-24 01:42:35 +0900 - - Test missing Content-Type warnings - -commit afea8db8c7a6bca9042002dd305d45494eb2656f - Author: Nobuyoshi Nakada - Date: 2019-07-24 01:42:05 +0900 - - Test invalid offset warnings - -commit f295e23e54dd000806e252798e352f327606cd86 - Author: git - Date: 2019-07-24 00:32:43 +0900 - - * 2019-07-24 - -commit c9826c20d204d4b8894e6fd51e5913959676776d - Author: Nobuyoshi Nakada - Date: 2019-07-24 00:24:12 +0900 - - Show the caller's location - - * lib/net/http/header.rb: show the caller's location instead of - the current lines. - -commit 325f7b6008a4a10e9b0f1c69ee4518b0669461be - Author: Jeremy Evans - Date: 2019-07-08 12:16:57 +0900 - - Make pkg_config in mkmf include -I cflags in return value - - This was the historical behavior, it was modified unintentionally - by 097c3e9cbbf23718371f08c24b2d2297b039f63f, which started storing - these flags in a different global variable. - - Also, include the incflags when logging, and document that the - method modifies $INCFLAGS. - - Fixes [Bug #10651] - -commit b6f07f748a95f1d5dc0d21e821320564776c744d - Author: Jesús Burgos Maciá - Date: 2019-07-20 04:59:21 +0900 - - Document that non-blocking mode isn't always supported on Windows [ci skip] - -commit 676df311d90990a4666adb5b1db4c7aa6b080e57 - Author: Nobuyoshi Nakada - Date: 2019-07-23 20:51:23 +0900 - - Reset mtime of all files on osx - - Often checked out files are in the future on OSX image. - -commit 03958a0c0d0140a2c27f8e3175f9c118425c762c - Author: Nobuyoshi Nakada - Date: 2019-07-23 18:22:25 +0900 - - Relaxed target_os matching - - When target_alias is not empty, `-gnu` suffixed is not stripped. - - [Bug #16015] - -commit e8d4f0cbc78b0e06806394a93ba73b7d04eba14d - Author: Nobuyoshi Nakada - Date: 2019-07-23 17:59:43 +0900 - - Show seconds and in the modified time order - - [ci skip] - -commit 0338c44bde4fe55f0507a82fe470dce2ac70127a - Author: Nobuyoshi Nakada - Date: 2019-07-23 17:39:03 +0900 - - Retry to update Unicode timestamp - -commit 009ec37a47e2f2b5e7f928004fbc3403f0bd8abe - Author: Lourens Naudé - Date: 2019-04-14 01:39:05 +0900 - - Let the index boundary check in rb_enc_from_index be flagged as unlikely - - [Misc #15806] - - Closes: https://github.com/ruby/ruby/pull/2128 - -commit 6546aed4757be07f4932326e1eb41a5d69141acf - Author: Lourens Naudé - Date: 2019-04-14 01:05:58 +0900 - - Explicitly initialise encodings on init to remove branches on encoding lookup - - [Misc #15806] - - Closes: https://github.com/ruby/ruby/pull/2128 - -commit c25ff7bb5d8e8d2985ec8fd32a7211a06ad4eca0 - Author: Koichi Sasada - Date: 2019-07-23 16:42:20 +0900 - - check iseq is executable - -commit 33f54da15ba137fc1569016f5caa492c1a57eb4d - Author: Nobuyoshi Nakada - Date: 2019-07-23 16:18:40 +0900 - - Support memsize of AST - -commit 90c4bd2d2bd10b19c2b09834396553742bc7e8a4 - Author: Lourens Naudé - Date: 2019-04-23 07:24:52 +0900 - - Let memory sizes of the various IMEMO object types be reflected correctly - - [Feature #15805] - - Closes: https://github.com/ruby/ruby/pull/2140 - -commit ab087ecb4dd21ea5f7d1cbadd8298f2f1a3c9ce9 - Author: Hiroshi SHIBATA - Date: 2019-07-23 13:34:35 +0900 - - Added the upstream repositories to default gems. - -commit 73d56d6fe7dd387342ddfcefbaff402f7dcaa232 - Author: Hiroshi SHIBATA - Date: 2019-07-23 13:32:21 +0900 - - reline is default gems now. - -commit 44cfabddbe8f62ce247118b12e75f4d2294d50b8 - Author: Hiroshi SHIBATA - Date: 2019-07-23 11:20:08 +0900 - - Removed duplicated entry for racc. - -commit 01995df6453de45ba0d99835e26799260517657c - Author: Jeremy Evans - Date: 2019-07-23 07:07:22 +0900 - - Document BasicObject does not implement #object_id and #send [ci skip] - - Fixes [Bug #10422] - -commit 32ec6dd5c7cb89979d48100acf8971ac09e0d02e - Author: Jeremy Evans - Date: 2019-07-23 06:43:36 +0900 - - Document encoding of string returned by Regexp.quote [ci skip] - - Also, remove documentation about returning self, which makes no - sense as self would be the Regexp class. It could be interpreted - as return the argument if no changes were made, but that hasn't - been the behavior at least since 1.8.7 (and probably before). - - Fixes [Bug #10239] - -commit c1ad6321b03bcf9f96f975bcba7ff1d205990149 - Author: Jeremy Evans - Date: 2019-07-23 06:02:39 +0900 - - Adjust documentation for Kernel#raise [ci skip] - - Mention how each of the arguments are retrievable from the generated - Exception object. - - Fixes [Bug #10110] - -commit d2710ba86677380f016b6a84d81e5cb39837c04d - Author: Nobuyoshi Nakada - Date: 2019-07-23 05:21:41 +0900 - - Split test/ripper/test_files.rb to run in parallel - -commit 11f3da8e9dd98cb6b0c2c2fd22220f8508af32f2 - Author: Nobuyoshi Nakada - Date: 2019-07-23 05:20:04 +0900 - - Stop packing rb_method_definition_t - - By using `BITFIELD`, `type` field should not be forced to align. - -commit 6b62aa7aec1c8beffafc5e321419cba408bf3c24 - Author: git - Date: 2019-07-23 04:10:42 +0900 - - * 2019-07-23 - -commit 2f6cc00338826dbaa439a18e4b4f7a19c1f5987a - Author: Jeremy Evans - Date: 2019-07-10 13:33:01 +0900 - - Fix documentation for Array#pack m directive count specifier [ci skip] - - Fixes [Bug #10025] - -commit 9f9a6dbc1491fa9407bf3da70646dc8636c566f5 - Author: Hiroshi SHIBATA - Date: 2019-07-22 18:00:37 +0900 - - Always fetch the latest commit from default gems repository. - -commit 1feda1c2b091b950efcaa481a11fd660efa9e717 - Author: Koichi Sasada - Date: 2019-07-22 17:44:58 +0900 - - constify again. - - Same as last commit, make some fields `const`. - - include/ruby/ruby.h: - * Rasic::klass - * RArray::heap::aux::shared_root - * RRegexp::src - internal.h: - * rb_classext_struct::origin_, redefined_class - * vm_svar::cref_or_me, lastline, backref, others - * vm_throw_data::throw_obj - * vm_ifunc::data - * MEMO::v1, v2, u3::value - - While modifying this patch, I found write-barrier miss on - rb_classext_struct::redefined_class. - - Also vm_throw_data::throw_state is only `int` so change the type. - -commit 9095ff53cf6c25154c7f80910aab8d1af45c42ec - Author: Jeremy Evans - Date: 2019-06-27 08:36:52 +0900 - - [ruby/date] Describe what is meant by valid in the Date.valid_date? rdoc - - https://github.com/ruby/date/commit/8eca79d1f0 - -commit f75561b8d455e1cf92dac8ac8838fdafc88cba71 - Author: Koichi Sasada - Date: 2019-07-22 17:01:31 +0900 - - constify RHash::ifnone. - - RHash::ifnone should be protected by write-barriers so this field - should be const. However, to introduce GC.compact, the const was - removed. This commit revert this removing `const` and modify - gc.c `TYPED_UPDATE_IF_MOVED` to remove `const` forcely by a type cast. - -commit d1c2b1969814fee14a01296aa2867abd07f70d04 - Author: Nobuyoshi Nakada - Date: 2019-07-22 13:51:14 +0900 - - Fixed exception message - -commit f6461fa890fa12501fe1696a36ab2cca036477ff - Author: Nobuyoshi Nakada - Date: 2019-07-22 12:31:40 +0900 - - Only the first argument can be --test-target-dir option - - Raise the proper exception when that option is not given but - non-option argument is. - -commit 463092b84da7933f307cc8747f948f68ef19f5fd - Author: Hiroshi SHIBATA - Date: 2019-07-22 11:05:34 +0900 - - Update rake-12.3.3. - -commit f6a7b10afa6f90a43df0bb336dfac05d38accf1e - Author: git - Date: 2019-07-22 10:10:51 +0900 - - * 2019-07-22 - -commit 28ae30b6ac0616ce3a7742d311d22909ee200dd8 - Author: Nobuyoshi Nakada - Date: 2019-07-22 10:10:28 +0900 - - Run test-tool in the order of the tests - -commit 08ea9240437bd866ae1169a91010d7767a22c9c1 - Author: Yusuke Endoh - Date: 2019-07-21 22:30:15 +0900 - - common.mk: `make check` now includes `make test-tool` - - And `make test-tool` includes `make test-testframework`. - - This change may be arguable because I'm unsure who is an intended user - of `make check`: a normal user, or Ruby-core developer. Normal users - don't have to run `make test-tool` for testing their installation, but - Ruby committers should run it before they commit anything. - - In this case, I'd be conservative; `make check` includes `test-tool`. - If normal users often report a failure of `make test-tool`, then we can - consider to split `make check` for two sets of target users. - -commit 24712eeec39f5e9a11cfc2b940358403cda4f2b6 - Author: Yusuke Endoh - Date: 2019-07-21 19:19:08 +0900 - - tool/test/runner.rb: support --test-target-dir option - - tool/test/runner.rb had been copied from test/runner.rb. - test/runner.rb was for `make test-all`, and tool/test/runner.rb was for - `make test-testframework` and `make test-tool`. - But I want to avoid the code clones. - - This change makes tool/test/runner.rb support --test-target-dir option - which allows tool/test/runner.rb to run `make test-all`. - Now we can remove test/runner.rb. - -commit 523fec8a4baec1e2a9c1adc0095646b12aa6c76c - Author: git - Date: 2019-07-21 09:47:57 +0900 - - * 2019-07-21 - -commit d285579ea796c0a9132cade07de4ffb6bae137e9 - Author: Hiroshi SHIBATA - Date: 2019-07-21 09:46:49 +0900 - - Update simplecov and doclie to the latest version. - -commit c584dd8460bdbb78b0e5ab47a1c15b2df2c45ded - Author: Samuel Williams - Date: 2019-07-20 16:44:49 +0900 - - Move travis coroutine check to cron only. - -commit e7b5b9144a8931af7510c7bc95c798df75af9499 - Author: Takashi Kokubun - Date: 2019-07-20 15:44:10 +0900 - - --debug was not functional either - - Even after 19d592dc82a31adf0bb6f027392cae69615c2394, the retry seems not - functional. Let's just add --debug from the beginning because an output - of each step is collapsed and we don't see `make up` output so often. - -commit 81fc3becc7b883571e5c716f4fdc490d107ad990 - Author: Yusuke Endoh - Date: 2019-07-20 15:42:59 +0900 - - file.c: add a NORETURN declaration for statx_notimplement - - clang complains the lack. - -commit 1392b821b99dacb4d4da5081640cfe7a4fb866f4 - Author: Takashi Kokubun - Date: 2019-07-20 15:32:36 +0900 - - Explain what's benchmark/lib/load.rb [ci skip] - - I'm actually not using this, but ko1 is. - -commit 56b957e88a015a6feb9401a57634d72f367df3be - Author: Takashi Kokubun - Date: 2019-07-20 15:27:57 +0900 - - Upgrade benchmark-driver.gem again - - because v0.14.18 was actually not working with `make run`. - In `make run`, `Gem` is defined but `Gem::Version` isn't. - v0.14.19 checks `defined?(Gem::Version)` instead of `defined?(Gem)`. - -commit 8a38eff2bd6338be412c8ef82e1bc50032c9f88f - Author: Takashi Kokubun - Date: 2019-07-20 15:13:02 +0900 - - Upgrade benchmark-driver.gem version - - This is to make `make run` with benchmark/lib/load.rb work for ko1 - https://github.com/benchmark-driver/benchmark-driver/compare/v0.14.17...v0.14.18 - -commit 77bb79b8cf69f6504bf0abe2e07a1a631cc4ef32 - Author: Yusuke Endoh - Date: 2019-07-20 09:08:34 +0900 - - array.c: factor out a complex condition of assert - - ARY_SHARED_P and ARY_EMBED_P included: - - assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), - - The two predicate macros are used in many other assert conditions, - which caused memory bloat during C compilation. - This change factors out the assertion above to a function. - Now gcc consumes 160 MB instead of 250 MB to compile array.c. - -commit d304f77c585c42a2e8b008d170ac153b7d8e5243 - Author: Aaron Patterson - Date: 2019-07-20 07:12:02 +0900 - - Only disable GC around reference updating - - This is the only place that can change the size of the object id tables - and cause a GC. - -commit c945d115a55710089ac23027c74ed32a40cd9e50 - Author: Jeremy Evans - Date: 2019-07-20 03:36:12 +0900 - - Document use of ensure and else at method level [ci skip] - -commit ceeb1535dd6f618ac6069415a69be6d8b2916450 - Author: Jeremy Evans - Date: 2019-07-20 03:23:00 +0900 - - Remove section on performance advantage of not using a block parameter [ci skip] - - Improvements in Ruby 2.5 and 2.6 make this section no longer - accurate. - -commit 7e2677675d76551a8a7abdba3fed350056640492 - Author: Jeremy Evans - Date: 2019-07-20 03:20:08 +0900 - - Remove mention of Proc.new with implicit block [ci skip] - - This support is now deprecated and will be removed in Ruby 3. - -commit bf2f84b2ff298583d3efbecb88da271e99fa7930 - Author: Jeremy Evans - Date: 2019-07-20 03:18:23 +0900 - - Document evaluation order of arguments [ci skip] - - Fixes [Misc #8905] - -commit 71d21f3c750f41ab44e618162515bd9e4a9f289e - Author: Jeremy Evans - Date: 2019-07-20 01:58:20 +0900 - - Document required keyword argument syntax [ci skip] - - Fixes [Bug #8952] - -commit 57b7bfad9e6421fb8387698908e06dcf363df213 - Author: git - Date: 2019-07-20 02:54:41 +0900 - - * 2019-07-20 - -commit de18328192de61be6f510c7402e1d7bd23efef6a - Author: aycabta - Date: 2019-07-20 02:53:40 +0900 - - Some keywords, "true", "false", and "nil" should be treated as a variable - -commit 0a16ff9f8366fd0d751191bd9c6eaa47f0ae33c8 - Author: Yusuke Endoh - Date: 2019-07-19 23:50:30 +0900 - - array.c: use assert in macro instead of in a function - - The old code lost information of lineno. Now, an assertion error will - output a correct lineno (but now gcc 8 requires 250 MB, unfortunately). - -commit 3e8d4ff3e571bd556898efd94badb66a5dadf4d2 - Author: Yusuke Endoh - Date: 2019-07-19 23:41:24 +0900 - - array.c: factor out `assert(RB_TYPE_P(ary, T_ARRAY))` to a function - - The assertion blows up gcc 8 by consuming approx. 1.8 GB memory. - This change reduces the amount of memory required to about 200 MB. - - A follow-up of ae750799c1b28b06d02e50cd26450b9903516526. - -commit 0a7093a8e9277d9f459b2c14f2eade02eed15e28 - Author: Samuel Williams - Date: 2019-07-19 17:18:42 +0900 - - Add documentation to `fiber_pool_allocate_memory`. - -commit 517f7f9b578f8f48ce80dfbe5c8e61b4f8ebd1d4 - Author: Samuel Williams - Date: 2019-07-19 17:09:03 +0900 - - Fix 32-bit build and typo. - - "Therefore, `fiber_pool_stack_free(&vacancy->stack)` can do the wrong - thing..." should be "... `fiber_pool_stack_free(stack)` ...". - -commit e004afd46d3bd27bda4c4922eadcf11c7e4bfc55 - Author: Samuel Williams - Date: 2019-07-19 16:42:00 +0900 - - Ensure that madvise does not clobber vacancy data. - - After calling `fiber_pool_vacancy_reset`, `vacancy->stack` and `stack` are - no longer in sync. Therefore, `fiber_pool_stack_free(&vacancy->stack)` can - do the wrong thing and clobber the vacancy data. - - Additionally, when testing using VM_CHECK_MODE > 0, use MADV_DONTNEED if - possible, to catch issues w.r.t. clobbered vacancy data earlier. - -commit fba3e76e3fded3534a34b21412c17af2b02a5f3d - Author: Koichi Sasada - Date: 2019-07-19 16:24:14 +0900 - - fix debug counter for Hash counts. - - Change debug_counters for Hash object counts: - - * obj_hash_under4 (1-3) -> obj_hash_1_4 (1-4) - * obj_hash_ge4 (4-7) -> obj_hash_5_8 (5-8) - * obj_hash_ge8 (>=8) -> obj_hash_g8 (> 8) - - For example on rdoc benchmark: - - [RUBY_DEBUG_COUNTER] obj_hash_empty 554,900 - [RUBY_DEBUG_COUNTER] obj_hash_under4 572,998 - [RUBY_DEBUG_COUNTER] obj_hash_ge4 1,825 - [RUBY_DEBUG_COUNTER] obj_hash_ge8 2,344 - [RUBY_DEBUG_COUNTER] obj_hash_empty 553,097 - [RUBY_DEBUG_COUNTER] obj_hash_1_4 571,880 - [RUBY_DEBUG_COUNTER] obj_hash_5_8 982 - [RUBY_DEBUG_COUNTER] obj_hash_g8 2,189 - -commit ae750799c1b28b06d02e50cd26450b9903516526 - Author: Koichi Sasada - Date: 2019-07-19 14:37:59 +0900 - - Use FL_TEST_RAW() to check flags. - - FL_TEST() uses FL_ABLE() which test data types. However, - in array.c we don't need to check it (all of them should be - T_ARRAY), so I changed from FL_TEST() to FL_TEST_RAW() which - does not check FL_ABLE(). Instead of FL_ABLE(), add assertion - to check given object is a T_ARRAY object. - - For example, rb_ary_free() becomes slim: - - with FL_TEST(): - 0000000000006a30 : - 6a30: 40 f6 c7 07 test $0x7,%dil - 6a34: 48 8b 07 mov (%rdi),%rax - 6a37: 75 09 jne 6a42 - 6a39: 48 f7 c7 f7 ff ff ff test $0xfffffffffffffff7,%rdi - 6a40: 75 1e jne 6a60 - 6a42: a9 00 00 00 02 test $0x2000000,%eax - 6a47: 74 07 je 6a50 - 6a49: f3 c3 repz retq - 6a4b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) - 6a50: 48 8b 7f 20 mov 0x20(%rdi),%rdi - 6a54: e9 00 00 00 00 jmpq 6a59 - 6a59: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) - 6a60: 89 c2 mov %eax,%edx - 6a62: 83 e2 1f and $0x1f,%edx - 6a65: 83 fa 1b cmp $0x1b,%edx - 6a68: 74 d8 je 6a42 - 6a6a: f6 c4 60 test $0x60,%ah - 6a6d: 74 d3 je 6a42 - 6a6f: eb d8 jmp 6a49 ``` - - with FL_TEST_RAW(): - 0000000000006a30 : - 6a30: 48 f7 07 00 60 00 02 testq $0x2006000,(%rdi) - 6a37: 74 07 je 6a40 - 6a39: f3 c3 repz retq - 6a3b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) - 6a40: 48 8b 7f 20 mov 0x20(%rdi),%rdi - 6a44: e9 00 00 00 00 jmpq 6a49 - -commit a44ad9a1451eb86385339cfd72713ff764f1c820 - Author: git - Date: 2019-07-19 13:10:08 +0900 - - * expand tabs. - -commit 182ae1407b3f6597cdbf6872f788c1ed3aa22a35 - Author: Koichi Sasada - Date: 2019-07-19 13:02:38 +0900 - - fix shared array terminology. - - Shared arrays created by Array#dup and so on points - a shared_root object to manage lifetime of Array buffer. - However, sometimes shared_root is called only shared so - it is confusing. So I fixed these wording "shared" to "shared_root". - - * RArray::heap::aux::shared -> RArray::heap::aux::shared_root - * ARY_SHARED() -> ARY_SHARED_ROOT() - * ARY_SHARED_NUM() -> ARY_SHARED_ROOT_REFCNT() - - Also, add some debug_counters to count shared array objects. - - * ary_shared_create: shared ary by Array#dup and so on. - * ary_shared: finished in shard. - * ary_shared_root_occupied: shared_root but has only 1 refcnt. - The number (ary_shared - ary_shared_root_occupied) is meaningful. - -commit 547f574b639cd8586568ebb8570c51faf102c313 - Author: Samuel Williams - Date: 2019-07-19 13:03:47 +0900 - - In some situations, `vm_stack` can be NULL, but `cfp` is valid. - -commit e14f5762c532241706ad5bd8f81b520c46d97654 - Author: Samuel Williams - Date: 2019-07-19 12:55:34 +0900 - - Add assertions to `coroutine_initialize_main`. - -commit dd0e33f0839124a910f4eb0bb67423e041036645 - Author: Samuel Williams - Date: 2019-07-19 12:53:47 +0900 - - Split assertions to check which one fails. - -commit cf93f98a609d8a48e3b69790bc38ae9edf8aa687 - Author: Samuel Williams - Date: 2019-07-19 12:45:44 +0900 - - Better usage of `rb_ec_clear_vm_stack` to maintain invariants. - -commit 6eef80d824aa4aca91ff13ea215f5cd053d16906 - Author: Samuel Williams - Date: 2019-07-19 11:54:31 +0900 - - Improve ec assertions. - -commit 63160a84b42cd3a7924e5abe94bbb08bb566f24b - Author: Koichi Sasada - Date: 2019-07-19 12:04:32 +0900 - - respect NDEBUG. - - ruby/ruby.h includes ruby/assert.h, and RUBY_NDEBUG is defined - by checking NDEBUG. In other words, NDEBUG is only seen just - after ruby/ruby.h. This patch also checks NDEBUG just after - including ruby_assert.h. - - Without this patch, assertions in array.c are always enabled. - -commit e644e2de85d0d76e1c28d45710f765757a22f5c6 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-19 09:00:55 +0900 - - Remove doc/etc.rd.ja [ci skip] - - [Feature #16003] [ruby-dev:50814] - -commit 4ec5b39ce8bd3b13dec0ac290b2d7d29c640b304 - Author: Koichi Sasada - Date: 2019-07-19 08:53:19 +0900 - - initialize only Fiber's cfp. - - fiber->cont.saved_ec.cfp should be initialized by NULL - because no vm_stack is allocated. However, cont_init() - captures current Fiber's cfp for continuation, so it should - only initialize fibers. - -commit 8ca32020b03a4f3e69c8f0b15e015eb7ad5d8e05 - Author: Samuel Williams - Date: 2019-07-19 08:32:40 +0900 - - Revert "Ensure cfp is initialized to NULL." - - This reverts commit d7fdf45a4ae1bcb6fac30a24b025d4f20149ba0a. - -commit c8ee44f44c0c7d333a33c62c811d1d0cdbc3554a - Author: aycabta - Date: 2019-07-19 08:23:37 +0900 - - Fix showing doc of "nil.to_s", nil doesn't have #name - -commit d7fdf45a4ae1bcb6fac30a24b025d4f20149ba0a - Author: Samuel Williams - Date: 2019-07-19 08:09:52 +0900 - - Ensure cfp is initialized to NULL. - - `cont_init` didn't initialize `cont->saved_ec.cfp`. Calling `cont_mark` - would result in an invalid `cfp` in `rb_execution_context_mark`. Because - fibers lazy-initialize the stack, fibers that are created but not resumed - could cause this problem to occur. - -commit 9dda0a03cc19d0ca20fc8fc220760e37cb5b9f02 - Author: Samuel Williams - Date: 2019-07-19 08:00:58 +0900 - - Remove `rb_vm_push_frame` as it is no longer used. - -commit fd461dea06b1a56eca9d1c662c3dc0c416c9e495 - Author: Nobuyoshi Nakada - Date: 2019-07-19 07:55:40 +0900 - - Ripper#validate_object: check if the object is hidden - -commit 0b826418af2a96b0e3a24a8b871996962efb6127 - Author: Nobuyoshi Nakada - Date: 2019-07-19 07:51:48 +0900 - - Update before commit - -commit 59d6ce4f4bf2d77dfd07975fed6a49609c2df97e - Author: Nobuyoshi Nakada - Date: 2019-07-19 07:48:55 +0900 - - Moved RIPPER_DEBUG methods to Ripper from Kernel - -commit 18bce998ddbcf1266d53071a5d46a9e71950f0ea - Author: Nobuyoshi Nakada - Date: 2019-07-19 07:48:30 +0900 - - Fixed build error with RIPPER_DEBUG - -commit d4c4029597d575aa9820698b5be7594b642b024f - Author: git - Date: 2019-07-19 06:40:24 +0900 - - * 2019-07-19 - -commit a036a8a038820660a6903af60376a2df502d0266 - Author: Nobuyoshi Nakada - Date: 2019-07-19 06:15:47 +0900 - - Adjust styles and indents - -commit a027c4b5b0bc1d6786852249847e8a2f56404d1a - Author: Nobuyoshi Nakada - Date: 2019-07-19 06:15:05 +0900 - - Use Qnull instead of 0 and Qundef - -commit d40d8b3caf40e0b1769bb4a196aa7740aef4737e - Author: Koichi Sasada - Date: 2019-07-18 22:59:44 +0900 - - check saved_ec.cfp - -commit 9790b778a339f36f9b29517a1d762cf02a2f0293 - Author: Samuel Williams - Date: 2019-07-18 21:33:03 +0900 - - Ensure we don't have dangling cfp. - -commit 78bc6cd8dff9ee584a447251490c88ee035d218d - Author: git - Date: 2019-07-18 17:55:22 +0900 - - * remove trailing spaces. - -commit 38e3c65a33aa7bcd4cee922487e259a8da699831 - Author: Samuel Williams - Date: 2019-07-18 16:02:16 +0900 - - Improve `fiber_pool_expand` allocation strategy. - - If `mmap` fails to allocate memory, try half the size, and so on. - - Limit FIBER_POOL_ALLOCATION_MAXIMUM_SIZE to 1024 stacks. In typical - configurations this limits the memory mapped region to ~128MB per - allocation. - -commit 311007bf403160b978e015997ad5076a229290da - Author: Samuel Williams - Date: 2019-07-16 13:35:55 +0900 - - Add experimental `RUBY_SHARED_FIBER_POOL_FREE_STACKS` to control madvise. - -commit 56fcf988495ec1b36655534f4cc2ae786e2ab8c5 - Author: Samuel Williams - Date: 2019-07-16 13:35:27 +0900 - - Add note about setting `vm.max_map_count` for Linux. - -commit 001f187ed6539f320421d8893d2f3c8f584cc3a5 - Author: Samuel Williams - Date: 2019-07-16 13:11:55 +0900 - - Make fiber_pool more conservative on platforms with limited address space. - - We use COROUTINE_LIMITED_ADDRESS_SPACE to select platforms where address - space is 32-bits or less. Fiber pool implementation enables more book - keeping, and reduces upper limits, in order to minimise address space - utilisation. - -commit 385ea910fc28f0e46c72669a260e44d4f3f37d9e - Author: Samuel Williams - Date: 2019-07-16 13:00:35 +0900 - - Add `struct fiber_pool {int free_stacks;}` to control usage of madvise. - - `madvise(free)` and similar operations are good because they avoid swap - usage by clearing the dirty bit on memory pages which are mapped but no - longer needed. However, there is some performance penalty if there is no - memory pressure. Therefore, we do it by default, but it can be avoided. - -commit 4d60a5820ae2c7bc2ce5bee441b834129a3a56e1 - Author: Samuel Williams - Date: 2019-07-16 09:49:14 +0900 - - Add FIBER_POOL_ALLOCATION_FREE to control allocation/free strategy. - -commit 8ac9a7be0fea95d9fc17cce53c0d18d70cc8d091 - Author: Samuel Williams - Date: 2019-07-12 10:42:34 +0900 - - Limit expansion of fiber pool on 32-bit platforms. - - On 32-bit platforms, expanding the fiber pool by a large amount may fail, - even if a smaller amount may succeed. We limit the maximum size of a single - allocation to maximise the number of fibers that can be allocated. - - Additionally, we implement the book-keeping required to free allocations - when their usage falls to zero. - -commit 77f3319071e600a2aafaa9863b892dfd3c1da343 - Author: Samuel Williams - Date: 2019-07-11 16:17:34 +0900 - - Enable `madvise` to release stack space back to OS. - -commit 47c0cab248ca09deb9508ff29edfd1dfc11b5f31 - Author: Samuel Williams - Date: 2019-07-01 13:24:39 +0900 - - Add details of fiber pool and coroutine selection to NEWS. - -commit b8242bce2301e33d3ba1fae95b68a291cc3004b5 - Author: Samuel Williams - Date: 2019-06-29 21:21:19 +0900 - - Add `ucontext` and `copy` coroutine implementations to test matrix. - -commit 7291fef55c90b9ab6b3c22018b16972861b98c9d - Author: Samuel Williams - Date: 2019-06-29 10:07:07 +0900 - - Improve build process and coroutine implementation selection. - -commit 91aae651bf90be46773a246e4c46b9e221353fbd - Author: Samuel Williams - Date: 2019-06-27 15:59:25 +0900 - - Stack copying implementation of coroutines. - -commit 8779382da44723438eb6cae23bd7267990157433 - Author: Samuel Williams - Date: 2019-06-19 21:13:49 +0900 - - Remove unused vm_stack recycling. - -commit 14cf95cff35612c6238790ad2f605530f69e9a44 - Author: Samuel Williams - Date: 2019-06-02 09:49:58 +0900 - - Implement fiber pool for reduced fiber allocation overhead. - - Replace previous stack cache with fiber pool cache. The fiber pool - allocates many stacks in a single memory region. Stack allocation - becomes O(log N) and fiber creation is amortized O(1). Around 10x - performance improvement was measured in micro-benchmarks. - -commit 1b82c877dfa72e8505ded149fd0e3ba956529d3f - Author: Samuel Williams - Date: 2019-06-01 14:48:25 +0900 - - Make FIBER_USE_NATIVE the default and reformat code. - -commit 97808e29cd5691092ad9004078852b3f16592cf2 - Author: git - Date: 2019-07-18 08:15:46 +0900 - - * 2019-07-18 - -commit 9b28eefeb2cea9690b897aeb3a1e1de2cbc19137 - Author: Samuel Williams - Date: 2019-07-18 08:13:49 +0900 - - Add benchmark to help diagnose performance regression. - - See https://bugs.ruby-lang.org/issues/16009 for more details. - -commit bdec1ad9a96700eb00ab953ea6ee2168449827d9 - Author: git - Date: 2019-07-17 23:42:21 +0900 - - * expand tabs. - -commit 416ead4cdaf849fe1f3dcda26d6ba04c80e36746 - Author: Yusuke Endoh - Date: 2019-07-17 08:24:25 +0900 - - compile.c: add NO_CHECK for the calls to COMPILE whose result is unused - - to suppress many warnings of Coverity Scan - -commit 0e23e0c3a0c1053c230205117b82cc8156f3a26a - Author: Nobuyoshi Nakada - Date: 2019-07-17 15:55:50 +0900 - - Adjust indent [ci skip] - -commit cd372f8db2e050241abf1d7360b7b29ac614ceec - Author: Nobuyoshi Nakada - Date: 2019-07-17 14:45:33 +0900 - - Get rid of LoadError with $DEBUG - -commit af07e07ac9331ec9c2f16b2329a0471ea663dd95 - Author: Nobuyoshi Nakada - Date: 2019-07-17 11:56:40 +0900 - - Separate pull-github from merge-github [ci skip] - -commit 0965bb6091a70d5237a8afd88d414b2d7fc9f5a8 - Author: git - Date: 2019-07-17 10:53:00 +0900 - - * 2019-07-17 - -commit f487e5b7a4b13d23a8bb7807e4f5cc3f9b2a30e3 - Author: Nobuyoshi Nakada - Date: 2019-07-16 21:47:32 +0900 - - Expanded buf to copy at once - - Build dumped string from base packed data and extended year at - once. Although currently ruby_marshal_write_long() never writes - more than 5 bytes per its format specification, allocate - `sizeof(long)+1` for the sanitation. - -commit ed2f2b4f98800540024b9c4a5ebde98674889013 - Author: Nobuyoshi Nakada - Date: 2019-07-16 22:39:39 +0900 - - Named the backward compatible dump size - -commit 6ab95fb741168895f9aebe8d6c45e5242cc81f2b - Author: Nobuyoshi Nakada - Date: 2019-07-16 22:00:54 +0900 - - Removed twisted tests - - Why does only Process.daemon have these tests? - -commit d45d448d71bfe9db4a71e06289e7b4d640bbd55c - Author: Nobuyoshi Nakada - Date: 2019-07-16 21:38:25 +0900 - - nil as the default of optional parameters - -commit d8e23a67c3869c70ef82b4337499367632ce911a - Author: Nobuyoshi Nakada - Date: 2019-07-16 19:27:22 +0900 - - nil as the default of optional parameters - -commit e988048e2589b6f517c11430d568e2ccf118e901 - Author: Nobuyoshi Nakada - Date: 2019-07-16 18:47:35 +0900 - - Moved the check for `exception` to rb_execarg_addopt - - Check for `exception` option in rb_execarg_addopt, as well as - other options. And then raise a particular ArgumentError if it is - not allowed. - -commit 8deabcd3280f6042ea1ed14b629d70680e081fec - Author: Nobuyoshi Nakada - Date: 2019-07-16 18:42:56 +0900 - - Constified afamily functions - -commit 19d592dc82a31adf0bb6f027392cae69615c2394 - Author: Nobuyoshi Nakada - Date: 2019-07-16 18:41:11 +0900 - - Somehow `if` didn't work - -commit 76c6cf2cbc549dead57725ccd934a42df5bc150d - Author: Nobuyoshi Nakada - Date: 2019-07-16 17:23:43 +0900 - - Print debugging information when updating failed - -commit 75fb0a9afad1685cedee9c7665a7f30ec95068fc - Author: Nobuyoshi Nakada - Date: 2019-07-16 09:30:58 +0900 - - Allow mday in Date.iso8601 to be omitted - - [Bug #12285] - -commit e2f987e65461bff85be2146dda93655b7d13a537 - Author: git - Date: 2019-07-16 09:22:11 +0900 - - * expand tabs. - -commit 00dc0dae0d7b247a917f5b676a777db86cdf1f3a - Author: Nobuyoshi Nakada - Date: 2019-07-16 08:48:57 +0900 - - Removed intermediate local variables - -commit 8e37ef76f6f640178ffaea4d7c0d36a17e6ca171 - Author: Nobuyoshi Nakada - Date: 2019-07-16 08:46:38 +0900 - - Fixed the library path for tools - -commit 71d5b4c32e892d1771d73ca869da3a59f5d0b4d1 - Author: Nobuyoshi Nakada - Date: 2019-07-16 08:25:39 +0900 - - Fixed the library path for tools - -commit ca524bcd494e2f284c3211cad8e8dde70e8aa86a - Author: Nobuyoshi Nakada - Date: 2019-07-16 08:15:05 +0900 - - Expanded f_numerator - -commit 34019a22eb41206e3d5d1ac29b3874275aa7f71c - Author: Nobuyoshi Nakada - Date: 2019-07-16 07:58:47 +0900 - - Expanded f_denominator - -commit 325d546d627f3cfb50c0371775f671cd88521c49 - Author: git - Date: 2019-07-16 07:19:56 +0900 - - * 2019-07-16 - -commit a8e4b7b12f348d5fdde4ba360a68d10c0f2689bf - Author: git - Date: 2019-07-16 07:19:52 +0900 - - * expand tabs. - -commit c184a1c261209da403db553eef7f7353f7ee5edd - Author: Yusuke Endoh - Date: 2019-07-16 07:18:54 +0900 - - compile.c: add NO_CHECK for the calls to COMPILE whose result is unused - - to suppress many warnings of Coverity Scan - -commit 6aab77a7a3e29a82006878f87e24ed30fa985a1f - Author: Yusuke Endoh - Date: 2019-07-16 07:17:57 +0900 - - Add a /* fall through */ comment - -commit 0c6c937904aafc1809386bd892a2d114d22d01fe - Author: Nobuyoshi Nakada - Date: 2019-07-15 19:31:48 +0900 - - Removed duplicate highlighting - -commit b452c03a14f943ae25338547bd680fce67399d85 - Author: Nobuyoshi Nakada - Date: 2019-07-15 17:45:37 +0900 - - Always evaluate the expression RUBY_ASSERT_MESG_WHEN just once - -commit c20445ab561b6b74bc60787b7c7f69795986e4a3 - Author: aycabta - Date: 2019-07-15 17:20:48 +0900 - - Require Ruby 2.4 or later because needs lex_state from Ripper - -commit c781b1b7a3d112c6f9b2521c4ff2c5408a429a72 - Author: Nobuyoshi Nakada - Date: 2019-07-15 17:06:35 +0900 - - update-deps for dependencies - -commit 5a42dca6887203ebba3532f4430c17d3a73a6169 - Author: git - Date: 2019-07-15 16:51:18 +0900 - - * expand tabs. - -commit 5e0d27a32f2b3f1242c9990acf83b7970b37bbce - Author: Nobuyoshi Nakada - Date: 2019-07-15 16:44:07 +0900 - - Removed dead code - - If `emesg` is `Qundef`, it is not a message string and then `elen` - (the length of the message) is 0. So `emesg` cannot be `Qundef` in - the `elen != 0` block. Pointed out by Coverity Scan. - -commit de0f192444e3822968d04cdea6e868bd42ccfa7f - Author: aycabta - Date: 2019-07-15 16:25:50 +0900 - - Add features of IRB to NEWS - -commit 574e8a6812aea072acbf55970f7ff2e32ed4e599 - Author: aycabta - Date: 2019-07-15 15:49:59 +0900 - - Add Reline section to NEWS - -commit 3a1d3556e2ae5f6083dbd8b97e5b3009eaceaab3 - Author: aycabta - Date: 2019-07-15 15:45:51 +0900 - - Fix a typo of Markdown of NEWS - -commit f73ea3342b5abd3136a1fb27fc0fdbe4039bc3bf - Author: Hiroshi SHIBATA - Date: 2019-07-15 15:07:26 +0900 - - Fixed ruby/spec for Logger::LogDevice changes. - -commit 5349aa23c8ad23786d25c1e18a3f541de06f4700 - Author: Hiroshi SHIBATA - Date: 2019-07-15 14:47:29 +0900 - - Also fixed up with 036039c8a29d3d8045207c111f9bbc481c904998 - -commit 036039c8a29d3d8045207c111f9bbc481c904998 - Author: Hiroshi SHIBATA - Date: 2019-07-15 14:45:05 +0900 - - Fixed LoadError of version file. - -commit f103ed8b7dae9ba9cb1d8dcc71164c972a4ebccd - Author: git - Date: 2019-07-15 14:43:39 +0900 - - * expand tabs. - -commit 4b345f9d4bbff2cfc9895155fb0e8f90d1cac816 - Author: Yusuke Endoh - Date: 2019-07-15 14:42:22 +0900 - - compile.c: ignore the result of COMPILE by marking with NO_CHECK - - to suppress many warnings of Coverity Scan - -commit 0eafa1dce86be0e2f86a029271ec24cf6b577fad - Author: Hiroshi SHIBATA - Date: 2019-07-15 14:41:22 +0900 - - Fixed inconsitency locations of default gems. - -commit 1b59ed9b494104d3a571bb222ee843cd82d1c9ba - Author: Hiroshi SHIBATA - Date: 2019-07-15 14:39:10 +0900 - - Move helper file of logger to under the test/logger. - -commit 58065b87018a9d1ed972b8c856004bf75728da02 - Author: Rafael Mendonça França - Date: 2019-06-05 07:07:26 +0900 - - [ruby/logger] Add option to set the binary mode of the log device - - Without binmode strings with incompatible encoding can't be written in - the file. This is very common in applications that log user provided - parameters. - - We need to allow changing the binnary mode because right now it is impossible to use - the built-in log rotation feature when you provide a File object to the - LogDevice, and if you provide a filename you can't have binmode. - - https://github.com/ruby/logger/commit/9114b3ac7e - -commit f4064a0a0c24734b1ec98e6e2dbdf5e38e856c41 - Author: Jeremy Evans - Date: 2019-05-17 09:35:21 +0900 - - [ruby/logger] Set filename when initializing logger with a File object - - This should allow reopen to work. Requested in ruby issue #14595. - - https://github.com/ruby/logger/commit/bd367aff12 - -commit 2c22051b4b54482531e43915f5edef0c3d3a053b - Author: Samuel Williams - Date: 2019-03-21 12:58:17 +0900 - - [ruby/logger] Enable `frozen_string_literal: true` in `logger.rb`. - - https://github.com/ruby/logger/commit/2dc832e901 - -commit 3fdb963827fde7fbe1837763cb834842b8336fee - Author: Samuel Williams - Date: 2019-03-21 08:35:29 +0900 - - [ruby/logger] Prefer require_relative, it's a little bit faster. - - https://github.com/ruby/logger/commit/1e2aab4bea - -commit 7ef08562871ca6d209415f16f942f6cd2a67df54 - Author: sonots - Date: 2019-03-18 20:56:29 +0900 - - [ruby/logger] Update logger.gemspec - - https://github.com/ruby/logger/commit/1335a71d98 - -commit 7f10da9d2762d1b6d0f3c45df4a23bbdc2d78e4c - Author: sonots - Date: 2019-03-18 21:02:02 +0900 - - [ruby/logger] require 'logger/errors' just for compat - - https://github.com/ruby/logger/commit/255a51dc10 - -commit bbe157f34046ec9ef81e6ad9ed37c86a0d9155e4 - Author: Colby Swandale - Date: 2018-12-12 12:08:35 +0900 - - [ruby/logger] split logger classes/modules into separate files - - https://github.com/ruby/logger/commit/f10ce9fff2 - -commit 136196785b10f7cffa1e4d557bc3bcc0e863813a - Author: sonots - Date: 2019-03-18 19:34:01 +0900 - - [ruby/logger] Fix to use logger and test-unit in this repo with - - `ruby test/logger/test_xxx.rb` - - https://github.com/ruby/logger/commit/d3c2402340 - -commit 47500f2055467d0c72c7ce53b2535d7610347fb0 - Author: Samuel Williams - Date: 2019-03-15 08:12:11 +0900 - - [ruby/logger] Add support for changing severity using bang methods. - - https://github.com/ruby/logger/commit/ae4c6dfcbb - -commit 310198d6be1ca5dc2f1279096d7134a02ee3d8ec - Author: Samuel Giddins - Date: 2019-01-18 03:13:20 +0900 - - [ruby/logger] Add missing closing " - https://github.com/ruby/logger/commit/b4b3caae40 - -commit 227eae79acde90e7c3ba171dbf4bdcedbb39a9f2 - Author: Samuel Giddins - Date: 2019-01-18 02:59:55 +0900 - - [ruby/logger] Say that logger requires ruby >= 2.3 - - Since it uses `&.`, it can't be used on older rubies - https://github.com/ruby/logger/commit/b872f90ab9 - -commit b9ba07a05c48176bfbba44133a9f3a43f387bedd - Author: Colby Swandale - Date: 2018-12-13 18:45:08 +0900 - - [ruby/logger] dont lock bundler to a specific version in travis - - https://github.com/ruby/logger/commit/eb5ac229a5 - -commit 99c14fb69491d52c474c3f303405e6f59b41034f - Author: Colby Swandale - Date: 2018-12-12 09:27:26 +0900 - - [ruby/logger] remove files that dont need to be included in gem releases - - https://github.com/ruby/logger/commit/9a3be8650f - -commit 3dc212896c422add43c850ee1d1a613c7cc96737 - Author: Koichi Sasada - Date: 2019-07-15 13:52:25 +0900 - - check return value of blocking_region_begin(). - - blocking_region_begin() can return FALSE if it fails to acquire - GVL, so check it. - -commit e4c1b199961cc5fa34c02b2225bbc14b75259fd2 - Author: Tanaka Akira - Date: 2019-07-15 14:17:27 +0900 - - add tests for orphan/not-orphan proc/lambda. - -commit 711dfec3fa9623c5e8ef6f5ce3627f8f1a85f19d - Author: Yusuke Endoh - Date: 2019-07-15 14:07:22 +0900 - - parse.y (here_document): remove dead code - - str is always zero when evaluating the branch. - Found by Coverity Scan. - -commit 5353401c254a926426d9a289606fad18a755fcd2 - Author: Yusuke Endoh - Date: 2019-07-15 14:02:45 +0900 - - thread.c (rb_thread_shield_waiting_{inc,dec}): prefer long to int - - `(unsigned int)(THREAD_SHIELD_WAITING_MASK>>THREAD_SHIELD_WAITING_SHIFT)` - is 0xffffffff, and w > 0xffffffff is always true. - Coverity Scan pointed out this issue. - -commit 62f34bd1fe9630b0e760860017955cec2d5fbd0a - Author: Kazuhiro NISHIYAMA - Date: 2019-07-15 13:57:43 +0900 - - doc/globals.rdoc: Add deprecated to TRUE,FALSE,NIL [ci skip] - - They are warned since 2.4.0. - -commit 9c38904ead89df7c41243f7a23dde3d07f22bd86 - Author: Takashi Kokubun - Date: 2019-07-15 13:56:32 +0900 - - Use consistent fetchDepth for all jobs - - a7dd6763bd1dac7952ace46be58083dbea332a0a was not applied for all jobs. - -commit d1e2650aca8ba340d98af22a08be20baf0abde0e - Author: Takashi Kokubun - Date: 2019-07-15 13:47:28 +0900 - - Force-fetch unicode update only when it's needed - - nobu said that we could be banned if we aggressively downloaded unicode - file from Travis. - -commit 929fa856ef8a9217b58dc43c9883c3202603c18e - Author: Kazuhiro NISHIYAMA - Date: 2019-07-15 13:44:50 +0900 - - Add tool/leaked-globals to .gitattributes [ci skip] - -commit b401fb35a4196ba0229622a1bcdc5966f10e8e5d - Author: Hiroshi SHIBATA - Date: 2019-07-15 13:42:37 +0900 - - Removed needless LOAD_PATH modification. - - We can use require_relative now. - -commit 99afea5328c61d3f212bbb684b33abf0d814f080 - Author: Jeremy Evans - Date: 2019-06-21 02:21:34 +0900 - - Add bug triaging guide - - Implements [Misc #15943] - -commit badfbdf32c26f44b93687698b4dca9dd95f70a75 - Author: Hiroshi SHIBATA - Date: 2019-07-15 13:15:13 +0900 - - Move vpath.rb into tool library directory. - -commit bd494ae79b18e260b0123bf40ddc1c694d7b25b8 - Author: Tanaka Akira - Date: 2019-07-15 12:59:53 +0900 - - add tests for "break" in lambda. - -commit 8ac1c6eb4837f5d088b7fc0a6ee51a5723f728a9 - Author: Koichi Sasada - Date: 2019-07-15 12:05:55 +0900 - - respect RUBY_DEBUG too - -commit 76bad330aae4ee867585dda3e547e5db740fc0f3 - Author: Yusuke Endoh - Date: 2019-07-15 12:00:12 +0900 - - encoding.c (enc_table_expand): prefer xrealloc to realloc - - And raise an exception when failed to register an encoding - -commit c23e5976744f1984b309f0af724fbd8ddea2c56a - Author: Koichi Sasada - Date: 2019-07-15 11:27:38 +0900 - - respect RUBY_DEBUG. - - see RUBY_DEBUG for each debug options. - -commit d02f2fc3e2b4d14793c3b25079787a8972ce49c8 - Author: Hiroshi SHIBATA - Date: 2019-07-15 11:19:13 +0900 - - Added help message for test-tool target. - -commit ac6d137157121381fb57e3febd34c84cb7ca47b2 - Author: Hiroshi SHIBATA - Date: 2019-07-15 11:16:05 +0900 - - Added test-tool target for the test suite of tool/test files. - -commit 41c5f9a166637bf9e49af19b3fa94163b51db64d - Author: Hiroshi SHIBATA - Date: 2019-07-15 10:43:12 +0900 - - Put jisx0208.rb to under the library directory. - -commit 73346823e1119a8e72baefab381dbe822c4c01f7 - Author: Takashi Kokubun - Date: 2019-07-15 11:04:12 +0900 - - Try to prevent random build failure on Travis osx - -commit 226d569e5729bc9ffa5a516f88251d99f404c7c7 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-15 11:01:57 +0900 - - doc/irb/irb.rd.ja: Update options from `irb -h` [ci skip] - -commit a7fdb22373442bb25e687a8f2df36fb5b85d2846 - Author: Nobuyoshi Nakada - Date: 2019-07-15 11:00:16 +0900 - - Enable RUBY_ASSERT_MESG_WHEN when RUBY_DEBUG is turned on - -commit 05cc87df1b5f7a125e24d64058d9ad1f75cdfd3f - Author: Kazuhiro NISHIYAMA - Date: 2019-07-15 10:51:58 +0900 - - [DOC] Struct::Passwd#uclass renamed from #class at r2500 [ci skip] - -commit e2512cff05b1d1cc60a03ef4388cab07531877ca - Author: aycabta - Date: 2019-07-15 10:39:44 +0900 - - Move a test file of Reline to test/reline/ - -commit f326b4f4af4963e252d24c4f7d7099fc607db859 - Author: Koichi Sasada - Date: 2019-07-15 10:39:28 +0900 - - simplify around GC_ASSERT() - -commit dd4f128ac5fa26e3d8c4d003c770e69f9ed9a91e - Author: Takashi Kokubun - Date: 2019-07-15 10:38:59 +0900 - - Handle failure of opening a null device - - This issue is detected by Coverity Scan. - -commit a191009a266e97453971f9b24f750861855aaa7b - Author: Takashi Kokubun - Date: 2019-07-15 10:29:39 +0900 - - Simplify start_process by exploiting C99 - - Having a block for mixing a declaration was confusing. - Also I moved `dev_null` and `pid` to limit their scope. - -commit b78964883037470f25755db740c09e835eadb5c9 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-15 10:26:50 +0900 - - Change PROMPT_S of simple-prompt - - When input `"` or `/` with simple-prompt, - - Before: - `"` or `/` - (prompt disappeared and indent is changed) - - After: - `"> "` or `/> /` - (indent is unchanged since `>> `) - -commit f6f09cbc76c3e47aec23898e024ff5bb5f061bc4 - Author: Koichi Sasada - Date: 2019-07-15 10:19:25 +0900 - - introduce RUBY_ASSERT_ALWAYS(expr). - - RUBY_ASSERT_ALWAYS(expr) ignores NDEBUG (we cannot remove this - assertion). - -commit 0af897ab59dfa3d06724f898f17bbf8a1970abd1 - Author: aycabta - Date: 2019-07-15 10:20:07 +0900 - - Simplify history saving code - -commit eed9db39e51f08fa84cbc20ffc7496f93828c06d - Author: Hiroshi SHIBATA - Date: 2019-07-15 10:11:07 +0900 - - Followed up e8ddbc0239. - -commit 223854ebe858a96560faac239f4c0e40d1af3943 - Author: Koichi Sasada - Date: 2019-07-15 09:58:26 +0900 - - catch up e8ddbc0239. - -commit 08b340d2f68daf6bbaba9be77ee7c17150bd7adb - Author: Hiroshi SHIBATA - Date: 2019-07-15 09:39:22 +0900 - - Separate the assertions of ruby core tests from test/unit/assertions. - -commit e8ddbc0239b9dfa32787e93c6942f085e5c42b49 - Author: Hiroshi SHIBATA - Date: 2019-07-15 08:54:34 +0900 - - Put colorize to library directory. - - Same as 66299e7ca83d379d13abaa5411f3e0419334cabb - -commit 0a711b0edff6eaf978cfc17cdd6a7cc6c17c6686 - Author: Hiroshi SHIBATA - Date: 2019-07-15 08:34:24 +0900 - - Put vcs .rb to under the lib directory. - - Because it's the common library for tool files. - -commit 8f7884761e30c453287d73de6ea733d565635ebc - Author: Tanaka Akira - Date: 2019-07-15 09:36:52 +0900 - - The default charset of text/* media type is UTF-8. - - Thanks for the patch gareth (Gareth Adams). [Bug #15933] - - ------- - - Combines two small, but very related changes - - 1: Treat HTTPS the same as HTTP - - Previously, OpenURI followed guidance in RFC2616/3.7.1: - - > When no explicit charset parameter is provided by the sender, media - > subtypes of the "text" type are defined to have a default charset - > value of "ISO-8859-1" when received via HTTP. - - However this RFC was written before TLS was established and OpenURI was - never updated to treat HTTPS traffic the same way. So, HTTPS documents - received a different default to HTTP documents. - - This commit removes the scheme check so that all text/* documents - processed by OpenURI are treated the same way. - - In theory this processing gets applied to FTP URIs too, but there's no - mechanism in OpenURI for FTP documents to have Content-Type metadata - appended to them, so this ends up being a no-op. - - 2: Change default charset for text/* to UTF-8 - - Replaces the default ISO-8859-1 charset previously defined in RFC2616 (now - obsoleted) with a UTF-8 charset as defined in RFC6838. - - Fixes: https://bugs.ruby-lang.org/issues/15933 - -commit 00a97d94122c256f4abe9375d19eaeb0f2eca201 - Author: Takashi Kokubun - Date: 2019-07-15 09:35:45 +0900 - - Always call va_end in form_args() - - This issue is detected by Coverity Scan. - -commit ff3704031a6c23ae2020576c4fecbdc6b1c91246 - Author: Nobuyoshi Nakada - Date: 2019-07-15 09:26:57 +0900 - - Insert a newline before `=end` - - For a certain editor which cannot handle here-document properly. - -commit a1975790731e1e9081e41e05b43516065b7d950a - Author: Yusuke Endoh - Date: 2019-07-15 08:36:57 +0900 - - addr2line.c: clarify the type of integer expression - - to suppress Coverity Scan warning. - This expression converted uint8_t to int, and then int to unsigned long. - Now it directly converts uint8_t to unsigned long. - -commit 0a417248a0ba6e4e5093f916dbf9b31e22f24078 - Author: Takashi Kokubun - Date: 2019-07-15 08:38:07 +0900 - - Fix unaligned help output - - 1f99274ccf31ba1f2a4b3ac20a9c6cdc5ae81152 was indenting details with a - hard tab, but other lines are using spaces. - -commit 02c4ed4a7f44a80d50c2d3e27f451b20c4360899 - Author: Takashi Kokubun - Date: 2019-07-15 08:36:51 +0900 - - Stop consuming 2 entries for goruby - - similar to 364f43ab7fc5920247fc73423c1428208cf78a4a and - 13cb9e6bd2c88d04fc9b21b8f8c1d192c67cd5a2 - -commit 17ccda54131e3e8f59fc5bc5be044aef78e2854c - Author: aycabta - Date: 2019-07-15 08:32:50 +0900 - - Use #to_a for Readline::HISTORY directly - -commit 9da969cae73b88a9e7acd761f184bd5275febdf7 - Author: Takashi Kokubun - Date: 2019-07-15 08:32:45 +0900 - - Revert "Dummy Makefile.in for CIs" - - This reverts commit c55de95ff1c4ea6313c2863037703a0e5f0d0f4f. - - Probably this is not needed for CI anymore. - -commit 1f99274ccf31ba1f2a4b3ac20a9c6cdc5ae81152 - Author: Hiroshi SHIBATA - Date: 2019-07-15 08:19:49 +0900 - - Added the bundled gems target to make help. - -commit 13cb9e6bd2c88d04fc9b21b8f8c1d192c67cd5a2 - Author: Yusuke Endoh - Date: 2019-07-15 08:18:30 +0900 - - common.mk: remove "make exam" from help - - Currently it is completely the same as "make check". - I think it is not worth mentioning now. - -commit 2b78a93bcfdc8884646cae88dffe06da6bdb6213 - Author: aycabta - Date: 2019-07-15 07:58:15 +0900 - - Add lib/irb/color.rb to destribution file list - -commit c9a59f491d0851c30e2f371eafcec486ce8ba27b - Author: Yusuke Endoh - Date: 2019-07-15 07:59:11 +0900 - - Add a /* fall through */ comment - -commit 772dae8bef36e3111b8e03fc6297cc99a959ae4b - Author: Yusuke Endoh - Date: 2019-07-15 07:56:53 +0900 - - Add a /* fall through */ comment - -commit 266f6cd8a1dbf93ab5a99d3508f7f1cb5d348be1 - Author: aycabta - Date: 2019-07-15 07:54:47 +0900 - - Remove debug print - -commit 4b7a04a5b8a583e7e818155a73069a9e58a1a246 - Author: aycabta - Date: 2019-07-15 07:51:57 +0900 - - Support multiline irb_history - - A history line ends with "\" to escape newline if it's a continuous - line. - -commit d37da601289d13396b1e986b81d51b05bcfdddd5 - Author: Yusuke Endoh - Date: 2019-07-15 06:42:55 +0900 - - time.c (time_mdump): use another buffer for year_extend - - ruby_marshal_write_long may write 9 bytes, but buf has only 8 bytes. - So the buffer cannot be reused. This issue was found by Coverity Scan. - -commit ea711285737faac6471fc22f0b8f9e9365e7e6ed - Author: Takashi Kokubun - Date: 2019-07-15 06:22:22 +0900 - - Unify documentations of `make benchmark` - -commit e8b6f6303999fd39d367d3eb114193faad13bbca - Author: Takashi Kokubun - Date: 2019-07-15 06:17:29 +0900 - - Drop `make change` and tool/change_maker.rb - - because we're not writing ChangeLog anymore. - -commit 364f43ab7fc5920247fc73423c1428208cf78a4a - Author: Takashi Kokubun - Date: 2019-07-15 06:11:40 +0900 - - Reduce the number of make help entries - - We've added some more things recently. It seems not worth having almost - the same two entries there anymore. - -commit 0ee105f3f0a3b409bc08e6a1336c898038c1088f - Author: Takashi Kokubun - Date: 2019-07-15 06:08:55 +0900 - - Mention SPECOPTS variable in make help - -commit 10d7b39d5d3141073221d4e53a8e81b7808a11b6 - Author: aycabta - Date: 2019-07-15 02:58:28 +0900 - - Check whether prompt_i is nil - -commit 078e50c5e9c53d935bdea6ca3ae156c0edcea467 - Author: aycabta - Date: 2019-07-15 01:16:18 +0900 - - Save history in IRB is enabled by default - -commit 6d573691058b353840c504d16cc2df1eb0bb517c - Author: aycabta - Date: 2019-07-15 01:07:37 +0900 - - Auto indent in IRB is enabled by default - -commit 82b058ff6067269c04265844c7df08a2971b0335 - Author: aycabta - Date: 2019-07-15 00:43:16 +0900 - - Version 1.1.0.pre.2 - -commit d0b1a8d5fb56a20198c69d77d9ce65740d0ddcc2 - Author: aycabta - Date: 2019-07-15 00:42:45 +0900 - - Need reline-0.0.1 or later for some features - -commit cd7b99bbfccd69b6cd75421b738bcda36f920e0d - Author: aycabta - Date: 2019-07-15 00:15:01 +0900 - - Version 0.0.1 - -commit 04e6b90d5be8f13344066de0d64ba11020e2c094 - Author: manga_osyo - Date: 2019-06-29 23:51:24 +0900 - - Remove unused method. - -commit 423feb53a20f323d6b7e27e132e68b70b888ffe9 - Author: Marcus Stollsteimer - Date: 2019-01-04 08:07:34 +0900 - - [ruby/matrix] Add Matrix::VERSION constant - - Add Matrix::VERSION for the gem version, use it in the gemspec, - and make it also available for library users. - - https://github.com/ruby/matrix/commit/65c2bb1fa1 - -commit 4403130193ac895820d9ccc8ec2ab13de37bfea6 - Author: Marcus Stollsteimer - Date: 2019-01-04 08:00:06 +0900 - - [ruby/matrix] Add missing `lib/matrix/' files to file list in gemspec - - https://github.com/ruby/matrix/commit/2bbb9be233 - -commit 3201062adf7f98f645b659852bd9fa6f566cb1dd - Author: Yusuke Endoh - Date: 2019-07-15 00:31:07 +0900 - - Add a /* fall through */ comment - -commit 970c12551efed86074d9c3440f82551795cbde6a - Author: Yusuke Endoh - Date: 2019-07-15 00:30:35 +0900 - - Add a /* fall through */ comment - -commit 9e3971c3ade4a2fd5c5d3123f9437fa3af352655 - Author: Yusuke Endoh - Date: 2019-07-15 00:29:56 +0900 - - Add a /* fall through */ comment - -commit deb5e582308950cdceb510807f498a7733dc076f - Author: Yusuke Endoh - Date: 2019-07-15 00:19:41 +0900 - - ext/stringio/stringio.c (strio_read): "binray" is always zero here - - Remove unused conditional expression to suppress Coverity Scan warnings. - -commit e6f188ea031db9bd7ac0d2931242eebc83b5aac7 - Author: manga_osyo - Date: 2019-06-25 22:08:15 +0900 - - Rename to Reline::History::Test. - -commit 073cc52dcc5f0945e56877c703688517f58c6a65 - Author: manga_osyo - Date: 2019-06-23 13:29:09 +0900 - - Add `class Reline::History` and test. - -commit 9806da50f49843c6983e3110a23ab7822c2e089d - Author: Masataka Pocke Kuwabara - Date: 2019-06-13 16:09:02 +0900 - - Suppress warnings - -commit 83171b0ee8dc8000819259bde764ea9ca3489290 - Author: aycabta - Date: 2018-12-27 07:09:56 +0900 - - [ruby/rdoc] Bump version to 6.1.1 - - https://github.com/ruby/rdoc/commit/55c0627fe0 - -commit 312d72000a5b49064670c1a7f4c2ad5e167d292b - Author: poloka - Date: 2018-12-27 04:06:23 +0900 - - [ruby/rdoc] Correction to include regexp_handling in list of loaded files - - https://github.com/ruby/rdoc/commit/1940b2318c - -commit 09187c64b8dcea6a6ed6134e939a2e0ca88a2bd6 - Author: Yusuke Endoh - Date: 2019-07-15 00:10:39 +0900 - - Add a /* fall through */ comment - -commit 517c8a532425a28ee2641fc100a91a691b501fe8 - Author: Yusuke Endoh - Date: 2019-07-15 00:08:34 +0900 - - dir.c (dir_each_entry): remove unnecessary check - - I guess that this check was to detect re-entrance (maybe callcc?). - But currently it does not work as intended. - -commit 721fc849370d88b87703b00ed1442295c1a94027 - Author: git - Date: 2019-07-15 00:08:33 +0900 - - * 2019-07-15 - -commit b4975693ed1ac46be081e02d82a6dfb7aea0e1c0 - Author: Yusuke Endoh - Date: 2019-07-15 00:07:32 +0900 - - process.c (p_sys_setregid, p_sys_setresgid): remove unused tmp buffer - - To suppress Coverity Scan warning - -commit 80da68db1e770c877782cdf571d96fd89e7774dd - Author: Yusuke Endoh - Date: 2019-07-14 23:36:23 +0900 - - Add a /* fall through */ comment - -commit 43c337dfc18676e95f9fb9b1d6bf3beb3ec6b306 - Author: Yusuke Endoh - Date: 2019-07-14 23:04:48 +0900 - - string.c (str_succ): refactoring - - Use more communicative variable name - -commit 3fd086ed565e6156db5e64a5c42469db331a6237 - Author: Yusuke Endoh - Date: 2019-07-14 23:04:16 +0900 - - string.c (str_succ): remove a unnecessary assignment - - This change will suppress Coverity Scan warnings - -commit 198281a71d95c1a48445dc6e913bc1bd62350054 - Author: Kouhei Sutou - Date: 2019-04-23 05:54:44 +0900 - - [ruby/csv] Fix a bug that strip: true removes newlines - - https://github.com/ruby/csv/commit/5540d35a30 - -commit 8c0edbd79d59789b9543d00322d6bde72f86bfda - Author: kawa_tech <49791334+kaerunote@users.noreply.github.com> - Date: 2019-04-20 16:37:52 +0900 - - [ruby/csv] add options doc :quote_empty (#89) - - - https://github.com/ruby/csv/commit/5ca8d79f60 - -commit 75620c804ea47de040016ccf9766c016f2934df2 - Author: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> - Date: 2019-04-20 00:42:40 +0900 - - [ruby/csv] Add options doc: :write_converters, :write_nil_value, :write_empty_value (#87) - - - https://github.com/ruby/csv/commit/5923ee08b7 - -commit fe40841bfb031d278daea5b05fb13084f887fec5 - Author: hayashiyoshino - Date: 2019-04-19 20:59:38 +0900 - - [ruby/csv] add document of strip (#88) - - * add document of strip - - * modify typo - - https://github.com/ruby/csv/commit/de0257dc31 - -commit c8b82998d4fbbb8988b0f2458327697918a9e1a2 - Author: Kouhei Sutou - Date: 2019-04-17 22:05:12 +0900 - - [ruby/csv] Bump version - - https://github.com/ruby/csv/commit/3976985008 - -commit 8392592a0a33bb9103a7aa968389fe50e304e062 - Author: Kouhei Sutou - Date: 2019-04-17 22:02:40 +0900 - - [ruby/csv] Don't raise on eof? - - GitHub: fix #86 - - Reported by krororo. Thanks!!! - - https://github.com/ruby/csv/commit/5a8d9d9297 - -commit 9171f833054cd47842e12fc0fd3cc1df704a9192 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-15 12:12:26 +0900 - - [ruby/csv] Refactor range in delete_suffix (#85) - - - https://github.com/ruby/csv/commit/7ff57a50e8 - -commit 864e2a95d90d547fe83c847c01daa1c3ba4503de - Author: Kouhei Sutou - Date: 2019-04-15 11:05:20 +0900 - - [ruby/csv] Bump version - - https://github.com/ruby/csv/commit/312f844693 - -commit 85497744305fcd7ff2b7768867f68c8fac03c8a0 - Author: Hiroshi SHIBATA - Date: 2019-07-14 22:05:39 +0900 - - Tweak upstream information of upstream commit. - -commit 0bf829c17b92c608bc374f03a63b89a940d61955 - Author: Yusuke Endoh - Date: 2019-07-14 23:02:23 +0900 - - transcode.c (rb_trans_conv): remove unnecessary assignments - - This change will suppress Coverity Scan warnings - -commit 36f2d9bac2c0e6dacc0488448c05dfde6ef2b23a - Author: Yusuke Endoh - Date: 2019-07-14 22:46:34 +0900 - - numeric.c (fix_cmp): remove a unreachable return statement - -commit 49362ddac60bb9d348cbcd8b7c003f52f5ffa1f5 - Author: Yusuke Endoh - Date: 2019-07-14 22:20:47 +0900 - - Add a /* fall through */ comment - -commit d0f113f6c169a618c41a857d2536c89b86c58d75 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 22:05:22 +0900 - - doc/globals.rdoc: Add RUBY_REVISION [ci skip] - -commit ab31e13e7513ffb08af41b0fc5f779c8d4a78fc2 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 22:03:52 +0900 - - doc/globals.rdoc: Add RUBY_PATCHLEVEL [ci skip] - -commit 9a402cf61f5ab86944c52466ae2e4db95bcc5f90 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 21:57:44 +0900 - - doc/globals.rdoc: Add RUBY_COPYRIGHT [ci skip] - -commit 5d606b5174a8842a6cf6397ee9c9e07736d6af8f - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 21:56:45 +0900 - - doc/globals.rdoc: Add TOPLEVEL_BINDING [ci skip] - -commit 7ac7685fa7a266e74102ac8ed067035ebfebe6e6 - Author: Takashi Kokubun - Date: 2019-07-14 22:12:33 +0900 - - Simplify link_o_to_so arguments - - by C99 compound literal for array and non-constant array initializer - -commit b7ec77f3614d7a89a47466f240d53abc0f967d19 - Author: Tanaka Akira - Date: 2019-07-14 22:04:27 +0900 - - fix typos. - -commit 085d0e5ccb7cecb1f761c1d3c72caeeedafc7d04 - Author: Yusuke Endoh - Date: 2019-07-14 21:56:39 +0900 - - ruby.c (name_match_p): remove unnecessary condition - - It always returns immediately when len was decremented to zero. - So len is always positive. This change will suppress Coverity Scan - warning. - -commit a3493521a55e32081520be805a764fd2ad43fe7b - Author: Hiroshi SHIBATA - Date: 2019-07-14 21:52:49 +0900 - - abort sync commit history when it failed to modify commit message. - -commit 8e6a68c18edeb8dfef494862093539d987b6ad6a - Author: Hiroshi SHIBATA - Date: 2019-07-14 21:49:10 +0900 - - Use force flag for filter-branch. - -commit c8e1be6f1fed7f4f54d5ac1f7ae1ebe2c0f60dbe - Author: Hiroshi SHIBATA - Date: 2019-07-14 17:53:14 +0900 - - Skip merge commit with rubygems and bundler. - -commit 46491af74ca2266aae0157b79a44898a2f4b728d - Author: Hiroshi SHIBATA - Date: 2019-07-14 21:31:16 +0900 - - Modified commit message with upstream repository name. - -commit 265e94a7fa96c918c4278ae58bf6e5cdb018906d - Author: Hiroshi SHIBATA - Date: 2019-07-14 17:15:06 +0900 - - Added chrry-pick feature from upstream repository. - -commit be082e28003543eff5ff07cf5261dbf7b6278a50 - Author: Hiroshi SHIBATA - Date: 2019-07-14 16:56:39 +0900 - - Try to sync with commit history for default gems. - -commit d8cc41c43be65dd4b17e7a6e38f5a7fdf2b247d6 - Author: Takashi Kokubun - Date: 2019-07-14 21:48:22 +0900 - - Fix a wrong buffer size to avoid stack corruption - - [Bug #15986] - -commit 20a3fb3c4b7c564ee7809ac1ed036b4874e47e26 - Author: Yusuke Endoh - Date: 2019-07-14 21:34:32 +0900 - - Add a /* fall through */ comment - -commit e8700b596b907ed0db80ccd398d9dfe1f0fe6dd1 - Author: Nobuyoshi Nakada - Date: 2019-07-14 20:52:49 +0900 - - Check the result of String#-@ - -commit 4900a10689036211da79c8189ff7eba11c8c81ee - Author: Tanaka Akira - Date: 2019-07-14 20:46:51 +0900 - - socket: use frozen string buffer when releasing GVL - - Thanks for the patch by normalperson (Eric Wong) [Bug #14204]. - -commit 5bd83909b961546ff6203ad088bfffeb8c19fceb - Author: Nobuyoshi Nakada - Date: 2019-07-14 18:02:02 +0900 - - Expand f_arg to use particular functions directly - -commit 1464f7a149264b02637fdd444f8a431f1692981a - Author: Nobuyoshi Nakada - Date: 2019-07-14 18:01:24 +0900 - - Expand f_abs to use particular functions directly - -commit 0df4a813ca8f9cb4d081c45ad91be3dd17bb06f1 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 20:33:41 +0900 - - NEWS: RubyVM.resolve_feature_path moved [ci skip] - -commit 41e09ca4becff3d573a5c8049624c664311492ae - Author: Yusuke Endoh - Date: 2019-07-14 20:23:29 +0900 - - addr2line.c (binary_filename): extend the buffer for NUL terminator - -commit a7dd6763bd1dac7952ace46be58083dbea332a0a - Author: Takashi Kokubun - Date: 2019-07-14 20:17:03 +0900 - - Increase fetchDepth to prevent checkout failure - - like https://dev.azure.com/rubylang/ruby/_build/results?buildId=1637 - -commit 45dfd4c09d399124ddc7abd1ae24e1e64019b333 - Author: Takashi Kokubun - Date: 2019-07-14 18:08:47 +0900 - - Make export declaration place more consistent - -commit 2553608c3b8dde72e8255e2306b5208813fff461 - Author: Nobuyoshi Nakada - Date: 2019-07-14 17:59:24 +0900 - - Removed binop macro which has not been used - -commit d30d404bc4b848f84959799b543de4bdbd8eef2b - Author: Takashi Kokubun - Date: 2019-07-14 18:04:14 +0900 - - MJIT Support for getblockparamproxy - -commit 043e3d2cdc02a3571e3e2c3b9252a65d3c049740 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 17:58:25 +0900 - - [DOC] Add missing headings [ci skip] - -commit 08c2a9dc599021668e11dee2f099a204122eab90 - Author: Nobuyoshi Nakada - Date: 2019-07-14 14:44:59 +0900 - - Introduce RUBY_DEBUG flag macro - - When RUBY_DEBUG is turned on, all RUBY_ASSERT() macros will be - enabled regardless RUBY_NDEBUG. - -commit 715955ff27206351dcf509eb3c60e0927ad9a708 - Author: Nobuyoshi Nakada - Date: 2019-07-14 13:06:22 +0900 - - Include ruby/assert.h in ruby/ruby.h so that assertions can be there - -commit db64093f512d93eb300131f52b7ddbd2d11f0aec - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 17:54:22 +0900 - - [DOC] Fix a typo [ci skip] - -commit db1c30b37fb0a837724cf5813e8684edc2639222 - Author: Yusuke Endoh - Date: 2019-07-14 17:53:45 +0900 - - addr2line.c (main_exe_path): avoid SEGV when /proc is not available - - readlink would return -1 if /proc is not mounted. - Coverity Scan found this issue. - -commit 47e571c9510a6d6e3f7d98a8a8800f391694bd19 - Author: Koichi Sasada - Date: 2019-07-14 17:48:11 +0900 - - complement '.rb' on `test-all TESTS=test_xxx` - - for test-all rule, we can specify a file with TESTS option like - `TESTS=test_xxx.rb`. However, we can eliminate last '.rb' suffix - so this patch try with '.rb' suffix if the given path is not available. - -commit b67b07bd5bd94433051b5e0a5db800f8b22361b4 - Author: Maxime Lapointe - Date: 2019-05-31 05:46:18 +0900 - - Fix links to headings - A previous change made the header's id be fully referenced (for the sidebar I believe) but this broke links to them. - This fixes the issue. - -commit 73904abb951ad60483124fa620b5561015906a79 - Author: git - Date: 2019-07-14 17:45:52 +0900 - - * expand tabs. - -commit 32f013514460574eed03aa678f87ed7ca9600872 - Author: Nobuyoshi Nakada - Date: 2019-07-14 13:05:16 +0900 - - Split RUBY_ASSERT and so on under include/ruby - -commit 5786df12f5c07510f9f15e984c564179afae33c0 - Author: Tanaka Akira - Date: 2019-07-14 17:44:33 +0900 - - Describe about Pathname.glob. - -commit 4d9504fe13c6470d9da74540f92a247e8c1d9b99 - Author: Tanaka Akira - Date: 2019-07-14 17:39:21 +0900 - - Delegates 3 arguments for Pathname.glob. - - Thanks for the patch by pocke (Masataka Kuwabara) [Feature #14405]. - -commit 61577fa53bd1ce949912c3b1281668e0ccbcda37 - Author: Yusuke Endoh - Date: 2019-07-14 17:32:49 +0900 - - Add a /* fall through */ comment - -commit 6bca4437dea5da28b8b7e5f1cb87561f2772a03d - Author: Tanaka Akira - Date: 2019-07-14 17:22:13 +0900 - - Describe warning of open-uri. - -commit 05aac90a1bcfeb180f5e78ea8b00a4d1b04d5eed - Author: Tanaka Akira - Date: 2019-07-14 17:18:17 +0900 - - Warn open-uri's "open" method at Kernel. - - Use URI.open instead. - - Thanks for the patch by jeremyevans0 (Jeremy Evans) [Misc #15893]. - -commit 9987296b8b5b7c02fca92761e498764dfeb584cf - Author: git - Date: 2019-07-14 17:16:35 +0900 - - * expand tabs. - -commit 934e6b2aeb495686f7fe0d8b1c69d863e6fca072 - Author: Yusuke Endoh - Date: 2019-07-14 17:15:44 +0900 - - Prefer `rb_error_arity` to `rb_check_arity` when it can be used - -commit 10de5f149acc620e12be5943e4e29f4f555b7551 - Author: Nobuyoshi Nakada - Date: 2019-07-14 16:31:36 +0900 - - Calculate float complex division per each part - - Arguments to f_complex_new2 should not be Complex, or violate the - assertion. - -commit 83153bbb149f5c827c4ce537722d3169d24b9de9 - Author: git - Date: 2019-07-14 16:18:48 +0900 - - * expand tabs. - -commit 73fab16e76d3879d2a099e2ce949b6b03f227d86 - Author: Yusuke Endoh - Date: 2019-07-14 16:17:49 +0900 - - compile.c (defined_expr): return void instead of int - - It always returned 1. - -commit 95de69df9906cde96d30aa2fbc6f5ed4891fdb9f - Author: Yusuke Endoh - Date: 2019-07-14 15:23:15 +0900 - - io.c (rb_file_open_internal): initialize all the fields - - Just for case. This will suppress the warning of Coverity Scan. - -commit 2618db3011edb07fffb9250137ea3a3a6c87cec4 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 16:00:34 +0900 - - [DOC] Fix typos [ci skip] - -commit f2d99fd8209058e75d5d1c56d179509c06486107 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 15:41:45 +0900 - - [DOC] Fix indent [ci skip] - -commit 3163a07878dfcefe7914067e58de78049b056624 - Author: Luke Gruber - Date: 2019-06-09 03:55:41 +0900 - - fix issue with 'SIGINT' handling in LineEditor#reset - - @old_trap is the string "DEFAULT" and not a callable object (Proc) - if there are no other signal handlers for SIGINT signal to chain. - -commit 47b04557b01dc109ccafc33db8e80148f07457a9 - Author: Koichi Sasada - Date: 2019-07-14 15:42:55 +0900 - - Method#inspect with source location. - - Method#inspect shows with source location. - [Feature #14145] - -commit 4ce935cd5dde69b39bb98b8948d41e3afba81e33 - Author: Hiroshi SHIBATA - Date: 2019-07-14 15:22:12 +0900 - - Removed FileUtils for file manipulations with module inclusion. - -commit a73f45247652d563e4043af8d14964b9d911fe81 - Author: Hiroshi SHIBATA - Date: 2019-07-14 15:21:27 +0900 - - Use FileUtils.mkdir_p instead of mkdir command directoly. - -commit e91ff4dbaf0bdbf7185b485b43cd9393419efd11 - Author: Hiroshi SHIBATA - Date: 2019-07-14 15:20:25 +0900 - - Use FileUtils.cp_r instead of cp command directoly. - -commit d25f355c655704d483ca402d0ac2644adb5733b0 - Author: Hiroshi SHIBATA - Date: 2019-07-14 15:07:17 +0900 - - Fixup dccb0e1ec94e7b9c13c715939ae7e0ccc4ffb23e - -commit 7d24a7ed7bae3adec131920d98c0b321e9d3e286 - Author: Hiroshi SHIBATA - Date: 2019-07-14 14:29:38 +0900 - - Use FileUtils.rm_rf instead of rm command directly. - -commit 7504d676c8ee245bb3b117e743fb3921a3ab56f7 - Author: Hiroshi SHIBATA - Date: 2019-07-14 14:17:06 +0900 - - Do not use hard-coded file path of default gems upstream. - -commit 357f295a0e97a105e51d0b3a4b5c062c55dffe92 - Author: Tanaka Akira - Date: 2019-07-14 15:01:39 +0900 - - Describe lambda-ness of Proc more. - -commit dda2c860d97ce3149361b143c9ccc5ed1a2f1af2 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 14:59:34 +0900 - - [DOC] Fix link to feature [ci skip] - -commit 6da539be3ec9e9ba7a45877108d095dcb349cabe - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 14:52:31 +0900 - - Fix typos [ci skip] - -commit 4f351111b811a7437f8356172a6cc59d8fb37022 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 14:40:38 +0900 - - NEWS: warning of flip-flop is reverted [ci skip] - -commit 421dd3114579f90ecced6cf221828a730357b50f - Author: Kazuhiro NISHIYAMA - Date: 2019-07-14 14:33:28 +0900 - - [DOC] Fix experimental marker [ci skip] - -commit 219643c075d9f5641307853cae052383bb289a11 - Author: Yusuke Endoh - Date: 2019-07-14 14:27:45 +0900 - - Add a /* fall through */ comment - -commit 34b3ef29b60f1351130f2ccc8adf3d174861233c - Author: Takashi Kokubun - Date: 2019-07-14 14:09:32 +0900 - - Drop obsoleted mjit_cancel_ivar debug_counter - - ivar_cancel label is handling mjit_cancel_ivar_inline instead. - -commit ff5b149435f6ae167df6cc8a17ad49b4c92209f1 - Author: git - Date: 2019-07-14 14:04:34 +0900 - - * expand tabs. - -commit ba94404f7021fae41a827e080be6d5dd0bbac8e4 - Author: Yusuke Endoh - Date: 2019-07-14 14:03:44 +0900 - - Add /* fall through */ comments - - to suppress some Coverity Scan warnings - -commit 1d46642487d5340cf6c1f17b36ff0f64b0c1595c - Author: git - Date: 2019-07-14 13:57:57 +0900 - - * expand tabs. - -commit 315d3adf0f9660568bdca01fd6ddd196c92973d2 - Author: Yusuke Endoh - Date: 2019-07-14 13:49:39 +0900 - - Avoid io_tell whose return value is not used - - In this case, flush_before_seek is enough. - This change will suppress a warning of Coverity Scan. - -commit 18603e9046c0baa23560268e16ead6bbc27726c2 - Author: Takashi Kokubun - Date: 2019-07-14 12:55:57 +0900 - - Update dependencies for 369ff79394765ce198ac7cee872a8c739d895aaa - - Just copy-pasting diff from - https://travis-ci.org/ruby/ruby/jobs/558407687 - -commit 4402c669785e7343cd65e4e90e436a3f8a3e00b5 - Author: Takashi Kokubun - Date: 2019-07-14 12:53:39 +0900 - - Refactor mjit_worker command line with C99 - - Mostly non-constatnt array initializer, and mixed declarations and code. - -commit 369ff79394765ce198ac7cee872a8c739d895aaa - Author: Martin Dürst - Date: 2019-07-14 10:58:50 +0900 - - add encoding conversion from/to CESU-8 - - Add encoding conversion (transcoding) from UTF-8 to CESU-8 - and back. CESU-8 is an encoding similar to UTF-8, but encodes - codepoints above U+FFFF as two surrogates, these surrogates - again being encoded as if they were UTF-8 codepoints. This - preserves the same binary sorting order as in UTF-16. It is - also somewhat similar (although not exactly identical) to an - encoding used internally by Java. - - This completes issue #15995. - - enc/trans/cesu_8.trans: Add encoding conversion from/to CESU-8 - test/ruby/test_transcode.rb: Add tests for above - -commit ac2866005b96baf986072f86ecd3dfd887f2bda3 - Author: Nobuyoshi Nakada - Date: 2019-07-14 01:41:55 +0900 - - Add empty depend file if extconf.rb only exists - -commit 69a66e8a8b492610eba77123de44e97d25012a41 - Author: git - Date: 2019-07-14 01:32:27 +0900 - - * 2019-07-14 - -commit dcb8c41a1e2146cc67c638ec391436e1ab2323d2 - Author: Nobuyoshi Nakada - Date: 2019-07-14 00:50:12 +0900 - - Added depend files - -commit 1a4f7c9bfae484bd9806efc8d1d8074b23e382bf - Author: Nobuyoshi Nakada - Date: 2019-07-13 23:32:18 +0900 - - [DOC] Markup code in globals.rdoc - - Look forward to further improvements in RDoc to automatically mark - up global variables and global constants. - -commit 6ef73c14725b90ae1fb0ec017564d560d05d8c01 - Author: Benoit Daloze - Date: 2019-07-13 22:47:37 +0900 - - Improve documentation in doc/globals.rdoc - -commit 237b3e00c72bff89b97d04d0a15200949ac1ee56 - Author: Benoit Daloze - Date: 2019-07-13 22:39:54 +0900 - - Document $~ before dependent global variables - -commit b1ee7148f8f9007d7154bf147daecc8c70dc44a3 - Author: Benoit Daloze - Date: 2019-07-13 22:35:16 +0900 - - Improve documentation of $LOAD_PATH - -commit 0a5463f7645f6366e2239268de5bc56c0dfea9d1 - Author: Benoit Daloze - Date: 2019-07-13 22:26:47 +0900 - - Add $LOAD_PATH.resolve_feature_path in NEWS - -commit 4a935bc6f66fda448fb430c7627a2f175dcd0650 - Author: Benoit Daloze - Date: 2019-07-13 22:23:49 +0900 - - Document $LOAD_PATH.resolve_feature_path in globals.rdoc - - * RDoc does not seem to support documenting singleton object methods, - and making $LOAD_PATH a class as a workaround is too weird. - -commit b0f6f33094606e50296cb525184708454420e860 - Author: Benoit Daloze - Date: 2019-07-13 22:16:26 +0900 - - Document a few more RUBY_* constants - -commit 43677a2c58c82ddd630eb5267d1683e1c651c529 - Author: Benoit Daloze - Date: 2019-07-13 22:07:19 +0900 - - Document the long form of global variables and mention aliases on the same line - - * The longer forms are self-explanatory and I believe more often used. - * Same for ARGV and ARGF, describe them there and mention $* and $< just refer to them. - -commit e2bee86dc4ec60c8834b976b83491358c4cb5f00 - Author: Nobuyoshi Nakada - Date: 2019-07-13 09:48:12 +0900 - - Relaxed delta of nanosec from Float time - -commit 331eccf3fea016f074f08f8215a9120e0a30468c - Author: Nobuyoshi Nakada - Date: 2019-07-12 07:25:06 +0900 - - Removed useless `freeze`s from gemspec files - -commit fd9f26df005824f5b1f1f41adaf63f2ff57062a7 - Author: Nobuyoshi Nakada - Date: 2019-07-10 17:16:01 +0900 - - Drop fossil rubygems support - -commit 143581cf4e8dec363b9636fdcd215153d94673c5 - Author: Nobuyoshi Nakada - Date: 2019-07-12 07:23:00 +0900 - - Removed stub lines from gemspec files - -commit cbe623f1c787ff2117045c7c4f03a294dfdb9370 - Author: Masatoshi SEKI - Date: 2019-07-13 07:22:55 +0900 - - change default value of load_limit (ignore load_limit) - -commit 10d7419eb43969de209c1bbcd56b052679cfa8d1 - Author: git - Date: 2019-07-13 06:10:07 +0900 - - * 2019-07-13 - -commit 1ee17782e108222d07a1c6b58cf1c7521d188b32 - Author: Nobuyoshi Nakada - Date: 2019-07-10 17:15:18 +0900 - - Removed binary line - -commit ae599db22fa46d3c04329e09294ff0a31d7ebfbb - Author: Nobuyoshi Nakada - Date: 2019-07-12 17:57:28 +0900 - - * remove trailing spaces. - -commit 00b34b05921da35a97d78d17133ff94abd0ae22b - Author: Nobuyoshi Nakada - Date: 2019-07-12 17:52:12 +0900 - - Fixed duplicate test name - -commit a9ff21a282845f81527b18607d246be90ea6701e - Author: git - Date: 2019-07-12 15:02:29 +0900 - - * 2019-07-12 - -commit b9ad62ea13bfaf0cad2ffc48d724b342ee55c7c8 - Author: git - Date: 2019-07-12 15:02:25 +0900 - - * remove trailing spaces. - -commit a2adcd40df96acd1218cc60dc1810e83dbc124d8 - Author: Samuel Williams - Date: 2019-06-03 18:35:03 +0900 - - Add note about `STACK_GROW_DIR_DETECTION`. - -commit 5c8061a9e2a34df975846d724273cb5be7d74a7c - Author: Samuel Williams - Date: 2019-07-07 19:58:55 +0900 - - Make `stack_check` slightly easier to use in debugger. - -commit 012e954b472d2e47b03647ac0c8f745416d7db58 - Author: Samuel Williams - Date: 2019-06-02 10:48:47 +0900 - - Improved fiber benchmarks. Increase number of iterations. - -commit 8745fa2ff0fbff67031bdecfdeea684b15515a2c - Author: Nobuyoshi Nakada - Date: 2019-07-11 21:05:25 +0900 - - Default to true when no exception flag [Bug #15987] - -commit f74e23af32525b5f2db1729586c930e2becdae30 - Author: Nobuyoshi Nakada - Date: 2019-07-11 20:21:50 +0900 - - Fixed argument in the fallback function [Bug #15987] - -commit c2723e59c2a66a3d2fc8849b3b25c04c9333230a - Author: Nobuyoshi Nakada - Date: 2019-07-11 20:19:53 +0900 - - Removed wrong argument in the fallback function [Bug #15987] - -commit 4018eee4311a610dfaa2b2dca02c6f026b71eab7 - Author: git - Date: 2019-07-11 20:14:57 +0900 - - * expand tabs. - -commit 3e7d002118a92fad5934e11c75be6768a1476c1b - Author: Nobuyoshi Nakada - Date: 2019-07-11 19:20:53 +0900 - - Check exception flag as a bool [Bug #15987] - -commit cd069df36596d9bf7a6db8aaa0dcefdafb233a91 - Author: Nobuyoshi Nakada - Date: 2019-07-11 19:45:03 +0900 - - File::Stat uses Time#inspect - -commit 71ead0787283b469f5e834cb1868a8caa78702f1 - Author: aycabta - Date: 2019-07-11 17:21:00 +0900 - - Add arg check to Reline.dig_perfect_match_proc= - -commit 4e038a7e64a9d52eed59b8f05647d4e58d265ec3 - Author: Nobuyoshi Nakada - Date: 2019-07-11 14:29:35 +0900 - - Revert "parse.y: Deprecate flip-flops" - - This reverts commit bae638ad5b782c44c80efe33834cb9039279af46. - - [Feature #5400] - -commit d77b84ca82e1cef10ef06776a207151ef864b3ca - Author: Nobuyoshi Nakada - Date: 2019-07-11 14:05:34 +0900 - - $LOAD_PATH.resolve_feature_path - - Moved from RubyVM. [Feature #15903] - -commit d34303ad109b93445b01d0420c9a5bfeffafac38 - Author: Tanaka Akira - Date: 2019-07-11 13:04:07 +0900 - - remove an unused variable. - -commit 26d674fdc73cec3777d1a719b42ccbe54c18a966 - Author: Nobuyoshi Nakada - Date: 2019-07-11 11:58:35 +0900 - - Suppress warning on x64-mingw - -commit 50d85436f8f194aa78cd0e819471fe20767a5993 - Author: Tanaka Akira - Date: 2019-07-11 09:18:41 +0900 - - WEBrick::HTTPResponse create tempfile if required. - - WEBrick::HTTPProxyServer implements HTTP proxy using - WEBrick and Net::HTTP. - WEBrick accepts HTTP/1.0 clients and - Net::HTTP uses always HTTP/1.1. - - However HTTP/1.1 supports chunked transfer coding HTTP/1.0 doesn't. - - Chunked transfer coding doesn't require that - content-length before the content is sent. - But non-chunked transfer coding require content-length before - the content is sent. - - So, when HTTP/1.0 clients connects WEBrick::HTTPProxyServer and - origin server returns chunked response, - WEBrick::HTTPProxyServer needs to store whole content to - know the length of it. - - This patch do it using tempfile. - -commit d57ce99b7d187eb3af7749a056edeea443da93f6 - Author: git - Date: 2019-07-11 03:37:22 +0900 - - * 2019-07-11 - -commit 12762b76cba8ac4623a6c16e1fe60efafa3b7d1c - Author: Aaron Patterson - Date: 2019-07-11 01:12:28 +0900 - - Don't manipulate GC flags directly - - We need to disable the GC around compaction (for now) because object id - book keeping can cause malloc to happen and that can trigger GC. - -commit f91879a7b548284c93743168acfd11e3d2aeefac - Author: NARUSE, Yui - Date: 2019-07-10 15:49:10 +0900 - - handle_interrupt to defend monitor state [Bug #15992] - - If an exception is raised from another thread for example Timeout - and this thread is just after `mon_exit`'s `@mon_owner = nil`, - the exception breaks the state of MonitorMixin. To prevent that situation, - it need to block interruption in mon_enter and mon_exit. - -commit 1d2ec4b21647089598d0be3a8bc5f56a71b5e892 - Author: Nobuyoshi Nakada - Date: 2019-07-10 12:33:29 +0900 - - Added Etc::VERSION - -commit 612b7b6224db7965e1b11463a8a83569afda101f - Author: Nobuyoshi Nakada - Date: 2019-07-10 12:32:35 +0900 - - Removed unused files - -commit cc936402eb60fc0ccdafd47dc1e4f6f8ae0c4b9c - Author: Nobuyoshi Nakada - Date: 2019-07-10 03:02:01 +0900 - - C90 for old versions - -commit de4889ce5c5177ed276dfc840a5c07f69317096c - Author: Nobuyoshi Nakada - Date: 2019-07-10 02:07:13 +0900 - - Use the found version number - -commit 9c48472b1e895156c4a577cab4f06b74f4844fe5 - Author: Nobuyoshi Nakada - Date: 2019-07-10 01:57:18 +0900 - - Removed useless `freeze`s - -commit db844749af2da9cc06d90db0cb317ec379582afa - Author: Nobuyoshi Nakada - Date: 2019-07-10 01:21:05 +0900 - - Added StringIO::VERSION - -commit 49cad676351120927a9eda5fea58334c3d32f858 - Author: Nobuyoshi Nakada - Date: 2019-07-10 00:20:00 +0900 - - Removed duplicate assignment - - This `last_state` is set to `lex.state` just before the `switch` - statement, and `token_flush` nor `nextc` never change the state. - -commit 57b8ca21f122108ca832f94b4b0f6f8367e3a4fc - Author: git - Date: 2019-07-10 00:09:43 +0900 - - * 2019-07-10 - -commit d0ef5c21fb91f7a82910fc71d4d8e1a801266232 - Author: Nobuyoshi Nakada - Date: 2019-07-09 22:54:34 +0900 - - Check dependencies on Travis-CI - -commit b1be349bfb327753d9f971c9ef692896fac7df08 - Author: Nobuyoshi Nakada - Date: 2019-07-09 21:21:00 +0900 - - Make symlink to "ruby" only from the install-name - -commit 9f275f7971ee7e659e0965122b2bb57e785d0181 - Author: Hiroshi SHIBATA - Date: 2019-07-09 21:16:49 +0900 - - Restore support library for only test files that are digest and csv. - -commit f9a2440866a2df05fcbacf31c4f4e5e18b996e15 - Author: Hiroshi SHIBATA - Date: 2019-07-09 21:04:07 +0900 - - Restore support library for only test files. - -commit d905ff61e69ce4f9bc134285f3ac1859e1eb74a6 - Author: Nobuyoshi Nakada - Date: 2019-07-09 13:47:07 +0900 - - Update dependencies - -commit 8a831e5cb6de530502e22be06f19b30afd64635c - Author: Nobuyoshi Nakada - Date: 2019-07-09 13:10:08 +0900 - - Do not make Unicode tables timestamp phony - -commit 515e106fb73a1a3bc69b6f1670bbaaebf45fee30 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-09 13:00:34 +0900 - - [DOC] Add link to Enumerable#grep from Enumerable#select - -commit 4cda2e5013b1351b9da087fe534907fcd7e52770 - Author: Nobuyoshi Nakada - Date: 2019-07-09 10:58:12 +0900 - - Moved error messages - -commit 9b18cb341f08c725d74f667ef3724c4cc852fdbd - Author: git - Date: 2019-07-09 08:39:30 +0900 - - * 2019-07-09 - -commit 2a8be8ec33a238410e58864f59b6ffccfd0cc19d - Author: Nobuyoshi Nakada - Date: 2019-07-09 08:31:27 +0900 - - Suppress uninitialized instance variable warnings - -commit ad38f026457304d677fde5dfa0d4d256fd4d6509 - Author: Hiroshi SHIBATA - Date: 2019-07-08 20:31:40 +0900 - - Adopt the directory structure of ruby repository for racc extension. - -commit 995ae6d529d6bef62ca756d4b1dbc1e01f062b8a - Author: Nobuyoshi Nakada - Date: 2019-07-08 17:09:59 +0900 - - Check indent of `end` against `else` if present - -commit e0a3c547dd2690e5bfa4a03f59aed5315d926a82 - Author: Nobuyoshi Nakada - Date: 2019-07-08 16:05:04 +0900 - - Get rid of toplevel methods - -commit 93c9405e0e4879fe83937547daefb7e303b22b04 - Author: git - Date: 2019-07-08 16:00:29 +0900 - - * expand tabs. - -commit 663d58ffde9a57ae52a5aa3492098c72f7b4f32e - Author: Nobuyoshi Nakada - Date: 2019-07-08 15:13:59 +0900 - - Fix indent - -commit a8c54932ba4ba002e7046d36af85f940212df9d1 - Author: Nobuyoshi Nakada - Date: 2019-07-08 14:59:28 +0900 - - Renamed fib to fiber - -commit 612cad5d202cec168bcbfec0f148a577dbd98e8d - Author: Lourens Naudé - Date: 2019-07-03 08:29:33 +0900 - - Let struct dump_config in objspace fit in a single cache line - - Let dump_config boolean members roots and full_heap be bit flags - instead - - Closes: https://github.com/ruby/ruby/pull/2274 - -commit e9907122ed6d71de4601b0be22e39e4486636c69 - Author: Nobuyoshi Nakada - Date: 2019-07-08 13:03:50 +0900 - - Suppress a warning when `write_headers: true` - -commit a2e0aaea1b240d7df57dd7f7bece8effa539a5cb - Author: git - Date: 2019-07-08 10:59:04 +0900 - - * 2019-07-08 - -commit 3fcffceafd2bce7186851bf4899484c545a9ace8 - Author: Jeremy Evans - Date: 2019-07-08 02:49:53 +0900 - - Fix default argument values for OptParse::Switch#summarize - - The documentation describes these arguments being hashes, and the method - is called with hashes, so a hash default makes more sense. - - The method would fail previously if called without arguments and @short - or @long contained a non-integer value. - - Fixes [Bug #10928] - -commit c1ebb384fdc222b58398d89a877a06b7efd5e290 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-07 20:16:15 +0900 - - Fix a typo - -commit fc4dd7d3e20b4eaf02d1dd59787abdc4c6c24e3a - Author: Nobuyoshi Nakada - Date: 2019-07-07 19:05:33 +0900 - - Git branch name can contain `#{}` too - -commit 19a4c42d6124aa3bcdf2cd53d510b22acb2b5104 - Author: Nobuyoshi Nakada - Date: 2019-07-07 18:54:17 +0900 - - Unescape #{} in the last commit title - - Get rid of unknown escape sequence warning, as `#` is not a - special character in C. - - ``` - version.c:126:26: warning: unknown escape sequence '\#' [-Wunknown-escape-sequence] - fputs("last_commit=" RUBY_LAST_COMMIT_TITLE, stdout); - ^~~~~~~~~~~~~~~~~~~~~~ - revision.h:4:42: note: expanded from macro 'RUBY_LAST_COMMIT_TITLE' - ^~ - ``` - -commit 68e580402272cea7f98145c3c562cab565a37046 - Author: Lars Kanis - Date: 2019-07-06 21:32:39 +0900 - - Add coroutine context switch for i386-mingw32 - - It's essentially a translation of Context.asm from Intel - to AT&T syntax. - -commit a13636e756662e563e4c4dc802c6fa21cb6d7b52 - Author: Nobuyoshi Nakada - Date: 2019-07-07 18:17:51 +0900 - - Message to pipe should end with a newline - -commit a33948f40a64d038ef848783dcfb33d801bc7018 - Author: git - Date: 2019-07-07 15:50:58 +0900 - - * 2019-07-07 - -commit d548073f68ae719933c328686df224f74a60d366 - Author: Nobuyoshi Nakada - Date: 2019-07-07 15:45:10 +0900 - - Enable indentation warning against `if` just after `else` - - ```ruby - if false - puts 'false' - else if true - puts 'true' - end # -:5: warning: mismatched indentations at 'end' with 'if' at 3 - end - ``` - - [Feature #15990] - -commit 789e49dc7e36f2c19a3df6dfa348e95b7105061c - Author: Nobuyoshi Nakada - Date: 2019-07-07 14:43:54 +0900 - - Renamed column in token_info to indent - -commit 9d8855b6820a53020d034756f6ec523fc14f663b - Author: Nobuyoshi Nakada - Date: 2019-07-06 18:46:00 +0900 - - Added assertions for Unicode escaped CHAR scanner events - -commit f296c260ef3b2d1a9299dbb4a84df567972453f2 - Author: Jeremy Evans - Date: 2019-07-05 05:47:43 +0900 - - Fix segfault when using method reference operator without using result - - Fixes [Bug #15985] - -commit 688cef2169a438c1402a8870887a6406f29a824b - Author: Nobuyoshi Nakada - Date: 2019-07-06 12:31:11 +0900 - - Refactored width calculations - -commit 44aae5fee666e6767415c214e25e90f6ad565550 - Author: Nobuyoshi Nakada - Date: 2019-07-06 12:11:12 +0900 - - Simplified - -commit 833cfeb2260c460d05c75cc6d16fa992d881ec54 - Author: git - Date: 2019-07-06 07:20:29 +0900 - - * 2019-07-06 - -commit 89e178c7cb3b6ba196cfef76d9604e45849c64fc - Author: aycabta - Date: 2019-07-06 07:13:51 +0900 - - Fix showing document of ClassName.method_name in IRB - - In IRB, Time.new is split as "Time", ".", and "new". The receiver "Time" - is processed by #class method but it means that "Time" changes to - "Class". This commit fixes it. - -commit d746a41e85b746a90eef20c46d24880fe084ffc5 - Author: Nobuyoshi Nakada - Date: 2019-07-05 22:18:08 +0900 - - Multiple codepoints are not allowed at single character literal - - It has unintentionally passed since 2.5. - -commit 0a2f598d23ef54ce906ebe302cc06e07a16f9022 - Author: git - Date: 2019-07-05 19:01:15 +0900 - - * 2019-07-05 - -commit fae4489a3a70b7620716c76b53c87fd3171a7571 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-05 19:00:37 +0900 - - Fix a typo - -commit 6c2b59f9237843a4570d0ab932705b3fa5c18524 - Author: aycabta - Date: 2019-07-04 20:58:11 +0900 - - Support Control- and Meta- - -commit d9f8b88b47c141e7dcbc50eb10812acaeca2a325 - Author: aycabta - Date: 2019-07-04 19:34:08 +0900 - - Move a comment to proper place - -commit 6fa7ed453e81ef3e74b2699db0533eb79e815dbb - Author: aycabta - Date: 2019-07-04 19:29:07 +0900 - - Check commented out line in inputrc correctly - -commit 265b9a0edf48e96d053724c9676af953e920246c - Author: Nobuyoshi Nakada - Date: 2019-07-04 18:54:50 +0900 - - Parse key sequence more strictly - -commit 12e06d32f55dff7f35c66842e5d6901857132060 - Author: Nobuyoshi Nakada - Date: 2019-07-04 18:49:42 +0900 - - Use lstrip instead of gsub which can match only once - -commit ee861e43f70d827abd1f8d26b2e97920237348b4 - Author: Nobuyoshi Nakada - Date: 2019-07-04 18:46:34 +0900 - - Skip indented comment lines [Bug #15981] - -commit 0c3e6e86bdcb708d283dc57ed3c18ed1b40e4a17 - Author: Nobuyoshi Nakada - Date: 2019-07-04 18:12:08 +0900 - - Suppress uninitialized instance variable warnings - -commit f19e048d244c709e2990ddbb0f986e8b51357bd2 - Author: Nobuyoshi Nakada - Date: 2019-07-04 15:43:33 +0900 - - Do not dispatch a nil token in ripper - - As a comment token includes the newline, so delayed newline token - just follows it should not be dispatched. [Bug #11485] - - Co-Authored-By: Jeremy Evans - -commit 23c92b6f820f670994026423d4c7b5abcf51eafa - Author: Nobuyoshi Nakada - Date: 2019-07-03 14:44:20 +0900 - - Revert self-referencing finalizer warning [Feature #15974] - - It has caused CI failures. - - * d0cd0866d82a58933e5dccd073c753c0c2ad4eb5 - - Disable GC during rb_objspace_reachable_object_p - - * 89cef1c56b3a0f9c5e6ccc22a5044477a4fd16c1 - - Version guard for [Feature #15974] - - * 796eeb6339952d92ae1b353d450c7883e589852d. - - Fix up [Feature #15974] - - * 928260c2a613bbdd4402c300e0bf86ae7562e52a. - - Warn in verbose mode on defining a finalizer that captures the object - -commit 5d9e91afe08c470485333f6c6e034d05ea3ee908 - Author: git - Date: 2019-07-04 01:04:47 +0900 - - * 2019-07-04 - -commit c62aac108666e0c74a4a24d6b4200c3326b21b64 - Author: git - Date: 2019-07-04 01:04:44 +0900 - - * expand tabs. - -commit d0cd0866d82a58933e5dccd073c753c0c2ad4eb5 - Author: Nobuyoshi Nakada - Date: 2019-07-04 00:58:52 +0900 - - Disable GC during rb_objspace_reachable_object_p - - Try to fix CI breakage by [Feature #15974]. - -commit 9f1d67a68f55fe7a16840960e0817d362b16d5b2 - Author: Nobuyoshi Nakada - Date: 2019-07-03 23:52:52 +0900 - - Renamed to rb_objspace_reachable_object_p - -commit 7b9bb6f44a0dc891f41c06804e828790ba5fec6d - Author: aycabta - Date: 2019-07-03 23:37:46 +0900 - - Check code_block_open for whether code continues - -commit 6bd49b33c859e3893318b8ceb1f3e0dd0988144f - Author: Aaron Patterson - Date: 2019-07-03 21:52:51 +0900 - - Ensure that GC is disabled during compaction - - Various things can cause GC to occur when compaction is running, for - example resizing the object identity map: - - ``` - frame #24: 0x000000010c784a10 ruby`gc_grey [inlined] push_mark_stack(stack=, data=) at gc.c:4311:42 - frame #25: 0x000000010c7849ff ruby`gc_grey(objspace=0x00007fc56c804400, obj=140485906037400) at gc.c:4907 - frame #26: 0x000000010c78f881 ruby`gc_start at gc.c:6464:8 - frame #27: 0x000000010c78f5d1 ruby`gc_start [inlined] gc_marks_start(objspace=0x00007fc56c804400, full_mark=) at gc.c:6009 - frame #28: 0x000000010c78f3c0 ruby`gc_start at gc.c:6291 - frame #29: 0x000000010c78f399 ruby`gc_start(objspace=0x00007fc56c804400, reason=) at gc.c:7104 - frame #30: 0x000000010c78930c ruby`objspace_xmalloc0 [inlined] objspace_malloc_fixup(objspace=, mem=0x000000011372a000, size=) at gc.c:9665:5 - frame #31: 0x000000010c7892f5 ruby`objspace_xmalloc0(objspace=0x00007fc56c804400, size=12582912) at gc.c:9707 - frame #32: 0x000000010c89bc13 ruby`st_init_table_with_size(type=, size=) at st.c:605:39 - frame #33: 0x000000010c89c5e2 ruby`rebuild_table_if_necessary [inlined] rebuild_table(tab=0x00007fc56c40b250) at st.c:780:19 - frame #34: 0x000000010c89c5ac ruby`rebuild_table_if_necessary(tab=0x00007fc56c40b250) at st.c:1142 - frame #35: 0x000000010c89c379 ruby`st_insert(tab=0x00007fc56c40b250, key=140486132605040, value=140485922918920) at st.c:1161:5 - frame #36: 0x000000010c794a16 ruby`gc_compact_heap [inlined] gc_move(objspace=0x00007fc56c804400, scan=, free=, moved_list=140485922918960) at gc.c:7441:9 - frame #37: 0x000000010c794917 ruby`gc_compact_heap(objspace=0x00007fc56c804400, comparator=) at gc.c:7695 - frame #38: 0x000000010c79410d ruby`gc_compact [inlined] gc_compact_after_gc(objspace=0x00007fc56c804400, use_toward_empty=1, use_double_pages=, use_verifier=1) at gc.c:0:22 - ``` - - We *definitely* need the heap to be in a consistent state during - compaction, so this commit sets the current state to "during_gc" so that - nothing will trigger a GC until the heap finishes compacting. - - This fixes the bug we saw when running the tests for https://github.com/ruby/ruby/pull/2264 - -commit e44c9b11475d0be2f63286c1332a48da1b4d8626 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-03 19:25:05 +0900 - - Try to avoid `not delagated` error - - ``` - .../ruby/lib/delegate.rb:405:in `__getobj__': not delegated (ArgumentError) - ``` - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian9/ruby-master/log/20190703T063006Z.fail.html.gz - -commit 89cef1c56b3a0f9c5e6ccc22a5044477a4fd16c1 - Author: Nobuyoshi Nakada - Date: 2019-07-03 15:22:16 +0900 - - Version guard for [Feature #15974] - -commit dcedf0a008f07f38e570c70b3872fa37e837be4a - Author: Nobuyoshi Nakada - Date: 2019-07-03 14:16:36 +0900 - - Fix order of tests - - `check` includes `test-testframework`, `test-short` and its - preceding tests, but `test-all` does not. - -commit 10cc6bc4d9276023db21db1014969381de813ff8 - Author: Takashi Kokubun - Date: 2019-07-03 10:00:50 +0900 - - Just disable inlining with local variable for now - - This partially reverts commit 712a66b0741605f5b2db670a292b9bb352f8a716. - - The previous fix made CI strange like: - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/2124178 - - Let me just downgrade the behavior for now and deal with it later. - - [Bug #15971] - -commit 07e9a1d9986b36d9702b480de549c1301dd897e0 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-03 10:20:51 +0900 - - Debugging failures on x86_64-darwin17 of travis-ci - - https://travis-ci.org/ruby/ruby/jobs/553346285 - -commit 9f26242411fe56c661644d63a9be11530889ebe3 - Author: git - Date: 2019-07-03 04:26:53 +0900 - - * expand tabs. - -commit 796eeb6339952d92ae1b353d450c7883e589852d - Author: Nobuyoshi Nakada - Date: 2019-07-03 04:12:20 +0900 - - Fix up [Feature #15974] - - * Fixed warning condition - * Fixed function signature - * Use ident hash - -commit 928260c2a613bbdd4402c300e0bf86ae7562e52a - Author: Chris Seaton - Date: 2019-07-02 22:19:15 +0900 - - Warn in verbose mode on defining a finalizer that captures the object - - [Feature #15974] - - Closes: https://github.com/ruby/ruby/pull/2264 - -commit efde19ce440f8656c3ce631a1d2a56e830961e9d - Author: Nobuyoshi Nakada - Date: 2019-07-03 03:53:20 +0900 - - Revert expansion of test-all - -commit 712a66b0741605f5b2db670a292b9bb352f8a716 - Author: Koichi Sasada - Date: 2019-07-03 03:37:25 +0900 - - Revert "Avoid corrupting VM stack on inlined setlocal" - - This reverts commit ea30dd702512ff9df34fe8c71c825f8f901bf5b1. - because it fails when VM_CHECK_MODE=1. - -commit c07165be1d2bccc9e1c67a90d16259a9c929b56d - Author: git - Date: 2019-07-03 02:13:25 +0900 - - * expand tabs. - -commit bdddaa9f56702e1d3a58a14607e9881052424b53 - Author: Nobuyoshi Nakada - Date: 2019-07-03 02:09:01 +0900 - - Use rb_ident_hash_new instead of rb_hash_new_compare_by_id - - The latter is same as the former, removed the duplicate function. - -commit 0f283054e7f568f09fbfc952d57ea6daf4abbd88 - Author: Jeremy Evans - Date: 2019-06-20 02:44:54 +0900 - - Check that String#scrub block does not modify receiver - - Similar to the check used for String#gsub. Can fix possible - segfault. - - Fixes [Bug #15941] - -commit 7582287eb27e6b649789ce31ffdcbbb9ffcaf726 - Author: Jeremy Evans - Date: 2019-06-19 10:59:49 +0900 - - Make String#-@ not freeze receiver if called on unfrozen subclass instance - - rb_fstring behavior in this case is to freeze the receiver. I'm - not sure if that should be changed, so this takes the conservative - approach of duping the receiver in String#-@ before passing - to rb_fstring. - - Fixes [Bug #15926] - -commit a4b5aaa9a7225693168e43455de2e10c3721b789 - Author: Jeremy Evans - Date: 2019-06-18 07:48:44 +0900 - - Remove Changelog section from doc/contributing.rdoc [ci skip] - - Replace it with a section on commit message formatting. Also, - move the section on rebasing to the bottom, since that only - applies to committers and not most contributors. - - Fixes [Bug #14886] - -commit 40d31073b7e9e14e5169cffca82a424e35b71b95 - Author: git - Date: 2019-07-03 00:19:03 +0900 - - * 2019-07-03 - -commit ced640951b0e7164a12ea1770330eba3e6109fc2 - Author: Jeremy Evans - Date: 2019-06-18 03:33:44 +0900 - - Implement Array#minmax - - Array#minmax was previous not implemented, so calling #minmax on - array was actually calling Enumerable#minmax. This is a simple - implementation of #minmax by just calling rb_ary_min and - rb_ary_max, which improves performance significantly. - - Fixes [Bug #15929] - -commit 649753b7f5410552c70931e32c193d83df3af97e - Author: Yusuke Endoh - Date: 2019-07-02 23:45:13 +0900 - - Fix timezone issue for logger period's tests - - This is a retry of 181b966e7553ac53d034266a7cdc18664d080814. - "Revert "Add a missing tests for Logger::Period module"" is also - reverted. - -commit f1043090a2361019ea4f6832512ef47de3627cb2 - Author: Koichi Sasada - Date: 2019-07-02 23:36:27 +0900 - - Revert "Add a missing tests for Logger::Period module" - - This reverts commit 181b966e7553ac53d034266a7cdc18664d080814. - -commit ea30dd702512ff9df34fe8c71c825f8f901bf5b1 - Author: Takashi Kokubun - Date: 2019-07-02 23:32:09 +0900 - - Avoid corrupting VM stack on inlined setlocal - - setlocal relies on cfp->ep, and frame-omitted method inlining introduced - in Ruby 2.7 kept it wrong. - - This change might slow down frame-omitted method inlining for cfp->ep - manipulation, and it obviously complicates the implementation more. By - introducing an optimization that changes Ruby's local variable to C - local variable, we could optimize it and simplify the cfp->ep - manipulation later. - - [Bug #15971] - -commit 181b966e7553ac53d034266a7cdc18664d080814 - Author: Anton Davydov - Date: 2019-07-02 22:33:12 +0900 - - Add a missing tests for Logger::Period module - - Closes: https://github.com/ruby/ruby/pull/2266 - -commit e9ea494171745cc22f458952b0aaf4443820caa9 - Author: Nobuyoshi Nakada - Date: 2019-07-02 22:10:11 +0900 - - The behavior of statx(2) depends on the filesystem - - birthtime may not be supported on some filesystems, and - NotImplementedError can be raised. [Bug #15972] - -commit e8a2521abecc6738c3480ec9b3d8c7b341cb576f - Author: Hiroshi SHIBATA - Date: 2019-07-02 21:39:22 +0900 - - Adjust memory_status.rb under the tool directory. - -commit 4d6c35d33a3f8a2ab29b3aabcf74be0bd9e7bf98 - Author: Nobuyoshi Nakada - Date: 2019-07-02 15:22:22 +0900 - - Fix test-all substitution - -commit 6ffef8d459e6423bf4fe35cccb24345bad862448 - Author: Nobuyoshi Nakada - Date: 2019-07-02 14:41:34 +0900 - - Clean up temporary expired cert file - -commit 92dcee393acc33075b533a2e8f5ea24ee8a5f579 - Author: Nobuyoshi Nakada - Date: 2019-07-02 14:10:50 +0900 - - Clean up temporary directory for racc - -commit eb043c88881bfa968a289b095518ec196edd47ad - Author: Nobuyoshi Nakada - Date: 2019-07-02 11:46:58 +0900 - - ${} does not work with nmake.exe - -commit 0b858425e1e4f2de40dc0d8e5dd105a2fd93e478 - Author: Takashi Kokubun - Date: 2019-07-02 10:40:17 +0900 - - Use GitHub ruby.git for make-snapshot - - Previously @hsbt disabled https git clone from git.ruby-lang.org. - - Using git.ruby-lang.org for non-commit purposes is discouraged. GitHub - mirror is actually recommended because it's reliable than single-hosted - git.ruby-lang.org, the mirror is almost always well-maintained, and its - latency is very small (usually about 10s). - - So we should just use GitHub here. - - [Bug #15969] - -commit 7f3bc3529b3edb5512a32cda0ae8fe108af0beed - Author: Hiroshi SHIBATA - Date: 2019-07-02 09:48:17 +0900 - - Adjust jit_support file path. - -commit c6a131da64a949c3148565f0bfd7777f5a4a309c - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:49:57 +0900 - - Removed test-almost from TEST_TARGETS - -commit 6e7e0bf25782644b4093e9bc957cbb08ca7ba99c - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:45:29 +0900 - - Now test-almost equals to test-all - -commit 580b7600c726c5293351e695bf6cf50339ef939b - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:44:37 +0900 - - Substitute autoconf variables by prereq.status - -commit 832b5094722477598c7f720584fb54c4b2f18228 - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:43:33 +0900 - - with_different_ofs.rb has been moved too - -commit 83fed5a4edc56f045ca698118af5ba58fce155a0 - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:37:10 +0900 - - Adjust minitest file path - -commit 934a3a926cfbed57bede5ffd018feda9a110381a - Author: Kazuhiro NISHIYAMA - Date: 2019-07-02 09:34:08 +0900 - - Prefer master rather than trunk in doc/contributing.rdoc [ci skip] - -commit 73923bf58305204d77c929670ee5dace2c95a6da - Author: Kazuhiro NISHIYAMA - Date: 2019-07-02 09:26:18 +0900 - - [DOC] Add LibreSSL [ci skip] - -commit b7fdeedbfd5d9f5250df7769837aee35a2362faa - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:31:32 +0900 - - Renamed to get rid of name clash - -commit 5aed62454cec6556d476347f13947f83f6f7de4b - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:26:11 +0900 - - Adjust minitest file path - -commit 4adfd5227f4f62c4e571d31e8bb07c40402f73b8 - Author: Hiroshi SHIBATA - Date: 2019-07-02 09:20:18 +0900 - - Removed needless exclude option related testframework. - - They are moved under the tool directory now. - -commit f47254d2162a95174ab7d1659bf6ec5a933bd0ca - Author: Nobuyoshi Nakada - Date: 2019-07-02 09:19:38 +0900 - - colors file has been moved from test to tool - -commit 897b1e05623996ea1003c812e7705a2d197464b3 - Author: Hiroshi SHIBATA - Date: 2019-07-02 08:00:29 +0900 - - Fixed the wrong path for COVERAGE. - - ref. c3c0e3f5c9444c197779cb242de46dfffda79dec - -commit c68781e9181cb43af1bac29b3c974887205c3bf3 - Author: Hiroshi SHIBATA - Date: 2019-07-01 21:05:55 +0900 - - Split test files for test-framework that are test-unit and minitest to tool directory. - -commit c3c0e3f5c9444c197779cb242de46dfffda79dec - Author: Hiroshi SHIBATA - Date: 2019-06-29 19:43:47 +0900 - - Move to tool/lib from test/lib. - -commit 142617c8e1cad65fa483c5beb78ab40a99626a87 - Author: Jeremy Evans - Date: 2019-07-02 07:33:13 +0900 - - Don't use native realpath(3) on Solaris - - CI shows it does work on Solaris 11, but does not work on Solaris - 10. However, until I figure out a good way to differentiate - between Solaris 10 and 11, this should get CI passing on both. - -commit f53d7e4bfd604be6f8131c5460c29f4af16da117 - Author: Jeremy Evans - Date: 2019-06-15 08:53:42 +0900 - - Raise TypeError if calling ENV.freeze - - Previously, you could call ENV.freeze, but it would not have - the desired effect, as you could still modify ENV. - - Fixes [Bug #15920] - -commit 93328b5237c515878dacfa7350688b016333225d - Author: git - Date: 2019-07-02 04:14:17 +0900 - - * expand tabs. - -commit 11c311e36fa6f27a9144b0aefe16bdffea651251 - Author: Jeremy Evans - Date: 2019-04-28 12:18:55 +0900 - - Use realpath(3) instead of custom realpath implementation if available - - This approach is simpler than the previous approach which tries to - emulate realpath(3). It also performs much better on both Linux and - OpenBSD on the included benchmarks. - - By using realpath(3), we can better integrate with system security - features such as OpenBSD's unveil(2) system call. - - This does not use realpath(3) on Windows even if it exists, as the - approach for checking for absolute paths does not work for drive - letters. This can be fixed without too much difficultly, though until - Windows defines realpath(3), there is no need to do so. - - For File.realdirpath, where the last element of the path is not - required to exist, fallback to the previous approach, as realpath(3) - on most operating systems requires the whole path be valid (per POSIX), - and the operating systems where this isn't true either plan to conform - to POSIX or may change to conform to POSIX in the future. - - glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb - paths, returning ENOTDIR in that case. Fallback to the previous code - if realpath(3) returns ENOTDIR. - - glibc doesn't like realpath(3) usage for paths like /dev/fd/5, - returning ENOENT even though the path may appear to exist in the - filesystem. If ENOENT is returned and the path exists, then fall - back to the default approach. - -commit 81fe82be4e5040b314717e8d6f9ba12de222b6e6 - Author: Jeremy Evans - Date: 2019-07-02 03:44:12 +0900 - - Enable native fiber coroutines on i386-openbsd - -commit 005dadf3c113226d18b6c63ffbe9cb00419bf797 - Author: git - Date: 2019-07-02 03:35:08 +0900 - - * 2019-07-02 - -commit 776759e300e4659bb7468e2b97c8c2d4359a2953 - Author: aycabta - Date: 2019-07-02 03:34:08 +0900 - - Keyword token that follows EXPR_FNAME must be a method name - -commit 7ff2bfed92f8017184963eaac13e75cfb5ce5d4a - Author: Nobuyoshi Nakada - Date: 2019-07-01 23:16:47 +0900 - - Alias "master" and "trunk" - -commit f2769ae2c9f5c5a902584282f1e512437db1f395 - Author: Nobuyoshi Nakada - Date: 2019-07-01 23:04:26 +0900 - - Default branch name to "master" - -commit acee9384840e8c75b0fd406180671df58d049c88 - Author: Nobuyoshi Nakada - Date: 2019-07-01 21:32:02 +0900 - - Default ASMEXT - -commit f28450c118beadc636db9edd150695a8d237fd0f - Author: Nobuyoshi Nakada - Date: 2019-07-01 21:31:18 +0900 - - Substitute suffixes with dot - -commit 76851381cb18a62f3a75720f868ac147e4c1c51c - Author: aycabta - Date: 2019-07-01 21:14:50 +0900 - - Show "-" if indent level is negative - -commit 90c51ca39170030b2ea0611bcbb435b76915a287 - Author: Nobuyoshi Nakada - Date: 2019-07-01 20:45:53 +0900 - - New indent must be non-negative number - -commit babaad1065b1e45614d03e30f82c9007cc115b7c - Author: Nobuyoshi Nakada - Date: 2019-07-01 20:05:06 +0900 - - Use configured ASMEXT - -commit 7f4f40ab31f79e0ab0196b9c11b942d475ff1fcd - Author: Nobuyoshi Nakada - Date: 2019-07-01 17:09:08 +0900 - - bootstraptest/runner.rb (show_limit): defer messages unless verbose and a tty - -commit 70dcf5b368bfeee9bc054895fc046bf69d32aa91 - Author: git - Date: 2019-07-01 16:25:56 +0900 - - * expand tabs. - -commit 78ee2c245331e353e218b8fac9ca722a2bcd8fea - Author: Nobuyoshi Nakada - Date: 2019-07-01 16:20:03 +0900 - - marshal.c: check instance variable count - - * marshal.c (w_ivar_each): ensure that no instance variable was - removed while dumping other instance variables. [Bug #15968] - -commit 0b1e26398e018116180bf41cb63887f77d5d1b82 - Author: Nobuyoshi Nakada - Date: 2019-07-01 16:18:51 +0900 - - Hoisted out w_ivar_each - -commit c9423b016cfeab852bc5a829e55e0a11f80b3ab7 - Author: Nobuyoshi Nakada - Date: 2019-07-01 15:02:27 +0900 - - marshal.c: check instance variable count - - * marshal.c (w_obj_each): ensure that no instance variable was - added while dumping other instance variables. [Bug #15968] - -commit 77a073239c207933e8a2562b51a206aa58dc66b4 - Author: git - Date: 2019-07-01 14:00:37 +0900 - - * expand tabs. - -commit 99dc885974bfe637f3e74f52efdbbf77d66d0d68 - Author: Nobuyoshi Nakada - Date: 2019-07-01 13:56:55 +0900 - - Fixed inadvertent ID creation in rb_iv_get - -commit 6982a9049ede1386fdfa10734f953867824ebe05 - Author: Nobuyoshi Nakada - Date: 2019-07-01 13:01:31 +0900 - - Assert obsolete method warnings in IPAddr - -commit fe03bbaf3405b9e45bb3504fab5f4195ec6c3630 - Author: Nobuyoshi Nakada - Date: 2019-07-01 10:16:47 +0900 - - bootstraptest/runner.rb (show_limit): show dots only when printing to a tty - -commit dbe834ab5ac4f90df5db9fc314b45890726cca3b - Author: Takashi Kokubun - Date: 2019-07-01 01:04:40 +0900 - - Prefer master rather than trunk in README [ci skip] - -commit d3d903cb5ff8a154d14aac1416815ce61affb335 - Author: Kazuhiro NISHIYAMA - Date: 2019-07-01 00:47:55 +0900 - - [DOC] Fix typos [ci skip] - -commit 3d1536e61812dab1f4c226eb60356fd238ab6bb8 - Author: Takashi Kokubun - Date: 2019-07-01 00:24:10 +0900 - - Build AppVeyor only on master - -commit f13fb814e0343b5c09afe0c6d3114ee24b84d295 - Author: Nobuyoshi Nakada - Date: 2019-06-30 22:49:56 +0900 - - Return the result of the block given to assert_warning/assert_no_warning - -commit 51b2b605e78a160790c6d751b2907b836b39561c - Author: Nobuyoshi Nakada - Date: 2019-06-30 22:49:10 +0900 - - Call deprecated method only inside assert_warning block - -commit 9cb58f1698b4a11af24d1129eb6b85d27e0a7145 - Author: Nobuyoshi Nakada - Date: 2019-06-30 22:48:39 +0900 - - Suppress unused variable warning - -commit fc4abbfcd014d9bd281bea7ebec30aabe243b410 - Author: git - Date: 2019-07-01 00:15:04 +0900 - - * 2019-07-01 - -commit 35cf3e8904efa54098c1f904de93167a17d8d313 - Author: Takashi Kokubun - Date: 2019-07-01 00:14:11 +0900 - - The default branch is changed to master - - and now Travis should run on master, instead of trunk. - - (this is testing git push to master branch) - -commit c5eb24349a4535948514fe765c3ddb0628d81004 - Author: Nobuyoshi Nakada - Date: 2019-06-30 21:23:54 +0900 - - [DOC] update target_thread to TracePoint#enable - -commit 8640153e59a106ab2331effc33dcf03415a7e89c - Author: Nobuyoshi Nakada - Date: 2019-06-30 21:21:06 +0900 - - Added test for require-return hook - -commit 1eca2f3ca936cfdbce7b82342f5903b7d16e9bc1 - Author: Nobuyoshi Nakada - Date: 2019-06-30 21:20:16 +0900 - - TracePoint#__enable requires 3 arguments now - -commit 62e66b8e180e17475a79fbdbdc36a33e488e4fe9 - Author: Nobuyoshi Nakada - Date: 2019-06-30 21:15:56 +0900 - - Allow dtrace without pty, i.e., with miniruby - -commit b89f6ac843d9abbe8488bd329e0ff0cccf5caaa3 - Author: Nobuyoshi Nakada - Date: 2019-06-30 21:12:15 +0900 - - Check for the privileges by the current process groups - - Group membership of login user is not activated until login after - adding to the group. - -commit 3b86ec22515853665c353f2fb14e5bdb10b2e65b - Author: Nobuyoshi Nakada - Date: 2019-06-30 18:41:17 +0900 - - dtrace: check for the command availability with sudo - -commit 126cf11d338d6ca8b78a5a425652167d8aacc222 - Author: Nobuyoshi Nakada - Date: 2019-06-30 20:19:21 +0900 - - Producer threads check is the primary condition - -commit 75129c62ebfcd67f08262a6f755e5c899e8ebaee - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:56:30 +0900 - - Suppress "statement not reached" warning - -commit cc680846529b1bb00cded40705e0de696f78b0f9 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:55:50 +0900 - - Suppress method redefinition warnings - -commit 5f736d431951baa2c6e5113322092f7f85d03ae4 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:54:21 +0900 - - Suppress "literal in condition" warnings - -commit 4a063546e7de9ddb424fdf822e69bb3ffeb50631 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:52:31 +0900 - - Suppress unused literal warnings in verbose mode - -commit 3620568d3ac0533b050985d7c3c4ca871d464fd6 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:51:09 +0900 - - Suppress void context warnings in verbose mode - -commit c400c0b4a00706a0da33664c1898e15f1aba0eec - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:46:58 +0900 - - Skip instead of return - -commit b43d6e570980a4f5d6f4c20de29024dc5df93472 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:46:21 +0900 - - Fixed non-working test - -commit 8fe359086484cd322704e57fce25ef8c41d949a8 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:44:15 +0900 - - Fixed ClosedQueueError by a timing issue - -commit 44eca1b22f96a3140d11d95f89948cbdae08daee - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:40:55 +0900 - - Reset the result between assertions - -commit ad3820886b8bd13bb6dbb784ba999b26ac65461c - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:40:23 +0900 - - Fixed an assertion - -commit 409b0ec4c3c4878c0ba164d1303de67787157808 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:34:41 +0900 - - Suppress unused variable warnings - -commit 84837e6d16cb0e588b1acc2691cb1048b9a89989 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:33:24 +0900 - - Wait for the helper thread to terminate - -commit 41012f2e2b71fddc9acf8a50d887707c44ad8f88 - Author: Nobuyoshi Nakada - Date: 2019-06-30 09:30:21 +0900 - - Add parentheses to suppress warnings - -commit 78a8888c3eb6377218e8d3ec94a162c2c20eef82 - Author: Nobuyoshi Nakada - Date: 2019-06-30 10:56:42 +0900 - - Hoisted out f_rest_marg - - * parse.y (f_rest_marg): extract named and unnamed rest parameter - in parenthesized method arguments, and should not be warned as - unused. - -commit 81e8830a76303db80499d44b9c600a575f86d4df - Author: git - Date: 2019-06-30 08:50:35 +0900 - - * 2019-06-30 - -commit 45ba027d086a04e09ed6ad48c5ac78e61f1174c4 - Author: Nobuyoshi Nakada - Date: 2019-06-29 21:19:01 +0900 - - Removed unused variables - -commit 9f648262f9372cbf21754a411a68e178f0fd8feb - Author: Nobuyoshi Nakada - Date: 2019-06-29 21:45:59 +0900 - - Fix predicate to assert if object is same - -commit cbb7dc21a823e8b09341860d8737ed24ee1ce1b8 - Author: Nobuyoshi Nakada - Date: 2019-06-29 19:17:51 +0900 - - Fix predicate to assert if object is same - -commit 792d1deb949e8416d7a76d66771b286d35c8278d - Author: Nobuyoshi Nakada - Date: 2019-06-29 19:07:25 +0900 - - Escape control codes in regexp warning message - -commit 27723b699b5fbad49a7bb16936d5a7d8e80376ba - Author: Nobuyoshi Nakada - Date: 2019-06-29 18:45:24 +0900 - - Should not warn massign parameters as unused - -commit a17fba6989d6f183275f0d9fa9dc0e43781bfe54 - Author: Nobuyoshi Nakada - Date: 2019-06-29 17:55:22 +0900 - - Remove old TestTimeTZ::TZ#abbr attribute - -commit 7ba14b029c64c7f9ef080f5b22065b662145d5d5 - Author: Nobuyoshi Nakada - Date: 2019-06-29 17:52:57 +0900 - - Add max option to TestProtocol#create_mockio - - * test/net/protocol/test_protocol.rb (TestProtocol#create_mockio): - max option to limit maximum writable size at once, and unify - mock method in test_write0_multibyte. - -commit a88107c44dd08b02ed1c1b5951882b070a1eab93 - Author: git - Date: 2019-06-29 10:17:37 +0900 - - * expand tabs. - -commit 2f6cc15cdb3d64135b29cfd5ee376a5a03ebbee7 - Author: Nobuyoshi Nakada - Date: 2019-06-29 10:10:17 +0900 - - Fixed String#grapheme_clusters with wide encodings - - * string.c (get_reg_grapheme_cluster): make regexp from properly - encoded sources for wide-char encodings. [Bug #15965] - - * regparse.c (node_extended_grapheme_cluster): suppress false - duplicated range warning for the time being. - -commit 8aecc90974ab1ac87056f77e2cb3406c5c041504 - Author: Nobuyoshi Nakada - Date: 2019-06-29 10:02:04 +0900 - - Hoisted out WIDE_ENCODINGS - -commit 14da3009f029b9bec5591fb1557c13de8b708c18 - Author: git - Date: 2019-06-29 08:12:36 +0900 - - * 2019-06-29 - -commit ede056909bf20356928a28a6165b31e6c8cb6687 - Author: Nobuyoshi Nakada - Date: 2019-06-29 01:31:52 +0900 - - Set file name and line number - -commit d12d53a6c8d959687d4ecec54501f3b13a806941 - Author: Nobuyoshi Nakada - Date: 2019-06-29 01:30:43 +0900 - - Adjust caller's line number, expect the next line as here-doc - -commit 2bb217bfb7703ba923d0e1d69b2f2dddb66cc7d6 - Author: Nobuyoshi Nakada - Date: 2019-06-28 18:31:42 +0900 - - Removed unused variables - -commit d233f9175cdb869a1928234f9c24a9d5d13f437f - Author: Nobuyoshi Nakada - Date: 2019-06-28 23:17:19 +0900 - - [DOC] Re-apply r11000, 41256fd43275c8bf66460510da7ab958a802e2a2 - - * eval.c (rb_thread_kill): fix Thread#kill docs, which returns - the thread object in all cases. - - From: why the lucky stiff - -commit c718f56ed9e07f66b6d476d16c2eea81e15c37d2 - Author: aycabta - Date: 2019-06-28 22:25:35 +0900 - - Remove auto indent of continuation line - -commit 8ec877d18361054d943fdf57f89b68f4e201d2c4 - Author: Nobuyoshi Nakada - Date: 2019-06-28 17:09:18 +0900 - - Add parentheses to suppress a warning - -commit 3dba16a5d6195a673537519edb024ef1d29f7715 - Author: Nobuyoshi Nakada - Date: 2019-06-28 17:08:47 +0900 - - Test string content - -commit 5331932cd22f4dab84196eca55a05264dc0b84d7 - Author: Nobuyoshi Nakada - Date: 2019-06-28 17:08:21 +0900 - - Removed unused variables - -commit 8d04f90da486a34f54589c2835518b1d720a4253 - Author: Nobuyoshi Nakada - Date: 2019-06-28 17:07:17 +0900 - - Fixed a variable name - -commit e9bce55c12f87d783c651d415b6b79beeeb79737 - Author: Nobuyoshi Nakada - Date: 2019-06-28 16:02:47 +0900 - - Removed excess spaces - -commit 566e6b0546633f3da4f868c3a217bc3167008fdf - Author: Nobuyoshi Nakada - Date: 2019-06-28 16:02:03 +0900 - - Fixed name conflict between helper classes - -commit 35b7e8eed8ad8ac111d099eafd5a6ac1561fbf44 - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:26:54 +0900 - - Skip instead of return - -commit f8b528ba92b5cc4b84e8966dd5d5a072d076c1d1 - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:26:25 +0900 - - Suppress unused variable warnings - -commit 11571b0e95346691e634781f281b92c75608955c - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:25:12 +0900 - - Use assert_separately instead of invoke_ruby - -commit e0c4cb2ea1ac648bdd0850dd1621f5e13382b760 - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:22:27 +0900 - - Define singleton method on each new objects - -commit a0c141b6d04482ebfc4b3abf3f00a476d073226a - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:09:14 +0900 - - Suppress redefinition and void context warnings - -commit f8b64e5f2cea508d1ea93966e2039b394715bae7 - Author: Nobuyoshi Nakada - Date: 2019-06-28 15:04:25 +0900 - - Use assigned local variable - -commit c52dad0ecf0b8d87afb570d7dde508fe78d145d4 - Author: Nobuyoshi Nakada - Date: 2019-06-28 14:51:23 +0900 - - Wait for the helper thread to terminate - -commit 023360ee4b1954a54b4d87d21cfc0eb5d662d5c5 - Author: Nobuyoshi Nakada - Date: 2019-06-28 14:37:52 +0900 - - [DOC] Singleton.instance [ci skip] - -commit 2d1728b9cede877ac45f5760ebf214d25685b285 - Author: Nobuyoshi Nakada - Date: 2019-06-28 14:23:22 +0900 - - Moved Singleton.instance to get rid of redefinition - -commit 951f80f2dde2f22eab3acf53101e4c912cb60bb2 - Author: Nobuyoshi Nakada - Date: 2019-06-28 14:09:02 +0900 - - Removed unused variable - -commit ef45fd53e47975f94661ea71ce78a1c1fa442bcb - Author: Nobuyoshi Nakada - Date: 2019-06-28 14:08:29 +0900 - - Fixed the test-case class name for zsh - -commit be14f62cafff30a6127c6ff533fec6de232ba7dd - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:41:03 +0900 - - Default @debug to $DEBUG - -commit 4562dad94c6af3db5af8704b0aec64119456275d - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:36:03 +0900 - - Removed unused variable - -commit 7eaedda557f689087861e6c0e7c9abca8cd92fc1 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-28 12:37:36 +0900 - - Use block instead of explicit close - -commit 5627f744ccb5fe5f9611f99e641d35e844e0851c - Author: Kazuhiro NISHIYAMA - Date: 2019-06-28 12:37:07 +0900 - - Add `require 'test/unit'` - -commit 3120252f010b979b633f0757ea7e145ccdc224fd - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:33:24 +0900 - - Suppress void context warning in verbose mode - -commit dc7da30bedd48d2ba38ce9cac05e378f0c823b50 - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:31:21 +0900 - - Close leaked file descriptor - -commit c9bbcaccf28c2a374f6530a36355b6d6f16e25cc - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:27:11 +0900 - - Suppress unused variable warning with RUBYOPT=-w - -commit ff7f71b28889e043798dddfec568083cc7db204a - Author: Nobuyoshi Nakada - Date: 2019-06-28 12:02:33 +0900 - - O_EXCL has no meaning for fdopen - - "exclusive access mode is not supported" exception has resulted in - empty "rubyheap-*.json" files after test/objspace/test_objspace.rb. - -commit 14b0c94ac38c40459d908fd4c5778efa60e4689f - Author: Jeremy Evans - Date: 2019-06-28 08:57:19 +0900 - - Fix documentation for Net::SMTPServerBusy - - Fixes [Bug #11628] - -commit a2091c3023a6741049d20beffbe8c94c2d5f4732 - Author: Benoit Daloze - Date: 2019-06-28 04:21:33 +0900 - - Update to ruby/spec@94d98ff - -commit 632a97227e0821bd7bedcf3f053b16e6b0b753fa - Author: git - Date: 2019-06-28 04:04:45 +0900 - - * 2019-06-28 - -commit d80e44deec77678fe2d72f94c17b2409b3e794d5 - Author: Benoit Daloze - Date: 2019-06-28 04:02:36 +0900 - - Update to ruby/spec@8d74d49 - -commit c940397116c5aef76b1c0d05561c11d43ef596a7 - Author: Benoit Daloze - Date: 2019-06-28 04:02:33 +0900 - - Update to ruby/mspec@ca2bc42 - -commit 310a42e89c431f9650c6727f934f35c5e6f9a6cc - Author: Takashi Kokubun - Date: 2019-06-27 22:32:26 +0900 - - Explain rubyspec Travis job in job name - - Eregon did not want https://github.com/ruby/ruby/commit/7b9dd379bfe4d597acfe4c26365feff61dabd488 - because people only see Travis job name and don't see .travis.yml. - - I believe the new job name is simple and informative enough to explain - why it exists. - -commit 1f7cb4bee9f711d07a5b31f439f621a2557e7505 - Author: Nobuyoshi Nakada - Date: 2019-06-27 17:18:24 +0900 - - Omit `EXPR_` prefix to show lex_state - -commit 9247f6fcc066280ca62f2fdf2902bb72c7880f44 - Author: Benoit Daloze - Date: 2019-06-27 19:06:39 +0900 - - Expand and clarify documentation about version guards for specs - -commit 2c02d5714e401159f0221d3c2d461bc79db61e3a - Author: Benoit Daloze - Date: 2019-06-27 18:57:23 +0900 - - Add a comment explaining what to do if specs fail on Ruby 2.4 - -commit 7b716bc52a5d4d000a0cee0841109c243cfcf6db - Author: Nobuyoshi Nakada - Date: 2019-06-27 16:57:31 +0900 - - Show the parser states in pretty_print too - -commit 2fd03fd7e651d5f0bf78e315eafdde5468c1de53 - Author: aycabta - Date: 2019-06-27 16:03:43 +0900 - - EXPR_LABEL also indicates non-continuation line - - Example: - - [ - 1, # this is not continuation line - 2 - ] - -commit 097554855c1a9404f3220bcc5c1906cc62399b59 - Author: Nobuyoshi Nakada - Date: 2019-06-27 15:16:15 +0900 - - Fix ripper fatal - - * parse.y (parser_yylex): return END_OF_INPUT at unterminated here - document instead of an error. [Bug #15962] - -commit 2a56702eeea5a571eaa2af15967c6535395e83a2 - Author: Nobuyoshi Nakada - Date: 2019-06-27 15:13:45 +0900 - - Test for unterminated here-docs - -commit c86a9e6592c2cb37734cf29d81a8f9d26a4340b3 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-27 11:17:03 +0900 - - bc mode is already removed [ci skip] - -commit d6bcf367936e92b8662dce969bc6b48ae2112d45 - Author: aycabta - Date: 2019-06-27 10:59:08 +0900 - - EXPR_CMDARG also indicates the end of an expression - -commit 7172ab0ec523fd190f661f52e999307d2e34429f - Author: Jeremy Evans - Date: 2019-06-27 07:21:59 +0900 - - Use native coroutine implementation on OpenBSD-amd64 - - When using native fibers, do not load ucontext, as it isn't needed. - -commit 24c4e6dec109e105c13bd4c1b7f7cd51e534a3c3 - Author: aycabta - Date: 2019-06-27 01:25:22 +0900 - - Increase indent of continuation line - - v = - 3 # auto indent - -commit df3c94712be83982301abaf49942052f0e6ae0fe - Author: git - Date: 2019-06-27 01:21:53 +0900 - - * 2019-06-27 - -commit 72bfc52de67d774316ca872a036476aa51886ab0 - Author: aycabta - Date: 2019-06-27 01:20:44 +0900 - - Decrease indent by closing token correctly - -commit d004989ac6355bcf2840ed190aae139c3a852848 - Author: Jeremy Evans - Date: 2019-06-26 23:53:54 +0900 - - Do not attempt to use ucontext for fibers on OpenBSD - - OpenBSD does not support ucontext. - - There may be a more generic way to handle this, using the result - of AC_CHECK_HEADERS(ucontext.h). - -commit 1235e054eb100fcd75f03d2f22dbbd4952bbaf31 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-26 21:44:42 +0900 - - [DOC] Add spaces [ci skip] - -commit d9a055a721f838fb5ed159fdd14497407dfad765 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-26 21:44:20 +0900 - - [DOC] Fix svn account [ci skip] - -commit acb67472c7da459812aa9008cf8cfbedcdddea67 - Author: Samuel Williams - Date: 2019-06-26 19:02:19 +0900 - - Restore updated implementation of arm32 coroutine code, but prefer ucontext. - -commit ba17127e992a4d1fb1fbd58869cbb4f12ff76227 - Author: aycabta - Date: 2019-06-26 18:41:42 +0900 - - Decrease nesting level when closing token comes at a non-first token of line - -commit 28eeaed8a9ec2557e8f8d42d8ab3e7cad310a8a9 - Author: Yusuke Endoh - Date: 2019-06-26 17:22:46 +0900 - - Revert "coroutine/arm32/Context.S: save/restore the registers via stack" - - This reverts commit 6df1814c08df93bbc0b3e7a73649bcf82e126064. - - It caused a SEGV again: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190626T051707Z.fail.html.gz - -commit 6c6bf9ffcbfeb8be9d9c342e7604b74ec819e88a - Author: Samuel Williams - Date: 2019-06-24 20:54:19 +0900 - - Add `ucontext` coroutine implementation for generic fallback. - -commit a84a99ffabf04d90be64ff28cf2e11766f6cce52 - Author: Yusuke Endoh - Date: 2019-06-26 16:01:45 +0900 - - test/ruby/test_array.rb (test_sort_with_replace): run in a subprocess - - This test invokes GC.start 100 times, which takes approx. six minutes in - Solaris. This change runs the test in a separated process, which makes - GC.start faster. - -commit 04bc4c0662344238a556aa92f5f8f6d42586bab3 - Author: John Hawthorn - Date: 2019-06-26 01:01:57 +0900 - - Resize capacity for fstring - - When a string is #frozen, it's capacity is resized to fit (if it is much - larger), since we know it will no longer be mutated. - - > puts ObjectSpace.dump(String.new("a"*30, capacity: 1000)) - {"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"... - > puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze) - {"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"... - - (ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize) - - Previously, if we dedup into an fstring, using String#-@, capacity would - not be reduced. - - > puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000)) - {"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"... - - This commit makes rb_fstring call rb_str_resize, the same as - rb_str_freeze does. - - Closes: https://github.com/ruby/ruby/pull/2256 - -commit fe0ddf0e58e65ab3ae3d6e73382c3bebcd4541e5 - Author: Nobuyoshi Nakada - Date: 2019-06-26 15:01:01 +0900 - - `ensure` is not a continuous line - -commit 6df1814c08df93bbc0b3e7a73649bcf82e126064 - Author: Yusuke Endoh - Date: 2019-06-26 14:08:10 +0900 - - coroutine/arm32/Context.S: save/restore the registers via stack - - Retry of 518adcca0a and dbe232e24e - -commit 51361272f9efca3eb0e1acb620ac62b576ddbb04 - Author: Jeremy Evans - Date: 2019-06-26 02:59:26 +0900 - - Respect --dest-dir when removing old default gems - - Before this, tool/rbinstall would try to remove a gem file that - it may not have access too. - - Fixes issue introduced in f550da512cefbe0283106ca839c4836a98efaf3a. - -commit a3d1cacda634b83032f79774d9a0e9e0c9c24cc8 - Author: Nobuyoshi Nakada - Date: 2019-06-26 08:43:08 +0900 - - Decrease indent at "elsif" too - -commit ea8bc6822da742f5818b13f444b5670a0e041dae - Author: Nobuyoshi Nakada - Date: 2019-06-26 08:37:14 +0900 - - Remove other debug prints - -commit e478671e19e09bf50ceb52efa720a8c520d87704 - Author: Hiroshi SHIBATA - Date: 2019-06-26 09:23:02 +0900 - - Added version guard for backtrace printing feature of psych to ruby/spec. - -commit cfa1a1843167e9dc8404403d3a64a506c3d6ce92 - Author: aycabta - Date: 2019-06-26 08:07:58 +0900 - - Remove debug print...sorry - -commit 0f28094201d86d4bf8d5ecb6061abbbf5cea5076 - Author: Jeremy Evans - Date: 2019-06-26 03:18:08 +0900 - - Improve wording of Local Variables and eval section - - As pointed out by nobu, "defined" should be used instead of "assigned". - -commit 0aa8c3d88bb2f59bede47164a5da20600cce399e - Author: git - Date: 2019-06-26 01:53:22 +0900 - - * 2019-06-26 - -commit dd57442f74024af465a16b7e19a34d0fc8533a53 - Author: git - Date: 2019-06-26 01:53:19 +0900 - - * remove trailing spaces. - -commit 0bd5f846df2f6268f653773e0cd4a20e2a944646 - Author: Jeremy Evans - Date: 2019-06-25 05:55:31 +0900 - - Document local variable interactions with eval - - Fixes [Bug #13337] - -commit 730aeb2523fadd816b07e0e5322fb79841efc709 - Author: Yusuke Endoh - Date: 2019-06-25 23:31:49 +0900 - - Revert 518adcca0a and dbe232e24e - - 518adcca0a: "Try using arm32 implementation for fibers." - dbe232e24e: "Order of arguments might be incorrect in arm32 coroutine implementation." - - It seems to cause SEGV consistently on Ubuntu armv7l eabihf: - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190625T081710Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190625T111708Z.fail.html.gz - -commit 57e1a69ea38d30bc249553e5fe15295ae0f5af81 - Author: aycabta - Date: 2019-06-25 22:07:32 +0900 - - Treat auto indent with newline correctly - -commit 0b57f9b25d43c2efec8ac17c0c03ce9fa461937a - Author: aycabta - Date: 2019-06-25 22:00:29 +0900 - - Decrease indent when "else", "rescue", "ensure", "when", or "in" come - -commit 1cbc4f987656ac8d8ede6c7cd178ac8e6c2a909b - Author: Yusuke Endoh - Date: 2019-06-25 17:20:01 +0900 - - test/net/imap/test_imap.rb: use Thread#stop? to wait for server thread - - Still timeout occurs. Retry for 5dd8fdd3f328f741fae4abba00c478e8a51d2a7e. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20190625T032405Z.fail.html.gz - -commit d7887b05d810e7e3188d25ed91364d5850d92cd7 - Author: Hiroshi SHIBATA - Date: 2019-06-25 16:46:42 +0900 - - Fixed broken ruby/spec related a53ab897c35586a836710a8afeb1e8c1abd9b087 - -commit 746812ee9645ff821a039136f9576b7c8f18b920 - Author: Jean Boussier - Date: 2019-04-27 02:38:43 +0900 - - Do not allocate a string to check if a scalar is an integer - -commit 5a4d2b9f2f1cb5124a4dccc103c7bbe8d27554d5 - Author: Jean Boussier - Date: 2019-04-27 01:57:03 +0900 - - Remove string_cache in ScalarScanner - -commit 63f78bbaaea4bb0b7009e50a938ef146416c53c2 - Author: Jean Boussier - Date: 2019-04-26 20:26:14 +0900 - - Reduce string allocations in scalar_scanner - -commit 00d0ede84593aa18203fe33d1056ffb1b1aedf99 - Author: SHIBATA Hiroshi - Date: 2019-02-27 08:44:33 +0900 - - Removed CHANGELOG from rdoc files. - -commit 3c4fc830dd3f2c3e1e642f83072bead8189aec63 - Author: SHIBATA Hiroshi - Date: 2019-02-26 15:56:55 +0900 - - Retired to write CHANGELOG.rdoc. Because It has no update from 2015. - -commit 03dac55f90bd6b842ffe90b6bfa98af5c0897513 - Author: Aaron Patterson - Date: 2019-01-17 03:46:34 +0900 - - Dump Hash ivars before elements - - When the Hash is revived, the ivars will be set before elements. This - is for the case when the hash setter depends on ivars set on the hash. - -commit 0016edbead23f2a9b4fa17bcec2798b5bf6a4c07 - Author: Jordan Owens - Date: 2019-01-16 14:29:12 +0900 - - Add test to demonstrate issue deserializing hash with ivar - - Currently the elements of a hash are revived before any ivar values. - This causes an issue when the `[]=` method references an instance - variable. - -commit a53ab897c35586a836710a8afeb1e8c1abd9b087 - Author: Aaron Patterson - Date: 2019-01-10 06:34:51 +0900 - - Round trip exception backtraces - - This commit allows exception backtraces to round trip - -commit f770a5be66412fcbdb238db950c80367100a257e - Author: Aaron Patterson - Date: 2019-01-10 06:28:08 +0900 - - Refactor exception dumping - -commit 4bd190942710725a79ca61fb30cff152888b55d0 - Author: Aaron Patterson - Date: 2019-01-10 06:25:09 +0900 - - Dumping the backtrace never worked, so remove it - - Dumping the backtrace for exceptions never worked, so lets remove it. - -commit d118c84b0b9110462e479487ffaf175a75e5718e - Author: Jeremy Evans - Date: 2019-06-15 09:50:31 +0900 - - Fix IO#scanf on pipes on Windows - - IO.seek on a pipe on Windows raises Errno::EINVAL instead of - Errno::ESPIPE. - - Fixes Ruby Bug #15199 - -commit e572ff2f953b774c372e31894f7bf9e86b3ea6fa - Author: David Rodríguez - Date: 2019-04-30 23:21:45 +0900 - - Require version file relatively - -commit 083fda8490210e5fb0bcfb7c0b49ac3df8f49452 - Author: SHIBATA Hiroshi - Date: 2019-03-27 16:53:54 +0900 - - Bump version to 1.2.0. - -commit 9b23aab290c9f0cbbc795282c5e90b6581452b58 - Author: Hiroshi SHIBATA - Date: 2019-06-25 11:51:25 +0900 - - Fixed the wrong path for io-console. - -commit dbe232e24e56cb200b8e5b78062c8a2784a792e9 - Author: Samuel Williams - Date: 2019-06-25 14:04:04 +0900 - - Order of arguments might be incorrect in arm32 coroutine implementation. - -commit e09afd15b797bc61a6ba93e3d1d32be11707404a - Author: git - Date: 2019-06-25 00:19:49 +0900 - - * 2019-06-25 - -commit 9c19cd5222a09481f0dd2d6470db38717e551989 - Author: aycabta - Date: 2019-06-24 23:58:50 +0900 - - Refactor calculation of corresponding token depth - -commit 518adcca0a2c611c4a94eaa778f9dcec4aff03f9 - Author: Samuel Williams - Date: 2019-06-24 16:09:16 +0900 - - Try using arm32 implementation for fibers. - -commit 4275f09015295a3f58dbe0aedede0d039f262499 - Author: NARUSE, Yui - Date: 2019-06-24 15:56:18 +0900 - - remove UNREACHABLE - -commit 97b4fe2ff6bffe8728952236f2027aa6242f8f40 - Author: Luke Gruber - Date: 2019-06-24 04:28:22 +0900 - - array.c: Wrong heap size given to ruby_sized_xfree when freeing shared roots - - Fixes [Bug #15953] - - Closes: https://github.com/ruby/ruby/pull/2253 - -commit 7f64a0b4db7ee27a04579236950d88301c7bcabb - Author: NARUSE, Yui - Date: 2019-06-17 08:50:44 +0900 - - Add new encoding CESU-8 [Feature #15931] - -commit 0e6396d2ac8bc3803742655896bb0fad70007dda - Author: Samuel Williams - Date: 2019-06-24 12:13:10 +0900 - - Try using arm64 implementation for fibers. - -commit abdbfebad11471e76e1e9756de7f9bc14bd30355 - Author: Samuel Williams - Date: 2019-06-24 12:12:21 +0900 - - Use spaces for indentation in `configure.ac`. - -commit 5d4dfcd808c49c9542a5ccaa5ada58a81c4e9ae9 - Author: git - Date: 2019-06-24 11:25:17 +0900 - - * remove trailing spaces. - -commit a071bed7a5041e3d3e7029f73c3f09a9f6cdfd98 - Author: Samuel Williams - Date: 2019-06-24 11:24:49 +0900 - - Print warning if not using native coroutine. - -commit 0b36c90e122a3687ce1049eedae623d77fa808bd - Author: git - Date: 2019-06-24 10:24:51 +0900 - - * 2019-06-24 - -commit edbad4adcc080fc7eada5ea367f0a61035a8d7cf - Author: masakazutakewaka - Date: 2019-06-20 03:22:52 +0900 - - httpstatus.rb 100% coverage - -commit c6229e7c692056940b1aec8af133e87883a76890 - Author: Rob - Date: 2019-03-31 02:28:22 +0900 - - Adds WebAssembly MIME type - -commit 11a60f9bdb486b5173946a7eb11b41e5f75a28cd - Author: Nobuyoshi Nakada - Date: 2019-03-09 19:53:51 +0900 - - Remove extraneous spaces at the end of status line - - Remove extraneous spaces after the status code that is - non-compliant with RFC, i.e `HTTP 200 OK `, to unnecessary - confusion for WEBrick users, by a risk that WEBrick instances in - the wild will have server responses flagged as suspicious or - malicious due to a similar bug in [Cobalt Strike - misconfiguration]. - - Reported by Matt Tennis - - [Cobalt Strike misconfiguration]: https://blog.fox-it.com/2019/02/26/identifying-cobalt-strike-team-servers-in-the-wild/ - -commit 97a7f463f683774f054f9d7dafc3756aad39dd1c - Author: Nobuyoshi Nakada - Date: 2019-06-23 23:12:47 +0900 - - Max length of UNIX socket path is 104 bytes on macOS - -commit 50b2807a7cc74dc1772496986ee2f3efef85a5db - Author: Nobuyoshi Nakada - Date: 2019-06-23 23:10:16 +0900 - - Do not lengthen UNIX socket path - - * spec/ruby/library/socket/unixsocket/recvfrom_spec.rb: do not - lengthen UNIX socket path, which is very stricted. - -commit bdcfba547df70d61abb8db10c32f56f9508f6da5 - Author: Nobuyoshi Nakada - Date: 2019-06-23 18:28:32 +0900 - - vcs.rb: handle --dryrun option - -commit 096a45d3d2c6ab0c40ec2d41bdb3a26cda091e6b - Author: Samuel Williams - Date: 2019-06-23 22:28:23 +0900 - - Update NEWS. - - - Add note regarding IA64 removal. - - Add note about Thread allocation performance improvements. - -commit 5a187e26adc8aa32367f294c1496935c7356d386 - Author: Luke Gruber - Date: 2019-06-23 11:22:23 +0900 - - array.c add back shared array optimization to ary_ensure_room_for_unshift - - Bug fix in commit ec8e5f5aa64e2a [Bug #15952] disabled an - optimization in this function. - - Closes: https://github.com/ruby/ruby/pull/2252 - -commit ec8e5f5aa64e2a54cf1e303f2b012c98e8d521ba - Author: Luke Gruber - Date: 2019-06-23 07:37:08 +0900 - - array.c: always check frozenness in Array#unshift. Fixes [Bug #15952] - - Closes: https://github.com/ruby/ruby/pull/2251 - -commit 3840791b7ebb2442724d96c69a791d0e678fbc6c - Author: Nobuyoshi Nakada - Date: 2019-06-23 07:56:43 +0900 - - Get rid of error with frozen string literal - - [Bug #14194] - -commit bebe8d13f8e14dffa9d1828f6e9805773dc30518 - Author: Nobuyoshi Nakada - Date: 2019-06-23 07:42:11 +0900 - - Disable frozen-string-literal to disable deduplication - - [Bug #14194] - -commit 2ad7a7f801c07f18150116b819530840eeefebf8 - Author: MSP-Greg (Greg L) - Date: 2019-06-23 07:33:15 +0900 - - Get rid of error with frozen string literal - - [Bug #14194] - -commit aa2f505825a914d1c5480d4e92696a1fa1ad0887 - Author: Nobuyoshi Nakada - Date: 2019-06-23 02:49:39 +0900 - - Make autoloading_const_entry static - -commit c5c3486340b67b6f6f6f980f2c3fa76780561767 - Author: git - Date: 2019-06-23 01:47:40 +0900 - - * expand tabs. - -commit ef524c13d96c645fd00c17267a553275adb0b106 - Author: Nobuyoshi Nakada - Date: 2019-06-23 01:44:07 +0900 - - NEWS: Module#constant_source_location - - [Feature #10771] - -commit 93843830198ba436e2ea21a60a11758d47cf521b - Author: Nobuyoshi Nakada - Date: 2018-12-13 21:49:05 +0900 - - Module#constant_source_location [Feature #10771] - -commit 5084233b88cc48a74b58690423df1129668d5706 - Author: Nobuyoshi Nakada - Date: 2018-12-13 18:27:32 +0900 - - Split global search for module - -commit 151843b9816b52b1ddb1e9b2040991a7de4173c6 - Author: Nobuyoshi Nakada - Date: 2018-12-13 18:12:07 +0900 - - Hoisted out autoloading_const_entry - -commit c033dc3073839e3578f1ba25d53b837974b56474 - Author: Luke Gruber - Date: 2019-06-23 00:25:52 +0900 - - Fix issue with Array#rindex when rb_equal modifies receiver array - - Fixes [Bug #15951] - - Closes: https://github.com/ruby/ruby/pull/2250 - -commit fd9ac1e76bc8b347ad55fdf5991839c1df4e891a - Author: git - Date: 2019-06-23 00:37:11 +0900 - - * 2019-06-23 - -commit f3c81b4e90ec492382e299573f2c3ac272adbb5f - Author: Nobuyoshi Nakada - Date: 2019-06-23 00:31:16 +0900 - - Frozen objects in WeakMap - - * gc.c (wmap_aset): bypass check for frozen and allow frozen - object in WeakMap. [Bug #13498] - -commit f5e29044710e74249e89bbb0f112dc22e5b91398 - Author: Nobuyoshi Nakada - Date: 2019-06-22 23:44:19 +0900 - - Use EXEEXT - - * test/lib/minitest/unit.rb (MiniTest::Assertions.diff): use - `EXEEXT` configured value instead of switching by hard coded - `host_os`. - -commit f738eeabc251c556feda1f9f22c060dac85054e1 - Author: Nobuyoshi Nakada - Date: 2019-06-22 23:38:07 +0900 - - golf_prelude.rb: suppress the redefining warning - -commit bad66f3e369810e1cca90493830d5e06485c3c30 - Author: Nobuyoshi Nakada - Date: 2019-06-22 18:39:06 +0900 - - Show timed out threads - - * test/lib/test/unit/assertions.rb (assert_join_threads): kill and - show timed out threads. - -commit 4d650bc25737a4d2c0dcc9d4c845688cb5dc85ce - Author: Nobuyoshi Nakada - Date: 2019-06-22 09:29:33 +0900 - - Fix over-expansion - - * test/lib/minitest/unit.rb (MiniTest::Assertions#mu_pp_for_diff): - do not expand escaped backslash followed by 'n'. - -commit d01fd821875b989affc36e54e98f5dd67f47062e - Author: Kenichi Kamiya - Date: 2019-06-21 12:28:28 +0900 - - Alias ENV.merge! as ENV.update - - [Feature #15947] - - Closes: https://github.com/ruby/ruby/pull/2246 - -commit 3b2d11ad90fcb64b41acc9006dfd1e40b4bd9000 - Author: Benoit Daloze - Date: 2019-06-22 01:21:16 +0900 - - Use different names for autoload constants in specs for clarity - -commit e5e811e4a04482a5ad764fbb2b792ee5fbdd7195 - Author: Jean Boussier - Date: 2019-05-07 19:52:24 +0900 - - Add extra spec from https://github.com/ruby/ruby/pull/2173 - -commit 2f2fc939eb13af9baa325f154872f60cdeff973c - Author: Nobuyoshi Nakada - Date: 2019-06-22 01:16:23 +0900 - - Always define RUBY_RELEASE_DATETIME - -commit c79131df283b6291029e96fbb5d1943aa26dc1c1 - Author: aycabta - Date: 2019-06-22 00:31:30 +0900 - - Treat closing token with starting token at head of 2nd line correctly - - v = - if true # starting token at head of 2nd line - 3 - end # closing token - -commit 5e2088665b938cd68587999f4d105331cd1feeea - Author: aycabta - Date: 2019-06-21 21:57:19 +0900 - - Do auto indent only when closing token at first of line - - if true - 3; end # this isn't auto-indented - -commit d1fa0f61918063717bba6bab15932ec69c655b81 - Author: git - Date: 2019-06-22 00:03:27 +0900 - - * 2019-06-22 - -commit 8a1dd9b84b02737cf43e62439730caec678cccf5 - Author: Nobuyoshi Nakada - Date: 2019-06-21 23:45:39 +0900 - - Revert RUBY_RELEASE_DATE to date only - -commit 1c7e303b26090205f393595f15dadddd4b2d31b6 - Author: Nobuyoshi Nakada - Date: 2019-06-21 23:03:36 +0900 - - Constified unusable chars - -commit 551ef27490bf380e46453846c040b48596f34a6a - Author: git - Date: 2019-06-21 22:48:50 +0900 - - * expand tabs. - -commit 8f51da5d41f0642d5a971e4223d1ba14643c6398 - Author: Nobuyoshi Nakada - Date: 2019-06-21 22:42:14 +0900 - - Get rid of undefined behavior - - * string.c (rb_str_sub_bang): str and repl can be same. - [Bug #15946] - -commit 50841eca43d2840df54804392afa67bca5f53c0f - Author: aycabta - Date: 2019-06-21 21:31:56 +0900 - - Support irregular auto indent - - v = - if true - 3 - end # this "end" is auto-indented correctly - -commit 38ccb8f74753c6c3d3e47ab612691bd01148eb90 - Author: Shugo Maeda - Date: 2019-06-21 18:02:24 +0900 - - Remove a duplicate test - -commit 16729f64306941a2662c8361d452e86998fc1239 - Author: Nobuyoshi Nakada - Date: 2019-06-21 17:53:32 +0900 - - Remove duplicate functions - -commit 432b28af9017c91a8032c532e9ddbe11c2d33845 - Author: git - Date: 2019-06-21 17:43:21 +0900 - - * expand tabs. - -commit 702cf3ec9051914c8ef5a353580e0e74f7ec7005 - Author: Shugo Maeda - Date: 2019-06-21 17:27:20 +0900 - - Enumerator::Lazy should support filter_map - - Fixes [Bug #15949] - -commit 35392ff0a00934ec02558305b7be8dffe6420d30 - Author: Nobuyoshi Nakada - Date: 2019-06-21 17:40:28 +0900 - - Fix an example [ci skip] - -commit c997f7daaa833ec02a852913925b361cd94fd2e8 - Author: git - Date: 2019-06-21 17:29:08 +0900 - - * expand tabs. - -commit 5b7cc63d114fbca641ce2d93c7b3f2117e38af60 - Author: Nobuyoshi Nakada - Date: 2019-06-21 17:21:34 +0900 - - Turned `recur` into `int` [Feature #15777] - -commit fb85a428605265a8fd449b0702a4dd88cb6f3b20 - Author: Jean Boussier - Date: 2019-05-07 19:52:24 +0900 - - Add an optional `inherit` argument to Module#autoload? - - [Feature #15777] - - Closes: https://github.com/ruby/ruby/pull/2173 - -commit 887163beb8f27c5400cd04dbf98c474ed035526f - Author: Kazuhiro NISHIYAMA - Date: 2019-06-21 17:08:42 +0900 - - Fix call-seq of lazy.filter_map [ci skip] - -commit 0174285e8cfea1ab7fa8dbbb6ab7607d74c20b9d - Author: git - Date: 2019-06-21 16:31:42 +0900 - - * expand tabs. - -commit 06a622b76e20b8996cd6d66c11ac7819a0996fae - Author: Nobuyoshi Nakada - Date: 2019-06-21 16:28:39 +0900 - - Lazy filter_map - -commit 4149fd60786527121d42e3d6f12d1447505d22fa - Author: Espartaco Palma - Date: 2019-06-21 14:46:24 +0900 - - Fix small typo on block_scanf example [ci-skip] - - Closes: https://github.com/ruby/ruby/pull/2247 - -commit fde842fec06b39f95eeed9ce095065d294fd2a65 - Author: Nobuyoshi Nakada - Date: 2019-06-21 03:19:42 +0900 - - Clean coroutine and timestamp directories - -commit 2ee1c762064d0ef78a22ca7e0eb63be4e0a93fa3 - Author: git - Date: 2019-06-21 02:28:27 +0900 - - * 2019-06-21 - -commit 4a5e07d8e17a0f62810f983114a88cb1011f971b - Author: Jeremy Evans - Date: 2019-06-21 02:22:01 +0900 - - Avoid verbose warning when using Net::POP3 with SSL - - Patch from Jos Kamphorst. - - Fixes [Bug #14822] - -commit 93356576fec17b1c7cafd56fc4a633776cb8169f - Author: Hiroshi SHIBATA - Date: 2019-06-20 22:27:06 +0900 - - Revert "Removed needless file with the upstream repository." - - This reverts commit 5bbfca7b1d4be89d4728203b4610de17bccbefd7. - -commit 1f0762ad2194aef6457c6687e2e536bb695193bf - Author: Nobuyoshi Nakada - Date: 2019-06-20 19:27:27 +0900 - - Suppress messages from mkmf - -commit 9e7a8a4351de0690b3d531c4be4fbb6fc8f4f813 - Author: Samuel Williams - Date: 2019-06-20 20:12:42 +0900 - - Only ignore build directories. - -commit f607e433520218ac2adc93fcf32bc3b797219a60 - Author: Samuel Williams - Date: 2019-06-20 17:29:35 +0900 - - Transition root fiber into state FIBER_TERMINATED. - - During fork, it's possible that threads with root fibers are terminated, - but fiber state is not updated. `fiber_verify` will subsequently fail. We - forcefully enter the FIBER_TERMINATED state when terminating the root - fiber. - -commit 3077cb6912033d18f4d34fd64011e9f8e9502b99 - Author: Nobuyoshi Nakada - Date: 2019-06-20 18:20:38 +0900 - - Restore $VERBOSE - -commit e31602b78d975741532b9e04a83fa5b67f85c31c - Author: Nobuyoshi Nakada - Date: 2019-06-20 17:41:01 +0900 - - Suppress warnings - -commit e6fbdde229fa07a59f372e4c9c297f9cb29cc0a8 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-20 17:40:08 +0900 - - Fix a typo [ci skip] - -commit 3aa8691d521519f0dc23d56be3b1fe633632720e - Author: Hiroshi SHIBATA - Date: 2019-06-20 16:10:24 +0900 - - Added and update the racc entries on doc/*. - -commit 557bcd877490092c826a56789d78dc73f8ad0321 - Author: Hiroshi SHIBATA - Date: 2019-06-20 15:59:20 +0900 - - Added racc entry to NEWS. - -commit 5bbfca7b1d4be89d4728203b4610de17bccbefd7 - Author: Hiroshi SHIBATA - Date: 2019-06-20 15:00:54 +0900 - - Removed needless file with the upstream repository. - -commit 71ebf6d8e5fa6ebc2f5f25c59c73a50f4c611b6a - Author: Hiroshi SHIBATA - Date: 2019-06-20 15:00:40 +0900 - - Update sync task for the directory structure of cparse and ignore JRuby files. - -commit 45e939f5adcb3f16682e7a957d7ecf91edc005e4 - Author: Hiroshi SHIBATA - Date: 2019-06-20 14:31:41 +0900 - - Added gemspec of racc generated from upstream for the default gems. - - 1.4.16.pre.1 is the teemporary version. It may be changed 1.5.0 or others. - -commit c4c47b792dc8360f2541a399e9fcf417d068eee3 - Author: aycabta - Date: 2019-06-20 15:56:10 +0900 - - Disable auto indent when move cursor up or down - - This commit suppresses a strange behavior below: - - if true - 1[cursor] - end - - and press down key - - if true - 1 - end - -commit e4cafa393f8fd4aa207f20b1d122884b4de99cf1 - Author: Samuel Williams - Date: 2019-06-20 08:31:22 +0900 - - Ensure that vm_stack is cleared in `thread_cleanup_func_before_exec`. - - If `vm_stack` is left dangling in a forked process, the gc attempts to scan - it, but it is invalid and will cause a segfault. Therefore, we clear it - before forking. - - In order to simplify this, `rb_ec_clear_vm_stack` was introduced. - -commit c26c51449461e3c8ee9bb4e1800933fb3d3caf67 - Author: Samuel Williams - Date: 2019-06-20 12:30:29 +0900 - - Revert failed attempt at fixing invalid usage of vm_stack. - -commit 7d9d1ed463323fe28f24d0b94212c2cb7ad109bd - Author: Samuel Williams - Date: 2019-06-20 11:55:43 +0900 - - Don't clear cfp, it causes problems. - -commit 15c4f6aed29b4f9f8d2c911548ac87756239b592 - Author: Samuel Williams - Date: 2019-06-20 11:16:08 +0900 - - Skip `rb_ec_clear_vm_stack` for now. - -commit 199310997f40e0989f218d109b56d2e592494791 - Author: git - Date: 2019-06-20 10:41:46 +0900 - - * remove trailing spaces. - -commit dbc2b89bc042d73e60aeb7d56686aa28d82e2622 - Author: Samuel Williams - Date: 2019-06-20 10:41:18 +0900 - - Ensure `vm_stack` is cleared after fork. - -commit 6bf1285b2069ff736e283a1f8328852e3175fccc - Author: Samuel Williams - Date: 2019-06-20 09:07:15 +0900 - - Fix typo in VM_ASSERT. - -commit 626483721ae297ecb641a36b7bb39fc6d6490c82 - Author: Samuel Williams - Date: 2019-06-20 08:56:06 +0900 - - Set `cfp` to null (along with vm_stack) in `rb_fiber_close`. - -commit 25049a6e818d879aecb88379753f1e215b915f93 - Author: Samuel Williams - Date: 2019-06-20 08:32:08 +0900 - - Extra assertions around thread. - -commit 91c4ef01512d1ba285ccb3c3cb03e611257790e8 - Author: Samuel Williams - Date: 2019-06-20 08:31:22 +0900 - - Don't try to dereference NULL cfp. - -commit a0af60c7f2d852faa6d3263874224dd7950bda43 - Author: Jeremy Evans - Date: 2019-06-13 23:55:26 +0900 - - Remove spec testing undefined behavior - - Fixes [Bug #15432] - -commit 208cc6e3d03cb95ec62a8515e4e79db183d30567 - Author: git - Date: 2019-06-20 04:07:35 +0900 - - * 2019-06-20 - -commit fdfe51d16984b80fe782cb434bba7aeb629c279f - Author: git - Date: 2019-06-20 04:07:31 +0900 - - * expand tabs. - -commit b9ef35e4c6325864e013ab6e45df6fe00f759a47 - Author: Jeremy Evans - Date: 2019-06-05 13:41:02 +0900 - - Implement Complex#<=> - - Implement Complex#<=> so that it is usable as an argument when - calling <=> on objects of other classes (since #coerce will coerce - such numbers to Complex). If the complex number has a zero imaginary - part, and the other argument is a real number (or complex number with - zero imaginary part), return -1, 0, or 1. Otherwise, return nil, - indicating the objects are not comparable. - - Fixes [Bug #15857] - -commit 65944e96d39a8ae3602751f49cb337335b2c6c45 - Author: Yusuke Endoh - Date: 2019-06-19 23:10:40 +0900 - - test/racc/test_racc_command.rb: Extend the timeout - - test_opal, test_ruby18, and test_ruby22 are slow tests. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-ad7f67/ruby-master/log/20190619T105405Z.fail.html.gz - -commit 2abe548f356756788db7f893b221938a5f775ccd - Author: Samuel Williams - Date: 2019-06-19 23:05:04 +0900 - - Don't change vm_stack/cfp without acquiring gvl first. - -commit ab6d8d0b65d42cb872707b330d6172beb8579e8b - Author: Nobuyoshi Nakada - Date: 2019-06-19 20:40:49 +0900 - - Adjust indent - -commit 659eda7f83a1c27e887f96c2e1bee687d363a187 - Author: git - Date: 2019-06-19 20:33:24 +0900 - - * expand tabs. - -commit d17344cfc56edc4599252041b3ec0d46af0851fd - Author: Samuel Williams - Date: 2019-06-19 18:06:57 +0900 - - Remove IA64 support. - -commit 40f8c82b960041d29aba028cc9fe01177bdc4f84 - Author: Hiroshi SHIBATA - Date: 2019-06-19 18:35:09 +0900 - - Partly revert directory structure for cparse. - - It break the some build environment. - -commit b93508b32c8f11bd468a885745338eab259bd2cd - Author: git - Date: 2019-06-19 18:19:20 +0900 - - * remove trailing spaces, append newline at EOF. - -commit 754df262100cc5febda728111e134e0098bb05ac - Author: Hiroshi SHIBATA - Date: 2019-06-19 16:08:55 +0900 - - Added binstub for racc executables. - -commit 2b4024da32018c7d63f3d051e8ece63ca3573077 - Author: Hiroshi SHIBATA - Date: 2019-06-19 12:34:34 +0900 - - Temporary disabled to invoke assert_output_unchanged. - - Because some environment created the different results from test fixtures. - -commit e892c2f924bb229ce4782d01ea0a5e2db5761f82 - Author: Hiroshi SHIBATA - Date: 2019-06-19 12:06:41 +0900 - - Restore ruby/ruby change for extconf.rb. - -commit d71032180021f4977978030b04a8d11ae5fb7337 - Author: Hiroshi SHIBATA - Date: 2019-06-02 20:50:42 +0900 - - Workaround for the external file for racc test - -commit 8a3bd06d277328cab362b0dffe99720fa5b09515 - Author: Hiroshi SHIBATA - Date: 2019-06-02 20:18:24 +0900 - - use TEMP_DIR. - -commit 4cca8c4d2021c90e351d0ee9000d448a9ed85e83 - Author: Hiroshi SHIBATA - Date: 2019-06-02 20:11:24 +0900 - - Use Test::Unit instead of Minitest and fixed test error with ruby repo. - - Co-authored-by: Nobuyoshi Nakada - -commit 2272d6ae24d4a059d57bd1b0c01587a934258084 - Author: Hiroshi SHIBATA - Date: 2019-06-02 19:56:57 +0900 - - Restore test_dir and update prefix for Dir.mktmpdir. - -commit 9ea1fc27a93c9a7a8f9aa2f8f61bc2529e93abb2 - Author: Hiroshi SHIBATA - Date: 2019-06-02 19:17:38 +0900 - - Try to use Dir.mktmpdir. - -commit 4e218282d284c7d0ea1bf3db7e5febb2dd5884f8 - Author: Hiroshi SHIBATA - Date: 2019-05-14 21:36:59 +0900 - - Added sync task for racc - -commit c110b59af5d1b1065c9e247260579e6212cb7fab - Author: Hiroshi SHIBATA - Date: 2019-05-14 21:18:57 +0900 - - Fixed path for ruby core repository. - -commit 1a2546c2be839baa7d0a50dc056d4d6987d26852 - Author: Hiroshi SHIBATA - Date: 2019-05-13 21:25:22 +0900 - - Backport racc-1.4.15 from upstream. - -commit cbe06cd3501fdadd0e6e63094da2973484d70b0b - Author: git - Date: 2019-06-19 17:39:58 +0900 - - * remove trailing spaces, expand tabs. - -commit 3e5b885cd271e42ba4cb39dc8e612714f88ec889 - Author: Samuel Williams - Date: 2019-06-19 16:09:48 +0900 - - Rework debug conditional. - -commit cb5da39f20a17bd73e791dca1e7e1832f0adbc53 - Author: Samuel Williams - Date: 2019-06-19 15:47:15 +0900 - - Use shared implementation of `rb_ec_initialize_vm_stack`. - -commit 714703805370767efb859078d5095a014417a692 - Author: Samuel Williams - Date: 2019-06-19 14:07:15 +0900 - - Update `stack_start` and `stack_maxsize` according to stack direction. - -commit dee0cfbb4757ca954853de48814367c51f255933 - Author: Samuel Williams - Date: 2019-06-06 12:02:35 +0900 - - Specify that size is non-committed memory. - -commit 561c9bcf3a1ce33e51c2c03e88aa3103d42f5af9 - Author: Samuel Williams - Date: 2019-06-06 08:04:24 +0900 - - Make sure `alloca` fast path is used (inline assembler). - -commit 7cc7269b3d3e3aff518a6cd05971422351253957 - Author: Samuel Williams - Date: 2019-06-06 07:25:08 +0900 - - Use default stack size for worker thread (no th pointer available). - -commit 9cb4e7725f668318d08cb79b1459a04eadf2f925 - Author: Samuel Williams - Date: 2019-06-06 06:54:29 +0900 - - Handle (empty) backtrace when thread is not born yet. - -commit 5855af73b8d7233bcdb18b6dda5c0058cbc315bf - Author: Samuel Williams - Date: 2019-06-06 06:54:07 +0900 - - Basic assertions for thread initialization. - -commit 8121a523c3ea68898016ab3984b6c0240ff66995 - Author: Samuel Williams - Date: 2019-06-06 06:53:25 +0900 - - Use stack size defaults for win32 threads. - -commit b8e4bea7806f481efab42f8d88ecba783c709042 - Author: Samuel Williams - Date: 2019-06-05 20:39:17 +0900 - - Track how stack was allocated for `cont_free`. - -commit 4b3b781c66c48604a013557172540effd929f96a - Author: Samuel Williams - Date: 2019-06-05 17:52:07 +0900 - - Ensure execution context is cleared after thread is finished. - -commit 38791145ebc6890b97ea55ee490084c63b67f3cc - Author: Samuel Williams - Date: 2019-06-05 15:23:04 +0900 - - Better handling of root fiber. - -commit 7c7a1c221281cdba1f48d5e42ee2f9af306d27f8 - Author: Samuel Williams - Date: 2019-06-05 10:53:19 +0900 - - Fix handling of vm_stack_size and avoid trying to deallocate it. - -commit b24603adff8ec1e93e71358b93b3e30c99ba29d5 - Author: Samuel Williams - Date: 2019-06-05 08:18:50 +0900 - - Move vm stack init into thread. - -commit 69195fd9b26d4585ad0d13d45ce9fd7b7ebac154 - Author: Samuel Williams - Date: 2019-06-19 14:53:52 +0900 - - Show thread and fiber limits as part of bootstrap tests. - -commit 3fd83cb6fcc483d2eac0795bc139c521a3a59bd2 - Author: Samuel Williams - Date: 2019-06-05 13:32:27 +0900 - - Improve benchmarks and tests for threads. - -commit a6a4e86029f16415767b579e62691f09b1fb6075 - Author: Samuel Williams - Date: 2019-06-05 13:32:06 +0900 - - Ignore `/build*`. - -commit e690df1f1ef4f791295448f9192d6e027400ee72 - Author: Nobuyoshi Nakada - Date: 2018-09-27 18:17:28 +0900 - - Marshal distant past/future - - [Feature #15160] - -commit 8797f48373dcfa3ff8e748667732dea8aea4347e - Author: Nobuyoshi Nakada - Date: 2019-06-19 14:03:02 +0900 - - New buffer for shared string - - * string.c (rb_str_init): allocate new buffer if the string is - shared. [Bug #15937] - -commit 148f50fc789d59319113a1fd2897dbe552e73e73 - Author: Takashi Kokubun - Date: 2019-06-19 10:09:35 +0900 - - Update homebrew on Travis - - because Travis is crashing like "Error: Your Homebrew is outdated. - Please run `brew update`." - https://travis-ci.org/ruby/ruby/jobs/547485832 - -commit 28678997e40869f5591eae60edd9757334426ffb - Author: Nobuyoshi Nakada - Date: 2019-06-19 09:44:26 +0900 - - Preserve the string content at self-copying - - * string.c (rb_str_init): preserve the embedded content when - self-copying with a capacity. [Bug #15937] - -commit d009e321a08d2ca401fceefa638e7e50872f5f54 - Author: aycabta - Date: 2019-06-19 09:19:41 +0900 - - Use IRB.conf[:AUTO_INDENT] setting in multiline mode - -commit c9729329862a979f2d07d7907c7a515dfcfb2ba4 - Author: git - Date: 2019-06-19 08:29:23 +0900 - - * 2019-06-19 - -commit 85ff2d74a217a02d050492e607b3a2764645107b - Author: aycabta - Date: 2019-06-19 08:28:00 +0900 - - Avoid auto indent in prompt when dynamic auto indent - -commit 84903b31c87b98083cec406745dc7e3088ba643b - Author: aycabta - Date: 2019-06-18 21:56:41 +0900 - - Fix auto indent crash when blank input - -commit 32e65e9e5adbfb8b3d67e0ec0865a3f90d2e82dd - Author: aycabta - Date: 2019-06-18 21:55:40 +0900 - - Print starting debug message with RELINE_STDERR_TTY - -commit af800b8ca25fc453da4e73b9e4628299605b5289 - Author: Takashi Kokubun - Date: 2019-06-18 21:22:06 +0900 - - Now test-bundler is not working on macOS either - - Let's stop reporting the failure until it gets stable. - We can see the build status on console with this config anyway. - -commit 235e72f17e2c02074721150035ffc30e339c307f - Author: aycabta - Date: 2019-06-18 20:57:58 +0900 - - Implement auto indent for multiline - -commit e6aa0a61fac94f16250412b8ac80657dd9d6d572 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-18 17:30:01 +0900 - - [DOC] non-nil `$,`,`$;` will be deprecated [ci skip] - - ``` - % ruby -e '$,=""; $;=""' - -e:1: warning: non-nil $, will be deprecated - -e:1: warning: non-nil $; will be deprecated - ``` - -commit 8b3774be3dd9f472bddd99e84e3c9fe2ff99d7ac - Author: Nobuyoshi Nakada - Date: 2019-06-18 13:27:05 +0900 - - Fix memory leak - - * string.c (str_make_independent_expand): free independent buffer. - [Bug# 15935] - - Co-Authored-By: luke-gru (Luke Gruber) - -commit c770c98ac42ee20129f1296d9f7c4dad2ae45124 - Author: git - Date: 2019-06-18 12:21:38 +0900 - - * expand tabs. - -commit 9dec4e8fc3a6018261834b5ac9b9877f787b97ca - Author: Alan Wu - Date: 2019-05-13 09:22:37 +0900 - - String#b: Don't depend on dependent string - - Registering a string that depend on a dependent string as fstring - can lead to use-after-free. See c06ddfe and 3f95620 for details. - - The following script triggers use-after-free on trunk, 2.4.6, 2.5.5 - and 2.6.3. Credits to @wanabe for using eval as a cross-version way - of registering a fstring. - - ```ruby - a = ('j' * 24).b.b - eval('', binding, a) - - p a - 4.times { GC.start } - p a - ``` - - - string.c (str_replace_shared_without_enc): when given a - dependent string, depend on the root of the dependent - string. - - [Bug #15934] - -commit 39a8c7142400d582ac4bb02a1804a5949f8da9bc - Author: git - Date: 2019-06-18 06:05:43 +0900 - - * 2019-06-18 - -commit c8edf70cd20b9ff72ebd1e9402a556089f6ff204 - Author: Jeremy Evans - Date: 2019-06-12 04:05:04 +0900 - - Update documentation for File.executable{,_real}? to mention Windows issues - - Fixes [Bug #15664] - -commit 801d0d9dd72209dab238e3d580ad1ab8116fd8fe - Author: Nobuyoshi Nakada - Date: 2019-06-17 23:25:47 +0900 - - Support Bison 3 in ripper - -commit c8e9e0b74b7fb2e225af8708426389db88f80683 - Author: Nobuyoshi Nakada - Date: 2019-06-17 22:30:52 +0900 - - Fix wrong "void value expression" error - - * parse.y (value_expr_check): `then` or `else` only `if` is not a - void value expression, as the counterpart is evaluated as `nil`. - [Bug #15932] - -commit 01b3a3804334be19d013526d3edde2b84399ae43 - Author: Nobuyoshi Nakada - Date: 2019-06-17 21:36:41 +0900 - - Fix wrong "void value expression" error - - * parse.y (value_expr_check): if either of `then` or `else` - statements is not a void value expression, the whole `if` is not - also a void value expression. [Bug #15932] - -commit 09a846085c2e675aa8397e9351c52d68215d7fa4 - Author: git - Date: 2019-06-17 19:56:35 +0900 - - * 2019-06-17 - -commit a064e46762ec0bfd40e6a04242d9e62fdd21e1f0 - Author: Nobuyoshi Nakada - Date: 2019-06-17 03:09:52 +0900 - - Support Bison 3 - -commit 53e9908d8afc7f03109b0aafd1698ab35f512b05 - Author: Nobuyoshi Nakada - Date: 2019-06-16 23:41:06 +0900 - - Fix memory leak - - * string.c (str_replace_shared_without_enc): free previous buffer - before replaced. - - * parse.y (gettable): make sure in advance that the `__FILE__` - object shares a fstring, to get rid of replacement with the - fstring later. - TODO: this hack may be needed in other places. - - [Bug #15916] - - Co-Authored-By: luke-gru (Luke Gruber) - -commit d4929f518562b4e346af57f724232595b674f2b0 - Author: git - Date: 2019-06-16 23:01:46 +0900 - - * expand tabs. - -commit 1ff26dc4c706cd6e8f227d159a2b23cba5f6de77 - Author: Yusuke Endoh - Date: 2019-06-16 23:00:05 +0900 - - Revert "Make constant assignments more conforming to JIS X 3017:2013 11.4.2.2.3" - - This reverts commit 44caca11cfa6bea01a1ef738846183f1a56d5658. - - The change caused a build failure. - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/2102153 - -commit 11f8c89171ff0b260891dec064cf69d9400a0704 - Author: git - Date: 2019-06-16 22:48:23 +0900 - - * expand tabs. - -commit 44caca11cfa6bea01a1ef738846183f1a56d5658 - Author: Yuki Yugui Sonoda - Date: 2019-06-16 22:28:34 +0900 - - Make constant assignments more conforming to JIS X 3017:2013 11.4.2.2.3 - - compile.c (NODE_CDECL): Evaluate the module before the value - test/ruby/test_const.rb (test_evaluation_order): added a test case - -commit 2fb1564c02899c73519164ddf3f2430dfbc8f3d6 - Author: aycabta - Date: 2019-06-16 14:46:22 +0900 - - Implement line_no correctly - -commit 17e6536fe0c6a7d213f500827346cacc210c536e - Author: nagachika - Date: 2019-06-16 11:59:52 +0900 - - tool/redmine-backporter.rb: Change redmine git revisions URL path. - -commit 72cc5cf0190618c67a0f697e91c61be07eadd5c5 - Author: git - Date: 2019-06-16 11:46:37 +0900 - - * 2019-06-16 - -commit ee7999bb8453201f895e6154b9169c4e5b5b9ef6 - Author: nagachika - Date: 2019-06-16 11:39:12 +0900 - - tool/redmine-backporter.rb: Add parens to fix condition for svn revision search. - -commit 5d7905490659b9b4f4604e9fd479563fcd103b34 - Author: Nobuyoshi Nakada - Date: 2019-06-15 12:04:16 +0900 - - Revert github/pull/2230, commit miss - -commit 6fa4c904483588d2aa08d1fd84e2b8efc95227df - Author: Nobuyoshi Nakada - Date: 2019-06-15 11:58:02 +0900 - - Prefer `enum yytokentype` to int - -commit 46527e1bf4a66a42ac4729e23f12bdfec8ae953e - Author: Josh Cheek - Date: 2019-06-15 11:13:27 +0900 - - Test for blank lines between leadinig dot method chains - -commit b8730f1251d94c0992db663f119df0a2bb31dca1 - Author: Josh Cheek - Date: 2019-02-06 16:10:23 +0900 - - Multiline method chain with leading dot works for blank lines - -commit 2240de98c0b174c2d0e61dd647776f5d5c404639 - Author: Josh Cheek - Date: 2019-02-06 15:58:50 +0900 - - Remove blank line I accidentally added - -commit 162bfa1c7cf325f6efce6f6e080d29db91fbcf78 - Author: Josh Cheek - Date: 2019-02-06 15:43:27 +0900 - - Test comments between multiline method chain - -commit cc180e937100c72b7ce849602c9d93d8e8a3d2aa - Author: Josh Cheek - Date: 2019-02-06 15:43:16 +0900 - - Rename LINEND to EMPTYLN - -commit 5af5dd463929837f7684d1e0865ac2d9394e19a5 - Author: Josh Cheek - Date: 2019-02-06 13:11:30 +0900 - - Omg, it works! - - I'll rename it and squash this commit later, - just wanted to make sure I couldn't lose it - (took a long time to come up with). - -commit e6aefe2a135102095bcaec379251dff2f4e843d6 - Author: git - Date: 2019-06-15 11:09:33 +0900 - - * 2019-06-15 - -commit 5dd8fdd3f328f741fae4abba00c478e8a51d2a7e - Author: Yusuke Endoh - Date: 2019-06-15 11:06:39 +0900 - - test/net/imap/test_imap.rb: wait for the server thread to start - - In some slow CI environments, the invocation of a thread seems very - slow. This causes a test failure to attempt to connect a server that - does not start yet. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20190615T002420Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-master/log/20190611T022407Z.fail.html.gz - -commit d365fd5a024254d7c105a62a015a7ea29ccf3e5d - Author: Nobuyoshi Nakada - Date: 2019-06-14 18:09:45 +0900 - - An operator is not allowed just after `|>` - - https://twitter.com/yukihiro_matz/status/1139454774640726019 - -commit d780c3662484d6072b3a6945b840049de72c2096 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-14 17:29:51 +0900 - - Pipeline operator is experimental [ci skip] - -commit aa32465ab36a56655d214313b828422563e109af - Author: Nobuyoshi Nakada - Date: 2019-06-14 15:31:03 +0900 - - irb.rb: [DOC] the default prompt includes :PROMPT_N [ci skip] - -commit 50bb8b6052a1fdec72ac46f9736719438fd5002c - Author: Nobuyoshi Nakada - Date: 2019-06-14 08:15:39 +0900 - - Use Exception#full_message for traceback - -commit 9402d019a51cf74cd6fceab534d4f1bde23a75e7 - Author: aycabta - Date: 2019-06-14 08:45:52 +0900 - - Remove debug print - -commit d0e5564140356ac6546a41d8a236287d952d563d - Author: aycabta - Date: 2019-06-14 08:45:35 +0900 - - Set allow_escape_code for prompt - -commit f80771f0a989efdde2276d4d6d213cb096843e92 - Author: aycabta - Date: 2019-06-14 08:26:06 +0900 - - Use Reline.prompt_proc in IRB - -commit 3757e492fb815656341dd430465e0f069e1bd562 - Author: git - Date: 2019-06-14 07:46:01 +0900 - - * 2019-06-14 - -commit 64310b2573a9e1e83cd405aed4a5c3351793e09d - Author: aycabta - Date: 2019-06-14 07:42:53 +0900 - - Add Reline.prompt_proc - -commit 56d595198b607d2abbb0f60ef0d9e1217d08d1af - Author: Yusuke Endoh - Date: 2019-06-13 23:04:41 +0900 - - test/webrick/test_ssl_server.rb: Use EnvUtil.timeout for timeout scale factor - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190613T091708Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190612T011708Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190611T211707Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190604T171708Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190529T091707Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190528T031708Z.fail.html.gz - -commit e75c278183306d28f0210673905437c2f6350b26 - Author: Yusuke Endoh - Date: 2019-06-13 22:44:01 +0900 - - test/lib/test/unit/assertions.rb (assert_cpu_usage_low): tweak the wait - - It still fails randomly. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/amazon2/ruby-master/log/20190613T093003Z.fail.html.gz - https://rubyci.org/logs/mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-master/log/20190613T051547Z.fail.html.gz - -commit aa7211836b769231a2a8ef6b6ec2fd0ec882ef29 - Author: Nobuyoshi Nakada - Date: 2019-06-13 22:19:47 +0900 - - Continue to the next line beginning with a pipeline - -commit 043f010c28e82ea38978bf8ed885416f133b5b75 - Author: Nobuyoshi Nakada - Date: 2019-06-13 22:03:10 +0900 - - parse.y: moved pipeline to expr - - To allow arguments without parentheses. - -commit f169043d81524b5b529f2c1e9c35437ba5bc3a7a - Author: Nobuyoshi Nakada - Date: 2019-04-23 13:14:27 +0900 - - Add pipeline operator [Feature #15799] - -commit e717d6faa8463c70407e6aaf116c6b6181f30be6 - Author: Nobuyoshi Nakada - Date: 2019-06-08 21:35:33 +0900 - - IO#set_encoding_by_bom - - * io.c (rb_io_set_encoding_by_bom): IO#set_encoding_by_bom to set - the encoding by BOM if exists. [Bug #15210] - -commit bdc8b3789ad388ff1d573369de6b085483b17098 - Author: git - Date: 2019-06-13 18:07:19 +0900 - - * expand tabs. - -commit 02b1a85385e7fd18b8bcecfdbbf1acbac703c039 - Author: Luke Gruber - Date: 2019-06-11 05:46:57 +0900 - - remove 2 redundant calls to rb_str_dup - - Because `rb_class_path` calls `rb_str_dup` already. - - Closes: https://github.com/ruby/ruby/pull/2232 - -commit 69509df2f4ed8e052d683fa3901c9f97d00ed7fc - Author: Kazuhiro NISHIYAMA - Date: 2019-06-13 16:42:31 +0900 - - squeeze space [ci skip] - -commit 7f79a86d8b4d250ea0e82eb06cd3336edb840a01 - Author: Martin Dürst - Date: 2019-06-13 15:30:03 +0900 - - add comments to mention sort.reverse! - - For array.c (Array#sort) and enum.c (Enumerable#sort_by), - add comments mentioning that sort.reverse! / sort_by { ... }.reverse! - can/should be used to reverse the result. [ci skip] - -commit 2a26c1ea24ec107cfb43d8561ad28984846b7660 - Author: Takashi Kokubun - Date: 2019-06-13 00:40:27 +0900 - - Clarify the Ruby version support status in IRB more - -commit 8d84e119da52573f9dfe3b2fe7a6d1c27b7fd71f - Author: git - Date: 2019-06-13 00:32:59 +0900 - - * 2019-06-13 - -commit 180802906190501e4eb9b9423adfb6116ceb334b - Author: Takashi Kokubun - Date: 2019-06-13 00:29:45 +0900 - - make sync-default-gems GEM=irb - - Upgrade IRB to https://github.com/ruby/irb/commit/41ea43a4a732e094acfa1b0fc1473fdcda9e6227 - - Mostly backport changes. - -commit 88411d350e9e3eb6425375238a20af9b6aae28ae - Author: Nobuyoshi Nakada - Date: 2019-06-12 15:30:07 +0900 - - Another incomplete string case - -commit 9593e76ac2cfd9366b8b904df3fc3e1047af3aee - Author: Nobuyoshi Nakada - Date: 2019-06-12 15:23:47 +0900 - - Ripper::Lexer: fallback parse error token to the previous one - -commit 8354cfd03b1e9961266e1fe56fca481450679b98 - Author: aycabta - Date: 2019-06-12 11:00:25 +0900 - - Treat "begin rescue end" correctly - -commit c1d78a7f0ece2004822193a0c1f1fd3dc38c2fdf - Author: Neeraj Bhunwal - Date: 2019-04-16 13:03:08 +0900 - - do_mutex_lock: release mutex before checking for interrupts (fixes issue 15360) - -commit 5e018214e7435030727a97ac49db038d96438e74 - Author: Jeremy Evans - Date: 2019-06-11 07:47:56 +0900 - - Fix SystemStackError when calling a method in an unused refinement - - Fixes [Bug #15720] - -commit 4f9e7c95e4c8216c17f46747092f28df9c54fab7 - Author: git - Date: 2019-06-12 01:16:49 +0900 - - * 2019-06-12 - -commit 23e3c1704b344819fcea907a67aafd1e6be8a9df - Author: git - Date: 2019-06-12 01:16:45 +0900 - - * expand tabs. - -commit 6db2d6d8520f88e25d97af77495eb6c879f90b21 - Author: Aaron Patterson - Date: 2019-06-01 05:25:24 +0900 - - Add compaction support for more types. - - This commit adds compaction support for: - - * Fibers - * Continuations - * Autoload Constants - -commit c4cbaef216ffcc9bda70cc328a805ad679ccaa8c - Author: Nobuyoshi Nakada - Date: 2019-06-11 11:13:26 +0900 - - assert_cpu_usage_low with timeout scale - - * test/lib/test/unit/assertions.rb (assert_cpu_usage_low): apply - the timeout scale to measuring period. this assertion is very - runtime environment dependent. - -commit 42f0a8fd6f7e1f4afcb17aeb34e9f8ddf8d66b9b - Author: Nobuyoshi Nakada - Date: 2019-06-11 11:09:02 +0900 - - MIN_HZ and MIN_MEASURABLE constants - - * test/lib/test/unit/assertions.rb (Test::Unit::Assertions): - promoted MIN_HZ and MIN_MEASURABLE as constants, which should be - constant through the process. - -commit eb016d835373cdce6f08694e527d7a569c208cb5 - Author: Nobuyoshi Nakada - Date: 2019-06-11 11:03:55 +0900 - - Generalize timeout_scale - - * test/lib/test/unit.rb (Test::Unit::TimeoutOption): renamed - SubprocessOption. - - * test/lib/test/unit.rb (Test::Unit::TimeoutOption#setup_options): - prefer `--timeout-scale` option. - - * test/lib/test/unit.rb (Test::Unit::TimeoutOption#non_options): - prefer `ENV["RUBY_TEST_TIMEOUT_SCALE"]`. - -commit 39ae88ad0dd0f8d7cf732e8567af13e7f2ce9748 - Author: Nobuyoshi Nakada - Date: 2019-06-11 22:31:57 +0900 - - Refined syntax error messages - -commit 140b8117bd3c32cb9d0b144937b90f0178a00b0e - Author: Nobuyoshi Nakada - Date: 2019-06-11 02:09:00 +0900 - - &. is not allowed inside LHS of massign - - https://hackerone.com/reports/605262 - -commit 42ac8890efbd38dc021bf5edab325a69be7fc4cf - Author: Kazuhiro NISHIYAMA - Date: 2019-06-11 12:32:13 +0900 - - Fail test if load ~/.irbrc - -commit e4364dbf6ecd9f87588f6f9e93d213046b75478e - Author: Hiroshi SHIBATA - Date: 2019-06-11 12:16:26 +0900 - - Fixed the code-style with the upstream rule. - -commit 4adc6f07ef8e1c620bee06f3614ce58b51839b34 - Author: Yusuke Endoh - Date: 2019-06-11 07:15:31 +0900 - - test/lib/test/unit/assertions.rb (assert_cpu_usage_low): Relax the limit - - CPU usage 1% causes occesional test failure. Try to use 5%. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/gentoo/ruby-master/log/20190604T153002Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/gentoo/ruby-master/log/20190610T153002Z.fail.html.gz - -commit fe9701ee0062f15409107a92582a9e6e5630bfbe - Author: git - Date: 2019-06-11 06:56:46 +0900 - - * expand tabs. - -commit de4b2930f71a88358c8f1968e410f420c54853bd - Author: Yusuke Endoh - Date: 2019-06-11 06:53:33 +0900 - - ext/socket/ipsocket.c: Use SO_REUSEADDR for local_host/port - - Sometimes ruby/spec fails when trying to specify local_host and - local_port for TCPSocket.open. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20190610T192504Z.fail.html.gz - -commit 6096baea5db6505206f0e636c4e5272b4eb72da4 - Author: Yusuke Endoh - Date: 2019-06-11 06:45:49 +0900 - - test/net/http/test_http.rb: Extend the timeout - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190610T071910Z.log.html.gz - -commit d7e7e998625a3ab10c76ba94816db9d6a753e058 - Author: git - Date: 2019-06-11 00:25:57 +0900 - - * 2019-06-11 - -commit be6b462489e42b6a8ee60ba96fc18fcc9794f819 - Author: Kazuki Tsujimoto - Date: 2019-06-11 00:20:10 +0900 - - Use checktype for performance - -commit f0bfa71ab3ce5f6045a39e503f6decbc9b3a7d3d - Author: Takashi Kokubun - Date: 2019-06-10 23:23:15 +0900 - - Use UTC for file2lastrev timezone - - 02155da7bad37bd1c8adadd486d2d16eac7af43b got a claim about sacrificing - ability to compare arbitrary `RUBY_DESCRIPTION`s without converting - timezones. - - Because most of the people would be familiar with timezone conversion - with UTC but it'd be harder when it comes to JST, this commit just - changes the timezone in f42588f754d5885ec30631e5008c383f3ef905d8 to UTC. - - Another bonus in using UTC is that we can use a shorter variant of - ISO 8601 format like "2019-06-10T14:26:24Z" (the last Z part). - -commit 02155da7bad37bd1c8adadd486d2d16eac7af43b - Author: Takashi Kokubun - Date: 2019-06-10 22:20:00 +0900 - - Make file2lastrev timezone consistent with git log - - Using the same timezone for all commits is convenient when just looking - dates in RUBY_DESCRIPTION, but usually we also check `git log` when - we're interested in the order of commits. - `git log` shows times in committer's timezone and forcing RUBY_RELEASE_DATE - to JST makes it harder to find a corresponding commit from `git log`. - - Because this label is only used in development, I believe there's no - strict requirement to use traditional timezone for release here. - - Also when building Ruby after committing from a non-JST timezone, I'd be - surprised to see a strange time (in a different timezone) for my very new - commit in `ruby -v`. - -commit caa90202c9d2acbb9bce32ceebe6166c2f1de5d0 - Author: Takashi Kokubun - Date: 2019-06-10 22:04:51 +0900 - - Make sure to suppress .irbrc on benchmark - - By the way, this is already improved by nobu: - - ``` - $ benchmark-driver benchmark/irb_exec.yml --rbenv '2.6.3;2.7.0-preview1;before;after' -v - 2.6.3: ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux] - 2.7.0-preview1: ruby 2.7.0preview1 (2019-05-31 trunk c55db6aa271df4a689dc8eb0039c929bf6ed43ff) [x86_64-linux] - before: ruby 2.7.0dev (2019-06-10T21:13:14+09:00 master 973fd18f11) [x86_64-linux] - after: ruby 2.7.0dev (2019-06-10T21:18:56+09:00 master 976c689ad4) [x86_64-linux] - Calculating ------------------------------------- - 2.6.3 2.7.0-preview1 before after - irb_exec 11.868 5.872 6.297 10.278 i/s - 30.000 times in 2.527776s 5.108997s 4.764167s 2.918821s - - Comparison: - irb_exec - 2.6.3: 11.9 i/s - after: 10.3 i/s - 1.15x slower - before: 6.3 i/s - 1.88x slower - 2.7.0-preview1: 5.9 i/s - 2.02x slower - - ``` - -commit 880204cf55813c975f3bbd0be93b292a099d5890 - Author: Nobuyoshi Nakada - Date: 2019-06-10 21:45:46 +0900 - - irb/cmd/help.rb: return nil after the redefinition - -commit 976c689ad478b8010b053aa270a28bd236b8380e - Author: Nobuyoshi Nakada - Date: 2019-06-10 21:07:24 +0900 - - irb: defer requiring rdoc to improve the start up time - -commit 973fd18f11f5026024fc43e2848db030110bdaee - Author: Takashi Kokubun - Date: 2019-06-10 21:13:12 +0900 - - Add a benchmark of irb boot time - - ``` - $ benchmark-driver benchmark/irb_exec.yml --rbenv '2.6.3;2.7.0-preview1' - Calculating ------------------------------------- - 2.6.3 2.7.0-preview1 - irb_exec 11.844 5.171 i/s - 30.000 times in 2.532887s 5.801960s - - Comparison: - irb_exec - 2.6.3: 11.8 i/s - 2.7.0-preview1: 5.2 i/s - 2.29x slower - ``` - -commit b9996b7b323d7e238512fa8dbd3d3b8576ba06e1 - Author: git - Date: 2019-06-10 19:48:08 +0900 - - * 2019-06-10 - -commit 626ae5a9b6531412f598b2f37a15821628857707 - Author: Benoit Daloze - Date: 2019-06-10 19:47:08 +0900 - - Resolv specs should pass on Windows now - -commit 60af6fef3c664ac7dab53fcde28c30f30ce862aa - Author: Benoit Daloze - Date: 2019-06-10 19:45:00 +0900 - - Fix Resolv specs to not depend on a system /etc/hosts file - - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/archlinux/ruby-master/log/20190609T153804Z.fail.html.gz - * Thanks @naruse for the tip. - -commit 614154bbb6adeb06cce755be7b8540e1594703c5 - Author: Hiroshi SHIBATA - Date: 2019-06-09 10:49:51 +0900 - - Added missing dependency for rake examples. - -commit 2c59c58a47db31e28757e1936dd355a98352b489 - Author: Hiroshi SHIBATA - Date: 2019-06-09 11:00:21 +0900 - - Fixed wrong BUNDLE_BIN_PATH for ruby core. - -commit 44f7f093ab8d8663cbbe31d8a975ae6e8d20724f - Author: Hiroshi SHIBATA - Date: 2019-06-09 11:00:07 +0900 - - Added the condition for ruby_core repository. - -commit 57ccea6232a76aec5711e5e583cffe0aa5221928 - Author: Hiroshi SHIBATA - Date: 2019-06-01 19:29:56 +0900 - - Revert to change for filelist of bundler gemspec. - -commit 8f37629519ad330032a38ac0e871b2912ed38a1b - Author: Hiroshi SHIBATA - Date: 2019-06-01 18:49:40 +0900 - - Merge bundler master from upstream. - - Pick from 8dd59e3ba97eb80a599f8149f31bf40773b69dc0 - -commit 66508992483ae5d77b56a98427c50c772341c0ac - Author: Jeremy Evans - Date: 2019-06-09 12:27:49 +0900 - - Make Resolv::DNS#each_name accept Resolv::IPv{4,6} arguments - - These arguments were previously documented as supported, but not - actually supported. - - Patch from Toru Iwase - - Fixes [Bug #15900] - -commit a432c014c99eb44b3f446aa43c7e83c945d3ec8e - Author: git - Date: 2019-06-09 12:30:40 +0900 - - * 2019-06-09 - -commit 562c0bfedaa96a1488cbfc0d282412743ea8cde0 - Author: Nobuyoshi Nakada - Date: 2019-06-09 11:34:58 +0900 - - Split test_strip_bom for each encoding - -commit a8ef498d6bfbd5c665b75a0782526d18b361dd5b - Author: Nobuyoshi Nakada - Date: 2019-06-09 11:10:34 +0900 - - Add tests of the encoding with BOM - -commit f42588f754d5885ec30631e5008c383f3ef905d8 - Author: Nobuyoshi Nakada - Date: 2019-06-08 20:08:18 +0900 - - Make RUBY_RELEASE_DATE full on development - - I cannot tell the order just by commit hashes. - -commit 1ca03dc4f77de4030534596ad23af64be925dc44 - Author: Nobuyoshi Nakada - Date: 2019-06-08 19:46:32 +0900 - - Suppress warnings by gcc 9.1 - -commit 27a59ca2c846e14ec6dbcb86fd2d6f65399ff28d - Author: Nobuyoshi Nakada - Date: 2019-06-08 19:40:55 +0900 - - file.c: fix compile error with MacPorts gcc - - With the SDK of Xcode 10.2.1, `API_AVAILABLE` and so on macros are - not defined in when using a compiler other - than clang (which has `__has_feature` and `__has_attribute`), but - `__API_AVAILABLE` macro and so on are defined, which are also - defined in . - - I suspect this is a bug of the SDK. - -commit 5a840517ae738357d3d5afdcef61461e3969edfa - Author: Nobuyoshi Nakada - Date: 2019-06-08 18:44:18 +0900 - - Fix broken `gem unpack` - - * lib/rubygems/commands/unpack_command.rb: 'rubygems/package' is - required here, to fix broken `gem unpack` command. - -commit 21de4a574f363e77c64d36ce2671fa55e7955b49 - Author: Nobuyoshi Nakada - Date: 2019-06-08 18:44:04 +0900 - - io.c: fold very very long lines - -commit 3776c48cf41950d2cc994676bb2735ee1a0a474e - Author: Hiroshi SHIBATA - Date: 2019-06-08 13:44:40 +0900 - - Revert "require rubygems/package where used" - - This reverts commit b76630f73e8362d3072bfa7178471ddc5d21c235. - - It fails with `make test-bundler BUNDLER_SPECS=runtime/setup_spec.rb:1204` - -commit 1696f80f400518ea1b5304c23d8192140a7e55c6 - Author: git - Date: 2019-06-08 00:15:42 +0900 - - * 2019-06-08 - -commit 19977cc761cf25748676e45a5a7a706b0d7fd70d - Author: aycabta - Date: 2019-06-07 23:54:49 +0900 - - Remove unnecessary variables - -commit ffaefcadd81cb8e4d38114e76b1831ba95d6a6f3 - Author: Nobuyoshi Nakada - Date: 2019-06-07 23:08:43 +0900 - - Report a sudden death of workers - -commit 75751dca2b9f573db923cecd9767e9174fb69a98 - Author: Yusuke Endoh - Date: 2019-06-07 23:33:23 +0900 - - test/openssl/utils.rb: Extend the timeout for armv7l - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190607T051708Z.fail.html.gz - -commit b76630f73e8362d3072bfa7178471ddc5d21c235 - Author: Nobuyoshi Nakada - Date: 2019-06-07 22:34:28 +0900 - - require rubygems/package where used - - * lib/rubygems/commands/unpack_command.rb: 'rubygems/package' is - required. fix the failure of `gem unpack` command. - - * lib/rubygems/source/local.rb: ditto. - - * lib/rubygems/source/specific_file.rb: ditto. - -commit 6566919176834efb47ea717967669ca83eb78347 - Author: Nobuyoshi Nakada - Date: 2019-06-07 18:45:49 +0900 - - ripper_state_lex.rb: chomp CR - - * lib/rdoc/parser/ripper_state_lex.rb (RDoc::Parser::RipperStateLex): - chomp newline, including CR, from here document terminator. - - Closes: ruby/rdoc#694 - Closes: ruby/rdoc#697 - Closes: ruby/rdoc#705 - -commit a6a26e42b15c46f117f4fce07a2050e9d727355d - Author: Yusuke Endoh - Date: 2019-06-07 14:45:06 +0900 - - compile.c: Partially revert r63870 which caused wrong optimization - - [Bug #15906] - -commit b8af33e63bd286308e5e1b20c182ec50e0f194de - Author: Jeremy Evans - Date: 2019-05-25 13:32:37 +0900 - - Skip one assertion for OpenSSL::PKey::EC::Point#mul on LibreSSL - - LibreSSL 2.8.0+ does not support multiple elements in the first - argument. - -commit 119ca4343cceed031f017ce2e0d2a1e709344a0f - Author: Jeremy Evans - Date: 2019-06-07 13:10:21 +0900 - - Make specs pass on OpenBSD - - Skip Process clockres specs that don't work on either FreeBSD or - Solaris/AIX in addition to OpenBSD. - - Run most current String#crypt specs on non-OpenBSD, and add a new - set of crypt specs for OpenBSD, which support bcrypt but not DES - in crypt(3). - - Use @server.connect_address instead of @server.getsockname in some - socket tests, as OpenBSD does not treat connection to all zero - IPv4 or IPv6 addresses as connection to localhost. - - When trying to connect using UDP on an unsupported address family, - allow Errno::EPROTONOSUPPORT in addition to Errno::EAFNOSUPPORT, - as OpenBSD raises the former. - -commit c55de95ff1c4ea6313c2863037703a0e5f0d0f4f - Author: Nobuyoshi Nakada - Date: 2019-06-07 10:05:42 +0900 - - Dummy Makefile.in for CIs - -commit 7e403dc6c84356e83c02538e76cc70ac789921ac - Author: Yusuke Endoh - Date: 2019-06-07 09:26:40 +0900 - - test/openssl/utils.rb: Extend the timeout - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-master/log/20190606T171708Z.fail.html.gz - -commit c7477c3e1fb661ed1cbcda9c7fbc710f77390845 - Author: Nobuyoshi Nakada - Date: 2019-06-07 09:09:29 +0900 - - Moved Makefile.in under template - -commit aef3bb3513d5b275ed9fa2765e83fab97122fd40 - Author: Nobuyoshi Nakada - Date: 2019-06-07 09:06:55 +0900 - - Remove the dependency of Makefile on Makefile.in transitionally - -commit 200c840b952a65fca10d5f3a47b69288f1d3dc65 - Author: Nobuyoshi Nakada - Date: 2019-06-07 09:02:48 +0900 - - Revert "Moved Makefile.in under template" - - This reverts commits: - * 6f9d5fafe040cb02a1278fbfcdcb8063d564824c - * bb3c89b6437049e26669b2156310670d5e06e386 - - And remove the dependency of Makefile on Makefile.in - transitionally. - -commit bb3c89b6437049e26669b2156310670d5e06e386 - Author: Nobuyoshi Nakada - Date: 2019-06-07 08:58:53 +0900 - - Makefile.in moved under template - -commit 6f9d5fafe040cb02a1278fbfcdcb8063d564824c - Author: Nobuyoshi Nakada - Date: 2019-06-06 12:49:08 +0900 - - Moved Makefile.in under template - -commit aee77901310389462c0971e7c45f7c19410f3371 - Author: git - Date: 2019-06-07 02:04:51 +0900 - - * 2019-06-07 - -commit 2bc09665ab8e72d4320a55a274eae903262f29cd - Author: Nobuyoshi Nakada - Date: 2019-06-07 02:00:48 +0900 - - win32/registry.rb: fix potential infinite loop - - * ext/win32/lib/win32/registry.rb (Win32::Registry#each_value): - advance the index even if an error occurred in #read. - -commit 09a2189c1b5dd5a28a052f9464a516213f89d6e7 - Author: Nobuyoshi Nakada - Date: 2019-06-07 01:56:22 +0900 - - Adjust indent - -commit 9f941f61efb5bdf6572f2d41ad29bcab267ecf5f - Author: Yusuke Endoh - Date: 2019-06-06 21:19:09 +0900 - - test/webrick/test_filehandler.rb: extend the timeout for Solaris CI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190602T031908Z.fail.html.gz - -commit 60924636e5184c967df129e523ba9374ccc57144 - Author: Yusuke Endoh - Date: 2019-06-06 21:18:26 +0900 - - test/net/http/test_http.rb: extend the timeout for Solaris CI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190605T231909Z.fail.html.gz - -commit fcc36d767b60329692b27d685ba867848da6aa04 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-06 16:49:40 +0900 - - Revert "Stop `circular require` warning" - - This reverts commit c2a9c350249588677cf68b506539093504927eac. - - It cannot stop `circular require` warning. - -commit c2a9c350249588677cf68b506539093504927eac - Author: Kazuhiro NISHIYAMA - Date: 2019-06-06 15:38:00 +0900 - - Stop `circular require` warning - -commit 861b50d81d9ed5f57b78c87b2e2f24f718db31dd - Author: Yusuke Endoh - Date: 2019-06-06 15:25:18 +0900 - - lib/rubygems.rb: Stop "Leaked file descriptor" warning - - Bundler.setup changes Gem::DefaultUserInteraction.ui and does not close - it. This change makes sure that it is closed. - -commit 1e54903684aa3c9ea3fe54520157846a1b1f07be - Author: Yusuke Endoh - Date: 2019-06-05 21:07:27 +0900 - - test/openssl: Support OpenSSL 1.1.1 - - OpenSSL 1.1.1 rejects some shorter keys, which caused some failures of - `make test-all TESTS=openssl`. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian/ruby-master/log/20190606T003005Z.fail.html.gz - - This change merges 6bbc31ddd1 and 63fb3a36d1 in - https://github.com/ruby/openssl. - Reference: https://github.com/ruby/openssl/pull/217 - -commit d046fe926273d0137f2d5cdf2dedfcfeeb98189b - Author: Nobuyoshi Nakada - Date: 2019-06-06 12:03:19 +0900 - - configure.ac: utilize wide columns for summary - -commit 884576bf12df04abbbc32bc74f142320bc6d7556 - Author: Nobuyoshi Nakada - Date: 2019-06-06 08:21:40 +0900 - - Update RDoc of RUBY_REVISION - -commit 02880d1f4a9ebd1c0a807376fcb25ccd908334b4 - Author: aycabta - Date: 2019-06-06 04:57:52 +0900 - - Skip transpose-words if less than 2 word - -commit fd173372285f9575e424f854d8072b5f71fce1e2 - Author: git - Date: 2019-06-06 04:25:58 +0900 - - * 2019-06-06 - -commit eadc06ba1664102da07ec08aeca6c3e1eccc4e96 - Author: aycabta - Date: 2019-06-06 04:25:16 +0900 - - Add test_ed_transpose_words_for_mbchar - -commit 6dc0541ed3c3736fb4c0b270f2c8df1c0dbfba95 - Author: Takashi Kokubun - Date: 2019-06-05 22:29:53 +0900 - - NEWS: Note about CGI.escapeHTML change [ci skip] - - See https://github.com/ruby/ruby/pull/2226 for benchmark results. - -commit 0a29dc87e62c701db56816cb430daf07a4f02bea - Author: Takashi Kokubun - Date: 2019-06-05 19:28:51 +0900 - - Optimize CGI.escapeHTML by reducing buffer extension - - and switch-case branches. - - Buffer allocation optimization using `ALLOCA_N` would be the main - benefit of patch. It eliminates the O(N) buffer extensions. - - It also reduces the number of branches using escape table like - https://mattn.kaoriya.net/software/lang/c/20160817011915.htm. - - Closes: https://github.com/ruby/ruby/pull/2226 - - Co-authored-by: Nobuyoshi Nakada - Co-authored-by: Yasuhiro MATSUMOTO - -commit f3c877e8deaea91ff27c0fca837c9388d030a896 - Author: Takashi Kokubun - Date: 2019-06-05 20:07:19 +0900 - - Ignore ~/.gitconfig on tool/vcs.rb git commands - - Because some `log.*` git configs may change the result of `git log`, - `RUBY_LAST_COMMIT_TITLE` can be wrongly formatted and break version.c - compilation. So the `git log` executions should not respect user's gitconfig. - -commit 84c294eb0b5b5206f01f062d4c2c860a57c7873c - Author: Nobuyoshi Nakada - Date: 2019-06-05 15:49:55 +0900 - - spec/bundler/bundler/dsl_spec.rb: fix exception to raise - - When describing "Runtime errors", raise a `RuntimeError` as-is. - -commit f258137083051a7fc2412c62e3fb239f93d1fdf8 - Author: Martin Dürst - Date: 2019-06-05 14:03:50 +0900 - - Fix grammar of macro name: ECCESSED -> EXCESSIVE - - Fix the name of the macro variable introduced in 0872ea5330 - from NODE_SPECIAL_EXCESSED_COMMA to NODE_SPECIAL_EXCESSIVE_COMMA. - -commit 1624d77f3ee0a536a6ab37da014d85d16fcd1de2 - Author: Nobuyoshi Nakada - Date: 2019-06-05 13:02:38 +0900 - - error.c: avoid infinite recursion at inspecting the frozen object - -commit b2fe7484e7e7c7741f33bfb02c2fc91f03763ab4 - Author: Nobuyoshi Nakada - Date: 2019-06-05 12:57:14 +0900 - - Test for f1f04caf60e4fc9dc3b12109e0be831f2d692810 - -commit 542d69c894f86cd9a395fdd5296981c998e4a6bf - Author: Nobuyoshi Nakada - Date: 2019-06-05 11:53:24 +0900 - - Revert "vcs.rb support non-inplace build" - - This reverts commit 22cd4027349f803efc7ede284376b7a7013f8dfe. - - It did not make sense due to a typo `@srcidr`. - -commit aa8a8d8f6d259da096afc1deb65cc35e0fe518d0 - Author: Nobuyoshi Nakada - Date: 2019-06-05 12:03:56 +0900 - - Split an assertion for f1f04caf60e4fc9dc3b12109e0be831f2d692810 - -commit c75a3356b39c5a6ede275f38d5d869dbcd5dba93 - Author: aycabta - Date: 2019-06-05 11:29:41 +0900 - - Move I/O access from Reline::KeyStroke to Reline - -commit 7c776038ec3e620625b7fe3e78638afe936f9a5d - Author: git - Date: 2019-06-05 11:29:04 +0900 - - * expand tabs. - -commit f1f04caf60e4fc9dc3b12109e0be831f2d692810 - Author: Jeremy Evans - Date: 2019-05-28 09:52:35 +0900 - - Include inspect value of object in FrozenError messages - - FrozenError#receiver was added recently for getting the related - object programmatically. However, there are cases where FrozenError - is raised and not handled, and in those cases the resulting error - messages lack detail, which makes debugging the error more difficult, - especially in cases where the error is not easily reproducible. - This includes the inspect value of the frozen object in FrozenError - messages, which should make debugging simpler. - -commit 96d65274246a4be88581693f452e6b3bae9fdc5c - Author: Jeremy Evans - Date: 2019-06-05 11:19:37 +0900 - - Add some documentation to Timeout#timeout about possible issues - - Documentation requested in [Bug #15886]. - -commit a105831819af8d143dd587a93844ca982cfadd67 - Author: Nobuyoshi Nakada - Date: 2019-06-05 11:03:57 +0900 - - tool/runruby.rb: support RUNRUBY_USE_LLDB as well as RUNRUBY_USE_GDB - -commit 26d02cc7cdb9fd2272a695083449824a3852717a - Author: Nobuyoshi Nakada - Date: 2019-06-05 11:03:19 +0900 - - tool/runruby.rb: load the default lldb scripts - -commit 5859ea1b1b3f1ba23a15174c6bef4a2ecabafb2f - Author: Nobuyoshi Nakada - Date: 2019-06-05 11:01:23 +0900 - - tool/runruby.rb: load .gdbinit explicitly - -commit 6b66a76f43038eb4b789f0f94729ddcc233d9c56 - Author: git - Date: 2019-06-05 11:01:59 +0900 - - * expand tabs. - -commit 71b14affc6b699f38aabe73125380cab57799e34 - Author: Takashi Kokubun - Date: 2019-06-05 11:00:54 +0900 - - Revert "Optimize CGI.escapeHTML by reducing buffer extension" - - This reverts commit 8d81e59aa7a62652caf85f9c8db371703668c149. - - `ALLOCA_N` does not check stack overflow unlike ALLOCV. I'll fix it and - re-commit it again. - -commit 804a7907a8974cf2f820a7cdce9133843b0fa7db - Author: git - Date: 2019-06-05 10:13:25 +0900 - - * 2019-06-05 - -commit 8d81e59aa7a62652caf85f9c8db371703668c149 - Author: Takashi Kokubun - Date: 2019-06-04 19:58:39 +0900 - - Optimize CGI.escapeHTML by reducing buffer extension - - and switch-case branches. - - Buffer allocation optimization using `ALLOCA_N` would be the main - benefit of patch. It eliminates the O(N) buffer extensions. - - It also reduces the number of branches using escape table like - https://mattn.kaoriya.net/software/lang/c/20160817011915.htm. - - Closes: https://github.com/ruby/ruby/pull/2226 - - Co-authored-by: Nobuyoshi Nakada - Co-authored-by: Yasuhiro MATSUMOTO - -commit b31e1b4a7c5b97d861c2b34ed4ccd982d5c6cb82 - Author: git - Date: 2019-06-04 23:17:38 +0900 - - * expand tabs. - -commit 0b0c6cb7e4fa17247cb214c4eaf924617a55e9a7 - Author: Yusuke Endoh - Date: 2019-06-04 23:15:14 +0900 - - compile.c: Remove the magical `(const NODE*) -1` - - It is used to represent "no default expression" for keyword argument: - `def foo(key:)`. This change uses NODE_SPECIAL_REQUIRED_KEYWORD. - -commit 0872ea53303499caf3584e40f2a5438e86eb4fed - Author: Yusuke Endoh - Date: 2019-06-04 23:11:38 +0900 - - node.h: Avoid a magic number to represent excessed comma - - `(ID)1` was assigned to NODE_ARGS#rest_arg for `{|x,| }`. - This change removes the magic number by introducing an explicit macro - variable for it: NODE_SPECIAL_EXCESSED_COMMA. - -commit 39eae6bf89773ef830b632c02737545ab9eedd35 - Author: Nobuyoshi Nakada - Date: 2019-06-04 21:27:46 +0900 - - tool/vcs.rb: return the commit date as the modified time - -commit 2e2cd8297bf34dd5f613d5001da54949ba228ca6 - Author: git - Date: 2019-06-04 19:55:04 +0900 - - * expand tabs. - -commit 2c60f3714381803218313a6056d3e1dd39782ca1 - Author: Nobuyoshi Nakada - Date: 2016-05-12 16:52:34 +0900 - - random_mt_type - - * random.c: renamed random_data_type as random_mt_type, and append - "MT" to `wrap_struct_name`, respecting the implementation. - -commit c8b001858ed6911db4285d239193bc2384ff6ce0 - Author: Nobuyoshi Nakada - Date: 2019-06-04 19:06:19 +0900 - - Revert "marshal.c: new functions for extensions" - - This reverts a commit miss, 24a96a0228ccf355826644a9daad69e11b67b53b. - -commit 9e472e18d22d013f5da7d5a3769599c5fb763f43 - Author: Nobuyoshi Nakada - Date: 2019-06-04 19:00:48 +0900 - - suppress marshal warnings - -commit 24a96a0228ccf355826644a9daad69e11b67b53b - Author: Nobuyoshi Nakada - Date: 2012-06-22 14:38:03 +0900 - - marshal.c: new functions for extensions - - * marshal.c (rb_marshal_dump_limited): new function for extension - libraries to dump object with limited nest level. - - * marshal.c (rb_marshal_load_with_proc): new function for extension - libraries to load object with hook proc. - -commit 51d27d25d7f6da520821feae94934c4de51b7bb3 - Author: Nobuyoshi Nakada - Date: 2019-06-04 18:51:49 +0900 - - test/lib/test/unit.rb: use colorize.rb - -commit e7aa87c35340c1690e903e8058d3c4e78f0f5335 - Author: Nobuyoshi Nakada - Date: 2019-06-04 18:33:34 +0900 - - Renamed duplicate test - -commit fade26afa72282ee9e2dbbc2e74cd9ea45674dc6 - Author: Nobuyoshi Nakada - Date: 2019-06-04 18:10:09 +0900 - - colorize.rb: get rid of syntax errors on older versions - -commit a57d6d2325ddc71363414acf2f923db0bf0ddc9c - Author: Nobuyoshi Nakada - Date: 2019-06-04 18:08:21 +0900 - - colorize.rb: make `colors_file` optional - - [ci skip] - -commit b0c35ff2db3a4ebb12a405705592e938f50bff64 - Author: Nobuyoshi Nakada - Date: 2019-06-04 17:23:57 +0900 - - colorize.rb: fix reading from test/colors - - [ci skip] - -commit 16cb1fb007a9d107b8c447e862c92c682a56a7c8 - Author: Nobuyoshi Nakada - Date: 2019-06-04 17:09:16 +0900 - - extlibs.rb: colorize - - [ci skip] - -commit 58fd27d3d89451fbbe840348cd66f2205e34e72b - Author: Nobuyoshi Nakada - Date: 2019-06-04 17:06:12 +0900 - - colorize.rb: read `test/colors` file after `$TEST_COLORS` - - [ci skip] - -commit ce4b5d90b2127af185f91037de1185ad7520ace3 - Author: git - Date: 2019-06-04 12:39:25 +0900 - - * remove trailing spaces. [ci skip] - -commit 8406547b7c3f97c073aa70d22ec7e90a6bf5af5e - Author: Kazuhiro NISHIYAMA - Date: 2019-06-04 12:39:03 +0900 - - Azure Pipelines run on master instead of trunk [ci skip] - -commit c1e2d50531f3ba50cce3016bcfd440546e1ef007 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-04 12:37:25 +0900 - - Azure Pipelines run on master instead of trunk [ci skip] - -commit b0cb4bdb4ee2aabc2f068a194a10882515d995d3 - Author: git - Date: 2019-06-04 11:40:21 +0900 - - * expand tabs. - -commit 7866ed850c1ae95a6b115e09f3788d5b623f0708 - Author: Yusuke Endoh - Date: 2019-06-04 11:39:27 +0900 - - node.c: Show the ID of internal variable - -commit 14b5ccf91b8df1e61ae20f606b85cbb86d087f16 - Author: git - Date: 2019-06-04 09:36:32 +0900 - - * expand tabs. - -commit aa8d393d8a69d1a5780d338692f75e2dd821c5b0 - Author: Nobuyoshi Nakada - Date: 2019-06-04 09:24:17 +0900 - - EOF by 2 ^D on a TTY - - Terminate the input from a TTY by 2 ^D at the middle of line, like - as many programs, `cat`, `perl` and so on, do. By the first ^D, - the line will be sent without a newline, and then EOF will be send - by the next ^D. - -commit 9a07915ae21d5a8e39d7dab6b609be033f2e2d7d - Author: aycabta - Date: 2019-06-04 08:34:10 +0900 - - Add aliases for commands for changing text macro - -commit d950cade5347a61cff6d9b63c7d0c5768b96b539 - Author: Takashi Kokubun - Date: 2019-06-04 08:33:03 +0900 - - azure-pipelines.yml: Upgrade Ruby for UseRubyVersion - - to fix - https://dev.azure.com/rubylang/ruby/_build/results?buildId=1162&view=logs - -commit 4b7213a85a6700657b825f8f127ce83a3070bf1d - Author: aycabta - Date: 2019-06-04 06:39:02 +0900 - - Implement transpose-words - -commit c9b74f9fd95113df903fc34cc1d6ec3fb3160c85 - Author: Aaron Patterson - Date: 2019-06-04 07:15:48 +0900 - - Pin keys in "compare by identity" hashes - - Hashes that compare by identity care about the location of the object in - memory. Since they care about the memory location, we can't let them - move. - -commit 790a1b17902f7ccb5939b9e0314571079fc30bc8 - Author: Aaron Patterson - Date: 2019-05-31 07:25:31 +0900 - - object id is stable now for all objects, so we can let hash keys move - -commit 2de3d92844058511debef2815a0402f892a5536a - Author: Aaron Patterson - Date: 2019-05-31 06:50:43 +0900 - - allow objects in imemo envs to move - -commit 4eb1c2365cd2745b58eb835ea1e26cc33a1238b1 - Author: Aaron Patterson - Date: 2019-05-31 04:08:06 +0900 - - Unpin objects that `proc` references - - This commit adds compaction support to method and proc objects. It just - unpins references and implements the "compact" callback and updates - references. - -commit ca22cccc14e17d21b4fe7b5aed680e9edf12afb7 - Author: NAKAMURA Usaku - Date: 2019-06-04 03:52:53 +0900 - - get rid of a warning of VC++ - -commit 1a0b82210c924dca447da6aeaffd0ddd502705ea - Author: Takashi Kokubun - Date: 2019-06-04 01:03:03 +0900 - - Upgrade benchmark-driver to fix deprecation warning - -commit 9987f457652f99794c3a8d4467c06ed770cdd393 - Author: Takashi Kokubun - Date: 2019-06-04 00:35:58 +0900 - - Reflect behavior changes to argument name - - 0c459af7c233adb5f44022350bfe8fa132d8053e changed the meaning of - `detect_compile_error`, and this commit lets it follow the change. - -commit fc7b4c70185b320db3bb6f9a05261ec54ce8bc4c - Author: Nobuyoshi Nakada - Date: 2019-06-04 00:27:44 +0900 - - Simplify matching - -commit 0da9205f154b4562aa575b3811dd0e33bc4b07f4 - Author: Takashi Kokubun - Date: 2019-06-04 00:32:16 +0900 - - Remove conflict resolution mistake [ci skip] - - in de541fe1961370e64541d73c96cf790d30f28604 :bow: - -commit d21a694075866f4a3333cf65910a649acd057306 - Author: Takashi Kokubun - Date: 2019-06-04 00:29:53 +0900 - - Improve test_color to prevent regression - - Actually de541fe1961370e64541d73c96cf790d30f28604 was still needed. - This commit would improve the test coverage using the branch. - -commit de541fe1961370e64541d73c96cf790d30f28604 - Author: Takashi Kokubun - Date: 2019-06-04 00:22:22 +0900 - - colorize_code must return escaped text - - This was needed before 0c459af7c233adb5f44022350bfe8fa132d8053e but it - could be actually useless now. But I added this anyway just in case. - -commit 6498c733da4f34aca47ca88412605761467a2fec - Author: git - Date: 2019-06-04 00:20:29 +0900 - - * 2019-06-04 - -commit 0c459af7c233adb5f44022350bfe8fa132d8053e - Author: Nobuyoshi Nakada - Date: 2019-06-04 00:14:55 +0900 - - Colorize error characters - - * lib/irb/color.rb (IRB::Color.scan): ignore "incomplete end of - input" error only, to colorize invalid characters, e.g., control - characters, and invalid symbols, as errors. - -commit 928377d2c5153333445d58710534b471042ffb46 - Author: Takashi Kokubun - Date: 2019-06-03 22:00:14 +0900 - - Revert "common.mk: allow brace expansion for benchmark targets" - - This reverts commit 4c0e21add7c87b70df27fbff81d8f192a467556d - because we're not using /bin/bash. - - See 11d3986d6557eb3cfcecbdd0ef6e21b18c7c960b and - 1b2b0e1f244b3e71812fa9859e8b87150ea30434 to know its context. - In short, 4c0e21add7c87b70df27fbff81d8f192a467556d does not work on - Ubuntu. - -commit 1b2b0e1f244b3e71812fa9859e8b87150ea30434 - Author: Takashi Kokubun - Date: 2019-06-03 21:59:34 +0900 - - Revert "common.mk is NOT working with /bin/sh anymore" - - This reverts commit 11d3986d6557eb3cfcecbdd0ef6e21b18c7c960b. - - Travis was broken by that. - -commit 11d3986d6557eb3cfcecbdd0ef6e21b18c7c960b - Author: Takashi Kokubun - Date: 2019-06-03 21:15:54 +0900 - - common.mk is NOT working with /bin/sh anymore - - at least on Ubuntu. - - The brace expansion does not work on Ubuntu /bin/sh (dash), and so - 4c0e21add7c87b70df27fbff81d8f192a467556d effectively broke /bin/sh - compatibility of common.mk. - I guess he was using macOS whose /bin/sh is bash. - -commit a4c5d234045438e09ea4f5feed0ae50958604907 - Author: Takashi Kokubun - Date: 2019-06-03 20:47:32 +0900 - - benchmark/time_strptime.yml does not work with miniruby - - Since 72ad092960c413b6a5687c552747b20a5ed78b22, we cannot run full `make benchmark` - because default BENCH_RUBY is miniruby and it fails to require 'time'. - - Using miniruby for benchmark by default seems reasonable for some cases, - but now it's just bothering for people running full `make benchmark`. - -commit d7c3eb570b2a9dd76f4e0e5d3c39fa10dc8d0cd7 - Author: aycabta - Date: 2019-06-03 17:23:06 +0900 - - Erase VI_OPERATORS - - The operators are using @waiting_operator_proc in vi mode. - -commit c2805192561ad9690b55c14aaccece1804b61a21 - Author: Koichi Sasada - Date: 2019-05-30 22:36:48 +0900 - - remove `rb_objspace_pinned_object_p()` - - Nobody uses this function other than gc.c. We only need - RVALUE_PINNED(). - -commit c990b3c41af5957a739dfb235dfbb821e73a74df - Author: Nobuyoshi Nakada - Date: 2019-06-03 14:56:42 +0900 - - Fix the error token on "invalid hex escape" - - * parse.y (tok_hex): flush token after dispatching the "invalid - hex escape" parse error. - -commit 22da5d71eaa50a749f8a08beb9bd6fe59e489449 - Author: Nobuyoshi Nakada - Date: 2019-06-03 12:56:13 +0900 - - `ruby -v` may no longer be ASCII-only on non-master branches - -commit 3102ca4c6e0b8fa50f56a6a25d8a28c48251d1c6 - Author: Nobuyoshi Nakada - Date: 2019-06-03 12:26:23 +0900 - - Default GIT external encoding to UTF-8 🤷â€â™‚ï¸ - - And dump the title as US-ASCII. - -commit 17af8bfce6508951edca8650155be5525a894f65 - Author: Jeremy Evans - Date: 2019-06-03 12:00:35 +0900 - - Make size on an infinite each_slice enumerator return Infinity - - Fixes [Bug #15889] - -commit f48aad7ba22811dcd5e5be7af667ec49301ad7cd - Author: Kazuhiro NISHIYAMA - Date: 2019-06-03 10:47:38 +0900 - - Add reline to doc/maintainers.rdoc - -commit 533070bfc69cae5b09103a229e4db33b6af695cb - Author: Kazuhiro NISHIYAMA - Date: 2019-06-03 10:32:32 +0900 - - Use lines instead of split - - ``` - % cat ~/bench-split.yml - prelude: | - s = "foo\nbar\nbaz\n" - benchmark: - '/(?<=\n)/': | - s.split(/(?<=\n)/) - '/^/': | - s.split(/^/) - 'lines': | - s.lines - Warming up -------------------------------------- - /(?<=\n)/ 459.123k i/s - 467.844k times in 1.018994s (2.18μs/i) - /^/ 467.922k i/s - 469.744k times in 1.003894s (2.14μs/i) - lines 2.343M i/s - 2.424M times in 1.034677s (426.84ns/i) - Calculating ------------------------------------- - /(?<=\n)/ 422.347k i/s - 1.377M times in 3.261232s (2.37μs/i) - /^/ 477.603k i/s - 1.404M times in 2.939186s (2.09μs/i) - lines 2.485M i/s - 7.028M times in 2.828757s (402.47ns/i) - - Comparison: - lines: 2484631.6 i/s - /^/: 477603.3 i/s - 5.20x slower - /(?<=\n)/: 422346.5 i/s - 5.88x slower - ``` - -commit 182072b2118ed3d1100303e3c67f54a3ee3d4c33 - Author: aycabta - Date: 2019-06-03 04:17:52 +0900 - - The C-q is also quoted insert in emacs mode - -commit 5524de5ca010e92f18fa6991f7bc953bcf84169d - Author: aycabta - Date: 2019-06-03 03:41:40 +0900 - - Add aliases for commands for moving macro - -commit 1bfba99b793e91f2d26af2ff7051a48f184f649e - Author: aycabta - Date: 2019-06-03 03:38:39 +0900 - - Close leaked file descriptors in tests - -commit 3428922437a31b644cffcabd33fd9353e68f88c8 - Author: aycabta - Date: 2019-06-03 03:29:19 +0900 - - The ed_move_to_beg is different from vi_first_print - -commit 65fdb903250f37add2f83b81a5600d0c3e417427 - Author: Nobuyoshi Nakada - Date: 2019-06-03 02:03:15 +0900 - - Reline::LineEditor::ARGUMENTABLE is no longer used - -commit aeb3a2b3373521a6eb47f7185836351a2c52c2bf - Author: git - Date: 2019-06-03 01:36:55 +0900 - - * 2019-06-03 - -commit 3457ce448655a3c2e52793186f62298903ddc26b - Author: Nobuyoshi Nakada - Date: 2019-06-02 13:10:03 +0900 - - Fix ArgumentError in aliased macro - - Closes: https://github.com/ruby/ruby/pull/2221 - -commit f4b060d8d7f927306cbbe24df888a09112acd4c8 - Author: Nobuyoshi Nakada - Date: 2019-06-02 12:14:29 +0900 - - Check conditional nestings in INPUTRC - - Closes: https://github.com/ruby/ruby/pull/2222 - -commit a1e6e45341d70c608b7b5af98be0f234fd0072fb - Author: Nobuyoshi Nakada - Date: 2019-06-02 12:06:49 +0900 - - Prefer $INPUTRC over the default in the home - - Closes: https://github.com/ruby/ruby/pull/2222 - -commit 4fda39fc8788cbcdd07f04768ec84faf3ea44721 - Author: Kazuhiro NISHIYAMA - Date: 2019-06-02 22:37:42 +0900 - - Use simpler regexp - -commit d04ebc57f232e1a2ca36bd3d5ed9a24f63ee43d6 - Author: Nobuyoshi Nakada - Date: 2019-06-02 12:21:09 +0900 - - Add true condition `Reline` - -commit 06a25344d9944529383cf76e81c8342b8821cf5e - Author: Jeremy Evans - Date: 2019-06-02 13:00:27 +0900 - - Make psych.so deterministic - - Fixes Ruby Bug #15890 - -commit 486a2c26d604ff0e18bae73fe97b95478a44f3d5 - Author: aycabta - Date: 2019-06-02 08:50:01 +0900 - - Add Reline test for unknown macro - -commit e360688c4df08c2a43daa00c1de9832a20ad1521 - Author: aycabta - Date: 2019-06-02 07:39:12 +0900 - - Add new test for Reline within pipe - -commit 28e01f006d124fa8d6d85450f92b188b473921f8 - Author: aycabta - Date: 2019-06-02 07:28:26 +0900 - - Add comments to key bindings vars of Reline::Config - -commit bfd26cc18df6c6eca5b67cea5f2d6a6d557da468 - Author: aycabta - Date: 2019-06-02 07:21:59 +0900 - - Reline.readmultiline always needs block to confirm termination - -commit 7b1c1b949201b5ebe5be597ec27317ea6e9f0841 - Author: aycabta - Date: 2019-06-02 05:07:04 +0900 - - Suppress error of macro not found - -commit 4b9869e7e04cbfb581f6f1b21ae17b310135c5e2 - Author: Jeremy Evans - Date: 2019-05-24 12:07:36 +0900 - - Update String#crypt tests to work on OpenBSD - - Skip the webrick httpauth tests that use crypt when testing on - OpenBSD. - - Fixes [Bug #11363] - -commit 09c09eb0db6c14c532935081c9b79d38fdc81f6b - Author: Nobuyoshi Nakada - Date: 2019-06-02 00:42:57 +0900 - - NEWS: move GC.compact - - From "Implementation improvements" to "Core classes updates". - -commit 3afae5b572bbf6b066ef90648917cbc5028dd4f6 - Author: Nobuyoshi Nakada - Date: 2019-06-02 00:42:11 +0900 - - NEWS: markup class and method names - -commit e814d2f84a6f7c83dcfe1133ec96cf981d09e067 - Author: git - Date: 2019-06-02 00:36:19 +0900 - - * 2019-06-02 - -commit 8a041c1b92b5dcc52908155ba1ca6c9f44a471cb - Author: Nobuyoshi Nakada - Date: 2019-06-02 00:34:02 +0900 - - delegate.rb: markup method names - -commit 2bad001cfd15c59630a03918dc80a703b093688e - Author: Hiroshi SHIBATA - Date: 2019-06-01 21:23:24 +0900 - - Ignore warnings about mismatched indentations. - -commit 464e55f1d0296c3593157a89159f75d58397a1f5 - Author: Hiroshi SHIBATA - Date: 2019-06-01 21:20:21 +0900 - - Ignore warnings about argument prefix with operator symbol. - -commit 3c77ef9adc567af58e27c62db35d618f3b3069d2 - Author: Hiroshi SHIBATA - Date: 2019-06-01 21:07:35 +0900 - - Ignore warnings about ambiguous first argument with the negative integer. - -commit 9eecd7a2fd0b67aa13450887a1fee9a6638b9e4e - Author: Hiroshi SHIBATA - Date: 2019-06-01 20:44:24 +0900 - - Ignore warnings about ambiguous first argument of regexp with assert match. - -commit f630359d9b60e298e472a62f0b6ff17f17ef5c69 - Author: Takashi Kokubun - Date: 2019-06-01 19:38:13 +0900 - - Add a benchmark using IRB::Color - - I heard actually this part would not be a bottleneck for rendering - because writing anything to terminal takes way longer time anyway, but I - thought this benchmark script might be useful for benchmarking Ruby - itself. - -commit 56660de3c6df7a4ff8667ef4047d30d0de169935 - Author: Hiroshi SHIBATA - Date: 2019-06-01 18:45:11 +0900 - - Merge rubygems master from upstream. - - I picked the commit from 3c469e0da538428a0ddd94f99aa73c32da22e8ba - -commit 560cd5b1f04f30542a294b3d77527d3b12f7cc15 - Author: Jeremy Evans - Date: 2019-06-01 16:52:40 +0900 - - Add myself as OpenBSD platform maintainer - -commit de01c4ec00d5357a2aa9ee1c1c989f691a865a21 - Author: aycabta - Date: 2019-06-01 16:47:59 +0900 - - Reset Config at Reline::Config::Test#teardown - -commit 34727475d0a255f4c9f3c66201ac7bcbb516256d - Author: aycabta - Date: 2019-06-01 15:07:22 +0900 - - Remove an unnecessary argument - -commit 3034d666e8015caa05c55a46debd5ed1ff502d47 - Author: Nobuyoshi Nakada - Date: 2019-06-01 14:57:36 +0900 - - Just use `File.readlines` - -commit b487b39b8597daf066fb1e1e7d3087ac694a0d3a - Author: git - Date: 2019-06-01 13:34:55 +0900 - - * expand tabs. - -commit 65e63af377bb493dea4d0207627ed87d5da360a8 - Author: Yusuke Endoh - Date: 2019-06-01 13:15:43 +0900 - - Make opt_aref instruction support Integer#[] - - only when its receiver and the argument are both Integers. - - Since 6bedbf4625, Integer#[] has supported a range extraction. - This means that Integer#[] now accepts multiple arguments, which made - the method very slow unfortunately. - - This change fixes the performance issue by adding a special handling for - its traditional use case: `num[idx]` where both `num` and `idx` are - Integers. - -commit 7df65ef67691fcc354d819da9cd54a1ade9b6247 - Author: aycabta - Date: 2019-06-01 09:05:58 +0900 - - Use inputrc data for keystroke setting - -commit c1e52997870a63168835fde49562cb3c822c968a - Author: Nobuyoshi Nakada - Date: 2019-06-01 01:46:23 +0900 - - Fix FrozenError when assigning frozen class to constant - - * variable.c (set_namespace_path): modules/classes can get named - by assignment to constant, even if frozen. [Bug #15891] - -commit aeb9a0ca77725896ef072fa9bc0a031430a3a0e5 - Author: MSP-Greg - Date: 2019-06-01 01:21:52 +0900 - - appveyor.yml again! - - This issuse is caused by MSYS2 changing from using ncurses to pdcurses. - Appveyor's MSYS2 is so out-of-date that partial updates are 'troublesome'... - -commit 1d37cc1900b6cf13285417577cb21c01195d3d2a - Author: Benoit Daloze - Date: 2019-06-01 02:02:08 +0900 - - Update to ruby/spec@cfe908c - -commit f97979ce888492cbf1c3c92839e086fbec1e5d15 - Author: Benoit Daloze - Date: 2019-06-01 02:02:06 +0900 - - Update to ruby/mspec@a57a9af - -commit 552c42f51f75eeeaa5a46e2df28fd5dab77261da - Author: Nobuyoshi Nakada - Date: 2019-06-01 00:34:38 +0900 - - Separate raw keystroke config for each platforms - -commit 8fc552adee76ec324a219ba6b19fa2e39a1e014e - Author: git - Date: 2019-06-01 00:03:18 +0900 - - * 2019-06-01 - -commit 88770c2ab668cd01cac016fcf81cb2c8f265ab18 - Author: aycabta - Date: 2019-06-01 00:02:35 +0900 - - Support Home and End key to move to beg and end - -commit 21a43489b18d2ceb04182e0d36bb906439a86610 - Author: aycabta - Date: 2019-05-31 22:53:01 +0900 - - Use IO#sync= instead of a monkey patch - -commit 73890d9d79425415774a3a2d72ee5882bc41e5c7 - Author: aycabta - Date: 2019-05-31 22:32:47 +0900 - - Flush I/O immediately if RELINE_STDERR_TTY is set - -commit 913661cca08ccc6e2b4fd7367ddafcc7e2569a36 - Author: Hiroshi SHIBATA - Date: 2019-05-31 22:15:43 +0900 - - Bump irb version to 1.1.0.pre.1. - - Because the current irb support reline and have many of changes. - -commit 1457ad1ea77ff2dd6498ad9c8f1ab6c8165df98e - Author: Nobuyoshi Nakada - Date: 2019-05-31 19:12:24 +0900 - - [DOC] JIS X 0301 has been updated - - [ruby-dev:50790] - * https://www.meti.go.jp/press/2019/05/20190520006/20190520006.html - * https://www.meti.go.jp/press/2019/05/20190520006/20190520006-2.pdf - - [ci skip] - -commit 8b39df854d7dea1c15949c6b047bcb0f0a12c287 - Author: Nobuyoshi Nakada - Date: 2019-05-31 16:31:22 +0900 - - Let irb use an empty file as irbrc - - to get rid of side-effect by existing .irbrc file. - -commit b632566d339968bfd271a07e290a71bbb7f621ec - Author: Nobuyoshi Nakada - Date: 2019-05-31 16:14:27 +0900 - - UNIX domain socket name length has a certain limit - -commit b1aecef87364631b0001dd2aafc432931e19a98f - Author: Nobuyoshi Nakada - Date: 2019-05-31 15:58:50 +0900 - - Use UNALIGNED_MEMBER_PTR - - * internal.h (UNALIGNED_MEMBER_ACCESS, UNALIGNED_MEMBER_PTR): - moved from eval_intern.h. - - * compile.c iseq.c, vm.c: use UNALIGNED_MEMBER_PTR for `entries` - in `struct iseq_catch_table`. - - * vm_eval.c, vm_insnhelper.c: use UNALIGNED_MEMBER_PTR for `body` - in `rb_method_definition_t`. - -commit ea42423908ed055f9039b1dce6e9a232a3b2dd90 - Author: Alan Wu - Date: 2019-05-31 12:16:27 +0900 - - Keep vm->orig_progname alive - - `vm->orig_progname` can be different from `vm->progname` when user - code assigns to `$0`. While `vm->progname` is kept alive by the - global table, nothing marked `vm->orig_progname`. - - [Bug #15887] - -commit 83f9183a7e549b0d7e6b68e298d57744ddb4d97f - Author: Nobuyoshi Nakada - Date: 2019-05-31 14:05:01 +0900 - - Also GCC 9 provides -Waddress-of-packed-member - -commit d2f663d6f185f62ef019434caf9bd6afd63849d4 - Author: Nobuyoshi Nakada - Date: 2019-05-31 10:05:38 +0900 - - STATIC_ASSERT for VM_METHOD_TYPE_MINIMUM_BITS - -commit d180e405703b36c3f3a84334779c56bf9a3ea6a8 - Author: Nobuyoshi Nakada - Date: 2019-05-31 02:52:41 +0900 - - Add --limit option and default it to 20 - -commit 1e9057b54a53e7bc1fa3d0e3eaef1dd33707d044 - Author: Nobuyoshi Nakada - Date: 2019-05-31 02:30:29 +0900 - - Prefer the current branch or tag name - -commit fd658ec821f07e0a2254fcd62ce29cc644d61302 - Author: Nobuyoshi Nakada - Date: 2019-05-31 02:28:38 +0900 - - Define RUBY_FULL_REVISION - - Only if the short revision differs from the full revision. - -commit e8c710b11a02c6ab82b358fc671a14f378cb1974 - Author: Jeremy Evans - Date: 2019-05-24 13:10:40 +0900 - - Fix visibility of some methods when using DelegateClass - - Public instance methods added to a delegated class after the - creation of the delegate class were not returned by the - public_instance_methods class method of the delegate class. - - Protected instance methods in the delegated class when the - delegate class is created were returned by the public_methods - instance method of the delegate class. - - Patch mostly from Kenichi Kamiya in - GitHub pull request 926. Minor changes to get it to apply, - and to fix tests after applying by me. - - Fixes [Bug #11512] - -commit 1cd93f1cdfbe6f7e71b05b3f8e707f21d70e94ba - Author: Jeremy Evans - Date: 2019-05-12 08:32:00 +0900 - - Allow DelegateClass() to module_eval given block - - Methods that return classes often module_eval the given block - (e.g. Class.new and Struct.new). This allows DelegateClass to - work similarly. This makes it easier to use DelegateClass - directly without subclassing, so as not to create an unnecessary - subclass. - - Implements [Feature #15842] - -commit 856593cc4972562d2ab0a59a61f38fe3a4a863ab - Author: Takashi Kokubun - Date: 2019-05-31 09:44:14 +0900 - - Fix typo :bug: [ci skip] - -commit 6a5e89e23c433199f926d757481bc3c29fce7854 - Author: Takashi Kokubun - Date: 2019-05-31 07:24:08 +0900 - - Set git config to commit mjit-debug - - As it failed to commit like: - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cefd8a8105780001c4f2d5d?step=5cefdd1e48fad200077fa3f8 - -commit cb40a21da0687b5dd3cd251c9e66bb0edf67f2b9 - Author: Takashi Kokubun - Date: 2019-05-31 06:03:18 +0900 - - Warn compile_error only when input is finished - - Let's say we are in progress to write `"foo"`: - - ``` - irb> "fo - ``` - - at this moment, nothing is wrong. - It would be just a normal way to write `"foo"`. - - Prior to this commit, the `fo` part was warned because of - 5b64d7ac6e7cbf759b859428f125539e58bac0bd. But I think warning such a - normal input is not valuable for users. - - However, we'd like to warn `:@1` or `@@1` which is also a syntax error. - Then this commit switches the syntax highlight based on whether the - input text is finished or not. When it's not finished yet, it does not - warn compile_error. - -commit 6e052817f95095217b67256aff48cedbd57717cf - Author: Takashi Kokubun - Date: 2019-05-31 06:17:56 +0900 - - Abstract away Ripper::Lexer#scan in IRB::Color#scan - - because 5b64d7ac6e7cbf759b859428f125539e58bac0bd made it hard to - understand #colorize_code for me and this change is needed for my next - commit. - -commit 8f83fe3b02f6689cd1ea85ec59c6fad12066f301 - Author: aycabta - Date: 2019-05-31 05:53:02 +0900 - - Finish with ^D only when input is completely empty in vi insert mode - -commit a4161b7649c5aec6ff4d857863e0e829f9d7fde8 - Author: Benoit Daloze - Date: 2019-05-31 05:11:24 +0900 - - Update to ruby/spec@0ba5312 - -commit e935a3227d1553539f65d1475f2c161082ba7148 - Author: Benoit Daloze - Date: 2019-05-31 05:11:22 +0900 - - Update to ruby/mspec@3cc36d0 - -commit c55db6aa271df4a689dc8eb0039c929bf6ed43ff - Author: git - Date: 2019-05-31 00:01:41 +0900 - - * 2019-05-31 - -commit f7aa80b3feeddac6a5689f286b3db3728128caa4 - Author: Nobuyoshi Nakada - Date: 2019-05-31 00:00:26 +0900 - - Make the target name unique when BASERUBY=no - -commit ab0c8cc021b26712c9af9b1309244b7d930c9dfa - Author: Nobuyoshi Nakada - Date: 2019-05-30 22:57:49 +0900 - - Touch Unicode headers and the timestamp before packaging - - Not to download Unicode data files at building from the packages. - -commit f0945176c356cfe615ff6b4e6012e7e8e0911bd6 - Author: Nobuyoshi Nakada - Date: 2019-05-30 22:27:11 +0900 - - Fix missing `gitcmd` - -commit 22cd4027349f803efc7ede284376b7a7013f8dfe - Author: NARUSE, Yui - Date: 2019-05-30 22:19:36 +0900 - - vcs.rb support non-inplace build - -commit 92ecf58b1e8ed15f5ec2bf69e3871de4343f71e0 - Author: Nobuyoshi Nakada - Date: 2019-05-30 22:03:33 +0900 - - parse.y: adjust here-doc error token - - * parse.y (here_document): adjust token to the here-doc identifier - in compile_error when a here-document misses the closing - identifier. - -commit b0e2b7a5ff0df14b3c8062c31ebb526a73a03763 - Author: Nobuyoshi Nakada - Date: 2019-05-30 21:49:08 +0900 - - Include stack elements left after errors - -commit 279c8e14d4b079e5b70b0389b82893de42b75c50 - Author: aycabta - Date: 2019-05-30 20:54:28 +0900 - - Use rebuilt buffer data to rerender all - -commit 74a0e3ec235380541db95e18978e4e1aa174b407 - Author: aycabta - Date: 2019-05-30 20:06:59 +0900 - - Use start_with? for escaped quote too - -commit ecd0f1d966209742382e5bd4591bafc88152a697 - Author: aycabta - Date: 2019-05-30 18:29:26 +0900 - - Use negative lookahead and start_with? - -commit fcca39fa73607e6acf2aea00fd8bf746023955dc - Author: aycabta - Date: 2019-05-30 18:20:59 +0900 - - Fix strange vertical cursor moving when adding a newline at bottom - -commit 106843d839cb5779c7e2761b826aea78bd9a7e63 - Author: git - Date: 2019-05-30 17:12:53 +0900 - - * expand tabs. - -commit 5fc9f0008f824936c667970593df1b6663f0ae24 - Author: Koichi Sasada - Date: 2019-05-30 17:12:26 +0900 - - reorder bitmap clearing. - -commit dd63d7da61c472809c5e6a1dba81b7dea5aa1c1b - Author: Koichi Sasada - Date: 2019-05-30 16:57:37 +0900 - - move pinned_bits[] position in struct heap_page. - - pinned_bits are not used frequently (only GC.compact use it) so - move it at the end of struct heap_page. - -commit e15de865837262122cc64705440d00efac4b8c71 - Author: Koichi Sasada - Date: 2019-05-30 16:52:42 +0900 - - introduce `during_compacting` flag. - - Usually PINNED_BITS are not needed (only for GC.compact need it) - so skip updating PINNED_BITS if the marking is not by GC.compact. - -commit 70e87d9660af24fb93cac1312b6e1990602c1396 - Author: Takashi Kokubun - Date: 2019-05-30 15:49:48 +0900 - - Do not rely on IRB.conf[:MAIN_CONTEXT] before initialize - - so that we can colorize binding.irb source lines. - -commit 55c34b994b40db4d9fdbc29d9d8521745a56fdfd - Author: aycabta - Date: 2019-05-30 15:34:41 +0900 - - Check the end token of heredoc correctly - -commit 5a229b0a88679529a18aa3ef87317bdbd1783c58 - Author: aycabta - Date: 2019-05-30 15:19:30 +0900 - - Calculate vertical position correctly when rerendering all lines - -commit 90014dddec70219c2da800bf0d4d262bfa99c9a8 - Author: aycabta - Date: 2019-05-30 15:04:37 +0900 - - Fix broken rendering when the last line is auto-wrapped - -commit eae953ba9ff3302a698115f34893f17bf458d2ea - Author: aycabta - Date: 2019-05-30 14:19:58 +0900 - - Rerender following lines when line number increased - -commit 1cf9f79342c517e3f12ba614ad874b1d619af5bc - Author: aycabta - Date: 2019-05-30 14:04:14 +0900 - - Clear remaining lines when line number decreased - -commit 4a31c1e45d12b7813096948616f8a03224f20ac8 - Author: Nobuyoshi Nakada - Date: 2019-05-30 12:35:27 +0900 - - parse.y: continue after heredoc error - - * parse.y: continue parsing the rest of the here-document starting - line, after the terminator was not found. - -commit cb520e76237d3884b768f4f68120beb13fcf1f04 - Author: aycabta - Date: 2019-05-30 12:29:38 +0900 - - Fix the auto-wrap behabior that was too buggy - -commit f0ded366933407cfd0ad2c516b69d2766d1634d2 - Author: Jeremy Evans - Date: 2019-05-30 10:40:03 +0900 - - Use Regexp#match instead of #match for 1.9 BASERUBY support - -commit d2ba80b5df7118383cbcfae934316310c6d81633 - Author: Jeremy Evans - Date: 2019-05-30 09:58:18 +0900 - - Revert "Fix building with 1.8 BASERUBY" - - This reverts commit 05bc14d81a1d7f6af826a92371aeff0c3fb2a67e. - - We have decided that the cost of reintroducing support for 1.8 - BASERUBY outweighs the benefit. If you are still using 1.8 and want - to build master/trunk, build and install the latest release, and use - that as BASERUBY. - -commit 5867e51e8311d1ed49457e946751cd0c06a306b8 - Author: git - Date: 2019-05-30 04:13:37 +0900 - - * 2019-05-30 - -commit 814eaa25e2a54b5997f0d89da1a6e2259d4fc1e9 - Author: Takashi Kokubun - Date: 2019-05-30 04:12:10 +0900 - - Do not use rb_iseq_path() while moving ISeq pointers - - in GC.compact. - - While `in_jit` is false, GC.compact is allowed to run and it may be - moving ISeq-related pointers. So calling rb_iseq_path() when `in_jit` - is true is illegal. - -commit 5b64d7ac6e7cbf759b859428f125539e58bac0bd - Author: Nobuyoshi Nakada - Date: 2019-05-29 22:03:47 +0900 - - Colorize errors more - - * lib/irb/color.rb (IRB::Color.colorize_code): colorize - `compile_error` part as same as `on_parse_error`. - -commit 12644e8b0208b01f4f4cea550d161a86e6f25aa8 - Author: Nobuyoshi Nakada - Date: 2019-05-29 21:59:34 +0900 - - Get rid of nested string interpolations - - * lib/irb/color.rb (IRB::Color.colorize): get rid of nesting string - interpolations not to confuse ruby-mode.el - -commit 1da5c73932b2dcf2a089f125df1fe7cc4ab9fafd - Author: Nobuyoshi Nakada - Date: 2019-05-29 21:39:45 +0900 - - parse.y: fix state after ivar/cvar - - * parse.y (parse_atmark): return EXPR_END or EXPR_ENDFN, depending - on the previous state, even incomplete names consistently. - -commit 83e905eb4e6d1e8a7ebe88e3b1a6d7efa67ba01c - Author: aycabta - Date: 2019-05-29 20:24:00 +0900 - - Revert "Use "require" just for essential" - - This reverts commit ab7a6e1a1651d82d327d155b78a8e3af1d976707. - -commit ab7a6e1a1651d82d327d155b78a8e3af1d976707 - Author: aycabta - Date: 2019-05-29 20:20:48 +0900 - - Use "require" just for essential - - The 559dca509d2a98584b09c7d9a6d74749ce793ad7 contains an excess range in - using "require". - -commit fafcbe0eb0af0aa25ca1fa6e162e081bb78a8107 - Author: aycabta - Date: 2019-05-29 18:52:20 +0900 - - Use reversed get_screen_size correctly on Windows - -commit 5ceff480c2c1696e9893a1e5e09e39f8425c6c5a - Author: Nobuyoshi Nakada - Date: 2019-05-29 16:02:09 +0900 - - ripper: Ripper::Lexer#scan - - * ext/ripper/lib/ripper/lexer.rb (Ripper::Lexer#scan): parses the - code and returns the result elements including errors. - [EXPERIMENTAL] - -commit 7c0639f3f83f85557aff87e94da1afd373555bcb - Author: Takashi Kokubun - Date: 2019-05-29 16:47:57 +0900 - - Never make a method call from MJIT worker - - by showing line number only when it's Fixnum. - - When it's not Fixnum, we need to call a method to know the line number. - -commit ce7b1132c581375dafa6a5b5071e66eaa362b429 - Author: Takashi Kokubun - Date: 2019-05-29 16:22:26 +0900 - - Do not call FIX2INT while GC.compact may be running - - because FIX2INT might crash by moving method entry pointer: - http://ci.rvm.jp/results/trunk-mjit@silicon-docker/2063412 - -commit 468b475e615e59c0778751051ecda175140c615e - Author: Takashi Kokubun - Date: 2019-05-29 16:09:07 +0900 - - .travis.yml: Minor reorder for shortening - -commit 1a0c3d8dd64eb90f5d74e68458d686c4f9cc1669 - Author: Takashi Kokubun - Date: 2019-05-29 15:04:31 +0900 - - Convert Enumerator to Array for Ruby 1.9.3 - - String#lines seems to return Enumerator in Ruby 1.9.3, and it does not - respond to #delete_if https://travis-ci.org/ruby/ruby/jobs/538559919 - -commit 5379ca92501c529005c0818f3cbbd1ef0798de6d - Author: Takashi Kokubun - Date: 2019-05-29 14:56:58 +0900 - - Skip spec broken since a66bc2c01194a9c017c874a30db5b3b6bd95e966 - - This has not worked since the merge https://travis-ci.org/ruby/ruby/jobs/538438184 - -commit 068d327595814a3448290eeba897fc37a8bb2dfb - Author: Nobuyoshi Nakada - Date: 2019-05-29 13:34:19 +0900 - - Colorize compile_error as same as on_parse_error - -commit cc66272e5061020cac6864bbc2f68f7d327ecfbb - Author: Nobuyoshi Nakada - Date: 2019-05-29 12:48:49 +0900 - - parse.y: flush invalid char - -commit 8552e9d69693b1d3f99a30d846b9dcc30bf590c2 - Author: Nobuyoshi Nakada - Date: 2019-05-29 13:24:01 +0900 - - Fix shorten-64-to-32 warning - -commit aee36bf149bedf97007584ac5d6cd5d438be28b5 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-29 13:12:15 +0900 - - Fix Possible Control flow issues (DEADCODE) - - Coverity Scan says `Execution cannot reach this statement: "poison_object(v);"`, - so do nothing when `ptr` is always 0 without address_sanitizer. - -commit e04d10b28f47ea4d32f9562aedc4be9749415219 - Author: Yusuke Endoh - Date: 2019-05-29 13:01:53 +0900 - - test/rubygems/test_gem_stream_ui.rb (test_ask_for_password): extend the timeout - - for Solaris. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190528T191908Z.fail.html.gz - -commit 8187ffa461be6c1ee198c0b8f2c3a22ca2681d9a - Author: Koichi Sasada - Date: 2019-05-29 12:30:36 +0900 - - Revert "Colorize error part more" - - This reverts commit c7f3c222c9b82736c993419daa6bfb643e5c0793. - -commit c7f3c222c9b82736c993419daa6bfb643e5c0793 - Author: Nobuyoshi Nakada - Date: 2019-05-28 18:19:59 +0900 - - Colorize error part more - - Colorize `compile_error` parts as well as `on_parse_error` parts. - -commit 34fe1f7d719d556cd7eda16d4df7cc64ce25dcfa - Author: Nobuyoshi Nakada - Date: 2019-05-29 12:09:19 +0900 - - Create empty revision.tmp if BASERUBY is not yes - -commit 3f132979236f4aa42e3347a920123ce271a1e695 - Author: aycabta - Date: 2019-05-29 10:04:39 +0900 - - Remove extra items because Reline::HISTORY is a sized queue - -commit c86d1fbed5e887ea7b59582510fb26ec912b7898 - Author: Nobuyoshi Nakada - Date: 2019-05-29 09:46:44 +0900 - - Create empty revision.tmp if no BASERUBY - -commit f60a59ed20648ddc4784d2dcb172d10c5f3405ed - Author: MSP-Greg - Date: 2019-05-29 06:03:30 +0900 - - appveyor.yml - update for msys2 - pdcurses, force toolchain - - Closes: https://github.com/ruby/ruby/pull/2208 - - Merging the PR for fixing AppVeyor msys2 failure related to GCC 9 like: - https://ci.appveyor.com/project/ruby/ruby/builds/24877992/job/ned5k4k5rwxnld5j - -commit 98ba116d402e7c255dae78ce43b76723a56c4cb7 - Author: Takashi Kokubun - Date: 2019-05-29 09:02:39 +0900 - - Revert 3b7862c8e88cd7838a53ec083ac5733386400956 causing various CI hangs - - and dependent commits c67934b1c3b40dda5f170b032423e520511c68dd and - f0d1dc5cee87dfb023cb43a2db9bcdef5a8dee8f. - - RubyCI and ci.rvm.jp are almost dead by timeout since this commit. - - --- - - Revert "Skip a reline test hanging on Wercker since 3b7862c8e8" - - This reverts commit f0d1dc5cee87dfb023cb43a2db9bcdef5a8dee8f. - - Revert "Remove extra items because Reline::HISTORY is a sized queue" - - This reverts commit c67934b1c3b40dda5f170b032423e520511c68dd. - - Revert "Use existing instances for LineEditor and Config" - - This reverts commit 3b7862c8e88cd7838a53ec083ac5733386400956. - -commit 797d7efde18c5f7acf5264047842fd974f383ca9 - Author: Takashi Kokubun - Date: 2019-05-29 08:56:26 +0900 - - Prevent MJIT compilation from running while moving - - pointers. - - Instead of 4fe908c1643c3f355edd787bb651aefb53b996c0, just locking the MJIT - worker may be fine for this case. And also we might have the same issue - in all `gc_compact_after_gc` calls. - -commit 6b5e712361cca8559ed66d5c1106e888c5971d39 - Author: Takashi Kokubun - Date: 2019-05-29 08:22:02 +0900 - - Make tool/vcs.rb compliant to BASERUBY - - People seem to consider BASERUBY is either 1.8 or 1.9 now. Since this - file may be executed by BASERUBY from file2lastrev.rb, I think we should - not rely on Ruby 2.0 in this file for now. - -commit e1f62d7f0e33de81a194f26a2c57e14e38d9de52 - Author: Takashi Kokubun - Date: 2019-05-29 07:46:44 +0900 - - Check the result of file2lastrev.rb if HAVE_BASERUBY - - is yes. - - We ignored the failure status of file2lastrev.rb on 73da429c36c, but it - was for an environment without BASERUBY. I think we should skip running - file2lastrev.rb on HAVE_BASERUBY=no, and run it and check the status on - HAVE_BASERUBY=yes. - - Otherwise we may have an ignored arbitrary error of file2lastrev.rb on - HAVE_BASERUBY=yes environment. - -commit f0d1dc5cee87dfb023cb43a2db9bcdef5a8dee8f - Author: Takashi Kokubun - Date: 2019-05-29 08:08:33 +0900 - - Skip a reline test hanging on Wercker since 3b7862c8e8 - - like https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cedad11105780001c4e7001?step=5cedaf6b48fad200076fe77b - -commit 67f75d5b4332f6bef2d1ea19803dc6092e6cbf3b - Author: Takashi Kokubun - Date: 2019-05-29 08:04:48 +0900 - - Add TESTOPTS=-v for Wercker test-all --jit-wait - - because it's hard to identify which test causes a hang for now. - -commit 8d837431709c004a0fcd0a9f7f811ced04a040d7 - Author: aycabta - Date: 2019-05-29 06:53:18 +0900 - - Use IO.copy_stream - -commit a4a682c450164d1d4371e00a4f83429aa85d29ae - Author: aycabta - Date: 2019-05-29 06:11:24 +0900 - - Check RUBY_YES_I_AM_NOT_A_NORMAL_USER env to access RubyVM doc - -commit d341bb285768ae70bc8d251e577181c57322968c - Author: aycabta - Date: 2019-05-29 06:08:25 +0900 - - IRB never show RubyVM's doc - -commit d390af3686d640dd2aa54af51ed5c2a8e581a46e - Author: aycabta - Date: 2019-05-29 06:54:49 +0900 - - Encode completed strings correctly - -commit 3e54ff67e6dc1c5882fc05392add09bc59c1afae - Author: Takashi Kokubun - Date: 2019-05-29 05:53:09 +0900 - - Test BASERUBY: Ruby 1.9.3 on Travis - - We have no clear assertion or check of BASERUBY requirement. - I want to make the current situation more explicit. - - I'm NOT saying we should support Ruby 1.9.3 here, - but I'm just checking the situation as per 05bc14d81a1d7f6af826a92371aeff0c3fb2a67e. - - FYI, at this moment Ruby 1.8.7 did not work with this Travis config, like: - https://travis-ci.org/k0kubun/ruby/builds/538459100 - -commit 91f5a8db593f9eef739517dc0067dae439934311 - Author: Benoit Daloze - Date: 2019-05-29 06:15:57 +0900 - - Update to ruby/spec@0c5c5c1 - -commit c67934b1c3b40dda5f170b032423e520511c68dd - Author: aycabta - Date: 2019-05-29 05:58:33 +0900 - - Remove extra items because Reline::HISTORY is a sized queue - -commit 3b7862c8e88cd7838a53ec083ac5733386400956 - Author: aycabta - Date: 2019-05-29 05:53:14 +0900 - - Use existing instances for LineEditor and Config - -commit a66bc2c01194a9c017c874a30db5b3b6bd95e966 - Author: Benoit Daloze - Date: 2019-05-29 05:41:48 +0900 - - Update to ruby/spec@9a501a8 - -commit d070523e7be4b95914adeef9a10401fba7718c5a - Author: Takashi Kokubun - Date: 2019-05-29 05:27:53 +0900 - - Drop unused Travis config: universal-darwin17 - - This has been unused since b7f5c573ef20dbbf5534ee3a45625c7f9d45f2ec. - -commit 462a63c39e7aa20253d6256077d298458c9ef7f3 - Author: Takashi Kokubun - Date: 2019-05-29 05:09:59 +0900 - - Drop MJIT debug code from GC.compact - - As ko1 added some improvements on GC.compact, I want to check if it - solved the problem too. - -commit abd556958d11321cf0a2991a86dc8b1a714fc79a - Author: git - Date: 2019-05-29 00:07:07 +0900 - - * 2019-05-29 - -commit c730c25354a18e99b9147c30ecc8f986d6a172f1 - Author: Nobuyoshi Nakada - Date: 2019-05-28 21:39:13 +0900 - - parse.y: warn escaped whitespace - - * parse.y (warn_space_char_code): warn whitespace characters - escaped with meta/control prefix. - -commit fb568fe724b0c8b2582263ed859ad10f0bd90d38 - Author: Nobuyoshi Nakada - Date: 2019-05-28 23:46:07 +0900 - - Added missing predicate macros - -commit 8a2b497e3b8d9c9be27278081526cace50490140 - Author: Koichi Sasada - Date: 2019-05-28 15:57:20 +0900 - - remove obsolete rb_gc_finalize_deferred(). - - rb_gc_finalize_deferred() is remained for compatibility with - C-extensions. However, this function is no longer working - from Ruby 2.4 (crash with SEGV immediately). - So remove it completely. - -commit 2562b7d7cd6621970fed1ad72d87f8d23d50d398 - Author: Nobuyoshi Nakada - Date: 2019-05-28 11:08:53 +0900 - - Unify RELINE_TEST_ENCODING setting - -commit d5f408403f805b2ff616b9c43528d9fdffa3bf60 - Author: Nobuyoshi Nakada - Date: 2019-05-28 11:08:22 +0900 - - Set read-only with attrib command - -commit 62b3d4c721334108f89cd59407ffd910204e7868 - Author: Nobuyoshi Nakada - Date: 2019-05-28 14:36:29 +0900 - - Skip following all digits after `@@` - -commit 40e175b390f39afdddcfbf74afcad96093a158e7 - Author: Nobuyoshi Nakada - Date: 2019-05-28 14:20:42 +0900 - - Clean a garbage [ci skip] - -commit 05bc14d81a1d7f6af826a92371aeff0c3fb2a67e - Author: Jeremy Evans - Date: 2019-05-28 12:54:20 +0900 - - Fix building with 1.8 BASERUBY - -commit f3bddc103d6a9d6e679ab35d1d3e8ab7aa2f3ae4 - Author: Koichi Sasada - Date: 2019-05-28 11:42:31 +0900 - - use malloc() instead of calloc(). - - Here malloc() is enough because all elements of the page_list - will be overwrite. - -commit f9401d5d44dd4ae69b6a14fcccd41c2810033986 - Author: Koichi Sasada - Date: 2019-05-28 11:41:49 +0900 - - should skip T_ZOMBIE here. - -commit 2229acaa54e1011ae77710e10f8c9e7933403127 - Author: Koichi Sasada - Date: 2019-05-28 11:41:03 +0900 - - should use heap_eden->total_pages. - - The size of page_list is heap_eden->total_pages, but - init_cursors() assumes the size of page_list is `heap_allocated_pages`. - This patch fix it. - -commit 72333286c45ac821e227ad62d810a09a0208ecbb - Author: Nobuyoshi Nakada - Date: 2019-05-28 11:38:13 +0900 - - Fix typos in Ripper::Lexer#inspect and Ripper::Lexer#pretty_print - -commit ccfb12d76ca58957cb95692594626169a97224b7 - Author: aycabta - Date: 2019-05-28 11:02:44 +0900 - - Fix condition..."and" is lowest priority operator, than "=" - -commit 7f211bfe6c5e4a763412406e5e257ea275ca53da - Author: Koichi Sasada - Date: 2019-05-28 10:26:23 +0900 - - use only eden_heaps on GC.compact. - - `heap_pages_sorted` includes eden and tomb pages, so we should not - use tomb pages for GC.compact (or we should move all of tomb pages - into eden pages). Now, I choose only eden pages. If we allow to - move Zombie objects (objects waiting for finalizers), we should - use both type of pages (TODO). - -commit cfd839c140707852340a840e9e164e0f211fbb42 - Author: Koichi Sasada - Date: 2019-05-27 17:15:58 +0900 - - Suppress warning (uninitialized variable). - -commit fa7a768fdfe5223a29db4fa71b3e6101fb02ad51 - Author: Hiroshi SHIBATA - Date: 2019-05-28 10:23:21 +0900 - - Removed inconsistency file from upstream repository of rubygems. - - followed up ae2a904ce9bffedee7d110dc60fd51c0a2879a5b - -commit 165ddfda20f6db8a3149d14c4f431fc242ddab70 - Author: git - Date: 2019-05-28 10:07:55 +0900 - - * remove trailing spaces. - -commit ae2a904ce9bffedee7d110dc60fd51c0a2879a5b - Author: Yusuke Endoh - Date: 2019-05-27 23:44:15 +0900 - - Update the certificate files to make the test pass on Debian 10 - - The old certificate files (for example, test/rubygems/ca_cert.pem) were - signed by SHA1. This message digest is considered too weak and rejected - by OpenSSL 1.1.1 or later. Because of this, the test suite does not - pass on Debian 10. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian/ruby-master/log/20190527T123003Z.fail.html.gz#test%2Frubygems - - This change regenerates the files. - A shell script for the regeneration (util/create_certs.sh) is also - added. - -commit cf904d9f9fb18fd2982651946125db62066c3ff5 - Author: Takashi Kokubun - Date: 2019-05-28 10:02:30 +0900 - - Avoid doubly building Travis and AppVeyor - - but on "master" branch. - - For Pull Request, I changed the approach from - d9b338a53f520b2dbb05555f18b8de8072300f40 and - 277e68825a8e4d0e6503a32e41f8b1b6c078b567. - -commit 1cdaa17a065c529354fa9bcb4a1f3001783900ef - Author: Nobuyoshi Nakada - Date: 2019-05-28 08:44:28 +0900 - - parse.y: numbered parameter symbol - - * parse.y (parse_atmark): numbered parameter name is not allowed - as a symbol regardless the context. - -commit 57b4df07bc1e863c48a3b0f4c3185de431454695 - Author: aycabta - Date: 2019-05-28 08:38:55 +0900 - - Use Reline.completer_quote_characters to complete - -commit 74c88e7cda8640084077003ec00b004f9dd7ae73 - Author: aycabta - Date: 2019-05-28 05:10:49 +0900 - - Fix reversed row and column get_screen_size on Windows - -commit f6b62d8fe77a474935ef3dee6bb20ca3cc4da602 - Author: aycabta - Date: 2019-05-28 04:39:29 +0900 - - Use Shift+Enter as Meta+Enter on Windows - -commit 8b135cc8752abf89f2c11fb8760febb756348577 - Author: aycabta - Date: 2019-05-28 04:25:50 +0900 - - Use VK_MENU instead of VK_LMENU to check ALT on Windows - -commit d5682eb9396c7813f50a1400f7e801d0058c6c6e - Author: aycabta - Date: 2019-05-28 03:25:31 +0900 - - Remove unused variable from IRB::InputCompletor - -commit 5e275dd2af4d9d24cdb1cfc0f232f348dae9c2cd - Author: aycabta - Date: 2019-05-28 03:23:52 +0900 - - Treat :@1, :@@1, @1, and @@1 correctly to check termination - -commit 7447c7b651d9074879429bb84dd73f8821521f27 - Author: aycabta - Date: 2019-05-28 01:52:04 +0900 - - Join next line if deletes newline at end of line - -commit 69c7ad17235319c78766102068402ab9fcc9a5ca - Author: aycabta - Date: 2019-05-28 01:51:01 +0900 - - Exit only when blank input - -commit b2b5ed14104d2010ceae9fc81823bdcdc84b3bd7 - Author: Kazuki Tsujimoto - Date: 2019-05-28 01:30:15 +0900 - - Suppress duplicated warning - -commit 9a68aba79f8a3e144e6409988c2e17a5d3f11f26 - Author: aycabta - Date: 2019-05-28 00:15:38 +0900 - - Support OSC and treat \1 \2 correctly - -commit 70166b3ca3eff9747d8c861b3a30e3ef96ffbb72 - Author: aycabta - Date: 2019-05-28 00:20:43 +0900 - - Revert "Support OSC and treat \1 \2 correctly" - - This reverts commit 77bfebebc44c5e46ebd156d074081846c037f882. - -commit 11778fd246a7fe58c3edfa1dbdb87f62b1f36747 - Author: git - Date: 2019-05-28 00:20:24 +0900 - - * 2019-05-28 - -commit 77bfebebc44c5e46ebd156d074081846c037f882 - Author: aycabta - Date: 2019-05-28 00:15:38 +0900 - - Support OSC and treat \1 \2 correctly - -commit 8a2a5822caa7a9fc146d7de4db679986603d7a4f - Author: Nobuyoshi Nakada - Date: 2019-05-27 19:59:17 +0900 - - Colorize error part - -commit b4365e75fd70618b79b3a71c1c13f202acd71368 - Author: Nobuyoshi Nakada - Date: 2019-05-27 19:58:15 +0900 - - Do not make an incomplete escape a valid char - -commit c40003da25543b0f828911af56108ee16af35236 - Author: Nobuyoshi Nakada - Date: 2019-05-27 19:20:11 +0900 - - Ripper#token - - * parse.y (ripper_token): added Ripper#token which returns the - current token string. [EXPERIMENTAL] - -commit b3602f1d20baa4e5f29b2baff2c265461af78f56 - Author: Koichi Sasada - Date: 2019-05-27 16:19:30 +0900 - - check the object is in tomb_heap. - -commit 35146c436820f35733982bac870e409c57888575 - Author: Koichi Sasada - Date: 2019-05-27 16:12:30 +0900 - - add a space between type and others - -commit b3a6469e46b3c9c10176b066e5076ddcc5f96939 - Author: Koichi Sasada - Date: 2019-05-27 16:09:47 +0900 - - add a line break for each error message - -commit 6c1a07555c7fb37a5cd36f08489d33d779b4d41b - Author: Koichi Sasada - Date: 2019-05-27 14:50:26 +0900 - - fix GC.verify_internal_consistency. - - Fix debug output to dump more useful information on GC.compact - debugging. - - check_rvalue_consistency_force() now accepts `terminate` flag - to terminate a program with rb_bug() or only print error message. - GC.verify_internal_consistency use this flag (== FALSE) to dump - all of debug output. - -commit 61da57c76a9e32a4154dac8f24f9b860d65b320d - Author: Koichi Sasada - Date: 2019-05-27 14:37:48 +0900 - - is_pointer_to_heap() checks also tomb or not. - - is_pointer_to_heap(obj) checks this obj belong to a heap page. - However, this function returns TRUE even if the page is tomb page. - This is re-commit of [712c027524]. - - heap_page_add_freeobj() should not use is_pointer_to_heap(), but - should check more explicitly. - -commit ea6e284d86ccbc2d1ed5637acd0940a12b58b672 - Author: Nobuyoshi Nakada - Date: 2019-05-27 12:22:11 +0900 - - parse.y: removed "parser_" prefix from tokadd_utf8 - -commit af17e111b3f7cb3c5ad7dc194399b44d0e5004d0 - Author: Nobuyoshi Nakada - Date: 2019-05-27 11:57:48 +0900 - - Added #inspect and #pretty_inspect to Ripper::Lexer::Elem - -commit 43730256e800dd8e0c5cc482e9861868590ae037 - Author: Yusuke Endoh - Date: 2019-05-27 12:58:08 +0900 - - open-uri: Regenerate server certificates for tests - - OpenSSL 1.1.1 requires 2048 bits or more. This change will fix: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian/ruby-master/log/20190527T003004Z.fail.html.gz#test%2Fopen-uri - -commit 4c277364a5e70983dcafc9b4d5d990414d61d264 - Author: Nobuyoshi Nakada - Date: 2019-05-27 11:47:09 +0900 - - CSI allows empty digit which equals 0 - -commit 0aa9b003de353e690f31ba59ca0a2db1df51b8bf - Author: Nobuyoshi Nakada - Date: 2019-05-27 11:05:51 +0900 - - context.rb: hide wrapping lines - - * lib/irb/context.rb (IRB::Context#evaluate): separate the code - from wrapping lines to propagate the given exception, not to show - the wrapping lines when SyntaxError. - -commit 9840f52c77a928479919e539d2e47ce36b5ede49 - Author: aycabta - Date: 2019-05-27 10:18:09 +0900 - - Use IRB::InputMethod#eof? to quit - -commit 1d301acbe8e9b0df7872d6719d6646ade25630d6 - Author: aycabta - Date: 2019-05-27 10:09:21 +0900 - - Fix rendering bug of ^D - -commit 9c136f3dea0c6052fefb377bf2c445daec1ca0b6 - Author: aycabta - Date: 2019-05-27 08:39:39 +0900 - - Move to next of last line by ^D - -commit 4e2c7783e364f37a748fe0d3a3cd9f96e58287c0 - Author: aycabta - Date: 2019-05-27 08:13:48 +0900 - - Check blank history - -commit 2805c55aa39bf6127e1e684deb0d5a0291cb6479 - Author: aycabta - Date: 2019-05-27 07:35:35 +0900 - - Move to next of last line by ^C - -commit c49796c9301845e17bd2d5b254ce75d40c898d56 - Author: aycabta - Date: 2019-05-27 07:00:06 +0900 - - Reline should move to next line after finished in Readline mode - -commit 29c16b30ce7655bf34ac59b1327ab13f83dc7970 - Author: Sutou Kouhei - Date: 2019-05-27 06:23:47 +0900 - - Add support for history with Reline backend - -commit 2c91c5b329796a0c7f3cda0296d7c6d6cd6aa8c6 - Author: aycabta - Date: 2019-05-27 06:04:42 +0900 - - Move to the other line when press <- at head or -> at tail - -commit 716ba4a12732d94a50fb31bcaca4ce07bc4b6870 - Author: aycabta - Date: 2019-05-27 05:45:08 +0900 - - Implement J to join lines in vi command mode - -commit 64dc21830aa60dc757df48c715a73f704eed43e0 - Author: aycabta - Date: 2019-05-27 05:01:04 +0900 - - Remove \1 and \2 that escape CSI before render - -commit c6b7cad5c903fa957c274d233c15fdcb3e4a9623 - Author: Takashi Kokubun - Date: 2019-05-27 04:19:59 +0900 - - .azure-pipelines.yml: Add timeout to install dependencies - - to avoid cancelling overall build pipeline when stucking there. - -commit 64ee8900c89444692c6a51f0153869cb634bb086 - Author: Takashi Kokubun - Date: 2019-05-27 03:32:23 +0900 - - Highlight global variable on IRB - -commit 7597f7ecb18ae537002391f9feb7f0e689d3b87b - Author: Takashi Kokubun - Date: 2019-05-27 03:24:52 +0900 - - Simplify lexer state matching in #dispatch_seq - - for improving readability of the condition. It may be slightly faster, or may not. - -commit 5a6c77bbe8acd5929421c359bca57ef559a4f0fe - Author: git - Date: 2019-05-27 03:10:15 +0900 - - * expand tabs. - -commit 39eadca76b48fc7841da688f6745e40897ec37ff - Author: Jeremy Evans - Date: 2019-04-06 16:02:11 +0900 - - Add FrozenError#receiver - - Similar to NameError#receiver, this returns the object on which - the modification was attempted. This is useful as it can pinpoint - exactly what is frozen. In many cases when a FrozenError is - raised, you cannot determine from the context which object is - frozen that you attempted to modify. - - Users of the current rb_error_frozen C function will have to switch - to using rb_error_frozen_object or the new rb_frozen_error_raise - in order to set the receiver of the FrozenError. - - To allow the receiver to be set from Ruby, support an optional - second argument to FrozenError#initialize. - - Implements [Feature #15751] - -commit 897901283c79e5f5f33656abdd453dc272268748 - Author: Takashi Kokubun - Date: 2019-05-27 02:29:20 +0900 - - Refactor IRB color dispatch - - The reason why we were checking lexer state in addition to token was - that we do not want to colorize local variable, method call, etc., while - they share the :on_ident token with a name of method definition which - should be colored as blue. - - It means that we're concerned about the lexer state only for :on_ident. - Thus we can skip checking lexer state for non-:on_ident tokens. This - refactoring is based on that idea. - - Also, now we manage Ripper's lexer state as Integer (use `|` if you - need to check multiple states). It should be faster than using Array of - Integer because #any? block call is not needed. - -commit e73a68ebc322516a42821f502d6d5de5bfa1eb47 - Author: aycabta - Date: 2019-05-27 02:59:21 +0900 - - Support op, cvar, iver, gvar and kw that follow on symbeg in IRB - -commit 122679136820afc663b854567afd16e49eae5a96 - Author: aycabta - Date: 2019-05-27 02:55:37 +0900 - - Support :@@cvar and : on colorize - -commit e50aa359de2a419c0a04eaee84a095f602e1ccb1 - Author: Takashi Kokubun - Date: 2019-05-27 02:22:57 +0900 - - Make the imaginary color on IRB close to pry - - and sorted the token names alphabetically. - -commit 60cc03ffe7a4b67300b0b547dfa4ddaaa894ece6 - Author: aycabta - Date: 2019-05-27 02:13:27 +0900 - - Fix indexes in comments of vi_insert.rb - - Previous fix was 2993b361333147f6dfb86a153971c22329ffbaf4. - -commit 0f35c79ad6bcf409851049639d7200ce7f9787fb - Author: aycabta - Date: 2019-05-27 01:59:17 +0900 - - Fix number literal regexp of IRB completion - -commit e39c950c2bcb8f77f12f841a7acc13b12402ee5a - Author: aycabta - Date: 2019-05-27 01:24:03 +0900 - - Use correctly RI output in IRB completion - -commit 2a7821b28964ba9d71d8714554502a02fabe3781 - Author: git - Date: 2019-05-27 00:45:50 +0900 - - * 2019-05-27 - -commit a43c637660cd3c893401e899014d721d2fa2a5b4 - Author: Nobuyoshi Nakada - Date: 2019-05-27 00:07:05 +0900 - - parse.y: broke the terminator condition down - - * parse.y (here_document): broke the terminator condition down - into each piece, the positional condition, resetting the - dedented here-document indentation, and matching identifier. - suppress a false warning by icc. - -commit 4f2a7b800110346292890e3bed41b37f3f58ab0b - Author: Nobuyoshi Nakada - Date: 2019-05-26 23:44:57 +0900 - - Colorize imaginary and rational literals - -commit 23270f6fee88668a5099fa16eb48739fba2d9dd6 - Author: Takashi Kokubun - Date: 2019-05-26 22:29:30 +0900 - - azure-pipelines.yml: Do not notify vs2017 failure - - It has not been stable recently. Let's stop notifying them for now. - -commit 2ce6365f9ccd93e8129252429391118f794f5e0b - Author: Nobuyoshi Nakada - Date: 2019-05-26 18:45:59 +0900 - - parse.y: adjust error indicator - - * parse.y (parser_yylex): adjust the error indicator of unexpected - fraction part. - - before: - ~~~ - 1.2.3 - ^~~ - ~~~ - - after: - ~~~ - 1.2.3 - ^~ - ~~~ - -commit 58308899151ee3d49f8d9ef5c4e8d108d8822525 - Author: Nobuyoshi Nakada - Date: 2019-05-26 18:24:06 +0900 - - test/ruby/test_notimp.rb: Use EnvUtil.timeout for timeout scale factor - -commit 2df2cdcff0b0358ebc98a43181b5271632563a68 - Author: Yusuke Endoh - Date: 2019-05-26 17:25:16 +0900 - - test/ruby/test_process.rb: Use EnvUtil.timeout for timeout scale factor - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-master/log/20190526T052508Z.fail.html.gz - -commit 4668a3a9da9f02b073631013e71722868ceafa53 - Author: Yusuke Endoh - Date: 2019-05-26 17:19:46 +0900 - - test/lib/envutil.rb (EnvUtil.timeout): added. - - It is a wrapper for Timeout.timeout with the scale factor applied. - -commit 02b39daef834890981689f1f697c7c25cad55dd6 - Author: Nobuyoshi Nakada - Date: 2019-05-26 11:33:40 +0900 - - Fix scanner event at invalid syntax - - * parse.y (parser_yyerror, parser_compile_error): revert - r67224 (e5d10cda07b23682e5e4e64d1324e4d3247d4785) "Flush erred - token". - -commit f20af9543f278ab602d001dace850dcf4411cfa6 - Author: Yusuke Endoh - Date: 2019-05-26 15:23:21 +0900 - - test/rubygems/test_gem_stream_ui.rb (test_ask): extend the timeout - - for Solaris. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190525T211908Z.fail.html.gz - -commit aaf6c678d272d4487179b7ae0b03990ac6b2aff5 - Author: Takashi Kokubun - Date: 2019-05-26 14:32:28 +0900 - - Handle keyword symbol in IRB::Color::SymbolState - -commit 52b09fcee1b170ad3be7d26b885b8a509c7ba006 - Author: Takashi Kokubun - Date: 2019-05-26 14:29:16 +0900 - - Deal with more syntax highlight edge cases - - Please refer to the tests again. - -commit 8aba3b7a04738c8cebcf3d4ecacd57199d976ae2 - Author: Takashi Kokubun - Date: 2019-05-26 13:39:11 +0900 - - Fix more unintended syntax highlights - - See tests for what kind of things are fixed. - -commit 13f58eccdab374ab14d33a6882c52e048cb52e3c - Author: Takashi Kokubun - Date: 2019-05-26 12:47:29 +0900 - - Always color Symbol as Yellow on IRB::Color - - Symbol color was made blue as a workaround because it was hard to - distinguish `foo`s in `:foo` and `def foo; end` (both are :on_ident). - But I wanted to make it yellow like pry. - - `:Struct` had the same problem in :on_const. Because the :on_const was - also blue (but underlined and bold), it was not a big issue. - - While they're not so problematic since we got a workaround, we also had - a more serious issue for highlighting a symbol like `:"a#{b}c"`. - The first half was considered as Symbol and the last half was considered - as String, because the colorizer did not have a state like a parser. - - To approach the last issue, I introduced `IRB::Color::SymbolState` which - is a thin state manager knowing only "the token is Symbol or not". Having - this module magically solves the first two problems as well. So now we - can highlight Symbol as yellow in the perfect manner. - -commit a516834b47de810b53241c66f677fafd4485bebd - Author: Yusuke Endoh - Date: 2019-05-26 09:48:38 +0900 - - test/ruby/test_rubyoptions.rb (test_script_from_stdin): scale timeout - - for Solaris. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10s/ruby-master/log/20190525T131909Z.fail.html.gz - -commit 208ed56e575b83c47d5cc2e48efd6807bb661bdd - Author: Takashi Kokubun - Date: 2019-05-26 05:54:03 +0900 - - Colorize empty embexpr more on IRB::Color - -commit ec759011201ce16db7079dbc26ae9c085c2608ba - Author: aycabta - Date: 2019-05-26 01:32:12 +0900 - - Fix completion menu state calculation - -commit 2993b361333147f6dfb86a153971c22329ffbaf4 - Author: Nobuyoshi Nakada - Date: 2019-05-26 00:48:26 +0900 - - Fix indexes in comments - -commit 98be203704e98c53b2d3b939b10a0d765c76d53d - Author: Takashi Kokubun - Date: 2019-05-26 00:01:51 +0900 - - Support some unhandled syntax highlight - - Heredoc, %i, :Foo, { 'a': ... }, ... - - :'a' is still half-broken. - -commit a4d44b08ec5139f91617f0fc5786494c5076aaa1 - Author: git - Date: 2019-05-26 00:00:56 +0900 - - * 2019-05-26 - -commit d9c41f2dec7af7f44b4545f4111498c8af3569fe - Author: aycabta - Date: 2019-05-26 00:00:03 +0900 - - Use Reline.completer_word_break_characters to complete - -commit ada64aa9e7f1e087b9fd536d9bc512de401f42a0 - Author: Takashi Kokubun - Date: 2019-05-25 23:48:58 +0900 - - Clear IRB::Color escape sequence before newline - - because otherwise prompt and other things could be polluted. - -commit 7c507345a73afe3f599e407e851b9c0d708adeb0 - Author: Takashi Kokubun - Date: 2019-05-25 23:21:37 +0900 - - Build trunk branch too to trigger AppVeyor on PR - -commit be851692cec43470aceed23ff40c198deb4d4680 - Author: Takashi Kokubun - Date: 2019-05-25 23:21:45 +0900 - - Build trunk branch too to trigger Travis on PR - -commit e2db9f4cc35dacdca1c0d1f1ae79772dae093c34 - Author: Takashi Kokubun - Date: 2019-05-25 22:52:10 +0900 - - Add and use Reline::Unicode.escape_for_print - -commit e691b4da5d1d70216be3e8853d18bcb6a62a617c - Author: Takashi Kokubun - Date: 2019-05-25 22:31:13 +0900 - - Respect --nocolorize on REPL source highlight - -commit 65ce14e7b5f66a92f452136290357eb3df147e5b - Author: Nobuyoshi Nakada - Date: 2019-05-25 17:20:31 +0900 - - Added --with-rdoc option - - New option to direct formats of RDoc to install. - -commit 4fae3c3fb0847ba8eccb61b3c0cc0ae874c17cf0 - Author: Nobuyoshi Nakada - Date: 2019-05-25 16:56:26 +0900 - - Show doc list to install - - Show document format list to install, not only enabled or disable. - -commit 8fd3b9fc5f0f0ef031c54982236b6da327b81458 - Author: Nobuyoshi Nakada - Date: 2019-05-25 16:53:20 +0900 - - Force update all RDoc at install - - RDoc needs to parse all files at once for the cross-reference. - -commit 061c781a09de68c7e34e45732081aac337c4facc - Author: Takashi Kokubun - Date: 2019-05-25 16:38:18 +0900 - - Drop method obsoleted by b83119be9e9a8611063142541993e4823a025622 - - We might need to do the same thing in IRB::Color now, but I'm not doing - that as I assume ANSI escape sequence does not come from a user input - though Reline. - -commit b83119be9e9a8611063142541993e4823a025622 - Author: Takashi Kokubun - Date: 2019-05-25 13:21:22 +0900 - - Incremental syntax highlight for IRB source lines - - Closes: https://github.com/ruby/ruby/pull/2202 - -commit 3c6e1a8cf911d312edeb9dfcc9153be68867ca4f - Author: Hiroshi SHIBATA - Date: 2019-05-25 11:28:07 +0900 - - Avoid to show warning message with unused variable. - -commit 7686e33ee453d43210afcf90fef8fc613dede31c - Author: aycabta - Date: 2019-05-25 10:36:30 +0900 - - JSON like label ends by differs from the start - - pp Ripper.lex('{ "a": 3 }') - => - [[[1, 0], :on_lbrace, "{", EXPR_BEG|EXPR_LABEL], - [[1, 1], :on_sp, " ", EXPR_BEG|EXPR_LABEL], - [[1, 2], :on_tstring_beg, "\"", EXPR_BEG|EXPR_LABEL], - [[1, 3], :on_tstring_content, "a", EXPR_BEG|EXPR_LABEL], - [[1, 4], :on_label_end, "\":", EXPR_BEG|EXPR_LABEL], - [[1, 6], :on_sp, " ", EXPR_BEG|EXPR_LABEL], - [[1, 7], :on_int, "3", EXPR_END], - [[1, 8], :on_sp, " ", EXPR_END], - [[1, 9], :on_rbrace, "}", EXPR_END]] - -commit 809ac9f2eaa0b9cf818f571f6febcee6785cc8e2 - Author: git - Date: 2019-05-25 09:51:27 +0900 - - * expand tabs. - -commit 1ef39d8d099f145222b9352423af16a2bab6e05b - Author: Jeremy Evans - Date: 2019-05-25 08:34:34 +0900 - - Fix process not waking up on signals on OpenBSD - - When using UBF_TIMER_PTHREAD (the UBF handler on OpenBSD), the - timer_pthread_fn function will not signal the main thread with - SIGVTALRM in cases where timer_pthread is armed before - consume_communication_pipe is called. This is because - consume_communication_pipe will unarm the timer. - - Fix this by checking the return value of consume_communication_pipe. - If it returns TRUE and the timer_pthread is disarmed, then signal - the main thread with SIGVTALRM. - - On OpenBSD, this fixes TestThread#test_thread_timer_and_interrupt, and - fixes hangs in TestProcess#test_execopts_redirect_open_fifo_interrupt_raise - and TestProcess#test_execopts_redirect_open_fifo_interrupt_print. - It also fixes the use of Ctrl+C/SIGINT in irb on OpenBSD. It does not - cause any test failures on Linux when UBF_TIMER_PTHREAD is forced as - the UBF handler. - - Fixes [Bug #15798] - -commit 19430b776c3ebae1adfdc5cbe6cdf69a92e37253 - Author: aycabta - Date: 2019-05-25 08:24:41 +0900 - - Fix wrong variable name - -commit 822468307b1a54eccd2711300008a3974c15141e - Author: aycabta - Date: 2019-05-25 08:08:54 +0900 - - Add round-robin variable - -commit 559dca509d2a98584b09c7d9a6d74749ce793ad7 - Author: aycabta - Date: 2019-04-28 07:47:33 +0900 - - Show documents when completion - -commit 260235ce871c3e7718af8d612f1a8ed400b56070 - Author: aycabta - Date: 2019-04-28 06:37:39 +0900 - - Use Reline as Reidline multiline editor in IRB - -commit ff43b2262702e828e2008ba65e68b331d263e3d0 - Author: aycabta - Date: 2019-05-25 02:13:14 +0900 - - Enter key always means evaluate in Reline#readmultiline - -commit 637ee7ee3853387b4f34aa350471692f1778693d - Author: aycabta - Date: 2019-05-25 01:13:02 +0900 - - Fix C-v C-j - -commit 27bab6a569389e743f09dd52c58d8d127eaa7772 - Author: aycabta - Date: 2019-05-25 00:44:09 +0900 - - Revert "Change Reline's version with "Reline 0.0.0"" - - This reverts commit 481ccf73d88797914f700e6e27711bf1ce997eb0. - -commit 481ccf73d88797914f700e6e27711bf1ce997eb0 - Author: aycabta - Date: 2019-05-25 00:40:14 +0900 - - Change Reline's version with "Reline 0.0.0" - -commit 4b012c23b282f48161718392cde8dc637f734623 - Author: aycabta - Date: 2019-05-25 00:38:57 +0900 - - Check block in #readmultiline - -commit b2150548001c412ad424251904d6ece1a80e55f4 - Author: git - Date: 2019-05-25 00:25:42 +0900 - - * 2019-05-25 - -commit eb4e774711b17b8a25a7b16c4f0b6044da3dc261 - Author: aycabta - Date: 2019-05-24 23:38:40 +0900 - - Support Meta key in Reline - -commit 2d34087a38ac680c5576a56fbf4104c3561b0204 - Author: Benoit Daloze - Date: 2019-05-24 21:48:10 +0900 - - Add notes for the Process#clock_getres spec - -commit 4541d2effe1f32e74d27602b44aff12cbf6937aa - Author: Benoit Daloze - Date: 2019-05-24 21:29:47 +0900 - - Only exclude the failing clocks for Process.clock_getres specs on AIX - - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/aix71_ppc/ruby-trunk/log/20190522T103301Z.fail.html.gz - -commit 706c816ad270d981c37894b78ac49cdf1d7cf350 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-24 19:01:39 +0900 - - Escape dots in regexp - -commit a4da223c9a37e2384086f4306571ff0a753fa844 - Author: git - Date: 2019-05-24 19:00:50 +0900 - - * expand tabs. - -commit 6ae9d5c85f3a2a7002b8fc0525e3aca645ec1709 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-24 18:59:58 +0900 - - Revert "check it in eden or tomb." - - This reverts commit 712c027524e3a03500b3098d950fc2f0608ce897. - -commit c06f9e1d24e0e164506c6b5946a02814319485cc - Author: Martin Dürst - Date: 2019-05-24 18:22:36 +0900 - - switch UNICODE_BETA to NO (one more try, first try didn't work) - - Unicode version 12.1.0 was officially released on May 7th, 2019. - There were no changes at all from the "real" beta - published shortly after the new era name "Reiwa" was announced. - So we can switch UNICODE_BETA back to NO. - - common.mk: switch UNICODE_BETA back to NO - tool/downloader.rb: add additional conditions to avoid an error - when moving from beta to final - -commit b0a4d81fc3c9195f7462a096a50e857669c47918 - Author: Koichi Sasada - Date: 2019-05-24 17:52:58 +0900 - - check RVALUE on verifier. - - GC.verify_internal_consistency() checks health of each RVALUE with - check_rvalue_consistency(). However, this function is enabled - only on debug environment (RGENGC_CHECK_MODE>1). So introduce - new function check_rvalue_consistency_force() and use it - in GC.verify_internal_consistency. - -commit 712c027524e3a03500b3098d950fc2f0608ce897 - Author: Koichi Sasada - Date: 2019-05-24 17:35:22 +0900 - - check it in eden or tomb. - - is_pointer_to_heap() checks if it is in valid pointer to the - RVALUE in any heap_page_body. However, it returns true if it - points tomb pages. This patch check it points to eden pages. - -commit 10927b59256aeb196d164e8a8e75180a72768e97 - Author: Koichi Sasada - Date: 2019-05-24 17:06:43 +0900 - - add separation char on rb_obj_info(imemo obj) - -commit 2893550452f6f3cadb17c670da185813d7d0a835 - Author: Nobuyoshi Nakada - Date: 2019-05-24 16:10:59 +0900 - - Mixed encoding error can continue to parse - -commit 45ad375acccca2bb0852613b1e809a7af556f5e6 - Author: Nobuyoshi Nakada - Date: 2019-05-24 16:10:10 +0900 - - [DOC] Use Rational literals than to_r in examples - -commit 1a4080cb0ade6c700ce763d4290e5b56635d1bc8 - Author: Nobuyoshi Nakada - Date: 2019-05-24 15:07:38 +0900 - - Hoisted out ndigits_denominator - - * time.c (ndigits_denominator): calculate the denominator for - digits. - -commit 54d5b599e850c08f92581645c56e4f5ccf20eb45 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-24 14:31:53 +0900 - - Fix typos [ci skip] - -commit 25415780964f2a104523318f3ceef389bfae6e94 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-24 00:47:03 +0900 - - Add leaked-globals to .travis.yml - -commit 491d2b8063d1f4e1c9e8fe0a57ff66fbfdf7d622 - Author: Nobuyoshi Nakada - Date: 2019-05-24 14:25:46 +0900 - - Removed symlinks by in-place build [Bug #15870] - -commit 14778125b12b80f1ebb0474f0360204f6b3abae5 - Author: Nobuyoshi Nakada - Date: 2019-05-24 14:24:38 +0900 - - Removed and ignore symlinks by in-place build [Bug #15870] - -commit e713c2bde8117f3aaf39d827d3fc504cd5866976 - Author: Martin Dürst - Date: 2019-05-12 16:21:24 +0900 - - switch UNICODE_BETA to NO - - Unicode version 12.1.0 was officially released on May 7th, 2019. - There were no changes at all from the "real" beta published shortly - after the new era name "Reiwa" was announced. So we can switch - UNICODE_BETA back to NO. - - common.mk: switch UNICODE_BETA back to NO - tool/downloader.rb: add additional conditions to avoid an error - when moving from beta to final - -commit 35caedc828667363413c7fbe4a4cc60758c426a2 - Author: Nobuyoshi Nakada - Date: 2019-05-24 14:11:00 +0900 - - --autostash is since Git 2.6 [Bug #15871] - -commit dfc21a0467d39af00666aec5098530529924cf48 - Author: Nobuyoshi Nakada - Date: 2019-05-24 12:23:26 +0900 - - Ignore generated files by in-place build [Bug #15870] - -commit 7f2f56b2f51269f42f822ecf346375b040267595 - Author: Nobuyoshi Nakada - Date: 2019-05-24 12:22:17 +0900 - - Define GITPULLOPTION to rebase [Bug #15871] - -commit 50e993d4e347bd3e821c4996cc745fa0aa74bd64 - Author: Yusuke Endoh - Date: 2019-05-24 12:17:05 +0900 - - Skip the Process.clock_getres spec on AIX - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/aix71_ppc/ruby-trunk/log/20190522T103301Z.fail.html.gz - -commit 498113d5d39a4227c2b9a9c11bea895fe316e6b9 - Author: Yusuke Endoh - Date: 2019-05-24 11:20:12 +0900 - - test/ruby/test_gc.rb (test_gc_stress_at_startup): extend time timeout - - It fails on some CI environments. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian8/ruby-trunk/log/20190524T003006Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11s/ruby-trunk/log/20190523T002505Z.fail.html.gz - -commit 1ee1e8fccdec8de86799db02d6f62ba3d064ba1e - Author: Takashi Kokubun - Date: 2019-05-24 01:03:23 +0900 - - Test GC.compact with MJIT again - -commit dde8ceaf709abca1e3af63739de65d2809691878 - Author: git - Date: 2019-05-24 00:42:54 +0900 - - * 2019-05-24 - -commit 187ef00a41ca28a26ffa0a9399c48335578590bb - Author: Takashi Kokubun - Date: 2019-05-24 00:41:18 +0900 - - wercker.yml: Commit MJIT debug logs to another repository - - because too-large Wercker output is truncated. - - ruby/mjit-debug is a private repository for now, because the person - fixing it is likely to be me or another committer. - -commit 4fe908c1643c3f355edd787bb651aefb53b996c0 - Author: Takashi Kokubun - Date: 2019-05-23 23:53:41 +0900 - - gc.c: Try pausing MJIT worker during GC.verify_compaction_references - - for debugging - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/2048247 - -commit c04ef141d2edd71f90f0707889b4adfd94e5be43 - Author: Yusuke Endoh - Date: 2019-05-23 23:34:18 +0900 - - enum.c (enum_tally): better example in rdoc - -commit e72769ef81a933959f4a85ee09eec66bedcbf022 - Author: Nobuyoshi Nakada - Date: 2019-05-23 23:24:22 +0900 - - Enumerable#filter_map in NEWS - -commit ccb165292962f42edbfc72cbf6b49a9ea8a319c9 - Author: Nobuyoshi Nakada - Date: 2019-05-23 22:47:55 +0900 - - New Time methods in NEWS - -commit 0b4d51b055ad2806719b1f4a3eca5c1bbce64631 - Author: git - Date: 2019-05-23 22:39:54 +0900 - - * expand tabs. - -commit f5415a95ce1d393a3fd1d7f657ba85d85171356a - Author: manga_osyo - Date: 2019-03-16 14:42:24 +0900 - - Add `Time#ceil`. - - Closes: https://github.com/ruby/ruby/pull/2133 - -commit fe3ff5afb07e171fd950623c69abfbabbb2762a3 - Author: Nobuyoshi Nakada - Date: 2019-05-23 17:27:24 +0900 - - Suppress paranoid warnings for external/3rd-party libraries - - [Feature #15665] - -commit dc95b57a68da6999ce6a1542b3ad81c51429cc99 - Author: Koichi Sasada - Date: 2019-05-23 17:30:53 +0900 - - add verifier before compact - -commit 878a06efecbd2d71bf1a852a6367fbcd3e8edf93 - Author: Urabe, Shyouhei - Date: 2019-05-23 17:24:15 +0900 - - add comments [ci skip] - - Also requested by Ko1. - -commit 763989c6c5a553fa072208e53707813fbde916d0 - Author: Urabe, Shyouhei - Date: 2019-05-23 17:02:07 +0900 - - prefix ASAN related inline functions asan_ - - requested by Ko1. - -commit 8fce83339b6a862001c4fbad6bcd72dc3efee136 - Author: Urabe, Shyouhei - Date: 2019-05-23 16:55:20 +0900 - - disable _FORTIFY_SOURCE - - Sanitizers and fortifications do not interface, and there is currently - no plan for them to work together. - - See also https://github.com/google/sanitizers/issues/247 - -commit 6be0ab73c3f2cc95d76ca21203adf6a73c8705e7 - Author: Koichi Sasada - Date: 2019-05-23 16:52:14 +0900 - - gc_pin() doesn't check is_markable_object(). - - Caller of gc_pin() should check it is a mark-able object. - So gc_pin() doesn't need to check it. With this fix, - we can refactoring around it. - -commit 65637dae30bda83b72f185bbcf01d7bad80926c7 - Author: Takashi Kokubun - Date: 2019-05-23 16:07:16 +0900 - - Test GC.compact on MJIT again - -commit c5cbabf8a8aa42b7dcf943c64274489286174108 - Author: NAKAMURA Usaku - Date: 2019-05-23 15:33:40 +0900 - - Use colorized IRB on Windows without checking `TERM` - -commit 0acbdd1ed0d2302743525a5188cc5a0d6251680c - Author: Alfonso Jiménez - Date: 2018-11-20 19:51:08 +0900 - - Adding Enumerable#filter_map - - [Feature #15323] - Closes: https://github.com/ruby/ruby/pull/2017 - -commit 1ccc2eeba08c370d84474357771f0bd7c5fe7f16 - Author: Nobuyoshi Nakada - Date: 2019-05-19 16:24:33 +0900 - - Pretend to update all Unicode files - -commit c05eaa93258ddc01e685b6cc3a0da82998a2af48 - Author: Jeremy Evans - Date: 2019-05-15 14:04:46 +0900 - - Fix mixed encoding in heredoc - - Heredocs are parsed line-by-line, so we need to keep track of the - temporary encoding of the string. Previously, a heredoc would - only detect mixed encoding errors if they were on the same line, - this changes things so they will be caught on different lines. - - Fixes [Bug #15839] - -commit f91b1ab33d397fdcdf452d563d7f59469a078d88 - Author: Jeremy Evans - Date: 2019-05-16 13:08:49 +0900 - - Skip assertion in readline test if Readline version is 4.3 - - Previously, the entire method was not run for Readline 4.3, probably - because it was known to fail. Commit - c754e979d3eeca51f1b13778f19f347df3da656e removed the check for - Readline 4.3. Other than this one assertion, which also doesn't - work when using Reline, the method runs correctly when using - Readline 4.3. - - Fixes [Bug #15853]. - -commit 4814f173615f8f9f2f3429fe788089479490fe10 - Author: Koichi Sasada - Date: 2019-05-23 13:21:40 +0900 - - skip zombies. - - rb_gc() no longer invokes finalizers, so there are T_ZOMBE objects. - -commit 02973d3ba8020f494ad2d627284f9bc45db48f9c - Author: Koichi Sasada - Date: 2019-05-23 11:42:15 +0900 - - pin `maybe` pointers. - - Objects pointed by "maybe" pointers because of conservative marking - should be pinned down. - -commit 136ae55892ae120bb94e4ff2d025c745fdaa1091 - Author: Koichi Sasada - Date: 2019-05-23 11:21:16 +0900 - - Do not kick finalizers on rb_gc(). - - rb_gc() kicks gc_finalize_deferred(), which invokes finalizers. - This means that any Ruby program can be run this point and - it may be thread switching points and so on. - - However, it is difficult to think it invokes any Ruby programs. - For example, `GC.compact` use `rb_gc()` to implement it, however, - any Ruby program must not be run on this timing. - - For this reason (it is difficult to image it run any Ruby program), - I removed `gc_finalize_deferred()` line in rb_gc(). - - This patch solves GC.compact issue. - [Bug #15809] and re-enable GC.compact test. - -commit 0eff21af8d03a9d2b881b9cce963262da3d952dc - Author: Koichi Sasada - Date: 2019-05-23 11:19:23 +0900 - - update Array's length correctly. - - ARRAY_ASET() does not change the length of array, so - use rb_ary_push() instead of ARRAY_ASET(). It prevents - updating reference on GC.compact. - -commit bb29ed6e336d26f25722f356e83a027394008443 - Author: aycabta - Date: 2019-05-23 08:33:20 +0900 - - C-v C-j means an newline insertion - -commit da3fabc976fb88c77e8b3446f2f0bc005e64056f - Author: aycabta - Date: 2019-05-23 08:23:22 +0900 - - Change behavior to confirm multiline termination - - Always checks termination if you press Enter at last line. - -commit c210c68d393b76149f02dc1f8b610269a53d94bc - Author: Takashi Kokubun - Date: 2019-05-23 03:14:54 +0900 - - Revert "Revert CI deduplication on Wercker / Azure for debugging" - - This reverts commit 1ebe9a2f82fef5190454e68d430004282f5da172. - - because it did not help. - -commit 1ebe9a2f82fef5190454e68d430004282f5da172 - Author: Takashi Kokubun - Date: 2019-05-23 01:58:57 +0900 - - Revert CI deduplication on Wercker / Azure for debugging - - CI seems to have a weird behavior now. Debugging. - - Revert "azure-pipelines.yml: Fix typo" - - This reverts commit f69d28fbca1eec8b9722cea1f989ee9554e8dad5. - - Revert "azure-pipelines.yml: Use simpler trigger syntax" - - This reverts commit 709756d89747bd36664593eda4156a7bf5ad7631. - - Revert "azure-pipelines.yml: Do not run CI on trunk" - - This reverts commit bec877b46fd4d0f621a75591b519a7e266eaa89b. - - Revert "appveyor.yml: Do not doubly run CI on trunk" - - This reverts commit d9b338a53f520b2dbb05555f18b8de8072300f40. - -commit 00f7e424516a6c5ea58ddb3cc821d3cabe9c496c - Author: Yusuke Endoh - Date: 2019-05-23 01:46:21 +0900 - - spec/ruby/core/hash/constructor_spec.rb: add "ruby_version_is" guard - - follow up for d3f1c615c5 - -commit a093c98ddc92d8b0a341233630aea8f778188c7e - Author: Nobuyoshi Nakada - Date: 2019-05-23 01:39:04 +0900 - - Fallback RUBY_FULL_REVISION if not defined - -commit f69d28fbca1eec8b9722cea1f989ee9554e8dad5 - Author: Takashi Kokubun - Date: 2019-05-23 01:18:30 +0900 - - azure-pipelines.yml: Fix typo - -commit 709756d89747bd36664593eda4156a7bf5ad7631 - Author: Takashi Kokubun - Date: 2019-05-23 01:17:26 +0900 - - azure-pipelines.yml: Use simpler trigger syntax - -commit bec877b46fd4d0f621a75591b519a7e266eaa89b - Author: Takashi Kokubun - Date: 2019-05-23 01:13:13 +0900 - - azure-pipelines.yml: Do not run CI on trunk - -commit b80adde359f82085db9065a9c06af5ee8f937c34 - Author: Takashi Kokubun - Date: 2019-05-23 01:07:16 +0900 - - wercker.yml: Notify master branch instead of trunk - -commit 9d39eb6b40966deeeaa23c28f0be640c56545644 - Author: Yusuke Endoh - Date: 2019-05-23 00:45:30 +0900 - - range.c (inspect_range): omit beginless "nil" - - except the special case `(nil..nil)`. - - ``` - (1..).inspect #=> "1.." - (..5).inspect #=> "..5" - (nil..nil).inspect #=> "nil..nil" - ``` - - [Bug #15745] - -commit d9b338a53f520b2dbb05555f18b8de8072300f40 - Author: Takashi Kokubun - Date: 2019-05-23 00:40:09 +0900 - - appveyor.yml: Do not doubly run CI on trunk - -commit 277e68825a8e4d0e6503a32e41f8b1b6c078b567 - Author: Takashi Kokubun - Date: 2019-05-23 00:33:44 +0900 - - .travis.yml: Test master branch instead of trunk - -commit d3f1c615c5b81319e422e9c92e1cb8ba82209fba - Author: Yusuke Endoh - Date: 2019-05-23 00:15:55 +0900 - - hash.c (rb_hash_s_create): Reject `Hash[[nil]]` - - The behavior of `Hash[[nil]] #=> {}` was a bug until 1.9.3, but had been - remained with a warning because some programs depended upon it. - Now, six years passed. We can remove the compatibility behavior. - [Bug #7300] - -commit 4d62296948c36615e73b99d592253256d0ea0d4a - Author: git - Date: 2019-05-23 00:15:54 +0900 - - * 2019-05-23 - -commit a205e24747497391390ef7c004293a8a7934dd96 - Author: Nobuyoshi Nakada - Date: 2019-05-22 23:18:37 +0900 - - Make RUBY_REVISION full length - -commit d819d97cf02fd0a5b5b1f6ee69c9fdb83276e6c2 - Author: Nobuyoshi Nakada - Date: 2019-05-22 23:18:09 +0900 - - Default to the current branch - - * tool/make-snapshot: default to the current branch if no branch - but srcdir is given. - -commit 8fb77acac70bab6924c063020b6fe3e93fece242 - Author: Nobuyoshi Nakada - Date: 2019-05-22 23:50:07 +0900 - - Fix revision name - - * tool/make-snapshot (package): dump to stringize GIT revisions - properly. - -commit 24684a81d2ed3ae32ad67659a8b18acd052727b5 - Author: Nobuyoshi Nakada - Date: 2019-05-22 22:15:55 +0900 - - Fix revision name - - * tool/make-snapshot (package): use the last revision of the whole - tree as the revision name, not a single file. - - * tool/file2lastrev.rb: ditto. dump without unnecessary subrange - and literal quotes, to stringize SVN revisions properly. - -commit 658f17b8ec56e3f8bbd70afdb92c6e7aa156e5be - Author: Nobuyoshi Nakada - Date: 2019-05-22 21:14:12 +0900 - - Fixed the method to delegate - - * tool/vcs.rb (VCS::GITSVN.revision_name): should delegate to the - same method of SVN, not an undefined method. - -commit 2fb69b32968e4c18c8b6fe0a9a33b454feccba32 - Author: git - Date: 2019-05-22 16:54:47 +0900 - - * expand tabs. - -commit 32dd1a798a6d042dbf91e24e9c9f44d94e68f721 - Author: Nobuyoshi Nakada - Date: 2019-05-22 16:52:19 +0900 - - gc.c: revert b00f280d4b "Eagerly name modules and classes" - - * gc.c (rb_raw_obj_info): new string objects cannot allocate to - create new class path name during GC. - -commit 4d93340d3836bc454cee0c74715a412d090ff178 - Author: Nobuyoshi Nakada - Date: 2019-05-22 16:33:03 +0900 - - ast.c: update inspect results in the documents - -commit 48f3dc3cce74f459a690f8434d191140a1c0d8a2 - Author: Nobuyoshi Nakada - Date: 2019-04-19 06:37:01 +0900 - - Set namespace tree - - * variable.c (set_namespace_path): set path to the whole namespace - tree. [Feature #15765] - -commit 1b20d6a6c6b0f72804fb25f90e78fe8efdcbed56 - Author: Alan Wu - Date: 2019-04-12 12:46:28 +0900 - - Extract build_const_pathname - - * variable.c (build_const_pathname): build constant path from - name as a string. [Feature #15765] - -commit b00f280d4b9569e7153365d7e1c522b3d6b3c6cf - Author: Alan Wu - Date: 2019-04-12 12:46:28 +0900 - - Eagerly name modules and classes - - * variable.c: make the hidden ivars `classpath` and `tmp_classpath` the source - of truth for module and constant names. Assign to them when modules are bind - to constants. - - * variable.c: remove references to module name cache, as what used to be the cache - is now the source of truth. Remove rb_class_path_no_cache(). - - * variable.c: remove the hidden ivar `classid`. This existed for the purposes of - module name search, which is now replaced. Also, remove the associated - rb_name_class(). - - * class.c: use rb_set_class_path_string to set the name of Object during boot. - Must use a fstring as this runs before rb_cString is initialized and - creating a normal string leads to a VALUE without a class. - - * spec/ruby/core/module/name_spec.rb: add a few specs to specify what happens - to Module#name across multiple operations. These specs pass without other - code changes in this commit. - - [Feature #15765] - -commit a829be209fc5866f07adc93e8b2f1ddf7131ebfd - Author: Nobuyoshi Nakada - Date: 2019-05-22 08:57:20 +0900 - - Ripper: no documents of fallback methods - -commit c48d9139d4a979e534c1522d2a09ec2a440a8e9a - Author: aycabta - Date: 2019-05-22 07:03:29 +0900 - - Remove unnecessary variable in LineEditor - -commit c00d8056729b72724b86b0f0412c6f2ca9fd1318 - Author: aycabta - Date: 2019-05-22 06:48:27 +0900 - - Support CSI sequences in prompt - -commit ca435ed04ae15607c598808473c59dd7c83debc1 - Author: aycabta - Date: 2019-05-22 03:12:37 +0900 - - Use Reline.test_mode in Reline's test too - -commit f8732bd4d65cf0b776348907b56bd58f4f79ca9c - Author: aycabta - Date: 2019-05-22 02:52:29 +0900 - - Reline#reset should initialize @rest_height and @screen_size eveytime - -commit 232f1117e8aa83ed315d2f0c5ebaaa68e722d204 - Author: git - Date: 2019-05-22 02:14:35 +0900 - - * 2019-05-22 - -commit be86e71c674a6eb3221019cc9e988b3e999b2220 - Author: aycabta - Date: 2019-05-22 02:13:57 +0900 - - Reopen $stderr with specified fd by RELINE_STDERR_TTY - -commit b508b623ee1cc526cfd674218f6e6e7fa6b10f26 - Author: Takashi Kokubun - Date: 2019-05-21 21:00:17 +0900 - - Use conssitent documentation about repository [ci skip] - - This unifies our explanation with - https://github.com/ruby/www.ruby-lang.org/pull/2069 - - Co-authored-by: OKURA Masafumi - -commit 2ecee730a577ece99d16792c12d6662578ac5a85 - Author: aycabta - Date: 2019-05-21 20:52:11 +0900 - - Remove ~/.inputrc not found error message - -commit 32ed85f601d2102990b62102c5f3b322306b1928 - Author: Takashi Kokubun - Date: 2019-05-21 20:32:15 +0900 - - Copy config to make IRB::Context#use_colorize? functional - - on initialize - - This fixes https://github.com/ruby/ruby/pull/2188 - -commit 4613c4bd5c22acb675ec385f4e0fa27ec7ad59ab - Author: aycabta - Date: 2019-05-21 18:55:31 +0900 - - Symbol beginning token may take a constant token - -commit bb5b4f9044b583e192d56c7feda4d1084542efd3 - Author: aycabta - Date: 2019-05-21 18:45:00 +0900 - - Cursor should be at line head after line breaking - -commit fd95ab44c66ce6b756f66210640cf8e8ffd1bd32 - Author: aycabta - Date: 2019-05-21 18:36:10 +0900 - - IRB should eval and show an error when only `.` is inputted - -commit 3f6b5f447caf8f8ca06d5c170e9266ef20945834 - Author: Koichi Sasada - Date: 2019-05-21 18:34:29 +0900 - - re-skip tests of GC.compact. - -commit 6d93baaedd0e9819d4ddb6637b2d3d539f1fa210 - Author: aycabta - Date: 2019-05-21 17:46:31 +0900 - - Support DEL key - -commit 8c004c71235c5ee8b2d4846672788d3089f3e884 - Author: Koichi Sasada - Date: 2019-05-21 17:45:28 +0900 - - enable test for GC.compact to reproduce an issue on CI - -commit 7ff4abe650038ec4a9fa5fa9e0fbc16ceff7714e - Author: Koichi Sasada - Date: 2019-05-21 15:45:21 +0900 - - unify normal and verify ver. - -commit 0b9a7b35287e7c4db37e0f49612faeff29752108 - Author: Koichi Sasada - Date: 2019-05-21 14:58:39 +0900 - - do not use RARRAY_SET() directly in array.c. - -commit 44e9b1e3a6ba464a8ecc22cd7779af64ea01e2e8 - Author: Nobuyoshi Nakada - Date: 2019-05-21 14:23:42 +0900 - - Fix typo - -commit ac00bdc8a8ac2c62a94dd36a7784d15bbcb7df19 - Author: Nobuyoshi Nakada - Date: 2019-05-20 18:10:35 +0900 - - Do not modify shared array - - [Bug #15821] - -commit f9696ca6cbfe827b7ce7199e511fa7431f9333b1 - Author: Nobuyoshi Nakada - Date: 2019-05-21 10:30:13 +0900 - - Simplified the guard against old versions - -commit be0d9c0d26adcf8017d0ce4adf782c1bea2b7240 - Author: aycabta - Date: 2019-05-21 09:24:09 +0900 - - Add "require 'irb'" to use IRB.conf - -commit 29c81265c1637245aa331f8d47c5060f4dc79ab0 - Author: aycabta - Date: 2019-05-21 09:14:08 +0900 - - Check whether IRB.conf is nil in IRB::WorkSpace#code_around_binding - -commit 3a9008b9845db544d0788851f9527ce9f9f6bf4a - Author: aycabta - Date: 2019-05-15 16:36:33 +0900 - - Add --colorize and --nocolorize options to IRB - -commit df6a673ca55d26a768ead23466c7e055a8596d7a - Author: aycabta - Date: 2019-05-21 08:10:36 +0900 - - Fix vertical cursor moving when splitting line - -commit 34d7ec4e9b0a24b3ce89009927738f1dac38e6d3 - Author: aycabta - Date: 2019-05-21 01:18:19 +0900 - - Finish only when buffer contains non-blank line - -commit b69dfdb4b3d9dfce18123d1814087fc49b390ea9 - Author: aycabta - Date: 2019-05-21 01:14:53 +0900 - - Cursor up should reduce 1 than editing height - -commit 8023b3ce9d654c1a58e1f4952b666e2c412938ca - Author: git - Date: 2019-05-21 01:10:47 +0900 - - * 2019-05-21 - -commit 6592f5fcc8e7c6130eba5acf71d2763e7a6d58cf - Author: aycabta - Date: 2019-05-21 00:59:43 +0900 - - Check bytesize in vi command mode last char back - -commit 583ecd5fc5d96a6a8135776db6e92b8565789fb0 - Author: git - Date: 2019-05-20 22:08:27 +0900 - - * expand tabs. - -commit e83f10b36865c7fc3f3e09deab679c4270310021 - Author: Nobuyoshi Nakada - Date: 2019-05-20 21:58:06 +0900 - - Get rid of undefined behavior that source and destination buffers overlap - -commit 8c8f2d97cf51103b6f3d40bf7239a40899e380f6 - Author: Benoit Daloze - Date: 2019-05-20 17:41:57 +0900 - - Remove redundant ignore rule for Process#clock_getres specs - -commit 2a34543e11299146db688e636e0b95c22990e302 - Author: Benoit Daloze - Date: 2019-05-20 17:40:34 +0900 - - Move exclusion for Hyper-V next to other skipped constants - -commit ab0f2deab11a3203f9af3af1a27dfea1f4a882f3 - Author: Koichi Sasada - Date: 2019-05-20 14:39:46 +0900 - - skip a test for CLOCK_MONOTONIC_RAW. - - On my Linux guest machine on Hyper-V, I got an error. - Process.clock_gettime(CLOCK_MONOTONIC_RAW, :nanosecond) returns like: - - ... - 875573945119100 - 875573945119600 - ... - - even if `Process.clock_getres(value, :nanosecond)` returns 1. - So I simply skip this test for CLOCK_MONOTONIC_RAW. - -commit 7ef548c0acf2f8b62db234e39a0f1030902a305c - Author: Nobuyoshi Nakada - Date: 2019-05-20 12:43:52 +0900 - - Mixed encoding error can continue to parse - -commit 9f49ff4965da8b05887912506dff7d0d20388550 - Author: aycabta - Date: 2019-05-20 07:45:36 +0900 - - Cursor can't move to eol when vi command mode - -commit f659e2f9bf0c7d0351a80dc284a384a948bd67dd - Author: git - Date: 2019-05-20 04:52:41 +0900 - - * 2019-05-20 - -commit 075e1acb4c920edf0b5d20a5cb5004a4f88fbcd8 - Author: aycabta - Date: 2019-05-20 04:47:43 +0900 - - Readline.completion_proc accepts US-ASCII - -commit 4d7ada10b1d8d6eba79d845aa9ecffb890f593d4 - Author: Nobuyoshi Nakada - Date: 2019-05-19 16:47:53 +0900 - - Update test-unit - -commit cc764e5d37a8424949af0e83a8bb5661a1d6e8a6 - Author: git - Date: 2019-05-19 05:45:50 +0900 - - * 2019-05-19 - -commit af1502175b5a3415949b8daa6f70a1cfaa7d1975 - Author: Nobuyoshi Nakada - Date: 2019-05-19 05:42:13 +0900 - - Touch the timestamp file for Unicode files - -commit 60de17258ba0be6c113e60ce237c3b8608457da7 - Author: Marcus Stollsteimer - Date: 2019-05-18 20:06:49 +0900 - - [DOC] Shorten examples for Time#{round,floor} - -commit cc0e460bccbf005d23616be1ea2624a161a4ecdd - Author: Marcus Stollsteimer - Date: 2019-05-18 20:06:10 +0900 - - [DOC] Improve documentation for Time#floor - - Use numbers that are more illustrative for #floor. - -commit f782e5bdcf91f2885519e20e3aa53eec063faea8 - Author: Marcus Stollsteimer - Date: 2019-05-18 20:05:26 +0900 - - [DOC] Use '&&' instead of 'and' in boolean expression - -commit acf6689a8c77b5730274e2c9ec1d49423674da15 - Author: Marcus Stollsteimer - Date: 2019-05-18 20:04:04 +0900 - - [DOC] Improve documentation for Enumerator::Lazy - -commit 154a67f140a8397df77d82cdc80e13b291b8aedd - Author: Aaron Patterson - Date: 2019-05-18 18:23:47 +0900 - - Rename rb_gc_new_location to rb_gc_location - - The function will return new or existing locations depending on whether - or not the object actually moved, so give it a more appropriate name. - -commit bbb84a16fab8e715a108c318e9e0e019339eb972 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-18 14:20:33 +0900 - - Add fall through comment for Coverity Scan - -commit 16917cc3cb27277d04b9c35fb7fc10f72a9b6dfa - Author: aycabta - Date: 2019-05-18 03:12:53 +0900 - - Add Reline.test_mode to use with special I/O - -commit b165bedcbd41d791a85fc1ce90b57a0d0525f319 - Author: Koichi Sasada - Date: 2019-05-18 12:17:02 +0900 - - skip a test to pass CIs. - - I'm debugging [Bug #15821] but my patch introduces another issue. - So I simply skip this test and re-enable it later. - -commit 6ae1c596f0b179f1b1b2b115ca75eab1631230fe - Author: Nobuyoshi Nakada - Date: 2019-05-18 09:40:52 +0900 - - Add test for UNTIL - -commit 4d9c3a8c2362b7d5973057435258e447ce733741 - Author: Nobuyoshi Nakada - Date: 2019-05-18 01:17:47 +0900 - - Update include files on msys2 too - -commit 719ebbec303967aacbf5122219d67b34aae9351e - Author: Nobuyoshi Nakada - Date: 2019-05-17 23:46:22 +0900 - - Get rid of always updating Unicode files - - [Misc #15859] - -commit c4bad9f74e432572b80c24c7f1c519c5cc4c59a2 - Author: Nobuyoshi Nakada - Date: 2019-05-18 09:35:40 +0900 - - Distinguish pre-condition and post-condition loops - -commit 39336a4210557d8677a2e07094efd785af0711ca - Author: git - Date: 2019-05-18 02:41:28 +0900 - - * 2019-05-18 - -commit 9858d74a128c1126f0d05ebe5c05a2e6b34ce0af - Author: aycabta - Date: 2019-05-18 02:32:25 +0900 - - Remove parent namespace from Readline test classes - - The namespace "Readline" doesn't exist when running tests if readline.so - doesn't exist and Reline exists. So test classes shouldn't be at nested - namespaces under "Readline". - -commit ea3e7e268546599883b25d9a33d26e042461ac25 - Author: Aaron Patterson - Date: 2019-05-17 23:08:31 +0900 - - Prevent Dynamic -> Static symbols from moving - - If a dynamic symbol has been converted to a static symbol, it gets added - to the global ID list and should no longer move. C extensions can pass - symbols to rb_sym2id and those symbols should no longer be movable. - When the symbol is passed to rb_sym2id, the `id` member is set, so we - can use its existence to prevent movement. - -commit 0723c107f4fb39f60113b44dd21d875c90da5456 - Author: Nobuyoshi Nakada - Date: 2019-05-17 13:55:59 +0900 - - Do not export InitVM functions - -commit e29a85a96c47be3b4ff77b1e6d2235ea935a35bc - Author: Nobuyoshi Nakada - Date: 2019-05-17 10:49:25 +0900 - - Make COROUTINE_XMM_REGISTERS compile-time only too - -commit b1b385465e4fc1cab84b2a3fa112a33a3e5ab076 - Author: Nobuyoshi Nakada - Date: 2019-05-17 10:25:34 +0900 - - Do not call memcpy if copying nothing - - c.f. - * e7b18ca6d9b45b7e71694557b9fab8152c62c1ed - * 34e1079aef81d108890fb167d7df69960e994ff5 - -commit 32e8b42852fc59a7064ec9ad642774c562b69c21 - Author: Koichi Sasada - Date: 2019-05-17 12:59:49 +0900 - - skip tests for GC.compact to pass CI. - - Now, GC.compact has issues which makes rubyci RED, so I skip this test - and debug soon. - -commit f1f402946023573d3d17410d0de19c653f53f96e - Author: git - Date: 2019-05-17 10:10:39 +0900 - - * 2019-05-17 - -commit 0971cab4d0cb730292461d16ac72c430aa23cc10 - Author: Nobuyoshi Nakada - Date: 2019-05-17 09:53:47 +0900 - - Test to disable ASCII-only optimization - - Examples why ASCII-only optimization cannot apply multi-byte - encodings which have 7-bit trailing bytes. - - Suggested by @duerst at https://github.com/ruby/ruby/pull/2187#issuecomment-492949218 - -commit 23751a2681abd50e9081bdbb00f818942570c872 - Author: Nobuyoshi Nakada - Date: 2019-05-16 23:26:57 +0900 - - leaked-globals: check if un-prefixed symbols leak externally - -commit e0f0ab959e9a0fa3db8dfdb2a493b057d6e7541b - Author: Nobuyoshi Nakada - Date: 2019-05-16 18:58:17 +0900 - - Remove unused symbols - -commit 0ed9bdfc13082b6d19712738ca69fbbe2a36f106 - Author: Nobuyoshi Nakada - Date: 2019-05-16 18:24:12 +0900 - - Pack struct rb_strterm_heredoc_struct on 32-bit platforms - -commit 88449100bc6d23a00dbf3addb97665f4f606f2b8 - Author: Koichi Sasada - Date: 2019-05-16 16:44:30 +0900 - - don't need to sweep rest. - - `transient_heap_evacuate()` disables GC using `rb_gc_disable()` - to prohibit GC invocation because of new allocation for evacuated - memory. However, `rb_gc_disable()` sweep all rest of unswept pages. - We don't need to cancel lazy sweep so this patch introduce - `rb_gc_disable_no_rest()` which doesn't cancel lazy sweep. - -commit a160b2f56716f70fa3e485ae89875da48baefc1d - Author: Nobuyoshi Nakada - Date: 2019-05-16 15:51:37 +0900 - - Make COROUTINE_REGISTERS compile-time only not to be a global symbol - -commit 7069f64c419ebb9a7fd3e48d81454148ed4b2fba - Author: Nobuyoshi Nakada - Date: 2019-05-16 15:43:16 +0900 - - Prefix global_symbols with `ruby_` - -commit 973431c059ab2719e97d1ec051d21aa63a43a005 - Author: Nobuyoshi Nakada - Date: 2019-05-16 15:36:58 +0900 - - Make internal functions static - -commit 82332c7d8b17b610a347f7c804219c7fcb702d23 - Author: Takashi Kokubun - Date: 2019-05-16 15:13:36 +0900 - - Rename mjit_gc_finish_hook to mjit_gc_exit_hook - - because @ko1 said "gc_finish" is confusing like a finish of entire GC - process - -commit 18e43e823106f15c8aaceb1f56874bdf67bc36a3 - Author: Nobuyoshi Nakada - Date: 2019-05-16 14:58:57 +0900 - - Fix fd leak - - merged https://github.com/rubygems/rubygems/pull/2765 - -commit fadab0f9fb18448c9146fce0fd87f4285f647516 - Author: git - Date: 2019-05-16 14:43:49 +0900 - - * 2019-05-16 - -commit e970ab3339109b89b4251887e39412af20348156 - Author: Nobuyoshi Nakada - Date: 2019-05-15 23:17:18 +0900 - - Suppress unused-but-set-variable warning - -commit 214e2f93aa6b0810353b67f320dab6aa63a97169 - Author: Nobuyoshi Nakada - Date: 2019-05-15 18:18:44 +0900 - - Fix the warning in 456586bb234915107da255d2944f620a7dd7048b - -commit 3cf767ee35060d7d261f47399a7d717256d0f237 - Author: Aaron Patterson - Date: 2019-05-10 06:36:30 +0900 - - unpin finalizers and update references - -commit c9b28fd7ae5c5a79a74afebd5b191cfd2f31a65f - Author: Nobuyoshi Nakada - Date: 2019-05-15 17:22:25 +0900 - - Allow --enable/--disable options to take an argument - - [Bug #15850] - -commit f54aa6c5b286b2b44bcdb1958fc9b1ebfce3559e - Author: aycabta - Date: 2019-05-15 15:52:12 +0900 - - Rename confused name Reline::IO with Reline::IOGate - -commit 0cc893d01d1c4a6b36f01a25587a121261601697 - Author: Aaron Patterson - Date: 2019-05-15 12:41:31 +0900 - - Static symbols can't be moved (they are not RValue) - - This is my mistake, I thought they were regular objects, but apparently - they are not. We don't need to pin them. - - Revert "Symbols can move so only cache IDs" - - This reverts commit 672ee5f6ed5a6840a3be9150b6721a5ee8f8766b. - -commit 672ee5f6ed5a6840a3be9150b6721a5ee8f8766b - Author: Aaron Patterson - Date: 2019-05-14 09:24:19 +0900 - - Symbols can move so only cache IDs - - IDs can't move, we need to use them to look up the symbol objects later. - -commit e8b929b9df3a686ab4e5e0a07fb813d0bedf508f - Author: git - Date: 2019-05-15 12:21:53 +0900 - - * expand tabs. - -commit c70ceb59928aa2c37befd6b03d73657ba5ece61c - Author: Aaron Patterson - Date: 2019-05-10 05:13:56 +0900 - - Add object packing strategies for compaction - - This commit adds an alternative packing strategy for compaction. - Instead of packing towards "most pinned" pages, we can pack towards - "most empty" pages. The idea is that we can double the heap size, then - pack all objects towards the empty side of the heap. This will ensure - maximum chaos for testing / verification. - -commit 46a479889cb5be2a7a24d6adbe54e822899d96cc - Author: git - Date: 2019-05-15 00:19:31 +0900 - - * 2019-05-15 - -commit 2ca537ba4b620d0a657b7da433df92f876974015 - Author: Aaron Patterson - Date: 2019-05-15 00:18:43 +0900 - - Fixing function name - - This function is used for marking / pinning vm stack values, so it - should have "vm" in the function name to be more clear. - -commit b5a3ec7f18761cbe30a90aa585b59ab05d926d2d - Author: aycabta - Date: 2019-05-14 17:15:49 +0900 - - Remove useless use of a variable in Reline::ANSI - -commit 80c968c571a65d140aefab4774fa87bf39966723 - Author: aycabta - Date: 2019-05-14 17:05:36 +0900 - - Rename Reline's test file name because of typo - -commit 4fe0961dca71406816e136a76f742adb1f0b9bb5 - Author: Takashi Kokubun - Date: 2019-05-14 16:45:18 +0900 - - Fix typo in debugged C source name - - I failed to collect any debug info in - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cda57fcab79a30008f195f6?step=5cda6a4e1090c4000800772e - - It seems that it's due to this typo. - -commit c754e979d3eeca51f1b13778f19f347df3da656e - Author: aycabta - Date: 2019-05-14 07:00:03 +0900 - - Test ext/readline and lib/reline by test/readline - -commit 07e7ae9ed78d0891a1c4755e2faf3c8d15d95102 - Author: aycabta - Date: 2019-05-14 05:34:20 +0900 - - Add an assertion message to test of Readline's class variables - -commit 1e65196b54644c5a8fe53c98643ab7e87dfb87c0 - Author: aycabta - Date: 2019-05-14 04:08:23 +0900 - - Check encoding when Readline completion - -commit 29dde62605d50a55933ec5d92bcb6f5f738c390b - Author: Nobuyoshi Nakada - Date: 2019-05-14 14:47:54 +0900 - - io/console: rb_str_cat_conv_enc_opts is not exported - -commit c1746708233bf90270dca1f698ca3616cc16922c - Author: Nobuyoshi Nakada - Date: 2019-05-14 14:39:08 +0900 - - io/console: fix up timeout on Windows - -commit 456586bb234915107da255d2944f620a7dd7048b - Author: Nobuyoshi Nakada - Date: 2019-05-14 14:21:46 +0900 - - io/console: support getch timeout on Windows - -commit 6d733565c2df1b34c7f0b7d43d97f80f714a64b9 - Author: Nobuyoshi Nakada - Date: 2019-05-14 14:19:15 +0900 - - io/console: support wide character input on Windows - -commit 602ef62ae693344aea70a85bb664bbbe93f20465 - Author: aycabta - Date: 2019-05-14 02:39:40 +0900 - - Rescue CompatibilityError for Readline's completion - -commit 5bab1304af25a843728dbcd2f3594913740aecb0 - Author: Urabe, Shyouhei - Date: 2019-05-14 11:44:20 +0900 - - fix visibility of SecureRandom.gen_random - - Aliasing a method preserves its visibility. These aliases turn - formerly-public methods into private. Should make them public - again. [Bug #15847] - -commit af1f3f131f6a82f5f06fe5b3adeb6f80cf86b941 - Author: aycabta - Date: 2019-05-14 01:10:15 +0900 - - Readline's class vars should be encoded as default_external - -commit 741321704fa1e4f180c853684a8ceaa6eff3b469 - Author: aycabta - Date: 2019-05-14 00:03:15 +0900 - - Remove unused variable in LineEditor - -commit 79ead821dd4880725c9c6bb9645b3fad71715c5b - Author: Aaron Patterson - Date: 2019-05-14 06:27:54 +0900 - - Add NaN / Infinity / MinusInfinity to mark list - - This prevents the constants from moving. - -commit a1ecf07dff7530f8f53fb456b2e38a8a039cb561 - Author: Aaron Patterson - Date: 2019-05-10 07:04:35 +0900 - - turn T_MOVED in to a linked list - -commit 66a7c92938638e3afceb1d92ae877376902a71a0 - Author: Aaron Patterson - Date: 2019-05-14 04:59:30 +0900 - - Don't run the compactor if GC is disabled - - GC is required for pinning / marking objects. If the compactor runs - without pinning everything, then it will blow up, so just return early - if the GC is disabled. - -commit 0215520beaa2be7a7bfb9aeb79bfc8c7ea7936b0 - Author: git - Date: 2019-05-14 00:32:58 +0900 - - * 2019-05-14 - -commit d2003a6d392b3b0054d7528e2e731584196aefad - Author: Nobuyoshi Nakada - Date: 2019-05-14 00:30:08 +0900 - - Symbol just represents a name - -commit 3b3b4a44e57dfe03ce3913009d69a33d6f6100be - Author: Nobuyoshi Nakada - Date: 2019-05-13 23:53:46 +0900 - - Update dependencies - -commit 082bbdc92e5d704c9fb2811d7c038f92aee77484 - Author: Hiroshi SHIBATA - Date: 2019-05-13 21:26:01 +0900 - - Update the canonical repository for racc. - -commit b42303b151534b4d0f2b7ccf7d4beeb27b0c2874 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-13 21:14:52 +0900 - - Fix typos - -commit 2dc613815d2c4a69bfbcbf78d1b99aa52fbabf60 - Author: Étienne Barrié - Date: 2016-08-31 02:29:07 +0900 - - delegate.rb: don't look for methods on Kernel - - Instead, look for instance methods of Kernel. - Otherwise, instance methods of Module (which are methods of Kernel - itself) are mistakenly believed to exist, and it fails when calling - Kernel.instance_method(). - - Closes: https://github.com/ruby/ruby/pull/1422 - -commit 24964fff92cd89925d2169ad97a357a5bc57e3e1 - Author: aycabta - Date: 2019-05-13 04:22:08 +0900 - - Check that Reline exists on test - -commit 75f196ce75f35ecbab8186c9ada2f3a91160f8f9 - Author: aycabta - Date: 2019-05-13 03:29:18 +0900 - - Skip tests depend on Readline's special behaviors - -commit caef2ddaaf4a121272ad5c11d046ff4511c0f560 - Author: aycabta - Date: 2019-05-13 03:26:10 +0900 - - Implement Reline::HISTORY as an expanded Array - -commit c48778d64294c7871e2be09b0138d74e4d9d8551 - Author: aycabta - Date: 2019-05-13 03:24:15 +0900 - - Add attr_accessor for Reline's Config attrs - -commit ebb15cc6c17e33b030b511fff8b5722a8238ace5 - Author: aycabta - Date: 2019-05-13 02:33:29 +0900 - - Reline.completion_proc= should raise ArgumentError - - When the value is not Proc. - -commit 130ced9fb025da05bc97346e30f1e3a6c86ead2e - Author: aycabta - Date: 2019-05-13 02:31:42 +0900 - - Reline.completion_append_character= should be nil - - When unknown value comes. - -commit e467f920a38cabad9568ebd5cfd46d11de04afa8 - Author: aycabta - Date: 2019-05-13 02:30:53 +0900 - - Add Reline.special_prefixes as stub - -commit 5837290af1216eaadbee3204e40ef16931da2fdb - Author: aycabta - Date: 2019-05-13 02:26:31 +0900 - - Implement Reline's class methods for compatibility - - - insert_text - - redisplay - - line_buffer - - point - - point= - - vi_editing_mode - - emacs_editing_mode - - vi_editing_mode? - - emacs_editing_mode? - - get_screen_size - -commit c137f015ab2283e885168f983e36e4bd2c1aa29e - Author: aycabta - Date: 2019-05-13 02:20:20 +0900 - - Add Reline.pre_input_hook interface - -commit 9cb821b02486de87b322089302fec3a63cda7b81 - Author: aycabta - Date: 2019-05-13 02:14:48 +0900 - - Implement Reline.input= and Reline.output= - -commit bb56b899009828d567062fa5b9dd0af9f927cd32 - Author: aycabta - Date: 2019-05-13 01:51:05 +0900 - - Add ed_search_prev_history to Reline - -commit 559cad9f2d87721fda1ffbf2e39ce4b328a5b17f - Author: okuramasafumi - Date: 2019-05-04 21:54:25 +0900 - - Improve doc for Enumerable#include? and member? - - Existing doc for Enumerable#include? and member? has some problems. - * `IO.constants` is not commonly used, and only some know - that `SEEK_SET` is actually included in constants. - * `IO.constants` is actually an Array, not the example is not - appropriate for `Enumerable` module. - So in this commit, the old example is replaced with new one. - New example uses integer range, which is much simpler and easier to - understand. - - Closes: https://github.com/ruby/ruby/pull/2168 - -commit 33bce2585ffacd8cf762972da7ca7a99d804989f - Author: aycabta - Date: 2019-05-13 00:30:39 +0900 - - Use LineEditor#reset on test - -commit d3a702a3f1568f33e1c681bc40bae396a2f46d17 - Author: git - Date: 2019-05-13 00:23:03 +0900 - - * 2019-05-13 - -commit 0f45bd0584f1550e153babc339ad7671e2424d20 - Author: aycabta - Date: 2019-05-13 00:22:27 +0900 - - Split namespace of env-dependent I/O classes - -commit 11476e9902405b90b7493fed43f9fc2e6db9a32c - Author: aycabta - Date: 2019-05-12 23:20:51 +0900 - - Check INPUTRC env in Reline::Config - -commit aaaede8bcff278bd304092e1c74d39e8fbd4cef8 - Author: aycabta - Date: 2019-05-12 21:22:04 +0900 - - Change LineEditor instance in Reline to class var - -commit fc57e10569614caf5efc5b7fe18e6c76fafbb2e9 - Author: aycabta - Date: 2019-05-12 20:43:38 +0900 - - Revert "Add a test for em_capitol_case of Reline" - - This reverts commit b1767e56b158d8307412a0928a7ac2366541429d. - -commit b1767e56b158d8307412a0928a7ac2366541429d - Author: aycabta - Date: 2019-05-12 17:25:28 +0900 - - Add a test for em_capitol_case of Reline - -commit 3211a0a1e87d7ad622906b84de27f49a7d0d7578 - Author: git - Date: 2019-05-12 00:52:17 +0900 - - * 2019-05-12 - -commit e9bb30d47e5f07774cfbc69f0c8824ec921f6cda - Author: Nobuyoshi Nakada - Date: 2019-05-12 00:03:19 +0900 - - Expect no conflict in the parser - -commit 79931dddba67ad68886f65ba8562eb99507cee3a - Author: Nobuyoshi Nakada - Date: 2019-05-10 16:40:34 +0900 - - Propagate parser_params to rb_yytnamerr - -commit dc65e75101de94c0f88851d7d3eab56cb7232c7a - Author: Nobuyoshi Nakada - Date: 2019-05-10 17:28:20 +0900 - - Adjust indent - -commit aa52464efd558010f4fa5ef5de68d8f684b637aa - Author: Hiroshi SHIBATA - Date: 2019-05-10 21:45:15 +0900 - - 15f45ae4d1 and 56528da3e broke the darwin environment. - - Revert "Propagate parser_params to rb_yytnamerr" - - This reverts commit 15f45ae4d12f14714ab3021b60887d8c7bf4b095. - -commit d4c8577a14fa272bc9a3e68d4748fdf2f2cf7dee - Author: Hiroshi SHIBATA - Date: 2019-05-10 21:45:04 +0900 - - Revert "Fix for bison 2.3" - - This reverts commit 56528da3efb32bb773b22740c24450246b861e58. - -commit 56528da3efb32bb773b22740c24450246b861e58 - Author: Nobuyoshi Nakada - Date: 2019-05-10 16:58:51 +0900 - - Fix for bison 2.3 - -commit 15f45ae4d12f14714ab3021b60887d8c7bf4b095 - Author: Nobuyoshi Nakada - Date: 2019-05-10 16:40:34 +0900 - - Propagate parser_params to rb_yytnamerr - -commit 9a4d39b95ed60a00aec2ee3447931015254eb794 - Author: Nobuyoshi Nakada - Date: 2019-05-10 15:22:54 +0900 - - No longer svn & git-svn are used - -commit dbcc224f3883c810049ef620fac8a1b59bde2e69 - Author: Nobuyoshi Nakada - Date: 2019-05-10 09:01:08 +0900 - - Removed old names of internal methods - -commit a7b68e63c5dd9d366b0ddc17b16650560800f03a - Author: Nobuyoshi Nakada - Date: 2019-05-10 12:48:43 +0900 - - Suppress a warning in Psych&YAML with verbose mode - -commit c8a891d1aa2fd54172d313441811aef2838b7797 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-10 12:21:25 +0900 - - Fix missing `\A` - -commit bef5829482ab410111911f2472442ff0dfbd3838 - Author: Takashi Kokubun - Date: 2019-05-10 11:54:15 +0900 - - Add one more retry for win32ole event matcher - - to fix - https://ci.appveyor.com/project/ruby/ruby/builds/24438615/job/yld1utsltxag9dr2 - -commit a85ed43294700ed0dd11d22b5c3d5d37d2b1809c - Author: Nobuyoshi Nakada - Date: 2019-05-10 08:59:08 +0900 - - Do not access the internal member - -commit c4d49749fbbb922f6102d3bf0729c861f9436a00 - Author: git - Date: 2019-05-10 04:28:19 +0900 - - * 2019-05-10 - -commit 5f05851ae37050c7031a080e405f8773089d7c14 - Author: Aaron Patterson - Date: 2019-05-10 04:27:44 +0900 - - add FROZEN to lldb debug output - -commit 025206d0dd29266771f166eb4f59609af602213a - Author: Nobuyoshi Nakada - Date: 2019-05-09 14:11:43 +0900 - - Fallback to an invalid branch name if no branch found - -commit eb84b33c86280a72aaeedae1e582045528c534b2 - Author: Nobuyoshi Nakada - Date: 2019-05-09 14:02:01 +0900 - - Search a branch name at a detached head - -commit c06ddfee878524168e4af07443217ed2f8d0954b - Author: Alan Wu - Date: 2019-05-08 22:44:41 +0900 - - str_duplicate: Don't share with a frozen shared string - - This is a follow up for 3f9562015e651735bfc2fdd14e8f6963b673e22a. - Before this commit, it was possible to create a shared string which - shares with another shared string by passing a frozen shared string - to `str_duplicate`. - - Such string looks like: - - ``` - -------- ----------------- - | root | ------ owns -----> | root's buffer | - -------- ----------------- - ^ ^ ^ - ----------- | | - | shared1 | ------ references ----- | - ----------- | - ^ | - ----------- | - | shared2 | ------ references --------- - ----------- - ``` - - This is bad news because `rb_fstring(shared2)` can make `shared1` - independent, which severs the reference from `shared1` to `root`: - - ```c - /* from fstr_update_callback() */ - str = str_new_frozen(rb_cString, shared2); /* can return shared1 */ - if (STR_SHARED_P(str)) { /* shared1 is also a shared string */ - str_make_independent(str); /* no frozen check */ - } - ``` - - If `shared1` was the only reference to `root`, then `root` can be - reclaimed by the GC, leaving `shared2` in a corrupted state: - - ``` - ----------- -------------------- - | shared1 | -------- owns --------> | shared1's buffer | - ----------- -------------------- - ^ - | - ----------- ------------------------- - | shared2 | ------ references ----> | root's buffer (freed) | - ----------- ------------------------- - ``` - - Here is a reproduction script for the situation this commit fixes. - - ```ruby - a = ('a' * 24).strip.freeze.strip - -a - p a - 4.times { GC.start } - p a - ``` - - - string.c (str_duplicate): always share with the root string when - the original is a shared string. - - test_rb_str_dup.rb: specifically test `rb_str_dup` to make - sure it does not try to share with a shared string. - - [Bug #15792] - - Closes: https://github.com/ruby/ruby/pull/2159 - -commit d802698d3e27a3cf091a56556df3562cc6ff996c - Author: Nobuyoshi Nakada - Date: 2019-05-09 10:01:31 +0900 - - Push the current (topic) branch to the remote upstream - -commit 4fabb744718ddbb2eb8f5f4a6ca3d47d8e770547 - Author: Nobuyoshi Nakada - Date: 2019-05-09 09:59:27 +0900 - - Show the commit command if dryrun - -commit f1486fea46cf36f1c936f5074a7251f29f9c1c5d - Author: NARUSE, Yui - Date: 2019-05-09 09:23:44 +0900 - - require 'stringio' - -commit 10723dd6cefb84e6a7d69b3bc3c1a74c345e4306 - Author: Nobuyoshi Nakada - Date: 2019-05-09 08:54:38 +0900 - - dryrun option is for `push`, not `git` - -commit dc405eb737c178016167c8e64bdf32d27c5455f0 - Author: Aaron Patterson - Date: 2019-05-09 07:55:35 +0900 - - Pin finalizer table - - Objects in the finalizer table stay pinned for now. In some cases, the - key could move which would cause a miss when removing the object from - the table (leading to a T_MOVED reference staying in the table). - -commit 4ff0911c796e80ad3740b1aea0199da698f4910b - Author: git - Date: 2019-05-09 07:26:32 +0900 - - * 2019-05-09 - -commit 8b12db6e197a5f4d57fb208b3f03b4b17733f1e4 - Author: git - Date: 2019-05-09 07:26:29 +0900 - - * expand tabs. - -commit c53f87943e53c96b86d50b496d2a410ff1245b4c - Author: Aaron Patterson - Date: 2019-05-09 07:19:59 +0900 - - Calling `obj_info` during sweep is unsafe - - `obj_info` will look at references of objects in some cases (for example - it will try to access path information on ISeq objects). But during the - sweep phase, if the referenced object is collected before `obj_info` is - called, then it could be a bad ref and a segv will occur. - - For example: - - A -> B - - Sweep phase: - - 1. obj_info(B) - 2. Sweep and free B - 3. obj_info(A); A tries to read B - 4. SEGV - - This commit simply removes the call to `obj_info` during the sweep - phase. - -commit a95ca6d5e9c1c7371f7324159840ac1e8c013125 - Author: Takashi Kokubun - Date: 2019-05-08 17:30:11 +0900 - - Trim MJIT output from TestHideSkip - - to prevent failure like - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cd28aa6ab79a30008ee819b?step=5cd28b2403f44600070db083 - with --jit-verbose=1. - -commit 29fcb37a8319c70a8524c13b525087ff63431676 - Author: Nobuyoshi Nakada - Date: 2019-05-08 16:59:37 +0900 - - Fixed a typo - -commit c54d5872fbd95c04ab77b4c1d6f95974ddac0090 - Author: Nobuyoshi Nakada - Date: 2019-05-08 16:55:59 +0900 - - Configure directories for headers and libraries automatically - - [EXPERIMENTAL] - -commit a1bab3d1a3bf36e113267c212d7fb36710859674 - Author: Takashi Kokubun - Date: 2019-05-08 16:51:37 +0900 - - Escape $@ in mjit-debug-on-fail - -commit e8e415b5347197666f4dd11d25df08881ddaa36f - Author: Kazuhiro NISHIYAMA - Date: 2019-05-08 16:44:08 +0900 - - Add workaround for `Permission denied` of `cp` - - see r67347 - recent log: https://travis-ci.org/ruby/ruby/jobs/529640417 - -commit b0965cc2d6fe284e0bf3154ed7a282a29287a20c - Author: Takashi Kokubun - Date: 2019-05-08 16:26:53 +0900 - - Add missing chmod for mjit-debug-on-fail - -commit 60869ebd005dc21e03e5f3cf9b517ff761781e80 - Author: Takashi Kokubun - Date: 2019-05-08 16:25:25 +0900 - - Wrap mjit-debug-on-fail for Wercker failure - - for debugging failure like - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cc98936ab79a30008eb86fa?step=5cc990d73d81fb0007bb04c3 - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cd18efa23fcb70008ddfd45?step=5cd1908603f4460007076c5a - -commit d736080c8b8731fe8e7be99893eea35b67cbbc0e - Author: Nobuyoshi Nakada - Date: 2019-05-08 15:45:13 +0900 - - Use ruby_bug guard - -commit a7cbb659566b4b9114cc2a00f036e7a88300b30d - Author: Takashi Kokubun - Date: 2019-05-08 15:13:33 +0900 - - Do not break rubyspec for old Ruby - - Fixing 7d805e67f3275aef066d77aa9c32bef715c362ed - -commit 229e5053a1ea9633489e296faafc34c9c51e7391 - Author: Takashi Kokubun - Date: 2019-05-08 14:59:18 +0900 - - Drop -fs from rubyspec to see test results easily - - Recently `ruby/spec on Ruby 2.4` seems stable. - -commit 6ec43d3d049f4736e6d0196497bfc9562001dd28 - Author: git - Date: 2019-05-08 11:18:20 +0900 - - * 2019-05-08 - -commit d56b0cb554dd75190b1d308e20f3f49f5f12571b - Author: Kazuhiro NISHIYAMA - Date: 2019-05-08 11:14:21 +0900 - - Use `start_with?(quoted)` instead of `[0] == char literal` - -commit efda52ba62361a0262d3775b8210fff85fb42247 - Author: Hiroshi SHIBATA - Date: 2019-05-07 23:30:39 +0900 - - Use cgit instead of svn. - -commit 45b125eca76e60482113575f1e71574fcbcc3b4c - Author: Hiroshi SHIBATA - Date: 2019-05-07 23:16:26 +0900 - - Update the canonical repository url. - -commit 5eb5613fef1c8a72df6843ffce9fc339f145948e - Author: Kazuhiro NISHIYAMA - Date: 2019-05-07 22:53:45 +0900 - - Recent commits of trunk do not have svn revision - -commit a47f598d77ac97f9fe89fe16aa8bcab4fd262c16 - Author: Lourens Naudé - Date: 2019-04-20 08:44:51 +0900 - - Reduce ONIG_NREGION from 10 to 4: power of 2 and testing revealed most pattern matches are less than or equal to 4 results - - Closes: https://github.com/ruby/ruby/pull/2135 - -commit 7d805e67f3275aef066d77aa9c32bef715c362ed - Author: Jean Boussier - Date: 2019-05-07 19:00:57 +0900 - - Avoid triggering autoload in Module#const_defined?(String) - - [Bug #15780] - -commit 6786fe44dcbb560d896bb9bb5baa9dc74677ce17 - Author: git - Date: 2019-05-07 17:36:10 +0900 - - * 2019-05-07 - -commit 4dc5d3c5dd43b4cc54517e604c16ecfc808e5481 - Author: Koichi Sasada - Date: 2019-05-07 14:06:25 +0900 - - add new debug_counters about is_pointer_to_heap(). - - is_pointer_to_heap() is used for conservative marking. To analyze - this function's behavior, introduce some debug_counters. - -commit 7e72ce0f734113e3e215a74b440092443e957d45 - Author: Nobuyoshi Nakada - Date: 2019-05-06 15:30:44 +0900 - - Load OptionParser defaults from XDG and Haiku standards - -commit 970a25b10415bc3735e6e3c165e167e6abc3d7f4 - Author: git - Date: 2019-05-06 11:08:03 +0900 - - * 2019-05-06 - -commit f1b0db2c70aa3120a557fd7553b98f96ecc62ade - Author: Nobuyoshi Nakada - Date: 2019-05-06 11:02:12 +0900 - - Revert "UTF-8 is one of byte based encodings" - - This reverts commit 5776ae347540ac19c40d146a3566a806cd176bf1. - - Mistaken `max` as `min`. - -commit 594a033ff0f6a22693b7b82b060e922c58dac8d0 - Author: Marcus Stollsteimer - Date: 2019-05-05 16:52:34 +0900 - - Improve description of Ruby in README - - Use improved description as suggested by Olivier Lacan (@olivierlacan), - see https://github.com/ruby/www.ruby-lang.org/pull/1888. - -commit 35ff4ed47fcdc14bbdd19540622cb04f86536c95 - Author: Marcus Stollsteimer - Date: 2019-05-05 16:51:40 +0900 - - Improve documentation for String#{dump,undump} - -commit bb4ac7a6506971dc34b5656f1a69aadc7299fcab - Author: Jeremy Evans - Date: 2019-05-05 13:43:22 +0900 - - Fix use of numbered parameter inside proc that is default value of optarg - - This allows cases such as: - - ```ruby - m ->(a = ->{@1}) {a} - m.call.call(1) - - m2 ->(a: ->{@1}) {a} - m2.call.call(2) - ``` - - Previously, this would cause a syntax error. - - [Bug#15789] - -commit 0c0ed1cee8aa8c538cc81f0daef26737eb2d5d0d - Author: Jeremy Evans - Date: 2019-05-05 13:43:22 +0900 - - Fix use of numbered parameter inside proc that is default value of optarg - - This allows cases such as: - - ```ruby - m ->(a = ->{@1}) {a} - m.call.call(1) - - m2 ->(a: ->{@1}) {a} - m2.call.call(2) - ``` - - Previously, this would cause a syntax error. - - [Bug#15789] - -commit b8f3be295b694964e88960c0228459b8aadd114a - Author: Jeremy Evans - Date: 2019-05-05 13:33:58 +0900 - - Fix a case where numbered parameters should not be allowed - - Because `proc{|| @1}` is a syntax error, the following should - also be syntax errors: - - ```ruby - proc { | - | @1} - ``` - - ```ruby - proc { |; a| @1 } - ``` - - This fixes both cases. - - [Bug #15825] - -commit 374c8f4ebab1a740990330c732b9de965c5e8d10 - Author: Nobuyoshi Nakada - Date: 2019-05-05 14:32:45 +0900 - - Fixed about ARGF.lineno - - [Bug #15823] - -commit 84e71e9fc1965d00013fea1bea1ce22aa7e7e619 - Author: git - Date: 2019-05-05 11:13:58 +0900 - - * 2019-05-05 - -commit f1b52d3a8889dbffddadd3e3ccf05fb9a90b18ee - Author: git - Date: 2019-05-05 11:13:54 +0900 - - * expand tabs. - -commit ff21e75d32e27a2b362ed53fb471828876b54418 - Author: Nobuyoshi Nakada - Date: 2018-07-28 00:07:56 +0900 - - parse.y: duplicated when clause warning - - * parse.y (case_args): moved "duplicated when clause" warning from - compile phase, so that `ruby -wc` shows them. - -commit 848edb03f8d3e5f5e97d3ea45fec592d87d73b05 - Author: Masatoshi SEKI - Date: 2019-05-04 22:52:25 +0900 - - ignore test_RangeError - -commit a380f4c2b7310c85635958c751ac78d7796bc8d2 - Author: Marcus Stollsteimer - Date: 2019-05-04 22:31:21 +0900 - - Fix typos, grammar, and style - -commit 8bf3040e301ffe82ab02df58c89bd1e55bb0980b - Author: Marcus Stollsteimer - Date: 2019-05-04 22:02:20 +0900 - - Fix grammar - -commit b9e52db28398c5a792ae16730243af764c869bcd - Author: Nobuyoshi Nakada - Date: 2019-05-04 22:00:22 +0900 - - Add a pathologic check - -commit 7d30cd47c4e9e27461d3906e5740daa02dac22ca - Author: git - Date: 2019-05-04 19:29:14 +0900 - - * remove trailing spaces. - -commit 8980b53a48b1f55e09c5223008225e6bfa765405 - Author: Masatoshi SEKI - Date: 2019-05-04 19:28:57 +0900 - - add DRb::WeakIdConv (Bug #15711) - -commit b72623012d74abdb06210153ed48c9e2fa075bbd - Author: Hiroshi SHIBATA - Date: 2019-05-04 06:23:25 +0900 - - Update broken URL in Float documentation. - - [Misc #15775][ruby-core:92332] - -commit a3cbce7822c680e62d000817c36fbdb5f62997d8 - Author: git - Date: 2019-05-04 00:00:01 +0900 - - * 2019-05-04 - -commit 04fd98d5963d45f69ff8239bd02392e550d67191 - Author: git - Date: 2019-05-03 23:59:58 +0900 - - * expand tabs. - -commit 77440e949bd69e6ed86d70026d238521adb8319a - Author: Nobuyoshi Nakada - Date: 2019-05-03 22:37:51 +0900 - - Improve performance of case-conversion methods - -commit 1f349ea297738f3a2c4914166746cea0e5ada031 - Author: Marcus Stollsteimer - Date: 2019-05-03 23:12:22 +0900 - - Fix typo - -commit 5776ae347540ac19c40d146a3566a806cd176bf1 - Author: Nobuyoshi Nakada - Date: 2019-05-03 15:33:59 +0900 - - UTF-8 is one of byte based encodings - -commit 58cd4b7bde1f03ddce41fdc8f30ebe3c75706e75 - Author: git - Date: 2019-05-03 06:26:18 +0900 - - * 2019-05-03 - -commit 7d02bab0b080bbf5f7dd3f29de57a52677e39a51 - Author: NAKAMURA Usaku - Date: 2019-05-03 06:24:57 +0900 - - Nil cannot and should not convert to a string - -commit 5c87bb3b90a6d77089314ed0e62e31654621efa9 - Author: git - Date: 2019-05-02 22:44:43 +0900 - - * expand tabs. - -commit 5e23b1138f16af0defb184d7deeffadfd2ce3c04 - Author: Nobuyoshi Nakada - Date: 2019-05-02 22:44:20 +0900 - - Fix potential memory leak - -commit d6efb386bab9ee3839cf17945ad810b03f28f129 - Author: git - Date: 2019-05-02 14:47:26 +0900 - - * 2019-05-02 - -commit a1ae478a31ffe4fd21c17f785f1827c031281be8 - Author: Kazuhiro NISHIYAMA - Date: 2019-05-02 14:44:47 +0900 - - Fix a typo - -commit 71952440adcbdd1ff51aea519bc14e8965b84ebf - Author: Nobuyoshi Nakada - Date: 2019-05-01 20:55:08 +0900 - - Silence a (probable) debug print - -commit 474af9ee9a4804d052e1e40503e1b6491d00a969 - Author: Nobuyoshi Nakada - Date: 2019-05-01 20:47:00 +0900 - - No last commit when up-to-date - - Get the last commit title from the upstream to the head, so that - no `last_commit` line will be shown when the branch is up to date - with the upstream. - -commit 2f0f9115d314d0fecbd0a9f5b5a6c59c611fa5e7 - Author: Nobuyoshi Nakada - Date: 2019-05-01 20:26:35 +0900 - - Ignore ChangeLog - -commit dcb6a6ae3e2b8a3e298e7f0d4a3e7f8ff102a30e - Author: NAKAMURA Usaku - Date: 2019-05-01 17:38:09 +0900 - - Windows simply causes an error to open invalid path - -commit fc3e80cf6d8847fd5a2313dd7e2079d268f1ec84 - Author: NARUSE, Yui - Date: 2019-05-01 01:06:13 +0900 - - guard include with has_feature - - clang's sanitizer/msan_interface.h has fallback macros. - It causes redefinition of __msan_unpoison(). - -commit 3de03544ff9fba80039460f2e2cd864010bf8cba - Author: aycabta - Date: 2019-05-01 00:45:54 +0900 - - Add Reline.delete_text that raises NotImplementedError - -commit c06821161ae9dcfebeabd30ec7ab598ee70c89ce - Author: git - Date: 2019-05-01 00:03:58 +0900 - - * 2019-05-01 - -commit 4e88e8692844a2a317bc19481f0f2601b6f00955 - Author: manga_osyo - Date: 2019-04-30 23:18:44 +0900 - - Add exception support in `Range#first`. - - Closes: https://github.com/ruby/ruby/pull/2163 - -commit 0eedec68673fa74960dec80b26659263ec3b6a9a - Author: Kazuhiro NISHIYAMA - Date: 2019-04-30 22:35:38 +0900 - - Change Accept-Encoding from `*` to `identity` - - When `Accept-Encoding` is `*`, - http://www.unicode.org/Public/12.1.0/ucd/ returns gzipped content now. - So set `identity`. - -commit dd942cd5b31947f6a514d4a916971011fbabc089 - Author: NAKAMURA Usaku - Date: 2019-04-30 22:24:45 +0900 - - Use redirect keyword arguments instead of ">" - -commit 50872f4a15a2070fa007c1d85fcf44802e4bcc0b - Author: Nobuyoshi Nakada - Date: 2019-04-30 22:23:20 +0900 - - Use array mode of `system` instead of `shellescape` - - `&.` is not available in ruby 2.0. - -commit df3de409325d1e95d375a736d2bc9c45d47ec317 - Author: Nobuyoshi Nakada - Date: 2019-04-30 22:13:47 +0900 - - String#[] with index to extract matched substring safely - -commit 1dd94dfba3ed3ffd087d1ba93154cb922033a37c - Author: NAKAMURA Usaku - Date: 2019-04-30 21:51:03 +0900 - - Must use IO::NULL instead of platform dependent filename - -commit 830e40ee05681a9230d523c1ca8b4bd3238fcfbf - Author: NAKAMURA Usaku - Date: 2019-04-30 19:45:44 +0900 - - Skip on Windows now when using reline because it causes hang of whole tests - -commit 5a83a1d55454d42cbf5b0bcc9df9c9c83e3a39d7 - Author: NAKAMURA Usaku - Date: 2019-04-30 18:01:17 +0900 - - **Must** use IO::NULL for null device - -commit c222f4d31fc5f0566fa969d8fbb948f8841daf94 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-30 16:18:45 +0900 - - `from` is not nil but `""` on shallow clone [ci skip] - -commit 151b7d72bd26f9676c92b69f6b4710af3cb7ea65 - Author: NAKAMURA Usaku - Date: 2019-04-30 15:02:03 +0900 - - Forgotten to remove - -commit 94b740b2499242e1aca67f7bbf595e75e63abc40 - Author: aycabta - Date: 2019-04-28 03:41:06 +0900 - - Use Ripper for IRB - - The debug option of IRB is deleted because it's just for IRB's pure Ruby - parser. - -commit 567cb1ae1d25b837bed6e91af1418c6a4f25cc90 - Author: aycabta - Date: 2019-04-30 12:52:48 +0900 - - Use Encoding::UTF_8 if RELINE_TEST_ENCODING doesn't exist - -commit 3be5907e734f9c88af577bb0b0e8ec2d66b7b2f7 - Author: aycabta - Date: 2019-04-30 12:47:40 +0900 - - Move Win32API to Reline::Win32API - -commit 319eee0f4a13d29a82eeffa348b8a3b5685e2f6e - Author: aycabta - Date: 2019-04-30 12:27:23 +0900 - - Use Encoding::UTF_8 if Encoding.default_external is Encoding::IBM437 - -commit 17350c7e5534c8678097d70698fe08614a6c3997 - Author: aycabta - Date: 2019-04-27 14:53:09 +0900 - - Add Reline as a fallback library for Readline - - * lib/reine.rb, lib/reline/*: Reline is a readline stdlib compatible - library. - * lib/readline.rb: Readline uses a fallback to Reline when ext/readline - doesn't exist. - * tool/sync_default_gems.rb: add ruby/reline as a default gem. - * appveyor.yml: add "set RELINE_TEST_ENCODING=Windows-31J" for test suit - of Reline, and add "--exclude readline" to "nmake test-all" on Visual - Studio builds because of strange behavior. - * spec/ruby/library/readline/spec_helper.rb: skip Reline as with - RbReadline. - -commit eb45ba61160dbae412407f232fe9b3252eb99362 - Author: NAKAMURA Usaku - Date: 2019-04-30 04:09:25 +0900 - - Skip the spec on Windows because RUBY_EXE is RUNRUBY and it calls ruby as grandchild - -commit 320f0aba49d17737ef965fc8c5f565dad96f514c - Author: NAKAMURA Usaku - Date: 2019-04-30 04:09:07 +0900 - - Revert previous commit; it was meaningless - -commit ae3a9862048135f846f694b98031cf264889580f - Author: git - Date: 2019-04-30 03:33:51 +0900 - - * expand tabs. - -commit 09022b6d70ad16737964e58db039aac00a1488ea - Author: NAKAMURA Usaku - Date: 2019-04-30 03:32:41 +0900 - - Use CreateToolhelp32Snapshot instead of NtQueryInformationProcess to get ppid on Windows - - Try to get rid of a spec error. - -commit b7d9ec8caa4fb9d279df22f82fe28777a98fa37e - Author: git - Date: 2019-04-30 00:28:44 +0900 - - * 2019-04-30 - -commit 7a34d8902ad93c0e487623cd99e6c23296a7a768 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-30 00:28:00 +0900 - - Merge .time - -commit 040b37f8b4b8d0a4931ee9b7c15b57f9f918639a - Author: Kazuhiro NISHIYAMA - Date: 2019-04-29 23:02:18 +0900 - - Use 10 chars as RUBY_REVISION in snapshot too - -commit f95f07dad30a80b7e3eb4b2838ca4311d2822764 - Author: Urabe, Shyouhei - Date: 2019-04-26 18:59:26 +0900 - - avoid passing NULL to memset - - `GC::Profiler.enable; GC::Profiler.clear` tries to clear - objspace->profile.records but it has never been allocated before. - Thus the MEMCPY took NULL argument before this changeset. - - The objspace->profile.records is allocated appropriately elsewhere. - Why not juts free it if any? That should work. - -commit 34e1079aef81d108890fb167d7df69960e994ff5 - Author: Urabe, Shyouhei - Date: 2019-04-26 18:37:21 +0900 - - glibc says memcpy cannot take NULL - - At least since 2004, glibc's annotates memcpy as - __attribute__((__nonnull__)). This basedir is passed to it. When - LOAD_RELATIVE is not defined and MJIT_SEARCH_BUILD_DIR is not set, - this variable is never updated. Should initialize with meaningful - default value. - -commit e7b18ca6d9b45b7e71694557b9fab8152c62c1ed - Author: Urabe, Shyouhei - Date: 2019-04-26 18:01:24 +0900 - - glibc says memcpy cannot take NULL - - At least since 2004, glibc's annotates memcpy as - __attribute__((__nonnull__)). On the other hand the argv here, - which is passed from rb_funcallv, may be NULL. Practically this - should never be a serious problem but for maximum safety, let's - avoid passing NULL here. - -commit a116f04ccabe8ce7d0e7312ef0f55f6a2cdd178e - Author: Urabe, Shyouhei - Date: 2019-04-26 17:28:43 +0900 - - suppress some UBSAN sanitizers - - They are not "undefined". UBSAN reports them because it thinks - they are "often unintentional". We see the report rather annoying. - -commit f4c68640d679c3786c19f3503c76112312636c37 - Author: Urabe, Shyouhei - Date: 2019-04-26 17:01:20 +0900 - - this variable is not guaranteed aligned - - No problem for unaligned-ness because we never dereference. - -commit 7c0f513e97828dd8274695a49bde92c326b208cb - Author: Urabe, Shyouhei - Date: 2019-04-26 17:00:58 +0900 - - fix typo - -commit 6a3165e19dfa21babfb2ef1f1c20c9930410b0ec - Author: Nobuyoshi Nakada - Date: 2019-04-29 18:32:21 +0900 - - Fixed HERETERM_LENGTH_MAX on IL32LLP64 - -commit c7f780c155ac553aa026e6caf4b1c88ff988adde - Author: Nobuyoshi Nakada - Date: 2019-04-29 15:57:40 +0900 - - Refactored rb_strterm_heredoc_t - -commit 1432471a759dc0cbc80c53766894dba45e6da887 - Author: Nobuyoshi Nakada - Date: 2019-04-29 13:45:32 +0900 - - Disallow also CR in here-doc identifier - - * parse.y (heredoc_identifier): CR in here-document identifier - might or might not result in a syntax error, by the EOL code. - make a syntax error regardless of the EOL code. - -commit 23375c8b81e07644517e5ad985b2fbf5e1b5d545 - Author: Nobuyoshi Nakada - Date: 2019-04-29 13:42:50 +0900 - - Make only `mesg` can be assigned with default `fname` - -commit 330b376133e00ae418bcf01e641e127df01fbc28 - Author: Nobuyoshi Nakada - Date: 2019-04-29 00:24:26 +0900 - - parse.y: fix here-doc identifier with newline - - * parse.y (heredoc_identifier): quoted here-document identifier - must end within the same line. - - the only corner case that here-document identifier can contain a - newline is that the closing quote is placed at the beginning of - the next line, and has been warned since 2.4. - - ```ruby - <<"EOS - " # warning: here document identifier ends with a newline - EOS - ``` - -commit 69cad44facc4dedfe181c6a669b63fb9da2aa673 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-29 12:19:07 +0900 - - Reduce debug output - - because I found machine clock problem - see r67347 - https://travis-ci.org/ruby/ruby/jobs/525784924 - https://travis-ci.community/t/mtime-of-source-codes-are-sometimes-newer-than-build-time-clock-skew/3215 - -commit 812a438145a604e1361d4bf07cc3d81452cfb0ec - Author: Nobuyoshi Nakada - Date: 2019-04-29 11:31:18 +0900 - - iseq.c: removed unnecessary zero-fills - -commit 6033423d6882546e132a450ab9efc66507879594 - Author: Nobuyoshi Nakada - Date: 2019-04-29 10:11:44 +0900 - - NEWS: Moved "Integer#[] with range" to "Core classes updates" - -commit daa0874056f602cbc99cab5ddfe3e590194f9bca - Author: Benoit Daloze - Date: 2019-04-29 06:29:10 +0900 - - CLOCK_MONOTONIC_RAW_APPROX seems less precise than advertised on macOS - - * https://travis-ci.org/ruby/ruby/builds/525651487 - -commit 79671ec57e59091260a0bc3d40a31d31d9c72a94 - Author: Benoit Daloze - Date: 2019-04-29 06:20:11 +0900 - - Update to ruby/spec@7de852d - -commit 994833085ae06afbe94d30ab183d80e0234fbe14 - Author: Benoit Daloze - Date: 2019-04-29 06:20:09 +0900 - - Update to ruby/mspec@c25d63d - -commit bbb93608a385242da93bc5256a90a6376981d86f - Author: Benoit Daloze - Date: 2019-04-29 06:16:03 +0900 - - Move the check for CentOS CLOCK_MONOTONIC_RAW next to others - - * Fixes "No behavior expectation was found in the example" - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos6/ruby-trunk/log/20190428T093004Z.fail.html.gz - -commit dfc0eeb0cfb22efde6369f275d3a28c29144d9a6 - Author: Takashi Kokubun - Date: 2019-04-29 01:22:28 +0900 - - Fully support Git in tool/merger.rb - - as both backport source repository and backport destination repository. - -commit f0776e3203b55b698971a2d2b0acc48cb3a0940e - Author: Kazuhiro NISHIYAMA - Date: 2019-04-29 01:23:09 +0900 - - Add more debug print for random CI failure on osx Travis - - and remove `git status` with noisy rvm trace log - - see r67347 - -commit 50cbb21ba533f67e29d7da0975ba186f9e3da93f - Author: Yusuke Endoh - Date: 2019-04-29 01:17:27 +0900 - - Add "Integer#[] with range" to NEWS - -commit 75260d36b591a6c9c6f183648434b3c1026e1cd8 - Author: git - Date: 2019-04-29 01:00:20 +0900 - - * remove trailing spaces. - -commit 991e32681eac3c675ef796f5691a6786e99c3fb0 - Author: Takashi Kokubun - Date: 2019-04-29 00:57:34 +0900 - - tool/merger.rb: Avoid making too-deep indentation - - because it's hard to understand what's going on when indentation depth - is too deep. - - Sorry for polluting git blame, but most of the Merger's lines are - updated recently anyway. - -commit 2dddd370a17a33177f0898986ea2b37eabd07f31 - Author: Takashi Kokubun - Date: 2019-04-29 00:53:06 +0900 - - Support `tool/merger.rb removetag` under Git - - repository. - -commit bbad0d05b3e42909da297db06d632d2102122f65 - Author: git - Date: 2019-04-29 00:22:48 +0900 - - * 2019-04-29 - -commit fad2825e42d80145ca7047f840b9b0cea00d0ca9 - Author: Takashi Kokubun - Date: 2019-04-28 23:51:43 +0900 - - Support `tool/merger.rb tag` under Git repository - -commit 555d1dda71a3cd1ac954c4d41d523562721cde8d - Author: git - Date: 2019-04-28 23:42:46 +0900 - - * expand tabs. - -commit 6bedbf462544a7917fdc8d8c44276079a6e156cf - Author: Yusuke Endoh - Date: 2019-04-28 23:24:09 +0900 - - numeric.c: Extend Integer#[] to support range arguments - - ```` - 0b01001101[2, 4] #=> 0b0011 - 0b01001100[2..5] #=> 0b0011 - 0b01001100[2...6] #=> 0b0011 - ^^^^ - ```` - - [Feature #8842] - -commit cb550246136b90a63b4f75f5e7cfaccb9da08eda - Author: Yusuke Endoh - Date: 2019-04-28 23:23:00 +0900 - - test/ruby/test_integer.rb: Add a sane test for Integer#[] - -commit 3bc810334c776bb68bddeeced9bd91f918c8581f - Author: Takashi Kokubun - Date: 2019-04-28 22:36:23 +0900 - - Support `tool/merger.rb up` under Git repository - - updating indentation (and slightly changing styles) for areas already - supporting Git. - -commit d906dd87b049e84fc9a17b89a74fdd52d40c5fbb - Author: Benoit Daloze - Date: 2019-04-28 22:23:12 +0900 - - Skip CLOCK_UPTIME_RAW_APPROX since it seems less precise than advertised on macOS - - * See https://travis-ci.org/ruby/ruby/jobs/525595997 - -commit 392d84b4900eb954fdfcf11c2a63dd4c029996f4 - Author: Takashi Kokubun - Date: 2019-04-28 22:14:55 +0900 - - Fix wrong svn options - - for SVN as a backport source. - - This was a mistake in de5378233b2ff5434f024ac66285e699794a321d... - -commit 1c8cefca310d12cf4ae475eeacec73bf1f5ae7c3 - Author: Takashi Kokubun - Date: 2019-04-28 22:02:09 +0900 - - Stop using global variable for repos - - to avoid having impact from other places. - -commit 9426da83c60eca84197e9fcf67dc9c7c12ad3d2e - Author: Benoit Daloze - Date: 2019-04-28 21:59:14 +0900 - - Exclude failing Process.clock_getres specs on AIX - -commit a27f7e499c66e5f09d5159c33c72834f14ec5aac - Author: Benoit Daloze - Date: 2019-04-28 21:54:42 +0900 - - Add missing platform guard - -commit 9a0dbb341442fc0d203a5cd6fb46250e429e9188 - Author: Benoit Daloze - Date: 2019-04-28 21:52:55 +0900 - - Skip problematic Process.clock_getres specs on ARM - - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-trunk/log/20190428T051708Z.fail.html.gz - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-ad7f67/ruby-trunk/log/20190428T045405Z.fail.html.gz - -commit cb8eb37377289a3874742af290bcd32dd09910bf - Author: Takashi Kokubun - Date: 2019-04-28 21:53:57 +0900 - - Now tool/merger.rb may use Git [ci skip] - -commit f2d7ba6a7473b408002c90b77b021fc837f93561 - Author: Takashi Kokubun - Date: 2019-04-28 21:51:35 +0900 - - make sync-default-gems GEM=irb - - from https://github.com/ruby/irb/commit/e8e79d569ed59fe4ed4fbca968917ce799f02a5e. - - This colorizes Range object on IRB inspect. - -commit 13abf5519a8c00ac2b05409e667c58f05c75123a - Author: Benoit Daloze - Date: 2019-04-28 21:39:37 +0900 - - Workaround a CentOS bug in Process.clock_getres specs - -commit 14965c5f4b0160d22febd94f258b2ba1491a585e - Author: Takashi Kokubun - Date: 2019-04-28 21:40:37 +0900 - - Drop SVN-specific method from Merger module - - to clarify it's not needed for Git support. - -commit fcb18755135982320900c45baa45bd4ba0029e07 - Author: Takashi Kokubun - Date: 2019-04-28 21:16:20 +0900 - - Make Merger.version private to the module - - because it's not used outside the Module. - -commit 16695af0ef13c709846a18ae9d186642445fae5f - Author: Benoit Daloze - Date: 2019-04-28 21:36:03 +0900 - - Refactor logic in Process.clock_gettime spec - -commit fc37a045a0b2cf02a77109eb87b01d8b82d5c15d - Author: Benoit Daloze - Date: 2019-04-28 21:35:17 +0900 - - Fix typo in spec - -commit d835ed4df1ae2bf317db41a8009b1fad143c94f1 - Author: Takashi Kokubun - Date: 2019-04-28 21:02:01 +0900 - - Define merger.rb's methods under Merger namespace - - so that we do not monkey-patch all classes by defining methods on - top-level (Object class). - - Not arranging indentation in it to keep `git blame` for now. - -commit 8711f77a26078b80eb954e0bc873418cf733eff5 - Author: Takashi Kokubun - Date: 2019-04-28 20:33:12 +0900 - - make sync-default-gems GEM=irb - - from https://github.com/ruby/irb/commit/96f05e726879e9858eb015c8d043c9f52b864ff9. - - Just syncing newer test changes so that conflicts do not happen when trunk is - modified and we need to backport that to ruby/irb. - -commit 588f212c2665555f76c68e0954332619bff60418 - Author: Takashi Kokubun - Date: 2019-04-28 20:18:44 +0900 - - make sync-default-gems GEM=irb - - from https://github.com/ruby/irb/commit/44301d382794d91e2caa16dd4efe62439e0041d8. - - This includes some fixes for string interpolation highlight fixes. - -commit 4d8ad48f7dc610f58150daf92a859ed53fdd3a6c - Author: Takashi Kokubun - Date: 2019-04-28 19:33:41 +0900 - - Support git as redmine-backporter's done destination - -commit 5d24fba544352a32fdd4e06fa25dc0625c6860f1 - Author: Benoit Daloze - Date: 2019-04-28 19:37:29 +0900 - - Skip the entire Process.clock_getres spec on FreeBSD - - * Clocks don't match the reported precision. - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd11zfs/ruby-trunk/log/20190428T093003Z.fail.html.gz - -commit f40458e9dda3298df12f5b602f02afd4dfae334b - Author: Takashi Kokubun - Date: 2019-04-28 14:10:08 +0900 - - Specify VM_CHECK_MODE explicitly - - In my understanding, `VM_CHECK_MODE` should be Integer and I'm not sure - how `-DVM_CHECK_MODE` would behave. To make the matters simple, let me - pass the mode explicitly. - -commit 766293fc490b6812739e837554dd5d8e703d352c - Author: Takashi Kokubun - Date: 2019-04-28 14:04:48 +0900 - - Ruby 2.3 is EOL - -commit 4c8f1078985613ea1015fe1a1cdbe9944528cb35 - Author: Nobuyoshi Nakada - Date: 2019-04-28 12:16:40 +0900 - - Make the range to export as changelog optional - - * `from` is defaulted to the beginning of the branch inclusively, - otherwise the given revision is excluded as the previous. - - * `to` is defaulted to the head. - -commit d72bd190a80e6b8258ca923b606175754a210b6d - Author: Nobuyoshi Nakada - Date: 2019-04-28 12:11:59 +0900 - - Added VCS::SVN#branch_beginning - -commit b7669705270478f14d02f15b51b74eeec52a49da - Author: Nobuyoshi Nakada - Date: 2019-04-28 12:04:15 +0900 - - Search the beginning revision more strictly a bit - -commit fdcd640507ab2600dfa96f4962eba2702acfc264 - Author: Nobuyoshi Nakada - Date: 2019-04-28 11:35:14 +0900 - - Makefiles need to be indented by tabs - -commit 5a53682d6dede337b81f944edc76b1a5e1243adc - Author: Nobuyoshi Nakada - Date: 2019-04-28 11:31:36 +0900 - - Removed `--reverse` option - - It is nonsense with `-n1` option. - -commit d0a54673202458455244f79ed212a97727f0c7c7 - Author: David Rodríguez - Date: 2019-04-26 20:26:21 +0900 - - Update rubygems with latest upstream changes - - Closes: https://github.com/ruby/ruby/pull/2154 - -commit a15f7dd1fb1148c3d586238ee6907875f2e40379 - Author: Jeremy Evans - Date: 2019-04-28 02:05:26 +0900 - - Always mark the string returned by File.realpath as tainted - - This string can include elements that were not in either string - passed to File.realpath, even if one of the strings is an - absolute path, due to symlinks: - - ```ruby - Dir.mkdir('b') unless File.directory?('b') - File.write('b/a', '') unless File.file?('b/a') - File.symlink('b', 'c') unless File.symlink?('c') - path = File.realpath('c/a'.untaint, Dir.pwd.untaint) - path # "/home/testr/ruby/b/a" - path.tainted? # should be true, as 'b' comes from file system - ``` - - [Bug #15803] - -commit d47cd75b4fead0cfc5fdb59c48d5d822ffe3382d - Author: Nobuyoshi Nakada - Date: 2019-04-28 10:41:11 +0900 - - Chomp a newline from the branch name - -commit 7790b610b8c11ae987e0f9a936418a7a34a8af0b - Author: Nobuyoshi Nakada - Date: 2019-04-28 02:00:39 +0900 - - Shorten git revision name without "r" prefix in snapshot - -commit 2c283655a650a7e97aaf36992d1d60c314403b7a - Author: Benoit Daloze - Date: 2019-04-28 06:43:58 +0900 - - Some Solaris versions seem to only provide millisecond accuracy for CLOCK_REALTIME - - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-trunk/log/20190427T182404Z.fail.html.gz - -commit b7c301569df2eaee3a2785e5ec56f8c53fbc9fea - Author: Benoit Daloze - Date: 2019-04-28 06:42:31 +0900 - - Skip clock_getres spec on BSD - - * clock_getres() seems to be incorrect on BSD: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd11zfs/ruby-trunk/log/20190427T183003Z.fail.html.gz - -commit 0d227d1ce6aa01b0f6db06bbbf828acb962d4734 - Author: Benoit Daloze - Date: 2019-04-28 02:42:54 +0900 - - Try to more accurately reflect MRI's logic in specs for finding the home if $HOME is unset - -commit 5b93321064e83ea180492469071189372e8289e8 - Author: Benoit Daloze - Date: 2019-04-28 02:23:45 +0900 - - Update to ruby/spec@14e6148 - -commit 14f004d3962f799ae2caca7d6a82f508e51270bc - Author: Takashi Kokubun - Date: 2019-04-28 02:17:49 +0900 - - Isolate test_gc_compact on AppVeyor mswin as well - - because it makes the CI unstable - https://ci.appveyor.com/project/ruby/ruby/builds/24143365/job/yrx7b8ce2qg9wro2 - -commit ed4f33187976ebbbe4d3eb83dceea1992e9f6a16 - Author: git - Date: 2019-04-28 02:02:30 +0900 - - * remove trailing spaces. - -commit cae0b73214d721539e335babf02283799198a983 - Author: Takashi Kokubun - Date: 2019-04-28 02:01:01 +0900 - - make sync-default-gems GEM=irb - - from https://github.com/ruby/irb/commit/89e9add06da3fd5f9ce91a2f5fa0b0190aa5d42f. - - This adds syntax highlight support for Module on inspect. - - In addition to that, I'm adding a trailing space in test_color.rb for - testing ruby-commit-hook's auto-style. - -commit a1b4816759418ca8fe510e8739622fc5d77ab0f0 - Author: Benoit Daloze - Date: 2019-04-28 01:53:23 +0900 - - Update to ruby/spec@15c9619 - -commit 00c33d9c232ed1a79eda17acd7231ac93caa162b - Author: Benoit Daloze - Date: 2019-04-28 01:53:20 +0900 - - Update to ruby/mspec@18c5a7d - -commit 80be9e986b81d1e50433005f6b91f4cd0c1c0939 - Author: git - Date: 2019-04-28 01:25:10 +0900 - - * 2019-04-28 - -commit bb6036946ef7337c8bef6380ba394c082d5452cb - Author: Nobuyoshi Nakada - Date: 2019-04-28 00:30:16 +0900 - - Reduce matz's work, let git do it instead - -commit 87d2a2df1b40016401a2f6dfc98e46880bbd18fd - Author: Benoit Daloze - Date: 2019-04-27 23:43:28 +0900 - - Improve documentation of Array.try_convert - - * Mostly to try the new git repository. - -commit 429fdf3de22690371b98590c4c1d6a53adbbfc26 - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:27:12 +0900 - - Added ChangeLog marker for the beginning of 2.7.0 - -commit db614dbf6d8c7f6e9ed315cd979500b131a5cc26 - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:25:48 +0900 - - Support git-log format ChangeLog - -commit 2a4625115a2020dd55f952bdb176ab30405e19b9 - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:14:59 +0900 - - Separate format_changelog - - VCS::GITSVN#format_changelog generates previous format, similar to - svn-log, and VCS::GIT#format_changelog stores just git-log as-is - for now. - -commit 7875c42f64e8656eb18262da65816a72375bf5f2 - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:13:03 +0900 - - Override log format to parse for ChangeLog - -commit 6f8ac2cb28f99a4b2588c59ec44eff6ed38c4d3b - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:08:50 +0900 - - Include the beginning commit in ChangeLog - -commit af1e487e9bb763b939dc6704c9a343c9eafa1637 - Author: Nobuyoshi Nakada - Date: 2019-04-27 23:05:05 +0900 - - Updated marked commits for ChangeLog - -commit 3067370f611b16955a8064116092e5f0f9f126a7 - Author: Takashi Kokubun - Date: 2019-04-27 22:21:34 +0900 - - Retry downloads more for unicode outage - - like https://ci.appveyor.com/project/ruby/ruby/builds/24142523/job/v6aq4srj7c3hgt86 - -commit 9348643575d7a744f3e404d9069a0d29f97960a0 - Author: Takashi Kokubun - Date: 2019-04-27 22:01:10 +0900 - - make sync-default-gems GEM=irb - - Synced from https://github.com/ruby/irb/commit/5feb361ed80736efa5b2c2b629837ec2a5fc2cdb. - This includes a support to colorize named Class instance on IRB inspect. - -commit 3f9562015e651735bfc2fdd14e8f6963b673e22a - Author: Nobuyoshi Nakada - Date: 2019-04-27 21:21:55 +0900 - - Get rid of indirect sharing - - * string.c (str_duplicate): share the root shared string if the - original string is already sharing, so that all shared strings - refer the root shared string directly. indirect sharing can - cause a dangling pointer. - - [Bug #15792] - -commit afb361dfd0811f96f601d8d6492f9e1a0321ea01 - Author: Takashi Kokubun - Date: 2019-04-27 20:15:07 +0900 - - Isolate test_gc_compact on msys2 AppVeyor - - as it's unstable on the environment - https://ci.appveyor.com/project/ruby/ruby/builds/24138134/job/i7e441u7se11w7ey - -commit bc01f7b7211b96b258fc6586789ce9875c079a7d - Author: Kazuki Tsujimoto - Date: 2019-04-27 12:55:32 +0900 - - Fix description of NODE_IN - -commit 7fe04850d21db1e17508fb8c05fd78fc079a71c6 - Author: okuramasafumi - Date: 2019-04-27 11:18:25 +0900 - - Add class ref to `UnboundMethod#owner` doc - - It refers to `Method#receiver` in the doc, but - there's no class reference in current doc. - Some tools automatically make it a link so it's useful. - - Closes: https://github.com/ruby/ruby/pull/2156 - -commit ecf660e438320f501ce4e05e92a5d6c79fe4d54d - Author: James Clarke - Date: 2019-04-27 07:32:46 +0900 - - ia64: Don't clear register_stack_start - - r59829 stopped clearing stack_start and enabled the code for - !FIBER_USE_NATIVE, but we need to do the same for register_stack_start - on ia64, otherwise we end up with NULL in cont_save_machine_stack. - - Closes: https://github.com/ruby/ruby/pull/2155 - -commit 5f6ba669ff79819e0e2cf006ed22f960d4565543 - Author: Takashi Kokubun - Date: 2019-04-27 12:28:00 +0900 - - Isolate TestGCCompact from JIT testing - - Wercker seems to randomly fail - https://app.wercker.com/ruby/ruby/runs/mjit-test1/5cc3c1c423fcb70008db9b64?step=5cc3c46a03f4460007da0659 - - To help debugging, let me isolate the impact from GC.compact in the JIT - testing on Wercker. - -commit 48313f129abd464c69853a66af22adbad260b82e - Author: Kazuhiro NISHIYAMA - Date: 2019-04-27 12:21:35 +0900 - - Add `or nil` to call-seq of `Enumerator::ArithmeticSequence#begin` - - ``` - % ruby -ve 'p (nil..).first' - ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18] - nil - % ruby -ve 'p (nil..).begin' - ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18] - nil - ``` - -commit be8cf0d4f672c6061c38c06a7d5d1ee909fc124b - Author: Kazuki Tsujimoto - Date: 2019-04-27 12:09:48 +0900 - - Update NEWS for pattern matching [ci skip] - -commit baad9e8a1c5b54d5728ce48d36726ed78754285f - Author: Takashi Kokubun - Date: 2019-04-27 12:08:48 +0900 - - NEWS: Note about $TERM requirement [ci skip] - -commit 569c1ef6f17ad12012ba85c443c6806b9d0a9da5 - Author: Takashi Kokubun - Date: 2019-04-27 11:42:38 +0900 - - make sync-default-gems GEM=irb - - Backport changes from ruby/irb. - -commit 782e48726082ee130b6ce27f2a21d33257f09d71 - Author: naruse - Date: 2019-04-21 14:48:35 +0900 - - suppress warning in test/irb - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos7/ruby-trunk/log/20190421T040003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - - Re-committing https://github.com/ruby/ruby/commit/7f09b5e9da8f83f84c5b6ae7a644a562811fec73 - -commit a2219e687e07fb7e3b9b6dce8e68210fd3a516f9 - Author: git - Date: 2019-04-27 09:17:50 +0900 - - * 2019-04-27 - -commit c8b675adb902a67bf62a1a9945bade7c8becc4e8 - Author: naruse - Date: 2019-04-21 14:48:35 +0900 - - suppress redefinition warnings - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67679 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8990779d3693b106fbca014518726ba53224f731 - Author: nobu - Date: 2019-01-18 18:52:50 +0900 - - Prefer block_given? to iterator? - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66866 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e804fcb42c56d5a4ff31df0391accaf5ede8c26e - Author: Nobuyoshi Nakada - Date: 2019-04-26 18:53:36 +0900 - - Fix rdoc in 52cfb17086 - -commit a429b3601f5dea7e3f7019733afffe64df583f34 - Author: Takashi Kokubun - Date: 2019-04-26 18:46:43 +0900 - - Revert "Class instance should be also colorable on IRB" - - This reverts commit 6669c966d2744f21315047d1725ad4494d15b8ba. - - It seems to make tests fail... let me fix this later. - -commit 6669c966d2744f21315047d1725ad4494d15b8ba - Author: Takashi Kokubun - Date: 2019-04-26 18:42:50 +0900 - - Class instance should be also colorable on IRB - - inspect. - - Change is made with: `$ make -C .ruby sync-default-gems GEM=irb` - -commit 52cfb17086998b9434c9c786bfcf827197216c9a - Author: Takashi Kokubun - Date: 2019-04-26 18:28:54 +0900 - - make sync-default-gems GEM=irb - - from https://github.com/ruby/irb/commit/e6739d8c66dc78562930adb0b96935c9b38acf74 - -commit a6805771ec202a8b8586d6624b05342029cace0d - Author: Takashi Kokubun - Date: 2019-04-26 18:25:54 +0900 - - Define `make sync-default-gems` - - to run tool/sync_default_gems.rb - -commit a93f55569950b714a3d1235e59ad0a7d5b88f938 - Author: Takashi Kokubun - Date: 2019-04-26 18:18:09 +0900 - - tool/sync_default_gems.rb: Check prerequisites - -commit 1cef6a0c0c996ab87ef41dfeede3203ee3c811dc - Author: Kazuhiro NISHIYAMA - Date: 2019-04-26 17:47:09 +0900 - - Add more debug print for random CI failure on osx Travis - - see r67347 - -commit 0523b02f481150d60fc0803689d0919ee22923e9 - Author: Urabe, Shyouhei - Date: 2019-04-26 14:33:44 +0900 - - yaml cannot deep-merge arrays - - The configuration cannot but be written here and there.... - -commit 267ac0624dad6be5c3f4760f691258ae7dc83861 - Author: Urabe, Shyouhei - Date: 2019-04-26 13:35:08 +0900 - - make test needs no gems - -commit d700a8a0eb5f0a17d689216b5944ab6e39f1d55e - Author: Urabe, Shyouhei - Date: 2019-04-26 13:32:55 +0900 - - update travis clang - - Seems clang-7 has false-positives around memory sanitizer. - - This line should not be reported because the memory region is - correctly unpoisoned beforehand: - https://travis-ci.org/ruby/ruby/jobs/524766381 - - Clang 8 seems to fix it. - -commit 3175c54cb6d0684cf5a9346838a91756db33e54e - Author: Urabe, Shyouhei - Date: 2019-04-26 11:58:43 +0900 - - new travis setting to enable assertions - -commit 2a49a4795679e17613435544766b127ebe31b6d3 - Author: Urabe, Shyouhei - Date: 2019-04-26 11:33:40 +0900 - - sanitizer compiler flag update - -commit 7b7043e5da8589e01b94575d4ed647e909e5c875 - Author: Urabe, Shyouhei - Date: 2019-04-25 15:50:47 +0900 - - eliminate use of freed memory - - rb_io_fptr_finalize_internal frees the memory region. - - ================================================================= - ==85264==ERROR: AddressSanitizer: heap-use-after-free on address 0x610000000d8c at pc 0x5608e38077f7 bp 0x7ffee12d5440 sp 0x7ffee12d5438 - READ of size 4 at 0x610000000d8c thread T0 - #0 0x5608e38077f6 in rb_io_memsize io.c:4749:24 - #1 0x5608e37a0481 in obj_memsize_of gc.c:3547:14 - #2 0x5608e37a4f30 in check_rvalue_consistency gc.c:1107:2 - #3 0x5608e37a2624 in RVALUE_OLD_P gc.c:1218:5 - #4 0x5608e37a5bae in rb_gc_force_recycle gc.c:6652:18 - #5 0x5608e38191f9 in rb_f_backquote io.c:9021:5 - #6 0x5608e3d8aa14 in call_cfunc_1 vm_insnhelper.c:2058:12 - #7 0x5608e3d6e23d in vm_call_cfunc_with_frame vm_insnhelper.c:2211:11 - #8 0x5608e3d54a35 in vm_call_cfunc vm_insnhelper.c:2229:12 - #9 0x5608e3d5253b in vm_call_method_each_type vm_insnhelper.c:2564:9 - #10 0x5608e3d51f50 in vm_call_method vm_insnhelper.c:2701:13 - #11 0x5608e3cf2de4 in vm_call_general vm_insnhelper.c:2734:12 - #12 0x5608e3d79918 in vm_sendish vm_insnhelper.c:3627:11 - #13 0x5608e3d06cf5 in vm_exec_core insns.def:789:11 - #14 0x5608e3d43700 in rb_vm_exec vm.c:1892:22 - #15 0x5608e3d47cbf in rb_iseq_eval_main vm.c:2151:11 - #16 0x5608e37620ca in ruby_exec_internal eval.c:262:2 - #17 0x5608e376198b in ruby_exec_node eval.c:326:12 - #18 0x5608e37617d0 in ruby_run_node eval.c:318:25 - #19 0x5608e35c9486 in main main.c:42:9 - #20 0x7f62e9421b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 - #21 0x5608e3522289 in _start (miniruby+0x15f289) - - 0x610000000d8c is located 76 bytes inside of 192-byte region [0x610000000d40,0x610000000e00) - freed by thread T0 here: - #0 0x5608e359a2ed in free (miniruby+0x1d72ed) - #1 0x5608e37af421 in objspace_xfree gc.c:9591:5 - #2 0x5608e37af3da in ruby_sized_xfree gc.c:9687:2 - #3 0x5608e3799ac8 in ruby_xfree gc.c:9694:5 - #4 0x5608e380746d in rb_io_fptr_finalize_internal io.c:4728:5 - #5 0x5608e38191ed in rb_f_backquote io.c:9020:5 - #6 0x5608e3d8aa14 in call_cfunc_1 vm_insnhelper.c:2058:12 - #7 0x5608e3d6e23d in vm_call_cfunc_with_frame vm_insnhelper.c:2211:11 - #8 0x5608e3d54a35 in vm_call_cfunc vm_insnhelper.c:2229:12 - #9 0x5608e3d5253b in vm_call_method_each_type vm_insnhelper.c:2564:9 - #10 0x5608e3d51f50 in vm_call_method vm_insnhelper.c:2701:13 - #11 0x5608e3cf2de4 in vm_call_general vm_insnhelper.c:2734:12 - #12 0x5608e3d79918 in vm_sendish vm_insnhelper.c:3627:11 - #13 0x5608e3d06cf5 in vm_exec_core insns.def:789:11 - #14 0x5608e3d43700 in rb_vm_exec vm.c:1892:22 - #15 0x5608e3d47cbf in rb_iseq_eval_main vm.c:2151:11 - #16 0x5608e37620ca in ruby_exec_internal eval.c:262:2 - #17 0x5608e376198b in ruby_exec_node eval.c:326:12 - #18 0x5608e37617d0 in ruby_run_node eval.c:318:25 - #19 0x5608e35c9486 in main main.c:42:9 - #20 0x7f62e9421b96 in __libc_start_main - /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 - - previously allocated by thread T0 here: - #0 0x5608e359a56d in malloc (miniruby+0x1d756d) - #1 0x5608e37aed12 in objspace_xmalloc0 gc.c:9416:5 - #2 0x5608e37aebe7 in ruby_xmalloc0 gc.c:9600:12 - #3 0x5608e37aea8b in ruby_xmalloc_body gc.c:9609:12 - #4 0x5608e37a6d64 in ruby_xmalloc gc.c:11469:12 - #5 0x5608e380e4b4 in rb_io_fptr_new io.c:8040:19 - #6 0x5608e380e446 in rb_io_make_open_file io.c:8077:10 - #7 0x5608e3850ea0 in pipe_open io.c:6707:5 - #8 0x5608e384edb4 in pipe_open_s io.c:6772:12 - #9 0x5608e381910b in rb_f_backquote io.c:9014:12 - #10 0x5608e3d8aa14 in call_cfunc_1 vm_insnhelper.c:2058:12 - #11 0x5608e3d6e23d in vm_call_cfunc_with_frame vm_insnhelper.c:2211:11 - #12 0x5608e3d54a35 in vm_call_cfunc vm_insnhelper.c:2229:12 - #13 0x5608e3d5253b in vm_call_method_each_type vm_insnhelper.c:2564:9 - #14 0x5608e3d51f50 in vm_call_method vm_insnhelper.c:2701:13 - #15 0x5608e3cf2de4 in vm_call_general vm_insnhelper.c:2734:12 - #16 0x5608e3d79918 in vm_sendish vm_insnhelper.c:3627:11 - #17 0x5608e3d06cf5 in vm_exec_core insns.def:789:11 - #18 0x5608e3d43700 in rb_vm_exec vm.c:1892:22 - #19 0x5608e3d47cbf in rb_iseq_eval_main vm.c:2151:11 - #20 0x5608e37620ca in ruby_exec_internal eval.c:262:2 - #21 0x5608e376198b in ruby_exec_node eval.c:326:12 - #22 0x5608e37617d0 in ruby_run_node eval.c:318:25 - #23 0x5608e35c9486 in main main.c:42:9 - #24 0x7f62e9421b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 - - SUMMARY: AddressSanitizer: heap-use-after-free io.c:4749:24 in - rb_io_memsize - Shadow bytes around the buggy address: - 0x0c207fff8160: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 - 0x0c207fff8170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0c207fff8180: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 - 0x0c207fff8190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0c207fff81a0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd - =>0x0c207fff81b0: fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd - 0x0c207fff81c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c207fff81d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c207fff81e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c207fff81f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0c207fff8200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - Shadow byte legend (one shadow byte represents 8 application bytes): - Addressable: 00 - Partially addressable: 01 02 03 04 05 06 07 - Heap left redzone: fa - Freed heap region: fd - Stack left redzone: f1 - Stack mid redzone: f2 - Stack right redzone: f3 - Stack after return: f5 - Stack use after scope: f8 - Global redzone: f9 - Global init order: f6 - Poisoned by user: f7 - Container overflow: fc - Array cookie: ac - Intra object redzone: bb - ASan internal: fe - Left alloca redzone: ca - Right alloca redzone: cb - Shadow gap: cc - ==85264==ABORTING - -commit 2a863d4babed062dd91d2fe519d5018651c6378e - Author: Urabe, Shyouhei - Date: 2019-04-25 15:03:18 +0900 - - avoid buffer overflow in vm_check_canary - - ec->cfp->iseq might not exist at the very beginning of a thread. - - ================================================================= - ==82954==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fc86f334810 at pc 0x55ceaf013125 bp 0x7ffe2eddbbf0 sp 0x7ffe2eddbbe8 - READ of size 8 at 0x7fc86f334810 thread T0 - #0 0x55ceaf013124 in vm_check_canary vm_insnhelper.c:217:24 - #1 0x55ceaefb4796 in vm_push_frame vm_insnhelper.c:276:5 - #2 0x55ceaf0124bd in th_init vm.c:2661:5 - #3 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5 - #4 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5 - #5 0x55ceaef0038b in thread_s_new thread.c:872:20 - #6 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12 - #7 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11 - #8 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12 - #9 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9 - #10 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13 - #11 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12 - #12 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11 - #13 0x55ceaefc95bb in vm_exec_core insns.def:771:11 - #14 0x55ceaf006700 in rb_vm_exec vm.c:1892:22 - #15 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11 - #16 0x55ceaea250ca in ruby_exec_internal eval.c:262:2 - #17 0x55ceaea2498b in ruby_exec_node eval.c:326:12 - #18 0x55ceaea247d0 in ruby_run_node eval.c:318:25 - #19 0x55ceae88c486 in main main.c:42:9 - #20 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 - #21 0x55ceae7e5289 in _start (miniruby+0x15f289) - - 0x7fc86f334810 is located 16 bytes to the right of 1048576-byte region [0x7fc86f234800,0x7fc86f334800) - allocated by thread T0 here: - #0 0x55ceae85d56d in malloc (miniruby+0x1d756d) - #1 0x55ceaea71d12 in objspace_xmalloc0 gc.c:9416:5 - #2 0x55ceaea71cd2 in ruby_xmalloc2_body gc.c:9623:12 - #3 0x55ceaea7d09c in ruby_xmalloc2 gc.c:11479:12 - #4 0x55ceaf00c3b7 in rb_thread_recycle_stack vm.c:2462:12 - #5 0x55ceaf012256 in th_init vm.c:2656:29 - #6 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5 - #7 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5 - #8 0x55ceaef0038b in thread_s_new thread.c:872:20 - #9 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12 - #10 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11 - #11 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12 - #12 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9 - #13 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13 - #14 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12 - #15 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11 - #16 0x55ceaefc95bb in vm_exec_core insns.def:771:11 - #17 0x55ceaf006700 in rb_vm_exec vm.c:1892:22 - #18 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11 - #19 0x55ceaea250ca in ruby_exec_internal eval.c:262:2 - #20 0x55ceaea2498b in ruby_exec_node eval.c:326:12 - #21 0x55ceaea247d0 in ruby_run_node eval.c:318:25 - #22 0x55ceae88c486 in main main.c:42:9 - #23 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310 - - SUMMARY: AddressSanitizer: heap-buffer-overflow vm_insnhelper.c:217:24 in vm_check_canary - Shadow bytes around the buggy address: - 0x0ff98de5e8b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0ff98de5e8c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0ff98de5e8d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0ff98de5e8e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 0x0ff98de5e8f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - =>0x0ff98de5e900: fa fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0ff98de5e910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0ff98de5e920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0ff98de5e930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0ff98de5e940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - 0x0ff98de5e950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa - Shadow byte legend (one shadow byte represents 8 application bytes): - Addressable: 00 - Partially addressable: 01 02 03 04 05 06 07 - Heap left redzone: fa - Freed heap region: fd - Stack left redzone: f1 - Stack mid redzone: f2 - Stack right redzone: f3 - Stack after return: f5 - Stack use after scope: f8 - Global redzone: f9 - Global init order: f6 - Poisoned by user: f7 - Container overflow: fc - Array cookie: ac - Intra object redzone: bb - ASan internal: fe - Left alloca redzone: ca - Right alloca redzone: cb - Shadow gap: cc - ==82954==ABORTING - -commit aa190abe207c9cdbd75a5f8670a4e613565ee6bf - Author: Urabe, Shyouhei - Date: 2019-04-25 13:10:29 +0900 - - newptr should not be NULL - - obj_ivar_heap_alloc already handles that situation. - -commit 1aa05fddd81846bfa2833dff5e0aaccc1e707c81 - Author: Urabe, Shyouhei - Date: 2019-04-24 16:47:09 +0900 - - unpoison header before touching - - This header is poisoned to detect unintentional buffer overrun. - However in this (and forthcoming) function, we are intentionally - looking at the header. We have to unpoison before anything. - -commit 40b5f2b85dc5c50d7757c3b2522a767188b0e0b3 - Author: Urabe, Shyouhei - Date: 2019-04-24 16:15:46 +0900 - - memo.c might not always be initialized - - memo.float_value might change inside of hash_sum. In case it - flipped from false to true there, and the calculated sum is Inf, - memo.c might not be initialized at all. This is bad. - - Found using memory sanitizer: - - ==55293==WARNING: MemorySanitizer: use-of-uninitialized-value - #0 0x55dfb8d6c529 in rb_float_new_inline internal.h:1814:53 - #1 0x55dfb8d1b30c in enum_sum enum.c:4017:18 - #2 0x55dfb86d75ad in call_cfunc_m1 vm_insnhelper.c:2041:12 - #3 0x55dfb864b141 in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11 - #4 0x55dfb85e843d in vm_call_cfunc vm_insnhelper.c:2225:12 - #5 0x55dfb85e08f3 in vm_call_method_each_type vm_insnhelper.c:2560:9 - #6 0x55dfb85de9c7 in vm_call_method vm_insnhelper.c:2686:13 - #7 0x55dfb849eac6 in vm_call_general vm_insnhelper.c:2730:12 - #8 0x55dfb8686103 in vm_sendish vm_insnhelper.c:3623:11 - #9 0x55dfb84dc29e in vm_exec_core insns.def:789:11 - -commit f02760fc0a455f376ad1a855fd1a5e9252c8267c - Author: Urabe, Shyouhei - Date: 2019-04-24 15:30:25 +0900 - - avoid reading uninitialized variable - - autoload_reset() can read this state.result. Because autoload_reset - is a function passed to rb_ensure, there is a chance when an - exception raises before actually filling this memory region. - - test/ruby/test_defined.rb:test_autoload_noload is one of such case. - - Found using memory sanitizer. - - ==54014==WARNING: MemorySanitizer: use-of-uninitialized-value - #0 0x557a683f3e5a in autoload_reset variable.c:2372:9 - #1 0x557a6707a93b in rb_ensure eval.c:1084:5 - #2 0x557a683efbf5 in rb_autoload_load variable.c:2475:14 - #3 0x557a685fc460 in vm_get_ev_const vm_insnhelper.c:938:4 - #4 0x557a68448e0a in vm_exec_core insns.def:267:11 - -commit 3ba485c0bfcfc0be351ef8278cd27187f4c11906 - Author: Urabe, Shyouhei - Date: 2019-04-23 18:02:24 +0900 - - zero-fill before GC mark - - Depending on architectures, setjmp might not fully fill a jmp_buf. - On such machines the union can contain wobbly bits. They are then - scanned during mark_locations_array(). This is bad. - -commit 504ce460d240b5b726e77c0b0915677892a19e58 - Author: Urabe, Shyouhei - Date: 2019-04-24 14:53:47 +0900 - - give up sanitizing BSD_vfprintf - - Sanitizers report something inside of this function but it is - beyond my brain capacity. Also the code is proven to work. - Let me ignore. - -commit b11b26bcaf711ad01d1a81943cca42f7ff40bfee - Author: Urabe, Shyouhei - Date: 2019-04-24 12:24:44 +0900 - - fix size of allocated memory - - The size of `ptr` here is not the same as the variable `size`. - We were counting the size of header twice. - -commit 6201a89b38afb6bb2a548aeba0ca77090851713b - Author: Urabe, Shyouhei - Date: 2019-04-24 11:23:13 +0900 - - mark verify functions non-sanitizable - - These functions purposefully read from memory regions potentially - not handled well. Should let sanitizers avoid checking them. - -commit 572f2ddff64ddf12f2331ad77b72d2b0c9d9883c - Author: Urabe, Shyouhei - Date: 2019-04-23 18:36:20 +0900 - - use __attribute__((__no_sanitize__("memory"))) - -commit fa09acafde3b7dbb23edadc6eddcce27f7395880 - Author: Urabe, Shyouhei - Date: 2019-04-24 18:22:33 +0900 - - extend machine stacks when sanitizers are there - - It seems sanitizers require extra amount of machine stacks. Without - extending them the process tends to stack overflow. - -commit 1f4204a762b2ddcc2f235b1a2b6a10071ef90d3b - Author: Urabe, Shyouhei - Date: 2019-04-23 17:55:15 +0900 - - disable assertion when MSAN is active - - These assertions check if a newly allocated object (which is marked - as an uninitialized memory region in MSAN) is in fact a T_NONE. - - Thus they intentionally read uninitialized memory regions, which do - not interface well with MSAN. Just disable them. - -commit bdd1b300f8bf540c8f237cce50e42991f94101e3 - Author: Urabe, Shyouhei - Date: 2019-04-23 17:47:49 +0900 - - __asan_region_is_poisoned takes void * - - while heap->obj is a VALUE. A cast should be there. - -commit 171a6ad1c12b1600b01d9bde29947526ae3e2aee - Author: Urabe, Shyouhei - Date: 2019-04-25 14:33:44 +0900 - - print the disasm - - It seems to be my fault to leave the variable disasm unused. - -commit b6ebbee5d64dbd422957efe55b4ec5520c9b11bf - Author: Urabe, Shyouhei - Date: 2019-04-25 16:36:32 +0900 - - suppress warning [ci skip] - -commit 54eac83b2ad77ddea84fa6d66c09e0bb014cf61e - Author: Nobuyoshi Nakada - Date: 2019-04-24 13:35:23 +0900 - - Hide internal IDs - - * parse.y (internal_id): number the ID serial for internal use by - counting down from the neary maximum value, not to accidentally - match permanent IDs. - - [Bug #15786] - - Notes: - Fixed: [Bug #15786] - -commit 5689c46457e6b078ac83b08b7e881e0050ebdfaa - Author: git - Date: 2019-04-26 01:43:26 +0900 - - * 2019-04-26 - -commit 0408b8b390f788693b10ad82281ae3d66ea52eb4 - Author: Takashi Kokubun - Date: 2019-04-26 01:43:11 +0900 - - Syntax-highlight yield in IRB - -commit 2422316aea034c818734ad2fa68c4b021a6aafeb - Author: Takashi Kokubun - Date: 2019-04-26 01:18:37 +0900 - - NEWS: Credit goes to Pry [ci skip] - - We must note this feature is heavily inspired by Pry. - -commit 5fe99aefd39ce535f658aabd0ca6e2265348d314 - Author: Takashi Kokubun - Date: 2019-04-26 01:15:30 +0900 - - Support highlighting Regexp in inspect - -commit e64bab5f779440ae920746ae5689a2af91de3604 - Author: Takashi Kokubun - Date: 2019-04-26 00:53:36 +0900 - - Add NEWS entry about IRB syntax highlight [ci skip] - - Details: https://github.com/ruby/ruby/pull/2150 - - Note that this introduction is discussed with @aycabta who is allowed to - make some changes to IRB by the IRB maintainer, keiju. - -commit 0c54d2e2c7697aa5d6a1315b79c16b88d34f5e81 - Author: Takashi Kokubun - Date: 2019-04-25 23:53:57 +0900 - - Force IRB::Color to recognize TERM - - Closes: https://github.com/ruby/ruby/pull/2150 - -commit 022cbb278f381e5774a5d0277a83127c6f6b4802 - Author: Pocket7878 - Date: 2019-04-25 23:47:12 +0900 - - Do not color IRB output on 'dumb' TERM - - Co-Authored-By: k0kubun - Closes: https://github.com/ruby/ruby/pull/2150 - -commit b55201dd099011a22c8c1d64c653f898d9b409ca - Author: Takashi Kokubun - Date: 2019-04-25 21:36:48 +0900 - - Colorize IRB's inspect result - - Closes: https://github.com/ruby/ruby/pull/2150 - -commit 94af6cd383f9dc3ae1204a5fba8f56ee7826cbce - Author: Takashi Kokubun - Date: 2019-04-25 21:16:21 +0900 - - Colorize IRB's code_around_binding - - Closes: https://github.com/ruby/ruby/pull/2150 - -commit 790f6709ae418345829d12f053cf270f4d535f1c - Author: Kazuhiro NISHIYAMA - Date: 2019-04-25 23:46:37 +0900 - - Mention warning of `$,` - - see [r67606](https://github.com/ruby/ruby/commit/3ee0648dc7a5465b2cbadd7246fc2edbd676d759) - -commit 2272cb00eadcbc48640c69fcd6a30e45a5977cd5 - Author: Nobuyoshi Nakada - Date: 2019-04-25 11:07:17 +0900 - - Ripper does not use internal IDs directly - -commit c9715eb494ee9055f76ff59027219b5b4756f7bd - Author: Kazuhiro NISHIYAMA - Date: 2019-04-25 20:02:22 +0900 - - Add more debug print for random CI failure on osx Travis - - see r67347 - -commit 3581a64239b333be33424888f689c9e452fc3334 - Author: Takashi Kokubun - Date: 2019-04-25 19:37:10 +0900 - - BSD's mktemp does not have `-p` - -commit 57225dc07a3fcc745c7aecc1fb04182b156ad29f - Author: Takashi Kokubun - Date: 2019-04-25 19:24:56 +0900 - - Show `make checkout-github/merge-github` in help - -commit b2e92bfd9f25274277f15faa6e9a70a7d0a36dfe - Author: Takashi Kokubun - Date: 2019-04-25 18:54:43 +0900 - - Resurrect `make xxx-github PR=1234` interface - - `call xxx, yyy` seems to pass " yyy" instead of "yyy". - -commit 70adfdcd8de3296e9015338216073e8144dbea04 - Author: Nobuyoshi Nakada - Date: 2019-04-25 18:29:58 +0900 - - Added pr-% - - May merge multiple github pull requests at once. e.g., - - $ make pr-123456789 pr-987654321 - -commit 44bb429bb1bb431dc2805daf93f52509c26b9da7 - Author: Nobuyoshi Nakada - Date: 2019-04-25 18:27:16 +0900 - - Cache git config values - -commit 6de9128fe942de9a0306fe63b949b1a9c343e2c8 - Author: Takashi Kokubun - Date: 2019-04-25 18:05:51 +0900 - - Add `make checkout-github` too - - You can use this like `make checkout-github PR=1234` - -commit 116f91ab504a450b1b96d6b3f029fbaa5f99a305 - Author: Nobuyoshi Nakada - Date: 2019-04-25 15:33:05 +0900 - - Make working tree under the source directory - -commit 09ce223b0b297359fd7f9a5d629a70be32157302 - Author: Nobuyoshi Nakada - Date: 2019-04-25 15:03:54 +0900 - - Rebase the pull request in a worktree - - A pull request based on an old commit may rewind too many files, - even if unnecessary. As rewinding some files, e.g., common header - files, configure.ac, will result in full-rebuild, rebase in a - separate directory to get rid of such rewind. - -commit d0ba4abf1a00339ebbb5d405db3240a8bdb7b68b - Author: Nobuyoshi Nakada - Date: 2019-04-25 13:22:06 +0900 - - Add RB_ID_SERIAL_MAX - -commit 99084f540171df301478ec66fb89e2c38287e504 - Author: Lourens Naudé - Date: 2019-04-10 21:05:15 +0900 - - Lazy allocate the compile data catch table array - - Closes: https://github.com/ruby/ruby/pull/2119 - -commit 9bfc185a0d93f05f7522a3dea89d69920dcf079c - Author: Kouhei Sutou - Date: 2019-04-25 05:28:56 +0900 - - Upgrade test-unit to 3.3.2 - -commit 7d2cb60e48f40d6d6105808e1de1e244a05a8138 - Author: git - Date: 2019-04-25 01:09:06 +0900 - - * 2019-04-25 - -commit 68e3f8192b6df3ee1759bef7725e958aa3e72c3d - Author: Masatoshi SEKI - Date: 2019-04-25 01:08:54 +0900 - - add DRbObject dereference test (Preparation for investigation of Bug #15711) - -commit dd5b6c71c6cf157406e5ead4dfc6188d563bc268 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-25 00:52:16 +0900 - - Fix typos [ci skip] - -commit 6061aa0ac1b4d43d107d47ba4d2eecbda77959a1 - Author: Takashi Kokubun - Date: 2019-04-24 23:26:56 +0900 - - Automatically gpg-sign rebase when commit.gpgsign - - is true - - Closes: https://github.com/ruby/ruby/pull/2148 - -commit daff4cbd6c7d6be07ae094bda45bca076b37a375 - Author: Takashi Kokubun - Date: 2019-04-24 22:40:54 +0900 - - Add `make fetch-github` and `make merge-github` - - Closes: https://github.com/ruby/ruby/pull/2147 - -commit 2642f22050d74d56da5525b0cd1a5c665ddb4c51 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-24 18:18:46 +0900 - - Add more debug print for random CI failure on osx Travis - - see r67347 - -commit 1613917ae6441b98a52d885f0df1479652be755d - Author: Nobuyoshi Nakada - Date: 2019-04-24 17:34:21 +0900 - - Defer setting gc_stress instead of setting dont_gc - - [Bug #15784] - -commit f1a52d96a59c63d46cb23af60cdcaf38e30e0512 - Author: Nobuyoshi Nakada - Date: 2019-04-24 12:52:57 +0900 - - Defer setting gc_stress until inits done - - [Bug #15784] - -commit 2ef66737081ec029f9c82e11671de36bb70a9e3b - Author: Koichi Sasada - Date: 2019-04-24 09:30:07 +0900 - - force 10 chars SHA1 display. - - `make update-src` shows latest commit hash for convenience. - However, `rev-parse --short` option shows different length - (maybe) between git versions. This fix force 10 chars - with `--short=10`. - -commit 19d454a957836a6118f42b0367aea7c823beffae - Author: Aaron Patterson - Date: 2019-04-24 07:16:17 +0900 - - syntax error can move, so do not cache - -commit 75061f46ae646e821e9228caa5e3b7f23fa609f0 - Author: Aaron Patterson - Date: 2019-04-24 04:10:52 +0900 - - Fix complex hash keys to work with compaction - - For example when an array containing objects is a hash key, the contents - of the array may move which can cause the hash value for the array to - change. This commit makes the default `hash` value based off the - object id, so the hash value will remain stable. - - Fixes test/shell/test_command_processor.rb - -commit cf930985da1ae15b66577ec8286e54ad04ccda78 - Author: Lourens Naudé - Date: 2019-03-17 00:53:18 +0900 - - Remove member char_offset_updated from struct rmatch as member char_offset_num_allocated can serve the same purpose as that predicate - -commit 82ef172a8cb90819bf835e468eb8af2323e3bccf - Author: Takashi Kokubun - Date: 2019-04-24 01:10:13 +0900 - - The step should not fail when isolated tests - - do not exist - -commit bc8e54911db505d9e1776673a86e956c7d7e3b89 - Author: Takashi Kokubun - Date: 2019-04-24 00:39:33 +0900 - - Isolate test_gc_compact for osx Travis - - After `GC.compact`, test/shell/test_command_processor.rb seems to be made - unstable on osx Travis like https://travis-ci.org/ruby/ruby/jobs/523487997. - - For investigating whether it's impacting that or not, let me try isolating - that for osx Travis for now. - -commit 9629f4c0518f4a22fe8c149019c3d15005f4ef00 - Author: git - Date: 2019-04-24 00:40:29 +0900 - - * 2019-04-24 - -commit 31cf13060cce44d782b068cf083b1ae4def6dc09 - Author: Lourens Naudé - Date: 2019-03-16 21:48:34 +0900 - - Only define history_root member of the Oniguruma re_registers struct if USE_CAPTURE_HISTORY is enabled - -commit 14dd8d6b370797f2e419205e9f28368433dc6ceb - Author: Hiroshi SHIBATA - Date: 2019-04-23 22:26:40 +0900 - - Added cgit url. - -commit f4f66bd11c65882b86e0acf4d58f15fb596f25cf - Author: Nobuyoshi Nakada - Date: 2019-04-23 21:55:29 +0900 - - Revert "IRB is improved with Reline and RDoc, take 2" - - Accidentally merged when 89271d4a3733bc5e70e9c56b4bd12f277e699c42 - "Adjusted indents". - -commit 89271d4a3733bc5e70e9c56b4bd12f277e699c42 - Author: Nobuyoshi Nakada - Date: 2019-04-23 20:27:24 +0900 - - Adjusted indents - -commit f2cd4f4cd0a1e352fcc48a216127beaeda2b2399 - Author: aycabta - Date: 2019-04-23 18:09:46 +0900 - - IRB is improved with Reline and RDoc, take 2 - -commit 87cf45a512a7803f266e4782c49e0a99c06a4039 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-23 16:48:48 +0900 - - Fix a typo - -commit 2ae5f6f97cd1cd79e3c0ef11da235ddc053a6186 - Author: Nobuyoshi Nakada - Date: 2019-04-23 15:43:51 +0900 - - Add VCS::GIT#commit - -commit 2fb83a0af7a49788e80c55fd324dfa8e046cd9d9 - Author: Nobuyoshi Nakada - Date: 2019-04-23 15:39:36 +0900 - - Split git-svn dependent methods - -commit 18eb9e585526881cba9752e50b2d206924714339 - Author: Nobuyoshi Nakada - Date: 2019-04-23 15:03:19 +0900 - - Use an exclusive range for ruby_version_is - -commit 0d41adf6e2d10ef699e291f468ee955b25671d6f - Author: Nobuyoshi Nakada - Date: 2019-01-07 11:03:41 +0900 - - Split long expression - -commit 4946c3e4b5e465c743da3050169fdb1f7b060c95 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-23 14:09:45 +0900 - - Add tool/format-release to .gitattributes - -commit 2e1ac220891eb6f53ab62b7c5f4376d8b7959779 - Author: Aaron Patterson - Date: 2019-04-23 12:38:49 +0900 - - Oops, bad merge 🙇â€â™‚ï¸ - -commit e50e60b96a90db8dd92a39f89bd1315d63e1515d - Author: git - Date: 2019-04-23 12:34:10 +0900 - - * expand tabs. - -commit 5a58318a9036ae2430d0a6b1d27ff3d3fd7fdf13 - Author: Aaron Patterson - Date: 2019-04-23 12:32:20 +0900 - - T_MOVED can live on the stack, so make sure we can do book keeping - - Unused T_MOVED objects can live on the stack, so we need to make sure - that they can be accounted for in book keeping - -commit 6ca9e7cc0785c33f6d382176dbd79d6c91db72fe - Author: Seiei Miyagi - Date: 2019-04-23 00:21:50 +0900 - - Disallow numbered parameter as the default value of optional argument - - [Fix GH-2139] [Bug #15783] - -commit ae07b66aaa092c59ac9d544c9b582712290dc357 - Author: Seiei Miyagi - Date: 2019-04-23 00:01:17 +0900 - - Fix internal error of `->x:@2{}` - - [Fix GH-2139] [Bug #15783] - -commit ea520ca9273699fc1c77a71bbeba4b6e06ccfc6c - Author: Aaron Patterson - Date: 2019-04-23 09:14:36 +0900 - - Prevent rb_define_(class|module) classes from moving - - Before this commit, classes and modules would be registered with the - VM's `defined_module_hash`. The key was the ID of the class, but that - meant that it was possible for hash collisions to occur. The compactor - doesn't allow classes in the `defined_module_hash` to move, but if there - is a conflict, then it's possible a class would be removed from the hash - and not get pined. - - This commit changes the key / value of the hash just to be the class - itself, thus preventing movement. - -commit 660c0716595a8fc942d12317a5c55c038b830e94 - Author: Urabe, Shyouhei - Date: 2019-03-08 17:10:08 +0900 - - [ci skip] grammars in comments - -commit 9cdb736672bec22a8396f8077f8eea758bb2ef88 - Author: Nobuyoshi Nakada - Date: 2019-04-23 10:15:01 +0900 - - Missing semicolon - -commit a9b57862bd5b81fb091202d82fb26f3f9ecdc4a3 - Author: git - Date: 2019-04-23 10:19:53 +0900 - - * 2019-04-23 - -commit a8d4dc287fc8621c5b786140714736cb747d3291 - Author: git - Date: 2019-04-23 10:19:47 +0900 - - * expand tabs. - -commit 98ee63693d963e96ac7d81ac33a5b12103b577b3 - Author: Aaron Patterson - Date: 2019-04-23 08:23:04 +0900 - - Symbols can move, so don't cache in static pointer - - This changes the static pointers to use IDs then look up the symbols - with the ID. Symbols can move, so we don't want to keep static - references to them. - -commit 6fbf4e22c83b4504d2d9a4a42216e4306a4e7e38 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-22 23:10:10 +0900 - - Adds a reference to `TracePoint` to `binding` docs - - This change adds an explicit reference to `TracePoint` in the - documentation for `binding`. Currently it only refers to the now - deprecated `Kernel#set_trace_func`. This reference is left alone for - continuity in the documentation. - [Fix GH-2079] - - Co-authored-by: Brandon Weaver - -commit e19e5d2409e99ef7fd450d317e71e119cb5a4c3a - Author: Stefan Schüßler - Date: 2019-02-18 20:44:01 +0900 - - Fix return value name in docs for Array#union - - Throughout the docs, `new_ary` is used to indicate a new array, whereas `ary` refers to the receiver. - - Notes: - Merge branch patch-5 of https://github.com/sos4nt/ruby into trunk - - [Fix GH-2084] - -commit 4cd67a848a0648c20b1cab9d2dfe1bf7d7d90be0 - Author: Takashi Kokubun - Date: 2019-04-22 22:00:33 +0900 - - Fix RUBY_REVISION spec - - broken by 5da52d1210625fb00acd573b3f32281b4bde1730 - -commit 87261cf59f4914801512cf0f3f1332f0c94b6952 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-22 21:44:44 +0900 - - Omit last_commit=RUBY_LAST_COMMIT_TITLE without local commits - -commit 5da52d1210625fb00acd573b3f32281b4bde1730 - Author: Takashi Kokubun - Date: 2019-04-22 21:23:37 +0900 - - Migrate RUBY_VERSION/RUBY_DESCRIPTION to Git - - from Subversion. - - This behavior is tentative and not discussed well. The point of - discussion will be just the length of commit hash, and I thought we - should include this kind of change in 2.7.0-preview1 release even before - the length is fixed yet. - - Let's discuss that afterwards and fix it later as needed. Naruse - suggested that length=10 is very unlikely to cause conflict, and thus - it's used by email notification and rubyci now. This behavior is in - favor of that for now. - -commit dd0b516399f1e009667a99e815bf86c6a1245ee5 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-22 21:01:34 +0900 - - Tk is already removed from stdlib at r55844 - - https://github.com/ruby/ruby/commit/303dc3c591e324b6bbc691326d8bea76fe3b8fda - -commit c697bade0fc1a7f80122fac7bfe4d137f999f841 - Author: SHIBATA Hiroshi - Date: 2019-04-22 20:01:07 +0900 - - Ignore VSCode configuration from git. - -commit 6a2c8e46f63998b860f5dbf4a89e2f7ee2d7ed0e - Author: SHIBATA Hiroshi - Date: 2019-04-22 20:00:32 +0900 - - Use github url instead of ViewVC. - -commit 184447d91c71aaab6a6f4e6e0527f553872036fb - Author: SHIBATA Hiroshi - Date: 2019-04-22 19:37:22 +0900 - - ViewVC of svn.ruby-lang.org was shutdown status. - -commit ae3f38dc533f2967214f826d3ed45f950f94a8e7 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-22 19:02:17 +0900 - - CRuby trunk uses git instead of subversion now - -commit f005ccc771574e8e4e17b7a35c19b352e0b7dc73 - Author: Shugo Maeda - Date: 2019-04-22 17:15:49 +0900 - - Clarify requirements of <=> - - A return value of <=> is automatically converted to -1, 0, or 1, so - other values can be returned. [Misc #15630] - -commit 6013e41a7bb1d6909e0538ccb885b477bd080163 - Author: Kazuhiro NISHIYAMA - Date: 2019-04-22 11:39:08 +0900 - - Support of Ruby 2.3 has ended - - https://www.ruby-lang.org/en/news/2019/03/31/support-of-ruby-2-3-has-ended/ - -commit beaddd1d327a1c6fe16ab2c84191251280657e48 - Author: NAKAMURA Usaku - Date: 2019-04-22 11:33:56 +0900 - - Now only supports Git repository - -commit b26a7c8d86d8a750a0124340a6d6c1010b768ab2 - Author: svn - Date: 2019-04-22 10:06:50 +0900 - - * remove trailing spaces. - -commit e949c084b52de8c2a938e7a959dd61d6e9b78f2d - Author: Takashi Kokubun - Date: 2019-04-22 10:05:56 +0900 - - README.ja.md: Update description about Git repository - - Backported 4c570abf77 to Japanese - -commit 44a468ccdad87ac58e0bb1eccb8b67910bfc7b50 - Author: svn - Date: 2019-04-22 09:55:20 +0900 - - * remove trailing spaces. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67701 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4c570abf773a0c627592ddef584f3375f791126c - Author: k0kubun - Date: 2019-04-22 09:55:19 +0900 - - README.md: Update description about Git repository - - We started to switch from SVN to Git. Because GitHub would be more - reliable than our single-host cgit, I continued to list GitHub mirror - repository in the first place. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 693c28d59f6c5eb9dc4fefba57c7967c0dd49b63 - Author: svn - Date: 2019-04-22 00:04:07 +0900 - - * 2019-04-22 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67699 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fdd3091274867197b20bd2c9502fcc5cf3470130 - Author: kazu - Date: 2019-04-22 00:04:06 +0900 - - Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67698 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b6fd7b1bb741edfe08b9f9da4652b5e1d5d3a57a - Author: k0kubun - Date: 2019-04-21 23:24:38 +0900 - - tool/redmine-backporter.rb: Git support in backport/rel - - close https://github.com/ruby/ruby/pull/2138 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67697 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c7db05d216cc4c72bed494d026898784ba6b3b5b - Author: k0kubun - Date: 2019-04-21 22:05:32 +0900 - - tool/redmine-backporter.rb: Remove unused methods - - They seem to have never been used from the beginning (r45081). - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67696 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 72be46f104446ed2dd0a6c2476045fa9f9051f6e - Author: k0kubun - Date: 2019-04-21 21:26:06 +0900 - - Drop tool/generate-backport-changelog.rb - - because we're not writing ChangeLog since ruby_2_4. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67695 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2c31e6dec4e0625c9a79f7d5df669d2ee5abb1de - Author: k0kubun - Date: 2019-04-21 21:03:39 +0900 - - tool/merger.rb: Guard match failure properly - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67694 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit de5378233b2ff5434f024ac66285e699794a321d - Author: k0kubun - Date: 2019-04-21 20:49:11 +0900 - - tool/merger.rb: Support fetching patch from cgit - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67693 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 47676e969e9ecb204e704f0221816167afa79362 - Author: k0kubun - Date: 2019-04-21 19:01:44 +0900 - - tool/merger.rb: Drop ChangeLog handling - - We're not writing ChangeLog since ruby_2_4. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67692 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 51cec00953ff8d7baa483d3846aa1dbdb89101aa - Author: aycabta - Date: 2019-04-21 18:13:49 +0900 - - Revert "IRB is improved with Reline and RDoc" - - This reverts commit 7f273ac6d0f05208b5b228da95205e20c0e8286c. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 683834eb72cfa77f4eac1c705327b522302b1721 - Author: k0kubun - Date: 2019-04-21 17:34:37 +0900 - - Drop MJIT_FUNC_EXPORTED from rb_hash_bulk_insert - - it's official API after r67677 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit add82b7e7eebfb8ee311bd85cd2111874f3564f2 - Author: k0kubun - Date: 2019-04-21 17:19:48 +0900 - - Drop obsoleted feature from help - - I understand this is dropped in r67569 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67689 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9c51ef5bc44fc50e9e89a622cf566c6aae0449b4 - Author: aycabta - Date: 2019-04-21 16:37:34 +0900 - - Merge upstream of Reline - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ea1835caf27e7a4ba31d2c87d05ac292d6d108cd - Author: k0kubun - Date: 2019-04-21 16:27:52 +0900 - - Drop unnecessary newline in short line [ci skip] - - I'm committing safe things to test commit hooks on production... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67687 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 60455b39bbc98a9faab4cf289feb7191cff8220d - Author: k0kubun - Date: 2019-04-21 16:21:55 +0900 - - Fold too-long line for readability [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0d23d02ac75cb4349d6dcc3b4ad2b3fba7573f58 - Author: k0kubun - Date: 2019-04-21 16:17:35 +0900 - - Use consistent comma in .ja [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67685 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c23b258d4dc3e1ee34ca6e3351952196bbbf7ab2 - Author: k0kubun - Date: 2019-04-21 16:14:59 +0900 - - Drop created at in .ja like en version [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67684 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 96147b3a12b24f69f2aaccc385d87cceaaec7f6a - Author: k0kubun - Date: 2019-04-21 16:12:51 +0900 - - Slightly modify ja sentence [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67683 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0d972252b0196d7ebb9994292c112a258e68886c - Author: k0kubun - Date: 2019-04-21 16:08:32 +0900 - - Backport README change to .ja.md [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67682 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 221e293733d89fd9b87d966b0891076162264535 - Author: aycabta - Date: 2019-04-21 16:08:26 +0900 - - Add test/reline/ again, I'm back - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67681 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d9a01bc17a3b1097906c8751b621c9a212f29f42 - Author: nobu - Date: 2019-04-21 15:08:00 +0900 - - Remove unused variable and check if succeeded - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9a83922b666d4e26b84840757b16b0f9df6acef9 - Author: naruse - Date: 2019-04-21 14:48:35 +0900 - - suppress redefinition warnings - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67679 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7f09b5e9da8f83f84c5b6ae7a644a562811fec73 - Author: naruse - Date: 2019-04-21 14:48:35 +0900 - - suppress warning in test/irb - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos7/ruby-trunk/log/20190421T040003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d3df725f9efeb0e6c121f9a1316abaa90956f1b8 - Author: naruse - Date: 2019-04-21 14:37:11 +0900 - - Make rb_hash_bulk_insert public - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67677 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d9c17c1a877349b193a0718d91bf9d5f05d3b853 - Author: kazu - Date: 2019-04-21 13:54:04 +0900 - - git.ruby-lang.org may be slow than github.com from oversea - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67676 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5906bcc95ab5973b46213e1ec08b71cd4f8f60bd - Author: usa - Date: 2019-04-21 13:53:44 +0900 - - Remove debug lines - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67675 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 66b6d76648c65bf1fa1f284ca691100a8a9f9882 - Author: usa - Date: 2019-04-21 13:52:38 +0900 - - Show/unshow executing command as specified by `V` - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 03c6cb5e8f503dcf6bc80a70a48a9775bbd2a47e - Author: k0kubun - Date: 2019-04-21 13:02:24 +0900 - - Note about cgit url [ci skip] - - testing svn hook by this commit - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67673 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 710e763e72d925fc25cd5974158cc9e14016a81b - Author: ktsj - Date: 2019-04-21 12:56:42 +0900 - - test/ruby/test_pattern_matching.rb: add missing tests for NODE_DASGN, NODE_LASGN - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2dc51bf447dd837e9dc3189bbccaf23db0776816 - Author: aycabta - Date: 2019-04-21 12:51:26 +0900 - - Remove test/reline temporary, I'll come back - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2a5ea43507564739be53af511c9b3a4891db9700 - Author: ko1 - Date: 2019-04-21 12:46:25 +0900 - - add ensure to restore $stdout correctly. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67670 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d0e50b7d5ba6cd247110a0b867a2e1b5442d9978 - Author: svn - Date: 2019-04-21 12:38:53 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67669 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b02f368c82ffbc5318a11e3d700035062bd1d816 - Author: nobu - Date: 2019-04-21 12:38:52 +0900 - - Restore pwd - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67668 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 72cbc3142dbabc54ff225950034335d4f5a4521f - Author: k0kubun - Date: 2019-04-21 12:35:07 +0900 - - Revert "Try dropping const qualifier to suppress msiwn warning" - - This reverts commit b023c1cc07b2fd6e201bf3aeb4a1df9af3854888. - - in favor of r67666. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67667 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e6a7b8a4879dfa44fa1dcefb67f064322570c4c7 - Author: usa - Date: 2019-04-21 12:33:05 +0900 - - Get rid of warnings of VC - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67666 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b023c1cc07b2fd6e201bf3aeb4a1df9af3854888 - Author: k0kubun - Date: 2019-04-21 12:32:03 +0900 - - Try dropping const qualifier to suppress msiwn warning - - https://ci.appveyor.com/project/ruby/ruby/builds/23995093/job/qo728n1uorepkx16 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67665 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4cb2dcdf02964650412c0e34ecbb3dcb744f2a2e - Author: hsbt - Date: 2019-04-21 12:31:34 +0900 - - ubygems.rb is already removed from ruby repository. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67664 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a3adb11fa60a184231cbd085c3171e675db4c8ce - Author: nobu - Date: 2019-04-21 12:30:48 +0900 - - test/reline/helper.rb: define RELINE_TEST_ENCODING always - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67663 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0db89a38f22754eb09c69ae3e38533c91b5e3b17 - Author: nobu - Date: 2019-04-21 12:30:38 +0900 - - Show the latest commit hash after update - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2c6e241462e02003fc9c3103b8f6aed465b33927 - Author: k0kubun - Date: 2019-04-21 12:12:05 +0900 - - Remove obsoleted TODO comment [ci skip] - - looks like it's updated sufficiently - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67661 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 01efa5d912f47829eb7fbb472d899ed293105d25 - Author: ktsj - Date: 2019-04-21 12:11:38 +0900 - - Add missing test for p_var_ref - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67660 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e7d76e3f5aa78f81e38de5e4ef16cffe7ad7a0d5 - Author: k0kubun - Date: 2019-04-21 11:58:10 +0900 - - tool/merger.rb: Drop some revision notations. - Maintainer use merger mainly from redmine-backporter.rb. - - [Fix GH-2136] - - From: Chikanaga Tomoyuki - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ffc93316c8035ade6bf035dd9348dfcc143e2d4b - Author: k0kubun - Date: 2019-04-21 11:58:10 +0900 - - tool/merger.rb: Remove unused command line format. - I believe no-one use this notation for years. - - [Fix GH-2136] - - From: Chikanaga Tomoyuki - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67658 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dad3047659a503d7e6f4ded362f8d58ecca20b1f - Author: kazu - Date: 2019-04-21 11:51:03 +0900 - - Remove redundant cast - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bb77cc183732cf68e224398c30d8e38d02cab14c - Author: ktsj - Date: 2019-04-21 11:43:31 +0900 - - Add missing tests for p_args - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67656 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1a0990cb143f8988603fe510b8ed840780a77d1f - Author: svn - Date: 2019-04-21 11:33:15 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67655 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 65f1b8118357f48064626702b19561eeb5d9b9c7 - Author: nobu - Date: 2019-04-21 11:33:14 +0900 - - Fix test library name - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit eeee4f404b9e2dd9cac84de2b30f7bf1ba608c53 - Author: ktsj - Date: 2019-04-21 11:18:28 +0900 - - Remove unnecessary condition - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67653 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ecf4e8fbd7efe33e536bbef8d9e58b3c345dda48 - Author: svn - Date: 2019-04-21 10:39:09 +0900 - - * 2019-04-21 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67652 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 985192f092aa36a88836a51012b7d572bccd5c0e - Author: k0kubun - Date: 2019-04-21 10:06:25 +0900 - - Make README.md similar to README.ja.md [ci skip] - - making safe commit to debug svn hook - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67651 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 838f1f61bfd31861a8ddc470e33cf21ee866ad7b - Author: tenderlove - Date: 2019-04-21 07:25:59 +0900 - - skip test until we can guarantee movement of certain objects - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67650 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3863b7776f68821e5a873fd3a73886a2eb377845 - Author: aycabta - Date: 2019-04-20 18:32:44 +0900 - - Remove IRB's old test files - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67649 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 66ae3bd5599186599af5041dced836087cdeb3bd - Author: tenderlove - Date: 2019-04-20 18:29:19 +0900 - - skip test if mjit is enabled - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67648 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d4a555d441895cc56243b1a411404e324fbcf89f - Author: aycabta - Date: 2019-04-20 18:23:09 +0900 - - Add "require 'stringio'" - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ffaee7b301abfd451c7c5028602a2184e6a9dd90 - Author: aycabta - Date: 2019-04-20 18:16:16 +0900 - - Use require_relative for tests of Reline - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7f273ac6d0f05208b5b228da95205e20c0e8286c - Author: aycabta - Date: 2019-04-20 17:51:20 +0900 - - IRB is improved with Reline and RDoc - - Reline is a readline stdlib compatible library. It also supports - multiline input. IRB is improved with Reline and supports multiline. - Besides, supports showing documents when completed. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91faab7f1477c65f71aee8324cdeca7b6f19434a - Author: k0kubun - Date: 2019-04-20 16:52:59 +0900 - - Fix wrong critical section label - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67644 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ef73bee8113638199595611240d74d310f8a4f57 - Author: k0kubun - Date: 2019-04-20 16:37:29 +0900 - - Prefix rb_ to MJIT wait call since it's exported - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67643 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e4a0304aef5f2475b6111eca85daee032d88155c - Author: k0kubun - Date: 2019-04-20 16:16:11 +0900 - - Workaround Wercker check which is not working now - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67642 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9c587d22bd31f50a3a07f5024b7376302e902e09 - Author: k0kubun - Date: 2019-04-20 15:54:41 +0900 - - Skip test_find_collided_object on problematic CIs for now - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67641 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 78d3e4396d3c2ca53875fdbc9a24032d6eebf4f6 - Author: tenderlove - Date: 2019-04-20 15:08:54 +0900 - - Make sure the has_remembered_objects flag is correctly set - - Remembered objects can move between pages, so we need to make sure the - flags on the page are set correctly. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c2b8cd425e80ea75c9f3efd8b5b63f1f235b6b54 - Author: k0kubun - Date: 2019-04-20 14:50:19 +0900 - - Revert "Revert "Skip ISeq reference for stale_units for debugging"" - - This reverts commit b79899b56a9ebadf5c493c4df2419ebf63934381. - - I wanted to test r67638 first. Now let me try this as well. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67639 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b2ffafd2383fef50933a725797b1ea7ae4fbdaea - Author: k0kubun - Date: 2019-04-20 14:48:22 +0900 - - Invalidate JIT-ed code if ISeq is moved by GC.compact - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67638 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b79899b56a9ebadf5c493c4df2419ebf63934381 - Author: k0kubun - Date: 2019-04-20 14:45:56 +0900 - - Revert "Skip ISeq reference for stale_units for debugging" - - This reverts commit 4bd4d4e4cfd164f767e88f844cf10b06faee14b9. - - Sorry, let me test another one first - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4bd4d4e4cfd164f767e88f844cf10b06faee14b9 - Author: k0kubun - Date: 2019-04-20 14:44:47 +0900 - - Skip ISeq reference for stale_units for debugging - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67636 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 109633b12730484ea23bac5203a8ed6d6d820477 - Author: tenderlove - Date: 2019-04-20 14:11:37 +0900 - - Always pin stack zombie and moved slots - - We should always pin stack zombies and moved - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67635 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b25bf66a8cd34e10f436535c8b9371bca8978a2c - Author: svn - Date: 2019-04-20 14:00:45 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67634 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5d9acf07fb679aab643fd553af8b2469aa145158 - Author: svn - Date: 2019-04-20 14:00:45 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67633 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1686c0d470d56dcd7348351f0d1979d1ca1b4133 - Author: nobu - Date: 2019-04-20 14:00:43 +0900 - - Add `Time#floor` - - [Feature #15653] - [Fix GH-2092] - - From: manga_osyo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67632 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b914bea88ea0371f0b37781a2d0db03759bd5a7e - Author: k0kubun - Date: 2019-04-20 13:50:21 +0900 - - Check ISeq references in stale_units too - - This is a possible bug from recent "JIT recompile" introduction. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c98d1f182d1b5870272e25b7e636b49849f2c71c - Author: tenderlove - Date: 2019-04-20 13:13:29 +0900 - - add more assertions around moved object - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67630 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 243842f68a97a34a36a7e8c690efe7e18bf81e91 - Author: ktsj - Date: 2019-04-20 12:37:22 +0900 - - Avoid usage of the dummy empty BEGIN node - - Use NODE_SPECIAL_NO_NAME_REST instead. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67629 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 27f75cf3dc74ad70d065a7d8a14dbaa0eeac1023 - Author: k0kubun - Date: 2019-04-20 12:29:20 +0900 - - Update ISeq references in stale_units as well - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67628 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b8b503d657731fc0982c584f8b82f4976ea1283f - Author: yui-knk - Date: 2019-04-20 12:25:36 +0900 - - Add symbol to the result of `RubyVM::AbstractSyntaxTree#children`. - - Add symbol to the result to make pattern match easily. - - For example: - - (1) NODE_MASGN * NODE_SPECIAL_NO_NAME_REST - - ``` - $ ./miniruby -e 'p RubyVM::AbstractSyntaxTree.parse("a, * = b").children[-1].children' - [#, #, :NODE_SPECIAL_NO_NAME_REST] - ``` - - (2) NODE_POSTARG * NODE_SPECIAL_NO_NAME_REST - - ``` - $ ./miniruby -e 'p RubyVM::AbstractSyntaxTree.parse("a, *, _ = b").children[-1].children[-1].children' - [:NODE_SPECIAL_NO_NAME_REST, #] - ``` - - (3) NODE_LASGN * NODE_SPECIAL_REQUIRED_KEYWORD - - ``` - $ ./miniruby -e 'p RubyVM::AbstractSyntaxTree.parse("def a(k:) end").children[-1].children[-1].children[1].children[7].children[0].children' - [:k, :NODE_SPECIAL_REQUIRED_KEYWORD] - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67627 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91557d0c52de3287a319e241215803989159adcc - Author: tenderlove - Date: 2019-04-20 12:00:49 +0900 - - check the index rather than include - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67626 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 79accaf8d4dda146004eaa9a3477b31448913537 - Author: tenderlove - Date: 2019-04-20 12:00:08 +0900 - - fix strict compile errors - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67625 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c784da17448c40e55cdd231724bfe4bf53da35a1 - Author: tenderlove - Date: 2019-04-20 11:40:41 +0900 - - Update MJIT references - - ISeq can move, so we need to tell MJIT where the new location is. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67624 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6c4fd432d0242647149906f7433a9f5025819d07 - Author: tenderlove - Date: 2019-04-20 10:59:34 +0900 - - Try harder to make objects move - - Sometimes the objects we allocated may not get compacted. This change - is to increase the likelihood that they will move - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67623 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit db14ceae4217a37d40fc676d893e44177bde35b6 - Author: svn - Date: 2019-04-20 10:20:09 +0900 - - * 2019-04-20 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c74a44d64c20a7f234d0135b492a7d0f06207351 - Author: svn - Date: 2019-04-20 10:20:08 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67621 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91793b8967e0531bd1159a8ff0cc7e50739c7620 - Author: tenderlove - Date: 2019-04-20 10:19:47 +0900 - - Add `GC.compact` again. - - 🙠- - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e3d547f6df76a48834cfd9893baf4f51567b3afb - Author: k0kubun - Date: 2019-04-19 22:57:21 +0900 - - Reflect README.md contents to README.ja.md [ci skip] - - I seem to have found the svn hook bug. Let me test that again. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5b3c099ad2aac985d054c1af9728bdb0eb9b0228 - Author: nobu - Date: 2019-04-19 19:55:07 +0900 - - Removed extra empty lines - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4cfc6cedc46c3bf95497290092a63028d6b4e3b2 - Author: nobu - Date: 2019-04-19 19:45:16 +0900 - - template/prelude.c.tmpl: allow UTF-8 characters - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67617 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f1a33775494f1b81d6f6722817f1c7e5db61a27c - Author: k0kubun - Date: 2019-04-19 18:23:13 +0900 - - Use similar line length in README [ci skip] - - still debugging svn hook... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit af56793a8d7e120e33b9327a8d52c18a6a1c76d8 - Author: k0kubun - Date: 2019-04-19 18:09:46 +0900 - - README.md simplified [ci skip] - - - "do system management tasks" -> "manage the system" - - "talk about" -> "discuss" - - "The URL of the Ruby home page is:" and "This is what you need to do to compile and install Ruby:" are removed because of redundancy. - - "Bugs reports should be filed" -> "Bugs should be reported" - - [Fix https://github.com/ruby/ruby/pull/2004] - - From: yzzhang-cs - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67615 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1845c9d9bae9bc0731bc5d58ecc0f5df4ea7c33d - Author: k0kubun - Date: 2019-04-19 18:00:26 +0900 - - Revert "README.md simplified [ci skip]" - - This reverts commit 41fabbcc0ef7f6e025c1af8bf0387ee9e38d655f. - - because I had a mistake in comment message. - (to commit svn hook again) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67614 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4dd1cf3b27f5a92045176129ff2d4f5d8cea466a - Author: nobu - Date: 2019-04-19 17:53:40 +0900 - - time.c: added in: option to Time.now - - * time.c (time_s_now): added in: option to Time.now as well as - Time.at. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67613 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fb042e0f0c6c7380ca1c68b3a8cb4b523ce164eb - Author: svn - Date: 2019-04-19 17:44:23 +0900 - - * remove trailing spaces. [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67612 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 41fabbcc0ef7f6e025c1af8bf0387ee9e38d655f - Author: k0kubun - Date: 2019-04-19 17:44:22 +0900 - - README.md simplified [ci skip] - - - "do system management tasks" -> "manage the system" - - "talk about" -> "discuss" - - "The URL of the Ruby home page is:" and "This is what you need to do to compile and install Ruby:" are removed because of redundancy. - - "Bugs reports should be filed" -> "Bugs should be reported" - - [Fix GH-${pr_id}] - - From: yzzhang-cs - - (merging some safe PR to test svn hook) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67611 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 390ea5442089b8507a7d88c7d8756049bfcc0d4a - Author: tenderlove - Date: 2019-04-19 15:21:55 +0900 - - Only mark the superclass if there is one - - Some classes don't have a superclass, so we should check to see if it's - there before marking. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 14626ed20a6677ab767e764c9edff83f94872f1a - Author: nobu - Date: 2019-04-19 07:30:01 +0900 - - fake.rb.in: split by whitespaces not to be affected by -F option - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67609 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c3c4e411ebd94403055360506ccac248114eebba - Author: nobu - Date: 2019-04-19 07:24:03 +0900 - - parse.y: suppress warning - - * parse.y (parser_append_options): explicitly pass $; when auto - splitting, to suppress the warning for non-nil $;. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67608 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 396c1846fa8ba1f513cfe3c846e383e4b46d2e53 - Author: svn - Date: 2019-04-19 06:57:09 +0900 - - * 2019-04-19 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67607 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3ee0648dc7a5465b2cbadd7246fc2edbd676d759 - Author: nobu - Date: 2019-04-19 06:56:55 +0900 - - io.c: warn non-nil $, - - * array.c (rb_ary_join_m): warn use of non-nil $,. - - * io.c (rb_output_fs_setter): warn when set to non-nil value. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67606 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4751caecc357c313c3c81c3d422a3cbc880c6ecc - Author: hsbt - Date: 2019-04-18 21:56:47 +0900 - - Removed deprecated executable from bundler upstream. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67605 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b86d87c81a6b2f2b494e1b23af22194c46864fb5 - Author: nobu - Date: 2019-04-18 18:56:03 +0900 - - Suppress warnings - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d1f86a1ffceb3323b4e2fac82dfc40c5a382e9e - Author: nobu - Date: 2019-04-18 18:34:40 +0900 - - string.c: warn non-nil $; - - * string.c (rb_str_split_m): warn use of non-nil $;. - - * string.c (rb_fs_setter): warn when set to non-nil value. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67603 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit eb3d3dfcc1ad61cb3040acfdf41f71c228b892e4 - Author: svn - Date: 2019-04-18 13:55:52 +0900 - - * 2019-04-18 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67602 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 80282c76a3f7caa22bc06e153a34ae69a35cc4ee - Author: kou - Date: 2019-04-18 13:55:49 +0900 - - Take over strscan maintenance - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 286f0b8ae3c30b5911199924a1779ca045afb079 - Author: hsbt - Date: 2019-04-17 22:20:02 +0900 - - Added rubygems and bundler entries. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 828353334afb893456cffdb2daca991e985af8a9 - Author: svn - Date: 2019-04-17 18:41:55 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67599 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 744e5df7156c8bb3fea61bacb1bf27d3d8698548 - Author: tenderlove - Date: 2019-04-17 18:41:41 +0900 - - Reverting compaction for now - - For some reason symbols (or classes) are being overridden in trunk - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f399134e8ff61faa81d624e2dd2e05ed61d32af1 - Author: k0kubun - Date: 2019-04-17 18:24:48 +0900 - - NEWS: note about recent changes around JIT [ci skip] - - This diff is backported from the upcoming preview release note. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67597 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0f31971ad3e846cc8d9fa3258e8b9abfe85f0f1f - Author: kazu - Date: 2019-04-17 17:53:32 +0900 - - Suppress warning in assertion too - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a2366a15bad75fb2ddec63d36aff4af4be14ff14 - Author: kazu - Date: 2019-04-17 17:39:52 +0900 - - Suppress warnings in `make test-all` - - suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!" - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ffbcf9f842d228e4a95b13f415dfc4e141e8f4f0 - Author: nobu - Date: 2019-04-17 16:35:29 +0900 - - downloader.rb: enable cache files - - * tool/downloader.rb (Downloader::Unicode.download): enable cache - files when index.html has not been modified since the previous - download, even if beta version. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67594 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c576f14039c920e40e6849657e6dd87772f6f7da - Author: nobu - Date: 2019-04-17 16:35:27 +0900 - - common.mk: download data and property files together - - * common.mk (update-unicode-files): download data and property - files together, not to download index html twice. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67593 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bd698312fa96a5a5232eb1f1943bf7eac997aa46 - Author: yui-knk - Date: 2019-04-17 16:15:08 +0900 - - Fix the format of NODE_IN node - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67592 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5141398ff060bdaa437418cc35adcbfe0f886cb0 - Author: nobu - Date: 2019-04-17 16:09:28 +0900 - - downloader.rb: use File.read instead of IO.read - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67591 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8e6c1a186c2c1ccfce2788ba307dae35e2dd03a8 - Author: nobu - Date: 2019-04-17 16:09:24 +0900 - - common.mk: update auxiliary and emoji files - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67590 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fc9f19abe853bcef2b348e2d6d7c555b677ab28d - Author: svn - Date: 2019-04-17 15:48:26 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67589 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da8cd2dc30c26e9df47b743e7d1c16025e255628 - Author: svn - Date: 2019-04-17 15:48:07 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67588 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9c9db64d7e9058dc6fc7ead3791b259685798806 - Author: ktsj - Date: 2019-04-17 15:48:05 +0900 - - Define Struct#deconstruct - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9738f96fcfe50b2a605e350bdd40bd7a85665f54 - Author: ktsj - Date: 2019-04-17 15:48:03 +0900 - - Introduce pattern matching [EXPERIMENTAL] - - [ruby-core:87945] [Feature #14912] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67586 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b077654a2c89485c086e77c337d30a11ff3781c3 - Author: svn - Date: 2019-04-17 15:16:39 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67585 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 281a22a39864602938cd881265243a3bb60df792 - Author: tenderlove - Date: 2019-04-17 15:16:35 +0900 - - Super should be marked regardless of whether or not ext exists - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67584 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7bd58a4e6d214b78645f0a15dcc691d3faaa1acf - Author: tenderlove - Date: 2019-04-17 15:13:11 +0900 - - update super even if there is no ext - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e1eb54b99d592c460fea4b0f897f5e8e61c96c07 - Author: nobu - Date: 2019-04-17 14:34:46 +0900 - - string.c: improve splitting into chars - - * string.c (rb_str_split_m): improve splitting into chars by an - empty string, without a regexp. - - Comparison: - to_chars-1 - built-ruby: 1273527.6 i/s - compare-ruby: 189423.3 i/s - 6.72x slower - - to_chars-10 - built-ruby: 120993.5 i/s - compare-ruby: 37075.8 i/s - 3.26x slower - - to_chars-100 - built-ruby: 15646.4 i/s - compare-ruby: 4012.1 i/s - 3.90x slower - - to_chars-1000 - built-ruby: 1295.1 i/s - compare-ruby: 408.5 i/s - 3.17x slower - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67582 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 62c07674e06443075872bdc11662de6408bd00d2 - Author: tenderlove - Date: 2019-04-17 14:19:05 +0900 - - make verification more strict - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67581 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dbc9f43cb38acc037b152949a9f7b98362a6dcac - Author: tenderlove - Date: 2019-04-17 13:05:29 +0900 - - call verification method in addition to compaction - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67579 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c54f9a5b101e709e98bc8306643feaddc8a3d934 - Author: svn - Date: 2019-04-17 12:17:42 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67578 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit aee9f24973271d8602cd6924266b1e6fffad3f8e - Author: svn - Date: 2019-04-17 12:17:42 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67577 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3c55b643aec09bbe779dab25b2397947eded2b9b - Author: tenderlove - Date: 2019-04-17 12:17:25 +0900 - - Adding `GC.compact` and compacting GC support. - - This commit adds the new method `GC.compact` and compacting GC support. - Please see this issue for caveats: - - https://bugs.ruby-lang.org/issues/15626 - - [Feature #15626] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fcd679ed11e3e801431f2f931dbe925edb8df0bf - Author: k0kubun - Date: 2019-04-17 02:02:35 +0900 - - Recompile without method inlining - - if cancel happens in an inlined method. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67575 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d71b78575b08f55d35194b2c091719b2c4463ea3 - Author: k0kubun - Date: 2019-04-17 02:02:16 +0900 - - Introduce frame-omitted method inlining - - for ISeq including only leaf and no-handles_sp insns except leaf. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67574 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b914166fcdba3faf5d4cb5e3a18d49691546ce21 - Author: svn - Date: 2019-04-17 02:01:07 +0900 - - * 2019-04-17 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67573 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b0614decfc2c756abd37347477f262bb09c27233 - Author: k0kubun - Date: 2019-04-17 02:01:05 +0900 - - Implement single-level basic method inlining in JIT - - "Basic" means it does not omit a call frame. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67572 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dcf5c19c9f89d732da70a1a16a2fe60cd1999bcc - Author: svn - Date: 2019-04-16 08:58:09 +0900 - - * 2019-04-16 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67569 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3f7c6aea3e7bd8cc8b70c2274659250f1b877de5 - Author: knu - Date: 2019-04-16 08:58:06 +0900 - - Mention SNI support in Net::IMAP - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67568 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e68495e5f4dfd466ad56f745502d1d78cdba07de - Author: k0kubun - Date: 2019-04-15 23:38:57 +0900 - - Carve out mjit_compile_body - - This refactoring is needed for implementing inlining later. - I've had this since long ago and it has conflicted sometimes. So let me - just commit this now. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67566 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 246723a34ce5024e1d018cee4327dcce1bbd55c6 - Author: knu - Date: 2019-04-15 19:52:34 +0900 - - Support SNI (Reapplying r67488) - - This fixes connecting using TLS 1.3 to imap.gmail.com - - [Fix GH-2077] [Feature #15594] - - From: Marc-Antoine Perennou - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67563 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3791bdf08084b40f0e6f499a83715639c7d25b1e - Author: kou - Date: 2019-04-15 11:05:03 +0900 - - Import CSV 3.0.9 - - This fixes test failures on Windows. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e3b6c7c7ebca1b051dbaa6f33494e92f5638fcc9 - Author: kou - Date: 2019-04-15 06:01:51 +0900 - - Import CSV 3.0.8 - - This includes performance improvements and backward incompatibility - fixes. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67560 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fb96811d15f83c6b692e8e00d458eef32032af6a - Author: k0kubun - Date: 2019-04-15 00:25:11 +0900 - - Drop obsoleted debugging output [ci skip] - - I confirmed that it's working now in - https://dev.azure.com/rubylang/ruby/_build/results?buildId=396&view=logs&jobId=8c5967c9-8e3a-5773-c80c-34c55d5c3051 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67559 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ad9c5c5db69a1e94a980a5b0d09bacca8b0c647e - Author: svn - Date: 2019-04-15 00:13:50 +0900 - - * 2019-04-15 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67558 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 17b606d8b356d732dbc0fb38c9ab05a5a28d3939 - Author: k0kubun - Date: 2019-04-15 00:13:49 +0900 - - Fix broken variable propagation on Azure - - It looks like the old definition was not working as intended... - https://dev.azure.com/rubylang/ruby/_build/results?buildId=394 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67557 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 816c5323fe82a7a4502f35ab8252ed56a6251688 - Author: marcandre - Date: 2019-04-14 22:47:24 +0900 - - OpenStruct: improve error message when passing wrong number of arguments. - - Patch by Lisa Ugray (issue #15515) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67556 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1119bb4794b32fc0edfc95ba12f02bf151c170c5 - Author: k0kubun - Date: 2019-04-14 22:42:13 +0900 - - Debug bundled-gems allow_failures - - it seems not working in - https://dev.azure.com/rubylang/ruby/_build/results?buildId=392 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ead870d7c3b95bc51bd404541e087352ed7bf464 - Author: k0kubun - Date: 2019-04-14 22:29:22 +0900 - - Do not require Ruby 2.4 for baseruby - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67554 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b041cf55bbd39ca690843b455e76e914869b8753 - Author: k0kubun - Date: 2019-04-14 22:10:14 +0900 - - Fix missing debug counter name - - r67550 introduced the typo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67553 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 009a0a3870656268d00e98a12311bfcc70f54a18 - Author: k0kubun - Date: 2019-04-14 21:49:20 +0900 - - Avoid crash on logging GC-ed ISeq - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67552 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e45c9a40a2ee2ca241565f5953af116cd2b5ab29 - Author: k0kubun - Date: 2019-04-14 21:40:44 +0900 - - Do not execute MJIT copy job when ISeq is GC-ed - - I assumed that ISeq is never GC-ed by `in_jit` + `mjit_mark` on copy job - ISeq, but unfortunately I found SEGV on `mjit_copy_job_handler` in which - iseq->body was somehow Qnil. And it seems to be fixed by disabling the - job when `mjit_free_iseq` is called for the ISeq. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67551 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 12225347198344590af4a4a55ac1f90591a21dac - Author: k0kubun - Date: 2019-04-14 21:25:23 +0900 - - Share optimization cancel handlers - - $ benchmark-driver benchmark.yml --rbenv='before --jit;after --jit' -v --output=all --repeat-count=12 - before --jit: ruby 2.7.0dev (2019-04-14 trunk 67549) +JIT [x86_64-linux] - after --jit: ruby 2.7.0dev (2019-04-14 trunk 67549) +JIT [x86_64-linux] - last_commit=Share optimization cancel handlers - Calculating ------------------------------------- - before --jit after --jit - Optcarrot Lan_Master.nes 69.55360655447375 74.15329176797863 fps - 73.74545038318978 79.60903046141544 - 75.85637357897092 82.00930075612054 - 77.10594124022951 82.56228187301674 - 78.67350527368366 83.37512204205953 - 79.97235230767613 83.41521927993719 - 81.03050342478066 84.20227901852776 - 81.61308297895094 84.73733526226468 - 82.06805141753206 85.27884867863791 - 82.46493179193394 85.36558922650367 - 83.85259832896313 85.39993587223481 - 84.02325292922997 85.63649355214602 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67550 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 04ac63fe57d3643dac0c0779d32f0b89ec9e2f15 - Author: k0kubun - Date: 2019-04-14 18:31:24 +0900 - - Prefer uintptr_t over ptrdiff_t for i686 - - as debugged in PR - - [close https://github.com/ruby/ruby/pull/2130] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67549 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c5570cf9bde992f3d14a6382f1038fb422182f45 - Author: k0kubun - Date: 2019-04-14 17:53:19 +0900 - - Detect send-compatible opt insns automatically - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67548 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b75bb06e00ab4d8b77ebd9b476ecf945f8b7f72a - Author: k0kubun - Date: 2019-04-14 17:33:43 +0900 - - Allow falling back to non-inlined opt_send_without_block - - for opt_aref with inline cache to minimize the possibility of JIT cancel. - - Also opt_aset and opt_mod are added for the targets. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67547 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 18b5148215df99cebb0ba27f45f0dc7e0599737a - Author: k0kubun - Date: 2019-04-14 16:12:44 +0900 - - Add debug counter for MJIT stale_units - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67546 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f7035dd3ff665dce14657cf244c10c2d4b2b43c7 - Author: k0kubun - Date: 2019-04-14 16:10:34 +0900 - - Do not reset non-increment-only counters - - to prevernt underflow. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67545 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5ce28c0642591a950e5757150137253cb8d0b9a9 - Author: k0kubun - Date: 2019-04-14 15:57:21 +0900 - - Add RubyVM.reset_debug_counters when RB_DEBUG_COUNTER - - is defined. It's 0 by default and so it disappears on actual build. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67544 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 57f9a700d719c0ab0a9ade41ebecac022a2a06d4 - Author: kazu - Date: 2019-04-14 15:52:37 +0900 - - Add more debug print for random CI failure on osx Travis - - see r67347 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67543 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3ac518f9bdd413cf2217b101bd5c62deadfbee2a - Author: hsbt - Date: 2019-04-14 15:05:27 +0900 - - Enabled to some bundler examples again. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67542 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2e8b9aba9bef6c913e5b2de25b24026943438519 - Author: hsbt - Date: 2019-04-14 15:03:58 +0900 - - Skip to failing examples on ruby core repository. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 59fa1232045b1a19c5beae8d8a3b51b66b1aeb2d - Author: hsbt - Date: 2019-04-14 15:02:47 +0900 - - Added rspec dependency for bundler examples. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67540 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 68ddd4d300e9a88737c4f37af74e1a0312949b2f - Author: hsbt - Date: 2019-04-14 15:01:35 +0900 - - Merge Bundler 2.1.0.pre.1 as developed version from upstream. - - https://github.com/bundler/bundler/commit/a53709556b95a914e874b22ed2116a46b0528852 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67539 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d636809c057432e8d42abe30c6c6785eb0721d77 - Author: k0kubun - Date: 2019-04-14 14:52:14 +0900 - - Revert "Try to set false explicitly" - - This reverts commit a1b5d20068a9b1859b383b249e510cd33d196e4a. - - Revert "Revert "Skip recompiling tests on i686 Linux"" - - This reverts commit 7b88a9207b97b94bc3c3be35084c742296f4aff2. - - Revert "Simplify matrix for debugging" - - This reverts commit e85d6c5c5e62dde37c6f6ffdb7125b9008b9ebfa. - - Sorry, these 3 commits were under debugging in - https://github.com/ruby/ruby/pull/2129 but accidentally merged by using - `git svn dcommit` instead of `git push` to the topic branch :bow: - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67538 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a1b5d20068a9b1859b383b249e510cd33d196e4a - Author: k0kubun - Date: 2019-04-14 14:48:40 +0900 - - Try to set false explicitly - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67537 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7b88a9207b97b94bc3c3be35084c742296f4aff2 - Author: k0kubun - Date: 2019-04-14 14:48:39 +0900 - - Revert "Skip recompiling tests on i686 Linux" - - This reverts commit 19513c88d5f923abb7f226520192aef9f3fcc1c7. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67536 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e85d6c5c5e62dde37c6f6ffdb7125b9008b9ebfa - Author: k0kubun - Date: 2019-04-14 14:48:38 +0900 - - Simplify matrix for debugging - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67535 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 661cefc5812b5f206b2af9640d7ad2e6efd0913e - Author: k0kubun - Date: 2019-04-14 14:40:18 +0900 - - Fix typo in platform matcher - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fa13bb1a6f0894d92b85337385058330eb071eea - Author: k0kubun - Date: 2019-04-14 14:26:46 +0900 - - Unify comment styles across MJIT sources - - I'm writing `//` comments in newer MJIT code after C99 enablement - (because I write 1-line comments more often than multi-line comments - and `//` requires fewer chars on 1-line) and then they are mixed - with `/* */` now. - - For consistency and to avoid the conversion in future changes, let me - finish the rewrite in MJIT-related code. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67533 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19513c88d5f923abb7f226520192aef9f3fcc1c7 - Author: k0kubun - Date: 2019-04-14 14:26:23 +0900 - - Skip recompiling tests on i686 Linux - - somehow they are filing like - https://travis-ci.org/ruby/ruby/jobs/519830085 - but they are not so fatal. - - Let me just skip them for now and fix tests afterwards. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67532 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d6d8fc2421c8171ef4f57d61c5b544e05ec5d468 - Author: svn - Date: 2019-04-14 13:52:04 +0900 - - * 2019-04-14 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67531 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9b6b4674d77da2ef3f9f15095af9e39cc966b882 - Author: k0kubun - Date: 2019-04-14 13:52:02 +0900 - - Recompile JIT-ed code without optimization - - based on inline cache when JIT cancel happens by that. - - This feature was in the original MJIT implementation by Vladimir, but on - merging MJIT to Ruby it was removed for simplification. This commit adds - the functionality again for the following benchmark: - - https://github.com/benchmark-driver/misc/blob/52f05781f65467baf895bf6ba79d172c9b0826fd/concurrent-map/bench.rb - (shown float is duration seconds. shorter is better) - - * Before - ``` - $ INHERIT=0 ruby -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) [x86_64-linux] - -- - 1.6507579649914987 - - $ INHERIT=0 ruby -v --jit bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) +JIT [x86_64-linux] - -- - 1.5091587850474752 - - $ INHERIT=1 ruby -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) [x86_64-linux] - -- - 1.6124781150138006 - - $ INHERIT=1 ruby --jit -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) +JIT [x86_64-linux] - -- - 1.7495657080435194 # <-- this - ``` - - * After - ``` - $ INHERIT=0 ruby -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) [x86_64-linux] - last_commit=Recompile JIT-ed code without optimization - -- - 1.653559010999743 - - $ INHERIT=0 ruby --jit -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) +JIT [x86_64-linux] - last_commit=Recompile JIT-ed code without optimization - -- - 1.4738391840364784 - - $ INHERIT=1 ruby -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) [x86_64-linux] - last_commit=Recompile JIT-ed code without optimization - -- - 1.645227018976584 - - $ INHERIT=1 ruby --jit -v bench.rb - ruby 2.7.0dev (2019-04-13 trunk 67523) +JIT [x86_64-linux] - last_commit=Recompile JIT-ed code without optimization - -- - 1.523708809982054 # <-- this - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67530 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 088df9c8c26bcd7ad4de6637d9e734c26e7b72a0 - Author: k0kubun - Date: 2019-04-13 15:55:35 +0900 - - Revert "GET_CFP and ec->cfp are different" - - This reverts commit 30f71f4768e0babc60f5be6ca235d2c40268bc27. - - I've also overlooked we're doing RESTORE_REGS()... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67523 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 30f71f4768e0babc60f5be6ca235d2c40268bc27 - Author: k0kubun - Date: 2019-04-13 15:27:52 +0900 - - GET_CFP and ec->cfp are different - - When reviewing r66565, I overlooked that `GET_ISEQ()` and `GET_EP()` are - NOT `ec->cfp->iseq` and `ec->cfp->ep` but `reg_cfp->iseq` and - `reg_cfp->ep`. - - `vm_push_frame` updates `ec->cfp` and in this case we want to check the - callee's cfp and so `ec->cfp` should be checked instead. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67522 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e7f7aa87420d6542b8e4a347a037e4ce293fb845 - Author: svn - Date: 2019-04-13 09:56:14 +0900 - - * 2019-04-13 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67521 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a73dae4c53f749223a744bdd5e2179b6b877d0e2 - Author: svn - Date: 2019-04-13 09:56:14 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d3da5fbd30e174c5737ec09c6896db7e81691714 - Author: marcandre - Date: 2019-04-13 09:56:12 +0900 - - Proc.new: change deprecation warning for clarity (issue #15539) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67519 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 95a82766306641595179e23dbac3d6992b919460 - Author: svn - Date: 2019-04-12 23:32:35 +0900 - - * 2019-04-12 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 39b04bc698c8ebebc00ca38ffda01473bfbdc43b - Author: nagachika - Date: 2019-04-12 23:32:31 +0900 - - [DOC] Add `ifnone` example to `find` documentation [ci skip] - [Fix GH-2110] - - From: OKURA Masafumi - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67517 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6f866fd9eacd69520918b4e96617a2f43f4d44ec - Author: svn - Date: 2019-04-11 19:36:38 +0900 - - * 2019-04-11 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67513 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 025343654dca186444e1eafc3760ad895366c46d - Author: nobu - Date: 2019-04-11 19:36:37 +0900 - - Get rid of a magic number - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67512 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 47c82df27ff73c5181f7bd4505b4c98a96f15a0c - Author: nobu - Date: 2019-04-11 19:36:36 +0900 - - Share the exception local ID table - - [Fix GH-2115] - - From: Lourens Naudé - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67511 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cf781b0871cb8d6b7135fa74d9549ca1cdb2a846 - Author: k0kubun - Date: 2019-04-10 23:56:17 +0900 - - Set a meaningful name to all Azure jobs - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67510 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 34af06037435cba85cafb0e8b24d37904ad7cced - Author: k0kubun - Date: 2019-04-10 23:47:18 +0900 - - Try uncommenting deb-src - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67509 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 724bc97d4bca5ee12c84926faf4df49d134d7e42 - Author: k0kubun - Date: 2019-04-10 23:42:18 +0900 - - Debug latest sources.list on Azure - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67508 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1d955861ed892ead71e2e5542235d5d0f37b8276 - Author: k0kubun - Date: 2019-04-10 23:34:53 +0900 - - Try removing apt update - - trying to fix - https://dev.azure.com/rubylang/ruby/_build/results?buildId=363 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67507 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 82632d4c0c117a7728293ff955e3527487230bc1 - Author: mame - Date: 2019-04-10 21:57:39 +0900 - - ext/openssl/ossl_bn.c (ossl_bn_initialize): get rid of SEGV - - OpenSSL::BN.new(nil, 2) dumped core. - - [ruby-core:92231] [Bug #15760] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 54b93ef1ac4c81730508740ae213f6f52b0bec94 - Author: nobu - Date: 2019-04-10 21:43:34 +0900 - - compile.c: name a hidden local variable as a predefined ID - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67505 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b9e52ef8b6a004082fa341ee9c6bbbd5168e7daf - Author: nobu - Date: 2019-04-10 21:43:33 +0900 - - Adjusted styles - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67504 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d8442c43066fe2ff875c74af5c8eda35437adb1e - Author: nobu - Date: 2019-04-10 21:43:32 +0900 - - parse.y: fix fatal messages - - * parse.y (rb_parser_fatal): fix "parser" in the message which was - replaced accidentally. it is not the argument name. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67503 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c84bdda47a9710a1ba0db1c847db8e224d0eaaf9 - Author: nobu - Date: 2019-04-10 21:43:31 +0900 - - timev.h: dummy definition for TAGS - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67502 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 37994bc5322c02a21e8905d373bef802cac91f72 - Author: svn - Date: 2019-04-10 18:16:01 +0900 - - * 2019-04-10 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67501 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 481481b81aaca7cc5de3982784f68981335005a7 - Author: svn - Date: 2019-04-10 18:16:00 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67500 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 25c1fd3b9037d9eb39596bb994eeabed812adada - Author: kazu - Date: 2019-04-10 18:15:21 +0900 - - Reverting all commits from r67479 to r67496 because of CI failures - - Because hard to specify commits related to r67479 only. - So please commit again. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67499 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0cc2ffbc1bf135a3b7a8656b9242e87b1ad96d6c - Author: svn - Date: 2019-04-10 17:03:48 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67498 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 83fc324d1dfb2bec7d683509e25e3cc17dbecf18 - Author: mame - Date: 2019-04-10 17:03:47 +0900 - - ext/openssl/ossl_bn.c (ossl_bn_initialize): get rid of SEGV - - OpenSSL::BN.new(nil, 2) dumped core. - - [ruby-core:92231] [Bug #15760] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67497 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91db3b6c6b0daff732c0bacfcc4db397f1df4a42 - Author: nobu - Date: 2019-04-10 16:18:25 +0900 - - compile.c: name a hidden local variable as a predefined ID - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67496 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b8e3a4bd2c3e5c508e6bd48f6686969c085042ce - Author: nobu - Date: 2019-04-10 15:44:43 +0900 - - id_table.c: use NULL as ID* instead of Qundef - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 33721b4d3306b68188ea253eb0cd717dfa71f917 - Author: nobu - Date: 2019-04-10 15:44:42 +0900 - - vm_method.c: fix a warning - - * vm_method.c (rb_add_method_iseq): use rb_method_iseq_t, as - rb_method_definition_set refers, with a cast to suppress a - warning. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67494 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5ae753dfa3632a8bc4a4141ff67e8fc9554ca7a0 - Author: nobu - Date: 2019-04-10 15:44:41 +0900 - - Adjusted styles - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cc02df324f74fc84b9eae1e66bdf38f4422c249b - Author: nobu - Date: 2019-04-10 14:12:33 +0900 - - parse.y: fix fatal messages - - * parse.y (rb_parser_fatal): fix "parser" in the message which was - replaced accidentally. it is not the argument name. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67492 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e86bf9a4d768df94c084c3cc8c0786bacad0f31a - Author: nobu - Date: 2019-04-10 10:34:44 +0900 - - timev.h: dummy definition for TAGS - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67491 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9e448d2fd7490636a9c3553f44d7db5334b04f39 - Author: nobu - Date: 2019-04-10 10:18:01 +0900 - - compile.c: cast iseqs to suppress warnings - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67490 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d099eabbb7c0d493dbf6c665aceaf4738fc68d0e - Author: tenderlove - Date: 2019-04-10 08:48:17 +0900 - - Set a write barrier between iseq and mark objects - - ISeq pins references in the mark array during compile, so it manually - marks references in the mark_ary. This was causing write barrier - misses, so we need to add a write barrier when pushing on the mark - array. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67489 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e553d94f01ab5c101c26627132ed12e30a00e8f7 - Author: shugo - Date: 2019-04-10 08:35:02 +0900 - - Support SNI - - This fixes connecting using TLS 1.3 to imap.gmail.com - - [Fix GH-2077] [Feature #15594] - - From: Marc-Antoine Perennou - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67488 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 73f891f1a5dafb1709b333d953ad8b50af7ee1f9 - Author: tenderlove - Date: 2019-04-10 08:23:39 +0900 - - fix RMoved definition location - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67487 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 70cd493b050f6328f2dbe43dad6741d9f0a96d92 - Author: tenderlove - Date: 2019-04-10 08:23:33 +0900 - - Don't fail the build if we can't get objects to move - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67486 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e900bba9454f8d1a75ac5aa68a15ac21e04c5340 - Author: tenderlove - Date: 2019-04-10 08:03:40 +0900 - - Pin weakmap references - - Weak map references can't move because the st_table needs their address - as a key. But, we also need to remove T_NONE from the map so they - aren't reused. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b84b8adc8910a877bf9217f95b5bfb0eea268e5a - Author: tenderlove - Date: 2019-04-10 06:40:07 +0900 - - Just a check to see what is breaking in CI - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67484 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e385c159da9338b14ab7fb67ce8d8398ab069d5a - Author: tenderlove - Date: 2019-04-10 06:13:32 +0900 - - Add error globals to mark list so they don't move - - JSON gem is referencing constants defined in Ruby then keeping a - reference as a global. We need to register these globals so they stay - pinned. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67483 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 41f5237ed19d5e8d471d441e2cbfc3063f58b110 - Author: tenderlove - Date: 2019-04-10 05:47:36 +0900 - - Try to make compaction more likely - - This commit tries to make compaction more likely by allocating some - objects and then throwing them away - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67482 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ca9733dc02213211a4e6fd767195cd7de36762c0 - Author: svn - Date: 2019-04-10 05:32:22 +0900 - - * 2019-04-10 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67481 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2d912017d7617ba9d9aff9b6ef52591e4b028e6b - Author: svn - Date: 2019-04-10 05:32:22 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67480 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3ef4db15e95740839a0ed6d0224b2c9562bb2544 - Author: tenderlove - Date: 2019-04-10 05:32:04 +0900 - - Adding `GC.compact` and compacting GC support. - - This commit adds the new method `GC.compact` and compacting GC support. - Please see this issue for caveats: - - https://bugs.ruby-lang.org/issues/15626 - - [Feature #15626] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67479 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c09e35d7bbb5c18124d7ab54740bef966e145529 - Author: nobu - Date: 2019-04-09 22:08:30 +0900 - - NEWS: [DOC] markup hyphens [ci skip] - - * NEWS: [DOC] markup command line options, not to convert - successive hyphens to an en-dash unintentionally. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67478 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ed958ef37ef85f7e2dcaf444ccb156f4bf611bce - Author: nobu - Date: 2019-04-09 22:08:29 +0900 - - NEWS: [DOC] fold lines [ci skip] - - * NEWS: [DOC] fold lines not to make the BTS references wrong - links, without a backslash. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67477 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a2429de63ce82c48a2c08ec4b0f9e89f700345cf - Author: duerst - Date: 2019-04-09 18:41:00 +0900 - - mention support for Unicode Version 12.1.0 (issue #15195) in NEWS - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67476 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 49255fd703a20f7a02eb3ba23ed63350a403072b - Author: svn - Date: 2019-04-09 10:27:37 +0900 - - * 2019-04-09 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67475 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 320c98b436b5277678907b9ba32e4c6cdd3678a0 - Author: nobu - Date: 2019-04-09 10:27:36 +0900 - - date: support for Reiwa, new Japanese era - - [Feature #15742] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67474 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 63e66f08b6b524aff2bce99e30ef4fb343b2fe30 - Author: nobu - Date: 2019-04-09 10:27:35 +0900 - - date_core.c: [DOC] Heisei will be assumed if no-era [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d10451f3fd51f577e704db770de48d05044eb45c - Author: nobu - Date: 2019-04-08 22:47:37 +0900 - - object.c: fix searching nested const paths - - * object.c (rb_mod_const_get, rb_mod_const_defined): nested const - paths should not search from toplevel constants. - [ruby-core:92202] [Bug #15758] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67472 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e1b592b508c72a56ae012869d97fe1580ff87246 - Author: nobu - Date: 2019-04-08 22:47:36 +0900 - - test_module.rb: fix a typo - - * test/ruby/test_module.rb (TestModule#test_nested_get): fix a - typo. nested module's name is a qualified path. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67471 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7a4c39c5f25c7bed475f65e45c76a646ad993d8b - Author: nobu - Date: 2019-04-08 14:06:43 +0900 - - struct.c: force hash values fixable - - * struct.c (rb_struct_hash): force hash values fixable on LLP64 - environment. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67470 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b29f55c5acc4addabc7ffa94e022e40b36255abb - Author: svn - Date: 2019-04-08 12:26:29 +0900 - - * 2019-04-08 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67469 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ae6c195f30f76b1dc4a32a0a91d35fe80f6f85d3 - Author: nobu - Date: 2019-04-08 12:26:29 +0900 - - range.c: force hash values fixable - - * range.c (range_hash): force hash values fixable on LLP64 - environment. [ruby-core:92194] [Bug #15757] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b5baceda18fd6e93f8db29f79055a004f6419e1d - Author: nobu - Date: 2019-04-08 12:26:28 +0900 - - range.c: force hash values fixable - - * range.c (method_hash): force hash values fixable on LLP64 - environment. [ruby-core:92191] [Bug #15756] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67467 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 06eece87c6e8b969a73aa80ac659f09eb9dcbbcb - Author: nobu - Date: 2019-04-08 12:26:27 +0900 - - enumerator.c: force hash values fixable - - * enumerator.c (arith_seq_hash): force hash values fixable on - LLP64 environment. [ruby-core:92190] [Bug #15755] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 012faccf040344360801b0fa77e85f9c8a3a4b2c - Author: eregon - Date: 2019-04-07 20:26:27 +0900 - - doc/signals.rdoc: Clarify a bit where Signal.trap handlers are executed - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67465 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b7c4e6d11c9d29ed4b5efa7606dc400216827bc4 - Author: nobu - Date: 2019-04-07 20:14:06 +0900 - - gc.c: missing break - - * gc.c (obj_memsize_of): T_RATIONAL and T_COMPLEX cannot be an - imemo. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67464 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 575735664b1b77924ffdc9faf87c44c67d9be363 - Author: k0kubun - Date: 2019-04-07 17:18:09 +0900 - - Add debug message for test_rinda crash - - We often see test-all worker crash on test_rinda, but for now we even - can't know which test is unstable from this output: - http://ci.rvm.jp/results/trunk_gcc5@silicon-docker/1926481 - - Let me print `caller` on the timeout failure. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67463 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 93ecb9a1de00db26f1581392ae519a6a9faeab0d - Author: svn - Date: 2019-04-07 01:03:14 +0900 - - * 2019-04-07 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bbb0db6f1c6650481ae2cd1cb771f896459c0c6b - Author: k0kubun - Date: 2019-04-07 01:03:11 +0900 - - Fix typo in a comment [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67461 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5a6b0e39a1913235d960fafb37b23a29317ccd11 - Author: k0kubun - Date: 2019-04-06 23:42:02 +0900 - - Add debug counter for VM <-> MJIT calls - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67460 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fe979e5bce4d5606d491ed25e603f5504a20c500 - Author: nobu - Date: 2019-04-06 22:21:18 +0900 - - internal.h: fix potential memory leak - - * internal.h (rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString): - create tmpbuf to keep the pointer before xmalloc which can raise - a NoMemoryError exception. extracted from - https://github.com/bear-metal/ruby/tree/transient-imemo-tmpbuf - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67459 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f15d04358827d60a708f296973c420b2c031ac5e - Author: k0kubun - Date: 2019-04-06 11:53:32 +0900 - - Cover all insns in test_jit again - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit feecc10bfcf6fb95f60f62dbfcc9b23fc15813f2 - Author: k0kubun - Date: 2019-04-06 11:42:30 +0900 - - Suppress unnecessary warnings in test_jit - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67457 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d1163b182bdd572edaa44ff000240d49acc09d6 - Author: k0kubun - Date: 2019-04-06 11:35:37 +0900 - - Resurrect a test dropped in r67442 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67456 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a26d525ae453fc59a8591d544cdba80f5e31900d - Author: k0kubun - Date: 2019-04-06 10:25:15 +0900 - - appveyor.yml: try porting r67454 to msys2 - - Trying to fix - https://ci.appveyor.com/project/ruby/ruby/builds/23639998/job/0hm9v79xlryod1ff - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b5df5296a4741839b6430c9f07cd25edbb7fb8c5 - Author: nobu - Date: 2019-04-06 09:08:04 +0900 - - appveyor.yml: Use pre-generated headers and tables - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67454 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 50eea44a27cc0b9b2c5c24b725a1119ec0c00e5c - Author: duerst - Date: 2019-04-06 08:52:15 +0900 - - remove Unicode 12.0.0 related directory and generated files - - This completes issue #15195. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67453 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4e78854080db3d18124ff9cfec9a257073e29150 - Author: svn - Date: 2019-04-06 08:16:03 +0900 - - * 2019-04-06 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67452 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cab005db92da4c867a464d2faf27ece30f61b26b - Author: duerst - Date: 2019-04-06 08:16:00 +0900 - - revert r67445, (r67446,) r67447 - - Debugging output is no longer needed because the problem has been fixed with r67449. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67451 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6e0e93e60ec55ab4a28d29d4ad70a3ad7e65c73e - Author: nobu - Date: 2019-04-05 23:44:15 +0900 - - downloader.rb: fix typo, extra % - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67450 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9dcc6f081000d9c0f11a97051654ee2091f632e0 - Author: nobu - Date: 2019-04-05 23:44:13 +0900 - - appveyor.yml: download beta version for test - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67449 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit aebc11dfe60bb9548843c22d7deb65c67d7a2915 - Author: nobu - Date: 2019-04-05 21:44:04 +0900 - - downloader.rb: quote base name - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67448 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8f734dc7b543e7662b66cffd5d698d372d9a0b7a - Author: duerst - Date: 2019-04-05 21:36:29 +0900 - - output more debug information in downloader.rb (temporary) - - Unicode file download doesn't work with Visual Studio, we need more debug output. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67447 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f6338966f15c0f77b3508ff0ceef8ea9553c5063 - Author: svn - Date: 2019-04-05 19:39:02 +0900 - - * remove trailing spaces. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67446 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7fd8cdf398456b2da0f6fe541b77826051e60624 - Author: duerst - Date: 2019-04-05 19:39:01 +0900 - - add puts statements to debug Unicode file download (temporary) - - Unicode file download doesn't work with Visual Studio, see e.g. - https://ci.appveyor.com/project/ruby/ruby/builds/23614399/job/f8vya2l7fjdfcye4 - We temporarily produce more output for debugging. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67445 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b2311c67671c69df8c390f22b3cb961f7be39a75 - Author: ko1 - Date: 2019-04-05 17:41:04 +0900 - - `rb_add_method` is void function. - - * method.h (rb_add_method): make it void function because - nobody use a return value. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4b53f843264df5694f6693a9a3461af055573fe0 - Author: svn - Date: 2019-04-05 17:15:21 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67443 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2b5bb8a0875b75f18e628c8b2df22760536bdad9 - Author: ko1 - Date: 2019-04-05 17:15:11 +0900 - - add definemethod/definesmethod insn. - - * insns.def: add definemethod and definesmethod (singleton method) - instructions. Old YARV contains these instructions, but it is moved - to methods of FrozenCore class because remove number of instructions - can improve performance for some techniques (static stack caching - and so on). However, we don't employ these technique and it is hard - to optimize/analysis definition sequence. So I decide to introduce - them (and remove definition methods). `putiseq` insn is also removed. - - * vm_method.c (rb_scope_visibility_get): renamed to - `vm_scope_visibility_get()` and make it accept `ec`. - Same for `vm_scope_module_func_check()`. - These fixes are result of refactoring `vm_define_method`. - - * vm_insnhelper.c (rb_vm_get_cref): renamed to `vm_get_cref` - because of consistency with other functions. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67442 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7fe64d17d3cd455a3f014d6f756cb201320f7f9a - Author: duerst - Date: 2019-04-05 09:58:51 +0900 - - update to Unicode Version 12.1.0 (beta) - - Unicode Version 12.1.0 adds one single character, U+32FF SQUARE ERA NAME REIWA, - for the new Japanese era starting on May 1st. 12.1.0 will be finalized only on - May 7th, so we go with the beta version because further changes in the data we - need are highly unlikely, and we want to make sure Ruby is ready for the new era. - - * common.mk: change UNICODE_VERSION to 12.1.0, UNICODE_BETA to YES - - * enc/unicode/12.1.0, enc/unicode/12.1.0/casefold.h, enc/unicode/12.1.0/name2ctype.h: - add directory and generated data files for new version - - * lib/unicode_normalize/tables.rb: update for new character - - * test/ruby/test_regexp.rb: add test for character property age=12.1 - - * test/test_unicode_normalize.rb: add test for NFKC decomposition of new character - - This (mostly) completes issue #15195. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c8d60fddc0f868a2bb8cee0a75859513afe41c0e - Author: svn - Date: 2019-04-05 08:40:51 +0900 - - * 2019-04-05 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67440 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c604219e8d79f4a224e446a4aa19711155070ef8 - Author: duerst - Date: 2019-04-05 08:40:48 +0900 - - change lib/unicode_normalize/tables.rb to single item per line to make diffs shorter - - * template/unicode_norm_gen.tmpl: Change formatting of output to produce only a - single item (or range) for each line to make future diffs shorter and easier - to understand and check. - - * lib/unicode_normalize/tables.rb: output of the above - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 59a37c028317441b4a1e6d9a1e9c69570b347ee9 - Author: nobu - Date: 2019-04-04 21:11:53 +0900 - - gmake.mk: get rid of unicode normalization table timestamp - - * common.mk, defs/gmake.mk: rid of unicode normalization tables - timestamp. update the target tables file only when only it - exists. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67438 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6f015efc64aece0d25cc25686ea63dc8ffd7a340 - Author: nobu - Date: 2019-04-04 14:26:11 +0900 - - iseq.h: Remove dead members - - * iseq.h (struct iseq_compile_data): Remove the dead ensure_node - and for_iseq members. - - [Fix GH-2108] - - From: Lourens Naudé - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67437 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6faf26689382c35d2fb8df90b096ea34c87b3ed5 - Author: nobu - Date: 2019-04-04 14:10:26 +0900 - - gmake.mk: update normalization table - - * defs/gmake.mk: try to update Unicode normalization tables file - if Unicode data files exist. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67436 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f1fb989f1a17c63af1062ea402ed50f0d6cb4efa - Author: mrkn - Date: 2019-04-04 12:34:55 +0900 - - enumerator.c: make arith_seq_first support nil begin - - * enumerator.c: (arith_seq_first): support nil begin. - - * test/ruby/test_arithmetic_sequence.rb (test_first): add assertions for - beginless and endless arithmetic sequences. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67435 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 53d3fe0643c591a9083e22ccea62e49f451fd450 - Author: mrkn - Date: 2019-04-04 12:34:53 +0900 - - ruby/test_arithmetic_sequence.rb: add assertions for beginless and endless ranges - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67434 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dcb37d06395d996b046b755d2219c4accaac0b5f - Author: mrkn - Date: 2019-04-04 12:34:52 +0900 - - range.c: support to make beginless arithmetic sequences - - * range.c (range_step): fix the guard condition so that a beginless - range can be turned into a beginless arithmetic sequence. - - * test/ruby/test_range.rb (test_step): add assertions for the above - change. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67433 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e59017354782c7cf599af39c6725486cca03297d - Author: svn - Date: 2019-04-04 10:34:56 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67432 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 22fd30e605bd9f13fa1db54316acc925721fea16 - Author: k0kubun - Date: 2019-04-04 10:34:53 +0900 - - Revert "Introduce inline cache for invokesuper" - - This reverts commit d147ad6231aebb1d478162fb8e109e0c6a696169. - - because failing on CI: - http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1916925 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e896292d64d86be9b82b29938b9f2dbadbafa0f4 - Author: svn - Date: 2019-04-04 01:06:06 +0900 - - * 2019-04-04 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67430 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d147ad6231aebb1d478162fb8e109e0c6a696169 - Author: k0kubun - Date: 2019-04-04 01:06:03 +0900 - - Introduce inline cache for invokesuper - - Looks good in micro benchmark: - ``` - $ benchmark-driver benchmark/vm2_super.yml -v --rbenv 'before;after' - before: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - after: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - last_commit=Introduce inline cache for invokesuper - Calculating ------------------------------------- - before after - vm2_super 19.265M 31.280M i/s - 6.000M times in 0.311447s 0.191813s - - Comparison: - vm2_super - after: 31280464.2 i/s - before: 19264906.2 i/s - 1.62x slower - ``` - - No significant impact to Optcarrot: - ``` - $ benchmark-driver benchmark.yml --rbenv='before;after' -v --output=all --repeat-count=12 - before: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - after: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - last_commit=Introduce inline cache for invokesuper - Calculating ------------------------------------- - before after - Optcarrot Lan_Master.nes 48.41126024010233 47.28027196127746 fps - 49.49212664510990 48.75072555488074 - 49.51485564376117 49.20650895701073 - 49.58351773328487 49.24563592659139 - 49.64022392458479 49.26292753046641 - 49.92566235019630 49.44496216868009 - 50.18022198879376 49.45467429762771 - 50.33038373991723 49.52003367348857 - 50.43202877523305 49.69190055704068 - 50.61368587766504 49.79856204866324 - 50.77975014460643 50.27764769510704 - 50.89807360753746 50.35785776505005 - ``` - - A little improvement to k0kubun/railsbench?: - ``` - $ rbenv shell before; RUBYOPT="-v" WARMUP=1 BENCHMARK=30000 bin/bench - ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - Warmup: 1 requests - Benchmark: 30000 requests - - Request per second: 897.1 [#/s] (mean) - - Percentage of the requests served within a certain time (ms) - 50% 1.01 - 66% 1.02 - 75% 1.03 - 80% 1.04 - 90% 1.08 - 95% 1.23 - 98% 2.10 - 99% 5.52 - 100% 13.26 - - $ rbenv shell after; RUBYOPT="-v" WARMUP=1 BENCHMARK=30000 bin/bench - ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux] - last_commit=Introduce inline cache for invokesuper - Warmup: 1 requests - Benchmark: 30000 requests - - Request per second: 913.0 [#/s] (mean) - - Percentage of the requests served within a certain time (ms) - 50% 0.99 - 66% 1.00 - 75% 1.01 - 80% 1.02 - 90% 1.06 - 95% 1.20 - 98% 2.12 - 99% 5.57 - 100% 12.39 - ``` - - No significant impact to discourse: - ``` - * before - categories_admin: - 50: 54 - 75: 60 - 90: 70 - 99: 86 - home_admin: - 50: 56 - 75: 65 - 90: 71 - 99: 122 - topic_admin: - 50: 64 - 75: 73 - 90: 79 - 99: 117 - categories: - 50: 32 - 75: 33 - 90: 46 - 99: 61 - home: - 50: 34 - 75: 36 - 90: 48 - 99: 56 - topic: - 50: 40 - 75: 42 - 90: 55 - 99: 83 - - * after - categories_admin: - 50: 59 - 75: 66 - 90: 80 - 99: 149 - home_admin: - 50: 54 - 75: 58 - 90: 70 - 99: 96 - topic_admin: - 50: 63 - 75: 66 - 90: 79 - 99: 115 - categories: - 50: 31 - 75: 32 - 90: 45 - 99: 65 - home: - 50: 34 - 75: 35 - 90: 49 - 99: 58 - topic: - 50: 40 - 75: 42 - 90: 55 - 99: 78 - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67429 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2482d1f9e6b770bc5f65ffde97df36066095ff2e - Author: k0kubun - Date: 2019-04-03 21:48:02 +0900 - - Partially allow failures in test-bundled-gems - - Tests of minitest randomly fails with strange errors: - https://dev.azure.com/rubylang/ruby/_build/results?buildId=303 - https://dev.azure.com/rubylang/ruby/_build/results?buildId=314 - - Instead of marking `continueOnError` for all, let me select - failure-allowed gems individually. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f4a1235abe83f8b52ac3048719fac6426469cb42 - Author: k0kubun - Date: 2019-04-03 20:16:47 +0900 - - vs2019 build is not functional now - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a6146af5bd2855f08e520fad67c39164adc507e9 - Author: svn - Date: 2019-04-03 19:56:37 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67426 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1329c7cdca5cca07e8680a28724b3f192144f04e - Author: nobu - Date: 2019-04-03 19:56:36 +0900 - - date: make zone a substring to copy encoding and taintedness - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67425 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f0204a254789608edc46515f181b1f52ec106442 - Author: kazu - Date: 2019-04-03 18:35:26 +0900 - - Revive accidentally removed assertion - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67424 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d4319541e870b3ec37ddb73d399dafcb39db35e7 - Author: mame - Date: 2019-04-03 17:35:57 +0900 - - range.c (r_cover_range_p): support beginless range - - `(..2).cover?(..1)` should return true. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67423 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 95f7992b89efd35de6b28ac095c4d3477019c583 - Author: mame - Date: 2019-04-03 17:11:41 +0900 - - Introduce beginless range [Feature#14799] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67422 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dd2479bcea6cfbfb7656ef691ad5f9ff6ae543cd - Author: tenderlove - Date: 2019-04-03 06:59:04 +0900 - - Fix more ASAN errors - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67421 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit be0f09a998c08eaa8bd4a5300e10b405cc9ae972 - Author: tenderlove - Date: 2019-04-03 06:58:59 +0900 - - Extract type to sym as a new function - - I will use this from another function in compaction - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67420 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ad67845ba82023474ed2c914e7b38859a9cd488d - Author: tenderlove - Date: 2019-04-03 06:13:22 +0900 - - Fix typo in lldb script - - Also fix tests - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67419 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 714c2b0a93a3ad2206dc93535f42987083b16ca9 - Author: svn - Date: 2019-04-03 04:13:13 +0900 - - * 2019-04-03 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67418 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e377eb0e75d6307ac379f575bf3caf0b8b08fab4 - Author: tenderlove - Date: 2019-04-03 04:13:12 +0900 - - Fix ASAN error - - This code was trying to access memory before unpoisoning it. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67417 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4283fb42bc7a4f7e6de1263756b32fdd2356bf3a - Author: tenderlove - Date: 2019-04-03 04:13:07 +0900 - - Poison / verify the freelist - - This commit just adds poisoning around the freelist to help debugging. - Also verify that the freelist only contains T_NONE objects when checking - the heap integrity - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67416 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f28be7e02d113bd26c33cb94e65004055576c065 - Author: hsbt - Date: 2019-04-02 20:48:18 +0900 - - Merge rubygems/rubygems from upstream. - - The current master branch is - https://github.com/rubygems/rubygems/commit/97b264f0fa248c864b6ee9a23d3ff1cdd217dddb - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 537024433720d7c54cba9bab4596638f59fbadc9 - Author: k0kubun - Date: 2019-04-02 19:51:35 +0900 - - Azure Pipeline tests on Linux are not reliable - - test-bundler started to fail with r67383 - https://dev.azure.com/rubylang/ruby/_build/results?buildId=278 - which is very unlikely to be Ruby implementation's fault. - - test-bundled_gems also started to fail with r67413 - https://dev.azure.com/rubylang/ruby/_build/results?buildId=303 - I'm not sure the commit is related to the failure. - - Overall, they are not useful as testing environment of Ruby itself for - now since nobody seems to take care of these CI statuses. Let's stop - reporting the status to GitHub until it becomes reliable. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67414 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 79de8e9f6ba093da4d792294f1675083634c9e3b - Author: nobu - Date: 2019-04-02 17:08:29 +0900 - - downloader.rb: keep linked file newer than cached file - - * tool/downloader.rb (Downloader.save_cache): keep linked file - newer than cached file, so that GNU make triggers when the - content is updated. it uses the timestamp of symlink itself - instead of the target. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7cd6706b9ab901b0b710a087b5aeb5654f219b09 - Author: nobu - Date: 2019-04-02 13:36:34 +0900 - - date_parse.c: name JISX0301_DEFAULT_ERA - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67412 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da0fceae3b3641c60823954e8198bf10a1b99c10 - Author: nobu - Date: 2019-04-02 13:36:33 +0900 - - date_parse.c: renamed JAPANESE prefix as JISX0301 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67411 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5f3e5e6fc5f545b5e6b496334578a16a2acf01c8 - Author: svn - Date: 2019-04-02 12:49:00 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e8f8cf111fc1cd6ee7a00b692ba208bd1c7ce539 - Author: nobu - Date: 2019-04-02 12:48:58 +0900 - - date: use del_hash to extract an element destructively - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67409 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1ad6dde9da48149f1998eb5b85916165867c2368 - Author: tenderlove - Date: 2019-04-02 08:55:02 +0900 - - Fix ASAN errors when walking the heap - - verify_internal_consistency_i and gc_verify_heap_page would walk the - heap, reading data from each slot, but would not unpoison the object - before reading. This commit unpoisons the slot before reading so that - we won't get ASAN errors - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67408 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f0f6615a25eb87e5e9954b7fec85c71f05100b7d - Author: tenderlove - Date: 2019-04-02 07:53:34 +0900 - - add regex support to lldb debug output - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f4bff3a7f944edee72118de5b762a46b1b98d463 - Author: svn - Date: 2019-04-02 07:52:39 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67406 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1286674bb9855d69f3448fb76c2721c5ac38b84c - Author: tenderlove - Date: 2019-04-02 07:52:35 +0900 - - unpoison / poison objects while walking the heap - - This fixes some ASAN errors - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67405 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 990df873029a632c06dee9de9768bda8400fe922 - Author: eregon - Date: 2019-04-02 05:46:10 +0900 - - Make spec for the jit feature more general and not MRI-specific - - * Other implementations should not define RubyVM. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67404 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 960d059ef71901980c95cd28013b7a93bc3f83d5 - Author: eregon - Date: 2019-04-02 05:45:55 +0900 - - Simplify spec as there is no easy way to tell if MJIT support is available - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67403 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d48783bb0236db505fe1205d1d9822309de53a36 - Author: svn - Date: 2019-04-02 05:35:13 +0900 - - * 2019-04-02 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67402 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c71c59feeb8edd975cc49c718dec8319e22ee2a4 - Author: eregon - Date: 2019-04-02 05:35:10 +0900 - - Fix Float#to_s specs to not depend on the platform representation of doubles - - * AIX, Solaris, etc have a different binary representation. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67401 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 321d72bdd6f26b26bc4b9989076f2d3a2fbdc9b3 - Author: nobu - Date: 2019-04-01 14:58:31 +0900 - - Added tests for end of Heisei - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67400 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 285817c6d8ed6117fc4931a32ae16aaf3c5b4c99 - Author: nobu - Date: 2019-04-01 14:28:25 +0900 - - date_parse.c: removed 'r' which is not in JIS X 0301 yet - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67399 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e836cd0b9f213084bf4a2b4c642e27c9d550a706 - Author: svn - Date: 2019-04-01 14:21:39 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67398 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 744c3140595c34171553515e127d080634704db3 - Author: nobu - Date: 2019-04-01 14:21:36 +0900 - - date_parse.c: extract Japanese era initials - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67397 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 367362b9d56bc8d9e5cafaec5abe7c987c4a831c - Author: svn - Date: 2019-04-01 00:37:47 +0900 - - * 2019-04-01 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67396 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e86970840145c4f1349dd5729e64960e5b04583 - Author: kazu - Date: 2019-04-01 00:37:45 +0900 - - exp is String, so it's always truthy - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67395 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4e0420f57749f85bebeabd509f9da73f7ae8c966 - Author: svn - Date: 2019-03-31 23:46:31 +0900 - - * 2019-03-31 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ddc5839005b91ec7a87f374d3b2606b158400817 - Author: kazu - Date: 2019-03-31 23:46:25 +0900 - - Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67389 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b84eed5dd8e2cb981a80091a58775a7d21946e5b - Author: nobu - Date: 2019-03-30 23:31:35 +0900 - - ruby.c: respect features by command line - - * ruby.c (process_options): feature options in command line - arguments take precedence over options in RUBYOPT environment - variable. [ruby-core:92052] [Bug #15738] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67388 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19e672cce9590c09b6beb3ada4ccf0e62bf6610c - Author: nobu - Date: 2019-03-30 21:39:35 +0900 - - rdoc: Colorize background of code/pre [ci skip] - - Borrowed the style of code/pre from bugs.ruby-lang.org. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67387 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 721be154946f0a13f739363c4968c548aba5fee3 - Author: nobu - Date: 2019-03-30 21:37:23 +0900 - - process.c: [DOC] remove extra quotes [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67386 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 413b12737697564a4de6bb88b2830169dc42909e - Author: nobu - Date: 2019-03-30 21:35:13 +0900 - - Fix a typo in an assertion message - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67385 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 031e2f1285e3ea37eca9a4c24d6ae25ef1c459d3 - Author: svn - Date: 2019-03-30 08:26:33 +0900 - - * 2019-03-30 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9249346c0bed3fa154a49b2ca924c205e66018ef - Author: mame - Date: 2019-03-30 08:26:31 +0900 - - mjit_worker.c: explicitly ignore the unused result of RB_DEBUG_COUNTER_INC_IF - - By adding `(void)`. This makes Coverity Scan happy. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67383 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9d047fd3e51945c8fcc3a8a97c41dc2baf016974 - Author: k0kubun - Date: 2019-03-29 23:44:09 +0900 - - Add mjit_compile_failures debug counter - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67382 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e465d6c5df2c3b6f97348b2d21037be3f55c7d38 - Author: k0kubun - Date: 2019-03-29 23:27:00 +0900 - - ruby tool/update-deps --fix - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67381 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5ee256da687f080f8ec0b12c10fc2592020e4872 - Author: k0kubun - Date: 2019-03-29 23:08:51 +0900 - - Prevent mjit length counters from being 0 - - It seems that `debug_counter_show_results_at_exit` could be called - earlier than `mjit_finish` sometimes. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67380 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b03c11a337c53c219a840eed4569e411289f0ddd - Author: k0kubun - Date: 2019-03-29 22:54:29 +0900 - - Add debug counters for MJIT cancel - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67379 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 017cb09eb6d40b3d7f7ca08db4aa16cfb91012f2 - Author: k0kubun - Date: 2019-03-29 22:24:56 +0900 - - Add debug counter for rb_mjit_unit_list - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67378 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 26d56f7b6f68058ca2321d797f86d1edd510644b - Author: kazu - Date: 2019-03-29 22:06:48 +0900 - - Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67377 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9254e1c740fd0829ad425670c770f782d20a0d82 - Author: k0kubun - Date: 2019-03-29 21:55:07 +0900 - - Debug make install instead of make - - Actually what has randomly failed was `make install`: - https://travis-ci.org/ruby/ruby/jobs/512988177 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67376 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bb5ab13bf58e0ccfe5b4c08fec8a0e70612d598c - Author: k0kubun - Date: 2019-03-29 21:52:59 +0900 - - Add debug counters for MJIT - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67375 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fe904f1eec1fe96cf148407c3c4c010de7dd8b73 - Author: k0kubun - Date: 2019-03-29 21:31:08 +0900 - - Elaborate more on some debug counters [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67374 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 49f1b71144e9e8352688caf7cb23b09b62873464 - Author: k0kubun - Date: 2019-03-29 21:00:44 +0900 - - Add some more buffer for timeout check - - This spec is unstable on our CI environment: - https://gist.github.com/ko1/efa58acf4cd1d7b5bf1f63881537afe8 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ce9e0ffd710db27f928ffa013d5d7047acb04511 - Author: svn - Date: 2019-03-29 15:36:48 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67372 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 35e677dd0ab6b042cb52e9f98e35a2d8d7dc5e14 - Author: ko1 - Date: 2019-03-29 15:36:46 +0900 - - use GET_CFP() instead of access reg_cfp directly. - - GET_CFP() macro contains performance counter logic. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67371 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fcf60d39776acf018eb7d855778f66568eb6d615 - Author: nobu - Date: 2019-03-29 10:26:23 +0900 - - process.c: [DOC] fix markups [ci skip] - - * process.c (rb_f_spawn): fix markups as rdoc. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67370 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b9ad698c8711ddb10e812b809522a865e4175718 - Author: nobu - Date: 2019-03-29 09:59:34 +0900 - - process.c: [DOC] fix markups [ci skip] - - * process.c (rb_clock_getres): fix code markups, as `+` can not - include parentheses. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67369 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f27d4354c837434a1e67fc20422c6f96bbe8dc69 - Author: nobu - Date: 2019-03-29 09:59:32 +0900 - - strip trailing spaces [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67368 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c33da35ddf14f39d622df42e0a63581636aa391c - Author: k0kubun - Date: 2019-03-29 09:49:35 +0900 - - Fix broken retry logic - - previous retry logic did not work - https://dev.azure.com/rubylang/ruby/_build/results?buildId=266 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67367 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b6c04a7ad76b8693048355d0a258731e10f111fd - Author: k0kubun - Date: 2019-03-29 01:25:25 +0900 - - Guard spec against msys2 shell - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67366 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e7477a949c157a700e70afff0675af676b57f00e - Author: k0kubun - Date: 2019-03-29 00:37:45 +0900 - - [bug:8215] seems to be still broken on mswin - - This test fails on AppVeyor mswin so often: - https://ci.appveyor.com/project/ruby/ruby/builds/23427134/job/rowv0dohwni0xa37 - https://ci.appveyor.com/project/ruby/ruby/builds/22970385/job/qdkqus13bhnyyfxf - https://ci.appveyor.com/project/ruby/ruby/builds/22970385/job/o4k8keg95ltcryoe - - Maybe it's related to https://bugs.ruby-lang.org/issues/15569. - As this test is harmful for mswin CI reliability, let me skip this at - least until somebody fixes the above issue. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67365 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 233267db34bfd74d94a5840cc582e0db7a2881c3 - Author: svn - Date: 2019-03-29 00:25:44 +0900 - - * 2019-03-29 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67364 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7ce0e96334c66af8f805d101fe35abb5742687e4 - Author: svn - Date: 2019-03-29 00:25:44 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67363 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 68987d4ae1a14d96047074599079acc2997e76e9 - Author: k0kubun - Date: 2019-03-29 00:25:43 +0900 - - Do not fail with --disable-jit-support - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67362 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a28aa80c739a1d169649a4da833ef48cfb3465b3 - Author: eregon - Date: 2019-03-28 23:22:29 +0900 - - Update to ruby/spec@e81b3cd - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67361 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0f64776745ef31e626dec0d42b7fb2a5988397ec - Author: kazu - Date: 2019-03-28 21:35:20 +0900 - - NEWS: Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67360 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b6443c62f0c3c4b002c6eaa2574da66f5635e076 - Author: k0kubun - Date: 2019-03-28 20:50:19 +0900 - - Note r67356 in NEWS [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67359 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ee5b54822cd08c11ae1b2060d28074d36aa45954 - Author: nobu - Date: 2019-03-28 19:19:08 +0900 - - parse.y: show error line separately - - * parse.y: show compile error and the error line separately, - instead of building the error message by snprintf then yyerror. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67358 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fa04b87af4300f747e3ce5cfe21b8edf85fe73b2 - Author: nobu - Date: 2019-03-28 17:39:24 +0900 - - [DOC] fix missing paren [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67357 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b3507bf147ff47e331da36ba7c8e6b700c513633 - Author: nobu - Date: 2019-03-28 12:46:48 +0900 - - erb.rb: prohibit marshaling [EXPERIMENTAL] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 978290515ea32204ff4b4173d6283050d628bd37 - Author: nobu - Date: 2019-03-28 12:33:36 +0900 - - [DOC] Fix method references to Method instance methods - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67355 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit de0ef1a9dfd9f966ad7e667788f3e333944d959e - Author: nobu - Date: 2019-03-28 12:33:35 +0900 - - [DOC] fix markups [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67354 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 832bc50768fe42f95f8dda0483f0ba1556175c9d - Author: svn - Date: 2019-03-28 08:56:17 +0900 - - * 2019-03-28 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67350 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ede77e64a7f465f9591ee9b1e9d6d7d69bfdb9af - Author: kazu - Date: 2019-03-28 08:56:14 +0900 - - Fix typos - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67349 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 41d36d2ce2a900bbb6812e23c13f35ee20f93d31 - Author: k0kubun - Date: 2019-03-27 22:31:36 +0900 - - Skip EBADF spec in MJIT test for now - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67348 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1c5fd2bff0e232aadf4b9486d086ccb6af87ceb6 - Author: k0kubun - Date: 2019-03-27 22:15:02 +0900 - - Add debug print for random CI failure on osx Travis - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67347 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b51b9d50e64170650db71ece4a6c08b3c9ae897a - Author: svn - Date: 2019-03-27 17:26:12 +0900 - - * 2019-03-27 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67346 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 191b99c89d5843bdee2bccc9ee2d34bc2b5513f0 - Author: hsbt - Date: 2019-03-27 17:26:09 +0900 - - Merge fileutils-1.2.0 from ruby/fileutils. - - It includes the following updates: - - * https://github.com/ruby/fileutils/pull/26 - * https://github.com/ruby/fileutils/pull/27 - * https://github.com/ruby/fileutils/pull/29 - * https://github.com/ruby/fileutils/pull/34 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c92c0a593593da2eb1ff94d83d80f71e7ae5343c - Author: k0kubun - Date: 2019-03-25 23:26:11 +0900 - - Prefer using vm_base_ptr rather than cfp->bp - - in MJIT implementation. - - This allows us to drop cfp->bp by just modifying vm_base_ptr in the - future. - - No performance impact: - - $ benchmark-driver benchmark.yml --rbenv='before::before --disable-gems --jit;bp_::after --disable-gems --jit;vm_env_ptr::ruby-svn --disable-gems --jit' -v --output=all --repeat-count=12 - before: ruby 2.7.0dev (2019-03-24 trunk 67341) +JIT [x86_64-linux] - bp_: ruby 2.7.0dev (2019-03-24 trunk 67342) +JIT [x86_64-linux] - vm_env_ptr: ruby 2.7.0dev (2019-03-25 trunk 67343) +JIT [x86_64-linux] - last_commit=Prefer using vm_base_ptr rather than cfp->bp - Calculating ------------------------------------- - before bp_ vm_env_ptr - Optcarrot Lan_Master.nes 77.15059205092646 70.18873044267853 69.62171387083328 fps - 78.75767783870441 77.49867689173411 75.43496867709587 - 79.60102690369321 77.78037687683523 79.36688927929428 - 80.25144236638835 78.74729849101701 80.42363742291455 - 82.22375417165489 80.44265482494045 80.90287243299306 - 82.29166786292619 80.51740049420938 81.81153053252902 - 83.35386925305345 80.91054205210609 81.93562989125176 - 83.39770634366975 81.34550754145043 82.24544621470430 - 83.88523450309972 81.60698516017347 82.76801860263230 - 84.17553130135879 82.69615943446324 83.02530407910871 - 84.42132328119858 83.00969158037691 83.19968539409922 - 84.60731429793329 83.32703363300098 83.81352746019631 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67344 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7976d0d153c021fb2e350743fbb54d239aa7acf1 - Author: svn - Date: 2019-03-25 15:58:55 +0900 - - * 2019-03-25 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67343 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8dd0fb9039bbe6152ea5542e6bc70de152871e23 - Author: ko1 - Date: 2019-03-25 15:58:50 +0900 - - use cfp->bp more. - - cfp->bp was (re-)introduced by Kokubun san, but VM doesn't use it - because I (ko1) want to remove it in a future. But using it make - leave instruction fast because of sp consistency check. - So now VM uses cfp->bp. - - To use cfp->bp, I checked the value and I found that it is not a - "initial value of sp" but a "initial value of ep". Fix this problem - and fix all bp references (this is why bp is renamed to bp_). - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67342 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9f05891c3daa79e26dd01f0575f1b595ddb7d302 - Author: svn - Date: 2019-03-24 09:28:54 +0900 - - * 2019-03-24 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67341 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 831e93d928aa1092fbbcabaa8051953de50ad9da - Author: ktsj - Date: 2019-03-24 09:28:51 +0900 - - Update power_assert to 1.1.4 - - This update fixes a failure of test-bundled-gems, so we revert r67275. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67340 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7e421044a3e1747e62c6760cde2f007223f73e0e - Author: svn - Date: 2019-03-23 19:41:20 +0900 - - * 2019-03-23 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67339 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0bd50e95f9e2357ac551bda501da91185875370e - Author: glass - Date: 2019-03-23 19:41:16 +0900 - - file.c: raise NotImplementedError instead of Errno::ENOSYS - - [Misc #15615] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67338 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 56557ec28a8712984a0e9744fd7547e797ec9b6b - Author: nobu - Date: 2019-03-22 20:04:59 +0900 - - [DOC] fix markups [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67337 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c671f836b4d123bf86bce6defe42c87caef582f8 - Author: ko1 - Date: 2019-03-22 16:57:26 +0900 - - add debug counters to count call cache fastpath. - - Add counters to count ccf (call cache fastpath) usage. - These counters will help which kind of method dispatch - is important to optimize. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67336 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d2bac1fd977d2ff76321654aece8744cac536dd - Author: svn - Date: 2019-03-22 09:21:44 +0900 - - * 2019-03-22 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67335 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a433f2c51be52042884998bb5a0048084adad4aa - Author: svn - Date: 2019-03-22 09:21:43 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67334 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 79ddbe9deebc5af0f08e52cd056f58b49e486ea6 - Author: ko1 - Date: 2019-03-22 09:21:41 +0900 - - optimize method dispatch for lead/kw params. - - similar idea to r67315, provide the following optimization - for method dispatch with lead and kw parameters. - - (1) add a special branch to check passing kw arguments to - a method which has lead and kw parameters. - ex) def foo(x, k:1); end; foo(0, k:1) - (2) add a special branch to check passing no-kw arguments to - a method which has lead and kw parameters. - ex) def foo(x, k:1); end; foo(0) - - For (1) and (2) cases, provide special dispatchers. For (2) case, - this patch only use the special dispatcher if all default - kw parameters are literal values (nil, 1, and so on. In other case, - kw->default_values does not contains Qundef) (and no required kw - parameters becaseu they don't pass any keyword parameters). - - Passing keyword arguments with a hash object is not a scope of - this patch. - - Without this patch, (1) and (2) cases use `setup_parameters_complex()`. - Especially, (2) seems frequent case for methods which extend a normal - usecase with keyword parameters (like: `exception: true`). - - We can measure the performance with benchmark-driver: - With methods: def kw k1:1, k2:2; end - def m; end - With the following binaries: - clean-miniruby: unmodified trunk. - opt_miniruby1: use special branches for lead/kw parameters. - opt_miniruby2: use special dispatchers for lead/kw parameters. - opt_cc_miniruby: apply step (2). - Result with benchmark-driver: - - m - opt_miniruby2: 75222278.0 i/s - clean-miniruby: 73177896.5 i/s - 1.03x slower - opt_miniruby1: 62466783.3 i/s - 1.20x slower - - kw - opt_miniruby2: 52044504.4 i/s - opt_miniruby1: 29142025.7 i/s - 1.79x slower - clean-miniruby: 20515235.4 i/s - 2.54x slower - - kw k1: 10 - opt_miniruby2: 26492219.5 i/s - opt_miniruby1: 25409484.9 i/s - 1.04x slower - clean-miniruby: 20235113.7 i/s - 1.31x slower - - kw k1: 10, k2: 20 - opt_miniruby1: 24159534.0 i/s - opt_miniruby2: 23470527.5 i/s - 1.03x slower - clean-miniruby: 17822621.5 i/s - 1.36x slower - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67333 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0f63d961169989a7f6dcf7c0487fe29da178a4d2 - Author: shirosaki - Date: 2019-03-21 22:32:03 +0900 - - dir.c: fix Dir.glob starts with brace - - * dir.c (ruby_glob0): expand braces if a glob pattern starts with - brace. - [ruby-core:91728] [Bug #15649] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67332 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 638c96858274deb90b2b923477d6b9525e1ed065 - Author: nobu - Date: 2019-03-21 21:01:36 +0900 - - array.c: [DOC] remove unnecessary markups [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67331 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 969156ce9a04b92ffc5b048cfbe666ae1f7b1cbd - Author: k0kubun - Date: 2019-03-21 15:48:00 +0900 - - Check argument_arity_error condition in inlinable_iseq_p - - to avoid inlining a method call when it becomes argument_arity_error, - fixing a potential bug. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67330 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 52bd8f6f68a45cb990a827e4a1c276251cdf471c - Author: k0kubun - Date: 2019-03-21 15:25:09 +0900 - - Share vm_call_iseq_optimizable_p to reduce copy-paste - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67329 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a8695d5022d7afbf004765bfb86457fbb9d56457 - Author: k0kubun - Date: 2019-03-21 14:59:57 +0900 - - Make rb_iseq_only_optparam_p static - - because it's not used outside vm*.c, and also having non-static function - without MJIT_STATIC is harmful for mswin JIT system. - - I hope this fix mswin test failure starting from r67315. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67328 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3c4b7898d82f0a57cc3d034a246c28093c5f2dfd - Author: svn - Date: 2019-03-21 14:59:16 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67327 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e1038377a9c8ec8002d07cfdbca6a1c0cca1fc8c - Author: mame - Date: 2019-03-21 14:59:14 +0900 - - Fix a wrong lineno in backtrace for cfunc - - lineno is an int, and INT2FIX(0) was assigned. - - [Bug #15719] [ruby-core:91911] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67326 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b8540a3c2eb375d1634a451574404d8cb4502f98 - Author: k0kubun - Date: 2019-03-21 14:44:26 +0900 - - Show retry's stdout as well - - because stderr did not have sufficient information - https://ci.appveyor.com/project/ruby/ruby/builds/23242505/job/dirugxujk70nnhp6 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67325 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ae0f20c6bf45fdf4e50bc6cc69577cb94cc44ed8 - Author: k0kubun - Date: 2019-03-21 14:30:27 +0900 - - Retry vcpkg install failures - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67324 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9810c08a5dd0f327f3d2fe2bd61874673ddece11 - Author: k0kubun - Date: 2019-03-21 13:49:45 +0900 - - Explain why cl.exe needs --jit-verbose=2 [ci skip] - - I forgot to explain it in the previous commit - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67323 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 81de7b9e622ecb57a607af8ba7c341ab8c659a4d - Author: k0kubun - Date: 2019-03-21 13:47:59 +0900 - - Insert --jit-verbose=2 logs for mswin debugging - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67322 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7aacb650153db6eb341907dff8c3f8445717e556 - Author: kazu - Date: 2019-03-21 12:24:59 +0900 - - Remove duplicated and change order - - `reg*` affects `doc/regexp.rdoc`, but it is not a file of the Oniguruma/Onigmo regular expression engine. - `reg*.[ch]` matches `reg*` except `doc/regexp.rdoc`. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67321 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f2ea705d68d7e814e68c2df4598b95106e280e49 - Author: hsbt - Date: 2019-03-21 08:32:11 +0900 - - Add Enumerator::Lazy docs. - - * explanation of the class concept, with examples; - * docs for all class methods (most of them just say "Like Enumerable#, but chains operation to be lazy-evaluated.", but I believe they are useful this way because now have proper call-sequences and link to corresponding Enumerable's explanations) - * simplified example for ::new to emphasize the main concept - * Enumerable#lazy docs are slightly lightened and linked to this class for more in-depth explanations. - - [Misc #15529][ruby-core:91046] - - Co-authored-by: zverok - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67320 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e8e1f72d8fae3d010a1a5bec90c897aee9f08ce0 - Author: ko1 - Date: 2019-03-21 05:37:03 +0900 - - remove redundant check. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67319 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit df2af1147fc250cee73853cd9c78d5afeb9e2591 - Author: ko1 - Date: 2019-03-21 05:26:21 +0900 - - fix a type error with a cast for clang. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67318 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 02df0f38df43395debdab80a24fabd8a0e3eb097 - Author: svn - Date: 2019-03-21 04:57:44 +0900 - - * 2019-03-21 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67317 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5c439ebfb076ac0b16e60dc83f3a56532e85b3c9 - Author: svn - Date: 2019-03-21 04:57:43 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67316 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 24e03d7e268f5b89367d495ee2b4aac0b700e6e1 - Author: ko1 - Date: 2019-03-21 04:57:39 +0900 - - optimize method dispatch for lead/opt params. - - There is a special optimization for "only lead parameters" - method dispatch using specialized dispatcher functions - `vm_call_iseq_setup_normal_0start...`. - Other cases (opt, rest, post, ...) we don't use specialized - dispatcher and call with `setup_parameters_complex` to - satisfy Ruby's complex parameter specification. - - This commit introduce a specialize dispatcher for - methods which use only lead and optional parameters. - - Two step improvements: - (1) prepare "lead/opt" only check pass. - It is to skip the `setup_parameters_complex` function. - (2) introduce specialized dispatcher for only "lead/opt" - parameters methods (vm_call_iseq_setup_normal_opt_start). - - With these improvements, we achieved good micro-benchmark - results: - With a method: `def opt2 a, b=nil; end` - With the following binaries: - clean-miniruby: unmodified trunk. - opt_miniruby: apply step (1). - opt_cc_miniruby: apply step (2). - Result with benchmark-driver: - - opt2(1) - opt_cc_miniruby: 42269409.1 i/s - opt_miniruby: 36304428.3 i/s - 1.16x slower - clean-miniruby: 25897409.5 i/s - 1.63x slower - - opt2(1, 2) - opt_cc_miniruby: 45935145.7 i/s - opt_miniruby: 40513196.9 i/s - 1.13x slower - clean-miniruby: 29976057.6 i/s - 1.53x slower - - This improvement may be trivial (difficult to improve practical - cases). However, this is enough small patch so I decide to - introduce it. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 139634a16fc5fa6779b08aeb89f40b289579c4bf - Author: nobu - Date: 2019-03-20 13:24:42 +0900 - - vm_trace.c: [DOC] remove the trick [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67314 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b55586902dbd3df7b749fd1463dacbe871550adc - Author: hsbt - Date: 2019-03-20 11:08:34 +0900 - - Improve TracePoint docs. - - * Mention new :script_compiled event; - * Deduplicate __enable/enable methods; - * Document target: and target_line: arguments. - - [Bug #15484][ruby-core:90801] - - Co-authored-by: zverok - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67313 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 46968fab0a0cec4a3e6e37f30b13d20998ba5e7a - Author: nobu - Date: 2019-03-20 10:35:27 +0900 - - string.c: [DOC] fix reference to sprintf [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67312 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b49e5b47d26228602f2dd57a81a6c12b1a19dde - Author: nobu - Date: 2019-03-20 10:31:44 +0900 - - string.c: [DOC] remove unnecessary markups [ci skip] - - * string.c: remove markups, which are not only unnecessary - but also prevented cross-references. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67311 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a265141c84f5b62d3dce62db1cf47d0c88dce601 - Author: nobu - Date: 2019-03-20 10:17:16 +0900 - - string.c: [DOC] fix indent [ci skip] - - * string.c (rb_str_crypt): fix indent not to make the whole list - verbatim entirely. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67310 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit eee58ca61134447e2f2140f9bf5366dc1495d7fe - Author: svn - Date: 2019-03-20 09:31:13 +0900 - - * 2019-03-20 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67309 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 740248425c5a47cb3f73eda97b42d52ef1070349 - Author: nobu - Date: 2019-03-20 09:31:02 +0900 - - parse.y: make tNUMPARAM id - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67308 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit afa1505ca89bd350558f1f42b96f1eee781ef019 - Author: nobu - Date: 2019-03-19 15:23:36 +0900 - - parse.y: removed redundant number_arg parser event - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67307 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fa66569afa0614ab27d941a68fb99e7adc1d2d48 - Author: nobu - Date: 2019-03-19 15:01:21 +0900 - - parse.y: fix var_ref of numbered param in ripper - - * parse.y (string_dvar, user_variable): register numbered - parameter in ripper for var_ref. - [ruby-core:91867] [Bug #15673] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67306 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e39f7e64b73f0506def7adc88226d6821608da54 - Author: nobu - Date: 2019-03-19 11:35:50 +0900 - - parse.y: fix segv with Ripper#yydebug - - * parse.y (parser_token_value_print): in ripper, ID values are - wrapped in NODE_RIPPER at set_yylval_name(), so print the Symbol - wrapped together. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67305 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ae5d9a7664e9664102b1ebc890afdafdf053bed8 - Author: nobu - Date: 2019-03-19 11:25:15 +0900 - - Added Ripper#debug_output - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67304 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 92b0331bcf33d1c4d3396c1ad85919934198aa28 - Author: k0kubun - Date: 2019-03-19 02:45:10 +0900 - - Use designated initializers for compile_status - - to make it easier to understand what values are grouped. - Just cosmetic changes. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67302 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b1241d87756b59b6e2f033f7a978130b896bbaf - Author: k0kubun - Date: 2019-03-19 02:28:23 +0900 - - Use alloca for stack_size_for_pos as well - - to eliminate necessity of error check and `free` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67301 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a75ae6faa931e8b9d32c99039a06b950df391a06 - Author: k0kubun - Date: 2019-03-19 02:20:21 +0900 - - Use alloca again instead of malloc and free - - by changing interface of `mjit_copy_cache_from_main_thread`. - - This is also fixing deadlock introduced by r67299. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67300 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d426e28d2cbbc09208987c6cf86180ea3ba3522 - Author: k0kubun - Date: 2019-03-19 01:32:48 +0900 - - Resurrect r67287 and r67288 - - I noticed that r67287 was illegal because memory allocated by `alloca` - was used after the stack is expired. - - So I just replaced that with `malloc` and `free` for now. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 08e9c58d519599def6b786ea211ac3a3d8b64d52 - Author: svn - Date: 2019-03-19 01:14:59 +0900 - - * 2019-03-19 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 78e87b7d4f580b041f96e0503febce528b8607b8 - Author: k0kubun - Date: 2019-03-19 01:14:57 +0900 - - Revert "Eliminate mjit_copy_job_t reference from mjit_worker" - - This reverts commit ba51ae0109ee1d1fa7ca90b43da115ea68d7214a. - - CI is failing again... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67297 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ba51ae0109ee1d1fa7ca90b43da115ea68d7214a - Author: k0kubun - Date: 2019-03-18 23:01:52 +0900 - - Eliminate mjit_copy_job_t reference from mjit_worker - - Take 2 of r67287. - - For some reasons, passing pointer of pointer on stack to a function - and assigning an addresse to a pointer dereferenced from the pointer - seems not working on mswin. - - So I achieved to return multiple values by returning struct instead of - taking pointers. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67296 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 964bbc1686c7dd42d58da504a6968c90d5a428fd - Author: nobu - Date: 2019-03-18 21:48:18 +0900 - - parse.y: numbered parameter in lambda - - * parse.y (lambda): support numbered parameters, only when no - argument list including empty parentheses, like empty vertical - bars. [ruby-core:91859] [Bug #15672] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67295 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f9e5b8d09cafc2c91137d293b1458f1b0432a12a - Author: k0kubun - Date: 2019-03-18 21:07:21 +0900 - - Revert "Try disabling Travis cache on darwin" - - This reverts commit 6b136a044205f6e6b66df68cd2da2a9c3e952a7d. - - This does not seem to work: - https://travis-ci.org/ruby/ruby/jobs/507646193#L2478 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67294 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c1dce923739d0355520c02eb588bc96bedae4328 - Author: k0kubun - Date: 2019-03-18 20:46:21 +0900 - - Merge https://github.com/rubygems/rubygems/pull/2684 - - to make CI stable. See the PR for details. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67293 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 17018d4c31a86af2b47e09b3229dab2e80d3db6d - Author: nobu - Date: 2019-03-18 15:42:19 +0900 - - parse.y: continue after invalid name - - * parse.y (set_yylval_noname): continue after an invalid global, - instance, class variable name, without "unexpected end-of-file" - error. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67292 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 908b5301124cf673a2ee44de652968aa5360afd1 - Author: k0kubun - Date: 2019-03-18 10:52:45 +0900 - - Revert "Request inline cache values from mjit_compile" - - This reverts commit 4161674b2fbea6bdd01783ac5d3b39d88db22972. - - Revert "Eliminate mjit_copy_job_t reference from mjit_worker" - - This reverts commit d86a1aa045959dfbf5cd472eae0d043180259727. - - Reverting them because of CI failures - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67291 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ba03222da8ecc408310c37dca908f671ee3f1791 - Author: nobu - Date: 2019-03-18 10:42:20 +0900 - - Pack rb_iseq_constant_body from 296 to 288 bytes - - [Fix GH-2099] - - From: Lourens Naudé - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67290 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d0e25ed277549af21242009e649d93b73c82576c - Author: nobu - Date: 2019-03-18 10:18:25 +0900 - - parse.y: parser_numbered_param - - * parse.y (parser_numbered_param): hoisted out the contextual - check for numbered parameters. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67289 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4161674b2fbea6bdd01783ac5d3b39d88db22972 - Author: k0kubun - Date: 2019-03-18 03:29:30 +0900 - - Request inline cache values from mjit_compile - - rather than preparing beforehand. - - By having this change, implementing inlining by calling - `mjit_copy_cache_from_main_thread` for inlined methods was made - possible. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67288 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d86a1aa045959dfbf5cd472eae0d043180259727 - Author: k0kubun - Date: 2019-03-18 03:07:06 +0900 - - Eliminate mjit_copy_job_t reference from mjit_worker - - and make `copy_cache_from_main_thread` easier to use. - - For implementing inlining later, I'll use `copy_cache_from_main_thread` - inside `mjit_compile`. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67287 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3fc26f601397f9b3e2893488749481f4df96df07 - Author: k0kubun - Date: 2019-03-18 02:12:47 +0900 - - Drop rb_mjit_unit from mjit_copy_job - - and guard iseq from GC by marking iseq in mjit_copy_job. - - This is a refactoring for implementing inlining later and - should not be fixing or introducing any bugs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67286 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cebc640790c084c110ae413231b976941fbfdc7f - Author: kazu - Date: 2019-03-18 01:35:20 +0900 - - Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67285 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5bd10603416d3f267704b8ad1040ebab163ca3b2 - Author: svn - Date: 2019-03-18 01:32:51 +0900 - - * 2019-03-18 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67284 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dfb9907cd35ab914a421ccd864ca03594265f5a2 - Author: kazu - Date: 2019-03-18 01:32:49 +0900 - - Fix typos [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67283 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a72bc2e716790b933106e524f662f2b63cafc6e2 - Author: kazu - Date: 2019-03-17 22:51:30 +0900 - - Fix a typo [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67282 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6b136a044205f6e6b66df68cd2da2a9c3e952a7d - Author: k0kubun - Date: 2019-03-17 15:20:01 +0900 - - Try disabling Travis cache on darwin - - to check if it resolves "Permission denied" problem. - https://travis-ci.org/ruby/ruby/jobs/507381339 - https://travis-ci.org/ruby/ruby/jobs/507392198 - - TBH I'm not exactly sure why it happens, but I don't have infinite time - to understand this. It would be appreciated to identify the root cause - and remove `DISABLE_CACHE` again if you're sure your patch fixes the problem. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67281 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d4b6198d8f13229123ebbcfcdfc4685a913b1ac8 - Author: k0kubun - Date: 2019-03-17 14:32:53 +0900 - - Roughly increase Azure Pipelines fetch depth - - because --depth=1 may randomly break checkout: - https://dev.azure.com/rubylang/ruby/_build/results?buildId=208&view=logs&jobId=7ded14dc-7a77-59da-f40a-71e137ad96c0&taskId=2045950f-1dcd-54a4-4c23-fae2521239c1&lineStart=1554&lineEnd=1555&colStart=1&colEnd=1 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67280 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 46f5eb5b48213e1561cd23fea4f672f2e0d09647 - Author: k0kubun - Date: 2019-03-17 14:28:54 +0900 - - Update NEWS for --jit option changes [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67279 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 12acc751e3e7fd6f8aec33abf661724ad76c862a - Author: nobu - Date: 2019-03-17 14:21:18 +0900 - - Numbered parameters [Feature #4475] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67278 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0fa4a6a618295d42eb039c65f0609fdb71255355 - Author: k0kubun - Date: 2019-03-17 14:13:38 +0900 - - Change defaults of --jit options - - * --jit-min-calls: 5 -> 10000 - - --jit-min-calls=5 obviously can compile non hotspot. This was not a - problem for MJIT-benchmarks and Optcarrot because the former has very - few hot optimiziable methods and the latter is likely to trigger - compilation of hotspot by its intensive calls to optimizable hotspot - methods and has a very short window to allow limited compilations. - - In real-world applications, it has more time to compile more methods and - it pressures computer's limited resources like icache. We should avoid - compiling too many methods. Also compiling many methods exhausts time - budget for compilation in one ruby process lifetime and delays the "JIT - compaction" of Ruby 2.6. - - JVM is known to use 1,500 for C1 (client) compiler and 10,000 for C2 - (server) compiler for -XX:CompileThreshold by default. - https://docs.oracle.com/javase/8/embedded/develop-apps-platforms/codecache.htm - - When things are called X,000 times, requiring 10,000 can eliminate - compilation of methods which are called only once in these X,000 - iterations and obviously not hotspot. And in fact things like - unicorn-worker-killer restarts unicorn process every 4096 requests. - So I felt 10,000 is good for such an environment. - - * --jit-max-cache: 1000 -> 100 - - By the same reason stated above, we should not allow compiling many - methods especially on MJIT which has a larger overhead due to poor code - locality by dlopen and whose code is also likely to be bigger by just - inlining many VM instructions with -O3 rather than directly generating - low-level code. - - In JVM -XX:ReservedCodeCacheSize is 32M for reserved and 48M for maximum. - --jit-max-cache=1,000 could be closer to it, but in this case MJIT's - compilation is slow due to data synchronization between threads (to be - improved in Ruby 2.7 though) and we do not want to delay the "JIT - compaction" for a long time. - - So I chose a really conservative number for this, but by having method - inlining in the future, wider range could be optimized even with this - value. - - * Optcarrot - - --disable-gems, --benchmark Lan_Master.nes 12 attempts. - No significant impact. - - | r67276 | r67276 --jit | after --jit | - |:-------------------|:------------------|:------------------| - | 50.44369263063978 | 72.87390680773056 | 73.47873485047297 | - | 50.58788746124193 | 78.06820808947026 | 78.29723420171945 | - | 50.77509250801378 | 80.29010348842613 | 78.94689404460769 | - | 50.935361702064405 | 80.42796829926374 | 80.39539527351525 | - | 51.27352672981195 | 81.98758158033202 | 81.6754198664817 | - | 51.720715743242124 | 82.00118535811626 | 82.22960569251283 | - | 51.89643169822524 | 82.2290091613556 | 82.5013636146388 | - | 51.95895898113868 | 82.37318990939565 | 82.74002377794454 | - | 52.10124886807968 | 82.48796686037502 | 83.23354941183932 | - | 52.292280637519376 | 83.0265226541066 | 84.01552618012572 | - | 52.51856237784144 | 83.8797360318052 | 84.8588319093393 | - | 52.65076845986818 | 84.80037351256634 | 85.13577756273656 | - - * Railsbench - - `WARMUP=20000 BENCHMARK=1000 bin/bench` of https://github.com/k0kubun/railsbench. - It gets closer to --disable=jit. - - | | r67276 | r67276 | after | - | | | --jit | --jit | - |:----------|:-------|:-------|:-------| - | req/s | 891.3 | 742.2 | 841.5 | - |:----------|:-------|:-------|:-------| - | 50%ile ms | 1.00 | 1.21 | 1.08 | - | 66%ile ms | 1.02 | 1.24 | 1.09 | - | 75%ile ms | 1.03 | 1.28 | 1.10 | - | 80%ile ms | 1.03 | 1.30 | 1.11 | - | 90%ile ms | 1.09 | 1.42 | 1.15 | - | 95%ile ms | 1.32 | 1.65 | 1.27 | - | 98%ile ms | 4.79 | 2.23 | 1.81 | - | 99%ile ms | 5.68 | 7.52 | 6.64 | - |100%ile ms | 6.52 | 9.69 | 8.59 | - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67277 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 407cd5cc54e12eec6688d175957afee3b022f54a - Author: k0kubun - Date: 2019-03-17 13:13:13 +0900 - - Drop invalid trailing comma in JSON object - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67276 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7fe77cbca9073f521b35fd11bd55dde300559e8d - Author: k0kubun - Date: 2019-03-17 01:53:55 +0900 - - Ignore test-bundled-gems failure on CI for now - - ktsj-san recognizes this issue and it's intentionally left failing now. - As failure notification of this task is NOT indicating ruby is broken, - let's stop notifying the failure fo rnow. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67275 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5b0bcb0b2261a3254a008deecba9227f87e975b4 - Author: svn - Date: 2019-03-17 01:26:46 +0900 - - * 2019-03-17 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67274 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 46a3b440fdb59da2ef250c585c50a4e1499a1f69 - Author: k0kubun - Date: 2019-03-17 01:26:44 +0900 - - Do not build Azure Pipelines on Pull Request - - For 2 reasons: - - * bundled_gems tend to be left broken (like now) - * We don't want Slack notification for pull request and it can't be - disabled on Azure Pipelines - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67273 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8ce6748fc81bdee29b5e790d5e9f8317f77a77bf - Author: k0kubun - Date: 2019-03-16 13:11:54 +0900 - - Notify AppVeyor results to multiple channels - - and simplified config by using dedicated webhook URL. - Sadly AppVeyor YAML does not support alias and so we need to copy-paste - the request body. - - memo: - https://slack-files2.s3-us-west-2.amazonaws.com/bot_icons/2018-02-10/314363543719_48.png - is the URL used by `provider: Slack` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67272 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f044cc1042ef7a3547fdf5f1934a3d108854870f - Author: svn - Date: 2019-03-16 13:00:30 +0900 - - * 2019-03-16 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67271 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7006fdecf2ff5e832cd6da1bf02462146a9190b8 - Author: ktsj - Date: 2019-03-16 13:00:14 +0900 - - dsym should be treated as string [ruby-core:91852] [Bug #15670] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67270 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e4c184c6aeb29e3f47c6daf7c5ff26ef1ef440a8 - Author: k0kubun - Date: 2019-03-15 22:25:06 +0900 - - Increase the number of curl retries - - Because retrying 5 times failed. - https://ci.appveyor.com/project/ruby/ruby/builds/23063048/job/k9lykaagfaex74gg - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67269 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d4f7fac6b8ba975b50c4144168f656454c92724b - Author: svn - Date: 2019-03-15 14:19:58 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67267 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c36a6f97f243778d3eb8e973eba89ce2b424b707 - Author: mame - Date: 2019-03-15 14:19:54 +0900 - - node.h: introduce nd_brace to determine if a hash literal is a keyword - - NODE_HASH#nd_brace is a flag that is 1 for `foo({ k: 1 })` and 0 for - `foo(k: 1)`. - nd_alen had been abused for the flag (and the implementation is - completely the same), but an explicit name is better to read. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67266 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 560bb32fb2a04713bdbe5fa51ee2aaa271da91b6 - Author: nobu - Date: 2019-03-15 10:19:31 +0900 - - NEWS: adjust indents and escape brackets not to be labeled lists - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67265 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3134b20a0129aa072d1cb40a5000297333b5818d - Author: nobu - Date: 2019-03-15 09:44:51 +0900 - - Show the source line at an invalid class/instance variable - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67264 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bf4bcaf06115b32b5ffb4ddea972624d3ac7fa50 - Author: svn - Date: 2019-03-15 07:43:59 +0900 - - * 2019-03-15 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67262 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9e7f197c8e0c20bdf96ab7438e30b0457a85ec72 - Author: nagachika - Date: 2019-03-15 07:43:57 +0900 - - tool/make-snapshot: Use 6-spaces indent for SIZE and digests - to align with release note markdown. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d6e20297783257574d8143e95fb55aafd91db66 - Author: k0kubun - Date: 2019-03-14 22:47:10 +0900 - - Skip Bundler's test made fail by r67226 - - Possible fix would be https://github.com/bundler/bundler/pull/7038, - but Ruby script ending with `^~~` could be wrongly stripped by that? - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67257 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3db2041f8772ec7c9faf379095d4c8d06e5e25ed - Author: mame - Date: 2019-03-14 18:04:57 +0900 - - compile.c: fix the corner case of rest and keyword arguments - - See https://bugs.ruby-lang.org/issues/10856#note-20 . [Bug #10856] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67256 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 146bb252a0fe114befe8aa762596563c886db7fc - Author: mame - Date: 2019-03-14 17:43:51 +0900 - - compile.c (setup_args): process arguments forward - - For unknown reason, setup_args processed the arguments from the last to - the first. This is not only difficult to read, but also inefficient in - some cases. For example, the arguments of `foo(*a1, *a2, *a3)` was - compiled like `a1.dup << (a2.dup << a3)`. The second dup (`a2.dup`) is - not needed. - - This change refactors the function so that it processes the arguments - forward: `foo(*a1, *a2, *a3)` is compiled as `a1.dup << a2 << a3`, and - in my opinion, the source code is now much more readable. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67255 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9800fc26b0367c63ada516b932b13268bb79524b - Author: nobu - Date: 2019-03-14 17:13:46 +0900 - - parse.y: no punctuation instance/class variables - - * parse.y (parse_atmark): exclude punctuation follows @ marks, - whereas it is inclusive after $ mark as some punctuation global - variables exist. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 277af37b427c635688d9ca7cba0b2fa8d1fb459d - Author: svn - Date: 2019-03-14 15:43:54 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67253 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4c41dc8945d167bc63932325e11f227b4ec102dd - Author: mame - Date: 2019-03-14 15:43:50 +0900 - - compile.c: factor out "compile_args" from "compile_array" - - compile_array function had three usages: array literal, hash literal, - and method arguments. I think the third is completely different than the - first and second. For example, method arguments and popped are - meaningless; keywords_ptr and flag parameter for array/hash literal is - also unused. - - This change refactors them: a function "compile_args" is created for the - third, and removes no longer used parameters of "compile_array". - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67252 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9c077bbed94307d67c82a6e805dd6cc486433df2 - Author: nobu - Date: 2019-03-14 14:57:42 +0900 - - parse.y: show invalid global variable line - - * parse.y (parse_gvar): show the source line erred by invalid - global variable, and indicate the variable including the wrong - punctuation. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67251 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ccc933d4a6873d9be359c8ab04b1f242ed64c1e5 - Author: nobu - Date: 2019-03-14 14:32:30 +0900 - - Hoisted out ruby_show_error_line - - * parse.y (ruby_show_error_line): hoisted out from parser_yyerror. - - * parse.y (regx_options): revert r67226 and show the error line - separately. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67250 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 86c5806c6a3452a0b81595f8a306ec5c421a16a8 - Author: nobu - Date: 2019-03-14 11:18:05 +0900 - - More initializations of YYLTYPE - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67249 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e20aa14a82604db9a5e4d33d206aacfebfbb7d62 - Author: svn - Date: 2019-03-14 10:04:55 +0900 - - * 2019-03-14 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67248 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6a860ea0062e2f18435a870ae8734f25bc9d9827 - Author: mame - Date: 2019-03-14 10:04:53 +0900 - - Guard out the test when it is run under root permission - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67247 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0d6910dfc8e63d8961b338ea949bc398dd52b5d0 - Author: svn - Date: 2019-03-13 10:44:45 +0900 - - * 2019-03-13 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67244 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8415df619ecfe9d869067faf1282f3552d18e578 - Author: nobu - Date: 2019-03-13 10:44:34 +0900 - - Remove unnecessary local variable - - newline is always "\n" when it is used. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67243 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8952525a8e688e0fe67bbc7a3c84256190a44c23 - Author: nobu - Date: 2019-03-12 21:04:03 +0900 - - Assertion for r67226 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67227 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b6468b01f7288789ef2e9bf548d81cdadb8ef053 - Author: nobu - Date: 2019-03-12 13:23:17 +0900 - - Show unkwon regexp option line - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67226 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 60bddf589fb518c6b84515749775dc78458aeaad - Author: svn - Date: 2019-03-12 13:11:51 +0900 - - * 2019-03-12 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67225 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e5d10cda07b23682e5e4e64d1324e4d3247d4785 - Author: nobu - Date: 2019-03-12 13:11:41 +0900 - - Flush erred token - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67224 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a3a1199f413f7a96c4c90c7513c832838379e468 - Author: naruse - Date: 2019-03-11 22:00:31 +0900 - - fix wrong merge of conflict at r67217 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67221 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 43ff4ef912df53da6cadf009ff4e366a0d79626a - Author: svn - Date: 2019-03-11 21:48:34 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67218 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 76fc1ce0a774aab411b4e9f4462c236852624764 - Author: mame - Date: 2019-03-11 21:48:33 +0900 - - The combination of non-Symbol keys and Symbol keys is now allowed again - - Revert r64358. [Bug #15658] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67217 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bda6df356a373289e179f2b09c0bbe84ffc70d03 - Author: nobu - Date: 2019-03-11 21:47:02 +0900 - - parse.y: moved excessed_comma - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67216 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bc76d8a232bed2e245cd3997ebd9826938f7a738 - Author: hsbt - Date: 2019-03-11 20:37:17 +0900 - - Removed from standard library. No one maintains it from Ruby 2.0.0. - - [Bug #15652][ruby-core:91736] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67215 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 098ec6eb5076f3a140777c5cb56be4465bfa432f - Author: hsbt - Date: 2019-03-11 19:09:48 +0900 - - Added to check MJIT constant for the Ruby 2.3-2.5. - - This commit picked from https://github.com/ruby/webrick/commit/2c13beca2c25dc099b7ed20dbe4d7ede77dfef86 - - Co-authored-by: Colby Swandale - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 448262c81d7fdbca7db0b50059e53b423a2436ec - Author: knu - Date: 2019-03-11 18:52:40 +0900 - - Mention the addition of Enumerator::Yielder#to_proc in NEWS - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7d3d8e79fe9cc9f21cd4341f0a6fb2e6306688fd - Author: hsbt - Date: 2019-03-11 18:52:31 +0900 - - fall back to copy + unlink on EPERM - - [Feature #15415][ruby-core:90536] - - Co-authored-by: Eric Wong - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67212 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c2d3b8dfb43e6dbc0b9af3c0f880636ffcc06ca9 - Author: knu - Date: 2019-03-11 18:49:14 +0900 - - Implement Enumerator::Yielder#to_proc - - A Yielder object can now be directly passed to another method as a - block argument. - - ```ruby - enum = Enumerator.new { |y| - Dir.glob("*.rb") { |file| - File.open(file) { |f| f.each_line(&y) } - } - } - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67211 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7d9664953ba574b04f6558e80e95a71289275d64 - Author: nobu - Date: 2019-03-11 12:53:33 +0900 - - Removed circular require - - Import rubygems/rubygems#2679 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67206 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit aef24ecbe959b5e91e2e06b3a2cbfaa02cae1672 - Author: nobu - Date: 2019-03-11 12:53:31 +0900 - - Renamed duplicate test - - Import rubygems/rubygems#2678 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67205 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 53f2cda8d4717f15680e0a5b3638443182ca6c1f - Author: svn - Date: 2019-03-11 10:37:21 +0900 - - * 2019-03-11 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67204 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e5f01dab9d1faebe8f1c8eab3ed805335c4b712d - Author: nobu - Date: 2019-03-11 10:37:16 +0900 - - numeric.c: fix infinite loop - - * numeric.c (int_pow): fix infinite loop in the case of y equal 1 - and power of x does not overflow. - [ruby-core:91734] [Bug #15651] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67203 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f399c2912bcb0ab782fc14a1987e07ceaaf060e7 - Author: svn - Date: 2019-03-10 15:46:36 +0900 - - * 2019-03-10 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67202 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ffec546b0e522a647c7c2473c40dbe018156736d - Author: nobu - Date: 2019-03-10 15:46:28 +0900 - - eval.c: clear internal errinfo - - * eval.c (ruby_cleanup): clear internal error info when invoking - end procs. [ruby-core:91731] [Bug #15650] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67201 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 72df0a8e4703c4e14cb2014d59d8ddad09a47859 - Author: nobu - Date: 2019-03-09 19:17:33 +0900 - - Add ignored_sp event - - * ext/ripper/lib/ripper/lexer.rb (Ripper::Lexer): add ignored_sp - event which will be fired from Ripper::Lexer#on_heredoc_dedent - method. [ruby-core:91727] [Bug #15648] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67200 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8776a09d4eed5662ee28eff0d829e880cc001684 - Author: nobu - Date: 2019-03-09 19:14:16 +0900 - - Use assert_respond_to - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67199 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 28f619e301cf5f266f38fe764c4018b7fabc77cb - Author: svn - Date: 2019-03-09 09:12:53 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67198 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5aecf03ec30a098ba58627aadcfbff4acdd11fdd - Author: nobu - Date: 2019-03-09 09:12:52 +0900 - - variable.c: hoisted out rb_namespace_p - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67197 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5cfa518406d9b411512cffbe6951537bd25a3ebb - Author: svn - Date: 2019-03-09 09:00:35 +0900 - - * 2019-03-09 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67196 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d5770197462ee4445c4bd4898339ce50052af7d7 - Author: nobu - Date: 2019-03-09 09:00:26 +0900 - - Early return in gc_mark_children - - for types Float, Bignum and Symbol as they do not have references - and singleton classes. - - [Fix GH-2091] - - From: Lourens Naudé - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit caa2a5bb0eb919d022bd50a7553197192dd78014 - Author: svn - Date: 2019-03-08 09:35:56 +0900 - - * 2019-03-08 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67194 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e185c9716e6cabc2a9d103c8c7a77ee73fbba546 - Author: tadd - Date: 2019-03-08 09:35:53 +0900 - - use __GNUC__ instead of __GCC__. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67193 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4c1952f4bf9d2fe183431747a83596287e9b7631 - Author: hsbt - Date: 2019-03-07 20:24:48 +0900 - - Ignore to handle the different platform - - When `GEM_HOME` was shared with CRuby and JRuby. RubyGems try to - handle both platforms. It should be ignored the different platform. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67190 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8cc53044081fa00384412a0f141c9f1be9065e1a - Author: svn - Date: 2019-03-07 14:11:55 +0900 - - * 2019-03-07 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67189 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 23488589b38f09a95e7ba61a72b12358ad6185cb - Author: nobu - Date: 2019-03-07 14:11:46 +0900 - - io.c: chomp CR at the end of read buffer - - * io.c (rb_io_getline_fast): chomp CR followed by LF but separated - by the read buffer boundary. [ruby-core:91707] [Bug #15642] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67188 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1598b5e7b343b6c05e6cab47ac3878276aea6d37 - Author: nobu - Date: 2019-03-06 20:49:53 +0900 - - Symbol creation is not a problem now unless pinned down - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67187 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7fed9a2df50404c734504e0405ecaa98f0d9147c - Author: nobu - Date: 2019-03-06 20:16:34 +0900 - - proc.c: call respond_to_missing? with a symbol - - [ruby-core:91683] [Bug #15640] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67185 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a679e98e64a7c69d65578b11ef072e1115d536ad - Author: naruse - Date: 2019-03-06 18:48:39 +0900 - - Fix PTY.open on OpenBSD [Bug #15607] - - From: Jeremy Evans - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67183 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f831ca67642101e29bd2de91998d80560d2b7fb6 - Author: duerst - Date: 2019-03-06 12:19:10 +0900 - - delete directory and files related to Unicode version 11.0.0 - - this completes and closes feature #15321 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67174 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b3f641085e347d55c1b9b72e25a19c28cdeb84f6 - Author: duerst - Date: 2019-03-06 12:15:06 +0900 - - add news about Unicode version update (issue #15321) to NEWS [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67173 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fdc42bf88d7900b722e46976b981ce0fa3d4f1e8 - Author: kazu - Date: 2019-03-06 12:04:36 +0900 - - Remove deprecated `sudo: false` in .travis.yml - - - https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration - - https://docs.travis-ci.com/user/reference/overview/#deprecated-virtualization-environments - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67172 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d4303528d39d38ae2141f13064e82a7908df4f14 - Author: hsbt - Date: 2019-03-06 11:08:20 +0900 - - Skip malicious extension test with mswin platform. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67171 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ad398b7e0c857cbaaf469f44759e163159b60148 - Author: svn - Date: 2019-03-06 10:55:26 +0900 - - * 2019-03-06 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67170 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cff7eefa07f8e7bccb5c0b8c856e5657d6d45ffa - Author: duerst - Date: 2019-03-06 10:55:19 +0900 - - update Unicode version (and Emoji version) to 12.0.0 - - - common.mk: set UNICODE_VERSION and UNICODE_EMOJI_VERSION to 12.0.0 - - - lib/unicode_normalize/tables.rb: update table data to Unicode version 12.0.0 - - - enc/unicode/12.0.0/casefold.h, enc/unicode/12.0.0/name2ctype.h: add generated - files for Unicode version 12.0.0 - - This is the main commit for #15321. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67169 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 08f8cfe14e0f8937e3bcf8a22becdc5ce60b920e - Author: hsbt - Date: 2019-03-05 12:32:58 +0900 - - Merge RubyGems upstream: 56c0bbb69e4506bda7ef7f447dfec5db820df20b - - It fixed the multiple vulnerabilities. - https://blog.rubygems.org/2019/03/05/security-advisories-2019-03.html - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67168 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 593505ac6f802d2b5bff469425b7c76b65cc9b10 - Author: nobu - Date: 2019-03-05 09:32:15 +0900 - - string.c: respect the actual encoding - - * string.c (rb_enc_str_coderange): respect the actual encoding of - if a BOM presents, and scan for the actual code range. - [ruby-core:91662] [Bug #15635] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67167 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4045cb82227e7b97342eb92b17e35f534128e90d - Author: svn - Date: 2019-03-05 09:28:25 +0900 - - * 2019-03-05 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67166 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19d3aaff5c45c8ee0a9083a182d77cd5f5acf935 - Author: nobu - Date: 2019-03-05 09:28:22 +0900 - - Directories in RbConfig may not exist until installation - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67165 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ba982a3da32ecb3ae0f08eceda55c503f39d3875 - Author: svn - Date: 2019-03-04 17:13:27 +0900 - - * 2019-03-04 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67164 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 958798851d24a70e849e19592a36edce2daf18d1 - Author: nobu - Date: 2019-03-04 17:13:25 +0900 - - FindFirstFile cannot glob share names - - * win32/file.c (replace_to_long_name): do not try to glob host - names and share names by FindFirstFile which is useless for that - purpose. [ruby-core:91656] [Bug #15633] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67163 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e4885d8accb0a30069374ee21f688631fca45f62 - Author: k0kubun - Date: 2019-03-03 22:35:25 +0900 - - Use --depth=1 for vs2019 as well - - to shorten time to clone - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67162 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2e9d4b9f0bd0cae89e75a7a16b2cf0c55aeb9c0e - Author: ko1 - Date: 2019-03-03 15:18:43 +0900 - - do not close FSs explicitly. - - * test/ruby/test_dir.rb: r67159 closes all files explicitly - but this change breaks attempt of this test introduced at - r56467. Try another solution which removes all references - from an Array with `#clear`. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67161 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7ebea69529a15e6e3004aeafb40f7d469f47b37d - Author: svn - Date: 2019-03-03 09:17:21 +0900 - - * 2019-03-03 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67160 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19a8bbafd8ef8b48a9d2832e605fb00b3284630e - Author: ko1 - Date: 2019-03-03 09:17:18 +0900 - - close opened files explicitly - to fix a test failure like - http://ci.rvm.jp/results/trunk-theap-asserts@silicon-docker/1804207 - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67159 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4eda7e1d1481168c016a589b53af2233ea2defb2 - Author: k0kubun - Date: 2019-03-01 23:09:41 +0900 - - Stop sharding --jit-wait testing - - by just randomizing test order. - - The original motivation to shard --jit-wait tests was forcing to test - major parts of code without actually stopping to test MJIT after - TracePoint enablement. But it tends to increase the test time because we - often compile the same thing in different shards. - - I made this decision because we seem to hit 1.5h timeout of Wercker - these days, and Wercker is really bad at handling timeout (it does not - report timeout as failure, but just keeps it "pending" state) - https://app.wercker.com/ruby/ruby/runs/mjit-test2/5c78f15cc9e725000805b86c?step=5c79031d6c1e2c0008ac41c3 - - By randomizing this, we could test things randomly. The downside of this - approach is that we may not be able to find a specific commit that - caused a future failure by having TracePoint in a very early phase. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4fd5a9e9bb58ab666809eda3256db2ae98b0032f - Author: hsbt - Date: 2019-03-01 22:16:29 +0900 - - Try to build readline extension with vcpkg on Azure Pipelines. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67157 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fe28e007f3226c48aee497558f8eff535485423d - Author: hsbt - Date: 2019-03-01 17:46:07 +0900 - - Try to build vs2019preview on Azure Pipelines. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19cf8e03878e93a9594c275b8f82a9d53e02eda1 - Author: hsbt - Date: 2019-03-01 17:31:43 +0900 - - Fixed build failure of Travis CI. We need to support `make srcs`. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67155 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a4020fbefcf61edfe604c25a0bc70a7aed380070 - Author: kazu - Date: 2019-03-01 13:21:33 +0900 - - Add Azure Pipelines build status badge [ci skip] - - copy from README.md. see r67146 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67152 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fb04855c415c2ea33f863841a4f4bdbe059131a5 - Author: k0kubun - Date: 2019-03-01 12:56:33 +0900 - - Drop obsoleted continueOnError - - now it's passing thanks to r67149 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9dbb14b77cb929d0f59b22152ea817e70ee8fa13 - Author: svn - Date: 2019-03-01 12:45:03 +0900 - - * 2019-03-01 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67150 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fe61f14d53c5b18d3c475eee23502ab1e5446291 - Author: hsbt - Date: 2019-03-01 12:45:00 +0900 - - Support YACC environment variable for ripper. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67149 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dfec1eb3cee833fa4bef6ce027a3e702508261ba - Author: k0kubun - Date: 2019-02-28 23:19:47 +0900 - - Add Azure Pipelines build status badge [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67146 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7b81d7f5c2a5fe93835c2b2d865a7378f5499f0f - Author: k0kubun - Date: 2019-02-28 22:26:14 +0900 - - Mark vs2017 build as continueOnError for now - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 12eca471a466daa4b03cb2c3edfb1a7039071eb6 - Author: k0kubun - Date: 2019-02-28 21:47:36 +0900 - - Revert "Try clean: true for vs2017 checkout failure" - - This reverts commit b0e350fe16ad17eabf5bbc603f7d817c06ce8554. - - The issue seems to be invalid tag name including `"` in ancient tag. - We're trying to delete that. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67144 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b0e350fe16ad17eabf5bbc603f7d817c06ce8554 - Author: k0kubun - Date: 2019-02-28 21:32:24 +0900 - - Try clean: true for vs2017 checkout failure - - https://dev.azure.com/rubylang/ruby/_build/results?buildId=107 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67143 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f03775fc0f536b43ace587f6ae9c299a0b8598ef - Author: k0kubun - Date: 2019-02-28 21:19:08 +0900 - - Try fetchDepth: 1 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67142 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ccd1c02ceaa04b29757954906859fe3b9e3dedf0 - Author: svn - Date: 2019-02-28 21:01:09 +0900 - - * 2019-02-28 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ef8ed5deee7a687190a33ac655dec271bb18db26 - Author: hsbt - Date: 2019-02-28 21:01:06 +0900 - - Removed fake environment variable because It is not necessary for macOS. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67140 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6f2c516d8031e1c7f4704bd59c5349fab7f24187 - Author: svn - Date: 2019-02-27 21:40:19 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67139 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 19408c785c6f258024efcaa69d0642ad995c50b3 - Author: hsbt - Date: 2019-02-27 21:40:19 +0900 - - skip to not support color tty environment. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67138 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 019864b4a5d14f25f5880cda996306908837d7ee - Author: hsbt - Date: 2019-02-27 21:30:24 +0900 - - Test Bundler examples and bundled gems tests with Azure Pipeline. - - * They are invoked on Linux and macOS environment. - * Try to build with vs2017. But it's only binary build. - - https://dev.azure.com/rubylang/ruby/ - - [Feature #15181][ruby-core:89222] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67137 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c2ee33898b21af45e9dad89942772c00d3ffc819 - Author: svn - Date: 2019-02-27 12:26:09 +0900 - - * 2019-02-27 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67136 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8092d571be8f65909c6e5a931429933d19566f36 - Author: svn - Date: 2019-02-27 12:26:09 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67135 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e2a8cb7b9de3d5a22e29886a5a1b7cafacdc31a - Author: nobu - Date: 2019-02-27 12:26:05 +0900 - - Remove stale arguments - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67134 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ff074304f4d393fa4a9c97f30829ccf5497009ae - Author: svn - Date: 2019-02-26 10:34:20 +0900 - - * 2019-02-26 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67133 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e2d1bb1fa4850c8212a7cdbd76a92634a1115453 - Author: duerst - Date: 2019-02-26 10:34:17 +0900 - - add exceptions for indenting conventions for files related to regular expressions - - Ruby uses the Oniguruma/Onigmo regular expression engine, including the underlying - character encoding framework. In contrast to other code implementing Ruby, the - regular expression engine related code is formatted with two spaces per indent - level. This commit adds rules for these files. (The commit may not completely cover - all related files.) [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67132 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 23a8183bea8dda2d7528b57f2e0c8bc31162db3e - Author: nobu - Date: 2019-02-24 20:57:18 +0900 - - Check stx_btime in struct statx - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67131 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a582007e3611e1d6e1d57b697391be74dc03c2ac - Author: svn - Date: 2019-02-24 14:27:40 +0900 - - * 2019-02-24 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67130 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b8285e25348ab6a7b16facb31e5753711b1191e - Author: glass - Date: 2019-02-24 14:27:33 +0900 - - configure.ac: remove check for broken memmem - - the bug of memmem(3) was fixed in glibc 2.1 released in 1999. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67129 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dc700cf903e7fa1852bd9390e5e350d07edf1000 - Author: glass - Date: 2019-02-23 13:42:48 +0900 - - configure.ac: skip check of statx() on AIX - - Linux and AIX have statx() with different prototype. - - Linux: int statx(int, const char*, int, unsigned int, struct statx*) - AIX: int statx(char, struct stat*, int, int) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67128 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6604e1b7cd75bef7ed72db699d8f88a7fb56c330 - Author: hsbt - Date: 2019-02-23 12:43:58 +0900 - - Merge json-2.2.0 from flori/json. - - https://github.com/flori/json/releases/tag/v2.2.0 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67127 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f22ffd83e92a214a697e93fe715d29cbfa52084d - Author: k0kubun - Date: 2019-02-23 11:22:05 +0900 - - spec/../rbconfig_spec.rb: skip spec not working on MinGW - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0dab1fce7c1eec3b67340e32678841151119beb1 - Author: svn - Date: 2019-02-23 11:17:57 +0900 - - * 2019-02-23 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67125 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 052dbbe74f00733b96841fc8fbe7bdefadf0440e - Author: k0kubun - Date: 2019-02-23 11:17:54 +0900 - - spec/../shared/write.rb: suppress random failure - - due to MJIT worker's known race condition. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67124 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f53548a86cec0ebe147c6ee4484fd8ccf0f42c79 - Author: svn - Date: 2019-02-22 16:25:54 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b1c1ee7183f6c9b6f585d35a5a8786594e1e7733 - Author: ko1 - Date: 2019-02-22 16:25:51 +0900 - - change `cfunc->invoker` type for opt. - - * vm_insnhelper.c: change `call_cfunc_*` parameters order - and specify a function type for the passed func ptr. - This fix reduce the number of asm instructions, such as: - # before this patch - 0000000000000110 : - 110: 48 89 fa mov %rdi,%rdx - 113: 31 c0 xor %eax,%eax - 115: 48 89 f7 mov %rsi,%rdi - 118: ff e2 jmpq *%rdx - 11a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) - - # after this patch - 0000000000000110 : - 110: ff e1 jmpq *%rcx - - However, this kind of instruction reduction doesn't affect - any performance because of great CPU architectures :p - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67122 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4af7f77d0ffe4371610143731e08f6e74314b4a1 - Author: nobu - Date: 2019-02-22 15:43:11 +0900 - - STATX_BTIME depends on filesystems - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67121 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit def040f6c330694e4f620a44b7790444d0f59157 - Author: nobu - Date: 2019-02-22 15:35:44 +0900 - - Skip EPERM, when statx(2) is wholely blocked - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67120 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1ae52fcddff2440ee96013c020c41844332fee38 - Author: nobu - Date: 2019-02-22 15:22:24 +0900 - - Skip EPERM, like as r67102 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67119 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit aa5dd6fe7ef58b4d10eb3192c342043fbe8be8cd - Author: nobu - Date: 2019-02-22 15:14:22 +0900 - - STATX_BTIME depends on filesystems - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67118 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b9357e4d1b6f318d2ffa7323f14f01272ad336ee - Author: nobu - Date: 2019-02-22 15:07:30 +0900 - - File#birthtime depends on the kernel version on Linux - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67117 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fc90c4ec5da9e60c18785b3b4c393b5294009c1e - Author: nobu - Date: 2019-02-22 15:01:08 +0900 - - Support File#birthtime on Linux - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67116 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 607ecea7c9ca30ef4dbdadc72c9d32131946a069 - Author: nobu - Date: 2019-02-22 12:08:38 +0900 - - Unified rb_file_s_birthtime - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67115 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 67032770242c09f9280cd765ff93735b451856bb - Author: svn - Date: 2019-02-22 05:59:12 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67114 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4e15be8bade0a6a75c209eff3b96b4c4f03019a9 - Author: ko1 - Date: 2019-02-22 05:59:08 +0900 - - refactoring compile.c. - - * compile.c: refacetoring: - * initialize `branches` with Qfalse instead of 0. - * make compile_call* functions from `iseq_compile_each0()` - to make modifying them easy. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67113 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da7976235fbc2986925969646071bebe3702e49f - Author: eregon - Date: 2019-02-22 00:38:59 +0900 - - Update to ruby/spec@7a16e01 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67112 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b8e389a0f3226c90e96e02e6396686a3bef6a456 - Author: svn - Date: 2019-02-22 00:38:38 +0900 - - * 2019-02-22 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67111 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 203d946781ce29069f56f259d455ffb3039315f5 - Author: svn - Date: 2019-02-22 00:38:37 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67110 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 92d3a7262468717757a3cf4ce24a5a6dd98f516a - Author: eregon - Date: 2019-02-22 00:38:36 +0900 - - Update to ruby/mspec@2ee5661 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67109 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b94ce988b1a000325d47daa02e16dd487c4f27d - Author: nobu - Date: 2019-02-21 16:32:24 +0900 - - Constified - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67108 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 936b61d4acffc632608d1c1990b02e6a791107d0 - Author: nobu - Date: 2019-02-21 16:03:12 +0900 - - Path for AT_EMPTY_PATH must not be NULL - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 32f3961fd687d1096f444d09c78d7dcd247649d1 - Author: svn - Date: 2019-02-21 15:12:17 +0900 - - * 2019-02-21 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7c369b78471e7c847cb4ffdbe95600bca55cabb5 - Author: nobu - Date: 2019-02-21 15:12:13 +0900 - - Separate fstatx_without_gvl from statx_without_gvl - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67105 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7c2bbd1c7d40a30583844d649045824161772e36 - Author: hsbt - Date: 2019-02-20 19:43:23 +0900 - - Adjust the rubycop rules of Bundler upstream repository. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67104 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5f08c9e2e073db205ec2bf2f5843117cb92ada68 - Author: nobu - Date: 2019-02-20 18:55:25 +0900 - - Do not test File class method - - It fails by EPERM for unknown reason. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67103 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cc6806c76c217354c6d1ad70585b033a00faa7a9 - Author: nobu - Date: 2019-02-20 17:31:17 +0900 - - Skip EPERM - - Docker's default seccomp whitelist does not include statx syscall - by the default. Skip this error for now. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67102 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c3e0244efe21a99cf81fb26a18b797e0e84b54a5 - Author: nobu - Date: 2019-02-20 17:09:32 +0900 - - Revise the example on OpenBSD - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67101 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8ed170961601a1becec56ffc0f0e7da1f9e56892 - Author: ko1 - Date: 2019-02-20 16:46:15 +0900 - - fix rubyspec test to pass tests. please revisit it @nobu? - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e487e86e982a56ded6e5070aeef0d77655043216 - Author: ko1 - Date: 2019-02-20 16:34:05 +0900 - - fix r67097 with cast - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67099 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f2d3b3623feb66b6ba59ecd866c40b531a3c5251 - Author: kazu - Date: 2019-02-20 16:19:39 +0900 - - Fix document and return value of `IO#autoclose=` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67098 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 15a98ab42838be248a5b59ca342033ee338357ad - Author: nobu - Date: 2019-02-20 15:54:23 +0900 - - Try statx syscall - - * file.c (rb_file_s_birthtime): export for pathname to check if - birthtime is supported. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d034fcb13f04b096f99d1824d5e7dd8ed256713e - Author: svn - Date: 2019-02-20 13:39:57 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b7f899681371358e84dbf230796a0a661217c2cd - Author: marcandre - Date: 2019-02-20 13:39:56 +0900 - - * spec/ruby: Tweak Enuemrator::Chain#rewind spec so that arity of block matches what is yielded - - Calling `and_yield(*args)` adds an implicit expectation that all the `args` are passed to a block that can accept them, even though blocks that are not lambda-like don't mind extra arguments. - It so happens that this spec passed on Ruby 2.6.1 See [Bug #15613] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67095 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e80e9144f88bac3e2d8890c9e2fc22f5e391aff - Author: ko1 - Date: 2019-02-20 13:27:24 +0900 - - revert r67093 because it breaks tests - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67094 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 10deba066e207eb142e7b61b1479c8af4016b247 - Author: nobu - Date: 2019-02-20 13:02:30 +0900 - - Try statx syscall - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67093 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5210b89fd730815ba2510b09a890910a7995a4a1 - Author: svn - Date: 2019-02-20 00:39:37 +0900 - - * 2019-02-20 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67092 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 193a06caf5b1fdbe9b4c6110314df03cab7145f5 - Author: k0kubun - Date: 2019-02-20 00:39:35 +0900 - - insns.def: opt_regexpmatch2 is not a leaf insn - - related: r66982 - Sadly opt_regexpmatch2 was not a leaf insn either. - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/1751213 - - CHECK_INTERRUPT_IN_MATCH_AT is just like RUBY_VM_CHECK_INTS, and it may - call arbitrary Ruby method, for example a GC finalizer from postponed - job in this case. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67091 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fe0f98e74746654c6b8bdd5203733ad01c732bde - Author: svn - Date: 2019-02-19 14:45:00 +0900 - - * 2019-02-19 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67090 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d3ff564779356be08274f851bf40f6a9b897fb6d - Author: svn - Date: 2019-02-19 14:45:00 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67089 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 88798f0787d9d4a331994332837e44f9fcc7bc5c - Author: glass - Date: 2019-02-19 14:44:53 +0900 - - file.c: enable File.birthtime on Linux - - enable File.birthtime on Linux if statx(2) is available. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67088 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5f090b8d8238b2adc0bf05d003d4384769b63e12 - Author: svn - Date: 2019-02-18 22:33:26 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67087 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d04963501bc057685220fa1160fb9a102dd46d57 - Author: hsbt - Date: 2019-02-18 22:33:25 +0900 - - Use ENV["BUNDLE_GEM"] instead of gem command provided by system ruby. - - It break the examples of bundler. Because some examples detect the - different version of system ruby than test target version like trunk. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67086 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bef0c0a3678d07ce40f147051fba092ee30da640 - Author: hsbt - Date: 2019-02-18 18:53:13 +0900 - - Fixup r66984. It breaks bundler's examples. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67085 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5c11d854110cd130a7b64e01b1e67bcf479ad886 - Author: svn - Date: 2019-02-18 18:46:28 +0900 - - * 2019-02-18 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67084 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3661d0521fa2cf4cdf9efa51c69cad4ea93fa2b3 - Author: hsbt - Date: 2019-02-18 18:46:25 +0900 - - The ruby core applied the difference structure from bundler upstream repository. We need to modify a configuration for test-bundler. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67083 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 124957566f041e5c6e8f678dfaf62cae381826dc - Author: ktsj - Date: 2019-02-17 15:59:11 +0900 - - .gdbinit (rp): follow up changes in r66390 - - RHASH_ARRAY_{LEN,BOUND}_{MASK,SHIFT} have been renamed to - RHASH_AR_TABLE_{SIZE,BOUND}_{MASK,SHIFT}. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67082 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1ce2ba32fb94aae94b7519a64e6330a6ff88c888 - Author: svn - Date: 2019-02-17 00:51:07 +0900 - - * 2019-02-17 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67081 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e5347b1c905acc58d98f9497d8edcb0f78729db6 - Author: naruse - Date: 2019-02-17 00:51:01 +0900 - - Revert "Assert that union sizes match" - - This reverts commit r67078. - It breaks armv7l-linux-eabihf and sparc-solaris2.11. - http://rubyci.s3.amazonaws.com/scw-9d6766/ruby-trunk/log/20190215T061708Z.diff.html.gz - http://rubyci.s3.amazonaws.com/unstable11s/ruby-trunk/log/20190215T072546Z.diff.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67080 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f450652becfaa6561399455a28211081704b0228 - Author: k0kubun - Date: 2019-02-15 21:38:03 +0900 - - Bump the benchmark-driver git ref to v0.14.13 (macOS memory runner support) - - [Fix GH-2082] - - From: Lourens Naudé - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67079 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 387e8967a37b269de221614d8f83060d5d713bcb - Author: nobu - Date: 2019-02-15 14:51:39 +0900 - - Assert that union sizes match - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67078 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b1daba8227ef420247e0133ecf9bb5b647b891e0 - Author: svn - Date: 2019-02-15 00:29:08 +0900 - - * 2019-02-15 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67077 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7570864267cb258e2d29881e37cb3b8a6930727a - Author: mrkn - Date: 2019-02-15 00:29:04 +0900 - - Introduce RVALUE_EMBED_LEN_MAX to remove a magic number - - * include/ruby/ruby.h: replace a magic number with RVALUE_EMBED_LEN_MAX, - which indicates the number of VALUE elements can be embedded in a RVALUE. - - * internal.h: ditto. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67076 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cb57336e86dbe9c21fd8bc447912256843fe6b26 - Author: nobu - Date: 2019-02-14 23:21:14 +0900 - - GNU make does not need srcs_vpath - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67075 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4ae3df42f723d25b0fe4ba6b2689d607b01c6f48 - Author: hsbt - Date: 2019-02-14 21:59:03 +0900 - - Merge RubyGems master@9be7858f7f17eae3058204f3c03e4b798ba18b9c - - This version contains the some style changes by RuboCop. - - * https://github.com/rubygems/rubygems/commit/9d810be0ede925fb2e3af535848582c3f8e0e72f - * https://github.com/rubygems/rubygems/commit/61ea98a727fb1b76b6fac52d74107ee4b02aaef2 - * https://github.com/rubygems/rubygems/commit/795893dce3c5f8540804fc08144cc6a90f086b13 - * https://github.com/rubygems/rubygems/commit/9be7858f7f17eae3058204f3c03e4b798ba18b9c - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67074 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d1e6304a891fc5e9cc63e50520bdc798fb95b829 - Author: nobu - Date: 2019-02-14 14:42:14 +0900 - - Prefer relative directory from srcdir to top_srcdir - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4fc656a2f331a91a71208d5a426fce951fa5ca82 - Author: nobu - Date: 2019-02-14 14:40:08 +0900 - - Removed duplicate dependents - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67072 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7b8986f2e441f5f71ec9c375baf71ee06fa53130 - Author: nobu - Date: 2019-02-14 00:48:36 +0900 - - Cleaning gems should not clean ext - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67071 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bd8cb9f5d268881a49819a1996d3dffdb951168e - Author: nobu - Date: 2019-02-14 00:34:08 +0900 - - Parenthesize `for` to ignore errors - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67070 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4844a449405060892db4c407b12f141364d3142d - Author: nobu - Date: 2019-02-14 00:20:50 +0900 - - Suppress a warning - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67069 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 63ca54e7aa1be7e8cb2eb11881dbc5bb9cfccb37 - Author: svn - Date: 2019-02-14 00:19:28 +0900 - - * 2019-02-14 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 43ee21f26dcf911450d5da9b3503eae0d7a87b76 - Author: nobu - Date: 2019-02-14 00:19:26 +0900 - - Ignore errors on cleaning - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67067 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f678332d8298e2c19d7c7daf19eeaf023f9a574f - Author: nobu - Date: 2019-02-13 21:02:08 +0900 - - Consider END block - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67066 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 87b1d186f9456e0c8c716eb12c67bc3c6d54ac41 - Author: nobu - Date: 2019-02-13 20:51:03 +0900 - - Fix rb_bug message pattern list - - "Other runtime information" section depends on platforms. - Make no expectation. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67065 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 00679d202d17bc629e02632801eac7c1bc7490c8 - Author: nobu - Date: 2019-02-13 20:36:15 +0900 - - Fix rb_bug message pattern list - - Each setions are separated by an empty line, and C level backtrace - information format has been changed. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67064 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c6a2de302900784dd74106091c723862119bdeca - Author: ko1 - Date: 2019-02-13 18:40:45 +0900 - - check return value of `write` to suppress warning. - - * ext/-test-/gvl/call_without_gvl/call_without_gvl.c (do_loop): - `-Wunused-result` compiler option (gcc?) checks checking - return value of `write`. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fb159b492f4c027d5068e17f0cd3360f31507878 - Author: naruse - Date: 2019-02-13 13:49:36 +0900 - - fix test for r67061 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67062 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a8c0f27276c16d4774f611ce2b1c793b92dcdc89 - Author: naruse - Date: 2019-02-13 13:32:03 +0900 - - Remove message to recommend to repot bug - - This message is showed on SEGV, but it is usually caused by 3rd party - libraries and we don't help reporters well. I concluded this message - doesn't help users as expected. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67061 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e20e67980e80bc83ca259bdf28e7247576fe742d - Author: svn - Date: 2019-02-13 13:25:00 +0900 - - * 2019-02-13 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67060 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 698c55d32a0aa61a7db127f7f88e87b7717b41f2 - Author: svn - Date: 2019-02-13 13:25:00 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67059 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 74b19e330adbdae2d8e53b58f1a2a7b725e69c8d - Author: ko1 - Date: 2019-02-13 13:24:59 +0900 - - fix imemo entry description. - - * ext/objspace/objspace.c (count_imemo_objects): `imemo_type_ids` - should be match with `enum imemo_type` in internal.h and this - patch fix mismatch. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67058 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b2f424150909a4441e906161d729d871b899101e - Author: nobu - Date: 2019-02-12 21:31:55 +0900 - - Update dependencies, internal.h includes ruby.h - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67057 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da1f593acabd1d95b4567170ed886c1cd5f33b9a - Author: nobu - Date: 2019-02-12 21:31:01 +0900 - - Skip erb files, idirect prerequisites - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67056 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 29c9f4a590e8ad415fb88e4309ec5df8bcc868e3 - Author: nobu - Date: 2019-02-12 21:15:30 +0900 - - Replace versioned Unicode header paths with UNICODE_HDR_DIR - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67055 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91cb5c1a70b2f659b6ee1dad4ca7c658fe1e00f9 - Author: ko1 - Date: 2019-02-12 12:45:15 +0900 - - fix empty Hash memsize. - - * gc.c (obj_memsize_of): ar_table ptr can be NULL (size == 0). - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67054 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9653f770ae359800dcd53b037fad5c07988717c2 - Author: svn - Date: 2019-02-12 06:57:13 +0900 - - * 2019-02-12 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2f1bf4fae3206c9fb02b9966d546d4c96b3343cd - Author: eregon - Date: 2019-02-12 06:57:10 +0900 - - Accept a third value for NaNs, as produced by the Sun Studio C Compiler - - * See http://rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-trunk/log/20190211T142523Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67052 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 63f990674bdf474f0ce88a23f0bc06b4443d3a94 - Author: nobu - Date: 2019-02-11 22:43:14 +0900 - - Use $(hdrdir) for include/ruby.h, as well as r67033 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67051 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 43a45b3fedcfc0b00ac6a0bafbcc49d8ab592671 - Author: glass - Date: 2019-02-11 12:06:10 +0900 - - io.c: remove unused variable and fix typo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67049 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0f79725a0d20182d749e6ad89785b9acfe5c50dd - Author: svn - Date: 2019-02-11 11:13:04 +0900 - - * 2019-02-11 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67048 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2d2a50961207307104ff16a49d07d6d3a91e0b24 - Author: glass - Date: 2019-02-11 11:12:54 +0900 - - io.c: check HAVE_FCOPYFILE - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c84a25e14882a356bc37647a2acf1b6a9127283b - Author: nobu - Date: 2019-02-10 19:42:50 +0900 - - random.c: unify syscall with getrandom - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 944a158a650a27b3fcbcc17c58605850e89b2b75 - Author: svn - Date: 2019-02-10 17:21:39 +0900 - - * 2019-02-10 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67045 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 61ffc7a0aeaa15a618f61c9df753543fa443df96 - Author: svn - Date: 2019-02-10 17:21:39 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67044 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1a8583de72e12e139e9c7fbcfc026c2cbf410519 - Author: glass - Date: 2019-02-10 17:21:33 +0900 - - random.c: use getrandom() if available. - - getrandom() is supported by glibc 2.25 or later. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b1cb15c4a42575eb8ceb1c89256f37c662e20172 - Author: akr - Date: 2019-02-09 23:54:54 +0900 - - new constant: Process::CLOCK_TAI. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67042 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5d490f6ef82062502aa5821cbd9ebe9b09871820 - Author: svn - Date: 2019-02-09 20:04:11 +0900 - - * 2019-02-09 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67041 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b795f9bd36dcf71fd0495d493b23752b73f4950d - Author: nobu - Date: 2019-02-09 20:04:09 +0900 - - make-snapshot: try downloading Unicode files - - Remove empty UNICODE_FILES list to update Unicode files like as - r67025, for 2.6 branch. - - [Bug #15593] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67040 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5133bfad5df57c3399d1ec13a33e944d90fd613b - Author: nobu - Date: 2019-02-08 18:57:23 +0900 - - enum.c: [DOC] tally does not take a block - - [Feature #11076] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67039 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1616dcb16ef34ebf4ffc2167292f9a779f3e121e - Author: nobu - Date: 2019-02-08 18:49:49 +0900 - - make-snapshot: try downloading Unicode files - - [Bug #15593] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67038 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0deeb1aeb6ab9c35454a64a4da0eeb587a4f2c65 - Author: naruse - Date: 2019-02-08 17:47:42 +0900 - - Call DRb.start_service with setup/teardown - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67037 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 74f94b3e6ebf15b76f3b357e754095412b006e94 - Author: nobu - Date: 2019-02-08 16:22:55 +0900 - - configure.ac: check finite,isinf,isnan as macros first - - [ruby-core:91487] [Bug #15595] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67036 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4578181509ffaafb1e872d6f49f551cc887b727d - Author: nobu - Date: 2019-02-08 11:54:21 +0900 - - Use assert_syntax_error - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67035 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 81fb05db9a09759e50b9b8004a89fd281d36bf67 - Author: nobu - Date: 2019-02-08 11:54:20 +0900 - - Suppress warning [Feature #15575] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67034 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3d1c86a26f0c96a9c1d0247b968aa96e6f3c30bb - Author: nobu - Date: 2019-02-08 11:46:22 +0900 - - Removed moving toplevel header since r12501 - - Moving public headers was 12-years ago, no depend files would - expect ruby.h in the top source directory now. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67033 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e6f8382a766a4e27e008d8cf753c6589a3eb6f85 - Author: headius - Date: 2019-02-08 02:29:16 +0900 - - Replace outdated blockless proc call with block argument syntax - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67032 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 713279550ad33836e5d7bbbb5b801aa13def24dc - Author: eregon - Date: 2019-02-08 01:40:27 +0900 - - Fix specs for yield in singleton class being deprecated - - * Use eval to trigger warning only when the method is called. - * Suppress warnings and clarify this will be removed in 3.0. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67031 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 75334db3c6479ea3cd7462d36ca5464d386f9c72 - Author: eregon - Date: 2019-02-08 01:35:33 +0900 - - Update to ruby/spec@6cf8ebe - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5c7c6763f6cf7b4face107735071c5470e835476 - Author: svn - Date: 2019-02-08 01:35:05 +0900 - - * 2019-02-08 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 820f99791eb813bd72ddce2f5b5c4173d3b69b7b - Author: eregon - Date: 2019-02-08 01:35:03 +0900 - - Update to ruby/mspec@231e2ce - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67028 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6c574d4be4fa5bca86b0afb3a675ace3a8e29de6 - Author: k0kubun - Date: 2019-02-07 23:58:37 +0900 - - appveyor.yml: retry zlib downloads - - https://ci.appveyor.com/project/ruby/ruby/builds/22196846/job/53xvhv265f8eogl4 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8ca727d80f9b25046f85d6cd2e1f68d2fa001760 - Author: k0kubun - Date: 2019-02-07 22:57:27 +0900 - - test_rinda.rb: give up stabilizing this test - - on --jit-wait. It's randomly failing and it's unlikely to be detecting - any MJIT's bug. - - https://app.wercker.com/ruby/ruby/runs/mjit-test2/5c5c2339940b5200f01a0822?step=5c5c2b9fcfa0fc000741d940 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67026 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 910b13fe51891cd6a7e2c391e9d9278f0a5b013a - Author: nobu - Date: 2019-02-07 21:23:02 +0900 - - Update Unicode files - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67025 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a67788b2f365d993c879ad0754f41bc64389459c - Author: nobu - Date: 2019-02-07 17:53:13 +0900 - - Split procstat_vm.c - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67024 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 18365f9e83ef8f8402426024de4777f1f831ba37 - Author: nobu - Date: 2019-02-07 17:53:12 +0900 - - Split mt19937.c - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67023 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 867338c36ea8094b6c45ed3e081315c654fd3617 - Author: nobu - Date: 2019-02-07 17:53:11 +0900 - - Split dtoa.c - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67022 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7199685dc6741c08324adb31462657161499399f - Author: svn - Date: 2019-02-07 17:14:12 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67021 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 673dc51c251588be3c9f4b5b5486cd80d46dfeee - Author: nobu - Date: 2019-02-07 17:14:10 +0900 - - enum.c: Enumerable#tally - - * enum.c (enum_tally): new methods Enumerable#tally, which group - and count elements of the collection. [Feature #11076] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67020 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e0f1b514d2f78fe5ea17ddf240307cafbf47fccf - Author: nobu - Date: 2019-02-07 17:14:09 +0900 - - enum.c: hoisted out enum_hashify - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fb84b86be0f2758bacfb6d04c13e5946f4179fa4 - Author: nobu - Date: 2019-02-07 16:39:47 +0900 - - * string.c (chopped_length): early return for empty strings - - [Bug #11391] - - From: Franck Verrot - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67018 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f27643e5eb464a6bd2c3b3ff3f2f7f165b14e1fb - Author: svn - Date: 2019-02-07 15:56:15 +0900 - - * 2019-02-07 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 58a415343963f0d1fe50b1f645463068dff6182b - Author: kazu - Date: 2019-02-07 15:56:13 +0900 - - tool/test/test_jisx0208.rb: Use `require_relative` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67016 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3104de4e16652b07ef818e09cfd4fc5874a66d20 - Author: svn - Date: 2019-02-06 09:11:08 +0900 - - * 2019-02-06 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67015 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4c0e21add7c87b70df27fbff81d8f192a467556d - Author: nobu - Date: 2019-02-06 09:11:04 +0900 - - common.mk: allow brace expansion for benchmark targets - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67014 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 173ad5202b29f350b61c5f64d952ff96bbf7c98d - Author: k0kubun - Date: 2019-02-05 20:45:52 +0900 - - test_rinda.rb: extend timeout of wait_for as well - - https://app.wercker.com/ruby/ruby/runs/mjit-test2/5c5961adb18ed400951edeeb?step=5c596fd563e946000717df91 - - see also: r67003 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67012 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c1f0daeb6ac5c5414c9a4a58bb778a118006ae1f - Author: eregon - Date: 2019-02-05 19:19:29 +0900 - - Make sure to wait with IO.select before using Socket#accept_nonblock and recvfrom_nonblock - - * On all platforms, as this is the recommended code pattern. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67011 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 920b924e5652884064a9529ffbd80d458a46fbc6 - Author: eregon - Date: 2019-02-05 18:58:50 +0900 - - Make sure to wait with IO.select before using Socket#recvfrom_nonblock - - * On all platforms, as this is the recommended code pattern. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67010 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8552ee87b663e10d6c2265748f57a7d041face2c - Author: eregon - Date: 2019-02-05 18:50:11 +0900 - - Pass the Array from select() to Socket.udp_server_recv - - * As mentioned in the documentation. - * Use Array#size instead of #count, it's more common. - * Use :unset, it clarifies things if the specs fails. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67009 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit af479d54dcd1ce4a02a1f73b3bcab9d30f164f2b - Author: nobu - Date: 2019-02-05 15:00:25 +0900 - - README.win32: [DOC] added modeline [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67008 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9d0b921a41ae3901f16750c2fb725885128379c1 - Author: svn - Date: 2019-02-05 13:58:47 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67007 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0fadb48498b3fee85aa02406b2119f9512c04ae3 - Author: hsbt - Date: 2019-02-05 13:58:46 +0900 - - Ignore to add bundler lib directory if it is same as rubylibdir. - - [Bug #15469][ruby-core:90742] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67006 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 883d2d01335ead7fc0cb002543be587105b8d034 - Author: svn - Date: 2019-02-05 11:19:54 +0900 - - * 2019-02-05 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67005 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c7628071b009e64a0c743e4a4edbed6b454e71fb - Author: samuel - Date: 2019-02-05 11:19:51 +0900 - - Make sure to wait for socket to be readable. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67004 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 190a61e3a506c7d5fa145d6bfc8faa94b71953ef - Author: k0kubun - Date: 2019-02-04 17:20:05 +0900 - - test_rinda.rb: increase timeout for --jit-wait CI - - https://app.wercker.com/ruby/ruby/runs/mjit-test2/5c57dbb6b18ed400951e3c74?step=5c57e8b963e94600070a5d61 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67003 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cc7dedfb4de1f47b2a1713cb7068f9d6ffc33152 - Author: nobu - Date: 2019-02-04 17:17:44 +0900 - - configure.ac: separate -std=gnu99 condition - - Also necessary on mingw, cygwin, darwin and netbsd. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit df2b8c05bac6414d5dae001310a09a2842910dcf - Author: nobu - Date: 2019-02-04 17:13:37 +0900 - - Show proper location for warning [Feature #15575] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67001 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9acd2b20c8fa85fe2ca827dbba195f5f12a16df0 - Author: usa - Date: 2019-02-04 17:10:24 +0900 - - Update requirements - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67000 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0fc597f29c663bd785d3a7868a95340eecc7dc03 - Author: ko1 - Date: 2019-02-04 16:10:05 +0900 - - check and show a warning for incorrect yield. - - * compile.c (check_yield_place): this function check the yield location. - * show a warning if yield in `class` syntax. [Feature #15575] - - * do strict check for toplevel `yield`. Without this patch, - `1.times{ yield }` in toplevel is valid-syntax (raise LocalJumpError - at runtime) although toplevel simple `yield` is not valid syntax. - This patch make them syntax error. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66999 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8bda94f78c959fbbcc17a99553b0c22396cabb96 - Author: ko1 - Date: 2019-02-04 15:28:57 +0900 - - For this may be a syntax error (instead of LocalJumpError) in Ruby 2.7 - [Fix GH-2078] - - This patch is from Yutaka HARA . - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66998 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0c18a3d9826d59c3d02fbd49f84c9d69a706b670 - Author: ko1 - Date: 2019-02-04 15:12:27 +0900 - - add debug code - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66997 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cc1dbb61e0c3344fc6e17fccf2b53e57ce844b9c - Author: glass - Date: 2019-02-04 08:30:56 +0900 - - io.c: get src_size from stp. Fix r66995. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3f0c966603c6ee1ccf4b37071dd586a1b0147433 - Author: svn - Date: 2019-02-04 06:04:12 +0900 - - * 2019-02-04 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66995 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e3fd9fa40364386174695856fe1bb2b6634eaa3c - Author: glass - Date: 2019-02-04 06:04:04 +0900 - - io.c: reuse results of fstat(2) in copy functions - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66994 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8cca079d3be8d07c261baea72529628469938245 - Author: hsbt - Date: 2019-02-02 19:41:22 +0900 - - Fixup r66984. Update the location of bundler gemspec. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66993 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8f8b51c6ac54f476854e355a633dcfb49d9e4459 - Author: nobu - Date: 2019-02-02 16:25:07 +0900 - - README.win32: mention GIT as well as SVN - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66992 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c2781525ec517909b5441d392b139f95865ae3c1 - Author: nobu - Date: 2019-02-02 16:18:50 +0900 - - README.win32: update required commands and platform names - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66991 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 33d026034e68fefcc8a6615907e864d39da6a3fb - Author: nobu - Date: 2019-02-02 15:54:55 +0900 - - rdoc.css: make label-list compact - - "Labeled Lists" section in lib/rdoc/markup.rb states labeled-list - will be formatted in same lines. - - ``` - Notice that blank lines right after the label are ignored in labeled lists: - - [one] - - definition 1 - - [two] - - definition 2 - - produces the same output as - - [one] definition 1 - [two] definition 2 - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66990 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fc7e1baf5184a362377f303821eb6dacd369b006 - Author: nobu - Date: 2019-02-02 15:38:10 +0900 - - COPYING: reformat as RDoc - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66989 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 009144e8efd84ad0223c96a172929a8816266809 - Author: nobu - Date: 2019-02-02 15:38:09 +0900 - - NEWS: use note-list - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66988 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3f78209cd15f3e4532689e3fe1acce6938859dde - Author: nobu - Date: 2019-02-02 15:38:08 +0900 - - README.win32: use label-list - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66987 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b01a7a3edcd05166d8ff1040fdf3d3c0c36cf919 - Author: svn - Date: 2019-02-02 15:17:35 +0900 - - * 2019-02-02 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66986 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3dd0b616243aa5e46df2d8362aa86675d338655c - Author: seki - Date: 2019-02-02 15:17:34 +0900 - - fix: https://twitter.com/_ko1/status/1086167481922646016 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66985 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7c9771be02ddc707fea8ec96089c8a100c59f806 - Author: hsbt - Date: 2019-02-01 22:41:56 +0900 - - Fixed gemspec location of bundler. - - FileCollector of rbinstall.rb requires location of gemspec under - the sub-direcotry with the same name as default gems. - - I forgot to fix it with r66867. - - [Bug #15582][ruby-core:91374] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit adbdbff2df25865e8ba0453749097d960a2384b5 - Author: nobu - Date: 2019-02-01 22:40:10 +0900 - - README.win32: reformat as RDoc - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66983 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1f34da3709673a926483fe056185c41766a637da - Author: k0kubun - Date: 2019-02-01 20:52:06 +0900 - - insns.def: opt_regexpmatch1 is not a leaf insn - - Given `str`, if `str_coderange(str)` is `ENC_CODERANGE_BROKEN`, - it calls `rb_raise`. And it calls `rb_funcallv` from `rb_exc_new3`. - - http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/1673244 - - Maybe we can have a function to directly call `exc_initialize` for this - purpose, but it may not be worth having such a function for keeping the - instruction leaf. We may even want to delete the insn - https://github.com/ruby/ruby/pull/1959. - - I'm not sure whether compile.c could generate opt_regexpmatch2 for - invalid coderange string. Let's monitor that for a while. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66982 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 232f31ca12a94eb9f51182955285a4474f876af7 - Author: shyouhei - Date: 2019-02-01 16:26:39 +0900 - - on-smash canary detection - - In addition to detect dead canary, we try to detect the very moment - when we smash the stack top. Requested by k0kubun: - https://twitter.com/k0kubun/status/1085180749899194368 - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8a098051c58446db8be3dcaea3447ce83e16df99 - Author: shyouhei - Date: 2019-02-01 15:29:02 +0900 - - insns.def: mark exception-raising instructions non-leaf - - These instructions were missed before. The stack canary mechanism - (see r64677) can not detect rb_raise() because exceptions jump over - the canary liveness check. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66980 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3c8ff424c63b6f581c64461bc4b5e13b8b0a710f - Author: nobu - Date: 2019-02-01 14:20:07 +0900 - - vm_trace.c: trick rdoc for TracePoint#enable - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8555c53e74f6862086bde429a18dbe775f661395 - Author: svn - Date: 2019-02-01 14:11:14 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66978 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1bc6c3f40777ca10d8e7df38b775b0bb81a25881 - Author: nobu - Date: 2019-02-01 14:11:08 +0900 - - Revert r63383, r63248 "compile.c: copy a short insn with leave" - - When copying `leave` insn, TRACE also should be copied if it is - present, but this optimization is trivial and not worth the - complexity. [ruby-core:91366] [Bug #15578] - - 4cae5353c03009beb1e0a1619422072773580609 - 5afd479de63b6609ddcd1510da94d2c1ac384f7f - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e826b7d39e0e1a58caa8554d8fe8426f919f726a - Author: shyouhei - Date: 2019-02-01 13:39:47 +0900 - - _leaf_helpers.erb: some functions are not leaf - - If a function has rb_warning() that is not a leaf because warning - ultimately is a method call of Warning#warn. - - If a function has rb_name_error() that is not a leaf because - NameError is allocated, then initialized. This of course - involves calling NameError#initialize. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66976 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5d5427cb0720772c60e4d61511a7a723e0553fdf - Author: svn - Date: 2019-02-01 10:31:36 +0900 - - * 2019-02-01 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66974 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit af83a85f75389f646b753807c1136a7e591dec6a - Author: nobu - Date: 2019-02-01 10:31:34 +0900 - - Run r66972 assertion only when a sticky-bit makes sense - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66973 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cb5a32981404e1bd691978ad9e7ce6a824315995 - Author: nobu - Date: 2019-01-31 23:02:30 +0900 - - Fix exception namespace - - * lib/fileutils.rb (remove_entry_secure): EISDIR is under the - Errno namespace. [ruby-core:91362] [Bug #15577] - - From: Tietew (Toru Iwase) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66972 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1f64192494e896277a8c72a9d0d53ebc93abe312 - Author: naruse - Date: 2019-01-31 21:58:33 +0900 - - Use _NSGetMachExecuteHeader() instead of _mh_execute_header - - _mh_execute_header is not accessible from a dylib unless libruby.dylib is - built with -undefined dynamic_lookup. And using -undefined - dynamic_lookup is not good style. - - Reported by Jeremy Huddleston Sequoia - Reviewed-by: Jeremy Huddleston Sequoia - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66971 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 857bbfd02c8c57b99c1f40311c507ca3bc2f16a6 - Author: shyouhei - Date: 2019-01-31 14:36:17 +0900 - - _insn_type_chars.erb: use C99 - - Now that comma at the end of enum is allowed, we can write this much - more straight-forward. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66960 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e20714062bf57efcbff0dd3162b148dd35312865 - Author: shyouhei - Date: 2019-01-31 14:22:58 +0900 - - _insn_operand_info.erb: use C99 - - Same as r66957. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66959 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 971f965da9a9f8f7cea9bead6c883e79dfc5b715 - Author: shyouhei - Date: 2019-01-31 14:00:41 +0900 - - _insn_len_info.erb: add ASSERT_VM_INSTRUCTION_SIZE - - Also previous rb_vm_insn_len_info is now a function static variable. - It seems nobody else is using it. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66958 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 72e318f118d5cfde0e66a41acd3a2070fcaf4348 - Author: shyouhei - Date: 2019-01-31 13:46:03 +0900 - - _insn_name_info.erb: use C99 - - C99 allows string literals of at least 4095 characters (cf: ISO/IEC - 9899:1999 section 5.2.4.1) so the previous complex struct layout is no - longer necessary. Just dump the verbatim memory contents we want. - - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66957 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 69431818f4166e0f2c35b8cec142e83bad603e13 - Author: svn - Date: 2019-01-31 13:35:15 +0900 - - * 2019-01-31 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66956 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 03dc91facf4688398fac33d90766642a4e14742c - Author: nobu - Date: 2019-01-31 13:35:14 +0900 - - test_iseq.rb: update expected error message - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66955 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ba4d6ae75f3b4aa26c07046671edabb92359f300 - Author: nobu - Date: 2019-01-31 13:35:13 +0900 - - test_iseq.rb: enabled - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66954 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 15f8fb34fa82ecb4c20c7dde3d10ca4a3206c408 - Author: nobu - Date: 2019-01-30 20:58:07 +0900 - - Show the code in syntax assertions - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ea88f7ddf914a85b82f4c228a2e1278c55dff962 - Author: svn - Date: 2019-01-30 15:06:02 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66948 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6f6cf042d2e348e73504258fe36f4bd27694a640 - Author: mrkn - Date: 2019-01-30 15:05:57 +0900 - - enumerator.c: fix arith_seq_first for Infinity - - * enumerator.c (arith_seq_first): fix for Float::INFINITY. - - * test/ruby/test_arithmetic_sequence.rb: add tests. - - * numeric.c (ruby_float_step_size): export for internal use. - - * internal.h: add prototype declaration of ruby_float_step_size. - - [ruby-core:90937][Bug #15518] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66947 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e1e3d642bfaf8f8c1a94687442cf51c897f8abdf - Author: nobu - Date: 2019-01-30 14:08:36 +0900 - - hash.c: hoisted out st_index_hash - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66946 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a94b78e41833d0f6b4e9b566dca234dde4628230 - Author: nobu - Date: 2019-01-30 13:54:01 +0900 - - hash.c: hoisted out dbl_to_index - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66945 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 15530088b66031228b55715bfafb7957da747e9b - Author: svn - Date: 2019-01-30 12:36:10 +0900 - - * 2019-01-30 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66944 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ef17936bc526652d7f3e9dc681a850d58da30242 - Author: svn - Date: 2019-01-30 12:36:09 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66943 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d07d192881920b2b46899fec55bf18199bd71d31 - Author: nobu - Date: 2019-01-30 12:36:06 +0900 - - hash.c: remove repeated rb_hash_start - - * hash.c (rb_dbl_long_hash): remove repeated rb_hash_start as - rb_objid_hash includes rb_hash_start, - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66942 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7fa16fd9624ca38f2d82c121a9af5f22c87e2697 - Author: nobu - Date: 2019-01-28 22:32:32 +0900 - - Fix `Module#const_defined?` on inherited constants - - [Fix GH-2061] - - From: manga_osyo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dd4fdb32bdbb68810fa77468157945a481bd85cc - Author: nobu - Date: 2019-01-28 20:53:54 +0900 - - added assertion with method ref operator - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66937 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b5f906136d821bf015583abdf3b01352805da290 - Author: svn - Date: 2019-01-28 20:45:24 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66936 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2a4c87dc31b3774b8f8f2ab7b74f6d864f41a804 - Author: nobu - Date: 2019-01-28 20:45:21 +0900 - - Add refinements support to method/instance_method. - - [Fix GH-2034] - - From: manga_osyo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66935 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2210709b79222ecd2d9758f7316fdbd7c068ea84 - Author: glass - Date: 2019-01-28 14:04:17 +0900 - - io.c: use fcopyfile(3) in IO.copy_stream if available - - fixed r66930. - - * io.c (nogvl_copy_stream_func): use fcopyfile(3) in IO.copy_stream if available - - * configure.ac: check copyfile.h and fcopyfile(3) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66934 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 774c60955a725e378caded5e074863ceddb27ca8 - Author: glass - Date: 2019-01-28 06:46:06 +0900 - - Revert "io.c: use fcopyfile(3) in IO.copy_stream if available" - - This reverts commit bd670062c4e3a3c9fdfaaaf7bd3c232442a26a4c. - It fails on rubyspec. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66933 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0c7768e63f8859ea996c99142eb0424e2255d91b - Author: svn - Date: 2019-01-28 05:55:39 +0900 - - * 2019-01-28 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66932 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f1a3be3565a04bbb1bb5658b340613585a871370 - Author: svn - Date: 2019-01-28 05:55:38 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66931 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bd670062c4e3a3c9fdfaaaf7bd3c232442a26a4c - Author: glass - Date: 2019-01-28 05:55:26 +0900 - - io.c: use fcopyfile(3) in IO.copy_stream if available - - * io.c (nogvl_copy_stream_func): use fcopyfile(3) in IO.copy_stream if available - - * configure.ac: check copyfile.h and fcopyfile(3) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66930 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 42921458ff7eacd1ef614c3e67596c75ccd0a1d4 - Author: eregon - Date: 2019-01-27 22:12:39 +0900 - - Update to ruby/spec@e57f49c - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a53ee2136ff59ebc54ae6c98a500765bc3d13d44 - Author: svn - Date: 2019-01-26 22:43:42 +0900 - - * 2019-01-26 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66928 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 60023cf4521ce86803b9d328982e679962d448cc - Author: nobu - Date: 2019-01-26 22:43:32 +0900 - - parse.y: trim newline in erred code - - * parse.y (parser_yyerror): trim a newline at the end of the erred - code which was replaced with an extra space in the succeeding - cursor line. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66927 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0a5b4c13ad16bacfa5659f7ac92eb7abf9416261 - Author: shyouhei - Date: 2019-01-25 23:09:10 +0900 - - vm.inc now in C99 - - This changeset modifies the VM generator so that vm.inc is written in - C99. Also added some comments in _insn_entry.erb so that the - intention of each parts to be made more clear. I think this improves - overall readability of the generated VM. - - Confirmed that the exact same binary is generated before/after this - changeset. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66923 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 24b57b102c1992b679f8f8c0fd1a0239289a129b - Author: kou - Date: 2019-01-25 15:49:59 +0900 - - Upgrade CSV to 3.0.4 - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cdca14e75e98e2657daa40589f18a0ad46846020 - Author: svn - Date: 2019-01-25 15:35:08 +0900 - - * 2019-01-25 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66921 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit cee0c36a0890dd44efacf4ea0d37872fb3e903c6 - Author: kou - Date: 2019-01-25 15:35:04 +0900 - - Upgrade RSS to 0.2.8 - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66920 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6375c68f8851e1e0fee8a95afba91c4555097127 - Author: nobu - Date: 2019-01-24 21:36:04 +0900 - - parse.y: function parser_mixed_error & parser_mixed_escape - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66919 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7e68efbc9599550eadf5aa9a50bdc9a36796db49 - Author: nobu - Date: 2019-01-24 20:43:11 +0900 - - parse.y: remove an extra error message - - * parse.y (parse_string): bail out when word-list meets end of - input not to show an extra "unexpected" error message after the - preceding error. - - $ ruby -e "%w[" - -e:1: unterminated string meets end of file - -e:1: syntax error, unexpected terminator, expecting ' ' - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66918 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c6fb7c1f33e128618bcd7799a2de52874c7ebdd8 - Author: nobu - Date: 2019-01-24 19:10:18 +0900 - - eval_error.c: should not escapce newline and tab - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66917 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e608402019642719dd994728c15c8ef45f163d4d - Author: svn - Date: 2019-01-24 14:30:45 +0900 - - * 2019-01-24 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66916 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4bcfccddca1f2ffb72f435ef2e5eb393448a2dea - Author: svn - Date: 2019-01-24 14:30:45 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66915 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 161ece479598629f4ace4fa23bfea7bc1331a8a0 - Author: mrkn - Date: 2019-01-24 14:30:42 +0900 - - numeric.c: Fix negative step with float components - - * numeric.c (ruby_float_step): fix negative step with float components. - - * test/ruby/test_numeric.c (test_step_bug15537): add tests. - - * test/ruby/test_range.c (test_step_bug15537): add tests. - - [Bug #15537] [ruby-core:91101] - - From: shuujii (Shuji KOBAYASHI) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c56f61161a7baefb3d1ed3f815e5dc544b3accd6 - Author: nobu - Date: 2019-01-23 18:39:45 +0900 - - parse.y: token name of tSTRING_DEND - - * parse.y (rb_yytnamerr): show single-quoted single char as-is, to - show a quoted closing brace as tSTRING_DEND. e.g.: - - $ ./ruby -e '"#{true' - -e:1: syntax error, unexpected end-of-input, expecting '}' - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 71342a46ac4244adb27a514f412aecd012e9ed40 - Author: nobu - Date: 2019-01-23 18:08:22 +0900 - - parse.y: token names - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66910 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1fae154c07b957278fd336b54256d5c57f21e0d5 - Author: nobu - Date: 2019-01-23 15:06:47 +0900 - - tmpdir.rb: permission of user given directory - - * lib/tmpdir.rb (Dir.mktmpdir): check if the permission of the - parent directory only when using the default temporary - directory, and no check against user given directory. the - security is the user's responsibility in that case. - [ruby-core:91216] [Bug #15555] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66909 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 05c3256b2883000aab033737ef121a96b8009b81 - Author: svn - Date: 2019-01-23 08:22:10 +0900 - - * 2019-01-23 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66908 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bcf85587b186bf92537ee5b456d2312a5dce9c9d - Author: nobu - Date: 2019-01-23 08:21:58 +0900 - - parse.y: literal add_mark_object - - * parse.y (set_yylval_str, set_yylval_literal): always imply - add_mark_object. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66907 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bdbc8a8f1214b601ca409f66f2fe00ac06f2e99a - Author: kazu - Date: 2019-01-22 21:43:57 +0900 - - Add more example of `String#dump` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66906 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4e64c54728d0d1db94f229feb59fd1bf2d60f686 - Author: nobu - Date: 2019-01-22 16:25:08 +0900 - - ripper.y: get rid of compile error - - yystpcpy is always used by yysyntax_error in bison 2.3, but may - not used by other than yytnamerr in newer bison. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66905 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3dc6efbe9ca582d6930f25754a16043dedecfa6f - Author: hsbt - Date: 2019-01-22 15:28:04 +0900 - - Merge rubygems master targeted RubyGems 3.1.0. - - https://github.com/rubygems/rubygems/commit/1172320540c8c33c59fc1db5191b021c3b2db487 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66904 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 59a6215af65b3bfade13836681cbacc3294e6e78 - Author: nobu - Date: 2019-01-22 15:24:59 +0900 - - parse.y: enclose keyword token names by quotes - - * parse.y (rb_yytnamerr): strip enclosing double-quotes, same as - the default yytnamerr except for that single-quotes matching - back-quotes do not stop stripping. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66903 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e7d03531e109269e3aff7d9865bdf11f3308e67 - Author: svn - Date: 2019-01-22 10:56:35 +0900 - - * 2019-01-22 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66902 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bac705529d358e512b6ce8b9ead6d776ab28486b - Author: nobu - Date: 2019-01-22 10:56:26 +0900 - - fix typo in r66836, missing '/'s - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66901 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f2d63385744da413cba482384d3bdbce288816a5 - Author: eregon - Date: 2019-01-21 21:31:29 +0900 - - benchmark/app_aobench.rb: complete commented code to write the image to a file - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66900 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 32e259f097a8dbae065d55c4d7b299e697a25f84 - Author: eregon - Date: 2019-01-21 21:31:20 +0900 - - benchmark/app_aobench.rb: remove extra printf arguments - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66899 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dfe69186042b2b28e32cb66240ecae820724e430 - Author: eregon - Date: 2019-01-21 21:31:10 +0900 - - benchmark/app_aobench.rb: move `srand(0)` at the top - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66898 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 502f159421cf3e35b9a62ade2a7e0fa2c53a7f21 - Author: samuel - Date: 2019-01-21 19:56:29 +0900 - - Improvements to documentation. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 62ec5eb01874472e2df9d871ef329d5a76b9c853 - Author: nobu - Date: 2019-01-21 19:24:56 +0900 - - parse.y: more token names - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 12afc11fcda570118c03e88cbb72521e33c38f78 - Author: glass - Date: 2019-01-21 19:11:04 +0900 - - * io.c: use copy_file_range() if defined - - * configure.ac: check copy_file_range() - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66895 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6891a1cd5ddd9e5e07d537060a257abaa6833648 - Author: mame - Date: 2019-01-21 17:51:51 +0900 - - string.c (rb_str_dump): Fix the rdoc - - * Officially states that String#dump is intended for round-trip. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66894 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8a294e0f20b0bf4df6528944aa4a4d5ea76b88de - Author: mame - Date: 2019-01-21 16:29:00 +0900 - - benchmark/app_aobench.rb: add `srand(0)` - - To prevent noise for benchmark result. Just for the case. - [Bug #15552] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66893 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit be3a0c7042583922befae8a11f08159607b28df9 - Author: mame - Date: 2019-01-21 16:13:32 +0900 - - benchmark/app_aobench.rb: add a magic comment - - To support the change of default encoding. - It had not worked correctly since 2.0 :-) - [Bug #15552] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66892 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 90653369097d4942cb0d397d77cf9106c839cbfc - Author: glass - Date: 2019-01-21 15:23:55 +0900 - - * lib/net/http.rb: handle Errno::ETIMEDOUT in Net::HTTP#transport_request - A patch from casperisfine (Jean byroot Boussier). - [Fix GH-2012] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66891 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 954d0815e9fea323c5c6b6ba072c0aded845a9b1 - Author: k0kubun - Date: 2019-01-21 10:11:57 +0900 - - test_io.rb: skip test on MJIT to prevent random failure - - like this: - http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/1636642 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66890 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4487562da19a50eceedad8956a652a173c96aff6 - Author: eregon - Date: 2019-01-21 06:25:08 +0900 - - Update to ruby/spec@e2fbd4d - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6204e0804b24f1675b49d5880da014411bcfb831 - Author: eregon - Date: 2019-01-21 05:38:57 +0900 - - Update to ruby/spec@35a9fba - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66888 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 58573c33e4720315ed27491e31dcc22892e1ce95 - Author: eregon - Date: 2019-01-21 05:38:27 +0900 - - Update to ruby/mspec@e9a482d - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66887 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1c53f86bd9701abd6c6d3a787541e5c408f5aef9 - Author: stomar - Date: 2019-01-21 00:07:17 +0900 - - process.c: [DOC] small improvements - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66886 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f284eb3d54df6d1bb754986f9f5272136ff73466 - Author: stomar - Date: 2019-01-21 00:06:11 +0900 - - lib/securerandom.rb: [DOC] small grammar fixes - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66885 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6833fbcfafdf80908e75aa1d13b9aff70646294c - Author: stomar - Date: 2019-01-21 00:04:41 +0900 - - time.c: [DOC] small improvement - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66884 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8fe427c1124601861cea4c00adfe625314b44f4b - Author: svn - Date: 2019-01-21 00:02:08 +0900 - - * 2019-01-21 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66883 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f9b298fe71614a8ceecba9eb78203a78e9fefb28 - Author: stomar - Date: 2019-01-21 00:02:07 +0900 - - vm.c: [DOC] small fix - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66882 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit afd68cd87114fb49158462f1594cacfd2b765e9b - Author: kazu - Date: 2019-01-20 13:44:25 +0900 - - raise FrozenError instead of RuntimeError - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66875 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 27f51081d3b0a4bfb94df1153c005c9bc2c748ba - Author: svn - Date: 2019-01-20 13:38:55 +0900 - - * 2019-01-20 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 141ed2f6409184412b57461de3f759db2520b9c6 - Author: nobu - Date: 2019-01-20 13:38:52 +0900 - - [DOC] Refactors documentation for `Forwardable` - - [ruby-core:71281] [Misc #11639] - - From: Sam Morgan - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66873 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 46549d6b11eb88d02bd2ac4561ab3c7b775cd241 - Author: k0kubun - Date: 2019-01-19 18:08:10 +0900 - - Revert "mjit_worker.c: try to simplify CC_DLDFLAGS_ARGS" - - This reverts commit 405940234eb7876a063eb7129ca61fcc318a633c. - - Not working on MinGW - https://ci.appveyor.com/project/ruby/ruby/builds/21737578/job/09a2tr94vof6fstt - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66872 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e90d826de7d661ef091761bf7d13c9fc70a9d956 - Author: naruse - Date: 2019-01-19 16:49:47 +0900 - - Indented here document (<<~) is Ruby 2.3 feature - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 405940234eb7876a063eb7129ca61fcc318a633c - Author: k0kubun - Date: 2019-01-19 16:35:30 +0900 - - mjit_worker.c: try to simplify CC_DLDFLAGS_ARGS - - assuming that -nostartfiles is just optional for mingw, cygwin, and AIX. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66870 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a5de8d1ccb98c3d1ea50159f5937b3429ff91c42 - Author: k0kubun - Date: 2019-01-19 16:26:59 +0900 - - mjit_worker.c: do not use GCC_NOSTDLIB_FLAGS for OpenBSD - - OpenBSD's GCC compiler has local extensions that break when - `-nostartfiles -nodefaultlibs -nostdlib` is used. - - From: Jeremy Evans - - [Bug #15548] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 31c862a775c8ca05c4f2f8001d32690e9e7f8e28 - Author: svn - Date: 2019-01-19 12:36:25 +0900 - - * 2019-01-19 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66868 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c52ca1f2ffcc8beeec043a9fa44004de59e1bb4c - Author: hsbt - Date: 2019-01-19 12:36:22 +0900 - - Revert r58345 and r58371. - - These changes break the behavior of default gems. Bug #13428 says - r58345 is reasonable because gemspec file is installed by `to_ruby_for_cache` - method. But I revert `to_ruby_for_cache` in rbinstall.rb at r58403. - There is no reason that we apply r58345 now. - - But I'm not sure about gemspec of default gems affects standalone gems. - I'm going to investigate it on rubygems/rubygems. - - [Bug #15500][ruby-core:90867] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c20aae965e2e79fcf4c443b266f7012157d5b23b - Author: nobu - Date: 2019-01-18 18:52:50 +0900 - - Prefer block_given? to iterator? - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66866 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 17aeff3e77e6fe0d37a9943dd93bcb16c4bb9f66 - Author: nobu - Date: 2019-01-18 18:31:32 +0900 - - make-snapshot: get rid of circular dependency - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66865 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c4e832bf6fa605234afee1fa91f0df93bc1a31c8 - Author: nobu - Date: 2019-01-18 15:13:10 +0900 - - configure.ac: fix build_os name - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66864 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3859b77be1141fef50688da3aa70502d1864504c - Author: nobu - Date: 2019-01-18 14:14:59 +0900 - - configure.ac: use MINIRUBY as BOOTSTRAPRUBY on msys - - Msys shell may not be able to run a command with a drive letter? - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66863 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7a86165d43829ed4a464dc9b14e48ffb0d1a6798 - Author: nobu - Date: 2019-01-18 11:36:14 +0900 - - [DOC] mention rb_str_modify - - [ruby-core:91134] [Bug #15543] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66861 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b4ab9c0e3214c619f2025fb19ff8e010d99112eb - Author: ko1 - Date: 2019-01-18 11:04:41 +0900 - - support older BASERUBY for btest. - - * bootstraptest/test_insns.rb: check RbConfig::LIMITS to support - older BASERUBY. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66860 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3c55a0b942be7c2f9e76cfd71f320ce1432c39aa - Author: nobu - Date: 2019-01-18 10:55:25 +0900 - - configure.ac: use BASERUBY as BOOTSTRAPRUBY if available - - MINIRUBY may not be stable enough to run btest, in developing. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66859 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6b5695fef9a99421a61c236c2118f793f6e4559b - Author: nobu - Date: 2019-01-18 08:52:58 +0900 - - make-snapshot: make permissions uniform - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66858 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dabbdcfd6d10e6853554b6224d962adfade53adf - Author: svn - Date: 2019-01-18 08:23:19 +0900 - - * 2019-01-18 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66857 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 92c6072ef4183021b57ccbd3fbd7fefc17952866 - Author: nobu - Date: 2019-01-18 08:23:14 +0900 - - rbinstall.rb: add --exclude option for install-nodoc - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66856 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f550da512cefbe0283106ca839c4836a98efaf3a - Author: hsbt - Date: 2019-01-17 22:45:48 +0900 - - Removed old gemspecs of default gems for the Ruby committers. - - [Bug #12764][ruby-core:77284] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66844 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 367fdd1aee07bd856612e9d796f301e1f1d5a30b - Author: ko1 - Date: 2019-01-17 16:52:47 +0900 - - reset bound if the size is 0. - - * hash.c (RHASH_AR_TABLE_SIZE_DEC): generally, we need to check all - entries to calculate exact "bound" in ar_table, but if size == 0, - we can clear bound because there are no active entries. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66843 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 07298ea2094bca6f847e7b0c82e3c7059ff745e3 - Author: ko1 - Date: 2019-01-17 10:36:21 +0900 - - support btest on older ruby. - - * bootstraptest/runner.rb (assert_normal_exit): check MJIT first - to support btest with ruby ~2.5. btest (bootstraptest) should be - enable to run with stable ruby interpreter because modified ruby - may not able to run runner.rb and we need to know why (this is why - we introduce btest). - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0280bef3417350a0932c084c8dc7a3db86ec93c2 - Author: svn - Date: 2019-01-17 09:36:10 +0900 - - * 2019-01-17 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66841 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d25a27abba89ade8039cc8baabce19e34865ee89 - Author: nobu - Date: 2019-01-17 09:36:08 +0900 - - call rb_str_modify to make a copy unshared - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66840 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d1417ff8fabe8a99dc6c21830b7b3169bb03aa64 - Author: shirosaki - Date: 2019-01-16 23:06:37 +0900 - - dir.c: fix Dir.glob with braces and matching dir - - * dir.c (join_path_from_pattern): add the last slash for directory - matching. - - * test/ruby/test_dir.rb (test_glob_recursive_directory): add a test - for above. - [ruby-core:91110] [Bug #15540] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66838 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 74477ec2b3904a0f39f11294d2bb336fb73586df - Author: nobu - Date: 2019-01-16 11:09:48 +0900 - - Strip warnflags - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d0318b8cfdc9dfd357b30b4394e5af9831de215d - Author: nobu - Date: 2019-01-16 10:35:28 +0900 - - Revert r65800 - - "Makefile.in: reconfig with the original warnflags" - It would be unnecessary since r65803 and r65805. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66835 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 98e218b69a51fe20926d86dc1b02f4b8ca2ee601 - Author: svn - Date: 2019-01-16 09:48:46 +0900 - - * 2019-01-16 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 923d03e10cd1446e53e56c7659c1b8c35eb155b1 - Author: nobu - Date: 2019-01-16 09:48:42 +0900 - - Fixed a typo, missing `$` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66833 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ab2547d786572f4c14e0d849f5f64f006425c5ba - Author: mame - Date: 2019-01-15 23:19:19 +0900 - - st.c (rb_hash_bulk_insert_into_st_table): avoid out-of-bounds write - - "hash_bulk_insert" first expands the table, but the target size was - wrong: it was calculated by "num_entries + (size to build insert)", but - it was wrong when "num_entries < entries_bound", i.e., it has a deleted - entry. "hash_bulk_insert" adds the given entries from entries_bound, - which led to out-of-bounds write access. [Bug #15536] - - As a simple fix, this commit changes the calculation to "entries_bound + - size". I'm afraid if this might be inefficient, but I think it is safe - anyway. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66832 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 10d85b19da5a9c94c5e7af16c53679981aee963b - Author: nobu - Date: 2019-01-15 22:52:38 +0900 - - Clarify Array#- and Array#difference documentation - - Currently we are not explicit enough regarding the potentially confusing - behavior of `Array#-` and `Array#difference` when it comes to duplicate items - within receiver arrays. - - Although the original documentation for these methods does use an array with - multiple instance of the same integers, the explanation for the behavior is - actually imprecise. - - > removing any items that also appear in +other_ary+ - - Not only does `Array#-` remove any items that also appear in `other_ary` but - it also remove any instance of any item in `other_ary`. - - One may expect `Array#-` to behave like mathematical subtraction or difference - when it doesn't. One could be forgiven to expect the following behavior: - - ```ruby - [1,1,2,2,3,3,4,4] - [1,2,3,4] - => [1,2,3,4] - ``` - - In reality this is the result: - - ```ruby - [1,1,2,2,3,3,4,4] - [1,2,3,4] - => [] - ``` - - I hope that I've prevented this potential confusion with the clarifications - in this change. I can offer this as evidence of likeliness for confusion: - https://twitter.com/olivierlacan/status/1084930269533085696 - - I'll freely admit I was surprised by this behavior myself since I needed to - obtain an Array with only one instance of each item in the argument array - removed. - - [Fix GH-2068] [ci skip] - - From: Olivier Lacan - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66831 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d7976d145193379d8c43f33e9a5714292a40d994 - Author: nobu - Date: 2019-01-15 21:05:46 +0900 - - Use `&` instead of `modulo` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66830 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d154bec0d5f0dd32e0d30559ab8a0a7ed8be98d2 - Author: shyouhei - Date: 2019-01-15 15:41:58 +0900 - - setbyte / ungetbyte allow out-of-range integers - - * string.c: String#setbyte to accept arbitrary integers [Bug #15460] - - * io.c: ditto for IO#ungetbyte - - * ext/strringio/stringio.c: ditto for StringIO#ungetbyte - - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66824 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e84537d32c3e2f21071384e2c967fe0308d408d - Author: k0kubun - Date: 2019-01-15 13:02:53 +0900 - - Revert "mjit_worker.c: try passing -nostdlib to AIX" - - This reverts commit b32fb23083912c37a2601c66531ed786a7c9f3e5. - - This didn't work on AIX. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66823 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a01f2f0abd2691270e71cf2374607c2ca4bbce5f - Author: svn - Date: 2019-01-15 12:43:47 +0900 - - * 2019-01-15 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 01d63239e40902bcdc2effa91a9707132290f3ed - Author: naruse - Date: 2019-01-15 12:43:44 +0900 - - Suppress warning: ambiguous first argument; put parentheses or a space even after `/' operator - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66821 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ad10418eab9c70f188d8735ccd1e6f2e160c64e2 - Author: nagachika - Date: 2019-01-14 20:04:52 +0900 - - update redmine-backporter to catch up Redmine 4.0. [ci skip] - - tool/redmine-backporter.rb: change revision resource URL. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66820 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4d727639b45a43e73ec8588e837f74315dafa619 - Author: nobu - Date: 2019-01-14 19:16:54 +0900 - - ast.c: fix missing head part in dynamic literal - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66819 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ec3cdb34ce6f19be7a6d887357fd1763f97992d1 - Author: k0kubun - Date: 2019-01-14 16:28:34 +0900 - - mjit_worker.c: pass -nostdlib when making pch as well - - [Bug #15513] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66817 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b32fb23083912c37a2601c66531ed786a7c9f3e5 - Author: k0kubun - Date: 2019-01-14 15:45:24 +0900 - - mjit_worker.c: try passing -nostdlib to AIX - - r66812 might have allowed this. Testing. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66816 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d14089fb3cef922a0c3a61661fd1c92bd083e991 - Author: k0kubun - Date: 2019-01-14 15:18:53 +0900 - - mjit_worker.c: pass -lgcc to GCC platforms - - using `-nodefaultlibs -nostdlib`. - - I assume libgcc is needed when we use -nostdlib, and it's linked on some - platforms but not linked on some platforms (like aarch64, and possibly - AIX as well) as said in https://wiki.osdev.org/Libgcc : - - > You can link with libgcc by passing -lgcc when linking your kernel - with your compiler. You don't need to do this unless you pass the - -nodefaultlibs option (implied by -nostdlib) - - Also note that -nostdlib is not strictly needed (rather implied - -nodefaultlibs is problematic for Gentoo like Bug#15513, which will be - approached later) but helpful for performance. So I want to keep it for - now. - - [Bug #15522] - - I'm not trying to add `-nodefaultlibs -nostdlib` for AIX in this commit - because AIX RubyCI is dead right now, but I'll try to add them again - once RubyCI is fixed. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66812 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d89d1d468779ccea52d9b8da4f9d967543d28723 - Author: k0kubun - Date: 2019-01-14 14:50:13 +0900 - - mjit_worker.c: untangle CC_LIBS nesting - - This should have no impact. - The CC_LIBS was too hard to read for human. - - I don't remember whether the order of -lmsvcrt and -lgcc matters or not, - but I kept that for the best safety. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66811 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b4bc6ccb4ebf8be89ae0a7fa5f7e764a1cefac86 - Author: svn - Date: 2019-01-14 13:49:32 +0900 - - * 2019-01-14 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66810 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4840771afb158c544d583384404d33dcb4405afe - Author: k0kubun - Date: 2019-01-14 13:49:28 +0900 - - vm_insnhelper.c: make VM helpers inline - - In r66597, both VM and JIT seem to be made slower: - - ``` - $ benchmark-driver benchmark.yml --rbenv 'r66596::before --disable-gems;r66597::after --disable-gems;r66596+JIT::before --disable-gems --jit;r66597+JIT::after --disable-gems --jit' -v --repeat-count 24 - r66596: ruby 2.7.0dev (2018-12-28 trunk 66596) [x86_64-linux] - r66597: ruby 2.7.0dev (2018-12-28 trunk 66597) [x86_64-linux] - r66596+JIT: ruby 2.7.0dev (2018-12-28 trunk 66596) +JIT [x86_64-linux] - r66597+JIT: ruby 2.7.0dev (2018-12-28 trunk 66597) +JIT [x86_64-linux] - Calculating ------------------------------------- - r66596 r66597 r66596+JIT r66597+JIT - Optcarrot Lan_Master.nes 55.174 54.620 88.011 85.326 fps - - Comparison: - Optcarrot Lan_Master.nes - r66596+JIT: 88.0 fps - r66597+JIT: 85.3 fps - 1.03x slower - r66596: 55.2 fps - 1.60x slower - r66597: 54.6 fps - 1.61x slower - ``` - - This commit makes JIT's situation a little better. But in 2.7 we seem to - have some other regressions after that, and this can't still resurrect the - 2.6.0's performance. - - ``` - $ benchmark-driver benchmark.yml --rbenv 'before::before --disable-gems;after::after --disable-gems;before+JIT::before --disable-gems --jit;after+JIT::after --disable-gems --jit' -v --repeat-count 24 - before: ruby 2.7.0dev (2019-01-13 trunk 66808) [x86_64-linux] - after: ruby 2.7.0dev (2019-01-13 trunk 66808) [x86_64-linux] - last_commit=vm_insnhelper.c: make VM helpers inline - before+JIT: ruby 2.7.0dev (2019-01-13 trunk 66808) +JIT [x86_64-linux] - after+JIT: ruby 2.7.0dev (2019-01-13 trunk 66808) +JIT [x86_64-linux] - last_commit=vm_insnhelper.c: make VM helpers inline - Calculating ------------------------------------- - before after before+JIT after+JIT - Optcarrot Lan_Master.nes 51.710 51.535 83.629 85.486 fps - - Comparison: - Optcarrot Lan_Master.nes - after+JIT: 85.5 fps - before+JIT: 83.6 fps - 1.02x slower - before: 51.7 fps - 1.65x slower - after: 51.5 fps - 1.66x slower - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66809 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit edb65a6254a1e06bb2155678676d6798acd7a51e - Author: nobu - Date: 2019-01-13 22:49:25 +0900 - - rdoc: ignore gemspec files - - [ruby-core:91067] [Bug #15531] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66808 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 71d2695d1725270caa1301ab39689c5a6e7e7072 - Author: nobu - Date: 2019-01-13 22:41:36 +0900 - - rdoc: fixup the test for r66806 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66807 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0fb782ea28b61035d56a8fb1f32754a18f2cee60 - Author: nobu - Date: 2019-01-13 22:16:56 +0900 - - rdoc: ignore garbage files - - * lib/rdoc/options.rb (RDoc::Options#init_ivars): exclude backup - files by default. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66806 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6feee125b96cd03794fd670ad02ba16ce7120b0d - Author: nobu - Date: 2019-01-13 22:16:55 +0900 - - common.mk: common rdoc variables - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66805 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 665d9a4331059687e87a6e9c6c1ce9d39b48c35a - Author: nobu - Date: 2019-01-13 13:36:45 +0900 - - time.c: separate sign argument - - * time.c (vtm_add_offset): separate sign argument to get rid of - repeated negations. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66804 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 019c891508334d0437140ac12badbceab86827bd - Author: nobu - Date: 2019-01-13 12:31:01 +0900 - - time.c: do not set utc_offset in vtm_add_offset - - * time.c (vtm_add_offset): just add offset to other components - only. removed subtraction of utc_offset as it is overwritten - always immediately in callers. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66803 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 128b6577b337e240f6e5141b9fbf380cd4d4d11a - Author: svn - Date: 2019-01-13 12:27:18 +0900 - - * 2019-01-13 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66802 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6d18187371c0b90eae41cea18f829363bd61e5f1 - Author: nobu - Date: 2019-01-13 12:27:16 +0900 - - Fix remaining syntax errors in Binding#irb docs - - Apologies for catching those so late. - - [Fix GH-2067] [ci skip] - - From: Olivier Lacan - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66801 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ad0ba0dc2739ebf54dd6df3e0f1d7bbe4712449f - Author: kazu - Date: 2019-01-12 21:39:41 +0900 - - trivial fix r66778 [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66798 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4e28fdf417fcd2d9492277b46a556264ab9ba0de - Author: nobu - Date: 2019-01-12 18:36:52 +0900 - - No FloatDomainError at non-finitive number if exception: false - - [ruby-core:91021] [Bug #15525] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66797 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 62c17a2f21b47243071075cbef37fe72b6ecd0ff - Author: nobu - Date: 2019-01-12 14:02:58 +0900 - - No TypeError at nil if exception: false - - [ruby-core:91021] [Bug #15525] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66796 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 52a97e36d09ae15800c2a52094759c18e7be4ee0 - Author: svn - Date: 2019-01-12 13:53:13 +0900 - - * 2019-01-12 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 056c24d3987e8608ebdddba864f112241ec21992 - Author: nobu - Date: 2019-01-12 13:53:09 +0900 - - RbConfig::CONFIG never had "exeext" - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66794 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0a5655a5be8a7447ca895a6e15a17fb2076d3f34 - Author: nobu - Date: 2019-01-11 18:36:49 +0900 - - Drop whole examples - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66793 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8197abf9aada88fd46bd6898bee21449ace9efaf - Author: nobu - Date: 2019-01-11 17:44:41 +0900 - - Fix r66791 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66792 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d03771d85a77fb85d17bb072618e78a910beb594 - Author: nobu - Date: 2019-01-11 16:50:23 +0900 - - Fix r66772 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66791 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e4f46eabab70bfcde67f0032a902433d11afc166 - Author: kazu - Date: 2019-01-11 13:58:33 +0900 - - Fix make-snapshot for trunk - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66790 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bdc36b360ea093e51cae4f983752bf077982fde0 - Author: nobu - Date: 2019-01-11 10:18:59 +0900 - - Ensure to terminate the child - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66789 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d95b13ead18a22cf7328064f9a29c7de72bf8103 - Author: tenderlove - Date: 2019-01-11 02:28:13 +0900 - - Update refinements docs - - Co-Authored-By: Vladimir Dementyev - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66788 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dd67af4892d7e498357e0e5fbb58512a26367080 - Author: k0kubun - Date: 2019-01-11 00:42:44 +0900 - - addr2line.c: fix -Wextra-semi - - and ignore only -Wgnu-empty-initializer. - https://travis-ci.org/ruby/ruby/jobs/477867392 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66787 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d74fc1b17548cc98b8a545b6c655f06e493a806e - Author: k0kubun - Date: 2019-01-11 00:02:35 +0900 - - addr2line.c: do not suppress -Wpedantic - - because it was for "-assi -Wpedantic" on Travis, but we changed the - Travis build to "-std=c99 -Wpedantic". - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66786 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1e19973d98e24768506cc5d2198f92c12e03476b - Author: svn - Date: 2019-01-11 00:00:42 +0900 - - * 2019-01-11 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66783 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 299e9cd91a97fb298632d4c9a91723cffb5fd6ac - Author: k0kubun - Date: 2019-01-11 00:00:40 +0900 - - revert r66768 for Ruby 2.7 due to Misc#15347 - - It's safer to backport r66768 to 2.6 branch, but for 2.7 it's not - needed anymore. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66782 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d31cbd4ff99c609f5a1b6b0ccf890c603db02e86 - Author: k0kubun - Date: 2019-01-10 23:55:24 +0900 - - test_jit.rb: change format of test error output - - to avoid breaking redmine quote like - https://bugs.ruby-lang.org/issues/15522 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66781 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bb44d9ecf035f2dac47606c50f7e797c79a5a367 - Author: nobu - Date: 2019-01-10 23:44:11 +0900 - - configure: refuse to build with jemalloc when header is missing - - [ruby-core:90964] [Bug #15520] - - Freom: Misty De Meo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66779 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 56bf732aaf5a109964b0297b2158372de2e3ae97 - Author: k0kubun - Date: 2019-01-10 23:31:18 +0900 - - mjit.c: use boolean type for boolean variables - - and functions to clarify the intention and make sure it's not used in a - surprising way (like using 2, 3, ... other than 0, 1 even while it seems - to be a boolean). - - This is a retry of r66775. It included some typos... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit efd99b533177d429dbc64ababfe342ebbd3f6502 - Author: k0kubun - Date: 2019-01-10 22:29:29 +0900 - - Revert "mjit.c: use boolean type for boolean variables" - - This reverts commit bb1a1aeab0f2a5fe437c89b841a887ba56653453. - - We hit something on ci.rvm.jp, reverting until investigation is done. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bb1a1aeab0f2a5fe437c89b841a887ba56653453 - Author: k0kubun - Date: 2019-01-10 22:21:58 +0900 - - mjit.c: use boolean type for boolean variables - - and functions to clarify the intention and make sure it's not used in a - surprising way (like using 2, 3, ... other than 0, 1 even while it seems - to be a boolean). - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66775 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5da9bd0ee5b9a4faf503942b803b8b54b70c98ee - Author: kazu - Date: 2019-01-10 21:41:06 +0900 - - test/ruby/test_method.rb: Remove unreachable call - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66774 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bfb684c0295e4527ba6b494834d783d878c2ca93 - Author: k0kubun - Date: 2019-01-10 17:22:23 +0900 - - NEWS: announce C99 requirement [ci skip] - - [Misc #15347] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66773 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9f1fb0a17febc59356d58cef5e98db61a3c03550 - Author: nobu - Date: 2019-01-10 17:19:14 +0900 - - proc.c: proc without block - - * proc.c (proc_new): promoted lambda/proc/Proc.new with no block - in a method called with a block to a warning/error. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66772 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ec336fb40e4df0c8615e584fbefb5e9e572cb9ec - Author: k0kubun - Date: 2019-01-10 17:04:35 +0900 - - configure.ac: Require C99 - - We already added AC_PROG_CC_C99 in r66605. - This commit stops warning C99 features. - - [Misc #15347] [close https://github.com/ruby/ruby/pull/2064] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66771 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dfdd0e1d08fce51c563d69f15067bf2495158a2b - Author: k0kubun - Date: 2019-01-10 16:59:18 +0900 - - .travis.yml: allow C99 on pedanticism build - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66770 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 33a75edd3cf6062796043ae75747b4b191db3789 - Author: nobu - Date: 2019-01-10 15:01:32 +0900 - - proc.c: check if callable - - * proc.c: check the argument at composition, expect a Proc, - Method, or callable object. [ruby-core:90591] [Bug #15428] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 671ef4e9e3d8cb3c397547934902a6a4fd312816 - Author: nobu - Date: 2019-01-10 09:36:28 +0900 - - Get rid of C99 feature for now [ruby-core:90949] [Bug #15519] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66768 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5577a8776ebcd801122f52d612285faee1dde0f2 - Author: tenderlove - Date: 2019-01-10 08:04:00 +0900 - - insns.def (duparray, duphash): add dtrace hooks - - They are considered Array and Hash creation events, so - allow dtrace (and systemtap) to track those creations. - - Co-Authored-By: Eric Wong - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66767 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5f17fa6c1935cfa145c41844f8d1faa47f532689 - Author: svn - Date: 2019-01-10 04:11:35 +0900 - - * 2019-01-10 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66766 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e3dbe84e12b3ebe95187edc3a5e9fe2f373a0388 - Author: ko1 - Date: 2019-01-10 04:11:32 +0900 - - add setter of iter_lev. - - * hash.c: add special setter function (inc and dec). - - * internal.h: constify RHash::iter_leve. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66765 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 140f8b94ced86966fc6979e8cfc5ef3bfa68da5d - Author: nobu - Date: 2019-01-09 23:04:21 +0900 - - class.c: refactor class_instance_method_list - - * class.c (class_instance_method_list): gather singleton and - extended methods first separately from ancestors. - [ruby-core:90872] [Bug #15501] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 347f3f30d6743e8b7cd133ae298c0290f2ef3a1d - Author: nobu - Date: 2019-01-09 22:58:51 +0900 - - time.c: update error message for invalid utc_offset - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66763 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 78d6e3370238c47d5933703fb55d5ab9e8bc4692 - Author: nobu - Date: 2019-01-09 22:58:49 +0900 - - Fix styles [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit df0faba1ff958590a02fd668afbf2b525e845b54 - Author: svn - Date: 2019-01-09 21:55:21 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66761 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 730f2886b535709832494ebe8c98f88ba0a29cea - Author: kazu - Date: 2019-01-09 21:55:20 +0900 - - Follow behaviour of IO#ungetbyte - - see r65802 and [Bug #14359] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66760 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bc27f87889934099f1b8b17512c634b615062e22 - Author: nobu - Date: 2019-01-09 17:43:50 +0900 - - Remove duplicate macro definition - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66759 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fc9e0302ea6756e0ea95dbc11216a3a776ad16a6 - Author: mrkn - Date: 2019-01-09 16:05:37 +0900 - - complex.c: optimize zero check for Float - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f7c0abeaeaba157b6535b397a4fd551e204608d3 - Author: svn - Date: 2019-01-09 04:22:11 +0900 - - * 2019-01-09 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66757 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 79c150f8a5af9ad555262646fb9631ac40f0c23f - Author: tenderlove - Date: 2019-01-09 04:22:05 +0900 - - Mark array as "going to be modified" in `Array#reject!` - - Before this patch, if `reject!` is called on a shared array it can - mutate the shared array rather than a copy. This patch marks the array - as "going to be modified" so that the shared source array isn't - mutated. - - [Bug #15479] [ruby-core:90781] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66756 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e9dc6f6076207f84a93ae917ca682d7d2c973f86 - Author: nobu - Date: 2019-01-08 19:53:43 +0900 - - Check by #name [ruby-core:90853] [Bug #15497] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66755 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 497075b3a1b2021f882f13b86b1e96dc87513d6f - Author: svn - Date: 2019-01-08 18:08:37 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66754 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 50784a0a4412df551d96dd01067473cd4226481b - Author: nobu - Date: 2019-01-08 18:08:31 +0900 - - Defer escaping control char in error messages - - * eval_error.c (print_errinfo): defer escaping control char in - error messages until writing to stderr, instead of quoting at - building the message. [ruby-core:90853] [Bug #15497] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66753 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e52b102c36dc1dd609a97149e99edc7d1f96b7a4 - Author: nobu - Date: 2019-01-08 16:45:04 +0900 - - Test for "%p" in Time.strptime - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66752 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bbd1e83e5aa15f2f5fd3afa569de04bbd9c21eec - Author: mrkn - Date: 2019-01-08 13:53:06 +0900 - - complex.c: replace misused UNLIKELY with LIKELY - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66751 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1e87935958c0afc9e953079e99eb628865e55820 - Author: svn - Date: 2019-01-08 13:37:44 +0900 - - * 2019-01-08 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66750 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2b9c6e1a8a1aa94ed8d300368abb4247cfb24d87 - Author: mrkn - Date: 2019-01-08 13:37:40 +0900 - - range.c (range_last): disable optimization when each is redefined - - Do not use the optimized version of Range#last when Range#each is - redefined. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66749 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8371a9a4ceea32f8e76f3d867722b42e5477fba1 - Author: nobu - Date: 2019-01-07 16:03:23 +0900 - - time.c: support military time zone names - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4f9ab3a01a475f5236632575fa4d3a6b6aef7d15 - Author: nobu - Date: 2019-01-07 15:59:46 +0900 - - time.c: UTC and Z timezones should be utc - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66746 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da1f9199bd659f6277d53cc41f6007911fb3a9c5 - Author: hsbt - Date: 2019-01-07 15:01:49 +0900 - - Bump version to date-2.0.0. - - I forgot to change it when Ruby 2.6.0 was released. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66745 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a288ff502ed5267898fd8e38d291c611befe7f0b - Author: mrkn - Date: 2019-01-07 13:49:34 +0900 - - complex.c (f_divide): canonicalize a quotient - - Canonicalize resultant real and imaginary parts when complex number - divided by non-complex number. - - [Fix GH-2065] [Bug #15505] [ruby-core:90891] - - From: Joe Peric - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66744 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 72ad092960c413b6a5687c552747b20a5ed78b22 - Author: nobu - Date: 2019-01-07 11:05:21 +0900 - - Time.strptime benchmarks - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66743 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9e3ffd41f5aa697bcfd2adac29498755f095d4a3 - Author: nobu - Date: 2019-01-07 10:58:05 +0900 - - Select ruby to run benchmarks with BENCH_RUBY - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66742 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 26ea03c04fdcd282d499b762017d78d8c06e68e5 - Author: svn - Date: 2019-01-07 00:46:22 +0900 - - * 2019-01-07 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d41fb6ce0b35e197b98ca441b05011d28577ddc2 - Author: mrkn - Date: 2019-01-07 00:46:21 +0900 - - benchmark/range_last.yml: remove needless prelude - - [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66740 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d8931259d0bfd8f4d97402250488a590be2a4453 - Author: k0kubun - Date: 2019-01-06 23:53:43 +0900 - - internal.h: unify our own stdtbool.h implementation - - because we had another one in missing/stdbool.h as well. - Assuming that _Bool does not exist when stdbool.h is absent, I'm in - favor of r57462 implementation rather than r61326. - - Note that Visual Studio 2013 has stdbool.h and thus r57462's commit - message is somewhat misleading. This missing/stdbool.h is for Visual - Studio 2012 or older, and for Oracle Solaris Studio 12.2 or older because - it's added in 12.3 https://docs.oracle.com/cd/E24457_01/html/E21987/gkeza.html. - - missing/stdbool.h: ditto. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66739 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d9699fadf8b7031fb92854106d7703b8370eb95f - Author: duerst - Date: 2019-01-06 20:41:12 +0900 - - simplify filename-related code - - (Thanks to Nobuyoshi Nakada for the hint!) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66738 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b991ccc2103eb468cc663a1263750fb86d0745ae - Author: duerst - Date: 2019-01-06 16:50:18 +0900 - - add logic to handle Unicode beta period file names - - In downloader.rb, add logic to handle file names of the form - UnicodeData-12.0.0d6.txt. To find the right file, we download - the index of the directory. Then we download the files by finding - the file names from the index. Files are always checked for changes, - because changes might be frequent during the beta period. - We also check whether any index.html files are left when we are not - in the beta period. This would indicate that we might have stale - data from the beta period rather than the actual release data. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66737 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit dd3ed41cd03f37da856e0af764d8cc8aec952531 - Author: nobu - Date: 2019-01-06 14:07:10 +0900 - - ast.c: argument must be a string - - [ruby-core:90904] [Bug #15511] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66736 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6629588aa555a21a6849f3b093c21fedf9880c23 - Author: nobu - Date: 2019-01-06 13:36:56 +0900 - - Fix mday overflow - - [ruby-core:90897] [Bug #15506] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66735 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6e1d498ac7cd6fcd18352a22d8a3e3ed19df9c6b - Author: mrkn - Date: 2019-01-06 09:46:36 +0900 - - range.c: optimize rb_range_last for int renage - - This change improves the performance of Range#last method for a range - of integer. This optimization directly computes only required values - only in a range instead of converting all values in the range to an - array. The optimized implementation is 129-16.7k times faster than - the previous one in the benchmark result given below. - - === Benchmark Result === - - ``` - $ make benchmark ITEM=range_last COMPARE_RUBY=/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby - generating known_errors.inc - known_errors.inc unchanged - /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged - /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \ - --executables="compare-ruby::/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby -I.ext/common --disable-gem" \ - --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \ - $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*range_last*.yml' -o -name '*range_last*.rb' | sort) - Warming up -------------------------------------- - (1..1_000_000).last(100) 35.600 i/s - 36.000 times in 1.011239s (28.09ms/i) - (1..1_000_000).last(1000) 36.204 i/s - 39.000 times in 1.077240s (27.62ms/i) - (1..1_000_000).last(10000) 36.470 i/s - 39.000 times in 1.069386s (27.42ms/i) - Calculating ------------------------------------- - compare-ruby built-ruby - (1..1_000_000).last(100) 36.477 609.196k i/s - 106.000 times in 2.905950s 0.000174s - (1..1_000_000).last(1000) 35.936 50.350k i/s - 108.000 times in 3.005321s 0.002145s - (1..1_000_000).last(10000) 35.641 4.602k i/s - 109.000 times in 3.058233s 0.023685s - - Comparison: - (1..1_000_000).last(100) - built-ruby: 609195.7 i/s - compare-ruby: 36.5 i/s - 16700.87x slower - - (1..1_000_000).last(1000) - built-ruby: 50349.7 i/s - compare-ruby: 35.9 i/s - 1401.08x slower - - (1..1_000_000).last(10000) - built-ruby: 4602.1 i/s - compare-ruby: 35.6 i/s - 129.12x slower - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66734 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bf6584b5d0f88377ed448612e1170716f6f7dc83 - Author: mrkn - Date: 2019-01-06 09:46:35 +0900 - - benchmark/range_last.yml: add benchmark cases - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66733 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fc7f99066608286f70fabcdec221e1502d40695b - Author: ko1 - Date: 2019-01-06 07:41:59 +0900 - - fix last commit. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66732 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 93583166c8cc9b28d36d8f4f8e23fe968849498c - Author: ko1 - Date: 2019-01-06 07:40:32 +0900 - - refactoring. - - * hash.c (EQUAL, PTR_EQUAL): make corresponding inline functions - ar_equal() and ar_ptr_equal(). - - * hash.c (SET_*): removed. set fields directly. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66731 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 70caae18f26fb305b73ca33e71c46f370c3e0d20 - Author: ko1 - Date: 2019-01-06 07:23:54 +0900 - - add ar_ prefix for ar_table functions. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66730 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 89cbf307b5c354f04b84b405bbd297c21c34ec03 - Author: svn - Date: 2019-01-06 00:09:45 +0900 - - * 2019-01-06 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66727 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6ce2ef33b562deaa4b4e3d94269fe64c93d3f985 - Author: mrkn - Date: 2019-01-06 00:09:44 +0900 - - test/ruby/test_range.rb: add assertions - - Add assertions of Range#first and Range#last to examine the type - conversion of the arguments and the negative value check. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66726 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b6b4c7cbb4581b8ce505e775a46531d33a6b3df6 - Author: nobu - Date: 2019-01-05 23:31:12 +0900 - - compile.c: initialize to suppress false warning. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66725 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9cbb4dde74f854b0cfcdb48b1ce0604894c83665 - Author: nobu - Date: 2019-01-05 22:15:07 +0900 - - parse.y: refactored symbol rules - - * parse.y (symbol): turned into a node, as well as `numeric`, for - a symbol literal, and includes `dsym` now. - - * parse.y (ssym): previous `symbol`. renamed as the counterpart - of `dsym`. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66724 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 47834932368f9af3a57e50f606d9990c1cd54c46 - Author: nobu - Date: 2019-01-05 21:13:39 +0900 - - parse.y: hoisted out qcall_branch_start and qcall_branch_end - - * compile.c (qcall_branch_start, qcall_branch_end): hoisted out - branch coverage traces generation for qcall. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66723 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 59f59f82d42e32980694ae7b8cd2b55384eb5918 - Author: nobu - Date: 2019-01-05 20:35:24 +0900 - - parse.y: refine error messages - - * parse.y: refine error messages for tSYMBEG and tSTRING_BEG, which - can appear at invalid places. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66722 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 56a6dd66d4deff3edc2af09271c50619a05cf1ea - Author: mrkn - Date: 2019-01-05 19:07:40 +0900 - - benchmark/range_last.yml: add a benchmark of Range#last - - [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66721 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 89e3d2f8d3db4ae43ee1f3a922136f30595f8467 - Author: duerst - Date: 2019-01-05 18:47:55 +0900 - - separate downloading of Unicode property files and auxiliary files - - Separate downloading of Unicode property files in ucd and in ucd/auxiliary. - This is needed because we need information from separate index.html files - to discover the exact file names of property files during a beta period. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66720 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0c0d181e0fc9947b4d64b9bb3fcafcc65c3ec8bb - Author: ko1 - Date: 2019-01-05 09:31:54 +0900 - - fix trivial indentation. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66719 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 23801110085a691095fc9a8eb164880418b2215d - Author: ko1 - Date: 2019-01-05 09:06:09 +0900 - - call functions directly. - - * hash.c: ar_table only supports `objhash` so we can call compare/hash - functions directly. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66718 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3a144485fc450465ba370cdf0d5501813d5962d7 - Author: ko1 - Date: 2019-01-05 08:48:33 +0900 - - refactoring usage of ar_lookup(). - - * hash.c (hash_stlike_lookup): introduce inline a function and use it - instead of using ar_lookup()/st_lookup() directly. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66717 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit eca91625b2ec367902a41a8a302bc802132ec02e - Author: svn - Date: 2019-01-05 00:41:32 +0900 - - * 2019-01-05 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66716 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6c1ed519ef51fe8afb7e0ed7f0df2cd2fc0db13d - Author: k0kubun - Date: 2019-01-05 00:41:29 +0900 - - win32/Makefile.sub: try to use __restrict on Visual Studio 2013 - - as well. Follows up r66598. - - https://bugs.ruby-lang.org/issues/15347#note-7 is saying __restrict - is supported on Visual Studio 2013. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66715 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a2eb04f52dccb9b42404f8b133acb36b577e3b54 - Author: svn - Date: 2019-01-04 22:14:18 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6304c0c4d1f2d582ccd2af15407bec3c5c647c8e - Author: svn - Date: 2019-01-04 22:14:18 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66713 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 23444302d9200bcc41ce279a529f73cad63c3f05 - Author: normal - Date: 2019-01-04 22:14:11 +0900 - - introduce rb_nogvl C-API to mark ubf as async-signal-safe - - zlib and bignum both contain unblocking functions which are - async-signal-safe and do not require spawning additional - threads. - - We can execute those functions directly in signal handlers - without incurring overhead of extra threads, so provide C-API - users the ability to deal with that. Other C-API users may - have similar need. - - This flexible API can supersede existing uses of - rb_thread_call_without_gvl and rb_thread_call_without_gvl2 by - introducing a flags argument to control behavior. - - Note: this API is NOT finalized. It needs approval from other - committers. I prefer shorter name than previous - rb_thread_call_without_gvl* functions because my eyes requires - big fonts. - - [Bug #15499] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66712 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 16cfd26a57c30e17bc3c116c83134420693ba5c4 - Author: svn - Date: 2019-01-04 22:11:02 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66711 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e97741e12a22d78825a3a9dfcb7382adb0e27855 - Author: hsbt - Date: 2019-01-04 22:10:58 +0900 - - Merge Bundler 2.0.1 from upstream. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66710 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4bbbbb6a3f5bd242f740041a644311f97c4a0052 - Author: svn - Date: 2019-01-04 21:53:10 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66709 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9e66910b3bd85de32e95cf019ed285a36aecfd9e - Author: normal - Date: 2019-01-04 21:53:06 +0900 - - thread.c (call_without_gvl): spawn thread for UBF iff single-threaded - - We need another native thread to call some unblocking functions - which aren't RUBY_UBF_IO or RUBY_UBF_PROCESS. Instead of a - permanent thread in <= 2.5, we can now rely on the thread cache - feature to perform interrupts. - - [ruby-core:90865] [Bug #15499] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66708 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 79aef1272e877b67b15b00a9cded806845556a0f - Author: nobu - Date: 2019-01-04 18:49:32 +0900 - - [DOC] escape descriptions [ci skip] - - Escape descriptions not to get parsed as directives. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66707 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9035e73a14087c1d3d6e015758ec467e47fc2d19 - Author: nobu - Date: 2019-01-04 18:41:13 +0900 - - [DOC] mark function names [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66706 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8513c20370d2416632f36858edd076e099836a99 - Author: nobu - Date: 2019-01-04 18:25:32 +0900 - - [DOC] split a tag for each function name [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66705 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 44aaff6d310f8cf88d89af4437d678a64bd89aa4 - Author: kazu - Date: 2019-01-04 18:10:10 +0900 - - [DOC] Fix close tags [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66704 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 74c462a90047ca25be8c7cc922dfa2118fc06bfd - Author: nobu - Date: 2019-01-04 17:22:27 +0900 - - class.c: [DOC] fix close tag [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 87e628d66b7bf98f276dbd38b810f0197f821081 - Author: ko1 - Date: 2019-01-04 16:49:00 +0900 - - skip to calculate hash value on empty Hash ar_table lookup. - - * hash.c (ar_lookup): don't calculate hash_value if ar_table is empty. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66702 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 784df9e6fd41a73cbdfc22222c5917991aa0825e - Author: svn - Date: 2019-01-04 10:59:54 +0900 - - * 2019-01-04 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66701 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ba4672c2cb90c85bfeb7cac3295c68b116c7c6f5 - Author: ko1 - Date: 2019-01-04 10:59:49 +0900 - - ar_table_entry::hash should be `st_hash_t`. - - * hash.c: the type of `ar_table_entry::hash` is not a `VALUE`, - but a `st_hash_t`. - Also `st_hash_t` is not a `st_data_t`, but `st_index_t` (same as st.c). - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b2a7a289e046cbbfc7f439f312a7204c174c3869 - Author: nobu - Date: 2019-01-03 20:42:24 +0900 - - Fix Random.urandom in a chroot on OpenBSD - - [ruby-core:90850] [Bug #15494] - - From: jeremyevans0 (Jeremy Evans) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66699 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d0045da598f13c32606b1bf04f2eac5c3759761a - Author: k0kubun - Date: 2019-01-03 15:27:35 +0900 - - .travis.yml: propagate -w properly - - r66692's `export RUBYOPT="-w"` does not seem to work. - Passing `RUBYOPT="-w"` to `make test-all`'s argument works. - - Let's try having this for all environments. - - (see r66690 for motivation) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66698 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 673ff731c17bbbae4d672c8514d4991382179981 - Author: mrkn - Date: 2019-01-03 15:19:17 +0900 - - complex.c: Optimize Complex#* and Complex#** - - Optimize f_mul for the core numeric class components. - This change improves the computation time of Complex#* and Complex#**. - - ``` - $ make benchmark ITEM=complex_float_ COMPARE_RUBY=/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby - generating known_errors.inc - known_errors.inc unchanged - /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged - /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \ - --executables="compare-ruby::/Users/mrkn/.rbenv/versions/2.6.0/bin/ruby -I.ext/common --disable-gem" \ - --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \ - $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*complex_float_*.yml' -o -name '*complex_float_*.rb' | sort) - Calculating ------------------------------------- - compare-ruby built-ruby - complex_float_add 6.558M 13.012M i/s - 1.000M times in 0.152480s 0.076850s - complex_float_div 576.821k 567.969k i/s - 1.000M times in 1.733640s 1.760660s - complex_float_mul 1.690M 2.628M i/s - 1.000M times in 0.591786s 0.380579s - complex_float_new 1.350M 1.268M i/s - 1.000M times in 0.740669s 0.788762s - complex_float_power 1.571M 1.835M i/s - 1.000M times in 0.636507s 0.544909s - complex_float_sub 8.635M 8.779M i/s - 1.000M times in 0.115814s 0.113906s - - Comparison: - complex_float_add - built-ruby: 13012361.7 i/s - compare-ruby: 6558237.1 i/s - 1.98x slower - - complex_float_div - compare-ruby: 576821.0 i/s - built-ruby: 567968.8 i/s - 1.02x slower - - complex_float_mul - built-ruby: 2627575.4 i/s - compare-ruby: 1689800.0 i/s - 1.55x slower - - complex_float_new - compare-ruby: 1350130.8 i/s - built-ruby: 1267809.6 i/s - 1.06x slower - - complex_float_power - built-ruby: 1835168.8 i/s - compare-ruby: 1571074.6 i/s - 1.17x slower - - complex_float_sub - built-ruby: 8779168.8 i/s - compare-ruby: 8634534.7 i/s - 1.02x slower - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66697 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 670725b08784e7467ffbd4b40c9a7c3cd9ca813e - Author: kazu - Date: 2019-01-03 14:51:19 +0900 - - [DOC] Complex() default behaviour is `exception: true` [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66696 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bace0d4cdcfaec75e76145349f0b3c0b989a0b6d - Author: kazu - Date: 2019-01-03 14:51:18 +0900 - - [DOC] Add `or nil` to call-seq [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66695 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 55cb93efc539cbc71de486aaba300457cf21e9b5 - Author: k0kubun - Date: 2019-01-03 14:24:05 +0900 - - test_complex.rb: use the same approach to fix failures - - as r66682. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66694 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2fd6ed62b4826c03bd6d41ae99a5bd7fecafec40 - Author: k0kubun - Date: 2019-01-03 14:19:05 +0900 - - test_complex.rb: fix tests for RUBYOPT="-w" - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66693 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3bc28f49330cc3114d39552399bf38aa31c19aa4 - Author: k0kubun - Date: 2019-01-03 14:15:54 +0900 - - .travis.yml: enforce -w in invoke_ruby as well - - actually current test-all does not fail with RUN_OPTS="-w". - - and chkbuild seems to use RUBYOPT="-w" - https://github.com/ruby/chkbuild/blob/bad4681c30e71f132cdd80f324d4b8f132f6582c/chkbuild/ruby.rb#L605 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66692 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5e1e60c3462b38d01f385a3fd2018f576a6e2722 - Author: svn - Date: 2019-01-03 14:08:46 +0900 - - * 2019-01-03 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5743c9e85897333c4e8e4bb59d2377f1780bc19b - Author: k0kubun - Date: 2019-01-03 14:08:43 +0900 - - .travis.yml: add a test matrix with -w - - currently Travis and AppVeyor does not run tests with test-all, - but RubyCI uses -w and currently all RubyCIs are failing. - - It might be better to fail at least one CI in Travis to notice it - earlier. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit ee2ddf5411f51ea89a1569ea5d70b41cd4c6c7f2 - Author: mrkn - Date: 2019-01-02 13:25:11 +0900 - - complex.c: fix against redefining component methods - - This fixes the incompatibility (maybe unintentionally) introduced by - removal of `#ifndef PRESERVE_SIGNEDZERO` guards in f_add, f_mul, and - f_sub functions in r62701. [Bug #15491] [ruby-core:90843] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 888ddda157a3253eac9e2b8962826f55e2b8fb85 - Author: mrkn - Date: 2019-01-02 13:18:34 +0900 - - test/net/fixtures/Makefile: moved from test/net/imap - - This Makefile can be used to update test certificates. It should have been - moved at which the certificates was moved at r56836. - - [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66687 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1e0b49a293d3792826c67b7e05c5fcbd09c9ea6e - Author: kazu - Date: 2019-01-02 12:29:01 +0900 - - Try to update cert (2nd try) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f234e6c3d3170f37508e214cdaef78d4b2584e5a - Author: kazu - Date: 2019-01-02 12:08:20 +0900 - - Try to update cert - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66685 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6d957b2f1198514243b62abb381a876184d0a684 - Author: mrkn - Date: 2019-01-02 10:36:39 +0900 - - complex.c: fix indentation - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66684 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f43b38abad6282809b2573d0bf8d364dbdd77869 - Author: svn - Date: 2019-01-02 07:49:58 +0900 - - * 2019-01-02 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66683 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b70a215ebb59961dff17a646831ae8801b1cca1 - Author: naruse - Date: 2019-01-02 07:49:55 +0900 - - suppress warning: method redefined; discarding old + introduced at r66681 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66682 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5f90845420bd65be6926976a8a0dfd7a1b3173cf - Author: mrkn - Date: 2019-01-01 21:20:05 +0900 - - complex.c: Optimize Complex#+ for some conditions - - Optimize f_add defined in complex.c for some specific conditions. - It makes Complex#+ about 1.4x faster than r66678. - - Compared to r66678: - - ``` - mrkn-mbp15-late2016:complex-optim-o3 mrkn$ make benchmark ITEM=complex_float_ COMPARE_RUBY=/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby - /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged - /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \ - --executables="compare-ruby::/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby -I.ext/common --disable-gem" \ - --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \ - $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*complex_float_*.yml' -o -name '*complex_float_*.rb' | sort) - Calculating ------------------------------------- - compare-ruby built-ruby - complex_float_add 9.132M 12.864M i/s - 1.000M times in 0.109511s 0.077734s - complex_float_div 600.723k 627.878k i/s - 1.000M times in 1.664662s 1.592666s - complex_float_mul 2.320M 2.347M i/s - 1.000M times in 0.431039s 0.426113s - complex_float_new 1.473M 1.489M i/s - 1.000M times in 0.678791s 0.671750s - complex_float_power 1.690M 1.722M i/s - 1.000M times in 0.591863s 0.580775s - complex_float_sub 8.870M 9.516M i/s - 1.000M times in 0.112740s 0.105091s - - Comparison: - complex_float_add - built-ruby: 12864383.7 i/s - compare-ruby: 9131502.8 i/s - 1.41x slower - - complex_float_div - built-ruby: 627878.0 i/s - compare-ruby: 600722.5 i/s - 1.05x slower - - complex_float_mul - built-ruby: 2346795.3 i/s - compare-ruby: 2319975.7 i/s - 1.01x slower - - complex_float_new - built-ruby: 1488649.1 i/s - compare-ruby: 1473207.5 i/s - 1.01x slower - - complex_float_power - built-ruby: 1721837.2 i/s - compare-ruby: 1689580.2 i/s - 1.02x slower - - complex_float_sub - built-ruby: 9515562.7 i/s - compare-ruby: 8869966.3 i/s - 1.07x slower - ``` - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66681 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8d473272dbd9f5c6adc518b780eafee3d1f0d6bc - Author: mrkn - Date: 2019-01-01 21:20:04 +0900 - - benchmark/complex_float_*.yml: New benchmarks - - Add new benchmark scripts for binary operations of Complex with float - components. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 11ba186c4725ef7acecbf99243083bc909b7c960 - Author: k0kubun - Date: 2019-01-01 18:52:15 +0900 - - test_jit.rb: test methodref insn - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66679 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6e7213f427c8030396c2de6cc488cae5d8dd5ff9 - Author: hsbt - Date: 2019-01-01 13:53:52 +0900 - - Merge rubygems-3.0.2. - - https://blog.rubygems.org/2019/01/01/3.0.2-released.html - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f77d381159419434b3c1f1a63839706967f348f9 - Author: svn - Date: 2019-01-01 12:03:20 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66677 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9613af6f34e46bc70528593b345824ccada18102 - Author: mame - Date: 2019-01-01 12:03:17 +0900 - - compile.c (iseq_set_sequence): fix branch coverage table - - Not only TRACE_ELEMENT but also INSN_ELEMENT may have events. - The old pc2branchindex was created using only events of TRACE_ELEMENTs. - This change uses events of INSN_ELEMENTs too for pc2branchindex table. - - [Bug #15476] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66676 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 99d363184765ef6b11e739299a805c366171fd26 - Author: svn - Date: 2019-01-01 10:51:01 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66675 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d58bada6cc35187d61315eb881674ae37cbbfce6 - Author: mame - Date: 2019-01-01 10:50:57 +0900 - - compile.c: support branch coverage for `a&.foo = 1` - - [Bug #15475] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7e035dcda7f8d2ce23d769424fdbf7d149c0b894 - Author: svn - Date: 2019-01-01 10:47:17 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66673 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4130969ea19835d0a69a69ee6ffc7fa3dfedb675 - Author: mame - Date: 2019-01-01 10:47:14 +0900 - - Revert r66670 because of wrong ticket number - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 04dec2df733a7ca1cf895be3e82ad3b0cf374741 - Author: svn - Date: 2019-01-01 10:41:26 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 67a257cac091e44cd49a5c1a8c00cee59e284cff - Author: mame - Date: 2019-01-01 10:41:23 +0900 - - compile.c: support branch coverage for `a&.foo = 1` - - [Bug #15476] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66670 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8423533c25db3d5e427accfa8e66895777c36df6 - Author: svn - Date: 2019-01-01 00:00:52 +0900 - - * 2019-01-01 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66669 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d935a0ab951510241450694c73361a03656ad15b - Author: svn - Date: 2019-01-01 00:00:52 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66668 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 67c574736912003c377218153f9d3b9c0c96a17b - Author: nobu - Date: 2019-01-01 00:00:37 +0900 - - Method reference operator - - Introduce the new operator for method reference, `.:`. - [Feature #12125] [Feature #13581] - [EXPERIMENTAL] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66667 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 4a6f7633303f2d6eb5ec164dc656cf5d47531960 - Author: svn - Date: 2018-12-31 23:59:32 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66666 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1bdd422b9360c886c02c2216a230a6c95fe475a0 - Author: nobu - Date: 2018-12-31 23:59:29 +0900 - - Fix indents [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66665 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 705941a4925e6721fe300d263de11179010d02d5 - Author: nobu - Date: 2018-12-31 23:59:27 +0900 - - use a local variable - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66664 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 271c8f5d06bc92d3d3382fbddae616019555ed91 - Author: k0kubun - Date: 2018-12-31 21:54:40 +0900 - - test_io_wait.rb: try to stabilize test_wait_readable - - that randomly fails - https://rubyci.org/logs/mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-trunk/log/20181231T103312Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66663 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d7c7382f7afcba2d74454b24f9d1b9bb761c7242 - Author: svn - Date: 2018-12-31 10:14:52 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 58508e8b558e1ae83d2f15617cb09f1cee8e222e - Author: nobu - Date: 2018-12-31 10:14:51 +0900 - - load.c: resolve_feature_path - - * load.c (rb_resolve_feature_path): search the path for already - loaded feature. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66661 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c5e8627f658c88b2403e7b20637cf25e31feff88 - Author: glass - Date: 2018-12-31 10:09:30 +0900 - - Revert "lib/net/http.rb: use connect_timeout instead of Timeout" - - This reverts commit 69a1db96fe63ff3071cb3d272675a1d0470aab01. - getaddrinfo(3) doesn't support timeout. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66660 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 69a1db96fe63ff3071cb3d272675a1d0470aab01 - Author: glass - Date: 2018-12-31 09:46:07 +0900 - - lib/net/http.rb: use connect_timeout instead of Timeout - - lib/net/pop.rb: ditto - - lib/net/ftp.rb: ditto - - lib/net/smtp.rb: ditto - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f964fd3fa5070b95cb412cb529b47e168c0af25a - Author: nobu - Date: 2018-12-31 06:42:52 +0900 - - vm_args.c: search symbol proc in super classes - - * vm_args.c (refine_sym_proc_call): traverse ancestors to search - inherited methods for symbol proc. - [ruby-dev:50741] [Bug #15489] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66658 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7e4e641c009fede540a9e307ac1d3bb9dcf00f7a - Author: eregon - Date: 2018-12-31 02:48:11 +0900 - - Exclude Solaris in Process.clock_gettime specs - - * It declares clocks which are invalid for clock_gettime(), which I consider OS bug. - * I want to keep testing all declared clocks on other platforms. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8b8e5246e79971457489cf4bd37309c2945c33e1 - Author: svn - Date: 2018-12-31 02:47:57 +0900 - - * 2018-12-31 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66656 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit eeedf7d57a4648fcfb75a54023c889fca3e78a3d - Author: eregon - Date: 2018-12-31 02:47:56 +0900 - - Revert "clock_gettime_spec.rb: exclude invalid clocks for Solaris" - - * This reverts commit a7edd05f7dca44f56fd72d7bcc232e1b27df0eb3. - * I prefer to exclude Solaris, I want to keep testing these clocks on Linux/macOS. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66655 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a46ce26870d8a758c596b95695429e177069f011 - Author: kazu - Date: 2018-12-30 23:09:09 +0900 - - [DOC] Update basename [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c6915042aba8525ab40a27342a04a2accf865955 - Author: mame - Date: 2018-12-30 22:21:30 +0900 - - vm.c: Move the rdoc of RubyVM.resolve_feature_path [Bug #15482] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66653 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 695cc19be963e35dabd85ea824a02f698bc260c0 - Author: k0kubun - Date: 2018-12-30 16:36:27 +0900 - - accept_nonblock_spec.rb: wait before calling #accept_nonblock - - fixes r66593 in a better way like r66646. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66652 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6f0e4c755f7d5921dfa3263ac25cab6a012e99ce - Author: k0kubun - Date: 2018-12-30 15:19:10 +0900 - - test_array.rb: increase timeout for RubyCI - - https://rubyci.org/logs/mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-trunk/log/20181230T041101Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66651 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a7edd05f7dca44f56fd72d7bcc232e1b27df0eb3 - Author: k0kubun - Date: 2018-12-30 15:17:16 +0900 - - clock_gettime_spec.rb: exclude invalid clocks for Solaris - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable10x/ruby-trunk/log/20181230T041806Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-trunk/log/20181230T042407Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11s/ruby-trunk/log/20181230T032505Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-trunk/log/20181230T022505Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66650 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f110ebfd141710e65e230b9e79855e9ded91258e - Author: k0kubun - Date: 2018-12-30 15:09:38 +0900 - - test_optimization.rb: increase timeout for RubyCI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/log/20181230T040002Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66649 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6b861342b9ef41daf3a4c55d5a50a09f023a2180 - Author: sorah - Date: 2018-12-30 12:15:58 +0900 - - Unset SOURCE_DATE_EPOCH on Rubygems test cases - - Relates to r66554. When test suites run with SOURCE_DATE_EPOCH, several - tests would fail. Environment Variables are already kept with this - setup & teardown phase. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66648 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e8d3fb6cdacd87a3f4d377ea13d8b47878d3006d - Author: k0kubun - Date: 2018-12-30 10:00:29 +0900 - - test_refinement.rb: increase timeout for RubyCI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/amazon/ruby-trunk/log/20181229T153003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 230fe41825b45c92cf73e7c8d62f4941dae7beb9 - Author: normal - Date: 2018-12-30 09:46:02 +0900 - - accept_nonblock_spec: IO.select instead of sleep - - Waiting on socket I/O using IO.select should work on all platforms. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7f54f1b5543b4a3267a64c47cff9127cbcafcc42 - Author: eregon - Date: 2018-12-30 09:05:56 +0900 - - Update to ruby/spec@2d89e48 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2eee74ef54a2e23eb870680a83dcf74c5d9d9d01 - Author: nobu - Date: 2018-12-30 08:40:15 +0900 - - Update NoMethodError/NameError docs [ci skip] - - [ruby-core:90796] [Bug #15481] - - From: zverok (Victor Shepelev) - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66644 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 65b1cf0e82255db68262dfb8fdb001268981e223 - Author: eregon - Date: 2018-12-30 06:55:12 +0900 - - Skip specs on AIX as it doesn't have /dev/fd - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66643 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c608af0f1eef89581b1222793e8497d302fb6701 - Author: eregon - Date: 2018-12-30 06:54:59 +0900 - - Re-enable spec on Solaris to find out which clocks fail on Solaris - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66642 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit be8d3ed1fd2f8eb8ec5918c0a7ec30afc4fb34d4 - Author: eregon - Date: 2018-12-30 06:54:45 +0900 - - Exclude CLOCKs which require special permissions in Process.clock_gettime specs - - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-ad7f67/ruby-trunk/log/20181229T135406Z.fail.html.gz - * https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel_zlinux/ruby-trunk/log/20181229T143303Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66641 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 94f4a0e91ee7077bcb4391a6f754c6ec58e78a15 - Author: ko1 - Date: 2018-12-30 01:44:09 +0900 - - `TracePoint#enable(target_thraed:)` [Feature #15473] - - * vm_trace.c (tracepoint_enable_m): `TracePoint#enable` supports - `target_thread:` keyword to filter a target thread. - [Feature #15473] - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fd7d4a871cd3ae035a4a48eb728f9d3fcb37e669 - Author: svn - Date: 2018-12-30 01:29:52 +0900 - - * 2018-12-30 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66639 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 8ee0a8e91a2dfcde0381949348268961b0f81393 - Author: ko1 - Date: 2018-12-30 01:29:44 +0900 - - hide ar_table internals from internal.h. - - * internal.h: move ar_table def to hash.c because other files - don't need to know implementation of ar_table. - - * hash.c (rb_hash_ar_table_size): added because gc.c needs to know - the size_of(ar_table). - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66638 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9f3585afad86f7683fec377a0eb4bb53b8165529 - Author: k0kubun - Date: 2018-12-29 20:04:42 +0900 - - process.c: document system(..., exception: true) [ci skip] - - From: Victor Shepelev - - [Bug #15480] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 31a60184f4a91424419b13171c3b04780ac064e4 - Author: eregon - Date: 2018-12-29 19:54:37 +0900 - - Re-enable spec on Linux to find out which clocks fail on RHEL - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66636 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 21f4795e80c244f0931dc0509b3bf6b3d650e7bd - Author: eregon - Date: 2018-12-29 19:54:22 +0900 - - Refactor Process.clock_gettime spec to give more information when it fails - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66635 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5049e4c5e8608848029710d441b5426766573a1c - Author: k0kubun - Date: 2018-12-29 19:50:31 +0900 - - test_jit.rb: suppress random test failure - - on mswin RubyCI by Permission Denied. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66634 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d8008fc29dd0551c7fa5625c91b7eae923d62939 - Author: k0kubun - Date: 2018-12-29 16:41:20 +0900 - - clock_gettime_spec.rb: add more platform guards for RubyCI - - `Errno::EINVAL: Invalid argument - clock_gettime` could occur even on Linux. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66633 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1ae3e6f3ce9f16c49d0584e0ad3dc3e709cc4a81 - Author: k0kubun - Date: 2018-12-29 16:26:22 +0900 - - erb.rb: increase warn level only when non-zero safe_level - - is given. - - This is merging Eric's patch in [Bug #15479] to Ruby 2.6's behavior in r66631. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66632 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c02f03609036ba4e815c2ed67fa002492b39dda9 - Author: k0kubun - Date: 2018-12-29 16:11:38 +0900 - - Revert "erb.rb: print deprecation warning with warn level 1" - - This reverts commit b5569b9ab2ad5e0e4a997df7eb73e97ecbacc9dd. - - The deprecation is indefinitely postponed. - - [Bug #15478] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit a403cd3598932b3349b8ff5a786b8fe4abbc3f91 - Author: k0kubun - Date: 2018-12-29 15:49:54 +0900 - - test_gc.rb: increase timeout for RubyCI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/amazon/ruby-trunk/log/20181229T033003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66630 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7a859b6ae3000e47a36cff5603c414bb55a4a08f - Author: k0kubun - Date: 2018-12-29 15:48:34 +0900 - - test_jit.rb: prevent mixing outputs by race condition - - to avoid random failures like - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11s/ruby-trunk/log/20181229T032506Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66629 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 63aaee923bdaab7b85fbbafa199b767e15523646 - Author: k0kubun - Date: 2018-12-29 13:48:23 +0900 - - test_notimp.rb: loosen timeout - - to prevent random failures like - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian8/ruby-trunk/log/20181229T033003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66628 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 952b218ffe78b7319c5e02887e7dd30d46dbc40e - Author: k0kubun - Date: 2018-12-29 12:57:15 +0900 - - spawn_spec.rb: add missing platform guard - - this exists for `context "when passed close_others: false" do`, but this - seems to be missing for `context "when passed close_others: true"`. - And this seems to hang forever on Windows since r66622. - https://ci.appveyor.com/project/ruby/ruby/builds/21277729 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66627 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f9dc0fb649e66cc0791d1b9c265644ed0fea82fa - Author: k0kubun - Date: 2018-12-29 10:53:10 +0900 - - test_iseq_load.rb: increase timeout for stressful roundtrip - - Even 60s is short for our CI environments: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/amazon/ruby-trunk/log/20181228T153002Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66626 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bfd1980db2f482670430577e04f0add5960313ee - Author: svn - Date: 2018-12-29 10:51:35 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66625 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 40b689c71a04d2033c5b2924bbaa21efaf395ea4 - Author: k0kubun - Date: 2018-12-29 10:51:34 +0900 - - clock_gettime_spec.rb: skip a new spec broken on solaris - - introduced in r66622, but this does not succeed on Solaris - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-trunk/log/20181229T002409Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66624 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c027f224431fe47ab5ea9ad2070a445244586fc4 - Author: eregon - Date: 2018-12-29 09:54:10 +0900 - - Update to ruby/spec@c8b36c4 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66623 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2076c2c3c401d9ab9324468818bbc46d4e4b870a - Author: eregon - Date: 2018-12-29 09:22:52 +0900 - - Update to ruby/spec@944ea57 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 548defb608847973e78462a38c8418f90dce9911 - Author: eregon - Date: 2018-12-29 09:22:31 +0900 - - Update to ruby/mspec@2bd2ead - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66621 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2ceebcc37b8ef5a9ca55d1fe3c3b000ccb9eaeb1 - Author: svn - Date: 2018-12-29 00:19:13 +0900 - - * 2018-12-29 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1317fefe53b95d763a281d8bf13e8bd023069068 - Author: k0kubun - Date: 2018-12-29 00:19:11 +0900 - - .travis.yml: increase timeout for test-all - - we reached 30min timeout on osx build - https://travis-ci.org/ruby/ruby/jobs/473019623 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 26572d228d3ba804d275aa55dc4f06adbcefb4af - Author: k0kubun - Date: 2018-12-28 23:30:16 +0900 - - test_io.rb: increase timeout for RubyCI - - to stabilize AIX powerpc CI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/aix71_ppc/ruby-trunk/log/20181227T113302Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0bbf1eb7542a56cc00a6c77e3f8bfd89a7b5bdd5 - Author: k0kubun - Date: 2018-12-28 23:24:46 +0900 - - test_readline.rb: skip readline test for new solaris11s-sunc - - for now. This should be fixed, but let me make this new CI green - first to introduce Solaris-related changes later. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66617 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b0b0ded5aa2cf7c4574b057d8326ed4e1c172c12 - Author: k0kubun - Date: 2018-12-28 23:18:05 +0900 - - webrick/test_utils.rb: loosen timeout severity - - to stabilize CI failure like: - https://rubyci.org/logs/rubyci.s3.amazonaws.com/osx1013/ruby-trunk/log/20181228T114501Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fa3fda1c620b14872dadc81b8b790e9dce80a619 - Author: k0kubun - Date: 2018-12-28 23:12:42 +0900 - - jit_support.rb: deal with -std=c99 flag - - CC is changed from "icc" to "icc -std=c99" by r66605. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/icc-x64/ruby-trunk/log/20181228T130003Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66615 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c42a872e5b960696f7ae4377ab80cbeb4b1d837b - Author: k0kubun - Date: 2018-12-28 23:05:45 +0900 - - test_array.rb: increase timeout for RubyCI - - to prevent random failures. - - test/ruby/test_autoload.rb: ditto - test/ruby/test_optimization.rb: ditto - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-trunk/log/20181228T101706Z.fail.html.gz - https://rubyci.org/logs/mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-trunk/log/20181228T114549Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66614 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 6e85a0ea7ee55e693148d82935da0c9b08e98974 - Author: k0kubun - Date: 2018-12-28 22:20:38 +0900 - - test_iseq_load.rb: increase timeout for RubyCI - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/arch/ruby-trunk/log/20181228T090001Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66613 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 78e3cd2bb1827eba1367b1ec9f4a58bce146d26b - Author: samuel - Date: 2018-12-28 22:03:18 +0900 - - Fix #endif annotation. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66612 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9ee79b658123a2a4af65c80484d1f91ce73354e2 - Author: samuel - Date: 2018-12-28 22:03:14 +0900 - - Don't allow rb_fiber_resume to raise exception on unborn fiber. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66611 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5fb9d1e11fc50df359a1f9d2537a11f13cdb6d33 - Author: samuel - Date: 2018-12-28 22:03:09 +0900 - - Implement Fiber#raise. Fixes #10344. - - This allows raising exceptions in another fiber, similarly to - Thread#raise. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b0d24baf8ab4fda0c24e15f9207984971cac8e07 - Author: svn - Date: 2018-12-28 19:33:04 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66609 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d54a86d49dfea10cfcd46fbde5046bdf13a479d1 - Author: nobu - Date: 2018-12-28 19:33:02 +0900 - - Hoisted out undefined_constant - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66608 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit f826cde5a9030e3ffb42bef2c09ee669b13d1465 - Author: nobu - Date: 2018-12-28 18:44:32 +0900 - - Add RUBY_API_VERSION to rbconfig.rb on mswin too - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66607 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 041b61e3407d317a0bff3bf4b85fe7b13833874f - Author: k0kubun - Date: 2018-12-28 18:34:51 +0900 - - test_jit.rb: suppress random failure on RubyCI - - This failure is a known issue that exists mainly on CI environments. - We should address this at some moment, but making CI red by this would - be just a false-positive alarm for now. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66606 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 61885c9b7ca8ccdaf53d7c365fbb86bad3294d88 - Author: k0kubun - Date: 2018-12-28 18:23:27 +0900 - - configure.ac: try to fix addr2line build failure - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian8/ruby-trunk/log/20181228T063002Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/scw-9d6766/ruby-trunk/log/20181228T081706Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/gentoo/ruby-trunk/log/20181228T063002Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos6/ruby-trunk/log/20181228T063003Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos7/ruby-trunk/log/20181228T080003Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/log/20181228T080002Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel_zlinux/ruby-trunk/log/20181228T063303Z.fail.html.gz - https://rubyci.org/logs/rubyci.s3.amazonaws.com/icc-x64/ruby-trunk/log/20181228T090003Z.fail.html.gz - - I suspect r66598 triggered something. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66605 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e23a166995dc1d671f15e8a8e77d110019f05875 - Author: nobu - Date: 2018-12-28 13:28:16 +0900 - - .travis.yml: ignore non-existent files - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 971e1aaf635c42498497d38829137af8b949f04a - Author: nobu - Date: 2018-12-28 13:23:39 +0900 - - .travis.yml: rbconfig.rb is not needed to setup sources - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66603 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9417d10fe18f2f51e80ecf415496e78fcdb3b64e - Author: nobu - Date: 2018-12-28 12:55:28 +0900 - - RUBY_PROGRAM_VERSION for MJIT_PRECOMPILED_HEADER - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66602 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 91dfdf840ba3f1b26ca26e75ac5e3c8166c7d5cc - Author: shyouhei - Date: 2018-12-28 12:42:11 +0900 - - vm_insnhelper.c: USE_FLONUM is always defined - - This changeset should fix the 32bit failures. - See also: https://travis-ci.org/ruby/ruby/jobs/472855470 - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit da8830e3de84717ca5dbb659b60dc94557f7258c - Author: ko1 - Date: 2018-12-28 12:09:29 +0900 - - fix r66599 to success install. please refix this patch @nobu - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 842272540886ff1da58e690907b08f2811a86607 - Author: nobu - Date: 2018-12-28 11:12:34 +0900 - - Moved version numbers - - * Define major and minor version numbers only in the public - include/ruby/version.h header, as the API version numbers. - - * Define only teeny version number in the private version.h - header. - - * RUBY_VERSION moved to version.c. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66599 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1095705c4218f8f752210f1a0b4f78d96ad675ac - Author: nobu - Date: 2018-12-28 10:56:20 +0900 - - Check if restrict keyword is supported - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 24b1b433c5abf02e9f9c7eb3851f4417dc5d8751 - Author: shyouhei - Date: 2018-12-28 10:06:04 +0900 - - vm_insnhelper.c: delete unused macros - - - FIXNUM_2_P: moved to vm_insnhelper.c because that is the only - place this macro is used. - - - FLONUM_2_P: ditto. - - - FLOAT_HEAP_P: not used anywhere. - - - FLOAT_INSTANCE_P: ditto. - - - GET_TOS: ditto. - - - USE_IC_FOR_SPECIALIZED_METHOD: ditto. - - - rb_obj_hidden_p: ditto. - - - REG_A: ditto. - - - REG_B: ditto. - - - GET_CONST_INLINE_CACHE: ditto. - - - vm_regan_regtype: moved inside of VM_COLLECT_USAGE_DETAILS - because that os the only place this enum is used. - - - vm_regan_acttype: ditto. - - - GET_GLOBAL: used only once. Removed with replacing that usage. - - - SET_GLOBAL: ditto. - - - rb_method_definition_create: declaration moved to - vm_insnhelper.c because that is the only place this declaration - makes sense. - - - rb_method_definition_set: ditto. - - - rb_method_definition_eq: ditto. - - - rb_make_no_method_exception: ditto. - - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66597 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d3c0b20949916aa7b432a0498a8016d67a7822ad - Author: svn - Date: 2018-12-28 02:39:21 +0900 - - * remove trailing spaces. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 496267023c490e717ad0598bf1e3364835b734a4 - Author: ko1 - Date: 2018-12-28 02:39:17 +0900 - - fix missed script_compiled events. [Bug #15471] - - * ruby.c (process_options): script_compiled events are missed on - command line -e or specified file. this commit fix it. - [Bug #15471] - - This patch should be backport to Ruby 2.6 branch. - - * vm_core.h (rb_exec_event_hook_script_compiled): introduce utility - function to invoke a script_compiled event. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit fcc5a19e2f9801217691a842250db937de3ea5ee - Author: k0kubun - Date: 2018-12-28 01:42:41 +0900 - - test_method.rb: do not kill RubyCI openSUSE machine - - with NoMemoryError on TestMethod#test_splat_long_array. - - https://rubyci.org/logs/rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/log/20181227T080002Z.log.html.gz - - Maybe better to check /proc/meminfo instead of /etc/os-release. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66594 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 006afb858d77efe9f63d056cf54c3bb578cd39da - Author: k0kubun - Date: 2018-12-28 01:28:40 +0900 - - accept_nonblock_spec.rb: skip spurious failure - - on solaris until it gets stable. - https://rubyci.org/logs/rubyci.s3.amazonaws.com/unstable11x/ruby-trunk/log/20181227T142405Z.fail.html.gz - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66593 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3e3b8df5f95418d68af6bae659bd16b8c80a3830 - Author: svn - Date: 2018-12-28 01:24:47 +0900 - - * 2018-12-28 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66592 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e1930666c76953ad8bcc3d4b95a5b94c553f525f - Author: k0kubun - Date: 2018-12-28 01:24:46 +0900 - - test/mkmf/test_flags.rb: try to suppress random CI failure - - on AIX ppc - https://rubyci.org/logs/rubyci.s3.amazonaws.com/aix71_ppc/ruby-trunk/log/20181226T113305Z.fail.html.gz - - test/lib/test/unit/assertions.rb: ditto, for TestIO#test_copy_stream_no_busy_wait - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66591 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 45918161a831c0ada6eecd79ba9500d50e308f72 - Author: k0kubun - Date: 2018-12-27 23:53:02 +0900 - - jit_support.rb: skip testing MJIT on oracle developer studio - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66590 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1922e6ad65b7a458eeeb84da9f07724b0f1c1145 - Author: k0kubun - Date: 2018-12-27 23:32:29 +0900 - - common.mk: pass CFLAGS to transform_mjit_header.rb - - so that flags like -msse4.1 are passed when checking compilation status - in transform_mjit_header.rb. It matters for checking __builtin_xxx things. - - [Fix GH-2059] [Bug #14964] - - From: pavel - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66589 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d9cce0814db58a506d549fea0f316a679335e22d - Author: nobu - Date: 2018-12-27 23:18:16 +0900 - - Fix restoration - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66588 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 71987f3f09ba51c34a002370ec5dd3202e9beae4 - Author: nobu - Date: 2018-12-27 23:15:36 +0900 - - Suppress warnings - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b7c2ca7a3225efcc79a72ee3798abc3320f5c304 - Author: akr - Date: 2018-12-27 21:42:45 +0900 - - [DOC] SecureRandom is extended by Random::Formatter. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66586 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e3e09806a227acb9d1d4ced37c808d97f4eeb3cf - Author: kazu - Date: 2018-12-27 18:09:42 +0900 - - Arrange as same as comment and return statement - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66585 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit bc64df876ebe96fa5da2b98d6227a8ef4163b911 - Author: shyouhei - Date: 2018-12-27 15:12:09 +0900 - - delete emacs mode lines [ci skip] - - These settings are now covered by .dir-locals.el. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66584 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 070a4aa0f00bd466fe52c526a0e862092cdcfa81 - Author: shyouhei - Date: 2018-12-27 15:11:09 +0900 - - add .dir-locals.el [ci skip] - - Recent Emacs (23 and up?) has this feature called .dir-locals.el. - See also: https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html - - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1680a13a926b17661329beec1ded6b32aad16c1b - Author: nobu - Date: 2018-12-27 13:49:12 +0900 - - Fix Net::Protocol::BufferedIO#write when sending large multi-byte string - - This commit should fix Net::Protocol::BufferedIO#write when sending - large multi-byte string like following example. - - ``` - $ ruby -rnet/http -rjson -v -e "Net::HTTP.post(URI('http://httpbin.org/post'), { text: 'ã‚'*100_000 }.to_json, 'Content-Type' => 'application/json')" - ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux] - Traceback (most recent call last): - 19: from -e:1:in `
' - 18: from lib/ruby/2.6.0/net/http.rb:500:in `post' - 17: from lib/ruby/2.6.0/net/http.rb:605:in `start' - 16: from lib/ruby/2.6.0/net/http.rb:920:in `start' - 15: from lib/ruby/2.6.0/net/http.rb:502:in `block in post' - 14: from lib/ruby/2.6.0/net/http.rb:1281:in `post' - 13: from lib/ruby/2.6.0/net/http.rb:1493:in `send_entity' - 12: from lib/ruby/2.6.0/net/http.rb:1479:in `request' - 11: from lib/ruby/2.6.0/net/http.rb:1506:in `transport_request' - 10: from lib/ruby/2.6.0/net/http.rb:1506:in `catch' - 9: from lib/ruby/2.6.0/net/http.rb:1507:in `block in transport_request' - 8: from lib/ruby/2.6.0/net/http/generic_request.rb:123:in `exec' - 7: from lib/ruby/2.6.0/net/http/generic_request.rb:189:in `send_request_with_body' - 6: from lib/ruby/2.6.0/net/protocol.rb:247:in `write' - 5: from lib/ruby/2.6.0/net/protocol.rb:265:in `writing' - 4: from lib/ruby/2.6.0/net/protocol.rb:248:in `block in write' - 3: from lib/ruby/2.6.0/net/protocol.rb:275:in `write0' - 2: from lib/ruby/2.6.0/net/protocol.rb:275:in `each_with_index' - 1: from lib/ruby/2.6.0/net/protocol.rb:275:in `each' - lib/ruby/2.6.0/net/protocol.rb:280:in `block in write0': undefined method `bytesize' for nil:NilClass (NoMethodError) - ``` - - [Fix GH-2058] - - From: Eito Katagiri - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66582 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1f866ddc1473588541f6b18761b43625857f7a37 - Author: svn - Date: 2018-12-27 13:21:56 +0900 - - * 2018-12-27 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66581 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 384ca22a7a8d9ccaea86ea336e349bcbd536335d - Author: nobu - Date: 2018-12-27 13:21:53 +0900 - - io-console.gemspec: update - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66580 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 94bdc4edf0583109ce97e244f6423d840b11c092 - Author: mame - Date: 2018-12-26 23:43:25 +0900 - - string.c: remove the deprecation warnings of `String#bytes` with block - - And its friends: lines, chars, grapheme_clusters, and codepoints. - [Feature #6670] [ruby-core:90728] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66579 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 0df1de8b32f98793f596fd8d3b608fc6f3104e01 - Author: mame - Date: 2018-12-26 23:42:07 +0900 - - Revert "string.c: remove the deprecation warnings of `String#bytes` with block" - - Forgot to write the ticket number in the commit log... - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66578 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 5281a0047f6f32103569372ae1a39cfadda4866c - Author: kazu - Date: 2018-12-26 18:14:28 +0900 - - Fix typos [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66577 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit e030e9f0b8be42dd8c5eb43e3f390106f3b6a48e - Author: mame - Date: 2018-12-26 18:04:12 +0900 - - object.c (rb_obj_match): use rb_warn for deprecation warning - - Now the warning is printed even without -w option. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2b21744efa34a685d0b3d3b333622989a7615cda - Author: mame - Date: 2018-12-26 17:52:19 +0900 - - string.c: remove the deprecation warnings of `String#bytes` with block - - And its friends: lines, chars, grapheme_clusters, and codepoints. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66575 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 35b7af7503d380f220b5730d47b542ba295be37b - Author: mrkn - Date: 2018-12-26 17:17:30 +0900 - - Import bigdecimal 1.4.2 - - * https://github.com/ruby/bigdecimal/compare/v1.4.1..v1.4.2 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66574 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9b817107ce0fea9e4dcde6edf5664c734a2faa2b - Author: naruse - Date: 2018-12-26 17:01:51 +0900 - - fix typo - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66573 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 9edb32dae72c2b45b524e9ca98650cd2b974fe22 - Author: shyouhei - Date: 2018-12-26 16:23:35 +0900 - - add #line [ci skip] - - These erb files are in fact erb comments + plain C. Adding #line - help us debug in case we have trouble there. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66572 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 2914522ffc39c22dfdccf5ad68162232c5cd0d35 - Author: mame - Date: 2018-12-26 16:04:31 +0900 - - spec/ruby/library/socket/socket/bind_spec.rb: allow to run under docker - - A root user runs the spec without Errno::EACCES - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66571 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 7453cdba1b62d6f6533f8c7bfdf6011524e11853 - Author: mame - Date: 2018-12-26 16:02:31 +0900 - - spec/ruby/core/process/setpriority_spec.rb: allow to run under docker - - Docker container is not always able to lower the nice value even if the - euid is a root. It depends upon the configuration of docker which - cannot check from the container itself. - - This change does check it by actually trying to lower the value first. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 925a722ae2c453c351d6e9fff9776bb0a2061642 - Author: mame - Date: 2018-12-26 15:01:18 +0900 - - test/rdoc: skip some tests when euid is root - - root user can access a file whose permission is 0000. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66569 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1df30008b2461c930a3fb8a8d887f54e403f8379 - Author: mame - Date: 2018-12-26 14:31:22 +0900 - - test/ruby/test_process.rb (test_execopts_uid): rescue Errno::EACCES - - The tests fail under the following condition: - - * executed as a root - * the code is in a directory that uid:30000 user cannot access - (e.g., /root) - - So, this change rescues Errno::EACCES explicitly. - Also, this change adds `exception: true` to `Kernel#system` calls. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66568 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b8d28b33b4df47f53d78b2f5587a72429cda3d91 - Author: normal - Date: 2018-12-26 13:04:01 +0900 - - doc/extension.ja.rdoc (rb_gc_register_mark_object): fix prototype - - It takes VALUE, not a pointer to a VALUE. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66567 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 70398311d06e48016ce944db69fce23bb361460c - Author: svn - Date: 2018-12-26 09:59:40 +0900 - - * expand tabs. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66566 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d46ab953765e2114b6f2f58792be9a7a974e5f27 - Author: shyouhei - Date: 2018-12-26 09:59:37 +0900 - - insns.def: refactor to avoid CALL_METHOD macro - - These send and its variant instructions are the most frequently called - paths in the entire process. Reducing macro expansions to make them - dedicated function called vm_sendish() is the main goal of this - changeset. It reduces the size of vm_exec_coref from 25,552 bytes to - 23,728 bytes on my machine. - - I see no significant slowdown. - - Fix: [GH-2056] - - vanilla: ruby 2.6.0dev (2018-12-19 trunk 66449) [x86_64-darwin15] - ours: ruby 2.6.0dev (2018-12-19 refactor-send 66449) [x86_64-darwin15] - last_commit=insns.def: refactor to avoid CALL_METHOD macro - Calculating ------------------------------------- - vanilla ours - vm2_defined_method 2.645M 2.823M i/s - 6.000M times in 5.109888s 4.783254s - vm2_method 8.553M 8.873M i/s - 6.000M times in 1.579892s 1.524026s - vm2_method_missing 3.772M 3.858M i/s - 6.000M times in 3.579482s 3.499220s - vm2_method_with_block 8.494M 8.944M i/s - 6.000M times in 1.589774s 1.509463s - vm2_poly_method 0.571 0.607 i/s - 1.000 times in 3.947570s 3.733528s - vm2_poly_method_ov 5.514 5.168 i/s - 1.000 times in 0.408156s 0.436169s - vm3_clearmethodcache 2.875 2.837 i/s - 1.000 times in 0.783018s 0.793493s - - Comparison: - vm2_defined_method - ours: 2822555.4 i/s - vanilla: 2644878.1 i/s - 1.07x slower - - vm2_method - ours: 8872947.8 i/s - vanilla: 8553433.1 i/s - 1.04x slower - - vm2_method_missing - ours: 3858192.3 i/s - vanilla: 3772296.3 i/s - 1.02x slower - - vm2_method_with_block - ours: 8943825.1 i/s - vanilla: 8493955.0 i/s - 1.05x slower - - vm2_poly_method - ours: 0.6 i/s - vanilla: 0.6 i/s - 1.06x slower - - vm2_poly_method_ov - vanilla: 5.5 i/s - ours: 5.2 i/s - 1.07x slower - - vm3_clearmethodcache - vanilla: 2.9 i/s - ours: 2.8 i/s - 1.01x slower - - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66565 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 686881d383cfe44c67875aada64207c5e0abaa8d - Author: shyouhei - Date: 2018-12-26 09:58:26 +0900 - - add _sp_inc_helpers.erb [ci skip] - - Just add more room for comments. This is a pure refactoring that does - not change anything but readability. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66564 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 756b200ad6623fdad76c30f19aaf25fb75a24f08 - Author: kazu - Date: 2018-12-26 01:11:18 +0900 - - [DOC] Remove heading with no content [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 1859c79190bd7f926d26b1f919e038c182080f2e - Author: svn - Date: 2018-12-26 01:09:40 +0900 - - * properties. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66560 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit d16509f1f009e06a1a9ff3bf9ab3f28aef415e87 - Author: kazu - Date: 2018-12-26 01:09:39 +0900 - - [DOC] Add doc/NEWS-2.6.0 [ci skip] - - fix previous commit miss - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66559 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 848a53d2b538d74730928737ec65325725f617f5 - Author: svn - Date: 2018-12-26 00:58:51 +0900 - - * 2018-12-26 - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66558 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit c14b9f9b638bc966923ae6fffa629ed171aea827 - Author: kazu - Date: 2018-12-26 00:58:49 +0900 - - [DOC] Move from NEWS to doc/NEWS-2.6.0 [ci skip] - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66557 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit b5569b9ab2ad5e0e4a997df7eb73e97ecbacc9dd - Author: k0kubun - Date: 2018-12-25 22:57:28 +0900 - - erb.rb: print deprecation warning with warn level 1 - - This was planned to be removed in Ruby 2.7 at first, but I changed my - mind to just keep warning it in Ruby 2.7. - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66556 b2dd03c8-39d4-4d8f-98ff-823fe69b080e - -commit 3a0471faa0d383392ba05b3a6409b973b7b009d1 - Author: matz - Date: 2018-12-25 22:45:17 +0900 - - version.h (RUBY_VERSION): 2.7.0 development has started. - - - git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e diff --git a/ruby/LEGAL b/ruby/LEGAL index 565c4c9cd..9645728ef 100644 --- a/ruby/LEGAL +++ b/ruby/LEGAL @@ -7,92 +7,118 @@ All the files in this distribution are covered under either the Ruby's license (see the file COPYING) or public-domain except some files mentioned below. -ccan/build_assert/build_assert.h:: -ccan/check_type/check_type.h:: -ccan/container_of/container_of.h:: -ccan/str/str.h:: +[addr2line.c] - These files are licensed under the CC0. + A part of this file is from FreeBSD. >>> - https://creativecommons.org/choose/zero/ + Copyright (c) 1986, 1988, 1991, 1993:: + The Regents of the University of California. All rights reserved. -ccan/list/list.h:: + (c) UNIX System Laboratories, Inc. - This file is licensed under the MIT License. + All or some portions of this file are derived from material licensed + to the University of California by American Telephone and Telegraph + Co. or Unix System Laboratories, Inc. and are reproduced herein with + the permission of UNIX System Laboratories, Inc. - >>> - 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: + 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. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -include/ruby/onigmo.h:: -include/ruby/oniguruma.h:: -regcomp.c:: -regenc.c:: -regenc.h:: -regerror.c:: -regexec.c:: -regint.h:: -regparse.c:: -regparse.h:: -enc/ascii.c:: -enc/big5.c:: -enc/cp949.c:: -enc/emacs_mule.c:: -enc/encdb.c:: -enc/euc_jp.c:: -enc/euc_kr.c:: -enc/euc_tw.c:: -enc/gb18030.c:: -enc/gb2312.c:: -enc/gbk.c:: -enc/iso_8859_1.c:: -enc/iso_8859_10.c:: -enc/iso_8859_11.c:: -enc/iso_8859_13.c:: -enc/iso_8859_14.c:: -enc/iso_8859_15.c:: -enc/iso_8859_16.c:: -enc/iso_8859_2.c:: -enc/iso_8859_3.c:: -enc/iso_8859_4.c:: -enc/iso_8859_5.c:: -enc/iso_8859_6.c:: -enc/iso_8859_7.c:: -enc/iso_8859_8.c:: -enc/iso_8859_9.c:: -enc/koi8_r.c:: -enc/koi8_u.c:: -enc/shift_jis.c:: -enc/unicode.c:: -enc/us_ascii.c:: -enc/utf_16be.c:: -enc/utf_16le.c:: -enc/utf_32be.c:: -enc/utf_32le.c:: -enc/utf_8.c:: -enc/windows_1251.c:: + @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + + +[ccan/build_assert/build_assert.h] +[ccan/check_type/check_type.h] +[ccan/container_of/container_of.h] +[ccan/str/str.h] + + These files are licensed under the {CC0}[https://creativecommons.org/choose/zero/]. + +[ccan/list/list.h] + + This file is licensed under the {MIT License}[rdoc-label:label-MIT+License]. + +[coroutine] + + Unless otherwise specified, these files are licensed under the + {MIT License}[rdoc-label:label-MIT+License]. + +[include/ruby/onigmo.h] +[include/ruby/oniguruma.h] +[regcomp.c] +[regenc.c] +[regenc.h] +[regerror.c] +[regexec.c] +[regint.h] +[regparse.c] +[regparse.h] +[enc/ascii.c] +[enc/big5.c] +[enc/cp949.c] +[enc/emacs_mule.c] +[enc/encdb.c] +[enc/euc_jp.c] +[enc/euc_kr.c] +[enc/euc_tw.c] +[enc/gb18030.c] +[enc/gb2312.c] +[enc/gbk.c] +[enc/iso_8859_1.c] +[enc/iso_8859_10.c] +[enc/iso_8859_11.c] +[enc/iso_8859_13.c] +[enc/iso_8859_14.c] +[enc/iso_8859_15.c] +[enc/iso_8859_16.c] +[enc/iso_8859_2.c] +[enc/iso_8859_3.c] +[enc/iso_8859_4.c] +[enc/iso_8859_5.c] +[enc/iso_8859_6.c] +[enc/iso_8859_7.c] +[enc/iso_8859_8.c] +[enc/iso_8859_9.c] +[enc/koi8_r.c] +[enc/koi8_u.c] +[enc/shift_jis.c] +[enc/unicode.c] +[enc/us_ascii.c] +[enc/utf_16be.c] +[enc/utf_16le.c] +[enc/utf_32be.c] +[enc/utf_32le.c] +[enc/utf_8.c] +[enc/windows_1251.c] +[enc/windows_31j.c] Onigmo (Oniguruma-mod) LICENSE >>> - Copyright (c) 2002-2009 K.Kosako - Copyright (c) 2011-2014 K.Takata + Copyright (c) 2002-2009:: K.Kosako + Copyright (c) 2011-2014:: K.Takata All rights reserved. Redistribution and use in source and binary forms, with or without @@ -119,7 +145,7 @@ enc/windows_1251.c:: Oniguruma LICENSE >>> - Copyright (c) 2002-2009 K.Kosako + Copyright (c) 2002-2009:: K.Kosako All rights reserved. Redistribution and use in source and binary forms, with or without @@ -150,10 +176,69 @@ enc/windows_1251.c:: When this software is partly used or it is distributed with Ruby, this of Ruby follows the license of Ruby. -enc/trans/GB/GB12345%UCS.src:: -enc/trans/GB/UCS%GB12345.src:: -enc/trans/GB/GB2312%UCS.src:: -enc/trans/GB/UCS%GB2312.src:: +[enc/windows_1250.c] +[enc/windows_1252.c] + + >>> + Copyright (c) 2006-2007:: Byte + K.Kosako + 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. + +[enc/cesu_8.c] +[enc/windows_1253.c] +[enc/windows_1254.c] +[enc/windows_1257.c] + + >>> + Copyright (c) 2002-2007:: K.Kosako + 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. + +[enc/trans/GB/GB12345%UCS.src] +[enc/trans/GB/UCS%GB12345.src] +[enc/trans/GB/GB2312%UCS.src] +[enc/trans/GB/UCS%GB2312.src] These files have this explanatory texts. @@ -165,12 +250,12 @@ enc/trans/GB/UCS%GB2312.src:: files for any particular purpose, and has ceased to publish the files many years ago. -enc/trans/JIS/JISX0201-KANA%UCS.src:: -enc/trans/JIS/JISX0208\@1990%UCS.src:: -enc/trans/JIS/JISX0212%UCS.src:: -enc/trans/JIS/UCS%JISX0201-KANA.src:: -enc/trans/JIS/UCS%JISX0208@1990.src:: -enc/trans/JIS/UCS%JISX0212.src:: +[enc/trans/JIS/JISX0201-KANA%UCS.src] +[enc/trans/JIS/JISX0208\@1990%UCS.src] +[enc/trans/JIS/JISX0212%UCS.src] +[enc/trans/JIS/UCS%JISX0201-KANA.src] +[enc/trans/JIS/UCS%JISX0208@1990.src] +[enc/trans/JIS/UCS%JISX0212.src] These files are copyrighted as the following. @@ -179,49 +264,64 @@ enc/trans/JIS/UCS%JISX0212.src:: For terms of use, see http://www.unicode.org/terms_of_use.html -enc/trans/JIS/JISX0213-1%UCS@BMP.src:: -enc/trans/JIS/JISX0213-1%UCS@SIP.src:: -enc/trans/JIS/JISX0213-2%UCS@BMP.src:: -enc/trans/JIS/JISX0213-2%UCS@SIP.src:: +[enc/trans/JIS/JISX0213-1%UCS@BMP.src] +[enc/trans/JIS/JISX0213-1%UCS@SIP.src] +[enc/trans/JIS/JISX0213-2%UCS@BMP.src] +[enc/trans/JIS/JISX0213-2%UCS@SIP.src] These files are copyrighted as the following. >>> - Copyright (C) 2001 earthian@tama.or.jp, All Rights Reserved. - Copyright (C) 2001 I'O, All Rights Reserved. - Copyright (C) 2006 Project X0213, All Rights Reserved. + Copyright (C) 2001:: earthian@tama.or.jp, All Rights Reserved. + Copyright (C) 2001:: I'O, All Rights Reserved. + Copyright (C) 2006:: Project X0213, All Rights Reserved. You can use, modify, distribute this table freely. -enc/trans/JIS/UCS@BMP%JISX0213-1.src:: -enc/trans/JIS/UCS@BMP%JISX0213-2.src:: -enc/trans/JIS/UCS@SIP%JISX0213-1.src:: -enc/trans/JIS/UCS@SIP%JISX0213-2.src:: +[enc/trans/JIS/UCS@BMP%JISX0213-1.src] +[enc/trans/JIS/UCS@BMP%JISX0213-2.src] +[enc/trans/JIS/UCS@SIP%JISX0213-1.src] +[enc/trans/JIS/UCS@SIP%JISX0213-2.src] These files are copyrighted as the following. >>> - Copyright (C) 2001 earthian@tama.or.jp, All Rights Reserved. - Copyright (C) 2001 I'O, All Rights Reserved. + Copyright (C) 2001:: earthian@tama.or.jp, All Rights Reserved. + Copyright (C) 2001:: I'O, All Rights Reserved. You can use, modify, distribute this table freely. -configure:: +[enc/trans/ucm/glibc-BIG5-2.3.3.ucm] +[enc/trans/ucm/glibc-BIG5HKSCS-2.3.3.ucm] + + >>> + Copyright (C) 2001-2005:: International Business Machines + Corporation and others. All Rights Reserved. + +[enc/trans/ucm/windows-950-2000.ucm] +[enc/trans/ucm/windows-950_hkscs-2001.ucm] + + >>> + Copyright (C) 2001-2002:: International Business Machines + Corporation and others. All Rights Reserved. + + +[configure] This file is free software. >>> - Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-2012:: Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. -tool/config.guess:: -tool/config.sub:: +[tool/config.guess] +[tool/config.sub] As long as you distribute these files with the file configure, they are covered under the Ruby's license. >>> - Copyright 1992-2018 Free Software Foundation, Inc. + Copyright 1992-2018:: Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -243,14 +343,43 @@ tool/config.sub:: program. This Exception is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). -parse.c:: +[tool/lib/test/*] +[tool/lib/core_assertions.rb] + + Some of methods on these files are based on MiniTest 4. MiniTest 4 is + distributed under the MIT License. + + >>> + Copyright (c) Ryan Davis, seattle.rb + + 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: - This file is licensed under the GPL, but is incorporated into Ruby and + 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. + +[parse.c] +[parse.h] + + These files are licensed under the GPL, but are incorporated into Ruby and redistributed under the terms of the Ruby license, as permitted by the exception to the GPL below. >>> - Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018:: Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -278,12 +407,12 @@ parse.c:: This special exception was added by the Free Software Foundation in version 2.2 of Bison. -missing/dtoa.c:: +[missing/dtoa.c] This file is under these licenses. >>> - Copyright (c) 1991, 2000, 2001 by Lucent Technologies. + 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 @@ -297,8 +426,8 @@ missing/dtoa.c:: OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. >>> - Copyright (c) 2004-2008 David Schultz - All rights reserved. + 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 @@ -321,32 +450,34 @@ missing/dtoa.c:: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -win32/win32.{c,h}:: +[win32/win32.c] +[include/ruby/win32.h] You can apply the Artistic License to these files. (or GPL, alternatively) >>> - Copyright (c) 1993, Intergraph Corporation + Copyright (c) 1993:: Intergraph Corporation You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the perl README file. -missing/mt19937.c:: +[missing/mt19937.c] This file is under the new-style BSD license. >>> - A C-program for MT19937, with initialization improved 2002/2/10. - Coded by Takuji Nishimura and Makoto Matsumoto. + A C-program for MT19937, with initialization improved 2002/2/10.:: + Coded by Takuji Nishimura and Makoto Matsumoto. + This is a faster version by taking Shawn Cokus's optimization, Matthe Bellew's simplification, Isaku Wada's real version. Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. + Copyright (C) 1997 - 2002:: Makoto Matsumoto and Takuji Nishimura, + All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -382,13 +513,13 @@ missing/mt19937.c:: The Wayback Machine url: http://web.archive.org/web/19990429082237/http://www.math.keio.ac.jp/matumoto/emt.html -missing/procstat_vm.c:: +[missing/procstat_vm.c] This file is under the new-style BSD license. >>> - Copyright (c) 2007 Robert N. M. Watson - All rights reserved. + Copyright (c) 2007:: Robert N. M. Watson + All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -413,151 +544,65 @@ missing/procstat_vm.c:: $FreeBSD: head/usr.bin/procstat/procstat_vm.c 261780 2014-02-11 21:57:37Z jhb $ -vsnprintf.c:: +[vsnprintf.c] - This file is under the old-style BSD license. Note that the - paragraph 3 below is now null and void. + This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. >>> - Copyright (c) 1990, 1993 + Copyright (c) 1990, 1993:: The Regents of the University of California. All rights reserved. This code is derived from software contributed to Berkeley by Chris Torek. - 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. - 3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - - IMPORTANT NOTE: - -------------- - From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change - paragraph 3 above is now null and void. - -st.c:: -strftime.c:: -include/ruby/st.h:: -missing/acosh.c:: -missing/alloca.c:: -missing/dup2.c:: -missing/erf.c:: -missing/finite.c:: -missing/hypot.c:: -missing/isinf.c:: -missing/isnan.c:: -missing/lgamma_r.c:: -missing/memcmp.c:: -missing/memmove.c:: -missing/strchr.c:: -missing/strerror.c:: -missing/strstr.c:: -missing/tgamma.c:: -ext/date/date_strftime.c:: -ext/digest/sha1/sha1.c:: -ext/digest/sha1/sha1.h:: -ext/sdbm/_sdbm.c:: -ext/sdbm/sdbm.h:: +[st.c] +[strftime.c] +[include/ruby/st.h] +[missing/acosh.c] +[missing/alloca.c] +[missing/erf.c] +[missing/hypot.c] +[missing/lgamma_r.c] +[missing/memcmp.c] +[missing/memmove.c] +[missing/strchr.c] +[missing/strerror.c] +[missing/strstr.c] +[missing/tgamma.c] +[ext/date/date_strftime.c] +[ext/digest/sha1/sha1.c] +[ext/digest/sha1/sha1.h] These files are all under public domain. -missing/crypt.c:: +[missing/crypt.c] - This file is under the old-style BSD license. Note that the - paragraph 3 below is now null and void. + This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. >>> - Copyright (c) 1989, 1993 + Copyright (c) 1989, 1993:: The Regents of the University of California. All rights reserved. This code is derived from software contributed to Berkeley by Tom Truscott. - 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. - 3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. +[missing/setproctitle.c] - THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - -missing/setproctitle.c:: - - This file is under the old-style BSD license. Note that the - paragraph 3 below is now null and void. + This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. >>> - Copyright 2003 Damien Miller - Copyright (c) 1983, 1995-1997 Eric P. Allman - Copyright (c) 1988, 1993 + Copyright 2003:: Damien Miller + Copyright (c) 1983, 1995-1997:: Eric P. Allman + Copyright (c) 1988, 1993:: The Regents of the University of California. 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. - 3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - -missing/strlcat.c:: -missing/strlcpy.c:: +[missing/strlcat.c] +[missing/strlcpy.c] These files are under an ISC-style license. >>> - Copyright (c) 1998, 2015 Todd C. Miller + Copyright (c) 1998, 2015:: Todd C. Miller Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -571,26 +616,26 @@ missing/strlcpy.c:: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -missing/langinfo.c:: +[missing/langinfo.c] This file is from http://www.cl.cam.ac.uk/~mgk25/ucs/langinfo.c. Ruby uses a modified version. The file contains the following author/copyright notice: >>> - Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11 + Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11:: Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted. The author disclaims all warranties with regard to this software. -ext/digest/md5/md5.c:: -ext/digest/md5/md5.h:: +[ext/digest/md5/md5.c] +[ext/digest/md5/md5.h] These files are under the following license. Ruby uses modified versions of them. >>> - Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. + Copyright (C) 1999, 2000:: Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -611,8 +656,8 @@ ext/digest/md5/md5.h:: L. Peter Deutsch ghost@aladdin.com -ext/digest/rmd160/rmd160.c:: -ext/digest/rmd160/rmd160.h:: +[ext/digest/rmd160/rmd160.c] +[ext/digest/rmd160/rmd160.h] These files have the following copyright information, and by the author we are allowed to use it under the new-style BSD license. @@ -622,16 +667,16 @@ ext/digest/rmd160/rmd160.h:: (Arranged for libc by Todd C. Miller) DATE:: 1 March 1996 - Copyright (c) Katholieke Universiteit Leuven + Copyright (c):: Katholieke Universiteit Leuven 1996, All Rights Reserved -ext/digest/sha2/sha2.c:: -ext/digest/sha2/sha2.h:: +[ext/digest/sha2/sha2.c] +[ext/digest/sha2/sha2.h] These files are under the new-style BSD license. >>> - Copyright 2000 Aaron D. Gifford. All rights reserved. + Copyright 2000:: Aaron D. Gifford. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -657,12 +702,12 @@ ext/digest/sha2/sha2.h:: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -ext/json/generator/generator.c:: +[ext/json/generator/generator.c] The file contains the following copyright notice. >>> - Copyright 2001-2004 Unicode, Inc. + Copyright 2001-2004:: Unicode, Inc. Disclaimer:: @@ -682,15 +727,15 @@ ext/json/generator/generator.c:: 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:: +[ext/nkf/nkf-utf8/config.h] +[ext/nkf/nkf-utf8/nkf.c] +[ext/nkf/nkf-utf8/utf8tbl.c] These files are under the following license. So to speak, it is copyrighted semi-public-domain software. >>> - Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA) + Copyright (C) 1987:: Fujitsu LTD. (Itaru ICHIKAWA) Everyone is permitted to do anything on this program including copying, modifying, improving, @@ -700,14 +745,14 @@ ext/nkf/nkf-utf8/utf8tbl.c:: You don't have to ask before copying, redistribution or publishing. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. -ext/psych:: -test/psych:: +[ext/psych] +[test/psych] The files under these directories are under the following license, except for ext/psych/yaml. >>> - Copyright 2009 Aaron Patterson, et al. + Copyright 2009:: Aaron Patterson, et al. 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 @@ -727,12 +772,12 @@ test/psych:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -ext/psych/yaml:: +[ext/psych/yaml] The files under this directory are under the following license. >>> - Copyright (c) 2006 Kirill Simonov + Copyright (c) 2006:: Kirill Simonov 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 @@ -752,14 +797,28 @@ ext/psych/yaml:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -ext/socket/addrinfo.h:: -ext/socket/getaddrinfo.c:: -ext/socket/getnameinfo.c:: +[ext/pty/pty.c] + + >>> + C) Copyright 1998:: by Akinori Ito. + + This software may be redistributed freely for this purpose, in full + or in part, provided that this entire copyright notice is included + on any copies of this software and applications and derivations thereof. + + This software is provided on an "as is" basis, without warranty of any + kind, either expressed or implied, as to any matter including, but not + limited to warranty of fitness of purpose, or merchantability, or + results obtained from use of this software. + +[ext/socket/addrinfo.h] +[ext/socket/getaddrinfo.c] +[ext/socket/getnameinfo.c] These files are under the new-style BSD license. >>> - Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + Copyright (C) 1995, 1996, 1997, 1998, and 1999:: WIDE Project. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -786,16 +845,16 @@ ext/socket/getnameinfo.c:: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -ext/win32ole/win32ole.c:: +[ext/win32ole/win32ole.c] You can apply the Artistic License to this file. (or GPL, alternatively) >>> - (c) 1995 Microsoft Corporation. All rights reserved. + (c) 1995:: Microsoft Corporation. All rights reserved. Developed by ActiveWare Internet Corp., http://www.ActiveWare.com - Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy + Other modifications Copyright (c) 1997, 1998:: by Gurusamy Sarathy and Jan Dubois You may distribute under the terms of either the GNU General Public @@ -804,20 +863,17 @@ ext/win32ole/win32ole.c:: The Wayback Machine url: http://web.archive.org/web/19970607104352/http://www.activeware.com:80/ -lib/rdoc/generator/template/darkfish/css/fonts.css:: +[lib/rdoc/generator/template/darkfish/css/fonts.css] - This file is licensed under the SIL Open Font License. + This file is licensed under the {SIL Open Font License}[http://scripts.sil.org/OFL]. - >>> - http://scripts.sil.org/OFL - -spec/mspec:: -spec/ruby:: +[spec/mspec] +[spec/ruby] The files under these directories are under the following license. >>> - Copyright (c) 2008 Engine Yard, Inc. All rights reserved. + Copyright (c) 2008:: Engine Yard, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -840,17 +896,17 @@ spec/ruby:: FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -lib/rubygems.rb:: -lib/rubygems:: -test/rubygems:: +[lib/rubygems.rb] +[lib/rubygems] +[test/rubygems] RubyGems is under the following license. >>> 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 (see the file MIT.txt), or the - conditions below: + either the terms of the {MIT license}[rdoc-label:label-MIT+License], or the conditions + below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the @@ -901,20 +957,109 @@ test/rubygems:: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -lib/bundler:: -lib/bundler.rb:: -lib/bundler.gemspec:: -spec/bundler:: -man/bundle-*,gemfile.*:: +[lib/bundler] +[lib/bundler.rb] +[spec/bundler] Bundler is under the following license. >>> - Portions copyright (c) 2010 Andre Arko - Portions copyright (c) 2009 Engine Yard + Portions copyright (c) 2010:: Andre Arko + Portions copyright (c) 2009:: Engine Yard + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/bundler/vendor/thor] + + Thor is under the following license. + + >>> + Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al. + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/rubygems/resolver/molinillo] +[lib/bundler/vendor/molinillo] + + molinillo is under the following license. + + >>> + Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/bundler/vendor/connection_pool] + + connection_pool is under the following license. + + >>> + Copyright (c) 2011 Mike Perham + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/bundler/vendor/net-http-persistent] - MIT License:: + net-http-persistent is under the following license. + >>> + Copyright (c) Eric Hodel, Aaron Patterson + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/did_you_mean] +[lib/did_you_mean.rb] +[test/did_you_mean] + + did_you_mean is under the following license. + + >>> + Copyright (c) 2014-2016 Yuki Nishijima + + {MIT License}[rdoc-label:label-MIT+License] + +[lib/error_highlight] +[lib/error_highlight.rb] +[test/error_highlight] + + error_highlight is under the following license. + + >>> + Copyright (c) 2021 Yusuke Endoh + + {MIT License}[rdoc-label:label-MIT+License] + +[benchmark/so_ackermann.rb] +[benchmark/so_array.rb] +[benchmark/so_binary_trees.rb] +[benchmark/so_concatenate.rb] +[benchmark/so_count_words.yml] +[benchmark/so_exception.rb] +[benchmark/so_fannkuch.rb] +[benchmark/so_fasta.rb] +[benchmark/so_k_nucleotide.yml] +[benchmark/so_lists.rb] +[benchmark/so_mandelbrot.rb] +[benchmark/so_matrix.rb] +[benchmark/so_meteor_contest.rb] +[benchmark/so_nbody.rb] +[benchmark/so_nested_loop.rb] +[benchmark/so_nsieve.rb] +[benchmark/so_nsieve_bits.rb] +[benchmark/so_object.rb] +[benchmark/so_partial_sums.rb] +[benchmark/so_pidigits.rb] +[benchmark/so_random.rb] +[benchmark/so_reverse_complement.yml] +[benchmark/so_sieve.rb] +[benchmark/so_spectralnorm.rb] + + These files are very old copy of then-called "The Great Computer Language + Shootout". LEGAL SITUATION OF THESE FILES ARE UNCLEAR because the original + site has been lost. Upstream diverged to delete several benchmarks listed + above. + +== MIT License +>>> 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 @@ -933,3 +1078,34 @@ man/bundle-*,gemfile.*:: 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. + +== Old-style BSD license +>>> + 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. + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + + IMPORTANT NOTE:: + + From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change + paragraph 3 above is now null and void. diff --git a/ruby/NEWS b/ruby/NEWS deleted file mode 100644 index e1adb5115..000000000 --- a/ruby/NEWS +++ /dev/null @@ -1,826 +0,0 @@ -# -*- rdoc -*- - -= NEWS for Ruby 2.7.0 - -This document is a list of user visible feature changes made between -releases except for bug fixes. - -Note that each entry is kept so brief that no reason behind or reference -information is supplied with. For a full list of changes with all -sufficient information, see the ChangeLog file or Redmine -(e.g. https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER). - -== Changes since the 2.6.0 release - -=== Language changes - -==== Pattern matching - -* Pattern matching is introduced as an experimental feature. [Feature #14912] - - case [0, [1, 2, 3]] - in [a, [b, *c]] - p a #=> 0 - p b #=> 1 - p c #=> [2, 3] - end - - case {a: 0, b: 1} - in {a: 0, x: 1} - :unreachable - in {a: 0, b: var} - p var #=> 1 - end - - case -1 - in 0 then :unreachable - in 1 then :unreachable - end #=> NoMatchingPatternError - - json = < "Bob" - p age #=> 2 - - JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]} - #=> NoMatchingPatternError - -* See the following slides for more details: - * https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7 - * Note that the slides are slightly obsolete. - -* The warning against pattern matching can be suppressed with - {-W:no-experimental option}[#label-Warning+option]. - -==== The spec of keyword arguments is changed towards 3.0 - -* Automatic conversion of keyword arguments and positional arguments is - deprecated, and conversion will be removed in Ruby 3. [Feature #14183] - - * When a method call passes a Hash at the last argument, and when it - passes no keywords, and when the called method accepts keywords, - a warning is emitted. To continue treating the hash as keywords, - add a double splat operator to avoid the warning and ensure - correct behavior in Ruby 3. - - def foo(key: 42); end; foo({key: 42}) # warned - def foo(**kw); end; foo({key: 42}) # warned - def foo(key: 42); end; foo(**{key: 42}) # OK - def foo(**kw); end; foo(**{key: 42}) # OK - - * When a method call passes keywords to a method that accepts keywords, - but it does not pass enough required positional arguments, the - keywords are treated as a final required positional argument, and a - warning is emitted. Pass the argument as a hash instead of keywords - to avoid the warning and ensure correct behavior in Ruby 3. - - def foo(h, **kw); end; foo(key: 42) # warned - def foo(h, key: 42); end; foo(key: 42) # warned - def foo(h, **kw); end; foo({key: 42}) # OK - def foo(h, key: 42); end; foo({key: 42}) # OK - - * When a method accepts specific keywords but not a keyword splat, and - a hash or keywords splat is passed to the method that includes both - Symbol and non-Symbol keys, the hash will continue to be split, and - a warning will be emitted. You will need to update the calling code - to pass separate hashes to ensure correct behavior in Ruby 3. - - def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned - def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned - def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK - - * If a method does not accept keywords, and is called with keywords, - the keywords are still treated as a positional hash, with no warning. - This behavior will continue to work in Ruby 3. - - def foo(opt={}); end; foo( key: 42 ) # OK - -* Non-symbols are allowed as keyword argument keys if the method accepts - arbitrary keywords. [Feature #14183] - - * Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0, - but are now allowed again. [Bug #15658] - - def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1} - -* **nil is allowed in method definitions to explicitly mark - that the method accepts no keywords. Calling such a method with keywords - will result in an ArgumentError. [Feature #14183] - - def foo(h, **nil); end; foo(key: 1) # ArgumentError - def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError - def foo(h, **nil); end; foo("str" => 1) # ArgumentError - def foo(h, **nil); end; foo({key: 1}) # OK - def foo(h, **nil); end; foo({"str" => 1}) # OK - -* Passing an empty keyword splat to a method that does not accept keywords - no longer passes an empty hash, unless the empty hash is necessary for - a required parameter, in which case a warning will be emitted. Remove - the double splat to continue passing a positional hash. [Feature #14183] - - h = {}; def foo(*a) a end; foo(**h) # [] - h = {}; def foo(a) a end; foo(**h) # {} and warning - h = {}; def foo(*a) a end; foo(h) # [{}] - h = {}; def foo(a) a end; foo(h) # {} - -* Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option]. - -==== Numbered parameters - -* Numbered parameters as default block parameters are introduced. - [Feature #4475] - - [1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"] - [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7] - - You can still define a local variable named +_1+ and so on, - and that is honored when present, but renders a warning. - - _1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name - [1].each { p _1 } # prints 0 instead of 1 - -==== proc/lambda without block is deprecated - -* Proc.new and Kernel#proc with no block in a method called with a block is - warned now. - - def foo - proc - end - foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead - - This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. - -* Kernel#lambda with no block in a method called with a block raises an exception. - - def bar - lambda - end - bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError) - -==== Other miscellaneous changes - -* A beginless range is experimentally introduced. It might be useful - in +case+, new call-sequence of the Comparable#clamp, - constants and DSLs. [Feature #14799] - - ary[..3] # identical to ary[0..3] - - case RUBY_VERSION - when ..."2.4" then puts "EOL" - # ... - end - - age.clamp(..100) - - where(sales: ..100) - -* Setting $; to a non-nil value is warned now. [Feature #14240] - Use of it in String#split is warned too. - This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. - -* Setting $, to a non-nil value is warned now. [Feature #14240] - Use of it in Array#join is warned too. - This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. - -* Quoted here-document identifiers must end within the same line. - - <<"EOS - " # This had been warned since 2.4; Now it raises a SyntaxError - EOS - -* The flip-flop syntax deprecation is reverted. [Feature #5400] - -* Comment lines can be placed between fluent dot now. - - foo - # .bar - .baz # => foo.baz - -* Calling a private method with a literal +self+ as the receiver - is now allowed. [Feature #11297] [Feature #16123] - -* Modifier rescue now operates the same for multiple assignment as single - assignment. [Bug #8279] - - a, b = raise rescue [1, 2] - # Previously parsed as: (a, b = raise) rescue [1, 2] - # Now parsed as: a, b = (raise rescue [1, 2]) - -* +yield+ in singleton class syntax is warned and will be deprecated later. [Feature #15575]. - - def foo - class << Object.new - yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575] - end - end - foo { p :ok } - - This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. - -* Argument forwarding by (...) is introduced. [Feature #16253] - - def foo(...) - bar(...) - end - - All arguments to +foo+ are forwarded to +bar+, including keyword and - block arguments. - Note that the parentheses are mandatory. bar ... is parsed - as an endless range. - -* Access and setting of $SAFE is now always warned. $SAFE - will become a normal global variable in Ruby 3.0. [Feature #16131] - -* Object#{taint,untaint,trust,untrust} and related functions in the C-API - no longer have an effect (all objects are always considered untainted), and are now - warned in verbose mode. This warning will be disabled even in non-verbose mode in - Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. [Feature #16131] - -* Refinements take place at Object#method and Module#instance_method. [Feature #15373] - -=== Command line options - -==== Warning option - -The +-W+ option has been extended with a following +:+, to manage categorized -warnings. [Feature #16345] [Feature #16420] - -* To suppress deprecation warnings: - - $ ruby -e '$; = ""' - -e:1: warning: `$;' is deprecated - - $ ruby -W:no-deprecated -e '$; = //' - -* It works with the +RUBYOPT+ environment variable: - - $ RUBYOPT=-W:no-deprecated ruby -e '$; = //' - -* To suppress experimental feature warnings: - - $ ruby -e '0 in a' - -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby! - - $ ruby -W:no-experimental -e '0 in a' - -* To suppress both by using +RUBYOPT+, set space separated values: - - $ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a' - -See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29]. - -=== Core classes updates (outstanding ones only) - -Array:: - - New methods:: - - * Added Array#intersection. [Feature #16155] - - * Added Array#minmax, with a faster implementation than Enumerable#minmax. [Bug #15929] - -Comparable:: - - Modified method:: - - * Comparable#clamp now accepts a Range argument. [Feature #14784] - - -1.clamp(0..2) #=> 0 - 1.clamp(0..2) #=> 1 - 3.clamp(0..2) #=> 2 - # With beginless and endless ranges: - -1.clamp(0..) #=> 0 - 3.clamp(..2) #=> 2 - - -Complex:: - - New method:: - - * Added Complex#<=>. - So 0 <=> 0i will not raise NoMethodError. [Bug #15857] - -Dir:: - - Modified methods:: - - * Dir.glob and Dir.[] no longer allow NUL-separated glob pattern. - Use Array instead. [Feature #14643] - -Encoding:: - - New encoding:: - - * Added new encoding CESU-8. [Feature #15931] - -Enumerable:: - - New methods:: - - * Added Enumerable#filter_map. [Feature #15323] - - [1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"] - - * Added Enumerable#tally. [Feature #11076] - - ["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1} - -Enumerator:: - - New methods:: - - * Added Enumerator.produce to generate an Enumerator from any custom - data transformation. [Feature #14781] - - require "date" - dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates - dates.detect(&:tuesday?) #=> next Tuesday - - * Added Enumerator::Lazy#eager that generates a non-lazy enumerator - from a lazy enumerator. [Feature #15901] - - a = %w(foo bar baz) - e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager - p e.class #=> Enumerator - p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"] - - * Added Enumerator::Yielder#to_proc so that a Yielder object - can be directly passed to another method as a block - argument. [Feature #15618] - -Fiber:: - - New method:: - - * Added Fiber#raise that behaves like Fiber#resume but raises an - exception on the resumed fiber. [Feature #10344] - -File:: - - Modified method:: - - * File.extname now returns a dot string for names ending with a dot on - non-Windows platforms. [Bug #15267] - - File.extname("foo.") #=> "." - -FrozenError:: - - New method:: - - * Added FrozenError#receiver to return the frozen object on which - modification was attempted. To set this object when raising - FrozenError in Ruby code, FrozenError.new accepts a +:receiver+ - option. [Feature #15751] - -GC:: - - New method:: - - * Added GC.compact method for compacting the heap. - This function compacts live objects in the heap so that fewer pages may - be used, and the heap may be more CoW (copy-on-write) friendly. [Feature #15626] - - Details on the algorithm and caveats can be found here: - https://bugs.ruby-lang.org/issues/15626 - -IO:: - - New method:: - - * Added IO#set_encoding_by_bom to check the BOM and set the external - encoding. [Bug #15210] - -Integer:: - - Modified method:: - - * Integer#[] now supports range operations. [Feature #8842] - - 0b01001101[2, 4] #=> 0b0011 - 0b01001100[2..5] #=> 0b0011 - 0b01001100[2...6] #=> 0b0011 - # ^^^^ - -Method:: - - Modified method:: - - * Method#inspect shows more information. [Feature #14145] - -Module:: - - New methods:: - - * Added Module#const_source_location to retrieve the location where a - constant is defined. [Feature #10771] - - * Added Module#ruby2_keywords for marking a method as passing keyword - arguments through a regular argument splat, useful when delegating - all arguments to another method in a way that can be backwards - compatible with older Ruby versions. [Bug #16154] - - Modified methods:: - - * Module#autoload? now takes an +inherit+ optional argument, like - Module#const_defined?. [Feature #15777] - - * Module#name now always returns a frozen String. The returned String is - always the same for a given Module. This change is - experimental. [Feature #16150] - -NilClass / TrueClass / FalseClass:: - - Modified methods:: - - * NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a - frozen String. The returned String is always the same for each of these - values. This change is experimental. [Feature #16150] - -ObjectSpace::WeakMap:: - - Modified method:: - - * ObjectSpace::WeakMap#[]= now accepts special objects as either key or - values. [Feature #16035] - -Proc:: - - New method:: - - * Added Proc#ruby2_keywords for marking the proc as passing keyword - arguments through a regular argument splat, useful when delegating - all arguments to another method or proc in a way that can be backwards - compatible with older Ruby versions. [Feature #16404] - -Range:: - - New method:: - - * Added Range#minmax, with a faster implementation than Enumerable#minmax. - It returns a maximum that now corresponds to Range#max. [Bug #15807] - - Modified method:: - - * Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was - changed from Range#include? for all types except strings). [Bug #15449] - - -RubyVM:: - - Removed method:: - - * +RubyVM.resolve_feature_path+ moved to - $LOAD_PATH.resolve_feature_path. [Feature #15903] [Feature #15230] - -String:: - - Unicode:: - - * Update Unicode version and Emoji version from 11.0.0 to - 12.0.0. [Feature #15321] - - * Update Unicode version to 12.1.0, adding support for - U+32FF SQUARE ERA NAME REIWA. [Feature #15195] - - * Update Unicode Emoji version to 12.1. [Feature #16272] - -Symbol:: - - New methods:: - - * Added Symbol#start_with? and Symbol#end_with? methods. [Feature #16348] - -Time:: - - New methods:: - - * Added Time#ceil method. [Feature #15772] - - * Added Time#floor method. [Feature #15653] - - Modified method:: - - * Time#inspect is separated from Time#to_s and it shows - the time's sub second. [Feature #15958] - -UnboundMethod:: - - New method:: - - * Added UnboundMethod#bind_call method. [Feature #15955] - - umethod.bind_call(obj, ...) is semantically equivalent - to umethod.bind(obj).call(...). This idiom is used in - some libraries to call a method that is overridden. The added - method does the same without allocation of an intermediate Method - object. - - class Foo - def add_1(x) - x + 1 - end - end - class Bar < Foo - def add_1(x) # override - x + 2 - end - end - - obj = Bar.new - p obj.add_1(1) #=> 3 - p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2 - p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2 - -Warning:: - - New methods:: - - * Added Warning.[] and Warning.[]= to manage emitting/suppressing - some categories of warnings. [Feature #16345] [Feature #16420] - -$LOAD_PATH:: - - New method:: - - * Added $LOAD_PATH.resolve_feature_path. [Feature #15903] [Feature #15230] - -=== Stdlib updates (outstanding ones only) - -Bundler:: - - * Upgrade to Bundler 2.1.2. - See https://github.com/bundler/bundler/releases/tag/v2.1.2 - -CGI:: - - * CGI.escapeHTML becomes 2~5x faster when there is at least one escaped character. - See https://github.com/ruby/ruby/pull/2226 - -CSV:: - - * Upgrade to 3.1.2. - See https://github.com/ruby/csv/blob/master/NEWS.md. - -Date:: - - * Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese - era. [Feature #15742] - -Delegator:: - - * Object#DelegateClass accepts a block and module_evals it in the context - of the returned class, similar to Class.new and Struct.new. - -ERB:: - - * Prohibit marshaling ERB instance. - -IRB:: - - * Introduce syntax highlighting inspired by the Pry gem to Binding#irb - source lines, REPL input, and inspect output of some core-class objects. - - * Introduce multiline editing mode provided by Reline. - - * Show documentation when completion. - - * Enable auto indent and save/load history by default. - -JSON:: - - * Upgrade to 2.3.0. - -Net::FTP:: - - * Add Net::FTP#features to check available features, and Net::FTP#option to - enable/disable each of them. [Feature #15964] - -Net::HTTP:: - - * Add +ipaddr+ optional parameter to Net::HTTP#start to replace the address for - the TCP/IP connection. [Feature #5180] - -Net::IMAP:: - - * Add Server Name Indication (SNI) support. [Feature #15594] - -open-uri:: - - * Warn open-uri's "open" method at Kernel. - Use URI.open instead. [Misc #15893] - - * The default charset of "text/*" media type is UTF-8 instead of - ISO-8859-1. [Bug #15933] - -OptionParser:: - - * Now show "Did you mean?" for unknown options. [Feature #16256] - - test.rb: - - require "optparse" - OptionParser.new do |opts| - opts.on("-f", "--foo", "foo") {|v| } - opts.on("-b", "--bar", "bar") {|v| } - opts.on("-c", "--baz", "baz") {|v| } - end.parse! - - example: - - $ ruby test.rb --baa - Traceback (most recent call last): - test.rb:7:in `
': invalid option: --baa (OptionParser::InvalidOption) - Did you mean? baz - bar - -Pathname:: - - * Pathname.glob now delegates 3 arguments to Dir.glob - to accept +base+ keyword. [Feature #14405] - -Racc:: - - * Merge 1.4.15 from upstream repository and added cli of racc. - -Reline:: - - * New stdlib that is compatible with the readline stdlib but is - implemented in pure Ruby. It also provides a multiline editing mode. - -REXML:: - - * Upgrade to 3.2.3. - See https://github.com/ruby/rexml/blob/master/NEWS.md. - -RSS:: - - * Upgrade to RSS 0.2.8. - See https://github.com/ruby/rss/blob/master/NEWS.md. - -RubyGems:: - - * Upgrade to RubyGems 3.1.2. - * https://github.com/rubygems/rubygems/releases/tag/v3.1.0 - * https://github.com/rubygems/rubygems/releases/tag/v3.1.1 - * https://github.com/rubygems/rubygems/releases/tag/v3.1.2 - -StringScanner:: - - * Upgrade to 1.0.3. - See https://github.com/ruby/strscan/blob/master/NEWS.md. - -=== Compatibility issues (excluding feature bug fixes) - -* The following libraries are no longer bundled gems. - Install corresponding gems to use these features. - * CMath (cmath gem) - * Scanf (scanf gem) - * Shell (shell gem) - * Synchronizer (sync gem) - * ThreadsWait (thwait gem) - * E2MM (e2mmap gem) - -Proc:: - * The Proc#to_s format was changed. [Feature #16101] - -Range:: - * Range#minmax used to iterate on the range to determine the maximum. - It now uses the same algorithm as Range#max. In rare cases (e.g. - ranges of Floats or Strings), this may yield different results. [Bug #15807] - -=== Stdlib compatibility issues (excluding feature bug fixes) - -* Promote stdlib to default gems - * The following default gems were published on rubygems.org - * benchmark - * cgi - * delegate - * getoptlong - * net-pop - * net-smtp - * open3 - * pstore - * readline - * readline-ext - * singleton - * The following default gems were only promoted at ruby-core, - but not yet published on rubygems.org. - * monitor - * observer - * timeout - * tracer - * uri - * yaml -* The did_you_mean gem has been promoted up to a default gem from a bundled gem - -pathname:: - - * Kernel#Pathname when called with a Pathname argument now returns - the argument instead of creating a new Pathname. This is more - similar to other Kernel methods, but can break code that modifies - the return value and expects the argument not to be modified. - -profile.rb, Profiler__:: - - * Removed from standard library. It was unmaintained since Ruby 2.0.0. - -=== C API updates - -* Many *_kw functions have been added for setting whether - the final argument being passed should be treated as keywords. You - may need to switch to these functions to avoid keyword argument - separation warnings, and to ensure correct behavior in Ruby 3. - -* The : character in rb_scan_args format string is now - treated as keyword arguments. Passing a positional hash instead of - keyword arguments will emit a deprecation warning. - -* C API declarations with +ANYARGS+ are changed not to use +ANYARGS+. - See https://github.com/ruby/ruby/pull/2404 - -=== Implementation improvements - -Fiber:: - - * Allow selecting different coroutine implementations by using - +--with-coroutine=+, e.g. - - $ ./configure --with-coroutine=ucontext - $ ./configure --with-coroutine=copy - - * Replace previous stack cache with fiber pool cache. The fiber pool - allocates many stacks in a single memory region. Stack allocation - becomes O(log N) and fiber creation is amortized O(1). Around 10x - performance improvement was measured in micro-benchmarks. - https://github.com/ruby/ruby/pull/2224 - -File:: - * File.realpath now uses realpath(3) on many platforms, which can - significantly improve performance. [Feature #15797] - -Hash:: - * Change data structure of small Hash objects. [Feature #15602] - -Monitor:: - * Monitor class is written in C-extension. [Feature #16255] - -Thread:: - - * VM stack memory allocation is now combined with native thread stack, - improving thread allocation performance and reducing allocation related - failures. Around 10x performance improvement was measured in micro-benchmarks. - -JIT:: - - * JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated. - - * Method inlining is performed when a method is considered as pure. - This optimization is still experimental and many methods are NOT considered as pure yet. - - * The default value of +--jit-max-cache+ is changed from 1,000 to 100. - - * The default value of +--jit-min-calls+ is changed from 5 to 10,000. - -RubyVM:: - - * Per-call-site method cache, which has been there since around 1.9, was - improved: cache hit rate raised from 89% to 94%. - See https://github.com/ruby/ruby/pull/2583 - -RubyVM::InstructionSequence:: - - * RubyVM::InstructionSequence#to_binary method generates compiled binary. - The binary size is reduced. [Feature #16163] - -=== Miscellaneous changes - -* Support for IA64 architecture has been removed. Hardware for testing was - difficult to find, native fiber code is difficult to implement, and it added - non-trivial complexity to the interpreter. [Feature #15894] - -* Require compilers to support C99. [Misc #15347] - - * Details of our dialect: https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/C99 - -* Ruby's upstream repository is changed from Subversion to Git. - - * https://git.ruby-lang.org/ruby.git - - * RUBY_REVISION class is changed from Integer to String. - - * RUBY_DESCRIPTION includes Git revision instead of Subversion's one. - -* Support built-in methods in Ruby with the _\_builtin_ syntax. [Feature #16254] - - Some methods are defined in *.rb (such as trace_point.rb). - For example, it is easy to define a method which accepts keyword arguments. diff --git a/ruby/NEWS.md b/ruby/NEWS.md new file mode 100644 index 000000000..cfe11295a --- /dev/null +++ b/ruby/NEWS.md @@ -0,0 +1,657 @@ +# NEWS for Ruby 3.1.0 + +This document is a list of user-visible feature changes +since the **3.0.0** release, except for bug fixes. + +Note that each entry is kept to a minimum, see links for details. + +## Language changes + +* The block argument can now be anonymous if the block will + only be passed to another method. [[Feature #11256]] + + ```ruby + def foo(&) + bar(&) + end + ``` + +* Pin operator now takes an expression. [[Feature #17411]] + + ```ruby + Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a + #=> [[3, 5], [5, 7], [11, 13]] + ``` + +* Pin operator now supports instance, class, and global variables. + [[Feature #17724]] + + ```ruby + @n = 5 + Prime.each_cons(2).lazy.find{_1 in [n, ^@n]} + #=> [3, 5] + ``` + +* One-line pattern matching is no longer experimental. + +* Parentheses can be omitted in one-line pattern matching. + [[Feature #16182]] + + ```ruby + [0, 1] => _, x + {y: 2} => y: + x #=> 1 + y #=> 2 + ``` + +* Multiple assignment evaluation order has been made consistent with + single assignment evaluation order. With single assignment, Ruby + uses a left-to-right evaluation order. With this code: + + ```ruby + foo[0] = bar + ``` + + The following evaluation order is used: + + 1. `foo` + 2. `bar` + 3. `[]=` called on the result of `foo` + + In Ruby before 3.1.0, multiple assignment did not follow this + evaluation order. With this code: + + ```ruby + foo[0], bar.baz = a, b + ``` + + Versions of Ruby before 3.1.0 would evaluate in the following + order + + 1. `a` + 2. `b` + 3. `foo` + 4. `[]=` called on the result of `foo` + 5. `bar` + 6. `baz=` called on the result of `bar` + + Starting in Ruby 3.1.0, the evaluation order is now consistent with + single assignment, with the left-hand side being evaluated before + the right-hand side: + + 1. `foo` + 2. `bar` + 3. `a` + 4. `b` + 5. `[]=` called on the result of `foo` + 6. `baz=` called on the result of `bar` + + [[Bug #4443]] + +* Values in Hash literals and keyword arguments can be omitted. + [[Feature #14579]] + + For example, + + * `{x:, y:}` is a syntax sugar of `{x: x, y: y}`. + * `foo(x:, y:)` is a syntax sugar of `foo(x: x, y: y)`. + + Constant names, local variable names, and method names are allowed as + key names. Note that a reserved word is considered as a local + variable or method name even if it's a pseudo variable name such as + `self`. + +* Non main-Ractors can get instance variables (ivars) of classes/modules + if ivars refer to shareable objects. + [[Feature #17592]] + +* A command syntax is allowed in endless method definitions, i.e., + you can now write `def foo = puts "Hello"`. + Note that `private def foo = puts "Hello"` does not parse. + [[Feature #17398]] + +## Command line options + +* `--disable-gems` is now explicitly declared as "just for debugging". + Never use it in any real-world codebase. + [[Feature #17684]] + +## Core classes updates + +Note: We're only listing outstanding class updates. + +* Array + + * Array#intersect? is added. [[Feature #15198]] + +* Class + + * Class#subclasses, which returns an array of classes + directly inheriting from the receiver, not + including singleton classes. + [[Feature #18273]] + + ```ruby + class A; end + class B < A; end + class C < B; end + class D < A; end + A.subclasses #=> [D, B] + B.subclasses #=> [C] + C.subclasses #=> [] + ``` + +* Enumerable + + * Enumerable#compact is added. [[Feature #17312]] + + * Enumerable#tally now accepts an optional hash to count. [[Feature #17744]] + + * Enumerable#each_cons and each_slice to return a receiver. [[GH-1509]] + + ```ruby + [1, 2, 3].each_cons(2){} + # 3.0 => nil + # 3.1 => [1, 2, 3] + + [1, 2, 3].each_slice(2){} + # 3.0 => nil + # 3.1 => [1, 2, 3] + ``` + +* Enumerator::Lazy + + * Enumerator::Lazy#compact is added. [[Feature #17312]] + +* File + + * File.dirname now accepts an optional argument for the level to + strip path components. [[Feature #12194]] + +* GC + + * "GC.measure_total_time = true" enables the measurement of GC. + Measurement can introduce overhead. It is enabled by default. + GC.measure_total_time returns the current setting. + GC.stat[:time] or GC.stat(:time) returns measured time + in milli-seconds. [[[Feature #10917]]] + + * GC.total_time returns measured time in nano-seconds. [[[Feature #10917]]] + +* Integer + + * Integer.try_convert is added. [[Feature #15211]] + +* Kernel + + + * Kernel#load now accepts a module as the second argument, + and will load the file using the given module as the + top-level module. [[Feature #6210]] + +* Marshal + + * Marshal.load now accepts a `freeze: true` option. + All returned objects are frozen except for `Class` and + `Module` instances. Strings are deduplicated. [[Feature #18148]] + +* MatchData + + * MatchData#match is added [[Feature #18172]] + + * MatchData#match_length is added [[Feature #18172]] + +* Method / UnboundMethod + + * Method#public?, Method#private?, Method#protected?, + UnboundMethod#public?, UnboundMethod#private?, + UnboundMethod#protected? have been added. [[Feature #11689]] + +* Module + + * Module#prepend now modifies the ancestor chain if the receiver + already includes the argument. Module#prepend still does not + modify the ancestor chain if the receiver has already prepended + the argument. [[Bug #17423]] + + * Module#private, #public, #protected, and #module_function will + now return their arguments. If a single argument is given, it + is returned. If no arguments are given, nil is returned. If + multiple arguments are given, they are returned as an array. + [[Feature #12495]] + +* Process + + * Process.\_fork is added. This is a core method for fork(2). + Do not call this method directly; it is called by existing + fork methods: Kernel.#fork, Process.fork, and IO.popen("-"). + Application monitoring libraries can overwrite this method to + hook fork events. [[Feature #17795]] + +* Struct + + * Passing only keyword arguments to Struct#initialize is warned. + You need to use a Hash literal to set a Hash to a first member. + [[Feature #16806]] + + * StructClass#keyword_init? is added [[Feature #18008]] + +* String + + * Update Unicode version to 13.0.0 [[Feature #17750]] + and Emoji version to 13.0 [[Feature #18029]] + + * String#unpack and String#unpack1 now accept an `offset:` keyword + argument to start the unpacking after an arbitrary number of bytes + have been skipped. If `offset` is outside of the string bounds + `ArgumentError` is raised. [[Feature #18254]] + +* Thread + + * Thread#native_thread_id is added. [[Feature #17853]] + +* Thread::Backtrace + + * Thread::Backtrace.limit, which returns the value to limit backtrace + length set by `--backtrace-limit` command line option, is added. + [[Feature #17479]] + +* Thread::Queue + + * Thread::Queue.new now accepts an Enumerable of initial values. + [[Feature #17327]] + +* Time + + * Time.new now accepts optional `in:` keyword argument for the + timezone, as well as `Time.at` and `Time.now`, so that is now + you can omit minor arguments to `Time.new`. [[Feature #17485]] + + ```ruby + Time.new(2021, 12, 25, in: "+07:00") + #=> 2021-12-25 00:00:00 +0700 + ``` + + At the same time, time component strings are converted to + integers more strictly now. + + ```ruby + Time.new(2021, 12, 25, "+07:30") + #=> invalid value for Integer(): "+07:30" (ArgumentError) + ``` + + Ruby 3.0 or earlier returned probably unexpected result + `2021-12-25 07:00:00`, not `2021-12-25 07:30:00` nor + `2021-12-25 00:00:00 +07:30`. + + * Time#strftime supports RFC 3339 UTC for unknown offset local + time, `-0000`, as `%-z`. [[Feature #17544]] + +* TracePoint + + * TracePoint.allow_reentry is added to allow reenter while TracePoint + callback. + [[Feature #15912]] + +* $LOAD_PATH + + * $LOAD_PATH.resolve_feature_path does not raise. [[Feature #16043]] + +* Fiber Scheduler + + * Add support for `Addrinfo.getaddrinfo` using `address_resolve` hook. + [[Feature #17370]] + + * Introduce non-blocking `Timeout.timeout` using `timeout_after` hook. + [[Feature #17470]] + + * Introduce new scheduler hooks `io_read` and `io_write` along with a + low level `IO::Buffer` for zero-copy read/write. [[Feature #18020]] + + * IO hooks `io_wait`, `io_read`, `io_write`, receive the original IO object + where possible. [[Bug #18003]] + + * Make `Monitor` fiber-safe. [[Bug #17827]] + + * Replace copy coroutine with pthread implementation. [[Feature #18015]] + +* Refinement + + * New class which represents a module created by Module#refine. + `include` and `prepend` are deprecated, and `import_methods` is added + instead. [[Bug #17429]] + +## Stdlib updates + +* The following default gem are updated. + * RubyGems 3.3.3 + * base64 0.1.1 + * benchmark 0.2.0 + * bigdecimal 3.1.1 + * bundler 2.3.3 + * cgi 0.3.1 + * csv 3.2.2 + * date 3.2.2 + * did_you_mean 1.6.1 + * digest 3.1.0 + * drb 2.1.0 + * erb 2.2.3 + * error_highlight 0.3.0 + * etc 1.3.0 + * fcntl 1.0.1 + * fiddle 1.1.0 + * fileutils 1.6.0 + * find 0.1.1 + * io-console 0.5.10 + * io-wait 0.2.1 + * ipaddr 1.2.3 + * irb 1.4.1 + * json 2.6.1 + * logger 1.5.0 + * net-http 0.2.0 + * net-protocol 0.1.2 + * nkf 0.1.1 + * open-uri 0.2.0 + * openssl 3.0.0 + * optparse 0.2.0 + * ostruct 0.5.2 + * pathname 0.2.0 + * pp 0.3.0 + * prettyprint 0.1.1 + * psych 4.0.3 + * racc 1.6.0 + * rdoc 6.4.0 + * readline 0.0.3 + * readline-ext 0.1.4 + * reline 0.3.0 + * resolv 0.2.1 + * rinda 0.1.1 + * ruby2_keywords 0.0.5 + * securerandom 0.1.1 + * set 1.0.2 + * stringio 3.0.1 + * strscan 3.0.1 + * tempfile 0.1.2 + * time 0.2.0 + * timeout 0.2.0 + * tmpdir 0.1.2 + * un 0.2.0 + * uri 0.11.0 + * yaml 0.2.0 + * zlib 2.1.1 +* The following bundled gems are updated. + * minitest 5.15.0 + * power_assert 2.0.1 + * rake 13.0.6 + * test-unit 3.5.3 + * rexml 3.2.5 + * rbs 2.1.0 + * typeprof 0.21.2 +* The following default gems are now bundled gems. + * net-ftp 0.1.3 + * net-imap 0.2.3 + * net-pop 0.1.1 + * net-smtp 0.3.1 + * matrix 0.4.2 + * prime 0.1.2 + * debug 1.4.0 + +* Coverage measurement now supports suspension. You can use `Coverage.suspend` + to stop the measurement temporarily, and `Coverage.resume` to restart it. + See [[Feature #18176]] in detail. + +* Random::Formatter is moved to random/formatter.rb, so that you can + use `Random#hex`, `Random#base64`, and so on without SecureRandom. + [[Feature #18190]] + +## Compatibility issues + +Note: Excluding feature bug fixes. + +* `rb_io_wait_readable`, `rb_io_wait_writable` and `rb_wait_for_single_fd` are + deprecated in favour of `rb_io_maybe_wait_readable`, + `rb_io_maybe_wait_writable` and `rb_io_maybe_wait` respectively. + `rb_thread_wait_fd` and `rb_thread_fd_writable` are deprecated. [[Bug #18003]] + +## Stdlib compatibility issues + +* `ERB#initialize` warns `safe_level` and later arguments even without -w. + [[Feature #14256]] + +* `lib/debug.rb` is replaced with `debug.gem` + +* `Kernel#pp` in `lib/pp.rb` uses the width of `IO#winsize` by default. + This means that the output width is automatically changed depending on + your terminal size. [[Feature #12913]] + +* Psych 4.0 changes `Psych.load` as `safe_load` by the default. + You may need to use Psych 3.3.2 for migrating to this behavior. + [[Bug #17866]] + +## C API updates + +* Documented. [[GH-4815]] + +* `rb_gc_force_recycle` is deprecated and has been changed to a no-op. + [[Feature #18290]] + +## Implementation improvements + +* Inline cache mechanism is introduced for reading class variables. + [[Feature #17763]] + +* `instance_eval` and `instance_exec` now only allocate a singleton class when + required, avoiding extra objects and improving performance. [[GH-5146]] + +* The performance of `Struct` accessors is improved. [[GH-5131]] + +* `mandatory_only?` builtin special form to improve performance on + builtin methods. [[GH-5112]] + +* Experimental feature Variable Width Allocation in the garbage collector. + This feature is turned off by default and can be enabled by compiling Ruby + with flag `USE_RVARGC=1` set. [[Feature #18045]] [[Feature #18239]] + +## JIT + +* Rename Ruby 3.0's `--jit` to `--mjit`, and alias `--jit` to `--yjit` + on non-Windows x86-64 platforms and to `--mjit` on others. + +### MJIT + +* The default `--mjit-max-cache` is changed from 100 to 10000. + +* JIT-ed code is no longer cancelled when a TracePoint for class events + is enabled. + +* The JIT compiler no longer skips compilation of methods longer than + 1000 instructions. + +* `--mjit-verbose` and `--mjit-warning` output "JIT cancel" when JIT-ed + code is disabled because TracePoint or GC.compact is used. + +### YJIT: New experimental in-process JIT compiler + +New JIT compiler available as an experimental feature. [[Feature #18229]] + +See [this blog post](https://shopify.engineering/yjit-just-in-time-compiler-cruby +) introducing the project. + +* Disabled by default, use `--yjit` command-line option to enable YJIT. + +* Performance improvements on benchmarks based on real-world software, + up to 22% on railsbench, 39% on liquid-render. + +* Fast warm-up times. + +* Limited to Unix-like x86-64 platforms for now. + +## Static analysis + +### RBS + +* Generics type parameters can be bounded ([PR](https://github.com/ruby/rbs/pull/844)). + + ```rbs + # `T` must be compatible with the `_Output` interface. + # `PrettyPrint[String]` is ok, but `PrettyPrint[Integer]` is a type error. + class PrettyPrint[T < _Output] + interface _Output + def <<: (String) -> void + end + + attr_reader output: T + + def initialize: (T output) -> void + end + ``` + +* Type aliases can be generic. ([PR](https://github.com/ruby/rbs/pull/823)) + + ```rbs + # Defines a generic type `list`. + type list[T] = [ T, list[T] ] + | nil + + type str_list = list[String] + type int_list = list[Integer] + ``` + +* [rbs collection](https://github.com/ruby/rbs/blob/master/docs/collection.md) has been introduced to manage gems’ RBSs. + +* Many signatures for built-in and standard libraries have been added/updated. + +* It includes many bug fixes and performance improvements too. + +See the [CHANGELOG.md](https://github.com/ruby/rbs/blob/master/CHANGELOG.md) for more information. + +### TypeProf + +* [Experimental IDE support](https://github.com/ruby/typeprof/blob/master/doc/ide.md) has been implemented. +* Many bug fixes and performance improvements since Ruby 3.0.0. + +## Debugger + +* A new debugger [debug.gem](https://github.com/ruby/debug) is bundled. + debug.gem is a fast debugger implementation, and it provides many features + like remote debugging, colorful REPL, IDE (VSCode) integration, and more. + It replaces `lib/debug.rb` standard library. + +* `rdbg` command is also installed into `bin/` directory to start and control + debugging execution. + +## error_highlight + +A built-in gem called error_highlight has been introduced. +It shows fine-grained error locations in the backtrace. + +Example: `title = json[:article][:title]` + +If `json` is nil, it shows: + +``` +$ ruby test.rb +test.rb:2:in `
': undefined method `[]' for nil:NilClass (NoMethodError) + +title = json[:article][:title] + ^^^^^^^^^^ +``` + +If `json[:article]` returns nil, it shows: + +``` +$ ruby test.rb +test.rb:2:in `
': undefined method `[]' for nil:NilClass (NoMethodError) + +title = json[:article][:title] + ^^^^^^^^ +``` + +This feature is enabled by default. +You can disable it by using a command-line option `--disable-error_highlight`. +See [the repository](https://github.com/ruby/error_highlight) in detail. + +## IRB Autocomplete and Document Display + +The IRB now has an autocomplete feature, where you can just type in the code, and the completion candidates dialog will appear. You can use Tab and Shift+Tab to move up and down. + +If documents are installed when you select a completion candidate, the documentation dialog will appear next to the completion candidates dialog, showing part of the content. You can read the full document by pressing Alt+d. + +## Miscellaneous changes + +* lib/objspace/trace.rb is added, which is a tool for tracing the object + allocation. Just by requiring this file, tracing is started *immediately*. + Just by `Kernel#p`, you can investigate where an object was created. + Note that just requiring this file brings a large performance overhead. + This is only for debugging purposes. Do not use this in production. + [[Feature #17762]] + +* Now exceptions raised in finalizers will be printed to `STDERR`, unless + `$VERBOSE` is `nil`. [[Feature #17798]] + +* `ruby -run -e httpd` displays URLs to access. [[Feature #17847]] + +* Add `ruby -run -e colorize` to colorize Ruby code using + `IRB::Color.colorize_code`. + +[Bug #4443]: https://bugs.ruby-lang.org/issues/4443 +[Feature #6210]: https://bugs.ruby-lang.org/issues/6210 +[Feature #10917]: https://bugs.ruby-lang.org/issues/10917 +[Feature #11256]: https://bugs.ruby-lang.org/issues/11256 +[Feature #11689]: https://bugs.ruby-lang.org/issues/11689 +[Feature #12194]: https://bugs.ruby-lang.org/issues/12194 +[Feature #12495]: https://bugs.ruby-lang.org/issues/12495 +[Feature #12913]: https://bugs.ruby-lang.org/issues/12913 +[Feature #14256]: https://bugs.ruby-lang.org/issues/14256 +[Feature #14579]: https://bugs.ruby-lang.org/issues/14579 +[Feature #15198]: https://bugs.ruby-lang.org/issues/15198 +[Feature #15211]: https://bugs.ruby-lang.org/issues/15211 +[Feature #15912]: https://bugs.ruby-lang.org/issues/15912 +[Feature #16043]: https://bugs.ruby-lang.org/issues/16043 +[Feature #16182]: https://bugs.ruby-lang.org/issues/16182 +[Feature #16806]: https://bugs.ruby-lang.org/issues/16806 +[Feature #17312]: https://bugs.ruby-lang.org/issues/17312 +[Feature #17327]: https://bugs.ruby-lang.org/issues/17327 +[Feature #17370]: https://bugs.ruby-lang.org/issues/17370 +[Feature #17398]: https://bugs.ruby-lang.org/issues/17398 +[Feature #17411]: https://bugs.ruby-lang.org/issues/17411 +[Bug #17423]: https://bugs.ruby-lang.org/issues/17423 +[Bug #17429]: https://bugs.ruby-lang.org/issues/17429 +[Feature #17470]: https://bugs.ruby-lang.org/issues/17470 +[Feature #17479]: https://bugs.ruby-lang.org/issues/17479 +[Feature #17485]: https://bugs.ruby-lang.org/issues/17485 +[Feature #17544]: https://bugs.ruby-lang.org/issues/17544 +[Feature #17592]: https://bugs.ruby-lang.org/issues/17592 +[Feature #17684]: https://bugs.ruby-lang.org/issues/17684 +[Feature #17724]: https://bugs.ruby-lang.org/issues/17724 +[Feature #17744]: https://bugs.ruby-lang.org/issues/17744 +[Feature #17750]: https://bugs.ruby-lang.org/issues/17750 +[Feature #17762]: https://bugs.ruby-lang.org/issues/17762 +[Feature #17763]: https://bugs.ruby-lang.org/issues/17763 +[Feature #17795]: https://bugs.ruby-lang.org/issues/17795 +[Feature #17798]: https://bugs.ruby-lang.org/issues/17798 +[Bug #17827]: https://bugs.ruby-lang.org/issues/17827 +[Feature #17847]: https://bugs.ruby-lang.org/issues/17847 +[Feature #17853]: https://bugs.ruby-lang.org/issues/17853 +[Bug #17866]: https://bugs.ruby-lang.org/issues/17866 +[Bug #18003]: https://bugs.ruby-lang.org/issues/18003 +[Feature #18008]: https://bugs.ruby-lang.org/issues/18008 +[Feature #18015]: https://bugs.ruby-lang.org/issues/18015 +[Feature #18020]: https://bugs.ruby-lang.org/issues/18020 +[Feature #18029]: https://bugs.ruby-lang.org/issues/18029 +[Feature #18045]: https://bugs.ruby-lang.org/issues/18045 +[Feature #18148]: https://bugs.ruby-lang.org/issues/18148 +[Feature #18172]: https://bugs.ruby-lang.org/issues/18172 +[Feature #18176]: https://bugs.ruby-lang.org/issues/18176 +[Feature #18190]: https://bugs.ruby-lang.org/issues/18190 +[Feature #18229]: https://bugs.ruby-lang.org/issues/18229 +[Feature #18239]: https://bugs.ruby-lang.org/issues/18239 +[Feature #18254]: https://bugs.ruby-lang.org/issues/18254 +[Feature #18273]: https://bugs.ruby-lang.org/issues/18273 +[Feature #18290]: https://bugs.ruby-lang.org/issues/18290 + +[GH-1509]: https://github.com/ruby/ruby/pull/1509 +[GH-4815]: https://github.com/ruby/ruby/pull/4815 +[GH-5112]: https://github.com/ruby/ruby/pull/5112 +[GH-5131]: https://github.com/ruby/ruby/pull/5131 +[GH-5146]: https://github.com/ruby/ruby/pull/5146 diff --git a/ruby/README.ja.md b/ruby/README.ja.md index 4e1e6b9d8..bb69c0905 100644 --- a/ruby/README.ja.md +++ b/ruby/README.ja.md @@ -1,10 +1,10 @@ -[![Build Status](https://travis-ci.org/ruby/ruby.svg?branch=master)](https://travis-ci.org/ruby/ruby) -[![Build status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master) -![](https://github.com/ruby/ruby/workflows/Cygwin/badge.svg) -![](https://github.com/ruby/ruby/workflows/macOS/badge.svg) -![](https://github.com/ruby/ruby/workflows/MJIT/badge.svg) -![](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg) -![](https://github.com/ruby/ruby/workflows/Windows/badge.svg) +[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW") +[![Actions Status: MJIT](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT") +[![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ã¨ã¯ @@ -52,11 +52,11 @@ Rubyリãƒã‚¸ãƒˆãƒªã®æœ¬æ¥ã®master㯠https://git.ruby-lang.org/ruby.git ã« ### Subversion -å¤ã„Rubyã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã§å–å¾—ã§ãã¾ã™ï¼Ž +å¤ã„Rubyã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã§ã‚‚å–å¾—ã§ãã¾ã™ï¼Ž $ svn co https://svn.ruby-lang.org/repos/ruby/branches/ruby_2_6/ ruby -ä»–ã«é–‹ç™ºä¸­ã®ãƒ–ランãƒã®ä¸€è¦§ã¯æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã§è¦‹ã‚‰ã‚Œã¾ã™ï¼Ž +ä»–ã®ãƒ–ランãƒã®ä¸€è¦§ã¯æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã§è¦‹ã‚‰ã‚Œã¾ã™ï¼Ž $ svn ls https://svn.ruby-lang.org/repos/ruby/branches/ @@ -71,38 +71,33 @@ https://www.ruby-lang.org/ ## メーリングリスト -Rubyã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ï¼Žå‚åŠ å¸Œæœ›ã®æ–¹ã¯ - -mailto:ruby-list-request@ruby-lang.org - -ã¾ã§æœ¬æ–‡ã« +Rubyã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ï¼Žå‚åŠ å¸Œæœ›ã®æ–¹ã¯ [ruby-list-request@ruby-lang.org] ã¾ã§æœ¬æ–‡ã« subscribe ã¨æ›¸ã„ã¦é€ã£ã¦ä¸‹ã•ã„. -Ruby開発者å‘ã‘メーリングリストもã‚りã¾ã™ï¼Žã“ã¡ã‚‰ã§ã¯rubyã®ãƒã‚°ï¼Œå°†æ¥ã®ä»•様拡張ãªã©å®Ÿè£…上ã®å•題ã«ã¤ã„ã¦è­°è«–ã•れã¦ã„ã¾ã™ï¼Ž å‚åŠ å¸Œæœ›ã®æ–¹ã¯ - -mailto:ruby-dev-request@ruby-lang.org - -ã¾ã§ruby-listã¨åŒæ§˜ã®æ–¹æ³•ã§ãƒ¡ãƒ¼ãƒ«ã—ã¦ãã ã•ã„. +Ruby開発者å‘ã‘メーリングリストもã‚りã¾ã™ï¼Žã“ã¡ã‚‰ã§ã¯rubyã®ãƒã‚°ï¼Œå°†æ¥ã®ä»•様拡張ãªã©å®Ÿè£…上ã®å•題ã«ã¤ã„ã¦è­°è«–ã•れã¦ã„ã¾ã™ï¼Ž +å‚åŠ å¸Œæœ›ã®æ–¹ã¯ [ruby-dev-request@ruby-lang.org] ã¾ã§ruby-listã¨åŒæ§˜ã®æ–¹æ³•ã§ãƒ¡ãƒ¼ãƒ«ã—ã¦ãã ã•ã„. Ruby拡張モジュールã«ã¤ã„ã¦è©±ã—åˆã†ruby-extãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã¨æ•°å­¦é–¢ä¿‚ã®è©±é¡Œã«ã¤ã„ã¦è©±ã—åˆã†ruby-mathメーリングリスト㨠英語ã§rubyã«ã¤ã„ã¦è©±ã—åˆã†ruby-talkメーリングリストもã‚りã¾ã™ï¼Žå‚加方法ã¯ã©ã‚Œã‚‚åŒã˜ã§ã™ï¼Ž +[ruby-list-request@ruby-lang.org]: mailto:ruby-list-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe +[ruby-dev-request@ruby-lang.org]: mailto:ruby-dev-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe + ## コンパイル・インストール ä»¥ä¸‹ã®æ‰‹é †ã§è¡Œã£ã¦ãã ã•ã„. -1. ã‚‚ã— `configure` ファイルãŒè¦‹ã¤ã‹ã‚‰ãªã„,もã—ã㯠`configure.ac` よりå¤ã„よã†ãªã‚‰ï¼Œ `autoconf` を実行ã—㦠- æ–°ã—ã `configure` を生æˆã™ã‚‹ +1. (Gitリãƒã‚¸ãƒˆãƒªã‹ã‚‰å–å¾—ã—ãŸã‚½ãƒ¼ã‚¹ã‚’ビルドã™ã‚‹å ´åˆ) `./autogen.sh` を実行ã—ã¦æ–°ã—ã `configure` を生æˆã™ã‚‹ 2. `configure` を実行ã—㦠`Makefile` ãªã©ã‚’生æˆã™ã‚‹ 環境ã«ã‚ˆã£ã¦ã¯ãƒ‡ãƒ•ォルトã®Cコンパイラ用オプションãŒä»˜ãã¾ã™ï¼Ž `configure` オプション㧠`optflags=..` `warnflags=..` ç­‰ã§ä¸Šæ›¸ãã§ãã¾ã™ï¼Ž -3. (å¿…è¦ãªã‚‰ã°)`defines.h` を編集ã™ã‚‹ +3. (å¿…è¦ãªã‚‰ã°)`include/ruby/defines.h` を編集ã™ã‚‹ 多分,必è¦ç„¡ã„ã¨æ€ã„ã¾ã™ï¼Ž @@ -172,11 +167,14 @@ UNIXã§ã‚れ㰠`configure` ãŒã»ã¨ã‚“ã©ã®å·®ç•°ã‚’å¸åŽã—ã¦ãれる㯠## フィードãƒãƒƒã‚¯ -Rubyã«é–¢ã™ã‚‹è³ªå•㯠Ruby-Talk(英語)や Ruby-List(日本語) (https://www.ruby-lang.org/ja/community/mailing-lists) や, -stackoverflow (https://ja.stackoverflow.com/) ãªã©ã®Webã‚µã‚¤ãƒˆã«æŠ•ç¨¿ã—ã¦ãã ã•ã„. +Rubyã«é–¢ã™ã‚‹è³ªå•㯠[Ruby-Talk](英語)や [Ruby-List](日本語)や, +[stackoverflow] ãªã©ã®Webã‚µã‚¤ãƒˆã«æŠ•ç¨¿ã—ã¦ãã ã•ã„. ãƒã‚°å ±å‘Šã¯ https://bugs.ruby-lang.org ã§å—ã‘付ã‘ã¦ã„ã¾ã™ï¼Ž +[Ruby-Talk]: https://www.ruby-lang.org/en/community/mailing-lists +[Ruby-List]: https://www.ruby-lang.org/ja/community/mailing-lists +[stackoverflow]: https://ja.stackoverflow.com/ ## 著者 diff --git a/ruby/README.md b/ruby/README.md index 1e935095c..9b5a553ff 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -1,10 +1,10 @@ -[![Build Status](https://travis-ci.org/ruby/ruby.svg?branch=master)](https://travis-ci.org/ruby/ruby) -[![Build status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master) -![](https://github.com/ruby/ruby/workflows/Cygwin/badge.svg) -![](https://github.com/ruby/ruby/workflows/macOS/badge.svg) -![](https://github.com/ruby/ruby/workflows/MJIT/badge.svg) -![](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg) -![](https://github.com/ruby/ruby/workflows/Windows/badge.svg) +[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW") +[![Actions Status: MJIT](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT") +[![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's Ruby @@ -24,8 +24,8 @@ It is simple, straightforward, and extensible. * Garbage Collection * Dynamic Loading of Object Files (on some architectures) * Highly Portable (works on many Unix-like/POSIX compatible platforms as - well as Windows, macOS, Haiku, etc.) cf. - https://github.com/ruby/ruby/blob/master/doc/contributing.rdoc#platform-maintainers + well as Windows, macOS, etc.) cf. + https://github.com/ruby/ruby/blob/master/doc/maintainers.rdoc#label-Platform+Maintainers ## How to get Ruby @@ -51,7 +51,8 @@ if you are a committer. ### Subversion -Stable branches for older Ruby versions can be checked out with the following command: +Stable branches for older Ruby versions can be checked out with also the +following command: $ svn co https://svn.ruby-lang.org/repos/ruby/branches/ruby_2_6/ ruby @@ -71,16 +72,29 @@ send the following phrase: subscribe -in the mail body (not subject) to the address -[ruby-talk-request@ruby-lang.org](mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe). +in the mail body (not subject) to the address [ruby-talk-request@ruby-lang.org]. + +[ruby-talk-request@ruby-lang.org]: mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe + +## Requirements to build from repository + +1. GNU or BSD make +2. C99 compiler +3. autoconf 2.67 or higher +4. automake 1.15 or higher +5. bison 2.3 or higher +6. Ruby 2.2 or higher + +When building from a released version, only a C99 compiler and GNU or BSD make +is required. ## How to compile and install 1. If you want to use Microsoft Visual C++ to compile Ruby, read - [win32/README.win32](win32/README.win32) instead of this document. + [win32/README.win32](rdoc-ref:win32/README.win32) instead of this document. -2. If `./configure` does not exist or is older than `configure.ac`, run - `autoconf` to (re)generate configure. +2. Run `./autogen.sh` to generate configure, when you build the source checked + out from the Git repository. 3. Run `./configure`, which will generate `config.h` and `Makefile`. @@ -88,14 +102,15 @@ in the mail body (not subject) to the address environment. Specify `optflags=..` and `warnflags=..` as necessary to override them. -4. Edit `defines.h` if you need. Usually this step will not be needed. +4. Edit `include/ruby/defines.h` if you need. Usually this step will not be needed. -5. Remove comment mark(`#`) before the module names from `ext/Setup` (or add - module names if not present), if you want to link modules statically. +5. Optional: Remove comment mark(`#`) before the module names from `ext/Setup`. - If you don't want to compile non static extension modules (probably on - architectures which do not allow dynamic loading), remove comment mark - from the line "`#option nodynamic`" in `ext/Setup`. + This step is only necessary if you want to link modules statically. + + If you don't want to compile dynamic extensions (probably on architectures + which do not allow dynamic loading), remove comment mark from the line + "`#option nodynamic`" in `ext/Setup`. Usually this step will not be needed. @@ -108,12 +123,7 @@ in the mail body (not subject) to the address interpreter works well. If you see the message "`check succeeded`", your Ruby works as it should (hopefully). -8. Optionally, run `make update-gems` and `make extract-gems`. - - If you want to install bundled gems, run `make update-gems` and - `make extract-gems` before running `make install`. - -9. Run '`make install`'. +8. Run '`make install`'. This command will create the following directories and install files into them. @@ -153,21 +163,21 @@ to remove old configuration after installing them in such case. ## Copying -See the file [COPYING](COPYING). +See the file [COPYING](rdoc-ref:COPYING). ## Feedback -Questions about the Ruby language can be asked on the Ruby-Talk mailing list -(https://www.ruby-lang.org/en/community/mailing-lists) or on websites like -(https://stackoverflow.com). +Questions about the Ruby language can be asked on the [Ruby-Talk] mailing list +or on websites like https://stackoverflow.com. Bugs should be reported at https://bugs.ruby-lang.org. Read [HowToReport] for more information. +[Ruby-Talk]: https://www.ruby-lang.org/en/community/mailing-lists [HowToReport]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToReport ## Contributing -See the file [CONTRIBUTING.md](CONTRIBUTING.md) +See the file [CONTRIBUTING.md](rdoc-ref:CONTRIBUTING) ## The Author diff --git a/ruby/aclocal.m4 b/ruby/aclocal.m4 index ed7d14ef6..e69de29bb 100644 --- a/ruby/aclocal.m4 +++ b/ruby/aclocal.m4 @@ -1,47 +0,0 @@ -# generated automatically by aclocal 1.16.1 -*- Autoconf -*- - -# Copyright (C) 1996-2018 Free Software Foundation, Inc. - -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -m4_include([tool/m4/_colorize_result_prepare.m4]) -m4_include([tool/m4/ac_msg_result.m4]) -m4_include([tool/m4/colorize_result.m4]) -m4_include([tool/m4/ruby_append_option.m4]) -m4_include([tool/m4/ruby_append_options.m4]) -m4_include([tool/m4/ruby_check_builtin_func.m4]) -m4_include([tool/m4/ruby_check_builtin_setjmp.m4]) -m4_include([tool/m4/ruby_check_printf_prefix.m4]) -m4_include([tool/m4/ruby_check_setjmp.m4]) -m4_include([tool/m4/ruby_check_signedness.m4]) -m4_include([tool/m4/ruby_check_sizeof.m4]) -m4_include([tool/m4/ruby_check_sysconf.m4]) -m4_include([tool/m4/ruby_cppoutfile.m4]) -m4_include([tool/m4/ruby_decl_attribute.m4]) -m4_include([tool/m4/ruby_default_arch.m4]) -m4_include([tool/m4/ruby_define_if.m4]) -m4_include([tool/m4/ruby_defint.m4]) -m4_include([tool/m4/ruby_dtrace_available.m4]) -m4_include([tool/m4/ruby_dtrace_postprocess.m4]) -m4_include([tool/m4/ruby_func_attribute.m4]) -m4_include([tool/m4/ruby_mingw32.m4]) -m4_include([tool/m4/ruby_prepend_option.m4]) -m4_include([tool/m4/ruby_prog_gnu_ld.m4]) -m4_include([tool/m4/ruby_replace_funcs.m4]) -m4_include([tool/m4/ruby_replace_type.m4]) -m4_include([tool/m4/ruby_rm_recursive.m4]) -m4_include([tool/m4/ruby_setjmp_type.m4]) -m4_include([tool/m4/ruby_stack_grow_direction.m4]) -m4_include([tool/m4/ruby_try_cflags.m4]) -m4_include([tool/m4/ruby_try_ldflags.m4]) -m4_include([tool/m4/ruby_type_attribute.m4]) -m4_include([tool/m4/ruby_universal_arch.m4]) -m4_include([tool/m4/ruby_werror_flag.m4]) diff --git a/ruby/addr2line.c b/ruby/addr2line.c index 635194b96..f660be912 100644 --- a/ruby/addr2line.c +++ b/ruby/addr2line.c @@ -13,7 +13,7 @@ #pragma clang diagnostic ignored "-Wgcc-compat" #endif -#include "ruby/config.h" +#include "ruby/internal/config.h" #include "ruby/defines.h" #include "ruby/missing.h" #include "addr2line.h" @@ -25,11 +25,7 @@ #include #endif -#ifdef HAVE_STDBOOL_H -#include -#else -#include "missing/stdbool.h" -#endif +#include "ruby/internal/stdbool.h" #if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H) @@ -163,11 +159,12 @@ typedef struct obj_info { struct dwarf_section debug_info; struct dwarf_section debug_line; struct dwarf_section debug_ranges; + struct dwarf_section debug_rnglists; struct dwarf_section debug_str; struct obj_info *next; } obj_info_t; -#define DWARF_SECTION_COUNT 5 +#define DWARF_SECTION_COUNT 6 static struct dwarf_section * obj_dwarf_section_at(obj_info_t *obj, int n) @@ -177,6 +174,7 @@ obj_dwarf_section_at(obj_info_t *obj, int n) &obj->debug_info, &obj->debug_line, &obj->debug_ranges, + &obj->debug_rnglists, &obj->debug_str }; if (n < 0 || DWARF_SECTION_COUNT <= n) { @@ -194,12 +192,12 @@ struct debug_section_definition { static char binary_filename[PATH_MAX + 1]; static unsigned long -uleb128(char **p) +uleb128(const char **p) { unsigned long r = 0; int s = 0; for (;;) { - unsigned char b = *(unsigned char *)(*p)++; + unsigned char b = (unsigned char)*(*p)++; if (b < 0x80) { r += (unsigned long)b << s; break; @@ -211,12 +209,12 @@ uleb128(char **p) } static long -sleb128(char **p) +sleb128(const char **p) { long r = 0; int s = 0; for (;;) { - unsigned char b = *(unsigned char *)(*p)++; + unsigned char b = (unsigned char)*(*p)++; if (b < 0x80) { if (b & 0x40) { r -= (0x80 - b) << s; @@ -233,7 +231,7 @@ sleb128(char **p) } static const char * -get_nth_dirname(unsigned long dir, char *p) +get_nth_dirname(unsigned long dir, const char *p) { if (!dir--) { return ""; @@ -251,11 +249,11 @@ get_nth_dirname(unsigned long dir, char *p) } static void -fill_filename(int file, char *include_directories, char *filenames, line_info_t *line, obj_info_t *obj) +fill_filename(int file, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj) { int i; - char *p = filenames; - char *filename; + const char *p = filenames; + const char *filename; unsigned long dir; for (i = 1; i <= file; i++) { filename = p; @@ -282,7 +280,7 @@ fill_filename(int file, char *include_directories, char *filenames, line_info_t static void fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line, - char *include_directories, char *filenames, + const char *include_directories, const char *filenames, obj_info_t *obj, line_info_t *lines, int offset) { int i; @@ -376,7 +374,7 @@ parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header) } static int -parse_debug_line_cu(int num_traces, void **traces, char **debug_line, +parse_debug_line_cu(int num_traces, void **traces, const char **debug_line, obj_info_t *obj, line_info_t *lines, int offset) { const char *p = (const char *)*debug_line; @@ -401,8 +399,8 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, #define FILL_LINE() \ do { \ fill_line(num_traces, traces, addr, file, line, \ - (char *)header.include_directories, \ - (char *)header.filenames, \ + header.include_directories, \ + header.filenames, \ obj, lines, offset); \ /*basic_block = prologue_end = epilogue_begin = 0;*/ \ } while (0) @@ -415,19 +413,19 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, FILL_LINE(); break; case DW_LNS_advance_pc: - a = uleb128((char **)&p); + a = uleb128(&p) * header.minimum_instruction_length; addr += a; break; case DW_LNS_advance_line: { - long a = sleb128((char **)&p); + long a = sleb128(&p); line += a; break; } case DW_LNS_set_file: - file = (unsigned int)uleb128((char **)&p); + file = (unsigned int)uleb128(&p); break; case DW_LNS_set_column: - /*column = (unsigned int)*/(void)uleb128((char **)&p); + /*column = (unsigned int)*/(void)uleb128(&p); break; case DW_LNS_negate_stmt: is_stmt = !is_stmt; @@ -441,7 +439,8 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, addr += a; break; case DW_LNS_fixed_advance_pc: - a = *(unsigned char *)p++; + a = *(uint16_t *)p; + p += sizeof(uint16_t); addr += a; break; case DW_LNS_set_prologue_end: @@ -451,10 +450,10 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, /* epilogue_begin = 1; */ break; case DW_LNS_set_isa: - /* isa = (unsigned int)*/(void)uleb128((char **)&p); + /* isa = (unsigned int)*/(void)uleb128(&p); break; case 0: - a = *(unsigned char *)p++; + a = uleb128(&p); op = *p++; switch (op) { case DW_LNE_end_sequence: @@ -478,7 +477,7 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, break; case DW_LNE_set_discriminator: /* TODO:currently ignore */ - uleb128((char **)&p); + uleb128(&p); break; default: kprintf("Unknown extended opcode: %d in %s\n", @@ -501,10 +500,10 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, static int parse_debug_line(int num_traces, void **traces, - char *debug_line, unsigned long size, + const char *debug_line, unsigned long size, obj_info_t *obj, line_info_t *lines, int offset) { - char *debug_line_end = debug_line + size; + 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; @@ -530,13 +529,25 @@ append_obj(obj_info_t **objp) } #ifdef USE_ELF +/* Ideally we should check 4 paths to follow gnu_debuglink: + * + * - /usr/lib/debug/.build-id/ab/cdef1234.debug + * - /usr/bin/ruby.debug + * - /usr/bin/.debug/ruby.debug + * - /usr/lib/debug/usr/bin/ruby.debug. + * + * but we handle only two cases for now as the two formats are + * used by some linux distributions. + * + * See GDB's info for detail. + * https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html + */ + +// 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) { - /* Ideally we should check 4 paths to follow gnu_debuglink, - but we handle only one case for now as this format is used - by some linux distributions. See GDB's info for detail. */ static const char global_debug_dir[] = "/usr/lib/debug"; const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1; char *p; @@ -563,6 +574,37 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces, o2->path = o1->path; fill_lines(num_traces, traces, 0, objp, lines, offset); } + +// 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) +{ + static const char global_debug_dir[] = "/usr/lib/debug/.build-id/"; + const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1; + char *p; + obj_info_t *o1 = *objp, *o2; + size_t i; + + if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return; + + memcpy(binary_filename, global_debug_dir, global_debug_dir_len); + p = binary_filename + global_debug_dir_len; + for (i = 0; i < build_id_size; i++) { + static const char tbl[] = "0123456789abcdef"; + unsigned char n = build_id[i]; + *p++ = tbl[n / 16]; + *p++ = tbl[n % 16]; + if (i == 0) *p++ = '/'; + } + strcpy(p, ".debug"); + + append_obj(objp); + o2 = *objp; + o2->base_addr = o1->base_addr; + o2->path = o1->path; + fill_lines(num_traces, traces, 0, objp, lines, offset); +} #endif enum @@ -768,6 +810,18 @@ enum DW_FORM_addrx4 = 0x2c }; +/* Range list entry encodings */ +enum { + DW_RLE_end_of_list = 0x00, + DW_RLE_base_addressx = 0x01, + DW_RLE_startx_endx = 0x02, + DW_RLE_startx_length = 0x03, + DW_RLE_offset_pair = 0x04, + DW_RLE_base_address = 0x05, + DW_RLE_start_end = 0x06, + DW_RLE_start_length = 0x07 +}; + enum { VAL_none = 0, VAL_cstr = 1, @@ -779,21 +833,21 @@ enum { # define ABBREV_TABLE_SIZE 256 typedef struct { obj_info_t *obj; - char *file; - char *current_cu; + const char *file; + const char *current_cu; uint64_t current_low_pc; - char *debug_line_cu_end; - char *debug_line_files; - char *debug_line_directories; - char *p; - char *cu_end; - char *pend; - char *q0; - char *q; + const char *debug_line_cu_end; + const char *debug_line_files; + const char *debug_line_directories; + const char *p; + const char *cu_end; + const char *pend; + const char *q0; + const char *q; int format; // 4 or 8 uint8_t address_size; int level; - char *abbrev_table[ABBREV_TABLE_SIZE]; + const char *abbrev_table[ABBREV_TABLE_SIZE]; } DebugInfoReader; typedef struct { @@ -804,7 +858,7 @@ typedef struct { typedef struct { union { - char *ptr; + const char *ptr; uint64_t uint64; int64_t int64; } as; @@ -837,39 +891,39 @@ get_uint64(const uint8_t *p) } static uint8_t -read_uint8(char **ptr) +read_uint8(const char **ptr) { - const unsigned char *p = (const unsigned char *)*ptr; - *ptr = (char *)(p + 1); - return *p; + const char *p = *ptr; + *ptr = (p + 1); + return (uint8_t)*p; } static uint16_t -read_uint16(char **ptr) +read_uint16(const char **ptr) { - const unsigned char *p = (const unsigned char *)*ptr; - *ptr = (char *)(p + 2); - return get_uint16(p); + const char *p = *ptr; + *ptr = (p + 2); + return get_uint16((const uint8_t *)p); } static uint32_t -read_uint24(char **ptr) +read_uint24(const char **ptr) { - const unsigned char *p = (const unsigned char *)*ptr; - *ptr = (char *)(p + 3); - return (*p << 16) | get_uint16(p+1); + const char *p = *ptr; + *ptr = (p + 3); + return ((uint8_t)*p << 16) | get_uint16((const uint8_t *)p+1); } static uint32_t -read_uint32(char **ptr) +read_uint32(const char **ptr) { - const unsigned char *p = (const unsigned char *)*ptr; - *ptr = (char *)(p + 4); - return get_uint32(p); + const char *p = *ptr; + *ptr = (p + 4); + return get_uint32((const uint8_t *)p); } static uint64_t -read_uint64(char **ptr) +read_uint64(const char **ptr) { const unsigned char *p = (const unsigned char *)*ptr; *ptr = (char *)(p + 8); @@ -877,7 +931,7 @@ read_uint64(char **ptr) } static uintptr_t -read_uintptr(char **ptr) +read_uintptr(const char **ptr) { const unsigned char *p = (const unsigned char *)*ptr; *ptr = (char *)(p + SIZEOF_VOIDP); @@ -918,13 +972,31 @@ debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj) reader->p = obj->debug_info.ptr; reader->pend = obj->debug_info.ptr + obj->debug_info.size; reader->debug_line_cu_end = obj->debug_line.ptr; + reader->current_low_pc = 0; +} + +static void +di_skip_die_attributes(const char **p) +{ + for (;;) { + uint64_t at = uleb128(p); + uint64_t form = uleb128(p); + if (!at && !form) break; + switch (form) { + default: + break; + case DW_FORM_implicit_const: + sleb128(p); + break; + } + } } static void di_read_debug_abbrev_cu(DebugInfoReader *reader) { uint64_t prev = 0; - char *p = reader->q0; + const char *p = reader->q0; for (;;) { uint64_t abbrev_number = uleb128(&p); if (abbrev_number <= prev) break; @@ -934,12 +1006,7 @@ di_read_debug_abbrev_cu(DebugInfoReader *reader) prev = abbrev_number; uleb128(&p); /* tag */ p++; /* has_children */ - /* skip content */ - for (;;) { - uint64_t at = uleb128(&p); - uint64_t form = uleb128(&p); - if (!at && !form) break; - } + di_skip_die_attributes(&p); } } @@ -975,7 +1042,7 @@ set_int_value(DebugInfoValue *v, int64_t n) } static void -set_cstr_value(DebugInfoValue *v, char *s) +set_cstr_value(DebugInfoValue *v, const char *s) { v->as.ptr = s; v->off = 0; @@ -983,7 +1050,7 @@ set_cstr_value(DebugInfoValue *v, char *s) } static void -set_cstrp_value(DebugInfoValue *v, char *s, uint64_t off) +set_cstrp_value(DebugInfoValue *v, const char *s, uint64_t off) { v->as.ptr = s; v->off = off; @@ -991,7 +1058,7 @@ set_cstrp_value(DebugInfoValue *v, char *s, uint64_t off) } static void -set_data_value(DebugInfoValue *v, char *s) +set_data_value(DebugInfoValue *v, const char *s) { v->as.ptr = s; v->type = VAL_data; @@ -1071,12 +1138,12 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa set_uint_value(v, read_uleb128(reader)); break; case DW_FORM_ref_addr: - if (reader->address_size == 4) { + if (reader->format == 4) { set_uint_value(v, read_uint32(&reader->p)); - } else if (reader->address_size == 8) { + } else if (reader->format == 8) { set_uint_value(v, read_uint64(&reader->p)); } else { - fprintf(stderr,"unknown address_size:%d", reader->address_size); + fprintf(stderr,"unknown format:%d", reader->format); abort(); } break; @@ -1192,10 +1259,10 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa } /* find abbrev in current compilation unit */ -static char * +static const char * di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number) { - char *p; + const char *p; if (abbrev_number < ABBREV_TABLE_SIZE) { return reader->abbrev_table[abbrev_number]; } @@ -1203,12 +1270,7 @@ di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number) /* skip 255th record */ uleb128(&p); /* tag */ p++; /* has_children */ - /* skip content */ - for (;;) { - uint64_t at = uleb128(&p); - uint64_t form = uleb128(&p); - if (!at && !form) break; - } + di_skip_die_attributes(&p); for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) { if (n == 0) { fprintf(stderr,"%d: Abbrev Number %"PRId64" not found\n",__LINE__, abbrev_number); @@ -1216,12 +1278,7 @@ di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number) } uleb128(&p); /* tag */ p++; /* has_children */ - /* skip content */ - for (;;) { - uint64_t at = uleb128(&p); - uint64_t form = uleb128(&p); - if (!at && !form) break; - } + di_skip_die_attributes(&p); } return p; } @@ -1256,10 +1313,10 @@ div_inspect(DebugInfoValue *v) { switch (v->type) { case VAL_uint: - fprintf(stderr,"%d: type:%d size:%zx v:%lx\n",__LINE__,v->type,v->size,v->as.uint64); + fprintf(stderr,"%d: type:%d size:%zx v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64); break; case VAL_int: - fprintf(stderr,"%d: type:%d size:%zx v:%ld\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64); + fprintf(stderr,"%d: type:%d size:%zx v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64); break; case VAL_cstr: fprintf(stderr,"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr); @@ -1349,6 +1406,21 @@ ranges_set(ranges_t *ptr, DebugInfoValue *v) } } +static uint64_t +read_dw_form_addr(DebugInfoReader *reader, const char **ptr) +{ + const char *p = *ptr; + *ptr = p + reader->address_size; + if (reader->address_size == 4) { + return read_uint32(&p); + } else if (reader->address_size == 8) { + return read_uint64(&p); + } else { + fprintf(stderr,"unknown address_size:%d", reader->address_size); + abort(); + } +} + static uintptr_t ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr) { @@ -1362,8 +1434,53 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr) } else if (ptr->ranges_set) { /* TODO: support base address selection entry */ - char *p = reader->obj->debug_ranges.ptr + ptr->ranges; + const char *p; uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc; + bool base_valid = true; + if (reader->obj->debug_rnglists.ptr) { + p = reader->obj->debug_rnglists.ptr + ptr->ranges; + for (;;) { + uint8_t rle = read_uint8(&p); + uintptr_t from = 0, to = 0; + if (rle == DW_RLE_end_of_list) break; + switch (rle) { + case DW_RLE_base_addressx: + uleb128(&p); + base_valid = false; /* not supported yet */ + break; + case DW_RLE_startx_endx: + uleb128(&p); + uleb128(&p); + break; + case DW_RLE_startx_length: + uleb128(&p); + uleb128(&p); + break; + case DW_RLE_offset_pair: + if (!base_valid) break; + from = (uintptr_t)base + uleb128(&p); + to = (uintptr_t)base + uleb128(&p); + break; + case DW_RLE_base_address: + base = read_dw_form_addr(reader, &p); + 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); + break; + case DW_RLE_start_length: + from = (uintptr_t)read_dw_form_addr(reader, &p); + to = from + uleb128(&p); + break; + } + if (from <= addr && addr < to) { + return from; + } + } + return false; + } + p = reader->obj->debug_ranges.ptr + ptr->ranges; for (;;) { uintptr_t from = read_uintptr(&p); uintptr_t to = read_uintptr(&p); @@ -1373,7 +1490,7 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr) base = to; } else if (base + from <= addr && addr < base + to) { - return from; + return (uintptr_t)base + from; } } } @@ -1479,14 +1596,31 @@ di_read_cu(DebugInfoReader *reader) } static void -read_abstract_origin(DebugInfoReader *reader, uint64_t abstract_origin, line_info_t *line) +read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line) { - char *p = reader->p; - char *q = reader->q; + const char *p = reader->p; + const char *q = reader->q; int level = reader->level; DIE die; - reader->p = reader->current_cu + abstract_origin; + switch (form) { + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + reader->p = reader->current_cu + abstract_origin; + break; + case DW_FORM_ref_addr: + goto finish; /* not supported yet */ + case DW_FORM_ref_sig8: + goto finish; /* not supported yet */ + case DW_FORM_ref_sup4: + case DW_FORM_ref_sup8: + goto finish; /* not supported yet */ + default: + goto finish; + } if (!di_read_die(reader, &die)) goto finish; /* enumerate abbrev */ @@ -1551,7 +1685,7 @@ 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.as.uint64, &line); + read_abstract_origin(reader, v.form, v.as.uint64, &line); break; /* goto skip_die; */ } } @@ -1585,6 +1719,7 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces, static unsigned long uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr) { + *ptr = NULL; #ifdef SUPPORT_COMPRESSED_DEBUG_LINE ElfW(Chdr) *chdr = (ElfW(Chdr) *)(file + shdr->sh_offset); unsigned long destsize = chdr->ch_size; @@ -1605,6 +1740,7 @@ uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr) fail: free(*ptr); + *ptr = NULL; #endif return 0; } @@ -1619,6 +1755,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, ElfW(Ehdr) *ehdr; ElfW(Shdr) *shdr, *shstr_shdr; ElfW(Shdr) *gnu_debuglink_shdr = NULL; + ElfW(Shdr) *note_gnu_build_id = NULL; int fd; off_t filesize; char *file; @@ -1691,6 +1828,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink, /* 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; @@ -1701,6 +1843,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, ".debug_info", ".debug_line", ".debug_ranges", + ".debug_rnglists", ".debug_str" }; @@ -1806,6 +1949,13 @@ fill_lines(int num_traces, void **traces, int check_debuglink, num_traces, traces, objp, lines, offset); } + 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); + } goto finish; } @@ -1950,6 +2100,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, "__debug_info", "__debug_line", "__debug_ranges", + "__debug_rnglists", "__debug_str" }; struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd; @@ -1987,7 +2138,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, char *strtab = file + cmd->stroff, *sname = 0; uint32_t j; uintptr_t saddr = 0; - /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, p); */ + /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, (void *)p); */ for (j = 0; j < cmd->nsyms; j++) { uintptr_t symsize, d; struct LP(nlist) *e = &nl[j]; @@ -2039,7 +2190,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, #endif #define HAVE_MAIN_EXE_PATH -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__DragonFly__) # include #endif /* ssize_t main_exe_path(void) @@ -2048,17 +2199,21 @@ fill_lines(int num_traces, void **traces, int check_debuglink, * and returns strlen(binary_filename). * it is NUL terminated. */ -#if defined(__linux__) +#if defined(__linux__) || defined(__NetBSD__) static ssize_t main_exe_path(void) { -# define PROC_SELF_EXE "/proc/self/exe" +# if defined(__linux__) +# define PROC_SELF_EXE "/proc/self/exe" +# elif defined(__NetBSD__) +# define PROC_SELF_EXE "/proc/curproc/exe" +# endif ssize_t len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX); if (len < 0) return 0; binary_filename[len] = 0; return len; } -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__DragonFly__) static ssize_t main_exe_path(void) { diff --git a/ruby/addr2line.h b/ruby/addr2line.h index 4f6cf179e..f09b66580 100644 --- a/ruby/addr2line.h +++ b/ruby/addr2line.h @@ -1,3 +1,5 @@ +#ifndef RUBY_ADDR2LINE_H +#define RUBY_ADDR2LINE_H /********************************************************************** addr2line.h - @@ -8,9 +10,6 @@ **********************************************************************/ -#ifndef RUBY_ADDR2LINE_H -#define RUBY_ADDR2LINE_H - #if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)) void diff --git a/ruby/appveyor.yml b/ruby/appveyor.yml deleted file mode 100644 index 7909de9e6..000000000 --- a/ruby/appveyor.yml +++ /dev/null @@ -1,94 +0,0 @@ ---- -version: '{build}' -shallow_clone: true -platform: - - x64 -environment: - ruby_version: "24-%Platform%" - zlib_version: "1.2.11" - matrix: - - build: vs - vs: 120 - ssl: OpenSSL - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - GEMS_FOR_TEST: "" - - build: vs - vs: 140 - ssl: OpenSSL-v111 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - GEMS_FOR_TEST: "" - RELINE_TEST_ENCODING: "Windows-31J" - UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=." -for: -- - matrix: - only: - - build: vs - install: - - ver - - chcp - - SET BITS=%Platform:x86=32% - - SET BITS=%BITS:x=% - - SET OPENSSL_DIR=C:\%ssl%-Win%BITS% - - 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% touch-unicode-files - - nmake %mflags% %UPDATE_UNICODE% up incs - - del Makefile - - mkdir \usr\local\bin - - mkdir \usr\local\include - - mkdir \usr\local\lib - - curl -fsSL -o zlib%zlib_version:.=%.zip --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip - - 7z x -o%APPVEYOR_BUILD_FOLDER%\ext\zlib zlib%zlib_version:.=%.zip - - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I - - attrib +r /s /d - - mkdir %Platform%-mswin_%vs% - build_script: - - cd %APPVEYOR_BUILD_FOLDER% - - cd %Platform%-mswin_%vs% - - ..\win32\configure.bat --without-ext=+,dbm,gdbm,readline --with-opt-dir=/usr/local --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=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor -j%JOBS% --exclude readline --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=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" test-all 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" - - nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows -notifications: - # Using "Webhook" with templated body to skip notification on Pull Request - - provider: Webhook - method: POST - url: - secure: iMINHMS0nZabaDsxN9omRDsekxzVvAAzEq5ev7lN6vb+gUETT+rbDKLGxBxBpEpxlnPlLdzroIJ+DTKlwfJA8VkGawTn9EXNsucH0OkSf2M= # AppVeyor CI - body: >- - {{^isPullRequest}} - { - "attachments": [ - { - "text": "Build <{{buildUrl}}|#{{buildVersion}}> (<{{commitUrl}}|{{commitId}}>) of {{repositoryName}}@{{branch}} by {{commitAuthor}} {{status}}", - "color": "{{#passed}}good{{/passed}}{{#failed}}danger{{/failed}}" - } - ], - "channel": "#alerts" - } - {{/isPullRequest}} - on_build_success: false - on_build_failure: true - on_build_status_changed: true diff --git a/ruby/array.c b/ruby/array.c index 28bd8c866..8becdbbc9 100644 --- a/ruby/array.c +++ b/ruby/array.c @@ -10,16 +10,29 @@ Copyright (C) 2000 Information-technology Promotion Agency, Japan **********************************************************************/ + +#include "debug_counter.h" +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compar.h" +#include "internal/enum.h" +#include "internal/gc.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/rational.h" +#include "internal/vm.h" +#include "probes.h" #include "ruby/encoding.h" -#include "ruby/util.h" #include "ruby/st.h" -#include "probes.h" -#include "id.h" -#include "debug_counter.h" +#include "ruby/util.h" #include "transient_heap.h" -#include "internal.h" +#include "builtin.h" #if !ARRAY_DEBUG +# undef NDEBUG # define NDEBUG #endif #include "ruby_assert.h" @@ -33,12 +46,14 @@ VALUE rb_cArray; #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE)) #define SMALL_ARRAY_LEN 16 +RBIMPL_ATTR_MAYBE_UNUSED() static int should_be_T_ARRAY(VALUE ary) { return RB_TYPE_P(ary, T_ARRAY); } +RBIMPL_ATTR_MAYBE_UNUSED() static int should_not_be_shared_and_embedded(VALUE ary) { @@ -204,9 +219,11 @@ ary_verify_(VALUE ary, const char *file, int line) #endif } +#if USE_TRANSIENT_HEAP if (RARRAY_TRANSIENT_P(ary)) { assert(rb_transient_heap_managed_ptr_p(RARRAY_CONST_PTR_TRANSIENT(ary))); } +#endif rb_transient_heap_verify(); @@ -337,14 +354,16 @@ ary_heap_free(VALUE ary) } } -static void +static size_t ary_heap_realloc(VALUE ary, size_t new_capa) { + size_t alloc_capa = new_capa; size_t old_capa = ARY_HEAP_CAPA(ary); if (RARRAY_TRANSIENT_P(ary)) { if (new_capa <= old_capa) { /* do nothing */ + alloc_capa = old_capa; } else { VALUE *new_ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * new_capa); @@ -362,6 +381,8 @@ ary_heap_realloc(VALUE ary, size_t new_capa) SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, old_capa); } ary_verify(ary); + + return alloc_capa; } #if USE_TRANSIENT_HEAP @@ -426,6 +447,7 @@ ary_resize_capa(VALUE ary, long capacity) assert(!ARY_SHARED_P(ary)); if (capacity > RARRAY_EMBED_LEN_MAX) { + size_t new_capa = capacity; if (ARY_EMBED_P(ary)) { long len = ARY_EMBED_LEN(ary); VALUE *ptr = ary_heap_alloc(ary, capacity); @@ -436,9 +458,9 @@ ary_resize_capa(VALUE ary, long capacity) ARY_SET_HEAP_LEN(ary, len); } else { - ary_heap_realloc(ary, capacity); + new_capa = ary_heap_realloc(ary, capacity); } - ARY_SET_CAPA(ary, capacity); + ARY_SET_CAPA(ary, new_capa); } else { if (!ARY_EMBED_P(ary)) { @@ -492,13 +514,9 @@ rb_ary_decrement_share(VALUE shared_root) { if (shared_root) { long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1; - if (num == 0) { - rb_ary_free(shared_root); - rb_gc_force_recycle(shared_root); - } - else if (num > 0) { + if (num > 0) { ARY_SET_SHARED_ROOT_REFCNT(shared_root, num); - } + } } } @@ -545,34 +563,33 @@ rb_ary_modify_check(VALUE ary) } void -rb_ary_modify(VALUE ary) +rb_ary_cancel_sharing(VALUE ary) { - rb_ary_modify_check(ary); if (ARY_SHARED_P(ary)) { - long shared_len, len = RARRAY_LEN(ary); + long shared_len, len = RARRAY_LEN(ary); VALUE shared_root = ARY_SHARED_ROOT(ary); ary_verify(shared_root); if (len <= RARRAY_EMBED_LEN_MAX) { - const VALUE *ptr = ARY_HEAP_PTR(ary); + const VALUE *ptr = ARY_HEAP_PTR(ary); FL_UNSET_SHARED(ary); FL_SET_EMBED(ary); - MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); + MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); rb_ary_decrement_share(shared_root); ARY_SET_EMBED_LEN(ary, len); } else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) { long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root); - FL_UNSET_SHARED(ary); + FL_UNSET_SHARED(ary); ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared_root)); - ARY_SET_CAPA(ary, shared_len); + ARY_SET_CAPA(ary, shared_len); RARRAY_PTR_USE_TRANSIENT(ary, ptr, { - MEMMOVE(ptr, ptr+shift, VALUE, len); - }); + MEMMOVE(ptr, ptr+shift, VALUE, len); + }); FL_SET_EMBED(shared_root); rb_ary_decrement_share(shared_root); - } + } else { VALUE *ptr = ary_heap_alloc(ary, len); MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len); @@ -581,11 +598,18 @@ rb_ary_modify(VALUE ary) ARY_SET_PTR(ary, ptr); } - rb_gc_writebarrier_remember(ary); + rb_gc_writebarrier_remember(ary); } ary_verify(ary); } +void +rb_ary_modify(VALUE ary) +{ + rb_ary_modify_check(ary); + rb_ary_cancel_sharing(ary); +} + static VALUE ary_ensure_room_for_push(VALUE ary, long add_len) { @@ -636,12 +660,15 @@ ary_ensure_room_for_push(VALUE ary, long add_len) /* * call-seq: - * ary.freeze -> ary + * array.freeze -> self * - * Calls Object#freeze on +ary+ to prevent any further - * modification. A RuntimeError will be raised if a modification - * attempt is made. + * Freezes +self+; returns +self+: + * a = [] + * a.frozen? # => false + * a.freeze + * a.frozen? # => true * + * An attempt to modify a frozen \Array raises FrozenError. */ VALUE @@ -764,6 +791,58 @@ rb_ary_new_from_values(long n, const VALUE *elts) return rb_ary_tmp_new_from_values(rb_cArray, n, elts); } +static VALUE +ec_ary_alloc(rb_execution_context_t *ec, VALUE klass) +{ + RB_EC_NEWOBJ_OF(ec, ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0)); + /* Created array is: + * FL_SET_EMBED((VALUE)ary); + * ARY_SET_EMBED_LEN((VALUE)ary, 0); + */ + return (VALUE)ary; +} + +static VALUE +ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa) +{ + VALUE ary,*ptr; + + if (capa < 0) { + rb_raise(rb_eArgError, "negative array size (or size too big)"); + } + if (capa > ARY_MAX_SIZE) { + rb_raise(rb_eArgError, "array size too big"); + } + + RUBY_DTRACE_CREATE_HOOK(ARRAY, capa); + + ary = ec_ary_alloc(ec, klass); + + if (capa > RARRAY_EMBED_LEN_MAX) { + ptr = ary_heap_alloc(ary, capa); + FL_UNSET_EMBED(ary); + ARY_SET_PTR(ary, ptr); + ARY_SET_CAPA(ary, capa); + ARY_SET_HEAP_LEN(ary, 0); + } + + return ary; +} + +VALUE +rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts) +{ + VALUE ary; + + ary = ec_ary_new(ec, rb_cArray, n); + if (n > 0 && elts) { + ary_memcpy(ary, 0, n, elts); + ARY_SET_LEN(ary, n); + } + + return ary; +} + VALUE rb_ary_tmp_new(long capa) { @@ -854,25 +933,26 @@ ary_make_shared(VALUE ary) long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary); const VALUE *ptr; NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0)); + VALUE vshared = (VALUE)shared; rb_ary_transient_heap_evacuate(ary, TRUE); ptr = ARY_HEAP_PTR(ary); - FL_UNSET_EMBED(shared); - ARY_SET_LEN((VALUE)shared, capa); - ARY_SET_PTR((VALUE)shared, ptr); - ary_mem_clear((VALUE)shared, len, capa - len); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_ROOT_REFCNT((VALUE)shared, 1); + FL_UNSET_EMBED(vshared); + ARY_SET_LEN(vshared, capa); + ARY_SET_PTR(vshared, ptr); + ary_mem_clear(vshared, len, capa - len); + FL_SET_SHARED_ROOT(vshared); + ARY_SET_SHARED_ROOT_REFCNT(vshared, 1); FL_SET_SHARED(ary); RB_DEBUG_COUNTER_INC(obj_ary_shared_create); - ARY_SET_SHARED(ary, (VALUE)shared); - OBJ_FREEZE(shared); + ARY_SET_SHARED(ary, vshared); + OBJ_FREEZE(vshared); - ary_verify((VALUE)shared); + ary_verify(vshared); ary_verify(ary); - return (VALUE)shared; + return vshared; } } @@ -917,23 +997,24 @@ rb_check_to_array(VALUE ary) return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a); } +VALUE +rb_to_array(VALUE ary) +{ + return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a); +} + /* * call-seq: - * Array.try_convert(obj) -> array or nil + * Array.try_convert(object) -> object, new_array, or nil * - * Tries to convert +obj+ into an array, using the +to_ary+ method. Returns - * the converted array or +nil+ if +obj+ cannot be converted. - * This method can be used to check if an argument is an array. + * If +object+ is an \Array object, returns +object+. * - * Array.try_convert([1]) #=> [1] - * Array.try_convert("1") #=> nil + * Otherwise if +object+ responds to :to_ary, + * calls object.to_ary and returns the result. * - * if tmp = Array.try_convert(arg) - * # the argument is an array - * elsif tmp = String.try_convert(arg) - * # the argument is a string - * end + * Returns +nil+ if +object+ does not respond to :to_ary * + * Raises an exception unless object.to_ary returns an \Array object. */ static VALUE @@ -944,58 +1025,46 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary) /* * call-seq: - * Array.new(size=0, default=nil) - * Array.new(array) - * Array.new(size) {|index| block } - * - * Returns a new array. - * - * In the first form, if no arguments are sent, the new array will be empty. - * When a +size+ and an optional +default+ are sent, an array is created with - * +size+ copies of +default+. Take notice that all elements will reference the - * same object +default+. - * - * The second form creates a copy of the array passed as a parameter (the - * array is generated by calling to_ary on the parameter). - * - * first_array = ["Matz", "Guido"] - * - * second_array = Array.new(first_array) #=> ["Matz", "Guido"] - * - * first_array.equal? second_array #=> false - * - * In the last form, an array of the given size is created. Each element in - * this array is created by passing the element's index to the given block - * and storing the return value. - * - * Array.new(3) {|index| index ** 2} - * # => [0, 1, 4] - * - * == Common gotchas - * - * When sending the second parameter, the same object will be used as the - * value for all the array elements: - * - * a = Array.new(2, Hash.new) - * # => [{}, {}] - * - * a[0]['cat'] = 'feline' - * a # => [{"cat"=>"feline"}, {"cat"=>"feline"}] - * - * a[1]['cat'] = 'Felix' - * a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}] - * - * Since all the Array elements store the same hash, changes to one of them - * will affect them all. - * - * If multiple copies are what you want, you should use the block - * version which uses the result of that block each time an element - * of the array needs to be initialized: - * - * a = Array.new(2) {Hash.new} - * a[0]['cat'] = 'feline' - * a # => [{"cat"=>"feline"}, {}] - * + * 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 + * + * Returns a new \Array. + * + * With no block and no arguments, returns a new empty \Array object. + * + * With no block and a single \Array argument +array+, + * returns a new \Array formed from +array+: + * a = Array.new([:foo, 'bar', 2]) + * a.class # => Array + * a # => [:foo, "bar", 2] + * + * With no block and a single \Integer argument +size+, + * returns a new \Array of the given size + * whose elements are all +nil+: + * a = Array.new(3) + * a # => [nil, nil, nil] + * + * With no block and arguments +size+ and +default_value+, + * returns an \Array of the given size; + * each element is that same +default_value+: + * a = Array.new(3, 'x') + * a # => ['x', 'x', 'x'] + * + * 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: + * a = Array.new(3) {|index| "Element #{index}" } + * a # => ["Element 0", "Element 1", "Element 2"] + * + * Raises ArgumentError if +size+ is negative. + * + * With a block and no argument, + * or a single argument +0+, + * ignores the block and returns a new empty \Array. */ static VALUE @@ -1136,10 +1205,56 @@ 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); + + const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary); + const long orig_len = len; + + if ((step > 0 && step >= len) || (step < 0 && (step < -len))) { + VALUE result = ary_new(klass, 1); + VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result); + RB_OBJ_WRITE(result, ptr, values[offset]); + ARY_SET_EMBED_LEN(result, 1); + return result; + } + + long ustep = (step < 0) ? -step : step; + len = (len + ustep - 1) / ustep; + + long i; + long j = offset + ((step > 0) ? 0 : (orig_len - 1)); + VALUE result = ary_new(klass, len); + if (len <= RARRAY_EMBED_LEN_MAX) { + VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result); + for (i = 0; i < len; ++i) { + RB_OBJ_WRITE(result, ptr+i, values[j]); + j += step; + } + ARY_SET_EMBED_LEN(result, len); + } + else { + RARRAY_PTR_USE_TRANSIENT(result, ptr, { + for (i = 0; i < len; ++i) { + RB_OBJ_WRITE(result, ptr+i, values[j]); + j += step; + } + }); + ARY_SET_LEN(result, len); + } + + return result; +} + static VALUE ary_make_shared_copy(VALUE ary) { - return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary)); + return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary)); } enum ary_take_pos_flags @@ -1177,18 +1292,16 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos /* * call-seq: - * ary << obj -> ary - * - * Append---Pushes the given object on to the end of this array. This - * expression returns the array itself, so several appends - * may be chained together. + * array << object -> self * - * a = [ 1, 2 ] - * a << "c" << "d" << [ 3, 4 ] - * #=> [ 1, 2, "c", "d", [ 3, 4 ] ] - * a - * #=> [ 1, 2, "c", "d", [ 3, 4 ] ] + * Appends +object+ to +self+; returns +self+: + * a = [:foo, 'bar', 2] + * a << :baz # => [:foo, "bar", 2, :baz] * + * Appends +object+ as one element, even if it is another \Array: + * a = [:foo, 'bar', 2] + * a1 = a << [3, 4] + * a1 # => [:foo, "bar", 2, [3, 4]] */ VALUE @@ -1216,19 +1329,22 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len) /* * call-seq: - * ary.push(obj, ...) -> ary - * ary.append(obj, ...) -> ary - * - * Append --- Pushes the given object(s) on to the end of this array. This - * expression returns the array itself, so several appends - * may be chained together. See also Array#pop for the opposite - * effect. - * - * a = [ "a", "b", "c" ] - * a.push("d", "e", "f") - * #=> ["a", "b", "c", "d", "e", "f"] - * [1, 2, 3].push(4).push(5) - * #=> [1, 2, 3, 4, 5] + * array.push(*objects) -> self + * + * Appends trailing elements. + * + * Appends each argument in +objects+ to +self+; returns +self+: + * a = [:foo, 'bar', 2] + * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat] + * + * Appends each argument as one 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]] + * + * Array#append is an alias for \Array#push. + * + * Related: #pop, #shift, #unshift. */ static VALUE @@ -1258,20 +1374,30 @@ rb_ary_pop(VALUE ary) /* * call-seq: - * ary.pop -> obj or nil - * ary.pop(n) -> new_ary + * array.pop -> object or nil + * array.pop(n) -> new_array + * + * Removes and returns trailing elements. + * + * When no argument is given and +self+ is not empty, + * removes and returns the last element: + * a = [:foo, 'bar', 2] + * a.pop # => 2 + * a # => [:foo, "bar"] + * + * Returns +nil+ if the array is empty. * - * Removes the last element from +self+ and returns it, or - * +nil+ if the array is empty. + * 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 a number +n+ is given, returns an array of the last +n+ elements - * (or less) just like array.slice!(-n, n) does. See also - * Array#push for the opposite effect. + * If +n+ is positive and out of range, + * removes and returns all elements: + * a = [:foo, 'bar', 2] + * a.pop(50) # => [:foo, "bar", 2] * - * a = [ "a", "b", "c", "d" ] - * a.pop #=> "d" - * a.pop(2) #=> ["b", "c"] - * a #=> ["a"] + * Related: #push, #shift, #unshift. */ static VALUE @@ -1326,25 +1452,32 @@ rb_ary_shift(VALUE ary) /* * call-seq: - * ary.shift -> obj or nil - * ary.shift(n) -> new_ary + * array.shift -> object or nil + * array.shift(n) -> new_array * - * Removes the first element of +self+ and returns it (shifting all - * other elements down by one). Returns +nil+ if the array - * is empty. + * Removes and returns leading elements. * - * If a number +n+ is given, returns an array of the first +n+ elements - * (or less) just like array.slice!(0, n) does. With +ary+ - * containing only the remainder elements, not including what was shifted to - * +new_ary+. See also Array#unshift for the opposite effect. + * When no argument is given, removes and returns the first element: + * a = [:foo, 'bar', 2] + * a.shift # => :foo + * a # => ['bar', 2] * - * args = [ "-m", "-q", "filename" ] - * args.shift #=> "-m" - * args #=> ["-q", "filename"] + * Returns +nil+ if +self+ is empty. * - * args = [ "-m", "-q", "filename" ] - * args.shift(2) #=> ["-m", "-q"] - * args #=> ["filename"] + * When positive \Integer argument +n+ is given, removes the first +n+ elements; + * returns those elements in a new \Array: + * a = [:foo, 'bar', 2] + * a.shift(2) # => [:foo, 'bar'] + * a # => [2] + * + * If +n+ is as large as or larger than self.length, + * removes all elements; returns those elements in a new \Array: + * a = [:foo, 'bar', 2] + * a.shift(3) # => [:foo, 'bar', 2] + * + * If +n+ is zero, returns a new empty \Array; +self+ is unmodified. + * + * Related: #push, #pop, #unshift. */ static VALUE @@ -1365,59 +1498,75 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) return result; } -MJIT_FUNC_EXPORTED VALUE -rb_ary_behead(VALUE ary, long n) +static VALUE +behead_shared(VALUE ary, long n) { - if (n<=0) return ary; + assert(ARY_SHARED_P(ary)); + rb_ary_modify_check(ary); + if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) { + ary_mem_clear(ary, 0, n); + } + ARY_INCREASE_PTR(ary, n); + ARY_INCREASE_LEN(ary, -n); + ary_verify(ary); + return ary; +} +static VALUE +behead_transient(VALUE ary, long n) +{ rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) { - setup_occupied_shared: - ary_mem_clear(ary, 0, n); - } - ARY_INCREASE_PTR(ary, n); + RARRAY_PTR_USE_TRANSIENT(ary, ptr, { + MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n); + }); /* WB: no new reference */ + ARY_INCREASE_LEN(ary, -n); + ary_verify(ary); + return ary; +} + +MJIT_FUNC_EXPORTED VALUE +rb_ary_behead(VALUE ary, long n) +{ + if (n <= 0) { + return ary; + } + else if (ARY_SHARED_P(ary)) { + return behead_shared(ary, n); + } + else if (RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) { + ary_make_shared(ary); + return behead_shared(ary, n); } else { - if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) { - RARRAY_PTR_USE_TRANSIENT(ary, ptr, { - MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n); - }); /* WB: no new reference */ - } - else { - ary_make_shared(ary); - goto setup_occupied_shared; - } + return behead_transient(ary, n); } - ARY_INCREASE_LEN(ary, -n); +} + +static VALUE +make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len) +{ + if (head - sharedp < argc) { + long room = capa - len - argc; + + room -= room >> 4; + MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len); + head = sharedp + argc + room; + } + ARY_SET_PTR(ary, head - argc); + assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))); ary_verify(ary); - return ary; + return ARY_SHARED_ROOT(ary); } static VALUE -ary_ensure_room_for_unshift(VALUE ary, int argc) +ary_modify_for_unshift(VALUE ary, int argc) { long len = RARRAY_LEN(ary); long new_len = len + argc; long capa; const VALUE *head, *sharedp; - if (len > ARY_MAX_SIZE - argc) { - rb_raise(rb_eIndexError, "index %ld too big", new_len); - } - - if (ARY_SHARED_P(ary)) { - VALUE shared_root = ARY_SHARED_ROOT(ary); - capa = RARRAY_LEN(shared_root); - if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && capa > new_len) { - rb_ary_modify_check(ary); - head = RARRAY_CONST_PTR_TRANSIENT(ary); - sharedp = RARRAY_CONST_PTR_TRANSIENT(shared_root); - goto makeroom_if_need; - } - } - rb_ary_modify(ary); capa = ARY_CAPA(ary); if (capa - (capa >> 6) <= new_len) { @@ -1433,21 +1582,7 @@ ary_ensure_room_for_unshift(VALUE ary, int argc) ary_make_shared(ary); head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary); - goto makeroom; - makeroom_if_need: - if (head - sharedp < argc) { - long room; - makeroom: - room = capa - new_len; - room -= room >> 4; - MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len); - head = sharedp + argc + room; - } - ARY_SET_PTR(ary, head - argc); - assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))); - - ary_verify(ary); - return ARY_SHARED_ROOT(ary); + return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len); } else { /* sliding items */ @@ -1460,17 +1595,49 @@ ary_ensure_room_for_unshift(VALUE ary, int argc) } } +static VALUE +ary_ensure_room_for_unshift(VALUE ary, int argc) +{ + long len = RARRAY_LEN(ary); + long new_len = len + argc; + + if (len > ARY_MAX_SIZE - argc) { + rb_raise(rb_eIndexError, "index %ld too big", new_len); + } + else if (! ARY_SHARED_P(ary)) { + return ary_modify_for_unshift(ary, argc); + } + else { + VALUE shared_root = ARY_SHARED_ROOT(ary); + long capa = RARRAY_LEN(shared_root); + + if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) { + return ary_modify_for_unshift(ary, argc); + } + else if (new_len > capa) { + return ary_modify_for_unshift(ary, argc); + } + else { + const VALUE * head = RARRAY_CONST_PTR_TRANSIENT(ary); + void *sharedp = (void *)RARRAY_CONST_PTR_TRANSIENT(shared_root); + + rb_ary_modify_check(ary); + return make_room_for_unshift(ary, head, sharedp, argc, capa, len); + } + } +} + /* * call-seq: - * ary.unshift(obj, ...) -> ary - * ary.prepend(obj, ...) -> ary + * array.unshift(*objects) -> self + * + * Prepends the given +objects+ to +self+: + * a = [:foo, 'bar', 2] + * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2] * - * Prepends objects to the front of +self+, moving other elements upwards. - * See also Array#shift for the opposite effect. + * Array#prepend is an alias for Array#unshift. * - * a = [ "b", "c", "d" ] - * a.unshift("a") #=> ["a", "b", "c", "d"] - * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"] + * Related: #push, #pop, #shift. */ static VALUE @@ -1515,7 +1682,7 @@ rb_ary_entry(VALUE ary, long offset) } VALUE -rb_ary_subseq(VALUE ary, long beg, long len) +rb_ary_subseq_step(VALUE ary, long beg, long len, long step) { VALUE klass; long alen = RARRAY_LEN(ary); @@ -1526,48 +1693,116 @@ rb_ary_subseq(VALUE ary, long beg, long len) if (alen < len || alen < beg + len) { len = alen - beg; } - klass = rb_obj_class(ary); + klass = rb_cArray; if (len == 0) return ary_new(klass, 0); + if (step == 0) + rb_raise(rb_eArgError, "slice step cannot be zero"); + if (step == 1) + return ary_make_partial(ary, klass, beg, len); + else + return ary_make_partial_step(ary, klass, beg, len, step); +} - return ary_make_partial(ary, klass, beg, len); +VALUE +rb_ary_subseq(VALUE ary, long beg, long len) +{ + return rb_ary_subseq_step(ary, beg, len, 1); } static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); /* * call-seq: - * ary[index] -> obj or nil - * ary[start, length] -> new_ary or nil - * ary[range] -> new_ary or nil - * ary.slice(index) -> obj or nil - * ary.slice(start, length) -> new_ary or nil - * ary.slice(range) -> new_ary or nil - * - * Element Reference --- Returns the element at +index+, or returns a - * subarray starting at the +start+ index and continuing for +length+ - * elements, or returns a subarray specified by +range+ of indices. - * - * Negative indices count backward from the end of the array (-1 is the last - * element). For +start+ and +range+ cases the starting index is just before - * an element. Additionally, an empty array is returned when the starting - * index for an element range is at the end of the array. - * - * Returns +nil+ if the index (or starting index) are out of range. - * - * a = [ "a", "b", "c", "d", "e" ] - * a[2] + a[0] + a[1] #=> "cab" - * a[6] #=> nil - * a[1, 2] #=> [ "b", "c" ] - * a[1..3] #=> [ "b", "c", "d" ] - * a[4..7] #=> [ "e" ] - * a[6..10] #=> nil - * a[-3, 3] #=> [ "c", "d", "e" ] - * # special cases - * a[5] #=> nil - * a[6, 1] #=> nil - * a[5, 1] #=> [] - * a[5..10] #=> [] - * + * 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 + * + * Returns elements from +self+; does not modify +self+. + * + * 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+: + * a = [:foo, 'bar', 2] + * a[-1] # => 2 + * a[-2] # => "bar" + * + * 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+: + * a = [:foo, 'bar', 2] + * a[0, 2] # => [:foo, "bar"] + * a[1, 2] # => ["bar", 2] + * + * If start + length is greater than self.length, + * returns all elements from offset +start+ to the end: + * a = [:foo, 'bar', 2] + * a[0, 4] # => [:foo, "bar", 2] + * a[1, 3] # => ["bar", 2] + * a[2, 2] # => [2] + * + * If start == self.size and length >= 0, + * returns a new empty \Array. + * + * If +length+ is negative, returns +nil+. + * + * When a single \Range argument +range+ is given, + * treats range.min as +start+ above + * and range.size as +length+ above: + * a = [:foo, 'bar', 2] + * a[0..1] # => [:foo, "bar"] + * a[1..2] # => ["bar", 2] + * + * Special case: If range.start == a.size, returns a new empty \Array. + * + * If range.end is negative, calculates the end index from the end: + * a = [:foo, 'bar', 2] + * a[0..-1] # => [:foo, "bar", 2] + * a[0..-2] # => [:foo, "bar"] + * a[0..-3] # => [:foo] + * + * If range.start is negative, calculates the start index from the end: + * a = [:foo, 'bar', 2] + * a[-1..2] # => [2] + * a[-2..2] # => ["bar", 2] + * a[-3..2] # => [:foo, "bar", 2] + * + * If range.start is larger than the array size, returns +nil+. + * a = [:foo, 'bar', 2] + * a[4..1] # => nil + * a[4..0] # => nil + * a[4..-1] # => nil + * + * When a single Enumerator::ArithmeticSequence argument +aseq+ is given, + * returns an Array of elements corresponding to the indexes produced by + * the sequence. + * a = ['--', 'data1', '--', 'data2', '--', 'data3'] + * a[(1..).step(2)] # => ["data1", "data2", "data3"] + * + * Unlike slicing with range, if the start or the end of the arithmetic sequence + * is larger than array size, throws RangeError. + * a = ['--', 'data1', '--', 'data2', '--', 'data3'] + * a[(1..11).step(2)] + * # RangeError (((1..11).step(2)) out of range) + * a[(7..).step(2)] + * # RangeError (((7..).step(2)) out of range) + * + * If given a single argument, and its type is not one of the listed, tries to + * convert it to Integer, and raises if it is impossible: + * a = [:foo, 'bar', 2] + * # Raises TypeError (no implicit conversion of Symbol into Integer): + * a[:foo] + * + * Array#slice is an alias for Array#[]. */ VALUE @@ -1580,7 +1815,7 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary) return rb_ary_aref1(ary, argv[0]); } -VALUE +static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e) { long beg = NUM2LONG(b); @@ -1594,35 +1829,33 @@ rb_ary_aref2(VALUE ary, VALUE b, VALUE e) MJIT_FUNC_EXPORTED VALUE rb_ary_aref1(VALUE ary, VALUE arg) { - long beg, len; + long beg, len, step; /* special case - speeding up */ if (FIXNUM_P(arg)) { return rb_ary_entry(ary, FIX2LONG(arg)); } - /* check if idx is Range */ - switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) { + /* check if idx is Range or ArithmeticSequence */ + switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) { case Qfalse: - break; + break; case Qnil: - return Qnil; + return Qnil; default: - return rb_ary_subseq(ary, beg, len); + return rb_ary_subseq_step(ary, beg, len, step); } + return rb_ary_entry(ary, NUM2LONG(arg)); } /* * call-seq: - * ary.at(index) -> obj or nil + * array.at(index) -> object * - * Returns the element at +index+. A negative index counts from the end of - * +self+. Returns +nil+ if the index is out of range. See also - * Array#[]. - * - * a = [ "a", "b", "c", "d", "e" ] - * a.at(0) #=> "a" - * a.at(-1) #=> "e" + * Returns the element at \Integer offset +index+; does not modify +self+. + * a = [:foo, 'bar', 2] + * a.at(0) # => :foo + * a.at(2) # => 2 */ VALUE @@ -1633,19 +1866,33 @@ rb_ary_at(VALUE ary, VALUE pos) /* * call-seq: - * ary.first -> obj or nil - * ary.first(n) -> new_ary + * array.first -> object or nil + * array.first(n) -> new_array + * + * Returns elements from +self+; does not modify +self+. + * + * When no argument is given, returns the first element: + * a = [:foo, 'bar', 2] + * a.first # => :foo + * a # => [:foo, "bar", 2] + * + * If +self+ is empty, returns +nil+. * - * Returns the first element, or the first +n+ elements, of the array. - * If the array is empty, the first form returns +nil+, and the - * second form returns an empty array. See also Array#last for - * the opposite effect. + * 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"] * - * a = [ "q", "r", "s", "t" ] - * a.first #=> "q" - * a.first(2) #=> ["q", "r"] + * If n >= array.size, returns all elements: + * a = [:foo, 'bar', 2] + * a.first(50) # => [:foo, "bar", 2] + * + * If n == 0 returns an new empty \Array: + * a = [:foo, 'bar', 2] + * a.first(0) # [] + * + * Related: #last. */ - static VALUE rb_ary_first(int argc, VALUE *argv, VALUE ary) { @@ -1660,17 +1907,32 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.last -> obj or nil - * ary.last(n) -> new_ary + * array.last -> object or nil + * array.last(n) -> new_array + * + * Returns elements from +self+; +self+ is not modified. * - * Returns the last element(s) of +self+. If the array is empty, - * the first form returns +nil+. + * When no argument is given, returns the last element: + * a = [:foo, 'bar', 2] + * a.last # => 2 + * a # => [:foo, "bar", 2] * - * See also Array#first for the opposite effect. + * If +self+ is empty, returns +nil+. * - * a = [ "w", "x", "y", "z" ] - * a.last #=> "z" - * a.last(2) #=> ["y", "z"] + * When non-negative \Innteger 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: + * a = [:foo, 'bar', 2] + * a.last(50) # => [:foo, "bar", 2] + * + * If n == 0, returns an new empty \Array: + * a = [:foo, 'bar', 2] + * a.last(0) # [] + * + * Related: #first. */ VALUE @@ -1688,26 +1950,35 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) /* * call-seq: - * ary.fetch(index) -> obj - * ary.fetch(index, default) -> obj - * ary.fetch(index) {|index| block} -> obj - * - * Tries to return the element at position +index+, but throws an IndexError - * exception if the referenced +index+ lies outside of the array bounds. This - * error can be prevented by supplying a second argument, which will act as a - * +default+ value. - * - * Alternatively, if a block is given it will only be executed when an - * invalid +index+ is referenced. - * - * Negative values of +index+ count from the end of the array. - * - * a = [ 11, 22, 33, 44 ] - * a.fetch(1) #=> 22 - * a.fetch(-1) #=> 44 - * a.fetch(4, 'cat') #=> "cat" - * a.fetch(100) {|i| puts "#{i} is out of bounds"} - * #=> "100 is out of bounds" + * array.fetch(index) -> element + * array.fetch(index, default_value) -> element + * array.fetch(index) {|index| ... } -> element + * + * Returns the element at offset +index+. + * + * With the single \Integer argument +index+, + * returns the element at offset +index+: + * a = [:foo, 'bar', 2] + * a.fetch(1) # => "bar" + * + * If +index+ is negative, counts from the end of the array: + * a = [:foo, 'bar', 2] + * 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+: + * a = [:foo, 'bar', 2] + * a.fetch(1, nil) # => "bar" + * + * With argument +index+ and a block, + * returns the element at offset +index+ if index is in range + * (and the block is not called); otherwise calls the block with index and returns its return value: + * + * a = [:foo, 'bar', 2] + * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar" + * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50" */ static VALUE @@ -1740,28 +2011,37 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.find_index(obj) -> int or nil - * ary.find_index {|item| block} -> int or nil - * ary.find_index -> Enumerator - * ary.index(obj) -> int or nil - * ary.index {|item| block} -> int or nil - * ary.index -> Enumerator + * array.index(object) -> integer or nil + * array.index {|element| ... } -> integer or nil + * array.index -> new_enumerator + * + * Returns the index of a specified element. * - * Returns the _index_ of the first object in +ary+ such that the object is - * == to +obj+. + * When argument +object+ is given but no block, + * returns the index of the first element +element+ + * for which object == element: + * a = [:foo, 'bar', 2, 'bar'] + * a.index('bar') # => 1 * - * If a block is given instead of an argument, returns the _index_ of the - * first object for which the block returns +true+. Returns +nil+ if no - * match is found. + * Returns +nil+ if no such element found. * - * See also Array#rindex. + * When both argument +object+ and a block are given, + * calls the block with each successive element; + * returns the index of the first element for which the block returns a truthy value: + * a = [:foo, 'bar', 2, 'bar'] + * a.index {|element| element == 'bar' } # => 1 * - * An Enumerator is returned if neither a block nor argument is given. + * Returns +nil+ if the block never returns a truthy value. * - * a = [ "a", "b", "c" ] - * a.index("b") #=> 1 - * a.index("z") #=> nil - * a.index {|x| x == "b"} #=> 1 + * When neither an argument nor a block is given, returns a new Enumerator: + * a = [:foo, 'bar', 2] + * e = a.index + * e # => # + * e.each {|element| element == 'bar' } # => 1 + * + * Array#find_index is an alias for Array#index. + * + * Related: #rindex. */ static VALUE @@ -1794,26 +2074,33 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.rindex(obj) -> int or nil - * ary.rindex {|item| block} -> int or nil - * ary.rindex -> Enumerator + * array.rindex(object) -> integer or nil + * array.rindex {|element| ... } -> integer or nil + * array.rindex -> new_enumerator + * + * Returns the index of the last element for which object == element. * - * Returns the _index_ of the last object in +self+ == to +obj+. + * When argument +object+ is given but no block, returns the index of the last such element found: + * a = [:foo, 'bar', 2, 'bar'] + * a.rindex('bar') # => 3 * - * If a block is given instead of an argument, returns the _index_ of the - * first object for which the block returns +true+, starting from the last - * object. + * Returns +nil+ if no such object found. * - * Returns +nil+ if no match is found. + * When a block is given but no argument, 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'] + * a.rindex {|element| element == 'bar' } # => 3 * - * See also Array#index. + * Returns +nil+ if the block never returns a truthy value. * - * If neither block nor argument is given, an Enumerator is returned instead. + * When neither an argument nor a block is given, returns a new \Enumerator: * - * a = [ "a", "b", "b", "b", "c" ] - * a.rindex("b") #=> 3 - * a.rindex("z") #=> nil - * a.rindex {|x| x == "b"} #=> 3 + * a = [:foo, 'bar', 2, 'bar'] + * e = a.rindex + * e # => # + * e.each {|element| element == 'bar' } # => 3 + * + * Related: #index. */ static VALUE @@ -1943,14 +2230,6 @@ rb_ary_set_len(VALUE ary, long len) ARY_SET_LEN(ary, len); } -/*! - * expands or shrinks \a ary to \a len elements. - * expanded region will be filled with Qnil. - * \param ary an array - * \param len new size - * \return \a ary - * \post the size of \a ary is \a len. - */ VALUE rb_ary_resize(VALUE ary, long len) { @@ -1981,8 +2260,8 @@ rb_ary_resize(VALUE ary, long len) } else { if (olen > len + ARY_DEFAULT_SIZE) { - ary_heap_realloc(ary, len); - ARY_SET_CAPA(ary, len); + size_t new_capa = ary_heap_realloc(ary, len); + ARY_SET_CAPA(ary, new_capa); } ARY_SET_HEAP_LEN(ary, len); } @@ -1990,88 +2269,175 @@ rb_ary_resize(VALUE ary, long len) return ary; } +static VALUE +ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val) +{ + rb_ary_store(ary, key, val); + return val; +} + +static VALUE +ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) +{ + VALUE rpl = rb_ary_to_ary(val); + rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl)); + RB_GC_GUARD(rpl); + return val; +} + /* * call-seq: - * ary[index] = obj -> obj - * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil - * ary[range] = obj or other_ary or nil -> obj or other_ary or nil - * - * Element Assignment --- Sets the element at +index+, or replaces a subarray - * from the +start+ index for +length+ elements, or replaces a subarray - * specified by the +range+ of indices. - * - * If indices are greater than the current capacity of the array, the array - * grows automatically. Elements are inserted into the array at +start+ if - * +length+ is zero. - * - * Negative indices will count backward from the end of the array. For - * +start+ and +range+ cases the starting index is just before an element. - * - * An IndexError is raised if a negative index points past the beginning of - * the array. - * - * See also Array#push, and Array#unshift. - * - * a = Array.new - * a[4] = "4"; #=> [nil, nil, nil, nil, "4"] - * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"] - * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"] - * a[0, 2] = "?" #=> ["?", 2, nil, "4"] - * a[0..2] = "A" #=> ["A", "4"] - * a[-1] = "Z" #=> ["A", "Z"] - * a[1..-1] = nil #=> ["A", nil] - * a[1..-1] = [] #=> ["A"] - * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"] - * a[3, 0] = "B" #=> [1, 2, "A", "B"] + * array[index] = object -> object + * array[start, length] = object -> object + * array[range] = object -> object + * + * Assigns elements in +self+; returns the given +object+. + * + * When \Integer argument +index+ is given, assigns +object+ to an element in +self+. + * + * If +index+ is non-negative, assigns +object+ the element at offset +index+: + * a = [:foo, 'bar', 2] + * a[0] = 'foo' # => "foo" + * a # => ["foo", "bar", 2] + * + * If +index+ is greater than self.length, extends the array: + * a = [:foo, 'bar', 2] + * a[7] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"] + * + * If +index+ is negative, counts backwards from the end of the array: + * a = [:foo, 'bar', 2] + * a[-1] = 'two' # => "two" + * a # => [:foo, "bar", "two"] + * + * 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+: + * a = [:foo, 'bar', 2] + * a[0, 2] = 'foo' # => "foo" + * a # => ["foo", 2] + * + * If +start+ is negative, counts backwards from the end of the array: + * a = [:foo, 'bar', 2] + * a[-2, 2] = 'foo' # => "foo" + * a # => [:foo, "foo"] + * + * If +start+ is non-negative and outside the array ( >= self.size), + * extends the array with +nil+, assigns +object+ at offset +start+, + * and ignores +length+: + * a = [:foo, 'bar', 2] + * a[6, 50] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, "foo"] + * + * If +length+ is zero, shifts elements at and following offset +start+ + * and assigns +object+ at offset +start+: + * a = [:foo, 'bar', 2] + * a[1, 0] = 'foo' # => "foo" + * a # => [:foo, "foo", "bar", 2] + * + * If +length+ is too large for the existing array, does not extend the array: + * a = [:foo, 'bar', 2] + * a[1, 5] = 'foo' # => "foo" + * a # => [:foo, "foo"] + * + * When \Range argument +range+ is given and +object+ is an \Array, + * removes length - 1 elements beginning at offset +start+, + * and assigns +object+ at offset +start+: + * a = [:foo, 'bar', 2] + * a[0..1] = 'foo' # => "foo" + * a # => ["foo", 2] + * + * if range.begin is negative, counts backwards from the end of the array: + * a = [:foo, 'bar', 2] + * a[-2..2] = 'foo' # => "foo" + * a # => [:foo, "foo"] + * + * If the array length is less than range.begin, + * assigns +object+ at offset range.begin, and ignores +length+: + * a = [:foo, 'bar', 2] + * a[6..50] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, "foo"] + * + * If range.end is zero, shifts elements at and following offset +start+ + * and assigns +object+ at offset +start+: + * a = [:foo, 'bar', 2] + * a[1..0] = 'foo' # => "foo" + * a # => [:foo, "foo", "bar", 2] + * + * If range.end is negative, assigns +object+ at offset +start+, + * retains range.end.abs -1 elements past that, and removes those beyond: + * a = [:foo, 'bar', 2] + * a[1..-1] = 'foo' # => "foo" + * a # => [:foo, "foo"] + * a = [:foo, 'bar', 2] + * a[1..-2] = 'foo' # => "foo" + * a # => [:foo, "foo", 2] + * a = [:foo, 'bar', 2] + * a[1..-3] = 'foo' # => "foo" + * a # => [:foo, "foo", "bar", 2] + * a = [:foo, 'bar', 2] + * + * If range.end is too large for the existing array, + * replaces array elements, but does not extend the array with +nil+ values: + * a = [:foo, 'bar', 2] + * a[1..5] = 'foo' # => "foo" + * a # => [:foo, "foo"] */ static VALUE rb_ary_aset(int argc, VALUE *argv, VALUE ary) { long offset, beg, len; - VALUE rpl; + rb_check_arity(argc, 2, 3); + rb_ary_modify_check(ary); if (argc == 3) { - rb_ary_modify_check(ary); beg = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); - goto range; + return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]); } - rb_check_arity(argc, 2, 2); - rb_ary_modify_check(ary); if (FIXNUM_P(argv[0])) { offset = FIX2LONG(argv[0]); - goto fixnum; + return ary_aset_by_rb_ary_store(ary, offset, argv[1]); } if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) { /* check if idx is Range */ - range: - rpl = rb_ary_to_ary(argv[argc-1]); - rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl)); - RB_GC_GUARD(rpl); - return argv[argc-1]; + return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]); } offset = NUM2LONG(argv[0]); -fixnum: - rb_ary_store(ary, offset, argv[1]); - return argv[1]; + return ary_aset_by_rb_ary_store(ary, offset, argv[1]); } /* * call-seq: - * ary.insert(index, obj...) -> ary - * - * Inserts the given values before the element with the given +index+. + * array.insert(index, *objects) -> self * - * Negative indices count backwards from the end of the array, where +-1+ is - * the last element. If a negative index is used, the given values will be - * inserted after that element, so using an index of +-1+ will insert the - * values at the end of the array. + * Inserts given +objects+ before or after the element at \Integer index +offset+; + * returns +self+. * - * a = %w{ a b c d } - * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"] - * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"] + * When +index+ is non-negative, inserts all given +objects+ + * before the element at offset +index+: + * a = [:foo, 'bar', 2] + * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2] + * + * 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] + * + * Does nothing if no objects given: + * a = [:foo, 'bar', 2] + * a.insert(1) + * a.insert(50) + * a.insert(-50) + * a # => [:foo, "bar", 2] + * + * When +index+ is negative, inserts all given +objects+ + * _after_ the element at offset index+self.size: + * a = [:foo, 'bar', 2] + * a.insert(-2, :bat, :bam) + * a # => [:foo, "bar", :bat, :bam, 2] */ static VALUE @@ -2109,20 +2475,41 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * ary.each {|item| block} -> ary - * ary.each -> Enumerator + * array.each {|element| ... } -> self + * array.each -> Enumerator + * + * Iterates over array elements. + * + * When a block given, passes each successive array element to the block; + * returns +self+: + * a = [:foo, 'bar', 2] + * a.each {|element| puts "#{element.class} #{element}" } * - * Calls the given block once for each element in +self+, passing that element - * as a parameter. Returns the array itself. + * Output: + * Symbol foo + * String bar + * Integer 2 * - * If no block is given, an Enumerator is returned. + * Allows the array to be modified during iteration: + * a = [:foo, 'bar', 2] + * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') } * - * a = [ "a", "b", "c" ] - * a.each {|x| print x, " -- " } + * Output: + * foo + * bar * - * produces: + * When no block given, returns a new \Enumerator: + * a = [:foo, 'bar', 2] + * e = a.each + * e # => # + * a1 = e.each {|element| puts "#{element.class} #{element}" } * - * a -- b -- c -- + * Output: + * Symbol foo + * String bar + * Integer 2 + * + * Related: #each_index, #reverse_each. */ VALUE @@ -2139,20 +2526,41 @@ rb_ary_each(VALUE ary) /* * call-seq: - * ary.each_index {|index| block} -> ary - * ary.each_index -> Enumerator + * array.each_index {|index| ... } -> self + * array.each_index -> Enumerator + * + * Iterates over array indexes. * - * Same as Array#each, but passes the +index+ of the element instead of the - * element itself. + * When a block given, passes each successive array index to the block; + * returns +self+: + * a = [:foo, 'bar', 2] + * a.each_index {|index| puts "#{index} #{a[index]}" } * - * An Enumerator is returned if no block is given. + * Output: + * 0 foo + * 1 bar + * 2 2 * - * a = [ "a", "b", "c" ] - * a.each_index {|x| print x, " -- " } + * Allows the array to be modified during iteration: + * a = [:foo, 'bar', 2] + * a.each_index {|index| puts index; a.clear if index > 0 } * - * produces: + * Output: + * 0 + * 1 * - * 0 -- 1 -- 2 -- + * 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 + * + * Related: #each, #reverse_each. */ static VALUE @@ -2169,17 +2577,40 @@ rb_ary_each_index(VALUE ary) /* * call-seq: - * ary.reverse_each {|item| block} -> ary - * ary.reverse_each -> Enumerator - * - * Same as Array#each, but traverses +self+ in reverse order. - * - * a = [ "a", "b", "c" ] - * a.reverse_each {|x| print x, " " } - * - * produces: - * - * c b a + * array.reverse_each {|element| ... } -> self + * array.reverse_each -> Enumerator + * + * Iterates backwards over array elements. + * + * When a block given, passes, 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 + * + * 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 = [:foo, 'bar', 2] + * e = a.reverse_each + * e # => # + * a1 = e.each {|element| puts "#{element.class} #{element}" } + * Output: + * Integer 2 + * String bar + * Symbol foo + * + * Related: #each, #each_index. */ static VALUE @@ -2202,12 +2633,9 @@ rb_ary_reverse_each(VALUE ary) /* * call-seq: - * ary.length -> int + * array.length -> an_integer * - * Returns the number of elements in +self+. May be zero. - * - * [ 1, 2, 3, 4, 5 ].length #=> 5 - * [].length #=> 0 + * Returns the count of elements in +self+. */ static VALUE @@ -2219,19 +2647,16 @@ rb_ary_length(VALUE ary) /* * call-seq: - * ary.empty? -> true or false - * - * Returns +true+ if +self+ contains no elements. + * array.empty? -> true or false * - * [].empty? #=> true + * Returns +true+ if the count of elements in +self+ is zero, + * +false+ otherwise. */ static VALUE rb_ary_empty_p(VALUE ary) -{ - if (RARRAY_LEN(ary) == 0) - return Qtrue; - return Qfalse; +{ + return RBOOL(RARRAY_LEN(ary) == 0); } VALUE @@ -2275,7 +2700,7 @@ recursive_join(VALUE obj, VALUE argp, int recur) return Qnil; } -static void +static long ary_join_0(VALUE ary, VALUE sep, long max, VALUE result) { long i; @@ -2284,10 +2709,40 @@ ary_join_0(VALUE ary, VALUE sep, long max, VALUE result) if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0)); for (i=0; i 0 && !NIL_P(sep)) rb_str_buf_append(result, sep); rb_str_buf_append(result, val); } + return i; +} + +static void +ary_join_1_str(VALUE dst, VALUE src, int *first) +{ + rb_str_buf_append(dst, src); + if (*first) { + rb_enc_copy(dst, src); + *first = FALSE; + } +} + +static void +ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first) +{ + if (val == ary) { + rb_raise(rb_eArgError, "recursive array join"); + } + else { + VALUE args[4]; + + *first = FALSE; + args[0] = val; + args[1] = sep; + args[2] = result; + args[3] = (VALUE)first; + rb_exec_recursive(recursive_join, obj, (VALUE)args); + } } static void @@ -2301,44 +2756,19 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first) val = RARRAY_AREF(ary, i); if (RB_TYPE_P(val, T_STRING)) { - str_join: - rb_str_buf_append(result, val); - if (*first) { - rb_enc_copy(result, val); - *first = FALSE; - } + ary_join_1_str(result, val, first); } else if (RB_TYPE_P(val, T_ARRAY)) { - obj = val; - ary_join: - if (val == ary) { - rb_raise(rb_eArgError, "recursive array join"); - } - else { - VALUE args[4]; - - *first = FALSE; - args[0] = val; - args[1] = sep; - args[2] = result; - args[3] = (VALUE)first; - rb_exec_recursive(recursive_join, obj, (VALUE)args); - } + ary_join_1_ary(val, ary, sep, result, val, first); } - else { - tmp = rb_check_string_type(val); - if (!NIL_P(tmp)) { - val = tmp; - goto str_join; - } - tmp = rb_check_array_type(val); - if (!NIL_P(tmp)) { - obj = val; - val = tmp; - goto ary_join; - } - val = rb_obj_as_string(val); - goto str_join; + else if (!NIL_P(tmp = rb_check_string_type(val))) { + ary_join_1_str(result, tmp, first); + } + else if (!NIL_P(tmp = rb_check_array_type(val))) { + ary_join_1_ary(val, ary, sep, result, tmp, first); + } + else { + ary_join_1_str(result, rb_obj_as_string(val), first); } } } @@ -2361,9 +2791,11 @@ rb_ary_join(VALUE ary, VALUE sep) if (NIL_P(tmp) || tmp != val) { int first; - result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10); + long n = RARRAY_LEN(ary); + if (i > n) i = n; + result = rb_str_buf_new(len + (n-i)*10); rb_enc_associate(result, rb_usascii_encoding()); - ary_join_0(ary, sep, i, result); + i = ary_join_0(ary, sep, i, result); first = i == 0; ary_join_1(ary, ary, sep, i, result, &first); return result; @@ -2382,22 +2814,27 @@ rb_ary_join(VALUE ary, VALUE sep) /* * call-seq: - * ary.join(separator=$,) -> str - * - * Returns a string created by converting each element of the array to - * a string, separated by the given +separator+. - * If the +separator+ is +nil+, it uses current $,. - * If both the +separator+ and $, are +nil+, - * it uses an empty string. - * - * [ "a", "b", "c" ].join #=> "abc" - * [ "a", "b", "c" ].join("-") #=> "a-b-c" - * - * For nested arrays, join is applied recursively: - * - * [ "a", [1, 2, [:x, :y]], "b" ].join("-") #=> "a-1-2-x-y-b" + * array.join ->new_string + * array.join(separator = $,) -> new_string + * + * Returns the new \String formed by joining the array elements after conversion. + * 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). + * + * With no argument, joins using the output field separator, $,: + * a = [:foo, 'bar', 2] + * $, # => nil + * a.join # => "foobar2" + * + * With \string argument +separator+, joins using that separator: + * a = [:foo, 'bar', 2] + * a.join("\n") # => "foo\nbar\n2" + * + * Joins recursively for nested Arrays: + * a = [:foo, [:bar, [:baz, :bat]]] + * a.join # => "foobarbazbat" */ - static VALUE rb_ary_join_m(int argc, VALUE *argv, VALUE ary) { @@ -2406,7 +2843,7 @@ rb_ary_join_m(int argc, VALUE *argv, VALUE ary) if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) { sep = rb_output_fs; if (!NIL_P(sep)) { - rb_warn("$, is set to non-nil value"); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value"); } } @@ -2433,13 +2870,14 @@ inspect_ary(VALUE ary, VALUE dummy, int recur) /* * call-seq: - * ary.inspect -> string - * ary.to_s -> string + * array.inspect -> new_string * - * Creates a string representation of +self+, by calling #inspect - * on each element. + * Returns the new \String formed by calling method #inspect + * on each array element: + * a = [:foo, 'bar', 2] + * a.inspect # => "[:foo, \"bar\", 2]" * - * [ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]" + * Array#to_s is an alias for Array#inspect. */ static VALUE @@ -2457,11 +2895,20 @@ rb_ary_to_s(VALUE ary) /* * call-seq: - * ary.to_a -> ary - * - * Returns +self+. - * - * If called on a subclass of Array, converts the receiver to an Array object. + * 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] + * + * 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 */ static VALUE @@ -2477,20 +2924,24 @@ rb_ary_to_a(VALUE ary) /* * call-seq: - * ary.to_h -> hash - * ary.to_h {|item| block } -> hash - * - * Returns the result of interpreting ary as an array of - * [key, value] pairs. - * - * [[:foo, :bar], [1, 2]].to_h - * # => {:foo => :bar, 1 => 2} - * - * If a block is given, the results of the block on each element of - * the array will be used as pairs. - * - * ["foo", "bar"].to_h {|s| [s.ord, s]} - * # => {102=>"foo", 98=>"bar"} + * array.to_h -> new_hash + * array.to_h {|item| ... } -> new_hash + * + * 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: + * 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}} + * + * 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: + * [].to_h # => {} + * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']] + * h = a.to_h + * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"} */ static VALUE @@ -2519,7 +2970,7 @@ rb_ary_to_h(VALUE ary) /* * call-seq: - * ary.to_ary -> ary + * array.to_ary -> self * * Returns +self+. */ @@ -2558,13 +3009,11 @@ rb_ary_reverse(VALUE ary) /* * call-seq: - * ary.reverse! -> ary - * - * Reverses +self+ in place. + * array.reverse! -> self * - * a = [ "a", "b", "c" ] - * a.reverse! #=> ["c", "b", "a"] - * a #=> ["c", "b", "a"] + * Reverses +self+ in place: + * a = ['foo', 'bar', 'two'] + * a.reverse! # => ["two", "bar", "foo"] */ static VALUE @@ -2575,12 +3024,12 @@ rb_ary_reverse_bang(VALUE ary) /* * call-seq: - * ary.reverse -> new_ary + * array.reverse -> new_array * - * Returns a new array containing +self+'s elements in reverse order. - * - * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"] - * [ 1 ].reverse #=> [1] + * Returns a new \Array with the elements of +self+ in reverse order. + * a = ['foo', 'bar', 'two'] + * a1 = a.reverse + * a1 # => ["two", "bar", "foo"] */ static VALUE @@ -2607,10 +3056,22 @@ rotate_count(long cnt, long len) static void ary_rotate_ptr(VALUE *ptr, long len, long cnt) { - --len; - if (cnt < len) ary_reverse(ptr + cnt, ptr + len); - if (--cnt > 0) ary_reverse(ptr, ptr + cnt); - if (len > 0) ary_reverse(ptr, ptr + len); + if (cnt == 1) { + VALUE tmp = *ptr; + memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1)); + *(ptr + len - 1) = tmp; + } + else if (cnt == len - 1) { + VALUE tmp = *(ptr + len - 1); + memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1)); + *ptr = tmp; + } + else { + --len; + if (cnt < len) ary_reverse(ptr + cnt, ptr + len); + if (--cnt > 0) ary_reverse(ptr, ptr + cnt); + if (len > 0) ary_reverse(ptr, ptr + len); + } } VALUE @@ -2620,7 +3081,7 @@ rb_ary_rotate(VALUE ary, long cnt) if (cnt != 0) { long len = RARRAY_LEN(ary); - if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) { + if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) { RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt)); return ary; } @@ -2630,19 +3091,41 @@ rb_ary_rotate(VALUE ary, long cnt) /* * call-seq: - * ary.rotate!(count=1) -> ary - * - * Rotates +self+ in place so that the element at +count+ comes first, and - * returns +self+. - * - * If +count+ is negative then it rotates in the opposite direction, starting - * from the end of the array where +-1+ is the last element. - * - * a = [ "a", "b", "c", "d" ] - * a.rotate! #=> ["b", "c", "d", "a"] - * a #=> ["b", "c", "d", "a"] - * a.rotate!(2) #=> ["d", "a", "b", "c"] - * a.rotate!(-3) #=> ["a", "b", "c", "d"] + * array.rotate! -> self + * array.rotate!(count) -> 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+, + * rotates +count+ elements from the beginning to the end: + * a = [:foo, 'bar', 2] + * a.rotate!(2) + * a # => [2, :foo, "bar"] + * + * If +count+ is large, uses count % array.size as the count: + * a = [:foo, 'bar', 2] + * a.rotate!(20) + * a # => [2, :foo, "bar"] + * + * If +count+ is zero, returns +self+ unmodified: + * a = [:foo, 'bar', 2] + * a.rotate!(0) + * a # => [:foo, "bar", 2] + * + * When given a negative Integer +count+, rotates in the opposite direction, + * from end to beginning: + * a = [:foo, 'bar', 2] + * a.rotate!(-2) + * a # => ["bar", 2, :foo] + * + * 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] */ static VALUE @@ -2655,19 +3138,44 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.rotate(count=1) -> new_ary - * - * Returns a new array by rotating +self+ so that the element at +count+ is - * the first element of the new array. - * - * If +count+ is negative then it rotates in the opposite direction, starting - * from the end of +self+ where +-1+ is the last element. - * - * a = [ "a", "b", "c", "d" ] - * a.rotate #=> ["b", "c", "d", "a"] - * a #=> ["a", "b", "c", "d"] - * a.rotate(2) #=> ["c", "d", "a", "b"] - * a.rotate(-3) #=> ["b", "c", "d", "a"] + * array.rotate -> new_array + * array.rotate(count) -> new_array + * + * 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: + * a = [:foo, 'bar', 2] + * a1 = a.rotate(2) + * a1 # => [2, :foo, "bar"] + * + * If +count+ is large, uses count % array.size as the count: + * a = [:foo, 'bar', 2] + * a1 = a.rotate(20) + * a1 # => [2, :foo, "bar"] + * + * If +count+ is zero, returns a copy of +self+, unmodified: + * a = [:foo, 'bar', 2] + * a1 = a.rotate(0) + * a1 # => [:foo, "bar", 2] + * + * When given a negative \Integer +count+, rotates in the opposite direction, + * from end to beginning: + * a = [:foo, 'bar', 2] + * a1 = a.rotate(-2) + * a1 # => ["bar", 2, :foo] + * + * 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] */ static VALUE @@ -2693,6 +3201,7 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary) struct ary_sort_data { VALUE ary; + VALUE receiver; struct cmp_opt_data cmp_opt; }; @@ -2705,6 +3214,15 @@ sort_reentered(VALUE ary) return Qnil; } +static void +sort_returned(struct ary_sort_data *data) +{ + if (rb_obj_frozen_p(data->receiver)) { + rb_raise(rb_eFrozenError, "array frozen during sort"); + } + sort_reentered(data->ary); +} + static int sort_1(const void *ap, const void *bp, void *dummy) { @@ -2718,7 +3236,7 @@ sort_1(const void *ap, const void *bp, void *dummy) args[1] = b; retval = rb_yield_values2(2, args); n = rb_cmpint(retval, a, b); - sort_reentered(data->ary); + sort_returned(data); return n; } @@ -2730,7 +3248,7 @@ sort_2(const void *ap, const void *bp, void *dummy) VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp; int n; - if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Fixnum)) { + if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Integer)) { if ((long)a > (long)b) return 1; if ((long)a < (long)b) return -1; return 0; @@ -2744,33 +3262,45 @@ sort_2(const void *ap, const void *bp, void *dummy) retval = rb_funcallv(a, id_cmp, 1, &b); n = rb_cmpint(retval, a, b); - sort_reentered(data->ary); + sort_returned(data); return n; } /* * call-seq: - * ary.sort! -> ary - * ary.sort! {|a, b| block} -> ary - * - * Sorts +self+ in place. - * - * Comparisons for the sort will be done using the <=> operator - * or using an optional code block. - * - * The block must implement a comparison between +a+ and +b+ and return - * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+ - * are equivalent, or an integer greater than 0 when +a+ follows +b+. - * - * The result is not guaranteed to be stable. When the comparison of two - * elements returns +0+, the order of the elements is unpredictable. - * - * ary = [ "d", "a", "e", "c", "b" ] - * ary.sort! #=> ["a", "b", "c", "d", "e"] - * ary.sort! {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"] - * - * See also Enumerable#sort_by. + * 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): + * 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"] */ VALUE @@ -2784,6 +3314,7 @@ rb_ary_sort_bang(VALUE ary) long len = RARRAY_LEN(ary); RBASIC_CLEAR_CLASS(tmp); data.ary = tmp; + data.receiver = ary; data.cmp_opt.opt_methods = 0; data.cmp_opt.opt_inited = 0; RARRAY_PTR_USE(tmp, ptr, { @@ -2835,31 +3366,40 @@ rb_ary_sort_bang(VALUE ary) /* * call-seq: - * ary.sort -> new_ary - * ary.sort {|a, b| block} -> new_ary - * - * Returns a new array created by sorting +self+. - * - * Comparisons for the sort will be done using the <=> operator - * or using an optional code block. - * - * The block must implement a comparison between +a+ and +b+ and return - * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+ - * are equivalent, or an integer greater than 0 when +a+ follows +b+. - * - * The result is not guaranteed to be stable. When the comparison of two - * elements returns +0+, the order of the elements is unpredictable. - * - * ary = [ "d", "a", "e", "c", "b" ] - * ary.sort #=> ["a", "b", "c", "d", "e"] - * ary.sort {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"] - * - * To produce the reverse order, the following can also be used - * (and may be faster): - * - * ary.sort.reverse! #=> ["e", "d", "c", "b", "a"] - * - * See also Enumerable#sort_by. + * array.sort -> new_array + * array.sort {|a, b| ... } -> new_array + * + * Returns a new \Array whose elements are those from +self+, sorted. + * + * With no block, compares elements using operator <=> + * (see Comparable): + * a = 'abcde'.split('').shuffle + * a # => ["e", "b", "d", "a", "c"] + * a1 = a.sort + * a1 # => ["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"] + * 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"] + * + * 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"] + * a1 = a.sort {|a, b| 0 } + * a1 # => ["c", "e", "b", "d", "a"] + * + * Related: Enumerable#sort_by. */ VALUE @@ -2874,55 +3414,12 @@ static VALUE rb_ary_bsearch_index(VALUE ary); /* * call-seq: - * ary.bsearch {|x| block } -> elem - * - * By using binary search, finds a value from this array which meets - * the given condition in O(log n) where n is the size of the array. - * - * You can use this method in two modes: a find-minimum mode and - * a find-any mode. In either case, the elements of the array must be - * monotone (or sorted) with respect to the block. - * - * In find-minimum mode (this is a good choice for typical use cases), - * the block must always return true or false, and there must be an index i - * (0 <= i <= ary.size) so that: - * - * - the block returns false for any element whose index is less than - * i, and - * - the block returns true for any element whose index is greater - * than or equal to i. - * - * This method returns the i-th element. If i is equal to ary.size, - * it returns nil. - * - * ary = [0, 4, 7, 10, 12] - * ary.bsearch {|x| x >= 4 } #=> 4 - * ary.bsearch {|x| x >= 6 } #=> 7 - * ary.bsearch {|x| x >= -1 } #=> 0 - * ary.bsearch {|x| x >= 100 } #=> nil - * - * In find-any mode (this behaves like libc's bsearch(3)), the block - * must always return a number, and there must be two indices i and j - * (0 <= i <= j <= ary.size) so that: - * - * - the block returns a positive number for ary[k] if 0 <= k < i, - * - the block returns zero for ary[k] if i <= k < j, and - * - the block returns a negative number for ary[k] if - * j <= k < ary.size. - * - * Under this condition, this method returns any element whose index - * is within i...j. If i is equal to j (i.e., there is no element - * that satisfies the block), this method returns nil. - * - * ary = [0, 4, 7, 10, 12] - * # try to find v such that 4 <= v < 8 - * ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7 - * # try to find v such that 8 <= v < 10 - * ary.bsearch {|x| 4 - x / 2 } #=> nil - * - * You must not mix the two modes at a time; the block must always - * return either true/false, or always return a number. It is - * undefined which value is actually picked up at each iteration. + * array.bsearch {|element| ... } -> object + * array.bsearch -> new_enumerator + * + * Returns an element from +self+ selected by a binary search. + * + * See {Binary Searching}[rdoc-ref:bsearch.rdoc]. */ static VALUE @@ -2938,15 +3435,11 @@ rb_ary_bsearch(VALUE ary) /* * call-seq: - * ary.bsearch_index {|x| block } -> int or nil + * array.bsearch_index {|element| ... } -> integer or nil + * array.bsearch_index -> new_enumerator * - * By using binary search, finds an index of a value from this array which - * meets the given condition in O(log n) where n is the size of the array. - * - * It supports two modes, depending on the nature of the block. They are - * exactly the same as in the case of the #bsearch method, with the only difference - * being that this method returns the index of the element instead of the - * element itself. For more details consult the documentation for #bsearch. + * Searches +self+ as described at method #bsearch, + * but returns the _index_ of the found element instead of the element itself. */ static VALUE @@ -2969,7 +3462,7 @@ rb_ary_bsearch_index(VALUE ary) satisfied = 1; smaller = 1; } - else if (v == Qfalse || v == Qnil) { + else if (!RTEST(v)) { smaller = 0; } else if (rb_obj_is_kind_of(v, rb_cNumeric)) { @@ -3005,18 +3498,26 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy)) /* * call-seq: - * ary.sort_by! {|obj| block} -> ary - * ary.sort_by! -> Enumerator + * array.sort_by! {|element| ... } -> self + * array.sort_by! -> new_enumerator + * + * Sorts the elements of +self+ in place, + * using an ordering determined by the block; returns self. * - * Sorts +self+ in place using a set of keys generated by mapping the - * values in +self+ through the given block. + * Calls the block with each successive element; + * sorts elements based on the values returned from the block. * - * The result is not guaranteed to be stable. When two keys are equal, - * the order of the corresponding elements is unpredictable. + * For duplicates returned by the block, the ordering is indeterminate, and may be unstable. * - * If no block is given, an Enumerator is returned instead. + * This example sorts strings based on their sizes: + * a = ['aaaa', 'bbb', 'cc', 'd'] + * a.sort_by! {|element| element.size } + * a # => ["d", "cc", "bbb", "aaaa"] * - * See also Enumerable#sort_by. + * Returns a new \Enumerator if no block given: + * + * a = ['aaaa', 'bbb', 'cc', 'd'] + * a.sort_by! # => # */ static VALUE @@ -3034,23 +3535,21 @@ rb_ary_sort_by_bang(VALUE ary) /* * call-seq: - * ary.collect {|item| block} -> new_ary - * ary.map {|item| block} -> new_ary - * ary.collect -> Enumerator - * ary.map -> Enumerator - * - * Invokes the given block once for each element of +self+. + * array.map {|element| ... } -> new_array + * array.map -> new_enumerator * - * Creates a new array containing the values returned by the block. + * Calls the block, if given, 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] * - * See also Enumerable#collect. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2] + * a1 = a.map + * a1 # => # * - * If no block is given, an Enumerator is returned instead. - * - * a = [ "a", "b", "c", "d" ] - * a.collect {|x| x + "!"} #=> ["a!", "b!", "c!", "d!"] - * a.map.with_index {|x, i| x * i} #=> ["", "b", "cc", "ddd"] - * a #=> ["a", "b", "c", "d"] + * Array#collect is an alias for Array#map. */ static VALUE @@ -3070,23 +3569,20 @@ rb_ary_collect(VALUE ary) /* * call-seq: - * ary.collect! {|item| block } -> ary - * ary.map! {|item| block } -> ary - * ary.collect! -> Enumerator - * ary.map! -> Enumerator - * - * Invokes the given block once for each element of +self+, replacing the - * element with the value returned by the block. + * array.map! {|element| ... } -> self + * array.map! -> new_enumerator * - * See also Enumerable#collect. + * Calls the block, if given, with each element; + * replaces the element with the block's return value: + * a = [:foo, 'bar', 2] + * a.map! { |element| element.class } # => [Symbol, String, Integer] * - * If no block is given, an Enumerator is returned instead. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2] + * a1 = a.map! + * a1 # => # * - * a = [ "a", "b", "c", "d" ] - * a.map! {|x| x + "!" } - * a #=> [ "a!", "b!", "c!", "d!" ] - * a.collect!.with_index {|x, i| x[0...i] } - * a #=> ["", "b", "c!", "d!"] + * Array#collect! is an alias for Array#map!. */ static VALUE @@ -3158,20 +3654,38 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx) /* * call-seq: - * ary.values_at(selector, ...) -> new_ary + * array.values_at(*indexes) -> new_array * - * Returns an array containing the elements in +self+ corresponding to the - * given +selector+(s). + * Returns a new \Array whose elements are the elements + * of +self+ at the given \Integer or \Range +indexes+. * - * The selectors may be either integer indices or ranges. + * For each positive +index+, returns the element at offset +index+: + * a = [:foo, 'bar', 2] + * a.values_at(0, 2) # => [:foo, 2] + * a.values_at(0..1) # => [:foo, "bar"] * - * See also Array#select. + * The given +indexes+ may be in any order, and may repeat: + * 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] * - * a = %w{ a b c d e f } - * a.values_at(1, 3, 5) # => ["b", "d", "f"] - * a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil] - * a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil] - * a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"] + * Assigns +nil+ for an +index+ that is too large: + * a = [:foo, 'bar', 2] + * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil] + * + * Returns a new empty \Array if no arguments given. + * + * For each negative +index+, counts backward from the end of the array: + * a = [:foo, 'bar', 2] + * a.values_at(-1, -3) # => [2, :foo] + * + * Assigns +nil+ for an +index+ that is too small: + * a = [:foo, 'bar', 2] + * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2] + * + * The given +indexes+ may have a mixture of signs: + * a = [:foo, 'bar', 2] + * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2] */ static VALUE @@ -3189,22 +3703,19 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.select {|item| block} -> new_ary - * ary.select -> Enumerator - * ary.filter {|item| block} -> new_ary - * ary.filter -> Enumerator + * array.select {|element| ... } -> new_array + * array.select -> new_enumerator * - * Returns a new array containing all elements of +ary+ - * for which the given +block+ returns a true value. + * Calls the block, if given, 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] * - * If no block is given, an Enumerator is returned instead. - * - * [1,2,3,4,5].select {|num| num.even? } #=> [2, 4] - * - * a = %w[ a b c d e f ] - * a.select {|v| v =~ /[aeiou]/ } #=> ["a", "e"] - * - * See also Enumerable#select. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2, :bam] + * a.select # => # * * Array#filter is an alias for Array#select. */ @@ -3258,6 +3769,7 @@ select_bang_ensure(VALUE a) if (i2 < len && i2 < i1) { long tail = 0; + rb_ary_modify(ary); if (i1 < len) { tail = len - i1; RARRAY_PTR_USE_TRANSIENT(ary, ptr, { @@ -3271,21 +3783,21 @@ select_bang_ensure(VALUE a) /* * call-seq: - * ary.select! {|item| block } -> ary or nil - * ary.select! -> Enumerator - * ary.filter! {|item| block } -> ary or nil - * ary.filter! -> Enumerator + * array.select! {|element| ... } -> self or nil + * array.select! -> new_enumerator * - * Invokes the given block passing in successive elements from +self+, - * deleting elements for which the block returns a +false+ value. + * Calls the block, if given with each element of +self+; + * removes from +self+ those elements for which the block returns +false+ or +nil+. * - * The array may not be changed instantly every time the block is called. + * Returns +self+ if any elements were removed: + * a = [:foo, 'bar', 2, :bam] + * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam] * - * If changes were made, it will return +self+, otherwise it returns +nil+. + * Returns +nil+ if no elements were removed. * - * If no block is given, an Enumerator is returned instead. - * - * See also Array#keep_if. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2, :bam] + * a.select! # => # * * Array#filter! is an alias for Array#select!. */ @@ -3305,19 +3817,17 @@ rb_ary_select_bang(VALUE ary) /* * call-seq: - * ary.keep_if {|item| block} -> ary - * ary.keep_if -> Enumerator - * - * Deletes every element of +self+ for which the given block evaluates to - * +false+, and returns +self+. + * array.keep_if {|element| ... } -> self + * array.keep_if -> new_enumeration * - * If no block is given, an Enumerator is returned instead. + * Retains those elements for which the block returns a truthy value; + * deletes all other elements; returns +self+: + * a = [:foo, 'bar', 2, :bam] + * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam] * - * a = %w[ a b c d e f ] - * a.keep_if {|v| v =~ /[aeiou]/ } #=> ["a", "e"] - * a #=> ["a", "e"] - * - * See also Array#select!. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2, :bam] + * a.keep_if # => # */ static VALUE @@ -3343,22 +3853,34 @@ ary_resize_smaller(VALUE ary, long len) /* * call-seq: - * ary.delete(obj) -> item or nil - * ary.delete(obj) {block} -> item or result of block - * - * Deletes all items from +self+ that are equal to +obj+. - * - * Returns the last deleted item, or +nil+ if no matching item is found. - * - * If the optional code block is given, the result of the block is returned if - * the item is not found. (To remove +nil+ elements and get an informative - * return value, use Array#compact!) - * - * a = [ "a", "b", "b", "b", "c" ] - * a.delete("b") #=> "b" - * a #=> ["a", "c"] - * a.delete("z") #=> nil - * a.delete("z") {"not found"} #=> "not found" + * array.delete(obj) -> deleted_object + * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return + * + * Removes zero or more elements from +self+; returns +self+. + * + * When no block is given, + * removes from +self+ each element +ele+ such that ele == obj; + * returns the last deleted element: + * s1 = 'bar'; s2 = 'bar' + * a = [:foo, s1, 2, s2] + * a.delete('bar') # => "bar" + * a # => [:foo, 2] + * + * Returns +nil+ if no elements removed. + * + * When a block is given, + * removes from +self+ each element +ele+ such that ele == obj. + * + * If any such elements are found, ignores the block + * and returns the last deleted element: + * s1 = 'bar'; s2 = 'bar' + * a = [:foo, s1, 2, s2] + * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' } + * a # => [:foo, 2] + * + * If no such elements are found, returns the block's return value: + * a = [:foo, 'bar', 2] + * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found" */ VALUE @@ -3439,17 +3961,23 @@ rb_ary_delete_at(VALUE ary, long pos) /* * call-seq: - * ary.delete_at(index) -> obj or nil + * array.delete_at(index) -> deleted_object or nil + * + * Deletes an element from +self+, per the given \Integer +index+. * - * Deletes the element at the specified +index+, returning that element, or - * +nil+ if the +index+ is out of range. + * When +index+ is non-negative, deletes the element at offset +index+: + * a = [:foo, 'bar', 2] + * a.delete_at(1) # => "bar" + * a # => [:foo, 2] * - * See also Array#slice! + * If index is too large, returns +nil+. * - * a = ["ant", "bat", "cat", "dog"] - * a.delete_at(2) #=> "cat" - * a #=> ["ant", "bat", "dog"] - * a.delete_at(99) #=> 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. */ static VALUE @@ -3458,63 +3986,118 @@ rb_ary_delete_at_m(VALUE ary, VALUE pos) return rb_ary_delete_at(ary, NUM2LONG(pos)); } +static VALUE +ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len) +{ + const long orig_len = RARRAY_LEN(ary); + + if (len < 0) { + return Qnil; + } + else if (pos < -orig_len) { + return Qnil; + } + else if (pos < 0) { + pos += orig_len; + } + else if (orig_len < pos) { + return Qnil; + } + if (orig_len < pos + len) { + len = orig_len - pos; + } + if (len == 0) { + return rb_ary_new2(0); + } + else { + VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos); + rb_ary_splice(ary, pos, len, 0, 0); + return arg2; + } +} + /* * call-seq: - * ary.slice!(index) -> obj or nil - * ary.slice!(start, length) -> new_ary or nil - * ary.slice!(range) -> new_ary or nil - * - * Deletes the element(s) given by an +index+ (optionally up to +length+ - * elements) or by a +range+. - * - * Returns the deleted object (or objects), or +nil+ if the +index+ is out of - * range. - * - * a = [ "a", "b", "c" ] - * a.slice!(1) #=> "b" - * a #=> ["a", "c"] - * a.slice!(-1) #=> "c" - * a #=> ["a"] - * a.slice!(100) #=> nil - * a #=> ["a"] + * array.slice!(n) -> object or nil + * array.slice!(start, length) -> new_array or nil + * array.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+: + * a = [:foo, 'bar', 2] + * a.slice!(1) # => "bar" + * a # => [:foo, 2] + * + * If +n+ is negative, counts backwards from the end of +self+: + * a = [:foo, 'bar', 2] + * a.slice!(-1) # => 2 + * a # => [:foo, "bar"] + * + * If +n+ 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: + * a = [:foo, 'bar', 2] + * a.slice!(0, 2) # => [:foo, "bar"] + * a # => [2] + * + * 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] + * + * If start == a.size and +length+ is non-negative, + * 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: + * a = [:foo, 'bar', 2] + * a.slice!(1..2) # => ["bar", 2] + * a # => [:foo] + * + * If range.start == a.size, returns a new empty \Array. + * + * If range.start is larger than the array size, returns +nil+. + * + * If range.end is negative, counts backwards from the end of the array: + * a = [:foo, 'bar', 2] + * a.slice!(0..-2) # => [:foo, "bar"] + * a # => [2] + * + * If range.start is negative, + * calculates the start index backwards from the end of the array: + * a = [:foo, 'bar', 2] + * a.slice!(-2..2) # => ["bar", 2] + * a # => [:foo] */ static VALUE rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary) { - VALUE arg1, arg2; - long pos, len, orig_len; + VALUE arg1; + long pos, len; rb_ary_modify_check(ary); + rb_check_arity(argc, 1, 2); + arg1 = argv[0]; + if (argc == 2) { pos = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); - delete_pos_len: - if (len < 0) return Qnil; - orig_len = RARRAY_LEN(ary); - if (pos < 0) { - pos += orig_len; - if (pos < 0) return Qnil; - } - else if (orig_len < pos) return Qnil; - if (orig_len < pos + len) { - len = orig_len - pos; - } - if (len == 0) return rb_ary_new2(0); - arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos); - RBASIC_SET_CLASS(arg2, rb_obj_class(ary)); - rb_ary_splice(ary, pos, len, 0, 0); - return arg2; + return ary_slice_bang_by_rb_ary_splice(ary, pos, len); } - rb_check_arity(argc, 1, 2); - arg1 = argv[0]; - if (!FIXNUM_P(arg1)) { switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) { case Qtrue: /* valid range */ - goto delete_pos_len; + return ary_slice_bang_by_rb_ary_splice(ary, pos, len); case Qnil: /* invalid range */ return Qnil; @@ -3572,17 +4155,20 @@ ary_reject_bang(VALUE ary) /* * call-seq: - * ary.reject! {|item| block} -> ary or nil - * ary.reject! -> Enumerator + * array.reject! {|element| ... } -> self or nil + * array.reject! -> new_enumerator * - * Deletes every element of +self+ for which the block evaluates to +true+, - * if no changes were made returns +nil+. + * Removes each element for which the block returns a truthy value. * - * The array may not be changed instantly every time the block is called. + * Returns +self+ if any elements removed: + * a = [:foo, 'bar', 2, 'bat'] + * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2] * - * See also Enumerable#reject and Array#delete_if. + * Returns +nil+ if no elements removed. * - * If no block is given, an Enumerator is returned instead. + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2] + * a.reject! # => # */ static VALUE @@ -3595,15 +4181,18 @@ rb_ary_reject_bang(VALUE ary) /* * call-seq: - * ary.reject {|item| block } -> new_ary - * ary.reject -> Enumerator - * - * Returns a new array containing the items in +self+ for which the given - * block is not +true+. The ordering of non-rejected elements is maintained. - * - * See also Array#delete_if - * - * If no block is given, an Enumerator is returned instead. + * array.reject {|element| ... } -> new_array + * array.reject -> new_enumerator + * + * 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 # => # */ static VALUE @@ -3619,20 +4208,17 @@ rb_ary_reject(VALUE ary) /* * call-seq: - * ary.delete_if {|item| block} -> ary - * ary.delete_if -> Enumerator - * - * Deletes every element of +self+ for which block evaluates to +true+. + * array.delete_if {|element| ... } -> self + * array.delete_if -> Enumerator * - * The array is changed instantly every time the block is called, not after - * the iteration is over. + * Removes each element in +self+ for which 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] * - * See also Array#reject! - * - * If no block is given, an Enumerator is returned instead. - * - * scores = [ 97, 42, 75 ] - * scores.delete_if {|score| score < 80 } #=> [97] + * Returns a new \Enumerator if no block given: + * a = [:foo, 'bar', 2] + * a.delete_if # => # */ static VALUE @@ -3648,10 +4234,9 @@ static VALUE take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg)) { VALUE *args = (VALUE *)cbarg; - if (args[1] == 0) rb_iter_break(); - else args[1]--; if (argc > 1) val = rb_ary_new4(argc, argv); rb_ary_push(args[0], val); + if (--args[1] == 0) rb_iter_break(); return Qnil; } @@ -3661,6 +4246,7 @@ take_items(VALUE obj, long n) VALUE result = rb_check_array_type(obj); VALUE args[2]; + if (n == 0) return result; if (!NIL_P(result)) return rb_ary_subseq(result, 0, n); result = rb_ary_new2(n); args[0] = result; args[1] = (VALUE)n; @@ -3673,26 +4259,51 @@ take_items(VALUE obj, long n) /* * call-seq: - * ary.zip(arg, ...) -> new_ary - * ary.zip(arg, ...) {|arr| block} -> nil - * - * Converts any arguments to arrays, then merges elements of +self+ with - * corresponding elements from each argument. - * - * This generates a sequence of ary.size _n_-element arrays, - * where _n_ is one more than the count of arguments. - * - * If the size of any argument is less than the size of the initial array, - * +nil+ values are supplied. - * - * If a block is given, it is invoked for each output +array+, otherwise an - * array of arrays is returned. - * - * a = [ 4, 5, 6 ] - * b = [ 7, 8, 9 ] - * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]] - * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]] - * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]] + * array.zip(*other_arrays) -> new_array + * array.zip(*other_arrays) {|other_array| ... } -> nil + * + * When no block given, returns a new \Array +new_array+ of size self.size + * whose elements are Arrays. + * + * Each nested array new_array[n] is of size other_arrays.size+1, + * and contains: + * - The _nth_ element of +self+. + * - The _nth_ element of each of the +other_arrays+. + * + * If all +other_arrays+ and +self+ are the same size: + * 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]] + * + * If any array in +other_arrays+ is smaller than +self+, + * fills to self.size with +nil+: + * 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]] + * + * If any array in +other_arrays+ is larger than +self+, + * its trailing elements are ignored: + * 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]] + * + * When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil + * 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] */ static VALUE @@ -3755,15 +4366,12 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.transpose -> new_ary - * - * Assumes that +self+ is an array of arrays and transposes the rows and - * columns. + * array.transpose -> new_array * - * a = [[1,2], [3,4], [5,6]] - * a.transpose #=> [[1, 3, 5], [2, 4, 6]] - * - * If the length of the subarrays don't match, an IndexError is raised. + * Transposes the rows and columns in an \Array of Arrays; + * the nested Arrays must all be the same size: + * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]] + * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]] */ static VALUE @@ -3796,15 +4404,11 @@ rb_ary_transpose(VALUE ary) /* * call-seq: - * ary.replace(other_ary) -> ary - * ary.initialize_copy(other_ary) -> ary - * - * Replaces the contents of +self+ with the contents of +other_ary+, - * truncating or expanding if necessary. + * array.replace(other_array) -> self * - * a = [ "a", "b", "c", "d", "e" ] - * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"] - * a #=> ["x", "y", "z"] + * Replaces the content of +self+ with the content of +other_array+; returns +self+: + * a = [:foo, 'bar', 2] + * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3] */ VALUE @@ -3850,12 +4454,11 @@ rb_ary_replace(VALUE copy, VALUE orig) /* * call-seq: - * ary.clear -> ary + * array.clear -> self * - * Removes all elements from +self+. - * - * a = [ "a", "b", "c", "d", "e" ] - * a.clear #=> [ ] + * Removes all elements from +self+: + * a = [:foo, 'bar', 2] + * a.clear # => [] */ VALUE @@ -3881,32 +4484,171 @@ rb_ary_clear(VALUE ary) /* * call-seq: - * ary.fill(obj) -> ary - * ary.fill(obj, start [, length]) -> ary - * ary.fill(obj, range) -> ary - * ary.fill {|index| block} -> ary - * ary.fill(start [, length]) {|index| block} -> ary - * ary.fill(range) {|index| block} -> ary - * - * The first three forms set the selected elements of +self+ (which - * may be the entire array) to +obj+. - * - * A +start+ of +nil+ is equivalent to zero. - * - * A +length+ of +nil+ is equivalent to the length of the array. - * - * The last three forms fill the array with the value of the given block, - * which is passed the absolute index of each element to be filled. - * - * Negative values of +start+ count from the end of the array, where +-1+ is - * the last element. - * - * a = [ "a", "b", "c", "d" ] - * a.fill("x") #=> ["x", "x", "x", "x"] - * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"] - * a.fill("y", 0..1) #=> ["y", "y", "z", "z"] - * a.fill {|i| i*i} #=> [0, 1, 4, 9] - * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27] + * 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] + * + * If +start+ is too large (start >= array.size), does nothing: + * 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"] + * + * If +start+ is negative, counts from the end (starting index is start + array.size): + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, -2) # => ["a", "b", :X, :X] + * + * If +start+ is too small (less than and far from zero), replaces all elements: + * 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] + * + * With arguments +obj+, \Integer +start+, and \Integer +length+, and no block given, + * replaces elements based on the given +start+ and +length+. + * + * If +start+ is in range, replaces +length+ elements beginning at offset +start+: + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"] + * + * If +start+ is negative, counts from the end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"] + * + * If +start+ is large (start >= array.size), extends +self+ with +nil+: + * 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] + * + * If +length+ is zero or negative, replaces no elements: + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"] + * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"] + * + * With arguments +obj+ and \Range +range+, and no block given, + * replaces elements based on the given range. + * + * If the range is positive and ascending (0 < range.begin <= range.end), + * replaces elements from range.begin to range.end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"] + * + * If range.first is negative, replaces no elements: + * a = ['a', 'b', 'c', 'd'] + * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"] + * + * If range.last is negative, counts from the end: + * 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"] + * + * If range.last and range.last are both negative, + * both count from the end of the array: + * 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"] + * + * With no arguments and a block given, calls the block with each index; + * replaces the corresponding element with the block's return value: + * a = ['a', 'b', 'c', 'd'] + * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"] + * + * 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 in range (0 <= start < array.size), + * replaces from offset +start+ to the end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"] + * + * If +start+ is too large(start >= array.size), does nothing: + * 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"] + * + * If +start+ is negative, counts from the end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"] + * + * If start is too small (start <= -array.size, replaces all elements: + * 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"] + * + * 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. + * + * If +start+ is in range, replaces +length+ elements beginning at offset +start+: + * a = ['a', 'b', 'c', 'd'] + * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"] + * + * If start is negative, counts from the end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"] + * + * If +start+ is large (start >= array.size), extends +self+ with +nil+: + * 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 +length+ is zero or less, replaces no elements: + * 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"] + * + * 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. + * + * If the range is positive and ascending (range 0 < range.begin <= range.end, + * replaces elements from range.begin to range.end: + * a = ['a', 'b', 'c', 'd'] + * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"] + * + * If +range.first+ is negative, does nothing: + * a = ['a', 'b', 'c', 'd'] + * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * + * If range.last is negative, counts from the end: + * 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"] + * + * If range.first and range.last are both negative, + * both count from the end: + * 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"] */ static VALUE @@ -3975,25 +4717,14 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary + other_ary -> new_ary - * - * Concatenation --- Returns a new array built by concatenating the - * two arrays together to produce a third array. + * array + other_array -> new_array * - * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ] - * a = [ "a", "b", "c" ] - * c = a + [ "d", "e", "f" ] - * c #=> [ "a", "b", "c", "d", "e", "f" ] - * a #=> [ "a", "b", "c" ] + * Returns a new \Array containing all elements of +array+ + * followed by all elements of +other_array+: + * a = [0, 1] + [2, 3] + * a # => [0, 1, 2, 3] * - * Note that - * x += y - * is the same as - * x = x + y - * This means that it produces a new array. As a consequence, - * repeated use of += on arrays can be quite inefficient. - * - * See also Array#concat. + * Related: #concat. */ VALUE @@ -4021,27 +4752,17 @@ ary_append(VALUE x, VALUE y) if (n > 0) { rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR_TRANSIENT(y), n); } + RB_GC_GUARD(y); return x; } /* * call-seq: - * ary.concat(other_ary1, other_ary2, ...) -> ary - * - * Appends the elements of other_arys to +self+. - * - * [ "a", "b" ].concat( ["c", "d"]) #=> [ "a", "b", "c", "d" ] - * [ "a" ].concat( ["b"], ["c", "d"]) #=> [ "a", "b", "c", "d" ] - * [ "a" ].concat #=> [ "a" ] - * - * a = [ 1, 2, 3 ] - * a.concat( [ 4, 5 ]) - * a #=> [ 1, 2, 3, 4, 5 ] - * - * a = [ 1, 2 ] - * a.concat(a, a) #=> [1, 2, 1, 2, 1, 2] + * array.concat(*other_arrays) -> self * - * See also Array#+. + * Adds to +array+ 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] */ static VALUE @@ -4073,19 +4794,17 @@ rb_ary_concat(VALUE x, VALUE y) /* * call-seq: - * ary * int -> new_ary - * ary * str -> new_string + * array * n -> new_array + * array * string_separator -> new_string * - * Repetition --- With a String argument, equivalent to - * ary.join(str). - * - * Otherwise, returns a new array built by concatenating the +int+ copies of - * +self+. - * - * - * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ] - * [ 1, 2, 3 ] * "," #=> "1,2,3" + * When non-negative argument \Integer +n+ is given, + * returns a new \Array built by concatenating the +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): + * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}" */ static VALUE @@ -4102,7 +4821,7 @@ rb_ary_times(VALUE ary, VALUE times) len = NUM2LONG(times); if (len == 0) { - ary2 = ary_new(rb_obj_class(ary), 0); + ary2 = ary_new(rb_cArray, 0); goto out; } if (len < 0) { @@ -4113,7 +4832,7 @@ rb_ary_times(VALUE ary, VALUE times) } len *= RARRAY_LEN(ary); - ary2 = ary_new(rb_obj_class(ary), len); + ary2 = ary_new(rb_cArray, len); ARY_SET_LEN(ary2, len); ptr = RARRAY_CONST_PTR_TRANSIENT(ary); @@ -4134,22 +4853,16 @@ rb_ary_times(VALUE ary, VALUE times) /* * call-seq: - * ary.assoc(obj) -> element_ary or nil - * - * Searches through an array whose elements are also arrays comparing +obj+ - * with the first element of each contained array using obj.==. + * array.assoc(obj) -> found_array or nil * - * Returns the first contained array that matches (that is, the first - * associated array), or +nil+ if no match is found. + * Returns the first element in +self+ that is an \Array + * whose first element == +obj+: + * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]] + * a.assoc(4) # => [4, 5, 6] * - * See also Array#rassoc + * Returns +nil+ if no such element is found. * - * s1 = [ "colors", "red", "blue", "green" ] - * s2 = [ "letters", "a", "b", "c" ] - * s3 = "foo" - * a = [ s1, s2, s3 ] - * a.assoc("letters") #=> [ "letters", "a", "b", "c" ] - * a.assoc("foo") #=> nil + * Related: #rassoc. */ VALUE @@ -4169,20 +4882,16 @@ rb_ary_assoc(VALUE ary, VALUE key) /* * call-seq: - * ary.rassoc(obj) -> element_ary or nil + * array.rassoc(obj) -> found_array or nil * - * Searches through the array whose elements are also arrays. + * Returns the first element in +self+ that is an \Array + * whose second element == +obj+: + * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]] + * a.rassoc(4) # => [2, 4] * - * Compares +obj+ with the second element of each contained array using - * obj.==. + * Returns +nil+ if no such element is found. * - * Returns the first contained array that matches +obj+. - * - * See also Array#assoc. - * - * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] - * a.rassoc("two") #=> [2, "two"] - * a.rassoc("four") #=> nil + * Related: #assoc. */ VALUE @@ -4237,16 +4946,19 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * ary == other_ary -> bool + * array == other_array -> true or false * - * Equality --- Two arrays are equal if they contain the same number of - * elements and if each element is equal to (according to Object#==) the - * corresponding element in +other_ary+. + * Returns +true+ if both array.size == other_array.size + * and for each index +i+ in +array+, array[i] == other_array[i]: + * a0 = [:foo, 'bar', 2] + * a1 = [:foo, 'bar', 2.0] + * a1 == a0 # => true + * [] == [] # => true * - * [ "a", "c" ] == [ "a", "c", 7 ] #=> false - * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true - * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false + * Otherwise, returns +false+. * + * This method is different from method Array#eql?, + * which compares elements using Object#eql?. */ static VALUE @@ -4279,10 +4991,18 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * ary.eql?(other) -> true or false + * array.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]: + * a0 = [:foo, 'bar', 2] + * a1 = [:foo, 'bar', 2] + * a1.eql?(a0) # => true + * + * Otherwise, returns +false+. * - * Returns +true+ if +self+ and +other+ are the same object, - * or are both arrays with the same content (according to Object#eql?). + * This method is different from method {Array#==}[#method-i-3D-3D], + * which compares using method Object#==. */ static VALUE @@ -4297,14 +5017,13 @@ rb_ary_eql(VALUE ary1, VALUE ary2) /* * call-seq: - * ary.hash -> integer + * array.hash -> integer * - * Compute a hash-code for this array. + * Returns the integer hash value for +self+. * - * Two arrays with the same content will have the same hash code (and will - * compare using #eql?). - * - * See also Object#hash. + * Two arrays with the same content will have the same hash code (and will compare using eql?): + * [0, 1, 2].hash == [0, 1, 2].hash # => true + * [0, 1, 2].hash == [0, 1, 3].hash # => false */ static VALUE @@ -4326,14 +5045,12 @@ rb_ary_hash(VALUE ary) /* * call-seq: - * ary.include?(object) -> true or false - * - * Returns +true+ if the given +object+ is present in +self+ (that is, if any - * element == +object+), otherwise returns +false+. + * array.include?(obj) -> true or false * - * a = [ "a", "b", "c" ] - * a.include?("b") #=> true - * a.include?("z") #=> false + * Returns +true+ if for some index +i+ in +self+, obj == self[i]; + * otherwise +false+: + * [0, 1, 2].include?(2) # => true + * [0, 1, 2].include?(3) # => false */ VALUE @@ -4388,32 +5105,24 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * ary <=> other_ary -> -1, 0, +1 or nil - * - * Comparison --- Returns an integer (+-1+, +0+, or +1) if this - * array is less than, equal to, or greater than +other_ary+. - * - * Each object in each array is compared (using the <=> operator). + * array <=> other_array -> -1, 0, or 1 * - * Arrays are compared in an "element-wise" manner; the first element of +ary+ - * is compared with the first one of +other_ary+ using the <=> operator, then - * each of the second elements, etc... - * As soon as the result of any such comparison is non zero (i.e. the two - * corresponding elements are not equal), that result is returned for the - * whole array comparison. + * 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]. * - * If all the elements are equal, then the result is based on a comparison of - * the array lengths. Thus, two arrays are "equal" according to Array#<=> if, - * and only if, they have the same length and the value of each element is - * equal to the value of the corresponding element in the other array. + * Returns -1 if any result is -1: + * [0, 1, 2] <=> [0, 1, 3] # => -1 * - * +nil+ is returned if the +other_ary+ is not an array or if the comparison - * of two elements returned +nil+. - * - * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1 - * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1 - * [ 1, 2 ] <=> [ 1, :two ] #=> nil + * Returns 1 if any result is 1: + * [0, 1, 2] <=> [0, 1, 1] # => 1 * + * When all results are zero: + * - Returns -1 if +array+ is smaller than +other_array+: + * [0, 1, 2] <=> [0, 1, 2, 3] # => -1 + * - Returns 1 if +array+ is larger than +other_array+: + * [0, 1, 2] <=> [0, 1] # => 1 + * - Returns 0 if +array+ and +other_array+ are the same size: + * [0, 1, 2] <=> [0, 1, 2] # => 0 */ VALUE @@ -4494,25 +5203,17 @@ ary_recycle_hash(VALUE hash) /* * call-seq: - * ary - other_ary -> new_ary - * - * Array Difference - * - * Returns a new array that is a copy of the original array, removing all - * occurrences of any item that also appear in +other_ary+. The order is - * preserved from the original array. - * - * It compares elements using their #hash and #eql? methods for efficiency. + * array - other_array -> new_array * - * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ] + * 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: + * [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] * - * Note that while 1 and 2 were only present once in the array argument, and - * were present twice in the receiver array, all occurrences of each Integer are - * removed in the returned array. - * - * If you need set-like behavior, see the library class Set. - * - * See also Array#difference. + * Related: Array#difference. */ static VALUE @@ -4523,6 +5224,7 @@ rb_ary_diff(VALUE ary1, VALUE ary2) long i; ary2 = to_ary(ary2); + if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); } ary3 = rb_ary_new(); if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) { @@ -4545,31 +5247,18 @@ rb_ary_diff(VALUE ary1, VALUE ary2) /* * call-seq: - * ary.difference(other_ary1, other_ary2, ...) -> new_ary - * - * Array Difference - * - * Returns a new array that is a copy of the original array, removing all - * occurrences of any item that also appear in +other_ary+. The order is - * preserved from the original array. - * - * It compares elements using their #hash and #eql? methods for efficiency. - * - * [ 1, 1, 2, 2, 3, 3, 4, 5 ].difference([ 1, 2, 4 ]) #=> [ 3, 3, 5 ] - * - * Note that while 1 and 2 were only present once in the array argument, and - * were present twice in the receiver array, all occurrences of each Integer are - * removed in the returned array. - * - * Multiple array arguments can be supplied and all occurrences of any element - * in those supplied arrays that match the receiver will be removed from the - * returned array. + * array.difference(*other_arrays) -> new_array * - * [ 1, 'c', :s, 'yep' ].difference([ 1 ], [ 'a', 'c' ]) #=> [ :s, "yep" ] + * Returns a new \Array containing only those elements from +self+ + * that are not found in any of the Arrays +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] * - * If you need set-like behavior, see the library class Set. + * Returns a copy of +self+ if no arguments given. * - * See also Array#-. + * Related: Array#-. */ static VALUE @@ -4611,17 +5300,17 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary & other_ary -> new_ary + * array & other_array -> new_array * - * Set Intersection --- Returns a new array containing unique elements common to the - * two arrays. The order is preserved from the original array. + * Returns a new \Array containing each element found in both +array+ and \Array +other_array+; + * duplicates are omitted; items are compared using eql?: + * [0, 1, 2, 3] & [1, 2] # => [1, 2] + * [0, 1, 0, 1] & [0, 1] # => [0, 1] * - * It compares elements using their #hash and #eql? methods for efficiency. + * Preserves order from +array+: + * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2] * - * [ 1, 1, 3, 5 ] & [ 3, 2, 1 ] #=> [ 1, 3 ] - * [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ] - * - * See also Array#uniq. + * Related: Array#intersection. */ @@ -4662,19 +5351,20 @@ rb_ary_and(VALUE ary1, VALUE ary2) /* * call-seq: - * ary.intersection(other_ary1, other_ary2, ...) -> new_ary + * array.intersection(*other_arrays) -> new_array * - * Set Intersection --- Returns a new array containing unique elements common - * to +self+ and other_arys. Order is preserved from the original - * 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?: + * [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] * - * It compares elements using their #hash and #eql? methods for efficiency. + * Preserves order from +self+: + * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2] * - * [ 1, 1, 3, 5 ].intersection([ 3, 2, 1 ]) # => [ 1, 3 ] - * [ "a", "b", "z" ].intersection([ "a", "b", "c" ], [ "b" ]) # => [ "b" ] - * [ "a" ].intersection #=> [ "a" ] + * Returns a copy of +self+ if no arguments given. * - * See also Array#&. + * Related: Array#&. */ static VALUE @@ -4723,17 +5413,16 @@ rb_ary_union_hash(VALUE hash, VALUE ary2) /* * call-seq: - * ary | other_ary -> new_ary - * - * Set Union --- Returns a new array by joining +ary+ with +other_ary+, - * excluding any duplicates and preserving the order from the given arrays. + * array | other_array -> new_array * - * It compares elements using their #hash and #eql? methods for efficiency. + * Returns the union of +array+ and \Array +other_array+; + * duplicates are removed; order is preserved; + * items are compared using eql?: + * [0, 1] | [2, 3] # => [0, 1, 2, 3] + * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3] + * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3] * - * [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ] - * [ "c", "d", "a" ] | [ "a", "b", "c" ] #=> [ "c", "d", "a", "b" ] - * - * See also Array#union. + * Related: Array#union. */ static VALUE @@ -4759,18 +5448,17 @@ rb_ary_or(VALUE ary1, VALUE ary2) /* * call-seq: - * ary.union(other_ary1, other_ary2, ...) -> new_ary - * - * Set Union --- Returns a new array by joining other_arys with +self+, - * excluding any duplicates and preserving the order from the given arrays. + * array.union(*other_arrays) -> new_array * - * It compares elements using their #hash and #eql? methods for efficiency. + * 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?: + * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7] + * [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] * - * [ "a", "b", "c" ].union( [ "c", "d", "a" ] ) #=> [ "a", "b", "c", "d" ] - * [ "a" ].union( ["e", "b"], ["a", "c", "b"] ) #=> [ "a", "e", "b", "c" ] - * [ "a" ].union #=> [ "a" ] + * Returns a copy of +self+ if no arguments given. * - * See also Array#|. + * Related: Array#|. */ static VALUE @@ -4786,44 +5474,199 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary) sum += RARRAY_LEN(argv[i]); } - if (sum <= SMALL_ARRAY_LEN) { - ary_union = rb_ary_new(); + if (sum <= SMALL_ARRAY_LEN) { + ary_union = rb_ary_new(); + + rb_ary_union(ary_union, ary); + for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]); + + return ary_union; + } + + hash = ary_make_hash(ary); + for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]); + + ary_union = rb_hash_values(hash); + ary_recycle_hash(hash); + return ary_union; +} + +/* + * call-seq: + * ary.intersect?(other_ary) -> true or false + * + * Returns +true+ if the array and +other_ary+ have at least one element in + * common, otherwise returns +false+. + * + * a = [ 1, 2, 3 ] + * b = [ 3, 4, 5 ] + * c = [ 5, 6, 7 ] + * a.intersect?(b) #=> true + * a.intersect?(c) #=> false + */ + +static VALUE +rb_ary_intersect_p(VALUE ary1, VALUE ary2) +{ + VALUE hash, v, result, shorter, longer; + st_data_t vv; + long i; + + ary2 = to_ary(ary2); + if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse; + + if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) { + for (i=0; i RARRAY_LEN(ary2)) { + longer = ary1; + shorter = ary2; + } + + hash = ary_make_hash(shorter); + result = Qfalse; + + for (i=0; i 0 && i < RARRAY_LEN(ary)); + + VALUE v; + for (; i < RARRAY_LEN(ary); ++i) { + v = RARRAY_AREF(ary, i); + + if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) { + vmax = v; + } + } + + return vmax; +} + +static VALUE +ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(FIXNUM_P(vmax)); + + VALUE v; + for (; i < n; ++i) { + v = RARRAY_AREF(ary, i); + + if (FIXNUM_P(v)) { + if ((long)vmax < (long)v) { + vmax = v; + } + } + else { + return ary_max_generic(ary, i, vmax); + } + } + + return vmax; +} + +static VALUE +ary_max_opt_float(VALUE ary, long i, VALUE vmax) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax)); + + VALUE v; + for (; i < n; ++i) { + v = RARRAY_AREF(ary, i); + + if (RB_FLOAT_TYPE_P(v)) { + if (rb_float_cmp(vmax, v) < 0) { + vmax = v; + } + } + else { + return ary_max_generic(ary, i, vmax); + } + } + + return vmax; +} - rb_ary_union(ary_union, ary); - for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]); +static VALUE +ary_max_opt_string(VALUE ary, long i, VALUE vmax) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(STRING_P(vmax)); - return ary_union; - } + VALUE v; + for (; i < n; ++i) { + v = RARRAY_AREF(ary, i); - hash = ary_make_hash(ary); - for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]); + if (STRING_P(v)) { + if (rb_str_cmp(vmax, v) < 0) { + vmax = v; + } + } + else { + return ary_max_generic(ary, i, vmax); + } + } - ary_union = rb_hash_values(hash); - ary_recycle_hash(hash); - return ary_union; + return vmax; } /* * call-seq: - * ary.max -> obj - * ary.max {|a, b| block} -> obj - * ary.max(n) -> array - * ary.max(n) {|a, b| block} -> array + * array.max -> element + * array.max {|a, b| ... } -> element + * array.max(n) -> new_array + * array.max(n) {|a, b| ... } -> new_array * - * Returns the object in _ary_ with the maximum value. The - * first form assumes all objects implement Comparable; - * the second uses the block to return a <=> b. + * Returns one of the following: + * - The maximum-valued element from +self+. + * - A new \Array of maximum-valued elements selected from +self+. * - * ary = %w(albatross dog horse) - * ary.max #=> "horse" - * ary.max {|a, b| a.length <=> b.length} #=> "albatross" + * When no block is given, each element in +self+ must respond to method <=> + * with an \Integer. * - * If the +n+ argument is given, maximum +n+ elements are returned - * as an array. + * With no argument and no block, returns the element in +self+ + * having the maximum value per method <=>: + * [0, 1, 2].max # => 2 * - * ary = %w[albatross dog horse] - * ary.max(2) #=> ["horse", "dog"] - * ary.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"] + * With an argument \Integer +n+ and no block, returns a new \Array with at most +n+ 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] + * + * When a block is given, the block must return an \Integer. + * + * 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" + * + * With an argument +n+ and a block, returns a new \Array with at most +n+ elements, + * in descending order per the block: + * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"] */ static VALUE rb_ary_max(int argc, VALUE *argv, VALUE ary) @@ -4836,6 +5679,7 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary) if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0])) return rb_nmin_run(ary, num, 0, 1, 1); + const long n = RARRAY_LEN(ary); if (rb_block_given_p()) { for (i = 0; i < RARRAY_LEN(ary); i++) { v = RARRAY_AREF(ary, i); @@ -4844,39 +5688,148 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary) } } } - else { - for (i = 0; i < RARRAY_LEN(ary); i++) { - v = RARRAY_AREF(ary, i); - if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) { - result = v; - } - } + else if (n > 0) { + result = RARRAY_AREF(ary, 0); + if (n > 1) { + if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) { + return ary_max_opt_fixnum(ary, 1, result); + } + else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) { + return ary_max_opt_string(ary, 1, result); + } + else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) { + return ary_max_opt_float(ary, 1, result); + } + else { + return ary_max_generic(ary, 1, result); + } + } } if (result == Qundef) return Qnil; return result; } +static VALUE +ary_min_generic(VALUE ary, long i, VALUE vmin) +{ + RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary)); + + VALUE v; + for (; i < RARRAY_LEN(ary); ++i) { + v = RARRAY_AREF(ary, i); + + if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) { + vmin = v; + } + } + + return vmin; +} + +static VALUE +ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(FIXNUM_P(vmin)); + + VALUE a; + for (; i < n; ++i) { + a = RARRAY_AREF(ary, i); + + if (FIXNUM_P(a)) { + if ((long)vmin > (long)a) { + vmin = a; + } + } + else { + return ary_min_generic(ary, i, vmin); + } + } + + return vmin; +} + +static VALUE +ary_min_opt_float(VALUE ary, long i, VALUE vmin) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin)); + + VALUE a; + for (; i < n; ++i) { + a = RARRAY_AREF(ary, i); + + if (RB_FLOAT_TYPE_P(a)) { + if (rb_float_cmp(vmin, a) > 0) { + vmin = a; + } + } + else { + return ary_min_generic(ary, i, vmin); + } + } + + return vmin; +} + +static VALUE +ary_min_opt_string(VALUE ary, long i, VALUE vmin) +{ + const long n = RARRAY_LEN(ary); + RUBY_ASSERT(i > 0 && i < n); + RUBY_ASSERT(STRING_P(vmin)); + + VALUE a; + for (; i < n; ++i) { + a = RARRAY_AREF(ary, i); + + if (STRING_P(a)) { + if (rb_str_cmp(vmin, a) > 0) { + vmin = a; + } + } + else { + return ary_min_generic(ary, i, vmin); + } + } + + return vmin; +} + /* * call-seq: - * ary.min -> obj - * ary.min {| a,b | block } -> obj - * ary.min(n) -> array - * ary.min(n) {| a,b | block } -> array + * array.min -> element + * array.min { |a, b| ... } -> element + * array.min(n) -> new_array + * array.min(n) { |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+. + * + * When no block is given, each element in +self+ must respond to method <=> + * with an \Integer. + * + * With no argument and no block, returns the element in +self+ + * having the minimum value per method <=>: + * [0, 1, 2].min # => 0 * - * Returns the object in _ary_ with the minimum value. The - * first form assumes all objects implement Comparable; - * the second uses the block to return a <=> b. + * With \Integer argument +n+ and no block, returns a new \Array with at most +n+ 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] * - * ary = %w(albatross dog horse) - * ary.min #=> "albatross" - * ary.min {|a, b| a.length <=> b.length} #=> "dog" + * When a block is given, the block must return an Integer. * - * If the +n+ argument is given, minimum +n+ elements are returned - * as an array. + * 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" * - * ary = %w[albatross dog horse] - * ary.min(2) #=> ["albatross", "dog"] - * ary.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"] + * With an argument +n+ and a block, returns a new \Array with at most +n+ elements, + * in ascending order per the block: + * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"] */ static VALUE rb_ary_min(int argc, VALUE *argv, VALUE ary) @@ -4889,6 +5842,7 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary) if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0])) return rb_nmin_run(ary, num, 0, 0, 1); + const long n = RARRAY_LEN(ary); if (rb_block_given_p()) { for (i = 0; i < RARRAY_LEN(ary); i++) { v = RARRAY_AREF(ary, i); @@ -4897,13 +5851,22 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary) } } } - else { - for (i = 0; i < RARRAY_LEN(ary); i++) { - v = RARRAY_AREF(ary, i); - if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) { - result = v; - } - } + else if (n > 0) { + result = RARRAY_AREF(ary, 0); + if (n > 1) { + if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) { + return ary_min_opt_fixnum(ary, 1, result); + } + else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) { + return ary_min_opt_string(ary, 1, result); + } + else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) { + return ary_min_opt_float(ary, 1, result); + } + else { + return ary_min_generic(ary, 1, result); + } + } } if (result == Qundef) return Qnil; return result; @@ -4911,14 +5874,23 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.minmax -> [obj, obj] - * ary.minmax {| a,b | block } -> [obj, obj] - * - * Returns a two element array which contains the minimum and the - * maximum value in the array. - * - * Can be given an optional block to override the default comparison - * method a <=> b. + * array.minmax -> [min_val, max_val] + * array.minmax {|a, b| ... } -> [min_val, max_val] + * + * Returns a new 2-element \Array containing the minimum and maximum values + * from +self+, either per method <=> or per a given block:. + * + * 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 <=>: + * [0, 1, 2].minmax # => [0, 2] + * + * 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: + * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"] */ static VALUE rb_ary_minmax(VALUE ary) @@ -4938,31 +5910,31 @@ push_value(st_data_t key, st_data_t val, st_data_t ary) /* * call-seq: - * ary.uniq! -> ary or nil - * ary.uniq! {|item| ...} -> ary or nil - * - * Removes duplicate elements from +self+. - * - * If a block is given, it will use the return value of the block for - * comparison. + * array.uniq! -> self or nil + * array.uniq! {|element| ... } -> self or nil * - * It compares values using their #hash and #eql? methods for efficiency. + * Removes duplicate elements from +self+, the first occurrence always being retained; + * returns +self+ if any elements removed, +nil+ otherwise. * - * +self+ is traversed in order, and the first occurrence is kept. + * With no block given, identifies and removes elements using method eql? + * to compare. * - * Returns +nil+ if no changes are made (that is, no duplicates are found). + * Returns +self+ if any elements removed: + * a = [0, 0, 1, 1, 2, 2] + * a.uniq! # => [0, 1, 2] * - * a = [ "a", "a", "b", "b", "c" ] - * a.uniq! # => ["a", "b", "c"] + * Returns +nil+ if no elements removed. * - * b = [ "a", "b", "c" ] - * b.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. * - * c = [["student","sam"], ["student","george"], ["teacher","matz"]] - * c.uniq! {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]] + * Returns +self+ if any elements removed: + * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb'] + * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa'] * + * Returns +nil+ if no elements removed. */ - static VALUE rb_ary_uniq_bang(VALUE ary) { @@ -4996,23 +5968,22 @@ rb_ary_uniq_bang(VALUE ary) /* * call-seq: - * ary.uniq -> new_ary - * ary.uniq {|item| ...} -> new_ary - * - * Returns a new array by removing duplicate values in +self+. - * - * If a block is given, it will use the return value of the block for comparison. - * - * It compares values using their #hash and #eql? methods for efficiency. - * - * +self+ is traversed in order, and the first occurrence is kept. - * - * a = [ "a", "a", "b", "b", "c" ] - * a.uniq # => ["a", "b", "c"] - * - * b = [["student","sam"], ["student","george"], ["teacher","matz"]] - * b.uniq {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]] - * + * array.uniq -> new_array + * array.uniq {|element| ... } -> new_array + * + * 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. + * 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: + * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb'] + * a.uniq {|element| element.size } # => ["a", "aa", "aaa"] */ static VALUE @@ -5032,7 +6003,6 @@ rb_ary_uniq(VALUE ary) hash = ary_make_hash(ary); uniq = rb_hash_values(hash); } - RBASIC_SET_CLASS(uniq, rb_obj_class(ary)); if (hash) { ary_recycle_hash(hash); } @@ -5042,14 +6012,11 @@ rb_ary_uniq(VALUE ary) /* * call-seq: - * ary.compact! -> ary or nil + * array.compact! -> self or nil * - * Removes +nil+ elements from the array. + * Removes all +nil+ elements from +self+. * - * Returns +nil+ if no changes were made, otherwise returns the array. - * - * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ] - * [ "a", "b", "c" ].compact! #=> nil + * Returns +self+ if any elements removed, otherwise +nil+. */ static VALUE @@ -5077,12 +6044,11 @@ rb_ary_compact_bang(VALUE ary) /* * call-seq: - * ary.compact -> new_ary - * - * Returns a copy of +self+ with all +nil+ elements removed. + * array.compact -> new_array * - * [ "a", nil, "b", nil, "c", nil ].compact - * #=> [ "a", "b", "c" ] + * Returns a new \Array containing all non-+nil+ elements from +self+: + * a = [nil, 0, nil, 1, nil, 2, nil] + * a.compact # => [0, 1, 2] */ static VALUE @@ -5095,23 +6061,26 @@ rb_ary_compact(VALUE ary) /* * call-seq: - * ary.count -> int - * ary.count(obj) -> int - * ary.count {|item| block} -> int + * array.count -> an_integer + * array.count(obj) -> an_integer + * array.count {|element| ... } -> an_integer * - * Returns the number of elements. + * Returns a count of specified elements. * - * If an argument is given, counts the number of elements which equal +obj+ - * using ==. + * With no argument and no block, returns the count of all elements: + * [0, 1, 2].count # => 3 + * [].count # => 0 * - * If a block is given, counts the number of elements for which the block - * returns a true value. + * With argument +obj+, returns the count of elements == to +obj+: + * [0, 1, 2, 0.0].count(0) # => 2 + * [0, 1, 2].count(3) # => 0 * - * ary = [1, 2, 4, 2] - * ary.count #=> 4 - * ary.count(2) #=> 2 - * ary.count {|x| x%2 == 0} #=> 3 + * 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 * + * With argument +obj+ and a block given, issues a warning, ignores the block, + * and returns the count of elements == to +obj+: */ static VALUE @@ -5148,8 +6117,8 @@ static VALUE flatten(VALUE ary, int level) { long i; - VALUE stack, result, tmp, elt, vmemo; - st_table *memo; + VALUE stack, result, tmp = 0, elt, vmemo; + st_table *memo = 0; st_data_t id; for (i = 0; i < RARRAY_LEN(ary); i++) { @@ -5161,8 +6130,6 @@ flatten(VALUE ary, int level) } if (i == RARRAY_LEN(ary)) { return ary; - } else if (tmp == ary) { - rb_raise(rb_eArgError, "tried to flatten recursive array"); } result = ary_new(0, RARRAY_LEN(ary)); @@ -5173,12 +6140,14 @@ flatten(VALUE ary, int level) rb_ary_push(stack, ary); rb_ary_push(stack, LONG2NUM(i + 1)); - vmemo = rb_hash_new(); - RBASIC_CLEAR_CLASS(vmemo); - memo = st_init_numtable(); - rb_hash_st_table_set(vmemo, memo); - st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue); - st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue); + if (level < 0) { + vmemo = rb_hash_new(); + RBASIC_CLEAR_CLASS(vmemo); + memo = st_init_numtable(); + rb_hash_st_table_set(vmemo, memo); + st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue); + st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue); + } ary = tmp; i = 0; @@ -5192,20 +6161,24 @@ flatten(VALUE ary, int level) } tmp = rb_check_array_type(elt); if (RBASIC(result)->klass) { - RB_GC_GUARD(vmemo); - st_clear(memo); + if (memo) { + RB_GC_GUARD(vmemo); + st_clear(memo); + } rb_raise(rb_eRuntimeError, "flatten reentered"); } if (NIL_P(tmp)) { rb_ary_push(result, elt); } else { - id = (st_data_t)tmp; - if (st_is_member(memo, id)) { - st_clear(memo); - rb_raise(rb_eArgError, "tried to flatten recursive array"); + if (memo) { + id = (st_data_t)tmp; + if (st_is_member(memo, id)) { + st_clear(memo); + rb_raise(rb_eArgError, "tried to flatten recursive array"); + } + st_insert(memo, id, (st_data_t)Qtrue); } - st_insert(memo, id, (st_data_t)Qtrue); rb_ary_push(stack, ary); rb_ary_push(stack, LONG2NUM(i)); ary = tmp; @@ -5215,37 +6188,49 @@ flatten(VALUE ary, int level) if (RARRAY_LEN(stack) == 0) { break; } - id = (st_data_t)ary; - st_delete(memo, &id, 0); + if (memo) { + id = (st_data_t)ary; + st_delete(memo, &id, 0); + } tmp = rb_ary_pop(stack); i = NUM2LONG(tmp); ary = rb_ary_pop(stack); } - st_clear(memo); + if (memo) { + st_clear(memo); + } - RBASIC_SET_CLASS(result, rb_obj_class(ary)); + RBASIC_SET_CLASS(result, rb_cArray); return result; } /* * call-seq: - * ary.flatten! -> ary or nil - * ary.flatten!(level) -> ary or nil - * - * Flattens +self+ in place. - * - * Returns +nil+ if no modifications were made (i.e., the array contains no - * subarrays.) - * - * The optional +level+ argument determines the level of recursion to flatten. - * - * a = [ 1, 2, [3, [4, 5] ] ] - * a.flatten! #=> [1, 2, 3, 4, 5] - * a.flatten! #=> nil - * a #=> [1, 2, 3, 4, 5] - * a = [ 1, 2, [3, [4, 5] ] ] - * a.flatten!(1) #=> [1, 2, 3, [4, 5]] + * array.flatten! -> self or nil + * array.flatten!(level) -> self or nil + * + * Replaces each nested \Array in +self+ with the elements from that \Array; + * returns +self+ if any changes, +nil+ otherwise. + * + * With non-negative \Integer argument +level+, flattens recursively through +level+ levels: + * 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 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! # => 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 */ static VALUE @@ -5272,24 +6257,32 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.flatten -> new_ary - * ary.flatten(level) -> new_ary - * - * Returns a new array that is a one-dimensional flattening of +self+ - * (recursively). - * - * That is, for every element that is an array, extract its elements into - * the new array. - * - * The optional +level+ argument determines the level of recursion to - * flatten. - * - * s = [ 1, 2, 3 ] #=> [1, 2, 3] - * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] - * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] - * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - * a = [ 1, 2, [3, [4, 5] ] ] - * a.flatten(1) #=> [1, 2, 3, [4, 5]] + * 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] */ static VALUE @@ -5311,45 +6304,13 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary) return result; } -#define OPTHASH_GIVEN_P(opts) \ - (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1)) -static ID id_random; - #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1) -/* - * call-seq: - * ary.shuffle! -> ary - * ary.shuffle!(random: rng) -> ary - * - * Shuffles elements in +self+ in place. - * - * a = [ 1, 2, 3 ] #=> [1, 2, 3] - * a.shuffle! #=> [2, 3, 1] - * a #=> [2, 3, 1] - * - * The optional +rng+ argument will be used as the random number generator. - * - * a.shuffle!(random: Random.new(1)) #=> [1, 3, 2] - */ - static VALUE -rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) +rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen) { - VALUE opts, randgen = rb_cRandom; long i, len; - if (OPTHASH_GIVEN_P(opts)) { - VALUE rnd; - ID keyword_ids[1]; - - keyword_ids[0] = id_random; - rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd); - if (rnd != Qundef) { - randgen = rnd; - } - } - rb_check_arity(argc, 0, 0); rb_ary_modify(ary); i = len = RARRAY_LEN(ary); RARRAY_PTR_USE(ary, ptr, { @@ -5367,80 +6328,24 @@ rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) return ary; } - -/* - * call-seq: - * ary.shuffle -> new_ary - * ary.shuffle(random: rng) -> new_ary - * - * 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] - * - * The optional +rng+ argument will be used as the random number generator. - * - * a.shuffle(random: Random.new(1)) #=> [1, 3, 2] - */ - static VALUE -rb_ary_shuffle(int argc, VALUE *argv, VALUE ary) +rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen) { ary = rb_ary_dup(ary); - rb_ary_shuffle_bang(argc, argv, ary); + rb_ary_shuffle_bang(ec, ary, randgen); return ary; } - -/* - * call-seq: - * ary.sample -> obj - * ary.sample(random: rng) -> obj - * ary.sample(n) -> new_ary - * ary.sample(n, random: rng) -> new_ary - * - * Choose a random element or +n+ random elements from the array. - * - * The elements are chosen by using random and unique indices into the array - * in order to ensure that an element doesn't repeat itself unless the array - * already contained duplicate elements. - * - * If the array is empty the first form returns +nil+ and the second form - * returns an empty array. - * - * a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] - * a.sample #=> 7 - * a.sample(4) #=> [6, 4, 2, 5] - * - * The optional +rng+ argument will be used as the random number generator. - * - * a.sample(random: Random.new(1)) #=> 6 - * a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2] - */ - - static VALUE -rb_ary_sample(int argc, VALUE *argv, VALUE ary) +ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array) { - VALUE nv, result; - VALUE opts, randgen = rb_cRandom; + VALUE result; long n, len, i, j, k, idx[10]; long rnds[numberof(idx)]; long memo_threshold; - if (OPTHASH_GIVEN_P(opts)) { - VALUE rnd; - ID keyword_ids[1]; - - keyword_ids[0] = id_random; - rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd); - if (rnd != Qundef) { - randgen = rnd; - } - } len = RARRAY_LEN(ary); - if (rb_check_arity(argc, 0, 1) == 0) { + if (!to_array) { if (len < 2) i = 0; else @@ -5448,7 +6353,6 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) return rb_ary_elt(ary, i); } - nv = argv[0]; n = NUM2LONG(nv); if (n < 0) rb_raise(rb_eArgError, "negative sample number"); if (n > len) n = len; @@ -5470,7 +6374,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) return rb_ary_new_capa(0); case 1: i = rnds[0]; - return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i)); + return rb_ary_new_from_args(1, RARRAY_AREF(ary, i)); case 2: i = rnds[0]; j = rnds[1]; @@ -5562,6 +6466,12 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) return result; } +static VALUE +ary_sample0(rb_execution_context_t *ec, VALUE ary) +{ + return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse); +} + static VALUE rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj) { @@ -5571,7 +6481,7 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj) n = RARRAY_AREF(args, 0); } if (RARRAY_LEN(self) == 0) return INT2FIX(0); - if (n == Qnil) return DBL2NUM(HUGE_VAL); + if (NIL_P(n)) return DBL2NUM(HUGE_VAL); mul = NUM2LONG(n); if (mul <= 0) return INT2FIX(0); n = LONG2FIX(mul); @@ -5580,24 +6490,33 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj) /* * call-seq: - * ary.cycle(n=nil) {|obj| block} -> nil - * ary.cycle(n=nil) -> Enumerator - * - * Calls the given block for each element +n+ times or forever if +nil+ is - * given. - * - * Does nothing if a non-positive number is given or the array is empty. - * - * Returns +nil+ if the loop has finished without getting interrupted. - * - * If no block is given, an Enumerator is returned instead. - * - * a = ["a", "b", "c"] - * a.cycle {|x| puts x} # print, a, b, c, a, b, c,.. forever. - * a.cycle(2) {|x| puts x} # print, a, b, c, a, b, c. - * + * array.cycle {|element| ... } -> nil + * array.cycle(count) {|element| ... } -> nil + * array.cycle -> new_enumerator + * array.cycle(count) -> new_enumerator + * + * When called with positive \Integer argument +count+ and a block, + * calls the block with each element, then does so again, + * 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: + * [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: + * # 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] */ - static VALUE rb_ary_cycle(int argc, VALUE *argv, VALUE ary) { @@ -5691,7 +6610,7 @@ permute0(const long n, const long r, long *const p, char *const used, const VALU /* * Returns the product of from, from-1, ..., from - how_many + 1. - * http://en.wikipedia.org/wiki/Pochhammer_symbol + * https://en.wikipedia.org/wiki/Pochhammer_symbol */ static VALUE descending_factorial(long from, long how_many) @@ -5743,30 +6662,66 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * ary.permutation {|p| block} -> ary - * ary.permutation -> Enumerator - * ary.permutation(n) {|p| block} -> ary - * ary.permutation(n) -> Enumerator - * - * When invoked with a block, yield all permutations of length +n+ of the - * elements of the array, then return the array itself. - * - * If +n+ is not specified, yield all permutations of all elements. - * - * The implementation makes no guarantees about the order in which the - * permutations are yielded. - * - * If no block is given, an Enumerator is returned instead. - * - * Examples: - * - * a = [1, 2, 3] - * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] - * a.permutation(1).to_a #=> [[1],[2],[3]] - * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]] - * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] - * a.permutation(0).to_a #=> [[]] # one permutation of length 0 - * a.permutation(4).to_a #=> [] # no permutations of length 4 + * array.permutation {|element| ... } -> self + * array.permutation(n) {|element| ... } -> self + * array.permutation -> new_enumerator + * array.permutation(n) -> new_enumerator + * + * When invoked with a block, yield all permutations of elements of +self+; returns +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: + * a = [0, 1, 2] + * a.permutation(3) {|permutation| p permutation } + * Output: + * [0, 1, 2] + * [0, 2, 1] + * [1, 0, 2] + * [1, 2, 0] + * [2, 0, 1] + * [2, 1, 0] + * + * When +n+ is zero, calls the block once with a new empty \Array: + * a = [0, 1, 2] + * a.permutation(0) {|permutation| p permutation } + * Output: + * [] + * + * When +n+ 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) # => # */ static VALUE @@ -5839,27 +6794,44 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * ary.combination(n) {|c| block} -> ary - * ary.combination(n) -> Enumerator - * - * When invoked with a block, yields all combinations of length +n+ of elements - * from the array and then returns the array itself. - * - * The implementation makes no guarantees about the order in which the - * combinations are yielded. - * - * If no block is given, an Enumerator is returned instead. - * - * Examples: - * - * a = [1, 2, 3, 4] - * a.combination(1).to_a #=> [[1],[2],[3],[4]] - * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] - * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]] - * a.combination(4).to_a #=> [[1,2,3,4]] - * a.combination(0).to_a #=> [[]] # one combination of length 0 - * a.combination(5).to_a #=> [] # no combinations of length 5 - * + * 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. + * + * 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: + * a = [0, 1, 2] + * a.combination(2) {|combination| p combination } + * Output: + * [0, 1] + * [0, 2] + * [1, 2] + * + * Another example: + * a = [0, 1, 2] + * a.combination(3) {|combination| p combination } + * 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 } + * Output: + * [] + * + * When +n+ is out of range (negative or larger than self.size), + * 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 = [0, 1, 2] + * a.combination(2) # => # */ static VALUE @@ -5946,27 +6918,59 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * ary.repeated_permutation(n) {|p| block} -> ary - * ary.repeated_permutation(n) -> Enumerator - * - * When invoked with a block, yield all repeated permutations of length +n+ of - * the elements of the array, then return the array itself. - * - * The implementation makes no guarantees about the order in which the repeated - * permutations are yielded. - * - * If no block is given, an Enumerator is returned instead. - * - * Examples: - * - * a = [1, 2] - * a.repeated_permutation(1).to_a #=> [[1], [2]] - * a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]] - * a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2], - * # [2,1,1],[2,1,2],[2,2,1],[2,2,2]] - * a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0 + * array.repeated_permutation(n) {|permutation| ... } -> self + * array.repeated_permutation(n) -> new_enumerator + * + * Calls the block with each repeated permutation of length +n+ 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. + * + * +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: + * [0, 0] + * [0, 1] + * [0, 2] + * [1, 0] + * [1, 1] + * [1, 2] + * [2, 0] + * [2, 1] + * [2, 2] + * + * If +n+ is zero, calls the block once with an empty \Array. + * + * If +n+ is negative, does not call the block: + * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' } + * + * Returns a new \Enumerator if no block given: + * a = [0, 1, 2] + * a.repeated_permutation(2) # => # + * + * Using Enumerators, it's convenient to show the permutations and counts + * for some values of +n+: + * 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]] */ - static VALUE rb_ary_repeated_permutation(VALUE ary, VALUE num) { @@ -6036,29 +7040,55 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * ary.repeated_combination(n) {|c| block} -> ary - * ary.repeated_combination(n) -> Enumerator - * - * When invoked with a block, yields all repeated combinations of length +n+ of - * elements from the array and then returns the array itself. - * - * The implementation makes no guarantees about the order in which the repeated - * combinations are yielded. - * - * If no block is given, an Enumerator is returned instead. - * - * Examples: - * - * a = [1, 2, 3] - * a.repeated_combination(1).to_a #=> [[1], [2], [3]] - * a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]] - * a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3], - * # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]] - * a.repeated_combination(4).to_a #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3], - * # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3], - * # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]] - * a.repeated_combination(0).to_a #=> [[]] # one combination of length 0 - * + * array.repeated_combination(n) {|combination| ... } -> self + * array.repeated_combination(n) -> new_enumerator + * + * Calls the block with each repeated combination of length +n+ 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: + * a.repeated_combination(2) {|combination| p combination } + * Output: + * [0, 0] + * [0, 1] + * [0, 2] + * [1, 1] + * [1, 2] + * [2, 2] + * + * If +n+ is zero, calls the block once with an empty \Array. + * + * If +n+ is negative, does not call the block: + * a.repeated_combination(-1) {|combination| fail 'Cannot happen' } + * + * Returns a new \Enumerator if no block given: + * a = [0, 1, 2] + * a.repeated_combination(2) # => # + * + * 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]] */ static VALUE @@ -6098,23 +7128,51 @@ rb_ary_repeated_combination(VALUE ary, VALUE num) /* * call-seq: - * ary.product(other_ary, ...) -> new_ary - * ary.product(other_ary, ...) {|p| block} -> ary - * - * Returns an array of all combinations of elements from all arrays. - * - * The length of the returned array is the product of the length of +self+ and - * the argument arrays. - * - * If given a block, #product will yield all combinations and return +self+ - * instead. - * - * [1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] - * [1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]] - * [1,2].product([3,4],[5,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]] - * [1,2].product() #=> [[1],[2]] - * [1,2].product([]) #=> [] + * array.product(*other_arrays) -> new_array + * array.product(*other_arrays) {|combination| ... } -> self + * + * Computes and returns or yields 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: + * 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]] + * + * When a block is given, yields each combination as an \Array; returns +self+: + * a.product(a1) {|combination| p combination } + * Output: + * [0, 3] + * [0, 4] + * [1, 3] + * [1, 4] + * [2, 3] + * [2, 4] + * + * If any argument is an empty \Array, does not call the block: + * a.product(a1, a2, []) {|combination| fail 'Cannot happen' } + * + * If no argument is given, yields each element of +self+ as a 1-element \Array: + * a.product {|combination| p combination } + * Output: + * [0] + * [1] + * [2] */ static VALUE @@ -6207,17 +7265,18 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.take(n) -> new_ary - * - * Returns first +n+ elements from the array. - * - * If a negative number is given, raises an ArgumentError. - * - * See also Array#drop - * - * a = [1, 2, 3, 4, 5, 0] - * a.take(3) #=> [1, 2, 3] - * + * 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+. + * + * Examples: + * 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] */ static VALUE @@ -6232,19 +7291,22 @@ rb_ary_take(VALUE obj, VALUE n) /* * call-seq: - * ary.take_while {|obj| block} -> new_ary - * ary.take_while -> Enumerator - * - * Passes elements to the block until the block returns +nil+ or +false+, then - * stops iterating and returns an array of all prior elements. - * - * If no block is given, an Enumerator is returned instead. - * - * See also Array#drop_while - * - * a = [1, 2, 3, 4, 5, 0] - * a.take_while {|i| i < 3} #=> [1, 2] - * + * 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+. + * + * 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: + * 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] + * + * With no block given, returns a new \Enumerator: + * [0, 1].take_while # => # */ static VALUE @@ -6261,18 +7323,17 @@ rb_ary_take_while(VALUE ary) /* * call-seq: - * ary.drop(n) -> new_ary - * - * Drops first +n+ elements from +ary+ and returns the rest of the elements in - * an array. - * - * If a negative number is given, raises an ArgumentError. + * array.drop(n) -> new_array * - * See also Array#take - * - * a = [1, 2, 3, 4, 5, 0] - * a.drop(3) #=> [4, 5, 0] + * Returns a new \Array containing all but the first +n+ element of +self+, + * where +n+ is a non-negative \Integer; + * does not modify +self+. * + * Examples: + * a = [0, 1, 2, 3, 4, 5] + * a.drop(0) # => [0, 1, 2, 3, 4, 5] + * a.drop(1) # => [1, 2, 3, 4, 5] + * a.drop(2) # => [2, 3, 4, 5] */ static VALUE @@ -6285,26 +7346,26 @@ rb_ary_drop(VALUE ary, VALUE n) } result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary)); - if (result == Qnil) result = rb_ary_new(); + if (NIL_P(result)) result = rb_ary_new(); return result; } /* * call-seq: - * ary.drop_while {|obj| block} -> new_ary - * ary.drop_while -> Enumerator - * - * Drops elements up to, but not including, the first element for which the - * block returns +nil+ or +false+ and returns an array containing the - * remaining elements. - * - * If no block is given, an Enumerator is returned instead. - * - * See also Array#take_while + * 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+. * - * a = [1, 2, 3, 4, 5, 0] - * a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0] + * 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: + * 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 # => # => # */ static VALUE @@ -6321,10 +7382,32 @@ rb_ary_drop_while(VALUE ary) /* * call-seq: - * ary.any? [{|obj| block} ] -> true or false - * ary.any?(pattern) -> true or false - * - * See also Enumerable#any? + * array.any? -> true or false + * array.any? {|element| ... } -> true or false + * array.any?(obj) -> true or false + * + * Returns +true+ if any element of +self+ meets a given criterion. + * + * With no block given and no argument, returns +true+ if +self+ has any truthy element, + * +false+ otherwise: + * [nil, 0, false].any? # => true + * [nil, false].any? # => false + * [].any? # => false + * + * 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: + * [0, 1, 2].any? {|element| element > 1 } # => true + * [0, 1, 2].any? {|element| element > 2 } # => false + * + * If argument +obj+ is given, returns +true+ if +obj+.=== any element, + * +false+ otherwise: + * ['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 + * + * Related: Enumerable#any? */ static VALUE @@ -6357,10 +7440,31 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.all? [{|obj| block} ] -> true or false - * ary.all?(pattern) -> true or false - * - * See also Enumerable#all? + * array.all? -> true or false + * array.all? {|element| ... } -> true or false + * array.all?(obj) -> true or false + * + * Returns +true+ if all elements of +self+ meet a given criterion. + * + * With no block given and no argument, returns +true+ if +self+ contains only truthy elements, + * +false+ otherwise: + * [0, 1, :foo].all? # => true + * [0, nil, 2].all? # => false + * [].all? # => true + * + * 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, 1, 2].all? { |element| element < 3 } # => true + * [0, 1, 2].all? { |element| element < 2 } # => false + * + * If argument +obj+ is given, returns +true+ if obj.=== every element, +false+ otherwise: + * ['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 + * + * Related: Enumerable#all? */ static VALUE @@ -6393,10 +7497,31 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.none? [{|obj| block} ] -> true or false - * ary.none?(pattern) -> true or false - * - * See also Enumerable#none? + * array.none? -> true or false + * array.none? {|element| ... } -> true or false + * array.none?(obj) -> true or false + * + * Returns +true+ if no element of +self+ meet a given criterion. + * + * With no block given and no argument, returns +true+ if +self+ has no truthy elements, + * +false+ otherwise: + * [nil, false].none? # => true + * [nil, 0, false].none? # => false + * [].none? # => true + * + * With a block given and no argument, 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? */ static VALUE @@ -6429,10 +7554,35 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.one? [{|obj| block} ] -> true or false - * ary.one?(pattern) -> true or false - * - * See also Enumerable#one? + * array.one? -> true or false + * array.one? {|element| ... } -> true or false + * array.one?(obj) -> true or false + * + * Returns +true+ if exactly one element of +self+ meets a given criterion. + * + * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element, + * +false+ otherwise: + * [nil, 0].one? # => true + * [0, 0].one? # => false + * [nil, nil].one? # => false + * [].one? # => false + * + * With a block given and no argument, 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, + * +false+ otherwise: + * [0, 1, 2].one?(0) # => true + * [0, 0, 1].one?(0) # => false + * [1, 1, 2].one?(0) # => false + * ['food', 'drink'].one?(/bar/) # => false + * ['food', 'drink'].one?(/foo/) # => true + * [].one?(/foo/) # => false + * + * Related: Enumerable#one? */ static VALUE @@ -6474,19 +7624,20 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary) } /* - * call-seq: - * ary.dig(idx, ...) -> object - * - * Extracts the nested value specified by the sequence of idx - * objects by calling +dig+ at each step, returning +nil+ if any - * intermediate step is +nil+. - * - * a = [[1, [2, 3]]] - * - * a.dig(0, 1, 1) #=> 3 - * a.dig(1, 2, 3) #=> nil - * a.dig(0, 0, 0) #=> TypeError: Integer does not have #dig method - * [42, {foo: :bar}].dig(1, :foo) #=> :bar + * call-seq: + * array.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. + * See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. + * + * Examples: + * a = [:foo, [:bar, :baz, [:bat, :bam]]] + * a.dig(1) # => [:bar, :baz, [:bat, :bam]] + * a.dig(1, 2) # => [:bat, :bam] + * a.dig(1, 2, 0) # => :bat + * a.dig(1, 2, 3) # => nil */ static VALUE @@ -6505,13 +7656,7 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z) if (n != 0) v = rb_fix_plus(LONG2FIX(n), v); if (r != Qundef) { - /* r can be an Integer when mathn is loaded */ - if (FIXNUM_P(r)) - v = rb_fix_plus(r, v); - else if (RB_TYPE_P(r, T_BIGNUM)) - v = rb_big_plus(r, v); - else - v = rb_rational_plus(r, v); + v = rb_rational_plus(r, v); } else if (!n && z) { v = rb_fix_plus(LONG2FIX(0), v); @@ -6521,44 +7666,35 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z) /* * call-seq: - * ary.sum(init=0) -> number - * ary.sum(init=0) {|e| expr } -> number - * - * Returns the sum of elements. - * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3. - * - * If a block is given, the block is applied to each element - * before addition. - * - * If ary is empty, it returns init. - * - * [].sum #=> 0 - * [].sum(0.0) #=> 0.0 - * [1, 2, 3].sum #=> 6 - * [3, 5.5].sum #=> 8.5 - * [2.5, 3.0].sum(0.0) {|e| e * e } #=> 15.25 - * [Object.new].sum #=> TypeError - * - * The (arithmetic) mean value of an array can be obtained as follows. - * - * mean = ary.sum(0.0) / ary.length - * - * This method can be used for non-numeric objects by - * explicit init argument. - * - * ["a", "b", "c"].sum("") #=> "abc" - * [[1], [[2]], [3]].sum([]) #=> [1, [2], 3] - * - * However, Array#join and Array#flatten is faster than Array#sum for - * array of strings and array of arrays. - * - * ["a", "b", "c"].join #=> "abc" - * [[1], [[2]], [3]].flatten(1) #=> [1, [2], 3] - * - * - * Array#sum method may not respect method redefinition of "+" methods - * such as Integer#+. - * + * array.sum(init = 0) -> object + * array.sum(init = 0) {|element| ... } -> object + * + * When no block is given, returns the object equivalent to: + * sum = init + * array.each {|element| sum += element } + * sum + * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3. + * + * Examples: + * a = [0, 1, 2, 3] + * a.sum # => 6 + * a.sum(100) # => 106 + * + * The elements need not be numeric, but must be +-compatible + * with each other and with +init+: + * a = ['abc', 'def', 'ghi'] + * a.sum('jkl') # => "jklabcdefghi" + * + * 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: + * a = ['zero', 1, :two] + * s = a.sum('Coerced and concatenated: ') {|element| element.to_s } + * 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. + * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+. */ static VALUE @@ -6588,7 +7724,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) n = 0; } } - else if (RB_TYPE_P(e, T_BIGNUM)) + else if (RB_BIGNUM_TYPE_P(e)) v = rb_big_plus(e, v); else if (RB_TYPE_P(e, T_RATIONAL)) { if (r == Qundef) @@ -6608,7 +7744,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) if (RB_FLOAT_TYPE_P(e)) { /* * Kahan-Babuska balancing compensated summation algorithm - * See http://link.springer.com/article/10.1007/s00607-005-0139-x + * See https://link.springer.com/article/10.1007/s00607-005-0139-x */ double f, c; double x, t; @@ -6625,7 +7761,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) x = RFLOAT_VALUE(e); else if (FIXNUM_P(e)) x = FIX2LONG(e); - else if (RB_TYPE_P(e, T_BIGNUM)) + else if (RB_BIGNUM_TYPE_P(e)) x = rb_big2dbl(e); else if (RB_TYPE_P(e, T_RATIONAL)) x = rb_num2dbl(e); @@ -6678,22 +7814,49 @@ rb_ary_deconstruct(VALUE ary) } /* - * Arrays are ordered, integer-indexed collections of any object. + * An \Array is an ordered, integer-indexed collection of objects, + * called _elements_. Any object may be an \Array element. + * + * == \Array Indexes + * + * \Array indexing starts at 0, as in C or Java. + * + * A positive index is an offset from the first element: + * - Index 0 indicates the first element. + * - Index 1 indicates the second element. + * - ... + * + * A negative index is an offset, backwards, from the end of the array: + * - Index -1 indicates the last element. + * - Index -2 indicates the next-to-last element. + * - ... * - * Array indexing starts at 0, as in C or Java. A negative index is assumed - * to be relative to the end of the array---that is, an index of -1 indicates - * the last element of the array, -2 is the next to last element in the - * array, and so on. + * A non-negative index is in range if it is smaller than + * the size of the array. For a 3-element array: + * - Indexes 0 through 2 are in range. + * - Index 3 is out of range. + * + * A negative index is in range if its absolute value is + * not larger than the size of the array. For a 3-element array: + * - Indexes -1 through -3 are in range. + * - Index -4 is out of range. * * == Creating Arrays * - * A new array can be created by using the literal constructor - * []. Arrays can contain different types of objects. For + * You can create an \Array object explicitly with: + * + * - An {array literal}[doc/syntax/literals_rdoc.html#label-Array+Literals]. + * + * You can convert certain objects to Arrays with: + * + * - \Method {Array}[Kernel.html#method-i-Array]. + * + * An \Array can contain different types of objects. For * example, the array below contains an Integer, a String and a Float: * * ary = [1, "two", 3.0] #=> [1, "two", 3.0] * - * An array can also be created by explicitly calling Array.new with zero, one + * An array can also be created by calling Array.new with zero, one * (the initial size of the Array) or two arguments (the initial size and a * default object). * @@ -6913,14 +8076,190 @@ rb_ary_deconstruct(VALUE ary) * arr.keep_if {|a| a < 4} #=> [1, 2, 3] * arr #=> [1, 2, 3] * + * == What's Here + * + * First, what's elsewhere. \Class \Array: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * which provides dozens of additional methods. + * + * Here, class \Array provides methods that are useful for: + * + * - {Creating an Array}[#class-Array-label-Methods+for+Creating+an+Array] + * - {Querying}[#class-Array-label-Methods+for+Querying] + * - {Comparing}[#class-Array-label-Methods+for+Comparing] + * - {Fetching}[#class-Array-label-Methods+for+Fetching] + * - {Assigning}[#class-Array-label-Methods+for+Assigning] + * - {Deleting}[#class-Array-label-Methods+for+Deleting] + * - {Combining}[#class-Array-label-Methods+for+Combining] + * - {Iterating}[#class-Array-label-Methods+for+Iterating] + * - {Converting}[#class-Array-label-Methods+for+Converting] + * - {And more....}[#class-Array-label-Other+Methods] + * + * === Methods for Creating an Array + * + * ::[]:: Returns a new array populated with given objects. + * ::new:: Returns a new array. + * ::try_convert:: Returns a new array created from a given object. + * + * === 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. + * #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 + * {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1 + * as +self+ is less than, equal to, or greater than a given object. + * {#==}[#method-i-3D-3D]:: 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. + * #max:: 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. + * #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. + * #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. + * #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. + * #shuffle:: Returns elements in a random order. + * + * === Methods for Assigning + * + * These methods add, replace, or reorder elements in +self+. + * + * #[]=:: 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. + * #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_by!:: Replaces +self+ with its elements sorted, as determined by a given block. + * + * === 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. + * #compact!:: Removes all non-+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. + * #reject!:: Removes elements specified by a given block. + * #select!, #filter!:: Removes elements not specified by a given block. + * #slice!:: Removes and returns a sequence of elements. + * #uniq!:: Removes duplicates. + * + * === Methods for Combining + * + * {#&}[#method-i-26]:: 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 containiing all elements of +self+ that are not found in a given array. + * {#|}[#method-i-7C]:: 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.. + * #product:: Returns or yields all combinations of elements from +self+ and given arrays. + * + * === Methods for Iterating + * + * #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. + * + * === 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. + * #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. + * #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. + * + * === Other Methods + * + * #*:: Returns one of the following: + * - With integer argument +n+, a new array that is the concatenation + * of +n+ copies of +self+. + * - 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. */ void Init_Array(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - rb_cArray = rb_define_class("Array", rb_cObject); rb_include_module(rb_cArray, rb_mEnumerable); @@ -6950,6 +8289,7 @@ Init_Array(void) rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1); rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1); rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1); + rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1); rb_define_method(rb_cArray, "<<", rb_ary_push, 1); rb_define_method(rb_cArray, "push", rb_ary_push_m, -1); rb_define_alias(rb_cArray, "append", "push"); @@ -6962,7 +8302,7 @@ Init_Array(void) rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0); rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0); rb_define_method(rb_cArray, "length", rb_ary_length, 0); - rb_define_alias(rb_cArray, "size", "length"); + rb_define_method(rb_cArray, "size", rb_ary_length, 0); rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0); rb_define_method(rb_cArray, "find_index", rb_ary_index, -1); rb_define_method(rb_cArray, "index", rb_ary_index, -1); @@ -7022,9 +8362,6 @@ Init_Array(void) rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1); rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1); rb_define_method(rb_cArray, "count", rb_ary_count, -1); - rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1); - rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1); - rb_define_method(rb_cArray, "sample", rb_ary_sample, -1); rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1); rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1); rb_define_method(rb_cArray, "combination", rb_ary_combination, 1); @@ -7046,6 +8383,6 @@ Init_Array(void) rb_define_method(rb_cArray, "sum", rb_ary_sum, -1); rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0); - - id_random = rb_intern("random"); } + +#include "array.rbinc" diff --git a/ruby/array.rb b/ruby/array.rb new file mode 100644 index 000000000..b9fa9844e --- /dev/null +++ b/ruby/array.rb @@ -0,0 +1,69 @@ +class Array + # call-seq: + # array.shuffle!(random: Random) -> array + # + # Shuffles the elements of +self+ in place. + # a = [1, 2, 3] #=> [1, 2, 3] + # a.shuffle! #=> [2, 3, 1] + # a #=> [2, 3, 1] + # + # The optional +random+ argument will be used as the random number generator: + # a.shuffle!(random: Random.new(1)) #=> [1, 3, 2] + def shuffle!(random: Random) + Primitive.rb_ary_shuffle_bang(random) + end + + # call-seq: + # array.shuffle(random: Random) -> new_ary + # + # 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] + # + # The optional +random+ argument will be used as the random number generator: + # a.shuffle(random: Random.new(1)) #=> [1, 3, 2] + def shuffle(random: Random) + Primitive.rb_ary_shuffle(random) + end + + # call-seq: + # array.sample(random: Random) -> object + # array.sample(n, random: Random) -> new_ary + # + # Returns random elements from +self+. + # + # 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+. + # + # 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] + def sample(n = (ary = false), random: Random) + if Primitive.mandatory_only? + # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) } + Primitive.ary_sample0 + else + # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) } + Primitive.ary_sample(random, n, ary) + end + end +end diff --git a/ruby/ast.c b/ruby/ast.c index 1133fb8a1..0515689a2 100644 --- a/ruby/ast.c +++ b/ruby/ast.c @@ -1,11 +1,15 @@ /* indent-tabs-mode: nil */ +#include "internal.h" +#include "internal/parse.h" +#include "internal/symbol.h" +#include "internal/warnings.h" +#include "iseq.h" +#include "node.h" #include "ruby.h" #include "ruby/encoding.h" #include "ruby/util.h" -#include "internal.h" -#include "node.h" #include "vm_core.h" -#include "iseq.h" + #include "builtin.h" static VALUE rb_mAST; @@ -13,7 +17,7 @@ static VALUE rb_cNode; struct ASTNodeData { rb_ast_t *ast; - NODE *node; + const NODE *node; }; static void @@ -40,7 +44,7 @@ static const rb_data_type_t rb_node_type = { static VALUE rb_ast_node_alloc(VALUE klass); static void -setup_node(VALUE obj, rb_ast_t *ast, NODE *node) +setup_node(VALUE obj, rb_ast_t *ast, const NODE *node) { struct ASTNodeData *data; @@ -50,7 +54,7 @@ setup_node(VALUE obj, rb_ast_t *ast, NODE *node) } static VALUE -ast_new_internal(rb_ast_t *ast, NODE *node) +ast_new_internal(rb_ast_t *ast, const NODE *node) { VALUE obj; @@ -60,9 +64,8 @@ ast_new_internal(rb_ast_t *ast, NODE *node) return obj; } -static VALUE rb_ast_parse_str(VALUE str); -static VALUE rb_ast_parse_file(VALUE path); -static VALUE rb_ast_parse_array(VALUE array); +static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines); +static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines); static VALUE ast_parse_new(void) @@ -82,29 +85,31 @@ ast_parse_done(rb_ast_t *ast) } static VALUE -ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str) +ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines) { - return rb_ast_parse_str(str); + return rb_ast_parse_str(str, keep_script_lines); } static VALUE -rb_ast_parse_str(VALUE str) +rb_ast_parse_str(VALUE str, VALUE keep_script_lines) { rb_ast_t *ast = 0; StringValue(str); - ast = rb_parser_compile_string_path(ast_parse_new(), Qnil, str, 1); + VALUE vparser = ast_parse_new(); + if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + ast = rb_parser_compile_string_path(vparser, Qnil, str, 1); return ast_parse_done(ast); } static VALUE -ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path) +ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines) { - return rb_ast_parse_file(path); + return rb_ast_parse_file(path, keep_script_lines); } static VALUE -rb_ast_parse_file(VALUE path) +rb_ast_parse_file(VALUE path, VALUE keep_script_lines) { VALUE f; rb_ast_t *ast = 0; @@ -113,7 +118,9 @@ rb_ast_parse_file(VALUE path) 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("-")); - ast = rb_parser_compile_file_path(ast_parse_new(), Qnil, f, 1); + VALUE vparser = ast_parse_new(); + if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + ast = rb_parser_compile_file_path(vparser, Qnil, f, 1); rb_io_close(f); return ast_parse_done(ast); } @@ -132,16 +139,18 @@ lex_array(VALUE array, int index) } static VALUE -rb_ast_parse_array(VALUE array) +rb_ast_parse_array(VALUE array, VALUE keep_script_lines) { rb_ast_t *ast = 0; array = rb_check_array_type(array); - ast = rb_parser_compile_generic(ast_parse_new(), lex_array, Qnil, array, 1); + VALUE vparser = ast_parse_new(); + if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1); return ast_parse_done(ast); } -static VALUE node_children(rb_ast_t*, NODE*); +static VALUE node_children(rb_ast_t*, const NODE*); static VALUE node_find(VALUE self, const int node_id) @@ -184,35 +193,52 @@ script_lines(VALUE path) } static VALUE -ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body) +ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines) { - VALUE path, node, lines; + VALUE node, lines = Qnil; + const rb_iseq_t *iseq; int node_id; - const rb_iseq_t *iseq = NULL; - if (rb_obj_is_proc(body)) { - iseq = vm_proc_iseq(body); + if (rb_frame_info_p(body)) { + iseq = rb_get_iseq_from_frame_info(body); + node_id = rb_get_node_id_from_frame_info(body); + } + else { + iseq = NULL; + + if (rb_obj_is_proc(body)) { + iseq = vm_proc_iseq(body); - if (!rb_obj_is_iseq((VALUE)iseq)) { - iseq = NULL; + if (!rb_obj_is_iseq((VALUE)iseq)) return Qnil; + } + else { + iseq = rb_method_iseq(body); + } + if (iseq) { + node_id = iseq->body->location.node_id; } } - else { - iseq = rb_method_iseq(body); + + if (!iseq) { + return Qnil; } + lines = iseq->body->variable.script_lines; - if (!iseq) return Qnil; + VALUE path = rb_iseq_path(iseq); + int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0; + + if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) { + rb_raise(rb_eArgError, "cannot get AST for method defined in eval"); + } - path = rb_iseq_path(iseq); - node_id = iseq->body->location.node_id; - if (!NIL_P(lines = script_lines(path))) { - node = rb_ast_parse_array(lines); + if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) { + node = rb_ast_parse_array(lines, keep_script_lines); } - else if (RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0) { - node = rb_ast_parse_str(rb_e_script); + else if (e_option) { + node = rb_ast_parse_str(rb_e_script, keep_script_lines); } else { - node = rb_ast_parse_file(path); + node = rb_ast_parse_file(path, keep_script_lines); } return node_find(node, node_id); @@ -242,6 +268,15 @@ ast_node_type(rb_execution_context_t *ec, VALUE self) return rb_sym_intern_ascii_cstr(node_type_to_str(data->node)); } +static VALUE +ast_node_node_id(rb_execution_context_t *ec, VALUE self) +{ + struct ASTNodeData *data; + TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); + + return INT2FIX(nd_node_id(data->node)); +} + #define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil static VALUE @@ -264,13 +299,13 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...) } static VALUE -dump_block(rb_ast_t *ast, NODE *node) +dump_block(rb_ast_t *ast, const NODE *node) { VALUE ary = rb_ary_new(); do { rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); } while (node->nd_next && - nd_type(node->nd_next) == NODE_BLOCK && + nd_type_p(node->nd_next, NODE_BLOCK) && (node = node->nd_next, 1)); if (node->nd_next) { rb_ary_push(ary, NEW_CHILD(ast, node->nd_next)); @@ -280,12 +315,12 @@ dump_block(rb_ast_t *ast, NODE *node) } static VALUE -dump_array(rb_ast_t *ast, NODE *node) +dump_array(rb_ast_t *ast, const NODE *node) { VALUE ary = rb_ary_new(); rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); - while (node->nd_next && nd_type(node->nd_next) == NODE_LIST) { + 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)); } @@ -303,7 +338,21 @@ var_name(ID id) } static VALUE -node_children(rb_ast_t *ast, NODE *node) +no_name_rest(void) +{ + ID rest; + CONST_ID(rest, "NODE_SPECIAL_NO_NAME_REST"); + return ID2SYM(rest); +} + +static VALUE +rest_arg(rb_ast_t *ast, const NODE *rest_arg) +{ + return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest(); +} + +static VALUE +node_children(rb_ast_t *ast, const NODE *node) { char name[DECIMAL_SIZE_OF_BITS(sizeof(long) * CHAR_BIT) + 2]; /* including '$' */ @@ -326,22 +375,17 @@ node_children(rb_ast_t *ast, NODE *node) case NODE_IN: return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next); case NODE_WHILE: - goto loop; case NODE_UNTIL: - loop: return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body), - (node->nd_state ? Qtrue : Qfalse)); + RBOOL(node->nd_state)); case NODE_ITER: case NODE_FOR: return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body); case NODE_FOR_MASGN: return rb_ary_new_from_node_args(ast, 1, node->nd_var); case NODE_BREAK: - goto jump; case NODE_NEXT: - goto jump; case NODE_RETURN: - jump: return rb_ary_new_from_node_args(ast, 1, node->nd_stts); case NODE_REDO: return rb_ary_new_from_node_args(ast, 0); @@ -356,15 +400,13 @@ node_children(rb_ast_t *ast, NODE *node) case NODE_ENSURE: return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_ensr); case NODE_AND: - goto andor; case NODE_OR: - andor: { VALUE ary = rb_ary_new(); while (1) { rb_ary_push(ary, NEW_CHILD(ast, node->nd_1st)); - if (!node->nd_2nd || nd_type(node->nd_2nd) != (int)type) + if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type)) break; node = node->nd_2nd; } @@ -378,24 +420,17 @@ node_children(rb_ast_t *ast, NODE *node) else { return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_value), NEW_CHILD(ast, node->nd_head), - ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST"))); + no_name_rest()); } case NODE_LASGN: - goto asgn; case NODE_DASGN: - goto asgn; - case NODE_DASGN_CURR: - goto asgn; case NODE_IASGN: - goto asgn; case NODE_CVASGN: - asgn: + 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)); - case NODE_GASGN: - goto asgn; case NODE_CDECL: if (node->nd_vid) { return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value)); @@ -407,9 +442,10 @@ node_children(rb_ast_t *ast, NODE *node) NEW_CHILD(ast, node->nd_args->nd_head), NEW_CHILD(ast, node->nd_args->nd_body)); case NODE_OP_ASGN2: - return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_recv), - node->nd_next->nd_aid ? Qtrue : Qfalse, + 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)); case NODE_OP_ASGN_AND: return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idANDOP), @@ -437,9 +473,7 @@ node_children(rb_ast_t *ast, NODE *node) case NODE_ZSUPER: return rb_ary_new_from_node_args(ast, 0); case NODE_LIST: - goto ary; case NODE_VALUES: - ary: return dump_array(ast, node); case NODE_ZLIST: return rb_ary_new_from_node_args(ast, 0); @@ -463,8 +497,6 @@ node_children(rb_ast_t *ast, NODE *node) name[1] = (char)node->nd_nth; name[2] = '\0'; return rb_ary_new_from_args(1, ID2SYM(rb_intern(name))); - case NODE_MATCH: - goto lit; 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); @@ -472,26 +504,26 @@ node_children(rb_ast_t *ast, NODE *node) return rb_ary_new_from_node_args(ast, 2, node->nd_recv, 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: - goto lit; case NODE_STR: - goto lit; case NODE_XSTR: - lit: return rb_ary_new_from_args(1, node->nd_lit); case NODE_ONCE: return rb_ary_new_from_node_args(ast, 1, node->nd_body); case NODE_DSTR: - goto dlit; case NODE_DXSTR: - goto dlit; case NODE_DREGX: - goto dlit; case NODE_DSYM: - dlit: - return rb_ary_new_from_args(3, node->nd_lit, - NEW_CHILD(ast, node->nd_next->nd_head), - NEW_CHILD(ast, node->nd_next->nd_next)); + { + NODE *n = node->nd_next; + VALUE head = Qnil, next = Qnil; + if (n) { + head = NEW_CHILD(ast, n->nd_head); + next = NEW_CHILD(ast, n->nd_next); + } + return rb_ary_new_from_args(3, node->nd_lit, head, next); + } case NODE_EVSTR: return rb_ary_new_from_node_args(ast, 1, node->nd_body); case NODE_ARGSCAT: @@ -523,13 +555,9 @@ node_children(rb_ast_t *ast, NODE *node) case NODE_COLON3: return rb_ary_new_from_args(1, ID2SYM(node->nd_mid)); case NODE_DOT2: - goto dot; case NODE_DOT3: - goto dot; case NODE_FLIP2: - goto dot; case NODE_FLIP3: - dot: return rb_ary_new_from_node_args(ast, 2, node->nd_beg, node->nd_end); case NODE_SELF: return rb_ary_new_from_node_args(ast, 0); @@ -557,7 +585,7 @@ node_children(rb_ast_t *ast, NODE *node) if (NODE_NAMED_REST_P(node->nd_1st)) { return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd); } - return rb_ary_new_from_args(2, ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST")), + return rb_ary_new_from_args(2, no_name_rest(), NEW_CHILD(ast, node->nd_2nd)); case NODE_ARGS: { @@ -569,32 +597,44 @@ node_children(rb_ast_t *ast, NODE *node) var_name(ainfo->first_post_arg), INT2NUM(ainfo->post_args_num), NEW_CHILD(ast, ainfo->post_init), - var_name(ainfo->rest_arg), + (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)), var_name(ainfo->block_arg)); } case NODE_SCOPE: { - ID *tbl = node->nd_tbl; - int i, size = tbl ? (int)*tbl++ : 0; + rb_ast_id_table_t *tbl = 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[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)); } case NODE_ARYPTN: { struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - VALUE rest = NODE_NAMED_REST_P(apinfo->rest_arg) ? NEW_CHILD(ast, apinfo->rest_arg) : - ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST")); + VALUE rest = rest_arg(ast, apinfo->rest_arg); return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_pconst), NEW_CHILD(ast, apinfo->pre_args), rest, NEW_CHILD(ast, apinfo->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); + return rb_ary_new_from_args(4, + NEW_CHILD(ast, node->nd_pconst), + pre_rest, + NEW_CHILD(ast, fpinfo->args), + post_rest); + } case NODE_HSHPTN: { VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) : @@ -678,6 +718,16 @@ ast_node_inspect(rb_execution_context_t *ec, VALUE self) return str; } +static VALUE +ast_node_script_lines(rb_execution_context_t *ec, VALUE self) +{ + struct ASTNodeData *data; + 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; +} + #include "ast.rbinc" void @@ -686,6 +736,4 @@ Init_ast(void) rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree"); rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject); rb_undef_alloc_func(rb_cNode); - - load_ast(); } diff --git a/ruby/ast.rb b/ruby/ast.rb index 1fedf7664..f866bd23e 100644 --- a/ruby/ast.rb +++ b/ruby/ast.rb @@ -1,143 +1,189 @@ # for ast.c -class RubyVM +# AbstractSyntaxTree provides methods to parse Ruby code into +# abstract syntax trees. The nodes in the tree +# are instances of RubyVM::AbstractSyntaxTree::Node. +# +# This module is MRI specific as it exposes implementation details +# of the MRI abstract syntax tree. +# +# This module is experimental and its API is not stable, therefore it might +# change without notice. As examples, the order of children nodes is not +# guaranteed, the number of children nodes might change, there is no way to +# 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. +# +module RubyVM::AbstractSyntaxTree - # AbstractSyntaxTree provides methods to parse Ruby code into - # abstract syntax trees. The nodes in the tree - # are instances of RubyVM::AbstractSyntaxTree::Node. + # call-seq: + # RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node # - # This class is MRI specific as it exposes implementation details - # of the MRI abstract syntax tree. + # Parses the given _string_ into an abstract syntax tree, + # returning the root node of that tree. # - # This class is experimental and its API is not stable, therefore it might - # change without notice. As examples, the order of children nodes is not - # guaranteed, the number of children nodes might change, there is no way to - # access children nodes by name, etc. + # SyntaxError is raised if the given _string_ is invalid syntax. # - # 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. + # RubyVM::AbstractSyntaxTree.parse("x = 1 + 2") + # # => # + def self.parse string, keep_script_lines: false + Primitive.ast_s_parse string, keep_script_lines + end + + # call-seq: + # RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node + # + # Reads the file from _pathname_, then parses it like ::parse, + # returning the root node of the abstract syntax tree. + # + # SyntaxError is raised if _pathname_'s contents are not + # valid Ruby syntax. + # + # RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb") + # # => # + def self.parse_file pathname, keep_script_lines: false + Primitive.ast_s_parse_file pathname, keep_script_lines + end + + # call-seq: + # RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node + # RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node + # + # Returns AST nodes of the given _proc_ or _method_. + # + # RubyVM::AbstractSyntaxTree.of(proc {1 + 2}) + # # => # + # + # def hello + # puts "hello, world" + # end + # + # RubyVM::AbstractSyntaxTree.of(method(:hello)) + # # => # + def self.of body, keep_script_lines: false + Primitive.ast_s_of body, keep_script_lines + end + + # RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in + # RubyVM::AbstractSyntaxTree. + # + # This class is MRI specific. # - module AbstractSyntaxTree + class Node # call-seq: - # RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node + # node.type -> symbol # - # Parses the given _string_ into an abstract syntax tree, - # returning the root node of that tree. + # Returns the type of this node as a symbol. # - # SyntaxError is raised if the given _string_ is invalid syntax. + # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2") + # root.type # => :SCOPE + # lasgn = root.children[2] + # lasgn.type # => :LASGN + # call = lasgn.children[1] + # call.type # => :OPCALL + def type + Primitive.ast_node_type + end + + # call-seq: + # node.first_lineno -> integer # - # RubyVM::AbstractSyntaxTree.parse("x = 1 + 2") - # # => # - def self.parse string - __builtin_ast_s_parse string + # The line number in the source code where this AST's text began. + def first_lineno + Primitive.ast_node_first_lineno end # call-seq: - # RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node + # node.first_column -> integer # - # Reads the file from _pathname_, then parses it like ::parse, - # returning the root node of the abstract syntax tree. + # The column number in the source code where this AST's text began. + def first_column + Primitive.ast_node_first_column + end + + # call-seq: + # node.last_lineno -> integer # - # SyntaxError is raised if _pathname_'s contents are not - # valid Ruby syntax. + # The line number in the source code where this AST's text ended. + def last_lineno + Primitive.ast_node_last_lineno + end + + # call-seq: + # node.last_column -> integer # - # RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb") - # # => # - def self.parse_file pathname - __builtin_ast_s_parse_file pathname + # The column number in the source code where this AST's text ended. + def last_column + Primitive.ast_node_last_column end # call-seq: - # RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node - # RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node + # node.children -> array # - # Returns AST nodes of the given _proc_ or _method_. + # Returns AST nodes under this one. Each kind of node + # has different children, depending on what kind of node it is. # - # RubyVM::AbstractSyntaxTree.of(proc {1 + 2}) - # # => # + # The returned array may contain other nodes or nil. + def children + Primitive.ast_node_children + end + + # call-seq: + # node.inspect -> string # - # def hello - # puts "hello, world" - # end + # Returns debugging information about this node as a string. + def inspect + Primitive.ast_node_inspect + end + + # call-seq: + # node.node_id -> integer # - # RubyVM::AbstractSyntaxTree.of(method(:hello)) - # # => # - def self.of body - __builtin_ast_s_of body + # Returns an internal node_id number. + # Note that this is an API for ruby internal use, debugging, + # and research. Do not use this for any other purpose. + # The compatibility is not guaranteed. + def node_id + Primitive.ast_node_node_id end - # RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in - # RubyVM::AbstractSyntaxTree. + # call-seq: + # node.script_lines -> array # - # This class is MRI specific. + # Returns the original source code as an array of lines. # - class Node - - # call-seq: - # node.type -> symbol - # - # Returns the type of this node as a symbol. - # - # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2") - # root.type # => :SCOPE - # call = root.children[2] - # call.type # => :OPCALL - def type - __builtin_ast_node_type - end - - # call-seq: - # node.first_lineno -> integer - # - # The line number in the source code where this AST's text began. - def first_lineno - __builtin_ast_node_first_lineno - end - - # call-seq: - # node.first_column -> integer - # - # The column number in the source code where this AST's text began. - def first_column - __builtin_ast_node_first_column - end - - # call-seq: - # node.last_lineno -> integer - # - # The line number in the source code where this AST's text ended. - def last_lineno - __builtin_ast_node_last_lineno - end - - # call-seq: - # node.last_column -> integer - # - # The column number in the source code where this AST's text ended. - def last_column - __builtin_ast_node_last_column - end - - # call-seq: - # node.children -> array - # - # Returns AST nodes under this one. Each kind of node - # has different children, depending on what kind of node it is. - # - # The returned array may contain other nodes or nil. - def children - __builtin_ast_node_children - end + # Note that this is an API for ruby internal use, debugging, + # and research. Do not use this for any other purpose. + # The compatibility is not guaranteed. + def script_lines + Primitive.ast_node_script_lines + end - # call-seq: - # node.inspect -> string - # - # Returns debugging information about this node as a string. - def inspect - __builtin_ast_node_inspect + # call-seq: + # node.source -> string + # + # Returns the code fragment that corresponds to this AST. + # + # Note that this is an API for ruby internal use, debugging, + # and research. Do not use this for any other purpose. + # The compatibility is not guaranteed. + # + # Also note that this API may return an incomplete code fragment + # that does not parse; for example, a here document following + # an expression may be dropped. + 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.join + else + nil end end end diff --git a/ruby/ast.rbinc b/ruby/ast.rbinc index c7bbe4cec..63c34ca83 100644 --- a/ruby/ast.rbinc +++ b/ruby/ast.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with ast.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_ast(void) +void Init_builtin_ast(void) { // table definition static const struct rb_builtin_function ast_table[] = { diff --git a/ruby/autogen.sh b/ruby/autogen.sh new file mode 100755 index 000000000..f8cdf3c0c --- /dev/null +++ b/ruby/autogen.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +PWD= +case "$0" in +*/*) srcdir=`dirname $0`;; +*) srcdir="";; +esac + +symlink='--install --symlink' +case " $* " in + *" -i "*|*" --install "*) + # reset to copy missing standard auxiliary files, instead of symlinks + symlink= + ;; +esac + +exec ${AUTORECONF:-autoreconf} ${symlink} "$@" ${srcdir:+"$srcdir"} diff --git a/ruby/basictest/test.rb b/ruby/basictest/test.rb index 25a429823..52008b78d 100755 --- a/ruby/basictest/test.rb +++ b/ruby/basictest/test.rb @@ -1425,9 +1425,6 @@ def marity_test(m) marity_test(:marity_test) marity_test(:p) -lambda(&method(:test_ok)).call(true) -lambda(&block_get{|a,n| test_ok(a,n)}).call(true, 2) - class ITER_TEST1 def a block_given? @@ -2140,7 +2137,7 @@ module M003; include M002; end test_ok($_ == foobar) class Gods - @@rule = "Uranus" # private to Gods + @@rule = "Uranus" def ruler0 @@rule end @@ -2163,7 +2160,7 @@ def ruler3 end class Titans < Gods - @@rule = "Cronus" # do not affect @@rule in Gods + @@rule = "Cronus" # modifies @@rule in Gods include Olympians def ruler4 @@rule @@ -2178,7 +2175,14 @@ def ruler4 atlas = Titans.new test_ok(atlas.ruler0 == "Cronus") test_ok(atlas.ruler3 == "Zeus") -test_ok(atlas.ruler4 == "Cronus") +begin + atlas.ruler4 +rescue RuntimeError => e + test_ok(e.message.include?("class variable @@rule of Olympians is overtaken by Gods")) +else + test_ok(false) +end +test_ok(atlas.ruler3 == "Zeus") test_check "trace" $x = 1234 diff --git a/ruby/benchmark/README.md b/ruby/benchmark/README.md index 24a266914..c222164be 100644 --- a/ruby/benchmark/README.md +++ b/ruby/benchmark/README.md @@ -37,7 +37,7 @@ Usage: benchmark-driver [options] RUBY|YAML... --bundler Install and use gems specified in Gemfile --filter REGEXP Filter out benchmarks with given regexp --run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3) - -v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2) + -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2) ``` ## make benchmark @@ -53,20 +53,20 @@ make benchmark # Or compare with specific ruby binary make benchmark COMPARE_RUBY="/path/to/ruby --jit" -# Run vm1 benchmarks -make benchmark ITEM=vm1 +# Run vm benchmarks +make benchmark ITEM=vm # Run some limited benchmarks in ITEM-matched files -make benchmark ITEM=vm1 OPTS=--filter=block +make benchmark ITEM=vm OPTS=--filter=block # You can specify the benchmark by an exact filename instead of using the default argument: # ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb') -make benchmark ARGS=../benchmark/erb_render.yml +make benchmark ARGS=benchmark/erb_render.yml # You can specify any option via $OPTS make benchmark OPTS="--help" # With `make benchmark`, some special runner plugins are available: # -r peak, -r size, -r total, -r utime, -r stime, -r cutime, -r cstime -make benchmark ITEM=vm2_bigarray OPTS="-r peak" +make benchmark ITEM=vm_bigarray OPTS="-r peak" ``` diff --git a/ruby/benchmark/array_max_float.yml b/ruby/benchmark/array_max_float.yml new file mode 100644 index 000000000..ace1ae2e1 --- /dev/null +++ b/ruby/benchmark/array_max_float.yml @@ -0,0 +1,30 @@ +prelude: | + ary2 = 2.times.map(&:to_f).shuffle + ary10 = 10.times.map(&:to_f).shuffle + ary100 = 100.times.map(&:to_f).shuffle + ary500 = 500.times.map(&:to_f).shuffle + ary1000 = 1000.times.map(&:to_f).shuffle + ary2000 = 2500.times.map(&:to_f).shuffle + ary3000 = 2500.times.map(&:to_f).shuffle + ary5000 = 5000.times.map(&:to_f).shuffle + ary10000 = 10000.times.map(&:to_f).shuffle + ary20000 = 20000.times.map(&:to_f).shuffle + ary50000 = 50000.times.map(&:to_f).shuffle + ary100000 = 100000.times.map(&:to_f).shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + +loop_count: 10000 + diff --git a/ruby/benchmark/array_max_int.yml b/ruby/benchmark/array_max_int.yml new file mode 100644 index 000000000..acd83684d --- /dev/null +++ b/ruby/benchmark/array_max_int.yml @@ -0,0 +1,31 @@ +prelude: | + ary2 = 2.times.to_a.shuffle + ary10 = 10.times.to_a.shuffle + ary100 = 100.times.to_a.shuffle + ary500 = 500.times.to_a.shuffle + ary1000 = 1000.times.to_a.shuffle + ary2000 = 2500.times.to_a.shuffle + ary3000 = 2500.times.to_a.shuffle + ary5000 = 5000.times.to_a.shuffle + ary10000 = 10000.times.to_a.shuffle + ary20000 = 20000.times.to_a.shuffle + ary50000 = 50000.times.to_a.shuffle + ary100000 = 100000.times.to_a.shuffle + ary1000000 = 1000000.times.to_a.shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + ary1000000.max: ary1000000.max + +loop_count: 10000 diff --git a/ruby/benchmark/array_max_str.yml b/ruby/benchmark/array_max_str.yml new file mode 100644 index 000000000..2aeed010f --- /dev/null +++ b/ruby/benchmark/array_max_str.yml @@ -0,0 +1,30 @@ +prelude: | + ary2 = 2.times.map(&:to_s).shuffle + ary10 = 10.times.map(&:to_s).shuffle + ary100 = 100.times.map(&:to_s).shuffle + ary500 = 500.times.map(&:to_s).shuffle + ary1000 = 1000.times.map(&:to_s).shuffle + ary2000 = 2500.times.map(&:to_s).shuffle + ary3000 = 2500.times.map(&:to_s).shuffle + ary5000 = 5000.times.map(&:to_s).shuffle + ary10000 = 10000.times.map(&:to_s).shuffle + ary20000 = 20000.times.map(&:to_s).shuffle + ary50000 = 50000.times.map(&:to_s).shuffle + ary100000 = 100000.times.map(&:to_s).shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + +loop_count: 10000 + diff --git a/ruby/benchmark/array_min.yml b/ruby/benchmark/array_min.yml new file mode 100644 index 000000000..53e5072b1 --- /dev/null +++ b/ruby/benchmark/array_min.yml @@ -0,0 +1,31 @@ +prelude: | + ary2 = 2.times.to_a.shuffle + ary10 = 10.times.to_a.shuffle + ary100 = 100.times.to_a.shuffle + ary500 = 500.times.to_a.shuffle + ary1000 = 1000.times.to_a.shuffle + ary2000 = 2500.times.to_a.shuffle + ary3000 = 2500.times.to_a.shuffle + ary5000 = 5000.times.to_a.shuffle + ary10000 = 10000.times.to_a.shuffle + ary20000 = 20000.times.to_a.shuffle + ary50000 = 50000.times.to_a.shuffle + ary100000 = 100000.times.to_a.shuffle + ary1000000 = 1000000.times.to_a.shuffle + +benchmark: + ary2.min: ary2.min + ary10.min: ary10.min + ary100.min: ary100.min + ary500.min: ary500.min + ary1000.min: ary1000.min + ary2000.min: ary2000.min + ary3000.min: ary3000.min + ary5000.min: ary5000.min + ary10000.min: ary10000.min + ary20000.min: ary20000.min + ary50000.min: ary50000.min + ary100000.min: ary100000.min + ary1000000.min: ary1000000.min + +loop_count: 10000 diff --git a/ruby/benchmark/array_sample.yml b/ruby/benchmark/array_sample.yml new file mode 100644 index 000000000..1cd2b3479 --- /dev/null +++ b/ruby/benchmark/array_sample.yml @@ -0,0 +1,4 @@ +prelude: ary = (1..10_000).to_a +benchmark: + - ary.sample + - ary.sample(2) diff --git a/ruby/benchmark/attr_accessor.yml b/ruby/benchmark/attr_accessor.yml new file mode 100644 index 000000000..82134cdf9 --- /dev/null +++ b/ruby/benchmark/attr_accessor.yml @@ -0,0 +1,29 @@ +prelude: | + class C + attr_accessor :x + def initialize + @x = nil + end + class_eval <<-END + def ar + #{'x;'*256} + end + def aw + #{'self.x = nil;'*256} + end + def arm + m = method(:x) + #{'m.call;'*256} + end + def awm + m = method(:x=) + #{'m.call(nil);'*256} + end + END + end + obj = C.new +benchmark: + attr_reader: "obj.ar" + attr_writer: "obj.aw" + attr_reader_method: "obj.arm" + attr_writer_method: "obj.awm" diff --git a/ruby/benchmark/buffer_get.yml b/ruby/benchmark/buffer_get.yml new file mode 100644 index 000000000..e375dcf85 --- /dev/null +++ b/ruby/benchmark/buffer_get.yml @@ -0,0 +1,9 @@ +benchmark: + - name: buffer.get + prelude: buffer = IO::Buffer.new(32, IO::Buffer::MAPPED) + script: buffer.get(:U32, 0) + loop_count: 20000000 + - name: string.unpack + prelude: string = "\0" * 32 + script: string.unpack("C") + loop_count: 20000000 diff --git a/ruby/benchmark/enum_lazy_flat_map.yml b/ruby/benchmark/enum_lazy_flat_map.yml new file mode 100644 index 000000000..0ee390a44 --- /dev/null +++ b/ruby/benchmark/enum_lazy_flat_map.yml @@ -0,0 +1,16 @@ +prelude: | + num = (1..).lazy.take(100) + ary2 = [[1,2]].cycle.lazy.take(10) + ary10 = [[*1..10]].cycle.lazy.take(10) + ary20 = [[*1..20]].cycle.lazy.take(10) + ary50 = [[*1..50]].cycle.lazy.take(10) + ary100 = [[*1..100]].cycle.lazy.take(10) + +benchmark: + num3: num.flat_map {|x| x}.take(3).to_a + num10: num.flat_map {|x| x}.take(3).to_a + ary2: ary2.flat_map {|x| x}.take(3).to_a + ary10: ary10.flat_map {|x| x}.take(3).to_a + ary20: ary20.flat_map {|x| x}.take(3).to_a + ary50: ary50.flat_map {|x| x}.take(3).to_a + ary100: ary100.flat_map {|x| x}.take(3).to_a diff --git a/ruby/benchmark/enum_lazy_zip.yml b/ruby/benchmark/enum_lazy_zip.yml new file mode 100644 index 000000000..4566ff026 --- /dev/null +++ b/ruby/benchmark/enum_lazy_zip.yml @@ -0,0 +1,22 @@ +prelude: | + a = (1..3).lazy + b = a.map {|x| x} + +benchmark: + first_ary: a.zip(["a", "b", "c"]).first + first_nonary: a.zip("a".."c").first + first_noarg: a.zip.first + + take3_ary: a.zip(["a", "b", "c"]).take(3).force + take3_nonary: a.zip("a".."c").take(3).force + take3_noarg: a.zip.take(3).force + + chain-first_ary: b.zip(["a", "b", "c"]).first + chain-first_nonary: b.zip("a".."c").first + chain-first_noarg: b.zip.first + + chain-take3_ary: b.zip(["a", "b", "c"]).take(3).force + chain-take3_nonary: b.zip("a".."c").take(3).force + chain-take3_noarg: b.zip.take(3).force + + block: a.zip("a".."c") {|x, y| [x, y]} diff --git a/ruby/benchmark/enum_tally.yml b/ruby/benchmark/enum_tally.yml new file mode 100644 index 000000000..edd2e040a --- /dev/null +++ b/ruby/benchmark/enum_tally.yml @@ -0,0 +1,4 @@ +prelude: | + list = ("aaa".."zzz").to_a*10 +benchmark: + tally: list.tally diff --git a/ruby/benchmark/fiber_chain.yml b/ruby/benchmark/fiber_chain.yml old mode 100755 new mode 100644 diff --git a/ruby/benchmark/fiber_locals.yml b/ruby/benchmark/fiber_locals.yml new file mode 100644 index 000000000..858868647 --- /dev/null +++ b/ruby/benchmark/fiber_locals.yml @@ -0,0 +1,8 @@ +prelude: | + th = Thread.current + th[:key] = :val +benchmark: + key?: th.key?(:key) + []: th[:key] + keys: th.keys +loop_count: 1_000_000 diff --git a/ruby/benchmark/float_methods.yml b/ruby/benchmark/float_methods.yml new file mode 100644 index 000000000..56ea41eff --- /dev/null +++ b/ruby/benchmark/float_methods.yml @@ -0,0 +1,14 @@ +prelude: | + flo = 4.2 +benchmark: + to_f: | + flo.to_f + abs: | + flo.abs + magnitude: | + flo.magnitude + -@: | + -flo + zero?: | + flo.zero? +loop_count: 20000000 diff --git a/ruby/benchmark/float_neg_posi.yml b/ruby/benchmark/float_neg_posi.yml new file mode 100644 index 000000000..172db1bf6 --- /dev/null +++ b/ruby/benchmark/float_neg_posi.yml @@ -0,0 +1,8 @@ +prelude: | + flo = 4.2 +benchmark: + negative?: | + flo.negative? + positive?: | + flo.positive? +loop_count: 20000000 diff --git a/ruby/benchmark/float_to_s.yml b/ruby/benchmark/float_to_s.yml new file mode 100644 index 000000000..0abae5cdb --- /dev/null +++ b/ruby/benchmark/float_to_s.yml @@ -0,0 +1,7 @@ +prelude: | + floats = [*0.0.step(1.0, 0.0001)] + +benchmark: + to_s: floats.each {|f| f.to_s} + +loop_count: 1000 diff --git a/ruby/benchmark/hash_aref_array.rb b/ruby/benchmark/hash_aref_array.rb new file mode 100644 index 000000000..ac7a683d9 --- /dev/null +++ b/ruby/benchmark/hash_aref_array.rb @@ -0,0 +1,5 @@ +h = {} +arrays = (0..99).each_slice(10).to_a +#STDERR.puts arrays.inspect +arrays.each { |s| h[s] = s } +200_000.times { arrays.each { |s| h[s] } } diff --git a/ruby/benchmark/hash_defaults.yml b/ruby/benchmark/hash_defaults.yml new file mode 100644 index 000000000..833f10e1c --- /dev/null +++ b/ruby/benchmark/hash_defaults.yml @@ -0,0 +1,6 @@ +prelude: | + h = Hash.new { :foo } +benchmark: + default_aref: h[1] + default_method: h.default(1) +loop_count: 1000000 diff --git a/ruby/benchmark/hash_first.yml b/ruby/benchmark/hash_first.yml new file mode 100644 index 000000000..c26df1a7e --- /dev/null +++ b/ruby/benchmark/hash_first.yml @@ -0,0 +1,11 @@ +prelude: | + hash1 = 1_000_000.times.to_h { [rand, true]} + hash2 = hash1.dup + hash2.keys[1..100_000].each { hash2.delete _1 } + hash2.delete hash2.first[0] + +benchmark: + hash1: hash1.first + hash2: hash2.first + +loop_count: 100_000 diff --git a/ruby/benchmark/iseq_load_from_binary.yml b/ruby/benchmark/iseq_load_from_binary.yml new file mode 100644 index 000000000..7e9d73bdd --- /dev/null +++ b/ruby/benchmark/iseq_load_from_binary.yml @@ -0,0 +1,25 @@ +prelude: | + symbol = RubyVM::InstructionSequence.compile(":foo; :bar; :baz; :egg; :spam").to_binary + + define_method = RubyVM::InstructionSequence.compile(%{ + def foo; end + def bar; end + def baz; end + def egg; end + def spam; end + }).to_binary + + all = RubyVM::InstructionSequence.compile(%{ + module Foo; def foo; :foo; end; end + module Bar; def bar; :bar; end; end + module Baz; def baz; :baz; end; end + class Egg; def egg; :egg; end; end + class Spaml; def spam; :spam; end; end + }).to_binary + +benchmark: + symbol: RubyVM::InstructionSequence.load_from_binary(symbol) + define_method: RubyVM::InstructionSequence.load_from_binary(define_method) + all: RubyVM::InstructionSequence.load_from_binary(all) + +loop_count: 100_000 diff --git a/ruby/benchmark/ivar_extend.yml b/ruby/benchmark/ivar_extend.yml new file mode 100644 index 000000000..eb9ee923f --- /dev/null +++ b/ruby/benchmark/ivar_extend.yml @@ -0,0 +1,23 @@ +prelude: | + class Embedded + def initialize + @a = 1 + @b = 1 + @c = 1 + end + end + + class Extended + def initialize + @a = 1 + @b = 1 + @c = 1 + @d = 1 + @e = 1 + @f = 1 + end + end +benchmark: + embedded: Embedded.new + extended: Extended.new +loop_count: 20_000_000 diff --git a/ruby/benchmark/kernel_clone.yml b/ruby/benchmark/kernel_clone.yml new file mode 100644 index 000000000..069b23abc --- /dev/null +++ b/ruby/benchmark/kernel_clone.yml @@ -0,0 +1,6 @@ +prelude: "object = Object.new" +benchmark: + clone: "object.clone" + clone_true: "object.clone(freeze: true)" + clone_false: "object.clone(freeze: false)" +loop_count: 10000 diff --git a/ruby/benchmark/kernel_float.yml b/ruby/benchmark/kernel_float.yml new file mode 100644 index 000000000..215f6750f --- /dev/null +++ b/ruby/benchmark/kernel_float.yml @@ -0,0 +1,5 @@ +benchmark: + float: "Float(42)" + float_true: "Float(42, exception: true)" + float_false: "Float(42, exception: false)" +loop_count: 10000 diff --git a/ruby/benchmark/kernel_tap.yml b/ruby/benchmark/kernel_tap.yml new file mode 100644 index 000000000..4dcbb31b4 --- /dev/null +++ b/ruby/benchmark/kernel_tap.yml @@ -0,0 +1,6 @@ +prelude: | + obj = Object.new + x = nil +benchmark: + kernel_tap: obj.tap { |o| x = o } +loop_count: 20000000 diff --git a/ruby/benchmark/kernel_then.yml b/ruby/benchmark/kernel_then.yml new file mode 100644 index 000000000..85f7341e3 --- /dev/null +++ b/ruby/benchmark/kernel_then.yml @@ -0,0 +1,6 @@ +benchmark: + kernel_then: 1.then { |i| i + 1 } + kernel_then_enum: 1.then + kernel_yield_self: 1.yield_self { |i| i + 1 } + kernel_yield_self_enum: 1.yield_self +loop_count: 20000000 diff --git a/ruby/benchmark/keyword_arguments.yml b/ruby/benchmark/keyword_arguments.yml new file mode 100644 index 000000000..fce6bce0b --- /dev/null +++ b/ruby/benchmark/keyword_arguments.yml @@ -0,0 +1,13 @@ +prelude: | + h = {a: 1} + def kw(a: 1) a end + def kws(**kw) kw end +benchmark: + kw_to_kw: "kw(a: 1)" + kw_splat_to_kw: "kw(**h)" + kw_to_kw_splat: "kws(a: 1)" + kw_splat_to_kw_splat: "kws(**h)" + kw_and_splat_to_kw: "kw(a: 1, **h)" + kw_splats_to_kw: "kw(**h, **h)" + kw_and_splat_to_kw_splat: "kws(a: 1, **h)" + kw_splats_to_kw_splat: "kws(**h, **h)" diff --git a/ruby/benchmark/lib/benchmark_driver/runner/mjit.rb b/ruby/benchmark/lib/benchmark_driver/runner/mjit.rb new file mode 100644 index 000000000..1d4693e8b --- /dev/null +++ b/ruby/benchmark/lib/benchmark_driver/runner/mjit.rb @@ -0,0 +1,34 @@ +require 'benchmark_driver/struct' +require 'benchmark_driver/metric' +require 'erb' + +# A runner to measure after-JIT performance easily +class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]).extend(Module.new{ + def parse(**) + jobs = super + jobs.map do |job| + job = job.dup + job.prelude = "#{job.prelude}\n#{<<~EOS}" + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + __bmdv_ruby_i = 0 + while __bmdv_ruby_i < 10000 # jit_min_calls + #{job.script} + __bmdv_ruby_i += 1 + end + RubyVM::MJIT.pause # compile + #{job.script} + RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile + #{job.script} + RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile 2 + end + EOS + job + end + end + }) +end diff --git a/ruby/benchmark/lib/benchmark_driver/runner/mjit_exec.rb b/ruby/benchmark/lib/benchmark_driver/runner/mjit_exec.rb index 9f7c8c8af..eac3dfba8 100644 --- a/ruby/benchmark/lib/benchmark_driver/runner/mjit_exec.rb +++ b/ruby/benchmark/lib/benchmark_driver/runner/mjit_exec.rb @@ -135,7 +135,7 @@ def a<%= i %> nil end % end - RubyVM::MJIT.pause if RubyVM::MJIT.enabled? + RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? def vm t = Process.clock_gettime(Process::CLOCK_MONOTONIC) @@ -172,7 +172,7 @@ def a<%= i %> a<%= i %> a<%= i %> # --jit-min-calls=2 % end - RubyVM::MJIT.pause if RubyVM::MJIT.enabled? + RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? def vm t = Process.clock_gettime(Process::CLOCK_MONOTONIC) @@ -228,7 +228,7 @@ def jit jit jit - RubyVM::MJIT.pause if RubyVM::MJIT.enabled? + RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? File.write(<%= result.dump %>, jit) EOS end diff --git a/ruby/benchmark/lib/benchmark_driver/runner/ractor.rb b/ruby/benchmark/lib/benchmark_driver/runner/ractor.rb new file mode 100644 index 000000000..c730b8e4a --- /dev/null +++ b/ruby/benchmark/lib/benchmark_driver/runner/ractor.rb @@ -0,0 +1,122 @@ +require 'erb' + +# A runner to measure performance *inside* Ractor +class BenchmarkDriver::Runner::Ractor < BenchmarkDriver::Runner::Ips + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) do + attr_accessor :ractor + end + + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]).extend(Module.new{ + def parse(ractor: 1, **kwargs) + super(**kwargs).each do |job| + job.ractor = ractor + end + end + }) + + private + + unless private_instance_methods.include?(:run_benchmark) + raise "#run_benchmark is no longer defined in BenchmarkDriver::Runner::Ips" + end + + # @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil + # @param [BenchmarkDriver::Context] context + # @return [BenchmarkDriver::Metrics] + def run_benchmark(job, context:) + benchmark = BenchmarkScript.new( + preludes: [context.prelude, job.prelude], + script: job.script, + teardown: job.teardown, + loop_count: job.loop_count, + ) + + results = job.ractor.times.map do + Tempfile.open('benchmark_driver_result') + end + duration = with_script(benchmark.render(results: results.map(&:path))) do |path| + success = execute(*context.executable.command, path, exception: false) + if success && ((value = results.map { |f| Float(f.read) }.max) > 0) + value + else + BenchmarkDriver::Result::ERROR + end + end + results.each(&:close) + + value_duration( + loop_count: job.loop_count, + duration: duration, + ) + end + + # @param [String] prelude + # @param [String] script + # @param [String] teardown + # @param [Integer] loop_count + BenchmarkScript = ::BenchmarkDriver::Struct.new(:preludes, :script, :teardown, :loop_count) do + # @param [String] result - A file to write result + def render(results:) + prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n") + ERB.new(<<-RUBY).result_with_hash(results: results) +Warning[:experimental] = false +# shareable-constant-value: experimental_everything +#{prelude} + +if #{loop_count} == 1 + __bmdv_loop_before = 0 + __bmdv_loop_after = 0 +else + __bmdv_loop_before = Time.new + #{while_loop('', loop_count, id: 0)} + __bmdv_loop_after = Time.new +end + +__bmdv_ractors = [] +<% results.size.times do %> +__bmdv_ractors << Ractor.new(__bmdv_loop_after - __bmdv_loop_before) { |__bmdv_loop_time| + __bmdv_time = Time + __bmdv_script_before = __bmdv_time.new + #{while_loop(script, loop_count, id: 1)} + __bmdv_script_after = __bmdv_time.new + + (__bmdv_script_after - __bmdv_script_before) - __bmdv_loop_time +} +<% end %> + +# Wait for all Ractors before executing code to write results +__bmdv_ractors.map!(&:take) + +<% results.each do |result| %> +File.write(<%= result.dump %>, __bmdv_ractors.shift) +<% end %> + +#{teardown} + RUBY + end + + private + + # id is to prevent: + # can not isolate a Proc because it accesses outer variables (__bmdv_i) + def while_loop(content, times, id:) + if !times.is_a?(Integer) || times <= 0 + raise ArgumentError.new("Unexpected times: #{times.inspect}") + elsif times == 1 + return content + end + + # TODO: execute in batch + <<-RUBY +__bmdv_i#{id} = 0 +while __bmdv_i#{id} < #{times} + #{content} + __bmdv_i#{id} += 1 +end + RUBY + end + end + private_constant :BenchmarkScript +end diff --git a/ruby/benchmark/masgn.yml b/ruby/benchmark/masgn.yml new file mode 100644 index 000000000..4be9333e2 --- /dev/null +++ b/ruby/benchmark/masgn.yml @@ -0,0 +1,29 @@ +prelude: | + a = [nil] * 3 + b = Class.new{attr_writer :a, :b, :c}.new + c, d, e, f = nil, nil, nil, nil +benchmark: + array2_2: "c = (a[0], a[1] = 1, 2)" + array2_3: "c = (a[0], a[1] = 1, 2, 3)" + array3_2: "c = (a[0], a[1], a[2] = 1, 2)" + array3_3: "c = (a[0], a[1], a[2] = 1, 2, 3)" + attr2_2: "c = (b.a, b.b = 1, 2)" + attr2_3: "c = (b.a, b.b = 1, 2, 3)" + attr3_2: "c = (b.a, b.b, b.c = 1, 2)" + attr3_3: "c = (b.a, b.b, b.c = 1, 2, 3)" + lvar2_2: "c = (d, e = 1, 2)" + lvar2_3: "c = (d, e = 1, 2, 3)" + lvar3_2: "c = (d, e, f = 1, 2)" + lvar3_3: "c = (d, e, f = 1, 2, 3)" + array2_2p: "(a[0], a[1] = 1, 2; nil)" + array2_3p: "(a[0], a[1] = 1, 2, 3; nil)" + array3_2p: "(a[0], a[1], a[2] = 1, 2; nil)" + array3_3p: "(a[0], a[1], a[2] = 1, 2, 3; nil)" + attr2_2p: "(b.a, b.b = 1, 2; nil)" + attr2_3p: "(b.a, b.b = 1, 2, 3; nil)" + attr3_2p: "(b.a, b.b, b.c = 1, 2; nil)" + attr3_3p: "(b.a, b.b, b.c = 1, 2, 3; nil)" + lvar2_2p: "(d, e = 1, 2; nil)" + lvar2_3p: "(d, e = 1, 2, 3; nil)" + lvar3_2p: "(d, e, f = 1, 2; nil)" + lvar3_3p: "(d, e, f = 1, 2, 3; nil)" diff --git a/ruby/benchmark/method_bind_call.yml b/ruby/benchmark/method_bind_call.yml new file mode 100644 index 000000000..9e0e046ed --- /dev/null +++ b/ruby/benchmark/method_bind_call.yml @@ -0,0 +1,16 @@ +prelude: | + named_module = Kernel + + module FakeName + def self.name + "NotMyame".freeze + end + end + + MOD_NAME = Module.instance_method(:name) + +benchmark: + fastpath: MOD_NAME.bind_call(Kernel) + slowpath: MOD_NAME.bind_call(FakeName) + +loop_count: 100_000 diff --git a/ruby/benchmark/mjit_exec_jt2jt.yml b/ruby/benchmark/mjit_exec_jt2jt.yml index 5be408e30..6c303c7a4 100644 --- a/ruby/benchmark/mjit_exec_jt2jt.yml +++ b/ruby/benchmark/mjit_exec_jt2jt.yml @@ -1,6 +1,4 @@ -# Usage: -# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2jt.yml -type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb +type: lib/benchmark_driver/runner/mjit_exec num_methods: [1] #num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000] loop_count: 50000000 diff --git a/ruby/benchmark/mjit_exec_vm2jt.yml b/ruby/benchmark/mjit_exec_vm2jt.yml index 9947dbb7d..764883f07 100644 --- a/ruby/benchmark/mjit_exec_vm2jt.yml +++ b/ruby/benchmark/mjit_exec_vm2jt.yml @@ -1,6 +1,4 @@ -# Usage: -# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2jt.yml -type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb +type: lib/benchmark_driver/runner/mjit_exec num_methods: [1] #num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000] loop_count: 50000000 diff --git a/ruby/benchmark/mjit_exec_vm2vm.yml b/ruby/benchmark/mjit_exec_vm2vm.yml index 4b84427b1..030aa76c1 100644 --- a/ruby/benchmark/mjit_exec_vm2vm.yml +++ b/ruby/benchmark/mjit_exec_vm2vm.yml @@ -1,6 +1,4 @@ -# Usage: -# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2vm.yml -type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb +type: lib/benchmark_driver/runner/mjit_exec num_methods: [1] #num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000] loop_count: 50000000 diff --git a/ruby/benchmark/mjit_exivar.yml b/ruby/benchmark/mjit_exivar.yml new file mode 100644 index 000000000..2584fa641 --- /dev/null +++ b/ruby/benchmark/mjit_exivar.yml @@ -0,0 +1,18 @@ +type: lib/benchmark_driver/runner/mjit +prelude: | + class Bench < Hash + def initialize + @exivar = nil + end + + def exivar + @exivar + end + end + + bench = Bench.new + +benchmark: + mjit_exivar: bench.exivar + +loop_count: 200000000 diff --git a/ruby/benchmark/mjit_integer.yml b/ruby/benchmark/mjit_integer.yml new file mode 100644 index 000000000..a6b5c9ee1 --- /dev/null +++ b/ruby/benchmark/mjit_integer.yml @@ -0,0 +1,32 @@ +type: lib/benchmark_driver/runner/mjit +prelude: | + def mjit_abs(int) int.abs end + def mjit_bit_length(int) int.bit_length end + def mjit_comp(int) ~int end + def mjit_even?(int) int.even? end + def mjit_integer?(int) int.integer? end + def mjit_magnitude(int) int.magnitude end + def mjit_odd?(int) int.odd? end + def mjit_ord(int) int.ord end + def mjit_size(int) int.size end + def mjit_to_i(int) int.to_i end + def mjit_to_int(int) int.to_int end + def mjit_uminus(int) -int end + def mjit_zero?(int) int.zero? end + +benchmark: + - mjit_abs(-1) + - mjit_bit_length(100) + - mjit_comp(1) + - mjit_even?(2) + - mjit_integer?(0) + - mjit_magnitude(-1) + - mjit_odd?(1) + - mjit_ord(1) + - mjit_size(1) + - mjit_to_i(1) + - mjit_to_int(1) + - mjit_uminus(1) + - mjit_zero?(0) + +loop_count: 40000000 diff --git a/ruby/benchmark/mjit_kernel.yml b/ruby/benchmark/mjit_kernel.yml new file mode 100644 index 000000000..7720e65c2 --- /dev/null +++ b/ruby/benchmark/mjit_kernel.yml @@ -0,0 +1,20 @@ +type: lib/benchmark_driver/runner/mjit +prelude: | + def mjit_class(obj) + obj.class + end + + def mjit_frozen?(obj) + obj.frozen? + end + + str = "" + fstr = "".freeze + +benchmark: + - mjit_class(self) + - mjit_class(1) + - mjit_frozen?(str) + - mjit_frozen?(fstr) + +loop_count: 40000000 diff --git a/ruby/benchmark/mjit_leave.yml b/ruby/benchmark/mjit_leave.yml new file mode 100644 index 000000000..9ac68b164 --- /dev/null +++ b/ruby/benchmark/mjit_leave.yml @@ -0,0 +1,8 @@ +type: lib/benchmark_driver/runner/mjit +prelude: | + def leave + nil + end +benchmark: + mjit_leave: leave +loop_count: 200000000 diff --git a/ruby/benchmark/mjit_opt_cc_insns.yml b/ruby/benchmark/mjit_opt_cc_insns.yml new file mode 100644 index 000000000..fed6d34bd --- /dev/null +++ b/ruby/benchmark/mjit_opt_cc_insns.yml @@ -0,0 +1,27 @@ +# opt_* insns using vm_method_cfunc_is with send-compatible operands: +# * opt_nil_p +# * opt_not +# * opt_eq +type: lib/benchmark_driver/runner/mjit +prelude: | + def mjit_nil?(obj) + obj.nil? + end + + def mjit_not(obj) + !obj + end + + def mjit_eq(a, b) + a == b + end + +benchmark: + - script: mjit_nil?(1) + loop_count: 40000000 + - script: mjit_not(1) + loop_count: 40000000 + - script: mjit_eq(1, nil) + loop_count: 8000000 + - script: mjit_eq(nil, 1) + loop_count: 8000000 diff --git a/ruby/benchmark/mjit_struct_aref.yml b/ruby/benchmark/mjit_struct_aref.yml new file mode 100644 index 000000000..bfba1323f --- /dev/null +++ b/ruby/benchmark/mjit_struct_aref.yml @@ -0,0 +1,10 @@ +type: lib/benchmark_driver/runner/mjit +prelude: | + def mjit_struct_aref(struct) + struct.aa + end + struct = Struct.new(:a0, :a1, :a2, :a3, :a4, :a5, :a6, :a7, :a8, :a9, :aa).new + +benchmark: mjit_struct_aref(struct) + +loop_count: 40000000 diff --git a/ruby/benchmark/nilclass.yml b/ruby/benchmark/nilclass.yml new file mode 100644 index 000000000..fba67a5f6 --- /dev/null +++ b/ruby/benchmark/nilclass.yml @@ -0,0 +1,6 @@ +benchmark: + to_i: | + nil.to_i + to_f: | + nil.to_f +loop_count: 100000 diff --git a/ruby/benchmark/num_zero_p.yml b/ruby/benchmark/num_zero_p.yml new file mode 100644 index 000000000..219596343 --- /dev/null +++ b/ruby/benchmark/num_zero_p.yml @@ -0,0 +1,8 @@ +benchmark: + - 0.zero? + - 1.zero? + - 0r.zero? + - 1r.zero? + - 0i.zero? + - 1i.zero? +loop_count: 50000000 diff --git a/ruby/benchmark/numeric_methods.yml b/ruby/benchmark/numeric_methods.yml new file mode 100644 index 000000000..433c2268a --- /dev/null +++ b/ruby/benchmark/numeric_methods.yml @@ -0,0 +1,13 @@ +prelude: | + int = 42 + flo = 4.2 +benchmark: + real?: | + int.real? + integer?: | + flo.integer? + finite?: | + int.finite? + infinite?: | + int.infinite? +loop_count: 20000000 diff --git a/ruby/benchmark/object_allocate.yml b/ruby/benchmark/object_allocate.yml new file mode 100644 index 000000000..93ff463e4 --- /dev/null +++ b/ruby/benchmark/object_allocate.yml @@ -0,0 +1,21 @@ +prelude: | + class Eight + 8.times { include(Module.new) } + end + class ThirtyTwo + 32.times { include(Module.new) } + end + class SixtyFour + 64.times { include(Module.new) } + end + class OneTwentyEight + 128.times { include(Module.new) } + end + # Disable GC to see raw throughput: + GC.disable +benchmark: + allocate_8_deep: Eight.new + allocate_32_deep: ThirtyTwo.new + allocate_64_deep: SixtyFour.new + allocate_128_deep: OneTwentyEight.new +loop_count: 100000 diff --git a/ruby/benchmark/objspace_dump_all.yml b/ruby/benchmark/objspace_dump_all.yml new file mode 100644 index 000000000..ebab562d2 --- /dev/null +++ b/ruby/benchmark/objspace_dump_all.yml @@ -0,0 +1,13 @@ +prelude: | + require 'objspace' + require 'tempfile' + $objs = 1_000.times.map { Object.new } + $strings = 1_000.times.map { |i| "string #{i}" } + $file = Tempfile.new('heap') + $dev_null = File.open(File::NULL, 'w+') + +benchmark: + dump_all_string: "ObjectSpace.dump_all(output: :string)" + dump_all_file: "ObjectSpace.dump_all(output: $file)" + dump_all_dev_null: "ObjectSpace.dump_all(output: $dev_null)" +loop_count: 1 diff --git a/ruby/benchmark/pm_array.yml b/ruby/benchmark/pm_array.yml new file mode 100644 index 000000000..babb65a28 --- /dev/null +++ b/ruby/benchmark/pm_array.yml @@ -0,0 +1,19 @@ +prelude: | + def call(*val) + case val + in [String => body] + [200, {}, [body]] + in [Integer => status] + [status, {}, [""]] + in [Integer, String] => response + [response[0], {}, [response[1]]] + in [Integer, Hash, String] => response + [response[0], response[1], [response[2]]] + end + end + +benchmark: + first_match: call("ok") + second_match: call(401) + third_match: call(200, "ok") + fourth_match: call(201, {}, "created") diff --git a/ruby/benchmark/ractor_const.yml b/ruby/benchmark/ractor_const.yml new file mode 100644 index 000000000..d7ab74bdc --- /dev/null +++ b/ruby/benchmark/ractor_const.yml @@ -0,0 +1,4 @@ +type: lib/benchmark_driver/runner/ractor +benchmark: + ractor_const: Object +ractor: 1 diff --git a/ruby/benchmark/ractor_float_to_s.yml b/ruby/benchmark/ractor_float_to_s.yml new file mode 100644 index 000000000..8f492be66 --- /dev/null +++ b/ruby/benchmark/ractor_float_to_s.yml @@ -0,0 +1,8 @@ +type: lib/benchmark_driver/runner/ractor +prelude: | + FLOATS = [*0.0.step(1.0, 0.001)] +benchmark: + ractor_float_to_s: | + FLOATS.each {|f| f.to_s} +loop_count: 100 +ractor: 2 diff --git a/ruby/benchmark/string_casecmp.yml b/ruby/benchmark/string_casecmp.yml new file mode 100644 index 000000000..2354040a0 --- /dev/null +++ b/ruby/benchmark/string_casecmp.yml @@ -0,0 +1,26 @@ +prelude: | + lstr1 = [*"a".."z",*"0".."9"].join("") + lstr10 = lstr1 * 10 + lstr100 = lstr10 * 10 + lstr1000 = lstr100 * 10 + lnonascii1 = [*"\u{e0}".."\u{ff}"].join("") + lnonascii10 = lnonascii1 * 10 + lnonascii100 = lnonascii10 * 10 + lnonascii1000 = lnonascii100 * 10 + ustr1 = [*"A".."Z",*"0".."9"].join("") + ustr10 = ustr1 * 10 + ustr100 = ustr10 * 10 + ustr1000 = ustr100 * 10 + unonascii1 = [*"\u{c0}".."\u{df}"].join("") + unonascii10 = unonascii1 * 10 + unonascii100 = unonascii10 * 10 + unonascii1000 = unonascii100 * 10 +benchmark: + casecmp-1: lstr1.casecmp(ustr1) + casecmp-10: lstr10.casecmp(ustr10) + casecmp-100: lstr100.casecmp(ustr100) + casecmp-1000: lstr1000.casecmp(ustr1000) + casecmp-nonascii1: lnonascii1.casecmp(unonascii1) + casecmp-nonascii10: lnonascii10.casecmp(unonascii10) + casecmp-nonascii100: lnonascii100.casecmp(unonascii100) + casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000) diff --git a/ruby/benchmark/string_casecmp_p.yml b/ruby/benchmark/string_casecmp_p.yml new file mode 100644 index 000000000..a790ce7d5 --- /dev/null +++ b/ruby/benchmark/string_casecmp_p.yml @@ -0,0 +1,26 @@ +prelude: | + lstr1 = [*"a".."z",*"0".."9"].join("") + lstr10 = lstr1 * 10 + lstr100 = lstr10 * 10 + lstr1000 = lstr100 * 10 + lnonascii1 = [*"\u{e0}".."\u{ff}"].join("") + lnonascii10 = lnonascii1 * 10 + lnonascii100 = lnonascii10 * 10 + lnonascii1000 = lnonascii100 * 10 + ustr1 = [*"A".."Z",*"0".."9"].join("") + ustr10 = ustr1 * 10 + ustr100 = ustr10 * 10 + ustr1000 = ustr100 * 10 + unonascii1 = [*"\u{c0}".."\u{df}"].join("") + unonascii10 = unonascii1 * 10 + unonascii100 = unonascii10 * 10 + unonascii1000 = unonascii100 * 10 +benchmark: + casecmp_p-1: lstr1.casecmp?(ustr1) + casecmp_p-10: lstr10.casecmp?(ustr10) + casecmp_p-100: lstr100.casecmp?(ustr100) + casecmp_p-1000: lstr1000.casecmp?(ustr1000) + casecmp_p-nonascii1: lnonascii1.casecmp?(unonascii1) + casecmp_p-nonascii10: lnonascii10.casecmp?(unonascii10) + casecmp_p-nonascii100: lnonascii100.casecmp?(unonascii100) + casecmp_p-nonascii1000: lnonascii1000.casecmp?(unonascii1000) diff --git a/ruby/benchmark/string_downcase.yml b/ruby/benchmark/string_downcase.yml index a31c3ac71..1fea6afbe 100644 --- a/ruby/benchmark/string_downcase.yml +++ b/ruby/benchmark/string_downcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{c0}".."\u{df}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: downcase-1: str1.upcase downcase-10: str10.upcase downcase-100: str100.upcase downcase-1000: str1000.upcase + downcase-nonascii1: nonascii1.downcase + downcase-nonascii10: nonascii10.downcase + downcase-nonascii100: nonascii100.downcase + downcase-nonascii1000: nonascii1000.downcase diff --git a/ruby/benchmark/string_slice.yml b/ruby/benchmark/string_slice.yml new file mode 100644 index 000000000..fc2393c5d --- /dev/null +++ b/ruby/benchmark/string_slice.yml @@ -0,0 +1,11 @@ +prelude: | + long_string = "x"*1000+"-hÃ¥r" +benchmark: + regexp-short: | + "x-hÃ¥r".slice!(/-(.)(.)(.)/, 3) + regexp-long: | + long_string.dup.slice!(/-(.)(.)(.)/, 3) + string-short: | + "x-hÃ¥r".slice!("r") + string-long: | + long_string.dup.slice!("r") diff --git a/ruby/benchmark/string_split.yml b/ruby/benchmark/string_split.yml index 84ffe8f6a..cc2c7d785 100644 --- a/ruby/benchmark/string_split.yml +++ b/ruby/benchmark/string_split.yml @@ -1,7 +1,22 @@ prelude: | - str0 = [*0..9].join("") + str1 = [*0..5].join(" ") + " " + str10 = str1 * 10 + str100 = str10 * 10 + str1000 = str100 * 10 benchmark: - to_chars-1: str0.split('') - to_chars-10: (str0 * 10).split('') - to_chars-100: (str0 * 100).split('') - to_chars-1000: (str0 * 1000).split('') + to_chars-1: str1.split('') + to_chars-10: str10.split('') + to_chars-100: str100.split('') + to_chars-1000: str1000.split('') + to_words-1: str1.split(' ') + to_words-10: str10.split(' ') + to_words-100: str100.split(' ') + to_words-1000: str1000.split(' ') + re_chars-1: str1.split(//) + re_chars-10: str10.split(//) + re_chars-100: str100.split(//) + re_chars-1000: str1000.split(//) + re_space-1: str1.split(/ /) + re_space-10: str10.split(/ /) + re_space-100: str100.split(/ /) + re_space-1000: str1000.split(/ /) diff --git a/ruby/benchmark/string_swapcase.yml b/ruby/benchmark/string_swapcase.yml index afaae3f69..eeb592890 100644 --- a/ruby/benchmark/string_swapcase.yml +++ b/ruby/benchmark/string_swapcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{c0}".."\u{cf}",*"\u{f0}".."\u{ff}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: swapcase-1: str1.swapcase swapcase-10: str10.swapcase swapcase-100: str100.swapcase swapcase-1000: str1000.swapcase + swapcase-nonascii1: nonascii1.swapcase + swapcase-nonascii10: nonascii10.swapcase + swapcase-nonascii100: nonascii100.swapcase + swapcase-nonascii1000: nonascii1000.swapcase diff --git a/ruby/benchmark/string_upcase.yml b/ruby/benchmark/string_upcase.yml index 456d213c7..dab84bbde 100644 --- a/ruby/benchmark/string_upcase.yml +++ b/ruby/benchmark/string_upcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{e0}".."\u{ff}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: upcase-1: str1.upcase upcase-10: str10.upcase upcase-100: str100.upcase upcase-1000: str1000.upcase + upcase-nonascii1: nonascii1.upcase + upcase-nonascii10: nonascii10.upcase + upcase-nonascii100: nonascii100.upcase + upcase-nonascii1000: nonascii1000.upcase diff --git a/ruby/benchmark/time_at.yml b/ruby/benchmark/time_at.yml new file mode 100644 index 000000000..3247efbe7 --- /dev/null +++ b/ruby/benchmark/time_at.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true +benchmark: + - 'Time.at(0)' + - 'Time.at(0, 500)' + - 'Time.at(0, in: "+09:00")' + - 'Time.at(0, 500, in: "+09:00")' diff --git a/ruby/benchmark/time_new.yml b/ruby/benchmark/time_new.yml new file mode 100644 index 000000000..5947dd3a4 --- /dev/null +++ b/ruby/benchmark/time_new.yml @@ -0,0 +1,4 @@ +benchmark: + - 'Time.new(2021)' + - 'Time.new(2021, 8, 22)' + - 'Time.new(2021, 8, 22, in: "+09:00")' diff --git a/ruby/benchmark/time_parse.yml b/ruby/benchmark/time_parse.yml new file mode 100644 index 000000000..a6d6948b9 --- /dev/null +++ b/ruby/benchmark/time_parse.yml @@ -0,0 +1,8 @@ +prelude: | + require 'time' + inspect = "2021-08-23 09:57:02 +0900" + iso8601 = "2021-08-23T09:57:02+09:00" +benchmark: + - Time.iso8601(iso8601) + - Time.parse(iso8601) + - Time.parse(inspect) diff --git a/ruby/benchmark/vm1_attr_ivar.yml b/ruby/benchmark/vm1_attr_ivar.yml deleted file mode 100644 index f714dd9bd..000000000 --- a/ruby/benchmark/vm1_attr_ivar.yml +++ /dev/null @@ -1,14 +0,0 @@ -prelude: | - class C - attr_reader :a, :b - def initialize - @a = nil - @b = nil - end - end - obj = C.new -benchmark: - vm1_attr_ivar: | - j = obj.a - k = obj.b -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_attr_ivar_set.yml b/ruby/benchmark/vm1_attr_ivar_set.yml deleted file mode 100644 index f383e59ef..000000000 --- a/ruby/benchmark/vm1_attr_ivar_set.yml +++ /dev/null @@ -1,14 +0,0 @@ -prelude: | - class C - attr_accessor :a, :b - def initialize - @a = nil - @b = nil - end - end - obj = C.new -benchmark: - vm1_attr_ivar_set: | - obj.a = 1 - obj.b = 2 -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_block.yml b/ruby/benchmark/vm1_block.yml deleted file mode 100644 index ac7c940f9..000000000 --- a/ruby/benchmark/vm1_block.yml +++ /dev/null @@ -1,9 +0,0 @@ -prelude: | - def m - yield - end -benchmark: - vm1_block: | - m{ - } -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_blockparam.yml b/ruby/benchmark/vm1_blockparam.yml deleted file mode 100644 index 947b8c53d..000000000 --- a/ruby/benchmark/vm1_blockparam.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - def m &b - end -benchmark: - vm1_blockparam: | - m{} -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_blockparam_call.yml b/ruby/benchmark/vm1_blockparam_call.yml deleted file mode 100644 index e2817a3ce..000000000 --- a/ruby/benchmark/vm1_blockparam_call.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - def m &b - b.call - end -benchmark: - vm1_blockparam_call: | - m{} -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_blockparam_pass.yml b/ruby/benchmark/vm1_blockparam_pass.yml deleted file mode 100644 index ca1bef336..000000000 --- a/ruby/benchmark/vm1_blockparam_pass.yml +++ /dev/null @@ -1,12 +0,0 @@ -prelude: | - def bp_yield - yield - end - - def bp_pass &b - bp_yield &b - end -benchmark: - vm1_blockparam_pass: | - bp_pass{} -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_blockparam_yield.yml b/ruby/benchmark/vm1_blockparam_yield.yml deleted file mode 100644 index 56ae61779..000000000 --- a/ruby/benchmark/vm1_blockparam_yield.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - def bp_yield &b - yield - end -benchmark: - vm1_blockparam_yield: | - bp_yield{} -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_const.yml b/ruby/benchmark/vm1_const.yml deleted file mode 100644 index b98db1545..000000000 --- a/ruby/benchmark/vm1_const.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - Const = 1 -benchmark: - vm1_const: | - j = Const - k = Const -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_ensure.yml b/ruby/benchmark/vm1_ensure.yml deleted file mode 100644 index afbbe38be..000000000 --- a/ruby/benchmark/vm1_ensure.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Not utilizing loop_count since using it for this is too unstable for now -benchmark: - vm1_ensure: | - i = 0 - while i<30_000_000 - i += 1 - begin - begin - ensure - end - ensure - end - end -loop_count: 1 diff --git a/ruby/benchmark/vm1_float_simple.yml b/ruby/benchmark/vm1_float_simple.yml deleted file mode 100644 index 4e9ad1852..000000000 --- a/ruby/benchmark/vm1_float_simple.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - f = 0.0 -benchmark: - vm1_float_simple: | - f += 0.1; f -= 0.1 - f += 0.1; f -= 0.1 - f += 0.1; f -= 0.1 -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_short_lived.yml b/ruby/benchmark/vm1_gc_short_lived.yml deleted file mode 100644 index 8fdcb7371..000000000 --- a/ruby/benchmark/vm1_gc_short_lived.yml +++ /dev/null @@ -1,9 +0,0 @@ -benchmark: - vm1_gc_short_lived: | - a = '' # short-lived String - b = '' - c = '' - d = '' - e = '' - f = '' -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_short_with_complex_long.yml b/ruby/benchmark/vm1_gc_short_with_complex_long.yml deleted file mode 100644 index c22ea74a6..000000000 --- a/ruby/benchmark/vm1_gc_short_with_complex_long.yml +++ /dev/null @@ -1,25 +0,0 @@ -prelude: | - def nested_hash h, n - if n == 0 - '' - else - 10.times{ - h[Object.new] = nested_hash(h, n-1) - } - end - end - - long_lived = Hash.new - nested_hash long_lived, 6 - - GC.start - GC.start -benchmark: - vm1_gc_short_with_complex_long: | - a = '' # short-lived String - b = '' - c = '' - d = '' - e = '' - f = '' -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_short_with_long.yml b/ruby/benchmark/vm1_gc_short_with_long.yml deleted file mode 100644 index c731aae54..000000000 --- a/ruby/benchmark/vm1_gc_short_with_long.yml +++ /dev/null @@ -1,13 +0,0 @@ -prelude: | - long_lived = Array.new(1_000_000){|i| "#{i}"} - GC.start - GC.start -benchmark: - vm1_gc_short_with_long: | - a = '' # short-lived String - b = '' - c = '' - d = '' - e = '' - f = '' -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_short_with_symbol.yml b/ruby/benchmark/vm1_gc_short_with_symbol.yml deleted file mode 100644 index 7fc1abedd..000000000 --- a/ruby/benchmark/vm1_gc_short_with_symbol.yml +++ /dev/null @@ -1,13 +0,0 @@ -prelude: | - 50_000.times{|i| sym = "sym#{i}".to_sym} - GC.start - GC.start -benchmark: - vm1_gc_short_with_symbol: | - a = '' # short-lived String - b = '' - c = '' - d = '' - e = '' - f = '' -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_wb_ary.yml b/ruby/benchmark/vm1_gc_wb_ary.yml deleted file mode 100644 index 50fb4b6f8..000000000 --- a/ruby/benchmark/vm1_gc_wb_ary.yml +++ /dev/null @@ -1,12 +0,0 @@ -prelude: | - short_lived_ary = [] - - if RUBY_VERSION >= "2.2.0" - GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) - end - - short_lived = '' -benchmark: - vm1_gc_wb_ary: | - short_lived_ary[0] = short_lived # write barrier -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_wb_ary_promoted.yml b/ruby/benchmark/vm1_gc_wb_ary_promoted.yml deleted file mode 100644 index cf9b5de00..000000000 --- a/ruby/benchmark/vm1_gc_wb_ary_promoted.yml +++ /dev/null @@ -1,15 +0,0 @@ -prelude: | - long_lived = [] - - if RUBY_VERSION > "2.2.0" - 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } - elsif - GC.start - end - - short_lived = '' - -benchmark: - vm1_gc_wb_ary_promoted: | - long_lived[0] = short_lived # write barrier -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_wb_obj.yml b/ruby/benchmark/vm1_gc_wb_obj.yml deleted file mode 100644 index 9dc08e7e1..000000000 --- a/ruby/benchmark/vm1_gc_wb_obj.yml +++ /dev/null @@ -1,15 +0,0 @@ -prelude: | - class C - attr_accessor :foo - end - short_lived_obj = C.new - - if RUBY_VERSION >= "2.2.0" - GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) - end - - short_lived = '' -benchmark: - vm1_gc_wb_obj: | - short_lived_obj.foo = short_lived # write barrier -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_gc_wb_obj_promoted.yml b/ruby/benchmark/vm1_gc_wb_obj_promoted.yml deleted file mode 100644 index 26859d2a5..000000000 --- a/ruby/benchmark/vm1_gc_wb_obj_promoted.yml +++ /dev/null @@ -1,17 +0,0 @@ -prelude: | - class C - attr_accessor :foo - end - long_lived = C.new - - if RUBY_VERSION >= "2.2.0" - 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } - elsif - GC.start - end - - short_lived = '' -benchmark: - vm1_gc_wb_obj_promoted: | - long_lived.foo = short_lived # write barrier -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_ivar.yml b/ruby/benchmark/vm1_ivar.yml deleted file mode 100644 index 7aa6fac72..000000000 --- a/ruby/benchmark/vm1_ivar.yml +++ /dev/null @@ -1,6 +0,0 @@ -prelude: "@a = 1\n" -benchmark: - vm1_ivar: | - j = @a - k = @a -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_ivar_set.yml b/ruby/benchmark/vm1_ivar_set.yml deleted file mode 100644 index 6f19412d1..000000000 --- a/ruby/benchmark/vm1_ivar_set.yml +++ /dev/null @@ -1,5 +0,0 @@ -benchmark: - vm1_ivar_set: | - @a = 1 - @b = 2 -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_length.yml b/ruby/benchmark/vm1_length.yml deleted file mode 100644 index a18e2ca2e..000000000 --- a/ruby/benchmark/vm1_length.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - a = 'abc' - b = [1, 2, 3] -benchmark: - vm1_length: | - a.length - b.length -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_lvar_init.yml b/ruby/benchmark/vm1_lvar_init.yml deleted file mode 100644 index 10e2becef..000000000 --- a/ruby/benchmark/vm1_lvar_init.yml +++ /dev/null @@ -1,21 +0,0 @@ -# while loop cost is not removed because `i` is used in the script -benchmark: - vm1_lvar_init: | - def m v - unless v - # unreachable code - v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 = - v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 = - v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 = - v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 = - v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1 - end - end - - i = 0 - - while i<30_000_000 - i += 1 - m i - end -loop_count: 1 diff --git a/ruby/benchmark/vm1_lvar_set.yml b/ruby/benchmark/vm1_lvar_set.yml deleted file mode 100644 index df8f6b6ea..000000000 --- a/ruby/benchmark/vm1_lvar_set.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm1_lvar_set: | - a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1 -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_neq.yml b/ruby/benchmark/vm1_neq.yml deleted file mode 100644 index 65a8128dd..000000000 --- a/ruby/benchmark/vm1_neq.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - obj1 = Object.new - obj2 = Object.new -benchmark: - vm1_neq: | - obj1 != obj2 -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_not.yml b/ruby/benchmark/vm1_not.yml deleted file mode 100644 index 0fb7b282a..000000000 --- a/ruby/benchmark/vm1_not.yml +++ /dev/null @@ -1,6 +0,0 @@ -prelude: | - obj = Object.new -benchmark: - vm1_not: | - !obj -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_rescue.yml b/ruby/benchmark/vm1_rescue.yml deleted file mode 100644 index a175b823a..000000000 --- a/ruby/benchmark/vm1_rescue.yml +++ /dev/null @@ -1,6 +0,0 @@ -benchmark: - vm1_rescue: | - begin - rescue - end -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_simplereturn.yml b/ruby/benchmark/vm1_simplereturn.yml deleted file mode 100644 index 3564aac7e..000000000 --- a/ruby/benchmark/vm1_simplereturn.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - def m - return 1 - end -benchmark: - vm1_simplereturn: m -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_swap.yml b/ruby/benchmark/vm1_swap.yml deleted file mode 100644 index fed87ccd6..000000000 --- a/ruby/benchmark/vm1_swap.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - a = 1 - b = 2 -benchmark: - vm1_swap: | - a, b = b, a -loop_count: 30000000 diff --git a/ruby/benchmark/vm1_yield.yml b/ruby/benchmark/vm1_yield.yml deleted file mode 100644 index ae1f9316f..000000000 --- a/ruby/benchmark/vm1_yield.yml +++ /dev/null @@ -1,13 +0,0 @@ -# while loop cost is not removed due to benchmark_driver.gem's limitation -benchmark: - vm1_yield: | - def m - i = 0 - while i<30_000_000 - i += 1 - yield - end - end - - m{} -loop_count: 1 diff --git a/ruby/benchmark/vm2_array.yml b/ruby/benchmark/vm2_array.yml deleted file mode 100644 index 7373098d5..000000000 --- a/ruby/benchmark/vm2_array.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_array: | - a = [1,2,3,4,5,6,7,8,9,10] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_bigarray.yml b/ruby/benchmark/vm2_bigarray.yml deleted file mode 100644 index 2ad6da390..000000000 --- a/ruby/benchmark/vm2_bigarray.yml +++ /dev/null @@ -1,105 +0,0 @@ -benchmark: - vm2_bigarray: | - a = [ - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - ] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_bighash.yml b/ruby/benchmark/vm2_bighash.yml deleted file mode 100644 index e9154e4ba..000000000 --- a/ruby/benchmark/vm2_bighash.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_bighash: | - a = {0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19, 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29, 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79, 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 128=>128, 129=>129, 130=>130, 131=>131, 132=>132, 133=>133, 134=>134, 135=>135, 136=>136, 137=>137, 138=>138, 139=>139, 140=>140, 141=>141, 142=>142, 143=>143, 144=>144, 145=>145, 146=>146, 147=>147, 148=>148, 149=>149, 150=>150, 151=>151, 152=>152, 153=>153, 154=>154, 155=>155, 156=>156, 157=>157, 158=>158, 159=>159, 160=>160, 161=>161, 162=>162, 163=>163, 164=>164, 165=>165, 166=>166, 167=>167, 168=>168, 169=>169, 170=>170, 171=>171, 172=>172, 173=>173, 174=>174, 175=>175, 176=>176, 177=>177, 178=>178, 179=>179, 180=>180, 181=>181, 182=>182, 183=>183, 184=>184, 185=>185, 186=>186, 187=>187, 188=>188, 189=>189, 190=>190, 191=>191, 192=>192, 193=>193, 194=>194, 195=>195, 196=>196, 197=>197, 198=>198, 199=>199, 200=>200, 201=>201, 202=>202, 203=>203, 204=>204, 205=>205, 206=>206, 207=>207, 208=>208, 209=>209, 210=>210, 211=>211, 212=>212, 213=>213, 214=>214, 215=>215, 216=>216, 217=>217, 218=>218, 219=>219, 220=>220, 221=>221, 222=>222, 223=>223, 224=>224, 225=>225, 226=>226, 227=>227, 228=>228, 229=>229, 230=>230, 231=>231, 232=>232, 233=>233, 234=>234, 235=>235, 236=>236, 237=>237, 238=>238, 239=>239, 240=>240, 241=>241, 242=>242, 243=>243, 244=>244, 245=>245, 246=>246, 247=>247, 248=>248, 249=>249, 250=>250, 251=>251, 252=>252, 253=>253, 254=>254, 255=>255, 256=>256, 257=>257, 258=>258, 259=>259, 260=>260, 261=>261, 262=>262, 263=>263, 264=>264, 265=>265, 266=>266, 267=>267, 268=>268, 269=>269, 270=>270, 271=>271, 272=>272, 273=>273, 274=>274, 275=>275, 276=>276, 277=>277, 278=>278, 279=>279, 280=>280, 281=>281, 282=>282, 283=>283, 284=>284, 285=>285, 286=>286, 287=>287, 288=>288, 289=>289, 290=>290, 291=>291, 292=>292, 293=>293, 294=>294, 295=>295, 296=>296, 297=>297, 298=>298, 299=>299, 300=>300, 301=>301, 302=>302, 303=>303, 304=>304, 305=>305, 306=>306, 307=>307, 308=>308, 309=>309, 310=>310, 311=>311, 312=>312, 313=>313, 314=>314, 315=>315, 316=>316, 317=>317, 318=>318, 319=>319, 320=>320, 321=>321, 322=>322, 323=>323, 324=>324, 325=>325, 326=>326, 327=>327, 328=>328, 329=>329, 330=>330, 331=>331, 332=>332, 333=>333, 334=>334, 335=>335, 336=>336, 337=>337, 338=>338, 339=>339, 340=>340, 341=>341, 342=>342, 343=>343, 344=>344, 345=>345, 346=>346, 347=>347, 348=>348, 349=>349, 350=>350, 351=>351, 352=>352, 353=>353, 354=>354, 355=>355, 356=>356, 357=>357, 358=>358, 359=>359, 360=>360, 361=>361, 362=>362, 363=>363, 364=>364, 365=>365, 366=>366, 367=>367, 368=>368, 369=>369, 370=>370, 371=>371, 372=>372, 373=>373, 374=>374, 375=>375, 376=>376, 377=>377, 378=>378, 379=>379, 380=>380, 381=>381, 382=>382, 383=>383, 384=>384, 385=>385, 386=>386, 387=>387, 388=>388, 389=>389, 390=>390, 391=>391, 392=>392, 393=>393, 394=>394, 395=>395, 396=>396, 397=>397, 398=>398, 399=>399, 400=>400, 401=>401, 402=>402, 403=>403, 404=>404, 405=>405, 406=>406, 407=>407, 408=>408, 409=>409, 410=>410, 411=>411, 412=>412, 413=>413, 414=>414, 415=>415, 416=>416, 417=>417, 418=>418, 419=>419, 420=>420, 421=>421, 422=>422, 423=>423, 424=>424, 425=>425, 426=>426, 427=>427, 428=>428, 429=>429, 430=>430, 431=>431, 432=>432, 433=>433, 434=>434, 435=>435, 436=>436, 437=>437, 438=>438, 439=>439, 440=>440, 441=>441, 442=>442, 443=>443, 444=>444, 445=>445, 446=>446, 447=>447, 448=>448, 449=>449, 450=>450, 451=>451, 452=>452, 453=>453, 454=>454, 455=>455, 456=>456, 457=>457, 458=>458, 459=>459, 460=>460, 461=>461, 462=>462, 463=>463, 464=>464, 465=>465, 466=>466, 467=>467, 468=>468, 469=>469, 470=>470, 471=>471, 472=>472, 473=>473, 474=>474, 475=>475, 476=>476, 477=>477, 478=>478, 479=>479, 480=>480, 481=>481, 482=>482, 483=>483, 484=>484, 485=>485, 486=>486, 487=>487, 488=>488, 489=>489, 490=>490, 491=>491, 492=>492, 493=>493, 494=>494, 495=>495, 496=>496, 497=>497, 498=>498, 499=>499, 500=>500,} -loop_count: 60000 diff --git a/ruby/benchmark/vm2_case.yml b/ruby/benchmark/vm2_case.yml deleted file mode 100644 index 7716783c0..000000000 --- a/ruby/benchmark/vm2_case.yml +++ /dev/null @@ -1,13 +0,0 @@ -benchmark: - vm2_case: | - case :foo - when :bar - raise - when :baz - raise - when :boo - raise - when :foo - # noop - end -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_case_lit.yml b/ruby/benchmark/vm2_case_lit.yml deleted file mode 100644 index c49b8dfe5..000000000 --- a/ruby/benchmark/vm2_case_lit.yml +++ /dev/null @@ -1,23 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_case_lit: | - i = 0 - @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ] - def foo(i) - @ret[i % @ret.size] - end - - while i<6_000_000 - case foo(i) - when "foo" then :foo - when true then true - when false then false - when :sym then :sym - when 6 then :fix - when nil then nil - when 0.1 then :float - when 0xffffffffffffffff then :big - end - i += 1 - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_defined_method.yml b/ruby/benchmark/vm2_defined_method.yml deleted file mode 100644 index e1b0d5567..000000000 --- a/ruby/benchmark/vm2_defined_method.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - class Object - define_method(:m){} - end -benchmark: - vm2_defined_method: | - m; m; m; m; m; m; m; m; -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_dstr.yml b/ruby/benchmark/vm2_dstr.yml deleted file mode 100644 index f8bd6e013..000000000 --- a/ruby/benchmark/vm2_dstr.yml +++ /dev/null @@ -1,6 +0,0 @@ -prelude: | - x = y = 'z' -benchmark: - vm2_dstr: | - str = "foo#{x}bar#{y}baz" -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_eval.yml b/ruby/benchmark/vm2_eval.yml deleted file mode 100644 index d506a9c07..000000000 --- a/ruby/benchmark/vm2_eval.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_eval: | - eval("1") -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_fiber_allocate.yml b/ruby/benchmark/vm2_fiber_allocate.yml deleted file mode 100644 index f29705f69..000000000 --- a/ruby/benchmark/vm2_fiber_allocate.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - # Disable GC to see raw throughput: - GC.disable -benchmark: - vm2_fiber_allocate: | - fiber = Fiber.new{Fiber.yield} - fiber.resume -loop_count: 100000 diff --git a/ruby/benchmark/vm2_fiber_count.yml b/ruby/benchmark/vm2_fiber_count.yml deleted file mode 100644 index 3ecf6bdcb..000000000 --- a/ruby/benchmark/vm2_fiber_count.yml +++ /dev/null @@ -1,10 +0,0 @@ -# On Linux, you will need to increase the maximum number of memory maps: -# sudo sysctl -w vm.max_map_count=200000 -prelude: | - fibers = [] -benchmark: - vm2_fiber_count: | - fiber = Fiber.new{Fiber.yield} - fibers << fiber - fiber.resume -loop_count: 100000 diff --git a/ruby/benchmark/vm2_fiber_reuse.yml b/ruby/benchmark/vm2_fiber_reuse.yml deleted file mode 100644 index 017065063..000000000 --- a/ruby/benchmark/vm2_fiber_reuse.yml +++ /dev/null @@ -1,14 +0,0 @@ -prelude: | - GC.disable - fibers = [] -benchmark: - vm2_fiber_reuse: | - 1024.times do - fiber = Fiber.new{Fiber.yield} - fibers << fiber - fiber.resume - end - - fibers.clear - GC.start -loop_count: 200 diff --git a/ruby/benchmark/vm2_fiber_reuse_gc.yml b/ruby/benchmark/vm2_fiber_reuse_gc.yml deleted file mode 100644 index 8fb91a84e..000000000 --- a/ruby/benchmark/vm2_fiber_reuse_gc.yml +++ /dev/null @@ -1,12 +0,0 @@ -# https://bugs.ruby-lang.org/issues/16009 -prelude: | - fibers = [] -benchmark: - vm2_fiber_reuse_gc: | - 2000.times do - fiber = Fiber.new{Fiber.yield} - fibers << fiber - fiber.resume - end - fibers.clear -loop_count: 100 diff --git a/ruby/benchmark/vm2_fiber_switch.yml b/ruby/benchmark/vm2_fiber_switch.yml deleted file mode 100644 index fbf7283c2..000000000 --- a/ruby/benchmark/vm2_fiber_switch.yml +++ /dev/null @@ -1,9 +0,0 @@ -prelude: | - # based on benchmark for [ruby-core:65518] [Feature #10341] by Knut Franke - fib = Fiber.new do - loop { Fiber.yield } - end -benchmark: - vm2_fiber_switch: | - fib.resume -loop_count: 20000000 diff --git a/ruby/benchmark/vm2_freezestring.yml b/ruby/benchmark/vm2_freezestring.yml deleted file mode 100644 index b78af91a2..000000000 --- a/ruby/benchmark/vm2_freezestring.yml +++ /dev/null @@ -1,10 +0,0 @@ -prelude: | - class String - def freeze - -self - end - end -benchmark: - vm2_freezestring: | - "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_method.yml b/ruby/benchmark/vm2_method.yml deleted file mode 100644 index cc7b9b28f..000000000 --- a/ruby/benchmark/vm2_method.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - def m - nil - end -benchmark: - vm2_method: | - m; m; m; m; m; m; m; m; -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_method_missing.yml b/ruby/benchmark/vm2_method_missing.yml deleted file mode 100644 index cbfb794b2..000000000 --- a/ruby/benchmark/vm2_method_missing.yml +++ /dev/null @@ -1,11 +0,0 @@ -prelude: | - class C - def method_missing mid - end - end - - obj = C.new -benchmark: - vm2_method_missing: | - obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_method_with_block.yml b/ruby/benchmark/vm2_method_with_block.yml deleted file mode 100644 index 6e522adcc..000000000 --- a/ruby/benchmark/vm2_method_with_block.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - def m - nil - end -benchmark: - vm2_method_with_block: | - m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{}; -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_module_ann_const_set.yml b/ruby/benchmark/vm2_module_ann_const_set.yml deleted file mode 100644 index b0becd9d3..000000000 --- a/ruby/benchmark/vm2_module_ann_const_set.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_module_ann_const_set: | - Module.new.const_set(:X, Module.new) -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_module_const_set.yml b/ruby/benchmark/vm2_module_const_set.yml deleted file mode 100644 index 05a640069..000000000 --- a/ruby/benchmark/vm2_module_const_set.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - module M - end - $VERBOSE = nil -benchmark: - vm2_module_const_set: | - M.const_set(:X, Module.new) -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_mutex.yml b/ruby/benchmark/vm2_mutex.yml deleted file mode 100644 index c40a90444..000000000 --- a/ruby/benchmark/vm2_mutex.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - require 'thread' - - m = Thread::Mutex.new -benchmark: - vm2_mutex: | - m.synchronize{} -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_newlambda.yml b/ruby/benchmark/vm2_newlambda.yml deleted file mode 100644 index 93133f9f3..000000000 --- a/ruby/benchmark/vm2_newlambda.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_newlambda: | - lambda {} -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_poly_method.yml b/ruby/benchmark/vm2_poly_method.yml deleted file mode 100644 index 0104bdfb6..000000000 --- a/ruby/benchmark/vm2_poly_method.yml +++ /dev/null @@ -1,24 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_poly_method: | - class C1 - def m - 1 - end - end - class C2 - def m - 2 - end - end - - o1 = C1.new - o2 = C2.new - - i = 0 - while i<6_000_000 - o = (i % 2 == 0) ? o1 : o2 - o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m - i += 1 - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_poly_method_ov.yml b/ruby/benchmark/vm2_poly_method_ov.yml deleted file mode 100644 index 3748073ba..000000000 --- a/ruby/benchmark/vm2_poly_method_ov.yml +++ /dev/null @@ -1,24 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_poly_method_ov: | - class C1 - def m - 1 - end - end - class C2 - def m - 2 - end - end - - o1 = C1.new - o2 = C2.new - - i = 0 - while i<6_000_000 - o = (i % 2 == 0) ? o1 : o2 - # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m - i += 1 - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_poly_same_method.yml b/ruby/benchmark/vm2_poly_same_method.yml deleted file mode 100644 index 867c433cf..000000000 --- a/ruby/benchmark/vm2_poly_same_method.yml +++ /dev/null @@ -1,25 +0,0 @@ -prelude: | - module AR; end - class AR::Base - def create_or_update - nil - end - def save - create_or_update - end - end - class Foo < AR::Base; end - class Bar < AR::Base; end - o1 = Foo.new - o2 = Bar.new -benchmark: - vm2_poly_same_method: | - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; - o1.save; o2.save; -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_poly_singleton.yml b/ruby/benchmark/vm2_poly_singleton.yml deleted file mode 100644 index e58d7bfb3..000000000 --- a/ruby/benchmark/vm2_poly_singleton.yml +++ /dev/null @@ -1,18 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_poly_singleton: | - class C1 - def m; 1; end - end - - o1 = C1.new - o2 = C1.new - o2.singleton_class - - i = 0 - while i<6_000_000 # benchmark loop 2 - o = (i % 2 == 0) ? o1 : o2 - o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m - i += 1 - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_proc.yml b/ruby/benchmark/vm2_proc.yml deleted file mode 100644 index 5c36e936d..000000000 --- a/ruby/benchmark/vm2_proc.yml +++ /dev/null @@ -1,12 +0,0 @@ -prelude: | - def m &b - b - end - - pr = m{ - a = 1 - } -benchmark: - vm2_proc: | - pr.call -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_raise1.yml b/ruby/benchmark/vm2_raise1.yml deleted file mode 100644 index f6eb30896..000000000 --- a/ruby/benchmark/vm2_raise1.yml +++ /dev/null @@ -1,16 +0,0 @@ -prelude: | - def rec n - if n > 0 - rec n-1 - else - raise - end - end -benchmark: - vm2_raise1: | - begin - rec 1 - rescue - # ignore - end -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_raise2.yml b/ruby/benchmark/vm2_raise2.yml deleted file mode 100644 index 7d51b1b31..000000000 --- a/ruby/benchmark/vm2_raise2.yml +++ /dev/null @@ -1,16 +0,0 @@ -prelude: | - def rec n - if n > 0 - rec n-1 - else - raise - end - end -benchmark: - vm2_raise2: | - begin - rec 10 - rescue - # ignore - end -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_regexp.yml b/ruby/benchmark/vm2_regexp.yml deleted file mode 100644 index e53341f43..000000000 --- a/ruby/benchmark/vm2_regexp.yml +++ /dev/null @@ -1,8 +0,0 @@ -prelude: | - str = 'xxxhogexxx' -benchmark: - vm2_regexp: | - /hoge/ =~ str - vm2_regexp_invert: | - str =~ /hoge/ -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_send.yml b/ruby/benchmark/vm2_send.yml deleted file mode 100644 index 44a12a27d..000000000 --- a/ruby/benchmark/vm2_send.yml +++ /dev/null @@ -1,11 +0,0 @@ -prelude: | - class C - def m - end - end - - o = C.new -benchmark: - vm2_send: | - o.__send__ :m -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_string_literal.yml b/ruby/benchmark/vm2_string_literal.yml deleted file mode 100644 index 54b0aec1f..000000000 --- a/ruby/benchmark/vm2_string_literal.yml +++ /dev/null @@ -1,4 +0,0 @@ -benchmark: - vm2_string_literal: | - x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_big_aref_hi.yml b/ruby/benchmark/vm2_struct_big_aref_hi.yml deleted file mode 100644 index eed1846d2..000000000 --- a/ruby/benchmark/vm2_struct_big_aref_hi.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new -benchmark: - vm2_struct_big_aref_hi: | - x.z # x[25] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_big_aref_lo.yml b/ruby/benchmark/vm2_struct_big_aref_lo.yml deleted file mode 100644 index 0915435b7..000000000 --- a/ruby/benchmark/vm2_struct_big_aref_lo.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new -benchmark: - vm2_struct_big_aref_lo: | - x.k # x[10] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_big_aset.yml b/ruby/benchmark/vm2_struct_big_aset.yml deleted file mode 100644 index 6af50103d..000000000 --- a/ruby/benchmark/vm2_struct_big_aset.yml +++ /dev/null @@ -1,11 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_struct_big_aset: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new - i = 0 - while i<6_000_000 - i += 1 - x.k = i # x[10] = i - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_struct_big_href_hi.yml b/ruby/benchmark/vm2_struct_big_href_hi.yml deleted file mode 100644 index 60aa7fddf..000000000 --- a/ruby/benchmark/vm2_struct_big_href_hi.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new -benchmark: - vm2_struct_big_href_hi: | - x[:z] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_big_href_lo.yml b/ruby/benchmark/vm2_struct_big_href_lo.yml deleted file mode 100644 index c55c0bd16..000000000 --- a/ruby/benchmark/vm2_struct_big_href_lo.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new -benchmark: - vm2_struct_big_href_lo: | - x[:k] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_big_hset.yml b/ruby/benchmark/vm2_struct_big_hset.yml deleted file mode 100644 index d199c5bd4..000000000 --- a/ruby/benchmark/vm2_struct_big_hset.yml +++ /dev/null @@ -1,11 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_struct_big_hset: | - s = Struct.new(*('a'..'z').map { |x| x.to_sym }) - x = s.new - i = 0 - while i<6_000_000 - i += 1 - x[:k] = i - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_struct_small_aref.yml b/ruby/benchmark/vm2_struct_small_aref.yml deleted file mode 100644 index 83381bed3..000000000 --- a/ruby/benchmark/vm2_struct_small_aref.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(:a, :b, :c) - x = s.new -benchmark: - vm2_struct_small_aref: | - x.a -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_small_aset.yml b/ruby/benchmark/vm2_struct_small_aset.yml deleted file mode 100644 index 3e84a61dd..000000000 --- a/ruby/benchmark/vm2_struct_small_aset.yml +++ /dev/null @@ -1,11 +0,0 @@ -# loop_count is not utilized since `i` is involved in the script -benchmark: - vm2_struct_small_aset: | - s = Struct.new(:a, :b, :c) - x = s.new - i = 0 - while i<6_000_000 - i += 1 - x.a = i - end -loop_count: 1 diff --git a/ruby/benchmark/vm2_struct_small_href.yml b/ruby/benchmark/vm2_struct_small_href.yml deleted file mode 100644 index b744f070d..000000000 --- a/ruby/benchmark/vm2_struct_small_href.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(:a, :b, :c) - x = s.new -benchmark: - vm2_struct_small_href: | - x[:a] -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_struct_small_hset.yml b/ruby/benchmark/vm2_struct_small_hset.yml deleted file mode 100644 index d43845d6e..000000000 --- a/ruby/benchmark/vm2_struct_small_hset.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - s = Struct.new(:a, :b, :c) - x = s.new -benchmark: - vm2_struct_small_hset: | - x[:a] = 1 -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_super.yml b/ruby/benchmark/vm2_super.yml deleted file mode 100644 index 674743762..000000000 --- a/ruby/benchmark/vm2_super.yml +++ /dev/null @@ -1,17 +0,0 @@ -prelude: | - class C - def m - 1 - end - end - - class CC < C - def m - super() - end - end - - obj = CC.new -benchmark: - vm2_super: obj.m -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_unif1.yml b/ruby/benchmark/vm2_unif1.yml deleted file mode 100644 index caef13279..000000000 --- a/ruby/benchmark/vm2_unif1.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - def m a, b - end -benchmark: - vm2_unif1: | - m 100, 200 -loop_count: 6000000 diff --git a/ruby/benchmark/vm2_zsuper.yml b/ruby/benchmark/vm2_zsuper.yml deleted file mode 100644 index f760cfd48..000000000 --- a/ruby/benchmark/vm2_zsuper.yml +++ /dev/null @@ -1,18 +0,0 @@ -prelude: | - class C - def m a - 1 - end - end - - class CC < C - def m a - super - end - end - - obj = CC.new -benchmark: - vm2_zsuper: | - obj.m 10 -loop_count: 6000000 diff --git a/ruby/benchmark/vm_array.yml b/ruby/benchmark/vm_array.yml new file mode 100644 index 000000000..2a177237e --- /dev/null +++ b/ruby/benchmark/vm_array.yml @@ -0,0 +1,4 @@ +benchmark: + vm_array: | + a = [1,2,3,4,5,6,7,8,9,10] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_attr_ivar.yml b/ruby/benchmark/vm_attr_ivar.yml new file mode 100644 index 000000000..75b803478 --- /dev/null +++ b/ruby/benchmark/vm_attr_ivar.yml @@ -0,0 +1,14 @@ +prelude: | + class C + attr_reader :a, :b + def initialize + @a = nil + @b = nil + end + end + obj = C.new +benchmark: + vm_attr_ivar: | + j = obj.a + k = obj.b +loop_count: 30000000 diff --git a/ruby/benchmark/vm_attr_ivar_set.yml b/ruby/benchmark/vm_attr_ivar_set.yml new file mode 100644 index 000000000..a0d379b18 --- /dev/null +++ b/ruby/benchmark/vm_attr_ivar_set.yml @@ -0,0 +1,14 @@ +prelude: | + class C + attr_accessor :a, :b + def initialize + @a = nil + @b = nil + end + end + obj = C.new +benchmark: + vm_attr_ivar_set: | + obj.a = 1 + obj.b = 2 +loop_count: 30000000 diff --git a/ruby/benchmark/vm3_backtrace.rb b/ruby/benchmark/vm_backtrace.rb similarity index 100% rename from ruby/benchmark/vm3_backtrace.rb rename to ruby/benchmark/vm_backtrace.rb diff --git a/ruby/benchmark/vm_bigarray.yml b/ruby/benchmark/vm_bigarray.yml new file mode 100644 index 000000000..8b2d3f344 --- /dev/null +++ b/ruby/benchmark/vm_bigarray.yml @@ -0,0 +1,105 @@ +benchmark: + vm_bigarray: | + a = [ + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + ] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_bighash.yml b/ruby/benchmark/vm_bighash.yml new file mode 100644 index 000000000..4dacfde79 --- /dev/null +++ b/ruby/benchmark/vm_bighash.yml @@ -0,0 +1,4 @@ +benchmark: + vm_bighash: | + a = {0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19, 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29, 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79, 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 128=>128, 129=>129, 130=>130, 131=>131, 132=>132, 133=>133, 134=>134, 135=>135, 136=>136, 137=>137, 138=>138, 139=>139, 140=>140, 141=>141, 142=>142, 143=>143, 144=>144, 145=>145, 146=>146, 147=>147, 148=>148, 149=>149, 150=>150, 151=>151, 152=>152, 153=>153, 154=>154, 155=>155, 156=>156, 157=>157, 158=>158, 159=>159, 160=>160, 161=>161, 162=>162, 163=>163, 164=>164, 165=>165, 166=>166, 167=>167, 168=>168, 169=>169, 170=>170, 171=>171, 172=>172, 173=>173, 174=>174, 175=>175, 176=>176, 177=>177, 178=>178, 179=>179, 180=>180, 181=>181, 182=>182, 183=>183, 184=>184, 185=>185, 186=>186, 187=>187, 188=>188, 189=>189, 190=>190, 191=>191, 192=>192, 193=>193, 194=>194, 195=>195, 196=>196, 197=>197, 198=>198, 199=>199, 200=>200, 201=>201, 202=>202, 203=>203, 204=>204, 205=>205, 206=>206, 207=>207, 208=>208, 209=>209, 210=>210, 211=>211, 212=>212, 213=>213, 214=>214, 215=>215, 216=>216, 217=>217, 218=>218, 219=>219, 220=>220, 221=>221, 222=>222, 223=>223, 224=>224, 225=>225, 226=>226, 227=>227, 228=>228, 229=>229, 230=>230, 231=>231, 232=>232, 233=>233, 234=>234, 235=>235, 236=>236, 237=>237, 238=>238, 239=>239, 240=>240, 241=>241, 242=>242, 243=>243, 244=>244, 245=>245, 246=>246, 247=>247, 248=>248, 249=>249, 250=>250, 251=>251, 252=>252, 253=>253, 254=>254, 255=>255, 256=>256, 257=>257, 258=>258, 259=>259, 260=>260, 261=>261, 262=>262, 263=>263, 264=>264, 265=>265, 266=>266, 267=>267, 268=>268, 269=>269, 270=>270, 271=>271, 272=>272, 273=>273, 274=>274, 275=>275, 276=>276, 277=>277, 278=>278, 279=>279, 280=>280, 281=>281, 282=>282, 283=>283, 284=>284, 285=>285, 286=>286, 287=>287, 288=>288, 289=>289, 290=>290, 291=>291, 292=>292, 293=>293, 294=>294, 295=>295, 296=>296, 297=>297, 298=>298, 299=>299, 300=>300, 301=>301, 302=>302, 303=>303, 304=>304, 305=>305, 306=>306, 307=>307, 308=>308, 309=>309, 310=>310, 311=>311, 312=>312, 313=>313, 314=>314, 315=>315, 316=>316, 317=>317, 318=>318, 319=>319, 320=>320, 321=>321, 322=>322, 323=>323, 324=>324, 325=>325, 326=>326, 327=>327, 328=>328, 329=>329, 330=>330, 331=>331, 332=>332, 333=>333, 334=>334, 335=>335, 336=>336, 337=>337, 338=>338, 339=>339, 340=>340, 341=>341, 342=>342, 343=>343, 344=>344, 345=>345, 346=>346, 347=>347, 348=>348, 349=>349, 350=>350, 351=>351, 352=>352, 353=>353, 354=>354, 355=>355, 356=>356, 357=>357, 358=>358, 359=>359, 360=>360, 361=>361, 362=>362, 363=>363, 364=>364, 365=>365, 366=>366, 367=>367, 368=>368, 369=>369, 370=>370, 371=>371, 372=>372, 373=>373, 374=>374, 375=>375, 376=>376, 377=>377, 378=>378, 379=>379, 380=>380, 381=>381, 382=>382, 383=>383, 384=>384, 385=>385, 386=>386, 387=>387, 388=>388, 389=>389, 390=>390, 391=>391, 392=>392, 393=>393, 394=>394, 395=>395, 396=>396, 397=>397, 398=>398, 399=>399, 400=>400, 401=>401, 402=>402, 403=>403, 404=>404, 405=>405, 406=>406, 407=>407, 408=>408, 409=>409, 410=>410, 411=>411, 412=>412, 413=>413, 414=>414, 415=>415, 416=>416, 417=>417, 418=>418, 419=>419, 420=>420, 421=>421, 422=>422, 423=>423, 424=>424, 425=>425, 426=>426, 427=>427, 428=>428, 429=>429, 430=>430, 431=>431, 432=>432, 433=>433, 434=>434, 435=>435, 436=>436, 437=>437, 438=>438, 439=>439, 440=>440, 441=>441, 442=>442, 443=>443, 444=>444, 445=>445, 446=>446, 447=>447, 448=>448, 449=>449, 450=>450, 451=>451, 452=>452, 453=>453, 454=>454, 455=>455, 456=>456, 457=>457, 458=>458, 459=>459, 460=>460, 461=>461, 462=>462, 463=>463, 464=>464, 465=>465, 466=>466, 467=>467, 468=>468, 469=>469, 470=>470, 471=>471, 472=>472, 473=>473, 474=>474, 475=>475, 476=>476, 477=>477, 478=>478, 479=>479, 480=>480, 481=>481, 482=>482, 483=>483, 484=>484, 485=>485, 486=>486, 487=>487, 488=>488, 489=>489, 490=>490, 491=>491, 492=>492, 493=>493, 494=>494, 495=>495, 496=>496, 497=>497, 498=>498, 499=>499, 500=>500,} +loop_count: 60000 diff --git a/ruby/benchmark/vm_block.yml b/ruby/benchmark/vm_block.yml new file mode 100644 index 000000000..68b3e40bf --- /dev/null +++ b/ruby/benchmark/vm_block.yml @@ -0,0 +1,9 @@ +prelude: | + def m + yield + end +benchmark: + vm_block: | + m{ + } +loop_count: 30000000 diff --git a/ruby/benchmark/vm_block_handler.yml b/ruby/benchmark/vm_block_handler.yml new file mode 100644 index 000000000..461d7953a --- /dev/null +++ b/ruby/benchmark/vm_block_handler.yml @@ -0,0 +1,27 @@ +# :FIXME: is there a way to benchmark block_handler_type_ifunc? + +prelude: | + p = proc{_1} + o = Object.new + def o.each + i = 0 + while i < 3_000_000 do + yield i + i += 1 + end + end + +benchmark: + - name: block_handler_type_iseq + script: | + o.each{_1} + + - name: block_handler_type_symbol + script: | + o.each(&:itself) + + - name: block_handler_type_proc + script: | + o.each(&p) + +loop_count: 1 diff --git a/ruby/benchmark/vm_blockparam.yml b/ruby/benchmark/vm_blockparam.yml new file mode 100644 index 000000000..5e5a0170a --- /dev/null +++ b/ruby/benchmark/vm_blockparam.yml @@ -0,0 +1,7 @@ +prelude: | + def m &b + end +benchmark: + vm_blockparam: | + m{} +loop_count: 30000000 diff --git a/ruby/benchmark/vm_blockparam_call.yml b/ruby/benchmark/vm_blockparam_call.yml new file mode 100644 index 000000000..a7d8d366e --- /dev/null +++ b/ruby/benchmark/vm_blockparam_call.yml @@ -0,0 +1,8 @@ +prelude: | + def m &b + b.call + end +benchmark: + vm_blockparam_call: | + m{} +loop_count: 30000000 diff --git a/ruby/benchmark/vm_blockparam_pass.yml b/ruby/benchmark/vm_blockparam_pass.yml new file mode 100644 index 000000000..841f5e7a6 --- /dev/null +++ b/ruby/benchmark/vm_blockparam_pass.yml @@ -0,0 +1,12 @@ +prelude: | + def bp_yield + yield + end + + def bp_pass &b + bp_yield &b + end +benchmark: + vm_blockparam_pass: | + bp_pass{} +loop_count: 30000000 diff --git a/ruby/benchmark/vm_blockparam_yield.yml b/ruby/benchmark/vm_blockparam_yield.yml new file mode 100644 index 000000000..8ea9b46ed --- /dev/null +++ b/ruby/benchmark/vm_blockparam_yield.yml @@ -0,0 +1,8 @@ +prelude: | + def bp_yield &b + yield + end +benchmark: + vm_blockparam_yield: | + bp_yield{} +loop_count: 30000000 diff --git a/ruby/benchmark/vm_case.yml b/ruby/benchmark/vm_case.yml new file mode 100644 index 000000000..b26a491a1 --- /dev/null +++ b/ruby/benchmark/vm_case.yml @@ -0,0 +1,13 @@ +benchmark: + vm_case: | + case :foo + when :bar + raise + when :baz + raise + when :boo + raise + when :foo + # noop + end +loop_count: 6000000 diff --git a/ruby/benchmark/vm_case_classes.yml b/ruby/benchmark/vm_case_classes.yml new file mode 100644 index 000000000..cacc4f046 --- /dev/null +++ b/ruby/benchmark/vm_case_classes.yml @@ -0,0 +1,9 @@ +benchmark: + vm_case_classes: | + case :foo + when Hash + raise + when Array + raise + end +loop_count: 6000000 diff --git a/ruby/benchmark/vm_case_lit.yml b/ruby/benchmark/vm_case_lit.yml new file mode 100644 index 000000000..9f9180154 --- /dev/null +++ b/ruby/benchmark/vm_case_lit.yml @@ -0,0 +1,23 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_case_lit: | + i = 0 + @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ] + def foo(i) + @ret[i % @ret.size] + end + + while i<6_000_000 + case foo(i) + when "foo" then :foo + when true then true + when false then false + when :sym then :sym + when 6 then :fix + when nil then nil + when 0.1 then :float + when 0xffffffffffffffff then :big + end + i += 1 + end +loop_count: 1 diff --git a/ruby/benchmark/vm3_clearmethodcache.rb b/ruby/benchmark/vm_clearmethodcache.rb similarity index 100% rename from ruby/benchmark/vm3_clearmethodcache.rb rename to ruby/benchmark/vm_clearmethodcache.rb diff --git a/ruby/benchmark/vm_const.yml b/ruby/benchmark/vm_const.yml new file mode 100644 index 000000000..6064d4eed --- /dev/null +++ b/ruby/benchmark/vm_const.yml @@ -0,0 +1,7 @@ +prelude: | + Const = 1 +benchmark: + vm_const: | + j = Const + k = Const +loop_count: 30000000 diff --git a/ruby/benchmark/vm_cvar.yml b/ruby/benchmark/vm_cvar.yml new file mode 100644 index 000000000..1d0e16182 --- /dev/null +++ b/ruby/benchmark/vm_cvar.yml @@ -0,0 +1,20 @@ +prelude: | + class A + @@foo = 1 + + def self.foo + @@foo + end + + ("A".."Z").each do |module_name| + eval <<-EOM + module #{module_name} + end + + include #{module_name} + EOM + end + end +benchmark: + vm_cvar: A.foo +loop_count: 600000 diff --git a/ruby/benchmark/vm_defined_method.yml b/ruby/benchmark/vm_defined_method.yml new file mode 100644 index 000000000..347e0cfd3 --- /dev/null +++ b/ruby/benchmark/vm_defined_method.yml @@ -0,0 +1,8 @@ +prelude: | + class Object + define_method(:m){} + end +benchmark: + vm_defined_method: | + m; m; m; m; m; m; m; m; +loop_count: 6000000 diff --git a/ruby/benchmark/vm_dstr.yml b/ruby/benchmark/vm_dstr.yml new file mode 100644 index 000000000..30c7a3193 --- /dev/null +++ b/ruby/benchmark/vm_dstr.yml @@ -0,0 +1,6 @@ +prelude: | + x = y = 'z' +benchmark: + vm_dstr: | + str = "foo#{x}bar#{y}baz" +loop_count: 6000000 diff --git a/ruby/benchmark/vm_dstr_ary.rb b/ruby/benchmark/vm_dstr_ary.rb new file mode 100644 index 000000000..1d3aa3b97 --- /dev/null +++ b/ruby/benchmark/vm_dstr_ary.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = [] +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_bool.rb b/ruby/benchmark/vm_dstr_bool.rb new file mode 100644 index 000000000..631ca5475 --- /dev/null +++ b/ruby/benchmark/vm_dstr_bool.rb @@ -0,0 +1,7 @@ +i = 0 +x = true +y = false +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_class_module.rb b/ruby/benchmark/vm_dstr_class_module.rb new file mode 100644 index 000000000..becf0861c --- /dev/null +++ b/ruby/benchmark/vm_dstr_class_module.rb @@ -0,0 +1,10 @@ +i = 0 +class A; end unless defined?(A) +module B; end unless defined?(B) +x = A +y = B +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end + diff --git a/ruby/benchmark/vm_dstr_digit.rb b/ruby/benchmark/vm_dstr_digit.rb new file mode 100644 index 000000000..caaa39519 --- /dev/null +++ b/ruby/benchmark/vm_dstr_digit.rb @@ -0,0 +1,7 @@ +i = 0 +x = 0 +y = 9 +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_int.rb b/ruby/benchmark/vm_dstr_int.rb new file mode 100644 index 000000000..ed380d759 --- /dev/null +++ b/ruby/benchmark/vm_dstr_int.rb @@ -0,0 +1,5 @@ +i = 0 +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{i}bar#{i}baz" +end diff --git a/ruby/benchmark/vm_dstr_nil.rb b/ruby/benchmark/vm_dstr_nil.rb new file mode 100644 index 000000000..ec4f5d6c6 --- /dev/null +++ b/ruby/benchmark/vm_dstr_nil.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = nil +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_obj.rb b/ruby/benchmark/vm_dstr_obj.rb new file mode 100644 index 000000000..fb78637ea --- /dev/null +++ b/ruby/benchmark/vm_dstr_obj.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = Object.new +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_obj_def.rb b/ruby/benchmark/vm_dstr_obj_def.rb new file mode 100644 index 000000000..99ff7b98f --- /dev/null +++ b/ruby/benchmark/vm_dstr_obj_def.rb @@ -0,0 +1,8 @@ +i = 0 +o = Object.new +def o.to_s; -""; end +x = y = o +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_str.rb b/ruby/benchmark/vm_dstr_str.rb new file mode 100644 index 000000000..45fc10789 --- /dev/null +++ b/ruby/benchmark/vm_dstr_str.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = "" +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_dstr_sym.rb b/ruby/benchmark/vm_dstr_sym.rb new file mode 100644 index 000000000..484b8f815 --- /dev/null +++ b/ruby/benchmark/vm_dstr_sym.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = :z +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/ruby/benchmark/vm_ensure.yml b/ruby/benchmark/vm_ensure.yml new file mode 100644 index 000000000..4ea62f30d --- /dev/null +++ b/ruby/benchmark/vm_ensure.yml @@ -0,0 +1,14 @@ +# Not utilizing loop_count since using it for this is too unstable for now +benchmark: + vm_ensure: | + i = 0 + while i<30_000_000 + i += 1 + begin + begin + ensure + end + ensure + end + end +loop_count: 1 diff --git a/ruby/benchmark/vm_eval.yml b/ruby/benchmark/vm_eval.yml new file mode 100644 index 000000000..7ba1a8d1d --- /dev/null +++ b/ruby/benchmark/vm_eval.yml @@ -0,0 +1,4 @@ +benchmark: + vm_eval: | + eval("1") +loop_count: 6000000 diff --git a/ruby/benchmark/vm_fiber_allocate.yml b/ruby/benchmark/vm_fiber_allocate.yml new file mode 100644 index 000000000..b5a54e1dd --- /dev/null +++ b/ruby/benchmark/vm_fiber_allocate.yml @@ -0,0 +1,8 @@ +prelude: | + # Disable GC to see raw throughput: + GC.disable +benchmark: + vm_fiber_allocate: | + fiber = Fiber.new{Fiber.yield} + fiber.resume +loop_count: 100000 diff --git a/ruby/benchmark/vm_fiber_count.yml b/ruby/benchmark/vm_fiber_count.yml new file mode 100644 index 000000000..b83d3152d --- /dev/null +++ b/ruby/benchmark/vm_fiber_count.yml @@ -0,0 +1,10 @@ +# On Linux, you will need to increase the maximum number of memory maps: +# sudo sysctl -w vm.max_map_count=200000 +prelude: | + fibers = [] +benchmark: + vm_fiber_count: | + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume +loop_count: 100000 diff --git a/ruby/benchmark/vm_fiber_reuse.yml b/ruby/benchmark/vm_fiber_reuse.yml new file mode 100644 index 000000000..4ca41085b --- /dev/null +++ b/ruby/benchmark/vm_fiber_reuse.yml @@ -0,0 +1,14 @@ +prelude: | + GC.disable + fibers = [] +benchmark: + vm_fiber_reuse: | + 1024.times do + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume + end + + fibers.clear + GC.start +loop_count: 200 diff --git a/ruby/benchmark/vm_fiber_reuse_gc.yml b/ruby/benchmark/vm_fiber_reuse_gc.yml new file mode 100644 index 000000000..892622f12 --- /dev/null +++ b/ruby/benchmark/vm_fiber_reuse_gc.yml @@ -0,0 +1,12 @@ +# https://bugs.ruby-lang.org/issues/16009 +prelude: | + fibers = [] +benchmark: + vm_fiber_reuse_gc: | + 2000.times do + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume + end + fibers.clear +loop_count: 100 diff --git a/ruby/benchmark/vm_fiber_switch.yml b/ruby/benchmark/vm_fiber_switch.yml new file mode 100644 index 000000000..3de36b66e --- /dev/null +++ b/ruby/benchmark/vm_fiber_switch.yml @@ -0,0 +1,9 @@ +prelude: | + # based on benchmark for [ruby-core:65518] [Feature #10341] by Knut Franke + fib = Fiber.new do + loop { Fiber.yield } + end +benchmark: + vm_fiber_switch: | + fib.resume +loop_count: 20000000 diff --git a/ruby/benchmark/vm_float_simple.yml b/ruby/benchmark/vm_float_simple.yml new file mode 100644 index 000000000..92f5fd52a --- /dev/null +++ b/ruby/benchmark/vm_float_simple.yml @@ -0,0 +1,8 @@ +prelude: | + f = 0.0 +benchmark: + vm_float_simple: | + f += 0.1; f -= 0.1 + f += 0.1; f -= 0.1 + f += 0.1; f -= 0.1 +loop_count: 30000000 diff --git a/ruby/benchmark/vm_freezestring.yml b/ruby/benchmark/vm_freezestring.yml new file mode 100644 index 000000000..facc9aa04 --- /dev/null +++ b/ruby/benchmark/vm_freezestring.yml @@ -0,0 +1,10 @@ +prelude: | + class String + def freeze + -self + end + end +benchmark: + vm_freezestring: | + "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze +loop_count: 6000000 diff --git a/ruby/benchmark/vm3_gc.rb b/ruby/benchmark/vm_gc.rb similarity index 100% rename from ruby/benchmark/vm3_gc.rb rename to ruby/benchmark/vm_gc.rb diff --git a/ruby/benchmark/vm3_gc_old_full.rb b/ruby/benchmark/vm_gc_old_full.rb similarity index 100% rename from ruby/benchmark/vm3_gc_old_full.rb rename to ruby/benchmark/vm_gc_old_full.rb diff --git a/ruby/benchmark/vm3_gc_old_immediate.rb b/ruby/benchmark/vm_gc_old_immediate.rb similarity index 100% rename from ruby/benchmark/vm3_gc_old_immediate.rb rename to ruby/benchmark/vm_gc_old_immediate.rb diff --git a/ruby/benchmark/vm3_gc_old_lazy.rb b/ruby/benchmark/vm_gc_old_lazy.rb similarity index 100% rename from ruby/benchmark/vm3_gc_old_lazy.rb rename to ruby/benchmark/vm_gc_old_lazy.rb diff --git a/ruby/benchmark/vm_gc_short_lived.yml b/ruby/benchmark/vm_gc_short_lived.yml new file mode 100644 index 000000000..29c803fee --- /dev/null +++ b/ruby/benchmark/vm_gc_short_lived.yml @@ -0,0 +1,9 @@ +benchmark: + vm_gc_short_lived: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_short_with_complex_long.yml b/ruby/benchmark/vm_gc_short_with_complex_long.yml new file mode 100644 index 000000000..4b6c3ed7b --- /dev/null +++ b/ruby/benchmark/vm_gc_short_with_complex_long.yml @@ -0,0 +1,25 @@ +prelude: | + def nested_hash h, n + if n == 0 + '' + else + 10.times{ + h[Object.new] = nested_hash(h, n-1) + } + end + end + + long_lived = Hash.new + nested_hash long_lived, 6 + + GC.start + GC.start +benchmark: + vm_gc_short_with_complex_long: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_short_with_long.yml b/ruby/benchmark/vm_gc_short_with_long.yml new file mode 100644 index 000000000..03ba0f95a --- /dev/null +++ b/ruby/benchmark/vm_gc_short_with_long.yml @@ -0,0 +1,13 @@ +prelude: | + long_lived = Array.new(1_000_000){|i| "#{i}"} + GC.start + GC.start +benchmark: + vm_gc_short_with_long: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_short_with_symbol.yml b/ruby/benchmark/vm_gc_short_with_symbol.yml new file mode 100644 index 000000000..129b8bf4e --- /dev/null +++ b/ruby/benchmark/vm_gc_short_with_symbol.yml @@ -0,0 +1,13 @@ +prelude: | + 50_000.times{|i| sym = "sym#{i}".to_sym} + GC.start + GC.start +benchmark: + vm_gc_short_with_symbol: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_wb_ary.yml b/ruby/benchmark/vm_gc_wb_ary.yml new file mode 100644 index 000000000..e3293e72d --- /dev/null +++ b/ruby/benchmark/vm_gc_wb_ary.yml @@ -0,0 +1,12 @@ +prelude: | + short_lived_ary = [] + + if RUBY_VERSION >= "2.2.0" + GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) + end + + short_lived = '' +benchmark: + vm_gc_wb_ary: | + short_lived_ary[0] = short_lived # write barrier +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_wb_ary_promoted.yml b/ruby/benchmark/vm_gc_wb_ary_promoted.yml new file mode 100644 index 000000000..003995945 --- /dev/null +++ b/ruby/benchmark/vm_gc_wb_ary_promoted.yml @@ -0,0 +1,15 @@ +prelude: | + long_lived = [] + + if RUBY_VERSION > "2.2.0" + 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } + elsif + GC.start + end + + short_lived = '' + +benchmark: + vm_gc_wb_ary_promoted: | + long_lived[0] = short_lived # write barrier +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_wb_obj.yml b/ruby/benchmark/vm_gc_wb_obj.yml new file mode 100644 index 000000000..a2a2ce2d1 --- /dev/null +++ b/ruby/benchmark/vm_gc_wb_obj.yml @@ -0,0 +1,15 @@ +prelude: | + class C + attr_accessor :foo + end + short_lived_obj = C.new + + if RUBY_VERSION >= "2.2.0" + GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) + end + + short_lived = '' +benchmark: + vm_gc_wb_obj: | + short_lived_obj.foo = short_lived # write barrier +loop_count: 30000000 diff --git a/ruby/benchmark/vm_gc_wb_obj_promoted.yml b/ruby/benchmark/vm_gc_wb_obj_promoted.yml new file mode 100644 index 000000000..00a454ba7 --- /dev/null +++ b/ruby/benchmark/vm_gc_wb_obj_promoted.yml @@ -0,0 +1,17 @@ +prelude: | + class C + attr_accessor :foo + end + long_lived = C.new + + if RUBY_VERSION >= "2.2.0" + 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } + elsif + GC.start + end + + short_lived = '' +benchmark: + vm_gc_wb_obj_promoted: | + long_lived.foo = short_lived # write barrier +loop_count: 30000000 diff --git a/ruby/benchmark/vm_iclass_super.yml b/ruby/benchmark/vm_iclass_super.yml new file mode 100644 index 000000000..21bb7db24 --- /dev/null +++ b/ruby/benchmark/vm_iclass_super.yml @@ -0,0 +1,20 @@ +prelude: | + class C + def m + 1 + end + + ("A".."M").each do |module_name| + eval <<-EOM + module #{module_name} + def m; super; end + end + prepend #{module_name} + EOM + end + end + + obj = C.new +benchmark: + vm_iclass_super: obj.m +loop_count: 6000000 diff --git a/ruby/benchmark/vm_ivar.yml b/ruby/benchmark/vm_ivar.yml new file mode 100644 index 000000000..119531d5e --- /dev/null +++ b/ruby/benchmark/vm_ivar.yml @@ -0,0 +1,6 @@ +prelude: "@a = 1\n" +benchmark: + vm_ivar: | + j = @a + k = @a +loop_count: 30000000 diff --git a/ruby/benchmark/vm_ivar_init.yml b/ruby/benchmark/vm_ivar_init.yml new file mode 100644 index 000000000..c6f163390 --- /dev/null +++ b/ruby/benchmark/vm_ivar_init.yml @@ -0,0 +1,14 @@ +prelude: | + class C + def initialize + @a = nil + @b = nil + @c = nil + @d = nil + @e = nil + end + end +benchmark: + vm_ivar_init: | + C.new +loop_count: 30000000 diff --git a/ruby/benchmark/vm_ivar_of_class.yml b/ruby/benchmark/vm_ivar_of_class.yml new file mode 100644 index 000000000..172e28b2f --- /dev/null +++ b/ruby/benchmark/vm_ivar_of_class.yml @@ -0,0 +1,12 @@ +prelude: | + class C + @a = 1 + def self.a + _a = @a; _a = @a; _a = @a; _a = @a; _a = @a; + _a = @a; _a = @a; _a = @a; _a = @a; _a = @a; + end + end +benchmark: + vm_ivar_of_class: | + a = C.a +loop_count: 30000000 diff --git a/ruby/benchmark/vm_ivar_of_class_set.yml b/ruby/benchmark/vm_ivar_of_class_set.yml new file mode 100644 index 000000000..2ea519942 --- /dev/null +++ b/ruby/benchmark/vm_ivar_of_class_set.yml @@ -0,0 +1,11 @@ +prelude: | + class C + @a = 1 + def self.a o + @a = o; @a = o; @a = o; @a = o; @a = o; @a = o; + end + end +benchmark: + vm_ivar_of_class_set: | + a = C.a(nil) +loop_count: 30000000 diff --git a/ruby/benchmark/vm_ivar_set.yml b/ruby/benchmark/vm_ivar_set.yml new file mode 100644 index 000000000..8bbb60043 --- /dev/null +++ b/ruby/benchmark/vm_ivar_set.yml @@ -0,0 +1,5 @@ +benchmark: + vm_ivar_set: | + @a = 1 + @b = 2 +loop_count: 30000000 diff --git a/ruby/benchmark/vm_ivar_set_subclass.yml b/ruby/benchmark/vm_ivar_set_subclass.yml new file mode 100644 index 000000000..2653d36de --- /dev/null +++ b/ruby/benchmark/vm_ivar_set_subclass.yml @@ -0,0 +1,17 @@ +prelude: | + class A + def initialize + @a = nil + @b = nil + @c = nil + @d = nil + @e = nil + end + end + class B < A; end + class C < A; end +benchmark: + vm_ivar_init_subclass: | + B.new + C.new +loop_count: 3000000 diff --git a/ruby/benchmark/vm_length.yml b/ruby/benchmark/vm_length.yml new file mode 100644 index 000000000..5fd94e7d8 --- /dev/null +++ b/ruby/benchmark/vm_length.yml @@ -0,0 +1,8 @@ +prelude: | + a = 'abc' + b = [1, 2, 3] +benchmark: + vm_length: | + a.length + b.length +loop_count: 30000000 diff --git a/ruby/benchmark/vm_lvar_init.yml b/ruby/benchmark/vm_lvar_init.yml new file mode 100644 index 000000000..70a9b1c0c --- /dev/null +++ b/ruby/benchmark/vm_lvar_init.yml @@ -0,0 +1,21 @@ +# while loop cost is not removed because `i` is used in the script +benchmark: + vm_lvar_init: | + def m v + unless v + # unreachable code + v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 = + v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 = + v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 = + v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 = + v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1 + end + end + + i = 0 + + while i<30_000_000 + i += 1 + m i + end +loop_count: 1 diff --git a/ruby/benchmark/vm_lvar_set.yml b/ruby/benchmark/vm_lvar_set.yml new file mode 100644 index 000000000..f29f763d8 --- /dev/null +++ b/ruby/benchmark/vm_lvar_set.yml @@ -0,0 +1,4 @@ +benchmark: + vm_lvar_set: | + a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1 +loop_count: 30000000 diff --git a/ruby/benchmark/vm_method.yml b/ruby/benchmark/vm_method.yml new file mode 100644 index 000000000..d45e4ec57 --- /dev/null +++ b/ruby/benchmark/vm_method.yml @@ -0,0 +1,8 @@ +prelude: | + def m + nil + end +benchmark: + vm_method: | + m; m; m; m; m; m; m; m; +loop_count: 6000000 diff --git a/ruby/benchmark/vm_method_missing.yml b/ruby/benchmark/vm_method_missing.yml new file mode 100644 index 000000000..3da456c0b --- /dev/null +++ b/ruby/benchmark/vm_method_missing.yml @@ -0,0 +1,11 @@ +prelude: | + class C + def method_missing mid + end + end + + obj = C.new +benchmark: + vm_method_missing: | + obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; +loop_count: 6000000 diff --git a/ruby/benchmark/vm_method_with_block.yml b/ruby/benchmark/vm_method_with_block.yml new file mode 100644 index 000000000..281a48139 --- /dev/null +++ b/ruby/benchmark/vm_method_with_block.yml @@ -0,0 +1,8 @@ +prelude: | + def m + nil + end +benchmark: + vm_method_with_block: | + m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{}; +loop_count: 6000000 diff --git a/ruby/benchmark/vm_module_ann_const_set.yml b/ruby/benchmark/vm_module_ann_const_set.yml new file mode 100644 index 000000000..243229ba4 --- /dev/null +++ b/ruby/benchmark/vm_module_ann_const_set.yml @@ -0,0 +1,4 @@ +benchmark: + vm_module_ann_const_set: | + Module.new.const_set(:X, Module.new) +loop_count: 6000000 diff --git a/ruby/benchmark/vm_module_const_set.yml b/ruby/benchmark/vm_module_const_set.yml new file mode 100644 index 000000000..e5a24181a --- /dev/null +++ b/ruby/benchmark/vm_module_const_set.yml @@ -0,0 +1,8 @@ +prelude: | + module M + end + $VERBOSE = nil +benchmark: + vm_module_const_set: | + M.const_set(:X, Module.new) +loop_count: 6000000 diff --git a/ruby/benchmark/vm_mutex.yml b/ruby/benchmark/vm_mutex.yml new file mode 100644 index 000000000..abcf1e28c --- /dev/null +++ b/ruby/benchmark/vm_mutex.yml @@ -0,0 +1,8 @@ +prelude: | + require 'thread' + + m = Thread::Mutex.new +benchmark: + vm_mutex: | + m.synchronize{} +loop_count: 6000000 diff --git a/ruby/benchmark/vm_neq.yml b/ruby/benchmark/vm_neq.yml new file mode 100644 index 000000000..fb04d15ae --- /dev/null +++ b/ruby/benchmark/vm_neq.yml @@ -0,0 +1,7 @@ +prelude: | + obj1 = Object.new + obj2 = Object.new +benchmark: + vm_neq: | + obj1 != obj2 +loop_count: 30000000 diff --git a/ruby/benchmark/vm_newlambda.yml b/ruby/benchmark/vm_newlambda.yml new file mode 100644 index 000000000..0b9787d91 --- /dev/null +++ b/ruby/benchmark/vm_newlambda.yml @@ -0,0 +1,4 @@ +benchmark: + vm_newlambda: | + lambda {} +loop_count: 6000000 diff --git a/ruby/benchmark/vm_not.yml b/ruby/benchmark/vm_not.yml new file mode 100644 index 000000000..c68dde3c5 --- /dev/null +++ b/ruby/benchmark/vm_not.yml @@ -0,0 +1,6 @@ +prelude: | + obj = Object.new +benchmark: + vm_not: | + !obj +loop_count: 30000000 diff --git a/ruby/benchmark/vm_poly_method.yml b/ruby/benchmark/vm_poly_method.yml new file mode 100644 index 000000000..dd2f4e71d --- /dev/null +++ b/ruby/benchmark/vm_poly_method.yml @@ -0,0 +1,24 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_method: | + class C1 + def m + 1 + end + end + class C2 + def m + 2 + end + end + + o1 = C1.new + o2 = C2.new + + i = 0 + while i<6_000_000 + o = (i % 2 == 0) ? o1 : o2 + o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 1 diff --git a/ruby/benchmark/vm_poly_method_ov.yml b/ruby/benchmark/vm_poly_method_ov.yml new file mode 100644 index 000000000..bca1b6272 --- /dev/null +++ b/ruby/benchmark/vm_poly_method_ov.yml @@ -0,0 +1,24 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_method_ov: | + class C1 + def m + 1 + end + end + class C2 + def m + 2 + end + end + + o1 = C1.new + o2 = C2.new + + i = 0 + while i<6_000_000 + o = (i % 2 == 0) ? o1 : o2 + # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 1 diff --git a/ruby/benchmark/vm_poly_same_method.yml b/ruby/benchmark/vm_poly_same_method.yml new file mode 100644 index 000000000..6c5404ac8 --- /dev/null +++ b/ruby/benchmark/vm_poly_same_method.yml @@ -0,0 +1,25 @@ +prelude: | + module AR; end + class AR::Base + def create_or_update + nil + end + def save + create_or_update + end + end + class Foo < AR::Base; end + class Bar < AR::Base; end + o1 = Foo.new + o2 = Bar.new +benchmark: + vm_poly_same_method: | + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; +loop_count: 6000000 diff --git a/ruby/benchmark/vm_poly_singleton.yml b/ruby/benchmark/vm_poly_singleton.yml new file mode 100644 index 000000000..c7923160f --- /dev/null +++ b/ruby/benchmark/vm_poly_singleton.yml @@ -0,0 +1,18 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_singleton: | + class C1 + def m; 1; end + end + + o1 = C1.new + o2 = C1.new + o2.singleton_class + + i = 0 + while i<6_000_000 # benchmark loop 2 + o = (i % 2 == 0) ? o1 : o2 + o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 1 diff --git a/ruby/benchmark/vm_proc.yml b/ruby/benchmark/vm_proc.yml new file mode 100644 index 000000000..2f8de6c27 --- /dev/null +++ b/ruby/benchmark/vm_proc.yml @@ -0,0 +1,12 @@ +prelude: | + def m &b + b + end + + pr = m{ + a = 1 + } +benchmark: + vm_proc: | + pr.call +loop_count: 6000000 diff --git a/ruby/benchmark/vm_raise1.yml b/ruby/benchmark/vm_raise1.yml new file mode 100644 index 000000000..247d9f70e --- /dev/null +++ b/ruby/benchmark/vm_raise1.yml @@ -0,0 +1,16 @@ +prelude: | + def rec n + if n > 0 + rec n-1 + else + raise + end + end +benchmark: + vm_raise1: | + begin + rec 1 + rescue + # ignore + end +loop_count: 6000000 diff --git a/ruby/benchmark/vm_raise2.yml b/ruby/benchmark/vm_raise2.yml new file mode 100644 index 000000000..f0fa047b3 --- /dev/null +++ b/ruby/benchmark/vm_raise2.yml @@ -0,0 +1,16 @@ +prelude: | + def rec n + if n > 0 + rec n-1 + else + raise + end + end +benchmark: + vm_raise2: | + begin + rec 10 + rescue + # ignore + end +loop_count: 6000000 diff --git a/ruby/benchmark/vm_regexp.yml b/ruby/benchmark/vm_regexp.yml new file mode 100644 index 000000000..2aa3d94db --- /dev/null +++ b/ruby/benchmark/vm_regexp.yml @@ -0,0 +1,8 @@ +prelude: | + str = 'xxxhogexxx' +benchmark: + vm_regexp: | + /hoge/ =~ str + vm_regexp_invert: | + str =~ /hoge/ +loop_count: 6000000 diff --git a/ruby/benchmark/vm_rescue.yml b/ruby/benchmark/vm_rescue.yml new file mode 100644 index 000000000..b4a0af521 --- /dev/null +++ b/ruby/benchmark/vm_rescue.yml @@ -0,0 +1,6 @@ +benchmark: + vm_rescue: | + begin + rescue + end +loop_count: 30000000 diff --git a/ruby/benchmark/vm_send.yml b/ruby/benchmark/vm_send.yml new file mode 100644 index 000000000..f31bc7ac8 --- /dev/null +++ b/ruby/benchmark/vm_send.yml @@ -0,0 +1,14 @@ +prelude: | + class C + def m + end + end + + o = C.new + m = :m +benchmark: + vm_send: | + o.__send__ :m + vm_send_var: | + o.__send__ m +loop_count: 6000000 diff --git a/ruby/benchmark/vm_send_cfunc.yml b/ruby/benchmark/vm_send_cfunc.yml new file mode 100644 index 000000000..b114ac317 --- /dev/null +++ b/ruby/benchmark/vm_send_cfunc.yml @@ -0,0 +1,3 @@ +benchmark: + vm_send_cfunc: self.class +loop_count: 100000000 diff --git a/ruby/benchmark/vm_simplereturn.yml b/ruby/benchmark/vm_simplereturn.yml new file mode 100644 index 000000000..c9829cff0 --- /dev/null +++ b/ruby/benchmark/vm_simplereturn.yml @@ -0,0 +1,7 @@ +prelude: | + def m + return 1 + end +benchmark: + vm_simplereturn: m +loop_count: 30000000 diff --git a/ruby/benchmark/vm_string_literal.yml b/ruby/benchmark/vm_string_literal.yml new file mode 100644 index 000000000..64439c798 --- /dev/null +++ b/ruby/benchmark/vm_string_literal.yml @@ -0,0 +1,4 @@ +benchmark: + vm_string_literal: | + x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_big_aref_hi.yml b/ruby/benchmark/vm_struct_big_aref_hi.yml new file mode 100644 index 000000000..4cf78970c --- /dev/null +++ b/ruby/benchmark/vm_struct_big_aref_hi.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_aref_hi: | + x.z # x[25] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_big_aref_lo.yml b/ruby/benchmark/vm_struct_big_aref_lo.yml new file mode 100644 index 000000000..c91af27fa --- /dev/null +++ b/ruby/benchmark/vm_struct_big_aref_lo.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_aref_lo: | + x.k # x[10] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_big_aset.yml b/ruby/benchmark/vm_struct_big_aset.yml new file mode 100644 index 000000000..69550d14e --- /dev/null +++ b/ruby/benchmark/vm_struct_big_aset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_big_aset: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x.k = i # x[10] = i + end +loop_count: 1 diff --git a/ruby/benchmark/vm_struct_big_href_hi.yml b/ruby/benchmark/vm_struct_big_href_hi.yml new file mode 100644 index 000000000..09b764dd1 --- /dev/null +++ b/ruby/benchmark/vm_struct_big_href_hi.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_href_hi: | + x[:z] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_big_href_lo.yml b/ruby/benchmark/vm_struct_big_href_lo.yml new file mode 100644 index 000000000..d2f00b220 --- /dev/null +++ b/ruby/benchmark/vm_struct_big_href_lo.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_href_lo: | + x[:k] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_big_hset.yml b/ruby/benchmark/vm_struct_big_hset.yml new file mode 100644 index 000000000..fc45cbee9 --- /dev/null +++ b/ruby/benchmark/vm_struct_big_hset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_big_hset: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x[:k] = i + end +loop_count: 1 diff --git a/ruby/benchmark/vm_struct_small_aref.yml b/ruby/benchmark/vm_struct_small_aref.yml new file mode 100644 index 000000000..5a83251d1 --- /dev/null +++ b/ruby/benchmark/vm_struct_small_aref.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_aref: | + x.a +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_small_aset.yml b/ruby/benchmark/vm_struct_small_aset.yml new file mode 100644 index 000000000..74f435f12 --- /dev/null +++ b/ruby/benchmark/vm_struct_small_aset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_small_aset: | + s = Struct.new(:a, :b, :c) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x.a = i + end +loop_count: 1 diff --git a/ruby/benchmark/vm_struct_small_href.yml b/ruby/benchmark/vm_struct_small_href.yml new file mode 100644 index 000000000..6b7d7f39e --- /dev/null +++ b/ruby/benchmark/vm_struct_small_href.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_href: | + x[:a] +loop_count: 6000000 diff --git a/ruby/benchmark/vm_struct_small_hset.yml b/ruby/benchmark/vm_struct_small_hset.yml new file mode 100644 index 000000000..5d43b150d --- /dev/null +++ b/ruby/benchmark/vm_struct_small_hset.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_hset: | + x[:a] = 1 +loop_count: 6000000 diff --git a/ruby/benchmark/vm_super.yml b/ruby/benchmark/vm_super.yml new file mode 100644 index 000000000..0d1e965c6 --- /dev/null +++ b/ruby/benchmark/vm_super.yml @@ -0,0 +1,17 @@ +prelude: | + class C + def m + 1 + end + end + + class CC < C + def m + super() + end + end + + obj = CC.new +benchmark: + vm_super: obj.m +loop_count: 6000000 diff --git a/ruby/benchmark/vm_swap.yml b/ruby/benchmark/vm_swap.yml new file mode 100644 index 000000000..e824a65e0 --- /dev/null +++ b/ruby/benchmark/vm_swap.yml @@ -0,0 +1,7 @@ +prelude: | + a = 1 + b = 2 +benchmark: + vm_swap: | + a, b = b, a +loop_count: 30000000 diff --git a/ruby/benchmark/vm_thread_condvar1.rb b/ruby/benchmark/vm_thread_condvar1.rb index cf5706b23..feed27c3a 100644 --- a/ruby/benchmark/vm_thread_condvar1.rb +++ b/ruby/benchmark/vm_thread_condvar1.rb @@ -1,9 +1,9 @@ # two threads, two mutex, two condvar ping-pong require 'thread' -m1 = Mutex.new -m2 = Mutex.new -cv1 = ConditionVariable.new -cv2 = ConditionVariable.new +m1 = Thread::Mutex.new +m2 = Thread::Mutex.new +cv1 = Thread::ConditionVariable.new +cv2 = Thread::ConditionVariable.new max = 100000 i = 0 wait = nil diff --git a/ruby/benchmark/vm_thread_condvar2.rb b/ruby/benchmark/vm_thread_condvar2.rb index 7c8dc1948..6590c4134 100644 --- a/ruby/benchmark/vm_thread_condvar2.rb +++ b/ruby/benchmark/vm_thread_condvar2.rb @@ -1,16 +1,16 @@ # many threads, one mutex, many condvars require 'thread' -m = Mutex.new -cv1 = ConditionVariable.new -cv2 = ConditionVariable.new +m = Thread::Mutex.new +cv1 = Thread::ConditionVariable.new +cv2 = Thread::ConditionVariable.new max = 1000 n = 100 waiting = 0 scvs = [] waiters = n.times.map do |i| - start_cv = ConditionVariable.new + start_cv = Thread::ConditionVariable.new scvs << start_cv - start_mtx = Mutex.new + start_mtx = Thread::Mutex.new start_mtx.synchronize do th = Thread.new(start_mtx, start_cv) do |sm, scv| m.synchronize do diff --git a/ruby/benchmark/vm_unif1.yml b/ruby/benchmark/vm_unif1.yml new file mode 100644 index 000000000..04187bb0e --- /dev/null +++ b/ruby/benchmark/vm_unif1.yml @@ -0,0 +1,7 @@ +prelude: | + def m a, b + end +benchmark: + vm_unif1: | + m 100, 200 +loop_count: 6000000 diff --git a/ruby/benchmark/vm_yield.yml b/ruby/benchmark/vm_yield.yml new file mode 100644 index 000000000..230be3d84 --- /dev/null +++ b/ruby/benchmark/vm_yield.yml @@ -0,0 +1,13 @@ +# while loop cost is not removed due to benchmark_driver.gem's limitation +benchmark: + vm_yield: | + def m + i = 0 + while i<30_000_000 + i += 1 + yield + end + end + + m{} +loop_count: 1 diff --git a/ruby/benchmark/vm_zsuper.yml b/ruby/benchmark/vm_zsuper.yml new file mode 100644 index 000000000..bfb583757 --- /dev/null +++ b/ruby/benchmark/vm_zsuper.yml @@ -0,0 +1,18 @@ +prelude: | + class C + def m a + 1 + end + end + + class CC < C + def m a + super + end + end + + obj = CC.new +benchmark: + vm_zsuper: | + obj.m 10 +loop_count: 6000000 diff --git a/ruby/bignum.c b/ruby/bignum.c index 4569183e4..f83fbe2c1 100644 --- a/ruby/bignum.c +++ b/ruby/bignum.c @@ -9,32 +9,39 @@ **********************************************************************/ -#include "internal.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "id.h" +#include "ruby/internal/config.h" + +#include +#include +#include #ifdef HAVE_STRINGS_H -#include +# include #endif -#include -#include -#include + #ifdef HAVE_IEEEFP_H -#include +# include #endif -#include "ruby_assert.h" #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) -#define USE_GMP -#include +# define USE_GMP +# include #endif -#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM) +#include "id.h" +#include "internal.h" +#include "internal/bignum.h" +#include "internal/complex.h" +#include "internal/gc.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/sanitizers.h" +#include "internal/variable.h" +#include "internal/warnings.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "ruby_assert.h" -#ifndef RUBY_INTEGER_UNIFICATION -VALUE rb_cBignum; -#endif const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; #ifndef SIZEOF_BDIGIT_DBL @@ -65,7 +72,7 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0); #else # define HOST_BIGENDIAN_P 0 #endif -/* (!LSHIFTABLE(d, n) ? 0 : (n)) is same as n but suppress a warning, C4293, by Visual Studio. */ +/* (!LSHIFTABLE(d, n) ? 0 : (n)) is the same as n but suppress a warning, C4293, by Visual Studio. */ #define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT) #define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n)))) #define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits))) @@ -149,15 +156,11 @@ typedef void (mulfunc_t)(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, c static mulfunc_t bary_mul_toom3_start; static mulfunc_t bary_mul_karatsuba_start; static BDIGIT bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y); -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); -static VALUE bigmul0(VALUE x, VALUE y); -static void bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn); static VALUE bignew_1(VALUE klass, size_t len, int sign); static inline VALUE bigtrunc(VALUE x); static VALUE bigsq(VALUE x); -static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp); static inline VALUE power_cache_get_power(int base, int power_level, size_t *numdigits_ret); #if SIZEOF_BDIGIT <= SIZEOF_INT @@ -457,7 +460,6 @@ static int bary_2comp(BDIGIT *ds, size_t n) { size_t i; - i = 0; for (i = 0; i < n; i++) { if (ds[i] != 0) { goto non_zero; @@ -1047,6 +1049,7 @@ integer_unpack_num_bdigits(size_t numwords, size_t wordsize, size_t nails, int * size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1); assert(num_bdigits == num_bdigits1); assert(*nlp_bits_ret == nlp_bits1); + (void)num_bdigits1; } #endif } @@ -1638,11 +1641,13 @@ rb_big_sq_fast(VALUE x) /* balancing multiplication by slicing larger argument */ static void -bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn, mulfunc_t *mulfunc) +bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn, + const BDIGIT *const xds, const size_t xn, + const BDIGIT *const yds, const size_t yn, + BDIGIT *wds, size_t wn, mulfunc_t *const mulfunc) { VALUE work = 0; - size_t yn0 = yn; - size_t r, n; + size_t n; assert(xn + yn <= zn); assert(xn <= yn); @@ -1650,14 +1655,20 @@ bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t BDIGITS_ZERO(zds, xn); + if (wn < xn) { + const size_t r = (yn % xn) ? (yn % xn) : xn; + if ((2 * xn + yn + r) > zn) { + wn = xn; + wds = ALLOCV_N(BDIGIT, work, wn); + } + } + n = 0; - while (yn > 0) { - BDIGIT *tds; - size_t tn; - r = xn > yn ? yn : xn; - tn = xn + r; + while (yn > n) { + const size_t r = (xn > (yn - n) ? (yn - n) : xn); + const size_t tn = (xn + r); if (2 * (xn + r) <= zn - n) { - tds = zds + n + xn + r; + BDIGIT *const tds = zds + n + xn + r; mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn); BDIGITS_ZERO(zds + n + xn, r); bary_add(zds + n, tn, @@ -1665,21 +1676,25 @@ bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t tds, tn); } else { + BDIGIT *const tds = zds + n; if (wn < xn) { + /* xn is invariant, only once here */ +#if 0 wn = xn; wds = ALLOCV_N(BDIGIT, work, wn); +#else + rb_bug("wds is not enough: %" PRIdSIZE " for %" PRIdSIZE, wn, xn); +#endif } - tds = zds + n; MEMCPY(wds, zds + n, BDIGIT, xn); mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn); bary_add(zds + n, tn, zds + n, tn, wds, xn); } - yn -= r; n += r; } - BDIGITS_ZERO(zds+xn+yn0, zn - (xn+yn0)); + BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn)); if (work) ALLOCV_END(work); @@ -1996,7 +2011,7 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI } /* - * ref. http://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication + * ref. https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication * * x(b) = x0 * b^0 + x1 * b^1 + x2 * b^2 * y(b) = y0 * b^0 + y1 * b^1 + y2 * b^2 @@ -2277,10 +2292,23 @@ rb_big_mul_toom3(VALUE x, VALUE y) } #ifdef USE_GMP +static inline void +bdigits_to_mpz(mpz_t mp, const BDIGIT *digits, size_t len) +{ + const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; + mpz_import(mp, len, -1, sizeof(BDIGIT), 0, nails, digits); +} + +static inline void +bdigits_from_mpz(mpz_t mp, BDIGIT *digits, size_t *len) +{ + const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; + mpz_export(digits, len, -1, sizeof(BDIGIT), 0, nails, mp); +} + static void bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn) { - const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; mpz_t x, y, z; size_t count; @@ -2289,15 +2317,15 @@ bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT mpz_init(x); mpz_init(y); mpz_init(z); - mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds); + bdigits_to_mpz(x, xds, xn); if (xds == yds && xn == yn) { mpz_mul(z, x, x); } else { - mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds); + bdigits_to_mpz(y, yds, yn); mpz_mul(z, x, y); } - mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z); + bdigits_from_mpz(z, zds, &count); BDIGITS_ZERO(zds+count, zn-count); mpz_clear(x); mpz_clear(y); @@ -2336,9 +2364,9 @@ bary_sparse_p(const BDIGIT *ds, size_t n) { long c = 0; - if ( ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++; - if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++; - if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++; + if ( ds[2 * n / 5]) c++; + if (c <= 1 && ds[ n / 2]) c++; + if (c <= 1 && ds[3 * n / 5]) c++; return (c <= 1) ? 1 : 0; } @@ -2446,12 +2474,7 @@ bary_mul_karatsuba_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, { /* normal multiplication when x is small */ if (xn < KARATSUBA_MUL_DIGITS) { - normal: - if (xds == yds && xn == yn) - bary_sq_fast(zds, zn, xds, xn); - else - bary_short_mul(zds, zn, xds, xn, yds, yn); - return; + goto normal; } /* normal multiplication when x or y is a sparse bignum */ @@ -2469,6 +2492,15 @@ bary_mul_karatsuba_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, /* multiplication by karatsuba method */ bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn); + return; + + normal: + if (xds == yds && xn == yn) { + bary_sq_fast(zds, zn, xds, xn); + } + else { + bary_short_mul(zds, zn, xds, xn, yds, yn); + } } static void @@ -2748,7 +2780,6 @@ rb_big_divrem_normal(VALUE x, VALUE y) static void bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn) { - const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; mpz_t x, y, q, r; size_t count; @@ -2762,8 +2793,8 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd if (qds) mpz_init(q); if (rds) mpz_init(r); - mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds); - mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds); + bdigits_to_mpz(x, xds, xn); + bdigits_to_mpz(y, yds, yn); if (!rds) { mpz_fdiv_q(q, x, y); @@ -2779,13 +2810,13 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd mpz_clear(y); if (qds) { - mpz_export(qds, &count, -1, sizeof(BDIGIT), 0, nails, q); + bdigits_from_mpz(q, qds, &count); BDIGITS_ZERO(qds+count, qn-count); mpz_clear(q); } if (rds) { - mpz_export(rds, &count, -1, sizeof(BDIGIT), 0, nails, r); + bdigits_from_mpz(r, rds, &count); BDIGITS_ZERO(rds+count, rn-count); mpz_clear(r); } @@ -2884,29 +2915,8 @@ bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, s } -#define BIGNUM_DEBUG 0 -#if BIGNUM_DEBUG -#define ON_DEBUG(x) do { x; } while (0) -static void -dump_bignum(VALUE x) -{ - long i; - printf("%c0x0", BIGNUM_SIGN(x) ? '+' : '-'); - for (i = BIGNUM_LEN(x); i--; ) { - printf("_%0*"PRIxBDIGIT, SIZEOF_BDIGIT*2, BDIGITS(x)[i]); - } - printf(", len=%"PRIuSIZE, BIGNUM_LEN(x)); - puts(""); -} - -static VALUE -rb_big_dump(VALUE x) -{ - dump_bignum(x); - return x; -} -#else -#define ON_DEBUG(x) +#ifndef BIGNUM_DEBUG +# define BIGNUM_DEBUG (0+RUBY_DEBUG) #endif static int @@ -2944,7 +2954,7 @@ rb_cmpint(VALUE val, VALUE a, VALUE b) } #define BIGNUM_SET_LEN(b,l) \ - ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \ + (BIGNUM_EMBED_P(b) ? \ (void)(RBASIC(b)->flags = \ (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \ ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \ @@ -2954,19 +2964,19 @@ static void rb_big_realloc(VALUE big, size_t len) { BDIGIT *ds; - if (RBASIC(big)->flags & BIGNUM_EMBED_FLAG) { + if (BIGNUM_EMBED_P(big)) { if (BIGNUM_EMBED_LEN_MAX < len) { ds = ALLOC_N(BDIGIT, len); MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX); RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big); RBIGNUM(big)->as.heap.digits = ds; - RBASIC(big)->flags &= ~BIGNUM_EMBED_FLAG; + FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG); } } else { if (len <= BIGNUM_EMBED_LEN_MAX) { ds = RBIGNUM(big)->as.heap.digits; - RBASIC(big)->flags |= BIGNUM_EMBED_FLAG; + FL_SET_RAW(big, BIGNUM_EMBED_FLAG); BIGNUM_SET_LEN(big, len); (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary)); if (ds) { @@ -2996,18 +3006,19 @@ static VALUE bignew_1(VALUE klass, size_t len, int sign) { NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0)); - BIGNUM_SET_SIGN(big, sign); + VALUE bigv = (VALUE)big; + BIGNUM_SET_SIGN(bigv, sign); if (len <= BIGNUM_EMBED_LEN_MAX) { - RBASIC(big)->flags |= BIGNUM_EMBED_FLAG; - BIGNUM_SET_LEN(big, len); - (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary)); + FL_SET_RAW(bigv, BIGNUM_EMBED_FLAG); + BIGNUM_SET_LEN(bigv, len); + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, sizeof(big->as.ary)); } else { - RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len); - RBIGNUM(big)->as.heap.len = len; + big->as.heap.digits = ALLOC_N(BDIGIT, len); + big->as.heap.len = len; } - OBJ_FREEZE(big); - return (VALUE)big; + OBJ_FREEZE(bigv); + return bigv; } VALUE @@ -3384,7 +3395,7 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret) size_t numbytes; int nlz_bits_in_msbyte; size_t numwords; - size_t nlz_bits; + size_t nlz_bits = 0; if (word_numbits == 0) return (size_t)-1; @@ -3399,6 +3410,7 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret) numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0); assert(numwords0 == numwords); assert(nlz_bits0 == nlz_bits); + (void)numwords0; } #endif } @@ -3586,7 +3598,7 @@ rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t } /* - * Import an integer into a buffer. + * Import an integer from a buffer. * * [words] buffer to import. * [numwords] the size of given buffer as number of words. @@ -3683,10 +3695,10 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na if (u == 0) return LONG2FIX(0); if (0 < sign && POSFIXABLE(u)) - return LONG2FIX(u); + return LONG2FIX((long)u); if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 && NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u)) - return LONG2FIX(-(BDIGIT_DBL_SIGNED)u); + return LONG2FIX((long)-(BDIGIT_DBL_SIGNED)u); val = bignew((long)num_bdigits, 0 <= sign); MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits); } @@ -3741,12 +3753,12 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size return TRUE; } - if (badcheck && *str == '_') goto bad; + if (badcheck && *str == '_') return FALSE; while ((c = *str++) != 0) { if (c == '_') { if (nondigit) { - if (badcheck) goto bad; + if (badcheck) return FALSE; break; } nondigit = (char) c; @@ -3761,7 +3773,7 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size } if (len > 0 && !--len) break; } - if (badcheck && nondigit) goto bad; + if (badcheck && nondigit) return FALSE; if (badcheck && len) { str--; while (*str && ISSPACE(*str)) { @@ -3769,7 +3781,6 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size if (len > 0 && !--len) break; } if (len && *str) { - bad: return FALSE; } } @@ -3956,7 +3967,6 @@ str2big_gmp( size_t num_bdigits, int base) { - const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; char *buf, *p; const char *q; VALUE tmps; @@ -3979,7 +3989,7 @@ str2big_gmp( zn = num_bdigits; z = bignew(zn, sign); zds = BDIGITS(z); - mpz_export(BDIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz); + bdigits_from_mpz(mz, BDIGITS(z), &count); BDIGITS_ZERO(zds+count, zn-count); mpz_clear(mz); @@ -4066,10 +4076,7 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, } while (0) if (!str) { - bad: - if (endp) *endp = (char *)str; - if (ndigits) *ndigits = num_digits; - return z; + goto bad; } if (len && (flags & RB_INT_PARSE_SIGN)) { while (ISSPACE(*str)) ADV(1); @@ -4233,6 +4240,11 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, } return bignorm(z); + + bad: + if (endp) *endp = (char *)str; + if (ndigits) *ndigits = num_digits; + return z; } static VALUE @@ -4481,14 +4493,14 @@ rb_ll2big(LONG_LONG n) VALUE rb_ull2inum(unsigned LONG_LONG n) { - if (POSFIXABLE(n)) return LONG2FIX(n); + if (POSFIXABLE(n)) return LONG2FIX((long)n); return rb_ull2big(n); } VALUE rb_ll2inum(LONG_LONG n) { - if (FIXABLE(n)) return LONG2FIX(n); + if (FIXABLE(n)) return LONG2FIX((long)n); return rb_ll2big(n); } @@ -4652,12 +4664,6 @@ static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES]; static void power_cache_init(void) { - int i, j; - for (i = 0; i < 35; ++i) { - for (j = 0; j < MAX_BASE36_POWER_TABLE_ENTRIES; ++j) { - base36_power_cache[i][j] = Qnil; - } - } } static inline VALUE @@ -4680,8 +4686,8 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret) if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level) rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level); - if (NIL_P(base36_power_cache[base - 2][power_level])) { - VALUE power; + VALUE power = base36_power_cache[base - 2][power_level]; + if (!power) { size_t numdigits; if (power_level == 0) { int numdigits0; @@ -4701,7 +4707,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret) } if (numdigits_ret) *numdigits_ret = base36_numdigits_cache[base - 2][power_level]; - return base36_power_cache[base - 2][power_level]; + return power; } struct big2str_struct { @@ -5010,7 +5016,6 @@ rb_big2str_generic(VALUE x, int base) static VALUE big2str_gmp(VALUE x, int base) { - const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; mpz_t mx; size_t size; VALUE str; @@ -5018,7 +5023,7 @@ big2str_gmp(VALUE x, int base) size_t xn = BIGNUM_LEN(x); mpz_init(mx); - mpz_import(mx, xn, -1, sizeof(BDIGIT), 0, nails, xds); + bdigits_to_mpz(mx, xds, xn); size = mpz_sizeinbase(mx, base); @@ -5373,11 +5378,9 @@ rb_integer_float_cmp(VALUE x, VALUE y) #if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */ COMPILER_WARNING_PUSH -#ifdef __has_warning #if __has_warning("-Wimplicit-int-float-conversion") COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion) #endif -#endif static const double LONG_MAX_as_double = LONG_MAX; COMPILER_WARNING_POP #endif @@ -5388,7 +5391,7 @@ rb_integer_float_eq(VALUE x, VALUE y) double yd = RFLOAT_VALUE(y); double yi, yf; - if (isnan(yd) || isinf(yd)) + if (!isfinite(yd)) return Qfalse; yf = modf(yd, &yi); if (yf != 0) @@ -5396,18 +5399,14 @@ rb_integer_float_eq(VALUE x, VALUE y) if (FIXNUM_P(x)) { #if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */ double xd = (double)FIX2LONG(x); - if (xd != yd) - return Qfalse; - return Qtrue; + return RBOOL(xd == yd); #else long xn, yn; if (yi < LONG_MIN || LONG_MAX_as_double <= yi) return Qfalse; xn = FIX2LONG(x); yn = (long)yi; - if (xn != yn) - return Qfalse; - return Qtrue; + return RBOOL(xn == yn); #endif } y = rb_dbl2big(yi); @@ -5477,10 +5476,10 @@ big_op(VALUE x, VALUE y, enum big_op_t op) n = FIX2INT(rel); switch (op) { - case big_op_gt: return n > 0 ? Qtrue : Qfalse; - case big_op_ge: return n >= 0 ? Qtrue : Qfalse; - case big_op_lt: return n < 0 ? Qtrue : Qfalse; - case big_op_le: return n <= 0 ? Qtrue : Qfalse; + 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; } @@ -5515,7 +5514,7 @@ rb_big_le(VALUE x, VALUE y) * * Returns true only if obj has the same value * as big. Contrast this with Integer#eql?, which requires - * obj to be a Integer. + * obj to be an Integer. * * 68719476736 == 68719476736.0 #=> true */ @@ -5524,7 +5523,7 @@ VALUE rb_big_eq(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - return bignorm(x) == y ? Qtrue : Qfalse; + return RBOOL(bignorm(x) == y); } else if (RB_BIGNUM_TYPE_P(y)) { } @@ -5536,8 +5535,7 @@ rb_big_eq(VALUE x, VALUE y) } if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse; if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse; - if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse; - return Qtrue; + return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0); } VALUE @@ -5546,8 +5544,7 @@ rb_big_eql(VALUE x, VALUE y) if (!RB_BIGNUM_TYPE_P(y)) return Qfalse; if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse; if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse; - if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse; - return Qtrue; + return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0); } VALUE @@ -6266,7 +6263,7 @@ rb_big_pow(VALUE x, VALUE y) yy = FIX2LONG(y); if (yy < 0) { - x = rb_big_pow(x, INT2NUM(-yy)); + x = rb_big_pow(x, LONG2NUM(-yy)); if (RB_INTEGER_TYPE_P(x)) return rb_rational_raw(INT2FIX(1), x); else @@ -6691,7 +6688,6 @@ rb_big_aref(VALUE x, VALUE y) return INT2FIX(0); bigtrunc(y); if (BIGSIZE(y) > sizeof(size_t)) { - out_of_range: return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1); } #if SIZEOF_SIZE_T <= SIZEOF_LONG @@ -6709,7 +6705,8 @@ rb_big_aref(VALUE x, VALUE y) s2 = shift%BITSPERDIG; bit = (BDIGIT)1 << s2; - if (s1 >= BIGNUM_LEN(x)) goto out_of_range; + if (s1 >= BIGNUM_LEN(x)) + return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1); xds = BDIGITS(x); if (BIGNUM_POSITIVE_P(x)) @@ -6830,10 +6827,7 @@ rb_big_bit_length(VALUE big) VALUE rb_big_odd_p(VALUE num) { - if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) { - return Qtrue; - } - return Qfalse; + return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1); } VALUE @@ -6940,8 +6934,6 @@ rb_big_isqrt(VALUE n) bary_small_rshift(xds, xds, xn, 1, carry); tn = BIGNUM_LEN(t); } - rb_big_realloc(t, 0); - rb_gc_force_recycle(t); } RBASIC_SET_CLASS_RAW(x, rb_cInteger); return x; @@ -6951,18 +6943,17 @@ rb_big_isqrt(VALUE n) static void bary_powm_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, const BDIGIT *mds, size_t mn) { - const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT; mpz_t z, x, y, m; size_t count; mpz_init(x); mpz_init(y); mpz_init(m); mpz_init(z); - mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds); - mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds); - mpz_import(m, mn, -1, sizeof(BDIGIT), 0, nails, mds); + bdigits_to_mpz(x, xds, xn); + bdigits_to_mpz(y, yds, yn); + bdigits_to_mpz(m, mds, mn); mpz_powm(z, x, y, m); - mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z); + bdigits_from_mpz(z, zds, &count); BDIGITS_ZERO(zds+count, zn-count); mpz_clear(x); mpz_clear(y); @@ -7140,6 +7131,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num) long const half_val = (long)HALF_LONG_MSB; long const mm = FIX2LONG(m); if (!mm) rb_num_zerodiv(); + if (mm == 1) return INT2FIX(0); if (mm <= half_val) { return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg); } @@ -7149,6 +7141,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num) } else { if (rb_bigzero_p(m)) rb_num_zerodiv(); + if (bignorm(m) == INT2FIX(1)) return INT2FIX(0); return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg); } } @@ -7176,9 +7169,6 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num) void Init_Bignum(void) { -#ifndef RUBY_INTEGER_UNIFICATION - rb_cBignum = rb_cInteger; -#endif /* An obsolete class, use Integer */ rb_define_const(rb_cObject, "Bignum", rb_cInteger); rb_deprecate_constant(rb_cObject, "Bignum"); diff --git a/ruby/bin/bundle b/ruby/bin/bundle deleted file mode 100755 index 1a0b06b00..000000000 --- a/ruby/bin/bundle +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'bundler' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('bundler', 'bundle', version) -else -gem "bundler", version -load Gem.bin_path("bundler", "bundle", version) -end diff --git a/ruby/bin/bundler b/ruby/bin/bundler deleted file mode 100755 index e15eb39ed..000000000 --- a/ruby/bin/bundler +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'bundler' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('bundler', 'bundler', version) -else -gem "bundler", version -load Gem.bin_path("bundler", "bundler", version) -end diff --git a/ruby/bin/irb b/ruby/bin/irb deleted file mode 100755 index ae6d358c9..000000000 --- a/ruby/bin/irb +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'irb' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('irb', 'irb', version) -else -gem "irb", version -load Gem.bin_path("irb", "irb", version) -end diff --git a/ruby/bin/racc b/ruby/bin/racc deleted file mode 100755 index 3ddac532b..000000000 --- a/ruby/bin/racc +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'racc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -if ARGV.first - str = ARGV.first - str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding - if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then - version = $1 - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('racc', 'racc', version) -else -gem "racc", version -load Gem.bin_path("racc", "racc", version) -end diff --git a/ruby/bin/racc2y b/ruby/bin/racc2y deleted file mode 100755 index a1e435263..000000000 --- a/ruby/bin/racc2y +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'racc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -if ARGV.first - str = ARGV.first - str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding - if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then - version = $1 - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('racc', 'racc2y', version) -else -gem "racc", version -load Gem.bin_path("racc", "racc2y", version) -end diff --git a/ruby/bin/rdoc b/ruby/bin/rdoc deleted file mode 100755 index 8fa948cdd..000000000 --- a/ruby/bin/rdoc +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'rdoc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('rdoc', 'rdoc', version) -else -gem "rdoc", version -load Gem.bin_path("rdoc", "rdoc", version) -end diff --git a/ruby/bin/ri b/ruby/bin/ri deleted file mode 100755 index 0cc2f73bb..000000000 --- a/ruby/bin/ri +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'rdoc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('rdoc', 'ri', version) -else -gem "rdoc", version -load Gem.bin_path("rdoc", "ri", version) -end diff --git a/ruby/bin/y2racc b/ruby/bin/y2racc deleted file mode 100755 index 023615f36..000000000 --- a/ruby/bin/y2racc +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by RubyGems. -# -# The application 'racc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -version = ">= 0.a" - -if ARGV.first - str = ARGV.first - str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding - if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then - version = $1 - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('racc', 'y2racc', version) -else -gem "racc", version -load Gem.bin_path("racc", "y2racc", version) -end diff --git a/ruby/bootstraptest/pending.rb b/ruby/bootstraptest/pending.rb index 0959bfa2b..2c4b85a41 100644 --- a/ruby/bootstraptest/pending.rb +++ b/ruby/bootstraptest/pending.rb @@ -1,19 +1,3 @@ -assert_equal 'A', %q{ - class A - @@a = 'A' - def a=(x) - @@a = x - end - def a - @@a - end - end - - B = A.dup - B.new.a = 'B' - A.new.a -}, '[ruby-core:17019]' - assert_equal 'ok', %q{ def m lambda{ @@ -31,13 +15,6 @@ def m end } -assert_normal_exit %q{ - r = Range.allocate - def r.<=>(o) true end - r.instance_eval { initialize r, r } - r.inspect -} - # This randomly fails on mswin. assert_equal %q{[]}, %q{ Thread.new{sleep}.backtrace diff --git a/ruby/bootstraptest/runner.rb b/ruby/bootstraptest/runner.rb index 56b4b1223..2cd91ffd0 100755 --- a/ruby/bootstraptest/runner.rb +++ b/ruby/bootstraptest/runner.rb @@ -261,6 +261,14 @@ def show_progress(message = '') $stderr.print 'E' $stderr.puts if @verbose error err.message, message +ensure + begin + check_coredump + rescue CoreDumpError => err + $stderr.print 'E' + $stderr.puts if @verbose + error err.message, message + end end def show_limit(testsrc, opt = '', **argh) @@ -275,7 +283,6 @@ def show_limit(testsrc, opt = '', **argh) def assert_check(testsrc, message = '', opt = '', **argh) show_progress(message) { result = get_result_string(testsrc, opt, **argh) - check_coredump yield(result) } end @@ -376,8 +383,8 @@ def assert_normal_exit(testsrc, *rest, timeout: nil, **opt) end def assert_finish(timeout_seconds, testsrc, message = '') - if RubyVM.const_defined? :MJIT - timeout_seconds *= 3 if RubyVM::MJIT.enabled? # for --jit-wait + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait + timeout_seconds *= 3 end newtest show_progress(message) { @@ -453,7 +460,6 @@ def get_result_string(src, opt = '', **argh) `#{@ruby} -W0 #{opt} #{filename}` ensure raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"] - raise CoreDumpError, "core dumped" if $? and $?.coredump? end else eval(src).to_s @@ -513,7 +519,21 @@ def in_temporary_working_directory(dir) end def cleanup_coredump - FileUtils.rm_f 'core' + if File.file?('core') + require 'time' + Dir.glob('/tmp/bootstraptest-core.*').each do |f| + if Time.now - File.mtime(f) > 7 * 24 * 60 * 60 # 7 days + warn "Deleting an old core file: #{f}" + FileUtils.rm(f) + end + end + core_path = "/tmp/bootstraptest-core.#{Time.now.utc.iso8601}" + warn "A core file is found. Saving it at: #{core_path.dump}" + FileUtils.mv('core', core_path) + cmd = ['gdb', @ruby, '-c', core_path, '-ex', 'bt', '-batch'] + p cmd # debugging why it's not working + system(*cmd) + end FileUtils.rm_f Dir.glob('core.*') FileUtils.rm_f @ruby+'.stackdump' if @ruby end diff --git a/ruby/bootstraptest/test_eval.rb b/ruby/bootstraptest/test_eval.rb index fa04323b7..a9f389c67 100644 --- a/ruby/bootstraptest/test_eval.rb +++ b/ruby/bootstraptest/test_eval.rb @@ -116,6 +116,33 @@ class Integer Const } } +assert_equal %q{1}, %q{ + class TrueClass + Const = 1 + end + true.instance_eval %{ + Const + } +} +assert_equal %q{[:Const]}, %q{ + mod = Module.new + mod.instance_eval %{ + Const = 1 + } + raise if defined?(Module::Const) + mod.singleton_class.constants +} +assert_equal %q{can't define singleton}, %q{ + begin + 123.instance_eval %{ + Const = 1 + } + "bad" + rescue TypeError => e + raise "bad" if defined?(Integer::Const) + e.message + end +} assert_equal %q{top}, %q{ Const = :top class C @@ -191,7 +218,7 @@ def initialize &b %w[break next redo].each do |keyword| assert_match %r"Can't escape from eval with #{keyword}\b", %{ - STDERR.reopen(STDOUT) + $stderr = STDOUT begin eval "0 rescue #{keyword}" rescue SyntaxError => e @@ -201,7 +228,7 @@ def initialize &b end assert_normal_exit %q{ - STDERR.reopen(STDOUT) + $stderr = STDOUT class Foo def self.add_method class_eval("def some-bad-name; puts 'hello' unless @some_variable.some_function(''); end") @@ -250,7 +277,9 @@ def hoge; end assert_equal 'ok', %q{ begin - 12.instance_eval { @@a } + class A + 12.instance_eval { @@a } + end rescue NameError :ok end @@ -258,7 +287,9 @@ def hoge; end assert_equal 'ok', %q{ begin - 12.instance_exec { @@a } + class A + 12.instance_exec { @@a } + end rescue NameError :ok end diff --git a/ruby/bootstraptest/test_fiber.rb b/ruby/bootstraptest/test_fiber.rb index 35e1bf685..2614dd13b 100644 --- a/ruby/bootstraptest/test_fiber.rb +++ b/ruby/bootstraptest/test_fiber.rb @@ -19,12 +19,12 @@ } assert_equal %q{ok}, %q{ - 10_000.times.collect{Fiber.new{}} + 100.times.collect{Fiber.new{}} :ok } assert_equal %q{ok}, %q{ - fibers = 100.times.collect{Fiber.new{Fiber.yield}} + fibers = 1000.times.collect{Fiber.new{Fiber.yield}} fibers.each(&:resume) fibers.each(&:resume) :ok diff --git a/ruby/bootstraptest/test_flow.rb b/ruby/bootstraptest/test_flow.rb index 9da6d45cb..35f19db58 100644 --- a/ruby/bootstraptest/test_flow.rb +++ b/ruby/bootstraptest/test_flow.rb @@ -534,11 +534,11 @@ def each ['[ruby-core:39125]', %q{ class Bug5234 include Enumerable - def each + def each(&block) begin yield :foo ensure - proc + proc(&block) end end end @@ -547,11 +547,11 @@ def each ['[ruby-dev:45656]', %q{ class Bug6460 include Enumerable - def each + def each(&block) begin yield :foo ensure - 1.times { Proc.new } + 1.times { Proc.new(&block) } end end end diff --git a/ruby/bootstraptest/test_insns.rb b/ruby/bootstraptest/test_insns.rb index 1269d7d01..91fba9b01 100644 --- a/ruby/bootstraptest/test_insns.rb +++ b/ruby/bootstraptest/test_insns.rb @@ -64,8 +64,8 @@ def m&b [ 'setinstancevariable', %q{ @x = true }, ], [ 'getinstancevariable', %q{ @x = true; @x }, ], - [ 'setclassvariable', %q{ @@x = true }, ], - [ 'getclassvariable', %q{ @@x = true; @@x }, ], + [ 'setclassvariable', %q{ class A; @@x = true; end }, ], + [ 'getclassvariable', %q{ class A; @@x = true; @@x end }, ], [ 'setconstant', %q{ X = true }, ], [ 'setconstant', %q{ Object::X = true }, ], @@ -86,11 +86,8 @@ def m&b [ 'putobject', %q{ /(?x)/ =~ "x"; x == "x" }, ], [ 'putspecialobject', %q{ {//=>true}[//] }, ], - [ 'putiseq', %q{ -> { true }.() }, ], [ 'putstring', %q{ "true" }, ], [ 'tostring / concatstrings', %q{ "#{true}" }, ], - [ 'freezestring', %q{ "#{true}" }, fsl, ], - [ 'freezestring', %q{ "#{true}" }, '-d', fsl, ], [ 'toregexp', %q{ /#{true}/ =~ "true" && $~ }, ], [ 'intern', %q{ :"#{true}" }, ], @@ -123,6 +120,7 @@ class X; def to_a; ['u']; end; end [ 'dup', %q{ x = y = true; x }, ], [ 'dupn', %q{ Object::X ||= true }, ], [ 'reverse', %q{ q, (w, e), r = 1, [2, 3], 4; e == 3 }, ], + [ 'swap', %q{ !!defined?([[]]) }, ], [ 'swap', <<-'},', ], # { x = [[false, true]] for i, j in x # here @@ -387,14 +385,13 @@ class X; def x; {}; end; end [ 'opt_empty_p', %q{ ''.empty? }, ], [ 'opt_empty_p', %q{ [].empty? }, ], [ 'opt_empty_p', %q{ {}.empty? }, ], - [ 'opt_empty_p', %q{ Queue.new.empty? }, ], + [ 'opt_empty_p', %q{ Thread::Queue.new.empty? }, ], [ 'opt_succ', %q{ 1.succ == 2 }, ], if defined? $FIXNUM_MAX then [ 'opt_succ',%Q{ #{ $FIXNUM_MAX }.succ == #{ $FIXNUM_MAX + 1 } }, ] end, [ 'opt_succ', %q{ '1'.succ == '2' }, ], - [ 'opt_succ', %q{ x = Time.at(0); x.succ == Time.at(1) }, ], [ 'opt_not', %q{ ! false }, ], [ 'opt_neq', <<-'},', ], # { @@ -412,8 +409,6 @@ class Regexp; def =~ other; true; end; end class String; def =~ other; true; end; end 'true' =~ /true/ }, - - [ 'opt_call_c_function', 'Struct.new(:x).new.x = true', ], ] # normal path @@ -438,3 +433,8 @@ class String; def =~ other; true; end; end assert_equal 'true', progn, 'trace_' + insn, *a end } + +assert_normal_exit("#{<<-"begin;"}\n#{<<-'end;'}") +begin; + RubyVM::InstructionSequence.compile("", debug_level: 5) +end; diff --git a/ruby/bootstraptest/test_jump.rb b/ruby/bootstraptest/test_jump.rb index 794491586..d07c47a56 100644 --- a/ruby/bootstraptest/test_jump.rb +++ b/ruby/bootstraptest/test_jump.rb @@ -147,7 +147,7 @@ def m } } assert_match %r{Invalid retry}, %q{ -STDERR.reopen(STDOUT) +$stderr = STDOUT begin eval %q{ 1.times{ @@ -296,14 +296,19 @@ class << self s.return_eigenclass == class << s; self; end }, '[ruby-core:21379]' -assert_equal "true", %q{ - class Object - def yield_eigenclass - class << self - yield self +assert_match %r{Invalid yield}, %q{ +$stderr = STDOUT +begin + eval %q{ + class Object + def yield_eigenclass + class << self + yield self + end end end - end - s = "foo" - s.yield_eigenclass {|c| c == class << s; self; end } -}, '[ruby-dev:40975]' + } +rescue SyntaxError => e + e.message +end +} diff --git a/ruby/bootstraptest/test_proc.rb b/ruby/bootstraptest/test_proc.rb index 1e384411d..637603243 100644 --- a/ruby/bootstraptest/test_proc.rb +++ b/ruby/bootstraptest/test_proc.rb @@ -224,19 +224,6 @@ def m(&b) Proc.new{|a, *b| [a, b]}.call(1, 2, 3), ] } -assert_equal %q{1}, %q{ - pr = proc{ - $SAFE - } - $SAFE = 1 - pr.call -} -assert_equal %q{[1, 1]}, %q{ - pr = proc{ - $SAFE += 1 - } - [pr.call, $SAFE] -} assert_equal %q{1}, %q{ def m(&b) b @@ -380,8 +367,8 @@ def m assert_equal 'ok', %q{ class Foo - def call_it - p = Proc.new + def call_it(&block) + p = Proc.new(&block) p.call end end diff --git a/ruby/bootstraptest/test_ractor.rb b/ruby/bootstraptest/test_ractor.rb new file mode 100644 index 000000000..b29db7ab0 --- /dev/null +++ b/ruby/bootstraptest/test_ractor.rb @@ -0,0 +1,1582 @@ +# Ractor.current returns a current ractor +assert_equal 'Ractor', %q{ + Ractor.current.class +} + +# Ractor.new returns new Ractor +assert_equal 'Ractor', %q{ + Ractor.new{}.class +} + +# Ractor.allocate is not supported +assert_equal "[:ok, :ok]", %q{ + rs = [] + begin + Ractor.allocate + rescue => e + rs << :ok if e.message == 'allocator undefined for Ractor' + end + + begin + Ractor.new{}.dup + rescue + rs << :ok if e.message == 'allocator undefined for Ractor' + end + + rs +} + +# A Ractor can have a name +assert_equal 'test-name', %q{ + r = Ractor.new name: 'test-name' do + end + r.name +} + +# If Ractor doesn't have a name, Ractor#name returns nil. +assert_equal 'nil', %q{ + r = Ractor.new do + end + r.name.inspect +} + +# Raises exceptions if initialize with an invalid name +assert_equal 'ok', %q{ + begin + r = Ractor.new(name: [{}]) {} + rescue TypeError => e + 'ok' + end +} + +# Ractor.new must call with a block +assert_equal "must be called with a block", %q{ + begin + Ractor.new + rescue ArgumentError => e + e.message + end +} + +# Ractor#inspect +# Return only id and status for main ractor +assert_equal "#", %q{ + Ractor.current.inspect +} + +# Return id, loc, and status for no-name ractor +assert_match /^#$/, %q{ + r = Ractor.new { '' } + r.take + sleep 0.1 until r.inspect =~ /terminated/ + r.inspect +} + +# Return id, name, loc, and status for named ractor +assert_match /^#$/, %q{ + r = Ractor.new(name: 'Test Ractor') { '' } + r.take + sleep 0.1 until r.inspect =~ /terminated/ + r.inspect +} + +# A return value of a Ractor block will be a message from the Ractor. +assert_equal 'ok', %q{ + # join + r = Ractor.new do + 'ok' + end + r.take +} + +# Passed arguments to Ractor.new will be a block parameter +# The values are passed with Ractor-communication pass. +assert_equal 'ok', %q{ + # ping-pong with arg + r = Ractor.new 'ok' do |msg| + msg + end + r.take +} + +# Pass multiple arguments to Ractor.new +assert_equal 'ok', %q{ + # ping-pong with two args + r = Ractor.new 'ping', 'pong' do |msg, msg2| + [msg, msg2] + end + 'ok' if r.take == ['ping', 'pong'] +} + +# Ractor#send passes an object with copy to a Ractor +# and Ractor.receive in the Ractor block can receive the passed value. +assert_equal 'ok', %q{ + r = Ractor.new do + msg = Ractor.receive + end + r.send 'ok' + r.take +} + +# 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 +} + +# 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 + 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 # +} + +# dtoa race condition +assert_equal '[:ok, :ok, :ok]', %q{ + n = 3 + n.times.map{ + Ractor.new{ + 10_000.times{ rand.to_s } + :ok + } + }.map(&:take) +} + +# Ractor.make_shareable issue for locals in proc [Bug #18023] +assert_equal '[:a, :b, :c, :d, :e]', %q{ + v1, v2, v3, v4, v5 = :a, :b, :c, :d, :e + closure = Ractor.current.instance_eval{ Proc.new { [v1, v2, v3, v4, v5] } } + + Ractor.make_shareable(closure).call +} + +# Ractor.make_shareable issue for locals in proc [Bug #18023] +assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{ + a = :a + closure = Ractor.current.instance_eval do + -> { + b, c, d = :b, :c, :d + -> { + e, f, g = :e, :f, :g + -> { [a, b, c, d, e, f, g] } + }.call + }.call + end + + 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' + # 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] +assert_equal 'ok', %q{ + # select 1 + r1 = Ractor.new{'r1'} + r, obj = Ractor.select(r1) + 'ok' if r == r1 and obj == 'r1' +} + +# Ractor.select from two ractors. +assert_equal '["r1", "r2"]', %q{ + # select 2 + r1 = Ractor.new{'r1'} + r2 = Ractor.new{'r2'} + rs = [r1, r2] + as = [] + r, obj = Ractor.select(*rs) + rs.delete(r) + as << obj + r, obj = Ractor.select(*rs) + as << obj + as.sort #=> ["r1", "r2"] +} + +# Ractor.select from multiple ractors. +assert_equal 30.times.map { 'ok' }.to_s, %q{ + def test n + rs = (1..n).map do |i| + Ractor.new(i) do |i| + "r#{i}" + end + end + as = [] + all_rs = rs.dup + + n.times{ + r, obj = Ractor.select(*rs) + as << [r, obj] + rs.delete(r) + } + + if as.map{|r, o| r.object_id}.sort == all_rs.map{|r| r.object_id}.sort && + as.map{|r, o| o}.sort == (1..n).map{|i| "r#{i}"}.sort + 'ok' + else + 'ng' + end + end + + 30.times.map{|i| + test i + } +} unless ENV['RUN_OPTS'] =~ /--jit-min-calls=5/ || # This always fails with --jit-wait --jit-min-calls=5 + (ENV.key?('TRAVIS') && ENV['TRAVIS_CPU_ARCH'] == 'arm64') # https://bugs.ruby-lang.org/issues/17878 + +# Exception for empty select +assert_match /specify at least one ractor/, %q{ + begin + Ractor.select + rescue ArgumentError => e + e.message + 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 + sleep 0.1 until r.inspect =~ /terminated/ + + begin + r.send(1) + rescue Ractor::ClosedError + 'ok' + else + 'ng' + 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] +assert_equal 'err', %q{ + Ractor.new{ + t = Thread.current + begin + Thread.new{ t.raise "err" }.join + rescue => e + e.message + end + }.take +} + +# Killed Ractor's thread yields nil +assert_equal 'nil', %q{ + Ractor.new{ + t = Thread.current + Thread.new{ t.kill }.join + }.take.inspect #=> nil +} + +# Ractor.yield raises Ractor::ClosedError when outgoing port is closed. +assert_equal 'ok', %q{ + r = Ractor.new Ractor.current do |main| + 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 + + begin + r.send(1) + rescue Ractor::ClosedError + 'ok' + else + 'ng' + 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 +} + +# a ractor with closed outgoing port should terminate +assert_equal 'ok', %q{ + Ractor.new do + close_outgoing + 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 + 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 +} + +# 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 = [] + take = [] + yielded = [] + until rs.empty? + r, v = Ractor.select(CR, *rs, yield_value: 'yield') + case r + when :receive + received << v + when :yield + yielded << v + else + take << v + rs.delete r + end + end + [received.all?('sendyield'), yielded.all?(nil), take.all?('take')] +} + +# 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 + end + + RN = 10 + RN.times.map{|i| + Ractor.new pipe, i do |pipe, i| + pipe << i + end + } + RN.times.map{ + pipe.take + }.sort +} + +# 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 + end + begin + r.take + rescue Ractor::RemoteError => e + [e.cause.class, #=> RuntimeError + e.cause.message, #=> 'ok' + e.ractor == r] #=> true + end +} + +# threads in a ractor will killed +assert_equal '{:ok=>3}', %q{ + Ractor.new Ractor.current do |main| + q = Thread::Queue.new + Thread.new do + q << true + loop{} + ensure + main << :ok + end + + Thread.new do + q << true + while true + end + ensure + main << :ok + end + + Thread.new do + q << true + sleep 1 + ensure + main << :ok + end + + # wait for the start of all threads + 3.times{q.pop} + end + + 3.times.map{Ractor.receive}.tally +} + +# unshareable object are copied +assert_equal 'false', %q{ + obj = 'str'.dup + r = Ractor.new obj do |msg| + msg.object_id + end + + obj.object_id == r.take +} + +# To copy the object, now Marshal#dump is used +assert_equal "allocator undefined for Thread", %q{ + obj = Thread.new{} + begin + r = Ractor.new obj do |msg| + msg + end + rescue TypeError => e + e.message #=> no _dump_data is defined for class Thread + else + 'ng' + end +} + +# send shareable and unshareable objects +assert_equal "ok", %q{ + echo_ractor = Ractor.new do + loop do + v = Ractor.receive + Ractor.yield v + end + end + + class C; end + module M; end + S = Struct.new(:a, :b, :c, :d) + + shareable_objects = [ + true, + false, + nil, + 1, + 1.1, # Float + 1+2r, # Rational + 3+4i, # Complex + 2**128, # Bignum + :sym, # Symbol + 'xyzzy'.to_sym, # dynamic symbol + 'frozen'.freeze, # frozen String + /regexp/, # regexp literal + /reg{true}exp/.freeze, # frozen dregexp + [1, 2].freeze, # frozen Array which only refers to shareable + {a: 1}.freeze, # frozen Hash which only refers to shareable + [{a: 1}.freeze, 'str'.freeze].freeze, # nested frozen container + S.new(1, 2).freeze, # frozen Struct + S.new(1, 2, 3, 4).freeze, # frozen Struct + (1..2), # Range on Struct + (1..), # Range on Struct + (..1), # Range on Struct + C, # class + M, # module + Ractor.current, # Ractor + ] + + unshareable_objects = [ + 'mutable str'.dup, + [:array], + {hash: true}, + S.new(1, 2), + S.new(1, 2, 3, 4), + S.new("a", 2).freeze, # frozen, but refers to an unshareable object + ] + + results = [] + + shareable_objects.map{|o| + echo_ractor << o + o2 = echo_ractor.take + results << "#{o} is copied" unless o.object_id == o2.object_id + } + + unshareable_objects.map{|o| + echo_ractor << o + o2 = echo_ractor.take + results << "#{o.inspect} is not copied" if o.object_id == o2.object_id + } + + if results.empty? + :ok + else + results.inspect + end +} + +# frozen Objects are shareable +assert_equal [false, true, false].inspect, %q{ + class C + def initialize freeze + @a = 1 + @b = :sym + @c = 'frozen_str' + @c.freeze if freeze + @d = true + end + end + + def check obj1 + obj2 = Ractor.new obj1 do |obj| + obj + end.take + + obj1.object_id == obj2.object_id + end + + results = [] + results << check(C.new(true)) # false + results << check(C.new(true).freeze) # true + results << check(C.new(false).freeze) # false +} + +# move example2: String +# touching moved object causes an error +assert_equal 'hello world', %q{ + # move + r = Ractor.new do + obj = Ractor.receive + obj << ' world' + end + + str = 'hello' + r.send str, move: true + modified = r.take + + begin + str << ' exception' # raise Ractor::MovedError + rescue Ractor::MovedError + modified #=> 'hello world' + else + raise 'unreachable' + end +} + +# move example2: Array +assert_equal '[0, 1]', %q{ + r = Ractor.new do + ary = Ractor.receive + ary << 1 + end + + a1 = [0] + r.send a1, move: true + a2 = r.take + begin + a1 << 2 # raise Ractor::MovedError + rescue Ractor::MovedError + a2.inspect + 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{ + r = Ractor.new do + obj = Thread.new{} + Ractor.yield obj + rescue => e + e.message + end + r.take +} + +# Access to global-variables are prohibited +assert_equal 'can not access global variables $gv from non-main Ractors', %q{ + $gv = 1 + r = Ractor.new do + $gv + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# Access to global-variables are prohibited +assert_equal 'can not access global variables $gv from non-main Ractors', %q{ + r = Ractor.new do + $gv = 1 + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# $stdin,out,err is Ractor local, but shared fds +assert_equal 'ok', %q{ + r = Ractor.new do + [$stdin, $stdout, $stderr].map{|io| + [io.object_id, io.fileno] + } + end + + [$stdin, $stdout, $stderr].zip(r.take){|io, (oid, fno)| + raise "should not be different object" if io.object_id == oid + raise "fd should be same" unless io.fileno == fno + } + 'ok' +} + +# $stdin,out,err belong to Ractor +assert_equal 'ok', %q{ + r = Ractor.new do + $stdin.itself + $stdout.itself + $stderr.itself + 'ok' + end + + r.take +} + +# $DEBUG, $VERBOSE are Ractor local +assert_equal 'true', %q{ + $DEBUG = true + $VERBOSE = true + + def ractor_local_globals + /a(b)(c)d/ =~ 'abcd' # for $~ + `echo foo` unless /solaris/ =~ RUBY_PLATFORM + + { + # ractor-local (derived from created ractor): debug + '$DEBUG' => $DEBUG, + '$-d' => $-d, + + # ractor-local (derived from created ractor): verbose + '$VERBOSE' => $VERBOSE, + '$-w' => $-w, + '$-W' => $-W, + '$-v' => $-v, + + # process-local (readonly): other commandline parameters + '$-p' => $-p, + '$-l' => $-l, + '$-a' => $-a, + + # process-local (readonly): getpid + '$$' => $$, + + # thread local: process result + '$?' => $?, + + # scope local: match + '$~' => $~.inspect, + '$&' => $&, + '$`' => $`, + '$\'' => $', + '$+' => $+, + '$1' => $1, + + # scope local: last line + '$_' => $_, + + # scope local: last backtrace + '$@' => $@, + '$!' => $!, + + # ractor local: stdin, out, err + '$stdin' => $stdin.inspect, + '$stdout' => $stdout.inspect, + '$stderr' => $stderr.inspect, + } + end + + h = Ractor.new do + ractor_local_globals + end.take + ractor_local_globals == h #=> true +} + +# selfs are different objects +assert_equal 'false', %q{ + r = Ractor.new do + self.object_id + end + r.take == self.object_id #=> false +} + +# self is a Ractor instance +assert_equal 'true', %q{ + r = Ractor.new do + self.object_id + end + r.object_id == r.take #=> true +} + +# given block Proc will be isolated, so can not access outer variables. +assert_equal 'ArgumentError', %q{ + begin + a = true + r = Ractor.new do + a + end + rescue => e + e.class + end +} + +# 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{ + class C + @iv = 'str' + end + + r = Ractor.new do + class C + p @iv + end + end + + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# 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{ + shared = Ractor.new{} + shared.instance_variable_set(:@iv, 'str') + + r = Ractor.new shared do |shared| + p shared.instance_variable_get(:@iv) + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# ivar in shareable-objects are not allowed to access from non-main Ractor, by @iv (get) +assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{ + class Ractor + def setup + @foo = '' + end + + def foo + @foo + end + end + + shared = Ractor.new{} + shared.setup + + r = Ractor.new shared do |shared| + p shared.foo + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# ivar in shareable-objects are not allowed to access from non-main Ractor, by @iv (set) +assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{ + class Ractor + def setup + @foo = '' + end + end + + shared = Ractor.new{} + + r = Ractor.new shared do |shared| + p shared.setup + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# But a shareable object is frozen, it is allowed to access ivars from non-main Ractor +assert_equal '11', %q{ + [Object.new, [], ].map{|obj| + obj.instance_variable_set('@a', 1) + Ractor.make_shareable obj = obj.freeze + + Ractor.new obj do |obj| + obj.instance_variable_get('@a') + end.take.to_s + }.join +} + +# and instance variables of classes/modules are accessible if they refer shareable objects +assert_equal '333', %q{ + class C + @int = 1 + @str = '-1000'.dup + @fstr = '100'.freeze + + def self.int = @int + def self.str = @str + def self.fstr = @fstr + end + + module M + @int = 2 + @str = '-2000'.dup + @fstr = '200'.freeze + + def self.int = @int + def self.str = @str + def self.fstr = @fstr + end + + a = Ractor.new{ C.int }.take + b = Ractor.new do + C.str.to_i + rescue Ractor::IsolationError + 10 + end.take + c = Ractor.new do + C.fstr.to_i + end.take + + d = Ractor.new{ M.int }.take + e = Ractor.new do + M.str.to_i + rescue Ractor::IsolationError + 20 + end.take + f = Ractor.new do + M.fstr.to_i + end.take + + + # 1 + 10 + 100 + 2 + 20 + 200 + a + b + c + d + e + f +} + +# 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 + @@cv = 'str' + end + + r = Ractor.new do + class C + p @@cv + end + end + + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# also cached 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 + @@cv = 'str' + def self.cv + @@cv + end + end + + C.cv # cache + + r = Ractor.new do + C.cv + end + + begin + r.take + 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{ + class C + CONST = 'str' + end + r = Ractor.new do + C::CONST + end + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# 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{ + STR = "hello" + def str; STR; end + s = str() # fill const cache + begin + Ractor.new{ str() }.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# 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{ + class C + end + r = Ractor.new do + C::CONST = 'str' + end + begin + r.take + rescue Ractor::RemoteError => e + e.cause.message + end +} + +# 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 + rescue => e + e.cause.message + end +} + +# Immutable Array and Hash are shareable, so it can be shared with constants +assert_equal '[1000, 3]', %q{ + A = Array.new(1000).freeze # [nil, ...] + H = {a: 1, b: 2, c: 3}.freeze + + Ractor.new{ [A.size, H.size] }.take +} + +# Ractor.count +assert_equal '[1, 4, 3, 2, 1]', %q{ + counts = [] + counts << Ractor.count + ractors = (1..3).map { Ractor.new { Ractor.receive } } + counts << Ractor.count + + ractors[0].send('End 0').take + sleep 0.1 until ractors[0].inspect =~ /terminated/ + counts << Ractor.count + + ractors[1].send('End 1').take + sleep 0.1 until ractors[1].inspect =~ /terminated/ + counts << Ractor.count + + ractors[2].send('End 2').take + sleep 0.1 until ractors[2].inspect =~ /terminated/ + counts << Ractor.count + + counts.inspect +} + +# ObjectSpace.each_object can not handle unshareable objects with Ractors +assert_equal '0', %q{ + Ractor.new{ + n = 0 + ObjectSpace.each_object{|o| n += 1 unless Ractor.shareable?(o)} + n + }.take +} + +# ObjectSpace._id2ref can not handle unshareable objects with Ractors +assert_equal 'ok', %q{ + s = 'hello' + + Ractor.new s.object_id do |id ;s| + begin + s = ObjectSpace._id2ref(id) + rescue => e + :ok + end + end.take +} + +# Ractor.make_shareable(obj) +assert_equal 'true', %q{ + class C + def initialize + @a = 'foo' + @b = 'bar' + end + + def freeze + @c = [:freeze_called] + super + end + + attr_reader :a, :b, :c + end + S = Struct.new(:s1, :s2) + str = "hello" + str.instance_variable_set("@iv", "hello") + /a/ =~ 'a' + m = $~ + class N < Numeric + def /(other) + 1 + end + end + ary = []; ary << ary + + a = [[1, ['2', '3']], + {Object.new => "hello"}, + C.new, + S.new("x", "y"), + ("a".."b"), + str, + ary, # cycle + /regexp/, + /#{'r'.upcase}/, + m, + Complex(N.new,0), + Rational(N.new,0), + true, + false, + nil, + 1, 1.2, 1+3r, 1+4i, # Numeric + ] + Ractor.make_shareable(a) + + # check all frozen + a.each{|o| + raise o.inspect unless o.frozen? + + case o + when C + raise o.a.inspect unless o.a.frozen? + raise o.b.inspect unless o.b.frozen? + raise o.c.inspect unless o.c.frozen? && o.c == [:freeze_called] + when Rational + raise o.numerator.inspect unless o.numerator.frozen? + when Complex + raise o.real.inspect unless o.real.frozen? + when Array + if o[0] == 1 + raise o[1][1].inspect unless o[1][1].frozen? + end + when Hash + o.each{|k, v| + raise k.inspect unless k.frozen? + raise v.inspect unless v.frozen? + } + end + } + + Ractor.shareable?(a) +} + +# Ractor.make_shareable(obj) doesn't freeze shareable objects +assert_equal 'true', %q{ + r = Ractor.new{} + Ractor.make_shareable(a = [r]) + [a.frozen?, a[0].frozen?] == [true, false] +} + +# Ractor.make_shareable(a_proc) makes a proc shareable. +assert_equal 'true', %q{ + a = [1, [2, 3], {a: "4"}] + + pr = Ractor.current.instance_eval do + Proc.new do + a + end + end + + Ractor.make_shareable(a) # referred value should be shareable + Ractor.make_shareable(pr) + Ractor.shareable?(pr) +} + +# Ractor.shareable?(recursive_objects) +assert_equal '[false, false]', %q{ + y = [] + x = [y, {}].freeze + y << x + y.freeze + [Ractor.shareable?(x), Ractor.shareable?(y)] +} + +# Ractor.make_shareable(recursive_objects) +assert_equal '[:ok, false, false]', %q{ + o = Object.new + def o.freeze; raise; end + y = [] + x = [y, o].freeze + y << x + y.freeze + [(Ractor.make_shareable(x) rescue :ok), Ractor.shareable?(x), Ractor.shareable?(y)] +} + +# Ractor.make_shareable with Class/Module +assert_equal '[C, M]', %q{ + class C; end + module M; end + + Ractor.make_shareable(ary = [C, M]) +} + +# define_method() can invoke different Ractor's proc if the proc is shareable. +assert_equal '1', %q{ + class C + a = 1 + define_method "foo", Ractor.make_shareable(Proc.new{ a }) + a = 2 + end + + Ractor.new{ C.new.foo }.take +} + +# Ractor.make_shareable(a_proc) makes a proc shareable. +assert_equal 'can not make a Proc shareable because it accesses outer variables (a).', %q{ + a = b = nil + pr = Ractor.current.instance_eval do + Proc.new do + c = b # assign to a is okay because c is block local variable + # reading b is okay + a = b # assign to a is not allowed #=> Ractor::Error + end + end + + begin + Ractor.make_shareable(pr) + rescue => e + e.message + end +} + +# Ractor.make_shareable(obj, copy: true) makes copied shareable object. +assert_equal '[false, false, true, true]', %q{ + r = [] + o1 = [1, 2, ["3"]] + + o2 = Ractor.make_shareable(o1, copy: true) + r << Ractor.shareable?(o1) # false + r << (o1.object_id == o2.object_id) # false + + o3 = Ractor.make_shareable(o1) + r << Ractor.shareable?(o1) # true + r << (o1.object_id == o3.object_id) # false + r +} + +# TracePoint with normal Proc should be Ractor local +assert_equal '[4, 8]', %q{ + rs = [] + TracePoint.new(:line){|tp| rs << tp.lineno if tp.path == __FILE__}.enable do + Ractor.new{ # line 4 + a = 1 + b = 2 + }.take + c = 3 # line 8 + end + rs +} + +# Ractor deep copies frozen objects (ary) +assert_equal '[true, false]', %q{ + Ractor.new([[]].freeze) { |ary| + [ary.frozen?, ary.first.frozen? ] + }.take +} + +# Ractor deep copies frozen objects (str) +assert_equal '[true, false]', %q{ + s = String.new.instance_eval { @x = []; freeze} + Ractor.new(s) { |s| + [s.frozen?, s.instance_variable_get(:@x).frozen?] + }.take +} + +# Can not trap with not isolated Proc on non-main ractor +assert_equal '[:ok, :ok]', %q{ + a = [] + Ractor.new{ + trap(:INT){p :ok} + }.take + a << :ok + + begin + Ractor.new{ + s = 'str' + trap(:INT){p s} + }.take + rescue => Ractor::RemoteError + a << :ok + end +} + +# Ractor-local storage +assert_equal '[nil, "b", "a"]', %q{ + ans = [] + Ractor.current[:key] = 'a' + r = Ractor.new{ + Ractor.yield self[:key] + self[:key] = 'b' + self[:key] + } + ans << r.take + ans << r.take + ans << Ractor.current[:key] +} + +### +### Synchronization tests +### + +N = 100_000 + +# fstring pool +assert_equal "#{N}#{N}", %Q{ + N = #{N} + 2.times.map{ + Ractor.new{ + N.times{|i| -(i.to_s)} + } + }.map{|r| r.take}.join +} + +# enc_table +assert_equal "#{N/10}", %Q{ + Ractor.new do + loop do + Encoding.find("test-enc-#{rand(5_000)}").inspect + rescue ArgumentError => e + end + end + + src = Encoding.find("UTF-8") + #{N/10}.times{|i| + src.replicate("test-enc-\#{i}") + } +} + +# Generic ivtbl +n = N/2 +assert_equal "#{n}#{n}", %Q{ + 2.times.map{ + Ractor.new do + #{n}.times do + 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 +} + +# NameError +assert_equal "ok", %q{ + begin + bar + rescue => err + end + begin + Ractor.new{} << err + rescue TypeError + 'ok' + end +} + +assert_equal "ok", %q{ + GC.disable + Ractor.new {} + raise "not ok" unless GC.disable + + foo = [] + 10.times { foo << 1 } + + GC.start + + 'ok' +} + +# Can yield back values while GC is sweeping [Bug #18117] +assert_equal "ok", %q{ + workers = (0...8).map do + Ractor.new do + loop do + 10_000.times.map { Object.new } + Ractor.yield Time.now + end + end + end + + 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) } + "ok" +} + +assert_equal "ok", %q{ + def foo(*); ->{ super }; end + begin + Ractor.make_shareable(foo) + rescue Ractor::IsolationError + "ok" + end +} + +assert_equal "ok", %q{ + def foo(**); ->{ super }; end + begin + Ractor.make_shareable(foo) + rescue Ractor::IsolationError + "ok" + end +} + +assert_equal "ok", %q{ + def foo(...); ->{ super }; end + begin + Ractor.make_shareable(foo) + rescue Ractor::IsolationError + "ok" + end +} + +assert_equal "ok", %q{ + def foo((x), (y)); ->{ super }; end + begin + Ractor.make_shareable(foo([], [])) + rescue Ractor::IsolationError + "ok" + end +} + +end # if !ENV['GITHUB_WORKFLOW'] diff --git a/ruby/bootstraptest/test_syntax.rb b/ruby/bootstraptest/test_syntax.rb index a111990a1..948e2d780 100644 --- a/ruby/bootstraptest/test_syntax.rb +++ b/ruby/bootstraptest/test_syntax.rb @@ -268,8 +268,10 @@ def m3 defined?(@@a) } assert_equal %q{class variable}, %q{ - @@a = 1 - defined?(@@a) + class A + @@a = 1 + defined?(@@a) + end } assert_equal %q{}, %q{ defined?($a) @@ -626,7 +628,7 @@ class << (ary=[]); def []; 0; end; def []=(x); super(0,x);end;end; ary[]+=1 } assert_match /invalid multibyte char/, %q{ - STDERR.reopen(STDOUT) + $stderr = STDOUT eval("\"\xf0".force_encoding("utf-8")) }, '[ruby-dev:32429]' diff --git a/ruby/bootstraptest/test_thread.rb b/ruby/bootstraptest/test_thread.rb index f00e2f7ef..38a55ff22 100644 --- a/ruby/bootstraptest/test_thread.rb +++ b/ruby/bootstraptest/test_thread.rb @@ -8,7 +8,8 @@ puts "Thread count: #{threads.count} (#{error})" break end while true -} +} if false # disable to pass CI + assert_equal %q{ok}, %q{ Thread.new{ }.join @@ -483,3 +484,17 @@ def m GC.start f.call.source } +assert_normal_exit %q{ + class C + def inspect + sleep 0.5 + 'C!!' + end + end + Thread.new{ + loop{ + p C.new + } + } + sleep 0.1 +}, timeout: 5 diff --git a/ruby/bootstraptest/test_yjit.rb b/ruby/bootstraptest/test_yjit.rb new file mode 100644 index 000000000..30298a820 --- /dev/null +++ b/ruby/bootstraptest/test_yjit.rb @@ -0,0 +1,2737 @@ +assert_equal '18374962167983112447', %q{ + # regression test for incorrectly discarding 32 bits of a pointer when it + # comes to default values. + def large_literal_default(n: 0xff00_fabcafe0_00ff) + n + end + + def call_graph_root + large_literal_default + end + + call_graph_root + call_graph_root +} + +assert_normal_exit %q{ + # regression test for a leak caught by an asert on --yjit-call-threshold=2 + Foo = 1 + + eval("def foo = [#{(['Foo,']*256).join}]") + + foo + foo + + Object.send(:remove_const, :Foo) +} + +assert_equal '[nil, nil, nil, nil, nil, nil]', %q{ + [NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass| + klass.class_eval("def foo = @foo") + end + + [nil, true, false, 0xFABCAFE, 0.42, :cake].map do |instance| + instance.foo + instance.foo + end +} + +assert_equal '0', %q{ + # This is a regression test for incomplete invalidation from + # opt_setinlinecache. This test might be brittle, so + # feel free to remove it in the future if it's too annoying. + # This test assumes --yjit-call-threshold=2. + module M + Foo = 1 + def foo + Foo + end + + def pin_self_type_then_foo + _ = @foo + foo + end + + def only_ints + 1 + self + foo + end + end + + class Integer + include M + end + + class Sub + include M + end + + foo_method = M.instance_method(:foo) + + dbg = ->(message) do + return # comment this out to get printouts + + $stderr.puts RubyVM::YJIT.disasm(foo_method) + $stderr.puts message + end + + 2.times { 42.only_ints } + + dbg["There should be two versions of getinlineache"] + + module M + remove_const(:Foo) + end + + dbg["There should be no getinlinecaches"] + + 2.times do + 42.only_ints + rescue NameError => err + _ = "caught name error #{err}" + end + + dbg["There should be one version of getinlineache"] + + 2.times do + Sub.new.pin_self_type_then_foo + rescue NameError + _ = 'second specialization' + end + + dbg["There should be two versions of getinlineache"] + + module M + Foo = 1 + end + + dbg["There should still be two versions of getinlineache"] + + 42.only_ints + + dbg["There should be no getinlinecaches"] + + # Find name of the first VM instruction in M#foo. + insns = RubyVM::InstructionSequence.of(foo_method).to_a + if defined?(RubyVM::YJIT.blocks_for) && (insns.last.find { Array === _1 }&.first == :opt_getinlinecache) + RubyVM::YJIT.blocks_for(RubyVM::InstructionSequence.of(foo_method)) + .filter { _1.iseq_start_index == 0 }.count + else + 0 # skip the test + end +} + +# Check that frozen objects are respected +assert_equal 'great', %q{ + class Foo + attr_accessor :bar + def initialize + @bar = 1 + freeze + end + end + + foo = Foo.new + + 5.times do + begin + foo.bar = 2 + rescue FrozenError + end + end + + foo.bar == 1 ? "great" : "NG" +} + +# Check that global variable set works +assert_equal 'string', %q{ + def foo + $foo = "string" + end + + foo +} + +# Check that exceptions work when setting global variables +assert_equal 'rescued', %q{ + def set_var + $var = 100 + rescue + :rescued + end + + set_var + trace_var(:$var) { raise } + set_var +} + +# Check that global variables work +assert_equal 'string', %q{ + $foo = "string" + + def foo + $foo + end + + foo +} + +# Check that exceptions work when getting global variable +assert_equal 'rescued', %q{ + module Warning + def warn(message) + raise + end + end + + def get_var + $= + rescue + :rescued + end + + $VERBOSE = true + get_var + get_var +} + +# Check that global tracepoints work +assert_equal 'true', %q{ + def foo + 1 + end + + foo + foo + foo + + called = false + + tp = TracePoint.new(:return) { |event| + if event.method_id == :foo + called = true + end + } + tp.enable + foo + tp.disable + called +} + +# Check that local tracepoints work +assert_equal 'true', %q{ + def foo + 1 + end + + foo + foo + foo + + called = false + + tp = TracePoint.new(:return) { |_| called = true } + tp.enable(target: method(:foo)) + foo + tp.disable + called +} + +# Make sure that optional param methods return the correct value +assert_equal '1', %q{ + def m(ary = []) + yield(ary) + end + + # Warm the JIT with a 0 param call + 2.times { m { } } + m(1) { |v| v } +} + +# Test for topn +assert_equal 'array', %q{ + def threequals(a) + case a + when Array + "array" + when Hash + "hash" + else + "unknown" + end + end + + threequals([]) + threequals([]) + threequals([]) +} + +# Test for opt_mod +assert_equal '2', %q{ + def mod(a, b) + a % b + end + + mod(7, 5) + mod(7, 5) +} + +# Test for opt_mult +assert_equal '12', %q{ + def mult(a, b) + a * b + end + + mult(6, 2) + mult(6, 2) +} + +# Test for opt_div +assert_equal '3', %q{ + def div(a, b) + a / b + end + + div(6, 2) + div(6, 2) +} + +# BOP redefined methods work when JIT compiled +assert_equal 'false', %q{ + def less_than x + x < 10 + end + + class Integer + def < x + false + end + end + + less_than 2 + less_than 2 + less_than 2 +} + +# BOP redefinition works on Integer#< +assert_equal 'false', %q{ + def less_than x + x < 10 + end + + less_than 2 + less_than 2 + + class Integer + def < x + false + end + end + + less_than 2 +} + +# Putobject, less-than operator, fixnums +assert_equal '2', %q{ + def check_index(index) + if 0x40000000 < index + raise "wat? #{index}" + end + index + end + check_index 2 + check_index 2 +} + +# foo leaves a temp on the stack before the call +assert_equal '6', %q{ + def bar + return 5 + end + + def foo + return 1 + bar + end + + foo() + retval = foo() +} + +# Method with one arguments +# foo leaves a temp on the stack before the call +assert_equal '7', %q{ + def bar(a) + return a + 1 + end + + def foo + return 1 + bar(5) + end + + foo() + retval = foo() +} + +# Method with two arguments +# foo leaves a temp on the stack before the call +assert_equal '0', %q{ + def bar(a, b) + return a - b + end + + def foo + return 1 + bar(1, 2) + end + + foo() + retval = foo() +} + +# Passing argument types to callees +assert_equal '8.5', %q{ + def foo(x, y) + x + y + end + + def bar + foo(7, 1.5) + end + + bar + bar +} + +# Recursive Ruby-to-Ruby calls +assert_equal '21', %q{ + def fib(n) + if n < 2 + return n + end + + return fib(n-1) + fib(n-2) + end + + r = fib(8) +} + +# Ruby-to-Ruby call and C call +assert_normal_exit %q{ + def bar + puts('hi!') + end + + def foo + bar + end + + foo() + foo() +} + +# Method aliasing +assert_equal '42', %q{ + class Foo + def method_a + 42 + end + + alias method_b method_a + + def method_a + :somethingelse + end + end + + @obj = Foo.new + + def test + @obj.method_b + end + + test + test +} + +# Method aliasing with method from parent class +assert_equal '777', %q{ + class A + def method_a + 777 + end + end + + class B < A + alias method_b method_a + end + + @obj = B.new + + def test + @obj.method_b + end + + test + test +} + +# The hash method is a C function and uses the self argument +assert_equal 'true', %q{ + def lehashself + hash + end + + a = lehashself + b = lehashself + a == b +} + +# Method redefinition (code invalidation) test +assert_equal '1', %q{ + def ret1 + return 1 + end + + klass = Class.new do + def alias_then_hash(klass, method_to_redefine) + # Redefine the method to be ret1 + klass.alias_method(method_to_redefine, :ret1) + hash + end + end + + instance = klass.new + + i = 0 + while i < 12 + if i < 11 + # Redefine the bar method + instance.alias_then_hash(klass, :bar) + else + # Redefine the hash method to be ret1 + retval = instance.alias_then_hash(klass, :hash) + end + i += 1 + end + + retval +} + +# Code invalidation and opt_getinlinecache +assert_normal_exit %q{ + class Foo; end + + # Uses the class constant Foo + def use_constant(arg) + [Foo.new, arg] + end + + def propagate_type + i = Array.new + i.itself # make it remember that i is on-heap + use_constant(i) + end + + propagate_type + propagate_type + use_constant(Foo.new) + class Jo; end # bump global constant state + use_constant(3) +} + +# Method redefinition (code invalidation) and GC +assert_equal '7', %q{ + def bar() + return 5 + end + + def foo() + bar() + end + + foo() + foo() + + def bar() + return 7 + end + + 4.times { GC.start } + + foo() + foo() +} + +# Method redefinition with two block versions +assert_equal '7', %q{ + def bar() + return 5 + end + + def foo(n) + return ((n < 5)? 5:false), bar() + end + + foo(4) + foo(4) + foo(10) + foo(10) + + def bar() + return 7 + end + + 4.times { GC.start } + + foo(4) + foo(4)[1] +} + +# Method redefinition while the method is on the stack +assert_equal '[777, 1]', %q{ + def foo + redef() + 777 + end + + def redef + # Redefine the global foo + eval("def foo; 1; end", TOPLEVEL_BINDING) + + # Collect dead code + GC.stress = true + GC.start + + # But we will return to the original foo, + # which remains alive because it's on the stack + end + + # Must produce [777, 1] + [foo, foo] +} + +# Test for GC safety. Don't invalidate dead iseqs. +assert_normal_exit %q{ + Class.new do + def foo + itself + end + + new.foo + new.foo + new.foo + new.foo + end + + 4.times { GC.start } + def itself + self + end +} + +# test setinstancevariable on extended objects +assert_equal '1', %q{ + class Extended + attr_reader :one + + def write_many + @a = 1 + @b = 2 + @c = 3 + @d = 4 + @one = 1 + end + end + + foo = Extended.new + foo.write_many + foo.write_many + foo.write_many +} + +# test setinstancevariable on embedded objects +assert_equal '1', %q{ + class Embedded + attr_reader :one + + def write_one + @one = 1 + end + end + + foo = Embedded.new + foo.write_one + foo.write_one + foo.write_one +} + +# test setinstancevariable after extension +assert_equal '[10, 11, 12, 13, 1]', %q{ + class WillExtend + attr_reader :one + + def make_extended + @foo1 = 10 + @foo2 = 11 + @foo3 = 12 + @foo4 = 13 + end + + def write_one + @one = 1 + end + + def read_all + [@foo1, @foo2, @foo3, @foo4, @one] + end + end + + foo = WillExtend.new + foo.write_one + foo.write_one + foo.make_extended + foo.write_one + foo.read_all +} + +# test setinstancevariable on frozen object +assert_equal 'object was not modified', %q{ + class WillFreeze + def write + @ivar = 1 + end + end + + wf = WillFreeze.new + wf.write + wf.write + wf.freeze + + begin + wf.write + rescue FrozenError + "object was not modified" + end +} + +# Test getinstancevariable and inline caches +assert_equal '6', %q{ + class Foo + def initialize + @x1 = 1 + @x2 = 1 + @x2 = 1 + @x3 = 1 + @x4 = 3 + end + + def bar + x = 1 + @x4 + @x4 + end + end + + f = Foo.new + f.bar + f.bar +} + +# Test that getinstancevariable codegen checks for extended table size +assert_equal "nil\n", %q{ + class A + def read + @ins1000 + end + end + + ins = A.new + other = A.new + 10.times { other.instance_variable_set(:"@otr#{_1}", 'value') } + 1001.times { ins.instance_variable_set(:"@ins#{_1}", 'value') } + + ins.read + ins.read + ins.read + + p other.read +} + +# Test that opt_aref checks the class of the receiver +assert_equal 'special', %q{ + def foo(array) + array[30] + end + + foo([]) + foo([]) + + special = [] + def special.[](idx) + 'special' + end + + foo(special) +} + +# Test that object references in generated code get marked and moved +assert_equal "good", %q{ + def bar + "good" + end + + def foo + bar + end + + foo + foo + + begin + GC.verify_compaction_references(double_heap: true, toward: :empty) + rescue NotImplementedError + # in case compaction isn't supported + end + + foo +} + +# Test polymorphic getinstancevariable. T_OBJECT -> T_STRING +assert_equal 'ok', %q{ + @hello = @h1 = @h2 = @h3 = @h4 = 'ok' + str = "" + str.instance_variable_set(:@hello, 'ok') + + public def get + @hello + end + + get + get + str.get + str.get +} + +# Test polymorphic getinstancevariable, two different classes +assert_equal 'ok', %q{ + class Embedded + def initialize + @ivar = 0 + end + + def get + @ivar + end + end + + class Extended < Embedded + def initialize + @v1 = @v2 = @v3 = @v4 = @ivar = 'ok' + end + end + + embed = Embedded.new + extend = Extended.new + + embed.get + embed.get + extend.get + extend.get +} + +# Test megamorphic getinstancevariable +assert_equal 'ok', %q{ + parent = Class.new do + def initialize + @hello = @h1 = @h2 = @h3 = @h4 = 'ok' + end + + def get + @hello + end + end + + subclasses = 300.times.map { Class.new(parent) } + subclasses.each { _1.new.get } + parent.new.get +} + +# Test polymorphic opt_aref. array -> hash +assert_equal '[42, :key]', %q{ + def index(obj, idx) + obj[idx] + end + + index([], 0) # get over compilation threshold + + [ + index([42], 0), + index({0=>:key}, 0), + ] +} + +# Test polymorphic opt_aref. hash -> array -> custom class +assert_equal '[nil, nil, :custom]', %q{ + def index(obj, idx) + obj[idx] + end + + custom = Object.new + def custom.[](_idx) + :custom + end + + index({}, 0) # get over compilation threshold + + [ + index({}, 0), + index([], 0), + index(custom, 0) + ] +} + +# Test polymorphic opt_aref. array -> custom class +assert_equal '[42, :custom]', %q{ + def index(obj, idx) + obj[idx] + end + + custom = Object.new + def custom.[](_idx) + :custom + end + + index([], 0) # get over compilation threshold + + [ + index([42], 0), + index(custom, 0) + ] +} + +# Test custom hash method with opt_aref +assert_equal '[nil, :ok]', %q{ + def index(obj, idx) + obj[idx] + end + + custom = Object.new + def custom.hash + 42 + end + + h = {custom => :ok} + + [ + index(h, 0), + index(h, custom) + ] +} + +# Test default value block for Hash with opt_aref +assert_equal '[42, :default]', %q{ + def index(obj, idx) + obj[idx] + end + + h = Hash.new { :default } + h[0] = 42 + + [ + index(h, 0), + index(h, 1) + ] +} + +# A regression test for making sure cfp->sp is proper when +# hitting stubs. See :stub-sp-flush: +assert_equal 'ok', %q{ + class D + def foo + Object.new + end + end + + GC.stress = true + 10.times do + D.new.foo + # ^ + # This hits a stub with sp_offset > 0 + end + + :ok +} + +# Test polymorphic callsite, cfunc -> iseq +assert_equal '[Cfunc, Iseq]', %q{ + public def call_itself + itself # the polymorphic callsite + end + + class Cfunc; end + + class Iseq + def itself + self + end + end + + call_itself # cross threshold + + [Cfunc.call_itself, Iseq.call_itself] +} + +# Test polymorphic callsite, iseq -> cfunc +assert_equal '[Iseq, Cfunc]', %q{ + public def call_itself + itself # the polymorphic callsite + end + + class Cfunc; end + + class Iseq + def itself + self + end + end + + call_itself # cross threshold + + [Iseq.call_itself, Cfunc.call_itself] +} + +# attr_reader method +assert_equal '[100, 299]', %q{ + class A + attr_reader :foo + + def initialize + @foo = 100 + end + + # Make it extended + def fill! + @bar = @jojo = @as = @sdfsdf = @foo = 299 + end + end + + def bar(ins) + ins.foo + end + + ins = A.new + oth = A.new + oth.fill! + + bar(ins) + bar(oth) + + [bar(ins), bar(oth)] +} + +# get ivar on object, then on hash +assert_equal '[42, 100]', %q{ + class Hash + attr_accessor :foo + end + + class A + attr_reader :foo + + def initialize + @foo = 42 + end + end + + def use(val) + val.foo + end + + + h = {} + h.foo = 100 + obj = A.new + + use(obj) + [use(obj), use(h)] +} + +# get ivar on String +assert_equal '[nil, nil, 42, 42]', %q{ + # @foo to exercise the getinstancevariable instruction + public def get_foo + @foo + end + + get_foo + get_foo # compile it for the top level object + + class String + attr_reader :foo + end + + def run + str = String.new + + getter = str.foo + insn = str.get_foo + + str.instance_variable_set(:@foo, 42) + + [getter, insn, str.foo, str.get_foo] + end + + run + run +} + +# splatting an empty array on a getter +assert_equal '42', %q{ + @foo = 42 + module Kernel + attr_reader :foo + end + + def run + foo(*[]) + end + + run + run +} + +# getinstancevariable on Symbol +assert_equal '[nil, nil]', %q{ + # @foo to exercise the getinstancevariable instruction + public def get_foo + @foo + end + + dyn_sym = ("a" + "b").to_sym + sym = :static + + # compile get_foo + dyn_sym.get_foo + dyn_sym.get_foo + + [dyn_sym.get_foo, sym.get_foo] +} + +# attr_reader on Symbol +assert_equal '[nil, nil]', %q{ + class Symbol + attr_reader :foo + end + + public def get_foo + foo + end + + dyn_sym = ("a" + "b").to_sym + sym = :static + + # compile get_foo + dyn_sym.get_foo + dyn_sym.get_foo + + [dyn_sym.get_foo, sym.get_foo] +} + +# passing too few arguments to method with optional parameters +assert_equal 'raised', %q{ + def opt(a, b = 0) + end + + def use + opt + end + + use rescue nil + begin + use + :ng + rescue ArgumentError + :raised + end +} + +# passing too many arguments to method with optional parameters +assert_equal 'raised', %q{ + def opt(a, b = 0) + end + + def use + opt(1, 2, 3, 4) + end + + use rescue nil + begin + use + :ng + rescue ArgumentError + :raised + end +} + +# test calling Ruby method with a block +assert_equal '[1, 2, 42]', %q{ + def thing(a, b) + [a, b, yield] + end + + def use + thing(1,2) { 42 } + end + + use + use +} + +# test calling C method with a block +assert_equal '[42, 42]', %q{ + def use(array, initial) + array.reduce(initial) { |a, b| a + b } + end + + use([], 0) + [use([2, 2], 38), use([14, 14, 14], 0)] +} + +# test calling block param +assert_equal '[1, 2, 42]', %q{ + def foo(&block) + block.call + end + + [foo {1}, foo {2}, foo {42}] +} + +# test calling block param failing +assert_equal '42', %q{ + def foo(&block) + block.call + end + + foo {} # warmup + + begin + foo + rescue NoMethodError => e + 42 if nil == e.receiver + end +} + +# test calling method taking block param +assert_equal '[Proc, 1, 2, 3, Proc]', %q{ + def three(a, b, c, &block) + [a, b, c, block.class] + end + + def zero(&block) + block.class + end + + def use_three + three(1, 2, 3) {} + end + + def use_zero + zero {} + end + + use_three + use_zero + + [use_zero] + use_three +} + +# test building empty array +assert_equal '[]', %q{ + def build_arr + [] + end + + build_arr + build_arr +} + +# test building array of one element +assert_equal '[5]', %q{ + def build_arr(val) + [val] + end + + build_arr(5) + build_arr(5) +} + +# test building array of several element +assert_equal '[5, 5, 5, 5, 5]', %q{ + def build_arr(val) + [val, val, val, val, val] + end + + build_arr(5) + build_arr(5) +} + +# test building empty hash +assert_equal '{}', %q{ + def build_hash + {} + end + + build_hash + build_hash +} + +# test building hash with values +assert_equal '{:foo=>:bar}', %q{ + def build_hash(val) + { foo: val } + end + + build_hash(:bar) + build_hash(:bar) +} + +# test string interpolation with known types +assert_equal 'foobar', %q{ + def make_str + foo = -"foo" + bar = -"bar" + "#{foo}#{bar}" + end + + make_str + make_str +} + +# test string interpolation with unknown types +assert_equal 'foobar', %q{ + def make_str(foo, bar) + "#{foo}#{bar}" + end + + make_str("foo", "bar") + make_str("foo", "bar") +} + +# test string interpolation with known non-strings +assert_equal 'foo123', %q{ + def make_str + foo = -"foo" + bar = 123 + "#{foo}#{bar}" + end + + make_str + make_str +} + +# test string interpolation with unknown non-strings +assert_equal 'foo123', %q{ + def make_str(foo, bar) + "#{foo}#{bar}" + end + + make_str("foo", 123) + make_str("foo", 123) +} + +# test string interpolation with overridden to_s +assert_equal 'foo', %q{ + class String + def to_s + "bad" + end + end + + def make_str(foo) + "#{foo}" + end + + make_str("foo") + make_str("foo") +} + + +# test invokebuiltin as used in struct assignment +assert_equal '123', %q{ + def foo(obj) + obj.foo = 123 + end + + struct = Struct.new(:foo) + obj = struct.new + foo(obj) + foo(obj) +} + +# test invokebuiltin_delegate as used inside Dir.open +assert_equal '.', %q{ + def foo(path) + Dir.open(path).path + end + + foo(".") + foo(".") +} + +# test invokebuiltin_delegate_leave in method called from jit +assert_normal_exit %q{ + def foo(obj) + obj.clone + end + + foo(Object.new) + foo(Object.new) +} + +# test invokebuiltin_delegate_leave in method called from cfunc +assert_normal_exit %q{ + def foo(obj) + [obj].map(&:clone) + end + + foo(Object.new) + foo(Object.new) +} + +# defining TrueClass#! +assert_equal '[false, false, :ok]', %q{ + def foo(obj) + !obj + end + + x = foo(true) + y = foo(true) + + class TrueClass + def ! + :ok + end + end + + z = foo(true) + + [x, y, z] +} + +# defining FalseClass#! +assert_equal '[true, true, :ok]', %q{ + def foo(obj) + !obj + end + + x = foo(false) + y = foo(false) + + class FalseClass + def ! + :ok + end + end + + z = foo(false) + + [x, y, z] +} + +# defining NilClass#! +assert_equal '[true, true, :ok]', %q{ + def foo(obj) + !obj + end + + x = foo(nil) + y = foo(nil) + + class NilClass + def ! + :ok + end + end + + z = foo(nil) + + [x, y, z] +} + +# polymorphic opt_not +assert_equal '[true, true, false, false, false, false, false]', %q{ + def foo(obj) + !obj + end + + foo(0) + [foo(nil), foo(false), foo(true), foo([]), foo(0), foo(4.2), foo(:sym)] +} + +# getlocal with 2 levels +assert_equal '7', %q{ + def foo(foo, bar) + while foo > 0 + while bar > 0 + return foo + bar + end + end + end + + foo(5,2) + foo(5,2) +} + +# test pattern matching +assert_equal '[:ok, :ok]', %q{ + class C + def destructure_keys + {} + end + end + + pattern_match = ->(i) do + case i + in a: 0 + :ng + else + :ok + end + end + + [{}, C.new].map(&pattern_match) +} + +# Call to object with singleton +assert_equal '123', %q{ + obj = Object.new + def obj.foo + 123 + end + + def foo(obj) + obj.foo() + end + + foo(obj) + foo(obj) +} + +# Call method on an object that has a non-material +# singleton class. +# TODO: assert that it takes no side exits? This +# test case revealed that we were taking exits unnecessarily. +assert_normal_exit %q{ + def foo(obj) + obj.itself + end + + o = Object.new.singleton_class + foo(o) + foo(o) +} + +# Call to singleton class +assert_equal '123', %q{ + class Foo + def self.foo + 123 + end + end + + def foo(obj) + obj.foo() + end + + foo(Foo) + foo(Foo) +} + +# invokesuper edge case +assert_equal '[:A, [:A, :B]]', %q{ + class B + def foo = :B + end + + class A < B + def foo = [:A, super()] + end + + A.new.foo + A.new.foo # compile A#foo + + class C < A + define_method(:bar, A.instance_method(:foo)) + end + + C.new.bar +} + +# Same invokesuper bytecode, multiple destinations +assert_equal '[:Forward, :SecondTerminus]', %q{ + module Terminus + def foo = :Terminus + end + + module SecondTerminus + def foo = :SecondTerminus + end + + + module Forward + def foo = [:Forward, super] + end + + class B + include SecondTerminus + end + + class A < B + include Terminus + include Forward + end + + A.new.foo + A.new.foo # compile + + class B + include Forward + alias bar foo + end + + # A.ancestors.take(5) == [A, Forward, Terminus, B, Forward, SecondTerminus] + + A.new.bar +} + +# invokesuper calling into itself +assert_equal '[:B, [:B, :m]]', %q{ + module M + def foo = :m + end + + class B + include M + def foo = [:B, super] + end + + ins = B.new + ins.singleton_class # materialize the singleton class + ins.foo + ins.foo # compile + + ins.singleton_class.define_method(:bar, B.instance_method(:foo)) + ins.bar +} + +# invokesuper changed ancestor +assert_equal '[:A, [:M, :B]]', %q{ + class B + def foo + :B + end + end + + class A < B + def foo + [:A, super] + end + end + + module M + def foo + [:M, super] + end + end + + ins = A.new + ins.foo + ins.foo + A.include(M) + ins.foo +} + +# invokesuper changed ancestor via prepend +assert_equal '[:A, [:M, :B]]', %q{ + class B + def foo + :B + end + end + + class A < B + def foo + [:A, super] + end + end + + module M + def foo + [:M, super] + end + end + + ins = A.new + ins.foo + ins.foo + B.prepend(M) + ins.foo +} + +# invokesuper replaced method +assert_equal '[:A, :Btwo]', %q{ + class B + def foo + :B + end + end + + class A < B + def foo + [:A, super] + end + end + + ins = A.new + ins.foo + ins.foo + class B + def foo + :Btwo + end + end + ins.foo +} + +# Call to fixnum +assert_equal '[true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + is_odd(1) + is_odd(1) + + [is_odd(123), is_odd(456)] +} + +# Call to bignum +assert_equal '[true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + bignum = 99999999999999999999 + is_odd(bignum) + is_odd(bignum) + + [is_odd(bignum), is_odd(bignum+1)] +} + +# Call to fixnum and bignum +assert_equal '[true, false, true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + bignum = 99999999999999999999 + is_odd(bignum) + is_odd(bignum) + is_odd(123) + is_odd(123) + + [is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)] +} + +# Call to static and dynamic symbol +assert_equal 'bar', %q{ + def to_string(obj) + obj.to_s + end + + to_string(:foo) + to_string(:foo) + to_string((-"bar").to_sym) + to_string((-"bar").to_sym) +} + +# Call to flonum and heap float +assert_equal '[nil, nil, nil, 1]', %q{ + def is_inf(obj) + obj.infinite? + end + + is_inf(0.0) + is_inf(0.0) + is_inf(1e256) + is_inf(1e256) + + [ + is_inf(0.0), + is_inf(1.0), + is_inf(1e256), + is_inf(1.0/0.0) + ] +} + +assert_equal '[1, 2, 3, 4, 5]', %q{ + def splatarray + [*(1..5)] + end + + splatarray + splatarray +} + +assert_equal '[1, 1, 2, 1, 2, 3]', %q{ + def expandarray + arr = [1, 2, 3] + + a, = arr + b, c, = arr + d, e, f = arr + + [a, b, c, d, e, f] + end + + expandarray + expandarray +} + +assert_equal '[1, 1]', %q{ + def expandarray_useless_splat + arr = (1..10).to_a + + a, * = arr + b, (*) = arr + + [a, b] + end + + expandarray_useless_splat + expandarray_useless_splat +} + +assert_equal '[:not_heap, nil, nil]', %q{ + def expandarray_not_heap + a, b, c = :not_heap + [a, b, c] + end + + expandarray_not_heap + expandarray_not_heap +} + +assert_equal '[:not_array, nil, nil]', %q{ + def expandarray_not_array(obj) + a, b, c = obj + [a, b, c] + end + + obj = Object.new + def obj.to_ary + [:not_array] + end + + expandarray_not_array(obj) + expandarray_not_array(obj) +} + +assert_equal '[1, 2, nil]', %q{ + def expandarray_rhs_too_small + a, b, c = [1, 2] + [a, b, c] + end + + expandarray_rhs_too_small + expandarray_rhs_too_small +} + +assert_equal '[1, [2]]', %q{ + def expandarray_splat + a, *b = [1, 2] + [a, b] + end + + expandarray_splat + expandarray_splat +} + +assert_equal '2', %q{ + def expandarray_postarg + *, a = [1, 2] + a + end + + expandarray_postarg + expandarray_postarg +} + +assert_equal '10', %q{ + obj = Object.new + val = nil + obj.define_singleton_method(:to_ary) { val = 10; [] } + + def expandarray_always_call_to_ary(object) + * = object + end + + expandarray_always_call_to_ary(obj) + expandarray_always_call_to_ary(obj) + + val +} + +# regression test of local type change +assert_equal '1.1', %q{ +def bar(baz, quux) + if baz.integer? + baz, quux = quux, nil + end + baz.to_s +end + +bar(123, 1.1) +bar(123, 1.1) +} + +# test enabling a line TracePoint in a C method call +assert_equal '[[:line, true]]', %q{ + events = [] + events.instance_variable_set( + :@tp, + TracePoint.new(:line) { |tp| events << [tp.event, tp.lineno] if tp.path == __FILE__ } + ) + def events.to_str + @tp.enable; '' + end + + # Stay in generated code while enabling tracing + def events.compiled(obj) + String(obj) + @tp.disable; __LINE__ + end + + line = events.compiled(events) + events[0][-1] = (events[0][-1] == line) + + events +} + +# test enabling a c_return TracePoint in a C method call +assert_equal '[[:c_return, :String, :string_alias, "events_to_str"]]', %q{ + events = [] + events.instance_variable_set(:@tp, TracePoint.new(:c_return) { |tp| events << [tp.event, tp.method_id, tp.callee_id, tp.return_value] }) + def events.to_str + @tp.enable; 'events_to_str' + end + + # Stay in generated code while enabling tracing + alias string_alias String + def events.compiled(obj) + string_alias(obj) + @tp.disable + end + + events.compiled(events) + + events +} + +# test enabling a TracePoint that targets a particular line in a C method call +assert_equal '[true]', %q{ + events = [] + events.instance_variable_set(:@tp, TracePoint.new(:line) { |tp| events << tp.lineno }) + def events.to_str + @tp.enable(target: method(:compiled)) + '' + end + + # Stay in generated code while enabling tracing + def events.compiled(obj) + String(obj) + __LINE__ + end + + line = events.compiled(events) + events[0] = (events[0] == line) + + events +} + +# test enabling tracing in the middle of splatarray +assert_equal '[true]', %q{ + events = [] + obj = Object.new + obj.instance_variable_set(:@tp, TracePoint.new(:line) { |tp| events << tp.lineno }) + def obj.to_a + @tp.enable(target: method(:compiled)) + [] + end + + # Enable tracing in the middle of the splatarray instruction + def obj.compiled(obj) + * = *obj + __LINE__ + end + + obj.compiled([]) + line = obj.compiled(obj) + events[0] = (events[0] == line) + + events +} + +# test enabling tracing in the middle of opt_aref. Different since the codegen +# for it ends in a jump. +assert_equal '[true]', %q{ + def lookup(hash, tp) + hash[42] + tp.disable; __LINE__ + end + + lines = [] + tp = TracePoint.new(:line) { lines << _1.lineno if _1.path == __FILE__ } + + lookup(:foo, tp) + lookup({}, tp) + + enable_tracing_on_missing = Hash.new { tp.enable } + + expected_line = lookup(enable_tracing_on_missing, tp) + + lines[0] = true if lines[0] == expected_line + + lines +} + +# test enabling c_call tracing before compiling +assert_equal '[[:c_call, :itself]]', %q{ + def shouldnt_compile + itself + end + + events = [] + tp = TracePoint.new(:c_call) { |tp| events << [tp.event, tp.method_id] } + + # assume first call compiles + tp.enable { shouldnt_compile } + + events +} + +# test enabling c_return tracing before compiling +assert_equal '[[:c_return, :itself, main]]', %q{ + def shouldnt_compile + itself + end + + events = [] + tp = TracePoint.new(:c_return) { |tp| events << [tp.event, tp.method_id, tp.return_value] } + + # assume first call compiles + tp.enable { shouldnt_compile } + + events +} + +# test enabling tracing for a suspended fiber +assert_equal '[[:return, 42]]', %q{ + def traced_method + Fiber.yield + 42 + end + + events = [] + tp = TracePoint.new(:return) { events << [_1.event, _1.return_value] } + # assume first call compiles + fiber = Fiber.new { traced_method } + fiber.resume + tp.enable(target: method(:traced_method)) + fiber.resume + + events +} + +# test compiling on non-tracing ractor then running on a tracing one +assert_equal '[:itself]', %q{ + def traced_method + itself + end + + + tracing_ractor = Ractor.new do + # 1: start tracing + events = [] + tp = TracePoint.new(:c_call) { events << _1.method_id } + tp.enable + Ractor.yield(nil) + + # 3: run compiled method on tracing ractor + Ractor.yield(nil) + traced_method + + events + ensure + tp&.disable + end + + tracing_ractor.take + + # 2: compile on non tracing ractor + traced_method + + tracing_ractor.take + tracing_ractor.take +} + +# Try to hit a lazy branch stub while another ractor enables tracing +assert_equal '42', %q{ + def compiled(arg) + if arg + arg + 1 + else + itself + itself + end + end + + ractor = Ractor.new do + compiled(false) + Ractor.yield(nil) + compiled(41) + end + + tp = TracePoint.new(:line) { itself } + ractor.take + tp.enable + + ractor.take +} + +# Test equality with changing types +assert_equal '[true, false, false, false]', %q{ + def eq(a, b) + a == b + end + + [ + eq("foo", "foo"), + eq("foo", "bar"), + eq(:foo, "bar"), + eq("foo", :bar) + ] +} + +# Redefined String eq +assert_equal 'true', %q{ + class String + def ==(other) + true + end + end + + def eq(a, b) + a == b + end + + eq("foo", "bar") + eq("foo", "bar") +} + +# Redefined Integer eq +assert_equal 'true', %q{ + class Integer + def ==(other) + true + end + end + + def eq(a, b) + a == b + end + + eq(1, 2) + eq(1, 2) +} + +# aset on array with invalid key +assert_normal_exit %q{ + def foo(arr) + arr[:foo] = 123 + end + + foo([1]) rescue nil + foo([1]) rescue nil +} + +# test ractor exception on when setting ivar +assert_equal '42', %q{ + class A + def self.foo + _foo = 1 + _bar = 2 + begin + @bar = _foo + _bar + rescue Ractor::IsolationError + 42 + end + end + end + + A.foo + A.foo + + Ractor.new { A.foo }.take +} + +assert_equal '["plain", "special", "sub", "plain"]', %q{ + def foo(arg) + arg.to_s + end + + class Sub < String + end + + special = String.new("special") + special.singleton_class + + [ + foo("plain"), + foo(special), + foo(Sub.new("sub")), + foo("plain") + ] +} + +assert_equal '["sub", "sub"]', %q{ + def foo(arg) + arg.to_s + end + + class Sub < String + def to_s + super + end + end + + sub = Sub.new("sub") + + [foo(sub), foo(sub)] +} + +assert_equal '[1]', %q{ + def kwargs(value:) + value + end + + 5.times.map { kwargs(value: 1) }.uniq +} + +assert_equal '[:ok]', %q{ + def kwargs(value:) + value + end + + 5.times.map { kwargs() rescue :ok }.uniq +} + +assert_equal '[:ok]', %q{ + def kwargs(a:, b: nil) + value + end + + 5.times.map { kwargs(b: 123) rescue :ok }.uniq +} + +assert_equal '[[1, 2]]', %q{ + def kwargs(left:, right:) + [left, right] + end + + 5.times.flat_map do + [ + kwargs(left: 1, right: 2), + kwargs(right: 2, left: 1) + ] + end.uniq +} + +assert_equal '[[1, 2]]', %q{ + def kwargs(lead, kwarg:) + [lead, kwarg] + end + + 5.times.map { kwargs(1, kwarg: 2) }.uniq +} + +# optional and keyword args +assert_equal '[[1, 2, 3]]', %q{ + def opt_and_kwargs(a, b=2, c: nil) + [a,b,c] + end + + 5.times.map { opt_and_kwargs(1, c: 3) }.uniq +} + +assert_equal '[[1, 2, 3]]', %q{ + def opt_and_kwargs(a, b=nil, c: nil) + [a,b,c] + end + + 5.times.map { opt_and_kwargs(1, 2, c: 3) }.uniq +} + +# Bug #18453 +assert_equal '[[1, nil, 2]]', %q{ + def opt_and_kwargs(a = {}, b: nil, c: nil) + [a, b, c] + end + + 5.times.map { opt_and_kwargs(1, c: 2) }.uniq +} + +assert_equal '[[{}, nil, 1]]', %q{ + def opt_and_kwargs(a = {}, b: nil, c: nil) + [a, b, c] + end + + 5.times.map { opt_and_kwargs(c: 1) }.uniq +} + +# leading and keyword arguments are swapped into the right order +assert_equal '[[1, 2, 3, 4, 5, 6]]', %q{ + def kwargs(five, six, a:, b:, c:, d:) + [a, b, c, d, five, six] + end + + 5.times.flat_map do + [ + kwargs(5, 6, a: 1, b: 2, c: 3, d: 4), + kwargs(5, 6, a: 1, b: 2, d: 4, c: 3), + kwargs(5, 6, a: 1, c: 3, b: 2, d: 4), + kwargs(5, 6, a: 1, c: 3, d: 4, b: 2), + kwargs(5, 6, a: 1, d: 4, b: 2, c: 3), + kwargs(5, 6, a: 1, d: 4, c: 3, b: 2), + kwargs(5, 6, b: 2, a: 1, c: 3, d: 4), + kwargs(5, 6, b: 2, a: 1, d: 4, c: 3), + kwargs(5, 6, b: 2, c: 3, a: 1, d: 4), + kwargs(5, 6, b: 2, c: 3, d: 4, a: 1), + kwargs(5, 6, b: 2, d: 4, a: 1, c: 3), + kwargs(5, 6, b: 2, d: 4, c: 3, a: 1), + kwargs(5, 6, c: 3, a: 1, b: 2, d: 4), + kwargs(5, 6, c: 3, a: 1, d: 4, b: 2), + kwargs(5, 6, c: 3, b: 2, a: 1, d: 4), + kwargs(5, 6, c: 3, b: 2, d: 4, a: 1), + kwargs(5, 6, c: 3, d: 4, a: 1, b: 2), + kwargs(5, 6, c: 3, d: 4, b: 2, a: 1), + kwargs(5, 6, d: 4, a: 1, b: 2, c: 3), + kwargs(5, 6, d: 4, a: 1, c: 3, b: 2), + kwargs(5, 6, d: 4, b: 2, a: 1, c: 3), + kwargs(5, 6, d: 4, b: 2, c: 3, a: 1), + kwargs(5, 6, d: 4, c: 3, a: 1, b: 2), + kwargs(5, 6, d: 4, c: 3, b: 2, a: 1) + ] + end.uniq +} + +# implicit hashes get skipped and don't break compilation +assert_equal '[[:key]]', %q{ + def implicit(hash) + hash.keys + end + + 5.times.map { implicit(key: :value) }.uniq +} + +# default values on keywords don't mess up argument order +assert_equal '[2]', %q{ + def default_value + 1 + end + + def default_expression(value: default_value) + value + end + + 5.times.map { default_expression(value: 2) }.uniq +} + +# constant default values on keywords +assert_equal '[3]', %q{ + def default_expression(value: 3) + value + end + + 5.times.map { default_expression }.uniq +} + +# non-constant default values on keywords +assert_equal '[3]', %q{ + def default_value + 3 + end + + def default_expression(value: default_value) + value + end + + 5.times.map { default_expression }.uniq +} + +# reordered optional kwargs +assert_equal '[[100, 1]]', %q{ + def foo(capacity: 100, max: nil) + [capacity, max] + end + + 5.times.map { foo(max: 1) }.uniq +} + +# invalid lead param +assert_equal 'ok', %q{ + def bar(baz: 2) + baz + end + + def foo + bar(1, baz: 123) + end + + begin + foo + foo + rescue ArgumentError => e + print "ok" + end +} + +# reordered required kwargs +assert_equal '[[1, 2, 3, 4]]', %q{ + def foo(default1: 1, required1:, default2: 3, required2:) + [default1, required1, default2, required2] + end + + 5.times.map { foo(required1: 2, required2: 4) }.uniq +} + +# reordered default expression kwargs +assert_equal '[[:one, :two, 3]]', %q{ + def foo(arg1: (1+0), arg2: (2+0), arg3: (3+0)) + [arg1, arg2, arg3] + end + + 5.times.map { foo(arg2: :two, arg1: :one) }.uniq +} + +# complex kwargs +assert_equal '[[1, 2, 3, 4]]', %q{ + def foo(required:, specified: 999, simple_default: 3, complex_default: "4".to_i) + [required, specified, simple_default, complex_default] + end + + 5.times.map { foo(specified: 2, required: 1) }.uniq +} + +# attr_reader on frozen object +assert_equal 'false', %q{ + class Foo + attr_reader :exception + + def failed? + !exception.nil? + end + end + + foo = Foo.new.freeze + foo.failed? + foo.failed? +} + +# regression test for doing kwarg shuffle before checking for interrupts +assert_equal 'ok', %q{ + def new_media_drop(attributes:, product_drop:, context:, sources:) + nil.nomethod rescue nil # force YJIT to bail to side exit + + [attributes, product_drop, context, sources] + end + + def load_medias(product_drop: nil, raw_medias:, context:) + raw_medias.map do |raw_media| + case new_media_drop(context: context, attributes: raw_media, product_drop: product_drop, sources: []) + in [Hash, ProductDrop, Context, Array] + else + raise "bad shuffle" + end + end + end + + class Context; end + + class ProductDrop + attr_reader :title + def initialize(title) + @title = title + end + end + + # Make a thread so we have thread switching interrupts + th = Thread.new do + while true; end + end + 1_000.times do |i| + load_medias(product_drop: ProductDrop.new("foo"), raw_medias: [{}, {}], context: Context.new) + end + th.kill.join + + :ok +} + +# regression test for tracing attr_accessor methods. +assert_equal "true", %q{ + c = Class.new do + attr_accessor :x + alias y x + alias y= x= + end + obj = c.new + + ar_meth = obj.method(:x) + aw_meth = obj.method(:x=) + aar_meth = obj.method(:y) + aaw_meth = obj.method(:y=) + events = [] + trace = TracePoint.new(:c_call, :c_return){|tp| + next if tp.path != __FILE__ + next if tp.method_id == :call + case tp.event + when :c_call + events << [tp.event, tp.method_id, tp.callee_id] + when :c_return + events << [tp.event, tp.method_id, tp.callee_id, tp.return_value] + end + } + test_proc = proc do + obj.x = 1 + obj.x + obj.y = 2 + obj.y + aw_meth.call(1) + ar_meth.call + aaw_meth.call(2) + aar_meth.call + end + test_proc.call # populate call caches + trace.enable(&test_proc) + expected = [ + [:c_call, :x=, :x=], + [:c_return, :x=, :x=, 1], + [:c_call, :x, :x], + [:c_return, :x, :x, 1], + [:c_call, :x=, :y=], + [:c_return, :x=, :y=, 2], + [:c_call, :x, :y], + [:c_return, :x, :y, 2], + ] * 2 + + expected == events +} + +# duphash +assert_equal '{:foo=>123}', %q{ + def foo + {foo: 123} + end + + foo + foo +} + +# newhash +assert_equal '{:foo=>2}', %q{ + def foo + {foo: 1+1} + end + + foo + foo +} + +# block invalidation edge case +assert_equal 'undef', %q{ + class A + def foo(arg) + arg.times { A.remove_method(:bar) } + self + end + + def bar + 4 + end + + def use(arg) + # two consecutive sends. When bar is removed, the return address + # for calling it is already on foo's control frame + foo(arg).bar + rescue NoMethodError + :undef + end + end + + A.new.use 0 + A.new.use 0 + A.new.use 1 +} + +# block invalidation edge case +assert_equal 'ok', %q{ + class A + Good = :ng + def foo(arg) + arg.times { A.const_set(:Good, :ok) } + self + end + + def id(arg) + arg + end + + def use(arg) + # send followed by an opt_getinlinecache. + # The return address remains on the control frame + # when opt_getinlinecache is invalidated. + foo(arg).id(Good) + end + end + + A.new.use 0 + A.new.use 0 + A.new.use 1 +} + +assert_equal 'ok', %q{ + # test hitting a branch stub when out of memory + def nimai(jita) + if jita + :ng + else + :ok + end + end + + nimai(true) + nimai(true) + + RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT) + + nimai(false) +} + +assert_equal 'new', %q{ + # test block invalidation while out of memory + def foo + :old + end + + def test + foo + end + + test + test + + RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT) + + def foo + :new + end + + test +} + +assert_equal 'ok', %q{ + # Try to compile new method while OOM + def foo + :ok + end + + RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT) + + foo + foo +} + +# struct aref embedded +assert_equal '2', %q{ + def foo(s) + s.foo + end + + S = Struct.new(:foo) + foo(S.new(1)) + foo(S.new(2)) +} + +# struct aref non-embedded +assert_equal '4', %q{ + def foo(s) + s.d + end + + S = Struct.new(:a, :b, :c, :d, :e) + foo(S.new(1,2,3,4,5)) + foo(S.new(1,2,3,4,5)) +} + +# struct aset embedded +assert_equal '123', %q{ + def foo(s) + s.foo = 123 + end + + s = Struct.new(:foo).new + foo(s) + s = Struct.new(:foo).new + foo(s) + s.foo +} + +# struct aset non-embedded +assert_equal '[1, 2, 3, 4, 5]', %q{ + def foo(s) + s.a = 1 + s.b = 2 + s.c = 3 + s.d = 4 + s.e = 5 + end + + S = Struct.new(:a, :b, :c, :d, :e) + s = S.new + foo(s) + s = S.new + foo(s) + [s.a, s.b, s.c, s.d, s.e] +} + +# struct aref too many args +assert_equal 'ok', %q{ + def foo(s) + s.foo(:bad) + end + + s = Struct.new(:foo).new + foo(s) rescue :ok + foo(s) rescue :ok +} + +# struct aset too many args +assert_equal 'ok', %q{ + def foo(s) + s.set_foo(123, :bad) + end + + s = Struct.new(:foo) do + alias :set_foo :foo= + end + foo(s) rescue :ok + foo(s) rescue :ok +} diff --git a/ruby/bootstraptest/test_yjit_30k_ifelse.rb b/ruby/bootstraptest/test_yjit_30k_ifelse.rb new file mode 100644 index 000000000..c3afa95e4 --- /dev/null +++ b/ruby/bootstraptest/test_yjit_30k_ifelse.rb @@ -0,0 +1,241023 @@ +# This is a torture test for the JIT. +# There are 30K tiny methods with if-else statements in a 30-deep call hierarchy. +assert_equal '100000', %q{ + +def fun_l0_n0(x) + if (x < 1) + fun_l1_n310(x) + else + fun_l1_n485(x) + end +end + +def fun_l0_n1(x) + if (x < 1) + fun_l1_n930(x) + else + fun_l1_n418(x) + end +end + +def fun_l0_n2(x) + if (x < 1) + fun_l1_n549(x) + else + fun_l1_n44(x) + end +end + +def fun_l0_n3(x) + if (x < 1) + fun_l1_n394(x) + else + fun_l1_n447(x) + end +end + +def fun_l0_n4(x) + if (x < 1) + fun_l1_n683(x) + else + fun_l1_n547(x) + end +end + +def fun_l0_n5(x) + if (x < 1) + fun_l1_n320(x) + else + fun_l1_n896(x) + end +end + +def fun_l0_n6(x) + if (x < 1) + fun_l1_n649(x) + else + fun_l1_n243(x) + end +end + +def fun_l0_n7(x) + if (x < 1) + fun_l1_n100(x) + else + fun_l1_n243(x) + end +end + +def fun_l0_n8(x) + if (x < 1) + fun_l1_n839(x) + else + fun_l1_n720(x) + end +end + +def fun_l0_n9(x) + if (x < 1) + fun_l1_n177(x) + else + fun_l1_n555(x) + end +end + +def fun_l0_n10(x) + if (x < 1) + fun_l1_n814(x) + else + fun_l1_n900(x) + end +end + +def fun_l0_n11(x) + if (x < 1) + fun_l1_n585(x) + else + fun_l1_n901(x) + end +end + +def fun_l0_n12(x) + if (x < 1) + fun_l1_n952(x) + else + fun_l1_n270(x) + end +end + +def fun_l0_n13(x) + if (x < 1) + fun_l1_n172(x) + else + fun_l1_n209(x) + end +end + +def fun_l0_n14(x) + if (x < 1) + fun_l1_n514(x) + else + fun_l1_n414(x) + end +end + +def fun_l0_n15(x) + if (x < 1) + fun_l1_n190(x) + else + fun_l1_n100(x) + end +end + +def fun_l0_n16(x) + if (x < 1) + fun_l1_n696(x) + else + fun_l1_n997(x) + end +end + +def fun_l0_n17(x) + if (x < 1) + fun_l1_n568(x) + else + fun_l1_n820(x) + end +end + +def fun_l0_n18(x) + if (x < 1) + fun_l1_n837(x) + else + fun_l1_n588(x) + end +end + +def fun_l0_n19(x) + if (x < 1) + fun_l1_n206(x) + else + fun_l1_n126(x) + end +end + +def fun_l0_n20(x) + if (x < 1) + fun_l1_n317(x) + else + fun_l1_n722(x) + end +end + +def fun_l0_n21(x) + if (x < 1) + fun_l1_n614(x) + else + fun_l1_n372(x) + end +end + +def fun_l0_n22(x) + if (x < 1) + fun_l1_n530(x) + else + fun_l1_n862(x) + end +end + +def fun_l0_n23(x) + if (x < 1) + fun_l1_n889(x) + else + fun_l1_n271(x) + end +end + +def fun_l0_n24(x) + if (x < 1) + fun_l1_n996(x) + else + fun_l1_n717(x) + end +end + +def fun_l0_n25(x) + if (x < 1) + fun_l1_n726(x) + else + fun_l1_n939(x) + end +end + +def fun_l0_n26(x) + if (x < 1) + fun_l1_n316(x) + else + fun_l1_n293(x) + end +end + +def fun_l0_n27(x) + if (x < 1) + fun_l1_n90(x) + else + fun_l1_n596(x) + end +end + +def fun_l0_n28(x) + if (x < 1) + fun_l1_n743(x) + else + fun_l1_n782(x) + end +end + +def fun_l0_n29(x) + if (x < 1) + fun_l1_n896(x) + else + fun_l1_n247(x) + end +end + +def fun_l0_n30(x) + if (x < 1) + fun_l1_n2(x) + else + fun_l1_n377(x) + end +end + +def fun_l0_n31(x) + if (x < 1) + fun_l1_n380(x) + else + fun_l1_n655(x) + end +end + +def fun_l0_n32(x) + if (x < 1) + fun_l1_n572(x) + else + fun_l1_n778(x) + end +end + +def fun_l0_n33(x) + if (x < 1) + fun_l1_n485(x) + else + fun_l1_n282(x) + end +end + +def fun_l0_n34(x) + if (x < 1) + fun_l1_n703(x) + else + fun_l1_n179(x) + end +end + +def fun_l0_n35(x) + if (x < 1) + fun_l1_n281(x) + else + fun_l1_n572(x) + end +end + +def fun_l0_n36(x) + if (x < 1) + fun_l1_n48(x) + else + fun_l1_n286(x) + end +end + +def fun_l0_n37(x) + if (x < 1) + fun_l1_n539(x) + else + fun_l1_n86(x) + end +end + +def fun_l0_n38(x) + if (x < 1) + fun_l1_n918(x) + else + fun_l1_n778(x) + end +end + +def fun_l0_n39(x) + if (x < 1) + fun_l1_n832(x) + else + fun_l1_n94(x) + end +end + +def fun_l0_n40(x) + if (x < 1) + fun_l1_n213(x) + else + fun_l1_n580(x) + end +end + +def fun_l0_n41(x) + if (x < 1) + fun_l1_n413(x) + else + fun_l1_n793(x) + end +end + +def fun_l0_n42(x) + if (x < 1) + fun_l1_n451(x) + else + fun_l1_n779(x) + end +end + +def fun_l0_n43(x) + if (x < 1) + fun_l1_n118(x) + else + fun_l1_n778(x) + end +end + +def fun_l0_n44(x) + if (x < 1) + fun_l1_n162(x) + else + fun_l1_n901(x) + end +end + +def fun_l0_n45(x) + if (x < 1) + fun_l1_n157(x) + else + fun_l1_n280(x) + end +end + +def fun_l0_n46(x) + if (x < 1) + fun_l1_n748(x) + else + fun_l1_n881(x) + end +end + +def fun_l0_n47(x) + if (x < 1) + fun_l1_n529(x) + else + fun_l1_n732(x) + end +end + +def fun_l0_n48(x) + if (x < 1) + fun_l1_n417(x) + else + fun_l1_n483(x) + end +end + +def fun_l0_n49(x) + if (x < 1) + fun_l1_n743(x) + else + fun_l1_n525(x) + end +end + +def fun_l0_n50(x) + if (x < 1) + fun_l1_n14(x) + else + fun_l1_n309(x) + end +end + +def fun_l0_n51(x) + if (x < 1) + fun_l1_n436(x) + else + fun_l1_n304(x) + end +end + +def fun_l0_n52(x) + if (x < 1) + fun_l1_n623(x) + else + fun_l1_n590(x) + end +end + +def fun_l0_n53(x) + if (x < 1) + fun_l1_n696(x) + else + fun_l1_n53(x) + end +end + +def fun_l0_n54(x) + if (x < 1) + fun_l1_n807(x) + else + fun_l1_n523(x) + end +end + +def fun_l0_n55(x) + if (x < 1) + fun_l1_n607(x) + else + fun_l1_n609(x) + end +end + +def fun_l0_n56(x) + if (x < 1) + fun_l1_n721(x) + else + fun_l1_n994(x) + end +end + +def fun_l0_n57(x) + if (x < 1) + fun_l1_n472(x) + else + fun_l1_n818(x) + end +end + +def fun_l0_n58(x) + if (x < 1) + fun_l1_n30(x) + else + fun_l1_n954(x) + end +end + +def fun_l0_n59(x) + if (x < 1) + fun_l1_n223(x) + else + fun_l1_n148(x) + end +end + +def fun_l0_n60(x) + if (x < 1) + fun_l1_n761(x) + else + fun_l1_n40(x) + end +end + +def fun_l0_n61(x) + if (x < 1) + fun_l1_n57(x) + else + fun_l1_n858(x) + end +end + +def fun_l0_n62(x) + if (x < 1) + fun_l1_n114(x) + else + fun_l1_n767(x) + end +end + +def fun_l0_n63(x) + if (x < 1) + fun_l1_n287(x) + else + fun_l1_n752(x) + end +end + +def fun_l0_n64(x) + if (x < 1) + fun_l1_n16(x) + else + fun_l1_n229(x) + end +end + +def fun_l0_n65(x) + if (x < 1) + fun_l1_n230(x) + else + fun_l1_n954(x) + end +end + +def fun_l0_n66(x) + if (x < 1) + fun_l1_n98(x) + else + fun_l1_n320(x) + end +end + +def fun_l0_n67(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n985(x) + end +end + +def fun_l0_n68(x) + if (x < 1) + fun_l1_n32(x) + else + fun_l1_n648(x) + end +end + +def fun_l0_n69(x) + if (x < 1) + fun_l1_n453(x) + else + fun_l1_n466(x) + end +end + +def fun_l0_n70(x) + if (x < 1) + fun_l1_n787(x) + else + fun_l1_n802(x) + end +end + +def fun_l0_n71(x) + if (x < 1) + fun_l1_n656(x) + else + fun_l1_n347(x) + end +end + +def fun_l0_n72(x) + if (x < 1) + fun_l1_n358(x) + else + fun_l1_n336(x) + end +end + +def fun_l0_n73(x) + if (x < 1) + fun_l1_n291(x) + else + fun_l1_n536(x) + end +end + +def fun_l0_n74(x) + if (x < 1) + fun_l1_n795(x) + else + fun_l1_n606(x) + end +end + +def fun_l0_n75(x) + if (x < 1) + fun_l1_n21(x) + else + fun_l1_n720(x) + end +end + +def fun_l0_n76(x) + if (x < 1) + fun_l1_n513(x) + else + fun_l1_n300(x) + end +end + +def fun_l0_n77(x) + if (x < 1) + fun_l1_n358(x) + else + fun_l1_n332(x) + end +end + +def fun_l0_n78(x) + if (x < 1) + fun_l1_n712(x) + else + fun_l1_n906(x) + end +end + +def fun_l0_n79(x) + if (x < 1) + fun_l1_n555(x) + else + fun_l1_n850(x) + end +end + +def fun_l0_n80(x) + if (x < 1) + fun_l1_n320(x) + else + fun_l1_n892(x) + end +end + +def fun_l0_n81(x) + if (x < 1) + fun_l1_n191(x) + else + fun_l1_n187(x) + end +end + +def fun_l0_n82(x) + if (x < 1) + fun_l1_n457(x) + else + fun_l1_n718(x) + end +end + +def fun_l0_n83(x) + if (x < 1) + fun_l1_n314(x) + else + fun_l1_n697(x) + end +end + +def fun_l0_n84(x) + if (x < 1) + fun_l1_n459(x) + else + fun_l1_n500(x) + end +end + +def fun_l0_n85(x) + if (x < 1) + fun_l1_n912(x) + else + fun_l1_n992(x) + end +end + +def fun_l0_n86(x) + if (x < 1) + fun_l1_n523(x) + else + fun_l1_n201(x) + end +end + +def fun_l0_n87(x) + if (x < 1) + fun_l1_n30(x) + else + fun_l1_n829(x) + end +end + +def fun_l0_n88(x) + if (x < 1) + fun_l1_n223(x) + else + fun_l1_n799(x) + end +end + +def fun_l0_n89(x) + if (x < 1) + fun_l1_n289(x) + else + fun_l1_n289(x) + end +end + +def fun_l0_n90(x) + if (x < 1) + fun_l1_n961(x) + else + fun_l1_n694(x) + end +end + +def fun_l0_n91(x) + if (x < 1) + fun_l1_n423(x) + else + fun_l1_n848(x) + end +end + +def fun_l0_n92(x) + if (x < 1) + fun_l1_n612(x) + else + fun_l1_n358(x) + end +end + +def fun_l0_n93(x) + if (x < 1) + fun_l1_n148(x) + else + fun_l1_n312(x) + end +end + +def fun_l0_n94(x) + if (x < 1) + fun_l1_n771(x) + else + fun_l1_n205(x) + end +end + +def fun_l0_n95(x) + if (x < 1) + fun_l1_n573(x) + else + fun_l1_n692(x) + end +end + +def fun_l0_n96(x) + if (x < 1) + fun_l1_n66(x) + else + fun_l1_n936(x) + end +end + +def fun_l0_n97(x) + if (x < 1) + fun_l1_n429(x) + else + fun_l1_n949(x) + end +end + +def fun_l0_n98(x) + if (x < 1) + fun_l1_n737(x) + else + fun_l1_n338(x) + end +end + +def fun_l0_n99(x) + if (x < 1) + fun_l1_n335(x) + else + fun_l1_n739(x) + end +end + +def fun_l0_n100(x) + if (x < 1) + fun_l1_n989(x) + else + fun_l1_n735(x) + end +end + +def fun_l0_n101(x) + if (x < 1) + fun_l1_n559(x) + else + fun_l1_n478(x) + end +end + +def fun_l0_n102(x) + if (x < 1) + fun_l1_n261(x) + else + fun_l1_n162(x) + end +end + +def fun_l0_n103(x) + if (x < 1) + fun_l1_n400(x) + else + fun_l1_n156(x) + end +end + +def fun_l0_n104(x) + if (x < 1) + fun_l1_n747(x) + else + fun_l1_n361(x) + end +end + +def fun_l0_n105(x) + if (x < 1) + fun_l1_n717(x) + else + fun_l1_n522(x) + end +end + +def fun_l0_n106(x) + if (x < 1) + fun_l1_n513(x) + else + fun_l1_n150(x) + end +end + +def fun_l0_n107(x) + if (x < 1) + fun_l1_n710(x) + else + fun_l1_n602(x) + end +end + +def fun_l0_n108(x) + if (x < 1) + fun_l1_n866(x) + else + fun_l1_n111(x) + end +end + +def fun_l0_n109(x) + if (x < 1) + fun_l1_n725(x) + else + fun_l1_n448(x) + end +end + +def fun_l0_n110(x) + if (x < 1) + fun_l1_n703(x) + else + fun_l1_n127(x) + end +end + +def fun_l0_n111(x) + if (x < 1) + fun_l1_n420(x) + else + fun_l1_n666(x) + end +end + +def fun_l0_n112(x) + if (x < 1) + fun_l1_n647(x) + else + fun_l1_n567(x) + end +end + +def fun_l0_n113(x) + if (x < 1) + fun_l1_n543(x) + else + fun_l1_n992(x) + end +end + +def fun_l0_n114(x) + if (x < 1) + fun_l1_n12(x) + else + fun_l1_n470(x) + end +end + +def fun_l0_n115(x) + if (x < 1) + fun_l1_n25(x) + else + fun_l1_n917(x) + end +end + +def fun_l0_n116(x) + if (x < 1) + fun_l1_n201(x) + else + fun_l1_n110(x) + end +end + +def fun_l0_n117(x) + if (x < 1) + fun_l1_n222(x) + else + fun_l1_n747(x) + end +end + +def fun_l0_n118(x) + if (x < 1) + fun_l1_n990(x) + else + fun_l1_n794(x) + end +end + +def fun_l0_n119(x) + if (x < 1) + fun_l1_n712(x) + else + fun_l1_n5(x) + end +end + +def fun_l0_n120(x) + if (x < 1) + fun_l1_n28(x) + else + fun_l1_n89(x) + end +end + +def fun_l0_n121(x) + if (x < 1) + fun_l1_n341(x) + else + fun_l1_n983(x) + end +end + +def fun_l0_n122(x) + if (x < 1) + fun_l1_n123(x) + else + fun_l1_n452(x) + end +end + +def fun_l0_n123(x) + if (x < 1) + fun_l1_n514(x) + else + fun_l1_n949(x) + end +end + +def fun_l0_n124(x) + if (x < 1) + fun_l1_n280(x) + else + fun_l1_n281(x) + end +end + +def fun_l0_n125(x) + if (x < 1) + fun_l1_n512(x) + else + fun_l1_n772(x) + end +end + +def fun_l0_n126(x) + if (x < 1) + fun_l1_n911(x) + else + fun_l1_n693(x) + end +end + +def fun_l0_n127(x) + if (x < 1) + fun_l1_n633(x) + else + fun_l1_n574(x) + end +end + +def fun_l0_n128(x) + if (x < 1) + fun_l1_n318(x) + else + fun_l1_n266(x) + end +end + +def fun_l0_n129(x) + if (x < 1) + fun_l1_n677(x) + else + fun_l1_n10(x) + end +end + +def fun_l0_n130(x) + if (x < 1) + fun_l1_n994(x) + else + fun_l1_n48(x) + end +end + +def fun_l0_n131(x) + if (x < 1) + fun_l1_n335(x) + else + fun_l1_n473(x) + end +end + +def fun_l0_n132(x) + if (x < 1) + fun_l1_n641(x) + else + fun_l1_n48(x) + end +end + +def fun_l0_n133(x) + if (x < 1) + fun_l1_n914(x) + else + fun_l1_n818(x) + end +end + +def fun_l0_n134(x) + if (x < 1) + fun_l1_n479(x) + else + fun_l1_n761(x) + end +end + +def fun_l0_n135(x) + if (x < 1) + fun_l1_n186(x) + else + fun_l1_n692(x) + end +end + +def fun_l0_n136(x) + if (x < 1) + fun_l1_n325(x) + else + fun_l1_n279(x) + end +end + +def fun_l0_n137(x) + if (x < 1) + fun_l1_n493(x) + else + fun_l1_n293(x) + end +end + +def fun_l0_n138(x) + if (x < 1) + fun_l1_n788(x) + else + fun_l1_n364(x) + end +end + +def fun_l0_n139(x) + if (x < 1) + fun_l1_n565(x) + else + fun_l1_n63(x) + end +end + +def fun_l0_n140(x) + if (x < 1) + fun_l1_n128(x) + else + fun_l1_n299(x) + end +end + +def fun_l0_n141(x) + if (x < 1) + fun_l1_n782(x) + else + fun_l1_n195(x) + end +end + +def fun_l0_n142(x) + if (x < 1) + fun_l1_n696(x) + else + fun_l1_n117(x) + end +end + +def fun_l0_n143(x) + if (x < 1) + fun_l1_n263(x) + else + fun_l1_n683(x) + end +end + +def fun_l0_n144(x) + if (x < 1) + fun_l1_n633(x) + else + fun_l1_n92(x) + end +end + +def fun_l0_n145(x) + if (x < 1) + fun_l1_n626(x) + else + fun_l1_n201(x) + end +end + +def fun_l0_n146(x) + if (x < 1) + fun_l1_n296(x) + else + fun_l1_n425(x) + end +end + +def fun_l0_n147(x) + if (x < 1) + fun_l1_n395(x) + else + fun_l1_n750(x) + end +end + +def fun_l0_n148(x) + if (x < 1) + fun_l1_n164(x) + else + fun_l1_n580(x) + end +end + +def fun_l0_n149(x) + if (x < 1) + fun_l1_n904(x) + else + fun_l1_n264(x) + end +end + +def fun_l0_n150(x) + if (x < 1) + fun_l1_n383(x) + else + fun_l1_n558(x) + end +end + +def fun_l0_n151(x) + if (x < 1) + fun_l1_n522(x) + else + fun_l1_n735(x) + end +end + +def fun_l0_n152(x) + if (x < 1) + fun_l1_n496(x) + else + fun_l1_n562(x) + end +end + +def fun_l0_n153(x) + if (x < 1) + fun_l1_n374(x) + else + fun_l1_n561(x) + end +end + +def fun_l0_n154(x) + if (x < 1) + fun_l1_n314(x) + else + fun_l1_n368(x) + end +end + +def fun_l0_n155(x) + if (x < 1) + fun_l1_n456(x) + else + fun_l1_n189(x) + end +end + +def fun_l0_n156(x) + if (x < 1) + fun_l1_n46(x) + else + fun_l1_n620(x) + end +end + +def fun_l0_n157(x) + if (x < 1) + fun_l1_n259(x) + else + fun_l1_n742(x) + end +end + +def fun_l0_n158(x) + if (x < 1) + fun_l1_n881(x) + else + fun_l1_n786(x) + end +end + +def fun_l0_n159(x) + if (x < 1) + fun_l1_n607(x) + else + fun_l1_n177(x) + end +end + +def fun_l0_n160(x) + if (x < 1) + fun_l1_n824(x) + else + fun_l1_n415(x) + end +end + +def fun_l0_n161(x) + if (x < 1) + fun_l1_n443(x) + else + fun_l1_n787(x) + end +end + +def fun_l0_n162(x) + if (x < 1) + fun_l1_n124(x) + else + fun_l1_n529(x) + end +end + +def fun_l0_n163(x) + if (x < 1) + fun_l1_n696(x) + else + fun_l1_n96(x) + end +end + +def fun_l0_n164(x) + if (x < 1) + fun_l1_n775(x) + else + fun_l1_n549(x) + end +end + +def fun_l0_n165(x) + if (x < 1) + fun_l1_n860(x) + else + fun_l1_n212(x) + end +end + +def fun_l0_n166(x) + if (x < 1) + fun_l1_n378(x) + else + fun_l1_n904(x) + end +end + +def fun_l0_n167(x) + if (x < 1) + fun_l1_n15(x) + else + fun_l1_n640(x) + end +end + +def fun_l0_n168(x) + if (x < 1) + fun_l1_n771(x) + else + fun_l1_n861(x) + end +end + +def fun_l0_n169(x) + if (x < 1) + fun_l1_n468(x) + else + fun_l1_n586(x) + end +end + +def fun_l0_n170(x) + if (x < 1) + fun_l1_n477(x) + else + fun_l1_n674(x) + end +end + +def fun_l0_n171(x) + if (x < 1) + fun_l1_n509(x) + else + fun_l1_n64(x) + end +end + +def fun_l0_n172(x) + if (x < 1) + fun_l1_n612(x) + else + fun_l1_n828(x) + end +end + +def fun_l0_n173(x) + if (x < 1) + fun_l1_n440(x) + else + fun_l1_n204(x) + end +end + +def fun_l0_n174(x) + if (x < 1) + fun_l1_n259(x) + else + fun_l1_n947(x) + end +end + +def fun_l0_n175(x) + if (x < 1) + fun_l1_n402(x) + else + fun_l1_n588(x) + end +end + +def fun_l0_n176(x) + if (x < 1) + fun_l1_n245(x) + else + fun_l1_n540(x) + end +end + +def fun_l0_n177(x) + if (x < 1) + fun_l1_n869(x) + else + fun_l1_n249(x) + end +end + +def fun_l0_n178(x) + if (x < 1) + fun_l1_n830(x) + else + fun_l1_n210(x) + end +end + +def fun_l0_n179(x) + if (x < 1) + fun_l1_n692(x) + else + fun_l1_n222(x) + end +end + +def fun_l0_n180(x) + if (x < 1) + fun_l1_n220(x) + else + fun_l1_n281(x) + end +end + +def fun_l0_n181(x) + if (x < 1) + fun_l1_n523(x) + else + fun_l1_n618(x) + end +end + +def fun_l0_n182(x) + if (x < 1) + fun_l1_n44(x) + else + fun_l1_n422(x) + end +end + +def fun_l0_n183(x) + if (x < 1) + fun_l1_n944(x) + else + fun_l1_n230(x) + end +end + +def fun_l0_n184(x) + if (x < 1) + fun_l1_n678(x) + else + fun_l1_n121(x) + end +end + +def fun_l0_n185(x) + if (x < 1) + fun_l1_n73(x) + else + fun_l1_n398(x) + end +end + +def fun_l0_n186(x) + if (x < 1) + fun_l1_n121(x) + else + fun_l1_n689(x) + end +end + +def fun_l0_n187(x) + if (x < 1) + fun_l1_n946(x) + else + fun_l1_n613(x) + end +end + +def fun_l0_n188(x) + if (x < 1) + fun_l1_n987(x) + else + fun_l1_n785(x) + end +end + +def fun_l0_n189(x) + if (x < 1) + fun_l1_n181(x) + else + fun_l1_n644(x) + end +end + +def fun_l0_n190(x) + if (x < 1) + fun_l1_n623(x) + else + fun_l1_n679(x) + end +end + +def fun_l0_n191(x) + if (x < 1) + fun_l1_n784(x) + else + fun_l1_n274(x) + end +end + +def fun_l0_n192(x) + if (x < 1) + fun_l1_n71(x) + else + fun_l1_n773(x) + end +end + +def fun_l0_n193(x) + if (x < 1) + fun_l1_n516(x) + else + fun_l1_n496(x) + end +end + +def fun_l0_n194(x) + if (x < 1) + fun_l1_n608(x) + else + fun_l1_n460(x) + end +end + +def fun_l0_n195(x) + if (x < 1) + fun_l1_n25(x) + else + fun_l1_n437(x) + end +end + +def fun_l0_n196(x) + if (x < 1) + fun_l1_n410(x) + else + fun_l1_n674(x) + end +end + +def fun_l0_n197(x) + if (x < 1) + fun_l1_n949(x) + else + fun_l1_n708(x) + end +end + +def fun_l0_n198(x) + if (x < 1) + fun_l1_n714(x) + else + fun_l1_n119(x) + end +end + +def fun_l0_n199(x) + if (x < 1) + fun_l1_n41(x) + else + fun_l1_n865(x) + end +end + +def fun_l0_n200(x) + if (x < 1) + fun_l1_n383(x) + else + fun_l1_n90(x) + end +end + +def fun_l0_n201(x) + if (x < 1) + fun_l1_n581(x) + else + fun_l1_n273(x) + end +end + +def fun_l0_n202(x) + if (x < 1) + fun_l1_n350(x) + else + fun_l1_n425(x) + end +end + +def fun_l0_n203(x) + if (x < 1) + fun_l1_n259(x) + else + fun_l1_n922(x) + end +end + +def fun_l0_n204(x) + if (x < 1) + fun_l1_n448(x) + else + fun_l1_n741(x) + end +end + +def fun_l0_n205(x) + if (x < 1) + fun_l1_n86(x) + else + fun_l1_n618(x) + end +end + +def fun_l0_n206(x) + if (x < 1) + fun_l1_n412(x) + else + fun_l1_n646(x) + end +end + +def fun_l0_n207(x) + if (x < 1) + fun_l1_n196(x) + else + fun_l1_n496(x) + end +end + +def fun_l0_n208(x) + if (x < 1) + fun_l1_n777(x) + else + fun_l1_n150(x) + end +end + +def fun_l0_n209(x) + if (x < 1) + fun_l1_n20(x) + else + fun_l1_n718(x) + end +end + +def fun_l0_n210(x) + if (x < 1) + fun_l1_n934(x) + else + fun_l1_n416(x) + end +end + +def fun_l0_n211(x) + if (x < 1) + fun_l1_n803(x) + else + fun_l1_n636(x) + end +end + +def fun_l0_n212(x) + if (x < 1) + fun_l1_n93(x) + else + fun_l1_n791(x) + end +end + +def fun_l0_n213(x) + if (x < 1) + fun_l1_n76(x) + else + fun_l1_n172(x) + end +end + +def fun_l0_n214(x) + if (x < 1) + fun_l1_n103(x) + else + fun_l1_n381(x) + end +end + +def fun_l0_n215(x) + if (x < 1) + fun_l1_n433(x) + else + fun_l1_n349(x) + end +end + +def fun_l0_n216(x) + if (x < 1) + fun_l1_n154(x) + else + fun_l1_n740(x) + end +end + +def fun_l0_n217(x) + if (x < 1) + fun_l1_n927(x) + else + fun_l1_n886(x) + end +end + +def fun_l0_n218(x) + if (x < 1) + fun_l1_n804(x) + else + fun_l1_n6(x) + end +end + +def fun_l0_n219(x) + if (x < 1) + fun_l1_n921(x) + else + fun_l1_n121(x) + end +end + +def fun_l0_n220(x) + if (x < 1) + fun_l1_n732(x) + else + fun_l1_n224(x) + end +end + +def fun_l0_n221(x) + if (x < 1) + fun_l1_n818(x) + else + fun_l1_n105(x) + end +end + +def fun_l0_n222(x) + if (x < 1) + fun_l1_n162(x) + else + fun_l1_n700(x) + end +end + +def fun_l0_n223(x) + if (x < 1) + fun_l1_n57(x) + else + fun_l1_n734(x) + end +end + +def fun_l0_n224(x) + if (x < 1) + fun_l1_n283(x) + else + fun_l1_n87(x) + end +end + +def fun_l0_n225(x) + if (x < 1) + fun_l1_n623(x) + else + fun_l1_n363(x) + end +end + +def fun_l0_n226(x) + if (x < 1) + fun_l1_n962(x) + else + fun_l1_n660(x) + end +end + +def fun_l0_n227(x) + if (x < 1) + fun_l1_n255(x) + else + fun_l1_n536(x) + end +end + +def fun_l0_n228(x) + if (x < 1) + fun_l1_n377(x) + else + fun_l1_n249(x) + end +end + +def fun_l0_n229(x) + if (x < 1) + fun_l1_n527(x) + else + fun_l1_n691(x) + end +end + +def fun_l0_n230(x) + if (x < 1) + fun_l1_n781(x) + else + fun_l1_n494(x) + end +end + +def fun_l0_n231(x) + if (x < 1) + fun_l1_n889(x) + else + fun_l1_n967(x) + end +end + +def fun_l0_n232(x) + if (x < 1) + fun_l1_n509(x) + else + fun_l1_n910(x) + end +end + +def fun_l0_n233(x) + if (x < 1) + fun_l1_n354(x) + else + fun_l1_n5(x) + end +end + +def fun_l0_n234(x) + if (x < 1) + fun_l1_n423(x) + else + fun_l1_n788(x) + end +end + +def fun_l0_n235(x) + if (x < 1) + fun_l1_n632(x) + else + fun_l1_n705(x) + end +end + +def fun_l0_n236(x) + if (x < 1) + fun_l1_n955(x) + else + fun_l1_n908(x) + end +end + +def fun_l0_n237(x) + if (x < 1) + fun_l1_n329(x) + else + fun_l1_n2(x) + end +end + +def fun_l0_n238(x) + if (x < 1) + fun_l1_n767(x) + else + fun_l1_n766(x) + end +end + +def fun_l0_n239(x) + if (x < 1) + fun_l1_n304(x) + else + fun_l1_n507(x) + end +end + +def fun_l0_n240(x) + if (x < 1) + fun_l1_n845(x) + else + fun_l1_n777(x) + end +end + +def fun_l0_n241(x) + if (x < 1) + fun_l1_n69(x) + else + fun_l1_n260(x) + end +end + +def fun_l0_n242(x) + if (x < 1) + fun_l1_n194(x) + else + fun_l1_n412(x) + end +end + +def fun_l0_n243(x) + if (x < 1) + fun_l1_n974(x) + else + fun_l1_n922(x) + end +end + +def fun_l0_n244(x) + if (x < 1) + fun_l1_n532(x) + else + fun_l1_n530(x) + end +end + +def fun_l0_n245(x) + if (x < 1) + fun_l1_n554(x) + else + fun_l1_n656(x) + end +end + +def fun_l0_n246(x) + if (x < 1) + fun_l1_n253(x) + else + fun_l1_n235(x) + end +end + +def fun_l0_n247(x) + if (x < 1) + fun_l1_n754(x) + else + fun_l1_n775(x) + end +end + +def fun_l0_n248(x) + if (x < 1) + fun_l1_n89(x) + else + fun_l1_n129(x) + end +end + +def fun_l0_n249(x) + if (x < 1) + fun_l1_n284(x) + else + fun_l1_n642(x) + end +end + +def fun_l0_n250(x) + if (x < 1) + fun_l1_n67(x) + else + fun_l1_n867(x) + end +end + +def fun_l0_n251(x) + if (x < 1) + fun_l1_n926(x) + else + fun_l1_n442(x) + end +end + +def fun_l0_n252(x) + if (x < 1) + fun_l1_n196(x) + else + fun_l1_n583(x) + end +end + +def fun_l0_n253(x) + if (x < 1) + fun_l1_n966(x) + else + fun_l1_n810(x) + end +end + +def fun_l0_n254(x) + if (x < 1) + fun_l1_n984(x) + else + fun_l1_n752(x) + end +end + +def fun_l0_n255(x) + if (x < 1) + fun_l1_n941(x) + else + fun_l1_n744(x) + end +end + +def fun_l0_n256(x) + if (x < 1) + fun_l1_n785(x) + else + fun_l1_n610(x) + end +end + +def fun_l0_n257(x) + if (x < 1) + fun_l1_n622(x) + else + fun_l1_n730(x) + end +end + +def fun_l0_n258(x) + if (x < 1) + fun_l1_n453(x) + else + fun_l1_n641(x) + end +end + +def fun_l0_n259(x) + if (x < 1) + fun_l1_n407(x) + else + fun_l1_n818(x) + end +end + +def fun_l0_n260(x) + if (x < 1) + fun_l1_n252(x) + else + fun_l1_n205(x) + end +end + +def fun_l0_n261(x) + if (x < 1) + fun_l1_n940(x) + else + fun_l1_n678(x) + end +end + +def fun_l0_n262(x) + if (x < 1) + fun_l1_n350(x) + else + fun_l1_n496(x) + end +end + +def fun_l0_n263(x) + if (x < 1) + fun_l1_n688(x) + else + fun_l1_n193(x) + end +end + +def fun_l0_n264(x) + if (x < 1) + fun_l1_n366(x) + else + fun_l1_n790(x) + end +end + +def fun_l0_n265(x) + if (x < 1) + fun_l1_n592(x) + else + fun_l1_n93(x) + end +end + +def fun_l0_n266(x) + if (x < 1) + fun_l1_n189(x) + else + fun_l1_n467(x) + end +end + +def fun_l0_n267(x) + if (x < 1) + fun_l1_n813(x) + else + fun_l1_n7(x) + end +end + +def fun_l0_n268(x) + if (x < 1) + fun_l1_n516(x) + else + fun_l1_n271(x) + end +end + +def fun_l0_n269(x) + if (x < 1) + fun_l1_n0(x) + else + fun_l1_n121(x) + end +end + +def fun_l0_n270(x) + if (x < 1) + fun_l1_n634(x) + else + fun_l1_n726(x) + end +end + +def fun_l0_n271(x) + if (x < 1) + fun_l1_n192(x) + else + fun_l1_n468(x) + end +end + +def fun_l0_n272(x) + if (x < 1) + fun_l1_n278(x) + else + fun_l1_n355(x) + end +end + +def fun_l0_n273(x) + if (x < 1) + fun_l1_n354(x) + else + fun_l1_n87(x) + end +end + +def fun_l0_n274(x) + if (x < 1) + fun_l1_n643(x) + else + fun_l1_n806(x) + end +end + +def fun_l0_n275(x) + if (x < 1) + fun_l1_n389(x) + else + fun_l1_n559(x) + end +end + +def fun_l0_n276(x) + if (x < 1) + fun_l1_n283(x) + else + fun_l1_n539(x) + end +end + +def fun_l0_n277(x) + if (x < 1) + fun_l1_n0(x) + else + fun_l1_n351(x) + end +end + +def fun_l0_n278(x) + if (x < 1) + fun_l1_n813(x) + else + fun_l1_n513(x) + end +end + +def fun_l0_n279(x) + if (x < 1) + fun_l1_n501(x) + else + fun_l1_n967(x) + end +end + +def fun_l0_n280(x) + if (x < 1) + fun_l1_n727(x) + else + fun_l1_n232(x) + end +end + +def fun_l0_n281(x) + if (x < 1) + fun_l1_n946(x) + else + fun_l1_n693(x) + end +end + +def fun_l0_n282(x) + if (x < 1) + fun_l1_n260(x) + else + fun_l1_n525(x) + end +end + +def fun_l0_n283(x) + if (x < 1) + fun_l1_n957(x) + else + fun_l1_n817(x) + end +end + +def fun_l0_n284(x) + if (x < 1) + fun_l1_n91(x) + else + fun_l1_n735(x) + end +end + +def fun_l0_n285(x) + if (x < 1) + fun_l1_n71(x) + else + fun_l1_n24(x) + end +end + +def fun_l0_n286(x) + if (x < 1) + fun_l1_n594(x) + else + fun_l1_n747(x) + end +end + +def fun_l0_n287(x) + if (x < 1) + fun_l1_n869(x) + else + fun_l1_n414(x) + end +end + +def fun_l0_n288(x) + if (x < 1) + fun_l1_n182(x) + else + fun_l1_n835(x) + end +end + +def fun_l0_n289(x) + if (x < 1) + fun_l1_n188(x) + else + fun_l1_n949(x) + end +end + +def fun_l0_n290(x) + if (x < 1) + fun_l1_n35(x) + else + fun_l1_n259(x) + end +end + +def fun_l0_n291(x) + if (x < 1) + fun_l1_n593(x) + else + fun_l1_n810(x) + end +end + +def fun_l0_n292(x) + if (x < 1) + fun_l1_n680(x) + else + fun_l1_n564(x) + end +end + +def fun_l0_n293(x) + if (x < 1) + fun_l1_n57(x) + else + fun_l1_n91(x) + end +end + +def fun_l0_n294(x) + if (x < 1) + fun_l1_n945(x) + else + fun_l1_n807(x) + end +end + +def fun_l0_n295(x) + if (x < 1) + fun_l1_n442(x) + else + fun_l1_n123(x) + end +end + +def fun_l0_n296(x) + if (x < 1) + fun_l1_n536(x) + else + fun_l1_n987(x) + end +end + +def fun_l0_n297(x) + if (x < 1) + fun_l1_n519(x) + else + fun_l1_n657(x) + end +end + +def fun_l0_n298(x) + if (x < 1) + fun_l1_n204(x) + else + fun_l1_n437(x) + end +end + +def fun_l0_n299(x) + if (x < 1) + fun_l1_n289(x) + else + fun_l1_n385(x) + end +end + +def fun_l0_n300(x) + if (x < 1) + fun_l1_n629(x) + else + fun_l1_n803(x) + end +end + +def fun_l0_n301(x) + if (x < 1) + fun_l1_n576(x) + else + fun_l1_n921(x) + end +end + +def fun_l0_n302(x) + if (x < 1) + fun_l1_n466(x) + else + fun_l1_n475(x) + end +end + +def fun_l0_n303(x) + if (x < 1) + fun_l1_n658(x) + else + fun_l1_n333(x) + end +end + +def fun_l0_n304(x) + if (x < 1) + fun_l1_n728(x) + else + fun_l1_n749(x) + end +end + +def fun_l0_n305(x) + if (x < 1) + fun_l1_n68(x) + else + fun_l1_n552(x) + end +end + +def fun_l0_n306(x) + if (x < 1) + fun_l1_n633(x) + else + fun_l1_n958(x) + end +end + +def fun_l0_n307(x) + if (x < 1) + fun_l1_n79(x) + else + fun_l1_n386(x) + end +end + +def fun_l0_n308(x) + if (x < 1) + fun_l1_n831(x) + else + fun_l1_n176(x) + end +end + +def fun_l0_n309(x) + if (x < 1) + fun_l1_n770(x) + else + fun_l1_n334(x) + end +end + +def fun_l0_n310(x) + if (x < 1) + fun_l1_n21(x) + else + fun_l1_n643(x) + end +end + +def fun_l0_n311(x) + if (x < 1) + fun_l1_n673(x) + else + fun_l1_n298(x) + end +end + +def fun_l0_n312(x) + if (x < 1) + fun_l1_n753(x) + else + fun_l1_n817(x) + end +end + +def fun_l0_n313(x) + if (x < 1) + fun_l1_n299(x) + else + fun_l1_n350(x) + end +end + +def fun_l0_n314(x) + if (x < 1) + fun_l1_n190(x) + else + fun_l1_n519(x) + end +end + +def fun_l0_n315(x) + if (x < 1) + fun_l1_n934(x) + else + fun_l1_n416(x) + end +end + +def fun_l0_n316(x) + if (x < 1) + fun_l1_n695(x) + else + fun_l1_n377(x) + end +end + +def fun_l0_n317(x) + if (x < 1) + fun_l1_n194(x) + else + fun_l1_n747(x) + end +end + +def fun_l0_n318(x) + if (x < 1) + fun_l1_n145(x) + else + fun_l1_n761(x) + end +end + +def fun_l0_n319(x) + if (x < 1) + fun_l1_n223(x) + else + fun_l1_n237(x) + end +end + +def fun_l0_n320(x) + if (x < 1) + fun_l1_n907(x) + else + fun_l1_n653(x) + end +end + +def fun_l0_n321(x) + if (x < 1) + fun_l1_n216(x) + else + fun_l1_n67(x) + end +end + +def fun_l0_n322(x) + if (x < 1) + fun_l1_n658(x) + else + fun_l1_n948(x) + end +end + +def fun_l0_n323(x) + if (x < 1) + fun_l1_n358(x) + else + fun_l1_n926(x) + end +end + +def fun_l0_n324(x) + if (x < 1) + fun_l1_n533(x) + else + fun_l1_n252(x) + end +end + +def fun_l0_n325(x) + if (x < 1) + fun_l1_n284(x) + else + fun_l1_n670(x) + end +end + +def fun_l0_n326(x) + if (x < 1) + fun_l1_n327(x) + else + fun_l1_n298(x) + end +end + +def fun_l0_n327(x) + if (x < 1) + fun_l1_n837(x) + else + fun_l1_n890(x) + end +end + +def fun_l0_n328(x) + if (x < 1) + fun_l1_n941(x) + else + fun_l1_n794(x) + end +end + +def fun_l0_n329(x) + if (x < 1) + fun_l1_n859(x) + else + fun_l1_n970(x) + end +end + +def fun_l0_n330(x) + if (x < 1) + fun_l1_n282(x) + else + fun_l1_n569(x) + end +end + +def fun_l0_n331(x) + if (x < 1) + fun_l1_n33(x) + else + fun_l1_n525(x) + end +end + +def fun_l0_n332(x) + if (x < 1) + fun_l1_n847(x) + else + fun_l1_n540(x) + end +end + +def fun_l0_n333(x) + if (x < 1) + fun_l1_n485(x) + else + fun_l1_n756(x) + end +end + +def fun_l0_n334(x) + if (x < 1) + fun_l1_n396(x) + else + fun_l1_n781(x) + end +end + +def fun_l0_n335(x) + if (x < 1) + fun_l1_n225(x) + else + fun_l1_n417(x) + end +end + +def fun_l0_n336(x) + if (x < 1) + fun_l1_n906(x) + else + fun_l1_n301(x) + end +end + +def fun_l0_n337(x) + if (x < 1) + fun_l1_n863(x) + else + fun_l1_n409(x) + end +end + +def fun_l0_n338(x) + if (x < 1) + fun_l1_n103(x) + else + fun_l1_n460(x) + end +end + +def fun_l0_n339(x) + if (x < 1) + fun_l1_n787(x) + else + fun_l1_n434(x) + end +end + +def fun_l0_n340(x) + if (x < 1) + fun_l1_n308(x) + else + fun_l1_n875(x) + end +end + +def fun_l0_n341(x) + if (x < 1) + fun_l1_n146(x) + else + fun_l1_n566(x) + end +end + +def fun_l0_n342(x) + if (x < 1) + fun_l1_n837(x) + else + fun_l1_n770(x) + end +end + +def fun_l0_n343(x) + if (x < 1) + fun_l1_n668(x) + else + fun_l1_n60(x) + end +end + +def fun_l0_n344(x) + if (x < 1) + fun_l1_n305(x) + else + fun_l1_n388(x) + end +end + +def fun_l0_n345(x) + if (x < 1) + fun_l1_n796(x) + else + fun_l1_n920(x) + end +end + +def fun_l0_n346(x) + if (x < 1) + fun_l1_n257(x) + else + fun_l1_n229(x) + end +end + +def fun_l0_n347(x) + if (x < 1) + fun_l1_n740(x) + else + fun_l1_n372(x) + end +end + +def fun_l0_n348(x) + if (x < 1) + fun_l1_n698(x) + else + fun_l1_n63(x) + end +end + +def fun_l0_n349(x) + if (x < 1) + fun_l1_n4(x) + else + fun_l1_n119(x) + end +end + +def fun_l0_n350(x) + if (x < 1) + fun_l1_n186(x) + else + fun_l1_n352(x) + end +end + +def fun_l0_n351(x) + if (x < 1) + fun_l1_n619(x) + else + fun_l1_n583(x) + end +end + +def fun_l0_n352(x) + if (x < 1) + fun_l1_n2(x) + else + fun_l1_n275(x) + end +end + +def fun_l0_n353(x) + if (x < 1) + fun_l1_n843(x) + else + fun_l1_n986(x) + end +end + +def fun_l0_n354(x) + if (x < 1) + fun_l1_n865(x) + else + fun_l1_n64(x) + end +end + +def fun_l0_n355(x) + if (x < 1) + fun_l1_n732(x) + else + fun_l1_n332(x) + end +end + +def fun_l0_n356(x) + if (x < 1) + fun_l1_n642(x) + else + fun_l1_n559(x) + end +end + +def fun_l0_n357(x) + if (x < 1) + fun_l1_n385(x) + else + fun_l1_n532(x) + end +end + +def fun_l0_n358(x) + if (x < 1) + fun_l1_n672(x) + else + fun_l1_n721(x) + end +end + +def fun_l0_n359(x) + if (x < 1) + fun_l1_n663(x) + else + fun_l1_n590(x) + end +end + +def fun_l0_n360(x) + if (x < 1) + fun_l1_n240(x) + else + fun_l1_n743(x) + end +end + +def fun_l0_n361(x) + if (x < 1) + fun_l1_n301(x) + else + fun_l1_n943(x) + end +end + +def fun_l0_n362(x) + if (x < 1) + fun_l1_n108(x) + else + fun_l1_n975(x) + end +end + +def fun_l0_n363(x) + if (x < 1) + fun_l1_n554(x) + else + fun_l1_n135(x) + end +end + +def fun_l0_n364(x) + if (x < 1) + fun_l1_n360(x) + else + fun_l1_n821(x) + end +end + +def fun_l0_n365(x) + if (x < 1) + fun_l1_n992(x) + else + fun_l1_n158(x) + end +end + +def fun_l0_n366(x) + if (x < 1) + fun_l1_n439(x) + else + fun_l1_n506(x) + end +end + +def fun_l0_n367(x) + if (x < 1) + fun_l1_n229(x) + else + fun_l1_n714(x) + end +end + +def fun_l0_n368(x) + if (x < 1) + fun_l1_n459(x) + else + fun_l1_n874(x) + end +end + +def fun_l0_n369(x) + if (x < 1) + fun_l1_n799(x) + else + fun_l1_n406(x) + end +end + +def fun_l0_n370(x) + if (x < 1) + fun_l1_n791(x) + else + fun_l1_n669(x) + end +end + +def fun_l0_n371(x) + if (x < 1) + fun_l1_n99(x) + else + fun_l1_n344(x) + end +end + +def fun_l0_n372(x) + if (x < 1) + fun_l1_n585(x) + else + fun_l1_n388(x) + end +end + +def fun_l0_n373(x) + if (x < 1) + fun_l1_n35(x) + else + fun_l1_n369(x) + end +end + +def fun_l0_n374(x) + if (x < 1) + fun_l1_n41(x) + else + fun_l1_n378(x) + end +end + +def fun_l0_n375(x) + if (x < 1) + fun_l1_n372(x) + else + fun_l1_n406(x) + end +end + +def fun_l0_n376(x) + if (x < 1) + fun_l1_n247(x) + else + fun_l1_n563(x) + end +end + +def fun_l0_n377(x) + if (x < 1) + fun_l1_n998(x) + else + fun_l1_n302(x) + end +end + +def fun_l0_n378(x) + if (x < 1) + fun_l1_n955(x) + else + fun_l1_n333(x) + end +end + +def fun_l0_n379(x) + if (x < 1) + fun_l1_n554(x) + else + fun_l1_n863(x) + end +end + +def fun_l0_n380(x) + if (x < 1) + fun_l1_n248(x) + else + fun_l1_n297(x) + end +end + +def fun_l0_n381(x) + if (x < 1) + fun_l1_n85(x) + else + fun_l1_n726(x) + end +end + +def fun_l0_n382(x) + if (x < 1) + fun_l1_n75(x) + else + fun_l1_n990(x) + end +end + +def fun_l0_n383(x) + if (x < 1) + fun_l1_n353(x) + else + fun_l1_n218(x) + end +end + +def fun_l0_n384(x) + if (x < 1) + fun_l1_n103(x) + else + fun_l1_n192(x) + end +end + +def fun_l0_n385(x) + if (x < 1) + fun_l1_n659(x) + else + fun_l1_n996(x) + end +end + +def fun_l0_n386(x) + if (x < 1) + fun_l1_n528(x) + else + fun_l1_n654(x) + end +end + +def fun_l0_n387(x) + if (x < 1) + fun_l1_n857(x) + else + fun_l1_n638(x) + end +end + +def fun_l0_n388(x) + if (x < 1) + fun_l1_n311(x) + else + fun_l1_n877(x) + end +end + +def fun_l0_n389(x) + if (x < 1) + fun_l1_n406(x) + else + fun_l1_n191(x) + end +end + +def fun_l0_n390(x) + if (x < 1) + fun_l1_n464(x) + else + fun_l1_n684(x) + end +end + +def fun_l0_n391(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n635(x) + end +end + +def fun_l0_n392(x) + if (x < 1) + fun_l1_n863(x) + else + fun_l1_n486(x) + end +end + +def fun_l0_n393(x) + if (x < 1) + fun_l1_n587(x) + else + fun_l1_n387(x) + end +end + +def fun_l0_n394(x) + if (x < 1) + fun_l1_n553(x) + else + fun_l1_n789(x) + end +end + +def fun_l0_n395(x) + if (x < 1) + fun_l1_n420(x) + else + fun_l1_n148(x) + end +end + +def fun_l0_n396(x) + if (x < 1) + fun_l1_n802(x) + else + fun_l1_n845(x) + end +end + +def fun_l0_n397(x) + if (x < 1) + fun_l1_n749(x) + else + fun_l1_n742(x) + end +end + +def fun_l0_n398(x) + if (x < 1) + fun_l1_n929(x) + else + fun_l1_n458(x) + end +end + +def fun_l0_n399(x) + if (x < 1) + fun_l1_n908(x) + else + fun_l1_n188(x) + end +end + +def fun_l0_n400(x) + if (x < 1) + fun_l1_n932(x) + else + fun_l1_n854(x) + end +end + +def fun_l0_n401(x) + if (x < 1) + fun_l1_n29(x) + else + fun_l1_n666(x) + end +end + +def fun_l0_n402(x) + if (x < 1) + fun_l1_n877(x) + else + fun_l1_n518(x) + end +end + +def fun_l0_n403(x) + if (x < 1) + fun_l1_n639(x) + else + fun_l1_n618(x) + end +end + +def fun_l0_n404(x) + if (x < 1) + fun_l1_n177(x) + else + fun_l1_n487(x) + end +end + +def fun_l0_n405(x) + if (x < 1) + fun_l1_n536(x) + else + fun_l1_n860(x) + end +end + +def fun_l0_n406(x) + if (x < 1) + fun_l1_n626(x) + else + fun_l1_n894(x) + end +end + +def fun_l0_n407(x) + if (x < 1) + fun_l1_n533(x) + else + fun_l1_n367(x) + end +end + +def fun_l0_n408(x) + if (x < 1) + fun_l1_n146(x) + else + fun_l1_n546(x) + end +end + +def fun_l0_n409(x) + if (x < 1) + fun_l1_n872(x) + else + fun_l1_n387(x) + end +end + +def fun_l0_n410(x) + if (x < 1) + fun_l1_n726(x) + else + fun_l1_n973(x) + end +end + +def fun_l0_n411(x) + if (x < 1) + fun_l1_n168(x) + else + fun_l1_n783(x) + end +end + +def fun_l0_n412(x) + if (x < 1) + fun_l1_n895(x) + else + fun_l1_n901(x) + end +end + +def fun_l0_n413(x) + if (x < 1) + fun_l1_n235(x) + else + fun_l1_n593(x) + end +end + +def fun_l0_n414(x) + if (x < 1) + fun_l1_n328(x) + else + fun_l1_n693(x) + end +end + +def fun_l0_n415(x) + if (x < 1) + fun_l1_n882(x) + else + fun_l1_n290(x) + end +end + +def fun_l0_n416(x) + if (x < 1) + fun_l1_n433(x) + else + fun_l1_n220(x) + end +end + +def fun_l0_n417(x) + if (x < 1) + fun_l1_n966(x) + else + fun_l1_n74(x) + end +end + +def fun_l0_n418(x) + if (x < 1) + fun_l1_n750(x) + else + fun_l1_n547(x) + end +end + +def fun_l0_n419(x) + if (x < 1) + fun_l1_n94(x) + else + fun_l1_n794(x) + end +end + +def fun_l0_n420(x) + if (x < 1) + fun_l1_n68(x) + else + fun_l1_n970(x) + end +end + +def fun_l0_n421(x) + if (x < 1) + fun_l1_n663(x) + else + fun_l1_n388(x) + end +end + +def fun_l0_n422(x) + if (x < 1) + fun_l1_n686(x) + else + fun_l1_n67(x) + end +end + +def fun_l0_n423(x) + if (x < 1) + fun_l1_n210(x) + else + fun_l1_n64(x) + end +end + +def fun_l0_n424(x) + if (x < 1) + fun_l1_n375(x) + else + fun_l1_n205(x) + end +end + +def fun_l0_n425(x) + if (x < 1) + fun_l1_n832(x) + else + fun_l1_n325(x) + end +end + +def fun_l0_n426(x) + if (x < 1) + fun_l1_n819(x) + else + fun_l1_n601(x) + end +end + +def fun_l0_n427(x) + if (x < 1) + fun_l1_n588(x) + else + fun_l1_n875(x) + end +end + +def fun_l0_n428(x) + if (x < 1) + fun_l1_n682(x) + else + fun_l1_n523(x) + end +end + +def fun_l0_n429(x) + if (x < 1) + fun_l1_n972(x) + else + fun_l1_n891(x) + end +end + +def fun_l0_n430(x) + if (x < 1) + fun_l1_n90(x) + else + fun_l1_n655(x) + end +end + +def fun_l0_n431(x) + if (x < 1) + fun_l1_n393(x) + else + fun_l1_n454(x) + end +end + +def fun_l0_n432(x) + if (x < 1) + fun_l1_n435(x) + else + fun_l1_n860(x) + end +end + +def fun_l0_n433(x) + if (x < 1) + fun_l1_n516(x) + else + fun_l1_n246(x) + end +end + +def fun_l0_n434(x) + if (x < 1) + fun_l1_n216(x) + else + fun_l1_n78(x) + end +end + +def fun_l0_n435(x) + if (x < 1) + fun_l1_n357(x) + else + fun_l1_n61(x) + end +end + +def fun_l0_n436(x) + if (x < 1) + fun_l1_n289(x) + else + fun_l1_n507(x) + end +end + +def fun_l0_n437(x) + if (x < 1) + fun_l1_n182(x) + else + fun_l1_n289(x) + end +end + +def fun_l0_n438(x) + if (x < 1) + fun_l1_n69(x) + else + fun_l1_n549(x) + end +end + +def fun_l0_n439(x) + if (x < 1) + fun_l1_n275(x) + else + fun_l1_n723(x) + end +end + +def fun_l0_n440(x) + if (x < 1) + fun_l1_n469(x) + else + fun_l1_n243(x) + end +end + +def fun_l0_n441(x) + if (x < 1) + fun_l1_n595(x) + else + fun_l1_n624(x) + end +end + +def fun_l0_n442(x) + if (x < 1) + fun_l1_n655(x) + else + fun_l1_n896(x) + end +end + +def fun_l0_n443(x) + if (x < 1) + fun_l1_n926(x) + else + fun_l1_n503(x) + end +end + +def fun_l0_n444(x) + if (x < 1) + fun_l1_n875(x) + else + fun_l1_n110(x) + end +end + +def fun_l0_n445(x) + if (x < 1) + fun_l1_n832(x) + else + fun_l1_n154(x) + end +end + +def fun_l0_n446(x) + if (x < 1) + fun_l1_n538(x) + else + fun_l1_n75(x) + end +end + +def fun_l0_n447(x) + if (x < 1) + fun_l1_n183(x) + else + fun_l1_n718(x) + end +end + +def fun_l0_n448(x) + if (x < 1) + fun_l1_n680(x) + else + fun_l1_n93(x) + end +end + +def fun_l0_n449(x) + if (x < 1) + fun_l1_n147(x) + else + fun_l1_n924(x) + end +end + +def fun_l0_n450(x) + if (x < 1) + fun_l1_n702(x) + else + fun_l1_n830(x) + end +end + +def fun_l0_n451(x) + if (x < 1) + fun_l1_n750(x) + else + fun_l1_n447(x) + end +end + +def fun_l0_n452(x) + if (x < 1) + fun_l1_n520(x) + else + fun_l1_n69(x) + end +end + +def fun_l0_n453(x) + if (x < 1) + fun_l1_n132(x) + else + fun_l1_n877(x) + end +end + +def fun_l0_n454(x) + if (x < 1) + fun_l1_n247(x) + else + fun_l1_n69(x) + end +end + +def fun_l0_n455(x) + if (x < 1) + fun_l1_n180(x) + else + fun_l1_n645(x) + end +end + +def fun_l0_n456(x) + if (x < 1) + fun_l1_n658(x) + else + fun_l1_n487(x) + end +end + +def fun_l0_n457(x) + if (x < 1) + fun_l1_n276(x) + else + fun_l1_n528(x) + end +end + +def fun_l0_n458(x) + if (x < 1) + fun_l1_n30(x) + else + fun_l1_n456(x) + end +end + +def fun_l0_n459(x) + if (x < 1) + fun_l1_n986(x) + else + fun_l1_n552(x) + end +end + +def fun_l0_n460(x) + if (x < 1) + fun_l1_n874(x) + else + fun_l1_n396(x) + end +end + +def fun_l0_n461(x) + if (x < 1) + fun_l1_n524(x) + else + fun_l1_n335(x) + end +end + +def fun_l0_n462(x) + if (x < 1) + fun_l1_n471(x) + else + fun_l1_n578(x) + end +end + +def fun_l0_n463(x) + if (x < 1) + fun_l1_n173(x) + else + fun_l1_n456(x) + end +end + +def fun_l0_n464(x) + if (x < 1) + fun_l1_n872(x) + else + fun_l1_n745(x) + end +end + +def fun_l0_n465(x) + if (x < 1) + fun_l1_n387(x) + else + fun_l1_n776(x) + end +end + +def fun_l0_n466(x) + if (x < 1) + fun_l1_n119(x) + else + fun_l1_n428(x) + end +end + +def fun_l0_n467(x) + if (x < 1) + fun_l1_n416(x) + else + fun_l1_n738(x) + end +end + +def fun_l0_n468(x) + if (x < 1) + fun_l1_n762(x) + else + fun_l1_n694(x) + end +end + +def fun_l0_n469(x) + if (x < 1) + fun_l1_n27(x) + else + fun_l1_n562(x) + end +end + +def fun_l0_n470(x) + if (x < 1) + fun_l1_n12(x) + else + fun_l1_n812(x) + end +end + +def fun_l0_n471(x) + if (x < 1) + fun_l1_n865(x) + else + fun_l1_n94(x) + end +end + +def fun_l0_n472(x) + if (x < 1) + fun_l1_n346(x) + else + fun_l1_n39(x) + end +end + +def fun_l0_n473(x) + if (x < 1) + fun_l1_n309(x) + else + fun_l1_n158(x) + end +end + +def fun_l0_n474(x) + if (x < 1) + fun_l1_n828(x) + else + fun_l1_n229(x) + end +end + +def fun_l0_n475(x) + if (x < 1) + fun_l1_n554(x) + else + fun_l1_n121(x) + end +end + +def fun_l0_n476(x) + if (x < 1) + fun_l1_n818(x) + else + fun_l1_n390(x) + end +end + +def fun_l0_n477(x) + if (x < 1) + fun_l1_n88(x) + else + fun_l1_n73(x) + end +end + +def fun_l0_n478(x) + if (x < 1) + fun_l1_n709(x) + else + fun_l1_n680(x) + end +end + +def fun_l0_n479(x) + if (x < 1) + fun_l1_n271(x) + else + fun_l1_n439(x) + end +end + +def fun_l0_n480(x) + if (x < 1) + fun_l1_n493(x) + else + fun_l1_n562(x) + end +end + +def fun_l0_n481(x) + if (x < 1) + fun_l1_n642(x) + else + fun_l1_n221(x) + end +end + +def fun_l0_n482(x) + if (x < 1) + fun_l1_n838(x) + else + fun_l1_n345(x) + end +end + +def fun_l0_n483(x) + if (x < 1) + fun_l1_n411(x) + else + fun_l1_n266(x) + end +end + +def fun_l0_n484(x) + if (x < 1) + fun_l1_n916(x) + else + fun_l1_n791(x) + end +end + +def fun_l0_n485(x) + if (x < 1) + fun_l1_n392(x) + else + fun_l1_n68(x) + end +end + +def fun_l0_n486(x) + if (x < 1) + fun_l1_n834(x) + else + fun_l1_n783(x) + end +end + +def fun_l0_n487(x) + if (x < 1) + fun_l1_n398(x) + else + fun_l1_n627(x) + end +end + +def fun_l0_n488(x) + if (x < 1) + fun_l1_n904(x) + else + fun_l1_n167(x) + end +end + +def fun_l0_n489(x) + if (x < 1) + fun_l1_n54(x) + else + fun_l1_n28(x) + end +end + +def fun_l0_n490(x) + if (x < 1) + fun_l1_n24(x) + else + fun_l1_n9(x) + end +end + +def fun_l0_n491(x) + if (x < 1) + fun_l1_n497(x) + else + fun_l1_n297(x) + end +end + +def fun_l0_n492(x) + if (x < 1) + fun_l1_n951(x) + else + fun_l1_n534(x) + end +end + +def fun_l0_n493(x) + if (x < 1) + fun_l1_n213(x) + else + fun_l1_n808(x) + end +end + +def fun_l0_n494(x) + if (x < 1) + fun_l1_n904(x) + else + fun_l1_n94(x) + end +end + +def fun_l0_n495(x) + if (x < 1) + fun_l1_n799(x) + else + fun_l1_n817(x) + end +end + +def fun_l0_n496(x) + if (x < 1) + fun_l1_n45(x) + else + fun_l1_n860(x) + end +end + +def fun_l0_n497(x) + if (x < 1) + fun_l1_n482(x) + else + fun_l1_n783(x) + end +end + +def fun_l0_n498(x) + if (x < 1) + fun_l1_n78(x) + else + fun_l1_n785(x) + end +end + +def fun_l0_n499(x) + if (x < 1) + fun_l1_n174(x) + else + fun_l1_n87(x) + end +end + +def fun_l0_n500(x) + if (x < 1) + fun_l1_n608(x) + else + fun_l1_n7(x) + end +end + +def fun_l0_n501(x) + if (x < 1) + fun_l1_n157(x) + else + fun_l1_n718(x) + end +end + +def fun_l0_n502(x) + if (x < 1) + fun_l1_n823(x) + else + fun_l1_n549(x) + end +end + +def fun_l0_n503(x) + if (x < 1) + fun_l1_n13(x) + else + fun_l1_n502(x) + end +end + +def fun_l0_n504(x) + if (x < 1) + fun_l1_n119(x) + else + fun_l1_n191(x) + end +end + +def fun_l0_n505(x) + if (x < 1) + fun_l1_n503(x) + else + fun_l1_n974(x) + end +end + +def fun_l0_n506(x) + if (x < 1) + fun_l1_n893(x) + else + fun_l1_n582(x) + end +end + +def fun_l0_n507(x) + if (x < 1) + fun_l1_n403(x) + else + fun_l1_n228(x) + end +end + +def fun_l0_n508(x) + if (x < 1) + fun_l1_n640(x) + else + fun_l1_n362(x) + end +end + +def fun_l0_n509(x) + if (x < 1) + fun_l1_n629(x) + else + fun_l1_n824(x) + end +end + +def fun_l0_n510(x) + if (x < 1) + fun_l1_n84(x) + else + fun_l1_n330(x) + end +end + +def fun_l0_n511(x) + if (x < 1) + fun_l1_n91(x) + else + fun_l1_n523(x) + end +end + +def fun_l0_n512(x) + if (x < 1) + fun_l1_n696(x) + else + fun_l1_n126(x) + end +end + +def fun_l0_n513(x) + if (x < 1) + fun_l1_n905(x) + else + fun_l1_n496(x) + end +end + +def fun_l0_n514(x) + if (x < 1) + fun_l1_n766(x) + else + fun_l1_n523(x) + end +end + +def fun_l0_n515(x) + if (x < 1) + fun_l1_n798(x) + else + fun_l1_n698(x) + end +end + +def fun_l0_n516(x) + if (x < 1) + fun_l1_n124(x) + else + fun_l1_n356(x) + end +end + +def fun_l0_n517(x) + if (x < 1) + fun_l1_n289(x) + else + fun_l1_n782(x) + end +end + +def fun_l0_n518(x) + if (x < 1) + fun_l1_n483(x) + else + fun_l1_n586(x) + end +end + +def fun_l0_n519(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n37(x) + end +end + +def fun_l0_n520(x) + if (x < 1) + fun_l1_n48(x) + else + fun_l1_n216(x) + end +end + +def fun_l0_n521(x) + if (x < 1) + fun_l1_n805(x) + else + fun_l1_n846(x) + end +end + +def fun_l0_n522(x) + if (x < 1) + fun_l1_n422(x) + else + fun_l1_n190(x) + end +end + +def fun_l0_n523(x) + if (x < 1) + fun_l1_n168(x) + else + fun_l1_n272(x) + end +end + +def fun_l0_n524(x) + if (x < 1) + fun_l1_n766(x) + else + fun_l1_n125(x) + end +end + +def fun_l0_n525(x) + if (x < 1) + fun_l1_n56(x) + else + fun_l1_n224(x) + end +end + +def fun_l0_n526(x) + if (x < 1) + fun_l1_n540(x) + else + fun_l1_n303(x) + end +end + +def fun_l0_n527(x) + if (x < 1) + fun_l1_n846(x) + else + fun_l1_n955(x) + end +end + +def fun_l0_n528(x) + if (x < 1) + fun_l1_n571(x) + else + fun_l1_n640(x) + end +end + +def fun_l0_n529(x) + if (x < 1) + fun_l1_n650(x) + else + fun_l1_n107(x) + end +end + +def fun_l0_n530(x) + if (x < 1) + fun_l1_n240(x) + else + fun_l1_n139(x) + end +end + +def fun_l0_n531(x) + if (x < 1) + fun_l1_n975(x) + else + fun_l1_n970(x) + end +end + +def fun_l0_n532(x) + if (x < 1) + fun_l1_n753(x) + else + fun_l1_n147(x) + end +end + +def fun_l0_n533(x) + if (x < 1) + fun_l1_n269(x) + else + fun_l1_n292(x) + end +end + +def fun_l0_n534(x) + if (x < 1) + fun_l1_n791(x) + else + fun_l1_n69(x) + end +end + +def fun_l0_n535(x) + if (x < 1) + fun_l1_n469(x) + else + fun_l1_n58(x) + end +end + +def fun_l0_n536(x) + if (x < 1) + fun_l1_n526(x) + else + fun_l1_n265(x) + end +end + +def fun_l0_n537(x) + if (x < 1) + fun_l1_n681(x) + else + fun_l1_n646(x) + end +end + +def fun_l0_n538(x) + if (x < 1) + fun_l1_n377(x) + else + fun_l1_n969(x) + end +end + +def fun_l0_n539(x) + if (x < 1) + fun_l1_n935(x) + else + fun_l1_n556(x) + end +end + +def fun_l0_n540(x) + if (x < 1) + fun_l1_n498(x) + else + fun_l1_n439(x) + end +end + +def fun_l0_n541(x) + if (x < 1) + fun_l1_n451(x) + else + fun_l1_n35(x) + end +end + +def fun_l0_n542(x) + if (x < 1) + fun_l1_n32(x) + else + fun_l1_n795(x) + end +end + +def fun_l0_n543(x) + if (x < 1) + fun_l1_n732(x) + else + fun_l1_n530(x) + end +end + +def fun_l0_n544(x) + if (x < 1) + fun_l1_n176(x) + else + fun_l1_n735(x) + end +end + +def fun_l0_n545(x) + if (x < 1) + fun_l1_n34(x) + else + fun_l1_n989(x) + end +end + +def fun_l0_n546(x) + if (x < 1) + fun_l1_n534(x) + else + fun_l1_n705(x) + end +end + +def fun_l0_n547(x) + if (x < 1) + fun_l1_n997(x) + else + fun_l1_n883(x) + end +end + +def fun_l0_n548(x) + if (x < 1) + fun_l1_n379(x) + else + fun_l1_n33(x) + end +end + +def fun_l0_n549(x) + if (x < 1) + fun_l1_n454(x) + else + fun_l1_n516(x) + end +end + +def fun_l0_n550(x) + if (x < 1) + fun_l1_n678(x) + else + fun_l1_n652(x) + end +end + +def fun_l0_n551(x) + if (x < 1) + fun_l1_n13(x) + else + fun_l1_n864(x) + end +end + +def fun_l0_n552(x) + if (x < 1) + fun_l1_n178(x) + else + fun_l1_n996(x) + end +end + +def fun_l0_n553(x) + if (x < 1) + fun_l1_n865(x) + else + fun_l1_n703(x) + end +end + +def fun_l0_n554(x) + if (x < 1) + fun_l1_n306(x) + else + fun_l1_n24(x) + end +end + +def fun_l0_n555(x) + if (x < 1) + fun_l1_n110(x) + else + fun_l1_n123(x) + end +end + +def fun_l0_n556(x) + if (x < 1) + fun_l1_n367(x) + else + fun_l1_n117(x) + end +end + +def fun_l0_n557(x) + if (x < 1) + fun_l1_n967(x) + else + fun_l1_n662(x) + end +end + +def fun_l0_n558(x) + if (x < 1) + fun_l1_n68(x) + else + fun_l1_n47(x) + end +end + +def fun_l0_n559(x) + if (x < 1) + fun_l1_n154(x) + else + fun_l1_n344(x) + end +end + +def fun_l0_n560(x) + if (x < 1) + fun_l1_n835(x) + else + fun_l1_n577(x) + end +end + +def fun_l0_n561(x) + if (x < 1) + fun_l1_n393(x) + else + fun_l1_n419(x) + end +end + +def fun_l0_n562(x) + if (x < 1) + fun_l1_n632(x) + else + fun_l1_n630(x) + end +end + +def fun_l0_n563(x) + if (x < 1) + fun_l1_n9(x) + else + fun_l1_n109(x) + end +end + +def fun_l0_n564(x) + if (x < 1) + fun_l1_n65(x) + else + fun_l1_n123(x) + end +end + +def fun_l0_n565(x) + if (x < 1) + fun_l1_n156(x) + else + fun_l1_n921(x) + end +end + +def fun_l0_n566(x) + if (x < 1) + fun_l1_n88(x) + else + fun_l1_n743(x) + end +end + +def fun_l0_n567(x) + if (x < 1) + fun_l1_n92(x) + else + fun_l1_n27(x) + end +end + +def fun_l0_n568(x) + if (x < 1) + fun_l1_n462(x) + else + fun_l1_n988(x) + end +end + +def fun_l0_n569(x) + if (x < 1) + fun_l1_n241(x) + else + fun_l1_n199(x) + end +end + +def fun_l0_n570(x) + if (x < 1) + fun_l1_n429(x) + else + fun_l1_n530(x) + end +end + +def fun_l0_n571(x) + if (x < 1) + fun_l1_n412(x) + else + fun_l1_n530(x) + end +end + +def fun_l0_n572(x) + if (x < 1) + fun_l1_n100(x) + else + fun_l1_n270(x) + end +end + +def fun_l0_n573(x) + if (x < 1) + fun_l1_n326(x) + else + fun_l1_n191(x) + end +end + +def fun_l0_n574(x) + if (x < 1) + fun_l1_n151(x) + else + fun_l1_n354(x) + end +end + +def fun_l0_n575(x) + if (x < 1) + fun_l1_n322(x) + else + fun_l1_n534(x) + end +end + +def fun_l0_n576(x) + if (x < 1) + fun_l1_n995(x) + else + fun_l1_n658(x) + end +end + +def fun_l0_n577(x) + if (x < 1) + fun_l1_n193(x) + else + fun_l1_n444(x) + end +end + +def fun_l0_n578(x) + if (x < 1) + fun_l1_n527(x) + else + fun_l1_n517(x) + end +end + +def fun_l0_n579(x) + if (x < 1) + fun_l1_n885(x) + else + fun_l1_n218(x) + end +end + +def fun_l0_n580(x) + if (x < 1) + fun_l1_n789(x) + else + fun_l1_n711(x) + end +end + +def fun_l0_n581(x) + if (x < 1) + fun_l1_n848(x) + else + fun_l1_n321(x) + end +end + +def fun_l0_n582(x) + if (x < 1) + fun_l1_n389(x) + else + fun_l1_n360(x) + end +end + +def fun_l0_n583(x) + if (x < 1) + fun_l1_n319(x) + else + fun_l1_n972(x) + end +end + +def fun_l0_n584(x) + if (x < 1) + fun_l1_n421(x) + else + fun_l1_n659(x) + end +end + +def fun_l0_n585(x) + if (x < 1) + fun_l1_n462(x) + else + fun_l1_n302(x) + end +end + +def fun_l0_n586(x) + if (x < 1) + fun_l1_n122(x) + else + fun_l1_n50(x) + end +end + +def fun_l0_n587(x) + if (x < 1) + fun_l1_n795(x) + else + fun_l1_n622(x) + end +end + +def fun_l0_n588(x) + if (x < 1) + fun_l1_n719(x) + else + fun_l1_n390(x) + end +end + +def fun_l0_n589(x) + if (x < 1) + fun_l1_n916(x) + else + fun_l1_n925(x) + end +end + +def fun_l0_n590(x) + if (x < 1) + fun_l1_n541(x) + else + fun_l1_n139(x) + end +end + +def fun_l0_n591(x) + if (x < 1) + fun_l1_n610(x) + else + fun_l1_n509(x) + end +end + +def fun_l0_n592(x) + if (x < 1) + fun_l1_n217(x) + else + fun_l1_n452(x) + end +end + +def fun_l0_n593(x) + if (x < 1) + fun_l1_n456(x) + else + fun_l1_n888(x) + end +end + +def fun_l0_n594(x) + if (x < 1) + fun_l1_n987(x) + else + fun_l1_n462(x) + end +end + +def fun_l0_n595(x) + if (x < 1) + fun_l1_n571(x) + else + fun_l1_n429(x) + end +end + +def fun_l0_n596(x) + if (x < 1) + fun_l1_n751(x) + else + fun_l1_n773(x) + end +end + +def fun_l0_n597(x) + if (x < 1) + fun_l1_n181(x) + else + fun_l1_n340(x) + end +end + +def fun_l0_n598(x) + if (x < 1) + fun_l1_n6(x) + else + fun_l1_n39(x) + end +end + +def fun_l0_n599(x) + if (x < 1) + fun_l1_n814(x) + else + fun_l1_n320(x) + end +end + +def fun_l0_n600(x) + if (x < 1) + fun_l1_n931(x) + else + fun_l1_n535(x) + end +end + +def fun_l0_n601(x) + if (x < 1) + fun_l1_n99(x) + else + fun_l1_n154(x) + end +end + +def fun_l0_n602(x) + if (x < 1) + fun_l1_n981(x) + else + fun_l1_n817(x) + end +end + +def fun_l0_n603(x) + if (x < 1) + fun_l1_n975(x) + else + fun_l1_n364(x) + end +end + +def fun_l0_n604(x) + if (x < 1) + fun_l1_n112(x) + else + fun_l1_n226(x) + end +end + +def fun_l0_n605(x) + if (x < 1) + fun_l1_n995(x) + else + fun_l1_n95(x) + end +end + +def fun_l0_n606(x) + if (x < 1) + fun_l1_n930(x) + else + fun_l1_n77(x) + end +end + +def fun_l0_n607(x) + if (x < 1) + fun_l1_n899(x) + else + fun_l1_n957(x) + end +end + +def fun_l0_n608(x) + if (x < 1) + fun_l1_n844(x) + else + fun_l1_n119(x) + end +end + +def fun_l0_n609(x) + if (x < 1) + fun_l1_n861(x) + else + fun_l1_n74(x) + end +end + +def fun_l0_n610(x) + if (x < 1) + fun_l1_n521(x) + else + fun_l1_n46(x) + end +end + +def fun_l0_n611(x) + if (x < 1) + fun_l1_n258(x) + else + fun_l1_n208(x) + end +end + +def fun_l0_n612(x) + if (x < 1) + fun_l1_n620(x) + else + fun_l1_n427(x) + end +end + +def fun_l0_n613(x) + if (x < 1) + fun_l1_n583(x) + else + fun_l1_n400(x) + end +end + +def fun_l0_n614(x) + if (x < 1) + fun_l1_n933(x) + else + fun_l1_n810(x) + end +end + +def fun_l0_n615(x) + if (x < 1) + fun_l1_n154(x) + else + fun_l1_n879(x) + end +end + +def fun_l0_n616(x) + if (x < 1) + fun_l1_n715(x) + else + fun_l1_n862(x) + end +end + +def fun_l0_n617(x) + if (x < 1) + fun_l1_n178(x) + else + fun_l1_n285(x) + end +end + +def fun_l0_n618(x) + if (x < 1) + fun_l1_n458(x) + else + fun_l1_n217(x) + end +end + +def fun_l0_n619(x) + if (x < 1) + fun_l1_n655(x) + else + fun_l1_n405(x) + end +end + +def fun_l0_n620(x) + if (x < 1) + fun_l1_n470(x) + else + fun_l1_n306(x) + end +end + +def fun_l0_n621(x) + if (x < 1) + fun_l1_n755(x) + else + fun_l1_n425(x) + end +end + +def fun_l0_n622(x) + if (x < 1) + fun_l1_n426(x) + else + fun_l1_n737(x) + end +end + +def fun_l0_n623(x) + if (x < 1) + fun_l1_n79(x) + else + fun_l1_n55(x) + end +end + +def fun_l0_n624(x) + if (x < 1) + fun_l1_n437(x) + else + fun_l1_n79(x) + end +end + +def fun_l0_n625(x) + if (x < 1) + fun_l1_n691(x) + else + fun_l1_n198(x) + end +end + +def fun_l0_n626(x) + if (x < 1) + fun_l1_n703(x) + else + fun_l1_n585(x) + end +end + +def fun_l0_n627(x) + if (x < 1) + fun_l1_n966(x) + else + fun_l1_n425(x) + end +end + +def fun_l0_n628(x) + if (x < 1) + fun_l1_n516(x) + else + fun_l1_n744(x) + end +end + +def fun_l0_n629(x) + if (x < 1) + fun_l1_n40(x) + else + fun_l1_n942(x) + end +end + +def fun_l0_n630(x) + if (x < 1) + fun_l1_n528(x) + else + fun_l1_n440(x) + end +end + +def fun_l0_n631(x) + if (x < 1) + fun_l1_n139(x) + else + fun_l1_n403(x) + end +end + +def fun_l0_n632(x) + if (x < 1) + fun_l1_n421(x) + else + fun_l1_n510(x) + end +end + +def fun_l0_n633(x) + if (x < 1) + fun_l1_n718(x) + else + fun_l1_n388(x) + end +end + +def fun_l0_n634(x) + if (x < 1) + fun_l1_n67(x) + else + fun_l1_n342(x) + end +end + +def fun_l0_n635(x) + if (x < 1) + fun_l1_n943(x) + else + fun_l1_n941(x) + end +end + +def fun_l0_n636(x) + if (x < 1) + fun_l1_n170(x) + else + fun_l1_n527(x) + end +end + +def fun_l0_n637(x) + if (x < 1) + fun_l1_n336(x) + else + fun_l1_n496(x) + end +end + +def fun_l0_n638(x) + if (x < 1) + fun_l1_n730(x) + else + fun_l1_n10(x) + end +end + +def fun_l0_n639(x) + if (x < 1) + fun_l1_n939(x) + else + fun_l1_n940(x) + end +end + +def fun_l0_n640(x) + if (x < 1) + fun_l1_n73(x) + else + fun_l1_n439(x) + end +end + +def fun_l0_n641(x) + if (x < 1) + fun_l1_n460(x) + else + fun_l1_n828(x) + end +end + +def fun_l0_n642(x) + if (x < 1) + fun_l1_n90(x) + else + fun_l1_n113(x) + end +end + +def fun_l0_n643(x) + if (x < 1) + fun_l1_n972(x) + else + fun_l1_n15(x) + end +end + +def fun_l0_n644(x) + if (x < 1) + fun_l1_n417(x) + else + fun_l1_n228(x) + end +end + +def fun_l0_n645(x) + if (x < 1) + fun_l1_n876(x) + else + fun_l1_n152(x) + end +end + +def fun_l0_n646(x) + if (x < 1) + fun_l1_n404(x) + else + fun_l1_n147(x) + end +end + +def fun_l0_n647(x) + if (x < 1) + fun_l1_n802(x) + else + fun_l1_n824(x) + end +end + +def fun_l0_n648(x) + if (x < 1) + fun_l1_n771(x) + else + fun_l1_n421(x) + end +end + +def fun_l0_n649(x) + if (x < 1) + fun_l1_n807(x) + else + fun_l1_n955(x) + end +end + +def fun_l0_n650(x) + if (x < 1) + fun_l1_n221(x) + else + fun_l1_n367(x) + end +end + +def fun_l0_n651(x) + if (x < 1) + fun_l1_n955(x) + else + fun_l1_n401(x) + end +end + +def fun_l0_n652(x) + if (x < 1) + fun_l1_n203(x) + else + fun_l1_n909(x) + end +end + +def fun_l0_n653(x) + if (x < 1) + fun_l1_n154(x) + else + fun_l1_n535(x) + end +end + +def fun_l0_n654(x) + if (x < 1) + fun_l1_n420(x) + else + fun_l1_n393(x) + end +end + +def fun_l0_n655(x) + if (x < 1) + fun_l1_n232(x) + else + fun_l1_n981(x) + end +end + +def fun_l0_n656(x) + if (x < 1) + fun_l1_n873(x) + else + fun_l1_n510(x) + end +end + +def fun_l0_n657(x) + if (x < 1) + fun_l1_n919(x) + else + fun_l1_n706(x) + end +end + +def fun_l0_n658(x) + if (x < 1) + fun_l1_n429(x) + else + fun_l1_n112(x) + end +end + +def fun_l0_n659(x) + if (x < 1) + fun_l1_n547(x) + else + fun_l1_n712(x) + end +end + +def fun_l0_n660(x) + if (x < 1) + fun_l1_n498(x) + else + fun_l1_n695(x) + end +end + +def fun_l0_n661(x) + if (x < 1) + fun_l1_n801(x) + else + fun_l1_n659(x) + end +end + +def fun_l0_n662(x) + if (x < 1) + fun_l1_n796(x) + else + fun_l1_n229(x) + end +end + +def fun_l0_n663(x) + if (x < 1) + fun_l1_n11(x) + else + fun_l1_n620(x) + end +end + +def fun_l0_n664(x) + if (x < 1) + fun_l1_n652(x) + else + fun_l1_n416(x) + end +end + +def fun_l0_n665(x) + if (x < 1) + fun_l1_n655(x) + else + fun_l1_n331(x) + end +end + +def fun_l0_n666(x) + if (x < 1) + fun_l1_n846(x) + else + fun_l1_n1(x) + end +end + +def fun_l0_n667(x) + if (x < 1) + fun_l1_n55(x) + else + fun_l1_n32(x) + end +end + +def fun_l0_n668(x) + if (x < 1) + fun_l1_n241(x) + else + fun_l1_n627(x) + end +end + +def fun_l0_n669(x) + if (x < 1) + fun_l1_n234(x) + else + fun_l1_n996(x) + end +end + +def fun_l0_n670(x) + if (x < 1) + fun_l1_n235(x) + else + fun_l1_n761(x) + end +end + +def fun_l0_n671(x) + if (x < 1) + fun_l1_n990(x) + else + fun_l1_n236(x) + end +end + +def fun_l0_n672(x) + if (x < 1) + fun_l1_n970(x) + else + fun_l1_n595(x) + end +end + +def fun_l0_n673(x) + if (x < 1) + fun_l1_n294(x) + else + fun_l1_n440(x) + end +end + +def fun_l0_n674(x) + if (x < 1) + fun_l1_n597(x) + else + fun_l1_n956(x) + end +end + +def fun_l0_n675(x) + if (x < 1) + fun_l1_n942(x) + else + fun_l1_n352(x) + end +end + +def fun_l0_n676(x) + if (x < 1) + fun_l1_n309(x) + else + fun_l1_n294(x) + end +end + +def fun_l0_n677(x) + if (x < 1) + fun_l1_n752(x) + else + fun_l1_n447(x) + end +end + +def fun_l0_n678(x) + if (x < 1) + fun_l1_n890(x) + else + fun_l1_n497(x) + end +end + +def fun_l0_n679(x) + if (x < 1) + fun_l1_n808(x) + else + fun_l1_n881(x) + end +end + +def fun_l0_n680(x) + if (x < 1) + fun_l1_n966(x) + else + fun_l1_n460(x) + end +end + +def fun_l0_n681(x) + if (x < 1) + fun_l1_n104(x) + else + fun_l1_n262(x) + end +end + +def fun_l0_n682(x) + if (x < 1) + fun_l1_n425(x) + else + fun_l1_n177(x) + end +end + +def fun_l0_n683(x) + if (x < 1) + fun_l1_n15(x) + else + fun_l1_n458(x) + end +end + +def fun_l0_n684(x) + if (x < 1) + fun_l1_n760(x) + else + fun_l1_n997(x) + end +end + +def fun_l0_n685(x) + if (x < 1) + fun_l1_n496(x) + else + fun_l1_n223(x) + end +end + +def fun_l0_n686(x) + if (x < 1) + fun_l1_n363(x) + else + fun_l1_n543(x) + end +end + +def fun_l0_n687(x) + if (x < 1) + fun_l1_n758(x) + else + fun_l1_n473(x) + end +end + +def fun_l0_n688(x) + if (x < 1) + fun_l1_n854(x) + else + fun_l1_n999(x) + end +end + +def fun_l0_n689(x) + if (x < 1) + fun_l1_n336(x) + else + fun_l1_n388(x) + end +end + +def fun_l0_n690(x) + if (x < 1) + fun_l1_n930(x) + else + fun_l1_n478(x) + end +end + +def fun_l0_n691(x) + if (x < 1) + fun_l1_n423(x) + else + fun_l1_n83(x) + end +end + +def fun_l0_n692(x) + if (x < 1) + fun_l1_n797(x) + else + fun_l1_n427(x) + end +end + +def fun_l0_n693(x) + if (x < 1) + fun_l1_n907(x) + else + fun_l1_n1(x) + end +end + +def fun_l0_n694(x) + if (x < 1) + fun_l1_n601(x) + else + fun_l1_n809(x) + end +end + +def fun_l0_n695(x) + if (x < 1) + fun_l1_n252(x) + else + fun_l1_n233(x) + end +end + +def fun_l0_n696(x) + if (x < 1) + fun_l1_n36(x) + else + fun_l1_n796(x) + end +end + +def fun_l0_n697(x) + if (x < 1) + fun_l1_n893(x) + else + fun_l1_n926(x) + end +end + +def fun_l0_n698(x) + if (x < 1) + fun_l1_n511(x) + else + fun_l1_n88(x) + end +end + +def fun_l0_n699(x) + if (x < 1) + fun_l1_n573(x) + else + fun_l1_n718(x) + end +end + +def fun_l0_n700(x) + if (x < 1) + fun_l1_n475(x) + else + fun_l1_n539(x) + end +end + +def fun_l0_n701(x) + if (x < 1) + fun_l1_n238(x) + else + fun_l1_n253(x) + end +end + +def fun_l0_n702(x) + if (x < 1) + fun_l1_n731(x) + else + fun_l1_n225(x) + end +end + +def fun_l0_n703(x) + if (x < 1) + fun_l1_n594(x) + else + fun_l1_n16(x) + end +end + +def fun_l0_n704(x) + if (x < 1) + fun_l1_n732(x) + else + fun_l1_n354(x) + end +end + +def fun_l0_n705(x) + if (x < 1) + fun_l1_n812(x) + else + fun_l1_n218(x) + end +end + +def fun_l0_n706(x) + if (x < 1) + fun_l1_n731(x) + else + fun_l1_n343(x) + end +end + +def fun_l0_n707(x) + if (x < 1) + fun_l1_n134(x) + else + fun_l1_n752(x) + end +end + +def fun_l0_n708(x) + if (x < 1) + fun_l1_n899(x) + else + fun_l1_n854(x) + end +end + +def fun_l0_n709(x) + if (x < 1) + fun_l1_n120(x) + else + fun_l1_n193(x) + end +end + +def fun_l0_n710(x) + if (x < 1) + fun_l1_n22(x) + else + fun_l1_n254(x) + end +end + +def fun_l0_n711(x) + if (x < 1) + fun_l1_n527(x) + else + fun_l1_n921(x) + end +end + +def fun_l0_n712(x) + if (x < 1) + fun_l1_n820(x) + else + fun_l1_n96(x) + end +end + +def fun_l0_n713(x) + if (x < 1) + fun_l1_n145(x) + else + fun_l1_n226(x) + end +end + +def fun_l0_n714(x) + if (x < 1) + fun_l1_n643(x) + else + fun_l1_n407(x) + end +end + +def fun_l0_n715(x) + if (x < 1) + fun_l1_n349(x) + else + fun_l1_n450(x) + end +end + +def fun_l0_n716(x) + if (x < 1) + fun_l1_n954(x) + else + fun_l1_n707(x) + end +end + +def fun_l0_n717(x) + if (x < 1) + fun_l1_n723(x) + else + fun_l1_n762(x) + end +end + +def fun_l0_n718(x) + if (x < 1) + fun_l1_n299(x) + else + fun_l1_n332(x) + end +end + +def fun_l0_n719(x) + if (x < 1) + fun_l1_n493(x) + else + fun_l1_n521(x) + end +end + +def fun_l0_n720(x) + if (x < 1) + fun_l1_n39(x) + else + fun_l1_n17(x) + end +end + +def fun_l0_n721(x) + if (x < 1) + fun_l1_n297(x) + else + fun_l1_n800(x) + end +end + +def fun_l0_n722(x) + if (x < 1) + fun_l1_n758(x) + else + fun_l1_n135(x) + end +end + +def fun_l0_n723(x) + if (x < 1) + fun_l1_n471(x) + else + fun_l1_n351(x) + end +end + +def fun_l0_n724(x) + if (x < 1) + fun_l1_n381(x) + else + fun_l1_n281(x) + end +end + +def fun_l0_n725(x) + if (x < 1) + fun_l1_n624(x) + else + fun_l1_n162(x) + end +end + +def fun_l0_n726(x) + if (x < 1) + fun_l1_n143(x) + else + fun_l1_n417(x) + end +end + +def fun_l0_n727(x) + if (x < 1) + fun_l1_n623(x) + else + fun_l1_n19(x) + end +end + +def fun_l0_n728(x) + if (x < 1) + fun_l1_n687(x) + else + fun_l1_n574(x) + end +end + +def fun_l0_n729(x) + if (x < 1) + fun_l1_n225(x) + else + fun_l1_n871(x) + end +end + +def fun_l0_n730(x) + if (x < 1) + fun_l1_n830(x) + else + fun_l1_n273(x) + end +end + +def fun_l0_n731(x) + if (x < 1) + fun_l1_n95(x) + else + fun_l1_n864(x) + end +end + +def fun_l0_n732(x) + if (x < 1) + fun_l1_n902(x) + else + fun_l1_n522(x) + end +end + +def fun_l0_n733(x) + if (x < 1) + fun_l1_n564(x) + else + fun_l1_n55(x) + end +end + +def fun_l0_n734(x) + if (x < 1) + fun_l1_n481(x) + else + fun_l1_n880(x) + end +end + +def fun_l0_n735(x) + if (x < 1) + fun_l1_n87(x) + else + fun_l1_n693(x) + end +end + +def fun_l0_n736(x) + if (x < 1) + fun_l1_n72(x) + else + fun_l1_n396(x) + end +end + +def fun_l0_n737(x) + if (x < 1) + fun_l1_n920(x) + else + fun_l1_n852(x) + end +end + +def fun_l0_n738(x) + if (x < 1) + fun_l1_n342(x) + else + fun_l1_n959(x) + end +end + +def fun_l0_n739(x) + if (x < 1) + fun_l1_n682(x) + else + fun_l1_n714(x) + end +end + +def fun_l0_n740(x) + if (x < 1) + fun_l1_n264(x) + else + fun_l1_n325(x) + end +end + +def fun_l0_n741(x) + if (x < 1) + fun_l1_n621(x) + else + fun_l1_n339(x) + end +end + +def fun_l0_n742(x) + if (x < 1) + fun_l1_n46(x) + else + fun_l1_n766(x) + end +end + +def fun_l0_n743(x) + if (x < 1) + fun_l1_n333(x) + else + fun_l1_n353(x) + end +end + +def fun_l0_n744(x) + if (x < 1) + fun_l1_n930(x) + else + fun_l1_n964(x) + end +end + +def fun_l0_n745(x) + if (x < 1) + fun_l1_n785(x) + else + fun_l1_n114(x) + end +end + +def fun_l0_n746(x) + if (x < 1) + fun_l1_n402(x) + else + fun_l1_n803(x) + end +end + +def fun_l0_n747(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n870(x) + end +end + +def fun_l0_n748(x) + if (x < 1) + fun_l1_n683(x) + else + fun_l1_n287(x) + end +end + +def fun_l0_n749(x) + if (x < 1) + fun_l1_n816(x) + else + fun_l1_n849(x) + end +end + +def fun_l0_n750(x) + if (x < 1) + fun_l1_n523(x) + else + fun_l1_n555(x) + end +end + +def fun_l0_n751(x) + if (x < 1) + fun_l1_n270(x) + else + fun_l1_n660(x) + end +end + +def fun_l0_n752(x) + if (x < 1) + fun_l1_n786(x) + else + fun_l1_n749(x) + end +end + +def fun_l0_n753(x) + if (x < 1) + fun_l1_n567(x) + else + fun_l1_n325(x) + end +end + +def fun_l0_n754(x) + if (x < 1) + fun_l1_n502(x) + else + fun_l1_n610(x) + end +end + +def fun_l0_n755(x) + if (x < 1) + fun_l1_n336(x) + else + fun_l1_n354(x) + end +end + +def fun_l0_n756(x) + if (x < 1) + fun_l1_n435(x) + else + fun_l1_n484(x) + end +end + +def fun_l0_n757(x) + if (x < 1) + fun_l1_n849(x) + else + fun_l1_n42(x) + end +end + +def fun_l0_n758(x) + if (x < 1) + fun_l1_n294(x) + else + fun_l1_n483(x) + end +end + +def fun_l0_n759(x) + if (x < 1) + fun_l1_n14(x) + else + fun_l1_n9(x) + end +end + +def fun_l0_n760(x) + if (x < 1) + fun_l1_n860(x) + else + fun_l1_n645(x) + end +end + +def fun_l0_n761(x) + if (x < 1) + fun_l1_n577(x) + else + fun_l1_n0(x) + end +end + +def fun_l0_n762(x) + if (x < 1) + fun_l1_n28(x) + else + fun_l1_n834(x) + end +end + +def fun_l0_n763(x) + if (x < 1) + fun_l1_n147(x) + else + fun_l1_n177(x) + end +end + +def fun_l0_n764(x) + if (x < 1) + fun_l1_n429(x) + else + fun_l1_n646(x) + end +end + +def fun_l0_n765(x) + if (x < 1) + fun_l1_n474(x) + else + fun_l1_n22(x) + end +end + +def fun_l0_n766(x) + if (x < 1) + fun_l1_n264(x) + else + fun_l1_n549(x) + end +end + +def fun_l0_n767(x) + if (x < 1) + fun_l1_n351(x) + else + fun_l1_n813(x) + end +end + +def fun_l0_n768(x) + if (x < 1) + fun_l1_n798(x) + else + fun_l1_n684(x) + end +end + +def fun_l0_n769(x) + if (x < 1) + fun_l1_n202(x) + else + fun_l1_n982(x) + end +end + +def fun_l0_n770(x) + if (x < 1) + fun_l1_n611(x) + else + fun_l1_n52(x) + end +end + +def fun_l0_n771(x) + if (x < 1) + fun_l1_n754(x) + else + fun_l1_n7(x) + end +end + +def fun_l0_n772(x) + if (x < 1) + fun_l1_n98(x) + else + fun_l1_n149(x) + end +end + +def fun_l0_n773(x) + if (x < 1) + fun_l1_n358(x) + else + fun_l1_n603(x) + end +end + +def fun_l0_n774(x) + if (x < 1) + fun_l1_n604(x) + else + fun_l1_n318(x) + end +end + +def fun_l0_n775(x) + if (x < 1) + fun_l1_n831(x) + else + fun_l1_n635(x) + end +end + +def fun_l0_n776(x) + if (x < 1) + fun_l1_n738(x) + else + fun_l1_n563(x) + end +end + +def fun_l0_n777(x) + if (x < 1) + fun_l1_n570(x) + else + fun_l1_n671(x) + end +end + +def fun_l0_n778(x) + if (x < 1) + fun_l1_n945(x) + else + fun_l1_n840(x) + end +end + +def fun_l0_n779(x) + if (x < 1) + fun_l1_n116(x) + else + fun_l1_n942(x) + end +end + +def fun_l0_n780(x) + if (x < 1) + fun_l1_n835(x) + else + fun_l1_n244(x) + end +end + +def fun_l0_n781(x) + if (x < 1) + fun_l1_n427(x) + else + fun_l1_n556(x) + end +end + +def fun_l0_n782(x) + if (x < 1) + fun_l1_n280(x) + else + fun_l1_n926(x) + end +end + +def fun_l0_n783(x) + if (x < 1) + fun_l1_n674(x) + else + fun_l1_n560(x) + end +end + +def fun_l0_n784(x) + if (x < 1) + fun_l1_n978(x) + else + fun_l1_n139(x) + end +end + +def fun_l0_n785(x) + if (x < 1) + fun_l1_n928(x) + else + fun_l1_n11(x) + end +end + +def fun_l0_n786(x) + if (x < 1) + fun_l1_n829(x) + else + fun_l1_n239(x) + end +end + +def fun_l0_n787(x) + if (x < 1) + fun_l1_n732(x) + else + fun_l1_n829(x) + end +end + +def fun_l0_n788(x) + if (x < 1) + fun_l1_n968(x) + else + fun_l1_n596(x) + end +end + +def fun_l0_n789(x) + if (x < 1) + fun_l1_n214(x) + else + fun_l1_n158(x) + end +end + +def fun_l0_n790(x) + if (x < 1) + fun_l1_n566(x) + else + fun_l1_n390(x) + end +end + +def fun_l0_n791(x) + if (x < 1) + fun_l1_n936(x) + else + fun_l1_n31(x) + end +end + +def fun_l0_n792(x) + if (x < 1) + fun_l1_n291(x) + else + fun_l1_n835(x) + end +end + +def fun_l0_n793(x) + if (x < 1) + fun_l1_n300(x) + else + fun_l1_n658(x) + end +end + +def fun_l0_n794(x) + if (x < 1) + fun_l1_n609(x) + else + fun_l1_n156(x) + end +end + +def fun_l0_n795(x) + if (x < 1) + fun_l1_n419(x) + else + fun_l1_n534(x) + end +end + +def fun_l0_n796(x) + if (x < 1) + fun_l1_n401(x) + else + fun_l1_n281(x) + end +end + +def fun_l0_n797(x) + if (x < 1) + fun_l1_n538(x) + else + fun_l1_n905(x) + end +end + +def fun_l0_n798(x) + if (x < 1) + fun_l1_n427(x) + else + fun_l1_n978(x) + end +end + +def fun_l0_n799(x) + if (x < 1) + fun_l1_n851(x) + else + fun_l1_n57(x) + end +end + +def fun_l0_n800(x) + if (x < 1) + fun_l1_n836(x) + else + fun_l1_n306(x) + end +end + +def fun_l0_n801(x) + if (x < 1) + fun_l1_n414(x) + else + fun_l1_n679(x) + end +end + +def fun_l0_n802(x) + if (x < 1) + fun_l1_n645(x) + else + fun_l1_n115(x) + end +end + +def fun_l0_n803(x) + if (x < 1) + fun_l1_n884(x) + else + fun_l1_n801(x) + end +end + +def fun_l0_n804(x) + if (x < 1) + fun_l1_n713(x) + else + fun_l1_n974(x) + end +end + +def fun_l0_n805(x) + if (x < 1) + fun_l1_n301(x) + else + fun_l1_n589(x) + end +end + +def fun_l0_n806(x) + if (x < 1) + fun_l1_n912(x) + else + fun_l1_n766(x) + end +end + +def fun_l0_n807(x) + if (x < 1) + fun_l1_n656(x) + else + fun_l1_n765(x) + end +end + +def fun_l0_n808(x) + if (x < 1) + fun_l1_n517(x) + else + fun_l1_n964(x) + end +end + +def fun_l0_n809(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n69(x) + end +end + +def fun_l0_n810(x) + if (x < 1) + fun_l1_n527(x) + else + fun_l1_n841(x) + end +end + +def fun_l0_n811(x) + if (x < 1) + fun_l1_n564(x) + else + fun_l1_n541(x) + end +end + +def fun_l0_n812(x) + if (x < 1) + fun_l1_n754(x) + else + fun_l1_n681(x) + end +end + +def fun_l0_n813(x) + if (x < 1) + fun_l1_n21(x) + else + fun_l1_n561(x) + end +end + +def fun_l0_n814(x) + if (x < 1) + fun_l1_n547(x) + else + fun_l1_n631(x) + end +end + +def fun_l0_n815(x) + if (x < 1) + fun_l1_n956(x) + else + fun_l1_n889(x) + end +end + +def fun_l0_n816(x) + if (x < 1) + fun_l1_n817(x) + else + fun_l1_n957(x) + end +end + +def fun_l0_n817(x) + if (x < 1) + fun_l1_n622(x) + else + fun_l1_n827(x) + end +end + +def fun_l0_n818(x) + if (x < 1) + fun_l1_n7(x) + else + fun_l1_n208(x) + end +end + +def fun_l0_n819(x) + if (x < 1) + fun_l1_n411(x) + else + fun_l1_n742(x) + end +end + +def fun_l0_n820(x) + if (x < 1) + fun_l1_n676(x) + else + fun_l1_n144(x) + end +end + +def fun_l0_n821(x) + if (x < 1) + fun_l1_n489(x) + else + fun_l1_n963(x) + end +end + +def fun_l0_n822(x) + if (x < 1) + fun_l1_n645(x) + else + fun_l1_n953(x) + end +end + +def fun_l0_n823(x) + if (x < 1) + fun_l1_n974(x) + else + fun_l1_n75(x) + end +end + +def fun_l0_n824(x) + if (x < 1) + fun_l1_n295(x) + else + fun_l1_n249(x) + end +end + +def fun_l0_n825(x) + if (x < 1) + fun_l1_n141(x) + else + fun_l1_n633(x) + end +end + +def fun_l0_n826(x) + if (x < 1) + fun_l1_n317(x) + else + fun_l1_n152(x) + end +end + +def fun_l0_n827(x) + if (x < 1) + fun_l1_n570(x) + else + fun_l1_n377(x) + end +end + +def fun_l0_n828(x) + if (x < 1) + fun_l1_n392(x) + else + fun_l1_n477(x) + end +end + +def fun_l0_n829(x) + if (x < 1) + fun_l1_n277(x) + else + fun_l1_n276(x) + end +end + +def fun_l0_n830(x) + if (x < 1) + fun_l1_n579(x) + else + fun_l1_n648(x) + end +end + +def fun_l0_n831(x) + if (x < 1) + fun_l1_n8(x) + else + fun_l1_n25(x) + end +end + +def fun_l0_n832(x) + if (x < 1) + fun_l1_n724(x) + else + fun_l1_n617(x) + end +end + +def fun_l0_n833(x) + if (x < 1) + fun_l1_n771(x) + else + fun_l1_n619(x) + end +end + +def fun_l0_n834(x) + if (x < 1) + fun_l1_n23(x) + else + fun_l1_n127(x) + end +end + +def fun_l0_n835(x) + if (x < 1) + fun_l1_n322(x) + else + fun_l1_n327(x) + end +end + +def fun_l0_n836(x) + if (x < 1) + fun_l1_n7(x) + else + fun_l1_n600(x) + end +end + +def fun_l0_n837(x) + if (x < 1) + fun_l1_n796(x) + else + fun_l1_n782(x) + end +end + +def fun_l0_n838(x) + if (x < 1) + fun_l1_n937(x) + else + fun_l1_n899(x) + end +end + +def fun_l0_n839(x) + if (x < 1) + fun_l1_n16(x) + else + fun_l1_n349(x) + end +end + +def fun_l0_n840(x) + if (x < 1) + fun_l1_n622(x) + else + fun_l1_n960(x) + end +end + +def fun_l0_n841(x) + if (x < 1) + fun_l1_n295(x) + else + fun_l1_n176(x) + end +end + +def fun_l0_n842(x) + if (x < 1) + fun_l1_n302(x) + else + fun_l1_n639(x) + end +end + +def fun_l0_n843(x) + if (x < 1) + fun_l1_n342(x) + else + fun_l1_n373(x) + end +end + +def fun_l0_n844(x) + if (x < 1) + fun_l1_n5(x) + else + fun_l1_n787(x) + end +end + +def fun_l0_n845(x) + if (x < 1) + fun_l1_n89(x) + else + fun_l1_n951(x) + end +end + +def fun_l0_n846(x) + if (x < 1) + fun_l1_n954(x) + else + fun_l1_n982(x) + end +end + +def fun_l0_n847(x) + if (x < 1) + fun_l1_n971(x) + else + fun_l1_n917(x) + end +end + +def fun_l0_n848(x) + if (x < 1) + fun_l1_n845(x) + else + fun_l1_n343(x) + end +end + +def fun_l0_n849(x) + if (x < 1) + fun_l1_n684(x) + else + fun_l1_n683(x) + end +end + +def fun_l0_n850(x) + if (x < 1) + fun_l1_n670(x) + else + fun_l1_n256(x) + end +end + +def fun_l0_n851(x) + if (x < 1) + fun_l1_n405(x) + else + fun_l1_n123(x) + end +end + +def fun_l0_n852(x) + if (x < 1) + fun_l1_n809(x) + else + fun_l1_n691(x) + end +end + +def fun_l0_n853(x) + if (x < 1) + fun_l1_n937(x) + else + fun_l1_n92(x) + end +end + +def fun_l0_n854(x) + if (x < 1) + fun_l1_n735(x) + else + fun_l1_n948(x) + end +end + +def fun_l0_n855(x) + if (x < 1) + fun_l1_n684(x) + else + fun_l1_n566(x) + end +end + +def fun_l0_n856(x) + if (x < 1) + fun_l1_n508(x) + else + fun_l1_n35(x) + end +end + +def fun_l0_n857(x) + if (x < 1) + fun_l1_n865(x) + else + fun_l1_n930(x) + end +end + +def fun_l0_n858(x) + if (x < 1) + fun_l1_n937(x) + else + fun_l1_n241(x) + end +end + +def fun_l0_n859(x) + if (x < 1) + fun_l1_n938(x) + else + fun_l1_n108(x) + end +end + +def fun_l0_n860(x) + if (x < 1) + fun_l1_n491(x) + else + fun_l1_n119(x) + end +end + +def fun_l0_n861(x) + if (x < 1) + fun_l1_n991(x) + else + fun_l1_n198(x) + end +end + +def fun_l0_n862(x) + if (x < 1) + fun_l1_n846(x) + else + fun_l1_n513(x) + end +end + +def fun_l0_n863(x) + if (x < 1) + fun_l1_n279(x) + else + fun_l1_n229(x) + end +end + +def fun_l0_n864(x) + if (x < 1) + fun_l1_n52(x) + else + fun_l1_n765(x) + end +end + +def fun_l0_n865(x) + if (x < 1) + fun_l1_n35(x) + else + fun_l1_n572(x) + end +end + +def fun_l0_n866(x) + if (x < 1) + fun_l1_n4(x) + else + fun_l1_n645(x) + end +end + +def fun_l0_n867(x) + if (x < 1) + fun_l1_n112(x) + else + fun_l1_n758(x) + end +end + +def fun_l0_n868(x) + if (x < 1) + fun_l1_n924(x) + else + fun_l1_n251(x) + end +end + +def fun_l0_n869(x) + if (x < 1) + fun_l1_n558(x) + else + fun_l1_n818(x) + end +end + +def fun_l0_n870(x) + if (x < 1) + fun_l1_n804(x) + else + fun_l1_n746(x) + end +end + +def fun_l0_n871(x) + if (x < 1) + fun_l1_n111(x) + else + fun_l1_n407(x) + end +end + +def fun_l0_n872(x) + if (x < 1) + fun_l1_n973(x) + else + fun_l1_n384(x) + end +end + +def fun_l0_n873(x) + if (x < 1) + fun_l1_n102(x) + else + fun_l1_n199(x) + end +end + +def fun_l0_n874(x) + if (x < 1) + fun_l1_n735(x) + else + fun_l1_n903(x) + end +end + +def fun_l0_n875(x) + if (x < 1) + fun_l1_n95(x) + else + fun_l1_n720(x) + end +end + +def fun_l0_n876(x) + if (x < 1) + fun_l1_n864(x) + else + fun_l1_n970(x) + end +end + +def fun_l0_n877(x) + if (x < 1) + fun_l1_n729(x) + else + fun_l1_n207(x) + end +end + +def fun_l0_n878(x) + if (x < 1) + fun_l1_n104(x) + else + fun_l1_n209(x) + end +end + +def fun_l0_n879(x) + if (x < 1) + fun_l1_n566(x) + else + fun_l1_n918(x) + end +end + +def fun_l0_n880(x) + if (x < 1) + fun_l1_n457(x) + else + fun_l1_n104(x) + end +end + +def fun_l0_n881(x) + if (x < 1) + fun_l1_n745(x) + else + fun_l1_n476(x) + end +end + +def fun_l0_n882(x) + if (x < 1) + fun_l1_n346(x) + else + fun_l1_n642(x) + end +end + +def fun_l0_n883(x) + if (x < 1) + fun_l1_n78(x) + else + fun_l1_n210(x) + end +end + +def fun_l0_n884(x) + if (x < 1) + fun_l1_n864(x) + else + fun_l1_n439(x) + end +end + +def fun_l0_n885(x) + if (x < 1) + fun_l1_n0(x) + else + fun_l1_n414(x) + end +end + +def fun_l0_n886(x) + if (x < 1) + fun_l1_n217(x) + else + fun_l1_n444(x) + end +end + +def fun_l0_n887(x) + if (x < 1) + fun_l1_n193(x) + else + fun_l1_n788(x) + end +end + +def fun_l0_n888(x) + if (x < 1) + fun_l1_n30(x) + else + fun_l1_n793(x) + end +end + +def fun_l0_n889(x) + if (x < 1) + fun_l1_n222(x) + else + fun_l1_n936(x) + end +end + +def fun_l0_n890(x) + if (x < 1) + fun_l1_n758(x) + else + fun_l1_n52(x) + end +end + +def fun_l0_n891(x) + if (x < 1) + fun_l1_n796(x) + else + fun_l1_n424(x) + end +end + +def fun_l0_n892(x) + if (x < 1) + fun_l1_n627(x) + else + fun_l1_n284(x) + end +end + +def fun_l0_n893(x) + if (x < 1) + fun_l1_n42(x) + else + fun_l1_n193(x) + end +end + +def fun_l0_n894(x) + if (x < 1) + fun_l1_n90(x) + else + fun_l1_n158(x) + end +end + +def fun_l0_n895(x) + if (x < 1) + fun_l1_n878(x) + else + fun_l1_n396(x) + end +end + +def fun_l0_n896(x) + if (x < 1) + fun_l1_n665(x) + else + fun_l1_n731(x) + end +end + +def fun_l0_n897(x) + if (x < 1) + fun_l1_n618(x) + else + fun_l1_n152(x) + end +end + +def fun_l0_n898(x) + if (x < 1) + fun_l1_n64(x) + else + fun_l1_n697(x) + end +end + +def fun_l0_n899(x) + if (x < 1) + fun_l1_n354(x) + else + fun_l1_n657(x) + end +end + +def fun_l0_n900(x) + if (x < 1) + fun_l1_n79(x) + else + fun_l1_n794(x) + end +end + +def fun_l0_n901(x) + if (x < 1) + fun_l1_n623(x) + else + fun_l1_n392(x) + end +end + +def fun_l0_n902(x) + if (x < 1) + fun_l1_n529(x) + else + fun_l1_n708(x) + end +end + +def fun_l0_n903(x) + if (x < 1) + fun_l1_n900(x) + else + fun_l1_n830(x) + end +end + +def fun_l0_n904(x) + if (x < 1) + fun_l1_n424(x) + else + fun_l1_n564(x) + end +end + +def fun_l0_n905(x) + if (x < 1) + fun_l1_n557(x) + else + fun_l1_n612(x) + end +end + +def fun_l0_n906(x) + if (x < 1) + fun_l1_n725(x) + else + fun_l1_n166(x) + end +end + +def fun_l0_n907(x) + if (x < 1) + fun_l1_n534(x) + else + fun_l1_n159(x) + end +end + +def fun_l0_n908(x) + if (x < 1) + fun_l1_n50(x) + else + fun_l1_n201(x) + end +end + +def fun_l0_n909(x) + if (x < 1) + fun_l1_n568(x) + else + fun_l1_n276(x) + end +end + +def fun_l0_n910(x) + if (x < 1) + fun_l1_n0(x) + else + fun_l1_n324(x) + end +end + +def fun_l0_n911(x) + if (x < 1) + fun_l1_n926(x) + else + fun_l1_n524(x) + end +end + +def fun_l0_n912(x) + if (x < 1) + fun_l1_n498(x) + else + fun_l1_n650(x) + end +end + +def fun_l0_n913(x) + if (x < 1) + fun_l1_n593(x) + else + fun_l1_n860(x) + end +end + +def fun_l0_n914(x) + if (x < 1) + fun_l1_n726(x) + else + fun_l1_n440(x) + end +end + +def fun_l0_n915(x) + if (x < 1) + fun_l1_n422(x) + else + fun_l1_n627(x) + end +end + +def fun_l0_n916(x) + if (x < 1) + fun_l1_n346(x) + else + fun_l1_n932(x) + end +end + +def fun_l0_n917(x) + if (x < 1) + fun_l1_n403(x) + else + fun_l1_n58(x) + end +end + +def fun_l0_n918(x) + if (x < 1) + fun_l1_n989(x) + else + fun_l1_n579(x) + end +end + +def fun_l0_n919(x) + if (x < 1) + fun_l1_n933(x) + else + fun_l1_n434(x) + end +end + +def fun_l0_n920(x) + if (x < 1) + fun_l1_n899(x) + else + fun_l1_n377(x) + end +end + +def fun_l0_n921(x) + if (x < 1) + fun_l1_n17(x) + else + fun_l1_n637(x) + end +end + +def fun_l0_n922(x) + if (x < 1) + fun_l1_n551(x) + else + fun_l1_n693(x) + end +end + +def fun_l0_n923(x) + if (x < 1) + fun_l1_n861(x) + else + fun_l1_n248(x) + end +end + +def fun_l0_n924(x) + if (x < 1) + fun_l1_n171(x) + else + fun_l1_n75(x) + end +end + +def fun_l0_n925(x) + if (x < 1) + fun_l1_n233(x) + else + fun_l1_n444(x) + end +end + +def fun_l0_n926(x) + if (x < 1) + fun_l1_n310(x) + else + fun_l1_n941(x) + end +end + +def fun_l0_n927(x) + if (x < 1) + fun_l1_n363(x) + else + fun_l1_n567(x) + end +end + +def fun_l0_n928(x) + if (x < 1) + fun_l1_n632(x) + else + fun_l1_n840(x) + end +end + +def fun_l0_n929(x) + if (x < 1) + fun_l1_n368(x) + else + fun_l1_n713(x) + end +end + +def fun_l0_n930(x) + if (x < 1) + fun_l1_n37(x) + else + fun_l1_n355(x) + end +end + +def fun_l0_n931(x) + if (x < 1) + fun_l1_n907(x) + else + fun_l1_n784(x) + end +end + +def fun_l0_n932(x) + if (x < 1) + fun_l1_n591(x) + else + fun_l1_n844(x) + end +end + +def fun_l0_n933(x) + if (x < 1) + fun_l1_n996(x) + else + fun_l1_n943(x) + end +end + +def fun_l0_n934(x) + if (x < 1) + fun_l1_n631(x) + else + fun_l1_n643(x) + end +end + +def fun_l0_n935(x) + if (x < 1) + fun_l1_n875(x) + else + fun_l1_n89(x) + end +end + +def fun_l0_n936(x) + if (x < 1) + fun_l1_n842(x) + else + fun_l1_n595(x) + end +end + +def fun_l0_n937(x) + if (x < 1) + fun_l1_n921(x) + else + fun_l1_n271(x) + end +end + +def fun_l0_n938(x) + if (x < 1) + fun_l1_n222(x) + else + fun_l1_n170(x) + end +end + +def fun_l0_n939(x) + if (x < 1) + fun_l1_n567(x) + else + fun_l1_n463(x) + end +end + +def fun_l0_n940(x) + if (x < 1) + fun_l1_n456(x) + else + fun_l1_n192(x) + end +end + +def fun_l0_n941(x) + if (x < 1) + fun_l1_n32(x) + else + fun_l1_n951(x) + end +end + +def fun_l0_n942(x) + if (x < 1) + fun_l1_n14(x) + else + fun_l1_n135(x) + end +end + +def fun_l0_n943(x) + if (x < 1) + fun_l1_n15(x) + else + fun_l1_n234(x) + end +end + +def fun_l0_n944(x) + if (x < 1) + fun_l1_n119(x) + else + fun_l1_n33(x) + end +end + +def fun_l0_n945(x) + if (x < 1) + fun_l1_n859(x) + else + fun_l1_n497(x) + end +end + +def fun_l0_n946(x) + if (x < 1) + fun_l1_n178(x) + else + fun_l1_n369(x) + end +end + +def fun_l0_n947(x) + if (x < 1) + fun_l1_n64(x) + else + fun_l1_n356(x) + end +end + +def fun_l0_n948(x) + if (x < 1) + fun_l1_n279(x) + else + fun_l1_n244(x) + end +end + +def fun_l0_n949(x) + if (x < 1) + fun_l1_n728(x) + else + fun_l1_n548(x) + end +end + +def fun_l0_n950(x) + if (x < 1) + fun_l1_n3(x) + else + fun_l1_n698(x) + end +end + +def fun_l0_n951(x) + if (x < 1) + fun_l1_n665(x) + else + fun_l1_n198(x) + end +end + +def fun_l0_n952(x) + if (x < 1) + fun_l1_n812(x) + else + fun_l1_n964(x) + end +end + +def fun_l0_n953(x) + if (x < 1) + fun_l1_n851(x) + else + fun_l1_n877(x) + end +end + +def fun_l0_n954(x) + if (x < 1) + fun_l1_n415(x) + else + fun_l1_n379(x) + end +end + +def fun_l0_n955(x) + if (x < 1) + fun_l1_n806(x) + else + fun_l1_n919(x) + end +end + +def fun_l0_n956(x) + if (x < 1) + fun_l1_n207(x) + else + fun_l1_n798(x) + end +end + +def fun_l0_n957(x) + if (x < 1) + fun_l1_n269(x) + else + fun_l1_n416(x) + end +end + +def fun_l0_n958(x) + if (x < 1) + fun_l1_n654(x) + else + fun_l1_n236(x) + end +end + +def fun_l0_n959(x) + if (x < 1) + fun_l1_n392(x) + else + fun_l1_n623(x) + end +end + +def fun_l0_n960(x) + if (x < 1) + fun_l1_n889(x) + else + fun_l1_n279(x) + end +end + +def fun_l0_n961(x) + if (x < 1) + fun_l1_n476(x) + else + fun_l1_n201(x) + end +end + +def fun_l0_n962(x) + if (x < 1) + fun_l1_n799(x) + else + fun_l1_n570(x) + end +end + +def fun_l0_n963(x) + if (x < 1) + fun_l1_n802(x) + else + fun_l1_n114(x) + end +end + +def fun_l0_n964(x) + if (x < 1) + fun_l1_n197(x) + else + fun_l1_n422(x) + end +end + +def fun_l0_n965(x) + if (x < 1) + fun_l1_n37(x) + else + fun_l1_n691(x) + end +end + +def fun_l0_n966(x) + if (x < 1) + fun_l1_n775(x) + else + fun_l1_n854(x) + end +end + +def fun_l0_n967(x) + if (x < 1) + fun_l1_n373(x) + else + fun_l1_n306(x) + end +end + +def fun_l0_n968(x) + if (x < 1) + fun_l1_n154(x) + else + fun_l1_n122(x) + end +end + +def fun_l0_n969(x) + if (x < 1) + fun_l1_n497(x) + else + fun_l1_n456(x) + end +end + +def fun_l0_n970(x) + if (x < 1) + fun_l1_n621(x) + else + fun_l1_n931(x) + end +end + +def fun_l0_n971(x) + if (x < 1) + fun_l1_n963(x) + else + fun_l1_n613(x) + end +end + +def fun_l0_n972(x) + if (x < 1) + fun_l1_n613(x) + else + fun_l1_n508(x) + end +end + +def fun_l0_n973(x) + if (x < 1) + fun_l1_n466(x) + else + fun_l1_n929(x) + end +end + +def fun_l0_n974(x) + if (x < 1) + fun_l1_n247(x) + else + fun_l1_n610(x) + end +end + +def fun_l0_n975(x) + if (x < 1) + fun_l1_n674(x) + else + fun_l1_n609(x) + end +end + +def fun_l0_n976(x) + if (x < 1) + fun_l1_n963(x) + else + fun_l1_n601(x) + end +end + +def fun_l0_n977(x) + if (x < 1) + fun_l1_n728(x) + else + fun_l1_n242(x) + end +end + +def fun_l0_n978(x) + if (x < 1) + fun_l1_n515(x) + else + fun_l1_n113(x) + end +end + +def fun_l0_n979(x) + if (x < 1) + fun_l1_n734(x) + else + fun_l1_n271(x) + end +end + +def fun_l0_n980(x) + if (x < 1) + fun_l1_n837(x) + else + fun_l1_n733(x) + end +end + +def fun_l0_n981(x) + if (x < 1) + fun_l1_n326(x) + else + fun_l1_n213(x) + end +end + +def fun_l0_n982(x) + if (x < 1) + fun_l1_n733(x) + else + fun_l1_n198(x) + end +end + +def fun_l0_n983(x) + if (x < 1) + fun_l1_n989(x) + else + fun_l1_n700(x) + end +end + +def fun_l0_n984(x) + if (x < 1) + fun_l1_n266(x) + else + fun_l1_n348(x) + end +end + +def fun_l0_n985(x) + if (x < 1) + fun_l1_n931(x) + else + fun_l1_n646(x) + end +end + +def fun_l0_n986(x) + if (x < 1) + fun_l1_n435(x) + else + fun_l1_n747(x) + end +end + +def fun_l0_n987(x) + if (x < 1) + fun_l1_n474(x) + else + fun_l1_n638(x) + end +end + +def fun_l0_n988(x) + if (x < 1) + fun_l1_n615(x) + else + fun_l1_n283(x) + end +end + +def fun_l0_n989(x) + if (x < 1) + fun_l1_n410(x) + else + fun_l1_n289(x) + end +end + +def fun_l0_n990(x) + if (x < 1) + fun_l1_n633(x) + else + fun_l1_n77(x) + end +end + +def fun_l0_n991(x) + if (x < 1) + fun_l1_n153(x) + else + fun_l1_n255(x) + end +end + +def fun_l0_n992(x) + if (x < 1) + fun_l1_n447(x) + else + fun_l1_n239(x) + end +end + +def fun_l0_n993(x) + if (x < 1) + fun_l1_n837(x) + else + fun_l1_n582(x) + end +end + +def fun_l0_n994(x) + if (x < 1) + fun_l1_n385(x) + else + fun_l1_n939(x) + end +end + +def fun_l0_n995(x) + if (x < 1) + fun_l1_n236(x) + else + fun_l1_n497(x) + end +end + +def fun_l0_n996(x) + if (x < 1) + fun_l1_n63(x) + else + fun_l1_n721(x) + end +end + +def fun_l0_n997(x) + if (x < 1) + fun_l1_n457(x) + else + fun_l1_n376(x) + end +end + +def fun_l0_n998(x) + if (x < 1) + fun_l1_n362(x) + else + fun_l1_n478(x) + end +end + +def fun_l0_n999(x) + if (x < 1) + fun_l1_n554(x) + else + fun_l1_n422(x) + end +end + +def fun_l1_n0(x) + if (x < 1) + fun_l2_n498(x) + else + fun_l2_n461(x) + end +end + +def fun_l1_n1(x) + if (x < 1) + fun_l2_n424(x) + else + fun_l2_n137(x) + end +end + +def fun_l1_n2(x) + if (x < 1) + fun_l2_n325(x) + else + fun_l2_n95(x) + end +end + +def fun_l1_n3(x) + if (x < 1) + fun_l2_n917(x) + else + fun_l2_n469(x) + end +end + +def fun_l1_n4(x) + if (x < 1) + fun_l2_n730(x) + else + fun_l2_n147(x) + end +end + +def fun_l1_n5(x) + if (x < 1) + fun_l2_n796(x) + else + fun_l2_n907(x) + end +end + +def fun_l1_n6(x) + if (x < 1) + fun_l2_n555(x) + else + fun_l2_n309(x) + end +end + +def fun_l1_n7(x) + if (x < 1) + fun_l2_n475(x) + else + fun_l2_n193(x) + end +end + +def fun_l1_n8(x) + if (x < 1) + fun_l2_n317(x) + else + fun_l2_n284(x) + end +end + +def fun_l1_n9(x) + if (x < 1) + fun_l2_n297(x) + else + fun_l2_n370(x) + end +end + +def fun_l1_n10(x) + if (x < 1) + fun_l2_n66(x) + else + fun_l2_n959(x) + end +end + +def fun_l1_n11(x) + if (x < 1) + fun_l2_n833(x) + else + fun_l2_n250(x) + end +end + +def fun_l1_n12(x) + if (x < 1) + fun_l2_n640(x) + else + fun_l2_n588(x) + end +end + +def fun_l1_n13(x) + if (x < 1) + fun_l2_n91(x) + else + fun_l2_n294(x) + end +end + +def fun_l1_n14(x) + if (x < 1) + fun_l2_n166(x) + else + fun_l2_n943(x) + end +end + +def fun_l1_n15(x) + if (x < 1) + fun_l2_n352(x) + else + fun_l2_n363(x) + end +end + +def fun_l1_n16(x) + if (x < 1) + fun_l2_n84(x) + else + fun_l2_n278(x) + end +end + +def fun_l1_n17(x) + if (x < 1) + fun_l2_n308(x) + else + fun_l2_n341(x) + end +end + +def fun_l1_n18(x) + if (x < 1) + fun_l2_n713(x) + else + fun_l2_n575(x) + end +end + +def fun_l1_n19(x) + if (x < 1) + fun_l2_n81(x) + else + fun_l2_n301(x) + end +end + +def fun_l1_n20(x) + if (x < 1) + fun_l2_n516(x) + else + fun_l2_n164(x) + end +end + +def fun_l1_n21(x) + if (x < 1) + fun_l2_n900(x) + else + fun_l2_n963(x) + end +end + +def fun_l1_n22(x) + if (x < 1) + fun_l2_n472(x) + else + fun_l2_n288(x) + end +end + +def fun_l1_n23(x) + if (x < 1) + fun_l2_n587(x) + else + fun_l2_n515(x) + end +end + +def fun_l1_n24(x) + if (x < 1) + fun_l2_n506(x) + else + fun_l2_n711(x) + end +end + +def fun_l1_n25(x) + if (x < 1) + fun_l2_n935(x) + else + fun_l2_n177(x) + end +end + +def fun_l1_n26(x) + if (x < 1) + fun_l2_n485(x) + else + fun_l2_n368(x) + end +end + +def fun_l1_n27(x) + if (x < 1) + fun_l2_n984(x) + else + fun_l2_n290(x) + end +end + +def fun_l1_n28(x) + if (x < 1) + fun_l2_n36(x) + else + fun_l2_n837(x) + end +end + +def fun_l1_n29(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n311(x) + end +end + +def fun_l1_n30(x) + if (x < 1) + fun_l2_n215(x) + else + fun_l2_n376(x) + end +end + +def fun_l1_n31(x) + if (x < 1) + fun_l2_n533(x) + else + fun_l2_n92(x) + end +end + +def fun_l1_n32(x) + if (x < 1) + fun_l2_n386(x) + else + fun_l2_n283(x) + end +end + +def fun_l1_n33(x) + if (x < 1) + fun_l2_n268(x) + else + fun_l2_n256(x) + end +end + +def fun_l1_n34(x) + if (x < 1) + fun_l2_n348(x) + else + fun_l2_n464(x) + end +end + +def fun_l1_n35(x) + if (x < 1) + fun_l2_n25(x) + else + fun_l2_n33(x) + end +end + +def fun_l1_n36(x) + if (x < 1) + fun_l2_n387(x) + else + fun_l2_n341(x) + end +end + +def fun_l1_n37(x) + if (x < 1) + fun_l2_n580(x) + else + fun_l2_n476(x) + end +end + +def fun_l1_n38(x) + if (x < 1) + fun_l2_n33(x) + else + fun_l2_n33(x) + end +end + +def fun_l1_n39(x) + if (x < 1) + fun_l2_n861(x) + else + fun_l2_n52(x) + end +end + +def fun_l1_n40(x) + if (x < 1) + fun_l2_n740(x) + else + fun_l2_n943(x) + end +end + +def fun_l1_n41(x) + if (x < 1) + fun_l2_n956(x) + else + fun_l2_n159(x) + end +end + +def fun_l1_n42(x) + if (x < 1) + fun_l2_n445(x) + else + fun_l2_n775(x) + end +end + +def fun_l1_n43(x) + if (x < 1) + fun_l2_n667(x) + else + fun_l2_n282(x) + end +end + +def fun_l1_n44(x) + if (x < 1) + fun_l2_n185(x) + else + fun_l2_n210(x) + end +end + +def fun_l1_n45(x) + if (x < 1) + fun_l2_n490(x) + else + fun_l2_n21(x) + end +end + +def fun_l1_n46(x) + if (x < 1) + fun_l2_n751(x) + else + fun_l2_n639(x) + end +end + +def fun_l1_n47(x) + if (x < 1) + fun_l2_n431(x) + else + fun_l2_n917(x) + end +end + +def fun_l1_n48(x) + if (x < 1) + fun_l2_n187(x) + else + fun_l2_n170(x) + end +end + +def fun_l1_n49(x) + if (x < 1) + fun_l2_n780(x) + else + fun_l2_n77(x) + end +end + +def fun_l1_n50(x) + if (x < 1) + fun_l2_n546(x) + else + fun_l2_n759(x) + end +end + +def fun_l1_n51(x) + if (x < 1) + fun_l2_n453(x) + else + fun_l2_n951(x) + end +end + +def fun_l1_n52(x) + if (x < 1) + fun_l2_n989(x) + else + fun_l2_n716(x) + end +end + +def fun_l1_n53(x) + if (x < 1) + fun_l2_n652(x) + else + fun_l2_n36(x) + end +end + +def fun_l1_n54(x) + if (x < 1) + fun_l2_n187(x) + else + fun_l2_n760(x) + end +end + +def fun_l1_n55(x) + if (x < 1) + fun_l2_n706(x) + else + fun_l2_n927(x) + end +end + +def fun_l1_n56(x) + if (x < 1) + fun_l2_n666(x) + else + fun_l2_n295(x) + end +end + +def fun_l1_n57(x) + if (x < 1) + fun_l2_n424(x) + else + fun_l2_n447(x) + end +end + +def fun_l1_n58(x) + if (x < 1) + fun_l2_n408(x) + else + fun_l2_n337(x) + end +end + +def fun_l1_n59(x) + if (x < 1) + fun_l2_n567(x) + else + fun_l2_n765(x) + end +end + +def fun_l1_n60(x) + if (x < 1) + fun_l2_n241(x) + else + fun_l2_n701(x) + end +end + +def fun_l1_n61(x) + if (x < 1) + fun_l2_n831(x) + else + fun_l2_n382(x) + end +end + +def fun_l1_n62(x) + if (x < 1) + fun_l2_n634(x) + else + fun_l2_n908(x) + end +end + +def fun_l1_n63(x) + if (x < 1) + fun_l2_n696(x) + else + fun_l2_n48(x) + end +end + +def fun_l1_n64(x) + if (x < 1) + fun_l2_n528(x) + else + fun_l2_n110(x) + end +end + +def fun_l1_n65(x) + if (x < 1) + fun_l2_n767(x) + else + fun_l2_n973(x) + end +end + +def fun_l1_n66(x) + if (x < 1) + fun_l2_n963(x) + else + fun_l2_n673(x) + end +end + +def fun_l1_n67(x) + if (x < 1) + fun_l2_n927(x) + else + fun_l2_n309(x) + end +end + +def fun_l1_n68(x) + if (x < 1) + fun_l2_n851(x) + else + fun_l2_n160(x) + end +end + +def fun_l1_n69(x) + if (x < 1) + fun_l2_n575(x) + else + fun_l2_n800(x) + end +end + +def fun_l1_n70(x) + if (x < 1) + fun_l2_n396(x) + else + fun_l2_n382(x) + end +end + +def fun_l1_n71(x) + if (x < 1) + fun_l2_n508(x) + else + fun_l2_n763(x) + end +end + +def fun_l1_n72(x) + if (x < 1) + fun_l2_n360(x) + else + fun_l2_n848(x) + end +end + +def fun_l1_n73(x) + if (x < 1) + fun_l2_n878(x) + else + fun_l2_n83(x) + end +end + +def fun_l1_n74(x) + if (x < 1) + fun_l2_n573(x) + else + fun_l2_n284(x) + end +end + +def fun_l1_n75(x) + if (x < 1) + fun_l2_n999(x) + else + fun_l2_n954(x) + end +end + +def fun_l1_n76(x) + if (x < 1) + fun_l2_n182(x) + else + fun_l2_n997(x) + end +end + +def fun_l1_n77(x) + if (x < 1) + fun_l2_n802(x) + else + fun_l2_n409(x) + end +end + +def fun_l1_n78(x) + if (x < 1) + fun_l2_n163(x) + else + fun_l2_n417(x) + end +end + +def fun_l1_n79(x) + if (x < 1) + fun_l2_n328(x) + else + fun_l2_n688(x) + end +end + +def fun_l1_n80(x) + if (x < 1) + fun_l2_n699(x) + else + fun_l2_n356(x) + end +end + +def fun_l1_n81(x) + if (x < 1) + fun_l2_n44(x) + else + fun_l2_n302(x) + end +end + +def fun_l1_n82(x) + if (x < 1) + fun_l2_n597(x) + else + fun_l2_n892(x) + end +end + +def fun_l1_n83(x) + if (x < 1) + fun_l2_n494(x) + else + fun_l2_n547(x) + end +end + +def fun_l1_n84(x) + if (x < 1) + fun_l2_n631(x) + else + fun_l2_n922(x) + end +end + +def fun_l1_n85(x) + if (x < 1) + fun_l2_n797(x) + else + fun_l2_n874(x) + end +end + +def fun_l1_n86(x) + if (x < 1) + fun_l2_n209(x) + else + fun_l2_n365(x) + end +end + +def fun_l1_n87(x) + if (x < 1) + fun_l2_n516(x) + else + fun_l2_n371(x) + end +end + +def fun_l1_n88(x) + if (x < 1) + fun_l2_n654(x) + else + fun_l2_n88(x) + end +end + +def fun_l1_n89(x) + if (x < 1) + fun_l2_n70(x) + else + fun_l2_n521(x) + end +end + +def fun_l1_n90(x) + if (x < 1) + fun_l2_n666(x) + else + fun_l2_n749(x) + end +end + +def fun_l1_n91(x) + if (x < 1) + fun_l2_n504(x) + else + fun_l2_n339(x) + end +end + +def fun_l1_n92(x) + if (x < 1) + fun_l2_n734(x) + else + fun_l2_n277(x) + end +end + +def fun_l1_n93(x) + if (x < 1) + fun_l2_n300(x) + else + fun_l2_n826(x) + end +end + +def fun_l1_n94(x) + if (x < 1) + fun_l2_n733(x) + else + fun_l2_n560(x) + end +end + +def fun_l1_n95(x) + if (x < 1) + fun_l2_n834(x) + else + fun_l2_n644(x) + end +end + +def fun_l1_n96(x) + if (x < 1) + fun_l2_n183(x) + else + fun_l2_n238(x) + end +end + +def fun_l1_n97(x) + if (x < 1) + fun_l2_n372(x) + else + fun_l2_n753(x) + end +end + +def fun_l1_n98(x) + if (x < 1) + fun_l2_n208(x) + else + fun_l2_n543(x) + end +end + +def fun_l1_n99(x) + if (x < 1) + fun_l2_n38(x) + else + fun_l2_n974(x) + end +end + +def fun_l1_n100(x) + if (x < 1) + fun_l2_n620(x) + else + fun_l2_n503(x) + end +end + +def fun_l1_n101(x) + if (x < 1) + fun_l2_n248(x) + else + fun_l2_n189(x) + end +end + +def fun_l1_n102(x) + if (x < 1) + fun_l2_n489(x) + else + fun_l2_n390(x) + end +end + +def fun_l1_n103(x) + if (x < 1) + fun_l2_n452(x) + else + fun_l2_n22(x) + end +end + +def fun_l1_n104(x) + if (x < 1) + fun_l2_n542(x) + else + fun_l2_n135(x) + end +end + +def fun_l1_n105(x) + if (x < 1) + fun_l2_n988(x) + else + fun_l2_n118(x) + end +end + +def fun_l1_n106(x) + if (x < 1) + fun_l2_n817(x) + else + fun_l2_n534(x) + end +end + +def fun_l1_n107(x) + if (x < 1) + fun_l2_n812(x) + else + fun_l2_n206(x) + end +end + +def fun_l1_n108(x) + if (x < 1) + fun_l2_n514(x) + else + fun_l2_n300(x) + end +end + +def fun_l1_n109(x) + if (x < 1) + fun_l2_n482(x) + else + fun_l2_n376(x) + end +end + +def fun_l1_n110(x) + if (x < 1) + fun_l2_n571(x) + else + fun_l2_n758(x) + end +end + +def fun_l1_n111(x) + if (x < 1) + fun_l2_n971(x) + else + fun_l2_n811(x) + end +end + +def fun_l1_n112(x) + if (x < 1) + fun_l2_n23(x) + else + fun_l2_n844(x) + end +end + +def fun_l1_n113(x) + if (x < 1) + fun_l2_n865(x) + else + fun_l2_n149(x) + end +end + +def fun_l1_n114(x) + if (x < 1) + fun_l2_n930(x) + else + fun_l2_n327(x) + end +end + +def fun_l1_n115(x) + if (x < 1) + fun_l2_n67(x) + else + fun_l2_n442(x) + end +end + +def fun_l1_n116(x) + if (x < 1) + fun_l2_n278(x) + else + fun_l2_n653(x) + end +end + +def fun_l1_n117(x) + if (x < 1) + fun_l2_n457(x) + else + fun_l2_n179(x) + end +end + +def fun_l1_n118(x) + if (x < 1) + fun_l2_n384(x) + else + fun_l2_n594(x) + end +end + +def fun_l1_n119(x) + if (x < 1) + fun_l2_n361(x) + else + fun_l2_n770(x) + end +end + +def fun_l1_n120(x) + if (x < 1) + fun_l2_n24(x) + else + fun_l2_n269(x) + end +end + +def fun_l1_n121(x) + if (x < 1) + fun_l2_n57(x) + else + fun_l2_n2(x) + end +end + +def fun_l1_n122(x) + if (x < 1) + fun_l2_n421(x) + else + fun_l2_n339(x) + end +end + +def fun_l1_n123(x) + if (x < 1) + fun_l2_n623(x) + else + fun_l2_n985(x) + end +end + +def fun_l1_n124(x) + if (x < 1) + fun_l2_n609(x) + else + fun_l2_n530(x) + end +end + +def fun_l1_n125(x) + if (x < 1) + fun_l2_n565(x) + else + fun_l2_n155(x) + end +end + +def fun_l1_n126(x) + if (x < 1) + fun_l2_n135(x) + else + fun_l2_n971(x) + end +end + +def fun_l1_n127(x) + if (x < 1) + fun_l2_n691(x) + else + fun_l2_n503(x) + end +end + +def fun_l1_n128(x) + if (x < 1) + fun_l2_n555(x) + else + fun_l2_n67(x) + end +end + +def fun_l1_n129(x) + if (x < 1) + fun_l2_n95(x) + else + fun_l2_n192(x) + end +end + +def fun_l1_n130(x) + if (x < 1) + fun_l2_n432(x) + else + fun_l2_n771(x) + end +end + +def fun_l1_n131(x) + if (x < 1) + fun_l2_n993(x) + else + fun_l2_n539(x) + end +end + +def fun_l1_n132(x) + if (x < 1) + fun_l2_n809(x) + else + fun_l2_n902(x) + end +end + +def fun_l1_n133(x) + if (x < 1) + fun_l2_n95(x) + else + fun_l2_n928(x) + end +end + +def fun_l1_n134(x) + if (x < 1) + fun_l2_n781(x) + else + fun_l2_n832(x) + end +end + +def fun_l1_n135(x) + if (x < 1) + fun_l2_n231(x) + else + fun_l2_n392(x) + end +end + +def fun_l1_n136(x) + if (x < 1) + fun_l2_n102(x) + else + fun_l2_n449(x) + end +end + +def fun_l1_n137(x) + if (x < 1) + fun_l2_n196(x) + else + fun_l2_n909(x) + end +end + +def fun_l1_n138(x) + if (x < 1) + fun_l2_n449(x) + else + fun_l2_n190(x) + end +end + +def fun_l1_n139(x) + if (x < 1) + fun_l2_n638(x) + else + fun_l2_n149(x) + end +end + +def fun_l1_n140(x) + if (x < 1) + fun_l2_n523(x) + else + fun_l2_n297(x) + end +end + +def fun_l1_n141(x) + if (x < 1) + fun_l2_n476(x) + else + fun_l2_n161(x) + end +end + +def fun_l1_n142(x) + if (x < 1) + fun_l2_n893(x) + else + fun_l2_n686(x) + end +end + +def fun_l1_n143(x) + if (x < 1) + fun_l2_n958(x) + else + fun_l2_n899(x) + end +end + +def fun_l1_n144(x) + if (x < 1) + fun_l2_n104(x) + else + fun_l2_n912(x) + end +end + +def fun_l1_n145(x) + if (x < 1) + fun_l2_n332(x) + else + fun_l2_n579(x) + end +end + +def fun_l1_n146(x) + if (x < 1) + fun_l2_n40(x) + else + fun_l2_n468(x) + end +end + +def fun_l1_n147(x) + if (x < 1) + fun_l2_n771(x) + else + fun_l2_n314(x) + end +end + +def fun_l1_n148(x) + if (x < 1) + fun_l2_n340(x) + else + fun_l2_n203(x) + end +end + +def fun_l1_n149(x) + if (x < 1) + fun_l2_n952(x) + else + fun_l2_n265(x) + end +end + +def fun_l1_n150(x) + if (x < 1) + fun_l2_n11(x) + else + fun_l2_n303(x) + end +end + +def fun_l1_n151(x) + if (x < 1) + fun_l2_n394(x) + else + fun_l2_n317(x) + end +end + +def fun_l1_n152(x) + if (x < 1) + fun_l2_n140(x) + else + fun_l2_n906(x) + end +end + +def fun_l1_n153(x) + if (x < 1) + fun_l2_n75(x) + else + fun_l2_n485(x) + end +end + +def fun_l1_n154(x) + if (x < 1) + fun_l2_n842(x) + else + fun_l2_n370(x) + end +end + +def fun_l1_n155(x) + if (x < 1) + fun_l2_n346(x) + else + fun_l2_n833(x) + end +end + +def fun_l1_n156(x) + if (x < 1) + fun_l2_n433(x) + else + fun_l2_n373(x) + end +end + +def fun_l1_n157(x) + if (x < 1) + fun_l2_n978(x) + else + fun_l2_n99(x) + end +end + +def fun_l1_n158(x) + if (x < 1) + fun_l2_n540(x) + else + fun_l2_n987(x) + end +end + +def fun_l1_n159(x) + if (x < 1) + fun_l2_n785(x) + else + fun_l2_n478(x) + end +end + +def fun_l1_n160(x) + if (x < 1) + fun_l2_n282(x) + else + fun_l2_n222(x) + end +end + +def fun_l1_n161(x) + if (x < 1) + fun_l2_n29(x) + else + fun_l2_n946(x) + end +end + +def fun_l1_n162(x) + if (x < 1) + fun_l2_n314(x) + else + fun_l2_n758(x) + end +end + +def fun_l1_n163(x) + if (x < 1) + fun_l2_n861(x) + else + fun_l2_n799(x) + end +end + +def fun_l1_n164(x) + if (x < 1) + fun_l2_n403(x) + else + fun_l2_n413(x) + end +end + +def fun_l1_n165(x) + if (x < 1) + fun_l2_n160(x) + else + fun_l2_n794(x) + end +end + +def fun_l1_n166(x) + if (x < 1) + fun_l2_n114(x) + else + fun_l2_n238(x) + end +end + +def fun_l1_n167(x) + if (x < 1) + fun_l2_n806(x) + else + fun_l2_n233(x) + end +end + +def fun_l1_n168(x) + if (x < 1) + fun_l2_n871(x) + else + fun_l2_n53(x) + end +end + +def fun_l1_n169(x) + if (x < 1) + fun_l2_n644(x) + else + fun_l2_n503(x) + end +end + +def fun_l1_n170(x) + if (x < 1) + fun_l2_n172(x) + else + fun_l2_n289(x) + end +end + +def fun_l1_n171(x) + if (x < 1) + fun_l2_n920(x) + else + fun_l2_n851(x) + end +end + +def fun_l1_n172(x) + if (x < 1) + fun_l2_n552(x) + else + fun_l2_n822(x) + end +end + +def fun_l1_n173(x) + if (x < 1) + fun_l2_n747(x) + else + fun_l2_n265(x) + end +end + +def fun_l1_n174(x) + if (x < 1) + fun_l2_n287(x) + else + fun_l2_n762(x) + end +end + +def fun_l1_n175(x) + if (x < 1) + fun_l2_n627(x) + else + fun_l2_n951(x) + end +end + +def fun_l1_n176(x) + if (x < 1) + fun_l2_n459(x) + else + fun_l2_n962(x) + end +end + +def fun_l1_n177(x) + if (x < 1) + fun_l2_n214(x) + else + fun_l2_n145(x) + end +end + +def fun_l1_n178(x) + if (x < 1) + fun_l2_n620(x) + else + fun_l2_n995(x) + end +end + +def fun_l1_n179(x) + if (x < 1) + fun_l2_n136(x) + else + fun_l2_n283(x) + end +end + +def fun_l1_n180(x) + if (x < 1) + fun_l2_n377(x) + else + fun_l2_n672(x) + end +end + +def fun_l1_n181(x) + if (x < 1) + fun_l2_n218(x) + else + fun_l2_n434(x) + end +end + +def fun_l1_n182(x) + if (x < 1) + fun_l2_n522(x) + else + fun_l2_n525(x) + end +end + +def fun_l1_n183(x) + if (x < 1) + fun_l2_n648(x) + else + fun_l2_n725(x) + end +end + +def fun_l1_n184(x) + if (x < 1) + fun_l2_n579(x) + else + fun_l2_n974(x) + end +end + +def fun_l1_n185(x) + if (x < 1) + fun_l2_n10(x) + else + fun_l2_n514(x) + end +end + +def fun_l1_n186(x) + if (x < 1) + fun_l2_n829(x) + else + fun_l2_n754(x) + end +end + +def fun_l1_n187(x) + if (x < 1) + fun_l2_n380(x) + else + fun_l2_n401(x) + end +end + +def fun_l1_n188(x) + if (x < 1) + fun_l2_n839(x) + else + fun_l2_n453(x) + end +end + +def fun_l1_n189(x) + if (x < 1) + fun_l2_n553(x) + else + fun_l2_n553(x) + end +end + +def fun_l1_n190(x) + if (x < 1) + fun_l2_n972(x) + else + fun_l2_n187(x) + end +end + +def fun_l1_n191(x) + if (x < 1) + fun_l2_n275(x) + else + fun_l2_n11(x) + end +end + +def fun_l1_n192(x) + if (x < 1) + fun_l2_n1(x) + else + fun_l2_n927(x) + end +end + +def fun_l1_n193(x) + if (x < 1) + fun_l2_n569(x) + else + fun_l2_n557(x) + end +end + +def fun_l1_n194(x) + if (x < 1) + fun_l2_n380(x) + else + fun_l2_n187(x) + end +end + +def fun_l1_n195(x) + if (x < 1) + fun_l2_n297(x) + else + fun_l2_n813(x) + end +end + +def fun_l1_n196(x) + if (x < 1) + fun_l2_n565(x) + else + fun_l2_n514(x) + end +end + +def fun_l1_n197(x) + if (x < 1) + fun_l2_n473(x) + else + fun_l2_n64(x) + end +end + +def fun_l1_n198(x) + if (x < 1) + fun_l2_n182(x) + else + fun_l2_n363(x) + end +end + +def fun_l1_n199(x) + if (x < 1) + fun_l2_n660(x) + else + fun_l2_n506(x) + end +end + +def fun_l1_n200(x) + if (x < 1) + fun_l2_n834(x) + else + fun_l2_n348(x) + end +end + +def fun_l1_n201(x) + if (x < 1) + fun_l2_n403(x) + else + fun_l2_n432(x) + end +end + +def fun_l1_n202(x) + if (x < 1) + fun_l2_n115(x) + else + fun_l2_n145(x) + end +end + +def fun_l1_n203(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n4(x) + end +end + +def fun_l1_n204(x) + if (x < 1) + fun_l2_n951(x) + else + fun_l2_n753(x) + end +end + +def fun_l1_n205(x) + if (x < 1) + fun_l2_n703(x) + else + fun_l2_n563(x) + end +end + +def fun_l1_n206(x) + if (x < 1) + fun_l2_n614(x) + else + fun_l2_n563(x) + end +end + +def fun_l1_n207(x) + if (x < 1) + fun_l2_n210(x) + else + fun_l2_n139(x) + end +end + +def fun_l1_n208(x) + if (x < 1) + fun_l2_n471(x) + else + fun_l2_n346(x) + end +end + +def fun_l1_n209(x) + if (x < 1) + fun_l2_n922(x) + else + fun_l2_n54(x) + end +end + +def fun_l1_n210(x) + if (x < 1) + fun_l2_n494(x) + else + fun_l2_n41(x) + end +end + +def fun_l1_n211(x) + if (x < 1) + fun_l2_n87(x) + else + fun_l2_n190(x) + end +end + +def fun_l1_n212(x) + if (x < 1) + fun_l2_n458(x) + else + fun_l2_n885(x) + end +end + +def fun_l1_n213(x) + if (x < 1) + fun_l2_n48(x) + else + fun_l2_n225(x) + end +end + +def fun_l1_n214(x) + if (x < 1) + fun_l2_n706(x) + else + fun_l2_n694(x) + end +end + +def fun_l1_n215(x) + if (x < 1) + fun_l2_n116(x) + else + fun_l2_n233(x) + end +end + +def fun_l1_n216(x) + if (x < 1) + fun_l2_n279(x) + else + fun_l2_n857(x) + end +end + +def fun_l1_n217(x) + if (x < 1) + fun_l2_n643(x) + else + fun_l2_n289(x) + end +end + +def fun_l1_n218(x) + if (x < 1) + fun_l2_n535(x) + else + fun_l2_n833(x) + end +end + +def fun_l1_n219(x) + if (x < 1) + fun_l2_n478(x) + else + fun_l2_n793(x) + end +end + +def fun_l1_n220(x) + if (x < 1) + fun_l2_n57(x) + else + fun_l2_n64(x) + end +end + +def fun_l1_n221(x) + if (x < 1) + fun_l2_n36(x) + else + fun_l2_n74(x) + end +end + +def fun_l1_n222(x) + if (x < 1) + fun_l2_n438(x) + else + fun_l2_n616(x) + end +end + +def fun_l1_n223(x) + if (x < 1) + fun_l2_n900(x) + else + fun_l2_n744(x) + end +end + +def fun_l1_n224(x) + if (x < 1) + fun_l2_n780(x) + else + fun_l2_n213(x) + end +end + +def fun_l1_n225(x) + if (x < 1) + fun_l2_n916(x) + else + fun_l2_n471(x) + end +end + +def fun_l1_n226(x) + if (x < 1) + fun_l2_n236(x) + else + fun_l2_n980(x) + end +end + +def fun_l1_n227(x) + if (x < 1) + fun_l2_n28(x) + else + fun_l2_n291(x) + end +end + +def fun_l1_n228(x) + if (x < 1) + fun_l2_n35(x) + else + fun_l2_n353(x) + end +end + +def fun_l1_n229(x) + if (x < 1) + fun_l2_n404(x) + else + fun_l2_n254(x) + end +end + +def fun_l1_n230(x) + if (x < 1) + fun_l2_n641(x) + else + fun_l2_n464(x) + end +end + +def fun_l1_n231(x) + if (x < 1) + fun_l2_n592(x) + else + fun_l2_n646(x) + end +end + +def fun_l1_n232(x) + if (x < 1) + fun_l2_n162(x) + else + fun_l2_n215(x) + end +end + +def fun_l1_n233(x) + if (x < 1) + fun_l2_n219(x) + else + fun_l2_n772(x) + end +end + +def fun_l1_n234(x) + if (x < 1) + fun_l2_n304(x) + else + fun_l2_n963(x) + end +end + +def fun_l1_n235(x) + if (x < 1) + fun_l2_n610(x) + else + fun_l2_n716(x) + end +end + +def fun_l1_n236(x) + if (x < 1) + fun_l2_n151(x) + else + fun_l2_n498(x) + end +end + +def fun_l1_n237(x) + if (x < 1) + fun_l2_n288(x) + else + fun_l2_n261(x) + end +end + +def fun_l1_n238(x) + if (x < 1) + fun_l2_n139(x) + else + fun_l2_n18(x) + end +end + +def fun_l1_n239(x) + if (x < 1) + fun_l2_n559(x) + else + fun_l2_n148(x) + end +end + +def fun_l1_n240(x) + if (x < 1) + fun_l2_n520(x) + else + fun_l2_n250(x) + end +end + +def fun_l1_n241(x) + if (x < 1) + fun_l2_n42(x) + else + fun_l2_n196(x) + end +end + +def fun_l1_n242(x) + if (x < 1) + fun_l2_n16(x) + else + fun_l2_n540(x) + end +end + +def fun_l1_n243(x) + if (x < 1) + fun_l2_n539(x) + else + fun_l2_n890(x) + end +end + +def fun_l1_n244(x) + if (x < 1) + fun_l2_n559(x) + else + fun_l2_n423(x) + end +end + +def fun_l1_n245(x) + if (x < 1) + fun_l2_n110(x) + else + fun_l2_n711(x) + end +end + +def fun_l1_n246(x) + if (x < 1) + fun_l2_n151(x) + else + fun_l2_n407(x) + end +end + +def fun_l1_n247(x) + if (x < 1) + fun_l2_n118(x) + else + fun_l2_n209(x) + end +end + +def fun_l1_n248(x) + if (x < 1) + fun_l2_n764(x) + else + fun_l2_n932(x) + end +end + +def fun_l1_n249(x) + if (x < 1) + fun_l2_n991(x) + else + fun_l2_n828(x) + end +end + +def fun_l1_n250(x) + if (x < 1) + fun_l2_n354(x) + else + fun_l2_n53(x) + end +end + +def fun_l1_n251(x) + if (x < 1) + fun_l2_n63(x) + else + fun_l2_n292(x) + end +end + +def fun_l1_n252(x) + if (x < 1) + fun_l2_n874(x) + else + fun_l2_n544(x) + end +end + +def fun_l1_n253(x) + if (x < 1) + fun_l2_n336(x) + else + fun_l2_n57(x) + end +end + +def fun_l1_n254(x) + if (x < 1) + fun_l2_n302(x) + else + fun_l2_n90(x) + end +end + +def fun_l1_n255(x) + if (x < 1) + fun_l2_n122(x) + else + fun_l2_n888(x) + end +end + +def fun_l1_n256(x) + if (x < 1) + fun_l2_n326(x) + else + fun_l2_n616(x) + end +end + +def fun_l1_n257(x) + if (x < 1) + fun_l2_n77(x) + else + fun_l2_n622(x) + end +end + +def fun_l1_n258(x) + if (x < 1) + fun_l2_n785(x) + else + fun_l2_n229(x) + end +end + +def fun_l1_n259(x) + if (x < 1) + fun_l2_n504(x) + else + fun_l2_n766(x) + end +end + +def fun_l1_n260(x) + if (x < 1) + fun_l2_n857(x) + else + fun_l2_n823(x) + end +end + +def fun_l1_n261(x) + if (x < 1) + fun_l2_n72(x) + else + fun_l2_n875(x) + end +end + +def fun_l1_n262(x) + if (x < 1) + fun_l2_n215(x) + else + fun_l2_n549(x) + end +end + +def fun_l1_n263(x) + if (x < 1) + fun_l2_n232(x) + else + fun_l2_n96(x) + end +end + +def fun_l1_n264(x) + if (x < 1) + fun_l2_n183(x) + else + fun_l2_n351(x) + end +end + +def fun_l1_n265(x) + if (x < 1) + fun_l2_n906(x) + else + fun_l2_n154(x) + end +end + +def fun_l1_n266(x) + if (x < 1) + fun_l2_n234(x) + else + fun_l2_n547(x) + end +end + +def fun_l1_n267(x) + if (x < 1) + fun_l2_n882(x) + else + fun_l2_n802(x) + end +end + +def fun_l1_n268(x) + if (x < 1) + fun_l2_n844(x) + else + fun_l2_n430(x) + end +end + +def fun_l1_n269(x) + if (x < 1) + fun_l2_n781(x) + else + fun_l2_n738(x) + end +end + +def fun_l1_n270(x) + if (x < 1) + fun_l2_n88(x) + else + fun_l2_n439(x) + end +end + +def fun_l1_n271(x) + if (x < 1) + fun_l2_n334(x) + else + fun_l2_n508(x) + end +end + +def fun_l1_n272(x) + if (x < 1) + fun_l2_n871(x) + else + fun_l2_n562(x) + end +end + +def fun_l1_n273(x) + if (x < 1) + fun_l2_n328(x) + else + fun_l2_n356(x) + end +end + +def fun_l1_n274(x) + if (x < 1) + fun_l2_n654(x) + else + fun_l2_n511(x) + end +end + +def fun_l1_n275(x) + if (x < 1) + fun_l2_n309(x) + else + fun_l2_n840(x) + end +end + +def fun_l1_n276(x) + if (x < 1) + fun_l2_n729(x) + else + fun_l2_n72(x) + end +end + +def fun_l1_n277(x) + if (x < 1) + fun_l2_n993(x) + else + fun_l2_n858(x) + end +end + +def fun_l1_n278(x) + if (x < 1) + fun_l2_n664(x) + else + fun_l2_n50(x) + end +end + +def fun_l1_n279(x) + if (x < 1) + fun_l2_n225(x) + else + fun_l2_n403(x) + end +end + +def fun_l1_n280(x) + if (x < 1) + fun_l2_n780(x) + else + fun_l2_n396(x) + end +end + +def fun_l1_n281(x) + if (x < 1) + fun_l2_n114(x) + else + fun_l2_n114(x) + end +end + +def fun_l1_n282(x) + if (x < 1) + fun_l2_n568(x) + else + fun_l2_n610(x) + end +end + +def fun_l1_n283(x) + if (x < 1) + fun_l2_n539(x) + else + fun_l2_n990(x) + end +end + +def fun_l1_n284(x) + if (x < 1) + fun_l2_n773(x) + else + fun_l2_n622(x) + end +end + +def fun_l1_n285(x) + if (x < 1) + fun_l2_n695(x) + else + fun_l2_n101(x) + end +end + +def fun_l1_n286(x) + if (x < 1) + fun_l2_n239(x) + else + fun_l2_n242(x) + end +end + +def fun_l1_n287(x) + if (x < 1) + fun_l2_n191(x) + else + fun_l2_n839(x) + end +end + +def fun_l1_n288(x) + if (x < 1) + fun_l2_n246(x) + else + fun_l2_n179(x) + end +end + +def fun_l1_n289(x) + if (x < 1) + fun_l2_n300(x) + else + fun_l2_n975(x) + end +end + +def fun_l1_n290(x) + if (x < 1) + fun_l2_n436(x) + else + fun_l2_n14(x) + end +end + +def fun_l1_n291(x) + if (x < 1) + fun_l2_n33(x) + else + fun_l2_n303(x) + end +end + +def fun_l1_n292(x) + if (x < 1) + fun_l2_n462(x) + else + fun_l2_n399(x) + end +end + +def fun_l1_n293(x) + if (x < 1) + fun_l2_n782(x) + else + fun_l2_n521(x) + end +end + +def fun_l1_n294(x) + if (x < 1) + fun_l2_n995(x) + else + fun_l2_n944(x) + end +end + +def fun_l1_n295(x) + if (x < 1) + fun_l2_n700(x) + else + fun_l2_n250(x) + end +end + +def fun_l1_n296(x) + if (x < 1) + fun_l2_n866(x) + else + fun_l2_n566(x) + end +end + +def fun_l1_n297(x) + if (x < 1) + fun_l2_n373(x) + else + fun_l2_n881(x) + end +end + +def fun_l1_n298(x) + if (x < 1) + fun_l2_n382(x) + else + fun_l2_n729(x) + end +end + +def fun_l1_n299(x) + if (x < 1) + fun_l2_n878(x) + else + fun_l2_n192(x) + end +end + +def fun_l1_n300(x) + if (x < 1) + fun_l2_n65(x) + else + fun_l2_n434(x) + end +end + +def fun_l1_n301(x) + if (x < 1) + fun_l2_n513(x) + else + fun_l2_n617(x) + end +end + +def fun_l1_n302(x) + if (x < 1) + fun_l2_n972(x) + else + fun_l2_n482(x) + end +end + +def fun_l1_n303(x) + if (x < 1) + fun_l2_n533(x) + else + fun_l2_n774(x) + end +end + +def fun_l1_n304(x) + if (x < 1) + fun_l2_n439(x) + else + fun_l2_n351(x) + end +end + +def fun_l1_n305(x) + if (x < 1) + fun_l2_n181(x) + else + fun_l2_n74(x) + end +end + +def fun_l1_n306(x) + if (x < 1) + fun_l2_n117(x) + else + fun_l2_n962(x) + end +end + +def fun_l1_n307(x) + if (x < 1) + fun_l2_n499(x) + else + fun_l2_n183(x) + end +end + +def fun_l1_n308(x) + if (x < 1) + fun_l2_n358(x) + else + fun_l2_n226(x) + end +end + +def fun_l1_n309(x) + if (x < 1) + fun_l2_n227(x) + else + fun_l2_n425(x) + end +end + +def fun_l1_n310(x) + if (x < 1) + fun_l2_n724(x) + else + fun_l2_n278(x) + end +end + +def fun_l1_n311(x) + if (x < 1) + fun_l2_n784(x) + else + fun_l2_n888(x) + end +end + +def fun_l1_n312(x) + if (x < 1) + fun_l2_n952(x) + else + fun_l2_n849(x) + end +end + +def fun_l1_n313(x) + if (x < 1) + fun_l2_n921(x) + else + fun_l2_n31(x) + end +end + +def fun_l1_n314(x) + if (x < 1) + fun_l2_n469(x) + else + fun_l2_n856(x) + end +end + +def fun_l1_n315(x) + if (x < 1) + fun_l2_n89(x) + else + fun_l2_n949(x) + end +end + +def fun_l1_n316(x) + if (x < 1) + fun_l2_n216(x) + else + fun_l2_n410(x) + end +end + +def fun_l1_n317(x) + if (x < 1) + fun_l2_n591(x) + else + fun_l2_n203(x) + end +end + +def fun_l1_n318(x) + if (x < 1) + fun_l2_n19(x) + else + fun_l2_n461(x) + end +end + +def fun_l1_n319(x) + if (x < 1) + fun_l2_n875(x) + else + fun_l2_n996(x) + end +end + +def fun_l1_n320(x) + if (x < 1) + fun_l2_n696(x) + else + fun_l2_n987(x) + end +end + +def fun_l1_n321(x) + if (x < 1) + fun_l2_n708(x) + else + fun_l2_n150(x) + end +end + +def fun_l1_n322(x) + if (x < 1) + fun_l2_n324(x) + else + fun_l2_n814(x) + end +end + +def fun_l1_n323(x) + if (x < 1) + fun_l2_n427(x) + else + fun_l2_n472(x) + end +end + +def fun_l1_n324(x) + if (x < 1) + fun_l2_n847(x) + else + fun_l2_n482(x) + end +end + +def fun_l1_n325(x) + if (x < 1) + fun_l2_n335(x) + else + fun_l2_n854(x) + end +end + +def fun_l1_n326(x) + if (x < 1) + fun_l2_n635(x) + else + fun_l2_n276(x) + end +end + +def fun_l1_n327(x) + if (x < 1) + fun_l2_n539(x) + else + fun_l2_n885(x) + end +end + +def fun_l1_n328(x) + if (x < 1) + fun_l2_n979(x) + else + fun_l2_n558(x) + end +end + +def fun_l1_n329(x) + if (x < 1) + fun_l2_n35(x) + else + fun_l2_n696(x) + end +end + +def fun_l1_n330(x) + if (x < 1) + fun_l2_n483(x) + else + fun_l2_n218(x) + end +end + +def fun_l1_n331(x) + if (x < 1) + fun_l2_n3(x) + else + fun_l2_n324(x) + end +end + +def fun_l1_n332(x) + if (x < 1) + fun_l2_n396(x) + else + fun_l2_n718(x) + end +end + +def fun_l1_n333(x) + if (x < 1) + fun_l2_n973(x) + else + fun_l2_n663(x) + end +end + +def fun_l1_n334(x) + if (x < 1) + fun_l2_n441(x) + else + fun_l2_n468(x) + end +end + +def fun_l1_n335(x) + if (x < 1) + fun_l2_n511(x) + else + fun_l2_n455(x) + end +end + +def fun_l1_n336(x) + if (x < 1) + fun_l2_n732(x) + else + fun_l2_n14(x) + end +end + +def fun_l1_n337(x) + if (x < 1) + fun_l2_n484(x) + else + fun_l2_n482(x) + end +end + +def fun_l1_n338(x) + if (x < 1) + fun_l2_n604(x) + else + fun_l2_n683(x) + end +end + +def fun_l1_n339(x) + if (x < 1) + fun_l2_n334(x) + else + fun_l2_n710(x) + end +end + +def fun_l1_n340(x) + if (x < 1) + fun_l2_n233(x) + else + fun_l2_n394(x) + end +end + +def fun_l1_n341(x) + if (x < 1) + fun_l2_n948(x) + else + fun_l2_n473(x) + end +end + +def fun_l1_n342(x) + if (x < 1) + fun_l2_n858(x) + else + fun_l2_n466(x) + end +end + +def fun_l1_n343(x) + if (x < 1) + fun_l2_n647(x) + else + fun_l2_n604(x) + end +end + +def fun_l1_n344(x) + if (x < 1) + fun_l2_n872(x) + else + fun_l2_n965(x) + end +end + +def fun_l1_n345(x) + if (x < 1) + fun_l2_n845(x) + else + fun_l2_n701(x) + end +end + +def fun_l1_n346(x) + if (x < 1) + fun_l2_n75(x) + else + fun_l2_n332(x) + end +end + +def fun_l1_n347(x) + if (x < 1) + fun_l2_n873(x) + else + fun_l2_n575(x) + end +end + +def fun_l1_n348(x) + if (x < 1) + fun_l2_n303(x) + else + fun_l2_n445(x) + end +end + +def fun_l1_n349(x) + if (x < 1) + fun_l2_n45(x) + else + fun_l2_n312(x) + end +end + +def fun_l1_n350(x) + if (x < 1) + fun_l2_n751(x) + else + fun_l2_n316(x) + end +end + +def fun_l1_n351(x) + if (x < 1) + fun_l2_n781(x) + else + fun_l2_n165(x) + end +end + +def fun_l1_n352(x) + if (x < 1) + fun_l2_n120(x) + else + fun_l2_n595(x) + end +end + +def fun_l1_n353(x) + if (x < 1) + fun_l2_n221(x) + else + fun_l2_n827(x) + end +end + +def fun_l1_n354(x) + if (x < 1) + fun_l2_n290(x) + else + fun_l2_n27(x) + end +end + +def fun_l1_n355(x) + if (x < 1) + fun_l2_n377(x) + else + fun_l2_n28(x) + end +end + +def fun_l1_n356(x) + if (x < 1) + fun_l2_n474(x) + else + fun_l2_n811(x) + end +end + +def fun_l1_n357(x) + if (x < 1) + fun_l2_n90(x) + else + fun_l2_n559(x) + end +end + +def fun_l1_n358(x) + if (x < 1) + fun_l2_n66(x) + else + fun_l2_n234(x) + end +end + +def fun_l1_n359(x) + if (x < 1) + fun_l2_n526(x) + else + fun_l2_n674(x) + end +end + +def fun_l1_n360(x) + if (x < 1) + fun_l2_n449(x) + else + fun_l2_n364(x) + end +end + +def fun_l1_n361(x) + if (x < 1) + fun_l2_n790(x) + else + fun_l2_n835(x) + end +end + +def fun_l1_n362(x) + if (x < 1) + fun_l2_n335(x) + else + fun_l2_n22(x) + end +end + +def fun_l1_n363(x) + if (x < 1) + fun_l2_n982(x) + else + fun_l2_n449(x) + end +end + +def fun_l1_n364(x) + if (x < 1) + fun_l2_n980(x) + else + fun_l2_n861(x) + end +end + +def fun_l1_n365(x) + if (x < 1) + fun_l2_n673(x) + else + fun_l2_n267(x) + end +end + +def fun_l1_n366(x) + if (x < 1) + fun_l2_n862(x) + else + fun_l2_n559(x) + end +end + +def fun_l1_n367(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n275(x) + end +end + +def fun_l1_n368(x) + if (x < 1) + fun_l2_n370(x) + else + fun_l2_n763(x) + end +end + +def fun_l1_n369(x) + if (x < 1) + fun_l2_n680(x) + else + fun_l2_n476(x) + end +end + +def fun_l1_n370(x) + if (x < 1) + fun_l2_n799(x) + else + fun_l2_n724(x) + end +end + +def fun_l1_n371(x) + if (x < 1) + fun_l2_n331(x) + else + fun_l2_n927(x) + end +end + +def fun_l1_n372(x) + if (x < 1) + fun_l2_n875(x) + else + fun_l2_n350(x) + end +end + +def fun_l1_n373(x) + if (x < 1) + fun_l2_n734(x) + else + fun_l2_n172(x) + end +end + +def fun_l1_n374(x) + if (x < 1) + fun_l2_n657(x) + else + fun_l2_n765(x) + end +end + +def fun_l1_n375(x) + if (x < 1) + fun_l2_n950(x) + else + fun_l2_n85(x) + end +end + +def fun_l1_n376(x) + if (x < 1) + fun_l2_n276(x) + else + fun_l2_n892(x) + end +end + +def fun_l1_n377(x) + if (x < 1) + fun_l2_n430(x) + else + fun_l2_n173(x) + end +end + +def fun_l1_n378(x) + if (x < 1) + fun_l2_n376(x) + else + fun_l2_n876(x) + end +end + +def fun_l1_n379(x) + if (x < 1) + fun_l2_n981(x) + else + fun_l2_n314(x) + end +end + +def fun_l1_n380(x) + if (x < 1) + fun_l2_n680(x) + else + fun_l2_n600(x) + end +end + +def fun_l1_n381(x) + if (x < 1) + fun_l2_n54(x) + else + fun_l2_n158(x) + end +end + +def fun_l1_n382(x) + if (x < 1) + fun_l2_n692(x) + else + fun_l2_n673(x) + end +end + +def fun_l1_n383(x) + if (x < 1) + fun_l2_n393(x) + else + fun_l2_n723(x) + end +end + +def fun_l1_n384(x) + if (x < 1) + fun_l2_n899(x) + else + fun_l2_n940(x) + end +end + +def fun_l1_n385(x) + if (x < 1) + fun_l2_n473(x) + else + fun_l2_n846(x) + end +end + +def fun_l1_n386(x) + if (x < 1) + fun_l2_n291(x) + else + fun_l2_n864(x) + end +end + +def fun_l1_n387(x) + if (x < 1) + fun_l2_n174(x) + else + fun_l2_n466(x) + end +end + +def fun_l1_n388(x) + if (x < 1) + fun_l2_n883(x) + else + fun_l2_n613(x) + end +end + +def fun_l1_n389(x) + if (x < 1) + fun_l2_n808(x) + else + fun_l2_n169(x) + end +end + +def fun_l1_n390(x) + if (x < 1) + fun_l2_n94(x) + else + fun_l2_n93(x) + end +end + +def fun_l1_n391(x) + if (x < 1) + fun_l2_n874(x) + else + fun_l2_n400(x) + end +end + +def fun_l1_n392(x) + if (x < 1) + fun_l2_n473(x) + else + fun_l2_n239(x) + end +end + +def fun_l1_n393(x) + if (x < 1) + fun_l2_n64(x) + else + fun_l2_n760(x) + end +end + +def fun_l1_n394(x) + if (x < 1) + fun_l2_n947(x) + else + fun_l2_n354(x) + end +end + +def fun_l1_n395(x) + if (x < 1) + fun_l2_n833(x) + else + fun_l2_n563(x) + end +end + +def fun_l1_n396(x) + if (x < 1) + fun_l2_n429(x) + else + fun_l2_n280(x) + end +end + +def fun_l1_n397(x) + if (x < 1) + fun_l2_n132(x) + else + fun_l2_n486(x) + end +end + +def fun_l1_n398(x) + if (x < 1) + fun_l2_n28(x) + else + fun_l2_n135(x) + end +end + +def fun_l1_n399(x) + if (x < 1) + fun_l2_n804(x) + else + fun_l2_n406(x) + end +end + +def fun_l1_n400(x) + if (x < 1) + fun_l2_n661(x) + else + fun_l2_n216(x) + end +end + +def fun_l1_n401(x) + if (x < 1) + fun_l2_n681(x) + else + fun_l2_n849(x) + end +end + +def fun_l1_n402(x) + if (x < 1) + fun_l2_n13(x) + else + fun_l2_n205(x) + end +end + +def fun_l1_n403(x) + if (x < 1) + fun_l2_n911(x) + else + fun_l2_n63(x) + end +end + +def fun_l1_n404(x) + if (x < 1) + fun_l2_n518(x) + else + fun_l2_n845(x) + end +end + +def fun_l1_n405(x) + if (x < 1) + fun_l2_n699(x) + else + fun_l2_n963(x) + end +end + +def fun_l1_n406(x) + if (x < 1) + fun_l2_n373(x) + else + fun_l2_n485(x) + end +end + +def fun_l1_n407(x) + if (x < 1) + fun_l2_n402(x) + else + fun_l2_n582(x) + end +end + +def fun_l1_n408(x) + if (x < 1) + fun_l2_n802(x) + else + fun_l2_n420(x) + end +end + +def fun_l1_n409(x) + if (x < 1) + fun_l2_n728(x) + else + fun_l2_n50(x) + end +end + +def fun_l1_n410(x) + if (x < 1) + fun_l2_n189(x) + else + fun_l2_n588(x) + end +end + +def fun_l1_n411(x) + if (x < 1) + fun_l2_n51(x) + else + fun_l2_n23(x) + end +end + +def fun_l1_n412(x) + if (x < 1) + fun_l2_n548(x) + else + fun_l2_n200(x) + end +end + +def fun_l1_n413(x) + if (x < 1) + fun_l2_n763(x) + else + fun_l2_n581(x) + end +end + +def fun_l1_n414(x) + if (x < 1) + fun_l2_n650(x) + else + fun_l2_n535(x) + end +end + +def fun_l1_n415(x) + if (x < 1) + fun_l2_n500(x) + else + fun_l2_n579(x) + end +end + +def fun_l1_n416(x) + if (x < 1) + fun_l2_n573(x) + else + fun_l2_n154(x) + end +end + +def fun_l1_n417(x) + if (x < 1) + fun_l2_n685(x) + else + fun_l2_n14(x) + end +end + +def fun_l1_n418(x) + if (x < 1) + fun_l2_n849(x) + else + fun_l2_n91(x) + end +end + +def fun_l1_n419(x) + if (x < 1) + fun_l2_n629(x) + else + fun_l2_n698(x) + end +end + +def fun_l1_n420(x) + if (x < 1) + fun_l2_n273(x) + else + fun_l2_n303(x) + end +end + +def fun_l1_n421(x) + if (x < 1) + fun_l2_n8(x) + else + fun_l2_n476(x) + end +end + +def fun_l1_n422(x) + if (x < 1) + fun_l2_n294(x) + else + fun_l2_n338(x) + end +end + +def fun_l1_n423(x) + if (x < 1) + fun_l2_n408(x) + else + fun_l2_n187(x) + end +end + +def fun_l1_n424(x) + if (x < 1) + fun_l2_n349(x) + else + fun_l2_n896(x) + end +end + +def fun_l1_n425(x) + if (x < 1) + fun_l2_n950(x) + else + fun_l2_n186(x) + end +end + +def fun_l1_n426(x) + if (x < 1) + fun_l2_n817(x) + else + fun_l2_n605(x) + end +end + +def fun_l1_n427(x) + if (x < 1) + fun_l2_n317(x) + else + fun_l2_n31(x) + end +end + +def fun_l1_n428(x) + if (x < 1) + fun_l2_n804(x) + else + fun_l2_n547(x) + end +end + +def fun_l1_n429(x) + if (x < 1) + fun_l2_n730(x) + else + fun_l2_n711(x) + end +end + +def fun_l1_n430(x) + if (x < 1) + fun_l2_n822(x) + else + fun_l2_n749(x) + end +end + +def fun_l1_n431(x) + if (x < 1) + fun_l2_n412(x) + else + fun_l2_n366(x) + end +end + +def fun_l1_n432(x) + if (x < 1) + fun_l2_n462(x) + else + fun_l2_n601(x) + end +end + +def fun_l1_n433(x) + if (x < 1) + fun_l2_n971(x) + else + fun_l2_n878(x) + end +end + +def fun_l1_n434(x) + if (x < 1) + fun_l2_n551(x) + else + fun_l2_n172(x) + end +end + +def fun_l1_n435(x) + if (x < 1) + fun_l2_n914(x) + else + fun_l2_n640(x) + end +end + +def fun_l1_n436(x) + if (x < 1) + fun_l2_n957(x) + else + fun_l2_n846(x) + end +end + +def fun_l1_n437(x) + if (x < 1) + fun_l2_n622(x) + else + fun_l2_n995(x) + end +end + +def fun_l1_n438(x) + if (x < 1) + fun_l2_n830(x) + else + fun_l2_n537(x) + end +end + +def fun_l1_n439(x) + if (x < 1) + fun_l2_n415(x) + else + fun_l2_n863(x) + end +end + +def fun_l1_n440(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n354(x) + end +end + +def fun_l1_n441(x) + if (x < 1) + fun_l2_n525(x) + else + fun_l2_n656(x) + end +end + +def fun_l1_n442(x) + if (x < 1) + fun_l2_n284(x) + else + fun_l2_n722(x) + end +end + +def fun_l1_n443(x) + if (x < 1) + fun_l2_n485(x) + else + fun_l2_n794(x) + end +end + +def fun_l1_n444(x) + if (x < 1) + fun_l2_n268(x) + else + fun_l2_n443(x) + end +end + +def fun_l1_n445(x) + if (x < 1) + fun_l2_n743(x) + else + fun_l2_n723(x) + end +end + +def fun_l1_n446(x) + if (x < 1) + fun_l2_n651(x) + else + fun_l2_n544(x) + end +end + +def fun_l1_n447(x) + if (x < 1) + fun_l2_n936(x) + else + fun_l2_n50(x) + end +end + +def fun_l1_n448(x) + if (x < 1) + fun_l2_n473(x) + else + fun_l2_n749(x) + end +end + +def fun_l1_n449(x) + if (x < 1) + fun_l2_n218(x) + else + fun_l2_n266(x) + end +end + +def fun_l1_n450(x) + if (x < 1) + fun_l2_n686(x) + else + fun_l2_n629(x) + end +end + +def fun_l1_n451(x) + if (x < 1) + fun_l2_n648(x) + else + fun_l2_n322(x) + end +end + +def fun_l1_n452(x) + if (x < 1) + fun_l2_n380(x) + else + fun_l2_n720(x) + end +end + +def fun_l1_n453(x) + if (x < 1) + fun_l2_n53(x) + else + fun_l2_n830(x) + end +end + +def fun_l1_n454(x) + if (x < 1) + fun_l2_n315(x) + else + fun_l2_n742(x) + end +end + +def fun_l1_n455(x) + if (x < 1) + fun_l2_n902(x) + else + fun_l2_n111(x) + end +end + +def fun_l1_n456(x) + if (x < 1) + fun_l2_n924(x) + else + fun_l2_n109(x) + end +end + +def fun_l1_n457(x) + if (x < 1) + fun_l2_n249(x) + else + fun_l2_n865(x) + end +end + +def fun_l1_n458(x) + if (x < 1) + fun_l2_n650(x) + else + fun_l2_n960(x) + end +end + +def fun_l1_n459(x) + if (x < 1) + fun_l2_n273(x) + else + fun_l2_n544(x) + end +end + +def fun_l1_n460(x) + if (x < 1) + fun_l2_n120(x) + else + fun_l2_n322(x) + end +end + +def fun_l1_n461(x) + if (x < 1) + fun_l2_n366(x) + else + fun_l2_n534(x) + end +end + +def fun_l1_n462(x) + if (x < 1) + fun_l2_n380(x) + else + fun_l2_n25(x) + end +end + +def fun_l1_n463(x) + if (x < 1) + fun_l2_n333(x) + else + fun_l2_n303(x) + end +end + +def fun_l1_n464(x) + if (x < 1) + fun_l2_n16(x) + else + fun_l2_n239(x) + end +end + +def fun_l1_n465(x) + if (x < 1) + fun_l2_n539(x) + else + fun_l2_n988(x) + end +end + +def fun_l1_n466(x) + if (x < 1) + fun_l2_n580(x) + else + fun_l2_n86(x) + end +end + +def fun_l1_n467(x) + if (x < 1) + fun_l2_n406(x) + else + fun_l2_n706(x) + end +end + +def fun_l1_n468(x) + if (x < 1) + fun_l2_n858(x) + else + fun_l2_n393(x) + end +end + +def fun_l1_n469(x) + if (x < 1) + fun_l2_n64(x) + else + fun_l2_n482(x) + end +end + +def fun_l1_n470(x) + if (x < 1) + fun_l2_n654(x) + else + fun_l2_n833(x) + end +end + +def fun_l1_n471(x) + if (x < 1) + fun_l2_n161(x) + else + fun_l2_n91(x) + end +end + +def fun_l1_n472(x) + if (x < 1) + fun_l2_n98(x) + else + fun_l2_n661(x) + end +end + +def fun_l1_n473(x) + if (x < 1) + fun_l2_n574(x) + else + fun_l2_n133(x) + end +end + +def fun_l1_n474(x) + if (x < 1) + fun_l2_n109(x) + else + fun_l2_n702(x) + end +end + +def fun_l1_n475(x) + if (x < 1) + fun_l2_n808(x) + else + fun_l2_n584(x) + end +end + +def fun_l1_n476(x) + if (x < 1) + fun_l2_n495(x) + else + fun_l2_n708(x) + end +end + +def fun_l1_n477(x) + if (x < 1) + fun_l2_n649(x) + else + fun_l2_n290(x) + end +end + +def fun_l1_n478(x) + if (x < 1) + fun_l2_n718(x) + else + fun_l2_n998(x) + end +end + +def fun_l1_n479(x) + if (x < 1) + fun_l2_n557(x) + else + fun_l2_n359(x) + end +end + +def fun_l1_n480(x) + if (x < 1) + fun_l2_n958(x) + else + fun_l2_n86(x) + end +end + +def fun_l1_n481(x) + if (x < 1) + fun_l2_n245(x) + else + fun_l2_n124(x) + end +end + +def fun_l1_n482(x) + if (x < 1) + fun_l2_n510(x) + else + fun_l2_n170(x) + end +end + +def fun_l1_n483(x) + if (x < 1) + fun_l2_n550(x) + else + fun_l2_n9(x) + end +end + +def fun_l1_n484(x) + if (x < 1) + fun_l2_n82(x) + else + fun_l2_n351(x) + end +end + +def fun_l1_n485(x) + if (x < 1) + fun_l2_n760(x) + else + fun_l2_n560(x) + end +end + +def fun_l1_n486(x) + if (x < 1) + fun_l2_n550(x) + else + fun_l2_n881(x) + end +end + +def fun_l1_n487(x) + if (x < 1) + fun_l2_n62(x) + else + fun_l2_n213(x) + end +end + +def fun_l1_n488(x) + if (x < 1) + fun_l2_n336(x) + else + fun_l2_n855(x) + end +end + +def fun_l1_n489(x) + if (x < 1) + fun_l2_n172(x) + else + fun_l2_n479(x) + end +end + +def fun_l1_n490(x) + if (x < 1) + fun_l2_n821(x) + else + fun_l2_n767(x) + end +end + +def fun_l1_n491(x) + if (x < 1) + fun_l2_n388(x) + else + fun_l2_n307(x) + end +end + +def fun_l1_n492(x) + if (x < 1) + fun_l2_n158(x) + else + fun_l2_n725(x) + end +end + +def fun_l1_n493(x) + if (x < 1) + fun_l2_n681(x) + else + fun_l2_n767(x) + end +end + +def fun_l1_n494(x) + if (x < 1) + fun_l2_n799(x) + else + fun_l2_n458(x) + end +end + +def fun_l1_n495(x) + if (x < 1) + fun_l2_n379(x) + else + fun_l2_n152(x) + end +end + +def fun_l1_n496(x) + if (x < 1) + fun_l2_n996(x) + else + fun_l2_n296(x) + end +end + +def fun_l1_n497(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n481(x) + end +end + +def fun_l1_n498(x) + if (x < 1) + fun_l2_n887(x) + else + fun_l2_n343(x) + end +end + +def fun_l1_n499(x) + if (x < 1) + fun_l2_n481(x) + else + fun_l2_n368(x) + end +end + +def fun_l1_n500(x) + if (x < 1) + fun_l2_n738(x) + else + fun_l2_n349(x) + end +end + +def fun_l1_n501(x) + if (x < 1) + fun_l2_n104(x) + else + fun_l2_n841(x) + end +end + +def fun_l1_n502(x) + if (x < 1) + fun_l2_n549(x) + else + fun_l2_n684(x) + end +end + +def fun_l1_n503(x) + if (x < 1) + fun_l2_n726(x) + else + fun_l2_n41(x) + end +end + +def fun_l1_n504(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n830(x) + end +end + +def fun_l1_n505(x) + if (x < 1) + fun_l2_n38(x) + else + fun_l2_n815(x) + end +end + +def fun_l1_n506(x) + if (x < 1) + fun_l2_n284(x) + else + fun_l2_n599(x) + end +end + +def fun_l1_n507(x) + if (x < 1) + fun_l2_n665(x) + else + fun_l2_n763(x) + end +end + +def fun_l1_n508(x) + if (x < 1) + fun_l2_n755(x) + else + fun_l2_n51(x) + end +end + +def fun_l1_n509(x) + if (x < 1) + fun_l2_n860(x) + else + fun_l2_n273(x) + end +end + +def fun_l1_n510(x) + if (x < 1) + fun_l2_n967(x) + else + fun_l2_n141(x) + end +end + +def fun_l1_n511(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n953(x) + end +end + +def fun_l1_n512(x) + if (x < 1) + fun_l2_n784(x) + else + fun_l2_n941(x) + end +end + +def fun_l1_n513(x) + if (x < 1) + fun_l2_n499(x) + else + fun_l2_n189(x) + end +end + +def fun_l1_n514(x) + if (x < 1) + fun_l2_n207(x) + else + fun_l2_n187(x) + end +end + +def fun_l1_n515(x) + if (x < 1) + fun_l2_n174(x) + else + fun_l2_n316(x) + end +end + +def fun_l1_n516(x) + if (x < 1) + fun_l2_n884(x) + else + fun_l2_n72(x) + end +end + +def fun_l1_n517(x) + if (x < 1) + fun_l2_n878(x) + else + fun_l2_n423(x) + end +end + +def fun_l1_n518(x) + if (x < 1) + fun_l2_n452(x) + else + fun_l2_n733(x) + end +end + +def fun_l1_n519(x) + if (x < 1) + fun_l2_n586(x) + else + fun_l2_n987(x) + end +end + +def fun_l1_n520(x) + if (x < 1) + fun_l2_n638(x) + else + fun_l2_n276(x) + end +end + +def fun_l1_n521(x) + if (x < 1) + fun_l2_n186(x) + else + fun_l2_n498(x) + end +end + +def fun_l1_n522(x) + if (x < 1) + fun_l2_n816(x) + else + fun_l2_n687(x) + end +end + +def fun_l1_n523(x) + if (x < 1) + fun_l2_n572(x) + else + fun_l2_n878(x) + end +end + +def fun_l1_n524(x) + if (x < 1) + fun_l2_n528(x) + else + fun_l2_n188(x) + end +end + +def fun_l1_n525(x) + if (x < 1) + fun_l2_n719(x) + else + fun_l2_n146(x) + end +end + +def fun_l1_n526(x) + if (x < 1) + fun_l2_n730(x) + else + fun_l2_n209(x) + end +end + +def fun_l1_n527(x) + if (x < 1) + fun_l2_n998(x) + else + fun_l2_n544(x) + end +end + +def fun_l1_n528(x) + if (x < 1) + fun_l2_n288(x) + else + fun_l2_n682(x) + end +end + +def fun_l1_n529(x) + if (x < 1) + fun_l2_n808(x) + else + fun_l2_n651(x) + end +end + +def fun_l1_n530(x) + if (x < 1) + fun_l2_n674(x) + else + fun_l2_n643(x) + end +end + +def fun_l1_n531(x) + if (x < 1) + fun_l2_n42(x) + else + fun_l2_n457(x) + end +end + +def fun_l1_n532(x) + if (x < 1) + fun_l2_n188(x) + else + fun_l2_n218(x) + end +end + +def fun_l1_n533(x) + if (x < 1) + fun_l2_n529(x) + else + fun_l2_n541(x) + end +end + +def fun_l1_n534(x) + if (x < 1) + fun_l2_n820(x) + else + fun_l2_n426(x) + end +end + +def fun_l1_n535(x) + if (x < 1) + fun_l2_n730(x) + else + fun_l2_n36(x) + end +end + +def fun_l1_n536(x) + if (x < 1) + fun_l2_n187(x) + else + fun_l2_n96(x) + end +end + +def fun_l1_n537(x) + if (x < 1) + fun_l2_n1(x) + else + fun_l2_n905(x) + end +end + +def fun_l1_n538(x) + if (x < 1) + fun_l2_n252(x) + else + fun_l2_n597(x) + end +end + +def fun_l1_n539(x) + if (x < 1) + fun_l2_n959(x) + else + fun_l2_n26(x) + end +end + +def fun_l1_n540(x) + if (x < 1) + fun_l2_n959(x) + else + fun_l2_n266(x) + end +end + +def fun_l1_n541(x) + if (x < 1) + fun_l2_n902(x) + else + fun_l2_n957(x) + end +end + +def fun_l1_n542(x) + if (x < 1) + fun_l2_n244(x) + else + fun_l2_n407(x) + end +end + +def fun_l1_n543(x) + if (x < 1) + fun_l2_n319(x) + else + fun_l2_n19(x) + end +end + +def fun_l1_n544(x) + if (x < 1) + fun_l2_n251(x) + else + fun_l2_n92(x) + end +end + +def fun_l1_n545(x) + if (x < 1) + fun_l2_n482(x) + else + fun_l2_n177(x) + end +end + +def fun_l1_n546(x) + if (x < 1) + fun_l2_n338(x) + else + fun_l2_n152(x) + end +end + +def fun_l1_n547(x) + if (x < 1) + fun_l2_n902(x) + else + fun_l2_n243(x) + end +end + +def fun_l1_n548(x) + if (x < 1) + fun_l2_n943(x) + else + fun_l2_n930(x) + end +end + +def fun_l1_n549(x) + if (x < 1) + fun_l2_n775(x) + else + fun_l2_n338(x) + end +end + +def fun_l1_n550(x) + if (x < 1) + fun_l2_n286(x) + else + fun_l2_n347(x) + end +end + +def fun_l1_n551(x) + if (x < 1) + fun_l2_n611(x) + else + fun_l2_n108(x) + end +end + +def fun_l1_n552(x) + if (x < 1) + fun_l2_n515(x) + else + fun_l2_n478(x) + end +end + +def fun_l1_n553(x) + if (x < 1) + fun_l2_n68(x) + else + fun_l2_n943(x) + end +end + +def fun_l1_n554(x) + if (x < 1) + fun_l2_n16(x) + else + fun_l2_n280(x) + end +end + +def fun_l1_n555(x) + if (x < 1) + fun_l2_n421(x) + else + fun_l2_n412(x) + end +end + +def fun_l1_n556(x) + if (x < 1) + fun_l2_n653(x) + else + fun_l2_n527(x) + end +end + +def fun_l1_n557(x) + if (x < 1) + fun_l2_n181(x) + else + fun_l2_n179(x) + end +end + +def fun_l1_n558(x) + if (x < 1) + fun_l2_n270(x) + else + fun_l2_n367(x) + end +end + +def fun_l1_n559(x) + if (x < 1) + fun_l2_n323(x) + else + fun_l2_n453(x) + end +end + +def fun_l1_n560(x) + if (x < 1) + fun_l2_n699(x) + else + fun_l2_n904(x) + end +end + +def fun_l1_n561(x) + if (x < 1) + fun_l2_n903(x) + else + fun_l2_n559(x) + end +end + +def fun_l1_n562(x) + if (x < 1) + fun_l2_n573(x) + else + fun_l2_n880(x) + end +end + +def fun_l1_n563(x) + if (x < 1) + fun_l2_n674(x) + else + fun_l2_n420(x) + end +end + +def fun_l1_n564(x) + if (x < 1) + fun_l2_n76(x) + else + fun_l2_n702(x) + end +end + +def fun_l1_n565(x) + if (x < 1) + fun_l2_n78(x) + else + fun_l2_n741(x) + end +end + +def fun_l1_n566(x) + if (x < 1) + fun_l2_n542(x) + else + fun_l2_n762(x) + end +end + +def fun_l1_n567(x) + if (x < 1) + fun_l2_n992(x) + else + fun_l2_n416(x) + end +end + +def fun_l1_n568(x) + if (x < 1) + fun_l2_n510(x) + else + fun_l2_n68(x) + end +end + +def fun_l1_n569(x) + if (x < 1) + fun_l2_n36(x) + else + fun_l2_n152(x) + end +end + +def fun_l1_n570(x) + if (x < 1) + fun_l2_n243(x) + else + fun_l2_n421(x) + end +end + +def fun_l1_n571(x) + if (x < 1) + fun_l2_n48(x) + else + fun_l2_n50(x) + end +end + +def fun_l1_n572(x) + if (x < 1) + fun_l2_n647(x) + else + fun_l2_n614(x) + end +end + +def fun_l1_n573(x) + if (x < 1) + fun_l2_n847(x) + else + fun_l2_n598(x) + end +end + +def fun_l1_n574(x) + if (x < 1) + fun_l2_n462(x) + else + fun_l2_n492(x) + end +end + +def fun_l1_n575(x) + if (x < 1) + fun_l2_n805(x) + else + fun_l2_n23(x) + end +end + +def fun_l1_n576(x) + if (x < 1) + fun_l2_n660(x) + else + fun_l2_n271(x) + end +end + +def fun_l1_n577(x) + if (x < 1) + fun_l2_n277(x) + else + fun_l2_n259(x) + end +end + +def fun_l1_n578(x) + if (x < 1) + fun_l2_n645(x) + else + fun_l2_n638(x) + end +end + +def fun_l1_n579(x) + if (x < 1) + fun_l2_n925(x) + else + fun_l2_n801(x) + end +end + +def fun_l1_n580(x) + if (x < 1) + fun_l2_n52(x) + else + fun_l2_n703(x) + end +end + +def fun_l1_n581(x) + if (x < 1) + fun_l2_n126(x) + else + fun_l2_n511(x) + end +end + +def fun_l1_n582(x) + if (x < 1) + fun_l2_n663(x) + else + fun_l2_n158(x) + end +end + +def fun_l1_n583(x) + if (x < 1) + fun_l2_n604(x) + else + fun_l2_n498(x) + end +end + +def fun_l1_n584(x) + if (x < 1) + fun_l2_n889(x) + else + fun_l2_n197(x) + end +end + +def fun_l1_n585(x) + if (x < 1) + fun_l2_n28(x) + else + fun_l2_n298(x) + end +end + +def fun_l1_n586(x) + if (x < 1) + fun_l2_n165(x) + else + fun_l2_n340(x) + end +end + +def fun_l1_n587(x) + if (x < 1) + fun_l2_n89(x) + else + fun_l2_n947(x) + end +end + +def fun_l1_n588(x) + if (x < 1) + fun_l2_n151(x) + else + fun_l2_n163(x) + end +end + +def fun_l1_n589(x) + if (x < 1) + fun_l2_n200(x) + else + fun_l2_n855(x) + end +end + +def fun_l1_n590(x) + if (x < 1) + fun_l2_n749(x) + else + fun_l2_n232(x) + end +end + +def fun_l1_n591(x) + if (x < 1) + fun_l2_n850(x) + else + fun_l2_n897(x) + end +end + +def fun_l1_n592(x) + if (x < 1) + fun_l2_n287(x) + else + fun_l2_n266(x) + end +end + +def fun_l1_n593(x) + if (x < 1) + fun_l2_n547(x) + else + fun_l2_n937(x) + end +end + +def fun_l1_n594(x) + if (x < 1) + fun_l2_n517(x) + else + fun_l2_n602(x) + end +end + +def fun_l1_n595(x) + if (x < 1) + fun_l2_n962(x) + else + fun_l2_n387(x) + end +end + +def fun_l1_n596(x) + if (x < 1) + fun_l2_n959(x) + else + fun_l2_n885(x) + end +end + +def fun_l1_n597(x) + if (x < 1) + fun_l2_n343(x) + else + fun_l2_n704(x) + end +end + +def fun_l1_n598(x) + if (x < 1) + fun_l2_n256(x) + else + fun_l2_n213(x) + end +end + +def fun_l1_n599(x) + if (x < 1) + fun_l2_n653(x) + else + fun_l2_n630(x) + end +end + +def fun_l1_n600(x) + if (x < 1) + fun_l2_n587(x) + else + fun_l2_n899(x) + end +end + +def fun_l1_n601(x) + if (x < 1) + fun_l2_n798(x) + else + fun_l2_n318(x) + end +end + +def fun_l1_n602(x) + if (x < 1) + fun_l2_n286(x) + else + fun_l2_n586(x) + end +end + +def fun_l1_n603(x) + if (x < 1) + fun_l2_n931(x) + else + fun_l2_n370(x) + end +end + +def fun_l1_n604(x) + if (x < 1) + fun_l2_n311(x) + else + fun_l2_n476(x) + end +end + +def fun_l1_n605(x) + if (x < 1) + fun_l2_n998(x) + else + fun_l2_n953(x) + end +end + +def fun_l1_n606(x) + if (x < 1) + fun_l2_n782(x) + else + fun_l2_n225(x) + end +end + +def fun_l1_n607(x) + if (x < 1) + fun_l2_n696(x) + else + fun_l2_n797(x) + end +end + +def fun_l1_n608(x) + if (x < 1) + fun_l2_n344(x) + else + fun_l2_n247(x) + end +end + +def fun_l1_n609(x) + if (x < 1) + fun_l2_n627(x) + else + fun_l2_n410(x) + end +end + +def fun_l1_n610(x) + if (x < 1) + fun_l2_n431(x) + else + fun_l2_n56(x) + end +end + +def fun_l1_n611(x) + if (x < 1) + fun_l2_n307(x) + else + fun_l2_n857(x) + end +end + +def fun_l1_n612(x) + if (x < 1) + fun_l2_n411(x) + else + fun_l2_n59(x) + end +end + +def fun_l1_n613(x) + if (x < 1) + fun_l2_n38(x) + else + fun_l2_n880(x) + end +end + +def fun_l1_n614(x) + if (x < 1) + fun_l2_n945(x) + else + fun_l2_n723(x) + end +end + +def fun_l1_n615(x) + if (x < 1) + fun_l2_n248(x) + else + fun_l2_n56(x) + end +end + +def fun_l1_n616(x) + if (x < 1) + fun_l2_n453(x) + else + fun_l2_n4(x) + end +end + +def fun_l1_n617(x) + if (x < 1) + fun_l2_n599(x) + else + fun_l2_n966(x) + end +end + +def fun_l1_n618(x) + if (x < 1) + fun_l2_n896(x) + else + fun_l2_n666(x) + end +end + +def fun_l1_n619(x) + if (x < 1) + fun_l2_n715(x) + else + fun_l2_n918(x) + end +end + +def fun_l1_n620(x) + if (x < 1) + fun_l2_n663(x) + else + fun_l2_n144(x) + end +end + +def fun_l1_n621(x) + if (x < 1) + fun_l2_n17(x) + else + fun_l2_n411(x) + end +end + +def fun_l1_n622(x) + if (x < 1) + fun_l2_n851(x) + else + fun_l2_n858(x) + end +end + +def fun_l1_n623(x) + if (x < 1) + fun_l2_n552(x) + else + fun_l2_n503(x) + end +end + +def fun_l1_n624(x) + if (x < 1) + fun_l2_n822(x) + else + fun_l2_n239(x) + end +end + +def fun_l1_n625(x) + if (x < 1) + fun_l2_n917(x) + else + fun_l2_n120(x) + end +end + +def fun_l1_n626(x) + if (x < 1) + fun_l2_n640(x) + else + fun_l2_n603(x) + end +end + +def fun_l1_n627(x) + if (x < 1) + fun_l2_n244(x) + else + fun_l2_n114(x) + end +end + +def fun_l1_n628(x) + if (x < 1) + fun_l2_n374(x) + else + fun_l2_n295(x) + end +end + +def fun_l1_n629(x) + if (x < 1) + fun_l2_n761(x) + else + fun_l2_n920(x) + end +end + +def fun_l1_n630(x) + if (x < 1) + fun_l2_n314(x) + else + fun_l2_n571(x) + end +end + +def fun_l1_n631(x) + if (x < 1) + fun_l2_n830(x) + else + fun_l2_n838(x) + end +end + +def fun_l1_n632(x) + if (x < 1) + fun_l2_n523(x) + else + fun_l2_n453(x) + end +end + +def fun_l1_n633(x) + if (x < 1) + fun_l2_n245(x) + else + fun_l2_n173(x) + end +end + +def fun_l1_n634(x) + if (x < 1) + fun_l2_n939(x) + else + fun_l2_n774(x) + end +end + +def fun_l1_n635(x) + if (x < 1) + fun_l2_n17(x) + else + fun_l2_n166(x) + end +end + +def fun_l1_n636(x) + if (x < 1) + fun_l2_n443(x) + else + fun_l2_n297(x) + end +end + +def fun_l1_n637(x) + if (x < 1) + fun_l2_n280(x) + else + fun_l2_n776(x) + end +end + +def fun_l1_n638(x) + if (x < 1) + fun_l2_n761(x) + else + fun_l2_n866(x) + end +end + +def fun_l1_n639(x) + if (x < 1) + fun_l2_n677(x) + else + fun_l2_n855(x) + end +end + +def fun_l1_n640(x) + if (x < 1) + fun_l2_n252(x) + else + fun_l2_n766(x) + end +end + +def fun_l1_n641(x) + if (x < 1) + fun_l2_n3(x) + else + fun_l2_n115(x) + end +end + +def fun_l1_n642(x) + if (x < 1) + fun_l2_n495(x) + else + fun_l2_n340(x) + end +end + +def fun_l1_n643(x) + if (x < 1) + fun_l2_n991(x) + else + fun_l2_n119(x) + end +end + +def fun_l1_n644(x) + if (x < 1) + fun_l2_n379(x) + else + fun_l2_n519(x) + end +end + +def fun_l1_n645(x) + if (x < 1) + fun_l2_n191(x) + else + fun_l2_n872(x) + end +end + +def fun_l1_n646(x) + if (x < 1) + fun_l2_n979(x) + else + fun_l2_n980(x) + end +end + +def fun_l1_n647(x) + if (x < 1) + fun_l2_n918(x) + else + fun_l2_n455(x) + end +end + +def fun_l1_n648(x) + if (x < 1) + fun_l2_n966(x) + else + fun_l2_n529(x) + end +end + +def fun_l1_n649(x) + if (x < 1) + fun_l2_n838(x) + else + fun_l2_n529(x) + end +end + +def fun_l1_n650(x) + if (x < 1) + fun_l2_n542(x) + else + fun_l2_n42(x) + end +end + +def fun_l1_n651(x) + if (x < 1) + fun_l2_n65(x) + else + fun_l2_n460(x) + end +end + +def fun_l1_n652(x) + if (x < 1) + fun_l2_n479(x) + else + fun_l2_n251(x) + end +end + +def fun_l1_n653(x) + if (x < 1) + fun_l2_n243(x) + else + fun_l2_n77(x) + end +end + +def fun_l1_n654(x) + if (x < 1) + fun_l2_n392(x) + else + fun_l2_n940(x) + end +end + +def fun_l1_n655(x) + if (x < 1) + fun_l2_n875(x) + else + fun_l2_n157(x) + end +end + +def fun_l1_n656(x) + if (x < 1) + fun_l2_n279(x) + else + fun_l2_n237(x) + end +end + +def fun_l1_n657(x) + if (x < 1) + fun_l2_n522(x) + else + fun_l2_n174(x) + end +end + +def fun_l1_n658(x) + if (x < 1) + fun_l2_n669(x) + else + fun_l2_n399(x) + end +end + +def fun_l1_n659(x) + if (x < 1) + fun_l2_n251(x) + else + fun_l2_n56(x) + end +end + +def fun_l1_n660(x) + if (x < 1) + fun_l2_n563(x) + else + fun_l2_n731(x) + end +end + +def fun_l1_n661(x) + if (x < 1) + fun_l2_n684(x) + else + fun_l2_n292(x) + end +end + +def fun_l1_n662(x) + if (x < 1) + fun_l2_n952(x) + else + fun_l2_n1(x) + end +end + +def fun_l1_n663(x) + if (x < 1) + fun_l2_n89(x) + else + fun_l2_n562(x) + end +end + +def fun_l1_n664(x) + if (x < 1) + fun_l2_n480(x) + else + fun_l2_n488(x) + end +end + +def fun_l1_n665(x) + if (x < 1) + fun_l2_n398(x) + else + fun_l2_n493(x) + end +end + +def fun_l1_n666(x) + if (x < 1) + fun_l2_n778(x) + else + fun_l2_n702(x) + end +end + +def fun_l1_n667(x) + if (x < 1) + fun_l2_n332(x) + else + fun_l2_n441(x) + end +end + +def fun_l1_n668(x) + if (x < 1) + fun_l2_n866(x) + else + fun_l2_n442(x) + end +end + +def fun_l1_n669(x) + if (x < 1) + fun_l2_n533(x) + else + fun_l2_n970(x) + end +end + +def fun_l1_n670(x) + if (x < 1) + fun_l2_n926(x) + else + fun_l2_n883(x) + end +end + +def fun_l1_n671(x) + if (x < 1) + fun_l2_n204(x) + else + fun_l2_n769(x) + end +end + +def fun_l1_n672(x) + if (x < 1) + fun_l2_n663(x) + else + fun_l2_n367(x) + end +end + +def fun_l1_n673(x) + if (x < 1) + fun_l2_n978(x) + else + fun_l2_n750(x) + end +end + +def fun_l1_n674(x) + if (x < 1) + fun_l2_n296(x) + else + fun_l2_n608(x) + end +end + +def fun_l1_n675(x) + if (x < 1) + fun_l2_n35(x) + else + fun_l2_n200(x) + end +end + +def fun_l1_n676(x) + if (x < 1) + fun_l2_n618(x) + else + fun_l2_n286(x) + end +end + +def fun_l1_n677(x) + if (x < 1) + fun_l2_n98(x) + else + fun_l2_n264(x) + end +end + +def fun_l1_n678(x) + if (x < 1) + fun_l2_n967(x) + else + fun_l2_n884(x) + end +end + +def fun_l1_n679(x) + if (x < 1) + fun_l2_n351(x) + else + fun_l2_n854(x) + end +end + +def fun_l1_n680(x) + if (x < 1) + fun_l2_n397(x) + else + fun_l2_n56(x) + end +end + +def fun_l1_n681(x) + if (x < 1) + fun_l2_n232(x) + else + fun_l2_n400(x) + end +end + +def fun_l1_n682(x) + if (x < 1) + fun_l2_n321(x) + else + fun_l2_n500(x) + end +end + +def fun_l1_n683(x) + if (x < 1) + fun_l2_n315(x) + else + fun_l2_n509(x) + end +end + +def fun_l1_n684(x) + if (x < 1) + fun_l2_n854(x) + else + fun_l2_n921(x) + end +end + +def fun_l1_n685(x) + if (x < 1) + fun_l2_n823(x) + else + fun_l2_n995(x) + end +end + +def fun_l1_n686(x) + if (x < 1) + fun_l2_n42(x) + else + fun_l2_n92(x) + end +end + +def fun_l1_n687(x) + if (x < 1) + fun_l2_n74(x) + else + fun_l2_n577(x) + end +end + +def fun_l1_n688(x) + if (x < 1) + fun_l2_n47(x) + else + fun_l2_n664(x) + end +end + +def fun_l1_n689(x) + if (x < 1) + fun_l2_n709(x) + else + fun_l2_n92(x) + end +end + +def fun_l1_n690(x) + if (x < 1) + fun_l2_n875(x) + else + fun_l2_n893(x) + end +end + +def fun_l1_n691(x) + if (x < 1) + fun_l2_n934(x) + else + fun_l2_n339(x) + end +end + +def fun_l1_n692(x) + if (x < 1) + fun_l2_n194(x) + else + fun_l2_n915(x) + end +end + +def fun_l1_n693(x) + if (x < 1) + fun_l2_n352(x) + else + fun_l2_n212(x) + end +end + +def fun_l1_n694(x) + if (x < 1) + fun_l2_n554(x) + else + fun_l2_n461(x) + end +end + +def fun_l1_n695(x) + if (x < 1) + fun_l2_n372(x) + else + fun_l2_n652(x) + end +end + +def fun_l1_n696(x) + if (x < 1) + fun_l2_n778(x) + else + fun_l2_n350(x) + end +end + +def fun_l1_n697(x) + if (x < 1) + fun_l2_n656(x) + else + fun_l2_n467(x) + end +end + +def fun_l1_n698(x) + if (x < 1) + fun_l2_n799(x) + else + fun_l2_n983(x) + end +end + +def fun_l1_n699(x) + if (x < 1) + fun_l2_n917(x) + else + fun_l2_n801(x) + end +end + +def fun_l1_n700(x) + if (x < 1) + fun_l2_n276(x) + else + fun_l2_n778(x) + end +end + +def fun_l1_n701(x) + if (x < 1) + fun_l2_n562(x) + else + fun_l2_n558(x) + end +end + +def fun_l1_n702(x) + if (x < 1) + fun_l2_n600(x) + else + fun_l2_n120(x) + end +end + +def fun_l1_n703(x) + if (x < 1) + fun_l2_n346(x) + else + fun_l2_n975(x) + end +end + +def fun_l1_n704(x) + if (x < 1) + fun_l2_n139(x) + else + fun_l2_n241(x) + end +end + +def fun_l1_n705(x) + if (x < 1) + fun_l2_n728(x) + else + fun_l2_n62(x) + end +end + +def fun_l1_n706(x) + if (x < 1) + fun_l2_n719(x) + else + fun_l2_n955(x) + end +end + +def fun_l1_n707(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n122(x) + end +end + +def fun_l1_n708(x) + if (x < 1) + fun_l2_n456(x) + else + fun_l2_n128(x) + end +end + +def fun_l1_n709(x) + if (x < 1) + fun_l2_n4(x) + else + fun_l2_n399(x) + end +end + +def fun_l1_n710(x) + if (x < 1) + fun_l2_n20(x) + else + fun_l2_n746(x) + end +end + +def fun_l1_n711(x) + if (x < 1) + fun_l2_n978(x) + else + fun_l2_n886(x) + end +end + +def fun_l1_n712(x) + if (x < 1) + fun_l2_n417(x) + else + fun_l2_n337(x) + end +end + +def fun_l1_n713(x) + if (x < 1) + fun_l2_n394(x) + else + fun_l2_n713(x) + end +end + +def fun_l1_n714(x) + if (x < 1) + fun_l2_n433(x) + else + fun_l2_n985(x) + end +end + +def fun_l1_n715(x) + if (x < 1) + fun_l2_n937(x) + else + fun_l2_n709(x) + end +end + +def fun_l1_n716(x) + if (x < 1) + fun_l2_n963(x) + else + fun_l2_n842(x) + end +end + +def fun_l1_n717(x) + if (x < 1) + fun_l2_n671(x) + else + fun_l2_n954(x) + end +end + +def fun_l1_n718(x) + if (x < 1) + fun_l2_n948(x) + else + fun_l2_n128(x) + end +end + +def fun_l1_n719(x) + if (x < 1) + fun_l2_n682(x) + else + fun_l2_n973(x) + end +end + +def fun_l1_n720(x) + if (x < 1) + fun_l2_n336(x) + else + fun_l2_n643(x) + end +end + +def fun_l1_n721(x) + if (x < 1) + fun_l2_n224(x) + else + fun_l2_n96(x) + end +end + +def fun_l1_n722(x) + if (x < 1) + fun_l2_n907(x) + else + fun_l2_n776(x) + end +end + +def fun_l1_n723(x) + if (x < 1) + fun_l2_n93(x) + else + fun_l2_n410(x) + end +end + +def fun_l1_n724(x) + if (x < 1) + fun_l2_n282(x) + else + fun_l2_n134(x) + end +end + +def fun_l1_n725(x) + if (x < 1) + fun_l2_n938(x) + else + fun_l2_n603(x) + end +end + +def fun_l1_n726(x) + if (x < 1) + fun_l2_n574(x) + else + fun_l2_n976(x) + end +end + +def fun_l1_n727(x) + if (x < 1) + fun_l2_n428(x) + else + fun_l2_n658(x) + end +end + +def fun_l1_n728(x) + if (x < 1) + fun_l2_n828(x) + else + fun_l2_n226(x) + end +end + +def fun_l1_n729(x) + if (x < 1) + fun_l2_n663(x) + else + fun_l2_n292(x) + end +end + +def fun_l1_n730(x) + if (x < 1) + fun_l2_n802(x) + else + fun_l2_n853(x) + end +end + +def fun_l1_n731(x) + if (x < 1) + fun_l2_n142(x) + else + fun_l2_n339(x) + end +end + +def fun_l1_n732(x) + if (x < 1) + fun_l2_n211(x) + else + fun_l2_n35(x) + end +end + +def fun_l1_n733(x) + if (x < 1) + fun_l2_n660(x) + else + fun_l2_n179(x) + end +end + +def fun_l1_n734(x) + if (x < 1) + fun_l2_n174(x) + else + fun_l2_n224(x) + end +end + +def fun_l1_n735(x) + if (x < 1) + fun_l2_n490(x) + else + fun_l2_n564(x) + end +end + +def fun_l1_n736(x) + if (x < 1) + fun_l2_n597(x) + else + fun_l2_n153(x) + end +end + +def fun_l1_n737(x) + if (x < 1) + fun_l2_n633(x) + else + fun_l2_n358(x) + end +end + +def fun_l1_n738(x) + if (x < 1) + fun_l2_n0(x) + else + fun_l2_n858(x) + end +end + +def fun_l1_n739(x) + if (x < 1) + fun_l2_n335(x) + else + fun_l2_n531(x) + end +end + +def fun_l1_n740(x) + if (x < 1) + fun_l2_n736(x) + else + fun_l2_n653(x) + end +end + +def fun_l1_n741(x) + if (x < 1) + fun_l2_n280(x) + else + fun_l2_n684(x) + end +end + +def fun_l1_n742(x) + if (x < 1) + fun_l2_n976(x) + else + fun_l2_n987(x) + end +end + +def fun_l1_n743(x) + if (x < 1) + fun_l2_n519(x) + else + fun_l2_n633(x) + end +end + +def fun_l1_n744(x) + if (x < 1) + fun_l2_n314(x) + else + fun_l2_n579(x) + end +end + +def fun_l1_n745(x) + if (x < 1) + fun_l2_n365(x) + else + fun_l2_n972(x) + end +end + +def fun_l1_n746(x) + if (x < 1) + fun_l2_n902(x) + else + fun_l2_n715(x) + end +end + +def fun_l1_n747(x) + if (x < 1) + fun_l2_n363(x) + else + fun_l2_n407(x) + end +end + +def fun_l1_n748(x) + if (x < 1) + fun_l2_n660(x) + else + fun_l2_n814(x) + end +end + +def fun_l1_n749(x) + if (x < 1) + fun_l2_n415(x) + else + fun_l2_n162(x) + end +end + +def fun_l1_n750(x) + if (x < 1) + fun_l2_n157(x) + else + fun_l2_n406(x) + end +end + +def fun_l1_n751(x) + if (x < 1) + fun_l2_n388(x) + else + fun_l2_n212(x) + end +end + +def fun_l1_n752(x) + if (x < 1) + fun_l2_n733(x) + else + fun_l2_n283(x) + end +end + +def fun_l1_n753(x) + if (x < 1) + fun_l2_n960(x) + else + fun_l2_n20(x) + end +end + +def fun_l1_n754(x) + if (x < 1) + fun_l2_n797(x) + else + fun_l2_n202(x) + end +end + +def fun_l1_n755(x) + if (x < 1) + fun_l2_n113(x) + else + fun_l2_n953(x) + end +end + +def fun_l1_n756(x) + if (x < 1) + fun_l2_n84(x) + else + fun_l2_n390(x) + end +end + +def fun_l1_n757(x) + if (x < 1) + fun_l2_n355(x) + else + fun_l2_n761(x) + end +end + +def fun_l1_n758(x) + if (x < 1) + fun_l2_n823(x) + else + fun_l2_n37(x) + end +end + +def fun_l1_n759(x) + if (x < 1) + fun_l2_n428(x) + else + fun_l2_n130(x) + end +end + +def fun_l1_n760(x) + if (x < 1) + fun_l2_n364(x) + else + fun_l2_n680(x) + end +end + +def fun_l1_n761(x) + if (x < 1) + fun_l2_n718(x) + else + fun_l2_n885(x) + end +end + +def fun_l1_n762(x) + if (x < 1) + fun_l2_n795(x) + else + fun_l2_n342(x) + end +end + +def fun_l1_n763(x) + if (x < 1) + fun_l2_n561(x) + else + fun_l2_n593(x) + end +end + +def fun_l1_n764(x) + if (x < 1) + fun_l2_n714(x) + else + fun_l2_n168(x) + end +end + +def fun_l1_n765(x) + if (x < 1) + fun_l2_n377(x) + else + fun_l2_n109(x) + end +end + +def fun_l1_n766(x) + if (x < 1) + fun_l2_n477(x) + else + fun_l2_n871(x) + end +end + +def fun_l1_n767(x) + if (x < 1) + fun_l2_n596(x) + else + fun_l2_n81(x) + end +end + +def fun_l1_n768(x) + if (x < 1) + fun_l2_n609(x) + else + fun_l2_n454(x) + end +end + +def fun_l1_n769(x) + if (x < 1) + fun_l2_n308(x) + else + fun_l2_n890(x) + end +end + +def fun_l1_n770(x) + if (x < 1) + fun_l2_n761(x) + else + fun_l2_n342(x) + end +end + +def fun_l1_n771(x) + if (x < 1) + fun_l2_n44(x) + else + fun_l2_n1(x) + end +end + +def fun_l1_n772(x) + if (x < 1) + fun_l2_n457(x) + else + fun_l2_n571(x) + end +end + +def fun_l1_n773(x) + if (x < 1) + fun_l2_n88(x) + else + fun_l2_n622(x) + end +end + +def fun_l1_n774(x) + if (x < 1) + fun_l2_n459(x) + else + fun_l2_n446(x) + end +end + +def fun_l1_n775(x) + if (x < 1) + fun_l2_n400(x) + else + fun_l2_n918(x) + end +end + +def fun_l1_n776(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n696(x) + end +end + +def fun_l1_n777(x) + if (x < 1) + fun_l2_n968(x) + else + fun_l2_n988(x) + end +end + +def fun_l1_n778(x) + if (x < 1) + fun_l2_n242(x) + else + fun_l2_n496(x) + end +end + +def fun_l1_n779(x) + if (x < 1) + fun_l2_n106(x) + else + fun_l2_n637(x) + end +end + +def fun_l1_n780(x) + if (x < 1) + fun_l2_n945(x) + else + fun_l2_n238(x) + end +end + +def fun_l1_n781(x) + if (x < 1) + fun_l2_n269(x) + else + fun_l2_n582(x) + end +end + +def fun_l1_n782(x) + if (x < 1) + fun_l2_n523(x) + else + fun_l2_n201(x) + end +end + +def fun_l1_n783(x) + if (x < 1) + fun_l2_n326(x) + else + fun_l2_n744(x) + end +end + +def fun_l1_n784(x) + if (x < 1) + fun_l2_n49(x) + else + fun_l2_n943(x) + end +end + +def fun_l1_n785(x) + if (x < 1) + fun_l2_n975(x) + else + fun_l2_n560(x) + end +end + +def fun_l1_n786(x) + if (x < 1) + fun_l2_n843(x) + else + fun_l2_n240(x) + end +end + +def fun_l1_n787(x) + if (x < 1) + fun_l2_n179(x) + else + fun_l2_n423(x) + end +end + +def fun_l1_n788(x) + if (x < 1) + fun_l2_n536(x) + else + fun_l2_n112(x) + end +end + +def fun_l1_n789(x) + if (x < 1) + fun_l2_n418(x) + else + fun_l2_n443(x) + end +end + +def fun_l1_n790(x) + if (x < 1) + fun_l2_n770(x) + else + fun_l2_n127(x) + end +end + +def fun_l1_n791(x) + if (x < 1) + fun_l2_n425(x) + else + fun_l2_n364(x) + end +end + +def fun_l1_n792(x) + if (x < 1) + fun_l2_n841(x) + else + fun_l2_n112(x) + end +end + +def fun_l1_n793(x) + if (x < 1) + fun_l2_n64(x) + else + fun_l2_n294(x) + end +end + +def fun_l1_n794(x) + if (x < 1) + fun_l2_n837(x) + else + fun_l2_n325(x) + end +end + +def fun_l1_n795(x) + if (x < 1) + fun_l2_n522(x) + else + fun_l2_n307(x) + end +end + +def fun_l1_n796(x) + if (x < 1) + fun_l2_n526(x) + else + fun_l2_n957(x) + end +end + +def fun_l1_n797(x) + if (x < 1) + fun_l2_n71(x) + else + fun_l2_n871(x) + end +end + +def fun_l1_n798(x) + if (x < 1) + fun_l2_n386(x) + else + fun_l2_n354(x) + end +end + +def fun_l1_n799(x) + if (x < 1) + fun_l2_n669(x) + else + fun_l2_n237(x) + end +end + +def fun_l1_n800(x) + if (x < 1) + fun_l2_n455(x) + else + fun_l2_n549(x) + end +end + +def fun_l1_n801(x) + if (x < 1) + fun_l2_n708(x) + else + fun_l2_n611(x) + end +end + +def fun_l1_n802(x) + if (x < 1) + fun_l2_n35(x) + else + fun_l2_n239(x) + end +end + +def fun_l1_n803(x) + if (x < 1) + fun_l2_n890(x) + else + fun_l2_n27(x) + end +end + +def fun_l1_n804(x) + if (x < 1) + fun_l2_n378(x) + else + fun_l2_n567(x) + end +end + +def fun_l1_n805(x) + if (x < 1) + fun_l2_n672(x) + else + fun_l2_n320(x) + end +end + +def fun_l1_n806(x) + if (x < 1) + fun_l2_n207(x) + else + fun_l2_n691(x) + end +end + +def fun_l1_n807(x) + if (x < 1) + fun_l2_n180(x) + else + fun_l2_n912(x) + end +end + +def fun_l1_n808(x) + if (x < 1) + fun_l2_n370(x) + else + fun_l2_n529(x) + end +end + +def fun_l1_n809(x) + if (x < 1) + fun_l2_n436(x) + else + fun_l2_n465(x) + end +end + +def fun_l1_n810(x) + if (x < 1) + fun_l2_n820(x) + else + fun_l2_n995(x) + end +end + +def fun_l1_n811(x) + if (x < 1) + fun_l2_n821(x) + else + fun_l2_n898(x) + end +end + +def fun_l1_n812(x) + if (x < 1) + fun_l2_n376(x) + else + fun_l2_n999(x) + end +end + +def fun_l1_n813(x) + if (x < 1) + fun_l2_n643(x) + else + fun_l2_n478(x) + end +end + +def fun_l1_n814(x) + if (x < 1) + fun_l2_n475(x) + else + fun_l2_n137(x) + end +end + +def fun_l1_n815(x) + if (x < 1) + fun_l2_n117(x) + else + fun_l2_n685(x) + end +end + +def fun_l1_n816(x) + if (x < 1) + fun_l2_n451(x) + else + fun_l2_n643(x) + end +end + +def fun_l1_n817(x) + if (x < 1) + fun_l2_n22(x) + else + fun_l2_n939(x) + end +end + +def fun_l1_n818(x) + if (x < 1) + fun_l2_n586(x) + else + fun_l2_n206(x) + end +end + +def fun_l1_n819(x) + if (x < 1) + fun_l2_n443(x) + else + fun_l2_n661(x) + end +end + +def fun_l1_n820(x) + if (x < 1) + fun_l2_n656(x) + else + fun_l2_n93(x) + end +end + +def fun_l1_n821(x) + if (x < 1) + fun_l2_n794(x) + else + fun_l2_n354(x) + end +end + +def fun_l1_n822(x) + if (x < 1) + fun_l2_n519(x) + else + fun_l2_n446(x) + end +end + +def fun_l1_n823(x) + if (x < 1) + fun_l2_n0(x) + else + fun_l2_n233(x) + end +end + +def fun_l1_n824(x) + if (x < 1) + fun_l2_n376(x) + else + fun_l2_n186(x) + end +end + +def fun_l1_n825(x) + if (x < 1) + fun_l2_n292(x) + else + fun_l2_n303(x) + end +end + +def fun_l1_n826(x) + if (x < 1) + fun_l2_n871(x) + else + fun_l2_n515(x) + end +end + +def fun_l1_n827(x) + if (x < 1) + fun_l2_n227(x) + else + fun_l2_n232(x) + end +end + +def fun_l1_n828(x) + if (x < 1) + fun_l2_n860(x) + else + fun_l2_n341(x) + end +end + +def fun_l1_n829(x) + if (x < 1) + fun_l2_n140(x) + else + fun_l2_n304(x) + end +end + +def fun_l1_n830(x) + if (x < 1) + fun_l2_n796(x) + else + fun_l2_n943(x) + end +end + +def fun_l1_n831(x) + if (x < 1) + fun_l2_n71(x) + else + fun_l2_n8(x) + end +end + +def fun_l1_n832(x) + if (x < 1) + fun_l2_n328(x) + else + fun_l2_n836(x) + end +end + +def fun_l1_n833(x) + if (x < 1) + fun_l2_n322(x) + else + fun_l2_n653(x) + end +end + +def fun_l1_n834(x) + if (x < 1) + fun_l2_n471(x) + else + fun_l2_n147(x) + end +end + +def fun_l1_n835(x) + if (x < 1) + fun_l2_n601(x) + else + fun_l2_n249(x) + end +end + +def fun_l1_n836(x) + if (x < 1) + fun_l2_n105(x) + else + fun_l2_n63(x) + end +end + +def fun_l1_n837(x) + if (x < 1) + fun_l2_n773(x) + else + fun_l2_n597(x) + end +end + +def fun_l1_n838(x) + if (x < 1) + fun_l2_n933(x) + else + fun_l2_n964(x) + end +end + +def fun_l1_n839(x) + if (x < 1) + fun_l2_n123(x) + else + fun_l2_n533(x) + end +end + +def fun_l1_n840(x) + if (x < 1) + fun_l2_n94(x) + else + fun_l2_n127(x) + end +end + +def fun_l1_n841(x) + if (x < 1) + fun_l2_n981(x) + else + fun_l2_n819(x) + end +end + +def fun_l1_n842(x) + if (x < 1) + fun_l2_n743(x) + else + fun_l2_n747(x) + end +end + +def fun_l1_n843(x) + if (x < 1) + fun_l2_n735(x) + else + fun_l2_n110(x) + end +end + +def fun_l1_n844(x) + if (x < 1) + fun_l2_n273(x) + else + fun_l2_n753(x) + end +end + +def fun_l1_n845(x) + if (x < 1) + fun_l2_n316(x) + else + fun_l2_n391(x) + end +end + +def fun_l1_n846(x) + if (x < 1) + fun_l2_n221(x) + else + fun_l2_n251(x) + end +end + +def fun_l1_n847(x) + if (x < 1) + fun_l2_n795(x) + else + fun_l2_n513(x) + end +end + +def fun_l1_n848(x) + if (x < 1) + fun_l2_n986(x) + else + fun_l2_n472(x) + end +end + +def fun_l1_n849(x) + if (x < 1) + fun_l2_n863(x) + else + fun_l2_n759(x) + end +end + +def fun_l1_n850(x) + if (x < 1) + fun_l2_n512(x) + else + fun_l2_n502(x) + end +end + +def fun_l1_n851(x) + if (x < 1) + fun_l2_n561(x) + else + fun_l2_n697(x) + end +end + +def fun_l1_n852(x) + if (x < 1) + fun_l2_n816(x) + else + fun_l2_n90(x) + end +end + +def fun_l1_n853(x) + if (x < 1) + fun_l2_n656(x) + else + fun_l2_n174(x) + end +end + +def fun_l1_n854(x) + if (x < 1) + fun_l2_n439(x) + else + fun_l2_n90(x) + end +end + +def fun_l1_n855(x) + if (x < 1) + fun_l2_n15(x) + else + fun_l2_n402(x) + end +end + +def fun_l1_n856(x) + if (x < 1) + fun_l2_n224(x) + else + fun_l2_n177(x) + end +end + +def fun_l1_n857(x) + if (x < 1) + fun_l2_n675(x) + else + fun_l2_n113(x) + end +end + +def fun_l1_n858(x) + if (x < 1) + fun_l2_n388(x) + else + fun_l2_n529(x) + end +end + +def fun_l1_n859(x) + if (x < 1) + fun_l2_n628(x) + else + fun_l2_n93(x) + end +end + +def fun_l1_n860(x) + if (x < 1) + fun_l2_n67(x) + else + fun_l2_n90(x) + end +end + +def fun_l1_n861(x) + if (x < 1) + fun_l2_n637(x) + else + fun_l2_n68(x) + end +end + +def fun_l1_n862(x) + if (x < 1) + fun_l2_n767(x) + else + fun_l2_n86(x) + end +end + +def fun_l1_n863(x) + if (x < 1) + fun_l2_n50(x) + else + fun_l2_n777(x) + end +end + +def fun_l1_n864(x) + if (x < 1) + fun_l2_n846(x) + else + fun_l2_n783(x) + end +end + +def fun_l1_n865(x) + if (x < 1) + fun_l2_n756(x) + else + fun_l2_n703(x) + end +end + +def fun_l1_n866(x) + if (x < 1) + fun_l2_n972(x) + else + fun_l2_n249(x) + end +end + +def fun_l1_n867(x) + if (x < 1) + fun_l2_n636(x) + else + fun_l2_n841(x) + end +end + +def fun_l1_n868(x) + if (x < 1) + fun_l2_n889(x) + else + fun_l2_n899(x) + end +end + +def fun_l1_n869(x) + if (x < 1) + fun_l2_n55(x) + else + fun_l2_n45(x) + end +end + +def fun_l1_n870(x) + if (x < 1) + fun_l2_n740(x) + else + fun_l2_n722(x) + end +end + +def fun_l1_n871(x) + if (x < 1) + fun_l2_n865(x) + else + fun_l2_n695(x) + end +end + +def fun_l1_n872(x) + if (x < 1) + fun_l2_n54(x) + else + fun_l2_n581(x) + end +end + +def fun_l1_n873(x) + if (x < 1) + fun_l2_n328(x) + else + fun_l2_n861(x) + end +end + +def fun_l1_n874(x) + if (x < 1) + fun_l2_n645(x) + else + fun_l2_n121(x) + end +end + +def fun_l1_n875(x) + if (x < 1) + fun_l2_n71(x) + else + fun_l2_n329(x) + end +end + +def fun_l1_n876(x) + if (x < 1) + fun_l2_n944(x) + else + fun_l2_n95(x) + end +end + +def fun_l1_n877(x) + if (x < 1) + fun_l2_n270(x) + else + fun_l2_n801(x) + end +end + +def fun_l1_n878(x) + if (x < 1) + fun_l2_n115(x) + else + fun_l2_n414(x) + end +end + +def fun_l1_n879(x) + if (x < 1) + fun_l2_n154(x) + else + fun_l2_n605(x) + end +end + +def fun_l1_n880(x) + if (x < 1) + fun_l2_n859(x) + else + fun_l2_n307(x) + end +end + +def fun_l1_n881(x) + if (x < 1) + fun_l2_n443(x) + else + fun_l2_n267(x) + end +end + +def fun_l1_n882(x) + if (x < 1) + fun_l2_n280(x) + else + fun_l2_n175(x) + end +end + +def fun_l1_n883(x) + if (x < 1) + fun_l2_n176(x) + else + fun_l2_n286(x) + end +end + +def fun_l1_n884(x) + if (x < 1) + fun_l2_n422(x) + else + fun_l2_n469(x) + end +end + +def fun_l1_n885(x) + if (x < 1) + fun_l2_n532(x) + else + fun_l2_n795(x) + end +end + +def fun_l1_n886(x) + if (x < 1) + fun_l2_n966(x) + else + fun_l2_n46(x) + end +end + +def fun_l1_n887(x) + if (x < 1) + fun_l2_n446(x) + else + fun_l2_n944(x) + end +end + +def fun_l1_n888(x) + if (x < 1) + fun_l2_n256(x) + else + fun_l2_n757(x) + end +end + +def fun_l1_n889(x) + if (x < 1) + fun_l2_n566(x) + else + fun_l2_n992(x) + end +end + +def fun_l1_n890(x) + if (x < 1) + fun_l2_n55(x) + else + fun_l2_n121(x) + end +end + +def fun_l1_n891(x) + if (x < 1) + fun_l2_n597(x) + else + fun_l2_n257(x) + end +end + +def fun_l1_n892(x) + if (x < 1) + fun_l2_n79(x) + else + fun_l2_n249(x) + end +end + +def fun_l1_n893(x) + if (x < 1) + fun_l2_n436(x) + else + fun_l2_n738(x) + end +end + +def fun_l1_n894(x) + if (x < 1) + fun_l2_n244(x) + else + fun_l2_n184(x) + end +end + +def fun_l1_n895(x) + if (x < 1) + fun_l2_n342(x) + else + fun_l2_n794(x) + end +end + +def fun_l1_n896(x) + if (x < 1) + fun_l2_n588(x) + else + fun_l2_n235(x) + end +end + +def fun_l1_n897(x) + if (x < 1) + fun_l2_n443(x) + else + fun_l2_n462(x) + end +end + +def fun_l1_n898(x) + if (x < 1) + fun_l2_n986(x) + else + fun_l2_n282(x) + end +end + +def fun_l1_n899(x) + if (x < 1) + fun_l2_n61(x) + else + fun_l2_n516(x) + end +end + +def fun_l1_n900(x) + if (x < 1) + fun_l2_n993(x) + else + fun_l2_n337(x) + end +end + +def fun_l1_n901(x) + if (x < 1) + fun_l2_n398(x) + else + fun_l2_n425(x) + end +end + +def fun_l1_n902(x) + if (x < 1) + fun_l2_n177(x) + else + fun_l2_n741(x) + end +end + +def fun_l1_n903(x) + if (x < 1) + fun_l2_n597(x) + else + fun_l2_n331(x) + end +end + +def fun_l1_n904(x) + if (x < 1) + fun_l2_n740(x) + else + fun_l2_n527(x) + end +end + +def fun_l1_n905(x) + if (x < 1) + fun_l2_n138(x) + else + fun_l2_n248(x) + end +end + +def fun_l1_n906(x) + if (x < 1) + fun_l2_n318(x) + else + fun_l2_n941(x) + end +end + +def fun_l1_n907(x) + if (x < 1) + fun_l2_n493(x) + else + fun_l2_n376(x) + end +end + +def fun_l1_n908(x) + if (x < 1) + fun_l2_n899(x) + else + fun_l2_n745(x) + end +end + +def fun_l1_n909(x) + if (x < 1) + fun_l2_n963(x) + else + fun_l2_n384(x) + end +end + +def fun_l1_n910(x) + if (x < 1) + fun_l2_n490(x) + else + fun_l2_n702(x) + end +end + +def fun_l1_n911(x) + if (x < 1) + fun_l2_n712(x) + else + fun_l2_n810(x) + end +end + +def fun_l1_n912(x) + if (x < 1) + fun_l2_n245(x) + else + fun_l2_n609(x) + end +end + +def fun_l1_n913(x) + if (x < 1) + fun_l2_n997(x) + else + fun_l2_n241(x) + end +end + +def fun_l1_n914(x) + if (x < 1) + fun_l2_n428(x) + else + fun_l2_n697(x) + end +end + +def fun_l1_n915(x) + if (x < 1) + fun_l2_n257(x) + else + fun_l2_n626(x) + end +end + +def fun_l1_n916(x) + if (x < 1) + fun_l2_n378(x) + else + fun_l2_n457(x) + end +end + +def fun_l1_n917(x) + if (x < 1) + fun_l2_n378(x) + else + fun_l2_n958(x) + end +end + +def fun_l1_n918(x) + if (x < 1) + fun_l2_n213(x) + else + fun_l2_n962(x) + end +end + +def fun_l1_n919(x) + if (x < 1) + fun_l2_n466(x) + else + fun_l2_n461(x) + end +end + +def fun_l1_n920(x) + if (x < 1) + fun_l2_n835(x) + else + fun_l2_n460(x) + end +end + +def fun_l1_n921(x) + if (x < 1) + fun_l2_n642(x) + else + fun_l2_n680(x) + end +end + +def fun_l1_n922(x) + if (x < 1) + fun_l2_n467(x) + else + fun_l2_n225(x) + end +end + +def fun_l1_n923(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n462(x) + end +end + +def fun_l1_n924(x) + if (x < 1) + fun_l2_n113(x) + else + fun_l2_n59(x) + end +end + +def fun_l1_n925(x) + if (x < 1) + fun_l2_n329(x) + else + fun_l2_n994(x) + end +end + +def fun_l1_n926(x) + if (x < 1) + fun_l2_n815(x) + else + fun_l2_n249(x) + end +end + +def fun_l1_n927(x) + if (x < 1) + fun_l2_n216(x) + else + fun_l2_n591(x) + end +end + +def fun_l1_n928(x) + if (x < 1) + fun_l2_n441(x) + else + fun_l2_n437(x) + end +end + +def fun_l1_n929(x) + if (x < 1) + fun_l2_n433(x) + else + fun_l2_n185(x) + end +end + +def fun_l1_n930(x) + if (x < 1) + fun_l2_n125(x) + else + fun_l2_n940(x) + end +end + +def fun_l1_n931(x) + if (x < 1) + fun_l2_n203(x) + else + fun_l2_n292(x) + end +end + +def fun_l1_n932(x) + if (x < 1) + fun_l2_n986(x) + else + fun_l2_n234(x) + end +end + +def fun_l1_n933(x) + if (x < 1) + fun_l2_n735(x) + else + fun_l2_n20(x) + end +end + +def fun_l1_n934(x) + if (x < 1) + fun_l2_n878(x) + else + fun_l2_n166(x) + end +end + +def fun_l1_n935(x) + if (x < 1) + fun_l2_n123(x) + else + fun_l2_n52(x) + end +end + +def fun_l1_n936(x) + if (x < 1) + fun_l2_n99(x) + else + fun_l2_n336(x) + end +end + +def fun_l1_n937(x) + if (x < 1) + fun_l2_n731(x) + else + fun_l2_n363(x) + end +end + +def fun_l1_n938(x) + if (x < 1) + fun_l2_n988(x) + else + fun_l2_n978(x) + end +end + +def fun_l1_n939(x) + if (x < 1) + fun_l2_n592(x) + else + fun_l2_n932(x) + end +end + +def fun_l1_n940(x) + if (x < 1) + fun_l2_n681(x) + else + fun_l2_n868(x) + end +end + +def fun_l1_n941(x) + if (x < 1) + fun_l2_n863(x) + else + fun_l2_n457(x) + end +end + +def fun_l1_n942(x) + if (x < 1) + fun_l2_n526(x) + else + fun_l2_n960(x) + end +end + +def fun_l1_n943(x) + if (x < 1) + fun_l2_n859(x) + else + fun_l2_n478(x) + end +end + +def fun_l1_n944(x) + if (x < 1) + fun_l2_n947(x) + else + fun_l2_n889(x) + end +end + +def fun_l1_n945(x) + if (x < 1) + fun_l2_n845(x) + else + fun_l2_n211(x) + end +end + +def fun_l1_n946(x) + if (x < 1) + fun_l2_n445(x) + else + fun_l2_n600(x) + end +end + +def fun_l1_n947(x) + if (x < 1) + fun_l2_n932(x) + else + fun_l2_n534(x) + end +end + +def fun_l1_n948(x) + if (x < 1) + fun_l2_n224(x) + else + fun_l2_n32(x) + end +end + +def fun_l1_n949(x) + if (x < 1) + fun_l2_n63(x) + else + fun_l2_n121(x) + end +end + +def fun_l1_n950(x) + if (x < 1) + fun_l2_n55(x) + else + fun_l2_n90(x) + end +end + +def fun_l1_n951(x) + if (x < 1) + fun_l2_n880(x) + else + fun_l2_n936(x) + end +end + +def fun_l1_n952(x) + if (x < 1) + fun_l2_n971(x) + else + fun_l2_n40(x) + end +end + +def fun_l1_n953(x) + if (x < 1) + fun_l2_n880(x) + else + fun_l2_n200(x) + end +end + +def fun_l1_n954(x) + if (x < 1) + fun_l2_n60(x) + else + fun_l2_n473(x) + end +end + +def fun_l1_n955(x) + if (x < 1) + fun_l2_n855(x) + else + fun_l2_n601(x) + end +end + +def fun_l1_n956(x) + if (x < 1) + fun_l2_n282(x) + else + fun_l2_n542(x) + end +end + +def fun_l1_n957(x) + if (x < 1) + fun_l2_n116(x) + else + fun_l2_n584(x) + end +end + +def fun_l1_n958(x) + if (x < 1) + fun_l2_n845(x) + else + fun_l2_n814(x) + end +end + +def fun_l1_n959(x) + if (x < 1) + fun_l2_n443(x) + else + fun_l2_n239(x) + end +end + +def fun_l1_n960(x) + if (x < 1) + fun_l2_n79(x) + else + fun_l2_n556(x) + end +end + +def fun_l1_n961(x) + if (x < 1) + fun_l2_n664(x) + else + fun_l2_n282(x) + end +end + +def fun_l1_n962(x) + if (x < 1) + fun_l2_n273(x) + else + fun_l2_n393(x) + end +end + +def fun_l1_n963(x) + if (x < 1) + fun_l2_n120(x) + else + fun_l2_n506(x) + end +end + +def fun_l1_n964(x) + if (x < 1) + fun_l2_n362(x) + else + fun_l2_n631(x) + end +end + +def fun_l1_n965(x) + if (x < 1) + fun_l2_n219(x) + else + fun_l2_n260(x) + end +end + +def fun_l1_n966(x) + if (x < 1) + fun_l2_n802(x) + else + fun_l2_n732(x) + end +end + +def fun_l1_n967(x) + if (x < 1) + fun_l2_n761(x) + else + fun_l2_n580(x) + end +end + +def fun_l1_n968(x) + if (x < 1) + fun_l2_n529(x) + else + fun_l2_n783(x) + end +end + +def fun_l1_n969(x) + if (x < 1) + fun_l2_n138(x) + else + fun_l2_n434(x) + end +end + +def fun_l1_n970(x) + if (x < 1) + fun_l2_n266(x) + else + fun_l2_n522(x) + end +end + +def fun_l1_n971(x) + if (x < 1) + fun_l2_n352(x) + else + fun_l2_n51(x) + end +end + +def fun_l1_n972(x) + if (x < 1) + fun_l2_n619(x) + else + fun_l2_n68(x) + end +end + +def fun_l1_n973(x) + if (x < 1) + fun_l2_n510(x) + else + fun_l2_n74(x) + end +end + +def fun_l1_n974(x) + if (x < 1) + fun_l2_n442(x) + else + fun_l2_n258(x) + end +end + +def fun_l1_n975(x) + if (x < 1) + fun_l2_n106(x) + else + fun_l2_n364(x) + end +end + +def fun_l1_n976(x) + if (x < 1) + fun_l2_n412(x) + else + fun_l2_n669(x) + end +end + +def fun_l1_n977(x) + if (x < 1) + fun_l2_n394(x) + else + fun_l2_n435(x) + end +end + +def fun_l1_n978(x) + if (x < 1) + fun_l2_n630(x) + else + fun_l2_n686(x) + end +end + +def fun_l1_n979(x) + if (x < 1) + fun_l2_n683(x) + else + fun_l2_n99(x) + end +end + +def fun_l1_n980(x) + if (x < 1) + fun_l2_n352(x) + else + fun_l2_n394(x) + end +end + +def fun_l1_n981(x) + if (x < 1) + fun_l2_n856(x) + else + fun_l2_n11(x) + end +end + +def fun_l1_n982(x) + if (x < 1) + fun_l2_n484(x) + else + fun_l2_n230(x) + end +end + +def fun_l1_n983(x) + if (x < 1) + fun_l2_n609(x) + else + fun_l2_n882(x) + end +end + +def fun_l1_n984(x) + if (x < 1) + fun_l2_n529(x) + else + fun_l2_n589(x) + end +end + +def fun_l1_n985(x) + if (x < 1) + fun_l2_n545(x) + else + fun_l2_n139(x) + end +end + +def fun_l1_n986(x) + if (x < 1) + fun_l2_n679(x) + else + fun_l2_n938(x) + end +end + +def fun_l1_n987(x) + if (x < 1) + fun_l2_n803(x) + else + fun_l2_n454(x) + end +end + +def fun_l1_n988(x) + if (x < 1) + fun_l2_n403(x) + else + fun_l2_n976(x) + end +end + +def fun_l1_n989(x) + if (x < 1) + fun_l2_n364(x) + else + fun_l2_n96(x) + end +end + +def fun_l1_n990(x) + if (x < 1) + fun_l2_n48(x) + else + fun_l2_n442(x) + end +end + +def fun_l1_n991(x) + if (x < 1) + fun_l2_n842(x) + else + fun_l2_n810(x) + end +end + +def fun_l1_n992(x) + if (x < 1) + fun_l2_n237(x) + else + fun_l2_n145(x) + end +end + +def fun_l1_n993(x) + if (x < 1) + fun_l2_n279(x) + else + fun_l2_n783(x) + end +end + +def fun_l1_n994(x) + if (x < 1) + fun_l2_n323(x) + else + fun_l2_n829(x) + end +end + +def fun_l1_n995(x) + if (x < 1) + fun_l2_n904(x) + else + fun_l2_n738(x) + end +end + +def fun_l1_n996(x) + if (x < 1) + fun_l2_n390(x) + else + fun_l2_n169(x) + end +end + +def fun_l1_n997(x) + if (x < 1) + fun_l2_n583(x) + else + fun_l2_n993(x) + end +end + +def fun_l1_n998(x) + if (x < 1) + fun_l2_n752(x) + else + fun_l2_n240(x) + end +end + +def fun_l1_n999(x) + if (x < 1) + fun_l2_n489(x) + else + fun_l2_n175(x) + end +end + +def fun_l2_n0(x) + if (x < 1) + fun_l3_n293(x) + else + fun_l3_n569(x) + end +end + +def fun_l2_n1(x) + if (x < 1) + fun_l3_n310(x) + else + fun_l3_n785(x) + end +end + +def fun_l2_n2(x) + if (x < 1) + fun_l3_n484(x) + else + fun_l3_n800(x) + end +end + +def fun_l2_n3(x) + if (x < 1) + fun_l3_n353(x) + else + fun_l3_n871(x) + end +end + +def fun_l2_n4(x) + if (x < 1) + fun_l3_n100(x) + else + fun_l3_n796(x) + end +end + +def fun_l2_n5(x) + if (x < 1) + fun_l3_n547(x) + else + fun_l3_n663(x) + end +end + +def fun_l2_n6(x) + if (x < 1) + fun_l3_n756(x) + else + fun_l3_n69(x) + end +end + +def fun_l2_n7(x) + if (x < 1) + fun_l3_n393(x) + else + fun_l3_n333(x) + end +end + +def fun_l2_n8(x) + if (x < 1) + fun_l3_n167(x) + else + fun_l3_n47(x) + end +end + +def fun_l2_n9(x) + if (x < 1) + fun_l3_n969(x) + else + fun_l3_n772(x) + end +end + +def fun_l2_n10(x) + if (x < 1) + fun_l3_n667(x) + else + fun_l3_n62(x) + end +end + +def fun_l2_n11(x) + if (x < 1) + fun_l3_n671(x) + else + fun_l3_n303(x) + end +end + +def fun_l2_n12(x) + if (x < 1) + fun_l3_n116(x) + else + fun_l3_n537(x) + end +end + +def fun_l2_n13(x) + if (x < 1) + fun_l3_n363(x) + else + fun_l3_n426(x) + end +end + +def fun_l2_n14(x) + if (x < 1) + fun_l3_n23(x) + else + fun_l3_n800(x) + end +end + +def fun_l2_n15(x) + if (x < 1) + fun_l3_n344(x) + else + fun_l3_n590(x) + end +end + +def fun_l2_n16(x) + if (x < 1) + fun_l3_n759(x) + else + fun_l3_n531(x) + end +end + +def fun_l2_n17(x) + if (x < 1) + fun_l3_n902(x) + else + fun_l3_n948(x) + end +end + +def fun_l2_n18(x) + if (x < 1) + fun_l3_n407(x) + else + fun_l3_n743(x) + end +end + +def fun_l2_n19(x) + if (x < 1) + fun_l3_n360(x) + else + fun_l3_n953(x) + end +end + +def fun_l2_n20(x) + if (x < 1) + fun_l3_n968(x) + else + fun_l3_n685(x) + end +end + +def fun_l2_n21(x) + if (x < 1) + fun_l3_n964(x) + else + fun_l3_n210(x) + end +end + +def fun_l2_n22(x) + if (x < 1) + fun_l3_n346(x) + else + fun_l3_n902(x) + end +end + +def fun_l2_n23(x) + if (x < 1) + fun_l3_n154(x) + else + fun_l3_n52(x) + end +end + +def fun_l2_n24(x) + if (x < 1) + fun_l3_n229(x) + else + fun_l3_n137(x) + end +end + +def fun_l2_n25(x) + if (x < 1) + fun_l3_n390(x) + else + fun_l3_n445(x) + end +end + +def fun_l2_n26(x) + if (x < 1) + fun_l3_n11(x) + else + fun_l3_n113(x) + end +end + +def fun_l2_n27(x) + if (x < 1) + fun_l3_n756(x) + else + fun_l3_n935(x) + end +end + +def fun_l2_n28(x) + if (x < 1) + fun_l3_n567(x) + else + fun_l3_n984(x) + end +end + +def fun_l2_n29(x) + if (x < 1) + fun_l3_n982(x) + else + fun_l3_n335(x) + end +end + +def fun_l2_n30(x) + if (x < 1) + fun_l3_n78(x) + else + fun_l3_n571(x) + end +end + +def fun_l2_n31(x) + if (x < 1) + fun_l3_n93(x) + else + fun_l3_n455(x) + end +end + +def fun_l2_n32(x) + if (x < 1) + fun_l3_n118(x) + else + fun_l3_n713(x) + end +end + +def fun_l2_n33(x) + if (x < 1) + fun_l3_n561(x) + else + fun_l3_n0(x) + end +end + +def fun_l2_n34(x) + if (x < 1) + fun_l3_n153(x) + else + fun_l3_n77(x) + end +end + +def fun_l2_n35(x) + if (x < 1) + fun_l3_n815(x) + else + fun_l3_n642(x) + end +end + +def fun_l2_n36(x) + if (x < 1) + fun_l3_n503(x) + else + fun_l3_n428(x) + end +end + +def fun_l2_n37(x) + if (x < 1) + fun_l3_n780(x) + else + fun_l3_n301(x) + end +end + +def fun_l2_n38(x) + if (x < 1) + fun_l3_n827(x) + else + fun_l3_n444(x) + end +end + +def fun_l2_n39(x) + if (x < 1) + fun_l3_n808(x) + else + fun_l3_n76(x) + end +end + +def fun_l2_n40(x) + if (x < 1) + fun_l3_n216(x) + else + fun_l3_n943(x) + end +end + +def fun_l2_n41(x) + if (x < 1) + fun_l3_n237(x) + else + fun_l3_n935(x) + end +end + +def fun_l2_n42(x) + if (x < 1) + fun_l3_n769(x) + else + fun_l3_n564(x) + end +end + +def fun_l2_n43(x) + if (x < 1) + fun_l3_n108(x) + else + fun_l3_n180(x) + end +end + +def fun_l2_n44(x) + if (x < 1) + fun_l3_n750(x) + else + fun_l3_n614(x) + end +end + +def fun_l2_n45(x) + if (x < 1) + fun_l3_n497(x) + else + fun_l3_n584(x) + end +end + +def fun_l2_n46(x) + if (x < 1) + fun_l3_n364(x) + else + fun_l3_n218(x) + end +end + +def fun_l2_n47(x) + if (x < 1) + fun_l3_n938(x) + else + fun_l3_n707(x) + end +end + +def fun_l2_n48(x) + if (x < 1) + fun_l3_n14(x) + else + fun_l3_n178(x) + end +end + +def fun_l2_n49(x) + if (x < 1) + fun_l3_n923(x) + else + fun_l3_n493(x) + end +end + +def fun_l2_n50(x) + if (x < 1) + fun_l3_n481(x) + else + fun_l3_n193(x) + end +end + +def fun_l2_n51(x) + if (x < 1) + fun_l3_n876(x) + else + fun_l3_n59(x) + end +end + +def fun_l2_n52(x) + if (x < 1) + fun_l3_n930(x) + else + fun_l3_n813(x) + end +end + +def fun_l2_n53(x) + if (x < 1) + fun_l3_n369(x) + else + fun_l3_n972(x) + end +end + +def fun_l2_n54(x) + if (x < 1) + fun_l3_n95(x) + else + fun_l3_n573(x) + end +end + +def fun_l2_n55(x) + if (x < 1) + fun_l3_n148(x) + else + fun_l3_n369(x) + end +end + +def fun_l2_n56(x) + if (x < 1) + fun_l3_n476(x) + else + fun_l3_n54(x) + end +end + +def fun_l2_n57(x) + if (x < 1) + fun_l3_n672(x) + else + fun_l3_n592(x) + end +end + +def fun_l2_n58(x) + if (x < 1) + fun_l3_n648(x) + else + fun_l3_n169(x) + end +end + +def fun_l2_n59(x) + if (x < 1) + fun_l3_n844(x) + else + fun_l3_n422(x) + end +end + +def fun_l2_n60(x) + if (x < 1) + fun_l3_n6(x) + else + fun_l3_n763(x) + end +end + +def fun_l2_n61(x) + if (x < 1) + fun_l3_n35(x) + else + fun_l3_n316(x) + end +end + +def fun_l2_n62(x) + if (x < 1) + fun_l3_n487(x) + else + fun_l3_n469(x) + end +end + +def fun_l2_n63(x) + if (x < 1) + fun_l3_n272(x) + else + fun_l3_n909(x) + end +end + +def fun_l2_n64(x) + if (x < 1) + fun_l3_n266(x) + else + fun_l3_n347(x) + end +end + +def fun_l2_n65(x) + if (x < 1) + fun_l3_n696(x) + else + fun_l3_n499(x) + end +end + +def fun_l2_n66(x) + if (x < 1) + fun_l3_n523(x) + else + fun_l3_n834(x) + end +end + +def fun_l2_n67(x) + if (x < 1) + fun_l3_n966(x) + else + fun_l3_n454(x) + end +end + +def fun_l2_n68(x) + if (x < 1) + fun_l3_n406(x) + else + fun_l3_n644(x) + end +end + +def fun_l2_n69(x) + if (x < 1) + fun_l3_n616(x) + else + fun_l3_n90(x) + end +end + +def fun_l2_n70(x) + if (x < 1) + fun_l3_n158(x) + else + fun_l3_n910(x) + end +end + +def fun_l2_n71(x) + if (x < 1) + fun_l3_n391(x) + else + fun_l3_n761(x) + end +end + +def fun_l2_n72(x) + if (x < 1) + fun_l3_n585(x) + else + fun_l3_n405(x) + end +end + +def fun_l2_n73(x) + if (x < 1) + fun_l3_n227(x) + else + fun_l3_n583(x) + end +end + +def fun_l2_n74(x) + if (x < 1) + fun_l3_n580(x) + else + fun_l3_n110(x) + end +end + +def fun_l2_n75(x) + if (x < 1) + fun_l3_n393(x) + else + fun_l3_n643(x) + end +end + +def fun_l2_n76(x) + if (x < 1) + fun_l3_n935(x) + else + fun_l3_n593(x) + end +end + +def fun_l2_n77(x) + if (x < 1) + fun_l3_n239(x) + else + fun_l3_n704(x) + end +end + +def fun_l2_n78(x) + if (x < 1) + fun_l3_n192(x) + else + fun_l3_n722(x) + end +end + +def fun_l2_n79(x) + if (x < 1) + fun_l3_n119(x) + else + fun_l3_n426(x) + end +end + +def fun_l2_n80(x) + if (x < 1) + fun_l3_n692(x) + else + fun_l3_n895(x) + end +end + +def fun_l2_n81(x) + if (x < 1) + fun_l3_n246(x) + else + fun_l3_n340(x) + end +end + +def fun_l2_n82(x) + if (x < 1) + fun_l3_n368(x) + else + fun_l3_n255(x) + end +end + +def fun_l2_n83(x) + if (x < 1) + fun_l3_n942(x) + else + fun_l3_n595(x) + end +end + +def fun_l2_n84(x) + if (x < 1) + fun_l3_n629(x) + else + fun_l3_n622(x) + end +end + +def fun_l2_n85(x) + if (x < 1) + fun_l3_n415(x) + else + fun_l3_n615(x) + end +end + +def fun_l2_n86(x) + if (x < 1) + fun_l3_n295(x) + else + fun_l3_n809(x) + end +end + +def fun_l2_n87(x) + if (x < 1) + fun_l3_n957(x) + else + fun_l3_n452(x) + end +end + +def fun_l2_n88(x) + if (x < 1) + fun_l3_n490(x) + else + fun_l3_n184(x) + end +end + +def fun_l2_n89(x) + if (x < 1) + fun_l3_n483(x) + else + fun_l3_n963(x) + end +end + +def fun_l2_n90(x) + if (x < 1) + fun_l3_n262(x) + else + fun_l3_n458(x) + end +end + +def fun_l2_n91(x) + if (x < 1) + fun_l3_n277(x) + else + fun_l3_n30(x) + end +end + +def fun_l2_n92(x) + if (x < 1) + fun_l3_n310(x) + else + fun_l3_n215(x) + end +end + +def fun_l2_n93(x) + if (x < 1) + fun_l3_n660(x) + else + fun_l3_n798(x) + end +end + +def fun_l2_n94(x) + if (x < 1) + fun_l3_n761(x) + else + fun_l3_n10(x) + end +end + +def fun_l2_n95(x) + if (x < 1) + fun_l3_n4(x) + else + fun_l3_n65(x) + end +end + +def fun_l2_n96(x) + if (x < 1) + fun_l3_n444(x) + else + fun_l3_n378(x) + end +end + +def fun_l2_n97(x) + if (x < 1) + fun_l3_n119(x) + else + fun_l3_n96(x) + end +end + +def fun_l2_n98(x) + if (x < 1) + fun_l3_n970(x) + else + fun_l3_n471(x) + end +end + +def fun_l2_n99(x) + if (x < 1) + fun_l3_n544(x) + else + fun_l3_n1(x) + end +end + +def fun_l2_n100(x) + if (x < 1) + fun_l3_n253(x) + else + fun_l3_n332(x) + end +end + +def fun_l2_n101(x) + if (x < 1) + fun_l3_n69(x) + else + fun_l3_n946(x) + end +end + +def fun_l2_n102(x) + if (x < 1) + fun_l3_n458(x) + else + fun_l3_n885(x) + end +end + +def fun_l2_n103(x) + if (x < 1) + fun_l3_n732(x) + else + fun_l3_n601(x) + end +end + +def fun_l2_n104(x) + if (x < 1) + fun_l3_n737(x) + else + fun_l3_n530(x) + end +end + +def fun_l2_n105(x) + if (x < 1) + fun_l3_n125(x) + else + fun_l3_n561(x) + end +end + +def fun_l2_n106(x) + if (x < 1) + fun_l3_n717(x) + else + fun_l3_n660(x) + end +end + +def fun_l2_n107(x) + if (x < 1) + fun_l3_n863(x) + else + fun_l3_n211(x) + end +end + +def fun_l2_n108(x) + if (x < 1) + fun_l3_n221(x) + else + fun_l3_n718(x) + end +end + +def fun_l2_n109(x) + if (x < 1) + fun_l3_n100(x) + else + fun_l3_n673(x) + end +end + +def fun_l2_n110(x) + if (x < 1) + fun_l3_n434(x) + else + fun_l3_n348(x) + end +end + +def fun_l2_n111(x) + if (x < 1) + fun_l3_n923(x) + else + fun_l3_n413(x) + end +end + +def fun_l2_n112(x) + if (x < 1) + fun_l3_n253(x) + else + fun_l3_n461(x) + end +end + +def fun_l2_n113(x) + if (x < 1) + fun_l3_n946(x) + else + fun_l3_n406(x) + end +end + +def fun_l2_n114(x) + if (x < 1) + fun_l3_n976(x) + else + fun_l3_n354(x) + end +end + +def fun_l2_n115(x) + if (x < 1) + fun_l3_n205(x) + else + fun_l3_n798(x) + end +end + +def fun_l2_n116(x) + if (x < 1) + fun_l3_n304(x) + else + fun_l3_n145(x) + end +end + +def fun_l2_n117(x) + if (x < 1) + fun_l3_n917(x) + else + fun_l3_n276(x) + end +end + +def fun_l2_n118(x) + if (x < 1) + fun_l3_n880(x) + else + fun_l3_n532(x) + end +end + +def fun_l2_n119(x) + if (x < 1) + fun_l3_n39(x) + else + fun_l3_n549(x) + end +end + +def fun_l2_n120(x) + if (x < 1) + fun_l3_n325(x) + else + fun_l3_n250(x) + end +end + +def fun_l2_n121(x) + if (x < 1) + fun_l3_n953(x) + else + fun_l3_n259(x) + end +end + +def fun_l2_n122(x) + if (x < 1) + fun_l3_n572(x) + else + fun_l3_n747(x) + end +end + +def fun_l2_n123(x) + if (x < 1) + fun_l3_n639(x) + else + fun_l3_n810(x) + end +end + +def fun_l2_n124(x) + if (x < 1) + fun_l3_n954(x) + else + fun_l3_n814(x) + end +end + +def fun_l2_n125(x) + if (x < 1) + fun_l3_n932(x) + else + fun_l3_n275(x) + end +end + +def fun_l2_n126(x) + if (x < 1) + fun_l3_n472(x) + else + fun_l3_n184(x) + end +end + +def fun_l2_n127(x) + if (x < 1) + fun_l3_n725(x) + else + fun_l3_n497(x) + end +end + +def fun_l2_n128(x) + if (x < 1) + fun_l3_n94(x) + else + fun_l3_n801(x) + end +end + +def fun_l2_n129(x) + if (x < 1) + fun_l3_n476(x) + else + fun_l3_n936(x) + end +end + +def fun_l2_n130(x) + if (x < 1) + fun_l3_n706(x) + else + fun_l3_n738(x) + end +end + +def fun_l2_n131(x) + if (x < 1) + fun_l3_n535(x) + else + fun_l3_n401(x) + end +end + +def fun_l2_n132(x) + if (x < 1) + fun_l3_n459(x) + else + fun_l3_n998(x) + end +end + +def fun_l2_n133(x) + if (x < 1) + fun_l3_n158(x) + else + fun_l3_n288(x) + end +end + +def fun_l2_n134(x) + if (x < 1) + fun_l3_n47(x) + else + fun_l3_n104(x) + end +end + +def fun_l2_n135(x) + if (x < 1) + fun_l3_n154(x) + else + fun_l3_n239(x) + end +end + +def fun_l2_n136(x) + if (x < 1) + fun_l3_n634(x) + else + fun_l3_n718(x) + end +end + +def fun_l2_n137(x) + if (x < 1) + fun_l3_n867(x) + else + fun_l3_n578(x) + end +end + +def fun_l2_n138(x) + if (x < 1) + fun_l3_n905(x) + else + fun_l3_n434(x) + end +end + +def fun_l2_n139(x) + if (x < 1) + fun_l3_n596(x) + else + fun_l3_n516(x) + end +end + +def fun_l2_n140(x) + if (x < 1) + fun_l3_n150(x) + else + fun_l3_n901(x) + end +end + +def fun_l2_n141(x) + if (x < 1) + fun_l3_n792(x) + else + fun_l3_n50(x) + end +end + +def fun_l2_n142(x) + if (x < 1) + fun_l3_n539(x) + else + fun_l3_n206(x) + end +end + +def fun_l2_n143(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n788(x) + end +end + +def fun_l2_n144(x) + if (x < 1) + fun_l3_n535(x) + else + fun_l3_n868(x) + end +end + +def fun_l2_n145(x) + if (x < 1) + fun_l3_n869(x) + else + fun_l3_n865(x) + end +end + +def fun_l2_n146(x) + if (x < 1) + fun_l3_n574(x) + else + fun_l3_n798(x) + end +end + +def fun_l2_n147(x) + if (x < 1) + fun_l3_n876(x) + else + fun_l3_n658(x) + end +end + +def fun_l2_n148(x) + if (x < 1) + fun_l3_n582(x) + else + fun_l3_n694(x) + end +end + +def fun_l2_n149(x) + if (x < 1) + fun_l3_n137(x) + else + fun_l3_n187(x) + end +end + +def fun_l2_n150(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n666(x) + end +end + +def fun_l2_n151(x) + if (x < 1) + fun_l3_n264(x) + else + fun_l3_n236(x) + end +end + +def fun_l2_n152(x) + if (x < 1) + fun_l3_n984(x) + else + fun_l3_n469(x) + end +end + +def fun_l2_n153(x) + if (x < 1) + fun_l3_n152(x) + else + fun_l3_n578(x) + end +end + +def fun_l2_n154(x) + if (x < 1) + fun_l3_n452(x) + else + fun_l3_n807(x) + end +end + +def fun_l2_n155(x) + if (x < 1) + fun_l3_n82(x) + else + fun_l3_n589(x) + end +end + +def fun_l2_n156(x) + if (x < 1) + fun_l3_n356(x) + else + fun_l3_n454(x) + end +end + +def fun_l2_n157(x) + if (x < 1) + fun_l3_n814(x) + else + fun_l3_n376(x) + end +end + +def fun_l2_n158(x) + if (x < 1) + fun_l3_n755(x) + else + fun_l3_n966(x) + end +end + +def fun_l2_n159(x) + if (x < 1) + fun_l3_n167(x) + else + fun_l3_n571(x) + end +end + +def fun_l2_n160(x) + if (x < 1) + fun_l3_n919(x) + else + fun_l3_n771(x) + end +end + +def fun_l2_n161(x) + if (x < 1) + fun_l3_n147(x) + else + fun_l3_n936(x) + end +end + +def fun_l2_n162(x) + if (x < 1) + fun_l3_n638(x) + else + fun_l3_n23(x) + end +end + +def fun_l2_n163(x) + if (x < 1) + fun_l3_n349(x) + else + fun_l3_n46(x) + end +end + +def fun_l2_n164(x) + if (x < 1) + fun_l3_n55(x) + else + fun_l3_n795(x) + end +end + +def fun_l2_n165(x) + if (x < 1) + fun_l3_n131(x) + else + fun_l3_n233(x) + end +end + +def fun_l2_n166(x) + if (x < 1) + fun_l3_n324(x) + else + fun_l3_n215(x) + end +end + +def fun_l2_n167(x) + if (x < 1) + fun_l3_n244(x) + else + fun_l3_n641(x) + end +end + +def fun_l2_n168(x) + if (x < 1) + fun_l3_n744(x) + else + fun_l3_n337(x) + end +end + +def fun_l2_n169(x) + if (x < 1) + fun_l3_n760(x) + else + fun_l3_n82(x) + end +end + +def fun_l2_n170(x) + if (x < 1) + fun_l3_n877(x) + else + fun_l3_n566(x) + end +end + +def fun_l2_n171(x) + if (x < 1) + fun_l3_n211(x) + else + fun_l3_n101(x) + end +end + +def fun_l2_n172(x) + if (x < 1) + fun_l3_n143(x) + else + fun_l3_n537(x) + end +end + +def fun_l2_n173(x) + if (x < 1) + fun_l3_n210(x) + else + fun_l3_n150(x) + end +end + +def fun_l2_n174(x) + if (x < 1) + fun_l3_n772(x) + else + fun_l3_n42(x) + end +end + +def fun_l2_n175(x) + if (x < 1) + fun_l3_n482(x) + else + fun_l3_n606(x) + end +end + +def fun_l2_n176(x) + if (x < 1) + fun_l3_n68(x) + else + fun_l3_n888(x) + end +end + +def fun_l2_n177(x) + if (x < 1) + fun_l3_n313(x) + else + fun_l3_n947(x) + end +end + +def fun_l2_n178(x) + if (x < 1) + fun_l3_n116(x) + else + fun_l3_n812(x) + end +end + +def fun_l2_n179(x) + if (x < 1) + fun_l3_n741(x) + else + fun_l3_n994(x) + end +end + +def fun_l2_n180(x) + if (x < 1) + fun_l3_n667(x) + else + fun_l3_n335(x) + end +end + +def fun_l2_n181(x) + if (x < 1) + fun_l3_n994(x) + else + fun_l3_n502(x) + end +end + +def fun_l2_n182(x) + if (x < 1) + fun_l3_n528(x) + else + fun_l3_n272(x) + end +end + +def fun_l2_n183(x) + if (x < 1) + fun_l3_n649(x) + else + fun_l3_n200(x) + end +end + +def fun_l2_n184(x) + if (x < 1) + fun_l3_n105(x) + else + fun_l3_n897(x) + end +end + +def fun_l2_n185(x) + if (x < 1) + fun_l3_n980(x) + else + fun_l3_n651(x) + end +end + +def fun_l2_n186(x) + if (x < 1) + fun_l3_n835(x) + else + fun_l3_n388(x) + end +end + +def fun_l2_n187(x) + if (x < 1) + fun_l3_n769(x) + else + fun_l3_n162(x) + end +end + +def fun_l2_n188(x) + if (x < 1) + fun_l3_n934(x) + else + fun_l3_n874(x) + end +end + +def fun_l2_n189(x) + if (x < 1) + fun_l3_n407(x) + else + fun_l3_n180(x) + end +end + +def fun_l2_n190(x) + if (x < 1) + fun_l3_n594(x) + else + fun_l3_n929(x) + end +end + +def fun_l2_n191(x) + if (x < 1) + fun_l3_n303(x) + else + fun_l3_n528(x) + end +end + +def fun_l2_n192(x) + if (x < 1) + fun_l3_n768(x) + else + fun_l3_n226(x) + end +end + +def fun_l2_n193(x) + if (x < 1) + fun_l3_n618(x) + else + fun_l3_n821(x) + end +end + +def fun_l2_n194(x) + if (x < 1) + fun_l3_n953(x) + else + fun_l3_n969(x) + end +end + +def fun_l2_n195(x) + if (x < 1) + fun_l3_n574(x) + else + fun_l3_n344(x) + end +end + +def fun_l2_n196(x) + if (x < 1) + fun_l3_n943(x) + else + fun_l3_n304(x) + end +end + +def fun_l2_n197(x) + if (x < 1) + fun_l3_n276(x) + else + fun_l3_n502(x) + end +end + +def fun_l2_n198(x) + if (x < 1) + fun_l3_n597(x) + else + fun_l3_n197(x) + end +end + +def fun_l2_n199(x) + if (x < 1) + fun_l3_n517(x) + else + fun_l3_n34(x) + end +end + +def fun_l2_n200(x) + if (x < 1) + fun_l3_n980(x) + else + fun_l3_n672(x) + end +end + +def fun_l2_n201(x) + if (x < 1) + fun_l3_n510(x) + else + fun_l3_n804(x) + end +end + +def fun_l2_n202(x) + if (x < 1) + fun_l3_n735(x) + else + fun_l3_n367(x) + end +end + +def fun_l2_n203(x) + if (x < 1) + fun_l3_n546(x) + else + fun_l3_n502(x) + end +end + +def fun_l2_n204(x) + if (x < 1) + fun_l3_n189(x) + else + fun_l3_n639(x) + end +end + +def fun_l2_n205(x) + if (x < 1) + fun_l3_n396(x) + else + fun_l3_n862(x) + end +end + +def fun_l2_n206(x) + if (x < 1) + fun_l3_n679(x) + else + fun_l3_n881(x) + end +end + +def fun_l2_n207(x) + if (x < 1) + fun_l3_n342(x) + else + fun_l3_n522(x) + end +end + +def fun_l2_n208(x) + if (x < 1) + fun_l3_n173(x) + else + fun_l3_n323(x) + end +end + +def fun_l2_n209(x) + if (x < 1) + fun_l3_n693(x) + else + fun_l3_n160(x) + end +end + +def fun_l2_n210(x) + if (x < 1) + fun_l3_n827(x) + else + fun_l3_n580(x) + end +end + +def fun_l2_n211(x) + if (x < 1) + fun_l3_n213(x) + else + fun_l3_n100(x) + end +end + +def fun_l2_n212(x) + if (x < 1) + fun_l3_n915(x) + else + fun_l3_n531(x) + end +end + +def fun_l2_n213(x) + if (x < 1) + fun_l3_n260(x) + else + fun_l3_n279(x) + end +end + +def fun_l2_n214(x) + if (x < 1) + fun_l3_n468(x) + else + fun_l3_n257(x) + end +end + +def fun_l2_n215(x) + if (x < 1) + fun_l3_n990(x) + else + fun_l3_n740(x) + end +end + +def fun_l2_n216(x) + if (x < 1) + fun_l3_n291(x) + else + fun_l3_n625(x) + end +end + +def fun_l2_n217(x) + if (x < 1) + fun_l3_n493(x) + else + fun_l3_n726(x) + end +end + +def fun_l2_n218(x) + if (x < 1) + fun_l3_n714(x) + else + fun_l3_n793(x) + end +end + +def fun_l2_n219(x) + if (x < 1) + fun_l3_n683(x) + else + fun_l3_n715(x) + end +end + +def fun_l2_n220(x) + if (x < 1) + fun_l3_n249(x) + else + fun_l3_n266(x) + end +end + +def fun_l2_n221(x) + if (x < 1) + fun_l3_n324(x) + else + fun_l3_n22(x) + end +end + +def fun_l2_n222(x) + if (x < 1) + fun_l3_n978(x) + else + fun_l3_n885(x) + end +end + +def fun_l2_n223(x) + if (x < 1) + fun_l3_n821(x) + else + fun_l3_n412(x) + end +end + +def fun_l2_n224(x) + if (x < 1) + fun_l3_n636(x) + else + fun_l3_n641(x) + end +end + +def fun_l2_n225(x) + if (x < 1) + fun_l3_n971(x) + else + fun_l3_n288(x) + end +end + +def fun_l2_n226(x) + if (x < 1) + fun_l3_n429(x) + else + fun_l3_n323(x) + end +end + +def fun_l2_n227(x) + if (x < 1) + fun_l3_n909(x) + else + fun_l3_n267(x) + end +end + +def fun_l2_n228(x) + if (x < 1) + fun_l3_n437(x) + else + fun_l3_n985(x) + end +end + +def fun_l2_n229(x) + if (x < 1) + fun_l3_n131(x) + else + fun_l3_n298(x) + end +end + +def fun_l2_n230(x) + if (x < 1) + fun_l3_n865(x) + else + fun_l3_n288(x) + end +end + +def fun_l2_n231(x) + if (x < 1) + fun_l3_n772(x) + else + fun_l3_n531(x) + end +end + +def fun_l2_n232(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n422(x) + end +end + +def fun_l2_n233(x) + if (x < 1) + fun_l3_n82(x) + else + fun_l3_n32(x) + end +end + +def fun_l2_n234(x) + if (x < 1) + fun_l3_n25(x) + else + fun_l3_n518(x) + end +end + +def fun_l2_n235(x) + if (x < 1) + fun_l3_n313(x) + else + fun_l3_n179(x) + end +end + +def fun_l2_n236(x) + if (x < 1) + fun_l3_n819(x) + else + fun_l3_n586(x) + end +end + +def fun_l2_n237(x) + if (x < 1) + fun_l3_n398(x) + else + fun_l3_n921(x) + end +end + +def fun_l2_n238(x) + if (x < 1) + fun_l3_n667(x) + else + fun_l3_n795(x) + end +end + +def fun_l2_n239(x) + if (x < 1) + fun_l3_n862(x) + else + fun_l3_n222(x) + end +end + +def fun_l2_n240(x) + if (x < 1) + fun_l3_n968(x) + else + fun_l3_n320(x) + end +end + +def fun_l2_n241(x) + if (x < 1) + fun_l3_n559(x) + else + fun_l3_n50(x) + end +end + +def fun_l2_n242(x) + if (x < 1) + fun_l3_n647(x) + else + fun_l3_n232(x) + end +end + +def fun_l2_n243(x) + if (x < 1) + fun_l3_n425(x) + else + fun_l3_n815(x) + end +end + +def fun_l2_n244(x) + if (x < 1) + fun_l3_n752(x) + else + fun_l3_n690(x) + end +end + +def fun_l2_n245(x) + if (x < 1) + fun_l3_n382(x) + else + fun_l3_n817(x) + end +end + +def fun_l2_n246(x) + if (x < 1) + fun_l3_n880(x) + else + fun_l3_n380(x) + end +end + +def fun_l2_n247(x) + if (x < 1) + fun_l3_n444(x) + else + fun_l3_n75(x) + end +end + +def fun_l2_n248(x) + if (x < 1) + fun_l3_n368(x) + else + fun_l3_n314(x) + end +end + +def fun_l2_n249(x) + if (x < 1) + fun_l3_n131(x) + else + fun_l3_n398(x) + end +end + +def fun_l2_n250(x) + if (x < 1) + fun_l3_n376(x) + else + fun_l3_n449(x) + end +end + +def fun_l2_n251(x) + if (x < 1) + fun_l3_n404(x) + else + fun_l3_n301(x) + end +end + +def fun_l2_n252(x) + if (x < 1) + fun_l3_n274(x) + else + fun_l3_n430(x) + end +end + +def fun_l2_n253(x) + if (x < 1) + fun_l3_n734(x) + else + fun_l3_n255(x) + end +end + +def fun_l2_n254(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n944(x) + end +end + +def fun_l2_n255(x) + if (x < 1) + fun_l3_n978(x) + else + fun_l3_n898(x) + end +end + +def fun_l2_n256(x) + if (x < 1) + fun_l3_n175(x) + else + fun_l3_n477(x) + end +end + +def fun_l2_n257(x) + if (x < 1) + fun_l3_n84(x) + else + fun_l3_n772(x) + end +end + +def fun_l2_n258(x) + if (x < 1) + fun_l3_n605(x) + else + fun_l3_n144(x) + end +end + +def fun_l2_n259(x) + if (x < 1) + fun_l3_n51(x) + else + fun_l3_n542(x) + end +end + +def fun_l2_n260(x) + if (x < 1) + fun_l3_n940(x) + else + fun_l3_n316(x) + end +end + +def fun_l2_n261(x) + if (x < 1) + fun_l3_n702(x) + else + fun_l3_n197(x) + end +end + +def fun_l2_n262(x) + if (x < 1) + fun_l3_n164(x) + else + fun_l3_n21(x) + end +end + +def fun_l2_n263(x) + if (x < 1) + fun_l3_n432(x) + else + fun_l3_n496(x) + end +end + +def fun_l2_n264(x) + if (x < 1) + fun_l3_n265(x) + else + fun_l3_n40(x) + end +end + +def fun_l2_n265(x) + if (x < 1) + fun_l3_n951(x) + else + fun_l3_n723(x) + end +end + +def fun_l2_n266(x) + if (x < 1) + fun_l3_n279(x) + else + fun_l3_n167(x) + end +end + +def fun_l2_n267(x) + if (x < 1) + fun_l3_n51(x) + else + fun_l3_n283(x) + end +end + +def fun_l2_n268(x) + if (x < 1) + fun_l3_n389(x) + else + fun_l3_n264(x) + end +end + +def fun_l2_n269(x) + if (x < 1) + fun_l3_n68(x) + else + fun_l3_n484(x) + end +end + +def fun_l2_n270(x) + if (x < 1) + fun_l3_n435(x) + else + fun_l3_n204(x) + end +end + +def fun_l2_n271(x) + if (x < 1) + fun_l3_n717(x) + else + fun_l3_n763(x) + end +end + +def fun_l2_n272(x) + if (x < 1) + fun_l3_n901(x) + else + fun_l3_n332(x) + end +end + +def fun_l2_n273(x) + if (x < 1) + fun_l3_n358(x) + else + fun_l3_n608(x) + end +end + +def fun_l2_n274(x) + if (x < 1) + fun_l3_n885(x) + else + fun_l3_n490(x) + end +end + +def fun_l2_n275(x) + if (x < 1) + fun_l3_n82(x) + else + fun_l3_n87(x) + end +end + +def fun_l2_n276(x) + if (x < 1) + fun_l3_n698(x) + else + fun_l3_n846(x) + end +end + +def fun_l2_n277(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n457(x) + end +end + +def fun_l2_n278(x) + if (x < 1) + fun_l3_n925(x) + else + fun_l3_n674(x) + end +end + +def fun_l2_n279(x) + if (x < 1) + fun_l3_n797(x) + else + fun_l3_n315(x) + end +end + +def fun_l2_n280(x) + if (x < 1) + fun_l3_n73(x) + else + fun_l3_n2(x) + end +end + +def fun_l2_n281(x) + if (x < 1) + fun_l3_n301(x) + else + fun_l3_n315(x) + end +end + +def fun_l2_n282(x) + if (x < 1) + fun_l3_n473(x) + else + fun_l3_n639(x) + end +end + +def fun_l2_n283(x) + if (x < 1) + fun_l3_n812(x) + else + fun_l3_n241(x) + end +end + +def fun_l2_n284(x) + if (x < 1) + fun_l3_n0(x) + else + fun_l3_n445(x) + end +end + +def fun_l2_n285(x) + if (x < 1) + fun_l3_n587(x) + else + fun_l3_n806(x) + end +end + +def fun_l2_n286(x) + if (x < 1) + fun_l3_n169(x) + else + fun_l3_n546(x) + end +end + +def fun_l2_n287(x) + if (x < 1) + fun_l3_n623(x) + else + fun_l3_n677(x) + end +end + +def fun_l2_n288(x) + if (x < 1) + fun_l3_n804(x) + else + fun_l3_n80(x) + end +end + +def fun_l2_n289(x) + if (x < 1) + fun_l3_n812(x) + else + fun_l3_n197(x) + end +end + +def fun_l2_n290(x) + if (x < 1) + fun_l3_n551(x) + else + fun_l3_n896(x) + end +end + +def fun_l2_n291(x) + if (x < 1) + fun_l3_n686(x) + else + fun_l3_n884(x) + end +end + +def fun_l2_n292(x) + if (x < 1) + fun_l3_n427(x) + else + fun_l3_n251(x) + end +end + +def fun_l2_n293(x) + if (x < 1) + fun_l3_n375(x) + else + fun_l3_n309(x) + end +end + +def fun_l2_n294(x) + if (x < 1) + fun_l3_n371(x) + else + fun_l3_n184(x) + end +end + +def fun_l2_n295(x) + if (x < 1) + fun_l3_n332(x) + else + fun_l3_n250(x) + end +end + +def fun_l2_n296(x) + if (x < 1) + fun_l3_n333(x) + else + fun_l3_n254(x) + end +end + +def fun_l2_n297(x) + if (x < 1) + fun_l3_n24(x) + else + fun_l3_n528(x) + end +end + +def fun_l2_n298(x) + if (x < 1) + fun_l3_n96(x) + else + fun_l3_n653(x) + end +end + +def fun_l2_n299(x) + if (x < 1) + fun_l3_n920(x) + else + fun_l3_n475(x) + end +end + +def fun_l2_n300(x) + if (x < 1) + fun_l3_n337(x) + else + fun_l3_n378(x) + end +end + +def fun_l2_n301(x) + if (x < 1) + fun_l3_n778(x) + else + fun_l3_n216(x) + end +end + +def fun_l2_n302(x) + if (x < 1) + fun_l3_n366(x) + else + fun_l3_n562(x) + end +end + +def fun_l2_n303(x) + if (x < 1) + fun_l3_n656(x) + else + fun_l3_n779(x) + end +end + +def fun_l2_n304(x) + if (x < 1) + fun_l3_n526(x) + else + fun_l3_n783(x) + end +end + +def fun_l2_n305(x) + if (x < 1) + fun_l3_n500(x) + else + fun_l3_n744(x) + end +end + +def fun_l2_n306(x) + if (x < 1) + fun_l3_n953(x) + else + fun_l3_n394(x) + end +end + +def fun_l2_n307(x) + if (x < 1) + fun_l3_n385(x) + else + fun_l3_n937(x) + end +end + +def fun_l2_n308(x) + if (x < 1) + fun_l3_n742(x) + else + fun_l3_n984(x) + end +end + +def fun_l2_n309(x) + if (x < 1) + fun_l3_n388(x) + else + fun_l3_n704(x) + end +end + +def fun_l2_n310(x) + if (x < 1) + fun_l3_n252(x) + else + fun_l3_n585(x) + end +end + +def fun_l2_n311(x) + if (x < 1) + fun_l3_n121(x) + else + fun_l3_n815(x) + end +end + +def fun_l2_n312(x) + if (x < 1) + fun_l3_n657(x) + else + fun_l3_n338(x) + end +end + +def fun_l2_n313(x) + if (x < 1) + fun_l3_n115(x) + else + fun_l3_n748(x) + end +end + +def fun_l2_n314(x) + if (x < 1) + fun_l3_n237(x) + else + fun_l3_n319(x) + end +end + +def fun_l2_n315(x) + if (x < 1) + fun_l3_n684(x) + else + fun_l3_n428(x) + end +end + +def fun_l2_n316(x) + if (x < 1) + fun_l3_n416(x) + else + fun_l3_n499(x) + end +end + +def fun_l2_n317(x) + if (x < 1) + fun_l3_n305(x) + else + fun_l3_n888(x) + end +end + +def fun_l2_n318(x) + if (x < 1) + fun_l3_n506(x) + else + fun_l3_n579(x) + end +end + +def fun_l2_n319(x) + if (x < 1) + fun_l3_n324(x) + else + fun_l3_n459(x) + end +end + +def fun_l2_n320(x) + if (x < 1) + fun_l3_n278(x) + else + fun_l3_n89(x) + end +end + +def fun_l2_n321(x) + if (x < 1) + fun_l3_n319(x) + else + fun_l3_n903(x) + end +end + +def fun_l2_n322(x) + if (x < 1) + fun_l3_n96(x) + else + fun_l3_n334(x) + end +end + +def fun_l2_n323(x) + if (x < 1) + fun_l3_n913(x) + else + fun_l3_n309(x) + end +end + +def fun_l2_n324(x) + if (x < 1) + fun_l3_n186(x) + else + fun_l3_n453(x) + end +end + +def fun_l2_n325(x) + if (x < 1) + fun_l3_n223(x) + else + fun_l3_n761(x) + end +end + +def fun_l2_n326(x) + if (x < 1) + fun_l3_n757(x) + else + fun_l3_n700(x) + end +end + +def fun_l2_n327(x) + if (x < 1) + fun_l3_n316(x) + else + fun_l3_n3(x) + end +end + +def fun_l2_n328(x) + if (x < 1) + fun_l3_n680(x) + else + fun_l3_n275(x) + end +end + +def fun_l2_n329(x) + if (x < 1) + fun_l3_n731(x) + else + fun_l3_n971(x) + end +end + +def fun_l2_n330(x) + if (x < 1) + fun_l3_n672(x) + else + fun_l3_n389(x) + end +end + +def fun_l2_n331(x) + if (x < 1) + fun_l3_n947(x) + else + fun_l3_n778(x) + end +end + +def fun_l2_n332(x) + if (x < 1) + fun_l3_n23(x) + else + fun_l3_n478(x) + end +end + +def fun_l2_n333(x) + if (x < 1) + fun_l3_n778(x) + else + fun_l3_n894(x) + end +end + +def fun_l2_n334(x) + if (x < 1) + fun_l3_n198(x) + else + fun_l3_n830(x) + end +end + +def fun_l2_n335(x) + if (x < 1) + fun_l3_n874(x) + else + fun_l3_n861(x) + end +end + +def fun_l2_n336(x) + if (x < 1) + fun_l3_n66(x) + else + fun_l3_n47(x) + end +end + +def fun_l2_n337(x) + if (x < 1) + fun_l3_n65(x) + else + fun_l3_n849(x) + end +end + +def fun_l2_n338(x) + if (x < 1) + fun_l3_n122(x) + else + fun_l3_n891(x) + end +end + +def fun_l2_n339(x) + if (x < 1) + fun_l3_n377(x) + else + fun_l3_n862(x) + end +end + +def fun_l2_n340(x) + if (x < 1) + fun_l3_n278(x) + else + fun_l3_n495(x) + end +end + +def fun_l2_n341(x) + if (x < 1) + fun_l3_n396(x) + else + fun_l3_n842(x) + end +end + +def fun_l2_n342(x) + if (x < 1) + fun_l3_n971(x) + else + fun_l3_n296(x) + end +end + +def fun_l2_n343(x) + if (x < 1) + fun_l3_n137(x) + else + fun_l3_n815(x) + end +end + +def fun_l2_n344(x) + if (x < 1) + fun_l3_n910(x) + else + fun_l3_n515(x) + end +end + +def fun_l2_n345(x) + if (x < 1) + fun_l3_n415(x) + else + fun_l3_n766(x) + end +end + +def fun_l2_n346(x) + if (x < 1) + fun_l3_n816(x) + else + fun_l3_n169(x) + end +end + +def fun_l2_n347(x) + if (x < 1) + fun_l3_n223(x) + else + fun_l3_n776(x) + end +end + +def fun_l2_n348(x) + if (x < 1) + fun_l3_n316(x) + else + fun_l3_n497(x) + end +end + +def fun_l2_n349(x) + if (x < 1) + fun_l3_n116(x) + else + fun_l3_n536(x) + end +end + +def fun_l2_n350(x) + if (x < 1) + fun_l3_n252(x) + else + fun_l3_n981(x) + end +end + +def fun_l2_n351(x) + if (x < 1) + fun_l3_n783(x) + else + fun_l3_n596(x) + end +end + +def fun_l2_n352(x) + if (x < 1) + fun_l3_n72(x) + else + fun_l3_n978(x) + end +end + +def fun_l2_n353(x) + if (x < 1) + fun_l3_n910(x) + else + fun_l3_n493(x) + end +end + +def fun_l2_n354(x) + if (x < 1) + fun_l3_n671(x) + else + fun_l3_n297(x) + end +end + +def fun_l2_n355(x) + if (x < 1) + fun_l3_n820(x) + else + fun_l3_n456(x) + end +end + +def fun_l2_n356(x) + if (x < 1) + fun_l3_n23(x) + else + fun_l3_n760(x) + end +end + +def fun_l2_n357(x) + if (x < 1) + fun_l3_n676(x) + else + fun_l3_n531(x) + end +end + +def fun_l2_n358(x) + if (x < 1) + fun_l3_n849(x) + else + fun_l3_n592(x) + end +end + +def fun_l2_n359(x) + if (x < 1) + fun_l3_n492(x) + else + fun_l3_n845(x) + end +end + +def fun_l2_n360(x) + if (x < 1) + fun_l3_n58(x) + else + fun_l3_n896(x) + end +end + +def fun_l2_n361(x) + if (x < 1) + fun_l3_n427(x) + else + fun_l3_n434(x) + end +end + +def fun_l2_n362(x) + if (x < 1) + fun_l3_n129(x) + else + fun_l3_n582(x) + end +end + +def fun_l2_n363(x) + if (x < 1) + fun_l3_n901(x) + else + fun_l3_n405(x) + end +end + +def fun_l2_n364(x) + if (x < 1) + fun_l3_n577(x) + else + fun_l3_n550(x) + end +end + +def fun_l2_n365(x) + if (x < 1) + fun_l3_n717(x) + else + fun_l3_n660(x) + end +end + +def fun_l2_n366(x) + if (x < 1) + fun_l3_n605(x) + else + fun_l3_n755(x) + end +end + +def fun_l2_n367(x) + if (x < 1) + fun_l3_n875(x) + else + fun_l3_n784(x) + end +end + +def fun_l2_n368(x) + if (x < 1) + fun_l3_n914(x) + else + fun_l3_n351(x) + end +end + +def fun_l2_n369(x) + if (x < 1) + fun_l3_n684(x) + else + fun_l3_n932(x) + end +end + +def fun_l2_n370(x) + if (x < 1) + fun_l3_n796(x) + else + fun_l3_n920(x) + end +end + +def fun_l2_n371(x) + if (x < 1) + fun_l3_n456(x) + else + fun_l3_n188(x) + end +end + +def fun_l2_n372(x) + if (x < 1) + fun_l3_n891(x) + else + fun_l3_n905(x) + end +end + +def fun_l2_n373(x) + if (x < 1) + fun_l3_n906(x) + else + fun_l3_n993(x) + end +end + +def fun_l2_n374(x) + if (x < 1) + fun_l3_n811(x) + else + fun_l3_n629(x) + end +end + +def fun_l2_n375(x) + if (x < 1) + fun_l3_n5(x) + else + fun_l3_n304(x) + end +end + +def fun_l2_n376(x) + if (x < 1) + fun_l3_n240(x) + else + fun_l3_n859(x) + end +end + +def fun_l2_n377(x) + if (x < 1) + fun_l3_n346(x) + else + fun_l3_n196(x) + end +end + +def fun_l2_n378(x) + if (x < 1) + fun_l3_n918(x) + else + fun_l3_n371(x) + end +end + +def fun_l2_n379(x) + if (x < 1) + fun_l3_n112(x) + else + fun_l3_n269(x) + end +end + +def fun_l2_n380(x) + if (x < 1) + fun_l3_n46(x) + else + fun_l3_n397(x) + end +end + +def fun_l2_n381(x) + if (x < 1) + fun_l3_n977(x) + else + fun_l3_n647(x) + end +end + +def fun_l2_n382(x) + if (x < 1) + fun_l3_n788(x) + else + fun_l3_n418(x) + end +end + +def fun_l2_n383(x) + if (x < 1) + fun_l3_n395(x) + else + fun_l3_n268(x) + end +end + +def fun_l2_n384(x) + if (x < 1) + fun_l3_n39(x) + else + fun_l3_n950(x) + end +end + +def fun_l2_n385(x) + if (x < 1) + fun_l3_n301(x) + else + fun_l3_n241(x) + end +end + +def fun_l2_n386(x) + if (x < 1) + fun_l3_n936(x) + else + fun_l3_n416(x) + end +end + +def fun_l2_n387(x) + if (x < 1) + fun_l3_n750(x) + else + fun_l3_n152(x) + end +end + +def fun_l2_n388(x) + if (x < 1) + fun_l3_n210(x) + else + fun_l3_n824(x) + end +end + +def fun_l2_n389(x) + if (x < 1) + fun_l3_n3(x) + else + fun_l3_n872(x) + end +end + +def fun_l2_n390(x) + if (x < 1) + fun_l3_n944(x) + else + fun_l3_n49(x) + end +end + +def fun_l2_n391(x) + if (x < 1) + fun_l3_n645(x) + else + fun_l3_n604(x) + end +end + +def fun_l2_n392(x) + if (x < 1) + fun_l3_n539(x) + else + fun_l3_n374(x) + end +end + +def fun_l2_n393(x) + if (x < 1) + fun_l3_n728(x) + else + fun_l3_n620(x) + end +end + +def fun_l2_n394(x) + if (x < 1) + fun_l3_n538(x) + else + fun_l3_n233(x) + end +end + +def fun_l2_n395(x) + if (x < 1) + fun_l3_n977(x) + else + fun_l3_n351(x) + end +end + +def fun_l2_n396(x) + if (x < 1) + fun_l3_n54(x) + else + fun_l3_n958(x) + end +end + +def fun_l2_n397(x) + if (x < 1) + fun_l3_n237(x) + else + fun_l3_n54(x) + end +end + +def fun_l2_n398(x) + if (x < 1) + fun_l3_n846(x) + else + fun_l3_n234(x) + end +end + +def fun_l2_n399(x) + if (x < 1) + fun_l3_n934(x) + else + fun_l3_n128(x) + end +end + +def fun_l2_n400(x) + if (x < 1) + fun_l3_n15(x) + else + fun_l3_n288(x) + end +end + +def fun_l2_n401(x) + if (x < 1) + fun_l3_n944(x) + else + fun_l3_n455(x) + end +end + +def fun_l2_n402(x) + if (x < 1) + fun_l3_n962(x) + else + fun_l3_n785(x) + end +end + +def fun_l2_n403(x) + if (x < 1) + fun_l3_n408(x) + else + fun_l3_n689(x) + end +end + +def fun_l2_n404(x) + if (x < 1) + fun_l3_n722(x) + else + fun_l3_n704(x) + end +end + +def fun_l2_n405(x) + if (x < 1) + fun_l3_n410(x) + else + fun_l3_n543(x) + end +end + +def fun_l2_n406(x) + if (x < 1) + fun_l3_n953(x) + else + fun_l3_n351(x) + end +end + +def fun_l2_n407(x) + if (x < 1) + fun_l3_n426(x) + else + fun_l3_n467(x) + end +end + +def fun_l2_n408(x) + if (x < 1) + fun_l3_n204(x) + else + fun_l3_n163(x) + end +end + +def fun_l2_n409(x) + if (x < 1) + fun_l3_n418(x) + else + fun_l3_n896(x) + end +end + +def fun_l2_n410(x) + if (x < 1) + fun_l3_n915(x) + else + fun_l3_n800(x) + end +end + +def fun_l2_n411(x) + if (x < 1) + fun_l3_n580(x) + else + fun_l3_n507(x) + end +end + +def fun_l2_n412(x) + if (x < 1) + fun_l3_n672(x) + else + fun_l3_n938(x) + end +end + +def fun_l2_n413(x) + if (x < 1) + fun_l3_n112(x) + else + fun_l3_n927(x) + end +end + +def fun_l2_n414(x) + if (x < 1) + fun_l3_n801(x) + else + fun_l3_n604(x) + end +end + +def fun_l2_n415(x) + if (x < 1) + fun_l3_n773(x) + else + fun_l3_n951(x) + end +end + +def fun_l2_n416(x) + if (x < 1) + fun_l3_n335(x) + else + fun_l3_n157(x) + end +end + +def fun_l2_n417(x) + if (x < 1) + fun_l3_n480(x) + else + fun_l3_n106(x) + end +end + +def fun_l2_n418(x) + if (x < 1) + fun_l3_n523(x) + else + fun_l3_n969(x) + end +end + +def fun_l2_n419(x) + if (x < 1) + fun_l3_n371(x) + else + fun_l3_n698(x) + end +end + +def fun_l2_n420(x) + if (x < 1) + fun_l3_n102(x) + else + fun_l3_n47(x) + end +end + +def fun_l2_n421(x) + if (x < 1) + fun_l3_n64(x) + else + fun_l3_n574(x) + end +end + +def fun_l2_n422(x) + if (x < 1) + fun_l3_n208(x) + else + fun_l3_n904(x) + end +end + +def fun_l2_n423(x) + if (x < 1) + fun_l3_n715(x) + else + fun_l3_n414(x) + end +end + +def fun_l2_n424(x) + if (x < 1) + fun_l3_n455(x) + else + fun_l3_n219(x) + end +end + +def fun_l2_n425(x) + if (x < 1) + fun_l3_n210(x) + else + fun_l3_n160(x) + end +end + +def fun_l2_n426(x) + if (x < 1) + fun_l3_n729(x) + else + fun_l3_n512(x) + end +end + +def fun_l2_n427(x) + if (x < 1) + fun_l3_n159(x) + else + fun_l3_n482(x) + end +end + +def fun_l2_n428(x) + if (x < 1) + fun_l3_n182(x) + else + fun_l3_n687(x) + end +end + +def fun_l2_n429(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n856(x) + end +end + +def fun_l2_n430(x) + if (x < 1) + fun_l3_n494(x) + else + fun_l3_n365(x) + end +end + +def fun_l2_n431(x) + if (x < 1) + fun_l3_n346(x) + else + fun_l3_n82(x) + end +end + +def fun_l2_n432(x) + if (x < 1) + fun_l3_n311(x) + else + fun_l3_n412(x) + end +end + +def fun_l2_n433(x) + if (x < 1) + fun_l3_n824(x) + else + fun_l3_n494(x) + end +end + +def fun_l2_n434(x) + if (x < 1) + fun_l3_n471(x) + else + fun_l3_n174(x) + end +end + +def fun_l2_n435(x) + if (x < 1) + fun_l3_n10(x) + else + fun_l3_n319(x) + end +end + +def fun_l2_n436(x) + if (x < 1) + fun_l3_n223(x) + else + fun_l3_n518(x) + end +end + +def fun_l2_n437(x) + if (x < 1) + fun_l3_n497(x) + else + fun_l3_n685(x) + end +end + +def fun_l2_n438(x) + if (x < 1) + fun_l3_n639(x) + else + fun_l3_n695(x) + end +end + +def fun_l2_n439(x) + if (x < 1) + fun_l3_n898(x) + else + fun_l3_n114(x) + end +end + +def fun_l2_n440(x) + if (x < 1) + fun_l3_n12(x) + else + fun_l3_n344(x) + end +end + +def fun_l2_n441(x) + if (x < 1) + fun_l3_n556(x) + else + fun_l3_n684(x) + end +end + +def fun_l2_n442(x) + if (x < 1) + fun_l3_n403(x) + else + fun_l3_n528(x) + end +end + +def fun_l2_n443(x) + if (x < 1) + fun_l3_n514(x) + else + fun_l3_n943(x) + end +end + +def fun_l2_n444(x) + if (x < 1) + fun_l3_n218(x) + else + fun_l3_n94(x) + end +end + +def fun_l2_n445(x) + if (x < 1) + fun_l3_n0(x) + else + fun_l3_n731(x) + end +end + +def fun_l2_n446(x) + if (x < 1) + fun_l3_n468(x) + else + fun_l3_n197(x) + end +end + +def fun_l2_n447(x) + if (x < 1) + fun_l3_n79(x) + else + fun_l3_n900(x) + end +end + +def fun_l2_n448(x) + if (x < 1) + fun_l3_n706(x) + else + fun_l3_n250(x) + end +end + +def fun_l2_n449(x) + if (x < 1) + fun_l3_n607(x) + else + fun_l3_n514(x) + end +end + +def fun_l2_n450(x) + if (x < 1) + fun_l3_n855(x) + else + fun_l3_n223(x) + end +end + +def fun_l2_n451(x) + if (x < 1) + fun_l3_n824(x) + else + fun_l3_n426(x) + end +end + +def fun_l2_n452(x) + if (x < 1) + fun_l3_n137(x) + else + fun_l3_n555(x) + end +end + +def fun_l2_n453(x) + if (x < 1) + fun_l3_n553(x) + else + fun_l3_n130(x) + end +end + +def fun_l2_n454(x) + if (x < 1) + fun_l3_n350(x) + else + fun_l3_n545(x) + end +end + +def fun_l2_n455(x) + if (x < 1) + fun_l3_n181(x) + else + fun_l3_n950(x) + end +end + +def fun_l2_n456(x) + if (x < 1) + fun_l3_n581(x) + else + fun_l3_n957(x) + end +end + +def fun_l2_n457(x) + if (x < 1) + fun_l3_n688(x) + else + fun_l3_n560(x) + end +end + +def fun_l2_n458(x) + if (x < 1) + fun_l3_n655(x) + else + fun_l3_n323(x) + end +end + +def fun_l2_n459(x) + if (x < 1) + fun_l3_n92(x) + else + fun_l3_n796(x) + end +end + +def fun_l2_n460(x) + if (x < 1) + fun_l3_n68(x) + else + fun_l3_n152(x) + end +end + +def fun_l2_n461(x) + if (x < 1) + fun_l3_n153(x) + else + fun_l3_n929(x) + end +end + +def fun_l2_n462(x) + if (x < 1) + fun_l3_n401(x) + else + fun_l3_n248(x) + end +end + +def fun_l2_n463(x) + if (x < 1) + fun_l3_n4(x) + else + fun_l3_n906(x) + end +end + +def fun_l2_n464(x) + if (x < 1) + fun_l3_n313(x) + else + fun_l3_n911(x) + end +end + +def fun_l2_n465(x) + if (x < 1) + fun_l3_n490(x) + else + fun_l3_n430(x) + end +end + +def fun_l2_n466(x) + if (x < 1) + fun_l3_n537(x) + else + fun_l3_n470(x) + end +end + +def fun_l2_n467(x) + if (x < 1) + fun_l3_n666(x) + else + fun_l3_n695(x) + end +end + +def fun_l2_n468(x) + if (x < 1) + fun_l3_n126(x) + else + fun_l3_n201(x) + end +end + +def fun_l2_n469(x) + if (x < 1) + fun_l3_n111(x) + else + fun_l3_n741(x) + end +end + +def fun_l2_n470(x) + if (x < 1) + fun_l3_n391(x) + else + fun_l3_n83(x) + end +end + +def fun_l2_n471(x) + if (x < 1) + fun_l3_n619(x) + else + fun_l3_n425(x) + end +end + +def fun_l2_n472(x) + if (x < 1) + fun_l3_n637(x) + else + fun_l3_n865(x) + end +end + +def fun_l2_n473(x) + if (x < 1) + fun_l3_n182(x) + else + fun_l3_n350(x) + end +end + +def fun_l2_n474(x) + if (x < 1) + fun_l3_n752(x) + else + fun_l3_n815(x) + end +end + +def fun_l2_n475(x) + if (x < 1) + fun_l3_n184(x) + else + fun_l3_n683(x) + end +end + +def fun_l2_n476(x) + if (x < 1) + fun_l3_n324(x) + else + fun_l3_n232(x) + end +end + +def fun_l2_n477(x) + if (x < 1) + fun_l3_n588(x) + else + fun_l3_n586(x) + end +end + +def fun_l2_n478(x) + if (x < 1) + fun_l3_n320(x) + else + fun_l3_n599(x) + end +end + +def fun_l2_n479(x) + if (x < 1) + fun_l3_n999(x) + else + fun_l3_n678(x) + end +end + +def fun_l2_n480(x) + if (x < 1) + fun_l3_n523(x) + else + fun_l3_n637(x) + end +end + +def fun_l2_n481(x) + if (x < 1) + fun_l3_n291(x) + else + fun_l3_n347(x) + end +end + +def fun_l2_n482(x) + if (x < 1) + fun_l3_n873(x) + else + fun_l3_n435(x) + end +end + +def fun_l2_n483(x) + if (x < 1) + fun_l3_n718(x) + else + fun_l3_n903(x) + end +end + +def fun_l2_n484(x) + if (x < 1) + fun_l3_n188(x) + else + fun_l3_n751(x) + end +end + +def fun_l2_n485(x) + if (x < 1) + fun_l3_n501(x) + else + fun_l3_n235(x) + end +end + +def fun_l2_n486(x) + if (x < 1) + fun_l3_n578(x) + else + fun_l3_n224(x) + end +end + +def fun_l2_n487(x) + if (x < 1) + fun_l3_n757(x) + else + fun_l3_n145(x) + end +end + +def fun_l2_n488(x) + if (x < 1) + fun_l3_n17(x) + else + fun_l3_n727(x) + end +end + +def fun_l2_n489(x) + if (x < 1) + fun_l3_n699(x) + else + fun_l3_n102(x) + end +end + +def fun_l2_n490(x) + if (x < 1) + fun_l3_n518(x) + else + fun_l3_n15(x) + end +end + +def fun_l2_n491(x) + if (x < 1) + fun_l3_n889(x) + else + fun_l3_n798(x) + end +end + +def fun_l2_n492(x) + if (x < 1) + fun_l3_n715(x) + else + fun_l3_n27(x) + end +end + +def fun_l2_n493(x) + if (x < 1) + fun_l3_n237(x) + else + fun_l3_n130(x) + end +end + +def fun_l2_n494(x) + if (x < 1) + fun_l3_n99(x) + else + fun_l3_n223(x) + end +end + +def fun_l2_n495(x) + if (x < 1) + fun_l3_n65(x) + else + fun_l3_n811(x) + end +end + +def fun_l2_n496(x) + if (x < 1) + fun_l3_n457(x) + else + fun_l3_n527(x) + end +end + +def fun_l2_n497(x) + if (x < 1) + fun_l3_n312(x) + else + fun_l3_n902(x) + end +end + +def fun_l2_n498(x) + if (x < 1) + fun_l3_n63(x) + else + fun_l3_n948(x) + end +end + +def fun_l2_n499(x) + if (x < 1) + fun_l3_n652(x) + else + fun_l3_n752(x) + end +end + +def fun_l2_n500(x) + if (x < 1) + fun_l3_n583(x) + else + fun_l3_n427(x) + end +end + +def fun_l2_n501(x) + if (x < 1) + fun_l3_n536(x) + else + fun_l3_n671(x) + end +end + +def fun_l2_n502(x) + if (x < 1) + fun_l3_n122(x) + else + fun_l3_n170(x) + end +end + +def fun_l2_n503(x) + if (x < 1) + fun_l3_n280(x) + else + fun_l3_n390(x) + end +end + +def fun_l2_n504(x) + if (x < 1) + fun_l3_n427(x) + else + fun_l3_n267(x) + end +end + +def fun_l2_n505(x) + if (x < 1) + fun_l3_n241(x) + else + fun_l3_n345(x) + end +end + +def fun_l2_n506(x) + if (x < 1) + fun_l3_n960(x) + else + fun_l3_n537(x) + end +end + +def fun_l2_n507(x) + if (x < 1) + fun_l3_n947(x) + else + fun_l3_n3(x) + end +end + +def fun_l2_n508(x) + if (x < 1) + fun_l3_n974(x) + else + fun_l3_n597(x) + end +end + +def fun_l2_n509(x) + if (x < 1) + fun_l3_n978(x) + else + fun_l3_n70(x) + end +end + +def fun_l2_n510(x) + if (x < 1) + fun_l3_n855(x) + else + fun_l3_n259(x) + end +end + +def fun_l2_n511(x) + if (x < 1) + fun_l3_n987(x) + else + fun_l3_n182(x) + end +end + +def fun_l2_n512(x) + if (x < 1) + fun_l3_n787(x) + else + fun_l3_n656(x) + end +end + +def fun_l2_n513(x) + if (x < 1) + fun_l3_n348(x) + else + fun_l3_n242(x) + end +end + +def fun_l2_n514(x) + if (x < 1) + fun_l3_n530(x) + else + fun_l3_n718(x) + end +end + +def fun_l2_n515(x) + if (x < 1) + fun_l3_n840(x) + else + fun_l3_n302(x) + end +end + +def fun_l2_n516(x) + if (x < 1) + fun_l3_n678(x) + else + fun_l3_n732(x) + end +end + +def fun_l2_n517(x) + if (x < 1) + fun_l3_n160(x) + else + fun_l3_n344(x) + end +end + +def fun_l2_n518(x) + if (x < 1) + fun_l3_n518(x) + else + fun_l3_n830(x) + end +end + +def fun_l2_n519(x) + if (x < 1) + fun_l3_n595(x) + else + fun_l3_n95(x) + end +end + +def fun_l2_n520(x) + if (x < 1) + fun_l3_n939(x) + else + fun_l3_n954(x) + end +end + +def fun_l2_n521(x) + if (x < 1) + fun_l3_n931(x) + else + fun_l3_n686(x) + end +end + +def fun_l2_n522(x) + if (x < 1) + fun_l3_n117(x) + else + fun_l3_n501(x) + end +end + +def fun_l2_n523(x) + if (x < 1) + fun_l3_n727(x) + else + fun_l3_n712(x) + end +end + +def fun_l2_n524(x) + if (x < 1) + fun_l3_n152(x) + else + fun_l3_n453(x) + end +end + +def fun_l2_n525(x) + if (x < 1) + fun_l3_n375(x) + else + fun_l3_n186(x) + end +end + +def fun_l2_n526(x) + if (x < 1) + fun_l3_n835(x) + else + fun_l3_n465(x) + end +end + +def fun_l2_n527(x) + if (x < 1) + fun_l3_n411(x) + else + fun_l3_n208(x) + end +end + +def fun_l2_n528(x) + if (x < 1) + fun_l3_n696(x) + else + fun_l3_n537(x) + end +end + +def fun_l2_n529(x) + if (x < 1) + fun_l3_n606(x) + else + fun_l3_n682(x) + end +end + +def fun_l2_n530(x) + if (x < 1) + fun_l3_n920(x) + else + fun_l3_n592(x) + end +end + +def fun_l2_n531(x) + if (x < 1) + fun_l3_n201(x) + else + fun_l3_n27(x) + end +end + +def fun_l2_n532(x) + if (x < 1) + fun_l3_n643(x) + else + fun_l3_n642(x) + end +end + +def fun_l2_n533(x) + if (x < 1) + fun_l3_n92(x) + else + fun_l3_n576(x) + end +end + +def fun_l2_n534(x) + if (x < 1) + fun_l3_n135(x) + else + fun_l3_n738(x) + end +end + +def fun_l2_n535(x) + if (x < 1) + fun_l3_n706(x) + else + fun_l3_n810(x) + end +end + +def fun_l2_n536(x) + if (x < 1) + fun_l3_n922(x) + else + fun_l3_n456(x) + end +end + +def fun_l2_n537(x) + if (x < 1) + fun_l3_n511(x) + else + fun_l3_n279(x) + end +end + +def fun_l2_n538(x) + if (x < 1) + fun_l3_n541(x) + else + fun_l3_n826(x) + end +end + +def fun_l2_n539(x) + if (x < 1) + fun_l3_n7(x) + else + fun_l3_n362(x) + end +end + +def fun_l2_n540(x) + if (x < 1) + fun_l3_n132(x) + else + fun_l3_n819(x) + end +end + +def fun_l2_n541(x) + if (x < 1) + fun_l3_n600(x) + else + fun_l3_n155(x) + end +end + +def fun_l2_n542(x) + if (x < 1) + fun_l3_n930(x) + else + fun_l3_n827(x) + end +end + +def fun_l2_n543(x) + if (x < 1) + fun_l3_n974(x) + else + fun_l3_n957(x) + end +end + +def fun_l2_n544(x) + if (x < 1) + fun_l3_n912(x) + else + fun_l3_n503(x) + end +end + +def fun_l2_n545(x) + if (x < 1) + fun_l3_n605(x) + else + fun_l3_n966(x) + end +end + +def fun_l2_n546(x) + if (x < 1) + fun_l3_n523(x) + else + fun_l3_n105(x) + end +end + +def fun_l2_n547(x) + if (x < 1) + fun_l3_n352(x) + else + fun_l3_n762(x) + end +end + +def fun_l2_n548(x) + if (x < 1) + fun_l3_n65(x) + else + fun_l3_n714(x) + end +end + +def fun_l2_n549(x) + if (x < 1) + fun_l3_n665(x) + else + fun_l3_n799(x) + end +end + +def fun_l2_n550(x) + if (x < 1) + fun_l3_n624(x) + else + fun_l3_n131(x) + end +end + +def fun_l2_n551(x) + if (x < 1) + fun_l3_n53(x) + else + fun_l3_n377(x) + end +end + +def fun_l2_n552(x) + if (x < 1) + fun_l3_n377(x) + else + fun_l3_n532(x) + end +end + +def fun_l2_n553(x) + if (x < 1) + fun_l3_n302(x) + else + fun_l3_n593(x) + end +end + +def fun_l2_n554(x) + if (x < 1) + fun_l3_n573(x) + else + fun_l3_n727(x) + end +end + +def fun_l2_n555(x) + if (x < 1) + fun_l3_n575(x) + else + fun_l3_n838(x) + end +end + +def fun_l2_n556(x) + if (x < 1) + fun_l3_n92(x) + else + fun_l3_n137(x) + end +end + +def fun_l2_n557(x) + if (x < 1) + fun_l3_n921(x) + else + fun_l3_n683(x) + end +end + +def fun_l2_n558(x) + if (x < 1) + fun_l3_n987(x) + else + fun_l3_n646(x) + end +end + +def fun_l2_n559(x) + if (x < 1) + fun_l3_n574(x) + else + fun_l3_n493(x) + end +end + +def fun_l2_n560(x) + if (x < 1) + fun_l3_n950(x) + else + fun_l3_n139(x) + end +end + +def fun_l2_n561(x) + if (x < 1) + fun_l3_n276(x) + else + fun_l3_n491(x) + end +end + +def fun_l2_n562(x) + if (x < 1) + fun_l3_n226(x) + else + fun_l3_n840(x) + end +end + +def fun_l2_n563(x) + if (x < 1) + fun_l3_n473(x) + else + fun_l3_n907(x) + end +end + +def fun_l2_n564(x) + if (x < 1) + fun_l3_n695(x) + else + fun_l3_n951(x) + end +end + +def fun_l2_n565(x) + if (x < 1) + fun_l3_n415(x) + else + fun_l3_n12(x) + end +end + +def fun_l2_n566(x) + if (x < 1) + fun_l3_n32(x) + else + fun_l3_n759(x) + end +end + +def fun_l2_n567(x) + if (x < 1) + fun_l3_n876(x) + else + fun_l3_n297(x) + end +end + +def fun_l2_n568(x) + if (x < 1) + fun_l3_n520(x) + else + fun_l3_n713(x) + end +end + +def fun_l2_n569(x) + if (x < 1) + fun_l3_n819(x) + else + fun_l3_n505(x) + end +end + +def fun_l2_n570(x) + if (x < 1) + fun_l3_n661(x) + else + fun_l3_n447(x) + end +end + +def fun_l2_n571(x) + if (x < 1) + fun_l3_n538(x) + else + fun_l3_n532(x) + end +end + +def fun_l2_n572(x) + if (x < 1) + fun_l3_n584(x) + else + fun_l3_n304(x) + end +end + +def fun_l2_n573(x) + if (x < 1) + fun_l3_n76(x) + else + fun_l3_n512(x) + end +end + +def fun_l2_n574(x) + if (x < 1) + fun_l3_n22(x) + else + fun_l3_n328(x) + end +end + +def fun_l2_n575(x) + if (x < 1) + fun_l3_n397(x) + else + fun_l3_n640(x) + end +end + +def fun_l2_n576(x) + if (x < 1) + fun_l3_n227(x) + else + fun_l3_n236(x) + end +end + +def fun_l2_n577(x) + if (x < 1) + fun_l3_n743(x) + else + fun_l3_n974(x) + end +end + +def fun_l2_n578(x) + if (x < 1) + fun_l3_n970(x) + else + fun_l3_n229(x) + end +end + +def fun_l2_n579(x) + if (x < 1) + fun_l3_n401(x) + else + fun_l3_n672(x) + end +end + +def fun_l2_n580(x) + if (x < 1) + fun_l3_n837(x) + else + fun_l3_n804(x) + end +end + +def fun_l2_n581(x) + if (x < 1) + fun_l3_n526(x) + else + fun_l3_n763(x) + end +end + +def fun_l2_n582(x) + if (x < 1) + fun_l3_n2(x) + else + fun_l3_n692(x) + end +end + +def fun_l2_n583(x) + if (x < 1) + fun_l3_n561(x) + else + fun_l3_n394(x) + end +end + +def fun_l2_n584(x) + if (x < 1) + fun_l3_n60(x) + else + fun_l3_n682(x) + end +end + +def fun_l2_n585(x) + if (x < 1) + fun_l3_n646(x) + else + fun_l3_n776(x) + end +end + +def fun_l2_n586(x) + if (x < 1) + fun_l3_n466(x) + else + fun_l3_n91(x) + end +end + +def fun_l2_n587(x) + if (x < 1) + fun_l3_n294(x) + else + fun_l3_n813(x) + end +end + +def fun_l2_n588(x) + if (x < 1) + fun_l3_n958(x) + else + fun_l3_n64(x) + end +end + +def fun_l2_n589(x) + if (x < 1) + fun_l3_n703(x) + else + fun_l3_n937(x) + end +end + +def fun_l2_n590(x) + if (x < 1) + fun_l3_n1(x) + else + fun_l3_n970(x) + end +end + +def fun_l2_n591(x) + if (x < 1) + fun_l3_n566(x) + else + fun_l3_n750(x) + end +end + +def fun_l2_n592(x) + if (x < 1) + fun_l3_n905(x) + else + fun_l3_n840(x) + end +end + +def fun_l2_n593(x) + if (x < 1) + fun_l3_n23(x) + else + fun_l3_n862(x) + end +end + +def fun_l2_n594(x) + if (x < 1) + fun_l3_n739(x) + else + fun_l3_n4(x) + end +end + +def fun_l2_n595(x) + if (x < 1) + fun_l3_n818(x) + else + fun_l3_n117(x) + end +end + +def fun_l2_n596(x) + if (x < 1) + fun_l3_n891(x) + else + fun_l3_n599(x) + end +end + +def fun_l2_n597(x) + if (x < 1) + fun_l3_n731(x) + else + fun_l3_n960(x) + end +end + +def fun_l2_n598(x) + if (x < 1) + fun_l3_n323(x) + else + fun_l3_n811(x) + end +end + +def fun_l2_n599(x) + if (x < 1) + fun_l3_n299(x) + else + fun_l3_n188(x) + end +end + +def fun_l2_n600(x) + if (x < 1) + fun_l3_n129(x) + else + fun_l3_n730(x) + end +end + +def fun_l2_n601(x) + if (x < 1) + fun_l3_n412(x) + else + fun_l3_n353(x) + end +end + +def fun_l2_n602(x) + if (x < 1) + fun_l3_n658(x) + else + fun_l3_n774(x) + end +end + +def fun_l2_n603(x) + if (x < 1) + fun_l3_n378(x) + else + fun_l3_n722(x) + end +end + +def fun_l2_n604(x) + if (x < 1) + fun_l3_n482(x) + else + fun_l3_n949(x) + end +end + +def fun_l2_n605(x) + if (x < 1) + fun_l3_n996(x) + else + fun_l3_n169(x) + end +end + +def fun_l2_n606(x) + if (x < 1) + fun_l3_n653(x) + else + fun_l3_n966(x) + end +end + +def fun_l2_n607(x) + if (x < 1) + fun_l3_n179(x) + else + fun_l3_n113(x) + end +end + +def fun_l2_n608(x) + if (x < 1) + fun_l3_n157(x) + else + fun_l3_n692(x) + end +end + +def fun_l2_n609(x) + if (x < 1) + fun_l3_n648(x) + else + fun_l3_n318(x) + end +end + +def fun_l2_n610(x) + if (x < 1) + fun_l3_n979(x) + else + fun_l3_n642(x) + end +end + +def fun_l2_n611(x) + if (x < 1) + fun_l3_n909(x) + else + fun_l3_n986(x) + end +end + +def fun_l2_n612(x) + if (x < 1) + fun_l3_n387(x) + else + fun_l3_n586(x) + end +end + +def fun_l2_n613(x) + if (x < 1) + fun_l3_n99(x) + else + fun_l3_n690(x) + end +end + +def fun_l2_n614(x) + if (x < 1) + fun_l3_n485(x) + else + fun_l3_n733(x) + end +end + +def fun_l2_n615(x) + if (x < 1) + fun_l3_n735(x) + else + fun_l3_n827(x) + end +end + +def fun_l2_n616(x) + if (x < 1) + fun_l3_n496(x) + else + fun_l3_n912(x) + end +end + +def fun_l2_n617(x) + if (x < 1) + fun_l3_n363(x) + else + fun_l3_n845(x) + end +end + +def fun_l2_n618(x) + if (x < 1) + fun_l3_n891(x) + else + fun_l3_n964(x) + end +end + +def fun_l2_n619(x) + if (x < 1) + fun_l3_n266(x) + else + fun_l3_n189(x) + end +end + +def fun_l2_n620(x) + if (x < 1) + fun_l3_n906(x) + else + fun_l3_n218(x) + end +end + +def fun_l2_n621(x) + if (x < 1) + fun_l3_n145(x) + else + fun_l3_n279(x) + end +end + +def fun_l2_n622(x) + if (x < 1) + fun_l3_n797(x) + else + fun_l3_n328(x) + end +end + +def fun_l2_n623(x) + if (x < 1) + fun_l3_n910(x) + else + fun_l3_n250(x) + end +end + +def fun_l2_n624(x) + if (x < 1) + fun_l3_n111(x) + else + fun_l3_n884(x) + end +end + +def fun_l2_n625(x) + if (x < 1) + fun_l3_n852(x) + else + fun_l3_n985(x) + end +end + +def fun_l2_n626(x) + if (x < 1) + fun_l3_n163(x) + else + fun_l3_n885(x) + end +end + +def fun_l2_n627(x) + if (x < 1) + fun_l3_n338(x) + else + fun_l3_n562(x) + end +end + +def fun_l2_n628(x) + if (x < 1) + fun_l3_n300(x) + else + fun_l3_n245(x) + end +end + +def fun_l2_n629(x) + if (x < 1) + fun_l3_n747(x) + else + fun_l3_n123(x) + end +end + +def fun_l2_n630(x) + if (x < 1) + fun_l3_n42(x) + else + fun_l3_n46(x) + end +end + +def fun_l2_n631(x) + if (x < 1) + fun_l3_n256(x) + else + fun_l3_n960(x) + end +end + +def fun_l2_n632(x) + if (x < 1) + fun_l3_n679(x) + else + fun_l3_n393(x) + end +end + +def fun_l2_n633(x) + if (x < 1) + fun_l3_n286(x) + else + fun_l3_n147(x) + end +end + +def fun_l2_n634(x) + if (x < 1) + fun_l3_n62(x) + else + fun_l3_n994(x) + end +end + +def fun_l2_n635(x) + if (x < 1) + fun_l3_n479(x) + else + fun_l3_n502(x) + end +end + +def fun_l2_n636(x) + if (x < 1) + fun_l3_n504(x) + else + fun_l3_n557(x) + end +end + +def fun_l2_n637(x) + if (x < 1) + fun_l3_n716(x) + else + fun_l3_n763(x) + end +end + +def fun_l2_n638(x) + if (x < 1) + fun_l3_n972(x) + else + fun_l3_n391(x) + end +end + +def fun_l2_n639(x) + if (x < 1) + fun_l3_n842(x) + else + fun_l3_n740(x) + end +end + +def fun_l2_n640(x) + if (x < 1) + fun_l3_n854(x) + else + fun_l3_n52(x) + end +end + +def fun_l2_n641(x) + if (x < 1) + fun_l3_n321(x) + else + fun_l3_n109(x) + end +end + +def fun_l2_n642(x) + if (x < 1) + fun_l3_n868(x) + else + fun_l3_n926(x) + end +end + +def fun_l2_n643(x) + if (x < 1) + fun_l3_n864(x) + else + fun_l3_n98(x) + end +end + +def fun_l2_n644(x) + if (x < 1) + fun_l3_n373(x) + else + fun_l3_n105(x) + end +end + +def fun_l2_n645(x) + if (x < 1) + fun_l3_n293(x) + else + fun_l3_n846(x) + end +end + +def fun_l2_n646(x) + if (x < 1) + fun_l3_n24(x) + else + fun_l3_n83(x) + end +end + +def fun_l2_n647(x) + if (x < 1) + fun_l3_n431(x) + else + fun_l3_n772(x) + end +end + +def fun_l2_n648(x) + if (x < 1) + fun_l3_n667(x) + else + fun_l3_n108(x) + end +end + +def fun_l2_n649(x) + if (x < 1) + fun_l3_n93(x) + else + fun_l3_n394(x) + end +end + +def fun_l2_n650(x) + if (x < 1) + fun_l3_n176(x) + else + fun_l3_n315(x) + end +end + +def fun_l2_n651(x) + if (x < 1) + fun_l3_n684(x) + else + fun_l3_n635(x) + end +end + +def fun_l2_n652(x) + if (x < 1) + fun_l3_n554(x) + else + fun_l3_n88(x) + end +end + +def fun_l2_n653(x) + if (x < 1) + fun_l3_n165(x) + else + fun_l3_n962(x) + end +end + +def fun_l2_n654(x) + if (x < 1) + fun_l3_n631(x) + else + fun_l3_n80(x) + end +end + +def fun_l2_n655(x) + if (x < 1) + fun_l3_n529(x) + else + fun_l3_n711(x) + end +end + +def fun_l2_n656(x) + if (x < 1) + fun_l3_n809(x) + else + fun_l3_n44(x) + end +end + +def fun_l2_n657(x) + if (x < 1) + fun_l3_n226(x) + else + fun_l3_n939(x) + end +end + +def fun_l2_n658(x) + if (x < 1) + fun_l3_n355(x) + else + fun_l3_n750(x) + end +end + +def fun_l2_n659(x) + if (x < 1) + fun_l3_n111(x) + else + fun_l3_n883(x) + end +end + +def fun_l2_n660(x) + if (x < 1) + fun_l3_n22(x) + else + fun_l3_n544(x) + end +end + +def fun_l2_n661(x) + if (x < 1) + fun_l3_n334(x) + else + fun_l3_n58(x) + end +end + +def fun_l2_n662(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n647(x) + end +end + +def fun_l2_n663(x) + if (x < 1) + fun_l3_n886(x) + else + fun_l3_n142(x) + end +end + +def fun_l2_n664(x) + if (x < 1) + fun_l3_n713(x) + else + fun_l3_n710(x) + end +end + +def fun_l2_n665(x) + if (x < 1) + fun_l3_n657(x) + else + fun_l3_n24(x) + end +end + +def fun_l2_n666(x) + if (x < 1) + fun_l3_n993(x) + else + fun_l3_n741(x) + end +end + +def fun_l2_n667(x) + if (x < 1) + fun_l3_n265(x) + else + fun_l3_n143(x) + end +end + +def fun_l2_n668(x) + if (x < 1) + fun_l3_n725(x) + else + fun_l3_n272(x) + end +end + +def fun_l2_n669(x) + if (x < 1) + fun_l3_n171(x) + else + fun_l3_n95(x) + end +end + +def fun_l2_n670(x) + if (x < 1) + fun_l3_n409(x) + else + fun_l3_n774(x) + end +end + +def fun_l2_n671(x) + if (x < 1) + fun_l3_n566(x) + else + fun_l3_n251(x) + end +end + +def fun_l2_n672(x) + if (x < 1) + fun_l3_n914(x) + else + fun_l3_n716(x) + end +end + +def fun_l2_n673(x) + if (x < 1) + fun_l3_n889(x) + else + fun_l3_n339(x) + end +end + +def fun_l2_n674(x) + if (x < 1) + fun_l3_n808(x) + else + fun_l3_n858(x) + end +end + +def fun_l2_n675(x) + if (x < 1) + fun_l3_n895(x) + else + fun_l3_n180(x) + end +end + +def fun_l2_n676(x) + if (x < 1) + fun_l3_n674(x) + else + fun_l3_n183(x) + end +end + +def fun_l2_n677(x) + if (x < 1) + fun_l3_n934(x) + else + fun_l3_n292(x) + end +end + +def fun_l2_n678(x) + if (x < 1) + fun_l3_n302(x) + else + fun_l3_n511(x) + end +end + +def fun_l2_n679(x) + if (x < 1) + fun_l3_n847(x) + else + fun_l3_n70(x) + end +end + +def fun_l2_n680(x) + if (x < 1) + fun_l3_n200(x) + else + fun_l3_n436(x) + end +end + +def fun_l2_n681(x) + if (x < 1) + fun_l3_n44(x) + else + fun_l3_n145(x) + end +end + +def fun_l2_n682(x) + if (x < 1) + fun_l3_n929(x) + else + fun_l3_n605(x) + end +end + +def fun_l2_n683(x) + if (x < 1) + fun_l3_n990(x) + else + fun_l3_n641(x) + end +end + +def fun_l2_n684(x) + if (x < 1) + fun_l3_n679(x) + else + fun_l3_n976(x) + end +end + +def fun_l2_n685(x) + if (x < 1) + fun_l3_n405(x) + else + fun_l3_n658(x) + end +end + +def fun_l2_n686(x) + if (x < 1) + fun_l3_n685(x) + else + fun_l3_n379(x) + end +end + +def fun_l2_n687(x) + if (x < 1) + fun_l3_n279(x) + else + fun_l3_n415(x) + end +end + +def fun_l2_n688(x) + if (x < 1) + fun_l3_n234(x) + else + fun_l3_n634(x) + end +end + +def fun_l2_n689(x) + if (x < 1) + fun_l3_n119(x) + else + fun_l3_n234(x) + end +end + +def fun_l2_n690(x) + if (x < 1) + fun_l3_n213(x) + else + fun_l3_n102(x) + end +end + +def fun_l2_n691(x) + if (x < 1) + fun_l3_n744(x) + else + fun_l3_n31(x) + end +end + +def fun_l2_n692(x) + if (x < 1) + fun_l3_n29(x) + else + fun_l3_n238(x) + end +end + +def fun_l2_n693(x) + if (x < 1) + fun_l3_n323(x) + else + fun_l3_n388(x) + end +end + +def fun_l2_n694(x) + if (x < 1) + fun_l3_n70(x) + else + fun_l3_n356(x) + end +end + +def fun_l2_n695(x) + if (x < 1) + fun_l3_n589(x) + else + fun_l3_n949(x) + end +end + +def fun_l2_n696(x) + if (x < 1) + fun_l3_n328(x) + else + fun_l3_n472(x) + end +end + +def fun_l2_n697(x) + if (x < 1) + fun_l3_n705(x) + else + fun_l3_n709(x) + end +end + +def fun_l2_n698(x) + if (x < 1) + fun_l3_n817(x) + else + fun_l3_n927(x) + end +end + +def fun_l2_n699(x) + if (x < 1) + fun_l3_n916(x) + else + fun_l3_n66(x) + end +end + +def fun_l2_n700(x) + if (x < 1) + fun_l3_n461(x) + else + fun_l3_n648(x) + end +end + +def fun_l2_n701(x) + if (x < 1) + fun_l3_n71(x) + else + fun_l3_n218(x) + end +end + +def fun_l2_n702(x) + if (x < 1) + fun_l3_n490(x) + else + fun_l3_n706(x) + end +end + +def fun_l2_n703(x) + if (x < 1) + fun_l3_n480(x) + else + fun_l3_n665(x) + end +end + +def fun_l2_n704(x) + if (x < 1) + fun_l3_n965(x) + else + fun_l3_n394(x) + end +end + +def fun_l2_n705(x) + if (x < 1) + fun_l3_n65(x) + else + fun_l3_n761(x) + end +end + +def fun_l2_n706(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n50(x) + end +end + +def fun_l2_n707(x) + if (x < 1) + fun_l3_n665(x) + else + fun_l3_n589(x) + end +end + +def fun_l2_n708(x) + if (x < 1) + fun_l3_n331(x) + else + fun_l3_n299(x) + end +end + +def fun_l2_n709(x) + if (x < 1) + fun_l3_n656(x) + else + fun_l3_n966(x) + end +end + +def fun_l2_n710(x) + if (x < 1) + fun_l3_n610(x) + else + fun_l3_n767(x) + end +end + +def fun_l2_n711(x) + if (x < 1) + fun_l3_n281(x) + else + fun_l3_n942(x) + end +end + +def fun_l2_n712(x) + if (x < 1) + fun_l3_n474(x) + else + fun_l3_n373(x) + end +end + +def fun_l2_n713(x) + if (x < 1) + fun_l3_n668(x) + else + fun_l3_n881(x) + end +end + +def fun_l2_n714(x) + if (x < 1) + fun_l3_n112(x) + else + fun_l3_n914(x) + end +end + +def fun_l2_n715(x) + if (x < 1) + fun_l3_n276(x) + else + fun_l3_n946(x) + end +end + +def fun_l2_n716(x) + if (x < 1) + fun_l3_n340(x) + else + fun_l3_n474(x) + end +end + +def fun_l2_n717(x) + if (x < 1) + fun_l3_n179(x) + else + fun_l3_n740(x) + end +end + +def fun_l2_n718(x) + if (x < 1) + fun_l3_n830(x) + else + fun_l3_n139(x) + end +end + +def fun_l2_n719(x) + if (x < 1) + fun_l3_n945(x) + else + fun_l3_n98(x) + end +end + +def fun_l2_n720(x) + if (x < 1) + fun_l3_n912(x) + else + fun_l3_n457(x) + end +end + +def fun_l2_n721(x) + if (x < 1) + fun_l3_n4(x) + else + fun_l3_n798(x) + end +end + +def fun_l2_n722(x) + if (x < 1) + fun_l3_n438(x) + else + fun_l3_n677(x) + end +end + +def fun_l2_n723(x) + if (x < 1) + fun_l3_n447(x) + else + fun_l3_n418(x) + end +end + +def fun_l2_n724(x) + if (x < 1) + fun_l3_n936(x) + else + fun_l3_n572(x) + end +end + +def fun_l2_n725(x) + if (x < 1) + fun_l3_n856(x) + else + fun_l3_n429(x) + end +end + +def fun_l2_n726(x) + if (x < 1) + fun_l3_n747(x) + else + fun_l3_n823(x) + end +end + +def fun_l2_n727(x) + if (x < 1) + fun_l3_n908(x) + else + fun_l3_n446(x) + end +end + +def fun_l2_n728(x) + if (x < 1) + fun_l3_n170(x) + else + fun_l3_n546(x) + end +end + +def fun_l2_n729(x) + if (x < 1) + fun_l3_n45(x) + else + fun_l3_n76(x) + end +end + +def fun_l2_n730(x) + if (x < 1) + fun_l3_n688(x) + else + fun_l3_n826(x) + end +end + +def fun_l2_n731(x) + if (x < 1) + fun_l3_n805(x) + else + fun_l3_n88(x) + end +end + +def fun_l2_n732(x) + if (x < 1) + fun_l3_n191(x) + else + fun_l3_n395(x) + end +end + +def fun_l2_n733(x) + if (x < 1) + fun_l3_n161(x) + else + fun_l3_n600(x) + end +end + +def fun_l2_n734(x) + if (x < 1) + fun_l3_n586(x) + else + fun_l3_n770(x) + end +end + +def fun_l2_n735(x) + if (x < 1) + fun_l3_n139(x) + else + fun_l3_n108(x) + end +end + +def fun_l2_n736(x) + if (x < 1) + fun_l3_n719(x) + else + fun_l3_n210(x) + end +end + +def fun_l2_n737(x) + if (x < 1) + fun_l3_n327(x) + else + fun_l3_n138(x) + end +end + +def fun_l2_n738(x) + if (x < 1) + fun_l3_n755(x) + else + fun_l3_n785(x) + end +end + +def fun_l2_n739(x) + if (x < 1) + fun_l3_n499(x) + else + fun_l3_n998(x) + end +end + +def fun_l2_n740(x) + if (x < 1) + fun_l3_n303(x) + else + fun_l3_n646(x) + end +end + +def fun_l2_n741(x) + if (x < 1) + fun_l3_n385(x) + else + fun_l3_n202(x) + end +end + +def fun_l2_n742(x) + if (x < 1) + fun_l3_n290(x) + else + fun_l3_n617(x) + end +end + +def fun_l2_n743(x) + if (x < 1) + fun_l3_n735(x) + else + fun_l3_n322(x) + end +end + +def fun_l2_n744(x) + if (x < 1) + fun_l3_n541(x) + else + fun_l3_n841(x) + end +end + +def fun_l2_n745(x) + if (x < 1) + fun_l3_n124(x) + else + fun_l3_n927(x) + end +end + +def fun_l2_n746(x) + if (x < 1) + fun_l3_n909(x) + else + fun_l3_n981(x) + end +end + +def fun_l2_n747(x) + if (x < 1) + fun_l3_n535(x) + else + fun_l3_n154(x) + end +end + +def fun_l2_n748(x) + if (x < 1) + fun_l3_n804(x) + else + fun_l3_n837(x) + end +end + +def fun_l2_n749(x) + if (x < 1) + fun_l3_n787(x) + else + fun_l3_n890(x) + end +end + +def fun_l2_n750(x) + if (x < 1) + fun_l3_n273(x) + else + fun_l3_n539(x) + end +end + +def fun_l2_n751(x) + if (x < 1) + fun_l3_n397(x) + else + fun_l3_n630(x) + end +end + +def fun_l2_n752(x) + if (x < 1) + fun_l3_n757(x) + else + fun_l3_n294(x) + end +end + +def fun_l2_n753(x) + if (x < 1) + fun_l3_n731(x) + else + fun_l3_n121(x) + end +end + +def fun_l2_n754(x) + if (x < 1) + fun_l3_n391(x) + else + fun_l3_n640(x) + end +end + +def fun_l2_n755(x) + if (x < 1) + fun_l3_n441(x) + else + fun_l3_n731(x) + end +end + +def fun_l2_n756(x) + if (x < 1) + fun_l3_n947(x) + else + fun_l3_n175(x) + end +end + +def fun_l2_n757(x) + if (x < 1) + fun_l3_n294(x) + else + fun_l3_n732(x) + end +end + +def fun_l2_n758(x) + if (x < 1) + fun_l3_n862(x) + else + fun_l3_n490(x) + end +end + +def fun_l2_n759(x) + if (x < 1) + fun_l3_n959(x) + else + fun_l3_n58(x) + end +end + +def fun_l2_n760(x) + if (x < 1) + fun_l3_n245(x) + else + fun_l3_n201(x) + end +end + +def fun_l2_n761(x) + if (x < 1) + fun_l3_n174(x) + else + fun_l3_n763(x) + end +end + +def fun_l2_n762(x) + if (x < 1) + fun_l3_n276(x) + else + fun_l3_n624(x) + end +end + +def fun_l2_n763(x) + if (x < 1) + fun_l3_n130(x) + else + fun_l3_n452(x) + end +end + +def fun_l2_n764(x) + if (x < 1) + fun_l3_n476(x) + else + fun_l3_n519(x) + end +end + +def fun_l2_n765(x) + if (x < 1) + fun_l3_n911(x) + else + fun_l3_n28(x) + end +end + +def fun_l2_n766(x) + if (x < 1) + fun_l3_n290(x) + else + fun_l3_n528(x) + end +end + +def fun_l2_n767(x) + if (x < 1) + fun_l3_n89(x) + else + fun_l3_n284(x) + end +end + +def fun_l2_n768(x) + if (x < 1) + fun_l3_n307(x) + else + fun_l3_n832(x) + end +end + +def fun_l2_n769(x) + if (x < 1) + fun_l3_n204(x) + else + fun_l3_n358(x) + end +end + +def fun_l2_n770(x) + if (x < 1) + fun_l3_n380(x) + else + fun_l3_n938(x) + end +end + +def fun_l2_n771(x) + if (x < 1) + fun_l3_n245(x) + else + fun_l3_n156(x) + end +end + +def fun_l2_n772(x) + if (x < 1) + fun_l3_n77(x) + else + fun_l3_n842(x) + end +end + +def fun_l2_n773(x) + if (x < 1) + fun_l3_n972(x) + else + fun_l3_n143(x) + end +end + +def fun_l2_n774(x) + if (x < 1) + fun_l3_n308(x) + else + fun_l3_n713(x) + end +end + +def fun_l2_n775(x) + if (x < 1) + fun_l3_n714(x) + else + fun_l3_n329(x) + end +end + +def fun_l2_n776(x) + if (x < 1) + fun_l3_n805(x) + else + fun_l3_n141(x) + end +end + +def fun_l2_n777(x) + if (x < 1) + fun_l3_n155(x) + else + fun_l3_n873(x) + end +end + +def fun_l2_n778(x) + if (x < 1) + fun_l3_n551(x) + else + fun_l3_n293(x) + end +end + +def fun_l2_n779(x) + if (x < 1) + fun_l3_n857(x) + else + fun_l3_n551(x) + end +end + +def fun_l2_n780(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n230(x) + end +end + +def fun_l2_n781(x) + if (x < 1) + fun_l3_n958(x) + else + fun_l3_n463(x) + end +end + +def fun_l2_n782(x) + if (x < 1) + fun_l3_n89(x) + else + fun_l3_n514(x) + end +end + +def fun_l2_n783(x) + if (x < 1) + fun_l3_n290(x) + else + fun_l3_n394(x) + end +end + +def fun_l2_n784(x) + if (x < 1) + fun_l3_n582(x) + else + fun_l3_n927(x) + end +end + +def fun_l2_n785(x) + if (x < 1) + fun_l3_n739(x) + else + fun_l3_n822(x) + end +end + +def fun_l2_n786(x) + if (x < 1) + fun_l3_n1(x) + else + fun_l3_n162(x) + end +end + +def fun_l2_n787(x) + if (x < 1) + fun_l3_n88(x) + else + fun_l3_n800(x) + end +end + +def fun_l2_n788(x) + if (x < 1) + fun_l3_n592(x) + else + fun_l3_n235(x) + end +end + +def fun_l2_n789(x) + if (x < 1) + fun_l3_n337(x) + else + fun_l3_n204(x) + end +end + +def fun_l2_n790(x) + if (x < 1) + fun_l3_n481(x) + else + fun_l3_n361(x) + end +end + +def fun_l2_n791(x) + if (x < 1) + fun_l3_n441(x) + else + fun_l3_n883(x) + end +end + +def fun_l2_n792(x) + if (x < 1) + fun_l3_n424(x) + else + fun_l3_n387(x) + end +end + +def fun_l2_n793(x) + if (x < 1) + fun_l3_n961(x) + else + fun_l3_n710(x) + end +end + +def fun_l2_n794(x) + if (x < 1) + fun_l3_n653(x) + else + fun_l3_n869(x) + end +end + +def fun_l2_n795(x) + if (x < 1) + fun_l3_n466(x) + else + fun_l3_n195(x) + end +end + +def fun_l2_n796(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n137(x) + end +end + +def fun_l2_n797(x) + if (x < 1) + fun_l3_n974(x) + else + fun_l3_n911(x) + end +end + +def fun_l2_n798(x) + if (x < 1) + fun_l3_n500(x) + else + fun_l3_n607(x) + end +end + +def fun_l2_n799(x) + if (x < 1) + fun_l3_n964(x) + else + fun_l3_n425(x) + end +end + +def fun_l2_n800(x) + if (x < 1) + fun_l3_n381(x) + else + fun_l3_n618(x) + end +end + +def fun_l2_n801(x) + if (x < 1) + fun_l3_n803(x) + else + fun_l3_n697(x) + end +end + +def fun_l2_n802(x) + if (x < 1) + fun_l3_n372(x) + else + fun_l3_n331(x) + end +end + +def fun_l2_n803(x) + if (x < 1) + fun_l3_n450(x) + else + fun_l3_n707(x) + end +end + +def fun_l2_n804(x) + if (x < 1) + fun_l3_n760(x) + else + fun_l3_n800(x) + end +end + +def fun_l2_n805(x) + if (x < 1) + fun_l3_n695(x) + else + fun_l3_n426(x) + end +end + +def fun_l2_n806(x) + if (x < 1) + fun_l3_n312(x) + else + fun_l3_n517(x) + end +end + +def fun_l2_n807(x) + if (x < 1) + fun_l3_n794(x) + else + fun_l3_n37(x) + end +end + +def fun_l2_n808(x) + if (x < 1) + fun_l3_n591(x) + else + fun_l3_n933(x) + end +end + +def fun_l2_n809(x) + if (x < 1) + fun_l3_n974(x) + else + fun_l3_n69(x) + end +end + +def fun_l2_n810(x) + if (x < 1) + fun_l3_n263(x) + else + fun_l3_n628(x) + end +end + +def fun_l2_n811(x) + if (x < 1) + fun_l3_n647(x) + else + fun_l3_n133(x) + end +end + +def fun_l2_n812(x) + if (x < 1) + fun_l3_n396(x) + else + fun_l3_n872(x) + end +end + +def fun_l2_n813(x) + if (x < 1) + fun_l3_n716(x) + else + fun_l3_n254(x) + end +end + +def fun_l2_n814(x) + if (x < 1) + fun_l3_n181(x) + else + fun_l3_n786(x) + end +end + +def fun_l2_n815(x) + if (x < 1) + fun_l3_n163(x) + else + fun_l3_n175(x) + end +end + +def fun_l2_n816(x) + if (x < 1) + fun_l3_n835(x) + else + fun_l3_n713(x) + end +end + +def fun_l2_n817(x) + if (x < 1) + fun_l3_n54(x) + else + fun_l3_n280(x) + end +end + +def fun_l2_n818(x) + if (x < 1) + fun_l3_n261(x) + else + fun_l3_n958(x) + end +end + +def fun_l2_n819(x) + if (x < 1) + fun_l3_n821(x) + else + fun_l3_n418(x) + end +end + +def fun_l2_n820(x) + if (x < 1) + fun_l3_n541(x) + else + fun_l3_n547(x) + end +end + +def fun_l2_n821(x) + if (x < 1) + fun_l3_n726(x) + else + fun_l3_n386(x) + end +end + +def fun_l2_n822(x) + if (x < 1) + fun_l3_n369(x) + else + fun_l3_n781(x) + end +end + +def fun_l2_n823(x) + if (x < 1) + fun_l3_n392(x) + else + fun_l3_n357(x) + end +end + +def fun_l2_n824(x) + if (x < 1) + fun_l3_n167(x) + else + fun_l3_n764(x) + end +end + +def fun_l2_n825(x) + if (x < 1) + fun_l3_n339(x) + else + fun_l3_n853(x) + end +end + +def fun_l2_n826(x) + if (x < 1) + fun_l3_n613(x) + else + fun_l3_n767(x) + end +end + +def fun_l2_n827(x) + if (x < 1) + fun_l3_n31(x) + else + fun_l3_n35(x) + end +end + +def fun_l2_n828(x) + if (x < 1) + fun_l3_n838(x) + else + fun_l3_n939(x) + end +end + +def fun_l2_n829(x) + if (x < 1) + fun_l3_n344(x) + else + fun_l3_n568(x) + end +end + +def fun_l2_n830(x) + if (x < 1) + fun_l3_n892(x) + else + fun_l3_n564(x) + end +end + +def fun_l2_n831(x) + if (x < 1) + fun_l3_n520(x) + else + fun_l3_n897(x) + end +end + +def fun_l2_n832(x) + if (x < 1) + fun_l3_n986(x) + else + fun_l3_n523(x) + end +end + +def fun_l2_n833(x) + if (x < 1) + fun_l3_n649(x) + else + fun_l3_n776(x) + end +end + +def fun_l2_n834(x) + if (x < 1) + fun_l3_n613(x) + else + fun_l3_n170(x) + end +end + +def fun_l2_n835(x) + if (x < 1) + fun_l3_n657(x) + else + fun_l3_n790(x) + end +end + +def fun_l2_n836(x) + if (x < 1) + fun_l3_n976(x) + else + fun_l3_n785(x) + end +end + +def fun_l2_n837(x) + if (x < 1) + fun_l3_n746(x) + else + fun_l3_n448(x) + end +end + +def fun_l2_n838(x) + if (x < 1) + fun_l3_n911(x) + else + fun_l3_n978(x) + end +end + +def fun_l2_n839(x) + if (x < 1) + fun_l3_n917(x) + else + fun_l3_n484(x) + end +end + +def fun_l2_n840(x) + if (x < 1) + fun_l3_n930(x) + else + fun_l3_n617(x) + end +end + +def fun_l2_n841(x) + if (x < 1) + fun_l3_n753(x) + else + fun_l3_n587(x) + end +end + +def fun_l2_n842(x) + if (x < 1) + fun_l3_n21(x) + else + fun_l3_n256(x) + end +end + +def fun_l2_n843(x) + if (x < 1) + fun_l3_n697(x) + else + fun_l3_n828(x) + end +end + +def fun_l2_n844(x) + if (x < 1) + fun_l3_n59(x) + else + fun_l3_n855(x) + end +end + +def fun_l2_n845(x) + if (x < 1) + fun_l3_n637(x) + else + fun_l3_n667(x) + end +end + +def fun_l2_n846(x) + if (x < 1) + fun_l3_n229(x) + else + fun_l3_n379(x) + end +end + +def fun_l2_n847(x) + if (x < 1) + fun_l3_n908(x) + else + fun_l3_n53(x) + end +end + +def fun_l2_n848(x) + if (x < 1) + fun_l3_n72(x) + else + fun_l3_n882(x) + end +end + +def fun_l2_n849(x) + if (x < 1) + fun_l3_n890(x) + else + fun_l3_n153(x) + end +end + +def fun_l2_n850(x) + if (x < 1) + fun_l3_n301(x) + else + fun_l3_n404(x) + end +end + +def fun_l2_n851(x) + if (x < 1) + fun_l3_n451(x) + else + fun_l3_n365(x) + end +end + +def fun_l2_n852(x) + if (x < 1) + fun_l3_n591(x) + else + fun_l3_n974(x) + end +end + +def fun_l2_n853(x) + if (x < 1) + fun_l3_n534(x) + else + fun_l3_n649(x) + end +end + +def fun_l2_n854(x) + if (x < 1) + fun_l3_n438(x) + else + fun_l3_n853(x) + end +end + +def fun_l2_n855(x) + if (x < 1) + fun_l3_n181(x) + else + fun_l3_n888(x) + end +end + +def fun_l2_n856(x) + if (x < 1) + fun_l3_n856(x) + else + fun_l3_n139(x) + end +end + +def fun_l2_n857(x) + if (x < 1) + fun_l3_n664(x) + else + fun_l3_n659(x) + end +end + +def fun_l2_n858(x) + if (x < 1) + fun_l3_n838(x) + else + fun_l3_n157(x) + end +end + +def fun_l2_n859(x) + if (x < 1) + fun_l3_n542(x) + else + fun_l3_n512(x) + end +end + +def fun_l2_n860(x) + if (x < 1) + fun_l3_n213(x) + else + fun_l3_n954(x) + end +end + +def fun_l2_n861(x) + if (x < 1) + fun_l3_n580(x) + else + fun_l3_n525(x) + end +end + +def fun_l2_n862(x) + if (x < 1) + fun_l3_n649(x) + else + fun_l3_n376(x) + end +end + +def fun_l2_n863(x) + if (x < 1) + fun_l3_n846(x) + else + fun_l3_n643(x) + end +end + +def fun_l2_n864(x) + if (x < 1) + fun_l3_n899(x) + else + fun_l3_n667(x) + end +end + +def fun_l2_n865(x) + if (x < 1) + fun_l3_n326(x) + else + fun_l3_n664(x) + end +end + +def fun_l2_n866(x) + if (x < 1) + fun_l3_n155(x) + else + fun_l3_n369(x) + end +end + +def fun_l2_n867(x) + if (x < 1) + fun_l3_n583(x) + else + fun_l3_n12(x) + end +end + +def fun_l2_n868(x) + if (x < 1) + fun_l3_n637(x) + else + fun_l3_n711(x) + end +end + +def fun_l2_n869(x) + if (x < 1) + fun_l3_n120(x) + else + fun_l3_n449(x) + end +end + +def fun_l2_n870(x) + if (x < 1) + fun_l3_n459(x) + else + fun_l3_n83(x) + end +end + +def fun_l2_n871(x) + if (x < 1) + fun_l3_n298(x) + else + fun_l3_n6(x) + end +end + +def fun_l2_n872(x) + if (x < 1) + fun_l3_n640(x) + else + fun_l3_n319(x) + end +end + +def fun_l2_n873(x) + if (x < 1) + fun_l3_n777(x) + else + fun_l3_n903(x) + end +end + +def fun_l2_n874(x) + if (x < 1) + fun_l3_n16(x) + else + fun_l3_n50(x) + end +end + +def fun_l2_n875(x) + if (x < 1) + fun_l3_n732(x) + else + fun_l3_n711(x) + end +end + +def fun_l2_n876(x) + if (x < 1) + fun_l3_n958(x) + else + fun_l3_n949(x) + end +end + +def fun_l2_n877(x) + if (x < 1) + fun_l3_n992(x) + else + fun_l3_n592(x) + end +end + +def fun_l2_n878(x) + if (x < 1) + fun_l3_n283(x) + else + fun_l3_n178(x) + end +end + +def fun_l2_n879(x) + if (x < 1) + fun_l3_n179(x) + else + fun_l3_n963(x) + end +end + +def fun_l2_n880(x) + if (x < 1) + fun_l3_n345(x) + else + fun_l3_n585(x) + end +end + +def fun_l2_n881(x) + if (x < 1) + fun_l3_n859(x) + else + fun_l3_n204(x) + end +end + +def fun_l2_n882(x) + if (x < 1) + fun_l3_n718(x) + else + fun_l3_n354(x) + end +end + +def fun_l2_n883(x) + if (x < 1) + fun_l3_n58(x) + else + fun_l3_n34(x) + end +end + +def fun_l2_n884(x) + if (x < 1) + fun_l3_n442(x) + else + fun_l3_n853(x) + end +end + +def fun_l2_n885(x) + if (x < 1) + fun_l3_n37(x) + else + fun_l3_n665(x) + end +end + +def fun_l2_n886(x) + if (x < 1) + fun_l3_n468(x) + else + fun_l3_n283(x) + end +end + +def fun_l2_n887(x) + if (x < 1) + fun_l3_n674(x) + else + fun_l3_n940(x) + end +end + +def fun_l2_n888(x) + if (x < 1) + fun_l3_n556(x) + else + fun_l3_n191(x) + end +end + +def fun_l2_n889(x) + if (x < 1) + fun_l3_n451(x) + else + fun_l3_n33(x) + end +end + +def fun_l2_n890(x) + if (x < 1) + fun_l3_n724(x) + else + fun_l3_n355(x) + end +end + +def fun_l2_n891(x) + if (x < 1) + fun_l3_n811(x) + else + fun_l3_n969(x) + end +end + +def fun_l2_n892(x) + if (x < 1) + fun_l3_n122(x) + else + fun_l3_n956(x) + end +end + +def fun_l2_n893(x) + if (x < 1) + fun_l3_n416(x) + else + fun_l3_n373(x) + end +end + +def fun_l2_n894(x) + if (x < 1) + fun_l3_n990(x) + else + fun_l3_n148(x) + end +end + +def fun_l2_n895(x) + if (x < 1) + fun_l3_n52(x) + else + fun_l3_n605(x) + end +end + +def fun_l2_n896(x) + if (x < 1) + fun_l3_n523(x) + else + fun_l3_n929(x) + end +end + +def fun_l2_n897(x) + if (x < 1) + fun_l3_n631(x) + else + fun_l3_n167(x) + end +end + +def fun_l2_n898(x) + if (x < 1) + fun_l3_n366(x) + else + fun_l3_n666(x) + end +end + +def fun_l2_n899(x) + if (x < 1) + fun_l3_n758(x) + else + fun_l3_n441(x) + end +end + +def fun_l2_n900(x) + if (x < 1) + fun_l3_n561(x) + else + fun_l3_n766(x) + end +end + +def fun_l2_n901(x) + if (x < 1) + fun_l3_n323(x) + else + fun_l3_n348(x) + end +end + +def fun_l2_n902(x) + if (x < 1) + fun_l3_n455(x) + else + fun_l3_n78(x) + end +end + +def fun_l2_n903(x) + if (x < 1) + fun_l3_n373(x) + else + fun_l3_n646(x) + end +end + +def fun_l2_n904(x) + if (x < 1) + fun_l3_n595(x) + else + fun_l3_n742(x) + end +end + +def fun_l2_n905(x) + if (x < 1) + fun_l3_n102(x) + else + fun_l3_n140(x) + end +end + +def fun_l2_n906(x) + if (x < 1) + fun_l3_n458(x) + else + fun_l3_n528(x) + end +end + +def fun_l2_n907(x) + if (x < 1) + fun_l3_n970(x) + else + fun_l3_n841(x) + end +end + +def fun_l2_n908(x) + if (x < 1) + fun_l3_n97(x) + else + fun_l3_n250(x) + end +end + +def fun_l2_n909(x) + if (x < 1) + fun_l3_n381(x) + else + fun_l3_n44(x) + end +end + +def fun_l2_n910(x) + if (x < 1) + fun_l3_n812(x) + else + fun_l3_n225(x) + end +end + +def fun_l2_n911(x) + if (x < 1) + fun_l3_n849(x) + else + fun_l3_n683(x) + end +end + +def fun_l2_n912(x) + if (x < 1) + fun_l3_n958(x) + else + fun_l3_n590(x) + end +end + +def fun_l2_n913(x) + if (x < 1) + fun_l3_n858(x) + else + fun_l3_n140(x) + end +end + +def fun_l2_n914(x) + if (x < 1) + fun_l3_n997(x) + else + fun_l3_n959(x) + end +end + +def fun_l2_n915(x) + if (x < 1) + fun_l3_n184(x) + else + fun_l3_n910(x) + end +end + +def fun_l2_n916(x) + if (x < 1) + fun_l3_n369(x) + else + fun_l3_n180(x) + end +end + +def fun_l2_n917(x) + if (x < 1) + fun_l3_n537(x) + else + fun_l3_n927(x) + end +end + +def fun_l2_n918(x) + if (x < 1) + fun_l3_n739(x) + else + fun_l3_n222(x) + end +end + +def fun_l2_n919(x) + if (x < 1) + fun_l3_n640(x) + else + fun_l3_n406(x) + end +end + +def fun_l2_n920(x) + if (x < 1) + fun_l3_n371(x) + else + fun_l3_n976(x) + end +end + +def fun_l2_n921(x) + if (x < 1) + fun_l3_n262(x) + else + fun_l3_n532(x) + end +end + +def fun_l2_n922(x) + if (x < 1) + fun_l3_n772(x) + else + fun_l3_n368(x) + end +end + +def fun_l2_n923(x) + if (x < 1) + fun_l3_n935(x) + else + fun_l3_n109(x) + end +end + +def fun_l2_n924(x) + if (x < 1) + fun_l3_n982(x) + else + fun_l3_n643(x) + end +end + +def fun_l2_n925(x) + if (x < 1) + fun_l3_n849(x) + else + fun_l3_n266(x) + end +end + +def fun_l2_n926(x) + if (x < 1) + fun_l3_n977(x) + else + fun_l3_n803(x) + end +end + +def fun_l2_n927(x) + if (x < 1) + fun_l3_n706(x) + else + fun_l3_n441(x) + end +end + +def fun_l2_n928(x) + if (x < 1) + fun_l3_n781(x) + else + fun_l3_n374(x) + end +end + +def fun_l2_n929(x) + if (x < 1) + fun_l3_n122(x) + else + fun_l3_n851(x) + end +end + +def fun_l2_n930(x) + if (x < 1) + fun_l3_n821(x) + else + fun_l3_n904(x) + end +end + +def fun_l2_n931(x) + if (x < 1) + fun_l3_n379(x) + else + fun_l3_n211(x) + end +end + +def fun_l2_n932(x) + if (x < 1) + fun_l3_n572(x) + else + fun_l3_n169(x) + end +end + +def fun_l2_n933(x) + if (x < 1) + fun_l3_n620(x) + else + fun_l3_n703(x) + end +end + +def fun_l2_n934(x) + if (x < 1) + fun_l3_n238(x) + else + fun_l3_n220(x) + end +end + +def fun_l2_n935(x) + if (x < 1) + fun_l3_n652(x) + else + fun_l3_n822(x) + end +end + +def fun_l2_n936(x) + if (x < 1) + fun_l3_n818(x) + else + fun_l3_n384(x) + end +end + +def fun_l2_n937(x) + if (x < 1) + fun_l3_n560(x) + else + fun_l3_n875(x) + end +end + +def fun_l2_n938(x) + if (x < 1) + fun_l3_n417(x) + else + fun_l3_n900(x) + end +end + +def fun_l2_n939(x) + if (x < 1) + fun_l3_n740(x) + else + fun_l3_n431(x) + end +end + +def fun_l2_n940(x) + if (x < 1) + fun_l3_n1(x) + else + fun_l3_n147(x) + end +end + +def fun_l2_n941(x) + if (x < 1) + fun_l3_n64(x) + else + fun_l3_n317(x) + end +end + +def fun_l2_n942(x) + if (x < 1) + fun_l3_n347(x) + else + fun_l3_n778(x) + end +end + +def fun_l2_n943(x) + if (x < 1) + fun_l3_n819(x) + else + fun_l3_n446(x) + end +end + +def fun_l2_n944(x) + if (x < 1) + fun_l3_n492(x) + else + fun_l3_n381(x) + end +end + +def fun_l2_n945(x) + if (x < 1) + fun_l3_n594(x) + else + fun_l3_n413(x) + end +end + +def fun_l2_n946(x) + if (x < 1) + fun_l3_n580(x) + else + fun_l3_n838(x) + end +end + +def fun_l2_n947(x) + if (x < 1) + fun_l3_n880(x) + else + fun_l3_n768(x) + end +end + +def fun_l2_n948(x) + if (x < 1) + fun_l3_n9(x) + else + fun_l3_n888(x) + end +end + +def fun_l2_n949(x) + if (x < 1) + fun_l3_n365(x) + else + fun_l3_n322(x) + end +end + +def fun_l2_n950(x) + if (x < 1) + fun_l3_n283(x) + else + fun_l3_n921(x) + end +end + +def fun_l2_n951(x) + if (x < 1) + fun_l3_n740(x) + else + fun_l3_n336(x) + end +end + +def fun_l2_n952(x) + if (x < 1) + fun_l3_n827(x) + else + fun_l3_n683(x) + end +end + +def fun_l2_n953(x) + if (x < 1) + fun_l3_n289(x) + else + fun_l3_n915(x) + end +end + +def fun_l2_n954(x) + if (x < 1) + fun_l3_n234(x) + else + fun_l3_n198(x) + end +end + +def fun_l2_n955(x) + if (x < 1) + fun_l3_n364(x) + else + fun_l3_n152(x) + end +end + +def fun_l2_n956(x) + if (x < 1) + fun_l3_n370(x) + else + fun_l3_n786(x) + end +end + +def fun_l2_n957(x) + if (x < 1) + fun_l3_n672(x) + else + fun_l3_n375(x) + end +end + +def fun_l2_n958(x) + if (x < 1) + fun_l3_n423(x) + else + fun_l3_n448(x) + end +end + +def fun_l2_n959(x) + if (x < 1) + fun_l3_n887(x) + else + fun_l3_n33(x) + end +end + +def fun_l2_n960(x) + if (x < 1) + fun_l3_n280(x) + else + fun_l3_n334(x) + end +end + +def fun_l2_n961(x) + if (x < 1) + fun_l3_n535(x) + else + fun_l3_n524(x) + end +end + +def fun_l2_n962(x) + if (x < 1) + fun_l3_n689(x) + else + fun_l3_n426(x) + end +end + +def fun_l2_n963(x) + if (x < 1) + fun_l3_n235(x) + else + fun_l3_n286(x) + end +end + +def fun_l2_n964(x) + if (x < 1) + fun_l3_n116(x) + else + fun_l3_n308(x) + end +end + +def fun_l2_n965(x) + if (x < 1) + fun_l3_n174(x) + else + fun_l3_n823(x) + end +end + +def fun_l2_n966(x) + if (x < 1) + fun_l3_n792(x) + else + fun_l3_n29(x) + end +end + +def fun_l2_n967(x) + if (x < 1) + fun_l3_n755(x) + else + fun_l3_n689(x) + end +end + +def fun_l2_n968(x) + if (x < 1) + fun_l3_n167(x) + else + fun_l3_n287(x) + end +end + +def fun_l2_n969(x) + if (x < 1) + fun_l3_n836(x) + else + fun_l3_n892(x) + end +end + +def fun_l2_n970(x) + if (x < 1) + fun_l3_n201(x) + else + fun_l3_n677(x) + end +end + +def fun_l2_n971(x) + if (x < 1) + fun_l3_n990(x) + else + fun_l3_n251(x) + end +end + +def fun_l2_n972(x) + if (x < 1) + fun_l3_n500(x) + else + fun_l3_n686(x) + end +end + +def fun_l2_n973(x) + if (x < 1) + fun_l3_n969(x) + else + fun_l3_n819(x) + end +end + +def fun_l2_n974(x) + if (x < 1) + fun_l3_n87(x) + else + fun_l3_n120(x) + end +end + +def fun_l2_n975(x) + if (x < 1) + fun_l3_n701(x) + else + fun_l3_n569(x) + end +end + +def fun_l2_n976(x) + if (x < 1) + fun_l3_n128(x) + else + fun_l3_n310(x) + end +end + +def fun_l2_n977(x) + if (x < 1) + fun_l3_n690(x) + else + fun_l3_n5(x) + end +end + +def fun_l2_n978(x) + if (x < 1) + fun_l3_n432(x) + else + fun_l3_n964(x) + end +end + +def fun_l2_n979(x) + if (x < 1) + fun_l3_n198(x) + else + fun_l3_n161(x) + end +end + +def fun_l2_n980(x) + if (x < 1) + fun_l3_n415(x) + else + fun_l3_n768(x) + end +end + +def fun_l2_n981(x) + if (x < 1) + fun_l3_n635(x) + else + fun_l3_n569(x) + end +end + +def fun_l2_n982(x) + if (x < 1) + fun_l3_n326(x) + else + fun_l3_n338(x) + end +end + +def fun_l2_n983(x) + if (x < 1) + fun_l3_n243(x) + else + fun_l3_n48(x) + end +end + +def fun_l2_n984(x) + if (x < 1) + fun_l3_n204(x) + else + fun_l3_n141(x) + end +end + +def fun_l2_n985(x) + if (x < 1) + fun_l3_n805(x) + else + fun_l3_n577(x) + end +end + +def fun_l2_n986(x) + if (x < 1) + fun_l3_n237(x) + else + fun_l3_n833(x) + end +end + +def fun_l2_n987(x) + if (x < 1) + fun_l3_n643(x) + else + fun_l3_n629(x) + end +end + +def fun_l2_n988(x) + if (x < 1) + fun_l3_n911(x) + else + fun_l3_n712(x) + end +end + +def fun_l2_n989(x) + if (x < 1) + fun_l3_n936(x) + else + fun_l3_n300(x) + end +end + +def fun_l2_n990(x) + if (x < 1) + fun_l3_n561(x) + else + fun_l3_n281(x) + end +end + +def fun_l2_n991(x) + if (x < 1) + fun_l3_n226(x) + else + fun_l3_n203(x) + end +end + +def fun_l2_n992(x) + if (x < 1) + fun_l3_n727(x) + else + fun_l3_n437(x) + end +end + +def fun_l2_n993(x) + if (x < 1) + fun_l3_n608(x) + else + fun_l3_n169(x) + end +end + +def fun_l2_n994(x) + if (x < 1) + fun_l3_n30(x) + else + fun_l3_n980(x) + end +end + +def fun_l2_n995(x) + if (x < 1) + fun_l3_n652(x) + else + fun_l3_n122(x) + end +end + +def fun_l2_n996(x) + if (x < 1) + fun_l3_n334(x) + else + fun_l3_n668(x) + end +end + +def fun_l2_n997(x) + if (x < 1) + fun_l3_n241(x) + else + fun_l3_n515(x) + end +end + +def fun_l2_n998(x) + if (x < 1) + fun_l3_n665(x) + else + fun_l3_n54(x) + end +end + +def fun_l2_n999(x) + if (x < 1) + fun_l3_n568(x) + else + fun_l3_n652(x) + end +end + +def fun_l3_n0(x) + if (x < 1) + fun_l4_n169(x) + else + fun_l4_n923(x) + end +end + +def fun_l3_n1(x) + if (x < 1) + fun_l4_n214(x) + else + fun_l4_n506(x) + end +end + +def fun_l3_n2(x) + if (x < 1) + fun_l4_n513(x) + else + fun_l4_n409(x) + end +end + +def fun_l3_n3(x) + if (x < 1) + fun_l4_n133(x) + else + fun_l4_n293(x) + end +end + +def fun_l3_n4(x) + if (x < 1) + fun_l4_n550(x) + else + fun_l4_n95(x) + end +end + +def fun_l3_n5(x) + if (x < 1) + fun_l4_n13(x) + else + fun_l4_n508(x) + end +end + +def fun_l3_n6(x) + if (x < 1) + fun_l4_n607(x) + else + fun_l4_n140(x) + end +end + +def fun_l3_n7(x) + if (x < 1) + fun_l4_n65(x) + else + fun_l4_n90(x) + end +end + +def fun_l3_n8(x) + if (x < 1) + fun_l4_n516(x) + else + fun_l4_n445(x) + end +end + +def fun_l3_n9(x) + if (x < 1) + fun_l4_n713(x) + else + fun_l4_n487(x) + end +end + +def fun_l3_n10(x) + if (x < 1) + fun_l4_n16(x) + else + fun_l4_n547(x) + end +end + +def fun_l3_n11(x) + if (x < 1) + fun_l4_n561(x) + else + fun_l4_n530(x) + end +end + +def fun_l3_n12(x) + if (x < 1) + fun_l4_n866(x) + else + fun_l4_n187(x) + end +end + +def fun_l3_n13(x) + if (x < 1) + fun_l4_n8(x) + else + fun_l4_n458(x) + end +end + +def fun_l3_n14(x) + if (x < 1) + fun_l4_n627(x) + else + fun_l4_n122(x) + end +end + +def fun_l3_n15(x) + if (x < 1) + fun_l4_n988(x) + else + fun_l4_n4(x) + end +end + +def fun_l3_n16(x) + if (x < 1) + fun_l4_n654(x) + else + fun_l4_n863(x) + end +end + +def fun_l3_n17(x) + if (x < 1) + fun_l4_n112(x) + else + fun_l4_n223(x) + end +end + +def fun_l3_n18(x) + if (x < 1) + fun_l4_n808(x) + else + fun_l4_n161(x) + end +end + +def fun_l3_n19(x) + if (x < 1) + fun_l4_n265(x) + else + fun_l4_n860(x) + end +end + +def fun_l3_n20(x) + if (x < 1) + fun_l4_n60(x) + else + fun_l4_n943(x) + end +end + +def fun_l3_n21(x) + if (x < 1) + fun_l4_n707(x) + else + fun_l4_n990(x) + end +end + +def fun_l3_n22(x) + if (x < 1) + fun_l4_n774(x) + else + fun_l4_n686(x) + end +end + +def fun_l3_n23(x) + if (x < 1) + fun_l4_n552(x) + else + fun_l4_n935(x) + end +end + +def fun_l3_n24(x) + if (x < 1) + fun_l4_n752(x) + else + fun_l4_n279(x) + end +end + +def fun_l3_n25(x) + if (x < 1) + fun_l4_n325(x) + else + fun_l4_n440(x) + end +end + +def fun_l3_n26(x) + if (x < 1) + fun_l4_n330(x) + else + fun_l4_n233(x) + end +end + +def fun_l3_n27(x) + if (x < 1) + fun_l4_n112(x) + else + fun_l4_n399(x) + end +end + +def fun_l3_n28(x) + if (x < 1) + fun_l4_n420(x) + else + fun_l4_n570(x) + end +end + +def fun_l3_n29(x) + if (x < 1) + fun_l4_n515(x) + else + fun_l4_n485(x) + end +end + +def fun_l3_n30(x) + if (x < 1) + fun_l4_n694(x) + else + fun_l4_n279(x) + end +end + +def fun_l3_n31(x) + if (x < 1) + fun_l4_n683(x) + else + fun_l4_n396(x) + end +end + +def fun_l3_n32(x) + if (x < 1) + fun_l4_n997(x) + else + fun_l4_n978(x) + end +end + +def fun_l3_n33(x) + if (x < 1) + fun_l4_n260(x) + else + fun_l4_n895(x) + end +end + +def fun_l3_n34(x) + if (x < 1) + fun_l4_n510(x) + else + fun_l4_n147(x) + end +end + +def fun_l3_n35(x) + if (x < 1) + fun_l4_n415(x) + else + fun_l4_n590(x) + end +end + +def fun_l3_n36(x) + if (x < 1) + fun_l4_n164(x) + else + fun_l4_n990(x) + end +end + +def fun_l3_n37(x) + if (x < 1) + fun_l4_n744(x) + else + fun_l4_n981(x) + end +end + +def fun_l3_n38(x) + if (x < 1) + fun_l4_n243(x) + else + fun_l4_n385(x) + end +end + +def fun_l3_n39(x) + if (x < 1) + fun_l4_n874(x) + else + fun_l4_n941(x) + end +end + +def fun_l3_n40(x) + if (x < 1) + fun_l4_n39(x) + else + fun_l4_n115(x) + end +end + +def fun_l3_n41(x) + if (x < 1) + fun_l4_n829(x) + else + fun_l4_n991(x) + end +end + +def fun_l3_n42(x) + if (x < 1) + fun_l4_n234(x) + else + fun_l4_n359(x) + end +end + +def fun_l3_n43(x) + if (x < 1) + fun_l4_n481(x) + else + fun_l4_n368(x) + end +end + +def fun_l3_n44(x) + if (x < 1) + fun_l4_n969(x) + else + fun_l4_n716(x) + end +end + +def fun_l3_n45(x) + if (x < 1) + fun_l4_n858(x) + else + fun_l4_n446(x) + end +end + +def fun_l3_n46(x) + if (x < 1) + fun_l4_n786(x) + else + fun_l4_n418(x) + end +end + +def fun_l3_n47(x) + if (x < 1) + fun_l4_n261(x) + else + fun_l4_n346(x) + end +end + +def fun_l3_n48(x) + if (x < 1) + fun_l4_n422(x) + else + fun_l4_n710(x) + end +end + +def fun_l3_n49(x) + if (x < 1) + fun_l4_n533(x) + else + fun_l4_n599(x) + end +end + +def fun_l3_n50(x) + if (x < 1) + fun_l4_n922(x) + else + fun_l4_n90(x) + end +end + +def fun_l3_n51(x) + if (x < 1) + fun_l4_n718(x) + else + fun_l4_n854(x) + end +end + +def fun_l3_n52(x) + if (x < 1) + fun_l4_n993(x) + else + fun_l4_n996(x) + end +end + +def fun_l3_n53(x) + if (x < 1) + fun_l4_n628(x) + else + fun_l4_n589(x) + end +end + +def fun_l3_n54(x) + if (x < 1) + fun_l4_n735(x) + else + fun_l4_n258(x) + end +end + +def fun_l3_n55(x) + if (x < 1) + fun_l4_n794(x) + else + fun_l4_n559(x) + end +end + +def fun_l3_n56(x) + if (x < 1) + fun_l4_n771(x) + else + fun_l4_n812(x) + end +end + +def fun_l3_n57(x) + if (x < 1) + fun_l4_n106(x) + else + fun_l4_n144(x) + end +end + +def fun_l3_n58(x) + if (x < 1) + fun_l4_n2(x) + else + fun_l4_n49(x) + end +end + +def fun_l3_n59(x) + if (x < 1) + fun_l4_n540(x) + else + fun_l4_n164(x) + end +end + +def fun_l3_n60(x) + if (x < 1) + fun_l4_n638(x) + else + fun_l4_n984(x) + end +end + +def fun_l3_n61(x) + if (x < 1) + fun_l4_n144(x) + else + fun_l4_n236(x) + end +end + +def fun_l3_n62(x) + if (x < 1) + fun_l4_n345(x) + else + fun_l4_n65(x) + end +end + +def fun_l3_n63(x) + if (x < 1) + fun_l4_n112(x) + else + fun_l4_n216(x) + end +end + +def fun_l3_n64(x) + if (x < 1) + fun_l4_n213(x) + else + fun_l4_n370(x) + end +end + +def fun_l3_n65(x) + if (x < 1) + fun_l4_n845(x) + else + fun_l4_n672(x) + end +end + +def fun_l3_n66(x) + if (x < 1) + fun_l4_n951(x) + else + fun_l4_n415(x) + end +end + +def fun_l3_n67(x) + if (x < 1) + fun_l4_n997(x) + else + fun_l4_n760(x) + end +end + +def fun_l3_n68(x) + if (x < 1) + fun_l4_n595(x) + else + fun_l4_n517(x) + end +end + +def fun_l3_n69(x) + if (x < 1) + fun_l4_n776(x) + else + fun_l4_n550(x) + end +end + +def fun_l3_n70(x) + if (x < 1) + fun_l4_n360(x) + else + fun_l4_n836(x) + end +end + +def fun_l3_n71(x) + if (x < 1) + fun_l4_n214(x) + else + fun_l4_n532(x) + end +end + +def fun_l3_n72(x) + if (x < 1) + fun_l4_n138(x) + else + fun_l4_n881(x) + end +end + +def fun_l3_n73(x) + if (x < 1) + fun_l4_n793(x) + else + fun_l4_n866(x) + end +end + +def fun_l3_n74(x) + if (x < 1) + fun_l4_n883(x) + else + fun_l4_n730(x) + end +end + +def fun_l3_n75(x) + if (x < 1) + fun_l4_n525(x) + else + fun_l4_n188(x) + end +end + +def fun_l3_n76(x) + if (x < 1) + fun_l4_n528(x) + else + fun_l4_n723(x) + end +end + +def fun_l3_n77(x) + if (x < 1) + fun_l4_n954(x) + else + fun_l4_n581(x) + end +end + +def fun_l3_n78(x) + if (x < 1) + fun_l4_n614(x) + else + fun_l4_n941(x) + end +end + +def fun_l3_n79(x) + if (x < 1) + fun_l4_n396(x) + else + fun_l4_n539(x) + end +end + +def fun_l3_n80(x) + if (x < 1) + fun_l4_n1(x) + else + fun_l4_n708(x) + end +end + +def fun_l3_n81(x) + if (x < 1) + fun_l4_n626(x) + else + fun_l4_n418(x) + end +end + +def fun_l3_n82(x) + if (x < 1) + fun_l4_n5(x) + else + fun_l4_n108(x) + end +end + +def fun_l3_n83(x) + if (x < 1) + fun_l4_n683(x) + else + fun_l4_n679(x) + end +end + +def fun_l3_n84(x) + if (x < 1) + fun_l4_n613(x) + else + fun_l4_n596(x) + end +end + +def fun_l3_n85(x) + if (x < 1) + fun_l4_n490(x) + else + fun_l4_n178(x) + end +end + +def fun_l3_n86(x) + if (x < 1) + fun_l4_n286(x) + else + fun_l4_n724(x) + end +end + +def fun_l3_n87(x) + if (x < 1) + fun_l4_n989(x) + else + fun_l4_n711(x) + end +end + +def fun_l3_n88(x) + if (x < 1) + fun_l4_n422(x) + else + fun_l4_n259(x) + end +end + +def fun_l3_n89(x) + if (x < 1) + fun_l4_n938(x) + else + fun_l4_n123(x) + end +end + +def fun_l3_n90(x) + if (x < 1) + fun_l4_n589(x) + else + fun_l4_n231(x) + end +end + +def fun_l3_n91(x) + if (x < 1) + fun_l4_n484(x) + else + fun_l4_n439(x) + end +end + +def fun_l3_n92(x) + if (x < 1) + fun_l4_n469(x) + else + fun_l4_n737(x) + end +end + +def fun_l3_n93(x) + if (x < 1) + fun_l4_n93(x) + else + fun_l4_n907(x) + end +end + +def fun_l3_n94(x) + if (x < 1) + fun_l4_n468(x) + else + fun_l4_n219(x) + end +end + +def fun_l3_n95(x) + if (x < 1) + fun_l4_n409(x) + else + fun_l4_n921(x) + end +end + +def fun_l3_n96(x) + if (x < 1) + fun_l4_n952(x) + else + fun_l4_n167(x) + end +end + +def fun_l3_n97(x) + if (x < 1) + fun_l4_n177(x) + else + fun_l4_n462(x) + end +end + +def fun_l3_n98(x) + if (x < 1) + fun_l4_n351(x) + else + fun_l4_n89(x) + end +end + +def fun_l3_n99(x) + if (x < 1) + fun_l4_n869(x) + else + fun_l4_n502(x) + end +end + +def fun_l3_n100(x) + if (x < 1) + fun_l4_n985(x) + else + fun_l4_n297(x) + end +end + +def fun_l3_n101(x) + if (x < 1) + fun_l4_n48(x) + else + fun_l4_n895(x) + end +end + +def fun_l3_n102(x) + if (x < 1) + fun_l4_n92(x) + else + fun_l4_n36(x) + end +end + +def fun_l3_n103(x) + if (x < 1) + fun_l4_n610(x) + else + fun_l4_n616(x) + end +end + +def fun_l3_n104(x) + if (x < 1) + fun_l4_n472(x) + else + fun_l4_n689(x) + end +end + +def fun_l3_n105(x) + if (x < 1) + fun_l4_n75(x) + else + fun_l4_n161(x) + end +end + +def fun_l3_n106(x) + if (x < 1) + fun_l4_n300(x) + else + fun_l4_n767(x) + end +end + +def fun_l3_n107(x) + if (x < 1) + fun_l4_n707(x) + else + fun_l4_n229(x) + end +end + +def fun_l3_n108(x) + if (x < 1) + fun_l4_n761(x) + else + fun_l4_n97(x) + end +end + +def fun_l3_n109(x) + if (x < 1) + fun_l4_n734(x) + else + fun_l4_n290(x) + end +end + +def fun_l3_n110(x) + if (x < 1) + fun_l4_n819(x) + else + fun_l4_n567(x) + end +end + +def fun_l3_n111(x) + if (x < 1) + fun_l4_n904(x) + else + fun_l4_n322(x) + end +end + +def fun_l3_n112(x) + if (x < 1) + fun_l4_n907(x) + else + fun_l4_n667(x) + end +end + +def fun_l3_n113(x) + if (x < 1) + fun_l4_n473(x) + else + fun_l4_n620(x) + end +end + +def fun_l3_n114(x) + if (x < 1) + fun_l4_n278(x) + else + fun_l4_n998(x) + end +end + +def fun_l3_n115(x) + if (x < 1) + fun_l4_n185(x) + else + fun_l4_n962(x) + end +end + +def fun_l3_n116(x) + if (x < 1) + fun_l4_n989(x) + else + fun_l4_n993(x) + end +end + +def fun_l3_n117(x) + if (x < 1) + fun_l4_n140(x) + else + fun_l4_n456(x) + end +end + +def fun_l3_n118(x) + if (x < 1) + fun_l4_n920(x) + else + fun_l4_n701(x) + end +end + +def fun_l3_n119(x) + if (x < 1) + fun_l4_n263(x) + else + fun_l4_n837(x) + end +end + +def fun_l3_n120(x) + if (x < 1) + fun_l4_n54(x) + else + fun_l4_n964(x) + end +end + +def fun_l3_n121(x) + if (x < 1) + fun_l4_n540(x) + else + fun_l4_n543(x) + end +end + +def fun_l3_n122(x) + if (x < 1) + fun_l4_n51(x) + else + fun_l4_n453(x) + end +end + +def fun_l3_n123(x) + if (x < 1) + fun_l4_n726(x) + else + fun_l4_n785(x) + end +end + +def fun_l3_n124(x) + if (x < 1) + fun_l4_n932(x) + else + fun_l4_n583(x) + end +end + +def fun_l3_n125(x) + if (x < 1) + fun_l4_n471(x) + else + fun_l4_n518(x) + end +end + +def fun_l3_n126(x) + if (x < 1) + fun_l4_n351(x) + else + fun_l4_n825(x) + end +end + +def fun_l3_n127(x) + if (x < 1) + fun_l4_n759(x) + else + fun_l4_n203(x) + end +end + +def fun_l3_n128(x) + if (x < 1) + fun_l4_n336(x) + else + fun_l4_n861(x) + end +end + +def fun_l3_n129(x) + if (x < 1) + fun_l4_n573(x) + else + fun_l4_n568(x) + end +end + +def fun_l3_n130(x) + if (x < 1) + fun_l4_n788(x) + else + fun_l4_n259(x) + end +end + +def fun_l3_n131(x) + if (x < 1) + fun_l4_n392(x) + else + fun_l4_n932(x) + end +end + +def fun_l3_n132(x) + if (x < 1) + fun_l4_n919(x) + else + fun_l4_n650(x) + end +end + +def fun_l3_n133(x) + if (x < 1) + fun_l4_n895(x) + else + fun_l4_n983(x) + end +end + +def fun_l3_n134(x) + if (x < 1) + fun_l4_n389(x) + else + fun_l4_n358(x) + end +end + +def fun_l3_n135(x) + if (x < 1) + fun_l4_n732(x) + else + fun_l4_n747(x) + end +end + +def fun_l3_n136(x) + if (x < 1) + fun_l4_n756(x) + else + fun_l4_n592(x) + end +end + +def fun_l3_n137(x) + if (x < 1) + fun_l4_n581(x) + else + fun_l4_n24(x) + end +end + +def fun_l3_n138(x) + if (x < 1) + fun_l4_n932(x) + else + fun_l4_n599(x) + end +end + +def fun_l3_n139(x) + if (x < 1) + fun_l4_n955(x) + else + fun_l4_n148(x) + end +end + +def fun_l3_n140(x) + if (x < 1) + fun_l4_n332(x) + else + fun_l4_n677(x) + end +end + +def fun_l3_n141(x) + if (x < 1) + fun_l4_n152(x) + else + fun_l4_n696(x) + end +end + +def fun_l3_n142(x) + if (x < 1) + fun_l4_n295(x) + else + fun_l4_n205(x) + end +end + +def fun_l3_n143(x) + if (x < 1) + fun_l4_n543(x) + else + fun_l4_n951(x) + end +end + +def fun_l3_n144(x) + if (x < 1) + fun_l4_n656(x) + else + fun_l4_n494(x) + end +end + +def fun_l3_n145(x) + if (x < 1) + fun_l4_n729(x) + else + fun_l4_n749(x) + end +end + +def fun_l3_n146(x) + if (x < 1) + fun_l4_n197(x) + else + fun_l4_n3(x) + end +end + +def fun_l3_n147(x) + if (x < 1) + fun_l4_n519(x) + else + fun_l4_n36(x) + end +end + +def fun_l3_n148(x) + if (x < 1) + fun_l4_n100(x) + else + fun_l4_n463(x) + end +end + +def fun_l3_n149(x) + if (x < 1) + fun_l4_n890(x) + else + fun_l4_n947(x) + end +end + +def fun_l3_n150(x) + if (x < 1) + fun_l4_n512(x) + else + fun_l4_n982(x) + end +end + +def fun_l3_n151(x) + if (x < 1) + fun_l4_n750(x) + else + fun_l4_n781(x) + end +end + +def fun_l3_n152(x) + if (x < 1) + fun_l4_n193(x) + else + fun_l4_n530(x) + end +end + +def fun_l3_n153(x) + if (x < 1) + fun_l4_n189(x) + else + fun_l4_n209(x) + end +end + +def fun_l3_n154(x) + if (x < 1) + fun_l4_n343(x) + else + fun_l4_n44(x) + end +end + +def fun_l3_n155(x) + if (x < 1) + fun_l4_n536(x) + else + fun_l4_n228(x) + end +end + +def fun_l3_n156(x) + if (x < 1) + fun_l4_n475(x) + else + fun_l4_n790(x) + end +end + +def fun_l3_n157(x) + if (x < 1) + fun_l4_n954(x) + else + fun_l4_n242(x) + end +end + +def fun_l3_n158(x) + if (x < 1) + fun_l4_n19(x) + else + fun_l4_n735(x) + end +end + +def fun_l3_n159(x) + if (x < 1) + fun_l4_n900(x) + else + fun_l4_n456(x) + end +end + +def fun_l3_n160(x) + if (x < 1) + fun_l4_n193(x) + else + fun_l4_n606(x) + end +end + +def fun_l3_n161(x) + if (x < 1) + fun_l4_n684(x) + else + fun_l4_n622(x) + end +end + +def fun_l3_n162(x) + if (x < 1) + fun_l4_n260(x) + else + fun_l4_n582(x) + end +end + +def fun_l3_n163(x) + if (x < 1) + fun_l4_n713(x) + else + fun_l4_n601(x) + end +end + +def fun_l3_n164(x) + if (x < 1) + fun_l4_n819(x) + else + fun_l4_n642(x) + end +end + +def fun_l3_n165(x) + if (x < 1) + fun_l4_n45(x) + else + fun_l4_n777(x) + end +end + +def fun_l3_n166(x) + if (x < 1) + fun_l4_n256(x) + else + fun_l4_n92(x) + end +end + +def fun_l3_n167(x) + if (x < 1) + fun_l4_n975(x) + else + fun_l4_n962(x) + end +end + +def fun_l3_n168(x) + if (x < 1) + fun_l4_n579(x) + else + fun_l4_n208(x) + end +end + +def fun_l3_n169(x) + if (x < 1) + fun_l4_n133(x) + else + fun_l4_n636(x) + end +end + +def fun_l3_n170(x) + if (x < 1) + fun_l4_n863(x) + else + fun_l4_n168(x) + end +end + +def fun_l3_n171(x) + if (x < 1) + fun_l4_n396(x) + else + fun_l4_n654(x) + end +end + +def fun_l3_n172(x) + if (x < 1) + fun_l4_n963(x) + else + fun_l4_n420(x) + end +end + +def fun_l3_n173(x) + if (x < 1) + fun_l4_n487(x) + else + fun_l4_n573(x) + end +end + +def fun_l3_n174(x) + if (x < 1) + fun_l4_n847(x) + else + fun_l4_n476(x) + end +end + +def fun_l3_n175(x) + if (x < 1) + fun_l4_n712(x) + else + fun_l4_n522(x) + end +end + +def fun_l3_n176(x) + if (x < 1) + fun_l4_n292(x) + else + fun_l4_n717(x) + end +end + +def fun_l3_n177(x) + if (x < 1) + fun_l4_n945(x) + else + fun_l4_n146(x) + end +end + +def fun_l3_n178(x) + if (x < 1) + fun_l4_n163(x) + else + fun_l4_n28(x) + end +end + +def fun_l3_n179(x) + if (x < 1) + fun_l4_n738(x) + else + fun_l4_n502(x) + end +end + +def fun_l3_n180(x) + if (x < 1) + fun_l4_n8(x) + else + fun_l4_n56(x) + end +end + +def fun_l3_n181(x) + if (x < 1) + fun_l4_n58(x) + else + fun_l4_n155(x) + end +end + +def fun_l3_n182(x) + if (x < 1) + fun_l4_n298(x) + else + fun_l4_n580(x) + end +end + +def fun_l3_n183(x) + if (x < 1) + fun_l4_n860(x) + else + fun_l4_n176(x) + end +end + +def fun_l3_n184(x) + if (x < 1) + fun_l4_n108(x) + else + fun_l4_n986(x) + end +end + +def fun_l3_n185(x) + if (x < 1) + fun_l4_n366(x) + else + fun_l4_n110(x) + end +end + +def fun_l3_n186(x) + if (x < 1) + fun_l4_n177(x) + else + fun_l4_n158(x) + end +end + +def fun_l3_n187(x) + if (x < 1) + fun_l4_n212(x) + else + fun_l4_n803(x) + end +end + +def fun_l3_n188(x) + if (x < 1) + fun_l4_n946(x) + else + fun_l4_n281(x) + end +end + +def fun_l3_n189(x) + if (x < 1) + fun_l4_n610(x) + else + fun_l4_n691(x) + end +end + +def fun_l3_n190(x) + if (x < 1) + fun_l4_n784(x) + else + fun_l4_n300(x) + end +end + +def fun_l3_n191(x) + if (x < 1) + fun_l4_n272(x) + else + fun_l4_n809(x) + end +end + +def fun_l3_n192(x) + if (x < 1) + fun_l4_n812(x) + else + fun_l4_n633(x) + end +end + +def fun_l3_n193(x) + if (x < 1) + fun_l4_n880(x) + else + fun_l4_n267(x) + end +end + +def fun_l3_n194(x) + if (x < 1) + fun_l4_n454(x) + else + fun_l4_n567(x) + end +end + +def fun_l3_n195(x) + if (x < 1) + fun_l4_n919(x) + else + fun_l4_n184(x) + end +end + +def fun_l3_n196(x) + if (x < 1) + fun_l4_n294(x) + else + fun_l4_n150(x) + end +end + +def fun_l3_n197(x) + if (x < 1) + fun_l4_n543(x) + else + fun_l4_n319(x) + end +end + +def fun_l3_n198(x) + if (x < 1) + fun_l4_n91(x) + else + fun_l4_n378(x) + end +end + +def fun_l3_n199(x) + if (x < 1) + fun_l4_n590(x) + else + fun_l4_n195(x) + end +end + +def fun_l3_n200(x) + if (x < 1) + fun_l4_n532(x) + else + fun_l4_n346(x) + end +end + +def fun_l3_n201(x) + if (x < 1) + fun_l4_n340(x) + else + fun_l4_n129(x) + end +end + +def fun_l3_n202(x) + if (x < 1) + fun_l4_n193(x) + else + fun_l4_n676(x) + end +end + +def fun_l3_n203(x) + if (x < 1) + fun_l4_n210(x) + else + fun_l4_n982(x) + end +end + +def fun_l3_n204(x) + if (x < 1) + fun_l4_n247(x) + else + fun_l4_n550(x) + end +end + +def fun_l3_n205(x) + if (x < 1) + fun_l4_n727(x) + else + fun_l4_n737(x) + end +end + +def fun_l3_n206(x) + if (x < 1) + fun_l4_n111(x) + else + fun_l4_n952(x) + end +end + +def fun_l3_n207(x) + if (x < 1) + fun_l4_n996(x) + else + fun_l4_n865(x) + end +end + +def fun_l3_n208(x) + if (x < 1) + fun_l4_n945(x) + else + fun_l4_n488(x) + end +end + +def fun_l3_n209(x) + if (x < 1) + fun_l4_n697(x) + else + fun_l4_n366(x) + end +end + +def fun_l3_n210(x) + if (x < 1) + fun_l4_n180(x) + else + fun_l4_n995(x) + end +end + +def fun_l3_n211(x) + if (x < 1) + fun_l4_n972(x) + else + fun_l4_n783(x) + end +end + +def fun_l3_n212(x) + if (x < 1) + fun_l4_n58(x) + else + fun_l4_n430(x) + end +end + +def fun_l3_n213(x) + if (x < 1) + fun_l4_n904(x) + else + fun_l4_n703(x) + end +end + +def fun_l3_n214(x) + if (x < 1) + fun_l4_n882(x) + else + fun_l4_n648(x) + end +end + +def fun_l3_n215(x) + if (x < 1) + fun_l4_n800(x) + else + fun_l4_n680(x) + end +end + +def fun_l3_n216(x) + if (x < 1) + fun_l4_n205(x) + else + fun_l4_n185(x) + end +end + +def fun_l3_n217(x) + if (x < 1) + fun_l4_n242(x) + else + fun_l4_n834(x) + end +end + +def fun_l3_n218(x) + if (x < 1) + fun_l4_n551(x) + else + fun_l4_n399(x) + end +end + +def fun_l3_n219(x) + if (x < 1) + fun_l4_n820(x) + else + fun_l4_n403(x) + end +end + +def fun_l3_n220(x) + if (x < 1) + fun_l4_n874(x) + else + fun_l4_n584(x) + end +end + +def fun_l3_n221(x) + if (x < 1) + fun_l4_n845(x) + else + fun_l4_n56(x) + end +end + +def fun_l3_n222(x) + if (x < 1) + fun_l4_n947(x) + else + fun_l4_n299(x) + end +end + +def fun_l3_n223(x) + if (x < 1) + fun_l4_n533(x) + else + fun_l4_n184(x) + end +end + +def fun_l3_n224(x) + if (x < 1) + fun_l4_n760(x) + else + fun_l4_n507(x) + end +end + +def fun_l3_n225(x) + if (x < 1) + fun_l4_n47(x) + else + fun_l4_n712(x) + end +end + +def fun_l3_n226(x) + if (x < 1) + fun_l4_n470(x) + else + fun_l4_n760(x) + end +end + +def fun_l3_n227(x) + if (x < 1) + fun_l4_n932(x) + else + fun_l4_n292(x) + end +end + +def fun_l3_n228(x) + if (x < 1) + fun_l4_n44(x) + else + fun_l4_n855(x) + end +end + +def fun_l3_n229(x) + if (x < 1) + fun_l4_n385(x) + else + fun_l4_n284(x) + end +end + +def fun_l3_n230(x) + if (x < 1) + fun_l4_n272(x) + else + fun_l4_n407(x) + end +end + +def fun_l3_n231(x) + if (x < 1) + fun_l4_n820(x) + else + fun_l4_n375(x) + end +end + +def fun_l3_n232(x) + if (x < 1) + fun_l4_n165(x) + else + fun_l4_n38(x) + end +end + +def fun_l3_n233(x) + if (x < 1) + fun_l4_n772(x) + else + fun_l4_n179(x) + end +end + +def fun_l3_n234(x) + if (x < 1) + fun_l4_n980(x) + else + fun_l4_n678(x) + end +end + +def fun_l3_n235(x) + if (x < 1) + fun_l4_n279(x) + else + fun_l4_n834(x) + end +end + +def fun_l3_n236(x) + if (x < 1) + fun_l4_n227(x) + else + fun_l4_n11(x) + end +end + +def fun_l3_n237(x) + if (x < 1) + fun_l4_n724(x) + else + fun_l4_n659(x) + end +end + +def fun_l3_n238(x) + if (x < 1) + fun_l4_n569(x) + else + fun_l4_n693(x) + end +end + +def fun_l3_n239(x) + if (x < 1) + fun_l4_n933(x) + else + fun_l4_n897(x) + end +end + +def fun_l3_n240(x) + if (x < 1) + fun_l4_n215(x) + else + fun_l4_n784(x) + end +end + +def fun_l3_n241(x) + if (x < 1) + fun_l4_n964(x) + else + fun_l4_n430(x) + end +end + +def fun_l3_n242(x) + if (x < 1) + fun_l4_n91(x) + else + fun_l4_n190(x) + end +end + +def fun_l3_n243(x) + if (x < 1) + fun_l4_n375(x) + else + fun_l4_n638(x) + end +end + +def fun_l3_n244(x) + if (x < 1) + fun_l4_n381(x) + else + fun_l4_n324(x) + end +end + +def fun_l3_n245(x) + if (x < 1) + fun_l4_n983(x) + else + fun_l4_n248(x) + end +end + +def fun_l3_n246(x) + if (x < 1) + fun_l4_n336(x) + else + fun_l4_n647(x) + end +end + +def fun_l3_n247(x) + if (x < 1) + fun_l4_n64(x) + else + fun_l4_n957(x) + end +end + +def fun_l3_n248(x) + if (x < 1) + fun_l4_n313(x) + else + fun_l4_n662(x) + end +end + +def fun_l3_n249(x) + if (x < 1) + fun_l4_n528(x) + else + fun_l4_n448(x) + end +end + +def fun_l3_n250(x) + if (x < 1) + fun_l4_n9(x) + else + fun_l4_n424(x) + end +end + +def fun_l3_n251(x) + if (x < 1) + fun_l4_n290(x) + else + fun_l4_n416(x) + end +end + +def fun_l3_n252(x) + if (x < 1) + fun_l4_n159(x) + else + fun_l4_n780(x) + end +end + +def fun_l3_n253(x) + if (x < 1) + fun_l4_n863(x) + else + fun_l4_n192(x) + end +end + +def fun_l3_n254(x) + if (x < 1) + fun_l4_n658(x) + else + fun_l4_n816(x) + end +end + +def fun_l3_n255(x) + if (x < 1) + fun_l4_n686(x) + else + fun_l4_n586(x) + end +end + +def fun_l3_n256(x) + if (x < 1) + fun_l4_n110(x) + else + fun_l4_n290(x) + end +end + +def fun_l3_n257(x) + if (x < 1) + fun_l4_n355(x) + else + fun_l4_n862(x) + end +end + +def fun_l3_n258(x) + if (x < 1) + fun_l4_n63(x) + else + fun_l4_n205(x) + end +end + +def fun_l3_n259(x) + if (x < 1) + fun_l4_n766(x) + else + fun_l4_n130(x) + end +end + +def fun_l3_n260(x) + if (x < 1) + fun_l4_n670(x) + else + fun_l4_n313(x) + end +end + +def fun_l3_n261(x) + if (x < 1) + fun_l4_n738(x) + else + fun_l4_n796(x) + end +end + +def fun_l3_n262(x) + if (x < 1) + fun_l4_n925(x) + else + fun_l4_n267(x) + end +end + +def fun_l3_n263(x) + if (x < 1) + fun_l4_n515(x) + else + fun_l4_n298(x) + end +end + +def fun_l3_n264(x) + if (x < 1) + fun_l4_n883(x) + else + fun_l4_n809(x) + end +end + +def fun_l3_n265(x) + if (x < 1) + fun_l4_n138(x) + else + fun_l4_n665(x) + end +end + +def fun_l3_n266(x) + if (x < 1) + fun_l4_n141(x) + else + fun_l4_n641(x) + end +end + +def fun_l3_n267(x) + if (x < 1) + fun_l4_n936(x) + else + fun_l4_n233(x) + end +end + +def fun_l3_n268(x) + if (x < 1) + fun_l4_n28(x) + else + fun_l4_n351(x) + end +end + +def fun_l3_n269(x) + if (x < 1) + fun_l4_n62(x) + else + fun_l4_n17(x) + end +end + +def fun_l3_n270(x) + if (x < 1) + fun_l4_n489(x) + else + fun_l4_n408(x) + end +end + +def fun_l3_n271(x) + if (x < 1) + fun_l4_n276(x) + else + fun_l4_n799(x) + end +end + +def fun_l3_n272(x) + if (x < 1) + fun_l4_n103(x) + else + fun_l4_n804(x) + end +end + +def fun_l3_n273(x) + if (x < 1) + fun_l4_n850(x) + else + fun_l4_n388(x) + end +end + +def fun_l3_n274(x) + if (x < 1) + fun_l4_n651(x) + else + fun_l4_n484(x) + end +end + +def fun_l3_n275(x) + if (x < 1) + fun_l4_n693(x) + else + fun_l4_n20(x) + end +end + +def fun_l3_n276(x) + if (x < 1) + fun_l4_n897(x) + else + fun_l4_n328(x) + end +end + +def fun_l3_n277(x) + if (x < 1) + fun_l4_n632(x) + else + fun_l4_n120(x) + end +end + +def fun_l3_n278(x) + if (x < 1) + fun_l4_n919(x) + else + fun_l4_n921(x) + end +end + +def fun_l3_n279(x) + if (x < 1) + fun_l4_n461(x) + else + fun_l4_n219(x) + end +end + +def fun_l3_n280(x) + if (x < 1) + fun_l4_n867(x) + else + fun_l4_n682(x) + end +end + +def fun_l3_n281(x) + if (x < 1) + fun_l4_n233(x) + else + fun_l4_n589(x) + end +end + +def fun_l3_n282(x) + if (x < 1) + fun_l4_n516(x) + else + fun_l4_n970(x) + end +end + +def fun_l3_n283(x) + if (x < 1) + fun_l4_n300(x) + else + fun_l4_n934(x) + end +end + +def fun_l3_n284(x) + if (x < 1) + fun_l4_n736(x) + else + fun_l4_n516(x) + end +end + +def fun_l3_n285(x) + if (x < 1) + fun_l4_n401(x) + else + fun_l4_n539(x) + end +end + +def fun_l3_n286(x) + if (x < 1) + fun_l4_n342(x) + else + fun_l4_n142(x) + end +end + +def fun_l3_n287(x) + if (x < 1) + fun_l4_n44(x) + else + fun_l4_n311(x) + end +end + +def fun_l3_n288(x) + if (x < 1) + fun_l4_n698(x) + else + fun_l4_n407(x) + end +end + +def fun_l3_n289(x) + if (x < 1) + fun_l4_n714(x) + else + fun_l4_n324(x) + end +end + +def fun_l3_n290(x) + if (x < 1) + fun_l4_n862(x) + else + fun_l4_n807(x) + end +end + +def fun_l3_n291(x) + if (x < 1) + fun_l4_n446(x) + else + fun_l4_n378(x) + end +end + +def fun_l3_n292(x) + if (x < 1) + fun_l4_n418(x) + else + fun_l4_n194(x) + end +end + +def fun_l3_n293(x) + if (x < 1) + fun_l4_n336(x) + else + fun_l4_n895(x) + end +end + +def fun_l3_n294(x) + if (x < 1) + fun_l4_n928(x) + else + fun_l4_n154(x) + end +end + +def fun_l3_n295(x) + if (x < 1) + fun_l4_n764(x) + else + fun_l4_n335(x) + end +end + +def fun_l3_n296(x) + if (x < 1) + fun_l4_n840(x) + else + fun_l4_n513(x) + end +end + +def fun_l3_n297(x) + if (x < 1) + fun_l4_n520(x) + else + fun_l4_n838(x) + end +end + +def fun_l3_n298(x) + if (x < 1) + fun_l4_n831(x) + else + fun_l4_n344(x) + end +end + +def fun_l3_n299(x) + if (x < 1) + fun_l4_n110(x) + else + fun_l4_n19(x) + end +end + +def fun_l3_n300(x) + if (x < 1) + fun_l4_n272(x) + else + fun_l4_n952(x) + end +end + +def fun_l3_n301(x) + if (x < 1) + fun_l4_n659(x) + else + fun_l4_n439(x) + end +end + +def fun_l3_n302(x) + if (x < 1) + fun_l4_n787(x) + else + fun_l4_n189(x) + end +end + +def fun_l3_n303(x) + if (x < 1) + fun_l4_n549(x) + else + fun_l4_n594(x) + end +end + +def fun_l3_n304(x) + if (x < 1) + fun_l4_n255(x) + else + fun_l4_n822(x) + end +end + +def fun_l3_n305(x) + if (x < 1) + fun_l4_n312(x) + else + fun_l4_n935(x) + end +end + +def fun_l3_n306(x) + if (x < 1) + fun_l4_n831(x) + else + fun_l4_n299(x) + end +end + +def fun_l3_n307(x) + if (x < 1) + fun_l4_n154(x) + else + fun_l4_n520(x) + end +end + +def fun_l3_n308(x) + if (x < 1) + fun_l4_n768(x) + else + fun_l4_n676(x) + end +end + +def fun_l3_n309(x) + if (x < 1) + fun_l4_n816(x) + else + fun_l4_n447(x) + end +end + +def fun_l3_n310(x) + if (x < 1) + fun_l4_n689(x) + else + fun_l4_n244(x) + end +end + +def fun_l3_n311(x) + if (x < 1) + fun_l4_n389(x) + else + fun_l4_n326(x) + end +end + +def fun_l3_n312(x) + if (x < 1) + fun_l4_n125(x) + else + fun_l4_n502(x) + end +end + +def fun_l3_n313(x) + if (x < 1) + fun_l4_n327(x) + else + fun_l4_n123(x) + end +end + +def fun_l3_n314(x) + if (x < 1) + fun_l4_n558(x) + else + fun_l4_n940(x) + end +end + +def fun_l3_n315(x) + if (x < 1) + fun_l4_n652(x) + else + fun_l4_n10(x) + end +end + +def fun_l3_n316(x) + if (x < 1) + fun_l4_n483(x) + else + fun_l4_n315(x) + end +end + +def fun_l3_n317(x) + if (x < 1) + fun_l4_n567(x) + else + fun_l4_n540(x) + end +end + +def fun_l3_n318(x) + if (x < 1) + fun_l4_n449(x) + else + fun_l4_n760(x) + end +end + +def fun_l3_n319(x) + if (x < 1) + fun_l4_n111(x) + else + fun_l4_n173(x) + end +end + +def fun_l3_n320(x) + if (x < 1) + fun_l4_n373(x) + else + fun_l4_n615(x) + end +end + +def fun_l3_n321(x) + if (x < 1) + fun_l4_n570(x) + else + fun_l4_n27(x) + end +end + +def fun_l3_n322(x) + if (x < 1) + fun_l4_n235(x) + else + fun_l4_n695(x) + end +end + +def fun_l3_n323(x) + if (x < 1) + fun_l4_n788(x) + else + fun_l4_n57(x) + end +end + +def fun_l3_n324(x) + if (x < 1) + fun_l4_n7(x) + else + fun_l4_n75(x) + end +end + +def fun_l3_n325(x) + if (x < 1) + fun_l4_n502(x) + else + fun_l4_n459(x) + end +end + +def fun_l3_n326(x) + if (x < 1) + fun_l4_n572(x) + else + fun_l4_n324(x) + end +end + +def fun_l3_n327(x) + if (x < 1) + fun_l4_n860(x) + else + fun_l4_n250(x) + end +end + +def fun_l3_n328(x) + if (x < 1) + fun_l4_n242(x) + else + fun_l4_n667(x) + end +end + +def fun_l3_n329(x) + if (x < 1) + fun_l4_n589(x) + else + fun_l4_n236(x) + end +end + +def fun_l3_n330(x) + if (x < 1) + fun_l4_n100(x) + else + fun_l4_n476(x) + end +end + +def fun_l3_n331(x) + if (x < 1) + fun_l4_n779(x) + else + fun_l4_n667(x) + end +end + +def fun_l3_n332(x) + if (x < 1) + fun_l4_n277(x) + else + fun_l4_n441(x) + end +end + +def fun_l3_n333(x) + if (x < 1) + fun_l4_n379(x) + else + fun_l4_n331(x) + end +end + +def fun_l3_n334(x) + if (x < 1) + fun_l4_n802(x) + else + fun_l4_n588(x) + end +end + +def fun_l3_n335(x) + if (x < 1) + fun_l4_n385(x) + else + fun_l4_n918(x) + end +end + +def fun_l3_n336(x) + if (x < 1) + fun_l4_n532(x) + else + fun_l4_n254(x) + end +end + +def fun_l3_n337(x) + if (x < 1) + fun_l4_n920(x) + else + fun_l4_n134(x) + end +end + +def fun_l3_n338(x) + if (x < 1) + fun_l4_n803(x) + else + fun_l4_n746(x) + end +end + +def fun_l3_n339(x) + if (x < 1) + fun_l4_n924(x) + else + fun_l4_n878(x) + end +end + +def fun_l3_n340(x) + if (x < 1) + fun_l4_n166(x) + else + fun_l4_n776(x) + end +end + +def fun_l3_n341(x) + if (x < 1) + fun_l4_n240(x) + else + fun_l4_n898(x) + end +end + +def fun_l3_n342(x) + if (x < 1) + fun_l4_n810(x) + else + fun_l4_n423(x) + end +end + +def fun_l3_n343(x) + if (x < 1) + fun_l4_n209(x) + else + fun_l4_n514(x) + end +end + +def fun_l3_n344(x) + if (x < 1) + fun_l4_n505(x) + else + fun_l4_n321(x) + end +end + +def fun_l3_n345(x) + if (x < 1) + fun_l4_n88(x) + else + fun_l4_n39(x) + end +end + +def fun_l3_n346(x) + if (x < 1) + fun_l4_n848(x) + else + fun_l4_n357(x) + end +end + +def fun_l3_n347(x) + if (x < 1) + fun_l4_n450(x) + else + fun_l4_n704(x) + end +end + +def fun_l3_n348(x) + if (x < 1) + fun_l4_n881(x) + else + fun_l4_n916(x) + end +end + +def fun_l3_n349(x) + if (x < 1) + fun_l4_n16(x) + else + fun_l4_n996(x) + end +end + +def fun_l3_n350(x) + if (x < 1) + fun_l4_n839(x) + else + fun_l4_n697(x) + end +end + +def fun_l3_n351(x) + if (x < 1) + fun_l4_n177(x) + else + fun_l4_n859(x) + end +end + +def fun_l3_n352(x) + if (x < 1) + fun_l4_n684(x) + else + fun_l4_n778(x) + end +end + +def fun_l3_n353(x) + if (x < 1) + fun_l4_n604(x) + else + fun_l4_n280(x) + end +end + +def fun_l3_n354(x) + if (x < 1) + fun_l4_n366(x) + else + fun_l4_n576(x) + end +end + +def fun_l3_n355(x) + if (x < 1) + fun_l4_n584(x) + else + fun_l4_n228(x) + end +end + +def fun_l3_n356(x) + if (x < 1) + fun_l4_n844(x) + else + fun_l4_n799(x) + end +end + +def fun_l3_n357(x) + if (x < 1) + fun_l4_n489(x) + else + fun_l4_n905(x) + end +end + +def fun_l3_n358(x) + if (x < 1) + fun_l4_n781(x) + else + fun_l4_n565(x) + end +end + +def fun_l3_n359(x) + if (x < 1) + fun_l4_n110(x) + else + fun_l4_n326(x) + end +end + +def fun_l3_n360(x) + if (x < 1) + fun_l4_n915(x) + else + fun_l4_n489(x) + end +end + +def fun_l3_n361(x) + if (x < 1) + fun_l4_n110(x) + else + fun_l4_n733(x) + end +end + +def fun_l3_n362(x) + if (x < 1) + fun_l4_n93(x) + else + fun_l4_n549(x) + end +end + +def fun_l3_n363(x) + if (x < 1) + fun_l4_n270(x) + else + fun_l4_n883(x) + end +end + +def fun_l3_n364(x) + if (x < 1) + fun_l4_n512(x) + else + fun_l4_n555(x) + end +end + +def fun_l3_n365(x) + if (x < 1) + fun_l4_n800(x) + else + fun_l4_n672(x) + end +end + +def fun_l3_n366(x) + if (x < 1) + fun_l4_n535(x) + else + fun_l4_n320(x) + end +end + +def fun_l3_n367(x) + if (x < 1) + fun_l4_n883(x) + else + fun_l4_n365(x) + end +end + +def fun_l3_n368(x) + if (x < 1) + fun_l4_n306(x) + else + fun_l4_n614(x) + end +end + +def fun_l3_n369(x) + if (x < 1) + fun_l4_n914(x) + else + fun_l4_n20(x) + end +end + +def fun_l3_n370(x) + if (x < 1) + fun_l4_n230(x) + else + fun_l4_n585(x) + end +end + +def fun_l3_n371(x) + if (x < 1) + fun_l4_n544(x) + else + fun_l4_n752(x) + end +end + +def fun_l3_n372(x) + if (x < 1) + fun_l4_n984(x) + else + fun_l4_n738(x) + end +end + +def fun_l3_n373(x) + if (x < 1) + fun_l4_n478(x) + else + fun_l4_n618(x) + end +end + +def fun_l3_n374(x) + if (x < 1) + fun_l4_n941(x) + else + fun_l4_n746(x) + end +end + +def fun_l3_n375(x) + if (x < 1) + fun_l4_n121(x) + else + fun_l4_n798(x) + end +end + +def fun_l3_n376(x) + if (x < 1) + fun_l4_n851(x) + else + fun_l4_n681(x) + end +end + +def fun_l3_n377(x) + if (x < 1) + fun_l4_n502(x) + else + fun_l4_n538(x) + end +end + +def fun_l3_n378(x) + if (x < 1) + fun_l4_n432(x) + else + fun_l4_n226(x) + end +end + +def fun_l3_n379(x) + if (x < 1) + fun_l4_n734(x) + else + fun_l4_n684(x) + end +end + +def fun_l3_n380(x) + if (x < 1) + fun_l4_n912(x) + else + fun_l4_n116(x) + end +end + +def fun_l3_n381(x) + if (x < 1) + fun_l4_n291(x) + else + fun_l4_n464(x) + end +end + +def fun_l3_n382(x) + if (x < 1) + fun_l4_n285(x) + else + fun_l4_n943(x) + end +end + +def fun_l3_n383(x) + if (x < 1) + fun_l4_n738(x) + else + fun_l4_n532(x) + end +end + +def fun_l3_n384(x) + if (x < 1) + fun_l4_n503(x) + else + fun_l4_n724(x) + end +end + +def fun_l3_n385(x) + if (x < 1) + fun_l4_n208(x) + else + fun_l4_n683(x) + end +end + +def fun_l3_n386(x) + if (x < 1) + fun_l4_n673(x) + else + fun_l4_n230(x) + end +end + +def fun_l3_n387(x) + if (x < 1) + fun_l4_n921(x) + else + fun_l4_n800(x) + end +end + +def fun_l3_n388(x) + if (x < 1) + fun_l4_n461(x) + else + fun_l4_n369(x) + end +end + +def fun_l3_n389(x) + if (x < 1) + fun_l4_n86(x) + else + fun_l4_n403(x) + end +end + +def fun_l3_n390(x) + if (x < 1) + fun_l4_n883(x) + else + fun_l4_n92(x) + end +end + +def fun_l3_n391(x) + if (x < 1) + fun_l4_n562(x) + else + fun_l4_n826(x) + end +end + +def fun_l3_n392(x) + if (x < 1) + fun_l4_n459(x) + else + fun_l4_n821(x) + end +end + +def fun_l3_n393(x) + if (x < 1) + fun_l4_n774(x) + else + fun_l4_n376(x) + end +end + +def fun_l3_n394(x) + if (x < 1) + fun_l4_n114(x) + else + fun_l4_n451(x) + end +end + +def fun_l3_n395(x) + if (x < 1) + fun_l4_n689(x) + else + fun_l4_n13(x) + end +end + +def fun_l3_n396(x) + if (x < 1) + fun_l4_n929(x) + else + fun_l4_n777(x) + end +end + +def fun_l3_n397(x) + if (x < 1) + fun_l4_n634(x) + else + fun_l4_n329(x) + end +end + +def fun_l3_n398(x) + if (x < 1) + fun_l4_n972(x) + else + fun_l4_n572(x) + end +end + +def fun_l3_n399(x) + if (x < 1) + fun_l4_n231(x) + else + fun_l4_n14(x) + end +end + +def fun_l3_n400(x) + if (x < 1) + fun_l4_n357(x) + else + fun_l4_n881(x) + end +end + +def fun_l3_n401(x) + if (x < 1) + fun_l4_n283(x) + else + fun_l4_n614(x) + end +end + +def fun_l3_n402(x) + if (x < 1) + fun_l4_n634(x) + else + fun_l4_n653(x) + end +end + +def fun_l3_n403(x) + if (x < 1) + fun_l4_n660(x) + else + fun_l4_n127(x) + end +end + +def fun_l3_n404(x) + if (x < 1) + fun_l4_n523(x) + else + fun_l4_n467(x) + end +end + +def fun_l3_n405(x) + if (x < 1) + fun_l4_n593(x) + else + fun_l4_n78(x) + end +end + +def fun_l3_n406(x) + if (x < 1) + fun_l4_n514(x) + else + fun_l4_n783(x) + end +end + +def fun_l3_n407(x) + if (x < 1) + fun_l4_n460(x) + else + fun_l4_n137(x) + end +end + +def fun_l3_n408(x) + if (x < 1) + fun_l4_n3(x) + else + fun_l4_n224(x) + end +end + +def fun_l3_n409(x) + if (x < 1) + fun_l4_n11(x) + else + fun_l4_n531(x) + end +end + +def fun_l3_n410(x) + if (x < 1) + fun_l4_n94(x) + else + fun_l4_n717(x) + end +end + +def fun_l3_n411(x) + if (x < 1) + fun_l4_n729(x) + else + fun_l4_n526(x) + end +end + +def fun_l3_n412(x) + if (x < 1) + fun_l4_n86(x) + else + fun_l4_n26(x) + end +end + +def fun_l3_n413(x) + if (x < 1) + fun_l4_n249(x) + else + fun_l4_n572(x) + end +end + +def fun_l3_n414(x) + if (x < 1) + fun_l4_n578(x) + else + fun_l4_n512(x) + end +end + +def fun_l3_n415(x) + if (x < 1) + fun_l4_n176(x) + else + fun_l4_n414(x) + end +end + +def fun_l3_n416(x) + if (x < 1) + fun_l4_n757(x) + else + fun_l4_n385(x) + end +end + +def fun_l3_n417(x) + if (x < 1) + fun_l4_n249(x) + else + fun_l4_n180(x) + end +end + +def fun_l3_n418(x) + if (x < 1) + fun_l4_n193(x) + else + fun_l4_n294(x) + end +end + +def fun_l3_n419(x) + if (x < 1) + fun_l4_n441(x) + else + fun_l4_n932(x) + end +end + +def fun_l3_n420(x) + if (x < 1) + fun_l4_n492(x) + else + fun_l4_n239(x) + end +end + +def fun_l3_n421(x) + if (x < 1) + fun_l4_n49(x) + else + fun_l4_n738(x) + end +end + +def fun_l3_n422(x) + if (x < 1) + fun_l4_n546(x) + else + fun_l4_n285(x) + end +end + +def fun_l3_n423(x) + if (x < 1) + fun_l4_n687(x) + else + fun_l4_n973(x) + end +end + +def fun_l3_n424(x) + if (x < 1) + fun_l4_n876(x) + else + fun_l4_n591(x) + end +end + +def fun_l3_n425(x) + if (x < 1) + fun_l4_n626(x) + else + fun_l4_n739(x) + end +end + +def fun_l3_n426(x) + if (x < 1) + fun_l4_n439(x) + else + fun_l4_n709(x) + end +end + +def fun_l3_n427(x) + if (x < 1) + fun_l4_n710(x) + else + fun_l4_n305(x) + end +end + +def fun_l3_n428(x) + if (x < 1) + fun_l4_n61(x) + else + fun_l4_n520(x) + end +end + +def fun_l3_n429(x) + if (x < 1) + fun_l4_n172(x) + else + fun_l4_n12(x) + end +end + +def fun_l3_n430(x) + if (x < 1) + fun_l4_n432(x) + else + fun_l4_n174(x) + end +end + +def fun_l3_n431(x) + if (x < 1) + fun_l4_n194(x) + else + fun_l4_n673(x) + end +end + +def fun_l3_n432(x) + if (x < 1) + fun_l4_n952(x) + else + fun_l4_n798(x) + end +end + +def fun_l3_n433(x) + if (x < 1) + fun_l4_n915(x) + else + fun_l4_n263(x) + end +end + +def fun_l3_n434(x) + if (x < 1) + fun_l4_n735(x) + else + fun_l4_n882(x) + end +end + +def fun_l3_n435(x) + if (x < 1) + fun_l4_n499(x) + else + fun_l4_n947(x) + end +end + +def fun_l3_n436(x) + if (x < 1) + fun_l4_n744(x) + else + fun_l4_n187(x) + end +end + +def fun_l3_n437(x) + if (x < 1) + fun_l4_n244(x) + else + fun_l4_n366(x) + end +end + +def fun_l3_n438(x) + if (x < 1) + fun_l4_n228(x) + else + fun_l4_n866(x) + end +end + +def fun_l3_n439(x) + if (x < 1) + fun_l4_n617(x) + else + fun_l4_n924(x) + end +end + +def fun_l3_n440(x) + if (x < 1) + fun_l4_n302(x) + else + fun_l4_n691(x) + end +end + +def fun_l3_n441(x) + if (x < 1) + fun_l4_n559(x) + else + fun_l4_n758(x) + end +end + +def fun_l3_n442(x) + if (x < 1) + fun_l4_n412(x) + else + fun_l4_n544(x) + end +end + +def fun_l3_n443(x) + if (x < 1) + fun_l4_n130(x) + else + fun_l4_n764(x) + end +end + +def fun_l3_n444(x) + if (x < 1) + fun_l4_n135(x) + else + fun_l4_n65(x) + end +end + +def fun_l3_n445(x) + if (x < 1) + fun_l4_n224(x) + else + fun_l4_n148(x) + end +end + +def fun_l3_n446(x) + if (x < 1) + fun_l4_n238(x) + else + fun_l4_n808(x) + end +end + +def fun_l3_n447(x) + if (x < 1) + fun_l4_n832(x) + else + fun_l4_n460(x) + end +end + +def fun_l3_n448(x) + if (x < 1) + fun_l4_n897(x) + else + fun_l4_n817(x) + end +end + +def fun_l3_n449(x) + if (x < 1) + fun_l4_n587(x) + else + fun_l4_n926(x) + end +end + +def fun_l3_n450(x) + if (x < 1) + fun_l4_n575(x) + else + fun_l4_n274(x) + end +end + +def fun_l3_n451(x) + if (x < 1) + fun_l4_n42(x) + else + fun_l4_n714(x) + end +end + +def fun_l3_n452(x) + if (x < 1) + fun_l4_n101(x) + else + fun_l4_n470(x) + end +end + +def fun_l3_n453(x) + if (x < 1) + fun_l4_n906(x) + else + fun_l4_n724(x) + end +end + +def fun_l3_n454(x) + if (x < 1) + fun_l4_n682(x) + else + fun_l4_n709(x) + end +end + +def fun_l3_n455(x) + if (x < 1) + fun_l4_n929(x) + else + fun_l4_n274(x) + end +end + +def fun_l3_n456(x) + if (x < 1) + fun_l4_n10(x) + else + fun_l4_n101(x) + end +end + +def fun_l3_n457(x) + if (x < 1) + fun_l4_n825(x) + else + fun_l4_n632(x) + end +end + +def fun_l3_n458(x) + if (x < 1) + fun_l4_n2(x) + else + fun_l4_n723(x) + end +end + +def fun_l3_n459(x) + if (x < 1) + fun_l4_n998(x) + else + fun_l4_n546(x) + end +end + +def fun_l3_n460(x) + if (x < 1) + fun_l4_n483(x) + else + fun_l4_n445(x) + end +end + +def fun_l3_n461(x) + if (x < 1) + fun_l4_n896(x) + else + fun_l4_n993(x) + end +end + +def fun_l3_n462(x) + if (x < 1) + fun_l4_n710(x) + else + fun_l4_n529(x) + end +end + +def fun_l3_n463(x) + if (x < 1) + fun_l4_n913(x) + else + fun_l4_n65(x) + end +end + +def fun_l3_n464(x) + if (x < 1) + fun_l4_n712(x) + else + fun_l4_n412(x) + end +end + +def fun_l3_n465(x) + if (x < 1) + fun_l4_n296(x) + else + fun_l4_n37(x) + end +end + +def fun_l3_n466(x) + if (x < 1) + fun_l4_n241(x) + else + fun_l4_n649(x) + end +end + +def fun_l3_n467(x) + if (x < 1) + fun_l4_n296(x) + else + fun_l4_n80(x) + end +end + +def fun_l3_n468(x) + if (x < 1) + fun_l4_n270(x) + else + fun_l4_n192(x) + end +end + +def fun_l3_n469(x) + if (x < 1) + fun_l4_n655(x) + else + fun_l4_n605(x) + end +end + +def fun_l3_n470(x) + if (x < 1) + fun_l4_n180(x) + else + fun_l4_n807(x) + end +end + +def fun_l3_n471(x) + if (x < 1) + fun_l4_n915(x) + else + fun_l4_n902(x) + end +end + +def fun_l3_n472(x) + if (x < 1) + fun_l4_n527(x) + else + fun_l4_n638(x) + end +end + +def fun_l3_n473(x) + if (x < 1) + fun_l4_n775(x) + else + fun_l4_n572(x) + end +end + +def fun_l3_n474(x) + if (x < 1) + fun_l4_n856(x) + else + fun_l4_n182(x) + end +end + +def fun_l3_n475(x) + if (x < 1) + fun_l4_n434(x) + else + fun_l4_n232(x) + end +end + +def fun_l3_n476(x) + if (x < 1) + fun_l4_n208(x) + else + fun_l4_n37(x) + end +end + +def fun_l3_n477(x) + if (x < 1) + fun_l4_n146(x) + else + fun_l4_n764(x) + end +end + +def fun_l3_n478(x) + if (x < 1) + fun_l4_n806(x) + else + fun_l4_n148(x) + end +end + +def fun_l3_n479(x) + if (x < 1) + fun_l4_n46(x) + else + fun_l4_n488(x) + end +end + +def fun_l3_n480(x) + if (x < 1) + fun_l4_n637(x) + else + fun_l4_n48(x) + end +end + +def fun_l3_n481(x) + if (x < 1) + fun_l4_n496(x) + else + fun_l4_n891(x) + end +end + +def fun_l3_n482(x) + if (x < 1) + fun_l4_n282(x) + else + fun_l4_n736(x) + end +end + +def fun_l3_n483(x) + if (x < 1) + fun_l4_n377(x) + else + fun_l4_n603(x) + end +end + +def fun_l3_n484(x) + if (x < 1) + fun_l4_n689(x) + else + fun_l4_n201(x) + end +end + +def fun_l3_n485(x) + if (x < 1) + fun_l4_n495(x) + else + fun_l4_n721(x) + end +end + +def fun_l3_n486(x) + if (x < 1) + fun_l4_n128(x) + else + fun_l4_n400(x) + end +end + +def fun_l3_n487(x) + if (x < 1) + fun_l4_n993(x) + else + fun_l4_n53(x) + end +end + +def fun_l3_n488(x) + if (x < 1) + fun_l4_n913(x) + else + fun_l4_n814(x) + end +end + +def fun_l3_n489(x) + if (x < 1) + fun_l4_n816(x) + else + fun_l4_n196(x) + end +end + +def fun_l3_n490(x) + if (x < 1) + fun_l4_n754(x) + else + fun_l4_n451(x) + end +end + +def fun_l3_n491(x) + if (x < 1) + fun_l4_n57(x) + else + fun_l4_n597(x) + end +end + +def fun_l3_n492(x) + if (x < 1) + fun_l4_n539(x) + else + fun_l4_n893(x) + end +end + +def fun_l3_n493(x) + if (x < 1) + fun_l4_n542(x) + else + fun_l4_n956(x) + end +end + +def fun_l3_n494(x) + if (x < 1) + fun_l4_n479(x) + else + fun_l4_n448(x) + end +end + +def fun_l3_n495(x) + if (x < 1) + fun_l4_n263(x) + else + fun_l4_n912(x) + end +end + +def fun_l3_n496(x) + if (x < 1) + fun_l4_n463(x) + else + fun_l4_n112(x) + end +end + +def fun_l3_n497(x) + if (x < 1) + fun_l4_n806(x) + else + fun_l4_n486(x) + end +end + +def fun_l3_n498(x) + if (x < 1) + fun_l4_n155(x) + else + fun_l4_n298(x) + end +end + +def fun_l3_n499(x) + if (x < 1) + fun_l4_n538(x) + else + fun_l4_n908(x) + end +end + +def fun_l3_n500(x) + if (x < 1) + fun_l4_n769(x) + else + fun_l4_n681(x) + end +end + +def fun_l3_n501(x) + if (x < 1) + fun_l4_n544(x) + else + fun_l4_n749(x) + end +end + +def fun_l3_n502(x) + if (x < 1) + fun_l4_n505(x) + else + fun_l4_n66(x) + end +end + +def fun_l3_n503(x) + if (x < 1) + fun_l4_n900(x) + else + fun_l4_n917(x) + end +end + +def fun_l3_n504(x) + if (x < 1) + fun_l4_n982(x) + else + fun_l4_n707(x) + end +end + +def fun_l3_n505(x) + if (x < 1) + fun_l4_n102(x) + else + fun_l4_n564(x) + end +end + +def fun_l3_n506(x) + if (x < 1) + fun_l4_n332(x) + else + fun_l4_n367(x) + end +end + +def fun_l3_n507(x) + if (x < 1) + fun_l4_n969(x) + else + fun_l4_n354(x) + end +end + +def fun_l3_n508(x) + if (x < 1) + fun_l4_n405(x) + else + fun_l4_n485(x) + end +end + +def fun_l3_n509(x) + if (x < 1) + fun_l4_n477(x) + else + fun_l4_n629(x) + end +end + +def fun_l3_n510(x) + if (x < 1) + fun_l4_n753(x) + else + fun_l4_n78(x) + end +end + +def fun_l3_n511(x) + if (x < 1) + fun_l4_n221(x) + else + fun_l4_n637(x) + end +end + +def fun_l3_n512(x) + if (x < 1) + fun_l4_n540(x) + else + fun_l4_n267(x) + end +end + +def fun_l3_n513(x) + if (x < 1) + fun_l4_n750(x) + else + fun_l4_n626(x) + end +end + +def fun_l3_n514(x) + if (x < 1) + fun_l4_n160(x) + else + fun_l4_n32(x) + end +end + +def fun_l3_n515(x) + if (x < 1) + fun_l4_n914(x) + else + fun_l4_n967(x) + end +end + +def fun_l3_n516(x) + if (x < 1) + fun_l4_n380(x) + else + fun_l4_n83(x) + end +end + +def fun_l3_n517(x) + if (x < 1) + fun_l4_n175(x) + else + fun_l4_n830(x) + end +end + +def fun_l3_n518(x) + if (x < 1) + fun_l4_n579(x) + else + fun_l4_n773(x) + end +end + +def fun_l3_n519(x) + if (x < 1) + fun_l4_n707(x) + else + fun_l4_n690(x) + end +end + +def fun_l3_n520(x) + if (x < 1) + fun_l4_n587(x) + else + fun_l4_n754(x) + end +end + +def fun_l3_n521(x) + if (x < 1) + fun_l4_n922(x) + else + fun_l4_n156(x) + end +end + +def fun_l3_n522(x) + if (x < 1) + fun_l4_n299(x) + else + fun_l4_n937(x) + end +end + +def fun_l3_n523(x) + if (x < 1) + fun_l4_n996(x) + else + fun_l4_n786(x) + end +end + +def fun_l3_n524(x) + if (x < 1) + fun_l4_n988(x) + else + fun_l4_n930(x) + end +end + +def fun_l3_n525(x) + if (x < 1) + fun_l4_n475(x) + else + fun_l4_n43(x) + end +end + +def fun_l3_n526(x) + if (x < 1) + fun_l4_n367(x) + else + fun_l4_n167(x) + end +end + +def fun_l3_n527(x) + if (x < 1) + fun_l4_n31(x) + else + fun_l4_n394(x) + end +end + +def fun_l3_n528(x) + if (x < 1) + fun_l4_n92(x) + else + fun_l4_n304(x) + end +end + +def fun_l3_n529(x) + if (x < 1) + fun_l4_n369(x) + else + fun_l4_n458(x) + end +end + +def fun_l3_n530(x) + if (x < 1) + fun_l4_n475(x) + else + fun_l4_n8(x) + end +end + +def fun_l3_n531(x) + if (x < 1) + fun_l4_n678(x) + else + fun_l4_n970(x) + end +end + +def fun_l3_n532(x) + if (x < 1) + fun_l4_n349(x) + else + fun_l4_n853(x) + end +end + +def fun_l3_n533(x) + if (x < 1) + fun_l4_n918(x) + else + fun_l4_n820(x) + end +end + +def fun_l3_n534(x) + if (x < 1) + fun_l4_n369(x) + else + fun_l4_n445(x) + end +end + +def fun_l3_n535(x) + if (x < 1) + fun_l4_n437(x) + else + fun_l4_n930(x) + end +end + +def fun_l3_n536(x) + if (x < 1) + fun_l4_n143(x) + else + fun_l4_n986(x) + end +end + +def fun_l3_n537(x) + if (x < 1) + fun_l4_n603(x) + else + fun_l4_n818(x) + end +end + +def fun_l3_n538(x) + if (x < 1) + fun_l4_n14(x) + else + fun_l4_n994(x) + end +end + +def fun_l3_n539(x) + if (x < 1) + fun_l4_n650(x) + else + fun_l4_n115(x) + end +end + +def fun_l3_n540(x) + if (x < 1) + fun_l4_n74(x) + else + fun_l4_n559(x) + end +end + +def fun_l3_n541(x) + if (x < 1) + fun_l4_n601(x) + else + fun_l4_n756(x) + end +end + +def fun_l3_n542(x) + if (x < 1) + fun_l4_n733(x) + else + fun_l4_n274(x) + end +end + +def fun_l3_n543(x) + if (x < 1) + fun_l4_n819(x) + else + fun_l4_n97(x) + end +end + +def fun_l3_n544(x) + if (x < 1) + fun_l4_n949(x) + else + fun_l4_n868(x) + end +end + +def fun_l3_n545(x) + if (x < 1) + fun_l4_n346(x) + else + fun_l4_n0(x) + end +end + +def fun_l3_n546(x) + if (x < 1) + fun_l4_n820(x) + else + fun_l4_n188(x) + end +end + +def fun_l3_n547(x) + if (x < 1) + fun_l4_n403(x) + else + fun_l4_n670(x) + end +end + +def fun_l3_n548(x) + if (x < 1) + fun_l4_n449(x) + else + fun_l4_n96(x) + end +end + +def fun_l3_n549(x) + if (x < 1) + fun_l4_n585(x) + else + fun_l4_n388(x) + end +end + +def fun_l3_n550(x) + if (x < 1) + fun_l4_n963(x) + else + fun_l4_n979(x) + end +end + +def fun_l3_n551(x) + if (x < 1) + fun_l4_n892(x) + else + fun_l4_n583(x) + end +end + +def fun_l3_n552(x) + if (x < 1) + fun_l4_n846(x) + else + fun_l4_n508(x) + end +end + +def fun_l3_n553(x) + if (x < 1) + fun_l4_n160(x) + else + fun_l4_n428(x) + end +end + +def fun_l3_n554(x) + if (x < 1) + fun_l4_n538(x) + else + fun_l4_n641(x) + end +end + +def fun_l3_n555(x) + if (x < 1) + fun_l4_n523(x) + else + fun_l4_n697(x) + end +end + +def fun_l3_n556(x) + if (x < 1) + fun_l4_n212(x) + else + fun_l4_n0(x) + end +end + +def fun_l3_n557(x) + if (x < 1) + fun_l4_n255(x) + else + fun_l4_n860(x) + end +end + +def fun_l3_n558(x) + if (x < 1) + fun_l4_n807(x) + else + fun_l4_n865(x) + end +end + +def fun_l3_n559(x) + if (x < 1) + fun_l4_n735(x) + else + fun_l4_n352(x) + end +end + +def fun_l3_n560(x) + if (x < 1) + fun_l4_n327(x) + else + fun_l4_n739(x) + end +end + +def fun_l3_n561(x) + if (x < 1) + fun_l4_n637(x) + else + fun_l4_n628(x) + end +end + +def fun_l3_n562(x) + if (x < 1) + fun_l4_n281(x) + else + fun_l4_n394(x) + end +end + +def fun_l3_n563(x) + if (x < 1) + fun_l4_n440(x) + else + fun_l4_n179(x) + end +end + +def fun_l3_n564(x) + if (x < 1) + fun_l4_n893(x) + else + fun_l4_n396(x) + end +end + +def fun_l3_n565(x) + if (x < 1) + fun_l4_n94(x) + else + fun_l4_n134(x) + end +end + +def fun_l3_n566(x) + if (x < 1) + fun_l4_n968(x) + else + fun_l4_n444(x) + end +end + +def fun_l3_n567(x) + if (x < 1) + fun_l4_n85(x) + else + fun_l4_n281(x) + end +end + +def fun_l3_n568(x) + if (x < 1) + fun_l4_n164(x) + else + fun_l4_n229(x) + end +end + +def fun_l3_n569(x) + if (x < 1) + fun_l4_n594(x) + else + fun_l4_n756(x) + end +end + +def fun_l3_n570(x) + if (x < 1) + fun_l4_n77(x) + else + fun_l4_n370(x) + end +end + +def fun_l3_n571(x) + if (x < 1) + fun_l4_n724(x) + else + fun_l4_n965(x) + end +end + +def fun_l3_n572(x) + if (x < 1) + fun_l4_n394(x) + else + fun_l4_n595(x) + end +end + +def fun_l3_n573(x) + if (x < 1) + fun_l4_n54(x) + else + fun_l4_n41(x) + end +end + +def fun_l3_n574(x) + if (x < 1) + fun_l4_n951(x) + else + fun_l4_n414(x) + end +end + +def fun_l3_n575(x) + if (x < 1) + fun_l4_n297(x) + else + fun_l4_n126(x) + end +end + +def fun_l3_n576(x) + if (x < 1) + fun_l4_n538(x) + else + fun_l4_n276(x) + end +end + +def fun_l3_n577(x) + if (x < 1) + fun_l4_n882(x) + else + fun_l4_n152(x) + end +end + +def fun_l3_n578(x) + if (x < 1) + fun_l4_n950(x) + else + fun_l4_n822(x) + end +end + +def fun_l3_n579(x) + if (x < 1) + fun_l4_n484(x) + else + fun_l4_n99(x) + end +end + +def fun_l3_n580(x) + if (x < 1) + fun_l4_n160(x) + else + fun_l4_n98(x) + end +end + +def fun_l3_n581(x) + if (x < 1) + fun_l4_n10(x) + else + fun_l4_n537(x) + end +end + +def fun_l3_n582(x) + if (x < 1) + fun_l4_n419(x) + else + fun_l4_n285(x) + end +end + +def fun_l3_n583(x) + if (x < 1) + fun_l4_n330(x) + else + fun_l4_n732(x) + end +end + +def fun_l3_n584(x) + if (x < 1) + fun_l4_n64(x) + else + fun_l4_n461(x) + end +end + +def fun_l3_n585(x) + if (x < 1) + fun_l4_n326(x) + else + fun_l4_n134(x) + end +end + +def fun_l3_n586(x) + if (x < 1) + fun_l4_n423(x) + else + fun_l4_n945(x) + end +end + +def fun_l3_n587(x) + if (x < 1) + fun_l4_n192(x) + else + fun_l4_n459(x) + end +end + +def fun_l3_n588(x) + if (x < 1) + fun_l4_n292(x) + else + fun_l4_n697(x) + end +end + +def fun_l3_n589(x) + if (x < 1) + fun_l4_n612(x) + else + fun_l4_n902(x) + end +end + +def fun_l3_n590(x) + if (x < 1) + fun_l4_n842(x) + else + fun_l4_n300(x) + end +end + +def fun_l3_n591(x) + if (x < 1) + fun_l4_n265(x) + else + fun_l4_n906(x) + end +end + +def fun_l3_n592(x) + if (x < 1) + fun_l4_n82(x) + else + fun_l4_n417(x) + end +end + +def fun_l3_n593(x) + if (x < 1) + fun_l4_n896(x) + else + fun_l4_n794(x) + end +end + +def fun_l3_n594(x) + if (x < 1) + fun_l4_n760(x) + else + fun_l4_n83(x) + end +end + +def fun_l3_n595(x) + if (x < 1) + fun_l4_n750(x) + else + fun_l4_n778(x) + end +end + +def fun_l3_n596(x) + if (x < 1) + fun_l4_n655(x) + else + fun_l4_n8(x) + end +end + +def fun_l3_n597(x) + if (x < 1) + fun_l4_n810(x) + else + fun_l4_n824(x) + end +end + +def fun_l3_n598(x) + if (x < 1) + fun_l4_n904(x) + else + fun_l4_n921(x) + end +end + +def fun_l3_n599(x) + if (x < 1) + fun_l4_n16(x) + else + fun_l4_n96(x) + end +end + +def fun_l3_n600(x) + if (x < 1) + fun_l4_n879(x) + else + fun_l4_n757(x) + end +end + +def fun_l3_n601(x) + if (x < 1) + fun_l4_n840(x) + else + fun_l4_n62(x) + end +end + +def fun_l3_n602(x) + if (x < 1) + fun_l4_n547(x) + else + fun_l4_n45(x) + end +end + +def fun_l3_n603(x) + if (x < 1) + fun_l4_n978(x) + else + fun_l4_n646(x) + end +end + +def fun_l3_n604(x) + if (x < 1) + fun_l4_n100(x) + else + fun_l4_n654(x) + end +end + +def fun_l3_n605(x) + if (x < 1) + fun_l4_n257(x) + else + fun_l4_n465(x) + end +end + +def fun_l3_n606(x) + if (x < 1) + fun_l4_n427(x) + else + fun_l4_n489(x) + end +end + +def fun_l3_n607(x) + if (x < 1) + fun_l4_n465(x) + else + fun_l4_n48(x) + end +end + +def fun_l3_n608(x) + if (x < 1) + fun_l4_n571(x) + else + fun_l4_n332(x) + end +end + +def fun_l3_n609(x) + if (x < 1) + fun_l4_n813(x) + else + fun_l4_n462(x) + end +end + +def fun_l3_n610(x) + if (x < 1) + fun_l4_n931(x) + else + fun_l4_n913(x) + end +end + +def fun_l3_n611(x) + if (x < 1) + fun_l4_n20(x) + else + fun_l4_n933(x) + end +end + +def fun_l3_n612(x) + if (x < 1) + fun_l4_n913(x) + else + fun_l4_n787(x) + end +end + +def fun_l3_n613(x) + if (x < 1) + fun_l4_n523(x) + else + fun_l4_n735(x) + end +end + +def fun_l3_n614(x) + if (x < 1) + fun_l4_n315(x) + else + fun_l4_n913(x) + end +end + +def fun_l3_n615(x) + if (x < 1) + fun_l4_n308(x) + else + fun_l4_n865(x) + end +end + +def fun_l3_n616(x) + if (x < 1) + fun_l4_n847(x) + else + fun_l4_n506(x) + end +end + +def fun_l3_n617(x) + if (x < 1) + fun_l4_n387(x) + else + fun_l4_n551(x) + end +end + +def fun_l3_n618(x) + if (x < 1) + fun_l4_n276(x) + else + fun_l4_n991(x) + end +end + +def fun_l3_n619(x) + if (x < 1) + fun_l4_n524(x) + else + fun_l4_n202(x) + end +end + +def fun_l3_n620(x) + if (x < 1) + fun_l4_n836(x) + else + fun_l4_n548(x) + end +end + +def fun_l3_n621(x) + if (x < 1) + fun_l4_n76(x) + else + fun_l4_n5(x) + end +end + +def fun_l3_n622(x) + if (x < 1) + fun_l4_n223(x) + else + fun_l4_n438(x) + end +end + +def fun_l3_n623(x) + if (x < 1) + fun_l4_n31(x) + else + fun_l4_n590(x) + end +end + +def fun_l3_n624(x) + if (x < 1) + fun_l4_n609(x) + else + fun_l4_n513(x) + end +end + +def fun_l3_n625(x) + if (x < 1) + fun_l4_n966(x) + else + fun_l4_n278(x) + end +end + +def fun_l3_n626(x) + if (x < 1) + fun_l4_n82(x) + else + fun_l4_n100(x) + end +end + +def fun_l3_n627(x) + if (x < 1) + fun_l4_n312(x) + else + fun_l4_n746(x) + end +end + +def fun_l3_n628(x) + if (x < 1) + fun_l4_n682(x) + else + fun_l4_n791(x) + end +end + +def fun_l3_n629(x) + if (x < 1) + fun_l4_n166(x) + else + fun_l4_n678(x) + end +end + +def fun_l3_n630(x) + if (x < 1) + fun_l4_n507(x) + else + fun_l4_n778(x) + end +end + +def fun_l3_n631(x) + if (x < 1) + fun_l4_n97(x) + else + fun_l4_n13(x) + end +end + +def fun_l3_n632(x) + if (x < 1) + fun_l4_n976(x) + else + fun_l4_n794(x) + end +end + +def fun_l3_n633(x) + if (x < 1) + fun_l4_n994(x) + else + fun_l4_n743(x) + end +end + +def fun_l3_n634(x) + if (x < 1) + fun_l4_n212(x) + else + fun_l4_n754(x) + end +end + +def fun_l3_n635(x) + if (x < 1) + fun_l4_n602(x) + else + fun_l4_n997(x) + end +end + +def fun_l3_n636(x) + if (x < 1) + fun_l4_n282(x) + else + fun_l4_n133(x) + end +end + +def fun_l3_n637(x) + if (x < 1) + fun_l4_n413(x) + else + fun_l4_n952(x) + end +end + +def fun_l3_n638(x) + if (x < 1) + fun_l4_n843(x) + else + fun_l4_n783(x) + end +end + +def fun_l3_n639(x) + if (x < 1) + fun_l4_n946(x) + else + fun_l4_n833(x) + end +end + +def fun_l3_n640(x) + if (x < 1) + fun_l4_n384(x) + else + fun_l4_n444(x) + end +end + +def fun_l3_n641(x) + if (x < 1) + fun_l4_n699(x) + else + fun_l4_n26(x) + end +end + +def fun_l3_n642(x) + if (x < 1) + fun_l4_n96(x) + else + fun_l4_n623(x) + end +end + +def fun_l3_n643(x) + if (x < 1) + fun_l4_n928(x) + else + fun_l4_n8(x) + end +end + +def fun_l3_n644(x) + if (x < 1) + fun_l4_n804(x) + else + fun_l4_n618(x) + end +end + +def fun_l3_n645(x) + if (x < 1) + fun_l4_n513(x) + else + fun_l4_n214(x) + end +end + +def fun_l3_n646(x) + if (x < 1) + fun_l4_n605(x) + else + fun_l4_n920(x) + end +end + +def fun_l3_n647(x) + if (x < 1) + fun_l4_n774(x) + else + fun_l4_n297(x) + end +end + +def fun_l3_n648(x) + if (x < 1) + fun_l4_n871(x) + else + fun_l4_n75(x) + end +end + +def fun_l3_n649(x) + if (x < 1) + fun_l4_n196(x) + else + fun_l4_n277(x) + end +end + +def fun_l3_n650(x) + if (x < 1) + fun_l4_n25(x) + else + fun_l4_n681(x) + end +end + +def fun_l3_n651(x) + if (x < 1) + fun_l4_n603(x) + else + fun_l4_n46(x) + end +end + +def fun_l3_n652(x) + if (x < 1) + fun_l4_n623(x) + else + fun_l4_n604(x) + end +end + +def fun_l3_n653(x) + if (x < 1) + fun_l4_n854(x) + else + fun_l4_n955(x) + end +end + +def fun_l3_n654(x) + if (x < 1) + fun_l4_n667(x) + else + fun_l4_n988(x) + end +end + +def fun_l3_n655(x) + if (x < 1) + fun_l4_n263(x) + else + fun_l4_n831(x) + end +end + +def fun_l3_n656(x) + if (x < 1) + fun_l4_n591(x) + else + fun_l4_n593(x) + end +end + +def fun_l3_n657(x) + if (x < 1) + fun_l4_n308(x) + else + fun_l4_n547(x) + end +end + +def fun_l3_n658(x) + if (x < 1) + fun_l4_n780(x) + else + fun_l4_n174(x) + end +end + +def fun_l3_n659(x) + if (x < 1) + fun_l4_n54(x) + else + fun_l4_n681(x) + end +end + +def fun_l3_n660(x) + if (x < 1) + fun_l4_n279(x) + else + fun_l4_n282(x) + end +end + +def fun_l3_n661(x) + if (x < 1) + fun_l4_n953(x) + else + fun_l4_n832(x) + end +end + +def fun_l3_n662(x) + if (x < 1) + fun_l4_n525(x) + else + fun_l4_n850(x) + end +end + +def fun_l3_n663(x) + if (x < 1) + fun_l4_n606(x) + else + fun_l4_n167(x) + end +end + +def fun_l3_n664(x) + if (x < 1) + fun_l4_n941(x) + else + fun_l4_n591(x) + end +end + +def fun_l3_n665(x) + if (x < 1) + fun_l4_n781(x) + else + fun_l4_n162(x) + end +end + +def fun_l3_n666(x) + if (x < 1) + fun_l4_n848(x) + else + fun_l4_n133(x) + end +end + +def fun_l3_n667(x) + if (x < 1) + fun_l4_n341(x) + else + fun_l4_n212(x) + end +end + +def fun_l3_n668(x) + if (x < 1) + fun_l4_n320(x) + else + fun_l4_n131(x) + end +end + +def fun_l3_n669(x) + if (x < 1) + fun_l4_n18(x) + else + fun_l4_n385(x) + end +end + +def fun_l3_n670(x) + if (x < 1) + fun_l4_n917(x) + else + fun_l4_n988(x) + end +end + +def fun_l3_n671(x) + if (x < 1) + fun_l4_n50(x) + else + fun_l4_n27(x) + end +end + +def fun_l3_n672(x) + if (x < 1) + fun_l4_n277(x) + else + fun_l4_n238(x) + end +end + +def fun_l3_n673(x) + if (x < 1) + fun_l4_n303(x) + else + fun_l4_n643(x) + end +end + +def fun_l3_n674(x) + if (x < 1) + fun_l4_n794(x) + else + fun_l4_n906(x) + end +end + +def fun_l3_n675(x) + if (x < 1) + fun_l4_n688(x) + else + fun_l4_n312(x) + end +end + +def fun_l3_n676(x) + if (x < 1) + fun_l4_n833(x) + else + fun_l4_n900(x) + end +end + +def fun_l3_n677(x) + if (x < 1) + fun_l4_n649(x) + else + fun_l4_n822(x) + end +end + +def fun_l3_n678(x) + if (x < 1) + fun_l4_n958(x) + else + fun_l4_n939(x) + end +end + +def fun_l3_n679(x) + if (x < 1) + fun_l4_n949(x) + else + fun_l4_n887(x) + end +end + +def fun_l3_n680(x) + if (x < 1) + fun_l4_n630(x) + else + fun_l4_n508(x) + end +end + +def fun_l3_n681(x) + if (x < 1) + fun_l4_n553(x) + else + fun_l4_n940(x) + end +end + +def fun_l3_n682(x) + if (x < 1) + fun_l4_n180(x) + else + fun_l4_n950(x) + end +end + +def fun_l3_n683(x) + if (x < 1) + fun_l4_n898(x) + else + fun_l4_n374(x) + end +end + +def fun_l3_n684(x) + if (x < 1) + fun_l4_n802(x) + else + fun_l4_n527(x) + end +end + +def fun_l3_n685(x) + if (x < 1) + fun_l4_n751(x) + else + fun_l4_n967(x) + end +end + +def fun_l3_n686(x) + if (x < 1) + fun_l4_n235(x) + else + fun_l4_n559(x) + end +end + +def fun_l3_n687(x) + if (x < 1) + fun_l4_n694(x) + else + fun_l4_n819(x) + end +end + +def fun_l3_n688(x) + if (x < 1) + fun_l4_n167(x) + else + fun_l4_n91(x) + end +end + +def fun_l3_n689(x) + if (x < 1) + fun_l4_n692(x) + else + fun_l4_n422(x) + end +end + +def fun_l3_n690(x) + if (x < 1) + fun_l4_n344(x) + else + fun_l4_n738(x) + end +end + +def fun_l3_n691(x) + if (x < 1) + fun_l4_n394(x) + else + fun_l4_n603(x) + end +end + +def fun_l3_n692(x) + if (x < 1) + fun_l4_n909(x) + else + fun_l4_n528(x) + end +end + +def fun_l3_n693(x) + if (x < 1) + fun_l4_n180(x) + else + fun_l4_n22(x) + end +end + +def fun_l3_n694(x) + if (x < 1) + fun_l4_n6(x) + else + fun_l4_n777(x) + end +end + +def fun_l3_n695(x) + if (x < 1) + fun_l4_n327(x) + else + fun_l4_n948(x) + end +end + +def fun_l3_n696(x) + if (x < 1) + fun_l4_n748(x) + else + fun_l4_n706(x) + end +end + +def fun_l3_n697(x) + if (x < 1) + fun_l4_n720(x) + else + fun_l4_n693(x) + end +end + +def fun_l3_n698(x) + if (x < 1) + fun_l4_n282(x) + else + fun_l4_n755(x) + end +end + +def fun_l3_n699(x) + if (x < 1) + fun_l4_n975(x) + else + fun_l4_n415(x) + end +end + +def fun_l3_n700(x) + if (x < 1) + fun_l4_n684(x) + else + fun_l4_n738(x) + end +end + +def fun_l3_n701(x) + if (x < 1) + fun_l4_n58(x) + else + fun_l4_n892(x) + end +end + +def fun_l3_n702(x) + if (x < 1) + fun_l4_n366(x) + else + fun_l4_n189(x) + end +end + +def fun_l3_n703(x) + if (x < 1) + fun_l4_n422(x) + else + fun_l4_n535(x) + end +end + +def fun_l3_n704(x) + if (x < 1) + fun_l4_n886(x) + else + fun_l4_n223(x) + end +end + +def fun_l3_n705(x) + if (x < 1) + fun_l4_n57(x) + else + fun_l4_n62(x) + end +end + +def fun_l3_n706(x) + if (x < 1) + fun_l4_n629(x) + else + fun_l4_n479(x) + end +end + +def fun_l3_n707(x) + if (x < 1) + fun_l4_n477(x) + else + fun_l4_n302(x) + end +end + +def fun_l3_n708(x) + if (x < 1) + fun_l4_n790(x) + else + fun_l4_n262(x) + end +end + +def fun_l3_n709(x) + if (x < 1) + fun_l4_n772(x) + else + fun_l4_n995(x) + end +end + +def fun_l3_n710(x) + if (x < 1) + fun_l4_n549(x) + else + fun_l4_n651(x) + end +end + +def fun_l3_n711(x) + if (x < 1) + fun_l4_n77(x) + else + fun_l4_n555(x) + end +end + +def fun_l3_n712(x) + if (x < 1) + fun_l4_n515(x) + else + fun_l4_n734(x) + end +end + +def fun_l3_n713(x) + if (x < 1) + fun_l4_n778(x) + else + fun_l4_n884(x) + end +end + +def fun_l3_n714(x) + if (x < 1) + fun_l4_n235(x) + else + fun_l4_n637(x) + end +end + +def fun_l3_n715(x) + if (x < 1) + fun_l4_n516(x) + else + fun_l4_n249(x) + end +end + +def fun_l3_n716(x) + if (x < 1) + fun_l4_n44(x) + else + fun_l4_n307(x) + end +end + +def fun_l3_n717(x) + if (x < 1) + fun_l4_n482(x) + else + fun_l4_n4(x) + end +end + +def fun_l3_n718(x) + if (x < 1) + fun_l4_n195(x) + else + fun_l4_n410(x) + end +end + +def fun_l3_n719(x) + if (x < 1) + fun_l4_n862(x) + else + fun_l4_n91(x) + end +end + +def fun_l3_n720(x) + if (x < 1) + fun_l4_n591(x) + else + fun_l4_n391(x) + end +end + +def fun_l3_n721(x) + if (x < 1) + fun_l4_n776(x) + else + fun_l4_n129(x) + end +end + +def fun_l3_n722(x) + if (x < 1) + fun_l4_n857(x) + else + fun_l4_n160(x) + end +end + +def fun_l3_n723(x) + if (x < 1) + fun_l4_n772(x) + else + fun_l4_n567(x) + end +end + +def fun_l3_n724(x) + if (x < 1) + fun_l4_n582(x) + else + fun_l4_n100(x) + end +end + +def fun_l3_n725(x) + if (x < 1) + fun_l4_n962(x) + else + fun_l4_n846(x) + end +end + +def fun_l3_n726(x) + if (x < 1) + fun_l4_n892(x) + else + fun_l4_n334(x) + end +end + +def fun_l3_n727(x) + if (x < 1) + fun_l4_n17(x) + else + fun_l4_n690(x) + end +end + +def fun_l3_n728(x) + if (x < 1) + fun_l4_n453(x) + else + fun_l4_n234(x) + end +end + +def fun_l3_n729(x) + if (x < 1) + fun_l4_n562(x) + else + fun_l4_n139(x) + end +end + +def fun_l3_n730(x) + if (x < 1) + fun_l4_n87(x) + else + fun_l4_n513(x) + end +end + +def fun_l3_n731(x) + if (x < 1) + fun_l4_n565(x) + else + fun_l4_n289(x) + end +end + +def fun_l3_n732(x) + if (x < 1) + fun_l4_n821(x) + else + fun_l4_n290(x) + end +end + +def fun_l3_n733(x) + if (x < 1) + fun_l4_n464(x) + else + fun_l4_n929(x) + end +end + +def fun_l3_n734(x) + if (x < 1) + fun_l4_n617(x) + else + fun_l4_n230(x) + end +end + +def fun_l3_n735(x) + if (x < 1) + fun_l4_n942(x) + else + fun_l4_n770(x) + end +end + +def fun_l3_n736(x) + if (x < 1) + fun_l4_n826(x) + else + fun_l4_n414(x) + end +end + +def fun_l3_n737(x) + if (x < 1) + fun_l4_n47(x) + else + fun_l4_n357(x) + end +end + +def fun_l3_n738(x) + if (x < 1) + fun_l4_n582(x) + else + fun_l4_n652(x) + end +end + +def fun_l3_n739(x) + if (x < 1) + fun_l4_n641(x) + else + fun_l4_n479(x) + end +end + +def fun_l3_n740(x) + if (x < 1) + fun_l4_n11(x) + else + fun_l4_n965(x) + end +end + +def fun_l3_n741(x) + if (x < 1) + fun_l4_n402(x) + else + fun_l4_n512(x) + end +end + +def fun_l3_n742(x) + if (x < 1) + fun_l4_n300(x) + else + fun_l4_n942(x) + end +end + +def fun_l3_n743(x) + if (x < 1) + fun_l4_n770(x) + else + fun_l4_n690(x) + end +end + +def fun_l3_n744(x) + if (x < 1) + fun_l4_n575(x) + else + fun_l4_n158(x) + end +end + +def fun_l3_n745(x) + if (x < 1) + fun_l4_n760(x) + else + fun_l4_n552(x) + end +end + +def fun_l3_n746(x) + if (x < 1) + fun_l4_n887(x) + else + fun_l4_n319(x) + end +end + +def fun_l3_n747(x) + if (x < 1) + fun_l4_n967(x) + else + fun_l4_n561(x) + end +end + +def fun_l3_n748(x) + if (x < 1) + fun_l4_n4(x) + else + fun_l4_n766(x) + end +end + +def fun_l3_n749(x) + if (x < 1) + fun_l4_n993(x) + else + fun_l4_n991(x) + end +end + +def fun_l3_n750(x) + if (x < 1) + fun_l4_n890(x) + else + fun_l4_n663(x) + end +end + +def fun_l3_n751(x) + if (x < 1) + fun_l4_n267(x) + else + fun_l4_n449(x) + end +end + +def fun_l3_n752(x) + if (x < 1) + fun_l4_n540(x) + else + fun_l4_n226(x) + end +end + +def fun_l3_n753(x) + if (x < 1) + fun_l4_n893(x) + else + fun_l4_n116(x) + end +end + +def fun_l3_n754(x) + if (x < 1) + fun_l4_n570(x) + else + fun_l4_n192(x) + end +end + +def fun_l3_n755(x) + if (x < 1) + fun_l4_n712(x) + else + fun_l4_n81(x) + end +end + +def fun_l3_n756(x) + if (x < 1) + fun_l4_n833(x) + else + fun_l4_n24(x) + end +end + +def fun_l3_n757(x) + if (x < 1) + fun_l4_n740(x) + else + fun_l4_n803(x) + end +end + +def fun_l3_n758(x) + if (x < 1) + fun_l4_n552(x) + else + fun_l4_n551(x) + end +end + +def fun_l3_n759(x) + if (x < 1) + fun_l4_n570(x) + else + fun_l4_n677(x) + end +end + +def fun_l3_n760(x) + if (x < 1) + fun_l4_n243(x) + else + fun_l4_n677(x) + end +end + +def fun_l3_n761(x) + if (x < 1) + fun_l4_n65(x) + else + fun_l4_n660(x) + end +end + +def fun_l3_n762(x) + if (x < 1) + fun_l4_n989(x) + else + fun_l4_n761(x) + end +end + +def fun_l3_n763(x) + if (x < 1) + fun_l4_n971(x) + else + fun_l4_n280(x) + end +end + +def fun_l3_n764(x) + if (x < 1) + fun_l4_n441(x) + else + fun_l4_n506(x) + end +end + +def fun_l3_n765(x) + if (x < 1) + fun_l4_n577(x) + else + fun_l4_n586(x) + end +end + +def fun_l3_n766(x) + if (x < 1) + fun_l4_n385(x) + else + fun_l4_n60(x) + end +end + +def fun_l3_n767(x) + if (x < 1) + fun_l4_n380(x) + else + fun_l4_n32(x) + end +end + +def fun_l3_n768(x) + if (x < 1) + fun_l4_n797(x) + else + fun_l4_n437(x) + end +end + +def fun_l3_n769(x) + if (x < 1) + fun_l4_n615(x) + else + fun_l4_n369(x) + end +end + +def fun_l3_n770(x) + if (x < 1) + fun_l4_n779(x) + else + fun_l4_n194(x) + end +end + +def fun_l3_n771(x) + if (x < 1) + fun_l4_n287(x) + else + fun_l4_n819(x) + end +end + +def fun_l3_n772(x) + if (x < 1) + fun_l4_n405(x) + else + fun_l4_n738(x) + end +end + +def fun_l3_n773(x) + if (x < 1) + fun_l4_n706(x) + else + fun_l4_n174(x) + end +end + +def fun_l3_n774(x) + if (x < 1) + fun_l4_n690(x) + else + fun_l4_n841(x) + end +end + +def fun_l3_n775(x) + if (x < 1) + fun_l4_n256(x) + else + fun_l4_n179(x) + end +end + +def fun_l3_n776(x) + if (x < 1) + fun_l4_n342(x) + else + fun_l4_n359(x) + end +end + +def fun_l3_n777(x) + if (x < 1) + fun_l4_n371(x) + else + fun_l4_n680(x) + end +end + +def fun_l3_n778(x) + if (x < 1) + fun_l4_n996(x) + else + fun_l4_n343(x) + end +end + +def fun_l3_n779(x) + if (x < 1) + fun_l4_n96(x) + else + fun_l4_n893(x) + end +end + +def fun_l3_n780(x) + if (x < 1) + fun_l4_n706(x) + else + fun_l4_n140(x) + end +end + +def fun_l3_n781(x) + if (x < 1) + fun_l4_n349(x) + else + fun_l4_n317(x) + end +end + +def fun_l3_n782(x) + if (x < 1) + fun_l4_n491(x) + else + fun_l4_n616(x) + end +end + +def fun_l3_n783(x) + if (x < 1) + fun_l4_n227(x) + else + fun_l4_n356(x) + end +end + +def fun_l3_n784(x) + if (x < 1) + fun_l4_n387(x) + else + fun_l4_n532(x) + end +end + +def fun_l3_n785(x) + if (x < 1) + fun_l4_n648(x) + else + fun_l4_n34(x) + end +end + +def fun_l3_n786(x) + if (x < 1) + fun_l4_n562(x) + else + fun_l4_n476(x) + end +end + +def fun_l3_n787(x) + if (x < 1) + fun_l4_n162(x) + else + fun_l4_n384(x) + end +end + +def fun_l3_n788(x) + if (x < 1) + fun_l4_n221(x) + else + fun_l4_n617(x) + end +end + +def fun_l3_n789(x) + if (x < 1) + fun_l4_n670(x) + else + fun_l4_n350(x) + end +end + +def fun_l3_n790(x) + if (x < 1) + fun_l4_n202(x) + else + fun_l4_n112(x) + end +end + +def fun_l3_n791(x) + if (x < 1) + fun_l4_n390(x) + else + fun_l4_n868(x) + end +end + +def fun_l3_n792(x) + if (x < 1) + fun_l4_n746(x) + else + fun_l4_n833(x) + end +end + +def fun_l3_n793(x) + if (x < 1) + fun_l4_n471(x) + else + fun_l4_n60(x) + end +end + +def fun_l3_n794(x) + if (x < 1) + fun_l4_n583(x) + else + fun_l4_n470(x) + end +end + +def fun_l3_n795(x) + if (x < 1) + fun_l4_n567(x) + else + fun_l4_n218(x) + end +end + +def fun_l3_n796(x) + if (x < 1) + fun_l4_n140(x) + else + fun_l4_n690(x) + end +end + +def fun_l3_n797(x) + if (x < 1) + fun_l4_n190(x) + else + fun_l4_n437(x) + end +end + +def fun_l3_n798(x) + if (x < 1) + fun_l4_n684(x) + else + fun_l4_n843(x) + end +end + +def fun_l3_n799(x) + if (x < 1) + fun_l4_n825(x) + else + fun_l4_n354(x) + end +end + +def fun_l3_n800(x) + if (x < 1) + fun_l4_n711(x) + else + fun_l4_n606(x) + end +end + +def fun_l3_n801(x) + if (x < 1) + fun_l4_n756(x) + else + fun_l4_n464(x) + end +end + +def fun_l3_n802(x) + if (x < 1) + fun_l4_n143(x) + else + fun_l4_n962(x) + end +end + +def fun_l3_n803(x) + if (x < 1) + fun_l4_n223(x) + else + fun_l4_n293(x) + end +end + +def fun_l3_n804(x) + if (x < 1) + fun_l4_n832(x) + else + fun_l4_n632(x) + end +end + +def fun_l3_n805(x) + if (x < 1) + fun_l4_n649(x) + else + fun_l4_n259(x) + end +end + +def fun_l3_n806(x) + if (x < 1) + fun_l4_n617(x) + else + fun_l4_n993(x) + end +end + +def fun_l3_n807(x) + if (x < 1) + fun_l4_n257(x) + else + fun_l4_n712(x) + end +end + +def fun_l3_n808(x) + if (x < 1) + fun_l4_n632(x) + else + fun_l4_n563(x) + end +end + +def fun_l3_n809(x) + if (x < 1) + fun_l4_n154(x) + else + fun_l4_n561(x) + end +end + +def fun_l3_n810(x) + if (x < 1) + fun_l4_n411(x) + else + fun_l4_n42(x) + end +end + +def fun_l3_n811(x) + if (x < 1) + fun_l4_n560(x) + else + fun_l4_n531(x) + end +end + +def fun_l3_n812(x) + if (x < 1) + fun_l4_n759(x) + else + fun_l4_n588(x) + end +end + +def fun_l3_n813(x) + if (x < 1) + fun_l4_n311(x) + else + fun_l4_n813(x) + end +end + +def fun_l3_n814(x) + if (x < 1) + fun_l4_n521(x) + else + fun_l4_n877(x) + end +end + +def fun_l3_n815(x) + if (x < 1) + fun_l4_n578(x) + else + fun_l4_n37(x) + end +end + +def fun_l3_n816(x) + if (x < 1) + fun_l4_n337(x) + else + fun_l4_n562(x) + end +end + +def fun_l3_n817(x) + if (x < 1) + fun_l4_n523(x) + else + fun_l4_n445(x) + end +end + +def fun_l3_n818(x) + if (x < 1) + fun_l4_n256(x) + else + fun_l4_n551(x) + end +end + +def fun_l3_n819(x) + if (x < 1) + fun_l4_n718(x) + else + fun_l4_n463(x) + end +end + +def fun_l3_n820(x) + if (x < 1) + fun_l4_n780(x) + else + fun_l4_n103(x) + end +end + +def fun_l3_n821(x) + if (x < 1) + fun_l4_n729(x) + else + fun_l4_n331(x) + end +end + +def fun_l3_n822(x) + if (x < 1) + fun_l4_n84(x) + else + fun_l4_n176(x) + end +end + +def fun_l3_n823(x) + if (x < 1) + fun_l4_n231(x) + else + fun_l4_n681(x) + end +end + +def fun_l3_n824(x) + if (x < 1) + fun_l4_n675(x) + else + fun_l4_n837(x) + end +end + +def fun_l3_n825(x) + if (x < 1) + fun_l4_n140(x) + else + fun_l4_n932(x) + end +end + +def fun_l3_n826(x) + if (x < 1) + fun_l4_n268(x) + else + fun_l4_n908(x) + end +end + +def fun_l3_n827(x) + if (x < 1) + fun_l4_n959(x) + else + fun_l4_n643(x) + end +end + +def fun_l3_n828(x) + if (x < 1) + fun_l4_n290(x) + else + fun_l4_n718(x) + end +end + +def fun_l3_n829(x) + if (x < 1) + fun_l4_n430(x) + else + fun_l4_n114(x) + end +end + +def fun_l3_n830(x) + if (x < 1) + fun_l4_n817(x) + else + fun_l4_n296(x) + end +end + +def fun_l3_n831(x) + if (x < 1) + fun_l4_n586(x) + else + fun_l4_n345(x) + end +end + +def fun_l3_n832(x) + if (x < 1) + fun_l4_n321(x) + else + fun_l4_n805(x) + end +end + +def fun_l3_n833(x) + if (x < 1) + fun_l4_n57(x) + else + fun_l4_n373(x) + end +end + +def fun_l3_n834(x) + if (x < 1) + fun_l4_n344(x) + else + fun_l4_n654(x) + end +end + +def fun_l3_n835(x) + if (x < 1) + fun_l4_n761(x) + else + fun_l4_n295(x) + end +end + +def fun_l3_n836(x) + if (x < 1) + fun_l4_n169(x) + else + fun_l4_n184(x) + end +end + +def fun_l3_n837(x) + if (x < 1) + fun_l4_n482(x) + else + fun_l4_n127(x) + end +end + +def fun_l3_n838(x) + if (x < 1) + fun_l4_n260(x) + else + fun_l4_n662(x) + end +end + +def fun_l3_n839(x) + if (x < 1) + fun_l4_n548(x) + else + fun_l4_n197(x) + end +end + +def fun_l3_n840(x) + if (x < 1) + fun_l4_n96(x) + else + fun_l4_n17(x) + end +end + +def fun_l3_n841(x) + if (x < 1) + fun_l4_n946(x) + else + fun_l4_n447(x) + end +end + +def fun_l3_n842(x) + if (x < 1) + fun_l4_n66(x) + else + fun_l4_n110(x) + end +end + +def fun_l3_n843(x) + if (x < 1) + fun_l4_n574(x) + else + fun_l4_n887(x) + end +end + +def fun_l3_n844(x) + if (x < 1) + fun_l4_n912(x) + else + fun_l4_n465(x) + end +end + +def fun_l3_n845(x) + if (x < 1) + fun_l4_n401(x) + else + fun_l4_n903(x) + end +end + +def fun_l3_n846(x) + if (x < 1) + fun_l4_n929(x) + else + fun_l4_n238(x) + end +end + +def fun_l3_n847(x) + if (x < 1) + fun_l4_n579(x) + else + fun_l4_n924(x) + end +end + +def fun_l3_n848(x) + if (x < 1) + fun_l4_n697(x) + else + fun_l4_n157(x) + end +end + +def fun_l3_n849(x) + if (x < 1) + fun_l4_n608(x) + else + fun_l4_n426(x) + end +end + +def fun_l3_n850(x) + if (x < 1) + fun_l4_n710(x) + else + fun_l4_n360(x) + end +end + +def fun_l3_n851(x) + if (x < 1) + fun_l4_n558(x) + else + fun_l4_n152(x) + end +end + +def fun_l3_n852(x) + if (x < 1) + fun_l4_n276(x) + else + fun_l4_n895(x) + end +end + +def fun_l3_n853(x) + if (x < 1) + fun_l4_n945(x) + else + fun_l4_n251(x) + end +end + +def fun_l3_n854(x) + if (x < 1) + fun_l4_n131(x) + else + fun_l4_n677(x) + end +end + +def fun_l3_n855(x) + if (x < 1) + fun_l4_n493(x) + else + fun_l4_n631(x) + end +end + +def fun_l3_n856(x) + if (x < 1) + fun_l4_n608(x) + else + fun_l4_n556(x) + end +end + +def fun_l3_n857(x) + if (x < 1) + fun_l4_n808(x) + else + fun_l4_n672(x) + end +end + +def fun_l3_n858(x) + if (x < 1) + fun_l4_n407(x) + else + fun_l4_n648(x) + end +end + +def fun_l3_n859(x) + if (x < 1) + fun_l4_n217(x) + else + fun_l4_n763(x) + end +end + +def fun_l3_n860(x) + if (x < 1) + fun_l4_n941(x) + else + fun_l4_n159(x) + end +end + +def fun_l3_n861(x) + if (x < 1) + fun_l4_n364(x) + else + fun_l4_n241(x) + end +end + +def fun_l3_n862(x) + if (x < 1) + fun_l4_n915(x) + else + fun_l4_n729(x) + end +end + +def fun_l3_n863(x) + if (x < 1) + fun_l4_n137(x) + else + fun_l4_n317(x) + end +end + +def fun_l3_n864(x) + if (x < 1) + fun_l4_n818(x) + else + fun_l4_n782(x) + end +end + +def fun_l3_n865(x) + if (x < 1) + fun_l4_n577(x) + else + fun_l4_n418(x) + end +end + +def fun_l3_n866(x) + if (x < 1) + fun_l4_n882(x) + else + fun_l4_n7(x) + end +end + +def fun_l3_n867(x) + if (x < 1) + fun_l4_n238(x) + else + fun_l4_n944(x) + end +end + +def fun_l3_n868(x) + if (x < 1) + fun_l4_n105(x) + else + fun_l4_n465(x) + end +end + +def fun_l3_n869(x) + if (x < 1) + fun_l4_n841(x) + else + fun_l4_n262(x) + end +end + +def fun_l3_n870(x) + if (x < 1) + fun_l4_n32(x) + else + fun_l4_n992(x) + end +end + +def fun_l3_n871(x) + if (x < 1) + fun_l4_n431(x) + else + fun_l4_n391(x) + end +end + +def fun_l3_n872(x) + if (x < 1) + fun_l4_n829(x) + else + fun_l4_n879(x) + end +end + +def fun_l3_n873(x) + if (x < 1) + fun_l4_n617(x) + else + fun_l4_n657(x) + end +end + +def fun_l3_n874(x) + if (x < 1) + fun_l4_n529(x) + else + fun_l4_n717(x) + end +end + +def fun_l3_n875(x) + if (x < 1) + fun_l4_n928(x) + else + fun_l4_n476(x) + end +end + +def fun_l3_n876(x) + if (x < 1) + fun_l4_n388(x) + else + fun_l4_n949(x) + end +end + +def fun_l3_n877(x) + if (x < 1) + fun_l4_n826(x) + else + fun_l4_n560(x) + end +end + +def fun_l3_n878(x) + if (x < 1) + fun_l4_n863(x) + else + fun_l4_n122(x) + end +end + +def fun_l3_n879(x) + if (x < 1) + fun_l4_n964(x) + else + fun_l4_n793(x) + end +end + +def fun_l3_n880(x) + if (x < 1) + fun_l4_n141(x) + else + fun_l4_n132(x) + end +end + +def fun_l3_n881(x) + if (x < 1) + fun_l4_n735(x) + else + fun_l4_n592(x) + end +end + +def fun_l3_n882(x) + if (x < 1) + fun_l4_n585(x) + else + fun_l4_n341(x) + end +end + +def fun_l3_n883(x) + if (x < 1) + fun_l4_n843(x) + else + fun_l4_n692(x) + end +end + +def fun_l3_n884(x) + if (x < 1) + fun_l4_n360(x) + else + fun_l4_n833(x) + end +end + +def fun_l3_n885(x) + if (x < 1) + fun_l4_n31(x) + else + fun_l4_n62(x) + end +end + +def fun_l3_n886(x) + if (x < 1) + fun_l4_n756(x) + else + fun_l4_n699(x) + end +end + +def fun_l3_n887(x) + if (x < 1) + fun_l4_n71(x) + else + fun_l4_n256(x) + end +end + +def fun_l3_n888(x) + if (x < 1) + fun_l4_n406(x) + else + fun_l4_n493(x) + end +end + +def fun_l3_n889(x) + if (x < 1) + fun_l4_n489(x) + else + fun_l4_n874(x) + end +end + +def fun_l3_n890(x) + if (x < 1) + fun_l4_n365(x) + else + fun_l4_n910(x) + end +end + +def fun_l3_n891(x) + if (x < 1) + fun_l4_n262(x) + else + fun_l4_n665(x) + end +end + +def fun_l3_n892(x) + if (x < 1) + fun_l4_n274(x) + else + fun_l4_n849(x) + end +end + +def fun_l3_n893(x) + if (x < 1) + fun_l4_n880(x) + else + fun_l4_n739(x) + end +end + +def fun_l3_n894(x) + if (x < 1) + fun_l4_n504(x) + else + fun_l4_n128(x) + end +end + +def fun_l3_n895(x) + if (x < 1) + fun_l4_n555(x) + else + fun_l4_n281(x) + end +end + +def fun_l3_n896(x) + if (x < 1) + fun_l4_n270(x) + else + fun_l4_n225(x) + end +end + +def fun_l3_n897(x) + if (x < 1) + fun_l4_n38(x) + else + fun_l4_n26(x) + end +end + +def fun_l3_n898(x) + if (x < 1) + fun_l4_n944(x) + else + fun_l4_n217(x) + end +end + +def fun_l3_n899(x) + if (x < 1) + fun_l4_n967(x) + else + fun_l4_n853(x) + end +end + +def fun_l3_n900(x) + if (x < 1) + fun_l4_n686(x) + else + fun_l4_n760(x) + end +end + +def fun_l3_n901(x) + if (x < 1) + fun_l4_n698(x) + else + fun_l4_n842(x) + end +end + +def fun_l3_n902(x) + if (x < 1) + fun_l4_n344(x) + else + fun_l4_n701(x) + end +end + +def fun_l3_n903(x) + if (x < 1) + fun_l4_n756(x) + else + fun_l4_n321(x) + end +end + +def fun_l3_n904(x) + if (x < 1) + fun_l4_n504(x) + else + fun_l4_n228(x) + end +end + +def fun_l3_n905(x) + if (x < 1) + fun_l4_n135(x) + else + fun_l4_n57(x) + end +end + +def fun_l3_n906(x) + if (x < 1) + fun_l4_n279(x) + else + fun_l4_n912(x) + end +end + +def fun_l3_n907(x) + if (x < 1) + fun_l4_n962(x) + else + fun_l4_n418(x) + end +end + +def fun_l3_n908(x) + if (x < 1) + fun_l4_n972(x) + else + fun_l4_n14(x) + end +end + +def fun_l3_n909(x) + if (x < 1) + fun_l4_n231(x) + else + fun_l4_n763(x) + end +end + +def fun_l3_n910(x) + if (x < 1) + fun_l4_n859(x) + else + fun_l4_n243(x) + end +end + +def fun_l3_n911(x) + if (x < 1) + fun_l4_n153(x) + else + fun_l4_n136(x) + end +end + +def fun_l3_n912(x) + if (x < 1) + fun_l4_n325(x) + else + fun_l4_n113(x) + end +end + +def fun_l3_n913(x) + if (x < 1) + fun_l4_n625(x) + else + fun_l4_n179(x) + end +end + +def fun_l3_n914(x) + if (x < 1) + fun_l4_n54(x) + else + fun_l4_n88(x) + end +end + +def fun_l3_n915(x) + if (x < 1) + fun_l4_n332(x) + else + fun_l4_n3(x) + end +end + +def fun_l3_n916(x) + if (x < 1) + fun_l4_n748(x) + else + fun_l4_n21(x) + end +end + +def fun_l3_n917(x) + if (x < 1) + fun_l4_n132(x) + else + fun_l4_n132(x) + end +end + +def fun_l3_n918(x) + if (x < 1) + fun_l4_n295(x) + else + fun_l4_n429(x) + end +end + +def fun_l3_n919(x) + if (x < 1) + fun_l4_n105(x) + else + fun_l4_n984(x) + end +end + +def fun_l3_n920(x) + if (x < 1) + fun_l4_n319(x) + else + fun_l4_n304(x) + end +end + +def fun_l3_n921(x) + if (x < 1) + fun_l4_n756(x) + else + fun_l4_n639(x) + end +end + +def fun_l3_n922(x) + if (x < 1) + fun_l4_n678(x) + else + fun_l4_n209(x) + end +end + +def fun_l3_n923(x) + if (x < 1) + fun_l4_n755(x) + else + fun_l4_n941(x) + end +end + +def fun_l3_n924(x) + if (x < 1) + fun_l4_n311(x) + else + fun_l4_n272(x) + end +end + +def fun_l3_n925(x) + if (x < 1) + fun_l4_n543(x) + else + fun_l4_n896(x) + end +end + +def fun_l3_n926(x) + if (x < 1) + fun_l4_n994(x) + else + fun_l4_n671(x) + end +end + +def fun_l3_n927(x) + if (x < 1) + fun_l4_n125(x) + else + fun_l4_n852(x) + end +end + +def fun_l3_n928(x) + if (x < 1) + fun_l4_n483(x) + else + fun_l4_n350(x) + end +end + +def fun_l3_n929(x) + if (x < 1) + fun_l4_n622(x) + else + fun_l4_n511(x) + end +end + +def fun_l3_n930(x) + if (x < 1) + fun_l4_n134(x) + else + fun_l4_n288(x) + end +end + +def fun_l3_n931(x) + if (x < 1) + fun_l4_n278(x) + else + fun_l4_n800(x) + end +end + +def fun_l3_n932(x) + if (x < 1) + fun_l4_n139(x) + else + fun_l4_n966(x) + end +end + +def fun_l3_n933(x) + if (x < 1) + fun_l4_n275(x) + else + fun_l4_n506(x) + end +end + +def fun_l3_n934(x) + if (x < 1) + fun_l4_n503(x) + else + fun_l4_n204(x) + end +end + +def fun_l3_n935(x) + if (x < 1) + fun_l4_n993(x) + else + fun_l4_n126(x) + end +end + +def fun_l3_n936(x) + if (x < 1) + fun_l4_n704(x) + else + fun_l4_n462(x) + end +end + +def fun_l3_n937(x) + if (x < 1) + fun_l4_n922(x) + else + fun_l4_n722(x) + end +end + +def fun_l3_n938(x) + if (x < 1) + fun_l4_n937(x) + else + fun_l4_n195(x) + end +end + +def fun_l3_n939(x) + if (x < 1) + fun_l4_n661(x) + else + fun_l4_n265(x) + end +end + +def fun_l3_n940(x) + if (x < 1) + fun_l4_n423(x) + else + fun_l4_n230(x) + end +end + +def fun_l3_n941(x) + if (x < 1) + fun_l4_n698(x) + else + fun_l4_n226(x) + end +end + +def fun_l3_n942(x) + if (x < 1) + fun_l4_n501(x) + else + fun_l4_n816(x) + end +end + +def fun_l3_n943(x) + if (x < 1) + fun_l4_n650(x) + else + fun_l4_n925(x) + end +end + +def fun_l3_n944(x) + if (x < 1) + fun_l4_n829(x) + else + fun_l4_n647(x) + end +end + +def fun_l3_n945(x) + if (x < 1) + fun_l4_n401(x) + else + fun_l4_n791(x) + end +end + +def fun_l3_n946(x) + if (x < 1) + fun_l4_n551(x) + else + fun_l4_n104(x) + end +end + +def fun_l3_n947(x) + if (x < 1) + fun_l4_n927(x) + else + fun_l4_n213(x) + end +end + +def fun_l3_n948(x) + if (x < 1) + fun_l4_n912(x) + else + fun_l4_n609(x) + end +end + +def fun_l3_n949(x) + if (x < 1) + fun_l4_n302(x) + else + fun_l4_n157(x) + end +end + +def fun_l3_n950(x) + if (x < 1) + fun_l4_n955(x) + else + fun_l4_n492(x) + end +end + +def fun_l3_n951(x) + if (x < 1) + fun_l4_n486(x) + else + fun_l4_n412(x) + end +end + +def fun_l3_n952(x) + if (x < 1) + fun_l4_n850(x) + else + fun_l4_n885(x) + end +end + +def fun_l3_n953(x) + if (x < 1) + fun_l4_n84(x) + else + fun_l4_n622(x) + end +end + +def fun_l3_n954(x) + if (x < 1) + fun_l4_n235(x) + else + fun_l4_n67(x) + end +end + +def fun_l3_n955(x) + if (x < 1) + fun_l4_n347(x) + else + fun_l4_n757(x) + end +end + +def fun_l3_n956(x) + if (x < 1) + fun_l4_n825(x) + else + fun_l4_n10(x) + end +end + +def fun_l3_n957(x) + if (x < 1) + fun_l4_n393(x) + else + fun_l4_n482(x) + end +end + +def fun_l3_n958(x) + if (x < 1) + fun_l4_n0(x) + else + fun_l4_n556(x) + end +end + +def fun_l3_n959(x) + if (x < 1) + fun_l4_n806(x) + else + fun_l4_n783(x) + end +end + +def fun_l3_n960(x) + if (x < 1) + fun_l4_n964(x) + else + fun_l4_n843(x) + end +end + +def fun_l3_n961(x) + if (x < 1) + fun_l4_n508(x) + else + fun_l4_n874(x) + end +end + +def fun_l3_n962(x) + if (x < 1) + fun_l4_n15(x) + else + fun_l4_n197(x) + end +end + +def fun_l3_n963(x) + if (x < 1) + fun_l4_n989(x) + else + fun_l4_n380(x) + end +end + +def fun_l3_n964(x) + if (x < 1) + fun_l4_n315(x) + else + fun_l4_n196(x) + end +end + +def fun_l3_n965(x) + if (x < 1) + fun_l4_n510(x) + else + fun_l4_n275(x) + end +end + +def fun_l3_n966(x) + if (x < 1) + fun_l4_n725(x) + else + fun_l4_n94(x) + end +end + +def fun_l3_n967(x) + if (x < 1) + fun_l4_n733(x) + else + fun_l4_n577(x) + end +end + +def fun_l3_n968(x) + if (x < 1) + fun_l4_n280(x) + else + fun_l4_n702(x) + end +end + +def fun_l3_n969(x) + if (x < 1) + fun_l4_n41(x) + else + fun_l4_n343(x) + end +end + +def fun_l3_n970(x) + if (x < 1) + fun_l4_n102(x) + else + fun_l4_n785(x) + end +end + +def fun_l3_n971(x) + if (x < 1) + fun_l4_n460(x) + else + fun_l4_n388(x) + end +end + +def fun_l3_n972(x) + if (x < 1) + fun_l4_n31(x) + else + fun_l4_n421(x) + end +end + +def fun_l3_n973(x) + if (x < 1) + fun_l4_n587(x) + else + fun_l4_n401(x) + end +end + +def fun_l3_n974(x) + if (x < 1) + fun_l4_n593(x) + else + fun_l4_n418(x) + end +end + +def fun_l3_n975(x) + if (x < 1) + fun_l4_n12(x) + else + fun_l4_n929(x) + end +end + +def fun_l3_n976(x) + if (x < 1) + fun_l4_n516(x) + else + fun_l4_n402(x) + end +end + +def fun_l3_n977(x) + if (x < 1) + fun_l4_n590(x) + else + fun_l4_n876(x) + end +end + +def fun_l3_n978(x) + if (x < 1) + fun_l4_n505(x) + else + fun_l4_n94(x) + end +end + +def fun_l3_n979(x) + if (x < 1) + fun_l4_n625(x) + else + fun_l4_n344(x) + end +end + +def fun_l3_n980(x) + if (x < 1) + fun_l4_n128(x) + else + fun_l4_n454(x) + end +end + +def fun_l3_n981(x) + if (x < 1) + fun_l4_n937(x) + else + fun_l4_n277(x) + end +end + +def fun_l3_n982(x) + if (x < 1) + fun_l4_n237(x) + else + fun_l4_n113(x) + end +end + +def fun_l3_n983(x) + if (x < 1) + fun_l4_n668(x) + else + fun_l4_n668(x) + end +end + +def fun_l3_n984(x) + if (x < 1) + fun_l4_n783(x) + else + fun_l4_n771(x) + end +end + +def fun_l3_n985(x) + if (x < 1) + fun_l4_n135(x) + else + fun_l4_n967(x) + end +end + +def fun_l3_n986(x) + if (x < 1) + fun_l4_n29(x) + else + fun_l4_n313(x) + end +end + +def fun_l3_n987(x) + if (x < 1) + fun_l4_n765(x) + else + fun_l4_n885(x) + end +end + +def fun_l3_n988(x) + if (x < 1) + fun_l4_n242(x) + else + fun_l4_n622(x) + end +end + +def fun_l3_n989(x) + if (x < 1) + fun_l4_n916(x) + else + fun_l4_n518(x) + end +end + +def fun_l3_n990(x) + if (x < 1) + fun_l4_n523(x) + else + fun_l4_n468(x) + end +end + +def fun_l3_n991(x) + if (x < 1) + fun_l4_n904(x) + else + fun_l4_n601(x) + end +end + +def fun_l3_n992(x) + if (x < 1) + fun_l4_n437(x) + else + fun_l4_n77(x) + end +end + +def fun_l3_n993(x) + if (x < 1) + fun_l4_n957(x) + else + fun_l4_n619(x) + end +end + +def fun_l3_n994(x) + if (x < 1) + fun_l4_n540(x) + else + fun_l4_n108(x) + end +end + +def fun_l3_n995(x) + if (x < 1) + fun_l4_n8(x) + else + fun_l4_n428(x) + end +end + +def fun_l3_n996(x) + if (x < 1) + fun_l4_n53(x) + else + fun_l4_n278(x) + end +end + +def fun_l3_n997(x) + if (x < 1) + fun_l4_n930(x) + else + fun_l4_n671(x) + end +end + +def fun_l3_n998(x) + if (x < 1) + fun_l4_n574(x) + else + fun_l4_n879(x) + end +end + +def fun_l3_n999(x) + if (x < 1) + fun_l4_n316(x) + else + fun_l4_n93(x) + end +end + +def fun_l4_n0(x) + if (x < 1) + fun_l5_n524(x) + else + fun_l5_n284(x) + end +end + +def fun_l4_n1(x) + if (x < 1) + fun_l5_n845(x) + else + fun_l5_n863(x) + end +end + +def fun_l4_n2(x) + if (x < 1) + fun_l5_n258(x) + else + fun_l5_n860(x) + end +end + +def fun_l4_n3(x) + if (x < 1) + fun_l5_n253(x) + else + fun_l5_n763(x) + end +end + +def fun_l4_n4(x) + if (x < 1) + fun_l5_n833(x) + else + fun_l5_n807(x) + end +end + +def fun_l4_n5(x) + if (x < 1) + fun_l5_n890(x) + else + fun_l5_n669(x) + end +end + +def fun_l4_n6(x) + if (x < 1) + fun_l5_n396(x) + else + fun_l5_n388(x) + end +end + +def fun_l4_n7(x) + if (x < 1) + fun_l5_n926(x) + else + fun_l5_n661(x) + end +end + +def fun_l4_n8(x) + if (x < 1) + fun_l5_n990(x) + else + fun_l5_n765(x) + end +end + +def fun_l4_n9(x) + if (x < 1) + fun_l5_n978(x) + else + fun_l5_n342(x) + end +end + +def fun_l4_n10(x) + if (x < 1) + fun_l5_n500(x) + else + fun_l5_n758(x) + end +end + +def fun_l4_n11(x) + if (x < 1) + fun_l5_n10(x) + else + fun_l5_n796(x) + end +end + +def fun_l4_n12(x) + if (x < 1) + fun_l5_n173(x) + else + fun_l5_n87(x) + end +end + +def fun_l4_n13(x) + if (x < 1) + fun_l5_n852(x) + else + fun_l5_n93(x) + end +end + +def fun_l4_n14(x) + if (x < 1) + fun_l5_n526(x) + else + fun_l5_n144(x) + end +end + +def fun_l4_n15(x) + if (x < 1) + fun_l5_n398(x) + else + fun_l5_n632(x) + end +end + +def fun_l4_n16(x) + if (x < 1) + fun_l5_n774(x) + else + fun_l5_n716(x) + end +end + +def fun_l4_n17(x) + if (x < 1) + fun_l5_n412(x) + else + fun_l5_n95(x) + end +end + +def fun_l4_n18(x) + if (x < 1) + fun_l5_n446(x) + else + fun_l5_n885(x) + end +end + +def fun_l4_n19(x) + if (x < 1) + fun_l5_n420(x) + else + fun_l5_n420(x) + end +end + +def fun_l4_n20(x) + if (x < 1) + fun_l5_n274(x) + else + fun_l5_n813(x) + end +end + +def fun_l4_n21(x) + if (x < 1) + fun_l5_n174(x) + else + fun_l5_n781(x) + end +end + +def fun_l4_n22(x) + if (x < 1) + fun_l5_n903(x) + else + fun_l5_n224(x) + end +end + +def fun_l4_n23(x) + if (x < 1) + fun_l5_n317(x) + else + fun_l5_n900(x) + end +end + +def fun_l4_n24(x) + if (x < 1) + fun_l5_n600(x) + else + fun_l5_n515(x) + end +end + +def fun_l4_n25(x) + if (x < 1) + fun_l5_n151(x) + else + fun_l5_n790(x) + end +end + +def fun_l4_n26(x) + if (x < 1) + fun_l5_n256(x) + else + fun_l5_n449(x) + end +end + +def fun_l4_n27(x) + if (x < 1) + fun_l5_n985(x) + else + fun_l5_n763(x) + end +end + +def fun_l4_n28(x) + if (x < 1) + fun_l5_n961(x) + else + fun_l5_n86(x) + end +end + +def fun_l4_n29(x) + if (x < 1) + fun_l5_n359(x) + else + fun_l5_n894(x) + end +end + +def fun_l4_n30(x) + if (x < 1) + fun_l5_n426(x) + else + fun_l5_n983(x) + end +end + +def fun_l4_n31(x) + if (x < 1) + fun_l5_n996(x) + else + fun_l5_n343(x) + end +end + +def fun_l4_n32(x) + if (x < 1) + fun_l5_n300(x) + else + fun_l5_n719(x) + end +end + +def fun_l4_n33(x) + if (x < 1) + fun_l5_n755(x) + else + fun_l5_n623(x) + end +end + +def fun_l4_n34(x) + if (x < 1) + fun_l5_n681(x) + else + fun_l5_n410(x) + end +end + +def fun_l4_n35(x) + if (x < 1) + fun_l5_n356(x) + else + fun_l5_n351(x) + end +end + +def fun_l4_n36(x) + if (x < 1) + fun_l5_n463(x) + else + fun_l5_n402(x) + end +end + +def fun_l4_n37(x) + if (x < 1) + fun_l5_n250(x) + else + fun_l5_n681(x) + end +end + +def fun_l4_n38(x) + if (x < 1) + fun_l5_n573(x) + else + fun_l5_n622(x) + end +end + +def fun_l4_n39(x) + if (x < 1) + fun_l5_n545(x) + else + fun_l5_n210(x) + end +end + +def fun_l4_n40(x) + if (x < 1) + fun_l5_n264(x) + else + fun_l5_n239(x) + end +end + +def fun_l4_n41(x) + if (x < 1) + fun_l5_n635(x) + else + fun_l5_n224(x) + end +end + +def fun_l4_n42(x) + if (x < 1) + fun_l5_n806(x) + else + fun_l5_n125(x) + end +end + +def fun_l4_n43(x) + if (x < 1) + fun_l5_n480(x) + else + fun_l5_n625(x) + end +end + +def fun_l4_n44(x) + if (x < 1) + fun_l5_n644(x) + else + fun_l5_n465(x) + end +end + +def fun_l4_n45(x) + if (x < 1) + fun_l5_n999(x) + else + fun_l5_n759(x) + end +end + +def fun_l4_n46(x) + if (x < 1) + fun_l5_n866(x) + else + fun_l5_n536(x) + end +end + +def fun_l4_n47(x) + if (x < 1) + fun_l5_n328(x) + else + fun_l5_n533(x) + end +end + +def fun_l4_n48(x) + if (x < 1) + fun_l5_n902(x) + else + fun_l5_n919(x) + end +end + +def fun_l4_n49(x) + if (x < 1) + fun_l5_n197(x) + else + fun_l5_n262(x) + end +end + +def fun_l4_n50(x) + if (x < 1) + fun_l5_n172(x) + else + fun_l5_n731(x) + end +end + +def fun_l4_n51(x) + if (x < 1) + fun_l5_n502(x) + else + fun_l5_n149(x) + end +end + +def fun_l4_n52(x) + if (x < 1) + fun_l5_n69(x) + else + fun_l5_n536(x) + end +end + +def fun_l4_n53(x) + if (x < 1) + fun_l5_n932(x) + else + fun_l5_n482(x) + end +end + +def fun_l4_n54(x) + if (x < 1) + fun_l5_n982(x) + else + fun_l5_n207(x) + end +end + +def fun_l4_n55(x) + if (x < 1) + fun_l5_n949(x) + else + fun_l5_n9(x) + end +end + +def fun_l4_n56(x) + if (x < 1) + fun_l5_n672(x) + else + fun_l5_n924(x) + end +end + +def fun_l4_n57(x) + if (x < 1) + fun_l5_n757(x) + else + fun_l5_n609(x) + end +end + +def fun_l4_n58(x) + if (x < 1) + fun_l5_n251(x) + else + fun_l5_n471(x) + end +end + +def fun_l4_n59(x) + if (x < 1) + fun_l5_n878(x) + else + fun_l5_n626(x) + end +end + +def fun_l4_n60(x) + if (x < 1) + fun_l5_n859(x) + else + fun_l5_n646(x) + end +end + +def fun_l4_n61(x) + if (x < 1) + fun_l5_n417(x) + else + fun_l5_n587(x) + end +end + +def fun_l4_n62(x) + if (x < 1) + fun_l5_n164(x) + else + fun_l5_n861(x) + end +end + +def fun_l4_n63(x) + if (x < 1) + fun_l5_n591(x) + else + fun_l5_n79(x) + end +end + +def fun_l4_n64(x) + if (x < 1) + fun_l5_n269(x) + else + fun_l5_n336(x) + end +end + +def fun_l4_n65(x) + if (x < 1) + fun_l5_n420(x) + else + fun_l5_n557(x) + end +end + +def fun_l4_n66(x) + if (x < 1) + fun_l5_n61(x) + else + fun_l5_n690(x) + end +end + +def fun_l4_n67(x) + if (x < 1) + fun_l5_n939(x) + else + fun_l5_n139(x) + end +end + +def fun_l4_n68(x) + if (x < 1) + fun_l5_n430(x) + else + fun_l5_n625(x) + end +end + +def fun_l4_n69(x) + if (x < 1) + fun_l5_n532(x) + else + fun_l5_n909(x) + end +end + +def fun_l4_n70(x) + if (x < 1) + fun_l5_n937(x) + else + fun_l5_n886(x) + end +end + +def fun_l4_n71(x) + if (x < 1) + fun_l5_n554(x) + else + fun_l5_n898(x) + end +end + +def fun_l4_n72(x) + if (x < 1) + fun_l5_n390(x) + else + fun_l5_n690(x) + end +end + +def fun_l4_n73(x) + if (x < 1) + fun_l5_n980(x) + else + fun_l5_n248(x) + end +end + +def fun_l4_n74(x) + if (x < 1) + fun_l5_n438(x) + else + fun_l5_n247(x) + end +end + +def fun_l4_n75(x) + if (x < 1) + fun_l5_n798(x) + else + fun_l5_n399(x) + end +end + +def fun_l4_n76(x) + if (x < 1) + fun_l5_n419(x) + else + fun_l5_n754(x) + end +end + +def fun_l4_n77(x) + if (x < 1) + fun_l5_n875(x) + else + fun_l5_n18(x) + end +end + +def fun_l4_n78(x) + if (x < 1) + fun_l5_n695(x) + else + fun_l5_n336(x) + end +end + +def fun_l4_n79(x) + if (x < 1) + fun_l5_n185(x) + else + fun_l5_n627(x) + end +end + +def fun_l4_n80(x) + if (x < 1) + fun_l5_n359(x) + else + fun_l5_n465(x) + end +end + +def fun_l4_n81(x) + if (x < 1) + fun_l5_n284(x) + else + fun_l5_n232(x) + end +end + +def fun_l4_n82(x) + if (x < 1) + fun_l5_n947(x) + else + fun_l5_n748(x) + end +end + +def fun_l4_n83(x) + if (x < 1) + fun_l5_n254(x) + else + fun_l5_n836(x) + end +end + +def fun_l4_n84(x) + if (x < 1) + fun_l5_n181(x) + else + fun_l5_n789(x) + end +end + +def fun_l4_n85(x) + if (x < 1) + fun_l5_n682(x) + else + fun_l5_n547(x) + end +end + +def fun_l4_n86(x) + if (x < 1) + fun_l5_n35(x) + else + fun_l5_n157(x) + end +end + +def fun_l4_n87(x) + if (x < 1) + fun_l5_n981(x) + else + fun_l5_n724(x) + end +end + +def fun_l4_n88(x) + if (x < 1) + fun_l5_n35(x) + else + fun_l5_n914(x) + end +end + +def fun_l4_n89(x) + if (x < 1) + fun_l5_n844(x) + else + fun_l5_n668(x) + end +end + +def fun_l4_n90(x) + if (x < 1) + fun_l5_n615(x) + else + fun_l5_n415(x) + end +end + +def fun_l4_n91(x) + if (x < 1) + fun_l5_n141(x) + else + fun_l5_n538(x) + end +end + +def fun_l4_n92(x) + if (x < 1) + fun_l5_n563(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n93(x) + if (x < 1) + fun_l5_n967(x) + else + fun_l5_n549(x) + end +end + +def fun_l4_n94(x) + if (x < 1) + fun_l5_n992(x) + else + fun_l5_n34(x) + end +end + +def fun_l4_n95(x) + if (x < 1) + fun_l5_n187(x) + else + fun_l5_n980(x) + end +end + +def fun_l4_n96(x) + if (x < 1) + fun_l5_n543(x) + else + fun_l5_n318(x) + end +end + +def fun_l4_n97(x) + if (x < 1) + fun_l5_n253(x) + else + fun_l5_n709(x) + end +end + +def fun_l4_n98(x) + if (x < 1) + fun_l5_n233(x) + else + fun_l5_n963(x) + end +end + +def fun_l4_n99(x) + if (x < 1) + fun_l5_n944(x) + else + fun_l5_n688(x) + end +end + +def fun_l4_n100(x) + if (x < 1) + fun_l5_n422(x) + else + fun_l5_n805(x) + end +end + +def fun_l4_n101(x) + if (x < 1) + fun_l5_n125(x) + else + fun_l5_n729(x) + end +end + +def fun_l4_n102(x) + if (x < 1) + fun_l5_n339(x) + else + fun_l5_n394(x) + end +end + +def fun_l4_n103(x) + if (x < 1) + fun_l5_n149(x) + else + fun_l5_n839(x) + end +end + +def fun_l4_n104(x) + if (x < 1) + fun_l5_n750(x) + else + fun_l5_n514(x) + end +end + +def fun_l4_n105(x) + if (x < 1) + fun_l5_n726(x) + else + fun_l5_n251(x) + end +end + +def fun_l4_n106(x) + if (x < 1) + fun_l5_n810(x) + else + fun_l5_n46(x) + end +end + +def fun_l4_n107(x) + if (x < 1) + fun_l5_n702(x) + else + fun_l5_n224(x) + end +end + +def fun_l4_n108(x) + if (x < 1) + fun_l5_n604(x) + else + fun_l5_n24(x) + end +end + +def fun_l4_n109(x) + if (x < 1) + fun_l5_n511(x) + else + fun_l5_n529(x) + end +end + +def fun_l4_n110(x) + if (x < 1) + fun_l5_n193(x) + else + fun_l5_n210(x) + end +end + +def fun_l4_n111(x) + if (x < 1) + fun_l5_n599(x) + else + fun_l5_n85(x) + end +end + +def fun_l4_n112(x) + if (x < 1) + fun_l5_n910(x) + else + fun_l5_n292(x) + end +end + +def fun_l4_n113(x) + if (x < 1) + fun_l5_n851(x) + else + fun_l5_n269(x) + end +end + +def fun_l4_n114(x) + if (x < 1) + fun_l5_n739(x) + else + fun_l5_n439(x) + end +end + +def fun_l4_n115(x) + if (x < 1) + fun_l5_n580(x) + else + fun_l5_n656(x) + end +end + +def fun_l4_n116(x) + if (x < 1) + fun_l5_n992(x) + else + fun_l5_n703(x) + end +end + +def fun_l4_n117(x) + if (x < 1) + fun_l5_n549(x) + else + fun_l5_n300(x) + end +end + +def fun_l4_n118(x) + if (x < 1) + fun_l5_n785(x) + else + fun_l5_n596(x) + end +end + +def fun_l4_n119(x) + if (x < 1) + fun_l5_n236(x) + else + fun_l5_n84(x) + end +end + +def fun_l4_n120(x) + if (x < 1) + fun_l5_n78(x) + else + fun_l5_n610(x) + end +end + +def fun_l4_n121(x) + if (x < 1) + fun_l5_n591(x) + else + fun_l5_n557(x) + end +end + +def fun_l4_n122(x) + if (x < 1) + fun_l5_n927(x) + else + fun_l5_n40(x) + end +end + +def fun_l4_n123(x) + if (x < 1) + fun_l5_n620(x) + else + fun_l5_n173(x) + end +end + +def fun_l4_n124(x) + if (x < 1) + fun_l5_n558(x) + else + fun_l5_n330(x) + end +end + +def fun_l4_n125(x) + if (x < 1) + fun_l5_n535(x) + else + fun_l5_n636(x) + end +end + +def fun_l4_n126(x) + if (x < 1) + fun_l5_n401(x) + else + fun_l5_n747(x) + end +end + +def fun_l4_n127(x) + if (x < 1) + fun_l5_n172(x) + else + fun_l5_n124(x) + end +end + +def fun_l4_n128(x) + if (x < 1) + fun_l5_n449(x) + else + fun_l5_n619(x) + end +end + +def fun_l4_n129(x) + if (x < 1) + fun_l5_n564(x) + else + fun_l5_n306(x) + end +end + +def fun_l4_n130(x) + if (x < 1) + fun_l5_n196(x) + else + fun_l5_n170(x) + end +end + +def fun_l4_n131(x) + if (x < 1) + fun_l5_n383(x) + else + fun_l5_n87(x) + end +end + +def fun_l4_n132(x) + if (x < 1) + fun_l5_n568(x) + else + fun_l5_n54(x) + end +end + +def fun_l4_n133(x) + if (x < 1) + fun_l5_n780(x) + else + fun_l5_n184(x) + end +end + +def fun_l4_n134(x) + if (x < 1) + fun_l5_n880(x) + else + fun_l5_n38(x) + end +end + +def fun_l4_n135(x) + if (x < 1) + fun_l5_n819(x) + else + fun_l5_n440(x) + end +end + +def fun_l4_n136(x) + if (x < 1) + fun_l5_n301(x) + else + fun_l5_n676(x) + end +end + +def fun_l4_n137(x) + if (x < 1) + fun_l5_n69(x) + else + fun_l5_n333(x) + end +end + +def fun_l4_n138(x) + if (x < 1) + fun_l5_n303(x) + else + fun_l5_n69(x) + end +end + +def fun_l4_n139(x) + if (x < 1) + fun_l5_n939(x) + else + fun_l5_n103(x) + end +end + +def fun_l4_n140(x) + if (x < 1) + fun_l5_n517(x) + else + fun_l5_n24(x) + end +end + +def fun_l4_n141(x) + if (x < 1) + fun_l5_n923(x) + else + fun_l5_n968(x) + end +end + +def fun_l4_n142(x) + if (x < 1) + fun_l5_n196(x) + else + fun_l5_n841(x) + end +end + +def fun_l4_n143(x) + if (x < 1) + fun_l5_n726(x) + else + fun_l5_n715(x) + end +end + +def fun_l4_n144(x) + if (x < 1) + fun_l5_n434(x) + else + fun_l5_n771(x) + end +end + +def fun_l4_n145(x) + if (x < 1) + fun_l5_n211(x) + else + fun_l5_n963(x) + end +end + +def fun_l4_n146(x) + if (x < 1) + fun_l5_n534(x) + else + fun_l5_n5(x) + end +end + +def fun_l4_n147(x) + if (x < 1) + fun_l5_n409(x) + else + fun_l5_n298(x) + end +end + +def fun_l4_n148(x) + if (x < 1) + fun_l5_n447(x) + else + fun_l5_n474(x) + end +end + +def fun_l4_n149(x) + if (x < 1) + fun_l5_n181(x) + else + fun_l5_n87(x) + end +end + +def fun_l4_n150(x) + if (x < 1) + fun_l5_n871(x) + else + fun_l5_n201(x) + end +end + +def fun_l4_n151(x) + if (x < 1) + fun_l5_n539(x) + else + fun_l5_n855(x) + end +end + +def fun_l4_n152(x) + if (x < 1) + fun_l5_n387(x) + else + fun_l5_n730(x) + end +end + +def fun_l4_n153(x) + if (x < 1) + fun_l5_n785(x) + else + fun_l5_n774(x) + end +end + +def fun_l4_n154(x) + if (x < 1) + fun_l5_n924(x) + else + fun_l5_n414(x) + end +end + +def fun_l4_n155(x) + if (x < 1) + fun_l5_n110(x) + else + fun_l5_n669(x) + end +end + +def fun_l4_n156(x) + if (x < 1) + fun_l5_n551(x) + else + fun_l5_n456(x) + end +end + +def fun_l4_n157(x) + if (x < 1) + fun_l5_n872(x) + else + fun_l5_n397(x) + end +end + +def fun_l4_n158(x) + if (x < 1) + fun_l5_n208(x) + else + fun_l5_n464(x) + end +end + +def fun_l4_n159(x) + if (x < 1) + fun_l5_n236(x) + else + fun_l5_n532(x) + end +end + +def fun_l4_n160(x) + if (x < 1) + fun_l5_n820(x) + else + fun_l5_n146(x) + end +end + +def fun_l4_n161(x) + if (x < 1) + fun_l5_n154(x) + else + fun_l5_n388(x) + end +end + +def fun_l4_n162(x) + if (x < 1) + fun_l5_n456(x) + else + fun_l5_n309(x) + end +end + +def fun_l4_n163(x) + if (x < 1) + fun_l5_n201(x) + else + fun_l5_n728(x) + end +end + +def fun_l4_n164(x) + if (x < 1) + fun_l5_n806(x) + else + fun_l5_n156(x) + end +end + +def fun_l4_n165(x) + if (x < 1) + fun_l5_n984(x) + else + fun_l5_n996(x) + end +end + +def fun_l4_n166(x) + if (x < 1) + fun_l5_n253(x) + else + fun_l5_n527(x) + end +end + +def fun_l4_n167(x) + if (x < 1) + fun_l5_n513(x) + else + fun_l5_n145(x) + end +end + +def fun_l4_n168(x) + if (x < 1) + fun_l5_n694(x) + else + fun_l5_n841(x) + end +end + +def fun_l4_n169(x) + if (x < 1) + fun_l5_n463(x) + else + fun_l5_n193(x) + end +end + +def fun_l4_n170(x) + if (x < 1) + fun_l5_n638(x) + else + fun_l5_n252(x) + end +end + +def fun_l4_n171(x) + if (x < 1) + fun_l5_n166(x) + else + fun_l5_n134(x) + end +end + +def fun_l4_n172(x) + if (x < 1) + fun_l5_n172(x) + else + fun_l5_n179(x) + end +end + +def fun_l4_n173(x) + if (x < 1) + fun_l5_n218(x) + else + fun_l5_n124(x) + end +end + +def fun_l4_n174(x) + if (x < 1) + fun_l5_n370(x) + else + fun_l5_n742(x) + end +end + +def fun_l4_n175(x) + if (x < 1) + fun_l5_n593(x) + else + fun_l5_n542(x) + end +end + +def fun_l4_n176(x) + if (x < 1) + fun_l5_n438(x) + else + fun_l5_n606(x) + end +end + +def fun_l4_n177(x) + if (x < 1) + fun_l5_n316(x) + else + fun_l5_n92(x) + end +end + +def fun_l4_n178(x) + if (x < 1) + fun_l5_n222(x) + else + fun_l5_n461(x) + end +end + +def fun_l4_n179(x) + if (x < 1) + fun_l5_n244(x) + else + fun_l5_n536(x) + end +end + +def fun_l4_n180(x) + if (x < 1) + fun_l5_n120(x) + else + fun_l5_n905(x) + end +end + +def fun_l4_n181(x) + if (x < 1) + fun_l5_n601(x) + else + fun_l5_n62(x) + end +end + +def fun_l4_n182(x) + if (x < 1) + fun_l5_n701(x) + else + fun_l5_n25(x) + end +end + +def fun_l4_n183(x) + if (x < 1) + fun_l5_n361(x) + else + fun_l5_n433(x) + end +end + +def fun_l4_n184(x) + if (x < 1) + fun_l5_n29(x) + else + fun_l5_n302(x) + end +end + +def fun_l4_n185(x) + if (x < 1) + fun_l5_n697(x) + else + fun_l5_n849(x) + end +end + +def fun_l4_n186(x) + if (x < 1) + fun_l5_n76(x) + else + fun_l5_n402(x) + end +end + +def fun_l4_n187(x) + if (x < 1) + fun_l5_n38(x) + else + fun_l5_n818(x) + end +end + +def fun_l4_n188(x) + if (x < 1) + fun_l5_n730(x) + else + fun_l5_n456(x) + end +end + +def fun_l4_n189(x) + if (x < 1) + fun_l5_n828(x) + else + fun_l5_n796(x) + end +end + +def fun_l4_n190(x) + if (x < 1) + fun_l5_n86(x) + else + fun_l5_n976(x) + end +end + +def fun_l4_n191(x) + if (x < 1) + fun_l5_n267(x) + else + fun_l5_n497(x) + end +end + +def fun_l4_n192(x) + if (x < 1) + fun_l5_n534(x) + else + fun_l5_n449(x) + end +end + +def fun_l4_n193(x) + if (x < 1) + fun_l5_n97(x) + else + fun_l5_n595(x) + end +end + +def fun_l4_n194(x) + if (x < 1) + fun_l5_n821(x) + else + fun_l5_n823(x) + end +end + +def fun_l4_n195(x) + if (x < 1) + fun_l5_n936(x) + else + fun_l5_n490(x) + end +end + +def fun_l4_n196(x) + if (x < 1) + fun_l5_n579(x) + else + fun_l5_n684(x) + end +end + +def fun_l4_n197(x) + if (x < 1) + fun_l5_n742(x) + else + fun_l5_n874(x) + end +end + +def fun_l4_n198(x) + if (x < 1) + fun_l5_n904(x) + else + fun_l5_n394(x) + end +end + +def fun_l4_n199(x) + if (x < 1) + fun_l5_n229(x) + else + fun_l5_n406(x) + end +end + +def fun_l4_n200(x) + if (x < 1) + fun_l5_n332(x) + else + fun_l5_n803(x) + end +end + +def fun_l4_n201(x) + if (x < 1) + fun_l5_n635(x) + else + fun_l5_n294(x) + end +end + +def fun_l4_n202(x) + if (x < 1) + fun_l5_n397(x) + else + fun_l5_n924(x) + end +end + +def fun_l4_n203(x) + if (x < 1) + fun_l5_n199(x) + else + fun_l5_n751(x) + end +end + +def fun_l4_n204(x) + if (x < 1) + fun_l5_n570(x) + else + fun_l5_n70(x) + end +end + +def fun_l4_n205(x) + if (x < 1) + fun_l5_n344(x) + else + fun_l5_n713(x) + end +end + +def fun_l4_n206(x) + if (x < 1) + fun_l5_n568(x) + else + fun_l5_n40(x) + end +end + +def fun_l4_n207(x) + if (x < 1) + fun_l5_n460(x) + else + fun_l5_n311(x) + end +end + +def fun_l4_n208(x) + if (x < 1) + fun_l5_n995(x) + else + fun_l5_n147(x) + end +end + +def fun_l4_n209(x) + if (x < 1) + fun_l5_n295(x) + else + fun_l5_n752(x) + end +end + +def fun_l4_n210(x) + if (x < 1) + fun_l5_n644(x) + else + fun_l5_n555(x) + end +end + +def fun_l4_n211(x) + if (x < 1) + fun_l5_n196(x) + else + fun_l5_n418(x) + end +end + +def fun_l4_n212(x) + if (x < 1) + fun_l5_n761(x) + else + fun_l5_n66(x) + end +end + +def fun_l4_n213(x) + if (x < 1) + fun_l5_n906(x) + else + fun_l5_n521(x) + end +end + +def fun_l4_n214(x) + if (x < 1) + fun_l5_n97(x) + else + fun_l5_n431(x) + end +end + +def fun_l4_n215(x) + if (x < 1) + fun_l5_n450(x) + else + fun_l5_n58(x) + end +end + +def fun_l4_n216(x) + if (x < 1) + fun_l5_n576(x) + else + fun_l5_n675(x) + end +end + +def fun_l4_n217(x) + if (x < 1) + fun_l5_n764(x) + else + fun_l5_n653(x) + end +end + +def fun_l4_n218(x) + if (x < 1) + fun_l5_n591(x) + else + fun_l5_n398(x) + end +end + +def fun_l4_n219(x) + if (x < 1) + fun_l5_n94(x) + else + fun_l5_n411(x) + end +end + +def fun_l4_n220(x) + if (x < 1) + fun_l5_n13(x) + else + fun_l5_n117(x) + end +end + +def fun_l4_n221(x) + if (x < 1) + fun_l5_n872(x) + else + fun_l5_n799(x) + end +end + +def fun_l4_n222(x) + if (x < 1) + fun_l5_n692(x) + else + fun_l5_n99(x) + end +end + +def fun_l4_n223(x) + if (x < 1) + fun_l5_n861(x) + else + fun_l5_n999(x) + end +end + +def fun_l4_n224(x) + if (x < 1) + fun_l5_n547(x) + else + fun_l5_n955(x) + end +end + +def fun_l4_n225(x) + if (x < 1) + fun_l5_n305(x) + else + fun_l5_n894(x) + end +end + +def fun_l4_n226(x) + if (x < 1) + fun_l5_n128(x) + else + fun_l5_n662(x) + end +end + +def fun_l4_n227(x) + if (x < 1) + fun_l5_n858(x) + else + fun_l5_n323(x) + end +end + +def fun_l4_n228(x) + if (x < 1) + fun_l5_n923(x) + else + fun_l5_n206(x) + end +end + +def fun_l4_n229(x) + if (x < 1) + fun_l5_n486(x) + else + fun_l5_n603(x) + end +end + +def fun_l4_n230(x) + if (x < 1) + fun_l5_n116(x) + else + fun_l5_n887(x) + end +end + +def fun_l4_n231(x) + if (x < 1) + fun_l5_n791(x) + else + fun_l5_n762(x) + end +end + +def fun_l4_n232(x) + if (x < 1) + fun_l5_n511(x) + else + fun_l5_n890(x) + end +end + +def fun_l4_n233(x) + if (x < 1) + fun_l5_n600(x) + else + fun_l5_n777(x) + end +end + +def fun_l4_n234(x) + if (x < 1) + fun_l5_n458(x) + else + fun_l5_n379(x) + end +end + +def fun_l4_n235(x) + if (x < 1) + fun_l5_n907(x) + else + fun_l5_n463(x) + end +end + +def fun_l4_n236(x) + if (x < 1) + fun_l5_n177(x) + else + fun_l5_n732(x) + end +end + +def fun_l4_n237(x) + if (x < 1) + fun_l5_n761(x) + else + fun_l5_n936(x) + end +end + +def fun_l4_n238(x) + if (x < 1) + fun_l5_n757(x) + else + fun_l5_n733(x) + end +end + +def fun_l4_n239(x) + if (x < 1) + fun_l5_n844(x) + else + fun_l5_n527(x) + end +end + +def fun_l4_n240(x) + if (x < 1) + fun_l5_n594(x) + else + fun_l5_n620(x) + end +end + +def fun_l4_n241(x) + if (x < 1) + fun_l5_n722(x) + else + fun_l5_n779(x) + end +end + +def fun_l4_n242(x) + if (x < 1) + fun_l5_n663(x) + else + fun_l5_n237(x) + end +end + +def fun_l4_n243(x) + if (x < 1) + fun_l5_n256(x) + else + fun_l5_n366(x) + end +end + +def fun_l4_n244(x) + if (x < 1) + fun_l5_n614(x) + else + fun_l5_n895(x) + end +end + +def fun_l4_n245(x) + if (x < 1) + fun_l5_n459(x) + else + fun_l5_n193(x) + end +end + +def fun_l4_n246(x) + if (x < 1) + fun_l5_n780(x) + else + fun_l5_n175(x) + end +end + +def fun_l4_n247(x) + if (x < 1) + fun_l5_n186(x) + else + fun_l5_n488(x) + end +end + +def fun_l4_n248(x) + if (x < 1) + fun_l5_n156(x) + else + fun_l5_n807(x) + end +end + +def fun_l4_n249(x) + if (x < 1) + fun_l5_n862(x) + else + fun_l5_n537(x) + end +end + +def fun_l4_n250(x) + if (x < 1) + fun_l5_n880(x) + else + fun_l5_n528(x) + end +end + +def fun_l4_n251(x) + if (x < 1) + fun_l5_n163(x) + else + fun_l5_n94(x) + end +end + +def fun_l4_n252(x) + if (x < 1) + fun_l5_n937(x) + else + fun_l5_n582(x) + end +end + +def fun_l4_n253(x) + if (x < 1) + fun_l5_n368(x) + else + fun_l5_n584(x) + end +end + +def fun_l4_n254(x) + if (x < 1) + fun_l5_n566(x) + else + fun_l5_n449(x) + end +end + +def fun_l4_n255(x) + if (x < 1) + fun_l5_n876(x) + else + fun_l5_n0(x) + end +end + +def fun_l4_n256(x) + if (x < 1) + fun_l5_n842(x) + else + fun_l5_n469(x) + end +end + +def fun_l4_n257(x) + if (x < 1) + fun_l5_n85(x) + else + fun_l5_n961(x) + end +end + +def fun_l4_n258(x) + if (x < 1) + fun_l5_n120(x) + else + fun_l5_n893(x) + end +end + +def fun_l4_n259(x) + if (x < 1) + fun_l5_n243(x) + else + fun_l5_n630(x) + end +end + +def fun_l4_n260(x) + if (x < 1) + fun_l5_n710(x) + else + fun_l5_n715(x) + end +end + +def fun_l4_n261(x) + if (x < 1) + fun_l5_n423(x) + else + fun_l5_n910(x) + end +end + +def fun_l4_n262(x) + if (x < 1) + fun_l5_n505(x) + else + fun_l5_n532(x) + end +end + +def fun_l4_n263(x) + if (x < 1) + fun_l5_n775(x) + else + fun_l5_n236(x) + end +end + +def fun_l4_n264(x) + if (x < 1) + fun_l5_n140(x) + else + fun_l5_n295(x) + end +end + +def fun_l4_n265(x) + if (x < 1) + fun_l5_n554(x) + else + fun_l5_n88(x) + end +end + +def fun_l4_n266(x) + if (x < 1) + fun_l5_n831(x) + else + fun_l5_n307(x) + end +end + +def fun_l4_n267(x) + if (x < 1) + fun_l5_n303(x) + else + fun_l5_n960(x) + end +end + +def fun_l4_n268(x) + if (x < 1) + fun_l5_n322(x) + else + fun_l5_n264(x) + end +end + +def fun_l4_n269(x) + if (x < 1) + fun_l5_n823(x) + else + fun_l5_n374(x) + end +end + +def fun_l4_n270(x) + if (x < 1) + fun_l5_n76(x) + else + fun_l5_n918(x) + end +end + +def fun_l4_n271(x) + if (x < 1) + fun_l5_n591(x) + else + fun_l5_n45(x) + end +end + +def fun_l4_n272(x) + if (x < 1) + fun_l5_n686(x) + else + fun_l5_n836(x) + end +end + +def fun_l4_n273(x) + if (x < 1) + fun_l5_n13(x) + else + fun_l5_n676(x) + end +end + +def fun_l4_n274(x) + if (x < 1) + fun_l5_n120(x) + else + fun_l5_n180(x) + end +end + +def fun_l4_n275(x) + if (x < 1) + fun_l5_n901(x) + else + fun_l5_n101(x) + end +end + +def fun_l4_n276(x) + if (x < 1) + fun_l5_n289(x) + else + fun_l5_n238(x) + end +end + +def fun_l4_n277(x) + if (x < 1) + fun_l5_n513(x) + else + fun_l5_n887(x) + end +end + +def fun_l4_n278(x) + if (x < 1) + fun_l5_n799(x) + else + fun_l5_n763(x) + end +end + +def fun_l4_n279(x) + if (x < 1) + fun_l5_n628(x) + else + fun_l5_n373(x) + end +end + +def fun_l4_n280(x) + if (x < 1) + fun_l5_n661(x) + else + fun_l5_n826(x) + end +end + +def fun_l4_n281(x) + if (x < 1) + fun_l5_n35(x) + else + fun_l5_n409(x) + end +end + +def fun_l4_n282(x) + if (x < 1) + fun_l5_n721(x) + else + fun_l5_n719(x) + end +end + +def fun_l4_n283(x) + if (x < 1) + fun_l5_n729(x) + else + fun_l5_n901(x) + end +end + +def fun_l4_n284(x) + if (x < 1) + fun_l5_n17(x) + else + fun_l5_n482(x) + end +end + +def fun_l4_n285(x) + if (x < 1) + fun_l5_n166(x) + else + fun_l5_n53(x) + end +end + +def fun_l4_n286(x) + if (x < 1) + fun_l5_n873(x) + else + fun_l5_n383(x) + end +end + +def fun_l4_n287(x) + if (x < 1) + fun_l5_n269(x) + else + fun_l5_n49(x) + end +end + +def fun_l4_n288(x) + if (x < 1) + fun_l5_n292(x) + else + fun_l5_n353(x) + end +end + +def fun_l4_n289(x) + if (x < 1) + fun_l5_n651(x) + else + fun_l5_n606(x) + end +end + +def fun_l4_n290(x) + if (x < 1) + fun_l5_n287(x) + else + fun_l5_n444(x) + end +end + +def fun_l4_n291(x) + if (x < 1) + fun_l5_n181(x) + else + fun_l5_n195(x) + end +end + +def fun_l4_n292(x) + if (x < 1) + fun_l5_n20(x) + else + fun_l5_n58(x) + end +end + +def fun_l4_n293(x) + if (x < 1) + fun_l5_n185(x) + else + fun_l5_n759(x) + end +end + +def fun_l4_n294(x) + if (x < 1) + fun_l5_n938(x) + else + fun_l5_n849(x) + end +end + +def fun_l4_n295(x) + if (x < 1) + fun_l5_n187(x) + else + fun_l5_n469(x) + end +end + +def fun_l4_n296(x) + if (x < 1) + fun_l5_n516(x) + else + fun_l5_n314(x) + end +end + +def fun_l4_n297(x) + if (x < 1) + fun_l5_n585(x) + else + fun_l5_n344(x) + end +end + +def fun_l4_n298(x) + if (x < 1) + fun_l5_n637(x) + else + fun_l5_n103(x) + end +end + +def fun_l4_n299(x) + if (x < 1) + fun_l5_n185(x) + else + fun_l5_n593(x) + end +end + +def fun_l4_n300(x) + if (x < 1) + fun_l5_n773(x) + else + fun_l5_n758(x) + end +end + +def fun_l4_n301(x) + if (x < 1) + fun_l5_n444(x) + else + fun_l5_n945(x) + end +end + +def fun_l4_n302(x) + if (x < 1) + fun_l5_n728(x) + else + fun_l5_n484(x) + end +end + +def fun_l4_n303(x) + if (x < 1) + fun_l5_n412(x) + else + fun_l5_n106(x) + end +end + +def fun_l4_n304(x) + if (x < 1) + fun_l5_n399(x) + else + fun_l5_n234(x) + end +end + +def fun_l4_n305(x) + if (x < 1) + fun_l5_n886(x) + else + fun_l5_n406(x) + end +end + +def fun_l4_n306(x) + if (x < 1) + fun_l5_n535(x) + else + fun_l5_n338(x) + end +end + +def fun_l4_n307(x) + if (x < 1) + fun_l5_n898(x) + else + fun_l5_n859(x) + end +end + +def fun_l4_n308(x) + if (x < 1) + fun_l5_n25(x) + else + fun_l5_n476(x) + end +end + +def fun_l4_n309(x) + if (x < 1) + fun_l5_n451(x) + else + fun_l5_n665(x) + end +end + +def fun_l4_n310(x) + if (x < 1) + fun_l5_n937(x) + else + fun_l5_n555(x) + end +end + +def fun_l4_n311(x) + if (x < 1) + fun_l5_n982(x) + else + fun_l5_n89(x) + end +end + +def fun_l4_n312(x) + if (x < 1) + fun_l5_n32(x) + else + fun_l5_n908(x) + end +end + +def fun_l4_n313(x) + if (x < 1) + fun_l5_n963(x) + else + fun_l5_n267(x) + end +end + +def fun_l4_n314(x) + if (x < 1) + fun_l5_n3(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n315(x) + if (x < 1) + fun_l5_n763(x) + else + fun_l5_n488(x) + end +end + +def fun_l4_n316(x) + if (x < 1) + fun_l5_n696(x) + else + fun_l5_n663(x) + end +end + +def fun_l4_n317(x) + if (x < 1) + fun_l5_n851(x) + else + fun_l5_n487(x) + end +end + +def fun_l4_n318(x) + if (x < 1) + fun_l5_n327(x) + else + fun_l5_n433(x) + end +end + +def fun_l4_n319(x) + if (x < 1) + fun_l5_n242(x) + else + fun_l5_n471(x) + end +end + +def fun_l4_n320(x) + if (x < 1) + fun_l5_n786(x) + else + fun_l5_n622(x) + end +end + +def fun_l4_n321(x) + if (x < 1) + fun_l5_n94(x) + else + fun_l5_n934(x) + end +end + +def fun_l4_n322(x) + if (x < 1) + fun_l5_n665(x) + else + fun_l5_n386(x) + end +end + +def fun_l4_n323(x) + if (x < 1) + fun_l5_n96(x) + else + fun_l5_n466(x) + end +end + +def fun_l4_n324(x) + if (x < 1) + fun_l5_n394(x) + else + fun_l5_n595(x) + end +end + +def fun_l4_n325(x) + if (x < 1) + fun_l5_n544(x) + else + fun_l5_n688(x) + end +end + +def fun_l4_n326(x) + if (x < 1) + fun_l5_n295(x) + else + fun_l5_n206(x) + end +end + +def fun_l4_n327(x) + if (x < 1) + fun_l5_n128(x) + else + fun_l5_n607(x) + end +end + +def fun_l4_n328(x) + if (x < 1) + fun_l5_n987(x) + else + fun_l5_n109(x) + end +end + +def fun_l4_n329(x) + if (x < 1) + fun_l5_n842(x) + else + fun_l5_n217(x) + end +end + +def fun_l4_n330(x) + if (x < 1) + fun_l5_n92(x) + else + fun_l5_n774(x) + end +end + +def fun_l4_n331(x) + if (x < 1) + fun_l5_n761(x) + else + fun_l5_n34(x) + end +end + +def fun_l4_n332(x) + if (x < 1) + fun_l5_n867(x) + else + fun_l5_n645(x) + end +end + +def fun_l4_n333(x) + if (x < 1) + fun_l5_n273(x) + else + fun_l5_n592(x) + end +end + +def fun_l4_n334(x) + if (x < 1) + fun_l5_n29(x) + else + fun_l5_n985(x) + end +end + +def fun_l4_n335(x) + if (x < 1) + fun_l5_n430(x) + else + fun_l5_n346(x) + end +end + +def fun_l4_n336(x) + if (x < 1) + fun_l5_n367(x) + else + fun_l5_n686(x) + end +end + +def fun_l4_n337(x) + if (x < 1) + fun_l5_n868(x) + else + fun_l5_n5(x) + end +end + +def fun_l4_n338(x) + if (x < 1) + fun_l5_n998(x) + else + fun_l5_n64(x) + end +end + +def fun_l4_n339(x) + if (x < 1) + fun_l5_n594(x) + else + fun_l5_n311(x) + end +end + +def fun_l4_n340(x) + if (x < 1) + fun_l5_n547(x) + else + fun_l5_n573(x) + end +end + +def fun_l4_n341(x) + if (x < 1) + fun_l5_n590(x) + else + fun_l5_n923(x) + end +end + +def fun_l4_n342(x) + if (x < 1) + fun_l5_n538(x) + else + fun_l5_n118(x) + end +end + +def fun_l4_n343(x) + if (x < 1) + fun_l5_n322(x) + else + fun_l5_n970(x) + end +end + +def fun_l4_n344(x) + if (x < 1) + fun_l5_n809(x) + else + fun_l5_n958(x) + end +end + +def fun_l4_n345(x) + if (x < 1) + fun_l5_n613(x) + else + fun_l5_n199(x) + end +end + +def fun_l4_n346(x) + if (x < 1) + fun_l5_n298(x) + else + fun_l5_n273(x) + end +end + +def fun_l4_n347(x) + if (x < 1) + fun_l5_n560(x) + else + fun_l5_n803(x) + end +end + +def fun_l4_n348(x) + if (x < 1) + fun_l5_n672(x) + else + fun_l5_n952(x) + end +end + +def fun_l4_n349(x) + if (x < 1) + fun_l5_n58(x) + else + fun_l5_n267(x) + end +end + +def fun_l4_n350(x) + if (x < 1) + fun_l5_n933(x) + else + fun_l5_n773(x) + end +end + +def fun_l4_n351(x) + if (x < 1) + fun_l5_n574(x) + else + fun_l5_n692(x) + end +end + +def fun_l4_n352(x) + if (x < 1) + fun_l5_n537(x) + else + fun_l5_n312(x) + end +end + +def fun_l4_n353(x) + if (x < 1) + fun_l5_n696(x) + else + fun_l5_n739(x) + end +end + +def fun_l4_n354(x) + if (x < 1) + fun_l5_n871(x) + else + fun_l5_n86(x) + end +end + +def fun_l4_n355(x) + if (x < 1) + fun_l5_n3(x) + else + fun_l5_n950(x) + end +end + +def fun_l4_n356(x) + if (x < 1) + fun_l5_n560(x) + else + fun_l5_n45(x) + end +end + +def fun_l4_n357(x) + if (x < 1) + fun_l5_n666(x) + else + fun_l5_n874(x) + end +end + +def fun_l4_n358(x) + if (x < 1) + fun_l5_n457(x) + else + fun_l5_n7(x) + end +end + +def fun_l4_n359(x) + if (x < 1) + fun_l5_n674(x) + else + fun_l5_n985(x) + end +end + +def fun_l4_n360(x) + if (x < 1) + fun_l5_n960(x) + else + fun_l5_n228(x) + end +end + +def fun_l4_n361(x) + if (x < 1) + fun_l5_n597(x) + else + fun_l5_n487(x) + end +end + +def fun_l4_n362(x) + if (x < 1) + fun_l5_n145(x) + else + fun_l5_n278(x) + end +end + +def fun_l4_n363(x) + if (x < 1) + fun_l5_n949(x) + else + fun_l5_n353(x) + end +end + +def fun_l4_n364(x) + if (x < 1) + fun_l5_n604(x) + else + fun_l5_n250(x) + end +end + +def fun_l4_n365(x) + if (x < 1) + fun_l5_n347(x) + else + fun_l5_n964(x) + end +end + +def fun_l4_n366(x) + if (x < 1) + fun_l5_n331(x) + else + fun_l5_n657(x) + end +end + +def fun_l4_n367(x) + if (x < 1) + fun_l5_n74(x) + else + fun_l5_n504(x) + end +end + +def fun_l4_n368(x) + if (x < 1) + fun_l5_n9(x) + else + fun_l5_n993(x) + end +end + +def fun_l4_n369(x) + if (x < 1) + fun_l5_n492(x) + else + fun_l5_n155(x) + end +end + +def fun_l4_n370(x) + if (x < 1) + fun_l5_n848(x) + else + fun_l5_n178(x) + end +end + +def fun_l4_n371(x) + if (x < 1) + fun_l5_n395(x) + else + fun_l5_n837(x) + end +end + +def fun_l4_n372(x) + if (x < 1) + fun_l5_n834(x) + else + fun_l5_n719(x) + end +end + +def fun_l4_n373(x) + if (x < 1) + fun_l5_n422(x) + else + fun_l5_n776(x) + end +end + +def fun_l4_n374(x) + if (x < 1) + fun_l5_n293(x) + else + fun_l5_n385(x) + end +end + +def fun_l4_n375(x) + if (x < 1) + fun_l5_n487(x) + else + fun_l5_n61(x) + end +end + +def fun_l4_n376(x) + if (x < 1) + fun_l5_n493(x) + else + fun_l5_n629(x) + end +end + +def fun_l4_n377(x) + if (x < 1) + fun_l5_n429(x) + else + fun_l5_n157(x) + end +end + +def fun_l4_n378(x) + if (x < 1) + fun_l5_n145(x) + else + fun_l5_n988(x) + end +end + +def fun_l4_n379(x) + if (x < 1) + fun_l5_n430(x) + else + fun_l5_n246(x) + end +end + +def fun_l4_n380(x) + if (x < 1) + fun_l5_n320(x) + else + fun_l5_n284(x) + end +end + +def fun_l4_n381(x) + if (x < 1) + fun_l5_n278(x) + else + fun_l5_n163(x) + end +end + +def fun_l4_n382(x) + if (x < 1) + fun_l5_n999(x) + else + fun_l5_n907(x) + end +end + +def fun_l4_n383(x) + if (x < 1) + fun_l5_n979(x) + else + fun_l5_n370(x) + end +end + +def fun_l4_n384(x) + if (x < 1) + fun_l5_n58(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n385(x) + if (x < 1) + fun_l5_n558(x) + else + fun_l5_n524(x) + end +end + +def fun_l4_n386(x) + if (x < 1) + fun_l5_n438(x) + else + fun_l5_n799(x) + end +end + +def fun_l4_n387(x) + if (x < 1) + fun_l5_n696(x) + else + fun_l5_n463(x) + end +end + +def fun_l4_n388(x) + if (x < 1) + fun_l5_n376(x) + else + fun_l5_n943(x) + end +end + +def fun_l4_n389(x) + if (x < 1) + fun_l5_n21(x) + else + fun_l5_n663(x) + end +end + +def fun_l4_n390(x) + if (x < 1) + fun_l5_n8(x) + else + fun_l5_n348(x) + end +end + +def fun_l4_n391(x) + if (x < 1) + fun_l5_n908(x) + else + fun_l5_n695(x) + end +end + +def fun_l4_n392(x) + if (x < 1) + fun_l5_n97(x) + else + fun_l5_n466(x) + end +end + +def fun_l4_n393(x) + if (x < 1) + fun_l5_n480(x) + else + fun_l5_n972(x) + end +end + +def fun_l4_n394(x) + if (x < 1) + fun_l5_n85(x) + else + fun_l5_n849(x) + end +end + +def fun_l4_n395(x) + if (x < 1) + fun_l5_n897(x) + else + fun_l5_n13(x) + end +end + +def fun_l4_n396(x) + if (x < 1) + fun_l5_n628(x) + else + fun_l5_n743(x) + end +end + +def fun_l4_n397(x) + if (x < 1) + fun_l5_n29(x) + else + fun_l5_n185(x) + end +end + +def fun_l4_n398(x) + if (x < 1) + fun_l5_n464(x) + else + fun_l5_n742(x) + end +end + +def fun_l4_n399(x) + if (x < 1) + fun_l5_n348(x) + else + fun_l5_n70(x) + end +end + +def fun_l4_n400(x) + if (x < 1) + fun_l5_n397(x) + else + fun_l5_n132(x) + end +end + +def fun_l4_n401(x) + if (x < 1) + fun_l5_n433(x) + else + fun_l5_n77(x) + end +end + +def fun_l4_n402(x) + if (x < 1) + fun_l5_n24(x) + else + fun_l5_n160(x) + end +end + +def fun_l4_n403(x) + if (x < 1) + fun_l5_n738(x) + else + fun_l5_n174(x) + end +end + +def fun_l4_n404(x) + if (x < 1) + fun_l5_n585(x) + else + fun_l5_n670(x) + end +end + +def fun_l4_n405(x) + if (x < 1) + fun_l5_n320(x) + else + fun_l5_n245(x) + end +end + +def fun_l4_n406(x) + if (x < 1) + fun_l5_n357(x) + else + fun_l5_n742(x) + end +end + +def fun_l4_n407(x) + if (x < 1) + fun_l5_n16(x) + else + fun_l5_n227(x) + end +end + +def fun_l4_n408(x) + if (x < 1) + fun_l5_n360(x) + else + fun_l5_n18(x) + end +end + +def fun_l4_n409(x) + if (x < 1) + fun_l5_n210(x) + else + fun_l5_n253(x) + end +end + +def fun_l4_n410(x) + if (x < 1) + fun_l5_n915(x) + else + fun_l5_n605(x) + end +end + +def fun_l4_n411(x) + if (x < 1) + fun_l5_n511(x) + else + fun_l5_n118(x) + end +end + +def fun_l4_n412(x) + if (x < 1) + fun_l5_n680(x) + else + fun_l5_n445(x) + end +end + +def fun_l4_n413(x) + if (x < 1) + fun_l5_n722(x) + else + fun_l5_n440(x) + end +end + +def fun_l4_n414(x) + if (x < 1) + fun_l5_n382(x) + else + fun_l5_n380(x) + end +end + +def fun_l4_n415(x) + if (x < 1) + fun_l5_n548(x) + else + fun_l5_n462(x) + end +end + +def fun_l4_n416(x) + if (x < 1) + fun_l5_n12(x) + else + fun_l5_n952(x) + end +end + +def fun_l4_n417(x) + if (x < 1) + fun_l5_n814(x) + else + fun_l5_n720(x) + end +end + +def fun_l4_n418(x) + if (x < 1) + fun_l5_n804(x) + else + fun_l5_n243(x) + end +end + +def fun_l4_n419(x) + if (x < 1) + fun_l5_n654(x) + else + fun_l5_n950(x) + end +end + +def fun_l4_n420(x) + if (x < 1) + fun_l5_n998(x) + else + fun_l5_n937(x) + end +end + +def fun_l4_n421(x) + if (x < 1) + fun_l5_n476(x) + else + fun_l5_n245(x) + end +end + +def fun_l4_n422(x) + if (x < 1) + fun_l5_n778(x) + else + fun_l5_n950(x) + end +end + +def fun_l4_n423(x) + if (x < 1) + fun_l5_n255(x) + else + fun_l5_n438(x) + end +end + +def fun_l4_n424(x) + if (x < 1) + fun_l5_n906(x) + else + fun_l5_n329(x) + end +end + +def fun_l4_n425(x) + if (x < 1) + fun_l5_n644(x) + else + fun_l5_n512(x) + end +end + +def fun_l4_n426(x) + if (x < 1) + fun_l5_n558(x) + else + fun_l5_n925(x) + end +end + +def fun_l4_n427(x) + if (x < 1) + fun_l5_n745(x) + else + fun_l5_n168(x) + end +end + +def fun_l4_n428(x) + if (x < 1) + fun_l5_n682(x) + else + fun_l5_n298(x) + end +end + +def fun_l4_n429(x) + if (x < 1) + fun_l5_n211(x) + else + fun_l5_n608(x) + end +end + +def fun_l4_n430(x) + if (x < 1) + fun_l5_n100(x) + else + fun_l5_n287(x) + end +end + +def fun_l4_n431(x) + if (x < 1) + fun_l5_n513(x) + else + fun_l5_n764(x) + end +end + +def fun_l4_n432(x) + if (x < 1) + fun_l5_n925(x) + else + fun_l5_n857(x) + end +end + +def fun_l4_n433(x) + if (x < 1) + fun_l5_n279(x) + else + fun_l5_n429(x) + end +end + +def fun_l4_n434(x) + if (x < 1) + fun_l5_n376(x) + else + fun_l5_n811(x) + end +end + +def fun_l4_n435(x) + if (x < 1) + fun_l5_n893(x) + else + fun_l5_n136(x) + end +end + +def fun_l4_n436(x) + if (x < 1) + fun_l5_n283(x) + else + fun_l5_n508(x) + end +end + +def fun_l4_n437(x) + if (x < 1) + fun_l5_n478(x) + else + fun_l5_n589(x) + end +end + +def fun_l4_n438(x) + if (x < 1) + fun_l5_n460(x) + else + fun_l5_n589(x) + end +end + +def fun_l4_n439(x) + if (x < 1) + fun_l5_n745(x) + else + fun_l5_n5(x) + end +end + +def fun_l4_n440(x) + if (x < 1) + fun_l5_n601(x) + else + fun_l5_n322(x) + end +end + +def fun_l4_n441(x) + if (x < 1) + fun_l5_n703(x) + else + fun_l5_n322(x) + end +end + +def fun_l4_n442(x) + if (x < 1) + fun_l5_n810(x) + else + fun_l5_n363(x) + end +end + +def fun_l4_n443(x) + if (x < 1) + fun_l5_n62(x) + else + fun_l5_n995(x) + end +end + +def fun_l4_n444(x) + if (x < 1) + fun_l5_n196(x) + else + fun_l5_n156(x) + end +end + +def fun_l4_n445(x) + if (x < 1) + fun_l5_n456(x) + else + fun_l5_n820(x) + end +end + +def fun_l4_n446(x) + if (x < 1) + fun_l5_n592(x) + else + fun_l5_n214(x) + end +end + +def fun_l4_n447(x) + if (x < 1) + fun_l5_n44(x) + else + fun_l5_n769(x) + end +end + +def fun_l4_n448(x) + if (x < 1) + fun_l5_n694(x) + else + fun_l5_n909(x) + end +end + +def fun_l4_n449(x) + if (x < 1) + fun_l5_n297(x) + else + fun_l5_n134(x) + end +end + +def fun_l4_n450(x) + if (x < 1) + fun_l5_n878(x) + else + fun_l5_n475(x) + end +end + +def fun_l4_n451(x) + if (x < 1) + fun_l5_n338(x) + else + fun_l5_n700(x) + end +end + +def fun_l4_n452(x) + if (x < 1) + fun_l5_n813(x) + else + fun_l5_n41(x) + end +end + +def fun_l4_n453(x) + if (x < 1) + fun_l5_n176(x) + else + fun_l5_n758(x) + end +end + +def fun_l4_n454(x) + if (x < 1) + fun_l5_n60(x) + else + fun_l5_n608(x) + end +end + +def fun_l4_n455(x) + if (x < 1) + fun_l5_n550(x) + else + fun_l5_n607(x) + end +end + +def fun_l4_n456(x) + if (x < 1) + fun_l5_n535(x) + else + fun_l5_n478(x) + end +end + +def fun_l4_n457(x) + if (x < 1) + fun_l5_n768(x) + else + fun_l5_n613(x) + end +end + +def fun_l4_n458(x) + if (x < 1) + fun_l5_n686(x) + else + fun_l5_n208(x) + end +end + +def fun_l4_n459(x) + if (x < 1) + fun_l5_n167(x) + else + fun_l5_n875(x) + end +end + +def fun_l4_n460(x) + if (x < 1) + fun_l5_n202(x) + else + fun_l5_n440(x) + end +end + +def fun_l4_n461(x) + if (x < 1) + fun_l5_n64(x) + else + fun_l5_n845(x) + end +end + +def fun_l4_n462(x) + if (x < 1) + fun_l5_n914(x) + else + fun_l5_n699(x) + end +end + +def fun_l4_n463(x) + if (x < 1) + fun_l5_n204(x) + else + fun_l5_n723(x) + end +end + +def fun_l4_n464(x) + if (x < 1) + fun_l5_n549(x) + else + fun_l5_n375(x) + end +end + +def fun_l4_n465(x) + if (x < 1) + fun_l5_n610(x) + else + fun_l5_n596(x) + end +end + +def fun_l4_n466(x) + if (x < 1) + fun_l5_n571(x) + else + fun_l5_n618(x) + end +end + +def fun_l4_n467(x) + if (x < 1) + fun_l5_n428(x) + else + fun_l5_n315(x) + end +end + +def fun_l4_n468(x) + if (x < 1) + fun_l5_n19(x) + else + fun_l5_n301(x) + end +end + +def fun_l4_n469(x) + if (x < 1) + fun_l5_n38(x) + else + fun_l5_n895(x) + end +end + +def fun_l4_n470(x) + if (x < 1) + fun_l5_n815(x) + else + fun_l5_n303(x) + end +end + +def fun_l4_n471(x) + if (x < 1) + fun_l5_n876(x) + else + fun_l5_n221(x) + end +end + +def fun_l4_n472(x) + if (x < 1) + fun_l5_n199(x) + else + fun_l5_n354(x) + end +end + +def fun_l4_n473(x) + if (x < 1) + fun_l5_n56(x) + else + fun_l5_n197(x) + end +end + +def fun_l4_n474(x) + if (x < 1) + fun_l5_n573(x) + else + fun_l5_n616(x) + end +end + +def fun_l4_n475(x) + if (x < 1) + fun_l5_n313(x) + else + fun_l5_n209(x) + end +end + +def fun_l4_n476(x) + if (x < 1) + fun_l5_n229(x) + else + fun_l5_n51(x) + end +end + +def fun_l4_n477(x) + if (x < 1) + fun_l5_n768(x) + else + fun_l5_n368(x) + end +end + +def fun_l4_n478(x) + if (x < 1) + fun_l5_n80(x) + else + fun_l5_n411(x) + end +end + +def fun_l4_n479(x) + if (x < 1) + fun_l5_n221(x) + else + fun_l5_n266(x) + end +end + +def fun_l4_n480(x) + if (x < 1) + fun_l5_n463(x) + else + fun_l5_n71(x) + end +end + +def fun_l4_n481(x) + if (x < 1) + fun_l5_n446(x) + else + fun_l5_n610(x) + end +end + +def fun_l4_n482(x) + if (x < 1) + fun_l5_n402(x) + else + fun_l5_n449(x) + end +end + +def fun_l4_n483(x) + if (x < 1) + fun_l5_n497(x) + else + fun_l5_n521(x) + end +end + +def fun_l4_n484(x) + if (x < 1) + fun_l5_n895(x) + else + fun_l5_n361(x) + end +end + +def fun_l4_n485(x) + if (x < 1) + fun_l5_n254(x) + else + fun_l5_n366(x) + end +end + +def fun_l4_n486(x) + if (x < 1) + fun_l5_n179(x) + else + fun_l5_n154(x) + end +end + +def fun_l4_n487(x) + if (x < 1) + fun_l5_n905(x) + else + fun_l5_n30(x) + end +end + +def fun_l4_n488(x) + if (x < 1) + fun_l5_n989(x) + else + fun_l5_n640(x) + end +end + +def fun_l4_n489(x) + if (x < 1) + fun_l5_n664(x) + else + fun_l5_n87(x) + end +end + +def fun_l4_n490(x) + if (x < 1) + fun_l5_n518(x) + else + fun_l5_n986(x) + end +end + +def fun_l4_n491(x) + if (x < 1) + fun_l5_n443(x) + else + fun_l5_n532(x) + end +end + +def fun_l4_n492(x) + if (x < 1) + fun_l5_n349(x) + else + fun_l5_n373(x) + end +end + +def fun_l4_n493(x) + if (x < 1) + fun_l5_n208(x) + else + fun_l5_n404(x) + end +end + +def fun_l4_n494(x) + if (x < 1) + fun_l5_n12(x) + else + fun_l5_n608(x) + end +end + +def fun_l4_n495(x) + if (x < 1) + fun_l5_n12(x) + else + fun_l5_n42(x) + end +end + +def fun_l4_n496(x) + if (x < 1) + fun_l5_n442(x) + else + fun_l5_n809(x) + end +end + +def fun_l4_n497(x) + if (x < 1) + fun_l5_n266(x) + else + fun_l5_n259(x) + end +end + +def fun_l4_n498(x) + if (x < 1) + fun_l5_n342(x) + else + fun_l5_n275(x) + end +end + +def fun_l4_n499(x) + if (x < 1) + fun_l5_n806(x) + else + fun_l5_n797(x) + end +end + +def fun_l4_n500(x) + if (x < 1) + fun_l5_n646(x) + else + fun_l5_n426(x) + end +end + +def fun_l4_n501(x) + if (x < 1) + fun_l5_n593(x) + else + fun_l5_n860(x) + end +end + +def fun_l4_n502(x) + if (x < 1) + fun_l5_n355(x) + else + fun_l5_n411(x) + end +end + +def fun_l4_n503(x) + if (x < 1) + fun_l5_n602(x) + else + fun_l5_n26(x) + end +end + +def fun_l4_n504(x) + if (x < 1) + fun_l5_n875(x) + else + fun_l5_n716(x) + end +end + +def fun_l4_n505(x) + if (x < 1) + fun_l5_n248(x) + else + fun_l5_n388(x) + end +end + +def fun_l4_n506(x) + if (x < 1) + fun_l5_n273(x) + else + fun_l5_n11(x) + end +end + +def fun_l4_n507(x) + if (x < 1) + fun_l5_n291(x) + else + fun_l5_n464(x) + end +end + +def fun_l4_n508(x) + if (x < 1) + fun_l5_n309(x) + else + fun_l5_n198(x) + end +end + +def fun_l4_n509(x) + if (x < 1) + fun_l5_n85(x) + else + fun_l5_n375(x) + end +end + +def fun_l4_n510(x) + if (x < 1) + fun_l5_n993(x) + else + fun_l5_n311(x) + end +end + +def fun_l4_n511(x) + if (x < 1) + fun_l5_n824(x) + else + fun_l5_n936(x) + end +end + +def fun_l4_n512(x) + if (x < 1) + fun_l5_n897(x) + else + fun_l5_n995(x) + end +end + +def fun_l4_n513(x) + if (x < 1) + fun_l5_n443(x) + else + fun_l5_n511(x) + end +end + +def fun_l4_n514(x) + if (x < 1) + fun_l5_n965(x) + else + fun_l5_n506(x) + end +end + +def fun_l4_n515(x) + if (x < 1) + fun_l5_n480(x) + else + fun_l5_n464(x) + end +end + +def fun_l4_n516(x) + if (x < 1) + fun_l5_n396(x) + else + fun_l5_n355(x) + end +end + +def fun_l4_n517(x) + if (x < 1) + fun_l5_n782(x) + else + fun_l5_n624(x) + end +end + +def fun_l4_n518(x) + if (x < 1) + fun_l5_n460(x) + else + fun_l5_n920(x) + end +end + +def fun_l4_n519(x) + if (x < 1) + fun_l5_n258(x) + else + fun_l5_n296(x) + end +end + +def fun_l4_n520(x) + if (x < 1) + fun_l5_n344(x) + else + fun_l5_n180(x) + end +end + +def fun_l4_n521(x) + if (x < 1) + fun_l5_n489(x) + else + fun_l5_n818(x) + end +end + +def fun_l4_n522(x) + if (x < 1) + fun_l5_n246(x) + else + fun_l5_n25(x) + end +end + +def fun_l4_n523(x) + if (x < 1) + fun_l5_n165(x) + else + fun_l5_n835(x) + end +end + +def fun_l4_n524(x) + if (x < 1) + fun_l5_n836(x) + else + fun_l5_n838(x) + end +end + +def fun_l4_n525(x) + if (x < 1) + fun_l5_n781(x) + else + fun_l5_n183(x) + end +end + +def fun_l4_n526(x) + if (x < 1) + fun_l5_n335(x) + else + fun_l5_n809(x) + end +end + +def fun_l4_n527(x) + if (x < 1) + fun_l5_n748(x) + else + fun_l5_n674(x) + end +end + +def fun_l4_n528(x) + if (x < 1) + fun_l5_n612(x) + else + fun_l5_n933(x) + end +end + +def fun_l4_n529(x) + if (x < 1) + fun_l5_n781(x) + else + fun_l5_n174(x) + end +end + +def fun_l4_n530(x) + if (x < 1) + fun_l5_n299(x) + else + fun_l5_n677(x) + end +end + +def fun_l4_n531(x) + if (x < 1) + fun_l5_n455(x) + else + fun_l5_n211(x) + end +end + +def fun_l4_n532(x) + if (x < 1) + fun_l5_n981(x) + else + fun_l5_n605(x) + end +end + +def fun_l4_n533(x) + if (x < 1) + fun_l5_n299(x) + else + fun_l5_n30(x) + end +end + +def fun_l4_n534(x) + if (x < 1) + fun_l5_n642(x) + else + fun_l5_n652(x) + end +end + +def fun_l4_n535(x) + if (x < 1) + fun_l5_n904(x) + else + fun_l5_n133(x) + end +end + +def fun_l4_n536(x) + if (x < 1) + fun_l5_n253(x) + else + fun_l5_n330(x) + end +end + +def fun_l4_n537(x) + if (x < 1) + fun_l5_n357(x) + else + fun_l5_n533(x) + end +end + +def fun_l4_n538(x) + if (x < 1) + fun_l5_n484(x) + else + fun_l5_n438(x) + end +end + +def fun_l4_n539(x) + if (x < 1) + fun_l5_n200(x) + else + fun_l5_n235(x) + end +end + +def fun_l4_n540(x) + if (x < 1) + fun_l5_n929(x) + else + fun_l5_n875(x) + end +end + +def fun_l4_n541(x) + if (x < 1) + fun_l5_n237(x) + else + fun_l5_n688(x) + end +end + +def fun_l4_n542(x) + if (x < 1) + fun_l5_n723(x) + else + fun_l5_n308(x) + end +end + +def fun_l4_n543(x) + if (x < 1) + fun_l5_n591(x) + else + fun_l5_n93(x) + end +end + +def fun_l4_n544(x) + if (x < 1) + fun_l5_n258(x) + else + fun_l5_n205(x) + end +end + +def fun_l4_n545(x) + if (x < 1) + fun_l5_n910(x) + else + fun_l5_n529(x) + end +end + +def fun_l4_n546(x) + if (x < 1) + fun_l5_n255(x) + else + fun_l5_n262(x) + end +end + +def fun_l4_n547(x) + if (x < 1) + fun_l5_n674(x) + else + fun_l5_n813(x) + end +end + +def fun_l4_n548(x) + if (x < 1) + fun_l5_n9(x) + else + fun_l5_n709(x) + end +end + +def fun_l4_n549(x) + if (x < 1) + fun_l5_n146(x) + else + fun_l5_n801(x) + end +end + +def fun_l4_n550(x) + if (x < 1) + fun_l5_n593(x) + else + fun_l5_n428(x) + end +end + +def fun_l4_n551(x) + if (x < 1) + fun_l5_n953(x) + else + fun_l5_n238(x) + end +end + +def fun_l4_n552(x) + if (x < 1) + fun_l5_n900(x) + else + fun_l5_n246(x) + end +end + +def fun_l4_n553(x) + if (x < 1) + fun_l5_n400(x) + else + fun_l5_n150(x) + end +end + +def fun_l4_n554(x) + if (x < 1) + fun_l5_n697(x) + else + fun_l5_n681(x) + end +end + +def fun_l4_n555(x) + if (x < 1) + fun_l5_n487(x) + else + fun_l5_n784(x) + end +end + +def fun_l4_n556(x) + if (x < 1) + fun_l5_n485(x) + else + fun_l5_n984(x) + end +end + +def fun_l4_n557(x) + if (x < 1) + fun_l5_n774(x) + else + fun_l5_n864(x) + end +end + +def fun_l4_n558(x) + if (x < 1) + fun_l5_n823(x) + else + fun_l5_n527(x) + end +end + +def fun_l4_n559(x) + if (x < 1) + fun_l5_n204(x) + else + fun_l5_n114(x) + end +end + +def fun_l4_n560(x) + if (x < 1) + fun_l5_n835(x) + else + fun_l5_n930(x) + end +end + +def fun_l4_n561(x) + if (x < 1) + fun_l5_n481(x) + else + fun_l5_n471(x) + end +end + +def fun_l4_n562(x) + if (x < 1) + fun_l5_n459(x) + else + fun_l5_n526(x) + end +end + +def fun_l4_n563(x) + if (x < 1) + fun_l5_n148(x) + else + fun_l5_n473(x) + end +end + +def fun_l4_n564(x) + if (x < 1) + fun_l5_n448(x) + else + fun_l5_n389(x) + end +end + +def fun_l4_n565(x) + if (x < 1) + fun_l5_n600(x) + else + fun_l5_n405(x) + end +end + +def fun_l4_n566(x) + if (x < 1) + fun_l5_n67(x) + else + fun_l5_n145(x) + end +end + +def fun_l4_n567(x) + if (x < 1) + fun_l5_n63(x) + else + fun_l5_n206(x) + end +end + +def fun_l4_n568(x) + if (x < 1) + fun_l5_n463(x) + else + fun_l5_n288(x) + end +end + +def fun_l4_n569(x) + if (x < 1) + fun_l5_n143(x) + else + fun_l5_n879(x) + end +end + +def fun_l4_n570(x) + if (x < 1) + fun_l5_n552(x) + else + fun_l5_n517(x) + end +end + +def fun_l4_n571(x) + if (x < 1) + fun_l5_n527(x) + else + fun_l5_n680(x) + end +end + +def fun_l4_n572(x) + if (x < 1) + fun_l5_n853(x) + else + fun_l5_n97(x) + end +end + +def fun_l4_n573(x) + if (x < 1) + fun_l5_n277(x) + else + fun_l5_n329(x) + end +end + +def fun_l4_n574(x) + if (x < 1) + fun_l5_n952(x) + else + fun_l5_n515(x) + end +end + +def fun_l4_n575(x) + if (x < 1) + fun_l5_n64(x) + else + fun_l5_n576(x) + end +end + +def fun_l4_n576(x) + if (x < 1) + fun_l5_n57(x) + else + fun_l5_n499(x) + end +end + +def fun_l4_n577(x) + if (x < 1) + fun_l5_n10(x) + else + fun_l5_n208(x) + end +end + +def fun_l4_n578(x) + if (x < 1) + fun_l5_n361(x) + else + fun_l5_n447(x) + end +end + +def fun_l4_n579(x) + if (x < 1) + fun_l5_n788(x) + else + fun_l5_n299(x) + end +end + +def fun_l4_n580(x) + if (x < 1) + fun_l5_n973(x) + else + fun_l5_n753(x) + end +end + +def fun_l4_n581(x) + if (x < 1) + fun_l5_n862(x) + else + fun_l5_n110(x) + end +end + +def fun_l4_n582(x) + if (x < 1) + fun_l5_n760(x) + else + fun_l5_n256(x) + end +end + +def fun_l4_n583(x) + if (x < 1) + fun_l5_n8(x) + else + fun_l5_n922(x) + end +end + +def fun_l4_n584(x) + if (x < 1) + fun_l5_n100(x) + else + fun_l5_n230(x) + end +end + +def fun_l4_n585(x) + if (x < 1) + fun_l5_n183(x) + else + fun_l5_n350(x) + end +end + +def fun_l4_n586(x) + if (x < 1) + fun_l5_n294(x) + else + fun_l5_n673(x) + end +end + +def fun_l4_n587(x) + if (x < 1) + fun_l5_n51(x) + else + fun_l5_n718(x) + end +end + +def fun_l4_n588(x) + if (x < 1) + fun_l5_n257(x) + else + fun_l5_n111(x) + end +end + +def fun_l4_n589(x) + if (x < 1) + fun_l5_n727(x) + else + fun_l5_n585(x) + end +end + +def fun_l4_n590(x) + if (x < 1) + fun_l5_n205(x) + else + fun_l5_n308(x) + end +end + +def fun_l4_n591(x) + if (x < 1) + fun_l5_n618(x) + else + fun_l5_n970(x) + end +end + +def fun_l4_n592(x) + if (x < 1) + fun_l5_n631(x) + else + fun_l5_n513(x) + end +end + +def fun_l4_n593(x) + if (x < 1) + fun_l5_n270(x) + else + fun_l5_n737(x) + end +end + +def fun_l4_n594(x) + if (x < 1) + fun_l5_n464(x) + else + fun_l5_n217(x) + end +end + +def fun_l4_n595(x) + if (x < 1) + fun_l5_n650(x) + else + fun_l5_n616(x) + end +end + +def fun_l4_n596(x) + if (x < 1) + fun_l5_n542(x) + else + fun_l5_n613(x) + end +end + +def fun_l4_n597(x) + if (x < 1) + fun_l5_n312(x) + else + fun_l5_n7(x) + end +end + +def fun_l4_n598(x) + if (x < 1) + fun_l5_n164(x) + else + fun_l5_n592(x) + end +end + +def fun_l4_n599(x) + if (x < 1) + fun_l5_n326(x) + else + fun_l5_n894(x) + end +end + +def fun_l4_n600(x) + if (x < 1) + fun_l5_n243(x) + else + fun_l5_n233(x) + end +end + +def fun_l4_n601(x) + if (x < 1) + fun_l5_n600(x) + else + fun_l5_n7(x) + end +end + +def fun_l4_n602(x) + if (x < 1) + fun_l5_n334(x) + else + fun_l5_n282(x) + end +end + +def fun_l4_n603(x) + if (x < 1) + fun_l5_n202(x) + else + fun_l5_n252(x) + end +end + +def fun_l4_n604(x) + if (x < 1) + fun_l5_n173(x) + else + fun_l5_n685(x) + end +end + +def fun_l4_n605(x) + if (x < 1) + fun_l5_n953(x) + else + fun_l5_n416(x) + end +end + +def fun_l4_n606(x) + if (x < 1) + fun_l5_n775(x) + else + fun_l5_n372(x) + end +end + +def fun_l4_n607(x) + if (x < 1) + fun_l5_n723(x) + else + fun_l5_n894(x) + end +end + +def fun_l4_n608(x) + if (x < 1) + fun_l5_n690(x) + else + fun_l5_n26(x) + end +end + +def fun_l4_n609(x) + if (x < 1) + fun_l5_n555(x) + else + fun_l5_n717(x) + end +end + +def fun_l4_n610(x) + if (x < 1) + fun_l5_n597(x) + else + fun_l5_n106(x) + end +end + +def fun_l4_n611(x) + if (x < 1) + fun_l5_n405(x) + else + fun_l5_n588(x) + end +end + +def fun_l4_n612(x) + if (x < 1) + fun_l5_n41(x) + else + fun_l5_n558(x) + end +end + +def fun_l4_n613(x) + if (x < 1) + fun_l5_n875(x) + else + fun_l5_n492(x) + end +end + +def fun_l4_n614(x) + if (x < 1) + fun_l5_n605(x) + else + fun_l5_n461(x) + end +end + +def fun_l4_n615(x) + if (x < 1) + fun_l5_n726(x) + else + fun_l5_n534(x) + end +end + +def fun_l4_n616(x) + if (x < 1) + fun_l5_n919(x) + else + fun_l5_n404(x) + end +end + +def fun_l4_n617(x) + if (x < 1) + fun_l5_n383(x) + else + fun_l5_n324(x) + end +end + +def fun_l4_n618(x) + if (x < 1) + fun_l5_n286(x) + else + fun_l5_n157(x) + end +end + +def fun_l4_n619(x) + if (x < 1) + fun_l5_n713(x) + else + fun_l5_n388(x) + end +end + +def fun_l4_n620(x) + if (x < 1) + fun_l5_n773(x) + else + fun_l5_n790(x) + end +end + +def fun_l4_n621(x) + if (x < 1) + fun_l5_n797(x) + else + fun_l5_n720(x) + end +end + +def fun_l4_n622(x) + if (x < 1) + fun_l5_n799(x) + else + fun_l5_n423(x) + end +end + +def fun_l4_n623(x) + if (x < 1) + fun_l5_n390(x) + else + fun_l5_n941(x) + end +end + +def fun_l4_n624(x) + if (x < 1) + fun_l5_n584(x) + else + fun_l5_n191(x) + end +end + +def fun_l4_n625(x) + if (x < 1) + fun_l5_n243(x) + else + fun_l5_n208(x) + end +end + +def fun_l4_n626(x) + if (x < 1) + fun_l5_n136(x) + else + fun_l5_n791(x) + end +end + +def fun_l4_n627(x) + if (x < 1) + fun_l5_n684(x) + else + fun_l5_n341(x) + end +end + +def fun_l4_n628(x) + if (x < 1) + fun_l5_n876(x) + else + fun_l5_n27(x) + end +end + +def fun_l4_n629(x) + if (x < 1) + fun_l5_n18(x) + else + fun_l5_n867(x) + end +end + +def fun_l4_n630(x) + if (x < 1) + fun_l5_n4(x) + else + fun_l5_n871(x) + end +end + +def fun_l4_n631(x) + if (x < 1) + fun_l5_n578(x) + else + fun_l5_n988(x) + end +end + +def fun_l4_n632(x) + if (x < 1) + fun_l5_n388(x) + else + fun_l5_n258(x) + end +end + +def fun_l4_n633(x) + if (x < 1) + fun_l5_n680(x) + else + fun_l5_n814(x) + end +end + +def fun_l4_n634(x) + if (x < 1) + fun_l5_n857(x) + else + fun_l5_n595(x) + end +end + +def fun_l4_n635(x) + if (x < 1) + fun_l5_n547(x) + else + fun_l5_n725(x) + end +end + +def fun_l4_n636(x) + if (x < 1) + fun_l5_n644(x) + else + fun_l5_n485(x) + end +end + +def fun_l4_n637(x) + if (x < 1) + fun_l5_n528(x) + else + fun_l5_n653(x) + end +end + +def fun_l4_n638(x) + if (x < 1) + fun_l5_n924(x) + else + fun_l5_n956(x) + end +end + +def fun_l4_n639(x) + if (x < 1) + fun_l5_n654(x) + else + fun_l5_n979(x) + end +end + +def fun_l4_n640(x) + if (x < 1) + fun_l5_n287(x) + else + fun_l5_n778(x) + end +end + +def fun_l4_n641(x) + if (x < 1) + fun_l5_n197(x) + else + fun_l5_n682(x) + end +end + +def fun_l4_n642(x) + if (x < 1) + fun_l5_n559(x) + else + fun_l5_n812(x) + end +end + +def fun_l4_n643(x) + if (x < 1) + fun_l5_n970(x) + else + fun_l5_n43(x) + end +end + +def fun_l4_n644(x) + if (x < 1) + fun_l5_n222(x) + else + fun_l5_n741(x) + end +end + +def fun_l4_n645(x) + if (x < 1) + fun_l5_n788(x) + else + fun_l5_n72(x) + end +end + +def fun_l4_n646(x) + if (x < 1) + fun_l5_n877(x) + else + fun_l5_n371(x) + end +end + +def fun_l4_n647(x) + if (x < 1) + fun_l5_n710(x) + else + fun_l5_n783(x) + end +end + +def fun_l4_n648(x) + if (x < 1) + fun_l5_n957(x) + else + fun_l5_n801(x) + end +end + +def fun_l4_n649(x) + if (x < 1) + fun_l5_n127(x) + else + fun_l5_n664(x) + end +end + +def fun_l4_n650(x) + if (x < 1) + fun_l5_n176(x) + else + fun_l5_n511(x) + end +end + +def fun_l4_n651(x) + if (x < 1) + fun_l5_n830(x) + else + fun_l5_n107(x) + end +end + +def fun_l4_n652(x) + if (x < 1) + fun_l5_n207(x) + else + fun_l5_n894(x) + end +end + +def fun_l4_n653(x) + if (x < 1) + fun_l5_n611(x) + else + fun_l5_n443(x) + end +end + +def fun_l4_n654(x) + if (x < 1) + fun_l5_n953(x) + else + fun_l5_n214(x) + end +end + +def fun_l4_n655(x) + if (x < 1) + fun_l5_n109(x) + else + fun_l5_n706(x) + end +end + +def fun_l4_n656(x) + if (x < 1) + fun_l5_n312(x) + else + fun_l5_n914(x) + end +end + +def fun_l4_n657(x) + if (x < 1) + fun_l5_n774(x) + else + fun_l5_n530(x) + end +end + +def fun_l4_n658(x) + if (x < 1) + fun_l5_n79(x) + else + fun_l5_n303(x) + end +end + +def fun_l4_n659(x) + if (x < 1) + fun_l5_n718(x) + else + fun_l5_n196(x) + end +end + +def fun_l4_n660(x) + if (x < 1) + fun_l5_n196(x) + else + fun_l5_n661(x) + end +end + +def fun_l4_n661(x) + if (x < 1) + fun_l5_n654(x) + else + fun_l5_n17(x) + end +end + +def fun_l4_n662(x) + if (x < 1) + fun_l5_n413(x) + else + fun_l5_n214(x) + end +end + +def fun_l4_n663(x) + if (x < 1) + fun_l5_n491(x) + else + fun_l5_n927(x) + end +end + +def fun_l4_n664(x) + if (x < 1) + fun_l5_n671(x) + else + fun_l5_n611(x) + end +end + +def fun_l4_n665(x) + if (x < 1) + fun_l5_n153(x) + else + fun_l5_n127(x) + end +end + +def fun_l4_n666(x) + if (x < 1) + fun_l5_n661(x) + else + fun_l5_n590(x) + end +end + +def fun_l4_n667(x) + if (x < 1) + fun_l5_n539(x) + else + fun_l5_n692(x) + end +end + +def fun_l4_n668(x) + if (x < 1) + fun_l5_n390(x) + else + fun_l5_n423(x) + end +end + +def fun_l4_n669(x) + if (x < 1) + fun_l5_n615(x) + else + fun_l5_n449(x) + end +end + +def fun_l4_n670(x) + if (x < 1) + fun_l5_n49(x) + else + fun_l5_n632(x) + end +end + +def fun_l4_n671(x) + if (x < 1) + fun_l5_n891(x) + else + fun_l5_n915(x) + end +end + +def fun_l4_n672(x) + if (x < 1) + fun_l5_n257(x) + else + fun_l5_n719(x) + end +end + +def fun_l4_n673(x) + if (x < 1) + fun_l5_n620(x) + else + fun_l5_n473(x) + end +end + +def fun_l4_n674(x) + if (x < 1) + fun_l5_n422(x) + else + fun_l5_n776(x) + end +end + +def fun_l4_n675(x) + if (x < 1) + fun_l5_n973(x) + else + fun_l5_n32(x) + end +end + +def fun_l4_n676(x) + if (x < 1) + fun_l5_n434(x) + else + fun_l5_n85(x) + end +end + +def fun_l4_n677(x) + if (x < 1) + fun_l5_n430(x) + else + fun_l5_n702(x) + end +end + +def fun_l4_n678(x) + if (x < 1) + fun_l5_n698(x) + else + fun_l5_n482(x) + end +end + +def fun_l4_n679(x) + if (x < 1) + fun_l5_n365(x) + else + fun_l5_n83(x) + end +end + +def fun_l4_n680(x) + if (x < 1) + fun_l5_n397(x) + else + fun_l5_n356(x) + end +end + +def fun_l4_n681(x) + if (x < 1) + fun_l5_n48(x) + else + fun_l5_n458(x) + end +end + +def fun_l4_n682(x) + if (x < 1) + fun_l5_n205(x) + else + fun_l5_n693(x) + end +end + +def fun_l4_n683(x) + if (x < 1) + fun_l5_n971(x) + else + fun_l5_n656(x) + end +end + +def fun_l4_n684(x) + if (x < 1) + fun_l5_n147(x) + else + fun_l5_n314(x) + end +end + +def fun_l4_n685(x) + if (x < 1) + fun_l5_n347(x) + else + fun_l5_n281(x) + end +end + +def fun_l4_n686(x) + if (x < 1) + fun_l5_n259(x) + else + fun_l5_n395(x) + end +end + +def fun_l4_n687(x) + if (x < 1) + fun_l5_n899(x) + else + fun_l5_n319(x) + end +end + +def fun_l4_n688(x) + if (x < 1) + fun_l5_n293(x) + else + fun_l5_n831(x) + end +end + +def fun_l4_n689(x) + if (x < 1) + fun_l5_n88(x) + else + fun_l5_n938(x) + end +end + +def fun_l4_n690(x) + if (x < 1) + fun_l5_n72(x) + else + fun_l5_n172(x) + end +end + +def fun_l4_n691(x) + if (x < 1) + fun_l5_n330(x) + else + fun_l5_n70(x) + end +end + +def fun_l4_n692(x) + if (x < 1) + fun_l5_n901(x) + else + fun_l5_n984(x) + end +end + +def fun_l4_n693(x) + if (x < 1) + fun_l5_n528(x) + else + fun_l5_n659(x) + end +end + +def fun_l4_n694(x) + if (x < 1) + fun_l5_n522(x) + else + fun_l5_n219(x) + end +end + +def fun_l4_n695(x) + if (x < 1) + fun_l5_n568(x) + else + fun_l5_n997(x) + end +end + +def fun_l4_n696(x) + if (x < 1) + fun_l5_n248(x) + else + fun_l5_n508(x) + end +end + +def fun_l4_n697(x) + if (x < 1) + fun_l5_n71(x) + else + fun_l5_n590(x) + end +end + +def fun_l4_n698(x) + if (x < 1) + fun_l5_n398(x) + else + fun_l5_n125(x) + end +end + +def fun_l4_n699(x) + if (x < 1) + fun_l5_n405(x) + else + fun_l5_n129(x) + end +end + +def fun_l4_n700(x) + if (x < 1) + fun_l5_n818(x) + else + fun_l5_n792(x) + end +end + +def fun_l4_n701(x) + if (x < 1) + fun_l5_n530(x) + else + fun_l5_n849(x) + end +end + +def fun_l4_n702(x) + if (x < 1) + fun_l5_n640(x) + else + fun_l5_n558(x) + end +end + +def fun_l4_n703(x) + if (x < 1) + fun_l5_n717(x) + else + fun_l5_n113(x) + end +end + +def fun_l4_n704(x) + if (x < 1) + fun_l5_n139(x) + else + fun_l5_n743(x) + end +end + +def fun_l4_n705(x) + if (x < 1) + fun_l5_n720(x) + else + fun_l5_n713(x) + end +end + +def fun_l4_n706(x) + if (x < 1) + fun_l5_n774(x) + else + fun_l5_n90(x) + end +end + +def fun_l4_n707(x) + if (x < 1) + fun_l5_n579(x) + else + fun_l5_n692(x) + end +end + +def fun_l4_n708(x) + if (x < 1) + fun_l5_n448(x) + else + fun_l5_n146(x) + end +end + +def fun_l4_n709(x) + if (x < 1) + fun_l5_n249(x) + else + fun_l5_n163(x) + end +end + +def fun_l4_n710(x) + if (x < 1) + fun_l5_n694(x) + else + fun_l5_n532(x) + end +end + +def fun_l4_n711(x) + if (x < 1) + fun_l5_n739(x) + else + fun_l5_n424(x) + end +end + +def fun_l4_n712(x) + if (x < 1) + fun_l5_n700(x) + else + fun_l5_n761(x) + end +end + +def fun_l4_n713(x) + if (x < 1) + fun_l5_n403(x) + else + fun_l5_n941(x) + end +end + +def fun_l4_n714(x) + if (x < 1) + fun_l5_n724(x) + else + fun_l5_n863(x) + end +end + +def fun_l4_n715(x) + if (x < 1) + fun_l5_n392(x) + else + fun_l5_n617(x) + end +end + +def fun_l4_n716(x) + if (x < 1) + fun_l5_n76(x) + else + fun_l5_n896(x) + end +end + +def fun_l4_n717(x) + if (x < 1) + fun_l5_n355(x) + else + fun_l5_n533(x) + end +end + +def fun_l4_n718(x) + if (x < 1) + fun_l5_n225(x) + else + fun_l5_n273(x) + end +end + +def fun_l4_n719(x) + if (x < 1) + fun_l5_n828(x) + else + fun_l5_n163(x) + end +end + +def fun_l4_n720(x) + if (x < 1) + fun_l5_n309(x) + else + fun_l5_n702(x) + end +end + +def fun_l4_n721(x) + if (x < 1) + fun_l5_n959(x) + else + fun_l5_n370(x) + end +end + +def fun_l4_n722(x) + if (x < 1) + fun_l5_n640(x) + else + fun_l5_n96(x) + end +end + +def fun_l4_n723(x) + if (x < 1) + fun_l5_n590(x) + else + fun_l5_n332(x) + end +end + +def fun_l4_n724(x) + if (x < 1) + fun_l5_n14(x) + else + fun_l5_n161(x) + end +end + +def fun_l4_n725(x) + if (x < 1) + fun_l5_n871(x) + else + fun_l5_n643(x) + end +end + +def fun_l4_n726(x) + if (x < 1) + fun_l5_n885(x) + else + fun_l5_n142(x) + end +end + +def fun_l4_n727(x) + if (x < 1) + fun_l5_n994(x) + else + fun_l5_n823(x) + end +end + +def fun_l4_n728(x) + if (x < 1) + fun_l5_n825(x) + else + fun_l5_n315(x) + end +end + +def fun_l4_n729(x) + if (x < 1) + fun_l5_n312(x) + else + fun_l5_n28(x) + end +end + +def fun_l4_n730(x) + if (x < 1) + fun_l5_n545(x) + else + fun_l5_n87(x) + end +end + +def fun_l4_n731(x) + if (x < 1) + fun_l5_n604(x) + else + fun_l5_n999(x) + end +end + +def fun_l4_n732(x) + if (x < 1) + fun_l5_n21(x) + else + fun_l5_n170(x) + end +end + +def fun_l4_n733(x) + if (x < 1) + fun_l5_n662(x) + else + fun_l5_n407(x) + end +end + +def fun_l4_n734(x) + if (x < 1) + fun_l5_n808(x) + else + fun_l5_n653(x) + end +end + +def fun_l4_n735(x) + if (x < 1) + fun_l5_n665(x) + else + fun_l5_n925(x) + end +end + +def fun_l4_n736(x) + if (x < 1) + fun_l5_n186(x) + else + fun_l5_n817(x) + end +end + +def fun_l4_n737(x) + if (x < 1) + fun_l5_n360(x) + else + fun_l5_n527(x) + end +end + +def fun_l4_n738(x) + if (x < 1) + fun_l5_n278(x) + else + fun_l5_n759(x) + end +end + +def fun_l4_n739(x) + if (x < 1) + fun_l5_n710(x) + else + fun_l5_n909(x) + end +end + +def fun_l4_n740(x) + if (x < 1) + fun_l5_n770(x) + else + fun_l5_n382(x) + end +end + +def fun_l4_n741(x) + if (x < 1) + fun_l5_n969(x) + else + fun_l5_n583(x) + end +end + +def fun_l4_n742(x) + if (x < 1) + fun_l5_n653(x) + else + fun_l5_n258(x) + end +end + +def fun_l4_n743(x) + if (x < 1) + fun_l5_n966(x) + else + fun_l5_n705(x) + end +end + +def fun_l4_n744(x) + if (x < 1) + fun_l5_n454(x) + else + fun_l5_n748(x) + end +end + +def fun_l4_n745(x) + if (x < 1) + fun_l5_n595(x) + else + fun_l5_n865(x) + end +end + +def fun_l4_n746(x) + if (x < 1) + fun_l5_n593(x) + else + fun_l5_n615(x) + end +end + +def fun_l4_n747(x) + if (x < 1) + fun_l5_n638(x) + else + fun_l5_n651(x) + end +end + +def fun_l4_n748(x) + if (x < 1) + fun_l5_n331(x) + else + fun_l5_n847(x) + end +end + +def fun_l4_n749(x) + if (x < 1) + fun_l5_n59(x) + else + fun_l5_n805(x) + end +end + +def fun_l4_n750(x) + if (x < 1) + fun_l5_n269(x) + else + fun_l5_n904(x) + end +end + +def fun_l4_n751(x) + if (x < 1) + fun_l5_n292(x) + else + fun_l5_n459(x) + end +end + +def fun_l4_n752(x) + if (x < 1) + fun_l5_n581(x) + else + fun_l5_n353(x) + end +end + +def fun_l4_n753(x) + if (x < 1) + fun_l5_n785(x) + else + fun_l5_n745(x) + end +end + +def fun_l4_n754(x) + if (x < 1) + fun_l5_n317(x) + else + fun_l5_n604(x) + end +end + +def fun_l4_n755(x) + if (x < 1) + fun_l5_n208(x) + else + fun_l5_n318(x) + end +end + +def fun_l4_n756(x) + if (x < 1) + fun_l5_n986(x) + else + fun_l5_n83(x) + end +end + +def fun_l4_n757(x) + if (x < 1) + fun_l5_n946(x) + else + fun_l5_n314(x) + end +end + +def fun_l4_n758(x) + if (x < 1) + fun_l5_n571(x) + else + fun_l5_n919(x) + end +end + +def fun_l4_n759(x) + if (x < 1) + fun_l5_n129(x) + else + fun_l5_n191(x) + end +end + +def fun_l4_n760(x) + if (x < 1) + fun_l5_n838(x) + else + fun_l5_n29(x) + end +end + +def fun_l4_n761(x) + if (x < 1) + fun_l5_n250(x) + else + fun_l5_n892(x) + end +end + +def fun_l4_n762(x) + if (x < 1) + fun_l5_n588(x) + else + fun_l5_n59(x) + end +end + +def fun_l4_n763(x) + if (x < 1) + fun_l5_n831(x) + else + fun_l5_n668(x) + end +end + +def fun_l4_n764(x) + if (x < 1) + fun_l5_n337(x) + else + fun_l5_n514(x) + end +end + +def fun_l4_n765(x) + if (x < 1) + fun_l5_n56(x) + else + fun_l5_n718(x) + end +end + +def fun_l4_n766(x) + if (x < 1) + fun_l5_n189(x) + else + fun_l5_n103(x) + end +end + +def fun_l4_n767(x) + if (x < 1) + fun_l5_n395(x) + else + fun_l5_n313(x) + end +end + +def fun_l4_n768(x) + if (x < 1) + fun_l5_n388(x) + else + fun_l5_n757(x) + end +end + +def fun_l4_n769(x) + if (x < 1) + fun_l5_n933(x) + else + fun_l5_n979(x) + end +end + +def fun_l4_n770(x) + if (x < 1) + fun_l5_n765(x) + else + fun_l5_n472(x) + end +end + +def fun_l4_n771(x) + if (x < 1) + fun_l5_n381(x) + else + fun_l5_n527(x) + end +end + +def fun_l4_n772(x) + if (x < 1) + fun_l5_n314(x) + else + fun_l5_n990(x) + end +end + +def fun_l4_n773(x) + if (x < 1) + fun_l5_n457(x) + else + fun_l5_n413(x) + end +end + +def fun_l4_n774(x) + if (x < 1) + fun_l5_n245(x) + else + fun_l5_n85(x) + end +end + +def fun_l4_n775(x) + if (x < 1) + fun_l5_n432(x) + else + fun_l5_n987(x) + end +end + +def fun_l4_n776(x) + if (x < 1) + fun_l5_n588(x) + else + fun_l5_n352(x) + end +end + +def fun_l4_n777(x) + if (x < 1) + fun_l5_n414(x) + else + fun_l5_n586(x) + end +end + +def fun_l4_n778(x) + if (x < 1) + fun_l5_n290(x) + else + fun_l5_n776(x) + end +end + +def fun_l4_n779(x) + if (x < 1) + fun_l5_n324(x) + else + fun_l5_n918(x) + end +end + +def fun_l4_n780(x) + if (x < 1) + fun_l5_n928(x) + else + fun_l5_n107(x) + end +end + +def fun_l4_n781(x) + if (x < 1) + fun_l5_n244(x) + else + fun_l5_n434(x) + end +end + +def fun_l4_n782(x) + if (x < 1) + fun_l5_n828(x) + else + fun_l5_n141(x) + end +end + +def fun_l4_n783(x) + if (x < 1) + fun_l5_n634(x) + else + fun_l5_n206(x) + end +end + +def fun_l4_n784(x) + if (x < 1) + fun_l5_n387(x) + else + fun_l5_n57(x) + end +end + +def fun_l4_n785(x) + if (x < 1) + fun_l5_n731(x) + else + fun_l5_n670(x) + end +end + +def fun_l4_n786(x) + if (x < 1) + fun_l5_n173(x) + else + fun_l5_n657(x) + end +end + +def fun_l4_n787(x) + if (x < 1) + fun_l5_n661(x) + else + fun_l5_n286(x) + end +end + +def fun_l4_n788(x) + if (x < 1) + fun_l5_n364(x) + else + fun_l5_n520(x) + end +end + +def fun_l4_n789(x) + if (x < 1) + fun_l5_n545(x) + else + fun_l5_n417(x) + end +end + +def fun_l4_n790(x) + if (x < 1) + fun_l5_n270(x) + else + fun_l5_n550(x) + end +end + +def fun_l4_n791(x) + if (x < 1) + fun_l5_n873(x) + else + fun_l5_n321(x) + end +end + +def fun_l4_n792(x) + if (x < 1) + fun_l5_n243(x) + else + fun_l5_n406(x) + end +end + +def fun_l4_n793(x) + if (x < 1) + fun_l5_n229(x) + else + fun_l5_n400(x) + end +end + +def fun_l4_n794(x) + if (x < 1) + fun_l5_n670(x) + else + fun_l5_n535(x) + end +end + +def fun_l4_n795(x) + if (x < 1) + fun_l5_n911(x) + else + fun_l5_n786(x) + end +end + +def fun_l4_n796(x) + if (x < 1) + fun_l5_n247(x) + else + fun_l5_n775(x) + end +end + +def fun_l4_n797(x) + if (x < 1) + fun_l5_n944(x) + else + fun_l5_n14(x) + end +end + +def fun_l4_n798(x) + if (x < 1) + fun_l5_n57(x) + else + fun_l5_n644(x) + end +end + +def fun_l4_n799(x) + if (x < 1) + fun_l5_n583(x) + else + fun_l5_n599(x) + end +end + +def fun_l4_n800(x) + if (x < 1) + fun_l5_n685(x) + else + fun_l5_n366(x) + end +end + +def fun_l4_n801(x) + if (x < 1) + fun_l5_n671(x) + else + fun_l5_n386(x) + end +end + +def fun_l4_n802(x) + if (x < 1) + fun_l5_n19(x) + else + fun_l5_n403(x) + end +end + +def fun_l4_n803(x) + if (x < 1) + fun_l5_n952(x) + else + fun_l5_n237(x) + end +end + +def fun_l4_n804(x) + if (x < 1) + fun_l5_n929(x) + else + fun_l5_n737(x) + end +end + +def fun_l4_n805(x) + if (x < 1) + fun_l5_n197(x) + else + fun_l5_n322(x) + end +end + +def fun_l4_n806(x) + if (x < 1) + fun_l5_n966(x) + else + fun_l5_n531(x) + end +end + +def fun_l4_n807(x) + if (x < 1) + fun_l5_n928(x) + else + fun_l5_n802(x) + end +end + +def fun_l4_n808(x) + if (x < 1) + fun_l5_n34(x) + else + fun_l5_n107(x) + end +end + +def fun_l4_n809(x) + if (x < 1) + fun_l5_n615(x) + else + fun_l5_n628(x) + end +end + +def fun_l4_n810(x) + if (x < 1) + fun_l5_n187(x) + else + fun_l5_n424(x) + end +end + +def fun_l4_n811(x) + if (x < 1) + fun_l5_n189(x) + else + fun_l5_n639(x) + end +end + +def fun_l4_n812(x) + if (x < 1) + fun_l5_n177(x) + else + fun_l5_n580(x) + end +end + +def fun_l4_n813(x) + if (x < 1) + fun_l5_n699(x) + else + fun_l5_n595(x) + end +end + +def fun_l4_n814(x) + if (x < 1) + fun_l5_n44(x) + else + fun_l5_n966(x) + end +end + +def fun_l4_n815(x) + if (x < 1) + fun_l5_n883(x) + else + fun_l5_n580(x) + end +end + +def fun_l4_n816(x) + if (x < 1) + fun_l5_n306(x) + else + fun_l5_n564(x) + end +end + +def fun_l4_n817(x) + if (x < 1) + fun_l5_n337(x) + else + fun_l5_n912(x) + end +end + +def fun_l4_n818(x) + if (x < 1) + fun_l5_n36(x) + else + fun_l5_n164(x) + end +end + +def fun_l4_n819(x) + if (x < 1) + fun_l5_n987(x) + else + fun_l5_n38(x) + end +end + +def fun_l4_n820(x) + if (x < 1) + fun_l5_n656(x) + else + fun_l5_n647(x) + end +end + +def fun_l4_n821(x) + if (x < 1) + fun_l5_n364(x) + else + fun_l5_n838(x) + end +end + +def fun_l4_n822(x) + if (x < 1) + fun_l5_n301(x) + else + fun_l5_n850(x) + end +end + +def fun_l4_n823(x) + if (x < 1) + fun_l5_n191(x) + else + fun_l5_n812(x) + end +end + +def fun_l4_n824(x) + if (x < 1) + fun_l5_n148(x) + else + fun_l5_n332(x) + end +end + +def fun_l4_n825(x) + if (x < 1) + fun_l5_n315(x) + else + fun_l5_n763(x) + end +end + +def fun_l4_n826(x) + if (x < 1) + fun_l5_n612(x) + else + fun_l5_n993(x) + end +end + +def fun_l4_n827(x) + if (x < 1) + fun_l5_n229(x) + else + fun_l5_n388(x) + end +end + +def fun_l4_n828(x) + if (x < 1) + fun_l5_n131(x) + else + fun_l5_n283(x) + end +end + +def fun_l4_n829(x) + if (x < 1) + fun_l5_n59(x) + else + fun_l5_n280(x) + end +end + +def fun_l4_n830(x) + if (x < 1) + fun_l5_n993(x) + else + fun_l5_n160(x) + end +end + +def fun_l4_n831(x) + if (x < 1) + fun_l5_n394(x) + else + fun_l5_n528(x) + end +end + +def fun_l4_n832(x) + if (x < 1) + fun_l5_n376(x) + else + fun_l5_n201(x) + end +end + +def fun_l4_n833(x) + if (x < 1) + fun_l5_n890(x) + else + fun_l5_n867(x) + end +end + +def fun_l4_n834(x) + if (x < 1) + fun_l5_n320(x) + else + fun_l5_n237(x) + end +end + +def fun_l4_n835(x) + if (x < 1) + fun_l5_n771(x) + else + fun_l5_n83(x) + end +end + +def fun_l4_n836(x) + if (x < 1) + fun_l5_n751(x) + else + fun_l5_n2(x) + end +end + +def fun_l4_n837(x) + if (x < 1) + fun_l5_n825(x) + else + fun_l5_n930(x) + end +end + +def fun_l4_n838(x) + if (x < 1) + fun_l5_n968(x) + else + fun_l5_n136(x) + end +end + +def fun_l4_n839(x) + if (x < 1) + fun_l5_n529(x) + else + fun_l5_n626(x) + end +end + +def fun_l4_n840(x) + if (x < 1) + fun_l5_n228(x) + else + fun_l5_n915(x) + end +end + +def fun_l4_n841(x) + if (x < 1) + fun_l5_n270(x) + else + fun_l5_n813(x) + end +end + +def fun_l4_n842(x) + if (x < 1) + fun_l5_n392(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n843(x) + if (x < 1) + fun_l5_n470(x) + else + fun_l5_n699(x) + end +end + +def fun_l4_n844(x) + if (x < 1) + fun_l5_n68(x) + else + fun_l5_n163(x) + end +end + +def fun_l4_n845(x) + if (x < 1) + fun_l5_n469(x) + else + fun_l5_n472(x) + end +end + +def fun_l4_n846(x) + if (x < 1) + fun_l5_n640(x) + else + fun_l5_n311(x) + end +end + +def fun_l4_n847(x) + if (x < 1) + fun_l5_n968(x) + else + fun_l5_n414(x) + end +end + +def fun_l4_n848(x) + if (x < 1) + fun_l5_n111(x) + else + fun_l5_n340(x) + end +end + +def fun_l4_n849(x) + if (x < 1) + fun_l5_n906(x) + else + fun_l5_n278(x) + end +end + +def fun_l4_n850(x) + if (x < 1) + fun_l5_n353(x) + else + fun_l5_n590(x) + end +end + +def fun_l4_n851(x) + if (x < 1) + fun_l5_n218(x) + else + fun_l5_n341(x) + end +end + +def fun_l4_n852(x) + if (x < 1) + fun_l5_n527(x) + else + fun_l5_n273(x) + end +end + +def fun_l4_n853(x) + if (x < 1) + fun_l5_n589(x) + else + fun_l5_n417(x) + end +end + +def fun_l4_n854(x) + if (x < 1) + fun_l5_n411(x) + else + fun_l5_n848(x) + end +end + +def fun_l4_n855(x) + if (x < 1) + fun_l5_n607(x) + else + fun_l5_n65(x) + end +end + +def fun_l4_n856(x) + if (x < 1) + fun_l5_n240(x) + else + fun_l5_n24(x) + end +end + +def fun_l4_n857(x) + if (x < 1) + fun_l5_n165(x) + else + fun_l5_n362(x) + end +end + +def fun_l4_n858(x) + if (x < 1) + fun_l5_n559(x) + else + fun_l5_n253(x) + end +end + +def fun_l4_n859(x) + if (x < 1) + fun_l5_n834(x) + else + fun_l5_n217(x) + end +end + +def fun_l4_n860(x) + if (x < 1) + fun_l5_n891(x) + else + fun_l5_n369(x) + end +end + +def fun_l4_n861(x) + if (x < 1) + fun_l5_n676(x) + else + fun_l5_n614(x) + end +end + +def fun_l4_n862(x) + if (x < 1) + fun_l5_n527(x) + else + fun_l5_n318(x) + end +end + +def fun_l4_n863(x) + if (x < 1) + fun_l5_n991(x) + else + fun_l5_n997(x) + end +end + +def fun_l4_n864(x) + if (x < 1) + fun_l5_n842(x) + else + fun_l5_n370(x) + end +end + +def fun_l4_n865(x) + if (x < 1) + fun_l5_n623(x) + else + fun_l5_n741(x) + end +end + +def fun_l4_n866(x) + if (x < 1) + fun_l5_n58(x) + else + fun_l5_n953(x) + end +end + +def fun_l4_n867(x) + if (x < 1) + fun_l5_n269(x) + else + fun_l5_n341(x) + end +end + +def fun_l4_n868(x) + if (x < 1) + fun_l5_n814(x) + else + fun_l5_n849(x) + end +end + +def fun_l4_n869(x) + if (x < 1) + fun_l5_n163(x) + else + fun_l5_n246(x) + end +end + +def fun_l4_n870(x) + if (x < 1) + fun_l5_n739(x) + else + fun_l5_n524(x) + end +end + +def fun_l4_n871(x) + if (x < 1) + fun_l5_n589(x) + else + fun_l5_n592(x) + end +end + +def fun_l4_n872(x) + if (x < 1) + fun_l5_n922(x) + else + fun_l5_n401(x) + end +end + +def fun_l4_n873(x) + if (x < 1) + fun_l5_n600(x) + else + fun_l5_n184(x) + end +end + +def fun_l4_n874(x) + if (x < 1) + fun_l5_n424(x) + else + fun_l5_n627(x) + end +end + +def fun_l4_n875(x) + if (x < 1) + fun_l5_n48(x) + else + fun_l5_n127(x) + end +end + +def fun_l4_n876(x) + if (x < 1) + fun_l5_n687(x) + else + fun_l5_n451(x) + end +end + +def fun_l4_n877(x) + if (x < 1) + fun_l5_n849(x) + else + fun_l5_n480(x) + end +end + +def fun_l4_n878(x) + if (x < 1) + fun_l5_n801(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n879(x) + if (x < 1) + fun_l5_n964(x) + else + fun_l5_n790(x) + end +end + +def fun_l4_n880(x) + if (x < 1) + fun_l5_n483(x) + else + fun_l5_n817(x) + end +end + +def fun_l4_n881(x) + if (x < 1) + fun_l5_n91(x) + else + fun_l5_n776(x) + end +end + +def fun_l4_n882(x) + if (x < 1) + fun_l5_n8(x) + else + fun_l5_n726(x) + end +end + +def fun_l4_n883(x) + if (x < 1) + fun_l5_n63(x) + else + fun_l5_n570(x) + end +end + +def fun_l4_n884(x) + if (x < 1) + fun_l5_n691(x) + else + fun_l5_n117(x) + end +end + +def fun_l4_n885(x) + if (x < 1) + fun_l5_n262(x) + else + fun_l5_n38(x) + end +end + +def fun_l4_n886(x) + if (x < 1) + fun_l5_n678(x) + else + fun_l5_n108(x) + end +end + +def fun_l4_n887(x) + if (x < 1) + fun_l5_n775(x) + else + fun_l5_n751(x) + end +end + +def fun_l4_n888(x) + if (x < 1) + fun_l5_n917(x) + else + fun_l5_n769(x) + end +end + +def fun_l4_n889(x) + if (x < 1) + fun_l5_n191(x) + else + fun_l5_n662(x) + end +end + +def fun_l4_n890(x) + if (x < 1) + fun_l5_n34(x) + else + fun_l5_n806(x) + end +end + +def fun_l4_n891(x) + if (x < 1) + fun_l5_n705(x) + else + fun_l5_n198(x) + end +end + +def fun_l4_n892(x) + if (x < 1) + fun_l5_n647(x) + else + fun_l5_n0(x) + end +end + +def fun_l4_n893(x) + if (x < 1) + fun_l5_n336(x) + else + fun_l5_n795(x) + end +end + +def fun_l4_n894(x) + if (x < 1) + fun_l5_n984(x) + else + fun_l5_n751(x) + end +end + +def fun_l4_n895(x) + if (x < 1) + fun_l5_n373(x) + else + fun_l5_n12(x) + end +end + +def fun_l4_n896(x) + if (x < 1) + fun_l5_n672(x) + else + fun_l5_n17(x) + end +end + +def fun_l4_n897(x) + if (x < 1) + fun_l5_n67(x) + else + fun_l5_n183(x) + end +end + +def fun_l4_n898(x) + if (x < 1) + fun_l5_n557(x) + else + fun_l5_n43(x) + end +end + +def fun_l4_n899(x) + if (x < 1) + fun_l5_n210(x) + else + fun_l5_n904(x) + end +end + +def fun_l4_n900(x) + if (x < 1) + fun_l5_n665(x) + else + fun_l5_n173(x) + end +end + +def fun_l4_n901(x) + if (x < 1) + fun_l5_n268(x) + else + fun_l5_n907(x) + end +end + +def fun_l4_n902(x) + if (x < 1) + fun_l5_n19(x) + else + fun_l5_n145(x) + end +end + +def fun_l4_n903(x) + if (x < 1) + fun_l5_n158(x) + else + fun_l5_n261(x) + end +end + +def fun_l4_n904(x) + if (x < 1) + fun_l5_n677(x) + else + fun_l5_n880(x) + end +end + +def fun_l4_n905(x) + if (x < 1) + fun_l5_n262(x) + else + fun_l5_n790(x) + end +end + +def fun_l4_n906(x) + if (x < 1) + fun_l5_n775(x) + else + fun_l5_n785(x) + end +end + +def fun_l4_n907(x) + if (x < 1) + fun_l5_n629(x) + else + fun_l5_n312(x) + end +end + +def fun_l4_n908(x) + if (x < 1) + fun_l5_n84(x) + else + fun_l5_n605(x) + end +end + +def fun_l4_n909(x) + if (x < 1) + fun_l5_n346(x) + else + fun_l5_n245(x) + end +end + +def fun_l4_n910(x) + if (x < 1) + fun_l5_n768(x) + else + fun_l5_n47(x) + end +end + +def fun_l4_n911(x) + if (x < 1) + fun_l5_n48(x) + else + fun_l5_n406(x) + end +end + +def fun_l4_n912(x) + if (x < 1) + fun_l5_n493(x) + else + fun_l5_n608(x) + end +end + +def fun_l4_n913(x) + if (x < 1) + fun_l5_n456(x) + else + fun_l5_n176(x) + end +end + +def fun_l4_n914(x) + if (x < 1) + fun_l5_n201(x) + else + fun_l5_n233(x) + end +end + +def fun_l4_n915(x) + if (x < 1) + fun_l5_n910(x) + else + fun_l5_n790(x) + end +end + +def fun_l4_n916(x) + if (x < 1) + fun_l5_n734(x) + else + fun_l5_n685(x) + end +end + +def fun_l4_n917(x) + if (x < 1) + fun_l5_n132(x) + else + fun_l5_n112(x) + end +end + +def fun_l4_n918(x) + if (x < 1) + fun_l5_n897(x) + else + fun_l5_n196(x) + end +end + +def fun_l4_n919(x) + if (x < 1) + fun_l5_n395(x) + else + fun_l5_n186(x) + end +end + +def fun_l4_n920(x) + if (x < 1) + fun_l5_n19(x) + else + fun_l5_n810(x) + end +end + +def fun_l4_n921(x) + if (x < 1) + fun_l5_n546(x) + else + fun_l5_n34(x) + end +end + +def fun_l4_n922(x) + if (x < 1) + fun_l5_n863(x) + else + fun_l5_n928(x) + end +end + +def fun_l4_n923(x) + if (x < 1) + fun_l5_n485(x) + else + fun_l5_n182(x) + end +end + +def fun_l4_n924(x) + if (x < 1) + fun_l5_n303(x) + else + fun_l5_n17(x) + end +end + +def fun_l4_n925(x) + if (x < 1) + fun_l5_n78(x) + else + fun_l5_n816(x) + end +end + +def fun_l4_n926(x) + if (x < 1) + fun_l5_n797(x) + else + fun_l5_n761(x) + end +end + +def fun_l4_n927(x) + if (x < 1) + fun_l5_n975(x) + else + fun_l5_n220(x) + end +end + +def fun_l4_n928(x) + if (x < 1) + fun_l5_n213(x) + else + fun_l5_n815(x) + end +end + +def fun_l4_n929(x) + if (x < 1) + fun_l5_n280(x) + else + fun_l5_n551(x) + end +end + +def fun_l4_n930(x) + if (x < 1) + fun_l5_n631(x) + else + fun_l5_n629(x) + end +end + +def fun_l4_n931(x) + if (x < 1) + fun_l5_n60(x) + else + fun_l5_n332(x) + end +end + +def fun_l4_n932(x) + if (x < 1) + fun_l5_n336(x) + else + fun_l5_n733(x) + end +end + +def fun_l4_n933(x) + if (x < 1) + fun_l5_n94(x) + else + fun_l5_n48(x) + end +end + +def fun_l4_n934(x) + if (x < 1) + fun_l5_n527(x) + else + fun_l5_n108(x) + end +end + +def fun_l4_n935(x) + if (x < 1) + fun_l5_n994(x) + else + fun_l5_n95(x) + end +end + +def fun_l4_n936(x) + if (x < 1) + fun_l5_n631(x) + else + fun_l5_n310(x) + end +end + +def fun_l4_n937(x) + if (x < 1) + fun_l5_n851(x) + else + fun_l5_n380(x) + end +end + +def fun_l4_n938(x) + if (x < 1) + fun_l5_n256(x) + else + fun_l5_n231(x) + end +end + +def fun_l4_n939(x) + if (x < 1) + fun_l5_n686(x) + else + fun_l5_n557(x) + end +end + +def fun_l4_n940(x) + if (x < 1) + fun_l5_n311(x) + else + fun_l5_n611(x) + end +end + +def fun_l4_n941(x) + if (x < 1) + fun_l5_n770(x) + else + fun_l5_n306(x) + end +end + +def fun_l4_n942(x) + if (x < 1) + fun_l5_n649(x) + else + fun_l5_n60(x) + end +end + +def fun_l4_n943(x) + if (x < 1) + fun_l5_n935(x) + else + fun_l5_n991(x) + end +end + +def fun_l4_n944(x) + if (x < 1) + fun_l5_n851(x) + else + fun_l5_n131(x) + end +end + +def fun_l4_n945(x) + if (x < 1) + fun_l5_n422(x) + else + fun_l5_n309(x) + end +end + +def fun_l4_n946(x) + if (x < 1) + fun_l5_n906(x) + else + fun_l5_n798(x) + end +end + +def fun_l4_n947(x) + if (x < 1) + fun_l5_n817(x) + else + fun_l5_n122(x) + end +end + +def fun_l4_n948(x) + if (x < 1) + fun_l5_n233(x) + else + fun_l5_n600(x) + end +end + +def fun_l4_n949(x) + if (x < 1) + fun_l5_n908(x) + else + fun_l5_n332(x) + end +end + +def fun_l4_n950(x) + if (x < 1) + fun_l5_n71(x) + else + fun_l5_n893(x) + end +end + +def fun_l4_n951(x) + if (x < 1) + fun_l5_n281(x) + else + fun_l5_n281(x) + end +end + +def fun_l4_n952(x) + if (x < 1) + fun_l5_n312(x) + else + fun_l5_n164(x) + end +end + +def fun_l4_n953(x) + if (x < 1) + fun_l5_n292(x) + else + fun_l5_n993(x) + end +end + +def fun_l4_n954(x) + if (x < 1) + fun_l5_n271(x) + else + fun_l5_n635(x) + end +end + +def fun_l4_n955(x) + if (x < 1) + fun_l5_n10(x) + else + fun_l5_n202(x) + end +end + +def fun_l4_n956(x) + if (x < 1) + fun_l5_n574(x) + else + fun_l5_n29(x) + end +end + +def fun_l4_n957(x) + if (x < 1) + fun_l5_n154(x) + else + fun_l5_n96(x) + end +end + +def fun_l4_n958(x) + if (x < 1) + fun_l5_n287(x) + else + fun_l5_n509(x) + end +end + +def fun_l4_n959(x) + if (x < 1) + fun_l5_n400(x) + else + fun_l5_n195(x) + end +end + +def fun_l4_n960(x) + if (x < 1) + fun_l5_n94(x) + else + fun_l5_n165(x) + end +end + +def fun_l4_n961(x) + if (x < 1) + fun_l5_n276(x) + else + fun_l5_n935(x) + end +end + +def fun_l4_n962(x) + if (x < 1) + fun_l5_n504(x) + else + fun_l5_n480(x) + end +end + +def fun_l4_n963(x) + if (x < 1) + fun_l5_n152(x) + else + fun_l5_n397(x) + end +end + +def fun_l4_n964(x) + if (x < 1) + fun_l5_n303(x) + else + fun_l5_n481(x) + end +end + +def fun_l4_n965(x) + if (x < 1) + fun_l5_n882(x) + else + fun_l5_n116(x) + end +end + +def fun_l4_n966(x) + if (x < 1) + fun_l5_n329(x) + else + fun_l5_n484(x) + end +end + +def fun_l4_n967(x) + if (x < 1) + fun_l5_n369(x) + else + fun_l5_n680(x) + end +end + +def fun_l4_n968(x) + if (x < 1) + fun_l5_n30(x) + else + fun_l5_n653(x) + end +end + +def fun_l4_n969(x) + if (x < 1) + fun_l5_n292(x) + else + fun_l5_n793(x) + end +end + +def fun_l4_n970(x) + if (x < 1) + fun_l5_n796(x) + else + fun_l5_n387(x) + end +end + +def fun_l4_n971(x) + if (x < 1) + fun_l5_n735(x) + else + fun_l5_n985(x) + end +end + +def fun_l4_n972(x) + if (x < 1) + fun_l5_n925(x) + else + fun_l5_n689(x) + end +end + +def fun_l4_n973(x) + if (x < 1) + fun_l5_n154(x) + else + fun_l5_n998(x) + end +end + +def fun_l4_n974(x) + if (x < 1) + fun_l5_n708(x) + else + fun_l5_n253(x) + end +end + +def fun_l4_n975(x) + if (x < 1) + fun_l5_n716(x) + else + fun_l5_n958(x) + end +end + +def fun_l4_n976(x) + if (x < 1) + fun_l5_n488(x) + else + fun_l5_n299(x) + end +end + +def fun_l4_n977(x) + if (x < 1) + fun_l5_n872(x) + else + fun_l5_n276(x) + end +end + +def fun_l4_n978(x) + if (x < 1) + fun_l5_n219(x) + else + fun_l5_n76(x) + end +end + +def fun_l4_n979(x) + if (x < 1) + fun_l5_n937(x) + else + fun_l5_n988(x) + end +end + +def fun_l4_n980(x) + if (x < 1) + fun_l5_n681(x) + else + fun_l5_n264(x) + end +end + +def fun_l4_n981(x) + if (x < 1) + fun_l5_n630(x) + else + fun_l5_n18(x) + end +end + +def fun_l4_n982(x) + if (x < 1) + fun_l5_n910(x) + else + fun_l5_n97(x) + end +end + +def fun_l4_n983(x) + if (x < 1) + fun_l5_n551(x) + else + fun_l5_n429(x) + end +end + +def fun_l4_n984(x) + if (x < 1) + fun_l5_n304(x) + else + fun_l5_n192(x) + end +end + +def fun_l4_n985(x) + if (x < 1) + fun_l5_n696(x) + else + fun_l5_n124(x) + end +end + +def fun_l4_n986(x) + if (x < 1) + fun_l5_n603(x) + else + fun_l5_n967(x) + end +end + +def fun_l4_n987(x) + if (x < 1) + fun_l5_n317(x) + else + fun_l5_n785(x) + end +end + +def fun_l4_n988(x) + if (x < 1) + fun_l5_n762(x) + else + fun_l5_n999(x) + end +end + +def fun_l4_n989(x) + if (x < 1) + fun_l5_n61(x) + else + fun_l5_n474(x) + end +end + +def fun_l4_n990(x) + if (x < 1) + fun_l5_n465(x) + else + fun_l5_n878(x) + end +end + +def fun_l4_n991(x) + if (x < 1) + fun_l5_n907(x) + else + fun_l5_n259(x) + end +end + +def fun_l4_n992(x) + if (x < 1) + fun_l5_n594(x) + else + fun_l5_n378(x) + end +end + +def fun_l4_n993(x) + if (x < 1) + fun_l5_n202(x) + else + fun_l5_n490(x) + end +end + +def fun_l4_n994(x) + if (x < 1) + fun_l5_n105(x) + else + fun_l5_n675(x) + end +end + +def fun_l4_n995(x) + if (x < 1) + fun_l5_n99(x) + else + fun_l5_n21(x) + end +end + +def fun_l4_n996(x) + if (x < 1) + fun_l5_n831(x) + else + fun_l5_n692(x) + end +end + +def fun_l4_n997(x) + if (x < 1) + fun_l5_n186(x) + else + fun_l5_n427(x) + end +end + +def fun_l4_n998(x) + if (x < 1) + fun_l5_n597(x) + else + fun_l5_n978(x) + end +end + +def fun_l4_n999(x) + if (x < 1) + fun_l5_n537(x) + else + fun_l5_n952(x) + end +end + +def fun_l5_n0(x) + if (x < 1) + fun_l6_n104(x) + else + fun_l6_n249(x) + end +end + +def fun_l5_n1(x) + if (x < 1) + fun_l6_n260(x) + else + fun_l6_n782(x) + end +end + +def fun_l5_n2(x) + if (x < 1) + fun_l6_n974(x) + else + fun_l6_n301(x) + end +end + +def fun_l5_n3(x) + if (x < 1) + fun_l6_n883(x) + else + fun_l6_n149(x) + end +end + +def fun_l5_n4(x) + if (x < 1) + fun_l6_n134(x) + else + fun_l6_n111(x) + end +end + +def fun_l5_n5(x) + if (x < 1) + fun_l6_n573(x) + else + fun_l6_n273(x) + end +end + +def fun_l5_n6(x) + if (x < 1) + fun_l6_n221(x) + else + fun_l6_n843(x) + end +end + +def fun_l5_n7(x) + if (x < 1) + fun_l6_n572(x) + else + fun_l6_n435(x) + end +end + +def fun_l5_n8(x) + if (x < 1) + fun_l6_n43(x) + else + fun_l6_n598(x) + end +end + +def fun_l5_n9(x) + if (x < 1) + fun_l6_n352(x) + else + fun_l6_n894(x) + end +end + +def fun_l5_n10(x) + if (x < 1) + fun_l6_n161(x) + else + fun_l6_n654(x) + end +end + +def fun_l5_n11(x) + if (x < 1) + fun_l6_n432(x) + else + fun_l6_n825(x) + end +end + +def fun_l5_n12(x) + if (x < 1) + fun_l6_n863(x) + else + fun_l6_n940(x) + end +end + +def fun_l5_n13(x) + if (x < 1) + fun_l6_n478(x) + else + fun_l6_n193(x) + end +end + +def fun_l5_n14(x) + if (x < 1) + fun_l6_n327(x) + else + fun_l6_n808(x) + end +end + +def fun_l5_n15(x) + if (x < 1) + fun_l6_n86(x) + else + fun_l6_n951(x) + end +end + +def fun_l5_n16(x) + if (x < 1) + fun_l6_n492(x) + else + fun_l6_n704(x) + end +end + +def fun_l5_n17(x) + if (x < 1) + fun_l6_n196(x) + else + fun_l6_n970(x) + end +end + +def fun_l5_n18(x) + if (x < 1) + fun_l6_n325(x) + else + fun_l6_n30(x) + end +end + +def fun_l5_n19(x) + if (x < 1) + fun_l6_n559(x) + else + fun_l6_n269(x) + end +end + +def fun_l5_n20(x) + if (x < 1) + fun_l6_n716(x) + else + fun_l6_n783(x) + end +end + +def fun_l5_n21(x) + if (x < 1) + fun_l6_n978(x) + else + fun_l6_n306(x) + end +end + +def fun_l5_n22(x) + if (x < 1) + fun_l6_n220(x) + else + fun_l6_n823(x) + end +end + +def fun_l5_n23(x) + if (x < 1) + fun_l6_n675(x) + else + fun_l6_n684(x) + end +end + +def fun_l5_n24(x) + if (x < 1) + fun_l6_n851(x) + else + fun_l6_n450(x) + end +end + +def fun_l5_n25(x) + if (x < 1) + fun_l6_n745(x) + else + fun_l6_n370(x) + end +end + +def fun_l5_n26(x) + if (x < 1) + fun_l6_n431(x) + else + fun_l6_n130(x) + end +end + +def fun_l5_n27(x) + if (x < 1) + fun_l6_n105(x) + else + fun_l6_n205(x) + end +end + +def fun_l5_n28(x) + if (x < 1) + fun_l6_n718(x) + else + fun_l6_n742(x) + end +end + +def fun_l5_n29(x) + if (x < 1) + fun_l6_n977(x) + else + fun_l6_n63(x) + end +end + +def fun_l5_n30(x) + if (x < 1) + fun_l6_n902(x) + else + fun_l6_n471(x) + end +end + +def fun_l5_n31(x) + if (x < 1) + fun_l6_n76(x) + else + fun_l6_n960(x) + end +end + +def fun_l5_n32(x) + if (x < 1) + fun_l6_n75(x) + else + fun_l6_n640(x) + end +end + +def fun_l5_n33(x) + if (x < 1) + fun_l6_n631(x) + else + fun_l6_n769(x) + end +end + +def fun_l5_n34(x) + if (x < 1) + fun_l6_n201(x) + else + fun_l6_n771(x) + end +end + +def fun_l5_n35(x) + if (x < 1) + fun_l6_n734(x) + else + fun_l6_n370(x) + end +end + +def fun_l5_n36(x) + if (x < 1) + fun_l6_n490(x) + else + fun_l6_n994(x) + end +end + +def fun_l5_n37(x) + if (x < 1) + fun_l6_n566(x) + else + fun_l6_n392(x) + end +end + +def fun_l5_n38(x) + if (x < 1) + fun_l6_n120(x) + else + fun_l6_n774(x) + end +end + +def fun_l5_n39(x) + if (x < 1) + fun_l6_n402(x) + else + fun_l6_n572(x) + end +end + +def fun_l5_n40(x) + if (x < 1) + fun_l6_n911(x) + else + fun_l6_n968(x) + end +end + +def fun_l5_n41(x) + if (x < 1) + fun_l6_n200(x) + else + fun_l6_n656(x) + end +end + +def fun_l5_n42(x) + if (x < 1) + fun_l6_n59(x) + else + fun_l6_n426(x) + end +end + +def fun_l5_n43(x) + if (x < 1) + fun_l6_n650(x) + else + fun_l6_n932(x) + end +end + +def fun_l5_n44(x) + if (x < 1) + fun_l6_n365(x) + else + fun_l6_n755(x) + end +end + +def fun_l5_n45(x) + if (x < 1) + fun_l6_n738(x) + else + fun_l6_n432(x) + end +end + +def fun_l5_n46(x) + if (x < 1) + fun_l6_n82(x) + else + fun_l6_n484(x) + end +end + +def fun_l5_n47(x) + if (x < 1) + fun_l6_n64(x) + else + fun_l6_n610(x) + end +end + +def fun_l5_n48(x) + if (x < 1) + fun_l6_n875(x) + else + fun_l6_n464(x) + end +end + +def fun_l5_n49(x) + if (x < 1) + fun_l6_n798(x) + else + fun_l6_n57(x) + end +end + +def fun_l5_n50(x) + if (x < 1) + fun_l6_n76(x) + else + fun_l6_n462(x) + end +end + +def fun_l5_n51(x) + if (x < 1) + fun_l6_n225(x) + else + fun_l6_n526(x) + end +end + +def fun_l5_n52(x) + if (x < 1) + fun_l6_n388(x) + else + fun_l6_n167(x) + end +end + +def fun_l5_n53(x) + if (x < 1) + fun_l6_n270(x) + else + fun_l6_n821(x) + end +end + +def fun_l5_n54(x) + if (x < 1) + fun_l6_n790(x) + else + fun_l6_n95(x) + end +end + +def fun_l5_n55(x) + if (x < 1) + fun_l6_n38(x) + else + fun_l6_n32(x) + end +end + +def fun_l5_n56(x) + if (x < 1) + fun_l6_n400(x) + else + fun_l6_n513(x) + end +end + +def fun_l5_n57(x) + if (x < 1) + fun_l6_n251(x) + else + fun_l6_n16(x) + end +end + +def fun_l5_n58(x) + if (x < 1) + fun_l6_n303(x) + else + fun_l6_n858(x) + end +end + +def fun_l5_n59(x) + if (x < 1) + fun_l6_n173(x) + else + fun_l6_n38(x) + end +end + +def fun_l5_n60(x) + if (x < 1) + fun_l6_n466(x) + else + fun_l6_n64(x) + end +end + +def fun_l5_n61(x) + if (x < 1) + fun_l6_n687(x) + else + fun_l6_n208(x) + end +end + +def fun_l5_n62(x) + if (x < 1) + fun_l6_n891(x) + else + fun_l6_n789(x) + end +end + +def fun_l5_n63(x) + if (x < 1) + fun_l6_n664(x) + else + fun_l6_n133(x) + end +end + +def fun_l5_n64(x) + if (x < 1) + fun_l6_n121(x) + else + fun_l6_n989(x) + end +end + +def fun_l5_n65(x) + if (x < 1) + fun_l6_n411(x) + else + fun_l6_n264(x) + end +end + +def fun_l5_n66(x) + if (x < 1) + fun_l6_n528(x) + else + fun_l6_n662(x) + end +end + +def fun_l5_n67(x) + if (x < 1) + fun_l6_n824(x) + else + fun_l6_n410(x) + end +end + +def fun_l5_n68(x) + if (x < 1) + fun_l6_n29(x) + else + fun_l6_n946(x) + end +end + +def fun_l5_n69(x) + if (x < 1) + fun_l6_n566(x) + else + fun_l6_n797(x) + end +end + +def fun_l5_n70(x) + if (x < 1) + fun_l6_n816(x) + else + fun_l6_n112(x) + end +end + +def fun_l5_n71(x) + if (x < 1) + fun_l6_n920(x) + else + fun_l6_n44(x) + end +end + +def fun_l5_n72(x) + if (x < 1) + fun_l6_n725(x) + else + fun_l6_n113(x) + end +end + +def fun_l5_n73(x) + if (x < 1) + fun_l6_n406(x) + else + fun_l6_n555(x) + end +end + +def fun_l5_n74(x) + if (x < 1) + fun_l6_n527(x) + else + fun_l6_n991(x) + end +end + +def fun_l5_n75(x) + if (x < 1) + fun_l6_n46(x) + else + fun_l6_n440(x) + end +end + +def fun_l5_n76(x) + if (x < 1) + fun_l6_n242(x) + else + fun_l6_n488(x) + end +end + +def fun_l5_n77(x) + if (x < 1) + fun_l6_n211(x) + else + fun_l6_n760(x) + end +end + +def fun_l5_n78(x) + if (x < 1) + fun_l6_n821(x) + else + fun_l6_n653(x) + end +end + +def fun_l5_n79(x) + if (x < 1) + fun_l6_n559(x) + else + fun_l6_n425(x) + end +end + +def fun_l5_n80(x) + if (x < 1) + fun_l6_n792(x) + else + fun_l6_n813(x) + end +end + +def fun_l5_n81(x) + if (x < 1) + fun_l6_n463(x) + else + fun_l6_n454(x) + end +end + +def fun_l5_n82(x) + if (x < 1) + fun_l6_n731(x) + else + fun_l6_n718(x) + end +end + +def fun_l5_n83(x) + if (x < 1) + fun_l6_n377(x) + else + fun_l6_n137(x) + end +end + +def fun_l5_n84(x) + if (x < 1) + fun_l6_n829(x) + else + fun_l6_n77(x) + end +end + +def fun_l5_n85(x) + if (x < 1) + fun_l6_n714(x) + else + fun_l6_n682(x) + end +end + +def fun_l5_n86(x) + if (x < 1) + fun_l6_n47(x) + else + fun_l6_n527(x) + end +end + +def fun_l5_n87(x) + if (x < 1) + fun_l6_n976(x) + else + fun_l6_n18(x) + end +end + +def fun_l5_n88(x) + if (x < 1) + fun_l6_n710(x) + else + fun_l6_n998(x) + end +end + +def fun_l5_n89(x) + if (x < 1) + fun_l6_n222(x) + else + fun_l6_n97(x) + end +end + +def fun_l5_n90(x) + if (x < 1) + fun_l6_n862(x) + else + fun_l6_n627(x) + end +end + +def fun_l5_n91(x) + if (x < 1) + fun_l6_n642(x) + else + fun_l6_n720(x) + end +end + +def fun_l5_n92(x) + if (x < 1) + fun_l6_n444(x) + else + fun_l6_n506(x) + end +end + +def fun_l5_n93(x) + if (x < 1) + fun_l6_n776(x) + else + fun_l6_n879(x) + end +end + +def fun_l5_n94(x) + if (x < 1) + fun_l6_n629(x) + else + fun_l6_n322(x) + end +end + +def fun_l5_n95(x) + if (x < 1) + fun_l6_n119(x) + else + fun_l6_n134(x) + end +end + +def fun_l5_n96(x) + if (x < 1) + fun_l6_n385(x) + else + fun_l6_n343(x) + end +end + +def fun_l5_n97(x) + if (x < 1) + fun_l6_n110(x) + else + fun_l6_n323(x) + end +end + +def fun_l5_n98(x) + if (x < 1) + fun_l6_n547(x) + else + fun_l6_n762(x) + end +end + +def fun_l5_n99(x) + if (x < 1) + fun_l6_n811(x) + else + fun_l6_n404(x) + end +end + +def fun_l5_n100(x) + if (x < 1) + fun_l6_n893(x) + else + fun_l6_n120(x) + end +end + +def fun_l5_n101(x) + if (x < 1) + fun_l6_n755(x) + else + fun_l6_n611(x) + end +end + +def fun_l5_n102(x) + if (x < 1) + fun_l6_n65(x) + else + fun_l6_n897(x) + end +end + +def fun_l5_n103(x) + if (x < 1) + fun_l6_n629(x) + else + fun_l6_n214(x) + end +end + +def fun_l5_n104(x) + if (x < 1) + fun_l6_n211(x) + else + fun_l6_n179(x) + end +end + +def fun_l5_n105(x) + if (x < 1) + fun_l6_n650(x) + else + fun_l6_n348(x) + end +end + +def fun_l5_n106(x) + if (x < 1) + fun_l6_n966(x) + else + fun_l6_n654(x) + end +end + +def fun_l5_n107(x) + if (x < 1) + fun_l6_n596(x) + else + fun_l6_n668(x) + end +end + +def fun_l5_n108(x) + if (x < 1) + fun_l6_n392(x) + else + fun_l6_n629(x) + end +end + +def fun_l5_n109(x) + if (x < 1) + fun_l6_n96(x) + else + fun_l6_n578(x) + end +end + +def fun_l5_n110(x) + if (x < 1) + fun_l6_n88(x) + else + fun_l6_n214(x) + end +end + +def fun_l5_n111(x) + if (x < 1) + fun_l6_n622(x) + else + fun_l6_n180(x) + end +end + +def fun_l5_n112(x) + if (x < 1) + fun_l6_n100(x) + else + fun_l6_n373(x) + end +end + +def fun_l5_n113(x) + if (x < 1) + fun_l6_n464(x) + else + fun_l6_n30(x) + end +end + +def fun_l5_n114(x) + if (x < 1) + fun_l6_n703(x) + else + fun_l6_n116(x) + end +end + +def fun_l5_n115(x) + if (x < 1) + fun_l6_n63(x) + else + fun_l6_n260(x) + end +end + +def fun_l5_n116(x) + if (x < 1) + fun_l6_n935(x) + else + fun_l6_n951(x) + end +end + +def fun_l5_n117(x) + if (x < 1) + fun_l6_n415(x) + else + fun_l6_n734(x) + end +end + +def fun_l5_n118(x) + if (x < 1) + fun_l6_n873(x) + else + fun_l6_n163(x) + end +end + +def fun_l5_n119(x) + if (x < 1) + fun_l6_n134(x) + else + fun_l6_n586(x) + end +end + +def fun_l5_n120(x) + if (x < 1) + fun_l6_n793(x) + else + fun_l6_n197(x) + end +end + +def fun_l5_n121(x) + if (x < 1) + fun_l6_n585(x) + else + fun_l6_n793(x) + end +end + +def fun_l5_n122(x) + if (x < 1) + fun_l6_n10(x) + else + fun_l6_n12(x) + end +end + +def fun_l5_n123(x) + if (x < 1) + fun_l6_n786(x) + else + fun_l6_n386(x) + end +end + +def fun_l5_n124(x) + if (x < 1) + fun_l6_n891(x) + else + fun_l6_n903(x) + end +end + +def fun_l5_n125(x) + if (x < 1) + fun_l6_n389(x) + else + fun_l6_n154(x) + end +end + +def fun_l5_n126(x) + if (x < 1) + fun_l6_n214(x) + else + fun_l6_n754(x) + end +end + +def fun_l5_n127(x) + if (x < 1) + fun_l6_n646(x) + else + fun_l6_n661(x) + end +end + +def fun_l5_n128(x) + if (x < 1) + fun_l6_n662(x) + else + fun_l6_n527(x) + end +end + +def fun_l5_n129(x) + if (x < 1) + fun_l6_n329(x) + else + fun_l6_n310(x) + end +end + +def fun_l5_n130(x) + if (x < 1) + fun_l6_n352(x) + else + fun_l6_n820(x) + end +end + +def fun_l5_n131(x) + if (x < 1) + fun_l6_n551(x) + else + fun_l6_n454(x) + end +end + +def fun_l5_n132(x) + if (x < 1) + fun_l6_n586(x) + else + fun_l6_n340(x) + end +end + +def fun_l5_n133(x) + if (x < 1) + fun_l6_n111(x) + else + fun_l6_n188(x) + end +end + +def fun_l5_n134(x) + if (x < 1) + fun_l6_n261(x) + else + fun_l6_n464(x) + end +end + +def fun_l5_n135(x) + if (x < 1) + fun_l6_n540(x) + else + fun_l6_n854(x) + end +end + +def fun_l5_n136(x) + if (x < 1) + fun_l6_n120(x) + else + fun_l6_n230(x) + end +end + +def fun_l5_n137(x) + if (x < 1) + fun_l6_n837(x) + else + fun_l6_n606(x) + end +end + +def fun_l5_n138(x) + if (x < 1) + fun_l6_n663(x) + else + fun_l6_n195(x) + end +end + +def fun_l5_n139(x) + if (x < 1) + fun_l6_n572(x) + else + fun_l6_n768(x) + end +end + +def fun_l5_n140(x) + if (x < 1) + fun_l6_n747(x) + else + fun_l6_n304(x) + end +end + +def fun_l5_n141(x) + if (x < 1) + fun_l6_n927(x) + else + fun_l6_n122(x) + end +end + +def fun_l5_n142(x) + if (x < 1) + fun_l6_n311(x) + else + fun_l6_n920(x) + end +end + +def fun_l5_n143(x) + if (x < 1) + fun_l6_n887(x) + else + fun_l6_n598(x) + end +end + +def fun_l5_n144(x) + if (x < 1) + fun_l6_n289(x) + else + fun_l6_n894(x) + end +end + +def fun_l5_n145(x) + if (x < 1) + fun_l6_n333(x) + else + fun_l6_n385(x) + end +end + +def fun_l5_n146(x) + if (x < 1) + fun_l6_n926(x) + else + fun_l6_n310(x) + end +end + +def fun_l5_n147(x) + if (x < 1) + fun_l6_n754(x) + else + fun_l6_n354(x) + end +end + +def fun_l5_n148(x) + if (x < 1) + fun_l6_n800(x) + else + fun_l6_n634(x) + end +end + +def fun_l5_n149(x) + if (x < 1) + fun_l6_n5(x) + else + fun_l6_n67(x) + end +end + +def fun_l5_n150(x) + if (x < 1) + fun_l6_n766(x) + else + fun_l6_n237(x) + end +end + +def fun_l5_n151(x) + if (x < 1) + fun_l6_n277(x) + else + fun_l6_n692(x) + end +end + +def fun_l5_n152(x) + if (x < 1) + fun_l6_n328(x) + else + fun_l6_n216(x) + end +end + +def fun_l5_n153(x) + if (x < 1) + fun_l6_n328(x) + else + fun_l6_n165(x) + end +end + +def fun_l5_n154(x) + if (x < 1) + fun_l6_n884(x) + else + fun_l6_n811(x) + end +end + +def fun_l5_n155(x) + if (x < 1) + fun_l6_n376(x) + else + fun_l6_n188(x) + end +end + +def fun_l5_n156(x) + if (x < 1) + fun_l6_n276(x) + else + fun_l6_n19(x) + end +end + +def fun_l5_n157(x) + if (x < 1) + fun_l6_n443(x) + else + fun_l6_n815(x) + end +end + +def fun_l5_n158(x) + if (x < 1) + fun_l6_n610(x) + else + fun_l6_n341(x) + end +end + +def fun_l5_n159(x) + if (x < 1) + fun_l6_n147(x) + else + fun_l6_n289(x) + end +end + +def fun_l5_n160(x) + if (x < 1) + fun_l6_n258(x) + else + fun_l6_n683(x) + end +end + +def fun_l5_n161(x) + if (x < 1) + fun_l6_n544(x) + else + fun_l6_n621(x) + end +end + +def fun_l5_n162(x) + if (x < 1) + fun_l6_n119(x) + else + fun_l6_n336(x) + end +end + +def fun_l5_n163(x) + if (x < 1) + fun_l6_n297(x) + else + fun_l6_n915(x) + end +end + +def fun_l5_n164(x) + if (x < 1) + fun_l6_n782(x) + else + fun_l6_n499(x) + end +end + +def fun_l5_n165(x) + if (x < 1) + fun_l6_n660(x) + else + fun_l6_n227(x) + end +end + +def fun_l5_n166(x) + if (x < 1) + fun_l6_n820(x) + else + fun_l6_n822(x) + end +end + +def fun_l5_n167(x) + if (x < 1) + fun_l6_n878(x) + else + fun_l6_n642(x) + end +end + +def fun_l5_n168(x) + if (x < 1) + fun_l6_n123(x) + else + fun_l6_n451(x) + end +end + +def fun_l5_n169(x) + if (x < 1) + fun_l6_n741(x) + else + fun_l6_n35(x) + end +end + +def fun_l5_n170(x) + if (x < 1) + fun_l6_n522(x) + else + fun_l6_n546(x) + end +end + +def fun_l5_n171(x) + if (x < 1) + fun_l6_n555(x) + else + fun_l6_n667(x) + end +end + +def fun_l5_n172(x) + if (x < 1) + fun_l6_n760(x) + else + fun_l6_n292(x) + end +end + +def fun_l5_n173(x) + if (x < 1) + fun_l6_n375(x) + else + fun_l6_n907(x) + end +end + +def fun_l5_n174(x) + if (x < 1) + fun_l6_n382(x) + else + fun_l6_n693(x) + end +end + +def fun_l5_n175(x) + if (x < 1) + fun_l6_n728(x) + else + fun_l6_n378(x) + end +end + +def fun_l5_n176(x) + if (x < 1) + fun_l6_n79(x) + else + fun_l6_n402(x) + end +end + +def fun_l5_n177(x) + if (x < 1) + fun_l6_n444(x) + else + fun_l6_n500(x) + end +end + +def fun_l5_n178(x) + if (x < 1) + fun_l6_n535(x) + else + fun_l6_n754(x) + end +end + +def fun_l5_n179(x) + if (x < 1) + fun_l6_n831(x) + else + fun_l6_n206(x) + end +end + +def fun_l5_n180(x) + if (x < 1) + fun_l6_n878(x) + else + fun_l6_n715(x) + end +end + +def fun_l5_n181(x) + if (x < 1) + fun_l6_n433(x) + else + fun_l6_n955(x) + end +end + +def fun_l5_n182(x) + if (x < 1) + fun_l6_n611(x) + else + fun_l6_n258(x) + end +end + +def fun_l5_n183(x) + if (x < 1) + fun_l6_n618(x) + else + fun_l6_n29(x) + end +end + +def fun_l5_n184(x) + if (x < 1) + fun_l6_n838(x) + else + fun_l6_n918(x) + end +end + +def fun_l5_n185(x) + if (x < 1) + fun_l6_n307(x) + else + fun_l6_n811(x) + end +end + +def fun_l5_n186(x) + if (x < 1) + fun_l6_n564(x) + else + fun_l6_n73(x) + end +end + +def fun_l5_n187(x) + if (x < 1) + fun_l6_n871(x) + else + fun_l6_n669(x) + end +end + +def fun_l5_n188(x) + if (x < 1) + fun_l6_n546(x) + else + fun_l6_n41(x) + end +end + +def fun_l5_n189(x) + if (x < 1) + fun_l6_n312(x) + else + fun_l6_n998(x) + end +end + +def fun_l5_n190(x) + if (x < 1) + fun_l6_n519(x) + else + fun_l6_n275(x) + end +end + +def fun_l5_n191(x) + if (x < 1) + fun_l6_n525(x) + else + fun_l6_n228(x) + end +end + +def fun_l5_n192(x) + if (x < 1) + fun_l6_n115(x) + else + fun_l6_n790(x) + end +end + +def fun_l5_n193(x) + if (x < 1) + fun_l6_n976(x) + else + fun_l6_n219(x) + end +end + +def fun_l5_n194(x) + if (x < 1) + fun_l6_n785(x) + else + fun_l6_n834(x) + end +end + +def fun_l5_n195(x) + if (x < 1) + fun_l6_n238(x) + else + fun_l6_n471(x) + end +end + +def fun_l5_n196(x) + if (x < 1) + fun_l6_n275(x) + else + fun_l6_n218(x) + end +end + +def fun_l5_n197(x) + if (x < 1) + fun_l6_n590(x) + else + fun_l6_n458(x) + end +end + +def fun_l5_n198(x) + if (x < 1) + fun_l6_n498(x) + else + fun_l6_n906(x) + end +end + +def fun_l5_n199(x) + if (x < 1) + fun_l6_n547(x) + else + fun_l6_n885(x) + end +end + +def fun_l5_n200(x) + if (x < 1) + fun_l6_n631(x) + else + fun_l6_n0(x) + end +end + +def fun_l5_n201(x) + if (x < 1) + fun_l6_n31(x) + else + fun_l6_n729(x) + end +end + +def fun_l5_n202(x) + if (x < 1) + fun_l6_n303(x) + else + fun_l6_n847(x) + end +end + +def fun_l5_n203(x) + if (x < 1) + fun_l6_n912(x) + else + fun_l6_n346(x) + end +end + +def fun_l5_n204(x) + if (x < 1) + fun_l6_n153(x) + else + fun_l6_n831(x) + end +end + +def fun_l5_n205(x) + if (x < 1) + fun_l6_n424(x) + else + fun_l6_n836(x) + end +end + +def fun_l5_n206(x) + if (x < 1) + fun_l6_n214(x) + else + fun_l6_n207(x) + end +end + +def fun_l5_n207(x) + if (x < 1) + fun_l6_n362(x) + else + fun_l6_n241(x) + end +end + +def fun_l5_n208(x) + if (x < 1) + fun_l6_n796(x) + else + fun_l6_n763(x) + end +end + +def fun_l5_n209(x) + if (x < 1) + fun_l6_n523(x) + else + fun_l6_n998(x) + end +end + +def fun_l5_n210(x) + if (x < 1) + fun_l6_n326(x) + else + fun_l6_n755(x) + end +end + +def fun_l5_n211(x) + if (x < 1) + fun_l6_n345(x) + else + fun_l6_n747(x) + end +end + +def fun_l5_n212(x) + if (x < 1) + fun_l6_n631(x) + else + fun_l6_n576(x) + end +end + +def fun_l5_n213(x) + if (x < 1) + fun_l6_n713(x) + else + fun_l6_n678(x) + end +end + +def fun_l5_n214(x) + if (x < 1) + fun_l6_n470(x) + else + fun_l6_n877(x) + end +end + +def fun_l5_n215(x) + if (x < 1) + fun_l6_n78(x) + else + fun_l6_n315(x) + end +end + +def fun_l5_n216(x) + if (x < 1) + fun_l6_n281(x) + else + fun_l6_n872(x) + end +end + +def fun_l5_n217(x) + if (x < 1) + fun_l6_n200(x) + else + fun_l6_n323(x) + end +end + +def fun_l5_n218(x) + if (x < 1) + fun_l6_n483(x) + else + fun_l6_n938(x) + end +end + +def fun_l5_n219(x) + if (x < 1) + fun_l6_n102(x) + else + fun_l6_n690(x) + end +end + +def fun_l5_n220(x) + if (x < 1) + fun_l6_n740(x) + else + fun_l6_n684(x) + end +end + +def fun_l5_n221(x) + if (x < 1) + fun_l6_n366(x) + else + fun_l6_n138(x) + end +end + +def fun_l5_n222(x) + if (x < 1) + fun_l6_n306(x) + else + fun_l6_n874(x) + end +end + +def fun_l5_n223(x) + if (x < 1) + fun_l6_n828(x) + else + fun_l6_n839(x) + end +end + +def fun_l5_n224(x) + if (x < 1) + fun_l6_n739(x) + else + fun_l6_n569(x) + end +end + +def fun_l5_n225(x) + if (x < 1) + fun_l6_n332(x) + else + fun_l6_n49(x) + end +end + +def fun_l5_n226(x) + if (x < 1) + fun_l6_n783(x) + else + fun_l6_n20(x) + end +end + +def fun_l5_n227(x) + if (x < 1) + fun_l6_n774(x) + else + fun_l6_n346(x) + end +end + +def fun_l5_n228(x) + if (x < 1) + fun_l6_n637(x) + else + fun_l6_n302(x) + end +end + +def fun_l5_n229(x) + if (x < 1) + fun_l6_n10(x) + else + fun_l6_n697(x) + end +end + +def fun_l5_n230(x) + if (x < 1) + fun_l6_n804(x) + else + fun_l6_n141(x) + end +end + +def fun_l5_n231(x) + if (x < 1) + fun_l6_n232(x) + else + fun_l6_n88(x) + end +end + +def fun_l5_n232(x) + if (x < 1) + fun_l6_n248(x) + else + fun_l6_n862(x) + end +end + +def fun_l5_n233(x) + if (x < 1) + fun_l6_n287(x) + else + fun_l6_n315(x) + end +end + +def fun_l5_n234(x) + if (x < 1) + fun_l6_n543(x) + else + fun_l6_n182(x) + end +end + +def fun_l5_n235(x) + if (x < 1) + fun_l6_n162(x) + else + fun_l6_n710(x) + end +end + +def fun_l5_n236(x) + if (x < 1) + fun_l6_n879(x) + else + fun_l6_n262(x) + end +end + +def fun_l5_n237(x) + if (x < 1) + fun_l6_n706(x) + else + fun_l6_n112(x) + end +end + +def fun_l5_n238(x) + if (x < 1) + fun_l6_n578(x) + else + fun_l6_n792(x) + end +end + +def fun_l5_n239(x) + if (x < 1) + fun_l6_n685(x) + else + fun_l6_n441(x) + end +end + +def fun_l5_n240(x) + if (x < 1) + fun_l6_n706(x) + else + fun_l6_n737(x) + end +end + +def fun_l5_n241(x) + if (x < 1) + fun_l6_n360(x) + else + fun_l6_n751(x) + end +end + +def fun_l5_n242(x) + if (x < 1) + fun_l6_n823(x) + else + fun_l6_n888(x) + end +end + +def fun_l5_n243(x) + if (x < 1) + fun_l6_n743(x) + else + fun_l6_n705(x) + end +end + +def fun_l5_n244(x) + if (x < 1) + fun_l6_n340(x) + else + fun_l6_n541(x) + end +end + +def fun_l5_n245(x) + if (x < 1) + fun_l6_n324(x) + else + fun_l6_n121(x) + end +end + +def fun_l5_n246(x) + if (x < 1) + fun_l6_n241(x) + else + fun_l6_n584(x) + end +end + +def fun_l5_n247(x) + if (x < 1) + fun_l6_n468(x) + else + fun_l6_n673(x) + end +end + +def fun_l5_n248(x) + if (x < 1) + fun_l6_n595(x) + else + fun_l6_n537(x) + end +end + +def fun_l5_n249(x) + if (x < 1) + fun_l6_n166(x) + else + fun_l6_n766(x) + end +end + +def fun_l5_n250(x) + if (x < 1) + fun_l6_n322(x) + else + fun_l6_n904(x) + end +end + +def fun_l5_n251(x) + if (x < 1) + fun_l6_n273(x) + else + fun_l6_n353(x) + end +end + +def fun_l5_n252(x) + if (x < 1) + fun_l6_n990(x) + else + fun_l6_n360(x) + end +end + +def fun_l5_n253(x) + if (x < 1) + fun_l6_n552(x) + else + fun_l6_n649(x) + end +end + +def fun_l5_n254(x) + if (x < 1) + fun_l6_n917(x) + else + fun_l6_n803(x) + end +end + +def fun_l5_n255(x) + if (x < 1) + fun_l6_n763(x) + else + fun_l6_n464(x) + end +end + +def fun_l5_n256(x) + if (x < 1) + fun_l6_n577(x) + else + fun_l6_n70(x) + end +end + +def fun_l5_n257(x) + if (x < 1) + fun_l6_n618(x) + else + fun_l6_n943(x) + end +end + +def fun_l5_n258(x) + if (x < 1) + fun_l6_n683(x) + else + fun_l6_n761(x) + end +end + +def fun_l5_n259(x) + if (x < 1) + fun_l6_n284(x) + else + fun_l6_n223(x) + end +end + +def fun_l5_n260(x) + if (x < 1) + fun_l6_n189(x) + else + fun_l6_n455(x) + end +end + +def fun_l5_n261(x) + if (x < 1) + fun_l6_n632(x) + else + fun_l6_n245(x) + end +end + +def fun_l5_n262(x) + if (x < 1) + fun_l6_n940(x) + else + fun_l6_n38(x) + end +end + +def fun_l5_n263(x) + if (x < 1) + fun_l6_n289(x) + else + fun_l6_n356(x) + end +end + +def fun_l5_n264(x) + if (x < 1) + fun_l6_n268(x) + else + fun_l6_n412(x) + end +end + +def fun_l5_n265(x) + if (x < 1) + fun_l6_n370(x) + else + fun_l6_n858(x) + end +end + +def fun_l5_n266(x) + if (x < 1) + fun_l6_n523(x) + else + fun_l6_n809(x) + end +end + +def fun_l5_n267(x) + if (x < 1) + fun_l6_n469(x) + else + fun_l6_n260(x) + end +end + +def fun_l5_n268(x) + if (x < 1) + fun_l6_n442(x) + else + fun_l6_n738(x) + end +end + +def fun_l5_n269(x) + if (x < 1) + fun_l6_n663(x) + else + fun_l6_n109(x) + end +end + +def fun_l5_n270(x) + if (x < 1) + fun_l6_n302(x) + else + fun_l6_n664(x) + end +end + +def fun_l5_n271(x) + if (x < 1) + fun_l6_n201(x) + else + fun_l6_n251(x) + end +end + +def fun_l5_n272(x) + if (x < 1) + fun_l6_n776(x) + else + fun_l6_n903(x) + end +end + +def fun_l5_n273(x) + if (x < 1) + fun_l6_n683(x) + else + fun_l6_n233(x) + end +end + +def fun_l5_n274(x) + if (x < 1) + fun_l6_n530(x) + else + fun_l6_n487(x) + end +end + +def fun_l5_n275(x) + if (x < 1) + fun_l6_n848(x) + else + fun_l6_n99(x) + end +end + +def fun_l5_n276(x) + if (x < 1) + fun_l6_n126(x) + else + fun_l6_n914(x) + end +end + +def fun_l5_n277(x) + if (x < 1) + fun_l6_n304(x) + else + fun_l6_n198(x) + end +end + +def fun_l5_n278(x) + if (x < 1) + fun_l6_n47(x) + else + fun_l6_n179(x) + end +end + +def fun_l5_n279(x) + if (x < 1) + fun_l6_n846(x) + else + fun_l6_n301(x) + end +end + +def fun_l5_n280(x) + if (x < 1) + fun_l6_n576(x) + else + fun_l6_n561(x) + end +end + +def fun_l5_n281(x) + if (x < 1) + fun_l6_n307(x) + else + fun_l6_n545(x) + end +end + +def fun_l5_n282(x) + if (x < 1) + fun_l6_n434(x) + else + fun_l6_n669(x) + end +end + +def fun_l5_n283(x) + if (x < 1) + fun_l6_n606(x) + else + fun_l6_n147(x) + end +end + +def fun_l5_n284(x) + if (x < 1) + fun_l6_n212(x) + else + fun_l6_n504(x) + end +end + +def fun_l5_n285(x) + if (x < 1) + fun_l6_n193(x) + else + fun_l6_n165(x) + end +end + +def fun_l5_n286(x) + if (x < 1) + fun_l6_n569(x) + else + fun_l6_n100(x) + end +end + +def fun_l5_n287(x) + if (x < 1) + fun_l6_n59(x) + else + fun_l6_n998(x) + end +end + +def fun_l5_n288(x) + if (x < 1) + fun_l6_n544(x) + else + fun_l6_n923(x) + end +end + +def fun_l5_n289(x) + if (x < 1) + fun_l6_n317(x) + else + fun_l6_n255(x) + end +end + +def fun_l5_n290(x) + if (x < 1) + fun_l6_n476(x) + else + fun_l6_n789(x) + end +end + +def fun_l5_n291(x) + if (x < 1) + fun_l6_n324(x) + else + fun_l6_n162(x) + end +end + +def fun_l5_n292(x) + if (x < 1) + fun_l6_n704(x) + else + fun_l6_n454(x) + end +end + +def fun_l5_n293(x) + if (x < 1) + fun_l6_n994(x) + else + fun_l6_n637(x) + end +end + +def fun_l5_n294(x) + if (x < 1) + fun_l6_n801(x) + else + fun_l6_n913(x) + end +end + +def fun_l5_n295(x) + if (x < 1) + fun_l6_n579(x) + else + fun_l6_n795(x) + end +end + +def fun_l5_n296(x) + if (x < 1) + fun_l6_n689(x) + else + fun_l6_n546(x) + end +end + +def fun_l5_n297(x) + if (x < 1) + fun_l6_n971(x) + else + fun_l6_n493(x) + end +end + +def fun_l5_n298(x) + if (x < 1) + fun_l6_n67(x) + else + fun_l6_n372(x) + end +end + +def fun_l5_n299(x) + if (x < 1) + fun_l6_n654(x) + else + fun_l6_n921(x) + end +end + +def fun_l5_n300(x) + if (x < 1) + fun_l6_n402(x) + else + fun_l6_n437(x) + end +end + +def fun_l5_n301(x) + if (x < 1) + fun_l6_n448(x) + else + fun_l6_n177(x) + end +end + +def fun_l5_n302(x) + if (x < 1) + fun_l6_n308(x) + else + fun_l6_n869(x) + end +end + +def fun_l5_n303(x) + if (x < 1) + fun_l6_n825(x) + else + fun_l6_n848(x) + end +end + +def fun_l5_n304(x) + if (x < 1) + fun_l6_n735(x) + else + fun_l6_n653(x) + end +end + +def fun_l5_n305(x) + if (x < 1) + fun_l6_n393(x) + else + fun_l6_n113(x) + end +end + +def fun_l5_n306(x) + if (x < 1) + fun_l6_n821(x) + else + fun_l6_n827(x) + end +end + +def fun_l5_n307(x) + if (x < 1) + fun_l6_n734(x) + else + fun_l6_n498(x) + end +end + +def fun_l5_n308(x) + if (x < 1) + fun_l6_n833(x) + else + fun_l6_n302(x) + end +end + +def fun_l5_n309(x) + if (x < 1) + fun_l6_n596(x) + else + fun_l6_n544(x) + end +end + +def fun_l5_n310(x) + if (x < 1) + fun_l6_n61(x) + else + fun_l6_n823(x) + end +end + +def fun_l5_n311(x) + if (x < 1) + fun_l6_n596(x) + else + fun_l6_n98(x) + end +end + +def fun_l5_n312(x) + if (x < 1) + fun_l6_n78(x) + else + fun_l6_n186(x) + end +end + +def fun_l5_n313(x) + if (x < 1) + fun_l6_n286(x) + else + fun_l6_n230(x) + end +end + +def fun_l5_n314(x) + if (x < 1) + fun_l6_n613(x) + else + fun_l6_n412(x) + end +end + +def fun_l5_n315(x) + if (x < 1) + fun_l6_n0(x) + else + fun_l6_n579(x) + end +end + +def fun_l5_n316(x) + if (x < 1) + fun_l6_n991(x) + else + fun_l6_n379(x) + end +end + +def fun_l5_n317(x) + if (x < 1) + fun_l6_n825(x) + else + fun_l6_n964(x) + end +end + +def fun_l5_n318(x) + if (x < 1) + fun_l6_n707(x) + else + fun_l6_n664(x) + end +end + +def fun_l5_n319(x) + if (x < 1) + fun_l6_n326(x) + else + fun_l6_n26(x) + end +end + +def fun_l5_n320(x) + if (x < 1) + fun_l6_n684(x) + else + fun_l6_n333(x) + end +end + +def fun_l5_n321(x) + if (x < 1) + fun_l6_n165(x) + else + fun_l6_n586(x) + end +end + +def fun_l5_n322(x) + if (x < 1) + fun_l6_n28(x) + else + fun_l6_n53(x) + end +end + +def fun_l5_n323(x) + if (x < 1) + fun_l6_n693(x) + else + fun_l6_n84(x) + end +end + +def fun_l5_n324(x) + if (x < 1) + fun_l6_n500(x) + else + fun_l6_n445(x) + end +end + +def fun_l5_n325(x) + if (x < 1) + fun_l6_n189(x) + else + fun_l6_n756(x) + end +end + +def fun_l5_n326(x) + if (x < 1) + fun_l6_n147(x) + else + fun_l6_n709(x) + end +end + +def fun_l5_n327(x) + if (x < 1) + fun_l6_n893(x) + else + fun_l6_n851(x) + end +end + +def fun_l5_n328(x) + if (x < 1) + fun_l6_n685(x) + else + fun_l6_n399(x) + end +end + +def fun_l5_n329(x) + if (x < 1) + fun_l6_n281(x) + else + fun_l6_n284(x) + end +end + +def fun_l5_n330(x) + if (x < 1) + fun_l6_n579(x) + else + fun_l6_n671(x) + end +end + +def fun_l5_n331(x) + if (x < 1) + fun_l6_n176(x) + else + fun_l6_n829(x) + end +end + +def fun_l5_n332(x) + if (x < 1) + fun_l6_n209(x) + else + fun_l6_n91(x) + end +end + +def fun_l5_n333(x) + if (x < 1) + fun_l6_n302(x) + else + fun_l6_n360(x) + end +end + +def fun_l5_n334(x) + if (x < 1) + fun_l6_n701(x) + else + fun_l6_n438(x) + end +end + +def fun_l5_n335(x) + if (x < 1) + fun_l6_n923(x) + else + fun_l6_n613(x) + end +end + +def fun_l5_n336(x) + if (x < 1) + fun_l6_n490(x) + else + fun_l6_n405(x) + end +end + +def fun_l5_n337(x) + if (x < 1) + fun_l6_n187(x) + else + fun_l6_n953(x) + end +end + +def fun_l5_n338(x) + if (x < 1) + fun_l6_n396(x) + else + fun_l6_n917(x) + end +end + +def fun_l5_n339(x) + if (x < 1) + fun_l6_n822(x) + else + fun_l6_n939(x) + end +end + +def fun_l5_n340(x) + if (x < 1) + fun_l6_n665(x) + else + fun_l6_n890(x) + end +end + +def fun_l5_n341(x) + if (x < 1) + fun_l6_n125(x) + else + fun_l6_n817(x) + end +end + +def fun_l5_n342(x) + if (x < 1) + fun_l6_n825(x) + else + fun_l6_n853(x) + end +end + +def fun_l5_n343(x) + if (x < 1) + fun_l6_n724(x) + else + fun_l6_n633(x) + end +end + +def fun_l5_n344(x) + if (x < 1) + fun_l6_n901(x) + else + fun_l6_n26(x) + end +end + +def fun_l5_n345(x) + if (x < 1) + fun_l6_n406(x) + else + fun_l6_n664(x) + end +end + +def fun_l5_n346(x) + if (x < 1) + fun_l6_n720(x) + else + fun_l6_n856(x) + end +end + +def fun_l5_n347(x) + if (x < 1) + fun_l6_n617(x) + else + fun_l6_n116(x) + end +end + +def fun_l5_n348(x) + if (x < 1) + fun_l6_n560(x) + else + fun_l6_n24(x) + end +end + +def fun_l5_n349(x) + if (x < 1) + fun_l6_n758(x) + else + fun_l6_n297(x) + end +end + +def fun_l5_n350(x) + if (x < 1) + fun_l6_n583(x) + else + fun_l6_n673(x) + end +end + +def fun_l5_n351(x) + if (x < 1) + fun_l6_n990(x) + else + fun_l6_n512(x) + end +end + +def fun_l5_n352(x) + if (x < 1) + fun_l6_n250(x) + else + fun_l6_n819(x) + end +end + +def fun_l5_n353(x) + if (x < 1) + fun_l6_n186(x) + else + fun_l6_n787(x) + end +end + +def fun_l5_n354(x) + if (x < 1) + fun_l6_n217(x) + else + fun_l6_n231(x) + end +end + +def fun_l5_n355(x) + if (x < 1) + fun_l6_n827(x) + else + fun_l6_n439(x) + end +end + +def fun_l5_n356(x) + if (x < 1) + fun_l6_n456(x) + else + fun_l6_n352(x) + end +end + +def fun_l5_n357(x) + if (x < 1) + fun_l6_n306(x) + else + fun_l6_n236(x) + end +end + +def fun_l5_n358(x) + if (x < 1) + fun_l6_n515(x) + else + fun_l6_n100(x) + end +end + +def fun_l5_n359(x) + if (x < 1) + fun_l6_n28(x) + else + fun_l6_n820(x) + end +end + +def fun_l5_n360(x) + if (x < 1) + fun_l6_n683(x) + else + fun_l6_n547(x) + end +end + +def fun_l5_n361(x) + if (x < 1) + fun_l6_n573(x) + else + fun_l6_n699(x) + end +end + +def fun_l5_n362(x) + if (x < 1) + fun_l6_n807(x) + else + fun_l6_n548(x) + end +end + +def fun_l5_n363(x) + if (x < 1) + fun_l6_n712(x) + else + fun_l6_n323(x) + end +end + +def fun_l5_n364(x) + if (x < 1) + fun_l6_n457(x) + else + fun_l6_n447(x) + end +end + +def fun_l5_n365(x) + if (x < 1) + fun_l6_n684(x) + else + fun_l6_n782(x) + end +end + +def fun_l5_n366(x) + if (x < 1) + fun_l6_n217(x) + else + fun_l6_n344(x) + end +end + +def fun_l5_n367(x) + if (x < 1) + fun_l6_n670(x) + else + fun_l6_n311(x) + end +end + +def fun_l5_n368(x) + if (x < 1) + fun_l6_n224(x) + else + fun_l6_n198(x) + end +end + +def fun_l5_n369(x) + if (x < 1) + fun_l6_n517(x) + else + fun_l6_n186(x) + end +end + +def fun_l5_n370(x) + if (x < 1) + fun_l6_n511(x) + else + fun_l6_n27(x) + end +end + +def fun_l5_n371(x) + if (x < 1) + fun_l6_n485(x) + else + fun_l6_n288(x) + end +end + +def fun_l5_n372(x) + if (x < 1) + fun_l6_n931(x) + else + fun_l6_n473(x) + end +end + +def fun_l5_n373(x) + if (x < 1) + fun_l6_n381(x) + else + fun_l6_n650(x) + end +end + +def fun_l5_n374(x) + if (x < 1) + fun_l6_n132(x) + else + fun_l6_n243(x) + end +end + +def fun_l5_n375(x) + if (x < 1) + fun_l6_n900(x) + else + fun_l6_n322(x) + end +end + +def fun_l5_n376(x) + if (x < 1) + fun_l6_n787(x) + else + fun_l6_n588(x) + end +end + +def fun_l5_n377(x) + if (x < 1) + fun_l6_n233(x) + else + fun_l6_n358(x) + end +end + +def fun_l5_n378(x) + if (x < 1) + fun_l6_n601(x) + else + fun_l6_n40(x) + end +end + +def fun_l5_n379(x) + if (x < 1) + fun_l6_n682(x) + else + fun_l6_n63(x) + end +end + +def fun_l5_n380(x) + if (x < 1) + fun_l6_n279(x) + else + fun_l6_n393(x) + end +end + +def fun_l5_n381(x) + if (x < 1) + fun_l6_n83(x) + else + fun_l6_n538(x) + end +end + +def fun_l5_n382(x) + if (x < 1) + fun_l6_n956(x) + else + fun_l6_n194(x) + end +end + +def fun_l5_n383(x) + if (x < 1) + fun_l6_n55(x) + else + fun_l6_n140(x) + end +end + +def fun_l5_n384(x) + if (x < 1) + fun_l6_n165(x) + else + fun_l6_n784(x) + end +end + +def fun_l5_n385(x) + if (x < 1) + fun_l6_n582(x) + else + fun_l6_n97(x) + end +end + +def fun_l5_n386(x) + if (x < 1) + fun_l6_n362(x) + else + fun_l6_n935(x) + end +end + +def fun_l5_n387(x) + if (x < 1) + fun_l6_n496(x) + else + fun_l6_n512(x) + end +end + +def fun_l5_n388(x) + if (x < 1) + fun_l6_n793(x) + else + fun_l6_n746(x) + end +end + +def fun_l5_n389(x) + if (x < 1) + fun_l6_n172(x) + else + fun_l6_n731(x) + end +end + +def fun_l5_n390(x) + if (x < 1) + fun_l6_n895(x) + else + fun_l6_n694(x) + end +end + +def fun_l5_n391(x) + if (x < 1) + fun_l6_n336(x) + else + fun_l6_n551(x) + end +end + +def fun_l5_n392(x) + if (x < 1) + fun_l6_n453(x) + else + fun_l6_n83(x) + end +end + +def fun_l5_n393(x) + if (x < 1) + fun_l6_n571(x) + else + fun_l6_n293(x) + end +end + +def fun_l5_n394(x) + if (x < 1) + fun_l6_n872(x) + else + fun_l6_n519(x) + end +end + +def fun_l5_n395(x) + if (x < 1) + fun_l6_n912(x) + else + fun_l6_n955(x) + end +end + +def fun_l5_n396(x) + if (x < 1) + fun_l6_n961(x) + else + fun_l6_n367(x) + end +end + +def fun_l5_n397(x) + if (x < 1) + fun_l6_n255(x) + else + fun_l6_n639(x) + end +end + +def fun_l5_n398(x) + if (x < 1) + fun_l6_n970(x) + else + fun_l6_n465(x) + end +end + +def fun_l5_n399(x) + if (x < 1) + fun_l6_n625(x) + else + fun_l6_n387(x) + end +end + +def fun_l5_n400(x) + if (x < 1) + fun_l6_n537(x) + else + fun_l6_n336(x) + end +end + +def fun_l5_n401(x) + if (x < 1) + fun_l6_n61(x) + else + fun_l6_n0(x) + end +end + +def fun_l5_n402(x) + if (x < 1) + fun_l6_n358(x) + else + fun_l6_n715(x) + end +end + +def fun_l5_n403(x) + if (x < 1) + fun_l6_n864(x) + else + fun_l6_n729(x) + end +end + +def fun_l5_n404(x) + if (x < 1) + fun_l6_n393(x) + else + fun_l6_n962(x) + end +end + +def fun_l5_n405(x) + if (x < 1) + fun_l6_n995(x) + else + fun_l6_n835(x) + end +end + +def fun_l5_n406(x) + if (x < 1) + fun_l6_n605(x) + else + fun_l6_n732(x) + end +end + +def fun_l5_n407(x) + if (x < 1) + fun_l6_n132(x) + else + fun_l6_n112(x) + end +end + +def fun_l5_n408(x) + if (x < 1) + fun_l6_n311(x) + else + fun_l6_n972(x) + end +end + +def fun_l5_n409(x) + if (x < 1) + fun_l6_n460(x) + else + fun_l6_n750(x) + end +end + +def fun_l5_n410(x) + if (x < 1) + fun_l6_n237(x) + else + fun_l6_n463(x) + end +end + +def fun_l5_n411(x) + if (x < 1) + fun_l6_n251(x) + else + fun_l6_n944(x) + end +end + +def fun_l5_n412(x) + if (x < 1) + fun_l6_n123(x) + else + fun_l6_n369(x) + end +end + +def fun_l5_n413(x) + if (x < 1) + fun_l6_n371(x) + else + fun_l6_n589(x) + end +end + +def fun_l5_n414(x) + if (x < 1) + fun_l6_n232(x) + else + fun_l6_n354(x) + end +end + +def fun_l5_n415(x) + if (x < 1) + fun_l6_n580(x) + else + fun_l6_n330(x) + end +end + +def fun_l5_n416(x) + if (x < 1) + fun_l6_n483(x) + else + fun_l6_n446(x) + end +end + +def fun_l5_n417(x) + if (x < 1) + fun_l6_n834(x) + else + fun_l6_n284(x) + end +end + +def fun_l5_n418(x) + if (x < 1) + fun_l6_n864(x) + else + fun_l6_n825(x) + end +end + +def fun_l5_n419(x) + if (x < 1) + fun_l6_n406(x) + else + fun_l6_n680(x) + end +end + +def fun_l5_n420(x) + if (x < 1) + fun_l6_n101(x) + else + fun_l6_n4(x) + end +end + +def fun_l5_n421(x) + if (x < 1) + fun_l6_n628(x) + else + fun_l6_n303(x) + end +end + +def fun_l5_n422(x) + if (x < 1) + fun_l6_n521(x) + else + fun_l6_n547(x) + end +end + +def fun_l5_n423(x) + if (x < 1) + fun_l6_n589(x) + else + fun_l6_n134(x) + end +end + +def fun_l5_n424(x) + if (x < 1) + fun_l6_n161(x) + else + fun_l6_n347(x) + end +end + +def fun_l5_n425(x) + if (x < 1) + fun_l6_n59(x) + else + fun_l6_n988(x) + end +end + +def fun_l5_n426(x) + if (x < 1) + fun_l6_n388(x) + else + fun_l6_n182(x) + end +end + +def fun_l5_n427(x) + if (x < 1) + fun_l6_n500(x) + else + fun_l6_n536(x) + end +end + +def fun_l5_n428(x) + if (x < 1) + fun_l6_n792(x) + else + fun_l6_n253(x) + end +end + +def fun_l5_n429(x) + if (x < 1) + fun_l6_n774(x) + else + fun_l6_n997(x) + end +end + +def fun_l5_n430(x) + if (x < 1) + fun_l6_n876(x) + else + fun_l6_n798(x) + end +end + +def fun_l5_n431(x) + if (x < 1) + fun_l6_n606(x) + else + fun_l6_n403(x) + end +end + +def fun_l5_n432(x) + if (x < 1) + fun_l6_n920(x) + else + fun_l6_n827(x) + end +end + +def fun_l5_n433(x) + if (x < 1) + fun_l6_n887(x) + else + fun_l6_n149(x) + end +end + +def fun_l5_n434(x) + if (x < 1) + fun_l6_n413(x) + else + fun_l6_n44(x) + end +end + +def fun_l5_n435(x) + if (x < 1) + fun_l6_n474(x) + else + fun_l6_n107(x) + end +end + +def fun_l5_n436(x) + if (x < 1) + fun_l6_n807(x) + else + fun_l6_n636(x) + end +end + +def fun_l5_n437(x) + if (x < 1) + fun_l6_n616(x) + else + fun_l6_n615(x) + end +end + +def fun_l5_n438(x) + if (x < 1) + fun_l6_n384(x) + else + fun_l6_n535(x) + end +end + +def fun_l5_n439(x) + if (x < 1) + fun_l6_n326(x) + else + fun_l6_n929(x) + end +end + +def fun_l5_n440(x) + if (x < 1) + fun_l6_n852(x) + else + fun_l6_n597(x) + end +end + +def fun_l5_n441(x) + if (x < 1) + fun_l6_n246(x) + else + fun_l6_n991(x) + end +end + +def fun_l5_n442(x) + if (x < 1) + fun_l6_n258(x) + else + fun_l6_n140(x) + end +end + +def fun_l5_n443(x) + if (x < 1) + fun_l6_n815(x) + else + fun_l6_n600(x) + end +end + +def fun_l5_n444(x) + if (x < 1) + fun_l6_n153(x) + else + fun_l6_n902(x) + end +end + +def fun_l5_n445(x) + if (x < 1) + fun_l6_n289(x) + else + fun_l6_n240(x) + end +end + +def fun_l5_n446(x) + if (x < 1) + fun_l6_n398(x) + else + fun_l6_n273(x) + end +end + +def fun_l5_n447(x) + if (x < 1) + fun_l6_n537(x) + else + fun_l6_n8(x) + end +end + +def fun_l5_n448(x) + if (x < 1) + fun_l6_n801(x) + else + fun_l6_n389(x) + end +end + +def fun_l5_n449(x) + if (x < 1) + fun_l6_n363(x) + else + fun_l6_n17(x) + end +end + +def fun_l5_n450(x) + if (x < 1) + fun_l6_n511(x) + else + fun_l6_n151(x) + end +end + +def fun_l5_n451(x) + if (x < 1) + fun_l6_n640(x) + else + fun_l6_n785(x) + end +end + +def fun_l5_n452(x) + if (x < 1) + fun_l6_n961(x) + else + fun_l6_n567(x) + end +end + +def fun_l5_n453(x) + if (x < 1) + fun_l6_n608(x) + else + fun_l6_n910(x) + end +end + +def fun_l5_n454(x) + if (x < 1) + fun_l6_n898(x) + else + fun_l6_n231(x) + end +end + +def fun_l5_n455(x) + if (x < 1) + fun_l6_n205(x) + else + fun_l6_n162(x) + end +end + +def fun_l5_n456(x) + if (x < 1) + fun_l6_n374(x) + else + fun_l6_n544(x) + end +end + +def fun_l5_n457(x) + if (x < 1) + fun_l6_n514(x) + else + fun_l6_n522(x) + end +end + +def fun_l5_n458(x) + if (x < 1) + fun_l6_n385(x) + else + fun_l6_n808(x) + end +end + +def fun_l5_n459(x) + if (x < 1) + fun_l6_n525(x) + else + fun_l6_n144(x) + end +end + +def fun_l5_n460(x) + if (x < 1) + fun_l6_n781(x) + else + fun_l6_n180(x) + end +end + +def fun_l5_n461(x) + if (x < 1) + fun_l6_n681(x) + else + fun_l6_n273(x) + end +end + +def fun_l5_n462(x) + if (x < 1) + fun_l6_n497(x) + else + fun_l6_n399(x) + end +end + +def fun_l5_n463(x) + if (x < 1) + fun_l6_n261(x) + else + fun_l6_n311(x) + end +end + +def fun_l5_n464(x) + if (x < 1) + fun_l6_n64(x) + else + fun_l6_n253(x) + end +end + +def fun_l5_n465(x) + if (x < 1) + fun_l6_n388(x) + else + fun_l6_n300(x) + end +end + +def fun_l5_n466(x) + if (x < 1) + fun_l6_n822(x) + else + fun_l6_n277(x) + end +end + +def fun_l5_n467(x) + if (x < 1) + fun_l6_n909(x) + else + fun_l6_n605(x) + end +end + +def fun_l5_n468(x) + if (x < 1) + fun_l6_n879(x) + else + fun_l6_n870(x) + end +end + +def fun_l5_n469(x) + if (x < 1) + fun_l6_n351(x) + else + fun_l6_n917(x) + end +end + +def fun_l5_n470(x) + if (x < 1) + fun_l6_n202(x) + else + fun_l6_n40(x) + end +end + +def fun_l5_n471(x) + if (x < 1) + fun_l6_n782(x) + else + fun_l6_n839(x) + end +end + +def fun_l5_n472(x) + if (x < 1) + fun_l6_n370(x) + else + fun_l6_n868(x) + end +end + +def fun_l5_n473(x) + if (x < 1) + fun_l6_n556(x) + else + fun_l6_n722(x) + end +end + +def fun_l5_n474(x) + if (x < 1) + fun_l6_n220(x) + else + fun_l6_n994(x) + end +end + +def fun_l5_n475(x) + if (x < 1) + fun_l6_n266(x) + else + fun_l6_n872(x) + end +end + +def fun_l5_n476(x) + if (x < 1) + fun_l6_n720(x) + else + fun_l6_n412(x) + end +end + +def fun_l5_n477(x) + if (x < 1) + fun_l6_n284(x) + else + fun_l6_n90(x) + end +end + +def fun_l5_n478(x) + if (x < 1) + fun_l6_n716(x) + else + fun_l6_n125(x) + end +end + +def fun_l5_n479(x) + if (x < 1) + fun_l6_n136(x) + else + fun_l6_n232(x) + end +end + +def fun_l5_n480(x) + if (x < 1) + fun_l6_n627(x) + else + fun_l6_n641(x) + end +end + +def fun_l5_n481(x) + if (x < 1) + fun_l6_n411(x) + else + fun_l6_n943(x) + end +end + +def fun_l5_n482(x) + if (x < 1) + fun_l6_n86(x) + else + fun_l6_n839(x) + end +end + +def fun_l5_n483(x) + if (x < 1) + fun_l6_n988(x) + else + fun_l6_n329(x) + end +end + +def fun_l5_n484(x) + if (x < 1) + fun_l6_n595(x) + else + fun_l6_n499(x) + end +end + +def fun_l5_n485(x) + if (x < 1) + fun_l6_n912(x) + else + fun_l6_n267(x) + end +end + +def fun_l5_n486(x) + if (x < 1) + fun_l6_n334(x) + else + fun_l6_n459(x) + end +end + +def fun_l5_n487(x) + if (x < 1) + fun_l6_n771(x) + else + fun_l6_n458(x) + end +end + +def fun_l5_n488(x) + if (x < 1) + fun_l6_n609(x) + else + fun_l6_n280(x) + end +end + +def fun_l5_n489(x) + if (x < 1) + fun_l6_n564(x) + else + fun_l6_n564(x) + end +end + +def fun_l5_n490(x) + if (x < 1) + fun_l6_n271(x) + else + fun_l6_n904(x) + end +end + +def fun_l5_n491(x) + if (x < 1) + fun_l6_n338(x) + else + fun_l6_n694(x) + end +end + +def fun_l5_n492(x) + if (x < 1) + fun_l6_n596(x) + else + fun_l6_n191(x) + end +end + +def fun_l5_n493(x) + if (x < 1) + fun_l6_n369(x) + else + fun_l6_n513(x) + end +end + +def fun_l5_n494(x) + if (x < 1) + fun_l6_n972(x) + else + fun_l6_n945(x) + end +end + +def fun_l5_n495(x) + if (x < 1) + fun_l6_n747(x) + else + fun_l6_n96(x) + end +end + +def fun_l5_n496(x) + if (x < 1) + fun_l6_n220(x) + else + fun_l6_n665(x) + end +end + +def fun_l5_n497(x) + if (x < 1) + fun_l6_n793(x) + else + fun_l6_n468(x) + end +end + +def fun_l5_n498(x) + if (x < 1) + fun_l6_n227(x) + else + fun_l6_n576(x) + end +end + +def fun_l5_n499(x) + if (x < 1) + fun_l6_n356(x) + else + fun_l6_n614(x) + end +end + +def fun_l5_n500(x) + if (x < 1) + fun_l6_n256(x) + else + fun_l6_n237(x) + end +end + +def fun_l5_n501(x) + if (x < 1) + fun_l6_n503(x) + else + fun_l6_n159(x) + end +end + +def fun_l5_n502(x) + if (x < 1) + fun_l6_n523(x) + else + fun_l6_n547(x) + end +end + +def fun_l5_n503(x) + if (x < 1) + fun_l6_n778(x) + else + fun_l6_n600(x) + end +end + +def fun_l5_n504(x) + if (x < 1) + fun_l6_n654(x) + else + fun_l6_n950(x) + end +end + +def fun_l5_n505(x) + if (x < 1) + fun_l6_n105(x) + else + fun_l6_n881(x) + end +end + +def fun_l5_n506(x) + if (x < 1) + fun_l6_n956(x) + else + fun_l6_n71(x) + end +end + +def fun_l5_n507(x) + if (x < 1) + fun_l6_n33(x) + else + fun_l6_n431(x) + end +end + +def fun_l5_n508(x) + if (x < 1) + fun_l6_n587(x) + else + fun_l6_n1(x) + end +end + +def fun_l5_n509(x) + if (x < 1) + fun_l6_n258(x) + else + fun_l6_n547(x) + end +end + +def fun_l5_n510(x) + if (x < 1) + fun_l6_n816(x) + else + fun_l6_n558(x) + end +end + +def fun_l5_n511(x) + if (x < 1) + fun_l6_n61(x) + else + fun_l6_n10(x) + end +end + +def fun_l5_n512(x) + if (x < 1) + fun_l6_n674(x) + else + fun_l6_n466(x) + end +end + +def fun_l5_n513(x) + if (x < 1) + fun_l6_n580(x) + else + fun_l6_n398(x) + end +end + +def fun_l5_n514(x) + if (x < 1) + fun_l6_n495(x) + else + fun_l6_n407(x) + end +end + +def fun_l5_n515(x) + if (x < 1) + fun_l6_n639(x) + else + fun_l6_n214(x) + end +end + +def fun_l5_n516(x) + if (x < 1) + fun_l6_n15(x) + else + fun_l6_n716(x) + end +end + +def fun_l5_n517(x) + if (x < 1) + fun_l6_n645(x) + else + fun_l6_n645(x) + end +end + +def fun_l5_n518(x) + if (x < 1) + fun_l6_n615(x) + else + fun_l6_n44(x) + end +end + +def fun_l5_n519(x) + if (x < 1) + fun_l6_n399(x) + else + fun_l6_n663(x) + end +end + +def fun_l5_n520(x) + if (x < 1) + fun_l6_n85(x) + else + fun_l6_n870(x) + end +end + +def fun_l5_n521(x) + if (x < 1) + fun_l6_n14(x) + else + fun_l6_n965(x) + end +end + +def fun_l5_n522(x) + if (x < 1) + fun_l6_n24(x) + else + fun_l6_n581(x) + end +end + +def fun_l5_n523(x) + if (x < 1) + fun_l6_n501(x) + else + fun_l6_n913(x) + end +end + +def fun_l5_n524(x) + if (x < 1) + fun_l6_n772(x) + else + fun_l6_n999(x) + end +end + +def fun_l5_n525(x) + if (x < 1) + fun_l6_n847(x) + else + fun_l6_n422(x) + end +end + +def fun_l5_n526(x) + if (x < 1) + fun_l6_n377(x) + else + fun_l6_n986(x) + end +end + +def fun_l5_n527(x) + if (x < 1) + fun_l6_n548(x) + else + fun_l6_n40(x) + end +end + +def fun_l5_n528(x) + if (x < 1) + fun_l6_n392(x) + else + fun_l6_n577(x) + end +end + +def fun_l5_n529(x) + if (x < 1) + fun_l6_n101(x) + else + fun_l6_n26(x) + end +end + +def fun_l5_n530(x) + if (x < 1) + fun_l6_n800(x) + else + fun_l6_n958(x) + end +end + +def fun_l5_n531(x) + if (x < 1) + fun_l6_n72(x) + else + fun_l6_n887(x) + end +end + +def fun_l5_n532(x) + if (x < 1) + fun_l6_n467(x) + else + fun_l6_n740(x) + end +end + +def fun_l5_n533(x) + if (x < 1) + fun_l6_n264(x) + else + fun_l6_n683(x) + end +end + +def fun_l5_n534(x) + if (x < 1) + fun_l6_n953(x) + else + fun_l6_n560(x) + end +end + +def fun_l5_n535(x) + if (x < 1) + fun_l6_n854(x) + else + fun_l6_n59(x) + end +end + +def fun_l5_n536(x) + if (x < 1) + fun_l6_n940(x) + else + fun_l6_n832(x) + end +end + +def fun_l5_n537(x) + if (x < 1) + fun_l6_n297(x) + else + fun_l6_n18(x) + end +end + +def fun_l5_n538(x) + if (x < 1) + fun_l6_n188(x) + else + fun_l6_n537(x) + end +end + +def fun_l5_n539(x) + if (x < 1) + fun_l6_n992(x) + else + fun_l6_n825(x) + end +end + +def fun_l5_n540(x) + if (x < 1) + fun_l6_n691(x) + else + fun_l6_n850(x) + end +end + +def fun_l5_n541(x) + if (x < 1) + fun_l6_n858(x) + else + fun_l6_n948(x) + end +end + +def fun_l5_n542(x) + if (x < 1) + fun_l6_n923(x) + else + fun_l6_n112(x) + end +end + +def fun_l5_n543(x) + if (x < 1) + fun_l6_n419(x) + else + fun_l6_n4(x) + end +end + +def fun_l5_n544(x) + if (x < 1) + fun_l6_n766(x) + else + fun_l6_n147(x) + end +end + +def fun_l5_n545(x) + if (x < 1) + fun_l6_n327(x) + else + fun_l6_n327(x) + end +end + +def fun_l5_n546(x) + if (x < 1) + fun_l6_n94(x) + else + fun_l6_n662(x) + end +end + +def fun_l5_n547(x) + if (x < 1) + fun_l6_n764(x) + else + fun_l6_n521(x) + end +end + +def fun_l5_n548(x) + if (x < 1) + fun_l6_n509(x) + else + fun_l6_n231(x) + end +end + +def fun_l5_n549(x) + if (x < 1) + fun_l6_n370(x) + else + fun_l6_n599(x) + end +end + +def fun_l5_n550(x) + if (x < 1) + fun_l6_n710(x) + else + fun_l6_n104(x) + end +end + +def fun_l5_n551(x) + if (x < 1) + fun_l6_n677(x) + else + fun_l6_n184(x) + end +end + +def fun_l5_n552(x) + if (x < 1) + fun_l6_n700(x) + else + fun_l6_n299(x) + end +end + +def fun_l5_n553(x) + if (x < 1) + fun_l6_n688(x) + else + fun_l6_n934(x) + end +end + +def fun_l5_n554(x) + if (x < 1) + fun_l6_n771(x) + else + fun_l6_n989(x) + end +end + +def fun_l5_n555(x) + if (x < 1) + fun_l6_n164(x) + else + fun_l6_n197(x) + end +end + +def fun_l5_n556(x) + if (x < 1) + fun_l6_n901(x) + else + fun_l6_n235(x) + end +end + +def fun_l5_n557(x) + if (x < 1) + fun_l6_n990(x) + else + fun_l6_n490(x) + end +end + +def fun_l5_n558(x) + if (x < 1) + fun_l6_n476(x) + else + fun_l6_n612(x) + end +end + +def fun_l5_n559(x) + if (x < 1) + fun_l6_n761(x) + else + fun_l6_n3(x) + end +end + +def fun_l5_n560(x) + if (x < 1) + fun_l6_n461(x) + else + fun_l6_n832(x) + end +end + +def fun_l5_n561(x) + if (x < 1) + fun_l6_n206(x) + else + fun_l6_n815(x) + end +end + +def fun_l5_n562(x) + if (x < 1) + fun_l6_n180(x) + else + fun_l6_n640(x) + end +end + +def fun_l5_n563(x) + if (x < 1) + fun_l6_n612(x) + else + fun_l6_n900(x) + end +end + +def fun_l5_n564(x) + if (x < 1) + fun_l6_n31(x) + else + fun_l6_n290(x) + end +end + +def fun_l5_n565(x) + if (x < 1) + fun_l6_n322(x) + else + fun_l6_n136(x) + end +end + +def fun_l5_n566(x) + if (x < 1) + fun_l6_n657(x) + else + fun_l6_n649(x) + end +end + +def fun_l5_n567(x) + if (x < 1) + fun_l6_n683(x) + else + fun_l6_n903(x) + end +end + +def fun_l5_n568(x) + if (x < 1) + fun_l6_n391(x) + else + fun_l6_n117(x) + end +end + +def fun_l5_n569(x) + if (x < 1) + fun_l6_n868(x) + else + fun_l6_n644(x) + end +end + +def fun_l5_n570(x) + if (x < 1) + fun_l6_n493(x) + else + fun_l6_n638(x) + end +end + +def fun_l5_n571(x) + if (x < 1) + fun_l6_n207(x) + else + fun_l6_n650(x) + end +end + +def fun_l5_n572(x) + if (x < 1) + fun_l6_n575(x) + else + fun_l6_n421(x) + end +end + +def fun_l5_n573(x) + if (x < 1) + fun_l6_n757(x) + else + fun_l6_n515(x) + end +end + +def fun_l5_n574(x) + if (x < 1) + fun_l6_n619(x) + else + fun_l6_n39(x) + end +end + +def fun_l5_n575(x) + if (x < 1) + fun_l6_n91(x) + else + fun_l6_n79(x) + end +end + +def fun_l5_n576(x) + if (x < 1) + fun_l6_n492(x) + else + fun_l6_n938(x) + end +end + +def fun_l5_n577(x) + if (x < 1) + fun_l6_n181(x) + else + fun_l6_n98(x) + end +end + +def fun_l5_n578(x) + if (x < 1) + fun_l6_n823(x) + else + fun_l6_n528(x) + end +end + +def fun_l5_n579(x) + if (x < 1) + fun_l6_n218(x) + else + fun_l6_n613(x) + end +end + +def fun_l5_n580(x) + if (x < 1) + fun_l6_n81(x) + else + fun_l6_n318(x) + end +end + +def fun_l5_n581(x) + if (x < 1) + fun_l6_n953(x) + else + fun_l6_n162(x) + end +end + +def fun_l5_n582(x) + if (x < 1) + fun_l6_n225(x) + else + fun_l6_n441(x) + end +end + +def fun_l5_n583(x) + if (x < 1) + fun_l6_n862(x) + else + fun_l6_n939(x) + end +end + +def fun_l5_n584(x) + if (x < 1) + fun_l6_n401(x) + else + fun_l6_n149(x) + end +end + +def fun_l5_n585(x) + if (x < 1) + fun_l6_n94(x) + else + fun_l6_n320(x) + end +end + +def fun_l5_n586(x) + if (x < 1) + fun_l6_n609(x) + else + fun_l6_n524(x) + end +end + +def fun_l5_n587(x) + if (x < 1) + fun_l6_n412(x) + else + fun_l6_n350(x) + end +end + +def fun_l5_n588(x) + if (x < 1) + fun_l6_n874(x) + else + fun_l6_n217(x) + end +end + +def fun_l5_n589(x) + if (x < 1) + fun_l6_n989(x) + else + fun_l6_n62(x) + end +end + +def fun_l5_n590(x) + if (x < 1) + fun_l6_n91(x) + else + fun_l6_n360(x) + end +end + +def fun_l5_n591(x) + if (x < 1) + fun_l6_n392(x) + else + fun_l6_n530(x) + end +end + +def fun_l5_n592(x) + if (x < 1) + fun_l6_n635(x) + else + fun_l6_n268(x) + end +end + +def fun_l5_n593(x) + if (x < 1) + fun_l6_n747(x) + else + fun_l6_n345(x) + end +end + +def fun_l5_n594(x) + if (x < 1) + fun_l6_n450(x) + else + fun_l6_n165(x) + end +end + +def fun_l5_n595(x) + if (x < 1) + fun_l6_n960(x) + else + fun_l6_n256(x) + end +end + +def fun_l5_n596(x) + if (x < 1) + fun_l6_n724(x) + else + fun_l6_n506(x) + end +end + +def fun_l5_n597(x) + if (x < 1) + fun_l6_n809(x) + else + fun_l6_n180(x) + end +end + +def fun_l5_n598(x) + if (x < 1) + fun_l6_n799(x) + else + fun_l6_n59(x) + end +end + +def fun_l5_n599(x) + if (x < 1) + fun_l6_n412(x) + else + fun_l6_n868(x) + end +end + +def fun_l5_n600(x) + if (x < 1) + fun_l6_n459(x) + else + fun_l6_n537(x) + end +end + +def fun_l5_n601(x) + if (x < 1) + fun_l6_n321(x) + else + fun_l6_n39(x) + end +end + +def fun_l5_n602(x) + if (x < 1) + fun_l6_n561(x) + else + fun_l6_n413(x) + end +end + +def fun_l5_n603(x) + if (x < 1) + fun_l6_n173(x) + else + fun_l6_n324(x) + end +end + +def fun_l5_n604(x) + if (x < 1) + fun_l6_n583(x) + else + fun_l6_n763(x) + end +end + +def fun_l5_n605(x) + if (x < 1) + fun_l6_n200(x) + else + fun_l6_n996(x) + end +end + +def fun_l5_n606(x) + if (x < 1) + fun_l6_n465(x) + else + fun_l6_n777(x) + end +end + +def fun_l5_n607(x) + if (x < 1) + fun_l6_n744(x) + else + fun_l6_n917(x) + end +end + +def fun_l5_n608(x) + if (x < 1) + fun_l6_n825(x) + else + fun_l6_n751(x) + end +end + +def fun_l5_n609(x) + if (x < 1) + fun_l6_n357(x) + else + fun_l6_n889(x) + end +end + +def fun_l5_n610(x) + if (x < 1) + fun_l6_n534(x) + else + fun_l6_n628(x) + end +end + +def fun_l5_n611(x) + if (x < 1) + fun_l6_n242(x) + else + fun_l6_n57(x) + end +end + +def fun_l5_n612(x) + if (x < 1) + fun_l6_n426(x) + else + fun_l6_n295(x) + end +end + +def fun_l5_n613(x) + if (x < 1) + fun_l6_n218(x) + else + fun_l6_n194(x) + end +end + +def fun_l5_n614(x) + if (x < 1) + fun_l6_n618(x) + else + fun_l6_n757(x) + end +end + +def fun_l5_n615(x) + if (x < 1) + fun_l6_n708(x) + else + fun_l6_n187(x) + end +end + +def fun_l5_n616(x) + if (x < 1) + fun_l6_n824(x) + else + fun_l6_n384(x) + end +end + +def fun_l5_n617(x) + if (x < 1) + fun_l6_n149(x) + else + fun_l6_n741(x) + end +end + +def fun_l5_n618(x) + if (x < 1) + fun_l6_n889(x) + else + fun_l6_n768(x) + end +end + +def fun_l5_n619(x) + if (x < 1) + fun_l6_n144(x) + else + fun_l6_n746(x) + end +end + +def fun_l5_n620(x) + if (x < 1) + fun_l6_n338(x) + else + fun_l6_n757(x) + end +end + +def fun_l5_n621(x) + if (x < 1) + fun_l6_n623(x) + else + fun_l6_n432(x) + end +end + +def fun_l5_n622(x) + if (x < 1) + fun_l6_n139(x) + else + fun_l6_n162(x) + end +end + +def fun_l5_n623(x) + if (x < 1) + fun_l6_n371(x) + else + fun_l6_n297(x) + end +end + +def fun_l5_n624(x) + if (x < 1) + fun_l6_n166(x) + else + fun_l6_n172(x) + end +end + +def fun_l5_n625(x) + if (x < 1) + fun_l6_n506(x) + else + fun_l6_n7(x) + end +end + +def fun_l5_n626(x) + if (x < 1) + fun_l6_n334(x) + else + fun_l6_n631(x) + end +end + +def fun_l5_n627(x) + if (x < 1) + fun_l6_n209(x) + else + fun_l6_n316(x) + end +end + +def fun_l5_n628(x) + if (x < 1) + fun_l6_n461(x) + else + fun_l6_n34(x) + end +end + +def fun_l5_n629(x) + if (x < 1) + fun_l6_n6(x) + else + fun_l6_n818(x) + end +end + +def fun_l5_n630(x) + if (x < 1) + fun_l6_n265(x) + else + fun_l6_n111(x) + end +end + +def fun_l5_n631(x) + if (x < 1) + fun_l6_n493(x) + else + fun_l6_n64(x) + end +end + +def fun_l5_n632(x) + if (x < 1) + fun_l6_n513(x) + else + fun_l6_n890(x) + end +end + +def fun_l5_n633(x) + if (x < 1) + fun_l6_n295(x) + else + fun_l6_n295(x) + end +end + +def fun_l5_n634(x) + if (x < 1) + fun_l6_n158(x) + else + fun_l6_n971(x) + end +end + +def fun_l5_n635(x) + if (x < 1) + fun_l6_n171(x) + else + fun_l6_n337(x) + end +end + +def fun_l5_n636(x) + if (x < 1) + fun_l6_n943(x) + else + fun_l6_n502(x) + end +end + +def fun_l5_n637(x) + if (x < 1) + fun_l6_n339(x) + else + fun_l6_n638(x) + end +end + +def fun_l5_n638(x) + if (x < 1) + fun_l6_n155(x) + else + fun_l6_n393(x) + end +end + +def fun_l5_n639(x) + if (x < 1) + fun_l6_n29(x) + else + fun_l6_n506(x) + end +end + +def fun_l5_n640(x) + if (x < 1) + fun_l6_n677(x) + else + fun_l6_n606(x) + end +end + +def fun_l5_n641(x) + if (x < 1) + fun_l6_n306(x) + else + fun_l6_n571(x) + end +end + +def fun_l5_n642(x) + if (x < 1) + fun_l6_n490(x) + else + fun_l6_n281(x) + end +end + +def fun_l5_n643(x) + if (x < 1) + fun_l6_n392(x) + else + fun_l6_n686(x) + end +end + +def fun_l5_n644(x) + if (x < 1) + fun_l6_n257(x) + else + fun_l6_n358(x) + end +end + +def fun_l5_n645(x) + if (x < 1) + fun_l6_n949(x) + else + fun_l6_n15(x) + end +end + +def fun_l5_n646(x) + if (x < 1) + fun_l6_n866(x) + else + fun_l6_n657(x) + end +end + +def fun_l5_n647(x) + if (x < 1) + fun_l6_n624(x) + else + fun_l6_n390(x) + end +end + +def fun_l5_n648(x) + if (x < 1) + fun_l6_n394(x) + else + fun_l6_n951(x) + end +end + +def fun_l5_n649(x) + if (x < 1) + fun_l6_n99(x) + else + fun_l6_n160(x) + end +end + +def fun_l5_n650(x) + if (x < 1) + fun_l6_n84(x) + else + fun_l6_n111(x) + end +end + +def fun_l5_n651(x) + if (x < 1) + fun_l6_n635(x) + else + fun_l6_n507(x) + end +end + +def fun_l5_n652(x) + if (x < 1) + fun_l6_n674(x) + else + fun_l6_n501(x) + end +end + +def fun_l5_n653(x) + if (x < 1) + fun_l6_n171(x) + else + fun_l6_n645(x) + end +end + +def fun_l5_n654(x) + if (x < 1) + fun_l6_n327(x) + else + fun_l6_n152(x) + end +end + +def fun_l5_n655(x) + if (x < 1) + fun_l6_n210(x) + else + fun_l6_n441(x) + end +end + +def fun_l5_n656(x) + if (x < 1) + fun_l6_n691(x) + else + fun_l6_n813(x) + end +end + +def fun_l5_n657(x) + if (x < 1) + fun_l6_n671(x) + else + fun_l6_n683(x) + end +end + +def fun_l5_n658(x) + if (x < 1) + fun_l6_n939(x) + else + fun_l6_n580(x) + end +end + +def fun_l5_n659(x) + if (x < 1) + fun_l6_n152(x) + else + fun_l6_n159(x) + end +end + +def fun_l5_n660(x) + if (x < 1) + fun_l6_n50(x) + else + fun_l6_n911(x) + end +end + +def fun_l5_n661(x) + if (x < 1) + fun_l6_n700(x) + else + fun_l6_n972(x) + end +end + +def fun_l5_n662(x) + if (x < 1) + fun_l6_n22(x) + else + fun_l6_n82(x) + end +end + +def fun_l5_n663(x) + if (x < 1) + fun_l6_n51(x) + else + fun_l6_n827(x) + end +end + +def fun_l5_n664(x) + if (x < 1) + fun_l6_n997(x) + else + fun_l6_n289(x) + end +end + +def fun_l5_n665(x) + if (x < 1) + fun_l6_n666(x) + else + fun_l6_n775(x) + end +end + +def fun_l5_n666(x) + if (x < 1) + fun_l6_n373(x) + else + fun_l6_n175(x) + end +end + +def fun_l5_n667(x) + if (x < 1) + fun_l6_n551(x) + else + fun_l6_n772(x) + end +end + +def fun_l5_n668(x) + if (x < 1) + fun_l6_n107(x) + else + fun_l6_n197(x) + end +end + +def fun_l5_n669(x) + if (x < 1) + fun_l6_n244(x) + else + fun_l6_n968(x) + end +end + +def fun_l5_n670(x) + if (x < 1) + fun_l6_n798(x) + else + fun_l6_n30(x) + end +end + +def fun_l5_n671(x) + if (x < 1) + fun_l6_n48(x) + else + fun_l6_n186(x) + end +end + +def fun_l5_n672(x) + if (x < 1) + fun_l6_n373(x) + else + fun_l6_n937(x) + end +end + +def fun_l5_n673(x) + if (x < 1) + fun_l6_n759(x) + else + fun_l6_n92(x) + end +end + +def fun_l5_n674(x) + if (x < 1) + fun_l6_n380(x) + else + fun_l6_n772(x) + end +end + +def fun_l5_n675(x) + if (x < 1) + fun_l6_n916(x) + else + fun_l6_n329(x) + end +end + +def fun_l5_n676(x) + if (x < 1) + fun_l6_n110(x) + else + fun_l6_n951(x) + end +end + +def fun_l5_n677(x) + if (x < 1) + fun_l6_n363(x) + else + fun_l6_n35(x) + end +end + +def fun_l5_n678(x) + if (x < 1) + fun_l6_n484(x) + else + fun_l6_n492(x) + end +end + +def fun_l5_n679(x) + if (x < 1) + fun_l6_n801(x) + else + fun_l6_n279(x) + end +end + +def fun_l5_n680(x) + if (x < 1) + fun_l6_n499(x) + else + fun_l6_n561(x) + end +end + +def fun_l5_n681(x) + if (x < 1) + fun_l6_n800(x) + else + fun_l6_n890(x) + end +end + +def fun_l5_n682(x) + if (x < 1) + fun_l6_n191(x) + else + fun_l6_n686(x) + end +end + +def fun_l5_n683(x) + if (x < 1) + fun_l6_n318(x) + else + fun_l6_n683(x) + end +end + +def fun_l5_n684(x) + if (x < 1) + fun_l6_n500(x) + else + fun_l6_n914(x) + end +end + +def fun_l5_n685(x) + if (x < 1) + fun_l6_n24(x) + else + fun_l6_n945(x) + end +end + +def fun_l5_n686(x) + if (x < 1) + fun_l6_n602(x) + else + fun_l6_n291(x) + end +end + +def fun_l5_n687(x) + if (x < 1) + fun_l6_n999(x) + else + fun_l6_n86(x) + end +end + +def fun_l5_n688(x) + if (x < 1) + fun_l6_n106(x) + else + fun_l6_n754(x) + end +end + +def fun_l5_n689(x) + if (x < 1) + fun_l6_n452(x) + else + fun_l6_n229(x) + end +end + +def fun_l5_n690(x) + if (x < 1) + fun_l6_n672(x) + else + fun_l6_n587(x) + end +end + +def fun_l5_n691(x) + if (x < 1) + fun_l6_n532(x) + else + fun_l6_n56(x) + end +end + +def fun_l5_n692(x) + if (x < 1) + fun_l6_n606(x) + else + fun_l6_n552(x) + end +end + +def fun_l5_n693(x) + if (x < 1) + fun_l6_n742(x) + else + fun_l6_n862(x) + end +end + +def fun_l5_n694(x) + if (x < 1) + fun_l6_n964(x) + else + fun_l6_n475(x) + end +end + +def fun_l5_n695(x) + if (x < 1) + fun_l6_n179(x) + else + fun_l6_n947(x) + end +end + +def fun_l5_n696(x) + if (x < 1) + fun_l6_n563(x) + else + fun_l6_n329(x) + end +end + +def fun_l5_n697(x) + if (x < 1) + fun_l6_n786(x) + else + fun_l6_n502(x) + end +end + +def fun_l5_n698(x) + if (x < 1) + fun_l6_n178(x) + else + fun_l6_n757(x) + end +end + +def fun_l5_n699(x) + if (x < 1) + fun_l6_n248(x) + else + fun_l6_n288(x) + end +end + +def fun_l5_n700(x) + if (x < 1) + fun_l6_n262(x) + else + fun_l6_n650(x) + end +end + +def fun_l5_n701(x) + if (x < 1) + fun_l6_n90(x) + else + fun_l6_n964(x) + end +end + +def fun_l5_n702(x) + if (x < 1) + fun_l6_n864(x) + else + fun_l6_n743(x) + end +end + +def fun_l5_n703(x) + if (x < 1) + fun_l6_n816(x) + else + fun_l6_n364(x) + end +end + +def fun_l5_n704(x) + if (x < 1) + fun_l6_n590(x) + else + fun_l6_n434(x) + end +end + +def fun_l5_n705(x) + if (x < 1) + fun_l6_n875(x) + else + fun_l6_n539(x) + end +end + +def fun_l5_n706(x) + if (x < 1) + fun_l6_n964(x) + else + fun_l6_n564(x) + end +end + +def fun_l5_n707(x) + if (x < 1) + fun_l6_n315(x) + else + fun_l6_n460(x) + end +end + +def fun_l5_n708(x) + if (x < 1) + fun_l6_n139(x) + else + fun_l6_n210(x) + end +end + +def fun_l5_n709(x) + if (x < 1) + fun_l6_n593(x) + else + fun_l6_n933(x) + end +end + +def fun_l5_n710(x) + if (x < 1) + fun_l6_n37(x) + else + fun_l6_n459(x) + end +end + +def fun_l5_n711(x) + if (x < 1) + fun_l6_n768(x) + else + fun_l6_n256(x) + end +end + +def fun_l5_n712(x) + if (x < 1) + fun_l6_n506(x) + else + fun_l6_n936(x) + end +end + +def fun_l5_n713(x) + if (x < 1) + fun_l6_n971(x) + else + fun_l6_n575(x) + end +end + +def fun_l5_n714(x) + if (x < 1) + fun_l6_n498(x) + else + fun_l6_n932(x) + end +end + +def fun_l5_n715(x) + if (x < 1) + fun_l6_n362(x) + else + fun_l6_n949(x) + end +end + +def fun_l5_n716(x) + if (x < 1) + fun_l6_n706(x) + else + fun_l6_n788(x) + end +end + +def fun_l5_n717(x) + if (x < 1) + fun_l6_n405(x) + else + fun_l6_n803(x) + end +end + +def fun_l5_n718(x) + if (x < 1) + fun_l6_n166(x) + else + fun_l6_n917(x) + end +end + +def fun_l5_n719(x) + if (x < 1) + fun_l6_n899(x) + else + fun_l6_n836(x) + end +end + +def fun_l5_n720(x) + if (x < 1) + fun_l6_n805(x) + else + fun_l6_n159(x) + end +end + +def fun_l5_n721(x) + if (x < 1) + fun_l6_n960(x) + else + fun_l6_n113(x) + end +end + +def fun_l5_n722(x) + if (x < 1) + fun_l6_n807(x) + else + fun_l6_n533(x) + end +end + +def fun_l5_n723(x) + if (x < 1) + fun_l6_n480(x) + else + fun_l6_n907(x) + end +end + +def fun_l5_n724(x) + if (x < 1) + fun_l6_n951(x) + else + fun_l6_n793(x) + end +end + +def fun_l5_n725(x) + if (x < 1) + fun_l6_n951(x) + else + fun_l6_n771(x) + end +end + +def fun_l5_n726(x) + if (x < 1) + fun_l6_n435(x) + else + fun_l6_n336(x) + end +end + +def fun_l5_n727(x) + if (x < 1) + fun_l6_n222(x) + else + fun_l6_n393(x) + end +end + +def fun_l5_n728(x) + if (x < 1) + fun_l6_n988(x) + else + fun_l6_n402(x) + end +end + +def fun_l5_n729(x) + if (x < 1) + fun_l6_n9(x) + else + fun_l6_n46(x) + end +end + +def fun_l5_n730(x) + if (x < 1) + fun_l6_n722(x) + else + fun_l6_n112(x) + end +end + +def fun_l5_n731(x) + if (x < 1) + fun_l6_n543(x) + else + fun_l6_n813(x) + end +end + +def fun_l5_n732(x) + if (x < 1) + fun_l6_n337(x) + else + fun_l6_n245(x) + end +end + +def fun_l5_n733(x) + if (x < 1) + fun_l6_n84(x) + else + fun_l6_n335(x) + end +end + +def fun_l5_n734(x) + if (x < 1) + fun_l6_n697(x) + else + fun_l6_n498(x) + end +end + +def fun_l5_n735(x) + if (x < 1) + fun_l6_n2(x) + else + fun_l6_n895(x) + end +end + +def fun_l5_n736(x) + if (x < 1) + fun_l6_n619(x) + else + fun_l6_n163(x) + end +end + +def fun_l5_n737(x) + if (x < 1) + fun_l6_n237(x) + else + fun_l6_n6(x) + end +end + +def fun_l5_n738(x) + if (x < 1) + fun_l6_n259(x) + else + fun_l6_n95(x) + end +end + +def fun_l5_n739(x) + if (x < 1) + fun_l6_n98(x) + else + fun_l6_n331(x) + end +end + +def fun_l5_n740(x) + if (x < 1) + fun_l6_n489(x) + else + fun_l6_n305(x) + end +end + +def fun_l5_n741(x) + if (x < 1) + fun_l6_n493(x) + else + fun_l6_n525(x) + end +end + +def fun_l5_n742(x) + if (x < 1) + fun_l6_n269(x) + else + fun_l6_n742(x) + end +end + +def fun_l5_n743(x) + if (x < 1) + fun_l6_n194(x) + else + fun_l6_n254(x) + end +end + +def fun_l5_n744(x) + if (x < 1) + fun_l6_n247(x) + else + fun_l6_n909(x) + end +end + +def fun_l5_n745(x) + if (x < 1) + fun_l6_n388(x) + else + fun_l6_n657(x) + end +end + +def fun_l5_n746(x) + if (x < 1) + fun_l6_n27(x) + else + fun_l6_n286(x) + end +end + +def fun_l5_n747(x) + if (x < 1) + fun_l6_n659(x) + else + fun_l6_n895(x) + end +end + +def fun_l5_n748(x) + if (x < 1) + fun_l6_n538(x) + else + fun_l6_n667(x) + end +end + +def fun_l5_n749(x) + if (x < 1) + fun_l6_n208(x) + else + fun_l6_n493(x) + end +end + +def fun_l5_n750(x) + if (x < 1) + fun_l6_n326(x) + else + fun_l6_n570(x) + end +end + +def fun_l5_n751(x) + if (x < 1) + fun_l6_n437(x) + else + fun_l6_n716(x) + end +end + +def fun_l5_n752(x) + if (x < 1) + fun_l6_n957(x) + else + fun_l6_n231(x) + end +end + +def fun_l5_n753(x) + if (x < 1) + fun_l6_n846(x) + else + fun_l6_n900(x) + end +end + +def fun_l5_n754(x) + if (x < 1) + fun_l6_n81(x) + else + fun_l6_n464(x) + end +end + +def fun_l5_n755(x) + if (x < 1) + fun_l6_n735(x) + else + fun_l6_n232(x) + end +end + +def fun_l5_n756(x) + if (x < 1) + fun_l6_n577(x) + else + fun_l6_n804(x) + end +end + +def fun_l5_n757(x) + if (x < 1) + fun_l6_n363(x) + else + fun_l6_n155(x) + end +end + +def fun_l5_n758(x) + if (x < 1) + fun_l6_n534(x) + else + fun_l6_n827(x) + end +end + +def fun_l5_n759(x) + if (x < 1) + fun_l6_n711(x) + else + fun_l6_n53(x) + end +end + +def fun_l5_n760(x) + if (x < 1) + fun_l6_n80(x) + else + fun_l6_n734(x) + end +end + +def fun_l5_n761(x) + if (x < 1) + fun_l6_n811(x) + else + fun_l6_n691(x) + end +end + +def fun_l5_n762(x) + if (x < 1) + fun_l6_n847(x) + else + fun_l6_n570(x) + end +end + +def fun_l5_n763(x) + if (x < 1) + fun_l6_n30(x) + else + fun_l6_n283(x) + end +end + +def fun_l5_n764(x) + if (x < 1) + fun_l6_n270(x) + else + fun_l6_n965(x) + end +end + +def fun_l5_n765(x) + if (x < 1) + fun_l6_n936(x) + else + fun_l6_n772(x) + end +end + +def fun_l5_n766(x) + if (x < 1) + fun_l6_n181(x) + else + fun_l6_n682(x) + end +end + +def fun_l5_n767(x) + if (x < 1) + fun_l6_n327(x) + else + fun_l6_n5(x) + end +end + +def fun_l5_n768(x) + if (x < 1) + fun_l6_n296(x) + else + fun_l6_n940(x) + end +end + +def fun_l5_n769(x) + if (x < 1) + fun_l6_n543(x) + else + fun_l6_n871(x) + end +end + +def fun_l5_n770(x) + if (x < 1) + fun_l6_n670(x) + else + fun_l6_n128(x) + end +end + +def fun_l5_n771(x) + if (x < 1) + fun_l6_n184(x) + else + fun_l6_n794(x) + end +end + +def fun_l5_n772(x) + if (x < 1) + fun_l6_n571(x) + else + fun_l6_n337(x) + end +end + +def fun_l5_n773(x) + if (x < 1) + fun_l6_n674(x) + else + fun_l6_n712(x) + end +end + +def fun_l5_n774(x) + if (x < 1) + fun_l6_n572(x) + else + fun_l6_n944(x) + end +end + +def fun_l5_n775(x) + if (x < 1) + fun_l6_n122(x) + else + fun_l6_n897(x) + end +end + +def fun_l5_n776(x) + if (x < 1) + fun_l6_n461(x) + else + fun_l6_n202(x) + end +end + +def fun_l5_n777(x) + if (x < 1) + fun_l6_n99(x) + else + fun_l6_n256(x) + end +end + +def fun_l5_n778(x) + if (x < 1) + fun_l6_n547(x) + else + fun_l6_n138(x) + end +end + +def fun_l5_n779(x) + if (x < 1) + fun_l6_n56(x) + else + fun_l6_n682(x) + end +end + +def fun_l5_n780(x) + if (x < 1) + fun_l6_n10(x) + else + fun_l6_n238(x) + end +end + +def fun_l5_n781(x) + if (x < 1) + fun_l6_n577(x) + else + fun_l6_n590(x) + end +end + +def fun_l5_n782(x) + if (x < 1) + fun_l6_n415(x) + else + fun_l6_n522(x) + end +end + +def fun_l5_n783(x) + if (x < 1) + fun_l6_n255(x) + else + fun_l6_n182(x) + end +end + +def fun_l5_n784(x) + if (x < 1) + fun_l6_n755(x) + else + fun_l6_n644(x) + end +end + +def fun_l5_n785(x) + if (x < 1) + fun_l6_n39(x) + else + fun_l6_n296(x) + end +end + +def fun_l5_n786(x) + if (x < 1) + fun_l6_n17(x) + else + fun_l6_n811(x) + end +end + +def fun_l5_n787(x) + if (x < 1) + fun_l6_n814(x) + else + fun_l6_n989(x) + end +end + +def fun_l5_n788(x) + if (x < 1) + fun_l6_n791(x) + else + fun_l6_n688(x) + end +end + +def fun_l5_n789(x) + if (x < 1) + fun_l6_n415(x) + else + fun_l6_n218(x) + end +end + +def fun_l5_n790(x) + if (x < 1) + fun_l6_n227(x) + else + fun_l6_n391(x) + end +end + +def fun_l5_n791(x) + if (x < 1) + fun_l6_n232(x) + else + fun_l6_n644(x) + end +end + +def fun_l5_n792(x) + if (x < 1) + fun_l6_n325(x) + else + fun_l6_n740(x) + end +end + +def fun_l5_n793(x) + if (x < 1) + fun_l6_n926(x) + else + fun_l6_n133(x) + end +end + +def fun_l5_n794(x) + if (x < 1) + fun_l6_n114(x) + else + fun_l6_n76(x) + end +end + +def fun_l5_n795(x) + if (x < 1) + fun_l6_n332(x) + else + fun_l6_n198(x) + end +end + +def fun_l5_n796(x) + if (x < 1) + fun_l6_n584(x) + else + fun_l6_n298(x) + end +end + +def fun_l5_n797(x) + if (x < 1) + fun_l6_n966(x) + else + fun_l6_n956(x) + end +end + +def fun_l5_n798(x) + if (x < 1) + fun_l6_n604(x) + else + fun_l6_n311(x) + end +end + +def fun_l5_n799(x) + if (x < 1) + fun_l6_n444(x) + else + fun_l6_n934(x) + end +end + +def fun_l5_n800(x) + if (x < 1) + fun_l6_n805(x) + else + fun_l6_n83(x) + end +end + +def fun_l5_n801(x) + if (x < 1) + fun_l6_n996(x) + else + fun_l6_n282(x) + end +end + +def fun_l5_n802(x) + if (x < 1) + fun_l6_n759(x) + else + fun_l6_n681(x) + end +end + +def fun_l5_n803(x) + if (x < 1) + fun_l6_n480(x) + else + fun_l6_n536(x) + end +end + +def fun_l5_n804(x) + if (x < 1) + fun_l6_n536(x) + else + fun_l6_n64(x) + end +end + +def fun_l5_n805(x) + if (x < 1) + fun_l6_n992(x) + else + fun_l6_n116(x) + end +end + +def fun_l5_n806(x) + if (x < 1) + fun_l6_n446(x) + else + fun_l6_n553(x) + end +end + +def fun_l5_n807(x) + if (x < 1) + fun_l6_n822(x) + else + fun_l6_n80(x) + end +end + +def fun_l5_n808(x) + if (x < 1) + fun_l6_n912(x) + else + fun_l6_n525(x) + end +end + +def fun_l5_n809(x) + if (x < 1) + fun_l6_n824(x) + else + fun_l6_n356(x) + end +end + +def fun_l5_n810(x) + if (x < 1) + fun_l6_n144(x) + else + fun_l6_n193(x) + end +end + +def fun_l5_n811(x) + if (x < 1) + fun_l6_n27(x) + else + fun_l6_n810(x) + end +end + +def fun_l5_n812(x) + if (x < 1) + fun_l6_n244(x) + else + fun_l6_n696(x) + end +end + +def fun_l5_n813(x) + if (x < 1) + fun_l6_n408(x) + else + fun_l6_n46(x) + end +end + +def fun_l5_n814(x) + if (x < 1) + fun_l6_n496(x) + else + fun_l6_n149(x) + end +end + +def fun_l5_n815(x) + if (x < 1) + fun_l6_n100(x) + else + fun_l6_n765(x) + end +end + +def fun_l5_n816(x) + if (x < 1) + fun_l6_n731(x) + else + fun_l6_n953(x) + end +end + +def fun_l5_n817(x) + if (x < 1) + fun_l6_n997(x) + else + fun_l6_n849(x) + end +end + +def fun_l5_n818(x) + if (x < 1) + fun_l6_n570(x) + else + fun_l6_n918(x) + end +end + +def fun_l5_n819(x) + if (x < 1) + fun_l6_n473(x) + else + fun_l6_n955(x) + end +end + +def fun_l5_n820(x) + if (x < 1) + fun_l6_n691(x) + else + fun_l6_n271(x) + end +end + +def fun_l5_n821(x) + if (x < 1) + fun_l6_n935(x) + else + fun_l6_n386(x) + end +end + +def fun_l5_n822(x) + if (x < 1) + fun_l6_n210(x) + else + fun_l6_n871(x) + end +end + +def fun_l5_n823(x) + if (x < 1) + fun_l6_n907(x) + else + fun_l6_n596(x) + end +end + +def fun_l5_n824(x) + if (x < 1) + fun_l6_n701(x) + else + fun_l6_n541(x) + end +end + +def fun_l5_n825(x) + if (x < 1) + fun_l6_n477(x) + else + fun_l6_n207(x) + end +end + +def fun_l5_n826(x) + if (x < 1) + fun_l6_n95(x) + else + fun_l6_n26(x) + end +end + +def fun_l5_n827(x) + if (x < 1) + fun_l6_n908(x) + else + fun_l6_n369(x) + end +end + +def fun_l5_n828(x) + if (x < 1) + fun_l6_n213(x) + else + fun_l6_n607(x) + end +end + +def fun_l5_n829(x) + if (x < 1) + fun_l6_n763(x) + else + fun_l6_n753(x) + end +end + +def fun_l5_n830(x) + if (x < 1) + fun_l6_n24(x) + else + fun_l6_n157(x) + end +end + +def fun_l5_n831(x) + if (x < 1) + fun_l6_n262(x) + else + fun_l6_n826(x) + end +end + +def fun_l5_n832(x) + if (x < 1) + fun_l6_n743(x) + else + fun_l6_n37(x) + end +end + +def fun_l5_n833(x) + if (x < 1) + fun_l6_n532(x) + else + fun_l6_n31(x) + end +end + +def fun_l5_n834(x) + if (x < 1) + fun_l6_n309(x) + else + fun_l6_n454(x) + end +end + +def fun_l5_n835(x) + if (x < 1) + fun_l6_n917(x) + else + fun_l6_n721(x) + end +end + +def fun_l5_n836(x) + if (x < 1) + fun_l6_n376(x) + else + fun_l6_n758(x) + end +end + +def fun_l5_n837(x) + if (x < 1) + fun_l6_n558(x) + else + fun_l6_n474(x) + end +end + +def fun_l5_n838(x) + if (x < 1) + fun_l6_n436(x) + else + fun_l6_n675(x) + end +end + +def fun_l5_n839(x) + if (x < 1) + fun_l6_n720(x) + else + fun_l6_n12(x) + end +end + +def fun_l5_n840(x) + if (x < 1) + fun_l6_n957(x) + else + fun_l6_n200(x) + end +end + +def fun_l5_n841(x) + if (x < 1) + fun_l6_n180(x) + else + fun_l6_n644(x) + end +end + +def fun_l5_n842(x) + if (x < 1) + fun_l6_n510(x) + else + fun_l6_n73(x) + end +end + +def fun_l5_n843(x) + if (x < 1) + fun_l6_n812(x) + else + fun_l6_n954(x) + end +end + +def fun_l5_n844(x) + if (x < 1) + fun_l6_n566(x) + else + fun_l6_n866(x) + end +end + +def fun_l5_n845(x) + if (x < 1) + fun_l6_n641(x) + else + fun_l6_n11(x) + end +end + +def fun_l5_n846(x) + if (x < 1) + fun_l6_n607(x) + else + fun_l6_n884(x) + end +end + +def fun_l5_n847(x) + if (x < 1) + fun_l6_n479(x) + else + fun_l6_n564(x) + end +end + +def fun_l5_n848(x) + if (x < 1) + fun_l6_n365(x) + else + fun_l6_n285(x) + end +end + +def fun_l5_n849(x) + if (x < 1) + fun_l6_n296(x) + else + fun_l6_n708(x) + end +end + +def fun_l5_n850(x) + if (x < 1) + fun_l6_n429(x) + else + fun_l6_n758(x) + end +end + +def fun_l5_n851(x) + if (x < 1) + fun_l6_n881(x) + else + fun_l6_n848(x) + end +end + +def fun_l5_n852(x) + if (x < 1) + fun_l6_n257(x) + else + fun_l6_n51(x) + end +end + +def fun_l5_n853(x) + if (x < 1) + fun_l6_n441(x) + else + fun_l6_n445(x) + end +end + +def fun_l5_n854(x) + if (x < 1) + fun_l6_n80(x) + else + fun_l6_n767(x) + end +end + +def fun_l5_n855(x) + if (x < 1) + fun_l6_n196(x) + else + fun_l6_n41(x) + end +end + +def fun_l5_n856(x) + if (x < 1) + fun_l6_n548(x) + else + fun_l6_n860(x) + end +end + +def fun_l5_n857(x) + if (x < 1) + fun_l6_n380(x) + else + fun_l6_n601(x) + end +end + +def fun_l5_n858(x) + if (x < 1) + fun_l6_n272(x) + else + fun_l6_n376(x) + end +end + +def fun_l5_n859(x) + if (x < 1) + fun_l6_n179(x) + else + fun_l6_n978(x) + end +end + +def fun_l5_n860(x) + if (x < 1) + fun_l6_n52(x) + else + fun_l6_n827(x) + end +end + +def fun_l5_n861(x) + if (x < 1) + fun_l6_n611(x) + else + fun_l6_n929(x) + end +end + +def fun_l5_n862(x) + if (x < 1) + fun_l6_n179(x) + else + fun_l6_n171(x) + end +end + +def fun_l5_n863(x) + if (x < 1) + fun_l6_n611(x) + else + fun_l6_n663(x) + end +end + +def fun_l5_n864(x) + if (x < 1) + fun_l6_n539(x) + else + fun_l6_n356(x) + end +end + +def fun_l5_n865(x) + if (x < 1) + fun_l6_n401(x) + else + fun_l6_n302(x) + end +end + +def fun_l5_n866(x) + if (x < 1) + fun_l6_n94(x) + else + fun_l6_n761(x) + end +end + +def fun_l5_n867(x) + if (x < 1) + fun_l6_n818(x) + else + fun_l6_n500(x) + end +end + +def fun_l5_n868(x) + if (x < 1) + fun_l6_n956(x) + else + fun_l6_n661(x) + end +end + +def fun_l5_n869(x) + if (x < 1) + fun_l6_n628(x) + else + fun_l6_n765(x) + end +end + +def fun_l5_n870(x) + if (x < 1) + fun_l6_n654(x) + else + fun_l6_n181(x) + end +end + +def fun_l5_n871(x) + if (x < 1) + fun_l6_n70(x) + else + fun_l6_n157(x) + end +end + +def fun_l5_n872(x) + if (x < 1) + fun_l6_n133(x) + else + fun_l6_n806(x) + end +end + +def fun_l5_n873(x) + if (x < 1) + fun_l6_n100(x) + else + fun_l6_n479(x) + end +end + +def fun_l5_n874(x) + if (x < 1) + fun_l6_n401(x) + else + fun_l6_n567(x) + end +end + +def fun_l5_n875(x) + if (x < 1) + fun_l6_n399(x) + else + fun_l6_n369(x) + end +end + +def fun_l5_n876(x) + if (x < 1) + fun_l6_n412(x) + else + fun_l6_n763(x) + end +end + +def fun_l5_n877(x) + if (x < 1) + fun_l6_n498(x) + else + fun_l6_n192(x) + end +end + +def fun_l5_n878(x) + if (x < 1) + fun_l6_n798(x) + else + fun_l6_n473(x) + end +end + +def fun_l5_n879(x) + if (x < 1) + fun_l6_n166(x) + else + fun_l6_n301(x) + end +end + +def fun_l5_n880(x) + if (x < 1) + fun_l6_n616(x) + else + fun_l6_n28(x) + end +end + +def fun_l5_n881(x) + if (x < 1) + fun_l6_n315(x) + else + fun_l6_n92(x) + end +end + +def fun_l5_n882(x) + if (x < 1) + fun_l6_n548(x) + else + fun_l6_n41(x) + end +end + +def fun_l5_n883(x) + if (x < 1) + fun_l6_n279(x) + else + fun_l6_n72(x) + end +end + +def fun_l5_n884(x) + if (x < 1) + fun_l6_n206(x) + else + fun_l6_n384(x) + end +end + +def fun_l5_n885(x) + if (x < 1) + fun_l6_n191(x) + else + fun_l6_n84(x) + end +end + +def fun_l5_n886(x) + if (x < 1) + fun_l6_n960(x) + else + fun_l6_n495(x) + end +end + +def fun_l5_n887(x) + if (x < 1) + fun_l6_n459(x) + else + fun_l6_n757(x) + end +end + +def fun_l5_n888(x) + if (x < 1) + fun_l6_n634(x) + else + fun_l6_n463(x) + end +end + +def fun_l5_n889(x) + if (x < 1) + fun_l6_n611(x) + else + fun_l6_n469(x) + end +end + +def fun_l5_n890(x) + if (x < 1) + fun_l6_n787(x) + else + fun_l6_n707(x) + end +end + +def fun_l5_n891(x) + if (x < 1) + fun_l6_n201(x) + else + fun_l6_n223(x) + end +end + +def fun_l5_n892(x) + if (x < 1) + fun_l6_n214(x) + else + fun_l6_n303(x) + end +end + +def fun_l5_n893(x) + if (x < 1) + fun_l6_n85(x) + else + fun_l6_n802(x) + end +end + +def fun_l5_n894(x) + if (x < 1) + fun_l6_n816(x) + else + fun_l6_n325(x) + end +end + +def fun_l5_n895(x) + if (x < 1) + fun_l6_n491(x) + else + fun_l6_n907(x) + end +end + +def fun_l5_n896(x) + if (x < 1) + fun_l6_n809(x) + else + fun_l6_n364(x) + end +end + +def fun_l5_n897(x) + if (x < 1) + fun_l6_n739(x) + else + fun_l6_n192(x) + end +end + +def fun_l5_n898(x) + if (x < 1) + fun_l6_n461(x) + else + fun_l6_n594(x) + end +end + +def fun_l5_n899(x) + if (x < 1) + fun_l6_n256(x) + else + fun_l6_n521(x) + end +end + +def fun_l5_n900(x) + if (x < 1) + fun_l6_n6(x) + else + fun_l6_n127(x) + end +end + +def fun_l5_n901(x) + if (x < 1) + fun_l6_n655(x) + else + fun_l6_n426(x) + end +end + +def fun_l5_n902(x) + if (x < 1) + fun_l6_n936(x) + else + fun_l6_n275(x) + end +end + +def fun_l5_n903(x) + if (x < 1) + fun_l6_n738(x) + else + fun_l6_n654(x) + end +end + +def fun_l5_n904(x) + if (x < 1) + fun_l6_n583(x) + else + fun_l6_n600(x) + end +end + +def fun_l5_n905(x) + if (x < 1) + fun_l6_n228(x) + else + fun_l6_n591(x) + end +end + +def fun_l5_n906(x) + if (x < 1) + fun_l6_n292(x) + else + fun_l6_n55(x) + end +end + +def fun_l5_n907(x) + if (x < 1) + fun_l6_n457(x) + else + fun_l6_n513(x) + end +end + +def fun_l5_n908(x) + if (x < 1) + fun_l6_n542(x) + else + fun_l6_n593(x) + end +end + +def fun_l5_n909(x) + if (x < 1) + fun_l6_n478(x) + else + fun_l6_n782(x) + end +end + +def fun_l5_n910(x) + if (x < 1) + fun_l6_n780(x) + else + fun_l6_n275(x) + end +end + +def fun_l5_n911(x) + if (x < 1) + fun_l6_n631(x) + else + fun_l6_n811(x) + end +end + +def fun_l5_n912(x) + if (x < 1) + fun_l6_n17(x) + else + fun_l6_n837(x) + end +end + +def fun_l5_n913(x) + if (x < 1) + fun_l6_n607(x) + else + fun_l6_n159(x) + end +end + +def fun_l5_n914(x) + if (x < 1) + fun_l6_n23(x) + else + fun_l6_n70(x) + end +end + +def fun_l5_n915(x) + if (x < 1) + fun_l6_n778(x) + else + fun_l6_n643(x) + end +end + +def fun_l5_n916(x) + if (x < 1) + fun_l6_n707(x) + else + fun_l6_n121(x) + end +end + +def fun_l5_n917(x) + if (x < 1) + fun_l6_n816(x) + else + fun_l6_n67(x) + end +end + +def fun_l5_n918(x) + if (x < 1) + fun_l6_n963(x) + else + fun_l6_n520(x) + end +end + +def fun_l5_n919(x) + if (x < 1) + fun_l6_n251(x) + else + fun_l6_n111(x) + end +end + +def fun_l5_n920(x) + if (x < 1) + fun_l6_n198(x) + else + fun_l6_n872(x) + end +end + +def fun_l5_n921(x) + if (x < 1) + fun_l6_n364(x) + else + fun_l6_n369(x) + end +end + +def fun_l5_n922(x) + if (x < 1) + fun_l6_n7(x) + else + fun_l6_n314(x) + end +end + +def fun_l5_n923(x) + if (x < 1) + fun_l6_n578(x) + else + fun_l6_n502(x) + end +end + +def fun_l5_n924(x) + if (x < 1) + fun_l6_n450(x) + else + fun_l6_n680(x) + end +end + +def fun_l5_n925(x) + if (x < 1) + fun_l6_n469(x) + else + fun_l6_n973(x) + end +end + +def fun_l5_n926(x) + if (x < 1) + fun_l6_n114(x) + else + fun_l6_n862(x) + end +end + +def fun_l5_n927(x) + if (x < 1) + fun_l6_n786(x) + else + fun_l6_n861(x) + end +end + +def fun_l5_n928(x) + if (x < 1) + fun_l6_n40(x) + else + fun_l6_n665(x) + end +end + +def fun_l5_n929(x) + if (x < 1) + fun_l6_n997(x) + else + fun_l6_n137(x) + end +end + +def fun_l5_n930(x) + if (x < 1) + fun_l6_n547(x) + else + fun_l6_n547(x) + end +end + +def fun_l5_n931(x) + if (x < 1) + fun_l6_n310(x) + else + fun_l6_n986(x) + end +end + +def fun_l5_n932(x) + if (x < 1) + fun_l6_n339(x) + else + fun_l6_n18(x) + end +end + +def fun_l5_n933(x) + if (x < 1) + fun_l6_n825(x) + else + fun_l6_n418(x) + end +end + +def fun_l5_n934(x) + if (x < 1) + fun_l6_n509(x) + else + fun_l6_n589(x) + end +end + +def fun_l5_n935(x) + if (x < 1) + fun_l6_n936(x) + else + fun_l6_n113(x) + end +end + +def fun_l5_n936(x) + if (x < 1) + fun_l6_n530(x) + else + fun_l6_n841(x) + end +end + +def fun_l5_n937(x) + if (x < 1) + fun_l6_n431(x) + else + fun_l6_n531(x) + end +end + +def fun_l5_n938(x) + if (x < 1) + fun_l6_n791(x) + else + fun_l6_n41(x) + end +end + +def fun_l5_n939(x) + if (x < 1) + fun_l6_n873(x) + else + fun_l6_n336(x) + end +end + +def fun_l5_n940(x) + if (x < 1) + fun_l6_n925(x) + else + fun_l6_n746(x) + end +end + +def fun_l5_n941(x) + if (x < 1) + fun_l6_n995(x) + else + fun_l6_n29(x) + end +end + +def fun_l5_n942(x) + if (x < 1) + fun_l6_n984(x) + else + fun_l6_n455(x) + end +end + +def fun_l5_n943(x) + if (x < 1) + fun_l6_n660(x) + else + fun_l6_n934(x) + end +end + +def fun_l5_n944(x) + if (x < 1) + fun_l6_n625(x) + else + fun_l6_n523(x) + end +end + +def fun_l5_n945(x) + if (x < 1) + fun_l6_n407(x) + else + fun_l6_n766(x) + end +end + +def fun_l5_n946(x) + if (x < 1) + fun_l6_n80(x) + else + fun_l6_n75(x) + end +end + +def fun_l5_n947(x) + if (x < 1) + fun_l6_n465(x) + else + fun_l6_n57(x) + end +end + +def fun_l5_n948(x) + if (x < 1) + fun_l6_n750(x) + else + fun_l6_n278(x) + end +end + +def fun_l5_n949(x) + if (x < 1) + fun_l6_n917(x) + else + fun_l6_n472(x) + end +end + +def fun_l5_n950(x) + if (x < 1) + fun_l6_n917(x) + else + fun_l6_n71(x) + end +end + +def fun_l5_n951(x) + if (x < 1) + fun_l6_n420(x) + else + fun_l6_n132(x) + end +end + +def fun_l5_n952(x) + if (x < 1) + fun_l6_n112(x) + else + fun_l6_n396(x) + end +end + +def fun_l5_n953(x) + if (x < 1) + fun_l6_n705(x) + else + fun_l6_n978(x) + end +end + +def fun_l5_n954(x) + if (x < 1) + fun_l6_n761(x) + else + fun_l6_n136(x) + end +end + +def fun_l5_n955(x) + if (x < 1) + fun_l6_n518(x) + else + fun_l6_n687(x) + end +end + +def fun_l5_n956(x) + if (x < 1) + fun_l6_n308(x) + else + fun_l6_n34(x) + end +end + +def fun_l5_n957(x) + if (x < 1) + fun_l6_n904(x) + else + fun_l6_n129(x) + end +end + +def fun_l5_n958(x) + if (x < 1) + fun_l6_n271(x) + else + fun_l6_n444(x) + end +end + +def fun_l5_n959(x) + if (x < 1) + fun_l6_n690(x) + else + fun_l6_n118(x) + end +end + +def fun_l5_n960(x) + if (x < 1) + fun_l6_n509(x) + else + fun_l6_n957(x) + end +end + +def fun_l5_n961(x) + if (x < 1) + fun_l6_n889(x) + else + fun_l6_n26(x) + end +end + +def fun_l5_n962(x) + if (x < 1) + fun_l6_n802(x) + else + fun_l6_n364(x) + end +end + +def fun_l5_n963(x) + if (x < 1) + fun_l6_n368(x) + else + fun_l6_n580(x) + end +end + +def fun_l5_n964(x) + if (x < 1) + fun_l6_n879(x) + else + fun_l6_n925(x) + end +end + +def fun_l5_n965(x) + if (x < 1) + fun_l6_n114(x) + else + fun_l6_n882(x) + end +end + +def fun_l5_n966(x) + if (x < 1) + fun_l6_n9(x) + else + fun_l6_n5(x) + end +end + +def fun_l5_n967(x) + if (x < 1) + fun_l6_n536(x) + else + fun_l6_n251(x) + end +end + +def fun_l5_n968(x) + if (x < 1) + fun_l6_n804(x) + else + fun_l6_n179(x) + end +end + +def fun_l5_n969(x) + if (x < 1) + fun_l6_n469(x) + else + fun_l6_n235(x) + end +end + +def fun_l5_n970(x) + if (x < 1) + fun_l6_n328(x) + else + fun_l6_n763(x) + end +end + +def fun_l5_n971(x) + if (x < 1) + fun_l6_n342(x) + else + fun_l6_n126(x) + end +end + +def fun_l5_n972(x) + if (x < 1) + fun_l6_n901(x) + else + fun_l6_n674(x) + end +end + +def fun_l5_n973(x) + if (x < 1) + fun_l6_n853(x) + else + fun_l6_n714(x) + end +end + +def fun_l5_n974(x) + if (x < 1) + fun_l6_n670(x) + else + fun_l6_n905(x) + end +end + +def fun_l5_n975(x) + if (x < 1) + fun_l6_n873(x) + else + fun_l6_n193(x) + end +end + +def fun_l5_n976(x) + if (x < 1) + fun_l6_n603(x) + else + fun_l6_n186(x) + end +end + +def fun_l5_n977(x) + if (x < 1) + fun_l6_n474(x) + else + fun_l6_n108(x) + end +end + +def fun_l5_n978(x) + if (x < 1) + fun_l6_n347(x) + else + fun_l6_n872(x) + end +end + +def fun_l5_n979(x) + if (x < 1) + fun_l6_n593(x) + else + fun_l6_n575(x) + end +end + +def fun_l5_n980(x) + if (x < 1) + fun_l6_n692(x) + else + fun_l6_n262(x) + end +end + +def fun_l5_n981(x) + if (x < 1) + fun_l6_n226(x) + else + fun_l6_n600(x) + end +end + +def fun_l5_n982(x) + if (x < 1) + fun_l6_n357(x) + else + fun_l6_n165(x) + end +end + +def fun_l5_n983(x) + if (x < 1) + fun_l6_n784(x) + else + fun_l6_n584(x) + end +end + +def fun_l5_n984(x) + if (x < 1) + fun_l6_n339(x) + else + fun_l6_n754(x) + end +end + +def fun_l5_n985(x) + if (x < 1) + fun_l6_n536(x) + else + fun_l6_n663(x) + end +end + +def fun_l5_n986(x) + if (x < 1) + fun_l6_n239(x) + else + fun_l6_n723(x) + end +end + +def fun_l5_n987(x) + if (x < 1) + fun_l6_n928(x) + else + fun_l6_n403(x) + end +end + +def fun_l5_n988(x) + if (x < 1) + fun_l6_n328(x) + else + fun_l6_n551(x) + end +end + +def fun_l5_n989(x) + if (x < 1) + fun_l6_n847(x) + else + fun_l6_n475(x) + end +end + +def fun_l5_n990(x) + if (x < 1) + fun_l6_n405(x) + else + fun_l6_n39(x) + end +end + +def fun_l5_n991(x) + if (x < 1) + fun_l6_n705(x) + else + fun_l6_n281(x) + end +end + +def fun_l5_n992(x) + if (x < 1) + fun_l6_n59(x) + else + fun_l6_n465(x) + end +end + +def fun_l5_n993(x) + if (x < 1) + fun_l6_n828(x) + else + fun_l6_n705(x) + end +end + +def fun_l5_n994(x) + if (x < 1) + fun_l6_n687(x) + else + fun_l6_n451(x) + end +end + +def fun_l5_n995(x) + if (x < 1) + fun_l6_n600(x) + else + fun_l6_n9(x) + end +end + +def fun_l5_n996(x) + if (x < 1) + fun_l6_n205(x) + else + fun_l6_n242(x) + end +end + +def fun_l5_n997(x) + if (x < 1) + fun_l6_n438(x) + else + fun_l6_n108(x) + end +end + +def fun_l5_n998(x) + if (x < 1) + fun_l6_n164(x) + else + fun_l6_n302(x) + end +end + +def fun_l5_n999(x) + if (x < 1) + fun_l6_n533(x) + else + fun_l6_n685(x) + end +end + +def fun_l6_n0(x) + if (x < 1) + fun_l7_n74(x) + else + fun_l7_n45(x) + end +end + +def fun_l6_n1(x) + if (x < 1) + fun_l7_n685(x) + else + fun_l7_n163(x) + end +end + +def fun_l6_n2(x) + if (x < 1) + fun_l7_n325(x) + else + fun_l7_n365(x) + end +end + +def fun_l6_n3(x) + if (x < 1) + fun_l7_n855(x) + else + fun_l7_n359(x) + end +end + +def fun_l6_n4(x) + if (x < 1) + fun_l7_n939(x) + else + fun_l7_n690(x) + end +end + +def fun_l6_n5(x) + if (x < 1) + fun_l7_n689(x) + else + fun_l7_n681(x) + end +end + +def fun_l6_n6(x) + if (x < 1) + fun_l7_n226(x) + else + fun_l7_n307(x) + end +end + +def fun_l6_n7(x) + if (x < 1) + fun_l7_n779(x) + else + fun_l7_n765(x) + end +end + +def fun_l6_n8(x) + if (x < 1) + fun_l7_n85(x) + else + fun_l7_n967(x) + end +end + +def fun_l6_n9(x) + if (x < 1) + fun_l7_n539(x) + else + fun_l7_n5(x) + end +end + +def fun_l6_n10(x) + if (x < 1) + fun_l7_n503(x) + else + fun_l7_n163(x) + end +end + +def fun_l6_n11(x) + if (x < 1) + fun_l7_n24(x) + else + fun_l7_n374(x) + end +end + +def fun_l6_n12(x) + if (x < 1) + fun_l7_n633(x) + else + fun_l7_n395(x) + end +end + +def fun_l6_n13(x) + if (x < 1) + fun_l7_n250(x) + else + fun_l7_n7(x) + end +end + +def fun_l6_n14(x) + if (x < 1) + fun_l7_n22(x) + else + fun_l7_n560(x) + end +end + +def fun_l6_n15(x) + if (x < 1) + fun_l7_n209(x) + else + fun_l7_n323(x) + end +end + +def fun_l6_n16(x) + if (x < 1) + fun_l7_n770(x) + else + fun_l7_n155(x) + end +end + +def fun_l6_n17(x) + if (x < 1) + fun_l7_n976(x) + else + fun_l7_n712(x) + end +end + +def fun_l6_n18(x) + if (x < 1) + fun_l7_n762(x) + else + fun_l7_n307(x) + end +end + +def fun_l6_n19(x) + if (x < 1) + fun_l7_n911(x) + else + fun_l7_n788(x) + end +end + +def fun_l6_n20(x) + if (x < 1) + fun_l7_n40(x) + else + fun_l7_n269(x) + end +end + +def fun_l6_n21(x) + if (x < 1) + fun_l7_n707(x) + else + fun_l7_n861(x) + end +end + +def fun_l6_n22(x) + if (x < 1) + fun_l7_n591(x) + else + fun_l7_n557(x) + end +end + +def fun_l6_n23(x) + if (x < 1) + fun_l7_n890(x) + else + fun_l7_n142(x) + end +end + +def fun_l6_n24(x) + if (x < 1) + fun_l7_n563(x) + else + fun_l7_n509(x) + end +end + +def fun_l6_n25(x) + if (x < 1) + fun_l7_n630(x) + else + fun_l7_n784(x) + end +end + +def fun_l6_n26(x) + if (x < 1) + fun_l7_n30(x) + else + fun_l7_n826(x) + end +end + +def fun_l6_n27(x) + if (x < 1) + fun_l7_n223(x) + else + fun_l7_n800(x) + end +end + +def fun_l6_n28(x) + if (x < 1) + fun_l7_n51(x) + else + fun_l7_n963(x) + end +end + +def fun_l6_n29(x) + if (x < 1) + fun_l7_n603(x) + else + fun_l7_n988(x) + end +end + +def fun_l6_n30(x) + if (x < 1) + fun_l7_n258(x) + else + fun_l7_n512(x) + end +end + +def fun_l6_n31(x) + if (x < 1) + fun_l7_n649(x) + else + fun_l7_n772(x) + end +end + +def fun_l6_n32(x) + if (x < 1) + fun_l7_n999(x) + else + fun_l7_n592(x) + end +end + +def fun_l6_n33(x) + if (x < 1) + fun_l7_n371(x) + else + fun_l7_n801(x) + end +end + +def fun_l6_n34(x) + if (x < 1) + fun_l7_n905(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n35(x) + if (x < 1) + fun_l7_n142(x) + else + fun_l7_n933(x) + end +end + +def fun_l6_n36(x) + if (x < 1) + fun_l7_n987(x) + else + fun_l7_n305(x) + end +end + +def fun_l6_n37(x) + if (x < 1) + fun_l7_n360(x) + else + fun_l7_n266(x) + end +end + +def fun_l6_n38(x) + if (x < 1) + fun_l7_n799(x) + else + fun_l7_n938(x) + end +end + +def fun_l6_n39(x) + if (x < 1) + fun_l7_n921(x) + else + fun_l7_n739(x) + end +end + +def fun_l6_n40(x) + if (x < 1) + fun_l7_n553(x) + else + fun_l7_n236(x) + end +end + +def fun_l6_n41(x) + if (x < 1) + fun_l7_n592(x) + else + fun_l7_n335(x) + end +end + +def fun_l6_n42(x) + if (x < 1) + fun_l7_n33(x) + else + fun_l7_n521(x) + end +end + +def fun_l6_n43(x) + if (x < 1) + fun_l7_n278(x) + else + fun_l7_n866(x) + end +end + +def fun_l6_n44(x) + if (x < 1) + fun_l7_n808(x) + else + fun_l7_n394(x) + end +end + +def fun_l6_n45(x) + if (x < 1) + fun_l7_n556(x) + else + fun_l7_n462(x) + end +end + +def fun_l6_n46(x) + if (x < 1) + fun_l7_n72(x) + else + fun_l7_n558(x) + end +end + +def fun_l6_n47(x) + if (x < 1) + fun_l7_n583(x) + else + fun_l7_n472(x) + end +end + +def fun_l6_n48(x) + if (x < 1) + fun_l7_n577(x) + else + fun_l7_n264(x) + end +end + +def fun_l6_n49(x) + if (x < 1) + fun_l7_n167(x) + else + fun_l7_n570(x) + end +end + +def fun_l6_n50(x) + if (x < 1) + fun_l7_n707(x) + else + fun_l7_n127(x) + end +end + +def fun_l6_n51(x) + if (x < 1) + fun_l7_n151(x) + else + fun_l7_n82(x) + end +end + +def fun_l6_n52(x) + if (x < 1) + fun_l7_n729(x) + else + fun_l7_n785(x) + end +end + +def fun_l6_n53(x) + if (x < 1) + fun_l7_n236(x) + else + fun_l7_n84(x) + end +end + +def fun_l6_n54(x) + if (x < 1) + fun_l7_n573(x) + else + fun_l7_n92(x) + end +end + +def fun_l6_n55(x) + if (x < 1) + fun_l7_n601(x) + else + fun_l7_n531(x) + end +end + +def fun_l6_n56(x) + if (x < 1) + fun_l7_n623(x) + else + fun_l7_n522(x) + end +end + +def fun_l6_n57(x) + if (x < 1) + fun_l7_n707(x) + else + fun_l7_n830(x) + end +end + +def fun_l6_n58(x) + if (x < 1) + fun_l7_n240(x) + else + fun_l7_n868(x) + end +end + +def fun_l6_n59(x) + if (x < 1) + fun_l7_n233(x) + else + fun_l7_n595(x) + end +end + +def fun_l6_n60(x) + if (x < 1) + fun_l7_n384(x) + else + fun_l7_n605(x) + end +end + +def fun_l6_n61(x) + if (x < 1) + fun_l7_n721(x) + else + fun_l7_n509(x) + end +end + +def fun_l6_n62(x) + if (x < 1) + fun_l7_n741(x) + else + fun_l7_n934(x) + end +end + +def fun_l6_n63(x) + if (x < 1) + fun_l7_n724(x) + else + fun_l7_n963(x) + end +end + +def fun_l6_n64(x) + if (x < 1) + fun_l7_n144(x) + else + fun_l7_n417(x) + end +end + +def fun_l6_n65(x) + if (x < 1) + fun_l7_n618(x) + else + fun_l7_n19(x) + end +end + +def fun_l6_n66(x) + if (x < 1) + fun_l7_n128(x) + else + fun_l7_n257(x) + end +end + +def fun_l6_n67(x) + if (x < 1) + fun_l7_n623(x) + else + fun_l7_n182(x) + end +end + +def fun_l6_n68(x) + if (x < 1) + fun_l7_n256(x) + else + fun_l7_n692(x) + end +end + +def fun_l6_n69(x) + if (x < 1) + fun_l7_n360(x) + else + fun_l7_n34(x) + end +end + +def fun_l6_n70(x) + if (x < 1) + fun_l7_n690(x) + else + fun_l7_n813(x) + end +end + +def fun_l6_n71(x) + if (x < 1) + fun_l7_n533(x) + else + fun_l7_n94(x) + end +end + +def fun_l6_n72(x) + if (x < 1) + fun_l7_n245(x) + else + fun_l7_n548(x) + end +end + +def fun_l6_n73(x) + if (x < 1) + fun_l7_n919(x) + else + fun_l7_n295(x) + end +end + +def fun_l6_n74(x) + if (x < 1) + fun_l7_n925(x) + else + fun_l7_n965(x) + end +end + +def fun_l6_n75(x) + if (x < 1) + fun_l7_n825(x) + else + fun_l7_n79(x) + end +end + +def fun_l6_n76(x) + if (x < 1) + fun_l7_n812(x) + else + fun_l7_n96(x) + end +end + +def fun_l6_n77(x) + if (x < 1) + fun_l7_n688(x) + else + fun_l7_n424(x) + end +end + +def fun_l6_n78(x) + if (x < 1) + fun_l7_n171(x) + else + fun_l7_n728(x) + end +end + +def fun_l6_n79(x) + if (x < 1) + fun_l7_n786(x) + else + fun_l7_n135(x) + end +end + +def fun_l6_n80(x) + if (x < 1) + fun_l7_n622(x) + else + fun_l7_n3(x) + end +end + +def fun_l6_n81(x) + if (x < 1) + fun_l7_n386(x) + else + fun_l7_n946(x) + end +end + +def fun_l6_n82(x) + if (x < 1) + fun_l7_n192(x) + else + fun_l7_n253(x) + end +end + +def fun_l6_n83(x) + if (x < 1) + fun_l7_n534(x) + else + fun_l7_n4(x) + end +end + +def fun_l6_n84(x) + if (x < 1) + fun_l7_n198(x) + else + fun_l7_n455(x) + end +end + +def fun_l6_n85(x) + if (x < 1) + fun_l7_n471(x) + else + fun_l7_n26(x) + end +end + +def fun_l6_n86(x) + if (x < 1) + fun_l7_n147(x) + else + fun_l7_n893(x) + end +end + +def fun_l6_n87(x) + if (x < 1) + fun_l7_n424(x) + else + fun_l7_n713(x) + end +end + +def fun_l6_n88(x) + if (x < 1) + fun_l7_n867(x) + else + fun_l7_n561(x) + end +end + +def fun_l6_n89(x) + if (x < 1) + fun_l7_n64(x) + else + fun_l7_n662(x) + end +end + +def fun_l6_n90(x) + if (x < 1) + fun_l7_n849(x) + else + fun_l7_n105(x) + end +end + +def fun_l6_n91(x) + if (x < 1) + fun_l7_n564(x) + else + fun_l7_n758(x) + end +end + +def fun_l6_n92(x) + if (x < 1) + fun_l7_n433(x) + else + fun_l7_n713(x) + end +end + +def fun_l6_n93(x) + if (x < 1) + fun_l7_n283(x) + else + fun_l7_n577(x) + end +end + +def fun_l6_n94(x) + if (x < 1) + fun_l7_n951(x) + else + fun_l7_n48(x) + end +end + +def fun_l6_n95(x) + if (x < 1) + fun_l7_n966(x) + else + fun_l7_n789(x) + end +end + +def fun_l6_n96(x) + if (x < 1) + fun_l7_n954(x) + else + fun_l7_n431(x) + end +end + +def fun_l6_n97(x) + if (x < 1) + fun_l7_n720(x) + else + fun_l7_n847(x) + end +end + +def fun_l6_n98(x) + if (x < 1) + fun_l7_n517(x) + else + fun_l7_n378(x) + end +end + +def fun_l6_n99(x) + if (x < 1) + fun_l7_n951(x) + else + fun_l7_n688(x) + end +end + +def fun_l6_n100(x) + if (x < 1) + fun_l7_n163(x) + else + fun_l7_n540(x) + end +end + +def fun_l6_n101(x) + if (x < 1) + fun_l7_n423(x) + else + fun_l7_n10(x) + end +end + +def fun_l6_n102(x) + if (x < 1) + fun_l7_n346(x) + else + fun_l7_n409(x) + end +end + +def fun_l6_n103(x) + if (x < 1) + fun_l7_n686(x) + else + fun_l7_n432(x) + end +end + +def fun_l6_n104(x) + if (x < 1) + fun_l7_n144(x) + else + fun_l7_n510(x) + end +end + +def fun_l6_n105(x) + if (x < 1) + fun_l7_n568(x) + else + fun_l7_n756(x) + end +end + +def fun_l6_n106(x) + if (x < 1) + fun_l7_n708(x) + else + fun_l7_n199(x) + end +end + +def fun_l6_n107(x) + if (x < 1) + fun_l7_n823(x) + else + fun_l7_n969(x) + end +end + +def fun_l6_n108(x) + if (x < 1) + fun_l7_n156(x) + else + fun_l7_n211(x) + end +end + +def fun_l6_n109(x) + if (x < 1) + fun_l7_n527(x) + else + fun_l7_n791(x) + end +end + +def fun_l6_n110(x) + if (x < 1) + fun_l7_n392(x) + else + fun_l7_n314(x) + end +end + +def fun_l6_n111(x) + if (x < 1) + fun_l7_n355(x) + else + fun_l7_n222(x) + end +end + +def fun_l6_n112(x) + if (x < 1) + fun_l7_n683(x) + else + fun_l7_n735(x) + end +end + +def fun_l6_n113(x) + if (x < 1) + fun_l7_n38(x) + else + fun_l7_n874(x) + end +end + +def fun_l6_n114(x) + if (x < 1) + fun_l7_n190(x) + else + fun_l7_n209(x) + end +end + +def fun_l6_n115(x) + if (x < 1) + fun_l7_n544(x) + else + fun_l7_n267(x) + end +end + +def fun_l6_n116(x) + if (x < 1) + fun_l7_n701(x) + else + fun_l7_n101(x) + end +end + +def fun_l6_n117(x) + if (x < 1) + fun_l7_n283(x) + else + fun_l7_n979(x) + end +end + +def fun_l6_n118(x) + if (x < 1) + fun_l7_n902(x) + else + fun_l7_n897(x) + end +end + +def fun_l6_n119(x) + if (x < 1) + fun_l7_n115(x) + else + fun_l7_n660(x) + end +end + +def fun_l6_n120(x) + if (x < 1) + fun_l7_n804(x) + else + fun_l7_n536(x) + end +end + +def fun_l6_n121(x) + if (x < 1) + fun_l7_n278(x) + else + fun_l7_n666(x) + end +end + +def fun_l6_n122(x) + if (x < 1) + fun_l7_n254(x) + else + fun_l7_n572(x) + end +end + +def fun_l6_n123(x) + if (x < 1) + fun_l7_n474(x) + else + fun_l7_n912(x) + end +end + +def fun_l6_n124(x) + if (x < 1) + fun_l7_n0(x) + else + fun_l7_n514(x) + end +end + +def fun_l6_n125(x) + if (x < 1) + fun_l7_n916(x) + else + fun_l7_n633(x) + end +end + +def fun_l6_n126(x) + if (x < 1) + fun_l7_n184(x) + else + fun_l7_n379(x) + end +end + +def fun_l6_n127(x) + if (x < 1) + fun_l7_n316(x) + else + fun_l7_n422(x) + end +end + +def fun_l6_n128(x) + if (x < 1) + fun_l7_n402(x) + else + fun_l7_n237(x) + end +end + +def fun_l6_n129(x) + if (x < 1) + fun_l7_n303(x) + else + fun_l7_n61(x) + end +end + +def fun_l6_n130(x) + if (x < 1) + fun_l7_n918(x) + else + fun_l7_n732(x) + end +end + +def fun_l6_n131(x) + if (x < 1) + fun_l7_n74(x) + else + fun_l7_n472(x) + end +end + +def fun_l6_n132(x) + if (x < 1) + fun_l7_n648(x) + else + fun_l7_n546(x) + end +end + +def fun_l6_n133(x) + if (x < 1) + fun_l7_n388(x) + else + fun_l7_n359(x) + end +end + +def fun_l6_n134(x) + if (x < 1) + fun_l7_n594(x) + else + fun_l7_n607(x) + end +end + +def fun_l6_n135(x) + if (x < 1) + fun_l7_n642(x) + else + fun_l7_n188(x) + end +end + +def fun_l6_n136(x) + if (x < 1) + fun_l7_n879(x) + else + fun_l7_n521(x) + end +end + +def fun_l6_n137(x) + if (x < 1) + fun_l7_n362(x) + else + fun_l7_n564(x) + end +end + +def fun_l6_n138(x) + if (x < 1) + fun_l7_n590(x) + else + fun_l7_n59(x) + end +end + +def fun_l6_n139(x) + if (x < 1) + fun_l7_n464(x) + else + fun_l7_n563(x) + end +end + +def fun_l6_n140(x) + if (x < 1) + fun_l7_n710(x) + else + fun_l7_n890(x) + end +end + +def fun_l6_n141(x) + if (x < 1) + fun_l7_n63(x) + else + fun_l7_n470(x) + end +end + +def fun_l6_n142(x) + if (x < 1) + fun_l7_n160(x) + else + fun_l7_n153(x) + end +end + +def fun_l6_n143(x) + if (x < 1) + fun_l7_n908(x) + else + fun_l7_n286(x) + end +end + +def fun_l6_n144(x) + if (x < 1) + fun_l7_n193(x) + else + fun_l7_n657(x) + end +end + +def fun_l6_n145(x) + if (x < 1) + fun_l7_n885(x) + else + fun_l7_n981(x) + end +end + +def fun_l6_n146(x) + if (x < 1) + fun_l7_n479(x) + else + fun_l7_n188(x) + end +end + +def fun_l6_n147(x) + if (x < 1) + fun_l7_n378(x) + else + fun_l7_n299(x) + end +end + +def fun_l6_n148(x) + if (x < 1) + fun_l7_n239(x) + else + fun_l7_n70(x) + end +end + +def fun_l6_n149(x) + if (x < 1) + fun_l7_n864(x) + else + fun_l7_n131(x) + end +end + +def fun_l6_n150(x) + if (x < 1) + fun_l7_n748(x) + else + fun_l7_n112(x) + end +end + +def fun_l6_n151(x) + if (x < 1) + fun_l7_n466(x) + else + fun_l7_n672(x) + end +end + +def fun_l6_n152(x) + if (x < 1) + fun_l7_n242(x) + else + fun_l7_n8(x) + end +end + +def fun_l6_n153(x) + if (x < 1) + fun_l7_n408(x) + else + fun_l7_n538(x) + end +end + +def fun_l6_n154(x) + if (x < 1) + fun_l7_n984(x) + else + fun_l7_n134(x) + end +end + +def fun_l6_n155(x) + if (x < 1) + fun_l7_n384(x) + else + fun_l7_n62(x) + end +end + +def fun_l6_n156(x) + if (x < 1) + fun_l7_n576(x) + else + fun_l7_n168(x) + end +end + +def fun_l6_n157(x) + if (x < 1) + fun_l7_n371(x) + else + fun_l7_n470(x) + end +end + +def fun_l6_n158(x) + if (x < 1) + fun_l7_n30(x) + else + fun_l7_n11(x) + end +end + +def fun_l6_n159(x) + if (x < 1) + fun_l7_n45(x) + else + fun_l7_n191(x) + end +end + +def fun_l6_n160(x) + if (x < 1) + fun_l7_n659(x) + else + fun_l7_n981(x) + end +end + +def fun_l6_n161(x) + if (x < 1) + fun_l7_n586(x) + else + fun_l7_n617(x) + end +end + +def fun_l6_n162(x) + if (x < 1) + fun_l7_n844(x) + else + fun_l7_n831(x) + end +end + +def fun_l6_n163(x) + if (x < 1) + fun_l7_n14(x) + else + fun_l7_n631(x) + end +end + +def fun_l6_n164(x) + if (x < 1) + fun_l7_n388(x) + else + fun_l7_n837(x) + end +end + +def fun_l6_n165(x) + if (x < 1) + fun_l7_n825(x) + else + fun_l7_n902(x) + end +end + +def fun_l6_n166(x) + if (x < 1) + fun_l7_n490(x) + else + fun_l7_n724(x) + end +end + +def fun_l6_n167(x) + if (x < 1) + fun_l7_n612(x) + else + fun_l7_n792(x) + end +end + +def fun_l6_n168(x) + if (x < 1) + fun_l7_n344(x) + else + fun_l7_n624(x) + end +end + +def fun_l6_n169(x) + if (x < 1) + fun_l7_n255(x) + else + fun_l7_n456(x) + end +end + +def fun_l6_n170(x) + if (x < 1) + fun_l7_n893(x) + else + fun_l7_n358(x) + end +end + +def fun_l6_n171(x) + if (x < 1) + fun_l7_n926(x) + else + fun_l7_n988(x) + end +end + +def fun_l6_n172(x) + if (x < 1) + fun_l7_n856(x) + else + fun_l7_n553(x) + end +end + +def fun_l6_n173(x) + if (x < 1) + fun_l7_n694(x) + else + fun_l7_n918(x) + end +end + +def fun_l6_n174(x) + if (x < 1) + fun_l7_n884(x) + else + fun_l7_n711(x) + end +end + +def fun_l6_n175(x) + if (x < 1) + fun_l7_n884(x) + else + fun_l7_n28(x) + end +end + +def fun_l6_n176(x) + if (x < 1) + fun_l7_n378(x) + else + fun_l7_n14(x) + end +end + +def fun_l6_n177(x) + if (x < 1) + fun_l7_n844(x) + else + fun_l7_n549(x) + end +end + +def fun_l6_n178(x) + if (x < 1) + fun_l7_n396(x) + else + fun_l7_n802(x) + end +end + +def fun_l6_n179(x) + if (x < 1) + fun_l7_n407(x) + else + fun_l7_n612(x) + end +end + +def fun_l6_n180(x) + if (x < 1) + fun_l7_n403(x) + else + fun_l7_n768(x) + end +end + +def fun_l6_n181(x) + if (x < 1) + fun_l7_n412(x) + else + fun_l7_n301(x) + end +end + +def fun_l6_n182(x) + if (x < 1) + fun_l7_n479(x) + else + fun_l7_n923(x) + end +end + +def fun_l6_n183(x) + if (x < 1) + fun_l7_n664(x) + else + fun_l7_n451(x) + end +end + +def fun_l6_n184(x) + if (x < 1) + fun_l7_n854(x) + else + fun_l7_n438(x) + end +end + +def fun_l6_n185(x) + if (x < 1) + fun_l7_n994(x) + else + fun_l7_n726(x) + end +end + +def fun_l6_n186(x) + if (x < 1) + fun_l7_n128(x) + else + fun_l7_n166(x) + end +end + +def fun_l6_n187(x) + if (x < 1) + fun_l7_n515(x) + else + fun_l7_n21(x) + end +end + +def fun_l6_n188(x) + if (x < 1) + fun_l7_n487(x) + else + fun_l7_n631(x) + end +end + +def fun_l6_n189(x) + if (x < 1) + fun_l7_n16(x) + else + fun_l7_n579(x) + end +end + +def fun_l6_n190(x) + if (x < 1) + fun_l7_n30(x) + else + fun_l7_n417(x) + end +end + +def fun_l6_n191(x) + if (x < 1) + fun_l7_n737(x) + else + fun_l7_n436(x) + end +end + +def fun_l6_n192(x) + if (x < 1) + fun_l7_n260(x) + else + fun_l7_n657(x) + end +end + +def fun_l6_n193(x) + if (x < 1) + fun_l7_n722(x) + else + fun_l7_n489(x) + end +end + +def fun_l6_n194(x) + if (x < 1) + fun_l7_n53(x) + else + fun_l7_n624(x) + end +end + +def fun_l6_n195(x) + if (x < 1) + fun_l7_n91(x) + else + fun_l7_n597(x) + end +end + +def fun_l6_n196(x) + if (x < 1) + fun_l7_n980(x) + else + fun_l7_n498(x) + end +end + +def fun_l6_n197(x) + if (x < 1) + fun_l7_n918(x) + else + fun_l7_n328(x) + end +end + +def fun_l6_n198(x) + if (x < 1) + fun_l7_n184(x) + else + fun_l7_n761(x) + end +end + +def fun_l6_n199(x) + if (x < 1) + fun_l7_n692(x) + else + fun_l7_n610(x) + end +end + +def fun_l6_n200(x) + if (x < 1) + fun_l7_n597(x) + else + fun_l7_n135(x) + end +end + +def fun_l6_n201(x) + if (x < 1) + fun_l7_n973(x) + else + fun_l7_n453(x) + end +end + +def fun_l6_n202(x) + if (x < 1) + fun_l7_n433(x) + else + fun_l7_n794(x) + end +end + +def fun_l6_n203(x) + if (x < 1) + fun_l7_n294(x) + else + fun_l7_n271(x) + end +end + +def fun_l6_n204(x) + if (x < 1) + fun_l7_n783(x) + else + fun_l7_n20(x) + end +end + +def fun_l6_n205(x) + if (x < 1) + fun_l7_n941(x) + else + fun_l7_n517(x) + end +end + +def fun_l6_n206(x) + if (x < 1) + fun_l7_n306(x) + else + fun_l7_n735(x) + end +end + +def fun_l6_n207(x) + if (x < 1) + fun_l7_n63(x) + else + fun_l7_n313(x) + end +end + +def fun_l6_n208(x) + if (x < 1) + fun_l7_n766(x) + else + fun_l7_n868(x) + end +end + +def fun_l6_n209(x) + if (x < 1) + fun_l7_n780(x) + else + fun_l7_n422(x) + end +end + +def fun_l6_n210(x) + if (x < 1) + fun_l7_n279(x) + else + fun_l7_n695(x) + end +end + +def fun_l6_n211(x) + if (x < 1) + fun_l7_n981(x) + else + fun_l7_n946(x) + end +end + +def fun_l6_n212(x) + if (x < 1) + fun_l7_n885(x) + else + fun_l7_n752(x) + end +end + +def fun_l6_n213(x) + if (x < 1) + fun_l7_n238(x) + else + fun_l7_n322(x) + end +end + +def fun_l6_n214(x) + if (x < 1) + fun_l7_n832(x) + else + fun_l7_n714(x) + end +end + +def fun_l6_n215(x) + if (x < 1) + fun_l7_n369(x) + else + fun_l7_n793(x) + end +end + +def fun_l6_n216(x) + if (x < 1) + fun_l7_n897(x) + else + fun_l7_n22(x) + end +end + +def fun_l6_n217(x) + if (x < 1) + fun_l7_n94(x) + else + fun_l7_n93(x) + end +end + +def fun_l6_n218(x) + if (x < 1) + fun_l7_n638(x) + else + fun_l7_n267(x) + end +end + +def fun_l6_n219(x) + if (x < 1) + fun_l7_n254(x) + else + fun_l7_n162(x) + end +end + +def fun_l6_n220(x) + if (x < 1) + fun_l7_n969(x) + else + fun_l7_n371(x) + end +end + +def fun_l6_n221(x) + if (x < 1) + fun_l7_n692(x) + else + fun_l7_n421(x) + end +end + +def fun_l6_n222(x) + if (x < 1) + fun_l7_n312(x) + else + fun_l7_n475(x) + end +end + +def fun_l6_n223(x) + if (x < 1) + fun_l7_n566(x) + else + fun_l7_n497(x) + end +end + +def fun_l6_n224(x) + if (x < 1) + fun_l7_n560(x) + else + fun_l7_n60(x) + end +end + +def fun_l6_n225(x) + if (x < 1) + fun_l7_n484(x) + else + fun_l7_n602(x) + end +end + +def fun_l6_n226(x) + if (x < 1) + fun_l7_n399(x) + else + fun_l7_n614(x) + end +end + +def fun_l6_n227(x) + if (x < 1) + fun_l7_n344(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n228(x) + if (x < 1) + fun_l7_n840(x) + else + fun_l7_n211(x) + end +end + +def fun_l6_n229(x) + if (x < 1) + fun_l7_n423(x) + else + fun_l7_n51(x) + end +end + +def fun_l6_n230(x) + if (x < 1) + fun_l7_n978(x) + else + fun_l7_n334(x) + end +end + +def fun_l6_n231(x) + if (x < 1) + fun_l7_n136(x) + else + fun_l7_n296(x) + end +end + +def fun_l6_n232(x) + if (x < 1) + fun_l7_n24(x) + else + fun_l7_n282(x) + end +end + +def fun_l6_n233(x) + if (x < 1) + fun_l7_n803(x) + else + fun_l7_n623(x) + end +end + +def fun_l6_n234(x) + if (x < 1) + fun_l7_n720(x) + else + fun_l7_n492(x) + end +end + +def fun_l6_n235(x) + if (x < 1) + fun_l7_n627(x) + else + fun_l7_n260(x) + end +end + +def fun_l6_n236(x) + if (x < 1) + fun_l7_n460(x) + else + fun_l7_n693(x) + end +end + +def fun_l6_n237(x) + if (x < 1) + fun_l7_n635(x) + else + fun_l7_n745(x) + end +end + +def fun_l6_n238(x) + if (x < 1) + fun_l7_n76(x) + else + fun_l7_n283(x) + end +end + +def fun_l6_n239(x) + if (x < 1) + fun_l7_n183(x) + else + fun_l7_n515(x) + end +end + +def fun_l6_n240(x) + if (x < 1) + fun_l7_n266(x) + else + fun_l7_n34(x) + end +end + +def fun_l6_n241(x) + if (x < 1) + fun_l7_n480(x) + else + fun_l7_n868(x) + end +end + +def fun_l6_n242(x) + if (x < 1) + fun_l7_n998(x) + else + fun_l7_n669(x) + end +end + +def fun_l6_n243(x) + if (x < 1) + fun_l7_n414(x) + else + fun_l7_n161(x) + end +end + +def fun_l6_n244(x) + if (x < 1) + fun_l7_n104(x) + else + fun_l7_n659(x) + end +end + +def fun_l6_n245(x) + if (x < 1) + fun_l7_n881(x) + else + fun_l7_n229(x) + end +end + +def fun_l6_n246(x) + if (x < 1) + fun_l7_n328(x) + else + fun_l7_n935(x) + end +end + +def fun_l6_n247(x) + if (x < 1) + fun_l7_n433(x) + else + fun_l7_n565(x) + end +end + +def fun_l6_n248(x) + if (x < 1) + fun_l7_n161(x) + else + fun_l7_n760(x) + end +end + +def fun_l6_n249(x) + if (x < 1) + fun_l7_n115(x) + else + fun_l7_n594(x) + end +end + +def fun_l6_n250(x) + if (x < 1) + fun_l7_n350(x) + else + fun_l7_n310(x) + end +end + +def fun_l6_n251(x) + if (x < 1) + fun_l7_n920(x) + else + fun_l7_n51(x) + end +end + +def fun_l6_n252(x) + if (x < 1) + fun_l7_n132(x) + else + fun_l7_n492(x) + end +end + +def fun_l6_n253(x) + if (x < 1) + fun_l7_n618(x) + else + fun_l7_n325(x) + end +end + +def fun_l6_n254(x) + if (x < 1) + fun_l7_n682(x) + else + fun_l7_n840(x) + end +end + +def fun_l6_n255(x) + if (x < 1) + fun_l7_n462(x) + else + fun_l7_n780(x) + end +end + +def fun_l6_n256(x) + if (x < 1) + fun_l7_n712(x) + else + fun_l7_n995(x) + end +end + +def fun_l6_n257(x) + if (x < 1) + fun_l7_n111(x) + else + fun_l7_n121(x) + end +end + +def fun_l6_n258(x) + if (x < 1) + fun_l7_n255(x) + else + fun_l7_n384(x) + end +end + +def fun_l6_n259(x) + if (x < 1) + fun_l7_n610(x) + else + fun_l7_n555(x) + end +end + +def fun_l6_n260(x) + if (x < 1) + fun_l7_n778(x) + else + fun_l7_n454(x) + end +end + +def fun_l6_n261(x) + if (x < 1) + fun_l7_n376(x) + else + fun_l7_n892(x) + end +end + +def fun_l6_n262(x) + if (x < 1) + fun_l7_n454(x) + else + fun_l7_n468(x) + end +end + +def fun_l6_n263(x) + if (x < 1) + fun_l7_n708(x) + else + fun_l7_n368(x) + end +end + +def fun_l6_n264(x) + if (x < 1) + fun_l7_n517(x) + else + fun_l7_n299(x) + end +end + +def fun_l6_n265(x) + if (x < 1) + fun_l7_n987(x) + else + fun_l7_n318(x) + end +end + +def fun_l6_n266(x) + if (x < 1) + fun_l7_n372(x) + else + fun_l7_n560(x) + end +end + +def fun_l6_n267(x) + if (x < 1) + fun_l7_n493(x) + else + fun_l7_n288(x) + end +end + +def fun_l6_n268(x) + if (x < 1) + fun_l7_n278(x) + else + fun_l7_n10(x) + end +end + +def fun_l6_n269(x) + if (x < 1) + fun_l7_n417(x) + else + fun_l7_n703(x) + end +end + +def fun_l6_n270(x) + if (x < 1) + fun_l7_n410(x) + else + fun_l7_n91(x) + end +end + +def fun_l6_n271(x) + if (x < 1) + fun_l7_n281(x) + else + fun_l7_n447(x) + end +end + +def fun_l6_n272(x) + if (x < 1) + fun_l7_n263(x) + else + fun_l7_n374(x) + end +end + +def fun_l6_n273(x) + if (x < 1) + fun_l7_n622(x) + else + fun_l7_n310(x) + end +end + +def fun_l6_n274(x) + if (x < 1) + fun_l7_n176(x) + else + fun_l7_n227(x) + end +end + +def fun_l6_n275(x) + if (x < 1) + fun_l7_n848(x) + else + fun_l7_n416(x) + end +end + +def fun_l6_n276(x) + if (x < 1) + fun_l7_n998(x) + else + fun_l7_n969(x) + end +end + +def fun_l6_n277(x) + if (x < 1) + fun_l7_n356(x) + else + fun_l7_n722(x) + end +end + +def fun_l6_n278(x) + if (x < 1) + fun_l7_n888(x) + else + fun_l7_n156(x) + end +end + +def fun_l6_n279(x) + if (x < 1) + fun_l7_n779(x) + else + fun_l7_n123(x) + end +end + +def fun_l6_n280(x) + if (x < 1) + fun_l7_n393(x) + else + fun_l7_n765(x) + end +end + +def fun_l6_n281(x) + if (x < 1) + fun_l7_n257(x) + else + fun_l7_n277(x) + end +end + +def fun_l6_n282(x) + if (x < 1) + fun_l7_n780(x) + else + fun_l7_n643(x) + end +end + +def fun_l6_n283(x) + if (x < 1) + fun_l7_n63(x) + else + fun_l7_n449(x) + end +end + +def fun_l6_n284(x) + if (x < 1) + fun_l7_n200(x) + else + fun_l7_n806(x) + end +end + +def fun_l6_n285(x) + if (x < 1) + fun_l7_n575(x) + else + fun_l7_n409(x) + end +end + +def fun_l6_n286(x) + if (x < 1) + fun_l7_n377(x) + else + fun_l7_n456(x) + end +end + +def fun_l6_n287(x) + if (x < 1) + fun_l7_n519(x) + else + fun_l7_n473(x) + end +end + +def fun_l6_n288(x) + if (x < 1) + fun_l7_n525(x) + else + fun_l7_n45(x) + end +end + +def fun_l6_n289(x) + if (x < 1) + fun_l7_n678(x) + else + fun_l7_n910(x) + end +end + +def fun_l6_n290(x) + if (x < 1) + fun_l7_n628(x) + else + fun_l7_n939(x) + end +end + +def fun_l6_n291(x) + if (x < 1) + fun_l7_n967(x) + else + fun_l7_n927(x) + end +end + +def fun_l6_n292(x) + if (x < 1) + fun_l7_n634(x) + else + fun_l7_n184(x) + end +end + +def fun_l6_n293(x) + if (x < 1) + fun_l7_n857(x) + else + fun_l7_n625(x) + end +end + +def fun_l6_n294(x) + if (x < 1) + fun_l7_n105(x) + else + fun_l7_n46(x) + end +end + +def fun_l6_n295(x) + if (x < 1) + fun_l7_n642(x) + else + fun_l7_n566(x) + end +end + +def fun_l6_n296(x) + if (x < 1) + fun_l7_n173(x) + else + fun_l7_n619(x) + end +end + +def fun_l6_n297(x) + if (x < 1) + fun_l7_n257(x) + else + fun_l7_n485(x) + end +end + +def fun_l6_n298(x) + if (x < 1) + fun_l7_n447(x) + else + fun_l7_n808(x) + end +end + +def fun_l6_n299(x) + if (x < 1) + fun_l7_n838(x) + else + fun_l7_n856(x) + end +end + +def fun_l6_n300(x) + if (x < 1) + fun_l7_n893(x) + else + fun_l7_n99(x) + end +end + +def fun_l6_n301(x) + if (x < 1) + fun_l7_n180(x) + else + fun_l7_n126(x) + end +end + +def fun_l6_n302(x) + if (x < 1) + fun_l7_n62(x) + else + fun_l7_n266(x) + end +end + +def fun_l6_n303(x) + if (x < 1) + fun_l7_n709(x) + else + fun_l7_n196(x) + end +end + +def fun_l6_n304(x) + if (x < 1) + fun_l7_n408(x) + else + fun_l7_n730(x) + end +end + +def fun_l6_n305(x) + if (x < 1) + fun_l7_n736(x) + else + fun_l7_n673(x) + end +end + +def fun_l6_n306(x) + if (x < 1) + fun_l7_n734(x) + else + fun_l7_n519(x) + end +end + +def fun_l6_n307(x) + if (x < 1) + fun_l7_n629(x) + else + fun_l7_n670(x) + end +end + +def fun_l6_n308(x) + if (x < 1) + fun_l7_n839(x) + else + fun_l7_n191(x) + end +end + +def fun_l6_n309(x) + if (x < 1) + fun_l7_n123(x) + else + fun_l7_n553(x) + end +end + +def fun_l6_n310(x) + if (x < 1) + fun_l7_n812(x) + else + fun_l7_n815(x) + end +end + +def fun_l6_n311(x) + if (x < 1) + fun_l7_n860(x) + else + fun_l7_n519(x) + end +end + +def fun_l6_n312(x) + if (x < 1) + fun_l7_n181(x) + else + fun_l7_n674(x) + end +end + +def fun_l6_n313(x) + if (x < 1) + fun_l7_n654(x) + else + fun_l7_n500(x) + end +end + +def fun_l6_n314(x) + if (x < 1) + fun_l7_n690(x) + else + fun_l7_n136(x) + end +end + +def fun_l6_n315(x) + if (x < 1) + fun_l7_n944(x) + else + fun_l7_n956(x) + end +end + +def fun_l6_n316(x) + if (x < 1) + fun_l7_n471(x) + else + fun_l7_n245(x) + end +end + +def fun_l6_n317(x) + if (x < 1) + fun_l7_n520(x) + else + fun_l7_n919(x) + end +end + +def fun_l6_n318(x) + if (x < 1) + fun_l7_n843(x) + else + fun_l7_n793(x) + end +end + +def fun_l6_n319(x) + if (x < 1) + fun_l7_n765(x) + else + fun_l7_n363(x) + end +end + +def fun_l6_n320(x) + if (x < 1) + fun_l7_n483(x) + else + fun_l7_n439(x) + end +end + +def fun_l6_n321(x) + if (x < 1) + fun_l7_n232(x) + else + fun_l7_n921(x) + end +end + +def fun_l6_n322(x) + if (x < 1) + fun_l7_n398(x) + else + fun_l7_n862(x) + end +end + +def fun_l6_n323(x) + if (x < 1) + fun_l7_n550(x) + else + fun_l7_n84(x) + end +end + +def fun_l6_n324(x) + if (x < 1) + fun_l7_n788(x) + else + fun_l7_n512(x) + end +end + +def fun_l6_n325(x) + if (x < 1) + fun_l7_n512(x) + else + fun_l7_n303(x) + end +end + +def fun_l6_n326(x) + if (x < 1) + fun_l7_n86(x) + else + fun_l7_n555(x) + end +end + +def fun_l6_n327(x) + if (x < 1) + fun_l7_n857(x) + else + fun_l7_n751(x) + end +end + +def fun_l6_n328(x) + if (x < 1) + fun_l7_n341(x) + else + fun_l7_n208(x) + end +end + +def fun_l6_n329(x) + if (x < 1) + fun_l7_n707(x) + else + fun_l7_n371(x) + end +end + +def fun_l6_n330(x) + if (x < 1) + fun_l7_n217(x) + else + fun_l7_n604(x) + end +end + +def fun_l6_n331(x) + if (x < 1) + fun_l7_n607(x) + else + fun_l7_n471(x) + end +end + +def fun_l6_n332(x) + if (x < 1) + fun_l7_n818(x) + else + fun_l7_n787(x) + end +end + +def fun_l6_n333(x) + if (x < 1) + fun_l7_n28(x) + else + fun_l7_n220(x) + end +end + +def fun_l6_n334(x) + if (x < 1) + fun_l7_n666(x) + else + fun_l7_n995(x) + end +end + +def fun_l6_n335(x) + if (x < 1) + fun_l7_n3(x) + else + fun_l7_n970(x) + end +end + +def fun_l6_n336(x) + if (x < 1) + fun_l7_n977(x) + else + fun_l7_n77(x) + end +end + +def fun_l6_n337(x) + if (x < 1) + fun_l7_n54(x) + else + fun_l7_n814(x) + end +end + +def fun_l6_n338(x) + if (x < 1) + fun_l7_n129(x) + else + fun_l7_n624(x) + end +end + +def fun_l6_n339(x) + if (x < 1) + fun_l7_n866(x) + else + fun_l7_n821(x) + end +end + +def fun_l6_n340(x) + if (x < 1) + fun_l7_n912(x) + else + fun_l7_n24(x) + end +end + +def fun_l6_n341(x) + if (x < 1) + fun_l7_n684(x) + else + fun_l7_n610(x) + end +end + +def fun_l6_n342(x) + if (x < 1) + fun_l7_n816(x) + else + fun_l7_n826(x) + end +end + +def fun_l6_n343(x) + if (x < 1) + fun_l7_n479(x) + else + fun_l7_n444(x) + end +end + +def fun_l6_n344(x) + if (x < 1) + fun_l7_n51(x) + else + fun_l7_n731(x) + end +end + +def fun_l6_n345(x) + if (x < 1) + fun_l7_n690(x) + else + fun_l7_n631(x) + end +end + +def fun_l6_n346(x) + if (x < 1) + fun_l7_n254(x) + else + fun_l7_n353(x) + end +end + +def fun_l6_n347(x) + if (x < 1) + fun_l7_n905(x) + else + fun_l7_n422(x) + end +end + +def fun_l6_n348(x) + if (x < 1) + fun_l7_n249(x) + else + fun_l7_n200(x) + end +end + +def fun_l6_n349(x) + if (x < 1) + fun_l7_n11(x) + else + fun_l7_n550(x) + end +end + +def fun_l6_n350(x) + if (x < 1) + fun_l7_n818(x) + else + fun_l7_n444(x) + end +end + +def fun_l6_n351(x) + if (x < 1) + fun_l7_n422(x) + else + fun_l7_n242(x) + end +end + +def fun_l6_n352(x) + if (x < 1) + fun_l7_n653(x) + else + fun_l7_n912(x) + end +end + +def fun_l6_n353(x) + if (x < 1) + fun_l7_n605(x) + else + fun_l7_n129(x) + end +end + +def fun_l6_n354(x) + if (x < 1) + fun_l7_n622(x) + else + fun_l7_n172(x) + end +end + +def fun_l6_n355(x) + if (x < 1) + fun_l7_n568(x) + else + fun_l7_n26(x) + end +end + +def fun_l6_n356(x) + if (x < 1) + fun_l7_n777(x) + else + fun_l7_n818(x) + end +end + +def fun_l6_n357(x) + if (x < 1) + fun_l7_n807(x) + else + fun_l7_n642(x) + end +end + +def fun_l6_n358(x) + if (x < 1) + fun_l7_n745(x) + else + fun_l7_n866(x) + end +end + +def fun_l6_n359(x) + if (x < 1) + fun_l7_n603(x) + else + fun_l7_n42(x) + end +end + +def fun_l6_n360(x) + if (x < 1) + fun_l7_n818(x) + else + fun_l7_n203(x) + end +end + +def fun_l6_n361(x) + if (x < 1) + fun_l7_n451(x) + else + fun_l7_n719(x) + end +end + +def fun_l6_n362(x) + if (x < 1) + fun_l7_n31(x) + else + fun_l7_n148(x) + end +end + +def fun_l6_n363(x) + if (x < 1) + fun_l7_n148(x) + else + fun_l7_n292(x) + end +end + +def fun_l6_n364(x) + if (x < 1) + fun_l7_n175(x) + else + fun_l7_n849(x) + end +end + +def fun_l6_n365(x) + if (x < 1) + fun_l7_n414(x) + else + fun_l7_n57(x) + end +end + +def fun_l6_n366(x) + if (x < 1) + fun_l7_n771(x) + else + fun_l7_n625(x) + end +end + +def fun_l6_n367(x) + if (x < 1) + fun_l7_n232(x) + else + fun_l7_n108(x) + end +end + +def fun_l6_n368(x) + if (x < 1) + fun_l7_n123(x) + else + fun_l7_n413(x) + end +end + +def fun_l6_n369(x) + if (x < 1) + fun_l7_n587(x) + else + fun_l7_n876(x) + end +end + +def fun_l6_n370(x) + if (x < 1) + fun_l7_n750(x) + else + fun_l7_n531(x) + end +end + +def fun_l6_n371(x) + if (x < 1) + fun_l7_n55(x) + else + fun_l7_n859(x) + end +end + +def fun_l6_n372(x) + if (x < 1) + fun_l7_n848(x) + else + fun_l7_n272(x) + end +end + +def fun_l6_n373(x) + if (x < 1) + fun_l7_n480(x) + else + fun_l7_n976(x) + end +end + +def fun_l6_n374(x) + if (x < 1) + fun_l7_n298(x) + else + fun_l7_n844(x) + end +end + +def fun_l6_n375(x) + if (x < 1) + fun_l7_n564(x) + else + fun_l7_n960(x) + end +end + +def fun_l6_n376(x) + if (x < 1) + fun_l7_n684(x) + else + fun_l7_n181(x) + end +end + +def fun_l6_n377(x) + if (x < 1) + fun_l7_n153(x) + else + fun_l7_n21(x) + end +end + +def fun_l6_n378(x) + if (x < 1) + fun_l7_n377(x) + else + fun_l7_n761(x) + end +end + +def fun_l6_n379(x) + if (x < 1) + fun_l7_n737(x) + else + fun_l7_n605(x) + end +end + +def fun_l6_n380(x) + if (x < 1) + fun_l7_n536(x) + else + fun_l7_n143(x) + end +end + +def fun_l6_n381(x) + if (x < 1) + fun_l7_n314(x) + else + fun_l7_n999(x) + end +end + +def fun_l6_n382(x) + if (x < 1) + fun_l7_n995(x) + else + fun_l7_n564(x) + end +end + +def fun_l6_n383(x) + if (x < 1) + fun_l7_n772(x) + else + fun_l7_n520(x) + end +end + +def fun_l6_n384(x) + if (x < 1) + fun_l7_n250(x) + else + fun_l7_n142(x) + end +end + +def fun_l6_n385(x) + if (x < 1) + fun_l7_n993(x) + else + fun_l7_n987(x) + end +end + +def fun_l6_n386(x) + if (x < 1) + fun_l7_n717(x) + else + fun_l7_n674(x) + end +end + +def fun_l6_n387(x) + if (x < 1) + fun_l7_n585(x) + else + fun_l7_n102(x) + end +end + +def fun_l6_n388(x) + if (x < 1) + fun_l7_n779(x) + else + fun_l7_n110(x) + end +end + +def fun_l6_n389(x) + if (x < 1) + fun_l7_n815(x) + else + fun_l7_n194(x) + end +end + +def fun_l6_n390(x) + if (x < 1) + fun_l7_n261(x) + else + fun_l7_n30(x) + end +end + +def fun_l6_n391(x) + if (x < 1) + fun_l7_n746(x) + else + fun_l7_n207(x) + end +end + +def fun_l6_n392(x) + if (x < 1) + fun_l7_n866(x) + else + fun_l7_n862(x) + end +end + +def fun_l6_n393(x) + if (x < 1) + fun_l7_n47(x) + else + fun_l7_n692(x) + end +end + +def fun_l6_n394(x) + if (x < 1) + fun_l7_n140(x) + else + fun_l7_n104(x) + end +end + +def fun_l6_n395(x) + if (x < 1) + fun_l7_n170(x) + else + fun_l7_n93(x) + end +end + +def fun_l6_n396(x) + if (x < 1) + fun_l7_n184(x) + else + fun_l7_n218(x) + end +end + +def fun_l6_n397(x) + if (x < 1) + fun_l7_n268(x) + else + fun_l7_n278(x) + end +end + +def fun_l6_n398(x) + if (x < 1) + fun_l7_n859(x) + else + fun_l7_n888(x) + end +end + +def fun_l6_n399(x) + if (x < 1) + fun_l7_n540(x) + else + fun_l7_n218(x) + end +end + +def fun_l6_n400(x) + if (x < 1) + fun_l7_n148(x) + else + fun_l7_n220(x) + end +end + +def fun_l6_n401(x) + if (x < 1) + fun_l7_n169(x) + else + fun_l7_n310(x) + end +end + +def fun_l6_n402(x) + if (x < 1) + fun_l7_n256(x) + else + fun_l7_n336(x) + end +end + +def fun_l6_n403(x) + if (x < 1) + fun_l7_n257(x) + else + fun_l7_n536(x) + end +end + +def fun_l6_n404(x) + if (x < 1) + fun_l7_n47(x) + else + fun_l7_n714(x) + end +end + +def fun_l6_n405(x) + if (x < 1) + fun_l7_n913(x) + else + fun_l7_n705(x) + end +end + +def fun_l6_n406(x) + if (x < 1) + fun_l7_n816(x) + else + fun_l7_n168(x) + end +end + +def fun_l6_n407(x) + if (x < 1) + fun_l7_n506(x) + else + fun_l7_n772(x) + end +end + +def fun_l6_n408(x) + if (x < 1) + fun_l7_n983(x) + else + fun_l7_n973(x) + end +end + +def fun_l6_n409(x) + if (x < 1) + fun_l7_n752(x) + else + fun_l7_n543(x) + end +end + +def fun_l6_n410(x) + if (x < 1) + fun_l7_n580(x) + else + fun_l7_n265(x) + end +end + +def fun_l6_n411(x) + if (x < 1) + fun_l7_n744(x) + else + fun_l7_n736(x) + end +end + +def fun_l6_n412(x) + if (x < 1) + fun_l7_n950(x) + else + fun_l7_n5(x) + end +end + +def fun_l6_n413(x) + if (x < 1) + fun_l7_n734(x) + else + fun_l7_n151(x) + end +end + +def fun_l6_n414(x) + if (x < 1) + fun_l7_n907(x) + else + fun_l7_n113(x) + end +end + +def fun_l6_n415(x) + if (x < 1) + fun_l7_n621(x) + else + fun_l7_n272(x) + end +end + +def fun_l6_n416(x) + if (x < 1) + fun_l7_n598(x) + else + fun_l7_n872(x) + end +end + +def fun_l6_n417(x) + if (x < 1) + fun_l7_n811(x) + else + fun_l7_n734(x) + end +end + +def fun_l6_n418(x) + if (x < 1) + fun_l7_n18(x) + else + fun_l7_n405(x) + end +end + +def fun_l6_n419(x) + if (x < 1) + fun_l7_n89(x) + else + fun_l7_n153(x) + end +end + +def fun_l6_n420(x) + if (x < 1) + fun_l7_n438(x) + else + fun_l7_n452(x) + end +end + +def fun_l6_n421(x) + if (x < 1) + fun_l7_n601(x) + else + fun_l7_n777(x) + end +end + +def fun_l6_n422(x) + if (x < 1) + fun_l7_n202(x) + else + fun_l7_n368(x) + end +end + +def fun_l6_n423(x) + if (x < 1) + fun_l7_n636(x) + else + fun_l7_n137(x) + end +end + +def fun_l6_n424(x) + if (x < 1) + fun_l7_n222(x) + else + fun_l7_n838(x) + end +end + +def fun_l6_n425(x) + if (x < 1) + fun_l7_n388(x) + else + fun_l7_n175(x) + end +end + +def fun_l6_n426(x) + if (x < 1) + fun_l7_n629(x) + else + fun_l7_n376(x) + end +end + +def fun_l6_n427(x) + if (x < 1) + fun_l7_n293(x) + else + fun_l7_n517(x) + end +end + +def fun_l6_n428(x) + if (x < 1) + fun_l7_n859(x) + else + fun_l7_n129(x) + end +end + +def fun_l6_n429(x) + if (x < 1) + fun_l7_n854(x) + else + fun_l7_n647(x) + end +end + +def fun_l6_n430(x) + if (x < 1) + fun_l7_n117(x) + else + fun_l7_n291(x) + end +end + +def fun_l6_n431(x) + if (x < 1) + fun_l7_n505(x) + else + fun_l7_n938(x) + end +end + +def fun_l6_n432(x) + if (x < 1) + fun_l7_n536(x) + else + fun_l7_n303(x) + end +end + +def fun_l6_n433(x) + if (x < 1) + fun_l7_n443(x) + else + fun_l7_n945(x) + end +end + +def fun_l6_n434(x) + if (x < 1) + fun_l7_n74(x) + else + fun_l7_n594(x) + end +end + +def fun_l6_n435(x) + if (x < 1) + fun_l7_n273(x) + else + fun_l7_n704(x) + end +end + +def fun_l6_n436(x) + if (x < 1) + fun_l7_n451(x) + else + fun_l7_n371(x) + end +end + +def fun_l6_n437(x) + if (x < 1) + fun_l7_n628(x) + else + fun_l7_n963(x) + end +end + +def fun_l6_n438(x) + if (x < 1) + fun_l7_n361(x) + else + fun_l7_n506(x) + end +end + +def fun_l6_n439(x) + if (x < 1) + fun_l7_n8(x) + else + fun_l7_n721(x) + end +end + +def fun_l6_n440(x) + if (x < 1) + fun_l7_n728(x) + else + fun_l7_n372(x) + end +end + +def fun_l6_n441(x) + if (x < 1) + fun_l7_n988(x) + else + fun_l7_n323(x) + end +end + +def fun_l6_n442(x) + if (x < 1) + fun_l7_n5(x) + else + fun_l7_n56(x) + end +end + +def fun_l6_n443(x) + if (x < 1) + fun_l7_n553(x) + else + fun_l7_n776(x) + end +end + +def fun_l6_n444(x) + if (x < 1) + fun_l7_n194(x) + else + fun_l7_n101(x) + end +end + +def fun_l6_n445(x) + if (x < 1) + fun_l7_n613(x) + else + fun_l7_n977(x) + end +end + +def fun_l6_n446(x) + if (x < 1) + fun_l7_n23(x) + else + fun_l7_n311(x) + end +end + +def fun_l6_n447(x) + if (x < 1) + fun_l7_n686(x) + else + fun_l7_n8(x) + end +end + +def fun_l6_n448(x) + if (x < 1) + fun_l7_n812(x) + else + fun_l7_n229(x) + end +end + +def fun_l6_n449(x) + if (x < 1) + fun_l7_n222(x) + else + fun_l7_n620(x) + end +end + +def fun_l6_n450(x) + if (x < 1) + fun_l7_n599(x) + else + fun_l7_n468(x) + end +end + +def fun_l6_n451(x) + if (x < 1) + fun_l7_n347(x) + else + fun_l7_n504(x) + end +end + +def fun_l6_n452(x) + if (x < 1) + fun_l7_n95(x) + else + fun_l7_n482(x) + end +end + +def fun_l6_n453(x) + if (x < 1) + fun_l7_n217(x) + else + fun_l7_n419(x) + end +end + +def fun_l6_n454(x) + if (x < 1) + fun_l7_n28(x) + else + fun_l7_n609(x) + end +end + +def fun_l6_n455(x) + if (x < 1) + fun_l7_n932(x) + else + fun_l7_n744(x) + end +end + +def fun_l6_n456(x) + if (x < 1) + fun_l7_n901(x) + else + fun_l7_n882(x) + end +end + +def fun_l6_n457(x) + if (x < 1) + fun_l7_n368(x) + else + fun_l7_n441(x) + end +end + +def fun_l6_n458(x) + if (x < 1) + fun_l7_n49(x) + else + fun_l7_n135(x) + end +end + +def fun_l6_n459(x) + if (x < 1) + fun_l7_n228(x) + else + fun_l7_n899(x) + end +end + +def fun_l6_n460(x) + if (x < 1) + fun_l7_n90(x) + else + fun_l7_n190(x) + end +end + +def fun_l6_n461(x) + if (x < 1) + fun_l7_n892(x) + else + fun_l7_n670(x) + end +end + +def fun_l6_n462(x) + if (x < 1) + fun_l7_n961(x) + else + fun_l7_n769(x) + end +end + +def fun_l6_n463(x) + if (x < 1) + fun_l7_n828(x) + else + fun_l7_n219(x) + end +end + +def fun_l6_n464(x) + if (x < 1) + fun_l7_n17(x) + else + fun_l7_n345(x) + end +end + +def fun_l6_n465(x) + if (x < 1) + fun_l7_n412(x) + else + fun_l7_n498(x) + end +end + +def fun_l6_n466(x) + if (x < 1) + fun_l7_n659(x) + else + fun_l7_n781(x) + end +end + +def fun_l6_n467(x) + if (x < 1) + fun_l7_n528(x) + else + fun_l7_n138(x) + end +end + +def fun_l6_n468(x) + if (x < 1) + fun_l7_n272(x) + else + fun_l7_n512(x) + end +end + +def fun_l6_n469(x) + if (x < 1) + fun_l7_n458(x) + else + fun_l7_n430(x) + end +end + +def fun_l6_n470(x) + if (x < 1) + fun_l7_n192(x) + else + fun_l7_n755(x) + end +end + +def fun_l6_n471(x) + if (x < 1) + fun_l7_n188(x) + else + fun_l7_n827(x) + end +end + +def fun_l6_n472(x) + if (x < 1) + fun_l7_n467(x) + else + fun_l7_n167(x) + end +end + +def fun_l6_n473(x) + if (x < 1) + fun_l7_n648(x) + else + fun_l7_n823(x) + end +end + +def fun_l6_n474(x) + if (x < 1) + fun_l7_n788(x) + else + fun_l7_n120(x) + end +end + +def fun_l6_n475(x) + if (x < 1) + fun_l7_n199(x) + else + fun_l7_n25(x) + end +end + +def fun_l6_n476(x) + if (x < 1) + fun_l7_n812(x) + else + fun_l7_n258(x) + end +end + +def fun_l6_n477(x) + if (x < 1) + fun_l7_n525(x) + else + fun_l7_n140(x) + end +end + +def fun_l6_n478(x) + if (x < 1) + fun_l7_n728(x) + else + fun_l7_n157(x) + end +end + +def fun_l6_n479(x) + if (x < 1) + fun_l7_n527(x) + else + fun_l7_n172(x) + end +end + +def fun_l6_n480(x) + if (x < 1) + fun_l7_n295(x) + else + fun_l7_n230(x) + end +end + +def fun_l6_n481(x) + if (x < 1) + fun_l7_n619(x) + else + fun_l7_n495(x) + end +end + +def fun_l6_n482(x) + if (x < 1) + fun_l7_n412(x) + else + fun_l7_n30(x) + end +end + +def fun_l6_n483(x) + if (x < 1) + fun_l7_n236(x) + else + fun_l7_n842(x) + end +end + +def fun_l6_n484(x) + if (x < 1) + fun_l7_n59(x) + else + fun_l7_n341(x) + end +end + +def fun_l6_n485(x) + if (x < 1) + fun_l7_n841(x) + else + fun_l7_n67(x) + end +end + +def fun_l6_n486(x) + if (x < 1) + fun_l7_n299(x) + else + fun_l7_n144(x) + end +end + +def fun_l6_n487(x) + if (x < 1) + fun_l7_n672(x) + else + fun_l7_n682(x) + end +end + +def fun_l6_n488(x) + if (x < 1) + fun_l7_n110(x) + else + fun_l7_n231(x) + end +end + +def fun_l6_n489(x) + if (x < 1) + fun_l7_n984(x) + else + fun_l7_n583(x) + end +end + +def fun_l6_n490(x) + if (x < 1) + fun_l7_n354(x) + else + fun_l7_n90(x) + end +end + +def fun_l6_n491(x) + if (x < 1) + fun_l7_n541(x) + else + fun_l7_n583(x) + end +end + +def fun_l6_n492(x) + if (x < 1) + fun_l7_n35(x) + else + fun_l7_n209(x) + end +end + +def fun_l6_n493(x) + if (x < 1) + fun_l7_n547(x) + else + fun_l7_n982(x) + end +end + +def fun_l6_n494(x) + if (x < 1) + fun_l7_n3(x) + else + fun_l7_n230(x) + end +end + +def fun_l6_n495(x) + if (x < 1) + fun_l7_n777(x) + else + fun_l7_n140(x) + end +end + +def fun_l6_n496(x) + if (x < 1) + fun_l7_n927(x) + else + fun_l7_n934(x) + end +end + +def fun_l6_n497(x) + if (x < 1) + fun_l7_n201(x) + else + fun_l7_n342(x) + end +end + +def fun_l6_n498(x) + if (x < 1) + fun_l7_n973(x) + else + fun_l7_n106(x) + end +end + +def fun_l6_n499(x) + if (x < 1) + fun_l7_n373(x) + else + fun_l7_n558(x) + end +end + +def fun_l6_n500(x) + if (x < 1) + fun_l7_n835(x) + else + fun_l7_n981(x) + end +end + +def fun_l6_n501(x) + if (x < 1) + fun_l7_n135(x) + else + fun_l7_n997(x) + end +end + +def fun_l6_n502(x) + if (x < 1) + fun_l7_n129(x) + else + fun_l7_n530(x) + end +end + +def fun_l6_n503(x) + if (x < 1) + fun_l7_n924(x) + else + fun_l7_n611(x) + end +end + +def fun_l6_n504(x) + if (x < 1) + fun_l7_n125(x) + else + fun_l7_n26(x) + end +end + +def fun_l6_n505(x) + if (x < 1) + fun_l7_n592(x) + else + fun_l7_n50(x) + end +end + +def fun_l6_n506(x) + if (x < 1) + fun_l7_n220(x) + else + fun_l7_n787(x) + end +end + +def fun_l6_n507(x) + if (x < 1) + fun_l7_n908(x) + else + fun_l7_n15(x) + end +end + +def fun_l6_n508(x) + if (x < 1) + fun_l7_n475(x) + else + fun_l7_n899(x) + end +end + +def fun_l6_n509(x) + if (x < 1) + fun_l7_n704(x) + else + fun_l7_n559(x) + end +end + +def fun_l6_n510(x) + if (x < 1) + fun_l7_n625(x) + else + fun_l7_n73(x) + end +end + +def fun_l6_n511(x) + if (x < 1) + fun_l7_n234(x) + else + fun_l7_n166(x) + end +end + +def fun_l6_n512(x) + if (x < 1) + fun_l7_n502(x) + else + fun_l7_n304(x) + end +end + +def fun_l6_n513(x) + if (x < 1) + fun_l7_n686(x) + else + fun_l7_n643(x) + end +end + +def fun_l6_n514(x) + if (x < 1) + fun_l7_n804(x) + else + fun_l7_n116(x) + end +end + +def fun_l6_n515(x) + if (x < 1) + fun_l7_n365(x) + else + fun_l7_n102(x) + end +end + +def fun_l6_n516(x) + if (x < 1) + fun_l7_n563(x) + else + fun_l7_n161(x) + end +end + +def fun_l6_n517(x) + if (x < 1) + fun_l7_n695(x) + else + fun_l7_n936(x) + end +end + +def fun_l6_n518(x) + if (x < 1) + fun_l7_n220(x) + else + fun_l7_n884(x) + end +end + +def fun_l6_n519(x) + if (x < 1) + fun_l7_n602(x) + else + fun_l7_n144(x) + end +end + +def fun_l6_n520(x) + if (x < 1) + fun_l7_n409(x) + else + fun_l7_n861(x) + end +end + +def fun_l6_n521(x) + if (x < 1) + fun_l7_n258(x) + else + fun_l7_n768(x) + end +end + +def fun_l6_n522(x) + if (x < 1) + fun_l7_n878(x) + else + fun_l7_n503(x) + end +end + +def fun_l6_n523(x) + if (x < 1) + fun_l7_n570(x) + else + fun_l7_n675(x) + end +end + +def fun_l6_n524(x) + if (x < 1) + fun_l7_n741(x) + else + fun_l7_n748(x) + end +end + +def fun_l6_n525(x) + if (x < 1) + fun_l7_n729(x) + else + fun_l7_n272(x) + end +end + +def fun_l6_n526(x) + if (x < 1) + fun_l7_n734(x) + else + fun_l7_n70(x) + end +end + +def fun_l6_n527(x) + if (x < 1) + fun_l7_n235(x) + else + fun_l7_n606(x) + end +end + +def fun_l6_n528(x) + if (x < 1) + fun_l7_n67(x) + else + fun_l7_n399(x) + end +end + +def fun_l6_n529(x) + if (x < 1) + fun_l7_n706(x) + else + fun_l7_n150(x) + end +end + +def fun_l6_n530(x) + if (x < 1) + fun_l7_n35(x) + else + fun_l7_n951(x) + end +end + +def fun_l6_n531(x) + if (x < 1) + fun_l7_n517(x) + else + fun_l7_n329(x) + end +end + +def fun_l6_n532(x) + if (x < 1) + fun_l7_n392(x) + else + fun_l7_n970(x) + end +end + +def fun_l6_n533(x) + if (x < 1) + fun_l7_n466(x) + else + fun_l7_n260(x) + end +end + +def fun_l6_n534(x) + if (x < 1) + fun_l7_n957(x) + else + fun_l7_n417(x) + end +end + +def fun_l6_n535(x) + if (x < 1) + fun_l7_n184(x) + else + fun_l7_n188(x) + end +end + +def fun_l6_n536(x) + if (x < 1) + fun_l7_n298(x) + else + fun_l7_n192(x) + end +end + +def fun_l6_n537(x) + if (x < 1) + fun_l7_n28(x) + else + fun_l7_n309(x) + end +end + +def fun_l6_n538(x) + if (x < 1) + fun_l7_n801(x) + else + fun_l7_n84(x) + end +end + +def fun_l6_n539(x) + if (x < 1) + fun_l7_n894(x) + else + fun_l7_n973(x) + end +end + +def fun_l6_n540(x) + if (x < 1) + fun_l7_n895(x) + else + fun_l7_n231(x) + end +end + +def fun_l6_n541(x) + if (x < 1) + fun_l7_n728(x) + else + fun_l7_n28(x) + end +end + +def fun_l6_n542(x) + if (x < 1) + fun_l7_n655(x) + else + fun_l7_n845(x) + end +end + +def fun_l6_n543(x) + if (x < 1) + fun_l7_n952(x) + else + fun_l7_n484(x) + end +end + +def fun_l6_n544(x) + if (x < 1) + fun_l7_n835(x) + else + fun_l7_n187(x) + end +end + +def fun_l6_n545(x) + if (x < 1) + fun_l7_n748(x) + else + fun_l7_n460(x) + end +end + +def fun_l6_n546(x) + if (x < 1) + fun_l7_n734(x) + else + fun_l7_n165(x) + end +end + +def fun_l6_n547(x) + if (x < 1) + fun_l7_n499(x) + else + fun_l7_n133(x) + end +end + +def fun_l6_n548(x) + if (x < 1) + fun_l7_n751(x) + else + fun_l7_n731(x) + end +end + +def fun_l6_n549(x) + if (x < 1) + fun_l7_n269(x) + else + fun_l7_n690(x) + end +end + +def fun_l6_n550(x) + if (x < 1) + fun_l7_n320(x) + else + fun_l7_n308(x) + end +end + +def fun_l6_n551(x) + if (x < 1) + fun_l7_n182(x) + else + fun_l7_n144(x) + end +end + +def fun_l6_n552(x) + if (x < 1) + fun_l7_n683(x) + else + fun_l7_n691(x) + end +end + +def fun_l6_n553(x) + if (x < 1) + fun_l7_n502(x) + else + fun_l7_n520(x) + end +end + +def fun_l6_n554(x) + if (x < 1) + fun_l7_n60(x) + else + fun_l7_n551(x) + end +end + +def fun_l6_n555(x) + if (x < 1) + fun_l7_n185(x) + else + fun_l7_n87(x) + end +end + +def fun_l6_n556(x) + if (x < 1) + fun_l7_n140(x) + else + fun_l7_n725(x) + end +end + +def fun_l6_n557(x) + if (x < 1) + fun_l7_n76(x) + else + fun_l7_n501(x) + end +end + +def fun_l6_n558(x) + if (x < 1) + fun_l7_n553(x) + else + fun_l7_n146(x) + end +end + +def fun_l6_n559(x) + if (x < 1) + fun_l7_n535(x) + else + fun_l7_n17(x) + end +end + +def fun_l6_n560(x) + if (x < 1) + fun_l7_n566(x) + else + fun_l7_n773(x) + end +end + +def fun_l6_n561(x) + if (x < 1) + fun_l7_n358(x) + else + fun_l7_n951(x) + end +end + +def fun_l6_n562(x) + if (x < 1) + fun_l7_n492(x) + else + fun_l7_n478(x) + end +end + +def fun_l6_n563(x) + if (x < 1) + fun_l7_n796(x) + else + fun_l7_n906(x) + end +end + +def fun_l6_n564(x) + if (x < 1) + fun_l7_n751(x) + else + fun_l7_n546(x) + end +end + +def fun_l6_n565(x) + if (x < 1) + fun_l7_n179(x) + else + fun_l7_n49(x) + end +end + +def fun_l6_n566(x) + if (x < 1) + fun_l7_n550(x) + else + fun_l7_n440(x) + end +end + +def fun_l6_n567(x) + if (x < 1) + fun_l7_n715(x) + else + fun_l7_n862(x) + end +end + +def fun_l6_n568(x) + if (x < 1) + fun_l7_n124(x) + else + fun_l7_n191(x) + end +end + +def fun_l6_n569(x) + if (x < 1) + fun_l7_n709(x) + else + fun_l7_n704(x) + end +end + +def fun_l6_n570(x) + if (x < 1) + fun_l7_n864(x) + else + fun_l7_n84(x) + end +end + +def fun_l6_n571(x) + if (x < 1) + fun_l7_n302(x) + else + fun_l7_n424(x) + end +end + +def fun_l6_n572(x) + if (x < 1) + fun_l7_n488(x) + else + fun_l7_n570(x) + end +end + +def fun_l6_n573(x) + if (x < 1) + fun_l7_n590(x) + else + fun_l7_n560(x) + end +end + +def fun_l6_n574(x) + if (x < 1) + fun_l7_n38(x) + else + fun_l7_n444(x) + end +end + +def fun_l6_n575(x) + if (x < 1) + fun_l7_n401(x) + else + fun_l7_n359(x) + end +end + +def fun_l6_n576(x) + if (x < 1) + fun_l7_n518(x) + else + fun_l7_n240(x) + end +end + +def fun_l6_n577(x) + if (x < 1) + fun_l7_n247(x) + else + fun_l7_n540(x) + end +end + +def fun_l6_n578(x) + if (x < 1) + fun_l7_n223(x) + else + fun_l7_n729(x) + end +end + +def fun_l6_n579(x) + if (x < 1) + fun_l7_n524(x) + else + fun_l7_n684(x) + end +end + +def fun_l6_n580(x) + if (x < 1) + fun_l7_n113(x) + else + fun_l7_n865(x) + end +end + +def fun_l6_n581(x) + if (x < 1) + fun_l7_n920(x) + else + fun_l7_n238(x) + end +end + +def fun_l6_n582(x) + if (x < 1) + fun_l7_n78(x) + else + fun_l7_n85(x) + end +end + +def fun_l6_n583(x) + if (x < 1) + fun_l7_n713(x) + else + fun_l7_n110(x) + end +end + +def fun_l6_n584(x) + if (x < 1) + fun_l7_n170(x) + else + fun_l7_n183(x) + end +end + +def fun_l6_n585(x) + if (x < 1) + fun_l7_n100(x) + else + fun_l7_n215(x) + end +end + +def fun_l6_n586(x) + if (x < 1) + fun_l7_n126(x) + else + fun_l7_n136(x) + end +end + +def fun_l6_n587(x) + if (x < 1) + fun_l7_n592(x) + else + fun_l7_n502(x) + end +end + +def fun_l6_n588(x) + if (x < 1) + fun_l7_n155(x) + else + fun_l7_n591(x) + end +end + +def fun_l6_n589(x) + if (x < 1) + fun_l7_n840(x) + else + fun_l7_n91(x) + end +end + +def fun_l6_n590(x) + if (x < 1) + fun_l7_n146(x) + else + fun_l7_n849(x) + end +end + +def fun_l6_n591(x) + if (x < 1) + fun_l7_n161(x) + else + fun_l7_n884(x) + end +end + +def fun_l6_n592(x) + if (x < 1) + fun_l7_n994(x) + else + fun_l7_n341(x) + end +end + +def fun_l6_n593(x) + if (x < 1) + fun_l7_n974(x) + else + fun_l7_n355(x) + end +end + +def fun_l6_n594(x) + if (x < 1) + fun_l7_n726(x) + else + fun_l7_n266(x) + end +end + +def fun_l6_n595(x) + if (x < 1) + fun_l7_n142(x) + else + fun_l7_n154(x) + end +end + +def fun_l6_n596(x) + if (x < 1) + fun_l7_n287(x) + else + fun_l7_n155(x) + end +end + +def fun_l6_n597(x) + if (x < 1) + fun_l7_n594(x) + else + fun_l7_n424(x) + end +end + +def fun_l6_n598(x) + if (x < 1) + fun_l7_n227(x) + else + fun_l7_n445(x) + end +end + +def fun_l6_n599(x) + if (x < 1) + fun_l7_n660(x) + else + fun_l7_n464(x) + end +end + +def fun_l6_n600(x) + if (x < 1) + fun_l7_n930(x) + else + fun_l7_n520(x) + end +end + +def fun_l6_n601(x) + if (x < 1) + fun_l7_n714(x) + else + fun_l7_n984(x) + end +end + +def fun_l6_n602(x) + if (x < 1) + fun_l7_n226(x) + else + fun_l7_n316(x) + end +end + +def fun_l6_n603(x) + if (x < 1) + fun_l7_n104(x) + else + fun_l7_n563(x) + end +end + +def fun_l6_n604(x) + if (x < 1) + fun_l7_n149(x) + else + fun_l7_n921(x) + end +end + +def fun_l6_n605(x) + if (x < 1) + fun_l7_n195(x) + else + fun_l7_n696(x) + end +end + +def fun_l6_n606(x) + if (x < 1) + fun_l7_n337(x) + else + fun_l7_n347(x) + end +end + +def fun_l6_n607(x) + if (x < 1) + fun_l7_n657(x) + else + fun_l7_n67(x) + end +end + +def fun_l6_n608(x) + if (x < 1) + fun_l7_n796(x) + else + fun_l7_n589(x) + end +end + +def fun_l6_n609(x) + if (x < 1) + fun_l7_n230(x) + else + fun_l7_n769(x) + end +end + +def fun_l6_n610(x) + if (x < 1) + fun_l7_n427(x) + else + fun_l7_n892(x) + end +end + +def fun_l6_n611(x) + if (x < 1) + fun_l7_n741(x) + else + fun_l7_n567(x) + end +end + +def fun_l6_n612(x) + if (x < 1) + fun_l7_n471(x) + else + fun_l7_n824(x) + end +end + +def fun_l6_n613(x) + if (x < 1) + fun_l7_n522(x) + else + fun_l7_n694(x) + end +end + +def fun_l6_n614(x) + if (x < 1) + fun_l7_n95(x) + else + fun_l7_n84(x) + end +end + +def fun_l6_n615(x) + if (x < 1) + fun_l7_n632(x) + else + fun_l7_n590(x) + end +end + +def fun_l6_n616(x) + if (x < 1) + fun_l7_n372(x) + else + fun_l7_n659(x) + end +end + +def fun_l6_n617(x) + if (x < 1) + fun_l7_n547(x) + else + fun_l7_n321(x) + end +end + +def fun_l6_n618(x) + if (x < 1) + fun_l7_n53(x) + else + fun_l7_n723(x) + end +end + +def fun_l6_n619(x) + if (x < 1) + fun_l7_n653(x) + else + fun_l7_n740(x) + end +end + +def fun_l6_n620(x) + if (x < 1) + fun_l7_n16(x) + else + fun_l7_n228(x) + end +end + +def fun_l6_n621(x) + if (x < 1) + fun_l7_n655(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n622(x) + if (x < 1) + fun_l7_n212(x) + else + fun_l7_n692(x) + end +end + +def fun_l6_n623(x) + if (x < 1) + fun_l7_n959(x) + else + fun_l7_n327(x) + end +end + +def fun_l6_n624(x) + if (x < 1) + fun_l7_n607(x) + else + fun_l7_n168(x) + end +end + +def fun_l6_n625(x) + if (x < 1) + fun_l7_n229(x) + else + fun_l7_n584(x) + end +end + +def fun_l6_n626(x) + if (x < 1) + fun_l7_n776(x) + else + fun_l7_n284(x) + end +end + +def fun_l6_n627(x) + if (x < 1) + fun_l7_n770(x) + else + fun_l7_n169(x) + end +end + +def fun_l6_n628(x) + if (x < 1) + fun_l7_n550(x) + else + fun_l7_n918(x) + end +end + +def fun_l6_n629(x) + if (x < 1) + fun_l7_n450(x) + else + fun_l7_n654(x) + end +end + +def fun_l6_n630(x) + if (x < 1) + fun_l7_n968(x) + else + fun_l7_n770(x) + end +end + +def fun_l6_n631(x) + if (x < 1) + fun_l7_n118(x) + else + fun_l7_n411(x) + end +end + +def fun_l6_n632(x) + if (x < 1) + fun_l7_n352(x) + else + fun_l7_n840(x) + end +end + +def fun_l6_n633(x) + if (x < 1) + fun_l7_n588(x) + else + fun_l7_n810(x) + end +end + +def fun_l6_n634(x) + if (x < 1) + fun_l7_n955(x) + else + fun_l7_n709(x) + end +end + +def fun_l6_n635(x) + if (x < 1) + fun_l7_n137(x) + else + fun_l7_n239(x) + end +end + +def fun_l6_n636(x) + if (x < 1) + fun_l7_n955(x) + else + fun_l7_n87(x) + end +end + +def fun_l6_n637(x) + if (x < 1) + fun_l7_n479(x) + else + fun_l7_n91(x) + end +end + +def fun_l6_n638(x) + if (x < 1) + fun_l7_n366(x) + else + fun_l7_n388(x) + end +end + +def fun_l6_n639(x) + if (x < 1) + fun_l7_n90(x) + else + fun_l7_n971(x) + end +end + +def fun_l6_n640(x) + if (x < 1) + fun_l7_n330(x) + else + fun_l7_n415(x) + end +end + +def fun_l6_n641(x) + if (x < 1) + fun_l7_n233(x) + else + fun_l7_n653(x) + end +end + +def fun_l6_n642(x) + if (x < 1) + fun_l7_n106(x) + else + fun_l7_n440(x) + end +end + +def fun_l6_n643(x) + if (x < 1) + fun_l7_n156(x) + else + fun_l7_n818(x) + end +end + +def fun_l6_n644(x) + if (x < 1) + fun_l7_n68(x) + else + fun_l7_n763(x) + end +end + +def fun_l6_n645(x) + if (x < 1) + fun_l7_n858(x) + else + fun_l7_n465(x) + end +end + +def fun_l6_n646(x) + if (x < 1) + fun_l7_n886(x) + else + fun_l7_n86(x) + end +end + +def fun_l6_n647(x) + if (x < 1) + fun_l7_n689(x) + else + fun_l7_n964(x) + end +end + +def fun_l6_n648(x) + if (x < 1) + fun_l7_n748(x) + else + fun_l7_n214(x) + end +end + +def fun_l6_n649(x) + if (x < 1) + fun_l7_n830(x) + else + fun_l7_n567(x) + end +end + +def fun_l6_n650(x) + if (x < 1) + fun_l7_n907(x) + else + fun_l7_n957(x) + end +end + +def fun_l6_n651(x) + if (x < 1) + fun_l7_n242(x) + else + fun_l7_n239(x) + end +end + +def fun_l6_n652(x) + if (x < 1) + fun_l7_n347(x) + else + fun_l7_n63(x) + end +end + +def fun_l6_n653(x) + if (x < 1) + fun_l7_n480(x) + else + fun_l7_n441(x) + end +end + +def fun_l6_n654(x) + if (x < 1) + fun_l7_n304(x) + else + fun_l7_n690(x) + end +end + +def fun_l6_n655(x) + if (x < 1) + fun_l7_n511(x) + else + fun_l7_n710(x) + end +end + +def fun_l6_n656(x) + if (x < 1) + fun_l7_n202(x) + else + fun_l7_n48(x) + end +end + +def fun_l6_n657(x) + if (x < 1) + fun_l7_n232(x) + else + fun_l7_n919(x) + end +end + +def fun_l6_n658(x) + if (x < 1) + fun_l7_n627(x) + else + fun_l7_n620(x) + end +end + +def fun_l6_n659(x) + if (x < 1) + fun_l7_n716(x) + else + fun_l7_n116(x) + end +end + +def fun_l6_n660(x) + if (x < 1) + fun_l7_n105(x) + else + fun_l7_n536(x) + end +end + +def fun_l6_n661(x) + if (x < 1) + fun_l7_n376(x) + else + fun_l7_n965(x) + end +end + +def fun_l6_n662(x) + if (x < 1) + fun_l7_n417(x) + else + fun_l7_n726(x) + end +end + +def fun_l6_n663(x) + if (x < 1) + fun_l7_n567(x) + else + fun_l7_n948(x) + end +end + +def fun_l6_n664(x) + if (x < 1) + fun_l7_n640(x) + else + fun_l7_n910(x) + end +end + +def fun_l6_n665(x) + if (x < 1) + fun_l7_n874(x) + else + fun_l7_n314(x) + end +end + +def fun_l6_n666(x) + if (x < 1) + fun_l7_n946(x) + else + fun_l7_n101(x) + end +end + +def fun_l6_n667(x) + if (x < 1) + fun_l7_n960(x) + else + fun_l7_n199(x) + end +end + +def fun_l6_n668(x) + if (x < 1) + fun_l7_n389(x) + else + fun_l7_n976(x) + end +end + +def fun_l6_n669(x) + if (x < 1) + fun_l7_n31(x) + else + fun_l7_n903(x) + end +end + +def fun_l6_n670(x) + if (x < 1) + fun_l7_n288(x) + else + fun_l7_n115(x) + end +end + +def fun_l6_n671(x) + if (x < 1) + fun_l7_n418(x) + else + fun_l7_n249(x) + end +end + +def fun_l6_n672(x) + if (x < 1) + fun_l7_n733(x) + else + fun_l7_n815(x) + end +end + +def fun_l6_n673(x) + if (x < 1) + fun_l7_n227(x) + else + fun_l7_n23(x) + end +end + +def fun_l6_n674(x) + if (x < 1) + fun_l7_n936(x) + else + fun_l7_n386(x) + end +end + +def fun_l6_n675(x) + if (x < 1) + fun_l7_n638(x) + else + fun_l7_n39(x) + end +end + +def fun_l6_n676(x) + if (x < 1) + fun_l7_n304(x) + else + fun_l7_n35(x) + end +end + +def fun_l6_n677(x) + if (x < 1) + fun_l7_n676(x) + else + fun_l7_n443(x) + end +end + +def fun_l6_n678(x) + if (x < 1) + fun_l7_n648(x) + else + fun_l7_n453(x) + end +end + +def fun_l6_n679(x) + if (x < 1) + fun_l7_n15(x) + else + fun_l7_n220(x) + end +end + +def fun_l6_n680(x) + if (x < 1) + fun_l7_n201(x) + else + fun_l7_n842(x) + end +end + +def fun_l6_n681(x) + if (x < 1) + fun_l7_n67(x) + else + fun_l7_n73(x) + end +end + +def fun_l6_n682(x) + if (x < 1) + fun_l7_n280(x) + else + fun_l7_n370(x) + end +end + +def fun_l6_n683(x) + if (x < 1) + fun_l7_n822(x) + else + fun_l7_n27(x) + end +end + +def fun_l6_n684(x) + if (x < 1) + fun_l7_n720(x) + else + fun_l7_n651(x) + end +end + +def fun_l6_n685(x) + if (x < 1) + fun_l7_n414(x) + else + fun_l7_n257(x) + end +end + +def fun_l6_n686(x) + if (x < 1) + fun_l7_n477(x) + else + fun_l7_n883(x) + end +end + +def fun_l6_n687(x) + if (x < 1) + fun_l7_n467(x) + else + fun_l7_n739(x) + end +end + +def fun_l6_n688(x) + if (x < 1) + fun_l7_n421(x) + else + fun_l7_n271(x) + end +end + +def fun_l6_n689(x) + if (x < 1) + fun_l7_n444(x) + else + fun_l7_n601(x) + end +end + +def fun_l6_n690(x) + if (x < 1) + fun_l7_n104(x) + else + fun_l7_n597(x) + end +end + +def fun_l6_n691(x) + if (x < 1) + fun_l7_n273(x) + else + fun_l7_n79(x) + end +end + +def fun_l6_n692(x) + if (x < 1) + fun_l7_n310(x) + else + fun_l7_n261(x) + end +end + +def fun_l6_n693(x) + if (x < 1) + fun_l7_n190(x) + else + fun_l7_n330(x) + end +end + +def fun_l6_n694(x) + if (x < 1) + fun_l7_n103(x) + else + fun_l7_n258(x) + end +end + +def fun_l6_n695(x) + if (x < 1) + fun_l7_n524(x) + else + fun_l7_n988(x) + end +end + +def fun_l6_n696(x) + if (x < 1) + fun_l7_n885(x) + else + fun_l7_n731(x) + end +end + +def fun_l6_n697(x) + if (x < 1) + fun_l7_n212(x) + else + fun_l7_n98(x) + end +end + +def fun_l6_n698(x) + if (x < 1) + fun_l7_n735(x) + else + fun_l7_n682(x) + end +end + +def fun_l6_n699(x) + if (x < 1) + fun_l7_n610(x) + else + fun_l7_n512(x) + end +end + +def fun_l6_n700(x) + if (x < 1) + fun_l7_n828(x) + else + fun_l7_n651(x) + end +end + +def fun_l6_n701(x) + if (x < 1) + fun_l7_n269(x) + else + fun_l7_n192(x) + end +end + +def fun_l6_n702(x) + if (x < 1) + fun_l7_n775(x) + else + fun_l7_n334(x) + end +end + +def fun_l6_n703(x) + if (x < 1) + fun_l7_n880(x) + else + fun_l7_n396(x) + end +end + +def fun_l6_n704(x) + if (x < 1) + fun_l7_n907(x) + else + fun_l7_n107(x) + end +end + +def fun_l6_n705(x) + if (x < 1) + fun_l7_n425(x) + else + fun_l7_n555(x) + end +end + +def fun_l6_n706(x) + if (x < 1) + fun_l7_n458(x) + else + fun_l7_n610(x) + end +end + +def fun_l6_n707(x) + if (x < 1) + fun_l7_n527(x) + else + fun_l7_n69(x) + end +end + +def fun_l6_n708(x) + if (x < 1) + fun_l7_n518(x) + else + fun_l7_n87(x) + end +end + +def fun_l6_n709(x) + if (x < 1) + fun_l7_n441(x) + else + fun_l7_n533(x) + end +end + +def fun_l6_n710(x) + if (x < 1) + fun_l7_n872(x) + else + fun_l7_n896(x) + end +end + +def fun_l6_n711(x) + if (x < 1) + fun_l7_n388(x) + else + fun_l7_n476(x) + end +end + +def fun_l6_n712(x) + if (x < 1) + fun_l7_n913(x) + else + fun_l7_n304(x) + end +end + +def fun_l6_n713(x) + if (x < 1) + fun_l7_n203(x) + else + fun_l7_n457(x) + end +end + +def fun_l6_n714(x) + if (x < 1) + fun_l7_n593(x) + else + fun_l7_n921(x) + end +end + +def fun_l6_n715(x) + if (x < 1) + fun_l7_n452(x) + else + fun_l7_n68(x) + end +end + +def fun_l6_n716(x) + if (x < 1) + fun_l7_n203(x) + else + fun_l7_n362(x) + end +end + +def fun_l6_n717(x) + if (x < 1) + fun_l7_n455(x) + else + fun_l7_n199(x) + end +end + +def fun_l6_n718(x) + if (x < 1) + fun_l7_n500(x) + else + fun_l7_n272(x) + end +end + +def fun_l6_n719(x) + if (x < 1) + fun_l7_n970(x) + else + fun_l7_n572(x) + end +end + +def fun_l6_n720(x) + if (x < 1) + fun_l7_n74(x) + else + fun_l7_n246(x) + end +end + +def fun_l6_n721(x) + if (x < 1) + fun_l7_n943(x) + else + fun_l7_n640(x) + end +end + +def fun_l6_n722(x) + if (x < 1) + fun_l7_n106(x) + else + fun_l7_n387(x) + end +end + +def fun_l6_n723(x) + if (x < 1) + fun_l7_n474(x) + else + fun_l7_n530(x) + end +end + +def fun_l6_n724(x) + if (x < 1) + fun_l7_n246(x) + else + fun_l7_n387(x) + end +end + +def fun_l6_n725(x) + if (x < 1) + fun_l7_n572(x) + else + fun_l7_n874(x) + end +end + +def fun_l6_n726(x) + if (x < 1) + fun_l7_n858(x) + else + fun_l7_n71(x) + end +end + +def fun_l6_n727(x) + if (x < 1) + fun_l7_n615(x) + else + fun_l7_n14(x) + end +end + +def fun_l6_n728(x) + if (x < 1) + fun_l7_n840(x) + else + fun_l7_n779(x) + end +end + +def fun_l6_n729(x) + if (x < 1) + fun_l7_n811(x) + else + fun_l7_n981(x) + end +end + +def fun_l6_n730(x) + if (x < 1) + fun_l7_n196(x) + else + fun_l7_n731(x) + end +end + +def fun_l6_n731(x) + if (x < 1) + fun_l7_n202(x) + else + fun_l7_n781(x) + end +end + +def fun_l6_n732(x) + if (x < 1) + fun_l7_n867(x) + else + fun_l7_n770(x) + end +end + +def fun_l6_n733(x) + if (x < 1) + fun_l7_n90(x) + else + fun_l7_n937(x) + end +end + +def fun_l6_n734(x) + if (x < 1) + fun_l7_n890(x) + else + fun_l7_n937(x) + end +end + +def fun_l6_n735(x) + if (x < 1) + fun_l7_n967(x) + else + fun_l7_n235(x) + end +end + +def fun_l6_n736(x) + if (x < 1) + fun_l7_n612(x) + else + fun_l7_n140(x) + end +end + +def fun_l6_n737(x) + if (x < 1) + fun_l7_n156(x) + else + fun_l7_n600(x) + end +end + +def fun_l6_n738(x) + if (x < 1) + fun_l7_n462(x) + else + fun_l7_n907(x) + end +end + +def fun_l6_n739(x) + if (x < 1) + fun_l7_n226(x) + else + fun_l7_n83(x) + end +end + +def fun_l6_n740(x) + if (x < 1) + fun_l7_n419(x) + else + fun_l7_n95(x) + end +end + +def fun_l6_n741(x) + if (x < 1) + fun_l7_n358(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n742(x) + if (x < 1) + fun_l7_n451(x) + else + fun_l7_n700(x) + end +end + +def fun_l6_n743(x) + if (x < 1) + fun_l7_n561(x) + else + fun_l7_n383(x) + end +end + +def fun_l6_n744(x) + if (x < 1) + fun_l7_n28(x) + else + fun_l7_n56(x) + end +end + +def fun_l6_n745(x) + if (x < 1) + fun_l7_n127(x) + else + fun_l7_n113(x) + end +end + +def fun_l6_n746(x) + if (x < 1) + fun_l7_n767(x) + else + fun_l7_n907(x) + end +end + +def fun_l6_n747(x) + if (x < 1) + fun_l7_n174(x) + else + fun_l7_n955(x) + end +end + +def fun_l6_n748(x) + if (x < 1) + fun_l7_n51(x) + else + fun_l7_n951(x) + end +end + +def fun_l6_n749(x) + if (x < 1) + fun_l7_n172(x) + else + fun_l7_n847(x) + end +end + +def fun_l6_n750(x) + if (x < 1) + fun_l7_n240(x) + else + fun_l7_n869(x) + end +end + +def fun_l6_n751(x) + if (x < 1) + fun_l7_n435(x) + else + fun_l7_n747(x) + end +end + +def fun_l6_n752(x) + if (x < 1) + fun_l7_n673(x) + else + fun_l7_n454(x) + end +end + +def fun_l6_n753(x) + if (x < 1) + fun_l7_n98(x) + else + fun_l7_n66(x) + end +end + +def fun_l6_n754(x) + if (x < 1) + fun_l7_n63(x) + else + fun_l7_n943(x) + end +end + +def fun_l6_n755(x) + if (x < 1) + fun_l7_n863(x) + else + fun_l7_n155(x) + end +end + +def fun_l6_n756(x) + if (x < 1) + fun_l7_n197(x) + else + fun_l7_n807(x) + end +end + +def fun_l6_n757(x) + if (x < 1) + fun_l7_n992(x) + else + fun_l7_n615(x) + end +end + +def fun_l6_n758(x) + if (x < 1) + fun_l7_n172(x) + else + fun_l7_n507(x) + end +end + +def fun_l6_n759(x) + if (x < 1) + fun_l7_n756(x) + else + fun_l7_n599(x) + end +end + +def fun_l6_n760(x) + if (x < 1) + fun_l7_n876(x) + else + fun_l7_n185(x) + end +end + +def fun_l6_n761(x) + if (x < 1) + fun_l7_n522(x) + else + fun_l7_n301(x) + end +end + +def fun_l6_n762(x) + if (x < 1) + fun_l7_n994(x) + else + fun_l7_n408(x) + end +end + +def fun_l6_n763(x) + if (x < 1) + fun_l7_n201(x) + else + fun_l7_n304(x) + end +end + +def fun_l6_n764(x) + if (x < 1) + fun_l7_n200(x) + else + fun_l7_n123(x) + end +end + +def fun_l6_n765(x) + if (x < 1) + fun_l7_n156(x) + else + fun_l7_n117(x) + end +end + +def fun_l6_n766(x) + if (x < 1) + fun_l7_n918(x) + else + fun_l7_n416(x) + end +end + +def fun_l6_n767(x) + if (x < 1) + fun_l7_n538(x) + else + fun_l7_n335(x) + end +end + +def fun_l6_n768(x) + if (x < 1) + fun_l7_n699(x) + else + fun_l7_n980(x) + end +end + +def fun_l6_n769(x) + if (x < 1) + fun_l7_n903(x) + else + fun_l7_n195(x) + end +end + +def fun_l6_n770(x) + if (x < 1) + fun_l7_n419(x) + else + fun_l7_n523(x) + end +end + +def fun_l6_n771(x) + if (x < 1) + fun_l7_n221(x) + else + fun_l7_n39(x) + end +end + +def fun_l6_n772(x) + if (x < 1) + fun_l7_n369(x) + else + fun_l7_n227(x) + end +end + +def fun_l6_n773(x) + if (x < 1) + fun_l7_n861(x) + else + fun_l7_n252(x) + end +end + +def fun_l6_n774(x) + if (x < 1) + fun_l7_n682(x) + else + fun_l7_n42(x) + end +end + +def fun_l6_n775(x) + if (x < 1) + fun_l7_n777(x) + else + fun_l7_n594(x) + end +end + +def fun_l6_n776(x) + if (x < 1) + fun_l7_n794(x) + else + fun_l7_n71(x) + end +end + +def fun_l6_n777(x) + if (x < 1) + fun_l7_n669(x) + else + fun_l7_n66(x) + end +end + +def fun_l6_n778(x) + if (x < 1) + fun_l7_n824(x) + else + fun_l7_n95(x) + end +end + +def fun_l6_n779(x) + if (x < 1) + fun_l7_n833(x) + else + fun_l7_n504(x) + end +end + +def fun_l6_n780(x) + if (x < 1) + fun_l7_n50(x) + else + fun_l7_n647(x) + end +end + +def fun_l6_n781(x) + if (x < 1) + fun_l7_n139(x) + else + fun_l7_n214(x) + end +end + +def fun_l6_n782(x) + if (x < 1) + fun_l7_n450(x) + else + fun_l7_n660(x) + end +end + +def fun_l6_n783(x) + if (x < 1) + fun_l7_n164(x) + else + fun_l7_n576(x) + end +end + +def fun_l6_n784(x) + if (x < 1) + fun_l7_n722(x) + else + fun_l7_n714(x) + end +end + +def fun_l6_n785(x) + if (x < 1) + fun_l7_n90(x) + else + fun_l7_n556(x) + end +end + +def fun_l6_n786(x) + if (x < 1) + fun_l7_n413(x) + else + fun_l7_n722(x) + end +end + +def fun_l6_n787(x) + if (x < 1) + fun_l7_n141(x) + else + fun_l7_n90(x) + end +end + +def fun_l6_n788(x) + if (x < 1) + fun_l7_n750(x) + else + fun_l7_n660(x) + end +end + +def fun_l6_n789(x) + if (x < 1) + fun_l7_n581(x) + else + fun_l7_n368(x) + end +end + +def fun_l6_n790(x) + if (x < 1) + fun_l7_n922(x) + else + fun_l7_n551(x) + end +end + +def fun_l6_n791(x) + if (x < 1) + fun_l7_n842(x) + else + fun_l7_n336(x) + end +end + +def fun_l6_n792(x) + if (x < 1) + fun_l7_n264(x) + else + fun_l7_n7(x) + end +end + +def fun_l6_n793(x) + if (x < 1) + fun_l7_n902(x) + else + fun_l7_n184(x) + end +end + +def fun_l6_n794(x) + if (x < 1) + fun_l7_n788(x) + else + fun_l7_n854(x) + end +end + +def fun_l6_n795(x) + if (x < 1) + fun_l7_n375(x) + else + fun_l7_n601(x) + end +end + +def fun_l6_n796(x) + if (x < 1) + fun_l7_n674(x) + else + fun_l7_n136(x) + end +end + +def fun_l6_n797(x) + if (x < 1) + fun_l7_n836(x) + else + fun_l7_n90(x) + end +end + +def fun_l6_n798(x) + if (x < 1) + fun_l7_n461(x) + else + fun_l7_n686(x) + end +end + +def fun_l6_n799(x) + if (x < 1) + fun_l7_n308(x) + else + fun_l7_n179(x) + end +end + +def fun_l6_n800(x) + if (x < 1) + fun_l7_n154(x) + else + fun_l7_n618(x) + end +end + +def fun_l6_n801(x) + if (x < 1) + fun_l7_n242(x) + else + fun_l7_n16(x) + end +end + +def fun_l6_n802(x) + if (x < 1) + fun_l7_n880(x) + else + fun_l7_n143(x) + end +end + +def fun_l6_n803(x) + if (x < 1) + fun_l7_n577(x) + else + fun_l7_n414(x) + end +end + +def fun_l6_n804(x) + if (x < 1) + fun_l7_n409(x) + else + fun_l7_n116(x) + end +end + +def fun_l6_n805(x) + if (x < 1) + fun_l7_n259(x) + else + fun_l7_n820(x) + end +end + +def fun_l6_n806(x) + if (x < 1) + fun_l7_n384(x) + else + fun_l7_n939(x) + end +end + +def fun_l6_n807(x) + if (x < 1) + fun_l7_n138(x) + else + fun_l7_n652(x) + end +end + +def fun_l6_n808(x) + if (x < 1) + fun_l7_n455(x) + else + fun_l7_n693(x) + end +end + +def fun_l6_n809(x) + if (x < 1) + fun_l7_n892(x) + else + fun_l7_n638(x) + end +end + +def fun_l6_n810(x) + if (x < 1) + fun_l7_n498(x) + else + fun_l7_n716(x) + end +end + +def fun_l6_n811(x) + if (x < 1) + fun_l7_n713(x) + else + fun_l7_n9(x) + end +end + +def fun_l6_n812(x) + if (x < 1) + fun_l7_n854(x) + else + fun_l7_n507(x) + end +end + +def fun_l6_n813(x) + if (x < 1) + fun_l7_n385(x) + else + fun_l7_n323(x) + end +end + +def fun_l6_n814(x) + if (x < 1) + fun_l7_n437(x) + else + fun_l7_n954(x) + end +end + +def fun_l6_n815(x) + if (x < 1) + fun_l7_n471(x) + else + fun_l7_n245(x) + end +end + +def fun_l6_n816(x) + if (x < 1) + fun_l7_n485(x) + else + fun_l7_n935(x) + end +end + +def fun_l6_n817(x) + if (x < 1) + fun_l7_n319(x) + else + fun_l7_n566(x) + end +end + +def fun_l6_n818(x) + if (x < 1) + fun_l7_n339(x) + else + fun_l7_n152(x) + end +end + +def fun_l6_n819(x) + if (x < 1) + fun_l7_n21(x) + else + fun_l7_n452(x) + end +end + +def fun_l6_n820(x) + if (x < 1) + fun_l7_n16(x) + else + fun_l7_n502(x) + end +end + +def fun_l6_n821(x) + if (x < 1) + fun_l7_n813(x) + else + fun_l7_n520(x) + end +end + +def fun_l6_n822(x) + if (x < 1) + fun_l7_n519(x) + else + fun_l7_n651(x) + end +end + +def fun_l6_n823(x) + if (x < 1) + fun_l7_n890(x) + else + fun_l7_n227(x) + end +end + +def fun_l6_n824(x) + if (x < 1) + fun_l7_n517(x) + else + fun_l7_n799(x) + end +end + +def fun_l6_n825(x) + if (x < 1) + fun_l7_n404(x) + else + fun_l7_n442(x) + end +end + +def fun_l6_n826(x) + if (x < 1) + fun_l7_n308(x) + else + fun_l7_n328(x) + end +end + +def fun_l6_n827(x) + if (x < 1) + fun_l7_n953(x) + else + fun_l7_n950(x) + end +end + +def fun_l6_n828(x) + if (x < 1) + fun_l7_n206(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n829(x) + if (x < 1) + fun_l7_n499(x) + else + fun_l7_n972(x) + end +end + +def fun_l6_n830(x) + if (x < 1) + fun_l7_n578(x) + else + fun_l7_n697(x) + end +end + +def fun_l6_n831(x) + if (x < 1) + fun_l7_n116(x) + else + fun_l7_n747(x) + end +end + +def fun_l6_n832(x) + if (x < 1) + fun_l7_n423(x) + else + fun_l7_n653(x) + end +end + +def fun_l6_n833(x) + if (x < 1) + fun_l7_n524(x) + else + fun_l7_n423(x) + end +end + +def fun_l6_n834(x) + if (x < 1) + fun_l7_n940(x) + else + fun_l7_n48(x) + end +end + +def fun_l6_n835(x) + if (x < 1) + fun_l7_n336(x) + else + fun_l7_n584(x) + end +end + +def fun_l6_n836(x) + if (x < 1) + fun_l7_n66(x) + else + fun_l7_n980(x) + end +end + +def fun_l6_n837(x) + if (x < 1) + fun_l7_n176(x) + else + fun_l7_n845(x) + end +end + +def fun_l6_n838(x) + if (x < 1) + fun_l7_n736(x) + else + fun_l7_n385(x) + end +end + +def fun_l6_n839(x) + if (x < 1) + fun_l7_n948(x) + else + fun_l7_n258(x) + end +end + +def fun_l6_n840(x) + if (x < 1) + fun_l7_n926(x) + else + fun_l7_n926(x) + end +end + +def fun_l6_n841(x) + if (x < 1) + fun_l7_n334(x) + else + fun_l7_n134(x) + end +end + +def fun_l6_n842(x) + if (x < 1) + fun_l7_n757(x) + else + fun_l7_n995(x) + end +end + +def fun_l6_n843(x) + if (x < 1) + fun_l7_n75(x) + else + fun_l7_n6(x) + end +end + +def fun_l6_n844(x) + if (x < 1) + fun_l7_n632(x) + else + fun_l7_n683(x) + end +end + +def fun_l6_n845(x) + if (x < 1) + fun_l7_n788(x) + else + fun_l7_n153(x) + end +end + +def fun_l6_n846(x) + if (x < 1) + fun_l7_n668(x) + else + fun_l7_n78(x) + end +end + +def fun_l6_n847(x) + if (x < 1) + fun_l7_n509(x) + else + fun_l7_n210(x) + end +end + +def fun_l6_n848(x) + if (x < 1) + fun_l7_n862(x) + else + fun_l7_n90(x) + end +end + +def fun_l6_n849(x) + if (x < 1) + fun_l7_n837(x) + else + fun_l7_n37(x) + end +end + +def fun_l6_n850(x) + if (x < 1) + fun_l7_n792(x) + else + fun_l7_n171(x) + end +end + +def fun_l6_n851(x) + if (x < 1) + fun_l7_n869(x) + else + fun_l7_n217(x) + end +end + +def fun_l6_n852(x) + if (x < 1) + fun_l7_n585(x) + else + fun_l7_n980(x) + end +end + +def fun_l6_n853(x) + if (x < 1) + fun_l7_n752(x) + else + fun_l7_n214(x) + end +end + +def fun_l6_n854(x) + if (x < 1) + fun_l7_n151(x) + else + fun_l7_n668(x) + end +end + +def fun_l6_n855(x) + if (x < 1) + fun_l7_n145(x) + else + fun_l7_n99(x) + end +end + +def fun_l6_n856(x) + if (x < 1) + fun_l7_n114(x) + else + fun_l7_n852(x) + end +end + +def fun_l6_n857(x) + if (x < 1) + fun_l7_n571(x) + else + fun_l7_n6(x) + end +end + +def fun_l6_n858(x) + if (x < 1) + fun_l7_n724(x) + else + fun_l7_n132(x) + end +end + +def fun_l6_n859(x) + if (x < 1) + fun_l7_n146(x) + else + fun_l7_n627(x) + end +end + +def fun_l6_n860(x) + if (x < 1) + fun_l7_n515(x) + else + fun_l7_n598(x) + end +end + +def fun_l6_n861(x) + if (x < 1) + fun_l7_n49(x) + else + fun_l7_n781(x) + end +end + +def fun_l6_n862(x) + if (x < 1) + fun_l7_n378(x) + else + fun_l7_n295(x) + end +end + +def fun_l6_n863(x) + if (x < 1) + fun_l7_n122(x) + else + fun_l7_n738(x) + end +end + +def fun_l6_n864(x) + if (x < 1) + fun_l7_n421(x) + else + fun_l7_n719(x) + end +end + +def fun_l6_n865(x) + if (x < 1) + fun_l7_n965(x) + else + fun_l7_n963(x) + end +end + +def fun_l6_n866(x) + if (x < 1) + fun_l7_n551(x) + else + fun_l7_n177(x) + end +end + +def fun_l6_n867(x) + if (x < 1) + fun_l7_n136(x) + else + fun_l7_n289(x) + end +end + +def fun_l6_n868(x) + if (x < 1) + fun_l7_n26(x) + else + fun_l7_n376(x) + end +end + +def fun_l6_n869(x) + if (x < 1) + fun_l7_n888(x) + else + fun_l7_n948(x) + end +end + +def fun_l6_n870(x) + if (x < 1) + fun_l7_n636(x) + else + fun_l7_n89(x) + end +end + +def fun_l6_n871(x) + if (x < 1) + fun_l7_n953(x) + else + fun_l7_n634(x) + end +end + +def fun_l6_n872(x) + if (x < 1) + fun_l7_n74(x) + else + fun_l7_n219(x) + end +end + +def fun_l6_n873(x) + if (x < 1) + fun_l7_n317(x) + else + fun_l7_n863(x) + end +end + +def fun_l6_n874(x) + if (x < 1) + fun_l7_n495(x) + else + fun_l7_n478(x) + end +end + +def fun_l6_n875(x) + if (x < 1) + fun_l7_n908(x) + else + fun_l7_n634(x) + end +end + +def fun_l6_n876(x) + if (x < 1) + fun_l7_n780(x) + else + fun_l7_n886(x) + end +end + +def fun_l6_n877(x) + if (x < 1) + fun_l7_n768(x) + else + fun_l7_n820(x) + end +end + +def fun_l6_n878(x) + if (x < 1) + fun_l7_n501(x) + else + fun_l7_n355(x) + end +end + +def fun_l6_n879(x) + if (x < 1) + fun_l7_n412(x) + else + fun_l7_n701(x) + end +end + +def fun_l6_n880(x) + if (x < 1) + fun_l7_n541(x) + else + fun_l7_n148(x) + end +end + +def fun_l6_n881(x) + if (x < 1) + fun_l7_n460(x) + else + fun_l7_n579(x) + end +end + +def fun_l6_n882(x) + if (x < 1) + fun_l7_n576(x) + else + fun_l7_n118(x) + end +end + +def fun_l6_n883(x) + if (x < 1) + fun_l7_n218(x) + else + fun_l7_n197(x) + end +end + +def fun_l6_n884(x) + if (x < 1) + fun_l7_n279(x) + else + fun_l7_n565(x) + end +end + +def fun_l6_n885(x) + if (x < 1) + fun_l7_n934(x) + else + fun_l7_n46(x) + end +end + +def fun_l6_n886(x) + if (x < 1) + fun_l7_n894(x) + else + fun_l7_n864(x) + end +end + +def fun_l6_n887(x) + if (x < 1) + fun_l7_n45(x) + else + fun_l7_n151(x) + end +end + +def fun_l6_n888(x) + if (x < 1) + fun_l7_n190(x) + else + fun_l7_n46(x) + end +end + +def fun_l6_n889(x) + if (x < 1) + fun_l7_n56(x) + else + fun_l7_n451(x) + end +end + +def fun_l6_n890(x) + if (x < 1) + fun_l7_n7(x) + else + fun_l7_n906(x) + end +end + +def fun_l6_n891(x) + if (x < 1) + fun_l7_n507(x) + else + fun_l7_n121(x) + end +end + +def fun_l6_n892(x) + if (x < 1) + fun_l7_n757(x) + else + fun_l7_n485(x) + end +end + +def fun_l6_n893(x) + if (x < 1) + fun_l7_n242(x) + else + fun_l7_n366(x) + end +end + +def fun_l6_n894(x) + if (x < 1) + fun_l7_n563(x) + else + fun_l7_n749(x) + end +end + +def fun_l6_n895(x) + if (x < 1) + fun_l7_n976(x) + else + fun_l7_n907(x) + end +end + +def fun_l6_n896(x) + if (x < 1) + fun_l7_n525(x) + else + fun_l7_n843(x) + end +end + +def fun_l6_n897(x) + if (x < 1) + fun_l7_n255(x) + else + fun_l7_n133(x) + end +end + +def fun_l6_n898(x) + if (x < 1) + fun_l7_n796(x) + else + fun_l7_n275(x) + end +end + +def fun_l6_n899(x) + if (x < 1) + fun_l7_n985(x) + else + fun_l7_n485(x) + end +end + +def fun_l6_n900(x) + if (x < 1) + fun_l7_n32(x) + else + fun_l7_n324(x) + end +end + +def fun_l6_n901(x) + if (x < 1) + fun_l7_n334(x) + else + fun_l7_n618(x) + end +end + +def fun_l6_n902(x) + if (x < 1) + fun_l7_n762(x) + else + fun_l7_n778(x) + end +end + +def fun_l6_n903(x) + if (x < 1) + fun_l7_n343(x) + else + fun_l7_n349(x) + end +end + +def fun_l6_n904(x) + if (x < 1) + fun_l7_n310(x) + else + fun_l7_n215(x) + end +end + +def fun_l6_n905(x) + if (x < 1) + fun_l7_n162(x) + else + fun_l7_n405(x) + end +end + +def fun_l6_n906(x) + if (x < 1) + fun_l7_n667(x) + else + fun_l7_n633(x) + end +end + +def fun_l6_n907(x) + if (x < 1) + fun_l7_n652(x) + else + fun_l7_n771(x) + end +end + +def fun_l6_n908(x) + if (x < 1) + fun_l7_n198(x) + else + fun_l7_n32(x) + end +end + +def fun_l6_n909(x) + if (x < 1) + fun_l7_n577(x) + else + fun_l7_n116(x) + end +end + +def fun_l6_n910(x) + if (x < 1) + fun_l7_n63(x) + else + fun_l7_n57(x) + end +end + +def fun_l6_n911(x) + if (x < 1) + fun_l7_n908(x) + else + fun_l7_n556(x) + end +end + +def fun_l6_n912(x) + if (x < 1) + fun_l7_n420(x) + else + fun_l7_n163(x) + end +end + +def fun_l6_n913(x) + if (x < 1) + fun_l7_n795(x) + else + fun_l7_n225(x) + end +end + +def fun_l6_n914(x) + if (x < 1) + fun_l7_n855(x) + else + fun_l7_n742(x) + end +end + +def fun_l6_n915(x) + if (x < 1) + fun_l7_n386(x) + else + fun_l7_n314(x) + end +end + +def fun_l6_n916(x) + if (x < 1) + fun_l7_n587(x) + else + fun_l7_n371(x) + end +end + +def fun_l6_n917(x) + if (x < 1) + fun_l7_n570(x) + else + fun_l7_n735(x) + end +end + +def fun_l6_n918(x) + if (x < 1) + fun_l7_n985(x) + else + fun_l7_n492(x) + end +end + +def fun_l6_n919(x) + if (x < 1) + fun_l7_n991(x) + else + fun_l7_n454(x) + end +end + +def fun_l6_n920(x) + if (x < 1) + fun_l7_n925(x) + else + fun_l7_n161(x) + end +end + +def fun_l6_n921(x) + if (x < 1) + fun_l7_n398(x) + else + fun_l7_n621(x) + end +end + +def fun_l6_n922(x) + if (x < 1) + fun_l7_n732(x) + else + fun_l7_n509(x) + end +end + +def fun_l6_n923(x) + if (x < 1) + fun_l7_n879(x) + else + fun_l7_n219(x) + end +end + +def fun_l6_n924(x) + if (x < 1) + fun_l7_n19(x) + else + fun_l7_n604(x) + end +end + +def fun_l6_n925(x) + if (x < 1) + fun_l7_n474(x) + else + fun_l7_n439(x) + end +end + +def fun_l6_n926(x) + if (x < 1) + fun_l7_n807(x) + else + fun_l7_n802(x) + end +end + +def fun_l6_n927(x) + if (x < 1) + fun_l7_n146(x) + else + fun_l7_n966(x) + end +end + +def fun_l6_n928(x) + if (x < 1) + fun_l7_n72(x) + else + fun_l7_n835(x) + end +end + +def fun_l6_n929(x) + if (x < 1) + fun_l7_n389(x) + else + fun_l7_n951(x) + end +end + +def fun_l6_n930(x) + if (x < 1) + fun_l7_n104(x) + else + fun_l7_n719(x) + end +end + +def fun_l6_n931(x) + if (x < 1) + fun_l7_n250(x) + else + fun_l7_n13(x) + end +end + +def fun_l6_n932(x) + if (x < 1) + fun_l7_n470(x) + else + fun_l7_n984(x) + end +end + +def fun_l6_n933(x) + if (x < 1) + fun_l7_n485(x) + else + fun_l7_n750(x) + end +end + +def fun_l6_n934(x) + if (x < 1) + fun_l7_n371(x) + else + fun_l7_n912(x) + end +end + +def fun_l6_n935(x) + if (x < 1) + fun_l7_n686(x) + else + fun_l7_n523(x) + end +end + +def fun_l6_n936(x) + if (x < 1) + fun_l7_n998(x) + else + fun_l7_n6(x) + end +end + +def fun_l6_n937(x) + if (x < 1) + fun_l7_n753(x) + else + fun_l7_n781(x) + end +end + +def fun_l6_n938(x) + if (x < 1) + fun_l7_n518(x) + else + fun_l7_n18(x) + end +end + +def fun_l6_n939(x) + if (x < 1) + fun_l7_n771(x) + else + fun_l7_n1(x) + end +end + +def fun_l6_n940(x) + if (x < 1) + fun_l7_n43(x) + else + fun_l7_n727(x) + end +end + +def fun_l6_n941(x) + if (x < 1) + fun_l7_n282(x) + else + fun_l7_n676(x) + end +end + +def fun_l6_n942(x) + if (x < 1) + fun_l7_n284(x) + else + fun_l7_n56(x) + end +end + +def fun_l6_n943(x) + if (x < 1) + fun_l7_n304(x) + else + fun_l7_n287(x) + end +end + +def fun_l6_n944(x) + if (x < 1) + fun_l7_n968(x) + else + fun_l7_n283(x) + end +end + +def fun_l6_n945(x) + if (x < 1) + fun_l7_n892(x) + else + fun_l7_n413(x) + end +end + +def fun_l6_n946(x) + if (x < 1) + fun_l7_n750(x) + else + fun_l7_n244(x) + end +end + +def fun_l6_n947(x) + if (x < 1) + fun_l7_n599(x) + else + fun_l7_n238(x) + end +end + +def fun_l6_n948(x) + if (x < 1) + fun_l7_n447(x) + else + fun_l7_n880(x) + end +end + +def fun_l6_n949(x) + if (x < 1) + fun_l7_n242(x) + else + fun_l7_n210(x) + end +end + +def fun_l6_n950(x) + if (x < 1) + fun_l7_n143(x) + else + fun_l7_n816(x) + end +end + +def fun_l6_n951(x) + if (x < 1) + fun_l7_n125(x) + else + fun_l7_n909(x) + end +end + +def fun_l6_n952(x) + if (x < 1) + fun_l7_n134(x) + else + fun_l7_n946(x) + end +end + +def fun_l6_n953(x) + if (x < 1) + fun_l7_n858(x) + else + fun_l7_n927(x) + end +end + +def fun_l6_n954(x) + if (x < 1) + fun_l7_n853(x) + else + fun_l7_n396(x) + end +end + +def fun_l6_n955(x) + if (x < 1) + fun_l7_n725(x) + else + fun_l7_n42(x) + end +end + +def fun_l6_n956(x) + if (x < 1) + fun_l7_n108(x) + else + fun_l7_n177(x) + end +end + +def fun_l6_n957(x) + if (x < 1) + fun_l7_n742(x) + else + fun_l7_n482(x) + end +end + +def fun_l6_n958(x) + if (x < 1) + fun_l7_n385(x) + else + fun_l7_n292(x) + end +end + +def fun_l6_n959(x) + if (x < 1) + fun_l7_n325(x) + else + fun_l7_n27(x) + end +end + +def fun_l6_n960(x) + if (x < 1) + fun_l7_n558(x) + else + fun_l7_n556(x) + end +end + +def fun_l6_n961(x) + if (x < 1) + fun_l7_n472(x) + else + fun_l7_n322(x) + end +end + +def fun_l6_n962(x) + if (x < 1) + fun_l7_n754(x) + else + fun_l7_n729(x) + end +end + +def fun_l6_n963(x) + if (x < 1) + fun_l7_n35(x) + else + fun_l7_n232(x) + end +end + +def fun_l6_n964(x) + if (x < 1) + fun_l7_n113(x) + else + fun_l7_n878(x) + end +end + +def fun_l6_n965(x) + if (x < 1) + fun_l7_n982(x) + else + fun_l7_n404(x) + end +end + +def fun_l6_n966(x) + if (x < 1) + fun_l7_n385(x) + else + fun_l7_n20(x) + end +end + +def fun_l6_n967(x) + if (x < 1) + fun_l7_n394(x) + else + fun_l7_n873(x) + end +end + +def fun_l6_n968(x) + if (x < 1) + fun_l7_n230(x) + else + fun_l7_n141(x) + end +end + +def fun_l6_n969(x) + if (x < 1) + fun_l7_n742(x) + else + fun_l7_n75(x) + end +end + +def fun_l6_n970(x) + if (x < 1) + fun_l7_n583(x) + else + fun_l7_n809(x) + end +end + +def fun_l6_n971(x) + if (x < 1) + fun_l7_n535(x) + else + fun_l7_n151(x) + end +end + +def fun_l6_n972(x) + if (x < 1) + fun_l7_n42(x) + else + fun_l7_n469(x) + end +end + +def fun_l6_n973(x) + if (x < 1) + fun_l7_n964(x) + else + fun_l7_n759(x) + end +end + +def fun_l6_n974(x) + if (x < 1) + fun_l7_n897(x) + else + fun_l7_n29(x) + end +end + +def fun_l6_n975(x) + if (x < 1) + fun_l7_n331(x) + else + fun_l7_n972(x) + end +end + +def fun_l6_n976(x) + if (x < 1) + fun_l7_n825(x) + else + fun_l7_n221(x) + end +end + +def fun_l6_n977(x) + if (x < 1) + fun_l7_n207(x) + else + fun_l7_n520(x) + end +end + +def fun_l6_n978(x) + if (x < 1) + fun_l7_n231(x) + else + fun_l7_n552(x) + end +end + +def fun_l6_n979(x) + if (x < 1) + fun_l7_n621(x) + else + fun_l7_n766(x) + end +end + +def fun_l6_n980(x) + if (x < 1) + fun_l7_n461(x) + else + fun_l7_n552(x) + end +end + +def fun_l6_n981(x) + if (x < 1) + fun_l7_n891(x) + else + fun_l7_n710(x) + end +end + +def fun_l6_n982(x) + if (x < 1) + fun_l7_n253(x) + else + fun_l7_n104(x) + end +end + +def fun_l6_n983(x) + if (x < 1) + fun_l7_n726(x) + else + fun_l7_n903(x) + end +end + +def fun_l6_n984(x) + if (x < 1) + fun_l7_n524(x) + else + fun_l7_n700(x) + end +end + +def fun_l6_n985(x) + if (x < 1) + fun_l7_n234(x) + else + fun_l7_n454(x) + end +end + +def fun_l6_n986(x) + if (x < 1) + fun_l7_n379(x) + else + fun_l7_n504(x) + end +end + +def fun_l6_n987(x) + if (x < 1) + fun_l7_n194(x) + else + fun_l7_n962(x) + end +end + +def fun_l6_n988(x) + if (x < 1) + fun_l7_n60(x) + else + fun_l7_n699(x) + end +end + +def fun_l6_n989(x) + if (x < 1) + fun_l7_n692(x) + else + fun_l7_n28(x) + end +end + +def fun_l6_n990(x) + if (x < 1) + fun_l7_n456(x) + else + fun_l7_n126(x) + end +end + +def fun_l6_n991(x) + if (x < 1) + fun_l7_n104(x) + else + fun_l7_n156(x) + end +end + +def fun_l6_n992(x) + if (x < 1) + fun_l7_n269(x) + else + fun_l7_n513(x) + end +end + +def fun_l6_n993(x) + if (x < 1) + fun_l7_n20(x) + else + fun_l7_n754(x) + end +end + +def fun_l6_n994(x) + if (x < 1) + fun_l7_n445(x) + else + fun_l7_n422(x) + end +end + +def fun_l6_n995(x) + if (x < 1) + fun_l7_n320(x) + else + fun_l7_n398(x) + end +end + +def fun_l6_n996(x) + if (x < 1) + fun_l7_n479(x) + else + fun_l7_n238(x) + end +end + +def fun_l6_n997(x) + if (x < 1) + fun_l7_n254(x) + else + fun_l7_n692(x) + end +end + +def fun_l6_n998(x) + if (x < 1) + fun_l7_n774(x) + else + fun_l7_n510(x) + end +end + +def fun_l6_n999(x) + if (x < 1) + fun_l7_n158(x) + else + fun_l7_n929(x) + end +end + +def fun_l7_n0(x) + if (x < 1) + fun_l8_n414(x) + else + fun_l8_n327(x) + end +end + +def fun_l7_n1(x) + if (x < 1) + fun_l8_n446(x) + else + fun_l8_n611(x) + end +end + +def fun_l7_n2(x) + if (x < 1) + fun_l8_n116(x) + else + fun_l8_n224(x) + end +end + +def fun_l7_n3(x) + if (x < 1) + fun_l8_n809(x) + else + fun_l8_n962(x) + end +end + +def fun_l7_n4(x) + if (x < 1) + fun_l8_n137(x) + else + fun_l8_n426(x) + end +end + +def fun_l7_n5(x) + if (x < 1) + fun_l8_n686(x) + else + fun_l8_n600(x) + end +end + +def fun_l7_n6(x) + if (x < 1) + fun_l8_n430(x) + else + fun_l8_n302(x) + end +end + +def fun_l7_n7(x) + if (x < 1) + fun_l8_n865(x) + else + fun_l8_n60(x) + end +end + +def fun_l7_n8(x) + if (x < 1) + fun_l8_n895(x) + else + fun_l8_n148(x) + end +end + +def fun_l7_n9(x) + if (x < 1) + fun_l8_n740(x) + else + fun_l8_n982(x) + end +end + +def fun_l7_n10(x) + if (x < 1) + fun_l8_n757(x) + else + fun_l8_n640(x) + end +end + +def fun_l7_n11(x) + if (x < 1) + fun_l8_n744(x) + else + fun_l8_n256(x) + end +end + +def fun_l7_n12(x) + if (x < 1) + fun_l8_n272(x) + else + fun_l8_n828(x) + end +end + +def fun_l7_n13(x) + if (x < 1) + fun_l8_n395(x) + else + fun_l8_n932(x) + end +end + +def fun_l7_n14(x) + if (x < 1) + fun_l8_n178(x) + else + fun_l8_n676(x) + end +end + +def fun_l7_n15(x) + if (x < 1) + fun_l8_n40(x) + else + fun_l8_n548(x) + end +end + +def fun_l7_n16(x) + if (x < 1) + fun_l8_n506(x) + else + fun_l8_n234(x) + end +end + +def fun_l7_n17(x) + if (x < 1) + fun_l8_n239(x) + else + fun_l8_n56(x) + end +end + +def fun_l7_n18(x) + if (x < 1) + fun_l8_n381(x) + else + fun_l8_n720(x) + end +end + +def fun_l7_n19(x) + if (x < 1) + fun_l8_n781(x) + else + fun_l8_n605(x) + end +end + +def fun_l7_n20(x) + if (x < 1) + fun_l8_n479(x) + else + fun_l8_n894(x) + end +end + +def fun_l7_n21(x) + if (x < 1) + fun_l8_n437(x) + else + fun_l8_n123(x) + end +end + +def fun_l7_n22(x) + if (x < 1) + fun_l8_n20(x) + else + fun_l8_n144(x) + end +end + +def fun_l7_n23(x) + if (x < 1) + fun_l8_n684(x) + else + fun_l8_n866(x) + end +end + +def fun_l7_n24(x) + if (x < 1) + fun_l8_n527(x) + else + fun_l8_n629(x) + end +end + +def fun_l7_n25(x) + if (x < 1) + fun_l8_n399(x) + else + fun_l8_n52(x) + end +end + +def fun_l7_n26(x) + if (x < 1) + fun_l8_n353(x) + else + fun_l8_n438(x) + end +end + +def fun_l7_n27(x) + if (x < 1) + fun_l8_n916(x) + else + fun_l8_n488(x) + end +end + +def fun_l7_n28(x) + if (x < 1) + fun_l8_n833(x) + else + fun_l8_n585(x) + end +end + +def fun_l7_n29(x) + if (x < 1) + fun_l8_n38(x) + else + fun_l8_n785(x) + end +end + +def fun_l7_n30(x) + if (x < 1) + fun_l8_n157(x) + else + fun_l8_n332(x) + end +end + +def fun_l7_n31(x) + if (x < 1) + fun_l8_n467(x) + else + fun_l8_n442(x) + end +end + +def fun_l7_n32(x) + if (x < 1) + fun_l8_n704(x) + else + fun_l8_n295(x) + end +end + +def fun_l7_n33(x) + if (x < 1) + fun_l8_n829(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n34(x) + if (x < 1) + fun_l8_n227(x) + else + fun_l8_n865(x) + end +end + +def fun_l7_n35(x) + if (x < 1) + fun_l8_n930(x) + else + fun_l8_n129(x) + end +end + +def fun_l7_n36(x) + if (x < 1) + fun_l8_n519(x) + else + fun_l8_n587(x) + end +end + +def fun_l7_n37(x) + if (x < 1) + fun_l8_n132(x) + else + fun_l8_n547(x) + end +end + +def fun_l7_n38(x) + if (x < 1) + fun_l8_n627(x) + else + fun_l8_n712(x) + end +end + +def fun_l7_n39(x) + if (x < 1) + fun_l8_n752(x) + else + fun_l8_n357(x) + end +end + +def fun_l7_n40(x) + if (x < 1) + fun_l8_n542(x) + else + fun_l8_n86(x) + end +end + +def fun_l7_n41(x) + if (x < 1) + fun_l8_n89(x) + else + fun_l8_n492(x) + end +end + +def fun_l7_n42(x) + if (x < 1) + fun_l8_n508(x) + else + fun_l8_n288(x) + end +end + +def fun_l7_n43(x) + if (x < 1) + fun_l8_n627(x) + else + fun_l8_n632(x) + end +end + +def fun_l7_n44(x) + if (x < 1) + fun_l8_n513(x) + else + fun_l8_n472(x) + end +end + +def fun_l7_n45(x) + if (x < 1) + fun_l8_n599(x) + else + fun_l8_n581(x) + end +end + +def fun_l7_n46(x) + if (x < 1) + fun_l8_n907(x) + else + fun_l8_n71(x) + end +end + +def fun_l7_n47(x) + if (x < 1) + fun_l8_n609(x) + else + fun_l8_n601(x) + end +end + +def fun_l7_n48(x) + if (x < 1) + fun_l8_n985(x) + else + fun_l8_n536(x) + end +end + +def fun_l7_n49(x) + if (x < 1) + fun_l8_n220(x) + else + fun_l8_n6(x) + end +end + +def fun_l7_n50(x) + if (x < 1) + fun_l8_n445(x) + else + fun_l8_n939(x) + end +end + +def fun_l7_n51(x) + if (x < 1) + fun_l8_n973(x) + else + fun_l8_n600(x) + end +end + +def fun_l7_n52(x) + if (x < 1) + fun_l8_n377(x) + else + fun_l8_n70(x) + end +end + +def fun_l7_n53(x) + if (x < 1) + fun_l8_n745(x) + else + fun_l8_n237(x) + end +end + +def fun_l7_n54(x) + if (x < 1) + fun_l8_n782(x) + else + fun_l8_n756(x) + end +end + +def fun_l7_n55(x) + if (x < 1) + fun_l8_n438(x) + else + fun_l8_n892(x) + end +end + +def fun_l7_n56(x) + if (x < 1) + fun_l8_n564(x) + else + fun_l8_n600(x) + end +end + +def fun_l7_n57(x) + if (x < 1) + fun_l8_n480(x) + else + fun_l8_n832(x) + end +end + +def fun_l7_n58(x) + if (x < 1) + fun_l8_n239(x) + else + fun_l8_n540(x) + end +end + +def fun_l7_n59(x) + if (x < 1) + fun_l8_n904(x) + else + fun_l8_n334(x) + end +end + +def fun_l7_n60(x) + if (x < 1) + fun_l8_n407(x) + else + fun_l8_n573(x) + end +end + +def fun_l7_n61(x) + if (x < 1) + fun_l8_n705(x) + else + fun_l8_n202(x) + end +end + +def fun_l7_n62(x) + if (x < 1) + fun_l8_n715(x) + else + fun_l8_n394(x) + end +end + +def fun_l7_n63(x) + if (x < 1) + fun_l8_n935(x) + else + fun_l8_n855(x) + end +end + +def fun_l7_n64(x) + if (x < 1) + fun_l8_n525(x) + else + fun_l8_n81(x) + end +end + +def fun_l7_n65(x) + if (x < 1) + fun_l8_n692(x) + else + fun_l8_n372(x) + end +end + +def fun_l7_n66(x) + if (x < 1) + fun_l8_n286(x) + else + fun_l8_n568(x) + end +end + +def fun_l7_n67(x) + if (x < 1) + fun_l8_n829(x) + else + fun_l8_n89(x) + end +end + +def fun_l7_n68(x) + if (x < 1) + fun_l8_n542(x) + else + fun_l8_n362(x) + end +end + +def fun_l7_n69(x) + if (x < 1) + fun_l8_n673(x) + else + fun_l8_n302(x) + end +end + +def fun_l7_n70(x) + if (x < 1) + fun_l8_n649(x) + else + fun_l8_n890(x) + end +end + +def fun_l7_n71(x) + if (x < 1) + fun_l8_n639(x) + else + fun_l8_n304(x) + end +end + +def fun_l7_n72(x) + if (x < 1) + fun_l8_n797(x) + else + fun_l8_n132(x) + end +end + +def fun_l7_n73(x) + if (x < 1) + fun_l8_n301(x) + else + fun_l8_n328(x) + end +end + +def fun_l7_n74(x) + if (x < 1) + fun_l8_n438(x) + else + fun_l8_n979(x) + end +end + +def fun_l7_n75(x) + if (x < 1) + fun_l8_n679(x) + else + fun_l8_n621(x) + end +end + +def fun_l7_n76(x) + if (x < 1) + fun_l8_n136(x) + else + fun_l8_n916(x) + end +end + +def fun_l7_n77(x) + if (x < 1) + fun_l8_n39(x) + else + fun_l8_n945(x) + end +end + +def fun_l7_n78(x) + if (x < 1) + fun_l8_n365(x) + else + fun_l8_n883(x) + end +end + +def fun_l7_n79(x) + if (x < 1) + fun_l8_n514(x) + else + fun_l8_n989(x) + end +end + +def fun_l7_n80(x) + if (x < 1) + fun_l8_n378(x) + else + fun_l8_n634(x) + end +end + +def fun_l7_n81(x) + if (x < 1) + fun_l8_n200(x) + else + fun_l8_n73(x) + end +end + +def fun_l7_n82(x) + if (x < 1) + fun_l8_n521(x) + else + fun_l8_n848(x) + end +end + +def fun_l7_n83(x) + if (x < 1) + fun_l8_n184(x) + else + fun_l8_n350(x) + end +end + +def fun_l7_n84(x) + if (x < 1) + fun_l8_n215(x) + else + fun_l8_n615(x) + end +end + +def fun_l7_n85(x) + if (x < 1) + fun_l8_n556(x) + else + fun_l8_n723(x) + end +end + +def fun_l7_n86(x) + if (x < 1) + fun_l8_n565(x) + else + fun_l8_n661(x) + end +end + +def fun_l7_n87(x) + if (x < 1) + fun_l8_n22(x) + else + fun_l8_n623(x) + end +end + +def fun_l7_n88(x) + if (x < 1) + fun_l8_n995(x) + else + fun_l8_n30(x) + end +end + +def fun_l7_n89(x) + if (x < 1) + fun_l8_n912(x) + else + fun_l8_n332(x) + end +end + +def fun_l7_n90(x) + if (x < 1) + fun_l8_n776(x) + else + fun_l8_n362(x) + end +end + +def fun_l7_n91(x) + if (x < 1) + fun_l8_n720(x) + else + fun_l8_n512(x) + end +end + +def fun_l7_n92(x) + if (x < 1) + fun_l8_n437(x) + else + fun_l8_n107(x) + end +end + +def fun_l7_n93(x) + if (x < 1) + fun_l8_n143(x) + else + fun_l8_n493(x) + end +end + +def fun_l7_n94(x) + if (x < 1) + fun_l8_n814(x) + else + fun_l8_n892(x) + end +end + +def fun_l7_n95(x) + if (x < 1) + fun_l8_n117(x) + else + fun_l8_n18(x) + end +end + +def fun_l7_n96(x) + if (x < 1) + fun_l8_n769(x) + else + fun_l8_n37(x) + end +end + +def fun_l7_n97(x) + if (x < 1) + fun_l8_n213(x) + else + fun_l8_n5(x) + end +end + +def fun_l7_n98(x) + if (x < 1) + fun_l8_n608(x) + else + fun_l8_n551(x) + end +end + +def fun_l7_n99(x) + if (x < 1) + fun_l8_n130(x) + else + fun_l8_n879(x) + end +end + +def fun_l7_n100(x) + if (x < 1) + fun_l8_n279(x) + else + fun_l8_n786(x) + end +end + +def fun_l7_n101(x) + if (x < 1) + fun_l8_n254(x) + else + fun_l8_n904(x) + end +end + +def fun_l7_n102(x) + if (x < 1) + fun_l8_n661(x) + else + fun_l8_n873(x) + end +end + +def fun_l7_n103(x) + if (x < 1) + fun_l8_n360(x) + else + fun_l8_n793(x) + end +end + +def fun_l7_n104(x) + if (x < 1) + fun_l8_n687(x) + else + fun_l8_n853(x) + end +end + +def fun_l7_n105(x) + if (x < 1) + fun_l8_n168(x) + else + fun_l8_n280(x) + end +end + +def fun_l7_n106(x) + if (x < 1) + fun_l8_n742(x) + else + fun_l8_n222(x) + end +end + +def fun_l7_n107(x) + if (x < 1) + fun_l8_n470(x) + else + fun_l8_n633(x) + end +end + +def fun_l7_n108(x) + if (x < 1) + fun_l8_n495(x) + else + fun_l8_n253(x) + end +end + +def fun_l7_n109(x) + if (x < 1) + fun_l8_n369(x) + else + fun_l8_n108(x) + end +end + +def fun_l7_n110(x) + if (x < 1) + fun_l8_n254(x) + else + fun_l8_n162(x) + end +end + +def fun_l7_n111(x) + if (x < 1) + fun_l8_n835(x) + else + fun_l8_n295(x) + end +end + +def fun_l7_n112(x) + if (x < 1) + fun_l8_n349(x) + else + fun_l8_n432(x) + end +end + +def fun_l7_n113(x) + if (x < 1) + fun_l8_n237(x) + else + fun_l8_n484(x) + end +end + +def fun_l7_n114(x) + if (x < 1) + fun_l8_n755(x) + else + fun_l8_n819(x) + end +end + +def fun_l7_n115(x) + if (x < 1) + fun_l8_n542(x) + else + fun_l8_n587(x) + end +end + +def fun_l7_n116(x) + if (x < 1) + fun_l8_n837(x) + else + fun_l8_n274(x) + end +end + +def fun_l7_n117(x) + if (x < 1) + fun_l8_n742(x) + else + fun_l8_n104(x) + end +end + +def fun_l7_n118(x) + if (x < 1) + fun_l8_n201(x) + else + fun_l8_n340(x) + end +end + +def fun_l7_n119(x) + if (x < 1) + fun_l8_n349(x) + else + fun_l8_n213(x) + end +end + +def fun_l7_n120(x) + if (x < 1) + fun_l8_n563(x) + else + fun_l8_n193(x) + end +end + +def fun_l7_n121(x) + if (x < 1) + fun_l8_n738(x) + else + fun_l8_n600(x) + end +end + +def fun_l7_n122(x) + if (x < 1) + fun_l8_n261(x) + else + fun_l8_n500(x) + end +end + +def fun_l7_n123(x) + if (x < 1) + fun_l8_n870(x) + else + fun_l8_n423(x) + end +end + +def fun_l7_n124(x) + if (x < 1) + fun_l8_n405(x) + else + fun_l8_n749(x) + end +end + +def fun_l7_n125(x) + if (x < 1) + fun_l8_n848(x) + else + fun_l8_n106(x) + end +end + +def fun_l7_n126(x) + if (x < 1) + fun_l8_n382(x) + else + fun_l8_n379(x) + end +end + +def fun_l7_n127(x) + if (x < 1) + fun_l8_n232(x) + else + fun_l8_n913(x) + end +end + +def fun_l7_n128(x) + if (x < 1) + fun_l8_n7(x) + else + fun_l8_n177(x) + end +end + +def fun_l7_n129(x) + if (x < 1) + fun_l8_n86(x) + else + fun_l8_n670(x) + end +end + +def fun_l7_n130(x) + if (x < 1) + fun_l8_n361(x) + else + fun_l8_n132(x) + end +end + +def fun_l7_n131(x) + if (x < 1) + fun_l8_n125(x) + else + fun_l8_n925(x) + end +end + +def fun_l7_n132(x) + if (x < 1) + fun_l8_n529(x) + else + fun_l8_n996(x) + end +end + +def fun_l7_n133(x) + if (x < 1) + fun_l8_n283(x) + else + fun_l8_n112(x) + end +end + +def fun_l7_n134(x) + if (x < 1) + fun_l8_n974(x) + else + fun_l8_n204(x) + end +end + +def fun_l7_n135(x) + if (x < 1) + fun_l8_n903(x) + else + fun_l8_n196(x) + end +end + +def fun_l7_n136(x) + if (x < 1) + fun_l8_n59(x) + else + fun_l8_n505(x) + end +end + +def fun_l7_n137(x) + if (x < 1) + fun_l8_n530(x) + else + fun_l8_n31(x) + end +end + +def fun_l7_n138(x) + if (x < 1) + fun_l8_n990(x) + else + fun_l8_n924(x) + end +end + +def fun_l7_n139(x) + if (x < 1) + fun_l8_n202(x) + else + fun_l8_n980(x) + end +end + +def fun_l7_n140(x) + if (x < 1) + fun_l8_n354(x) + else + fun_l8_n694(x) + end +end + +def fun_l7_n141(x) + if (x < 1) + fun_l8_n306(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n142(x) + if (x < 1) + fun_l8_n433(x) + else + fun_l8_n902(x) + end +end + +def fun_l7_n143(x) + if (x < 1) + fun_l8_n522(x) + else + fun_l8_n904(x) + end +end + +def fun_l7_n144(x) + if (x < 1) + fun_l8_n86(x) + else + fun_l8_n11(x) + end +end + +def fun_l7_n145(x) + if (x < 1) + fun_l8_n147(x) + else + fun_l8_n21(x) + end +end + +def fun_l7_n146(x) + if (x < 1) + fun_l8_n47(x) + else + fun_l8_n855(x) + end +end + +def fun_l7_n147(x) + if (x < 1) + fun_l8_n306(x) + else + fun_l8_n309(x) + end +end + +def fun_l7_n148(x) + if (x < 1) + fun_l8_n757(x) + else + fun_l8_n83(x) + end +end + +def fun_l7_n149(x) + if (x < 1) + fun_l8_n377(x) + else + fun_l8_n124(x) + end +end + +def fun_l7_n150(x) + if (x < 1) + fun_l8_n276(x) + else + fun_l8_n838(x) + end +end + +def fun_l7_n151(x) + if (x < 1) + fun_l8_n148(x) + else + fun_l8_n653(x) + end +end + +def fun_l7_n152(x) + if (x < 1) + fun_l8_n315(x) + else + fun_l8_n942(x) + end +end + +def fun_l7_n153(x) + if (x < 1) + fun_l8_n794(x) + else + fun_l8_n680(x) + end +end + +def fun_l7_n154(x) + if (x < 1) + fun_l8_n508(x) + else + fun_l8_n427(x) + end +end + +def fun_l7_n155(x) + if (x < 1) + fun_l8_n249(x) + else + fun_l8_n615(x) + end +end + +def fun_l7_n156(x) + if (x < 1) + fun_l8_n339(x) + else + fun_l8_n559(x) + end +end + +def fun_l7_n157(x) + if (x < 1) + fun_l8_n772(x) + else + fun_l8_n128(x) + end +end + +def fun_l7_n158(x) + if (x < 1) + fun_l8_n247(x) + else + fun_l8_n962(x) + end +end + +def fun_l7_n159(x) + if (x < 1) + fun_l8_n648(x) + else + fun_l8_n338(x) + end +end + +def fun_l7_n160(x) + if (x < 1) + fun_l8_n104(x) + else + fun_l8_n757(x) + end +end + +def fun_l7_n161(x) + if (x < 1) + fun_l8_n74(x) + else + fun_l8_n288(x) + end +end + +def fun_l7_n162(x) + if (x < 1) + fun_l8_n849(x) + else + fun_l8_n982(x) + end +end + +def fun_l7_n163(x) + if (x < 1) + fun_l8_n433(x) + else + fun_l8_n442(x) + end +end + +def fun_l7_n164(x) + if (x < 1) + fun_l8_n268(x) + else + fun_l8_n717(x) + end +end + +def fun_l7_n165(x) + if (x < 1) + fun_l8_n185(x) + else + fun_l8_n628(x) + end +end + +def fun_l7_n166(x) + if (x < 1) + fun_l8_n207(x) + else + fun_l8_n830(x) + end +end + +def fun_l7_n167(x) + if (x < 1) + fun_l8_n334(x) + else + fun_l8_n20(x) + end +end + +def fun_l7_n168(x) + if (x < 1) + fun_l8_n835(x) + else + fun_l8_n493(x) + end +end + +def fun_l7_n169(x) + if (x < 1) + fun_l8_n559(x) + else + fun_l8_n561(x) + end +end + +def fun_l7_n170(x) + if (x < 1) + fun_l8_n942(x) + else + fun_l8_n699(x) + end +end + +def fun_l7_n171(x) + if (x < 1) + fun_l8_n833(x) + else + fun_l8_n928(x) + end +end + +def fun_l7_n172(x) + if (x < 1) + fun_l8_n564(x) + else + fun_l8_n972(x) + end +end + +def fun_l7_n173(x) + if (x < 1) + fun_l8_n509(x) + else + fun_l8_n125(x) + end +end + +def fun_l7_n174(x) + if (x < 1) + fun_l8_n643(x) + else + fun_l8_n813(x) + end +end + +def fun_l7_n175(x) + if (x < 1) + fun_l8_n763(x) + else + fun_l8_n22(x) + end +end + +def fun_l7_n176(x) + if (x < 1) + fun_l8_n955(x) + else + fun_l8_n579(x) + end +end + +def fun_l7_n177(x) + if (x < 1) + fun_l8_n577(x) + else + fun_l8_n675(x) + end +end + +def fun_l7_n178(x) + if (x < 1) + fun_l8_n867(x) + else + fun_l8_n119(x) + end +end + +def fun_l7_n179(x) + if (x < 1) + fun_l8_n357(x) + else + fun_l8_n543(x) + end +end + +def fun_l7_n180(x) + if (x < 1) + fun_l8_n67(x) + else + fun_l8_n643(x) + end +end + +def fun_l7_n181(x) + if (x < 1) + fun_l8_n377(x) + else + fun_l8_n931(x) + end +end + +def fun_l7_n182(x) + if (x < 1) + fun_l8_n962(x) + else + fun_l8_n220(x) + end +end + +def fun_l7_n183(x) + if (x < 1) + fun_l8_n568(x) + else + fun_l8_n702(x) + end +end + +def fun_l7_n184(x) + if (x < 1) + fun_l8_n877(x) + else + fun_l8_n376(x) + end +end + +def fun_l7_n185(x) + if (x < 1) + fun_l8_n171(x) + else + fun_l8_n981(x) + end +end + +def fun_l7_n186(x) + if (x < 1) + fun_l8_n283(x) + else + fun_l8_n81(x) + end +end + +def fun_l7_n187(x) + if (x < 1) + fun_l8_n318(x) + else + fun_l8_n7(x) + end +end + +def fun_l7_n188(x) + if (x < 1) + fun_l8_n874(x) + else + fun_l8_n879(x) + end +end + +def fun_l7_n189(x) + if (x < 1) + fun_l8_n944(x) + else + fun_l8_n881(x) + end +end + +def fun_l7_n190(x) + if (x < 1) + fun_l8_n462(x) + else + fun_l8_n570(x) + end +end + +def fun_l7_n191(x) + if (x < 1) + fun_l8_n815(x) + else + fun_l8_n957(x) + end +end + +def fun_l7_n192(x) + if (x < 1) + fun_l8_n217(x) + else + fun_l8_n93(x) + end +end + +def fun_l7_n193(x) + if (x < 1) + fun_l8_n708(x) + else + fun_l8_n323(x) + end +end + +def fun_l7_n194(x) + if (x < 1) + fun_l8_n420(x) + else + fun_l8_n375(x) + end +end + +def fun_l7_n195(x) + if (x < 1) + fun_l8_n307(x) + else + fun_l8_n427(x) + end +end + +def fun_l7_n196(x) + if (x < 1) + fun_l8_n200(x) + else + fun_l8_n265(x) + end +end + +def fun_l7_n197(x) + if (x < 1) + fun_l8_n547(x) + else + fun_l8_n687(x) + end +end + +def fun_l7_n198(x) + if (x < 1) + fun_l8_n693(x) + else + fun_l8_n420(x) + end +end + +def fun_l7_n199(x) + if (x < 1) + fun_l8_n297(x) + else + fun_l8_n702(x) + end +end + +def fun_l7_n200(x) + if (x < 1) + fun_l8_n418(x) + else + fun_l8_n758(x) + end +end + +def fun_l7_n201(x) + if (x < 1) + fun_l8_n204(x) + else + fun_l8_n572(x) + end +end + +def fun_l7_n202(x) + if (x < 1) + fun_l8_n847(x) + else + fun_l8_n440(x) + end +end + +def fun_l7_n203(x) + if (x < 1) + fun_l8_n692(x) + else + fun_l8_n595(x) + end +end + +def fun_l7_n204(x) + if (x < 1) + fun_l8_n922(x) + else + fun_l8_n618(x) + end +end + +def fun_l7_n205(x) + if (x < 1) + fun_l8_n431(x) + else + fun_l8_n135(x) + end +end + +def fun_l7_n206(x) + if (x < 1) + fun_l8_n92(x) + else + fun_l8_n370(x) + end +end + +def fun_l7_n207(x) + if (x < 1) + fun_l8_n141(x) + else + fun_l8_n845(x) + end +end + +def fun_l7_n208(x) + if (x < 1) + fun_l8_n552(x) + else + fun_l8_n917(x) + end +end + +def fun_l7_n209(x) + if (x < 1) + fun_l8_n341(x) + else + fun_l8_n794(x) + end +end + +def fun_l7_n210(x) + if (x < 1) + fun_l8_n772(x) + else + fun_l8_n515(x) + end +end + +def fun_l7_n211(x) + if (x < 1) + fun_l8_n37(x) + else + fun_l8_n635(x) + end +end + +def fun_l7_n212(x) + if (x < 1) + fun_l8_n164(x) + else + fun_l8_n506(x) + end +end + +def fun_l7_n213(x) + if (x < 1) + fun_l8_n621(x) + else + fun_l8_n722(x) + end +end + +def fun_l7_n214(x) + if (x < 1) + fun_l8_n475(x) + else + fun_l8_n854(x) + end +end + +def fun_l7_n215(x) + if (x < 1) + fun_l8_n275(x) + else + fun_l8_n884(x) + end +end + +def fun_l7_n216(x) + if (x < 1) + fun_l8_n894(x) + else + fun_l8_n424(x) + end +end + +def fun_l7_n217(x) + if (x < 1) + fun_l8_n32(x) + else + fun_l8_n698(x) + end +end + +def fun_l7_n218(x) + if (x < 1) + fun_l8_n707(x) + else + fun_l8_n728(x) + end +end + +def fun_l7_n219(x) + if (x < 1) + fun_l8_n294(x) + else + fun_l8_n583(x) + end +end + +def fun_l7_n220(x) + if (x < 1) + fun_l8_n577(x) + else + fun_l8_n881(x) + end +end + +def fun_l7_n221(x) + if (x < 1) + fun_l8_n925(x) + else + fun_l8_n177(x) + end +end + +def fun_l7_n222(x) + if (x < 1) + fun_l8_n495(x) + else + fun_l8_n407(x) + end +end + +def fun_l7_n223(x) + if (x < 1) + fun_l8_n11(x) + else + fun_l8_n753(x) + end +end + +def fun_l7_n224(x) + if (x < 1) + fun_l8_n366(x) + else + fun_l8_n546(x) + end +end + +def fun_l7_n225(x) + if (x < 1) + fun_l8_n644(x) + else + fun_l8_n728(x) + end +end + +def fun_l7_n226(x) + if (x < 1) + fun_l8_n731(x) + else + fun_l8_n292(x) + end +end + +def fun_l7_n227(x) + if (x < 1) + fun_l8_n653(x) + else + fun_l8_n521(x) + end +end + +def fun_l7_n228(x) + if (x < 1) + fun_l8_n479(x) + else + fun_l8_n329(x) + end +end + +def fun_l7_n229(x) + if (x < 1) + fun_l8_n151(x) + else + fun_l8_n620(x) + end +end + +def fun_l7_n230(x) + if (x < 1) + fun_l8_n58(x) + else + fun_l8_n369(x) + end +end + +def fun_l7_n231(x) + if (x < 1) + fun_l8_n301(x) + else + fun_l8_n869(x) + end +end + +def fun_l7_n232(x) + if (x < 1) + fun_l8_n810(x) + else + fun_l8_n376(x) + end +end + +def fun_l7_n233(x) + if (x < 1) + fun_l8_n19(x) + else + fun_l8_n278(x) + end +end + +def fun_l7_n234(x) + if (x < 1) + fun_l8_n509(x) + else + fun_l8_n826(x) + end +end + +def fun_l7_n235(x) + if (x < 1) + fun_l8_n302(x) + else + fun_l8_n62(x) + end +end + +def fun_l7_n236(x) + if (x < 1) + fun_l8_n289(x) + else + fun_l8_n935(x) + end +end + +def fun_l7_n237(x) + if (x < 1) + fun_l8_n217(x) + else + fun_l8_n652(x) + end +end + +def fun_l7_n238(x) + if (x < 1) + fun_l8_n234(x) + else + fun_l8_n720(x) + end +end + +def fun_l7_n239(x) + if (x < 1) + fun_l8_n158(x) + else + fun_l8_n409(x) + end +end + +def fun_l7_n240(x) + if (x < 1) + fun_l8_n478(x) + else + fun_l8_n855(x) + end +end + +def fun_l7_n241(x) + if (x < 1) + fun_l8_n115(x) + else + fun_l8_n406(x) + end +end + +def fun_l7_n242(x) + if (x < 1) + fun_l8_n278(x) + else + fun_l8_n12(x) + end +end + +def fun_l7_n243(x) + if (x < 1) + fun_l8_n273(x) + else + fun_l8_n243(x) + end +end + +def fun_l7_n244(x) + if (x < 1) + fun_l8_n909(x) + else + fun_l8_n721(x) + end +end + +def fun_l7_n245(x) + if (x < 1) + fun_l8_n415(x) + else + fun_l8_n530(x) + end +end + +def fun_l7_n246(x) + if (x < 1) + fun_l8_n770(x) + else + fun_l8_n413(x) + end +end + +def fun_l7_n247(x) + if (x < 1) + fun_l8_n228(x) + else + fun_l8_n668(x) + end +end + +def fun_l7_n248(x) + if (x < 1) + fun_l8_n174(x) + else + fun_l8_n559(x) + end +end + +def fun_l7_n249(x) + if (x < 1) + fun_l8_n740(x) + else + fun_l8_n314(x) + end +end + +def fun_l7_n250(x) + if (x < 1) + fun_l8_n293(x) + else + fun_l8_n835(x) + end +end + +def fun_l7_n251(x) + if (x < 1) + fun_l8_n584(x) + else + fun_l8_n755(x) + end +end + +def fun_l7_n252(x) + if (x < 1) + fun_l8_n792(x) + else + fun_l8_n135(x) + end +end + +def fun_l7_n253(x) + if (x < 1) + fun_l8_n116(x) + else + fun_l8_n82(x) + end +end + +def fun_l7_n254(x) + if (x < 1) + fun_l8_n478(x) + else + fun_l8_n809(x) + end +end + +def fun_l7_n255(x) + if (x < 1) + fun_l8_n924(x) + else + fun_l8_n708(x) + end +end + +def fun_l7_n256(x) + if (x < 1) + fun_l8_n345(x) + else + fun_l8_n669(x) + end +end + +def fun_l7_n257(x) + if (x < 1) + fun_l8_n300(x) + else + fun_l8_n166(x) + end +end + +def fun_l7_n258(x) + if (x < 1) + fun_l8_n979(x) + else + fun_l8_n894(x) + end +end + +def fun_l7_n259(x) + if (x < 1) + fun_l8_n765(x) + else + fun_l8_n838(x) + end +end + +def fun_l7_n260(x) + if (x < 1) + fun_l8_n812(x) + else + fun_l8_n472(x) + end +end + +def fun_l7_n261(x) + if (x < 1) + fun_l8_n220(x) + else + fun_l8_n106(x) + end +end + +def fun_l7_n262(x) + if (x < 1) + fun_l8_n727(x) + else + fun_l8_n783(x) + end +end + +def fun_l7_n263(x) + if (x < 1) + fun_l8_n560(x) + else + fun_l8_n781(x) + end +end + +def fun_l7_n264(x) + if (x < 1) + fun_l8_n709(x) + else + fun_l8_n33(x) + end +end + +def fun_l7_n265(x) + if (x < 1) + fun_l8_n904(x) + else + fun_l8_n64(x) + end +end + +def fun_l7_n266(x) + if (x < 1) + fun_l8_n944(x) + else + fun_l8_n652(x) + end +end + +def fun_l7_n267(x) + if (x < 1) + fun_l8_n154(x) + else + fun_l8_n103(x) + end +end + +def fun_l7_n268(x) + if (x < 1) + fun_l8_n55(x) + else + fun_l8_n841(x) + end +end + +def fun_l7_n269(x) + if (x < 1) + fun_l8_n914(x) + else + fun_l8_n108(x) + end +end + +def fun_l7_n270(x) + if (x < 1) + fun_l8_n733(x) + else + fun_l8_n398(x) + end +end + +def fun_l7_n271(x) + if (x < 1) + fun_l8_n145(x) + else + fun_l8_n735(x) + end +end + +def fun_l7_n272(x) + if (x < 1) + fun_l8_n404(x) + else + fun_l8_n216(x) + end +end + +def fun_l7_n273(x) + if (x < 1) + fun_l8_n380(x) + else + fun_l8_n798(x) + end +end + +def fun_l7_n274(x) + if (x < 1) + fun_l8_n63(x) + else + fun_l8_n133(x) + end +end + +def fun_l7_n275(x) + if (x < 1) + fun_l8_n878(x) + else + fun_l8_n284(x) + end +end + +def fun_l7_n276(x) + if (x < 1) + fun_l8_n718(x) + else + fun_l8_n97(x) + end +end + +def fun_l7_n277(x) + if (x < 1) + fun_l8_n509(x) + else + fun_l8_n695(x) + end +end + +def fun_l7_n278(x) + if (x < 1) + fun_l8_n581(x) + else + fun_l8_n898(x) + end +end + +def fun_l7_n279(x) + if (x < 1) + fun_l8_n247(x) + else + fun_l8_n526(x) + end +end + +def fun_l7_n280(x) + if (x < 1) + fun_l8_n995(x) + else + fun_l8_n614(x) + end +end + +def fun_l7_n281(x) + if (x < 1) + fun_l8_n301(x) + else + fun_l8_n178(x) + end +end + +def fun_l7_n282(x) + if (x < 1) + fun_l8_n575(x) + else + fun_l8_n712(x) + end +end + +def fun_l7_n283(x) + if (x < 1) + fun_l8_n261(x) + else + fun_l8_n740(x) + end +end + +def fun_l7_n284(x) + if (x < 1) + fun_l8_n284(x) + else + fun_l8_n350(x) + end +end + +def fun_l7_n285(x) + if (x < 1) + fun_l8_n521(x) + else + fun_l8_n305(x) + end +end + +def fun_l7_n286(x) + if (x < 1) + fun_l8_n271(x) + else + fun_l8_n728(x) + end +end + +def fun_l7_n287(x) + if (x < 1) + fun_l8_n292(x) + else + fun_l8_n799(x) + end +end + +def fun_l7_n288(x) + if (x < 1) + fun_l8_n852(x) + else + fun_l8_n606(x) + end +end + +def fun_l7_n289(x) + if (x < 1) + fun_l8_n177(x) + else + fun_l8_n649(x) + end +end + +def fun_l7_n290(x) + if (x < 1) + fun_l8_n488(x) + else + fun_l8_n252(x) + end +end + +def fun_l7_n291(x) + if (x < 1) + fun_l8_n815(x) + else + fun_l8_n690(x) + end +end + +def fun_l7_n292(x) + if (x < 1) + fun_l8_n999(x) + else + fun_l8_n700(x) + end +end + +def fun_l7_n293(x) + if (x < 1) + fun_l8_n9(x) + else + fun_l8_n194(x) + end +end + +def fun_l7_n294(x) + if (x < 1) + fun_l8_n390(x) + else + fun_l8_n772(x) + end +end + +def fun_l7_n295(x) + if (x < 1) + fun_l8_n487(x) + else + fun_l8_n587(x) + end +end + +def fun_l7_n296(x) + if (x < 1) + fun_l8_n892(x) + else + fun_l8_n126(x) + end +end + +def fun_l7_n297(x) + if (x < 1) + fun_l8_n199(x) + else + fun_l8_n312(x) + end +end + +def fun_l7_n298(x) + if (x < 1) + fun_l8_n534(x) + else + fun_l8_n640(x) + end +end + +def fun_l7_n299(x) + if (x < 1) + fun_l8_n344(x) + else + fun_l8_n58(x) + end +end + +def fun_l7_n300(x) + if (x < 1) + fun_l8_n11(x) + else + fun_l8_n922(x) + end +end + +def fun_l7_n301(x) + if (x < 1) + fun_l8_n848(x) + else + fun_l8_n432(x) + end +end + +def fun_l7_n302(x) + if (x < 1) + fun_l8_n292(x) + else + fun_l8_n86(x) + end +end + +def fun_l7_n303(x) + if (x < 1) + fun_l8_n239(x) + else + fun_l8_n296(x) + end +end + +def fun_l7_n304(x) + if (x < 1) + fun_l8_n350(x) + else + fun_l8_n769(x) + end +end + +def fun_l7_n305(x) + if (x < 1) + fun_l8_n959(x) + else + fun_l8_n292(x) + end +end + +def fun_l7_n306(x) + if (x < 1) + fun_l8_n371(x) + else + fun_l8_n507(x) + end +end + +def fun_l7_n307(x) + if (x < 1) + fun_l8_n910(x) + else + fun_l8_n542(x) + end +end + +def fun_l7_n308(x) + if (x < 1) + fun_l8_n299(x) + else + fun_l8_n543(x) + end +end + +def fun_l7_n309(x) + if (x < 1) + fun_l8_n145(x) + else + fun_l8_n393(x) + end +end + +def fun_l7_n310(x) + if (x < 1) + fun_l8_n1(x) + else + fun_l8_n810(x) + end +end + +def fun_l7_n311(x) + if (x < 1) + fun_l8_n866(x) + else + fun_l8_n519(x) + end +end + +def fun_l7_n312(x) + if (x < 1) + fun_l8_n730(x) + else + fun_l8_n912(x) + end +end + +def fun_l7_n313(x) + if (x < 1) + fun_l8_n128(x) + else + fun_l8_n3(x) + end +end + +def fun_l7_n314(x) + if (x < 1) + fun_l8_n393(x) + else + fun_l8_n887(x) + end +end + +def fun_l7_n315(x) + if (x < 1) + fun_l8_n165(x) + else + fun_l8_n540(x) + end +end + +def fun_l7_n316(x) + if (x < 1) + fun_l8_n641(x) + else + fun_l8_n255(x) + end +end + +def fun_l7_n317(x) + if (x < 1) + fun_l8_n265(x) + else + fun_l8_n754(x) + end +end + +def fun_l7_n318(x) + if (x < 1) + fun_l8_n433(x) + else + fun_l8_n163(x) + end +end + +def fun_l7_n319(x) + if (x < 1) + fun_l8_n409(x) + else + fun_l8_n110(x) + end +end + +def fun_l7_n320(x) + if (x < 1) + fun_l8_n704(x) + else + fun_l8_n959(x) + end +end + +def fun_l7_n321(x) + if (x < 1) + fun_l8_n334(x) + else + fun_l8_n280(x) + end +end + +def fun_l7_n322(x) + if (x < 1) + fun_l8_n107(x) + else + fun_l8_n403(x) + end +end + +def fun_l7_n323(x) + if (x < 1) + fun_l8_n108(x) + else + fun_l8_n426(x) + end +end + +def fun_l7_n324(x) + if (x < 1) + fun_l8_n310(x) + else + fun_l8_n968(x) + end +end + +def fun_l7_n325(x) + if (x < 1) + fun_l8_n600(x) + else + fun_l8_n850(x) + end +end + +def fun_l7_n326(x) + if (x < 1) + fun_l8_n736(x) + else + fun_l8_n61(x) + end +end + +def fun_l7_n327(x) + if (x < 1) + fun_l8_n86(x) + else + fun_l8_n948(x) + end +end + +def fun_l7_n328(x) + if (x < 1) + fun_l8_n625(x) + else + fun_l8_n644(x) + end +end + +def fun_l7_n329(x) + if (x < 1) + fun_l8_n507(x) + else + fun_l8_n624(x) + end +end + +def fun_l7_n330(x) + if (x < 1) + fun_l8_n956(x) + else + fun_l8_n281(x) + end +end + +def fun_l7_n331(x) + if (x < 1) + fun_l8_n72(x) + else + fun_l8_n695(x) + end +end + +def fun_l7_n332(x) + if (x < 1) + fun_l8_n445(x) + else + fun_l8_n465(x) + end +end + +def fun_l7_n333(x) + if (x < 1) + fun_l8_n438(x) + else + fun_l8_n698(x) + end +end + +def fun_l7_n334(x) + if (x < 1) + fun_l8_n242(x) + else + fun_l8_n837(x) + end +end + +def fun_l7_n335(x) + if (x < 1) + fun_l8_n299(x) + else + fun_l8_n312(x) + end +end + +def fun_l7_n336(x) + if (x < 1) + fun_l8_n264(x) + else + fun_l8_n330(x) + end +end + +def fun_l7_n337(x) + if (x < 1) + fun_l8_n251(x) + else + fun_l8_n459(x) + end +end + +def fun_l7_n338(x) + if (x < 1) + fun_l8_n876(x) + else + fun_l8_n689(x) + end +end + +def fun_l7_n339(x) + if (x < 1) + fun_l8_n547(x) + else + fun_l8_n745(x) + end +end + +def fun_l7_n340(x) + if (x < 1) + fun_l8_n493(x) + else + fun_l8_n877(x) + end +end + +def fun_l7_n341(x) + if (x < 1) + fun_l8_n143(x) + else + fun_l8_n429(x) + end +end + +def fun_l7_n342(x) + if (x < 1) + fun_l8_n650(x) + else + fun_l8_n384(x) + end +end + +def fun_l7_n343(x) + if (x < 1) + fun_l8_n897(x) + else + fun_l8_n980(x) + end +end + +def fun_l7_n344(x) + if (x < 1) + fun_l8_n699(x) + else + fun_l8_n673(x) + end +end + +def fun_l7_n345(x) + if (x < 1) + fun_l8_n25(x) + else + fun_l8_n342(x) + end +end + +def fun_l7_n346(x) + if (x < 1) + fun_l8_n345(x) + else + fun_l8_n140(x) + end +end + +def fun_l7_n347(x) + if (x < 1) + fun_l8_n661(x) + else + fun_l8_n153(x) + end +end + +def fun_l7_n348(x) + if (x < 1) + fun_l8_n477(x) + else + fun_l8_n460(x) + end +end + +def fun_l7_n349(x) + if (x < 1) + fun_l8_n641(x) + else + fun_l8_n941(x) + end +end + +def fun_l7_n350(x) + if (x < 1) + fun_l8_n952(x) + else + fun_l8_n886(x) + end +end + +def fun_l7_n351(x) + if (x < 1) + fun_l8_n338(x) + else + fun_l8_n655(x) + end +end + +def fun_l7_n352(x) + if (x < 1) + fun_l8_n717(x) + else + fun_l8_n314(x) + end +end + +def fun_l7_n353(x) + if (x < 1) + fun_l8_n645(x) + else + fun_l8_n464(x) + end +end + +def fun_l7_n354(x) + if (x < 1) + fun_l8_n114(x) + else + fun_l8_n816(x) + end +end + +def fun_l7_n355(x) + if (x < 1) + fun_l8_n18(x) + else + fun_l8_n173(x) + end +end + +def fun_l7_n356(x) + if (x < 1) + fun_l8_n214(x) + else + fun_l8_n834(x) + end +end + +def fun_l7_n357(x) + if (x < 1) + fun_l8_n6(x) + else + fun_l8_n161(x) + end +end + +def fun_l7_n358(x) + if (x < 1) + fun_l8_n823(x) + else + fun_l8_n695(x) + end +end + +def fun_l7_n359(x) + if (x < 1) + fun_l8_n86(x) + else + fun_l8_n174(x) + end +end + +def fun_l7_n360(x) + if (x < 1) + fun_l8_n904(x) + else + fun_l8_n240(x) + end +end + +def fun_l7_n361(x) + if (x < 1) + fun_l8_n857(x) + else + fun_l8_n494(x) + end +end + +def fun_l7_n362(x) + if (x < 1) + fun_l8_n780(x) + else + fun_l8_n186(x) + end +end + +def fun_l7_n363(x) + if (x < 1) + fun_l8_n575(x) + else + fun_l8_n510(x) + end +end + +def fun_l7_n364(x) + if (x < 1) + fun_l8_n412(x) + else + fun_l8_n153(x) + end +end + +def fun_l7_n365(x) + if (x < 1) + fun_l8_n840(x) + else + fun_l8_n199(x) + end +end + +def fun_l7_n366(x) + if (x < 1) + fun_l8_n162(x) + else + fun_l8_n971(x) + end +end + +def fun_l7_n367(x) + if (x < 1) + fun_l8_n200(x) + else + fun_l8_n128(x) + end +end + +def fun_l7_n368(x) + if (x < 1) + fun_l8_n404(x) + else + fun_l8_n657(x) + end +end + +def fun_l7_n369(x) + if (x < 1) + fun_l8_n631(x) + else + fun_l8_n714(x) + end +end + +def fun_l7_n370(x) + if (x < 1) + fun_l8_n177(x) + else + fun_l8_n718(x) + end +end + +def fun_l7_n371(x) + if (x < 1) + fun_l8_n284(x) + else + fun_l8_n474(x) + end +end + +def fun_l7_n372(x) + if (x < 1) + fun_l8_n138(x) + else + fun_l8_n461(x) + end +end + +def fun_l7_n373(x) + if (x < 1) + fun_l8_n78(x) + else + fun_l8_n750(x) + end +end + +def fun_l7_n374(x) + if (x < 1) + fun_l8_n231(x) + else + fun_l8_n648(x) + end +end + +def fun_l7_n375(x) + if (x < 1) + fun_l8_n238(x) + else + fun_l8_n644(x) + end +end + +def fun_l7_n376(x) + if (x < 1) + fun_l8_n509(x) + else + fun_l8_n354(x) + end +end + +def fun_l7_n377(x) + if (x < 1) + fun_l8_n332(x) + else + fun_l8_n739(x) + end +end + +def fun_l7_n378(x) + if (x < 1) + fun_l8_n76(x) + else + fun_l8_n505(x) + end +end + +def fun_l7_n379(x) + if (x < 1) + fun_l8_n781(x) + else + fun_l8_n918(x) + end +end + +def fun_l7_n380(x) + if (x < 1) + fun_l8_n854(x) + else + fun_l8_n85(x) + end +end + +def fun_l7_n381(x) + if (x < 1) + fun_l8_n67(x) + else + fun_l8_n690(x) + end +end + +def fun_l7_n382(x) + if (x < 1) + fun_l8_n425(x) + else + fun_l8_n643(x) + end +end + +def fun_l7_n383(x) + if (x < 1) + fun_l8_n210(x) + else + fun_l8_n533(x) + end +end + +def fun_l7_n384(x) + if (x < 1) + fun_l8_n469(x) + else + fun_l8_n274(x) + end +end + +def fun_l7_n385(x) + if (x < 1) + fun_l8_n398(x) + else + fun_l8_n583(x) + end +end + +def fun_l7_n386(x) + if (x < 1) + fun_l8_n483(x) + else + fun_l8_n80(x) + end +end + +def fun_l7_n387(x) + if (x < 1) + fun_l8_n557(x) + else + fun_l8_n165(x) + end +end + +def fun_l7_n388(x) + if (x < 1) + fun_l8_n335(x) + else + fun_l8_n656(x) + end +end + +def fun_l7_n389(x) + if (x < 1) + fun_l8_n810(x) + else + fun_l8_n586(x) + end +end + +def fun_l7_n390(x) + if (x < 1) + fun_l8_n90(x) + else + fun_l8_n788(x) + end +end + +def fun_l7_n391(x) + if (x < 1) + fun_l8_n709(x) + else + fun_l8_n948(x) + end +end + +def fun_l7_n392(x) + if (x < 1) + fun_l8_n139(x) + else + fun_l8_n631(x) + end +end + +def fun_l7_n393(x) + if (x < 1) + fun_l8_n341(x) + else + fun_l8_n506(x) + end +end + +def fun_l7_n394(x) + if (x < 1) + fun_l8_n435(x) + else + fun_l8_n178(x) + end +end + +def fun_l7_n395(x) + if (x < 1) + fun_l8_n186(x) + else + fun_l8_n58(x) + end +end + +def fun_l7_n396(x) + if (x < 1) + fun_l8_n512(x) + else + fun_l8_n87(x) + end +end + +def fun_l7_n397(x) + if (x < 1) + fun_l8_n763(x) + else + fun_l8_n220(x) + end +end + +def fun_l7_n398(x) + if (x < 1) + fun_l8_n266(x) + else + fun_l8_n231(x) + end +end + +def fun_l7_n399(x) + if (x < 1) + fun_l8_n308(x) + else + fun_l8_n512(x) + end +end + +def fun_l7_n400(x) + if (x < 1) + fun_l8_n26(x) + else + fun_l8_n228(x) + end +end + +def fun_l7_n401(x) + if (x < 1) + fun_l8_n143(x) + else + fun_l8_n826(x) + end +end + +def fun_l7_n402(x) + if (x < 1) + fun_l8_n893(x) + else + fun_l8_n334(x) + end +end + +def fun_l7_n403(x) + if (x < 1) + fun_l8_n9(x) + else + fun_l8_n867(x) + end +end + +def fun_l7_n404(x) + if (x < 1) + fun_l8_n85(x) + else + fun_l8_n279(x) + end +end + +def fun_l7_n405(x) + if (x < 1) + fun_l8_n30(x) + else + fun_l8_n85(x) + end +end + +def fun_l7_n406(x) + if (x < 1) + fun_l8_n38(x) + else + fun_l8_n979(x) + end +end + +def fun_l7_n407(x) + if (x < 1) + fun_l8_n630(x) + else + fun_l8_n262(x) + end +end + +def fun_l7_n408(x) + if (x < 1) + fun_l8_n430(x) + else + fun_l8_n178(x) + end +end + +def fun_l7_n409(x) + if (x < 1) + fun_l8_n131(x) + else + fun_l8_n66(x) + end +end + +def fun_l7_n410(x) + if (x < 1) + fun_l8_n373(x) + else + fun_l8_n514(x) + end +end + +def fun_l7_n411(x) + if (x < 1) + fun_l8_n334(x) + else + fun_l8_n591(x) + end +end + +def fun_l7_n412(x) + if (x < 1) + fun_l8_n619(x) + else + fun_l8_n490(x) + end +end + +def fun_l7_n413(x) + if (x < 1) + fun_l8_n318(x) + else + fun_l8_n456(x) + end +end + +def fun_l7_n414(x) + if (x < 1) + fun_l8_n576(x) + else + fun_l8_n638(x) + end +end + +def fun_l7_n415(x) + if (x < 1) + fun_l8_n407(x) + else + fun_l8_n44(x) + end +end + +def fun_l7_n416(x) + if (x < 1) + fun_l8_n970(x) + else + fun_l8_n564(x) + end +end + +def fun_l7_n417(x) + if (x < 1) + fun_l8_n163(x) + else + fun_l8_n533(x) + end +end + +def fun_l7_n418(x) + if (x < 1) + fun_l8_n216(x) + else + fun_l8_n604(x) + end +end + +def fun_l7_n419(x) + if (x < 1) + fun_l8_n505(x) + else + fun_l8_n620(x) + end +end + +def fun_l7_n420(x) + if (x < 1) + fun_l8_n746(x) + else + fun_l8_n998(x) + end +end + +def fun_l7_n421(x) + if (x < 1) + fun_l8_n266(x) + else + fun_l8_n762(x) + end +end + +def fun_l7_n422(x) + if (x < 1) + fun_l8_n216(x) + else + fun_l8_n995(x) + end +end + +def fun_l7_n423(x) + if (x < 1) + fun_l8_n824(x) + else + fun_l8_n349(x) + end +end + +def fun_l7_n424(x) + if (x < 1) + fun_l8_n177(x) + else + fun_l8_n61(x) + end +end + +def fun_l7_n425(x) + if (x < 1) + fun_l8_n286(x) + else + fun_l8_n213(x) + end +end + +def fun_l7_n426(x) + if (x < 1) + fun_l8_n794(x) + else + fun_l8_n428(x) + end +end + +def fun_l7_n427(x) + if (x < 1) + fun_l8_n404(x) + else + fun_l8_n202(x) + end +end + +def fun_l7_n428(x) + if (x < 1) + fun_l8_n571(x) + else + fun_l8_n812(x) + end +end + +def fun_l7_n429(x) + if (x < 1) + fun_l8_n165(x) + else + fun_l8_n277(x) + end +end + +def fun_l7_n430(x) + if (x < 1) + fun_l8_n138(x) + else + fun_l8_n230(x) + end +end + +def fun_l7_n431(x) + if (x < 1) + fun_l8_n832(x) + else + fun_l8_n78(x) + end +end + +def fun_l7_n432(x) + if (x < 1) + fun_l8_n866(x) + else + fun_l8_n137(x) + end +end + +def fun_l7_n433(x) + if (x < 1) + fun_l8_n92(x) + else + fun_l8_n638(x) + end +end + +def fun_l7_n434(x) + if (x < 1) + fun_l8_n788(x) + else + fun_l8_n991(x) + end +end + +def fun_l7_n435(x) + if (x < 1) + fun_l8_n584(x) + else + fun_l8_n783(x) + end +end + +def fun_l7_n436(x) + if (x < 1) + fun_l8_n786(x) + else + fun_l8_n771(x) + end +end + +def fun_l7_n437(x) + if (x < 1) + fun_l8_n650(x) + else + fun_l8_n684(x) + end +end + +def fun_l7_n438(x) + if (x < 1) + fun_l8_n964(x) + else + fun_l8_n738(x) + end +end + +def fun_l7_n439(x) + if (x < 1) + fun_l8_n356(x) + else + fun_l8_n979(x) + end +end + +def fun_l7_n440(x) + if (x < 1) + fun_l8_n630(x) + else + fun_l8_n79(x) + end +end + +def fun_l7_n441(x) + if (x < 1) + fun_l8_n326(x) + else + fun_l8_n667(x) + end +end + +def fun_l7_n442(x) + if (x < 1) + fun_l8_n561(x) + else + fun_l8_n263(x) + end +end + +def fun_l7_n443(x) + if (x < 1) + fun_l8_n62(x) + else + fun_l8_n528(x) + end +end + +def fun_l7_n444(x) + if (x < 1) + fun_l8_n156(x) + else + fun_l8_n496(x) + end +end + +def fun_l7_n445(x) + if (x < 1) + fun_l8_n971(x) + else + fun_l8_n853(x) + end +end + +def fun_l7_n446(x) + if (x < 1) + fun_l8_n217(x) + else + fun_l8_n985(x) + end +end + +def fun_l7_n447(x) + if (x < 1) + fun_l8_n569(x) + else + fun_l8_n320(x) + end +end + +def fun_l7_n448(x) + if (x < 1) + fun_l8_n133(x) + else + fun_l8_n417(x) + end +end + +def fun_l7_n449(x) + if (x < 1) + fun_l8_n369(x) + else + fun_l8_n25(x) + end +end + +def fun_l7_n450(x) + if (x < 1) + fun_l8_n735(x) + else + fun_l8_n573(x) + end +end + +def fun_l7_n451(x) + if (x < 1) + fun_l8_n764(x) + else + fun_l8_n247(x) + end +end + +def fun_l7_n452(x) + if (x < 1) + fun_l8_n512(x) + else + fun_l8_n274(x) + end +end + +def fun_l7_n453(x) + if (x < 1) + fun_l8_n388(x) + else + fun_l8_n438(x) + end +end + +def fun_l7_n454(x) + if (x < 1) + fun_l8_n565(x) + else + fun_l8_n449(x) + end +end + +def fun_l7_n455(x) + if (x < 1) + fun_l8_n771(x) + else + fun_l8_n827(x) + end +end + +def fun_l7_n456(x) + if (x < 1) + fun_l8_n538(x) + else + fun_l8_n270(x) + end +end + +def fun_l7_n457(x) + if (x < 1) + fun_l8_n288(x) + else + fun_l8_n325(x) + end +end + +def fun_l7_n458(x) + if (x < 1) + fun_l8_n345(x) + else + fun_l8_n334(x) + end +end + +def fun_l7_n459(x) + if (x < 1) + fun_l8_n696(x) + else + fun_l8_n440(x) + end +end + +def fun_l7_n460(x) + if (x < 1) + fun_l8_n509(x) + else + fun_l8_n580(x) + end +end + +def fun_l7_n461(x) + if (x < 1) + fun_l8_n254(x) + else + fun_l8_n162(x) + end +end + +def fun_l7_n462(x) + if (x < 1) + fun_l8_n541(x) + else + fun_l8_n493(x) + end +end + +def fun_l7_n463(x) + if (x < 1) + fun_l8_n371(x) + else + fun_l8_n302(x) + end +end + +def fun_l7_n464(x) + if (x < 1) + fun_l8_n44(x) + else + fun_l8_n677(x) + end +end + +def fun_l7_n465(x) + if (x < 1) + fun_l8_n312(x) + else + fun_l8_n716(x) + end +end + +def fun_l7_n466(x) + if (x < 1) + fun_l8_n252(x) + else + fun_l8_n827(x) + end +end + +def fun_l7_n467(x) + if (x < 1) + fun_l8_n871(x) + else + fun_l8_n962(x) + end +end + +def fun_l7_n468(x) + if (x < 1) + fun_l8_n323(x) + else + fun_l8_n813(x) + end +end + +def fun_l7_n469(x) + if (x < 1) + fun_l8_n100(x) + else + fun_l8_n905(x) + end +end + +def fun_l7_n470(x) + if (x < 1) + fun_l8_n95(x) + else + fun_l8_n96(x) + end +end + +def fun_l7_n471(x) + if (x < 1) + fun_l8_n398(x) + else + fun_l8_n40(x) + end +end + +def fun_l7_n472(x) + if (x < 1) + fun_l8_n280(x) + else + fun_l8_n34(x) + end +end + +def fun_l7_n473(x) + if (x < 1) + fun_l8_n262(x) + else + fun_l8_n399(x) + end +end + +def fun_l7_n474(x) + if (x < 1) + fun_l8_n126(x) + else + fun_l8_n208(x) + end +end + +def fun_l7_n475(x) + if (x < 1) + fun_l8_n371(x) + else + fun_l8_n697(x) + end +end + +def fun_l7_n476(x) + if (x < 1) + fun_l8_n617(x) + else + fun_l8_n822(x) + end +end + +def fun_l7_n477(x) + if (x < 1) + fun_l8_n24(x) + else + fun_l8_n300(x) + end +end + +def fun_l7_n478(x) + if (x < 1) + fun_l8_n864(x) + else + fun_l8_n357(x) + end +end + +def fun_l7_n479(x) + if (x < 1) + fun_l8_n231(x) + else + fun_l8_n892(x) + end +end + +def fun_l7_n480(x) + if (x < 1) + fun_l8_n200(x) + else + fun_l8_n49(x) + end +end + +def fun_l7_n481(x) + if (x < 1) + fun_l8_n43(x) + else + fun_l8_n86(x) + end +end + +def fun_l7_n482(x) + if (x < 1) + fun_l8_n617(x) + else + fun_l8_n752(x) + end +end + +def fun_l7_n483(x) + if (x < 1) + fun_l8_n65(x) + else + fun_l8_n796(x) + end +end + +def fun_l7_n484(x) + if (x < 1) + fun_l8_n960(x) + else + fun_l8_n174(x) + end +end + +def fun_l7_n485(x) + if (x < 1) + fun_l8_n383(x) + else + fun_l8_n50(x) + end +end + +def fun_l7_n486(x) + if (x < 1) + fun_l8_n269(x) + else + fun_l8_n413(x) + end +end + +def fun_l7_n487(x) + if (x < 1) + fun_l8_n762(x) + else + fun_l8_n368(x) + end +end + +def fun_l7_n488(x) + if (x < 1) + fun_l8_n635(x) + else + fun_l8_n900(x) + end +end + +def fun_l7_n489(x) + if (x < 1) + fun_l8_n707(x) + else + fun_l8_n376(x) + end +end + +def fun_l7_n490(x) + if (x < 1) + fun_l8_n215(x) + else + fun_l8_n255(x) + end +end + +def fun_l7_n491(x) + if (x < 1) + fun_l8_n730(x) + else + fun_l8_n489(x) + end +end + +def fun_l7_n492(x) + if (x < 1) + fun_l8_n896(x) + else + fun_l8_n501(x) + end +end + +def fun_l7_n493(x) + if (x < 1) + fun_l8_n359(x) + else + fun_l8_n876(x) + end +end + +def fun_l7_n494(x) + if (x < 1) + fun_l8_n13(x) + else + fun_l8_n669(x) + end +end + +def fun_l7_n495(x) + if (x < 1) + fun_l8_n442(x) + else + fun_l8_n975(x) + end +end + +def fun_l7_n496(x) + if (x < 1) + fun_l8_n349(x) + else + fun_l8_n240(x) + end +end + +def fun_l7_n497(x) + if (x < 1) + fun_l8_n174(x) + else + fun_l8_n416(x) + end +end + +def fun_l7_n498(x) + if (x < 1) + fun_l8_n141(x) + else + fun_l8_n231(x) + end +end + +def fun_l7_n499(x) + if (x < 1) + fun_l8_n868(x) + else + fun_l8_n370(x) + end +end + +def fun_l7_n500(x) + if (x < 1) + fun_l8_n888(x) + else + fun_l8_n525(x) + end +end + +def fun_l7_n501(x) + if (x < 1) + fun_l8_n418(x) + else + fun_l8_n402(x) + end +end + +def fun_l7_n502(x) + if (x < 1) + fun_l8_n910(x) + else + fun_l8_n308(x) + end +end + +def fun_l7_n503(x) + if (x < 1) + fun_l8_n435(x) + else + fun_l8_n106(x) + end +end + +def fun_l7_n504(x) + if (x < 1) + fun_l8_n716(x) + else + fun_l8_n768(x) + end +end + +def fun_l7_n505(x) + if (x < 1) + fun_l8_n690(x) + else + fun_l8_n382(x) + end +end + +def fun_l7_n506(x) + if (x < 1) + fun_l8_n786(x) + else + fun_l8_n270(x) + end +end + +def fun_l7_n507(x) + if (x < 1) + fun_l8_n317(x) + else + fun_l8_n802(x) + end +end + +def fun_l7_n508(x) + if (x < 1) + fun_l8_n423(x) + else + fun_l8_n91(x) + end +end + +def fun_l7_n509(x) + if (x < 1) + fun_l8_n853(x) + else + fun_l8_n434(x) + end +end + +def fun_l7_n510(x) + if (x < 1) + fun_l8_n691(x) + else + fun_l8_n458(x) + end +end + +def fun_l7_n511(x) + if (x < 1) + fun_l8_n806(x) + else + fun_l8_n989(x) + end +end + +def fun_l7_n512(x) + if (x < 1) + fun_l8_n696(x) + else + fun_l8_n234(x) + end +end + +def fun_l7_n513(x) + if (x < 1) + fun_l8_n370(x) + else + fun_l8_n440(x) + end +end + +def fun_l7_n514(x) + if (x < 1) + fun_l8_n889(x) + else + fun_l8_n306(x) + end +end + +def fun_l7_n515(x) + if (x < 1) + fun_l8_n147(x) + else + fun_l8_n527(x) + end +end + +def fun_l7_n516(x) + if (x < 1) + fun_l8_n18(x) + else + fun_l8_n120(x) + end +end + +def fun_l7_n517(x) + if (x < 1) + fun_l8_n93(x) + else + fun_l8_n861(x) + end +end + +def fun_l7_n518(x) + if (x < 1) + fun_l8_n954(x) + else + fun_l8_n864(x) + end +end + +def fun_l7_n519(x) + if (x < 1) + fun_l8_n886(x) + else + fun_l8_n227(x) + end +end + +def fun_l7_n520(x) + if (x < 1) + fun_l8_n525(x) + else + fun_l8_n73(x) + end +end + +def fun_l7_n521(x) + if (x < 1) + fun_l8_n550(x) + else + fun_l8_n638(x) + end +end + +def fun_l7_n522(x) + if (x < 1) + fun_l8_n36(x) + else + fun_l8_n511(x) + end +end + +def fun_l7_n523(x) + if (x < 1) + fun_l8_n346(x) + else + fun_l8_n257(x) + end +end + +def fun_l7_n524(x) + if (x < 1) + fun_l8_n973(x) + else + fun_l8_n704(x) + end +end + +def fun_l7_n525(x) + if (x < 1) + fun_l8_n21(x) + else + fun_l8_n354(x) + end +end + +def fun_l7_n526(x) + if (x < 1) + fun_l8_n394(x) + else + fun_l8_n461(x) + end +end + +def fun_l7_n527(x) + if (x < 1) + fun_l8_n444(x) + else + fun_l8_n333(x) + end +end + +def fun_l7_n528(x) + if (x < 1) + fun_l8_n743(x) + else + fun_l8_n579(x) + end +end + +def fun_l7_n529(x) + if (x < 1) + fun_l8_n135(x) + else + fun_l8_n69(x) + end +end + +def fun_l7_n530(x) + if (x < 1) + fun_l8_n66(x) + else + fun_l8_n6(x) + end +end + +def fun_l7_n531(x) + if (x < 1) + fun_l8_n84(x) + else + fun_l8_n392(x) + end +end + +def fun_l7_n532(x) + if (x < 1) + fun_l8_n178(x) + else + fun_l8_n227(x) + end +end + +def fun_l7_n533(x) + if (x < 1) + fun_l8_n695(x) + else + fun_l8_n696(x) + end +end + +def fun_l7_n534(x) + if (x < 1) + fun_l8_n266(x) + else + fun_l8_n8(x) + end +end + +def fun_l7_n535(x) + if (x < 1) + fun_l8_n806(x) + else + fun_l8_n878(x) + end +end + +def fun_l7_n536(x) + if (x < 1) + fun_l8_n775(x) + else + fun_l8_n778(x) + end +end + +def fun_l7_n537(x) + if (x < 1) + fun_l8_n133(x) + else + fun_l8_n552(x) + end +end + +def fun_l7_n538(x) + if (x < 1) + fun_l8_n71(x) + else + fun_l8_n786(x) + end +end + +def fun_l7_n539(x) + if (x < 1) + fun_l8_n679(x) + else + fun_l8_n407(x) + end +end + +def fun_l7_n540(x) + if (x < 1) + fun_l8_n532(x) + else + fun_l8_n75(x) + end +end + +def fun_l7_n541(x) + if (x < 1) + fun_l8_n367(x) + else + fun_l8_n505(x) + end +end + +def fun_l7_n542(x) + if (x < 1) + fun_l8_n74(x) + else + fun_l8_n374(x) + end +end + +def fun_l7_n543(x) + if (x < 1) + fun_l8_n207(x) + else + fun_l8_n874(x) + end +end + +def fun_l7_n544(x) + if (x < 1) + fun_l8_n774(x) + else + fun_l8_n750(x) + end +end + +def fun_l7_n545(x) + if (x < 1) + fun_l8_n503(x) + else + fun_l8_n933(x) + end +end + +def fun_l7_n546(x) + if (x < 1) + fun_l8_n125(x) + else + fun_l8_n570(x) + end +end + +def fun_l7_n547(x) + if (x < 1) + fun_l8_n743(x) + else + fun_l8_n506(x) + end +end + +def fun_l7_n548(x) + if (x < 1) + fun_l8_n297(x) + else + fun_l8_n70(x) + end +end + +def fun_l7_n549(x) + if (x < 1) + fun_l8_n692(x) + else + fun_l8_n652(x) + end +end + +def fun_l7_n550(x) + if (x < 1) + fun_l8_n446(x) + else + fun_l8_n432(x) + end +end + +def fun_l7_n551(x) + if (x < 1) + fun_l8_n947(x) + else + fun_l8_n429(x) + end +end + +def fun_l7_n552(x) + if (x < 1) + fun_l8_n417(x) + else + fun_l8_n136(x) + end +end + +def fun_l7_n553(x) + if (x < 1) + fun_l8_n236(x) + else + fun_l8_n291(x) + end +end + +def fun_l7_n554(x) + if (x < 1) + fun_l8_n60(x) + else + fun_l8_n328(x) + end +end + +def fun_l7_n555(x) + if (x < 1) + fun_l8_n97(x) + else + fun_l8_n461(x) + end +end + +def fun_l7_n556(x) + if (x < 1) + fun_l8_n158(x) + else + fun_l8_n603(x) + end +end + +def fun_l7_n557(x) + if (x < 1) + fun_l8_n328(x) + else + fun_l8_n725(x) + end +end + +def fun_l7_n558(x) + if (x < 1) + fun_l8_n25(x) + else + fun_l8_n933(x) + end +end + +def fun_l7_n559(x) + if (x < 1) + fun_l8_n352(x) + else + fun_l8_n552(x) + end +end + +def fun_l7_n560(x) + if (x < 1) + fun_l8_n427(x) + else + fun_l8_n91(x) + end +end + +def fun_l7_n561(x) + if (x < 1) + fun_l8_n293(x) + else + fun_l8_n749(x) + end +end + +def fun_l7_n562(x) + if (x < 1) + fun_l8_n672(x) + else + fun_l8_n905(x) + end +end + +def fun_l7_n563(x) + if (x < 1) + fun_l8_n201(x) + else + fun_l8_n668(x) + end +end + +def fun_l7_n564(x) + if (x < 1) + fun_l8_n109(x) + else + fun_l8_n401(x) + end +end + +def fun_l7_n565(x) + if (x < 1) + fun_l8_n678(x) + else + fun_l8_n890(x) + end +end + +def fun_l7_n566(x) + if (x < 1) + fun_l8_n876(x) + else + fun_l8_n129(x) + end +end + +def fun_l7_n567(x) + if (x < 1) + fun_l8_n908(x) + else + fun_l8_n979(x) + end +end + +def fun_l7_n568(x) + if (x < 1) + fun_l8_n899(x) + else + fun_l8_n792(x) + end +end + +def fun_l7_n569(x) + if (x < 1) + fun_l8_n742(x) + else + fun_l8_n441(x) + end +end + +def fun_l7_n570(x) + if (x < 1) + fun_l8_n338(x) + else + fun_l8_n877(x) + end +end + +def fun_l7_n571(x) + if (x < 1) + fun_l8_n684(x) + else + fun_l8_n167(x) + end +end + +def fun_l7_n572(x) + if (x < 1) + fun_l8_n366(x) + else + fun_l8_n239(x) + end +end + +def fun_l7_n573(x) + if (x < 1) + fun_l8_n925(x) + else + fun_l8_n648(x) + end +end + +def fun_l7_n574(x) + if (x < 1) + fun_l8_n825(x) + else + fun_l8_n811(x) + end +end + +def fun_l7_n575(x) + if (x < 1) + fun_l8_n348(x) + else + fun_l8_n994(x) + end +end + +def fun_l7_n576(x) + if (x < 1) + fun_l8_n721(x) + else + fun_l8_n584(x) + end +end + +def fun_l7_n577(x) + if (x < 1) + fun_l8_n827(x) + else + fun_l8_n968(x) + end +end + +def fun_l7_n578(x) + if (x < 1) + fun_l8_n649(x) + else + fun_l8_n684(x) + end +end + +def fun_l7_n579(x) + if (x < 1) + fun_l8_n43(x) + else + fun_l8_n183(x) + end +end + +def fun_l7_n580(x) + if (x < 1) + fun_l8_n516(x) + else + fun_l8_n893(x) + end +end + +def fun_l7_n581(x) + if (x < 1) + fun_l8_n334(x) + else + fun_l8_n677(x) + end +end + +def fun_l7_n582(x) + if (x < 1) + fun_l8_n731(x) + else + fun_l8_n922(x) + end +end + +def fun_l7_n583(x) + if (x < 1) + fun_l8_n653(x) + else + fun_l8_n403(x) + end +end + +def fun_l7_n584(x) + if (x < 1) + fun_l8_n534(x) + else + fun_l8_n155(x) + end +end + +def fun_l7_n585(x) + if (x < 1) + fun_l8_n1(x) + else + fun_l8_n903(x) + end +end + +def fun_l7_n586(x) + if (x < 1) + fun_l8_n956(x) + else + fun_l8_n182(x) + end +end + +def fun_l7_n587(x) + if (x < 1) + fun_l8_n590(x) + else + fun_l8_n707(x) + end +end + +def fun_l7_n588(x) + if (x < 1) + fun_l8_n74(x) + else + fun_l8_n612(x) + end +end + +def fun_l7_n589(x) + if (x < 1) + fun_l8_n17(x) + else + fun_l8_n193(x) + end +end + +def fun_l7_n590(x) + if (x < 1) + fun_l8_n650(x) + else + fun_l8_n863(x) + end +end + +def fun_l7_n591(x) + if (x < 1) + fun_l8_n974(x) + else + fun_l8_n932(x) + end +end + +def fun_l7_n592(x) + if (x < 1) + fun_l8_n17(x) + else + fun_l8_n537(x) + end +end + +def fun_l7_n593(x) + if (x < 1) + fun_l8_n118(x) + else + fun_l8_n588(x) + end +end + +def fun_l7_n594(x) + if (x < 1) + fun_l8_n241(x) + else + fun_l8_n929(x) + end +end + +def fun_l7_n595(x) + if (x < 1) + fun_l8_n667(x) + else + fun_l8_n251(x) + end +end + +def fun_l7_n596(x) + if (x < 1) + fun_l8_n473(x) + else + fun_l8_n189(x) + end +end + +def fun_l7_n597(x) + if (x < 1) + fun_l8_n687(x) + else + fun_l8_n666(x) + end +end + +def fun_l7_n598(x) + if (x < 1) + fun_l8_n700(x) + else + fun_l8_n294(x) + end +end + +def fun_l7_n599(x) + if (x < 1) + fun_l8_n144(x) + else + fun_l8_n656(x) + end +end + +def fun_l7_n600(x) + if (x < 1) + fun_l8_n375(x) + else + fun_l8_n571(x) + end +end + +def fun_l7_n601(x) + if (x < 1) + fun_l8_n506(x) + else + fun_l8_n212(x) + end +end + +def fun_l7_n602(x) + if (x < 1) + fun_l8_n770(x) + else + fun_l8_n491(x) + end +end + +def fun_l7_n603(x) + if (x < 1) + fun_l8_n325(x) + else + fun_l8_n660(x) + end +end + +def fun_l7_n604(x) + if (x < 1) + fun_l8_n255(x) + else + fun_l8_n842(x) + end +end + +def fun_l7_n605(x) + if (x < 1) + fun_l8_n149(x) + else + fun_l8_n648(x) + end +end + +def fun_l7_n606(x) + if (x < 1) + fun_l8_n845(x) + else + fun_l8_n248(x) + end +end + +def fun_l7_n607(x) + if (x < 1) + fun_l8_n484(x) + else + fun_l8_n333(x) + end +end + +def fun_l7_n608(x) + if (x < 1) + fun_l8_n287(x) + else + fun_l8_n341(x) + end +end + +def fun_l7_n609(x) + if (x < 1) + fun_l8_n873(x) + else + fun_l8_n113(x) + end +end + +def fun_l7_n610(x) + if (x < 1) + fun_l8_n45(x) + else + fun_l8_n994(x) + end +end + +def fun_l7_n611(x) + if (x < 1) + fun_l8_n427(x) + else + fun_l8_n359(x) + end +end + +def fun_l7_n612(x) + if (x < 1) + fun_l8_n433(x) + else + fun_l8_n189(x) + end +end + +def fun_l7_n613(x) + if (x < 1) + fun_l8_n25(x) + else + fun_l8_n564(x) + end +end + +def fun_l7_n614(x) + if (x < 1) + fun_l8_n789(x) + else + fun_l8_n441(x) + end +end + +def fun_l7_n615(x) + if (x < 1) + fun_l8_n353(x) + else + fun_l8_n217(x) + end +end + +def fun_l7_n616(x) + if (x < 1) + fun_l8_n334(x) + else + fun_l8_n559(x) + end +end + +def fun_l7_n617(x) + if (x < 1) + fun_l8_n709(x) + else + fun_l8_n764(x) + end +end + +def fun_l7_n618(x) + if (x < 1) + fun_l8_n710(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n619(x) + if (x < 1) + fun_l8_n246(x) + else + fun_l8_n88(x) + end +end + +def fun_l7_n620(x) + if (x < 1) + fun_l8_n259(x) + else + fun_l8_n813(x) + end +end + +def fun_l7_n621(x) + if (x < 1) + fun_l8_n250(x) + else + fun_l8_n566(x) + end +end + +def fun_l7_n622(x) + if (x < 1) + fun_l8_n223(x) + else + fun_l8_n627(x) + end +end + +def fun_l7_n623(x) + if (x < 1) + fun_l8_n345(x) + else + fun_l8_n604(x) + end +end + +def fun_l7_n624(x) + if (x < 1) + fun_l8_n405(x) + else + fun_l8_n850(x) + end +end + +def fun_l7_n625(x) + if (x < 1) + fun_l8_n278(x) + else + fun_l8_n643(x) + end +end + +def fun_l7_n626(x) + if (x < 1) + fun_l8_n359(x) + else + fun_l8_n167(x) + end +end + +def fun_l7_n627(x) + if (x < 1) + fun_l8_n589(x) + else + fun_l8_n656(x) + end +end + +def fun_l7_n628(x) + if (x < 1) + fun_l8_n612(x) + else + fun_l8_n227(x) + end +end + +def fun_l7_n629(x) + if (x < 1) + fun_l8_n845(x) + else + fun_l8_n469(x) + end +end + +def fun_l7_n630(x) + if (x < 1) + fun_l8_n833(x) + else + fun_l8_n92(x) + end +end + +def fun_l7_n631(x) + if (x < 1) + fun_l8_n411(x) + else + fun_l8_n815(x) + end +end + +def fun_l7_n632(x) + if (x < 1) + fun_l8_n844(x) + else + fun_l8_n349(x) + end +end + +def fun_l7_n633(x) + if (x < 1) + fun_l8_n333(x) + else + fun_l8_n468(x) + end +end + +def fun_l7_n634(x) + if (x < 1) + fun_l8_n12(x) + else + fun_l8_n727(x) + end +end + +def fun_l7_n635(x) + if (x < 1) + fun_l8_n65(x) + else + fun_l8_n729(x) + end +end + +def fun_l7_n636(x) + if (x < 1) + fun_l8_n54(x) + else + fun_l8_n524(x) + end +end + +def fun_l7_n637(x) + if (x < 1) + fun_l8_n547(x) + else + fun_l8_n220(x) + end +end + +def fun_l7_n638(x) + if (x < 1) + fun_l8_n679(x) + else + fun_l8_n693(x) + end +end + +def fun_l7_n639(x) + if (x < 1) + fun_l8_n428(x) + else + fun_l8_n938(x) + end +end + +def fun_l7_n640(x) + if (x < 1) + fun_l8_n779(x) + else + fun_l8_n323(x) + end +end + +def fun_l7_n641(x) + if (x < 1) + fun_l8_n254(x) + else + fun_l8_n443(x) + end +end + +def fun_l7_n642(x) + if (x < 1) + fun_l8_n623(x) + else + fun_l8_n361(x) + end +end + +def fun_l7_n643(x) + if (x < 1) + fun_l8_n524(x) + else + fun_l8_n19(x) + end +end + +def fun_l7_n644(x) + if (x < 1) + fun_l8_n77(x) + else + fun_l8_n696(x) + end +end + +def fun_l7_n645(x) + if (x < 1) + fun_l8_n468(x) + else + fun_l8_n819(x) + end +end + +def fun_l7_n646(x) + if (x < 1) + fun_l8_n319(x) + else + fun_l8_n921(x) + end +end + +def fun_l7_n647(x) + if (x < 1) + fun_l8_n681(x) + else + fun_l8_n925(x) + end +end + +def fun_l7_n648(x) + if (x < 1) + fun_l8_n146(x) + else + fun_l8_n451(x) + end +end + +def fun_l7_n649(x) + if (x < 1) + fun_l8_n871(x) + else + fun_l8_n707(x) + end +end + +def fun_l7_n650(x) + if (x < 1) + fun_l8_n782(x) + else + fun_l8_n556(x) + end +end + +def fun_l7_n651(x) + if (x < 1) + fun_l8_n721(x) + else + fun_l8_n80(x) + end +end + +def fun_l7_n652(x) + if (x < 1) + fun_l8_n110(x) + else + fun_l8_n529(x) + end +end + +def fun_l7_n653(x) + if (x < 1) + fun_l8_n107(x) + else + fun_l8_n876(x) + end +end + +def fun_l7_n654(x) + if (x < 1) + fun_l8_n902(x) + else + fun_l8_n45(x) + end +end + +def fun_l7_n655(x) + if (x < 1) + fun_l8_n714(x) + else + fun_l8_n939(x) + end +end + +def fun_l7_n656(x) + if (x < 1) + fun_l8_n761(x) + else + fun_l8_n940(x) + end +end + +def fun_l7_n657(x) + if (x < 1) + fun_l8_n165(x) + else + fun_l8_n779(x) + end +end + +def fun_l7_n658(x) + if (x < 1) + fun_l8_n848(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n659(x) + if (x < 1) + fun_l8_n414(x) + else + fun_l8_n855(x) + end +end + +def fun_l7_n660(x) + if (x < 1) + fun_l8_n963(x) + else + fun_l8_n887(x) + end +end + +def fun_l7_n661(x) + if (x < 1) + fun_l8_n71(x) + else + fun_l8_n249(x) + end +end + +def fun_l7_n662(x) + if (x < 1) + fun_l8_n426(x) + else + fun_l8_n977(x) + end +end + +def fun_l7_n663(x) + if (x < 1) + fun_l8_n924(x) + else + fun_l8_n606(x) + end +end + +def fun_l7_n664(x) + if (x < 1) + fun_l8_n88(x) + else + fun_l8_n718(x) + end +end + +def fun_l7_n665(x) + if (x < 1) + fun_l8_n611(x) + else + fun_l8_n898(x) + end +end + +def fun_l7_n666(x) + if (x < 1) + fun_l8_n656(x) + else + fun_l8_n116(x) + end +end + +def fun_l7_n667(x) + if (x < 1) + fun_l8_n196(x) + else + fun_l8_n688(x) + end +end + +def fun_l7_n668(x) + if (x < 1) + fun_l8_n873(x) + else + fun_l8_n561(x) + end +end + +def fun_l7_n669(x) + if (x < 1) + fun_l8_n947(x) + else + fun_l8_n64(x) + end +end + +def fun_l7_n670(x) + if (x < 1) + fun_l8_n309(x) + else + fun_l8_n708(x) + end +end + +def fun_l7_n671(x) + if (x < 1) + fun_l8_n699(x) + else + fun_l8_n218(x) + end +end + +def fun_l7_n672(x) + if (x < 1) + fun_l8_n930(x) + else + fun_l8_n387(x) + end +end + +def fun_l7_n673(x) + if (x < 1) + fun_l8_n598(x) + else + fun_l8_n245(x) + end +end + +def fun_l7_n674(x) + if (x < 1) + fun_l8_n411(x) + else + fun_l8_n236(x) + end +end + +def fun_l7_n675(x) + if (x < 1) + fun_l8_n193(x) + else + fun_l8_n61(x) + end +end + +def fun_l7_n676(x) + if (x < 1) + fun_l8_n2(x) + else + fun_l8_n253(x) + end +end + +def fun_l7_n677(x) + if (x < 1) + fun_l8_n839(x) + else + fun_l8_n919(x) + end +end + +def fun_l7_n678(x) + if (x < 1) + fun_l8_n643(x) + else + fun_l8_n245(x) + end +end + +def fun_l7_n679(x) + if (x < 1) + fun_l8_n625(x) + else + fun_l8_n690(x) + end +end + +def fun_l7_n680(x) + if (x < 1) + fun_l8_n899(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n681(x) + if (x < 1) + fun_l8_n894(x) + else + fun_l8_n92(x) + end +end + +def fun_l7_n682(x) + if (x < 1) + fun_l8_n139(x) + else + fun_l8_n252(x) + end +end + +def fun_l7_n683(x) + if (x < 1) + fun_l8_n978(x) + else + fun_l8_n84(x) + end +end + +def fun_l7_n684(x) + if (x < 1) + fun_l8_n426(x) + else + fun_l8_n329(x) + end +end + +def fun_l7_n685(x) + if (x < 1) + fun_l8_n241(x) + else + fun_l8_n780(x) + end +end + +def fun_l7_n686(x) + if (x < 1) + fun_l8_n793(x) + else + fun_l8_n534(x) + end +end + +def fun_l7_n687(x) + if (x < 1) + fun_l8_n409(x) + else + fun_l8_n152(x) + end +end + +def fun_l7_n688(x) + if (x < 1) + fun_l8_n838(x) + else + fun_l8_n555(x) + end +end + +def fun_l7_n689(x) + if (x < 1) + fun_l8_n634(x) + else + fun_l8_n27(x) + end +end + +def fun_l7_n690(x) + if (x < 1) + fun_l8_n629(x) + else + fun_l8_n448(x) + end +end + +def fun_l7_n691(x) + if (x < 1) + fun_l8_n487(x) + else + fun_l8_n293(x) + end +end + +def fun_l7_n692(x) + if (x < 1) + fun_l8_n739(x) + else + fun_l8_n472(x) + end +end + +def fun_l7_n693(x) + if (x < 1) + fun_l8_n619(x) + else + fun_l8_n642(x) + end +end + +def fun_l7_n694(x) + if (x < 1) + fun_l8_n123(x) + else + fun_l8_n880(x) + end +end + +def fun_l7_n695(x) + if (x < 1) + fun_l8_n695(x) + else + fun_l8_n364(x) + end +end + +def fun_l7_n696(x) + if (x < 1) + fun_l8_n610(x) + else + fun_l8_n798(x) + end +end + +def fun_l7_n697(x) + if (x < 1) + fun_l8_n396(x) + else + fun_l8_n704(x) + end +end + +def fun_l7_n698(x) + if (x < 1) + fun_l8_n759(x) + else + fun_l8_n880(x) + end +end + +def fun_l7_n699(x) + if (x < 1) + fun_l8_n885(x) + else + fun_l8_n139(x) + end +end + +def fun_l7_n700(x) + if (x < 1) + fun_l8_n244(x) + else + fun_l8_n307(x) + end +end + +def fun_l7_n701(x) + if (x < 1) + fun_l8_n698(x) + else + fun_l8_n949(x) + end +end + +def fun_l7_n702(x) + if (x < 1) + fun_l8_n585(x) + else + fun_l8_n211(x) + end +end + +def fun_l7_n703(x) + if (x < 1) + fun_l8_n834(x) + else + fun_l8_n111(x) + end +end + +def fun_l7_n704(x) + if (x < 1) + fun_l8_n690(x) + else + fun_l8_n981(x) + end +end + +def fun_l7_n705(x) + if (x < 1) + fun_l8_n377(x) + else + fun_l8_n392(x) + end +end + +def fun_l7_n706(x) + if (x < 1) + fun_l8_n988(x) + else + fun_l8_n759(x) + end +end + +def fun_l7_n707(x) + if (x < 1) + fun_l8_n917(x) + else + fun_l8_n326(x) + end +end + +def fun_l7_n708(x) + if (x < 1) + fun_l8_n662(x) + else + fun_l8_n488(x) + end +end + +def fun_l7_n709(x) + if (x < 1) + fun_l8_n530(x) + else + fun_l8_n663(x) + end +end + +def fun_l7_n710(x) + if (x < 1) + fun_l8_n344(x) + else + fun_l8_n282(x) + end +end + +def fun_l7_n711(x) + if (x < 1) + fun_l8_n908(x) + else + fun_l8_n405(x) + end +end + +def fun_l7_n712(x) + if (x < 1) + fun_l8_n332(x) + else + fun_l8_n660(x) + end +end + +def fun_l7_n713(x) + if (x < 1) + fun_l8_n37(x) + else + fun_l8_n689(x) + end +end + +def fun_l7_n714(x) + if (x < 1) + fun_l8_n642(x) + else + fun_l8_n996(x) + end +end + +def fun_l7_n715(x) + if (x < 1) + fun_l8_n322(x) + else + fun_l8_n609(x) + end +end + +def fun_l7_n716(x) + if (x < 1) + fun_l8_n567(x) + else + fun_l8_n492(x) + end +end + +def fun_l7_n717(x) + if (x < 1) + fun_l8_n934(x) + else + fun_l8_n353(x) + end +end + +def fun_l7_n718(x) + if (x < 1) + fun_l8_n572(x) + else + fun_l8_n859(x) + end +end + +def fun_l7_n719(x) + if (x < 1) + fun_l8_n777(x) + else + fun_l8_n810(x) + end +end + +def fun_l7_n720(x) + if (x < 1) + fun_l8_n121(x) + else + fun_l8_n847(x) + end +end + +def fun_l7_n721(x) + if (x < 1) + fun_l8_n177(x) + else + fun_l8_n484(x) + end +end + +def fun_l7_n722(x) + if (x < 1) + fun_l8_n73(x) + else + fun_l8_n795(x) + end +end + +def fun_l7_n723(x) + if (x < 1) + fun_l8_n950(x) + else + fun_l8_n382(x) + end +end + +def fun_l7_n724(x) + if (x < 1) + fun_l8_n349(x) + else + fun_l8_n644(x) + end +end + +def fun_l7_n725(x) + if (x < 1) + fun_l8_n480(x) + else + fun_l8_n262(x) + end +end + +def fun_l7_n726(x) + if (x < 1) + fun_l8_n39(x) + else + fun_l8_n543(x) + end +end + +def fun_l7_n727(x) + if (x < 1) + fun_l8_n934(x) + else + fun_l8_n440(x) + end +end + +def fun_l7_n728(x) + if (x < 1) + fun_l8_n312(x) + else + fun_l8_n341(x) + end +end + +def fun_l7_n729(x) + if (x < 1) + fun_l8_n284(x) + else + fun_l8_n884(x) + end +end + +def fun_l7_n730(x) + if (x < 1) + fun_l8_n841(x) + else + fun_l8_n221(x) + end +end + +def fun_l7_n731(x) + if (x < 1) + fun_l8_n719(x) + else + fun_l8_n907(x) + end +end + +def fun_l7_n732(x) + if (x < 1) + fun_l8_n422(x) + else + fun_l8_n65(x) + end +end + +def fun_l7_n733(x) + if (x < 1) + fun_l8_n324(x) + else + fun_l8_n811(x) + end +end + +def fun_l7_n734(x) + if (x < 1) + fun_l8_n643(x) + else + fun_l8_n622(x) + end +end + +def fun_l7_n735(x) + if (x < 1) + fun_l8_n20(x) + else + fun_l8_n205(x) + end +end + +def fun_l7_n736(x) + if (x < 1) + fun_l8_n487(x) + else + fun_l8_n908(x) + end +end + +def fun_l7_n737(x) + if (x < 1) + fun_l8_n576(x) + else + fun_l8_n789(x) + end +end + +def fun_l7_n738(x) + if (x < 1) + fun_l8_n353(x) + else + fun_l8_n286(x) + end +end + +def fun_l7_n739(x) + if (x < 1) + fun_l8_n614(x) + else + fun_l8_n121(x) + end +end + +def fun_l7_n740(x) + if (x < 1) + fun_l8_n79(x) + else + fun_l8_n637(x) + end +end + +def fun_l7_n741(x) + if (x < 1) + fun_l8_n808(x) + else + fun_l8_n461(x) + end +end + +def fun_l7_n742(x) + if (x < 1) + fun_l8_n590(x) + else + fun_l8_n198(x) + end +end + +def fun_l7_n743(x) + if (x < 1) + fun_l8_n498(x) + else + fun_l8_n379(x) + end +end + +def fun_l7_n744(x) + if (x < 1) + fun_l8_n599(x) + else + fun_l8_n359(x) + end +end + +def fun_l7_n745(x) + if (x < 1) + fun_l8_n898(x) + else + fun_l8_n520(x) + end +end + +def fun_l7_n746(x) + if (x < 1) + fun_l8_n835(x) + else + fun_l8_n131(x) + end +end + +def fun_l7_n747(x) + if (x < 1) + fun_l8_n648(x) + else + fun_l8_n248(x) + end +end + +def fun_l7_n748(x) + if (x < 1) + fun_l8_n451(x) + else + fun_l8_n352(x) + end +end + +def fun_l7_n749(x) + if (x < 1) + fun_l8_n69(x) + else + fun_l8_n974(x) + end +end + +def fun_l7_n750(x) + if (x < 1) + fun_l8_n108(x) + else + fun_l8_n744(x) + end +end + +def fun_l7_n751(x) + if (x < 1) + fun_l8_n171(x) + else + fun_l8_n305(x) + end +end + +def fun_l7_n752(x) + if (x < 1) + fun_l8_n180(x) + else + fun_l8_n293(x) + end +end + +def fun_l7_n753(x) + if (x < 1) + fun_l8_n555(x) + else + fun_l8_n882(x) + end +end + +def fun_l7_n754(x) + if (x < 1) + fun_l8_n756(x) + else + fun_l8_n604(x) + end +end + +def fun_l7_n755(x) + if (x < 1) + fun_l8_n782(x) + else + fun_l8_n708(x) + end +end + +def fun_l7_n756(x) + if (x < 1) + fun_l8_n65(x) + else + fun_l8_n474(x) + end +end + +def fun_l7_n757(x) + if (x < 1) + fun_l8_n43(x) + else + fun_l8_n892(x) + end +end + +def fun_l7_n758(x) + if (x < 1) + fun_l8_n90(x) + else + fun_l8_n968(x) + end +end + +def fun_l7_n759(x) + if (x < 1) + fun_l8_n599(x) + else + fun_l8_n505(x) + end +end + +def fun_l7_n760(x) + if (x < 1) + fun_l8_n344(x) + else + fun_l8_n122(x) + end +end + +def fun_l7_n761(x) + if (x < 1) + fun_l8_n289(x) + else + fun_l8_n867(x) + end +end + +def fun_l7_n762(x) + if (x < 1) + fun_l8_n107(x) + else + fun_l8_n950(x) + end +end + +def fun_l7_n763(x) + if (x < 1) + fun_l8_n405(x) + else + fun_l8_n178(x) + end +end + +def fun_l7_n764(x) + if (x < 1) + fun_l8_n91(x) + else + fun_l8_n760(x) + end +end + +def fun_l7_n765(x) + if (x < 1) + fun_l8_n268(x) + else + fun_l8_n451(x) + end +end + +def fun_l7_n766(x) + if (x < 1) + fun_l8_n693(x) + else + fun_l8_n150(x) + end +end + +def fun_l7_n767(x) + if (x < 1) + fun_l8_n622(x) + else + fun_l8_n114(x) + end +end + +def fun_l7_n768(x) + if (x < 1) + fun_l8_n662(x) + else + fun_l8_n514(x) + end +end + +def fun_l7_n769(x) + if (x < 1) + fun_l8_n440(x) + else + fun_l8_n537(x) + end +end + +def fun_l7_n770(x) + if (x < 1) + fun_l8_n207(x) + else + fun_l8_n513(x) + end +end + +def fun_l7_n771(x) + if (x < 1) + fun_l8_n394(x) + else + fun_l8_n857(x) + end +end + +def fun_l7_n772(x) + if (x < 1) + fun_l8_n635(x) + else + fun_l8_n696(x) + end +end + +def fun_l7_n773(x) + if (x < 1) + fun_l8_n687(x) + else + fun_l8_n926(x) + end +end + +def fun_l7_n774(x) + if (x < 1) + fun_l8_n54(x) + else + fun_l8_n410(x) + end +end + +def fun_l7_n775(x) + if (x < 1) + fun_l8_n825(x) + else + fun_l8_n339(x) + end +end + +def fun_l7_n776(x) + if (x < 1) + fun_l8_n130(x) + else + fun_l8_n48(x) + end +end + +def fun_l7_n777(x) + if (x < 1) + fun_l8_n627(x) + else + fun_l8_n191(x) + end +end + +def fun_l7_n778(x) + if (x < 1) + fun_l8_n843(x) + else + fun_l8_n627(x) + end +end + +def fun_l7_n779(x) + if (x < 1) + fun_l8_n950(x) + else + fun_l8_n247(x) + end +end + +def fun_l7_n780(x) + if (x < 1) + fun_l8_n865(x) + else + fun_l8_n540(x) + end +end + +def fun_l7_n781(x) + if (x < 1) + fun_l8_n440(x) + else + fun_l8_n326(x) + end +end + +def fun_l7_n782(x) + if (x < 1) + fun_l8_n463(x) + else + fun_l8_n808(x) + end +end + +def fun_l7_n783(x) + if (x < 1) + fun_l8_n44(x) + else + fun_l8_n888(x) + end +end + +def fun_l7_n784(x) + if (x < 1) + fun_l8_n690(x) + else + fun_l8_n673(x) + end +end + +def fun_l7_n785(x) + if (x < 1) + fun_l8_n641(x) + else + fun_l8_n367(x) + end +end + +def fun_l7_n786(x) + if (x < 1) + fun_l8_n193(x) + else + fun_l8_n764(x) + end +end + +def fun_l7_n787(x) + if (x < 1) + fun_l8_n604(x) + else + fun_l8_n527(x) + end +end + +def fun_l7_n788(x) + if (x < 1) + fun_l8_n626(x) + else + fun_l8_n101(x) + end +end + +def fun_l7_n789(x) + if (x < 1) + fun_l8_n152(x) + else + fun_l8_n9(x) + end +end + +def fun_l7_n790(x) + if (x < 1) + fun_l8_n541(x) + else + fun_l8_n789(x) + end +end + +def fun_l7_n791(x) + if (x < 1) + fun_l8_n706(x) + else + fun_l8_n577(x) + end +end + +def fun_l7_n792(x) + if (x < 1) + fun_l8_n480(x) + else + fun_l8_n284(x) + end +end + +def fun_l7_n793(x) + if (x < 1) + fun_l8_n157(x) + else + fun_l8_n620(x) + end +end + +def fun_l7_n794(x) + if (x < 1) + fun_l8_n666(x) + else + fun_l8_n755(x) + end +end + +def fun_l7_n795(x) + if (x < 1) + fun_l8_n487(x) + else + fun_l8_n20(x) + end +end + +def fun_l7_n796(x) + if (x < 1) + fun_l8_n750(x) + else + fun_l8_n974(x) + end +end + +def fun_l7_n797(x) + if (x < 1) + fun_l8_n812(x) + else + fun_l8_n915(x) + end +end + +def fun_l7_n798(x) + if (x < 1) + fun_l8_n297(x) + else + fun_l8_n8(x) + end +end + +def fun_l7_n799(x) + if (x < 1) + fun_l8_n385(x) + else + fun_l8_n920(x) + end +end + +def fun_l7_n800(x) + if (x < 1) + fun_l8_n322(x) + else + fun_l8_n603(x) + end +end + +def fun_l7_n801(x) + if (x < 1) + fun_l8_n825(x) + else + fun_l8_n702(x) + end +end + +def fun_l7_n802(x) + if (x < 1) + fun_l8_n902(x) + else + fun_l8_n978(x) + end +end + +def fun_l7_n803(x) + if (x < 1) + fun_l8_n921(x) + else + fun_l8_n61(x) + end +end + +def fun_l7_n804(x) + if (x < 1) + fun_l8_n171(x) + else + fun_l8_n630(x) + end +end + +def fun_l7_n805(x) + if (x < 1) + fun_l8_n469(x) + else + fun_l8_n265(x) + end +end + +def fun_l7_n806(x) + if (x < 1) + fun_l8_n367(x) + else + fun_l8_n820(x) + end +end + +def fun_l7_n807(x) + if (x < 1) + fun_l8_n242(x) + else + fun_l8_n707(x) + end +end + +def fun_l7_n808(x) + if (x < 1) + fun_l8_n512(x) + else + fun_l8_n139(x) + end +end + +def fun_l7_n809(x) + if (x < 1) + fun_l8_n17(x) + else + fun_l8_n615(x) + end +end + +def fun_l7_n810(x) + if (x < 1) + fun_l8_n600(x) + else + fun_l8_n6(x) + end +end + +def fun_l7_n811(x) + if (x < 1) + fun_l8_n342(x) + else + fun_l8_n194(x) + end +end + +def fun_l7_n812(x) + if (x < 1) + fun_l8_n191(x) + else + fun_l8_n864(x) + end +end + +def fun_l7_n813(x) + if (x < 1) + fun_l8_n577(x) + else + fun_l8_n113(x) + end +end + +def fun_l7_n814(x) + if (x < 1) + fun_l8_n729(x) + else + fun_l8_n989(x) + end +end + +def fun_l7_n815(x) + if (x < 1) + fun_l8_n707(x) + else + fun_l8_n846(x) + end +end + +def fun_l7_n816(x) + if (x < 1) + fun_l8_n874(x) + else + fun_l8_n790(x) + end +end + +def fun_l7_n817(x) + if (x < 1) + fun_l8_n968(x) + else + fun_l8_n215(x) + end +end + +def fun_l7_n818(x) + if (x < 1) + fun_l8_n444(x) + else + fun_l8_n182(x) + end +end + +def fun_l7_n819(x) + if (x < 1) + fun_l8_n103(x) + else + fun_l8_n134(x) + end +end + +def fun_l7_n820(x) + if (x < 1) + fun_l8_n718(x) + else + fun_l8_n950(x) + end +end + +def fun_l7_n821(x) + if (x < 1) + fun_l8_n439(x) + else + fun_l8_n68(x) + end +end + +def fun_l7_n822(x) + if (x < 1) + fun_l8_n961(x) + else + fun_l8_n593(x) + end +end + +def fun_l7_n823(x) + if (x < 1) + fun_l8_n212(x) + else + fun_l8_n346(x) + end +end + +def fun_l7_n824(x) + if (x < 1) + fun_l8_n926(x) + else + fun_l8_n225(x) + end +end + +def fun_l7_n825(x) + if (x < 1) + fun_l8_n880(x) + else + fun_l8_n527(x) + end +end + +def fun_l7_n826(x) + if (x < 1) + fun_l8_n13(x) + else + fun_l8_n436(x) + end +end + +def fun_l7_n827(x) + if (x < 1) + fun_l8_n19(x) + else + fun_l8_n201(x) + end +end + +def fun_l7_n828(x) + if (x < 1) + fun_l8_n568(x) + else + fun_l8_n450(x) + end +end + +def fun_l7_n829(x) + if (x < 1) + fun_l8_n543(x) + else + fun_l8_n606(x) + end +end + +def fun_l7_n830(x) + if (x < 1) + fun_l8_n503(x) + else + fun_l8_n104(x) + end +end + +def fun_l7_n831(x) + if (x < 1) + fun_l8_n185(x) + else + fun_l8_n1(x) + end +end + +def fun_l7_n832(x) + if (x < 1) + fun_l8_n598(x) + else + fun_l8_n637(x) + end +end + +def fun_l7_n833(x) + if (x < 1) + fun_l8_n936(x) + else + fun_l8_n554(x) + end +end + +def fun_l7_n834(x) + if (x < 1) + fun_l8_n864(x) + else + fun_l8_n766(x) + end +end + +def fun_l7_n835(x) + if (x < 1) + fun_l8_n11(x) + else + fun_l8_n472(x) + end +end + +def fun_l7_n836(x) + if (x < 1) + fun_l8_n596(x) + else + fun_l8_n429(x) + end +end + +def fun_l7_n837(x) + if (x < 1) + fun_l8_n643(x) + else + fun_l8_n61(x) + end +end + +def fun_l7_n838(x) + if (x < 1) + fun_l8_n905(x) + else + fun_l8_n605(x) + end +end + +def fun_l7_n839(x) + if (x < 1) + fun_l8_n371(x) + else + fun_l8_n44(x) + end +end + +def fun_l7_n840(x) + if (x < 1) + fun_l8_n195(x) + else + fun_l8_n368(x) + end +end + +def fun_l7_n841(x) + if (x < 1) + fun_l8_n432(x) + else + fun_l8_n368(x) + end +end + +def fun_l7_n842(x) + if (x < 1) + fun_l8_n145(x) + else + fun_l8_n180(x) + end +end + +def fun_l7_n843(x) + if (x < 1) + fun_l8_n124(x) + else + fun_l8_n358(x) + end +end + +def fun_l7_n844(x) + if (x < 1) + fun_l8_n87(x) + else + fun_l8_n364(x) + end +end + +def fun_l7_n845(x) + if (x < 1) + fun_l8_n133(x) + else + fun_l8_n849(x) + end +end + +def fun_l7_n846(x) + if (x < 1) + fun_l8_n686(x) + else + fun_l8_n556(x) + end +end + +def fun_l7_n847(x) + if (x < 1) + fun_l8_n732(x) + else + fun_l8_n536(x) + end +end + +def fun_l7_n848(x) + if (x < 1) + fun_l8_n950(x) + else + fun_l8_n173(x) + end +end + +def fun_l7_n849(x) + if (x < 1) + fun_l8_n694(x) + else + fun_l8_n747(x) + end +end + +def fun_l7_n850(x) + if (x < 1) + fun_l8_n421(x) + else + fun_l8_n940(x) + end +end + +def fun_l7_n851(x) + if (x < 1) + fun_l8_n359(x) + else + fun_l8_n239(x) + end +end + +def fun_l7_n852(x) + if (x < 1) + fun_l8_n731(x) + else + fun_l8_n530(x) + end +end + +def fun_l7_n853(x) + if (x < 1) + fun_l8_n887(x) + else + fun_l8_n548(x) + end +end + +def fun_l7_n854(x) + if (x < 1) + fun_l8_n47(x) + else + fun_l8_n675(x) + end +end + +def fun_l7_n855(x) + if (x < 1) + fun_l8_n534(x) + else + fun_l8_n34(x) + end +end + +def fun_l7_n856(x) + if (x < 1) + fun_l8_n935(x) + else + fun_l8_n402(x) + end +end + +def fun_l7_n857(x) + if (x < 1) + fun_l8_n873(x) + else + fun_l8_n864(x) + end +end + +def fun_l7_n858(x) + if (x < 1) + fun_l8_n325(x) + else + fun_l8_n495(x) + end +end + +def fun_l7_n859(x) + if (x < 1) + fun_l8_n758(x) + else + fun_l8_n63(x) + end +end + +def fun_l7_n860(x) + if (x < 1) + fun_l8_n811(x) + else + fun_l8_n150(x) + end +end + +def fun_l7_n861(x) + if (x < 1) + fun_l8_n666(x) + else + fun_l8_n282(x) + end +end + +def fun_l7_n862(x) + if (x < 1) + fun_l8_n123(x) + else + fun_l8_n893(x) + end +end + +def fun_l7_n863(x) + if (x < 1) + fun_l8_n681(x) + else + fun_l8_n640(x) + end +end + +def fun_l7_n864(x) + if (x < 1) + fun_l8_n861(x) + else + fun_l8_n922(x) + end +end + +def fun_l7_n865(x) + if (x < 1) + fun_l8_n8(x) + else + fun_l8_n14(x) + end +end + +def fun_l7_n866(x) + if (x < 1) + fun_l8_n713(x) + else + fun_l8_n802(x) + end +end + +def fun_l7_n867(x) + if (x < 1) + fun_l8_n654(x) + else + fun_l8_n540(x) + end +end + +def fun_l7_n868(x) + if (x < 1) + fun_l8_n308(x) + else + fun_l8_n504(x) + end +end + +def fun_l7_n869(x) + if (x < 1) + fun_l8_n67(x) + else + fun_l8_n592(x) + end +end + +def fun_l7_n870(x) + if (x < 1) + fun_l8_n295(x) + else + fun_l8_n585(x) + end +end + +def fun_l7_n871(x) + if (x < 1) + fun_l8_n121(x) + else + fun_l8_n797(x) + end +end + +def fun_l7_n872(x) + if (x < 1) + fun_l8_n234(x) + else + fun_l8_n834(x) + end +end + +def fun_l7_n873(x) + if (x < 1) + fun_l8_n287(x) + else + fun_l8_n731(x) + end +end + +def fun_l7_n874(x) + if (x < 1) + fun_l8_n460(x) + else + fun_l8_n261(x) + end +end + +def fun_l7_n875(x) + if (x < 1) + fun_l8_n211(x) + else + fun_l8_n199(x) + end +end + +def fun_l7_n876(x) + if (x < 1) + fun_l8_n256(x) + else + fun_l8_n547(x) + end +end + +def fun_l7_n877(x) + if (x < 1) + fun_l8_n560(x) + else + fun_l8_n202(x) + end +end + +def fun_l7_n878(x) + if (x < 1) + fun_l8_n5(x) + else + fun_l8_n955(x) + end +end + +def fun_l7_n879(x) + if (x < 1) + fun_l8_n908(x) + else + fun_l8_n677(x) + end +end + +def fun_l7_n880(x) + if (x < 1) + fun_l8_n366(x) + else + fun_l8_n226(x) + end +end + +def fun_l7_n881(x) + if (x < 1) + fun_l8_n970(x) + else + fun_l8_n939(x) + end +end + +def fun_l7_n882(x) + if (x < 1) + fun_l8_n562(x) + else + fun_l8_n420(x) + end +end + +def fun_l7_n883(x) + if (x < 1) + fun_l8_n377(x) + else + fun_l8_n35(x) + end +end + +def fun_l7_n884(x) + if (x < 1) + fun_l8_n459(x) + else + fun_l8_n155(x) + end +end + +def fun_l7_n885(x) + if (x < 1) + fun_l8_n257(x) + else + fun_l8_n704(x) + end +end + +def fun_l7_n886(x) + if (x < 1) + fun_l8_n393(x) + else + fun_l8_n741(x) + end +end + +def fun_l7_n887(x) + if (x < 1) + fun_l8_n333(x) + else + fun_l8_n225(x) + end +end + +def fun_l7_n888(x) + if (x < 1) + fun_l8_n614(x) + else + fun_l8_n106(x) + end +end + +def fun_l7_n889(x) + if (x < 1) + fun_l8_n229(x) + else + fun_l8_n519(x) + end +end + +def fun_l7_n890(x) + if (x < 1) + fun_l8_n651(x) + else + fun_l8_n68(x) + end +end + +def fun_l7_n891(x) + if (x < 1) + fun_l8_n987(x) + else + fun_l8_n905(x) + end +end + +def fun_l7_n892(x) + if (x < 1) + fun_l8_n698(x) + else + fun_l8_n942(x) + end +end + +def fun_l7_n893(x) + if (x < 1) + fun_l8_n559(x) + else + fun_l8_n613(x) + end +end + +def fun_l7_n894(x) + if (x < 1) + fun_l8_n402(x) + else + fun_l8_n966(x) + end +end + +def fun_l7_n895(x) + if (x < 1) + fun_l8_n475(x) + else + fun_l8_n158(x) + end +end + +def fun_l7_n896(x) + if (x < 1) + fun_l8_n420(x) + else + fun_l8_n113(x) + end +end + +def fun_l7_n897(x) + if (x < 1) + fun_l8_n366(x) + else + fun_l8_n272(x) + end +end + +def fun_l7_n898(x) + if (x < 1) + fun_l8_n252(x) + else + fun_l8_n821(x) + end +end + +def fun_l7_n899(x) + if (x < 1) + fun_l8_n736(x) + else + fun_l8_n174(x) + end +end + +def fun_l7_n900(x) + if (x < 1) + fun_l8_n151(x) + else + fun_l8_n611(x) + end +end + +def fun_l7_n901(x) + if (x < 1) + fun_l8_n3(x) + else + fun_l8_n221(x) + end +end + +def fun_l7_n902(x) + if (x < 1) + fun_l8_n319(x) + else + fun_l8_n930(x) + end +end + +def fun_l7_n903(x) + if (x < 1) + fun_l8_n619(x) + else + fun_l8_n491(x) + end +end + +def fun_l7_n904(x) + if (x < 1) + fun_l8_n144(x) + else + fun_l8_n304(x) + end +end + +def fun_l7_n905(x) + if (x < 1) + fun_l8_n721(x) + else + fun_l8_n996(x) + end +end + +def fun_l7_n906(x) + if (x < 1) + fun_l8_n700(x) + else + fun_l8_n688(x) + end +end + +def fun_l7_n907(x) + if (x < 1) + fun_l8_n202(x) + else + fun_l8_n668(x) + end +end + +def fun_l7_n908(x) + if (x < 1) + fun_l8_n514(x) + else + fun_l8_n306(x) + end +end + +def fun_l7_n909(x) + if (x < 1) + fun_l8_n592(x) + else + fun_l8_n43(x) + end +end + +def fun_l7_n910(x) + if (x < 1) + fun_l8_n743(x) + else + fun_l8_n406(x) + end +end + +def fun_l7_n911(x) + if (x < 1) + fun_l8_n801(x) + else + fun_l8_n91(x) + end +end + +def fun_l7_n912(x) + if (x < 1) + fun_l8_n392(x) + else + fun_l8_n461(x) + end +end + +def fun_l7_n913(x) + if (x < 1) + fun_l8_n175(x) + else + fun_l8_n578(x) + end +end + +def fun_l7_n914(x) + if (x < 1) + fun_l8_n155(x) + else + fun_l8_n795(x) + end +end + +def fun_l7_n915(x) + if (x < 1) + fun_l8_n394(x) + else + fun_l8_n89(x) + end +end + +def fun_l7_n916(x) + if (x < 1) + fun_l8_n59(x) + else + fun_l8_n345(x) + end +end + +def fun_l7_n917(x) + if (x < 1) + fun_l8_n450(x) + else + fun_l8_n136(x) + end +end + +def fun_l7_n918(x) + if (x < 1) + fun_l8_n530(x) + else + fun_l8_n233(x) + end +end + +def fun_l7_n919(x) + if (x < 1) + fun_l8_n632(x) + else + fun_l8_n631(x) + end +end + +def fun_l7_n920(x) + if (x < 1) + fun_l8_n252(x) + else + fun_l8_n95(x) + end +end + +def fun_l7_n921(x) + if (x < 1) + fun_l8_n980(x) + else + fun_l8_n819(x) + end +end + +def fun_l7_n922(x) + if (x < 1) + fun_l8_n866(x) + else + fun_l8_n652(x) + end +end + +def fun_l7_n923(x) + if (x < 1) + fun_l8_n239(x) + else + fun_l8_n83(x) + end +end + +def fun_l7_n924(x) + if (x < 1) + fun_l8_n162(x) + else + fun_l8_n193(x) + end +end + +def fun_l7_n925(x) + if (x < 1) + fun_l8_n78(x) + else + fun_l8_n546(x) + end +end + +def fun_l7_n926(x) + if (x < 1) + fun_l8_n102(x) + else + fun_l8_n847(x) + end +end + +def fun_l7_n927(x) + if (x < 1) + fun_l8_n84(x) + else + fun_l8_n257(x) + end +end + +def fun_l7_n928(x) + if (x < 1) + fun_l8_n195(x) + else + fun_l8_n200(x) + end +end + +def fun_l7_n929(x) + if (x < 1) + fun_l8_n245(x) + else + fun_l8_n926(x) + end +end + +def fun_l7_n930(x) + if (x < 1) + fun_l8_n651(x) + else + fun_l8_n308(x) + end +end + +def fun_l7_n931(x) + if (x < 1) + fun_l8_n312(x) + else + fun_l8_n901(x) + end +end + +def fun_l7_n932(x) + if (x < 1) + fun_l8_n221(x) + else + fun_l8_n775(x) + end +end + +def fun_l7_n933(x) + if (x < 1) + fun_l8_n397(x) + else + fun_l8_n973(x) + end +end + +def fun_l7_n934(x) + if (x < 1) + fun_l8_n788(x) + else + fun_l8_n952(x) + end +end + +def fun_l7_n935(x) + if (x < 1) + fun_l8_n965(x) + else + fun_l8_n861(x) + end +end + +def fun_l7_n936(x) + if (x < 1) + fun_l8_n969(x) + else + fun_l8_n773(x) + end +end + +def fun_l7_n937(x) + if (x < 1) + fun_l8_n742(x) + else + fun_l8_n237(x) + end +end + +def fun_l7_n938(x) + if (x < 1) + fun_l8_n369(x) + else + fun_l8_n444(x) + end +end + +def fun_l7_n939(x) + if (x < 1) + fun_l8_n863(x) + else + fun_l8_n515(x) + end +end + +def fun_l7_n940(x) + if (x < 1) + fun_l8_n573(x) + else + fun_l8_n356(x) + end +end + +def fun_l7_n941(x) + if (x < 1) + fun_l8_n188(x) + else + fun_l8_n171(x) + end +end + +def fun_l7_n942(x) + if (x < 1) + fun_l8_n483(x) + else + fun_l8_n556(x) + end +end + +def fun_l7_n943(x) + if (x < 1) + fun_l8_n935(x) + else + fun_l8_n723(x) + end +end + +def fun_l7_n944(x) + if (x < 1) + fun_l8_n451(x) + else + fun_l8_n227(x) + end +end + +def fun_l7_n945(x) + if (x < 1) + fun_l8_n651(x) + else + fun_l8_n891(x) + end +end + +def fun_l7_n946(x) + if (x < 1) + fun_l8_n225(x) + else + fun_l8_n178(x) + end +end + +def fun_l7_n947(x) + if (x < 1) + fun_l8_n704(x) + else + fun_l8_n456(x) + end +end + +def fun_l7_n948(x) + if (x < 1) + fun_l8_n995(x) + else + fun_l8_n816(x) + end +end + +def fun_l7_n949(x) + if (x < 1) + fun_l8_n287(x) + else + fun_l8_n140(x) + end +end + +def fun_l7_n950(x) + if (x < 1) + fun_l8_n302(x) + else + fun_l8_n582(x) + end +end + +def fun_l7_n951(x) + if (x < 1) + fun_l8_n58(x) + else + fun_l8_n759(x) + end +end + +def fun_l7_n952(x) + if (x < 1) + fun_l8_n54(x) + else + fun_l8_n812(x) + end +end + +def fun_l7_n953(x) + if (x < 1) + fun_l8_n263(x) + else + fun_l8_n801(x) + end +end + +def fun_l7_n954(x) + if (x < 1) + fun_l8_n507(x) + else + fun_l8_n781(x) + end +end + +def fun_l7_n955(x) + if (x < 1) + fun_l8_n328(x) + else + fun_l8_n886(x) + end +end + +def fun_l7_n956(x) + if (x < 1) + fun_l8_n653(x) + else + fun_l8_n847(x) + end +end + +def fun_l7_n957(x) + if (x < 1) + fun_l8_n594(x) + else + fun_l8_n9(x) + end +end + +def fun_l7_n958(x) + if (x < 1) + fun_l8_n818(x) + else + fun_l8_n912(x) + end +end + +def fun_l7_n959(x) + if (x < 1) + fun_l8_n941(x) + else + fun_l8_n394(x) + end +end + +def fun_l7_n960(x) + if (x < 1) + fun_l8_n151(x) + else + fun_l8_n426(x) + end +end + +def fun_l7_n961(x) + if (x < 1) + fun_l8_n276(x) + else + fun_l8_n458(x) + end +end + +def fun_l7_n962(x) + if (x < 1) + fun_l8_n310(x) + else + fun_l8_n472(x) + end +end + +def fun_l7_n963(x) + if (x < 1) + fun_l8_n103(x) + else + fun_l8_n995(x) + end +end + +def fun_l7_n964(x) + if (x < 1) + fun_l8_n808(x) + else + fun_l8_n41(x) + end +end + +def fun_l7_n965(x) + if (x < 1) + fun_l8_n840(x) + else + fun_l8_n143(x) + end +end + +def fun_l7_n966(x) + if (x < 1) + fun_l8_n855(x) + else + fun_l8_n38(x) + end +end + +def fun_l7_n967(x) + if (x < 1) + fun_l8_n316(x) + else + fun_l8_n86(x) + end +end + +def fun_l7_n968(x) + if (x < 1) + fun_l8_n856(x) + else + fun_l8_n182(x) + end +end + +def fun_l7_n969(x) + if (x < 1) + fun_l8_n436(x) + else + fun_l8_n460(x) + end +end + +def fun_l7_n970(x) + if (x < 1) + fun_l8_n187(x) + else + fun_l8_n90(x) + end +end + +def fun_l7_n971(x) + if (x < 1) + fun_l8_n689(x) + else + fun_l8_n921(x) + end +end + +def fun_l7_n972(x) + if (x < 1) + fun_l8_n207(x) + else + fun_l8_n79(x) + end +end + +def fun_l7_n973(x) + if (x < 1) + fun_l8_n137(x) + else + fun_l8_n17(x) + end +end + +def fun_l7_n974(x) + if (x < 1) + fun_l8_n813(x) + else + fun_l8_n944(x) + end +end + +def fun_l7_n975(x) + if (x < 1) + fun_l8_n589(x) + else + fun_l8_n416(x) + end +end + +def fun_l7_n976(x) + if (x < 1) + fun_l8_n763(x) + else + fun_l8_n289(x) + end +end + +def fun_l7_n977(x) + if (x < 1) + fun_l8_n118(x) + else + fun_l8_n998(x) + end +end + +def fun_l7_n978(x) + if (x < 1) + fun_l8_n382(x) + else + fun_l8_n216(x) + end +end + +def fun_l7_n979(x) + if (x < 1) + fun_l8_n304(x) + else + fun_l8_n586(x) + end +end + +def fun_l7_n980(x) + if (x < 1) + fun_l8_n693(x) + else + fun_l8_n118(x) + end +end + +def fun_l7_n981(x) + if (x < 1) + fun_l8_n669(x) + else + fun_l8_n796(x) + end +end + +def fun_l7_n982(x) + if (x < 1) + fun_l8_n187(x) + else + fun_l8_n143(x) + end +end + +def fun_l7_n983(x) + if (x < 1) + fun_l8_n848(x) + else + fun_l8_n172(x) + end +end + +def fun_l7_n984(x) + if (x < 1) + fun_l8_n782(x) + else + fun_l8_n670(x) + end +end + +def fun_l7_n985(x) + if (x < 1) + fun_l8_n275(x) + else + fun_l8_n520(x) + end +end + +def fun_l7_n986(x) + if (x < 1) + fun_l8_n841(x) + else + fun_l8_n446(x) + end +end + +def fun_l7_n987(x) + if (x < 1) + fun_l8_n712(x) + else + fun_l8_n976(x) + end +end + +def fun_l7_n988(x) + if (x < 1) + fun_l8_n115(x) + else + fun_l8_n222(x) + end +end + +def fun_l7_n989(x) + if (x < 1) + fun_l8_n23(x) + else + fun_l8_n665(x) + end +end + +def fun_l7_n990(x) + if (x < 1) + fun_l8_n416(x) + else + fun_l8_n455(x) + end +end + +def fun_l7_n991(x) + if (x < 1) + fun_l8_n556(x) + else + fun_l8_n971(x) + end +end + +def fun_l7_n992(x) + if (x < 1) + fun_l8_n726(x) + else + fun_l8_n312(x) + end +end + +def fun_l7_n993(x) + if (x < 1) + fun_l8_n354(x) + else + fun_l8_n860(x) + end +end + +def fun_l7_n994(x) + if (x < 1) + fun_l8_n62(x) + else + fun_l8_n290(x) + end +end + +def fun_l7_n995(x) + if (x < 1) + fun_l8_n695(x) + else + fun_l8_n881(x) + end +end + +def fun_l7_n996(x) + if (x < 1) + fun_l8_n938(x) + else + fun_l8_n566(x) + end +end + +def fun_l7_n997(x) + if (x < 1) + fun_l8_n379(x) + else + fun_l8_n731(x) + end +end + +def fun_l7_n998(x) + if (x < 1) + fun_l8_n320(x) + else + fun_l8_n339(x) + end +end + +def fun_l7_n999(x) + if (x < 1) + fun_l8_n219(x) + else + fun_l8_n320(x) + end +end + +def fun_l8_n0(x) + if (x < 1) + fun_l9_n590(x) + else + fun_l9_n825(x) + end +end + +def fun_l8_n1(x) + if (x < 1) + fun_l9_n301(x) + else + fun_l9_n457(x) + end +end + +def fun_l8_n2(x) + if (x < 1) + fun_l9_n637(x) + else + fun_l9_n909(x) + end +end + +def fun_l8_n3(x) + if (x < 1) + fun_l9_n485(x) + else + fun_l9_n603(x) + end +end + +def fun_l8_n4(x) + if (x < 1) + fun_l9_n465(x) + else + fun_l9_n39(x) + end +end + +def fun_l8_n5(x) + if (x < 1) + fun_l9_n861(x) + else + fun_l9_n153(x) + end +end + +def fun_l8_n6(x) + if (x < 1) + fun_l9_n130(x) + else + fun_l9_n401(x) + end +end + +def fun_l8_n7(x) + if (x < 1) + fun_l9_n726(x) + else + fun_l9_n248(x) + end +end + +def fun_l8_n8(x) + if (x < 1) + fun_l9_n607(x) + else + fun_l9_n681(x) + end +end + +def fun_l8_n9(x) + if (x < 1) + fun_l9_n862(x) + else + fun_l9_n8(x) + end +end + +def fun_l8_n10(x) + if (x < 1) + fun_l9_n607(x) + else + fun_l9_n373(x) + end +end + +def fun_l8_n11(x) + if (x < 1) + fun_l9_n692(x) + else + fun_l9_n31(x) + end +end + +def fun_l8_n12(x) + if (x < 1) + fun_l9_n412(x) + else + fun_l9_n576(x) + end +end + +def fun_l8_n13(x) + if (x < 1) + fun_l9_n582(x) + else + fun_l9_n281(x) + end +end + +def fun_l8_n14(x) + if (x < 1) + fun_l9_n986(x) + else + fun_l9_n99(x) + end +end + +def fun_l8_n15(x) + if (x < 1) + fun_l9_n807(x) + else + fun_l9_n807(x) + end +end + +def fun_l8_n16(x) + if (x < 1) + fun_l9_n635(x) + else + fun_l9_n51(x) + end +end + +def fun_l8_n17(x) + if (x < 1) + fun_l9_n193(x) + else + fun_l9_n673(x) + end +end + +def fun_l8_n18(x) + if (x < 1) + fun_l9_n897(x) + else + fun_l9_n881(x) + end +end + +def fun_l8_n19(x) + if (x < 1) + fun_l9_n288(x) + else + fun_l9_n337(x) + end +end + +def fun_l8_n20(x) + if (x < 1) + fun_l9_n754(x) + else + fun_l9_n581(x) + end +end + +def fun_l8_n21(x) + if (x < 1) + fun_l9_n265(x) + else + fun_l9_n205(x) + end +end + +def fun_l8_n22(x) + if (x < 1) + fun_l9_n784(x) + else + fun_l9_n428(x) + end +end + +def fun_l8_n23(x) + if (x < 1) + fun_l9_n821(x) + else + fun_l9_n930(x) + end +end + +def fun_l8_n24(x) + if (x < 1) + fun_l9_n237(x) + else + fun_l9_n681(x) + end +end + +def fun_l8_n25(x) + if (x < 1) + fun_l9_n32(x) + else + fun_l9_n405(x) + end +end + +def fun_l8_n26(x) + if (x < 1) + fun_l9_n370(x) + else + fun_l9_n802(x) + end +end + +def fun_l8_n27(x) + if (x < 1) + fun_l9_n4(x) + else + fun_l9_n288(x) + end +end + +def fun_l8_n28(x) + if (x < 1) + fun_l9_n9(x) + else + fun_l9_n180(x) + end +end + +def fun_l8_n29(x) + if (x < 1) + fun_l9_n585(x) + else + fun_l9_n396(x) + end +end + +def fun_l8_n30(x) + if (x < 1) + fun_l9_n954(x) + else + fun_l9_n603(x) + end +end + +def fun_l8_n31(x) + if (x < 1) + fun_l9_n808(x) + else + fun_l9_n770(x) + end +end + +def fun_l8_n32(x) + if (x < 1) + fun_l9_n442(x) + else + fun_l9_n243(x) + end +end + +def fun_l8_n33(x) + if (x < 1) + fun_l9_n139(x) + else + fun_l9_n93(x) + end +end + +def fun_l8_n34(x) + if (x < 1) + fun_l9_n270(x) + else + fun_l9_n333(x) + end +end + +def fun_l8_n35(x) + if (x < 1) + fun_l9_n542(x) + else + fun_l9_n38(x) + end +end + +def fun_l8_n36(x) + if (x < 1) + fun_l9_n892(x) + else + fun_l9_n517(x) + end +end + +def fun_l8_n37(x) + if (x < 1) + fun_l9_n599(x) + else + fun_l9_n692(x) + end +end + +def fun_l8_n38(x) + if (x < 1) + fun_l9_n0(x) + else + fun_l9_n879(x) + end +end + +def fun_l8_n39(x) + if (x < 1) + fun_l9_n835(x) + else + fun_l9_n134(x) + end +end + +def fun_l8_n40(x) + if (x < 1) + fun_l9_n151(x) + else + fun_l9_n546(x) + end +end + +def fun_l8_n41(x) + if (x < 1) + fun_l9_n214(x) + else + fun_l9_n652(x) + end +end + +def fun_l8_n42(x) + if (x < 1) + fun_l9_n239(x) + else + fun_l9_n123(x) + end +end + +def fun_l8_n43(x) + if (x < 1) + fun_l9_n763(x) + else + fun_l9_n953(x) + end +end + +def fun_l8_n44(x) + if (x < 1) + fun_l9_n449(x) + else + fun_l9_n343(x) + end +end + +def fun_l8_n45(x) + if (x < 1) + fun_l9_n727(x) + else + fun_l9_n47(x) + end +end + +def fun_l8_n46(x) + if (x < 1) + fun_l9_n684(x) + else + fun_l9_n711(x) + end +end + +def fun_l8_n47(x) + if (x < 1) + fun_l9_n895(x) + else + fun_l9_n864(x) + end +end + +def fun_l8_n48(x) + if (x < 1) + fun_l9_n544(x) + else + fun_l9_n358(x) + end +end + +def fun_l8_n49(x) + if (x < 1) + fun_l9_n829(x) + else + fun_l9_n411(x) + end +end + +def fun_l8_n50(x) + if (x < 1) + fun_l9_n673(x) + else + fun_l9_n640(x) + end +end + +def fun_l8_n51(x) + if (x < 1) + fun_l9_n9(x) + else + fun_l9_n690(x) + end +end + +def fun_l8_n52(x) + if (x < 1) + fun_l9_n293(x) + else + fun_l9_n889(x) + end +end + +def fun_l8_n53(x) + if (x < 1) + fun_l9_n141(x) + else + fun_l9_n554(x) + end +end + +def fun_l8_n54(x) + if (x < 1) + fun_l9_n982(x) + else + fun_l9_n955(x) + end +end + +def fun_l8_n55(x) + if (x < 1) + fun_l9_n382(x) + else + fun_l9_n897(x) + end +end + +def fun_l8_n56(x) + if (x < 1) + fun_l9_n332(x) + else + fun_l9_n550(x) + end +end + +def fun_l8_n57(x) + if (x < 1) + fun_l9_n46(x) + else + fun_l9_n569(x) + end +end + +def fun_l8_n58(x) + if (x < 1) + fun_l9_n556(x) + else + fun_l9_n0(x) + end +end + +def fun_l8_n59(x) + if (x < 1) + fun_l9_n931(x) + else + fun_l9_n995(x) + end +end + +def fun_l8_n60(x) + if (x < 1) + fun_l9_n470(x) + else + fun_l9_n679(x) + end +end + +def fun_l8_n61(x) + if (x < 1) + fun_l9_n269(x) + else + fun_l9_n742(x) + end +end + +def fun_l8_n62(x) + if (x < 1) + fun_l9_n542(x) + else + fun_l9_n556(x) + end +end + +def fun_l8_n63(x) + if (x < 1) + fun_l9_n713(x) + else + fun_l9_n249(x) + end +end + +def fun_l8_n64(x) + if (x < 1) + fun_l9_n842(x) + else + fun_l9_n566(x) + end +end + +def fun_l8_n65(x) + if (x < 1) + fun_l9_n708(x) + else + fun_l9_n3(x) + end +end + +def fun_l8_n66(x) + if (x < 1) + fun_l9_n845(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n67(x) + if (x < 1) + fun_l9_n823(x) + else + fun_l9_n326(x) + end +end + +def fun_l8_n68(x) + if (x < 1) + fun_l9_n457(x) + else + fun_l9_n888(x) + end +end + +def fun_l8_n69(x) + if (x < 1) + fun_l9_n454(x) + else + fun_l9_n601(x) + end +end + +def fun_l8_n70(x) + if (x < 1) + fun_l9_n636(x) + else + fun_l9_n482(x) + end +end + +def fun_l8_n71(x) + if (x < 1) + fun_l9_n778(x) + else + fun_l9_n678(x) + end +end + +def fun_l8_n72(x) + if (x < 1) + fun_l9_n715(x) + else + fun_l9_n851(x) + end +end + +def fun_l8_n73(x) + if (x < 1) + fun_l9_n330(x) + else + fun_l9_n84(x) + end +end + +def fun_l8_n74(x) + if (x < 1) + fun_l9_n524(x) + else + fun_l9_n109(x) + end +end + +def fun_l8_n75(x) + if (x < 1) + fun_l9_n610(x) + else + fun_l9_n723(x) + end +end + +def fun_l8_n76(x) + if (x < 1) + fun_l9_n964(x) + else + fun_l9_n893(x) + end +end + +def fun_l8_n77(x) + if (x < 1) + fun_l9_n653(x) + else + fun_l9_n451(x) + end +end + +def fun_l8_n78(x) + if (x < 1) + fun_l9_n582(x) + else + fun_l9_n29(x) + end +end + +def fun_l8_n79(x) + if (x < 1) + fun_l9_n219(x) + else + fun_l9_n25(x) + end +end + +def fun_l8_n80(x) + if (x < 1) + fun_l9_n471(x) + else + fun_l9_n217(x) + end +end + +def fun_l8_n81(x) + if (x < 1) + fun_l9_n339(x) + else + fun_l9_n365(x) + end +end + +def fun_l8_n82(x) + if (x < 1) + fun_l9_n808(x) + else + fun_l9_n501(x) + end +end + +def fun_l8_n83(x) + if (x < 1) + fun_l9_n23(x) + else + fun_l9_n252(x) + end +end + +def fun_l8_n84(x) + if (x < 1) + fun_l9_n628(x) + else + fun_l9_n514(x) + end +end + +def fun_l8_n85(x) + if (x < 1) + fun_l9_n22(x) + else + fun_l9_n465(x) + end +end + +def fun_l8_n86(x) + if (x < 1) + fun_l9_n553(x) + else + fun_l9_n788(x) + end +end + +def fun_l8_n87(x) + if (x < 1) + fun_l9_n852(x) + else + fun_l9_n945(x) + end +end + +def fun_l8_n88(x) + if (x < 1) + fun_l9_n886(x) + else + fun_l9_n438(x) + end +end + +def fun_l8_n89(x) + if (x < 1) + fun_l9_n821(x) + else + fun_l9_n697(x) + end +end + +def fun_l8_n90(x) + if (x < 1) + fun_l9_n388(x) + else + fun_l9_n39(x) + end +end + +def fun_l8_n91(x) + if (x < 1) + fun_l9_n135(x) + else + fun_l9_n736(x) + end +end + +def fun_l8_n92(x) + if (x < 1) + fun_l9_n225(x) + else + fun_l9_n125(x) + end +end + +def fun_l8_n93(x) + if (x < 1) + fun_l9_n201(x) + else + fun_l9_n320(x) + end +end + +def fun_l8_n94(x) + if (x < 1) + fun_l9_n30(x) + else + fun_l9_n938(x) + end +end + +def fun_l8_n95(x) + if (x < 1) + fun_l9_n987(x) + else + fun_l9_n141(x) + end +end + +def fun_l8_n96(x) + if (x < 1) + fun_l9_n968(x) + else + fun_l9_n999(x) + end +end + +def fun_l8_n97(x) + if (x < 1) + fun_l9_n852(x) + else + fun_l9_n927(x) + end +end + +def fun_l8_n98(x) + if (x < 1) + fun_l9_n720(x) + else + fun_l9_n717(x) + end +end + +def fun_l8_n99(x) + if (x < 1) + fun_l9_n907(x) + else + fun_l9_n8(x) + end +end + +def fun_l8_n100(x) + if (x < 1) + fun_l9_n973(x) + else + fun_l9_n379(x) + end +end + +def fun_l8_n101(x) + if (x < 1) + fun_l9_n370(x) + else + fun_l9_n530(x) + end +end + +def fun_l8_n102(x) + if (x < 1) + fun_l9_n411(x) + else + fun_l9_n560(x) + end +end + +def fun_l8_n103(x) + if (x < 1) + fun_l9_n54(x) + else + fun_l9_n813(x) + end +end + +def fun_l8_n104(x) + if (x < 1) + fun_l9_n217(x) + else + fun_l9_n455(x) + end +end + +def fun_l8_n105(x) + if (x < 1) + fun_l9_n667(x) + else + fun_l9_n92(x) + end +end + +def fun_l8_n106(x) + if (x < 1) + fun_l9_n933(x) + else + fun_l9_n727(x) + end +end + +def fun_l8_n107(x) + if (x < 1) + fun_l9_n578(x) + else + fun_l9_n350(x) + end +end + +def fun_l8_n108(x) + if (x < 1) + fun_l9_n75(x) + else + fun_l9_n439(x) + end +end + +def fun_l8_n109(x) + if (x < 1) + fun_l9_n21(x) + else + fun_l9_n112(x) + end +end + +def fun_l8_n110(x) + if (x < 1) + fun_l9_n57(x) + else + fun_l9_n553(x) + end +end + +def fun_l8_n111(x) + if (x < 1) + fun_l9_n347(x) + else + fun_l9_n285(x) + end +end + +def fun_l8_n112(x) + if (x < 1) + fun_l9_n837(x) + else + fun_l9_n793(x) + end +end + +def fun_l8_n113(x) + if (x < 1) + fun_l9_n517(x) + else + fun_l9_n668(x) + end +end + +def fun_l8_n114(x) + if (x < 1) + fun_l9_n486(x) + else + fun_l9_n872(x) + end +end + +def fun_l8_n115(x) + if (x < 1) + fun_l9_n454(x) + else + fun_l9_n507(x) + end +end + +def fun_l8_n116(x) + if (x < 1) + fun_l9_n110(x) + else + fun_l9_n263(x) + end +end + +def fun_l8_n117(x) + if (x < 1) + fun_l9_n878(x) + else + fun_l9_n21(x) + end +end + +def fun_l8_n118(x) + if (x < 1) + fun_l9_n564(x) + else + fun_l9_n409(x) + end +end + +def fun_l8_n119(x) + if (x < 1) + fun_l9_n511(x) + else + fun_l9_n800(x) + end +end + +def fun_l8_n120(x) + if (x < 1) + fun_l9_n501(x) + else + fun_l9_n305(x) + end +end + +def fun_l8_n121(x) + if (x < 1) + fun_l9_n630(x) + else + fun_l9_n319(x) + end +end + +def fun_l8_n122(x) + if (x < 1) + fun_l9_n271(x) + else + fun_l9_n639(x) + end +end + +def fun_l8_n123(x) + if (x < 1) + fun_l9_n812(x) + else + fun_l9_n735(x) + end +end + +def fun_l8_n124(x) + if (x < 1) + fun_l9_n828(x) + else + fun_l9_n203(x) + end +end + +def fun_l8_n125(x) + if (x < 1) + fun_l9_n228(x) + else + fun_l9_n536(x) + end +end + +def fun_l8_n126(x) + if (x < 1) + fun_l9_n426(x) + else + fun_l9_n325(x) + end +end + +def fun_l8_n127(x) + if (x < 1) + fun_l9_n19(x) + else + fun_l9_n324(x) + end +end + +def fun_l8_n128(x) + if (x < 1) + fun_l9_n419(x) + else + fun_l9_n425(x) + end +end + +def fun_l8_n129(x) + if (x < 1) + fun_l9_n384(x) + else + fun_l9_n550(x) + end +end + +def fun_l8_n130(x) + if (x < 1) + fun_l9_n956(x) + else + fun_l9_n270(x) + end +end + +def fun_l8_n131(x) + if (x < 1) + fun_l9_n20(x) + else + fun_l9_n949(x) + end +end + +def fun_l8_n132(x) + if (x < 1) + fun_l9_n317(x) + else + fun_l9_n909(x) + end +end + +def fun_l8_n133(x) + if (x < 1) + fun_l9_n131(x) + else + fun_l9_n108(x) + end +end + +def fun_l8_n134(x) + if (x < 1) + fun_l9_n648(x) + else + fun_l9_n473(x) + end +end + +def fun_l8_n135(x) + if (x < 1) + fun_l9_n837(x) + else + fun_l9_n89(x) + end +end + +def fun_l8_n136(x) + if (x < 1) + fun_l9_n637(x) + else + fun_l9_n394(x) + end +end + +def fun_l8_n137(x) + if (x < 1) + fun_l9_n608(x) + else + fun_l9_n283(x) + end +end + +def fun_l8_n138(x) + if (x < 1) + fun_l9_n728(x) + else + fun_l9_n586(x) + end +end + +def fun_l8_n139(x) + if (x < 1) + fun_l9_n689(x) + else + fun_l9_n700(x) + end +end + +def fun_l8_n140(x) + if (x < 1) + fun_l9_n532(x) + else + fun_l9_n98(x) + end +end + +def fun_l8_n141(x) + if (x < 1) + fun_l9_n696(x) + else + fun_l9_n951(x) + end +end + +def fun_l8_n142(x) + if (x < 1) + fun_l9_n28(x) + else + fun_l9_n714(x) + end +end + +def fun_l8_n143(x) + if (x < 1) + fun_l9_n438(x) + else + fun_l9_n934(x) + end +end + +def fun_l8_n144(x) + if (x < 1) + fun_l9_n738(x) + else + fun_l9_n473(x) + end +end + +def fun_l8_n145(x) + if (x < 1) + fun_l9_n201(x) + else + fun_l9_n634(x) + end +end + +def fun_l8_n146(x) + if (x < 1) + fun_l9_n391(x) + else + fun_l9_n703(x) + end +end + +def fun_l8_n147(x) + if (x < 1) + fun_l9_n740(x) + else + fun_l9_n265(x) + end +end + +def fun_l8_n148(x) + if (x < 1) + fun_l9_n303(x) + else + fun_l9_n162(x) + end +end + +def fun_l8_n149(x) + if (x < 1) + fun_l9_n518(x) + else + fun_l9_n899(x) + end +end + +def fun_l8_n150(x) + if (x < 1) + fun_l9_n847(x) + else + fun_l9_n840(x) + end +end + +def fun_l8_n151(x) + if (x < 1) + fun_l9_n567(x) + else + fun_l9_n29(x) + end +end + +def fun_l8_n152(x) + if (x < 1) + fun_l9_n426(x) + else + fun_l9_n578(x) + end +end + +def fun_l8_n153(x) + if (x < 1) + fun_l9_n617(x) + else + fun_l9_n703(x) + end +end + +def fun_l8_n154(x) + if (x < 1) + fun_l9_n673(x) + else + fun_l9_n663(x) + end +end + +def fun_l8_n155(x) + if (x < 1) + fun_l9_n456(x) + else + fun_l9_n406(x) + end +end + +def fun_l8_n156(x) + if (x < 1) + fun_l9_n297(x) + else + fun_l9_n444(x) + end +end + +def fun_l8_n157(x) + if (x < 1) + fun_l9_n300(x) + else + fun_l9_n179(x) + end +end + +def fun_l8_n158(x) + if (x < 1) + fun_l9_n646(x) + else + fun_l9_n9(x) + end +end + +def fun_l8_n159(x) + if (x < 1) + fun_l9_n133(x) + else + fun_l9_n228(x) + end +end + +def fun_l8_n160(x) + if (x < 1) + fun_l9_n814(x) + else + fun_l9_n775(x) + end +end + +def fun_l8_n161(x) + if (x < 1) + fun_l9_n748(x) + else + fun_l9_n849(x) + end +end + +def fun_l8_n162(x) + if (x < 1) + fun_l9_n209(x) + else + fun_l9_n273(x) + end +end + +def fun_l8_n163(x) + if (x < 1) + fun_l9_n116(x) + else + fun_l9_n669(x) + end +end + +def fun_l8_n164(x) + if (x < 1) + fun_l9_n714(x) + else + fun_l9_n621(x) + end +end + +def fun_l8_n165(x) + if (x < 1) + fun_l9_n619(x) + else + fun_l9_n365(x) + end +end + +def fun_l8_n166(x) + if (x < 1) + fun_l9_n756(x) + else + fun_l9_n745(x) + end +end + +def fun_l8_n167(x) + if (x < 1) + fun_l9_n12(x) + else + fun_l9_n633(x) + end +end + +def fun_l8_n168(x) + if (x < 1) + fun_l9_n619(x) + else + fun_l9_n31(x) + end +end + +def fun_l8_n169(x) + if (x < 1) + fun_l9_n685(x) + else + fun_l9_n107(x) + end +end + +def fun_l8_n170(x) + if (x < 1) + fun_l9_n636(x) + else + fun_l9_n280(x) + end +end + +def fun_l8_n171(x) + if (x < 1) + fun_l9_n254(x) + else + fun_l9_n742(x) + end +end + +def fun_l8_n172(x) + if (x < 1) + fun_l9_n829(x) + else + fun_l9_n632(x) + end +end + +def fun_l8_n173(x) + if (x < 1) + fun_l9_n341(x) + else + fun_l9_n186(x) + end +end + +def fun_l8_n174(x) + if (x < 1) + fun_l9_n903(x) + else + fun_l9_n93(x) + end +end + +def fun_l8_n175(x) + if (x < 1) + fun_l9_n416(x) + else + fun_l9_n318(x) + end +end + +def fun_l8_n176(x) + if (x < 1) + fun_l9_n893(x) + else + fun_l9_n438(x) + end +end + +def fun_l8_n177(x) + if (x < 1) + fun_l9_n551(x) + else + fun_l9_n312(x) + end +end + +def fun_l8_n178(x) + if (x < 1) + fun_l9_n582(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n179(x) + if (x < 1) + fun_l9_n547(x) + else + fun_l9_n804(x) + end +end + +def fun_l8_n180(x) + if (x < 1) + fun_l9_n589(x) + else + fun_l9_n246(x) + end +end + +def fun_l8_n181(x) + if (x < 1) + fun_l9_n67(x) + else + fun_l9_n345(x) + end +end + +def fun_l8_n182(x) + if (x < 1) + fun_l9_n958(x) + else + fun_l9_n923(x) + end +end + +def fun_l8_n183(x) + if (x < 1) + fun_l9_n418(x) + else + fun_l9_n532(x) + end +end + +def fun_l8_n184(x) + if (x < 1) + fun_l9_n372(x) + else + fun_l9_n808(x) + end +end + +def fun_l8_n185(x) + if (x < 1) + fun_l9_n849(x) + else + fun_l9_n755(x) + end +end + +def fun_l8_n186(x) + if (x < 1) + fun_l9_n544(x) + else + fun_l9_n73(x) + end +end + +def fun_l8_n187(x) + if (x < 1) + fun_l9_n729(x) + else + fun_l9_n295(x) + end +end + +def fun_l8_n188(x) + if (x < 1) + fun_l9_n782(x) + else + fun_l9_n117(x) + end +end + +def fun_l8_n189(x) + if (x < 1) + fun_l9_n947(x) + else + fun_l9_n93(x) + end +end + +def fun_l8_n190(x) + if (x < 1) + fun_l9_n989(x) + else + fun_l9_n444(x) + end +end + +def fun_l8_n191(x) + if (x < 1) + fun_l9_n394(x) + else + fun_l9_n741(x) + end +end + +def fun_l8_n192(x) + if (x < 1) + fun_l9_n582(x) + else + fun_l9_n333(x) + end +end + +def fun_l8_n193(x) + if (x < 1) + fun_l9_n73(x) + else + fun_l9_n227(x) + end +end + +def fun_l8_n194(x) + if (x < 1) + fun_l9_n946(x) + else + fun_l9_n354(x) + end +end + +def fun_l8_n195(x) + if (x < 1) + fun_l9_n383(x) + else + fun_l9_n863(x) + end +end + +def fun_l8_n196(x) + if (x < 1) + fun_l9_n441(x) + else + fun_l9_n947(x) + end +end + +def fun_l8_n197(x) + if (x < 1) + fun_l9_n506(x) + else + fun_l9_n45(x) + end +end + +def fun_l8_n198(x) + if (x < 1) + fun_l9_n890(x) + else + fun_l9_n341(x) + end +end + +def fun_l8_n199(x) + if (x < 1) + fun_l9_n75(x) + else + fun_l9_n56(x) + end +end + +def fun_l8_n200(x) + if (x < 1) + fun_l9_n386(x) + else + fun_l9_n280(x) + end +end + +def fun_l8_n201(x) + if (x < 1) + fun_l9_n364(x) + else + fun_l9_n424(x) + end +end + +def fun_l8_n202(x) + if (x < 1) + fun_l9_n923(x) + else + fun_l9_n326(x) + end +end + +def fun_l8_n203(x) + if (x < 1) + fun_l9_n692(x) + else + fun_l9_n502(x) + end +end + +def fun_l8_n204(x) + if (x < 1) + fun_l9_n508(x) + else + fun_l9_n561(x) + end +end + +def fun_l8_n205(x) + if (x < 1) + fun_l9_n496(x) + else + fun_l9_n949(x) + end +end + +def fun_l8_n206(x) + if (x < 1) + fun_l9_n852(x) + else + fun_l9_n447(x) + end +end + +def fun_l8_n207(x) + if (x < 1) + fun_l9_n757(x) + else + fun_l9_n782(x) + end +end + +def fun_l8_n208(x) + if (x < 1) + fun_l9_n505(x) + else + fun_l9_n32(x) + end +end + +def fun_l8_n209(x) + if (x < 1) + fun_l9_n591(x) + else + fun_l9_n967(x) + end +end + +def fun_l8_n210(x) + if (x < 1) + fun_l9_n537(x) + else + fun_l9_n380(x) + end +end + +def fun_l8_n211(x) + if (x < 1) + fun_l9_n19(x) + else + fun_l9_n362(x) + end +end + +def fun_l8_n212(x) + if (x < 1) + fun_l9_n759(x) + else + fun_l9_n835(x) + end +end + +def fun_l8_n213(x) + if (x < 1) + fun_l9_n518(x) + else + fun_l9_n294(x) + end +end + +def fun_l8_n214(x) + if (x < 1) + fun_l9_n921(x) + else + fun_l9_n687(x) + end +end + +def fun_l8_n215(x) + if (x < 1) + fun_l9_n114(x) + else + fun_l9_n130(x) + end +end + +def fun_l8_n216(x) + if (x < 1) + fun_l9_n829(x) + else + fun_l9_n8(x) + end +end + +def fun_l8_n217(x) + if (x < 1) + fun_l9_n875(x) + else + fun_l9_n392(x) + end +end + +def fun_l8_n218(x) + if (x < 1) + fun_l9_n13(x) + else + fun_l9_n907(x) + end +end + +def fun_l8_n219(x) + if (x < 1) + fun_l9_n457(x) + else + fun_l9_n77(x) + end +end + +def fun_l8_n220(x) + if (x < 1) + fun_l9_n404(x) + else + fun_l9_n12(x) + end +end + +def fun_l8_n221(x) + if (x < 1) + fun_l9_n244(x) + else + fun_l9_n231(x) + end +end + +def fun_l8_n222(x) + if (x < 1) + fun_l9_n205(x) + else + fun_l9_n458(x) + end +end + +def fun_l8_n223(x) + if (x < 1) + fun_l9_n570(x) + else + fun_l9_n44(x) + end +end + +def fun_l8_n224(x) + if (x < 1) + fun_l9_n651(x) + else + fun_l9_n836(x) + end +end + +def fun_l8_n225(x) + if (x < 1) + fun_l9_n518(x) + else + fun_l9_n845(x) + end +end + +def fun_l8_n226(x) + if (x < 1) + fun_l9_n92(x) + else + fun_l9_n637(x) + end +end + +def fun_l8_n227(x) + if (x < 1) + fun_l9_n990(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n228(x) + if (x < 1) + fun_l9_n465(x) + else + fun_l9_n764(x) + end +end + +def fun_l8_n229(x) + if (x < 1) + fun_l9_n7(x) + else + fun_l9_n981(x) + end +end + +def fun_l8_n230(x) + if (x < 1) + fun_l9_n250(x) + else + fun_l9_n690(x) + end +end + +def fun_l8_n231(x) + if (x < 1) + fun_l9_n101(x) + else + fun_l9_n342(x) + end +end + +def fun_l8_n232(x) + if (x < 1) + fun_l9_n659(x) + else + fun_l9_n216(x) + end +end + +def fun_l8_n233(x) + if (x < 1) + fun_l9_n129(x) + else + fun_l9_n439(x) + end +end + +def fun_l8_n234(x) + if (x < 1) + fun_l9_n616(x) + else + fun_l9_n700(x) + end +end + +def fun_l8_n235(x) + if (x < 1) + fun_l9_n850(x) + else + fun_l9_n254(x) + end +end + +def fun_l8_n236(x) + if (x < 1) + fun_l9_n186(x) + else + fun_l9_n592(x) + end +end + +def fun_l8_n237(x) + if (x < 1) + fun_l9_n895(x) + else + fun_l9_n752(x) + end +end + +def fun_l8_n238(x) + if (x < 1) + fun_l9_n496(x) + else + fun_l9_n784(x) + end +end + +def fun_l8_n239(x) + if (x < 1) + fun_l9_n579(x) + else + fun_l9_n144(x) + end +end + +def fun_l8_n240(x) + if (x < 1) + fun_l9_n805(x) + else + fun_l9_n851(x) + end +end + +def fun_l8_n241(x) + if (x < 1) + fun_l9_n756(x) + else + fun_l9_n332(x) + end +end + +def fun_l8_n242(x) + if (x < 1) + fun_l9_n898(x) + else + fun_l9_n285(x) + end +end + +def fun_l8_n243(x) + if (x < 1) + fun_l9_n729(x) + else + fun_l9_n149(x) + end +end + +def fun_l8_n244(x) + if (x < 1) + fun_l9_n881(x) + else + fun_l9_n356(x) + end +end + +def fun_l8_n245(x) + if (x < 1) + fun_l9_n351(x) + else + fun_l9_n805(x) + end +end + +def fun_l8_n246(x) + if (x < 1) + fun_l9_n493(x) + else + fun_l9_n200(x) + end +end + +def fun_l8_n247(x) + if (x < 1) + fun_l9_n706(x) + else + fun_l9_n917(x) + end +end + +def fun_l8_n248(x) + if (x < 1) + fun_l9_n370(x) + else + fun_l9_n755(x) + end +end + +def fun_l8_n249(x) + if (x < 1) + fun_l9_n859(x) + else + fun_l9_n496(x) + end +end + +def fun_l8_n250(x) + if (x < 1) + fun_l9_n443(x) + else + fun_l9_n113(x) + end +end + +def fun_l8_n251(x) + if (x < 1) + fun_l9_n631(x) + else + fun_l9_n195(x) + end +end + +def fun_l8_n252(x) + if (x < 1) + fun_l9_n357(x) + else + fun_l9_n694(x) + end +end + +def fun_l8_n253(x) + if (x < 1) + fun_l9_n387(x) + else + fun_l9_n820(x) + end +end + +def fun_l8_n254(x) + if (x < 1) + fun_l9_n909(x) + else + fun_l9_n559(x) + end +end + +def fun_l8_n255(x) + if (x < 1) + fun_l9_n474(x) + else + fun_l9_n864(x) + end +end + +def fun_l8_n256(x) + if (x < 1) + fun_l9_n914(x) + else + fun_l9_n672(x) + end +end + +def fun_l8_n257(x) + if (x < 1) + fun_l9_n915(x) + else + fun_l9_n177(x) + end +end + +def fun_l8_n258(x) + if (x < 1) + fun_l9_n917(x) + else + fun_l9_n210(x) + end +end + +def fun_l8_n259(x) + if (x < 1) + fun_l9_n851(x) + else + fun_l9_n342(x) + end +end + +def fun_l8_n260(x) + if (x < 1) + fun_l9_n205(x) + else + fun_l9_n412(x) + end +end + +def fun_l8_n261(x) + if (x < 1) + fun_l9_n110(x) + else + fun_l9_n62(x) + end +end + +def fun_l8_n262(x) + if (x < 1) + fun_l9_n706(x) + else + fun_l9_n903(x) + end +end + +def fun_l8_n263(x) + if (x < 1) + fun_l9_n403(x) + else + fun_l9_n994(x) + end +end + +def fun_l8_n264(x) + if (x < 1) + fun_l9_n631(x) + else + fun_l9_n126(x) + end +end + +def fun_l8_n265(x) + if (x < 1) + fun_l9_n216(x) + else + fun_l9_n573(x) + end +end + +def fun_l8_n266(x) + if (x < 1) + fun_l9_n174(x) + else + fun_l9_n495(x) + end +end + +def fun_l8_n267(x) + if (x < 1) + fun_l9_n802(x) + else + fun_l9_n881(x) + end +end + +def fun_l8_n268(x) + if (x < 1) + fun_l9_n148(x) + else + fun_l9_n399(x) + end +end + +def fun_l8_n269(x) + if (x < 1) + fun_l9_n675(x) + else + fun_l9_n596(x) + end +end + +def fun_l8_n270(x) + if (x < 1) + fun_l9_n306(x) + else + fun_l9_n413(x) + end +end + +def fun_l8_n271(x) + if (x < 1) + fun_l9_n205(x) + else + fun_l9_n569(x) + end +end + +def fun_l8_n272(x) + if (x < 1) + fun_l9_n6(x) + else + fun_l9_n531(x) + end +end + +def fun_l8_n273(x) + if (x < 1) + fun_l9_n516(x) + else + fun_l9_n172(x) + end +end + +def fun_l8_n274(x) + if (x < 1) + fun_l9_n641(x) + else + fun_l9_n85(x) + end +end + +def fun_l8_n275(x) + if (x < 1) + fun_l9_n258(x) + else + fun_l9_n773(x) + end +end + +def fun_l8_n276(x) + if (x < 1) + fun_l9_n233(x) + else + fun_l9_n222(x) + end +end + +def fun_l8_n277(x) + if (x < 1) + fun_l9_n615(x) + else + fun_l9_n598(x) + end +end + +def fun_l8_n278(x) + if (x < 1) + fun_l9_n126(x) + else + fun_l9_n270(x) + end +end + +def fun_l8_n279(x) + if (x < 1) + fun_l9_n186(x) + else + fun_l9_n78(x) + end +end + +def fun_l8_n280(x) + if (x < 1) + fun_l9_n731(x) + else + fun_l9_n114(x) + end +end + +def fun_l8_n281(x) + if (x < 1) + fun_l9_n513(x) + else + fun_l9_n69(x) + end +end + +def fun_l8_n282(x) + if (x < 1) + fun_l9_n208(x) + else + fun_l9_n466(x) + end +end + +def fun_l8_n283(x) + if (x < 1) + fun_l9_n958(x) + else + fun_l9_n86(x) + end +end + +def fun_l8_n284(x) + if (x < 1) + fun_l9_n663(x) + else + fun_l9_n619(x) + end +end + +def fun_l8_n285(x) + if (x < 1) + fun_l9_n698(x) + else + fun_l9_n97(x) + end +end + +def fun_l8_n286(x) + if (x < 1) + fun_l9_n544(x) + else + fun_l9_n791(x) + end +end + +def fun_l8_n287(x) + if (x < 1) + fun_l9_n51(x) + else + fun_l9_n415(x) + end +end + +def fun_l8_n288(x) + if (x < 1) + fun_l9_n942(x) + else + fun_l9_n11(x) + end +end + +def fun_l8_n289(x) + if (x < 1) + fun_l9_n386(x) + else + fun_l9_n507(x) + end +end + +def fun_l8_n290(x) + if (x < 1) + fun_l9_n983(x) + else + fun_l9_n81(x) + end +end + +def fun_l8_n291(x) + if (x < 1) + fun_l9_n403(x) + else + fun_l9_n628(x) + end +end + +def fun_l8_n292(x) + if (x < 1) + fun_l9_n479(x) + else + fun_l9_n379(x) + end +end + +def fun_l8_n293(x) + if (x < 1) + fun_l9_n284(x) + else + fun_l9_n109(x) + end +end + +def fun_l8_n294(x) + if (x < 1) + fun_l9_n29(x) + else + fun_l9_n802(x) + end +end + +def fun_l8_n295(x) + if (x < 1) + fun_l9_n579(x) + else + fun_l9_n371(x) + end +end + +def fun_l8_n296(x) + if (x < 1) + fun_l9_n96(x) + else + fun_l9_n632(x) + end +end + +def fun_l8_n297(x) + if (x < 1) + fun_l9_n442(x) + else + fun_l9_n396(x) + end +end + +def fun_l8_n298(x) + if (x < 1) + fun_l9_n902(x) + else + fun_l9_n804(x) + end +end + +def fun_l8_n299(x) + if (x < 1) + fun_l9_n561(x) + else + fun_l9_n952(x) + end +end + +def fun_l8_n300(x) + if (x < 1) + fun_l9_n757(x) + else + fun_l9_n819(x) + end +end + +def fun_l8_n301(x) + if (x < 1) + fun_l9_n97(x) + else + fun_l9_n892(x) + end +end + +def fun_l8_n302(x) + if (x < 1) + fun_l9_n67(x) + else + fun_l9_n765(x) + end +end + +def fun_l8_n303(x) + if (x < 1) + fun_l9_n166(x) + else + fun_l9_n769(x) + end +end + +def fun_l8_n304(x) + if (x < 1) + fun_l9_n592(x) + else + fun_l9_n423(x) + end +end + +def fun_l8_n305(x) + if (x < 1) + fun_l9_n354(x) + else + fun_l9_n953(x) + end +end + +def fun_l8_n306(x) + if (x < 1) + fun_l9_n857(x) + else + fun_l9_n18(x) + end +end + +def fun_l8_n307(x) + if (x < 1) + fun_l9_n445(x) + else + fun_l9_n796(x) + end +end + +def fun_l8_n308(x) + if (x < 1) + fun_l9_n293(x) + else + fun_l9_n304(x) + end +end + +def fun_l8_n309(x) + if (x < 1) + fun_l9_n859(x) + else + fun_l9_n282(x) + end +end + +def fun_l8_n310(x) + if (x < 1) + fun_l9_n133(x) + else + fun_l9_n90(x) + end +end + +def fun_l8_n311(x) + if (x < 1) + fun_l9_n997(x) + else + fun_l9_n201(x) + end +end + +def fun_l8_n312(x) + if (x < 1) + fun_l9_n140(x) + else + fun_l9_n772(x) + end +end + +def fun_l8_n313(x) + if (x < 1) + fun_l9_n761(x) + else + fun_l9_n980(x) + end +end + +def fun_l8_n314(x) + if (x < 1) + fun_l9_n357(x) + else + fun_l9_n552(x) + end +end + +def fun_l8_n315(x) + if (x < 1) + fun_l9_n312(x) + else + fun_l9_n412(x) + end +end + +def fun_l8_n316(x) + if (x < 1) + fun_l9_n700(x) + else + fun_l9_n551(x) + end +end + +def fun_l8_n317(x) + if (x < 1) + fun_l9_n623(x) + else + fun_l9_n219(x) + end +end + +def fun_l8_n318(x) + if (x < 1) + fun_l9_n613(x) + else + fun_l9_n959(x) + end +end + +def fun_l8_n319(x) + if (x < 1) + fun_l9_n978(x) + else + fun_l9_n596(x) + end +end + +def fun_l8_n320(x) + if (x < 1) + fun_l9_n542(x) + else + fun_l9_n527(x) + end +end + +def fun_l8_n321(x) + if (x < 1) + fun_l9_n877(x) + else + fun_l9_n108(x) + end +end + +def fun_l8_n322(x) + if (x < 1) + fun_l9_n817(x) + else + fun_l9_n476(x) + end +end + +def fun_l8_n323(x) + if (x < 1) + fun_l9_n765(x) + else + fun_l9_n672(x) + end +end + +def fun_l8_n324(x) + if (x < 1) + fun_l9_n863(x) + else + fun_l9_n605(x) + end +end + +def fun_l8_n325(x) + if (x < 1) + fun_l9_n566(x) + else + fun_l9_n592(x) + end +end + +def fun_l8_n326(x) + if (x < 1) + fun_l9_n607(x) + else + fun_l9_n968(x) + end +end + +def fun_l8_n327(x) + if (x < 1) + fun_l9_n36(x) + else + fun_l9_n380(x) + end +end + +def fun_l8_n328(x) + if (x < 1) + fun_l9_n597(x) + else + fun_l9_n664(x) + end +end + +def fun_l8_n329(x) + if (x < 1) + fun_l9_n195(x) + else + fun_l9_n268(x) + end +end + +def fun_l8_n330(x) + if (x < 1) + fun_l9_n419(x) + else + fun_l9_n715(x) + end +end + +def fun_l8_n331(x) + if (x < 1) + fun_l9_n451(x) + else + fun_l9_n518(x) + end +end + +def fun_l8_n332(x) + if (x < 1) + fun_l9_n106(x) + else + fun_l9_n236(x) + end +end + +def fun_l8_n333(x) + if (x < 1) + fun_l9_n611(x) + else + fun_l9_n825(x) + end +end + +def fun_l8_n334(x) + if (x < 1) + fun_l9_n394(x) + else + fun_l9_n34(x) + end +end + +def fun_l8_n335(x) + if (x < 1) + fun_l9_n63(x) + else + fun_l9_n58(x) + end +end + +def fun_l8_n336(x) + if (x < 1) + fun_l9_n475(x) + else + fun_l9_n455(x) + end +end + +def fun_l8_n337(x) + if (x < 1) + fun_l9_n836(x) + else + fun_l9_n318(x) + end +end + +def fun_l8_n338(x) + if (x < 1) + fun_l9_n844(x) + else + fun_l9_n21(x) + end +end + +def fun_l8_n339(x) + if (x < 1) + fun_l9_n628(x) + else + fun_l9_n721(x) + end +end + +def fun_l8_n340(x) + if (x < 1) + fun_l9_n966(x) + else + fun_l9_n833(x) + end +end + +def fun_l8_n341(x) + if (x < 1) + fun_l9_n267(x) + else + fun_l9_n28(x) + end +end + +def fun_l8_n342(x) + if (x < 1) + fun_l9_n204(x) + else + fun_l9_n838(x) + end +end + +def fun_l8_n343(x) + if (x < 1) + fun_l9_n151(x) + else + fun_l9_n382(x) + end +end + +def fun_l8_n344(x) + if (x < 1) + fun_l9_n409(x) + else + fun_l9_n591(x) + end +end + +def fun_l8_n345(x) + if (x < 1) + fun_l9_n680(x) + else + fun_l9_n912(x) + end +end + +def fun_l8_n346(x) + if (x < 1) + fun_l9_n150(x) + else + fun_l9_n34(x) + end +end + +def fun_l8_n347(x) + if (x < 1) + fun_l9_n538(x) + else + fun_l9_n441(x) + end +end + +def fun_l8_n348(x) + if (x < 1) + fun_l9_n707(x) + else + fun_l9_n199(x) + end +end + +def fun_l8_n349(x) + if (x < 1) + fun_l9_n245(x) + else + fun_l9_n809(x) + end +end + +def fun_l8_n350(x) + if (x < 1) + fun_l9_n16(x) + else + fun_l9_n565(x) + end +end + +def fun_l8_n351(x) + if (x < 1) + fun_l9_n857(x) + else + fun_l9_n37(x) + end +end + +def fun_l8_n352(x) + if (x < 1) + fun_l9_n816(x) + else + fun_l9_n941(x) + end +end + +def fun_l8_n353(x) + if (x < 1) + fun_l9_n605(x) + else + fun_l9_n476(x) + end +end + +def fun_l8_n354(x) + if (x < 1) + fun_l9_n641(x) + else + fun_l9_n319(x) + end +end + +def fun_l8_n355(x) + if (x < 1) + fun_l9_n133(x) + else + fun_l9_n676(x) + end +end + +def fun_l8_n356(x) + if (x < 1) + fun_l9_n826(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n357(x) + if (x < 1) + fun_l9_n17(x) + else + fun_l9_n486(x) + end +end + +def fun_l8_n358(x) + if (x < 1) + fun_l9_n90(x) + else + fun_l9_n744(x) + end +end + +def fun_l8_n359(x) + if (x < 1) + fun_l9_n745(x) + else + fun_l9_n158(x) + end +end + +def fun_l8_n360(x) + if (x < 1) + fun_l9_n261(x) + else + fun_l9_n878(x) + end +end + +def fun_l8_n361(x) + if (x < 1) + fun_l9_n832(x) + else + fun_l9_n905(x) + end +end + +def fun_l8_n362(x) + if (x < 1) + fun_l9_n879(x) + else + fun_l9_n475(x) + end +end + +def fun_l8_n363(x) + if (x < 1) + fun_l9_n586(x) + else + fun_l9_n272(x) + end +end + +def fun_l8_n364(x) + if (x < 1) + fun_l9_n469(x) + else + fun_l9_n918(x) + end +end + +def fun_l8_n365(x) + if (x < 1) + fun_l9_n568(x) + else + fun_l9_n777(x) + end +end + +def fun_l8_n366(x) + if (x < 1) + fun_l9_n662(x) + else + fun_l9_n957(x) + end +end + +def fun_l8_n367(x) + if (x < 1) + fun_l9_n26(x) + else + fun_l9_n593(x) + end +end + +def fun_l8_n368(x) + if (x < 1) + fun_l9_n766(x) + else + fun_l9_n598(x) + end +end + +def fun_l8_n369(x) + if (x < 1) + fun_l9_n362(x) + else + fun_l9_n491(x) + end +end + +def fun_l8_n370(x) + if (x < 1) + fun_l9_n205(x) + else + fun_l9_n585(x) + end +end + +def fun_l8_n371(x) + if (x < 1) + fun_l9_n301(x) + else + fun_l9_n796(x) + end +end + +def fun_l8_n372(x) + if (x < 1) + fun_l9_n527(x) + else + fun_l9_n31(x) + end +end + +def fun_l8_n373(x) + if (x < 1) + fun_l9_n461(x) + else + fun_l9_n42(x) + end +end + +def fun_l8_n374(x) + if (x < 1) + fun_l9_n288(x) + else + fun_l9_n534(x) + end +end + +def fun_l8_n375(x) + if (x < 1) + fun_l9_n558(x) + else + fun_l9_n403(x) + end +end + +def fun_l8_n376(x) + if (x < 1) + fun_l9_n835(x) + else + fun_l9_n390(x) + end +end + +def fun_l8_n377(x) + if (x < 1) + fun_l9_n658(x) + else + fun_l9_n768(x) + end +end + +def fun_l8_n378(x) + if (x < 1) + fun_l9_n856(x) + else + fun_l9_n299(x) + end +end + +def fun_l8_n379(x) + if (x < 1) + fun_l9_n196(x) + else + fun_l9_n540(x) + end +end + +def fun_l8_n380(x) + if (x < 1) + fun_l9_n70(x) + else + fun_l9_n627(x) + end +end + +def fun_l8_n381(x) + if (x < 1) + fun_l9_n28(x) + else + fun_l9_n377(x) + end +end + +def fun_l8_n382(x) + if (x < 1) + fun_l9_n955(x) + else + fun_l9_n124(x) + end +end + +def fun_l8_n383(x) + if (x < 1) + fun_l9_n16(x) + else + fun_l9_n783(x) + end +end + +def fun_l8_n384(x) + if (x < 1) + fun_l9_n843(x) + else + fun_l9_n801(x) + end +end + +def fun_l8_n385(x) + if (x < 1) + fun_l9_n876(x) + else + fun_l9_n152(x) + end +end + +def fun_l8_n386(x) + if (x < 1) + fun_l9_n6(x) + else + fun_l9_n432(x) + end +end + +def fun_l8_n387(x) + if (x < 1) + fun_l9_n636(x) + else + fun_l9_n325(x) + end +end + +def fun_l8_n388(x) + if (x < 1) + fun_l9_n267(x) + else + fun_l9_n716(x) + end +end + +def fun_l8_n389(x) + if (x < 1) + fun_l9_n898(x) + else + fun_l9_n776(x) + end +end + +def fun_l8_n390(x) + if (x < 1) + fun_l9_n481(x) + else + fun_l9_n878(x) + end +end + +def fun_l8_n391(x) + if (x < 1) + fun_l9_n398(x) + else + fun_l9_n159(x) + end +end + +def fun_l8_n392(x) + if (x < 1) + fun_l9_n889(x) + else + fun_l9_n517(x) + end +end + +def fun_l8_n393(x) + if (x < 1) + fun_l9_n460(x) + else + fun_l9_n440(x) + end +end + +def fun_l8_n394(x) + if (x < 1) + fun_l9_n576(x) + else + fun_l9_n421(x) + end +end + +def fun_l8_n395(x) + if (x < 1) + fun_l9_n310(x) + else + fun_l9_n646(x) + end +end + +def fun_l8_n396(x) + if (x < 1) + fun_l9_n914(x) + else + fun_l9_n414(x) + end +end + +def fun_l8_n397(x) + if (x < 1) + fun_l9_n330(x) + else + fun_l9_n520(x) + end +end + +def fun_l8_n398(x) + if (x < 1) + fun_l9_n175(x) + else + fun_l9_n975(x) + end +end + +def fun_l8_n399(x) + if (x < 1) + fun_l9_n443(x) + else + fun_l9_n964(x) + end +end + +def fun_l8_n400(x) + if (x < 1) + fun_l9_n810(x) + else + fun_l9_n102(x) + end +end + +def fun_l8_n401(x) + if (x < 1) + fun_l9_n352(x) + else + fun_l9_n295(x) + end +end + +def fun_l8_n402(x) + if (x < 1) + fun_l9_n980(x) + else + fun_l9_n974(x) + end +end + +def fun_l8_n403(x) + if (x < 1) + fun_l9_n169(x) + else + fun_l9_n877(x) + end +end + +def fun_l8_n404(x) + if (x < 1) + fun_l9_n333(x) + else + fun_l9_n306(x) + end +end + +def fun_l8_n405(x) + if (x < 1) + fun_l9_n183(x) + else + fun_l9_n704(x) + end +end + +def fun_l8_n406(x) + if (x < 1) + fun_l9_n532(x) + else + fun_l9_n684(x) + end +end + +def fun_l8_n407(x) + if (x < 1) + fun_l9_n526(x) + else + fun_l9_n287(x) + end +end + +def fun_l8_n408(x) + if (x < 1) + fun_l9_n377(x) + else + fun_l9_n351(x) + end +end + +def fun_l8_n409(x) + if (x < 1) + fun_l9_n770(x) + else + fun_l9_n738(x) + end +end + +def fun_l8_n410(x) + if (x < 1) + fun_l9_n61(x) + else + fun_l9_n499(x) + end +end + +def fun_l8_n411(x) + if (x < 1) + fun_l9_n156(x) + else + fun_l9_n247(x) + end +end + +def fun_l8_n412(x) + if (x < 1) + fun_l9_n431(x) + else + fun_l9_n636(x) + end +end + +def fun_l8_n413(x) + if (x < 1) + fun_l9_n540(x) + else + fun_l9_n329(x) + end +end + +def fun_l8_n414(x) + if (x < 1) + fun_l9_n49(x) + else + fun_l9_n979(x) + end +end + +def fun_l8_n415(x) + if (x < 1) + fun_l9_n94(x) + else + fun_l9_n487(x) + end +end + +def fun_l8_n416(x) + if (x < 1) + fun_l9_n679(x) + else + fun_l9_n644(x) + end +end + +def fun_l8_n417(x) + if (x < 1) + fun_l9_n907(x) + else + fun_l9_n324(x) + end +end + +def fun_l8_n418(x) + if (x < 1) + fun_l9_n426(x) + else + fun_l9_n495(x) + end +end + +def fun_l8_n419(x) + if (x < 1) + fun_l9_n273(x) + else + fun_l9_n838(x) + end +end + +def fun_l8_n420(x) + if (x < 1) + fun_l9_n631(x) + else + fun_l9_n205(x) + end +end + +def fun_l8_n421(x) + if (x < 1) + fun_l9_n484(x) + else + fun_l9_n80(x) + end +end + +def fun_l8_n422(x) + if (x < 1) + fun_l9_n908(x) + else + fun_l9_n514(x) + end +end + +def fun_l8_n423(x) + if (x < 1) + fun_l9_n265(x) + else + fun_l9_n190(x) + end +end + +def fun_l8_n424(x) + if (x < 1) + fun_l9_n463(x) + else + fun_l9_n714(x) + end +end + +def fun_l8_n425(x) + if (x < 1) + fun_l9_n780(x) + else + fun_l9_n444(x) + end +end + +def fun_l8_n426(x) + if (x < 1) + fun_l9_n418(x) + else + fun_l9_n518(x) + end +end + +def fun_l8_n427(x) + if (x < 1) + fun_l9_n912(x) + else + fun_l9_n27(x) + end +end + +def fun_l8_n428(x) + if (x < 1) + fun_l9_n157(x) + else + fun_l9_n547(x) + end +end + +def fun_l8_n429(x) + if (x < 1) + fun_l9_n760(x) + else + fun_l9_n466(x) + end +end + +def fun_l8_n430(x) + if (x < 1) + fun_l9_n726(x) + else + fun_l9_n609(x) + end +end + +def fun_l8_n431(x) + if (x < 1) + fun_l9_n206(x) + else + fun_l9_n65(x) + end +end + +def fun_l8_n432(x) + if (x < 1) + fun_l9_n396(x) + else + fun_l9_n325(x) + end +end + +def fun_l8_n433(x) + if (x < 1) + fun_l9_n100(x) + else + fun_l9_n519(x) + end +end + +def fun_l8_n434(x) + if (x < 1) + fun_l9_n923(x) + else + fun_l9_n387(x) + end +end + +def fun_l8_n435(x) + if (x < 1) + fun_l9_n334(x) + else + fun_l9_n866(x) + end +end + +def fun_l8_n436(x) + if (x < 1) + fun_l9_n896(x) + else + fun_l9_n780(x) + end +end + +def fun_l8_n437(x) + if (x < 1) + fun_l9_n328(x) + else + fun_l9_n776(x) + end +end + +def fun_l8_n438(x) + if (x < 1) + fun_l9_n414(x) + else + fun_l9_n884(x) + end +end + +def fun_l8_n439(x) + if (x < 1) + fun_l9_n528(x) + else + fun_l9_n419(x) + end +end + +def fun_l8_n440(x) + if (x < 1) + fun_l9_n192(x) + else + fun_l9_n973(x) + end +end + +def fun_l8_n441(x) + if (x < 1) + fun_l9_n679(x) + else + fun_l9_n135(x) + end +end + +def fun_l8_n442(x) + if (x < 1) + fun_l9_n294(x) + else + fun_l9_n138(x) + end +end + +def fun_l8_n443(x) + if (x < 1) + fun_l9_n784(x) + else + fun_l9_n940(x) + end +end + +def fun_l8_n444(x) + if (x < 1) + fun_l9_n834(x) + else + fun_l9_n127(x) + end +end + +def fun_l8_n445(x) + if (x < 1) + fun_l9_n217(x) + else + fun_l9_n788(x) + end +end + +def fun_l8_n446(x) + if (x < 1) + fun_l9_n173(x) + else + fun_l9_n49(x) + end +end + +def fun_l8_n447(x) + if (x < 1) + fun_l9_n493(x) + else + fun_l9_n384(x) + end +end + +def fun_l8_n448(x) + if (x < 1) + fun_l9_n770(x) + else + fun_l9_n761(x) + end +end + +def fun_l8_n449(x) + if (x < 1) + fun_l9_n633(x) + else + fun_l9_n555(x) + end +end + +def fun_l8_n450(x) + if (x < 1) + fun_l9_n25(x) + else + fun_l9_n714(x) + end +end + +def fun_l8_n451(x) + if (x < 1) + fun_l9_n960(x) + else + fun_l9_n371(x) + end +end + +def fun_l8_n452(x) + if (x < 1) + fun_l9_n733(x) + else + fun_l9_n996(x) + end +end + +def fun_l8_n453(x) + if (x < 1) + fun_l9_n628(x) + else + fun_l9_n512(x) + end +end + +def fun_l8_n454(x) + if (x < 1) + fun_l9_n406(x) + else + fun_l9_n671(x) + end +end + +def fun_l8_n455(x) + if (x < 1) + fun_l9_n47(x) + else + fun_l9_n102(x) + end +end + +def fun_l8_n456(x) + if (x < 1) + fun_l9_n85(x) + else + fun_l9_n591(x) + end +end + +def fun_l8_n457(x) + if (x < 1) + fun_l9_n234(x) + else + fun_l9_n209(x) + end +end + +def fun_l8_n458(x) + if (x < 1) + fun_l9_n186(x) + else + fun_l9_n928(x) + end +end + +def fun_l8_n459(x) + if (x < 1) + fun_l9_n36(x) + else + fun_l9_n783(x) + end +end + +def fun_l8_n460(x) + if (x < 1) + fun_l9_n775(x) + else + fun_l9_n641(x) + end +end + +def fun_l8_n461(x) + if (x < 1) + fun_l9_n426(x) + else + fun_l9_n740(x) + end +end + +def fun_l8_n462(x) + if (x < 1) + fun_l9_n770(x) + else + fun_l9_n113(x) + end +end + +def fun_l8_n463(x) + if (x < 1) + fun_l9_n94(x) + else + fun_l9_n574(x) + end +end + +def fun_l8_n464(x) + if (x < 1) + fun_l9_n457(x) + else + fun_l9_n776(x) + end +end + +def fun_l8_n465(x) + if (x < 1) + fun_l9_n252(x) + else + fun_l9_n182(x) + end +end + +def fun_l8_n466(x) + if (x < 1) + fun_l9_n157(x) + else + fun_l9_n849(x) + end +end + +def fun_l8_n467(x) + if (x < 1) + fun_l9_n393(x) + else + fun_l9_n437(x) + end +end + +def fun_l8_n468(x) + if (x < 1) + fun_l9_n269(x) + else + fun_l9_n381(x) + end +end + +def fun_l8_n469(x) + if (x < 1) + fun_l9_n97(x) + else + fun_l9_n184(x) + end +end + +def fun_l8_n470(x) + if (x < 1) + fun_l9_n157(x) + else + fun_l9_n621(x) + end +end + +def fun_l8_n471(x) + if (x < 1) + fun_l9_n627(x) + else + fun_l9_n793(x) + end +end + +def fun_l8_n472(x) + if (x < 1) + fun_l9_n117(x) + else + fun_l9_n318(x) + end +end + +def fun_l8_n473(x) + if (x < 1) + fun_l9_n238(x) + else + fun_l9_n559(x) + end +end + +def fun_l8_n474(x) + if (x < 1) + fun_l9_n81(x) + else + fun_l9_n355(x) + end +end + +def fun_l8_n475(x) + if (x < 1) + fun_l9_n889(x) + else + fun_l9_n940(x) + end +end + +def fun_l8_n476(x) + if (x < 1) + fun_l9_n358(x) + else + fun_l9_n52(x) + end +end + +def fun_l8_n477(x) + if (x < 1) + fun_l9_n144(x) + else + fun_l9_n575(x) + end +end + +def fun_l8_n478(x) + if (x < 1) + fun_l9_n975(x) + else + fun_l9_n740(x) + end +end + +def fun_l8_n479(x) + if (x < 1) + fun_l9_n552(x) + else + fun_l9_n169(x) + end +end + +def fun_l8_n480(x) + if (x < 1) + fun_l9_n854(x) + else + fun_l9_n524(x) + end +end + +def fun_l8_n481(x) + if (x < 1) + fun_l9_n461(x) + else + fun_l9_n65(x) + end +end + +def fun_l8_n482(x) + if (x < 1) + fun_l9_n809(x) + else + fun_l9_n844(x) + end +end + +def fun_l8_n483(x) + if (x < 1) + fun_l9_n741(x) + else + fun_l9_n327(x) + end +end + +def fun_l8_n484(x) + if (x < 1) + fun_l9_n560(x) + else + fun_l9_n385(x) + end +end + +def fun_l8_n485(x) + if (x < 1) + fun_l9_n798(x) + else + fun_l9_n154(x) + end +end + +def fun_l8_n486(x) + if (x < 1) + fun_l9_n892(x) + else + fun_l9_n367(x) + end +end + +def fun_l8_n487(x) + if (x < 1) + fun_l9_n423(x) + else + fun_l9_n723(x) + end +end + +def fun_l8_n488(x) + if (x < 1) + fun_l9_n618(x) + else + fun_l9_n649(x) + end +end + +def fun_l8_n489(x) + if (x < 1) + fun_l9_n261(x) + else + fun_l9_n495(x) + end +end + +def fun_l8_n490(x) + if (x < 1) + fun_l9_n566(x) + else + fun_l9_n405(x) + end +end + +def fun_l8_n491(x) + if (x < 1) + fun_l9_n718(x) + else + fun_l9_n674(x) + end +end + +def fun_l8_n492(x) + if (x < 1) + fun_l9_n487(x) + else + fun_l9_n95(x) + end +end + +def fun_l8_n493(x) + if (x < 1) + fun_l9_n473(x) + else + fun_l9_n722(x) + end +end + +def fun_l8_n494(x) + if (x < 1) + fun_l9_n460(x) + else + fun_l9_n157(x) + end +end + +def fun_l8_n495(x) + if (x < 1) + fun_l9_n812(x) + else + fun_l9_n807(x) + end +end + +def fun_l8_n496(x) + if (x < 1) + fun_l9_n609(x) + else + fun_l9_n697(x) + end +end + +def fun_l8_n497(x) + if (x < 1) + fun_l9_n894(x) + else + fun_l9_n580(x) + end +end + +def fun_l8_n498(x) + if (x < 1) + fun_l9_n642(x) + else + fun_l9_n13(x) + end +end + +def fun_l8_n499(x) + if (x < 1) + fun_l9_n961(x) + else + fun_l9_n669(x) + end +end + +def fun_l8_n500(x) + if (x < 1) + fun_l9_n587(x) + else + fun_l9_n828(x) + end +end + +def fun_l8_n501(x) + if (x < 1) + fun_l9_n30(x) + else + fun_l9_n966(x) + end +end + +def fun_l8_n502(x) + if (x < 1) + fun_l9_n436(x) + else + fun_l9_n170(x) + end +end + +def fun_l8_n503(x) + if (x < 1) + fun_l9_n20(x) + else + fun_l9_n927(x) + end +end + +def fun_l8_n504(x) + if (x < 1) + fun_l9_n326(x) + else + fun_l9_n223(x) + end +end + +def fun_l8_n505(x) + if (x < 1) + fun_l9_n911(x) + else + fun_l9_n746(x) + end +end + +def fun_l8_n506(x) + if (x < 1) + fun_l9_n333(x) + else + fun_l9_n773(x) + end +end + +def fun_l8_n507(x) + if (x < 1) + fun_l9_n514(x) + else + fun_l9_n882(x) + end +end + +def fun_l8_n508(x) + if (x < 1) + fun_l9_n918(x) + else + fun_l9_n713(x) + end +end + +def fun_l8_n509(x) + if (x < 1) + fun_l9_n694(x) + else + fun_l9_n950(x) + end +end + +def fun_l8_n510(x) + if (x < 1) + fun_l9_n77(x) + else + fun_l9_n65(x) + end +end + +def fun_l8_n511(x) + if (x < 1) + fun_l9_n506(x) + else + fun_l9_n144(x) + end +end + +def fun_l8_n512(x) + if (x < 1) + fun_l9_n69(x) + else + fun_l9_n308(x) + end +end + +def fun_l8_n513(x) + if (x < 1) + fun_l9_n377(x) + else + fun_l9_n531(x) + end +end + +def fun_l8_n514(x) + if (x < 1) + fun_l9_n342(x) + else + fun_l9_n265(x) + end +end + +def fun_l8_n515(x) + if (x < 1) + fun_l9_n453(x) + else + fun_l9_n227(x) + end +end + +def fun_l8_n516(x) + if (x < 1) + fun_l9_n396(x) + else + fun_l9_n130(x) + end +end + +def fun_l8_n517(x) + if (x < 1) + fun_l9_n715(x) + else + fun_l9_n953(x) + end +end + +def fun_l8_n518(x) + if (x < 1) + fun_l9_n326(x) + else + fun_l9_n949(x) + end +end + +def fun_l8_n519(x) + if (x < 1) + fun_l9_n535(x) + else + fun_l9_n41(x) + end +end + +def fun_l8_n520(x) + if (x < 1) + fun_l9_n985(x) + else + fun_l9_n942(x) + end +end + +def fun_l8_n521(x) + if (x < 1) + fun_l9_n347(x) + else + fun_l9_n263(x) + end +end + +def fun_l8_n522(x) + if (x < 1) + fun_l9_n532(x) + else + fun_l9_n378(x) + end +end + +def fun_l8_n523(x) + if (x < 1) + fun_l9_n362(x) + else + fun_l9_n630(x) + end +end + +def fun_l8_n524(x) + if (x < 1) + fun_l9_n382(x) + else + fun_l9_n256(x) + end +end + +def fun_l8_n525(x) + if (x < 1) + fun_l9_n444(x) + else + fun_l9_n756(x) + end +end + +def fun_l8_n526(x) + if (x < 1) + fun_l9_n5(x) + else + fun_l9_n754(x) + end +end + +def fun_l8_n527(x) + if (x < 1) + fun_l9_n157(x) + else + fun_l9_n279(x) + end +end + +def fun_l8_n528(x) + if (x < 1) + fun_l9_n110(x) + else + fun_l9_n246(x) + end +end + +def fun_l8_n529(x) + if (x < 1) + fun_l9_n312(x) + else + fun_l9_n890(x) + end +end + +def fun_l8_n530(x) + if (x < 1) + fun_l9_n624(x) + else + fun_l9_n548(x) + end +end + +def fun_l8_n531(x) + if (x < 1) + fun_l9_n615(x) + else + fun_l9_n948(x) + end +end + +def fun_l8_n532(x) + if (x < 1) + fun_l9_n519(x) + else + fun_l9_n583(x) + end +end + +def fun_l8_n533(x) + if (x < 1) + fun_l9_n292(x) + else + fun_l9_n827(x) + end +end + +def fun_l8_n534(x) + if (x < 1) + fun_l9_n893(x) + else + fun_l9_n877(x) + end +end + +def fun_l8_n535(x) + if (x < 1) + fun_l9_n873(x) + else + fun_l9_n399(x) + end +end + +def fun_l8_n536(x) + if (x < 1) + fun_l9_n497(x) + else + fun_l9_n507(x) + end +end + +def fun_l8_n537(x) + if (x < 1) + fun_l9_n404(x) + else + fun_l9_n815(x) + end +end + +def fun_l8_n538(x) + if (x < 1) + fun_l9_n258(x) + else + fun_l9_n810(x) + end +end + +def fun_l8_n539(x) + if (x < 1) + fun_l9_n907(x) + else + fun_l9_n720(x) + end +end + +def fun_l8_n540(x) + if (x < 1) + fun_l9_n752(x) + else + fun_l9_n597(x) + end +end + +def fun_l8_n541(x) + if (x < 1) + fun_l9_n802(x) + else + fun_l9_n45(x) + end +end + +def fun_l8_n542(x) + if (x < 1) + fun_l9_n635(x) + else + fun_l9_n470(x) + end +end + +def fun_l8_n543(x) + if (x < 1) + fun_l9_n353(x) + else + fun_l9_n238(x) + end +end + +def fun_l8_n544(x) + if (x < 1) + fun_l9_n656(x) + else + fun_l9_n569(x) + end +end + +def fun_l8_n545(x) + if (x < 1) + fun_l9_n494(x) + else + fun_l9_n566(x) + end +end + +def fun_l8_n546(x) + if (x < 1) + fun_l9_n65(x) + else + fun_l9_n896(x) + end +end + +def fun_l8_n547(x) + if (x < 1) + fun_l9_n995(x) + else + fun_l9_n727(x) + end +end + +def fun_l8_n548(x) + if (x < 1) + fun_l9_n562(x) + else + fun_l9_n759(x) + end +end + +def fun_l8_n549(x) + if (x < 1) + fun_l9_n210(x) + else + fun_l9_n734(x) + end +end + +def fun_l8_n550(x) + if (x < 1) + fun_l9_n482(x) + else + fun_l9_n11(x) + end +end + +def fun_l8_n551(x) + if (x < 1) + fun_l9_n86(x) + else + fun_l9_n867(x) + end +end + +def fun_l8_n552(x) + if (x < 1) + fun_l9_n647(x) + else + fun_l9_n293(x) + end +end + +def fun_l8_n553(x) + if (x < 1) + fun_l9_n98(x) + else + fun_l9_n868(x) + end +end + +def fun_l8_n554(x) + if (x < 1) + fun_l9_n380(x) + else + fun_l9_n2(x) + end +end + +def fun_l8_n555(x) + if (x < 1) + fun_l9_n274(x) + else + fun_l9_n489(x) + end +end + +def fun_l8_n556(x) + if (x < 1) + fun_l9_n623(x) + else + fun_l9_n848(x) + end +end + +def fun_l8_n557(x) + if (x < 1) + fun_l9_n642(x) + else + fun_l9_n890(x) + end +end + +def fun_l8_n558(x) + if (x < 1) + fun_l9_n247(x) + else + fun_l9_n65(x) + end +end + +def fun_l8_n559(x) + if (x < 1) + fun_l9_n896(x) + else + fun_l9_n937(x) + end +end + +def fun_l8_n560(x) + if (x < 1) + fun_l9_n592(x) + else + fun_l9_n211(x) + end +end + +def fun_l8_n561(x) + if (x < 1) + fun_l9_n205(x) + else + fun_l9_n971(x) + end +end + +def fun_l8_n562(x) + if (x < 1) + fun_l9_n663(x) + else + fun_l9_n147(x) + end +end + +def fun_l8_n563(x) + if (x < 1) + fun_l9_n722(x) + else + fun_l9_n649(x) + end +end + +def fun_l8_n564(x) + if (x < 1) + fun_l9_n605(x) + else + fun_l9_n58(x) + end +end + +def fun_l8_n565(x) + if (x < 1) + fun_l9_n914(x) + else + fun_l9_n617(x) + end +end + +def fun_l8_n566(x) + if (x < 1) + fun_l9_n772(x) + else + fun_l9_n428(x) + end +end + +def fun_l8_n567(x) + if (x < 1) + fun_l9_n870(x) + else + fun_l9_n672(x) + end +end + +def fun_l8_n568(x) + if (x < 1) + fun_l9_n946(x) + else + fun_l9_n465(x) + end +end + +def fun_l8_n569(x) + if (x < 1) + fun_l9_n507(x) + else + fun_l9_n346(x) + end +end + +def fun_l8_n570(x) + if (x < 1) + fun_l9_n157(x) + else + fun_l9_n70(x) + end +end + +def fun_l8_n571(x) + if (x < 1) + fun_l9_n549(x) + else + fun_l9_n831(x) + end +end + +def fun_l8_n572(x) + if (x < 1) + fun_l9_n463(x) + else + fun_l9_n843(x) + end +end + +def fun_l8_n573(x) + if (x < 1) + fun_l9_n676(x) + else + fun_l9_n651(x) + end +end + +def fun_l8_n574(x) + if (x < 1) + fun_l9_n648(x) + else + fun_l9_n562(x) + end +end + +def fun_l8_n575(x) + if (x < 1) + fun_l9_n771(x) + else + fun_l9_n549(x) + end +end + +def fun_l8_n576(x) + if (x < 1) + fun_l9_n899(x) + else + fun_l9_n436(x) + end +end + +def fun_l8_n577(x) + if (x < 1) + fun_l9_n110(x) + else + fun_l9_n708(x) + end +end + +def fun_l8_n578(x) + if (x < 1) + fun_l9_n49(x) + else + fun_l9_n559(x) + end +end + +def fun_l8_n579(x) + if (x < 1) + fun_l9_n937(x) + else + fun_l9_n962(x) + end +end + +def fun_l8_n580(x) + if (x < 1) + fun_l9_n970(x) + else + fun_l9_n203(x) + end +end + +def fun_l8_n581(x) + if (x < 1) + fun_l9_n901(x) + else + fun_l9_n666(x) + end +end + +def fun_l8_n582(x) + if (x < 1) + fun_l9_n79(x) + else + fun_l9_n260(x) + end +end + +def fun_l8_n583(x) + if (x < 1) + fun_l9_n167(x) + else + fun_l9_n512(x) + end +end + +def fun_l8_n584(x) + if (x < 1) + fun_l9_n750(x) + else + fun_l9_n406(x) + end +end + +def fun_l8_n585(x) + if (x < 1) + fun_l9_n118(x) + else + fun_l9_n525(x) + end +end + +def fun_l8_n586(x) + if (x < 1) + fun_l9_n573(x) + else + fun_l9_n657(x) + end +end + +def fun_l8_n587(x) + if (x < 1) + fun_l9_n228(x) + else + fun_l9_n903(x) + end +end + +def fun_l8_n588(x) + if (x < 1) + fun_l9_n971(x) + else + fun_l9_n608(x) + end +end + +def fun_l8_n589(x) + if (x < 1) + fun_l9_n334(x) + else + fun_l9_n704(x) + end +end + +def fun_l8_n590(x) + if (x < 1) + fun_l9_n398(x) + else + fun_l9_n500(x) + end +end + +def fun_l8_n591(x) + if (x < 1) + fun_l9_n196(x) + else + fun_l9_n616(x) + end +end + +def fun_l8_n592(x) + if (x < 1) + fun_l9_n756(x) + else + fun_l9_n655(x) + end +end + +def fun_l8_n593(x) + if (x < 1) + fun_l9_n864(x) + else + fun_l9_n697(x) + end +end + +def fun_l8_n594(x) + if (x < 1) + fun_l9_n35(x) + else + fun_l9_n554(x) + end +end + +def fun_l8_n595(x) + if (x < 1) + fun_l9_n480(x) + else + fun_l9_n688(x) + end +end + +def fun_l8_n596(x) + if (x < 1) + fun_l9_n846(x) + else + fun_l9_n403(x) + end +end + +def fun_l8_n597(x) + if (x < 1) + fun_l9_n522(x) + else + fun_l9_n532(x) + end +end + +def fun_l8_n598(x) + if (x < 1) + fun_l9_n800(x) + else + fun_l9_n531(x) + end +end + +def fun_l8_n599(x) + if (x < 1) + fun_l9_n64(x) + else + fun_l9_n876(x) + end +end + +def fun_l8_n600(x) + if (x < 1) + fun_l9_n614(x) + else + fun_l9_n660(x) + end +end + +def fun_l8_n601(x) + if (x < 1) + fun_l9_n119(x) + else + fun_l9_n998(x) + end +end + +def fun_l8_n602(x) + if (x < 1) + fun_l9_n549(x) + else + fun_l9_n911(x) + end +end + +def fun_l8_n603(x) + if (x < 1) + fun_l9_n659(x) + else + fun_l9_n664(x) + end +end + +def fun_l8_n604(x) + if (x < 1) + fun_l9_n570(x) + else + fun_l9_n960(x) + end +end + +def fun_l8_n605(x) + if (x < 1) + fun_l9_n82(x) + else + fun_l9_n658(x) + end +end + +def fun_l8_n606(x) + if (x < 1) + fun_l9_n379(x) + else + fun_l9_n881(x) + end +end + +def fun_l8_n607(x) + if (x < 1) + fun_l9_n104(x) + else + fun_l9_n869(x) + end +end + +def fun_l8_n608(x) + if (x < 1) + fun_l9_n874(x) + else + fun_l9_n63(x) + end +end + +def fun_l8_n609(x) + if (x < 1) + fun_l9_n921(x) + else + fun_l9_n667(x) + end +end + +def fun_l8_n610(x) + if (x < 1) + fun_l9_n1(x) + else + fun_l9_n524(x) + end +end + +def fun_l8_n611(x) + if (x < 1) + fun_l9_n523(x) + else + fun_l9_n230(x) + end +end + +def fun_l8_n612(x) + if (x < 1) + fun_l9_n914(x) + else + fun_l9_n129(x) + end +end + +def fun_l8_n613(x) + if (x < 1) + fun_l9_n591(x) + else + fun_l9_n551(x) + end +end + +def fun_l8_n614(x) + if (x < 1) + fun_l9_n860(x) + else + fun_l9_n358(x) + end +end + +def fun_l8_n615(x) + if (x < 1) + fun_l9_n387(x) + else + fun_l9_n425(x) + end +end + +def fun_l8_n616(x) + if (x < 1) + fun_l9_n426(x) + else + fun_l9_n449(x) + end +end + +def fun_l8_n617(x) + if (x < 1) + fun_l9_n627(x) + else + fun_l9_n399(x) + end +end + +def fun_l8_n618(x) + if (x < 1) + fun_l9_n244(x) + else + fun_l9_n24(x) + end +end + +def fun_l8_n619(x) + if (x < 1) + fun_l9_n574(x) + else + fun_l9_n640(x) + end +end + +def fun_l8_n620(x) + if (x < 1) + fun_l9_n20(x) + else + fun_l9_n6(x) + end +end + +def fun_l8_n621(x) + if (x < 1) + fun_l9_n148(x) + else + fun_l9_n718(x) + end +end + +def fun_l8_n622(x) + if (x < 1) + fun_l9_n151(x) + else + fun_l9_n56(x) + end +end + +def fun_l8_n623(x) + if (x < 1) + fun_l9_n672(x) + else + fun_l9_n93(x) + end +end + +def fun_l8_n624(x) + if (x < 1) + fun_l9_n948(x) + else + fun_l9_n530(x) + end +end + +def fun_l8_n625(x) + if (x < 1) + fun_l9_n0(x) + else + fun_l9_n334(x) + end +end + +def fun_l8_n626(x) + if (x < 1) + fun_l9_n736(x) + else + fun_l9_n922(x) + end +end + +def fun_l8_n627(x) + if (x < 1) + fun_l9_n291(x) + else + fun_l9_n953(x) + end +end + +def fun_l8_n628(x) + if (x < 1) + fun_l9_n493(x) + else + fun_l9_n4(x) + end +end + +def fun_l8_n629(x) + if (x < 1) + fun_l9_n890(x) + else + fun_l9_n297(x) + end +end + +def fun_l8_n630(x) + if (x < 1) + fun_l9_n860(x) + else + fun_l9_n74(x) + end +end + +def fun_l8_n631(x) + if (x < 1) + fun_l9_n400(x) + else + fun_l9_n584(x) + end +end + +def fun_l8_n632(x) + if (x < 1) + fun_l9_n714(x) + else + fun_l9_n200(x) + end +end + +def fun_l8_n633(x) + if (x < 1) + fun_l9_n433(x) + else + fun_l9_n489(x) + end +end + +def fun_l8_n634(x) + if (x < 1) + fun_l9_n974(x) + else + fun_l9_n25(x) + end +end + +def fun_l8_n635(x) + if (x < 1) + fun_l9_n739(x) + else + fun_l9_n695(x) + end +end + +def fun_l8_n636(x) + if (x < 1) + fun_l9_n855(x) + else + fun_l9_n898(x) + end +end + +def fun_l8_n637(x) + if (x < 1) + fun_l9_n868(x) + else + fun_l9_n825(x) + end +end + +def fun_l8_n638(x) + if (x < 1) + fun_l9_n537(x) + else + fun_l9_n417(x) + end +end + +def fun_l8_n639(x) + if (x < 1) + fun_l9_n975(x) + else + fun_l9_n484(x) + end +end + +def fun_l8_n640(x) + if (x < 1) + fun_l9_n228(x) + else + fun_l9_n964(x) + end +end + +def fun_l8_n641(x) + if (x < 1) + fun_l9_n743(x) + else + fun_l9_n986(x) + end +end + +def fun_l8_n642(x) + if (x < 1) + fun_l9_n763(x) + else + fun_l9_n747(x) + end +end + +def fun_l8_n643(x) + if (x < 1) + fun_l9_n77(x) + else + fun_l9_n149(x) + end +end + +def fun_l8_n644(x) + if (x < 1) + fun_l9_n393(x) + else + fun_l9_n694(x) + end +end + +def fun_l8_n645(x) + if (x < 1) + fun_l9_n196(x) + else + fun_l9_n211(x) + end +end + +def fun_l8_n646(x) + if (x < 1) + fun_l9_n94(x) + else + fun_l9_n649(x) + end +end + +def fun_l8_n647(x) + if (x < 1) + fun_l9_n669(x) + else + fun_l9_n12(x) + end +end + +def fun_l8_n648(x) + if (x < 1) + fun_l9_n175(x) + else + fun_l9_n388(x) + end +end + +def fun_l8_n649(x) + if (x < 1) + fun_l9_n122(x) + else + fun_l9_n736(x) + end +end + +def fun_l8_n650(x) + if (x < 1) + fun_l9_n817(x) + else + fun_l9_n274(x) + end +end + +def fun_l8_n651(x) + if (x < 1) + fun_l9_n919(x) + else + fun_l9_n538(x) + end +end + +def fun_l8_n652(x) + if (x < 1) + fun_l9_n171(x) + else + fun_l9_n895(x) + end +end + +def fun_l8_n653(x) + if (x < 1) + fun_l9_n417(x) + else + fun_l9_n618(x) + end +end + +def fun_l8_n654(x) + if (x < 1) + fun_l9_n709(x) + else + fun_l9_n892(x) + end +end + +def fun_l8_n655(x) + if (x < 1) + fun_l9_n906(x) + else + fun_l9_n602(x) + end +end + +def fun_l8_n656(x) + if (x < 1) + fun_l9_n769(x) + else + fun_l9_n554(x) + end +end + +def fun_l8_n657(x) + if (x < 1) + fun_l9_n468(x) + else + fun_l9_n320(x) + end +end + +def fun_l8_n658(x) + if (x < 1) + fun_l9_n38(x) + else + fun_l9_n947(x) + end +end + +def fun_l8_n659(x) + if (x < 1) + fun_l9_n635(x) + else + fun_l9_n327(x) + end +end + +def fun_l8_n660(x) + if (x < 1) + fun_l9_n452(x) + else + fun_l9_n313(x) + end +end + +def fun_l8_n661(x) + if (x < 1) + fun_l9_n568(x) + else + fun_l9_n383(x) + end +end + +def fun_l8_n662(x) + if (x < 1) + fun_l9_n795(x) + else + fun_l9_n680(x) + end +end + +def fun_l8_n663(x) + if (x < 1) + fun_l9_n152(x) + else + fun_l9_n846(x) + end +end + +def fun_l8_n664(x) + if (x < 1) + fun_l9_n585(x) + else + fun_l9_n670(x) + end +end + +def fun_l8_n665(x) + if (x < 1) + fun_l9_n133(x) + else + fun_l9_n799(x) + end +end + +def fun_l8_n666(x) + if (x < 1) + fun_l9_n699(x) + else + fun_l9_n311(x) + end +end + +def fun_l8_n667(x) + if (x < 1) + fun_l9_n558(x) + else + fun_l9_n669(x) + end +end + +def fun_l8_n668(x) + if (x < 1) + fun_l9_n825(x) + else + fun_l9_n534(x) + end +end + +def fun_l8_n669(x) + if (x < 1) + fun_l9_n143(x) + else + fun_l9_n21(x) + end +end + +def fun_l8_n670(x) + if (x < 1) + fun_l9_n827(x) + else + fun_l9_n679(x) + end +end + +def fun_l8_n671(x) + if (x < 1) + fun_l9_n704(x) + else + fun_l9_n922(x) + end +end + +def fun_l8_n672(x) + if (x < 1) + fun_l9_n776(x) + else + fun_l9_n867(x) + end +end + +def fun_l8_n673(x) + if (x < 1) + fun_l9_n871(x) + else + fun_l9_n315(x) + end +end + +def fun_l8_n674(x) + if (x < 1) + fun_l9_n860(x) + else + fun_l9_n945(x) + end +end + +def fun_l8_n675(x) + if (x < 1) + fun_l9_n890(x) + else + fun_l9_n629(x) + end +end + +def fun_l8_n676(x) + if (x < 1) + fun_l9_n91(x) + else + fun_l9_n35(x) + end +end + +def fun_l8_n677(x) + if (x < 1) + fun_l9_n825(x) + else + fun_l9_n922(x) + end +end + +def fun_l8_n678(x) + if (x < 1) + fun_l9_n457(x) + else + fun_l9_n156(x) + end +end + +def fun_l8_n679(x) + if (x < 1) + fun_l9_n455(x) + else + fun_l9_n809(x) + end +end + +def fun_l8_n680(x) + if (x < 1) + fun_l9_n213(x) + else + fun_l9_n944(x) + end +end + +def fun_l8_n681(x) + if (x < 1) + fun_l9_n760(x) + else + fun_l9_n137(x) + end +end + +def fun_l8_n682(x) + if (x < 1) + fun_l9_n998(x) + else + fun_l9_n703(x) + end +end + +def fun_l8_n683(x) + if (x < 1) + fun_l9_n988(x) + else + fun_l9_n952(x) + end +end + +def fun_l8_n684(x) + if (x < 1) + fun_l9_n583(x) + else + fun_l9_n890(x) + end +end + +def fun_l8_n685(x) + if (x < 1) + fun_l9_n879(x) + else + fun_l9_n978(x) + end +end + +def fun_l8_n686(x) + if (x < 1) + fun_l9_n6(x) + else + fun_l9_n978(x) + end +end + +def fun_l8_n687(x) + if (x < 1) + fun_l9_n67(x) + else + fun_l9_n149(x) + end +end + +def fun_l8_n688(x) + if (x < 1) + fun_l9_n386(x) + else + fun_l9_n293(x) + end +end + +def fun_l8_n689(x) + if (x < 1) + fun_l9_n493(x) + else + fun_l9_n140(x) + end +end + +def fun_l8_n690(x) + if (x < 1) + fun_l9_n92(x) + else + fun_l9_n550(x) + end +end + +def fun_l8_n691(x) + if (x < 1) + fun_l9_n456(x) + else + fun_l9_n976(x) + end +end + +def fun_l8_n692(x) + if (x < 1) + fun_l9_n516(x) + else + fun_l9_n145(x) + end +end + +def fun_l8_n693(x) + if (x < 1) + fun_l9_n757(x) + else + fun_l9_n647(x) + end +end + +def fun_l8_n694(x) + if (x < 1) + fun_l9_n348(x) + else + fun_l9_n86(x) + end +end + +def fun_l8_n695(x) + if (x < 1) + fun_l9_n546(x) + else + fun_l9_n320(x) + end +end + +def fun_l8_n696(x) + if (x < 1) + fun_l9_n588(x) + else + fun_l9_n285(x) + end +end + +def fun_l8_n697(x) + if (x < 1) + fun_l9_n635(x) + else + fun_l9_n710(x) + end +end + +def fun_l8_n698(x) + if (x < 1) + fun_l9_n312(x) + else + fun_l9_n217(x) + end +end + +def fun_l8_n699(x) + if (x < 1) + fun_l9_n714(x) + else + fun_l9_n723(x) + end +end + +def fun_l8_n700(x) + if (x < 1) + fun_l9_n378(x) + else + fun_l9_n122(x) + end +end + +def fun_l8_n701(x) + if (x < 1) + fun_l9_n696(x) + else + fun_l9_n577(x) + end +end + +def fun_l8_n702(x) + if (x < 1) + fun_l9_n388(x) + else + fun_l9_n578(x) + end +end + +def fun_l8_n703(x) + if (x < 1) + fun_l9_n502(x) + else + fun_l9_n410(x) + end +end + +def fun_l8_n704(x) + if (x < 1) + fun_l9_n532(x) + else + fun_l9_n532(x) + end +end + +def fun_l8_n705(x) + if (x < 1) + fun_l9_n662(x) + else + fun_l9_n361(x) + end +end + +def fun_l8_n706(x) + if (x < 1) + fun_l9_n109(x) + else + fun_l9_n380(x) + end +end + +def fun_l8_n707(x) + if (x < 1) + fun_l9_n653(x) + else + fun_l9_n566(x) + end +end + +def fun_l8_n708(x) + if (x < 1) + fun_l9_n587(x) + else + fun_l9_n465(x) + end +end + +def fun_l8_n709(x) + if (x < 1) + fun_l9_n523(x) + else + fun_l9_n274(x) + end +end + +def fun_l8_n710(x) + if (x < 1) + fun_l9_n459(x) + else + fun_l9_n872(x) + end +end + +def fun_l8_n711(x) + if (x < 1) + fun_l9_n71(x) + else + fun_l9_n135(x) + end +end + +def fun_l8_n712(x) + if (x < 1) + fun_l9_n770(x) + else + fun_l9_n405(x) + end +end + +def fun_l8_n713(x) + if (x < 1) + fun_l9_n233(x) + else + fun_l9_n232(x) + end +end + +def fun_l8_n714(x) + if (x < 1) + fun_l9_n29(x) + else + fun_l9_n23(x) + end +end + +def fun_l8_n715(x) + if (x < 1) + fun_l9_n44(x) + else + fun_l9_n185(x) + end +end + +def fun_l8_n716(x) + if (x < 1) + fun_l9_n980(x) + else + fun_l9_n967(x) + end +end + +def fun_l8_n717(x) + if (x < 1) + fun_l9_n323(x) + else + fun_l9_n636(x) + end +end + +def fun_l8_n718(x) + if (x < 1) + fun_l9_n733(x) + else + fun_l9_n10(x) + end +end + +def fun_l8_n719(x) + if (x < 1) + fun_l9_n100(x) + else + fun_l9_n123(x) + end +end + +def fun_l8_n720(x) + if (x < 1) + fun_l9_n572(x) + else + fun_l9_n813(x) + end +end + +def fun_l8_n721(x) + if (x < 1) + fun_l9_n634(x) + else + fun_l9_n152(x) + end +end + +def fun_l8_n722(x) + if (x < 1) + fun_l9_n527(x) + else + fun_l9_n881(x) + end +end + +def fun_l8_n723(x) + if (x < 1) + fun_l9_n202(x) + else + fun_l9_n294(x) + end +end + +def fun_l8_n724(x) + if (x < 1) + fun_l9_n668(x) + else + fun_l9_n792(x) + end +end + +def fun_l8_n725(x) + if (x < 1) + fun_l9_n309(x) + else + fun_l9_n612(x) + end +end + +def fun_l8_n726(x) + if (x < 1) + fun_l9_n320(x) + else + fun_l9_n459(x) + end +end + +def fun_l8_n727(x) + if (x < 1) + fun_l9_n355(x) + else + fun_l9_n321(x) + end +end + +def fun_l8_n728(x) + if (x < 1) + fun_l9_n237(x) + else + fun_l9_n135(x) + end +end + +def fun_l8_n729(x) + if (x < 1) + fun_l9_n980(x) + else + fun_l9_n209(x) + end +end + +def fun_l8_n730(x) + if (x < 1) + fun_l9_n957(x) + else + fun_l9_n481(x) + end +end + +def fun_l8_n731(x) + if (x < 1) + fun_l9_n594(x) + else + fun_l9_n396(x) + end +end + +def fun_l8_n732(x) + if (x < 1) + fun_l9_n916(x) + else + fun_l9_n473(x) + end +end + +def fun_l8_n733(x) + if (x < 1) + fun_l9_n376(x) + else + fun_l9_n231(x) + end +end + +def fun_l8_n734(x) + if (x < 1) + fun_l9_n758(x) + else + fun_l9_n111(x) + end +end + +def fun_l8_n735(x) + if (x < 1) + fun_l9_n131(x) + else + fun_l9_n586(x) + end +end + +def fun_l8_n736(x) + if (x < 1) + fun_l9_n290(x) + else + fun_l9_n227(x) + end +end + +def fun_l8_n737(x) + if (x < 1) + fun_l9_n784(x) + else + fun_l9_n869(x) + end +end + +def fun_l8_n738(x) + if (x < 1) + fun_l9_n94(x) + else + fun_l9_n79(x) + end +end + +def fun_l8_n739(x) + if (x < 1) + fun_l9_n489(x) + else + fun_l9_n347(x) + end +end + +def fun_l8_n740(x) + if (x < 1) + fun_l9_n4(x) + else + fun_l9_n587(x) + end +end + +def fun_l8_n741(x) + if (x < 1) + fun_l9_n949(x) + else + fun_l9_n196(x) + end +end + +def fun_l8_n742(x) + if (x < 1) + fun_l9_n577(x) + else + fun_l9_n562(x) + end +end + +def fun_l8_n743(x) + if (x < 1) + fun_l9_n656(x) + else + fun_l9_n685(x) + end +end + +def fun_l8_n744(x) + if (x < 1) + fun_l9_n792(x) + else + fun_l9_n572(x) + end +end + +def fun_l8_n745(x) + if (x < 1) + fun_l9_n318(x) + else + fun_l9_n335(x) + end +end + +def fun_l8_n746(x) + if (x < 1) + fun_l9_n59(x) + else + fun_l9_n109(x) + end +end + +def fun_l8_n747(x) + if (x < 1) + fun_l9_n276(x) + else + fun_l9_n567(x) + end +end + +def fun_l8_n748(x) + if (x < 1) + fun_l9_n902(x) + else + fun_l9_n220(x) + end +end + +def fun_l8_n749(x) + if (x < 1) + fun_l9_n208(x) + else + fun_l9_n108(x) + end +end + +def fun_l8_n750(x) + if (x < 1) + fun_l9_n927(x) + else + fun_l9_n950(x) + end +end + +def fun_l8_n751(x) + if (x < 1) + fun_l9_n371(x) + else + fun_l9_n72(x) + end +end + +def fun_l8_n752(x) + if (x < 1) + fun_l9_n455(x) + else + fun_l9_n467(x) + end +end + +def fun_l8_n753(x) + if (x < 1) + fun_l9_n344(x) + else + fun_l9_n82(x) + end +end + +def fun_l8_n754(x) + if (x < 1) + fun_l9_n902(x) + else + fun_l9_n219(x) + end +end + +def fun_l8_n755(x) + if (x < 1) + fun_l9_n101(x) + else + fun_l9_n523(x) + end +end + +def fun_l8_n756(x) + if (x < 1) + fun_l9_n517(x) + else + fun_l9_n97(x) + end +end + +def fun_l8_n757(x) + if (x < 1) + fun_l9_n571(x) + else + fun_l9_n650(x) + end +end + +def fun_l8_n758(x) + if (x < 1) + fun_l9_n701(x) + else + fun_l9_n962(x) + end +end + +def fun_l8_n759(x) + if (x < 1) + fun_l9_n589(x) + else + fun_l9_n808(x) + end +end + +def fun_l8_n760(x) + if (x < 1) + fun_l9_n570(x) + else + fun_l9_n90(x) + end +end + +def fun_l8_n761(x) + if (x < 1) + fun_l9_n792(x) + else + fun_l9_n673(x) + end +end + +def fun_l8_n762(x) + if (x < 1) + fun_l9_n514(x) + else + fun_l9_n771(x) + end +end + +def fun_l8_n763(x) + if (x < 1) + fun_l9_n404(x) + else + fun_l9_n264(x) + end +end + +def fun_l8_n764(x) + if (x < 1) + fun_l9_n270(x) + else + fun_l9_n738(x) + end +end + +def fun_l8_n765(x) + if (x < 1) + fun_l9_n915(x) + else + fun_l9_n901(x) + end +end + +def fun_l8_n766(x) + if (x < 1) + fun_l9_n120(x) + else + fun_l9_n176(x) + end +end + +def fun_l8_n767(x) + if (x < 1) + fun_l9_n470(x) + else + fun_l9_n837(x) + end +end + +def fun_l8_n768(x) + if (x < 1) + fun_l9_n912(x) + else + fun_l9_n898(x) + end +end + +def fun_l8_n769(x) + if (x < 1) + fun_l9_n76(x) + else + fun_l9_n350(x) + end +end + +def fun_l8_n770(x) + if (x < 1) + fun_l9_n487(x) + else + fun_l9_n572(x) + end +end + +def fun_l8_n771(x) + if (x < 1) + fun_l9_n823(x) + else + fun_l9_n815(x) + end +end + +def fun_l8_n772(x) + if (x < 1) + fun_l9_n655(x) + else + fun_l9_n968(x) + end +end + +def fun_l8_n773(x) + if (x < 1) + fun_l9_n824(x) + else + fun_l9_n741(x) + end +end + +def fun_l8_n774(x) + if (x < 1) + fun_l9_n143(x) + else + fun_l9_n641(x) + end +end + +def fun_l8_n775(x) + if (x < 1) + fun_l9_n985(x) + else + fun_l9_n592(x) + end +end + +def fun_l8_n776(x) + if (x < 1) + fun_l9_n686(x) + else + fun_l9_n234(x) + end +end + +def fun_l8_n777(x) + if (x < 1) + fun_l9_n540(x) + else + fun_l9_n794(x) + end +end + +def fun_l8_n778(x) + if (x < 1) + fun_l9_n154(x) + else + fun_l9_n656(x) + end +end + +def fun_l8_n779(x) + if (x < 1) + fun_l9_n836(x) + else + fun_l9_n756(x) + end +end + +def fun_l8_n780(x) + if (x < 1) + fun_l9_n98(x) + else + fun_l9_n233(x) + end +end + +def fun_l8_n781(x) + if (x < 1) + fun_l9_n584(x) + else + fun_l9_n398(x) + end +end + +def fun_l8_n782(x) + if (x < 1) + fun_l9_n851(x) + else + fun_l9_n967(x) + end +end + +def fun_l8_n783(x) + if (x < 1) + fun_l9_n868(x) + else + fun_l9_n57(x) + end +end + +def fun_l8_n784(x) + if (x < 1) + fun_l9_n782(x) + else + fun_l9_n214(x) + end +end + +def fun_l8_n785(x) + if (x < 1) + fun_l9_n79(x) + else + fun_l9_n489(x) + end +end + +def fun_l8_n786(x) + if (x < 1) + fun_l9_n757(x) + else + fun_l9_n918(x) + end +end + +def fun_l8_n787(x) + if (x < 1) + fun_l9_n985(x) + else + fun_l9_n781(x) + end +end + +def fun_l8_n788(x) + if (x < 1) + fun_l9_n921(x) + else + fun_l9_n542(x) + end +end + +def fun_l8_n789(x) + if (x < 1) + fun_l9_n982(x) + else + fun_l9_n834(x) + end +end + +def fun_l8_n790(x) + if (x < 1) + fun_l9_n482(x) + else + fun_l9_n424(x) + end +end + +def fun_l8_n791(x) + if (x < 1) + fun_l9_n289(x) + else + fun_l9_n487(x) + end +end + +def fun_l8_n792(x) + if (x < 1) + fun_l9_n820(x) + else + fun_l9_n242(x) + end +end + +def fun_l8_n793(x) + if (x < 1) + fun_l9_n110(x) + else + fun_l9_n356(x) + end +end + +def fun_l8_n794(x) + if (x < 1) + fun_l9_n142(x) + else + fun_l9_n607(x) + end +end + +def fun_l8_n795(x) + if (x < 1) + fun_l9_n21(x) + else + fun_l9_n14(x) + end +end + +def fun_l8_n796(x) + if (x < 1) + fun_l9_n147(x) + else + fun_l9_n767(x) + end +end + +def fun_l8_n797(x) + if (x < 1) + fun_l9_n427(x) + else + fun_l9_n854(x) + end +end + +def fun_l8_n798(x) + if (x < 1) + fun_l9_n557(x) + else + fun_l9_n729(x) + end +end + +def fun_l8_n799(x) + if (x < 1) + fun_l9_n150(x) + else + fun_l9_n180(x) + end +end + +def fun_l8_n800(x) + if (x < 1) + fun_l9_n888(x) + else + fun_l9_n612(x) + end +end + +def fun_l8_n801(x) + if (x < 1) + fun_l9_n631(x) + else + fun_l9_n370(x) + end +end + +def fun_l8_n802(x) + if (x < 1) + fun_l9_n759(x) + else + fun_l9_n446(x) + end +end + +def fun_l8_n803(x) + if (x < 1) + fun_l9_n182(x) + else + fun_l9_n705(x) + end +end + +def fun_l8_n804(x) + if (x < 1) + fun_l9_n474(x) + else + fun_l9_n461(x) + end +end + +def fun_l8_n805(x) + if (x < 1) + fun_l9_n897(x) + else + fun_l9_n935(x) + end +end + +def fun_l8_n806(x) + if (x < 1) + fun_l9_n793(x) + else + fun_l9_n981(x) + end +end + +def fun_l8_n807(x) + if (x < 1) + fun_l9_n124(x) + else + fun_l9_n528(x) + end +end + +def fun_l8_n808(x) + if (x < 1) + fun_l9_n637(x) + else + fun_l9_n989(x) + end +end + +def fun_l8_n809(x) + if (x < 1) + fun_l9_n388(x) + else + fun_l9_n196(x) + end +end + +def fun_l8_n810(x) + if (x < 1) + fun_l9_n333(x) + else + fun_l9_n806(x) + end +end + +def fun_l8_n811(x) + if (x < 1) + fun_l9_n541(x) + else + fun_l9_n6(x) + end +end + +def fun_l8_n812(x) + if (x < 1) + fun_l9_n346(x) + else + fun_l9_n496(x) + end +end + +def fun_l8_n813(x) + if (x < 1) + fun_l9_n374(x) + else + fun_l9_n739(x) + end +end + +def fun_l8_n814(x) + if (x < 1) + fun_l9_n121(x) + else + fun_l9_n184(x) + end +end + +def fun_l8_n815(x) + if (x < 1) + fun_l9_n460(x) + else + fun_l9_n759(x) + end +end + +def fun_l8_n816(x) + if (x < 1) + fun_l9_n598(x) + else + fun_l9_n638(x) + end +end + +def fun_l8_n817(x) + if (x < 1) + fun_l9_n986(x) + else + fun_l9_n658(x) + end +end + +def fun_l8_n818(x) + if (x < 1) + fun_l9_n169(x) + else + fun_l9_n696(x) + end +end + +def fun_l8_n819(x) + if (x < 1) + fun_l9_n885(x) + else + fun_l9_n74(x) + end +end + +def fun_l8_n820(x) + if (x < 1) + fun_l9_n24(x) + else + fun_l9_n87(x) + end +end + +def fun_l8_n821(x) + if (x < 1) + fun_l9_n59(x) + else + fun_l9_n843(x) + end +end + +def fun_l8_n822(x) + if (x < 1) + fun_l9_n640(x) + else + fun_l9_n360(x) + end +end + +def fun_l8_n823(x) + if (x < 1) + fun_l9_n355(x) + else + fun_l9_n28(x) + end +end + +def fun_l8_n824(x) + if (x < 1) + fun_l9_n553(x) + else + fun_l9_n475(x) + end +end + +def fun_l8_n825(x) + if (x < 1) + fun_l9_n757(x) + else + fun_l9_n790(x) + end +end + +def fun_l8_n826(x) + if (x < 1) + fun_l9_n787(x) + else + fun_l9_n226(x) + end +end + +def fun_l8_n827(x) + if (x < 1) + fun_l9_n622(x) + else + fun_l9_n711(x) + end +end + +def fun_l8_n828(x) + if (x < 1) + fun_l9_n399(x) + else + fun_l9_n7(x) + end +end + +def fun_l8_n829(x) + if (x < 1) + fun_l9_n589(x) + else + fun_l9_n276(x) + end +end + +def fun_l8_n830(x) + if (x < 1) + fun_l9_n83(x) + else + fun_l9_n126(x) + end +end + +def fun_l8_n831(x) + if (x < 1) + fun_l9_n576(x) + else + fun_l9_n855(x) + end +end + +def fun_l8_n832(x) + if (x < 1) + fun_l9_n756(x) + else + fun_l9_n638(x) + end +end + +def fun_l8_n833(x) + if (x < 1) + fun_l9_n388(x) + else + fun_l9_n154(x) + end +end + +def fun_l8_n834(x) + if (x < 1) + fun_l9_n268(x) + else + fun_l9_n85(x) + end +end + +def fun_l8_n835(x) + if (x < 1) + fun_l9_n32(x) + else + fun_l9_n678(x) + end +end + +def fun_l8_n836(x) + if (x < 1) + fun_l9_n537(x) + else + fun_l9_n984(x) + end +end + +def fun_l8_n837(x) + if (x < 1) + fun_l9_n798(x) + else + fun_l9_n221(x) + end +end + +def fun_l8_n838(x) + if (x < 1) + fun_l9_n153(x) + else + fun_l9_n414(x) + end +end + +def fun_l8_n839(x) + if (x < 1) + fun_l9_n904(x) + else + fun_l9_n847(x) + end +end + +def fun_l8_n840(x) + if (x < 1) + fun_l9_n501(x) + else + fun_l9_n971(x) + end +end + +def fun_l8_n841(x) + if (x < 1) + fun_l9_n94(x) + else + fun_l9_n719(x) + end +end + +def fun_l8_n842(x) + if (x < 1) + fun_l9_n343(x) + else + fun_l9_n365(x) + end +end + +def fun_l8_n843(x) + if (x < 1) + fun_l9_n541(x) + else + fun_l9_n800(x) + end +end + +def fun_l8_n844(x) + if (x < 1) + fun_l9_n122(x) + else + fun_l9_n662(x) + end +end + +def fun_l8_n845(x) + if (x < 1) + fun_l9_n312(x) + else + fun_l9_n688(x) + end +end + +def fun_l8_n846(x) + if (x < 1) + fun_l9_n668(x) + else + fun_l9_n805(x) + end +end + +def fun_l8_n847(x) + if (x < 1) + fun_l9_n785(x) + else + fun_l9_n917(x) + end +end + +def fun_l8_n848(x) + if (x < 1) + fun_l9_n333(x) + else + fun_l9_n782(x) + end +end + +def fun_l8_n849(x) + if (x < 1) + fun_l9_n402(x) + else + fun_l9_n398(x) + end +end + +def fun_l8_n850(x) + if (x < 1) + fun_l9_n708(x) + else + fun_l9_n199(x) + end +end + +def fun_l8_n851(x) + if (x < 1) + fun_l9_n950(x) + else + fun_l9_n308(x) + end +end + +def fun_l8_n852(x) + if (x < 1) + fun_l9_n524(x) + else + fun_l9_n411(x) + end +end + +def fun_l8_n853(x) + if (x < 1) + fun_l9_n467(x) + else + fun_l9_n807(x) + end +end + +def fun_l8_n854(x) + if (x < 1) + fun_l9_n316(x) + else + fun_l9_n717(x) + end +end + +def fun_l8_n855(x) + if (x < 1) + fun_l9_n955(x) + else + fun_l9_n631(x) + end +end + +def fun_l8_n856(x) + if (x < 1) + fun_l9_n244(x) + else + fun_l9_n838(x) + end +end + +def fun_l8_n857(x) + if (x < 1) + fun_l9_n574(x) + else + fun_l9_n720(x) + end +end + +def fun_l8_n858(x) + if (x < 1) + fun_l9_n80(x) + else + fun_l9_n888(x) + end +end + +def fun_l8_n859(x) + if (x < 1) + fun_l9_n675(x) + else + fun_l9_n71(x) + end +end + +def fun_l8_n860(x) + if (x < 1) + fun_l9_n375(x) + else + fun_l9_n507(x) + end +end + +def fun_l8_n861(x) + if (x < 1) + fun_l9_n450(x) + else + fun_l9_n705(x) + end +end + +def fun_l8_n862(x) + if (x < 1) + fun_l9_n358(x) + else + fun_l9_n614(x) + end +end + +def fun_l8_n863(x) + if (x < 1) + fun_l9_n690(x) + else + fun_l9_n73(x) + end +end + +def fun_l8_n864(x) + if (x < 1) + fun_l9_n806(x) + else + fun_l9_n85(x) + end +end + +def fun_l8_n865(x) + if (x < 1) + fun_l9_n251(x) + else + fun_l9_n657(x) + end +end + +def fun_l8_n866(x) + if (x < 1) + fun_l9_n921(x) + else + fun_l9_n199(x) + end +end + +def fun_l8_n867(x) + if (x < 1) + fun_l9_n265(x) + else + fun_l9_n937(x) + end +end + +def fun_l8_n868(x) + if (x < 1) + fun_l9_n610(x) + else + fun_l9_n7(x) + end +end + +def fun_l8_n869(x) + if (x < 1) + fun_l9_n703(x) + else + fun_l9_n74(x) + end +end + +def fun_l8_n870(x) + if (x < 1) + fun_l9_n869(x) + else + fun_l9_n665(x) + end +end + +def fun_l8_n871(x) + if (x < 1) + fun_l9_n808(x) + else + fun_l9_n686(x) + end +end + +def fun_l8_n872(x) + if (x < 1) + fun_l9_n678(x) + else + fun_l9_n709(x) + end +end + +def fun_l8_n873(x) + if (x < 1) + fun_l9_n557(x) + else + fun_l9_n63(x) + end +end + +def fun_l8_n874(x) + if (x < 1) + fun_l9_n214(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n875(x) + if (x < 1) + fun_l9_n218(x) + else + fun_l9_n810(x) + end +end + +def fun_l8_n876(x) + if (x < 1) + fun_l9_n365(x) + else + fun_l9_n257(x) + end +end + +def fun_l8_n877(x) + if (x < 1) + fun_l9_n51(x) + else + fun_l9_n68(x) + end +end + +def fun_l8_n878(x) + if (x < 1) + fun_l9_n20(x) + else + fun_l9_n55(x) + end +end + +def fun_l8_n879(x) + if (x < 1) + fun_l9_n686(x) + else + fun_l9_n226(x) + end +end + +def fun_l8_n880(x) + if (x < 1) + fun_l9_n283(x) + else + fun_l9_n270(x) + end +end + +def fun_l8_n881(x) + if (x < 1) + fun_l9_n811(x) + else + fun_l9_n820(x) + end +end + +def fun_l8_n882(x) + if (x < 1) + fun_l9_n342(x) + else + fun_l9_n919(x) + end +end + +def fun_l8_n883(x) + if (x < 1) + fun_l9_n515(x) + else + fun_l9_n24(x) + end +end + +def fun_l8_n884(x) + if (x < 1) + fun_l9_n0(x) + else + fun_l9_n150(x) + end +end + +def fun_l8_n885(x) + if (x < 1) + fun_l9_n481(x) + else + fun_l9_n65(x) + end +end + +def fun_l8_n886(x) + if (x < 1) + fun_l9_n252(x) + else + fun_l9_n544(x) + end +end + +def fun_l8_n887(x) + if (x < 1) + fun_l9_n635(x) + else + fun_l9_n402(x) + end +end + +def fun_l8_n888(x) + if (x < 1) + fun_l9_n78(x) + else + fun_l9_n779(x) + end +end + +def fun_l8_n889(x) + if (x < 1) + fun_l9_n249(x) + else + fun_l9_n331(x) + end +end + +def fun_l8_n890(x) + if (x < 1) + fun_l9_n914(x) + else + fun_l9_n115(x) + end +end + +def fun_l8_n891(x) + if (x < 1) + fun_l9_n832(x) + else + fun_l9_n34(x) + end +end + +def fun_l8_n892(x) + if (x < 1) + fun_l9_n919(x) + else + fun_l9_n620(x) + end +end + +def fun_l8_n893(x) + if (x < 1) + fun_l9_n360(x) + else + fun_l9_n189(x) + end +end + +def fun_l8_n894(x) + if (x < 1) + fun_l9_n736(x) + else + fun_l9_n949(x) + end +end + +def fun_l8_n895(x) + if (x < 1) + fun_l9_n56(x) + else + fun_l9_n826(x) + end +end + +def fun_l8_n896(x) + if (x < 1) + fun_l9_n159(x) + else + fun_l9_n523(x) + end +end + +def fun_l8_n897(x) + if (x < 1) + fun_l9_n630(x) + else + fun_l9_n601(x) + end +end + +def fun_l8_n898(x) + if (x < 1) + fun_l9_n434(x) + else + fun_l9_n919(x) + end +end + +def fun_l8_n899(x) + if (x < 1) + fun_l9_n872(x) + else + fun_l9_n652(x) + end +end + +def fun_l8_n900(x) + if (x < 1) + fun_l9_n550(x) + else + fun_l9_n124(x) + end +end + +def fun_l8_n901(x) + if (x < 1) + fun_l9_n56(x) + else + fun_l9_n422(x) + end +end + +def fun_l8_n902(x) + if (x < 1) + fun_l9_n297(x) + else + fun_l9_n281(x) + end +end + +def fun_l8_n903(x) + if (x < 1) + fun_l9_n764(x) + else + fun_l9_n942(x) + end +end + +def fun_l8_n904(x) + if (x < 1) + fun_l9_n700(x) + else + fun_l9_n525(x) + end +end + +def fun_l8_n905(x) + if (x < 1) + fun_l9_n370(x) + else + fun_l9_n871(x) + end +end + +def fun_l8_n906(x) + if (x < 1) + fun_l9_n385(x) + else + fun_l9_n999(x) + end +end + +def fun_l8_n907(x) + if (x < 1) + fun_l9_n63(x) + else + fun_l9_n137(x) + end +end + +def fun_l8_n908(x) + if (x < 1) + fun_l9_n793(x) + else + fun_l9_n720(x) + end +end + +def fun_l8_n909(x) + if (x < 1) + fun_l9_n141(x) + else + fun_l9_n838(x) + end +end + +def fun_l8_n910(x) + if (x < 1) + fun_l9_n764(x) + else + fun_l9_n334(x) + end +end + +def fun_l8_n911(x) + if (x < 1) + fun_l9_n429(x) + else + fun_l9_n309(x) + end +end + +def fun_l8_n912(x) + if (x < 1) + fun_l9_n852(x) + else + fun_l9_n662(x) + end +end + +def fun_l8_n913(x) + if (x < 1) + fun_l9_n467(x) + else + fun_l9_n817(x) + end +end + +def fun_l8_n914(x) + if (x < 1) + fun_l9_n318(x) + else + fun_l9_n942(x) + end +end + +def fun_l8_n915(x) + if (x < 1) + fun_l9_n442(x) + else + fun_l9_n987(x) + end +end + +def fun_l8_n916(x) + if (x < 1) + fun_l9_n657(x) + else + fun_l9_n736(x) + end +end + +def fun_l8_n917(x) + if (x < 1) + fun_l9_n839(x) + else + fun_l9_n897(x) + end +end + +def fun_l8_n918(x) + if (x < 1) + fun_l9_n659(x) + else + fun_l9_n766(x) + end +end + +def fun_l8_n919(x) + if (x < 1) + fun_l9_n523(x) + else + fun_l9_n54(x) + end +end + +def fun_l8_n920(x) + if (x < 1) + fun_l9_n298(x) + else + fun_l9_n169(x) + end +end + +def fun_l8_n921(x) + if (x < 1) + fun_l9_n752(x) + else + fun_l9_n281(x) + end +end + +def fun_l8_n922(x) + if (x < 1) + fun_l9_n703(x) + else + fun_l9_n874(x) + end +end + +def fun_l8_n923(x) + if (x < 1) + fun_l9_n218(x) + else + fun_l9_n880(x) + end +end + +def fun_l8_n924(x) + if (x < 1) + fun_l9_n699(x) + else + fun_l9_n357(x) + end +end + +def fun_l8_n925(x) + if (x < 1) + fun_l9_n279(x) + else + fun_l9_n300(x) + end +end + +def fun_l8_n926(x) + if (x < 1) + fun_l9_n955(x) + else + fun_l9_n522(x) + end +end + +def fun_l8_n927(x) + if (x < 1) + fun_l9_n943(x) + else + fun_l9_n597(x) + end +end + +def fun_l8_n928(x) + if (x < 1) + fun_l9_n828(x) + else + fun_l9_n658(x) + end +end + +def fun_l8_n929(x) + if (x < 1) + fun_l9_n160(x) + else + fun_l9_n536(x) + end +end + +def fun_l8_n930(x) + if (x < 1) + fun_l9_n422(x) + else + fun_l9_n848(x) + end +end + +def fun_l8_n931(x) + if (x < 1) + fun_l9_n66(x) + else + fun_l9_n298(x) + end +end + +def fun_l8_n932(x) + if (x < 1) + fun_l9_n871(x) + else + fun_l9_n443(x) + end +end + +def fun_l8_n933(x) + if (x < 1) + fun_l9_n876(x) + else + fun_l9_n459(x) + end +end + +def fun_l8_n934(x) + if (x < 1) + fun_l9_n319(x) + else + fun_l9_n921(x) + end +end + +def fun_l8_n935(x) + if (x < 1) + fun_l9_n741(x) + else + fun_l9_n659(x) + end +end + +def fun_l8_n936(x) + if (x < 1) + fun_l9_n713(x) + else + fun_l9_n800(x) + end +end + +def fun_l8_n937(x) + if (x < 1) + fun_l9_n945(x) + else + fun_l9_n548(x) + end +end + +def fun_l8_n938(x) + if (x < 1) + fun_l9_n732(x) + else + fun_l9_n10(x) + end +end + +def fun_l8_n939(x) + if (x < 1) + fun_l9_n5(x) + else + fun_l9_n864(x) + end +end + +def fun_l8_n940(x) + if (x < 1) + fun_l9_n353(x) + else + fun_l9_n46(x) + end +end + +def fun_l8_n941(x) + if (x < 1) + fun_l9_n622(x) + else + fun_l9_n430(x) + end +end + +def fun_l8_n942(x) + if (x < 1) + fun_l9_n120(x) + else + fun_l9_n265(x) + end +end + +def fun_l8_n943(x) + if (x < 1) + fun_l9_n272(x) + else + fun_l9_n290(x) + end +end + +def fun_l8_n944(x) + if (x < 1) + fun_l9_n527(x) + else + fun_l9_n830(x) + end +end + +def fun_l8_n945(x) + if (x < 1) + fun_l9_n202(x) + else + fun_l9_n597(x) + end +end + +def fun_l8_n946(x) + if (x < 1) + fun_l9_n797(x) + else + fun_l9_n984(x) + end +end + +def fun_l8_n947(x) + if (x < 1) + fun_l9_n3(x) + else + fun_l9_n173(x) + end +end + +def fun_l8_n948(x) + if (x < 1) + fun_l9_n658(x) + else + fun_l9_n48(x) + end +end + +def fun_l8_n949(x) + if (x < 1) + fun_l9_n302(x) + else + fun_l9_n549(x) + end +end + +def fun_l8_n950(x) + if (x < 1) + fun_l9_n450(x) + else + fun_l9_n442(x) + end +end + +def fun_l8_n951(x) + if (x < 1) + fun_l9_n32(x) + else + fun_l9_n287(x) + end +end + +def fun_l8_n952(x) + if (x < 1) + fun_l9_n427(x) + else + fun_l9_n67(x) + end +end + +def fun_l8_n953(x) + if (x < 1) + fun_l9_n153(x) + else + fun_l9_n748(x) + end +end + +def fun_l8_n954(x) + if (x < 1) + fun_l9_n528(x) + else + fun_l9_n754(x) + end +end + +def fun_l8_n955(x) + if (x < 1) + fun_l9_n722(x) + else + fun_l9_n982(x) + end +end + +def fun_l8_n956(x) + if (x < 1) + fun_l9_n857(x) + else + fun_l9_n286(x) + end +end + +def fun_l8_n957(x) + if (x < 1) + fun_l9_n579(x) + else + fun_l9_n830(x) + end +end + +def fun_l8_n958(x) + if (x < 1) + fun_l9_n913(x) + else + fun_l9_n918(x) + end +end + +def fun_l8_n959(x) + if (x < 1) + fun_l9_n575(x) + else + fun_l9_n441(x) + end +end + +def fun_l8_n960(x) + if (x < 1) + fun_l9_n774(x) + else + fun_l9_n426(x) + end +end + +def fun_l8_n961(x) + if (x < 1) + fun_l9_n415(x) + else + fun_l9_n720(x) + end +end + +def fun_l8_n962(x) + if (x < 1) + fun_l9_n187(x) + else + fun_l9_n101(x) + end +end + +def fun_l8_n963(x) + if (x < 1) + fun_l9_n146(x) + else + fun_l9_n911(x) + end +end + +def fun_l8_n964(x) + if (x < 1) + fun_l9_n758(x) + else + fun_l9_n46(x) + end +end + +def fun_l8_n965(x) + if (x < 1) + fun_l9_n316(x) + else + fun_l9_n874(x) + end +end + +def fun_l8_n966(x) + if (x < 1) + fun_l9_n604(x) + else + fun_l9_n933(x) + end +end + +def fun_l8_n967(x) + if (x < 1) + fun_l9_n185(x) + else + fun_l9_n729(x) + end +end + +def fun_l8_n968(x) + if (x < 1) + fun_l9_n735(x) + else + fun_l9_n347(x) + end +end + +def fun_l8_n969(x) + if (x < 1) + fun_l9_n796(x) + else + fun_l9_n163(x) + end +end + +def fun_l8_n970(x) + if (x < 1) + fun_l9_n535(x) + else + fun_l9_n184(x) + end +end + +def fun_l8_n971(x) + if (x < 1) + fun_l9_n919(x) + else + fun_l9_n838(x) + end +end + +def fun_l8_n972(x) + if (x < 1) + fun_l9_n296(x) + else + fun_l9_n822(x) + end +end + +def fun_l8_n973(x) + if (x < 1) + fun_l9_n503(x) + else + fun_l9_n979(x) + end +end + +def fun_l8_n974(x) + if (x < 1) + fun_l9_n598(x) + else + fun_l9_n916(x) + end +end + +def fun_l8_n975(x) + if (x < 1) + fun_l9_n119(x) + else + fun_l9_n138(x) + end +end + +def fun_l8_n976(x) + if (x < 1) + fun_l9_n92(x) + else + fun_l9_n244(x) + end +end + +def fun_l8_n977(x) + if (x < 1) + fun_l9_n250(x) + else + fun_l9_n496(x) + end +end + +def fun_l8_n978(x) + if (x < 1) + fun_l9_n665(x) + else + fun_l9_n617(x) + end +end + +def fun_l8_n979(x) + if (x < 1) + fun_l9_n212(x) + else + fun_l9_n63(x) + end +end + +def fun_l8_n980(x) + if (x < 1) + fun_l9_n304(x) + else + fun_l9_n373(x) + end +end + +def fun_l8_n981(x) + if (x < 1) + fun_l9_n70(x) + else + fun_l9_n194(x) + end +end + +def fun_l8_n982(x) + if (x < 1) + fun_l9_n996(x) + else + fun_l9_n821(x) + end +end + +def fun_l8_n983(x) + if (x < 1) + fun_l9_n109(x) + else + fun_l9_n926(x) + end +end + +def fun_l8_n984(x) + if (x < 1) + fun_l9_n342(x) + else + fun_l9_n768(x) + end +end + +def fun_l8_n985(x) + if (x < 1) + fun_l9_n12(x) + else + fun_l9_n55(x) + end +end + +def fun_l8_n986(x) + if (x < 1) + fun_l9_n663(x) + else + fun_l9_n963(x) + end +end + +def fun_l8_n987(x) + if (x < 1) + fun_l9_n108(x) + else + fun_l9_n139(x) + end +end + +def fun_l8_n988(x) + if (x < 1) + fun_l9_n256(x) + else + fun_l9_n55(x) + end +end + +def fun_l8_n989(x) + if (x < 1) + fun_l9_n261(x) + else + fun_l9_n962(x) + end +end + +def fun_l8_n990(x) + if (x < 1) + fun_l9_n581(x) + else + fun_l9_n558(x) + end +end + +def fun_l8_n991(x) + if (x < 1) + fun_l9_n379(x) + else + fun_l9_n179(x) + end +end + +def fun_l8_n992(x) + if (x < 1) + fun_l9_n256(x) + else + fun_l9_n158(x) + end +end + +def fun_l8_n993(x) + if (x < 1) + fun_l9_n75(x) + else + fun_l9_n669(x) + end +end + +def fun_l8_n994(x) + if (x < 1) + fun_l9_n1(x) + else + fun_l9_n723(x) + end +end + +def fun_l8_n995(x) + if (x < 1) + fun_l9_n52(x) + else + fun_l9_n706(x) + end +end + +def fun_l8_n996(x) + if (x < 1) + fun_l9_n583(x) + else + fun_l9_n769(x) + end +end + +def fun_l8_n997(x) + if (x < 1) + fun_l9_n91(x) + else + fun_l9_n86(x) + end +end + +def fun_l8_n998(x) + if (x < 1) + fun_l9_n605(x) + else + fun_l9_n106(x) + end +end + +def fun_l8_n999(x) + if (x < 1) + fun_l9_n634(x) + else + fun_l9_n110(x) + end +end + +def fun_l9_n0(x) + if (x < 1) + fun_l10_n583(x) + else + fun_l10_n168(x) + end +end + +def fun_l9_n1(x) + if (x < 1) + fun_l10_n523(x) + else + fun_l10_n486(x) + end +end + +def fun_l9_n2(x) + if (x < 1) + fun_l10_n869(x) + else + fun_l10_n480(x) + end +end + +def fun_l9_n3(x) + if (x < 1) + fun_l10_n227(x) + else + fun_l10_n798(x) + end +end + +def fun_l9_n4(x) + if (x < 1) + fun_l10_n8(x) + else + fun_l10_n984(x) + end +end + +def fun_l9_n5(x) + if (x < 1) + fun_l10_n757(x) + else + fun_l10_n791(x) + end +end + +def fun_l9_n6(x) + if (x < 1) + fun_l10_n131(x) + else + fun_l10_n44(x) + end +end + +def fun_l9_n7(x) + if (x < 1) + fun_l10_n292(x) + else + fun_l10_n793(x) + end +end + +def fun_l9_n8(x) + if (x < 1) + fun_l10_n237(x) + else + fun_l10_n439(x) + end +end + +def fun_l9_n9(x) + if (x < 1) + fun_l10_n99(x) + else + fun_l10_n914(x) + end +end + +def fun_l9_n10(x) + if (x < 1) + fun_l10_n702(x) + else + fun_l10_n983(x) + end +end + +def fun_l9_n11(x) + if (x < 1) + fun_l10_n843(x) + else + fun_l10_n774(x) + end +end + +def fun_l9_n12(x) + if (x < 1) + fun_l10_n720(x) + else + fun_l10_n238(x) + end +end + +def fun_l9_n13(x) + if (x < 1) + fun_l10_n339(x) + else + fun_l10_n613(x) + end +end + +def fun_l9_n14(x) + if (x < 1) + fun_l10_n711(x) + else + fun_l10_n836(x) + end +end + +def fun_l9_n15(x) + if (x < 1) + fun_l10_n542(x) + else + fun_l10_n90(x) + end +end + +def fun_l9_n16(x) + if (x < 1) + fun_l10_n931(x) + else + fun_l10_n1(x) + end +end + +def fun_l9_n17(x) + if (x < 1) + fun_l10_n568(x) + else + fun_l10_n397(x) + end +end + +def fun_l9_n18(x) + if (x < 1) + fun_l10_n108(x) + else + fun_l10_n245(x) + end +end + +def fun_l9_n19(x) + if (x < 1) + fun_l10_n413(x) + else + fun_l10_n644(x) + end +end + +def fun_l9_n20(x) + if (x < 1) + fun_l10_n533(x) + else + fun_l10_n345(x) + end +end + +def fun_l9_n21(x) + if (x < 1) + fun_l10_n84(x) + else + fun_l10_n821(x) + end +end + +def fun_l9_n22(x) + if (x < 1) + fun_l10_n391(x) + else + fun_l10_n154(x) + end +end + +def fun_l9_n23(x) + if (x < 1) + fun_l10_n591(x) + else + fun_l10_n443(x) + end +end + +def fun_l9_n24(x) + if (x < 1) + fun_l10_n105(x) + else + fun_l10_n652(x) + end +end + +def fun_l9_n25(x) + if (x < 1) + fun_l10_n495(x) + else + fun_l10_n185(x) + end +end + +def fun_l9_n26(x) + if (x < 1) + fun_l10_n160(x) + else + fun_l10_n77(x) + end +end + +def fun_l9_n27(x) + if (x < 1) + fun_l10_n307(x) + else + fun_l10_n813(x) + end +end + +def fun_l9_n28(x) + if (x < 1) + fun_l10_n651(x) + else + fun_l10_n198(x) + end +end + +def fun_l9_n29(x) + if (x < 1) + fun_l10_n689(x) + else + fun_l10_n995(x) + end +end + +def fun_l9_n30(x) + if (x < 1) + fun_l10_n52(x) + else + fun_l10_n846(x) + end +end + +def fun_l9_n31(x) + if (x < 1) + fun_l10_n151(x) + else + fun_l10_n758(x) + end +end + +def fun_l9_n32(x) + if (x < 1) + fun_l10_n675(x) + else + fun_l10_n240(x) + end +end + +def fun_l9_n33(x) + if (x < 1) + fun_l10_n660(x) + else + fun_l10_n826(x) + end +end + +def fun_l9_n34(x) + if (x < 1) + fun_l10_n858(x) + else + fun_l10_n120(x) + end +end + +def fun_l9_n35(x) + if (x < 1) + fun_l10_n28(x) + else + fun_l10_n870(x) + end +end + +def fun_l9_n36(x) + if (x < 1) + fun_l10_n275(x) + else + fun_l10_n376(x) + end +end + +def fun_l9_n37(x) + if (x < 1) + fun_l10_n852(x) + else + fun_l10_n413(x) + end +end + +def fun_l9_n38(x) + if (x < 1) + fun_l10_n608(x) + else + fun_l10_n740(x) + end +end + +def fun_l9_n39(x) + if (x < 1) + fun_l10_n856(x) + else + fun_l10_n543(x) + end +end + +def fun_l9_n40(x) + if (x < 1) + fun_l10_n979(x) + else + fun_l10_n37(x) + end +end + +def fun_l9_n41(x) + if (x < 1) + fun_l10_n752(x) + else + fun_l10_n94(x) + end +end + +def fun_l9_n42(x) + if (x < 1) + fun_l10_n653(x) + else + fun_l10_n64(x) + end +end + +def fun_l9_n43(x) + if (x < 1) + fun_l10_n860(x) + else + fun_l10_n658(x) + end +end + +def fun_l9_n44(x) + if (x < 1) + fun_l10_n952(x) + else + fun_l10_n413(x) + end +end + +def fun_l9_n45(x) + if (x < 1) + fun_l10_n70(x) + else + fun_l10_n297(x) + end +end + +def fun_l9_n46(x) + if (x < 1) + fun_l10_n100(x) + else + fun_l10_n154(x) + end +end + +def fun_l9_n47(x) + if (x < 1) + fun_l10_n746(x) + else + fun_l10_n937(x) + end +end + +def fun_l9_n48(x) + if (x < 1) + fun_l10_n341(x) + else + fun_l10_n200(x) + end +end + +def fun_l9_n49(x) + if (x < 1) + fun_l10_n317(x) + else + fun_l10_n607(x) + end +end + +def fun_l9_n50(x) + if (x < 1) + fun_l10_n194(x) + else + fun_l10_n499(x) + end +end + +def fun_l9_n51(x) + if (x < 1) + fun_l10_n936(x) + else + fun_l10_n387(x) + end +end + +def fun_l9_n52(x) + if (x < 1) + fun_l10_n660(x) + else + fun_l10_n734(x) + end +end + +def fun_l9_n53(x) + if (x < 1) + fun_l10_n523(x) + else + fun_l10_n532(x) + end +end + +def fun_l9_n54(x) + if (x < 1) + fun_l10_n847(x) + else + fun_l10_n586(x) + end +end + +def fun_l9_n55(x) + if (x < 1) + fun_l10_n378(x) + else + fun_l10_n226(x) + end +end + +def fun_l9_n56(x) + if (x < 1) + fun_l10_n55(x) + else + fun_l10_n823(x) + end +end + +def fun_l9_n57(x) + if (x < 1) + fun_l10_n931(x) + else + fun_l10_n268(x) + end +end + +def fun_l9_n58(x) + if (x < 1) + fun_l10_n603(x) + else + fun_l10_n746(x) + end +end + +def fun_l9_n59(x) + if (x < 1) + fun_l10_n174(x) + else + fun_l10_n196(x) + end +end + +def fun_l9_n60(x) + if (x < 1) + fun_l10_n45(x) + else + fun_l10_n907(x) + end +end + +def fun_l9_n61(x) + if (x < 1) + fun_l10_n282(x) + else + fun_l10_n478(x) + end +end + +def fun_l9_n62(x) + if (x < 1) + fun_l10_n558(x) + else + fun_l10_n354(x) + end +end + +def fun_l9_n63(x) + if (x < 1) + fun_l10_n729(x) + else + fun_l10_n275(x) + end +end + +def fun_l9_n64(x) + if (x < 1) + fun_l10_n804(x) + else + fun_l10_n873(x) + end +end + +def fun_l9_n65(x) + if (x < 1) + fun_l10_n901(x) + else + fun_l10_n684(x) + end +end + +def fun_l9_n66(x) + if (x < 1) + fun_l10_n542(x) + else + fun_l10_n668(x) + end +end + +def fun_l9_n67(x) + if (x < 1) + fun_l10_n112(x) + else + fun_l10_n48(x) + end +end + +def fun_l9_n68(x) + if (x < 1) + fun_l10_n78(x) + else + fun_l10_n50(x) + end +end + +def fun_l9_n69(x) + if (x < 1) + fun_l10_n595(x) + else + fun_l10_n163(x) + end +end + +def fun_l9_n70(x) + if (x < 1) + fun_l10_n839(x) + else + fun_l10_n811(x) + end +end + +def fun_l9_n71(x) + if (x < 1) + fun_l10_n704(x) + else + fun_l10_n81(x) + end +end + +def fun_l9_n72(x) + if (x < 1) + fun_l10_n708(x) + else + fun_l10_n711(x) + end +end + +def fun_l9_n73(x) + if (x < 1) + fun_l10_n948(x) + else + fun_l10_n397(x) + end +end + +def fun_l9_n74(x) + if (x < 1) + fun_l10_n168(x) + else + fun_l10_n415(x) + end +end + +def fun_l9_n75(x) + if (x < 1) + fun_l10_n191(x) + else + fun_l10_n547(x) + end +end + +def fun_l9_n76(x) + if (x < 1) + fun_l10_n163(x) + else + fun_l10_n246(x) + end +end + +def fun_l9_n77(x) + if (x < 1) + fun_l10_n948(x) + else + fun_l10_n80(x) + end +end + +def fun_l9_n78(x) + if (x < 1) + fun_l10_n178(x) + else + fun_l10_n698(x) + end +end + +def fun_l9_n79(x) + if (x < 1) + fun_l10_n150(x) + else + fun_l10_n545(x) + end +end + +def fun_l9_n80(x) + if (x < 1) + fun_l10_n808(x) + else + fun_l10_n668(x) + end +end + +def fun_l9_n81(x) + if (x < 1) + fun_l10_n597(x) + else + fun_l10_n908(x) + end +end + +def fun_l9_n82(x) + if (x < 1) + fun_l10_n868(x) + else + fun_l10_n831(x) + end +end + +def fun_l9_n83(x) + if (x < 1) + fun_l10_n432(x) + else + fun_l10_n281(x) + end +end + +def fun_l9_n84(x) + if (x < 1) + fun_l10_n906(x) + else + fun_l10_n838(x) + end +end + +def fun_l9_n85(x) + if (x < 1) + fun_l10_n828(x) + else + fun_l10_n876(x) + end +end + +def fun_l9_n86(x) + if (x < 1) + fun_l10_n537(x) + else + fun_l10_n283(x) + end +end + +def fun_l9_n87(x) + if (x < 1) + fun_l10_n108(x) + else + fun_l10_n157(x) + end +end + +def fun_l9_n88(x) + if (x < 1) + fun_l10_n576(x) + else + fun_l10_n448(x) + end +end + +def fun_l9_n89(x) + if (x < 1) + fun_l10_n633(x) + else + fun_l10_n43(x) + end +end + +def fun_l9_n90(x) + if (x < 1) + fun_l10_n114(x) + else + fun_l10_n44(x) + end +end + +def fun_l9_n91(x) + if (x < 1) + fun_l10_n656(x) + else + fun_l10_n586(x) + end +end + +def fun_l9_n92(x) + if (x < 1) + fun_l10_n366(x) + else + fun_l10_n613(x) + end +end + +def fun_l9_n93(x) + if (x < 1) + fun_l10_n174(x) + else + fun_l10_n250(x) + end +end + +def fun_l9_n94(x) + if (x < 1) + fun_l10_n911(x) + else + fun_l10_n877(x) + end +end + +def fun_l9_n95(x) + if (x < 1) + fun_l10_n940(x) + else + fun_l10_n334(x) + end +end + +def fun_l9_n96(x) + if (x < 1) + fun_l10_n473(x) + else + fun_l10_n914(x) + end +end + +def fun_l9_n97(x) + if (x < 1) + fun_l10_n550(x) + else + fun_l10_n80(x) + end +end + +def fun_l9_n98(x) + if (x < 1) + fun_l10_n46(x) + else + fun_l10_n716(x) + end +end + +def fun_l9_n99(x) + if (x < 1) + fun_l10_n294(x) + else + fun_l10_n615(x) + end +end + +def fun_l9_n100(x) + if (x < 1) + fun_l10_n286(x) + else + fun_l10_n120(x) + end +end + +def fun_l9_n101(x) + if (x < 1) + fun_l10_n674(x) + else + fun_l10_n498(x) + end +end + +def fun_l9_n102(x) + if (x < 1) + fun_l10_n700(x) + else + fun_l10_n35(x) + end +end + +def fun_l9_n103(x) + if (x < 1) + fun_l10_n225(x) + else + fun_l10_n206(x) + end +end + +def fun_l9_n104(x) + if (x < 1) + fun_l10_n594(x) + else + fun_l10_n679(x) + end +end + +def fun_l9_n105(x) + if (x < 1) + fun_l10_n148(x) + else + fun_l10_n449(x) + end +end + +def fun_l9_n106(x) + if (x < 1) + fun_l10_n125(x) + else + fun_l10_n761(x) + end +end + +def fun_l9_n107(x) + if (x < 1) + fun_l10_n642(x) + else + fun_l10_n988(x) + end +end + +def fun_l9_n108(x) + if (x < 1) + fun_l10_n952(x) + else + fun_l10_n436(x) + end +end + +def fun_l9_n109(x) + if (x < 1) + fun_l10_n955(x) + else + fun_l10_n380(x) + end +end + +def fun_l9_n110(x) + if (x < 1) + fun_l10_n813(x) + else + fun_l10_n837(x) + end +end + +def fun_l9_n111(x) + if (x < 1) + fun_l10_n471(x) + else + fun_l10_n69(x) + end +end + +def fun_l9_n112(x) + if (x < 1) + fun_l10_n614(x) + else + fun_l10_n665(x) + end +end + +def fun_l9_n113(x) + if (x < 1) + fun_l10_n485(x) + else + fun_l10_n276(x) + end +end + +def fun_l9_n114(x) + if (x < 1) + fun_l10_n171(x) + else + fun_l10_n457(x) + end +end + +def fun_l9_n115(x) + if (x < 1) + fun_l10_n106(x) + else + fun_l10_n555(x) + end +end + +def fun_l9_n116(x) + if (x < 1) + fun_l10_n231(x) + else + fun_l10_n163(x) + end +end + +def fun_l9_n117(x) + if (x < 1) + fun_l10_n569(x) + else + fun_l10_n345(x) + end +end + +def fun_l9_n118(x) + if (x < 1) + fun_l10_n946(x) + else + fun_l10_n174(x) + end +end + +def fun_l9_n119(x) + if (x < 1) + fun_l10_n716(x) + else + fun_l10_n882(x) + end +end + +def fun_l9_n120(x) + if (x < 1) + fun_l10_n628(x) + else + fun_l10_n838(x) + end +end + +def fun_l9_n121(x) + if (x < 1) + fun_l10_n699(x) + else + fun_l10_n384(x) + end +end + +def fun_l9_n122(x) + if (x < 1) + fun_l10_n180(x) + else + fun_l10_n98(x) + end +end + +def fun_l9_n123(x) + if (x < 1) + fun_l10_n177(x) + else + fun_l10_n635(x) + end +end + +def fun_l9_n124(x) + if (x < 1) + fun_l10_n398(x) + else + fun_l10_n121(x) + end +end + +def fun_l9_n125(x) + if (x < 1) + fun_l10_n866(x) + else + fun_l10_n595(x) + end +end + +def fun_l9_n126(x) + if (x < 1) + fun_l10_n9(x) + else + fun_l10_n901(x) + end +end + +def fun_l9_n127(x) + if (x < 1) + fun_l10_n579(x) + else + fun_l10_n640(x) + end +end + +def fun_l9_n128(x) + if (x < 1) + fun_l10_n884(x) + else + fun_l10_n327(x) + end +end + +def fun_l9_n129(x) + if (x < 1) + fun_l10_n553(x) + else + fun_l10_n73(x) + end +end + +def fun_l9_n130(x) + if (x < 1) + fun_l10_n372(x) + else + fun_l10_n450(x) + end +end + +def fun_l9_n131(x) + if (x < 1) + fun_l10_n748(x) + else + fun_l10_n534(x) + end +end + +def fun_l9_n132(x) + if (x < 1) + fun_l10_n529(x) + else + fun_l10_n689(x) + end +end + +def fun_l9_n133(x) + if (x < 1) + fun_l10_n24(x) + else + fun_l10_n677(x) + end +end + +def fun_l9_n134(x) + if (x < 1) + fun_l10_n4(x) + else + fun_l10_n482(x) + end +end + +def fun_l9_n135(x) + if (x < 1) + fun_l10_n314(x) + else + fun_l10_n509(x) + end +end + +def fun_l9_n136(x) + if (x < 1) + fun_l10_n160(x) + else + fun_l10_n342(x) + end +end + +def fun_l9_n137(x) + if (x < 1) + fun_l10_n289(x) + else + fun_l10_n910(x) + end +end + +def fun_l9_n138(x) + if (x < 1) + fun_l10_n926(x) + else + fun_l10_n752(x) + end +end + +def fun_l9_n139(x) + if (x < 1) + fun_l10_n303(x) + else + fun_l10_n399(x) + end +end + +def fun_l9_n140(x) + if (x < 1) + fun_l10_n11(x) + else + fun_l10_n241(x) + end +end + +def fun_l9_n141(x) + if (x < 1) + fun_l10_n528(x) + else + fun_l10_n727(x) + end +end + +def fun_l9_n142(x) + if (x < 1) + fun_l10_n572(x) + else + fun_l10_n132(x) + end +end + +def fun_l9_n143(x) + if (x < 1) + fun_l10_n858(x) + else + fun_l10_n712(x) + end +end + +def fun_l9_n144(x) + if (x < 1) + fun_l10_n662(x) + else + fun_l10_n128(x) + end +end + +def fun_l9_n145(x) + if (x < 1) + fun_l10_n668(x) + else + fun_l10_n483(x) + end +end + +def fun_l9_n146(x) + if (x < 1) + fun_l10_n401(x) + else + fun_l10_n330(x) + end +end + +def fun_l9_n147(x) + if (x < 1) + fun_l10_n103(x) + else + fun_l10_n859(x) + end +end + +def fun_l9_n148(x) + if (x < 1) + fun_l10_n129(x) + else + fun_l10_n628(x) + end +end + +def fun_l9_n149(x) + if (x < 1) + fun_l10_n898(x) + else + fun_l10_n984(x) + end +end + +def fun_l9_n150(x) + if (x < 1) + fun_l10_n574(x) + else + fun_l10_n59(x) + end +end + +def fun_l9_n151(x) + if (x < 1) + fun_l10_n759(x) + else + fun_l10_n782(x) + end +end + +def fun_l9_n152(x) + if (x < 1) + fun_l10_n588(x) + else + fun_l10_n383(x) + end +end + +def fun_l9_n153(x) + if (x < 1) + fun_l10_n889(x) + else + fun_l10_n628(x) + end +end + +def fun_l9_n154(x) + if (x < 1) + fun_l10_n376(x) + else + fun_l10_n442(x) + end +end + +def fun_l9_n155(x) + if (x < 1) + fun_l10_n497(x) + else + fun_l10_n269(x) + end +end + +def fun_l9_n156(x) + if (x < 1) + fun_l10_n976(x) + else + fun_l10_n829(x) + end +end + +def fun_l9_n157(x) + if (x < 1) + fun_l10_n366(x) + else + fun_l10_n416(x) + end +end + +def fun_l9_n158(x) + if (x < 1) + fun_l10_n712(x) + else + fun_l10_n19(x) + end +end + +def fun_l9_n159(x) + if (x < 1) + fun_l10_n151(x) + else + fun_l10_n129(x) + end +end + +def fun_l9_n160(x) + if (x < 1) + fun_l10_n621(x) + else + fun_l10_n385(x) + end +end + +def fun_l9_n161(x) + if (x < 1) + fun_l10_n626(x) + else + fun_l10_n686(x) + end +end + +def fun_l9_n162(x) + if (x < 1) + fun_l10_n165(x) + else + fun_l10_n922(x) + end +end + +def fun_l9_n163(x) + if (x < 1) + fun_l10_n670(x) + else + fun_l10_n889(x) + end +end + +def fun_l9_n164(x) + if (x < 1) + fun_l10_n346(x) + else + fun_l10_n292(x) + end +end + +def fun_l9_n165(x) + if (x < 1) + fun_l10_n812(x) + else + fun_l10_n799(x) + end +end + +def fun_l9_n166(x) + if (x < 1) + fun_l10_n21(x) + else + fun_l10_n641(x) + end +end + +def fun_l9_n167(x) + if (x < 1) + fun_l10_n268(x) + else + fun_l10_n943(x) + end +end + +def fun_l9_n168(x) + if (x < 1) + fun_l10_n349(x) + else + fun_l10_n620(x) + end +end + +def fun_l9_n169(x) + if (x < 1) + fun_l10_n894(x) + else + fun_l10_n625(x) + end +end + +def fun_l9_n170(x) + if (x < 1) + fun_l10_n732(x) + else + fun_l10_n518(x) + end +end + +def fun_l9_n171(x) + if (x < 1) + fun_l10_n272(x) + else + fun_l10_n148(x) + end +end + +def fun_l9_n172(x) + if (x < 1) + fun_l10_n701(x) + else + fun_l10_n227(x) + end +end + +def fun_l9_n173(x) + if (x < 1) + fun_l10_n833(x) + else + fun_l10_n853(x) + end +end + +def fun_l9_n174(x) + if (x < 1) + fun_l10_n643(x) + else + fun_l10_n314(x) + end +end + +def fun_l9_n175(x) + if (x < 1) + fun_l10_n217(x) + else + fun_l10_n64(x) + end +end + +def fun_l9_n176(x) + if (x < 1) + fun_l10_n204(x) + else + fun_l10_n990(x) + end +end + +def fun_l9_n177(x) + if (x < 1) + fun_l10_n130(x) + else + fun_l10_n829(x) + end +end + +def fun_l9_n178(x) + if (x < 1) + fun_l10_n260(x) + else + fun_l10_n881(x) + end +end + +def fun_l9_n179(x) + if (x < 1) + fun_l10_n728(x) + else + fun_l10_n491(x) + end +end + +def fun_l9_n180(x) + if (x < 1) + fun_l10_n456(x) + else + fun_l10_n221(x) + end +end + +def fun_l9_n181(x) + if (x < 1) + fun_l10_n634(x) + else + fun_l10_n166(x) + end +end + +def fun_l9_n182(x) + if (x < 1) + fun_l10_n427(x) + else + fun_l10_n452(x) + end +end + +def fun_l9_n183(x) + if (x < 1) + fun_l10_n754(x) + else + fun_l10_n54(x) + end +end + +def fun_l9_n184(x) + if (x < 1) + fun_l10_n137(x) + else + fun_l10_n155(x) + end +end + +def fun_l9_n185(x) + if (x < 1) + fun_l10_n611(x) + else + fun_l10_n573(x) + end +end + +def fun_l9_n186(x) + if (x < 1) + fun_l10_n694(x) + else + fun_l10_n890(x) + end +end + +def fun_l9_n187(x) + if (x < 1) + fun_l10_n533(x) + else + fun_l10_n102(x) + end +end + +def fun_l9_n188(x) + if (x < 1) + fun_l10_n400(x) + else + fun_l10_n838(x) + end +end + +def fun_l9_n189(x) + if (x < 1) + fun_l10_n783(x) + else + fun_l10_n620(x) + end +end + +def fun_l9_n190(x) + if (x < 1) + fun_l10_n209(x) + else + fun_l10_n777(x) + end +end + +def fun_l9_n191(x) + if (x < 1) + fun_l10_n760(x) + else + fun_l10_n299(x) + end +end + +def fun_l9_n192(x) + if (x < 1) + fun_l10_n306(x) + else + fun_l10_n509(x) + end +end + +def fun_l9_n193(x) + if (x < 1) + fun_l10_n842(x) + else + fun_l10_n0(x) + end +end + +def fun_l9_n194(x) + if (x < 1) + fun_l10_n620(x) + else + fun_l10_n757(x) + end +end + +def fun_l9_n195(x) + if (x < 1) + fun_l10_n944(x) + else + fun_l10_n257(x) + end +end + +def fun_l9_n196(x) + if (x < 1) + fun_l10_n222(x) + else + fun_l10_n11(x) + end +end + +def fun_l9_n197(x) + if (x < 1) + fun_l10_n419(x) + else + fun_l10_n704(x) + end +end + +def fun_l9_n198(x) + if (x < 1) + fun_l10_n656(x) + else + fun_l10_n341(x) + end +end + +def fun_l9_n199(x) + if (x < 1) + fun_l10_n129(x) + else + fun_l10_n815(x) + end +end + +def fun_l9_n200(x) + if (x < 1) + fun_l10_n768(x) + else + fun_l10_n924(x) + end +end + +def fun_l9_n201(x) + if (x < 1) + fun_l10_n439(x) + else + fun_l10_n361(x) + end +end + +def fun_l9_n202(x) + if (x < 1) + fun_l10_n421(x) + else + fun_l10_n937(x) + end +end + +def fun_l9_n203(x) + if (x < 1) + fun_l10_n323(x) + else + fun_l10_n262(x) + end +end + +def fun_l9_n204(x) + if (x < 1) + fun_l10_n335(x) + else + fun_l10_n87(x) + end +end + +def fun_l9_n205(x) + if (x < 1) + fun_l10_n973(x) + else + fun_l10_n262(x) + end +end + +def fun_l9_n206(x) + if (x < 1) + fun_l10_n494(x) + else + fun_l10_n430(x) + end +end + +def fun_l9_n207(x) + if (x < 1) + fun_l10_n482(x) + else + fun_l10_n828(x) + end +end + +def fun_l9_n208(x) + if (x < 1) + fun_l10_n820(x) + else + fun_l10_n646(x) + end +end + +def fun_l9_n209(x) + if (x < 1) + fun_l10_n669(x) + else + fun_l10_n176(x) + end +end + +def fun_l9_n210(x) + if (x < 1) + fun_l10_n165(x) + else + fun_l10_n963(x) + end +end + +def fun_l9_n211(x) + if (x < 1) + fun_l10_n772(x) + else + fun_l10_n49(x) + end +end + +def fun_l9_n212(x) + if (x < 1) + fun_l10_n167(x) + else + fun_l10_n598(x) + end +end + +def fun_l9_n213(x) + if (x < 1) + fun_l10_n552(x) + else + fun_l10_n374(x) + end +end + +def fun_l9_n214(x) + if (x < 1) + fun_l10_n39(x) + else + fun_l10_n470(x) + end +end + +def fun_l9_n215(x) + if (x < 1) + fun_l10_n489(x) + else + fun_l10_n812(x) + end +end + +def fun_l9_n216(x) + if (x < 1) + fun_l10_n390(x) + else + fun_l10_n928(x) + end +end + +def fun_l9_n217(x) + if (x < 1) + fun_l10_n909(x) + else + fun_l10_n876(x) + end +end + +def fun_l9_n218(x) + if (x < 1) + fun_l10_n781(x) + else + fun_l10_n799(x) + end +end + +def fun_l9_n219(x) + if (x < 1) + fun_l10_n958(x) + else + fun_l10_n697(x) + end +end + +def fun_l9_n220(x) + if (x < 1) + fun_l10_n577(x) + else + fun_l10_n667(x) + end +end + +def fun_l9_n221(x) + if (x < 1) + fun_l10_n206(x) + else + fun_l10_n573(x) + end +end + +def fun_l9_n222(x) + if (x < 1) + fun_l10_n389(x) + else + fun_l10_n659(x) + end +end + +def fun_l9_n223(x) + if (x < 1) + fun_l10_n951(x) + else + fun_l10_n572(x) + end +end + +def fun_l9_n224(x) + if (x < 1) + fun_l10_n158(x) + else + fun_l10_n500(x) + end +end + +def fun_l9_n225(x) + if (x < 1) + fun_l10_n681(x) + else + fun_l10_n983(x) + end +end + +def fun_l9_n226(x) + if (x < 1) + fun_l10_n987(x) + else + fun_l10_n116(x) + end +end + +def fun_l9_n227(x) + if (x < 1) + fun_l10_n347(x) + else + fun_l10_n606(x) + end +end + +def fun_l9_n228(x) + if (x < 1) + fun_l10_n566(x) + else + fun_l10_n77(x) + end +end + +def fun_l9_n229(x) + if (x < 1) + fun_l10_n879(x) + else + fun_l10_n66(x) + end +end + +def fun_l9_n230(x) + if (x < 1) + fun_l10_n355(x) + else + fun_l10_n97(x) + end +end + +def fun_l9_n231(x) + if (x < 1) + fun_l10_n938(x) + else + fun_l10_n5(x) + end +end + +def fun_l9_n232(x) + if (x < 1) + fun_l10_n684(x) + else + fun_l10_n528(x) + end +end + +def fun_l9_n233(x) + if (x < 1) + fun_l10_n500(x) + else + fun_l10_n246(x) + end +end + +def fun_l9_n234(x) + if (x < 1) + fun_l10_n610(x) + else + fun_l10_n61(x) + end +end + +def fun_l9_n235(x) + if (x < 1) + fun_l10_n199(x) + else + fun_l10_n838(x) + end +end + +def fun_l9_n236(x) + if (x < 1) + fun_l10_n820(x) + else + fun_l10_n633(x) + end +end + +def fun_l9_n237(x) + if (x < 1) + fun_l10_n216(x) + else + fun_l10_n546(x) + end +end + +def fun_l9_n238(x) + if (x < 1) + fun_l10_n555(x) + else + fun_l10_n153(x) + end +end + +def fun_l9_n239(x) + if (x < 1) + fun_l10_n236(x) + else + fun_l10_n231(x) + end +end + +def fun_l9_n240(x) + if (x < 1) + fun_l10_n775(x) + else + fun_l10_n823(x) + end +end + +def fun_l9_n241(x) + if (x < 1) + fun_l10_n275(x) + else + fun_l10_n519(x) + end +end + +def fun_l9_n242(x) + if (x < 1) + fun_l10_n239(x) + else + fun_l10_n791(x) + end +end + +def fun_l9_n243(x) + if (x < 1) + fun_l10_n639(x) + else + fun_l10_n972(x) + end +end + +def fun_l9_n244(x) + if (x < 1) + fun_l10_n5(x) + else + fun_l10_n510(x) + end +end + +def fun_l9_n245(x) + if (x < 1) + fun_l10_n256(x) + else + fun_l10_n298(x) + end +end + +def fun_l9_n246(x) + if (x < 1) + fun_l10_n139(x) + else + fun_l10_n385(x) + end +end + +def fun_l9_n247(x) + if (x < 1) + fun_l10_n4(x) + else + fun_l10_n323(x) + end +end + +def fun_l9_n248(x) + if (x < 1) + fun_l10_n166(x) + else + fun_l10_n539(x) + end +end + +def fun_l9_n249(x) + if (x < 1) + fun_l10_n374(x) + else + fun_l10_n351(x) + end +end + +def fun_l9_n250(x) + if (x < 1) + fun_l10_n650(x) + else + fun_l10_n791(x) + end +end + +def fun_l9_n251(x) + if (x < 1) + fun_l10_n799(x) + else + fun_l10_n990(x) + end +end + +def fun_l9_n252(x) + if (x < 1) + fun_l10_n388(x) + else + fun_l10_n887(x) + end +end + +def fun_l9_n253(x) + if (x < 1) + fun_l10_n564(x) + else + fun_l10_n997(x) + end +end + +def fun_l9_n254(x) + if (x < 1) + fun_l10_n580(x) + else + fun_l10_n646(x) + end +end + +def fun_l9_n255(x) + if (x < 1) + fun_l10_n0(x) + else + fun_l10_n480(x) + end +end + +def fun_l9_n256(x) + if (x < 1) + fun_l10_n606(x) + else + fun_l10_n48(x) + end +end + +def fun_l9_n257(x) + if (x < 1) + fun_l10_n601(x) + else + fun_l10_n657(x) + end +end + +def fun_l9_n258(x) + if (x < 1) + fun_l10_n419(x) + else + fun_l10_n909(x) + end +end + +def fun_l9_n259(x) + if (x < 1) + fun_l10_n194(x) + else + fun_l10_n961(x) + end +end + +def fun_l9_n260(x) + if (x < 1) + fun_l10_n876(x) + else + fun_l10_n345(x) + end +end + +def fun_l9_n261(x) + if (x < 1) + fun_l10_n643(x) + else + fun_l10_n905(x) + end +end + +def fun_l9_n262(x) + if (x < 1) + fun_l10_n105(x) + else + fun_l10_n61(x) + end +end + +def fun_l9_n263(x) + if (x < 1) + fun_l10_n610(x) + else + fun_l10_n527(x) + end +end + +def fun_l9_n264(x) + if (x < 1) + fun_l10_n183(x) + else + fun_l10_n51(x) + end +end + +def fun_l9_n265(x) + if (x < 1) + fun_l10_n800(x) + else + fun_l10_n103(x) + end +end + +def fun_l9_n266(x) + if (x < 1) + fun_l10_n501(x) + else + fun_l10_n293(x) + end +end + +def fun_l9_n267(x) + if (x < 1) + fun_l10_n207(x) + else + fun_l10_n162(x) + end +end + +def fun_l9_n268(x) + if (x < 1) + fun_l10_n901(x) + else + fun_l10_n914(x) + end +end + +def fun_l9_n269(x) + if (x < 1) + fun_l10_n711(x) + else + fun_l10_n227(x) + end +end + +def fun_l9_n270(x) + if (x < 1) + fun_l10_n445(x) + else + fun_l10_n227(x) + end +end + +def fun_l9_n271(x) + if (x < 1) + fun_l10_n585(x) + else + fun_l10_n371(x) + end +end + +def fun_l9_n272(x) + if (x < 1) + fun_l10_n137(x) + else + fun_l10_n678(x) + end +end + +def fun_l9_n273(x) + if (x < 1) + fun_l10_n284(x) + else + fun_l10_n801(x) + end +end + +def fun_l9_n274(x) + if (x < 1) + fun_l10_n829(x) + else + fun_l10_n456(x) + end +end + +def fun_l9_n275(x) + if (x < 1) + fun_l10_n663(x) + else + fun_l10_n529(x) + end +end + +def fun_l9_n276(x) + if (x < 1) + fun_l10_n154(x) + else + fun_l10_n421(x) + end +end + +def fun_l9_n277(x) + if (x < 1) + fun_l10_n778(x) + else + fun_l10_n325(x) + end +end + +def fun_l9_n278(x) + if (x < 1) + fun_l10_n179(x) + else + fun_l10_n369(x) + end +end + +def fun_l9_n279(x) + if (x < 1) + fun_l10_n800(x) + else + fun_l10_n488(x) + end +end + +def fun_l9_n280(x) + if (x < 1) + fun_l10_n617(x) + else + fun_l10_n1(x) + end +end + +def fun_l9_n281(x) + if (x < 1) + fun_l10_n951(x) + else + fun_l10_n763(x) + end +end + +def fun_l9_n282(x) + if (x < 1) + fun_l10_n537(x) + else + fun_l10_n541(x) + end +end + +def fun_l9_n283(x) + if (x < 1) + fun_l10_n664(x) + else + fun_l10_n854(x) + end +end + +def fun_l9_n284(x) + if (x < 1) + fun_l10_n711(x) + else + fun_l10_n767(x) + end +end + +def fun_l9_n285(x) + if (x < 1) + fun_l10_n211(x) + else + fun_l10_n733(x) + end +end + +def fun_l9_n286(x) + if (x < 1) + fun_l10_n524(x) + else + fun_l10_n850(x) + end +end + +def fun_l9_n287(x) + if (x < 1) + fun_l10_n270(x) + else + fun_l10_n798(x) + end +end + +def fun_l9_n288(x) + if (x < 1) + fun_l10_n906(x) + else + fun_l10_n408(x) + end +end + +def fun_l9_n289(x) + if (x < 1) + fun_l10_n873(x) + else + fun_l10_n298(x) + end +end + +def fun_l9_n290(x) + if (x < 1) + fun_l10_n535(x) + else + fun_l10_n946(x) + end +end + +def fun_l9_n291(x) + if (x < 1) + fun_l10_n290(x) + else + fun_l10_n631(x) + end +end + +def fun_l9_n292(x) + if (x < 1) + fun_l10_n223(x) + else + fun_l10_n165(x) + end +end + +def fun_l9_n293(x) + if (x < 1) + fun_l10_n768(x) + else + fun_l10_n512(x) + end +end + +def fun_l9_n294(x) + if (x < 1) + fun_l10_n133(x) + else + fun_l10_n986(x) + end +end + +def fun_l9_n295(x) + if (x < 1) + fun_l10_n657(x) + else + fun_l10_n914(x) + end +end + +def fun_l9_n296(x) + if (x < 1) + fun_l10_n444(x) + else + fun_l10_n490(x) + end +end + +def fun_l9_n297(x) + if (x < 1) + fun_l10_n478(x) + else + fun_l10_n979(x) + end +end + +def fun_l9_n298(x) + if (x < 1) + fun_l10_n994(x) + else + fun_l10_n945(x) + end +end + +def fun_l9_n299(x) + if (x < 1) + fun_l10_n865(x) + else + fun_l10_n206(x) + end +end + +def fun_l9_n300(x) + if (x < 1) + fun_l10_n678(x) + else + fun_l10_n103(x) + end +end + +def fun_l9_n301(x) + if (x < 1) + fun_l10_n115(x) + else + fun_l10_n742(x) + end +end + +def fun_l9_n302(x) + if (x < 1) + fun_l10_n677(x) + else + fun_l10_n446(x) + end +end + +def fun_l9_n303(x) + if (x < 1) + fun_l10_n144(x) + else + fun_l10_n856(x) + end +end + +def fun_l9_n304(x) + if (x < 1) + fun_l10_n751(x) + else + fun_l10_n989(x) + end +end + +def fun_l9_n305(x) + if (x < 1) + fun_l10_n200(x) + else + fun_l10_n97(x) + end +end + +def fun_l9_n306(x) + if (x < 1) + fun_l10_n685(x) + else + fun_l10_n663(x) + end +end + +def fun_l9_n307(x) + if (x < 1) + fun_l10_n831(x) + else + fun_l10_n770(x) + end +end + +def fun_l9_n308(x) + if (x < 1) + fun_l10_n467(x) + else + fun_l10_n715(x) + end +end + +def fun_l9_n309(x) + if (x < 1) + fun_l10_n676(x) + else + fun_l10_n885(x) + end +end + +def fun_l9_n310(x) + if (x < 1) + fun_l10_n382(x) + else + fun_l10_n687(x) + end +end + +def fun_l9_n311(x) + if (x < 1) + fun_l10_n489(x) + else + fun_l10_n810(x) + end +end + +def fun_l9_n312(x) + if (x < 1) + fun_l10_n922(x) + else + fun_l10_n81(x) + end +end + +def fun_l9_n313(x) + if (x < 1) + fun_l10_n788(x) + else + fun_l10_n519(x) + end +end + +def fun_l9_n314(x) + if (x < 1) + fun_l10_n830(x) + else + fun_l10_n486(x) + end +end + +def fun_l9_n315(x) + if (x < 1) + fun_l10_n848(x) + else + fun_l10_n250(x) + end +end + +def fun_l9_n316(x) + if (x < 1) + fun_l10_n933(x) + else + fun_l10_n268(x) + end +end + +def fun_l9_n317(x) + if (x < 1) + fun_l10_n659(x) + else + fun_l10_n91(x) + end +end + +def fun_l9_n318(x) + if (x < 1) + fun_l10_n417(x) + else + fun_l10_n99(x) + end +end + +def fun_l9_n319(x) + if (x < 1) + fun_l10_n781(x) + else + fun_l10_n770(x) + end +end + +def fun_l9_n320(x) + if (x < 1) + fun_l10_n820(x) + else + fun_l10_n836(x) + end +end + +def fun_l9_n321(x) + if (x < 1) + fun_l10_n865(x) + else + fun_l10_n232(x) + end +end + +def fun_l9_n322(x) + if (x < 1) + fun_l10_n793(x) + else + fun_l10_n856(x) + end +end + +def fun_l9_n323(x) + if (x < 1) + fun_l10_n91(x) + else + fun_l10_n356(x) + end +end + +def fun_l9_n324(x) + if (x < 1) + fun_l10_n262(x) + else + fun_l10_n776(x) + end +end + +def fun_l9_n325(x) + if (x < 1) + fun_l10_n733(x) + else + fun_l10_n866(x) + end +end + +def fun_l9_n326(x) + if (x < 1) + fun_l10_n798(x) + else + fun_l10_n703(x) + end +end + +def fun_l9_n327(x) + if (x < 1) + fun_l10_n478(x) + else + fun_l10_n181(x) + end +end + +def fun_l9_n328(x) + if (x < 1) + fun_l10_n66(x) + else + fun_l10_n736(x) + end +end + +def fun_l9_n329(x) + if (x < 1) + fun_l10_n388(x) + else + fun_l10_n122(x) + end +end + +def fun_l9_n330(x) + if (x < 1) + fun_l10_n382(x) + else + fun_l10_n85(x) + end +end + +def fun_l9_n331(x) + if (x < 1) + fun_l10_n987(x) + else + fun_l10_n769(x) + end +end + +def fun_l9_n332(x) + if (x < 1) + fun_l10_n644(x) + else + fun_l10_n230(x) + end +end + +def fun_l9_n333(x) + if (x < 1) + fun_l10_n604(x) + else + fun_l10_n157(x) + end +end + +def fun_l9_n334(x) + if (x < 1) + fun_l10_n50(x) + else + fun_l10_n417(x) + end +end + +def fun_l9_n335(x) + if (x < 1) + fun_l10_n37(x) + else + fun_l10_n564(x) + end +end + +def fun_l9_n336(x) + if (x < 1) + fun_l10_n265(x) + else + fun_l10_n330(x) + end +end + +def fun_l9_n337(x) + if (x < 1) + fun_l10_n816(x) + else + fun_l10_n723(x) + end +end + +def fun_l9_n338(x) + if (x < 1) + fun_l10_n583(x) + else + fun_l10_n193(x) + end +end + +def fun_l9_n339(x) + if (x < 1) + fun_l10_n552(x) + else + fun_l10_n710(x) + end +end + +def fun_l9_n340(x) + if (x < 1) + fun_l10_n594(x) + else + fun_l10_n323(x) + end +end + +def fun_l9_n341(x) + if (x < 1) + fun_l10_n727(x) + else + fun_l10_n305(x) + end +end + +def fun_l9_n342(x) + if (x < 1) + fun_l10_n621(x) + else + fun_l10_n917(x) + end +end + +def fun_l9_n343(x) + if (x < 1) + fun_l10_n634(x) + else + fun_l10_n36(x) + end +end + +def fun_l9_n344(x) + if (x < 1) + fun_l10_n792(x) + else + fun_l10_n438(x) + end +end + +def fun_l9_n345(x) + if (x < 1) + fun_l10_n399(x) + else + fun_l10_n577(x) + end +end + +def fun_l9_n346(x) + if (x < 1) + fun_l10_n110(x) + else + fun_l10_n120(x) + end +end + +def fun_l9_n347(x) + if (x < 1) + fun_l10_n521(x) + else + fun_l10_n111(x) + end +end + +def fun_l9_n348(x) + if (x < 1) + fun_l10_n134(x) + else + fun_l10_n49(x) + end +end + +def fun_l9_n349(x) + if (x < 1) + fun_l10_n353(x) + else + fun_l10_n156(x) + end +end + +def fun_l9_n350(x) + if (x < 1) + fun_l10_n532(x) + else + fun_l10_n796(x) + end +end + +def fun_l9_n351(x) + if (x < 1) + fun_l10_n896(x) + else + fun_l10_n176(x) + end +end + +def fun_l9_n352(x) + if (x < 1) + fun_l10_n857(x) + else + fun_l10_n798(x) + end +end + +def fun_l9_n353(x) + if (x < 1) + fun_l10_n676(x) + else + fun_l10_n870(x) + end +end + +def fun_l9_n354(x) + if (x < 1) + fun_l10_n806(x) + else + fun_l10_n951(x) + end +end + +def fun_l9_n355(x) + if (x < 1) + fun_l10_n841(x) + else + fun_l10_n918(x) + end +end + +def fun_l9_n356(x) + if (x < 1) + fun_l10_n226(x) + else + fun_l10_n514(x) + end +end + +def fun_l9_n357(x) + if (x < 1) + fun_l10_n289(x) + else + fun_l10_n911(x) + end +end + +def fun_l9_n358(x) + if (x < 1) + fun_l10_n697(x) + else + fun_l10_n138(x) + end +end + +def fun_l9_n359(x) + if (x < 1) + fun_l10_n432(x) + else + fun_l10_n88(x) + end +end + +def fun_l9_n360(x) + if (x < 1) + fun_l10_n351(x) + else + fun_l10_n968(x) + end +end + +def fun_l9_n361(x) + if (x < 1) + fun_l10_n782(x) + else + fun_l10_n506(x) + end +end + +def fun_l9_n362(x) + if (x < 1) + fun_l10_n875(x) + else + fun_l10_n459(x) + end +end + +def fun_l9_n363(x) + if (x < 1) + fun_l10_n2(x) + else + fun_l10_n468(x) + end +end + +def fun_l9_n364(x) + if (x < 1) + fun_l10_n151(x) + else + fun_l10_n538(x) + end +end + +def fun_l9_n365(x) + if (x < 1) + fun_l10_n203(x) + else + fun_l10_n890(x) + end +end + +def fun_l9_n366(x) + if (x < 1) + fun_l10_n612(x) + else + fun_l10_n483(x) + end +end + +def fun_l9_n367(x) + if (x < 1) + fun_l10_n465(x) + else + fun_l10_n724(x) + end +end + +def fun_l9_n368(x) + if (x < 1) + fun_l10_n745(x) + else + fun_l10_n92(x) + end +end + +def fun_l9_n369(x) + if (x < 1) + fun_l10_n312(x) + else + fun_l10_n754(x) + end +end + +def fun_l9_n370(x) + if (x < 1) + fun_l10_n432(x) + else + fun_l10_n234(x) + end +end + +def fun_l9_n371(x) + if (x < 1) + fun_l10_n629(x) + else + fun_l10_n751(x) + end +end + +def fun_l9_n372(x) + if (x < 1) + fun_l10_n142(x) + else + fun_l10_n381(x) + end +end + +def fun_l9_n373(x) + if (x < 1) + fun_l10_n490(x) + else + fun_l10_n405(x) + end +end + +def fun_l9_n374(x) + if (x < 1) + fun_l10_n197(x) + else + fun_l10_n574(x) + end +end + +def fun_l9_n375(x) + if (x < 1) + fun_l10_n808(x) + else + fun_l10_n753(x) + end +end + +def fun_l9_n376(x) + if (x < 1) + fun_l10_n195(x) + else + fun_l10_n186(x) + end +end + +def fun_l9_n377(x) + if (x < 1) + fun_l10_n172(x) + else + fun_l10_n233(x) + end +end + +def fun_l9_n378(x) + if (x < 1) + fun_l10_n723(x) + else + fun_l10_n919(x) + end +end + +def fun_l9_n379(x) + if (x < 1) + fun_l10_n937(x) + else + fun_l10_n149(x) + end +end + +def fun_l9_n380(x) + if (x < 1) + fun_l10_n676(x) + else + fun_l10_n502(x) + end +end + +def fun_l9_n381(x) + if (x < 1) + fun_l10_n756(x) + else + fun_l10_n346(x) + end +end + +def fun_l9_n382(x) + if (x < 1) + fun_l10_n477(x) + else + fun_l10_n179(x) + end +end + +def fun_l9_n383(x) + if (x < 1) + fun_l10_n729(x) + else + fun_l10_n862(x) + end +end + +def fun_l9_n384(x) + if (x < 1) + fun_l10_n406(x) + else + fun_l10_n145(x) + end +end + +def fun_l9_n385(x) + if (x < 1) + fun_l10_n239(x) + else + fun_l10_n169(x) + end +end + +def fun_l9_n386(x) + if (x < 1) + fun_l10_n596(x) + else + fun_l10_n971(x) + end +end + +def fun_l9_n387(x) + if (x < 1) + fun_l10_n466(x) + else + fun_l10_n488(x) + end +end + +def fun_l9_n388(x) + if (x < 1) + fun_l10_n711(x) + else + fun_l10_n553(x) + end +end + +def fun_l9_n389(x) + if (x < 1) + fun_l10_n776(x) + else + fun_l10_n227(x) + end +end + +def fun_l9_n390(x) + if (x < 1) + fun_l10_n872(x) + else + fun_l10_n901(x) + end +end + +def fun_l9_n391(x) + if (x < 1) + fun_l10_n579(x) + else + fun_l10_n906(x) + end +end + +def fun_l9_n392(x) + if (x < 1) + fun_l10_n734(x) + else + fun_l10_n195(x) + end +end + +def fun_l9_n393(x) + if (x < 1) + fun_l10_n691(x) + else + fun_l10_n68(x) + end +end + +def fun_l9_n394(x) + if (x < 1) + fun_l10_n446(x) + else + fun_l10_n838(x) + end +end + +def fun_l9_n395(x) + if (x < 1) + fun_l10_n708(x) + else + fun_l10_n319(x) + end +end + +def fun_l9_n396(x) + if (x < 1) + fun_l10_n414(x) + else + fun_l10_n152(x) + end +end + +def fun_l9_n397(x) + if (x < 1) + fun_l10_n637(x) + else + fun_l10_n662(x) + end +end + +def fun_l9_n398(x) + if (x < 1) + fun_l10_n990(x) + else + fun_l10_n547(x) + end +end + +def fun_l9_n399(x) + if (x < 1) + fun_l10_n43(x) + else + fun_l10_n845(x) + end +end + +def fun_l9_n400(x) + if (x < 1) + fun_l10_n843(x) + else + fun_l10_n876(x) + end +end + +def fun_l9_n401(x) + if (x < 1) + fun_l10_n925(x) + else + fun_l10_n221(x) + end +end + +def fun_l9_n402(x) + if (x < 1) + fun_l10_n420(x) + else + fun_l10_n267(x) + end +end + +def fun_l9_n403(x) + if (x < 1) + fun_l10_n78(x) + else + fun_l10_n316(x) + end +end + +def fun_l9_n404(x) + if (x < 1) + fun_l10_n291(x) + else + fun_l10_n614(x) + end +end + +def fun_l9_n405(x) + if (x < 1) + fun_l10_n956(x) + else + fun_l10_n550(x) + end +end + +def fun_l9_n406(x) + if (x < 1) + fun_l10_n232(x) + else + fun_l10_n53(x) + end +end + +def fun_l9_n407(x) + if (x < 1) + fun_l10_n171(x) + else + fun_l10_n51(x) + end +end + +def fun_l9_n408(x) + if (x < 1) + fun_l10_n401(x) + else + fun_l10_n932(x) + end +end + +def fun_l9_n409(x) + if (x < 1) + fun_l10_n863(x) + else + fun_l10_n951(x) + end +end + +def fun_l9_n410(x) + if (x < 1) + fun_l10_n64(x) + else + fun_l10_n721(x) + end +end + +def fun_l9_n411(x) + if (x < 1) + fun_l10_n539(x) + else + fun_l10_n951(x) + end +end + +def fun_l9_n412(x) + if (x < 1) + fun_l10_n660(x) + else + fun_l10_n852(x) + end +end + +def fun_l9_n413(x) + if (x < 1) + fun_l10_n777(x) + else + fun_l10_n366(x) + end +end + +def fun_l9_n414(x) + if (x < 1) + fun_l10_n695(x) + else + fun_l10_n538(x) + end +end + +def fun_l9_n415(x) + if (x < 1) + fun_l10_n208(x) + else + fun_l10_n892(x) + end +end + +def fun_l9_n416(x) + if (x < 1) + fun_l10_n632(x) + else + fun_l10_n463(x) + end +end + +def fun_l9_n417(x) + if (x < 1) + fun_l10_n238(x) + else + fun_l10_n55(x) + end +end + +def fun_l9_n418(x) + if (x < 1) + fun_l10_n276(x) + else + fun_l10_n526(x) + end +end + +def fun_l9_n419(x) + if (x < 1) + fun_l10_n625(x) + else + fun_l10_n806(x) + end +end + +def fun_l9_n420(x) + if (x < 1) + fun_l10_n899(x) + else + fun_l10_n594(x) + end +end + +def fun_l9_n421(x) + if (x < 1) + fun_l10_n725(x) + else + fun_l10_n461(x) + end +end + +def fun_l9_n422(x) + if (x < 1) + fun_l10_n187(x) + else + fun_l10_n953(x) + end +end + +def fun_l9_n423(x) + if (x < 1) + fun_l10_n698(x) + else + fun_l10_n751(x) + end +end + +def fun_l9_n424(x) + if (x < 1) + fun_l10_n115(x) + else + fun_l10_n321(x) + end +end + +def fun_l9_n425(x) + if (x < 1) + fun_l10_n775(x) + else + fun_l10_n100(x) + end +end + +def fun_l9_n426(x) + if (x < 1) + fun_l10_n177(x) + else + fun_l10_n565(x) + end +end + +def fun_l9_n427(x) + if (x < 1) + fun_l10_n568(x) + else + fun_l10_n234(x) + end +end + +def fun_l9_n428(x) + if (x < 1) + fun_l10_n787(x) + else + fun_l10_n815(x) + end +end + +def fun_l9_n429(x) + if (x < 1) + fun_l10_n580(x) + else + fun_l10_n990(x) + end +end + +def fun_l9_n430(x) + if (x < 1) + fun_l10_n680(x) + else + fun_l10_n696(x) + end +end + +def fun_l9_n431(x) + if (x < 1) + fun_l10_n650(x) + else + fun_l10_n776(x) + end +end + +def fun_l9_n432(x) + if (x < 1) + fun_l10_n377(x) + else + fun_l10_n232(x) + end +end + +def fun_l9_n433(x) + if (x < 1) + fun_l10_n621(x) + else + fun_l10_n948(x) + end +end + +def fun_l9_n434(x) + if (x < 1) + fun_l10_n126(x) + else + fun_l10_n220(x) + end +end + +def fun_l9_n435(x) + if (x < 1) + fun_l10_n395(x) + else + fun_l10_n732(x) + end +end + +def fun_l9_n436(x) + if (x < 1) + fun_l10_n194(x) + else + fun_l10_n159(x) + end +end + +def fun_l9_n437(x) + if (x < 1) + fun_l10_n123(x) + else + fun_l10_n40(x) + end +end + +def fun_l9_n438(x) + if (x < 1) + fun_l10_n241(x) + else + fun_l10_n861(x) + end +end + +def fun_l9_n439(x) + if (x < 1) + fun_l10_n333(x) + else + fun_l10_n950(x) + end +end + +def fun_l9_n440(x) + if (x < 1) + fun_l10_n116(x) + else + fun_l10_n832(x) + end +end + +def fun_l9_n441(x) + if (x < 1) + fun_l10_n598(x) + else + fun_l10_n68(x) + end +end + +def fun_l9_n442(x) + if (x < 1) + fun_l10_n234(x) + else + fun_l10_n277(x) + end +end + +def fun_l9_n443(x) + if (x < 1) + fun_l10_n943(x) + else + fun_l10_n895(x) + end +end + +def fun_l9_n444(x) + if (x < 1) + fun_l10_n490(x) + else + fun_l10_n512(x) + end +end + +def fun_l9_n445(x) + if (x < 1) + fun_l10_n54(x) + else + fun_l10_n74(x) + end +end + +def fun_l9_n446(x) + if (x < 1) + fun_l10_n214(x) + else + fun_l10_n858(x) + end +end + +def fun_l9_n447(x) + if (x < 1) + fun_l10_n274(x) + else + fun_l10_n255(x) + end +end + +def fun_l9_n448(x) + if (x < 1) + fun_l10_n307(x) + else + fun_l10_n197(x) + end +end + +def fun_l9_n449(x) + if (x < 1) + fun_l10_n152(x) + else + fun_l10_n543(x) + end +end + +def fun_l9_n450(x) + if (x < 1) + fun_l10_n773(x) + else + fun_l10_n582(x) + end +end + +def fun_l9_n451(x) + if (x < 1) + fun_l10_n757(x) + else + fun_l10_n298(x) + end +end + +def fun_l9_n452(x) + if (x < 1) + fun_l10_n648(x) + else + fun_l10_n826(x) + end +end + +def fun_l9_n453(x) + if (x < 1) + fun_l10_n209(x) + else + fun_l10_n767(x) + end +end + +def fun_l9_n454(x) + if (x < 1) + fun_l10_n448(x) + else + fun_l10_n374(x) + end +end + +def fun_l9_n455(x) + if (x < 1) + fun_l10_n975(x) + else + fun_l10_n45(x) + end +end + +def fun_l9_n456(x) + if (x < 1) + fun_l10_n938(x) + else + fun_l10_n354(x) + end +end + +def fun_l9_n457(x) + if (x < 1) + fun_l10_n723(x) + else + fun_l10_n511(x) + end +end + +def fun_l9_n458(x) + if (x < 1) + fun_l10_n864(x) + else + fun_l10_n688(x) + end +end + +def fun_l9_n459(x) + if (x < 1) + fun_l10_n283(x) + else + fun_l10_n776(x) + end +end + +def fun_l9_n460(x) + if (x < 1) + fun_l10_n167(x) + else + fun_l10_n639(x) + end +end + +def fun_l9_n461(x) + if (x < 1) + fun_l10_n493(x) + else + fun_l10_n538(x) + end +end + +def fun_l9_n462(x) + if (x < 1) + fun_l10_n392(x) + else + fun_l10_n434(x) + end +end + +def fun_l9_n463(x) + if (x < 1) + fun_l10_n958(x) + else + fun_l10_n305(x) + end +end + +def fun_l9_n464(x) + if (x < 1) + fun_l10_n516(x) + else + fun_l10_n375(x) + end +end + +def fun_l9_n465(x) + if (x < 1) + fun_l10_n371(x) + else + fun_l10_n596(x) + end +end + +def fun_l9_n466(x) + if (x < 1) + fun_l10_n435(x) + else + fun_l10_n176(x) + end +end + +def fun_l9_n467(x) + if (x < 1) + fun_l10_n391(x) + else + fun_l10_n83(x) + end +end + +def fun_l9_n468(x) + if (x < 1) + fun_l10_n751(x) + else + fun_l10_n632(x) + end +end + +def fun_l9_n469(x) + if (x < 1) + fun_l10_n14(x) + else + fun_l10_n530(x) + end +end + +def fun_l9_n470(x) + if (x < 1) + fun_l10_n663(x) + else + fun_l10_n844(x) + end +end + +def fun_l9_n471(x) + if (x < 1) + fun_l10_n82(x) + else + fun_l10_n493(x) + end +end + +def fun_l9_n472(x) + if (x < 1) + fun_l10_n614(x) + else + fun_l10_n277(x) + end +end + +def fun_l9_n473(x) + if (x < 1) + fun_l10_n492(x) + else + fun_l10_n492(x) + end +end + +def fun_l9_n474(x) + if (x < 1) + fun_l10_n440(x) + else + fun_l10_n665(x) + end +end + +def fun_l9_n475(x) + if (x < 1) + fun_l10_n284(x) + else + fun_l10_n513(x) + end +end + +def fun_l9_n476(x) + if (x < 1) + fun_l10_n690(x) + else + fun_l10_n507(x) + end +end + +def fun_l9_n477(x) + if (x < 1) + fun_l10_n281(x) + else + fun_l10_n519(x) + end +end + +def fun_l9_n478(x) + if (x < 1) + fun_l10_n903(x) + else + fun_l10_n866(x) + end +end + +def fun_l9_n479(x) + if (x < 1) + fun_l10_n880(x) + else + fun_l10_n310(x) + end +end + +def fun_l9_n480(x) + if (x < 1) + fun_l10_n69(x) + else + fun_l10_n227(x) + end +end + +def fun_l9_n481(x) + if (x < 1) + fun_l10_n316(x) + else + fun_l10_n692(x) + end +end + +def fun_l9_n482(x) + if (x < 1) + fun_l10_n875(x) + else + fun_l10_n384(x) + end +end + +def fun_l9_n483(x) + if (x < 1) + fun_l10_n496(x) + else + fun_l10_n81(x) + end +end + +def fun_l9_n484(x) + if (x < 1) + fun_l10_n336(x) + else + fun_l10_n193(x) + end +end + +def fun_l9_n485(x) + if (x < 1) + fun_l10_n541(x) + else + fun_l10_n465(x) + end +end + +def fun_l9_n486(x) + if (x < 1) + fun_l10_n197(x) + else + fun_l10_n844(x) + end +end + +def fun_l9_n487(x) + if (x < 1) + fun_l10_n652(x) + else + fun_l10_n736(x) + end +end + +def fun_l9_n488(x) + if (x < 1) + fun_l10_n960(x) + else + fun_l10_n912(x) + end +end + +def fun_l9_n489(x) + if (x < 1) + fun_l10_n238(x) + else + fun_l10_n64(x) + end +end + +def fun_l9_n490(x) + if (x < 1) + fun_l10_n505(x) + else + fun_l10_n204(x) + end +end + +def fun_l9_n491(x) + if (x < 1) + fun_l10_n960(x) + else + fun_l10_n198(x) + end +end + +def fun_l9_n492(x) + if (x < 1) + fun_l10_n148(x) + else + fun_l10_n669(x) + end +end + +def fun_l9_n493(x) + if (x < 1) + fun_l10_n860(x) + else + fun_l10_n676(x) + end +end + +def fun_l9_n494(x) + if (x < 1) + fun_l10_n77(x) + else + fun_l10_n945(x) + end +end + +def fun_l9_n495(x) + if (x < 1) + fun_l10_n151(x) + else + fun_l10_n588(x) + end +end + +def fun_l9_n496(x) + if (x < 1) + fun_l10_n159(x) + else + fun_l10_n727(x) + end +end + +def fun_l9_n497(x) + if (x < 1) + fun_l10_n803(x) + else + fun_l10_n292(x) + end +end + +def fun_l9_n498(x) + if (x < 1) + fun_l10_n308(x) + else + fun_l10_n46(x) + end +end + +def fun_l9_n499(x) + if (x < 1) + fun_l10_n511(x) + else + fun_l10_n766(x) + end +end + +def fun_l9_n500(x) + if (x < 1) + fun_l10_n753(x) + else + fun_l10_n235(x) + end +end + +def fun_l9_n501(x) + if (x < 1) + fun_l10_n776(x) + else + fun_l10_n779(x) + end +end + +def fun_l9_n502(x) + if (x < 1) + fun_l10_n114(x) + else + fun_l10_n969(x) + end +end + +def fun_l9_n503(x) + if (x < 1) + fun_l10_n511(x) + else + fun_l10_n678(x) + end +end + +def fun_l9_n504(x) + if (x < 1) + fun_l10_n578(x) + else + fun_l10_n689(x) + end +end + +def fun_l9_n505(x) + if (x < 1) + fun_l10_n434(x) + else + fun_l10_n0(x) + end +end + +def fun_l9_n506(x) + if (x < 1) + fun_l10_n121(x) + else + fun_l10_n488(x) + end +end + +def fun_l9_n507(x) + if (x < 1) + fun_l10_n865(x) + else + fun_l10_n540(x) + end +end + +def fun_l9_n508(x) + if (x < 1) + fun_l10_n809(x) + else + fun_l10_n764(x) + end +end + +def fun_l9_n509(x) + if (x < 1) + fun_l10_n463(x) + else + fun_l10_n141(x) + end +end + +def fun_l9_n510(x) + if (x < 1) + fun_l10_n442(x) + else + fun_l10_n646(x) + end +end + +def fun_l9_n511(x) + if (x < 1) + fun_l10_n971(x) + else + fun_l10_n57(x) + end +end + +def fun_l9_n512(x) + if (x < 1) + fun_l10_n892(x) + else + fun_l10_n612(x) + end +end + +def fun_l9_n513(x) + if (x < 1) + fun_l10_n864(x) + else + fun_l10_n438(x) + end +end + +def fun_l9_n514(x) + if (x < 1) + fun_l10_n504(x) + else + fun_l10_n100(x) + end +end + +def fun_l9_n515(x) + if (x < 1) + fun_l10_n881(x) + else + fun_l10_n621(x) + end +end + +def fun_l9_n516(x) + if (x < 1) + fun_l10_n170(x) + else + fun_l10_n435(x) + end +end + +def fun_l9_n517(x) + if (x < 1) + fun_l10_n712(x) + else + fun_l10_n537(x) + end +end + +def fun_l9_n518(x) + if (x < 1) + fun_l10_n369(x) + else + fun_l10_n832(x) + end +end + +def fun_l9_n519(x) + if (x < 1) + fun_l10_n654(x) + else + fun_l10_n364(x) + end +end + +def fun_l9_n520(x) + if (x < 1) + fun_l10_n410(x) + else + fun_l10_n10(x) + end +end + +def fun_l9_n521(x) + if (x < 1) + fun_l10_n814(x) + else + fun_l10_n569(x) + end +end + +def fun_l9_n522(x) + if (x < 1) + fun_l10_n787(x) + else + fun_l10_n333(x) + end +end + +def fun_l9_n523(x) + if (x < 1) + fun_l10_n336(x) + else + fun_l10_n720(x) + end +end + +def fun_l9_n524(x) + if (x < 1) + fun_l10_n34(x) + else + fun_l10_n643(x) + end +end + +def fun_l9_n525(x) + if (x < 1) + fun_l10_n147(x) + else + fun_l10_n62(x) + end +end + +def fun_l9_n526(x) + if (x < 1) + fun_l10_n431(x) + else + fun_l10_n452(x) + end +end + +def fun_l9_n527(x) + if (x < 1) + fun_l10_n374(x) + else + fun_l10_n831(x) + end +end + +def fun_l9_n528(x) + if (x < 1) + fun_l10_n604(x) + else + fun_l10_n274(x) + end +end + +def fun_l9_n529(x) + if (x < 1) + fun_l10_n470(x) + else + fun_l10_n764(x) + end +end + +def fun_l9_n530(x) + if (x < 1) + fun_l10_n552(x) + else + fun_l10_n646(x) + end +end + +def fun_l9_n531(x) + if (x < 1) + fun_l10_n427(x) + else + fun_l10_n464(x) + end +end + +def fun_l9_n532(x) + if (x < 1) + fun_l10_n553(x) + else + fun_l10_n605(x) + end +end + +def fun_l9_n533(x) + if (x < 1) + fun_l10_n59(x) + else + fun_l10_n794(x) + end +end + +def fun_l9_n534(x) + if (x < 1) + fun_l10_n168(x) + else + fun_l10_n740(x) + end +end + +def fun_l9_n535(x) + if (x < 1) + fun_l10_n227(x) + else + fun_l10_n651(x) + end +end + +def fun_l9_n536(x) + if (x < 1) + fun_l10_n904(x) + else + fun_l10_n552(x) + end +end + +def fun_l9_n537(x) + if (x < 1) + fun_l10_n389(x) + else + fun_l10_n397(x) + end +end + +def fun_l9_n538(x) + if (x < 1) + fun_l10_n622(x) + else + fun_l10_n100(x) + end +end + +def fun_l9_n539(x) + if (x < 1) + fun_l10_n117(x) + else + fun_l10_n715(x) + end +end + +def fun_l9_n540(x) + if (x < 1) + fun_l10_n959(x) + else + fun_l10_n391(x) + end +end + +def fun_l9_n541(x) + if (x < 1) + fun_l10_n733(x) + else + fun_l10_n393(x) + end +end + +def fun_l9_n542(x) + if (x < 1) + fun_l10_n171(x) + else + fun_l10_n299(x) + end +end + +def fun_l9_n543(x) + if (x < 1) + fun_l10_n655(x) + else + fun_l10_n285(x) + end +end + +def fun_l9_n544(x) + if (x < 1) + fun_l10_n819(x) + else + fun_l10_n817(x) + end +end + +def fun_l9_n545(x) + if (x < 1) + fun_l10_n938(x) + else + fun_l10_n54(x) + end +end + +def fun_l9_n546(x) + if (x < 1) + fun_l10_n712(x) + else + fun_l10_n6(x) + end +end + +def fun_l9_n547(x) + if (x < 1) + fun_l10_n203(x) + else + fun_l10_n626(x) + end +end + +def fun_l9_n548(x) + if (x < 1) + fun_l10_n643(x) + else + fun_l10_n761(x) + end +end + +def fun_l9_n549(x) + if (x < 1) + fun_l10_n450(x) + else + fun_l10_n673(x) + end +end + +def fun_l9_n550(x) + if (x < 1) + fun_l10_n496(x) + else + fun_l10_n568(x) + end +end + +def fun_l9_n551(x) + if (x < 1) + fun_l10_n30(x) + else + fun_l10_n518(x) + end +end + +def fun_l9_n552(x) + if (x < 1) + fun_l10_n398(x) + else + fun_l10_n858(x) + end +end + +def fun_l9_n553(x) + if (x < 1) + fun_l10_n253(x) + else + fun_l10_n831(x) + end +end + +def fun_l9_n554(x) + if (x < 1) + fun_l10_n493(x) + else + fun_l10_n750(x) + end +end + +def fun_l9_n555(x) + if (x < 1) + fun_l10_n111(x) + else + fun_l10_n279(x) + end +end + +def fun_l9_n556(x) + if (x < 1) + fun_l10_n927(x) + else + fun_l10_n793(x) + end +end + +def fun_l9_n557(x) + if (x < 1) + fun_l10_n530(x) + else + fun_l10_n182(x) + end +end + +def fun_l9_n558(x) + if (x < 1) + fun_l10_n434(x) + else + fun_l10_n453(x) + end +end + +def fun_l9_n559(x) + if (x < 1) + fun_l10_n480(x) + else + fun_l10_n590(x) + end +end + +def fun_l9_n560(x) + if (x < 1) + fun_l10_n906(x) + else + fun_l10_n280(x) + end +end + +def fun_l9_n561(x) + if (x < 1) + fun_l10_n107(x) + else + fun_l10_n716(x) + end +end + +def fun_l9_n562(x) + if (x < 1) + fun_l10_n15(x) + else + fun_l10_n671(x) + end +end + +def fun_l9_n563(x) + if (x < 1) + fun_l10_n544(x) + else + fun_l10_n571(x) + end +end + +def fun_l9_n564(x) + if (x < 1) + fun_l10_n482(x) + else + fun_l10_n885(x) + end +end + +def fun_l9_n565(x) + if (x < 1) + fun_l10_n465(x) + else + fun_l10_n916(x) + end +end + +def fun_l9_n566(x) + if (x < 1) + fun_l10_n413(x) + else + fun_l10_n684(x) + end +end + +def fun_l9_n567(x) + if (x < 1) + fun_l10_n413(x) + else + fun_l10_n577(x) + end +end + +def fun_l9_n568(x) + if (x < 1) + fun_l10_n604(x) + else + fun_l10_n899(x) + end +end + +def fun_l9_n569(x) + if (x < 1) + fun_l10_n138(x) + else + fun_l10_n164(x) + end +end + +def fun_l9_n570(x) + if (x < 1) + fun_l10_n993(x) + else + fun_l10_n94(x) + end +end + +def fun_l9_n571(x) + if (x < 1) + fun_l10_n602(x) + else + fun_l10_n989(x) + end +end + +def fun_l9_n572(x) + if (x < 1) + fun_l10_n700(x) + else + fun_l10_n308(x) + end +end + +def fun_l9_n573(x) + if (x < 1) + fun_l10_n773(x) + else + fun_l10_n945(x) + end +end + +def fun_l9_n574(x) + if (x < 1) + fun_l10_n148(x) + else + fun_l10_n608(x) + end +end + +def fun_l9_n575(x) + if (x < 1) + fun_l10_n439(x) + else + fun_l10_n908(x) + end +end + +def fun_l9_n576(x) + if (x < 1) + fun_l10_n174(x) + else + fun_l10_n872(x) + end +end + +def fun_l9_n577(x) + if (x < 1) + fun_l10_n291(x) + else + fun_l10_n265(x) + end +end + +def fun_l9_n578(x) + if (x < 1) + fun_l10_n425(x) + else + fun_l10_n928(x) + end +end + +def fun_l9_n579(x) + if (x < 1) + fun_l10_n674(x) + else + fun_l10_n666(x) + end +end + +def fun_l9_n580(x) + if (x < 1) + fun_l10_n784(x) + else + fun_l10_n147(x) + end +end + +def fun_l9_n581(x) + if (x < 1) + fun_l10_n550(x) + else + fun_l10_n119(x) + end +end + +def fun_l9_n582(x) + if (x < 1) + fun_l10_n953(x) + else + fun_l10_n269(x) + end +end + +def fun_l9_n583(x) + if (x < 1) + fun_l10_n575(x) + else + fun_l10_n79(x) + end +end + +def fun_l9_n584(x) + if (x < 1) + fun_l10_n498(x) + else + fun_l10_n1(x) + end +end + +def fun_l9_n585(x) + if (x < 1) + fun_l10_n728(x) + else + fun_l10_n92(x) + end +end + +def fun_l9_n586(x) + if (x < 1) + fun_l10_n344(x) + else + fun_l10_n753(x) + end +end + +def fun_l9_n587(x) + if (x < 1) + fun_l10_n911(x) + else + fun_l10_n327(x) + end +end + +def fun_l9_n588(x) + if (x < 1) + fun_l10_n422(x) + else + fun_l10_n224(x) + end +end + +def fun_l9_n589(x) + if (x < 1) + fun_l10_n311(x) + else + fun_l10_n457(x) + end +end + +def fun_l9_n590(x) + if (x < 1) + fun_l10_n705(x) + else + fun_l10_n136(x) + end +end + +def fun_l9_n591(x) + if (x < 1) + fun_l10_n338(x) + else + fun_l10_n14(x) + end +end + +def fun_l9_n592(x) + if (x < 1) + fun_l10_n144(x) + else + fun_l10_n671(x) + end +end + +def fun_l9_n593(x) + if (x < 1) + fun_l10_n402(x) + else + fun_l10_n218(x) + end +end + +def fun_l9_n594(x) + if (x < 1) + fun_l10_n854(x) + else + fun_l10_n198(x) + end +end + +def fun_l9_n595(x) + if (x < 1) + fun_l10_n932(x) + else + fun_l10_n181(x) + end +end + +def fun_l9_n596(x) + if (x < 1) + fun_l10_n373(x) + else + fun_l10_n937(x) + end +end + +def fun_l9_n597(x) + if (x < 1) + fun_l10_n181(x) + else + fun_l10_n925(x) + end +end + +def fun_l9_n598(x) + if (x < 1) + fun_l10_n263(x) + else + fun_l10_n98(x) + end +end + +def fun_l9_n599(x) + if (x < 1) + fun_l10_n736(x) + else + fun_l10_n951(x) + end +end + +def fun_l9_n600(x) + if (x < 1) + fun_l10_n576(x) + else + fun_l10_n998(x) + end +end + +def fun_l9_n601(x) + if (x < 1) + fun_l10_n577(x) + else + fun_l10_n559(x) + end +end + +def fun_l9_n602(x) + if (x < 1) + fun_l10_n143(x) + else + fun_l10_n993(x) + end +end + +def fun_l9_n603(x) + if (x < 1) + fun_l10_n35(x) + else + fun_l10_n132(x) + end +end + +def fun_l9_n604(x) + if (x < 1) + fun_l10_n715(x) + else + fun_l10_n933(x) + end +end + +def fun_l9_n605(x) + if (x < 1) + fun_l10_n570(x) + else + fun_l10_n455(x) + end +end + +def fun_l9_n606(x) + if (x < 1) + fun_l10_n225(x) + else + fun_l10_n216(x) + end +end + +def fun_l9_n607(x) + if (x < 1) + fun_l10_n431(x) + else + fun_l10_n285(x) + end +end + +def fun_l9_n608(x) + if (x < 1) + fun_l10_n647(x) + else + fun_l10_n221(x) + end +end + +def fun_l9_n609(x) + if (x < 1) + fun_l10_n348(x) + else + fun_l10_n849(x) + end +end + +def fun_l9_n610(x) + if (x < 1) + fun_l10_n301(x) + else + fun_l10_n500(x) + end +end + +def fun_l9_n611(x) + if (x < 1) + fun_l10_n152(x) + else + fun_l10_n1(x) + end +end + +def fun_l9_n612(x) + if (x < 1) + fun_l10_n339(x) + else + fun_l10_n577(x) + end +end + +def fun_l9_n613(x) + if (x < 1) + fun_l10_n427(x) + else + fun_l10_n779(x) + end +end + +def fun_l9_n614(x) + if (x < 1) + fun_l10_n60(x) + else + fun_l10_n199(x) + end +end + +def fun_l9_n615(x) + if (x < 1) + fun_l10_n616(x) + else + fun_l10_n33(x) + end +end + +def fun_l9_n616(x) + if (x < 1) + fun_l10_n940(x) + else + fun_l10_n981(x) + end +end + +def fun_l9_n617(x) + if (x < 1) + fun_l10_n594(x) + else + fun_l10_n321(x) + end +end + +def fun_l9_n618(x) + if (x < 1) + fun_l10_n233(x) + else + fun_l10_n500(x) + end +end + +def fun_l9_n619(x) + if (x < 1) + fun_l10_n169(x) + else + fun_l10_n883(x) + end +end + +def fun_l9_n620(x) + if (x < 1) + fun_l10_n611(x) + else + fun_l10_n345(x) + end +end + +def fun_l9_n621(x) + if (x < 1) + fun_l10_n155(x) + else + fun_l10_n547(x) + end +end + +def fun_l9_n622(x) + if (x < 1) + fun_l10_n244(x) + else + fun_l10_n760(x) + end +end + +def fun_l9_n623(x) + if (x < 1) + fun_l10_n893(x) + else + fun_l10_n13(x) + end +end + +def fun_l9_n624(x) + if (x < 1) + fun_l10_n465(x) + else + fun_l10_n276(x) + end +end + +def fun_l9_n625(x) + if (x < 1) + fun_l10_n196(x) + else + fun_l10_n920(x) + end +end + +def fun_l9_n626(x) + if (x < 1) + fun_l10_n235(x) + else + fun_l10_n962(x) + end +end + +def fun_l9_n627(x) + if (x < 1) + fun_l10_n361(x) + else + fun_l10_n162(x) + end +end + +def fun_l9_n628(x) + if (x < 1) + fun_l10_n110(x) + else + fun_l10_n574(x) + end +end + +def fun_l9_n629(x) + if (x < 1) + fun_l10_n861(x) + else + fun_l10_n839(x) + end +end + +def fun_l9_n630(x) + if (x < 1) + fun_l10_n386(x) + else + fun_l10_n741(x) + end +end + +def fun_l9_n631(x) + if (x < 1) + fun_l10_n426(x) + else + fun_l10_n430(x) + end +end + +def fun_l9_n632(x) + if (x < 1) + fun_l10_n231(x) + else + fun_l10_n353(x) + end +end + +def fun_l9_n633(x) + if (x < 1) + fun_l10_n945(x) + else + fun_l10_n199(x) + end +end + +def fun_l9_n634(x) + if (x < 1) + fun_l10_n607(x) + else + fun_l10_n388(x) + end +end + +def fun_l9_n635(x) + if (x < 1) + fun_l10_n214(x) + else + fun_l10_n135(x) + end +end + +def fun_l9_n636(x) + if (x < 1) + fun_l10_n642(x) + else + fun_l10_n522(x) + end +end + +def fun_l9_n637(x) + if (x < 1) + fun_l10_n605(x) + else + fun_l10_n336(x) + end +end + +def fun_l9_n638(x) + if (x < 1) + fun_l10_n719(x) + else + fun_l10_n213(x) + end +end + +def fun_l9_n639(x) + if (x < 1) + fun_l10_n202(x) + else + fun_l10_n767(x) + end +end + +def fun_l9_n640(x) + if (x < 1) + fun_l10_n242(x) + else + fun_l10_n596(x) + end +end + +def fun_l9_n641(x) + if (x < 1) + fun_l10_n851(x) + else + fun_l10_n216(x) + end +end + +def fun_l9_n642(x) + if (x < 1) + fun_l10_n645(x) + else + fun_l10_n890(x) + end +end + +def fun_l9_n643(x) + if (x < 1) + fun_l10_n241(x) + else + fun_l10_n350(x) + end +end + +def fun_l9_n644(x) + if (x < 1) + fun_l10_n597(x) + else + fun_l10_n350(x) + end +end + +def fun_l9_n645(x) + if (x < 1) + fun_l10_n170(x) + else + fun_l10_n962(x) + end +end + +def fun_l9_n646(x) + if (x < 1) + fun_l10_n229(x) + else + fun_l10_n543(x) + end +end + +def fun_l9_n647(x) + if (x < 1) + fun_l10_n473(x) + else + fun_l10_n942(x) + end +end + +def fun_l9_n648(x) + if (x < 1) + fun_l10_n630(x) + else + fun_l10_n630(x) + end +end + +def fun_l9_n649(x) + if (x < 1) + fun_l10_n183(x) + else + fun_l10_n313(x) + end +end + +def fun_l9_n650(x) + if (x < 1) + fun_l10_n951(x) + else + fun_l10_n394(x) + end +end + +def fun_l9_n651(x) + if (x < 1) + fun_l10_n107(x) + else + fun_l10_n849(x) + end +end + +def fun_l9_n652(x) + if (x < 1) + fun_l10_n678(x) + else + fun_l10_n768(x) + end +end + +def fun_l9_n653(x) + if (x < 1) + fun_l10_n534(x) + else + fun_l10_n410(x) + end +end + +def fun_l9_n654(x) + if (x < 1) + fun_l10_n694(x) + else + fun_l10_n134(x) + end +end + +def fun_l9_n655(x) + if (x < 1) + fun_l10_n751(x) + else + fun_l10_n923(x) + end +end + +def fun_l9_n656(x) + if (x < 1) + fun_l10_n957(x) + else + fun_l10_n489(x) + end +end + +def fun_l9_n657(x) + if (x < 1) + fun_l10_n612(x) + else + fun_l10_n577(x) + end +end + +def fun_l9_n658(x) + if (x < 1) + fun_l10_n814(x) + else + fun_l10_n801(x) + end +end + +def fun_l9_n659(x) + if (x < 1) + fun_l10_n297(x) + else + fun_l10_n344(x) + end +end + +def fun_l9_n660(x) + if (x < 1) + fun_l10_n674(x) + else + fun_l10_n780(x) + end +end + +def fun_l9_n661(x) + if (x < 1) + fun_l10_n302(x) + else + fun_l10_n184(x) + end +end + +def fun_l9_n662(x) + if (x < 1) + fun_l10_n308(x) + else + fun_l10_n302(x) + end +end + +def fun_l9_n663(x) + if (x < 1) + fun_l10_n825(x) + else + fun_l10_n866(x) + end +end + +def fun_l9_n664(x) + if (x < 1) + fun_l10_n771(x) + else + fun_l10_n141(x) + end +end + +def fun_l9_n665(x) + if (x < 1) + fun_l10_n369(x) + else + fun_l10_n63(x) + end +end + +def fun_l9_n666(x) + if (x < 1) + fun_l10_n198(x) + else + fun_l10_n793(x) + end +end + +def fun_l9_n667(x) + if (x < 1) + fun_l10_n800(x) + else + fun_l10_n748(x) + end +end + +def fun_l9_n668(x) + if (x < 1) + fun_l10_n809(x) + else + fun_l10_n673(x) + end +end + +def fun_l9_n669(x) + if (x < 1) + fun_l10_n438(x) + else + fun_l10_n301(x) + end +end + +def fun_l9_n670(x) + if (x < 1) + fun_l10_n802(x) + else + fun_l10_n882(x) + end +end + +def fun_l9_n671(x) + if (x < 1) + fun_l10_n690(x) + else + fun_l10_n524(x) + end +end + +def fun_l9_n672(x) + if (x < 1) + fun_l10_n996(x) + else + fun_l10_n68(x) + end +end + +def fun_l9_n673(x) + if (x < 1) + fun_l10_n773(x) + else + fun_l10_n26(x) + end +end + +def fun_l9_n674(x) + if (x < 1) + fun_l10_n252(x) + else + fun_l10_n680(x) + end +end + +def fun_l9_n675(x) + if (x < 1) + fun_l10_n466(x) + else + fun_l10_n885(x) + end +end + +def fun_l9_n676(x) + if (x < 1) + fun_l10_n746(x) + else + fun_l10_n968(x) + end +end + +def fun_l9_n677(x) + if (x < 1) + fun_l10_n827(x) + else + fun_l10_n69(x) + end +end + +def fun_l9_n678(x) + if (x < 1) + fun_l10_n158(x) + else + fun_l10_n780(x) + end +end + +def fun_l9_n679(x) + if (x < 1) + fun_l10_n267(x) + else + fun_l10_n907(x) + end +end + +def fun_l9_n680(x) + if (x < 1) + fun_l10_n378(x) + else + fun_l10_n668(x) + end +end + +def fun_l9_n681(x) + if (x < 1) + fun_l10_n481(x) + else + fun_l10_n421(x) + end +end + +def fun_l9_n682(x) + if (x < 1) + fun_l10_n501(x) + else + fun_l10_n277(x) + end +end + +def fun_l9_n683(x) + if (x < 1) + fun_l10_n533(x) + else + fun_l10_n604(x) + end +end + +def fun_l9_n684(x) + if (x < 1) + fun_l10_n483(x) + else + fun_l10_n761(x) + end +end + +def fun_l9_n685(x) + if (x < 1) + fun_l10_n41(x) + else + fun_l10_n374(x) + end +end + +def fun_l9_n686(x) + if (x < 1) + fun_l10_n549(x) + else + fun_l10_n319(x) + end +end + +def fun_l9_n687(x) + if (x < 1) + fun_l10_n246(x) + else + fun_l10_n854(x) + end +end + +def fun_l9_n688(x) + if (x < 1) + fun_l10_n634(x) + else + fun_l10_n43(x) + end +end + +def fun_l9_n689(x) + if (x < 1) + fun_l10_n994(x) + else + fun_l10_n549(x) + end +end + +def fun_l9_n690(x) + if (x < 1) + fun_l10_n439(x) + else + fun_l10_n560(x) + end +end + +def fun_l9_n691(x) + if (x < 1) + fun_l10_n227(x) + else + fun_l10_n877(x) + end +end + +def fun_l9_n692(x) + if (x < 1) + fun_l10_n644(x) + else + fun_l10_n350(x) + end +end + +def fun_l9_n693(x) + if (x < 1) + fun_l10_n543(x) + else + fun_l10_n638(x) + end +end + +def fun_l9_n694(x) + if (x < 1) + fun_l10_n537(x) + else + fun_l10_n187(x) + end +end + +def fun_l9_n695(x) + if (x < 1) + fun_l10_n1(x) + else + fun_l10_n540(x) + end +end + +def fun_l9_n696(x) + if (x < 1) + fun_l10_n306(x) + else + fun_l10_n290(x) + end +end + +def fun_l9_n697(x) + if (x < 1) + fun_l10_n140(x) + else + fun_l10_n72(x) + end +end + +def fun_l9_n698(x) + if (x < 1) + fun_l10_n43(x) + else + fun_l10_n257(x) + end +end + +def fun_l9_n699(x) + if (x < 1) + fun_l10_n91(x) + else + fun_l10_n816(x) + end +end + +def fun_l9_n700(x) + if (x < 1) + fun_l10_n420(x) + else + fun_l10_n763(x) + end +end + +def fun_l9_n701(x) + if (x < 1) + fun_l10_n429(x) + else + fun_l10_n28(x) + end +end + +def fun_l9_n702(x) + if (x < 1) + fun_l10_n615(x) + else + fun_l10_n995(x) + end +end + +def fun_l9_n703(x) + if (x < 1) + fun_l10_n776(x) + else + fun_l10_n85(x) + end +end + +def fun_l9_n704(x) + if (x < 1) + fun_l10_n795(x) + else + fun_l10_n542(x) + end +end + +def fun_l9_n705(x) + if (x < 1) + fun_l10_n114(x) + else + fun_l10_n166(x) + end +end + +def fun_l9_n706(x) + if (x < 1) + fun_l10_n99(x) + else + fun_l10_n400(x) + end +end + +def fun_l9_n707(x) + if (x < 1) + fun_l10_n292(x) + else + fun_l10_n801(x) + end +end + +def fun_l9_n708(x) + if (x < 1) + fun_l10_n303(x) + else + fun_l10_n380(x) + end +end + +def fun_l9_n709(x) + if (x < 1) + fun_l10_n369(x) + else + fun_l10_n938(x) + end +end + +def fun_l9_n710(x) + if (x < 1) + fun_l10_n652(x) + else + fun_l10_n453(x) + end +end + +def fun_l9_n711(x) + if (x < 1) + fun_l10_n770(x) + else + fun_l10_n32(x) + end +end + +def fun_l9_n712(x) + if (x < 1) + fun_l10_n261(x) + else + fun_l10_n485(x) + end +end + +def fun_l9_n713(x) + if (x < 1) + fun_l10_n935(x) + else + fun_l10_n39(x) + end +end + +def fun_l9_n714(x) + if (x < 1) + fun_l10_n332(x) + else + fun_l10_n309(x) + end +end + +def fun_l9_n715(x) + if (x < 1) + fun_l10_n824(x) + else + fun_l10_n614(x) + end +end + +def fun_l9_n716(x) + if (x < 1) + fun_l10_n468(x) + else + fun_l10_n341(x) + end +end + +def fun_l9_n717(x) + if (x < 1) + fun_l10_n425(x) + else + fun_l10_n67(x) + end +end + +def fun_l9_n718(x) + if (x < 1) + fun_l10_n199(x) + else + fun_l10_n423(x) + end +end + +def fun_l9_n719(x) + if (x < 1) + fun_l10_n294(x) + else + fun_l10_n484(x) + end +end + +def fun_l9_n720(x) + if (x < 1) + fun_l10_n276(x) + else + fun_l10_n799(x) + end +end + +def fun_l9_n721(x) + if (x < 1) + fun_l10_n98(x) + else + fun_l10_n278(x) + end +end + +def fun_l9_n722(x) + if (x < 1) + fun_l10_n689(x) + else + fun_l10_n767(x) + end +end + +def fun_l9_n723(x) + if (x < 1) + fun_l10_n786(x) + else + fun_l10_n409(x) + end +end + +def fun_l9_n724(x) + if (x < 1) + fun_l10_n874(x) + else + fun_l10_n413(x) + end +end + +def fun_l9_n725(x) + if (x < 1) + fun_l10_n806(x) + else + fun_l10_n529(x) + end +end + +def fun_l9_n726(x) + if (x < 1) + fun_l10_n847(x) + else + fun_l10_n427(x) + end +end + +def fun_l9_n727(x) + if (x < 1) + fun_l10_n285(x) + else + fun_l10_n878(x) + end +end + +def fun_l9_n728(x) + if (x < 1) + fun_l10_n829(x) + else + fun_l10_n341(x) + end +end + +def fun_l9_n729(x) + if (x < 1) + fun_l10_n797(x) + else + fun_l10_n865(x) + end +end + +def fun_l9_n730(x) + if (x < 1) + fun_l10_n689(x) + else + fun_l10_n241(x) + end +end + +def fun_l9_n731(x) + if (x < 1) + fun_l10_n764(x) + else + fun_l10_n451(x) + end +end + +def fun_l9_n732(x) + if (x < 1) + fun_l10_n147(x) + else + fun_l10_n998(x) + end +end + +def fun_l9_n733(x) + if (x < 1) + fun_l10_n192(x) + else + fun_l10_n293(x) + end +end + +def fun_l9_n734(x) + if (x < 1) + fun_l10_n207(x) + else + fun_l10_n696(x) + end +end + +def fun_l9_n735(x) + if (x < 1) + fun_l10_n457(x) + else + fun_l10_n93(x) + end +end + +def fun_l9_n736(x) + if (x < 1) + fun_l10_n130(x) + else + fun_l10_n512(x) + end +end + +def fun_l9_n737(x) + if (x < 1) + fun_l10_n86(x) + else + fun_l10_n409(x) + end +end + +def fun_l9_n738(x) + if (x < 1) + fun_l10_n783(x) + else + fun_l10_n981(x) + end +end + +def fun_l9_n739(x) + if (x < 1) + fun_l10_n927(x) + else + fun_l10_n831(x) + end +end + +def fun_l9_n740(x) + if (x < 1) + fun_l10_n719(x) + else + fun_l10_n422(x) + end +end + +def fun_l9_n741(x) + if (x < 1) + fun_l10_n287(x) + else + fun_l10_n139(x) + end +end + +def fun_l9_n742(x) + if (x < 1) + fun_l10_n533(x) + else + fun_l10_n687(x) + end +end + +def fun_l9_n743(x) + if (x < 1) + fun_l10_n550(x) + else + fun_l10_n972(x) + end +end + +def fun_l9_n744(x) + if (x < 1) + fun_l10_n5(x) + else + fun_l10_n306(x) + end +end + +def fun_l9_n745(x) + if (x < 1) + fun_l10_n755(x) + else + fun_l10_n849(x) + end +end + +def fun_l9_n746(x) + if (x < 1) + fun_l10_n912(x) + else + fun_l10_n307(x) + end +end + +def fun_l9_n747(x) + if (x < 1) + fun_l10_n181(x) + else + fun_l10_n476(x) + end +end + +def fun_l9_n748(x) + if (x < 1) + fun_l10_n353(x) + else + fun_l10_n412(x) + end +end + +def fun_l9_n749(x) + if (x < 1) + fun_l10_n187(x) + else + fun_l10_n591(x) + end +end + +def fun_l9_n750(x) + if (x < 1) + fun_l10_n464(x) + else + fun_l10_n581(x) + end +end + +def fun_l9_n751(x) + if (x < 1) + fun_l10_n1(x) + else + fun_l10_n557(x) + end +end + +def fun_l9_n752(x) + if (x < 1) + fun_l10_n788(x) + else + fun_l10_n438(x) + end +end + +def fun_l9_n753(x) + if (x < 1) + fun_l10_n535(x) + else + fun_l10_n13(x) + end +end + +def fun_l9_n754(x) + if (x < 1) + fun_l10_n811(x) + else + fun_l10_n543(x) + end +end + +def fun_l9_n755(x) + if (x < 1) + fun_l10_n328(x) + else + fun_l10_n44(x) + end +end + +def fun_l9_n756(x) + if (x < 1) + fun_l10_n839(x) + else + fun_l10_n16(x) + end +end + +def fun_l9_n757(x) + if (x < 1) + fun_l10_n778(x) + else + fun_l10_n865(x) + end +end + +def fun_l9_n758(x) + if (x < 1) + fun_l10_n552(x) + else + fun_l10_n783(x) + end +end + +def fun_l9_n759(x) + if (x < 1) + fun_l10_n293(x) + else + fun_l10_n140(x) + end +end + +def fun_l9_n760(x) + if (x < 1) + fun_l10_n814(x) + else + fun_l10_n497(x) + end +end + +def fun_l9_n761(x) + if (x < 1) + fun_l10_n922(x) + else + fun_l10_n986(x) + end +end + +def fun_l9_n762(x) + if (x < 1) + fun_l10_n100(x) + else + fun_l10_n346(x) + end +end + +def fun_l9_n763(x) + if (x < 1) + fun_l10_n738(x) + else + fun_l10_n223(x) + end +end + +def fun_l9_n764(x) + if (x < 1) + fun_l10_n168(x) + else + fun_l10_n367(x) + end +end + +def fun_l9_n765(x) + if (x < 1) + fun_l10_n929(x) + else + fun_l10_n684(x) + end +end + +def fun_l9_n766(x) + if (x < 1) + fun_l10_n940(x) + else + fun_l10_n497(x) + end +end + +def fun_l9_n767(x) + if (x < 1) + fun_l10_n198(x) + else + fun_l10_n386(x) + end +end + +def fun_l9_n768(x) + if (x < 1) + fun_l10_n667(x) + else + fun_l10_n913(x) + end +end + +def fun_l9_n769(x) + if (x < 1) + fun_l10_n210(x) + else + fun_l10_n233(x) + end +end + +def fun_l9_n770(x) + if (x < 1) + fun_l10_n819(x) + else + fun_l10_n755(x) + end +end + +def fun_l9_n771(x) + if (x < 1) + fun_l10_n519(x) + else + fun_l10_n554(x) + end +end + +def fun_l9_n772(x) + if (x < 1) + fun_l10_n880(x) + else + fun_l10_n280(x) + end +end + +def fun_l9_n773(x) + if (x < 1) + fun_l10_n368(x) + else + fun_l10_n97(x) + end +end + +def fun_l9_n774(x) + if (x < 1) + fun_l10_n447(x) + else + fun_l10_n918(x) + end +end + +def fun_l9_n775(x) + if (x < 1) + fun_l10_n222(x) + else + fun_l10_n35(x) + end +end + +def fun_l9_n776(x) + if (x < 1) + fun_l10_n339(x) + else + fun_l10_n309(x) + end +end + +def fun_l9_n777(x) + if (x < 1) + fun_l10_n948(x) + else + fun_l10_n967(x) + end +end + +def fun_l9_n778(x) + if (x < 1) + fun_l10_n561(x) + else + fun_l10_n202(x) + end +end + +def fun_l9_n779(x) + if (x < 1) + fun_l10_n863(x) + else + fun_l10_n356(x) + end +end + +def fun_l9_n780(x) + if (x < 1) + fun_l10_n459(x) + else + fun_l10_n358(x) + end +end + +def fun_l9_n781(x) + if (x < 1) + fun_l10_n543(x) + else + fun_l10_n229(x) + end +end + +def fun_l9_n782(x) + if (x < 1) + fun_l10_n422(x) + else + fun_l10_n448(x) + end +end + +def fun_l9_n783(x) + if (x < 1) + fun_l10_n222(x) + else + fun_l10_n63(x) + end +end + +def fun_l9_n784(x) + if (x < 1) + fun_l10_n520(x) + else + fun_l10_n443(x) + end +end + +def fun_l9_n785(x) + if (x < 1) + fun_l10_n894(x) + else + fun_l10_n379(x) + end +end + +def fun_l9_n786(x) + if (x < 1) + fun_l10_n362(x) + else + fun_l10_n676(x) + end +end + +def fun_l9_n787(x) + if (x < 1) + fun_l10_n545(x) + else + fun_l10_n263(x) + end +end + +def fun_l9_n788(x) + if (x < 1) + fun_l10_n322(x) + else + fun_l10_n631(x) + end +end + +def fun_l9_n789(x) + if (x < 1) + fun_l10_n916(x) + else + fun_l10_n877(x) + end +end + +def fun_l9_n790(x) + if (x < 1) + fun_l10_n443(x) + else + fun_l10_n640(x) + end +end + +def fun_l9_n791(x) + if (x < 1) + fun_l10_n202(x) + else + fun_l10_n686(x) + end +end + +def fun_l9_n792(x) + if (x < 1) + fun_l10_n143(x) + else + fun_l10_n200(x) + end +end + +def fun_l9_n793(x) + if (x < 1) + fun_l10_n939(x) + else + fun_l10_n374(x) + end +end + +def fun_l9_n794(x) + if (x < 1) + fun_l10_n506(x) + else + fun_l10_n782(x) + end +end + +def fun_l9_n795(x) + if (x < 1) + fun_l10_n619(x) + else + fun_l10_n439(x) + end +end + +def fun_l9_n796(x) + if (x < 1) + fun_l10_n748(x) + else + fun_l10_n61(x) + end +end + +def fun_l9_n797(x) + if (x < 1) + fun_l10_n217(x) + else + fun_l10_n816(x) + end +end + +def fun_l9_n798(x) + if (x < 1) + fun_l10_n310(x) + else + fun_l10_n445(x) + end +end + +def fun_l9_n799(x) + if (x < 1) + fun_l10_n262(x) + else + fun_l10_n776(x) + end +end + +def fun_l9_n800(x) + if (x < 1) + fun_l10_n807(x) + else + fun_l10_n566(x) + end +end + +def fun_l9_n801(x) + if (x < 1) + fun_l10_n466(x) + else + fun_l10_n287(x) + end +end + +def fun_l9_n802(x) + if (x < 1) + fun_l10_n205(x) + else + fun_l10_n415(x) + end +end + +def fun_l9_n803(x) + if (x < 1) + fun_l10_n618(x) + else + fun_l10_n87(x) + end +end + +def fun_l9_n804(x) + if (x < 1) + fun_l10_n248(x) + else + fun_l10_n32(x) + end +end + +def fun_l9_n805(x) + if (x < 1) + fun_l10_n537(x) + else + fun_l10_n844(x) + end +end + +def fun_l9_n806(x) + if (x < 1) + fun_l10_n554(x) + else + fun_l10_n696(x) + end +end + +def fun_l9_n807(x) + if (x < 1) + fun_l10_n774(x) + else + fun_l10_n486(x) + end +end + +def fun_l9_n808(x) + if (x < 1) + fun_l10_n500(x) + else + fun_l10_n926(x) + end +end + +def fun_l9_n809(x) + if (x < 1) + fun_l10_n601(x) + else + fun_l10_n696(x) + end +end + +def fun_l9_n810(x) + if (x < 1) + fun_l10_n770(x) + else + fun_l10_n948(x) + end +end + +def fun_l9_n811(x) + if (x < 1) + fun_l10_n658(x) + else + fun_l10_n840(x) + end +end + +def fun_l9_n812(x) + if (x < 1) + fun_l10_n913(x) + else + fun_l10_n892(x) + end +end + +def fun_l9_n813(x) + if (x < 1) + fun_l10_n440(x) + else + fun_l10_n204(x) + end +end + +def fun_l9_n814(x) + if (x < 1) + fun_l10_n273(x) + else + fun_l10_n816(x) + end +end + +def fun_l9_n815(x) + if (x < 1) + fun_l10_n190(x) + else + fun_l10_n735(x) + end +end + +def fun_l9_n816(x) + if (x < 1) + fun_l10_n77(x) + else + fun_l10_n30(x) + end +end + +def fun_l9_n817(x) + if (x < 1) + fun_l10_n697(x) + else + fun_l10_n985(x) + end +end + +def fun_l9_n818(x) + if (x < 1) + fun_l10_n583(x) + else + fun_l10_n314(x) + end +end + +def fun_l9_n819(x) + if (x < 1) + fun_l10_n149(x) + else + fun_l10_n556(x) + end +end + +def fun_l9_n820(x) + if (x < 1) + fun_l10_n634(x) + else + fun_l10_n392(x) + end +end + +def fun_l9_n821(x) + if (x < 1) + fun_l10_n401(x) + else + fun_l10_n217(x) + end +end + +def fun_l9_n822(x) + if (x < 1) + fun_l10_n564(x) + else + fun_l10_n860(x) + end +end + +def fun_l9_n823(x) + if (x < 1) + fun_l10_n901(x) + else + fun_l10_n836(x) + end +end + +def fun_l9_n824(x) + if (x < 1) + fun_l10_n526(x) + else + fun_l10_n660(x) + end +end + +def fun_l9_n825(x) + if (x < 1) + fun_l10_n245(x) + else + fun_l10_n914(x) + end +end + +def fun_l9_n826(x) + if (x < 1) + fun_l10_n712(x) + else + fun_l10_n928(x) + end +end + +def fun_l9_n827(x) + if (x < 1) + fun_l10_n596(x) + else + fun_l10_n803(x) + end +end + +def fun_l9_n828(x) + if (x < 1) + fun_l10_n454(x) + else + fun_l10_n679(x) + end +end + +def fun_l9_n829(x) + if (x < 1) + fun_l10_n104(x) + else + fun_l10_n137(x) + end +end + +def fun_l9_n830(x) + if (x < 1) + fun_l10_n516(x) + else + fun_l10_n687(x) + end +end + +def fun_l9_n831(x) + if (x < 1) + fun_l10_n720(x) + else + fun_l10_n770(x) + end +end + +def fun_l9_n832(x) + if (x < 1) + fun_l10_n939(x) + else + fun_l10_n119(x) + end +end + +def fun_l9_n833(x) + if (x < 1) + fun_l10_n515(x) + else + fun_l10_n71(x) + end +end + +def fun_l9_n834(x) + if (x < 1) + fun_l10_n668(x) + else + fun_l10_n521(x) + end +end + +def fun_l9_n835(x) + if (x < 1) + fun_l10_n405(x) + else + fun_l10_n69(x) + end +end + +def fun_l9_n836(x) + if (x < 1) + fun_l10_n201(x) + else + fun_l10_n681(x) + end +end + +def fun_l9_n837(x) + if (x < 1) + fun_l10_n161(x) + else + fun_l10_n258(x) + end +end + +def fun_l9_n838(x) + if (x < 1) + fun_l10_n913(x) + else + fun_l10_n586(x) + end +end + +def fun_l9_n839(x) + if (x < 1) + fun_l10_n566(x) + else + fun_l10_n543(x) + end +end + +def fun_l9_n840(x) + if (x < 1) + fun_l10_n547(x) + else + fun_l10_n570(x) + end +end + +def fun_l9_n841(x) + if (x < 1) + fun_l10_n888(x) + else + fun_l10_n843(x) + end +end + +def fun_l9_n842(x) + if (x < 1) + fun_l10_n497(x) + else + fun_l10_n985(x) + end +end + +def fun_l9_n843(x) + if (x < 1) + fun_l10_n754(x) + else + fun_l10_n390(x) + end +end + +def fun_l9_n844(x) + if (x < 1) + fun_l10_n625(x) + else + fun_l10_n562(x) + end +end + +def fun_l9_n845(x) + if (x < 1) + fun_l10_n858(x) + else + fun_l10_n553(x) + end +end + +def fun_l9_n846(x) + if (x < 1) + fun_l10_n145(x) + else + fun_l10_n551(x) + end +end + +def fun_l9_n847(x) + if (x < 1) + fun_l10_n916(x) + else + fun_l10_n851(x) + end +end + +def fun_l9_n848(x) + if (x < 1) + fun_l10_n935(x) + else + fun_l10_n448(x) + end +end + +def fun_l9_n849(x) + if (x < 1) + fun_l10_n664(x) + else + fun_l10_n832(x) + end +end + +def fun_l9_n850(x) + if (x < 1) + fun_l10_n904(x) + else + fun_l10_n203(x) + end +end + +def fun_l9_n851(x) + if (x < 1) + fun_l10_n863(x) + else + fun_l10_n491(x) + end +end + +def fun_l9_n852(x) + if (x < 1) + fun_l10_n930(x) + else + fun_l10_n248(x) + end +end + +def fun_l9_n853(x) + if (x < 1) + fun_l10_n637(x) + else + fun_l10_n716(x) + end +end + +def fun_l9_n854(x) + if (x < 1) + fun_l10_n35(x) + else + fun_l10_n662(x) + end +end + +def fun_l9_n855(x) + if (x < 1) + fun_l10_n57(x) + else + fun_l10_n392(x) + end +end + +def fun_l9_n856(x) + if (x < 1) + fun_l10_n480(x) + else + fun_l10_n447(x) + end +end + +def fun_l9_n857(x) + if (x < 1) + fun_l10_n134(x) + else + fun_l10_n842(x) + end +end + +def fun_l9_n858(x) + if (x < 1) + fun_l10_n384(x) + else + fun_l10_n577(x) + end +end + +def fun_l9_n859(x) + if (x < 1) + fun_l10_n718(x) + else + fun_l10_n571(x) + end +end + +def fun_l9_n860(x) + if (x < 1) + fun_l10_n237(x) + else + fun_l10_n654(x) + end +end + +def fun_l9_n861(x) + if (x < 1) + fun_l10_n807(x) + else + fun_l10_n409(x) + end +end + +def fun_l9_n862(x) + if (x < 1) + fun_l10_n801(x) + else + fun_l10_n575(x) + end +end + +def fun_l9_n863(x) + if (x < 1) + fun_l10_n500(x) + else + fun_l10_n133(x) + end +end + +def fun_l9_n864(x) + if (x < 1) + fun_l10_n403(x) + else + fun_l10_n720(x) + end +end + +def fun_l9_n865(x) + if (x < 1) + fun_l10_n648(x) + else + fun_l10_n677(x) + end +end + +def fun_l9_n866(x) + if (x < 1) + fun_l10_n873(x) + else + fun_l10_n519(x) + end +end + +def fun_l9_n867(x) + if (x < 1) + fun_l10_n459(x) + else + fun_l10_n331(x) + end +end + +def fun_l9_n868(x) + if (x < 1) + fun_l10_n159(x) + else + fun_l10_n64(x) + end +end + +def fun_l9_n869(x) + if (x < 1) + fun_l10_n155(x) + else + fun_l10_n41(x) + end +end + +def fun_l9_n870(x) + if (x < 1) + fun_l10_n947(x) + else + fun_l10_n386(x) + end +end + +def fun_l9_n871(x) + if (x < 1) + fun_l10_n868(x) + else + fun_l10_n794(x) + end +end + +def fun_l9_n872(x) + if (x < 1) + fun_l10_n77(x) + else + fun_l10_n268(x) + end +end + +def fun_l9_n873(x) + if (x < 1) + fun_l10_n119(x) + else + fun_l10_n819(x) + end +end + +def fun_l9_n874(x) + if (x < 1) + fun_l10_n143(x) + else + fun_l10_n434(x) + end +end + +def fun_l9_n875(x) + if (x < 1) + fun_l10_n238(x) + else + fun_l10_n489(x) + end +end + +def fun_l9_n876(x) + if (x < 1) + fun_l10_n687(x) + else + fun_l10_n384(x) + end +end + +def fun_l9_n877(x) + if (x < 1) + fun_l10_n27(x) + else + fun_l10_n138(x) + end +end + +def fun_l9_n878(x) + if (x < 1) + fun_l10_n208(x) + else + fun_l10_n691(x) + end +end + +def fun_l9_n879(x) + if (x < 1) + fun_l10_n793(x) + else + fun_l10_n165(x) + end +end + +def fun_l9_n880(x) + if (x < 1) + fun_l10_n358(x) + else + fun_l10_n455(x) + end +end + +def fun_l9_n881(x) + if (x < 1) + fun_l10_n558(x) + else + fun_l10_n184(x) + end +end + +def fun_l9_n882(x) + if (x < 1) + fun_l10_n461(x) + else + fun_l10_n155(x) + end +end + +def fun_l9_n883(x) + if (x < 1) + fun_l10_n503(x) + else + fun_l10_n225(x) + end +end + +def fun_l9_n884(x) + if (x < 1) + fun_l10_n384(x) + else + fun_l10_n262(x) + end +end + +def fun_l9_n885(x) + if (x < 1) + fun_l10_n565(x) + else + fun_l10_n633(x) + end +end + +def fun_l9_n886(x) + if (x < 1) + fun_l10_n626(x) + else + fun_l10_n796(x) + end +end + +def fun_l9_n887(x) + if (x < 1) + fun_l10_n424(x) + else + fun_l10_n458(x) + end +end + +def fun_l9_n888(x) + if (x < 1) + fun_l10_n687(x) + else + fun_l10_n145(x) + end +end + +def fun_l9_n889(x) + if (x < 1) + fun_l10_n787(x) + else + fun_l10_n225(x) + end +end + +def fun_l9_n890(x) + if (x < 1) + fun_l10_n249(x) + else + fun_l10_n154(x) + end +end + +def fun_l9_n891(x) + if (x < 1) + fun_l10_n38(x) + else + fun_l10_n635(x) + end +end + +def fun_l9_n892(x) + if (x < 1) + fun_l10_n920(x) + else + fun_l10_n478(x) + end +end + +def fun_l9_n893(x) + if (x < 1) + fun_l10_n13(x) + else + fun_l10_n174(x) + end +end + +def fun_l9_n894(x) + if (x < 1) + fun_l10_n304(x) + else + fun_l10_n495(x) + end +end + +def fun_l9_n895(x) + if (x < 1) + fun_l10_n226(x) + else + fun_l10_n420(x) + end +end + +def fun_l9_n896(x) + if (x < 1) + fun_l10_n86(x) + else + fun_l10_n837(x) + end +end + +def fun_l9_n897(x) + if (x < 1) + fun_l10_n927(x) + else + fun_l10_n344(x) + end +end + +def fun_l9_n898(x) + if (x < 1) + fun_l10_n87(x) + else + fun_l10_n270(x) + end +end + +def fun_l9_n899(x) + if (x < 1) + fun_l10_n549(x) + else + fun_l10_n349(x) + end +end + +def fun_l9_n900(x) + if (x < 1) + fun_l10_n456(x) + else + fun_l10_n345(x) + end +end + +def fun_l9_n901(x) + if (x < 1) + fun_l10_n154(x) + else + fun_l10_n764(x) + end +end + +def fun_l9_n902(x) + if (x < 1) + fun_l10_n614(x) + else + fun_l10_n536(x) + end +end + +def fun_l9_n903(x) + if (x < 1) + fun_l10_n108(x) + else + fun_l10_n197(x) + end +end + +def fun_l9_n904(x) + if (x < 1) + fun_l10_n616(x) + else + fun_l10_n777(x) + end +end + +def fun_l9_n905(x) + if (x < 1) + fun_l10_n515(x) + else + fun_l10_n830(x) + end +end + +def fun_l9_n906(x) + if (x < 1) + fun_l10_n288(x) + else + fun_l10_n717(x) + end +end + +def fun_l9_n907(x) + if (x < 1) + fun_l10_n704(x) + else + fun_l10_n962(x) + end +end + +def fun_l9_n908(x) + if (x < 1) + fun_l10_n85(x) + else + fun_l10_n70(x) + end +end + +def fun_l9_n909(x) + if (x < 1) + fun_l10_n806(x) + else + fun_l10_n97(x) + end +end + +def fun_l9_n910(x) + if (x < 1) + fun_l10_n567(x) + else + fun_l10_n47(x) + end +end + +def fun_l9_n911(x) + if (x < 1) + fun_l10_n919(x) + else + fun_l10_n879(x) + end +end + +def fun_l9_n912(x) + if (x < 1) + fun_l10_n229(x) + else + fun_l10_n200(x) + end +end + +def fun_l9_n913(x) + if (x < 1) + fun_l10_n502(x) + else + fun_l10_n820(x) + end +end + +def fun_l9_n914(x) + if (x < 1) + fun_l10_n57(x) + else + fun_l10_n470(x) + end +end + +def fun_l9_n915(x) + if (x < 1) + fun_l10_n909(x) + else + fun_l10_n845(x) + end +end + +def fun_l9_n916(x) + if (x < 1) + fun_l10_n658(x) + else + fun_l10_n925(x) + end +end + +def fun_l9_n917(x) + if (x < 1) + fun_l10_n886(x) + else + fun_l10_n285(x) + end +end + +def fun_l9_n918(x) + if (x < 1) + fun_l10_n484(x) + else + fun_l10_n712(x) + end +end + +def fun_l9_n919(x) + if (x < 1) + fun_l10_n299(x) + else + fun_l10_n144(x) + end +end + +def fun_l9_n920(x) + if (x < 1) + fun_l10_n830(x) + else + fun_l10_n913(x) + end +end + +def fun_l9_n921(x) + if (x < 1) + fun_l10_n306(x) + else + fun_l10_n242(x) + end +end + +def fun_l9_n922(x) + if (x < 1) + fun_l10_n442(x) + else + fun_l10_n497(x) + end +end + +def fun_l9_n923(x) + if (x < 1) + fun_l10_n22(x) + else + fun_l10_n376(x) + end +end + +def fun_l9_n924(x) + if (x < 1) + fun_l10_n737(x) + else + fun_l10_n603(x) + end +end + +def fun_l9_n925(x) + if (x < 1) + fun_l10_n300(x) + else + fun_l10_n974(x) + end +end + +def fun_l9_n926(x) + if (x < 1) + fun_l10_n644(x) + else + fun_l10_n973(x) + end +end + +def fun_l9_n927(x) + if (x < 1) + fun_l10_n413(x) + else + fun_l10_n353(x) + end +end + +def fun_l9_n928(x) + if (x < 1) + fun_l10_n438(x) + else + fun_l10_n518(x) + end +end + +def fun_l9_n929(x) + if (x < 1) + fun_l10_n30(x) + else + fun_l10_n207(x) + end +end + +def fun_l9_n930(x) + if (x < 1) + fun_l10_n976(x) + else + fun_l10_n70(x) + end +end + +def fun_l9_n931(x) + if (x < 1) + fun_l10_n5(x) + else + fun_l10_n37(x) + end +end + +def fun_l9_n932(x) + if (x < 1) + fun_l10_n612(x) + else + fun_l10_n268(x) + end +end + +def fun_l9_n933(x) + if (x < 1) + fun_l10_n81(x) + else + fun_l10_n373(x) + end +end + +def fun_l9_n934(x) + if (x < 1) + fun_l10_n30(x) + else + fun_l10_n504(x) + end +end + +def fun_l9_n935(x) + if (x < 1) + fun_l10_n131(x) + else + fun_l10_n617(x) + end +end + +def fun_l9_n936(x) + if (x < 1) + fun_l10_n114(x) + else + fun_l10_n883(x) + end +end + +def fun_l9_n937(x) + if (x < 1) + fun_l10_n859(x) + else + fun_l10_n788(x) + end +end + +def fun_l9_n938(x) + if (x < 1) + fun_l10_n993(x) + else + fun_l10_n349(x) + end +end + +def fun_l9_n939(x) + if (x < 1) + fun_l10_n775(x) + else + fun_l10_n195(x) + end +end + +def fun_l9_n940(x) + if (x < 1) + fun_l10_n829(x) + else + fun_l10_n398(x) + end +end + +def fun_l9_n941(x) + if (x < 1) + fun_l10_n906(x) + else + fun_l10_n529(x) + end +end + +def fun_l9_n942(x) + if (x < 1) + fun_l10_n965(x) + else + fun_l10_n372(x) + end +end + +def fun_l9_n943(x) + if (x < 1) + fun_l10_n953(x) + else + fun_l10_n397(x) + end +end + +def fun_l9_n944(x) + if (x < 1) + fun_l10_n984(x) + else + fun_l10_n909(x) + end +end + +def fun_l9_n945(x) + if (x < 1) + fun_l10_n649(x) + else + fun_l10_n304(x) + end +end + +def fun_l9_n946(x) + if (x < 1) + fun_l10_n0(x) + else + fun_l10_n922(x) + end +end + +def fun_l9_n947(x) + if (x < 1) + fun_l10_n460(x) + else + fun_l10_n215(x) + end +end + +def fun_l9_n948(x) + if (x < 1) + fun_l10_n251(x) + else + fun_l10_n636(x) + end +end + +def fun_l9_n949(x) + if (x < 1) + fun_l10_n14(x) + else + fun_l10_n494(x) + end +end + +def fun_l9_n950(x) + if (x < 1) + fun_l10_n6(x) + else + fun_l10_n523(x) + end +end + +def fun_l9_n951(x) + if (x < 1) + fun_l10_n705(x) + else + fun_l10_n689(x) + end +end + +def fun_l9_n952(x) + if (x < 1) + fun_l10_n830(x) + else + fun_l10_n374(x) + end +end + +def fun_l9_n953(x) + if (x < 1) + fun_l10_n451(x) + else + fun_l10_n87(x) + end +end + +def fun_l9_n954(x) + if (x < 1) + fun_l10_n202(x) + else + fun_l10_n753(x) + end +end + +def fun_l9_n955(x) + if (x < 1) + fun_l10_n384(x) + else + fun_l10_n216(x) + end +end + +def fun_l9_n956(x) + if (x < 1) + fun_l10_n381(x) + else + fun_l10_n727(x) + end +end + +def fun_l9_n957(x) + if (x < 1) + fun_l10_n876(x) + else + fun_l10_n760(x) + end +end + +def fun_l9_n958(x) + if (x < 1) + fun_l10_n975(x) + else + fun_l10_n372(x) + end +end + +def fun_l9_n959(x) + if (x < 1) + fun_l10_n714(x) + else + fun_l10_n680(x) + end +end + +def fun_l9_n960(x) + if (x < 1) + fun_l10_n733(x) + else + fun_l10_n508(x) + end +end + +def fun_l9_n961(x) + if (x < 1) + fun_l10_n319(x) + else + fun_l10_n90(x) + end +end + +def fun_l9_n962(x) + if (x < 1) + fun_l10_n964(x) + else + fun_l10_n282(x) + end +end + +def fun_l9_n963(x) + if (x < 1) + fun_l10_n179(x) + else + fun_l10_n324(x) + end +end + +def fun_l9_n964(x) + if (x < 1) + fun_l10_n627(x) + else + fun_l10_n627(x) + end +end + +def fun_l9_n965(x) + if (x < 1) + fun_l10_n7(x) + else + fun_l10_n375(x) + end +end + +def fun_l9_n966(x) + if (x < 1) + fun_l10_n960(x) + else + fun_l10_n272(x) + end +end + +def fun_l9_n967(x) + if (x < 1) + fun_l10_n869(x) + else + fun_l10_n737(x) + end +end + +def fun_l9_n968(x) + if (x < 1) + fun_l10_n621(x) + else + fun_l10_n413(x) + end +end + +def fun_l9_n969(x) + if (x < 1) + fun_l10_n258(x) + else + fun_l10_n105(x) + end +end + +def fun_l9_n970(x) + if (x < 1) + fun_l10_n817(x) + else + fun_l10_n519(x) + end +end + +def fun_l9_n971(x) + if (x < 1) + fun_l10_n462(x) + else + fun_l10_n335(x) + end +end + +def fun_l9_n972(x) + if (x < 1) + fun_l10_n770(x) + else + fun_l10_n856(x) + end +end + +def fun_l9_n973(x) + if (x < 1) + fun_l10_n607(x) + else + fun_l10_n142(x) + end +end + +def fun_l9_n974(x) + if (x < 1) + fun_l10_n498(x) + else + fun_l10_n373(x) + end +end + +def fun_l9_n975(x) + if (x < 1) + fun_l10_n239(x) + else + fun_l10_n895(x) + end +end + +def fun_l9_n976(x) + if (x < 1) + fun_l10_n312(x) + else + fun_l10_n489(x) + end +end + +def fun_l9_n977(x) + if (x < 1) + fun_l10_n595(x) + else + fun_l10_n674(x) + end +end + +def fun_l9_n978(x) + if (x < 1) + fun_l10_n928(x) + else + fun_l10_n774(x) + end +end + +def fun_l9_n979(x) + if (x < 1) + fun_l10_n964(x) + else + fun_l10_n860(x) + end +end + +def fun_l9_n980(x) + if (x < 1) + fun_l10_n63(x) + else + fun_l10_n115(x) + end +end + +def fun_l9_n981(x) + if (x < 1) + fun_l10_n930(x) + else + fun_l10_n559(x) + end +end + +def fun_l9_n982(x) + if (x < 1) + fun_l10_n391(x) + else + fun_l10_n411(x) + end +end + +def fun_l9_n983(x) + if (x < 1) + fun_l10_n71(x) + else + fun_l10_n632(x) + end +end + +def fun_l9_n984(x) + if (x < 1) + fun_l10_n613(x) + else + fun_l10_n218(x) + end +end + +def fun_l9_n985(x) + if (x < 1) + fun_l10_n263(x) + else + fun_l10_n858(x) + end +end + +def fun_l9_n986(x) + if (x < 1) + fun_l10_n974(x) + else + fun_l10_n824(x) + end +end + +def fun_l9_n987(x) + if (x < 1) + fun_l10_n636(x) + else + fun_l10_n55(x) + end +end + +def fun_l9_n988(x) + if (x < 1) + fun_l10_n367(x) + else + fun_l10_n878(x) + end +end + +def fun_l9_n989(x) + if (x < 1) + fun_l10_n316(x) + else + fun_l10_n800(x) + end +end + +def fun_l9_n990(x) + if (x < 1) + fun_l10_n581(x) + else + fun_l10_n511(x) + end +end + +def fun_l9_n991(x) + if (x < 1) + fun_l10_n667(x) + else + fun_l10_n566(x) + end +end + +def fun_l9_n992(x) + if (x < 1) + fun_l10_n144(x) + else + fun_l10_n51(x) + end +end + +def fun_l9_n993(x) + if (x < 1) + fun_l10_n652(x) + else + fun_l10_n436(x) + end +end + +def fun_l9_n994(x) + if (x < 1) + fun_l10_n283(x) + else + fun_l10_n480(x) + end +end + +def fun_l9_n995(x) + if (x < 1) + fun_l10_n908(x) + else + fun_l10_n86(x) + end +end + +def fun_l9_n996(x) + if (x < 1) + fun_l10_n43(x) + else + fun_l10_n466(x) + end +end + +def fun_l9_n997(x) + if (x < 1) + fun_l10_n968(x) + else + fun_l10_n97(x) + end +end + +def fun_l9_n998(x) + if (x < 1) + fun_l10_n38(x) + else + fun_l10_n78(x) + end +end + +def fun_l9_n999(x) + if (x < 1) + fun_l10_n947(x) + else + fun_l10_n322(x) + end +end + +def fun_l10_n0(x) + if (x < 1) + fun_l11_n424(x) + else + fun_l11_n206(x) + end +end + +def fun_l10_n1(x) + if (x < 1) + fun_l11_n263(x) + else + fun_l11_n886(x) + end +end + +def fun_l10_n2(x) + if (x < 1) + fun_l11_n31(x) + else + fun_l11_n693(x) + end +end + +def fun_l10_n3(x) + if (x < 1) + fun_l11_n924(x) + else + fun_l11_n585(x) + end +end + +def fun_l10_n4(x) + if (x < 1) + fun_l11_n552(x) + else + fun_l11_n904(x) + end +end + +def fun_l10_n5(x) + if (x < 1) + fun_l11_n912(x) + else + fun_l11_n127(x) + end +end + +def fun_l10_n6(x) + if (x < 1) + fun_l11_n284(x) + else + fun_l11_n952(x) + end +end + +def fun_l10_n7(x) + if (x < 1) + fun_l11_n294(x) + else + fun_l11_n527(x) + end +end + +def fun_l10_n8(x) + if (x < 1) + fun_l11_n675(x) + else + fun_l11_n457(x) + end +end + +def fun_l10_n9(x) + if (x < 1) + fun_l11_n908(x) + else + fun_l11_n963(x) + end +end + +def fun_l10_n10(x) + if (x < 1) + fun_l11_n361(x) + else + fun_l11_n839(x) + end +end + +def fun_l10_n11(x) + if (x < 1) + fun_l11_n402(x) + else + fun_l11_n228(x) + end +end + +def fun_l10_n12(x) + if (x < 1) + fun_l11_n871(x) + else + fun_l11_n194(x) + end +end + +def fun_l10_n13(x) + if (x < 1) + fun_l11_n255(x) + else + fun_l11_n816(x) + end +end + +def fun_l10_n14(x) + if (x < 1) + fun_l11_n987(x) + else + fun_l11_n870(x) + end +end + +def fun_l10_n15(x) + if (x < 1) + fun_l11_n538(x) + else + fun_l11_n837(x) + end +end + +def fun_l10_n16(x) + if (x < 1) + fun_l11_n205(x) + else + fun_l11_n831(x) + end +end + +def fun_l10_n17(x) + if (x < 1) + fun_l11_n737(x) + else + fun_l11_n242(x) + end +end + +def fun_l10_n18(x) + if (x < 1) + fun_l11_n18(x) + else + fun_l11_n103(x) + end +end + +def fun_l10_n19(x) + if (x < 1) + fun_l11_n928(x) + else + fun_l11_n300(x) + end +end + +def fun_l10_n20(x) + if (x < 1) + fun_l11_n816(x) + else + fun_l11_n225(x) + end +end + +def fun_l10_n21(x) + if (x < 1) + fun_l11_n52(x) + else + fun_l11_n901(x) + end +end + +def fun_l10_n22(x) + if (x < 1) + fun_l11_n316(x) + else + fun_l11_n556(x) + end +end + +def fun_l10_n23(x) + if (x < 1) + fun_l11_n103(x) + else + fun_l11_n223(x) + end +end + +def fun_l10_n24(x) + if (x < 1) + fun_l11_n14(x) + else + fun_l11_n875(x) + end +end + +def fun_l10_n25(x) + if (x < 1) + fun_l11_n359(x) + else + fun_l11_n504(x) + end +end + +def fun_l10_n26(x) + if (x < 1) + fun_l11_n416(x) + else + fun_l11_n172(x) + end +end + +def fun_l10_n27(x) + if (x < 1) + fun_l11_n142(x) + else + fun_l11_n238(x) + end +end + +def fun_l10_n28(x) + if (x < 1) + fun_l11_n319(x) + else + fun_l11_n350(x) + end +end + +def fun_l10_n29(x) + if (x < 1) + fun_l11_n53(x) + else + fun_l11_n162(x) + end +end + +def fun_l10_n30(x) + if (x < 1) + fun_l11_n121(x) + else + fun_l11_n39(x) + end +end + +def fun_l10_n31(x) + if (x < 1) + fun_l11_n447(x) + else + fun_l11_n259(x) + end +end + +def fun_l10_n32(x) + if (x < 1) + fun_l11_n931(x) + else + fun_l11_n571(x) + end +end + +def fun_l10_n33(x) + if (x < 1) + fun_l11_n705(x) + else + fun_l11_n544(x) + end +end + +def fun_l10_n34(x) + if (x < 1) + fun_l11_n990(x) + else + fun_l11_n695(x) + end +end + +def fun_l10_n35(x) + if (x < 1) + fun_l11_n197(x) + else + fun_l11_n391(x) + end +end + +def fun_l10_n36(x) + if (x < 1) + fun_l11_n686(x) + else + fun_l11_n785(x) + end +end + +def fun_l10_n37(x) + if (x < 1) + fun_l11_n466(x) + else + fun_l11_n783(x) + end +end + +def fun_l10_n38(x) + if (x < 1) + fun_l11_n351(x) + else + fun_l11_n732(x) + end +end + +def fun_l10_n39(x) + if (x < 1) + fun_l11_n22(x) + else + fun_l11_n995(x) + end +end + +def fun_l10_n40(x) + if (x < 1) + fun_l11_n264(x) + else + fun_l11_n662(x) + end +end + +def fun_l10_n41(x) + if (x < 1) + fun_l11_n91(x) + else + fun_l11_n673(x) + end +end + +def fun_l10_n42(x) + if (x < 1) + fun_l11_n993(x) + else + fun_l11_n839(x) + end +end + +def fun_l10_n43(x) + if (x < 1) + fun_l11_n158(x) + else + fun_l11_n774(x) + end +end + +def fun_l10_n44(x) + if (x < 1) + fun_l11_n977(x) + else + fun_l11_n321(x) + end +end + +def fun_l10_n45(x) + if (x < 1) + fun_l11_n121(x) + else + fun_l11_n184(x) + end +end + +def fun_l10_n46(x) + if (x < 1) + fun_l11_n446(x) + else + fun_l11_n426(x) + end +end + +def fun_l10_n47(x) + if (x < 1) + fun_l11_n524(x) + else + fun_l11_n123(x) + end +end + +def fun_l10_n48(x) + if (x < 1) + fun_l11_n435(x) + else + fun_l11_n560(x) + end +end + +def fun_l10_n49(x) + if (x < 1) + fun_l11_n94(x) + else + fun_l11_n731(x) + end +end + +def fun_l10_n50(x) + if (x < 1) + fun_l11_n177(x) + else + fun_l11_n902(x) + end +end + +def fun_l10_n51(x) + if (x < 1) + fun_l11_n648(x) + else + fun_l11_n807(x) + end +end + +def fun_l10_n52(x) + if (x < 1) + fun_l11_n414(x) + else + fun_l11_n335(x) + end +end + +def fun_l10_n53(x) + if (x < 1) + fun_l11_n754(x) + else + fun_l11_n789(x) + end +end + +def fun_l10_n54(x) + if (x < 1) + fun_l11_n843(x) + else + fun_l11_n980(x) + end +end + +def fun_l10_n55(x) + if (x < 1) + fun_l11_n706(x) + else + fun_l11_n160(x) + end +end + +def fun_l10_n56(x) + if (x < 1) + fun_l11_n564(x) + else + fun_l11_n672(x) + end +end + +def fun_l10_n57(x) + if (x < 1) + fun_l11_n158(x) + else + fun_l11_n154(x) + end +end + +def fun_l10_n58(x) + if (x < 1) + fun_l11_n120(x) + else + fun_l11_n970(x) + end +end + +def fun_l10_n59(x) + if (x < 1) + fun_l11_n561(x) + else + fun_l11_n872(x) + end +end + +def fun_l10_n60(x) + if (x < 1) + fun_l11_n93(x) + else + fun_l11_n723(x) + end +end + +def fun_l10_n61(x) + if (x < 1) + fun_l11_n921(x) + else + fun_l11_n578(x) + end +end + +def fun_l10_n62(x) + if (x < 1) + fun_l11_n527(x) + else + fun_l11_n118(x) + end +end + +def fun_l10_n63(x) + if (x < 1) + fun_l11_n225(x) + else + fun_l11_n937(x) + end +end + +def fun_l10_n64(x) + if (x < 1) + fun_l11_n634(x) + else + fun_l11_n415(x) + end +end + +def fun_l10_n65(x) + if (x < 1) + fun_l11_n718(x) + else + fun_l11_n958(x) + end +end + +def fun_l10_n66(x) + if (x < 1) + fun_l11_n972(x) + else + fun_l11_n453(x) + end +end + +def fun_l10_n67(x) + if (x < 1) + fun_l11_n85(x) + else + fun_l11_n934(x) + end +end + +def fun_l10_n68(x) + if (x < 1) + fun_l11_n386(x) + else + fun_l11_n138(x) + end +end + +def fun_l10_n69(x) + if (x < 1) + fun_l11_n312(x) + else + fun_l11_n62(x) + end +end + +def fun_l10_n70(x) + if (x < 1) + fun_l11_n591(x) + else + fun_l11_n906(x) + end +end + +def fun_l10_n71(x) + if (x < 1) + fun_l11_n571(x) + else + fun_l11_n429(x) + end +end + +def fun_l10_n72(x) + if (x < 1) + fun_l11_n996(x) + else + fun_l11_n932(x) + end +end + +def fun_l10_n73(x) + if (x < 1) + fun_l11_n691(x) + else + fun_l11_n116(x) + end +end + +def fun_l10_n74(x) + if (x < 1) + fun_l11_n670(x) + else + fun_l11_n865(x) + end +end + +def fun_l10_n75(x) + if (x < 1) + fun_l11_n568(x) + else + fun_l11_n164(x) + end +end + +def fun_l10_n76(x) + if (x < 1) + fun_l11_n747(x) + else + fun_l11_n235(x) + end +end + +def fun_l10_n77(x) + if (x < 1) + fun_l11_n402(x) + else + fun_l11_n670(x) + end +end + +def fun_l10_n78(x) + if (x < 1) + fun_l11_n525(x) + else + fun_l11_n675(x) + end +end + +def fun_l10_n79(x) + if (x < 1) + fun_l11_n6(x) + else + fun_l11_n238(x) + end +end + +def fun_l10_n80(x) + if (x < 1) + fun_l11_n905(x) + else + fun_l11_n170(x) + end +end + +def fun_l10_n81(x) + if (x < 1) + fun_l11_n610(x) + else + fun_l11_n527(x) + end +end + +def fun_l10_n82(x) + if (x < 1) + fun_l11_n796(x) + else + fun_l11_n749(x) + end +end + +def fun_l10_n83(x) + if (x < 1) + fun_l11_n634(x) + else + fun_l11_n49(x) + end +end + +def fun_l10_n84(x) + if (x < 1) + fun_l11_n376(x) + else + fun_l11_n852(x) + end +end + +def fun_l10_n85(x) + if (x < 1) + fun_l11_n593(x) + else + fun_l11_n752(x) + end +end + +def fun_l10_n86(x) + if (x < 1) + fun_l11_n821(x) + else + fun_l11_n892(x) + end +end + +def fun_l10_n87(x) + if (x < 1) + fun_l11_n950(x) + else + fun_l11_n309(x) + end +end + +def fun_l10_n88(x) + if (x < 1) + fun_l11_n360(x) + else + fun_l11_n134(x) + end +end + +def fun_l10_n89(x) + if (x < 1) + fun_l11_n935(x) + else + fun_l11_n241(x) + end +end + +def fun_l10_n90(x) + if (x < 1) + fun_l11_n524(x) + else + fun_l11_n120(x) + end +end + +def fun_l10_n91(x) + if (x < 1) + fun_l11_n25(x) + else + fun_l11_n357(x) + end +end + +def fun_l10_n92(x) + if (x < 1) + fun_l11_n248(x) + else + fun_l11_n212(x) + end +end + +def fun_l10_n93(x) + if (x < 1) + fun_l11_n860(x) + else + fun_l11_n733(x) + end +end + +def fun_l10_n94(x) + if (x < 1) + fun_l11_n147(x) + else + fun_l11_n907(x) + end +end + +def fun_l10_n95(x) + if (x < 1) + fun_l11_n758(x) + else + fun_l11_n62(x) + end +end + +def fun_l10_n96(x) + if (x < 1) + fun_l11_n205(x) + else + fun_l11_n54(x) + end +end + +def fun_l10_n97(x) + if (x < 1) + fun_l11_n8(x) + else + fun_l11_n813(x) + end +end + +def fun_l10_n98(x) + if (x < 1) + fun_l11_n296(x) + else + fun_l11_n693(x) + end +end + +def fun_l10_n99(x) + if (x < 1) + fun_l11_n181(x) + else + fun_l11_n709(x) + end +end + +def fun_l10_n100(x) + if (x < 1) + fun_l11_n109(x) + else + fun_l11_n560(x) + end +end + +def fun_l10_n101(x) + if (x < 1) + fun_l11_n290(x) + else + fun_l11_n693(x) + end +end + +def fun_l10_n102(x) + if (x < 1) + fun_l11_n826(x) + else + fun_l11_n813(x) + end +end + +def fun_l10_n103(x) + if (x < 1) + fun_l11_n3(x) + else + fun_l11_n787(x) + end +end + +def fun_l10_n104(x) + if (x < 1) + fun_l11_n477(x) + else + fun_l11_n336(x) + end +end + +def fun_l10_n105(x) + if (x < 1) + fun_l11_n131(x) + else + fun_l11_n500(x) + end +end + +def fun_l10_n106(x) + if (x < 1) + fun_l11_n278(x) + else + fun_l11_n948(x) + end +end + +def fun_l10_n107(x) + if (x < 1) + fun_l11_n950(x) + else + fun_l11_n848(x) + end +end + +def fun_l10_n108(x) + if (x < 1) + fun_l11_n490(x) + else + fun_l11_n1(x) + end +end + +def fun_l10_n109(x) + if (x < 1) + fun_l11_n297(x) + else + fun_l11_n902(x) + end +end + +def fun_l10_n110(x) + if (x < 1) + fun_l11_n808(x) + else + fun_l11_n697(x) + end +end + +def fun_l10_n111(x) + if (x < 1) + fun_l11_n330(x) + else + fun_l11_n424(x) + end +end + +def fun_l10_n112(x) + if (x < 1) + fun_l11_n254(x) + else + fun_l11_n662(x) + end +end + +def fun_l10_n113(x) + if (x < 1) + fun_l11_n811(x) + else + fun_l11_n196(x) + end +end + +def fun_l10_n114(x) + if (x < 1) + fun_l11_n868(x) + else + fun_l11_n812(x) + end +end + +def fun_l10_n115(x) + if (x < 1) + fun_l11_n308(x) + else + fun_l11_n184(x) + end +end + +def fun_l10_n116(x) + if (x < 1) + fun_l11_n64(x) + else + fun_l11_n906(x) + end +end + +def fun_l10_n117(x) + if (x < 1) + fun_l11_n339(x) + else + fun_l11_n338(x) + end +end + +def fun_l10_n118(x) + if (x < 1) + fun_l11_n993(x) + else + fun_l11_n915(x) + end +end + +def fun_l10_n119(x) + if (x < 1) + fun_l11_n729(x) + else + fun_l11_n472(x) + end +end + +def fun_l10_n120(x) + if (x < 1) + fun_l11_n646(x) + else + fun_l11_n83(x) + end +end + +def fun_l10_n121(x) + if (x < 1) + fun_l11_n294(x) + else + fun_l11_n208(x) + end +end + +def fun_l10_n122(x) + if (x < 1) + fun_l11_n309(x) + else + fun_l11_n52(x) + end +end + +def fun_l10_n123(x) + if (x < 1) + fun_l11_n5(x) + else + fun_l11_n124(x) + end +end + +def fun_l10_n124(x) + if (x < 1) + fun_l11_n288(x) + else + fun_l11_n731(x) + end +end + +def fun_l10_n125(x) + if (x < 1) + fun_l11_n835(x) + else + fun_l11_n381(x) + end +end + +def fun_l10_n126(x) + if (x < 1) + fun_l11_n269(x) + else + fun_l11_n104(x) + end +end + +def fun_l10_n127(x) + if (x < 1) + fun_l11_n377(x) + else + fun_l11_n650(x) + end +end + +def fun_l10_n128(x) + if (x < 1) + fun_l11_n749(x) + else + fun_l11_n223(x) + end +end + +def fun_l10_n129(x) + if (x < 1) + fun_l11_n493(x) + else + fun_l11_n834(x) + end +end + +def fun_l10_n130(x) + if (x < 1) + fun_l11_n826(x) + else + fun_l11_n857(x) + end +end + +def fun_l10_n131(x) + if (x < 1) + fun_l11_n19(x) + else + fun_l11_n932(x) + end +end + +def fun_l10_n132(x) + if (x < 1) + fun_l11_n585(x) + else + fun_l11_n13(x) + end +end + +def fun_l10_n133(x) + if (x < 1) + fun_l11_n91(x) + else + fun_l11_n748(x) + end +end + +def fun_l10_n134(x) + if (x < 1) + fun_l11_n218(x) + else + fun_l11_n343(x) + end +end + +def fun_l10_n135(x) + if (x < 1) + fun_l11_n386(x) + else + fun_l11_n655(x) + end +end + +def fun_l10_n136(x) + if (x < 1) + fun_l11_n43(x) + else + fun_l11_n964(x) + end +end + +def fun_l10_n137(x) + if (x < 1) + fun_l11_n50(x) + else + fun_l11_n836(x) + end +end + +def fun_l10_n138(x) + if (x < 1) + fun_l11_n915(x) + else + fun_l11_n262(x) + end +end + +def fun_l10_n139(x) + if (x < 1) + fun_l11_n187(x) + else + fun_l11_n321(x) + end +end + +def fun_l10_n140(x) + if (x < 1) + fun_l11_n473(x) + else + fun_l11_n771(x) + end +end + +def fun_l10_n141(x) + if (x < 1) + fun_l11_n125(x) + else + fun_l11_n118(x) + end +end + +def fun_l10_n142(x) + if (x < 1) + fun_l11_n993(x) + else + fun_l11_n178(x) + end +end + +def fun_l10_n143(x) + if (x < 1) + fun_l11_n223(x) + else + fun_l11_n509(x) + end +end + +def fun_l10_n144(x) + if (x < 1) + fun_l11_n62(x) + else + fun_l11_n455(x) + end +end + +def fun_l10_n145(x) + if (x < 1) + fun_l11_n155(x) + else + fun_l11_n486(x) + end +end + +def fun_l10_n146(x) + if (x < 1) + fun_l11_n414(x) + else + fun_l11_n384(x) + end +end + +def fun_l10_n147(x) + if (x < 1) + fun_l11_n840(x) + else + fun_l11_n287(x) + end +end + +def fun_l10_n148(x) + if (x < 1) + fun_l11_n605(x) + else + fun_l11_n283(x) + end +end + +def fun_l10_n149(x) + if (x < 1) + fun_l11_n101(x) + else + fun_l11_n710(x) + end +end + +def fun_l10_n150(x) + if (x < 1) + fun_l11_n51(x) + else + fun_l11_n304(x) + end +end + +def fun_l10_n151(x) + if (x < 1) + fun_l11_n501(x) + else + fun_l11_n789(x) + end +end + +def fun_l10_n152(x) + if (x < 1) + fun_l11_n265(x) + else + fun_l11_n304(x) + end +end + +def fun_l10_n153(x) + if (x < 1) + fun_l11_n500(x) + else + fun_l11_n32(x) + end +end + +def fun_l10_n154(x) + if (x < 1) + fun_l11_n464(x) + else + fun_l11_n212(x) + end +end + +def fun_l10_n155(x) + if (x < 1) + fun_l11_n729(x) + else + fun_l11_n805(x) + end +end + +def fun_l10_n156(x) + if (x < 1) + fun_l11_n225(x) + else + fun_l11_n241(x) + end +end + +def fun_l10_n157(x) + if (x < 1) + fun_l11_n600(x) + else + fun_l11_n424(x) + end +end + +def fun_l10_n158(x) + if (x < 1) + fun_l11_n684(x) + else + fun_l11_n898(x) + end +end + +def fun_l10_n159(x) + if (x < 1) + fun_l11_n354(x) + else + fun_l11_n909(x) + end +end + +def fun_l10_n160(x) + if (x < 1) + fun_l11_n879(x) + else + fun_l11_n917(x) + end +end + +def fun_l10_n161(x) + if (x < 1) + fun_l11_n547(x) + else + fun_l11_n333(x) + end +end + +def fun_l10_n162(x) + if (x < 1) + fun_l11_n769(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n163(x) + if (x < 1) + fun_l11_n292(x) + else + fun_l11_n526(x) + end +end + +def fun_l10_n164(x) + if (x < 1) + fun_l11_n355(x) + else + fun_l11_n783(x) + end +end + +def fun_l10_n165(x) + if (x < 1) + fun_l11_n413(x) + else + fun_l11_n570(x) + end +end + +def fun_l10_n166(x) + if (x < 1) + fun_l11_n535(x) + else + fun_l11_n953(x) + end +end + +def fun_l10_n167(x) + if (x < 1) + fun_l11_n661(x) + else + fun_l11_n178(x) + end +end + +def fun_l10_n168(x) + if (x < 1) + fun_l11_n749(x) + else + fun_l11_n853(x) + end +end + +def fun_l10_n169(x) + if (x < 1) + fun_l11_n208(x) + else + fun_l11_n378(x) + end +end + +def fun_l10_n170(x) + if (x < 1) + fun_l11_n385(x) + else + fun_l11_n811(x) + end +end + +def fun_l10_n171(x) + if (x < 1) + fun_l11_n960(x) + else + fun_l11_n631(x) + end +end + +def fun_l10_n172(x) + if (x < 1) + fun_l11_n104(x) + else + fun_l11_n667(x) + end +end + +def fun_l10_n173(x) + if (x < 1) + fun_l11_n532(x) + else + fun_l11_n169(x) + end +end + +def fun_l10_n174(x) + if (x < 1) + fun_l11_n794(x) + else + fun_l11_n761(x) + end +end + +def fun_l10_n175(x) + if (x < 1) + fun_l11_n306(x) + else + fun_l11_n369(x) + end +end + +def fun_l10_n176(x) + if (x < 1) + fun_l11_n693(x) + else + fun_l11_n254(x) + end +end + +def fun_l10_n177(x) + if (x < 1) + fun_l11_n927(x) + else + fun_l11_n194(x) + end +end + +def fun_l10_n178(x) + if (x < 1) + fun_l11_n197(x) + else + fun_l11_n136(x) + end +end + +def fun_l10_n179(x) + if (x < 1) + fun_l11_n482(x) + else + fun_l11_n182(x) + end +end + +def fun_l10_n180(x) + if (x < 1) + fun_l11_n20(x) + else + fun_l11_n978(x) + end +end + +def fun_l10_n181(x) + if (x < 1) + fun_l11_n101(x) + else + fun_l11_n92(x) + end +end + +def fun_l10_n182(x) + if (x < 1) + fun_l11_n179(x) + else + fun_l11_n634(x) + end +end + +def fun_l10_n183(x) + if (x < 1) + fun_l11_n221(x) + else + fun_l11_n275(x) + end +end + +def fun_l10_n184(x) + if (x < 1) + fun_l11_n826(x) + else + fun_l11_n630(x) + end +end + +def fun_l10_n185(x) + if (x < 1) + fun_l11_n706(x) + else + fun_l11_n30(x) + end +end + +def fun_l10_n186(x) + if (x < 1) + fun_l11_n491(x) + else + fun_l11_n182(x) + end +end + +def fun_l10_n187(x) + if (x < 1) + fun_l11_n404(x) + else + fun_l11_n812(x) + end +end + +def fun_l10_n188(x) + if (x < 1) + fun_l11_n41(x) + else + fun_l11_n39(x) + end +end + +def fun_l10_n189(x) + if (x < 1) + fun_l11_n620(x) + else + fun_l11_n659(x) + end +end + +def fun_l10_n190(x) + if (x < 1) + fun_l11_n717(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n191(x) + if (x < 1) + fun_l11_n328(x) + else + fun_l11_n223(x) + end +end + +def fun_l10_n192(x) + if (x < 1) + fun_l11_n280(x) + else + fun_l11_n360(x) + end +end + +def fun_l10_n193(x) + if (x < 1) + fun_l11_n798(x) + else + fun_l11_n303(x) + end +end + +def fun_l10_n194(x) + if (x < 1) + fun_l11_n617(x) + else + fun_l11_n207(x) + end +end + +def fun_l10_n195(x) + if (x < 1) + fun_l11_n918(x) + else + fun_l11_n398(x) + end +end + +def fun_l10_n196(x) + if (x < 1) + fun_l11_n998(x) + else + fun_l11_n31(x) + end +end + +def fun_l10_n197(x) + if (x < 1) + fun_l11_n740(x) + else + fun_l11_n220(x) + end +end + +def fun_l10_n198(x) + if (x < 1) + fun_l11_n847(x) + else + fun_l11_n915(x) + end +end + +def fun_l10_n199(x) + if (x < 1) + fun_l11_n946(x) + else + fun_l11_n300(x) + end +end + +def fun_l10_n200(x) + if (x < 1) + fun_l11_n494(x) + else + fun_l11_n316(x) + end +end + +def fun_l10_n201(x) + if (x < 1) + fun_l11_n871(x) + else + fun_l11_n310(x) + end +end + +def fun_l10_n202(x) + if (x < 1) + fun_l11_n660(x) + else + fun_l11_n538(x) + end +end + +def fun_l10_n203(x) + if (x < 1) + fun_l11_n478(x) + else + fun_l11_n618(x) + end +end + +def fun_l10_n204(x) + if (x < 1) + fun_l11_n134(x) + else + fun_l11_n224(x) + end +end + +def fun_l10_n205(x) + if (x < 1) + fun_l11_n128(x) + else + fun_l11_n279(x) + end +end + +def fun_l10_n206(x) + if (x < 1) + fun_l11_n718(x) + else + fun_l11_n514(x) + end +end + +def fun_l10_n207(x) + if (x < 1) + fun_l11_n466(x) + else + fun_l11_n979(x) + end +end + +def fun_l10_n208(x) + if (x < 1) + fun_l11_n990(x) + else + fun_l11_n881(x) + end +end + +def fun_l10_n209(x) + if (x < 1) + fun_l11_n860(x) + else + fun_l11_n995(x) + end +end + +def fun_l10_n210(x) + if (x < 1) + fun_l11_n269(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n211(x) + if (x < 1) + fun_l11_n155(x) + else + fun_l11_n97(x) + end +end + +def fun_l10_n212(x) + if (x < 1) + fun_l11_n377(x) + else + fun_l11_n749(x) + end +end + +def fun_l10_n213(x) + if (x < 1) + fun_l11_n647(x) + else + fun_l11_n276(x) + end +end + +def fun_l10_n214(x) + if (x < 1) + fun_l11_n290(x) + else + fun_l11_n325(x) + end +end + +def fun_l10_n215(x) + if (x < 1) + fun_l11_n445(x) + else + fun_l11_n538(x) + end +end + +def fun_l10_n216(x) + if (x < 1) + fun_l11_n433(x) + else + fun_l11_n937(x) + end +end + +def fun_l10_n217(x) + if (x < 1) + fun_l11_n288(x) + else + fun_l11_n897(x) + end +end + +def fun_l10_n218(x) + if (x < 1) + fun_l11_n386(x) + else + fun_l11_n545(x) + end +end + +def fun_l10_n219(x) + if (x < 1) + fun_l11_n678(x) + else + fun_l11_n433(x) + end +end + +def fun_l10_n220(x) + if (x < 1) + fun_l11_n203(x) + else + fun_l11_n163(x) + end +end + +def fun_l10_n221(x) + if (x < 1) + fun_l11_n134(x) + else + fun_l11_n545(x) + end +end + +def fun_l10_n222(x) + if (x < 1) + fun_l11_n556(x) + else + fun_l11_n537(x) + end +end + +def fun_l10_n223(x) + if (x < 1) + fun_l11_n743(x) + else + fun_l11_n88(x) + end +end + +def fun_l10_n224(x) + if (x < 1) + fun_l11_n678(x) + else + fun_l11_n643(x) + end +end + +def fun_l10_n225(x) + if (x < 1) + fun_l11_n13(x) + else + fun_l11_n219(x) + end +end + +def fun_l10_n226(x) + if (x < 1) + fun_l11_n454(x) + else + fun_l11_n691(x) + end +end + +def fun_l10_n227(x) + if (x < 1) + fun_l11_n117(x) + else + fun_l11_n433(x) + end +end + +def fun_l10_n228(x) + if (x < 1) + fun_l11_n559(x) + else + fun_l11_n884(x) + end +end + +def fun_l10_n229(x) + if (x < 1) + fun_l11_n58(x) + else + fun_l11_n620(x) + end +end + +def fun_l10_n230(x) + if (x < 1) + fun_l11_n688(x) + else + fun_l11_n76(x) + end +end + +def fun_l10_n231(x) + if (x < 1) + fun_l11_n726(x) + else + fun_l11_n644(x) + end +end + +def fun_l10_n232(x) + if (x < 1) + fun_l11_n918(x) + else + fun_l11_n0(x) + end +end + +def fun_l10_n233(x) + if (x < 1) + fun_l11_n761(x) + else + fun_l11_n487(x) + end +end + +def fun_l10_n234(x) + if (x < 1) + fun_l11_n657(x) + else + fun_l11_n107(x) + end +end + +def fun_l10_n235(x) + if (x < 1) + fun_l11_n897(x) + else + fun_l11_n881(x) + end +end + +def fun_l10_n236(x) + if (x < 1) + fun_l11_n851(x) + else + fun_l11_n593(x) + end +end + +def fun_l10_n237(x) + if (x < 1) + fun_l11_n319(x) + else + fun_l11_n983(x) + end +end + +def fun_l10_n238(x) + if (x < 1) + fun_l11_n648(x) + else + fun_l11_n870(x) + end +end + +def fun_l10_n239(x) + if (x < 1) + fun_l11_n195(x) + else + fun_l11_n378(x) + end +end + +def fun_l10_n240(x) + if (x < 1) + fun_l11_n398(x) + else + fun_l11_n284(x) + end +end + +def fun_l10_n241(x) + if (x < 1) + fun_l11_n118(x) + else + fun_l11_n417(x) + end +end + +def fun_l10_n242(x) + if (x < 1) + fun_l11_n220(x) + else + fun_l11_n445(x) + end +end + +def fun_l10_n243(x) + if (x < 1) + fun_l11_n783(x) + else + fun_l11_n989(x) + end +end + +def fun_l10_n244(x) + if (x < 1) + fun_l11_n229(x) + else + fun_l11_n439(x) + end +end + +def fun_l10_n245(x) + if (x < 1) + fun_l11_n78(x) + else + fun_l11_n272(x) + end +end + +def fun_l10_n246(x) + if (x < 1) + fun_l11_n481(x) + else + fun_l11_n499(x) + end +end + +def fun_l10_n247(x) + if (x < 1) + fun_l11_n213(x) + else + fun_l11_n471(x) + end +end + +def fun_l10_n248(x) + if (x < 1) + fun_l11_n45(x) + else + fun_l11_n919(x) + end +end + +def fun_l10_n249(x) + if (x < 1) + fun_l11_n13(x) + else + fun_l11_n526(x) + end +end + +def fun_l10_n250(x) + if (x < 1) + fun_l11_n997(x) + else + fun_l11_n112(x) + end +end + +def fun_l10_n251(x) + if (x < 1) + fun_l11_n662(x) + else + fun_l11_n950(x) + end +end + +def fun_l10_n252(x) + if (x < 1) + fun_l11_n272(x) + else + fun_l11_n345(x) + end +end + +def fun_l10_n253(x) + if (x < 1) + fun_l11_n28(x) + else + fun_l11_n24(x) + end +end + +def fun_l10_n254(x) + if (x < 1) + fun_l11_n326(x) + else + fun_l11_n907(x) + end +end + +def fun_l10_n255(x) + if (x < 1) + fun_l11_n612(x) + else + fun_l11_n790(x) + end +end + +def fun_l10_n256(x) + if (x < 1) + fun_l11_n50(x) + else + fun_l11_n16(x) + end +end + +def fun_l10_n257(x) + if (x < 1) + fun_l11_n350(x) + else + fun_l11_n151(x) + end +end + +def fun_l10_n258(x) + if (x < 1) + fun_l11_n290(x) + else + fun_l11_n113(x) + end +end + +def fun_l10_n259(x) + if (x < 1) + fun_l11_n751(x) + else + fun_l11_n16(x) + end +end + +def fun_l10_n260(x) + if (x < 1) + fun_l11_n337(x) + else + fun_l11_n516(x) + end +end + +def fun_l10_n261(x) + if (x < 1) + fun_l11_n530(x) + else + fun_l11_n19(x) + end +end + +def fun_l10_n262(x) + if (x < 1) + fun_l11_n977(x) + else + fun_l11_n529(x) + end +end + +def fun_l10_n263(x) + if (x < 1) + fun_l11_n769(x) + else + fun_l11_n723(x) + end +end + +def fun_l10_n264(x) + if (x < 1) + fun_l11_n673(x) + else + fun_l11_n771(x) + end +end + +def fun_l10_n265(x) + if (x < 1) + fun_l11_n28(x) + else + fun_l11_n427(x) + end +end + +def fun_l10_n266(x) + if (x < 1) + fun_l11_n92(x) + else + fun_l11_n590(x) + end +end + +def fun_l10_n267(x) + if (x < 1) + fun_l11_n762(x) + else + fun_l11_n352(x) + end +end + +def fun_l10_n268(x) + if (x < 1) + fun_l11_n988(x) + else + fun_l11_n126(x) + end +end + +def fun_l10_n269(x) + if (x < 1) + fun_l11_n92(x) + else + fun_l11_n455(x) + end +end + +def fun_l10_n270(x) + if (x < 1) + fun_l11_n233(x) + else + fun_l11_n404(x) + end +end + +def fun_l10_n271(x) + if (x < 1) + fun_l11_n122(x) + else + fun_l11_n245(x) + end +end + +def fun_l10_n272(x) + if (x < 1) + fun_l11_n277(x) + else + fun_l11_n969(x) + end +end + +def fun_l10_n273(x) + if (x < 1) + fun_l11_n848(x) + else + fun_l11_n56(x) + end +end + +def fun_l10_n274(x) + if (x < 1) + fun_l11_n640(x) + else + fun_l11_n632(x) + end +end + +def fun_l10_n275(x) + if (x < 1) + fun_l11_n38(x) + else + fun_l11_n816(x) + end +end + +def fun_l10_n276(x) + if (x < 1) + fun_l11_n706(x) + else + fun_l11_n126(x) + end +end + +def fun_l10_n277(x) + if (x < 1) + fun_l11_n710(x) + else + fun_l11_n128(x) + end +end + +def fun_l10_n278(x) + if (x < 1) + fun_l11_n175(x) + else + fun_l11_n954(x) + end +end + +def fun_l10_n279(x) + if (x < 1) + fun_l11_n379(x) + else + fun_l11_n58(x) + end +end + +def fun_l10_n280(x) + if (x < 1) + fun_l11_n926(x) + else + fun_l11_n287(x) + end +end + +def fun_l10_n281(x) + if (x < 1) + fun_l11_n981(x) + else + fun_l11_n921(x) + end +end + +def fun_l10_n282(x) + if (x < 1) + fun_l11_n222(x) + else + fun_l11_n954(x) + end +end + +def fun_l10_n283(x) + if (x < 1) + fun_l11_n295(x) + else + fun_l11_n575(x) + end +end + +def fun_l10_n284(x) + if (x < 1) + fun_l11_n554(x) + else + fun_l11_n559(x) + end +end + +def fun_l10_n285(x) + if (x < 1) + fun_l11_n476(x) + else + fun_l11_n487(x) + end +end + +def fun_l10_n286(x) + if (x < 1) + fun_l11_n102(x) + else + fun_l11_n928(x) + end +end + +def fun_l10_n287(x) + if (x < 1) + fun_l11_n949(x) + else + fun_l11_n900(x) + end +end + +def fun_l10_n288(x) + if (x < 1) + fun_l11_n717(x) + else + fun_l11_n762(x) + end +end + +def fun_l10_n289(x) + if (x < 1) + fun_l11_n304(x) + else + fun_l11_n572(x) + end +end + +def fun_l10_n290(x) + if (x < 1) + fun_l11_n748(x) + else + fun_l11_n791(x) + end +end + +def fun_l10_n291(x) + if (x < 1) + fun_l11_n557(x) + else + fun_l11_n79(x) + end +end + +def fun_l10_n292(x) + if (x < 1) + fun_l11_n74(x) + else + fun_l11_n931(x) + end +end + +def fun_l10_n293(x) + if (x < 1) + fun_l11_n31(x) + else + fun_l11_n791(x) + end +end + +def fun_l10_n294(x) + if (x < 1) + fun_l11_n29(x) + else + fun_l11_n377(x) + end +end + +def fun_l10_n295(x) + if (x < 1) + fun_l11_n509(x) + else + fun_l11_n900(x) + end +end + +def fun_l10_n296(x) + if (x < 1) + fun_l11_n594(x) + else + fun_l11_n835(x) + end +end + +def fun_l10_n297(x) + if (x < 1) + fun_l11_n943(x) + else + fun_l11_n621(x) + end +end + +def fun_l10_n298(x) + if (x < 1) + fun_l11_n860(x) + else + fun_l11_n403(x) + end +end + +def fun_l10_n299(x) + if (x < 1) + fun_l11_n676(x) + else + fun_l11_n478(x) + end +end + +def fun_l10_n300(x) + if (x < 1) + fun_l11_n513(x) + else + fun_l11_n661(x) + end +end + +def fun_l10_n301(x) + if (x < 1) + fun_l11_n513(x) + else + fun_l11_n30(x) + end +end + +def fun_l10_n302(x) + if (x < 1) + fun_l11_n763(x) + else + fun_l11_n823(x) + end +end + +def fun_l10_n303(x) + if (x < 1) + fun_l11_n469(x) + else + fun_l11_n250(x) + end +end + +def fun_l10_n304(x) + if (x < 1) + fun_l11_n637(x) + else + fun_l11_n478(x) + end +end + +def fun_l10_n305(x) + if (x < 1) + fun_l11_n825(x) + else + fun_l11_n258(x) + end +end + +def fun_l10_n306(x) + if (x < 1) + fun_l11_n264(x) + else + fun_l11_n698(x) + end +end + +def fun_l10_n307(x) + if (x < 1) + fun_l11_n426(x) + else + fun_l11_n490(x) + end +end + +def fun_l10_n308(x) + if (x < 1) + fun_l11_n157(x) + else + fun_l11_n407(x) + end +end + +def fun_l10_n309(x) + if (x < 1) + fun_l11_n68(x) + else + fun_l11_n424(x) + end +end + +def fun_l10_n310(x) + if (x < 1) + fun_l11_n844(x) + else + fun_l11_n955(x) + end +end + +def fun_l10_n311(x) + if (x < 1) + fun_l11_n316(x) + else + fun_l11_n27(x) + end +end + +def fun_l10_n312(x) + if (x < 1) + fun_l11_n771(x) + else + fun_l11_n604(x) + end +end + +def fun_l10_n313(x) + if (x < 1) + fun_l11_n436(x) + else + fun_l11_n714(x) + end +end + +def fun_l10_n314(x) + if (x < 1) + fun_l11_n791(x) + else + fun_l11_n889(x) + end +end + +def fun_l10_n315(x) + if (x < 1) + fun_l11_n621(x) + else + fun_l11_n694(x) + end +end + +def fun_l10_n316(x) + if (x < 1) + fun_l11_n403(x) + else + fun_l11_n625(x) + end +end + +def fun_l10_n317(x) + if (x < 1) + fun_l11_n532(x) + else + fun_l11_n920(x) + end +end + +def fun_l10_n318(x) + if (x < 1) + fun_l11_n895(x) + else + fun_l11_n781(x) + end +end + +def fun_l10_n319(x) + if (x < 1) + fun_l11_n109(x) + else + fun_l11_n254(x) + end +end + +def fun_l10_n320(x) + if (x < 1) + fun_l11_n842(x) + else + fun_l11_n879(x) + end +end + +def fun_l10_n321(x) + if (x < 1) + fun_l11_n655(x) + else + fun_l11_n518(x) + end +end + +def fun_l10_n322(x) + if (x < 1) + fun_l11_n727(x) + else + fun_l11_n14(x) + end +end + +def fun_l10_n323(x) + if (x < 1) + fun_l11_n808(x) + else + fun_l11_n128(x) + end +end + +def fun_l10_n324(x) + if (x < 1) + fun_l11_n412(x) + else + fun_l11_n940(x) + end +end + +def fun_l10_n325(x) + if (x < 1) + fun_l11_n944(x) + else + fun_l11_n915(x) + end +end + +def fun_l10_n326(x) + if (x < 1) + fun_l11_n120(x) + else + fun_l11_n572(x) + end +end + +def fun_l10_n327(x) + if (x < 1) + fun_l11_n444(x) + else + fun_l11_n793(x) + end +end + +def fun_l10_n328(x) + if (x < 1) + fun_l11_n892(x) + else + fun_l11_n475(x) + end +end + +def fun_l10_n329(x) + if (x < 1) + fun_l11_n919(x) + else + fun_l11_n183(x) + end +end + +def fun_l10_n330(x) + if (x < 1) + fun_l11_n80(x) + else + fun_l11_n357(x) + end +end + +def fun_l10_n331(x) + if (x < 1) + fun_l11_n340(x) + else + fun_l11_n349(x) + end +end + +def fun_l10_n332(x) + if (x < 1) + fun_l11_n579(x) + else + fun_l11_n845(x) + end +end + +def fun_l10_n333(x) + if (x < 1) + fun_l11_n169(x) + else + fun_l11_n583(x) + end +end + +def fun_l10_n334(x) + if (x < 1) + fun_l11_n544(x) + else + fun_l11_n462(x) + end +end + +def fun_l10_n335(x) + if (x < 1) + fun_l11_n51(x) + else + fun_l11_n635(x) + end +end + +def fun_l10_n336(x) + if (x < 1) + fun_l11_n965(x) + else + fun_l11_n538(x) + end +end + +def fun_l10_n337(x) + if (x < 1) + fun_l11_n930(x) + else + fun_l11_n169(x) + end +end + +def fun_l10_n338(x) + if (x < 1) + fun_l11_n732(x) + else + fun_l11_n574(x) + end +end + +def fun_l10_n339(x) + if (x < 1) + fun_l11_n51(x) + else + fun_l11_n141(x) + end +end + +def fun_l10_n340(x) + if (x < 1) + fun_l11_n149(x) + else + fun_l11_n346(x) + end +end + +def fun_l10_n341(x) + if (x < 1) + fun_l11_n163(x) + else + fun_l11_n224(x) + end +end + +def fun_l10_n342(x) + if (x < 1) + fun_l11_n175(x) + else + fun_l11_n40(x) + end +end + +def fun_l10_n343(x) + if (x < 1) + fun_l11_n156(x) + else + fun_l11_n639(x) + end +end + +def fun_l10_n344(x) + if (x < 1) + fun_l11_n934(x) + else + fun_l11_n85(x) + end +end + +def fun_l10_n345(x) + if (x < 1) + fun_l11_n182(x) + else + fun_l11_n190(x) + end +end + +def fun_l10_n346(x) + if (x < 1) + fun_l11_n879(x) + else + fun_l11_n702(x) + end +end + +def fun_l10_n347(x) + if (x < 1) + fun_l11_n540(x) + else + fun_l11_n689(x) + end +end + +def fun_l10_n348(x) + if (x < 1) + fun_l11_n945(x) + else + fun_l11_n39(x) + end +end + +def fun_l10_n349(x) + if (x < 1) + fun_l11_n683(x) + else + fun_l11_n688(x) + end +end + +def fun_l10_n350(x) + if (x < 1) + fun_l11_n750(x) + else + fun_l11_n577(x) + end +end + +def fun_l10_n351(x) + if (x < 1) + fun_l11_n74(x) + else + fun_l11_n672(x) + end +end + +def fun_l10_n352(x) + if (x < 1) + fun_l11_n252(x) + else + fun_l11_n766(x) + end +end + +def fun_l10_n353(x) + if (x < 1) + fun_l11_n702(x) + else + fun_l11_n516(x) + end +end + +def fun_l10_n354(x) + if (x < 1) + fun_l11_n19(x) + else + fun_l11_n290(x) + end +end + +def fun_l10_n355(x) + if (x < 1) + fun_l11_n70(x) + else + fun_l11_n553(x) + end +end + +def fun_l10_n356(x) + if (x < 1) + fun_l11_n654(x) + else + fun_l11_n108(x) + end +end + +def fun_l10_n357(x) + if (x < 1) + fun_l11_n820(x) + else + fun_l11_n320(x) + end +end + +def fun_l10_n358(x) + if (x < 1) + fun_l11_n417(x) + else + fun_l11_n290(x) + end +end + +def fun_l10_n359(x) + if (x < 1) + fun_l11_n832(x) + else + fun_l11_n647(x) + end +end + +def fun_l10_n360(x) + if (x < 1) + fun_l11_n625(x) + else + fun_l11_n723(x) + end +end + +def fun_l10_n361(x) + if (x < 1) + fun_l11_n257(x) + else + fun_l11_n991(x) + end +end + +def fun_l10_n362(x) + if (x < 1) + fun_l11_n101(x) + else + fun_l11_n247(x) + end +end + +def fun_l10_n363(x) + if (x < 1) + fun_l11_n484(x) + else + fun_l11_n953(x) + end +end + +def fun_l10_n364(x) + if (x < 1) + fun_l11_n281(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n365(x) + if (x < 1) + fun_l11_n425(x) + else + fun_l11_n772(x) + end +end + +def fun_l10_n366(x) + if (x < 1) + fun_l11_n724(x) + else + fun_l11_n725(x) + end +end + +def fun_l10_n367(x) + if (x < 1) + fun_l11_n943(x) + else + fun_l11_n360(x) + end +end + +def fun_l10_n368(x) + if (x < 1) + fun_l11_n874(x) + else + fun_l11_n698(x) + end +end + +def fun_l10_n369(x) + if (x < 1) + fun_l11_n419(x) + else + fun_l11_n672(x) + end +end + +def fun_l10_n370(x) + if (x < 1) + fun_l11_n655(x) + else + fun_l11_n468(x) + end +end + +def fun_l10_n371(x) + if (x < 1) + fun_l11_n577(x) + else + fun_l11_n402(x) + end +end + +def fun_l10_n372(x) + if (x < 1) + fun_l11_n531(x) + else + fun_l11_n319(x) + end +end + +def fun_l10_n373(x) + if (x < 1) + fun_l11_n972(x) + else + fun_l11_n901(x) + end +end + +def fun_l10_n374(x) + if (x < 1) + fun_l11_n59(x) + else + fun_l11_n12(x) + end +end + +def fun_l10_n375(x) + if (x < 1) + fun_l11_n409(x) + else + fun_l11_n214(x) + end +end + +def fun_l10_n376(x) + if (x < 1) + fun_l11_n52(x) + else + fun_l11_n395(x) + end +end + +def fun_l10_n377(x) + if (x < 1) + fun_l11_n594(x) + else + fun_l11_n434(x) + end +end + +def fun_l10_n378(x) + if (x < 1) + fun_l11_n795(x) + else + fun_l11_n820(x) + end +end + +def fun_l10_n379(x) + if (x < 1) + fun_l11_n962(x) + else + fun_l11_n111(x) + end +end + +def fun_l10_n380(x) + if (x < 1) + fun_l11_n762(x) + else + fun_l11_n678(x) + end +end + +def fun_l10_n381(x) + if (x < 1) + fun_l11_n324(x) + else + fun_l11_n478(x) + end +end + +def fun_l10_n382(x) + if (x < 1) + fun_l11_n360(x) + else + fun_l11_n35(x) + end +end + +def fun_l10_n383(x) + if (x < 1) + fun_l11_n710(x) + else + fun_l11_n898(x) + end +end + +def fun_l10_n384(x) + if (x < 1) + fun_l11_n584(x) + else + fun_l11_n260(x) + end +end + +def fun_l10_n385(x) + if (x < 1) + fun_l11_n514(x) + else + fun_l11_n649(x) + end +end + +def fun_l10_n386(x) + if (x < 1) + fun_l11_n426(x) + else + fun_l11_n391(x) + end +end + +def fun_l10_n387(x) + if (x < 1) + fun_l11_n713(x) + else + fun_l11_n734(x) + end +end + +def fun_l10_n388(x) + if (x < 1) + fun_l11_n236(x) + else + fun_l11_n469(x) + end +end + +def fun_l10_n389(x) + if (x < 1) + fun_l11_n267(x) + else + fun_l11_n965(x) + end +end + +def fun_l10_n390(x) + if (x < 1) + fun_l11_n943(x) + else + fun_l11_n181(x) + end +end + +def fun_l10_n391(x) + if (x < 1) + fun_l11_n869(x) + else + fun_l11_n348(x) + end +end + +def fun_l10_n392(x) + if (x < 1) + fun_l11_n144(x) + else + fun_l11_n801(x) + end +end + +def fun_l10_n393(x) + if (x < 1) + fun_l11_n907(x) + else + fun_l11_n609(x) + end +end + +def fun_l10_n394(x) + if (x < 1) + fun_l11_n801(x) + else + fun_l11_n691(x) + end +end + +def fun_l10_n395(x) + if (x < 1) + fun_l11_n629(x) + else + fun_l11_n924(x) + end +end + +def fun_l10_n396(x) + if (x < 1) + fun_l11_n191(x) + else + fun_l11_n248(x) + end +end + +def fun_l10_n397(x) + if (x < 1) + fun_l11_n339(x) + else + fun_l11_n805(x) + end +end + +def fun_l10_n398(x) + if (x < 1) + fun_l11_n798(x) + else + fun_l11_n154(x) + end +end + +def fun_l10_n399(x) + if (x < 1) + fun_l11_n847(x) + else + fun_l11_n14(x) + end +end + +def fun_l10_n400(x) + if (x < 1) + fun_l11_n296(x) + else + fun_l11_n144(x) + end +end + +def fun_l10_n401(x) + if (x < 1) + fun_l11_n853(x) + else + fun_l11_n156(x) + end +end + +def fun_l10_n402(x) + if (x < 1) + fun_l11_n54(x) + else + fun_l11_n944(x) + end +end + +def fun_l10_n403(x) + if (x < 1) + fun_l11_n617(x) + else + fun_l11_n324(x) + end +end + +def fun_l10_n404(x) + if (x < 1) + fun_l11_n962(x) + else + fun_l11_n139(x) + end +end + +def fun_l10_n405(x) + if (x < 1) + fun_l11_n466(x) + else + fun_l11_n388(x) + end +end + +def fun_l10_n406(x) + if (x < 1) + fun_l11_n914(x) + else + fun_l11_n847(x) + end +end + +def fun_l10_n407(x) + if (x < 1) + fun_l11_n741(x) + else + fun_l11_n757(x) + end +end + +def fun_l10_n408(x) + if (x < 1) + fun_l11_n36(x) + else + fun_l11_n312(x) + end +end + +def fun_l10_n409(x) + if (x < 1) + fun_l11_n203(x) + else + fun_l11_n523(x) + end +end + +def fun_l10_n410(x) + if (x < 1) + fun_l11_n187(x) + else + fun_l11_n291(x) + end +end + +def fun_l10_n411(x) + if (x < 1) + fun_l11_n13(x) + else + fun_l11_n107(x) + end +end + +def fun_l10_n412(x) + if (x < 1) + fun_l11_n960(x) + else + fun_l11_n565(x) + end +end + +def fun_l10_n413(x) + if (x < 1) + fun_l11_n549(x) + else + fun_l11_n885(x) + end +end + +def fun_l10_n414(x) + if (x < 1) + fun_l11_n559(x) + else + fun_l11_n612(x) + end +end + +def fun_l10_n415(x) + if (x < 1) + fun_l11_n18(x) + else + fun_l11_n167(x) + end +end + +def fun_l10_n416(x) + if (x < 1) + fun_l11_n125(x) + else + fun_l11_n206(x) + end +end + +def fun_l10_n417(x) + if (x < 1) + fun_l11_n980(x) + else + fun_l11_n497(x) + end +end + +def fun_l10_n418(x) + if (x < 1) + fun_l11_n703(x) + else + fun_l11_n49(x) + end +end + +def fun_l10_n419(x) + if (x < 1) + fun_l11_n690(x) + else + fun_l11_n63(x) + end +end + +def fun_l10_n420(x) + if (x < 1) + fun_l11_n219(x) + else + fun_l11_n814(x) + end +end + +def fun_l10_n421(x) + if (x < 1) + fun_l11_n864(x) + else + fun_l11_n963(x) + end +end + +def fun_l10_n422(x) + if (x < 1) + fun_l11_n672(x) + else + fun_l11_n87(x) + end +end + +def fun_l10_n423(x) + if (x < 1) + fun_l11_n41(x) + else + fun_l11_n461(x) + end +end + +def fun_l10_n424(x) + if (x < 1) + fun_l11_n334(x) + else + fun_l11_n283(x) + end +end + +def fun_l10_n425(x) + if (x < 1) + fun_l11_n369(x) + else + fun_l11_n269(x) + end +end + +def fun_l10_n426(x) + if (x < 1) + fun_l11_n832(x) + else + fun_l11_n625(x) + end +end + +def fun_l10_n427(x) + if (x < 1) + fun_l11_n272(x) + else + fun_l11_n634(x) + end +end + +def fun_l10_n428(x) + if (x < 1) + fun_l11_n122(x) + else + fun_l11_n53(x) + end +end + +def fun_l10_n429(x) + if (x < 1) + fun_l11_n895(x) + else + fun_l11_n292(x) + end +end + +def fun_l10_n430(x) + if (x < 1) + fun_l11_n460(x) + else + fun_l11_n177(x) + end +end + +def fun_l10_n431(x) + if (x < 1) + fun_l11_n238(x) + else + fun_l11_n938(x) + end +end + +def fun_l10_n432(x) + if (x < 1) + fun_l11_n302(x) + else + fun_l11_n492(x) + end +end + +def fun_l10_n433(x) + if (x < 1) + fun_l11_n307(x) + else + fun_l11_n876(x) + end +end + +def fun_l10_n434(x) + if (x < 1) + fun_l11_n64(x) + else + fun_l11_n892(x) + end +end + +def fun_l10_n435(x) + if (x < 1) + fun_l11_n940(x) + else + fun_l11_n718(x) + end +end + +def fun_l10_n436(x) + if (x < 1) + fun_l11_n988(x) + else + fun_l11_n216(x) + end +end + +def fun_l10_n437(x) + if (x < 1) + fun_l11_n282(x) + else + fun_l11_n168(x) + end +end + +def fun_l10_n438(x) + if (x < 1) + fun_l11_n529(x) + else + fun_l11_n66(x) + end +end + +def fun_l10_n439(x) + if (x < 1) + fun_l11_n286(x) + else + fun_l11_n134(x) + end +end + +def fun_l10_n440(x) + if (x < 1) + fun_l11_n454(x) + else + fun_l11_n873(x) + end +end + +def fun_l10_n441(x) + if (x < 1) + fun_l11_n871(x) + else + fun_l11_n13(x) + end +end + +def fun_l10_n442(x) + if (x < 1) + fun_l11_n314(x) + else + fun_l11_n685(x) + end +end + +def fun_l10_n443(x) + if (x < 1) + fun_l11_n752(x) + else + fun_l11_n162(x) + end +end + +def fun_l10_n444(x) + if (x < 1) + fun_l11_n686(x) + else + fun_l11_n585(x) + end +end + +def fun_l10_n445(x) + if (x < 1) + fun_l11_n42(x) + else + fun_l11_n932(x) + end +end + +def fun_l10_n446(x) + if (x < 1) + fun_l11_n433(x) + else + fun_l11_n241(x) + end +end + +def fun_l10_n447(x) + if (x < 1) + fun_l11_n99(x) + else + fun_l11_n563(x) + end +end + +def fun_l10_n448(x) + if (x < 1) + fun_l11_n463(x) + else + fun_l11_n395(x) + end +end + +def fun_l10_n449(x) + if (x < 1) + fun_l11_n393(x) + else + fun_l11_n151(x) + end +end + +def fun_l10_n450(x) + if (x < 1) + fun_l11_n255(x) + else + fun_l11_n834(x) + end +end + +def fun_l10_n451(x) + if (x < 1) + fun_l11_n195(x) + else + fun_l11_n0(x) + end +end + +def fun_l10_n452(x) + if (x < 1) + fun_l11_n372(x) + else + fun_l11_n228(x) + end +end + +def fun_l10_n453(x) + if (x < 1) + fun_l11_n526(x) + else + fun_l11_n54(x) + end +end + +def fun_l10_n454(x) + if (x < 1) + fun_l11_n594(x) + else + fun_l11_n116(x) + end +end + +def fun_l10_n455(x) + if (x < 1) + fun_l11_n25(x) + else + fun_l11_n930(x) + end +end + +def fun_l10_n456(x) + if (x < 1) + fun_l11_n83(x) + else + fun_l11_n30(x) + end +end + +def fun_l10_n457(x) + if (x < 1) + fun_l11_n644(x) + else + fun_l11_n837(x) + end +end + +def fun_l10_n458(x) + if (x < 1) + fun_l11_n311(x) + else + fun_l11_n86(x) + end +end + +def fun_l10_n459(x) + if (x < 1) + fun_l11_n139(x) + else + fun_l11_n735(x) + end +end + +def fun_l10_n460(x) + if (x < 1) + fun_l11_n431(x) + else + fun_l11_n808(x) + end +end + +def fun_l10_n461(x) + if (x < 1) + fun_l11_n488(x) + else + fun_l11_n439(x) + end +end + +def fun_l10_n462(x) + if (x < 1) + fun_l11_n448(x) + else + fun_l11_n882(x) + end +end + +def fun_l10_n463(x) + if (x < 1) + fun_l11_n362(x) + else + fun_l11_n875(x) + end +end + +def fun_l10_n464(x) + if (x < 1) + fun_l11_n88(x) + else + fun_l11_n842(x) + end +end + +def fun_l10_n465(x) + if (x < 1) + fun_l11_n651(x) + else + fun_l11_n368(x) + end +end + +def fun_l10_n466(x) + if (x < 1) + fun_l11_n121(x) + else + fun_l11_n3(x) + end +end + +def fun_l10_n467(x) + if (x < 1) + fun_l11_n654(x) + else + fun_l11_n260(x) + end +end + +def fun_l10_n468(x) + if (x < 1) + fun_l11_n765(x) + else + fun_l11_n604(x) + end +end + +def fun_l10_n469(x) + if (x < 1) + fun_l11_n881(x) + else + fun_l11_n567(x) + end +end + +def fun_l10_n470(x) + if (x < 1) + fun_l11_n41(x) + else + fun_l11_n92(x) + end +end + +def fun_l10_n471(x) + if (x < 1) + fun_l11_n905(x) + else + fun_l11_n731(x) + end +end + +def fun_l10_n472(x) + if (x < 1) + fun_l11_n797(x) + else + fun_l11_n878(x) + end +end + +def fun_l10_n473(x) + if (x < 1) + fun_l11_n487(x) + else + fun_l11_n951(x) + end +end + +def fun_l10_n474(x) + if (x < 1) + fun_l11_n998(x) + else + fun_l11_n900(x) + end +end + +def fun_l10_n475(x) + if (x < 1) + fun_l11_n451(x) + else + fun_l11_n780(x) + end +end + +def fun_l10_n476(x) + if (x < 1) + fun_l11_n427(x) + else + fun_l11_n760(x) + end +end + +def fun_l10_n477(x) + if (x < 1) + fun_l11_n758(x) + else + fun_l11_n177(x) + end +end + +def fun_l10_n478(x) + if (x < 1) + fun_l11_n359(x) + else + fun_l11_n236(x) + end +end + +def fun_l10_n479(x) + if (x < 1) + fun_l11_n70(x) + else + fun_l11_n49(x) + end +end + +def fun_l10_n480(x) + if (x < 1) + fun_l11_n338(x) + else + fun_l11_n714(x) + end +end + +def fun_l10_n481(x) + if (x < 1) + fun_l11_n6(x) + else + fun_l11_n194(x) + end +end + +def fun_l10_n482(x) + if (x < 1) + fun_l11_n801(x) + else + fun_l11_n591(x) + end +end + +def fun_l10_n483(x) + if (x < 1) + fun_l11_n362(x) + else + fun_l11_n687(x) + end +end + +def fun_l10_n484(x) + if (x < 1) + fun_l11_n659(x) + else + fun_l11_n661(x) + end +end + +def fun_l10_n485(x) + if (x < 1) + fun_l11_n903(x) + else + fun_l11_n419(x) + end +end + +def fun_l10_n486(x) + if (x < 1) + fun_l11_n279(x) + else + fun_l11_n995(x) + end +end + +def fun_l10_n487(x) + if (x < 1) + fun_l11_n529(x) + else + fun_l11_n373(x) + end +end + +def fun_l10_n488(x) + if (x < 1) + fun_l11_n198(x) + else + fun_l11_n899(x) + end +end + +def fun_l10_n489(x) + if (x < 1) + fun_l11_n174(x) + else + fun_l11_n485(x) + end +end + +def fun_l10_n490(x) + if (x < 1) + fun_l11_n19(x) + else + fun_l11_n322(x) + end +end + +def fun_l10_n491(x) + if (x < 1) + fun_l11_n0(x) + else + fun_l11_n855(x) + end +end + +def fun_l10_n492(x) + if (x < 1) + fun_l11_n126(x) + else + fun_l11_n986(x) + end +end + +def fun_l10_n493(x) + if (x < 1) + fun_l11_n263(x) + else + fun_l11_n374(x) + end +end + +def fun_l10_n494(x) + if (x < 1) + fun_l11_n21(x) + else + fun_l11_n749(x) + end +end + +def fun_l10_n495(x) + if (x < 1) + fun_l11_n618(x) + else + fun_l11_n955(x) + end +end + +def fun_l10_n496(x) + if (x < 1) + fun_l11_n157(x) + else + fun_l11_n230(x) + end +end + +def fun_l10_n497(x) + if (x < 1) + fun_l11_n387(x) + else + fun_l11_n841(x) + end +end + +def fun_l10_n498(x) + if (x < 1) + fun_l11_n496(x) + else + fun_l11_n30(x) + end +end + +def fun_l10_n499(x) + if (x < 1) + fun_l11_n581(x) + else + fun_l11_n821(x) + end +end + +def fun_l10_n500(x) + if (x < 1) + fun_l11_n202(x) + else + fun_l11_n26(x) + end +end + +def fun_l10_n501(x) + if (x < 1) + fun_l11_n273(x) + else + fun_l11_n294(x) + end +end + +def fun_l10_n502(x) + if (x < 1) + fun_l11_n604(x) + else + fun_l11_n261(x) + end +end + +def fun_l10_n503(x) + if (x < 1) + fun_l11_n632(x) + else + fun_l11_n340(x) + end +end + +def fun_l10_n504(x) + if (x < 1) + fun_l11_n162(x) + else + fun_l11_n483(x) + end +end + +def fun_l10_n505(x) + if (x < 1) + fun_l11_n824(x) + else + fun_l11_n747(x) + end +end + +def fun_l10_n506(x) + if (x < 1) + fun_l11_n575(x) + else + fun_l11_n932(x) + end +end + +def fun_l10_n507(x) + if (x < 1) + fun_l11_n645(x) + else + fun_l11_n486(x) + end +end + +def fun_l10_n508(x) + if (x < 1) + fun_l11_n876(x) + else + fun_l11_n640(x) + end +end + +def fun_l10_n509(x) + if (x < 1) + fun_l11_n280(x) + else + fun_l11_n116(x) + end +end + +def fun_l10_n510(x) + if (x < 1) + fun_l11_n570(x) + else + fun_l11_n640(x) + end +end + +def fun_l10_n511(x) + if (x < 1) + fun_l11_n576(x) + else + fun_l11_n124(x) + end +end + +def fun_l10_n512(x) + if (x < 1) + fun_l11_n328(x) + else + fun_l11_n880(x) + end +end + +def fun_l10_n513(x) + if (x < 1) + fun_l11_n185(x) + else + fun_l11_n977(x) + end +end + +def fun_l10_n514(x) + if (x < 1) + fun_l11_n560(x) + else + fun_l11_n825(x) + end +end + +def fun_l10_n515(x) + if (x < 1) + fun_l11_n28(x) + else + fun_l11_n908(x) + end +end + +def fun_l10_n516(x) + if (x < 1) + fun_l11_n902(x) + else + fun_l11_n882(x) + end +end + +def fun_l10_n517(x) + if (x < 1) + fun_l11_n429(x) + else + fun_l11_n824(x) + end +end + +def fun_l10_n518(x) + if (x < 1) + fun_l11_n706(x) + else + fun_l11_n149(x) + end +end + +def fun_l10_n519(x) + if (x < 1) + fun_l11_n837(x) + else + fun_l11_n573(x) + end +end + +def fun_l10_n520(x) + if (x < 1) + fun_l11_n934(x) + else + fun_l11_n504(x) + end +end + +def fun_l10_n521(x) + if (x < 1) + fun_l11_n254(x) + else + fun_l11_n551(x) + end +end + +def fun_l10_n522(x) + if (x < 1) + fun_l11_n53(x) + else + fun_l11_n297(x) + end +end + +def fun_l10_n523(x) + if (x < 1) + fun_l11_n648(x) + else + fun_l11_n695(x) + end +end + +def fun_l10_n524(x) + if (x < 1) + fun_l11_n737(x) + else + fun_l11_n636(x) + end +end + +def fun_l10_n525(x) + if (x < 1) + fun_l11_n249(x) + else + fun_l11_n757(x) + end +end + +def fun_l10_n526(x) + if (x < 1) + fun_l11_n42(x) + else + fun_l11_n199(x) + end +end + +def fun_l10_n527(x) + if (x < 1) + fun_l11_n783(x) + else + fun_l11_n856(x) + end +end + +def fun_l10_n528(x) + if (x < 1) + fun_l11_n708(x) + else + fun_l11_n550(x) + end +end + +def fun_l10_n529(x) + if (x < 1) + fun_l11_n749(x) + else + fun_l11_n56(x) + end +end + +def fun_l10_n530(x) + if (x < 1) + fun_l11_n838(x) + else + fun_l11_n57(x) + end +end + +def fun_l10_n531(x) + if (x < 1) + fun_l11_n293(x) + else + fun_l11_n938(x) + end +end + +def fun_l10_n532(x) + if (x < 1) + fun_l11_n245(x) + else + fun_l11_n367(x) + end +end + +def fun_l10_n533(x) + if (x < 1) + fun_l11_n255(x) + else + fun_l11_n234(x) + end +end + +def fun_l10_n534(x) + if (x < 1) + fun_l11_n315(x) + else + fun_l11_n982(x) + end +end + +def fun_l10_n535(x) + if (x < 1) + fun_l11_n841(x) + else + fun_l11_n112(x) + end +end + +def fun_l10_n536(x) + if (x < 1) + fun_l11_n481(x) + else + fun_l11_n622(x) + end +end + +def fun_l10_n537(x) + if (x < 1) + fun_l11_n666(x) + else + fun_l11_n775(x) + end +end + +def fun_l10_n538(x) + if (x < 1) + fun_l11_n409(x) + else + fun_l11_n733(x) + end +end + +def fun_l10_n539(x) + if (x < 1) + fun_l11_n633(x) + else + fun_l11_n122(x) + end +end + +def fun_l10_n540(x) + if (x < 1) + fun_l11_n453(x) + else + fun_l11_n938(x) + end +end + +def fun_l10_n541(x) + if (x < 1) + fun_l11_n55(x) + else + fun_l11_n344(x) + end +end + +def fun_l10_n542(x) + if (x < 1) + fun_l11_n167(x) + else + fun_l11_n908(x) + end +end + +def fun_l10_n543(x) + if (x < 1) + fun_l11_n318(x) + else + fun_l11_n893(x) + end +end + +def fun_l10_n544(x) + if (x < 1) + fun_l11_n683(x) + else + fun_l11_n109(x) + end +end + +def fun_l10_n545(x) + if (x < 1) + fun_l11_n728(x) + else + fun_l11_n432(x) + end +end + +def fun_l10_n546(x) + if (x < 1) + fun_l11_n343(x) + else + fun_l11_n674(x) + end +end + +def fun_l10_n547(x) + if (x < 1) + fun_l11_n374(x) + else + fun_l11_n293(x) + end +end + +def fun_l10_n548(x) + if (x < 1) + fun_l11_n661(x) + else + fun_l11_n619(x) + end +end + +def fun_l10_n549(x) + if (x < 1) + fun_l11_n984(x) + else + fun_l11_n261(x) + end +end + +def fun_l10_n550(x) + if (x < 1) + fun_l11_n729(x) + else + fun_l11_n469(x) + end +end + +def fun_l10_n551(x) + if (x < 1) + fun_l11_n829(x) + else + fun_l11_n30(x) + end +end + +def fun_l10_n552(x) + if (x < 1) + fun_l11_n457(x) + else + fun_l11_n440(x) + end +end + +def fun_l10_n553(x) + if (x < 1) + fun_l11_n128(x) + else + fun_l11_n790(x) + end +end + +def fun_l10_n554(x) + if (x < 1) + fun_l11_n135(x) + else + fun_l11_n118(x) + end +end + +def fun_l10_n555(x) + if (x < 1) + fun_l11_n558(x) + else + fun_l11_n415(x) + end +end + +def fun_l10_n556(x) + if (x < 1) + fun_l11_n388(x) + else + fun_l11_n102(x) + end +end + +def fun_l10_n557(x) + if (x < 1) + fun_l11_n575(x) + else + fun_l11_n877(x) + end +end + +def fun_l10_n558(x) + if (x < 1) + fun_l11_n266(x) + else + fun_l11_n216(x) + end +end + +def fun_l10_n559(x) + if (x < 1) + fun_l11_n681(x) + else + fun_l11_n259(x) + end +end + +def fun_l10_n560(x) + if (x < 1) + fun_l11_n922(x) + else + fun_l11_n828(x) + end +end + +def fun_l10_n561(x) + if (x < 1) + fun_l11_n135(x) + else + fun_l11_n971(x) + end +end + +def fun_l10_n562(x) + if (x < 1) + fun_l11_n940(x) + else + fun_l11_n266(x) + end +end + +def fun_l10_n563(x) + if (x < 1) + fun_l11_n291(x) + else + fun_l11_n587(x) + end +end + +def fun_l10_n564(x) + if (x < 1) + fun_l11_n143(x) + else + fun_l11_n289(x) + end +end + +def fun_l10_n565(x) + if (x < 1) + fun_l11_n947(x) + else + fun_l11_n462(x) + end +end + +def fun_l10_n566(x) + if (x < 1) + fun_l11_n307(x) + else + fun_l11_n904(x) + end +end + +def fun_l10_n567(x) + if (x < 1) + fun_l11_n945(x) + else + fun_l11_n814(x) + end +end + +def fun_l10_n568(x) + if (x < 1) + fun_l11_n689(x) + else + fun_l11_n61(x) + end +end + +def fun_l10_n569(x) + if (x < 1) + fun_l11_n446(x) + else + fun_l11_n305(x) + end +end + +def fun_l10_n570(x) + if (x < 1) + fun_l11_n209(x) + else + fun_l11_n768(x) + end +end + +def fun_l10_n571(x) + if (x < 1) + fun_l11_n904(x) + else + fun_l11_n736(x) + end +end + +def fun_l10_n572(x) + if (x < 1) + fun_l11_n87(x) + else + fun_l11_n474(x) + end +end + +def fun_l10_n573(x) + if (x < 1) + fun_l11_n886(x) + else + fun_l11_n75(x) + end +end + +def fun_l10_n574(x) + if (x < 1) + fun_l11_n761(x) + else + fun_l11_n662(x) + end +end + +def fun_l10_n575(x) + if (x < 1) + fun_l11_n255(x) + else + fun_l11_n321(x) + end +end + +def fun_l10_n576(x) + if (x < 1) + fun_l11_n154(x) + else + fun_l11_n356(x) + end +end + +def fun_l10_n577(x) + if (x < 1) + fun_l11_n802(x) + else + fun_l11_n912(x) + end +end + +def fun_l10_n578(x) + if (x < 1) + fun_l11_n709(x) + else + fun_l11_n66(x) + end +end + +def fun_l10_n579(x) + if (x < 1) + fun_l11_n994(x) + else + fun_l11_n424(x) + end +end + +def fun_l10_n580(x) + if (x < 1) + fun_l11_n520(x) + else + fun_l11_n551(x) + end +end + +def fun_l10_n581(x) + if (x < 1) + fun_l11_n386(x) + else + fun_l11_n615(x) + end +end + +def fun_l10_n582(x) + if (x < 1) + fun_l11_n125(x) + else + fun_l11_n667(x) + end +end + +def fun_l10_n583(x) + if (x < 1) + fun_l11_n829(x) + else + fun_l11_n802(x) + end +end + +def fun_l10_n584(x) + if (x < 1) + fun_l11_n649(x) + else + fun_l11_n39(x) + end +end + +def fun_l10_n585(x) + if (x < 1) + fun_l11_n454(x) + else + fun_l11_n541(x) + end +end + +def fun_l10_n586(x) + if (x < 1) + fun_l11_n281(x) + else + fun_l11_n4(x) + end +end + +def fun_l10_n587(x) + if (x < 1) + fun_l11_n382(x) + else + fun_l11_n656(x) + end +end + +def fun_l10_n588(x) + if (x < 1) + fun_l11_n177(x) + else + fun_l11_n38(x) + end +end + +def fun_l10_n589(x) + if (x < 1) + fun_l11_n555(x) + else + fun_l11_n557(x) + end +end + +def fun_l10_n590(x) + if (x < 1) + fun_l11_n999(x) + else + fun_l11_n645(x) + end +end + +def fun_l10_n591(x) + if (x < 1) + fun_l11_n714(x) + else + fun_l11_n872(x) + end +end + +def fun_l10_n592(x) + if (x < 1) + fun_l11_n779(x) + else + fun_l11_n524(x) + end +end + +def fun_l10_n593(x) + if (x < 1) + fun_l11_n557(x) + else + fun_l11_n906(x) + end +end + +def fun_l10_n594(x) + if (x < 1) + fun_l11_n379(x) + else + fun_l11_n550(x) + end +end + +def fun_l10_n595(x) + if (x < 1) + fun_l11_n138(x) + else + fun_l11_n785(x) + end +end + +def fun_l10_n596(x) + if (x < 1) + fun_l11_n486(x) + else + fun_l11_n381(x) + end +end + +def fun_l10_n597(x) + if (x < 1) + fun_l11_n374(x) + else + fun_l11_n477(x) + end +end + +def fun_l10_n598(x) + if (x < 1) + fun_l11_n113(x) + else + fun_l11_n455(x) + end +end + +def fun_l10_n599(x) + if (x < 1) + fun_l11_n31(x) + else + fun_l11_n983(x) + end +end + +def fun_l10_n600(x) + if (x < 1) + fun_l11_n758(x) + else + fun_l11_n187(x) + end +end + +def fun_l10_n601(x) + if (x < 1) + fun_l11_n198(x) + else + fun_l11_n436(x) + end +end + +def fun_l10_n602(x) + if (x < 1) + fun_l11_n207(x) + else + fun_l11_n86(x) + end +end + +def fun_l10_n603(x) + if (x < 1) + fun_l11_n827(x) + else + fun_l11_n267(x) + end +end + +def fun_l10_n604(x) + if (x < 1) + fun_l11_n760(x) + else + fun_l11_n707(x) + end +end + +def fun_l10_n605(x) + if (x < 1) + fun_l11_n791(x) + else + fun_l11_n249(x) + end +end + +def fun_l10_n606(x) + if (x < 1) + fun_l11_n634(x) + else + fun_l11_n607(x) + end +end + +def fun_l10_n607(x) + if (x < 1) + fun_l11_n605(x) + else + fun_l11_n698(x) + end +end + +def fun_l10_n608(x) + if (x < 1) + fun_l11_n401(x) + else + fun_l11_n316(x) + end +end + +def fun_l10_n609(x) + if (x < 1) + fun_l11_n928(x) + else + fun_l11_n313(x) + end +end + +def fun_l10_n610(x) + if (x < 1) + fun_l11_n601(x) + else + fun_l11_n278(x) + end +end + +def fun_l10_n611(x) + if (x < 1) + fun_l11_n554(x) + else + fun_l11_n584(x) + end +end + +def fun_l10_n612(x) + if (x < 1) + fun_l11_n906(x) + else + fun_l11_n58(x) + end +end + +def fun_l10_n613(x) + if (x < 1) + fun_l11_n85(x) + else + fun_l11_n631(x) + end +end + +def fun_l10_n614(x) + if (x < 1) + fun_l11_n221(x) + else + fun_l11_n85(x) + end +end + +def fun_l10_n615(x) + if (x < 1) + fun_l11_n88(x) + else + fun_l11_n367(x) + end +end + +def fun_l10_n616(x) + if (x < 1) + fun_l11_n693(x) + else + fun_l11_n385(x) + end +end + +def fun_l10_n617(x) + if (x < 1) + fun_l11_n18(x) + else + fun_l11_n526(x) + end +end + +def fun_l10_n618(x) + if (x < 1) + fun_l11_n307(x) + else + fun_l11_n303(x) + end +end + +def fun_l10_n619(x) + if (x < 1) + fun_l11_n972(x) + else + fun_l11_n246(x) + end +end + +def fun_l10_n620(x) + if (x < 1) + fun_l11_n185(x) + else + fun_l11_n512(x) + end +end + +def fun_l10_n621(x) + if (x < 1) + fun_l11_n87(x) + else + fun_l11_n131(x) + end +end + +def fun_l10_n622(x) + if (x < 1) + fun_l11_n617(x) + else + fun_l11_n869(x) + end +end + +def fun_l10_n623(x) + if (x < 1) + fun_l11_n514(x) + else + fun_l11_n824(x) + end +end + +def fun_l10_n624(x) + if (x < 1) + fun_l11_n551(x) + else + fun_l11_n430(x) + end +end + +def fun_l10_n625(x) + if (x < 1) + fun_l11_n266(x) + else + fun_l11_n826(x) + end +end + +def fun_l10_n626(x) + if (x < 1) + fun_l11_n90(x) + else + fun_l11_n866(x) + end +end + +def fun_l10_n627(x) + if (x < 1) + fun_l11_n34(x) + else + fun_l11_n694(x) + end +end + +def fun_l10_n628(x) + if (x < 1) + fun_l11_n455(x) + else + fun_l11_n990(x) + end +end + +def fun_l10_n629(x) + if (x < 1) + fun_l11_n573(x) + else + fun_l11_n874(x) + end +end + +def fun_l10_n630(x) + if (x < 1) + fun_l11_n836(x) + else + fun_l11_n87(x) + end +end + +def fun_l10_n631(x) + if (x < 1) + fun_l11_n234(x) + else + fun_l11_n389(x) + end +end + +def fun_l10_n632(x) + if (x < 1) + fun_l11_n647(x) + else + fun_l11_n655(x) + end +end + +def fun_l10_n633(x) + if (x < 1) + fun_l11_n649(x) + else + fun_l11_n426(x) + end +end + +def fun_l10_n634(x) + if (x < 1) + fun_l11_n613(x) + else + fun_l11_n10(x) + end +end + +def fun_l10_n635(x) + if (x < 1) + fun_l11_n315(x) + else + fun_l11_n419(x) + end +end + +def fun_l10_n636(x) + if (x < 1) + fun_l11_n575(x) + else + fun_l11_n29(x) + end +end + +def fun_l10_n637(x) + if (x < 1) + fun_l11_n75(x) + else + fun_l11_n710(x) + end +end + +def fun_l10_n638(x) + if (x < 1) + fun_l11_n42(x) + else + fun_l11_n45(x) + end +end + +def fun_l10_n639(x) + if (x < 1) + fun_l11_n629(x) + else + fun_l11_n850(x) + end +end + +def fun_l10_n640(x) + if (x < 1) + fun_l11_n491(x) + else + fun_l11_n708(x) + end +end + +def fun_l10_n641(x) + if (x < 1) + fun_l11_n673(x) + else + fun_l11_n722(x) + end +end + +def fun_l10_n642(x) + if (x < 1) + fun_l11_n922(x) + else + fun_l11_n783(x) + end +end + +def fun_l10_n643(x) + if (x < 1) + fun_l11_n855(x) + else + fun_l11_n145(x) + end +end + +def fun_l10_n644(x) + if (x < 1) + fun_l11_n897(x) + else + fun_l11_n281(x) + end +end + +def fun_l10_n645(x) + if (x < 1) + fun_l11_n148(x) + else + fun_l11_n786(x) + end +end + +def fun_l10_n646(x) + if (x < 1) + fun_l11_n743(x) + else + fun_l11_n627(x) + end +end + +def fun_l10_n647(x) + if (x < 1) + fun_l11_n343(x) + else + fun_l11_n234(x) + end +end + +def fun_l10_n648(x) + if (x < 1) + fun_l11_n995(x) + else + fun_l11_n199(x) + end +end + +def fun_l10_n649(x) + if (x < 1) + fun_l11_n155(x) + else + fun_l11_n384(x) + end +end + +def fun_l10_n650(x) + if (x < 1) + fun_l11_n329(x) + else + fun_l11_n313(x) + end +end + +def fun_l10_n651(x) + if (x < 1) + fun_l11_n254(x) + else + fun_l11_n763(x) + end +end + +def fun_l10_n652(x) + if (x < 1) + fun_l11_n839(x) + else + fun_l11_n692(x) + end +end + +def fun_l10_n653(x) + if (x < 1) + fun_l11_n388(x) + else + fun_l11_n187(x) + end +end + +def fun_l10_n654(x) + if (x < 1) + fun_l11_n919(x) + else + fun_l11_n198(x) + end +end + +def fun_l10_n655(x) + if (x < 1) + fun_l11_n313(x) + else + fun_l11_n686(x) + end +end + +def fun_l10_n656(x) + if (x < 1) + fun_l11_n91(x) + else + fun_l11_n95(x) + end +end + +def fun_l10_n657(x) + if (x < 1) + fun_l11_n801(x) + else + fun_l11_n700(x) + end +end + +def fun_l10_n658(x) + if (x < 1) + fun_l11_n938(x) + else + fun_l11_n936(x) + end +end + +def fun_l10_n659(x) + if (x < 1) + fun_l11_n78(x) + else + fun_l11_n611(x) + end +end + +def fun_l10_n660(x) + if (x < 1) + fun_l11_n261(x) + else + fun_l11_n396(x) + end +end + +def fun_l10_n661(x) + if (x < 1) + fun_l11_n154(x) + else + fun_l11_n132(x) + end +end + +def fun_l10_n662(x) + if (x < 1) + fun_l11_n603(x) + else + fun_l11_n718(x) + end +end + +def fun_l10_n663(x) + if (x < 1) + fun_l11_n512(x) + else + fun_l11_n158(x) + end +end + +def fun_l10_n664(x) + if (x < 1) + fun_l11_n178(x) + else + fun_l11_n59(x) + end +end + +def fun_l10_n665(x) + if (x < 1) + fun_l11_n703(x) + else + fun_l11_n54(x) + end +end + +def fun_l10_n666(x) + if (x < 1) + fun_l11_n623(x) + else + fun_l11_n793(x) + end +end + +def fun_l10_n667(x) + if (x < 1) + fun_l11_n350(x) + else + fun_l11_n244(x) + end +end + +def fun_l10_n668(x) + if (x < 1) + fun_l11_n253(x) + else + fun_l11_n297(x) + end +end + +def fun_l10_n669(x) + if (x < 1) + fun_l11_n137(x) + else + fun_l11_n76(x) + end +end + +def fun_l10_n670(x) + if (x < 1) + fun_l11_n755(x) + else + fun_l11_n627(x) + end +end + +def fun_l10_n671(x) + if (x < 1) + fun_l11_n393(x) + else + fun_l11_n394(x) + end +end + +def fun_l10_n672(x) + if (x < 1) + fun_l11_n858(x) + else + fun_l11_n823(x) + end +end + +def fun_l10_n673(x) + if (x < 1) + fun_l11_n202(x) + else + fun_l11_n800(x) + end +end + +def fun_l10_n674(x) + if (x < 1) + fun_l11_n977(x) + else + fun_l11_n343(x) + end +end + +def fun_l10_n675(x) + if (x < 1) + fun_l11_n352(x) + else + fun_l11_n690(x) + end +end + +def fun_l10_n676(x) + if (x < 1) + fun_l11_n598(x) + else + fun_l11_n108(x) + end +end + +def fun_l10_n677(x) + if (x < 1) + fun_l11_n126(x) + else + fun_l11_n226(x) + end +end + +def fun_l10_n678(x) + if (x < 1) + fun_l11_n937(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n679(x) + if (x < 1) + fun_l11_n231(x) + else + fun_l11_n264(x) + end +end + +def fun_l10_n680(x) + if (x < 1) + fun_l11_n657(x) + else + fun_l11_n766(x) + end +end + +def fun_l10_n681(x) + if (x < 1) + fun_l11_n444(x) + else + fun_l11_n405(x) + end +end + +def fun_l10_n682(x) + if (x < 1) + fun_l11_n410(x) + else + fun_l11_n409(x) + end +end + +def fun_l10_n683(x) + if (x < 1) + fun_l11_n690(x) + else + fun_l11_n673(x) + end +end + +def fun_l10_n684(x) + if (x < 1) + fun_l11_n737(x) + else + fun_l11_n61(x) + end +end + +def fun_l10_n685(x) + if (x < 1) + fun_l11_n54(x) + else + fun_l11_n387(x) + end +end + +def fun_l10_n686(x) + if (x < 1) + fun_l11_n271(x) + else + fun_l11_n698(x) + end +end + +def fun_l10_n687(x) + if (x < 1) + fun_l11_n988(x) + else + fun_l11_n816(x) + end +end + +def fun_l10_n688(x) + if (x < 1) + fun_l11_n309(x) + else + fun_l11_n576(x) + end +end + +def fun_l10_n689(x) + if (x < 1) + fun_l11_n390(x) + else + fun_l11_n35(x) + end +end + +def fun_l10_n690(x) + if (x < 1) + fun_l11_n93(x) + else + fun_l11_n712(x) + end +end + +def fun_l10_n691(x) + if (x < 1) + fun_l11_n285(x) + else + fun_l11_n467(x) + end +end + +def fun_l10_n692(x) + if (x < 1) + fun_l11_n403(x) + else + fun_l11_n41(x) + end +end + +def fun_l10_n693(x) + if (x < 1) + fun_l11_n228(x) + else + fun_l11_n689(x) + end +end + +def fun_l10_n694(x) + if (x < 1) + fun_l11_n581(x) + else + fun_l11_n989(x) + end +end + +def fun_l10_n695(x) + if (x < 1) + fun_l11_n451(x) + else + fun_l11_n618(x) + end +end + +def fun_l10_n696(x) + if (x < 1) + fun_l11_n640(x) + else + fun_l11_n13(x) + end +end + +def fun_l10_n697(x) + if (x < 1) + fun_l11_n968(x) + else + fun_l11_n903(x) + end +end + +def fun_l10_n698(x) + if (x < 1) + fun_l11_n918(x) + else + fun_l11_n244(x) + end +end + +def fun_l10_n699(x) + if (x < 1) + fun_l11_n17(x) + else + fun_l11_n17(x) + end +end + +def fun_l10_n700(x) + if (x < 1) + fun_l11_n918(x) + else + fun_l11_n539(x) + end +end + +def fun_l10_n701(x) + if (x < 1) + fun_l11_n924(x) + else + fun_l11_n103(x) + end +end + +def fun_l10_n702(x) + if (x < 1) + fun_l11_n908(x) + else + fun_l11_n328(x) + end +end + +def fun_l10_n703(x) + if (x < 1) + fun_l11_n393(x) + else + fun_l11_n386(x) + end +end + +def fun_l10_n704(x) + if (x < 1) + fun_l11_n194(x) + else + fun_l11_n812(x) + end +end + +def fun_l10_n705(x) + if (x < 1) + fun_l11_n382(x) + else + fun_l11_n276(x) + end +end + +def fun_l10_n706(x) + if (x < 1) + fun_l11_n257(x) + else + fun_l11_n269(x) + end +end + +def fun_l10_n707(x) + if (x < 1) + fun_l11_n940(x) + else + fun_l11_n593(x) + end +end + +def fun_l10_n708(x) + if (x < 1) + fun_l11_n710(x) + else + fun_l11_n992(x) + end +end + +def fun_l10_n709(x) + if (x < 1) + fun_l11_n244(x) + else + fun_l11_n500(x) + end +end + +def fun_l10_n710(x) + if (x < 1) + fun_l11_n712(x) + else + fun_l11_n544(x) + end +end + +def fun_l10_n711(x) + if (x < 1) + fun_l11_n701(x) + else + fun_l11_n104(x) + end +end + +def fun_l10_n712(x) + if (x < 1) + fun_l11_n706(x) + else + fun_l11_n199(x) + end +end + +def fun_l10_n713(x) + if (x < 1) + fun_l11_n189(x) + else + fun_l11_n840(x) + end +end + +def fun_l10_n714(x) + if (x < 1) + fun_l11_n122(x) + else + fun_l11_n318(x) + end +end + +def fun_l10_n715(x) + if (x < 1) + fun_l11_n915(x) + else + fun_l11_n964(x) + end +end + +def fun_l10_n716(x) + if (x < 1) + fun_l11_n341(x) + else + fun_l11_n118(x) + end +end + +def fun_l10_n717(x) + if (x < 1) + fun_l11_n846(x) + else + fun_l11_n235(x) + end +end + +def fun_l10_n718(x) + if (x < 1) + fun_l11_n679(x) + else + fun_l11_n959(x) + end +end + +def fun_l10_n719(x) + if (x < 1) + fun_l11_n121(x) + else + fun_l11_n708(x) + end +end + +def fun_l10_n720(x) + if (x < 1) + fun_l11_n651(x) + else + fun_l11_n480(x) + end +end + +def fun_l10_n721(x) + if (x < 1) + fun_l11_n773(x) + else + fun_l11_n568(x) + end +end + +def fun_l10_n722(x) + if (x < 1) + fun_l11_n809(x) + else + fun_l11_n111(x) + end +end + +def fun_l10_n723(x) + if (x < 1) + fun_l11_n586(x) + else + fun_l11_n553(x) + end +end + +def fun_l10_n724(x) + if (x < 1) + fun_l11_n473(x) + else + fun_l11_n387(x) + end +end + +def fun_l10_n725(x) + if (x < 1) + fun_l11_n584(x) + else + fun_l11_n224(x) + end +end + +def fun_l10_n726(x) + if (x < 1) + fun_l11_n110(x) + else + fun_l11_n827(x) + end +end + +def fun_l10_n727(x) + if (x < 1) + fun_l11_n753(x) + else + fun_l11_n745(x) + end +end + +def fun_l10_n728(x) + if (x < 1) + fun_l11_n550(x) + else + fun_l11_n380(x) + end +end + +def fun_l10_n729(x) + if (x < 1) + fun_l11_n844(x) + else + fun_l11_n401(x) + end +end + +def fun_l10_n730(x) + if (x < 1) + fun_l11_n837(x) + else + fun_l11_n759(x) + end +end + +def fun_l10_n731(x) + if (x < 1) + fun_l11_n850(x) + else + fun_l11_n953(x) + end +end + +def fun_l10_n732(x) + if (x < 1) + fun_l11_n872(x) + else + fun_l11_n864(x) + end +end + +def fun_l10_n733(x) + if (x < 1) + fun_l11_n894(x) + else + fun_l11_n943(x) + end +end + +def fun_l10_n734(x) + if (x < 1) + fun_l11_n830(x) + else + fun_l11_n858(x) + end +end + +def fun_l10_n735(x) + if (x < 1) + fun_l11_n661(x) + else + fun_l11_n366(x) + end +end + +def fun_l10_n736(x) + if (x < 1) + fun_l11_n736(x) + else + fun_l11_n636(x) + end +end + +def fun_l10_n737(x) + if (x < 1) + fun_l11_n316(x) + else + fun_l11_n977(x) + end +end + +def fun_l10_n738(x) + if (x < 1) + fun_l11_n54(x) + else + fun_l11_n386(x) + end +end + +def fun_l10_n739(x) + if (x < 1) + fun_l11_n985(x) + else + fun_l11_n274(x) + end +end + +def fun_l10_n740(x) + if (x < 1) + fun_l11_n756(x) + else + fun_l11_n171(x) + end +end + +def fun_l10_n741(x) + if (x < 1) + fun_l11_n457(x) + else + fun_l11_n251(x) + end +end + +def fun_l10_n742(x) + if (x < 1) + fun_l11_n751(x) + else + fun_l11_n29(x) + end +end + +def fun_l10_n743(x) + if (x < 1) + fun_l11_n6(x) + else + fun_l11_n892(x) + end +end + +def fun_l10_n744(x) + if (x < 1) + fun_l11_n85(x) + else + fun_l11_n205(x) + end +end + +def fun_l10_n745(x) + if (x < 1) + fun_l11_n887(x) + else + fun_l11_n734(x) + end +end + +def fun_l10_n746(x) + if (x < 1) + fun_l11_n478(x) + else + fun_l11_n505(x) + end +end + +def fun_l10_n747(x) + if (x < 1) + fun_l11_n760(x) + else + fun_l11_n286(x) + end +end + +def fun_l10_n748(x) + if (x < 1) + fun_l11_n391(x) + else + fun_l11_n69(x) + end +end + +def fun_l10_n749(x) + if (x < 1) + fun_l11_n780(x) + else + fun_l11_n28(x) + end +end + +def fun_l10_n750(x) + if (x < 1) + fun_l11_n337(x) + else + fun_l11_n647(x) + end +end + +def fun_l10_n751(x) + if (x < 1) + fun_l11_n92(x) + else + fun_l11_n121(x) + end +end + +def fun_l10_n752(x) + if (x < 1) + fun_l11_n358(x) + else + fun_l11_n177(x) + end +end + +def fun_l10_n753(x) + if (x < 1) + fun_l11_n642(x) + else + fun_l11_n426(x) + end +end + +def fun_l10_n754(x) + if (x < 1) + fun_l11_n66(x) + else + fun_l11_n948(x) + end +end + +def fun_l10_n755(x) + if (x < 1) + fun_l11_n45(x) + else + fun_l11_n795(x) + end +end + +def fun_l10_n756(x) + if (x < 1) + fun_l11_n734(x) + else + fun_l11_n162(x) + end +end + +def fun_l10_n757(x) + if (x < 1) + fun_l11_n689(x) + else + fun_l11_n31(x) + end +end + +def fun_l10_n758(x) + if (x < 1) + fun_l11_n33(x) + else + fun_l11_n992(x) + end +end + +def fun_l10_n759(x) + if (x < 1) + fun_l11_n210(x) + else + fun_l11_n330(x) + end +end + +def fun_l10_n760(x) + if (x < 1) + fun_l11_n727(x) + else + fun_l11_n265(x) + end +end + +def fun_l10_n761(x) + if (x < 1) + fun_l11_n710(x) + else + fun_l11_n706(x) + end +end + +def fun_l10_n762(x) + if (x < 1) + fun_l11_n791(x) + else + fun_l11_n325(x) + end +end + +def fun_l10_n763(x) + if (x < 1) + fun_l11_n350(x) + else + fun_l11_n443(x) + end +end + +def fun_l10_n764(x) + if (x < 1) + fun_l11_n522(x) + else + fun_l11_n662(x) + end +end + +def fun_l10_n765(x) + if (x < 1) + fun_l11_n786(x) + else + fun_l11_n969(x) + end +end + +def fun_l10_n766(x) + if (x < 1) + fun_l11_n486(x) + else + fun_l11_n834(x) + end +end + +def fun_l10_n767(x) + if (x < 1) + fun_l11_n84(x) + else + fun_l11_n989(x) + end +end + +def fun_l10_n768(x) + if (x < 1) + fun_l11_n511(x) + else + fun_l11_n0(x) + end +end + +def fun_l10_n769(x) + if (x < 1) + fun_l11_n459(x) + else + fun_l11_n243(x) + end +end + +def fun_l10_n770(x) + if (x < 1) + fun_l11_n59(x) + else + fun_l11_n267(x) + end +end + +def fun_l10_n771(x) + if (x < 1) + fun_l11_n435(x) + else + fun_l11_n132(x) + end +end + +def fun_l10_n772(x) + if (x < 1) + fun_l11_n986(x) + else + fun_l11_n227(x) + end +end + +def fun_l10_n773(x) + if (x < 1) + fun_l11_n931(x) + else + fun_l11_n215(x) + end +end + +def fun_l10_n774(x) + if (x < 1) + fun_l11_n586(x) + else + fun_l11_n170(x) + end +end + +def fun_l10_n775(x) + if (x < 1) + fun_l11_n334(x) + else + fun_l11_n780(x) + end +end + +def fun_l10_n776(x) + if (x < 1) + fun_l11_n81(x) + else + fun_l11_n583(x) + end +end + +def fun_l10_n777(x) + if (x < 1) + fun_l11_n118(x) + else + fun_l11_n451(x) + end +end + +def fun_l10_n778(x) + if (x < 1) + fun_l11_n767(x) + else + fun_l11_n824(x) + end +end + +def fun_l10_n779(x) + if (x < 1) + fun_l11_n270(x) + else + fun_l11_n725(x) + end +end + +def fun_l10_n780(x) + if (x < 1) + fun_l11_n146(x) + else + fun_l11_n407(x) + end +end + +def fun_l10_n781(x) + if (x < 1) + fun_l11_n103(x) + else + fun_l11_n523(x) + end +end + +def fun_l10_n782(x) + if (x < 1) + fun_l11_n499(x) + else + fun_l11_n710(x) + end +end + +def fun_l10_n783(x) + if (x < 1) + fun_l11_n971(x) + else + fun_l11_n426(x) + end +end + +def fun_l10_n784(x) + if (x < 1) + fun_l11_n457(x) + else + fun_l11_n207(x) + end +end + +def fun_l10_n785(x) + if (x < 1) + fun_l11_n307(x) + else + fun_l11_n19(x) + end +end + +def fun_l10_n786(x) + if (x < 1) + fun_l11_n458(x) + else + fun_l11_n243(x) + end +end + +def fun_l10_n787(x) + if (x < 1) + fun_l11_n488(x) + else + fun_l11_n694(x) + end +end + +def fun_l10_n788(x) + if (x < 1) + fun_l11_n422(x) + else + fun_l11_n201(x) + end +end + +def fun_l10_n789(x) + if (x < 1) + fun_l11_n45(x) + else + fun_l11_n993(x) + end +end + +def fun_l10_n790(x) + if (x < 1) + fun_l11_n443(x) + else + fun_l11_n124(x) + end +end + +def fun_l10_n791(x) + if (x < 1) + fun_l11_n875(x) + else + fun_l11_n605(x) + end +end + +def fun_l10_n792(x) + if (x < 1) + fun_l11_n836(x) + else + fun_l11_n776(x) + end +end + +def fun_l10_n793(x) + if (x < 1) + fun_l11_n58(x) + else + fun_l11_n847(x) + end +end + +def fun_l10_n794(x) + if (x < 1) + fun_l11_n334(x) + else + fun_l11_n981(x) + end +end + +def fun_l10_n795(x) + if (x < 1) + fun_l11_n187(x) + else + fun_l11_n599(x) + end +end + +def fun_l10_n796(x) + if (x < 1) + fun_l11_n37(x) + else + fun_l11_n211(x) + end +end + +def fun_l10_n797(x) + if (x < 1) + fun_l11_n770(x) + else + fun_l11_n688(x) + end +end + +def fun_l10_n798(x) + if (x < 1) + fun_l11_n728(x) + else + fun_l11_n150(x) + end +end + +def fun_l10_n799(x) + if (x < 1) + fun_l11_n175(x) + else + fun_l11_n762(x) + end +end + +def fun_l10_n800(x) + if (x < 1) + fun_l11_n977(x) + else + fun_l11_n86(x) + end +end + +def fun_l10_n801(x) + if (x < 1) + fun_l11_n669(x) + else + fun_l11_n120(x) + end +end + +def fun_l10_n802(x) + if (x < 1) + fun_l11_n630(x) + else + fun_l11_n839(x) + end +end + +def fun_l10_n803(x) + if (x < 1) + fun_l11_n505(x) + else + fun_l11_n461(x) + end +end + +def fun_l10_n804(x) + if (x < 1) + fun_l11_n757(x) + else + fun_l11_n620(x) + end +end + +def fun_l10_n805(x) + if (x < 1) + fun_l11_n379(x) + else + fun_l11_n468(x) + end +end + +def fun_l10_n806(x) + if (x < 1) + fun_l11_n708(x) + else + fun_l11_n73(x) + end +end + +def fun_l10_n807(x) + if (x < 1) + fun_l11_n340(x) + else + fun_l11_n671(x) + end +end + +def fun_l10_n808(x) + if (x < 1) + fun_l11_n628(x) + else + fun_l11_n912(x) + end +end + +def fun_l10_n809(x) + if (x < 1) + fun_l11_n455(x) + else + fun_l11_n20(x) + end +end + +def fun_l10_n810(x) + if (x < 1) + fun_l11_n211(x) + else + fun_l11_n724(x) + end +end + +def fun_l10_n811(x) + if (x < 1) + fun_l11_n982(x) + else + fun_l11_n876(x) + end +end + +def fun_l10_n812(x) + if (x < 1) + fun_l11_n455(x) + else + fun_l11_n846(x) + end +end + +def fun_l10_n813(x) + if (x < 1) + fun_l11_n317(x) + else + fun_l11_n909(x) + end +end + +def fun_l10_n814(x) + if (x < 1) + fun_l11_n622(x) + else + fun_l11_n147(x) + end +end + +def fun_l10_n815(x) + if (x < 1) + fun_l11_n174(x) + else + fun_l11_n660(x) + end +end + +def fun_l10_n816(x) + if (x < 1) + fun_l11_n63(x) + else + fun_l11_n427(x) + end +end + +def fun_l10_n817(x) + if (x < 1) + fun_l11_n944(x) + else + fun_l11_n40(x) + end +end + +def fun_l10_n818(x) + if (x < 1) + fun_l11_n887(x) + else + fun_l11_n641(x) + end +end + +def fun_l10_n819(x) + if (x < 1) + fun_l11_n237(x) + else + fun_l11_n568(x) + end +end + +def fun_l10_n820(x) + if (x < 1) + fun_l11_n415(x) + else + fun_l11_n374(x) + end +end + +def fun_l10_n821(x) + if (x < 1) + fun_l11_n183(x) + else + fun_l11_n38(x) + end +end + +def fun_l10_n822(x) + if (x < 1) + fun_l11_n835(x) + else + fun_l11_n406(x) + end +end + +def fun_l10_n823(x) + if (x < 1) + fun_l11_n233(x) + else + fun_l11_n118(x) + end +end + +def fun_l10_n824(x) + if (x < 1) + fun_l11_n898(x) + else + fun_l11_n543(x) + end +end + +def fun_l10_n825(x) + if (x < 1) + fun_l11_n971(x) + else + fun_l11_n750(x) + end +end + +def fun_l10_n826(x) + if (x < 1) + fun_l11_n254(x) + else + fun_l11_n759(x) + end +end + +def fun_l10_n827(x) + if (x < 1) + fun_l11_n953(x) + else + fun_l11_n187(x) + end +end + +def fun_l10_n828(x) + if (x < 1) + fun_l11_n403(x) + else + fun_l11_n170(x) + end +end + +def fun_l10_n829(x) + if (x < 1) + fun_l11_n251(x) + else + fun_l11_n506(x) + end +end + +def fun_l10_n830(x) + if (x < 1) + fun_l11_n426(x) + else + fun_l11_n325(x) + end +end + +def fun_l10_n831(x) + if (x < 1) + fun_l11_n958(x) + else + fun_l11_n4(x) + end +end + +def fun_l10_n832(x) + if (x < 1) + fun_l11_n628(x) + else + fun_l11_n920(x) + end +end + +def fun_l10_n833(x) + if (x < 1) + fun_l11_n241(x) + else + fun_l11_n459(x) + end +end + +def fun_l10_n834(x) + if (x < 1) + fun_l11_n559(x) + else + fun_l11_n671(x) + end +end + +def fun_l10_n835(x) + if (x < 1) + fun_l11_n980(x) + else + fun_l11_n295(x) + end +end + +def fun_l10_n836(x) + if (x < 1) + fun_l11_n306(x) + else + fun_l11_n143(x) + end +end + +def fun_l10_n837(x) + if (x < 1) + fun_l11_n176(x) + else + fun_l11_n341(x) + end +end + +def fun_l10_n838(x) + if (x < 1) + fun_l11_n130(x) + else + fun_l11_n380(x) + end +end + +def fun_l10_n839(x) + if (x < 1) + fun_l11_n630(x) + else + fun_l11_n216(x) + end +end + +def fun_l10_n840(x) + if (x < 1) + fun_l11_n500(x) + else + fun_l11_n579(x) + end +end + +def fun_l10_n841(x) + if (x < 1) + fun_l11_n312(x) + else + fun_l11_n656(x) + end +end + +def fun_l10_n842(x) + if (x < 1) + fun_l11_n209(x) + else + fun_l11_n332(x) + end +end + +def fun_l10_n843(x) + if (x < 1) + fun_l11_n555(x) + else + fun_l11_n179(x) + end +end + +def fun_l10_n844(x) + if (x < 1) + fun_l11_n154(x) + else + fun_l11_n284(x) + end +end + +def fun_l10_n845(x) + if (x < 1) + fun_l11_n912(x) + else + fun_l11_n543(x) + end +end + +def fun_l10_n846(x) + if (x < 1) + fun_l11_n346(x) + else + fun_l11_n553(x) + end +end + +def fun_l10_n847(x) + if (x < 1) + fun_l11_n117(x) + else + fun_l11_n738(x) + end +end + +def fun_l10_n848(x) + if (x < 1) + fun_l11_n664(x) + else + fun_l11_n988(x) + end +end + +def fun_l10_n849(x) + if (x < 1) + fun_l11_n298(x) + else + fun_l11_n753(x) + end +end + +def fun_l10_n850(x) + if (x < 1) + fun_l11_n177(x) + else + fun_l11_n690(x) + end +end + +def fun_l10_n851(x) + if (x < 1) + fun_l11_n259(x) + else + fun_l11_n713(x) + end +end + +def fun_l10_n852(x) + if (x < 1) + fun_l11_n151(x) + else + fun_l11_n580(x) + end +end + +def fun_l10_n853(x) + if (x < 1) + fun_l11_n274(x) + else + fun_l11_n703(x) + end +end + +def fun_l10_n854(x) + if (x < 1) + fun_l11_n295(x) + else + fun_l11_n885(x) + end +end + +def fun_l10_n855(x) + if (x < 1) + fun_l11_n513(x) + else + fun_l11_n963(x) + end +end + +def fun_l10_n856(x) + if (x < 1) + fun_l11_n855(x) + else + fun_l11_n435(x) + end +end + +def fun_l10_n857(x) + if (x < 1) + fun_l11_n573(x) + else + fun_l11_n489(x) + end +end + +def fun_l10_n858(x) + if (x < 1) + fun_l11_n880(x) + else + fun_l11_n91(x) + end +end + +def fun_l10_n859(x) + if (x < 1) + fun_l11_n993(x) + else + fun_l11_n358(x) + end +end + +def fun_l10_n860(x) + if (x < 1) + fun_l11_n836(x) + else + fun_l11_n192(x) + end +end + +def fun_l10_n861(x) + if (x < 1) + fun_l11_n493(x) + else + fun_l11_n564(x) + end +end + +def fun_l10_n862(x) + if (x < 1) + fun_l11_n111(x) + else + fun_l11_n8(x) + end +end + +def fun_l10_n863(x) + if (x < 1) + fun_l11_n596(x) + else + fun_l11_n129(x) + end +end + +def fun_l10_n864(x) + if (x < 1) + fun_l11_n0(x) + else + fun_l11_n687(x) + end +end + +def fun_l10_n865(x) + if (x < 1) + fun_l11_n543(x) + else + fun_l11_n866(x) + end +end + +def fun_l10_n866(x) + if (x < 1) + fun_l11_n398(x) + else + fun_l11_n532(x) + end +end + +def fun_l10_n867(x) + if (x < 1) + fun_l11_n15(x) + else + fun_l11_n991(x) + end +end + +def fun_l10_n868(x) + if (x < 1) + fun_l11_n890(x) + else + fun_l11_n222(x) + end +end + +def fun_l10_n869(x) + if (x < 1) + fun_l11_n206(x) + else + fun_l11_n983(x) + end +end + +def fun_l10_n870(x) + if (x < 1) + fun_l11_n869(x) + else + fun_l11_n619(x) + end +end + +def fun_l10_n871(x) + if (x < 1) + fun_l11_n417(x) + else + fun_l11_n18(x) + end +end + +def fun_l10_n872(x) + if (x < 1) + fun_l11_n738(x) + else + fun_l11_n473(x) + end +end + +def fun_l10_n873(x) + if (x < 1) + fun_l11_n773(x) + else + fun_l11_n128(x) + end +end + +def fun_l10_n874(x) + if (x < 1) + fun_l11_n930(x) + else + fun_l11_n563(x) + end +end + +def fun_l10_n875(x) + if (x < 1) + fun_l11_n868(x) + else + fun_l11_n356(x) + end +end + +def fun_l10_n876(x) + if (x < 1) + fun_l11_n533(x) + else + fun_l11_n402(x) + end +end + +def fun_l10_n877(x) + if (x < 1) + fun_l11_n959(x) + else + fun_l11_n921(x) + end +end + +def fun_l10_n878(x) + if (x < 1) + fun_l11_n717(x) + else + fun_l11_n484(x) + end +end + +def fun_l10_n879(x) + if (x < 1) + fun_l11_n583(x) + else + fun_l11_n801(x) + end +end + +def fun_l10_n880(x) + if (x < 1) + fun_l11_n576(x) + else + fun_l11_n811(x) + end +end + +def fun_l10_n881(x) + if (x < 1) + fun_l11_n382(x) + else + fun_l11_n585(x) + end +end + +def fun_l10_n882(x) + if (x < 1) + fun_l11_n648(x) + else + fun_l11_n930(x) + end +end + +def fun_l10_n883(x) + if (x < 1) + fun_l11_n246(x) + else + fun_l11_n636(x) + end +end + +def fun_l10_n884(x) + if (x < 1) + fun_l11_n112(x) + else + fun_l11_n798(x) + end +end + +def fun_l10_n885(x) + if (x < 1) + fun_l11_n517(x) + else + fun_l11_n633(x) + end +end + +def fun_l10_n886(x) + if (x < 1) + fun_l11_n651(x) + else + fun_l11_n377(x) + end +end + +def fun_l10_n887(x) + if (x < 1) + fun_l11_n652(x) + else + fun_l11_n419(x) + end +end + +def fun_l10_n888(x) + if (x < 1) + fun_l11_n346(x) + else + fun_l11_n294(x) + end +end + +def fun_l10_n889(x) + if (x < 1) + fun_l11_n809(x) + else + fun_l11_n844(x) + end +end + +def fun_l10_n890(x) + if (x < 1) + fun_l11_n382(x) + else + fun_l11_n930(x) + end +end + +def fun_l10_n891(x) + if (x < 1) + fun_l11_n900(x) + else + fun_l11_n293(x) + end +end + +def fun_l10_n892(x) + if (x < 1) + fun_l11_n912(x) + else + fun_l11_n46(x) + end +end + +def fun_l10_n893(x) + if (x < 1) + fun_l11_n429(x) + else + fun_l11_n174(x) + end +end + +def fun_l10_n894(x) + if (x < 1) + fun_l11_n142(x) + else + fun_l11_n739(x) + end +end + +def fun_l10_n895(x) + if (x < 1) + fun_l11_n300(x) + else + fun_l11_n546(x) + end +end + +def fun_l10_n896(x) + if (x < 1) + fun_l11_n253(x) + else + fun_l11_n555(x) + end +end + +def fun_l10_n897(x) + if (x < 1) + fun_l11_n29(x) + else + fun_l11_n913(x) + end +end + +def fun_l10_n898(x) + if (x < 1) + fun_l11_n879(x) + else + fun_l11_n2(x) + end +end + +def fun_l10_n899(x) + if (x < 1) + fun_l11_n191(x) + else + fun_l11_n418(x) + end +end + +def fun_l10_n900(x) + if (x < 1) + fun_l11_n239(x) + else + fun_l11_n904(x) + end +end + +def fun_l10_n901(x) + if (x < 1) + fun_l11_n962(x) + else + fun_l11_n978(x) + end +end + +def fun_l10_n902(x) + if (x < 1) + fun_l11_n343(x) + else + fun_l11_n358(x) + end +end + +def fun_l10_n903(x) + if (x < 1) + fun_l11_n334(x) + else + fun_l11_n806(x) + end +end + +def fun_l10_n904(x) + if (x < 1) + fun_l11_n973(x) + else + fun_l11_n708(x) + end +end + +def fun_l10_n905(x) + if (x < 1) + fun_l11_n990(x) + else + fun_l11_n211(x) + end +end + +def fun_l10_n906(x) + if (x < 1) + fun_l11_n499(x) + else + fun_l11_n605(x) + end +end + +def fun_l10_n907(x) + if (x < 1) + fun_l11_n335(x) + else + fun_l11_n855(x) + end +end + +def fun_l10_n908(x) + if (x < 1) + fun_l11_n197(x) + else + fun_l11_n130(x) + end +end + +def fun_l10_n909(x) + if (x < 1) + fun_l11_n462(x) + else + fun_l11_n838(x) + end +end + +def fun_l10_n910(x) + if (x < 1) + fun_l11_n254(x) + else + fun_l11_n16(x) + end +end + +def fun_l10_n911(x) + if (x < 1) + fun_l11_n321(x) + else + fun_l11_n158(x) + end +end + +def fun_l10_n912(x) + if (x < 1) + fun_l11_n113(x) + else + fun_l11_n50(x) + end +end + +def fun_l10_n913(x) + if (x < 1) + fun_l11_n492(x) + else + fun_l11_n502(x) + end +end + +def fun_l10_n914(x) + if (x < 1) + fun_l11_n221(x) + else + fun_l11_n732(x) + end +end + +def fun_l10_n915(x) + if (x < 1) + fun_l11_n853(x) + else + fun_l11_n625(x) + end +end + +def fun_l10_n916(x) + if (x < 1) + fun_l11_n172(x) + else + fun_l11_n17(x) + end +end + +def fun_l10_n917(x) + if (x < 1) + fun_l11_n438(x) + else + fun_l11_n480(x) + end +end + +def fun_l10_n918(x) + if (x < 1) + fun_l11_n646(x) + else + fun_l11_n833(x) + end +end + +def fun_l10_n919(x) + if (x < 1) + fun_l11_n628(x) + else + fun_l11_n40(x) + end +end + +def fun_l10_n920(x) + if (x < 1) + fun_l11_n387(x) + else + fun_l11_n824(x) + end +end + +def fun_l10_n921(x) + if (x < 1) + fun_l11_n641(x) + else + fun_l11_n669(x) + end +end + +def fun_l10_n922(x) + if (x < 1) + fun_l11_n484(x) + else + fun_l11_n591(x) + end +end + +def fun_l10_n923(x) + if (x < 1) + fun_l11_n610(x) + else + fun_l11_n132(x) + end +end + +def fun_l10_n924(x) + if (x < 1) + fun_l11_n90(x) + else + fun_l11_n727(x) + end +end + +def fun_l10_n925(x) + if (x < 1) + fun_l11_n44(x) + else + fun_l11_n412(x) + end +end + +def fun_l10_n926(x) + if (x < 1) + fun_l11_n912(x) + else + fun_l11_n229(x) + end +end + +def fun_l10_n927(x) + if (x < 1) + fun_l11_n647(x) + else + fun_l11_n13(x) + end +end + +def fun_l10_n928(x) + if (x < 1) + fun_l11_n820(x) + else + fun_l11_n316(x) + end +end + +def fun_l10_n929(x) + if (x < 1) + fun_l11_n850(x) + else + fun_l11_n868(x) + end +end + +def fun_l10_n930(x) + if (x < 1) + fun_l11_n373(x) + else + fun_l11_n183(x) + end +end + +def fun_l10_n931(x) + if (x < 1) + fun_l11_n217(x) + else + fun_l11_n230(x) + end +end + +def fun_l10_n932(x) + if (x < 1) + fun_l11_n77(x) + else + fun_l11_n917(x) + end +end + +def fun_l10_n933(x) + if (x < 1) + fun_l11_n264(x) + else + fun_l11_n992(x) + end +end + +def fun_l10_n934(x) + if (x < 1) + fun_l11_n125(x) + else + fun_l11_n441(x) + end +end + +def fun_l10_n935(x) + if (x < 1) + fun_l11_n586(x) + else + fun_l11_n946(x) + end +end + +def fun_l10_n936(x) + if (x < 1) + fun_l11_n186(x) + else + fun_l11_n595(x) + end +end + +def fun_l10_n937(x) + if (x < 1) + fun_l11_n210(x) + else + fun_l11_n186(x) + end +end + +def fun_l10_n938(x) + if (x < 1) + fun_l11_n131(x) + else + fun_l11_n519(x) + end +end + +def fun_l10_n939(x) + if (x < 1) + fun_l11_n863(x) + else + fun_l11_n486(x) + end +end + +def fun_l10_n940(x) + if (x < 1) + fun_l11_n753(x) + else + fun_l11_n916(x) + end +end + +def fun_l10_n941(x) + if (x < 1) + fun_l11_n8(x) + else + fun_l11_n153(x) + end +end + +def fun_l10_n942(x) + if (x < 1) + fun_l11_n798(x) + else + fun_l11_n873(x) + end +end + +def fun_l10_n943(x) + if (x < 1) + fun_l11_n862(x) + else + fun_l11_n293(x) + end +end + +def fun_l10_n944(x) + if (x < 1) + fun_l11_n554(x) + else + fun_l11_n599(x) + end +end + +def fun_l10_n945(x) + if (x < 1) + fun_l11_n134(x) + else + fun_l11_n535(x) + end +end + +def fun_l10_n946(x) + if (x < 1) + fun_l11_n992(x) + else + fun_l11_n624(x) + end +end + +def fun_l10_n947(x) + if (x < 1) + fun_l11_n436(x) + else + fun_l11_n153(x) + end +end + +def fun_l10_n948(x) + if (x < 1) + fun_l11_n72(x) + else + fun_l11_n154(x) + end +end + +def fun_l10_n949(x) + if (x < 1) + fun_l11_n61(x) + else + fun_l11_n612(x) + end +end + +def fun_l10_n950(x) + if (x < 1) + fun_l11_n964(x) + else + fun_l11_n999(x) + end +end + +def fun_l10_n951(x) + if (x < 1) + fun_l11_n689(x) + else + fun_l11_n165(x) + end +end + +def fun_l10_n952(x) + if (x < 1) + fun_l11_n856(x) + else + fun_l11_n7(x) + end +end + +def fun_l10_n953(x) + if (x < 1) + fun_l11_n421(x) + else + fun_l11_n416(x) + end +end + +def fun_l10_n954(x) + if (x < 1) + fun_l11_n969(x) + else + fun_l11_n260(x) + end +end + +def fun_l10_n955(x) + if (x < 1) + fun_l11_n716(x) + else + fun_l11_n364(x) + end +end + +def fun_l10_n956(x) + if (x < 1) + fun_l11_n491(x) + else + fun_l11_n575(x) + end +end + +def fun_l10_n957(x) + if (x < 1) + fun_l11_n522(x) + else + fun_l11_n430(x) + end +end + +def fun_l10_n958(x) + if (x < 1) + fun_l11_n712(x) + else + fun_l11_n939(x) + end +end + +def fun_l10_n959(x) + if (x < 1) + fun_l11_n230(x) + else + fun_l11_n819(x) + end +end + +def fun_l10_n960(x) + if (x < 1) + fun_l11_n790(x) + else + fun_l11_n939(x) + end +end + +def fun_l10_n961(x) + if (x < 1) + fun_l11_n844(x) + else + fun_l11_n847(x) + end +end + +def fun_l10_n962(x) + if (x < 1) + fun_l11_n105(x) + else + fun_l11_n722(x) + end +end + +def fun_l10_n963(x) + if (x < 1) + fun_l11_n166(x) + else + fun_l11_n990(x) + end +end + +def fun_l10_n964(x) + if (x < 1) + fun_l11_n224(x) + else + fun_l11_n751(x) + end +end + +def fun_l10_n965(x) + if (x < 1) + fun_l11_n809(x) + else + fun_l11_n739(x) + end +end + +def fun_l10_n966(x) + if (x < 1) + fun_l11_n840(x) + else + fun_l11_n795(x) + end +end + +def fun_l10_n967(x) + if (x < 1) + fun_l11_n791(x) + else + fun_l11_n926(x) + end +end + +def fun_l10_n968(x) + if (x < 1) + fun_l11_n484(x) + else + fun_l11_n409(x) + end +end + +def fun_l10_n969(x) + if (x < 1) + fun_l11_n22(x) + else + fun_l11_n284(x) + end +end + +def fun_l10_n970(x) + if (x < 1) + fun_l11_n539(x) + else + fun_l11_n661(x) + end +end + +def fun_l10_n971(x) + if (x < 1) + fun_l11_n453(x) + else + fun_l11_n619(x) + end +end + +def fun_l10_n972(x) + if (x < 1) + fun_l11_n80(x) + else + fun_l11_n848(x) + end +end + +def fun_l10_n973(x) + if (x < 1) + fun_l11_n599(x) + else + fun_l11_n147(x) + end +end + +def fun_l10_n974(x) + if (x < 1) + fun_l11_n784(x) + else + fun_l11_n603(x) + end +end + +def fun_l10_n975(x) + if (x < 1) + fun_l11_n166(x) + else + fun_l11_n12(x) + end +end + +def fun_l10_n976(x) + if (x < 1) + fun_l11_n739(x) + else + fun_l11_n381(x) + end +end + +def fun_l10_n977(x) + if (x < 1) + fun_l11_n45(x) + else + fun_l11_n67(x) + end +end + +def fun_l10_n978(x) + if (x < 1) + fun_l11_n243(x) + else + fun_l11_n51(x) + end +end + +def fun_l10_n979(x) + if (x < 1) + fun_l11_n964(x) + else + fun_l11_n949(x) + end +end + +def fun_l10_n980(x) + if (x < 1) + fun_l11_n881(x) + else + fun_l11_n893(x) + end +end + +def fun_l10_n981(x) + if (x < 1) + fun_l11_n808(x) + else + fun_l11_n205(x) + end +end + +def fun_l10_n982(x) + if (x < 1) + fun_l11_n897(x) + else + fun_l11_n259(x) + end +end + +def fun_l10_n983(x) + if (x < 1) + fun_l11_n671(x) + else + fun_l11_n115(x) + end +end + +def fun_l10_n984(x) + if (x < 1) + fun_l11_n9(x) + else + fun_l11_n994(x) + end +end + +def fun_l10_n985(x) + if (x < 1) + fun_l11_n663(x) + else + fun_l11_n979(x) + end +end + +def fun_l10_n986(x) + if (x < 1) + fun_l11_n8(x) + else + fun_l11_n949(x) + end +end + +def fun_l10_n987(x) + if (x < 1) + fun_l11_n230(x) + else + fun_l11_n822(x) + end +end + +def fun_l10_n988(x) + if (x < 1) + fun_l11_n767(x) + else + fun_l11_n691(x) + end +end + +def fun_l10_n989(x) + if (x < 1) + fun_l11_n524(x) + else + fun_l11_n514(x) + end +end + +def fun_l10_n990(x) + if (x < 1) + fun_l11_n556(x) + else + fun_l11_n34(x) + end +end + +def fun_l10_n991(x) + if (x < 1) + fun_l11_n516(x) + else + fun_l11_n817(x) + end +end + +def fun_l10_n992(x) + if (x < 1) + fun_l11_n273(x) + else + fun_l11_n189(x) + end +end + +def fun_l10_n993(x) + if (x < 1) + fun_l11_n726(x) + else + fun_l11_n260(x) + end +end + +def fun_l10_n994(x) + if (x < 1) + fun_l11_n789(x) + else + fun_l11_n993(x) + end +end + +def fun_l10_n995(x) + if (x < 1) + fun_l11_n187(x) + else + fun_l11_n291(x) + end +end + +def fun_l10_n996(x) + if (x < 1) + fun_l11_n145(x) + else + fun_l11_n500(x) + end +end + +def fun_l10_n997(x) + if (x < 1) + fun_l11_n437(x) + else + fun_l11_n925(x) + end +end + +def fun_l10_n998(x) + if (x < 1) + fun_l11_n945(x) + else + fun_l11_n300(x) + end +end + +def fun_l10_n999(x) + if (x < 1) + fun_l11_n703(x) + else + fun_l11_n542(x) + end +end + +def fun_l11_n0(x) + if (x < 1) + fun_l12_n539(x) + else + fun_l12_n60(x) + end +end + +def fun_l11_n1(x) + if (x < 1) + fun_l12_n659(x) + else + fun_l12_n739(x) + end +end + +def fun_l11_n2(x) + if (x < 1) + fun_l12_n273(x) + else + fun_l12_n392(x) + end +end + +def fun_l11_n3(x) + if (x < 1) + fun_l12_n394(x) + else + fun_l12_n989(x) + end +end + +def fun_l11_n4(x) + if (x < 1) + fun_l12_n254(x) + else + fun_l12_n906(x) + end +end + +def fun_l11_n5(x) + if (x < 1) + fun_l12_n229(x) + else + fun_l12_n345(x) + end +end + +def fun_l11_n6(x) + if (x < 1) + fun_l12_n15(x) + else + fun_l12_n893(x) + end +end + +def fun_l11_n7(x) + if (x < 1) + fun_l12_n185(x) + else + fun_l12_n187(x) + end +end + +def fun_l11_n8(x) + if (x < 1) + fun_l12_n761(x) + else + fun_l12_n850(x) + end +end + +def fun_l11_n9(x) + if (x < 1) + fun_l12_n644(x) + else + fun_l12_n274(x) + end +end + +def fun_l11_n10(x) + if (x < 1) + fun_l12_n652(x) + else + fun_l12_n223(x) + end +end + +def fun_l11_n11(x) + if (x < 1) + fun_l12_n905(x) + else + fun_l12_n215(x) + end +end + +def fun_l11_n12(x) + if (x < 1) + fun_l12_n58(x) + else + fun_l12_n495(x) + end +end + +def fun_l11_n13(x) + if (x < 1) + fun_l12_n529(x) + else + fun_l12_n477(x) + end +end + +def fun_l11_n14(x) + if (x < 1) + fun_l12_n743(x) + else + fun_l12_n847(x) + end +end + +def fun_l11_n15(x) + if (x < 1) + fun_l12_n558(x) + else + fun_l12_n252(x) + end +end + +def fun_l11_n16(x) + if (x < 1) + fun_l12_n115(x) + else + fun_l12_n972(x) + end +end + +def fun_l11_n17(x) + if (x < 1) + fun_l12_n374(x) + else + fun_l12_n637(x) + end +end + +def fun_l11_n18(x) + if (x < 1) + fun_l12_n978(x) + else + fun_l12_n570(x) + end +end + +def fun_l11_n19(x) + if (x < 1) + fun_l12_n264(x) + else + fun_l12_n743(x) + end +end + +def fun_l11_n20(x) + if (x < 1) + fun_l12_n936(x) + else + fun_l12_n986(x) + end +end + +def fun_l11_n21(x) + if (x < 1) + fun_l12_n107(x) + else + fun_l12_n167(x) + end +end + +def fun_l11_n22(x) + if (x < 1) + fun_l12_n777(x) + else + fun_l12_n143(x) + end +end + +def fun_l11_n23(x) + if (x < 1) + fun_l12_n510(x) + else + fun_l12_n236(x) + end +end + +def fun_l11_n24(x) + if (x < 1) + fun_l12_n180(x) + else + fun_l12_n309(x) + end +end + +def fun_l11_n25(x) + if (x < 1) + fun_l12_n850(x) + else + fun_l12_n374(x) + end +end + +def fun_l11_n26(x) + if (x < 1) + fun_l12_n573(x) + else + fun_l12_n722(x) + end +end + +def fun_l11_n27(x) + if (x < 1) + fun_l12_n800(x) + else + fun_l12_n981(x) + end +end + +def fun_l11_n28(x) + if (x < 1) + fun_l12_n705(x) + else + fun_l12_n636(x) + end +end + +def fun_l11_n29(x) + if (x < 1) + fun_l12_n618(x) + else + fun_l12_n429(x) + end +end + +def fun_l11_n30(x) + if (x < 1) + fun_l12_n139(x) + else + fun_l12_n95(x) + end +end + +def fun_l11_n31(x) + if (x < 1) + fun_l12_n861(x) + else + fun_l12_n797(x) + end +end + +def fun_l11_n32(x) + if (x < 1) + fun_l12_n576(x) + else + fun_l12_n719(x) + end +end + +def fun_l11_n33(x) + if (x < 1) + fun_l12_n236(x) + else + fun_l12_n429(x) + end +end + +def fun_l11_n34(x) + if (x < 1) + fun_l12_n375(x) + else + fun_l12_n696(x) + end +end + +def fun_l11_n35(x) + if (x < 1) + fun_l12_n291(x) + else + fun_l12_n799(x) + end +end + +def fun_l11_n36(x) + if (x < 1) + fun_l12_n180(x) + else + fun_l12_n228(x) + end +end + +def fun_l11_n37(x) + if (x < 1) + fun_l12_n455(x) + else + fun_l12_n983(x) + end +end + +def fun_l11_n38(x) + if (x < 1) + fun_l12_n486(x) + else + fun_l12_n871(x) + end +end + +def fun_l11_n39(x) + if (x < 1) + fun_l12_n945(x) + else + fun_l12_n47(x) + end +end + +def fun_l11_n40(x) + if (x < 1) + fun_l12_n531(x) + else + fun_l12_n506(x) + end +end + +def fun_l11_n41(x) + if (x < 1) + fun_l12_n248(x) + else + fun_l12_n142(x) + end +end + +def fun_l11_n42(x) + if (x < 1) + fun_l12_n415(x) + else + fun_l12_n177(x) + end +end + +def fun_l11_n43(x) + if (x < 1) + fun_l12_n560(x) + else + fun_l12_n63(x) + end +end + +def fun_l11_n44(x) + if (x < 1) + fun_l12_n180(x) + else + fun_l12_n268(x) + end +end + +def fun_l11_n45(x) + if (x < 1) + fun_l12_n814(x) + else + fun_l12_n967(x) + end +end + +def fun_l11_n46(x) + if (x < 1) + fun_l12_n273(x) + else + fun_l12_n702(x) + end +end + +def fun_l11_n47(x) + if (x < 1) + fun_l12_n626(x) + else + fun_l12_n615(x) + end +end + +def fun_l11_n48(x) + if (x < 1) + fun_l12_n374(x) + else + fun_l12_n669(x) + end +end + +def fun_l11_n49(x) + if (x < 1) + fun_l12_n681(x) + else + fun_l12_n48(x) + end +end + +def fun_l11_n50(x) + if (x < 1) + fun_l12_n3(x) + else + fun_l12_n455(x) + end +end + +def fun_l11_n51(x) + if (x < 1) + fun_l12_n461(x) + else + fun_l12_n350(x) + end +end + +def fun_l11_n52(x) + if (x < 1) + fun_l12_n129(x) + else + fun_l12_n266(x) + end +end + +def fun_l11_n53(x) + if (x < 1) + fun_l12_n802(x) + else + fun_l12_n863(x) + end +end + +def fun_l11_n54(x) + if (x < 1) + fun_l12_n216(x) + else + fun_l12_n820(x) + end +end + +def fun_l11_n55(x) + if (x < 1) + fun_l12_n626(x) + else + fun_l12_n476(x) + end +end + +def fun_l11_n56(x) + if (x < 1) + fun_l12_n162(x) + else + fun_l12_n796(x) + end +end + +def fun_l11_n57(x) + if (x < 1) + fun_l12_n45(x) + else + fun_l12_n893(x) + end +end + +def fun_l11_n58(x) + if (x < 1) + fun_l12_n227(x) + else + fun_l12_n919(x) + end +end + +def fun_l11_n59(x) + if (x < 1) + fun_l12_n300(x) + else + fun_l12_n360(x) + end +end + +def fun_l11_n60(x) + if (x < 1) + fun_l12_n265(x) + else + fun_l12_n552(x) + end +end + +def fun_l11_n61(x) + if (x < 1) + fun_l12_n927(x) + else + fun_l12_n486(x) + end +end + +def fun_l11_n62(x) + if (x < 1) + fun_l12_n94(x) + else + fun_l12_n28(x) + end +end + +def fun_l11_n63(x) + if (x < 1) + fun_l12_n295(x) + else + fun_l12_n967(x) + end +end + +def fun_l11_n64(x) + if (x < 1) + fun_l12_n713(x) + else + fun_l12_n463(x) + end +end + +def fun_l11_n65(x) + if (x < 1) + fun_l12_n454(x) + else + fun_l12_n616(x) + end +end + +def fun_l11_n66(x) + if (x < 1) + fun_l12_n121(x) + else + fun_l12_n277(x) + end +end + +def fun_l11_n67(x) + if (x < 1) + fun_l12_n524(x) + else + fun_l12_n242(x) + end +end + +def fun_l11_n68(x) + if (x < 1) + fun_l12_n570(x) + else + fun_l12_n658(x) + end +end + +def fun_l11_n69(x) + if (x < 1) + fun_l12_n343(x) + else + fun_l12_n826(x) + end +end + +def fun_l11_n70(x) + if (x < 1) + fun_l12_n732(x) + else + fun_l12_n993(x) + end +end + +def fun_l11_n71(x) + if (x < 1) + fun_l12_n380(x) + else + fun_l12_n486(x) + end +end + +def fun_l11_n72(x) + if (x < 1) + fun_l12_n55(x) + else + fun_l12_n342(x) + end +end + +def fun_l11_n73(x) + if (x < 1) + fun_l12_n789(x) + else + fun_l12_n646(x) + end +end + +def fun_l11_n74(x) + if (x < 1) + fun_l12_n106(x) + else + fun_l12_n557(x) + end +end + +def fun_l11_n75(x) + if (x < 1) + fun_l12_n368(x) + else + fun_l12_n5(x) + end +end + +def fun_l11_n76(x) + if (x < 1) + fun_l12_n992(x) + else + fun_l12_n521(x) + end +end + +def fun_l11_n77(x) + if (x < 1) + fun_l12_n754(x) + else + fun_l12_n259(x) + end +end + +def fun_l11_n78(x) + if (x < 1) + fun_l12_n855(x) + else + fun_l12_n946(x) + end +end + +def fun_l11_n79(x) + if (x < 1) + fun_l12_n727(x) + else + fun_l12_n422(x) + end +end + +def fun_l11_n80(x) + if (x < 1) + fun_l12_n649(x) + else + fun_l12_n593(x) + end +end + +def fun_l11_n81(x) + if (x < 1) + fun_l12_n206(x) + else + fun_l12_n222(x) + end +end + +def fun_l11_n82(x) + if (x < 1) + fun_l12_n995(x) + else + fun_l12_n471(x) + end +end + +def fun_l11_n83(x) + if (x < 1) + fun_l12_n926(x) + else + fun_l12_n165(x) + end +end + +def fun_l11_n84(x) + if (x < 1) + fun_l12_n988(x) + else + fun_l12_n495(x) + end +end + +def fun_l11_n85(x) + if (x < 1) + fun_l12_n839(x) + else + fun_l12_n565(x) + end +end + +def fun_l11_n86(x) + if (x < 1) + fun_l12_n381(x) + else + fun_l12_n981(x) + end +end + +def fun_l11_n87(x) + if (x < 1) + fun_l12_n64(x) + else + fun_l12_n616(x) + end +end + +def fun_l11_n88(x) + if (x < 1) + fun_l12_n714(x) + else + fun_l12_n995(x) + end +end + +def fun_l11_n89(x) + if (x < 1) + fun_l12_n796(x) + else + fun_l12_n534(x) + end +end + +def fun_l11_n90(x) + if (x < 1) + fun_l12_n31(x) + else + fun_l12_n584(x) + end +end + +def fun_l11_n91(x) + if (x < 1) + fun_l12_n741(x) + else + fun_l12_n356(x) + end +end + +def fun_l11_n92(x) + if (x < 1) + fun_l12_n418(x) + else + fun_l12_n184(x) + end +end + +def fun_l11_n93(x) + if (x < 1) + fun_l12_n427(x) + else + fun_l12_n136(x) + end +end + +def fun_l11_n94(x) + if (x < 1) + fun_l12_n968(x) + else + fun_l12_n647(x) + end +end + +def fun_l11_n95(x) + if (x < 1) + fun_l12_n641(x) + else + fun_l12_n675(x) + end +end + +def fun_l11_n96(x) + if (x < 1) + fun_l12_n465(x) + else + fun_l12_n507(x) + end +end + +def fun_l11_n97(x) + if (x < 1) + fun_l12_n910(x) + else + fun_l12_n718(x) + end +end + +def fun_l11_n98(x) + if (x < 1) + fun_l12_n686(x) + else + fun_l12_n94(x) + end +end + +def fun_l11_n99(x) + if (x < 1) + fun_l12_n94(x) + else + fun_l12_n632(x) + end +end + +def fun_l11_n100(x) + if (x < 1) + fun_l12_n270(x) + else + fun_l12_n228(x) + end +end + +def fun_l11_n101(x) + if (x < 1) + fun_l12_n569(x) + else + fun_l12_n492(x) + end +end + +def fun_l11_n102(x) + if (x < 1) + fun_l12_n187(x) + else + fun_l12_n183(x) + end +end + +def fun_l11_n103(x) + if (x < 1) + fun_l12_n894(x) + else + fun_l12_n655(x) + end +end + +def fun_l11_n104(x) + if (x < 1) + fun_l12_n347(x) + else + fun_l12_n467(x) + end +end + +def fun_l11_n105(x) + if (x < 1) + fun_l12_n198(x) + else + fun_l12_n838(x) + end +end + +def fun_l11_n106(x) + if (x < 1) + fun_l12_n941(x) + else + fun_l12_n98(x) + end +end + +def fun_l11_n107(x) + if (x < 1) + fun_l12_n406(x) + else + fun_l12_n773(x) + end +end + +def fun_l11_n108(x) + if (x < 1) + fun_l12_n980(x) + else + fun_l12_n508(x) + end +end + +def fun_l11_n109(x) + if (x < 1) + fun_l12_n286(x) + else + fun_l12_n928(x) + end +end + +def fun_l11_n110(x) + if (x < 1) + fun_l12_n710(x) + else + fun_l12_n20(x) + end +end + +def fun_l11_n111(x) + if (x < 1) + fun_l12_n358(x) + else + fun_l12_n549(x) + end +end + +def fun_l11_n112(x) + if (x < 1) + fun_l12_n359(x) + else + fun_l12_n548(x) + end +end + +def fun_l11_n113(x) + if (x < 1) + fun_l12_n665(x) + else + fun_l12_n802(x) + end +end + +def fun_l11_n114(x) + if (x < 1) + fun_l12_n199(x) + else + fun_l12_n904(x) + end +end + +def fun_l11_n115(x) + if (x < 1) + fun_l12_n995(x) + else + fun_l12_n319(x) + end +end + +def fun_l11_n116(x) + if (x < 1) + fun_l12_n873(x) + else + fun_l12_n786(x) + end +end + +def fun_l11_n117(x) + if (x < 1) + fun_l12_n147(x) + else + fun_l12_n542(x) + end +end + +def fun_l11_n118(x) + if (x < 1) + fun_l12_n669(x) + else + fun_l12_n871(x) + end +end + +def fun_l11_n119(x) + if (x < 1) + fun_l12_n552(x) + else + fun_l12_n998(x) + end +end + +def fun_l11_n120(x) + if (x < 1) + fun_l12_n300(x) + else + fun_l12_n333(x) + end +end + +def fun_l11_n121(x) + if (x < 1) + fun_l12_n846(x) + else + fun_l12_n133(x) + end +end + +def fun_l11_n122(x) + if (x < 1) + fun_l12_n946(x) + else + fun_l12_n540(x) + end +end + +def fun_l11_n123(x) + if (x < 1) + fun_l12_n71(x) + else + fun_l12_n264(x) + end +end + +def fun_l11_n124(x) + if (x < 1) + fun_l12_n410(x) + else + fun_l12_n60(x) + end +end + +def fun_l11_n125(x) + if (x < 1) + fun_l12_n62(x) + else + fun_l12_n211(x) + end +end + +def fun_l11_n126(x) + if (x < 1) + fun_l12_n252(x) + else + fun_l12_n635(x) + end +end + +def fun_l11_n127(x) + if (x < 1) + fun_l12_n444(x) + else + fun_l12_n735(x) + end +end + +def fun_l11_n128(x) + if (x < 1) + fun_l12_n3(x) + else + fun_l12_n403(x) + end +end + +def fun_l11_n129(x) + if (x < 1) + fun_l12_n121(x) + else + fun_l12_n882(x) + end +end + +def fun_l11_n130(x) + if (x < 1) + fun_l12_n985(x) + else + fun_l12_n983(x) + end +end + +def fun_l11_n131(x) + if (x < 1) + fun_l12_n413(x) + else + fun_l12_n117(x) + end +end + +def fun_l11_n132(x) + if (x < 1) + fun_l12_n856(x) + else + fun_l12_n312(x) + end +end + +def fun_l11_n133(x) + if (x < 1) + fun_l12_n249(x) + else + fun_l12_n870(x) + end +end + +def fun_l11_n134(x) + if (x < 1) + fun_l12_n367(x) + else + fun_l12_n748(x) + end +end + +def fun_l11_n135(x) + if (x < 1) + fun_l12_n670(x) + else + fun_l12_n464(x) + end +end + +def fun_l11_n136(x) + if (x < 1) + fun_l12_n698(x) + else + fun_l12_n238(x) + end +end + +def fun_l11_n137(x) + if (x < 1) + fun_l12_n856(x) + else + fun_l12_n660(x) + end +end + +def fun_l11_n138(x) + if (x < 1) + fun_l12_n693(x) + else + fun_l12_n793(x) + end +end + +def fun_l11_n139(x) + if (x < 1) + fun_l12_n959(x) + else + fun_l12_n377(x) + end +end + +def fun_l11_n140(x) + if (x < 1) + fun_l12_n24(x) + else + fun_l12_n250(x) + end +end + +def fun_l11_n141(x) + if (x < 1) + fun_l12_n270(x) + else + fun_l12_n720(x) + end +end + +def fun_l11_n142(x) + if (x < 1) + fun_l12_n775(x) + else + fun_l12_n781(x) + end +end + +def fun_l11_n143(x) + if (x < 1) + fun_l12_n266(x) + else + fun_l12_n608(x) + end +end + +def fun_l11_n144(x) + if (x < 1) + fun_l12_n196(x) + else + fun_l12_n70(x) + end +end + +def fun_l11_n145(x) + if (x < 1) + fun_l12_n100(x) + else + fun_l12_n846(x) + end +end + +def fun_l11_n146(x) + if (x < 1) + fun_l12_n406(x) + else + fun_l12_n966(x) + end +end + +def fun_l11_n147(x) + if (x < 1) + fun_l12_n816(x) + else + fun_l12_n54(x) + end +end + +def fun_l11_n148(x) + if (x < 1) + fun_l12_n856(x) + else + fun_l12_n710(x) + end +end + +def fun_l11_n149(x) + if (x < 1) + fun_l12_n597(x) + else + fun_l12_n596(x) + end +end + +def fun_l11_n150(x) + if (x < 1) + fun_l12_n938(x) + else + fun_l12_n349(x) + end +end + +def fun_l11_n151(x) + if (x < 1) + fun_l12_n987(x) + else + fun_l12_n231(x) + end +end + +def fun_l11_n152(x) + if (x < 1) + fun_l12_n67(x) + else + fun_l12_n685(x) + end +end + +def fun_l11_n153(x) + if (x < 1) + fun_l12_n786(x) + else + fun_l12_n71(x) + end +end + +def fun_l11_n154(x) + if (x < 1) + fun_l12_n245(x) + else + fun_l12_n109(x) + end +end + +def fun_l11_n155(x) + if (x < 1) + fun_l12_n665(x) + else + fun_l12_n565(x) + end +end + +def fun_l11_n156(x) + if (x < 1) + fun_l12_n885(x) + else + fun_l12_n27(x) + end +end + +def fun_l11_n157(x) + if (x < 1) + fun_l12_n704(x) + else + fun_l12_n140(x) + end +end + +def fun_l11_n158(x) + if (x < 1) + fun_l12_n505(x) + else + fun_l12_n428(x) + end +end + +def fun_l11_n159(x) + if (x < 1) + fun_l12_n646(x) + else + fun_l12_n250(x) + end +end + +def fun_l11_n160(x) + if (x < 1) + fun_l12_n125(x) + else + fun_l12_n22(x) + end +end + +def fun_l11_n161(x) + if (x < 1) + fun_l12_n49(x) + else + fun_l12_n852(x) + end +end + +def fun_l11_n162(x) + if (x < 1) + fun_l12_n992(x) + else + fun_l12_n321(x) + end +end + +def fun_l11_n163(x) + if (x < 1) + fun_l12_n457(x) + else + fun_l12_n162(x) + end +end + +def fun_l11_n164(x) + if (x < 1) + fun_l12_n612(x) + else + fun_l12_n107(x) + end +end + +def fun_l11_n165(x) + if (x < 1) + fun_l12_n786(x) + else + fun_l12_n338(x) + end +end + +def fun_l11_n166(x) + if (x < 1) + fun_l12_n623(x) + else + fun_l12_n18(x) + end +end + +def fun_l11_n167(x) + if (x < 1) + fun_l12_n605(x) + else + fun_l12_n963(x) + end +end + +def fun_l11_n168(x) + if (x < 1) + fun_l12_n111(x) + else + fun_l12_n822(x) + end +end + +def fun_l11_n169(x) + if (x < 1) + fun_l12_n502(x) + else + fun_l12_n291(x) + end +end + +def fun_l11_n170(x) + if (x < 1) + fun_l12_n984(x) + else + fun_l12_n950(x) + end +end + +def fun_l11_n171(x) + if (x < 1) + fun_l12_n915(x) + else + fun_l12_n81(x) + end +end + +def fun_l11_n172(x) + if (x < 1) + fun_l12_n839(x) + else + fun_l12_n405(x) + end +end + +def fun_l11_n173(x) + if (x < 1) + fun_l12_n331(x) + else + fun_l12_n906(x) + end +end + +def fun_l11_n174(x) + if (x < 1) + fun_l12_n698(x) + else + fun_l12_n378(x) + end +end + +def fun_l11_n175(x) + if (x < 1) + fun_l12_n648(x) + else + fun_l12_n824(x) + end +end + +def fun_l11_n176(x) + if (x < 1) + fun_l12_n876(x) + else + fun_l12_n873(x) + end +end + +def fun_l11_n177(x) + if (x < 1) + fun_l12_n932(x) + else + fun_l12_n797(x) + end +end + +def fun_l11_n178(x) + if (x < 1) + fun_l12_n975(x) + else + fun_l12_n166(x) + end +end + +def fun_l11_n179(x) + if (x < 1) + fun_l12_n66(x) + else + fun_l12_n624(x) + end +end + +def fun_l11_n180(x) + if (x < 1) + fun_l12_n676(x) + else + fun_l12_n603(x) + end +end + +def fun_l11_n181(x) + if (x < 1) + fun_l12_n80(x) + else + fun_l12_n504(x) + end +end + +def fun_l11_n182(x) + if (x < 1) + fun_l12_n465(x) + else + fun_l12_n319(x) + end +end + +def fun_l11_n183(x) + if (x < 1) + fun_l12_n493(x) + else + fun_l12_n412(x) + end +end + +def fun_l11_n184(x) + if (x < 1) + fun_l12_n278(x) + else + fun_l12_n145(x) + end +end + +def fun_l11_n185(x) + if (x < 1) + fun_l12_n328(x) + else + fun_l12_n777(x) + end +end + +def fun_l11_n186(x) + if (x < 1) + fun_l12_n120(x) + else + fun_l12_n462(x) + end +end + +def fun_l11_n187(x) + if (x < 1) + fun_l12_n755(x) + else + fun_l12_n260(x) + end +end + +def fun_l11_n188(x) + if (x < 1) + fun_l12_n378(x) + else + fun_l12_n174(x) + end +end + +def fun_l11_n189(x) + if (x < 1) + fun_l12_n100(x) + else + fun_l12_n234(x) + end +end + +def fun_l11_n190(x) + if (x < 1) + fun_l12_n132(x) + else + fun_l12_n437(x) + end +end + +def fun_l11_n191(x) + if (x < 1) + fun_l12_n399(x) + else + fun_l12_n989(x) + end +end + +def fun_l11_n192(x) + if (x < 1) + fun_l12_n355(x) + else + fun_l12_n953(x) + end +end + +def fun_l11_n193(x) + if (x < 1) + fun_l12_n139(x) + else + fun_l12_n138(x) + end +end + +def fun_l11_n194(x) + if (x < 1) + fun_l12_n294(x) + else + fun_l12_n676(x) + end +end + +def fun_l11_n195(x) + if (x < 1) + fun_l12_n581(x) + else + fun_l12_n549(x) + end +end + +def fun_l11_n196(x) + if (x < 1) + fun_l12_n555(x) + else + fun_l12_n738(x) + end +end + +def fun_l11_n197(x) + if (x < 1) + fun_l12_n170(x) + else + fun_l12_n476(x) + end +end + +def fun_l11_n198(x) + if (x < 1) + fun_l12_n350(x) + else + fun_l12_n576(x) + end +end + +def fun_l11_n199(x) + if (x < 1) + fun_l12_n647(x) + else + fun_l12_n94(x) + end +end + +def fun_l11_n200(x) + if (x < 1) + fun_l12_n28(x) + else + fun_l12_n706(x) + end +end + +def fun_l11_n201(x) + if (x < 1) + fun_l12_n189(x) + else + fun_l12_n366(x) + end +end + +def fun_l11_n202(x) + if (x < 1) + fun_l12_n690(x) + else + fun_l12_n807(x) + end +end + +def fun_l11_n203(x) + if (x < 1) + fun_l12_n402(x) + else + fun_l12_n685(x) + end +end + +def fun_l11_n204(x) + if (x < 1) + fun_l12_n232(x) + else + fun_l12_n257(x) + end +end + +def fun_l11_n205(x) + if (x < 1) + fun_l12_n108(x) + else + fun_l12_n888(x) + end +end + +def fun_l11_n206(x) + if (x < 1) + fun_l12_n494(x) + else + fun_l12_n372(x) + end +end + +def fun_l11_n207(x) + if (x < 1) + fun_l12_n607(x) + else + fun_l12_n336(x) + end +end + +def fun_l11_n208(x) + if (x < 1) + fun_l12_n913(x) + else + fun_l12_n134(x) + end +end + +def fun_l11_n209(x) + if (x < 1) + fun_l12_n996(x) + else + fun_l12_n918(x) + end +end + +def fun_l11_n210(x) + if (x < 1) + fun_l12_n674(x) + else + fun_l12_n260(x) + end +end + +def fun_l11_n211(x) + if (x < 1) + fun_l12_n344(x) + else + fun_l12_n219(x) + end +end + +def fun_l11_n212(x) + if (x < 1) + fun_l12_n161(x) + else + fun_l12_n415(x) + end +end + +def fun_l11_n213(x) + if (x < 1) + fun_l12_n65(x) + else + fun_l12_n777(x) + end +end + +def fun_l11_n214(x) + if (x < 1) + fun_l12_n369(x) + else + fun_l12_n899(x) + end +end + +def fun_l11_n215(x) + if (x < 1) + fun_l12_n310(x) + else + fun_l12_n118(x) + end +end + +def fun_l11_n216(x) + if (x < 1) + fun_l12_n326(x) + else + fun_l12_n823(x) + end +end + +def fun_l11_n217(x) + if (x < 1) + fun_l12_n981(x) + else + fun_l12_n824(x) + end +end + +def fun_l11_n218(x) + if (x < 1) + fun_l12_n425(x) + else + fun_l12_n483(x) + end +end + +def fun_l11_n219(x) + if (x < 1) + fun_l12_n931(x) + else + fun_l12_n366(x) + end +end + +def fun_l11_n220(x) + if (x < 1) + fun_l12_n325(x) + else + fun_l12_n926(x) + end +end + +def fun_l11_n221(x) + if (x < 1) + fun_l12_n924(x) + else + fun_l12_n764(x) + end +end + +def fun_l11_n222(x) + if (x < 1) + fun_l12_n407(x) + else + fun_l12_n137(x) + end +end + +def fun_l11_n223(x) + if (x < 1) + fun_l12_n584(x) + else + fun_l12_n294(x) + end +end + +def fun_l11_n224(x) + if (x < 1) + fun_l12_n39(x) + else + fun_l12_n795(x) + end +end + +def fun_l11_n225(x) + if (x < 1) + fun_l12_n37(x) + else + fun_l12_n738(x) + end +end + +def fun_l11_n226(x) + if (x < 1) + fun_l12_n779(x) + else + fun_l12_n152(x) + end +end + +def fun_l11_n227(x) + if (x < 1) + fun_l12_n116(x) + else + fun_l12_n589(x) + end +end + +def fun_l11_n228(x) + if (x < 1) + fun_l12_n500(x) + else + fun_l12_n916(x) + end +end + +def fun_l11_n229(x) + if (x < 1) + fun_l12_n443(x) + else + fun_l12_n126(x) + end +end + +def fun_l11_n230(x) + if (x < 1) + fun_l12_n311(x) + else + fun_l12_n184(x) + end +end + +def fun_l11_n231(x) + if (x < 1) + fun_l12_n604(x) + else + fun_l12_n171(x) + end +end + +def fun_l11_n232(x) + if (x < 1) + fun_l12_n287(x) + else + fun_l12_n899(x) + end +end + +def fun_l11_n233(x) + if (x < 1) + fun_l12_n834(x) + else + fun_l12_n435(x) + end +end + +def fun_l11_n234(x) + if (x < 1) + fun_l12_n187(x) + else + fun_l12_n584(x) + end +end + +def fun_l11_n235(x) + if (x < 1) + fun_l12_n711(x) + else + fun_l12_n542(x) + end +end + +def fun_l11_n236(x) + if (x < 1) + fun_l12_n797(x) + else + fun_l12_n702(x) + end +end + +def fun_l11_n237(x) + if (x < 1) + fun_l12_n645(x) + else + fun_l12_n691(x) + end +end + +def fun_l11_n238(x) + if (x < 1) + fun_l12_n920(x) + else + fun_l12_n97(x) + end +end + +def fun_l11_n239(x) + if (x < 1) + fun_l12_n491(x) + else + fun_l12_n172(x) + end +end + +def fun_l11_n240(x) + if (x < 1) + fun_l12_n882(x) + else + fun_l12_n596(x) + end +end + +def fun_l11_n241(x) + if (x < 1) + fun_l12_n178(x) + else + fun_l12_n671(x) + end +end + +def fun_l11_n242(x) + if (x < 1) + fun_l12_n483(x) + else + fun_l12_n143(x) + end +end + +def fun_l11_n243(x) + if (x < 1) + fun_l12_n677(x) + else + fun_l12_n542(x) + end +end + +def fun_l11_n244(x) + if (x < 1) + fun_l12_n676(x) + else + fun_l12_n873(x) + end +end + +def fun_l11_n245(x) + if (x < 1) + fun_l12_n393(x) + else + fun_l12_n532(x) + end +end + +def fun_l11_n246(x) + if (x < 1) + fun_l12_n704(x) + else + fun_l12_n885(x) + end +end + +def fun_l11_n247(x) + if (x < 1) + fun_l12_n668(x) + else + fun_l12_n305(x) + end +end + +def fun_l11_n248(x) + if (x < 1) + fun_l12_n925(x) + else + fun_l12_n342(x) + end +end + +def fun_l11_n249(x) + if (x < 1) + fun_l12_n487(x) + else + fun_l12_n517(x) + end +end + +def fun_l11_n250(x) + if (x < 1) + fun_l12_n889(x) + else + fun_l12_n91(x) + end +end + +def fun_l11_n251(x) + if (x < 1) + fun_l12_n908(x) + else + fun_l12_n645(x) + end +end + +def fun_l11_n252(x) + if (x < 1) + fun_l12_n747(x) + else + fun_l12_n736(x) + end +end + +def fun_l11_n253(x) + if (x < 1) + fun_l12_n749(x) + else + fun_l12_n264(x) + end +end + +def fun_l11_n254(x) + if (x < 1) + fun_l12_n353(x) + else + fun_l12_n120(x) + end +end + +def fun_l11_n255(x) + if (x < 1) + fun_l12_n231(x) + else + fun_l12_n211(x) + end +end + +def fun_l11_n256(x) + if (x < 1) + fun_l12_n66(x) + else + fun_l12_n998(x) + end +end + +def fun_l11_n257(x) + if (x < 1) + fun_l12_n818(x) + else + fun_l12_n37(x) + end +end + +def fun_l11_n258(x) + if (x < 1) + fun_l12_n96(x) + else + fun_l12_n489(x) + end +end + +def fun_l11_n259(x) + if (x < 1) + fun_l12_n86(x) + else + fun_l12_n432(x) + end +end + +def fun_l11_n260(x) + if (x < 1) + fun_l12_n774(x) + else + fun_l12_n203(x) + end +end + +def fun_l11_n261(x) + if (x < 1) + fun_l12_n935(x) + else + fun_l12_n29(x) + end +end + +def fun_l11_n262(x) + if (x < 1) + fun_l12_n599(x) + else + fun_l12_n204(x) + end +end + +def fun_l11_n263(x) + if (x < 1) + fun_l12_n63(x) + else + fun_l12_n866(x) + end +end + +def fun_l11_n264(x) + if (x < 1) + fun_l12_n892(x) + else + fun_l12_n847(x) + end +end + +def fun_l11_n265(x) + if (x < 1) + fun_l12_n695(x) + else + fun_l12_n881(x) + end +end + +def fun_l11_n266(x) + if (x < 1) + fun_l12_n176(x) + else + fun_l12_n39(x) + end +end + +def fun_l11_n267(x) + if (x < 1) + fun_l12_n448(x) + else + fun_l12_n744(x) + end +end + +def fun_l11_n268(x) + if (x < 1) + fun_l12_n587(x) + else + fun_l12_n462(x) + end +end + +def fun_l11_n269(x) + if (x < 1) + fun_l12_n670(x) + else + fun_l12_n797(x) + end +end + +def fun_l11_n270(x) + if (x < 1) + fun_l12_n856(x) + else + fun_l12_n903(x) + end +end + +def fun_l11_n271(x) + if (x < 1) + fun_l12_n914(x) + else + fun_l12_n459(x) + end +end + +def fun_l11_n272(x) + if (x < 1) + fun_l12_n932(x) + else + fun_l12_n10(x) + end +end + +def fun_l11_n273(x) + if (x < 1) + fun_l12_n554(x) + else + fun_l12_n528(x) + end +end + +def fun_l11_n274(x) + if (x < 1) + fun_l12_n698(x) + else + fun_l12_n899(x) + end +end + +def fun_l11_n275(x) + if (x < 1) + fun_l12_n907(x) + else + fun_l12_n945(x) + end +end + +def fun_l11_n276(x) + if (x < 1) + fun_l12_n421(x) + else + fun_l12_n575(x) + end +end + +def fun_l11_n277(x) + if (x < 1) + fun_l12_n757(x) + else + fun_l12_n808(x) + end +end + +def fun_l11_n278(x) + if (x < 1) + fun_l12_n527(x) + else + fun_l12_n438(x) + end +end + +def fun_l11_n279(x) + if (x < 1) + fun_l12_n263(x) + else + fun_l12_n842(x) + end +end + +def fun_l11_n280(x) + if (x < 1) + fun_l12_n603(x) + else + fun_l12_n899(x) + end +end + +def fun_l11_n281(x) + if (x < 1) + fun_l12_n486(x) + else + fun_l12_n380(x) + end +end + +def fun_l11_n282(x) + if (x < 1) + fun_l12_n699(x) + else + fun_l12_n199(x) + end +end + +def fun_l11_n283(x) + if (x < 1) + fun_l12_n422(x) + else + fun_l12_n258(x) + end +end + +def fun_l11_n284(x) + if (x < 1) + fun_l12_n255(x) + else + fun_l12_n752(x) + end +end + +def fun_l11_n285(x) + if (x < 1) + fun_l12_n506(x) + else + fun_l12_n801(x) + end +end + +def fun_l11_n286(x) + if (x < 1) + fun_l12_n535(x) + else + fun_l12_n892(x) + end +end + +def fun_l11_n287(x) + if (x < 1) + fun_l12_n547(x) + else + fun_l12_n74(x) + end +end + +def fun_l11_n288(x) + if (x < 1) + fun_l12_n923(x) + else + fun_l12_n135(x) + end +end + +def fun_l11_n289(x) + if (x < 1) + fun_l12_n78(x) + else + fun_l12_n704(x) + end +end + +def fun_l11_n290(x) + if (x < 1) + fun_l12_n771(x) + else + fun_l12_n915(x) + end +end + +def fun_l11_n291(x) + if (x < 1) + fun_l12_n184(x) + else + fun_l12_n188(x) + end +end + +def fun_l11_n292(x) + if (x < 1) + fun_l12_n736(x) + else + fun_l12_n190(x) + end +end + +def fun_l11_n293(x) + if (x < 1) + fun_l12_n301(x) + else + fun_l12_n745(x) + end +end + +def fun_l11_n294(x) + if (x < 1) + fun_l12_n525(x) + else + fun_l12_n603(x) + end +end + +def fun_l11_n295(x) + if (x < 1) + fun_l12_n339(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n296(x) + if (x < 1) + fun_l12_n491(x) + else + fun_l12_n601(x) + end +end + +def fun_l11_n297(x) + if (x < 1) + fun_l12_n449(x) + else + fun_l12_n361(x) + end +end + +def fun_l11_n298(x) + if (x < 1) + fun_l12_n617(x) + else + fun_l12_n346(x) + end +end + +def fun_l11_n299(x) + if (x < 1) + fun_l12_n578(x) + else + fun_l12_n147(x) + end +end + +def fun_l11_n300(x) + if (x < 1) + fun_l12_n73(x) + else + fun_l12_n360(x) + end +end + +def fun_l11_n301(x) + if (x < 1) + fun_l12_n398(x) + else + fun_l12_n749(x) + end +end + +def fun_l11_n302(x) + if (x < 1) + fun_l12_n871(x) + else + fun_l12_n745(x) + end +end + +def fun_l11_n303(x) + if (x < 1) + fun_l12_n669(x) + else + fun_l12_n196(x) + end +end + +def fun_l11_n304(x) + if (x < 1) + fun_l12_n202(x) + else + fun_l12_n173(x) + end +end + +def fun_l11_n305(x) + if (x < 1) + fun_l12_n975(x) + else + fun_l12_n859(x) + end +end + +def fun_l11_n306(x) + if (x < 1) + fun_l12_n776(x) + else + fun_l12_n433(x) + end +end + +def fun_l11_n307(x) + if (x < 1) + fun_l12_n760(x) + else + fun_l12_n4(x) + end +end + +def fun_l11_n308(x) + if (x < 1) + fun_l12_n834(x) + else + fun_l12_n276(x) + end +end + +def fun_l11_n309(x) + if (x < 1) + fun_l12_n162(x) + else + fun_l12_n741(x) + end +end + +def fun_l11_n310(x) + if (x < 1) + fun_l12_n231(x) + else + fun_l12_n646(x) + end +end + +def fun_l11_n311(x) + if (x < 1) + fun_l12_n90(x) + else + fun_l12_n46(x) + end +end + +def fun_l11_n312(x) + if (x < 1) + fun_l12_n101(x) + else + fun_l12_n75(x) + end +end + +def fun_l11_n313(x) + if (x < 1) + fun_l12_n415(x) + else + fun_l12_n535(x) + end +end + +def fun_l11_n314(x) + if (x < 1) + fun_l12_n550(x) + else + fun_l12_n305(x) + end +end + +def fun_l11_n315(x) + if (x < 1) + fun_l12_n971(x) + else + fun_l12_n700(x) + end +end + +def fun_l11_n316(x) + if (x < 1) + fun_l12_n942(x) + else + fun_l12_n793(x) + end +end + +def fun_l11_n317(x) + if (x < 1) + fun_l12_n771(x) + else + fun_l12_n383(x) + end +end + +def fun_l11_n318(x) + if (x < 1) + fun_l12_n846(x) + else + fun_l12_n504(x) + end +end + +def fun_l11_n319(x) + if (x < 1) + fun_l12_n28(x) + else + fun_l12_n174(x) + end +end + +def fun_l11_n320(x) + if (x < 1) + fun_l12_n437(x) + else + fun_l12_n355(x) + end +end + +def fun_l11_n321(x) + if (x < 1) + fun_l12_n954(x) + else + fun_l12_n78(x) + end +end + +def fun_l11_n322(x) + if (x < 1) + fun_l12_n256(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n323(x) + if (x < 1) + fun_l12_n41(x) + else + fun_l12_n88(x) + end +end + +def fun_l11_n324(x) + if (x < 1) + fun_l12_n256(x) + else + fun_l12_n162(x) + end +end + +def fun_l11_n325(x) + if (x < 1) + fun_l12_n143(x) + else + fun_l12_n506(x) + end +end + +def fun_l11_n326(x) + if (x < 1) + fun_l12_n686(x) + else + fun_l12_n968(x) + end +end + +def fun_l11_n327(x) + if (x < 1) + fun_l12_n235(x) + else + fun_l12_n246(x) + end +end + +def fun_l11_n328(x) + if (x < 1) + fun_l12_n85(x) + else + fun_l12_n125(x) + end +end + +def fun_l11_n329(x) + if (x < 1) + fun_l12_n877(x) + else + fun_l12_n193(x) + end +end + +def fun_l11_n330(x) + if (x < 1) + fun_l12_n678(x) + else + fun_l12_n147(x) + end +end + +def fun_l11_n331(x) + if (x < 1) + fun_l12_n402(x) + else + fun_l12_n747(x) + end +end + +def fun_l11_n332(x) + if (x < 1) + fun_l12_n390(x) + else + fun_l12_n852(x) + end +end + +def fun_l11_n333(x) + if (x < 1) + fun_l12_n299(x) + else + fun_l12_n122(x) + end +end + +def fun_l11_n334(x) + if (x < 1) + fun_l12_n398(x) + else + fun_l12_n886(x) + end +end + +def fun_l11_n335(x) + if (x < 1) + fun_l12_n128(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n336(x) + if (x < 1) + fun_l12_n611(x) + else + fun_l12_n75(x) + end +end + +def fun_l11_n337(x) + if (x < 1) + fun_l12_n327(x) + else + fun_l12_n442(x) + end +end + +def fun_l11_n338(x) + if (x < 1) + fun_l12_n353(x) + else + fun_l12_n259(x) + end +end + +def fun_l11_n339(x) + if (x < 1) + fun_l12_n173(x) + else + fun_l12_n846(x) + end +end + +def fun_l11_n340(x) + if (x < 1) + fun_l12_n579(x) + else + fun_l12_n869(x) + end +end + +def fun_l11_n341(x) + if (x < 1) + fun_l12_n336(x) + else + fun_l12_n364(x) + end +end + +def fun_l11_n342(x) + if (x < 1) + fun_l12_n355(x) + else + fun_l12_n317(x) + end +end + +def fun_l11_n343(x) + if (x < 1) + fun_l12_n560(x) + else + fun_l12_n202(x) + end +end + +def fun_l11_n344(x) + if (x < 1) + fun_l12_n232(x) + else + fun_l12_n447(x) + end +end + +def fun_l11_n345(x) + if (x < 1) + fun_l12_n712(x) + else + fun_l12_n205(x) + end +end + +def fun_l11_n346(x) + if (x < 1) + fun_l12_n102(x) + else + fun_l12_n785(x) + end +end + +def fun_l11_n347(x) + if (x < 1) + fun_l12_n545(x) + else + fun_l12_n186(x) + end +end + +def fun_l11_n348(x) + if (x < 1) + fun_l12_n530(x) + else + fun_l12_n705(x) + end +end + +def fun_l11_n349(x) + if (x < 1) + fun_l12_n428(x) + else + fun_l12_n295(x) + end +end + +def fun_l11_n350(x) + if (x < 1) + fun_l12_n855(x) + else + fun_l12_n232(x) + end +end + +def fun_l11_n351(x) + if (x < 1) + fun_l12_n759(x) + else + fun_l12_n13(x) + end +end + +def fun_l11_n352(x) + if (x < 1) + fun_l12_n366(x) + else + fun_l12_n700(x) + end +end + +def fun_l11_n353(x) + if (x < 1) + fun_l12_n814(x) + else + fun_l12_n101(x) + end +end + +def fun_l11_n354(x) + if (x < 1) + fun_l12_n788(x) + else + fun_l12_n509(x) + end +end + +def fun_l11_n355(x) + if (x < 1) + fun_l12_n619(x) + else + fun_l12_n531(x) + end +end + +def fun_l11_n356(x) + if (x < 1) + fun_l12_n142(x) + else + fun_l12_n586(x) + end +end + +def fun_l11_n357(x) + if (x < 1) + fun_l12_n772(x) + else + fun_l12_n714(x) + end +end + +def fun_l11_n358(x) + if (x < 1) + fun_l12_n506(x) + else + fun_l12_n405(x) + end +end + +def fun_l11_n359(x) + if (x < 1) + fun_l12_n991(x) + else + fun_l12_n141(x) + end +end + +def fun_l11_n360(x) + if (x < 1) + fun_l12_n156(x) + else + fun_l12_n67(x) + end +end + +def fun_l11_n361(x) + if (x < 1) + fun_l12_n525(x) + else + fun_l12_n293(x) + end +end + +def fun_l11_n362(x) + if (x < 1) + fun_l12_n396(x) + else + fun_l12_n931(x) + end +end + +def fun_l11_n363(x) + if (x < 1) + fun_l12_n153(x) + else + fun_l12_n831(x) + end +end + +def fun_l11_n364(x) + if (x < 1) + fun_l12_n240(x) + else + fun_l12_n450(x) + end +end + +def fun_l11_n365(x) + if (x < 1) + fun_l12_n514(x) + else + fun_l12_n312(x) + end +end + +def fun_l11_n366(x) + if (x < 1) + fun_l12_n456(x) + else + fun_l12_n221(x) + end +end + +def fun_l11_n367(x) + if (x < 1) + fun_l12_n920(x) + else + fun_l12_n699(x) + end +end + +def fun_l11_n368(x) + if (x < 1) + fun_l12_n738(x) + else + fun_l12_n793(x) + end +end + +def fun_l11_n369(x) + if (x < 1) + fun_l12_n13(x) + else + fun_l12_n812(x) + end +end + +def fun_l11_n370(x) + if (x < 1) + fun_l12_n392(x) + else + fun_l12_n342(x) + end +end + +def fun_l11_n371(x) + if (x < 1) + fun_l12_n470(x) + else + fun_l12_n623(x) + end +end + +def fun_l11_n372(x) + if (x < 1) + fun_l12_n26(x) + else + fun_l12_n138(x) + end +end + +def fun_l11_n373(x) + if (x < 1) + fun_l12_n70(x) + else + fun_l12_n682(x) + end +end + +def fun_l11_n374(x) + if (x < 1) + fun_l12_n413(x) + else + fun_l12_n900(x) + end +end + +def fun_l11_n375(x) + if (x < 1) + fun_l12_n328(x) + else + fun_l12_n848(x) + end +end + +def fun_l11_n376(x) + if (x < 1) + fun_l12_n604(x) + else + fun_l12_n823(x) + end +end + +def fun_l11_n377(x) + if (x < 1) + fun_l12_n469(x) + else + fun_l12_n868(x) + end +end + +def fun_l11_n378(x) + if (x < 1) + fun_l12_n241(x) + else + fun_l12_n571(x) + end +end + +def fun_l11_n379(x) + if (x < 1) + fun_l12_n669(x) + else + fun_l12_n75(x) + end +end + +def fun_l11_n380(x) + if (x < 1) + fun_l12_n587(x) + else + fun_l12_n454(x) + end +end + +def fun_l11_n381(x) + if (x < 1) + fun_l12_n210(x) + else + fun_l12_n512(x) + end +end + +def fun_l11_n382(x) + if (x < 1) + fun_l12_n73(x) + else + fun_l12_n981(x) + end +end + +def fun_l11_n383(x) + if (x < 1) + fun_l12_n59(x) + else + fun_l12_n274(x) + end +end + +def fun_l11_n384(x) + if (x < 1) + fun_l12_n242(x) + else + fun_l12_n631(x) + end +end + +def fun_l11_n385(x) + if (x < 1) + fun_l12_n933(x) + else + fun_l12_n678(x) + end +end + +def fun_l11_n386(x) + if (x < 1) + fun_l12_n695(x) + else + fun_l12_n766(x) + end +end + +def fun_l11_n387(x) + if (x < 1) + fun_l12_n49(x) + else + fun_l12_n459(x) + end +end + +def fun_l11_n388(x) + if (x < 1) + fun_l12_n751(x) + else + fun_l12_n594(x) + end +end + +def fun_l11_n389(x) + if (x < 1) + fun_l12_n149(x) + else + fun_l12_n290(x) + end +end + +def fun_l11_n390(x) + if (x < 1) + fun_l12_n307(x) + else + fun_l12_n723(x) + end +end + +def fun_l11_n391(x) + if (x < 1) + fun_l12_n606(x) + else + fun_l12_n97(x) + end +end + +def fun_l11_n392(x) + if (x < 1) + fun_l12_n31(x) + else + fun_l12_n610(x) + end +end + +def fun_l11_n393(x) + if (x < 1) + fun_l12_n798(x) + else + fun_l12_n940(x) + end +end + +def fun_l11_n394(x) + if (x < 1) + fun_l12_n131(x) + else + fun_l12_n79(x) + end +end + +def fun_l11_n395(x) + if (x < 1) + fun_l12_n230(x) + else + fun_l12_n72(x) + end +end + +def fun_l11_n396(x) + if (x < 1) + fun_l12_n506(x) + else + fun_l12_n433(x) + end +end + +def fun_l11_n397(x) + if (x < 1) + fun_l12_n410(x) + else + fun_l12_n648(x) + end +end + +def fun_l11_n398(x) + if (x < 1) + fun_l12_n946(x) + else + fun_l12_n630(x) + end +end + +def fun_l11_n399(x) + if (x < 1) + fun_l12_n394(x) + else + fun_l12_n220(x) + end +end + +def fun_l11_n400(x) + if (x < 1) + fun_l12_n761(x) + else + fun_l12_n407(x) + end +end + +def fun_l11_n401(x) + if (x < 1) + fun_l12_n386(x) + else + fun_l12_n411(x) + end +end + +def fun_l11_n402(x) + if (x < 1) + fun_l12_n290(x) + else + fun_l12_n334(x) + end +end + +def fun_l11_n403(x) + if (x < 1) + fun_l12_n600(x) + else + fun_l12_n282(x) + end +end + +def fun_l11_n404(x) + if (x < 1) + fun_l12_n334(x) + else + fun_l12_n214(x) + end +end + +def fun_l11_n405(x) + if (x < 1) + fun_l12_n103(x) + else + fun_l12_n188(x) + end +end + +def fun_l11_n406(x) + if (x < 1) + fun_l12_n755(x) + else + fun_l12_n773(x) + end +end + +def fun_l11_n407(x) + if (x < 1) + fun_l12_n269(x) + else + fun_l12_n579(x) + end +end + +def fun_l11_n408(x) + if (x < 1) + fun_l12_n54(x) + else + fun_l12_n961(x) + end +end + +def fun_l11_n409(x) + if (x < 1) + fun_l12_n699(x) + else + fun_l12_n117(x) + end +end + +def fun_l11_n410(x) + if (x < 1) + fun_l12_n802(x) + else + fun_l12_n65(x) + end +end + +def fun_l11_n411(x) + if (x < 1) + fun_l12_n776(x) + else + fun_l12_n676(x) + end +end + +def fun_l11_n412(x) + if (x < 1) + fun_l12_n520(x) + else + fun_l12_n447(x) + end +end + +def fun_l11_n413(x) + if (x < 1) + fun_l12_n856(x) + else + fun_l12_n285(x) + end +end + +def fun_l11_n414(x) + if (x < 1) + fun_l12_n797(x) + else + fun_l12_n590(x) + end +end + +def fun_l11_n415(x) + if (x < 1) + fun_l12_n128(x) + else + fun_l12_n677(x) + end +end + +def fun_l11_n416(x) + if (x < 1) + fun_l12_n422(x) + else + fun_l12_n632(x) + end +end + +def fun_l11_n417(x) + if (x < 1) + fun_l12_n159(x) + else + fun_l12_n722(x) + end +end + +def fun_l11_n418(x) + if (x < 1) + fun_l12_n989(x) + else + fun_l12_n670(x) + end +end + +def fun_l11_n419(x) + if (x < 1) + fun_l12_n952(x) + else + fun_l12_n65(x) + end +end + +def fun_l11_n420(x) + if (x < 1) + fun_l12_n796(x) + else + fun_l12_n493(x) + end +end + +def fun_l11_n421(x) + if (x < 1) + fun_l12_n897(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n422(x) + if (x < 1) + fun_l12_n557(x) + else + fun_l12_n545(x) + end +end + +def fun_l11_n423(x) + if (x < 1) + fun_l12_n716(x) + else + fun_l12_n746(x) + end +end + +def fun_l11_n424(x) + if (x < 1) + fun_l12_n335(x) + else + fun_l12_n968(x) + end +end + +def fun_l11_n425(x) + if (x < 1) + fun_l12_n891(x) + else + fun_l12_n115(x) + end +end + +def fun_l11_n426(x) + if (x < 1) + fun_l12_n757(x) + else + fun_l12_n750(x) + end +end + +def fun_l11_n427(x) + if (x < 1) + fun_l12_n391(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n428(x) + if (x < 1) + fun_l12_n249(x) + else + fun_l12_n347(x) + end +end + +def fun_l11_n429(x) + if (x < 1) + fun_l12_n234(x) + else + fun_l12_n154(x) + end +end + +def fun_l11_n430(x) + if (x < 1) + fun_l12_n890(x) + else + fun_l12_n40(x) + end +end + +def fun_l11_n431(x) + if (x < 1) + fun_l12_n804(x) + else + fun_l12_n90(x) + end +end + +def fun_l11_n432(x) + if (x < 1) + fun_l12_n936(x) + else + fun_l12_n127(x) + end +end + +def fun_l11_n433(x) + if (x < 1) + fun_l12_n551(x) + else + fun_l12_n404(x) + end +end + +def fun_l11_n434(x) + if (x < 1) + fun_l12_n246(x) + else + fun_l12_n759(x) + end +end + +def fun_l11_n435(x) + if (x < 1) + fun_l12_n708(x) + else + fun_l12_n735(x) + end +end + +def fun_l11_n436(x) + if (x < 1) + fun_l12_n535(x) + else + fun_l12_n785(x) + end +end + +def fun_l11_n437(x) + if (x < 1) + fun_l12_n322(x) + else + fun_l12_n629(x) + end +end + +def fun_l11_n438(x) + if (x < 1) + fun_l12_n986(x) + else + fun_l12_n899(x) + end +end + +def fun_l11_n439(x) + if (x < 1) + fun_l12_n147(x) + else + fun_l12_n582(x) + end +end + +def fun_l11_n440(x) + if (x < 1) + fun_l12_n375(x) + else + fun_l12_n667(x) + end +end + +def fun_l11_n441(x) + if (x < 1) + fun_l12_n467(x) + else + fun_l12_n994(x) + end +end + +def fun_l11_n442(x) + if (x < 1) + fun_l12_n176(x) + else + fun_l12_n558(x) + end +end + +def fun_l11_n443(x) + if (x < 1) + fun_l12_n452(x) + else + fun_l12_n37(x) + end +end + +def fun_l11_n444(x) + if (x < 1) + fun_l12_n701(x) + else + fun_l12_n382(x) + end +end + +def fun_l11_n445(x) + if (x < 1) + fun_l12_n881(x) + else + fun_l12_n896(x) + end +end + +def fun_l11_n446(x) + if (x < 1) + fun_l12_n901(x) + else + fun_l12_n822(x) + end +end + +def fun_l11_n447(x) + if (x < 1) + fun_l12_n6(x) + else + fun_l12_n648(x) + end +end + +def fun_l11_n448(x) + if (x < 1) + fun_l12_n359(x) + else + fun_l12_n682(x) + end +end + +def fun_l11_n449(x) + if (x < 1) + fun_l12_n675(x) + else + fun_l12_n379(x) + end +end + +def fun_l11_n450(x) + if (x < 1) + fun_l12_n254(x) + else + fun_l12_n475(x) + end +end + +def fun_l11_n451(x) + if (x < 1) + fun_l12_n951(x) + else + fun_l12_n947(x) + end +end + +def fun_l11_n452(x) + if (x < 1) + fun_l12_n909(x) + else + fun_l12_n703(x) + end +end + +def fun_l11_n453(x) + if (x < 1) + fun_l12_n555(x) + else + fun_l12_n862(x) + end +end + +def fun_l11_n454(x) + if (x < 1) + fun_l12_n379(x) + else + fun_l12_n852(x) + end +end + +def fun_l11_n455(x) + if (x < 1) + fun_l12_n85(x) + else + fun_l12_n219(x) + end +end + +def fun_l11_n456(x) + if (x < 1) + fun_l12_n84(x) + else + fun_l12_n678(x) + end +end + +def fun_l11_n457(x) + if (x < 1) + fun_l12_n663(x) + else + fun_l12_n637(x) + end +end + +def fun_l11_n458(x) + if (x < 1) + fun_l12_n627(x) + else + fun_l12_n764(x) + end +end + +def fun_l11_n459(x) + if (x < 1) + fun_l12_n3(x) + else + fun_l12_n419(x) + end +end + +def fun_l11_n460(x) + if (x < 1) + fun_l12_n69(x) + else + fun_l12_n802(x) + end +end + +def fun_l11_n461(x) + if (x < 1) + fun_l12_n708(x) + else + fun_l12_n304(x) + end +end + +def fun_l11_n462(x) + if (x < 1) + fun_l12_n323(x) + else + fun_l12_n92(x) + end +end + +def fun_l11_n463(x) + if (x < 1) + fun_l12_n987(x) + else + fun_l12_n434(x) + end +end + +def fun_l11_n464(x) + if (x < 1) + fun_l12_n532(x) + else + fun_l12_n82(x) + end +end + +def fun_l11_n465(x) + if (x < 1) + fun_l12_n664(x) + else + fun_l12_n982(x) + end +end + +def fun_l11_n466(x) + if (x < 1) + fun_l12_n488(x) + else + fun_l12_n799(x) + end +end + +def fun_l11_n467(x) + if (x < 1) + fun_l12_n882(x) + else + fun_l12_n948(x) + end +end + +def fun_l11_n468(x) + if (x < 1) + fun_l12_n585(x) + else + fun_l12_n528(x) + end +end + +def fun_l11_n469(x) + if (x < 1) + fun_l12_n318(x) + else + fun_l12_n233(x) + end +end + +def fun_l11_n470(x) + if (x < 1) + fun_l12_n537(x) + else + fun_l12_n803(x) + end +end + +def fun_l11_n471(x) + if (x < 1) + fun_l12_n391(x) + else + fun_l12_n298(x) + end +end + +def fun_l11_n472(x) + if (x < 1) + fun_l12_n266(x) + else + fun_l12_n345(x) + end +end + +def fun_l11_n473(x) + if (x < 1) + fun_l12_n355(x) + else + fun_l12_n713(x) + end +end + +def fun_l11_n474(x) + if (x < 1) + fun_l12_n352(x) + else + fun_l12_n12(x) + end +end + +def fun_l11_n475(x) + if (x < 1) + fun_l12_n23(x) + else + fun_l12_n715(x) + end +end + +def fun_l11_n476(x) + if (x < 1) + fun_l12_n342(x) + else + fun_l12_n323(x) + end +end + +def fun_l11_n477(x) + if (x < 1) + fun_l12_n563(x) + else + fun_l12_n905(x) + end +end + +def fun_l11_n478(x) + if (x < 1) + fun_l12_n313(x) + else + fun_l12_n489(x) + end +end + +def fun_l11_n479(x) + if (x < 1) + fun_l12_n75(x) + else + fun_l12_n291(x) + end +end + +def fun_l11_n480(x) + if (x < 1) + fun_l12_n693(x) + else + fun_l12_n991(x) + end +end + +def fun_l11_n481(x) + if (x < 1) + fun_l12_n246(x) + else + fun_l12_n664(x) + end +end + +def fun_l11_n482(x) + if (x < 1) + fun_l12_n524(x) + else + fun_l12_n1(x) + end +end + +def fun_l11_n483(x) + if (x < 1) + fun_l12_n712(x) + else + fun_l12_n289(x) + end +end + +def fun_l11_n484(x) + if (x < 1) + fun_l12_n435(x) + else + fun_l12_n163(x) + end +end + +def fun_l11_n485(x) + if (x < 1) + fun_l12_n338(x) + else + fun_l12_n883(x) + end +end + +def fun_l11_n486(x) + if (x < 1) + fun_l12_n958(x) + else + fun_l12_n143(x) + end +end + +def fun_l11_n487(x) + if (x < 1) + fun_l12_n22(x) + else + fun_l12_n674(x) + end +end + +def fun_l11_n488(x) + if (x < 1) + fun_l12_n905(x) + else + fun_l12_n955(x) + end +end + +def fun_l11_n489(x) + if (x < 1) + fun_l12_n590(x) + else + fun_l12_n623(x) + end +end + +def fun_l11_n490(x) + if (x < 1) + fun_l12_n434(x) + else + fun_l12_n793(x) + end +end + +def fun_l11_n491(x) + if (x < 1) + fun_l12_n274(x) + else + fun_l12_n879(x) + end +end + +def fun_l11_n492(x) + if (x < 1) + fun_l12_n639(x) + else + fun_l12_n915(x) + end +end + +def fun_l11_n493(x) + if (x < 1) + fun_l12_n547(x) + else + fun_l12_n87(x) + end +end + +def fun_l11_n494(x) + if (x < 1) + fun_l12_n364(x) + else + fun_l12_n133(x) + end +end + +def fun_l11_n495(x) + if (x < 1) + fun_l12_n568(x) + else + fun_l12_n449(x) + end +end + +def fun_l11_n496(x) + if (x < 1) + fun_l12_n751(x) + else + fun_l12_n580(x) + end +end + +def fun_l11_n497(x) + if (x < 1) + fun_l12_n864(x) + else + fun_l12_n505(x) + end +end + +def fun_l11_n498(x) + if (x < 1) + fun_l12_n68(x) + else + fun_l12_n280(x) + end +end + +def fun_l11_n499(x) + if (x < 1) + fun_l12_n821(x) + else + fun_l12_n816(x) + end +end + +def fun_l11_n500(x) + if (x < 1) + fun_l12_n793(x) + else + fun_l12_n558(x) + end +end + +def fun_l11_n501(x) + if (x < 1) + fun_l12_n460(x) + else + fun_l12_n358(x) + end +end + +def fun_l11_n502(x) + if (x < 1) + fun_l12_n99(x) + else + fun_l12_n149(x) + end +end + +def fun_l11_n503(x) + if (x < 1) + fun_l12_n599(x) + else + fun_l12_n257(x) + end +end + +def fun_l11_n504(x) + if (x < 1) + fun_l12_n853(x) + else + fun_l12_n477(x) + end +end + +def fun_l11_n505(x) + if (x < 1) + fun_l12_n845(x) + else + fun_l12_n776(x) + end +end + +def fun_l11_n506(x) + if (x < 1) + fun_l12_n533(x) + else + fun_l12_n6(x) + end +end + +def fun_l11_n507(x) + if (x < 1) + fun_l12_n700(x) + else + fun_l12_n47(x) + end +end + +def fun_l11_n508(x) + if (x < 1) + fun_l12_n449(x) + else + fun_l12_n261(x) + end +end + +def fun_l11_n509(x) + if (x < 1) + fun_l12_n773(x) + else + fun_l12_n583(x) + end +end + +def fun_l11_n510(x) + if (x < 1) + fun_l12_n252(x) + else + fun_l12_n215(x) + end +end + +def fun_l11_n511(x) + if (x < 1) + fun_l12_n280(x) + else + fun_l12_n589(x) + end +end + +def fun_l11_n512(x) + if (x < 1) + fun_l12_n796(x) + else + fun_l12_n803(x) + end +end + +def fun_l11_n513(x) + if (x < 1) + fun_l12_n450(x) + else + fun_l12_n606(x) + end +end + +def fun_l11_n514(x) + if (x < 1) + fun_l12_n509(x) + else + fun_l12_n521(x) + end +end + +def fun_l11_n515(x) + if (x < 1) + fun_l12_n658(x) + else + fun_l12_n912(x) + end +end + +def fun_l11_n516(x) + if (x < 1) + fun_l12_n181(x) + else + fun_l12_n724(x) + end +end + +def fun_l11_n517(x) + if (x < 1) + fun_l12_n167(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n518(x) + if (x < 1) + fun_l12_n654(x) + else + fun_l12_n67(x) + end +end + +def fun_l11_n519(x) + if (x < 1) + fun_l12_n192(x) + else + fun_l12_n110(x) + end +end + +def fun_l11_n520(x) + if (x < 1) + fun_l12_n271(x) + else + fun_l12_n74(x) + end +end + +def fun_l11_n521(x) + if (x < 1) + fun_l12_n324(x) + else + fun_l12_n224(x) + end +end + +def fun_l11_n522(x) + if (x < 1) + fun_l12_n535(x) + else + fun_l12_n537(x) + end +end + +def fun_l11_n523(x) + if (x < 1) + fun_l12_n103(x) + else + fun_l12_n942(x) + end +end + +def fun_l11_n524(x) + if (x < 1) + fun_l12_n755(x) + else + fun_l12_n431(x) + end +end + +def fun_l11_n525(x) + if (x < 1) + fun_l12_n243(x) + else + fun_l12_n131(x) + end +end + +def fun_l11_n526(x) + if (x < 1) + fun_l12_n270(x) + else + fun_l12_n747(x) + end +end + +def fun_l11_n527(x) + if (x < 1) + fun_l12_n566(x) + else + fun_l12_n284(x) + end +end + +def fun_l11_n528(x) + if (x < 1) + fun_l12_n510(x) + else + fun_l12_n928(x) + end +end + +def fun_l11_n529(x) + if (x < 1) + fun_l12_n354(x) + else + fun_l12_n1(x) + end +end + +def fun_l11_n530(x) + if (x < 1) + fun_l12_n271(x) + else + fun_l12_n875(x) + end +end + +def fun_l11_n531(x) + if (x < 1) + fun_l12_n871(x) + else + fun_l12_n441(x) + end +end + +def fun_l11_n532(x) + if (x < 1) + fun_l12_n727(x) + else + fun_l12_n903(x) + end +end + +def fun_l11_n533(x) + if (x < 1) + fun_l12_n843(x) + else + fun_l12_n202(x) + end +end + +def fun_l11_n534(x) + if (x < 1) + fun_l12_n798(x) + else + fun_l12_n309(x) + end +end + +def fun_l11_n535(x) + if (x < 1) + fun_l12_n397(x) + else + fun_l12_n377(x) + end +end + +def fun_l11_n536(x) + if (x < 1) + fun_l12_n441(x) + else + fun_l12_n253(x) + end +end + +def fun_l11_n537(x) + if (x < 1) + fun_l12_n861(x) + else + fun_l12_n84(x) + end +end + +def fun_l11_n538(x) + if (x < 1) + fun_l12_n268(x) + else + fun_l12_n627(x) + end +end + +def fun_l11_n539(x) + if (x < 1) + fun_l12_n923(x) + else + fun_l12_n650(x) + end +end + +def fun_l11_n540(x) + if (x < 1) + fun_l12_n503(x) + else + fun_l12_n598(x) + end +end + +def fun_l11_n541(x) + if (x < 1) + fun_l12_n355(x) + else + fun_l12_n201(x) + end +end + +def fun_l11_n542(x) + if (x < 1) + fun_l12_n956(x) + else + fun_l12_n789(x) + end +end + +def fun_l11_n543(x) + if (x < 1) + fun_l12_n438(x) + else + fun_l12_n47(x) + end +end + +def fun_l11_n544(x) + if (x < 1) + fun_l12_n425(x) + else + fun_l12_n109(x) + end +end + +def fun_l11_n545(x) + if (x < 1) + fun_l12_n540(x) + else + fun_l12_n360(x) + end +end + +def fun_l11_n546(x) + if (x < 1) + fun_l12_n228(x) + else + fun_l12_n270(x) + end +end + +def fun_l11_n547(x) + if (x < 1) + fun_l12_n528(x) + else + fun_l12_n423(x) + end +end + +def fun_l11_n548(x) + if (x < 1) + fun_l12_n656(x) + else + fun_l12_n269(x) + end +end + +def fun_l11_n549(x) + if (x < 1) + fun_l12_n541(x) + else + fun_l12_n488(x) + end +end + +def fun_l11_n550(x) + if (x < 1) + fun_l12_n240(x) + else + fun_l12_n990(x) + end +end + +def fun_l11_n551(x) + if (x < 1) + fun_l12_n279(x) + else + fun_l12_n61(x) + end +end + +def fun_l11_n552(x) + if (x < 1) + fun_l12_n996(x) + else + fun_l12_n738(x) + end +end + +def fun_l11_n553(x) + if (x < 1) + fun_l12_n334(x) + else + fun_l12_n117(x) + end +end + +def fun_l11_n554(x) + if (x < 1) + fun_l12_n943(x) + else + fun_l12_n754(x) + end +end + +def fun_l11_n555(x) + if (x < 1) + fun_l12_n256(x) + else + fun_l12_n961(x) + end +end + +def fun_l11_n556(x) + if (x < 1) + fun_l12_n530(x) + else + fun_l12_n378(x) + end +end + +def fun_l11_n557(x) + if (x < 1) + fun_l12_n681(x) + else + fun_l12_n153(x) + end +end + +def fun_l11_n558(x) + if (x < 1) + fun_l12_n145(x) + else + fun_l12_n951(x) + end +end + +def fun_l11_n559(x) + if (x < 1) + fun_l12_n107(x) + else + fun_l12_n341(x) + end +end + +def fun_l11_n560(x) + if (x < 1) + fun_l12_n570(x) + else + fun_l12_n152(x) + end +end + +def fun_l11_n561(x) + if (x < 1) + fun_l12_n351(x) + else + fun_l12_n664(x) + end +end + +def fun_l11_n562(x) + if (x < 1) + fun_l12_n825(x) + else + fun_l12_n226(x) + end +end + +def fun_l11_n563(x) + if (x < 1) + fun_l12_n898(x) + else + fun_l12_n553(x) + end +end + +def fun_l11_n564(x) + if (x < 1) + fun_l12_n122(x) + else + fun_l12_n618(x) + end +end + +def fun_l11_n565(x) + if (x < 1) + fun_l12_n185(x) + else + fun_l12_n51(x) + end +end + +def fun_l11_n566(x) + if (x < 1) + fun_l12_n359(x) + else + fun_l12_n67(x) + end +end + +def fun_l11_n567(x) + if (x < 1) + fun_l12_n471(x) + else + fun_l12_n28(x) + end +end + +def fun_l11_n568(x) + if (x < 1) + fun_l12_n195(x) + else + fun_l12_n104(x) + end +end + +def fun_l11_n569(x) + if (x < 1) + fun_l12_n556(x) + else + fun_l12_n242(x) + end +end + +def fun_l11_n570(x) + if (x < 1) + fun_l12_n203(x) + else + fun_l12_n204(x) + end +end + +def fun_l11_n571(x) + if (x < 1) + fun_l12_n217(x) + else + fun_l12_n392(x) + end +end + +def fun_l11_n572(x) + if (x < 1) + fun_l12_n223(x) + else + fun_l12_n176(x) + end +end + +def fun_l11_n573(x) + if (x < 1) + fun_l12_n184(x) + else + fun_l12_n19(x) + end +end + +def fun_l11_n574(x) + if (x < 1) + fun_l12_n799(x) + else + fun_l12_n652(x) + end +end + +def fun_l11_n575(x) + if (x < 1) + fun_l12_n311(x) + else + fun_l12_n332(x) + end +end + +def fun_l11_n576(x) + if (x < 1) + fun_l12_n928(x) + else + fun_l12_n584(x) + end +end + +def fun_l11_n577(x) + if (x < 1) + fun_l12_n796(x) + else + fun_l12_n931(x) + end +end + +def fun_l11_n578(x) + if (x < 1) + fun_l12_n991(x) + else + fun_l12_n985(x) + end +end + +def fun_l11_n579(x) + if (x < 1) + fun_l12_n246(x) + else + fun_l12_n253(x) + end +end + +def fun_l11_n580(x) + if (x < 1) + fun_l12_n492(x) + else + fun_l12_n239(x) + end +end + +def fun_l11_n581(x) + if (x < 1) + fun_l12_n428(x) + else + fun_l12_n351(x) + end +end + +def fun_l11_n582(x) + if (x < 1) + fun_l12_n184(x) + else + fun_l12_n37(x) + end +end + +def fun_l11_n583(x) + if (x < 1) + fun_l12_n809(x) + else + fun_l12_n527(x) + end +end + +def fun_l11_n584(x) + if (x < 1) + fun_l12_n661(x) + else + fun_l12_n539(x) + end +end + +def fun_l11_n585(x) + if (x < 1) + fun_l12_n696(x) + else + fun_l12_n190(x) + end +end + +def fun_l11_n586(x) + if (x < 1) + fun_l12_n178(x) + else + fun_l12_n301(x) + end +end + +def fun_l11_n587(x) + if (x < 1) + fun_l12_n316(x) + else + fun_l12_n731(x) + end +end + +def fun_l11_n588(x) + if (x < 1) + fun_l12_n502(x) + else + fun_l12_n776(x) + end +end + +def fun_l11_n589(x) + if (x < 1) + fun_l12_n273(x) + else + fun_l12_n268(x) + end +end + +def fun_l11_n590(x) + if (x < 1) + fun_l12_n623(x) + else + fun_l12_n622(x) + end +end + +def fun_l11_n591(x) + if (x < 1) + fun_l12_n359(x) + else + fun_l12_n694(x) + end +end + +def fun_l11_n592(x) + if (x < 1) + fun_l12_n71(x) + else + fun_l12_n984(x) + end +end + +def fun_l11_n593(x) + if (x < 1) + fun_l12_n790(x) + else + fun_l12_n547(x) + end +end + +def fun_l11_n594(x) + if (x < 1) + fun_l12_n313(x) + else + fun_l12_n526(x) + end +end + +def fun_l11_n595(x) + if (x < 1) + fun_l12_n239(x) + else + fun_l12_n821(x) + end +end + +def fun_l11_n596(x) + if (x < 1) + fun_l12_n36(x) + else + fun_l12_n141(x) + end +end + +def fun_l11_n597(x) + if (x < 1) + fun_l12_n450(x) + else + fun_l12_n65(x) + end +end + +def fun_l11_n598(x) + if (x < 1) + fun_l12_n226(x) + else + fun_l12_n490(x) + end +end + +def fun_l11_n599(x) + if (x < 1) + fun_l12_n716(x) + else + fun_l12_n7(x) + end +end + +def fun_l11_n600(x) + if (x < 1) + fun_l12_n694(x) + else + fun_l12_n663(x) + end +end + +def fun_l11_n601(x) + if (x < 1) + fun_l12_n690(x) + else + fun_l12_n256(x) + end +end + +def fun_l11_n602(x) + if (x < 1) + fun_l12_n251(x) + else + fun_l12_n177(x) + end +end + +def fun_l11_n603(x) + if (x < 1) + fun_l12_n659(x) + else + fun_l12_n732(x) + end +end + +def fun_l11_n604(x) + if (x < 1) + fun_l12_n440(x) + else + fun_l12_n334(x) + end +end + +def fun_l11_n605(x) + if (x < 1) + fun_l12_n396(x) + else + fun_l12_n931(x) + end +end + +def fun_l11_n606(x) + if (x < 1) + fun_l12_n687(x) + else + fun_l12_n88(x) + end +end + +def fun_l11_n607(x) + if (x < 1) + fun_l12_n647(x) + else + fun_l12_n799(x) + end +end + +def fun_l11_n608(x) + if (x < 1) + fun_l12_n383(x) + else + fun_l12_n889(x) + end +end + +def fun_l11_n609(x) + if (x < 1) + fun_l12_n174(x) + else + fun_l12_n121(x) + end +end + +def fun_l11_n610(x) + if (x < 1) + fun_l12_n818(x) + else + fun_l12_n835(x) + end +end + +def fun_l11_n611(x) + if (x < 1) + fun_l12_n684(x) + else + fun_l12_n625(x) + end +end + +def fun_l11_n612(x) + if (x < 1) + fun_l12_n961(x) + else + fun_l12_n711(x) + end +end + +def fun_l11_n613(x) + if (x < 1) + fun_l12_n15(x) + else + fun_l12_n542(x) + end +end + +def fun_l11_n614(x) + if (x < 1) + fun_l12_n378(x) + else + fun_l12_n809(x) + end +end + +def fun_l11_n615(x) + if (x < 1) + fun_l12_n970(x) + else + fun_l12_n283(x) + end +end + +def fun_l11_n616(x) + if (x < 1) + fun_l12_n391(x) + else + fun_l12_n949(x) + end +end + +def fun_l11_n617(x) + if (x < 1) + fun_l12_n135(x) + else + fun_l12_n29(x) + end +end + +def fun_l11_n618(x) + if (x < 1) + fun_l12_n449(x) + else + fun_l12_n834(x) + end +end + +def fun_l11_n619(x) + if (x < 1) + fun_l12_n555(x) + else + fun_l12_n464(x) + end +end + +def fun_l11_n620(x) + if (x < 1) + fun_l12_n414(x) + else + fun_l12_n632(x) + end +end + +def fun_l11_n621(x) + if (x < 1) + fun_l12_n964(x) + else + fun_l12_n311(x) + end +end + +def fun_l11_n622(x) + if (x < 1) + fun_l12_n184(x) + else + fun_l12_n499(x) + end +end + +def fun_l11_n623(x) + if (x < 1) + fun_l12_n441(x) + else + fun_l12_n124(x) + end +end + +def fun_l11_n624(x) + if (x < 1) + fun_l12_n884(x) + else + fun_l12_n484(x) + end +end + +def fun_l11_n625(x) + if (x < 1) + fun_l12_n878(x) + else + fun_l12_n646(x) + end +end + +def fun_l11_n626(x) + if (x < 1) + fun_l12_n918(x) + else + fun_l12_n481(x) + end +end + +def fun_l11_n627(x) + if (x < 1) + fun_l12_n162(x) + else + fun_l12_n197(x) + end +end + +def fun_l11_n628(x) + if (x < 1) + fun_l12_n852(x) + else + fun_l12_n874(x) + end +end + +def fun_l11_n629(x) + if (x < 1) + fun_l12_n654(x) + else + fun_l12_n709(x) + end +end + +def fun_l11_n630(x) + if (x < 1) + fun_l12_n819(x) + else + fun_l12_n325(x) + end +end + +def fun_l11_n631(x) + if (x < 1) + fun_l12_n776(x) + else + fun_l12_n621(x) + end +end + +def fun_l11_n632(x) + if (x < 1) + fun_l12_n648(x) + else + fun_l12_n53(x) + end +end + +def fun_l11_n633(x) + if (x < 1) + fun_l12_n182(x) + else + fun_l12_n267(x) + end +end + +def fun_l11_n634(x) + if (x < 1) + fun_l12_n17(x) + else + fun_l12_n415(x) + end +end + +def fun_l11_n635(x) + if (x < 1) + fun_l12_n123(x) + else + fun_l12_n862(x) + end +end + +def fun_l11_n636(x) + if (x < 1) + fun_l12_n594(x) + else + fun_l12_n878(x) + end +end + +def fun_l11_n637(x) + if (x < 1) + fun_l12_n913(x) + else + fun_l12_n245(x) + end +end + +def fun_l11_n638(x) + if (x < 1) + fun_l12_n976(x) + else + fun_l12_n19(x) + end +end + +def fun_l11_n639(x) + if (x < 1) + fun_l12_n490(x) + else + fun_l12_n999(x) + end +end + +def fun_l11_n640(x) + if (x < 1) + fun_l12_n345(x) + else + fun_l12_n585(x) + end +end + +def fun_l11_n641(x) + if (x < 1) + fun_l12_n245(x) + else + fun_l12_n566(x) + end +end + +def fun_l11_n642(x) + if (x < 1) + fun_l12_n680(x) + else + fun_l12_n77(x) + end +end + +def fun_l11_n643(x) + if (x < 1) + fun_l12_n330(x) + else + fun_l12_n268(x) + end +end + +def fun_l11_n644(x) + if (x < 1) + fun_l12_n651(x) + else + fun_l12_n386(x) + end +end + +def fun_l11_n645(x) + if (x < 1) + fun_l12_n276(x) + else + fun_l12_n471(x) + end +end + +def fun_l11_n646(x) + if (x < 1) + fun_l12_n784(x) + else + fun_l12_n892(x) + end +end + +def fun_l11_n647(x) + if (x < 1) + fun_l12_n963(x) + else + fun_l12_n864(x) + end +end + +def fun_l11_n648(x) + if (x < 1) + fun_l12_n58(x) + else + fun_l12_n252(x) + end +end + +def fun_l11_n649(x) + if (x < 1) + fun_l12_n321(x) + else + fun_l12_n593(x) + end +end + +def fun_l11_n650(x) + if (x < 1) + fun_l12_n598(x) + else + fun_l12_n54(x) + end +end + +def fun_l11_n651(x) + if (x < 1) + fun_l12_n201(x) + else + fun_l12_n760(x) + end +end + +def fun_l11_n652(x) + if (x < 1) + fun_l12_n880(x) + else + fun_l12_n841(x) + end +end + +def fun_l11_n653(x) + if (x < 1) + fun_l12_n61(x) + else + fun_l12_n403(x) + end +end + +def fun_l11_n654(x) + if (x < 1) + fun_l12_n114(x) + else + fun_l12_n768(x) + end +end + +def fun_l11_n655(x) + if (x < 1) + fun_l12_n511(x) + else + fun_l12_n521(x) + end +end + +def fun_l11_n656(x) + if (x < 1) + fun_l12_n27(x) + else + fun_l12_n490(x) + end +end + +def fun_l11_n657(x) + if (x < 1) + fun_l12_n217(x) + else + fun_l12_n547(x) + end +end + +def fun_l11_n658(x) + if (x < 1) + fun_l12_n549(x) + else + fun_l12_n823(x) + end +end + +def fun_l11_n659(x) + if (x < 1) + fun_l12_n327(x) + else + fun_l12_n529(x) + end +end + +def fun_l11_n660(x) + if (x < 1) + fun_l12_n395(x) + else + fun_l12_n797(x) + end +end + +def fun_l11_n661(x) + if (x < 1) + fun_l12_n867(x) + else + fun_l12_n142(x) + end +end + +def fun_l11_n662(x) + if (x < 1) + fun_l12_n818(x) + else + fun_l12_n311(x) + end +end + +def fun_l11_n663(x) + if (x < 1) + fun_l12_n628(x) + else + fun_l12_n798(x) + end +end + +def fun_l11_n664(x) + if (x < 1) + fun_l12_n260(x) + else + fun_l12_n607(x) + end +end + +def fun_l11_n665(x) + if (x < 1) + fun_l12_n911(x) + else + fun_l12_n487(x) + end +end + +def fun_l11_n666(x) + if (x < 1) + fun_l12_n340(x) + else + fun_l12_n23(x) + end +end + +def fun_l11_n667(x) + if (x < 1) + fun_l12_n744(x) + else + fun_l12_n874(x) + end +end + +def fun_l11_n668(x) + if (x < 1) + fun_l12_n53(x) + else + fun_l12_n203(x) + end +end + +def fun_l11_n669(x) + if (x < 1) + fun_l12_n775(x) + else + fun_l12_n963(x) + end +end + +def fun_l11_n670(x) + if (x < 1) + fun_l12_n922(x) + else + fun_l12_n0(x) + end +end + +def fun_l11_n671(x) + if (x < 1) + fun_l12_n23(x) + else + fun_l12_n798(x) + end +end + +def fun_l11_n672(x) + if (x < 1) + fun_l12_n453(x) + else + fun_l12_n667(x) + end +end + +def fun_l11_n673(x) + if (x < 1) + fun_l12_n991(x) + else + fun_l12_n350(x) + end +end + +def fun_l11_n674(x) + if (x < 1) + fun_l12_n865(x) + else + fun_l12_n95(x) + end +end + +def fun_l11_n675(x) + if (x < 1) + fun_l12_n404(x) + else + fun_l12_n714(x) + end +end + +def fun_l11_n676(x) + if (x < 1) + fun_l12_n576(x) + else + fun_l12_n162(x) + end +end + +def fun_l11_n677(x) + if (x < 1) + fun_l12_n530(x) + else + fun_l12_n453(x) + end +end + +def fun_l11_n678(x) + if (x < 1) + fun_l12_n127(x) + else + fun_l12_n224(x) + end +end + +def fun_l11_n679(x) + if (x < 1) + fun_l12_n658(x) + else + fun_l12_n11(x) + end +end + +def fun_l11_n680(x) + if (x < 1) + fun_l12_n778(x) + else + fun_l12_n202(x) + end +end + +def fun_l11_n681(x) + if (x < 1) + fun_l12_n745(x) + else + fun_l12_n690(x) + end +end + +def fun_l11_n682(x) + if (x < 1) + fun_l12_n920(x) + else + fun_l12_n54(x) + end +end + +def fun_l11_n683(x) + if (x < 1) + fun_l12_n726(x) + else + fun_l12_n466(x) + end +end + +def fun_l11_n684(x) + if (x < 1) + fun_l12_n709(x) + else + fun_l12_n287(x) + end +end + +def fun_l11_n685(x) + if (x < 1) + fun_l12_n304(x) + else + fun_l12_n617(x) + end +end + +def fun_l11_n686(x) + if (x < 1) + fun_l12_n834(x) + else + fun_l12_n240(x) + end +end + +def fun_l11_n687(x) + if (x < 1) + fun_l12_n406(x) + else + fun_l12_n588(x) + end +end + +def fun_l11_n688(x) + if (x < 1) + fun_l12_n308(x) + else + fun_l12_n790(x) + end +end + +def fun_l11_n689(x) + if (x < 1) + fun_l12_n969(x) + else + fun_l12_n249(x) + end +end + +def fun_l11_n690(x) + if (x < 1) + fun_l12_n760(x) + else + fun_l12_n807(x) + end +end + +def fun_l11_n691(x) + if (x < 1) + fun_l12_n417(x) + else + fun_l12_n645(x) + end +end + +def fun_l11_n692(x) + if (x < 1) + fun_l12_n722(x) + else + fun_l12_n614(x) + end +end + +def fun_l11_n693(x) + if (x < 1) + fun_l12_n19(x) + else + fun_l12_n497(x) + end +end + +def fun_l11_n694(x) + if (x < 1) + fun_l12_n580(x) + else + fun_l12_n76(x) + end +end + +def fun_l11_n695(x) + if (x < 1) + fun_l12_n527(x) + else + fun_l12_n819(x) + end +end + +def fun_l11_n696(x) + if (x < 1) + fun_l12_n71(x) + else + fun_l12_n906(x) + end +end + +def fun_l11_n697(x) + if (x < 1) + fun_l12_n95(x) + else + fun_l12_n743(x) + end +end + +def fun_l11_n698(x) + if (x < 1) + fun_l12_n544(x) + else + fun_l12_n265(x) + end +end + +def fun_l11_n699(x) + if (x < 1) + fun_l12_n833(x) + else + fun_l12_n210(x) + end +end + +def fun_l11_n700(x) + if (x < 1) + fun_l12_n865(x) + else + fun_l12_n318(x) + end +end + +def fun_l11_n701(x) + if (x < 1) + fun_l12_n88(x) + else + fun_l12_n120(x) + end +end + +def fun_l11_n702(x) + if (x < 1) + fun_l12_n165(x) + else + fun_l12_n671(x) + end +end + +def fun_l11_n703(x) + if (x < 1) + fun_l12_n607(x) + else + fun_l12_n730(x) + end +end + +def fun_l11_n704(x) + if (x < 1) + fun_l12_n690(x) + else + fun_l12_n553(x) + end +end + +def fun_l11_n705(x) + if (x < 1) + fun_l12_n826(x) + else + fun_l12_n665(x) + end +end + +def fun_l11_n706(x) + if (x < 1) + fun_l12_n125(x) + else + fun_l12_n167(x) + end +end + +def fun_l11_n707(x) + if (x < 1) + fun_l12_n961(x) + else + fun_l12_n73(x) + end +end + +def fun_l11_n708(x) + if (x < 1) + fun_l12_n446(x) + else + fun_l12_n373(x) + end +end + +def fun_l11_n709(x) + if (x < 1) + fun_l12_n199(x) + else + fun_l12_n803(x) + end +end + +def fun_l11_n710(x) + if (x < 1) + fun_l12_n960(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n711(x) + if (x < 1) + fun_l12_n602(x) + else + fun_l12_n896(x) + end +end + +def fun_l11_n712(x) + if (x < 1) + fun_l12_n198(x) + else + fun_l12_n857(x) + end +end + +def fun_l11_n713(x) + if (x < 1) + fun_l12_n19(x) + else + fun_l12_n938(x) + end +end + +def fun_l11_n714(x) + if (x < 1) + fun_l12_n530(x) + else + fun_l12_n432(x) + end +end + +def fun_l11_n715(x) + if (x < 1) + fun_l12_n99(x) + else + fun_l12_n382(x) + end +end + +def fun_l11_n716(x) + if (x < 1) + fun_l12_n623(x) + else + fun_l12_n461(x) + end +end + +def fun_l11_n717(x) + if (x < 1) + fun_l12_n658(x) + else + fun_l12_n432(x) + end +end + +def fun_l11_n718(x) + if (x < 1) + fun_l12_n17(x) + else + fun_l12_n83(x) + end +end + +def fun_l11_n719(x) + if (x < 1) + fun_l12_n439(x) + else + fun_l12_n747(x) + end +end + +def fun_l11_n720(x) + if (x < 1) + fun_l12_n259(x) + else + fun_l12_n80(x) + end +end + +def fun_l11_n721(x) + if (x < 1) + fun_l12_n749(x) + else + fun_l12_n108(x) + end +end + +def fun_l11_n722(x) + if (x < 1) + fun_l12_n20(x) + else + fun_l12_n391(x) + end +end + +def fun_l11_n723(x) + if (x < 1) + fun_l12_n181(x) + else + fun_l12_n204(x) + end +end + +def fun_l11_n724(x) + if (x < 1) + fun_l12_n426(x) + else + fun_l12_n109(x) + end +end + +def fun_l11_n725(x) + if (x < 1) + fun_l12_n436(x) + else + fun_l12_n754(x) + end +end + +def fun_l11_n726(x) + if (x < 1) + fun_l12_n496(x) + else + fun_l12_n265(x) + end +end + +def fun_l11_n727(x) + if (x < 1) + fun_l12_n58(x) + else + fun_l12_n982(x) + end +end + +def fun_l11_n728(x) + if (x < 1) + fun_l12_n236(x) + else + fun_l12_n152(x) + end +end + +def fun_l11_n729(x) + if (x < 1) + fun_l12_n818(x) + else + fun_l12_n95(x) + end +end + +def fun_l11_n730(x) + if (x < 1) + fun_l12_n696(x) + else + fun_l12_n263(x) + end +end + +def fun_l11_n731(x) + if (x < 1) + fun_l12_n539(x) + else + fun_l12_n774(x) + end +end + +def fun_l11_n732(x) + if (x < 1) + fun_l12_n788(x) + else + fun_l12_n454(x) + end +end + +def fun_l11_n733(x) + if (x < 1) + fun_l12_n131(x) + else + fun_l12_n877(x) + end +end + +def fun_l11_n734(x) + if (x < 1) + fun_l12_n449(x) + else + fun_l12_n222(x) + end +end + +def fun_l11_n735(x) + if (x < 1) + fun_l12_n71(x) + else + fun_l12_n467(x) + end +end + +def fun_l11_n736(x) + if (x < 1) + fun_l12_n220(x) + else + fun_l12_n214(x) + end +end + +def fun_l11_n737(x) + if (x < 1) + fun_l12_n537(x) + else + fun_l12_n173(x) + end +end + +def fun_l11_n738(x) + if (x < 1) + fun_l12_n897(x) + else + fun_l12_n515(x) + end +end + +def fun_l11_n739(x) + if (x < 1) + fun_l12_n724(x) + else + fun_l12_n48(x) + end +end + +def fun_l11_n740(x) + if (x < 1) + fun_l12_n61(x) + else + fun_l12_n963(x) + end +end + +def fun_l11_n741(x) + if (x < 1) + fun_l12_n40(x) + else + fun_l12_n553(x) + end +end + +def fun_l11_n742(x) + if (x < 1) + fun_l12_n361(x) + else + fun_l12_n975(x) + end +end + +def fun_l11_n743(x) + if (x < 1) + fun_l12_n306(x) + else + fun_l12_n982(x) + end +end + +def fun_l11_n744(x) + if (x < 1) + fun_l12_n951(x) + else + fun_l12_n590(x) + end +end + +def fun_l11_n745(x) + if (x < 1) + fun_l12_n224(x) + else + fun_l12_n409(x) + end +end + +def fun_l11_n746(x) + if (x < 1) + fun_l12_n24(x) + else + fun_l12_n249(x) + end +end + +def fun_l11_n747(x) + if (x < 1) + fun_l12_n533(x) + else + fun_l12_n543(x) + end +end + +def fun_l11_n748(x) + if (x < 1) + fun_l12_n616(x) + else + fun_l12_n63(x) + end +end + +def fun_l11_n749(x) + if (x < 1) + fun_l12_n365(x) + else + fun_l12_n335(x) + end +end + +def fun_l11_n750(x) + if (x < 1) + fun_l12_n134(x) + else + fun_l12_n363(x) + end +end + +def fun_l11_n751(x) + if (x < 1) + fun_l12_n413(x) + else + fun_l12_n582(x) + end +end + +def fun_l11_n752(x) + if (x < 1) + fun_l12_n987(x) + else + fun_l12_n948(x) + end +end + +def fun_l11_n753(x) + if (x < 1) + fun_l12_n696(x) + else + fun_l12_n374(x) + end +end + +def fun_l11_n754(x) + if (x < 1) + fun_l12_n730(x) + else + fun_l12_n345(x) + end +end + +def fun_l11_n755(x) + if (x < 1) + fun_l12_n857(x) + else + fun_l12_n441(x) + end +end + +def fun_l11_n756(x) + if (x < 1) + fun_l12_n711(x) + else + fun_l12_n39(x) + end +end + +def fun_l11_n757(x) + if (x < 1) + fun_l12_n946(x) + else + fun_l12_n657(x) + end +end + +def fun_l11_n758(x) + if (x < 1) + fun_l12_n470(x) + else + fun_l12_n650(x) + end +end + +def fun_l11_n759(x) + if (x < 1) + fun_l12_n119(x) + else + fun_l12_n479(x) + end +end + +def fun_l11_n760(x) + if (x < 1) + fun_l12_n429(x) + else + fun_l12_n922(x) + end +end + +def fun_l11_n761(x) + if (x < 1) + fun_l12_n13(x) + else + fun_l12_n134(x) + end +end + +def fun_l11_n762(x) + if (x < 1) + fun_l12_n797(x) + else + fun_l12_n223(x) + end +end + +def fun_l11_n763(x) + if (x < 1) + fun_l12_n945(x) + else + fun_l12_n197(x) + end +end + +def fun_l11_n764(x) + if (x < 1) + fun_l12_n612(x) + else + fun_l12_n773(x) + end +end + +def fun_l11_n765(x) + if (x < 1) + fun_l12_n478(x) + else + fun_l12_n972(x) + end +end + +def fun_l11_n766(x) + if (x < 1) + fun_l12_n946(x) + else + fun_l12_n9(x) + end +end + +def fun_l11_n767(x) + if (x < 1) + fun_l12_n247(x) + else + fun_l12_n730(x) + end +end + +def fun_l11_n768(x) + if (x < 1) + fun_l12_n223(x) + else + fun_l12_n986(x) + end +end + +def fun_l11_n769(x) + if (x < 1) + fun_l12_n676(x) + else + fun_l12_n527(x) + end +end + +def fun_l11_n770(x) + if (x < 1) + fun_l12_n112(x) + else + fun_l12_n660(x) + end +end + +def fun_l11_n771(x) + if (x < 1) + fun_l12_n457(x) + else + fun_l12_n733(x) + end +end + +def fun_l11_n772(x) + if (x < 1) + fun_l12_n633(x) + else + fun_l12_n449(x) + end +end + +def fun_l11_n773(x) + if (x < 1) + fun_l12_n910(x) + else + fun_l12_n329(x) + end +end + +def fun_l11_n774(x) + if (x < 1) + fun_l12_n354(x) + else + fun_l12_n233(x) + end +end + +def fun_l11_n775(x) + if (x < 1) + fun_l12_n887(x) + else + fun_l12_n100(x) + end +end + +def fun_l11_n776(x) + if (x < 1) + fun_l12_n65(x) + else + fun_l12_n199(x) + end +end + +def fun_l11_n777(x) + if (x < 1) + fun_l12_n978(x) + else + fun_l12_n364(x) + end +end + +def fun_l11_n778(x) + if (x < 1) + fun_l12_n502(x) + else + fun_l12_n90(x) + end +end + +def fun_l11_n779(x) + if (x < 1) + fun_l12_n37(x) + else + fun_l12_n668(x) + end +end + +def fun_l11_n780(x) + if (x < 1) + fun_l12_n80(x) + else + fun_l12_n603(x) + end +end + +def fun_l11_n781(x) + if (x < 1) + fun_l12_n435(x) + else + fun_l12_n583(x) + end +end + +def fun_l11_n782(x) + if (x < 1) + fun_l12_n899(x) + else + fun_l12_n863(x) + end +end + +def fun_l11_n783(x) + if (x < 1) + fun_l12_n414(x) + else + fun_l12_n96(x) + end +end + +def fun_l11_n784(x) + if (x < 1) + fun_l12_n286(x) + else + fun_l12_n126(x) + end +end + +def fun_l11_n785(x) + if (x < 1) + fun_l12_n444(x) + else + fun_l12_n344(x) + end +end + +def fun_l11_n786(x) + if (x < 1) + fun_l12_n484(x) + else + fun_l12_n469(x) + end +end + +def fun_l11_n787(x) + if (x < 1) + fun_l12_n686(x) + else + fun_l12_n728(x) + end +end + +def fun_l11_n788(x) + if (x < 1) + fun_l12_n938(x) + else + fun_l12_n70(x) + end +end + +def fun_l11_n789(x) + if (x < 1) + fun_l12_n958(x) + else + fun_l12_n633(x) + end +end + +def fun_l11_n790(x) + if (x < 1) + fun_l12_n984(x) + else + fun_l12_n39(x) + end +end + +def fun_l11_n791(x) + if (x < 1) + fun_l12_n877(x) + else + fun_l12_n721(x) + end +end + +def fun_l11_n792(x) + if (x < 1) + fun_l12_n710(x) + else + fun_l12_n840(x) + end +end + +def fun_l11_n793(x) + if (x < 1) + fun_l12_n955(x) + else + fun_l12_n774(x) + end +end + +def fun_l11_n794(x) + if (x < 1) + fun_l12_n816(x) + else + fun_l12_n859(x) + end +end + +def fun_l11_n795(x) + if (x < 1) + fun_l12_n722(x) + else + fun_l12_n700(x) + end +end + +def fun_l11_n796(x) + if (x < 1) + fun_l12_n508(x) + else + fun_l12_n617(x) + end +end + +def fun_l11_n797(x) + if (x < 1) + fun_l12_n382(x) + else + fun_l12_n1(x) + end +end + +def fun_l11_n798(x) + if (x < 1) + fun_l12_n857(x) + else + fun_l12_n141(x) + end +end + +def fun_l11_n799(x) + if (x < 1) + fun_l12_n711(x) + else + fun_l12_n842(x) + end +end + +def fun_l11_n800(x) + if (x < 1) + fun_l12_n588(x) + else + fun_l12_n511(x) + end +end + +def fun_l11_n801(x) + if (x < 1) + fun_l12_n114(x) + else + fun_l12_n516(x) + end +end + +def fun_l11_n802(x) + if (x < 1) + fun_l12_n792(x) + else + fun_l12_n128(x) + end +end + +def fun_l11_n803(x) + if (x < 1) + fun_l12_n833(x) + else + fun_l12_n444(x) + end +end + +def fun_l11_n804(x) + if (x < 1) + fun_l12_n564(x) + else + fun_l12_n129(x) + end +end + +def fun_l11_n805(x) + if (x < 1) + fun_l12_n234(x) + else + fun_l12_n429(x) + end +end + +def fun_l11_n806(x) + if (x < 1) + fun_l12_n841(x) + else + fun_l12_n705(x) + end +end + +def fun_l11_n807(x) + if (x < 1) + fun_l12_n72(x) + else + fun_l12_n87(x) + end +end + +def fun_l11_n808(x) + if (x < 1) + fun_l12_n131(x) + else + fun_l12_n27(x) + end +end + +def fun_l11_n809(x) + if (x < 1) + fun_l12_n136(x) + else + fun_l12_n84(x) + end +end + +def fun_l11_n810(x) + if (x < 1) + fun_l12_n464(x) + else + fun_l12_n411(x) + end +end + +def fun_l11_n811(x) + if (x < 1) + fun_l12_n939(x) + else + fun_l12_n584(x) + end +end + +def fun_l11_n812(x) + if (x < 1) + fun_l12_n24(x) + else + fun_l12_n593(x) + end +end + +def fun_l11_n813(x) + if (x < 1) + fun_l12_n980(x) + else + fun_l12_n318(x) + end +end + +def fun_l11_n814(x) + if (x < 1) + fun_l12_n73(x) + else + fun_l12_n431(x) + end +end + +def fun_l11_n815(x) + if (x < 1) + fun_l12_n938(x) + else + fun_l12_n794(x) + end +end + +def fun_l11_n816(x) + if (x < 1) + fun_l12_n305(x) + else + fun_l12_n620(x) + end +end + +def fun_l11_n817(x) + if (x < 1) + fun_l12_n881(x) + else + fun_l12_n636(x) + end +end + +def fun_l11_n818(x) + if (x < 1) + fun_l12_n493(x) + else + fun_l12_n536(x) + end +end + +def fun_l11_n819(x) + if (x < 1) + fun_l12_n32(x) + else + fun_l12_n69(x) + end +end + +def fun_l11_n820(x) + if (x < 1) + fun_l12_n131(x) + else + fun_l12_n206(x) + end +end + +def fun_l11_n821(x) + if (x < 1) + fun_l12_n130(x) + else + fun_l12_n63(x) + end +end + +def fun_l11_n822(x) + if (x < 1) + fun_l12_n228(x) + else + fun_l12_n753(x) + end +end + +def fun_l11_n823(x) + if (x < 1) + fun_l12_n171(x) + else + fun_l12_n605(x) + end +end + +def fun_l11_n824(x) + if (x < 1) + fun_l12_n69(x) + else + fun_l12_n900(x) + end +end + +def fun_l11_n825(x) + if (x < 1) + fun_l12_n802(x) + else + fun_l12_n682(x) + end +end + +def fun_l11_n826(x) + if (x < 1) + fun_l12_n311(x) + else + fun_l12_n257(x) + end +end + +def fun_l11_n827(x) + if (x < 1) + fun_l12_n994(x) + else + fun_l12_n162(x) + end +end + +def fun_l11_n828(x) + if (x < 1) + fun_l12_n780(x) + else + fun_l12_n805(x) + end +end + +def fun_l11_n829(x) + if (x < 1) + fun_l12_n744(x) + else + fun_l12_n55(x) + end +end + +def fun_l11_n830(x) + if (x < 1) + fun_l12_n655(x) + else + fun_l12_n603(x) + end +end + +def fun_l11_n831(x) + if (x < 1) + fun_l12_n245(x) + else + fun_l12_n196(x) + end +end + +def fun_l11_n832(x) + if (x < 1) + fun_l12_n381(x) + else + fun_l12_n582(x) + end +end + +def fun_l11_n833(x) + if (x < 1) + fun_l12_n185(x) + else + fun_l12_n339(x) + end +end + +def fun_l11_n834(x) + if (x < 1) + fun_l12_n601(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n835(x) + if (x < 1) + fun_l12_n934(x) + else + fun_l12_n460(x) + end +end + +def fun_l11_n836(x) + if (x < 1) + fun_l12_n550(x) + else + fun_l12_n55(x) + end +end + +def fun_l11_n837(x) + if (x < 1) + fun_l12_n183(x) + else + fun_l12_n880(x) + end +end + +def fun_l11_n838(x) + if (x < 1) + fun_l12_n742(x) + else + fun_l12_n249(x) + end +end + +def fun_l11_n839(x) + if (x < 1) + fun_l12_n979(x) + else + fun_l12_n100(x) + end +end + +def fun_l11_n840(x) + if (x < 1) + fun_l12_n889(x) + else + fun_l12_n683(x) + end +end + +def fun_l11_n841(x) + if (x < 1) + fun_l12_n964(x) + else + fun_l12_n0(x) + end +end + +def fun_l11_n842(x) + if (x < 1) + fun_l12_n461(x) + else + fun_l12_n126(x) + end +end + +def fun_l11_n843(x) + if (x < 1) + fun_l12_n839(x) + else + fun_l12_n554(x) + end +end + +def fun_l11_n844(x) + if (x < 1) + fun_l12_n150(x) + else + fun_l12_n857(x) + end +end + +def fun_l11_n845(x) + if (x < 1) + fun_l12_n114(x) + else + fun_l12_n72(x) + end +end + +def fun_l11_n846(x) + if (x < 1) + fun_l12_n953(x) + else + fun_l12_n695(x) + end +end + +def fun_l11_n847(x) + if (x < 1) + fun_l12_n16(x) + else + fun_l12_n216(x) + end +end + +def fun_l11_n848(x) + if (x < 1) + fun_l12_n440(x) + else + fun_l12_n893(x) + end +end + +def fun_l11_n849(x) + if (x < 1) + fun_l12_n176(x) + else + fun_l12_n932(x) + end +end + +def fun_l11_n850(x) + if (x < 1) + fun_l12_n723(x) + else + fun_l12_n363(x) + end +end + +def fun_l11_n851(x) + if (x < 1) + fun_l12_n779(x) + else + fun_l12_n774(x) + end +end + +def fun_l11_n852(x) + if (x < 1) + fun_l12_n618(x) + else + fun_l12_n252(x) + end +end + +def fun_l11_n853(x) + if (x < 1) + fun_l12_n298(x) + else + fun_l12_n563(x) + end +end + +def fun_l11_n854(x) + if (x < 1) + fun_l12_n972(x) + else + fun_l12_n681(x) + end +end + +def fun_l11_n855(x) + if (x < 1) + fun_l12_n412(x) + else + fun_l12_n932(x) + end +end + +def fun_l11_n856(x) + if (x < 1) + fun_l12_n132(x) + else + fun_l12_n699(x) + end +end + +def fun_l11_n857(x) + if (x < 1) + fun_l12_n208(x) + else + fun_l12_n602(x) + end +end + +def fun_l11_n858(x) + if (x < 1) + fun_l12_n705(x) + else + fun_l12_n833(x) + end +end + +def fun_l11_n859(x) + if (x < 1) + fun_l12_n408(x) + else + fun_l12_n570(x) + end +end + +def fun_l11_n860(x) + if (x < 1) + fun_l12_n720(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n861(x) + if (x < 1) + fun_l12_n926(x) + else + fun_l12_n490(x) + end +end + +def fun_l11_n862(x) + if (x < 1) + fun_l12_n985(x) + else + fun_l12_n54(x) + end +end + +def fun_l11_n863(x) + if (x < 1) + fun_l12_n214(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n864(x) + if (x < 1) + fun_l12_n351(x) + else + fun_l12_n951(x) + end +end + +def fun_l11_n865(x) + if (x < 1) + fun_l12_n514(x) + else + fun_l12_n468(x) + end +end + +def fun_l11_n866(x) + if (x < 1) + fun_l12_n793(x) + else + fun_l12_n712(x) + end +end + +def fun_l11_n867(x) + if (x < 1) + fun_l12_n697(x) + else + fun_l12_n824(x) + end +end + +def fun_l11_n868(x) + if (x < 1) + fun_l12_n144(x) + else + fun_l12_n703(x) + end +end + +def fun_l11_n869(x) + if (x < 1) + fun_l12_n552(x) + else + fun_l12_n612(x) + end +end + +def fun_l11_n870(x) + if (x < 1) + fun_l12_n2(x) + else + fun_l12_n287(x) + end +end + +def fun_l11_n871(x) + if (x < 1) + fun_l12_n604(x) + else + fun_l12_n260(x) + end +end + +def fun_l11_n872(x) + if (x < 1) + fun_l12_n517(x) + else + fun_l12_n173(x) + end +end + +def fun_l11_n873(x) + if (x < 1) + fun_l12_n640(x) + else + fun_l12_n196(x) + end +end + +def fun_l11_n874(x) + if (x < 1) + fun_l12_n874(x) + else + fun_l12_n697(x) + end +end + +def fun_l11_n875(x) + if (x < 1) + fun_l12_n180(x) + else + fun_l12_n652(x) + end +end + +def fun_l11_n876(x) + if (x < 1) + fun_l12_n432(x) + else + fun_l12_n971(x) + end +end + +def fun_l11_n877(x) + if (x < 1) + fun_l12_n111(x) + else + fun_l12_n919(x) + end +end + +def fun_l11_n878(x) + if (x < 1) + fun_l12_n631(x) + else + fun_l12_n439(x) + end +end + +def fun_l11_n879(x) + if (x < 1) + fun_l12_n39(x) + else + fun_l12_n372(x) + end +end + +def fun_l11_n880(x) + if (x < 1) + fun_l12_n675(x) + else + fun_l12_n64(x) + end +end + +def fun_l11_n881(x) + if (x < 1) + fun_l12_n831(x) + else + fun_l12_n705(x) + end +end + +def fun_l11_n882(x) + if (x < 1) + fun_l12_n126(x) + else + fun_l12_n648(x) + end +end + +def fun_l11_n883(x) + if (x < 1) + fun_l12_n768(x) + else + fun_l12_n483(x) + end +end + +def fun_l11_n884(x) + if (x < 1) + fun_l12_n328(x) + else + fun_l12_n646(x) + end +end + +def fun_l11_n885(x) + if (x < 1) + fun_l12_n890(x) + else + fun_l12_n544(x) + end +end + +def fun_l11_n886(x) + if (x < 1) + fun_l12_n651(x) + else + fun_l12_n557(x) + end +end + +def fun_l11_n887(x) + if (x < 1) + fun_l12_n479(x) + else + fun_l12_n594(x) + end +end + +def fun_l11_n888(x) + if (x < 1) + fun_l12_n649(x) + else + fun_l12_n488(x) + end +end + +def fun_l11_n889(x) + if (x < 1) + fun_l12_n347(x) + else + fun_l12_n42(x) + end +end + +def fun_l11_n890(x) + if (x < 1) + fun_l12_n111(x) + else + fun_l12_n683(x) + end +end + +def fun_l11_n891(x) + if (x < 1) + fun_l12_n965(x) + else + fun_l12_n275(x) + end +end + +def fun_l11_n892(x) + if (x < 1) + fun_l12_n148(x) + else + fun_l12_n541(x) + end +end + +def fun_l11_n893(x) + if (x < 1) + fun_l12_n633(x) + else + fun_l12_n358(x) + end +end + +def fun_l11_n894(x) + if (x < 1) + fun_l12_n681(x) + else + fun_l12_n236(x) + end +end + +def fun_l11_n895(x) + if (x < 1) + fun_l12_n292(x) + else + fun_l12_n417(x) + end +end + +def fun_l11_n896(x) + if (x < 1) + fun_l12_n165(x) + else + fun_l12_n80(x) + end +end + +def fun_l11_n897(x) + if (x < 1) + fun_l12_n132(x) + else + fun_l12_n659(x) + end +end + +def fun_l11_n898(x) + if (x < 1) + fun_l12_n329(x) + else + fun_l12_n204(x) + end +end + +def fun_l11_n899(x) + if (x < 1) + fun_l12_n339(x) + else + fun_l12_n632(x) + end +end + +def fun_l11_n900(x) + if (x < 1) + fun_l12_n957(x) + else + fun_l12_n282(x) + end +end + +def fun_l11_n901(x) + if (x < 1) + fun_l12_n709(x) + else + fun_l12_n155(x) + end +end + +def fun_l11_n902(x) + if (x < 1) + fun_l12_n227(x) + else + fun_l12_n659(x) + end +end + +def fun_l11_n903(x) + if (x < 1) + fun_l12_n224(x) + else + fun_l12_n23(x) + end +end + +def fun_l11_n904(x) + if (x < 1) + fun_l12_n494(x) + else + fun_l12_n292(x) + end +end + +def fun_l11_n905(x) + if (x < 1) + fun_l12_n309(x) + else + fun_l12_n949(x) + end +end + +def fun_l11_n906(x) + if (x < 1) + fun_l12_n960(x) + else + fun_l12_n24(x) + end +end + +def fun_l11_n907(x) + if (x < 1) + fun_l12_n98(x) + else + fun_l12_n674(x) + end +end + +def fun_l11_n908(x) + if (x < 1) + fun_l12_n84(x) + else + fun_l12_n307(x) + end +end + +def fun_l11_n909(x) + if (x < 1) + fun_l12_n786(x) + else + fun_l12_n311(x) + end +end + +def fun_l11_n910(x) + if (x < 1) + fun_l12_n631(x) + else + fun_l12_n605(x) + end +end + +def fun_l11_n911(x) + if (x < 1) + fun_l12_n352(x) + else + fun_l12_n750(x) + end +end + +def fun_l11_n912(x) + if (x < 1) + fun_l12_n75(x) + else + fun_l12_n112(x) + end +end + +def fun_l11_n913(x) + if (x < 1) + fun_l12_n404(x) + else + fun_l12_n995(x) + end +end + +def fun_l11_n914(x) + if (x < 1) + fun_l12_n656(x) + else + fun_l12_n203(x) + end +end + +def fun_l11_n915(x) + if (x < 1) + fun_l12_n625(x) + else + fun_l12_n32(x) + end +end + +def fun_l11_n916(x) + if (x < 1) + fun_l12_n785(x) + else + fun_l12_n237(x) + end +end + +def fun_l11_n917(x) + if (x < 1) + fun_l12_n643(x) + else + fun_l12_n364(x) + end +end + +def fun_l11_n918(x) + if (x < 1) + fun_l12_n920(x) + else + fun_l12_n957(x) + end +end + +def fun_l11_n919(x) + if (x < 1) + fun_l12_n336(x) + else + fun_l12_n726(x) + end +end + +def fun_l11_n920(x) + if (x < 1) + fun_l12_n329(x) + else + fun_l12_n15(x) + end +end + +def fun_l11_n921(x) + if (x < 1) + fun_l12_n911(x) + else + fun_l12_n824(x) + end +end + +def fun_l11_n922(x) + if (x < 1) + fun_l12_n907(x) + else + fun_l12_n854(x) + end +end + +def fun_l11_n923(x) + if (x < 1) + fun_l12_n779(x) + else + fun_l12_n549(x) + end +end + +def fun_l11_n924(x) + if (x < 1) + fun_l12_n833(x) + else + fun_l12_n986(x) + end +end + +def fun_l11_n925(x) + if (x < 1) + fun_l12_n450(x) + else + fun_l12_n783(x) + end +end + +def fun_l11_n926(x) + if (x < 1) + fun_l12_n405(x) + else + fun_l12_n960(x) + end +end + +def fun_l11_n927(x) + if (x < 1) + fun_l12_n603(x) + else + fun_l12_n892(x) + end +end + +def fun_l11_n928(x) + if (x < 1) + fun_l12_n137(x) + else + fun_l12_n200(x) + end +end + +def fun_l11_n929(x) + if (x < 1) + fun_l12_n161(x) + else + fun_l12_n754(x) + end +end + +def fun_l11_n930(x) + if (x < 1) + fun_l12_n107(x) + else + fun_l12_n258(x) + end +end + +def fun_l11_n931(x) + if (x < 1) + fun_l12_n794(x) + else + fun_l12_n812(x) + end +end + +def fun_l11_n932(x) + if (x < 1) + fun_l12_n956(x) + else + fun_l12_n156(x) + end +end + +def fun_l11_n933(x) + if (x < 1) + fun_l12_n676(x) + else + fun_l12_n496(x) + end +end + +def fun_l11_n934(x) + if (x < 1) + fun_l12_n229(x) + else + fun_l12_n339(x) + end +end + +def fun_l11_n935(x) + if (x < 1) + fun_l12_n353(x) + else + fun_l12_n430(x) + end +end + +def fun_l11_n936(x) + if (x < 1) + fun_l12_n721(x) + else + fun_l12_n409(x) + end +end + +def fun_l11_n937(x) + if (x < 1) + fun_l12_n151(x) + else + fun_l12_n60(x) + end +end + +def fun_l11_n938(x) + if (x < 1) + fun_l12_n362(x) + else + fun_l12_n92(x) + end +end + +def fun_l11_n939(x) + if (x < 1) + fun_l12_n315(x) + else + fun_l12_n905(x) + end +end + +def fun_l11_n940(x) + if (x < 1) + fun_l12_n788(x) + else + fun_l12_n105(x) + end +end + +def fun_l11_n941(x) + if (x < 1) + fun_l12_n124(x) + else + fun_l12_n496(x) + end +end + +def fun_l11_n942(x) + if (x < 1) + fun_l12_n546(x) + else + fun_l12_n17(x) + end +end + +def fun_l11_n943(x) + if (x < 1) + fun_l12_n594(x) + else + fun_l12_n55(x) + end +end + +def fun_l11_n944(x) + if (x < 1) + fun_l12_n187(x) + else + fun_l12_n139(x) + end +end + +def fun_l11_n945(x) + if (x < 1) + fun_l12_n117(x) + else + fun_l12_n382(x) + end +end + +def fun_l11_n946(x) + if (x < 1) + fun_l12_n579(x) + else + fun_l12_n895(x) + end +end + +def fun_l11_n947(x) + if (x < 1) + fun_l12_n541(x) + else + fun_l12_n497(x) + end +end + +def fun_l11_n948(x) + if (x < 1) + fun_l12_n250(x) + else + fun_l12_n257(x) + end +end + +def fun_l11_n949(x) + if (x < 1) + fun_l12_n553(x) + else + fun_l12_n663(x) + end +end + +def fun_l11_n950(x) + if (x < 1) + fun_l12_n779(x) + else + fun_l12_n414(x) + end +end + +def fun_l11_n951(x) + if (x < 1) + fun_l12_n748(x) + else + fun_l12_n525(x) + end +end + +def fun_l11_n952(x) + if (x < 1) + fun_l12_n669(x) + else + fun_l12_n339(x) + end +end + +def fun_l11_n953(x) + if (x < 1) + fun_l12_n665(x) + else + fun_l12_n996(x) + end +end + +def fun_l11_n954(x) + if (x < 1) + fun_l12_n366(x) + else + fun_l12_n149(x) + end +end + +def fun_l11_n955(x) + if (x < 1) + fun_l12_n549(x) + else + fun_l12_n414(x) + end +end + +def fun_l11_n956(x) + if (x < 1) + fun_l12_n258(x) + else + fun_l12_n67(x) + end +end + +def fun_l11_n957(x) + if (x < 1) + fun_l12_n439(x) + else + fun_l12_n83(x) + end +end + +def fun_l11_n958(x) + if (x < 1) + fun_l12_n601(x) + else + fun_l12_n938(x) + end +end + +def fun_l11_n959(x) + if (x < 1) + fun_l12_n953(x) + else + fun_l12_n973(x) + end +end + +def fun_l11_n960(x) + if (x < 1) + fun_l12_n426(x) + else + fun_l12_n8(x) + end +end + +def fun_l11_n961(x) + if (x < 1) + fun_l12_n719(x) + else + fun_l12_n657(x) + end +end + +def fun_l11_n962(x) + if (x < 1) + fun_l12_n391(x) + else + fun_l12_n992(x) + end +end + +def fun_l11_n963(x) + if (x < 1) + fun_l12_n141(x) + else + fun_l12_n468(x) + end +end + +def fun_l11_n964(x) + if (x < 1) + fun_l12_n463(x) + else + fun_l12_n94(x) + end +end + +def fun_l11_n965(x) + if (x < 1) + fun_l12_n765(x) + else + fun_l12_n168(x) + end +end + +def fun_l11_n966(x) + if (x < 1) + fun_l12_n237(x) + else + fun_l12_n437(x) + end +end + +def fun_l11_n967(x) + if (x < 1) + fun_l12_n741(x) + else + fun_l12_n331(x) + end +end + +def fun_l11_n968(x) + if (x < 1) + fun_l12_n617(x) + else + fun_l12_n773(x) + end +end + +def fun_l11_n969(x) + if (x < 1) + fun_l12_n880(x) + else + fun_l12_n727(x) + end +end + +def fun_l11_n970(x) + if (x < 1) + fun_l12_n781(x) + else + fun_l12_n270(x) + end +end + +def fun_l11_n971(x) + if (x < 1) + fun_l12_n511(x) + else + fun_l12_n183(x) + end +end + +def fun_l11_n972(x) + if (x < 1) + fun_l12_n448(x) + else + fun_l12_n965(x) + end +end + +def fun_l11_n973(x) + if (x < 1) + fun_l12_n816(x) + else + fun_l12_n974(x) + end +end + +def fun_l11_n974(x) + if (x < 1) + fun_l12_n583(x) + else + fun_l12_n731(x) + end +end + +def fun_l11_n975(x) + if (x < 1) + fun_l12_n42(x) + else + fun_l12_n463(x) + end +end + +def fun_l11_n976(x) + if (x < 1) + fun_l12_n267(x) + else + fun_l12_n769(x) + end +end + +def fun_l11_n977(x) + if (x < 1) + fun_l12_n993(x) + else + fun_l12_n391(x) + end +end + +def fun_l11_n978(x) + if (x < 1) + fun_l12_n507(x) + else + fun_l12_n905(x) + end +end + +def fun_l11_n979(x) + if (x < 1) + fun_l12_n486(x) + else + fun_l12_n562(x) + end +end + +def fun_l11_n980(x) + if (x < 1) + fun_l12_n252(x) + else + fun_l12_n475(x) + end +end + +def fun_l11_n981(x) + if (x < 1) + fun_l12_n979(x) + else + fun_l12_n70(x) + end +end + +def fun_l11_n982(x) + if (x < 1) + fun_l12_n11(x) + else + fun_l12_n483(x) + end +end + +def fun_l11_n983(x) + if (x < 1) + fun_l12_n208(x) + else + fun_l12_n315(x) + end +end + +def fun_l11_n984(x) + if (x < 1) + fun_l12_n452(x) + else + fun_l12_n367(x) + end +end + +def fun_l11_n985(x) + if (x < 1) + fun_l12_n937(x) + else + fun_l12_n33(x) + end +end + +def fun_l11_n986(x) + if (x < 1) + fun_l12_n227(x) + else + fun_l12_n448(x) + end +end + +def fun_l11_n987(x) + if (x < 1) + fun_l12_n928(x) + else + fun_l12_n693(x) + end +end + +def fun_l11_n988(x) + if (x < 1) + fun_l12_n731(x) + else + fun_l12_n872(x) + end +end + +def fun_l11_n989(x) + if (x < 1) + fun_l12_n355(x) + else + fun_l12_n0(x) + end +end + +def fun_l11_n990(x) + if (x < 1) + fun_l12_n203(x) + else + fun_l12_n545(x) + end +end + +def fun_l11_n991(x) + if (x < 1) + fun_l12_n237(x) + else + fun_l12_n186(x) + end +end + +def fun_l11_n992(x) + if (x < 1) + fun_l12_n22(x) + else + fun_l12_n597(x) + end +end + +def fun_l11_n993(x) + if (x < 1) + fun_l12_n711(x) + else + fun_l12_n677(x) + end +end + +def fun_l11_n994(x) + if (x < 1) + fun_l12_n892(x) + else + fun_l12_n729(x) + end +end + +def fun_l11_n995(x) + if (x < 1) + fun_l12_n51(x) + else + fun_l12_n279(x) + end +end + +def fun_l11_n996(x) + if (x < 1) + fun_l12_n430(x) + else + fun_l12_n527(x) + end +end + +def fun_l11_n997(x) + if (x < 1) + fun_l12_n153(x) + else + fun_l12_n366(x) + end +end + +def fun_l11_n998(x) + if (x < 1) + fun_l12_n574(x) + else + fun_l12_n432(x) + end +end + +def fun_l11_n999(x) + if (x < 1) + fun_l12_n100(x) + else + fun_l12_n943(x) + end +end + +def fun_l12_n0(x) + if (x < 1) + fun_l13_n874(x) + else + fun_l13_n769(x) + end +end + +def fun_l12_n1(x) + if (x < 1) + fun_l13_n354(x) + else + fun_l13_n103(x) + end +end + +def fun_l12_n2(x) + if (x < 1) + fun_l13_n265(x) + else + fun_l13_n936(x) + end +end + +def fun_l12_n3(x) + if (x < 1) + fun_l13_n683(x) + else + fun_l13_n607(x) + end +end + +def fun_l12_n4(x) + if (x < 1) + fun_l13_n398(x) + else + fun_l13_n902(x) + end +end + +def fun_l12_n5(x) + if (x < 1) + fun_l13_n694(x) + else + fun_l13_n392(x) + end +end + +def fun_l12_n6(x) + if (x < 1) + fun_l13_n170(x) + else + fun_l13_n207(x) + end +end + +def fun_l12_n7(x) + if (x < 1) + fun_l13_n978(x) + else + fun_l13_n368(x) + end +end + +def fun_l12_n8(x) + if (x < 1) + fun_l13_n970(x) + else + fun_l13_n560(x) + end +end + +def fun_l12_n9(x) + if (x < 1) + fun_l13_n56(x) + else + fun_l13_n697(x) + end +end + +def fun_l12_n10(x) + if (x < 1) + fun_l13_n860(x) + else + fun_l13_n407(x) + end +end + +def fun_l12_n11(x) + if (x < 1) + fun_l13_n581(x) + else + fun_l13_n582(x) + end +end + +def fun_l12_n12(x) + if (x < 1) + fun_l13_n835(x) + else + fun_l13_n706(x) + end +end + +def fun_l12_n13(x) + if (x < 1) + fun_l13_n862(x) + else + fun_l13_n89(x) + end +end + +def fun_l12_n14(x) + if (x < 1) + fun_l13_n379(x) + else + fun_l13_n896(x) + end +end + +def fun_l12_n15(x) + if (x < 1) + fun_l13_n175(x) + else + fun_l13_n113(x) + end +end + +def fun_l12_n16(x) + if (x < 1) + fun_l13_n553(x) + else + fun_l13_n935(x) + end +end + +def fun_l12_n17(x) + if (x < 1) + fun_l13_n171(x) + else + fun_l13_n264(x) + end +end + +def fun_l12_n18(x) + if (x < 1) + fun_l13_n61(x) + else + fun_l13_n412(x) + end +end + +def fun_l12_n19(x) + if (x < 1) + fun_l13_n213(x) + else + fun_l13_n422(x) + end +end + +def fun_l12_n20(x) + if (x < 1) + fun_l13_n401(x) + else + fun_l13_n537(x) + end +end + +def fun_l12_n21(x) + if (x < 1) + fun_l13_n207(x) + else + fun_l13_n495(x) + end +end + +def fun_l12_n22(x) + if (x < 1) + fun_l13_n941(x) + else + fun_l13_n466(x) + end +end + +def fun_l12_n23(x) + if (x < 1) + fun_l13_n195(x) + else + fun_l13_n984(x) + end +end + +def fun_l12_n24(x) + if (x < 1) + fun_l13_n106(x) + else + fun_l13_n812(x) + end +end + +def fun_l12_n25(x) + if (x < 1) + fun_l13_n979(x) + else + fun_l13_n902(x) + end +end + +def fun_l12_n26(x) + if (x < 1) + fun_l13_n726(x) + else + fun_l13_n440(x) + end +end + +def fun_l12_n27(x) + if (x < 1) + fun_l13_n229(x) + else + fun_l13_n995(x) + end +end + +def fun_l12_n28(x) + if (x < 1) + fun_l13_n764(x) + else + fun_l13_n333(x) + end +end + +def fun_l12_n29(x) + if (x < 1) + fun_l13_n971(x) + else + fun_l13_n59(x) + end +end + +def fun_l12_n30(x) + if (x < 1) + fun_l13_n731(x) + else + fun_l13_n138(x) + end +end + +def fun_l12_n31(x) + if (x < 1) + fun_l13_n591(x) + else + fun_l13_n473(x) + end +end + +def fun_l12_n32(x) + if (x < 1) + fun_l13_n50(x) + else + fun_l13_n175(x) + end +end + +def fun_l12_n33(x) + if (x < 1) + fun_l13_n26(x) + else + fun_l13_n867(x) + end +end + +def fun_l12_n34(x) + if (x < 1) + fun_l13_n349(x) + else + fun_l13_n332(x) + end +end + +def fun_l12_n35(x) + if (x < 1) + fun_l13_n180(x) + else + fun_l13_n591(x) + end +end + +def fun_l12_n36(x) + if (x < 1) + fun_l13_n339(x) + else + fun_l13_n354(x) + end +end + +def fun_l12_n37(x) + if (x < 1) + fun_l13_n289(x) + else + fun_l13_n101(x) + end +end + +def fun_l12_n38(x) + if (x < 1) + fun_l13_n410(x) + else + fun_l13_n91(x) + end +end + +def fun_l12_n39(x) + if (x < 1) + fun_l13_n617(x) + else + fun_l13_n716(x) + end +end + +def fun_l12_n40(x) + if (x < 1) + fun_l13_n116(x) + else + fun_l13_n875(x) + end +end + +def fun_l12_n41(x) + if (x < 1) + fun_l13_n162(x) + else + fun_l13_n844(x) + end +end + +def fun_l12_n42(x) + if (x < 1) + fun_l13_n79(x) + else + fun_l13_n589(x) + end +end + +def fun_l12_n43(x) + if (x < 1) + fun_l13_n835(x) + else + fun_l13_n21(x) + end +end + +def fun_l12_n44(x) + if (x < 1) + fun_l13_n420(x) + else + fun_l13_n403(x) + end +end + +def fun_l12_n45(x) + if (x < 1) + fun_l13_n203(x) + else + fun_l13_n890(x) + end +end + +def fun_l12_n46(x) + if (x < 1) + fun_l13_n529(x) + else + fun_l13_n717(x) + end +end + +def fun_l12_n47(x) + if (x < 1) + fun_l13_n766(x) + else + fun_l13_n635(x) + end +end + +def fun_l12_n48(x) + if (x < 1) + fun_l13_n223(x) + else + fun_l13_n460(x) + end +end + +def fun_l12_n49(x) + if (x < 1) + fun_l13_n799(x) + else + fun_l13_n397(x) + end +end + +def fun_l12_n50(x) + if (x < 1) + fun_l13_n200(x) + else + fun_l13_n608(x) + end +end + +def fun_l12_n51(x) + if (x < 1) + fun_l13_n212(x) + else + fun_l13_n612(x) + end +end + +def fun_l12_n52(x) + if (x < 1) + fun_l13_n271(x) + else + fun_l13_n324(x) + end +end + +def fun_l12_n53(x) + if (x < 1) + fun_l13_n639(x) + else + fun_l13_n603(x) + end +end + +def fun_l12_n54(x) + if (x < 1) + fun_l13_n125(x) + else + fun_l13_n726(x) + end +end + +def fun_l12_n55(x) + if (x < 1) + fun_l13_n266(x) + else + fun_l13_n552(x) + end +end + +def fun_l12_n56(x) + if (x < 1) + fun_l13_n412(x) + else + fun_l13_n132(x) + end +end + +def fun_l12_n57(x) + if (x < 1) + fun_l13_n235(x) + else + fun_l13_n892(x) + end +end + +def fun_l12_n58(x) + if (x < 1) + fun_l13_n515(x) + else + fun_l13_n465(x) + end +end + +def fun_l12_n59(x) + if (x < 1) + fun_l13_n38(x) + else + fun_l13_n757(x) + end +end + +def fun_l12_n60(x) + if (x < 1) + fun_l13_n544(x) + else + fun_l13_n794(x) + end +end + +def fun_l12_n61(x) + if (x < 1) + fun_l13_n622(x) + else + fun_l13_n340(x) + end +end + +def fun_l12_n62(x) + if (x < 1) + fun_l13_n563(x) + else + fun_l13_n313(x) + end +end + +def fun_l12_n63(x) + if (x < 1) + fun_l13_n936(x) + else + fun_l13_n38(x) + end +end + +def fun_l12_n64(x) + if (x < 1) + fun_l13_n951(x) + else + fun_l13_n543(x) + end +end + +def fun_l12_n65(x) + if (x < 1) + fun_l13_n577(x) + else + fun_l13_n190(x) + end +end + +def fun_l12_n66(x) + if (x < 1) + fun_l13_n649(x) + else + fun_l13_n887(x) + end +end + +def fun_l12_n67(x) + if (x < 1) + fun_l13_n218(x) + else + fun_l13_n200(x) + end +end + +def fun_l12_n68(x) + if (x < 1) + fun_l13_n111(x) + else + fun_l13_n849(x) + end +end + +def fun_l12_n69(x) + if (x < 1) + fun_l13_n431(x) + else + fun_l13_n816(x) + end +end + +def fun_l12_n70(x) + if (x < 1) + fun_l13_n970(x) + else + fun_l13_n545(x) + end +end + +def fun_l12_n71(x) + if (x < 1) + fun_l13_n3(x) + else + fun_l13_n751(x) + end +end + +def fun_l12_n72(x) + if (x < 1) + fun_l13_n58(x) + else + fun_l13_n994(x) + end +end + +def fun_l12_n73(x) + if (x < 1) + fun_l13_n397(x) + else + fun_l13_n783(x) + end +end + +def fun_l12_n74(x) + if (x < 1) + fun_l13_n705(x) + else + fun_l13_n318(x) + end +end + +def fun_l12_n75(x) + if (x < 1) + fun_l13_n406(x) + else + fun_l13_n880(x) + end +end + +def fun_l12_n76(x) + if (x < 1) + fun_l13_n867(x) + else + fun_l13_n234(x) + end +end + +def fun_l12_n77(x) + if (x < 1) + fun_l13_n447(x) + else + fun_l13_n617(x) + end +end + +def fun_l12_n78(x) + if (x < 1) + fun_l13_n631(x) + else + fun_l13_n687(x) + end +end + +def fun_l12_n79(x) + if (x < 1) + fun_l13_n735(x) + else + fun_l13_n512(x) + end +end + +def fun_l12_n80(x) + if (x < 1) + fun_l13_n826(x) + else + fun_l13_n626(x) + end +end + +def fun_l12_n81(x) + if (x < 1) + fun_l13_n959(x) + else + fun_l13_n357(x) + end +end + +def fun_l12_n82(x) + if (x < 1) + fun_l13_n17(x) + else + fun_l13_n722(x) + end +end + +def fun_l12_n83(x) + if (x < 1) + fun_l13_n702(x) + else + fun_l13_n441(x) + end +end + +def fun_l12_n84(x) + if (x < 1) + fun_l13_n939(x) + else + fun_l13_n972(x) + end +end + +def fun_l12_n85(x) + if (x < 1) + fun_l13_n747(x) + else + fun_l13_n481(x) + end +end + +def fun_l12_n86(x) + if (x < 1) + fun_l13_n813(x) + else + fun_l13_n780(x) + end +end + +def fun_l12_n87(x) + if (x < 1) + fun_l13_n87(x) + else + fun_l13_n19(x) + end +end + +def fun_l12_n88(x) + if (x < 1) + fun_l13_n422(x) + else + fun_l13_n938(x) + end +end + +def fun_l12_n89(x) + if (x < 1) + fun_l13_n575(x) + else + fun_l13_n150(x) + end +end + +def fun_l12_n90(x) + if (x < 1) + fun_l13_n294(x) + else + fun_l13_n666(x) + end +end + +def fun_l12_n91(x) + if (x < 1) + fun_l13_n216(x) + else + fun_l13_n315(x) + end +end + +def fun_l12_n92(x) + if (x < 1) + fun_l13_n580(x) + else + fun_l13_n487(x) + end +end + +def fun_l12_n93(x) + if (x < 1) + fun_l13_n500(x) + else + fun_l13_n2(x) + end +end + +def fun_l12_n94(x) + if (x < 1) + fun_l13_n362(x) + else + fun_l13_n69(x) + end +end + +def fun_l12_n95(x) + if (x < 1) + fun_l13_n50(x) + else + fun_l13_n549(x) + end +end + +def fun_l12_n96(x) + if (x < 1) + fun_l13_n407(x) + else + fun_l13_n935(x) + end +end + +def fun_l12_n97(x) + if (x < 1) + fun_l13_n715(x) + else + fun_l13_n70(x) + end +end + +def fun_l12_n98(x) + if (x < 1) + fun_l13_n184(x) + else + fun_l13_n702(x) + end +end + +def fun_l12_n99(x) + if (x < 1) + fun_l13_n612(x) + else + fun_l13_n972(x) + end +end + +def fun_l12_n100(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n458(x) + end +end + +def fun_l12_n101(x) + if (x < 1) + fun_l13_n387(x) + else + fun_l13_n783(x) + end +end + +def fun_l12_n102(x) + if (x < 1) + fun_l13_n764(x) + else + fun_l13_n647(x) + end +end + +def fun_l12_n103(x) + if (x < 1) + fun_l13_n310(x) + else + fun_l13_n46(x) + end +end + +def fun_l12_n104(x) + if (x < 1) + fun_l13_n643(x) + else + fun_l13_n479(x) + end +end + +def fun_l12_n105(x) + if (x < 1) + fun_l13_n909(x) + else + fun_l13_n10(x) + end +end + +def fun_l12_n106(x) + if (x < 1) + fun_l13_n181(x) + else + fun_l13_n671(x) + end +end + +def fun_l12_n107(x) + if (x < 1) + fun_l13_n592(x) + else + fun_l13_n421(x) + end +end + +def fun_l12_n108(x) + if (x < 1) + fun_l13_n438(x) + else + fun_l13_n196(x) + end +end + +def fun_l12_n109(x) + if (x < 1) + fun_l13_n605(x) + else + fun_l13_n529(x) + end +end + +def fun_l12_n110(x) + if (x < 1) + fun_l13_n31(x) + else + fun_l13_n769(x) + end +end + +def fun_l12_n111(x) + if (x < 1) + fun_l13_n790(x) + else + fun_l13_n773(x) + end +end + +def fun_l12_n112(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n621(x) + end +end + +def fun_l12_n113(x) + if (x < 1) + fun_l13_n892(x) + else + fun_l13_n413(x) + end +end + +def fun_l12_n114(x) + if (x < 1) + fun_l13_n675(x) + else + fun_l13_n124(x) + end +end + +def fun_l12_n115(x) + if (x < 1) + fun_l13_n366(x) + else + fun_l13_n884(x) + end +end + +def fun_l12_n116(x) + if (x < 1) + fun_l13_n552(x) + else + fun_l13_n769(x) + end +end + +def fun_l12_n117(x) + if (x < 1) + fun_l13_n11(x) + else + fun_l13_n46(x) + end +end + +def fun_l12_n118(x) + if (x < 1) + fun_l13_n766(x) + else + fun_l13_n914(x) + end +end + +def fun_l12_n119(x) + if (x < 1) + fun_l13_n980(x) + else + fun_l13_n956(x) + end +end + +def fun_l12_n120(x) + if (x < 1) + fun_l13_n668(x) + else + fun_l13_n532(x) + end +end + +def fun_l12_n121(x) + if (x < 1) + fun_l13_n864(x) + else + fun_l13_n489(x) + end +end + +def fun_l12_n122(x) + if (x < 1) + fun_l13_n581(x) + else + fun_l13_n33(x) + end +end + +def fun_l12_n123(x) + if (x < 1) + fun_l13_n188(x) + else + fun_l13_n652(x) + end +end + +def fun_l12_n124(x) + if (x < 1) + fun_l13_n631(x) + else + fun_l13_n932(x) + end +end + +def fun_l12_n125(x) + if (x < 1) + fun_l13_n646(x) + else + fun_l13_n525(x) + end +end + +def fun_l12_n126(x) + if (x < 1) + fun_l13_n878(x) + else + fun_l13_n98(x) + end +end + +def fun_l12_n127(x) + if (x < 1) + fun_l13_n120(x) + else + fun_l13_n950(x) + end +end + +def fun_l12_n128(x) + if (x < 1) + fun_l13_n405(x) + else + fun_l13_n60(x) + end +end + +def fun_l12_n129(x) + if (x < 1) + fun_l13_n635(x) + else + fun_l13_n992(x) + end +end + +def fun_l12_n130(x) + if (x < 1) + fun_l13_n711(x) + else + fun_l13_n172(x) + end +end + +def fun_l12_n131(x) + if (x < 1) + fun_l13_n2(x) + else + fun_l13_n328(x) + end +end + +def fun_l12_n132(x) + if (x < 1) + fun_l13_n506(x) + else + fun_l13_n258(x) + end +end + +def fun_l12_n133(x) + if (x < 1) + fun_l13_n737(x) + else + fun_l13_n552(x) + end +end + +def fun_l12_n134(x) + if (x < 1) + fun_l13_n596(x) + else + fun_l13_n475(x) + end +end + +def fun_l12_n135(x) + if (x < 1) + fun_l13_n751(x) + else + fun_l13_n610(x) + end +end + +def fun_l12_n136(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n719(x) + end +end + +def fun_l12_n137(x) + if (x < 1) + fun_l13_n779(x) + else + fun_l13_n204(x) + end +end + +def fun_l12_n138(x) + if (x < 1) + fun_l13_n765(x) + else + fun_l13_n280(x) + end +end + +def fun_l12_n139(x) + if (x < 1) + fun_l13_n896(x) + else + fun_l13_n558(x) + end +end + +def fun_l12_n140(x) + if (x < 1) + fun_l13_n16(x) + else + fun_l13_n809(x) + end +end + +def fun_l12_n141(x) + if (x < 1) + fun_l13_n182(x) + else + fun_l13_n960(x) + end +end + +def fun_l12_n142(x) + if (x < 1) + fun_l13_n196(x) + else + fun_l13_n794(x) + end +end + +def fun_l12_n143(x) + if (x < 1) + fun_l13_n993(x) + else + fun_l13_n426(x) + end +end + +def fun_l12_n144(x) + if (x < 1) + fun_l13_n926(x) + else + fun_l13_n554(x) + end +end + +def fun_l12_n145(x) + if (x < 1) + fun_l13_n839(x) + else + fun_l13_n987(x) + end +end + +def fun_l12_n146(x) + if (x < 1) + fun_l13_n412(x) + else + fun_l13_n359(x) + end +end + +def fun_l12_n147(x) + if (x < 1) + fun_l13_n147(x) + else + fun_l13_n640(x) + end +end + +def fun_l12_n148(x) + if (x < 1) + fun_l13_n831(x) + else + fun_l13_n862(x) + end +end + +def fun_l12_n149(x) + if (x < 1) + fun_l13_n161(x) + else + fun_l13_n396(x) + end +end + +def fun_l12_n150(x) + if (x < 1) + fun_l13_n734(x) + else + fun_l13_n226(x) + end +end + +def fun_l12_n151(x) + if (x < 1) + fun_l13_n390(x) + else + fun_l13_n396(x) + end +end + +def fun_l12_n152(x) + if (x < 1) + fun_l13_n722(x) + else + fun_l13_n939(x) + end +end + +def fun_l12_n153(x) + if (x < 1) + fun_l13_n554(x) + else + fun_l13_n461(x) + end +end + +def fun_l12_n154(x) + if (x < 1) + fun_l13_n223(x) + else + fun_l13_n502(x) + end +end + +def fun_l12_n155(x) + if (x < 1) + fun_l13_n526(x) + else + fun_l13_n949(x) + end +end + +def fun_l12_n156(x) + if (x < 1) + fun_l13_n764(x) + else + fun_l13_n290(x) + end +end + +def fun_l12_n157(x) + if (x < 1) + fun_l13_n904(x) + else + fun_l13_n562(x) + end +end + +def fun_l12_n158(x) + if (x < 1) + fun_l13_n308(x) + else + fun_l13_n646(x) + end +end + +def fun_l12_n159(x) + if (x < 1) + fun_l13_n417(x) + else + fun_l13_n576(x) + end +end + +def fun_l12_n160(x) + if (x < 1) + fun_l13_n846(x) + else + fun_l13_n989(x) + end +end + +def fun_l12_n161(x) + if (x < 1) + fun_l13_n59(x) + else + fun_l13_n877(x) + end +end + +def fun_l12_n162(x) + if (x < 1) + fun_l13_n194(x) + else + fun_l13_n654(x) + end +end + +def fun_l12_n163(x) + if (x < 1) + fun_l13_n350(x) + else + fun_l13_n412(x) + end +end + +def fun_l12_n164(x) + if (x < 1) + fun_l13_n482(x) + else + fun_l13_n820(x) + end +end + +def fun_l12_n165(x) + if (x < 1) + fun_l13_n251(x) + else + fun_l13_n421(x) + end +end + +def fun_l12_n166(x) + if (x < 1) + fun_l13_n832(x) + else + fun_l13_n505(x) + end +end + +def fun_l12_n167(x) + if (x < 1) + fun_l13_n316(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n168(x) + if (x < 1) + fun_l13_n325(x) + else + fun_l13_n755(x) + end +end + +def fun_l12_n169(x) + if (x < 1) + fun_l13_n536(x) + else + fun_l13_n753(x) + end +end + +def fun_l12_n170(x) + if (x < 1) + fun_l13_n819(x) + else + fun_l13_n532(x) + end +end + +def fun_l12_n171(x) + if (x < 1) + fun_l13_n633(x) + else + fun_l13_n96(x) + end +end + +def fun_l12_n172(x) + if (x < 1) + fun_l13_n229(x) + else + fun_l13_n105(x) + end +end + +def fun_l12_n173(x) + if (x < 1) + fun_l13_n796(x) + else + fun_l13_n466(x) + end +end + +def fun_l12_n174(x) + if (x < 1) + fun_l13_n520(x) + else + fun_l13_n329(x) + end +end + +def fun_l12_n175(x) + if (x < 1) + fun_l13_n358(x) + else + fun_l13_n201(x) + end +end + +def fun_l12_n176(x) + if (x < 1) + fun_l13_n42(x) + else + fun_l13_n649(x) + end +end + +def fun_l12_n177(x) + if (x < 1) + fun_l13_n933(x) + else + fun_l13_n719(x) + end +end + +def fun_l12_n178(x) + if (x < 1) + fun_l13_n236(x) + else + fun_l13_n723(x) + end +end + +def fun_l12_n179(x) + if (x < 1) + fun_l13_n992(x) + else + fun_l13_n436(x) + end +end + +def fun_l12_n180(x) + if (x < 1) + fun_l13_n221(x) + else + fun_l13_n294(x) + end +end + +def fun_l12_n181(x) + if (x < 1) + fun_l13_n580(x) + else + fun_l13_n939(x) + end +end + +def fun_l12_n182(x) + if (x < 1) + fun_l13_n608(x) + else + fun_l13_n709(x) + end +end + +def fun_l12_n183(x) + if (x < 1) + fun_l13_n644(x) + else + fun_l13_n717(x) + end +end + +def fun_l12_n184(x) + if (x < 1) + fun_l13_n605(x) + else + fun_l13_n665(x) + end +end + +def fun_l12_n185(x) + if (x < 1) + fun_l13_n729(x) + else + fun_l13_n876(x) + end +end + +def fun_l12_n186(x) + if (x < 1) + fun_l13_n43(x) + else + fun_l13_n366(x) + end +end + +def fun_l12_n187(x) + if (x < 1) + fun_l13_n401(x) + else + fun_l13_n610(x) + end +end + +def fun_l12_n188(x) + if (x < 1) + fun_l13_n489(x) + else + fun_l13_n107(x) + end +end + +def fun_l12_n189(x) + if (x < 1) + fun_l13_n859(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n190(x) + if (x < 1) + fun_l13_n631(x) + else + fun_l13_n399(x) + end +end + +def fun_l12_n191(x) + if (x < 1) + fun_l13_n332(x) + else + fun_l13_n333(x) + end +end + +def fun_l12_n192(x) + if (x < 1) + fun_l13_n535(x) + else + fun_l13_n191(x) + end +end + +def fun_l12_n193(x) + if (x < 1) + fun_l13_n157(x) + else + fun_l13_n927(x) + end +end + +def fun_l12_n194(x) + if (x < 1) + fun_l13_n733(x) + else + fun_l13_n798(x) + end +end + +def fun_l12_n195(x) + if (x < 1) + fun_l13_n31(x) + else + fun_l13_n703(x) + end +end + +def fun_l12_n196(x) + if (x < 1) + fun_l13_n976(x) + else + fun_l13_n862(x) + end +end + +def fun_l12_n197(x) + if (x < 1) + fun_l13_n267(x) + else + fun_l13_n803(x) + end +end + +def fun_l12_n198(x) + if (x < 1) + fun_l13_n598(x) + else + fun_l13_n255(x) + end +end + +def fun_l12_n199(x) + if (x < 1) + fun_l13_n566(x) + else + fun_l13_n668(x) + end +end + +def fun_l12_n200(x) + if (x < 1) + fun_l13_n48(x) + else + fun_l13_n406(x) + end +end + +def fun_l12_n201(x) + if (x < 1) + fun_l13_n971(x) + else + fun_l13_n225(x) + end +end + +def fun_l12_n202(x) + if (x < 1) + fun_l13_n120(x) + else + fun_l13_n72(x) + end +end + +def fun_l12_n203(x) + if (x < 1) + fun_l13_n333(x) + else + fun_l13_n381(x) + end +end + +def fun_l12_n204(x) + if (x < 1) + fun_l13_n558(x) + else + fun_l13_n474(x) + end +end + +def fun_l12_n205(x) + if (x < 1) + fun_l13_n796(x) + else + fun_l13_n420(x) + end +end + +def fun_l12_n206(x) + if (x < 1) + fun_l13_n287(x) + else + fun_l13_n43(x) + end +end + +def fun_l12_n207(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n560(x) + end +end + +def fun_l12_n208(x) + if (x < 1) + fun_l13_n707(x) + else + fun_l13_n824(x) + end +end + +def fun_l12_n209(x) + if (x < 1) + fun_l13_n788(x) + else + fun_l13_n625(x) + end +end + +def fun_l12_n210(x) + if (x < 1) + fun_l13_n818(x) + else + fun_l13_n667(x) + end +end + +def fun_l12_n211(x) + if (x < 1) + fun_l13_n710(x) + else + fun_l13_n508(x) + end +end + +def fun_l12_n212(x) + if (x < 1) + fun_l13_n497(x) + else + fun_l13_n20(x) + end +end + +def fun_l12_n213(x) + if (x < 1) + fun_l13_n648(x) + else + fun_l13_n33(x) + end +end + +def fun_l12_n214(x) + if (x < 1) + fun_l13_n404(x) + else + fun_l13_n918(x) + end +end + +def fun_l12_n215(x) + if (x < 1) + fun_l13_n595(x) + else + fun_l13_n440(x) + end +end + +def fun_l12_n216(x) + if (x < 1) + fun_l13_n302(x) + else + fun_l13_n388(x) + end +end + +def fun_l12_n217(x) + if (x < 1) + fun_l13_n301(x) + else + fun_l13_n416(x) + end +end + +def fun_l12_n218(x) + if (x < 1) + fun_l13_n114(x) + else + fun_l13_n650(x) + end +end + +def fun_l12_n219(x) + if (x < 1) + fun_l13_n221(x) + else + fun_l13_n539(x) + end +end + +def fun_l12_n220(x) + if (x < 1) + fun_l13_n529(x) + else + fun_l13_n438(x) + end +end + +def fun_l12_n221(x) + if (x < 1) + fun_l13_n528(x) + else + fun_l13_n284(x) + end +end + +def fun_l12_n222(x) + if (x < 1) + fun_l13_n746(x) + else + fun_l13_n634(x) + end +end + +def fun_l12_n223(x) + if (x < 1) + fun_l13_n726(x) + else + fun_l13_n142(x) + end +end + +def fun_l12_n224(x) + if (x < 1) + fun_l13_n57(x) + else + fun_l13_n625(x) + end +end + +def fun_l12_n225(x) + if (x < 1) + fun_l13_n739(x) + else + fun_l13_n667(x) + end +end + +def fun_l12_n226(x) + if (x < 1) + fun_l13_n693(x) + else + fun_l13_n819(x) + end +end + +def fun_l12_n227(x) + if (x < 1) + fun_l13_n316(x) + else + fun_l13_n866(x) + end +end + +def fun_l12_n228(x) + if (x < 1) + fun_l13_n88(x) + else + fun_l13_n336(x) + end +end + +def fun_l12_n229(x) + if (x < 1) + fun_l13_n387(x) + else + fun_l13_n226(x) + end +end + +def fun_l12_n230(x) + if (x < 1) + fun_l13_n644(x) + else + fun_l13_n933(x) + end +end + +def fun_l12_n231(x) + if (x < 1) + fun_l13_n952(x) + else + fun_l13_n747(x) + end +end + +def fun_l12_n232(x) + if (x < 1) + fun_l13_n107(x) + else + fun_l13_n0(x) + end +end + +def fun_l12_n233(x) + if (x < 1) + fun_l13_n589(x) + else + fun_l13_n712(x) + end +end + +def fun_l12_n234(x) + if (x < 1) + fun_l13_n429(x) + else + fun_l13_n845(x) + end +end + +def fun_l12_n235(x) + if (x < 1) + fun_l13_n733(x) + else + fun_l13_n203(x) + end +end + +def fun_l12_n236(x) + if (x < 1) + fun_l13_n842(x) + else + fun_l13_n134(x) + end +end + +def fun_l12_n237(x) + if (x < 1) + fun_l13_n114(x) + else + fun_l13_n794(x) + end +end + +def fun_l12_n238(x) + if (x < 1) + fun_l13_n463(x) + else + fun_l13_n127(x) + end +end + +def fun_l12_n239(x) + if (x < 1) + fun_l13_n443(x) + else + fun_l13_n13(x) + end +end + +def fun_l12_n240(x) + if (x < 1) + fun_l13_n713(x) + else + fun_l13_n447(x) + end +end + +def fun_l12_n241(x) + if (x < 1) + fun_l13_n404(x) + else + fun_l13_n796(x) + end +end + +def fun_l12_n242(x) + if (x < 1) + fun_l13_n277(x) + else + fun_l13_n106(x) + end +end + +def fun_l12_n243(x) + if (x < 1) + fun_l13_n584(x) + else + fun_l13_n262(x) + end +end + +def fun_l12_n244(x) + if (x < 1) + fun_l13_n670(x) + else + fun_l13_n989(x) + end +end + +def fun_l12_n245(x) + if (x < 1) + fun_l13_n588(x) + else + fun_l13_n513(x) + end +end + +def fun_l12_n246(x) + if (x < 1) + fun_l13_n98(x) + else + fun_l13_n400(x) + end +end + +def fun_l12_n247(x) + if (x < 1) + fun_l13_n119(x) + else + fun_l13_n321(x) + end +end + +def fun_l12_n248(x) + if (x < 1) + fun_l13_n157(x) + else + fun_l13_n557(x) + end +end + +def fun_l12_n249(x) + if (x < 1) + fun_l13_n243(x) + else + fun_l13_n596(x) + end +end + +def fun_l12_n250(x) + if (x < 1) + fun_l13_n280(x) + else + fun_l13_n779(x) + end +end + +def fun_l12_n251(x) + if (x < 1) + fun_l13_n437(x) + else + fun_l13_n829(x) + end +end + +def fun_l12_n252(x) + if (x < 1) + fun_l13_n472(x) + else + fun_l13_n224(x) + end +end + +def fun_l12_n253(x) + if (x < 1) + fun_l13_n151(x) + else + fun_l13_n168(x) + end +end + +def fun_l12_n254(x) + if (x < 1) + fun_l13_n724(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n255(x) + if (x < 1) + fun_l13_n27(x) + else + fun_l13_n776(x) + end +end + +def fun_l12_n256(x) + if (x < 1) + fun_l13_n116(x) + else + fun_l13_n52(x) + end +end + +def fun_l12_n257(x) + if (x < 1) + fun_l13_n201(x) + else + fun_l13_n982(x) + end +end + +def fun_l12_n258(x) + if (x < 1) + fun_l13_n152(x) + else + fun_l13_n818(x) + end +end + +def fun_l12_n259(x) + if (x < 1) + fun_l13_n859(x) + else + fun_l13_n555(x) + end +end + +def fun_l12_n260(x) + if (x < 1) + fun_l13_n29(x) + else + fun_l13_n416(x) + end +end + +def fun_l12_n261(x) + if (x < 1) + fun_l13_n811(x) + else + fun_l13_n827(x) + end +end + +def fun_l12_n262(x) + if (x < 1) + fun_l13_n867(x) + else + fun_l13_n298(x) + end +end + +def fun_l12_n263(x) + if (x < 1) + fun_l13_n464(x) + else + fun_l13_n420(x) + end +end + +def fun_l12_n264(x) + if (x < 1) + fun_l13_n494(x) + else + fun_l13_n368(x) + end +end + +def fun_l12_n265(x) + if (x < 1) + fun_l13_n959(x) + else + fun_l13_n425(x) + end +end + +def fun_l12_n266(x) + if (x < 1) + fun_l13_n841(x) + else + fun_l13_n874(x) + end +end + +def fun_l12_n267(x) + if (x < 1) + fun_l13_n885(x) + else + fun_l13_n631(x) + end +end + +def fun_l12_n268(x) + if (x < 1) + fun_l13_n645(x) + else + fun_l13_n342(x) + end +end + +def fun_l12_n269(x) + if (x < 1) + fun_l13_n4(x) + else + fun_l13_n81(x) + end +end + +def fun_l12_n270(x) + if (x < 1) + fun_l13_n44(x) + else + fun_l13_n924(x) + end +end + +def fun_l12_n271(x) + if (x < 1) + fun_l13_n955(x) + else + fun_l13_n834(x) + end +end + +def fun_l12_n272(x) + if (x < 1) + fun_l13_n969(x) + else + fun_l13_n699(x) + end +end + +def fun_l12_n273(x) + if (x < 1) + fun_l13_n590(x) + else + fun_l13_n608(x) + end +end + +def fun_l12_n274(x) + if (x < 1) + fun_l13_n170(x) + else + fun_l13_n343(x) + end +end + +def fun_l12_n275(x) + if (x < 1) + fun_l13_n317(x) + else + fun_l13_n998(x) + end +end + +def fun_l12_n276(x) + if (x < 1) + fun_l13_n864(x) + else + fun_l13_n644(x) + end +end + +def fun_l12_n277(x) + if (x < 1) + fun_l13_n42(x) + else + fun_l13_n663(x) + end +end + +def fun_l12_n278(x) + if (x < 1) + fun_l13_n39(x) + else + fun_l13_n624(x) + end +end + +def fun_l12_n279(x) + if (x < 1) + fun_l13_n578(x) + else + fun_l13_n592(x) + end +end + +def fun_l12_n280(x) + if (x < 1) + fun_l13_n345(x) + else + fun_l13_n462(x) + end +end + +def fun_l12_n281(x) + if (x < 1) + fun_l13_n741(x) + else + fun_l13_n93(x) + end +end + +def fun_l12_n282(x) + if (x < 1) + fun_l13_n845(x) + else + fun_l13_n981(x) + end +end + +def fun_l12_n283(x) + if (x < 1) + fun_l13_n479(x) + else + fun_l13_n823(x) + end +end + +def fun_l12_n284(x) + if (x < 1) + fun_l13_n201(x) + else + fun_l13_n526(x) + end +end + +def fun_l12_n285(x) + if (x < 1) + fun_l13_n890(x) + else + fun_l13_n237(x) + end +end + +def fun_l12_n286(x) + if (x < 1) + fun_l13_n377(x) + else + fun_l13_n249(x) + end +end + +def fun_l12_n287(x) + if (x < 1) + fun_l13_n147(x) + else + fun_l13_n306(x) + end +end + +def fun_l12_n288(x) + if (x < 1) + fun_l13_n822(x) + else + fun_l13_n220(x) + end +end + +def fun_l12_n289(x) + if (x < 1) + fun_l13_n106(x) + else + fun_l13_n648(x) + end +end + +def fun_l12_n290(x) + if (x < 1) + fun_l13_n278(x) + else + fun_l13_n255(x) + end +end + +def fun_l12_n291(x) + if (x < 1) + fun_l13_n994(x) + else + fun_l13_n36(x) + end +end + +def fun_l12_n292(x) + if (x < 1) + fun_l13_n731(x) + else + fun_l13_n473(x) + end +end + +def fun_l12_n293(x) + if (x < 1) + fun_l13_n321(x) + else + fun_l13_n518(x) + end +end + +def fun_l12_n294(x) + if (x < 1) + fun_l13_n91(x) + else + fun_l13_n765(x) + end +end + +def fun_l12_n295(x) + if (x < 1) + fun_l13_n39(x) + else + fun_l13_n639(x) + end +end + +def fun_l12_n296(x) + if (x < 1) + fun_l13_n800(x) + else + fun_l13_n821(x) + end +end + +def fun_l12_n297(x) + if (x < 1) + fun_l13_n553(x) + else + fun_l13_n898(x) + end +end + +def fun_l12_n298(x) + if (x < 1) + fun_l13_n487(x) + else + fun_l13_n470(x) + end +end + +def fun_l12_n299(x) + if (x < 1) + fun_l13_n743(x) + else + fun_l13_n684(x) + end +end + +def fun_l12_n300(x) + if (x < 1) + fun_l13_n177(x) + else + fun_l13_n375(x) + end +end + +def fun_l12_n301(x) + if (x < 1) + fun_l13_n714(x) + else + fun_l13_n922(x) + end +end + +def fun_l12_n302(x) + if (x < 1) + fun_l13_n845(x) + else + fun_l13_n93(x) + end +end + +def fun_l12_n303(x) + if (x < 1) + fun_l13_n806(x) + else + fun_l13_n706(x) + end +end + +def fun_l12_n304(x) + if (x < 1) + fun_l13_n428(x) + else + fun_l13_n942(x) + end +end + +def fun_l12_n305(x) + if (x < 1) + fun_l13_n170(x) + else + fun_l13_n634(x) + end +end + +def fun_l12_n306(x) + if (x < 1) + fun_l13_n998(x) + else + fun_l13_n224(x) + end +end + +def fun_l12_n307(x) + if (x < 1) + fun_l13_n15(x) + else + fun_l13_n753(x) + end +end + +def fun_l12_n308(x) + if (x < 1) + fun_l13_n323(x) + else + fun_l13_n846(x) + end +end + +def fun_l12_n309(x) + if (x < 1) + fun_l13_n779(x) + else + fun_l13_n330(x) + end +end + +def fun_l12_n310(x) + if (x < 1) + fun_l13_n652(x) + else + fun_l13_n560(x) + end +end + +def fun_l12_n311(x) + if (x < 1) + fun_l13_n54(x) + else + fun_l13_n144(x) + end +end + +def fun_l12_n312(x) + if (x < 1) + fun_l13_n674(x) + else + fun_l13_n779(x) + end +end + +def fun_l12_n313(x) + if (x < 1) + fun_l13_n975(x) + else + fun_l13_n109(x) + end +end + +def fun_l12_n314(x) + if (x < 1) + fun_l13_n997(x) + else + fun_l13_n827(x) + end +end + +def fun_l12_n315(x) + if (x < 1) + fun_l13_n822(x) + else + fun_l13_n349(x) + end +end + +def fun_l12_n316(x) + if (x < 1) + fun_l13_n516(x) + else + fun_l13_n974(x) + end +end + +def fun_l12_n317(x) + if (x < 1) + fun_l13_n538(x) + else + fun_l13_n786(x) + end +end + +def fun_l12_n318(x) + if (x < 1) + fun_l13_n125(x) + else + fun_l13_n809(x) + end +end + +def fun_l12_n319(x) + if (x < 1) + fun_l13_n642(x) + else + fun_l13_n188(x) + end +end + +def fun_l12_n320(x) + if (x < 1) + fun_l13_n904(x) + else + fun_l13_n396(x) + end +end + +def fun_l12_n321(x) + if (x < 1) + fun_l13_n278(x) + else + fun_l13_n752(x) + end +end + +def fun_l12_n322(x) + if (x < 1) + fun_l13_n566(x) + else + fun_l13_n894(x) + end +end + +def fun_l12_n323(x) + if (x < 1) + fun_l13_n357(x) + else + fun_l13_n742(x) + end +end + +def fun_l12_n324(x) + if (x < 1) + fun_l13_n667(x) + else + fun_l13_n764(x) + end +end + +def fun_l12_n325(x) + if (x < 1) + fun_l13_n333(x) + else + fun_l13_n445(x) + end +end + +def fun_l12_n326(x) + if (x < 1) + fun_l13_n669(x) + else + fun_l13_n484(x) + end +end + +def fun_l12_n327(x) + if (x < 1) + fun_l13_n662(x) + else + fun_l13_n610(x) + end +end + +def fun_l12_n328(x) + if (x < 1) + fun_l13_n869(x) + else + fun_l13_n993(x) + end +end + +def fun_l12_n329(x) + if (x < 1) + fun_l13_n305(x) + else + fun_l13_n45(x) + end +end + +def fun_l12_n330(x) + if (x < 1) + fun_l13_n32(x) + else + fun_l13_n253(x) + end +end + +def fun_l12_n331(x) + if (x < 1) + fun_l13_n45(x) + else + fun_l13_n327(x) + end +end + +def fun_l12_n332(x) + if (x < 1) + fun_l13_n685(x) + else + fun_l13_n562(x) + end +end + +def fun_l12_n333(x) + if (x < 1) + fun_l13_n274(x) + else + fun_l13_n461(x) + end +end + +def fun_l12_n334(x) + if (x < 1) + fun_l13_n93(x) + else + fun_l13_n7(x) + end +end + +def fun_l12_n335(x) + if (x < 1) + fun_l13_n742(x) + else + fun_l13_n259(x) + end +end + +def fun_l12_n336(x) + if (x < 1) + fun_l13_n518(x) + else + fun_l13_n108(x) + end +end + +def fun_l12_n337(x) + if (x < 1) + fun_l13_n439(x) + else + fun_l13_n21(x) + end +end + +def fun_l12_n338(x) + if (x < 1) + fun_l13_n34(x) + else + fun_l13_n869(x) + end +end + +def fun_l12_n339(x) + if (x < 1) + fun_l13_n995(x) + else + fun_l13_n810(x) + end +end + +def fun_l12_n340(x) + if (x < 1) + fun_l13_n640(x) + else + fun_l13_n108(x) + end +end + +def fun_l12_n341(x) + if (x < 1) + fun_l13_n332(x) + else + fun_l13_n174(x) + end +end + +def fun_l12_n342(x) + if (x < 1) + fun_l13_n425(x) + else + fun_l13_n523(x) + end +end + +def fun_l12_n343(x) + if (x < 1) + fun_l13_n886(x) + else + fun_l13_n9(x) + end +end + +def fun_l12_n344(x) + if (x < 1) + fun_l13_n644(x) + else + fun_l13_n558(x) + end +end + +def fun_l12_n345(x) + if (x < 1) + fun_l13_n40(x) + else + fun_l13_n569(x) + end +end + +def fun_l12_n346(x) + if (x < 1) + fun_l13_n530(x) + else + fun_l13_n52(x) + end +end + +def fun_l12_n347(x) + if (x < 1) + fun_l13_n624(x) + else + fun_l13_n525(x) + end +end + +def fun_l12_n348(x) + if (x < 1) + fun_l13_n106(x) + else + fun_l13_n101(x) + end +end + +def fun_l12_n349(x) + if (x < 1) + fun_l13_n164(x) + else + fun_l13_n675(x) + end +end + +def fun_l12_n350(x) + if (x < 1) + fun_l13_n349(x) + else + fun_l13_n125(x) + end +end + +def fun_l12_n351(x) + if (x < 1) + fun_l13_n536(x) + else + fun_l13_n949(x) + end +end + +def fun_l12_n352(x) + if (x < 1) + fun_l13_n872(x) + else + fun_l13_n678(x) + end +end + +def fun_l12_n353(x) + if (x < 1) + fun_l13_n566(x) + else + fun_l13_n576(x) + end +end + +def fun_l12_n354(x) + if (x < 1) + fun_l13_n978(x) + else + fun_l13_n539(x) + end +end + +def fun_l12_n355(x) + if (x < 1) + fun_l13_n929(x) + else + fun_l13_n301(x) + end +end + +def fun_l12_n356(x) + if (x < 1) + fun_l13_n768(x) + else + fun_l13_n292(x) + end +end + +def fun_l12_n357(x) + if (x < 1) + fun_l13_n873(x) + else + fun_l13_n201(x) + end +end + +def fun_l12_n358(x) + if (x < 1) + fun_l13_n852(x) + else + fun_l13_n144(x) + end +end + +def fun_l12_n359(x) + if (x < 1) + fun_l13_n220(x) + else + fun_l13_n318(x) + end +end + +def fun_l12_n360(x) + if (x < 1) + fun_l13_n339(x) + else + fun_l13_n896(x) + end +end + +def fun_l12_n361(x) + if (x < 1) + fun_l13_n896(x) + else + fun_l13_n611(x) + end +end + +def fun_l12_n362(x) + if (x < 1) + fun_l13_n237(x) + else + fun_l13_n781(x) + end +end + +def fun_l12_n363(x) + if (x < 1) + fun_l13_n994(x) + else + fun_l13_n306(x) + end +end + +def fun_l12_n364(x) + if (x < 1) + fun_l13_n437(x) + else + fun_l13_n634(x) + end +end + +def fun_l12_n365(x) + if (x < 1) + fun_l13_n367(x) + else + fun_l13_n798(x) + end +end + +def fun_l12_n366(x) + if (x < 1) + fun_l13_n831(x) + else + fun_l13_n352(x) + end +end + +def fun_l12_n367(x) + if (x < 1) + fun_l13_n554(x) + else + fun_l13_n999(x) + end +end + +def fun_l12_n368(x) + if (x < 1) + fun_l13_n214(x) + else + fun_l13_n67(x) + end +end + +def fun_l12_n369(x) + if (x < 1) + fun_l13_n628(x) + else + fun_l13_n637(x) + end +end + +def fun_l12_n370(x) + if (x < 1) + fun_l13_n42(x) + else + fun_l13_n631(x) + end +end + +def fun_l12_n371(x) + if (x < 1) + fun_l13_n53(x) + else + fun_l13_n226(x) + end +end + +def fun_l12_n372(x) + if (x < 1) + fun_l13_n810(x) + else + fun_l13_n853(x) + end +end + +def fun_l12_n373(x) + if (x < 1) + fun_l13_n257(x) + else + fun_l13_n480(x) + end +end + +def fun_l12_n374(x) + if (x < 1) + fun_l13_n715(x) + else + fun_l13_n481(x) + end +end + +def fun_l12_n375(x) + if (x < 1) + fun_l13_n499(x) + else + fun_l13_n694(x) + end +end + +def fun_l12_n376(x) + if (x < 1) + fun_l13_n376(x) + else + fun_l13_n99(x) + end +end + +def fun_l12_n377(x) + if (x < 1) + fun_l13_n672(x) + else + fun_l13_n421(x) + end +end + +def fun_l12_n378(x) + if (x < 1) + fun_l13_n320(x) + else + fun_l13_n590(x) + end +end + +def fun_l12_n379(x) + if (x < 1) + fun_l13_n678(x) + else + fun_l13_n727(x) + end +end + +def fun_l12_n380(x) + if (x < 1) + fun_l13_n269(x) + else + fun_l13_n74(x) + end +end + +def fun_l12_n381(x) + if (x < 1) + fun_l13_n838(x) + else + fun_l13_n105(x) + end +end + +def fun_l12_n382(x) + if (x < 1) + fun_l13_n482(x) + else + fun_l13_n400(x) + end +end + +def fun_l12_n383(x) + if (x < 1) + fun_l13_n376(x) + else + fun_l13_n829(x) + end +end + +def fun_l12_n384(x) + if (x < 1) + fun_l13_n81(x) + else + fun_l13_n895(x) + end +end + +def fun_l12_n385(x) + if (x < 1) + fun_l13_n718(x) + else + fun_l13_n641(x) + end +end + +def fun_l12_n386(x) + if (x < 1) + fun_l13_n825(x) + else + fun_l13_n761(x) + end +end + +def fun_l12_n387(x) + if (x < 1) + fun_l13_n930(x) + else + fun_l13_n204(x) + end +end + +def fun_l12_n388(x) + if (x < 1) + fun_l13_n81(x) + else + fun_l13_n319(x) + end +end + +def fun_l12_n389(x) + if (x < 1) + fun_l13_n40(x) + else + fun_l13_n57(x) + end +end + +def fun_l12_n390(x) + if (x < 1) + fun_l13_n206(x) + else + fun_l13_n219(x) + end +end + +def fun_l12_n391(x) + if (x < 1) + fun_l13_n538(x) + else + fun_l13_n239(x) + end +end + +def fun_l12_n392(x) + if (x < 1) + fun_l13_n326(x) + else + fun_l13_n613(x) + end +end + +def fun_l12_n393(x) + if (x < 1) + fun_l13_n860(x) + else + fun_l13_n712(x) + end +end + +def fun_l12_n394(x) + if (x < 1) + fun_l13_n829(x) + else + fun_l13_n153(x) + end +end + +def fun_l12_n395(x) + if (x < 1) + fun_l13_n734(x) + else + fun_l13_n926(x) + end +end + +def fun_l12_n396(x) + if (x < 1) + fun_l13_n188(x) + else + fun_l13_n821(x) + end +end + +def fun_l12_n397(x) + if (x < 1) + fun_l13_n161(x) + else + fun_l13_n284(x) + end +end + +def fun_l12_n398(x) + if (x < 1) + fun_l13_n402(x) + else + fun_l13_n481(x) + end +end + +def fun_l12_n399(x) + if (x < 1) + fun_l13_n469(x) + else + fun_l13_n348(x) + end +end + +def fun_l12_n400(x) + if (x < 1) + fun_l13_n567(x) + else + fun_l13_n702(x) + end +end + +def fun_l12_n401(x) + if (x < 1) + fun_l13_n787(x) + else + fun_l13_n5(x) + end +end + +def fun_l12_n402(x) + if (x < 1) + fun_l13_n525(x) + else + fun_l13_n983(x) + end +end + +def fun_l12_n403(x) + if (x < 1) + fun_l13_n185(x) + else + fun_l13_n315(x) + end +end + +def fun_l12_n404(x) + if (x < 1) + fun_l13_n746(x) + else + fun_l13_n892(x) + end +end + +def fun_l12_n405(x) + if (x < 1) + fun_l13_n990(x) + else + fun_l13_n868(x) + end +end + +def fun_l12_n406(x) + if (x < 1) + fun_l13_n399(x) + else + fun_l13_n298(x) + end +end + +def fun_l12_n407(x) + if (x < 1) + fun_l13_n283(x) + else + fun_l13_n87(x) + end +end + +def fun_l12_n408(x) + if (x < 1) + fun_l13_n597(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n409(x) + if (x < 1) + fun_l13_n517(x) + else + fun_l13_n700(x) + end +end + +def fun_l12_n410(x) + if (x < 1) + fun_l13_n796(x) + else + fun_l13_n282(x) + end +end + +def fun_l12_n411(x) + if (x < 1) + fun_l13_n876(x) + else + fun_l13_n562(x) + end +end + +def fun_l12_n412(x) + if (x < 1) + fun_l13_n344(x) + else + fun_l13_n182(x) + end +end + +def fun_l12_n413(x) + if (x < 1) + fun_l13_n879(x) + else + fun_l13_n443(x) + end +end + +def fun_l12_n414(x) + if (x < 1) + fun_l13_n335(x) + else + fun_l13_n451(x) + end +end + +def fun_l12_n415(x) + if (x < 1) + fun_l13_n112(x) + else + fun_l13_n391(x) + end +end + +def fun_l12_n416(x) + if (x < 1) + fun_l13_n217(x) + else + fun_l13_n221(x) + end +end + +def fun_l12_n417(x) + if (x < 1) + fun_l13_n113(x) + else + fun_l13_n563(x) + end +end + +def fun_l12_n418(x) + if (x < 1) + fun_l13_n486(x) + else + fun_l13_n374(x) + end +end + +def fun_l12_n419(x) + if (x < 1) + fun_l13_n970(x) + else + fun_l13_n393(x) + end +end + +def fun_l12_n420(x) + if (x < 1) + fun_l13_n273(x) + else + fun_l13_n64(x) + end +end + +def fun_l12_n421(x) + if (x < 1) + fun_l13_n69(x) + else + fun_l13_n158(x) + end +end + +def fun_l12_n422(x) + if (x < 1) + fun_l13_n308(x) + else + fun_l13_n609(x) + end +end + +def fun_l12_n423(x) + if (x < 1) + fun_l13_n964(x) + else + fun_l13_n36(x) + end +end + +def fun_l12_n424(x) + if (x < 1) + fun_l13_n783(x) + else + fun_l13_n513(x) + end +end + +def fun_l12_n425(x) + if (x < 1) + fun_l13_n792(x) + else + fun_l13_n960(x) + end +end + +def fun_l12_n426(x) + if (x < 1) + fun_l13_n160(x) + else + fun_l13_n911(x) + end +end + +def fun_l12_n427(x) + if (x < 1) + fun_l13_n374(x) + else + fun_l13_n672(x) + end +end + +def fun_l12_n428(x) + if (x < 1) + fun_l13_n694(x) + else + fun_l13_n166(x) + end +end + +def fun_l12_n429(x) + if (x < 1) + fun_l13_n807(x) + else + fun_l13_n929(x) + end +end + +def fun_l12_n430(x) + if (x < 1) + fun_l13_n997(x) + else + fun_l13_n938(x) + end +end + +def fun_l12_n431(x) + if (x < 1) + fun_l13_n934(x) + else + fun_l13_n365(x) + end +end + +def fun_l12_n432(x) + if (x < 1) + fun_l13_n546(x) + else + fun_l13_n272(x) + end +end + +def fun_l12_n433(x) + if (x < 1) + fun_l13_n176(x) + else + fun_l13_n629(x) + end +end + +def fun_l12_n434(x) + if (x < 1) + fun_l13_n536(x) + else + fun_l13_n165(x) + end +end + +def fun_l12_n435(x) + if (x < 1) + fun_l13_n915(x) + else + fun_l13_n823(x) + end +end + +def fun_l12_n436(x) + if (x < 1) + fun_l13_n580(x) + else + fun_l13_n214(x) + end +end + +def fun_l12_n437(x) + if (x < 1) + fun_l13_n353(x) + else + fun_l13_n626(x) + end +end + +def fun_l12_n438(x) + if (x < 1) + fun_l13_n888(x) + else + fun_l13_n874(x) + end +end + +def fun_l12_n439(x) + if (x < 1) + fun_l13_n670(x) + else + fun_l13_n279(x) + end +end + +def fun_l12_n440(x) + if (x < 1) + fun_l13_n818(x) + else + fun_l13_n927(x) + end +end + +def fun_l12_n441(x) + if (x < 1) + fun_l13_n686(x) + else + fun_l13_n32(x) + end +end + +def fun_l12_n442(x) + if (x < 1) + fun_l13_n882(x) + else + fun_l13_n932(x) + end +end + +def fun_l12_n443(x) + if (x < 1) + fun_l13_n677(x) + else + fun_l13_n267(x) + end +end + +def fun_l12_n444(x) + if (x < 1) + fun_l13_n632(x) + else + fun_l13_n808(x) + end +end + +def fun_l12_n445(x) + if (x < 1) + fun_l13_n159(x) + else + fun_l13_n251(x) + end +end + +def fun_l12_n446(x) + if (x < 1) + fun_l13_n939(x) + else + fun_l13_n231(x) + end +end + +def fun_l12_n447(x) + if (x < 1) + fun_l13_n971(x) + else + fun_l13_n103(x) + end +end + +def fun_l12_n448(x) + if (x < 1) + fun_l13_n556(x) + else + fun_l13_n356(x) + end +end + +def fun_l12_n449(x) + if (x < 1) + fun_l13_n999(x) + else + fun_l13_n722(x) + end +end + +def fun_l12_n450(x) + if (x < 1) + fun_l13_n387(x) + else + fun_l13_n15(x) + end +end + +def fun_l12_n451(x) + if (x < 1) + fun_l13_n736(x) + else + fun_l13_n869(x) + end +end + +def fun_l12_n452(x) + if (x < 1) + fun_l13_n984(x) + else + fun_l13_n396(x) + end +end + +def fun_l12_n453(x) + if (x < 1) + fun_l13_n375(x) + else + fun_l13_n275(x) + end +end + +def fun_l12_n454(x) + if (x < 1) + fun_l13_n100(x) + else + fun_l13_n956(x) + end +end + +def fun_l12_n455(x) + if (x < 1) + fun_l13_n575(x) + else + fun_l13_n22(x) + end +end + +def fun_l12_n456(x) + if (x < 1) + fun_l13_n515(x) + else + fun_l13_n716(x) + end +end + +def fun_l12_n457(x) + if (x < 1) + fun_l13_n953(x) + else + fun_l13_n823(x) + end +end + +def fun_l12_n458(x) + if (x < 1) + fun_l13_n343(x) + else + fun_l13_n843(x) + end +end + +def fun_l12_n459(x) + if (x < 1) + fun_l13_n209(x) + else + fun_l13_n464(x) + end +end + +def fun_l12_n460(x) + if (x < 1) + fun_l13_n281(x) + else + fun_l13_n165(x) + end +end + +def fun_l12_n461(x) + if (x < 1) + fun_l13_n416(x) + else + fun_l13_n896(x) + end +end + +def fun_l12_n462(x) + if (x < 1) + fun_l13_n677(x) + else + fun_l13_n767(x) + end +end + +def fun_l12_n463(x) + if (x < 1) + fun_l13_n271(x) + else + fun_l13_n515(x) + end +end + +def fun_l12_n464(x) + if (x < 1) + fun_l13_n589(x) + else + fun_l13_n447(x) + end +end + +def fun_l12_n465(x) + if (x < 1) + fun_l13_n316(x) + else + fun_l13_n309(x) + end +end + +def fun_l12_n466(x) + if (x < 1) + fun_l13_n48(x) + else + fun_l13_n999(x) + end +end + +def fun_l12_n467(x) + if (x < 1) + fun_l13_n334(x) + else + fun_l13_n138(x) + end +end + +def fun_l12_n468(x) + if (x < 1) + fun_l13_n483(x) + else + fun_l13_n353(x) + end +end + +def fun_l12_n469(x) + if (x < 1) + fun_l13_n893(x) + else + fun_l13_n114(x) + end +end + +def fun_l12_n470(x) + if (x < 1) + fun_l13_n945(x) + else + fun_l13_n438(x) + end +end + +def fun_l12_n471(x) + if (x < 1) + fun_l13_n546(x) + else + fun_l13_n181(x) + end +end + +def fun_l12_n472(x) + if (x < 1) + fun_l13_n443(x) + else + fun_l13_n35(x) + end +end + +def fun_l12_n473(x) + if (x < 1) + fun_l13_n611(x) + else + fun_l13_n106(x) + end +end + +def fun_l12_n474(x) + if (x < 1) + fun_l13_n408(x) + else + fun_l13_n162(x) + end +end + +def fun_l12_n475(x) + if (x < 1) + fun_l13_n104(x) + else + fun_l13_n173(x) + end +end + +def fun_l12_n476(x) + if (x < 1) + fun_l13_n922(x) + else + fun_l13_n593(x) + end +end + +def fun_l12_n477(x) + if (x < 1) + fun_l13_n650(x) + else + fun_l13_n659(x) + end +end + +def fun_l12_n478(x) + if (x < 1) + fun_l13_n746(x) + else + fun_l13_n484(x) + end +end + +def fun_l12_n479(x) + if (x < 1) + fun_l13_n366(x) + else + fun_l13_n318(x) + end +end + +def fun_l12_n480(x) + if (x < 1) + fun_l13_n995(x) + else + fun_l13_n108(x) + end +end + +def fun_l12_n481(x) + if (x < 1) + fun_l13_n61(x) + else + fun_l13_n426(x) + end +end + +def fun_l12_n482(x) + if (x < 1) + fun_l13_n578(x) + else + fun_l13_n955(x) + end +end + +def fun_l12_n483(x) + if (x < 1) + fun_l13_n650(x) + else + fun_l13_n588(x) + end +end + +def fun_l12_n484(x) + if (x < 1) + fun_l13_n842(x) + else + fun_l13_n198(x) + end +end + +def fun_l12_n485(x) + if (x < 1) + fun_l13_n439(x) + else + fun_l13_n372(x) + end +end + +def fun_l12_n486(x) + if (x < 1) + fun_l13_n94(x) + else + fun_l13_n531(x) + end +end + +def fun_l12_n487(x) + if (x < 1) + fun_l13_n743(x) + else + fun_l13_n955(x) + end +end + +def fun_l12_n488(x) + if (x < 1) + fun_l13_n648(x) + else + fun_l13_n849(x) + end +end + +def fun_l12_n489(x) + if (x < 1) + fun_l13_n371(x) + else + fun_l13_n972(x) + end +end + +def fun_l12_n490(x) + if (x < 1) + fun_l13_n128(x) + else + fun_l13_n617(x) + end +end + +def fun_l12_n491(x) + if (x < 1) + fun_l13_n22(x) + else + fun_l13_n201(x) + end +end + +def fun_l12_n492(x) + if (x < 1) + fun_l13_n209(x) + else + fun_l13_n679(x) + end +end + +def fun_l12_n493(x) + if (x < 1) + fun_l13_n415(x) + else + fun_l13_n765(x) + end +end + +def fun_l12_n494(x) + if (x < 1) + fun_l13_n498(x) + else + fun_l13_n719(x) + end +end + +def fun_l12_n495(x) + if (x < 1) + fun_l13_n492(x) + else + fun_l13_n161(x) + end +end + +def fun_l12_n496(x) + if (x < 1) + fun_l13_n162(x) + else + fun_l13_n54(x) + end +end + +def fun_l12_n497(x) + if (x < 1) + fun_l13_n743(x) + else + fun_l13_n834(x) + end +end + +def fun_l12_n498(x) + if (x < 1) + fun_l13_n376(x) + else + fun_l13_n676(x) + end +end + +def fun_l12_n499(x) + if (x < 1) + fun_l13_n626(x) + else + fun_l13_n357(x) + end +end + +def fun_l12_n500(x) + if (x < 1) + fun_l13_n874(x) + else + fun_l13_n53(x) + end +end + +def fun_l12_n501(x) + if (x < 1) + fun_l13_n146(x) + else + fun_l13_n732(x) + end +end + +def fun_l12_n502(x) + if (x < 1) + fun_l13_n908(x) + else + fun_l13_n933(x) + end +end + +def fun_l12_n503(x) + if (x < 1) + fun_l13_n758(x) + else + fun_l13_n289(x) + end +end + +def fun_l12_n504(x) + if (x < 1) + fun_l13_n913(x) + else + fun_l13_n770(x) + end +end + +def fun_l12_n505(x) + if (x < 1) + fun_l13_n305(x) + else + fun_l13_n990(x) + end +end + +def fun_l12_n506(x) + if (x < 1) + fun_l13_n79(x) + else + fun_l13_n199(x) + end +end + +def fun_l12_n507(x) + if (x < 1) + fun_l13_n430(x) + else + fun_l13_n394(x) + end +end + +def fun_l12_n508(x) + if (x < 1) + fun_l13_n835(x) + else + fun_l13_n64(x) + end +end + +def fun_l12_n509(x) + if (x < 1) + fun_l13_n661(x) + else + fun_l13_n301(x) + end +end + +def fun_l12_n510(x) + if (x < 1) + fun_l13_n672(x) + else + fun_l13_n498(x) + end +end + +def fun_l12_n511(x) + if (x < 1) + fun_l13_n540(x) + else + fun_l13_n57(x) + end +end + +def fun_l12_n512(x) + if (x < 1) + fun_l13_n634(x) + else + fun_l13_n790(x) + end +end + +def fun_l12_n513(x) + if (x < 1) + fun_l13_n998(x) + else + fun_l13_n3(x) + end +end + +def fun_l12_n514(x) + if (x < 1) + fun_l13_n482(x) + else + fun_l13_n116(x) + end +end + +def fun_l12_n515(x) + if (x < 1) + fun_l13_n967(x) + else + fun_l13_n17(x) + end +end + +def fun_l12_n516(x) + if (x < 1) + fun_l13_n614(x) + else + fun_l13_n260(x) + end +end + +def fun_l12_n517(x) + if (x < 1) + fun_l13_n273(x) + else + fun_l13_n982(x) + end +end + +def fun_l12_n518(x) + if (x < 1) + fun_l13_n786(x) + else + fun_l13_n186(x) + end +end + +def fun_l12_n519(x) + if (x < 1) + fun_l13_n990(x) + else + fun_l13_n223(x) + end +end + +def fun_l12_n520(x) + if (x < 1) + fun_l13_n406(x) + else + fun_l13_n374(x) + end +end + +def fun_l12_n521(x) + if (x < 1) + fun_l13_n548(x) + else + fun_l13_n160(x) + end +end + +def fun_l12_n522(x) + if (x < 1) + fun_l13_n249(x) + else + fun_l13_n295(x) + end +end + +def fun_l12_n523(x) + if (x < 1) + fun_l13_n434(x) + else + fun_l13_n73(x) + end +end + +def fun_l12_n524(x) + if (x < 1) + fun_l13_n550(x) + else + fun_l13_n472(x) + end +end + +def fun_l12_n525(x) + if (x < 1) + fun_l13_n720(x) + else + fun_l13_n979(x) + end +end + +def fun_l12_n526(x) + if (x < 1) + fun_l13_n806(x) + else + fun_l13_n156(x) + end +end + +def fun_l12_n527(x) + if (x < 1) + fun_l13_n689(x) + else + fun_l13_n781(x) + end +end + +def fun_l12_n528(x) + if (x < 1) + fun_l13_n130(x) + else + fun_l13_n909(x) + end +end + +def fun_l12_n529(x) + if (x < 1) + fun_l13_n762(x) + else + fun_l13_n301(x) + end +end + +def fun_l12_n530(x) + if (x < 1) + fun_l13_n580(x) + else + fun_l13_n269(x) + end +end + +def fun_l12_n531(x) + if (x < 1) + fun_l13_n427(x) + else + fun_l13_n279(x) + end +end + +def fun_l12_n532(x) + if (x < 1) + fun_l13_n408(x) + else + fun_l13_n523(x) + end +end + +def fun_l12_n533(x) + if (x < 1) + fun_l13_n358(x) + else + fun_l13_n386(x) + end +end + +def fun_l12_n534(x) + if (x < 1) + fun_l13_n401(x) + else + fun_l13_n148(x) + end +end + +def fun_l12_n535(x) + if (x < 1) + fun_l13_n588(x) + else + fun_l13_n607(x) + end +end + +def fun_l12_n536(x) + if (x < 1) + fun_l13_n445(x) + else + fun_l13_n681(x) + end +end + +def fun_l12_n537(x) + if (x < 1) + fun_l13_n16(x) + else + fun_l13_n931(x) + end +end + +def fun_l12_n538(x) + if (x < 1) + fun_l13_n567(x) + else + fun_l13_n9(x) + end +end + +def fun_l12_n539(x) + if (x < 1) + fun_l13_n584(x) + else + fun_l13_n46(x) + end +end + +def fun_l12_n540(x) + if (x < 1) + fun_l13_n147(x) + else + fun_l13_n498(x) + end +end + +def fun_l12_n541(x) + if (x < 1) + fun_l13_n727(x) + else + fun_l13_n152(x) + end +end + +def fun_l12_n542(x) + if (x < 1) + fun_l13_n797(x) + else + fun_l13_n789(x) + end +end + +def fun_l12_n543(x) + if (x < 1) + fun_l13_n711(x) + else + fun_l13_n939(x) + end +end + +def fun_l12_n544(x) + if (x < 1) + fun_l13_n276(x) + else + fun_l13_n325(x) + end +end + +def fun_l12_n545(x) + if (x < 1) + fun_l13_n800(x) + else + fun_l13_n974(x) + end +end + +def fun_l12_n546(x) + if (x < 1) + fun_l13_n654(x) + else + fun_l13_n331(x) + end +end + +def fun_l12_n547(x) + if (x < 1) + fun_l13_n179(x) + else + fun_l13_n395(x) + end +end + +def fun_l12_n548(x) + if (x < 1) + fun_l13_n348(x) + else + fun_l13_n210(x) + end +end + +def fun_l12_n549(x) + if (x < 1) + fun_l13_n669(x) + else + fun_l13_n459(x) + end +end + +def fun_l12_n550(x) + if (x < 1) + fun_l13_n316(x) + else + fun_l13_n846(x) + end +end + +def fun_l12_n551(x) + if (x < 1) + fun_l13_n262(x) + else + fun_l13_n430(x) + end +end + +def fun_l12_n552(x) + if (x < 1) + fun_l13_n224(x) + else + fun_l13_n866(x) + end +end + +def fun_l12_n553(x) + if (x < 1) + fun_l13_n551(x) + else + fun_l13_n30(x) + end +end + +def fun_l12_n554(x) + if (x < 1) + fun_l13_n864(x) + else + fun_l13_n931(x) + end +end + +def fun_l12_n555(x) + if (x < 1) + fun_l13_n427(x) + else + fun_l13_n138(x) + end +end + +def fun_l12_n556(x) + if (x < 1) + fun_l13_n603(x) + else + fun_l13_n167(x) + end +end + +def fun_l12_n557(x) + if (x < 1) + fun_l13_n858(x) + else + fun_l13_n123(x) + end +end + +def fun_l12_n558(x) + if (x < 1) + fun_l13_n729(x) + else + fun_l13_n769(x) + end +end + +def fun_l12_n559(x) + if (x < 1) + fun_l13_n529(x) + else + fun_l13_n114(x) + end +end + +def fun_l12_n560(x) + if (x < 1) + fun_l13_n727(x) + else + fun_l13_n673(x) + end +end + +def fun_l12_n561(x) + if (x < 1) + fun_l13_n742(x) + else + fun_l13_n981(x) + end +end + +def fun_l12_n562(x) + if (x < 1) + fun_l13_n29(x) + else + fun_l13_n493(x) + end +end + +def fun_l12_n563(x) + if (x < 1) + fun_l13_n207(x) + else + fun_l13_n361(x) + end +end + +def fun_l12_n564(x) + if (x < 1) + fun_l13_n370(x) + else + fun_l13_n185(x) + end +end + +def fun_l12_n565(x) + if (x < 1) + fun_l13_n755(x) + else + fun_l13_n28(x) + end +end + +def fun_l12_n566(x) + if (x < 1) + fun_l13_n332(x) + else + fun_l13_n718(x) + end +end + +def fun_l12_n567(x) + if (x < 1) + fun_l13_n329(x) + else + fun_l13_n623(x) + end +end + +def fun_l12_n568(x) + if (x < 1) + fun_l13_n592(x) + else + fun_l13_n870(x) + end +end + +def fun_l12_n569(x) + if (x < 1) + fun_l13_n539(x) + else + fun_l13_n68(x) + end +end + +def fun_l12_n570(x) + if (x < 1) + fun_l13_n794(x) + else + fun_l13_n617(x) + end +end + +def fun_l12_n571(x) + if (x < 1) + fun_l13_n801(x) + else + fun_l13_n610(x) + end +end + +def fun_l12_n572(x) + if (x < 1) + fun_l13_n781(x) + else + fun_l13_n879(x) + end +end + +def fun_l12_n573(x) + if (x < 1) + fun_l13_n519(x) + else + fun_l13_n748(x) + end +end + +def fun_l12_n574(x) + if (x < 1) + fun_l13_n416(x) + else + fun_l13_n908(x) + end +end + +def fun_l12_n575(x) + if (x < 1) + fun_l13_n288(x) + else + fun_l13_n925(x) + end +end + +def fun_l12_n576(x) + if (x < 1) + fun_l13_n398(x) + else + fun_l13_n185(x) + end +end + +def fun_l12_n577(x) + if (x < 1) + fun_l13_n742(x) + else + fun_l13_n768(x) + end +end + +def fun_l12_n578(x) + if (x < 1) + fun_l13_n472(x) + else + fun_l13_n474(x) + end +end + +def fun_l12_n579(x) + if (x < 1) + fun_l13_n229(x) + else + fun_l13_n479(x) + end +end + +def fun_l12_n580(x) + if (x < 1) + fun_l13_n483(x) + else + fun_l13_n60(x) + end +end + +def fun_l12_n581(x) + if (x < 1) + fun_l13_n971(x) + else + fun_l13_n958(x) + end +end + +def fun_l12_n582(x) + if (x < 1) + fun_l13_n612(x) + else + fun_l13_n491(x) + end +end + +def fun_l12_n583(x) + if (x < 1) + fun_l13_n320(x) + else + fun_l13_n356(x) + end +end + +def fun_l12_n584(x) + if (x < 1) + fun_l13_n521(x) + else + fun_l13_n126(x) + end +end + +def fun_l12_n585(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n503(x) + end +end + +def fun_l12_n586(x) + if (x < 1) + fun_l13_n715(x) + else + fun_l13_n849(x) + end +end + +def fun_l12_n587(x) + if (x < 1) + fun_l13_n192(x) + else + fun_l13_n278(x) + end +end + +def fun_l12_n588(x) + if (x < 1) + fun_l13_n882(x) + else + fun_l13_n992(x) + end +end + +def fun_l12_n589(x) + if (x < 1) + fun_l13_n693(x) + else + fun_l13_n734(x) + end +end + +def fun_l12_n590(x) + if (x < 1) + fun_l13_n207(x) + else + fun_l13_n674(x) + end +end + +def fun_l12_n591(x) + if (x < 1) + fun_l13_n409(x) + else + fun_l13_n937(x) + end +end + +def fun_l12_n592(x) + if (x < 1) + fun_l13_n424(x) + else + fun_l13_n709(x) + end +end + +def fun_l12_n593(x) + if (x < 1) + fun_l13_n530(x) + else + fun_l13_n50(x) + end +end + +def fun_l12_n594(x) + if (x < 1) + fun_l13_n451(x) + else + fun_l13_n513(x) + end +end + +def fun_l12_n595(x) + if (x < 1) + fun_l13_n522(x) + else + fun_l13_n414(x) + end +end + +def fun_l12_n596(x) + if (x < 1) + fun_l13_n352(x) + else + fun_l13_n323(x) + end +end + +def fun_l12_n597(x) + if (x < 1) + fun_l13_n342(x) + else + fun_l13_n362(x) + end +end + +def fun_l12_n598(x) + if (x < 1) + fun_l13_n870(x) + else + fun_l13_n366(x) + end +end + +def fun_l12_n599(x) + if (x < 1) + fun_l13_n562(x) + else + fun_l13_n455(x) + end +end + +def fun_l12_n600(x) + if (x < 1) + fun_l13_n554(x) + else + fun_l13_n929(x) + end +end + +def fun_l12_n601(x) + if (x < 1) + fun_l13_n498(x) + else + fun_l13_n287(x) + end +end + +def fun_l12_n602(x) + if (x < 1) + fun_l13_n9(x) + else + fun_l13_n258(x) + end +end + +def fun_l12_n603(x) + if (x < 1) + fun_l13_n976(x) + else + fun_l13_n604(x) + end +end + +def fun_l12_n604(x) + if (x < 1) + fun_l13_n411(x) + else + fun_l13_n238(x) + end +end + +def fun_l12_n605(x) + if (x < 1) + fun_l13_n80(x) + else + fun_l13_n665(x) + end +end + +def fun_l12_n606(x) + if (x < 1) + fun_l13_n453(x) + else + fun_l13_n642(x) + end +end + +def fun_l12_n607(x) + if (x < 1) + fun_l13_n247(x) + else + fun_l13_n651(x) + end +end + +def fun_l12_n608(x) + if (x < 1) + fun_l13_n586(x) + else + fun_l13_n372(x) + end +end + +def fun_l12_n609(x) + if (x < 1) + fun_l13_n623(x) + else + fun_l13_n380(x) + end +end + +def fun_l12_n610(x) + if (x < 1) + fun_l13_n399(x) + else + fun_l13_n43(x) + end +end + +def fun_l12_n611(x) + if (x < 1) + fun_l13_n191(x) + else + fun_l13_n211(x) + end +end + +def fun_l12_n612(x) + if (x < 1) + fun_l13_n719(x) + else + fun_l13_n663(x) + end +end + +def fun_l12_n613(x) + if (x < 1) + fun_l13_n849(x) + else + fun_l13_n39(x) + end +end + +def fun_l12_n614(x) + if (x < 1) + fun_l13_n822(x) + else + fun_l13_n927(x) + end +end + +def fun_l12_n615(x) + if (x < 1) + fun_l13_n358(x) + else + fun_l13_n364(x) + end +end + +def fun_l12_n616(x) + if (x < 1) + fun_l13_n685(x) + else + fun_l13_n897(x) + end +end + +def fun_l12_n617(x) + if (x < 1) + fun_l13_n243(x) + else + fun_l13_n138(x) + end +end + +def fun_l12_n618(x) + if (x < 1) + fun_l13_n737(x) + else + fun_l13_n187(x) + end +end + +def fun_l12_n619(x) + if (x < 1) + fun_l13_n56(x) + else + fun_l13_n684(x) + end +end + +def fun_l12_n620(x) + if (x < 1) + fun_l13_n865(x) + else + fun_l13_n886(x) + end +end + +def fun_l12_n621(x) + if (x < 1) + fun_l13_n749(x) + else + fun_l13_n554(x) + end +end + +def fun_l12_n622(x) + if (x < 1) + fun_l13_n162(x) + else + fun_l13_n600(x) + end +end + +def fun_l12_n623(x) + if (x < 1) + fun_l13_n763(x) + else + fun_l13_n227(x) + end +end + +def fun_l12_n624(x) + if (x < 1) + fun_l13_n767(x) + else + fun_l13_n431(x) + end +end + +def fun_l12_n625(x) + if (x < 1) + fun_l13_n347(x) + else + fun_l13_n214(x) + end +end + +def fun_l12_n626(x) + if (x < 1) + fun_l13_n365(x) + else + fun_l13_n747(x) + end +end + +def fun_l12_n627(x) + if (x < 1) + fun_l13_n783(x) + else + fun_l13_n597(x) + end +end + +def fun_l12_n628(x) + if (x < 1) + fun_l13_n249(x) + else + fun_l13_n906(x) + end +end + +def fun_l12_n629(x) + if (x < 1) + fun_l13_n803(x) + else + fun_l13_n855(x) + end +end + +def fun_l12_n630(x) + if (x < 1) + fun_l13_n981(x) + else + fun_l13_n38(x) + end +end + +def fun_l12_n631(x) + if (x < 1) + fun_l13_n437(x) + else + fun_l13_n158(x) + end +end + +def fun_l12_n632(x) + if (x < 1) + fun_l13_n611(x) + else + fun_l13_n142(x) + end +end + +def fun_l12_n633(x) + if (x < 1) + fun_l13_n880(x) + else + fun_l13_n172(x) + end +end + +def fun_l12_n634(x) + if (x < 1) + fun_l13_n135(x) + else + fun_l13_n529(x) + end +end + +def fun_l12_n635(x) + if (x < 1) + fun_l13_n694(x) + else + fun_l13_n949(x) + end +end + +def fun_l12_n636(x) + if (x < 1) + fun_l13_n153(x) + else + fun_l13_n326(x) + end +end + +def fun_l12_n637(x) + if (x < 1) + fun_l13_n318(x) + else + fun_l13_n372(x) + end +end + +def fun_l12_n638(x) + if (x < 1) + fun_l13_n467(x) + else + fun_l13_n450(x) + end +end + +def fun_l12_n639(x) + if (x < 1) + fun_l13_n397(x) + else + fun_l13_n138(x) + end +end + +def fun_l12_n640(x) + if (x < 1) + fun_l13_n408(x) + else + fun_l13_n335(x) + end +end + +def fun_l12_n641(x) + if (x < 1) + fun_l13_n342(x) + else + fun_l13_n856(x) + end +end + +def fun_l12_n642(x) + if (x < 1) + fun_l13_n163(x) + else + fun_l13_n979(x) + end +end + +def fun_l12_n643(x) + if (x < 1) + fun_l13_n509(x) + else + fun_l13_n153(x) + end +end + +def fun_l12_n644(x) + if (x < 1) + fun_l13_n3(x) + else + fun_l13_n55(x) + end +end + +def fun_l12_n645(x) + if (x < 1) + fun_l13_n730(x) + else + fun_l13_n52(x) + end +end + +def fun_l12_n646(x) + if (x < 1) + fun_l13_n553(x) + else + fun_l13_n885(x) + end +end + +def fun_l12_n647(x) + if (x < 1) + fun_l13_n866(x) + else + fun_l13_n684(x) + end +end + +def fun_l12_n648(x) + if (x < 1) + fun_l13_n989(x) + else + fun_l13_n511(x) + end +end + +def fun_l12_n649(x) + if (x < 1) + fun_l13_n527(x) + else + fun_l13_n166(x) + end +end + +def fun_l12_n650(x) + if (x < 1) + fun_l13_n507(x) + else + fun_l13_n527(x) + end +end + +def fun_l12_n651(x) + if (x < 1) + fun_l13_n174(x) + else + fun_l13_n881(x) + end +end + +def fun_l12_n652(x) + if (x < 1) + fun_l13_n302(x) + else + fun_l13_n3(x) + end +end + +def fun_l12_n653(x) + if (x < 1) + fun_l13_n971(x) + else + fun_l13_n601(x) + end +end + +def fun_l12_n654(x) + if (x < 1) + fun_l13_n440(x) + else + fun_l13_n286(x) + end +end + +def fun_l12_n655(x) + if (x < 1) + fun_l13_n208(x) + else + fun_l13_n275(x) + end +end + +def fun_l12_n656(x) + if (x < 1) + fun_l13_n954(x) + else + fun_l13_n991(x) + end +end + +def fun_l12_n657(x) + if (x < 1) + fun_l13_n212(x) + else + fun_l13_n640(x) + end +end + +def fun_l12_n658(x) + if (x < 1) + fun_l13_n733(x) + else + fun_l13_n459(x) + end +end + +def fun_l12_n659(x) + if (x < 1) + fun_l13_n767(x) + else + fun_l13_n581(x) + end +end + +def fun_l12_n660(x) + if (x < 1) + fun_l13_n421(x) + else + fun_l13_n19(x) + end +end + +def fun_l12_n661(x) + if (x < 1) + fun_l13_n500(x) + else + fun_l13_n464(x) + end +end + +def fun_l12_n662(x) + if (x < 1) + fun_l13_n26(x) + else + fun_l13_n300(x) + end +end + +def fun_l12_n663(x) + if (x < 1) + fun_l13_n160(x) + else + fun_l13_n112(x) + end +end + +def fun_l12_n664(x) + if (x < 1) + fun_l13_n181(x) + else + fun_l13_n511(x) + end +end + +def fun_l12_n665(x) + if (x < 1) + fun_l13_n573(x) + else + fun_l13_n283(x) + end +end + +def fun_l12_n666(x) + if (x < 1) + fun_l13_n562(x) + else + fun_l13_n992(x) + end +end + +def fun_l12_n667(x) + if (x < 1) + fun_l13_n426(x) + else + fun_l13_n921(x) + end +end + +def fun_l12_n668(x) + if (x < 1) + fun_l13_n319(x) + else + fun_l13_n226(x) + end +end + +def fun_l12_n669(x) + if (x < 1) + fun_l13_n832(x) + else + fun_l13_n690(x) + end +end + +def fun_l12_n670(x) + if (x < 1) + fun_l13_n921(x) + else + fun_l13_n964(x) + end +end + +def fun_l12_n671(x) + if (x < 1) + fun_l13_n823(x) + else + fun_l13_n903(x) + end +end + +def fun_l12_n672(x) + if (x < 1) + fun_l13_n469(x) + else + fun_l13_n914(x) + end +end + +def fun_l12_n673(x) + if (x < 1) + fun_l13_n478(x) + else + fun_l13_n481(x) + end +end + +def fun_l12_n674(x) + if (x < 1) + fun_l13_n762(x) + else + fun_l13_n464(x) + end +end + +def fun_l12_n675(x) + if (x < 1) + fun_l13_n930(x) + else + fun_l13_n587(x) + end +end + +def fun_l12_n676(x) + if (x < 1) + fun_l13_n351(x) + else + fun_l13_n239(x) + end +end + +def fun_l12_n677(x) + if (x < 1) + fun_l13_n989(x) + else + fun_l13_n424(x) + end +end + +def fun_l12_n678(x) + if (x < 1) + fun_l13_n505(x) + else + fun_l13_n186(x) + end +end + +def fun_l12_n679(x) + if (x < 1) + fun_l13_n665(x) + else + fun_l13_n536(x) + end +end + +def fun_l12_n680(x) + if (x < 1) + fun_l13_n734(x) + else + fun_l13_n36(x) + end +end + +def fun_l12_n681(x) + if (x < 1) + fun_l13_n380(x) + else + fun_l13_n340(x) + end +end + +def fun_l12_n682(x) + if (x < 1) + fun_l13_n293(x) + else + fun_l13_n205(x) + end +end + +def fun_l12_n683(x) + if (x < 1) + fun_l13_n412(x) + else + fun_l13_n13(x) + end +end + +def fun_l12_n684(x) + if (x < 1) + fun_l13_n187(x) + else + fun_l13_n186(x) + end +end + +def fun_l12_n685(x) + if (x < 1) + fun_l13_n299(x) + else + fun_l13_n875(x) + end +end + +def fun_l12_n686(x) + if (x < 1) + fun_l13_n943(x) + else + fun_l13_n96(x) + end +end + +def fun_l12_n687(x) + if (x < 1) + fun_l13_n736(x) + else + fun_l13_n377(x) + end +end + +def fun_l12_n688(x) + if (x < 1) + fun_l13_n559(x) + else + fun_l13_n410(x) + end +end + +def fun_l12_n689(x) + if (x < 1) + fun_l13_n538(x) + else + fun_l13_n521(x) + end +end + +def fun_l12_n690(x) + if (x < 1) + fun_l13_n568(x) + else + fun_l13_n838(x) + end +end + +def fun_l12_n691(x) + if (x < 1) + fun_l13_n556(x) + else + fun_l13_n42(x) + end +end + +def fun_l12_n692(x) + if (x < 1) + fun_l13_n137(x) + else + fun_l13_n939(x) + end +end + +def fun_l12_n693(x) + if (x < 1) + fun_l13_n974(x) + else + fun_l13_n308(x) + end +end + +def fun_l12_n694(x) + if (x < 1) + fun_l13_n459(x) + else + fun_l13_n323(x) + end +end + +def fun_l12_n695(x) + if (x < 1) + fun_l13_n829(x) + else + fun_l13_n909(x) + end +end + +def fun_l12_n696(x) + if (x < 1) + fun_l13_n710(x) + else + fun_l13_n648(x) + end +end + +def fun_l12_n697(x) + if (x < 1) + fun_l13_n27(x) + else + fun_l13_n500(x) + end +end + +def fun_l12_n698(x) + if (x < 1) + fun_l13_n553(x) + else + fun_l13_n865(x) + end +end + +def fun_l12_n699(x) + if (x < 1) + fun_l13_n126(x) + else + fun_l13_n789(x) + end +end + +def fun_l12_n700(x) + if (x < 1) + fun_l13_n408(x) + else + fun_l13_n391(x) + end +end + +def fun_l12_n701(x) + if (x < 1) + fun_l13_n469(x) + else + fun_l13_n48(x) + end +end + +def fun_l12_n702(x) + if (x < 1) + fun_l13_n646(x) + else + fun_l13_n117(x) + end +end + +def fun_l12_n703(x) + if (x < 1) + fun_l13_n461(x) + else + fun_l13_n114(x) + end +end + +def fun_l12_n704(x) + if (x < 1) + fun_l13_n603(x) + else + fun_l13_n27(x) + end +end + +def fun_l12_n705(x) + if (x < 1) + fun_l13_n842(x) + else + fun_l13_n792(x) + end +end + +def fun_l12_n706(x) + if (x < 1) + fun_l13_n194(x) + else + fun_l13_n405(x) + end +end + +def fun_l12_n707(x) + if (x < 1) + fun_l13_n975(x) + else + fun_l13_n933(x) + end +end + +def fun_l12_n708(x) + if (x < 1) + fun_l13_n919(x) + else + fun_l13_n558(x) + end +end + +def fun_l12_n709(x) + if (x < 1) + fun_l13_n293(x) + else + fun_l13_n868(x) + end +end + +def fun_l12_n710(x) + if (x < 1) + fun_l13_n577(x) + else + fun_l13_n816(x) + end +end + +def fun_l12_n711(x) + if (x < 1) + fun_l13_n625(x) + else + fun_l13_n319(x) + end +end + +def fun_l12_n712(x) + if (x < 1) + fun_l13_n100(x) + else + fun_l13_n421(x) + end +end + +def fun_l12_n713(x) + if (x < 1) + fun_l13_n120(x) + else + fun_l13_n727(x) + end +end + +def fun_l12_n714(x) + if (x < 1) + fun_l13_n346(x) + else + fun_l13_n399(x) + end +end + +def fun_l12_n715(x) + if (x < 1) + fun_l13_n64(x) + else + fun_l13_n895(x) + end +end + +def fun_l12_n716(x) + if (x < 1) + fun_l13_n810(x) + else + fun_l13_n958(x) + end +end + +def fun_l12_n717(x) + if (x < 1) + fun_l13_n24(x) + else + fun_l13_n851(x) + end +end + +def fun_l12_n718(x) + if (x < 1) + fun_l13_n716(x) + else + fun_l13_n859(x) + end +end + +def fun_l12_n719(x) + if (x < 1) + fun_l13_n556(x) + else + fun_l13_n999(x) + end +end + +def fun_l12_n720(x) + if (x < 1) + fun_l13_n388(x) + else + fun_l13_n127(x) + end +end + +def fun_l12_n721(x) + if (x < 1) + fun_l13_n447(x) + else + fun_l13_n880(x) + end +end + +def fun_l12_n722(x) + if (x < 1) + fun_l13_n415(x) + else + fun_l13_n636(x) + end +end + +def fun_l12_n723(x) + if (x < 1) + fun_l13_n315(x) + else + fun_l13_n766(x) + end +end + +def fun_l12_n724(x) + if (x < 1) + fun_l13_n600(x) + else + fun_l13_n223(x) + end +end + +def fun_l12_n725(x) + if (x < 1) + fun_l13_n773(x) + else + fun_l13_n523(x) + end +end + +def fun_l12_n726(x) + if (x < 1) + fun_l13_n662(x) + else + fun_l13_n775(x) + end +end + +def fun_l12_n727(x) + if (x < 1) + fun_l13_n553(x) + else + fun_l13_n247(x) + end +end + +def fun_l12_n728(x) + if (x < 1) + fun_l13_n180(x) + else + fun_l13_n815(x) + end +end + +def fun_l12_n729(x) + if (x < 1) + fun_l13_n786(x) + else + fun_l13_n729(x) + end +end + +def fun_l12_n730(x) + if (x < 1) + fun_l13_n1(x) + else + fun_l13_n791(x) + end +end + +def fun_l12_n731(x) + if (x < 1) + fun_l13_n216(x) + else + fun_l13_n682(x) + end +end + +def fun_l12_n732(x) + if (x < 1) + fun_l13_n953(x) + else + fun_l13_n364(x) + end +end + +def fun_l12_n733(x) + if (x < 1) + fun_l13_n164(x) + else + fun_l13_n277(x) + end +end + +def fun_l12_n734(x) + if (x < 1) + fun_l13_n486(x) + else + fun_l13_n741(x) + end +end + +def fun_l12_n735(x) + if (x < 1) + fun_l13_n310(x) + else + fun_l13_n940(x) + end +end + +def fun_l12_n736(x) + if (x < 1) + fun_l13_n312(x) + else + fun_l13_n46(x) + end +end + +def fun_l12_n737(x) + if (x < 1) + fun_l13_n473(x) + else + fun_l13_n728(x) + end +end + +def fun_l12_n738(x) + if (x < 1) + fun_l13_n602(x) + else + fun_l13_n652(x) + end +end + +def fun_l12_n739(x) + if (x < 1) + fun_l13_n397(x) + else + fun_l13_n855(x) + end +end + +def fun_l12_n740(x) + if (x < 1) + fun_l13_n81(x) + else + fun_l13_n32(x) + end +end + +def fun_l12_n741(x) + if (x < 1) + fun_l13_n822(x) + else + fun_l13_n231(x) + end +end + +def fun_l12_n742(x) + if (x < 1) + fun_l13_n200(x) + else + fun_l13_n440(x) + end +end + +def fun_l12_n743(x) + if (x < 1) + fun_l13_n415(x) + else + fun_l13_n631(x) + end +end + +def fun_l12_n744(x) + if (x < 1) + fun_l13_n353(x) + else + fun_l13_n536(x) + end +end + +def fun_l12_n745(x) + if (x < 1) + fun_l13_n986(x) + else + fun_l13_n384(x) + end +end + +def fun_l12_n746(x) + if (x < 1) + fun_l13_n237(x) + else + fun_l13_n583(x) + end +end + +def fun_l12_n747(x) + if (x < 1) + fun_l13_n518(x) + else + fun_l13_n717(x) + end +end + +def fun_l12_n748(x) + if (x < 1) + fun_l13_n242(x) + else + fun_l13_n180(x) + end +end + +def fun_l12_n749(x) + if (x < 1) + fun_l13_n369(x) + else + fun_l13_n249(x) + end +end + +def fun_l12_n750(x) + if (x < 1) + fun_l13_n335(x) + else + fun_l13_n180(x) + end +end + +def fun_l12_n751(x) + if (x < 1) + fun_l13_n952(x) + else + fun_l13_n506(x) + end +end + +def fun_l12_n752(x) + if (x < 1) + fun_l13_n941(x) + else + fun_l13_n251(x) + end +end + +def fun_l12_n753(x) + if (x < 1) + fun_l13_n21(x) + else + fun_l13_n536(x) + end +end + +def fun_l12_n754(x) + if (x < 1) + fun_l13_n123(x) + else + fun_l13_n976(x) + end +end + +def fun_l12_n755(x) + if (x < 1) + fun_l13_n229(x) + else + fun_l13_n535(x) + end +end + +def fun_l12_n756(x) + if (x < 1) + fun_l13_n23(x) + else + fun_l13_n976(x) + end +end + +def fun_l12_n757(x) + if (x < 1) + fun_l13_n755(x) + else + fun_l13_n677(x) + end +end + +def fun_l12_n758(x) + if (x < 1) + fun_l13_n692(x) + else + fun_l13_n334(x) + end +end + +def fun_l12_n759(x) + if (x < 1) + fun_l13_n380(x) + else + fun_l13_n903(x) + end +end + +def fun_l12_n760(x) + if (x < 1) + fun_l13_n16(x) + else + fun_l13_n750(x) + end +end + +def fun_l12_n761(x) + if (x < 1) + fun_l13_n186(x) + else + fun_l13_n639(x) + end +end + +def fun_l12_n762(x) + if (x < 1) + fun_l13_n163(x) + else + fun_l13_n273(x) + end +end + +def fun_l12_n763(x) + if (x < 1) + fun_l13_n791(x) + else + fun_l13_n55(x) + end +end + +def fun_l12_n764(x) + if (x < 1) + fun_l13_n10(x) + else + fun_l13_n672(x) + end +end + +def fun_l12_n765(x) + if (x < 1) + fun_l13_n382(x) + else + fun_l13_n284(x) + end +end + +def fun_l12_n766(x) + if (x < 1) + fun_l13_n940(x) + else + fun_l13_n716(x) + end +end + +def fun_l12_n767(x) + if (x < 1) + fun_l13_n414(x) + else + fun_l13_n997(x) + end +end + +def fun_l12_n768(x) + if (x < 1) + fun_l13_n345(x) + else + fun_l13_n511(x) + end +end + +def fun_l12_n769(x) + if (x < 1) + fun_l13_n915(x) + else + fun_l13_n907(x) + end +end + +def fun_l12_n770(x) + if (x < 1) + fun_l13_n508(x) + else + fun_l13_n144(x) + end +end + +def fun_l12_n771(x) + if (x < 1) + fun_l13_n764(x) + else + fun_l13_n211(x) + end +end + +def fun_l12_n772(x) + if (x < 1) + fun_l13_n571(x) + else + fun_l13_n486(x) + end +end + +def fun_l12_n773(x) + if (x < 1) + fun_l13_n503(x) + else + fun_l13_n561(x) + end +end + +def fun_l12_n774(x) + if (x < 1) + fun_l13_n831(x) + else + fun_l13_n608(x) + end +end + +def fun_l12_n775(x) + if (x < 1) + fun_l13_n254(x) + else + fun_l13_n626(x) + end +end + +def fun_l12_n776(x) + if (x < 1) + fun_l13_n155(x) + else + fun_l13_n602(x) + end +end + +def fun_l12_n777(x) + if (x < 1) + fun_l13_n331(x) + else + fun_l13_n837(x) + end +end + +def fun_l12_n778(x) + if (x < 1) + fun_l13_n109(x) + else + fun_l13_n558(x) + end +end + +def fun_l12_n779(x) + if (x < 1) + fun_l13_n557(x) + else + fun_l13_n784(x) + end +end + +def fun_l12_n780(x) + if (x < 1) + fun_l13_n719(x) + else + fun_l13_n933(x) + end +end + +def fun_l12_n781(x) + if (x < 1) + fun_l13_n63(x) + else + fun_l13_n776(x) + end +end + +def fun_l12_n782(x) + if (x < 1) + fun_l13_n146(x) + else + fun_l13_n32(x) + end +end + +def fun_l12_n783(x) + if (x < 1) + fun_l13_n452(x) + else + fun_l13_n621(x) + end +end + +def fun_l12_n784(x) + if (x < 1) + fun_l13_n821(x) + else + fun_l13_n454(x) + end +end + +def fun_l12_n785(x) + if (x < 1) + fun_l13_n943(x) + else + fun_l13_n835(x) + end +end + +def fun_l12_n786(x) + if (x < 1) + fun_l13_n47(x) + else + fun_l13_n252(x) + end +end + +def fun_l12_n787(x) + if (x < 1) + fun_l13_n759(x) + else + fun_l13_n820(x) + end +end + +def fun_l12_n788(x) + if (x < 1) + fun_l13_n883(x) + else + fun_l13_n218(x) + end +end + +def fun_l12_n789(x) + if (x < 1) + fun_l13_n10(x) + else + fun_l13_n765(x) + end +end + +def fun_l12_n790(x) + if (x < 1) + fun_l13_n6(x) + else + fun_l13_n424(x) + end +end + +def fun_l12_n791(x) + if (x < 1) + fun_l13_n645(x) + else + fun_l13_n598(x) + end +end + +def fun_l12_n792(x) + if (x < 1) + fun_l13_n237(x) + else + fun_l13_n141(x) + end +end + +def fun_l12_n793(x) + if (x < 1) + fun_l13_n793(x) + else + fun_l13_n109(x) + end +end + +def fun_l12_n794(x) + if (x < 1) + fun_l13_n404(x) + else + fun_l13_n864(x) + end +end + +def fun_l12_n795(x) + if (x < 1) + fun_l13_n511(x) + else + fun_l13_n620(x) + end +end + +def fun_l12_n796(x) + if (x < 1) + fun_l13_n880(x) + else + fun_l13_n330(x) + end +end + +def fun_l12_n797(x) + if (x < 1) + fun_l13_n637(x) + else + fun_l13_n13(x) + end +end + +def fun_l12_n798(x) + if (x < 1) + fun_l13_n567(x) + else + fun_l13_n958(x) + end +end + +def fun_l12_n799(x) + if (x < 1) + fun_l13_n715(x) + else + fun_l13_n983(x) + end +end + +def fun_l12_n800(x) + if (x < 1) + fun_l13_n502(x) + else + fun_l13_n600(x) + end +end + +def fun_l12_n801(x) + if (x < 1) + fun_l13_n645(x) + else + fun_l13_n713(x) + end +end + +def fun_l12_n802(x) + if (x < 1) + fun_l13_n804(x) + else + fun_l13_n475(x) + end +end + +def fun_l12_n803(x) + if (x < 1) + fun_l13_n286(x) + else + fun_l13_n135(x) + end +end + +def fun_l12_n804(x) + if (x < 1) + fun_l13_n420(x) + else + fun_l13_n534(x) + end +end + +def fun_l12_n805(x) + if (x < 1) + fun_l13_n345(x) + else + fun_l13_n833(x) + end +end + +def fun_l12_n806(x) + if (x < 1) + fun_l13_n558(x) + else + fun_l13_n831(x) + end +end + +def fun_l12_n807(x) + if (x < 1) + fun_l13_n82(x) + else + fun_l13_n56(x) + end +end + +def fun_l12_n808(x) + if (x < 1) + fun_l13_n809(x) + else + fun_l13_n12(x) + end +end + +def fun_l12_n809(x) + if (x < 1) + fun_l13_n450(x) + else + fun_l13_n326(x) + end +end + +def fun_l12_n810(x) + if (x < 1) + fun_l13_n567(x) + else + fun_l13_n437(x) + end +end + +def fun_l12_n811(x) + if (x < 1) + fun_l13_n880(x) + else + fun_l13_n785(x) + end +end + +def fun_l12_n812(x) + if (x < 1) + fun_l13_n585(x) + else + fun_l13_n610(x) + end +end + +def fun_l12_n813(x) + if (x < 1) + fun_l13_n41(x) + else + fun_l13_n911(x) + end +end + +def fun_l12_n814(x) + if (x < 1) + fun_l13_n438(x) + else + fun_l13_n300(x) + end +end + +def fun_l12_n815(x) + if (x < 1) + fun_l13_n363(x) + else + fun_l13_n357(x) + end +end + +def fun_l12_n816(x) + if (x < 1) + fun_l13_n172(x) + else + fun_l13_n25(x) + end +end + +def fun_l12_n817(x) + if (x < 1) + fun_l13_n593(x) + else + fun_l13_n853(x) + end +end + +def fun_l12_n818(x) + if (x < 1) + fun_l13_n790(x) + else + fun_l13_n575(x) + end +end + +def fun_l12_n819(x) + if (x < 1) + fun_l13_n795(x) + else + fun_l13_n877(x) + end +end + +def fun_l12_n820(x) + if (x < 1) + fun_l13_n563(x) + else + fun_l13_n170(x) + end +end + +def fun_l12_n821(x) + if (x < 1) + fun_l13_n405(x) + else + fun_l13_n985(x) + end +end + +def fun_l12_n822(x) + if (x < 1) + fun_l13_n668(x) + else + fun_l13_n702(x) + end +end + +def fun_l12_n823(x) + if (x < 1) + fun_l13_n210(x) + else + fun_l13_n450(x) + end +end + +def fun_l12_n824(x) + if (x < 1) + fun_l13_n817(x) + else + fun_l13_n693(x) + end +end + +def fun_l12_n825(x) + if (x < 1) + fun_l13_n909(x) + else + fun_l13_n857(x) + end +end + +def fun_l12_n826(x) + if (x < 1) + fun_l13_n944(x) + else + fun_l13_n601(x) + end +end + +def fun_l12_n827(x) + if (x < 1) + fun_l13_n152(x) + else + fun_l13_n187(x) + end +end + +def fun_l12_n828(x) + if (x < 1) + fun_l13_n735(x) + else + fun_l13_n198(x) + end +end + +def fun_l12_n829(x) + if (x < 1) + fun_l13_n892(x) + else + fun_l13_n362(x) + end +end + +def fun_l12_n830(x) + if (x < 1) + fun_l13_n636(x) + else + fun_l13_n779(x) + end +end + +def fun_l12_n831(x) + if (x < 1) + fun_l13_n597(x) + else + fun_l13_n186(x) + end +end + +def fun_l12_n832(x) + if (x < 1) + fun_l13_n680(x) + else + fun_l13_n477(x) + end +end + +def fun_l12_n833(x) + if (x < 1) + fun_l13_n334(x) + else + fun_l13_n508(x) + end +end + +def fun_l12_n834(x) + if (x < 1) + fun_l13_n927(x) + else + fun_l13_n111(x) + end +end + +def fun_l12_n835(x) + if (x < 1) + fun_l13_n424(x) + else + fun_l13_n326(x) + end +end + +def fun_l12_n836(x) + if (x < 1) + fun_l13_n624(x) + else + fun_l13_n270(x) + end +end + +def fun_l12_n837(x) + if (x < 1) + fun_l13_n458(x) + else + fun_l13_n736(x) + end +end + +def fun_l12_n838(x) + if (x < 1) + fun_l13_n881(x) + else + fun_l13_n702(x) + end +end + +def fun_l12_n839(x) + if (x < 1) + fun_l13_n778(x) + else + fun_l13_n374(x) + end +end + +def fun_l12_n840(x) + if (x < 1) + fun_l13_n118(x) + else + fun_l13_n543(x) + end +end + +def fun_l12_n841(x) + if (x < 1) + fun_l13_n270(x) + else + fun_l13_n810(x) + end +end + +def fun_l12_n842(x) + if (x < 1) + fun_l13_n122(x) + else + fun_l13_n905(x) + end +end + +def fun_l12_n843(x) + if (x < 1) + fun_l13_n154(x) + else + fun_l13_n636(x) + end +end + +def fun_l12_n844(x) + if (x < 1) + fun_l13_n603(x) + else + fun_l13_n586(x) + end +end + +def fun_l12_n845(x) + if (x < 1) + fun_l13_n264(x) + else + fun_l13_n492(x) + end +end + +def fun_l12_n846(x) + if (x < 1) + fun_l13_n264(x) + else + fun_l13_n214(x) + end +end + +def fun_l12_n847(x) + if (x < 1) + fun_l13_n337(x) + else + fun_l13_n339(x) + end +end + +def fun_l12_n848(x) + if (x < 1) + fun_l13_n83(x) + else + fun_l13_n454(x) + end +end + +def fun_l12_n849(x) + if (x < 1) + fun_l13_n129(x) + else + fun_l13_n30(x) + end +end + +def fun_l12_n850(x) + if (x < 1) + fun_l13_n602(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n851(x) + if (x < 1) + fun_l13_n650(x) + else + fun_l13_n715(x) + end +end + +def fun_l12_n852(x) + if (x < 1) + fun_l13_n482(x) + else + fun_l13_n852(x) + end +end + +def fun_l12_n853(x) + if (x < 1) + fun_l13_n946(x) + else + fun_l13_n393(x) + end +end + +def fun_l12_n854(x) + if (x < 1) + fun_l13_n16(x) + else + fun_l13_n512(x) + end +end + +def fun_l12_n855(x) + if (x < 1) + fun_l13_n469(x) + else + fun_l13_n567(x) + end +end + +def fun_l12_n856(x) + if (x < 1) + fun_l13_n531(x) + else + fun_l13_n39(x) + end +end + +def fun_l12_n857(x) + if (x < 1) + fun_l13_n673(x) + else + fun_l13_n670(x) + end +end + +def fun_l12_n858(x) + if (x < 1) + fun_l13_n83(x) + else + fun_l13_n588(x) + end +end + +def fun_l12_n859(x) + if (x < 1) + fun_l13_n247(x) + else + fun_l13_n460(x) + end +end + +def fun_l12_n860(x) + if (x < 1) + fun_l13_n621(x) + else + fun_l13_n229(x) + end +end + +def fun_l12_n861(x) + if (x < 1) + fun_l13_n121(x) + else + fun_l13_n147(x) + end +end + +def fun_l12_n862(x) + if (x < 1) + fun_l13_n293(x) + else + fun_l13_n976(x) + end +end + +def fun_l12_n863(x) + if (x < 1) + fun_l13_n64(x) + else + fun_l13_n569(x) + end +end + +def fun_l12_n864(x) + if (x < 1) + fun_l13_n802(x) + else + fun_l13_n962(x) + end +end + +def fun_l12_n865(x) + if (x < 1) + fun_l13_n406(x) + else + fun_l13_n571(x) + end +end + +def fun_l12_n866(x) + if (x < 1) + fun_l13_n798(x) + else + fun_l13_n418(x) + end +end + +def fun_l12_n867(x) + if (x < 1) + fun_l13_n725(x) + else + fun_l13_n716(x) + end +end + +def fun_l12_n868(x) + if (x < 1) + fun_l13_n245(x) + else + fun_l13_n154(x) + end +end + +def fun_l12_n869(x) + if (x < 1) + fun_l13_n954(x) + else + fun_l13_n242(x) + end +end + +def fun_l12_n870(x) + if (x < 1) + fun_l13_n649(x) + else + fun_l13_n160(x) + end +end + +def fun_l12_n871(x) + if (x < 1) + fun_l13_n700(x) + else + fun_l13_n863(x) + end +end + +def fun_l12_n872(x) + if (x < 1) + fun_l13_n60(x) + else + fun_l13_n359(x) + end +end + +def fun_l12_n873(x) + if (x < 1) + fun_l13_n820(x) + else + fun_l13_n247(x) + end +end + +def fun_l12_n874(x) + if (x < 1) + fun_l13_n294(x) + else + fun_l13_n179(x) + end +end + +def fun_l12_n875(x) + if (x < 1) + fun_l13_n599(x) + else + fun_l13_n309(x) + end +end + +def fun_l12_n876(x) + if (x < 1) + fun_l13_n922(x) + else + fun_l13_n632(x) + end +end + +def fun_l12_n877(x) + if (x < 1) + fun_l13_n921(x) + else + fun_l13_n200(x) + end +end + +def fun_l12_n878(x) + if (x < 1) + fun_l13_n375(x) + else + fun_l13_n109(x) + end +end + +def fun_l12_n879(x) + if (x < 1) + fun_l13_n771(x) + else + fun_l13_n758(x) + end +end + +def fun_l12_n880(x) + if (x < 1) + fun_l13_n887(x) + else + fun_l13_n958(x) + end +end + +def fun_l12_n881(x) + if (x < 1) + fun_l13_n668(x) + else + fun_l13_n508(x) + end +end + +def fun_l12_n882(x) + if (x < 1) + fun_l13_n822(x) + else + fun_l13_n933(x) + end +end + +def fun_l12_n883(x) + if (x < 1) + fun_l13_n328(x) + else + fun_l13_n152(x) + end +end + +def fun_l12_n884(x) + if (x < 1) + fun_l13_n978(x) + else + fun_l13_n282(x) + end +end + +def fun_l12_n885(x) + if (x < 1) + fun_l13_n91(x) + else + fun_l13_n592(x) + end +end + +def fun_l12_n886(x) + if (x < 1) + fun_l13_n844(x) + else + fun_l13_n254(x) + end +end + +def fun_l12_n887(x) + if (x < 1) + fun_l13_n49(x) + else + fun_l13_n430(x) + end +end + +def fun_l12_n888(x) + if (x < 1) + fun_l13_n653(x) + else + fun_l13_n612(x) + end +end + +def fun_l12_n889(x) + if (x < 1) + fun_l13_n352(x) + else + fun_l13_n228(x) + end +end + +def fun_l12_n890(x) + if (x < 1) + fun_l13_n952(x) + else + fun_l13_n505(x) + end +end + +def fun_l12_n891(x) + if (x < 1) + fun_l13_n381(x) + else + fun_l13_n799(x) + end +end + +def fun_l12_n892(x) + if (x < 1) + fun_l13_n160(x) + else + fun_l13_n78(x) + end +end + +def fun_l12_n893(x) + if (x < 1) + fun_l13_n554(x) + else + fun_l13_n383(x) + end +end + +def fun_l12_n894(x) + if (x < 1) + fun_l13_n475(x) + else + fun_l13_n853(x) + end +end + +def fun_l12_n895(x) + if (x < 1) + fun_l13_n588(x) + else + fun_l13_n452(x) + end +end + +def fun_l12_n896(x) + if (x < 1) + fun_l13_n991(x) + else + fun_l13_n758(x) + end +end + +def fun_l12_n897(x) + if (x < 1) + fun_l13_n808(x) + else + fun_l13_n742(x) + end +end + +def fun_l12_n898(x) + if (x < 1) + fun_l13_n654(x) + else + fun_l13_n772(x) + end +end + +def fun_l12_n899(x) + if (x < 1) + fun_l13_n365(x) + else + fun_l13_n3(x) + end +end + +def fun_l12_n900(x) + if (x < 1) + fun_l13_n322(x) + else + fun_l13_n143(x) + end +end + +def fun_l12_n901(x) + if (x < 1) + fun_l13_n833(x) + else + fun_l13_n19(x) + end +end + +def fun_l12_n902(x) + if (x < 1) + fun_l13_n796(x) + else + fun_l13_n140(x) + end +end + +def fun_l12_n903(x) + if (x < 1) + fun_l13_n866(x) + else + fun_l13_n227(x) + end +end + +def fun_l12_n904(x) + if (x < 1) + fun_l13_n814(x) + else + fun_l13_n714(x) + end +end + +def fun_l12_n905(x) + if (x < 1) + fun_l13_n841(x) + else + fun_l13_n802(x) + end +end + +def fun_l12_n906(x) + if (x < 1) + fun_l13_n212(x) + else + fun_l13_n14(x) + end +end + +def fun_l12_n907(x) + if (x < 1) + fun_l13_n35(x) + else + fun_l13_n952(x) + end +end + +def fun_l12_n908(x) + if (x < 1) + fun_l13_n181(x) + else + fun_l13_n539(x) + end +end + +def fun_l12_n909(x) + if (x < 1) + fun_l13_n770(x) + else + fun_l13_n80(x) + end +end + +def fun_l12_n910(x) + if (x < 1) + fun_l13_n421(x) + else + fun_l13_n512(x) + end +end + +def fun_l12_n911(x) + if (x < 1) + fun_l13_n710(x) + else + fun_l13_n666(x) + end +end + +def fun_l12_n912(x) + if (x < 1) + fun_l13_n319(x) + else + fun_l13_n491(x) + end +end + +def fun_l12_n913(x) + if (x < 1) + fun_l13_n924(x) + else + fun_l13_n198(x) + end +end + +def fun_l12_n914(x) + if (x < 1) + fun_l13_n707(x) + else + fun_l13_n91(x) + end +end + +def fun_l12_n915(x) + if (x < 1) + fun_l13_n29(x) + else + fun_l13_n134(x) + end +end + +def fun_l12_n916(x) + if (x < 1) + fun_l13_n314(x) + else + fun_l13_n831(x) + end +end + +def fun_l12_n917(x) + if (x < 1) + fun_l13_n986(x) + else + fun_l13_n732(x) + end +end + +def fun_l12_n918(x) + if (x < 1) + fun_l13_n787(x) + else + fun_l13_n232(x) + end +end + +def fun_l12_n919(x) + if (x < 1) + fun_l13_n452(x) + else + fun_l13_n386(x) + end +end + +def fun_l12_n920(x) + if (x < 1) + fun_l13_n12(x) + else + fun_l13_n264(x) + end +end + +def fun_l12_n921(x) + if (x < 1) + fun_l13_n734(x) + else + fun_l13_n885(x) + end +end + +def fun_l12_n922(x) + if (x < 1) + fun_l13_n180(x) + else + fun_l13_n509(x) + end +end + +def fun_l12_n923(x) + if (x < 1) + fun_l13_n783(x) + else + fun_l13_n212(x) + end +end + +def fun_l12_n924(x) + if (x < 1) + fun_l13_n623(x) + else + fun_l13_n159(x) + end +end + +def fun_l12_n925(x) + if (x < 1) + fun_l13_n361(x) + else + fun_l13_n47(x) + end +end + +def fun_l12_n926(x) + if (x < 1) + fun_l13_n355(x) + else + fun_l13_n337(x) + end +end + +def fun_l12_n927(x) + if (x < 1) + fun_l13_n892(x) + else + fun_l13_n814(x) + end +end + +def fun_l12_n928(x) + if (x < 1) + fun_l13_n173(x) + else + fun_l13_n613(x) + end +end + +def fun_l12_n929(x) + if (x < 1) + fun_l13_n140(x) + else + fun_l13_n782(x) + end +end + +def fun_l12_n930(x) + if (x < 1) + fun_l13_n964(x) + else + fun_l13_n830(x) + end +end + +def fun_l12_n931(x) + if (x < 1) + fun_l13_n110(x) + else + fun_l13_n767(x) + end +end + +def fun_l12_n932(x) + if (x < 1) + fun_l13_n738(x) + else + fun_l13_n73(x) + end +end + +def fun_l12_n933(x) + if (x < 1) + fun_l13_n92(x) + else + fun_l13_n113(x) + end +end + +def fun_l12_n934(x) + if (x < 1) + fun_l13_n377(x) + else + fun_l13_n464(x) + end +end + +def fun_l12_n935(x) + if (x < 1) + fun_l13_n544(x) + else + fun_l13_n808(x) + end +end + +def fun_l12_n936(x) + if (x < 1) + fun_l13_n36(x) + else + fun_l13_n343(x) + end +end + +def fun_l12_n937(x) + if (x < 1) + fun_l13_n745(x) + else + fun_l13_n342(x) + end +end + +def fun_l12_n938(x) + if (x < 1) + fun_l13_n238(x) + else + fun_l13_n703(x) + end +end + +def fun_l12_n939(x) + if (x < 1) + fun_l13_n229(x) + else + fun_l13_n118(x) + end +end + +def fun_l12_n940(x) + if (x < 1) + fun_l13_n90(x) + else + fun_l13_n0(x) + end +end + +def fun_l12_n941(x) + if (x < 1) + fun_l13_n586(x) + else + fun_l13_n99(x) + end +end + +def fun_l12_n942(x) + if (x < 1) + fun_l13_n755(x) + else + fun_l13_n573(x) + end +end + +def fun_l12_n943(x) + if (x < 1) + fun_l13_n74(x) + else + fun_l13_n805(x) + end +end + +def fun_l12_n944(x) + if (x < 1) + fun_l13_n574(x) + else + fun_l13_n876(x) + end +end + +def fun_l12_n945(x) + if (x < 1) + fun_l13_n0(x) + else + fun_l13_n478(x) + end +end + +def fun_l12_n946(x) + if (x < 1) + fun_l13_n536(x) + else + fun_l13_n957(x) + end +end + +def fun_l12_n947(x) + if (x < 1) + fun_l13_n644(x) + else + fun_l13_n285(x) + end +end + +def fun_l12_n948(x) + if (x < 1) + fun_l13_n215(x) + else + fun_l13_n914(x) + end +end + +def fun_l12_n949(x) + if (x < 1) + fun_l13_n265(x) + else + fun_l13_n262(x) + end +end + +def fun_l12_n950(x) + if (x < 1) + fun_l13_n44(x) + else + fun_l13_n917(x) + end +end + +def fun_l12_n951(x) + if (x < 1) + fun_l13_n222(x) + else + fun_l13_n53(x) + end +end + +def fun_l12_n952(x) + if (x < 1) + fun_l13_n149(x) + else + fun_l13_n11(x) + end +end + +def fun_l12_n953(x) + if (x < 1) + fun_l13_n827(x) + else + fun_l13_n737(x) + end +end + +def fun_l12_n954(x) + if (x < 1) + fun_l13_n655(x) + else + fun_l13_n308(x) + end +end + +def fun_l12_n955(x) + if (x < 1) + fun_l13_n108(x) + else + fun_l13_n940(x) + end +end + +def fun_l12_n956(x) + if (x < 1) + fun_l13_n236(x) + else + fun_l13_n259(x) + end +end + +def fun_l12_n957(x) + if (x < 1) + fun_l13_n886(x) + else + fun_l13_n955(x) + end +end + +def fun_l12_n958(x) + if (x < 1) + fun_l13_n688(x) + else + fun_l13_n391(x) + end +end + +def fun_l12_n959(x) + if (x < 1) + fun_l13_n521(x) + else + fun_l13_n395(x) + end +end + +def fun_l12_n960(x) + if (x < 1) + fun_l13_n877(x) + else + fun_l13_n808(x) + end +end + +def fun_l12_n961(x) + if (x < 1) + fun_l13_n29(x) + else + fun_l13_n422(x) + end +end + +def fun_l12_n962(x) + if (x < 1) + fun_l13_n417(x) + else + fun_l13_n310(x) + end +end + +def fun_l12_n963(x) + if (x < 1) + fun_l13_n987(x) + else + fun_l13_n462(x) + end +end + +def fun_l12_n964(x) + if (x < 1) + fun_l13_n914(x) + else + fun_l13_n115(x) + end +end + +def fun_l12_n965(x) + if (x < 1) + fun_l13_n895(x) + else + fun_l13_n504(x) + end +end + +def fun_l12_n966(x) + if (x < 1) + fun_l13_n304(x) + else + fun_l13_n788(x) + end +end + +def fun_l12_n967(x) + if (x < 1) + fun_l13_n354(x) + else + fun_l13_n592(x) + end +end + +def fun_l12_n968(x) + if (x < 1) + fun_l13_n231(x) + else + fun_l13_n214(x) + end +end + +def fun_l12_n969(x) + if (x < 1) + fun_l13_n435(x) + else + fun_l13_n779(x) + end +end + +def fun_l12_n970(x) + if (x < 1) + fun_l13_n261(x) + else + fun_l13_n139(x) + end +end + +def fun_l12_n971(x) + if (x < 1) + fun_l13_n320(x) + else + fun_l13_n749(x) + end +end + +def fun_l12_n972(x) + if (x < 1) + fun_l13_n56(x) + else + fun_l13_n207(x) + end +end + +def fun_l12_n973(x) + if (x < 1) + fun_l13_n238(x) + else + fun_l13_n637(x) + end +end + +def fun_l12_n974(x) + if (x < 1) + fun_l13_n474(x) + else + fun_l13_n512(x) + end +end + +def fun_l12_n975(x) + if (x < 1) + fun_l13_n552(x) + else + fun_l13_n355(x) + end +end + +def fun_l12_n976(x) + if (x < 1) + fun_l13_n127(x) + else + fun_l13_n571(x) + end +end + +def fun_l12_n977(x) + if (x < 1) + fun_l13_n261(x) + else + fun_l13_n845(x) + end +end + +def fun_l12_n978(x) + if (x < 1) + fun_l13_n280(x) + else + fun_l13_n465(x) + end +end + +def fun_l12_n979(x) + if (x < 1) + fun_l13_n249(x) + else + fun_l13_n66(x) + end +end + +def fun_l12_n980(x) + if (x < 1) + fun_l13_n306(x) + else + fun_l13_n53(x) + end +end + +def fun_l12_n981(x) + if (x < 1) + fun_l13_n827(x) + else + fun_l13_n395(x) + end +end + +def fun_l12_n982(x) + if (x < 1) + fun_l13_n858(x) + else + fun_l13_n644(x) + end +end + +def fun_l12_n983(x) + if (x < 1) + fun_l13_n50(x) + else + fun_l13_n671(x) + end +end + +def fun_l12_n984(x) + if (x < 1) + fun_l13_n629(x) + else + fun_l13_n55(x) + end +end + +def fun_l12_n985(x) + if (x < 1) + fun_l13_n73(x) + else + fun_l13_n958(x) + end +end + +def fun_l12_n986(x) + if (x < 1) + fun_l13_n197(x) + else + fun_l13_n444(x) + end +end + +def fun_l12_n987(x) + if (x < 1) + fun_l13_n108(x) + else + fun_l13_n898(x) + end +end + +def fun_l12_n988(x) + if (x < 1) + fun_l13_n153(x) + else + fun_l13_n278(x) + end +end + +def fun_l12_n989(x) + if (x < 1) + fun_l13_n764(x) + else + fun_l13_n712(x) + end +end + +def fun_l12_n990(x) + if (x < 1) + fun_l13_n711(x) + else + fun_l13_n825(x) + end +end + +def fun_l12_n991(x) + if (x < 1) + fun_l13_n767(x) + else + fun_l13_n169(x) + end +end + +def fun_l12_n992(x) + if (x < 1) + fun_l13_n917(x) + else + fun_l13_n524(x) + end +end + +def fun_l12_n993(x) + if (x < 1) + fun_l13_n589(x) + else + fun_l13_n695(x) + end +end + +def fun_l12_n994(x) + if (x < 1) + fun_l13_n733(x) + else + fun_l13_n764(x) + end +end + +def fun_l12_n995(x) + if (x < 1) + fun_l13_n86(x) + else + fun_l13_n547(x) + end +end + +def fun_l12_n996(x) + if (x < 1) + fun_l13_n236(x) + else + fun_l13_n197(x) + end +end + +def fun_l12_n997(x) + if (x < 1) + fun_l13_n592(x) + else + fun_l13_n313(x) + end +end + +def fun_l12_n998(x) + if (x < 1) + fun_l13_n878(x) + else + fun_l13_n439(x) + end +end + +def fun_l12_n999(x) + if (x < 1) + fun_l13_n904(x) + else + fun_l13_n651(x) + end +end + +def fun_l13_n0(x) + if (x < 1) + fun_l14_n72(x) + else + fun_l14_n951(x) + end +end + +def fun_l13_n1(x) + if (x < 1) + fun_l14_n950(x) + else + fun_l14_n170(x) + end +end + +def fun_l13_n2(x) + if (x < 1) + fun_l14_n773(x) + else + fun_l14_n351(x) + end +end + +def fun_l13_n3(x) + if (x < 1) + fun_l14_n814(x) + else + fun_l14_n304(x) + end +end + +def fun_l13_n4(x) + if (x < 1) + fun_l14_n395(x) + else + fun_l14_n187(x) + end +end + +def fun_l13_n5(x) + if (x < 1) + fun_l14_n60(x) + else + fun_l14_n165(x) + end +end + +def fun_l13_n6(x) + if (x < 1) + fun_l14_n711(x) + else + fun_l14_n815(x) + end +end + +def fun_l13_n7(x) + if (x < 1) + fun_l14_n396(x) + else + fun_l14_n614(x) + end +end + +def fun_l13_n8(x) + if (x < 1) + fun_l14_n477(x) + else + fun_l14_n427(x) + end +end + +def fun_l13_n9(x) + if (x < 1) + fun_l14_n803(x) + else + fun_l14_n655(x) + end +end + +def fun_l13_n10(x) + if (x < 1) + fun_l14_n261(x) + else + fun_l14_n324(x) + end +end + +def fun_l13_n11(x) + if (x < 1) + fun_l14_n485(x) + else + fun_l14_n302(x) + end +end + +def fun_l13_n12(x) + if (x < 1) + fun_l14_n324(x) + else + fun_l14_n840(x) + end +end + +def fun_l13_n13(x) + if (x < 1) + fun_l14_n811(x) + else + fun_l14_n357(x) + end +end + +def fun_l13_n14(x) + if (x < 1) + fun_l14_n736(x) + else + fun_l14_n763(x) + end +end + +def fun_l13_n15(x) + if (x < 1) + fun_l14_n572(x) + else + fun_l14_n557(x) + end +end + +def fun_l13_n16(x) + if (x < 1) + fun_l14_n406(x) + else + fun_l14_n200(x) + end +end + +def fun_l13_n17(x) + if (x < 1) + fun_l14_n500(x) + else + fun_l14_n480(x) + end +end + +def fun_l13_n18(x) + if (x < 1) + fun_l14_n215(x) + else + fun_l14_n241(x) + end +end + +def fun_l13_n19(x) + if (x < 1) + fun_l14_n341(x) + else + fun_l14_n142(x) + end +end + +def fun_l13_n20(x) + if (x < 1) + fun_l14_n649(x) + else + fun_l14_n853(x) + end +end + +def fun_l13_n21(x) + if (x < 1) + fun_l14_n153(x) + else + fun_l14_n295(x) + end +end + +def fun_l13_n22(x) + if (x < 1) + fun_l14_n210(x) + else + fun_l14_n947(x) + end +end + +def fun_l13_n23(x) + if (x < 1) + fun_l14_n764(x) + else + fun_l14_n810(x) + end +end + +def fun_l13_n24(x) + if (x < 1) + fun_l14_n96(x) + else + fun_l14_n359(x) + end +end + +def fun_l13_n25(x) + if (x < 1) + fun_l14_n542(x) + else + fun_l14_n506(x) + end +end + +def fun_l13_n26(x) + if (x < 1) + fun_l14_n583(x) + else + fun_l14_n754(x) + end +end + +def fun_l13_n27(x) + if (x < 1) + fun_l14_n881(x) + else + fun_l14_n693(x) + end +end + +def fun_l13_n28(x) + if (x < 1) + fun_l14_n385(x) + else + fun_l14_n628(x) + end +end + +def fun_l13_n29(x) + if (x < 1) + fun_l14_n429(x) + else + fun_l14_n370(x) + end +end + +def fun_l13_n30(x) + if (x < 1) + fun_l14_n484(x) + else + fun_l14_n724(x) + end +end + +def fun_l13_n31(x) + if (x < 1) + fun_l14_n328(x) + else + fun_l14_n857(x) + end +end + +def fun_l13_n32(x) + if (x < 1) + fun_l14_n367(x) + else + fun_l14_n441(x) + end +end + +def fun_l13_n33(x) + if (x < 1) + fun_l14_n322(x) + else + fun_l14_n390(x) + end +end + +def fun_l13_n34(x) + if (x < 1) + fun_l14_n935(x) + else + fun_l14_n46(x) + end +end + +def fun_l13_n35(x) + if (x < 1) + fun_l14_n274(x) + else + fun_l14_n536(x) + end +end + +def fun_l13_n36(x) + if (x < 1) + fun_l14_n645(x) + else + fun_l14_n396(x) + end +end + +def fun_l13_n37(x) + if (x < 1) + fun_l14_n905(x) + else + fun_l14_n19(x) + end +end + +def fun_l13_n38(x) + if (x < 1) + fun_l14_n562(x) + else + fun_l14_n983(x) + end +end + +def fun_l13_n39(x) + if (x < 1) + fun_l14_n846(x) + else + fun_l14_n140(x) + end +end + +def fun_l13_n40(x) + if (x < 1) + fun_l14_n308(x) + else + fun_l14_n968(x) + end +end + +def fun_l13_n41(x) + if (x < 1) + fun_l14_n299(x) + else + fun_l14_n364(x) + end +end + +def fun_l13_n42(x) + if (x < 1) + fun_l14_n266(x) + else + fun_l14_n368(x) + end +end + +def fun_l13_n43(x) + if (x < 1) + fun_l14_n216(x) + else + fun_l14_n894(x) + end +end + +def fun_l13_n44(x) + if (x < 1) + fun_l14_n30(x) + else + fun_l14_n118(x) + end +end + +def fun_l13_n45(x) + if (x < 1) + fun_l14_n66(x) + else + fun_l14_n677(x) + end +end + +def fun_l13_n46(x) + if (x < 1) + fun_l14_n415(x) + else + fun_l14_n311(x) + end +end + +def fun_l13_n47(x) + if (x < 1) + fun_l14_n63(x) + else + fun_l14_n410(x) + end +end + +def fun_l13_n48(x) + if (x < 1) + fun_l14_n640(x) + else + fun_l14_n161(x) + end +end + +def fun_l13_n49(x) + if (x < 1) + fun_l14_n546(x) + else + fun_l14_n655(x) + end +end + +def fun_l13_n50(x) + if (x < 1) + fun_l14_n102(x) + else + fun_l14_n791(x) + end +end + +def fun_l13_n51(x) + if (x < 1) + fun_l14_n333(x) + else + fun_l14_n641(x) + end +end + +def fun_l13_n52(x) + if (x < 1) + fun_l14_n16(x) + else + fun_l14_n653(x) + end +end + +def fun_l13_n53(x) + if (x < 1) + fun_l14_n842(x) + else + fun_l14_n780(x) + end +end + +def fun_l13_n54(x) + if (x < 1) + fun_l14_n663(x) + else + fun_l14_n903(x) + end +end + +def fun_l13_n55(x) + if (x < 1) + fun_l14_n745(x) + else + fun_l14_n925(x) + end +end + +def fun_l13_n56(x) + if (x < 1) + fun_l14_n688(x) + else + fun_l14_n930(x) + end +end + +def fun_l13_n57(x) + if (x < 1) + fun_l14_n58(x) + else + fun_l14_n864(x) + end +end + +def fun_l13_n58(x) + if (x < 1) + fun_l14_n107(x) + else + fun_l14_n197(x) + end +end + +def fun_l13_n59(x) + if (x < 1) + fun_l14_n334(x) + else + fun_l14_n147(x) + end +end + +def fun_l13_n60(x) + if (x < 1) + fun_l14_n814(x) + else + fun_l14_n417(x) + end +end + +def fun_l13_n61(x) + if (x < 1) + fun_l14_n696(x) + else + fun_l14_n973(x) + end +end + +def fun_l13_n62(x) + if (x < 1) + fun_l14_n378(x) + else + fun_l14_n968(x) + end +end + +def fun_l13_n63(x) + if (x < 1) + fun_l14_n107(x) + else + fun_l14_n100(x) + end +end + +def fun_l13_n64(x) + if (x < 1) + fun_l14_n105(x) + else + fun_l14_n393(x) + end +end + +def fun_l13_n65(x) + if (x < 1) + fun_l14_n833(x) + else + fun_l14_n424(x) + end +end + +def fun_l13_n66(x) + if (x < 1) + fun_l14_n125(x) + else + fun_l14_n697(x) + end +end + +def fun_l13_n67(x) + if (x < 1) + fun_l14_n684(x) + else + fun_l14_n458(x) + end +end + +def fun_l13_n68(x) + if (x < 1) + fun_l14_n301(x) + else + fun_l14_n711(x) + end +end + +def fun_l13_n69(x) + if (x < 1) + fun_l14_n131(x) + else + fun_l14_n552(x) + end +end + +def fun_l13_n70(x) + if (x < 1) + fun_l14_n425(x) + else + fun_l14_n241(x) + end +end + +def fun_l13_n71(x) + if (x < 1) + fun_l14_n531(x) + else + fun_l14_n364(x) + end +end + +def fun_l13_n72(x) + if (x < 1) + fun_l14_n801(x) + else + fun_l14_n951(x) + end +end + +def fun_l13_n73(x) + if (x < 1) + fun_l14_n415(x) + else + fun_l14_n294(x) + end +end + +def fun_l13_n74(x) + if (x < 1) + fun_l14_n715(x) + else + fun_l14_n606(x) + end +end + +def fun_l13_n75(x) + if (x < 1) + fun_l14_n932(x) + else + fun_l14_n928(x) + end +end + +def fun_l13_n76(x) + if (x < 1) + fun_l14_n930(x) + else + fun_l14_n102(x) + end +end + +def fun_l13_n77(x) + if (x < 1) + fun_l14_n293(x) + else + fun_l14_n301(x) + end +end + +def fun_l13_n78(x) + if (x < 1) + fun_l14_n270(x) + else + fun_l14_n715(x) + end +end + +def fun_l13_n79(x) + if (x < 1) + fun_l14_n862(x) + else + fun_l14_n589(x) + end +end + +def fun_l13_n80(x) + if (x < 1) + fun_l14_n337(x) + else + fun_l14_n940(x) + end +end + +def fun_l13_n81(x) + if (x < 1) + fun_l14_n394(x) + else + fun_l14_n902(x) + end +end + +def fun_l13_n82(x) + if (x < 1) + fun_l14_n468(x) + else + fun_l14_n816(x) + end +end + +def fun_l13_n83(x) + if (x < 1) + fun_l14_n517(x) + else + fun_l14_n633(x) + end +end + +def fun_l13_n84(x) + if (x < 1) + fun_l14_n312(x) + else + fun_l14_n473(x) + end +end + +def fun_l13_n85(x) + if (x < 1) + fun_l14_n377(x) + else + fun_l14_n616(x) + end +end + +def fun_l13_n86(x) + if (x < 1) + fun_l14_n541(x) + else + fun_l14_n77(x) + end +end + +def fun_l13_n87(x) + if (x < 1) + fun_l14_n66(x) + else + fun_l14_n162(x) + end +end + +def fun_l13_n88(x) + if (x < 1) + fun_l14_n202(x) + else + fun_l14_n158(x) + end +end + +def fun_l13_n89(x) + if (x < 1) + fun_l14_n549(x) + else + fun_l14_n947(x) + end +end + +def fun_l13_n90(x) + if (x < 1) + fun_l14_n82(x) + else + fun_l14_n747(x) + end +end + +def fun_l13_n91(x) + if (x < 1) + fun_l14_n374(x) + else + fun_l14_n738(x) + end +end + +def fun_l13_n92(x) + if (x < 1) + fun_l14_n124(x) + else + fun_l14_n673(x) + end +end + +def fun_l13_n93(x) + if (x < 1) + fun_l14_n405(x) + else + fun_l14_n562(x) + end +end + +def fun_l13_n94(x) + if (x < 1) + fun_l14_n766(x) + else + fun_l14_n466(x) + end +end + +def fun_l13_n95(x) + if (x < 1) + fun_l14_n908(x) + else + fun_l14_n208(x) + end +end + +def fun_l13_n96(x) + if (x < 1) + fun_l14_n439(x) + else + fun_l14_n964(x) + end +end + +def fun_l13_n97(x) + if (x < 1) + fun_l14_n529(x) + else + fun_l14_n374(x) + end +end + +def fun_l13_n98(x) + if (x < 1) + fun_l14_n723(x) + else + fun_l14_n464(x) + end +end + +def fun_l13_n99(x) + if (x < 1) + fun_l14_n849(x) + else + fun_l14_n951(x) + end +end + +def fun_l13_n100(x) + if (x < 1) + fun_l14_n797(x) + else + fun_l14_n421(x) + end +end + +def fun_l13_n101(x) + if (x < 1) + fun_l14_n989(x) + else + fun_l14_n392(x) + end +end + +def fun_l13_n102(x) + if (x < 1) + fun_l14_n8(x) + else + fun_l14_n913(x) + end +end + +def fun_l13_n103(x) + if (x < 1) + fun_l14_n498(x) + else + fun_l14_n248(x) + end +end + +def fun_l13_n104(x) + if (x < 1) + fun_l14_n989(x) + else + fun_l14_n83(x) + end +end + +def fun_l13_n105(x) + if (x < 1) + fun_l14_n943(x) + else + fun_l14_n358(x) + end +end + +def fun_l13_n106(x) + if (x < 1) + fun_l14_n252(x) + else + fun_l14_n626(x) + end +end + +def fun_l13_n107(x) + if (x < 1) + fun_l14_n495(x) + else + fun_l14_n627(x) + end +end + +def fun_l13_n108(x) + if (x < 1) + fun_l14_n286(x) + else + fun_l14_n500(x) + end +end + +def fun_l13_n109(x) + if (x < 1) + fun_l14_n927(x) + else + fun_l14_n627(x) + end +end + +def fun_l13_n110(x) + if (x < 1) + fun_l14_n103(x) + else + fun_l14_n319(x) + end +end + +def fun_l13_n111(x) + if (x < 1) + fun_l14_n730(x) + else + fun_l14_n960(x) + end +end + +def fun_l13_n112(x) + if (x < 1) + fun_l14_n188(x) + else + fun_l14_n145(x) + end +end + +def fun_l13_n113(x) + if (x < 1) + fun_l14_n361(x) + else + fun_l14_n707(x) + end +end + +def fun_l13_n114(x) + if (x < 1) + fun_l14_n629(x) + else + fun_l14_n536(x) + end +end + +def fun_l13_n115(x) + if (x < 1) + fun_l14_n276(x) + else + fun_l14_n244(x) + end +end + +def fun_l13_n116(x) + if (x < 1) + fun_l14_n512(x) + else + fun_l14_n578(x) + end +end + +def fun_l13_n117(x) + if (x < 1) + fun_l14_n448(x) + else + fun_l14_n437(x) + end +end + +def fun_l13_n118(x) + if (x < 1) + fun_l14_n855(x) + else + fun_l14_n617(x) + end +end + +def fun_l13_n119(x) + if (x < 1) + fun_l14_n467(x) + else + fun_l14_n594(x) + end +end + +def fun_l13_n120(x) + if (x < 1) + fun_l14_n54(x) + else + fun_l14_n765(x) + end +end + +def fun_l13_n121(x) + if (x < 1) + fun_l14_n700(x) + else + fun_l14_n189(x) + end +end + +def fun_l13_n122(x) + if (x < 1) + fun_l14_n731(x) + else + fun_l14_n469(x) + end +end + +def fun_l13_n123(x) + if (x < 1) + fun_l14_n6(x) + else + fun_l14_n451(x) + end +end + +def fun_l13_n124(x) + if (x < 1) + fun_l14_n402(x) + else + fun_l14_n445(x) + end +end + +def fun_l13_n125(x) + if (x < 1) + fun_l14_n412(x) + else + fun_l14_n551(x) + end +end + +def fun_l13_n126(x) + if (x < 1) + fun_l14_n295(x) + else + fun_l14_n180(x) + end +end + +def fun_l13_n127(x) + if (x < 1) + fun_l14_n873(x) + else + fun_l14_n209(x) + end +end + +def fun_l13_n128(x) + if (x < 1) + fun_l14_n181(x) + else + fun_l14_n198(x) + end +end + +def fun_l13_n129(x) + if (x < 1) + fun_l14_n817(x) + else + fun_l14_n894(x) + end +end + +def fun_l13_n130(x) + if (x < 1) + fun_l14_n306(x) + else + fun_l14_n429(x) + end +end + +def fun_l13_n131(x) + if (x < 1) + fun_l14_n573(x) + else + fun_l14_n120(x) + end +end + +def fun_l13_n132(x) + if (x < 1) + fun_l14_n433(x) + else + fun_l14_n668(x) + end +end + +def fun_l13_n133(x) + if (x < 1) + fun_l14_n653(x) + else + fun_l14_n934(x) + end +end + +def fun_l13_n134(x) + if (x < 1) + fun_l14_n280(x) + else + fun_l14_n533(x) + end +end + +def fun_l13_n135(x) + if (x < 1) + fun_l14_n471(x) + else + fun_l14_n612(x) + end +end + +def fun_l13_n136(x) + if (x < 1) + fun_l14_n55(x) + else + fun_l14_n684(x) + end +end + +def fun_l13_n137(x) + if (x < 1) + fun_l14_n458(x) + else + fun_l14_n107(x) + end +end + +def fun_l13_n138(x) + if (x < 1) + fun_l14_n415(x) + else + fun_l14_n189(x) + end +end + +def fun_l13_n139(x) + if (x < 1) + fun_l14_n877(x) + else + fun_l14_n862(x) + end +end + +def fun_l13_n140(x) + if (x < 1) + fun_l14_n471(x) + else + fun_l14_n533(x) + end +end + +def fun_l13_n141(x) + if (x < 1) + fun_l14_n817(x) + else + fun_l14_n121(x) + end +end + +def fun_l13_n142(x) + if (x < 1) + fun_l14_n523(x) + else + fun_l14_n894(x) + end +end + +def fun_l13_n143(x) + if (x < 1) + fun_l14_n893(x) + else + fun_l14_n187(x) + end +end + +def fun_l13_n144(x) + if (x < 1) + fun_l14_n921(x) + else + fun_l14_n253(x) + end +end + +def fun_l13_n145(x) + if (x < 1) + fun_l14_n0(x) + else + fun_l14_n608(x) + end +end + +def fun_l13_n146(x) + if (x < 1) + fun_l14_n83(x) + else + fun_l14_n450(x) + end +end + +def fun_l13_n147(x) + if (x < 1) + fun_l14_n689(x) + else + fun_l14_n19(x) + end +end + +def fun_l13_n148(x) + if (x < 1) + fun_l14_n922(x) + else + fun_l14_n417(x) + end +end + +def fun_l13_n149(x) + if (x < 1) + fun_l14_n449(x) + else + fun_l14_n273(x) + end +end + +def fun_l13_n150(x) + if (x < 1) + fun_l14_n601(x) + else + fun_l14_n442(x) + end +end + +def fun_l13_n151(x) + if (x < 1) + fun_l14_n96(x) + else + fun_l14_n552(x) + end +end + +def fun_l13_n152(x) + if (x < 1) + fun_l14_n667(x) + else + fun_l14_n273(x) + end +end + +def fun_l13_n153(x) + if (x < 1) + fun_l14_n445(x) + else + fun_l14_n81(x) + end +end + +def fun_l13_n154(x) + if (x < 1) + fun_l14_n906(x) + else + fun_l14_n960(x) + end +end + +def fun_l13_n155(x) + if (x < 1) + fun_l14_n781(x) + else + fun_l14_n763(x) + end +end + +def fun_l13_n156(x) + if (x < 1) + fun_l14_n201(x) + else + fun_l14_n886(x) + end +end + +def fun_l13_n157(x) + if (x < 1) + fun_l14_n926(x) + else + fun_l14_n852(x) + end +end + +def fun_l13_n158(x) + if (x < 1) + fun_l14_n114(x) + else + fun_l14_n23(x) + end +end + +def fun_l13_n159(x) + if (x < 1) + fun_l14_n967(x) + else + fun_l14_n885(x) + end +end + +def fun_l13_n160(x) + if (x < 1) + fun_l14_n563(x) + else + fun_l14_n309(x) + end +end + +def fun_l13_n161(x) + if (x < 1) + fun_l14_n26(x) + else + fun_l14_n232(x) + end +end + +def fun_l13_n162(x) + if (x < 1) + fun_l14_n212(x) + else + fun_l14_n147(x) + end +end + +def fun_l13_n163(x) + if (x < 1) + fun_l14_n841(x) + else + fun_l14_n636(x) + end +end + +def fun_l13_n164(x) + if (x < 1) + fun_l14_n405(x) + else + fun_l14_n709(x) + end +end + +def fun_l13_n165(x) + if (x < 1) + fun_l14_n803(x) + else + fun_l14_n398(x) + end +end + +def fun_l13_n166(x) + if (x < 1) + fun_l14_n112(x) + else + fun_l14_n197(x) + end +end + +def fun_l13_n167(x) + if (x < 1) + fun_l14_n414(x) + else + fun_l14_n509(x) + end +end + +def fun_l13_n168(x) + if (x < 1) + fun_l14_n585(x) + else + fun_l14_n166(x) + end +end + +def fun_l13_n169(x) + if (x < 1) + fun_l14_n653(x) + else + fun_l14_n581(x) + end +end + +def fun_l13_n170(x) + if (x < 1) + fun_l14_n291(x) + else + fun_l14_n520(x) + end +end + +def fun_l13_n171(x) + if (x < 1) + fun_l14_n920(x) + else + fun_l14_n599(x) + end +end + +def fun_l13_n172(x) + if (x < 1) + fun_l14_n125(x) + else + fun_l14_n84(x) + end +end + +def fun_l13_n173(x) + if (x < 1) + fun_l14_n635(x) + else + fun_l14_n224(x) + end +end + +def fun_l13_n174(x) + if (x < 1) + fun_l14_n23(x) + else + fun_l14_n922(x) + end +end + +def fun_l13_n175(x) + if (x < 1) + fun_l14_n736(x) + else + fun_l14_n685(x) + end +end + +def fun_l13_n176(x) + if (x < 1) + fun_l14_n235(x) + else + fun_l14_n157(x) + end +end + +def fun_l13_n177(x) + if (x < 1) + fun_l14_n284(x) + else + fun_l14_n601(x) + end +end + +def fun_l13_n178(x) + if (x < 1) + fun_l14_n785(x) + else + fun_l14_n498(x) + end +end + +def fun_l13_n179(x) + if (x < 1) + fun_l14_n416(x) + else + fun_l14_n624(x) + end +end + +def fun_l13_n180(x) + if (x < 1) + fun_l14_n747(x) + else + fun_l14_n824(x) + end +end + +def fun_l13_n181(x) + if (x < 1) + fun_l14_n658(x) + else + fun_l14_n814(x) + end +end + +def fun_l13_n182(x) + if (x < 1) + fun_l14_n723(x) + else + fun_l14_n365(x) + end +end + +def fun_l13_n183(x) + if (x < 1) + fun_l14_n772(x) + else + fun_l14_n831(x) + end +end + +def fun_l13_n184(x) + if (x < 1) + fun_l14_n560(x) + else + fun_l14_n933(x) + end +end + +def fun_l13_n185(x) + if (x < 1) + fun_l14_n550(x) + else + fun_l14_n716(x) + end +end + +def fun_l13_n186(x) + if (x < 1) + fun_l14_n72(x) + else + fun_l14_n224(x) + end +end + +def fun_l13_n187(x) + if (x < 1) + fun_l14_n910(x) + else + fun_l14_n31(x) + end +end + +def fun_l13_n188(x) + if (x < 1) + fun_l14_n792(x) + else + fun_l14_n69(x) + end +end + +def fun_l13_n189(x) + if (x < 1) + fun_l14_n42(x) + else + fun_l14_n942(x) + end +end + +def fun_l13_n190(x) + if (x < 1) + fun_l14_n520(x) + else + fun_l14_n826(x) + end +end + +def fun_l13_n191(x) + if (x < 1) + fun_l14_n723(x) + else + fun_l14_n5(x) + end +end + +def fun_l13_n192(x) + if (x < 1) + fun_l14_n448(x) + else + fun_l14_n243(x) + end +end + +def fun_l13_n193(x) + if (x < 1) + fun_l14_n722(x) + else + fun_l14_n450(x) + end +end + +def fun_l13_n194(x) + if (x < 1) + fun_l14_n31(x) + else + fun_l14_n968(x) + end +end + +def fun_l13_n195(x) + if (x < 1) + fun_l14_n381(x) + else + fun_l14_n964(x) + end +end + +def fun_l13_n196(x) + if (x < 1) + fun_l14_n797(x) + else + fun_l14_n216(x) + end +end + +def fun_l13_n197(x) + if (x < 1) + fun_l14_n351(x) + else + fun_l14_n439(x) + end +end + +def fun_l13_n198(x) + if (x < 1) + fun_l14_n983(x) + else + fun_l14_n363(x) + end +end + +def fun_l13_n199(x) + if (x < 1) + fun_l14_n939(x) + else + fun_l14_n806(x) + end +end + +def fun_l13_n200(x) + if (x < 1) + fun_l14_n710(x) + else + fun_l14_n513(x) + end +end + +def fun_l13_n201(x) + if (x < 1) + fun_l14_n431(x) + else + fun_l14_n81(x) + end +end + +def fun_l13_n202(x) + if (x < 1) + fun_l14_n41(x) + else + fun_l14_n916(x) + end +end + +def fun_l13_n203(x) + if (x < 1) + fun_l14_n368(x) + else + fun_l14_n626(x) + end +end + +def fun_l13_n204(x) + if (x < 1) + fun_l14_n505(x) + else + fun_l14_n750(x) + end +end + +def fun_l13_n205(x) + if (x < 1) + fun_l14_n263(x) + else + fun_l14_n636(x) + end +end + +def fun_l13_n206(x) + if (x < 1) + fun_l14_n589(x) + else + fun_l14_n215(x) + end +end + +def fun_l13_n207(x) + if (x < 1) + fun_l14_n435(x) + else + fun_l14_n69(x) + end +end + +def fun_l13_n208(x) + if (x < 1) + fun_l14_n114(x) + else + fun_l14_n222(x) + end +end + +def fun_l13_n209(x) + if (x < 1) + fun_l14_n784(x) + else + fun_l14_n337(x) + end +end + +def fun_l13_n210(x) + if (x < 1) + fun_l14_n434(x) + else + fun_l14_n79(x) + end +end + +def fun_l13_n211(x) + if (x < 1) + fun_l14_n152(x) + else + fun_l14_n428(x) + end +end + +def fun_l13_n212(x) + if (x < 1) + fun_l14_n24(x) + else + fun_l14_n101(x) + end +end + +def fun_l13_n213(x) + if (x < 1) + fun_l14_n880(x) + else + fun_l14_n672(x) + end +end + +def fun_l13_n214(x) + if (x < 1) + fun_l14_n824(x) + else + fun_l14_n351(x) + end +end + +def fun_l13_n215(x) + if (x < 1) + fun_l14_n657(x) + else + fun_l14_n822(x) + end +end + +def fun_l13_n216(x) + if (x < 1) + fun_l14_n603(x) + else + fun_l14_n993(x) + end +end + +def fun_l13_n217(x) + if (x < 1) + fun_l14_n593(x) + else + fun_l14_n808(x) + end +end + +def fun_l13_n218(x) + if (x < 1) + fun_l14_n30(x) + else + fun_l14_n632(x) + end +end + +def fun_l13_n219(x) + if (x < 1) + fun_l14_n175(x) + else + fun_l14_n124(x) + end +end + +def fun_l13_n220(x) + if (x < 1) + fun_l14_n878(x) + else + fun_l14_n342(x) + end +end + +def fun_l13_n221(x) + if (x < 1) + fun_l14_n857(x) + else + fun_l14_n204(x) + end +end + +def fun_l13_n222(x) + if (x < 1) + fun_l14_n29(x) + else + fun_l14_n573(x) + end +end + +def fun_l13_n223(x) + if (x < 1) + fun_l14_n329(x) + else + fun_l14_n35(x) + end +end + +def fun_l13_n224(x) + if (x < 1) + fun_l14_n31(x) + else + fun_l14_n323(x) + end +end + +def fun_l13_n225(x) + if (x < 1) + fun_l14_n921(x) + else + fun_l14_n161(x) + end +end + +def fun_l13_n226(x) + if (x < 1) + fun_l14_n599(x) + else + fun_l14_n566(x) + end +end + +def fun_l13_n227(x) + if (x < 1) + fun_l14_n994(x) + else + fun_l14_n549(x) + end +end + +def fun_l13_n228(x) + if (x < 1) + fun_l14_n989(x) + else + fun_l14_n212(x) + end +end + +def fun_l13_n229(x) + if (x < 1) + fun_l14_n22(x) + else + fun_l14_n656(x) + end +end + +def fun_l13_n230(x) + if (x < 1) + fun_l14_n232(x) + else + fun_l14_n658(x) + end +end + +def fun_l13_n231(x) + if (x < 1) + fun_l14_n522(x) + else + fun_l14_n596(x) + end +end + +def fun_l13_n232(x) + if (x < 1) + fun_l14_n296(x) + else + fun_l14_n53(x) + end +end + +def fun_l13_n233(x) + if (x < 1) + fun_l14_n958(x) + else + fun_l14_n818(x) + end +end + +def fun_l13_n234(x) + if (x < 1) + fun_l14_n267(x) + else + fun_l14_n299(x) + end +end + +def fun_l13_n235(x) + if (x < 1) + fun_l14_n776(x) + else + fun_l14_n99(x) + end +end + +def fun_l13_n236(x) + if (x < 1) + fun_l14_n204(x) + else + fun_l14_n34(x) + end +end + +def fun_l13_n237(x) + if (x < 1) + fun_l14_n704(x) + else + fun_l14_n808(x) + end +end + +def fun_l13_n238(x) + if (x < 1) + fun_l14_n82(x) + else + fun_l14_n352(x) + end +end + +def fun_l13_n239(x) + if (x < 1) + fun_l14_n382(x) + else + fun_l14_n447(x) + end +end + +def fun_l13_n240(x) + if (x < 1) + fun_l14_n200(x) + else + fun_l14_n623(x) + end +end + +def fun_l13_n241(x) + if (x < 1) + fun_l14_n563(x) + else + fun_l14_n259(x) + end +end + +def fun_l13_n242(x) + if (x < 1) + fun_l14_n126(x) + else + fun_l14_n337(x) + end +end + +def fun_l13_n243(x) + if (x < 1) + fun_l14_n287(x) + else + fun_l14_n441(x) + end +end + +def fun_l13_n244(x) + if (x < 1) + fun_l14_n271(x) + else + fun_l14_n961(x) + end +end + +def fun_l13_n245(x) + if (x < 1) + fun_l14_n677(x) + else + fun_l14_n310(x) + end +end + +def fun_l13_n246(x) + if (x < 1) + fun_l14_n504(x) + else + fun_l14_n504(x) + end +end + +def fun_l13_n247(x) + if (x < 1) + fun_l14_n61(x) + else + fun_l14_n560(x) + end +end + +def fun_l13_n248(x) + if (x < 1) + fun_l14_n813(x) + else + fun_l14_n337(x) + end +end + +def fun_l13_n249(x) + if (x < 1) + fun_l14_n89(x) + else + fun_l14_n733(x) + end +end + +def fun_l13_n250(x) + if (x < 1) + fun_l14_n203(x) + else + fun_l14_n342(x) + end +end + +def fun_l13_n251(x) + if (x < 1) + fun_l14_n605(x) + else + fun_l14_n767(x) + end +end + +def fun_l13_n252(x) + if (x < 1) + fun_l14_n35(x) + else + fun_l14_n338(x) + end +end + +def fun_l13_n253(x) + if (x < 1) + fun_l14_n894(x) + else + fun_l14_n905(x) + end +end + +def fun_l13_n254(x) + if (x < 1) + fun_l14_n516(x) + else + fun_l14_n832(x) + end +end + +def fun_l13_n255(x) + if (x < 1) + fun_l14_n106(x) + else + fun_l14_n672(x) + end +end + +def fun_l13_n256(x) + if (x < 1) + fun_l14_n978(x) + else + fun_l14_n940(x) + end +end + +def fun_l13_n257(x) + if (x < 1) + fun_l14_n808(x) + else + fun_l14_n906(x) + end +end + +def fun_l13_n258(x) + if (x < 1) + fun_l14_n435(x) + else + fun_l14_n55(x) + end +end + +def fun_l13_n259(x) + if (x < 1) + fun_l14_n981(x) + else + fun_l14_n550(x) + end +end + +def fun_l13_n260(x) + if (x < 1) + fun_l14_n689(x) + else + fun_l14_n533(x) + end +end + +def fun_l13_n261(x) + if (x < 1) + fun_l14_n995(x) + else + fun_l14_n174(x) + end +end + +def fun_l13_n262(x) + if (x < 1) + fun_l14_n161(x) + else + fun_l14_n357(x) + end +end + +def fun_l13_n263(x) + if (x < 1) + fun_l14_n248(x) + else + fun_l14_n509(x) + end +end + +def fun_l13_n264(x) + if (x < 1) + fun_l14_n521(x) + else + fun_l14_n41(x) + end +end + +def fun_l13_n265(x) + if (x < 1) + fun_l14_n771(x) + else + fun_l14_n387(x) + end +end + +def fun_l13_n266(x) + if (x < 1) + fun_l14_n149(x) + else + fun_l14_n814(x) + end +end + +def fun_l13_n267(x) + if (x < 1) + fun_l14_n958(x) + else + fun_l14_n172(x) + end +end + +def fun_l13_n268(x) + if (x < 1) + fun_l14_n167(x) + else + fun_l14_n889(x) + end +end + +def fun_l13_n269(x) + if (x < 1) + fun_l14_n321(x) + else + fun_l14_n152(x) + end +end + +def fun_l13_n270(x) + if (x < 1) + fun_l14_n851(x) + else + fun_l14_n793(x) + end +end + +def fun_l13_n271(x) + if (x < 1) + fun_l14_n306(x) + else + fun_l14_n843(x) + end +end + +def fun_l13_n272(x) + if (x < 1) + fun_l14_n499(x) + else + fun_l14_n118(x) + end +end + +def fun_l13_n273(x) + if (x < 1) + fun_l14_n958(x) + else + fun_l14_n597(x) + end +end + +def fun_l13_n274(x) + if (x < 1) + fun_l14_n884(x) + else + fun_l14_n23(x) + end +end + +def fun_l13_n275(x) + if (x < 1) + fun_l14_n203(x) + else + fun_l14_n796(x) + end +end + +def fun_l13_n276(x) + if (x < 1) + fun_l14_n944(x) + else + fun_l14_n239(x) + end +end + +def fun_l13_n277(x) + if (x < 1) + fun_l14_n511(x) + else + fun_l14_n464(x) + end +end + +def fun_l13_n278(x) + if (x < 1) + fun_l14_n906(x) + else + fun_l14_n713(x) + end +end + +def fun_l13_n279(x) + if (x < 1) + fun_l14_n872(x) + else + fun_l14_n77(x) + end +end + +def fun_l13_n280(x) + if (x < 1) + fun_l14_n888(x) + else + fun_l14_n117(x) + end +end + +def fun_l13_n281(x) + if (x < 1) + fun_l14_n298(x) + else + fun_l14_n695(x) + end +end + +def fun_l13_n282(x) + if (x < 1) + fun_l14_n740(x) + else + fun_l14_n668(x) + end +end + +def fun_l13_n283(x) + if (x < 1) + fun_l14_n438(x) + else + fun_l14_n322(x) + end +end + +def fun_l13_n284(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n39(x) + end +end + +def fun_l13_n285(x) + if (x < 1) + fun_l14_n271(x) + else + fun_l14_n984(x) + end +end + +def fun_l13_n286(x) + if (x < 1) + fun_l14_n278(x) + else + fun_l14_n453(x) + end +end + +def fun_l13_n287(x) + if (x < 1) + fun_l14_n303(x) + else + fun_l14_n812(x) + end +end + +def fun_l13_n288(x) + if (x < 1) + fun_l14_n891(x) + else + fun_l14_n843(x) + end +end + +def fun_l13_n289(x) + if (x < 1) + fun_l14_n672(x) + else + fun_l14_n543(x) + end +end + +def fun_l13_n290(x) + if (x < 1) + fun_l14_n115(x) + else + fun_l14_n33(x) + end +end + +def fun_l13_n291(x) + if (x < 1) + fun_l14_n467(x) + else + fun_l14_n427(x) + end +end + +def fun_l13_n292(x) + if (x < 1) + fun_l14_n528(x) + else + fun_l14_n51(x) + end +end + +def fun_l13_n293(x) + if (x < 1) + fun_l14_n50(x) + else + fun_l14_n917(x) + end +end + +def fun_l13_n294(x) + if (x < 1) + fun_l14_n245(x) + else + fun_l14_n289(x) + end +end + +def fun_l13_n295(x) + if (x < 1) + fun_l14_n108(x) + else + fun_l14_n772(x) + end +end + +def fun_l13_n296(x) + if (x < 1) + fun_l14_n451(x) + else + fun_l14_n127(x) + end +end + +def fun_l13_n297(x) + if (x < 1) + fun_l14_n374(x) + else + fun_l14_n20(x) + end +end + +def fun_l13_n298(x) + if (x < 1) + fun_l14_n588(x) + else + fun_l14_n95(x) + end +end + +def fun_l13_n299(x) + if (x < 1) + fun_l14_n33(x) + else + fun_l14_n146(x) + end +end + +def fun_l13_n300(x) + if (x < 1) + fun_l14_n812(x) + else + fun_l14_n373(x) + end +end + +def fun_l13_n301(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n228(x) + end +end + +def fun_l13_n302(x) + if (x < 1) + fun_l14_n992(x) + else + fun_l14_n578(x) + end +end + +def fun_l13_n303(x) + if (x < 1) + fun_l14_n106(x) + else + fun_l14_n413(x) + end +end + +def fun_l13_n304(x) + if (x < 1) + fun_l14_n463(x) + else + fun_l14_n884(x) + end +end + +def fun_l13_n305(x) + if (x < 1) + fun_l14_n754(x) + else + fun_l14_n114(x) + end +end + +def fun_l13_n306(x) + if (x < 1) + fun_l14_n960(x) + else + fun_l14_n596(x) + end +end + +def fun_l13_n307(x) + if (x < 1) + fun_l14_n858(x) + else + fun_l14_n488(x) + end +end + +def fun_l13_n308(x) + if (x < 1) + fun_l14_n968(x) + else + fun_l14_n507(x) + end +end + +def fun_l13_n309(x) + if (x < 1) + fun_l14_n956(x) + else + fun_l14_n125(x) + end +end + +def fun_l13_n310(x) + if (x < 1) + fun_l14_n190(x) + else + fun_l14_n817(x) + end +end + +def fun_l13_n311(x) + if (x < 1) + fun_l14_n574(x) + else + fun_l14_n447(x) + end +end + +def fun_l13_n312(x) + if (x < 1) + fun_l14_n403(x) + else + fun_l14_n591(x) + end +end + +def fun_l13_n313(x) + if (x < 1) + fun_l14_n499(x) + else + fun_l14_n458(x) + end +end + +def fun_l13_n314(x) + if (x < 1) + fun_l14_n994(x) + else + fun_l14_n77(x) + end +end + +def fun_l13_n315(x) + if (x < 1) + fun_l14_n421(x) + else + fun_l14_n810(x) + end +end + +def fun_l13_n316(x) + if (x < 1) + fun_l14_n304(x) + else + fun_l14_n785(x) + end +end + +def fun_l13_n317(x) + if (x < 1) + fun_l14_n624(x) + else + fun_l14_n399(x) + end +end + +def fun_l13_n318(x) + if (x < 1) + fun_l14_n882(x) + else + fun_l14_n3(x) + end +end + +def fun_l13_n319(x) + if (x < 1) + fun_l14_n267(x) + else + fun_l14_n955(x) + end +end + +def fun_l13_n320(x) + if (x < 1) + fun_l14_n690(x) + else + fun_l14_n281(x) + end +end + +def fun_l13_n321(x) + if (x < 1) + fun_l14_n453(x) + else + fun_l14_n969(x) + end +end + +def fun_l13_n322(x) + if (x < 1) + fun_l14_n297(x) + else + fun_l14_n50(x) + end +end + +def fun_l13_n323(x) + if (x < 1) + fun_l14_n342(x) + else + fun_l14_n618(x) + end +end + +def fun_l13_n324(x) + if (x < 1) + fun_l14_n74(x) + else + fun_l14_n638(x) + end +end + +def fun_l13_n325(x) + if (x < 1) + fun_l14_n218(x) + else + fun_l14_n169(x) + end +end + +def fun_l13_n326(x) + if (x < 1) + fun_l14_n128(x) + else + fun_l14_n504(x) + end +end + +def fun_l13_n327(x) + if (x < 1) + fun_l14_n612(x) + else + fun_l14_n62(x) + end +end + +def fun_l13_n328(x) + if (x < 1) + fun_l14_n83(x) + else + fun_l14_n67(x) + end +end + +def fun_l13_n329(x) + if (x < 1) + fun_l14_n515(x) + else + fun_l14_n15(x) + end +end + +def fun_l13_n330(x) + if (x < 1) + fun_l14_n448(x) + else + fun_l14_n951(x) + end +end + +def fun_l13_n331(x) + if (x < 1) + fun_l14_n804(x) + else + fun_l14_n315(x) + end +end + +def fun_l13_n332(x) + if (x < 1) + fun_l14_n522(x) + else + fun_l14_n761(x) + end +end + +def fun_l13_n333(x) + if (x < 1) + fun_l14_n421(x) + else + fun_l14_n542(x) + end +end + +def fun_l13_n334(x) + if (x < 1) + fun_l14_n952(x) + else + fun_l14_n390(x) + end +end + +def fun_l13_n335(x) + if (x < 1) + fun_l14_n324(x) + else + fun_l14_n60(x) + end +end + +def fun_l13_n336(x) + if (x < 1) + fun_l14_n887(x) + else + fun_l14_n474(x) + end +end + +def fun_l13_n337(x) + if (x < 1) + fun_l14_n355(x) + else + fun_l14_n840(x) + end +end + +def fun_l13_n338(x) + if (x < 1) + fun_l14_n21(x) + else + fun_l14_n133(x) + end +end + +def fun_l13_n339(x) + if (x < 1) + fun_l14_n12(x) + else + fun_l14_n30(x) + end +end + +def fun_l13_n340(x) + if (x < 1) + fun_l14_n678(x) + else + fun_l14_n583(x) + end +end + +def fun_l13_n341(x) + if (x < 1) + fun_l14_n289(x) + else + fun_l14_n490(x) + end +end + +def fun_l13_n342(x) + if (x < 1) + fun_l14_n232(x) + else + fun_l14_n288(x) + end +end + +def fun_l13_n343(x) + if (x < 1) + fun_l14_n744(x) + else + fun_l14_n963(x) + end +end + +def fun_l13_n344(x) + if (x < 1) + fun_l14_n651(x) + else + fun_l14_n377(x) + end +end + +def fun_l13_n345(x) + if (x < 1) + fun_l14_n13(x) + else + fun_l14_n749(x) + end +end + +def fun_l13_n346(x) + if (x < 1) + fun_l14_n789(x) + else + fun_l14_n621(x) + end +end + +def fun_l13_n347(x) + if (x < 1) + fun_l14_n346(x) + else + fun_l14_n663(x) + end +end + +def fun_l13_n348(x) + if (x < 1) + fun_l14_n252(x) + else + fun_l14_n202(x) + end +end + +def fun_l13_n349(x) + if (x < 1) + fun_l14_n919(x) + else + fun_l14_n997(x) + end +end + +def fun_l13_n350(x) + if (x < 1) + fun_l14_n472(x) + else + fun_l14_n900(x) + end +end + +def fun_l13_n351(x) + if (x < 1) + fun_l14_n954(x) + else + fun_l14_n606(x) + end +end + +def fun_l13_n352(x) + if (x < 1) + fun_l14_n227(x) + else + fun_l14_n344(x) + end +end + +def fun_l13_n353(x) + if (x < 1) + fun_l14_n110(x) + else + fun_l14_n266(x) + end +end + +def fun_l13_n354(x) + if (x < 1) + fun_l14_n840(x) + else + fun_l14_n905(x) + end +end + +def fun_l13_n355(x) + if (x < 1) + fun_l14_n950(x) + else + fun_l14_n307(x) + end +end + +def fun_l13_n356(x) + if (x < 1) + fun_l14_n572(x) + else + fun_l14_n480(x) + end +end + +def fun_l13_n357(x) + if (x < 1) + fun_l14_n122(x) + else + fun_l14_n408(x) + end +end + +def fun_l13_n358(x) + if (x < 1) + fun_l14_n105(x) + else + fun_l14_n173(x) + end +end + +def fun_l13_n359(x) + if (x < 1) + fun_l14_n358(x) + else + fun_l14_n336(x) + end +end + +def fun_l13_n360(x) + if (x < 1) + fun_l14_n457(x) + else + fun_l14_n434(x) + end +end + +def fun_l13_n361(x) + if (x < 1) + fun_l14_n679(x) + else + fun_l14_n771(x) + end +end + +def fun_l13_n362(x) + if (x < 1) + fun_l14_n419(x) + else + fun_l14_n909(x) + end +end + +def fun_l13_n363(x) + if (x < 1) + fun_l14_n672(x) + else + fun_l14_n132(x) + end +end + +def fun_l13_n364(x) + if (x < 1) + fun_l14_n947(x) + else + fun_l14_n328(x) + end +end + +def fun_l13_n365(x) + if (x < 1) + fun_l14_n959(x) + else + fun_l14_n122(x) + end +end + +def fun_l13_n366(x) + if (x < 1) + fun_l14_n534(x) + else + fun_l14_n611(x) + end +end + +def fun_l13_n367(x) + if (x < 1) + fun_l14_n349(x) + else + fun_l14_n149(x) + end +end + +def fun_l13_n368(x) + if (x < 1) + fun_l14_n94(x) + else + fun_l14_n870(x) + end +end + +def fun_l13_n369(x) + if (x < 1) + fun_l14_n774(x) + else + fun_l14_n696(x) + end +end + +def fun_l13_n370(x) + if (x < 1) + fun_l14_n311(x) + else + fun_l14_n479(x) + end +end + +def fun_l13_n371(x) + if (x < 1) + fun_l14_n650(x) + else + fun_l14_n66(x) + end +end + +def fun_l13_n372(x) + if (x < 1) + fun_l14_n825(x) + else + fun_l14_n910(x) + end +end + +def fun_l13_n373(x) + if (x < 1) + fun_l14_n454(x) + else + fun_l14_n492(x) + end +end + +def fun_l13_n374(x) + if (x < 1) + fun_l14_n785(x) + else + fun_l14_n352(x) + end +end + +def fun_l13_n375(x) + if (x < 1) + fun_l14_n124(x) + else + fun_l14_n664(x) + end +end + +def fun_l13_n376(x) + if (x < 1) + fun_l14_n427(x) + else + fun_l14_n615(x) + end +end + +def fun_l13_n377(x) + if (x < 1) + fun_l14_n926(x) + else + fun_l14_n307(x) + end +end + +def fun_l13_n378(x) + if (x < 1) + fun_l14_n575(x) + else + fun_l14_n561(x) + end +end + +def fun_l13_n379(x) + if (x < 1) + fun_l14_n497(x) + else + fun_l14_n690(x) + end +end + +def fun_l13_n380(x) + if (x < 1) + fun_l14_n350(x) + else + fun_l14_n641(x) + end +end + +def fun_l13_n381(x) + if (x < 1) + fun_l14_n292(x) + else + fun_l14_n739(x) + end +end + +def fun_l13_n382(x) + if (x < 1) + fun_l14_n302(x) + else + fun_l14_n583(x) + end +end + +def fun_l13_n383(x) + if (x < 1) + fun_l14_n36(x) + else + fun_l14_n603(x) + end +end + +def fun_l13_n384(x) + if (x < 1) + fun_l14_n953(x) + else + fun_l14_n394(x) + end +end + +def fun_l13_n385(x) + if (x < 1) + fun_l14_n107(x) + else + fun_l14_n149(x) + end +end + +def fun_l13_n386(x) + if (x < 1) + fun_l14_n77(x) + else + fun_l14_n880(x) + end +end + +def fun_l13_n387(x) + if (x < 1) + fun_l14_n670(x) + else + fun_l14_n649(x) + end +end + +def fun_l13_n388(x) + if (x < 1) + fun_l14_n277(x) + else + fun_l14_n922(x) + end +end + +def fun_l13_n389(x) + if (x < 1) + fun_l14_n981(x) + else + fun_l14_n427(x) + end +end + +def fun_l13_n390(x) + if (x < 1) + fun_l14_n411(x) + else + fun_l14_n804(x) + end +end + +def fun_l13_n391(x) + if (x < 1) + fun_l14_n52(x) + else + fun_l14_n770(x) + end +end + +def fun_l13_n392(x) + if (x < 1) + fun_l14_n592(x) + else + fun_l14_n672(x) + end +end + +def fun_l13_n393(x) + if (x < 1) + fun_l14_n274(x) + else + fun_l14_n778(x) + end +end + +def fun_l13_n394(x) + if (x < 1) + fun_l14_n708(x) + else + fun_l14_n262(x) + end +end + +def fun_l13_n395(x) + if (x < 1) + fun_l14_n449(x) + else + fun_l14_n273(x) + end +end + +def fun_l13_n396(x) + if (x < 1) + fun_l14_n567(x) + else + fun_l14_n148(x) + end +end + +def fun_l13_n397(x) + if (x < 1) + fun_l14_n127(x) + else + fun_l14_n309(x) + end +end + +def fun_l13_n398(x) + if (x < 1) + fun_l14_n150(x) + else + fun_l14_n540(x) + end +end + +def fun_l13_n399(x) + if (x < 1) + fun_l14_n791(x) + else + fun_l14_n517(x) + end +end + +def fun_l13_n400(x) + if (x < 1) + fun_l14_n152(x) + else + fun_l14_n319(x) + end +end + +def fun_l13_n401(x) + if (x < 1) + fun_l14_n911(x) + else + fun_l14_n544(x) + end +end + +def fun_l13_n402(x) + if (x < 1) + fun_l14_n915(x) + else + fun_l14_n208(x) + end +end + +def fun_l13_n403(x) + if (x < 1) + fun_l14_n452(x) + else + fun_l14_n62(x) + end +end + +def fun_l13_n404(x) + if (x < 1) + fun_l14_n823(x) + else + fun_l14_n913(x) + end +end + +def fun_l13_n405(x) + if (x < 1) + fun_l14_n808(x) + else + fun_l14_n49(x) + end +end + +def fun_l13_n406(x) + if (x < 1) + fun_l14_n498(x) + else + fun_l14_n470(x) + end +end + +def fun_l13_n407(x) + if (x < 1) + fun_l14_n314(x) + else + fun_l14_n248(x) + end +end + +def fun_l13_n408(x) + if (x < 1) + fun_l14_n61(x) + else + fun_l14_n190(x) + end +end + +def fun_l13_n409(x) + if (x < 1) + fun_l14_n126(x) + else + fun_l14_n505(x) + end +end + +def fun_l13_n410(x) + if (x < 1) + fun_l14_n646(x) + else + fun_l14_n319(x) + end +end + +def fun_l13_n411(x) + if (x < 1) + fun_l14_n741(x) + else + fun_l14_n979(x) + end +end + +def fun_l13_n412(x) + if (x < 1) + fun_l14_n840(x) + else + fun_l14_n211(x) + end +end + +def fun_l13_n413(x) + if (x < 1) + fun_l14_n217(x) + else + fun_l14_n98(x) + end +end + +def fun_l13_n414(x) + if (x < 1) + fun_l14_n398(x) + else + fun_l14_n701(x) + end +end + +def fun_l13_n415(x) + if (x < 1) + fun_l14_n470(x) + else + fun_l14_n394(x) + end +end + +def fun_l13_n416(x) + if (x < 1) + fun_l14_n113(x) + else + fun_l14_n792(x) + end +end + +def fun_l13_n417(x) + if (x < 1) + fun_l14_n969(x) + else + fun_l14_n99(x) + end +end + +def fun_l13_n418(x) + if (x < 1) + fun_l14_n54(x) + else + fun_l14_n800(x) + end +end + +def fun_l13_n419(x) + if (x < 1) + fun_l14_n763(x) + else + fun_l14_n510(x) + end +end + +def fun_l13_n420(x) + if (x < 1) + fun_l14_n660(x) + else + fun_l14_n904(x) + end +end + +def fun_l13_n421(x) + if (x < 1) + fun_l14_n345(x) + else + fun_l14_n200(x) + end +end + +def fun_l13_n422(x) + if (x < 1) + fun_l14_n831(x) + else + fun_l14_n35(x) + end +end + +def fun_l13_n423(x) + if (x < 1) + fun_l14_n644(x) + else + fun_l14_n963(x) + end +end + +def fun_l13_n424(x) + if (x < 1) + fun_l14_n0(x) + else + fun_l14_n625(x) + end +end + +def fun_l13_n425(x) + if (x < 1) + fun_l14_n186(x) + else + fun_l14_n409(x) + end +end + +def fun_l13_n426(x) + if (x < 1) + fun_l14_n869(x) + else + fun_l14_n852(x) + end +end + +def fun_l13_n427(x) + if (x < 1) + fun_l14_n322(x) + else + fun_l14_n160(x) + end +end + +def fun_l13_n428(x) + if (x < 1) + fun_l14_n974(x) + else + fun_l14_n139(x) + end +end + +def fun_l13_n429(x) + if (x < 1) + fun_l14_n570(x) + else + fun_l14_n10(x) + end +end + +def fun_l13_n430(x) + if (x < 1) + fun_l14_n199(x) + else + fun_l14_n829(x) + end +end + +def fun_l13_n431(x) + if (x < 1) + fun_l14_n700(x) + else + fun_l14_n362(x) + end +end + +def fun_l13_n432(x) + if (x < 1) + fun_l14_n925(x) + else + fun_l14_n365(x) + end +end + +def fun_l13_n433(x) + if (x < 1) + fun_l14_n837(x) + else + fun_l14_n119(x) + end +end + +def fun_l13_n434(x) + if (x < 1) + fun_l14_n355(x) + else + fun_l14_n374(x) + end +end + +def fun_l13_n435(x) + if (x < 1) + fun_l14_n126(x) + else + fun_l14_n568(x) + end +end + +def fun_l13_n436(x) + if (x < 1) + fun_l14_n468(x) + else + fun_l14_n299(x) + end +end + +def fun_l13_n437(x) + if (x < 1) + fun_l14_n667(x) + else + fun_l14_n795(x) + end +end + +def fun_l13_n438(x) + if (x < 1) + fun_l14_n989(x) + else + fun_l14_n484(x) + end +end + +def fun_l13_n439(x) + if (x < 1) + fun_l14_n109(x) + else + fun_l14_n534(x) + end +end + +def fun_l13_n440(x) + if (x < 1) + fun_l14_n999(x) + else + fun_l14_n69(x) + end +end + +def fun_l13_n441(x) + if (x < 1) + fun_l14_n616(x) + else + fun_l14_n794(x) + end +end + +def fun_l13_n442(x) + if (x < 1) + fun_l14_n719(x) + else + fun_l14_n967(x) + end +end + +def fun_l13_n443(x) + if (x < 1) + fun_l14_n279(x) + else + fun_l14_n240(x) + end +end + +def fun_l13_n444(x) + if (x < 1) + fun_l14_n660(x) + else + fun_l14_n146(x) + end +end + +def fun_l13_n445(x) + if (x < 1) + fun_l14_n164(x) + else + fun_l14_n903(x) + end +end + +def fun_l13_n446(x) + if (x < 1) + fun_l14_n474(x) + else + fun_l14_n137(x) + end +end + +def fun_l13_n447(x) + if (x < 1) + fun_l14_n198(x) + else + fun_l14_n66(x) + end +end + +def fun_l13_n448(x) + if (x < 1) + fun_l14_n948(x) + else + fun_l14_n682(x) + end +end + +def fun_l13_n449(x) + if (x < 1) + fun_l14_n545(x) + else + fun_l14_n928(x) + end +end + +def fun_l13_n450(x) + if (x < 1) + fun_l14_n822(x) + else + fun_l14_n846(x) + end +end + +def fun_l13_n451(x) + if (x < 1) + fun_l14_n514(x) + else + fun_l14_n54(x) + end +end + +def fun_l13_n452(x) + if (x < 1) + fun_l14_n539(x) + else + fun_l14_n199(x) + end +end + +def fun_l13_n453(x) + if (x < 1) + fun_l14_n917(x) + else + fun_l14_n173(x) + end +end + +def fun_l13_n454(x) + if (x < 1) + fun_l14_n924(x) + else + fun_l14_n51(x) + end +end + +def fun_l13_n455(x) + if (x < 1) + fun_l14_n675(x) + else + fun_l14_n139(x) + end +end + +def fun_l13_n456(x) + if (x < 1) + fun_l14_n335(x) + else + fun_l14_n138(x) + end +end + +def fun_l13_n457(x) + if (x < 1) + fun_l14_n112(x) + else + fun_l14_n707(x) + end +end + +def fun_l13_n458(x) + if (x < 1) + fun_l14_n784(x) + else + fun_l14_n278(x) + end +end + +def fun_l13_n459(x) + if (x < 1) + fun_l14_n165(x) + else + fun_l14_n985(x) + end +end + +def fun_l13_n460(x) + if (x < 1) + fun_l14_n843(x) + else + fun_l14_n262(x) + end +end + +def fun_l13_n461(x) + if (x < 1) + fun_l14_n492(x) + else + fun_l14_n21(x) + end +end + +def fun_l13_n462(x) + if (x < 1) + fun_l14_n864(x) + else + fun_l14_n248(x) + end +end + +def fun_l13_n463(x) + if (x < 1) + fun_l14_n940(x) + else + fun_l14_n713(x) + end +end + +def fun_l13_n464(x) + if (x < 1) + fun_l14_n8(x) + else + fun_l14_n771(x) + end +end + +def fun_l13_n465(x) + if (x < 1) + fun_l14_n83(x) + else + fun_l14_n663(x) + end +end + +def fun_l13_n466(x) + if (x < 1) + fun_l14_n411(x) + else + fun_l14_n570(x) + end +end + +def fun_l13_n467(x) + if (x < 1) + fun_l14_n464(x) + else + fun_l14_n497(x) + end +end + +def fun_l13_n468(x) + if (x < 1) + fun_l14_n49(x) + else + fun_l14_n153(x) + end +end + +def fun_l13_n469(x) + if (x < 1) + fun_l14_n33(x) + else + fun_l14_n562(x) + end +end + +def fun_l13_n470(x) + if (x < 1) + fun_l14_n207(x) + else + fun_l14_n328(x) + end +end + +def fun_l13_n471(x) + if (x < 1) + fun_l14_n356(x) + else + fun_l14_n834(x) + end +end + +def fun_l13_n472(x) + if (x < 1) + fun_l14_n46(x) + else + fun_l14_n842(x) + end +end + +def fun_l13_n473(x) + if (x < 1) + fun_l14_n14(x) + else + fun_l14_n488(x) + end +end + +def fun_l13_n474(x) + if (x < 1) + fun_l14_n307(x) + else + fun_l14_n647(x) + end +end + +def fun_l13_n475(x) + if (x < 1) + fun_l14_n474(x) + else + fun_l14_n369(x) + end +end + +def fun_l13_n476(x) + if (x < 1) + fun_l14_n471(x) + else + fun_l14_n956(x) + end +end + +def fun_l13_n477(x) + if (x < 1) + fun_l14_n368(x) + else + fun_l14_n478(x) + end +end + +def fun_l13_n478(x) + if (x < 1) + fun_l14_n377(x) + else + fun_l14_n675(x) + end +end + +def fun_l13_n479(x) + if (x < 1) + fun_l14_n370(x) + else + fun_l14_n819(x) + end +end + +def fun_l13_n480(x) + if (x < 1) + fun_l14_n459(x) + else + fun_l14_n59(x) + end +end + +def fun_l13_n481(x) + if (x < 1) + fun_l14_n200(x) + else + fun_l14_n681(x) + end +end + +def fun_l13_n482(x) + if (x < 1) + fun_l14_n893(x) + else + fun_l14_n518(x) + end +end + +def fun_l13_n483(x) + if (x < 1) + fun_l14_n130(x) + else + fun_l14_n902(x) + end +end + +def fun_l13_n484(x) + if (x < 1) + fun_l14_n598(x) + else + fun_l14_n533(x) + end +end + +def fun_l13_n485(x) + if (x < 1) + fun_l14_n254(x) + else + fun_l14_n294(x) + end +end + +def fun_l13_n486(x) + if (x < 1) + fun_l14_n608(x) + else + fun_l14_n858(x) + end +end + +def fun_l13_n487(x) + if (x < 1) + fun_l14_n82(x) + else + fun_l14_n379(x) + end +end + +def fun_l13_n488(x) + if (x < 1) + fun_l14_n605(x) + else + fun_l14_n530(x) + end +end + +def fun_l13_n489(x) + if (x < 1) + fun_l14_n572(x) + else + fun_l14_n199(x) + end +end + +def fun_l13_n490(x) + if (x < 1) + fun_l14_n3(x) + else + fun_l14_n103(x) + end +end + +def fun_l13_n491(x) + if (x < 1) + fun_l14_n922(x) + else + fun_l14_n372(x) + end +end + +def fun_l13_n492(x) + if (x < 1) + fun_l14_n306(x) + else + fun_l14_n378(x) + end +end + +def fun_l13_n493(x) + if (x < 1) + fun_l14_n980(x) + else + fun_l14_n617(x) + end +end + +def fun_l13_n494(x) + if (x < 1) + fun_l14_n127(x) + else + fun_l14_n348(x) + end +end + +def fun_l13_n495(x) + if (x < 1) + fun_l14_n631(x) + else + fun_l14_n281(x) + end +end + +def fun_l13_n496(x) + if (x < 1) + fun_l14_n552(x) + else + fun_l14_n493(x) + end +end + +def fun_l13_n497(x) + if (x < 1) + fun_l14_n342(x) + else + fun_l14_n931(x) + end +end + +def fun_l13_n498(x) + if (x < 1) + fun_l14_n297(x) + else + fun_l14_n512(x) + end +end + +def fun_l13_n499(x) + if (x < 1) + fun_l14_n950(x) + else + fun_l14_n952(x) + end +end + +def fun_l13_n500(x) + if (x < 1) + fun_l14_n355(x) + else + fun_l14_n383(x) + end +end + +def fun_l13_n501(x) + if (x < 1) + fun_l14_n278(x) + else + fun_l14_n442(x) + end +end + +def fun_l13_n502(x) + if (x < 1) + fun_l14_n16(x) + else + fun_l14_n150(x) + end +end + +def fun_l13_n503(x) + if (x < 1) + fun_l14_n399(x) + else + fun_l14_n989(x) + end +end + +def fun_l13_n504(x) + if (x < 1) + fun_l14_n289(x) + else + fun_l14_n925(x) + end +end + +def fun_l13_n505(x) + if (x < 1) + fun_l14_n743(x) + else + fun_l14_n784(x) + end +end + +def fun_l13_n506(x) + if (x < 1) + fun_l14_n916(x) + else + fun_l14_n111(x) + end +end + +def fun_l13_n507(x) + if (x < 1) + fun_l14_n912(x) + else + fun_l14_n448(x) + end +end + +def fun_l13_n508(x) + if (x < 1) + fun_l14_n10(x) + else + fun_l14_n451(x) + end +end + +def fun_l13_n509(x) + if (x < 1) + fun_l14_n15(x) + else + fun_l14_n697(x) + end +end + +def fun_l13_n510(x) + if (x < 1) + fun_l14_n565(x) + else + fun_l14_n511(x) + end +end + +def fun_l13_n511(x) + if (x < 1) + fun_l14_n843(x) + else + fun_l14_n272(x) + end +end + +def fun_l13_n512(x) + if (x < 1) + fun_l14_n70(x) + else + fun_l14_n333(x) + end +end + +def fun_l13_n513(x) + if (x < 1) + fun_l14_n100(x) + else + fun_l14_n399(x) + end +end + +def fun_l13_n514(x) + if (x < 1) + fun_l14_n678(x) + else + fun_l14_n247(x) + end +end + +def fun_l13_n515(x) + if (x < 1) + fun_l14_n823(x) + else + fun_l14_n371(x) + end +end + +def fun_l13_n516(x) + if (x < 1) + fun_l14_n994(x) + else + fun_l14_n322(x) + end +end + +def fun_l13_n517(x) + if (x < 1) + fun_l14_n399(x) + else + fun_l14_n567(x) + end +end + +def fun_l13_n518(x) + if (x < 1) + fun_l14_n898(x) + else + fun_l14_n59(x) + end +end + +def fun_l13_n519(x) + if (x < 1) + fun_l14_n33(x) + else + fun_l14_n640(x) + end +end + +def fun_l13_n520(x) + if (x < 1) + fun_l14_n475(x) + else + fun_l14_n67(x) + end +end + +def fun_l13_n521(x) + if (x < 1) + fun_l14_n896(x) + else + fun_l14_n312(x) + end +end + +def fun_l13_n522(x) + if (x < 1) + fun_l14_n454(x) + else + fun_l14_n520(x) + end +end + +def fun_l13_n523(x) + if (x < 1) + fun_l14_n334(x) + else + fun_l14_n879(x) + end +end + +def fun_l13_n524(x) + if (x < 1) + fun_l14_n267(x) + else + fun_l14_n526(x) + end +end + +def fun_l13_n525(x) + if (x < 1) + fun_l14_n552(x) + else + fun_l14_n103(x) + end +end + +def fun_l13_n526(x) + if (x < 1) + fun_l14_n224(x) + else + fun_l14_n211(x) + end +end + +def fun_l13_n527(x) + if (x < 1) + fun_l14_n113(x) + else + fun_l14_n193(x) + end +end + +def fun_l13_n528(x) + if (x < 1) + fun_l14_n389(x) + else + fun_l14_n332(x) + end +end + +def fun_l13_n529(x) + if (x < 1) + fun_l14_n881(x) + else + fun_l14_n655(x) + end +end + +def fun_l13_n530(x) + if (x < 1) + fun_l14_n857(x) + else + fun_l14_n588(x) + end +end + +def fun_l13_n531(x) + if (x < 1) + fun_l14_n70(x) + else + fun_l14_n232(x) + end +end + +def fun_l13_n532(x) + if (x < 1) + fun_l14_n617(x) + else + fun_l14_n477(x) + end +end + +def fun_l13_n533(x) + if (x < 1) + fun_l14_n655(x) + else + fun_l14_n801(x) + end +end + +def fun_l13_n534(x) + if (x < 1) + fun_l14_n665(x) + else + fun_l14_n22(x) + end +end + +def fun_l13_n535(x) + if (x < 1) + fun_l14_n314(x) + else + fun_l14_n924(x) + end +end + +def fun_l13_n536(x) + if (x < 1) + fun_l14_n619(x) + else + fun_l14_n455(x) + end +end + +def fun_l13_n537(x) + if (x < 1) + fun_l14_n183(x) + else + fun_l14_n767(x) + end +end + +def fun_l13_n538(x) + if (x < 1) + fun_l14_n862(x) + else + fun_l14_n352(x) + end +end + +def fun_l13_n539(x) + if (x < 1) + fun_l14_n540(x) + else + fun_l14_n813(x) + end +end + +def fun_l13_n540(x) + if (x < 1) + fun_l14_n429(x) + else + fun_l14_n515(x) + end +end + +def fun_l13_n541(x) + if (x < 1) + fun_l14_n294(x) + else + fun_l14_n341(x) + end +end + +def fun_l13_n542(x) + if (x < 1) + fun_l14_n910(x) + else + fun_l14_n882(x) + end +end + +def fun_l13_n543(x) + if (x < 1) + fun_l14_n971(x) + else + fun_l14_n19(x) + end +end + +def fun_l13_n544(x) + if (x < 1) + fun_l14_n344(x) + else + fun_l14_n419(x) + end +end + +def fun_l13_n545(x) + if (x < 1) + fun_l14_n410(x) + else + fun_l14_n996(x) + end +end + +def fun_l13_n546(x) + if (x < 1) + fun_l14_n857(x) + else + fun_l14_n431(x) + end +end + +def fun_l13_n547(x) + if (x < 1) + fun_l14_n548(x) + else + fun_l14_n934(x) + end +end + +def fun_l13_n548(x) + if (x < 1) + fun_l14_n420(x) + else + fun_l14_n506(x) + end +end + +def fun_l13_n549(x) + if (x < 1) + fun_l14_n992(x) + else + fun_l14_n213(x) + end +end + +def fun_l13_n550(x) + if (x < 1) + fun_l14_n754(x) + else + fun_l14_n666(x) + end +end + +def fun_l13_n551(x) + if (x < 1) + fun_l14_n412(x) + else + fun_l14_n908(x) + end +end + +def fun_l13_n552(x) + if (x < 1) + fun_l14_n708(x) + else + fun_l14_n308(x) + end +end + +def fun_l13_n553(x) + if (x < 1) + fun_l14_n797(x) + else + fun_l14_n622(x) + end +end + +def fun_l13_n554(x) + if (x < 1) + fun_l14_n26(x) + else + fun_l14_n102(x) + end +end + +def fun_l13_n555(x) + if (x < 1) + fun_l14_n614(x) + else + fun_l14_n110(x) + end +end + +def fun_l13_n556(x) + if (x < 1) + fun_l14_n368(x) + else + fun_l14_n718(x) + end +end + +def fun_l13_n557(x) + if (x < 1) + fun_l14_n782(x) + else + fun_l14_n659(x) + end +end + +def fun_l13_n558(x) + if (x < 1) + fun_l14_n544(x) + else + fun_l14_n507(x) + end +end + +def fun_l13_n559(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n97(x) + end +end + +def fun_l13_n560(x) + if (x < 1) + fun_l14_n390(x) + else + fun_l14_n93(x) + end +end + +def fun_l13_n561(x) + if (x < 1) + fun_l14_n28(x) + else + fun_l14_n267(x) + end +end + +def fun_l13_n562(x) + if (x < 1) + fun_l14_n10(x) + else + fun_l14_n990(x) + end +end + +def fun_l13_n563(x) + if (x < 1) + fun_l14_n428(x) + else + fun_l14_n878(x) + end +end + +def fun_l13_n564(x) + if (x < 1) + fun_l14_n587(x) + else + fun_l14_n724(x) + end +end + +def fun_l13_n565(x) + if (x < 1) + fun_l14_n524(x) + else + fun_l14_n87(x) + end +end + +def fun_l13_n566(x) + if (x < 1) + fun_l14_n213(x) + else + fun_l14_n718(x) + end +end + +def fun_l13_n567(x) + if (x < 1) + fun_l14_n821(x) + else + fun_l14_n478(x) + end +end + +def fun_l13_n568(x) + if (x < 1) + fun_l14_n580(x) + else + fun_l14_n731(x) + end +end + +def fun_l13_n569(x) + if (x < 1) + fun_l14_n673(x) + else + fun_l14_n780(x) + end +end + +def fun_l13_n570(x) + if (x < 1) + fun_l14_n791(x) + else + fun_l14_n691(x) + end +end + +def fun_l13_n571(x) + if (x < 1) + fun_l14_n192(x) + else + fun_l14_n712(x) + end +end + +def fun_l13_n572(x) + if (x < 1) + fun_l14_n201(x) + else + fun_l14_n732(x) + end +end + +def fun_l13_n573(x) + if (x < 1) + fun_l14_n180(x) + else + fun_l14_n260(x) + end +end + +def fun_l13_n574(x) + if (x < 1) + fun_l14_n609(x) + else + fun_l14_n110(x) + end +end + +def fun_l13_n575(x) + if (x < 1) + fun_l14_n993(x) + else + fun_l14_n510(x) + end +end + +def fun_l13_n576(x) + if (x < 1) + fun_l14_n318(x) + else + fun_l14_n915(x) + end +end + +def fun_l13_n577(x) + if (x < 1) + fun_l14_n635(x) + else + fun_l14_n21(x) + end +end + +def fun_l13_n578(x) + if (x < 1) + fun_l14_n330(x) + else + fun_l14_n860(x) + end +end + +def fun_l13_n579(x) + if (x < 1) + fun_l14_n24(x) + else + fun_l14_n87(x) + end +end + +def fun_l13_n580(x) + if (x < 1) + fun_l14_n404(x) + else + fun_l14_n530(x) + end +end + +def fun_l13_n581(x) + if (x < 1) + fun_l14_n831(x) + else + fun_l14_n384(x) + end +end + +def fun_l13_n582(x) + if (x < 1) + fun_l14_n272(x) + else + fun_l14_n438(x) + end +end + +def fun_l13_n583(x) + if (x < 1) + fun_l14_n297(x) + else + fun_l14_n414(x) + end +end + +def fun_l13_n584(x) + if (x < 1) + fun_l14_n38(x) + else + fun_l14_n676(x) + end +end + +def fun_l13_n585(x) + if (x < 1) + fun_l14_n104(x) + else + fun_l14_n566(x) + end +end + +def fun_l13_n586(x) + if (x < 1) + fun_l14_n322(x) + else + fun_l14_n601(x) + end +end + +def fun_l13_n587(x) + if (x < 1) + fun_l14_n20(x) + else + fun_l14_n242(x) + end +end + +def fun_l13_n588(x) + if (x < 1) + fun_l14_n291(x) + else + fun_l14_n744(x) + end +end + +def fun_l13_n589(x) + if (x < 1) + fun_l14_n702(x) + else + fun_l14_n456(x) + end +end + +def fun_l13_n590(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n493(x) + end +end + +def fun_l13_n591(x) + if (x < 1) + fun_l14_n51(x) + else + fun_l14_n193(x) + end +end + +def fun_l13_n592(x) + if (x < 1) + fun_l14_n512(x) + else + fun_l14_n382(x) + end +end + +def fun_l13_n593(x) + if (x < 1) + fun_l14_n550(x) + else + fun_l14_n711(x) + end +end + +def fun_l13_n594(x) + if (x < 1) + fun_l14_n586(x) + else + fun_l14_n130(x) + end +end + +def fun_l13_n595(x) + if (x < 1) + fun_l14_n348(x) + else + fun_l14_n214(x) + end +end + +def fun_l13_n596(x) + if (x < 1) + fun_l14_n193(x) + else + fun_l14_n490(x) + end +end + +def fun_l13_n597(x) + if (x < 1) + fun_l14_n736(x) + else + fun_l14_n824(x) + end +end + +def fun_l13_n598(x) + if (x < 1) + fun_l14_n555(x) + else + fun_l14_n546(x) + end +end + +def fun_l13_n599(x) + if (x < 1) + fun_l14_n244(x) + else + fun_l14_n903(x) + end +end + +def fun_l13_n600(x) + if (x < 1) + fun_l14_n786(x) + else + fun_l14_n817(x) + end +end + +def fun_l13_n601(x) + if (x < 1) + fun_l14_n991(x) + else + fun_l14_n691(x) + end +end + +def fun_l13_n602(x) + if (x < 1) + fun_l14_n369(x) + else + fun_l14_n85(x) + end +end + +def fun_l13_n603(x) + if (x < 1) + fun_l14_n232(x) + else + fun_l14_n287(x) + end +end + +def fun_l13_n604(x) + if (x < 1) + fun_l14_n397(x) + else + fun_l14_n59(x) + end +end + +def fun_l13_n605(x) + if (x < 1) + fun_l14_n394(x) + else + fun_l14_n297(x) + end +end + +def fun_l13_n606(x) + if (x < 1) + fun_l14_n676(x) + else + fun_l14_n444(x) + end +end + +def fun_l13_n607(x) + if (x < 1) + fun_l14_n894(x) + else + fun_l14_n147(x) + end +end + +def fun_l13_n608(x) + if (x < 1) + fun_l14_n593(x) + else + fun_l14_n880(x) + end +end + +def fun_l13_n609(x) + if (x < 1) + fun_l14_n306(x) + else + fun_l14_n610(x) + end +end + +def fun_l13_n610(x) + if (x < 1) + fun_l14_n884(x) + else + fun_l14_n202(x) + end +end + +def fun_l13_n611(x) + if (x < 1) + fun_l14_n763(x) + else + fun_l14_n592(x) + end +end + +def fun_l13_n612(x) + if (x < 1) + fun_l14_n477(x) + else + fun_l14_n614(x) + end +end + +def fun_l13_n613(x) + if (x < 1) + fun_l14_n372(x) + else + fun_l14_n330(x) + end +end + +def fun_l13_n614(x) + if (x < 1) + fun_l14_n767(x) + else + fun_l14_n277(x) + end +end + +def fun_l13_n615(x) + if (x < 1) + fun_l14_n530(x) + else + fun_l14_n24(x) + end +end + +def fun_l13_n616(x) + if (x < 1) + fun_l14_n657(x) + else + fun_l14_n709(x) + end +end + +def fun_l13_n617(x) + if (x < 1) + fun_l14_n559(x) + else + fun_l14_n125(x) + end +end + +def fun_l13_n618(x) + if (x < 1) + fun_l14_n855(x) + else + fun_l14_n353(x) + end +end + +def fun_l13_n619(x) + if (x < 1) + fun_l14_n635(x) + else + fun_l14_n907(x) + end +end + +def fun_l13_n620(x) + if (x < 1) + fun_l14_n229(x) + else + fun_l14_n7(x) + end +end + +def fun_l13_n621(x) + if (x < 1) + fun_l14_n568(x) + else + fun_l14_n393(x) + end +end + +def fun_l13_n622(x) + if (x < 1) + fun_l14_n153(x) + else + fun_l14_n641(x) + end +end + +def fun_l13_n623(x) + if (x < 1) + fun_l14_n249(x) + else + fun_l14_n139(x) + end +end + +def fun_l13_n624(x) + if (x < 1) + fun_l14_n961(x) + else + fun_l14_n897(x) + end +end + +def fun_l13_n625(x) + if (x < 1) + fun_l14_n535(x) + else + fun_l14_n252(x) + end +end + +def fun_l13_n626(x) + if (x < 1) + fun_l14_n832(x) + else + fun_l14_n995(x) + end +end + +def fun_l13_n627(x) + if (x < 1) + fun_l14_n896(x) + else + fun_l14_n173(x) + end +end + +def fun_l13_n628(x) + if (x < 1) + fun_l14_n939(x) + else + fun_l14_n852(x) + end +end + +def fun_l13_n629(x) + if (x < 1) + fun_l14_n424(x) + else + fun_l14_n161(x) + end +end + +def fun_l13_n630(x) + if (x < 1) + fun_l14_n822(x) + else + fun_l14_n523(x) + end +end + +def fun_l13_n631(x) + if (x < 1) + fun_l14_n697(x) + else + fun_l14_n939(x) + end +end + +def fun_l13_n632(x) + if (x < 1) + fun_l14_n831(x) + else + fun_l14_n722(x) + end +end + +def fun_l13_n633(x) + if (x < 1) + fun_l14_n837(x) + else + fun_l14_n994(x) + end +end + +def fun_l13_n634(x) + if (x < 1) + fun_l14_n568(x) + else + fun_l14_n636(x) + end +end + +def fun_l13_n635(x) + if (x < 1) + fun_l14_n573(x) + else + fun_l14_n156(x) + end +end + +def fun_l13_n636(x) + if (x < 1) + fun_l14_n682(x) + else + fun_l14_n999(x) + end +end + +def fun_l13_n637(x) + if (x < 1) + fun_l14_n648(x) + else + fun_l14_n567(x) + end +end + +def fun_l13_n638(x) + if (x < 1) + fun_l14_n395(x) + else + fun_l14_n837(x) + end +end + +def fun_l13_n639(x) + if (x < 1) + fun_l14_n294(x) + else + fun_l14_n508(x) + end +end + +def fun_l13_n640(x) + if (x < 1) + fun_l14_n530(x) + else + fun_l14_n542(x) + end +end + +def fun_l13_n641(x) + if (x < 1) + fun_l14_n227(x) + else + fun_l14_n939(x) + end +end + +def fun_l13_n642(x) + if (x < 1) + fun_l14_n415(x) + else + fun_l14_n79(x) + end +end + +def fun_l13_n643(x) + if (x < 1) + fun_l14_n354(x) + else + fun_l14_n606(x) + end +end + +def fun_l13_n644(x) + if (x < 1) + fun_l14_n270(x) + else + fun_l14_n644(x) + end +end + +def fun_l13_n645(x) + if (x < 1) + fun_l14_n345(x) + else + fun_l14_n299(x) + end +end + +def fun_l13_n646(x) + if (x < 1) + fun_l14_n384(x) + else + fun_l14_n97(x) + end +end + +def fun_l13_n647(x) + if (x < 1) + fun_l14_n86(x) + else + fun_l14_n103(x) + end +end + +def fun_l13_n648(x) + if (x < 1) + fun_l14_n765(x) + else + fun_l14_n498(x) + end +end + +def fun_l13_n649(x) + if (x < 1) + fun_l14_n135(x) + else + fun_l14_n993(x) + end +end + +def fun_l13_n650(x) + if (x < 1) + fun_l14_n837(x) + else + fun_l14_n576(x) + end +end + +def fun_l13_n651(x) + if (x < 1) + fun_l14_n75(x) + else + fun_l14_n351(x) + end +end + +def fun_l13_n652(x) + if (x < 1) + fun_l14_n932(x) + else + fun_l14_n646(x) + end +end + +def fun_l13_n653(x) + if (x < 1) + fun_l14_n908(x) + else + fun_l14_n384(x) + end +end + +def fun_l13_n654(x) + if (x < 1) + fun_l14_n540(x) + else + fun_l14_n946(x) + end +end + +def fun_l13_n655(x) + if (x < 1) + fun_l14_n686(x) + else + fun_l14_n926(x) + end +end + +def fun_l13_n656(x) + if (x < 1) + fun_l14_n567(x) + else + fun_l14_n815(x) + end +end + +def fun_l13_n657(x) + if (x < 1) + fun_l14_n101(x) + else + fun_l14_n960(x) + end +end + +def fun_l13_n658(x) + if (x < 1) + fun_l14_n956(x) + else + fun_l14_n980(x) + end +end + +def fun_l13_n659(x) + if (x < 1) + fun_l14_n196(x) + else + fun_l14_n632(x) + end +end + +def fun_l13_n660(x) + if (x < 1) + fun_l14_n83(x) + else + fun_l14_n288(x) + end +end + +def fun_l13_n661(x) + if (x < 1) + fun_l14_n907(x) + else + fun_l14_n719(x) + end +end + +def fun_l13_n662(x) + if (x < 1) + fun_l14_n922(x) + else + fun_l14_n186(x) + end +end + +def fun_l13_n663(x) + if (x < 1) + fun_l14_n439(x) + else + fun_l14_n890(x) + end +end + +def fun_l13_n664(x) + if (x < 1) + fun_l14_n310(x) + else + fun_l14_n534(x) + end +end + +def fun_l13_n665(x) + if (x < 1) + fun_l14_n584(x) + else + fun_l14_n322(x) + end +end + +def fun_l13_n666(x) + if (x < 1) + fun_l14_n385(x) + else + fun_l14_n466(x) + end +end + +def fun_l13_n667(x) + if (x < 1) + fun_l14_n387(x) + else + fun_l14_n284(x) + end +end + +def fun_l13_n668(x) + if (x < 1) + fun_l14_n834(x) + else + fun_l14_n446(x) + end +end + +def fun_l13_n669(x) + if (x < 1) + fun_l14_n839(x) + else + fun_l14_n820(x) + end +end + +def fun_l13_n670(x) + if (x < 1) + fun_l14_n666(x) + else + fun_l14_n690(x) + end +end + +def fun_l13_n671(x) + if (x < 1) + fun_l14_n640(x) + else + fun_l14_n83(x) + end +end + +def fun_l13_n672(x) + if (x < 1) + fun_l14_n663(x) + else + fun_l14_n332(x) + end +end + +def fun_l13_n673(x) + if (x < 1) + fun_l14_n776(x) + else + fun_l14_n818(x) + end +end + +def fun_l13_n674(x) + if (x < 1) + fun_l14_n82(x) + else + fun_l14_n594(x) + end +end + +def fun_l13_n675(x) + if (x < 1) + fun_l14_n491(x) + else + fun_l14_n0(x) + end +end + +def fun_l13_n676(x) + if (x < 1) + fun_l14_n963(x) + else + fun_l14_n634(x) + end +end + +def fun_l13_n677(x) + if (x < 1) + fun_l14_n716(x) + else + fun_l14_n99(x) + end +end + +def fun_l13_n678(x) + if (x < 1) + fun_l14_n997(x) + else + fun_l14_n933(x) + end +end + +def fun_l13_n679(x) + if (x < 1) + fun_l14_n171(x) + else + fun_l14_n356(x) + end +end + +def fun_l13_n680(x) + if (x < 1) + fun_l14_n214(x) + else + fun_l14_n360(x) + end +end + +def fun_l13_n681(x) + if (x < 1) + fun_l14_n758(x) + else + fun_l14_n185(x) + end +end + +def fun_l13_n682(x) + if (x < 1) + fun_l14_n480(x) + else + fun_l14_n572(x) + end +end + +def fun_l13_n683(x) + if (x < 1) + fun_l14_n595(x) + else + fun_l14_n534(x) + end +end + +def fun_l13_n684(x) + if (x < 1) + fun_l14_n462(x) + else + fun_l14_n481(x) + end +end + +def fun_l13_n685(x) + if (x < 1) + fun_l14_n946(x) + else + fun_l14_n726(x) + end +end + +def fun_l13_n686(x) + if (x < 1) + fun_l14_n428(x) + else + fun_l14_n256(x) + end +end + +def fun_l13_n687(x) + if (x < 1) + fun_l14_n562(x) + else + fun_l14_n290(x) + end +end + +def fun_l13_n688(x) + if (x < 1) + fun_l14_n679(x) + else + fun_l14_n787(x) + end +end + +def fun_l13_n689(x) + if (x < 1) + fun_l14_n972(x) + else + fun_l14_n809(x) + end +end + +def fun_l13_n690(x) + if (x < 1) + fun_l14_n700(x) + else + fun_l14_n239(x) + end +end + +def fun_l13_n691(x) + if (x < 1) + fun_l14_n525(x) + else + fun_l14_n251(x) + end +end + +def fun_l13_n692(x) + if (x < 1) + fun_l14_n4(x) + else + fun_l14_n889(x) + end +end + +def fun_l13_n693(x) + if (x < 1) + fun_l14_n362(x) + else + fun_l14_n495(x) + end +end + +def fun_l13_n694(x) + if (x < 1) + fun_l14_n466(x) + else + fun_l14_n820(x) + end +end + +def fun_l13_n695(x) + if (x < 1) + fun_l14_n244(x) + else + fun_l14_n233(x) + end +end + +def fun_l13_n696(x) + if (x < 1) + fun_l14_n920(x) + else + fun_l14_n124(x) + end +end + +def fun_l13_n697(x) + if (x < 1) + fun_l14_n926(x) + else + fun_l14_n417(x) + end +end + +def fun_l13_n698(x) + if (x < 1) + fun_l14_n756(x) + else + fun_l14_n683(x) + end +end + +def fun_l13_n699(x) + if (x < 1) + fun_l14_n487(x) + else + fun_l14_n191(x) + end +end + +def fun_l13_n700(x) + if (x < 1) + fun_l14_n316(x) + else + fun_l14_n123(x) + end +end + +def fun_l13_n701(x) + if (x < 1) + fun_l14_n851(x) + else + fun_l14_n695(x) + end +end + +def fun_l13_n702(x) + if (x < 1) + fun_l14_n766(x) + else + fun_l14_n603(x) + end +end + +def fun_l13_n703(x) + if (x < 1) + fun_l14_n689(x) + else + fun_l14_n524(x) + end +end + +def fun_l13_n704(x) + if (x < 1) + fun_l14_n23(x) + else + fun_l14_n866(x) + end +end + +def fun_l13_n705(x) + if (x < 1) + fun_l14_n62(x) + else + fun_l14_n926(x) + end +end + +def fun_l13_n706(x) + if (x < 1) + fun_l14_n53(x) + else + fun_l14_n567(x) + end +end + +def fun_l13_n707(x) + if (x < 1) + fun_l14_n756(x) + else + fun_l14_n595(x) + end +end + +def fun_l13_n708(x) + if (x < 1) + fun_l14_n495(x) + else + fun_l14_n698(x) + end +end + +def fun_l13_n709(x) + if (x < 1) + fun_l14_n511(x) + else + fun_l14_n131(x) + end +end + +def fun_l13_n710(x) + if (x < 1) + fun_l14_n593(x) + else + fun_l14_n233(x) + end +end + +def fun_l13_n711(x) + if (x < 1) + fun_l14_n846(x) + else + fun_l14_n166(x) + end +end + +def fun_l13_n712(x) + if (x < 1) + fun_l14_n759(x) + else + fun_l14_n103(x) + end +end + +def fun_l13_n713(x) + if (x < 1) + fun_l14_n364(x) + else + fun_l14_n805(x) + end +end + +def fun_l13_n714(x) + if (x < 1) + fun_l14_n957(x) + else + fun_l14_n85(x) + end +end + +def fun_l13_n715(x) + if (x < 1) + fun_l14_n877(x) + else + fun_l14_n111(x) + end +end + +def fun_l13_n716(x) + if (x < 1) + fun_l14_n290(x) + else + fun_l14_n894(x) + end +end + +def fun_l13_n717(x) + if (x < 1) + fun_l14_n354(x) + else + fun_l14_n646(x) + end +end + +def fun_l13_n718(x) + if (x < 1) + fun_l14_n364(x) + else + fun_l14_n810(x) + end +end + +def fun_l13_n719(x) + if (x < 1) + fun_l14_n392(x) + else + fun_l14_n537(x) + end +end + +def fun_l13_n720(x) + if (x < 1) + fun_l14_n546(x) + else + fun_l14_n681(x) + end +end + +def fun_l13_n721(x) + if (x < 1) + fun_l14_n153(x) + else + fun_l14_n925(x) + end +end + +def fun_l13_n722(x) + if (x < 1) + fun_l14_n107(x) + else + fun_l14_n482(x) + end +end + +def fun_l13_n723(x) + if (x < 1) + fun_l14_n981(x) + else + fun_l14_n364(x) + end +end + +def fun_l13_n724(x) + if (x < 1) + fun_l14_n869(x) + else + fun_l14_n871(x) + end +end + +def fun_l13_n725(x) + if (x < 1) + fun_l14_n693(x) + else + fun_l14_n690(x) + end +end + +def fun_l13_n726(x) + if (x < 1) + fun_l14_n587(x) + else + fun_l14_n654(x) + end +end + +def fun_l13_n727(x) + if (x < 1) + fun_l14_n150(x) + else + fun_l14_n904(x) + end +end + +def fun_l13_n728(x) + if (x < 1) + fun_l14_n843(x) + else + fun_l14_n556(x) + end +end + +def fun_l13_n729(x) + if (x < 1) + fun_l14_n726(x) + else + fun_l14_n114(x) + end +end + +def fun_l13_n730(x) + if (x < 1) + fun_l14_n976(x) + else + fun_l14_n740(x) + end +end + +def fun_l13_n731(x) + if (x < 1) + fun_l14_n709(x) + else + fun_l14_n293(x) + end +end + +def fun_l13_n732(x) + if (x < 1) + fun_l14_n858(x) + else + fun_l14_n530(x) + end +end + +def fun_l13_n733(x) + if (x < 1) + fun_l14_n789(x) + else + fun_l14_n475(x) + end +end + +def fun_l13_n734(x) + if (x < 1) + fun_l14_n813(x) + else + fun_l14_n359(x) + end +end + +def fun_l13_n735(x) + if (x < 1) + fun_l14_n209(x) + else + fun_l14_n29(x) + end +end + +def fun_l13_n736(x) + if (x < 1) + fun_l14_n710(x) + else + fun_l14_n823(x) + end +end + +def fun_l13_n737(x) + if (x < 1) + fun_l14_n434(x) + else + fun_l14_n864(x) + end +end + +def fun_l13_n738(x) + if (x < 1) + fun_l14_n184(x) + else + fun_l14_n902(x) + end +end + +def fun_l13_n739(x) + if (x < 1) + fun_l14_n206(x) + else + fun_l14_n65(x) + end +end + +def fun_l13_n740(x) + if (x < 1) + fun_l14_n670(x) + else + fun_l14_n956(x) + end +end + +def fun_l13_n741(x) + if (x < 1) + fun_l14_n91(x) + else + fun_l14_n341(x) + end +end + +def fun_l13_n742(x) + if (x < 1) + fun_l14_n864(x) + else + fun_l14_n864(x) + end +end + +def fun_l13_n743(x) + if (x < 1) + fun_l14_n426(x) + else + fun_l14_n302(x) + end +end + +def fun_l13_n744(x) + if (x < 1) + fun_l14_n241(x) + else + fun_l14_n151(x) + end +end + +def fun_l13_n745(x) + if (x < 1) + fun_l14_n161(x) + else + fun_l14_n715(x) + end +end + +def fun_l13_n746(x) + if (x < 1) + fun_l14_n925(x) + else + fun_l14_n840(x) + end +end + +def fun_l13_n747(x) + if (x < 1) + fun_l14_n864(x) + else + fun_l14_n610(x) + end +end + +def fun_l13_n748(x) + if (x < 1) + fun_l14_n322(x) + else + fun_l14_n69(x) + end +end + +def fun_l13_n749(x) + if (x < 1) + fun_l14_n847(x) + else + fun_l14_n3(x) + end +end + +def fun_l13_n750(x) + if (x < 1) + fun_l14_n124(x) + else + fun_l14_n915(x) + end +end + +def fun_l13_n751(x) + if (x < 1) + fun_l14_n163(x) + else + fun_l14_n136(x) + end +end + +def fun_l13_n752(x) + if (x < 1) + fun_l14_n525(x) + else + fun_l14_n197(x) + end +end + +def fun_l13_n753(x) + if (x < 1) + fun_l14_n109(x) + else + fun_l14_n208(x) + end +end + +def fun_l13_n754(x) + if (x < 1) + fun_l14_n597(x) + else + fun_l14_n307(x) + end +end + +def fun_l13_n755(x) + if (x < 1) + fun_l14_n36(x) + else + fun_l14_n948(x) + end +end + +def fun_l13_n756(x) + if (x < 1) + fun_l14_n236(x) + else + fun_l14_n716(x) + end +end + +def fun_l13_n757(x) + if (x < 1) + fun_l14_n326(x) + else + fun_l14_n870(x) + end +end + +def fun_l13_n758(x) + if (x < 1) + fun_l14_n333(x) + else + fun_l14_n224(x) + end +end + +def fun_l13_n759(x) + if (x < 1) + fun_l14_n141(x) + else + fun_l14_n232(x) + end +end + +def fun_l13_n760(x) + if (x < 1) + fun_l14_n653(x) + else + fun_l14_n559(x) + end +end + +def fun_l13_n761(x) + if (x < 1) + fun_l14_n305(x) + else + fun_l14_n296(x) + end +end + +def fun_l13_n762(x) + if (x < 1) + fun_l14_n318(x) + else + fun_l14_n351(x) + end +end + +def fun_l13_n763(x) + if (x < 1) + fun_l14_n685(x) + else + fun_l14_n643(x) + end +end + +def fun_l13_n764(x) + if (x < 1) + fun_l14_n180(x) + else + fun_l14_n348(x) + end +end + +def fun_l13_n765(x) + if (x < 1) + fun_l14_n72(x) + else + fun_l14_n99(x) + end +end + +def fun_l13_n766(x) + if (x < 1) + fun_l14_n463(x) + else + fun_l14_n135(x) + end +end + +def fun_l13_n767(x) + if (x < 1) + fun_l14_n461(x) + else + fun_l14_n989(x) + end +end + +def fun_l13_n768(x) + if (x < 1) + fun_l14_n759(x) + else + fun_l14_n907(x) + end +end + +def fun_l13_n769(x) + if (x < 1) + fun_l14_n330(x) + else + fun_l14_n268(x) + end +end + +def fun_l13_n770(x) + if (x < 1) + fun_l14_n809(x) + else + fun_l14_n46(x) + end +end + +def fun_l13_n771(x) + if (x < 1) + fun_l14_n396(x) + else + fun_l14_n114(x) + end +end + +def fun_l13_n772(x) + if (x < 1) + fun_l14_n300(x) + else + fun_l14_n60(x) + end +end + +def fun_l13_n773(x) + if (x < 1) + fun_l14_n938(x) + else + fun_l14_n112(x) + end +end + +def fun_l13_n774(x) + if (x < 1) + fun_l14_n862(x) + else + fun_l14_n503(x) + end +end + +def fun_l13_n775(x) + if (x < 1) + fun_l14_n305(x) + else + fun_l14_n11(x) + end +end + +def fun_l13_n776(x) + if (x < 1) + fun_l14_n638(x) + else + fun_l14_n161(x) + end +end + +def fun_l13_n777(x) + if (x < 1) + fun_l14_n2(x) + else + fun_l14_n176(x) + end +end + +def fun_l13_n778(x) + if (x < 1) + fun_l14_n967(x) + else + fun_l14_n739(x) + end +end + +def fun_l13_n779(x) + if (x < 1) + fun_l14_n961(x) + else + fun_l14_n609(x) + end +end + +def fun_l13_n780(x) + if (x < 1) + fun_l14_n207(x) + else + fun_l14_n910(x) + end +end + +def fun_l13_n781(x) + if (x < 1) + fun_l14_n370(x) + else + fun_l14_n163(x) + end +end + +def fun_l13_n782(x) + if (x < 1) + fun_l14_n140(x) + else + fun_l14_n816(x) + end +end + +def fun_l13_n783(x) + if (x < 1) + fun_l14_n351(x) + else + fun_l14_n406(x) + end +end + +def fun_l13_n784(x) + if (x < 1) + fun_l14_n790(x) + else + fun_l14_n175(x) + end +end + +def fun_l13_n785(x) + if (x < 1) + fun_l14_n644(x) + else + fun_l14_n713(x) + end +end + +def fun_l13_n786(x) + if (x < 1) + fun_l14_n800(x) + else + fun_l14_n257(x) + end +end + +def fun_l13_n787(x) + if (x < 1) + fun_l14_n248(x) + else + fun_l14_n709(x) + end +end + +def fun_l13_n788(x) + if (x < 1) + fun_l14_n280(x) + else + fun_l14_n485(x) + end +end + +def fun_l13_n789(x) + if (x < 1) + fun_l14_n900(x) + else + fun_l14_n675(x) + end +end + +def fun_l13_n790(x) + if (x < 1) + fun_l14_n65(x) + else + fun_l14_n426(x) + end +end + +def fun_l13_n791(x) + if (x < 1) + fun_l14_n410(x) + else + fun_l14_n484(x) + end +end + +def fun_l13_n792(x) + if (x < 1) + fun_l14_n741(x) + else + fun_l14_n13(x) + end +end + +def fun_l13_n793(x) + if (x < 1) + fun_l14_n550(x) + else + fun_l14_n884(x) + end +end + +def fun_l13_n794(x) + if (x < 1) + fun_l14_n120(x) + else + fun_l14_n262(x) + end +end + +def fun_l13_n795(x) + if (x < 1) + fun_l14_n537(x) + else + fun_l14_n980(x) + end +end + +def fun_l13_n796(x) + if (x < 1) + fun_l14_n742(x) + else + fun_l14_n6(x) + end +end + +def fun_l13_n797(x) + if (x < 1) + fun_l14_n986(x) + else + fun_l14_n434(x) + end +end + +def fun_l13_n798(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n658(x) + end +end + +def fun_l13_n799(x) + if (x < 1) + fun_l14_n838(x) + else + fun_l14_n810(x) + end +end + +def fun_l13_n800(x) + if (x < 1) + fun_l14_n79(x) + else + fun_l14_n695(x) + end +end + +def fun_l13_n801(x) + if (x < 1) + fun_l14_n99(x) + else + fun_l14_n26(x) + end +end + +def fun_l13_n802(x) + if (x < 1) + fun_l14_n839(x) + else + fun_l14_n430(x) + end +end + +def fun_l13_n803(x) + if (x < 1) + fun_l14_n410(x) + else + fun_l14_n403(x) + end +end + +def fun_l13_n804(x) + if (x < 1) + fun_l14_n143(x) + else + fun_l14_n689(x) + end +end + +def fun_l13_n805(x) + if (x < 1) + fun_l14_n695(x) + else + fun_l14_n721(x) + end +end + +def fun_l13_n806(x) + if (x < 1) + fun_l14_n418(x) + else + fun_l14_n508(x) + end +end + +def fun_l13_n807(x) + if (x < 1) + fun_l14_n569(x) + else + fun_l14_n86(x) + end +end + +def fun_l13_n808(x) + if (x < 1) + fun_l14_n670(x) + else + fun_l14_n690(x) + end +end + +def fun_l13_n809(x) + if (x < 1) + fun_l14_n283(x) + else + fun_l14_n630(x) + end +end + +def fun_l13_n810(x) + if (x < 1) + fun_l14_n54(x) + else + fun_l14_n180(x) + end +end + +def fun_l13_n811(x) + if (x < 1) + fun_l14_n669(x) + else + fun_l14_n131(x) + end +end + +def fun_l13_n812(x) + if (x < 1) + fun_l14_n972(x) + else + fun_l14_n948(x) + end +end + +def fun_l13_n813(x) + if (x < 1) + fun_l14_n585(x) + else + fun_l14_n244(x) + end +end + +def fun_l13_n814(x) + if (x < 1) + fun_l14_n277(x) + else + fun_l14_n530(x) + end +end + +def fun_l13_n815(x) + if (x < 1) + fun_l14_n908(x) + else + fun_l14_n380(x) + end +end + +def fun_l13_n816(x) + if (x < 1) + fun_l14_n520(x) + else + fun_l14_n382(x) + end +end + +def fun_l13_n817(x) + if (x < 1) + fun_l14_n40(x) + else + fun_l14_n757(x) + end +end + +def fun_l13_n818(x) + if (x < 1) + fun_l14_n220(x) + else + fun_l14_n781(x) + end +end + +def fun_l13_n819(x) + if (x < 1) + fun_l14_n507(x) + else + fun_l14_n602(x) + end +end + +def fun_l13_n820(x) + if (x < 1) + fun_l14_n39(x) + else + fun_l14_n798(x) + end +end + +def fun_l13_n821(x) + if (x < 1) + fun_l14_n412(x) + else + fun_l14_n58(x) + end +end + +def fun_l13_n822(x) + if (x < 1) + fun_l14_n599(x) + else + fun_l14_n206(x) + end +end + +def fun_l13_n823(x) + if (x < 1) + fun_l14_n294(x) + else + fun_l14_n711(x) + end +end + +def fun_l13_n824(x) + if (x < 1) + fun_l14_n421(x) + else + fun_l14_n191(x) + end +end + +def fun_l13_n825(x) + if (x < 1) + fun_l14_n598(x) + else + fun_l14_n547(x) + end +end + +def fun_l13_n826(x) + if (x < 1) + fun_l14_n131(x) + else + fun_l14_n29(x) + end +end + +def fun_l13_n827(x) + if (x < 1) + fun_l14_n19(x) + else + fun_l14_n213(x) + end +end + +def fun_l13_n828(x) + if (x < 1) + fun_l14_n202(x) + else + fun_l14_n195(x) + end +end + +def fun_l13_n829(x) + if (x < 1) + fun_l14_n133(x) + else + fun_l14_n949(x) + end +end + +def fun_l13_n830(x) + if (x < 1) + fun_l14_n402(x) + else + fun_l14_n762(x) + end +end + +def fun_l13_n831(x) + if (x < 1) + fun_l14_n233(x) + else + fun_l14_n984(x) + end +end + +def fun_l13_n832(x) + if (x < 1) + fun_l14_n309(x) + else + fun_l14_n545(x) + end +end + +def fun_l13_n833(x) + if (x < 1) + fun_l14_n160(x) + else + fun_l14_n434(x) + end +end + +def fun_l13_n834(x) + if (x < 1) + fun_l14_n909(x) + else + fun_l14_n681(x) + end +end + +def fun_l13_n835(x) + if (x < 1) + fun_l14_n747(x) + else + fun_l14_n813(x) + end +end + +def fun_l13_n836(x) + if (x < 1) + fun_l14_n338(x) + else + fun_l14_n592(x) + end +end + +def fun_l13_n837(x) + if (x < 1) + fun_l14_n707(x) + else + fun_l14_n587(x) + end +end + +def fun_l13_n838(x) + if (x < 1) + fun_l14_n655(x) + else + fun_l14_n207(x) + end +end + +def fun_l13_n839(x) + if (x < 1) + fun_l14_n231(x) + else + fun_l14_n459(x) + end +end + +def fun_l13_n840(x) + if (x < 1) + fun_l14_n351(x) + else + fun_l14_n228(x) + end +end + +def fun_l13_n841(x) + if (x < 1) + fun_l14_n205(x) + else + fun_l14_n628(x) + end +end + +def fun_l13_n842(x) + if (x < 1) + fun_l14_n725(x) + else + fun_l14_n246(x) + end +end + +def fun_l13_n843(x) + if (x < 1) + fun_l14_n297(x) + else + fun_l14_n891(x) + end +end + +def fun_l13_n844(x) + if (x < 1) + fun_l14_n598(x) + else + fun_l14_n168(x) + end +end + +def fun_l13_n845(x) + if (x < 1) + fun_l14_n101(x) + else + fun_l14_n681(x) + end +end + +def fun_l13_n846(x) + if (x < 1) + fun_l14_n162(x) + else + fun_l14_n270(x) + end +end + +def fun_l13_n847(x) + if (x < 1) + fun_l14_n84(x) + else + fun_l14_n957(x) + end +end + +def fun_l13_n848(x) + if (x < 1) + fun_l14_n16(x) + else + fun_l14_n708(x) + end +end + +def fun_l13_n849(x) + if (x < 1) + fun_l14_n636(x) + else + fun_l14_n518(x) + end +end + +def fun_l13_n850(x) + if (x < 1) + fun_l14_n379(x) + else + fun_l14_n595(x) + end +end + +def fun_l13_n851(x) + if (x < 1) + fun_l14_n258(x) + else + fun_l14_n757(x) + end +end + +def fun_l13_n852(x) + if (x < 1) + fun_l14_n995(x) + else + fun_l14_n380(x) + end +end + +def fun_l13_n853(x) + if (x < 1) + fun_l14_n505(x) + else + fun_l14_n934(x) + end +end + +def fun_l13_n854(x) + if (x < 1) + fun_l14_n268(x) + else + fun_l14_n36(x) + end +end + +def fun_l13_n855(x) + if (x < 1) + fun_l14_n795(x) + else + fun_l14_n905(x) + end +end + +def fun_l13_n856(x) + if (x < 1) + fun_l14_n136(x) + else + fun_l14_n750(x) + end +end + +def fun_l13_n857(x) + if (x < 1) + fun_l14_n120(x) + else + fun_l14_n156(x) + end +end + +def fun_l13_n858(x) + if (x < 1) + fun_l14_n157(x) + else + fun_l14_n414(x) + end +end + +def fun_l13_n859(x) + if (x < 1) + fun_l14_n926(x) + else + fun_l14_n718(x) + end +end + +def fun_l13_n860(x) + if (x < 1) + fun_l14_n904(x) + else + fun_l14_n821(x) + end +end + +def fun_l13_n861(x) + if (x < 1) + fun_l14_n887(x) + else + fun_l14_n407(x) + end +end + +def fun_l13_n862(x) + if (x < 1) + fun_l14_n870(x) + else + fun_l14_n950(x) + end +end + +def fun_l13_n863(x) + if (x < 1) + fun_l14_n267(x) + else + fun_l14_n712(x) + end +end + +def fun_l13_n864(x) + if (x < 1) + fun_l14_n409(x) + else + fun_l14_n309(x) + end +end + +def fun_l13_n865(x) + if (x < 1) + fun_l14_n345(x) + else + fun_l14_n110(x) + end +end + +def fun_l13_n866(x) + if (x < 1) + fun_l14_n401(x) + else + fun_l14_n970(x) + end +end + +def fun_l13_n867(x) + if (x < 1) + fun_l14_n814(x) + else + fun_l14_n260(x) + end +end + +def fun_l13_n868(x) + if (x < 1) + fun_l14_n490(x) + else + fun_l14_n31(x) + end +end + +def fun_l13_n869(x) + if (x < 1) + fun_l14_n214(x) + else + fun_l14_n425(x) + end +end + +def fun_l13_n870(x) + if (x < 1) + fun_l14_n660(x) + else + fun_l14_n703(x) + end +end + +def fun_l13_n871(x) + if (x < 1) + fun_l14_n650(x) + else + fun_l14_n257(x) + end +end + +def fun_l13_n872(x) + if (x < 1) + fun_l14_n701(x) + else + fun_l14_n55(x) + end +end + +def fun_l13_n873(x) + if (x < 1) + fun_l14_n225(x) + else + fun_l14_n701(x) + end +end + +def fun_l13_n874(x) + if (x < 1) + fun_l14_n525(x) + else + fun_l14_n793(x) + end +end + +def fun_l13_n875(x) + if (x < 1) + fun_l14_n87(x) + else + fun_l14_n807(x) + end +end + +def fun_l13_n876(x) + if (x < 1) + fun_l14_n24(x) + else + fun_l14_n15(x) + end +end + +def fun_l13_n877(x) + if (x < 1) + fun_l14_n120(x) + else + fun_l14_n551(x) + end +end + +def fun_l13_n878(x) + if (x < 1) + fun_l14_n703(x) + else + fun_l14_n67(x) + end +end + +def fun_l13_n879(x) + if (x < 1) + fun_l14_n496(x) + else + fun_l14_n197(x) + end +end + +def fun_l13_n880(x) + if (x < 1) + fun_l14_n369(x) + else + fun_l14_n834(x) + end +end + +def fun_l13_n881(x) + if (x < 1) + fun_l14_n892(x) + else + fun_l14_n210(x) + end +end + +def fun_l13_n882(x) + if (x < 1) + fun_l14_n587(x) + else + fun_l14_n472(x) + end +end + +def fun_l13_n883(x) + if (x < 1) + fun_l14_n1(x) + else + fun_l14_n778(x) + end +end + +def fun_l13_n884(x) + if (x < 1) + fun_l14_n762(x) + else + fun_l14_n286(x) + end +end + +def fun_l13_n885(x) + if (x < 1) + fun_l14_n36(x) + else + fun_l14_n326(x) + end +end + +def fun_l13_n886(x) + if (x < 1) + fun_l14_n857(x) + else + fun_l14_n564(x) + end +end + +def fun_l13_n887(x) + if (x < 1) + fun_l14_n461(x) + else + fun_l14_n415(x) + end +end + +def fun_l13_n888(x) + if (x < 1) + fun_l14_n225(x) + else + fun_l14_n783(x) + end +end + +def fun_l13_n889(x) + if (x < 1) + fun_l14_n10(x) + else + fun_l14_n114(x) + end +end + +def fun_l13_n890(x) + if (x < 1) + fun_l14_n670(x) + else + fun_l14_n473(x) + end +end + +def fun_l13_n891(x) + if (x < 1) + fun_l14_n777(x) + else + fun_l14_n98(x) + end +end + +def fun_l13_n892(x) + if (x < 1) + fun_l14_n600(x) + else + fun_l14_n808(x) + end +end + +def fun_l13_n893(x) + if (x < 1) + fun_l14_n605(x) + else + fun_l14_n687(x) + end +end + +def fun_l13_n894(x) + if (x < 1) + fun_l14_n29(x) + else + fun_l14_n190(x) + end +end + +def fun_l13_n895(x) + if (x < 1) + fun_l14_n26(x) + else + fun_l14_n887(x) + end +end + +def fun_l13_n896(x) + if (x < 1) + fun_l14_n680(x) + else + fun_l14_n413(x) + end +end + +def fun_l13_n897(x) + if (x < 1) + fun_l14_n634(x) + else + fun_l14_n184(x) + end +end + +def fun_l13_n898(x) + if (x < 1) + fun_l14_n420(x) + else + fun_l14_n603(x) + end +end + +def fun_l13_n899(x) + if (x < 1) + fun_l14_n702(x) + else + fun_l14_n54(x) + end +end + +def fun_l13_n900(x) + if (x < 1) + fun_l14_n620(x) + else + fun_l14_n849(x) + end +end + +def fun_l13_n901(x) + if (x < 1) + fun_l14_n848(x) + else + fun_l14_n384(x) + end +end + +def fun_l13_n902(x) + if (x < 1) + fun_l14_n726(x) + else + fun_l14_n624(x) + end +end + +def fun_l13_n903(x) + if (x < 1) + fun_l14_n663(x) + else + fun_l14_n395(x) + end +end + +def fun_l13_n904(x) + if (x < 1) + fun_l14_n803(x) + else + fun_l14_n979(x) + end +end + +def fun_l13_n905(x) + if (x < 1) + fun_l14_n487(x) + else + fun_l14_n530(x) + end +end + +def fun_l13_n906(x) + if (x < 1) + fun_l14_n737(x) + else + fun_l14_n679(x) + end +end + +def fun_l13_n907(x) + if (x < 1) + fun_l14_n815(x) + else + fun_l14_n84(x) + end +end + +def fun_l13_n908(x) + if (x < 1) + fun_l14_n116(x) + else + fun_l14_n820(x) + end +end + +def fun_l13_n909(x) + if (x < 1) + fun_l14_n353(x) + else + fun_l14_n949(x) + end +end + +def fun_l13_n910(x) + if (x < 1) + fun_l14_n271(x) + else + fun_l14_n168(x) + end +end + +def fun_l13_n911(x) + if (x < 1) + fun_l14_n54(x) + else + fun_l14_n236(x) + end +end + +def fun_l13_n912(x) + if (x < 1) + fun_l14_n391(x) + else + fun_l14_n152(x) + end +end + +def fun_l13_n913(x) + if (x < 1) + fun_l14_n450(x) + else + fun_l14_n521(x) + end +end + +def fun_l13_n914(x) + if (x < 1) + fun_l14_n36(x) + else + fun_l14_n995(x) + end +end + +def fun_l13_n915(x) + if (x < 1) + fun_l14_n177(x) + else + fun_l14_n358(x) + end +end + +def fun_l13_n916(x) + if (x < 1) + fun_l14_n36(x) + else + fun_l14_n32(x) + end +end + +def fun_l13_n917(x) + if (x < 1) + fun_l14_n970(x) + else + fun_l14_n957(x) + end +end + +def fun_l13_n918(x) + if (x < 1) + fun_l14_n229(x) + else + fun_l14_n138(x) + end +end + +def fun_l13_n919(x) + if (x < 1) + fun_l14_n439(x) + else + fun_l14_n641(x) + end +end + +def fun_l13_n920(x) + if (x < 1) + fun_l14_n318(x) + else + fun_l14_n649(x) + end +end + +def fun_l13_n921(x) + if (x < 1) + fun_l14_n455(x) + else + fun_l14_n312(x) + end +end + +def fun_l13_n922(x) + if (x < 1) + fun_l14_n15(x) + else + fun_l14_n825(x) + end +end + +def fun_l13_n923(x) + if (x < 1) + fun_l14_n546(x) + else + fun_l14_n629(x) + end +end + +def fun_l13_n924(x) + if (x < 1) + fun_l14_n298(x) + else + fun_l14_n563(x) + end +end + +def fun_l13_n925(x) + if (x < 1) + fun_l14_n312(x) + else + fun_l14_n736(x) + end +end + +def fun_l13_n926(x) + if (x < 1) + fun_l14_n767(x) + else + fun_l14_n107(x) + end +end + +def fun_l13_n927(x) + if (x < 1) + fun_l14_n966(x) + else + fun_l14_n765(x) + end +end + +def fun_l13_n928(x) + if (x < 1) + fun_l14_n545(x) + else + fun_l14_n383(x) + end +end + +def fun_l13_n929(x) + if (x < 1) + fun_l14_n389(x) + else + fun_l14_n48(x) + end +end + +def fun_l13_n930(x) + if (x < 1) + fun_l14_n142(x) + else + fun_l14_n632(x) + end +end + +def fun_l13_n931(x) + if (x < 1) + fun_l14_n146(x) + else + fun_l14_n275(x) + end +end + +def fun_l13_n932(x) + if (x < 1) + fun_l14_n754(x) + else + fun_l14_n380(x) + end +end + +def fun_l13_n933(x) + if (x < 1) + fun_l14_n561(x) + else + fun_l14_n677(x) + end +end + +def fun_l13_n934(x) + if (x < 1) + fun_l14_n253(x) + else + fun_l14_n86(x) + end +end + +def fun_l13_n935(x) + if (x < 1) + fun_l14_n528(x) + else + fun_l14_n177(x) + end +end + +def fun_l13_n936(x) + if (x < 1) + fun_l14_n938(x) + else + fun_l14_n265(x) + end +end + +def fun_l13_n937(x) + if (x < 1) + fun_l14_n763(x) + else + fun_l14_n662(x) + end +end + +def fun_l13_n938(x) + if (x < 1) + fun_l14_n836(x) + else + fun_l14_n734(x) + end +end + +def fun_l13_n939(x) + if (x < 1) + fun_l14_n127(x) + else + fun_l14_n111(x) + end +end + +def fun_l13_n940(x) + if (x < 1) + fun_l14_n356(x) + else + fun_l14_n544(x) + end +end + +def fun_l13_n941(x) + if (x < 1) + fun_l14_n525(x) + else + fun_l14_n762(x) + end +end + +def fun_l13_n942(x) + if (x < 1) + fun_l14_n333(x) + else + fun_l14_n639(x) + end +end + +def fun_l13_n943(x) + if (x < 1) + fun_l14_n452(x) + else + fun_l14_n944(x) + end +end + +def fun_l13_n944(x) + if (x < 1) + fun_l14_n827(x) + else + fun_l14_n961(x) + end +end + +def fun_l13_n945(x) + if (x < 1) + fun_l14_n991(x) + else + fun_l14_n431(x) + end +end + +def fun_l13_n946(x) + if (x < 1) + fun_l14_n646(x) + else + fun_l14_n183(x) + end +end + +def fun_l13_n947(x) + if (x < 1) + fun_l14_n107(x) + else + fun_l14_n273(x) + end +end + +def fun_l13_n948(x) + if (x < 1) + fun_l14_n210(x) + else + fun_l14_n664(x) + end +end + +def fun_l13_n949(x) + if (x < 1) + fun_l14_n542(x) + else + fun_l14_n462(x) + end +end + +def fun_l13_n950(x) + if (x < 1) + fun_l14_n891(x) + else + fun_l14_n486(x) + end +end + +def fun_l13_n951(x) + if (x < 1) + fun_l14_n527(x) + else + fun_l14_n721(x) + end +end + +def fun_l13_n952(x) + if (x < 1) + fun_l14_n745(x) + else + fun_l14_n11(x) + end +end + +def fun_l13_n953(x) + if (x < 1) + fun_l14_n427(x) + else + fun_l14_n521(x) + end +end + +def fun_l13_n954(x) + if (x < 1) + fun_l14_n907(x) + else + fun_l14_n878(x) + end +end + +def fun_l13_n955(x) + if (x < 1) + fun_l14_n818(x) + else + fun_l14_n722(x) + end +end + +def fun_l13_n956(x) + if (x < 1) + fun_l14_n567(x) + else + fun_l14_n71(x) + end +end + +def fun_l13_n957(x) + if (x < 1) + fun_l14_n203(x) + else + fun_l14_n221(x) + end +end + +def fun_l13_n958(x) + if (x < 1) + fun_l14_n173(x) + else + fun_l14_n854(x) + end +end + +def fun_l13_n959(x) + if (x < 1) + fun_l14_n201(x) + else + fun_l14_n930(x) + end +end + +def fun_l13_n960(x) + if (x < 1) + fun_l14_n736(x) + else + fun_l14_n539(x) + end +end + +def fun_l13_n961(x) + if (x < 1) + fun_l14_n459(x) + else + fun_l14_n771(x) + end +end + +def fun_l13_n962(x) + if (x < 1) + fun_l14_n682(x) + else + fun_l14_n19(x) + end +end + +def fun_l13_n963(x) + if (x < 1) + fun_l14_n897(x) + else + fun_l14_n650(x) + end +end + +def fun_l13_n964(x) + if (x < 1) + fun_l14_n814(x) + else + fun_l14_n726(x) + end +end + +def fun_l13_n965(x) + if (x < 1) + fun_l14_n31(x) + else + fun_l14_n211(x) + end +end + +def fun_l13_n966(x) + if (x < 1) + fun_l14_n89(x) + else + fun_l14_n407(x) + end +end + +def fun_l13_n967(x) + if (x < 1) + fun_l14_n772(x) + else + fun_l14_n7(x) + end +end + +def fun_l13_n968(x) + if (x < 1) + fun_l14_n764(x) + else + fun_l14_n523(x) + end +end + +def fun_l13_n969(x) + if (x < 1) + fun_l14_n680(x) + else + fun_l14_n674(x) + end +end + +def fun_l13_n970(x) + if (x < 1) + fun_l14_n517(x) + else + fun_l14_n346(x) + end +end + +def fun_l13_n971(x) + if (x < 1) + fun_l14_n136(x) + else + fun_l14_n921(x) + end +end + +def fun_l13_n972(x) + if (x < 1) + fun_l14_n400(x) + else + fun_l14_n901(x) + end +end + +def fun_l13_n973(x) + if (x < 1) + fun_l14_n62(x) + else + fun_l14_n784(x) + end +end + +def fun_l13_n974(x) + if (x < 1) + fun_l14_n411(x) + else + fun_l14_n889(x) + end +end + +def fun_l13_n975(x) + if (x < 1) + fun_l14_n291(x) + else + fun_l14_n198(x) + end +end + +def fun_l13_n976(x) + if (x < 1) + fun_l14_n229(x) + else + fun_l14_n346(x) + end +end + +def fun_l13_n977(x) + if (x < 1) + fun_l14_n769(x) + else + fun_l14_n381(x) + end +end + +def fun_l13_n978(x) + if (x < 1) + fun_l14_n430(x) + else + fun_l14_n205(x) + end +end + +def fun_l13_n979(x) + if (x < 1) + fun_l14_n170(x) + else + fun_l14_n927(x) + end +end + +def fun_l13_n980(x) + if (x < 1) + fun_l14_n12(x) + else + fun_l14_n605(x) + end +end + +def fun_l13_n981(x) + if (x < 1) + fun_l14_n613(x) + else + fun_l14_n912(x) + end +end + +def fun_l13_n982(x) + if (x < 1) + fun_l14_n982(x) + else + fun_l14_n707(x) + end +end + +def fun_l13_n983(x) + if (x < 1) + fun_l14_n230(x) + else + fun_l14_n239(x) + end +end + +def fun_l13_n984(x) + if (x < 1) + fun_l14_n55(x) + else + fun_l14_n337(x) + end +end + +def fun_l13_n985(x) + if (x < 1) + fun_l14_n853(x) + else + fun_l14_n425(x) + end +end + +def fun_l13_n986(x) + if (x < 1) + fun_l14_n14(x) + else + fun_l14_n921(x) + end +end + +def fun_l13_n987(x) + if (x < 1) + fun_l14_n166(x) + else + fun_l14_n948(x) + end +end + +def fun_l13_n988(x) + if (x < 1) + fun_l14_n752(x) + else + fun_l14_n226(x) + end +end + +def fun_l13_n989(x) + if (x < 1) + fun_l14_n730(x) + else + fun_l14_n671(x) + end +end + +def fun_l13_n990(x) + if (x < 1) + fun_l14_n603(x) + else + fun_l14_n903(x) + end +end + +def fun_l13_n991(x) + if (x < 1) + fun_l14_n598(x) + else + fun_l14_n842(x) + end +end + +def fun_l13_n992(x) + if (x < 1) + fun_l14_n230(x) + else + fun_l14_n704(x) + end +end + +def fun_l13_n993(x) + if (x < 1) + fun_l14_n897(x) + else + fun_l14_n190(x) + end +end + +def fun_l13_n994(x) + if (x < 1) + fun_l14_n640(x) + else + fun_l14_n622(x) + end +end + +def fun_l13_n995(x) + if (x < 1) + fun_l14_n988(x) + else + fun_l14_n471(x) + end +end + +def fun_l13_n996(x) + if (x < 1) + fun_l14_n721(x) + else + fun_l14_n672(x) + end +end + +def fun_l13_n997(x) + if (x < 1) + fun_l14_n425(x) + else + fun_l14_n885(x) + end +end + +def fun_l13_n998(x) + if (x < 1) + fun_l14_n279(x) + else + fun_l14_n966(x) + end +end + +def fun_l13_n999(x) + if (x < 1) + fun_l14_n610(x) + else + fun_l14_n319(x) + end +end + +def fun_l14_n0(x) + if (x < 1) + fun_l15_n46(x) + else + fun_l15_n966(x) + end +end + +def fun_l14_n1(x) + if (x < 1) + fun_l15_n360(x) + else + fun_l15_n637(x) + end +end + +def fun_l14_n2(x) + if (x < 1) + fun_l15_n381(x) + else + fun_l15_n728(x) + end +end + +def fun_l14_n3(x) + if (x < 1) + fun_l15_n189(x) + else + fun_l15_n826(x) + end +end + +def fun_l14_n4(x) + if (x < 1) + fun_l15_n789(x) + else + fun_l15_n157(x) + end +end + +def fun_l14_n5(x) + if (x < 1) + fun_l15_n132(x) + else + fun_l15_n703(x) + end +end + +def fun_l14_n6(x) + if (x < 1) + fun_l15_n64(x) + else + fun_l15_n537(x) + end +end + +def fun_l14_n7(x) + if (x < 1) + fun_l15_n423(x) + else + fun_l15_n162(x) + end +end + +def fun_l14_n8(x) + if (x < 1) + fun_l15_n177(x) + else + fun_l15_n923(x) + end +end + +def fun_l14_n9(x) + if (x < 1) + fun_l15_n508(x) + else + fun_l15_n135(x) + end +end + +def fun_l14_n10(x) + if (x < 1) + fun_l15_n640(x) + else + fun_l15_n869(x) + end +end + +def fun_l14_n11(x) + if (x < 1) + fun_l15_n592(x) + else + fun_l15_n519(x) + end +end + +def fun_l14_n12(x) + if (x < 1) + fun_l15_n332(x) + else + fun_l15_n263(x) + end +end + +def fun_l14_n13(x) + if (x < 1) + fun_l15_n644(x) + else + fun_l15_n21(x) + end +end + +def fun_l14_n14(x) + if (x < 1) + fun_l15_n436(x) + else + fun_l15_n566(x) + end +end + +def fun_l14_n15(x) + if (x < 1) + fun_l15_n160(x) + else + fun_l15_n291(x) + end +end + +def fun_l14_n16(x) + if (x < 1) + fun_l15_n726(x) + else + fun_l15_n704(x) + end +end + +def fun_l14_n17(x) + if (x < 1) + fun_l15_n237(x) + else + fun_l15_n962(x) + end +end + +def fun_l14_n18(x) + if (x < 1) + fun_l15_n941(x) + else + fun_l15_n217(x) + end +end + +def fun_l14_n19(x) + if (x < 1) + fun_l15_n904(x) + else + fun_l15_n36(x) + end +end + +def fun_l14_n20(x) + if (x < 1) + fun_l15_n74(x) + else + fun_l15_n790(x) + end +end + +def fun_l14_n21(x) + if (x < 1) + fun_l15_n694(x) + else + fun_l15_n298(x) + end +end + +def fun_l14_n22(x) + if (x < 1) + fun_l15_n757(x) + else + fun_l15_n636(x) + end +end + +def fun_l14_n23(x) + if (x < 1) + fun_l15_n989(x) + else + fun_l15_n508(x) + end +end + +def fun_l14_n24(x) + if (x < 1) + fun_l15_n80(x) + else + fun_l15_n686(x) + end +end + +def fun_l14_n25(x) + if (x < 1) + fun_l15_n365(x) + else + fun_l15_n922(x) + end +end + +def fun_l14_n26(x) + if (x < 1) + fun_l15_n922(x) + else + fun_l15_n207(x) + end +end + +def fun_l14_n27(x) + if (x < 1) + fun_l15_n406(x) + else + fun_l15_n481(x) + end +end + +def fun_l14_n28(x) + if (x < 1) + fun_l15_n986(x) + else + fun_l15_n181(x) + end +end + +def fun_l14_n29(x) + if (x < 1) + fun_l15_n958(x) + else + fun_l15_n804(x) + end +end + +def fun_l14_n30(x) + if (x < 1) + fun_l15_n233(x) + else + fun_l15_n877(x) + end +end + +def fun_l14_n31(x) + if (x < 1) + fun_l15_n648(x) + else + fun_l15_n547(x) + end +end + +def fun_l14_n32(x) + if (x < 1) + fun_l15_n641(x) + else + fun_l15_n628(x) + end +end + +def fun_l14_n33(x) + if (x < 1) + fun_l15_n351(x) + else + fun_l15_n280(x) + end +end + +def fun_l14_n34(x) + if (x < 1) + fun_l15_n373(x) + else + fun_l15_n948(x) + end +end + +def fun_l14_n35(x) + if (x < 1) + fun_l15_n761(x) + else + fun_l15_n384(x) + end +end + +def fun_l14_n36(x) + if (x < 1) + fun_l15_n75(x) + else + fun_l15_n581(x) + end +end + +def fun_l14_n37(x) + if (x < 1) + fun_l15_n962(x) + else + fun_l15_n723(x) + end +end + +def fun_l14_n38(x) + if (x < 1) + fun_l15_n422(x) + else + fun_l15_n953(x) + end +end + +def fun_l14_n39(x) + if (x < 1) + fun_l15_n123(x) + else + fun_l15_n989(x) + end +end + +def fun_l14_n40(x) + if (x < 1) + fun_l15_n789(x) + else + fun_l15_n472(x) + end +end + +def fun_l14_n41(x) + if (x < 1) + fun_l15_n261(x) + else + fun_l15_n997(x) + end +end + +def fun_l14_n42(x) + if (x < 1) + fun_l15_n231(x) + else + fun_l15_n703(x) + end +end + +def fun_l14_n43(x) + if (x < 1) + fun_l15_n520(x) + else + fun_l15_n252(x) + end +end + +def fun_l14_n44(x) + if (x < 1) + fun_l15_n966(x) + else + fun_l15_n244(x) + end +end + +def fun_l14_n45(x) + if (x < 1) + fun_l15_n192(x) + else + fun_l15_n280(x) + end +end + +def fun_l14_n46(x) + if (x < 1) + fun_l15_n422(x) + else + fun_l15_n847(x) + end +end + +def fun_l14_n47(x) + if (x < 1) + fun_l15_n228(x) + else + fun_l15_n564(x) + end +end + +def fun_l14_n48(x) + if (x < 1) + fun_l15_n263(x) + else + fun_l15_n226(x) + end +end + +def fun_l14_n49(x) + if (x < 1) + fun_l15_n440(x) + else + fun_l15_n592(x) + end +end + +def fun_l14_n50(x) + if (x < 1) + fun_l15_n464(x) + else + fun_l15_n135(x) + end +end + +def fun_l14_n51(x) + if (x < 1) + fun_l15_n903(x) + else + fun_l15_n821(x) + end +end + +def fun_l14_n52(x) + if (x < 1) + fun_l15_n472(x) + else + fun_l15_n322(x) + end +end + +def fun_l14_n53(x) + if (x < 1) + fun_l15_n107(x) + else + fun_l15_n497(x) + end +end + +def fun_l14_n54(x) + if (x < 1) + fun_l15_n692(x) + else + fun_l15_n392(x) + end +end + +def fun_l14_n55(x) + if (x < 1) + fun_l15_n694(x) + else + fun_l15_n995(x) + end +end + +def fun_l14_n56(x) + if (x < 1) + fun_l15_n181(x) + else + fun_l15_n200(x) + end +end + +def fun_l14_n57(x) + if (x < 1) + fun_l15_n721(x) + else + fun_l15_n849(x) + end +end + +def fun_l14_n58(x) + if (x < 1) + fun_l15_n626(x) + else + fun_l15_n866(x) + end +end + +def fun_l14_n59(x) + if (x < 1) + fun_l15_n689(x) + else + fun_l15_n387(x) + end +end + +def fun_l14_n60(x) + if (x < 1) + fun_l15_n805(x) + else + fun_l15_n842(x) + end +end + +def fun_l14_n61(x) + if (x < 1) + fun_l15_n457(x) + else + fun_l15_n472(x) + end +end + +def fun_l14_n62(x) + if (x < 1) + fun_l15_n884(x) + else + fun_l15_n786(x) + end +end + +def fun_l14_n63(x) + if (x < 1) + fun_l15_n509(x) + else + fun_l15_n106(x) + end +end + +def fun_l14_n64(x) + if (x < 1) + fun_l15_n600(x) + else + fun_l15_n314(x) + end +end + +def fun_l14_n65(x) + if (x < 1) + fun_l15_n761(x) + else + fun_l15_n362(x) + end +end + +def fun_l14_n66(x) + if (x < 1) + fun_l15_n812(x) + else + fun_l15_n640(x) + end +end + +def fun_l14_n67(x) + if (x < 1) + fun_l15_n862(x) + else + fun_l15_n627(x) + end +end + +def fun_l14_n68(x) + if (x < 1) + fun_l15_n503(x) + else + fun_l15_n381(x) + end +end + +def fun_l14_n69(x) + if (x < 1) + fun_l15_n482(x) + else + fun_l15_n851(x) + end +end + +def fun_l14_n70(x) + if (x < 1) + fun_l15_n253(x) + else + fun_l15_n728(x) + end +end + +def fun_l14_n71(x) + if (x < 1) + fun_l15_n195(x) + else + fun_l15_n537(x) + end +end + +def fun_l14_n72(x) + if (x < 1) + fun_l15_n482(x) + else + fun_l15_n604(x) + end +end + +def fun_l14_n73(x) + if (x < 1) + fun_l15_n373(x) + else + fun_l15_n502(x) + end +end + +def fun_l14_n74(x) + if (x < 1) + fun_l15_n183(x) + else + fun_l15_n50(x) + end +end + +def fun_l14_n75(x) + if (x < 1) + fun_l15_n397(x) + else + fun_l15_n467(x) + end +end + +def fun_l14_n76(x) + if (x < 1) + fun_l15_n207(x) + else + fun_l15_n566(x) + end +end + +def fun_l14_n77(x) + if (x < 1) + fun_l15_n416(x) + else + fun_l15_n846(x) + end +end + +def fun_l14_n78(x) + if (x < 1) + fun_l15_n426(x) + else + fun_l15_n142(x) + end +end + +def fun_l14_n79(x) + if (x < 1) + fun_l15_n234(x) + else + fun_l15_n5(x) + end +end + +def fun_l14_n80(x) + if (x < 1) + fun_l15_n133(x) + else + fun_l15_n216(x) + end +end + +def fun_l14_n81(x) + if (x < 1) + fun_l15_n23(x) + else + fun_l15_n126(x) + end +end + +def fun_l14_n82(x) + if (x < 1) + fun_l15_n129(x) + else + fun_l15_n614(x) + end +end + +def fun_l14_n83(x) + if (x < 1) + fun_l15_n560(x) + else + fun_l15_n559(x) + end +end + +def fun_l14_n84(x) + if (x < 1) + fun_l15_n113(x) + else + fun_l15_n300(x) + end +end + +def fun_l14_n85(x) + if (x < 1) + fun_l15_n584(x) + else + fun_l15_n249(x) + end +end + +def fun_l14_n86(x) + if (x < 1) + fun_l15_n933(x) + else + fun_l15_n280(x) + end +end + +def fun_l14_n87(x) + if (x < 1) + fun_l15_n528(x) + else + fun_l15_n350(x) + end +end + +def fun_l14_n88(x) + if (x < 1) + fun_l15_n568(x) + else + fun_l15_n762(x) + end +end + +def fun_l14_n89(x) + if (x < 1) + fun_l15_n190(x) + else + fun_l15_n858(x) + end +end + +def fun_l14_n90(x) + if (x < 1) + fun_l15_n896(x) + else + fun_l15_n543(x) + end +end + +def fun_l14_n91(x) + if (x < 1) + fun_l15_n937(x) + else + fun_l15_n593(x) + end +end + +def fun_l14_n92(x) + if (x < 1) + fun_l15_n135(x) + else + fun_l15_n5(x) + end +end + +def fun_l14_n93(x) + if (x < 1) + fun_l15_n351(x) + else + fun_l15_n779(x) + end +end + +def fun_l14_n94(x) + if (x < 1) + fun_l15_n617(x) + else + fun_l15_n375(x) + end +end + +def fun_l14_n95(x) + if (x < 1) + fun_l15_n111(x) + else + fun_l15_n870(x) + end +end + +def fun_l14_n96(x) + if (x < 1) + fun_l15_n187(x) + else + fun_l15_n881(x) + end +end + +def fun_l14_n97(x) + if (x < 1) + fun_l15_n150(x) + else + fun_l15_n98(x) + end +end + +def fun_l14_n98(x) + if (x < 1) + fun_l15_n629(x) + else + fun_l15_n548(x) + end +end + +def fun_l14_n99(x) + if (x < 1) + fun_l15_n37(x) + else + fun_l15_n383(x) + end +end + +def fun_l14_n100(x) + if (x < 1) + fun_l15_n719(x) + else + fun_l15_n503(x) + end +end + +def fun_l14_n101(x) + if (x < 1) + fun_l15_n415(x) + else + fun_l15_n650(x) + end +end + +def fun_l14_n102(x) + if (x < 1) + fun_l15_n924(x) + else + fun_l15_n520(x) + end +end + +def fun_l14_n103(x) + if (x < 1) + fun_l15_n194(x) + else + fun_l15_n613(x) + end +end + +def fun_l14_n104(x) + if (x < 1) + fun_l15_n909(x) + else + fun_l15_n333(x) + end +end + +def fun_l14_n105(x) + if (x < 1) + fun_l15_n586(x) + else + fun_l15_n2(x) + end +end + +def fun_l14_n106(x) + if (x < 1) + fun_l15_n373(x) + else + fun_l15_n316(x) + end +end + +def fun_l14_n107(x) + if (x < 1) + fun_l15_n737(x) + else + fun_l15_n469(x) + end +end + +def fun_l14_n108(x) + if (x < 1) + fun_l15_n841(x) + else + fun_l15_n888(x) + end +end + +def fun_l14_n109(x) + if (x < 1) + fun_l15_n165(x) + else + fun_l15_n108(x) + end +end + +def fun_l14_n110(x) + if (x < 1) + fun_l15_n344(x) + else + fun_l15_n893(x) + end +end + +def fun_l14_n111(x) + if (x < 1) + fun_l15_n424(x) + else + fun_l15_n702(x) + end +end + +def fun_l14_n112(x) + if (x < 1) + fun_l15_n161(x) + else + fun_l15_n827(x) + end +end + +def fun_l14_n113(x) + if (x < 1) + fun_l15_n982(x) + else + fun_l15_n172(x) + end +end + +def fun_l14_n114(x) + if (x < 1) + fun_l15_n233(x) + else + fun_l15_n178(x) + end +end + +def fun_l14_n115(x) + if (x < 1) + fun_l15_n130(x) + else + fun_l15_n266(x) + end +end + +def fun_l14_n116(x) + if (x < 1) + fun_l15_n32(x) + else + fun_l15_n63(x) + end +end + +def fun_l14_n117(x) + if (x < 1) + fun_l15_n117(x) + else + fun_l15_n659(x) + end +end + +def fun_l14_n118(x) + if (x < 1) + fun_l15_n607(x) + else + fun_l15_n516(x) + end +end + +def fun_l14_n119(x) + if (x < 1) + fun_l15_n30(x) + else + fun_l15_n130(x) + end +end + +def fun_l14_n120(x) + if (x < 1) + fun_l15_n510(x) + else + fun_l15_n789(x) + end +end + +def fun_l14_n121(x) + if (x < 1) + fun_l15_n906(x) + else + fun_l15_n700(x) + end +end + +def fun_l14_n122(x) + if (x < 1) + fun_l15_n51(x) + else + fun_l15_n378(x) + end +end + +def fun_l14_n123(x) + if (x < 1) + fun_l15_n243(x) + else + fun_l15_n896(x) + end +end + +def fun_l14_n124(x) + if (x < 1) + fun_l15_n23(x) + else + fun_l15_n648(x) + end +end + +def fun_l14_n125(x) + if (x < 1) + fun_l15_n290(x) + else + fun_l15_n604(x) + end +end + +def fun_l14_n126(x) + if (x < 1) + fun_l15_n410(x) + else + fun_l15_n646(x) + end +end + +def fun_l14_n127(x) + if (x < 1) + fun_l15_n162(x) + else + fun_l15_n43(x) + end +end + +def fun_l14_n128(x) + if (x < 1) + fun_l15_n775(x) + else + fun_l15_n176(x) + end +end + +def fun_l14_n129(x) + if (x < 1) + fun_l15_n642(x) + else + fun_l15_n709(x) + end +end + +def fun_l14_n130(x) + if (x < 1) + fun_l15_n669(x) + else + fun_l15_n936(x) + end +end + +def fun_l14_n131(x) + if (x < 1) + fun_l15_n301(x) + else + fun_l15_n578(x) + end +end + +def fun_l14_n132(x) + if (x < 1) + fun_l15_n112(x) + else + fun_l15_n72(x) + end +end + +def fun_l14_n133(x) + if (x < 1) + fun_l15_n293(x) + else + fun_l15_n516(x) + end +end + +def fun_l14_n134(x) + if (x < 1) + fun_l15_n525(x) + else + fun_l15_n199(x) + end +end + +def fun_l14_n135(x) + if (x < 1) + fun_l15_n168(x) + else + fun_l15_n430(x) + end +end + +def fun_l14_n136(x) + if (x < 1) + fun_l15_n889(x) + else + fun_l15_n635(x) + end +end + +def fun_l14_n137(x) + if (x < 1) + fun_l15_n348(x) + else + fun_l15_n445(x) + end +end + +def fun_l14_n138(x) + if (x < 1) + fun_l15_n828(x) + else + fun_l15_n23(x) + end +end + +def fun_l14_n139(x) + if (x < 1) + fun_l15_n621(x) + else + fun_l15_n25(x) + end +end + +def fun_l14_n140(x) + if (x < 1) + fun_l15_n268(x) + else + fun_l15_n105(x) + end +end + +def fun_l14_n141(x) + if (x < 1) + fun_l15_n296(x) + else + fun_l15_n856(x) + end +end + +def fun_l14_n142(x) + if (x < 1) + fun_l15_n206(x) + else + fun_l15_n417(x) + end +end + +def fun_l14_n143(x) + if (x < 1) + fun_l15_n203(x) + else + fun_l15_n240(x) + end +end + +def fun_l14_n144(x) + if (x < 1) + fun_l15_n556(x) + else + fun_l15_n47(x) + end +end + +def fun_l14_n145(x) + if (x < 1) + fun_l15_n340(x) + else + fun_l15_n511(x) + end +end + +def fun_l14_n146(x) + if (x < 1) + fun_l15_n250(x) + else + fun_l15_n402(x) + end +end + +def fun_l14_n147(x) + if (x < 1) + fun_l15_n4(x) + else + fun_l15_n26(x) + end +end + +def fun_l14_n148(x) + if (x < 1) + fun_l15_n52(x) + else + fun_l15_n366(x) + end +end + +def fun_l14_n149(x) + if (x < 1) + fun_l15_n163(x) + else + fun_l15_n884(x) + end +end + +def fun_l14_n150(x) + if (x < 1) + fun_l15_n677(x) + else + fun_l15_n509(x) + end +end + +def fun_l14_n151(x) + if (x < 1) + fun_l15_n949(x) + else + fun_l15_n393(x) + end +end + +def fun_l14_n152(x) + if (x < 1) + fun_l15_n719(x) + else + fun_l15_n307(x) + end +end + +def fun_l14_n153(x) + if (x < 1) + fun_l15_n12(x) + else + fun_l15_n985(x) + end +end + +def fun_l14_n154(x) + if (x < 1) + fun_l15_n639(x) + else + fun_l15_n367(x) + end +end + +def fun_l14_n155(x) + if (x < 1) + fun_l15_n401(x) + else + fun_l15_n431(x) + end +end + +def fun_l14_n156(x) + if (x < 1) + fun_l15_n897(x) + else + fun_l15_n136(x) + end +end + +def fun_l14_n157(x) + if (x < 1) + fun_l15_n792(x) + else + fun_l15_n865(x) + end +end + +def fun_l14_n158(x) + if (x < 1) + fun_l15_n851(x) + else + fun_l15_n167(x) + end +end + +def fun_l14_n159(x) + if (x < 1) + fun_l15_n643(x) + else + fun_l15_n458(x) + end +end + +def fun_l14_n160(x) + if (x < 1) + fun_l15_n539(x) + else + fun_l15_n36(x) + end +end + +def fun_l14_n161(x) + if (x < 1) + fun_l15_n91(x) + else + fun_l15_n130(x) + end +end + +def fun_l14_n162(x) + if (x < 1) + fun_l15_n214(x) + else + fun_l15_n712(x) + end +end + +def fun_l14_n163(x) + if (x < 1) + fun_l15_n47(x) + else + fun_l15_n799(x) + end +end + +def fun_l14_n164(x) + if (x < 1) + fun_l15_n715(x) + else + fun_l15_n888(x) + end +end + +def fun_l14_n165(x) + if (x < 1) + fun_l15_n904(x) + else + fun_l15_n484(x) + end +end + +def fun_l14_n166(x) + if (x < 1) + fun_l15_n870(x) + else + fun_l15_n121(x) + end +end + +def fun_l14_n167(x) + if (x < 1) + fun_l15_n960(x) + else + fun_l15_n33(x) + end +end + +def fun_l14_n168(x) + if (x < 1) + fun_l15_n16(x) + else + fun_l15_n24(x) + end +end + +def fun_l14_n169(x) + if (x < 1) + fun_l15_n913(x) + else + fun_l15_n793(x) + end +end + +def fun_l14_n170(x) + if (x < 1) + fun_l15_n35(x) + else + fun_l15_n204(x) + end +end + +def fun_l14_n171(x) + if (x < 1) + fun_l15_n526(x) + else + fun_l15_n92(x) + end +end + +def fun_l14_n172(x) + if (x < 1) + fun_l15_n648(x) + else + fun_l15_n535(x) + end +end + +def fun_l14_n173(x) + if (x < 1) + fun_l15_n415(x) + else + fun_l15_n610(x) + end +end + +def fun_l14_n174(x) + if (x < 1) + fun_l15_n352(x) + else + fun_l15_n256(x) + end +end + +def fun_l14_n175(x) + if (x < 1) + fun_l15_n692(x) + else + fun_l15_n686(x) + end +end + +def fun_l14_n176(x) + if (x < 1) + fun_l15_n189(x) + else + fun_l15_n307(x) + end +end + +def fun_l14_n177(x) + if (x < 1) + fun_l15_n725(x) + else + fun_l15_n714(x) + end +end + +def fun_l14_n178(x) + if (x < 1) + fun_l15_n43(x) + else + fun_l15_n392(x) + end +end + +def fun_l14_n179(x) + if (x < 1) + fun_l15_n890(x) + else + fun_l15_n887(x) + end +end + +def fun_l14_n180(x) + if (x < 1) + fun_l15_n499(x) + else + fun_l15_n729(x) + end +end + +def fun_l14_n181(x) + if (x < 1) + fun_l15_n714(x) + else + fun_l15_n417(x) + end +end + +def fun_l14_n182(x) + if (x < 1) + fun_l15_n935(x) + else + fun_l15_n671(x) + end +end + +def fun_l14_n183(x) + if (x < 1) + fun_l15_n123(x) + else + fun_l15_n349(x) + end +end + +def fun_l14_n184(x) + if (x < 1) + fun_l15_n653(x) + else + fun_l15_n160(x) + end +end + +def fun_l14_n185(x) + if (x < 1) + fun_l15_n43(x) + else + fun_l15_n965(x) + end +end + +def fun_l14_n186(x) + if (x < 1) + fun_l15_n38(x) + else + fun_l15_n411(x) + end +end + +def fun_l14_n187(x) + if (x < 1) + fun_l15_n788(x) + else + fun_l15_n297(x) + end +end + +def fun_l14_n188(x) + if (x < 1) + fun_l15_n83(x) + else + fun_l15_n784(x) + end +end + +def fun_l14_n189(x) + if (x < 1) + fun_l15_n403(x) + else + fun_l15_n469(x) + end +end + +def fun_l14_n190(x) + if (x < 1) + fun_l15_n77(x) + else + fun_l15_n55(x) + end +end + +def fun_l14_n191(x) + if (x < 1) + fun_l15_n835(x) + else + fun_l15_n462(x) + end +end + +def fun_l14_n192(x) + if (x < 1) + fun_l15_n830(x) + else + fun_l15_n680(x) + end +end + +def fun_l14_n193(x) + if (x < 1) + fun_l15_n750(x) + else + fun_l15_n580(x) + end +end + +def fun_l14_n194(x) + if (x < 1) + fun_l15_n668(x) + else + fun_l15_n911(x) + end +end + +def fun_l14_n195(x) + if (x < 1) + fun_l15_n90(x) + else + fun_l15_n232(x) + end +end + +def fun_l14_n196(x) + if (x < 1) + fun_l15_n936(x) + else + fun_l15_n127(x) + end +end + +def fun_l14_n197(x) + if (x < 1) + fun_l15_n566(x) + else + fun_l15_n687(x) + end +end + +def fun_l14_n198(x) + if (x < 1) + fun_l15_n797(x) + else + fun_l15_n835(x) + end +end + +def fun_l14_n199(x) + if (x < 1) + fun_l15_n96(x) + else + fun_l15_n917(x) + end +end + +def fun_l14_n200(x) + if (x < 1) + fun_l15_n891(x) + else + fun_l15_n566(x) + end +end + +def fun_l14_n201(x) + if (x < 1) + fun_l15_n697(x) + else + fun_l15_n218(x) + end +end + +def fun_l14_n202(x) + if (x < 1) + fun_l15_n802(x) + else + fun_l15_n977(x) + end +end + +def fun_l14_n203(x) + if (x < 1) + fun_l15_n38(x) + else + fun_l15_n992(x) + end +end + +def fun_l14_n204(x) + if (x < 1) + fun_l15_n591(x) + else + fun_l15_n394(x) + end +end + +def fun_l14_n205(x) + if (x < 1) + fun_l15_n552(x) + else + fun_l15_n522(x) + end +end + +def fun_l14_n206(x) + if (x < 1) + fun_l15_n90(x) + else + fun_l15_n470(x) + end +end + +def fun_l14_n207(x) + if (x < 1) + fun_l15_n92(x) + else + fun_l15_n148(x) + end +end + +def fun_l14_n208(x) + if (x < 1) + fun_l15_n954(x) + else + fun_l15_n769(x) + end +end + +def fun_l14_n209(x) + if (x < 1) + fun_l15_n32(x) + else + fun_l15_n211(x) + end +end + +def fun_l14_n210(x) + if (x < 1) + fun_l15_n338(x) + else + fun_l15_n678(x) + end +end + +def fun_l14_n211(x) + if (x < 1) + fun_l15_n113(x) + else + fun_l15_n605(x) + end +end + +def fun_l14_n212(x) + if (x < 1) + fun_l15_n359(x) + else + fun_l15_n970(x) + end +end + +def fun_l14_n213(x) + if (x < 1) + fun_l15_n437(x) + else + fun_l15_n279(x) + end +end + +def fun_l14_n214(x) + if (x < 1) + fun_l15_n782(x) + else + fun_l15_n344(x) + end +end + +def fun_l14_n215(x) + if (x < 1) + fun_l15_n501(x) + else + fun_l15_n19(x) + end +end + +def fun_l14_n216(x) + if (x < 1) + fun_l15_n525(x) + else + fun_l15_n269(x) + end +end + +def fun_l14_n217(x) + if (x < 1) + fun_l15_n35(x) + else + fun_l15_n786(x) + end +end + +def fun_l14_n218(x) + if (x < 1) + fun_l15_n759(x) + else + fun_l15_n547(x) + end +end + +def fun_l14_n219(x) + if (x < 1) + fun_l15_n260(x) + else + fun_l15_n155(x) + end +end + +def fun_l14_n220(x) + if (x < 1) + fun_l15_n691(x) + else + fun_l15_n969(x) + end +end + +def fun_l14_n221(x) + if (x < 1) + fun_l15_n632(x) + else + fun_l15_n803(x) + end +end + +def fun_l14_n222(x) + if (x < 1) + fun_l15_n652(x) + else + fun_l15_n70(x) + end +end + +def fun_l14_n223(x) + if (x < 1) + fun_l15_n710(x) + else + fun_l15_n873(x) + end +end + +def fun_l14_n224(x) + if (x < 1) + fun_l15_n3(x) + else + fun_l15_n509(x) + end +end + +def fun_l14_n225(x) + if (x < 1) + fun_l15_n37(x) + else + fun_l15_n814(x) + end +end + +def fun_l14_n226(x) + if (x < 1) + fun_l15_n88(x) + else + fun_l15_n683(x) + end +end + +def fun_l14_n227(x) + if (x < 1) + fun_l15_n898(x) + else + fun_l15_n996(x) + end +end + +def fun_l14_n228(x) + if (x < 1) + fun_l15_n510(x) + else + fun_l15_n315(x) + end +end + +def fun_l14_n229(x) + if (x < 1) + fun_l15_n509(x) + else + fun_l15_n75(x) + end +end + +def fun_l14_n230(x) + if (x < 1) + fun_l15_n184(x) + else + fun_l15_n650(x) + end +end + +def fun_l14_n231(x) + if (x < 1) + fun_l15_n227(x) + else + fun_l15_n607(x) + end +end + +def fun_l14_n232(x) + if (x < 1) + fun_l15_n245(x) + else + fun_l15_n347(x) + end +end + +def fun_l14_n233(x) + if (x < 1) + fun_l15_n728(x) + else + fun_l15_n457(x) + end +end + +def fun_l14_n234(x) + if (x < 1) + fun_l15_n619(x) + else + fun_l15_n936(x) + end +end + +def fun_l14_n235(x) + if (x < 1) + fun_l15_n855(x) + else + fun_l15_n774(x) + end +end + +def fun_l14_n236(x) + if (x < 1) + fun_l15_n217(x) + else + fun_l15_n908(x) + end +end + +def fun_l14_n237(x) + if (x < 1) + fun_l15_n537(x) + else + fun_l15_n441(x) + end +end + +def fun_l14_n238(x) + if (x < 1) + fun_l15_n930(x) + else + fun_l15_n601(x) + end +end + +def fun_l14_n239(x) + if (x < 1) + fun_l15_n976(x) + else + fun_l15_n903(x) + end +end + +def fun_l14_n240(x) + if (x < 1) + fun_l15_n792(x) + else + fun_l15_n882(x) + end +end + +def fun_l14_n241(x) + if (x < 1) + fun_l15_n662(x) + else + fun_l15_n197(x) + end +end + +def fun_l14_n242(x) + if (x < 1) + fun_l15_n839(x) + else + fun_l15_n486(x) + end +end + +def fun_l14_n243(x) + if (x < 1) + fun_l15_n122(x) + else + fun_l15_n165(x) + end +end + +def fun_l14_n244(x) + if (x < 1) + fun_l15_n209(x) + else + fun_l15_n977(x) + end +end + +def fun_l14_n245(x) + if (x < 1) + fun_l15_n231(x) + else + fun_l15_n318(x) + end +end + +def fun_l14_n246(x) + if (x < 1) + fun_l15_n53(x) + else + fun_l15_n995(x) + end +end + +def fun_l14_n247(x) + if (x < 1) + fun_l15_n276(x) + else + fun_l15_n458(x) + end +end + +def fun_l14_n248(x) + if (x < 1) + fun_l15_n964(x) + else + fun_l15_n753(x) + end +end + +def fun_l14_n249(x) + if (x < 1) + fun_l15_n964(x) + else + fun_l15_n783(x) + end +end + +def fun_l14_n250(x) + if (x < 1) + fun_l15_n865(x) + else + fun_l15_n736(x) + end +end + +def fun_l14_n251(x) + if (x < 1) + fun_l15_n861(x) + else + fun_l15_n414(x) + end +end + +def fun_l14_n252(x) + if (x < 1) + fun_l15_n327(x) + else + fun_l15_n440(x) + end +end + +def fun_l14_n253(x) + if (x < 1) + fun_l15_n800(x) + else + fun_l15_n186(x) + end +end + +def fun_l14_n254(x) + if (x < 1) + fun_l15_n687(x) + else + fun_l15_n245(x) + end +end + +def fun_l14_n255(x) + if (x < 1) + fun_l15_n421(x) + else + fun_l15_n421(x) + end +end + +def fun_l14_n256(x) + if (x < 1) + fun_l15_n417(x) + else + fun_l15_n975(x) + end +end + +def fun_l14_n257(x) + if (x < 1) + fun_l15_n835(x) + else + fun_l15_n697(x) + end +end + +def fun_l14_n258(x) + if (x < 1) + fun_l15_n433(x) + else + fun_l15_n811(x) + end +end + +def fun_l14_n259(x) + if (x < 1) + fun_l15_n473(x) + else + fun_l15_n747(x) + end +end + +def fun_l14_n260(x) + if (x < 1) + fun_l15_n636(x) + else + fun_l15_n718(x) + end +end + +def fun_l14_n261(x) + if (x < 1) + fun_l15_n472(x) + else + fun_l15_n971(x) + end +end + +def fun_l14_n262(x) + if (x < 1) + fun_l15_n91(x) + else + fun_l15_n18(x) + end +end + +def fun_l14_n263(x) + if (x < 1) + fun_l15_n582(x) + else + fun_l15_n629(x) + end +end + +def fun_l14_n264(x) + if (x < 1) + fun_l15_n493(x) + else + fun_l15_n718(x) + end +end + +def fun_l14_n265(x) + if (x < 1) + fun_l15_n857(x) + else + fun_l15_n134(x) + end +end + +def fun_l14_n266(x) + if (x < 1) + fun_l15_n351(x) + else + fun_l15_n454(x) + end +end + +def fun_l14_n267(x) + if (x < 1) + fun_l15_n578(x) + else + fun_l15_n453(x) + end +end + +def fun_l14_n268(x) + if (x < 1) + fun_l15_n679(x) + else + fun_l15_n886(x) + end +end + +def fun_l14_n269(x) + if (x < 1) + fun_l15_n446(x) + else + fun_l15_n7(x) + end +end + +def fun_l14_n270(x) + if (x < 1) + fun_l15_n375(x) + else + fun_l15_n83(x) + end +end + +def fun_l14_n271(x) + if (x < 1) + fun_l15_n688(x) + else + fun_l15_n863(x) + end +end + +def fun_l14_n272(x) + if (x < 1) + fun_l15_n382(x) + else + fun_l15_n997(x) + end +end + +def fun_l14_n273(x) + if (x < 1) + fun_l15_n281(x) + else + fun_l15_n909(x) + end +end + +def fun_l14_n274(x) + if (x < 1) + fun_l15_n618(x) + else + fun_l15_n967(x) + end +end + +def fun_l14_n275(x) + if (x < 1) + fun_l15_n651(x) + else + fun_l15_n826(x) + end +end + +def fun_l14_n276(x) + if (x < 1) + fun_l15_n326(x) + else + fun_l15_n11(x) + end +end + +def fun_l14_n277(x) + if (x < 1) + fun_l15_n193(x) + else + fun_l15_n719(x) + end +end + +def fun_l14_n278(x) + if (x < 1) + fun_l15_n973(x) + else + fun_l15_n313(x) + end +end + +def fun_l14_n279(x) + if (x < 1) + fun_l15_n33(x) + else + fun_l15_n526(x) + end +end + +def fun_l14_n280(x) + if (x < 1) + fun_l15_n334(x) + else + fun_l15_n158(x) + end +end + +def fun_l14_n281(x) + if (x < 1) + fun_l15_n627(x) + else + fun_l15_n346(x) + end +end + +def fun_l14_n282(x) + if (x < 1) + fun_l15_n537(x) + else + fun_l15_n198(x) + end +end + +def fun_l14_n283(x) + if (x < 1) + fun_l15_n779(x) + else + fun_l15_n0(x) + end +end + +def fun_l14_n284(x) + if (x < 1) + fun_l15_n487(x) + else + fun_l15_n489(x) + end +end + +def fun_l14_n285(x) + if (x < 1) + fun_l15_n793(x) + else + fun_l15_n803(x) + end +end + +def fun_l14_n286(x) + if (x < 1) + fun_l15_n206(x) + else + fun_l15_n936(x) + end +end + +def fun_l14_n287(x) + if (x < 1) + fun_l15_n223(x) + else + fun_l15_n278(x) + end +end + +def fun_l14_n288(x) + if (x < 1) + fun_l15_n601(x) + else + fun_l15_n251(x) + end +end + +def fun_l14_n289(x) + if (x < 1) + fun_l15_n144(x) + else + fun_l15_n420(x) + end +end + +def fun_l14_n290(x) + if (x < 1) + fun_l15_n964(x) + else + fun_l15_n319(x) + end +end + +def fun_l14_n291(x) + if (x < 1) + fun_l15_n385(x) + else + fun_l15_n498(x) + end +end + +def fun_l14_n292(x) + if (x < 1) + fun_l15_n19(x) + else + fun_l15_n959(x) + end +end + +def fun_l14_n293(x) + if (x < 1) + fun_l15_n77(x) + else + fun_l15_n849(x) + end +end + +def fun_l14_n294(x) + if (x < 1) + fun_l15_n96(x) + else + fun_l15_n964(x) + end +end + +def fun_l14_n295(x) + if (x < 1) + fun_l15_n374(x) + else + fun_l15_n337(x) + end +end + +def fun_l14_n296(x) + if (x < 1) + fun_l15_n210(x) + else + fun_l15_n621(x) + end +end + +def fun_l14_n297(x) + if (x < 1) + fun_l15_n992(x) + else + fun_l15_n90(x) + end +end + +def fun_l14_n298(x) + if (x < 1) + fun_l15_n442(x) + else + fun_l15_n799(x) + end +end + +def fun_l14_n299(x) + if (x < 1) + fun_l15_n133(x) + else + fun_l15_n21(x) + end +end + +def fun_l14_n300(x) + if (x < 1) + fun_l15_n619(x) + else + fun_l15_n46(x) + end +end + +def fun_l14_n301(x) + if (x < 1) + fun_l15_n359(x) + else + fun_l15_n386(x) + end +end + +def fun_l14_n302(x) + if (x < 1) + fun_l15_n163(x) + else + fun_l15_n197(x) + end +end + +def fun_l14_n303(x) + if (x < 1) + fun_l15_n382(x) + else + fun_l15_n693(x) + end +end + +def fun_l14_n304(x) + if (x < 1) + fun_l15_n700(x) + else + fun_l15_n167(x) + end +end + +def fun_l14_n305(x) + if (x < 1) + fun_l15_n124(x) + else + fun_l15_n448(x) + end +end + +def fun_l14_n306(x) + if (x < 1) + fun_l15_n829(x) + else + fun_l15_n986(x) + end +end + +def fun_l14_n307(x) + if (x < 1) + fun_l15_n39(x) + else + fun_l15_n557(x) + end +end + +def fun_l14_n308(x) + if (x < 1) + fun_l15_n495(x) + else + fun_l15_n259(x) + end +end + +def fun_l14_n309(x) + if (x < 1) + fun_l15_n462(x) + else + fun_l15_n121(x) + end +end + +def fun_l14_n310(x) + if (x < 1) + fun_l15_n110(x) + else + fun_l15_n159(x) + end +end + +def fun_l14_n311(x) + if (x < 1) + fun_l15_n144(x) + else + fun_l15_n969(x) + end +end + +def fun_l14_n312(x) + if (x < 1) + fun_l15_n679(x) + else + fun_l15_n610(x) + end +end + +def fun_l14_n313(x) + if (x < 1) + fun_l15_n332(x) + else + fun_l15_n759(x) + end +end + +def fun_l14_n314(x) + if (x < 1) + fun_l15_n819(x) + else + fun_l15_n595(x) + end +end + +def fun_l14_n315(x) + if (x < 1) + fun_l15_n180(x) + else + fun_l15_n555(x) + end +end + +def fun_l14_n316(x) + if (x < 1) + fun_l15_n218(x) + else + fun_l15_n844(x) + end +end + +def fun_l14_n317(x) + if (x < 1) + fun_l15_n486(x) + else + fun_l15_n666(x) + end +end + +def fun_l14_n318(x) + if (x < 1) + fun_l15_n277(x) + else + fun_l15_n486(x) + end +end + +def fun_l14_n319(x) + if (x < 1) + fun_l15_n874(x) + else + fun_l15_n802(x) + end +end + +def fun_l14_n320(x) + if (x < 1) + fun_l15_n717(x) + else + fun_l15_n348(x) + end +end + +def fun_l14_n321(x) + if (x < 1) + fun_l15_n701(x) + else + fun_l15_n897(x) + end +end + +def fun_l14_n322(x) + if (x < 1) + fun_l15_n229(x) + else + fun_l15_n976(x) + end +end + +def fun_l14_n323(x) + if (x < 1) + fun_l15_n288(x) + else + fun_l15_n801(x) + end +end + +def fun_l14_n324(x) + if (x < 1) + fun_l15_n25(x) + else + fun_l15_n566(x) + end +end + +def fun_l14_n325(x) + if (x < 1) + fun_l15_n489(x) + else + fun_l15_n165(x) + end +end + +def fun_l14_n326(x) + if (x < 1) + fun_l15_n646(x) + else + fun_l15_n529(x) + end +end + +def fun_l14_n327(x) + if (x < 1) + fun_l15_n126(x) + else + fun_l15_n247(x) + end +end + +def fun_l14_n328(x) + if (x < 1) + fun_l15_n180(x) + else + fun_l15_n838(x) + end +end + +def fun_l14_n329(x) + if (x < 1) + fun_l15_n827(x) + else + fun_l15_n251(x) + end +end + +def fun_l14_n330(x) + if (x < 1) + fun_l15_n232(x) + else + fun_l15_n371(x) + end +end + +def fun_l14_n331(x) + if (x < 1) + fun_l15_n742(x) + else + fun_l15_n365(x) + end +end + +def fun_l14_n332(x) + if (x < 1) + fun_l15_n254(x) + else + fun_l15_n895(x) + end +end + +def fun_l14_n333(x) + if (x < 1) + fun_l15_n267(x) + else + fun_l15_n716(x) + end +end + +def fun_l14_n334(x) + if (x < 1) + fun_l15_n907(x) + else + fun_l15_n846(x) + end +end + +def fun_l14_n335(x) + if (x < 1) + fun_l15_n432(x) + else + fun_l15_n207(x) + end +end + +def fun_l14_n336(x) + if (x < 1) + fun_l15_n342(x) + else + fun_l15_n533(x) + end +end + +def fun_l14_n337(x) + if (x < 1) + fun_l15_n155(x) + else + fun_l15_n626(x) + end +end + +def fun_l14_n338(x) + if (x < 1) + fun_l15_n457(x) + else + fun_l15_n226(x) + end +end + +def fun_l14_n339(x) + if (x < 1) + fun_l15_n621(x) + else + fun_l15_n685(x) + end +end + +def fun_l14_n340(x) + if (x < 1) + fun_l15_n502(x) + else + fun_l15_n604(x) + end +end + +def fun_l14_n341(x) + if (x < 1) + fun_l15_n578(x) + else + fun_l15_n250(x) + end +end + +def fun_l14_n342(x) + if (x < 1) + fun_l15_n16(x) + else + fun_l15_n897(x) + end +end + +def fun_l14_n343(x) + if (x < 1) + fun_l15_n173(x) + else + fun_l15_n441(x) + end +end + +def fun_l14_n344(x) + if (x < 1) + fun_l15_n882(x) + else + fun_l15_n287(x) + end +end + +def fun_l14_n345(x) + if (x < 1) + fun_l15_n549(x) + else + fun_l15_n559(x) + end +end + +def fun_l14_n346(x) + if (x < 1) + fun_l15_n587(x) + else + fun_l15_n712(x) + end +end + +def fun_l14_n347(x) + if (x < 1) + fun_l15_n2(x) + else + fun_l15_n279(x) + end +end + +def fun_l14_n348(x) + if (x < 1) + fun_l15_n602(x) + else + fun_l15_n801(x) + end +end + +def fun_l14_n349(x) + if (x < 1) + fun_l15_n114(x) + else + fun_l15_n181(x) + end +end + +def fun_l14_n350(x) + if (x < 1) + fun_l15_n751(x) + else + fun_l15_n760(x) + end +end + +def fun_l14_n351(x) + if (x < 1) + fun_l15_n570(x) + else + fun_l15_n168(x) + end +end + +def fun_l14_n352(x) + if (x < 1) + fun_l15_n342(x) + else + fun_l15_n401(x) + end +end + +def fun_l14_n353(x) + if (x < 1) + fun_l15_n775(x) + else + fun_l15_n175(x) + end +end + +def fun_l14_n354(x) + if (x < 1) + fun_l15_n0(x) + else + fun_l15_n831(x) + end +end + +def fun_l14_n355(x) + if (x < 1) + fun_l15_n127(x) + else + fun_l15_n751(x) + end +end + +def fun_l14_n356(x) + if (x < 1) + fun_l15_n57(x) + else + fun_l15_n58(x) + end +end + +def fun_l14_n357(x) + if (x < 1) + fun_l15_n696(x) + else + fun_l15_n694(x) + end +end + +def fun_l14_n358(x) + if (x < 1) + fun_l15_n240(x) + else + fun_l15_n525(x) + end +end + +def fun_l14_n359(x) + if (x < 1) + fun_l15_n552(x) + else + fun_l15_n126(x) + end +end + +def fun_l14_n360(x) + if (x < 1) + fun_l15_n435(x) + else + fun_l15_n24(x) + end +end + +def fun_l14_n361(x) + if (x < 1) + fun_l15_n366(x) + else + fun_l15_n397(x) + end +end + +def fun_l14_n362(x) + if (x < 1) + fun_l15_n626(x) + else + fun_l15_n288(x) + end +end + +def fun_l14_n363(x) + if (x < 1) + fun_l15_n474(x) + else + fun_l15_n205(x) + end +end + +def fun_l14_n364(x) + if (x < 1) + fun_l15_n299(x) + else + fun_l15_n9(x) + end +end + +def fun_l14_n365(x) + if (x < 1) + fun_l15_n115(x) + else + fun_l15_n126(x) + end +end + +def fun_l14_n366(x) + if (x < 1) + fun_l15_n777(x) + else + fun_l15_n714(x) + end +end + +def fun_l14_n367(x) + if (x < 1) + fun_l15_n697(x) + else + fun_l15_n663(x) + end +end + +def fun_l14_n368(x) + if (x < 1) + fun_l15_n72(x) + else + fun_l15_n339(x) + end +end + +def fun_l14_n369(x) + if (x < 1) + fun_l15_n703(x) + else + fun_l15_n901(x) + end +end + +def fun_l14_n370(x) + if (x < 1) + fun_l15_n38(x) + else + fun_l15_n920(x) + end +end + +def fun_l14_n371(x) + if (x < 1) + fun_l15_n97(x) + else + fun_l15_n418(x) + end +end + +def fun_l14_n372(x) + if (x < 1) + fun_l15_n831(x) + else + fun_l15_n295(x) + end +end + +def fun_l14_n373(x) + if (x < 1) + fun_l15_n849(x) + else + fun_l15_n818(x) + end +end + +def fun_l14_n374(x) + if (x < 1) + fun_l15_n308(x) + else + fun_l15_n379(x) + end +end + +def fun_l14_n375(x) + if (x < 1) + fun_l15_n552(x) + else + fun_l15_n109(x) + end +end + +def fun_l14_n376(x) + if (x < 1) + fun_l15_n444(x) + else + fun_l15_n509(x) + end +end + +def fun_l14_n377(x) + if (x < 1) + fun_l15_n498(x) + else + fun_l15_n363(x) + end +end + +def fun_l14_n378(x) + if (x < 1) + fun_l15_n475(x) + else + fun_l15_n250(x) + end +end + +def fun_l14_n379(x) + if (x < 1) + fun_l15_n635(x) + else + fun_l15_n550(x) + end +end + +def fun_l14_n380(x) + if (x < 1) + fun_l15_n835(x) + else + fun_l15_n261(x) + end +end + +def fun_l14_n381(x) + if (x < 1) + fun_l15_n903(x) + else + fun_l15_n492(x) + end +end + +def fun_l14_n382(x) + if (x < 1) + fun_l15_n447(x) + else + fun_l15_n570(x) + end +end + +def fun_l14_n383(x) + if (x < 1) + fun_l15_n785(x) + else + fun_l15_n711(x) + end +end + +def fun_l14_n384(x) + if (x < 1) + fun_l15_n321(x) + else + fun_l15_n966(x) + end +end + +def fun_l14_n385(x) + if (x < 1) + fun_l15_n786(x) + else + fun_l15_n667(x) + end +end + +def fun_l14_n386(x) + if (x < 1) + fun_l15_n954(x) + else + fun_l15_n101(x) + end +end + +def fun_l14_n387(x) + if (x < 1) + fun_l15_n868(x) + else + fun_l15_n1(x) + end +end + +def fun_l14_n388(x) + if (x < 1) + fun_l15_n380(x) + else + fun_l15_n949(x) + end +end + +def fun_l14_n389(x) + if (x < 1) + fun_l15_n456(x) + else + fun_l15_n122(x) + end +end + +def fun_l14_n390(x) + if (x < 1) + fun_l15_n644(x) + else + fun_l15_n601(x) + end +end + +def fun_l14_n391(x) + if (x < 1) + fun_l15_n523(x) + else + fun_l15_n754(x) + end +end + +def fun_l14_n392(x) + if (x < 1) + fun_l15_n882(x) + else + fun_l15_n453(x) + end +end + +def fun_l14_n393(x) + if (x < 1) + fun_l15_n249(x) + else + fun_l15_n773(x) + end +end + +def fun_l14_n394(x) + if (x < 1) + fun_l15_n453(x) + else + fun_l15_n490(x) + end +end + +def fun_l14_n395(x) + if (x < 1) + fun_l15_n699(x) + else + fun_l15_n95(x) + end +end + +def fun_l14_n396(x) + if (x < 1) + fun_l15_n726(x) + else + fun_l15_n632(x) + end +end + +def fun_l14_n397(x) + if (x < 1) + fun_l15_n139(x) + else + fun_l15_n682(x) + end +end + +def fun_l14_n398(x) + if (x < 1) + fun_l15_n246(x) + else + fun_l15_n74(x) + end +end + +def fun_l14_n399(x) + if (x < 1) + fun_l15_n334(x) + else + fun_l15_n504(x) + end +end + +def fun_l14_n400(x) + if (x < 1) + fun_l15_n450(x) + else + fun_l15_n778(x) + end +end + +def fun_l14_n401(x) + if (x < 1) + fun_l15_n428(x) + else + fun_l15_n101(x) + end +end + +def fun_l14_n402(x) + if (x < 1) + fun_l15_n779(x) + else + fun_l15_n924(x) + end +end + +def fun_l14_n403(x) + if (x < 1) + fun_l15_n957(x) + else + fun_l15_n83(x) + end +end + +def fun_l14_n404(x) + if (x < 1) + fun_l15_n0(x) + else + fun_l15_n781(x) + end +end + +def fun_l14_n405(x) + if (x < 1) + fun_l15_n100(x) + else + fun_l15_n21(x) + end +end + +def fun_l14_n406(x) + if (x < 1) + fun_l15_n262(x) + else + fun_l15_n925(x) + end +end + +def fun_l14_n407(x) + if (x < 1) + fun_l15_n935(x) + else + fun_l15_n193(x) + end +end + +def fun_l14_n408(x) + if (x < 1) + fun_l15_n140(x) + else + fun_l15_n459(x) + end +end + +def fun_l14_n409(x) + if (x < 1) + fun_l15_n484(x) + else + fun_l15_n584(x) + end +end + +def fun_l14_n410(x) + if (x < 1) + fun_l15_n762(x) + else + fun_l15_n640(x) + end +end + +def fun_l14_n411(x) + if (x < 1) + fun_l15_n347(x) + else + fun_l15_n395(x) + end +end + +def fun_l14_n412(x) + if (x < 1) + fun_l15_n809(x) + else + fun_l15_n105(x) + end +end + +def fun_l14_n413(x) + if (x < 1) + fun_l15_n929(x) + else + fun_l15_n265(x) + end +end + +def fun_l14_n414(x) + if (x < 1) + fun_l15_n228(x) + else + fun_l15_n88(x) + end +end + +def fun_l14_n415(x) + if (x < 1) + fun_l15_n650(x) + else + fun_l15_n785(x) + end +end + +def fun_l14_n416(x) + if (x < 1) + fun_l15_n806(x) + else + fun_l15_n743(x) + end +end + +def fun_l14_n417(x) + if (x < 1) + fun_l15_n417(x) + else + fun_l15_n454(x) + end +end + +def fun_l14_n418(x) + if (x < 1) + fun_l15_n571(x) + else + fun_l15_n651(x) + end +end + +def fun_l14_n419(x) + if (x < 1) + fun_l15_n341(x) + else + fun_l15_n242(x) + end +end + +def fun_l14_n420(x) + if (x < 1) + fun_l15_n613(x) + else + fun_l15_n339(x) + end +end + +def fun_l14_n421(x) + if (x < 1) + fun_l15_n657(x) + else + fun_l15_n759(x) + end +end + +def fun_l14_n422(x) + if (x < 1) + fun_l15_n33(x) + else + fun_l15_n669(x) + end +end + +def fun_l14_n423(x) + if (x < 1) + fun_l15_n628(x) + else + fun_l15_n963(x) + end +end + +def fun_l14_n424(x) + if (x < 1) + fun_l15_n940(x) + else + fun_l15_n773(x) + end +end + +def fun_l14_n425(x) + if (x < 1) + fun_l15_n489(x) + else + fun_l15_n625(x) + end +end + +def fun_l14_n426(x) + if (x < 1) + fun_l15_n501(x) + else + fun_l15_n278(x) + end +end + +def fun_l14_n427(x) + if (x < 1) + fun_l15_n620(x) + else + fun_l15_n426(x) + end +end + +def fun_l14_n428(x) + if (x < 1) + fun_l15_n606(x) + else + fun_l15_n123(x) + end +end + +def fun_l14_n429(x) + if (x < 1) + fun_l15_n622(x) + else + fun_l15_n873(x) + end +end + +def fun_l14_n430(x) + if (x < 1) + fun_l15_n660(x) + else + fun_l15_n736(x) + end +end + +def fun_l14_n431(x) + if (x < 1) + fun_l15_n927(x) + else + fun_l15_n893(x) + end +end + +def fun_l14_n432(x) + if (x < 1) + fun_l15_n492(x) + else + fun_l15_n947(x) + end +end + +def fun_l14_n433(x) + if (x < 1) + fun_l15_n164(x) + else + fun_l15_n853(x) + end +end + +def fun_l14_n434(x) + if (x < 1) + fun_l15_n730(x) + else + fun_l15_n265(x) + end +end + +def fun_l14_n435(x) + if (x < 1) + fun_l15_n548(x) + else + fun_l15_n272(x) + end +end + +def fun_l14_n436(x) + if (x < 1) + fun_l15_n944(x) + else + fun_l15_n344(x) + end +end + +def fun_l14_n437(x) + if (x < 1) + fun_l15_n931(x) + else + fun_l15_n376(x) + end +end + +def fun_l14_n438(x) + if (x < 1) + fun_l15_n261(x) + else + fun_l15_n270(x) + end +end + +def fun_l14_n439(x) + if (x < 1) + fun_l15_n705(x) + else + fun_l15_n700(x) + end +end + +def fun_l14_n440(x) + if (x < 1) + fun_l15_n115(x) + else + fun_l15_n964(x) + end +end + +def fun_l14_n441(x) + if (x < 1) + fun_l15_n396(x) + else + fun_l15_n780(x) + end +end + +def fun_l14_n442(x) + if (x < 1) + fun_l15_n813(x) + else + fun_l15_n25(x) + end +end + +def fun_l14_n443(x) + if (x < 1) + fun_l15_n405(x) + else + fun_l15_n264(x) + end +end + +def fun_l14_n444(x) + if (x < 1) + fun_l15_n816(x) + else + fun_l15_n857(x) + end +end + +def fun_l14_n445(x) + if (x < 1) + fun_l15_n191(x) + else + fun_l15_n886(x) + end +end + +def fun_l14_n446(x) + if (x < 1) + fun_l15_n415(x) + else + fun_l15_n611(x) + end +end + +def fun_l14_n447(x) + if (x < 1) + fun_l15_n473(x) + else + fun_l15_n701(x) + end +end + +def fun_l14_n448(x) + if (x < 1) + fun_l15_n532(x) + else + fun_l15_n501(x) + end +end + +def fun_l14_n449(x) + if (x < 1) + fun_l15_n731(x) + else + fun_l15_n631(x) + end +end + +def fun_l14_n450(x) + if (x < 1) + fun_l15_n75(x) + else + fun_l15_n356(x) + end +end + +def fun_l14_n451(x) + if (x < 1) + fun_l15_n614(x) + else + fun_l15_n600(x) + end +end + +def fun_l14_n452(x) + if (x < 1) + fun_l15_n592(x) + else + fun_l15_n995(x) + end +end + +def fun_l14_n453(x) + if (x < 1) + fun_l15_n712(x) + else + fun_l15_n815(x) + end +end + +def fun_l14_n454(x) + if (x < 1) + fun_l15_n859(x) + else + fun_l15_n560(x) + end +end + +def fun_l14_n455(x) + if (x < 1) + fun_l15_n665(x) + else + fun_l15_n408(x) + end +end + +def fun_l14_n456(x) + if (x < 1) + fun_l15_n693(x) + else + fun_l15_n491(x) + end +end + +def fun_l14_n457(x) + if (x < 1) + fun_l15_n29(x) + else + fun_l15_n515(x) + end +end + +def fun_l14_n458(x) + if (x < 1) + fun_l15_n598(x) + else + fun_l15_n448(x) + end +end + +def fun_l14_n459(x) + if (x < 1) + fun_l15_n937(x) + else + fun_l15_n199(x) + end +end + +def fun_l14_n460(x) + if (x < 1) + fun_l15_n950(x) + else + fun_l15_n874(x) + end +end + +def fun_l14_n461(x) + if (x < 1) + fun_l15_n38(x) + else + fun_l15_n650(x) + end +end + +def fun_l14_n462(x) + if (x < 1) + fun_l15_n366(x) + else + fun_l15_n271(x) + end +end + +def fun_l14_n463(x) + if (x < 1) + fun_l15_n21(x) + else + fun_l15_n690(x) + end +end + +def fun_l14_n464(x) + if (x < 1) + fun_l15_n660(x) + else + fun_l15_n71(x) + end +end + +def fun_l14_n465(x) + if (x < 1) + fun_l15_n889(x) + else + fun_l15_n324(x) + end +end + +def fun_l14_n466(x) + if (x < 1) + fun_l15_n808(x) + else + fun_l15_n532(x) + end +end + +def fun_l14_n467(x) + if (x < 1) + fun_l15_n72(x) + else + fun_l15_n52(x) + end +end + +def fun_l14_n468(x) + if (x < 1) + fun_l15_n563(x) + else + fun_l15_n327(x) + end +end + +def fun_l14_n469(x) + if (x < 1) + fun_l15_n570(x) + else + fun_l15_n794(x) + end +end + +def fun_l14_n470(x) + if (x < 1) + fun_l15_n8(x) + else + fun_l15_n594(x) + end +end + +def fun_l14_n471(x) + if (x < 1) + fun_l15_n859(x) + else + fun_l15_n519(x) + end +end + +def fun_l14_n472(x) + if (x < 1) + fun_l15_n539(x) + else + fun_l15_n432(x) + end +end + +def fun_l14_n473(x) + if (x < 1) + fun_l15_n795(x) + else + fun_l15_n916(x) + end +end + +def fun_l14_n474(x) + if (x < 1) + fun_l15_n851(x) + else + fun_l15_n157(x) + end +end + +def fun_l14_n475(x) + if (x < 1) + fun_l15_n274(x) + else + fun_l15_n678(x) + end +end + +def fun_l14_n476(x) + if (x < 1) + fun_l15_n221(x) + else + fun_l15_n906(x) + end +end + +def fun_l14_n477(x) + if (x < 1) + fun_l15_n116(x) + else + fun_l15_n778(x) + end +end + +def fun_l14_n478(x) + if (x < 1) + fun_l15_n715(x) + else + fun_l15_n855(x) + end +end + +def fun_l14_n479(x) + if (x < 1) + fun_l15_n705(x) + else + fun_l15_n935(x) + end +end + +def fun_l14_n480(x) + if (x < 1) + fun_l15_n119(x) + else + fun_l15_n559(x) + end +end + +def fun_l14_n481(x) + if (x < 1) + fun_l15_n996(x) + else + fun_l15_n768(x) + end +end + +def fun_l14_n482(x) + if (x < 1) + fun_l15_n619(x) + else + fun_l15_n475(x) + end +end + +def fun_l14_n483(x) + if (x < 1) + fun_l15_n189(x) + else + fun_l15_n398(x) + end +end + +def fun_l14_n484(x) + if (x < 1) + fun_l15_n758(x) + else + fun_l15_n864(x) + end +end + +def fun_l14_n485(x) + if (x < 1) + fun_l15_n508(x) + else + fun_l15_n393(x) + end +end + +def fun_l14_n486(x) + if (x < 1) + fun_l15_n825(x) + else + fun_l15_n337(x) + end +end + +def fun_l14_n487(x) + if (x < 1) + fun_l15_n449(x) + else + fun_l15_n389(x) + end +end + +def fun_l14_n488(x) + if (x < 1) + fun_l15_n328(x) + else + fun_l15_n658(x) + end +end + +def fun_l14_n489(x) + if (x < 1) + fun_l15_n138(x) + else + fun_l15_n938(x) + end +end + +def fun_l14_n490(x) + if (x < 1) + fun_l15_n387(x) + else + fun_l15_n865(x) + end +end + +def fun_l14_n491(x) + if (x < 1) + fun_l15_n621(x) + else + fun_l15_n516(x) + end +end + +def fun_l14_n492(x) + if (x < 1) + fun_l15_n962(x) + else + fun_l15_n821(x) + end +end + +def fun_l14_n493(x) + if (x < 1) + fun_l15_n544(x) + else + fun_l15_n625(x) + end +end + +def fun_l14_n494(x) + if (x < 1) + fun_l15_n610(x) + else + fun_l15_n404(x) + end +end + +def fun_l14_n495(x) + if (x < 1) + fun_l15_n329(x) + else + fun_l15_n537(x) + end +end + +def fun_l14_n496(x) + if (x < 1) + fun_l15_n659(x) + else + fun_l15_n837(x) + end +end + +def fun_l14_n497(x) + if (x < 1) + fun_l15_n974(x) + else + fun_l15_n55(x) + end +end + +def fun_l14_n498(x) + if (x < 1) + fun_l15_n243(x) + else + fun_l15_n810(x) + end +end + +def fun_l14_n499(x) + if (x < 1) + fun_l15_n260(x) + else + fun_l15_n412(x) + end +end + +def fun_l14_n500(x) + if (x < 1) + fun_l15_n940(x) + else + fun_l15_n920(x) + end +end + +def fun_l14_n501(x) + if (x < 1) + fun_l15_n829(x) + else + fun_l15_n877(x) + end +end + +def fun_l14_n502(x) + if (x < 1) + fun_l15_n457(x) + else + fun_l15_n307(x) + end +end + +def fun_l14_n503(x) + if (x < 1) + fun_l15_n301(x) + else + fun_l15_n812(x) + end +end + +def fun_l14_n504(x) + if (x < 1) + fun_l15_n175(x) + else + fun_l15_n715(x) + end +end + +def fun_l14_n505(x) + if (x < 1) + fun_l15_n897(x) + else + fun_l15_n103(x) + end +end + +def fun_l14_n506(x) + if (x < 1) + fun_l15_n357(x) + else + fun_l15_n606(x) + end +end + +def fun_l14_n507(x) + if (x < 1) + fun_l15_n974(x) + else + fun_l15_n389(x) + end +end + +def fun_l14_n508(x) + if (x < 1) + fun_l15_n641(x) + else + fun_l15_n450(x) + end +end + +def fun_l14_n509(x) + if (x < 1) + fun_l15_n4(x) + else + fun_l15_n533(x) + end +end + +def fun_l14_n510(x) + if (x < 1) + fun_l15_n258(x) + else + fun_l15_n716(x) + end +end + +def fun_l14_n511(x) + if (x < 1) + fun_l15_n919(x) + else + fun_l15_n881(x) + end +end + +def fun_l14_n512(x) + if (x < 1) + fun_l15_n313(x) + else + fun_l15_n282(x) + end +end + +def fun_l14_n513(x) + if (x < 1) + fun_l15_n116(x) + else + fun_l15_n861(x) + end +end + +def fun_l14_n514(x) + if (x < 1) + fun_l15_n178(x) + else + fun_l15_n717(x) + end +end + +def fun_l14_n515(x) + if (x < 1) + fun_l15_n896(x) + else + fun_l15_n583(x) + end +end + +def fun_l14_n516(x) + if (x < 1) + fun_l15_n203(x) + else + fun_l15_n802(x) + end +end + +def fun_l14_n517(x) + if (x < 1) + fun_l15_n810(x) + else + fun_l15_n34(x) + end +end + +def fun_l14_n518(x) + if (x < 1) + fun_l15_n908(x) + else + fun_l15_n623(x) + end +end + +def fun_l14_n519(x) + if (x < 1) + fun_l15_n954(x) + else + fun_l15_n411(x) + end +end + +def fun_l14_n520(x) + if (x < 1) + fun_l15_n880(x) + else + fun_l15_n38(x) + end +end + +def fun_l14_n521(x) + if (x < 1) + fun_l15_n954(x) + else + fun_l15_n917(x) + end +end + +def fun_l14_n522(x) + if (x < 1) + fun_l15_n693(x) + else + fun_l15_n950(x) + end +end + +def fun_l14_n523(x) + if (x < 1) + fun_l15_n654(x) + else + fun_l15_n27(x) + end +end + +def fun_l14_n524(x) + if (x < 1) + fun_l15_n316(x) + else + fun_l15_n873(x) + end +end + +def fun_l14_n525(x) + if (x < 1) + fun_l15_n554(x) + else + fun_l15_n656(x) + end +end + +def fun_l14_n526(x) + if (x < 1) + fun_l15_n739(x) + else + fun_l15_n69(x) + end +end + +def fun_l14_n527(x) + if (x < 1) + fun_l15_n851(x) + else + fun_l15_n366(x) + end +end + +def fun_l14_n528(x) + if (x < 1) + fun_l15_n113(x) + else + fun_l15_n271(x) + end +end + +def fun_l14_n529(x) + if (x < 1) + fun_l15_n652(x) + else + fun_l15_n831(x) + end +end + +def fun_l14_n530(x) + if (x < 1) + fun_l15_n746(x) + else + fun_l15_n841(x) + end +end + +def fun_l14_n531(x) + if (x < 1) + fun_l15_n758(x) + else + fun_l15_n893(x) + end +end + +def fun_l14_n532(x) + if (x < 1) + fun_l15_n976(x) + else + fun_l15_n514(x) + end +end + +def fun_l14_n533(x) + if (x < 1) + fun_l15_n375(x) + else + fun_l15_n84(x) + end +end + +def fun_l14_n534(x) + if (x < 1) + fun_l15_n226(x) + else + fun_l15_n770(x) + end +end + +def fun_l14_n535(x) + if (x < 1) + fun_l15_n106(x) + else + fun_l15_n230(x) + end +end + +def fun_l14_n536(x) + if (x < 1) + fun_l15_n18(x) + else + fun_l15_n335(x) + end +end + +def fun_l14_n537(x) + if (x < 1) + fun_l15_n755(x) + else + fun_l15_n16(x) + end +end + +def fun_l14_n538(x) + if (x < 1) + fun_l15_n653(x) + else + fun_l15_n486(x) + end +end + +def fun_l14_n539(x) + if (x < 1) + fun_l15_n665(x) + else + fun_l15_n768(x) + end +end + +def fun_l14_n540(x) + if (x < 1) + fun_l15_n282(x) + else + fun_l15_n780(x) + end +end + +def fun_l14_n541(x) + if (x < 1) + fun_l15_n633(x) + else + fun_l15_n240(x) + end +end + +def fun_l14_n542(x) + if (x < 1) + fun_l15_n141(x) + else + fun_l15_n474(x) + end +end + +def fun_l14_n543(x) + if (x < 1) + fun_l15_n80(x) + else + fun_l15_n708(x) + end +end + +def fun_l14_n544(x) + if (x < 1) + fun_l15_n309(x) + else + fun_l15_n808(x) + end +end + +def fun_l14_n545(x) + if (x < 1) + fun_l15_n744(x) + else + fun_l15_n51(x) + end +end + +def fun_l14_n546(x) + if (x < 1) + fun_l15_n571(x) + else + fun_l15_n581(x) + end +end + +def fun_l14_n547(x) + if (x < 1) + fun_l15_n272(x) + else + fun_l15_n867(x) + end +end + +def fun_l14_n548(x) + if (x < 1) + fun_l15_n96(x) + else + fun_l15_n83(x) + end +end + +def fun_l14_n549(x) + if (x < 1) + fun_l15_n828(x) + else + fun_l15_n109(x) + end +end + +def fun_l14_n550(x) + if (x < 1) + fun_l15_n94(x) + else + fun_l15_n839(x) + end +end + +def fun_l14_n551(x) + if (x < 1) + fun_l15_n704(x) + else + fun_l15_n88(x) + end +end + +def fun_l14_n552(x) + if (x < 1) + fun_l15_n531(x) + else + fun_l15_n865(x) + end +end + +def fun_l14_n553(x) + if (x < 1) + fun_l15_n506(x) + else + fun_l15_n16(x) + end +end + +def fun_l14_n554(x) + if (x < 1) + fun_l15_n583(x) + else + fun_l15_n186(x) + end +end + +def fun_l14_n555(x) + if (x < 1) + fun_l15_n673(x) + else + fun_l15_n560(x) + end +end + +def fun_l14_n556(x) + if (x < 1) + fun_l15_n947(x) + else + fun_l15_n268(x) + end +end + +def fun_l14_n557(x) + if (x < 1) + fun_l15_n88(x) + else + fun_l15_n43(x) + end +end + +def fun_l14_n558(x) + if (x < 1) + fun_l15_n690(x) + else + fun_l15_n145(x) + end +end + +def fun_l14_n559(x) + if (x < 1) + fun_l15_n24(x) + else + fun_l15_n631(x) + end +end + +def fun_l14_n560(x) + if (x < 1) + fun_l15_n381(x) + else + fun_l15_n3(x) + end +end + +def fun_l14_n561(x) + if (x < 1) + fun_l15_n954(x) + else + fun_l15_n816(x) + end +end + +def fun_l14_n562(x) + if (x < 1) + fun_l15_n948(x) + else + fun_l15_n886(x) + end +end + +def fun_l14_n563(x) + if (x < 1) + fun_l15_n749(x) + else + fun_l15_n558(x) + end +end + +def fun_l14_n564(x) + if (x < 1) + fun_l15_n715(x) + else + fun_l15_n157(x) + end +end + +def fun_l14_n565(x) + if (x < 1) + fun_l15_n674(x) + else + fun_l15_n643(x) + end +end + +def fun_l14_n566(x) + if (x < 1) + fun_l15_n151(x) + else + fun_l15_n686(x) + end +end + +def fun_l14_n567(x) + if (x < 1) + fun_l15_n362(x) + else + fun_l15_n37(x) + end +end + +def fun_l14_n568(x) + if (x < 1) + fun_l15_n132(x) + else + fun_l15_n146(x) + end +end + +def fun_l14_n569(x) + if (x < 1) + fun_l15_n32(x) + else + fun_l15_n203(x) + end +end + +def fun_l14_n570(x) + if (x < 1) + fun_l15_n477(x) + else + fun_l15_n403(x) + end +end + +def fun_l14_n571(x) + if (x < 1) + fun_l15_n976(x) + else + fun_l15_n632(x) + end +end + +def fun_l14_n572(x) + if (x < 1) + fun_l15_n735(x) + else + fun_l15_n100(x) + end +end + +def fun_l14_n573(x) + if (x < 1) + fun_l15_n186(x) + else + fun_l15_n83(x) + end +end + +def fun_l14_n574(x) + if (x < 1) + fun_l15_n246(x) + else + fun_l15_n573(x) + end +end + +def fun_l14_n575(x) + if (x < 1) + fun_l15_n316(x) + else + fun_l15_n618(x) + end +end + +def fun_l14_n576(x) + if (x < 1) + fun_l15_n426(x) + else + fun_l15_n616(x) + end +end + +def fun_l14_n577(x) + if (x < 1) + fun_l15_n810(x) + else + fun_l15_n817(x) + end +end + +def fun_l14_n578(x) + if (x < 1) + fun_l15_n262(x) + else + fun_l15_n815(x) + end +end + +def fun_l14_n579(x) + if (x < 1) + fun_l15_n851(x) + else + fun_l15_n524(x) + end +end + +def fun_l14_n580(x) + if (x < 1) + fun_l15_n748(x) + else + fun_l15_n843(x) + end +end + +def fun_l14_n581(x) + if (x < 1) + fun_l15_n284(x) + else + fun_l15_n108(x) + end +end + +def fun_l14_n582(x) + if (x < 1) + fun_l15_n976(x) + else + fun_l15_n294(x) + end +end + +def fun_l14_n583(x) + if (x < 1) + fun_l15_n609(x) + else + fun_l15_n866(x) + end +end + +def fun_l14_n584(x) + if (x < 1) + fun_l15_n293(x) + else + fun_l15_n980(x) + end +end + +def fun_l14_n585(x) + if (x < 1) + fun_l15_n548(x) + else + fun_l15_n319(x) + end +end + +def fun_l14_n586(x) + if (x < 1) + fun_l15_n566(x) + else + fun_l15_n843(x) + end +end + +def fun_l14_n587(x) + if (x < 1) + fun_l15_n963(x) + else + fun_l15_n120(x) + end +end + +def fun_l14_n588(x) + if (x < 1) + fun_l15_n149(x) + else + fun_l15_n17(x) + end +end + +def fun_l14_n589(x) + if (x < 1) + fun_l15_n11(x) + else + fun_l15_n396(x) + end +end + +def fun_l14_n590(x) + if (x < 1) + fun_l15_n40(x) + else + fun_l15_n687(x) + end +end + +def fun_l14_n591(x) + if (x < 1) + fun_l15_n617(x) + else + fun_l15_n564(x) + end +end + +def fun_l14_n592(x) + if (x < 1) + fun_l15_n26(x) + else + fun_l15_n812(x) + end +end + +def fun_l14_n593(x) + if (x < 1) + fun_l15_n890(x) + else + fun_l15_n403(x) + end +end + +def fun_l14_n594(x) + if (x < 1) + fun_l15_n455(x) + else + fun_l15_n248(x) + end +end + +def fun_l14_n595(x) + if (x < 1) + fun_l15_n880(x) + else + fun_l15_n488(x) + end +end + +def fun_l14_n596(x) + if (x < 1) + fun_l15_n412(x) + else + fun_l15_n986(x) + end +end + +def fun_l14_n597(x) + if (x < 1) + fun_l15_n487(x) + else + fun_l15_n75(x) + end +end + +def fun_l14_n598(x) + if (x < 1) + fun_l15_n911(x) + else + fun_l15_n789(x) + end +end + +def fun_l14_n599(x) + if (x < 1) + fun_l15_n856(x) + else + fun_l15_n773(x) + end +end + +def fun_l14_n600(x) + if (x < 1) + fun_l15_n57(x) + else + fun_l15_n538(x) + end +end + +def fun_l14_n601(x) + if (x < 1) + fun_l15_n828(x) + else + fun_l15_n165(x) + end +end + +def fun_l14_n602(x) + if (x < 1) + fun_l15_n230(x) + else + fun_l15_n326(x) + end +end + +def fun_l14_n603(x) + if (x < 1) + fun_l15_n463(x) + else + fun_l15_n906(x) + end +end + +def fun_l14_n604(x) + if (x < 1) + fun_l15_n584(x) + else + fun_l15_n205(x) + end +end + +def fun_l14_n605(x) + if (x < 1) + fun_l15_n243(x) + else + fun_l15_n0(x) + end +end + +def fun_l14_n606(x) + if (x < 1) + fun_l15_n258(x) + else + fun_l15_n574(x) + end +end + +def fun_l14_n607(x) + if (x < 1) + fun_l15_n821(x) + else + fun_l15_n786(x) + end +end + +def fun_l14_n608(x) + if (x < 1) + fun_l15_n553(x) + else + fun_l15_n183(x) + end +end + +def fun_l14_n609(x) + if (x < 1) + fun_l15_n853(x) + else + fun_l15_n600(x) + end +end + +def fun_l14_n610(x) + if (x < 1) + fun_l15_n606(x) + else + fun_l15_n76(x) + end +end + +def fun_l14_n611(x) + if (x < 1) + fun_l15_n488(x) + else + fun_l15_n313(x) + end +end + +def fun_l14_n612(x) + if (x < 1) + fun_l15_n261(x) + else + fun_l15_n320(x) + end +end + +def fun_l14_n613(x) + if (x < 1) + fun_l15_n410(x) + else + fun_l15_n225(x) + end +end + +def fun_l14_n614(x) + if (x < 1) + fun_l15_n653(x) + else + fun_l15_n699(x) + end +end + +def fun_l14_n615(x) + if (x < 1) + fun_l15_n917(x) + else + fun_l15_n199(x) + end +end + +def fun_l14_n616(x) + if (x < 1) + fun_l15_n583(x) + else + fun_l15_n676(x) + end +end + +def fun_l14_n617(x) + if (x < 1) + fun_l15_n708(x) + else + fun_l15_n323(x) + end +end + +def fun_l14_n618(x) + if (x < 1) + fun_l15_n935(x) + else + fun_l15_n570(x) + end +end + +def fun_l14_n619(x) + if (x < 1) + fun_l15_n440(x) + else + fun_l15_n765(x) + end +end + +def fun_l14_n620(x) + if (x < 1) + fun_l15_n621(x) + else + fun_l15_n239(x) + end +end + +def fun_l14_n621(x) + if (x < 1) + fun_l15_n498(x) + else + fun_l15_n586(x) + end +end + +def fun_l14_n622(x) + if (x < 1) + fun_l15_n786(x) + else + fun_l15_n894(x) + end +end + +def fun_l14_n623(x) + if (x < 1) + fun_l15_n637(x) + else + fun_l15_n502(x) + end +end + +def fun_l14_n624(x) + if (x < 1) + fun_l15_n982(x) + else + fun_l15_n690(x) + end +end + +def fun_l14_n625(x) + if (x < 1) + fun_l15_n696(x) + else + fun_l15_n407(x) + end +end + +def fun_l14_n626(x) + if (x < 1) + fun_l15_n324(x) + else + fun_l15_n937(x) + end +end + +def fun_l14_n627(x) + if (x < 1) + fun_l15_n223(x) + else + fun_l15_n538(x) + end +end + +def fun_l14_n628(x) + if (x < 1) + fun_l15_n865(x) + else + fun_l15_n459(x) + end +end + +def fun_l14_n629(x) + if (x < 1) + fun_l15_n990(x) + else + fun_l15_n602(x) + end +end + +def fun_l14_n630(x) + if (x < 1) + fun_l15_n289(x) + else + fun_l15_n608(x) + end +end + +def fun_l14_n631(x) + if (x < 1) + fun_l15_n802(x) + else + fun_l15_n254(x) + end +end + +def fun_l14_n632(x) + if (x < 1) + fun_l15_n8(x) + else + fun_l15_n114(x) + end +end + +def fun_l14_n633(x) + if (x < 1) + fun_l15_n91(x) + else + fun_l15_n130(x) + end +end + +def fun_l14_n634(x) + if (x < 1) + fun_l15_n691(x) + else + fun_l15_n961(x) + end +end + +def fun_l14_n635(x) + if (x < 1) + fun_l15_n590(x) + else + fun_l15_n739(x) + end +end + +def fun_l14_n636(x) + if (x < 1) + fun_l15_n552(x) + else + fun_l15_n526(x) + end +end + +def fun_l14_n637(x) + if (x < 1) + fun_l15_n741(x) + else + fun_l15_n506(x) + end +end + +def fun_l14_n638(x) + if (x < 1) + fun_l15_n458(x) + else + fun_l15_n1(x) + end +end + +def fun_l14_n639(x) + if (x < 1) + fun_l15_n933(x) + else + fun_l15_n500(x) + end +end + +def fun_l14_n640(x) + if (x < 1) + fun_l15_n267(x) + else + fun_l15_n450(x) + end +end + +def fun_l14_n641(x) + if (x < 1) + fun_l15_n51(x) + else + fun_l15_n591(x) + end +end + +def fun_l14_n642(x) + if (x < 1) + fun_l15_n262(x) + else + fun_l15_n254(x) + end +end + +def fun_l14_n643(x) + if (x < 1) + fun_l15_n320(x) + else + fun_l15_n610(x) + end +end + +def fun_l14_n644(x) + if (x < 1) + fun_l15_n137(x) + else + fun_l15_n802(x) + end +end + +def fun_l14_n645(x) + if (x < 1) + fun_l15_n365(x) + else + fun_l15_n779(x) + end +end + +def fun_l14_n646(x) + if (x < 1) + fun_l15_n863(x) + else + fun_l15_n273(x) + end +end + +def fun_l14_n647(x) + if (x < 1) + fun_l15_n334(x) + else + fun_l15_n519(x) + end +end + +def fun_l14_n648(x) + if (x < 1) + fun_l15_n232(x) + else + fun_l15_n876(x) + end +end + +def fun_l14_n649(x) + if (x < 1) + fun_l15_n850(x) + else + fun_l15_n51(x) + end +end + +def fun_l14_n650(x) + if (x < 1) + fun_l15_n610(x) + else + fun_l15_n52(x) + end +end + +def fun_l14_n651(x) + if (x < 1) + fun_l15_n701(x) + else + fun_l15_n143(x) + end +end + +def fun_l14_n652(x) + if (x < 1) + fun_l15_n933(x) + else + fun_l15_n748(x) + end +end + +def fun_l14_n653(x) + if (x < 1) + fun_l15_n280(x) + else + fun_l15_n632(x) + end +end + +def fun_l14_n654(x) + if (x < 1) + fun_l15_n361(x) + else + fun_l15_n107(x) + end +end + +def fun_l14_n655(x) + if (x < 1) + fun_l15_n743(x) + else + fun_l15_n899(x) + end +end + +def fun_l14_n656(x) + if (x < 1) + fun_l15_n383(x) + else + fun_l15_n441(x) + end +end + +def fun_l14_n657(x) + if (x < 1) + fun_l15_n244(x) + else + fun_l15_n349(x) + end +end + +def fun_l14_n658(x) + if (x < 1) + fun_l15_n69(x) + else + fun_l15_n758(x) + end +end + +def fun_l14_n659(x) + if (x < 1) + fun_l15_n570(x) + else + fun_l15_n760(x) + end +end + +def fun_l14_n660(x) + if (x < 1) + fun_l15_n554(x) + else + fun_l15_n258(x) + end +end + +def fun_l14_n661(x) + if (x < 1) + fun_l15_n417(x) + else + fun_l15_n934(x) + end +end + +def fun_l14_n662(x) + if (x < 1) + fun_l15_n717(x) + else + fun_l15_n99(x) + end +end + +def fun_l14_n663(x) + if (x < 1) + fun_l15_n882(x) + else + fun_l15_n515(x) + end +end + +def fun_l14_n664(x) + if (x < 1) + fun_l15_n623(x) + else + fun_l15_n679(x) + end +end + +def fun_l14_n665(x) + if (x < 1) + fun_l15_n974(x) + else + fun_l15_n127(x) + end +end + +def fun_l14_n666(x) + if (x < 1) + fun_l15_n592(x) + else + fun_l15_n322(x) + end +end + +def fun_l14_n667(x) + if (x < 1) + fun_l15_n698(x) + else + fun_l15_n670(x) + end +end + +def fun_l14_n668(x) + if (x < 1) + fun_l15_n164(x) + else + fun_l15_n670(x) + end +end + +def fun_l14_n669(x) + if (x < 1) + fun_l15_n837(x) + else + fun_l15_n113(x) + end +end + +def fun_l14_n670(x) + if (x < 1) + fun_l15_n200(x) + else + fun_l15_n486(x) + end +end + +def fun_l14_n671(x) + if (x < 1) + fun_l15_n593(x) + else + fun_l15_n822(x) + end +end + +def fun_l14_n672(x) + if (x < 1) + fun_l15_n191(x) + else + fun_l15_n842(x) + end +end + +def fun_l14_n673(x) + if (x < 1) + fun_l15_n391(x) + else + fun_l15_n119(x) + end +end + +def fun_l14_n674(x) + if (x < 1) + fun_l15_n914(x) + else + fun_l15_n453(x) + end +end + +def fun_l14_n675(x) + if (x < 1) + fun_l15_n73(x) + else + fun_l15_n366(x) + end +end + +def fun_l14_n676(x) + if (x < 1) + fun_l15_n58(x) + else + fun_l15_n804(x) + end +end + +def fun_l14_n677(x) + if (x < 1) + fun_l15_n905(x) + else + fun_l15_n969(x) + end +end + +def fun_l14_n678(x) + if (x < 1) + fun_l15_n301(x) + else + fun_l15_n838(x) + end +end + +def fun_l14_n679(x) + if (x < 1) + fun_l15_n14(x) + else + fun_l15_n567(x) + end +end + +def fun_l14_n680(x) + if (x < 1) + fun_l15_n262(x) + else + fun_l15_n325(x) + end +end + +def fun_l14_n681(x) + if (x < 1) + fun_l15_n985(x) + else + fun_l15_n181(x) + end +end + +def fun_l14_n682(x) + if (x < 1) + fun_l15_n197(x) + else + fun_l15_n175(x) + end +end + +def fun_l14_n683(x) + if (x < 1) + fun_l15_n714(x) + else + fun_l15_n276(x) + end +end + +def fun_l14_n684(x) + if (x < 1) + fun_l15_n720(x) + else + fun_l15_n517(x) + end +end + +def fun_l14_n685(x) + if (x < 1) + fun_l15_n351(x) + else + fun_l15_n917(x) + end +end + +def fun_l14_n686(x) + if (x < 1) + fun_l15_n199(x) + else + fun_l15_n163(x) + end +end + +def fun_l14_n687(x) + if (x < 1) + fun_l15_n769(x) + else + fun_l15_n205(x) + end +end + +def fun_l14_n688(x) + if (x < 1) + fun_l15_n840(x) + else + fun_l15_n756(x) + end +end + +def fun_l14_n689(x) + if (x < 1) + fun_l15_n306(x) + else + fun_l15_n273(x) + end +end + +def fun_l14_n690(x) + if (x < 1) + fun_l15_n549(x) + else + fun_l15_n192(x) + end +end + +def fun_l14_n691(x) + if (x < 1) + fun_l15_n167(x) + else + fun_l15_n403(x) + end +end + +def fun_l14_n692(x) + if (x < 1) + fun_l15_n175(x) + else + fun_l15_n361(x) + end +end + +def fun_l14_n693(x) + if (x < 1) + fun_l15_n208(x) + else + fun_l15_n582(x) + end +end + +def fun_l14_n694(x) + if (x < 1) + fun_l15_n347(x) + else + fun_l15_n962(x) + end +end + +def fun_l14_n695(x) + if (x < 1) + fun_l15_n381(x) + else + fun_l15_n865(x) + end +end + +def fun_l14_n696(x) + if (x < 1) + fun_l15_n76(x) + else + fun_l15_n140(x) + end +end + +def fun_l14_n697(x) + if (x < 1) + fun_l15_n801(x) + else + fun_l15_n267(x) + end +end + +def fun_l14_n698(x) + if (x < 1) + fun_l15_n137(x) + else + fun_l15_n518(x) + end +end + +def fun_l14_n699(x) + if (x < 1) + fun_l15_n56(x) + else + fun_l15_n758(x) + end +end + +def fun_l14_n700(x) + if (x < 1) + fun_l15_n178(x) + else + fun_l15_n641(x) + end +end + +def fun_l14_n701(x) + if (x < 1) + fun_l15_n815(x) + else + fun_l15_n692(x) + end +end + +def fun_l14_n702(x) + if (x < 1) + fun_l15_n355(x) + else + fun_l15_n338(x) + end +end + +def fun_l14_n703(x) + if (x < 1) + fun_l15_n894(x) + else + fun_l15_n843(x) + end +end + +def fun_l14_n704(x) + if (x < 1) + fun_l15_n728(x) + else + fun_l15_n140(x) + end +end + +def fun_l14_n705(x) + if (x < 1) + fun_l15_n304(x) + else + fun_l15_n237(x) + end +end + +def fun_l14_n706(x) + if (x < 1) + fun_l15_n57(x) + else + fun_l15_n947(x) + end +end + +def fun_l14_n707(x) + if (x < 1) + fun_l15_n90(x) + else + fun_l15_n831(x) + end +end + +def fun_l14_n708(x) + if (x < 1) + fun_l15_n487(x) + else + fun_l15_n937(x) + end +end + +def fun_l14_n709(x) + if (x < 1) + fun_l15_n898(x) + else + fun_l15_n151(x) + end +end + +def fun_l14_n710(x) + if (x < 1) + fun_l15_n306(x) + else + fun_l15_n687(x) + end +end + +def fun_l14_n711(x) + if (x < 1) + fun_l15_n151(x) + else + fun_l15_n239(x) + end +end + +def fun_l14_n712(x) + if (x < 1) + fun_l15_n512(x) + else + fun_l15_n203(x) + end +end + +def fun_l14_n713(x) + if (x < 1) + fun_l15_n611(x) + else + fun_l15_n474(x) + end +end + +def fun_l14_n714(x) + if (x < 1) + fun_l15_n109(x) + else + fun_l15_n149(x) + end +end + +def fun_l14_n715(x) + if (x < 1) + fun_l15_n187(x) + else + fun_l15_n563(x) + end +end + +def fun_l14_n716(x) + if (x < 1) + fun_l15_n877(x) + else + fun_l15_n644(x) + end +end + +def fun_l14_n717(x) + if (x < 1) + fun_l15_n960(x) + else + fun_l15_n471(x) + end +end + +def fun_l14_n718(x) + if (x < 1) + fun_l15_n250(x) + else + fun_l15_n93(x) + end +end + +def fun_l14_n719(x) + if (x < 1) + fun_l15_n177(x) + else + fun_l15_n14(x) + end +end + +def fun_l14_n720(x) + if (x < 1) + fun_l15_n912(x) + else + fun_l15_n95(x) + end +end + +def fun_l14_n721(x) + if (x < 1) + fun_l15_n776(x) + else + fun_l15_n256(x) + end +end + +def fun_l14_n722(x) + if (x < 1) + fun_l15_n968(x) + else + fun_l15_n857(x) + end +end + +def fun_l14_n723(x) + if (x < 1) + fun_l15_n402(x) + else + fun_l15_n60(x) + end +end + +def fun_l14_n724(x) + if (x < 1) + fun_l15_n345(x) + else + fun_l15_n688(x) + end +end + +def fun_l14_n725(x) + if (x < 1) + fun_l15_n72(x) + else + fun_l15_n943(x) + end +end + +def fun_l14_n726(x) + if (x < 1) + fun_l15_n535(x) + else + fun_l15_n916(x) + end +end + +def fun_l14_n727(x) + if (x < 1) + fun_l15_n717(x) + else + fun_l15_n354(x) + end +end + +def fun_l14_n728(x) + if (x < 1) + fun_l15_n679(x) + else + fun_l15_n348(x) + end +end + +def fun_l14_n729(x) + if (x < 1) + fun_l15_n187(x) + else + fun_l15_n910(x) + end +end + +def fun_l14_n730(x) + if (x < 1) + fun_l15_n151(x) + else + fun_l15_n689(x) + end +end + +def fun_l14_n731(x) + if (x < 1) + fun_l15_n653(x) + else + fun_l15_n380(x) + end +end + +def fun_l14_n732(x) + if (x < 1) + fun_l15_n627(x) + else + fun_l15_n214(x) + end +end + +def fun_l14_n733(x) + if (x < 1) + fun_l15_n53(x) + else + fun_l15_n882(x) + end +end + +def fun_l14_n734(x) + if (x < 1) + fun_l15_n628(x) + else + fun_l15_n632(x) + end +end + +def fun_l14_n735(x) + if (x < 1) + fun_l15_n415(x) + else + fun_l15_n719(x) + end +end + +def fun_l14_n736(x) + if (x < 1) + fun_l15_n474(x) + else + fun_l15_n966(x) + end +end + +def fun_l14_n737(x) + if (x < 1) + fun_l15_n140(x) + else + fun_l15_n79(x) + end +end + +def fun_l14_n738(x) + if (x < 1) + fun_l15_n682(x) + else + fun_l15_n788(x) + end +end + +def fun_l14_n739(x) + if (x < 1) + fun_l15_n62(x) + else + fun_l15_n289(x) + end +end + +def fun_l14_n740(x) + if (x < 1) + fun_l15_n256(x) + else + fun_l15_n53(x) + end +end + +def fun_l14_n741(x) + if (x < 1) + fun_l15_n571(x) + else + fun_l15_n912(x) + end +end + +def fun_l14_n742(x) + if (x < 1) + fun_l15_n477(x) + else + fun_l15_n757(x) + end +end + +def fun_l14_n743(x) + if (x < 1) + fun_l15_n914(x) + else + fun_l15_n216(x) + end +end + +def fun_l14_n744(x) + if (x < 1) + fun_l15_n474(x) + else + fun_l15_n860(x) + end +end + +def fun_l14_n745(x) + if (x < 1) + fun_l15_n303(x) + else + fun_l15_n417(x) + end +end + +def fun_l14_n746(x) + if (x < 1) + fun_l15_n601(x) + else + fun_l15_n872(x) + end +end + +def fun_l14_n747(x) + if (x < 1) + fun_l15_n70(x) + else + fun_l15_n245(x) + end +end + +def fun_l14_n748(x) + if (x < 1) + fun_l15_n628(x) + else + fun_l15_n503(x) + end +end + +def fun_l14_n749(x) + if (x < 1) + fun_l15_n965(x) + else + fun_l15_n89(x) + end +end + +def fun_l14_n750(x) + if (x < 1) + fun_l15_n910(x) + else + fun_l15_n386(x) + end +end + +def fun_l14_n751(x) + if (x < 1) + fun_l15_n444(x) + else + fun_l15_n765(x) + end +end + +def fun_l14_n752(x) + if (x < 1) + fun_l15_n481(x) + else + fun_l15_n356(x) + end +end + +def fun_l14_n753(x) + if (x < 1) + fun_l15_n45(x) + else + fun_l15_n644(x) + end +end + +def fun_l14_n754(x) + if (x < 1) + fun_l15_n262(x) + else + fun_l15_n681(x) + end +end + +def fun_l14_n755(x) + if (x < 1) + fun_l15_n984(x) + else + fun_l15_n488(x) + end +end + +def fun_l14_n756(x) + if (x < 1) + fun_l15_n751(x) + else + fun_l15_n165(x) + end +end + +def fun_l14_n757(x) + if (x < 1) + fun_l15_n716(x) + else + fun_l15_n483(x) + end +end + +def fun_l14_n758(x) + if (x < 1) + fun_l15_n863(x) + else + fun_l15_n841(x) + end +end + +def fun_l14_n759(x) + if (x < 1) + fun_l15_n654(x) + else + fun_l15_n782(x) + end +end + +def fun_l14_n760(x) + if (x < 1) + fun_l15_n390(x) + else + fun_l15_n254(x) + end +end + +def fun_l14_n761(x) + if (x < 1) + fun_l15_n888(x) + else + fun_l15_n739(x) + end +end + +def fun_l14_n762(x) + if (x < 1) + fun_l15_n775(x) + else + fun_l15_n310(x) + end +end + +def fun_l14_n763(x) + if (x < 1) + fun_l15_n713(x) + else + fun_l15_n246(x) + end +end + +def fun_l14_n764(x) + if (x < 1) + fun_l15_n318(x) + else + fun_l15_n121(x) + end +end + +def fun_l14_n765(x) + if (x < 1) + fun_l15_n424(x) + else + fun_l15_n538(x) + end +end + +def fun_l14_n766(x) + if (x < 1) + fun_l15_n58(x) + else + fun_l15_n487(x) + end +end + +def fun_l14_n767(x) + if (x < 1) + fun_l15_n48(x) + else + fun_l15_n776(x) + end +end + +def fun_l14_n768(x) + if (x < 1) + fun_l15_n156(x) + else + fun_l15_n340(x) + end +end + +def fun_l14_n769(x) + if (x < 1) + fun_l15_n66(x) + else + fun_l15_n655(x) + end +end + +def fun_l14_n770(x) + if (x < 1) + fun_l15_n15(x) + else + fun_l15_n392(x) + end +end + +def fun_l14_n771(x) + if (x < 1) + fun_l15_n331(x) + else + fun_l15_n114(x) + end +end + +def fun_l14_n772(x) + if (x < 1) + fun_l15_n267(x) + else + fun_l15_n711(x) + end +end + +def fun_l14_n773(x) + if (x < 1) + fun_l15_n567(x) + else + fun_l15_n869(x) + end +end + +def fun_l14_n774(x) + if (x < 1) + fun_l15_n915(x) + else + fun_l15_n594(x) + end +end + +def fun_l14_n775(x) + if (x < 1) + fun_l15_n139(x) + else + fun_l15_n285(x) + end +end + +def fun_l14_n776(x) + if (x < 1) + fun_l15_n994(x) + else + fun_l15_n116(x) + end +end + +def fun_l14_n777(x) + if (x < 1) + fun_l15_n999(x) + else + fun_l15_n356(x) + end +end + +def fun_l14_n778(x) + if (x < 1) + fun_l15_n46(x) + else + fun_l15_n845(x) + end +end + +def fun_l14_n779(x) + if (x < 1) + fun_l15_n313(x) + else + fun_l15_n785(x) + end +end + +def fun_l14_n780(x) + if (x < 1) + fun_l15_n282(x) + else + fun_l15_n489(x) + end +end + +def fun_l14_n781(x) + if (x < 1) + fun_l15_n101(x) + else + fun_l15_n928(x) + end +end + +def fun_l14_n782(x) + if (x < 1) + fun_l15_n307(x) + else + fun_l15_n808(x) + end +end + +def fun_l14_n783(x) + if (x < 1) + fun_l15_n475(x) + else + fun_l15_n347(x) + end +end + +def fun_l14_n784(x) + if (x < 1) + fun_l15_n404(x) + else + fun_l15_n65(x) + end +end + +def fun_l14_n785(x) + if (x < 1) + fun_l15_n61(x) + else + fun_l15_n145(x) + end +end + +def fun_l14_n786(x) + if (x < 1) + fun_l15_n919(x) + else + fun_l15_n700(x) + end +end + +def fun_l14_n787(x) + if (x < 1) + fun_l15_n333(x) + else + fun_l15_n702(x) + end +end + +def fun_l14_n788(x) + if (x < 1) + fun_l15_n924(x) + else + fun_l15_n354(x) + end +end + +def fun_l14_n789(x) + if (x < 1) + fun_l15_n171(x) + else + fun_l15_n643(x) + end +end + +def fun_l14_n790(x) + if (x < 1) + fun_l15_n852(x) + else + fun_l15_n421(x) + end +end + +def fun_l14_n791(x) + if (x < 1) + fun_l15_n706(x) + else + fun_l15_n260(x) + end +end + +def fun_l14_n792(x) + if (x < 1) + fun_l15_n908(x) + else + fun_l15_n145(x) + end +end + +def fun_l14_n793(x) + if (x < 1) + fun_l15_n802(x) + else + fun_l15_n365(x) + end +end + +def fun_l14_n794(x) + if (x < 1) + fun_l15_n727(x) + else + fun_l15_n758(x) + end +end + +def fun_l14_n795(x) + if (x < 1) + fun_l15_n463(x) + else + fun_l15_n58(x) + end +end + +def fun_l14_n796(x) + if (x < 1) + fun_l15_n413(x) + else + fun_l15_n525(x) + end +end + +def fun_l14_n797(x) + if (x < 1) + fun_l15_n970(x) + else + fun_l15_n480(x) + end +end + +def fun_l14_n798(x) + if (x < 1) + fun_l15_n476(x) + else + fun_l15_n316(x) + end +end + +def fun_l14_n799(x) + if (x < 1) + fun_l15_n578(x) + else + fun_l15_n586(x) + end +end + +def fun_l14_n800(x) + if (x < 1) + fun_l15_n848(x) + else + fun_l15_n286(x) + end +end + +def fun_l14_n801(x) + if (x < 1) + fun_l15_n745(x) + else + fun_l15_n144(x) + end +end + +def fun_l14_n802(x) + if (x < 1) + fun_l15_n369(x) + else + fun_l15_n819(x) + end +end + +def fun_l14_n803(x) + if (x < 1) + fun_l15_n498(x) + else + fun_l15_n206(x) + end +end + +def fun_l14_n804(x) + if (x < 1) + fun_l15_n817(x) + else + fun_l15_n707(x) + end +end + +def fun_l14_n805(x) + if (x < 1) + fun_l15_n935(x) + else + fun_l15_n43(x) + end +end + +def fun_l14_n806(x) + if (x < 1) + fun_l15_n285(x) + else + fun_l15_n605(x) + end +end + +def fun_l14_n807(x) + if (x < 1) + fun_l15_n392(x) + else + fun_l15_n672(x) + end +end + +def fun_l14_n808(x) + if (x < 1) + fun_l15_n965(x) + else + fun_l15_n610(x) + end +end + +def fun_l14_n809(x) + if (x < 1) + fun_l15_n266(x) + else + fun_l15_n233(x) + end +end + +def fun_l14_n810(x) + if (x < 1) + fun_l15_n514(x) + else + fun_l15_n204(x) + end +end + +def fun_l14_n811(x) + if (x < 1) + fun_l15_n973(x) + else + fun_l15_n768(x) + end +end + +def fun_l14_n812(x) + if (x < 1) + fun_l15_n241(x) + else + fun_l15_n329(x) + end +end + +def fun_l14_n813(x) + if (x < 1) + fun_l15_n150(x) + else + fun_l15_n264(x) + end +end + +def fun_l14_n814(x) + if (x < 1) + fun_l15_n205(x) + else + fun_l15_n595(x) + end +end + +def fun_l14_n815(x) + if (x < 1) + fun_l15_n452(x) + else + fun_l15_n288(x) + end +end + +def fun_l14_n816(x) + if (x < 1) + fun_l15_n385(x) + else + fun_l15_n633(x) + end +end + +def fun_l14_n817(x) + if (x < 1) + fun_l15_n290(x) + else + fun_l15_n656(x) + end +end + +def fun_l14_n818(x) + if (x < 1) + fun_l15_n463(x) + else + fun_l15_n785(x) + end +end + +def fun_l14_n819(x) + if (x < 1) + fun_l15_n183(x) + else + fun_l15_n787(x) + end +end + +def fun_l14_n820(x) + if (x < 1) + fun_l15_n515(x) + else + fun_l15_n104(x) + end +end + +def fun_l14_n821(x) + if (x < 1) + fun_l15_n848(x) + else + fun_l15_n745(x) + end +end + +def fun_l14_n822(x) + if (x < 1) + fun_l15_n268(x) + else + fun_l15_n140(x) + end +end + +def fun_l14_n823(x) + if (x < 1) + fun_l15_n607(x) + else + fun_l15_n785(x) + end +end + +def fun_l14_n824(x) + if (x < 1) + fun_l15_n261(x) + else + fun_l15_n659(x) + end +end + +def fun_l14_n825(x) + if (x < 1) + fun_l15_n628(x) + else + fun_l15_n427(x) + end +end + +def fun_l14_n826(x) + if (x < 1) + fun_l15_n293(x) + else + fun_l15_n141(x) + end +end + +def fun_l14_n827(x) + if (x < 1) + fun_l15_n112(x) + else + fun_l15_n135(x) + end +end + +def fun_l14_n828(x) + if (x < 1) + fun_l15_n779(x) + else + fun_l15_n323(x) + end +end + +def fun_l14_n829(x) + if (x < 1) + fun_l15_n295(x) + else + fun_l15_n753(x) + end +end + +def fun_l14_n830(x) + if (x < 1) + fun_l15_n683(x) + else + fun_l15_n303(x) + end +end + +def fun_l14_n831(x) + if (x < 1) + fun_l15_n522(x) + else + fun_l15_n983(x) + end +end + +def fun_l14_n832(x) + if (x < 1) + fun_l15_n338(x) + else + fun_l15_n835(x) + end +end + +def fun_l14_n833(x) + if (x < 1) + fun_l15_n888(x) + else + fun_l15_n95(x) + end +end + +def fun_l14_n834(x) + if (x < 1) + fun_l15_n510(x) + else + fun_l15_n342(x) + end +end + +def fun_l14_n835(x) + if (x < 1) + fun_l15_n168(x) + else + fun_l15_n864(x) + end +end + +def fun_l14_n836(x) + if (x < 1) + fun_l15_n392(x) + else + fun_l15_n779(x) + end +end + +def fun_l14_n837(x) + if (x < 1) + fun_l15_n176(x) + else + fun_l15_n354(x) + end +end + +def fun_l14_n838(x) + if (x < 1) + fun_l15_n477(x) + else + fun_l15_n95(x) + end +end + +def fun_l14_n839(x) + if (x < 1) + fun_l15_n223(x) + else + fun_l15_n213(x) + end +end + +def fun_l14_n840(x) + if (x < 1) + fun_l15_n228(x) + else + fun_l15_n897(x) + end +end + +def fun_l14_n841(x) + if (x < 1) + fun_l15_n551(x) + else + fun_l15_n649(x) + end +end + +def fun_l14_n842(x) + if (x < 1) + fun_l15_n541(x) + else + fun_l15_n741(x) + end +end + +def fun_l14_n843(x) + if (x < 1) + fun_l15_n464(x) + else + fun_l15_n403(x) + end +end + +def fun_l14_n844(x) + if (x < 1) + fun_l15_n853(x) + else + fun_l15_n223(x) + end +end + +def fun_l14_n845(x) + if (x < 1) + fun_l15_n443(x) + else + fun_l15_n441(x) + end +end + +def fun_l14_n846(x) + if (x < 1) + fun_l15_n864(x) + else + fun_l15_n912(x) + end +end + +def fun_l14_n847(x) + if (x < 1) + fun_l15_n631(x) + else + fun_l15_n764(x) + end +end + +def fun_l14_n848(x) + if (x < 1) + fun_l15_n198(x) + else + fun_l15_n825(x) + end +end + +def fun_l14_n849(x) + if (x < 1) + fun_l15_n525(x) + else + fun_l15_n31(x) + end +end + +def fun_l14_n850(x) + if (x < 1) + fun_l15_n928(x) + else + fun_l15_n893(x) + end +end + +def fun_l14_n851(x) + if (x < 1) + fun_l15_n499(x) + else + fun_l15_n297(x) + end +end + +def fun_l14_n852(x) + if (x < 1) + fun_l15_n777(x) + else + fun_l15_n239(x) + end +end + +def fun_l14_n853(x) + if (x < 1) + fun_l15_n120(x) + else + fun_l15_n134(x) + end +end + +def fun_l14_n854(x) + if (x < 1) + fun_l15_n613(x) + else + fun_l15_n324(x) + end +end + +def fun_l14_n855(x) + if (x < 1) + fun_l15_n22(x) + else + fun_l15_n192(x) + end +end + +def fun_l14_n856(x) + if (x < 1) + fun_l15_n609(x) + else + fun_l15_n284(x) + end +end + +def fun_l14_n857(x) + if (x < 1) + fun_l15_n130(x) + else + fun_l15_n256(x) + end +end + +def fun_l14_n858(x) + if (x < 1) + fun_l15_n40(x) + else + fun_l15_n340(x) + end +end + +def fun_l14_n859(x) + if (x < 1) + fun_l15_n644(x) + else + fun_l15_n522(x) + end +end + +def fun_l14_n860(x) + if (x < 1) + fun_l15_n363(x) + else + fun_l15_n52(x) + end +end + +def fun_l14_n861(x) + if (x < 1) + fun_l15_n166(x) + else + fun_l15_n452(x) + end +end + +def fun_l14_n862(x) + if (x < 1) + fun_l15_n552(x) + else + fun_l15_n534(x) + end +end + +def fun_l14_n863(x) + if (x < 1) + fun_l15_n489(x) + else + fun_l15_n181(x) + end +end + +def fun_l14_n864(x) + if (x < 1) + fun_l15_n584(x) + else + fun_l15_n871(x) + end +end + +def fun_l14_n865(x) + if (x < 1) + fun_l15_n868(x) + else + fun_l15_n807(x) + end +end + +def fun_l14_n866(x) + if (x < 1) + fun_l15_n159(x) + else + fun_l15_n226(x) + end +end + +def fun_l14_n867(x) + if (x < 1) + fun_l15_n440(x) + else + fun_l15_n318(x) + end +end + +def fun_l14_n868(x) + if (x < 1) + fun_l15_n603(x) + else + fun_l15_n440(x) + end +end + +def fun_l14_n869(x) + if (x < 1) + fun_l15_n478(x) + else + fun_l15_n896(x) + end +end + +def fun_l14_n870(x) + if (x < 1) + fun_l15_n593(x) + else + fun_l15_n973(x) + end +end + +def fun_l14_n871(x) + if (x < 1) + fun_l15_n767(x) + else + fun_l15_n828(x) + end +end + +def fun_l14_n872(x) + if (x < 1) + fun_l15_n578(x) + else + fun_l15_n309(x) + end +end + +def fun_l14_n873(x) + if (x < 1) + fun_l15_n959(x) + else + fun_l15_n263(x) + end +end + +def fun_l14_n874(x) + if (x < 1) + fun_l15_n170(x) + else + fun_l15_n700(x) + end +end + +def fun_l14_n875(x) + if (x < 1) + fun_l15_n800(x) + else + fun_l15_n703(x) + end +end + +def fun_l14_n876(x) + if (x < 1) + fun_l15_n556(x) + else + fun_l15_n854(x) + end +end + +def fun_l14_n877(x) + if (x < 1) + fun_l15_n472(x) + else + fun_l15_n893(x) + end +end + +def fun_l14_n878(x) + if (x < 1) + fun_l15_n847(x) + else + fun_l15_n438(x) + end +end + +def fun_l14_n879(x) + if (x < 1) + fun_l15_n401(x) + else + fun_l15_n59(x) + end +end + +def fun_l14_n880(x) + if (x < 1) + fun_l15_n321(x) + else + fun_l15_n57(x) + end +end + +def fun_l14_n881(x) + if (x < 1) + fun_l15_n664(x) + else + fun_l15_n448(x) + end +end + +def fun_l14_n882(x) + if (x < 1) + fun_l15_n113(x) + else + fun_l15_n270(x) + end +end + +def fun_l14_n883(x) + if (x < 1) + fun_l15_n596(x) + else + fun_l15_n354(x) + end +end + +def fun_l14_n884(x) + if (x < 1) + fun_l15_n681(x) + else + fun_l15_n801(x) + end +end + +def fun_l14_n885(x) + if (x < 1) + fun_l15_n802(x) + else + fun_l15_n327(x) + end +end + +def fun_l14_n886(x) + if (x < 1) + fun_l15_n657(x) + else + fun_l15_n325(x) + end +end + +def fun_l14_n887(x) + if (x < 1) + fun_l15_n108(x) + else + fun_l15_n11(x) + end +end + +def fun_l14_n888(x) + if (x < 1) + fun_l15_n696(x) + else + fun_l15_n88(x) + end +end + +def fun_l14_n889(x) + if (x < 1) + fun_l15_n220(x) + else + fun_l15_n282(x) + end +end + +def fun_l14_n890(x) + if (x < 1) + fun_l15_n702(x) + else + fun_l15_n550(x) + end +end + +def fun_l14_n891(x) + if (x < 1) + fun_l15_n67(x) + else + fun_l15_n763(x) + end +end + +def fun_l14_n892(x) + if (x < 1) + fun_l15_n386(x) + else + fun_l15_n938(x) + end +end + +def fun_l14_n893(x) + if (x < 1) + fun_l15_n193(x) + else + fun_l15_n110(x) + end +end + +def fun_l14_n894(x) + if (x < 1) + fun_l15_n408(x) + else + fun_l15_n392(x) + end +end + +def fun_l14_n895(x) + if (x < 1) + fun_l15_n488(x) + else + fun_l15_n445(x) + end +end + +def fun_l14_n896(x) + if (x < 1) + fun_l15_n572(x) + else + fun_l15_n645(x) + end +end + +def fun_l14_n897(x) + if (x < 1) + fun_l15_n432(x) + else + fun_l15_n288(x) + end +end + +def fun_l14_n898(x) + if (x < 1) + fun_l15_n466(x) + else + fun_l15_n877(x) + end +end + +def fun_l14_n899(x) + if (x < 1) + fun_l15_n981(x) + else + fun_l15_n546(x) + end +end + +def fun_l14_n900(x) + if (x < 1) + fun_l15_n334(x) + else + fun_l15_n198(x) + end +end + +def fun_l14_n901(x) + if (x < 1) + fun_l15_n447(x) + else + fun_l15_n881(x) + end +end + +def fun_l14_n902(x) + if (x < 1) + fun_l15_n818(x) + else + fun_l15_n882(x) + end +end + +def fun_l14_n903(x) + if (x < 1) + fun_l15_n86(x) + else + fun_l15_n864(x) + end +end + +def fun_l14_n904(x) + if (x < 1) + fun_l15_n981(x) + else + fun_l15_n472(x) + end +end + +def fun_l14_n905(x) + if (x < 1) + fun_l15_n684(x) + else + fun_l15_n314(x) + end +end + +def fun_l14_n906(x) + if (x < 1) + fun_l15_n792(x) + else + fun_l15_n270(x) + end +end + +def fun_l14_n907(x) + if (x < 1) + fun_l15_n958(x) + else + fun_l15_n293(x) + end +end + +def fun_l14_n908(x) + if (x < 1) + fun_l15_n953(x) + else + fun_l15_n837(x) + end +end + +def fun_l14_n909(x) + if (x < 1) + fun_l15_n448(x) + else + fun_l15_n985(x) + end +end + +def fun_l14_n910(x) + if (x < 1) + fun_l15_n148(x) + else + fun_l15_n210(x) + end +end + +def fun_l14_n911(x) + if (x < 1) + fun_l15_n51(x) + else + fun_l15_n714(x) + end +end + +def fun_l14_n912(x) + if (x < 1) + fun_l15_n538(x) + else + fun_l15_n653(x) + end +end + +def fun_l14_n913(x) + if (x < 1) + fun_l15_n374(x) + else + fun_l15_n836(x) + end +end + +def fun_l14_n914(x) + if (x < 1) + fun_l15_n5(x) + else + fun_l15_n307(x) + end +end + +def fun_l14_n915(x) + if (x < 1) + fun_l15_n670(x) + else + fun_l15_n961(x) + end +end + +def fun_l14_n916(x) + if (x < 1) + fun_l15_n600(x) + else + fun_l15_n843(x) + end +end + +def fun_l14_n917(x) + if (x < 1) + fun_l15_n235(x) + else + fun_l15_n542(x) + end +end + +def fun_l14_n918(x) + if (x < 1) + fun_l15_n883(x) + else + fun_l15_n990(x) + end +end + +def fun_l14_n919(x) + if (x < 1) + fun_l15_n988(x) + else + fun_l15_n678(x) + end +end + +def fun_l14_n920(x) + if (x < 1) + fun_l15_n246(x) + else + fun_l15_n942(x) + end +end + +def fun_l14_n921(x) + if (x < 1) + fun_l15_n316(x) + else + fun_l15_n503(x) + end +end + +def fun_l14_n922(x) + if (x < 1) + fun_l15_n392(x) + else + fun_l15_n948(x) + end +end + +def fun_l14_n923(x) + if (x < 1) + fun_l15_n79(x) + else + fun_l15_n375(x) + end +end + +def fun_l14_n924(x) + if (x < 1) + fun_l15_n139(x) + else + fun_l15_n350(x) + end +end + +def fun_l14_n925(x) + if (x < 1) + fun_l15_n132(x) + else + fun_l15_n27(x) + end +end + +def fun_l14_n926(x) + if (x < 1) + fun_l15_n608(x) + else + fun_l15_n910(x) + end +end + +def fun_l14_n927(x) + if (x < 1) + fun_l15_n447(x) + else + fun_l15_n361(x) + end +end + +def fun_l14_n928(x) + if (x < 1) + fun_l15_n432(x) + else + fun_l15_n943(x) + end +end + +def fun_l14_n929(x) + if (x < 1) + fun_l15_n726(x) + else + fun_l15_n19(x) + end +end + +def fun_l14_n930(x) + if (x < 1) + fun_l15_n311(x) + else + fun_l15_n683(x) + end +end + +def fun_l14_n931(x) + if (x < 1) + fun_l15_n988(x) + else + fun_l15_n731(x) + end +end + +def fun_l14_n932(x) + if (x < 1) + fun_l15_n916(x) + else + fun_l15_n625(x) + end +end + +def fun_l14_n933(x) + if (x < 1) + fun_l15_n723(x) + else + fun_l15_n954(x) + end +end + +def fun_l14_n934(x) + if (x < 1) + fun_l15_n82(x) + else + fun_l15_n140(x) + end +end + +def fun_l14_n935(x) + if (x < 1) + fun_l15_n11(x) + else + fun_l15_n407(x) + end +end + +def fun_l14_n936(x) + if (x < 1) + fun_l15_n261(x) + else + fun_l15_n733(x) + end +end + +def fun_l14_n937(x) + if (x < 1) + fun_l15_n37(x) + else + fun_l15_n617(x) + end +end + +def fun_l14_n938(x) + if (x < 1) + fun_l15_n733(x) + else + fun_l15_n178(x) + end +end + +def fun_l14_n939(x) + if (x < 1) + fun_l15_n989(x) + else + fun_l15_n917(x) + end +end + +def fun_l14_n940(x) + if (x < 1) + fun_l15_n297(x) + else + fun_l15_n393(x) + end +end + +def fun_l14_n941(x) + if (x < 1) + fun_l15_n167(x) + else + fun_l15_n498(x) + end +end + +def fun_l14_n942(x) + if (x < 1) + fun_l15_n365(x) + else + fun_l15_n158(x) + end +end + +def fun_l14_n943(x) + if (x < 1) + fun_l15_n340(x) + else + fun_l15_n813(x) + end +end + +def fun_l14_n944(x) + if (x < 1) + fun_l15_n417(x) + else + fun_l15_n150(x) + end +end + +def fun_l14_n945(x) + if (x < 1) + fun_l15_n477(x) + else + fun_l15_n639(x) + end +end + +def fun_l14_n946(x) + if (x < 1) + fun_l15_n243(x) + else + fun_l15_n439(x) + end +end + +def fun_l14_n947(x) + if (x < 1) + fun_l15_n149(x) + else + fun_l15_n881(x) + end +end + +def fun_l14_n948(x) + if (x < 1) + fun_l15_n383(x) + else + fun_l15_n525(x) + end +end + +def fun_l14_n949(x) + if (x < 1) + fun_l15_n482(x) + else + fun_l15_n625(x) + end +end + +def fun_l14_n950(x) + if (x < 1) + fun_l15_n376(x) + else + fun_l15_n743(x) + end +end + +def fun_l14_n951(x) + if (x < 1) + fun_l15_n53(x) + else + fun_l15_n734(x) + end +end + +def fun_l14_n952(x) + if (x < 1) + fun_l15_n437(x) + else + fun_l15_n829(x) + end +end + +def fun_l14_n953(x) + if (x < 1) + fun_l15_n673(x) + else + fun_l15_n540(x) + end +end + +def fun_l14_n954(x) + if (x < 1) + fun_l15_n477(x) + else + fun_l15_n488(x) + end +end + +def fun_l14_n955(x) + if (x < 1) + fun_l15_n876(x) + else + fun_l15_n710(x) + end +end + +def fun_l14_n956(x) + if (x < 1) + fun_l15_n823(x) + else + fun_l15_n841(x) + end +end + +def fun_l14_n957(x) + if (x < 1) + fun_l15_n948(x) + else + fun_l15_n378(x) + end +end + +def fun_l14_n958(x) + if (x < 1) + fun_l15_n941(x) + else + fun_l15_n555(x) + end +end + +def fun_l14_n959(x) + if (x < 1) + fun_l15_n204(x) + else + fun_l15_n792(x) + end +end + +def fun_l14_n960(x) + if (x < 1) + fun_l15_n897(x) + else + fun_l15_n287(x) + end +end + +def fun_l14_n961(x) + if (x < 1) + fun_l15_n771(x) + else + fun_l15_n409(x) + end +end + +def fun_l14_n962(x) + if (x < 1) + fun_l15_n597(x) + else + fun_l15_n190(x) + end +end + +def fun_l14_n963(x) + if (x < 1) + fun_l15_n573(x) + else + fun_l15_n982(x) + end +end + +def fun_l14_n964(x) + if (x < 1) + fun_l15_n186(x) + else + fun_l15_n363(x) + end +end + +def fun_l14_n965(x) + if (x < 1) + fun_l15_n694(x) + else + fun_l15_n319(x) + end +end + +def fun_l14_n966(x) + if (x < 1) + fun_l15_n312(x) + else + fun_l15_n332(x) + end +end + +def fun_l14_n967(x) + if (x < 1) + fun_l15_n754(x) + else + fun_l15_n965(x) + end +end + +def fun_l14_n968(x) + if (x < 1) + fun_l15_n18(x) + else + fun_l15_n723(x) + end +end + +def fun_l14_n969(x) + if (x < 1) + fun_l15_n111(x) + else + fun_l15_n447(x) + end +end + +def fun_l14_n970(x) + if (x < 1) + fun_l15_n3(x) + else + fun_l15_n302(x) + end +end + +def fun_l14_n971(x) + if (x < 1) + fun_l15_n121(x) + else + fun_l15_n764(x) + end +end + +def fun_l14_n972(x) + if (x < 1) + fun_l15_n192(x) + else + fun_l15_n692(x) + end +end + +def fun_l14_n973(x) + if (x < 1) + fun_l15_n596(x) + else + fun_l15_n514(x) + end +end + +def fun_l14_n974(x) + if (x < 1) + fun_l15_n845(x) + else + fun_l15_n245(x) + end +end + +def fun_l14_n975(x) + if (x < 1) + fun_l15_n566(x) + else + fun_l15_n58(x) + end +end + +def fun_l14_n976(x) + if (x < 1) + fun_l15_n843(x) + else + fun_l15_n35(x) + end +end + +def fun_l14_n977(x) + if (x < 1) + fun_l15_n995(x) + else + fun_l15_n723(x) + end +end + +def fun_l14_n978(x) + if (x < 1) + fun_l15_n534(x) + else + fun_l15_n704(x) + end +end + +def fun_l14_n979(x) + if (x < 1) + fun_l15_n533(x) + else + fun_l15_n492(x) + end +end + +def fun_l14_n980(x) + if (x < 1) + fun_l15_n758(x) + else + fun_l15_n655(x) + end +end + +def fun_l14_n981(x) + if (x < 1) + fun_l15_n94(x) + else + fun_l15_n246(x) + end +end + +def fun_l14_n982(x) + if (x < 1) + fun_l15_n873(x) + else + fun_l15_n996(x) + end +end + +def fun_l14_n983(x) + if (x < 1) + fun_l15_n681(x) + else + fun_l15_n522(x) + end +end + +def fun_l14_n984(x) + if (x < 1) + fun_l15_n272(x) + else + fun_l15_n501(x) + end +end + +def fun_l14_n985(x) + if (x < 1) + fun_l15_n345(x) + else + fun_l15_n61(x) + end +end + +def fun_l14_n986(x) + if (x < 1) + fun_l15_n517(x) + else + fun_l15_n151(x) + end +end + +def fun_l14_n987(x) + if (x < 1) + fun_l15_n792(x) + else + fun_l15_n969(x) + end +end + +def fun_l14_n988(x) + if (x < 1) + fun_l15_n683(x) + else + fun_l15_n537(x) + end +end + +def fun_l14_n989(x) + if (x < 1) + fun_l15_n310(x) + else + fun_l15_n367(x) + end +end + +def fun_l14_n990(x) + if (x < 1) + fun_l15_n249(x) + else + fun_l15_n897(x) + end +end + +def fun_l14_n991(x) + if (x < 1) + fun_l15_n389(x) + else + fun_l15_n176(x) + end +end + +def fun_l14_n992(x) + if (x < 1) + fun_l15_n233(x) + else + fun_l15_n220(x) + end +end + +def fun_l14_n993(x) + if (x < 1) + fun_l15_n161(x) + else + fun_l15_n642(x) + end +end + +def fun_l14_n994(x) + if (x < 1) + fun_l15_n163(x) + else + fun_l15_n5(x) + end +end + +def fun_l14_n995(x) + if (x < 1) + fun_l15_n678(x) + else + fun_l15_n108(x) + end +end + +def fun_l14_n996(x) + if (x < 1) + fun_l15_n732(x) + else + fun_l15_n26(x) + end +end + +def fun_l14_n997(x) + if (x < 1) + fun_l15_n805(x) + else + fun_l15_n726(x) + end +end + +def fun_l14_n998(x) + if (x < 1) + fun_l15_n543(x) + else + fun_l15_n102(x) + end +end + +def fun_l14_n999(x) + if (x < 1) + fun_l15_n358(x) + else + fun_l15_n986(x) + end +end + +def fun_l15_n0(x) + if (x < 1) + fun_l16_n832(x) + else + fun_l16_n319(x) + end +end + +def fun_l15_n1(x) + if (x < 1) + fun_l16_n920(x) + else + fun_l16_n27(x) + end +end + +def fun_l15_n2(x) + if (x < 1) + fun_l16_n929(x) + else + fun_l16_n230(x) + end +end + +def fun_l15_n3(x) + if (x < 1) + fun_l16_n135(x) + else + fun_l16_n427(x) + end +end + +def fun_l15_n4(x) + if (x < 1) + fun_l16_n299(x) + else + fun_l16_n811(x) + end +end + +def fun_l15_n5(x) + if (x < 1) + fun_l16_n821(x) + else + fun_l16_n717(x) + end +end + +def fun_l15_n6(x) + if (x < 1) + fun_l16_n907(x) + else + fun_l16_n348(x) + end +end + +def fun_l15_n7(x) + if (x < 1) + fun_l16_n708(x) + else + fun_l16_n180(x) + end +end + +def fun_l15_n8(x) + if (x < 1) + fun_l16_n835(x) + else + fun_l16_n754(x) + end +end + +def fun_l15_n9(x) + if (x < 1) + fun_l16_n25(x) + else + fun_l16_n607(x) + end +end + +def fun_l15_n10(x) + if (x < 1) + fun_l16_n73(x) + else + fun_l16_n784(x) + end +end + +def fun_l15_n11(x) + if (x < 1) + fun_l16_n413(x) + else + fun_l16_n914(x) + end +end + +def fun_l15_n12(x) + if (x < 1) + fun_l16_n734(x) + else + fun_l16_n688(x) + end +end + +def fun_l15_n13(x) + if (x < 1) + fun_l16_n658(x) + else + fun_l16_n491(x) + end +end + +def fun_l15_n14(x) + if (x < 1) + fun_l16_n839(x) + else + fun_l16_n740(x) + end +end + +def fun_l15_n15(x) + if (x < 1) + fun_l16_n378(x) + else + fun_l16_n800(x) + end +end + +def fun_l15_n16(x) + if (x < 1) + fun_l16_n980(x) + else + fun_l16_n83(x) + end +end + +def fun_l15_n17(x) + if (x < 1) + fun_l16_n338(x) + else + fun_l16_n871(x) + end +end + +def fun_l15_n18(x) + if (x < 1) + fun_l16_n497(x) + else + fun_l16_n347(x) + end +end + +def fun_l15_n19(x) + if (x < 1) + fun_l16_n483(x) + else + fun_l16_n913(x) + end +end + +def fun_l15_n20(x) + if (x < 1) + fun_l16_n663(x) + else + fun_l16_n432(x) + end +end + +def fun_l15_n21(x) + if (x < 1) + fun_l16_n787(x) + else + fun_l16_n248(x) + end +end + +def fun_l15_n22(x) + if (x < 1) + fun_l16_n257(x) + else + fun_l16_n944(x) + end +end + +def fun_l15_n23(x) + if (x < 1) + fun_l16_n11(x) + else + fun_l16_n343(x) + end +end + +def fun_l15_n24(x) + if (x < 1) + fun_l16_n860(x) + else + fun_l16_n752(x) + end +end + +def fun_l15_n25(x) + if (x < 1) + fun_l16_n766(x) + else + fun_l16_n719(x) + end +end + +def fun_l15_n26(x) + if (x < 1) + fun_l16_n144(x) + else + fun_l16_n963(x) + end +end + +def fun_l15_n27(x) + if (x < 1) + fun_l16_n659(x) + else + fun_l16_n916(x) + end +end + +def fun_l15_n28(x) + if (x < 1) + fun_l16_n429(x) + else + fun_l16_n272(x) + end +end + +def fun_l15_n29(x) + if (x < 1) + fun_l16_n54(x) + else + fun_l16_n794(x) + end +end + +def fun_l15_n30(x) + if (x < 1) + fun_l16_n273(x) + else + fun_l16_n929(x) + end +end + +def fun_l15_n31(x) + if (x < 1) + fun_l16_n868(x) + else + fun_l16_n967(x) + end +end + +def fun_l15_n32(x) + if (x < 1) + fun_l16_n888(x) + else + fun_l16_n283(x) + end +end + +def fun_l15_n33(x) + if (x < 1) + fun_l16_n6(x) + else + fun_l16_n677(x) + end +end + +def fun_l15_n34(x) + if (x < 1) + fun_l16_n248(x) + else + fun_l16_n831(x) + end +end + +def fun_l15_n35(x) + if (x < 1) + fun_l16_n832(x) + else + fun_l16_n634(x) + end +end + +def fun_l15_n36(x) + if (x < 1) + fun_l16_n221(x) + else + fun_l16_n401(x) + end +end + +def fun_l15_n37(x) + if (x < 1) + fun_l16_n403(x) + else + fun_l16_n29(x) + end +end + +def fun_l15_n38(x) + if (x < 1) + fun_l16_n11(x) + else + fun_l16_n517(x) + end +end + +def fun_l15_n39(x) + if (x < 1) + fun_l16_n234(x) + else + fun_l16_n231(x) + end +end + +def fun_l15_n40(x) + if (x < 1) + fun_l16_n185(x) + else + fun_l16_n818(x) + end +end + +def fun_l15_n41(x) + if (x < 1) + fun_l16_n169(x) + else + fun_l16_n239(x) + end +end + +def fun_l15_n42(x) + if (x < 1) + fun_l16_n111(x) + else + fun_l16_n836(x) + end +end + +def fun_l15_n43(x) + if (x < 1) + fun_l16_n832(x) + else + fun_l16_n714(x) + end +end + +def fun_l15_n44(x) + if (x < 1) + fun_l16_n167(x) + else + fun_l16_n65(x) + end +end + +def fun_l15_n45(x) + if (x < 1) + fun_l16_n801(x) + else + fun_l16_n456(x) + end +end + +def fun_l15_n46(x) + if (x < 1) + fun_l16_n894(x) + else + fun_l16_n103(x) + end +end + +def fun_l15_n47(x) + if (x < 1) + fun_l16_n156(x) + else + fun_l16_n228(x) + end +end + +def fun_l15_n48(x) + if (x < 1) + fun_l16_n167(x) + else + fun_l16_n317(x) + end +end + +def fun_l15_n49(x) + if (x < 1) + fun_l16_n864(x) + else + fun_l16_n425(x) + end +end + +def fun_l15_n50(x) + if (x < 1) + fun_l16_n11(x) + else + fun_l16_n498(x) + end +end + +def fun_l15_n51(x) + if (x < 1) + fun_l16_n209(x) + else + fun_l16_n399(x) + end +end + +def fun_l15_n52(x) + if (x < 1) + fun_l16_n320(x) + else + fun_l16_n912(x) + end +end + +def fun_l15_n53(x) + if (x < 1) + fun_l16_n135(x) + else + fun_l16_n349(x) + end +end + +def fun_l15_n54(x) + if (x < 1) + fun_l16_n410(x) + else + fun_l16_n849(x) + end +end + +def fun_l15_n55(x) + if (x < 1) + fun_l16_n989(x) + else + fun_l16_n700(x) + end +end + +def fun_l15_n56(x) + if (x < 1) + fun_l16_n79(x) + else + fun_l16_n549(x) + end +end + +def fun_l15_n57(x) + if (x < 1) + fun_l16_n396(x) + else + fun_l16_n182(x) + end +end + +def fun_l15_n58(x) + if (x < 1) + fun_l16_n765(x) + else + fun_l16_n225(x) + end +end + +def fun_l15_n59(x) + if (x < 1) + fun_l16_n124(x) + else + fun_l16_n694(x) + end +end + +def fun_l15_n60(x) + if (x < 1) + fun_l16_n813(x) + else + fun_l16_n319(x) + end +end + +def fun_l15_n61(x) + if (x < 1) + fun_l16_n568(x) + else + fun_l16_n581(x) + end +end + +def fun_l15_n62(x) + if (x < 1) + fun_l16_n667(x) + else + fun_l16_n12(x) + end +end + +def fun_l15_n63(x) + if (x < 1) + fun_l16_n176(x) + else + fun_l16_n136(x) + end +end + +def fun_l15_n64(x) + if (x < 1) + fun_l16_n620(x) + else + fun_l16_n937(x) + end +end + +def fun_l15_n65(x) + if (x < 1) + fun_l16_n130(x) + else + fun_l16_n503(x) + end +end + +def fun_l15_n66(x) + if (x < 1) + fun_l16_n774(x) + else + fun_l16_n109(x) + end +end + +def fun_l15_n67(x) + if (x < 1) + fun_l16_n817(x) + else + fun_l16_n497(x) + end +end + +def fun_l15_n68(x) + if (x < 1) + fun_l16_n123(x) + else + fun_l16_n482(x) + end +end + +def fun_l15_n69(x) + if (x < 1) + fun_l16_n173(x) + else + fun_l16_n22(x) + end +end + +def fun_l15_n70(x) + if (x < 1) + fun_l16_n648(x) + else + fun_l16_n671(x) + end +end + +def fun_l15_n71(x) + if (x < 1) + fun_l16_n831(x) + else + fun_l16_n126(x) + end +end + +def fun_l15_n72(x) + if (x < 1) + fun_l16_n731(x) + else + fun_l16_n273(x) + end +end + +def fun_l15_n73(x) + if (x < 1) + fun_l16_n695(x) + else + fun_l16_n772(x) + end +end + +def fun_l15_n74(x) + if (x < 1) + fun_l16_n831(x) + else + fun_l16_n49(x) + end +end + +def fun_l15_n75(x) + if (x < 1) + fun_l16_n501(x) + else + fun_l16_n4(x) + end +end + +def fun_l15_n76(x) + if (x < 1) + fun_l16_n712(x) + else + fun_l16_n762(x) + end +end + +def fun_l15_n77(x) + if (x < 1) + fun_l16_n585(x) + else + fun_l16_n398(x) + end +end + +def fun_l15_n78(x) + if (x < 1) + fun_l16_n811(x) + else + fun_l16_n866(x) + end +end + +def fun_l15_n79(x) + if (x < 1) + fun_l16_n69(x) + else + fun_l16_n502(x) + end +end + +def fun_l15_n80(x) + if (x < 1) + fun_l16_n885(x) + else + fun_l16_n116(x) + end +end + +def fun_l15_n81(x) + if (x < 1) + fun_l16_n30(x) + else + fun_l16_n1(x) + end +end + +def fun_l15_n82(x) + if (x < 1) + fun_l16_n105(x) + else + fun_l16_n526(x) + end +end + +def fun_l15_n83(x) + if (x < 1) + fun_l16_n760(x) + else + fun_l16_n206(x) + end +end + +def fun_l15_n84(x) + if (x < 1) + fun_l16_n722(x) + else + fun_l16_n211(x) + end +end + +def fun_l15_n85(x) + if (x < 1) + fun_l16_n145(x) + else + fun_l16_n222(x) + end +end + +def fun_l15_n86(x) + if (x < 1) + fun_l16_n691(x) + else + fun_l16_n885(x) + end +end + +def fun_l15_n87(x) + if (x < 1) + fun_l16_n2(x) + else + fun_l16_n180(x) + end +end + +def fun_l15_n88(x) + if (x < 1) + fun_l16_n272(x) + else + fun_l16_n433(x) + end +end + +def fun_l15_n89(x) + if (x < 1) + fun_l16_n31(x) + else + fun_l16_n854(x) + end +end + +def fun_l15_n90(x) + if (x < 1) + fun_l16_n264(x) + else + fun_l16_n231(x) + end +end + +def fun_l15_n91(x) + if (x < 1) + fun_l16_n637(x) + else + fun_l16_n96(x) + end +end + +def fun_l15_n92(x) + if (x < 1) + fun_l16_n317(x) + else + fun_l16_n56(x) + end +end + +def fun_l15_n93(x) + if (x < 1) + fun_l16_n523(x) + else + fun_l16_n948(x) + end +end + +def fun_l15_n94(x) + if (x < 1) + fun_l16_n694(x) + else + fun_l16_n948(x) + end +end + +def fun_l15_n95(x) + if (x < 1) + fun_l16_n708(x) + else + fun_l16_n581(x) + end +end + +def fun_l15_n96(x) + if (x < 1) + fun_l16_n725(x) + else + fun_l16_n931(x) + end +end + +def fun_l15_n97(x) + if (x < 1) + fun_l16_n432(x) + else + fun_l16_n367(x) + end +end + +def fun_l15_n98(x) + if (x < 1) + fun_l16_n671(x) + else + fun_l16_n165(x) + end +end + +def fun_l15_n99(x) + if (x < 1) + fun_l16_n617(x) + else + fun_l16_n498(x) + end +end + +def fun_l15_n100(x) + if (x < 1) + fun_l16_n32(x) + else + fun_l16_n103(x) + end +end + +def fun_l15_n101(x) + if (x < 1) + fun_l16_n619(x) + else + fun_l16_n556(x) + end +end + +def fun_l15_n102(x) + if (x < 1) + fun_l16_n0(x) + else + fun_l16_n925(x) + end +end + +def fun_l15_n103(x) + if (x < 1) + fun_l16_n484(x) + else + fun_l16_n889(x) + end +end + +def fun_l15_n104(x) + if (x < 1) + fun_l16_n557(x) + else + fun_l16_n465(x) + end +end + +def fun_l15_n105(x) + if (x < 1) + fun_l16_n486(x) + else + fun_l16_n720(x) + end +end + +def fun_l15_n106(x) + if (x < 1) + fun_l16_n281(x) + else + fun_l16_n61(x) + end +end + +def fun_l15_n107(x) + if (x < 1) + fun_l16_n861(x) + else + fun_l16_n944(x) + end +end + +def fun_l15_n108(x) + if (x < 1) + fun_l16_n739(x) + else + fun_l16_n192(x) + end +end + +def fun_l15_n109(x) + if (x < 1) + fun_l16_n327(x) + else + fun_l16_n423(x) + end +end + +def fun_l15_n110(x) + if (x < 1) + fun_l16_n541(x) + else + fun_l16_n927(x) + end +end + +def fun_l15_n111(x) + if (x < 1) + fun_l16_n86(x) + else + fun_l16_n170(x) + end +end + +def fun_l15_n112(x) + if (x < 1) + fun_l16_n508(x) + else + fun_l16_n554(x) + end +end + +def fun_l15_n113(x) + if (x < 1) + fun_l16_n326(x) + else + fun_l16_n289(x) + end +end + +def fun_l15_n114(x) + if (x < 1) + fun_l16_n309(x) + else + fun_l16_n125(x) + end +end + +def fun_l15_n115(x) + if (x < 1) + fun_l16_n936(x) + else + fun_l16_n64(x) + end +end + +def fun_l15_n116(x) + if (x < 1) + fun_l16_n942(x) + else + fun_l16_n737(x) + end +end + +def fun_l15_n117(x) + if (x < 1) + fun_l16_n717(x) + else + fun_l16_n701(x) + end +end + +def fun_l15_n118(x) + if (x < 1) + fun_l16_n789(x) + else + fun_l16_n901(x) + end +end + +def fun_l15_n119(x) + if (x < 1) + fun_l16_n49(x) + else + fun_l16_n610(x) + end +end + +def fun_l15_n120(x) + if (x < 1) + fun_l16_n578(x) + else + fun_l16_n372(x) + end +end + +def fun_l15_n121(x) + if (x < 1) + fun_l16_n262(x) + else + fun_l16_n441(x) + end +end + +def fun_l15_n122(x) + if (x < 1) + fun_l16_n29(x) + else + fun_l16_n837(x) + end +end + +def fun_l15_n123(x) + if (x < 1) + fun_l16_n796(x) + else + fun_l16_n771(x) + end +end + +def fun_l15_n124(x) + if (x < 1) + fun_l16_n354(x) + else + fun_l16_n818(x) + end +end + +def fun_l15_n125(x) + if (x < 1) + fun_l16_n971(x) + else + fun_l16_n305(x) + end +end + +def fun_l15_n126(x) + if (x < 1) + fun_l16_n435(x) + else + fun_l16_n307(x) + end +end + +def fun_l15_n127(x) + if (x < 1) + fun_l16_n809(x) + else + fun_l16_n884(x) + end +end + +def fun_l15_n128(x) + if (x < 1) + fun_l16_n794(x) + else + fun_l16_n480(x) + end +end + +def fun_l15_n129(x) + if (x < 1) + fun_l16_n797(x) + else + fun_l16_n193(x) + end +end + +def fun_l15_n130(x) + if (x < 1) + fun_l16_n415(x) + else + fun_l16_n255(x) + end +end + +def fun_l15_n131(x) + if (x < 1) + fun_l16_n736(x) + else + fun_l16_n904(x) + end +end + +def fun_l15_n132(x) + if (x < 1) + fun_l16_n753(x) + else + fun_l16_n408(x) + end +end + +def fun_l15_n133(x) + if (x < 1) + fun_l16_n61(x) + else + fun_l16_n231(x) + end +end + +def fun_l15_n134(x) + if (x < 1) + fun_l16_n541(x) + else + fun_l16_n93(x) + end +end + +def fun_l15_n135(x) + if (x < 1) + fun_l16_n617(x) + else + fun_l16_n765(x) + end +end + +def fun_l15_n136(x) + if (x < 1) + fun_l16_n749(x) + else + fun_l16_n344(x) + end +end + +def fun_l15_n137(x) + if (x < 1) + fun_l16_n431(x) + else + fun_l16_n354(x) + end +end + +def fun_l15_n138(x) + if (x < 1) + fun_l16_n116(x) + else + fun_l16_n963(x) + end +end + +def fun_l15_n139(x) + if (x < 1) + fun_l16_n500(x) + else + fun_l16_n380(x) + end +end + +def fun_l15_n140(x) + if (x < 1) + fun_l16_n120(x) + else + fun_l16_n953(x) + end +end + +def fun_l15_n141(x) + if (x < 1) + fun_l16_n287(x) + else + fun_l16_n154(x) + end +end + +def fun_l15_n142(x) + if (x < 1) + fun_l16_n347(x) + else + fun_l16_n841(x) + end +end + +def fun_l15_n143(x) + if (x < 1) + fun_l16_n562(x) + else + fun_l16_n674(x) + end +end + +def fun_l15_n144(x) + if (x < 1) + fun_l16_n146(x) + else + fun_l16_n788(x) + end +end + +def fun_l15_n145(x) + if (x < 1) + fun_l16_n463(x) + else + fun_l16_n590(x) + end +end + +def fun_l15_n146(x) + if (x < 1) + fun_l16_n452(x) + else + fun_l16_n732(x) + end +end + +def fun_l15_n147(x) + if (x < 1) + fun_l16_n840(x) + else + fun_l16_n254(x) + end +end + +def fun_l15_n148(x) + if (x < 1) + fun_l16_n224(x) + else + fun_l16_n826(x) + end +end + +def fun_l15_n149(x) + if (x < 1) + fun_l16_n40(x) + else + fun_l16_n267(x) + end +end + +def fun_l15_n150(x) + if (x < 1) + fun_l16_n160(x) + else + fun_l16_n745(x) + end +end + +def fun_l15_n151(x) + if (x < 1) + fun_l16_n926(x) + else + fun_l16_n567(x) + end +end + +def fun_l15_n152(x) + if (x < 1) + fun_l16_n392(x) + else + fun_l16_n487(x) + end +end + +def fun_l15_n153(x) + if (x < 1) + fun_l16_n603(x) + else + fun_l16_n549(x) + end +end + +def fun_l15_n154(x) + if (x < 1) + fun_l16_n993(x) + else + fun_l16_n451(x) + end +end + +def fun_l15_n155(x) + if (x < 1) + fun_l16_n358(x) + else + fun_l16_n52(x) + end +end + +def fun_l15_n156(x) + if (x < 1) + fun_l16_n694(x) + else + fun_l16_n419(x) + end +end + +def fun_l15_n157(x) + if (x < 1) + fun_l16_n138(x) + else + fun_l16_n127(x) + end +end + +def fun_l15_n158(x) + if (x < 1) + fun_l16_n619(x) + else + fun_l16_n328(x) + end +end + +def fun_l15_n159(x) + if (x < 1) + fun_l16_n281(x) + else + fun_l16_n503(x) + end +end + +def fun_l15_n160(x) + if (x < 1) + fun_l16_n631(x) + else + fun_l16_n69(x) + end +end + +def fun_l15_n161(x) + if (x < 1) + fun_l16_n41(x) + else + fun_l16_n734(x) + end +end + +def fun_l15_n162(x) + if (x < 1) + fun_l16_n809(x) + else + fun_l16_n303(x) + end +end + +def fun_l15_n163(x) + if (x < 1) + fun_l16_n851(x) + else + fun_l16_n420(x) + end +end + +def fun_l15_n164(x) + if (x < 1) + fun_l16_n534(x) + else + fun_l16_n686(x) + end +end + +def fun_l15_n165(x) + if (x < 1) + fun_l16_n639(x) + else + fun_l16_n155(x) + end +end + +def fun_l15_n166(x) + if (x < 1) + fun_l16_n196(x) + else + fun_l16_n478(x) + end +end + +def fun_l15_n167(x) + if (x < 1) + fun_l16_n926(x) + else + fun_l16_n506(x) + end +end + +def fun_l15_n168(x) + if (x < 1) + fun_l16_n74(x) + else + fun_l16_n442(x) + end +end + +def fun_l15_n169(x) + if (x < 1) + fun_l16_n122(x) + else + fun_l16_n150(x) + end +end + +def fun_l15_n170(x) + if (x < 1) + fun_l16_n805(x) + else + fun_l16_n46(x) + end +end + +def fun_l15_n171(x) + if (x < 1) + fun_l16_n741(x) + else + fun_l16_n88(x) + end +end + +def fun_l15_n172(x) + if (x < 1) + fun_l16_n749(x) + else + fun_l16_n896(x) + end +end + +def fun_l15_n173(x) + if (x < 1) + fun_l16_n310(x) + else + fun_l16_n517(x) + end +end + +def fun_l15_n174(x) + if (x < 1) + fun_l16_n237(x) + else + fun_l16_n948(x) + end +end + +def fun_l15_n175(x) + if (x < 1) + fun_l16_n402(x) + else + fun_l16_n332(x) + end +end + +def fun_l15_n176(x) + if (x < 1) + fun_l16_n189(x) + else + fun_l16_n223(x) + end +end + +def fun_l15_n177(x) + if (x < 1) + fun_l16_n1(x) + else + fun_l16_n577(x) + end +end + +def fun_l15_n178(x) + if (x < 1) + fun_l16_n738(x) + else + fun_l16_n775(x) + end +end + +def fun_l15_n179(x) + if (x < 1) + fun_l16_n80(x) + else + fun_l16_n652(x) + end +end + +def fun_l15_n180(x) + if (x < 1) + fun_l16_n72(x) + else + fun_l16_n635(x) + end +end + +def fun_l15_n181(x) + if (x < 1) + fun_l16_n721(x) + else + fun_l16_n661(x) + end +end + +def fun_l15_n182(x) + if (x < 1) + fun_l16_n354(x) + else + fun_l16_n681(x) + end +end + +def fun_l15_n183(x) + if (x < 1) + fun_l16_n689(x) + else + fun_l16_n775(x) + end +end + +def fun_l15_n184(x) + if (x < 1) + fun_l16_n923(x) + else + fun_l16_n719(x) + end +end + +def fun_l15_n185(x) + if (x < 1) + fun_l16_n33(x) + else + fun_l16_n98(x) + end +end + +def fun_l15_n186(x) + if (x < 1) + fun_l16_n155(x) + else + fun_l16_n880(x) + end +end + +def fun_l15_n187(x) + if (x < 1) + fun_l16_n625(x) + else + fun_l16_n314(x) + end +end + +def fun_l15_n188(x) + if (x < 1) + fun_l16_n284(x) + else + fun_l16_n229(x) + end +end + +def fun_l15_n189(x) + if (x < 1) + fun_l16_n471(x) + else + fun_l16_n740(x) + end +end + +def fun_l15_n190(x) + if (x < 1) + fun_l16_n102(x) + else + fun_l16_n766(x) + end +end + +def fun_l15_n191(x) + if (x < 1) + fun_l16_n812(x) + else + fun_l16_n94(x) + end +end + +def fun_l15_n192(x) + if (x < 1) + fun_l16_n797(x) + else + fun_l16_n736(x) + end +end + +def fun_l15_n193(x) + if (x < 1) + fun_l16_n976(x) + else + fun_l16_n4(x) + end +end + +def fun_l15_n194(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n612(x) + end +end + +def fun_l15_n195(x) + if (x < 1) + fun_l16_n510(x) + else + fun_l16_n237(x) + end +end + +def fun_l15_n196(x) + if (x < 1) + fun_l16_n116(x) + else + fun_l16_n624(x) + end +end + +def fun_l15_n197(x) + if (x < 1) + fun_l16_n515(x) + else + fun_l16_n979(x) + end +end + +def fun_l15_n198(x) + if (x < 1) + fun_l16_n700(x) + else + fun_l16_n284(x) + end +end + +def fun_l15_n199(x) + if (x < 1) + fun_l16_n226(x) + else + fun_l16_n32(x) + end +end + +def fun_l15_n200(x) + if (x < 1) + fun_l16_n453(x) + else + fun_l16_n959(x) + end +end + +def fun_l15_n201(x) + if (x < 1) + fun_l16_n132(x) + else + fun_l16_n323(x) + end +end + +def fun_l15_n202(x) + if (x < 1) + fun_l16_n539(x) + else + fun_l16_n670(x) + end +end + +def fun_l15_n203(x) + if (x < 1) + fun_l16_n786(x) + else + fun_l16_n633(x) + end +end + +def fun_l15_n204(x) + if (x < 1) + fun_l16_n498(x) + else + fun_l16_n520(x) + end +end + +def fun_l15_n205(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n573(x) + end +end + +def fun_l15_n206(x) + if (x < 1) + fun_l16_n746(x) + else + fun_l16_n562(x) + end +end + +def fun_l15_n207(x) + if (x < 1) + fun_l16_n500(x) + else + fun_l16_n951(x) + end +end + +def fun_l15_n208(x) + if (x < 1) + fun_l16_n331(x) + else + fun_l16_n596(x) + end +end + +def fun_l15_n209(x) + if (x < 1) + fun_l16_n1(x) + else + fun_l16_n69(x) + end +end + +def fun_l15_n210(x) + if (x < 1) + fun_l16_n19(x) + else + fun_l16_n148(x) + end +end + +def fun_l15_n211(x) + if (x < 1) + fun_l16_n770(x) + else + fun_l16_n216(x) + end +end + +def fun_l15_n212(x) + if (x < 1) + fun_l16_n863(x) + else + fun_l16_n319(x) + end +end + +def fun_l15_n213(x) + if (x < 1) + fun_l16_n675(x) + else + fun_l16_n797(x) + end +end + +def fun_l15_n214(x) + if (x < 1) + fun_l16_n392(x) + else + fun_l16_n593(x) + end +end + +def fun_l15_n215(x) + if (x < 1) + fun_l16_n120(x) + else + fun_l16_n232(x) + end +end + +def fun_l15_n216(x) + if (x < 1) + fun_l16_n549(x) + else + fun_l16_n175(x) + end +end + +def fun_l15_n217(x) + if (x < 1) + fun_l16_n784(x) + else + fun_l16_n8(x) + end +end + +def fun_l15_n218(x) + if (x < 1) + fun_l16_n296(x) + else + fun_l16_n454(x) + end +end + +def fun_l15_n219(x) + if (x < 1) + fun_l16_n585(x) + else + fun_l16_n628(x) + end +end + +def fun_l15_n220(x) + if (x < 1) + fun_l16_n375(x) + else + fun_l16_n294(x) + end +end + +def fun_l15_n221(x) + if (x < 1) + fun_l16_n69(x) + else + fun_l16_n771(x) + end +end + +def fun_l15_n222(x) + if (x < 1) + fun_l16_n885(x) + else + fun_l16_n476(x) + end +end + +def fun_l15_n223(x) + if (x < 1) + fun_l16_n929(x) + else + fun_l16_n850(x) + end +end + +def fun_l15_n224(x) + if (x < 1) + fun_l16_n489(x) + else + fun_l16_n234(x) + end +end + +def fun_l15_n225(x) + if (x < 1) + fun_l16_n478(x) + else + fun_l16_n744(x) + end +end + +def fun_l15_n226(x) + if (x < 1) + fun_l16_n714(x) + else + fun_l16_n323(x) + end +end + +def fun_l15_n227(x) + if (x < 1) + fun_l16_n146(x) + else + fun_l16_n937(x) + end +end + +def fun_l15_n228(x) + if (x < 1) + fun_l16_n611(x) + else + fun_l16_n320(x) + end +end + +def fun_l15_n229(x) + if (x < 1) + fun_l16_n184(x) + else + fun_l16_n129(x) + end +end + +def fun_l15_n230(x) + if (x < 1) + fun_l16_n563(x) + else + fun_l16_n581(x) + end +end + +def fun_l15_n231(x) + if (x < 1) + fun_l16_n585(x) + else + fun_l16_n63(x) + end +end + +def fun_l15_n232(x) + if (x < 1) + fun_l16_n895(x) + else + fun_l16_n622(x) + end +end + +def fun_l15_n233(x) + if (x < 1) + fun_l16_n998(x) + else + fun_l16_n95(x) + end +end + +def fun_l15_n234(x) + if (x < 1) + fun_l16_n770(x) + else + fun_l16_n557(x) + end +end + +def fun_l15_n235(x) + if (x < 1) + fun_l16_n418(x) + else + fun_l16_n382(x) + end +end + +def fun_l15_n236(x) + if (x < 1) + fun_l16_n842(x) + else + fun_l16_n543(x) + end +end + +def fun_l15_n237(x) + if (x < 1) + fun_l16_n677(x) + else + fun_l16_n108(x) + end +end + +def fun_l15_n238(x) + if (x < 1) + fun_l16_n557(x) + else + fun_l16_n288(x) + end +end + +def fun_l15_n239(x) + if (x < 1) + fun_l16_n467(x) + else + fun_l16_n661(x) + end +end + +def fun_l15_n240(x) + if (x < 1) + fun_l16_n267(x) + else + fun_l16_n559(x) + end +end + +def fun_l15_n241(x) + if (x < 1) + fun_l16_n655(x) + else + fun_l16_n990(x) + end +end + +def fun_l15_n242(x) + if (x < 1) + fun_l16_n673(x) + else + fun_l16_n390(x) + end +end + +def fun_l15_n243(x) + if (x < 1) + fun_l16_n691(x) + else + fun_l16_n901(x) + end +end + +def fun_l15_n244(x) + if (x < 1) + fun_l16_n490(x) + else + fun_l16_n627(x) + end +end + +def fun_l15_n245(x) + if (x < 1) + fun_l16_n293(x) + else + fun_l16_n569(x) + end +end + +def fun_l15_n246(x) + if (x < 1) + fun_l16_n818(x) + else + fun_l16_n74(x) + end +end + +def fun_l15_n247(x) + if (x < 1) + fun_l16_n141(x) + else + fun_l16_n743(x) + end +end + +def fun_l15_n248(x) + if (x < 1) + fun_l16_n819(x) + else + fun_l16_n141(x) + end +end + +def fun_l15_n249(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n53(x) + end +end + +def fun_l15_n250(x) + if (x < 1) + fun_l16_n694(x) + else + fun_l16_n463(x) + end +end + +def fun_l15_n251(x) + if (x < 1) + fun_l16_n828(x) + else + fun_l16_n739(x) + end +end + +def fun_l15_n252(x) + if (x < 1) + fun_l16_n18(x) + else + fun_l16_n694(x) + end +end + +def fun_l15_n253(x) + if (x < 1) + fun_l16_n668(x) + else + fun_l16_n501(x) + end +end + +def fun_l15_n254(x) + if (x < 1) + fun_l16_n649(x) + else + fun_l16_n397(x) + end +end + +def fun_l15_n255(x) + if (x < 1) + fun_l16_n376(x) + else + fun_l16_n375(x) + end +end + +def fun_l15_n256(x) + if (x < 1) + fun_l16_n451(x) + else + fun_l16_n537(x) + end +end + +def fun_l15_n257(x) + if (x < 1) + fun_l16_n360(x) + else + fun_l16_n330(x) + end +end + +def fun_l15_n258(x) + if (x < 1) + fun_l16_n581(x) + else + fun_l16_n193(x) + end +end + +def fun_l15_n259(x) + if (x < 1) + fun_l16_n738(x) + else + fun_l16_n662(x) + end +end + +def fun_l15_n260(x) + if (x < 1) + fun_l16_n450(x) + else + fun_l16_n942(x) + end +end + +def fun_l15_n261(x) + if (x < 1) + fun_l16_n23(x) + else + fun_l16_n534(x) + end +end + +def fun_l15_n262(x) + if (x < 1) + fun_l16_n364(x) + else + fun_l16_n716(x) + end +end + +def fun_l15_n263(x) + if (x < 1) + fun_l16_n528(x) + else + fun_l16_n185(x) + end +end + +def fun_l15_n264(x) + if (x < 1) + fun_l16_n491(x) + else + fun_l16_n686(x) + end +end + +def fun_l15_n265(x) + if (x < 1) + fun_l16_n242(x) + else + fun_l16_n986(x) + end +end + +def fun_l15_n266(x) + if (x < 1) + fun_l16_n726(x) + else + fun_l16_n88(x) + end +end + +def fun_l15_n267(x) + if (x < 1) + fun_l16_n611(x) + else + fun_l16_n11(x) + end +end + +def fun_l15_n268(x) + if (x < 1) + fun_l16_n993(x) + else + fun_l16_n269(x) + end +end + +def fun_l15_n269(x) + if (x < 1) + fun_l16_n296(x) + else + fun_l16_n8(x) + end +end + +def fun_l15_n270(x) + if (x < 1) + fun_l16_n700(x) + else + fun_l16_n692(x) + end +end + +def fun_l15_n271(x) + if (x < 1) + fun_l16_n902(x) + else + fun_l16_n548(x) + end +end + +def fun_l15_n272(x) + if (x < 1) + fun_l16_n39(x) + else + fun_l16_n635(x) + end +end + +def fun_l15_n273(x) + if (x < 1) + fun_l16_n520(x) + else + fun_l16_n49(x) + end +end + +def fun_l15_n274(x) + if (x < 1) + fun_l16_n24(x) + else + fun_l16_n466(x) + end +end + +def fun_l15_n275(x) + if (x < 1) + fun_l16_n144(x) + else + fun_l16_n555(x) + end +end + +def fun_l15_n276(x) + if (x < 1) + fun_l16_n719(x) + else + fun_l16_n693(x) + end +end + +def fun_l15_n277(x) + if (x < 1) + fun_l16_n687(x) + else + fun_l16_n987(x) + end +end + +def fun_l15_n278(x) + if (x < 1) + fun_l16_n426(x) + else + fun_l16_n179(x) + end +end + +def fun_l15_n279(x) + if (x < 1) + fun_l16_n659(x) + else + fun_l16_n36(x) + end +end + +def fun_l15_n280(x) + if (x < 1) + fun_l16_n460(x) + else + fun_l16_n450(x) + end +end + +def fun_l15_n281(x) + if (x < 1) + fun_l16_n42(x) + else + fun_l16_n230(x) + end +end + +def fun_l15_n282(x) + if (x < 1) + fun_l16_n168(x) + else + fun_l16_n422(x) + end +end + +def fun_l15_n283(x) + if (x < 1) + fun_l16_n305(x) + else + fun_l16_n554(x) + end +end + +def fun_l15_n284(x) + if (x < 1) + fun_l16_n680(x) + else + fun_l16_n147(x) + end +end + +def fun_l15_n285(x) + if (x < 1) + fun_l16_n632(x) + else + fun_l16_n767(x) + end +end + +def fun_l15_n286(x) + if (x < 1) + fun_l16_n735(x) + else + fun_l16_n465(x) + end +end + +def fun_l15_n287(x) + if (x < 1) + fun_l16_n17(x) + else + fun_l16_n638(x) + end +end + +def fun_l15_n288(x) + if (x < 1) + fun_l16_n517(x) + else + fun_l16_n47(x) + end +end + +def fun_l15_n289(x) + if (x < 1) + fun_l16_n101(x) + else + fun_l16_n882(x) + end +end + +def fun_l15_n290(x) + if (x < 1) + fun_l16_n697(x) + else + fun_l16_n963(x) + end +end + +def fun_l15_n291(x) + if (x < 1) + fun_l16_n468(x) + else + fun_l16_n340(x) + end +end + +def fun_l15_n292(x) + if (x < 1) + fun_l16_n817(x) + else + fun_l16_n454(x) + end +end + +def fun_l15_n293(x) + if (x < 1) + fun_l16_n885(x) + else + fun_l16_n733(x) + end +end + +def fun_l15_n294(x) + if (x < 1) + fun_l16_n844(x) + else + fun_l16_n564(x) + end +end + +def fun_l15_n295(x) + if (x < 1) + fun_l16_n667(x) + else + fun_l16_n286(x) + end +end + +def fun_l15_n296(x) + if (x < 1) + fun_l16_n694(x) + else + fun_l16_n660(x) + end +end + +def fun_l15_n297(x) + if (x < 1) + fun_l16_n839(x) + else + fun_l16_n274(x) + end +end + +def fun_l15_n298(x) + if (x < 1) + fun_l16_n385(x) + else + fun_l16_n821(x) + end +end + +def fun_l15_n299(x) + if (x < 1) + fun_l16_n137(x) + else + fun_l16_n548(x) + end +end + +def fun_l15_n300(x) + if (x < 1) + fun_l16_n662(x) + else + fun_l16_n2(x) + end +end + +def fun_l15_n301(x) + if (x < 1) + fun_l16_n998(x) + else + fun_l16_n186(x) + end +end + +def fun_l15_n302(x) + if (x < 1) + fun_l16_n667(x) + else + fun_l16_n454(x) + end +end + +def fun_l15_n303(x) + if (x < 1) + fun_l16_n765(x) + else + fun_l16_n519(x) + end +end + +def fun_l15_n304(x) + if (x < 1) + fun_l16_n936(x) + else + fun_l16_n213(x) + end +end + +def fun_l15_n305(x) + if (x < 1) + fun_l16_n695(x) + else + fun_l16_n545(x) + end +end + +def fun_l15_n306(x) + if (x < 1) + fun_l16_n221(x) + else + fun_l16_n545(x) + end +end + +def fun_l15_n307(x) + if (x < 1) + fun_l16_n555(x) + else + fun_l16_n570(x) + end +end + +def fun_l15_n308(x) + if (x < 1) + fun_l16_n57(x) + else + fun_l16_n91(x) + end +end + +def fun_l15_n309(x) + if (x < 1) + fun_l16_n37(x) + else + fun_l16_n516(x) + end +end + +def fun_l15_n310(x) + if (x < 1) + fun_l16_n661(x) + else + fun_l16_n98(x) + end +end + +def fun_l15_n311(x) + if (x < 1) + fun_l16_n119(x) + else + fun_l16_n613(x) + end +end + +def fun_l15_n312(x) + if (x < 1) + fun_l16_n982(x) + else + fun_l16_n20(x) + end +end + +def fun_l15_n313(x) + if (x < 1) + fun_l16_n241(x) + else + fun_l16_n555(x) + end +end + +def fun_l15_n314(x) + if (x < 1) + fun_l16_n638(x) + else + fun_l16_n854(x) + end +end + +def fun_l15_n315(x) + if (x < 1) + fun_l16_n580(x) + else + fun_l16_n39(x) + end +end + +def fun_l15_n316(x) + if (x < 1) + fun_l16_n705(x) + else + fun_l16_n240(x) + end +end + +def fun_l15_n317(x) + if (x < 1) + fun_l16_n395(x) + else + fun_l16_n114(x) + end +end + +def fun_l15_n318(x) + if (x < 1) + fun_l16_n554(x) + else + fun_l16_n239(x) + end +end + +def fun_l15_n319(x) + if (x < 1) + fun_l16_n108(x) + else + fun_l16_n537(x) + end +end + +def fun_l15_n320(x) + if (x < 1) + fun_l16_n554(x) + else + fun_l16_n902(x) + end +end + +def fun_l15_n321(x) + if (x < 1) + fun_l16_n665(x) + else + fun_l16_n369(x) + end +end + +def fun_l15_n322(x) + if (x < 1) + fun_l16_n4(x) + else + fun_l16_n572(x) + end +end + +def fun_l15_n323(x) + if (x < 1) + fun_l16_n579(x) + else + fun_l16_n182(x) + end +end + +def fun_l15_n324(x) + if (x < 1) + fun_l16_n593(x) + else + fun_l16_n203(x) + end +end + +def fun_l15_n325(x) + if (x < 1) + fun_l16_n678(x) + else + fun_l16_n0(x) + end +end + +def fun_l15_n326(x) + if (x < 1) + fun_l16_n809(x) + else + fun_l16_n833(x) + end +end + +def fun_l15_n327(x) + if (x < 1) + fun_l16_n618(x) + else + fun_l16_n381(x) + end +end + +def fun_l15_n328(x) + if (x < 1) + fun_l16_n133(x) + else + fun_l16_n744(x) + end +end + +def fun_l15_n329(x) + if (x < 1) + fun_l16_n488(x) + else + fun_l16_n88(x) + end +end + +def fun_l15_n330(x) + if (x < 1) + fun_l16_n205(x) + else + fun_l16_n402(x) + end +end + +def fun_l15_n331(x) + if (x < 1) + fun_l16_n515(x) + else + fun_l16_n145(x) + end +end + +def fun_l15_n332(x) + if (x < 1) + fun_l16_n581(x) + else + fun_l16_n607(x) + end +end + +def fun_l15_n333(x) + if (x < 1) + fun_l16_n356(x) + else + fun_l16_n155(x) + end +end + +def fun_l15_n334(x) + if (x < 1) + fun_l16_n936(x) + else + fun_l16_n272(x) + end +end + +def fun_l15_n335(x) + if (x < 1) + fun_l16_n714(x) + else + fun_l16_n245(x) + end +end + +def fun_l15_n336(x) + if (x < 1) + fun_l16_n581(x) + else + fun_l16_n877(x) + end +end + +def fun_l15_n337(x) + if (x < 1) + fun_l16_n558(x) + else + fun_l16_n944(x) + end +end + +def fun_l15_n338(x) + if (x < 1) + fun_l16_n49(x) + else + fun_l16_n501(x) + end +end + +def fun_l15_n339(x) + if (x < 1) + fun_l16_n68(x) + else + fun_l16_n448(x) + end +end + +def fun_l15_n340(x) + if (x < 1) + fun_l16_n249(x) + else + fun_l16_n210(x) + end +end + +def fun_l15_n341(x) + if (x < 1) + fun_l16_n720(x) + else + fun_l16_n977(x) + end +end + +def fun_l15_n342(x) + if (x < 1) + fun_l16_n771(x) + else + fun_l16_n519(x) + end +end + +def fun_l15_n343(x) + if (x < 1) + fun_l16_n995(x) + else + fun_l16_n759(x) + end +end + +def fun_l15_n344(x) + if (x < 1) + fun_l16_n972(x) + else + fun_l16_n558(x) + end +end + +def fun_l15_n345(x) + if (x < 1) + fun_l16_n184(x) + else + fun_l16_n774(x) + end +end + +def fun_l15_n346(x) + if (x < 1) + fun_l16_n881(x) + else + fun_l16_n858(x) + end +end + +def fun_l15_n347(x) + if (x < 1) + fun_l16_n921(x) + else + fun_l16_n640(x) + end +end + +def fun_l15_n348(x) + if (x < 1) + fun_l16_n840(x) + else + fun_l16_n366(x) + end +end + +def fun_l15_n349(x) + if (x < 1) + fun_l16_n835(x) + else + fun_l16_n701(x) + end +end + +def fun_l15_n350(x) + if (x < 1) + fun_l16_n304(x) + else + fun_l16_n144(x) + end +end + +def fun_l15_n351(x) + if (x < 1) + fun_l16_n867(x) + else + fun_l16_n247(x) + end +end + +def fun_l15_n352(x) + if (x < 1) + fun_l16_n595(x) + else + fun_l16_n676(x) + end +end + +def fun_l15_n353(x) + if (x < 1) + fun_l16_n125(x) + else + fun_l16_n99(x) + end +end + +def fun_l15_n354(x) + if (x < 1) + fun_l16_n659(x) + else + fun_l16_n559(x) + end +end + +def fun_l15_n355(x) + if (x < 1) + fun_l16_n405(x) + else + fun_l16_n182(x) + end +end + +def fun_l15_n356(x) + if (x < 1) + fun_l16_n347(x) + else + fun_l16_n482(x) + end +end + +def fun_l15_n357(x) + if (x < 1) + fun_l16_n742(x) + else + fun_l16_n531(x) + end +end + +def fun_l15_n358(x) + if (x < 1) + fun_l16_n954(x) + else + fun_l16_n908(x) + end +end + +def fun_l15_n359(x) + if (x < 1) + fun_l16_n670(x) + else + fun_l16_n401(x) + end +end + +def fun_l15_n360(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n802(x) + end +end + +def fun_l15_n361(x) + if (x < 1) + fun_l16_n12(x) + else + fun_l16_n985(x) + end +end + +def fun_l15_n362(x) + if (x < 1) + fun_l16_n644(x) + else + fun_l16_n40(x) + end +end + +def fun_l15_n363(x) + if (x < 1) + fun_l16_n491(x) + else + fun_l16_n255(x) + end +end + +def fun_l15_n364(x) + if (x < 1) + fun_l16_n14(x) + else + fun_l16_n433(x) + end +end + +def fun_l15_n365(x) + if (x < 1) + fun_l16_n652(x) + else + fun_l16_n418(x) + end +end + +def fun_l15_n366(x) + if (x < 1) + fun_l16_n815(x) + else + fun_l16_n325(x) + end +end + +def fun_l15_n367(x) + if (x < 1) + fun_l16_n623(x) + else + fun_l16_n34(x) + end +end + +def fun_l15_n368(x) + if (x < 1) + fun_l16_n596(x) + else + fun_l16_n382(x) + end +end + +def fun_l15_n369(x) + if (x < 1) + fun_l16_n144(x) + else + fun_l16_n18(x) + end +end + +def fun_l15_n370(x) + if (x < 1) + fun_l16_n37(x) + else + fun_l16_n626(x) + end +end + +def fun_l15_n371(x) + if (x < 1) + fun_l16_n275(x) + else + fun_l16_n343(x) + end +end + +def fun_l15_n372(x) + if (x < 1) + fun_l16_n951(x) + else + fun_l16_n93(x) + end +end + +def fun_l15_n373(x) + if (x < 1) + fun_l16_n893(x) + else + fun_l16_n137(x) + end +end + +def fun_l15_n374(x) + if (x < 1) + fun_l16_n32(x) + else + fun_l16_n663(x) + end +end + +def fun_l15_n375(x) + if (x < 1) + fun_l16_n888(x) + else + fun_l16_n708(x) + end +end + +def fun_l15_n376(x) + if (x < 1) + fun_l16_n745(x) + else + fun_l16_n275(x) + end +end + +def fun_l15_n377(x) + if (x < 1) + fun_l16_n957(x) + else + fun_l16_n766(x) + end +end + +def fun_l15_n378(x) + if (x < 1) + fun_l16_n242(x) + else + fun_l16_n309(x) + end +end + +def fun_l15_n379(x) + if (x < 1) + fun_l16_n855(x) + else + fun_l16_n289(x) + end +end + +def fun_l15_n380(x) + if (x < 1) + fun_l16_n511(x) + else + fun_l16_n261(x) + end +end + +def fun_l15_n381(x) + if (x < 1) + fun_l16_n867(x) + else + fun_l16_n169(x) + end +end + +def fun_l15_n382(x) + if (x < 1) + fun_l16_n646(x) + else + fun_l16_n821(x) + end +end + +def fun_l15_n383(x) + if (x < 1) + fun_l16_n181(x) + else + fun_l16_n798(x) + end +end + +def fun_l15_n384(x) + if (x < 1) + fun_l16_n290(x) + else + fun_l16_n756(x) + end +end + +def fun_l15_n385(x) + if (x < 1) + fun_l16_n896(x) + else + fun_l16_n14(x) + end +end + +def fun_l15_n386(x) + if (x < 1) + fun_l16_n602(x) + else + fun_l16_n817(x) + end +end + +def fun_l15_n387(x) + if (x < 1) + fun_l16_n908(x) + else + fun_l16_n773(x) + end +end + +def fun_l15_n388(x) + if (x < 1) + fun_l16_n708(x) + else + fun_l16_n416(x) + end +end + +def fun_l15_n389(x) + if (x < 1) + fun_l16_n42(x) + else + fun_l16_n325(x) + end +end + +def fun_l15_n390(x) + if (x < 1) + fun_l16_n245(x) + else + fun_l16_n211(x) + end +end + +def fun_l15_n391(x) + if (x < 1) + fun_l16_n674(x) + else + fun_l16_n854(x) + end +end + +def fun_l15_n392(x) + if (x < 1) + fun_l16_n294(x) + else + fun_l16_n299(x) + end +end + +def fun_l15_n393(x) + if (x < 1) + fun_l16_n873(x) + else + fun_l16_n17(x) + end +end + +def fun_l15_n394(x) + if (x < 1) + fun_l16_n375(x) + else + fun_l16_n976(x) + end +end + +def fun_l15_n395(x) + if (x < 1) + fun_l16_n753(x) + else + fun_l16_n362(x) + end +end + +def fun_l15_n396(x) + if (x < 1) + fun_l16_n326(x) + else + fun_l16_n878(x) + end +end + +def fun_l15_n397(x) + if (x < 1) + fun_l16_n118(x) + else + fun_l16_n552(x) + end +end + +def fun_l15_n398(x) + if (x < 1) + fun_l16_n931(x) + else + fun_l16_n552(x) + end +end + +def fun_l15_n399(x) + if (x < 1) + fun_l16_n125(x) + else + fun_l16_n817(x) + end +end + +def fun_l15_n400(x) + if (x < 1) + fun_l16_n747(x) + else + fun_l16_n328(x) + end +end + +def fun_l15_n401(x) + if (x < 1) + fun_l16_n204(x) + else + fun_l16_n644(x) + end +end + +def fun_l15_n402(x) + if (x < 1) + fun_l16_n730(x) + else + fun_l16_n622(x) + end +end + +def fun_l15_n403(x) + if (x < 1) + fun_l16_n718(x) + else + fun_l16_n616(x) + end +end + +def fun_l15_n404(x) + if (x < 1) + fun_l16_n260(x) + else + fun_l16_n96(x) + end +end + +def fun_l15_n405(x) + if (x < 1) + fun_l16_n123(x) + else + fun_l16_n377(x) + end +end + +def fun_l15_n406(x) + if (x < 1) + fun_l16_n425(x) + else + fun_l16_n601(x) + end +end + +def fun_l15_n407(x) + if (x < 1) + fun_l16_n842(x) + else + fun_l16_n936(x) + end +end + +def fun_l15_n408(x) + if (x < 1) + fun_l16_n797(x) + else + fun_l16_n194(x) + end +end + +def fun_l15_n409(x) + if (x < 1) + fun_l16_n930(x) + else + fun_l16_n976(x) + end +end + +def fun_l15_n410(x) + if (x < 1) + fun_l16_n163(x) + else + fun_l16_n703(x) + end +end + +def fun_l15_n411(x) + if (x < 1) + fun_l16_n109(x) + else + fun_l16_n276(x) + end +end + +def fun_l15_n412(x) + if (x < 1) + fun_l16_n37(x) + else + fun_l16_n372(x) + end +end + +def fun_l15_n413(x) + if (x < 1) + fun_l16_n995(x) + else + fun_l16_n762(x) + end +end + +def fun_l15_n414(x) + if (x < 1) + fun_l16_n789(x) + else + fun_l16_n601(x) + end +end + +def fun_l15_n415(x) + if (x < 1) + fun_l16_n699(x) + else + fun_l16_n853(x) + end +end + +def fun_l15_n416(x) + if (x < 1) + fun_l16_n936(x) + else + fun_l16_n478(x) + end +end + +def fun_l15_n417(x) + if (x < 1) + fun_l16_n50(x) + else + fun_l16_n67(x) + end +end + +def fun_l15_n418(x) + if (x < 1) + fun_l16_n563(x) + else + fun_l16_n248(x) + end +end + +def fun_l15_n419(x) + if (x < 1) + fun_l16_n238(x) + else + fun_l16_n188(x) + end +end + +def fun_l15_n420(x) + if (x < 1) + fun_l16_n369(x) + else + fun_l16_n706(x) + end +end + +def fun_l15_n421(x) + if (x < 1) + fun_l16_n641(x) + else + fun_l16_n869(x) + end +end + +def fun_l15_n422(x) + if (x < 1) + fun_l16_n219(x) + else + fun_l16_n333(x) + end +end + +def fun_l15_n423(x) + if (x < 1) + fun_l16_n156(x) + else + fun_l16_n22(x) + end +end + +def fun_l15_n424(x) + if (x < 1) + fun_l16_n443(x) + else + fun_l16_n1(x) + end +end + +def fun_l15_n425(x) + if (x < 1) + fun_l16_n892(x) + else + fun_l16_n937(x) + end +end + +def fun_l15_n426(x) + if (x < 1) + fun_l16_n586(x) + else + fun_l16_n636(x) + end +end + +def fun_l15_n427(x) + if (x < 1) + fun_l16_n519(x) + else + fun_l16_n269(x) + end +end + +def fun_l15_n428(x) + if (x < 1) + fun_l16_n379(x) + else + fun_l16_n994(x) + end +end + +def fun_l15_n429(x) + if (x < 1) + fun_l16_n588(x) + else + fun_l16_n532(x) + end +end + +def fun_l15_n430(x) + if (x < 1) + fun_l16_n584(x) + else + fun_l16_n445(x) + end +end + +def fun_l15_n431(x) + if (x < 1) + fun_l16_n63(x) + else + fun_l16_n678(x) + end +end + +def fun_l15_n432(x) + if (x < 1) + fun_l16_n487(x) + else + fun_l16_n435(x) + end +end + +def fun_l15_n433(x) + if (x < 1) + fun_l16_n673(x) + else + fun_l16_n220(x) + end +end + +def fun_l15_n434(x) + if (x < 1) + fun_l16_n131(x) + else + fun_l16_n751(x) + end +end + +def fun_l15_n435(x) + if (x < 1) + fun_l16_n557(x) + else + fun_l16_n340(x) + end +end + +def fun_l15_n436(x) + if (x < 1) + fun_l16_n511(x) + else + fun_l16_n751(x) + end +end + +def fun_l15_n437(x) + if (x < 1) + fun_l16_n983(x) + else + fun_l16_n632(x) + end +end + +def fun_l15_n438(x) + if (x < 1) + fun_l16_n350(x) + else + fun_l16_n492(x) + end +end + +def fun_l15_n439(x) + if (x < 1) + fun_l16_n994(x) + else + fun_l16_n76(x) + end +end + +def fun_l15_n440(x) + if (x < 1) + fun_l16_n756(x) + else + fun_l16_n177(x) + end +end + +def fun_l15_n441(x) + if (x < 1) + fun_l16_n619(x) + else + fun_l16_n473(x) + end +end + +def fun_l15_n442(x) + if (x < 1) + fun_l16_n667(x) + else + fun_l16_n714(x) + end +end + +def fun_l15_n443(x) + if (x < 1) + fun_l16_n790(x) + else + fun_l16_n848(x) + end +end + +def fun_l15_n444(x) + if (x < 1) + fun_l16_n925(x) + else + fun_l16_n113(x) + end +end + +def fun_l15_n445(x) + if (x < 1) + fun_l16_n990(x) + else + fun_l16_n566(x) + end +end + +def fun_l15_n446(x) + if (x < 1) + fun_l16_n589(x) + else + fun_l16_n881(x) + end +end + +def fun_l15_n447(x) + if (x < 1) + fun_l16_n961(x) + else + fun_l16_n786(x) + end +end + +def fun_l15_n448(x) + if (x < 1) + fun_l16_n928(x) + else + fun_l16_n631(x) + end +end + +def fun_l15_n449(x) + if (x < 1) + fun_l16_n317(x) + else + fun_l16_n980(x) + end +end + +def fun_l15_n450(x) + if (x < 1) + fun_l16_n276(x) + else + fun_l16_n941(x) + end +end + +def fun_l15_n451(x) + if (x < 1) + fun_l16_n552(x) + else + fun_l16_n545(x) + end +end + +def fun_l15_n452(x) + if (x < 1) + fun_l16_n334(x) + else + fun_l16_n340(x) + end +end + +def fun_l15_n453(x) + if (x < 1) + fun_l16_n800(x) + else + fun_l16_n548(x) + end +end + +def fun_l15_n454(x) + if (x < 1) + fun_l16_n676(x) + else + fun_l16_n742(x) + end +end + +def fun_l15_n455(x) + if (x < 1) + fun_l16_n722(x) + else + fun_l16_n446(x) + end +end + +def fun_l15_n456(x) + if (x < 1) + fun_l16_n570(x) + else + fun_l16_n203(x) + end +end + +def fun_l15_n457(x) + if (x < 1) + fun_l16_n425(x) + else + fun_l16_n401(x) + end +end + +def fun_l15_n458(x) + if (x < 1) + fun_l16_n3(x) + else + fun_l16_n483(x) + end +end + +def fun_l15_n459(x) + if (x < 1) + fun_l16_n450(x) + else + fun_l16_n468(x) + end +end + +def fun_l15_n460(x) + if (x < 1) + fun_l16_n447(x) + else + fun_l16_n758(x) + end +end + +def fun_l15_n461(x) + if (x < 1) + fun_l16_n531(x) + else + fun_l16_n268(x) + end +end + +def fun_l15_n462(x) + if (x < 1) + fun_l16_n628(x) + else + fun_l16_n142(x) + end +end + +def fun_l15_n463(x) + if (x < 1) + fun_l16_n823(x) + else + fun_l16_n97(x) + end +end + +def fun_l15_n464(x) + if (x < 1) + fun_l16_n807(x) + else + fun_l16_n231(x) + end +end + +def fun_l15_n465(x) + if (x < 1) + fun_l16_n113(x) + else + fun_l16_n438(x) + end +end + +def fun_l15_n466(x) + if (x < 1) + fun_l16_n234(x) + else + fun_l16_n369(x) + end +end + +def fun_l15_n467(x) + if (x < 1) + fun_l16_n242(x) + else + fun_l16_n121(x) + end +end + +def fun_l15_n468(x) + if (x < 1) + fun_l16_n38(x) + else + fun_l16_n223(x) + end +end + +def fun_l15_n469(x) + if (x < 1) + fun_l16_n618(x) + else + fun_l16_n550(x) + end +end + +def fun_l15_n470(x) + if (x < 1) + fun_l16_n318(x) + else + fun_l16_n182(x) + end +end + +def fun_l15_n471(x) + if (x < 1) + fun_l16_n782(x) + else + fun_l16_n876(x) + end +end + +def fun_l15_n472(x) + if (x < 1) + fun_l16_n995(x) + else + fun_l16_n4(x) + end +end + +def fun_l15_n473(x) + if (x < 1) + fun_l16_n425(x) + else + fun_l16_n891(x) + end +end + +def fun_l15_n474(x) + if (x < 1) + fun_l16_n263(x) + else + fun_l16_n278(x) + end +end + +def fun_l15_n475(x) + if (x < 1) + fun_l16_n116(x) + else + fun_l16_n62(x) + end +end + +def fun_l15_n476(x) + if (x < 1) + fun_l16_n855(x) + else + fun_l16_n153(x) + end +end + +def fun_l15_n477(x) + if (x < 1) + fun_l16_n979(x) + else + fun_l16_n957(x) + end +end + +def fun_l15_n478(x) + if (x < 1) + fun_l16_n671(x) + else + fun_l16_n694(x) + end +end + +def fun_l15_n479(x) + if (x < 1) + fun_l16_n479(x) + else + fun_l16_n400(x) + end +end + +def fun_l15_n480(x) + if (x < 1) + fun_l16_n740(x) + else + fun_l16_n940(x) + end +end + +def fun_l15_n481(x) + if (x < 1) + fun_l16_n270(x) + else + fun_l16_n802(x) + end +end + +def fun_l15_n482(x) + if (x < 1) + fun_l16_n489(x) + else + fun_l16_n402(x) + end +end + +def fun_l15_n483(x) + if (x < 1) + fun_l16_n505(x) + else + fun_l16_n97(x) + end +end + +def fun_l15_n484(x) + if (x < 1) + fun_l16_n64(x) + else + fun_l16_n748(x) + end +end + +def fun_l15_n485(x) + if (x < 1) + fun_l16_n7(x) + else + fun_l16_n627(x) + end +end + +def fun_l15_n486(x) + if (x < 1) + fun_l16_n302(x) + else + fun_l16_n331(x) + end +end + +def fun_l15_n487(x) + if (x < 1) + fun_l16_n771(x) + else + fun_l16_n895(x) + end +end + +def fun_l15_n488(x) + if (x < 1) + fun_l16_n306(x) + else + fun_l16_n740(x) + end +end + +def fun_l15_n489(x) + if (x < 1) + fun_l16_n722(x) + else + fun_l16_n848(x) + end +end + +def fun_l15_n490(x) + if (x < 1) + fun_l16_n764(x) + else + fun_l16_n851(x) + end +end + +def fun_l15_n491(x) + if (x < 1) + fun_l16_n357(x) + else + fun_l16_n117(x) + end +end + +def fun_l15_n492(x) + if (x < 1) + fun_l16_n483(x) + else + fun_l16_n187(x) + end +end + +def fun_l15_n493(x) + if (x < 1) + fun_l16_n695(x) + else + fun_l16_n727(x) + end +end + +def fun_l15_n494(x) + if (x < 1) + fun_l16_n460(x) + else + fun_l16_n154(x) + end +end + +def fun_l15_n495(x) + if (x < 1) + fun_l16_n130(x) + else + fun_l16_n999(x) + end +end + +def fun_l15_n496(x) + if (x < 1) + fun_l16_n963(x) + else + fun_l16_n746(x) + end +end + +def fun_l15_n497(x) + if (x < 1) + fun_l16_n630(x) + else + fun_l16_n852(x) + end +end + +def fun_l15_n498(x) + if (x < 1) + fun_l16_n847(x) + else + fun_l16_n836(x) + end +end + +def fun_l15_n499(x) + if (x < 1) + fun_l16_n100(x) + else + fun_l16_n40(x) + end +end + +def fun_l15_n500(x) + if (x < 1) + fun_l16_n246(x) + else + fun_l16_n442(x) + end +end + +def fun_l15_n501(x) + if (x < 1) + fun_l16_n355(x) + else + fun_l16_n405(x) + end +end + +def fun_l15_n502(x) + if (x < 1) + fun_l16_n857(x) + else + fun_l16_n652(x) + end +end + +def fun_l15_n503(x) + if (x < 1) + fun_l16_n612(x) + else + fun_l16_n779(x) + end +end + +def fun_l15_n504(x) + if (x < 1) + fun_l16_n836(x) + else + fun_l16_n625(x) + end +end + +def fun_l15_n505(x) + if (x < 1) + fun_l16_n872(x) + else + fun_l16_n905(x) + end +end + +def fun_l15_n506(x) + if (x < 1) + fun_l16_n953(x) + else + fun_l16_n955(x) + end +end + +def fun_l15_n507(x) + if (x < 1) + fun_l16_n678(x) + else + fun_l16_n663(x) + end +end + +def fun_l15_n508(x) + if (x < 1) + fun_l16_n848(x) + else + fun_l16_n438(x) + end +end + +def fun_l15_n509(x) + if (x < 1) + fun_l16_n558(x) + else + fun_l16_n430(x) + end +end + +def fun_l15_n510(x) + if (x < 1) + fun_l16_n424(x) + else + fun_l16_n473(x) + end +end + +def fun_l15_n511(x) + if (x < 1) + fun_l16_n897(x) + else + fun_l16_n359(x) + end +end + +def fun_l15_n512(x) + if (x < 1) + fun_l16_n229(x) + else + fun_l16_n205(x) + end +end + +def fun_l15_n513(x) + if (x < 1) + fun_l16_n553(x) + else + fun_l16_n438(x) + end +end + +def fun_l15_n514(x) + if (x < 1) + fun_l16_n300(x) + else + fun_l16_n588(x) + end +end + +def fun_l15_n515(x) + if (x < 1) + fun_l16_n819(x) + else + fun_l16_n467(x) + end +end + +def fun_l15_n516(x) + if (x < 1) + fun_l16_n767(x) + else + fun_l16_n786(x) + end +end + +def fun_l15_n517(x) + if (x < 1) + fun_l16_n50(x) + else + fun_l16_n309(x) + end +end + +def fun_l15_n518(x) + if (x < 1) + fun_l16_n671(x) + else + fun_l16_n635(x) + end +end + +def fun_l15_n519(x) + if (x < 1) + fun_l16_n935(x) + else + fun_l16_n497(x) + end +end + +def fun_l15_n520(x) + if (x < 1) + fun_l16_n343(x) + else + fun_l16_n175(x) + end +end + +def fun_l15_n521(x) + if (x < 1) + fun_l16_n212(x) + else + fun_l16_n987(x) + end +end + +def fun_l15_n522(x) + if (x < 1) + fun_l16_n780(x) + else + fun_l16_n331(x) + end +end + +def fun_l15_n523(x) + if (x < 1) + fun_l16_n452(x) + else + fun_l16_n393(x) + end +end + +def fun_l15_n524(x) + if (x < 1) + fun_l16_n823(x) + else + fun_l16_n212(x) + end +end + +def fun_l15_n525(x) + if (x < 1) + fun_l16_n516(x) + else + fun_l16_n906(x) + end +end + +def fun_l15_n526(x) + if (x < 1) + fun_l16_n590(x) + else + fun_l16_n278(x) + end +end + +def fun_l15_n527(x) + if (x < 1) + fun_l16_n392(x) + else + fun_l16_n714(x) + end +end + +def fun_l15_n528(x) + if (x < 1) + fun_l16_n729(x) + else + fun_l16_n751(x) + end +end + +def fun_l15_n529(x) + if (x < 1) + fun_l16_n863(x) + else + fun_l16_n478(x) + end +end + +def fun_l15_n530(x) + if (x < 1) + fun_l16_n472(x) + else + fun_l16_n672(x) + end +end + +def fun_l15_n531(x) + if (x < 1) + fun_l16_n811(x) + else + fun_l16_n201(x) + end +end + +def fun_l15_n532(x) + if (x < 1) + fun_l16_n558(x) + else + fun_l16_n602(x) + end +end + +def fun_l15_n533(x) + if (x < 1) + fun_l16_n788(x) + else + fun_l16_n175(x) + end +end + +def fun_l15_n534(x) + if (x < 1) + fun_l16_n497(x) + else + fun_l16_n807(x) + end +end + +def fun_l15_n535(x) + if (x < 1) + fun_l16_n712(x) + else + fun_l16_n870(x) + end +end + +def fun_l15_n536(x) + if (x < 1) + fun_l16_n699(x) + else + fun_l16_n879(x) + end +end + +def fun_l15_n537(x) + if (x < 1) + fun_l16_n215(x) + else + fun_l16_n807(x) + end +end + +def fun_l15_n538(x) + if (x < 1) + fun_l16_n569(x) + else + fun_l16_n385(x) + end +end + +def fun_l15_n539(x) + if (x < 1) + fun_l16_n807(x) + else + fun_l16_n699(x) + end +end + +def fun_l15_n540(x) + if (x < 1) + fun_l16_n982(x) + else + fun_l16_n436(x) + end +end + +def fun_l15_n541(x) + if (x < 1) + fun_l16_n852(x) + else + fun_l16_n800(x) + end +end + +def fun_l15_n542(x) + if (x < 1) + fun_l16_n401(x) + else + fun_l16_n478(x) + end +end + +def fun_l15_n543(x) + if (x < 1) + fun_l16_n373(x) + else + fun_l16_n465(x) + end +end + +def fun_l15_n544(x) + if (x < 1) + fun_l16_n299(x) + else + fun_l16_n337(x) + end +end + +def fun_l15_n545(x) + if (x < 1) + fun_l16_n931(x) + else + fun_l16_n68(x) + end +end + +def fun_l15_n546(x) + if (x < 1) + fun_l16_n87(x) + else + fun_l16_n947(x) + end +end + +def fun_l15_n547(x) + if (x < 1) + fun_l16_n287(x) + else + fun_l16_n530(x) + end +end + +def fun_l15_n548(x) + if (x < 1) + fun_l16_n910(x) + else + fun_l16_n112(x) + end +end + +def fun_l15_n549(x) + if (x < 1) + fun_l16_n878(x) + else + fun_l16_n737(x) + end +end + +def fun_l15_n550(x) + if (x < 1) + fun_l16_n538(x) + else + fun_l16_n634(x) + end +end + +def fun_l15_n551(x) + if (x < 1) + fun_l16_n109(x) + else + fun_l16_n493(x) + end +end + +def fun_l15_n552(x) + if (x < 1) + fun_l16_n631(x) + else + fun_l16_n244(x) + end +end + +def fun_l15_n553(x) + if (x < 1) + fun_l16_n107(x) + else + fun_l16_n718(x) + end +end + +def fun_l15_n554(x) + if (x < 1) + fun_l16_n572(x) + else + fun_l16_n199(x) + end +end + +def fun_l15_n555(x) + if (x < 1) + fun_l16_n109(x) + else + fun_l16_n705(x) + end +end + +def fun_l15_n556(x) + if (x < 1) + fun_l16_n679(x) + else + fun_l16_n999(x) + end +end + +def fun_l15_n557(x) + if (x < 1) + fun_l16_n714(x) + else + fun_l16_n121(x) + end +end + +def fun_l15_n558(x) + if (x < 1) + fun_l16_n408(x) + else + fun_l16_n239(x) + end +end + +def fun_l15_n559(x) + if (x < 1) + fun_l16_n861(x) + else + fun_l16_n83(x) + end +end + +def fun_l15_n560(x) + if (x < 1) + fun_l16_n597(x) + else + fun_l16_n413(x) + end +end + +def fun_l15_n561(x) + if (x < 1) + fun_l16_n485(x) + else + fun_l16_n42(x) + end +end + +def fun_l15_n562(x) + if (x < 1) + fun_l16_n798(x) + else + fun_l16_n340(x) + end +end + +def fun_l15_n563(x) + if (x < 1) + fun_l16_n50(x) + else + fun_l16_n858(x) + end +end + +def fun_l15_n564(x) + if (x < 1) + fun_l16_n92(x) + else + fun_l16_n3(x) + end +end + +def fun_l15_n565(x) + if (x < 1) + fun_l16_n311(x) + else + fun_l16_n953(x) + end +end + +def fun_l15_n566(x) + if (x < 1) + fun_l16_n649(x) + else + fun_l16_n670(x) + end +end + +def fun_l15_n567(x) + if (x < 1) + fun_l16_n598(x) + else + fun_l16_n268(x) + end +end + +def fun_l15_n568(x) + if (x < 1) + fun_l16_n425(x) + else + fun_l16_n821(x) + end +end + +def fun_l15_n569(x) + if (x < 1) + fun_l16_n447(x) + else + fun_l16_n940(x) + end +end + +def fun_l15_n570(x) + if (x < 1) + fun_l16_n755(x) + else + fun_l16_n26(x) + end +end + +def fun_l15_n571(x) + if (x < 1) + fun_l16_n157(x) + else + fun_l16_n582(x) + end +end + +def fun_l15_n572(x) + if (x < 1) + fun_l16_n530(x) + else + fun_l16_n202(x) + end +end + +def fun_l15_n573(x) + if (x < 1) + fun_l16_n95(x) + else + fun_l16_n137(x) + end +end + +def fun_l15_n574(x) + if (x < 1) + fun_l16_n789(x) + else + fun_l16_n531(x) + end +end + +def fun_l15_n575(x) + if (x < 1) + fun_l16_n677(x) + else + fun_l16_n686(x) + end +end + +def fun_l15_n576(x) + if (x < 1) + fun_l16_n253(x) + else + fun_l16_n101(x) + end +end + +def fun_l15_n577(x) + if (x < 1) + fun_l16_n579(x) + else + fun_l16_n250(x) + end +end + +def fun_l15_n578(x) + if (x < 1) + fun_l16_n104(x) + else + fun_l16_n860(x) + end +end + +def fun_l15_n579(x) + if (x < 1) + fun_l16_n415(x) + else + fun_l16_n480(x) + end +end + +def fun_l15_n580(x) + if (x < 1) + fun_l16_n255(x) + else + fun_l16_n123(x) + end +end + +def fun_l15_n581(x) + if (x < 1) + fun_l16_n40(x) + else + fun_l16_n36(x) + end +end + +def fun_l15_n582(x) + if (x < 1) + fun_l16_n612(x) + else + fun_l16_n46(x) + end +end + +def fun_l15_n583(x) + if (x < 1) + fun_l16_n328(x) + else + fun_l16_n638(x) + end +end + +def fun_l15_n584(x) + if (x < 1) + fun_l16_n219(x) + else + fun_l16_n672(x) + end +end + +def fun_l15_n585(x) + if (x < 1) + fun_l16_n67(x) + else + fun_l16_n584(x) + end +end + +def fun_l15_n586(x) + if (x < 1) + fun_l16_n222(x) + else + fun_l16_n366(x) + end +end + +def fun_l15_n587(x) + if (x < 1) + fun_l16_n194(x) + else + fun_l16_n54(x) + end +end + +def fun_l15_n588(x) + if (x < 1) + fun_l16_n742(x) + else + fun_l16_n725(x) + end +end + +def fun_l15_n589(x) + if (x < 1) + fun_l16_n557(x) + else + fun_l16_n688(x) + end +end + +def fun_l15_n590(x) + if (x < 1) + fun_l16_n588(x) + else + fun_l16_n296(x) + end +end + +def fun_l15_n591(x) + if (x < 1) + fun_l16_n756(x) + else + fun_l16_n619(x) + end +end + +def fun_l15_n592(x) + if (x < 1) + fun_l16_n919(x) + else + fun_l16_n607(x) + end +end + +def fun_l15_n593(x) + if (x < 1) + fun_l16_n168(x) + else + fun_l16_n425(x) + end +end + +def fun_l15_n594(x) + if (x < 1) + fun_l16_n641(x) + else + fun_l16_n980(x) + end +end + +def fun_l15_n595(x) + if (x < 1) + fun_l16_n132(x) + else + fun_l16_n120(x) + end +end + +def fun_l15_n596(x) + if (x < 1) + fun_l16_n998(x) + else + fun_l16_n383(x) + end +end + +def fun_l15_n597(x) + if (x < 1) + fun_l16_n987(x) + else + fun_l16_n685(x) + end +end + +def fun_l15_n598(x) + if (x < 1) + fun_l16_n898(x) + else + fun_l16_n53(x) + end +end + +def fun_l15_n599(x) + if (x < 1) + fun_l16_n589(x) + else + fun_l16_n25(x) + end +end + +def fun_l15_n600(x) + if (x < 1) + fun_l16_n841(x) + else + fun_l16_n623(x) + end +end + +def fun_l15_n601(x) + if (x < 1) + fun_l16_n63(x) + else + fun_l16_n515(x) + end +end + +def fun_l15_n602(x) + if (x < 1) + fun_l16_n708(x) + else + fun_l16_n318(x) + end +end + +def fun_l15_n603(x) + if (x < 1) + fun_l16_n679(x) + else + fun_l16_n31(x) + end +end + +def fun_l15_n604(x) + if (x < 1) + fun_l16_n617(x) + else + fun_l16_n20(x) + end +end + +def fun_l15_n605(x) + if (x < 1) + fun_l16_n635(x) + else + fun_l16_n990(x) + end +end + +def fun_l15_n606(x) + if (x < 1) + fun_l16_n174(x) + else + fun_l16_n977(x) + end +end + +def fun_l15_n607(x) + if (x < 1) + fun_l16_n449(x) + else + fun_l16_n658(x) + end +end + +def fun_l15_n608(x) + if (x < 1) + fun_l16_n208(x) + else + fun_l16_n875(x) + end +end + +def fun_l15_n609(x) + if (x < 1) + fun_l16_n665(x) + else + fun_l16_n431(x) + end +end + +def fun_l15_n610(x) + if (x < 1) + fun_l16_n6(x) + else + fun_l16_n78(x) + end +end + +def fun_l15_n611(x) + if (x < 1) + fun_l16_n335(x) + else + fun_l16_n558(x) + end +end + +def fun_l15_n612(x) + if (x < 1) + fun_l16_n259(x) + else + fun_l16_n893(x) + end +end + +def fun_l15_n613(x) + if (x < 1) + fun_l16_n511(x) + else + fun_l16_n519(x) + end +end + +def fun_l15_n614(x) + if (x < 1) + fun_l16_n96(x) + else + fun_l16_n28(x) + end +end + +def fun_l15_n615(x) + if (x < 1) + fun_l16_n166(x) + else + fun_l16_n417(x) + end +end + +def fun_l15_n616(x) + if (x < 1) + fun_l16_n666(x) + else + fun_l16_n932(x) + end +end + +def fun_l15_n617(x) + if (x < 1) + fun_l16_n745(x) + else + fun_l16_n967(x) + end +end + +def fun_l15_n618(x) + if (x < 1) + fun_l16_n5(x) + else + fun_l16_n769(x) + end +end + +def fun_l15_n619(x) + if (x < 1) + fun_l16_n108(x) + else + fun_l16_n658(x) + end +end + +def fun_l15_n620(x) + if (x < 1) + fun_l16_n454(x) + else + fun_l16_n666(x) + end +end + +def fun_l15_n621(x) + if (x < 1) + fun_l16_n756(x) + else + fun_l16_n580(x) + end +end + +def fun_l15_n622(x) + if (x < 1) + fun_l16_n419(x) + else + fun_l16_n450(x) + end +end + +def fun_l15_n623(x) + if (x < 1) + fun_l16_n793(x) + else + fun_l16_n268(x) + end +end + +def fun_l15_n624(x) + if (x < 1) + fun_l16_n78(x) + else + fun_l16_n311(x) + end +end + +def fun_l15_n625(x) + if (x < 1) + fun_l16_n35(x) + else + fun_l16_n378(x) + end +end + +def fun_l15_n626(x) + if (x < 1) + fun_l16_n974(x) + else + fun_l16_n483(x) + end +end + +def fun_l15_n627(x) + if (x < 1) + fun_l16_n67(x) + else + fun_l16_n497(x) + end +end + +def fun_l15_n628(x) + if (x < 1) + fun_l16_n640(x) + else + fun_l16_n32(x) + end +end + +def fun_l15_n629(x) + if (x < 1) + fun_l16_n297(x) + else + fun_l16_n63(x) + end +end + +def fun_l15_n630(x) + if (x < 1) + fun_l16_n546(x) + else + fun_l16_n931(x) + end +end + +def fun_l15_n631(x) + if (x < 1) + fun_l16_n688(x) + else + fun_l16_n542(x) + end +end + +def fun_l15_n632(x) + if (x < 1) + fun_l16_n313(x) + else + fun_l16_n1(x) + end +end + +def fun_l15_n633(x) + if (x < 1) + fun_l16_n743(x) + else + fun_l16_n382(x) + end +end + +def fun_l15_n634(x) + if (x < 1) + fun_l16_n224(x) + else + fun_l16_n311(x) + end +end + +def fun_l15_n635(x) + if (x < 1) + fun_l16_n926(x) + else + fun_l16_n329(x) + end +end + +def fun_l15_n636(x) + if (x < 1) + fun_l16_n735(x) + else + fun_l16_n759(x) + end +end + +def fun_l15_n637(x) + if (x < 1) + fun_l16_n699(x) + else + fun_l16_n27(x) + end +end + +def fun_l15_n638(x) + if (x < 1) + fun_l16_n710(x) + else + fun_l16_n194(x) + end +end + +def fun_l15_n639(x) + if (x < 1) + fun_l16_n245(x) + else + fun_l16_n950(x) + end +end + +def fun_l15_n640(x) + if (x < 1) + fun_l16_n488(x) + else + fun_l16_n357(x) + end +end + +def fun_l15_n641(x) + if (x < 1) + fun_l16_n331(x) + else + fun_l16_n962(x) + end +end + +def fun_l15_n642(x) + if (x < 1) + fun_l16_n144(x) + else + fun_l16_n877(x) + end +end + +def fun_l15_n643(x) + if (x < 1) + fun_l16_n605(x) + else + fun_l16_n733(x) + end +end + +def fun_l15_n644(x) + if (x < 1) + fun_l16_n22(x) + else + fun_l16_n176(x) + end +end + +def fun_l15_n645(x) + if (x < 1) + fun_l16_n934(x) + else + fun_l16_n351(x) + end +end + +def fun_l15_n646(x) + if (x < 1) + fun_l16_n224(x) + else + fun_l16_n308(x) + end +end + +def fun_l15_n647(x) + if (x < 1) + fun_l16_n374(x) + else + fun_l16_n612(x) + end +end + +def fun_l15_n648(x) + if (x < 1) + fun_l16_n105(x) + else + fun_l16_n563(x) + end +end + +def fun_l15_n649(x) + if (x < 1) + fun_l16_n955(x) + else + fun_l16_n63(x) + end +end + +def fun_l15_n650(x) + if (x < 1) + fun_l16_n734(x) + else + fun_l16_n194(x) + end +end + +def fun_l15_n651(x) + if (x < 1) + fun_l16_n237(x) + else + fun_l16_n425(x) + end +end + +def fun_l15_n652(x) + if (x < 1) + fun_l16_n135(x) + else + fun_l16_n217(x) + end +end + +def fun_l15_n653(x) + if (x < 1) + fun_l16_n565(x) + else + fun_l16_n437(x) + end +end + +def fun_l15_n654(x) + if (x < 1) + fun_l16_n471(x) + else + fun_l16_n426(x) + end +end + +def fun_l15_n655(x) + if (x < 1) + fun_l16_n570(x) + else + fun_l16_n64(x) + end +end + +def fun_l15_n656(x) + if (x < 1) + fun_l16_n456(x) + else + fun_l16_n479(x) + end +end + +def fun_l15_n657(x) + if (x < 1) + fun_l16_n446(x) + else + fun_l16_n362(x) + end +end + +def fun_l15_n658(x) + if (x < 1) + fun_l16_n294(x) + else + fun_l16_n485(x) + end +end + +def fun_l15_n659(x) + if (x < 1) + fun_l16_n96(x) + else + fun_l16_n60(x) + end +end + +def fun_l15_n660(x) + if (x < 1) + fun_l16_n436(x) + else + fun_l16_n12(x) + end +end + +def fun_l15_n661(x) + if (x < 1) + fun_l16_n5(x) + else + fun_l16_n452(x) + end +end + +def fun_l15_n662(x) + if (x < 1) + fun_l16_n70(x) + else + fun_l16_n564(x) + end +end + +def fun_l15_n663(x) + if (x < 1) + fun_l16_n92(x) + else + fun_l16_n333(x) + end +end + +def fun_l15_n664(x) + if (x < 1) + fun_l16_n884(x) + else + fun_l16_n381(x) + end +end + +def fun_l15_n665(x) + if (x < 1) + fun_l16_n816(x) + else + fun_l16_n243(x) + end +end + +def fun_l15_n666(x) + if (x < 1) + fun_l16_n680(x) + else + fun_l16_n306(x) + end +end + +def fun_l15_n667(x) + if (x < 1) + fun_l16_n470(x) + else + fun_l16_n559(x) + end +end + +def fun_l15_n668(x) + if (x < 1) + fun_l16_n34(x) + else + fun_l16_n261(x) + end +end + +def fun_l15_n669(x) + if (x < 1) + fun_l16_n644(x) + else + fun_l16_n389(x) + end +end + +def fun_l15_n670(x) + if (x < 1) + fun_l16_n313(x) + else + fun_l16_n575(x) + end +end + +def fun_l15_n671(x) + if (x < 1) + fun_l16_n241(x) + else + fun_l16_n304(x) + end +end + +def fun_l15_n672(x) + if (x < 1) + fun_l16_n280(x) + else + fun_l16_n996(x) + end +end + +def fun_l15_n673(x) + if (x < 1) + fun_l16_n723(x) + else + fun_l16_n42(x) + end +end + +def fun_l15_n674(x) + if (x < 1) + fun_l16_n503(x) + else + fun_l16_n837(x) + end +end + +def fun_l15_n675(x) + if (x < 1) + fun_l16_n105(x) + else + fun_l16_n815(x) + end +end + +def fun_l15_n676(x) + if (x < 1) + fun_l16_n441(x) + else + fun_l16_n313(x) + end +end + +def fun_l15_n677(x) + if (x < 1) + fun_l16_n277(x) + else + fun_l16_n653(x) + end +end + +def fun_l15_n678(x) + if (x < 1) + fun_l16_n105(x) + else + fun_l16_n907(x) + end +end + +def fun_l15_n679(x) + if (x < 1) + fun_l16_n549(x) + else + fun_l16_n956(x) + end +end + +def fun_l15_n680(x) + if (x < 1) + fun_l16_n177(x) + else + fun_l16_n238(x) + end +end + +def fun_l15_n681(x) + if (x < 1) + fun_l16_n931(x) + else + fun_l16_n278(x) + end +end + +def fun_l15_n682(x) + if (x < 1) + fun_l16_n923(x) + else + fun_l16_n924(x) + end +end + +def fun_l15_n683(x) + if (x < 1) + fun_l16_n926(x) + else + fun_l16_n76(x) + end +end + +def fun_l15_n684(x) + if (x < 1) + fun_l16_n828(x) + else + fun_l16_n961(x) + end +end + +def fun_l15_n685(x) + if (x < 1) + fun_l16_n298(x) + else + fun_l16_n95(x) + end +end + +def fun_l15_n686(x) + if (x < 1) + fun_l16_n929(x) + else + fun_l16_n239(x) + end +end + +def fun_l15_n687(x) + if (x < 1) + fun_l16_n488(x) + else + fun_l16_n543(x) + end +end + +def fun_l15_n688(x) + if (x < 1) + fun_l16_n562(x) + else + fun_l16_n879(x) + end +end + +def fun_l15_n689(x) + if (x < 1) + fun_l16_n348(x) + else + fun_l16_n458(x) + end +end + +def fun_l15_n690(x) + if (x < 1) + fun_l16_n431(x) + else + fun_l16_n653(x) + end +end + +def fun_l15_n691(x) + if (x < 1) + fun_l16_n173(x) + else + fun_l16_n600(x) + end +end + +def fun_l15_n692(x) + if (x < 1) + fun_l16_n820(x) + else + fun_l16_n793(x) + end +end + +def fun_l15_n693(x) + if (x < 1) + fun_l16_n611(x) + else + fun_l16_n308(x) + end +end + +def fun_l15_n694(x) + if (x < 1) + fun_l16_n325(x) + else + fun_l16_n791(x) + end +end + +def fun_l15_n695(x) + if (x < 1) + fun_l16_n890(x) + else + fun_l16_n98(x) + end +end + +def fun_l15_n696(x) + if (x < 1) + fun_l16_n803(x) + else + fun_l16_n890(x) + end +end + +def fun_l15_n697(x) + if (x < 1) + fun_l16_n182(x) + else + fun_l16_n229(x) + end +end + +def fun_l15_n698(x) + if (x < 1) + fun_l16_n238(x) + else + fun_l16_n395(x) + end +end + +def fun_l15_n699(x) + if (x < 1) + fun_l16_n349(x) + else + fun_l16_n903(x) + end +end + +def fun_l15_n700(x) + if (x < 1) + fun_l16_n328(x) + else + fun_l16_n664(x) + end +end + +def fun_l15_n701(x) + if (x < 1) + fun_l16_n924(x) + else + fun_l16_n415(x) + end +end + +def fun_l15_n702(x) + if (x < 1) + fun_l16_n504(x) + else + fun_l16_n180(x) + end +end + +def fun_l15_n703(x) + if (x < 1) + fun_l16_n754(x) + else + fun_l16_n580(x) + end +end + +def fun_l15_n704(x) + if (x < 1) + fun_l16_n686(x) + else + fun_l16_n75(x) + end +end + +def fun_l15_n705(x) + if (x < 1) + fun_l16_n295(x) + else + fun_l16_n789(x) + end +end + +def fun_l15_n706(x) + if (x < 1) + fun_l16_n796(x) + else + fun_l16_n628(x) + end +end + +def fun_l15_n707(x) + if (x < 1) + fun_l16_n603(x) + else + fun_l16_n864(x) + end +end + +def fun_l15_n708(x) + if (x < 1) + fun_l16_n420(x) + else + fun_l16_n506(x) + end +end + +def fun_l15_n709(x) + if (x < 1) + fun_l16_n417(x) + else + fun_l16_n677(x) + end +end + +def fun_l15_n710(x) + if (x < 1) + fun_l16_n484(x) + else + fun_l16_n210(x) + end +end + +def fun_l15_n711(x) + if (x < 1) + fun_l16_n127(x) + else + fun_l16_n423(x) + end +end + +def fun_l15_n712(x) + if (x < 1) + fun_l16_n395(x) + else + fun_l16_n75(x) + end +end + +def fun_l15_n713(x) + if (x < 1) + fun_l16_n388(x) + else + fun_l16_n261(x) + end +end + +def fun_l15_n714(x) + if (x < 1) + fun_l16_n508(x) + else + fun_l16_n160(x) + end +end + +def fun_l15_n715(x) + if (x < 1) + fun_l16_n468(x) + else + fun_l16_n784(x) + end +end + +def fun_l15_n716(x) + if (x < 1) + fun_l16_n156(x) + else + fun_l16_n769(x) + end +end + +def fun_l15_n717(x) + if (x < 1) + fun_l16_n219(x) + else + fun_l16_n618(x) + end +end + +def fun_l15_n718(x) + if (x < 1) + fun_l16_n921(x) + else + fun_l16_n83(x) + end +end + +def fun_l15_n719(x) + if (x < 1) + fun_l16_n262(x) + else + fun_l16_n170(x) + end +end + +def fun_l15_n720(x) + if (x < 1) + fun_l16_n420(x) + else + fun_l16_n504(x) + end +end + +def fun_l15_n721(x) + if (x < 1) + fun_l16_n485(x) + else + fun_l16_n782(x) + end +end + +def fun_l15_n722(x) + if (x < 1) + fun_l16_n607(x) + else + fun_l16_n706(x) + end +end + +def fun_l15_n723(x) + if (x < 1) + fun_l16_n116(x) + else + fun_l16_n73(x) + end +end + +def fun_l15_n724(x) + if (x < 1) + fun_l16_n946(x) + else + fun_l16_n694(x) + end +end + +def fun_l15_n725(x) + if (x < 1) + fun_l16_n73(x) + else + fun_l16_n223(x) + end +end + +def fun_l15_n726(x) + if (x < 1) + fun_l16_n54(x) + else + fun_l16_n681(x) + end +end + +def fun_l15_n727(x) + if (x < 1) + fun_l16_n474(x) + else + fun_l16_n339(x) + end +end + +def fun_l15_n728(x) + if (x < 1) + fun_l16_n780(x) + else + fun_l16_n364(x) + end +end + +def fun_l15_n729(x) + if (x < 1) + fun_l16_n537(x) + else + fun_l16_n1(x) + end +end + +def fun_l15_n730(x) + if (x < 1) + fun_l16_n81(x) + else + fun_l16_n591(x) + end +end + +def fun_l15_n731(x) + if (x < 1) + fun_l16_n631(x) + else + fun_l16_n626(x) + end +end + +def fun_l15_n732(x) + if (x < 1) + fun_l16_n904(x) + else + fun_l16_n988(x) + end +end + +def fun_l15_n733(x) + if (x < 1) + fun_l16_n933(x) + else + fun_l16_n761(x) + end +end + +def fun_l15_n734(x) + if (x < 1) + fun_l16_n687(x) + else + fun_l16_n611(x) + end +end + +def fun_l15_n735(x) + if (x < 1) + fun_l16_n197(x) + else + fun_l16_n210(x) + end +end + +def fun_l15_n736(x) + if (x < 1) + fun_l16_n227(x) + else + fun_l16_n82(x) + end +end + +def fun_l15_n737(x) + if (x < 1) + fun_l16_n981(x) + else + fun_l16_n18(x) + end +end + +def fun_l15_n738(x) + if (x < 1) + fun_l16_n673(x) + else + fun_l16_n452(x) + end +end + +def fun_l15_n739(x) + if (x < 1) + fun_l16_n225(x) + else + fun_l16_n555(x) + end +end + +def fun_l15_n740(x) + if (x < 1) + fun_l16_n409(x) + else + fun_l16_n29(x) + end +end + +def fun_l15_n741(x) + if (x < 1) + fun_l16_n550(x) + else + fun_l16_n880(x) + end +end + +def fun_l15_n742(x) + if (x < 1) + fun_l16_n930(x) + else + fun_l16_n280(x) + end +end + +def fun_l15_n743(x) + if (x < 1) + fun_l16_n622(x) + else + fun_l16_n438(x) + end +end + +def fun_l15_n744(x) + if (x < 1) + fun_l16_n874(x) + else + fun_l16_n921(x) + end +end + +def fun_l15_n745(x) + if (x < 1) + fun_l16_n337(x) + else + fun_l16_n879(x) + end +end + +def fun_l15_n746(x) + if (x < 1) + fun_l16_n668(x) + else + fun_l16_n858(x) + end +end + +def fun_l15_n747(x) + if (x < 1) + fun_l16_n588(x) + else + fun_l16_n433(x) + end +end + +def fun_l15_n748(x) + if (x < 1) + fun_l16_n263(x) + else + fun_l16_n389(x) + end +end + +def fun_l15_n749(x) + if (x < 1) + fun_l16_n79(x) + else + fun_l16_n218(x) + end +end + +def fun_l15_n750(x) + if (x < 1) + fun_l16_n586(x) + else + fun_l16_n426(x) + end +end + +def fun_l15_n751(x) + if (x < 1) + fun_l16_n29(x) + else + fun_l16_n183(x) + end +end + +def fun_l15_n752(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n994(x) + end +end + +def fun_l15_n753(x) + if (x < 1) + fun_l16_n176(x) + else + fun_l16_n425(x) + end +end + +def fun_l15_n754(x) + if (x < 1) + fun_l16_n58(x) + else + fun_l16_n980(x) + end +end + +def fun_l15_n755(x) + if (x < 1) + fun_l16_n333(x) + else + fun_l16_n949(x) + end +end + +def fun_l15_n756(x) + if (x < 1) + fun_l16_n846(x) + else + fun_l16_n449(x) + end +end + +def fun_l15_n757(x) + if (x < 1) + fun_l16_n341(x) + else + fun_l16_n200(x) + end +end + +def fun_l15_n758(x) + if (x < 1) + fun_l16_n32(x) + else + fun_l16_n271(x) + end +end + +def fun_l15_n759(x) + if (x < 1) + fun_l16_n654(x) + else + fun_l16_n978(x) + end +end + +def fun_l15_n760(x) + if (x < 1) + fun_l16_n438(x) + else + fun_l16_n426(x) + end +end + +def fun_l15_n761(x) + if (x < 1) + fun_l16_n218(x) + else + fun_l16_n393(x) + end +end + +def fun_l15_n762(x) + if (x < 1) + fun_l16_n873(x) + else + fun_l16_n231(x) + end +end + +def fun_l15_n763(x) + if (x < 1) + fun_l16_n957(x) + else + fun_l16_n801(x) + end +end + +def fun_l15_n764(x) + if (x < 1) + fun_l16_n571(x) + else + fun_l16_n369(x) + end +end + +def fun_l15_n765(x) + if (x < 1) + fun_l16_n806(x) + else + fun_l16_n527(x) + end +end + +def fun_l15_n766(x) + if (x < 1) + fun_l16_n511(x) + else + fun_l16_n911(x) + end +end + +def fun_l15_n767(x) + if (x < 1) + fun_l16_n589(x) + else + fun_l16_n468(x) + end +end + +def fun_l15_n768(x) + if (x < 1) + fun_l16_n846(x) + else + fun_l16_n325(x) + end +end + +def fun_l15_n769(x) + if (x < 1) + fun_l16_n350(x) + else + fun_l16_n268(x) + end +end + +def fun_l15_n770(x) + if (x < 1) + fun_l16_n200(x) + else + fun_l16_n151(x) + end +end + +def fun_l15_n771(x) + if (x < 1) + fun_l16_n246(x) + else + fun_l16_n442(x) + end +end + +def fun_l15_n772(x) + if (x < 1) + fun_l16_n768(x) + else + fun_l16_n303(x) + end +end + +def fun_l15_n773(x) + if (x < 1) + fun_l16_n414(x) + else + fun_l16_n857(x) + end +end + +def fun_l15_n774(x) + if (x < 1) + fun_l16_n654(x) + else + fun_l16_n151(x) + end +end + +def fun_l15_n775(x) + if (x < 1) + fun_l16_n283(x) + else + fun_l16_n565(x) + end +end + +def fun_l15_n776(x) + if (x < 1) + fun_l16_n375(x) + else + fun_l16_n897(x) + end +end + +def fun_l15_n777(x) + if (x < 1) + fun_l16_n711(x) + else + fun_l16_n487(x) + end +end + +def fun_l15_n778(x) + if (x < 1) + fun_l16_n445(x) + else + fun_l16_n99(x) + end +end + +def fun_l15_n779(x) + if (x < 1) + fun_l16_n320(x) + else + fun_l16_n614(x) + end +end + +def fun_l15_n780(x) + if (x < 1) + fun_l16_n330(x) + else + fun_l16_n478(x) + end +end + +def fun_l15_n781(x) + if (x < 1) + fun_l16_n680(x) + else + fun_l16_n882(x) + end +end + +def fun_l15_n782(x) + if (x < 1) + fun_l16_n799(x) + else + fun_l16_n511(x) + end +end + +def fun_l15_n783(x) + if (x < 1) + fun_l16_n630(x) + else + fun_l16_n946(x) + end +end + +def fun_l15_n784(x) + if (x < 1) + fun_l16_n867(x) + else + fun_l16_n4(x) + end +end + +def fun_l15_n785(x) + if (x < 1) + fun_l16_n154(x) + else + fun_l16_n400(x) + end +end + +def fun_l15_n786(x) + if (x < 1) + fun_l16_n166(x) + else + fun_l16_n224(x) + end +end + +def fun_l15_n787(x) + if (x < 1) + fun_l16_n120(x) + else + fun_l16_n518(x) + end +end + +def fun_l15_n788(x) + if (x < 1) + fun_l16_n648(x) + else + fun_l16_n56(x) + end +end + +def fun_l15_n789(x) + if (x < 1) + fun_l16_n965(x) + else + fun_l16_n760(x) + end +end + +def fun_l15_n790(x) + if (x < 1) + fun_l16_n880(x) + else + fun_l16_n809(x) + end +end + +def fun_l15_n791(x) + if (x < 1) + fun_l16_n836(x) + else + fun_l16_n61(x) + end +end + +def fun_l15_n792(x) + if (x < 1) + fun_l16_n874(x) + else + fun_l16_n559(x) + end +end + +def fun_l15_n793(x) + if (x < 1) + fun_l16_n896(x) + else + fun_l16_n72(x) + end +end + +def fun_l15_n794(x) + if (x < 1) + fun_l16_n994(x) + else + fun_l16_n411(x) + end +end + +def fun_l15_n795(x) + if (x < 1) + fun_l16_n289(x) + else + fun_l16_n151(x) + end +end + +def fun_l15_n796(x) + if (x < 1) + fun_l16_n190(x) + else + fun_l16_n693(x) + end +end + +def fun_l15_n797(x) + if (x < 1) + fun_l16_n320(x) + else + fun_l16_n955(x) + end +end + +def fun_l15_n798(x) + if (x < 1) + fun_l16_n572(x) + else + fun_l16_n626(x) + end +end + +def fun_l15_n799(x) + if (x < 1) + fun_l16_n35(x) + else + fun_l16_n838(x) + end +end + +def fun_l15_n800(x) + if (x < 1) + fun_l16_n423(x) + else + fun_l16_n834(x) + end +end + +def fun_l15_n801(x) + if (x < 1) + fun_l16_n964(x) + else + fun_l16_n824(x) + end +end + +def fun_l15_n802(x) + if (x < 1) + fun_l16_n77(x) + else + fun_l16_n62(x) + end +end + +def fun_l15_n803(x) + if (x < 1) + fun_l16_n226(x) + else + fun_l16_n373(x) + end +end + +def fun_l15_n804(x) + if (x < 1) + fun_l16_n832(x) + else + fun_l16_n915(x) + end +end + +def fun_l15_n805(x) + if (x < 1) + fun_l16_n421(x) + else + fun_l16_n621(x) + end +end + +def fun_l15_n806(x) + if (x < 1) + fun_l16_n303(x) + else + fun_l16_n713(x) + end +end + +def fun_l15_n807(x) + if (x < 1) + fun_l16_n393(x) + else + fun_l16_n698(x) + end +end + +def fun_l15_n808(x) + if (x < 1) + fun_l16_n303(x) + else + fun_l16_n341(x) + end +end + +def fun_l15_n809(x) + if (x < 1) + fun_l16_n116(x) + else + fun_l16_n976(x) + end +end + +def fun_l15_n810(x) + if (x < 1) + fun_l16_n873(x) + else + fun_l16_n822(x) + end +end + +def fun_l15_n811(x) + if (x < 1) + fun_l16_n358(x) + else + fun_l16_n334(x) + end +end + +def fun_l15_n812(x) + if (x < 1) + fun_l16_n599(x) + else + fun_l16_n527(x) + end +end + +def fun_l15_n813(x) + if (x < 1) + fun_l16_n842(x) + else + fun_l16_n791(x) + end +end + +def fun_l15_n814(x) + if (x < 1) + fun_l16_n45(x) + else + fun_l16_n280(x) + end +end + +def fun_l15_n815(x) + if (x < 1) + fun_l16_n187(x) + else + fun_l16_n151(x) + end +end + +def fun_l15_n816(x) + if (x < 1) + fun_l16_n8(x) + else + fun_l16_n409(x) + end +end + +def fun_l15_n817(x) + if (x < 1) + fun_l16_n670(x) + else + fun_l16_n569(x) + end +end + +def fun_l15_n818(x) + if (x < 1) + fun_l16_n344(x) + else + fun_l16_n618(x) + end +end + +def fun_l15_n819(x) + if (x < 1) + fun_l16_n659(x) + else + fun_l16_n321(x) + end +end + +def fun_l15_n820(x) + if (x < 1) + fun_l16_n890(x) + else + fun_l16_n911(x) + end +end + +def fun_l15_n821(x) + if (x < 1) + fun_l16_n360(x) + else + fun_l16_n742(x) + end +end + +def fun_l15_n822(x) + if (x < 1) + fun_l16_n166(x) + else + fun_l16_n803(x) + end +end + +def fun_l15_n823(x) + if (x < 1) + fun_l16_n765(x) + else + fun_l16_n958(x) + end +end + +def fun_l15_n824(x) + if (x < 1) + fun_l16_n439(x) + else + fun_l16_n931(x) + end +end + +def fun_l15_n825(x) + if (x < 1) + fun_l16_n740(x) + else + fun_l16_n901(x) + end +end + +def fun_l15_n826(x) + if (x < 1) + fun_l16_n223(x) + else + fun_l16_n878(x) + end +end + +def fun_l15_n827(x) + if (x < 1) + fun_l16_n969(x) + else + fun_l16_n553(x) + end +end + +def fun_l15_n828(x) + if (x < 1) + fun_l16_n42(x) + else + fun_l16_n915(x) + end +end + +def fun_l15_n829(x) + if (x < 1) + fun_l16_n386(x) + else + fun_l16_n430(x) + end +end + +def fun_l15_n830(x) + if (x < 1) + fun_l16_n164(x) + else + fun_l16_n337(x) + end +end + +def fun_l15_n831(x) + if (x < 1) + fun_l16_n465(x) + else + fun_l16_n898(x) + end +end + +def fun_l15_n832(x) + if (x < 1) + fun_l16_n145(x) + else + fun_l16_n688(x) + end +end + +def fun_l15_n833(x) + if (x < 1) + fun_l16_n238(x) + else + fun_l16_n624(x) + end +end + +def fun_l15_n834(x) + if (x < 1) + fun_l16_n973(x) + else + fun_l16_n507(x) + end +end + +def fun_l15_n835(x) + if (x < 1) + fun_l16_n24(x) + else + fun_l16_n607(x) + end +end + +def fun_l15_n836(x) + if (x < 1) + fun_l16_n307(x) + else + fun_l16_n265(x) + end +end + +def fun_l15_n837(x) + if (x < 1) + fun_l16_n91(x) + else + fun_l16_n543(x) + end +end + +def fun_l15_n838(x) + if (x < 1) + fun_l16_n544(x) + else + fun_l16_n397(x) + end +end + +def fun_l15_n839(x) + if (x < 1) + fun_l16_n121(x) + else + fun_l16_n503(x) + end +end + +def fun_l15_n840(x) + if (x < 1) + fun_l16_n806(x) + else + fun_l16_n831(x) + end +end + +def fun_l15_n841(x) + if (x < 1) + fun_l16_n629(x) + else + fun_l16_n553(x) + end +end + +def fun_l15_n842(x) + if (x < 1) + fun_l16_n674(x) + else + fun_l16_n945(x) + end +end + +def fun_l15_n843(x) + if (x < 1) + fun_l16_n409(x) + else + fun_l16_n469(x) + end +end + +def fun_l15_n844(x) + if (x < 1) + fun_l16_n779(x) + else + fun_l16_n168(x) + end +end + +def fun_l15_n845(x) + if (x < 1) + fun_l16_n258(x) + else + fun_l16_n501(x) + end +end + +def fun_l15_n846(x) + if (x < 1) + fun_l16_n408(x) + else + fun_l16_n211(x) + end +end + +def fun_l15_n847(x) + if (x < 1) + fun_l16_n844(x) + else + fun_l16_n458(x) + end +end + +def fun_l15_n848(x) + if (x < 1) + fun_l16_n565(x) + else + fun_l16_n177(x) + end +end + +def fun_l15_n849(x) + if (x < 1) + fun_l16_n111(x) + else + fun_l16_n995(x) + end +end + +def fun_l15_n850(x) + if (x < 1) + fun_l16_n883(x) + else + fun_l16_n776(x) + end +end + +def fun_l15_n851(x) + if (x < 1) + fun_l16_n821(x) + else + fun_l16_n352(x) + end +end + +def fun_l15_n852(x) + if (x < 1) + fun_l16_n977(x) + else + fun_l16_n520(x) + end +end + +def fun_l15_n853(x) + if (x < 1) + fun_l16_n602(x) + else + fun_l16_n88(x) + end +end + +def fun_l15_n854(x) + if (x < 1) + fun_l16_n819(x) + else + fun_l16_n177(x) + end +end + +def fun_l15_n855(x) + if (x < 1) + fun_l16_n878(x) + else + fun_l16_n648(x) + end +end + +def fun_l15_n856(x) + if (x < 1) + fun_l16_n69(x) + else + fun_l16_n134(x) + end +end + +def fun_l15_n857(x) + if (x < 1) + fun_l16_n728(x) + else + fun_l16_n282(x) + end +end + +def fun_l15_n858(x) + if (x < 1) + fun_l16_n152(x) + else + fun_l16_n725(x) + end +end + +def fun_l15_n859(x) + if (x < 1) + fun_l16_n140(x) + else + fun_l16_n12(x) + end +end + +def fun_l15_n860(x) + if (x < 1) + fun_l16_n691(x) + else + fun_l16_n159(x) + end +end + +def fun_l15_n861(x) + if (x < 1) + fun_l16_n366(x) + else + fun_l16_n97(x) + end +end + +def fun_l15_n862(x) + if (x < 1) + fun_l16_n812(x) + else + fun_l16_n178(x) + end +end + +def fun_l15_n863(x) + if (x < 1) + fun_l16_n491(x) + else + fun_l16_n167(x) + end +end + +def fun_l15_n864(x) + if (x < 1) + fun_l16_n280(x) + else + fun_l16_n463(x) + end +end + +def fun_l15_n865(x) + if (x < 1) + fun_l16_n405(x) + else + fun_l16_n108(x) + end +end + +def fun_l15_n866(x) + if (x < 1) + fun_l16_n956(x) + else + fun_l16_n840(x) + end +end + +def fun_l15_n867(x) + if (x < 1) + fun_l16_n866(x) + else + fun_l16_n291(x) + end +end + +def fun_l15_n868(x) + if (x < 1) + fun_l16_n176(x) + else + fun_l16_n192(x) + end +end + +def fun_l15_n869(x) + if (x < 1) + fun_l16_n833(x) + else + fun_l16_n503(x) + end +end + +def fun_l15_n870(x) + if (x < 1) + fun_l16_n648(x) + else + fun_l16_n778(x) + end +end + +def fun_l15_n871(x) + if (x < 1) + fun_l16_n237(x) + else + fun_l16_n206(x) + end +end + +def fun_l15_n872(x) + if (x < 1) + fun_l16_n676(x) + else + fun_l16_n868(x) + end +end + +def fun_l15_n873(x) + if (x < 1) + fun_l16_n547(x) + else + fun_l16_n731(x) + end +end + +def fun_l15_n874(x) + if (x < 1) + fun_l16_n870(x) + else + fun_l16_n43(x) + end +end + +def fun_l15_n875(x) + if (x < 1) + fun_l16_n246(x) + else + fun_l16_n654(x) + end +end + +def fun_l15_n876(x) + if (x < 1) + fun_l16_n570(x) + else + fun_l16_n842(x) + end +end + +def fun_l15_n877(x) + if (x < 1) + fun_l16_n272(x) + else + fun_l16_n784(x) + end +end + +def fun_l15_n878(x) + if (x < 1) + fun_l16_n702(x) + else + fun_l16_n758(x) + end +end + +def fun_l15_n879(x) + if (x < 1) + fun_l16_n691(x) + else + fun_l16_n303(x) + end +end + +def fun_l15_n880(x) + if (x < 1) + fun_l16_n944(x) + else + fun_l16_n449(x) + end +end + +def fun_l15_n881(x) + if (x < 1) + fun_l16_n741(x) + else + fun_l16_n254(x) + end +end + +def fun_l15_n882(x) + if (x < 1) + fun_l16_n195(x) + else + fun_l16_n294(x) + end +end + +def fun_l15_n883(x) + if (x < 1) + fun_l16_n776(x) + else + fun_l16_n147(x) + end +end + +def fun_l15_n884(x) + if (x < 1) + fun_l16_n145(x) + else + fun_l16_n856(x) + end +end + +def fun_l15_n885(x) + if (x < 1) + fun_l16_n671(x) + else + fun_l16_n429(x) + end +end + +def fun_l15_n886(x) + if (x < 1) + fun_l16_n72(x) + else + fun_l16_n455(x) + end +end + +def fun_l15_n887(x) + if (x < 1) + fun_l16_n775(x) + else + fun_l16_n43(x) + end +end + +def fun_l15_n888(x) + if (x < 1) + fun_l16_n936(x) + else + fun_l16_n642(x) + end +end + +def fun_l15_n889(x) + if (x < 1) + fun_l16_n794(x) + else + fun_l16_n277(x) + end +end + +def fun_l15_n890(x) + if (x < 1) + fun_l16_n72(x) + else + fun_l16_n450(x) + end +end + +def fun_l15_n891(x) + if (x < 1) + fun_l16_n417(x) + else + fun_l16_n5(x) + end +end + +def fun_l15_n892(x) + if (x < 1) + fun_l16_n69(x) + else + fun_l16_n355(x) + end +end + +def fun_l15_n893(x) + if (x < 1) + fun_l16_n352(x) + else + fun_l16_n635(x) + end +end + +def fun_l15_n894(x) + if (x < 1) + fun_l16_n168(x) + else + fun_l16_n16(x) + end +end + +def fun_l15_n895(x) + if (x < 1) + fun_l16_n922(x) + else + fun_l16_n440(x) + end +end + +def fun_l15_n896(x) + if (x < 1) + fun_l16_n808(x) + else + fun_l16_n896(x) + end +end + +def fun_l15_n897(x) + if (x < 1) + fun_l16_n736(x) + else + fun_l16_n596(x) + end +end + +def fun_l15_n898(x) + if (x < 1) + fun_l16_n886(x) + else + fun_l16_n386(x) + end +end + +def fun_l15_n899(x) + if (x < 1) + fun_l16_n374(x) + else + fun_l16_n746(x) + end +end + +def fun_l15_n900(x) + if (x < 1) + fun_l16_n623(x) + else + fun_l16_n329(x) + end +end + +def fun_l15_n901(x) + if (x < 1) + fun_l16_n313(x) + else + fun_l16_n102(x) + end +end + +def fun_l15_n902(x) + if (x < 1) + fun_l16_n234(x) + else + fun_l16_n425(x) + end +end + +def fun_l15_n903(x) + if (x < 1) + fun_l16_n836(x) + else + fun_l16_n492(x) + end +end + +def fun_l15_n904(x) + if (x < 1) + fun_l16_n690(x) + else + fun_l16_n241(x) + end +end + +def fun_l15_n905(x) + if (x < 1) + fun_l16_n129(x) + else + fun_l16_n57(x) + end +end + +def fun_l15_n906(x) + if (x < 1) + fun_l16_n50(x) + else + fun_l16_n24(x) + end +end + +def fun_l15_n907(x) + if (x < 1) + fun_l16_n609(x) + else + fun_l16_n4(x) + end +end + +def fun_l15_n908(x) + if (x < 1) + fun_l16_n483(x) + else + fun_l16_n708(x) + end +end + +def fun_l15_n909(x) + if (x < 1) + fun_l16_n656(x) + else + fun_l16_n234(x) + end +end + +def fun_l15_n910(x) + if (x < 1) + fun_l16_n945(x) + else + fun_l16_n753(x) + end +end + +def fun_l15_n911(x) + if (x < 1) + fun_l16_n152(x) + else + fun_l16_n739(x) + end +end + +def fun_l15_n912(x) + if (x < 1) + fun_l16_n855(x) + else + fun_l16_n518(x) + end +end + +def fun_l15_n913(x) + if (x < 1) + fun_l16_n295(x) + else + fun_l16_n719(x) + end +end + +def fun_l15_n914(x) + if (x < 1) + fun_l16_n442(x) + else + fun_l16_n803(x) + end +end + +def fun_l15_n915(x) + if (x < 1) + fun_l16_n672(x) + else + fun_l16_n935(x) + end +end + +def fun_l15_n916(x) + if (x < 1) + fun_l16_n908(x) + else + fun_l16_n900(x) + end +end + +def fun_l15_n917(x) + if (x < 1) + fun_l16_n853(x) + else + fun_l16_n896(x) + end +end + +def fun_l15_n918(x) + if (x < 1) + fun_l16_n90(x) + else + fun_l16_n56(x) + end +end + +def fun_l15_n919(x) + if (x < 1) + fun_l16_n944(x) + else + fun_l16_n763(x) + end +end + +def fun_l15_n920(x) + if (x < 1) + fun_l16_n303(x) + else + fun_l16_n328(x) + end +end + +def fun_l15_n921(x) + if (x < 1) + fun_l16_n599(x) + else + fun_l16_n648(x) + end +end + +def fun_l15_n922(x) + if (x < 1) + fun_l16_n113(x) + else + fun_l16_n665(x) + end +end + +def fun_l15_n923(x) + if (x < 1) + fun_l16_n97(x) + else + fun_l16_n757(x) + end +end + +def fun_l15_n924(x) + if (x < 1) + fun_l16_n815(x) + else + fun_l16_n821(x) + end +end + +def fun_l15_n925(x) + if (x < 1) + fun_l16_n146(x) + else + fun_l16_n970(x) + end +end + +def fun_l15_n926(x) + if (x < 1) + fun_l16_n74(x) + else + fun_l16_n203(x) + end +end + +def fun_l15_n927(x) + if (x < 1) + fun_l16_n573(x) + else + fun_l16_n763(x) + end +end + +def fun_l15_n928(x) + if (x < 1) + fun_l16_n656(x) + else + fun_l16_n691(x) + end +end + +def fun_l15_n929(x) + if (x < 1) + fun_l16_n240(x) + else + fun_l16_n536(x) + end +end + +def fun_l15_n930(x) + if (x < 1) + fun_l16_n168(x) + else + fun_l16_n145(x) + end +end + +def fun_l15_n931(x) + if (x < 1) + fun_l16_n502(x) + else + fun_l16_n603(x) + end +end + +def fun_l15_n932(x) + if (x < 1) + fun_l16_n998(x) + else + fun_l16_n259(x) + end +end + +def fun_l15_n933(x) + if (x < 1) + fun_l16_n633(x) + else + fun_l16_n66(x) + end +end + +def fun_l15_n934(x) + if (x < 1) + fun_l16_n657(x) + else + fun_l16_n727(x) + end +end + +def fun_l15_n935(x) + if (x < 1) + fun_l16_n641(x) + else + fun_l16_n975(x) + end +end + +def fun_l15_n936(x) + if (x < 1) + fun_l16_n610(x) + else + fun_l16_n256(x) + end +end + +def fun_l15_n937(x) + if (x < 1) + fun_l16_n760(x) + else + fun_l16_n304(x) + end +end + +def fun_l15_n938(x) + if (x < 1) + fun_l16_n395(x) + else + fun_l16_n302(x) + end +end + +def fun_l15_n939(x) + if (x < 1) + fun_l16_n810(x) + else + fun_l16_n549(x) + end +end + +def fun_l15_n940(x) + if (x < 1) + fun_l16_n452(x) + else + fun_l16_n914(x) + end +end + +def fun_l15_n941(x) + if (x < 1) + fun_l16_n472(x) + else + fun_l16_n328(x) + end +end + +def fun_l15_n942(x) + if (x < 1) + fun_l16_n886(x) + else + fun_l16_n535(x) + end +end + +def fun_l15_n943(x) + if (x < 1) + fun_l16_n162(x) + else + fun_l16_n449(x) + end +end + +def fun_l15_n944(x) + if (x < 1) + fun_l16_n152(x) + else + fun_l16_n790(x) + end +end + +def fun_l15_n945(x) + if (x < 1) + fun_l16_n228(x) + else + fun_l16_n391(x) + end +end + +def fun_l15_n946(x) + if (x < 1) + fun_l16_n115(x) + else + fun_l16_n371(x) + end +end + +def fun_l15_n947(x) + if (x < 1) + fun_l16_n359(x) + else + fun_l16_n928(x) + end +end + +def fun_l15_n948(x) + if (x < 1) + fun_l16_n246(x) + else + fun_l16_n907(x) + end +end + +def fun_l15_n949(x) + if (x < 1) + fun_l16_n448(x) + else + fun_l16_n845(x) + end +end + +def fun_l15_n950(x) + if (x < 1) + fun_l16_n457(x) + else + fun_l16_n954(x) + end +end + +def fun_l15_n951(x) + if (x < 1) + fun_l16_n627(x) + else + fun_l16_n684(x) + end +end + +def fun_l15_n952(x) + if (x < 1) + fun_l16_n887(x) + else + fun_l16_n928(x) + end +end + +def fun_l15_n953(x) + if (x < 1) + fun_l16_n782(x) + else + fun_l16_n619(x) + end +end + +def fun_l15_n954(x) + if (x < 1) + fun_l16_n436(x) + else + fun_l16_n745(x) + end +end + +def fun_l15_n955(x) + if (x < 1) + fun_l16_n9(x) + else + fun_l16_n604(x) + end +end + +def fun_l15_n956(x) + if (x < 1) + fun_l16_n149(x) + else + fun_l16_n357(x) + end +end + +def fun_l15_n957(x) + if (x < 1) + fun_l16_n664(x) + else + fun_l16_n371(x) + end +end + +def fun_l15_n958(x) + if (x < 1) + fun_l16_n236(x) + else + fun_l16_n402(x) + end +end + +def fun_l15_n959(x) + if (x < 1) + fun_l16_n681(x) + else + fun_l16_n410(x) + end +end + +def fun_l15_n960(x) + if (x < 1) + fun_l16_n909(x) + else + fun_l16_n958(x) + end +end + +def fun_l15_n961(x) + if (x < 1) + fun_l16_n400(x) + else + fun_l16_n497(x) + end +end + +def fun_l15_n962(x) + if (x < 1) + fun_l16_n949(x) + else + fun_l16_n794(x) + end +end + +def fun_l15_n963(x) + if (x < 1) + fun_l16_n774(x) + else + fun_l16_n770(x) + end +end + +def fun_l15_n964(x) + if (x < 1) + fun_l16_n573(x) + else + fun_l16_n73(x) + end +end + +def fun_l15_n965(x) + if (x < 1) + fun_l16_n33(x) + else + fun_l16_n978(x) + end +end + +def fun_l15_n966(x) + if (x < 1) + fun_l16_n8(x) + else + fun_l16_n542(x) + end +end + +def fun_l15_n967(x) + if (x < 1) + fun_l16_n780(x) + else + fun_l16_n96(x) + end +end + +def fun_l15_n968(x) + if (x < 1) + fun_l16_n75(x) + else + fun_l16_n560(x) + end +end + +def fun_l15_n969(x) + if (x < 1) + fun_l16_n950(x) + else + fun_l16_n610(x) + end +end + +def fun_l15_n970(x) + if (x < 1) + fun_l16_n254(x) + else + fun_l16_n2(x) + end +end + +def fun_l15_n971(x) + if (x < 1) + fun_l16_n793(x) + else + fun_l16_n89(x) + end +end + +def fun_l15_n972(x) + if (x < 1) + fun_l16_n409(x) + else + fun_l16_n967(x) + end +end + +def fun_l15_n973(x) + if (x < 1) + fun_l16_n356(x) + else + fun_l16_n421(x) + end +end + +def fun_l15_n974(x) + if (x < 1) + fun_l16_n539(x) + else + fun_l16_n997(x) + end +end + +def fun_l15_n975(x) + if (x < 1) + fun_l16_n772(x) + else + fun_l16_n304(x) + end +end + +def fun_l15_n976(x) + if (x < 1) + fun_l16_n228(x) + else + fun_l16_n420(x) + end +end + +def fun_l15_n977(x) + if (x < 1) + fun_l16_n508(x) + else + fun_l16_n352(x) + end +end + +def fun_l15_n978(x) + if (x < 1) + fun_l16_n878(x) + else + fun_l16_n316(x) + end +end + +def fun_l15_n979(x) + if (x < 1) + fun_l16_n279(x) + else + fun_l16_n325(x) + end +end + +def fun_l15_n980(x) + if (x < 1) + fun_l16_n98(x) + else + fun_l16_n10(x) + end +end + +def fun_l15_n981(x) + if (x < 1) + fun_l16_n320(x) + else + fun_l16_n578(x) + end +end + +def fun_l15_n982(x) + if (x < 1) + fun_l16_n112(x) + else + fun_l16_n353(x) + end +end + +def fun_l15_n983(x) + if (x < 1) + fun_l16_n579(x) + else + fun_l16_n946(x) + end +end + +def fun_l15_n984(x) + if (x < 1) + fun_l16_n183(x) + else + fun_l16_n638(x) + end +end + +def fun_l15_n985(x) + if (x < 1) + fun_l16_n500(x) + else + fun_l16_n11(x) + end +end + +def fun_l15_n986(x) + if (x < 1) + fun_l16_n773(x) + else + fun_l16_n135(x) + end +end + +def fun_l15_n987(x) + if (x < 1) + fun_l16_n997(x) + else + fun_l16_n645(x) + end +end + +def fun_l15_n988(x) + if (x < 1) + fun_l16_n392(x) + else + fun_l16_n172(x) + end +end + +def fun_l15_n989(x) + if (x < 1) + fun_l16_n150(x) + else + fun_l16_n163(x) + end +end + +def fun_l15_n990(x) + if (x < 1) + fun_l16_n351(x) + else + fun_l16_n297(x) + end +end + +def fun_l15_n991(x) + if (x < 1) + fun_l16_n676(x) + else + fun_l16_n31(x) + end +end + +def fun_l15_n992(x) + if (x < 1) + fun_l16_n257(x) + else + fun_l16_n45(x) + end +end + +def fun_l15_n993(x) + if (x < 1) + fun_l16_n971(x) + else + fun_l16_n60(x) + end +end + +def fun_l15_n994(x) + if (x < 1) + fun_l16_n472(x) + else + fun_l16_n774(x) + end +end + +def fun_l15_n995(x) + if (x < 1) + fun_l16_n559(x) + else + fun_l16_n605(x) + end +end + +def fun_l15_n996(x) + if (x < 1) + fun_l16_n122(x) + else + fun_l16_n695(x) + end +end + +def fun_l15_n997(x) + if (x < 1) + fun_l16_n118(x) + else + fun_l16_n613(x) + end +end + +def fun_l15_n998(x) + if (x < 1) + fun_l16_n973(x) + else + fun_l16_n193(x) + end +end + +def fun_l15_n999(x) + if (x < 1) + fun_l16_n652(x) + else + fun_l16_n658(x) + end +end + +def fun_l16_n0(x) + if (x < 1) + fun_l17_n352(x) + else + fun_l17_n155(x) + end +end + +def fun_l16_n1(x) + if (x < 1) + fun_l17_n786(x) + else + fun_l17_n961(x) + end +end + +def fun_l16_n2(x) + if (x < 1) + fun_l17_n760(x) + else + fun_l17_n629(x) + end +end + +def fun_l16_n3(x) + if (x < 1) + fun_l17_n788(x) + else + fun_l17_n70(x) + end +end + +def fun_l16_n4(x) + if (x < 1) + fun_l17_n116(x) + else + fun_l17_n616(x) + end +end + +def fun_l16_n5(x) + if (x < 1) + fun_l17_n470(x) + else + fun_l17_n859(x) + end +end + +def fun_l16_n6(x) + if (x < 1) + fun_l17_n830(x) + else + fun_l17_n987(x) + end +end + +def fun_l16_n7(x) + if (x < 1) + fun_l17_n339(x) + else + fun_l17_n284(x) + end +end + +def fun_l16_n8(x) + if (x < 1) + fun_l17_n677(x) + else + fun_l17_n77(x) + end +end + +def fun_l16_n9(x) + if (x < 1) + fun_l17_n7(x) + else + fun_l17_n159(x) + end +end + +def fun_l16_n10(x) + if (x < 1) + fun_l17_n275(x) + else + fun_l17_n37(x) + end +end + +def fun_l16_n11(x) + if (x < 1) + fun_l17_n406(x) + else + fun_l17_n588(x) + end +end + +def fun_l16_n12(x) + if (x < 1) + fun_l17_n132(x) + else + fun_l17_n208(x) + end +end + +def fun_l16_n13(x) + if (x < 1) + fun_l17_n87(x) + else + fun_l17_n850(x) + end +end + +def fun_l16_n14(x) + if (x < 1) + fun_l17_n965(x) + else + fun_l17_n106(x) + end +end + +def fun_l16_n15(x) + if (x < 1) + fun_l17_n176(x) + else + fun_l17_n966(x) + end +end + +def fun_l16_n16(x) + if (x < 1) + fun_l17_n825(x) + else + fun_l17_n815(x) + end +end + +def fun_l16_n17(x) + if (x < 1) + fun_l17_n939(x) + else + fun_l17_n591(x) + end +end + +def fun_l16_n18(x) + if (x < 1) + fun_l17_n166(x) + else + fun_l17_n732(x) + end +end + +def fun_l16_n19(x) + if (x < 1) + fun_l17_n471(x) + else + fun_l17_n175(x) + end +end + +def fun_l16_n20(x) + if (x < 1) + fun_l17_n887(x) + else + fun_l17_n304(x) + end +end + +def fun_l16_n21(x) + if (x < 1) + fun_l17_n545(x) + else + fun_l17_n221(x) + end +end + +def fun_l16_n22(x) + if (x < 1) + fun_l17_n879(x) + else + fun_l17_n143(x) + end +end + +def fun_l16_n23(x) + if (x < 1) + fun_l17_n732(x) + else + fun_l17_n902(x) + end +end + +def fun_l16_n24(x) + if (x < 1) + fun_l17_n490(x) + else + fun_l17_n327(x) + end +end + +def fun_l16_n25(x) + if (x < 1) + fun_l17_n588(x) + else + fun_l17_n658(x) + end +end + +def fun_l16_n26(x) + if (x < 1) + fun_l17_n555(x) + else + fun_l17_n507(x) + end +end + +def fun_l16_n27(x) + if (x < 1) + fun_l17_n228(x) + else + fun_l17_n808(x) + end +end + +def fun_l16_n28(x) + if (x < 1) + fun_l17_n705(x) + else + fun_l17_n696(x) + end +end + +def fun_l16_n29(x) + if (x < 1) + fun_l17_n711(x) + else + fun_l17_n913(x) + end +end + +def fun_l16_n30(x) + if (x < 1) + fun_l17_n264(x) + else + fun_l17_n287(x) + end +end + +def fun_l16_n31(x) + if (x < 1) + fun_l17_n624(x) + else + fun_l17_n358(x) + end +end + +def fun_l16_n32(x) + if (x < 1) + fun_l17_n102(x) + else + fun_l17_n303(x) + end +end + +def fun_l16_n33(x) + if (x < 1) + fun_l17_n613(x) + else + fun_l17_n921(x) + end +end + +def fun_l16_n34(x) + if (x < 1) + fun_l17_n637(x) + else + fun_l17_n142(x) + end +end + +def fun_l16_n35(x) + if (x < 1) + fun_l17_n8(x) + else + fun_l17_n752(x) + end +end + +def fun_l16_n36(x) + if (x < 1) + fun_l17_n748(x) + else + fun_l17_n956(x) + end +end + +def fun_l16_n37(x) + if (x < 1) + fun_l17_n985(x) + else + fun_l17_n133(x) + end +end + +def fun_l16_n38(x) + if (x < 1) + fun_l17_n422(x) + else + fun_l17_n608(x) + end +end + +def fun_l16_n39(x) + if (x < 1) + fun_l17_n455(x) + else + fun_l17_n247(x) + end +end + +def fun_l16_n40(x) + if (x < 1) + fun_l17_n363(x) + else + fun_l17_n874(x) + end +end + +def fun_l16_n41(x) + if (x < 1) + fun_l17_n299(x) + else + fun_l17_n971(x) + end +end + +def fun_l16_n42(x) + if (x < 1) + fun_l17_n788(x) + else + fun_l17_n535(x) + end +end + +def fun_l16_n43(x) + if (x < 1) + fun_l17_n282(x) + else + fun_l17_n468(x) + end +end + +def fun_l16_n44(x) + if (x < 1) + fun_l17_n493(x) + else + fun_l17_n931(x) + end +end + +def fun_l16_n45(x) + if (x < 1) + fun_l17_n750(x) + else + fun_l17_n725(x) + end +end + +def fun_l16_n46(x) + if (x < 1) + fun_l17_n227(x) + else + fun_l17_n769(x) + end +end + +def fun_l16_n47(x) + if (x < 1) + fun_l17_n348(x) + else + fun_l17_n83(x) + end +end + +def fun_l16_n48(x) + if (x < 1) + fun_l17_n624(x) + else + fun_l17_n398(x) + end +end + +def fun_l16_n49(x) + if (x < 1) + fun_l17_n645(x) + else + fun_l17_n645(x) + end +end + +def fun_l16_n50(x) + if (x < 1) + fun_l17_n191(x) + else + fun_l17_n256(x) + end +end + +def fun_l16_n51(x) + if (x < 1) + fun_l17_n947(x) + else + fun_l17_n188(x) + end +end + +def fun_l16_n52(x) + if (x < 1) + fun_l17_n135(x) + else + fun_l17_n923(x) + end +end + +def fun_l16_n53(x) + if (x < 1) + fun_l17_n867(x) + else + fun_l17_n520(x) + end +end + +def fun_l16_n54(x) + if (x < 1) + fun_l17_n450(x) + else + fun_l17_n864(x) + end +end + +def fun_l16_n55(x) + if (x < 1) + fun_l17_n116(x) + else + fun_l17_n370(x) + end +end + +def fun_l16_n56(x) + if (x < 1) + fun_l17_n754(x) + else + fun_l17_n919(x) + end +end + +def fun_l16_n57(x) + if (x < 1) + fun_l17_n360(x) + else + fun_l17_n513(x) + end +end + +def fun_l16_n58(x) + if (x < 1) + fun_l17_n436(x) + else + fun_l17_n618(x) + end +end + +def fun_l16_n59(x) + if (x < 1) + fun_l17_n795(x) + else + fun_l17_n851(x) + end +end + +def fun_l16_n60(x) + if (x < 1) + fun_l17_n624(x) + else + fun_l17_n305(x) + end +end + +def fun_l16_n61(x) + if (x < 1) + fun_l17_n520(x) + else + fun_l17_n360(x) + end +end + +def fun_l16_n62(x) + if (x < 1) + fun_l17_n297(x) + else + fun_l17_n218(x) + end +end + +def fun_l16_n63(x) + if (x < 1) + fun_l17_n116(x) + else + fun_l17_n888(x) + end +end + +def fun_l16_n64(x) + if (x < 1) + fun_l17_n800(x) + else + fun_l17_n985(x) + end +end + +def fun_l16_n65(x) + if (x < 1) + fun_l17_n875(x) + else + fun_l17_n821(x) + end +end + +def fun_l16_n66(x) + if (x < 1) + fun_l17_n677(x) + else + fun_l17_n705(x) + end +end + +def fun_l16_n67(x) + if (x < 1) + fun_l17_n643(x) + else + fun_l17_n240(x) + end +end + +def fun_l16_n68(x) + if (x < 1) + fun_l17_n290(x) + else + fun_l17_n885(x) + end +end + +def fun_l16_n69(x) + if (x < 1) + fun_l17_n987(x) + else + fun_l17_n611(x) + end +end + +def fun_l16_n70(x) + if (x < 1) + fun_l17_n546(x) + else + fun_l17_n95(x) + end +end + +def fun_l16_n71(x) + if (x < 1) + fun_l17_n301(x) + else + fun_l17_n260(x) + end +end + +def fun_l16_n72(x) + if (x < 1) + fun_l17_n118(x) + else + fun_l17_n110(x) + end +end + +def fun_l16_n73(x) + if (x < 1) + fun_l17_n254(x) + else + fun_l17_n602(x) + end +end + +def fun_l16_n74(x) + if (x < 1) + fun_l17_n725(x) + else + fun_l17_n606(x) + end +end + +def fun_l16_n75(x) + if (x < 1) + fun_l17_n114(x) + else + fun_l17_n336(x) + end +end + +def fun_l16_n76(x) + if (x < 1) + fun_l17_n930(x) + else + fun_l17_n513(x) + end +end + +def fun_l16_n77(x) + if (x < 1) + fun_l17_n217(x) + else + fun_l17_n158(x) + end +end + +def fun_l16_n78(x) + if (x < 1) + fun_l17_n987(x) + else + fun_l17_n538(x) + end +end + +def fun_l16_n79(x) + if (x < 1) + fun_l17_n467(x) + else + fun_l17_n675(x) + end +end + +def fun_l16_n80(x) + if (x < 1) + fun_l17_n553(x) + else + fun_l17_n77(x) + end +end + +def fun_l16_n81(x) + if (x < 1) + fun_l17_n643(x) + else + fun_l17_n156(x) + end +end + +def fun_l16_n82(x) + if (x < 1) + fun_l17_n858(x) + else + fun_l17_n300(x) + end +end + +def fun_l16_n83(x) + if (x < 1) + fun_l17_n136(x) + else + fun_l17_n637(x) + end +end + +def fun_l16_n84(x) + if (x < 1) + fun_l17_n71(x) + else + fun_l17_n979(x) + end +end + +def fun_l16_n85(x) + if (x < 1) + fun_l17_n135(x) + else + fun_l17_n893(x) + end +end + +def fun_l16_n86(x) + if (x < 1) + fun_l17_n734(x) + else + fun_l17_n254(x) + end +end + +def fun_l16_n87(x) + if (x < 1) + fun_l17_n809(x) + else + fun_l17_n475(x) + end +end + +def fun_l16_n88(x) + if (x < 1) + fun_l17_n931(x) + else + fun_l17_n110(x) + end +end + +def fun_l16_n89(x) + if (x < 1) + fun_l17_n957(x) + else + fun_l17_n489(x) + end +end + +def fun_l16_n90(x) + if (x < 1) + fun_l17_n145(x) + else + fun_l17_n861(x) + end +end + +def fun_l16_n91(x) + if (x < 1) + fun_l17_n276(x) + else + fun_l17_n967(x) + end +end + +def fun_l16_n92(x) + if (x < 1) + fun_l17_n657(x) + else + fun_l17_n638(x) + end +end + +def fun_l16_n93(x) + if (x < 1) + fun_l17_n714(x) + else + fun_l17_n52(x) + end +end + +def fun_l16_n94(x) + if (x < 1) + fun_l17_n487(x) + else + fun_l17_n380(x) + end +end + +def fun_l16_n95(x) + if (x < 1) + fun_l17_n58(x) + else + fun_l17_n67(x) + end +end + +def fun_l16_n96(x) + if (x < 1) + fun_l17_n9(x) + else + fun_l17_n896(x) + end +end + +def fun_l16_n97(x) + if (x < 1) + fun_l17_n723(x) + else + fun_l17_n16(x) + end +end + +def fun_l16_n98(x) + if (x < 1) + fun_l17_n143(x) + else + fun_l17_n31(x) + end +end + +def fun_l16_n99(x) + if (x < 1) + fun_l17_n33(x) + else + fun_l17_n615(x) + end +end + +def fun_l16_n100(x) + if (x < 1) + fun_l17_n318(x) + else + fun_l17_n83(x) + end +end + +def fun_l16_n101(x) + if (x < 1) + fun_l17_n694(x) + else + fun_l17_n851(x) + end +end + +def fun_l16_n102(x) + if (x < 1) + fun_l17_n31(x) + else + fun_l17_n881(x) + end +end + +def fun_l16_n103(x) + if (x < 1) + fun_l17_n739(x) + else + fun_l17_n680(x) + end +end + +def fun_l16_n104(x) + if (x < 1) + fun_l17_n123(x) + else + fun_l17_n969(x) + end +end + +def fun_l16_n105(x) + if (x < 1) + fun_l17_n526(x) + else + fun_l17_n529(x) + end +end + +def fun_l16_n106(x) + if (x < 1) + fun_l17_n613(x) + else + fun_l17_n738(x) + end +end + +def fun_l16_n107(x) + if (x < 1) + fun_l17_n48(x) + else + fun_l17_n107(x) + end +end + +def fun_l16_n108(x) + if (x < 1) + fun_l17_n493(x) + else + fun_l17_n875(x) + end +end + +def fun_l16_n109(x) + if (x < 1) + fun_l17_n101(x) + else + fun_l17_n295(x) + end +end + +def fun_l16_n110(x) + if (x < 1) + fun_l17_n257(x) + else + fun_l17_n132(x) + end +end + +def fun_l16_n111(x) + if (x < 1) + fun_l17_n702(x) + else + fun_l17_n635(x) + end +end + +def fun_l16_n112(x) + if (x < 1) + fun_l17_n193(x) + else + fun_l17_n931(x) + end +end + +def fun_l16_n113(x) + if (x < 1) + fun_l17_n973(x) + else + fun_l17_n708(x) + end +end + +def fun_l16_n114(x) + if (x < 1) + fun_l17_n110(x) + else + fun_l17_n247(x) + end +end + +def fun_l16_n115(x) + if (x < 1) + fun_l17_n769(x) + else + fun_l17_n872(x) + end +end + +def fun_l16_n116(x) + if (x < 1) + fun_l17_n63(x) + else + fun_l17_n90(x) + end +end + +def fun_l16_n117(x) + if (x < 1) + fun_l17_n392(x) + else + fun_l17_n3(x) + end +end + +def fun_l16_n118(x) + if (x < 1) + fun_l17_n73(x) + else + fun_l17_n354(x) + end +end + +def fun_l16_n119(x) + if (x < 1) + fun_l17_n173(x) + else + fun_l17_n573(x) + end +end + +def fun_l16_n120(x) + if (x < 1) + fun_l17_n481(x) + else + fun_l17_n571(x) + end +end + +def fun_l16_n121(x) + if (x < 1) + fun_l17_n838(x) + else + fun_l17_n736(x) + end +end + +def fun_l16_n122(x) + if (x < 1) + fun_l17_n400(x) + else + fun_l17_n169(x) + end +end + +def fun_l16_n123(x) + if (x < 1) + fun_l17_n806(x) + else + fun_l17_n954(x) + end +end + +def fun_l16_n124(x) + if (x < 1) + fun_l17_n328(x) + else + fun_l17_n200(x) + end +end + +def fun_l16_n125(x) + if (x < 1) + fun_l17_n388(x) + else + fun_l17_n875(x) + end +end + +def fun_l16_n126(x) + if (x < 1) + fun_l17_n178(x) + else + fun_l17_n122(x) + end +end + +def fun_l16_n127(x) + if (x < 1) + fun_l17_n974(x) + else + fun_l17_n490(x) + end +end + +def fun_l16_n128(x) + if (x < 1) + fun_l17_n731(x) + else + fun_l17_n807(x) + end +end + +def fun_l16_n129(x) + if (x < 1) + fun_l17_n939(x) + else + fun_l17_n532(x) + end +end + +def fun_l16_n130(x) + if (x < 1) + fun_l17_n482(x) + else + fun_l17_n926(x) + end +end + +def fun_l16_n131(x) + if (x < 1) + fun_l17_n884(x) + else + fun_l17_n179(x) + end +end + +def fun_l16_n132(x) + if (x < 1) + fun_l17_n683(x) + else + fun_l17_n24(x) + end +end + +def fun_l16_n133(x) + if (x < 1) + fun_l17_n968(x) + else + fun_l17_n536(x) + end +end + +def fun_l16_n134(x) + if (x < 1) + fun_l17_n229(x) + else + fun_l17_n280(x) + end +end + +def fun_l16_n135(x) + if (x < 1) + fun_l17_n47(x) + else + fun_l17_n12(x) + end +end + +def fun_l16_n136(x) + if (x < 1) + fun_l17_n905(x) + else + fun_l17_n461(x) + end +end + +def fun_l16_n137(x) + if (x < 1) + fun_l17_n992(x) + else + fun_l17_n294(x) + end +end + +def fun_l16_n138(x) + if (x < 1) + fun_l17_n383(x) + else + fun_l17_n916(x) + end +end + +def fun_l16_n139(x) + if (x < 1) + fun_l17_n116(x) + else + fun_l17_n96(x) + end +end + +def fun_l16_n140(x) + if (x < 1) + fun_l17_n702(x) + else + fun_l17_n294(x) + end +end + +def fun_l16_n141(x) + if (x < 1) + fun_l17_n528(x) + else + fun_l17_n650(x) + end +end + +def fun_l16_n142(x) + if (x < 1) + fun_l17_n341(x) + else + fun_l17_n168(x) + end +end + +def fun_l16_n143(x) + if (x < 1) + fun_l17_n85(x) + else + fun_l17_n384(x) + end +end + +def fun_l16_n144(x) + if (x < 1) + fun_l17_n738(x) + else + fun_l17_n842(x) + end +end + +def fun_l16_n145(x) + if (x < 1) + fun_l17_n359(x) + else + fun_l17_n691(x) + end +end + +def fun_l16_n146(x) + if (x < 1) + fun_l17_n465(x) + else + fun_l17_n310(x) + end +end + +def fun_l16_n147(x) + if (x < 1) + fun_l17_n610(x) + else + fun_l17_n133(x) + end +end + +def fun_l16_n148(x) + if (x < 1) + fun_l17_n829(x) + else + fun_l17_n449(x) + end +end + +def fun_l16_n149(x) + if (x < 1) + fun_l17_n319(x) + else + fun_l17_n875(x) + end +end + +def fun_l16_n150(x) + if (x < 1) + fun_l17_n493(x) + else + fun_l17_n39(x) + end +end + +def fun_l16_n151(x) + if (x < 1) + fun_l17_n801(x) + else + fun_l17_n294(x) + end +end + +def fun_l16_n152(x) + if (x < 1) + fun_l17_n39(x) + else + fun_l17_n113(x) + end +end + +def fun_l16_n153(x) + if (x < 1) + fun_l17_n299(x) + else + fun_l17_n560(x) + end +end + +def fun_l16_n154(x) + if (x < 1) + fun_l17_n220(x) + else + fun_l17_n485(x) + end +end + +def fun_l16_n155(x) + if (x < 1) + fun_l17_n219(x) + else + fun_l17_n210(x) + end +end + +def fun_l16_n156(x) + if (x < 1) + fun_l17_n44(x) + else + fun_l17_n394(x) + end +end + +def fun_l16_n157(x) + if (x < 1) + fun_l17_n858(x) + else + fun_l17_n9(x) + end +end + +def fun_l16_n158(x) + if (x < 1) + fun_l17_n298(x) + else + fun_l17_n584(x) + end +end + +def fun_l16_n159(x) + if (x < 1) + fun_l17_n627(x) + else + fun_l17_n991(x) + end +end + +def fun_l16_n160(x) + if (x < 1) + fun_l17_n459(x) + else + fun_l17_n686(x) + end +end + +def fun_l16_n161(x) + if (x < 1) + fun_l17_n694(x) + else + fun_l17_n503(x) + end +end + +def fun_l16_n162(x) + if (x < 1) + fun_l17_n331(x) + else + fun_l17_n869(x) + end +end + +def fun_l16_n163(x) + if (x < 1) + fun_l17_n958(x) + else + fun_l17_n102(x) + end +end + +def fun_l16_n164(x) + if (x < 1) + fun_l17_n254(x) + else + fun_l17_n888(x) + end +end + +def fun_l16_n165(x) + if (x < 1) + fun_l17_n639(x) + else + fun_l17_n342(x) + end +end + +def fun_l16_n166(x) + if (x < 1) + fun_l17_n859(x) + else + fun_l17_n2(x) + end +end + +def fun_l16_n167(x) + if (x < 1) + fun_l17_n504(x) + else + fun_l17_n726(x) + end +end + +def fun_l16_n168(x) + if (x < 1) + fun_l17_n426(x) + else + fun_l17_n532(x) + end +end + +def fun_l16_n169(x) + if (x < 1) + fun_l17_n919(x) + else + fun_l17_n515(x) + end +end + +def fun_l16_n170(x) + if (x < 1) + fun_l17_n394(x) + else + fun_l17_n259(x) + end +end + +def fun_l16_n171(x) + if (x < 1) + fun_l17_n920(x) + else + fun_l17_n502(x) + end +end + +def fun_l16_n172(x) + if (x < 1) + fun_l17_n898(x) + else + fun_l17_n984(x) + end +end + +def fun_l16_n173(x) + if (x < 1) + fun_l17_n869(x) + else + fun_l17_n470(x) + end +end + +def fun_l16_n174(x) + if (x < 1) + fun_l17_n959(x) + else + fun_l17_n283(x) + end +end + +def fun_l16_n175(x) + if (x < 1) + fun_l17_n1(x) + else + fun_l17_n68(x) + end +end + +def fun_l16_n176(x) + if (x < 1) + fun_l17_n91(x) + else + fun_l17_n684(x) + end +end + +def fun_l16_n177(x) + if (x < 1) + fun_l17_n803(x) + else + fun_l17_n335(x) + end +end + +def fun_l16_n178(x) + if (x < 1) + fun_l17_n242(x) + else + fun_l17_n671(x) + end +end + +def fun_l16_n179(x) + if (x < 1) + fun_l17_n944(x) + else + fun_l17_n136(x) + end +end + +def fun_l16_n180(x) + if (x < 1) + fun_l17_n681(x) + else + fun_l17_n587(x) + end +end + +def fun_l16_n181(x) + if (x < 1) + fun_l17_n564(x) + else + fun_l17_n965(x) + end +end + +def fun_l16_n182(x) + if (x < 1) + fun_l17_n107(x) + else + fun_l17_n229(x) + end +end + +def fun_l16_n183(x) + if (x < 1) + fun_l17_n467(x) + else + fun_l17_n155(x) + end +end + +def fun_l16_n184(x) + if (x < 1) + fun_l17_n62(x) + else + fun_l17_n507(x) + end +end + +def fun_l16_n185(x) + if (x < 1) + fun_l17_n632(x) + else + fun_l17_n792(x) + end +end + +def fun_l16_n186(x) + if (x < 1) + fun_l17_n174(x) + else + fun_l17_n623(x) + end +end + +def fun_l16_n187(x) + if (x < 1) + fun_l17_n733(x) + else + fun_l17_n640(x) + end +end + +def fun_l16_n188(x) + if (x < 1) + fun_l17_n968(x) + else + fun_l17_n554(x) + end +end + +def fun_l16_n189(x) + if (x < 1) + fun_l17_n363(x) + else + fun_l17_n381(x) + end +end + +def fun_l16_n190(x) + if (x < 1) + fun_l17_n34(x) + else + fun_l17_n145(x) + end +end + +def fun_l16_n191(x) + if (x < 1) + fun_l17_n407(x) + else + fun_l17_n567(x) + end +end + +def fun_l16_n192(x) + if (x < 1) + fun_l17_n497(x) + else + fun_l17_n842(x) + end +end + +def fun_l16_n193(x) + if (x < 1) + fun_l17_n935(x) + else + fun_l17_n394(x) + end +end + +def fun_l16_n194(x) + if (x < 1) + fun_l17_n728(x) + else + fun_l17_n885(x) + end +end + +def fun_l16_n195(x) + if (x < 1) + fun_l17_n974(x) + else + fun_l17_n678(x) + end +end + +def fun_l16_n196(x) + if (x < 1) + fun_l17_n420(x) + else + fun_l17_n894(x) + end +end + +def fun_l16_n197(x) + if (x < 1) + fun_l17_n651(x) + else + fun_l17_n569(x) + end +end + +def fun_l16_n198(x) + if (x < 1) + fun_l17_n274(x) + else + fun_l17_n683(x) + end +end + +def fun_l16_n199(x) + if (x < 1) + fun_l17_n624(x) + else + fun_l17_n343(x) + end +end + +def fun_l16_n200(x) + if (x < 1) + fun_l17_n82(x) + else + fun_l17_n472(x) + end +end + +def fun_l16_n201(x) + if (x < 1) + fun_l17_n519(x) + else + fun_l17_n54(x) + end +end + +def fun_l16_n202(x) + if (x < 1) + fun_l17_n858(x) + else + fun_l17_n379(x) + end +end + +def fun_l16_n203(x) + if (x < 1) + fun_l17_n515(x) + else + fun_l17_n59(x) + end +end + +def fun_l16_n204(x) + if (x < 1) + fun_l17_n736(x) + else + fun_l17_n880(x) + end +end + +def fun_l16_n205(x) + if (x < 1) + fun_l17_n724(x) + else + fun_l17_n890(x) + end +end + +def fun_l16_n206(x) + if (x < 1) + fun_l17_n92(x) + else + fun_l17_n305(x) + end +end + +def fun_l16_n207(x) + if (x < 1) + fun_l17_n123(x) + else + fun_l17_n455(x) + end +end + +def fun_l16_n208(x) + if (x < 1) + fun_l17_n722(x) + else + fun_l17_n142(x) + end +end + +def fun_l16_n209(x) + if (x < 1) + fun_l17_n250(x) + else + fun_l17_n810(x) + end +end + +def fun_l16_n210(x) + if (x < 1) + fun_l17_n118(x) + else + fun_l17_n902(x) + end +end + +def fun_l16_n211(x) + if (x < 1) + fun_l17_n8(x) + else + fun_l17_n874(x) + end +end + +def fun_l16_n212(x) + if (x < 1) + fun_l17_n589(x) + else + fun_l17_n731(x) + end +end + +def fun_l16_n213(x) + if (x < 1) + fun_l17_n786(x) + else + fun_l17_n249(x) + end +end + +def fun_l16_n214(x) + if (x < 1) + fun_l17_n80(x) + else + fun_l17_n763(x) + end +end + +def fun_l16_n215(x) + if (x < 1) + fun_l17_n733(x) + else + fun_l17_n657(x) + end +end + +def fun_l16_n216(x) + if (x < 1) + fun_l17_n168(x) + else + fun_l17_n881(x) + end +end + +def fun_l16_n217(x) + if (x < 1) + fun_l17_n568(x) + else + fun_l17_n698(x) + end +end + +def fun_l16_n218(x) + if (x < 1) + fun_l17_n727(x) + else + fun_l17_n388(x) + end +end + +def fun_l16_n219(x) + if (x < 1) + fun_l17_n443(x) + else + fun_l17_n600(x) + end +end + +def fun_l16_n220(x) + if (x < 1) + fun_l17_n901(x) + else + fun_l17_n875(x) + end +end + +def fun_l16_n221(x) + if (x < 1) + fun_l17_n374(x) + else + fun_l17_n819(x) + end +end + +def fun_l16_n222(x) + if (x < 1) + fun_l17_n563(x) + else + fun_l17_n341(x) + end +end + +def fun_l16_n223(x) + if (x < 1) + fun_l17_n404(x) + else + fun_l17_n201(x) + end +end + +def fun_l16_n224(x) + if (x < 1) + fun_l17_n932(x) + else + fun_l17_n803(x) + end +end + +def fun_l16_n225(x) + if (x < 1) + fun_l17_n970(x) + else + fun_l17_n717(x) + end +end + +def fun_l16_n226(x) + if (x < 1) + fun_l17_n599(x) + else + fun_l17_n692(x) + end +end + +def fun_l16_n227(x) + if (x < 1) + fun_l17_n351(x) + else + fun_l17_n177(x) + end +end + +def fun_l16_n228(x) + if (x < 1) + fun_l17_n891(x) + else + fun_l17_n79(x) + end +end + +def fun_l16_n229(x) + if (x < 1) + fun_l17_n143(x) + else + fun_l17_n702(x) + end +end + +def fun_l16_n230(x) + if (x < 1) + fun_l17_n591(x) + else + fun_l17_n317(x) + end +end + +def fun_l16_n231(x) + if (x < 1) + fun_l17_n727(x) + else + fun_l17_n881(x) + end +end + +def fun_l16_n232(x) + if (x < 1) + fun_l17_n390(x) + else + fun_l17_n580(x) + end +end + +def fun_l16_n233(x) + if (x < 1) + fun_l17_n530(x) + else + fun_l17_n102(x) + end +end + +def fun_l16_n234(x) + if (x < 1) + fun_l17_n891(x) + else + fun_l17_n783(x) + end +end + +def fun_l16_n235(x) + if (x < 1) + fun_l17_n91(x) + else + fun_l17_n142(x) + end +end + +def fun_l16_n236(x) + if (x < 1) + fun_l17_n55(x) + else + fun_l17_n897(x) + end +end + +def fun_l16_n237(x) + if (x < 1) + fun_l17_n471(x) + else + fun_l17_n24(x) + end +end + +def fun_l16_n238(x) + if (x < 1) + fun_l17_n812(x) + else + fun_l17_n833(x) + end +end + +def fun_l16_n239(x) + if (x < 1) + fun_l17_n879(x) + else + fun_l17_n560(x) + end +end + +def fun_l16_n240(x) + if (x < 1) + fun_l17_n882(x) + else + fun_l17_n473(x) + end +end + +def fun_l16_n241(x) + if (x < 1) + fun_l17_n30(x) + else + fun_l17_n299(x) + end +end + +def fun_l16_n242(x) + if (x < 1) + fun_l17_n855(x) + else + fun_l17_n751(x) + end +end + +def fun_l16_n243(x) + if (x < 1) + fun_l17_n184(x) + else + fun_l17_n997(x) + end +end + +def fun_l16_n244(x) + if (x < 1) + fun_l17_n151(x) + else + fun_l17_n495(x) + end +end + +def fun_l16_n245(x) + if (x < 1) + fun_l17_n181(x) + else + fun_l17_n360(x) + end +end + +def fun_l16_n246(x) + if (x < 1) + fun_l17_n208(x) + else + fun_l17_n767(x) + end +end + +def fun_l16_n247(x) + if (x < 1) + fun_l17_n969(x) + else + fun_l17_n15(x) + end +end + +def fun_l16_n248(x) + if (x < 1) + fun_l17_n529(x) + else + fun_l17_n879(x) + end +end + +def fun_l16_n249(x) + if (x < 1) + fun_l17_n729(x) + else + fun_l17_n355(x) + end +end + +def fun_l16_n250(x) + if (x < 1) + fun_l17_n239(x) + else + fun_l17_n414(x) + end +end + +def fun_l16_n251(x) + if (x < 1) + fun_l17_n257(x) + else + fun_l17_n362(x) + end +end + +def fun_l16_n252(x) + if (x < 1) + fun_l17_n832(x) + else + fun_l17_n924(x) + end +end + +def fun_l16_n253(x) + if (x < 1) + fun_l17_n907(x) + else + fun_l17_n548(x) + end +end + +def fun_l16_n254(x) + if (x < 1) + fun_l17_n391(x) + else + fun_l17_n316(x) + end +end + +def fun_l16_n255(x) + if (x < 1) + fun_l17_n163(x) + else + fun_l17_n164(x) + end +end + +def fun_l16_n256(x) + if (x < 1) + fun_l17_n86(x) + else + fun_l17_n473(x) + end +end + +def fun_l16_n257(x) + if (x < 1) + fun_l17_n519(x) + else + fun_l17_n556(x) + end +end + +def fun_l16_n258(x) + if (x < 1) + fun_l17_n819(x) + else + fun_l17_n41(x) + end +end + +def fun_l16_n259(x) + if (x < 1) + fun_l17_n330(x) + else + fun_l17_n334(x) + end +end + +def fun_l16_n260(x) + if (x < 1) + fun_l17_n441(x) + else + fun_l17_n529(x) + end +end + +def fun_l16_n261(x) + if (x < 1) + fun_l17_n116(x) + else + fun_l17_n597(x) + end +end + +def fun_l16_n262(x) + if (x < 1) + fun_l17_n537(x) + else + fun_l17_n594(x) + end +end + +def fun_l16_n263(x) + if (x < 1) + fun_l17_n511(x) + else + fun_l17_n56(x) + end +end + +def fun_l16_n264(x) + if (x < 1) + fun_l17_n264(x) + else + fun_l17_n641(x) + end +end + +def fun_l16_n265(x) + if (x < 1) + fun_l17_n806(x) + else + fun_l17_n432(x) + end +end + +def fun_l16_n266(x) + if (x < 1) + fun_l17_n428(x) + else + fun_l17_n463(x) + end +end + +def fun_l16_n267(x) + if (x < 1) + fun_l17_n39(x) + else + fun_l17_n362(x) + end +end + +def fun_l16_n268(x) + if (x < 1) + fun_l17_n502(x) + else + fun_l17_n87(x) + end +end + +def fun_l16_n269(x) + if (x < 1) + fun_l17_n143(x) + else + fun_l17_n92(x) + end +end + +def fun_l16_n270(x) + if (x < 1) + fun_l17_n675(x) + else + fun_l17_n629(x) + end +end + +def fun_l16_n271(x) + if (x < 1) + fun_l17_n33(x) + else + fun_l17_n158(x) + end +end + +def fun_l16_n272(x) + if (x < 1) + fun_l17_n480(x) + else + fun_l17_n204(x) + end +end + +def fun_l16_n273(x) + if (x < 1) + fun_l17_n81(x) + else + fun_l17_n855(x) + end +end + +def fun_l16_n274(x) + if (x < 1) + fun_l17_n608(x) + else + fun_l17_n969(x) + end +end + +def fun_l16_n275(x) + if (x < 1) + fun_l17_n606(x) + else + fun_l17_n292(x) + end +end + +def fun_l16_n276(x) + if (x < 1) + fun_l17_n494(x) + else + fun_l17_n689(x) + end +end + +def fun_l16_n277(x) + if (x < 1) + fun_l17_n3(x) + else + fun_l17_n207(x) + end +end + +def fun_l16_n278(x) + if (x < 1) + fun_l17_n85(x) + else + fun_l17_n59(x) + end +end + +def fun_l16_n279(x) + if (x < 1) + fun_l17_n363(x) + else + fun_l17_n651(x) + end +end + +def fun_l16_n280(x) + if (x < 1) + fun_l17_n199(x) + else + fun_l17_n77(x) + end +end + +def fun_l16_n281(x) + if (x < 1) + fun_l17_n83(x) + else + fun_l17_n865(x) + end +end + +def fun_l16_n282(x) + if (x < 1) + fun_l17_n120(x) + else + fun_l17_n466(x) + end +end + +def fun_l16_n283(x) + if (x < 1) + fun_l17_n667(x) + else + fun_l17_n867(x) + end +end + +def fun_l16_n284(x) + if (x < 1) + fun_l17_n248(x) + else + fun_l17_n480(x) + end +end + +def fun_l16_n285(x) + if (x < 1) + fun_l17_n766(x) + else + fun_l17_n609(x) + end +end + +def fun_l16_n286(x) + if (x < 1) + fun_l17_n95(x) + else + fun_l17_n341(x) + end +end + +def fun_l16_n287(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n552(x) + end +end + +def fun_l16_n288(x) + if (x < 1) + fun_l17_n955(x) + else + fun_l17_n434(x) + end +end + +def fun_l16_n289(x) + if (x < 1) + fun_l17_n954(x) + else + fun_l17_n554(x) + end +end + +def fun_l16_n290(x) + if (x < 1) + fun_l17_n981(x) + else + fun_l17_n374(x) + end +end + +def fun_l16_n291(x) + if (x < 1) + fun_l17_n153(x) + else + fun_l17_n849(x) + end +end + +def fun_l16_n292(x) + if (x < 1) + fun_l17_n89(x) + else + fun_l17_n491(x) + end +end + +def fun_l16_n293(x) + if (x < 1) + fun_l17_n908(x) + else + fun_l17_n75(x) + end +end + +def fun_l16_n294(x) + if (x < 1) + fun_l17_n772(x) + else + fun_l17_n474(x) + end +end + +def fun_l16_n295(x) + if (x < 1) + fun_l17_n577(x) + else + fun_l17_n470(x) + end +end + +def fun_l16_n296(x) + if (x < 1) + fun_l17_n699(x) + else + fun_l17_n172(x) + end +end + +def fun_l16_n297(x) + if (x < 1) + fun_l17_n408(x) + else + fun_l17_n314(x) + end +end + +def fun_l16_n298(x) + if (x < 1) + fun_l17_n521(x) + else + fun_l17_n940(x) + end +end + +def fun_l16_n299(x) + if (x < 1) + fun_l17_n804(x) + else + fun_l17_n503(x) + end +end + +def fun_l16_n300(x) + if (x < 1) + fun_l17_n712(x) + else + fun_l17_n227(x) + end +end + +def fun_l16_n301(x) + if (x < 1) + fun_l17_n700(x) + else + fun_l17_n102(x) + end +end + +def fun_l16_n302(x) + if (x < 1) + fun_l17_n290(x) + else + fun_l17_n212(x) + end +end + +def fun_l16_n303(x) + if (x < 1) + fun_l17_n525(x) + else + fun_l17_n273(x) + end +end + +def fun_l16_n304(x) + if (x < 1) + fun_l17_n356(x) + else + fun_l17_n359(x) + end +end + +def fun_l16_n305(x) + if (x < 1) + fun_l17_n84(x) + else + fun_l17_n207(x) + end +end + +def fun_l16_n306(x) + if (x < 1) + fun_l17_n566(x) + else + fun_l17_n945(x) + end +end + +def fun_l16_n307(x) + if (x < 1) + fun_l17_n692(x) + else + fun_l17_n326(x) + end +end + +def fun_l16_n308(x) + if (x < 1) + fun_l17_n727(x) + else + fun_l17_n205(x) + end +end + +def fun_l16_n309(x) + if (x < 1) + fun_l17_n568(x) + else + fun_l17_n386(x) + end +end + +def fun_l16_n310(x) + if (x < 1) + fun_l17_n244(x) + else + fun_l17_n472(x) + end +end + +def fun_l16_n311(x) + if (x < 1) + fun_l17_n956(x) + else + fun_l17_n546(x) + end +end + +def fun_l16_n312(x) + if (x < 1) + fun_l17_n807(x) + else + fun_l17_n924(x) + end +end + +def fun_l16_n313(x) + if (x < 1) + fun_l17_n931(x) + else + fun_l17_n962(x) + end +end + +def fun_l16_n314(x) + if (x < 1) + fun_l17_n64(x) + else + fun_l17_n178(x) + end +end + +def fun_l16_n315(x) + if (x < 1) + fun_l17_n460(x) + else + fun_l17_n438(x) + end +end + +def fun_l16_n316(x) + if (x < 1) + fun_l17_n185(x) + else + fun_l17_n25(x) + end +end + +def fun_l16_n317(x) + if (x < 1) + fun_l17_n732(x) + else + fun_l17_n460(x) + end +end + +def fun_l16_n318(x) + if (x < 1) + fun_l17_n5(x) + else + fun_l17_n947(x) + end +end + +def fun_l16_n319(x) + if (x < 1) + fun_l17_n682(x) + else + fun_l17_n644(x) + end +end + +def fun_l16_n320(x) + if (x < 1) + fun_l17_n151(x) + else + fun_l17_n578(x) + end +end + +def fun_l16_n321(x) + if (x < 1) + fun_l17_n219(x) + else + fun_l17_n4(x) + end +end + +def fun_l16_n322(x) + if (x < 1) + fun_l17_n214(x) + else + fun_l17_n594(x) + end +end + +def fun_l16_n323(x) + if (x < 1) + fun_l17_n970(x) + else + fun_l17_n275(x) + end +end + +def fun_l16_n324(x) + if (x < 1) + fun_l17_n442(x) + else + fun_l17_n377(x) + end +end + +def fun_l16_n325(x) + if (x < 1) + fun_l17_n783(x) + else + fun_l17_n731(x) + end +end + +def fun_l16_n326(x) + if (x < 1) + fun_l17_n43(x) + else + fun_l17_n884(x) + end +end + +def fun_l16_n327(x) + if (x < 1) + fun_l17_n857(x) + else + fun_l17_n593(x) + end +end + +def fun_l16_n328(x) + if (x < 1) + fun_l17_n942(x) + else + fun_l17_n772(x) + end +end + +def fun_l16_n329(x) + if (x < 1) + fun_l17_n309(x) + else + fun_l17_n508(x) + end +end + +def fun_l16_n330(x) + if (x < 1) + fun_l17_n30(x) + else + fun_l17_n165(x) + end +end + +def fun_l16_n331(x) + if (x < 1) + fun_l17_n981(x) + else + fun_l17_n355(x) + end +end + +def fun_l16_n332(x) + if (x < 1) + fun_l17_n159(x) + else + fun_l17_n228(x) + end +end + +def fun_l16_n333(x) + if (x < 1) + fun_l17_n499(x) + else + fun_l17_n565(x) + end +end + +def fun_l16_n334(x) + if (x < 1) + fun_l17_n371(x) + else + fun_l17_n856(x) + end +end + +def fun_l16_n335(x) + if (x < 1) + fun_l17_n717(x) + else + fun_l17_n229(x) + end +end + +def fun_l16_n336(x) + if (x < 1) + fun_l17_n678(x) + else + fun_l17_n236(x) + end +end + +def fun_l16_n337(x) + if (x < 1) + fun_l17_n472(x) + else + fun_l17_n566(x) + end +end + +def fun_l16_n338(x) + if (x < 1) + fun_l17_n74(x) + else + fun_l17_n247(x) + end +end + +def fun_l16_n339(x) + if (x < 1) + fun_l17_n379(x) + else + fun_l17_n443(x) + end +end + +def fun_l16_n340(x) + if (x < 1) + fun_l17_n233(x) + else + fun_l17_n79(x) + end +end + +def fun_l16_n341(x) + if (x < 1) + fun_l17_n136(x) + else + fun_l17_n900(x) + end +end + +def fun_l16_n342(x) + if (x < 1) + fun_l17_n785(x) + else + fun_l17_n63(x) + end +end + +def fun_l16_n343(x) + if (x < 1) + fun_l17_n429(x) + else + fun_l17_n111(x) + end +end + +def fun_l16_n344(x) + if (x < 1) + fun_l17_n226(x) + else + fun_l17_n137(x) + end +end + +def fun_l16_n345(x) + if (x < 1) + fun_l17_n428(x) + else + fun_l17_n674(x) + end +end + +def fun_l16_n346(x) + if (x < 1) + fun_l17_n940(x) + else + fun_l17_n987(x) + end +end + +def fun_l16_n347(x) + if (x < 1) + fun_l17_n579(x) + else + fun_l17_n220(x) + end +end + +def fun_l16_n348(x) + if (x < 1) + fun_l17_n502(x) + else + fun_l17_n530(x) + end +end + +def fun_l16_n349(x) + if (x < 1) + fun_l17_n334(x) + else + fun_l17_n955(x) + end +end + +def fun_l16_n350(x) + if (x < 1) + fun_l17_n680(x) + else + fun_l17_n41(x) + end +end + +def fun_l16_n351(x) + if (x < 1) + fun_l17_n821(x) + else + fun_l17_n750(x) + end +end + +def fun_l16_n352(x) + if (x < 1) + fun_l17_n212(x) + else + fun_l17_n537(x) + end +end + +def fun_l16_n353(x) + if (x < 1) + fun_l17_n555(x) + else + fun_l17_n834(x) + end +end + +def fun_l16_n354(x) + if (x < 1) + fun_l17_n532(x) + else + fun_l17_n940(x) + end +end + +def fun_l16_n355(x) + if (x < 1) + fun_l17_n771(x) + else + fun_l17_n915(x) + end +end + +def fun_l16_n356(x) + if (x < 1) + fun_l17_n844(x) + else + fun_l17_n235(x) + end +end + +def fun_l16_n357(x) + if (x < 1) + fun_l17_n604(x) + else + fun_l17_n241(x) + end +end + +def fun_l16_n358(x) + if (x < 1) + fun_l17_n156(x) + else + fun_l17_n832(x) + end +end + +def fun_l16_n359(x) + if (x < 1) + fun_l17_n335(x) + else + fun_l17_n115(x) + end +end + +def fun_l16_n360(x) + if (x < 1) + fun_l17_n563(x) + else + fun_l17_n779(x) + end +end + +def fun_l16_n361(x) + if (x < 1) + fun_l17_n280(x) + else + fun_l17_n946(x) + end +end + +def fun_l16_n362(x) + if (x < 1) + fun_l17_n497(x) + else + fun_l17_n390(x) + end +end + +def fun_l16_n363(x) + if (x < 1) + fun_l17_n59(x) + else + fun_l17_n178(x) + end +end + +def fun_l16_n364(x) + if (x < 1) + fun_l17_n509(x) + else + fun_l17_n963(x) + end +end + +def fun_l16_n365(x) + if (x < 1) + fun_l17_n670(x) + else + fun_l17_n455(x) + end +end + +def fun_l16_n366(x) + if (x < 1) + fun_l17_n852(x) + else + fun_l17_n590(x) + end +end + +def fun_l16_n367(x) + if (x < 1) + fun_l17_n714(x) + else + fun_l17_n98(x) + end +end + +def fun_l16_n368(x) + if (x < 1) + fun_l17_n456(x) + else + fun_l17_n754(x) + end +end + +def fun_l16_n369(x) + if (x < 1) + fun_l17_n809(x) + else + fun_l17_n38(x) + end +end + +def fun_l16_n370(x) + if (x < 1) + fun_l17_n127(x) + else + fun_l17_n395(x) + end +end + +def fun_l16_n371(x) + if (x < 1) + fun_l17_n700(x) + else + fun_l17_n175(x) + end +end + +def fun_l16_n372(x) + if (x < 1) + fun_l17_n705(x) + else + fun_l17_n598(x) + end +end + +def fun_l16_n373(x) + if (x < 1) + fun_l17_n808(x) + else + fun_l17_n253(x) + end +end + +def fun_l16_n374(x) + if (x < 1) + fun_l17_n195(x) + else + fun_l17_n47(x) + end +end + +def fun_l16_n375(x) + if (x < 1) + fun_l17_n124(x) + else + fun_l17_n438(x) + end +end + +def fun_l16_n376(x) + if (x < 1) + fun_l17_n261(x) + else + fun_l17_n317(x) + end +end + +def fun_l16_n377(x) + if (x < 1) + fun_l17_n702(x) + else + fun_l17_n67(x) + end +end + +def fun_l16_n378(x) + if (x < 1) + fun_l17_n194(x) + else + fun_l17_n990(x) + end +end + +def fun_l16_n379(x) + if (x < 1) + fun_l17_n574(x) + else + fun_l17_n379(x) + end +end + +def fun_l16_n380(x) + if (x < 1) + fun_l17_n182(x) + else + fun_l17_n902(x) + end +end + +def fun_l16_n381(x) + if (x < 1) + fun_l17_n963(x) + else + fun_l17_n627(x) + end +end + +def fun_l16_n382(x) + if (x < 1) + fun_l17_n200(x) + else + fun_l17_n889(x) + end +end + +def fun_l16_n383(x) + if (x < 1) + fun_l17_n14(x) + else + fun_l17_n422(x) + end +end + +def fun_l16_n384(x) + if (x < 1) + fun_l17_n543(x) + else + fun_l17_n940(x) + end +end + +def fun_l16_n385(x) + if (x < 1) + fun_l17_n762(x) + else + fun_l17_n493(x) + end +end + +def fun_l16_n386(x) + if (x < 1) + fun_l17_n824(x) + else + fun_l17_n963(x) + end +end + +def fun_l16_n387(x) + if (x < 1) + fun_l17_n298(x) + else + fun_l17_n831(x) + end +end + +def fun_l16_n388(x) + if (x < 1) + fun_l17_n284(x) + else + fun_l17_n784(x) + end +end + +def fun_l16_n389(x) + if (x < 1) + fun_l17_n461(x) + else + fun_l17_n684(x) + end +end + +def fun_l16_n390(x) + if (x < 1) + fun_l17_n829(x) + else + fun_l17_n788(x) + end +end + +def fun_l16_n391(x) + if (x < 1) + fun_l17_n263(x) + else + fun_l17_n21(x) + end +end + +def fun_l16_n392(x) + if (x < 1) + fun_l17_n994(x) + else + fun_l17_n646(x) + end +end + +def fun_l16_n393(x) + if (x < 1) + fun_l17_n438(x) + else + fun_l17_n84(x) + end +end + +def fun_l16_n394(x) + if (x < 1) + fun_l17_n660(x) + else + fun_l17_n269(x) + end +end + +def fun_l16_n395(x) + if (x < 1) + fun_l17_n939(x) + else + fun_l17_n676(x) + end +end + +def fun_l16_n396(x) + if (x < 1) + fun_l17_n608(x) + else + fun_l17_n483(x) + end +end + +def fun_l16_n397(x) + if (x < 1) + fun_l17_n504(x) + else + fun_l17_n499(x) + end +end + +def fun_l16_n398(x) + if (x < 1) + fun_l17_n793(x) + else + fun_l17_n489(x) + end +end + +def fun_l16_n399(x) + if (x < 1) + fun_l17_n28(x) + else + fun_l17_n158(x) + end +end + +def fun_l16_n400(x) + if (x < 1) + fun_l17_n30(x) + else + fun_l17_n21(x) + end +end + +def fun_l16_n401(x) + if (x < 1) + fun_l17_n532(x) + else + fun_l17_n730(x) + end +end + +def fun_l16_n402(x) + if (x < 1) + fun_l17_n593(x) + else + fun_l17_n4(x) + end +end + +def fun_l16_n403(x) + if (x < 1) + fun_l17_n881(x) + else + fun_l17_n956(x) + end +end + +def fun_l16_n404(x) + if (x < 1) + fun_l17_n676(x) + else + fun_l17_n625(x) + end +end + +def fun_l16_n405(x) + if (x < 1) + fun_l17_n192(x) + else + fun_l17_n301(x) + end +end + +def fun_l16_n406(x) + if (x < 1) + fun_l17_n170(x) + else + fun_l17_n970(x) + end +end + +def fun_l16_n407(x) + if (x < 1) + fun_l17_n268(x) + else + fun_l17_n765(x) + end +end + +def fun_l16_n408(x) + if (x < 1) + fun_l17_n310(x) + else + fun_l17_n578(x) + end +end + +def fun_l16_n409(x) + if (x < 1) + fun_l17_n301(x) + else + fun_l17_n870(x) + end +end + +def fun_l16_n410(x) + if (x < 1) + fun_l17_n390(x) + else + fun_l17_n769(x) + end +end + +def fun_l16_n411(x) + if (x < 1) + fun_l17_n973(x) + else + fun_l17_n545(x) + end +end + +def fun_l16_n412(x) + if (x < 1) + fun_l17_n108(x) + else + fun_l17_n731(x) + end +end + +def fun_l16_n413(x) + if (x < 1) + fun_l17_n842(x) + else + fun_l17_n106(x) + end +end + +def fun_l16_n414(x) + if (x < 1) + fun_l17_n10(x) + else + fun_l17_n421(x) + end +end + +def fun_l16_n415(x) + if (x < 1) + fun_l17_n765(x) + else + fun_l17_n584(x) + end +end + +def fun_l16_n416(x) + if (x < 1) + fun_l17_n480(x) + else + fun_l17_n494(x) + end +end + +def fun_l16_n417(x) + if (x < 1) + fun_l17_n977(x) + else + fun_l17_n66(x) + end +end + +def fun_l16_n418(x) + if (x < 1) + fun_l17_n291(x) + else + fun_l17_n161(x) + end +end + +def fun_l16_n419(x) + if (x < 1) + fun_l17_n400(x) + else + fun_l17_n99(x) + end +end + +def fun_l16_n420(x) + if (x < 1) + fun_l17_n621(x) + else + fun_l17_n778(x) + end +end + +def fun_l16_n421(x) + if (x < 1) + fun_l17_n286(x) + else + fun_l17_n784(x) + end +end + +def fun_l16_n422(x) + if (x < 1) + fun_l17_n575(x) + else + fun_l17_n606(x) + end +end + +def fun_l16_n423(x) + if (x < 1) + fun_l17_n459(x) + else + fun_l17_n198(x) + end +end + +def fun_l16_n424(x) + if (x < 1) + fun_l17_n190(x) + else + fun_l17_n597(x) + end +end + +def fun_l16_n425(x) + if (x < 1) + fun_l17_n365(x) + else + fun_l17_n73(x) + end +end + +def fun_l16_n426(x) + if (x < 1) + fun_l17_n769(x) + else + fun_l17_n658(x) + end +end + +def fun_l16_n427(x) + if (x < 1) + fun_l17_n980(x) + else + fun_l17_n594(x) + end +end + +def fun_l16_n428(x) + if (x < 1) + fun_l17_n210(x) + else + fun_l17_n33(x) + end +end + +def fun_l16_n429(x) + if (x < 1) + fun_l17_n585(x) + else + fun_l17_n997(x) + end +end + +def fun_l16_n430(x) + if (x < 1) + fun_l17_n660(x) + else + fun_l17_n883(x) + end +end + +def fun_l16_n431(x) + if (x < 1) + fun_l17_n613(x) + else + fun_l17_n7(x) + end +end + +def fun_l16_n432(x) + if (x < 1) + fun_l17_n764(x) + else + fun_l17_n150(x) + end +end + +def fun_l16_n433(x) + if (x < 1) + fun_l17_n582(x) + else + fun_l17_n197(x) + end +end + +def fun_l16_n434(x) + if (x < 1) + fun_l17_n553(x) + else + fun_l17_n107(x) + end +end + +def fun_l16_n435(x) + if (x < 1) + fun_l17_n975(x) + else + fun_l17_n865(x) + end +end + +def fun_l16_n436(x) + if (x < 1) + fun_l17_n622(x) + else + fun_l17_n351(x) + end +end + +def fun_l16_n437(x) + if (x < 1) + fun_l17_n681(x) + else + fun_l17_n472(x) + end +end + +def fun_l16_n438(x) + if (x < 1) + fun_l17_n329(x) + else + fun_l17_n54(x) + end +end + +def fun_l16_n439(x) + if (x < 1) + fun_l17_n340(x) + else + fun_l17_n567(x) + end +end + +def fun_l16_n440(x) + if (x < 1) + fun_l17_n563(x) + else + fun_l17_n134(x) + end +end + +def fun_l16_n441(x) + if (x < 1) + fun_l17_n194(x) + else + fun_l17_n986(x) + end +end + +def fun_l16_n442(x) + if (x < 1) + fun_l17_n926(x) + else + fun_l17_n35(x) + end +end + +def fun_l16_n443(x) + if (x < 1) + fun_l17_n771(x) + else + fun_l17_n383(x) + end +end + +def fun_l16_n444(x) + if (x < 1) + fun_l17_n682(x) + else + fun_l17_n1(x) + end +end + +def fun_l16_n445(x) + if (x < 1) + fun_l17_n633(x) + else + fun_l17_n757(x) + end +end + +def fun_l16_n446(x) + if (x < 1) + fun_l17_n95(x) + else + fun_l17_n256(x) + end +end + +def fun_l16_n447(x) + if (x < 1) + fun_l17_n183(x) + else + fun_l17_n214(x) + end +end + +def fun_l16_n448(x) + if (x < 1) + fun_l17_n140(x) + else + fun_l17_n371(x) + end +end + +def fun_l16_n449(x) + if (x < 1) + fun_l17_n188(x) + else + fun_l17_n898(x) + end +end + +def fun_l16_n450(x) + if (x < 1) + fun_l17_n710(x) + else + fun_l17_n512(x) + end +end + +def fun_l16_n451(x) + if (x < 1) + fun_l17_n796(x) + else + fun_l17_n56(x) + end +end + +def fun_l16_n452(x) + if (x < 1) + fun_l17_n124(x) + else + fun_l17_n304(x) + end +end + +def fun_l16_n453(x) + if (x < 1) + fun_l17_n150(x) + else + fun_l17_n503(x) + end +end + +def fun_l16_n454(x) + if (x < 1) + fun_l17_n369(x) + else + fun_l17_n623(x) + end +end + +def fun_l16_n455(x) + if (x < 1) + fun_l17_n514(x) + else + fun_l17_n672(x) + end +end + +def fun_l16_n456(x) + if (x < 1) + fun_l17_n80(x) + else + fun_l17_n332(x) + end +end + +def fun_l16_n457(x) + if (x < 1) + fun_l17_n80(x) + else + fun_l17_n32(x) + end +end + +def fun_l16_n458(x) + if (x < 1) + fun_l17_n310(x) + else + fun_l17_n90(x) + end +end + +def fun_l16_n459(x) + if (x < 1) + fun_l17_n730(x) + else + fun_l17_n170(x) + end +end + +def fun_l16_n460(x) + if (x < 1) + fun_l17_n908(x) + else + fun_l17_n865(x) + end +end + +def fun_l16_n461(x) + if (x < 1) + fun_l17_n399(x) + else + fun_l17_n536(x) + end +end + +def fun_l16_n462(x) + if (x < 1) + fun_l17_n123(x) + else + fun_l17_n216(x) + end +end + +def fun_l16_n463(x) + if (x < 1) + fun_l17_n577(x) + else + fun_l17_n757(x) + end +end + +def fun_l16_n464(x) + if (x < 1) + fun_l17_n750(x) + else + fun_l17_n916(x) + end +end + +def fun_l16_n465(x) + if (x < 1) + fun_l17_n621(x) + else + fun_l17_n386(x) + end +end + +def fun_l16_n466(x) + if (x < 1) + fun_l17_n904(x) + else + fun_l17_n732(x) + end +end + +def fun_l16_n467(x) + if (x < 1) + fun_l17_n625(x) + else + fun_l17_n1(x) + end +end + +def fun_l16_n468(x) + if (x < 1) + fun_l17_n762(x) + else + fun_l17_n373(x) + end +end + +def fun_l16_n469(x) + if (x < 1) + fun_l17_n816(x) + else + fun_l17_n490(x) + end +end + +def fun_l16_n470(x) + if (x < 1) + fun_l17_n908(x) + else + fun_l17_n701(x) + end +end + +def fun_l16_n471(x) + if (x < 1) + fun_l17_n690(x) + else + fun_l17_n374(x) + end +end + +def fun_l16_n472(x) + if (x < 1) + fun_l17_n753(x) + else + fun_l17_n625(x) + end +end + +def fun_l16_n473(x) + if (x < 1) + fun_l17_n602(x) + else + fun_l17_n947(x) + end +end + +def fun_l16_n474(x) + if (x < 1) + fun_l17_n565(x) + else + fun_l17_n320(x) + end +end + +def fun_l16_n475(x) + if (x < 1) + fun_l17_n990(x) + else + fun_l17_n431(x) + end +end + +def fun_l16_n476(x) + if (x < 1) + fun_l17_n135(x) + else + fun_l17_n506(x) + end +end + +def fun_l16_n477(x) + if (x < 1) + fun_l17_n57(x) + else + fun_l17_n944(x) + end +end + +def fun_l16_n478(x) + if (x < 1) + fun_l17_n877(x) + else + fun_l17_n28(x) + end +end + +def fun_l16_n479(x) + if (x < 1) + fun_l17_n132(x) + else + fun_l17_n280(x) + end +end + +def fun_l16_n480(x) + if (x < 1) + fun_l17_n514(x) + else + fun_l17_n51(x) + end +end + +def fun_l16_n481(x) + if (x < 1) + fun_l17_n55(x) + else + fun_l17_n366(x) + end +end + +def fun_l16_n482(x) + if (x < 1) + fun_l17_n59(x) + else + fun_l17_n810(x) + end +end + +def fun_l16_n483(x) + if (x < 1) + fun_l17_n965(x) + else + fun_l17_n55(x) + end +end + +def fun_l16_n484(x) + if (x < 1) + fun_l17_n813(x) + else + fun_l17_n408(x) + end +end + +def fun_l16_n485(x) + if (x < 1) + fun_l17_n190(x) + else + fun_l17_n126(x) + end +end + +def fun_l16_n486(x) + if (x < 1) + fun_l17_n479(x) + else + fun_l17_n964(x) + end +end + +def fun_l16_n487(x) + if (x < 1) + fun_l17_n267(x) + else + fun_l17_n867(x) + end +end + +def fun_l16_n488(x) + if (x < 1) + fun_l17_n787(x) + else + fun_l17_n34(x) + end +end + +def fun_l16_n489(x) + if (x < 1) + fun_l17_n223(x) + else + fun_l17_n568(x) + end +end + +def fun_l16_n490(x) + if (x < 1) + fun_l17_n773(x) + else + fun_l17_n11(x) + end +end + +def fun_l16_n491(x) + if (x < 1) + fun_l17_n906(x) + else + fun_l17_n146(x) + end +end + +def fun_l16_n492(x) + if (x < 1) + fun_l17_n221(x) + else + fun_l17_n136(x) + end +end + +def fun_l16_n493(x) + if (x < 1) + fun_l17_n40(x) + else + fun_l17_n599(x) + end +end + +def fun_l16_n494(x) + if (x < 1) + fun_l17_n494(x) + else + fun_l17_n591(x) + end +end + +def fun_l16_n495(x) + if (x < 1) + fun_l17_n237(x) + else + fun_l17_n149(x) + end +end + +def fun_l16_n496(x) + if (x < 1) + fun_l17_n501(x) + else + fun_l17_n681(x) + end +end + +def fun_l16_n497(x) + if (x < 1) + fun_l17_n141(x) + else + fun_l17_n226(x) + end +end + +def fun_l16_n498(x) + if (x < 1) + fun_l17_n868(x) + else + fun_l17_n837(x) + end +end + +def fun_l16_n499(x) + if (x < 1) + fun_l17_n921(x) + else + fun_l17_n806(x) + end +end + +def fun_l16_n500(x) + if (x < 1) + fun_l17_n117(x) + else + fun_l17_n835(x) + end +end + +def fun_l16_n501(x) + if (x < 1) + fun_l17_n872(x) + else + fun_l17_n567(x) + end +end + +def fun_l16_n502(x) + if (x < 1) + fun_l17_n787(x) + else + fun_l17_n785(x) + end +end + +def fun_l16_n503(x) + if (x < 1) + fun_l17_n827(x) + else + fun_l17_n388(x) + end +end + +def fun_l16_n504(x) + if (x < 1) + fun_l17_n328(x) + else + fun_l17_n849(x) + end +end + +def fun_l16_n505(x) + if (x < 1) + fun_l17_n348(x) + else + fun_l17_n580(x) + end +end + +def fun_l16_n506(x) + if (x < 1) + fun_l17_n408(x) + else + fun_l17_n236(x) + end +end + +def fun_l16_n507(x) + if (x < 1) + fun_l17_n959(x) + else + fun_l17_n739(x) + end +end + +def fun_l16_n508(x) + if (x < 1) + fun_l17_n496(x) + else + fun_l17_n774(x) + end +end + +def fun_l16_n509(x) + if (x < 1) + fun_l17_n639(x) + else + fun_l17_n147(x) + end +end + +def fun_l16_n510(x) + if (x < 1) + fun_l17_n910(x) + else + fun_l17_n697(x) + end +end + +def fun_l16_n511(x) + if (x < 1) + fun_l17_n239(x) + else + fun_l17_n691(x) + end +end + +def fun_l16_n512(x) + if (x < 1) + fun_l17_n923(x) + else + fun_l17_n735(x) + end +end + +def fun_l16_n513(x) + if (x < 1) + fun_l17_n911(x) + else + fun_l17_n372(x) + end +end + +def fun_l16_n514(x) + if (x < 1) + fun_l17_n706(x) + else + fun_l17_n27(x) + end +end + +def fun_l16_n515(x) + if (x < 1) + fun_l17_n788(x) + else + fun_l17_n670(x) + end +end + +def fun_l16_n516(x) + if (x < 1) + fun_l17_n507(x) + else + fun_l17_n330(x) + end +end + +def fun_l16_n517(x) + if (x < 1) + fun_l17_n398(x) + else + fun_l17_n997(x) + end +end + +def fun_l16_n518(x) + if (x < 1) + fun_l17_n675(x) + else + fun_l17_n383(x) + end +end + +def fun_l16_n519(x) + if (x < 1) + fun_l17_n193(x) + else + fun_l17_n611(x) + end +end + +def fun_l16_n520(x) + if (x < 1) + fun_l17_n884(x) + else + fun_l17_n200(x) + end +end + +def fun_l16_n521(x) + if (x < 1) + fun_l17_n574(x) + else + fun_l17_n192(x) + end +end + +def fun_l16_n522(x) + if (x < 1) + fun_l17_n883(x) + else + fun_l17_n399(x) + end +end + +def fun_l16_n523(x) + if (x < 1) + fun_l17_n516(x) + else + fun_l17_n592(x) + end +end + +def fun_l16_n524(x) + if (x < 1) + fun_l17_n653(x) + else + fun_l17_n355(x) + end +end + +def fun_l16_n525(x) + if (x < 1) + fun_l17_n872(x) + else + fun_l17_n714(x) + end +end + +def fun_l16_n526(x) + if (x < 1) + fun_l17_n891(x) + else + fun_l17_n70(x) + end +end + +def fun_l16_n527(x) + if (x < 1) + fun_l17_n46(x) + else + fun_l17_n591(x) + end +end + +def fun_l16_n528(x) + if (x < 1) + fun_l17_n969(x) + else + fun_l17_n289(x) + end +end + +def fun_l16_n529(x) + if (x < 1) + fun_l17_n713(x) + else + fun_l17_n775(x) + end +end + +def fun_l16_n530(x) + if (x < 1) + fun_l17_n374(x) + else + fun_l17_n708(x) + end +end + +def fun_l16_n531(x) + if (x < 1) + fun_l17_n996(x) + else + fun_l17_n764(x) + end +end + +def fun_l16_n532(x) + if (x < 1) + fun_l17_n314(x) + else + fun_l17_n445(x) + end +end + +def fun_l16_n533(x) + if (x < 1) + fun_l17_n951(x) + else + fun_l17_n912(x) + end +end + +def fun_l16_n534(x) + if (x < 1) + fun_l17_n760(x) + else + fun_l17_n445(x) + end +end + +def fun_l16_n535(x) + if (x < 1) + fun_l17_n310(x) + else + fun_l17_n16(x) + end +end + +def fun_l16_n536(x) + if (x < 1) + fun_l17_n254(x) + else + fun_l17_n693(x) + end +end + +def fun_l16_n537(x) + if (x < 1) + fun_l17_n631(x) + else + fun_l17_n934(x) + end +end + +def fun_l16_n538(x) + if (x < 1) + fun_l17_n944(x) + else + fun_l17_n922(x) + end +end + +def fun_l16_n539(x) + if (x < 1) + fun_l17_n263(x) + else + fun_l17_n796(x) + end +end + +def fun_l16_n540(x) + if (x < 1) + fun_l17_n928(x) + else + fun_l17_n604(x) + end +end + +def fun_l16_n541(x) + if (x < 1) + fun_l17_n678(x) + else + fun_l17_n880(x) + end +end + +def fun_l16_n542(x) + if (x < 1) + fun_l17_n286(x) + else + fun_l17_n123(x) + end +end + +def fun_l16_n543(x) + if (x < 1) + fun_l17_n604(x) + else + fun_l17_n57(x) + end +end + +def fun_l16_n544(x) + if (x < 1) + fun_l17_n204(x) + else + fun_l17_n950(x) + end +end + +def fun_l16_n545(x) + if (x < 1) + fun_l17_n60(x) + else + fun_l17_n667(x) + end +end + +def fun_l16_n546(x) + if (x < 1) + fun_l17_n472(x) + else + fun_l17_n818(x) + end +end + +def fun_l16_n547(x) + if (x < 1) + fun_l17_n515(x) + else + fun_l17_n180(x) + end +end + +def fun_l16_n548(x) + if (x < 1) + fun_l17_n443(x) + else + fun_l17_n159(x) + end +end + +def fun_l16_n549(x) + if (x < 1) + fun_l17_n820(x) + else + fun_l17_n468(x) + end +end + +def fun_l16_n550(x) + if (x < 1) + fun_l17_n938(x) + else + fun_l17_n307(x) + end +end + +def fun_l16_n551(x) + if (x < 1) + fun_l17_n350(x) + else + fun_l17_n177(x) + end +end + +def fun_l16_n552(x) + if (x < 1) + fun_l17_n761(x) + else + fun_l17_n35(x) + end +end + +def fun_l16_n553(x) + if (x < 1) + fun_l17_n189(x) + else + fun_l17_n991(x) + end +end + +def fun_l16_n554(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n721(x) + end +end + +def fun_l16_n555(x) + if (x < 1) + fun_l17_n42(x) + else + fun_l17_n273(x) + end +end + +def fun_l16_n556(x) + if (x < 1) + fun_l17_n261(x) + else + fun_l17_n328(x) + end +end + +def fun_l16_n557(x) + if (x < 1) + fun_l17_n28(x) + else + fun_l17_n403(x) + end +end + +def fun_l16_n558(x) + if (x < 1) + fun_l17_n766(x) + else + fun_l17_n363(x) + end +end + +def fun_l16_n559(x) + if (x < 1) + fun_l17_n35(x) + else + fun_l17_n648(x) + end +end + +def fun_l16_n560(x) + if (x < 1) + fun_l17_n288(x) + else + fun_l17_n684(x) + end +end + +def fun_l16_n561(x) + if (x < 1) + fun_l17_n529(x) + else + fun_l17_n908(x) + end +end + +def fun_l16_n562(x) + if (x < 1) + fun_l17_n244(x) + else + fun_l17_n342(x) + end +end + +def fun_l16_n563(x) + if (x < 1) + fun_l17_n535(x) + else + fun_l17_n750(x) + end +end + +def fun_l16_n564(x) + if (x < 1) + fun_l17_n761(x) + else + fun_l17_n106(x) + end +end + +def fun_l16_n565(x) + if (x < 1) + fun_l17_n236(x) + else + fun_l17_n95(x) + end +end + +def fun_l16_n566(x) + if (x < 1) + fun_l17_n356(x) + else + fun_l17_n129(x) + end +end + +def fun_l16_n567(x) + if (x < 1) + fun_l17_n297(x) + else + fun_l17_n247(x) + end +end + +def fun_l16_n568(x) + if (x < 1) + fun_l17_n735(x) + else + fun_l17_n781(x) + end +end + +def fun_l16_n569(x) + if (x < 1) + fun_l17_n650(x) + else + fun_l17_n377(x) + end +end + +def fun_l16_n570(x) + if (x < 1) + fun_l17_n872(x) + else + fun_l17_n52(x) + end +end + +def fun_l16_n571(x) + if (x < 1) + fun_l17_n970(x) + else + fun_l17_n719(x) + end +end + +def fun_l16_n572(x) + if (x < 1) + fun_l17_n380(x) + else + fun_l17_n121(x) + end +end + +def fun_l16_n573(x) + if (x < 1) + fun_l17_n190(x) + else + fun_l17_n675(x) + end +end + +def fun_l16_n574(x) + if (x < 1) + fun_l17_n269(x) + else + fun_l17_n362(x) + end +end + +def fun_l16_n575(x) + if (x < 1) + fun_l17_n480(x) + else + fun_l17_n228(x) + end +end + +def fun_l16_n576(x) + if (x < 1) + fun_l17_n791(x) + else + fun_l17_n45(x) + end +end + +def fun_l16_n577(x) + if (x < 1) + fun_l17_n403(x) + else + fun_l17_n887(x) + end +end + +def fun_l16_n578(x) + if (x < 1) + fun_l17_n139(x) + else + fun_l17_n446(x) + end +end + +def fun_l16_n579(x) + if (x < 1) + fun_l17_n472(x) + else + fun_l17_n869(x) + end +end + +def fun_l16_n580(x) + if (x < 1) + fun_l17_n738(x) + else + fun_l17_n298(x) + end +end + +def fun_l16_n581(x) + if (x < 1) + fun_l17_n822(x) + else + fun_l17_n859(x) + end +end + +def fun_l16_n582(x) + if (x < 1) + fun_l17_n768(x) + else + fun_l17_n814(x) + end +end + +def fun_l16_n583(x) + if (x < 1) + fun_l17_n892(x) + else + fun_l17_n821(x) + end +end + +def fun_l16_n584(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n276(x) + end +end + +def fun_l16_n585(x) + if (x < 1) + fun_l17_n162(x) + else + fun_l17_n873(x) + end +end + +def fun_l16_n586(x) + if (x < 1) + fun_l17_n932(x) + else + fun_l17_n227(x) + end +end + +def fun_l16_n587(x) + if (x < 1) + fun_l17_n105(x) + else + fun_l17_n620(x) + end +end + +def fun_l16_n588(x) + if (x < 1) + fun_l17_n137(x) + else + fun_l17_n941(x) + end +end + +def fun_l16_n589(x) + if (x < 1) + fun_l17_n936(x) + else + fun_l17_n877(x) + end +end + +def fun_l16_n590(x) + if (x < 1) + fun_l17_n280(x) + else + fun_l17_n711(x) + end +end + +def fun_l16_n591(x) + if (x < 1) + fun_l17_n968(x) + else + fun_l17_n695(x) + end +end + +def fun_l16_n592(x) + if (x < 1) + fun_l17_n774(x) + else + fun_l17_n674(x) + end +end + +def fun_l16_n593(x) + if (x < 1) + fun_l17_n421(x) + else + fun_l17_n516(x) + end +end + +def fun_l16_n594(x) + if (x < 1) + fun_l17_n830(x) + else + fun_l17_n852(x) + end +end + +def fun_l16_n595(x) + if (x < 1) + fun_l17_n659(x) + else + fun_l17_n114(x) + end +end + +def fun_l16_n596(x) + if (x < 1) + fun_l17_n411(x) + else + fun_l17_n217(x) + end +end + +def fun_l16_n597(x) + if (x < 1) + fun_l17_n506(x) + else + fun_l17_n721(x) + end +end + +def fun_l16_n598(x) + if (x < 1) + fun_l17_n979(x) + else + fun_l17_n579(x) + end +end + +def fun_l16_n599(x) + if (x < 1) + fun_l17_n423(x) + else + fun_l17_n765(x) + end +end + +def fun_l16_n600(x) + if (x < 1) + fun_l17_n138(x) + else + fun_l17_n878(x) + end +end + +def fun_l16_n601(x) + if (x < 1) + fun_l17_n616(x) + else + fun_l17_n531(x) + end +end + +def fun_l16_n602(x) + if (x < 1) + fun_l17_n737(x) + else + fun_l17_n936(x) + end +end + +def fun_l16_n603(x) + if (x < 1) + fun_l17_n106(x) + else + fun_l17_n147(x) + end +end + +def fun_l16_n604(x) + if (x < 1) + fun_l17_n562(x) + else + fun_l17_n852(x) + end +end + +def fun_l16_n605(x) + if (x < 1) + fun_l17_n473(x) + else + fun_l17_n771(x) + end +end + +def fun_l16_n606(x) + if (x < 1) + fun_l17_n778(x) + else + fun_l17_n463(x) + end +end + +def fun_l16_n607(x) + if (x < 1) + fun_l17_n35(x) + else + fun_l17_n341(x) + end +end + +def fun_l16_n608(x) + if (x < 1) + fun_l17_n268(x) + else + fun_l17_n659(x) + end +end + +def fun_l16_n609(x) + if (x < 1) + fun_l17_n734(x) + else + fun_l17_n174(x) + end +end + +def fun_l16_n610(x) + if (x < 1) + fun_l17_n815(x) + else + fun_l17_n798(x) + end +end + +def fun_l16_n611(x) + if (x < 1) + fun_l17_n251(x) + else + fun_l17_n694(x) + end +end + +def fun_l16_n612(x) + if (x < 1) + fun_l17_n597(x) + else + fun_l17_n245(x) + end +end + +def fun_l16_n613(x) + if (x < 1) + fun_l17_n990(x) + else + fun_l17_n58(x) + end +end + +def fun_l16_n614(x) + if (x < 1) + fun_l17_n877(x) + else + fun_l17_n13(x) + end +end + +def fun_l16_n615(x) + if (x < 1) + fun_l17_n7(x) + else + fun_l17_n787(x) + end +end + +def fun_l16_n616(x) + if (x < 1) + fun_l17_n372(x) + else + fun_l17_n643(x) + end +end + +def fun_l16_n617(x) + if (x < 1) + fun_l17_n592(x) + else + fun_l17_n508(x) + end +end + +def fun_l16_n618(x) + if (x < 1) + fun_l17_n928(x) + else + fun_l17_n923(x) + end +end + +def fun_l16_n619(x) + if (x < 1) + fun_l17_n407(x) + else + fun_l17_n885(x) + end +end + +def fun_l16_n620(x) + if (x < 1) + fun_l17_n4(x) + else + fun_l17_n532(x) + end +end + +def fun_l16_n621(x) + if (x < 1) + fun_l17_n791(x) + else + fun_l17_n141(x) + end +end + +def fun_l16_n622(x) + if (x < 1) + fun_l17_n529(x) + else + fun_l17_n140(x) + end +end + +def fun_l16_n623(x) + if (x < 1) + fun_l17_n713(x) + else + fun_l17_n867(x) + end +end + +def fun_l16_n624(x) + if (x < 1) + fun_l17_n148(x) + else + fun_l17_n195(x) + end +end + +def fun_l16_n625(x) + if (x < 1) + fun_l17_n287(x) + else + fun_l17_n662(x) + end +end + +def fun_l16_n626(x) + if (x < 1) + fun_l17_n678(x) + else + fun_l17_n262(x) + end +end + +def fun_l16_n627(x) + if (x < 1) + fun_l17_n217(x) + else + fun_l17_n612(x) + end +end + +def fun_l16_n628(x) + if (x < 1) + fun_l17_n826(x) + else + fun_l17_n164(x) + end +end + +def fun_l16_n629(x) + if (x < 1) + fun_l17_n360(x) + else + fun_l17_n221(x) + end +end + +def fun_l16_n630(x) + if (x < 1) + fun_l17_n842(x) + else + fun_l17_n362(x) + end +end + +def fun_l16_n631(x) + if (x < 1) + fun_l17_n53(x) + else + fun_l17_n216(x) + end +end + +def fun_l16_n632(x) + if (x < 1) + fun_l17_n628(x) + else + fun_l17_n150(x) + end +end + +def fun_l16_n633(x) + if (x < 1) + fun_l17_n206(x) + else + fun_l17_n789(x) + end +end + +def fun_l16_n634(x) + if (x < 1) + fun_l17_n26(x) + else + fun_l17_n376(x) + end +end + +def fun_l16_n635(x) + if (x < 1) + fun_l17_n614(x) + else + fun_l17_n109(x) + end +end + +def fun_l16_n636(x) + if (x < 1) + fun_l17_n626(x) + else + fun_l17_n456(x) + end +end + +def fun_l16_n637(x) + if (x < 1) + fun_l17_n836(x) + else + fun_l17_n602(x) + end +end + +def fun_l16_n638(x) + if (x < 1) + fun_l17_n793(x) + else + fun_l17_n791(x) + end +end + +def fun_l16_n639(x) + if (x < 1) + fun_l17_n689(x) + else + fun_l17_n714(x) + end +end + +def fun_l16_n640(x) + if (x < 1) + fun_l17_n587(x) + else + fun_l17_n203(x) + end +end + +def fun_l16_n641(x) + if (x < 1) + fun_l17_n686(x) + else + fun_l17_n297(x) + end +end + +def fun_l16_n642(x) + if (x < 1) + fun_l17_n394(x) + else + fun_l17_n564(x) + end +end + +def fun_l16_n643(x) + if (x < 1) + fun_l17_n669(x) + else + fun_l17_n250(x) + end +end + +def fun_l16_n644(x) + if (x < 1) + fun_l17_n407(x) + else + fun_l17_n631(x) + end +end + +def fun_l16_n645(x) + if (x < 1) + fun_l17_n928(x) + else + fun_l17_n856(x) + end +end + +def fun_l16_n646(x) + if (x < 1) + fun_l17_n344(x) + else + fun_l17_n529(x) + end +end + +def fun_l16_n647(x) + if (x < 1) + fun_l17_n540(x) + else + fun_l17_n468(x) + end +end + +def fun_l16_n648(x) + if (x < 1) + fun_l17_n831(x) + else + fun_l17_n350(x) + end +end + +def fun_l16_n649(x) + if (x < 1) + fun_l17_n154(x) + else + fun_l17_n587(x) + end +end + +def fun_l16_n650(x) + if (x < 1) + fun_l17_n379(x) + else + fun_l17_n421(x) + end +end + +def fun_l16_n651(x) + if (x < 1) + fun_l17_n839(x) + else + fun_l17_n782(x) + end +end + +def fun_l16_n652(x) + if (x < 1) + fun_l17_n408(x) + else + fun_l17_n923(x) + end +end + +def fun_l16_n653(x) + if (x < 1) + fun_l17_n51(x) + else + fun_l17_n317(x) + end +end + +def fun_l16_n654(x) + if (x < 1) + fun_l17_n635(x) + else + fun_l17_n39(x) + end +end + +def fun_l16_n655(x) + if (x < 1) + fun_l17_n921(x) + else + fun_l17_n641(x) + end +end + +def fun_l16_n656(x) + if (x < 1) + fun_l17_n615(x) + else + fun_l17_n118(x) + end +end + +def fun_l16_n657(x) + if (x < 1) + fun_l17_n673(x) + else + fun_l17_n842(x) + end +end + +def fun_l16_n658(x) + if (x < 1) + fun_l17_n743(x) + else + fun_l17_n594(x) + end +end + +def fun_l16_n659(x) + if (x < 1) + fun_l17_n85(x) + else + fun_l17_n787(x) + end +end + +def fun_l16_n660(x) + if (x < 1) + fun_l17_n363(x) + else + fun_l17_n830(x) + end +end + +def fun_l16_n661(x) + if (x < 1) + fun_l17_n897(x) + else + fun_l17_n989(x) + end +end + +def fun_l16_n662(x) + if (x < 1) + fun_l17_n644(x) + else + fun_l17_n924(x) + end +end + +def fun_l16_n663(x) + if (x < 1) + fun_l17_n812(x) + else + fun_l17_n159(x) + end +end + +def fun_l16_n664(x) + if (x < 1) + fun_l17_n937(x) + else + fun_l17_n720(x) + end +end + +def fun_l16_n665(x) + if (x < 1) + fun_l17_n732(x) + else + fun_l17_n516(x) + end +end + +def fun_l16_n666(x) + if (x < 1) + fun_l17_n399(x) + else + fun_l17_n728(x) + end +end + +def fun_l16_n667(x) + if (x < 1) + fun_l17_n673(x) + else + fun_l17_n735(x) + end +end + +def fun_l16_n668(x) + if (x < 1) + fun_l17_n321(x) + else + fun_l17_n850(x) + end +end + +def fun_l16_n669(x) + if (x < 1) + fun_l17_n873(x) + else + fun_l17_n701(x) + end +end + +def fun_l16_n670(x) + if (x < 1) + fun_l17_n683(x) + else + fun_l17_n903(x) + end +end + +def fun_l16_n671(x) + if (x < 1) + fun_l17_n440(x) + else + fun_l17_n178(x) + end +end + +def fun_l16_n672(x) + if (x < 1) + fun_l17_n619(x) + else + fun_l17_n785(x) + end +end + +def fun_l16_n673(x) + if (x < 1) + fun_l17_n185(x) + else + fun_l17_n794(x) + end +end + +def fun_l16_n674(x) + if (x < 1) + fun_l17_n543(x) + else + fun_l17_n161(x) + end +end + +def fun_l16_n675(x) + if (x < 1) + fun_l17_n898(x) + else + fun_l17_n590(x) + end +end + +def fun_l16_n676(x) + if (x < 1) + fun_l17_n471(x) + else + fun_l17_n66(x) + end +end + +def fun_l16_n677(x) + if (x < 1) + fun_l17_n764(x) + else + fun_l17_n163(x) + end +end + +def fun_l16_n678(x) + if (x < 1) + fun_l17_n290(x) + else + fun_l17_n353(x) + end +end + +def fun_l16_n679(x) + if (x < 1) + fun_l17_n851(x) + else + fun_l17_n7(x) + end +end + +def fun_l16_n680(x) + if (x < 1) + fun_l17_n741(x) + else + fun_l17_n180(x) + end +end + +def fun_l16_n681(x) + if (x < 1) + fun_l17_n887(x) + else + fun_l17_n258(x) + end +end + +def fun_l16_n682(x) + if (x < 1) + fun_l17_n536(x) + else + fun_l17_n84(x) + end +end + +def fun_l16_n683(x) + if (x < 1) + fun_l17_n447(x) + else + fun_l17_n455(x) + end +end + +def fun_l16_n684(x) + if (x < 1) + fun_l17_n23(x) + else + fun_l17_n47(x) + end +end + +def fun_l16_n685(x) + if (x < 1) + fun_l17_n983(x) + else + fun_l17_n470(x) + end +end + +def fun_l16_n686(x) + if (x < 1) + fun_l17_n261(x) + else + fun_l17_n138(x) + end +end + +def fun_l16_n687(x) + if (x < 1) + fun_l17_n791(x) + else + fun_l17_n474(x) + end +end + +def fun_l16_n688(x) + if (x < 1) + fun_l17_n148(x) + else + fun_l17_n317(x) + end +end + +def fun_l16_n689(x) + if (x < 1) + fun_l17_n107(x) + else + fun_l17_n529(x) + end +end + +def fun_l16_n690(x) + if (x < 1) + fun_l17_n310(x) + else + fun_l17_n394(x) + end +end + +def fun_l16_n691(x) + if (x < 1) + fun_l17_n193(x) + else + fun_l17_n348(x) + end +end + +def fun_l16_n692(x) + if (x < 1) + fun_l17_n308(x) + else + fun_l17_n26(x) + end +end + +def fun_l16_n693(x) + if (x < 1) + fun_l17_n502(x) + else + fun_l17_n517(x) + end +end + +def fun_l16_n694(x) + if (x < 1) + fun_l17_n396(x) + else + fun_l17_n886(x) + end +end + +def fun_l16_n695(x) + if (x < 1) + fun_l17_n179(x) + else + fun_l17_n35(x) + end +end + +def fun_l16_n696(x) + if (x < 1) + fun_l17_n431(x) + else + fun_l17_n392(x) + end +end + +def fun_l16_n697(x) + if (x < 1) + fun_l17_n778(x) + else + fun_l17_n766(x) + end +end + +def fun_l16_n698(x) + if (x < 1) + fun_l17_n868(x) + else + fun_l17_n31(x) + end +end + +def fun_l16_n699(x) + if (x < 1) + fun_l17_n277(x) + else + fun_l17_n649(x) + end +end + +def fun_l16_n700(x) + if (x < 1) + fun_l17_n638(x) + else + fun_l17_n411(x) + end +end + +def fun_l16_n701(x) + if (x < 1) + fun_l17_n730(x) + else + fun_l17_n188(x) + end +end + +def fun_l16_n702(x) + if (x < 1) + fun_l17_n530(x) + else + fun_l17_n540(x) + end +end + +def fun_l16_n703(x) + if (x < 1) + fun_l17_n691(x) + else + fun_l17_n550(x) + end +end + +def fun_l16_n704(x) + if (x < 1) + fun_l17_n691(x) + else + fun_l17_n25(x) + end +end + +def fun_l16_n705(x) + if (x < 1) + fun_l17_n744(x) + else + fun_l17_n333(x) + end +end + +def fun_l16_n706(x) + if (x < 1) + fun_l17_n845(x) + else + fun_l17_n229(x) + end +end + +def fun_l16_n707(x) + if (x < 1) + fun_l17_n784(x) + else + fun_l17_n123(x) + end +end + +def fun_l16_n708(x) + if (x < 1) + fun_l17_n88(x) + else + fun_l17_n961(x) + end +end + +def fun_l16_n709(x) + if (x < 1) + fun_l17_n310(x) + else + fun_l17_n943(x) + end +end + +def fun_l16_n710(x) + if (x < 1) + fun_l17_n265(x) + else + fun_l17_n958(x) + end +end + +def fun_l16_n711(x) + if (x < 1) + fun_l17_n483(x) + else + fun_l17_n577(x) + end +end + +def fun_l16_n712(x) + if (x < 1) + fun_l17_n703(x) + else + fun_l17_n625(x) + end +end + +def fun_l16_n713(x) + if (x < 1) + fun_l17_n301(x) + else + fun_l17_n17(x) + end +end + +def fun_l16_n714(x) + if (x < 1) + fun_l17_n455(x) + else + fun_l17_n647(x) + end +end + +def fun_l16_n715(x) + if (x < 1) + fun_l17_n628(x) + else + fun_l17_n748(x) + end +end + +def fun_l16_n716(x) + if (x < 1) + fun_l17_n10(x) + else + fun_l17_n632(x) + end +end + +def fun_l16_n717(x) + if (x < 1) + fun_l17_n82(x) + else + fun_l17_n888(x) + end +end + +def fun_l16_n718(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n554(x) + end +end + +def fun_l16_n719(x) + if (x < 1) + fun_l17_n811(x) + else + fun_l17_n46(x) + end +end + +def fun_l16_n720(x) + if (x < 1) + fun_l17_n227(x) + else + fun_l17_n89(x) + end +end + +def fun_l16_n721(x) + if (x < 1) + fun_l17_n780(x) + else + fun_l17_n941(x) + end +end + +def fun_l16_n722(x) + if (x < 1) + fun_l17_n877(x) + else + fun_l17_n262(x) + end +end + +def fun_l16_n723(x) + if (x < 1) + fun_l17_n649(x) + else + fun_l17_n477(x) + end +end + +def fun_l16_n724(x) + if (x < 1) + fun_l17_n902(x) + else + fun_l17_n315(x) + end +end + +def fun_l16_n725(x) + if (x < 1) + fun_l17_n985(x) + else + fun_l17_n232(x) + end +end + +def fun_l16_n726(x) + if (x < 1) + fun_l17_n5(x) + else + fun_l17_n981(x) + end +end + +def fun_l16_n727(x) + if (x < 1) + fun_l17_n730(x) + else + fun_l17_n780(x) + end +end + +def fun_l16_n728(x) + if (x < 1) + fun_l17_n626(x) + else + fun_l17_n272(x) + end +end + +def fun_l16_n729(x) + if (x < 1) + fun_l17_n380(x) + else + fun_l17_n289(x) + end +end + +def fun_l16_n730(x) + if (x < 1) + fun_l17_n711(x) + else + fun_l17_n861(x) + end +end + +def fun_l16_n731(x) + if (x < 1) + fun_l17_n351(x) + else + fun_l17_n948(x) + end +end + +def fun_l16_n732(x) + if (x < 1) + fun_l17_n864(x) + else + fun_l17_n60(x) + end +end + +def fun_l16_n733(x) + if (x < 1) + fun_l17_n974(x) + else + fun_l17_n475(x) + end +end + +def fun_l16_n734(x) + if (x < 1) + fun_l17_n855(x) + else + fun_l17_n988(x) + end +end + +def fun_l16_n735(x) + if (x < 1) + fun_l17_n740(x) + else + fun_l17_n559(x) + end +end + +def fun_l16_n736(x) + if (x < 1) + fun_l17_n449(x) + else + fun_l17_n580(x) + end +end + +def fun_l16_n737(x) + if (x < 1) + fun_l17_n313(x) + else + fun_l17_n462(x) + end +end + +def fun_l16_n738(x) + if (x < 1) + fun_l17_n177(x) + else + fun_l17_n812(x) + end +end + +def fun_l16_n739(x) + if (x < 1) + fun_l17_n518(x) + else + fun_l17_n453(x) + end +end + +def fun_l16_n740(x) + if (x < 1) + fun_l17_n190(x) + else + fun_l17_n722(x) + end +end + +def fun_l16_n741(x) + if (x < 1) + fun_l17_n509(x) + else + fun_l17_n203(x) + end +end + +def fun_l16_n742(x) + if (x < 1) + fun_l17_n901(x) + else + fun_l17_n497(x) + end +end + +def fun_l16_n743(x) + if (x < 1) + fun_l17_n19(x) + else + fun_l17_n789(x) + end +end + +def fun_l16_n744(x) + if (x < 1) + fun_l17_n879(x) + else + fun_l17_n554(x) + end +end + +def fun_l16_n745(x) + if (x < 1) + fun_l17_n106(x) + else + fun_l17_n255(x) + end +end + +def fun_l16_n746(x) + if (x < 1) + fun_l17_n942(x) + else + fun_l17_n701(x) + end +end + +def fun_l16_n747(x) + if (x < 1) + fun_l17_n738(x) + else + fun_l17_n459(x) + end +end + +def fun_l16_n748(x) + if (x < 1) + fun_l17_n984(x) + else + fun_l17_n501(x) + end +end + +def fun_l16_n749(x) + if (x < 1) + fun_l17_n399(x) + else + fun_l17_n165(x) + end +end + +def fun_l16_n750(x) + if (x < 1) + fun_l17_n956(x) + else + fun_l17_n210(x) + end +end + +def fun_l16_n751(x) + if (x < 1) + fun_l17_n549(x) + else + fun_l17_n406(x) + end +end + +def fun_l16_n752(x) + if (x < 1) + fun_l17_n671(x) + else + fun_l17_n809(x) + end +end + +def fun_l16_n753(x) + if (x < 1) + fun_l17_n807(x) + else + fun_l17_n544(x) + end +end + +def fun_l16_n754(x) + if (x < 1) + fun_l17_n150(x) + else + fun_l17_n705(x) + end +end + +def fun_l16_n755(x) + if (x < 1) + fun_l17_n822(x) + else + fun_l17_n627(x) + end +end + +def fun_l16_n756(x) + if (x < 1) + fun_l17_n429(x) + else + fun_l17_n598(x) + end +end + +def fun_l16_n757(x) + if (x < 1) + fun_l17_n327(x) + else + fun_l17_n391(x) + end +end + +def fun_l16_n758(x) + if (x < 1) + fun_l17_n335(x) + else + fun_l17_n779(x) + end +end + +def fun_l16_n759(x) + if (x < 1) + fun_l17_n149(x) + else + fun_l17_n637(x) + end +end + +def fun_l16_n760(x) + if (x < 1) + fun_l17_n83(x) + else + fun_l17_n616(x) + end +end + +def fun_l16_n761(x) + if (x < 1) + fun_l17_n997(x) + else + fun_l17_n189(x) + end +end + +def fun_l16_n762(x) + if (x < 1) + fun_l17_n779(x) + else + fun_l17_n175(x) + end +end + +def fun_l16_n763(x) + if (x < 1) + fun_l17_n73(x) + else + fun_l17_n473(x) + end +end + +def fun_l16_n764(x) + if (x < 1) + fun_l17_n784(x) + else + fun_l17_n415(x) + end +end + +def fun_l16_n765(x) + if (x < 1) + fun_l17_n809(x) + else + fun_l17_n263(x) + end +end + +def fun_l16_n766(x) + if (x < 1) + fun_l17_n114(x) + else + fun_l17_n898(x) + end +end + +def fun_l16_n767(x) + if (x < 1) + fun_l17_n983(x) + else + fun_l17_n114(x) + end +end + +def fun_l16_n768(x) + if (x < 1) + fun_l17_n141(x) + else + fun_l17_n492(x) + end +end + +def fun_l16_n769(x) + if (x < 1) + fun_l17_n216(x) + else + fun_l17_n610(x) + end +end + +def fun_l16_n770(x) + if (x < 1) + fun_l17_n797(x) + else + fun_l17_n164(x) + end +end + +def fun_l16_n771(x) + if (x < 1) + fun_l17_n434(x) + else + fun_l17_n876(x) + end +end + +def fun_l16_n772(x) + if (x < 1) + fun_l17_n165(x) + else + fun_l17_n646(x) + end +end + +def fun_l16_n773(x) + if (x < 1) + fun_l17_n359(x) + else + fun_l17_n754(x) + end +end + +def fun_l16_n774(x) + if (x < 1) + fun_l17_n314(x) + else + fun_l17_n745(x) + end +end + +def fun_l16_n775(x) + if (x < 1) + fun_l17_n35(x) + else + fun_l17_n673(x) + end +end + +def fun_l16_n776(x) + if (x < 1) + fun_l17_n51(x) + else + fun_l17_n708(x) + end +end + +def fun_l16_n777(x) + if (x < 1) + fun_l17_n451(x) + else + fun_l17_n30(x) + end +end + +def fun_l16_n778(x) + if (x < 1) + fun_l17_n821(x) + else + fun_l17_n114(x) + end +end + +def fun_l16_n779(x) + if (x < 1) + fun_l17_n727(x) + else + fun_l17_n71(x) + end +end + +def fun_l16_n780(x) + if (x < 1) + fun_l17_n404(x) + else + fun_l17_n42(x) + end +end + +def fun_l16_n781(x) + if (x < 1) + fun_l17_n926(x) + else + fun_l17_n53(x) + end +end + +def fun_l16_n782(x) + if (x < 1) + fun_l17_n499(x) + else + fun_l17_n429(x) + end +end + +def fun_l16_n783(x) + if (x < 1) + fun_l17_n887(x) + else + fun_l17_n912(x) + end +end + +def fun_l16_n784(x) + if (x < 1) + fun_l17_n900(x) + else + fun_l17_n163(x) + end +end + +def fun_l16_n785(x) + if (x < 1) + fun_l17_n589(x) + else + fun_l17_n271(x) + end +end + +def fun_l16_n786(x) + if (x < 1) + fun_l17_n732(x) + else + fun_l17_n296(x) + end +end + +def fun_l16_n787(x) + if (x < 1) + fun_l17_n711(x) + else + fun_l17_n777(x) + end +end + +def fun_l16_n788(x) + if (x < 1) + fun_l17_n426(x) + else + fun_l17_n291(x) + end +end + +def fun_l16_n789(x) + if (x < 1) + fun_l17_n833(x) + else + fun_l17_n958(x) + end +end + +def fun_l16_n790(x) + if (x < 1) + fun_l17_n680(x) + else + fun_l17_n707(x) + end +end + +def fun_l16_n791(x) + if (x < 1) + fun_l17_n668(x) + else + fun_l17_n727(x) + end +end + +def fun_l16_n792(x) + if (x < 1) + fun_l17_n948(x) + else + fun_l17_n160(x) + end +end + +def fun_l16_n793(x) + if (x < 1) + fun_l17_n847(x) + else + fun_l17_n643(x) + end +end + +def fun_l16_n794(x) + if (x < 1) + fun_l17_n89(x) + else + fun_l17_n704(x) + end +end + +def fun_l16_n795(x) + if (x < 1) + fun_l17_n52(x) + else + fun_l17_n307(x) + end +end + +def fun_l16_n796(x) + if (x < 1) + fun_l17_n632(x) + else + fun_l17_n839(x) + end +end + +def fun_l16_n797(x) + if (x < 1) + fun_l17_n343(x) + else + fun_l17_n969(x) + end +end + +def fun_l16_n798(x) + if (x < 1) + fun_l17_n850(x) + else + fun_l17_n975(x) + end +end + +def fun_l16_n799(x) + if (x < 1) + fun_l17_n119(x) + else + fun_l17_n303(x) + end +end + +def fun_l16_n800(x) + if (x < 1) + fun_l17_n870(x) + else + fun_l17_n4(x) + end +end + +def fun_l16_n801(x) + if (x < 1) + fun_l17_n223(x) + else + fun_l17_n618(x) + end +end + +def fun_l16_n802(x) + if (x < 1) + fun_l17_n183(x) + else + fun_l17_n358(x) + end +end + +def fun_l16_n803(x) + if (x < 1) + fun_l17_n152(x) + else + fun_l17_n76(x) + end +end + +def fun_l16_n804(x) + if (x < 1) + fun_l17_n487(x) + else + fun_l17_n475(x) + end +end + +def fun_l16_n805(x) + if (x < 1) + fun_l17_n900(x) + else + fun_l17_n786(x) + end +end + +def fun_l16_n806(x) + if (x < 1) + fun_l17_n881(x) + else + fun_l17_n523(x) + end +end + +def fun_l16_n807(x) + if (x < 1) + fun_l17_n686(x) + else + fun_l17_n5(x) + end +end + +def fun_l16_n808(x) + if (x < 1) + fun_l17_n841(x) + else + fun_l17_n73(x) + end +end + +def fun_l16_n809(x) + if (x < 1) + fun_l17_n737(x) + else + fun_l17_n590(x) + end +end + +def fun_l16_n810(x) + if (x < 1) + fun_l17_n252(x) + else + fun_l17_n867(x) + end +end + +def fun_l16_n811(x) + if (x < 1) + fun_l17_n333(x) + else + fun_l17_n418(x) + end +end + +def fun_l16_n812(x) + if (x < 1) + fun_l17_n155(x) + else + fun_l17_n104(x) + end +end + +def fun_l16_n813(x) + if (x < 1) + fun_l17_n933(x) + else + fun_l17_n344(x) + end +end + +def fun_l16_n814(x) + if (x < 1) + fun_l17_n107(x) + else + fun_l17_n784(x) + end +end + +def fun_l16_n815(x) + if (x < 1) + fun_l17_n355(x) + else + fun_l17_n184(x) + end +end + +def fun_l16_n816(x) + if (x < 1) + fun_l17_n266(x) + else + fun_l17_n315(x) + end +end + +def fun_l16_n817(x) + if (x < 1) + fun_l17_n821(x) + else + fun_l17_n534(x) + end +end + +def fun_l16_n818(x) + if (x < 1) + fun_l17_n126(x) + else + fun_l17_n712(x) + end +end + +def fun_l16_n819(x) + if (x < 1) + fun_l17_n309(x) + else + fun_l17_n39(x) + end +end + +def fun_l16_n820(x) + if (x < 1) + fun_l17_n629(x) + else + fun_l17_n689(x) + end +end + +def fun_l16_n821(x) + if (x < 1) + fun_l17_n35(x) + else + fun_l17_n250(x) + end +end + +def fun_l16_n822(x) + if (x < 1) + fun_l17_n276(x) + else + fun_l17_n350(x) + end +end + +def fun_l16_n823(x) + if (x < 1) + fun_l17_n775(x) + else + fun_l17_n542(x) + end +end + +def fun_l16_n824(x) + if (x < 1) + fun_l17_n739(x) + else + fun_l17_n441(x) + end +end + +def fun_l16_n825(x) + if (x < 1) + fun_l17_n86(x) + else + fun_l17_n360(x) + end +end + +def fun_l16_n826(x) + if (x < 1) + fun_l17_n196(x) + else + fun_l17_n406(x) + end +end + +def fun_l16_n827(x) + if (x < 1) + fun_l17_n612(x) + else + fun_l17_n471(x) + end +end + +def fun_l16_n828(x) + if (x < 1) + fun_l17_n409(x) + else + fun_l17_n572(x) + end +end + +def fun_l16_n829(x) + if (x < 1) + fun_l17_n347(x) + else + fun_l17_n450(x) + end +end + +def fun_l16_n830(x) + if (x < 1) + fun_l17_n75(x) + else + fun_l17_n185(x) + end +end + +def fun_l16_n831(x) + if (x < 1) + fun_l17_n904(x) + else + fun_l17_n894(x) + end +end + +def fun_l16_n832(x) + if (x < 1) + fun_l17_n889(x) + else + fun_l17_n651(x) + end +end + +def fun_l16_n833(x) + if (x < 1) + fun_l17_n670(x) + else + fun_l17_n216(x) + end +end + +def fun_l16_n834(x) + if (x < 1) + fun_l17_n212(x) + else + fun_l17_n445(x) + end +end + +def fun_l16_n835(x) + if (x < 1) + fun_l17_n453(x) + else + fun_l17_n187(x) + end +end + +def fun_l16_n836(x) + if (x < 1) + fun_l17_n614(x) + else + fun_l17_n203(x) + end +end + +def fun_l16_n837(x) + if (x < 1) + fun_l17_n177(x) + else + fun_l17_n721(x) + end +end + +def fun_l16_n838(x) + if (x < 1) + fun_l17_n910(x) + else + fun_l17_n510(x) + end +end + +def fun_l16_n839(x) + if (x < 1) + fun_l17_n880(x) + else + fun_l17_n365(x) + end +end + +def fun_l16_n840(x) + if (x < 1) + fun_l17_n336(x) + else + fun_l17_n483(x) + end +end + +def fun_l16_n841(x) + if (x < 1) + fun_l17_n83(x) + else + fun_l17_n947(x) + end +end + +def fun_l16_n842(x) + if (x < 1) + fun_l17_n723(x) + else + fun_l17_n209(x) + end +end + +def fun_l16_n843(x) + if (x < 1) + fun_l17_n432(x) + else + fun_l17_n664(x) + end +end + +def fun_l16_n844(x) + if (x < 1) + fun_l17_n906(x) + else + fun_l17_n472(x) + end +end + +def fun_l16_n845(x) + if (x < 1) + fun_l17_n147(x) + else + fun_l17_n623(x) + end +end + +def fun_l16_n846(x) + if (x < 1) + fun_l17_n296(x) + else + fun_l17_n44(x) + end +end + +def fun_l16_n847(x) + if (x < 1) + fun_l17_n498(x) + else + fun_l17_n764(x) + end +end + +def fun_l16_n848(x) + if (x < 1) + fun_l17_n428(x) + else + fun_l17_n575(x) + end +end + +def fun_l16_n849(x) + if (x < 1) + fun_l17_n311(x) + else + fun_l17_n975(x) + end +end + +def fun_l16_n850(x) + if (x < 1) + fun_l17_n482(x) + else + fun_l17_n388(x) + end +end + +def fun_l16_n851(x) + if (x < 1) + fun_l17_n174(x) + else + fun_l17_n190(x) + end +end + +def fun_l16_n852(x) + if (x < 1) + fun_l17_n28(x) + else + fun_l17_n598(x) + end +end + +def fun_l16_n853(x) + if (x < 1) + fun_l17_n142(x) + else + fun_l17_n340(x) + end +end + +def fun_l16_n854(x) + if (x < 1) + fun_l17_n793(x) + else + fun_l17_n226(x) + end +end + +def fun_l16_n855(x) + if (x < 1) + fun_l17_n268(x) + else + fun_l17_n201(x) + end +end + +def fun_l16_n856(x) + if (x < 1) + fun_l17_n52(x) + else + fun_l17_n871(x) + end +end + +def fun_l16_n857(x) + if (x < 1) + fun_l17_n30(x) + else + fun_l17_n673(x) + end +end + +def fun_l16_n858(x) + if (x < 1) + fun_l17_n794(x) + else + fun_l17_n839(x) + end +end + +def fun_l16_n859(x) + if (x < 1) + fun_l17_n162(x) + else + fun_l17_n655(x) + end +end + +def fun_l16_n860(x) + if (x < 1) + fun_l17_n770(x) + else + fun_l17_n879(x) + end +end + +def fun_l16_n861(x) + if (x < 1) + fun_l17_n93(x) + else + fun_l17_n338(x) + end +end + +def fun_l16_n862(x) + if (x < 1) + fun_l17_n468(x) + else + fun_l17_n977(x) + end +end + +def fun_l16_n863(x) + if (x < 1) + fun_l17_n627(x) + else + fun_l17_n296(x) + end +end + +def fun_l16_n864(x) + if (x < 1) + fun_l17_n402(x) + else + fun_l17_n515(x) + end +end + +def fun_l16_n865(x) + if (x < 1) + fun_l17_n793(x) + else + fun_l17_n62(x) + end +end + +def fun_l16_n866(x) + if (x < 1) + fun_l17_n87(x) + else + fun_l17_n532(x) + end +end + +def fun_l16_n867(x) + if (x < 1) + fun_l17_n766(x) + else + fun_l17_n162(x) + end +end + +def fun_l16_n868(x) + if (x < 1) + fun_l17_n214(x) + else + fun_l17_n827(x) + end +end + +def fun_l16_n869(x) + if (x < 1) + fun_l17_n879(x) + else + fun_l17_n285(x) + end +end + +def fun_l16_n870(x) + if (x < 1) + fun_l17_n619(x) + else + fun_l17_n648(x) + end +end + +def fun_l16_n871(x) + if (x < 1) + fun_l17_n150(x) + else + fun_l17_n458(x) + end +end + +def fun_l16_n872(x) + if (x < 1) + fun_l17_n346(x) + else + fun_l17_n824(x) + end +end + +def fun_l16_n873(x) + if (x < 1) + fun_l17_n839(x) + else + fun_l17_n188(x) + end +end + +def fun_l16_n874(x) + if (x < 1) + fun_l17_n202(x) + else + fun_l17_n147(x) + end +end + +def fun_l16_n875(x) + if (x < 1) + fun_l17_n779(x) + else + fun_l17_n217(x) + end +end + +def fun_l16_n876(x) + if (x < 1) + fun_l17_n417(x) + else + fun_l17_n350(x) + end +end + +def fun_l16_n877(x) + if (x < 1) + fun_l17_n971(x) + else + fun_l17_n825(x) + end +end + +def fun_l16_n878(x) + if (x < 1) + fun_l17_n843(x) + else + fun_l17_n431(x) + end +end + +def fun_l16_n879(x) + if (x < 1) + fun_l17_n560(x) + else + fun_l17_n421(x) + end +end + +def fun_l16_n880(x) + if (x < 1) + fun_l17_n399(x) + else + fun_l17_n101(x) + end +end + +def fun_l16_n881(x) + if (x < 1) + fun_l17_n458(x) + else + fun_l17_n805(x) + end +end + +def fun_l16_n882(x) + if (x < 1) + fun_l17_n590(x) + else + fun_l17_n924(x) + end +end + +def fun_l16_n883(x) + if (x < 1) + fun_l17_n753(x) + else + fun_l17_n128(x) + end +end + +def fun_l16_n884(x) + if (x < 1) + fun_l17_n271(x) + else + fun_l17_n366(x) + end +end + +def fun_l16_n885(x) + if (x < 1) + fun_l17_n251(x) + else + fun_l17_n581(x) + end +end + +def fun_l16_n886(x) + if (x < 1) + fun_l17_n82(x) + else + fun_l17_n212(x) + end +end + +def fun_l16_n887(x) + if (x < 1) + fun_l17_n254(x) + else + fun_l17_n476(x) + end +end + +def fun_l16_n888(x) + if (x < 1) + fun_l17_n774(x) + else + fun_l17_n23(x) + end +end + +def fun_l16_n889(x) + if (x < 1) + fun_l17_n258(x) + else + fun_l17_n931(x) + end +end + +def fun_l16_n890(x) + if (x < 1) + fun_l17_n60(x) + else + fun_l17_n267(x) + end +end + +def fun_l16_n891(x) + if (x < 1) + fun_l17_n465(x) + else + fun_l17_n298(x) + end +end + +def fun_l16_n892(x) + if (x < 1) + fun_l17_n284(x) + else + fun_l17_n59(x) + end +end + +def fun_l16_n893(x) + if (x < 1) + fun_l17_n485(x) + else + fun_l17_n19(x) + end +end + +def fun_l16_n894(x) + if (x < 1) + fun_l17_n676(x) + else + fun_l17_n196(x) + end +end + +def fun_l16_n895(x) + if (x < 1) + fun_l17_n894(x) + else + fun_l17_n667(x) + end +end + +def fun_l16_n896(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n115(x) + end +end + +def fun_l16_n897(x) + if (x < 1) + fun_l17_n161(x) + else + fun_l17_n47(x) + end +end + +def fun_l16_n898(x) + if (x < 1) + fun_l17_n598(x) + else + fun_l17_n796(x) + end +end + +def fun_l16_n899(x) + if (x < 1) + fun_l17_n191(x) + else + fun_l17_n36(x) + end +end + +def fun_l16_n900(x) + if (x < 1) + fun_l17_n803(x) + else + fun_l17_n894(x) + end +end + +def fun_l16_n901(x) + if (x < 1) + fun_l17_n225(x) + else + fun_l17_n608(x) + end +end + +def fun_l16_n902(x) + if (x < 1) + fun_l17_n318(x) + else + fun_l17_n667(x) + end +end + +def fun_l16_n903(x) + if (x < 1) + fun_l17_n815(x) + else + fun_l17_n645(x) + end +end + +def fun_l16_n904(x) + if (x < 1) + fun_l17_n891(x) + else + fun_l17_n465(x) + end +end + +def fun_l16_n905(x) + if (x < 1) + fun_l17_n789(x) + else + fun_l17_n573(x) + end +end + +def fun_l16_n906(x) + if (x < 1) + fun_l17_n139(x) + else + fun_l17_n745(x) + end +end + +def fun_l16_n907(x) + if (x < 1) + fun_l17_n632(x) + else + fun_l17_n625(x) + end +end + +def fun_l16_n908(x) + if (x < 1) + fun_l17_n249(x) + else + fun_l17_n279(x) + end +end + +def fun_l16_n909(x) + if (x < 1) + fun_l17_n357(x) + else + fun_l17_n477(x) + end +end + +def fun_l16_n910(x) + if (x < 1) + fun_l17_n796(x) + else + fun_l17_n313(x) + end +end + +def fun_l16_n911(x) + if (x < 1) + fun_l17_n917(x) + else + fun_l17_n775(x) + end +end + +def fun_l16_n912(x) + if (x < 1) + fun_l17_n451(x) + else + fun_l17_n102(x) + end +end + +def fun_l16_n913(x) + if (x < 1) + fun_l17_n782(x) + else + fun_l17_n998(x) + end +end + +def fun_l16_n914(x) + if (x < 1) + fun_l17_n237(x) + else + fun_l17_n586(x) + end +end + +def fun_l16_n915(x) + if (x < 1) + fun_l17_n399(x) + else + fun_l17_n676(x) + end +end + +def fun_l16_n916(x) + if (x < 1) + fun_l17_n65(x) + else + fun_l17_n61(x) + end +end + +def fun_l16_n917(x) + if (x < 1) + fun_l17_n861(x) + else + fun_l17_n72(x) + end +end + +def fun_l16_n918(x) + if (x < 1) + fun_l17_n375(x) + else + fun_l17_n446(x) + end +end + +def fun_l16_n919(x) + if (x < 1) + fun_l17_n776(x) + else + fun_l17_n302(x) + end +end + +def fun_l16_n920(x) + if (x < 1) + fun_l17_n216(x) + else + fun_l17_n804(x) + end +end + +def fun_l16_n921(x) + if (x < 1) + fun_l17_n667(x) + else + fun_l17_n593(x) + end +end + +def fun_l16_n922(x) + if (x < 1) + fun_l17_n499(x) + else + fun_l17_n577(x) + end +end + +def fun_l16_n923(x) + if (x < 1) + fun_l17_n41(x) + else + fun_l17_n316(x) + end +end + +def fun_l16_n924(x) + if (x < 1) + fun_l17_n521(x) + else + fun_l17_n86(x) + end +end + +def fun_l16_n925(x) + if (x < 1) + fun_l17_n695(x) + else + fun_l17_n662(x) + end +end + +def fun_l16_n926(x) + if (x < 1) + fun_l17_n379(x) + else + fun_l17_n58(x) + end +end + +def fun_l16_n927(x) + if (x < 1) + fun_l17_n820(x) + else + fun_l17_n801(x) + end +end + +def fun_l16_n928(x) + if (x < 1) + fun_l17_n175(x) + else + fun_l17_n865(x) + end +end + +def fun_l16_n929(x) + if (x < 1) + fun_l17_n903(x) + else + fun_l17_n644(x) + end +end + +def fun_l16_n930(x) + if (x < 1) + fun_l17_n801(x) + else + fun_l17_n265(x) + end +end + +def fun_l16_n931(x) + if (x < 1) + fun_l17_n292(x) + else + fun_l17_n897(x) + end +end + +def fun_l16_n932(x) + if (x < 1) + fun_l17_n666(x) + else + fun_l17_n531(x) + end +end + +def fun_l16_n933(x) + if (x < 1) + fun_l17_n929(x) + else + fun_l17_n205(x) + end +end + +def fun_l16_n934(x) + if (x < 1) + fun_l17_n557(x) + else + fun_l17_n70(x) + end +end + +def fun_l16_n935(x) + if (x < 1) + fun_l17_n831(x) + else + fun_l17_n194(x) + end +end + +def fun_l16_n936(x) + if (x < 1) + fun_l17_n277(x) + else + fun_l17_n786(x) + end +end + +def fun_l16_n937(x) + if (x < 1) + fun_l17_n464(x) + else + fun_l17_n482(x) + end +end + +def fun_l16_n938(x) + if (x < 1) + fun_l17_n782(x) + else + fun_l17_n60(x) + end +end + +def fun_l16_n939(x) + if (x < 1) + fun_l17_n780(x) + else + fun_l17_n786(x) + end +end + +def fun_l16_n940(x) + if (x < 1) + fun_l17_n201(x) + else + fun_l17_n614(x) + end +end + +def fun_l16_n941(x) + if (x < 1) + fun_l17_n318(x) + else + fun_l17_n210(x) + end +end + +def fun_l16_n942(x) + if (x < 1) + fun_l17_n831(x) + else + fun_l17_n293(x) + end +end + +def fun_l16_n943(x) + if (x < 1) + fun_l17_n368(x) + else + fun_l17_n292(x) + end +end + +def fun_l16_n944(x) + if (x < 1) + fun_l17_n924(x) + else + fun_l17_n20(x) + end +end + +def fun_l16_n945(x) + if (x < 1) + fun_l17_n340(x) + else + fun_l17_n268(x) + end +end + +def fun_l16_n946(x) + if (x < 1) + fun_l17_n913(x) + else + fun_l17_n877(x) + end +end + +def fun_l16_n947(x) + if (x < 1) + fun_l17_n577(x) + else + fun_l17_n973(x) + end +end + +def fun_l16_n948(x) + if (x < 1) + fun_l17_n101(x) + else + fun_l17_n350(x) + end +end + +def fun_l16_n949(x) + if (x < 1) + fun_l17_n1(x) + else + fun_l17_n683(x) + end +end + +def fun_l16_n950(x) + if (x < 1) + fun_l17_n290(x) + else + fun_l17_n30(x) + end +end + +def fun_l16_n951(x) + if (x < 1) + fun_l17_n965(x) + else + fun_l17_n165(x) + end +end + +def fun_l16_n952(x) + if (x < 1) + fun_l17_n532(x) + else + fun_l17_n887(x) + end +end + +def fun_l16_n953(x) + if (x < 1) + fun_l17_n73(x) + else + fun_l17_n82(x) + end +end + +def fun_l16_n954(x) + if (x < 1) + fun_l17_n518(x) + else + fun_l17_n886(x) + end +end + +def fun_l16_n955(x) + if (x < 1) + fun_l17_n990(x) + else + fun_l17_n213(x) + end +end + +def fun_l16_n956(x) + if (x < 1) + fun_l17_n489(x) + else + fun_l17_n937(x) + end +end + +def fun_l16_n957(x) + if (x < 1) + fun_l17_n657(x) + else + fun_l17_n25(x) + end +end + +def fun_l16_n958(x) + if (x < 1) + fun_l17_n988(x) + else + fun_l17_n684(x) + end +end + +def fun_l16_n959(x) + if (x < 1) + fun_l17_n142(x) + else + fun_l17_n291(x) + end +end + +def fun_l16_n960(x) + if (x < 1) + fun_l17_n495(x) + else + fun_l17_n806(x) + end +end + +def fun_l16_n961(x) + if (x < 1) + fun_l17_n92(x) + else + fun_l17_n137(x) + end +end + +def fun_l16_n962(x) + if (x < 1) + fun_l17_n954(x) + else + fun_l17_n943(x) + end +end + +def fun_l16_n963(x) + if (x < 1) + fun_l17_n761(x) + else + fun_l17_n839(x) + end +end + +def fun_l16_n964(x) + if (x < 1) + fun_l17_n591(x) + else + fun_l17_n519(x) + end +end + +def fun_l16_n965(x) + if (x < 1) + fun_l17_n548(x) + else + fun_l17_n190(x) + end +end + +def fun_l16_n966(x) + if (x < 1) + fun_l17_n206(x) + else + fun_l17_n491(x) + end +end + +def fun_l16_n967(x) + if (x < 1) + fun_l17_n895(x) + else + fun_l17_n404(x) + end +end + +def fun_l16_n968(x) + if (x < 1) + fun_l17_n284(x) + else + fun_l17_n715(x) + end +end + +def fun_l16_n969(x) + if (x < 1) + fun_l17_n507(x) + else + fun_l17_n623(x) + end +end + +def fun_l16_n970(x) + if (x < 1) + fun_l17_n415(x) + else + fun_l17_n718(x) + end +end + +def fun_l16_n971(x) + if (x < 1) + fun_l17_n72(x) + else + fun_l17_n938(x) + end +end + +def fun_l16_n972(x) + if (x < 1) + fun_l17_n661(x) + else + fun_l17_n525(x) + end +end + +def fun_l16_n973(x) + if (x < 1) + fun_l17_n314(x) + else + fun_l17_n195(x) + end +end + +def fun_l16_n974(x) + if (x < 1) + fun_l17_n53(x) + else + fun_l17_n562(x) + end +end + +def fun_l16_n975(x) + if (x < 1) + fun_l17_n381(x) + else + fun_l17_n241(x) + end +end + +def fun_l16_n976(x) + if (x < 1) + fun_l17_n919(x) + else + fun_l17_n291(x) + end +end + +def fun_l16_n977(x) + if (x < 1) + fun_l17_n455(x) + else + fun_l17_n773(x) + end +end + +def fun_l16_n978(x) + if (x < 1) + fun_l17_n75(x) + else + fun_l17_n737(x) + end +end + +def fun_l16_n979(x) + if (x < 1) + fun_l17_n68(x) + else + fun_l17_n339(x) + end +end + +def fun_l16_n980(x) + if (x < 1) + fun_l17_n719(x) + else + fun_l17_n464(x) + end +end + +def fun_l16_n981(x) + if (x < 1) + fun_l17_n681(x) + else + fun_l17_n611(x) + end +end + +def fun_l16_n982(x) + if (x < 1) + fun_l17_n367(x) + else + fun_l17_n446(x) + end +end + +def fun_l16_n983(x) + if (x < 1) + fun_l17_n493(x) + else + fun_l17_n958(x) + end +end + +def fun_l16_n984(x) + if (x < 1) + fun_l17_n271(x) + else + fun_l17_n982(x) + end +end + +def fun_l16_n985(x) + if (x < 1) + fun_l17_n136(x) + else + fun_l17_n446(x) + end +end + +def fun_l16_n986(x) + if (x < 1) + fun_l17_n362(x) + else + fun_l17_n114(x) + end +end + +def fun_l16_n987(x) + if (x < 1) + fun_l17_n234(x) + else + fun_l17_n236(x) + end +end + +def fun_l16_n988(x) + if (x < 1) + fun_l17_n339(x) + else + fun_l17_n2(x) + end +end + +def fun_l16_n989(x) + if (x < 1) + fun_l17_n66(x) + else + fun_l17_n378(x) + end +end + +def fun_l16_n990(x) + if (x < 1) + fun_l17_n366(x) + else + fun_l17_n289(x) + end +end + +def fun_l16_n991(x) + if (x < 1) + fun_l17_n977(x) + else + fun_l17_n520(x) + end +end + +def fun_l16_n992(x) + if (x < 1) + fun_l17_n953(x) + else + fun_l17_n254(x) + end +end + +def fun_l16_n993(x) + if (x < 1) + fun_l17_n569(x) + else + fun_l17_n63(x) + end +end + +def fun_l16_n994(x) + if (x < 1) + fun_l17_n844(x) + else + fun_l17_n42(x) + end +end + +def fun_l16_n995(x) + if (x < 1) + fun_l17_n184(x) + else + fun_l17_n371(x) + end +end + +def fun_l16_n996(x) + if (x < 1) + fun_l17_n229(x) + else + fun_l17_n309(x) + end +end + +def fun_l16_n997(x) + if (x < 1) + fun_l17_n468(x) + else + fun_l17_n653(x) + end +end + +def fun_l16_n998(x) + if (x < 1) + fun_l17_n173(x) + else + fun_l17_n709(x) + end +end + +def fun_l16_n999(x) + if (x < 1) + fun_l17_n625(x) + else + fun_l17_n831(x) + end +end + +def fun_l17_n0(x) + if (x < 1) + fun_l18_n495(x) + else + fun_l18_n122(x) + end +end + +def fun_l17_n1(x) + if (x < 1) + fun_l18_n99(x) + else + fun_l18_n84(x) + end +end + +def fun_l17_n2(x) + if (x < 1) + fun_l18_n464(x) + else + fun_l18_n321(x) + end +end + +def fun_l17_n3(x) + if (x < 1) + fun_l18_n391(x) + else + fun_l18_n122(x) + end +end + +def fun_l17_n4(x) + if (x < 1) + fun_l18_n65(x) + else + fun_l18_n514(x) + end +end + +def fun_l17_n5(x) + if (x < 1) + fun_l18_n972(x) + else + fun_l18_n802(x) + end +end + +def fun_l17_n6(x) + if (x < 1) + fun_l18_n577(x) + else + fun_l18_n26(x) + end +end + +def fun_l17_n7(x) + if (x < 1) + fun_l18_n988(x) + else + fun_l18_n403(x) + end +end + +def fun_l17_n8(x) + if (x < 1) + fun_l18_n466(x) + else + fun_l18_n162(x) + end +end + +def fun_l17_n9(x) + if (x < 1) + fun_l18_n30(x) + else + fun_l18_n438(x) + end +end + +def fun_l17_n10(x) + if (x < 1) + fun_l18_n92(x) + else + fun_l18_n365(x) + end +end + +def fun_l17_n11(x) + if (x < 1) + fun_l18_n230(x) + else + fun_l18_n466(x) + end +end + +def fun_l17_n12(x) + if (x < 1) + fun_l18_n274(x) + else + fun_l18_n38(x) + end +end + +def fun_l17_n13(x) + if (x < 1) + fun_l18_n84(x) + else + fun_l18_n951(x) + end +end + +def fun_l17_n14(x) + if (x < 1) + fun_l18_n878(x) + else + fun_l18_n981(x) + end +end + +def fun_l17_n15(x) + if (x < 1) + fun_l18_n592(x) + else + fun_l18_n917(x) + end +end + +def fun_l17_n16(x) + if (x < 1) + fun_l18_n524(x) + else + fun_l18_n812(x) + end +end + +def fun_l17_n17(x) + if (x < 1) + fun_l18_n267(x) + else + fun_l18_n335(x) + end +end + +def fun_l17_n18(x) + if (x < 1) + fun_l18_n427(x) + else + fun_l18_n591(x) + end +end + +def fun_l17_n19(x) + if (x < 1) + fun_l18_n520(x) + else + fun_l18_n240(x) + end +end + +def fun_l17_n20(x) + if (x < 1) + fun_l18_n729(x) + else + fun_l18_n709(x) + end +end + +def fun_l17_n21(x) + if (x < 1) + fun_l18_n100(x) + else + fun_l18_n192(x) + end +end + +def fun_l17_n22(x) + if (x < 1) + fun_l18_n762(x) + else + fun_l18_n373(x) + end +end + +def fun_l17_n23(x) + if (x < 1) + fun_l18_n485(x) + else + fun_l18_n736(x) + end +end + +def fun_l17_n24(x) + if (x < 1) + fun_l18_n743(x) + else + fun_l18_n83(x) + end +end + +def fun_l17_n25(x) + if (x < 1) + fun_l18_n750(x) + else + fun_l18_n545(x) + end +end + +def fun_l17_n26(x) + if (x < 1) + fun_l18_n488(x) + else + fun_l18_n870(x) + end +end + +def fun_l17_n27(x) + if (x < 1) + fun_l18_n0(x) + else + fun_l18_n675(x) + end +end + +def fun_l17_n28(x) + if (x < 1) + fun_l18_n878(x) + else + fun_l18_n32(x) + end +end + +def fun_l17_n29(x) + if (x < 1) + fun_l18_n906(x) + else + fun_l18_n376(x) + end +end + +def fun_l17_n30(x) + if (x < 1) + fun_l18_n182(x) + else + fun_l18_n58(x) + end +end + +def fun_l17_n31(x) + if (x < 1) + fun_l18_n117(x) + else + fun_l18_n592(x) + end +end + +def fun_l17_n32(x) + if (x < 1) + fun_l18_n123(x) + else + fun_l18_n697(x) + end +end + +def fun_l17_n33(x) + if (x < 1) + fun_l18_n672(x) + else + fun_l18_n645(x) + end +end + +def fun_l17_n34(x) + if (x < 1) + fun_l18_n640(x) + else + fun_l18_n280(x) + end +end + +def fun_l17_n35(x) + if (x < 1) + fun_l18_n851(x) + else + fun_l18_n723(x) + end +end + +def fun_l17_n36(x) + if (x < 1) + fun_l18_n968(x) + else + fun_l18_n840(x) + end +end + +def fun_l17_n37(x) + if (x < 1) + fun_l18_n153(x) + else + fun_l18_n979(x) + end +end + +def fun_l17_n38(x) + if (x < 1) + fun_l18_n817(x) + else + fun_l18_n521(x) + end +end + +def fun_l17_n39(x) + if (x < 1) + fun_l18_n742(x) + else + fun_l18_n576(x) + end +end + +def fun_l17_n40(x) + if (x < 1) + fun_l18_n5(x) + else + fun_l18_n998(x) + end +end + +def fun_l17_n41(x) + if (x < 1) + fun_l18_n442(x) + else + fun_l18_n157(x) + end +end + +def fun_l17_n42(x) + if (x < 1) + fun_l18_n832(x) + else + fun_l18_n218(x) + end +end + +def fun_l17_n43(x) + if (x < 1) + fun_l18_n298(x) + else + fun_l18_n132(x) + end +end + +def fun_l17_n44(x) + if (x < 1) + fun_l18_n397(x) + else + fun_l18_n375(x) + end +end + +def fun_l17_n45(x) + if (x < 1) + fun_l18_n974(x) + else + fun_l18_n19(x) + end +end + +def fun_l17_n46(x) + if (x < 1) + fun_l18_n340(x) + else + fun_l18_n506(x) + end +end + +def fun_l17_n47(x) + if (x < 1) + fun_l18_n943(x) + else + fun_l18_n585(x) + end +end + +def fun_l17_n48(x) + if (x < 1) + fun_l18_n756(x) + else + fun_l18_n2(x) + end +end + +def fun_l17_n49(x) + if (x < 1) + fun_l18_n229(x) + else + fun_l18_n313(x) + end +end + +def fun_l17_n50(x) + if (x < 1) + fun_l18_n243(x) + else + fun_l18_n562(x) + end +end + +def fun_l17_n51(x) + if (x < 1) + fun_l18_n231(x) + else + fun_l18_n381(x) + end +end + +def fun_l17_n52(x) + if (x < 1) + fun_l18_n509(x) + else + fun_l18_n693(x) + end +end + +def fun_l17_n53(x) + if (x < 1) + fun_l18_n877(x) + else + fun_l18_n620(x) + end +end + +def fun_l17_n54(x) + if (x < 1) + fun_l18_n435(x) + else + fun_l18_n3(x) + end +end + +def fun_l17_n55(x) + if (x < 1) + fun_l18_n929(x) + else + fun_l18_n640(x) + end +end + +def fun_l17_n56(x) + if (x < 1) + fun_l18_n913(x) + else + fun_l18_n374(x) + end +end + +def fun_l17_n57(x) + if (x < 1) + fun_l18_n174(x) + else + fun_l18_n588(x) + end +end + +def fun_l17_n58(x) + if (x < 1) + fun_l18_n339(x) + else + fun_l18_n860(x) + end +end + +def fun_l17_n59(x) + if (x < 1) + fun_l18_n649(x) + else + fun_l18_n986(x) + end +end + +def fun_l17_n60(x) + if (x < 1) + fun_l18_n326(x) + else + fun_l18_n739(x) + end +end + +def fun_l17_n61(x) + if (x < 1) + fun_l18_n692(x) + else + fun_l18_n673(x) + end +end + +def fun_l17_n62(x) + if (x < 1) + fun_l18_n515(x) + else + fun_l18_n951(x) + end +end + +def fun_l17_n63(x) + if (x < 1) + fun_l18_n502(x) + else + fun_l18_n781(x) + end +end + +def fun_l17_n64(x) + if (x < 1) + fun_l18_n833(x) + else + fun_l18_n235(x) + end +end + +def fun_l17_n65(x) + if (x < 1) + fun_l18_n483(x) + else + fun_l18_n207(x) + end +end + +def fun_l17_n66(x) + if (x < 1) + fun_l18_n292(x) + else + fun_l18_n916(x) + end +end + +def fun_l17_n67(x) + if (x < 1) + fun_l18_n677(x) + else + fun_l18_n937(x) + end +end + +def fun_l17_n68(x) + if (x < 1) + fun_l18_n733(x) + else + fun_l18_n426(x) + end +end + +def fun_l17_n69(x) + if (x < 1) + fun_l18_n186(x) + else + fun_l18_n146(x) + end +end + +def fun_l17_n70(x) + if (x < 1) + fun_l18_n493(x) + else + fun_l18_n418(x) + end +end + +def fun_l17_n71(x) + if (x < 1) + fun_l18_n732(x) + else + fun_l18_n584(x) + end +end + +def fun_l17_n72(x) + if (x < 1) + fun_l18_n774(x) + else + fun_l18_n349(x) + end +end + +def fun_l17_n73(x) + if (x < 1) + fun_l18_n833(x) + else + fun_l18_n142(x) + end +end + +def fun_l17_n74(x) + if (x < 1) + fun_l18_n506(x) + else + fun_l18_n882(x) + end +end + +def fun_l17_n75(x) + if (x < 1) + fun_l18_n856(x) + else + fun_l18_n906(x) + end +end + +def fun_l17_n76(x) + if (x < 1) + fun_l18_n172(x) + else + fun_l18_n426(x) + end +end + +def fun_l17_n77(x) + if (x < 1) + fun_l18_n357(x) + else + fun_l18_n508(x) + end +end + +def fun_l17_n78(x) + if (x < 1) + fun_l18_n25(x) + else + fun_l18_n899(x) + end +end + +def fun_l17_n79(x) + if (x < 1) + fun_l18_n639(x) + else + fun_l18_n644(x) + end +end + +def fun_l17_n80(x) + if (x < 1) + fun_l18_n207(x) + else + fun_l18_n193(x) + end +end + +def fun_l17_n81(x) + if (x < 1) + fun_l18_n200(x) + else + fun_l18_n766(x) + end +end + +def fun_l17_n82(x) + if (x < 1) + fun_l18_n815(x) + else + fun_l18_n533(x) + end +end + +def fun_l17_n83(x) + if (x < 1) + fun_l18_n740(x) + else + fun_l18_n507(x) + end +end + +def fun_l17_n84(x) + if (x < 1) + fun_l18_n484(x) + else + fun_l18_n158(x) + end +end + +def fun_l17_n85(x) + if (x < 1) + fun_l18_n924(x) + else + fun_l18_n963(x) + end +end + +def fun_l17_n86(x) + if (x < 1) + fun_l18_n614(x) + else + fun_l18_n806(x) + end +end + +def fun_l17_n87(x) + if (x < 1) + fun_l18_n553(x) + else + fun_l18_n510(x) + end +end + +def fun_l17_n88(x) + if (x < 1) + fun_l18_n561(x) + else + fun_l18_n860(x) + end +end + +def fun_l17_n89(x) + if (x < 1) + fun_l18_n757(x) + else + fun_l18_n248(x) + end +end + +def fun_l17_n90(x) + if (x < 1) + fun_l18_n616(x) + else + fun_l18_n217(x) + end +end + +def fun_l17_n91(x) + if (x < 1) + fun_l18_n997(x) + else + fun_l18_n861(x) + end +end + +def fun_l17_n92(x) + if (x < 1) + fun_l18_n18(x) + else + fun_l18_n457(x) + end +end + +def fun_l17_n93(x) + if (x < 1) + fun_l18_n264(x) + else + fun_l18_n213(x) + end +end + +def fun_l17_n94(x) + if (x < 1) + fun_l18_n352(x) + else + fun_l18_n304(x) + end +end + +def fun_l17_n95(x) + if (x < 1) + fun_l18_n975(x) + else + fun_l18_n868(x) + end +end + +def fun_l17_n96(x) + if (x < 1) + fun_l18_n859(x) + else + fun_l18_n786(x) + end +end + +def fun_l17_n97(x) + if (x < 1) + fun_l18_n610(x) + else + fun_l18_n423(x) + end +end + +def fun_l17_n98(x) + if (x < 1) + fun_l18_n814(x) + else + fun_l18_n71(x) + end +end + +def fun_l17_n99(x) + if (x < 1) + fun_l18_n897(x) + else + fun_l18_n412(x) + end +end + +def fun_l17_n100(x) + if (x < 1) + fun_l18_n654(x) + else + fun_l18_n600(x) + end +end + +def fun_l17_n101(x) + if (x < 1) + fun_l18_n185(x) + else + fun_l18_n188(x) + end +end + +def fun_l17_n102(x) + if (x < 1) + fun_l18_n262(x) + else + fun_l18_n509(x) + end +end + +def fun_l17_n103(x) + if (x < 1) + fun_l18_n115(x) + else + fun_l18_n497(x) + end +end + +def fun_l17_n104(x) + if (x < 1) + fun_l18_n650(x) + else + fun_l18_n389(x) + end +end + +def fun_l17_n105(x) + if (x < 1) + fun_l18_n939(x) + else + fun_l18_n842(x) + end +end + +def fun_l17_n106(x) + if (x < 1) + fun_l18_n645(x) + else + fun_l18_n34(x) + end +end + +def fun_l17_n107(x) + if (x < 1) + fun_l18_n510(x) + else + fun_l18_n313(x) + end +end + +def fun_l17_n108(x) + if (x < 1) + fun_l18_n377(x) + else + fun_l18_n397(x) + end +end + +def fun_l17_n109(x) + if (x < 1) + fun_l18_n884(x) + else + fun_l18_n380(x) + end +end + +def fun_l17_n110(x) + if (x < 1) + fun_l18_n924(x) + else + fun_l18_n102(x) + end +end + +def fun_l17_n111(x) + if (x < 1) + fun_l18_n856(x) + else + fun_l18_n646(x) + end +end + +def fun_l17_n112(x) + if (x < 1) + fun_l18_n270(x) + else + fun_l18_n345(x) + end +end + +def fun_l17_n113(x) + if (x < 1) + fun_l18_n211(x) + else + fun_l18_n672(x) + end +end + +def fun_l17_n114(x) + if (x < 1) + fun_l18_n947(x) + else + fun_l18_n376(x) + end +end + +def fun_l17_n115(x) + if (x < 1) + fun_l18_n219(x) + else + fun_l18_n927(x) + end +end + +def fun_l17_n116(x) + if (x < 1) + fun_l18_n731(x) + else + fun_l18_n327(x) + end +end + +def fun_l17_n117(x) + if (x < 1) + fun_l18_n512(x) + else + fun_l18_n658(x) + end +end + +def fun_l17_n118(x) + if (x < 1) + fun_l18_n248(x) + else + fun_l18_n661(x) + end +end + +def fun_l17_n119(x) + if (x < 1) + fun_l18_n18(x) + else + fun_l18_n56(x) + end +end + +def fun_l17_n120(x) + if (x < 1) + fun_l18_n441(x) + else + fun_l18_n648(x) + end +end + +def fun_l17_n121(x) + if (x < 1) + fun_l18_n122(x) + else + fun_l18_n717(x) + end +end + +def fun_l17_n122(x) + if (x < 1) + fun_l18_n495(x) + else + fun_l18_n30(x) + end +end + +def fun_l17_n123(x) + if (x < 1) + fun_l18_n418(x) + else + fun_l18_n686(x) + end +end + +def fun_l17_n124(x) + if (x < 1) + fun_l18_n274(x) + else + fun_l18_n300(x) + end +end + +def fun_l17_n125(x) + if (x < 1) + fun_l18_n677(x) + else + fun_l18_n662(x) + end +end + +def fun_l17_n126(x) + if (x < 1) + fun_l18_n448(x) + else + fun_l18_n584(x) + end +end + +def fun_l17_n127(x) + if (x < 1) + fun_l18_n316(x) + else + fun_l18_n507(x) + end +end + +def fun_l17_n128(x) + if (x < 1) + fun_l18_n166(x) + else + fun_l18_n266(x) + end +end + +def fun_l17_n129(x) + if (x < 1) + fun_l18_n890(x) + else + fun_l18_n581(x) + end +end + +def fun_l17_n130(x) + if (x < 1) + fun_l18_n554(x) + else + fun_l18_n925(x) + end +end + +def fun_l17_n131(x) + if (x < 1) + fun_l18_n607(x) + else + fun_l18_n43(x) + end +end + +def fun_l17_n132(x) + if (x < 1) + fun_l18_n747(x) + else + fun_l18_n461(x) + end +end + +def fun_l17_n133(x) + if (x < 1) + fun_l18_n399(x) + else + fun_l18_n436(x) + end +end + +def fun_l17_n134(x) + if (x < 1) + fun_l18_n922(x) + else + fun_l18_n33(x) + end +end + +def fun_l17_n135(x) + if (x < 1) + fun_l18_n719(x) + else + fun_l18_n70(x) + end +end + +def fun_l17_n136(x) + if (x < 1) + fun_l18_n664(x) + else + fun_l18_n842(x) + end +end + +def fun_l17_n137(x) + if (x < 1) + fun_l18_n626(x) + else + fun_l18_n328(x) + end +end + +def fun_l17_n138(x) + if (x < 1) + fun_l18_n64(x) + else + fun_l18_n24(x) + end +end + +def fun_l17_n139(x) + if (x < 1) + fun_l18_n198(x) + else + fun_l18_n658(x) + end +end + +def fun_l17_n140(x) + if (x < 1) + fun_l18_n813(x) + else + fun_l18_n5(x) + end +end + +def fun_l17_n141(x) + if (x < 1) + fun_l18_n8(x) + else + fun_l18_n115(x) + end +end + +def fun_l17_n142(x) + if (x < 1) + fun_l18_n699(x) + else + fun_l18_n135(x) + end +end + +def fun_l17_n143(x) + if (x < 1) + fun_l18_n595(x) + else + fun_l18_n607(x) + end +end + +def fun_l17_n144(x) + if (x < 1) + fun_l18_n650(x) + else + fun_l18_n994(x) + end +end + +def fun_l17_n145(x) + if (x < 1) + fun_l18_n14(x) + else + fun_l18_n798(x) + end +end + +def fun_l17_n146(x) + if (x < 1) + fun_l18_n107(x) + else + fun_l18_n144(x) + end +end + +def fun_l17_n147(x) + if (x < 1) + fun_l18_n923(x) + else + fun_l18_n482(x) + end +end + +def fun_l17_n148(x) + if (x < 1) + fun_l18_n629(x) + else + fun_l18_n224(x) + end +end + +def fun_l17_n149(x) + if (x < 1) + fun_l18_n363(x) + else + fun_l18_n958(x) + end +end + +def fun_l17_n150(x) + if (x < 1) + fun_l18_n143(x) + else + fun_l18_n828(x) + end +end + +def fun_l17_n151(x) + if (x < 1) + fun_l18_n615(x) + else + fun_l18_n561(x) + end +end + +def fun_l17_n152(x) + if (x < 1) + fun_l18_n418(x) + else + fun_l18_n46(x) + end +end + +def fun_l17_n153(x) + if (x < 1) + fun_l18_n331(x) + else + fun_l18_n736(x) + end +end + +def fun_l17_n154(x) + if (x < 1) + fun_l18_n340(x) + else + fun_l18_n221(x) + end +end + +def fun_l17_n155(x) + if (x < 1) + fun_l18_n488(x) + else + fun_l18_n995(x) + end +end + +def fun_l17_n156(x) + if (x < 1) + fun_l18_n500(x) + else + fun_l18_n106(x) + end +end + +def fun_l17_n157(x) + if (x < 1) + fun_l18_n76(x) + else + fun_l18_n147(x) + end +end + +def fun_l17_n158(x) + if (x < 1) + fun_l18_n258(x) + else + fun_l18_n754(x) + end +end + +def fun_l17_n159(x) + if (x < 1) + fun_l18_n174(x) + else + fun_l18_n676(x) + end +end + +def fun_l17_n160(x) + if (x < 1) + fun_l18_n997(x) + else + fun_l18_n662(x) + end +end + +def fun_l17_n161(x) + if (x < 1) + fun_l18_n614(x) + else + fun_l18_n425(x) + end +end + +def fun_l17_n162(x) + if (x < 1) + fun_l18_n943(x) + else + fun_l18_n534(x) + end +end + +def fun_l17_n163(x) + if (x < 1) + fun_l18_n577(x) + else + fun_l18_n670(x) + end +end + +def fun_l17_n164(x) + if (x < 1) + fun_l18_n707(x) + else + fun_l18_n701(x) + end +end + +def fun_l17_n165(x) + if (x < 1) + fun_l18_n316(x) + else + fun_l18_n981(x) + end +end + +def fun_l17_n166(x) + if (x < 1) + fun_l18_n557(x) + else + fun_l18_n710(x) + end +end + +def fun_l17_n167(x) + if (x < 1) + fun_l18_n763(x) + else + fun_l18_n900(x) + end +end + +def fun_l17_n168(x) + if (x < 1) + fun_l18_n818(x) + else + fun_l18_n2(x) + end +end + +def fun_l17_n169(x) + if (x < 1) + fun_l18_n68(x) + else + fun_l18_n894(x) + end +end + +def fun_l17_n170(x) + if (x < 1) + fun_l18_n88(x) + else + fun_l18_n431(x) + end +end + +def fun_l17_n171(x) + if (x < 1) + fun_l18_n530(x) + else + fun_l18_n714(x) + end +end + +def fun_l17_n172(x) + if (x < 1) + fun_l18_n636(x) + else + fun_l18_n747(x) + end +end + +def fun_l17_n173(x) + if (x < 1) + fun_l18_n481(x) + else + fun_l18_n804(x) + end +end + +def fun_l17_n174(x) + if (x < 1) + fun_l18_n591(x) + else + fun_l18_n121(x) + end +end + +def fun_l17_n175(x) + if (x < 1) + fun_l18_n320(x) + else + fun_l18_n881(x) + end +end + +def fun_l17_n176(x) + if (x < 1) + fun_l18_n524(x) + else + fun_l18_n948(x) + end +end + +def fun_l17_n177(x) + if (x < 1) + fun_l18_n540(x) + else + fun_l18_n508(x) + end +end + +def fun_l17_n178(x) + if (x < 1) + fun_l18_n949(x) + else + fun_l18_n492(x) + end +end + +def fun_l17_n179(x) + if (x < 1) + fun_l18_n548(x) + else + fun_l18_n534(x) + end +end + +def fun_l17_n180(x) + if (x < 1) + fun_l18_n591(x) + else + fun_l18_n104(x) + end +end + +def fun_l17_n181(x) + if (x < 1) + fun_l18_n727(x) + else + fun_l18_n144(x) + end +end + +def fun_l17_n182(x) + if (x < 1) + fun_l18_n365(x) + else + fun_l18_n628(x) + end +end + +def fun_l17_n183(x) + if (x < 1) + fun_l18_n32(x) + else + fun_l18_n752(x) + end +end + +def fun_l17_n184(x) + if (x < 1) + fun_l18_n778(x) + else + fun_l18_n929(x) + end +end + +def fun_l17_n185(x) + if (x < 1) + fun_l18_n797(x) + else + fun_l18_n525(x) + end +end + +def fun_l17_n186(x) + if (x < 1) + fun_l18_n800(x) + else + fun_l18_n799(x) + end +end + +def fun_l17_n187(x) + if (x < 1) + fun_l18_n974(x) + else + fun_l18_n982(x) + end +end + +def fun_l17_n188(x) + if (x < 1) + fun_l18_n259(x) + else + fun_l18_n465(x) + end +end + +def fun_l17_n189(x) + if (x < 1) + fun_l18_n905(x) + else + fun_l18_n477(x) + end +end + +def fun_l17_n190(x) + if (x < 1) + fun_l18_n453(x) + else + fun_l18_n894(x) + end +end + +def fun_l17_n191(x) + if (x < 1) + fun_l18_n461(x) + else + fun_l18_n251(x) + end +end + +def fun_l17_n192(x) + if (x < 1) + fun_l18_n377(x) + else + fun_l18_n371(x) + end +end + +def fun_l17_n193(x) + if (x < 1) + fun_l18_n252(x) + else + fun_l18_n493(x) + end +end + +def fun_l17_n194(x) + if (x < 1) + fun_l18_n398(x) + else + fun_l18_n104(x) + end +end + +def fun_l17_n195(x) + if (x < 1) + fun_l18_n791(x) + else + fun_l18_n4(x) + end +end + +def fun_l17_n196(x) + if (x < 1) + fun_l18_n801(x) + else + fun_l18_n429(x) + end +end + +def fun_l17_n197(x) + if (x < 1) + fun_l18_n106(x) + else + fun_l18_n622(x) + end +end + +def fun_l17_n198(x) + if (x < 1) + fun_l18_n581(x) + else + fun_l18_n312(x) + end +end + +def fun_l17_n199(x) + if (x < 1) + fun_l18_n142(x) + else + fun_l18_n296(x) + end +end + +def fun_l17_n200(x) + if (x < 1) + fun_l18_n234(x) + else + fun_l18_n185(x) + end +end + +def fun_l17_n201(x) + if (x < 1) + fun_l18_n486(x) + else + fun_l18_n857(x) + end +end + +def fun_l17_n202(x) + if (x < 1) + fun_l18_n84(x) + else + fun_l18_n718(x) + end +end + +def fun_l17_n203(x) + if (x < 1) + fun_l18_n830(x) + else + fun_l18_n618(x) + end +end + +def fun_l17_n204(x) + if (x < 1) + fun_l18_n860(x) + else + fun_l18_n28(x) + end +end + +def fun_l17_n205(x) + if (x < 1) + fun_l18_n244(x) + else + fun_l18_n575(x) + end +end + +def fun_l17_n206(x) + if (x < 1) + fun_l18_n189(x) + else + fun_l18_n722(x) + end +end + +def fun_l17_n207(x) + if (x < 1) + fun_l18_n164(x) + else + fun_l18_n197(x) + end +end + +def fun_l17_n208(x) + if (x < 1) + fun_l18_n109(x) + else + fun_l18_n392(x) + end +end + +def fun_l17_n209(x) + if (x < 1) + fun_l18_n629(x) + else + fun_l18_n290(x) + end +end + +def fun_l17_n210(x) + if (x < 1) + fun_l18_n637(x) + else + fun_l18_n317(x) + end +end + +def fun_l17_n211(x) + if (x < 1) + fun_l18_n148(x) + else + fun_l18_n702(x) + end +end + +def fun_l17_n212(x) + if (x < 1) + fun_l18_n892(x) + else + fun_l18_n395(x) + end +end + +def fun_l17_n213(x) + if (x < 1) + fun_l18_n457(x) + else + fun_l18_n859(x) + end +end + +def fun_l17_n214(x) + if (x < 1) + fun_l18_n561(x) + else + fun_l18_n295(x) + end +end + +def fun_l17_n215(x) + if (x < 1) + fun_l18_n459(x) + else + fun_l18_n407(x) + end +end + +def fun_l17_n216(x) + if (x < 1) + fun_l18_n761(x) + else + fun_l18_n308(x) + end +end + +def fun_l17_n217(x) + if (x < 1) + fun_l18_n350(x) + else + fun_l18_n680(x) + end +end + +def fun_l17_n218(x) + if (x < 1) + fun_l18_n240(x) + else + fun_l18_n119(x) + end +end + +def fun_l17_n219(x) + if (x < 1) + fun_l18_n538(x) + else + fun_l18_n732(x) + end +end + +def fun_l17_n220(x) + if (x < 1) + fun_l18_n45(x) + else + fun_l18_n643(x) + end +end + +def fun_l17_n221(x) + if (x < 1) + fun_l18_n258(x) + else + fun_l18_n690(x) + end +end + +def fun_l17_n222(x) + if (x < 1) + fun_l18_n288(x) + else + fun_l18_n998(x) + end +end + +def fun_l17_n223(x) + if (x < 1) + fun_l18_n591(x) + else + fun_l18_n278(x) + end +end + +def fun_l17_n224(x) + if (x < 1) + fun_l18_n433(x) + else + fun_l18_n852(x) + end +end + +def fun_l17_n225(x) + if (x < 1) + fun_l18_n51(x) + else + fun_l18_n837(x) + end +end + +def fun_l17_n226(x) + if (x < 1) + fun_l18_n755(x) + else + fun_l18_n949(x) + end +end + +def fun_l17_n227(x) + if (x < 1) + fun_l18_n566(x) + else + fun_l18_n754(x) + end +end + +def fun_l17_n228(x) + if (x < 1) + fun_l18_n915(x) + else + fun_l18_n893(x) + end +end + +def fun_l17_n229(x) + if (x < 1) + fun_l18_n990(x) + else + fun_l18_n208(x) + end +end + +def fun_l17_n230(x) + if (x < 1) + fun_l18_n220(x) + else + fun_l18_n292(x) + end +end + +def fun_l17_n231(x) + if (x < 1) + fun_l18_n39(x) + else + fun_l18_n211(x) + end +end + +def fun_l17_n232(x) + if (x < 1) + fun_l18_n669(x) + else + fun_l18_n818(x) + end +end + +def fun_l17_n233(x) + if (x < 1) + fun_l18_n804(x) + else + fun_l18_n400(x) + end +end + +def fun_l17_n234(x) + if (x < 1) + fun_l18_n198(x) + else + fun_l18_n393(x) + end +end + +def fun_l17_n235(x) + if (x < 1) + fun_l18_n154(x) + else + fun_l18_n980(x) + end +end + +def fun_l17_n236(x) + if (x < 1) + fun_l18_n46(x) + else + fun_l18_n926(x) + end +end + +def fun_l17_n237(x) + if (x < 1) + fun_l18_n158(x) + else + fun_l18_n364(x) + end +end + +def fun_l17_n238(x) + if (x < 1) + fun_l18_n728(x) + else + fun_l18_n864(x) + end +end + +def fun_l17_n239(x) + if (x < 1) + fun_l18_n793(x) + else + fun_l18_n985(x) + end +end + +def fun_l17_n240(x) + if (x < 1) + fun_l18_n619(x) + else + fun_l18_n216(x) + end +end + +def fun_l17_n241(x) + if (x < 1) + fun_l18_n338(x) + else + fun_l18_n289(x) + end +end + +def fun_l17_n242(x) + if (x < 1) + fun_l18_n42(x) + else + fun_l18_n360(x) + end +end + +def fun_l17_n243(x) + if (x < 1) + fun_l18_n883(x) + else + fun_l18_n243(x) + end +end + +def fun_l17_n244(x) + if (x < 1) + fun_l18_n474(x) + else + fun_l18_n236(x) + end +end + +def fun_l17_n245(x) + if (x < 1) + fun_l18_n694(x) + else + fun_l18_n579(x) + end +end + +def fun_l17_n246(x) + if (x < 1) + fun_l18_n787(x) + else + fun_l18_n349(x) + end +end + +def fun_l17_n247(x) + if (x < 1) + fun_l18_n140(x) + else + fun_l18_n894(x) + end +end + +def fun_l17_n248(x) + if (x < 1) + fun_l18_n587(x) + else + fun_l18_n19(x) + end +end + +def fun_l17_n249(x) + if (x < 1) + fun_l18_n7(x) + else + fun_l18_n352(x) + end +end + +def fun_l17_n250(x) + if (x < 1) + fun_l18_n330(x) + else + fun_l18_n779(x) + end +end + +def fun_l17_n251(x) + if (x < 1) + fun_l18_n655(x) + else + fun_l18_n45(x) + end +end + +def fun_l17_n252(x) + if (x < 1) + fun_l18_n263(x) + else + fun_l18_n668(x) + end +end + +def fun_l17_n253(x) + if (x < 1) + fun_l18_n799(x) + else + fun_l18_n141(x) + end +end + +def fun_l17_n254(x) + if (x < 1) + fun_l18_n868(x) + else + fun_l18_n486(x) + end +end + +def fun_l17_n255(x) + if (x < 1) + fun_l18_n238(x) + else + fun_l18_n298(x) + end +end + +def fun_l17_n256(x) + if (x < 1) + fun_l18_n939(x) + else + fun_l18_n977(x) + end +end + +def fun_l17_n257(x) + if (x < 1) + fun_l18_n999(x) + else + fun_l18_n241(x) + end +end + +def fun_l17_n258(x) + if (x < 1) + fun_l18_n362(x) + else + fun_l18_n19(x) + end +end + +def fun_l17_n259(x) + if (x < 1) + fun_l18_n166(x) + else + fun_l18_n550(x) + end +end + +def fun_l17_n260(x) + if (x < 1) + fun_l18_n18(x) + else + fun_l18_n453(x) + end +end + +def fun_l17_n261(x) + if (x < 1) + fun_l18_n590(x) + else + fun_l18_n217(x) + end +end + +def fun_l17_n262(x) + if (x < 1) + fun_l18_n703(x) + else + fun_l18_n827(x) + end +end + +def fun_l17_n263(x) + if (x < 1) + fun_l18_n911(x) + else + fun_l18_n869(x) + end +end + +def fun_l17_n264(x) + if (x < 1) + fun_l18_n980(x) + else + fun_l18_n598(x) + end +end + +def fun_l17_n265(x) + if (x < 1) + fun_l18_n751(x) + else + fun_l18_n298(x) + end +end + +def fun_l17_n266(x) + if (x < 1) + fun_l18_n527(x) + else + fun_l18_n392(x) + end +end + +def fun_l17_n267(x) + if (x < 1) + fun_l18_n257(x) + else + fun_l18_n731(x) + end +end + +def fun_l17_n268(x) + if (x < 1) + fun_l18_n254(x) + else + fun_l18_n188(x) + end +end + +def fun_l17_n269(x) + if (x < 1) + fun_l18_n145(x) + else + fun_l18_n987(x) + end +end + +def fun_l17_n270(x) + if (x < 1) + fun_l18_n640(x) + else + fun_l18_n370(x) + end +end + +def fun_l17_n271(x) + if (x < 1) + fun_l18_n767(x) + else + fun_l18_n246(x) + end +end + +def fun_l17_n272(x) + if (x < 1) + fun_l18_n274(x) + else + fun_l18_n851(x) + end +end + +def fun_l17_n273(x) + if (x < 1) + fun_l18_n12(x) + else + fun_l18_n48(x) + end +end + +def fun_l17_n274(x) + if (x < 1) + fun_l18_n389(x) + else + fun_l18_n353(x) + end +end + +def fun_l17_n275(x) + if (x < 1) + fun_l18_n966(x) + else + fun_l18_n248(x) + end +end + +def fun_l17_n276(x) + if (x < 1) + fun_l18_n459(x) + else + fun_l18_n989(x) + end +end + +def fun_l17_n277(x) + if (x < 1) + fun_l18_n416(x) + else + fun_l18_n976(x) + end +end + +def fun_l17_n278(x) + if (x < 1) + fun_l18_n752(x) + else + fun_l18_n282(x) + end +end + +def fun_l17_n279(x) + if (x < 1) + fun_l18_n774(x) + else + fun_l18_n478(x) + end +end + +def fun_l17_n280(x) + if (x < 1) + fun_l18_n713(x) + else + fun_l18_n117(x) + end +end + +def fun_l17_n281(x) + if (x < 1) + fun_l18_n365(x) + else + fun_l18_n932(x) + end +end + +def fun_l17_n282(x) + if (x < 1) + fun_l18_n791(x) + else + fun_l18_n331(x) + end +end + +def fun_l17_n283(x) + if (x < 1) + fun_l18_n955(x) + else + fun_l18_n847(x) + end +end + +def fun_l17_n284(x) + if (x < 1) + fun_l18_n409(x) + else + fun_l18_n681(x) + end +end + +def fun_l17_n285(x) + if (x < 1) + fun_l18_n185(x) + else + fun_l18_n651(x) + end +end + +def fun_l17_n286(x) + if (x < 1) + fun_l18_n894(x) + else + fun_l18_n827(x) + end +end + +def fun_l17_n287(x) + if (x < 1) + fun_l18_n788(x) + else + fun_l18_n794(x) + end +end + +def fun_l17_n288(x) + if (x < 1) + fun_l18_n361(x) + else + fun_l18_n415(x) + end +end + +def fun_l17_n289(x) + if (x < 1) + fun_l18_n357(x) + else + fun_l18_n375(x) + end +end + +def fun_l17_n290(x) + if (x < 1) + fun_l18_n557(x) + else + fun_l18_n85(x) + end +end + +def fun_l17_n291(x) + if (x < 1) + fun_l18_n490(x) + else + fun_l18_n260(x) + end +end + +def fun_l17_n292(x) + if (x < 1) + fun_l18_n21(x) + else + fun_l18_n497(x) + end +end + +def fun_l17_n293(x) + if (x < 1) + fun_l18_n716(x) + else + fun_l18_n94(x) + end +end + +def fun_l17_n294(x) + if (x < 1) + fun_l18_n462(x) + else + fun_l18_n408(x) + end +end + +def fun_l17_n295(x) + if (x < 1) + fun_l18_n87(x) + else + fun_l18_n732(x) + end +end + +def fun_l17_n296(x) + if (x < 1) + fun_l18_n889(x) + else + fun_l18_n755(x) + end +end + +def fun_l17_n297(x) + if (x < 1) + fun_l18_n539(x) + else + fun_l18_n130(x) + end +end + +def fun_l17_n298(x) + if (x < 1) + fun_l18_n729(x) + else + fun_l18_n861(x) + end +end + +def fun_l17_n299(x) + if (x < 1) + fun_l18_n605(x) + else + fun_l18_n408(x) + end +end + +def fun_l17_n300(x) + if (x < 1) + fun_l18_n408(x) + else + fun_l18_n281(x) + end +end + +def fun_l17_n301(x) + if (x < 1) + fun_l18_n793(x) + else + fun_l18_n188(x) + end +end + +def fun_l17_n302(x) + if (x < 1) + fun_l18_n42(x) + else + fun_l18_n970(x) + end +end + +def fun_l17_n303(x) + if (x < 1) + fun_l18_n904(x) + else + fun_l18_n630(x) + end +end + +def fun_l17_n304(x) + if (x < 1) + fun_l18_n142(x) + else + fun_l18_n366(x) + end +end + +def fun_l17_n305(x) + if (x < 1) + fun_l18_n242(x) + else + fun_l18_n111(x) + end +end + +def fun_l17_n306(x) + if (x < 1) + fun_l18_n184(x) + else + fun_l18_n301(x) + end +end + +def fun_l17_n307(x) + if (x < 1) + fun_l18_n297(x) + else + fun_l18_n722(x) + end +end + +def fun_l17_n308(x) + if (x < 1) + fun_l18_n608(x) + else + fun_l18_n502(x) + end +end + +def fun_l17_n309(x) + if (x < 1) + fun_l18_n513(x) + else + fun_l18_n828(x) + end +end + +def fun_l17_n310(x) + if (x < 1) + fun_l18_n5(x) + else + fun_l18_n638(x) + end +end + +def fun_l17_n311(x) + if (x < 1) + fun_l18_n404(x) + else + fun_l18_n510(x) + end +end + +def fun_l17_n312(x) + if (x < 1) + fun_l18_n961(x) + else + fun_l18_n526(x) + end +end + +def fun_l17_n313(x) + if (x < 1) + fun_l18_n795(x) + else + fun_l18_n24(x) + end +end + +def fun_l17_n314(x) + if (x < 1) + fun_l18_n505(x) + else + fun_l18_n526(x) + end +end + +def fun_l17_n315(x) + if (x < 1) + fun_l18_n458(x) + else + fun_l18_n767(x) + end +end + +def fun_l17_n316(x) + if (x < 1) + fun_l18_n778(x) + else + fun_l18_n972(x) + end +end + +def fun_l17_n317(x) + if (x < 1) + fun_l18_n734(x) + else + fun_l18_n289(x) + end +end + +def fun_l17_n318(x) + if (x < 1) + fun_l18_n950(x) + else + fun_l18_n507(x) + end +end + +def fun_l17_n319(x) + if (x < 1) + fun_l18_n597(x) + else + fun_l18_n697(x) + end +end + +def fun_l17_n320(x) + if (x < 1) + fun_l18_n270(x) + else + fun_l18_n323(x) + end +end + +def fun_l17_n321(x) + if (x < 1) + fun_l18_n558(x) + else + fun_l18_n357(x) + end +end + +def fun_l17_n322(x) + if (x < 1) + fun_l18_n948(x) + else + fun_l18_n726(x) + end +end + +def fun_l17_n323(x) + if (x < 1) + fun_l18_n787(x) + else + fun_l18_n89(x) + end +end + +def fun_l17_n324(x) + if (x < 1) + fun_l18_n894(x) + else + fun_l18_n454(x) + end +end + +def fun_l17_n325(x) + if (x < 1) + fun_l18_n173(x) + else + fun_l18_n815(x) + end +end + +def fun_l17_n326(x) + if (x < 1) + fun_l18_n102(x) + else + fun_l18_n261(x) + end +end + +def fun_l17_n327(x) + if (x < 1) + fun_l18_n83(x) + else + fun_l18_n732(x) + end +end + +def fun_l17_n328(x) + if (x < 1) + fun_l18_n675(x) + else + fun_l18_n186(x) + end +end + +def fun_l17_n329(x) + if (x < 1) + fun_l18_n783(x) + else + fun_l18_n481(x) + end +end + +def fun_l17_n330(x) + if (x < 1) + fun_l18_n828(x) + else + fun_l18_n829(x) + end +end + +def fun_l17_n331(x) + if (x < 1) + fun_l18_n195(x) + else + fun_l18_n264(x) + end +end + +def fun_l17_n332(x) + if (x < 1) + fun_l18_n842(x) + else + fun_l18_n198(x) + end +end + +def fun_l17_n333(x) + if (x < 1) + fun_l18_n549(x) + else + fun_l18_n208(x) + end +end + +def fun_l17_n334(x) + if (x < 1) + fun_l18_n976(x) + else + fun_l18_n316(x) + end +end + +def fun_l17_n335(x) + if (x < 1) + fun_l18_n401(x) + else + fun_l18_n105(x) + end +end + +def fun_l17_n336(x) + if (x < 1) + fun_l18_n357(x) + else + fun_l18_n54(x) + end +end + +def fun_l17_n337(x) + if (x < 1) + fun_l18_n685(x) + else + fun_l18_n140(x) + end +end + +def fun_l17_n338(x) + if (x < 1) + fun_l18_n301(x) + else + fun_l18_n167(x) + end +end + +def fun_l17_n339(x) + if (x < 1) + fun_l18_n398(x) + else + fun_l18_n643(x) + end +end + +def fun_l17_n340(x) + if (x < 1) + fun_l18_n147(x) + else + fun_l18_n27(x) + end +end + +def fun_l17_n341(x) + if (x < 1) + fun_l18_n813(x) + else + fun_l18_n935(x) + end +end + +def fun_l17_n342(x) + if (x < 1) + fun_l18_n319(x) + else + fun_l18_n429(x) + end +end + +def fun_l17_n343(x) + if (x < 1) + fun_l18_n957(x) + else + fun_l18_n961(x) + end +end + +def fun_l17_n344(x) + if (x < 1) + fun_l18_n380(x) + else + fun_l18_n604(x) + end +end + +def fun_l17_n345(x) + if (x < 1) + fun_l18_n321(x) + else + fun_l18_n473(x) + end +end + +def fun_l17_n346(x) + if (x < 1) + fun_l18_n346(x) + else + fun_l18_n752(x) + end +end + +def fun_l17_n347(x) + if (x < 1) + fun_l18_n645(x) + else + fun_l18_n511(x) + end +end + +def fun_l17_n348(x) + if (x < 1) + fun_l18_n647(x) + else + fun_l18_n997(x) + end +end + +def fun_l17_n349(x) + if (x < 1) + fun_l18_n291(x) + else + fun_l18_n580(x) + end +end + +def fun_l17_n350(x) + if (x < 1) + fun_l18_n745(x) + else + fun_l18_n402(x) + end +end + +def fun_l17_n351(x) + if (x < 1) + fun_l18_n533(x) + else + fun_l18_n117(x) + end +end + +def fun_l17_n352(x) + if (x < 1) + fun_l18_n490(x) + else + fun_l18_n458(x) + end +end + +def fun_l17_n353(x) + if (x < 1) + fun_l18_n526(x) + else + fun_l18_n311(x) + end +end + +def fun_l17_n354(x) + if (x < 1) + fun_l18_n315(x) + else + fun_l18_n306(x) + end +end + +def fun_l17_n355(x) + if (x < 1) + fun_l18_n349(x) + else + fun_l18_n975(x) + end +end + +def fun_l17_n356(x) + if (x < 1) + fun_l18_n764(x) + else + fun_l18_n897(x) + end +end + +def fun_l17_n357(x) + if (x < 1) + fun_l18_n308(x) + else + fun_l18_n662(x) + end +end + +def fun_l17_n358(x) + if (x < 1) + fun_l18_n7(x) + else + fun_l18_n807(x) + end +end + +def fun_l17_n359(x) + if (x < 1) + fun_l18_n896(x) + else + fun_l18_n277(x) + end +end + +def fun_l17_n360(x) + if (x < 1) + fun_l18_n606(x) + else + fun_l18_n605(x) + end +end + +def fun_l17_n361(x) + if (x < 1) + fun_l18_n971(x) + else + fun_l18_n59(x) + end +end + +def fun_l17_n362(x) + if (x < 1) + fun_l18_n304(x) + else + fun_l18_n604(x) + end +end + +def fun_l17_n363(x) + if (x < 1) + fun_l18_n607(x) + else + fun_l18_n758(x) + end +end + +def fun_l17_n364(x) + if (x < 1) + fun_l18_n454(x) + else + fun_l18_n635(x) + end +end + +def fun_l17_n365(x) + if (x < 1) + fun_l18_n287(x) + else + fun_l18_n979(x) + end +end + +def fun_l17_n366(x) + if (x < 1) + fun_l18_n708(x) + else + fun_l18_n480(x) + end +end + +def fun_l17_n367(x) + if (x < 1) + fun_l18_n925(x) + else + fun_l18_n96(x) + end +end + +def fun_l17_n368(x) + if (x < 1) + fun_l18_n756(x) + else + fun_l18_n765(x) + end +end + +def fun_l17_n369(x) + if (x < 1) + fun_l18_n134(x) + else + fun_l18_n320(x) + end +end + +def fun_l17_n370(x) + if (x < 1) + fun_l18_n167(x) + else + fun_l18_n112(x) + end +end + +def fun_l17_n371(x) + if (x < 1) + fun_l18_n393(x) + else + fun_l18_n701(x) + end +end + +def fun_l17_n372(x) + if (x < 1) + fun_l18_n363(x) + else + fun_l18_n934(x) + end +end + +def fun_l17_n373(x) + if (x < 1) + fun_l18_n431(x) + else + fun_l18_n343(x) + end +end + +def fun_l17_n374(x) + if (x < 1) + fun_l18_n111(x) + else + fun_l18_n689(x) + end +end + +def fun_l17_n375(x) + if (x < 1) + fun_l18_n609(x) + else + fun_l18_n814(x) + end +end + +def fun_l17_n376(x) + if (x < 1) + fun_l18_n9(x) + else + fun_l18_n711(x) + end +end + +def fun_l17_n377(x) + if (x < 1) + fun_l18_n270(x) + else + fun_l18_n455(x) + end +end + +def fun_l17_n378(x) + if (x < 1) + fun_l18_n432(x) + else + fun_l18_n348(x) + end +end + +def fun_l17_n379(x) + if (x < 1) + fun_l18_n646(x) + else + fun_l18_n934(x) + end +end + +def fun_l17_n380(x) + if (x < 1) + fun_l18_n737(x) + else + fun_l18_n472(x) + end +end + +def fun_l17_n381(x) + if (x < 1) + fun_l18_n163(x) + else + fun_l18_n533(x) + end +end + +def fun_l17_n382(x) + if (x < 1) + fun_l18_n71(x) + else + fun_l18_n343(x) + end +end + +def fun_l17_n383(x) + if (x < 1) + fun_l18_n52(x) + else + fun_l18_n0(x) + end +end + +def fun_l17_n384(x) + if (x < 1) + fun_l18_n708(x) + else + fun_l18_n616(x) + end +end + +def fun_l17_n385(x) + if (x < 1) + fun_l18_n525(x) + else + fun_l18_n818(x) + end +end + +def fun_l17_n386(x) + if (x < 1) + fun_l18_n154(x) + else + fun_l18_n588(x) + end +end + +def fun_l17_n387(x) + if (x < 1) + fun_l18_n295(x) + else + fun_l18_n462(x) + end +end + +def fun_l17_n388(x) + if (x < 1) + fun_l18_n331(x) + else + fun_l18_n773(x) + end +end + +def fun_l17_n389(x) + if (x < 1) + fun_l18_n221(x) + else + fun_l18_n168(x) + end +end + +def fun_l17_n390(x) + if (x < 1) + fun_l18_n575(x) + else + fun_l18_n284(x) + end +end + +def fun_l17_n391(x) + if (x < 1) + fun_l18_n936(x) + else + fun_l18_n71(x) + end +end + +def fun_l17_n392(x) + if (x < 1) + fun_l18_n123(x) + else + fun_l18_n863(x) + end +end + +def fun_l17_n393(x) + if (x < 1) + fun_l18_n664(x) + else + fun_l18_n189(x) + end +end + +def fun_l17_n394(x) + if (x < 1) + fun_l18_n456(x) + else + fun_l18_n476(x) + end +end + +def fun_l17_n395(x) + if (x < 1) + fun_l18_n557(x) + else + fun_l18_n877(x) + end +end + +def fun_l17_n396(x) + if (x < 1) + fun_l18_n192(x) + else + fun_l18_n312(x) + end +end + +def fun_l17_n397(x) + if (x < 1) + fun_l18_n87(x) + else + fun_l18_n56(x) + end +end + +def fun_l17_n398(x) + if (x < 1) + fun_l18_n769(x) + else + fun_l18_n597(x) + end +end + +def fun_l17_n399(x) + if (x < 1) + fun_l18_n534(x) + else + fun_l18_n366(x) + end +end + +def fun_l17_n400(x) + if (x < 1) + fun_l18_n284(x) + else + fun_l18_n503(x) + end +end + +def fun_l17_n401(x) + if (x < 1) + fun_l18_n655(x) + else + fun_l18_n242(x) + end +end + +def fun_l17_n402(x) + if (x < 1) + fun_l18_n491(x) + else + fun_l18_n81(x) + end +end + +def fun_l17_n403(x) + if (x < 1) + fun_l18_n861(x) + else + fun_l18_n372(x) + end +end + +def fun_l17_n404(x) + if (x < 1) + fun_l18_n600(x) + else + fun_l18_n692(x) + end +end + +def fun_l17_n405(x) + if (x < 1) + fun_l18_n336(x) + else + fun_l18_n778(x) + end +end + +def fun_l17_n406(x) + if (x < 1) + fun_l18_n224(x) + else + fun_l18_n277(x) + end +end + +def fun_l17_n407(x) + if (x < 1) + fun_l18_n630(x) + else + fun_l18_n861(x) + end +end + +def fun_l17_n408(x) + if (x < 1) + fun_l18_n829(x) + else + fun_l18_n213(x) + end +end + +def fun_l17_n409(x) + if (x < 1) + fun_l18_n325(x) + else + fun_l18_n599(x) + end +end + +def fun_l17_n410(x) + if (x < 1) + fun_l18_n850(x) + else + fun_l18_n828(x) + end +end + +def fun_l17_n411(x) + if (x < 1) + fun_l18_n557(x) + else + fun_l18_n757(x) + end +end + +def fun_l17_n412(x) + if (x < 1) + fun_l18_n755(x) + else + fun_l18_n474(x) + end +end + +def fun_l17_n413(x) + if (x < 1) + fun_l18_n945(x) + else + fun_l18_n113(x) + end +end + +def fun_l17_n414(x) + if (x < 1) + fun_l18_n584(x) + else + fun_l18_n815(x) + end +end + +def fun_l17_n415(x) + if (x < 1) + fun_l18_n136(x) + else + fun_l18_n997(x) + end +end + +def fun_l17_n416(x) + if (x < 1) + fun_l18_n57(x) + else + fun_l18_n361(x) + end +end + +def fun_l17_n417(x) + if (x < 1) + fun_l18_n3(x) + else + fun_l18_n882(x) + end +end + +def fun_l17_n418(x) + if (x < 1) + fun_l18_n578(x) + else + fun_l18_n719(x) + end +end + +def fun_l17_n419(x) + if (x < 1) + fun_l18_n426(x) + else + fun_l18_n958(x) + end +end + +def fun_l17_n420(x) + if (x < 1) + fun_l18_n384(x) + else + fun_l18_n182(x) + end +end + +def fun_l17_n421(x) + if (x < 1) + fun_l18_n458(x) + else + fun_l18_n314(x) + end +end + +def fun_l17_n422(x) + if (x < 1) + fun_l18_n641(x) + else + fun_l18_n678(x) + end +end + +def fun_l17_n423(x) + if (x < 1) + fun_l18_n790(x) + else + fun_l18_n830(x) + end +end + +def fun_l17_n424(x) + if (x < 1) + fun_l18_n207(x) + else + fun_l18_n686(x) + end +end + +def fun_l17_n425(x) + if (x < 1) + fun_l18_n847(x) + else + fun_l18_n387(x) + end +end + +def fun_l17_n426(x) + if (x < 1) + fun_l18_n744(x) + else + fun_l18_n9(x) + end +end + +def fun_l17_n427(x) + if (x < 1) + fun_l18_n446(x) + else + fun_l18_n533(x) + end +end + +def fun_l17_n428(x) + if (x < 1) + fun_l18_n910(x) + else + fun_l18_n749(x) + end +end + +def fun_l17_n429(x) + if (x < 1) + fun_l18_n918(x) + else + fun_l18_n260(x) + end +end + +def fun_l17_n430(x) + if (x < 1) + fun_l18_n812(x) + else + fun_l18_n545(x) + end +end + +def fun_l17_n431(x) + if (x < 1) + fun_l18_n191(x) + else + fun_l18_n260(x) + end +end + +def fun_l17_n432(x) + if (x < 1) + fun_l18_n155(x) + else + fun_l18_n582(x) + end +end + +def fun_l17_n433(x) + if (x < 1) + fun_l18_n374(x) + else + fun_l18_n991(x) + end +end + +def fun_l17_n434(x) + if (x < 1) + fun_l18_n611(x) + else + fun_l18_n334(x) + end +end + +def fun_l17_n435(x) + if (x < 1) + fun_l18_n876(x) + else + fun_l18_n386(x) + end +end + +def fun_l17_n436(x) + if (x < 1) + fun_l18_n985(x) + else + fun_l18_n874(x) + end +end + +def fun_l17_n437(x) + if (x < 1) + fun_l18_n715(x) + else + fun_l18_n52(x) + end +end + +def fun_l17_n438(x) + if (x < 1) + fun_l18_n53(x) + else + fun_l18_n15(x) + end +end + +def fun_l17_n439(x) + if (x < 1) + fun_l18_n689(x) + else + fun_l18_n498(x) + end +end + +def fun_l17_n440(x) + if (x < 1) + fun_l18_n990(x) + else + fun_l18_n70(x) + end +end + +def fun_l17_n441(x) + if (x < 1) + fun_l18_n369(x) + else + fun_l18_n327(x) + end +end + +def fun_l17_n442(x) + if (x < 1) + fun_l18_n157(x) + else + fun_l18_n917(x) + end +end + +def fun_l17_n443(x) + if (x < 1) + fun_l18_n822(x) + else + fun_l18_n472(x) + end +end + +def fun_l17_n444(x) + if (x < 1) + fun_l18_n465(x) + else + fun_l18_n19(x) + end +end + +def fun_l17_n445(x) + if (x < 1) + fun_l18_n543(x) + else + fun_l18_n499(x) + end +end + +def fun_l17_n446(x) + if (x < 1) + fun_l18_n662(x) + else + fun_l18_n531(x) + end +end + +def fun_l17_n447(x) + if (x < 1) + fun_l18_n452(x) + else + fun_l18_n150(x) + end +end + +def fun_l17_n448(x) + if (x < 1) + fun_l18_n438(x) + else + fun_l18_n552(x) + end +end + +def fun_l17_n449(x) + if (x < 1) + fun_l18_n23(x) + else + fun_l18_n89(x) + end +end + +def fun_l17_n450(x) + if (x < 1) + fun_l18_n896(x) + else + fun_l18_n313(x) + end +end + +def fun_l17_n451(x) + if (x < 1) + fun_l18_n221(x) + else + fun_l18_n622(x) + end +end + +def fun_l17_n452(x) + if (x < 1) + fun_l18_n347(x) + else + fun_l18_n43(x) + end +end + +def fun_l17_n453(x) + if (x < 1) + fun_l18_n695(x) + else + fun_l18_n5(x) + end +end + +def fun_l17_n454(x) + if (x < 1) + fun_l18_n829(x) + else + fun_l18_n409(x) + end +end + +def fun_l17_n455(x) + if (x < 1) + fun_l18_n398(x) + else + fun_l18_n906(x) + end +end + +def fun_l17_n456(x) + if (x < 1) + fun_l18_n983(x) + else + fun_l18_n235(x) + end +end + +def fun_l17_n457(x) + if (x < 1) + fun_l18_n542(x) + else + fun_l18_n819(x) + end +end + +def fun_l17_n458(x) + if (x < 1) + fun_l18_n952(x) + else + fun_l18_n123(x) + end +end + +def fun_l17_n459(x) + if (x < 1) + fun_l18_n249(x) + else + fun_l18_n525(x) + end +end + +def fun_l17_n460(x) + if (x < 1) + fun_l18_n833(x) + else + fun_l18_n657(x) + end +end + +def fun_l17_n461(x) + if (x < 1) + fun_l18_n847(x) + else + fun_l18_n396(x) + end +end + +def fun_l17_n462(x) + if (x < 1) + fun_l18_n611(x) + else + fun_l18_n790(x) + end +end + +def fun_l17_n463(x) + if (x < 1) + fun_l18_n944(x) + else + fun_l18_n655(x) + end +end + +def fun_l17_n464(x) + if (x < 1) + fun_l18_n688(x) + else + fun_l18_n804(x) + end +end + +def fun_l17_n465(x) + if (x < 1) + fun_l18_n29(x) + else + fun_l18_n324(x) + end +end + +def fun_l17_n466(x) + if (x < 1) + fun_l18_n496(x) + else + fun_l18_n76(x) + end +end + +def fun_l17_n467(x) + if (x < 1) + fun_l18_n317(x) + else + fun_l18_n241(x) + end +end + +def fun_l17_n468(x) + if (x < 1) + fun_l18_n759(x) + else + fun_l18_n516(x) + end +end + +def fun_l17_n469(x) + if (x < 1) + fun_l18_n430(x) + else + fun_l18_n355(x) + end +end + +def fun_l17_n470(x) + if (x < 1) + fun_l18_n683(x) + else + fun_l18_n16(x) + end +end + +def fun_l17_n471(x) + if (x < 1) + fun_l18_n46(x) + else + fun_l18_n216(x) + end +end + +def fun_l17_n472(x) + if (x < 1) + fun_l18_n460(x) + else + fun_l18_n460(x) + end +end + +def fun_l17_n473(x) + if (x < 1) + fun_l18_n120(x) + else + fun_l18_n189(x) + end +end + +def fun_l17_n474(x) + if (x < 1) + fun_l18_n663(x) + else + fun_l18_n732(x) + end +end + +def fun_l17_n475(x) + if (x < 1) + fun_l18_n441(x) + else + fun_l18_n460(x) + end +end + +def fun_l17_n476(x) + if (x < 1) + fun_l18_n759(x) + else + fun_l18_n533(x) + end +end + +def fun_l17_n477(x) + if (x < 1) + fun_l18_n105(x) + else + fun_l18_n671(x) + end +end + +def fun_l17_n478(x) + if (x < 1) + fun_l18_n849(x) + else + fun_l18_n316(x) + end +end + +def fun_l17_n479(x) + if (x < 1) + fun_l18_n482(x) + else + fun_l18_n502(x) + end +end + +def fun_l17_n480(x) + if (x < 1) + fun_l18_n335(x) + else + fun_l18_n795(x) + end +end + +def fun_l17_n481(x) + if (x < 1) + fun_l18_n168(x) + else + fun_l18_n799(x) + end +end + +def fun_l17_n482(x) + if (x < 1) + fun_l18_n981(x) + else + fun_l18_n633(x) + end +end + +def fun_l17_n483(x) + if (x < 1) + fun_l18_n873(x) + else + fun_l18_n723(x) + end +end + +def fun_l17_n484(x) + if (x < 1) + fun_l18_n448(x) + else + fun_l18_n954(x) + end +end + +def fun_l17_n485(x) + if (x < 1) + fun_l18_n421(x) + else + fun_l18_n802(x) + end +end + +def fun_l17_n486(x) + if (x < 1) + fun_l18_n477(x) + else + fun_l18_n976(x) + end +end + +def fun_l17_n487(x) + if (x < 1) + fun_l18_n53(x) + else + fun_l18_n298(x) + end +end + +def fun_l17_n488(x) + if (x < 1) + fun_l18_n733(x) + else + fun_l18_n585(x) + end +end + +def fun_l17_n489(x) + if (x < 1) + fun_l18_n684(x) + else + fun_l18_n537(x) + end +end + +def fun_l17_n490(x) + if (x < 1) + fun_l18_n409(x) + else + fun_l18_n178(x) + end +end + +def fun_l17_n491(x) + if (x < 1) + fun_l18_n335(x) + else + fun_l18_n255(x) + end +end + +def fun_l17_n492(x) + if (x < 1) + fun_l18_n798(x) + else + fun_l18_n398(x) + end +end + +def fun_l17_n493(x) + if (x < 1) + fun_l18_n112(x) + else + fun_l18_n83(x) + end +end + +def fun_l17_n494(x) + if (x < 1) + fun_l18_n888(x) + else + fun_l18_n136(x) + end +end + +def fun_l17_n495(x) + if (x < 1) + fun_l18_n726(x) + else + fun_l18_n678(x) + end +end + +def fun_l17_n496(x) + if (x < 1) + fun_l18_n224(x) + else + fun_l18_n625(x) + end +end + +def fun_l17_n497(x) + if (x < 1) + fun_l18_n772(x) + else + fun_l18_n14(x) + end +end + +def fun_l17_n498(x) + if (x < 1) + fun_l18_n646(x) + else + fun_l18_n758(x) + end +end + +def fun_l17_n499(x) + if (x < 1) + fun_l18_n961(x) + else + fun_l18_n570(x) + end +end + +def fun_l17_n500(x) + if (x < 1) + fun_l18_n368(x) + else + fun_l18_n681(x) + end +end + +def fun_l17_n501(x) + if (x < 1) + fun_l18_n768(x) + else + fun_l18_n747(x) + end +end + +def fun_l17_n502(x) + if (x < 1) + fun_l18_n957(x) + else + fun_l18_n851(x) + end +end + +def fun_l17_n503(x) + if (x < 1) + fun_l18_n669(x) + else + fun_l18_n939(x) + end +end + +def fun_l17_n504(x) + if (x < 1) + fun_l18_n969(x) + else + fun_l18_n899(x) + end +end + +def fun_l17_n505(x) + if (x < 1) + fun_l18_n756(x) + else + fun_l18_n29(x) + end +end + +def fun_l17_n506(x) + if (x < 1) + fun_l18_n92(x) + else + fun_l18_n230(x) + end +end + +def fun_l17_n507(x) + if (x < 1) + fun_l18_n670(x) + else + fun_l18_n744(x) + end +end + +def fun_l17_n508(x) + if (x < 1) + fun_l18_n646(x) + else + fun_l18_n900(x) + end +end + +def fun_l17_n509(x) + if (x < 1) + fun_l18_n480(x) + else + fun_l18_n6(x) + end +end + +def fun_l17_n510(x) + if (x < 1) + fun_l18_n141(x) + else + fun_l18_n735(x) + end +end + +def fun_l17_n511(x) + if (x < 1) + fun_l18_n622(x) + else + fun_l18_n617(x) + end +end + +def fun_l17_n512(x) + if (x < 1) + fun_l18_n491(x) + else + fun_l18_n154(x) + end +end + +def fun_l17_n513(x) + if (x < 1) + fun_l18_n931(x) + else + fun_l18_n730(x) + end +end + +def fun_l17_n514(x) + if (x < 1) + fun_l18_n935(x) + else + fun_l18_n51(x) + end +end + +def fun_l17_n515(x) + if (x < 1) + fun_l18_n751(x) + else + fun_l18_n786(x) + end +end + +def fun_l17_n516(x) + if (x < 1) + fun_l18_n538(x) + else + fun_l18_n630(x) + end +end + +def fun_l17_n517(x) + if (x < 1) + fun_l18_n832(x) + else + fun_l18_n932(x) + end +end + +def fun_l17_n518(x) + if (x < 1) + fun_l18_n572(x) + else + fun_l18_n408(x) + end +end + +def fun_l17_n519(x) + if (x < 1) + fun_l18_n961(x) + else + fun_l18_n820(x) + end +end + +def fun_l17_n520(x) + if (x < 1) + fun_l18_n33(x) + else + fun_l18_n655(x) + end +end + +def fun_l17_n521(x) + if (x < 1) + fun_l18_n940(x) + else + fun_l18_n436(x) + end +end + +def fun_l17_n522(x) + if (x < 1) + fun_l18_n471(x) + else + fun_l18_n975(x) + end +end + +def fun_l17_n523(x) + if (x < 1) + fun_l18_n752(x) + else + fun_l18_n640(x) + end +end + +def fun_l17_n524(x) + if (x < 1) + fun_l18_n226(x) + else + fun_l18_n645(x) + end +end + +def fun_l17_n525(x) + if (x < 1) + fun_l18_n986(x) + else + fun_l18_n858(x) + end +end + +def fun_l17_n526(x) + if (x < 1) + fun_l18_n362(x) + else + fun_l18_n842(x) + end +end + +def fun_l17_n527(x) + if (x < 1) + fun_l18_n273(x) + else + fun_l18_n510(x) + end +end + +def fun_l17_n528(x) + if (x < 1) + fun_l18_n728(x) + else + fun_l18_n906(x) + end +end + +def fun_l17_n529(x) + if (x < 1) + fun_l18_n225(x) + else + fun_l18_n988(x) + end +end + +def fun_l17_n530(x) + if (x < 1) + fun_l18_n472(x) + else + fun_l18_n933(x) + end +end + +def fun_l17_n531(x) + if (x < 1) + fun_l18_n105(x) + else + fun_l18_n501(x) + end +end + +def fun_l17_n532(x) + if (x < 1) + fun_l18_n77(x) + else + fun_l18_n616(x) + end +end + +def fun_l17_n533(x) + if (x < 1) + fun_l18_n404(x) + else + fun_l18_n86(x) + end +end + +def fun_l17_n534(x) + if (x < 1) + fun_l18_n312(x) + else + fun_l18_n638(x) + end +end + +def fun_l17_n535(x) + if (x < 1) + fun_l18_n908(x) + else + fun_l18_n697(x) + end +end + +def fun_l17_n536(x) + if (x < 1) + fun_l18_n520(x) + else + fun_l18_n379(x) + end +end + +def fun_l17_n537(x) + if (x < 1) + fun_l18_n15(x) + else + fun_l18_n97(x) + end +end + +def fun_l17_n538(x) + if (x < 1) + fun_l18_n312(x) + else + fun_l18_n981(x) + end +end + +def fun_l17_n539(x) + if (x < 1) + fun_l18_n901(x) + else + fun_l18_n579(x) + end +end + +def fun_l17_n540(x) + if (x < 1) + fun_l18_n569(x) + else + fun_l18_n512(x) + end +end + +def fun_l17_n541(x) + if (x < 1) + fun_l18_n319(x) + else + fun_l18_n388(x) + end +end + +def fun_l17_n542(x) + if (x < 1) + fun_l18_n288(x) + else + fun_l18_n422(x) + end +end + +def fun_l17_n543(x) + if (x < 1) + fun_l18_n873(x) + else + fun_l18_n614(x) + end +end + +def fun_l17_n544(x) + if (x < 1) + fun_l18_n104(x) + else + fun_l18_n771(x) + end +end + +def fun_l17_n545(x) + if (x < 1) + fun_l18_n204(x) + else + fun_l18_n452(x) + end +end + +def fun_l17_n546(x) + if (x < 1) + fun_l18_n288(x) + else + fun_l18_n558(x) + end +end + +def fun_l17_n547(x) + if (x < 1) + fun_l18_n265(x) + else + fun_l18_n768(x) + end +end + +def fun_l17_n548(x) + if (x < 1) + fun_l18_n21(x) + else + fun_l18_n44(x) + end +end + +def fun_l17_n549(x) + if (x < 1) + fun_l18_n72(x) + else + fun_l18_n321(x) + end +end + +def fun_l17_n550(x) + if (x < 1) + fun_l18_n473(x) + else + fun_l18_n127(x) + end +end + +def fun_l17_n551(x) + if (x < 1) + fun_l18_n188(x) + else + fun_l18_n782(x) + end +end + +def fun_l17_n552(x) + if (x < 1) + fun_l18_n118(x) + else + fun_l18_n466(x) + end +end + +def fun_l17_n553(x) + if (x < 1) + fun_l18_n279(x) + else + fun_l18_n605(x) + end +end + +def fun_l17_n554(x) + if (x < 1) + fun_l18_n760(x) + else + fun_l18_n561(x) + end +end + +def fun_l17_n555(x) + if (x < 1) + fun_l18_n873(x) + else + fun_l18_n846(x) + end +end + +def fun_l17_n556(x) + if (x < 1) + fun_l18_n555(x) + else + fun_l18_n955(x) + end +end + +def fun_l17_n557(x) + if (x < 1) + fun_l18_n757(x) + else + fun_l18_n171(x) + end +end + +def fun_l17_n558(x) + if (x < 1) + fun_l18_n684(x) + else + fun_l18_n784(x) + end +end + +def fun_l17_n559(x) + if (x < 1) + fun_l18_n457(x) + else + fun_l18_n798(x) + end +end + +def fun_l17_n560(x) + if (x < 1) + fun_l18_n472(x) + else + fun_l18_n291(x) + end +end + +def fun_l17_n561(x) + if (x < 1) + fun_l18_n870(x) + else + fun_l18_n395(x) + end +end + +def fun_l17_n562(x) + if (x < 1) + fun_l18_n482(x) + else + fun_l18_n281(x) + end +end + +def fun_l17_n563(x) + if (x < 1) + fun_l18_n761(x) + else + fun_l18_n362(x) + end +end + +def fun_l17_n564(x) + if (x < 1) + fun_l18_n586(x) + else + fun_l18_n92(x) + end +end + +def fun_l17_n565(x) + if (x < 1) + fun_l18_n620(x) + else + fun_l18_n356(x) + end +end + +def fun_l17_n566(x) + if (x < 1) + fun_l18_n529(x) + else + fun_l18_n985(x) + end +end + +def fun_l17_n567(x) + if (x < 1) + fun_l18_n351(x) + else + fun_l18_n77(x) + end +end + +def fun_l17_n568(x) + if (x < 1) + fun_l18_n659(x) + else + fun_l18_n631(x) + end +end + +def fun_l17_n569(x) + if (x < 1) + fun_l18_n630(x) + else + fun_l18_n466(x) + end +end + +def fun_l17_n570(x) + if (x < 1) + fun_l18_n374(x) + else + fun_l18_n203(x) + end +end + +def fun_l17_n571(x) + if (x < 1) + fun_l18_n479(x) + else + fun_l18_n977(x) + end +end + +def fun_l17_n572(x) + if (x < 1) + fun_l18_n862(x) + else + fun_l18_n323(x) + end +end + +def fun_l17_n573(x) + if (x < 1) + fun_l18_n148(x) + else + fun_l18_n848(x) + end +end + +def fun_l17_n574(x) + if (x < 1) + fun_l18_n29(x) + else + fun_l18_n210(x) + end +end + +def fun_l17_n575(x) + if (x < 1) + fun_l18_n39(x) + else + fun_l18_n874(x) + end +end + +def fun_l17_n576(x) + if (x < 1) + fun_l18_n843(x) + else + fun_l18_n5(x) + end +end + +def fun_l17_n577(x) + if (x < 1) + fun_l18_n284(x) + else + fun_l18_n242(x) + end +end + +def fun_l17_n578(x) + if (x < 1) + fun_l18_n768(x) + else + fun_l18_n683(x) + end +end + +def fun_l17_n579(x) + if (x < 1) + fun_l18_n67(x) + else + fun_l18_n423(x) + end +end + +def fun_l17_n580(x) + if (x < 1) + fun_l18_n326(x) + else + fun_l18_n200(x) + end +end + +def fun_l17_n581(x) + if (x < 1) + fun_l18_n186(x) + else + fun_l18_n772(x) + end +end + +def fun_l17_n582(x) + if (x < 1) + fun_l18_n151(x) + else + fun_l18_n222(x) + end +end + +def fun_l17_n583(x) + if (x < 1) + fun_l18_n690(x) + else + fun_l18_n925(x) + end +end + +def fun_l17_n584(x) + if (x < 1) + fun_l18_n225(x) + else + fun_l18_n286(x) + end +end + +def fun_l17_n585(x) + if (x < 1) + fun_l18_n542(x) + else + fun_l18_n703(x) + end +end + +def fun_l17_n586(x) + if (x < 1) + fun_l18_n417(x) + else + fun_l18_n364(x) + end +end + +def fun_l17_n587(x) + if (x < 1) + fun_l18_n540(x) + else + fun_l18_n231(x) + end +end + +def fun_l17_n588(x) + if (x < 1) + fun_l18_n859(x) + else + fun_l18_n557(x) + end +end + +def fun_l17_n589(x) + if (x < 1) + fun_l18_n131(x) + else + fun_l18_n847(x) + end +end + +def fun_l17_n590(x) + if (x < 1) + fun_l18_n267(x) + else + fun_l18_n613(x) + end +end + +def fun_l17_n591(x) + if (x < 1) + fun_l18_n273(x) + else + fun_l18_n857(x) + end +end + +def fun_l17_n592(x) + if (x < 1) + fun_l18_n561(x) + else + fun_l18_n243(x) + end +end + +def fun_l17_n593(x) + if (x < 1) + fun_l18_n742(x) + else + fun_l18_n123(x) + end +end + +def fun_l17_n594(x) + if (x < 1) + fun_l18_n480(x) + else + fun_l18_n290(x) + end +end + +def fun_l17_n595(x) + if (x < 1) + fun_l18_n56(x) + else + fun_l18_n727(x) + end +end + +def fun_l17_n596(x) + if (x < 1) + fun_l18_n901(x) + else + fun_l18_n723(x) + end +end + +def fun_l17_n597(x) + if (x < 1) + fun_l18_n405(x) + else + fun_l18_n498(x) + end +end + +def fun_l17_n598(x) + if (x < 1) + fun_l18_n772(x) + else + fun_l18_n543(x) + end +end + +def fun_l17_n599(x) + if (x < 1) + fun_l18_n20(x) + else + fun_l18_n39(x) + end +end + +def fun_l17_n600(x) + if (x < 1) + fun_l18_n657(x) + else + fun_l18_n381(x) + end +end + +def fun_l17_n601(x) + if (x < 1) + fun_l18_n505(x) + else + fun_l18_n196(x) + end +end + +def fun_l17_n602(x) + if (x < 1) + fun_l18_n250(x) + else + fun_l18_n503(x) + end +end + +def fun_l17_n603(x) + if (x < 1) + fun_l18_n694(x) + else + fun_l18_n589(x) + end +end + +def fun_l17_n604(x) + if (x < 1) + fun_l18_n27(x) + else + fun_l18_n202(x) + end +end + +def fun_l17_n605(x) + if (x < 1) + fun_l18_n901(x) + else + fun_l18_n823(x) + end +end + +def fun_l17_n606(x) + if (x < 1) + fun_l18_n296(x) + else + fun_l18_n854(x) + end +end + +def fun_l17_n607(x) + if (x < 1) + fun_l18_n226(x) + else + fun_l18_n110(x) + end +end + +def fun_l17_n608(x) + if (x < 1) + fun_l18_n205(x) + else + fun_l18_n215(x) + end +end + +def fun_l17_n609(x) + if (x < 1) + fun_l18_n265(x) + else + fun_l18_n715(x) + end +end + +def fun_l17_n610(x) + if (x < 1) + fun_l18_n881(x) + else + fun_l18_n106(x) + end +end + +def fun_l17_n611(x) + if (x < 1) + fun_l18_n674(x) + else + fun_l18_n189(x) + end +end + +def fun_l17_n612(x) + if (x < 1) + fun_l18_n20(x) + else + fun_l18_n96(x) + end +end + +def fun_l17_n613(x) + if (x < 1) + fun_l18_n880(x) + else + fun_l18_n599(x) + end +end + +def fun_l17_n614(x) + if (x < 1) + fun_l18_n47(x) + else + fun_l18_n633(x) + end +end + +def fun_l17_n615(x) + if (x < 1) + fun_l18_n7(x) + else + fun_l18_n165(x) + end +end + +def fun_l17_n616(x) + if (x < 1) + fun_l18_n478(x) + else + fun_l18_n94(x) + end +end + +def fun_l17_n617(x) + if (x < 1) + fun_l18_n97(x) + else + fun_l18_n369(x) + end +end + +def fun_l17_n618(x) + if (x < 1) + fun_l18_n291(x) + else + fun_l18_n637(x) + end +end + +def fun_l17_n619(x) + if (x < 1) + fun_l18_n966(x) + else + fun_l18_n851(x) + end +end + +def fun_l17_n620(x) + if (x < 1) + fun_l18_n349(x) + else + fun_l18_n413(x) + end +end + +def fun_l17_n621(x) + if (x < 1) + fun_l18_n343(x) + else + fun_l18_n224(x) + end +end + +def fun_l17_n622(x) + if (x < 1) + fun_l18_n452(x) + else + fun_l18_n3(x) + end +end + +def fun_l17_n623(x) + if (x < 1) + fun_l18_n539(x) + else + fun_l18_n542(x) + end +end + +def fun_l17_n624(x) + if (x < 1) + fun_l18_n117(x) + else + fun_l18_n348(x) + end +end + +def fun_l17_n625(x) + if (x < 1) + fun_l18_n753(x) + else + fun_l18_n284(x) + end +end + +def fun_l17_n626(x) + if (x < 1) + fun_l18_n146(x) + else + fun_l18_n228(x) + end +end + +def fun_l17_n627(x) + if (x < 1) + fun_l18_n286(x) + else + fun_l18_n413(x) + end +end + +def fun_l17_n628(x) + if (x < 1) + fun_l18_n730(x) + else + fun_l18_n311(x) + end +end + +def fun_l17_n629(x) + if (x < 1) + fun_l18_n455(x) + else + fun_l18_n141(x) + end +end + +def fun_l17_n630(x) + if (x < 1) + fun_l18_n300(x) + else + fun_l18_n368(x) + end +end + +def fun_l17_n631(x) + if (x < 1) + fun_l18_n490(x) + else + fun_l18_n711(x) + end +end + +def fun_l17_n632(x) + if (x < 1) + fun_l18_n310(x) + else + fun_l18_n805(x) + end +end + +def fun_l17_n633(x) + if (x < 1) + fun_l18_n2(x) + else + fun_l18_n709(x) + end +end + +def fun_l17_n634(x) + if (x < 1) + fun_l18_n239(x) + else + fun_l18_n394(x) + end +end + +def fun_l17_n635(x) + if (x < 1) + fun_l18_n933(x) + else + fun_l18_n749(x) + end +end + +def fun_l17_n636(x) + if (x < 1) + fun_l18_n54(x) + else + fun_l18_n511(x) + end +end + +def fun_l17_n637(x) + if (x < 1) + fun_l18_n908(x) + else + fun_l18_n550(x) + end +end + +def fun_l17_n638(x) + if (x < 1) + fun_l18_n262(x) + else + fun_l18_n485(x) + end +end + +def fun_l17_n639(x) + if (x < 1) + fun_l18_n676(x) + else + fun_l18_n860(x) + end +end + +def fun_l17_n640(x) + if (x < 1) + fun_l18_n205(x) + else + fun_l18_n901(x) + end +end + +def fun_l17_n641(x) + if (x < 1) + fun_l18_n834(x) + else + fun_l18_n133(x) + end +end + +def fun_l17_n642(x) + if (x < 1) + fun_l18_n824(x) + else + fun_l18_n551(x) + end +end + +def fun_l17_n643(x) + if (x < 1) + fun_l18_n362(x) + else + fun_l18_n684(x) + end +end + +def fun_l17_n644(x) + if (x < 1) + fun_l18_n856(x) + else + fun_l18_n103(x) + end +end + +def fun_l17_n645(x) + if (x < 1) + fun_l18_n999(x) + else + fun_l18_n995(x) + end +end + +def fun_l17_n646(x) + if (x < 1) + fun_l18_n24(x) + else + fun_l18_n405(x) + end +end + +def fun_l17_n647(x) + if (x < 1) + fun_l18_n71(x) + else + fun_l18_n201(x) + end +end + +def fun_l17_n648(x) + if (x < 1) + fun_l18_n905(x) + else + fun_l18_n14(x) + end +end + +def fun_l17_n649(x) + if (x < 1) + fun_l18_n490(x) + else + fun_l18_n932(x) + end +end + +def fun_l17_n650(x) + if (x < 1) + fun_l18_n25(x) + else + fun_l18_n333(x) + end +end + +def fun_l17_n651(x) + if (x < 1) + fun_l18_n282(x) + else + fun_l18_n197(x) + end +end + +def fun_l17_n652(x) + if (x < 1) + fun_l18_n684(x) + else + fun_l18_n618(x) + end +end + +def fun_l17_n653(x) + if (x < 1) + fun_l18_n201(x) + else + fun_l18_n571(x) + end +end + +def fun_l17_n654(x) + if (x < 1) + fun_l18_n26(x) + else + fun_l18_n813(x) + end +end + +def fun_l17_n655(x) + if (x < 1) + fun_l18_n879(x) + else + fun_l18_n860(x) + end +end + +def fun_l17_n656(x) + if (x < 1) + fun_l18_n193(x) + else + fun_l18_n635(x) + end +end + +def fun_l17_n657(x) + if (x < 1) + fun_l18_n163(x) + else + fun_l18_n601(x) + end +end + +def fun_l17_n658(x) + if (x < 1) + fun_l18_n794(x) + else + fun_l18_n582(x) + end +end + +def fun_l17_n659(x) + if (x < 1) + fun_l18_n22(x) + else + fun_l18_n427(x) + end +end + +def fun_l17_n660(x) + if (x < 1) + fun_l18_n959(x) + else + fun_l18_n21(x) + end +end + +def fun_l17_n661(x) + if (x < 1) + fun_l18_n233(x) + else + fun_l18_n852(x) + end +end + +def fun_l17_n662(x) + if (x < 1) + fun_l18_n367(x) + else + fun_l18_n119(x) + end +end + +def fun_l17_n663(x) + if (x < 1) + fun_l18_n511(x) + else + fun_l18_n425(x) + end +end + +def fun_l17_n664(x) + if (x < 1) + fun_l18_n256(x) + else + fun_l18_n294(x) + end +end + +def fun_l17_n665(x) + if (x < 1) + fun_l18_n263(x) + else + fun_l18_n549(x) + end +end + +def fun_l17_n666(x) + if (x < 1) + fun_l18_n868(x) + else + fun_l18_n221(x) + end +end + +def fun_l17_n667(x) + if (x < 1) + fun_l18_n703(x) + else + fun_l18_n157(x) + end +end + +def fun_l17_n668(x) + if (x < 1) + fun_l18_n639(x) + else + fun_l18_n685(x) + end +end + +def fun_l17_n669(x) + if (x < 1) + fun_l18_n278(x) + else + fun_l18_n366(x) + end +end + +def fun_l17_n670(x) + if (x < 1) + fun_l18_n267(x) + else + fun_l18_n641(x) + end +end + +def fun_l17_n671(x) + if (x < 1) + fun_l18_n452(x) + else + fun_l18_n851(x) + end +end + +def fun_l17_n672(x) + if (x < 1) + fun_l18_n256(x) + else + fun_l18_n282(x) + end +end + +def fun_l17_n673(x) + if (x < 1) + fun_l18_n397(x) + else + fun_l18_n446(x) + end +end + +def fun_l17_n674(x) + if (x < 1) + fun_l18_n499(x) + else + fun_l18_n166(x) + end +end + +def fun_l17_n675(x) + if (x < 1) + fun_l18_n299(x) + else + fun_l18_n473(x) + end +end + +def fun_l17_n676(x) + if (x < 1) + fun_l18_n331(x) + else + fun_l18_n590(x) + end +end + +def fun_l17_n677(x) + if (x < 1) + fun_l18_n951(x) + else + fun_l18_n227(x) + end +end + +def fun_l17_n678(x) + if (x < 1) + fun_l18_n874(x) + else + fun_l18_n359(x) + end +end + +def fun_l17_n679(x) + if (x < 1) + fun_l18_n187(x) + else + fun_l18_n13(x) + end +end + +def fun_l17_n680(x) + if (x < 1) + fun_l18_n878(x) + else + fun_l18_n902(x) + end +end + +def fun_l17_n681(x) + if (x < 1) + fun_l18_n450(x) + else + fun_l18_n262(x) + end +end + +def fun_l17_n682(x) + if (x < 1) + fun_l18_n759(x) + else + fun_l18_n253(x) + end +end + +def fun_l17_n683(x) + if (x < 1) + fun_l18_n199(x) + else + fun_l18_n191(x) + end +end + +def fun_l17_n684(x) + if (x < 1) + fun_l18_n93(x) + else + fun_l18_n275(x) + end +end + +def fun_l17_n685(x) + if (x < 1) + fun_l18_n17(x) + else + fun_l18_n575(x) + end +end + +def fun_l17_n686(x) + if (x < 1) + fun_l18_n971(x) + else + fun_l18_n540(x) + end +end + +def fun_l17_n687(x) + if (x < 1) + fun_l18_n942(x) + else + fun_l18_n285(x) + end +end + +def fun_l17_n688(x) + if (x < 1) + fun_l18_n348(x) + else + fun_l18_n7(x) + end +end + +def fun_l17_n689(x) + if (x < 1) + fun_l18_n839(x) + else + fun_l18_n532(x) + end +end + +def fun_l17_n690(x) + if (x < 1) + fun_l18_n578(x) + else + fun_l18_n751(x) + end +end + +def fun_l17_n691(x) + if (x < 1) + fun_l18_n85(x) + else + fun_l18_n311(x) + end +end + +def fun_l17_n692(x) + if (x < 1) + fun_l18_n573(x) + else + fun_l18_n685(x) + end +end + +def fun_l17_n693(x) + if (x < 1) + fun_l18_n449(x) + else + fun_l18_n749(x) + end +end + +def fun_l17_n694(x) + if (x < 1) + fun_l18_n251(x) + else + fun_l18_n266(x) + end +end + +def fun_l17_n695(x) + if (x < 1) + fun_l18_n69(x) + else + fun_l18_n725(x) + end +end + +def fun_l17_n696(x) + if (x < 1) + fun_l18_n54(x) + else + fun_l18_n196(x) + end +end + +def fun_l17_n697(x) + if (x < 1) + fun_l18_n950(x) + else + fun_l18_n423(x) + end +end + +def fun_l17_n698(x) + if (x < 1) + fun_l18_n809(x) + else + fun_l18_n787(x) + end +end + +def fun_l17_n699(x) + if (x < 1) + fun_l18_n211(x) + else + fun_l18_n79(x) + end +end + +def fun_l17_n700(x) + if (x < 1) + fun_l18_n686(x) + else + fun_l18_n287(x) + end +end + +def fun_l17_n701(x) + if (x < 1) + fun_l18_n412(x) + else + fun_l18_n769(x) + end +end + +def fun_l17_n702(x) + if (x < 1) + fun_l18_n62(x) + else + fun_l18_n592(x) + end +end + +def fun_l17_n703(x) + if (x < 1) + fun_l18_n628(x) + else + fun_l18_n121(x) + end +end + +def fun_l17_n704(x) + if (x < 1) + fun_l18_n84(x) + else + fun_l18_n350(x) + end +end + +def fun_l17_n705(x) + if (x < 1) + fun_l18_n599(x) + else + fun_l18_n174(x) + end +end + +def fun_l17_n706(x) + if (x < 1) + fun_l18_n39(x) + else + fun_l18_n266(x) + end +end + +def fun_l17_n707(x) + if (x < 1) + fun_l18_n196(x) + else + fun_l18_n838(x) + end +end + +def fun_l17_n708(x) + if (x < 1) + fun_l18_n647(x) + else + fun_l18_n26(x) + end +end + +def fun_l17_n709(x) + if (x < 1) + fun_l18_n693(x) + else + fun_l18_n660(x) + end +end + +def fun_l17_n710(x) + if (x < 1) + fun_l18_n530(x) + else + fun_l18_n654(x) + end +end + +def fun_l17_n711(x) + if (x < 1) + fun_l18_n580(x) + else + fun_l18_n65(x) + end +end + +def fun_l17_n712(x) + if (x < 1) + fun_l18_n789(x) + else + fun_l18_n832(x) + end +end + +def fun_l17_n713(x) + if (x < 1) + fun_l18_n366(x) + else + fun_l18_n168(x) + end +end + +def fun_l17_n714(x) + if (x < 1) + fun_l18_n571(x) + else + fun_l18_n23(x) + end +end + +def fun_l17_n715(x) + if (x < 1) + fun_l18_n552(x) + else + fun_l18_n400(x) + end +end + +def fun_l17_n716(x) + if (x < 1) + fun_l18_n752(x) + else + fun_l18_n403(x) + end +end + +def fun_l17_n717(x) + if (x < 1) + fun_l18_n498(x) + else + fun_l18_n173(x) + end +end + +def fun_l17_n718(x) + if (x < 1) + fun_l18_n168(x) + else + fun_l18_n656(x) + end +end + +def fun_l17_n719(x) + if (x < 1) + fun_l18_n75(x) + else + fun_l18_n393(x) + end +end + +def fun_l17_n720(x) + if (x < 1) + fun_l18_n856(x) + else + fun_l18_n101(x) + end +end + +def fun_l17_n721(x) + if (x < 1) + fun_l18_n445(x) + else + fun_l18_n846(x) + end +end + +def fun_l17_n722(x) + if (x < 1) + fun_l18_n450(x) + else + fun_l18_n136(x) + end +end + +def fun_l17_n723(x) + if (x < 1) + fun_l18_n267(x) + else + fun_l18_n800(x) + end +end + +def fun_l17_n724(x) + if (x < 1) + fun_l18_n98(x) + else + fun_l18_n955(x) + end +end + +def fun_l17_n725(x) + if (x < 1) + fun_l18_n951(x) + else + fun_l18_n319(x) + end +end + +def fun_l17_n726(x) + if (x < 1) + fun_l18_n531(x) + else + fun_l18_n846(x) + end +end + +def fun_l17_n727(x) + if (x < 1) + fun_l18_n888(x) + else + fun_l18_n600(x) + end +end + +def fun_l17_n728(x) + if (x < 1) + fun_l18_n278(x) + else + fun_l18_n445(x) + end +end + +def fun_l17_n729(x) + if (x < 1) + fun_l18_n113(x) + else + fun_l18_n991(x) + end +end + +def fun_l17_n730(x) + if (x < 1) + fun_l18_n756(x) + else + fun_l18_n935(x) + end +end + +def fun_l17_n731(x) + if (x < 1) + fun_l18_n2(x) + else + fun_l18_n969(x) + end +end + +def fun_l17_n732(x) + if (x < 1) + fun_l18_n138(x) + else + fun_l18_n198(x) + end +end + +def fun_l17_n733(x) + if (x < 1) + fun_l18_n845(x) + else + fun_l18_n614(x) + end +end + +def fun_l17_n734(x) + if (x < 1) + fun_l18_n603(x) + else + fun_l18_n568(x) + end +end + +def fun_l17_n735(x) + if (x < 1) + fun_l18_n276(x) + else + fun_l18_n58(x) + end +end + +def fun_l17_n736(x) + if (x < 1) + fun_l18_n404(x) + else + fun_l18_n906(x) + end +end + +def fun_l17_n737(x) + if (x < 1) + fun_l18_n199(x) + else + fun_l18_n734(x) + end +end + +def fun_l17_n738(x) + if (x < 1) + fun_l18_n327(x) + else + fun_l18_n667(x) + end +end + +def fun_l17_n739(x) + if (x < 1) + fun_l18_n600(x) + else + fun_l18_n986(x) + end +end + +def fun_l17_n740(x) + if (x < 1) + fun_l18_n820(x) + else + fun_l18_n615(x) + end +end + +def fun_l17_n741(x) + if (x < 1) + fun_l18_n779(x) + else + fun_l18_n912(x) + end +end + +def fun_l17_n742(x) + if (x < 1) + fun_l18_n55(x) + else + fun_l18_n41(x) + end +end + +def fun_l17_n743(x) + if (x < 1) + fun_l18_n24(x) + else + fun_l18_n877(x) + end +end + +def fun_l17_n744(x) + if (x < 1) + fun_l18_n834(x) + else + fun_l18_n10(x) + end +end + +def fun_l17_n745(x) + if (x < 1) + fun_l18_n369(x) + else + fun_l18_n761(x) + end +end + +def fun_l17_n746(x) + if (x < 1) + fun_l18_n534(x) + else + fun_l18_n292(x) + end +end + +def fun_l17_n747(x) + if (x < 1) + fun_l18_n260(x) + else + fun_l18_n98(x) + end +end + +def fun_l17_n748(x) + if (x < 1) + fun_l18_n738(x) + else + fun_l18_n298(x) + end +end + +def fun_l17_n749(x) + if (x < 1) + fun_l18_n156(x) + else + fun_l18_n322(x) + end +end + +def fun_l17_n750(x) + if (x < 1) + fun_l18_n519(x) + else + fun_l18_n566(x) + end +end + +def fun_l17_n751(x) + if (x < 1) + fun_l18_n599(x) + else + fun_l18_n525(x) + end +end + +def fun_l17_n752(x) + if (x < 1) + fun_l18_n51(x) + else + fun_l18_n334(x) + end +end + +def fun_l17_n753(x) + if (x < 1) + fun_l18_n593(x) + else + fun_l18_n799(x) + end +end + +def fun_l17_n754(x) + if (x < 1) + fun_l18_n599(x) + else + fun_l18_n167(x) + end +end + +def fun_l17_n755(x) + if (x < 1) + fun_l18_n799(x) + else + fun_l18_n909(x) + end +end + +def fun_l17_n756(x) + if (x < 1) + fun_l18_n988(x) + else + fun_l18_n793(x) + end +end + +def fun_l17_n757(x) + if (x < 1) + fun_l18_n144(x) + else + fun_l18_n279(x) + end +end + +def fun_l17_n758(x) + if (x < 1) + fun_l18_n981(x) + else + fun_l18_n603(x) + end +end + +def fun_l17_n759(x) + if (x < 1) + fun_l18_n576(x) + else + fun_l18_n730(x) + end +end + +def fun_l17_n760(x) + if (x < 1) + fun_l18_n66(x) + else + fun_l18_n359(x) + end +end + +def fun_l17_n761(x) + if (x < 1) + fun_l18_n555(x) + else + fun_l18_n553(x) + end +end + +def fun_l17_n762(x) + if (x < 1) + fun_l18_n508(x) + else + fun_l18_n665(x) + end +end + +def fun_l17_n763(x) + if (x < 1) + fun_l18_n911(x) + else + fun_l18_n19(x) + end +end + +def fun_l17_n764(x) + if (x < 1) + fun_l18_n162(x) + else + fun_l18_n707(x) + end +end + +def fun_l17_n765(x) + if (x < 1) + fun_l18_n262(x) + else + fun_l18_n494(x) + end +end + +def fun_l17_n766(x) + if (x < 1) + fun_l18_n220(x) + else + fun_l18_n144(x) + end +end + +def fun_l17_n767(x) + if (x < 1) + fun_l18_n245(x) + else + fun_l18_n727(x) + end +end + +def fun_l17_n768(x) + if (x < 1) + fun_l18_n875(x) + else + fun_l18_n610(x) + end +end + +def fun_l17_n769(x) + if (x < 1) + fun_l18_n338(x) + else + fun_l18_n344(x) + end +end + +def fun_l17_n770(x) + if (x < 1) + fun_l18_n224(x) + else + fun_l18_n682(x) + end +end + +def fun_l17_n771(x) + if (x < 1) + fun_l18_n353(x) + else + fun_l18_n102(x) + end +end + +def fun_l17_n772(x) + if (x < 1) + fun_l18_n122(x) + else + fun_l18_n979(x) + end +end + +def fun_l17_n773(x) + if (x < 1) + fun_l18_n549(x) + else + fun_l18_n296(x) + end +end + +def fun_l17_n774(x) + if (x < 1) + fun_l18_n82(x) + else + fun_l18_n748(x) + end +end + +def fun_l17_n775(x) + if (x < 1) + fun_l18_n958(x) + else + fun_l18_n917(x) + end +end + +def fun_l17_n776(x) + if (x < 1) + fun_l18_n173(x) + else + fun_l18_n438(x) + end +end + +def fun_l17_n777(x) + if (x < 1) + fun_l18_n222(x) + else + fun_l18_n55(x) + end +end + +def fun_l17_n778(x) + if (x < 1) + fun_l18_n529(x) + else + fun_l18_n548(x) + end +end + +def fun_l17_n779(x) + if (x < 1) + fun_l18_n28(x) + else + fun_l18_n582(x) + end +end + +def fun_l17_n780(x) + if (x < 1) + fun_l18_n818(x) + else + fun_l18_n836(x) + end +end + +def fun_l17_n781(x) + if (x < 1) + fun_l18_n972(x) + else + fun_l18_n73(x) + end +end + +def fun_l17_n782(x) + if (x < 1) + fun_l18_n527(x) + else + fun_l18_n999(x) + end +end + +def fun_l17_n783(x) + if (x < 1) + fun_l18_n832(x) + else + fun_l18_n833(x) + end +end + +def fun_l17_n784(x) + if (x < 1) + fun_l18_n987(x) + else + fun_l18_n329(x) + end +end + +def fun_l17_n785(x) + if (x < 1) + fun_l18_n715(x) + else + fun_l18_n441(x) + end +end + +def fun_l17_n786(x) + if (x < 1) + fun_l18_n55(x) + else + fun_l18_n682(x) + end +end + +def fun_l17_n787(x) + if (x < 1) + fun_l18_n606(x) + else + fun_l18_n656(x) + end +end + +def fun_l17_n788(x) + if (x < 1) + fun_l18_n254(x) + else + fun_l18_n544(x) + end +end + +def fun_l17_n789(x) + if (x < 1) + fun_l18_n285(x) + else + fun_l18_n585(x) + end +end + +def fun_l17_n790(x) + if (x < 1) + fun_l18_n441(x) + else + fun_l18_n716(x) + end +end + +def fun_l17_n791(x) + if (x < 1) + fun_l18_n415(x) + else + fun_l18_n126(x) + end +end + +def fun_l17_n792(x) + if (x < 1) + fun_l18_n490(x) + else + fun_l18_n753(x) + end +end + +def fun_l17_n793(x) + if (x < 1) + fun_l18_n324(x) + else + fun_l18_n223(x) + end +end + +def fun_l17_n794(x) + if (x < 1) + fun_l18_n913(x) + else + fun_l18_n94(x) + end +end + +def fun_l17_n795(x) + if (x < 1) + fun_l18_n879(x) + else + fun_l18_n404(x) + end +end + +def fun_l17_n796(x) + if (x < 1) + fun_l18_n309(x) + else + fun_l18_n65(x) + end +end + +def fun_l17_n797(x) + if (x < 1) + fun_l18_n712(x) + else + fun_l18_n947(x) + end +end + +def fun_l17_n798(x) + if (x < 1) + fun_l18_n238(x) + else + fun_l18_n83(x) + end +end + +def fun_l17_n799(x) + if (x < 1) + fun_l18_n25(x) + else + fun_l18_n371(x) + end +end + +def fun_l17_n800(x) + if (x < 1) + fun_l18_n501(x) + else + fun_l18_n386(x) + end +end + +def fun_l17_n801(x) + if (x < 1) + fun_l18_n453(x) + else + fun_l18_n168(x) + end +end + +def fun_l17_n802(x) + if (x < 1) + fun_l18_n763(x) + else + fun_l18_n675(x) + end +end + +def fun_l17_n803(x) + if (x < 1) + fun_l18_n984(x) + else + fun_l18_n882(x) + end +end + +def fun_l17_n804(x) + if (x < 1) + fun_l18_n545(x) + else + fun_l18_n79(x) + end +end + +def fun_l17_n805(x) + if (x < 1) + fun_l18_n263(x) + else + fun_l18_n143(x) + end +end + +def fun_l17_n806(x) + if (x < 1) + fun_l18_n232(x) + else + fun_l18_n864(x) + end +end + +def fun_l17_n807(x) + if (x < 1) + fun_l18_n6(x) + else + fun_l18_n983(x) + end +end + +def fun_l17_n808(x) + if (x < 1) + fun_l18_n17(x) + else + fun_l18_n426(x) + end +end + +def fun_l17_n809(x) + if (x < 1) + fun_l18_n1(x) + else + fun_l18_n669(x) + end +end + +def fun_l17_n810(x) + if (x < 1) + fun_l18_n191(x) + else + fun_l18_n540(x) + end +end + +def fun_l17_n811(x) + if (x < 1) + fun_l18_n16(x) + else + fun_l18_n871(x) + end +end + +def fun_l17_n812(x) + if (x < 1) + fun_l18_n352(x) + else + fun_l18_n156(x) + end +end + +def fun_l17_n813(x) + if (x < 1) + fun_l18_n239(x) + else + fun_l18_n314(x) + end +end + +def fun_l17_n814(x) + if (x < 1) + fun_l18_n890(x) + else + fun_l18_n21(x) + end +end + +def fun_l17_n815(x) + if (x < 1) + fun_l18_n894(x) + else + fun_l18_n894(x) + end +end + +def fun_l17_n816(x) + if (x < 1) + fun_l18_n75(x) + else + fun_l18_n631(x) + end +end + +def fun_l17_n817(x) + if (x < 1) + fun_l18_n118(x) + else + fun_l18_n857(x) + end +end + +def fun_l17_n818(x) + if (x < 1) + fun_l18_n403(x) + else + fun_l18_n364(x) + end +end + +def fun_l17_n819(x) + if (x < 1) + fun_l18_n15(x) + else + fun_l18_n232(x) + end +end + +def fun_l17_n820(x) + if (x < 1) + fun_l18_n610(x) + else + fun_l18_n43(x) + end +end + +def fun_l17_n821(x) + if (x < 1) + fun_l18_n949(x) + else + fun_l18_n884(x) + end +end + +def fun_l17_n822(x) + if (x < 1) + fun_l18_n387(x) + else + fun_l18_n587(x) + end +end + +def fun_l17_n823(x) + if (x < 1) + fun_l18_n99(x) + else + fun_l18_n653(x) + end +end + +def fun_l17_n824(x) + if (x < 1) + fun_l18_n41(x) + else + fun_l18_n822(x) + end +end + +def fun_l17_n825(x) + if (x < 1) + fun_l18_n325(x) + else + fun_l18_n735(x) + end +end + +def fun_l17_n826(x) + if (x < 1) + fun_l18_n415(x) + else + fun_l18_n684(x) + end +end + +def fun_l17_n827(x) + if (x < 1) + fun_l18_n856(x) + else + fun_l18_n257(x) + end +end + +def fun_l17_n828(x) + if (x < 1) + fun_l18_n455(x) + else + fun_l18_n200(x) + end +end + +def fun_l17_n829(x) + if (x < 1) + fun_l18_n486(x) + else + fun_l18_n528(x) + end +end + +def fun_l17_n830(x) + if (x < 1) + fun_l18_n321(x) + else + fun_l18_n619(x) + end +end + +def fun_l17_n831(x) + if (x < 1) + fun_l18_n910(x) + else + fun_l18_n796(x) + end +end + +def fun_l17_n832(x) + if (x < 1) + fun_l18_n303(x) + else + fun_l18_n278(x) + end +end + +def fun_l17_n833(x) + if (x < 1) + fun_l18_n477(x) + else + fun_l18_n733(x) + end +end + +def fun_l17_n834(x) + if (x < 1) + fun_l18_n320(x) + else + fun_l18_n801(x) + end +end + +def fun_l17_n835(x) + if (x < 1) + fun_l18_n672(x) + else + fun_l18_n183(x) + end +end + +def fun_l17_n836(x) + if (x < 1) + fun_l18_n810(x) + else + fun_l18_n923(x) + end +end + +def fun_l17_n837(x) + if (x < 1) + fun_l18_n775(x) + else + fun_l18_n884(x) + end +end + +def fun_l17_n838(x) + if (x < 1) + fun_l18_n9(x) + else + fun_l18_n690(x) + end +end + +def fun_l17_n839(x) + if (x < 1) + fun_l18_n843(x) + else + fun_l18_n482(x) + end +end + +def fun_l17_n840(x) + if (x < 1) + fun_l18_n527(x) + else + fun_l18_n331(x) + end +end + +def fun_l17_n841(x) + if (x < 1) + fun_l18_n210(x) + else + fun_l18_n119(x) + end +end + +def fun_l17_n842(x) + if (x < 1) + fun_l18_n365(x) + else + fun_l18_n752(x) + end +end + +def fun_l17_n843(x) + if (x < 1) + fun_l18_n855(x) + else + fun_l18_n149(x) + end +end + +def fun_l17_n844(x) + if (x < 1) + fun_l18_n822(x) + else + fun_l18_n852(x) + end +end + +def fun_l17_n845(x) + if (x < 1) + fun_l18_n182(x) + else + fun_l18_n145(x) + end +end + +def fun_l17_n846(x) + if (x < 1) + fun_l18_n167(x) + else + fun_l18_n47(x) + end +end + +def fun_l17_n847(x) + if (x < 1) + fun_l18_n350(x) + else + fun_l18_n894(x) + end +end + +def fun_l17_n848(x) + if (x < 1) + fun_l18_n264(x) + else + fun_l18_n739(x) + end +end + +def fun_l17_n849(x) + if (x < 1) + fun_l18_n475(x) + else + fun_l18_n974(x) + end +end + +def fun_l17_n850(x) + if (x < 1) + fun_l18_n849(x) + else + fun_l18_n68(x) + end +end + +def fun_l17_n851(x) + if (x < 1) + fun_l18_n160(x) + else + fun_l18_n173(x) + end +end + +def fun_l17_n852(x) + if (x < 1) + fun_l18_n353(x) + else + fun_l18_n931(x) + end +end + +def fun_l17_n853(x) + if (x < 1) + fun_l18_n706(x) + else + fun_l18_n540(x) + end +end + +def fun_l17_n854(x) + if (x < 1) + fun_l18_n559(x) + else + fun_l18_n149(x) + end +end + +def fun_l17_n855(x) + if (x < 1) + fun_l18_n347(x) + else + fun_l18_n559(x) + end +end + +def fun_l17_n856(x) + if (x < 1) + fun_l18_n640(x) + else + fun_l18_n529(x) + end +end + +def fun_l17_n857(x) + if (x < 1) + fun_l18_n410(x) + else + fun_l18_n278(x) + end +end + +def fun_l17_n858(x) + if (x < 1) + fun_l18_n15(x) + else + fun_l18_n21(x) + end +end + +def fun_l17_n859(x) + if (x < 1) + fun_l18_n180(x) + else + fun_l18_n530(x) + end +end + +def fun_l17_n860(x) + if (x < 1) + fun_l18_n739(x) + else + fun_l18_n817(x) + end +end + +def fun_l17_n861(x) + if (x < 1) + fun_l18_n341(x) + else + fun_l18_n962(x) + end +end + +def fun_l17_n862(x) + if (x < 1) + fun_l18_n994(x) + else + fun_l18_n338(x) + end +end + +def fun_l17_n863(x) + if (x < 1) + fun_l18_n428(x) + else + fun_l18_n608(x) + end +end + +def fun_l17_n864(x) + if (x < 1) + fun_l18_n889(x) + else + fun_l18_n974(x) + end +end + +def fun_l17_n865(x) + if (x < 1) + fun_l18_n300(x) + else + fun_l18_n164(x) + end +end + +def fun_l17_n866(x) + if (x < 1) + fun_l18_n195(x) + else + fun_l18_n75(x) + end +end + +def fun_l17_n867(x) + if (x < 1) + fun_l18_n725(x) + else + fun_l18_n639(x) + end +end + +def fun_l17_n868(x) + if (x < 1) + fun_l18_n793(x) + else + fun_l18_n925(x) + end +end + +def fun_l17_n869(x) + if (x < 1) + fun_l18_n845(x) + else + fun_l18_n174(x) + end +end + +def fun_l17_n870(x) + if (x < 1) + fun_l18_n202(x) + else + fun_l18_n376(x) + end +end + +def fun_l17_n871(x) + if (x < 1) + fun_l18_n503(x) + else + fun_l18_n441(x) + end +end + +def fun_l17_n872(x) + if (x < 1) + fun_l18_n675(x) + else + fun_l18_n180(x) + end +end + +def fun_l17_n873(x) + if (x < 1) + fun_l18_n457(x) + else + fun_l18_n286(x) + end +end + +def fun_l17_n874(x) + if (x < 1) + fun_l18_n918(x) + else + fun_l18_n438(x) + end +end + +def fun_l17_n875(x) + if (x < 1) + fun_l18_n269(x) + else + fun_l18_n539(x) + end +end + +def fun_l17_n876(x) + if (x < 1) + fun_l18_n417(x) + else + fun_l18_n68(x) + end +end + +def fun_l17_n877(x) + if (x < 1) + fun_l18_n382(x) + else + fun_l18_n392(x) + end +end + +def fun_l17_n878(x) + if (x < 1) + fun_l18_n981(x) + else + fun_l18_n997(x) + end +end + +def fun_l17_n879(x) + if (x < 1) + fun_l18_n8(x) + else + fun_l18_n255(x) + end +end + +def fun_l17_n880(x) + if (x < 1) + fun_l18_n634(x) + else + fun_l18_n971(x) + end +end + +def fun_l17_n881(x) + if (x < 1) + fun_l18_n940(x) + else + fun_l18_n410(x) + end +end + +def fun_l17_n882(x) + if (x < 1) + fun_l18_n550(x) + else + fun_l18_n959(x) + end +end + +def fun_l17_n883(x) + if (x < 1) + fun_l18_n258(x) + else + fun_l18_n766(x) + end +end + +def fun_l17_n884(x) + if (x < 1) + fun_l18_n841(x) + else + fun_l18_n387(x) + end +end + +def fun_l17_n885(x) + if (x < 1) + fun_l18_n357(x) + else + fun_l18_n128(x) + end +end + +def fun_l17_n886(x) + if (x < 1) + fun_l18_n872(x) + else + fun_l18_n471(x) + end +end + +def fun_l17_n887(x) + if (x < 1) + fun_l18_n596(x) + else + fun_l18_n639(x) + end +end + +def fun_l17_n888(x) + if (x < 1) + fun_l18_n665(x) + else + fun_l18_n999(x) + end +end + +def fun_l17_n889(x) + if (x < 1) + fun_l18_n898(x) + else + fun_l18_n899(x) + end +end + +def fun_l17_n890(x) + if (x < 1) + fun_l18_n457(x) + else + fun_l18_n370(x) + end +end + +def fun_l17_n891(x) + if (x < 1) + fun_l18_n100(x) + else + fun_l18_n899(x) + end +end + +def fun_l17_n892(x) + if (x < 1) + fun_l18_n785(x) + else + fun_l18_n552(x) + end +end + +def fun_l17_n893(x) + if (x < 1) + fun_l18_n386(x) + else + fun_l18_n971(x) + end +end + +def fun_l17_n894(x) + if (x < 1) + fun_l18_n128(x) + else + fun_l18_n28(x) + end +end + +def fun_l17_n895(x) + if (x < 1) + fun_l18_n18(x) + else + fun_l18_n682(x) + end +end + +def fun_l17_n896(x) + if (x < 1) + fun_l18_n470(x) + else + fun_l18_n477(x) + end +end + +def fun_l17_n897(x) + if (x < 1) + fun_l18_n543(x) + else + fun_l18_n943(x) + end +end + +def fun_l17_n898(x) + if (x < 1) + fun_l18_n554(x) + else + fun_l18_n431(x) + end +end + +def fun_l17_n899(x) + if (x < 1) + fun_l18_n615(x) + else + fun_l18_n480(x) + end +end + +def fun_l17_n900(x) + if (x < 1) + fun_l18_n557(x) + else + fun_l18_n831(x) + end +end + +def fun_l17_n901(x) + if (x < 1) + fun_l18_n245(x) + else + fun_l18_n79(x) + end +end + +def fun_l17_n902(x) + if (x < 1) + fun_l18_n332(x) + else + fun_l18_n536(x) + end +end + +def fun_l17_n903(x) + if (x < 1) + fun_l18_n531(x) + else + fun_l18_n933(x) + end +end + +def fun_l17_n904(x) + if (x < 1) + fun_l18_n748(x) + else + fun_l18_n210(x) + end +end + +def fun_l17_n905(x) + if (x < 1) + fun_l18_n351(x) + else + fun_l18_n698(x) + end +end + +def fun_l17_n906(x) + if (x < 1) + fun_l18_n112(x) + else + fun_l18_n397(x) + end +end + +def fun_l17_n907(x) + if (x < 1) + fun_l18_n177(x) + else + fun_l18_n826(x) + end +end + +def fun_l17_n908(x) + if (x < 1) + fun_l18_n635(x) + else + fun_l18_n885(x) + end +end + +def fun_l17_n909(x) + if (x < 1) + fun_l18_n225(x) + else + fun_l18_n139(x) + end +end + +def fun_l17_n910(x) + if (x < 1) + fun_l18_n30(x) + else + fun_l18_n113(x) + end +end + +def fun_l17_n911(x) + if (x < 1) + fun_l18_n5(x) + else + fun_l18_n324(x) + end +end + +def fun_l17_n912(x) + if (x < 1) + fun_l18_n626(x) + else + fun_l18_n326(x) + end +end + +def fun_l17_n913(x) + if (x < 1) + fun_l18_n478(x) + else + fun_l18_n373(x) + end +end + +def fun_l17_n914(x) + if (x < 1) + fun_l18_n348(x) + else + fun_l18_n420(x) + end +end + +def fun_l17_n915(x) + if (x < 1) + fun_l18_n777(x) + else + fun_l18_n185(x) + end +end + +def fun_l17_n916(x) + if (x < 1) + fun_l18_n18(x) + else + fun_l18_n286(x) + end +end + +def fun_l17_n917(x) + if (x < 1) + fun_l18_n199(x) + else + fun_l18_n378(x) + end +end + +def fun_l17_n918(x) + if (x < 1) + fun_l18_n282(x) + else + fun_l18_n617(x) + end +end + +def fun_l17_n919(x) + if (x < 1) + fun_l18_n634(x) + else + fun_l18_n396(x) + end +end + +def fun_l17_n920(x) + if (x < 1) + fun_l18_n630(x) + else + fun_l18_n479(x) + end +end + +def fun_l17_n921(x) + if (x < 1) + fun_l18_n828(x) + else + fun_l18_n189(x) + end +end + +def fun_l17_n922(x) + if (x < 1) + fun_l18_n468(x) + else + fun_l18_n400(x) + end +end + +def fun_l17_n923(x) + if (x < 1) + fun_l18_n815(x) + else + fun_l18_n0(x) + end +end + +def fun_l17_n924(x) + if (x < 1) + fun_l18_n796(x) + else + fun_l18_n357(x) + end +end + +def fun_l17_n925(x) + if (x < 1) + fun_l18_n4(x) + else + fun_l18_n293(x) + end +end + +def fun_l17_n926(x) + if (x < 1) + fun_l18_n187(x) + else + fun_l18_n131(x) + end +end + +def fun_l17_n927(x) + if (x < 1) + fun_l18_n896(x) + else + fun_l18_n257(x) + end +end + +def fun_l17_n928(x) + if (x < 1) + fun_l18_n596(x) + else + fun_l18_n115(x) + end +end + +def fun_l17_n929(x) + if (x < 1) + fun_l18_n630(x) + else + fun_l18_n62(x) + end +end + +def fun_l17_n930(x) + if (x < 1) + fun_l18_n776(x) + else + fun_l18_n664(x) + end +end + +def fun_l17_n931(x) + if (x < 1) + fun_l18_n424(x) + else + fun_l18_n298(x) + end +end + +def fun_l17_n932(x) + if (x < 1) + fun_l18_n734(x) + else + fun_l18_n652(x) + end +end + +def fun_l17_n933(x) + if (x < 1) + fun_l18_n796(x) + else + fun_l18_n8(x) + end +end + +def fun_l17_n934(x) + if (x < 1) + fun_l18_n783(x) + else + fun_l18_n177(x) + end +end + +def fun_l17_n935(x) + if (x < 1) + fun_l18_n288(x) + else + fun_l18_n274(x) + end +end + +def fun_l17_n936(x) + if (x < 1) + fun_l18_n289(x) + else + fun_l18_n938(x) + end +end + +def fun_l17_n937(x) + if (x < 1) + fun_l18_n815(x) + else + fun_l18_n924(x) + end +end + +def fun_l17_n938(x) + if (x < 1) + fun_l18_n145(x) + else + fun_l18_n497(x) + end +end + +def fun_l17_n939(x) + if (x < 1) + fun_l18_n433(x) + else + fun_l18_n628(x) + end +end + +def fun_l17_n940(x) + if (x < 1) + fun_l18_n410(x) + else + fun_l18_n461(x) + end +end + +def fun_l17_n941(x) + if (x < 1) + fun_l18_n682(x) + else + fun_l18_n81(x) + end +end + +def fun_l17_n942(x) + if (x < 1) + fun_l18_n948(x) + else + fun_l18_n29(x) + end +end + +def fun_l17_n943(x) + if (x < 1) + fun_l18_n78(x) + else + fun_l18_n237(x) + end +end + +def fun_l17_n944(x) + if (x < 1) + fun_l18_n683(x) + else + fun_l18_n936(x) + end +end + +def fun_l17_n945(x) + if (x < 1) + fun_l18_n339(x) + else + fun_l18_n471(x) + end +end + +def fun_l17_n946(x) + if (x < 1) + fun_l18_n903(x) + else + fun_l18_n983(x) + end +end + +def fun_l17_n947(x) + if (x < 1) + fun_l18_n231(x) + else + fun_l18_n985(x) + end +end + +def fun_l17_n948(x) + if (x < 1) + fun_l18_n379(x) + else + fun_l18_n385(x) + end +end + +def fun_l17_n949(x) + if (x < 1) + fun_l18_n89(x) + else + fun_l18_n499(x) + end +end + +def fun_l17_n950(x) + if (x < 1) + fun_l18_n851(x) + else + fun_l18_n563(x) + end +end + +def fun_l17_n951(x) + if (x < 1) + fun_l18_n803(x) + else + fun_l18_n109(x) + end +end + +def fun_l17_n952(x) + if (x < 1) + fun_l18_n178(x) + else + fun_l18_n886(x) + end +end + +def fun_l17_n953(x) + if (x < 1) + fun_l18_n705(x) + else + fun_l18_n340(x) + end +end + +def fun_l17_n954(x) + if (x < 1) + fun_l18_n207(x) + else + fun_l18_n499(x) + end +end + +def fun_l17_n955(x) + if (x < 1) + fun_l18_n298(x) + else + fun_l18_n921(x) + end +end + +def fun_l17_n956(x) + if (x < 1) + fun_l18_n291(x) + else + fun_l18_n768(x) + end +end + +def fun_l17_n957(x) + if (x < 1) + fun_l18_n144(x) + else + fun_l18_n316(x) + end +end + +def fun_l17_n958(x) + if (x < 1) + fun_l18_n375(x) + else + fun_l18_n891(x) + end +end + +def fun_l17_n959(x) + if (x < 1) + fun_l18_n989(x) + else + fun_l18_n773(x) + end +end + +def fun_l17_n960(x) + if (x < 1) + fun_l18_n615(x) + else + fun_l18_n252(x) + end +end + +def fun_l17_n961(x) + if (x < 1) + fun_l18_n827(x) + else + fun_l18_n567(x) + end +end + +def fun_l17_n962(x) + if (x < 1) + fun_l18_n792(x) + else + fun_l18_n81(x) + end +end + +def fun_l17_n963(x) + if (x < 1) + fun_l18_n561(x) + else + fun_l18_n732(x) + end +end + +def fun_l17_n964(x) + if (x < 1) + fun_l18_n113(x) + else + fun_l18_n110(x) + end +end + +def fun_l17_n965(x) + if (x < 1) + fun_l18_n321(x) + else + fun_l18_n557(x) + end +end + +def fun_l17_n966(x) + if (x < 1) + fun_l18_n409(x) + else + fun_l18_n449(x) + end +end + +def fun_l17_n967(x) + if (x < 1) + fun_l18_n316(x) + else + fun_l18_n669(x) + end +end + +def fun_l17_n968(x) + if (x < 1) + fun_l18_n190(x) + else + fun_l18_n450(x) + end +end + +def fun_l17_n969(x) + if (x < 1) + fun_l18_n174(x) + else + fun_l18_n425(x) + end +end + +def fun_l17_n970(x) + if (x < 1) + fun_l18_n918(x) + else + fun_l18_n537(x) + end +end + +def fun_l17_n971(x) + if (x < 1) + fun_l18_n923(x) + else + fun_l18_n998(x) + end +end + +def fun_l17_n972(x) + if (x < 1) + fun_l18_n625(x) + else + fun_l18_n75(x) + end +end + +def fun_l17_n973(x) + if (x < 1) + fun_l18_n171(x) + else + fun_l18_n180(x) + end +end + +def fun_l17_n974(x) + if (x < 1) + fun_l18_n430(x) + else + fun_l18_n659(x) + end +end + +def fun_l17_n975(x) + if (x < 1) + fun_l18_n88(x) + else + fun_l18_n363(x) + end +end + +def fun_l17_n976(x) + if (x < 1) + fun_l18_n408(x) + else + fun_l18_n986(x) + end +end + +def fun_l17_n977(x) + if (x < 1) + fun_l18_n988(x) + else + fun_l18_n818(x) + end +end + +def fun_l17_n978(x) + if (x < 1) + fun_l18_n824(x) + else + fun_l18_n24(x) + end +end + +def fun_l17_n979(x) + if (x < 1) + fun_l18_n182(x) + else + fun_l18_n969(x) + end +end + +def fun_l17_n980(x) + if (x < 1) + fun_l18_n187(x) + else + fun_l18_n615(x) + end +end + +def fun_l17_n981(x) + if (x < 1) + fun_l18_n646(x) + else + fun_l18_n25(x) + end +end + +def fun_l17_n982(x) + if (x < 1) + fun_l18_n700(x) + else + fun_l18_n127(x) + end +end + +def fun_l17_n983(x) + if (x < 1) + fun_l18_n153(x) + else + fun_l18_n831(x) + end +end + +def fun_l17_n984(x) + if (x < 1) + fun_l18_n884(x) + else + fun_l18_n540(x) + end +end + +def fun_l17_n985(x) + if (x < 1) + fun_l18_n225(x) + else + fun_l18_n221(x) + end +end + +def fun_l17_n986(x) + if (x < 1) + fun_l18_n431(x) + else + fun_l18_n884(x) + end +end + +def fun_l17_n987(x) + if (x < 1) + fun_l18_n271(x) + else + fun_l18_n541(x) + end +end + +def fun_l17_n988(x) + if (x < 1) + fun_l18_n419(x) + else + fun_l18_n183(x) + end +end + +def fun_l17_n989(x) + if (x < 1) + fun_l18_n85(x) + else + fun_l18_n51(x) + end +end + +def fun_l17_n990(x) + if (x < 1) + fun_l18_n528(x) + else + fun_l18_n380(x) + end +end + +def fun_l17_n991(x) + if (x < 1) + fun_l18_n13(x) + else + fun_l18_n137(x) + end +end + +def fun_l17_n992(x) + if (x < 1) + fun_l18_n655(x) + else + fun_l18_n344(x) + end +end + +def fun_l17_n993(x) + if (x < 1) + fun_l18_n911(x) + else + fun_l18_n21(x) + end +end + +def fun_l17_n994(x) + if (x < 1) + fun_l18_n887(x) + else + fun_l18_n935(x) + end +end + +def fun_l17_n995(x) + if (x < 1) + fun_l18_n206(x) + else + fun_l18_n374(x) + end +end + +def fun_l17_n996(x) + if (x < 1) + fun_l18_n552(x) + else + fun_l18_n209(x) + end +end + +def fun_l17_n997(x) + if (x < 1) + fun_l18_n540(x) + else + fun_l18_n901(x) + end +end + +def fun_l17_n998(x) + if (x < 1) + fun_l18_n547(x) + else + fun_l18_n304(x) + end +end + +def fun_l17_n999(x) + if (x < 1) + fun_l18_n297(x) + else + fun_l18_n868(x) + end +end + +def fun_l18_n0(x) + if (x < 1) + fun_l19_n619(x) + else + fun_l19_n167(x) + end +end + +def fun_l18_n1(x) + if (x < 1) + fun_l19_n669(x) + else + fun_l19_n962(x) + end +end + +def fun_l18_n2(x) + if (x < 1) + fun_l19_n235(x) + else + fun_l19_n99(x) + end +end + +def fun_l18_n3(x) + if (x < 1) + fun_l19_n961(x) + else + fun_l19_n200(x) + end +end + +def fun_l18_n4(x) + if (x < 1) + fun_l19_n812(x) + else + fun_l19_n764(x) + end +end + +def fun_l18_n5(x) + if (x < 1) + fun_l19_n605(x) + else + fun_l19_n260(x) + end +end + +def fun_l18_n6(x) + if (x < 1) + fun_l19_n146(x) + else + fun_l19_n617(x) + end +end + +def fun_l18_n7(x) + if (x < 1) + fun_l19_n181(x) + else + fun_l19_n31(x) + end +end + +def fun_l18_n8(x) + if (x < 1) + fun_l19_n884(x) + else + fun_l19_n341(x) + end +end + +def fun_l18_n9(x) + if (x < 1) + fun_l19_n741(x) + else + fun_l19_n704(x) + end +end + +def fun_l18_n10(x) + if (x < 1) + fun_l19_n610(x) + else + fun_l19_n24(x) + end +end + +def fun_l18_n11(x) + if (x < 1) + fun_l19_n184(x) + else + fun_l19_n125(x) + end +end + +def fun_l18_n12(x) + if (x < 1) + fun_l19_n59(x) + else + fun_l19_n30(x) + end +end + +def fun_l18_n13(x) + if (x < 1) + fun_l19_n255(x) + else + fun_l19_n18(x) + end +end + +def fun_l18_n14(x) + if (x < 1) + fun_l19_n661(x) + else + fun_l19_n554(x) + end +end + +def fun_l18_n15(x) + if (x < 1) + fun_l19_n557(x) + else + fun_l19_n757(x) + end +end + +def fun_l18_n16(x) + if (x < 1) + fun_l19_n946(x) + else + fun_l19_n403(x) + end +end + +def fun_l18_n17(x) + if (x < 1) + fun_l19_n872(x) + else + fun_l19_n64(x) + end +end + +def fun_l18_n18(x) + if (x < 1) + fun_l19_n531(x) + else + fun_l19_n200(x) + end +end + +def fun_l18_n19(x) + if (x < 1) + fun_l19_n172(x) + else + fun_l19_n319(x) + end +end + +def fun_l18_n20(x) + if (x < 1) + fun_l19_n369(x) + else + fun_l19_n707(x) + end +end + +def fun_l18_n21(x) + if (x < 1) + fun_l19_n726(x) + else + fun_l19_n718(x) + end +end + +def fun_l18_n22(x) + if (x < 1) + fun_l19_n169(x) + else + fun_l19_n117(x) + end +end + +def fun_l18_n23(x) + if (x < 1) + fun_l19_n913(x) + else + fun_l19_n489(x) + end +end + +def fun_l18_n24(x) + if (x < 1) + fun_l19_n950(x) + else + fun_l19_n272(x) + end +end + +def fun_l18_n25(x) + if (x < 1) + fun_l19_n835(x) + else + fun_l19_n341(x) + end +end + +def fun_l18_n26(x) + if (x < 1) + fun_l19_n771(x) + else + fun_l19_n805(x) + end +end + +def fun_l18_n27(x) + if (x < 1) + fun_l19_n71(x) + else + fun_l19_n515(x) + end +end + +def fun_l18_n28(x) + if (x < 1) + fun_l19_n472(x) + else + fun_l19_n807(x) + end +end + +def fun_l18_n29(x) + if (x < 1) + fun_l19_n957(x) + else + fun_l19_n555(x) + end +end + +def fun_l18_n30(x) + if (x < 1) + fun_l19_n629(x) + else + fun_l19_n113(x) + end +end + +def fun_l18_n31(x) + if (x < 1) + fun_l19_n791(x) + else + fun_l19_n340(x) + end +end + +def fun_l18_n32(x) + if (x < 1) + fun_l19_n852(x) + else + fun_l19_n204(x) + end +end + +def fun_l18_n33(x) + if (x < 1) + fun_l19_n441(x) + else + fun_l19_n331(x) + end +end + +def fun_l18_n34(x) + if (x < 1) + fun_l19_n51(x) + else + fun_l19_n199(x) + end +end + +def fun_l18_n35(x) + if (x < 1) + fun_l19_n472(x) + else + fun_l19_n589(x) + end +end + +def fun_l18_n36(x) + if (x < 1) + fun_l19_n191(x) + else + fun_l19_n333(x) + end +end + +def fun_l18_n37(x) + if (x < 1) + fun_l19_n412(x) + else + fun_l19_n661(x) + end +end + +def fun_l18_n38(x) + if (x < 1) + fun_l19_n427(x) + else + fun_l19_n401(x) + end +end + +def fun_l18_n39(x) + if (x < 1) + fun_l19_n96(x) + else + fun_l19_n235(x) + end +end + +def fun_l18_n40(x) + if (x < 1) + fun_l19_n984(x) + else + fun_l19_n586(x) + end +end + +def fun_l18_n41(x) + if (x < 1) + fun_l19_n559(x) + else + fun_l19_n382(x) + end +end + +def fun_l18_n42(x) + if (x < 1) + fun_l19_n802(x) + else + fun_l19_n217(x) + end +end + +def fun_l18_n43(x) + if (x < 1) + fun_l19_n693(x) + else + fun_l19_n178(x) + end +end + +def fun_l18_n44(x) + if (x < 1) + fun_l19_n961(x) + else + fun_l19_n425(x) + end +end + +def fun_l18_n45(x) + if (x < 1) + fun_l19_n242(x) + else + fun_l19_n949(x) + end +end + +def fun_l18_n46(x) + if (x < 1) + fun_l19_n418(x) + else + fun_l19_n462(x) + end +end + +def fun_l18_n47(x) + if (x < 1) + fun_l19_n56(x) + else + fun_l19_n79(x) + end +end + +def fun_l18_n48(x) + if (x < 1) + fun_l19_n5(x) + else + fun_l19_n939(x) + end +end + +def fun_l18_n49(x) + if (x < 1) + fun_l19_n4(x) + else + fun_l19_n262(x) + end +end + +def fun_l18_n50(x) + if (x < 1) + fun_l19_n476(x) + else + fun_l19_n751(x) + end +end + +def fun_l18_n51(x) + if (x < 1) + fun_l19_n687(x) + else + fun_l19_n489(x) + end +end + +def fun_l18_n52(x) + if (x < 1) + fun_l19_n965(x) + else + fun_l19_n198(x) + end +end + +def fun_l18_n53(x) + if (x < 1) + fun_l19_n349(x) + else + fun_l19_n603(x) + end +end + +def fun_l18_n54(x) + if (x < 1) + fun_l19_n893(x) + else + fun_l19_n279(x) + end +end + +def fun_l18_n55(x) + if (x < 1) + fun_l19_n816(x) + else + fun_l19_n922(x) + end +end + +def fun_l18_n56(x) + if (x < 1) + fun_l19_n10(x) + else + fun_l19_n750(x) + end +end + +def fun_l18_n57(x) + if (x < 1) + fun_l19_n787(x) + else + fun_l19_n446(x) + end +end + +def fun_l18_n58(x) + if (x < 1) + fun_l19_n662(x) + else + fun_l19_n636(x) + end +end + +def fun_l18_n59(x) + if (x < 1) + fun_l19_n640(x) + else + fun_l19_n604(x) + end +end + +def fun_l18_n60(x) + if (x < 1) + fun_l19_n1(x) + else + fun_l19_n657(x) + end +end + +def fun_l18_n61(x) + if (x < 1) + fun_l19_n657(x) + else + fun_l19_n516(x) + end +end + +def fun_l18_n62(x) + if (x < 1) + fun_l19_n167(x) + else + fun_l19_n770(x) + end +end + +def fun_l18_n63(x) + if (x < 1) + fun_l19_n572(x) + else + fun_l19_n224(x) + end +end + +def fun_l18_n64(x) + if (x < 1) + fun_l19_n564(x) + else + fun_l19_n64(x) + end +end + +def fun_l18_n65(x) + if (x < 1) + fun_l19_n200(x) + else + fun_l19_n724(x) + end +end + +def fun_l18_n66(x) + if (x < 1) + fun_l19_n295(x) + else + fun_l19_n127(x) + end +end + +def fun_l18_n67(x) + if (x < 1) + fun_l19_n81(x) + else + fun_l19_n757(x) + end +end + +def fun_l18_n68(x) + if (x < 1) + fun_l19_n573(x) + else + fun_l19_n473(x) + end +end + +def fun_l18_n69(x) + if (x < 1) + fun_l19_n475(x) + else + fun_l19_n8(x) + end +end + +def fun_l18_n70(x) + if (x < 1) + fun_l19_n564(x) + else + fun_l19_n74(x) + end +end + +def fun_l18_n71(x) + if (x < 1) + fun_l19_n270(x) + else + fun_l19_n12(x) + end +end + +def fun_l18_n72(x) + if (x < 1) + fun_l19_n809(x) + else + fun_l19_n857(x) + end +end + +def fun_l18_n73(x) + if (x < 1) + fun_l19_n329(x) + else + fun_l19_n850(x) + end +end + +def fun_l18_n74(x) + if (x < 1) + fun_l19_n471(x) + else + fun_l19_n127(x) + end +end + +def fun_l18_n75(x) + if (x < 1) + fun_l19_n558(x) + else + fun_l19_n626(x) + end +end + +def fun_l18_n76(x) + if (x < 1) + fun_l19_n648(x) + else + fun_l19_n687(x) + end +end + +def fun_l18_n77(x) + if (x < 1) + fun_l19_n690(x) + else + fun_l19_n612(x) + end +end + +def fun_l18_n78(x) + if (x < 1) + fun_l19_n122(x) + else + fun_l19_n843(x) + end +end + +def fun_l18_n79(x) + if (x < 1) + fun_l19_n375(x) + else + fun_l19_n56(x) + end +end + +def fun_l18_n80(x) + if (x < 1) + fun_l19_n184(x) + else + fun_l19_n280(x) + end +end + +def fun_l18_n81(x) + if (x < 1) + fun_l19_n588(x) + else + fun_l19_n433(x) + end +end + +def fun_l18_n82(x) + if (x < 1) + fun_l19_n144(x) + else + fun_l19_n754(x) + end +end + +def fun_l18_n83(x) + if (x < 1) + fun_l19_n468(x) + else + fun_l19_n951(x) + end +end + +def fun_l18_n84(x) + if (x < 1) + fun_l19_n380(x) + else + fun_l19_n597(x) + end +end + +def fun_l18_n85(x) + if (x < 1) + fun_l19_n651(x) + else + fun_l19_n756(x) + end +end + +def fun_l18_n86(x) + if (x < 1) + fun_l19_n440(x) + else + fun_l19_n184(x) + end +end + +def fun_l18_n87(x) + if (x < 1) + fun_l19_n851(x) + else + fun_l19_n753(x) + end +end + +def fun_l18_n88(x) + if (x < 1) + fun_l19_n808(x) + else + fun_l19_n102(x) + end +end + +def fun_l18_n89(x) + if (x < 1) + fun_l19_n768(x) + else + fun_l19_n885(x) + end +end + +def fun_l18_n90(x) + if (x < 1) + fun_l19_n933(x) + else + fun_l19_n284(x) + end +end + +def fun_l18_n91(x) + if (x < 1) + fun_l19_n234(x) + else + fun_l19_n927(x) + end +end + +def fun_l18_n92(x) + if (x < 1) + fun_l19_n901(x) + else + fun_l19_n690(x) + end +end + +def fun_l18_n93(x) + if (x < 1) + fun_l19_n386(x) + else + fun_l19_n692(x) + end +end + +def fun_l18_n94(x) + if (x < 1) + fun_l19_n572(x) + else + fun_l19_n795(x) + end +end + +def fun_l18_n95(x) + if (x < 1) + fun_l19_n647(x) + else + fun_l19_n337(x) + end +end + +def fun_l18_n96(x) + if (x < 1) + fun_l19_n794(x) + else + fun_l19_n611(x) + end +end + +def fun_l18_n97(x) + if (x < 1) + fun_l19_n752(x) + else + fun_l19_n548(x) + end +end + +def fun_l18_n98(x) + if (x < 1) + fun_l19_n710(x) + else + fun_l19_n685(x) + end +end + +def fun_l18_n99(x) + if (x < 1) + fun_l19_n711(x) + else + fun_l19_n307(x) + end +end + +def fun_l18_n100(x) + if (x < 1) + fun_l19_n834(x) + else + fun_l19_n355(x) + end +end + +def fun_l18_n101(x) + if (x < 1) + fun_l19_n473(x) + else + fun_l19_n924(x) + end +end + +def fun_l18_n102(x) + if (x < 1) + fun_l19_n79(x) + else + fun_l19_n87(x) + end +end + +def fun_l18_n103(x) + if (x < 1) + fun_l19_n27(x) + else + fun_l19_n914(x) + end +end + +def fun_l18_n104(x) + if (x < 1) + fun_l19_n327(x) + else + fun_l19_n136(x) + end +end + +def fun_l18_n105(x) + if (x < 1) + fun_l19_n42(x) + else + fun_l19_n289(x) + end +end + +def fun_l18_n106(x) + if (x < 1) + fun_l19_n371(x) + else + fun_l19_n453(x) + end +end + +def fun_l18_n107(x) + if (x < 1) + fun_l19_n579(x) + else + fun_l19_n500(x) + end +end + +def fun_l18_n108(x) + if (x < 1) + fun_l19_n351(x) + else + fun_l19_n683(x) + end +end + +def fun_l18_n109(x) + if (x < 1) + fun_l19_n831(x) + else + fun_l19_n310(x) + end +end + +def fun_l18_n110(x) + if (x < 1) + fun_l19_n618(x) + else + fun_l19_n113(x) + end +end + +def fun_l18_n111(x) + if (x < 1) + fun_l19_n147(x) + else + fun_l19_n324(x) + end +end + +def fun_l18_n112(x) + if (x < 1) + fun_l19_n97(x) + else + fun_l19_n901(x) + end +end + +def fun_l18_n113(x) + if (x < 1) + fun_l19_n223(x) + else + fun_l19_n819(x) + end +end + +def fun_l18_n114(x) + if (x < 1) + fun_l19_n929(x) + else + fun_l19_n143(x) + end +end + +def fun_l18_n115(x) + if (x < 1) + fun_l19_n697(x) + else + fun_l19_n934(x) + end +end + +def fun_l18_n116(x) + if (x < 1) + fun_l19_n143(x) + else + fun_l19_n815(x) + end +end + +def fun_l18_n117(x) + if (x < 1) + fun_l19_n889(x) + else + fun_l19_n859(x) + end +end + +def fun_l18_n118(x) + if (x < 1) + fun_l19_n233(x) + else + fun_l19_n6(x) + end +end + +def fun_l18_n119(x) + if (x < 1) + fun_l19_n490(x) + else + fun_l19_n783(x) + end +end + +def fun_l18_n120(x) + if (x < 1) + fun_l19_n930(x) + else + fun_l19_n376(x) + end +end + +def fun_l18_n121(x) + if (x < 1) + fun_l19_n567(x) + else + fun_l19_n882(x) + end +end + +def fun_l18_n122(x) + if (x < 1) + fun_l19_n532(x) + else + fun_l19_n294(x) + end +end + +def fun_l18_n123(x) + if (x < 1) + fun_l19_n20(x) + else + fun_l19_n433(x) + end +end + +def fun_l18_n124(x) + if (x < 1) + fun_l19_n301(x) + else + fun_l19_n591(x) + end +end + +def fun_l18_n125(x) + if (x < 1) + fun_l19_n424(x) + else + fun_l19_n524(x) + end +end + +def fun_l18_n126(x) + if (x < 1) + fun_l19_n12(x) + else + fun_l19_n537(x) + end +end + +def fun_l18_n127(x) + if (x < 1) + fun_l19_n548(x) + else + fun_l19_n850(x) + end +end + +def fun_l18_n128(x) + if (x < 1) + fun_l19_n463(x) + else + fun_l19_n714(x) + end +end + +def fun_l18_n129(x) + if (x < 1) + fun_l19_n438(x) + else + fun_l19_n667(x) + end +end + +def fun_l18_n130(x) + if (x < 1) + fun_l19_n481(x) + else + fun_l19_n236(x) + end +end + +def fun_l18_n131(x) + if (x < 1) + fun_l19_n84(x) + else + fun_l19_n370(x) + end +end + +def fun_l18_n132(x) + if (x < 1) + fun_l19_n447(x) + else + fun_l19_n740(x) + end +end + +def fun_l18_n133(x) + if (x < 1) + fun_l19_n807(x) + else + fun_l19_n595(x) + end +end + +def fun_l18_n134(x) + if (x < 1) + fun_l19_n716(x) + else + fun_l19_n440(x) + end +end + +def fun_l18_n135(x) + if (x < 1) + fun_l19_n657(x) + else + fun_l19_n683(x) + end +end + +def fun_l18_n136(x) + if (x < 1) + fun_l19_n683(x) + else + fun_l19_n344(x) + end +end + +def fun_l18_n137(x) + if (x < 1) + fun_l19_n228(x) + else + fun_l19_n186(x) + end +end + +def fun_l18_n138(x) + if (x < 1) + fun_l19_n666(x) + else + fun_l19_n66(x) + end +end + +def fun_l18_n139(x) + if (x < 1) + fun_l19_n416(x) + else + fun_l19_n398(x) + end +end + +def fun_l18_n140(x) + if (x < 1) + fun_l19_n766(x) + else + fun_l19_n534(x) + end +end + +def fun_l18_n141(x) + if (x < 1) + fun_l19_n370(x) + else + fun_l19_n653(x) + end +end + +def fun_l18_n142(x) + if (x < 1) + fun_l19_n953(x) + else + fun_l19_n917(x) + end +end + +def fun_l18_n143(x) + if (x < 1) + fun_l19_n989(x) + else + fun_l19_n862(x) + end +end + +def fun_l18_n144(x) + if (x < 1) + fun_l19_n969(x) + else + fun_l19_n243(x) + end +end + +def fun_l18_n145(x) + if (x < 1) + fun_l19_n379(x) + else + fun_l19_n315(x) + end +end + +def fun_l18_n146(x) + if (x < 1) + fun_l19_n360(x) + else + fun_l19_n585(x) + end +end + +def fun_l18_n147(x) + if (x < 1) + fun_l19_n4(x) + else + fun_l19_n372(x) + end +end + +def fun_l18_n148(x) + if (x < 1) + fun_l19_n395(x) + else + fun_l19_n817(x) + end +end + +def fun_l18_n149(x) + if (x < 1) + fun_l19_n237(x) + else + fun_l19_n506(x) + end +end + +def fun_l18_n150(x) + if (x < 1) + fun_l19_n940(x) + else + fun_l19_n380(x) + end +end + +def fun_l18_n151(x) + if (x < 1) + fun_l19_n190(x) + else + fun_l19_n925(x) + end +end + +def fun_l18_n152(x) + if (x < 1) + fun_l19_n810(x) + else + fun_l19_n958(x) + end +end + +def fun_l18_n153(x) + if (x < 1) + fun_l19_n69(x) + else + fun_l19_n19(x) + end +end + +def fun_l18_n154(x) + if (x < 1) + fun_l19_n984(x) + else + fun_l19_n149(x) + end +end + +def fun_l18_n155(x) + if (x < 1) + fun_l19_n179(x) + else + fun_l19_n583(x) + end +end + +def fun_l18_n156(x) + if (x < 1) + fun_l19_n583(x) + else + fun_l19_n374(x) + end +end + +def fun_l18_n157(x) + if (x < 1) + fun_l19_n908(x) + else + fun_l19_n769(x) + end +end + +def fun_l18_n158(x) + if (x < 1) + fun_l19_n288(x) + else + fun_l19_n715(x) + end +end + +def fun_l18_n159(x) + if (x < 1) + fun_l19_n742(x) + else + fun_l19_n733(x) + end +end + +def fun_l18_n160(x) + if (x < 1) + fun_l19_n994(x) + else + fun_l19_n434(x) + end +end + +def fun_l18_n161(x) + if (x < 1) + fun_l19_n440(x) + else + fun_l19_n994(x) + end +end + +def fun_l18_n162(x) + if (x < 1) + fun_l19_n400(x) + else + fun_l19_n632(x) + end +end + +def fun_l18_n163(x) + if (x < 1) + fun_l19_n237(x) + else + fun_l19_n369(x) + end +end + +def fun_l18_n164(x) + if (x < 1) + fun_l19_n431(x) + else + fun_l19_n276(x) + end +end + +def fun_l18_n165(x) + if (x < 1) + fun_l19_n173(x) + else + fun_l19_n93(x) + end +end + +def fun_l18_n166(x) + if (x < 1) + fun_l19_n875(x) + else + fun_l19_n568(x) + end +end + +def fun_l18_n167(x) + if (x < 1) + fun_l19_n61(x) + else + fun_l19_n79(x) + end +end + +def fun_l18_n168(x) + if (x < 1) + fun_l19_n683(x) + else + fun_l19_n958(x) + end +end + +def fun_l18_n169(x) + if (x < 1) + fun_l19_n419(x) + else + fun_l19_n648(x) + end +end + +def fun_l18_n170(x) + if (x < 1) + fun_l19_n152(x) + else + fun_l19_n746(x) + end +end + +def fun_l18_n171(x) + if (x < 1) + fun_l19_n670(x) + else + fun_l19_n974(x) + end +end + +def fun_l18_n172(x) + if (x < 1) + fun_l19_n142(x) + else + fun_l19_n751(x) + end +end + +def fun_l18_n173(x) + if (x < 1) + fun_l19_n640(x) + else + fun_l19_n911(x) + end +end + +def fun_l18_n174(x) + if (x < 1) + fun_l19_n256(x) + else + fun_l19_n414(x) + end +end + +def fun_l18_n175(x) + if (x < 1) + fun_l19_n207(x) + else + fun_l19_n80(x) + end +end + +def fun_l18_n176(x) + if (x < 1) + fun_l19_n317(x) + else + fun_l19_n22(x) + end +end + +def fun_l18_n177(x) + if (x < 1) + fun_l19_n457(x) + else + fun_l19_n723(x) + end +end + +def fun_l18_n178(x) + if (x < 1) + fun_l19_n36(x) + else + fun_l19_n44(x) + end +end + +def fun_l18_n179(x) + if (x < 1) + fun_l19_n92(x) + else + fun_l19_n75(x) + end +end + +def fun_l18_n180(x) + if (x < 1) + fun_l19_n878(x) + else + fun_l19_n318(x) + end +end + +def fun_l18_n181(x) + if (x < 1) + fun_l19_n499(x) + else + fun_l19_n462(x) + end +end + +def fun_l18_n182(x) + if (x < 1) + fun_l19_n172(x) + else + fun_l19_n91(x) + end +end + +def fun_l18_n183(x) + if (x < 1) + fun_l19_n549(x) + else + fun_l19_n126(x) + end +end + +def fun_l18_n184(x) + if (x < 1) + fun_l19_n484(x) + else + fun_l19_n45(x) + end +end + +def fun_l18_n185(x) + if (x < 1) + fun_l19_n237(x) + else + fun_l19_n651(x) + end +end + +def fun_l18_n186(x) + if (x < 1) + fun_l19_n458(x) + else + fun_l19_n466(x) + end +end + +def fun_l18_n187(x) + if (x < 1) + fun_l19_n856(x) + else + fun_l19_n184(x) + end +end + +def fun_l18_n188(x) + if (x < 1) + fun_l19_n432(x) + else + fun_l19_n251(x) + end +end + +def fun_l18_n189(x) + if (x < 1) + fun_l19_n719(x) + else + fun_l19_n442(x) + end +end + +def fun_l18_n190(x) + if (x < 1) + fun_l19_n516(x) + else + fun_l19_n331(x) + end +end + +def fun_l18_n191(x) + if (x < 1) + fun_l19_n342(x) + else + fun_l19_n750(x) + end +end + +def fun_l18_n192(x) + if (x < 1) + fun_l19_n820(x) + else + fun_l19_n137(x) + end +end + +def fun_l18_n193(x) + if (x < 1) + fun_l19_n514(x) + else + fun_l19_n594(x) + end +end + +def fun_l18_n194(x) + if (x < 1) + fun_l19_n744(x) + else + fun_l19_n605(x) + end +end + +def fun_l18_n195(x) + if (x < 1) + fun_l19_n428(x) + else + fun_l19_n528(x) + end +end + +def fun_l18_n196(x) + if (x < 1) + fun_l19_n291(x) + else + fun_l19_n382(x) + end +end + +def fun_l18_n197(x) + if (x < 1) + fun_l19_n238(x) + else + fun_l19_n38(x) + end +end + +def fun_l18_n198(x) + if (x < 1) + fun_l19_n332(x) + else + fun_l19_n112(x) + end +end + +def fun_l18_n199(x) + if (x < 1) + fun_l19_n703(x) + else + fun_l19_n108(x) + end +end + +def fun_l18_n200(x) + if (x < 1) + fun_l19_n917(x) + else + fun_l19_n629(x) + end +end + +def fun_l18_n201(x) + if (x < 1) + fun_l19_n402(x) + else + fun_l19_n223(x) + end +end + +def fun_l18_n202(x) + if (x < 1) + fun_l19_n9(x) + else + fun_l19_n318(x) + end +end + +def fun_l18_n203(x) + if (x < 1) + fun_l19_n560(x) + else + fun_l19_n77(x) + end +end + +def fun_l18_n204(x) + if (x < 1) + fun_l19_n379(x) + else + fun_l19_n903(x) + end +end + +def fun_l18_n205(x) + if (x < 1) + fun_l19_n185(x) + else + fun_l19_n174(x) + end +end + +def fun_l18_n206(x) + if (x < 1) + fun_l19_n738(x) + else + fun_l19_n518(x) + end +end + +def fun_l18_n207(x) + if (x < 1) + fun_l19_n343(x) + else + fun_l19_n567(x) + end +end + +def fun_l18_n208(x) + if (x < 1) + fun_l19_n546(x) + else + fun_l19_n370(x) + end +end + +def fun_l18_n209(x) + if (x < 1) + fun_l19_n589(x) + else + fun_l19_n511(x) + end +end + +def fun_l18_n210(x) + if (x < 1) + fun_l19_n507(x) + else + fun_l19_n912(x) + end +end + +def fun_l18_n211(x) + if (x < 1) + fun_l19_n779(x) + else + fun_l19_n133(x) + end +end + +def fun_l18_n212(x) + if (x < 1) + fun_l19_n400(x) + else + fun_l19_n345(x) + end +end + +def fun_l18_n213(x) + if (x < 1) + fun_l19_n214(x) + else + fun_l19_n393(x) + end +end + +def fun_l18_n214(x) + if (x < 1) + fun_l19_n829(x) + else + fun_l19_n769(x) + end +end + +def fun_l18_n215(x) + if (x < 1) + fun_l19_n835(x) + else + fun_l19_n80(x) + end +end + +def fun_l18_n216(x) + if (x < 1) + fun_l19_n640(x) + else + fun_l19_n836(x) + end +end + +def fun_l18_n217(x) + if (x < 1) + fun_l19_n861(x) + else + fun_l19_n801(x) + end +end + +def fun_l18_n218(x) + if (x < 1) + fun_l19_n316(x) + else + fun_l19_n263(x) + end +end + +def fun_l18_n219(x) + if (x < 1) + fun_l19_n231(x) + else + fun_l19_n315(x) + end +end + +def fun_l18_n220(x) + if (x < 1) + fun_l19_n700(x) + else + fun_l19_n276(x) + end +end + +def fun_l18_n221(x) + if (x < 1) + fun_l19_n654(x) + else + fun_l19_n32(x) + end +end + +def fun_l18_n222(x) + if (x < 1) + fun_l19_n758(x) + else + fun_l19_n598(x) + end +end + +def fun_l18_n223(x) + if (x < 1) + fun_l19_n819(x) + else + fun_l19_n764(x) + end +end + +def fun_l18_n224(x) + if (x < 1) + fun_l19_n31(x) + else + fun_l19_n51(x) + end +end + +def fun_l18_n225(x) + if (x < 1) + fun_l19_n704(x) + else + fun_l19_n932(x) + end +end + +def fun_l18_n226(x) + if (x < 1) + fun_l19_n635(x) + else + fun_l19_n411(x) + end +end + +def fun_l18_n227(x) + if (x < 1) + fun_l19_n368(x) + else + fun_l19_n472(x) + end +end + +def fun_l18_n228(x) + if (x < 1) + fun_l19_n928(x) + else + fun_l19_n357(x) + end +end + +def fun_l18_n229(x) + if (x < 1) + fun_l19_n503(x) + else + fun_l19_n495(x) + end +end + +def fun_l18_n230(x) + if (x < 1) + fun_l19_n497(x) + else + fun_l19_n73(x) + end +end + +def fun_l18_n231(x) + if (x < 1) + fun_l19_n718(x) + else + fun_l19_n971(x) + end +end + +def fun_l18_n232(x) + if (x < 1) + fun_l19_n314(x) + else + fun_l19_n100(x) + end +end + +def fun_l18_n233(x) + if (x < 1) + fun_l19_n490(x) + else + fun_l19_n569(x) + end +end + +def fun_l18_n234(x) + if (x < 1) + fun_l19_n309(x) + else + fun_l19_n806(x) + end +end + +def fun_l18_n235(x) + if (x < 1) + fun_l19_n839(x) + else + fun_l19_n388(x) + end +end + +def fun_l18_n236(x) + if (x < 1) + fun_l19_n158(x) + else + fun_l19_n438(x) + end +end + +def fun_l18_n237(x) + if (x < 1) + fun_l19_n181(x) + else + fun_l19_n728(x) + end +end + +def fun_l18_n238(x) + if (x < 1) + fun_l19_n238(x) + else + fun_l19_n41(x) + end +end + +def fun_l18_n239(x) + if (x < 1) + fun_l19_n342(x) + else + fun_l19_n756(x) + end +end + +def fun_l18_n240(x) + if (x < 1) + fun_l19_n873(x) + else + fun_l19_n274(x) + end +end + +def fun_l18_n241(x) + if (x < 1) + fun_l19_n273(x) + else + fun_l19_n740(x) + end +end + +def fun_l18_n242(x) + if (x < 1) + fun_l19_n256(x) + else + fun_l19_n99(x) + end +end + +def fun_l18_n243(x) + if (x < 1) + fun_l19_n482(x) + else + fun_l19_n569(x) + end +end + +def fun_l18_n244(x) + if (x < 1) + fun_l19_n598(x) + else + fun_l19_n393(x) + end +end + +def fun_l18_n245(x) + if (x < 1) + fun_l19_n320(x) + else + fun_l19_n164(x) + end +end + +def fun_l18_n246(x) + if (x < 1) + fun_l19_n803(x) + else + fun_l19_n240(x) + end +end + +def fun_l18_n247(x) + if (x < 1) + fun_l19_n790(x) + else + fun_l19_n55(x) + end +end + +def fun_l18_n248(x) + if (x < 1) + fun_l19_n193(x) + else + fun_l19_n754(x) + end +end + +def fun_l18_n249(x) + if (x < 1) + fun_l19_n122(x) + else + fun_l19_n841(x) + end +end + +def fun_l18_n250(x) + if (x < 1) + fun_l19_n724(x) + else + fun_l19_n359(x) + end +end + +def fun_l18_n251(x) + if (x < 1) + fun_l19_n497(x) + else + fun_l19_n777(x) + end +end + +def fun_l18_n252(x) + if (x < 1) + fun_l19_n986(x) + else + fun_l19_n666(x) + end +end + +def fun_l18_n253(x) + if (x < 1) + fun_l19_n864(x) + else + fun_l19_n320(x) + end +end + +def fun_l18_n254(x) + if (x < 1) + fun_l19_n386(x) + else + fun_l19_n582(x) + end +end + +def fun_l18_n255(x) + if (x < 1) + fun_l19_n434(x) + else + fun_l19_n224(x) + end +end + +def fun_l18_n256(x) + if (x < 1) + fun_l19_n921(x) + else + fun_l19_n8(x) + end +end + +def fun_l18_n257(x) + if (x < 1) + fun_l19_n789(x) + else + fun_l19_n546(x) + end +end + +def fun_l18_n258(x) + if (x < 1) + fun_l19_n324(x) + else + fun_l19_n987(x) + end +end + +def fun_l18_n259(x) + if (x < 1) + fun_l19_n279(x) + else + fun_l19_n180(x) + end +end + +def fun_l18_n260(x) + if (x < 1) + fun_l19_n596(x) + else + fun_l19_n670(x) + end +end + +def fun_l18_n261(x) + if (x < 1) + fun_l19_n940(x) + else + fun_l19_n982(x) + end +end + +def fun_l18_n262(x) + if (x < 1) + fun_l19_n54(x) + else + fun_l19_n342(x) + end +end + +def fun_l18_n263(x) + if (x < 1) + fun_l19_n815(x) + else + fun_l19_n663(x) + end +end + +def fun_l18_n264(x) + if (x < 1) + fun_l19_n794(x) + else + fun_l19_n251(x) + end +end + +def fun_l18_n265(x) + if (x < 1) + fun_l19_n485(x) + else + fun_l19_n896(x) + end +end + +def fun_l18_n266(x) + if (x < 1) + fun_l19_n346(x) + else + fun_l19_n151(x) + end +end + +def fun_l18_n267(x) + if (x < 1) + fun_l19_n162(x) + else + fun_l19_n395(x) + end +end + +def fun_l18_n268(x) + if (x < 1) + fun_l19_n76(x) + else + fun_l19_n25(x) + end +end + +def fun_l18_n269(x) + if (x < 1) + fun_l19_n943(x) + else + fun_l19_n587(x) + end +end + +def fun_l18_n270(x) + if (x < 1) + fun_l19_n663(x) + else + fun_l19_n255(x) + end +end + +def fun_l18_n271(x) + if (x < 1) + fun_l19_n307(x) + else + fun_l19_n261(x) + end +end + +def fun_l18_n272(x) + if (x < 1) + fun_l19_n478(x) + else + fun_l19_n600(x) + end +end + +def fun_l18_n273(x) + if (x < 1) + fun_l19_n345(x) + else + fun_l19_n877(x) + end +end + +def fun_l18_n274(x) + if (x < 1) + fun_l19_n637(x) + else + fun_l19_n27(x) + end +end + +def fun_l18_n275(x) + if (x < 1) + fun_l19_n752(x) + else + fun_l19_n946(x) + end +end + +def fun_l18_n276(x) + if (x < 1) + fun_l19_n571(x) + else + fun_l19_n973(x) + end +end + +def fun_l18_n277(x) + if (x < 1) + fun_l19_n274(x) + else + fun_l19_n673(x) + end +end + +def fun_l18_n278(x) + if (x < 1) + fun_l19_n922(x) + else + fun_l19_n826(x) + end +end + +def fun_l18_n279(x) + if (x < 1) + fun_l19_n294(x) + else + fun_l19_n236(x) + end +end + +def fun_l18_n280(x) + if (x < 1) + fun_l19_n661(x) + else + fun_l19_n531(x) + end +end + +def fun_l18_n281(x) + if (x < 1) + fun_l19_n295(x) + else + fun_l19_n961(x) + end +end + +def fun_l18_n282(x) + if (x < 1) + fun_l19_n902(x) + else + fun_l19_n364(x) + end +end + +def fun_l18_n283(x) + if (x < 1) + fun_l19_n147(x) + else + fun_l19_n709(x) + end +end + +def fun_l18_n284(x) + if (x < 1) + fun_l19_n394(x) + else + fun_l19_n757(x) + end +end + +def fun_l18_n285(x) + if (x < 1) + fun_l19_n372(x) + else + fun_l19_n45(x) + end +end + +def fun_l18_n286(x) + if (x < 1) + fun_l19_n323(x) + else + fun_l19_n128(x) + end +end + +def fun_l18_n287(x) + if (x < 1) + fun_l19_n50(x) + else + fun_l19_n650(x) + end +end + +def fun_l18_n288(x) + if (x < 1) + fun_l19_n300(x) + else + fun_l19_n308(x) + end +end + +def fun_l18_n289(x) + if (x < 1) + fun_l19_n2(x) + else + fun_l19_n27(x) + end +end + +def fun_l18_n290(x) + if (x < 1) + fun_l19_n341(x) + else + fun_l19_n281(x) + end +end + +def fun_l18_n291(x) + if (x < 1) + fun_l19_n797(x) + else + fun_l19_n575(x) + end +end + +def fun_l18_n292(x) + if (x < 1) + fun_l19_n740(x) + else + fun_l19_n772(x) + end +end + +def fun_l18_n293(x) + if (x < 1) + fun_l19_n707(x) + else + fun_l19_n456(x) + end +end + +def fun_l18_n294(x) + if (x < 1) + fun_l19_n714(x) + else + fun_l19_n601(x) + end +end + +def fun_l18_n295(x) + if (x < 1) + fun_l19_n298(x) + else + fun_l19_n367(x) + end +end + +def fun_l18_n296(x) + if (x < 1) + fun_l19_n0(x) + else + fun_l19_n970(x) + end +end + +def fun_l18_n297(x) + if (x < 1) + fun_l19_n703(x) + else + fun_l19_n673(x) + end +end + +def fun_l18_n298(x) + if (x < 1) + fun_l19_n890(x) + else + fun_l19_n932(x) + end +end + +def fun_l18_n299(x) + if (x < 1) + fun_l19_n152(x) + else + fun_l19_n784(x) + end +end + +def fun_l18_n300(x) + if (x < 1) + fun_l19_n24(x) + else + fun_l19_n449(x) + end +end + +def fun_l18_n301(x) + if (x < 1) + fun_l19_n161(x) + else + fun_l19_n51(x) + end +end + +def fun_l18_n302(x) + if (x < 1) + fun_l19_n695(x) + else + fun_l19_n604(x) + end +end + +def fun_l18_n303(x) + if (x < 1) + fun_l19_n415(x) + else + fun_l19_n752(x) + end +end + +def fun_l18_n304(x) + if (x < 1) + fun_l19_n737(x) + else + fun_l19_n944(x) + end +end + +def fun_l18_n305(x) + if (x < 1) + fun_l19_n833(x) + else + fun_l19_n98(x) + end +end + +def fun_l18_n306(x) + if (x < 1) + fun_l19_n598(x) + else + fun_l19_n601(x) + end +end + +def fun_l18_n307(x) + if (x < 1) + fun_l19_n728(x) + else + fun_l19_n116(x) + end +end + +def fun_l18_n308(x) + if (x < 1) + fun_l19_n892(x) + else + fun_l19_n826(x) + end +end + +def fun_l18_n309(x) + if (x < 1) + fun_l19_n926(x) + else + fun_l19_n119(x) + end +end + +def fun_l18_n310(x) + if (x < 1) + fun_l19_n194(x) + else + fun_l19_n331(x) + end +end + +def fun_l18_n311(x) + if (x < 1) + fun_l19_n490(x) + else + fun_l19_n401(x) + end +end + +def fun_l18_n312(x) + if (x < 1) + fun_l19_n727(x) + else + fun_l19_n193(x) + end +end + +def fun_l18_n313(x) + if (x < 1) + fun_l19_n643(x) + else + fun_l19_n327(x) + end +end + +def fun_l18_n314(x) + if (x < 1) + fun_l19_n747(x) + else + fun_l19_n938(x) + end +end + +def fun_l18_n315(x) + if (x < 1) + fun_l19_n153(x) + else + fun_l19_n438(x) + end +end + +def fun_l18_n316(x) + if (x < 1) + fun_l19_n719(x) + else + fun_l19_n471(x) + end +end + +def fun_l18_n317(x) + if (x < 1) + fun_l19_n105(x) + else + fun_l19_n832(x) + end +end + +def fun_l18_n318(x) + if (x < 1) + fun_l19_n652(x) + else + fun_l19_n826(x) + end +end + +def fun_l18_n319(x) + if (x < 1) + fun_l19_n3(x) + else + fun_l19_n250(x) + end +end + +def fun_l18_n320(x) + if (x < 1) + fun_l19_n854(x) + else + fun_l19_n371(x) + end +end + +def fun_l18_n321(x) + if (x < 1) + fun_l19_n241(x) + else + fun_l19_n51(x) + end +end + +def fun_l18_n322(x) + if (x < 1) + fun_l19_n832(x) + else + fun_l19_n897(x) + end +end + +def fun_l18_n323(x) + if (x < 1) + fun_l19_n472(x) + else + fun_l19_n838(x) + end +end + +def fun_l18_n324(x) + if (x < 1) + fun_l19_n844(x) + else + fun_l19_n228(x) + end +end + +def fun_l18_n325(x) + if (x < 1) + fun_l19_n132(x) + else + fun_l19_n424(x) + end +end + +def fun_l18_n326(x) + if (x < 1) + fun_l19_n311(x) + else + fun_l19_n388(x) + end +end + +def fun_l18_n327(x) + if (x < 1) + fun_l19_n709(x) + else + fun_l19_n98(x) + end +end + +def fun_l18_n328(x) + if (x < 1) + fun_l19_n342(x) + else + fun_l19_n743(x) + end +end + +def fun_l18_n329(x) + if (x < 1) + fun_l19_n984(x) + else + fun_l19_n762(x) + end +end + +def fun_l18_n330(x) + if (x < 1) + fun_l19_n358(x) + else + fun_l19_n624(x) + end +end + +def fun_l18_n331(x) + if (x < 1) + fun_l19_n574(x) + else + fun_l19_n35(x) + end +end + +def fun_l18_n332(x) + if (x < 1) + fun_l19_n564(x) + else + fun_l19_n629(x) + end +end + +def fun_l18_n333(x) + if (x < 1) + fun_l19_n70(x) + else + fun_l19_n150(x) + end +end + +def fun_l18_n334(x) + if (x < 1) + fun_l19_n538(x) + else + fun_l19_n239(x) + end +end + +def fun_l18_n335(x) + if (x < 1) + fun_l19_n818(x) + else + fun_l19_n878(x) + end +end + +def fun_l18_n336(x) + if (x < 1) + fun_l19_n233(x) + else + fun_l19_n286(x) + end +end + +def fun_l18_n337(x) + if (x < 1) + fun_l19_n731(x) + else + fun_l19_n416(x) + end +end + +def fun_l18_n338(x) + if (x < 1) + fun_l19_n917(x) + else + fun_l19_n710(x) + end +end + +def fun_l18_n339(x) + if (x < 1) + fun_l19_n638(x) + else + fun_l19_n187(x) + end +end + +def fun_l18_n340(x) + if (x < 1) + fun_l19_n922(x) + else + fun_l19_n767(x) + end +end + +def fun_l18_n341(x) + if (x < 1) + fun_l19_n9(x) + else + fun_l19_n708(x) + end +end + +def fun_l18_n342(x) + if (x < 1) + fun_l19_n76(x) + else + fun_l19_n479(x) + end +end + +def fun_l18_n343(x) + if (x < 1) + fun_l19_n679(x) + else + fun_l19_n85(x) + end +end + +def fun_l18_n344(x) + if (x < 1) + fun_l19_n725(x) + else + fun_l19_n809(x) + end +end + +def fun_l18_n345(x) + if (x < 1) + fun_l19_n680(x) + else + fun_l19_n416(x) + end +end + +def fun_l18_n346(x) + if (x < 1) + fun_l19_n66(x) + else + fun_l19_n36(x) + end +end + +def fun_l18_n347(x) + if (x < 1) + fun_l19_n420(x) + else + fun_l19_n879(x) + end +end + +def fun_l18_n348(x) + if (x < 1) + fun_l19_n653(x) + else + fun_l19_n634(x) + end +end + +def fun_l18_n349(x) + if (x < 1) + fun_l19_n134(x) + else + fun_l19_n840(x) + end +end + +def fun_l18_n350(x) + if (x < 1) + fun_l19_n21(x) + else + fun_l19_n843(x) + end +end + +def fun_l18_n351(x) + if (x < 1) + fun_l19_n917(x) + else + fun_l19_n101(x) + end +end + +def fun_l18_n352(x) + if (x < 1) + fun_l19_n541(x) + else + fun_l19_n646(x) + end +end + +def fun_l18_n353(x) + if (x < 1) + fun_l19_n555(x) + else + fun_l19_n648(x) + end +end + +def fun_l18_n354(x) + if (x < 1) + fun_l19_n431(x) + else + fun_l19_n736(x) + end +end + +def fun_l18_n355(x) + if (x < 1) + fun_l19_n294(x) + else + fun_l19_n512(x) + end +end + +def fun_l18_n356(x) + if (x < 1) + fun_l19_n852(x) + else + fun_l19_n348(x) + end +end + +def fun_l18_n357(x) + if (x < 1) + fun_l19_n670(x) + else + fun_l19_n997(x) + end +end + +def fun_l18_n358(x) + if (x < 1) + fun_l19_n595(x) + else + fun_l19_n544(x) + end +end + +def fun_l18_n359(x) + if (x < 1) + fun_l19_n13(x) + else + fun_l19_n838(x) + end +end + +def fun_l18_n360(x) + if (x < 1) + fun_l19_n518(x) + else + fun_l19_n642(x) + end +end + +def fun_l18_n361(x) + if (x < 1) + fun_l19_n333(x) + else + fun_l19_n59(x) + end +end + +def fun_l18_n362(x) + if (x < 1) + fun_l19_n670(x) + else + fun_l19_n844(x) + end +end + +def fun_l18_n363(x) + if (x < 1) + fun_l19_n14(x) + else + fun_l19_n932(x) + end +end + +def fun_l18_n364(x) + if (x < 1) + fun_l19_n508(x) + else + fun_l19_n466(x) + end +end + +def fun_l18_n365(x) + if (x < 1) + fun_l19_n177(x) + else + fun_l19_n365(x) + end +end + +def fun_l18_n366(x) + if (x < 1) + fun_l19_n367(x) + else + fun_l19_n205(x) + end +end + +def fun_l18_n367(x) + if (x < 1) + fun_l19_n353(x) + else + fun_l19_n328(x) + end +end + +def fun_l18_n368(x) + if (x < 1) + fun_l19_n801(x) + else + fun_l19_n420(x) + end +end + +def fun_l18_n369(x) + if (x < 1) + fun_l19_n162(x) + else + fun_l19_n670(x) + end +end + +def fun_l18_n370(x) + if (x < 1) + fun_l19_n908(x) + else + fun_l19_n852(x) + end +end + +def fun_l18_n371(x) + if (x < 1) + fun_l19_n47(x) + else + fun_l19_n130(x) + end +end + +def fun_l18_n372(x) + if (x < 1) + fun_l19_n774(x) + else + fun_l19_n792(x) + end +end + +def fun_l18_n373(x) + if (x < 1) + fun_l19_n124(x) + else + fun_l19_n665(x) + end +end + +def fun_l18_n374(x) + if (x < 1) + fun_l19_n24(x) + else + fun_l19_n371(x) + end +end + +def fun_l18_n375(x) + if (x < 1) + fun_l19_n484(x) + else + fun_l19_n708(x) + end +end + +def fun_l18_n376(x) + if (x < 1) + fun_l19_n810(x) + else + fun_l19_n856(x) + end +end + +def fun_l18_n377(x) + if (x < 1) + fun_l19_n23(x) + else + fun_l19_n817(x) + end +end + +def fun_l18_n378(x) + if (x < 1) + fun_l19_n827(x) + else + fun_l19_n639(x) + end +end + +def fun_l18_n379(x) + if (x < 1) + fun_l19_n557(x) + else + fun_l19_n268(x) + end +end + +def fun_l18_n380(x) + if (x < 1) + fun_l19_n885(x) + else + fun_l19_n421(x) + end +end + +def fun_l18_n381(x) + if (x < 1) + fun_l19_n543(x) + else + fun_l19_n230(x) + end +end + +def fun_l18_n382(x) + if (x < 1) + fun_l19_n978(x) + else + fun_l19_n848(x) + end +end + +def fun_l18_n383(x) + if (x < 1) + fun_l19_n31(x) + else + fun_l19_n731(x) + end +end + +def fun_l18_n384(x) + if (x < 1) + fun_l19_n20(x) + else + fun_l19_n149(x) + end +end + +def fun_l18_n385(x) + if (x < 1) + fun_l19_n650(x) + else + fun_l19_n268(x) + end +end + +def fun_l18_n386(x) + if (x < 1) + fun_l19_n491(x) + else + fun_l19_n644(x) + end +end + +def fun_l18_n387(x) + if (x < 1) + fun_l19_n537(x) + else + fun_l19_n400(x) + end +end + +def fun_l18_n388(x) + if (x < 1) + fun_l19_n939(x) + else + fun_l19_n861(x) + end +end + +def fun_l18_n389(x) + if (x < 1) + fun_l19_n728(x) + else + fun_l19_n877(x) + end +end + +def fun_l18_n390(x) + if (x < 1) + fun_l19_n226(x) + else + fun_l19_n288(x) + end +end + +def fun_l18_n391(x) + if (x < 1) + fun_l19_n921(x) + else + fun_l19_n754(x) + end +end + +def fun_l18_n392(x) + if (x < 1) + fun_l19_n71(x) + else + fun_l19_n844(x) + end +end + +def fun_l18_n393(x) + if (x < 1) + fun_l19_n310(x) + else + fun_l19_n442(x) + end +end + +def fun_l18_n394(x) + if (x < 1) + fun_l19_n539(x) + else + fun_l19_n933(x) + end +end + +def fun_l18_n395(x) + if (x < 1) + fun_l19_n849(x) + else + fun_l19_n719(x) + end +end + +def fun_l18_n396(x) + if (x < 1) + fun_l19_n922(x) + else + fun_l19_n435(x) + end +end + +def fun_l18_n397(x) + if (x < 1) + fun_l19_n916(x) + else + fun_l19_n399(x) + end +end + +def fun_l18_n398(x) + if (x < 1) + fun_l19_n820(x) + else + fun_l19_n650(x) + end +end + +def fun_l18_n399(x) + if (x < 1) + fun_l19_n497(x) + else + fun_l19_n678(x) + end +end + +def fun_l18_n400(x) + if (x < 1) + fun_l19_n562(x) + else + fun_l19_n392(x) + end +end + +def fun_l18_n401(x) + if (x < 1) + fun_l19_n298(x) + else + fun_l19_n61(x) + end +end + +def fun_l18_n402(x) + if (x < 1) + fun_l19_n803(x) + else + fun_l19_n535(x) + end +end + +def fun_l18_n403(x) + if (x < 1) + fun_l19_n335(x) + else + fun_l19_n431(x) + end +end + +def fun_l18_n404(x) + if (x < 1) + fun_l19_n558(x) + else + fun_l19_n821(x) + end +end + +def fun_l18_n405(x) + if (x < 1) + fun_l19_n608(x) + else + fun_l19_n415(x) + end +end + +def fun_l18_n406(x) + if (x < 1) + fun_l19_n709(x) + else + fun_l19_n635(x) + end +end + +def fun_l18_n407(x) + if (x < 1) + fun_l19_n432(x) + else + fun_l19_n923(x) + end +end + +def fun_l18_n408(x) + if (x < 1) + fun_l19_n612(x) + else + fun_l19_n386(x) + end +end + +def fun_l18_n409(x) + if (x < 1) + fun_l19_n1(x) + else + fun_l19_n679(x) + end +end + +def fun_l18_n410(x) + if (x < 1) + fun_l19_n998(x) + else + fun_l19_n969(x) + end +end + +def fun_l18_n411(x) + if (x < 1) + fun_l19_n210(x) + else + fun_l19_n642(x) + end +end + +def fun_l18_n412(x) + if (x < 1) + fun_l19_n902(x) + else + fun_l19_n591(x) + end +end + +def fun_l18_n413(x) + if (x < 1) + fun_l19_n417(x) + else + fun_l19_n192(x) + end +end + +def fun_l18_n414(x) + if (x < 1) + fun_l19_n543(x) + else + fun_l19_n277(x) + end +end + +def fun_l18_n415(x) + if (x < 1) + fun_l19_n145(x) + else + fun_l19_n157(x) + end +end + +def fun_l18_n416(x) + if (x < 1) + fun_l19_n696(x) + else + fun_l19_n453(x) + end +end + +def fun_l18_n417(x) + if (x < 1) + fun_l19_n593(x) + else + fun_l19_n683(x) + end +end + +def fun_l18_n418(x) + if (x < 1) + fun_l19_n459(x) + else + fun_l19_n292(x) + end +end + +def fun_l18_n419(x) + if (x < 1) + fun_l19_n37(x) + else + fun_l19_n281(x) + end +end + +def fun_l18_n420(x) + if (x < 1) + fun_l19_n39(x) + else + fun_l19_n642(x) + end +end + +def fun_l18_n421(x) + if (x < 1) + fun_l19_n942(x) + else + fun_l19_n997(x) + end +end + +def fun_l18_n422(x) + if (x < 1) + fun_l19_n18(x) + else + fun_l19_n301(x) + end +end + +def fun_l18_n423(x) + if (x < 1) + fun_l19_n473(x) + else + fun_l19_n231(x) + end +end + +def fun_l18_n424(x) + if (x < 1) + fun_l19_n331(x) + else + fun_l19_n110(x) + end +end + +def fun_l18_n425(x) + if (x < 1) + fun_l19_n786(x) + else + fun_l19_n991(x) + end +end + +def fun_l18_n426(x) + if (x < 1) + fun_l19_n440(x) + else + fun_l19_n17(x) + end +end + +def fun_l18_n427(x) + if (x < 1) + fun_l19_n294(x) + else + fun_l19_n3(x) + end +end + +def fun_l18_n428(x) + if (x < 1) + fun_l19_n369(x) + else + fun_l19_n576(x) + end +end + +def fun_l18_n429(x) + if (x < 1) + fun_l19_n818(x) + else + fun_l19_n236(x) + end +end + +def fun_l18_n430(x) + if (x < 1) + fun_l19_n360(x) + else + fun_l19_n443(x) + end +end + +def fun_l18_n431(x) + if (x < 1) + fun_l19_n432(x) + else + fun_l19_n863(x) + end +end + +def fun_l18_n432(x) + if (x < 1) + fun_l19_n591(x) + else + fun_l19_n167(x) + end +end + +def fun_l18_n433(x) + if (x < 1) + fun_l19_n955(x) + else + fun_l19_n265(x) + end +end + +def fun_l18_n434(x) + if (x < 1) + fun_l19_n374(x) + else + fun_l19_n812(x) + end +end + +def fun_l18_n435(x) + if (x < 1) + fun_l19_n712(x) + else + fun_l19_n603(x) + end +end + +def fun_l18_n436(x) + if (x < 1) + fun_l19_n750(x) + else + fun_l19_n852(x) + end +end + +def fun_l18_n437(x) + if (x < 1) + fun_l19_n393(x) + else + fun_l19_n121(x) + end +end + +def fun_l18_n438(x) + if (x < 1) + fun_l19_n555(x) + else + fun_l19_n33(x) + end +end + +def fun_l18_n439(x) + if (x < 1) + fun_l19_n872(x) + else + fun_l19_n841(x) + end +end + +def fun_l18_n440(x) + if (x < 1) + fun_l19_n828(x) + else + fun_l19_n549(x) + end +end + +def fun_l18_n441(x) + if (x < 1) + fun_l19_n647(x) + else + fun_l19_n795(x) + end +end + +def fun_l18_n442(x) + if (x < 1) + fun_l19_n609(x) + else + fun_l19_n837(x) + end +end + +def fun_l18_n443(x) + if (x < 1) + fun_l19_n977(x) + else + fun_l19_n670(x) + end +end + +def fun_l18_n444(x) + if (x < 1) + fun_l19_n649(x) + else + fun_l19_n912(x) + end +end + +def fun_l18_n445(x) + if (x < 1) + fun_l19_n856(x) + else + fun_l19_n994(x) + end +end + +def fun_l18_n446(x) + if (x < 1) + fun_l19_n868(x) + else + fun_l19_n105(x) + end +end + +def fun_l18_n447(x) + if (x < 1) + fun_l19_n405(x) + else + fun_l19_n318(x) + end +end + +def fun_l18_n448(x) + if (x < 1) + fun_l19_n966(x) + else + fun_l19_n214(x) + end +end + +def fun_l18_n449(x) + if (x < 1) + fun_l19_n458(x) + else + fun_l19_n650(x) + end +end + +def fun_l18_n450(x) + if (x < 1) + fun_l19_n875(x) + else + fun_l19_n697(x) + end +end + +def fun_l18_n451(x) + if (x < 1) + fun_l19_n799(x) + else + fun_l19_n661(x) + end +end + +def fun_l18_n452(x) + if (x < 1) + fun_l19_n677(x) + else + fun_l19_n750(x) + end +end + +def fun_l18_n453(x) + if (x < 1) + fun_l19_n530(x) + else + fun_l19_n110(x) + end +end + +def fun_l18_n454(x) + if (x < 1) + fun_l19_n785(x) + else + fun_l19_n381(x) + end +end + +def fun_l18_n455(x) + if (x < 1) + fun_l19_n680(x) + else + fun_l19_n201(x) + end +end + +def fun_l18_n456(x) + if (x < 1) + fun_l19_n246(x) + else + fun_l19_n972(x) + end +end + +def fun_l18_n457(x) + if (x < 1) + fun_l19_n656(x) + else + fun_l19_n451(x) + end +end + +def fun_l18_n458(x) + if (x < 1) + fun_l19_n612(x) + else + fun_l19_n288(x) + end +end + +def fun_l18_n459(x) + if (x < 1) + fun_l19_n612(x) + else + fun_l19_n150(x) + end +end + +def fun_l18_n460(x) + if (x < 1) + fun_l19_n549(x) + else + fun_l19_n917(x) + end +end + +def fun_l18_n461(x) + if (x < 1) + fun_l19_n661(x) + else + fun_l19_n11(x) + end +end + +def fun_l18_n462(x) + if (x < 1) + fun_l19_n172(x) + else + fun_l19_n561(x) + end +end + +def fun_l18_n463(x) + if (x < 1) + fun_l19_n687(x) + else + fun_l19_n12(x) + end +end + +def fun_l18_n464(x) + if (x < 1) + fun_l19_n57(x) + else + fun_l19_n835(x) + end +end + +def fun_l18_n465(x) + if (x < 1) + fun_l19_n116(x) + else + fun_l19_n993(x) + end +end + +def fun_l18_n466(x) + if (x < 1) + fun_l19_n932(x) + else + fun_l19_n623(x) + end +end + +def fun_l18_n467(x) + if (x < 1) + fun_l19_n839(x) + else + fun_l19_n70(x) + end +end + +def fun_l18_n468(x) + if (x < 1) + fun_l19_n574(x) + else + fun_l19_n193(x) + end +end + +def fun_l18_n469(x) + if (x < 1) + fun_l19_n762(x) + else + fun_l19_n654(x) + end +end + +def fun_l18_n470(x) + if (x < 1) + fun_l19_n656(x) + else + fun_l19_n42(x) + end +end + +def fun_l18_n471(x) + if (x < 1) + fun_l19_n959(x) + else + fun_l19_n368(x) + end +end + +def fun_l18_n472(x) + if (x < 1) + fun_l19_n494(x) + else + fun_l19_n357(x) + end +end + +def fun_l18_n473(x) + if (x < 1) + fun_l19_n394(x) + else + fun_l19_n313(x) + end +end + +def fun_l18_n474(x) + if (x < 1) + fun_l19_n826(x) + else + fun_l19_n33(x) + end +end + +def fun_l18_n475(x) + if (x < 1) + fun_l19_n202(x) + else + fun_l19_n455(x) + end +end + +def fun_l18_n476(x) + if (x < 1) + fun_l19_n855(x) + else + fun_l19_n375(x) + end +end + +def fun_l18_n477(x) + if (x < 1) + fun_l19_n554(x) + else + fun_l19_n176(x) + end +end + +def fun_l18_n478(x) + if (x < 1) + fun_l19_n705(x) + else + fun_l19_n509(x) + end +end + +def fun_l18_n479(x) + if (x < 1) + fun_l19_n473(x) + else + fun_l19_n123(x) + end +end + +def fun_l18_n480(x) + if (x < 1) + fun_l19_n108(x) + else + fun_l19_n125(x) + end +end + +def fun_l18_n481(x) + if (x < 1) + fun_l19_n476(x) + else + fun_l19_n657(x) + end +end + +def fun_l18_n482(x) + if (x < 1) + fun_l19_n800(x) + else + fun_l19_n691(x) + end +end + +def fun_l18_n483(x) + if (x < 1) + fun_l19_n343(x) + else + fun_l19_n573(x) + end +end + +def fun_l18_n484(x) + if (x < 1) + fun_l19_n654(x) + else + fun_l19_n114(x) + end +end + +def fun_l18_n485(x) + if (x < 1) + fun_l19_n231(x) + else + fun_l19_n291(x) + end +end + +def fun_l18_n486(x) + if (x < 1) + fun_l19_n877(x) + else + fun_l19_n628(x) + end +end + +def fun_l18_n487(x) + if (x < 1) + fun_l19_n35(x) + else + fun_l19_n992(x) + end +end + +def fun_l18_n488(x) + if (x < 1) + fun_l19_n592(x) + else + fun_l19_n951(x) + end +end + +def fun_l18_n489(x) + if (x < 1) + fun_l19_n292(x) + else + fun_l19_n768(x) + end +end + +def fun_l18_n490(x) + if (x < 1) + fun_l19_n191(x) + else + fun_l19_n759(x) + end +end + +def fun_l18_n491(x) + if (x < 1) + fun_l19_n474(x) + else + fun_l19_n393(x) + end +end + +def fun_l18_n492(x) + if (x < 1) + fun_l19_n556(x) + else + fun_l19_n691(x) + end +end + +def fun_l18_n493(x) + if (x < 1) + fun_l19_n717(x) + else + fun_l19_n714(x) + end +end + +def fun_l18_n494(x) + if (x < 1) + fun_l19_n542(x) + else + fun_l19_n505(x) + end +end + +def fun_l18_n495(x) + if (x < 1) + fun_l19_n154(x) + else + fun_l19_n500(x) + end +end + +def fun_l18_n496(x) + if (x < 1) + fun_l19_n311(x) + else + fun_l19_n458(x) + end +end + +def fun_l18_n497(x) + if (x < 1) + fun_l19_n523(x) + else + fun_l19_n475(x) + end +end + +def fun_l18_n498(x) + if (x < 1) + fun_l19_n101(x) + else + fun_l19_n478(x) + end +end + +def fun_l18_n499(x) + if (x < 1) + fun_l19_n243(x) + else + fun_l19_n586(x) + end +end + +def fun_l18_n500(x) + if (x < 1) + fun_l19_n263(x) + else + fun_l19_n888(x) + end +end + +def fun_l18_n501(x) + if (x < 1) + fun_l19_n415(x) + else + fun_l19_n808(x) + end +end + +def fun_l18_n502(x) + if (x < 1) + fun_l19_n38(x) + else + fun_l19_n640(x) + end +end + +def fun_l18_n503(x) + if (x < 1) + fun_l19_n218(x) + else + fun_l19_n577(x) + end +end + +def fun_l18_n504(x) + if (x < 1) + fun_l19_n723(x) + else + fun_l19_n594(x) + end +end + +def fun_l18_n505(x) + if (x < 1) + fun_l19_n392(x) + else + fun_l19_n984(x) + end +end + +def fun_l18_n506(x) + if (x < 1) + fun_l19_n310(x) + else + fun_l19_n668(x) + end +end + +def fun_l18_n507(x) + if (x < 1) + fun_l19_n278(x) + else + fun_l19_n812(x) + end +end + +def fun_l18_n508(x) + if (x < 1) + fun_l19_n230(x) + else + fun_l19_n479(x) + end +end + +def fun_l18_n509(x) + if (x < 1) + fun_l19_n63(x) + else + fun_l19_n774(x) + end +end + +def fun_l18_n510(x) + if (x < 1) + fun_l19_n607(x) + else + fun_l19_n433(x) + end +end + +def fun_l18_n511(x) + if (x < 1) + fun_l19_n28(x) + else + fun_l19_n672(x) + end +end + +def fun_l18_n512(x) + if (x < 1) + fun_l19_n684(x) + else + fun_l19_n247(x) + end +end + +def fun_l18_n513(x) + if (x < 1) + fun_l19_n181(x) + else + fun_l19_n649(x) + end +end + +def fun_l18_n514(x) + if (x < 1) + fun_l19_n787(x) + else + fun_l19_n281(x) + end +end + +def fun_l18_n515(x) + if (x < 1) + fun_l19_n191(x) + else + fun_l19_n848(x) + end +end + +def fun_l18_n516(x) + if (x < 1) + fun_l19_n796(x) + else + fun_l19_n572(x) + end +end + +def fun_l18_n517(x) + if (x < 1) + fun_l19_n780(x) + else + fun_l19_n816(x) + end +end + +def fun_l18_n518(x) + if (x < 1) + fun_l19_n429(x) + else + fun_l19_n681(x) + end +end + +def fun_l18_n519(x) + if (x < 1) + fun_l19_n476(x) + else + fun_l19_n954(x) + end +end + +def fun_l18_n520(x) + if (x < 1) + fun_l19_n537(x) + else + fun_l19_n690(x) + end +end + +def fun_l18_n521(x) + if (x < 1) + fun_l19_n657(x) + else + fun_l19_n293(x) + end +end + +def fun_l18_n522(x) + if (x < 1) + fun_l19_n369(x) + else + fun_l19_n685(x) + end +end + +def fun_l18_n523(x) + if (x < 1) + fun_l19_n785(x) + else + fun_l19_n184(x) + end +end + +def fun_l18_n524(x) + if (x < 1) + fun_l19_n6(x) + else + fun_l19_n970(x) + end +end + +def fun_l18_n525(x) + if (x < 1) + fun_l19_n395(x) + else + fun_l19_n570(x) + end +end + +def fun_l18_n526(x) + if (x < 1) + fun_l19_n837(x) + else + fun_l19_n992(x) + end +end + +def fun_l18_n527(x) + if (x < 1) + fun_l19_n827(x) + else + fun_l19_n119(x) + end +end + +def fun_l18_n528(x) + if (x < 1) + fun_l19_n819(x) + else + fun_l19_n382(x) + end +end + +def fun_l18_n529(x) + if (x < 1) + fun_l19_n365(x) + else + fun_l19_n713(x) + end +end + +def fun_l18_n530(x) + if (x < 1) + fun_l19_n223(x) + else + fun_l19_n346(x) + end +end + +def fun_l18_n531(x) + if (x < 1) + fun_l19_n624(x) + else + fun_l19_n671(x) + end +end + +def fun_l18_n532(x) + if (x < 1) + fun_l19_n522(x) + else + fun_l19_n354(x) + end +end + +def fun_l18_n533(x) + if (x < 1) + fun_l19_n324(x) + else + fun_l19_n602(x) + end +end + +def fun_l18_n534(x) + if (x < 1) + fun_l19_n138(x) + else + fun_l19_n259(x) + end +end + +def fun_l18_n535(x) + if (x < 1) + fun_l19_n692(x) + else + fun_l19_n810(x) + end +end + +def fun_l18_n536(x) + if (x < 1) + fun_l19_n694(x) + else + fun_l19_n39(x) + end +end + +def fun_l18_n537(x) + if (x < 1) + fun_l19_n441(x) + else + fun_l19_n158(x) + end +end + +def fun_l18_n538(x) + if (x < 1) + fun_l19_n609(x) + else + fun_l19_n54(x) + end +end + +def fun_l18_n539(x) + if (x < 1) + fun_l19_n984(x) + else + fun_l19_n206(x) + end +end + +def fun_l18_n540(x) + if (x < 1) + fun_l19_n548(x) + else + fun_l19_n558(x) + end +end + +def fun_l18_n541(x) + if (x < 1) + fun_l19_n640(x) + else + fun_l19_n721(x) + end +end + +def fun_l18_n542(x) + if (x < 1) + fun_l19_n50(x) + else + fun_l19_n598(x) + end +end + +def fun_l18_n543(x) + if (x < 1) + fun_l19_n774(x) + else + fun_l19_n753(x) + end +end + +def fun_l18_n544(x) + if (x < 1) + fun_l19_n151(x) + else + fun_l19_n75(x) + end +end + +def fun_l18_n545(x) + if (x < 1) + fun_l19_n162(x) + else + fun_l19_n550(x) + end +end + +def fun_l18_n546(x) + if (x < 1) + fun_l19_n892(x) + else + fun_l19_n322(x) + end +end + +def fun_l18_n547(x) + if (x < 1) + fun_l19_n15(x) + else + fun_l19_n854(x) + end +end + +def fun_l18_n548(x) + if (x < 1) + fun_l19_n54(x) + else + fun_l19_n627(x) + end +end + +def fun_l18_n549(x) + if (x < 1) + fun_l19_n847(x) + else + fun_l19_n236(x) + end +end + +def fun_l18_n550(x) + if (x < 1) + fun_l19_n796(x) + else + fun_l19_n895(x) + end +end + +def fun_l18_n551(x) + if (x < 1) + fun_l19_n922(x) + else + fun_l19_n854(x) + end +end + +def fun_l18_n552(x) + if (x < 1) + fun_l19_n378(x) + else + fun_l19_n449(x) + end +end + +def fun_l18_n553(x) + if (x < 1) + fun_l19_n188(x) + else + fun_l19_n65(x) + end +end + +def fun_l18_n554(x) + if (x < 1) + fun_l19_n606(x) + else + fun_l19_n292(x) + end +end + +def fun_l18_n555(x) + if (x < 1) + fun_l19_n718(x) + else + fun_l19_n926(x) + end +end + +def fun_l18_n556(x) + if (x < 1) + fun_l19_n765(x) + else + fun_l19_n975(x) + end +end + +def fun_l18_n557(x) + if (x < 1) + fun_l19_n987(x) + else + fun_l19_n152(x) + end +end + +def fun_l18_n558(x) + if (x < 1) + fun_l19_n978(x) + else + fun_l19_n861(x) + end +end + +def fun_l18_n559(x) + if (x < 1) + fun_l19_n563(x) + else + fun_l19_n532(x) + end +end + +def fun_l18_n560(x) + if (x < 1) + fun_l19_n492(x) + else + fun_l19_n337(x) + end +end + +def fun_l18_n561(x) + if (x < 1) + fun_l19_n967(x) + else + fun_l19_n33(x) + end +end + +def fun_l18_n562(x) + if (x < 1) + fun_l19_n509(x) + else + fun_l19_n212(x) + end +end + +def fun_l18_n563(x) + if (x < 1) + fun_l19_n55(x) + else + fun_l19_n167(x) + end +end + +def fun_l18_n564(x) + if (x < 1) + fun_l19_n263(x) + else + fun_l19_n386(x) + end +end + +def fun_l18_n565(x) + if (x < 1) + fun_l19_n292(x) + else + fun_l19_n576(x) + end +end + +def fun_l18_n566(x) + if (x < 1) + fun_l19_n16(x) + else + fun_l19_n180(x) + end +end + +def fun_l18_n567(x) + if (x < 1) + fun_l19_n359(x) + else + fun_l19_n398(x) + end +end + +def fun_l18_n568(x) + if (x < 1) + fun_l19_n799(x) + else + fun_l19_n616(x) + end +end + +def fun_l18_n569(x) + if (x < 1) + fun_l19_n751(x) + else + fun_l19_n539(x) + end +end + +def fun_l18_n570(x) + if (x < 1) + fun_l19_n497(x) + else + fun_l19_n197(x) + end +end + +def fun_l18_n571(x) + if (x < 1) + fun_l19_n88(x) + else + fun_l19_n565(x) + end +end + +def fun_l18_n572(x) + if (x < 1) + fun_l19_n213(x) + else + fun_l19_n137(x) + end +end + +def fun_l18_n573(x) + if (x < 1) + fun_l19_n570(x) + else + fun_l19_n893(x) + end +end + +def fun_l18_n574(x) + if (x < 1) + fun_l19_n436(x) + else + fun_l19_n285(x) + end +end + +def fun_l18_n575(x) + if (x < 1) + fun_l19_n787(x) + else + fun_l19_n541(x) + end +end + +def fun_l18_n576(x) + if (x < 1) + fun_l19_n432(x) + else + fun_l19_n371(x) + end +end + +def fun_l18_n577(x) + if (x < 1) + fun_l19_n542(x) + else + fun_l19_n431(x) + end +end + +def fun_l18_n578(x) + if (x < 1) + fun_l19_n829(x) + else + fun_l19_n415(x) + end +end + +def fun_l18_n579(x) + if (x < 1) + fun_l19_n925(x) + else + fun_l19_n862(x) + end +end + +def fun_l18_n580(x) + if (x < 1) + fun_l19_n214(x) + else + fun_l19_n67(x) + end +end + +def fun_l18_n581(x) + if (x < 1) + fun_l19_n734(x) + else + fun_l19_n220(x) + end +end + +def fun_l18_n582(x) + if (x < 1) + fun_l19_n971(x) + else + fun_l19_n359(x) + end +end + +def fun_l18_n583(x) + if (x < 1) + fun_l19_n293(x) + else + fun_l19_n286(x) + end +end + +def fun_l18_n584(x) + if (x < 1) + fun_l19_n618(x) + else + fun_l19_n866(x) + end +end + +def fun_l18_n585(x) + if (x < 1) + fun_l19_n315(x) + else + fun_l19_n594(x) + end +end + +def fun_l18_n586(x) + if (x < 1) + fun_l19_n230(x) + else + fun_l19_n450(x) + end +end + +def fun_l18_n587(x) + if (x < 1) + fun_l19_n805(x) + else + fun_l19_n429(x) + end +end + +def fun_l18_n588(x) + if (x < 1) + fun_l19_n782(x) + else + fun_l19_n133(x) + end +end + +def fun_l18_n589(x) + if (x < 1) + fun_l19_n166(x) + else + fun_l19_n111(x) + end +end + +def fun_l18_n590(x) + if (x < 1) + fun_l19_n26(x) + else + fun_l19_n678(x) + end +end + +def fun_l18_n591(x) + if (x < 1) + fun_l19_n728(x) + else + fun_l19_n346(x) + end +end + +def fun_l18_n592(x) + if (x < 1) + fun_l19_n882(x) + else + fun_l19_n930(x) + end +end + +def fun_l18_n593(x) + if (x < 1) + fun_l19_n454(x) + else + fun_l19_n560(x) + end +end + +def fun_l18_n594(x) + if (x < 1) + fun_l19_n881(x) + else + fun_l19_n929(x) + end +end + +def fun_l18_n595(x) + if (x < 1) + fun_l19_n464(x) + else + fun_l19_n8(x) + end +end + +def fun_l18_n596(x) + if (x < 1) + fun_l19_n247(x) + else + fun_l19_n48(x) + end +end + +def fun_l18_n597(x) + if (x < 1) + fun_l19_n838(x) + else + fun_l19_n811(x) + end +end + +def fun_l18_n598(x) + if (x < 1) + fun_l19_n493(x) + else + fun_l19_n975(x) + end +end + +def fun_l18_n599(x) + if (x < 1) + fun_l19_n372(x) + else + fun_l19_n334(x) + end +end + +def fun_l18_n600(x) + if (x < 1) + fun_l19_n971(x) + else + fun_l19_n198(x) + end +end + +def fun_l18_n601(x) + if (x < 1) + fun_l19_n494(x) + else + fun_l19_n273(x) + end +end + +def fun_l18_n602(x) + if (x < 1) + fun_l19_n778(x) + else + fun_l19_n815(x) + end +end + +def fun_l18_n603(x) + if (x < 1) + fun_l19_n247(x) + else + fun_l19_n615(x) + end +end + +def fun_l18_n604(x) + if (x < 1) + fun_l19_n659(x) + else + fun_l19_n613(x) + end +end + +def fun_l18_n605(x) + if (x < 1) + fun_l19_n814(x) + else + fun_l19_n742(x) + end +end + +def fun_l18_n606(x) + if (x < 1) + fun_l19_n988(x) + else + fun_l19_n877(x) + end +end + +def fun_l18_n607(x) + if (x < 1) + fun_l19_n908(x) + else + fun_l19_n491(x) + end +end + +def fun_l18_n608(x) + if (x < 1) + fun_l19_n600(x) + else + fun_l19_n381(x) + end +end + +def fun_l18_n609(x) + if (x < 1) + fun_l19_n695(x) + else + fun_l19_n343(x) + end +end + +def fun_l18_n610(x) + if (x < 1) + fun_l19_n686(x) + else + fun_l19_n154(x) + end +end + +def fun_l18_n611(x) + if (x < 1) + fun_l19_n413(x) + else + fun_l19_n364(x) + end +end + +def fun_l18_n612(x) + if (x < 1) + fun_l19_n86(x) + else + fun_l19_n478(x) + end +end + +def fun_l18_n613(x) + if (x < 1) + fun_l19_n288(x) + else + fun_l19_n134(x) + end +end + +def fun_l18_n614(x) + if (x < 1) + fun_l19_n71(x) + else + fun_l19_n95(x) + end +end + +def fun_l18_n615(x) + if (x < 1) + fun_l19_n716(x) + else + fun_l19_n697(x) + end +end + +def fun_l18_n616(x) + if (x < 1) + fun_l19_n24(x) + else + fun_l19_n365(x) + end +end + +def fun_l18_n617(x) + if (x < 1) + fun_l19_n317(x) + else + fun_l19_n117(x) + end +end + +def fun_l18_n618(x) + if (x < 1) + fun_l19_n304(x) + else + fun_l19_n115(x) + end +end + +def fun_l18_n619(x) + if (x < 1) + fun_l19_n322(x) + else + fun_l19_n105(x) + end +end + +def fun_l18_n620(x) + if (x < 1) + fun_l19_n213(x) + else + fun_l19_n122(x) + end +end + +def fun_l18_n621(x) + if (x < 1) + fun_l19_n675(x) + else + fun_l19_n769(x) + end +end + +def fun_l18_n622(x) + if (x < 1) + fun_l19_n660(x) + else + fun_l19_n895(x) + end +end + +def fun_l18_n623(x) + if (x < 1) + fun_l19_n656(x) + else + fun_l19_n698(x) + end +end + +def fun_l18_n624(x) + if (x < 1) + fun_l19_n575(x) + else + fun_l19_n274(x) + end +end + +def fun_l18_n625(x) + if (x < 1) + fun_l19_n44(x) + else + fun_l19_n78(x) + end +end + +def fun_l18_n626(x) + if (x < 1) + fun_l19_n326(x) + else + fun_l19_n76(x) + end +end + +def fun_l18_n627(x) + if (x < 1) + fun_l19_n365(x) + else + fun_l19_n453(x) + end +end + +def fun_l18_n628(x) + if (x < 1) + fun_l19_n306(x) + else + fun_l19_n63(x) + end +end + +def fun_l18_n629(x) + if (x < 1) + fun_l19_n116(x) + else + fun_l19_n577(x) + end +end + +def fun_l18_n630(x) + if (x < 1) + fun_l19_n625(x) + else + fun_l19_n321(x) + end +end + +def fun_l18_n631(x) + if (x < 1) + fun_l19_n328(x) + else + fun_l19_n989(x) + end +end + +def fun_l18_n632(x) + if (x < 1) + fun_l19_n216(x) + else + fun_l19_n375(x) + end +end + +def fun_l18_n633(x) + if (x < 1) + fun_l19_n942(x) + else + fun_l19_n17(x) + end +end + +def fun_l18_n634(x) + if (x < 1) + fun_l19_n821(x) + else + fun_l19_n132(x) + end +end + +def fun_l18_n635(x) + if (x < 1) + fun_l19_n164(x) + else + fun_l19_n679(x) + end +end + +def fun_l18_n636(x) + if (x < 1) + fun_l19_n494(x) + else + fun_l19_n404(x) + end +end + +def fun_l18_n637(x) + if (x < 1) + fun_l19_n715(x) + else + fun_l19_n955(x) + end +end + +def fun_l18_n638(x) + if (x < 1) + fun_l19_n297(x) + else + fun_l19_n349(x) + end +end + +def fun_l18_n639(x) + if (x < 1) + fun_l19_n835(x) + else + fun_l19_n965(x) + end +end + +def fun_l18_n640(x) + if (x < 1) + fun_l19_n778(x) + else + fun_l19_n572(x) + end +end + +def fun_l18_n641(x) + if (x < 1) + fun_l19_n51(x) + else + fun_l19_n497(x) + end +end + +def fun_l18_n642(x) + if (x < 1) + fun_l19_n390(x) + else + fun_l19_n341(x) + end +end + +def fun_l18_n643(x) + if (x < 1) + fun_l19_n961(x) + else + fun_l19_n966(x) + end +end + +def fun_l18_n644(x) + if (x < 1) + fun_l19_n832(x) + else + fun_l19_n279(x) + end +end + +def fun_l18_n645(x) + if (x < 1) + fun_l19_n0(x) + else + fun_l19_n266(x) + end +end + +def fun_l18_n646(x) + if (x < 1) + fun_l19_n512(x) + else + fun_l19_n988(x) + end +end + +def fun_l18_n647(x) + if (x < 1) + fun_l19_n728(x) + else + fun_l19_n390(x) + end +end + +def fun_l18_n648(x) + if (x < 1) + fun_l19_n61(x) + else + fun_l19_n188(x) + end +end + +def fun_l18_n649(x) + if (x < 1) + fun_l19_n772(x) + else + fun_l19_n457(x) + end +end + +def fun_l18_n650(x) + if (x < 1) + fun_l19_n768(x) + else + fun_l19_n624(x) + end +end + +def fun_l18_n651(x) + if (x < 1) + fun_l19_n30(x) + else + fun_l19_n663(x) + end +end + +def fun_l18_n652(x) + if (x < 1) + fun_l19_n42(x) + else + fun_l19_n781(x) + end +end + +def fun_l18_n653(x) + if (x < 1) + fun_l19_n59(x) + else + fun_l19_n99(x) + end +end + +def fun_l18_n654(x) + if (x < 1) + fun_l19_n81(x) + else + fun_l19_n368(x) + end +end + +def fun_l18_n655(x) + if (x < 1) + fun_l19_n0(x) + else + fun_l19_n321(x) + end +end + +def fun_l18_n656(x) + if (x < 1) + fun_l19_n344(x) + else + fun_l19_n996(x) + end +end + +def fun_l18_n657(x) + if (x < 1) + fun_l19_n384(x) + else + fun_l19_n123(x) + end +end + +def fun_l18_n658(x) + if (x < 1) + fun_l19_n336(x) + else + fun_l19_n928(x) + end +end + +def fun_l18_n659(x) + if (x < 1) + fun_l19_n785(x) + else + fun_l19_n370(x) + end +end + +def fun_l18_n660(x) + if (x < 1) + fun_l19_n508(x) + else + fun_l19_n200(x) + end +end + +def fun_l18_n661(x) + if (x < 1) + fun_l19_n674(x) + else + fun_l19_n95(x) + end +end + +def fun_l18_n662(x) + if (x < 1) + fun_l19_n839(x) + else + fun_l19_n737(x) + end +end + +def fun_l18_n663(x) + if (x < 1) + fun_l19_n670(x) + else + fun_l19_n77(x) + end +end + +def fun_l18_n664(x) + if (x < 1) + fun_l19_n402(x) + else + fun_l19_n7(x) + end +end + +def fun_l18_n665(x) + if (x < 1) + fun_l19_n357(x) + else + fun_l19_n961(x) + end +end + +def fun_l18_n666(x) + if (x < 1) + fun_l19_n72(x) + else + fun_l19_n535(x) + end +end + +def fun_l18_n667(x) + if (x < 1) + fun_l19_n317(x) + else + fun_l19_n450(x) + end +end + +def fun_l18_n668(x) + if (x < 1) + fun_l19_n823(x) + else + fun_l19_n301(x) + end +end + +def fun_l18_n669(x) + if (x < 1) + fun_l19_n36(x) + else + fun_l19_n660(x) + end +end + +def fun_l18_n670(x) + if (x < 1) + fun_l19_n322(x) + else + fun_l19_n626(x) + end +end + +def fun_l18_n671(x) + if (x < 1) + fun_l19_n408(x) + else + fun_l19_n872(x) + end +end + +def fun_l18_n672(x) + if (x < 1) + fun_l19_n614(x) + else + fun_l19_n567(x) + end +end + +def fun_l18_n673(x) + if (x < 1) + fun_l19_n601(x) + else + fun_l19_n429(x) + end +end + +def fun_l18_n674(x) + if (x < 1) + fun_l19_n658(x) + else + fun_l19_n424(x) + end +end + +def fun_l18_n675(x) + if (x < 1) + fun_l19_n248(x) + else + fun_l19_n29(x) + end +end + +def fun_l18_n676(x) + if (x < 1) + fun_l19_n206(x) + else + fun_l19_n838(x) + end +end + +def fun_l18_n677(x) + if (x < 1) + fun_l19_n354(x) + else + fun_l19_n700(x) + end +end + +def fun_l18_n678(x) + if (x < 1) + fun_l19_n264(x) + else + fun_l19_n591(x) + end +end + +def fun_l18_n679(x) + if (x < 1) + fun_l19_n73(x) + else + fun_l19_n419(x) + end +end + +def fun_l18_n680(x) + if (x < 1) + fun_l19_n260(x) + else + fun_l19_n902(x) + end +end + +def fun_l18_n681(x) + if (x < 1) + fun_l19_n776(x) + else + fun_l19_n148(x) + end +end + +def fun_l18_n682(x) + if (x < 1) + fun_l19_n819(x) + else + fun_l19_n743(x) + end +end + +def fun_l18_n683(x) + if (x < 1) + fun_l19_n831(x) + else + fun_l19_n194(x) + end +end + +def fun_l18_n684(x) + if (x < 1) + fun_l19_n652(x) + else + fun_l19_n229(x) + end +end + +def fun_l18_n685(x) + if (x < 1) + fun_l19_n533(x) + else + fun_l19_n600(x) + end +end + +def fun_l18_n686(x) + if (x < 1) + fun_l19_n45(x) + else + fun_l19_n623(x) + end +end + +def fun_l18_n687(x) + if (x < 1) + fun_l19_n287(x) + else + fun_l19_n443(x) + end +end + +def fun_l18_n688(x) + if (x < 1) + fun_l19_n719(x) + else + fun_l19_n819(x) + end +end + +def fun_l18_n689(x) + if (x < 1) + fun_l19_n872(x) + else + fun_l19_n944(x) + end +end + +def fun_l18_n690(x) + if (x < 1) + fun_l19_n352(x) + else + fun_l19_n49(x) + end +end + +def fun_l18_n691(x) + if (x < 1) + fun_l19_n438(x) + else + fun_l19_n592(x) + end +end + +def fun_l18_n692(x) + if (x < 1) + fun_l19_n717(x) + else + fun_l19_n30(x) + end +end + +def fun_l18_n693(x) + if (x < 1) + fun_l19_n132(x) + else + fun_l19_n830(x) + end +end + +def fun_l18_n694(x) + if (x < 1) + fun_l19_n17(x) + else + fun_l19_n649(x) + end +end + +def fun_l18_n695(x) + if (x < 1) + fun_l19_n883(x) + else + fun_l19_n812(x) + end +end + +def fun_l18_n696(x) + if (x < 1) + fun_l19_n354(x) + else + fun_l19_n927(x) + end +end + +def fun_l18_n697(x) + if (x < 1) + fun_l19_n534(x) + else + fun_l19_n192(x) + end +end + +def fun_l18_n698(x) + if (x < 1) + fun_l19_n911(x) + else + fun_l19_n386(x) + end +end + +def fun_l18_n699(x) + if (x < 1) + fun_l19_n1(x) + else + fun_l19_n253(x) + end +end + +def fun_l18_n700(x) + if (x < 1) + fun_l19_n318(x) + else + fun_l19_n323(x) + end +end + +def fun_l18_n701(x) + if (x < 1) + fun_l19_n158(x) + else + fun_l19_n61(x) + end +end + +def fun_l18_n702(x) + if (x < 1) + fun_l19_n719(x) + else + fun_l19_n842(x) + end +end + +def fun_l18_n703(x) + if (x < 1) + fun_l19_n918(x) + else + fun_l19_n231(x) + end +end + +def fun_l18_n704(x) + if (x < 1) + fun_l19_n136(x) + else + fun_l19_n28(x) + end +end + +def fun_l18_n705(x) + if (x < 1) + fun_l19_n451(x) + else + fun_l19_n328(x) + end +end + +def fun_l18_n706(x) + if (x < 1) + fun_l19_n182(x) + else + fun_l19_n434(x) + end +end + +def fun_l18_n707(x) + if (x < 1) + fun_l19_n368(x) + else + fun_l19_n302(x) + end +end + +def fun_l18_n708(x) + if (x < 1) + fun_l19_n370(x) + else + fun_l19_n291(x) + end +end + +def fun_l18_n709(x) + if (x < 1) + fun_l19_n104(x) + else + fun_l19_n530(x) + end +end + +def fun_l18_n710(x) + if (x < 1) + fun_l19_n712(x) + else + fun_l19_n325(x) + end +end + +def fun_l18_n711(x) + if (x < 1) + fun_l19_n555(x) + else + fun_l19_n299(x) + end +end + +def fun_l18_n712(x) + if (x < 1) + fun_l19_n40(x) + else + fun_l19_n342(x) + end +end + +def fun_l18_n713(x) + if (x < 1) + fun_l19_n871(x) + else + fun_l19_n72(x) + end +end + +def fun_l18_n714(x) + if (x < 1) + fun_l19_n137(x) + else + fun_l19_n195(x) + end +end + +def fun_l18_n715(x) + if (x < 1) + fun_l19_n534(x) + else + fun_l19_n613(x) + end +end + +def fun_l18_n716(x) + if (x < 1) + fun_l19_n591(x) + else + fun_l19_n899(x) + end +end + +def fun_l18_n717(x) + if (x < 1) + fun_l19_n103(x) + else + fun_l19_n333(x) + end +end + +def fun_l18_n718(x) + if (x < 1) + fun_l19_n470(x) + else + fun_l19_n576(x) + end +end + +def fun_l18_n719(x) + if (x < 1) + fun_l19_n494(x) + else + fun_l19_n765(x) + end +end + +def fun_l18_n720(x) + if (x < 1) + fun_l19_n317(x) + else + fun_l19_n720(x) + end +end + +def fun_l18_n721(x) + if (x < 1) + fun_l19_n567(x) + else + fun_l19_n280(x) + end +end + +def fun_l18_n722(x) + if (x < 1) + fun_l19_n642(x) + else + fun_l19_n700(x) + end +end + +def fun_l18_n723(x) + if (x < 1) + fun_l19_n775(x) + else + fun_l19_n239(x) + end +end + +def fun_l18_n724(x) + if (x < 1) + fun_l19_n346(x) + else + fun_l19_n974(x) + end +end + +def fun_l18_n725(x) + if (x < 1) + fun_l19_n509(x) + else + fun_l19_n90(x) + end +end + +def fun_l18_n726(x) + if (x < 1) + fun_l19_n834(x) + else + fun_l19_n793(x) + end +end + +def fun_l18_n727(x) + if (x < 1) + fun_l19_n588(x) + else + fun_l19_n895(x) + end +end + +def fun_l18_n728(x) + if (x < 1) + fun_l19_n18(x) + else + fun_l19_n218(x) + end +end + +def fun_l18_n729(x) + if (x < 1) + fun_l19_n109(x) + else + fun_l19_n970(x) + end +end + +def fun_l18_n730(x) + if (x < 1) + fun_l19_n721(x) + else + fun_l19_n81(x) + end +end + +def fun_l18_n731(x) + if (x < 1) + fun_l19_n935(x) + else + fun_l19_n652(x) + end +end + +def fun_l18_n732(x) + if (x < 1) + fun_l19_n821(x) + else + fun_l19_n32(x) + end +end + +def fun_l18_n733(x) + if (x < 1) + fun_l19_n189(x) + else + fun_l19_n469(x) + end +end + +def fun_l18_n734(x) + if (x < 1) + fun_l19_n11(x) + else + fun_l19_n741(x) + end +end + +def fun_l18_n735(x) + if (x < 1) + fun_l19_n575(x) + else + fun_l19_n679(x) + end +end + +def fun_l18_n736(x) + if (x < 1) + fun_l19_n442(x) + else + fun_l19_n652(x) + end +end + +def fun_l18_n737(x) + if (x < 1) + fun_l19_n22(x) + else + fun_l19_n950(x) + end +end + +def fun_l18_n738(x) + if (x < 1) + fun_l19_n605(x) + else + fun_l19_n16(x) + end +end + +def fun_l18_n739(x) + if (x < 1) + fun_l19_n888(x) + else + fun_l19_n873(x) + end +end + +def fun_l18_n740(x) + if (x < 1) + fun_l19_n355(x) + else + fun_l19_n558(x) + end +end + +def fun_l18_n741(x) + if (x < 1) + fun_l19_n171(x) + else + fun_l19_n513(x) + end +end + +def fun_l18_n742(x) + if (x < 1) + fun_l19_n843(x) + else + fun_l19_n833(x) + end +end + +def fun_l18_n743(x) + if (x < 1) + fun_l19_n774(x) + else + fun_l19_n992(x) + end +end + +def fun_l18_n744(x) + if (x < 1) + fun_l19_n505(x) + else + fun_l19_n353(x) + end +end + +def fun_l18_n745(x) + if (x < 1) + fun_l19_n93(x) + else + fun_l19_n476(x) + end +end + +def fun_l18_n746(x) + if (x < 1) + fun_l19_n555(x) + else + fun_l19_n233(x) + end +end + +def fun_l18_n747(x) + if (x < 1) + fun_l19_n639(x) + else + fun_l19_n239(x) + end +end + +def fun_l18_n748(x) + if (x < 1) + fun_l19_n318(x) + else + fun_l19_n342(x) + end +end + +def fun_l18_n749(x) + if (x < 1) + fun_l19_n80(x) + else + fun_l19_n252(x) + end +end + +def fun_l18_n750(x) + if (x < 1) + fun_l19_n546(x) + else + fun_l19_n57(x) + end +end + +def fun_l18_n751(x) + if (x < 1) + fun_l19_n620(x) + else + fun_l19_n732(x) + end +end + +def fun_l18_n752(x) + if (x < 1) + fun_l19_n870(x) + else + fun_l19_n696(x) + end +end + +def fun_l18_n753(x) + if (x < 1) + fun_l19_n633(x) + else + fun_l19_n547(x) + end +end + +def fun_l18_n754(x) + if (x < 1) + fun_l19_n860(x) + else + fun_l19_n70(x) + end +end + +def fun_l18_n755(x) + if (x < 1) + fun_l19_n4(x) + else + fun_l19_n560(x) + end +end + +def fun_l18_n756(x) + if (x < 1) + fun_l19_n227(x) + else + fun_l19_n189(x) + end +end + +def fun_l18_n757(x) + if (x < 1) + fun_l19_n560(x) + else + fun_l19_n467(x) + end +end + +def fun_l18_n758(x) + if (x < 1) + fun_l19_n777(x) + else + fun_l19_n761(x) + end +end + +def fun_l18_n759(x) + if (x < 1) + fun_l19_n626(x) + else + fun_l19_n391(x) + end +end + +def fun_l18_n760(x) + if (x < 1) + fun_l19_n989(x) + else + fun_l19_n629(x) + end +end + +def fun_l18_n761(x) + if (x < 1) + fun_l19_n509(x) + else + fun_l19_n268(x) + end +end + +def fun_l18_n762(x) + if (x < 1) + fun_l19_n49(x) + else + fun_l19_n149(x) + end +end + +def fun_l18_n763(x) + if (x < 1) + fun_l19_n614(x) + else + fun_l19_n490(x) + end +end + +def fun_l18_n764(x) + if (x < 1) + fun_l19_n7(x) + else + fun_l19_n686(x) + end +end + +def fun_l18_n765(x) + if (x < 1) + fun_l19_n93(x) + else + fun_l19_n334(x) + end +end + +def fun_l18_n766(x) + if (x < 1) + fun_l19_n30(x) + else + fun_l19_n396(x) + end +end + +def fun_l18_n767(x) + if (x < 1) + fun_l19_n437(x) + else + fun_l19_n614(x) + end +end + +def fun_l18_n768(x) + if (x < 1) + fun_l19_n168(x) + else + fun_l19_n915(x) + end +end + +def fun_l18_n769(x) + if (x < 1) + fun_l19_n465(x) + else + fun_l19_n816(x) + end +end + +def fun_l18_n770(x) + if (x < 1) + fun_l19_n692(x) + else + fun_l19_n772(x) + end +end + +def fun_l18_n771(x) + if (x < 1) + fun_l19_n196(x) + else + fun_l19_n812(x) + end +end + +def fun_l18_n772(x) + if (x < 1) + fun_l19_n785(x) + else + fun_l19_n592(x) + end +end + +def fun_l18_n773(x) + if (x < 1) + fun_l19_n649(x) + else + fun_l19_n50(x) + end +end + +def fun_l18_n774(x) + if (x < 1) + fun_l19_n102(x) + else + fun_l19_n843(x) + end +end + +def fun_l18_n775(x) + if (x < 1) + fun_l19_n856(x) + else + fun_l19_n805(x) + end +end + +def fun_l18_n776(x) + if (x < 1) + fun_l19_n449(x) + else + fun_l19_n425(x) + end +end + +def fun_l18_n777(x) + if (x < 1) + fun_l19_n855(x) + else + fun_l19_n345(x) + end +end + +def fun_l18_n778(x) + if (x < 1) + fun_l19_n714(x) + else + fun_l19_n499(x) + end +end + +def fun_l18_n779(x) + if (x < 1) + fun_l19_n131(x) + else + fun_l19_n396(x) + end +end + +def fun_l18_n780(x) + if (x < 1) + fun_l19_n709(x) + else + fun_l19_n851(x) + end +end + +def fun_l18_n781(x) + if (x < 1) + fun_l19_n104(x) + else + fun_l19_n569(x) + end +end + +def fun_l18_n782(x) + if (x < 1) + fun_l19_n121(x) + else + fun_l19_n690(x) + end +end + +def fun_l18_n783(x) + if (x < 1) + fun_l19_n72(x) + else + fun_l19_n522(x) + end +end + +def fun_l18_n784(x) + if (x < 1) + fun_l19_n212(x) + else + fun_l19_n199(x) + end +end + +def fun_l18_n785(x) + if (x < 1) + fun_l19_n168(x) + else + fun_l19_n948(x) + end +end + +def fun_l18_n786(x) + if (x < 1) + fun_l19_n288(x) + else + fun_l19_n631(x) + end +end + +def fun_l18_n787(x) + if (x < 1) + fun_l19_n713(x) + else + fun_l19_n232(x) + end +end + +def fun_l18_n788(x) + if (x < 1) + fun_l19_n6(x) + else + fun_l19_n725(x) + end +end + +def fun_l18_n789(x) + if (x < 1) + fun_l19_n893(x) + else + fun_l19_n677(x) + end +end + +def fun_l18_n790(x) + if (x < 1) + fun_l19_n734(x) + else + fun_l19_n589(x) + end +end + +def fun_l18_n791(x) + if (x < 1) + fun_l19_n369(x) + else + fun_l19_n710(x) + end +end + +def fun_l18_n792(x) + if (x < 1) + fun_l19_n373(x) + else + fun_l19_n226(x) + end +end + +def fun_l18_n793(x) + if (x < 1) + fun_l19_n651(x) + else + fun_l19_n292(x) + end +end + +def fun_l18_n794(x) + if (x < 1) + fun_l19_n625(x) + else + fun_l19_n494(x) + end +end + +def fun_l18_n795(x) + if (x < 1) + fun_l19_n463(x) + else + fun_l19_n113(x) + end +end + +def fun_l18_n796(x) + if (x < 1) + fun_l19_n857(x) + else + fun_l19_n561(x) + end +end + +def fun_l18_n797(x) + if (x < 1) + fun_l19_n845(x) + else + fun_l19_n598(x) + end +end + +def fun_l18_n798(x) + if (x < 1) + fun_l19_n606(x) + else + fun_l19_n822(x) + end +end + +def fun_l18_n799(x) + if (x < 1) + fun_l19_n649(x) + else + fun_l19_n610(x) + end +end + +def fun_l18_n800(x) + if (x < 1) + fun_l19_n619(x) + else + fun_l19_n753(x) + end +end + +def fun_l18_n801(x) + if (x < 1) + fun_l19_n947(x) + else + fun_l19_n665(x) + end +end + +def fun_l18_n802(x) + if (x < 1) + fun_l19_n869(x) + else + fun_l19_n928(x) + end +end + +def fun_l18_n803(x) + if (x < 1) + fun_l19_n568(x) + else + fun_l19_n624(x) + end +end + +def fun_l18_n804(x) + if (x < 1) + fun_l19_n724(x) + else + fun_l19_n104(x) + end +end + +def fun_l18_n805(x) + if (x < 1) + fun_l19_n687(x) + else + fun_l19_n906(x) + end +end + +def fun_l18_n806(x) + if (x < 1) + fun_l19_n387(x) + else + fun_l19_n317(x) + end +end + +def fun_l18_n807(x) + if (x < 1) + fun_l19_n433(x) + else + fun_l19_n211(x) + end +end + +def fun_l18_n808(x) + if (x < 1) + fun_l19_n574(x) + else + fun_l19_n848(x) + end +end + +def fun_l18_n809(x) + if (x < 1) + fun_l19_n929(x) + else + fun_l19_n751(x) + end +end + +def fun_l18_n810(x) + if (x < 1) + fun_l19_n24(x) + else + fun_l19_n97(x) + end +end + +def fun_l18_n811(x) + if (x < 1) + fun_l19_n503(x) + else + fun_l19_n173(x) + end +end + +def fun_l18_n812(x) + if (x < 1) + fun_l19_n431(x) + else + fun_l19_n553(x) + end +end + +def fun_l18_n813(x) + if (x < 1) + fun_l19_n215(x) + else + fun_l19_n920(x) + end +end + +def fun_l18_n814(x) + if (x < 1) + fun_l19_n952(x) + else + fun_l19_n484(x) + end +end + +def fun_l18_n815(x) + if (x < 1) + fun_l19_n253(x) + else + fun_l19_n20(x) + end +end + +def fun_l18_n816(x) + if (x < 1) + fun_l19_n853(x) + else + fun_l19_n902(x) + end +end + +def fun_l18_n817(x) + if (x < 1) + fun_l19_n606(x) + else + fun_l19_n732(x) + end +end + +def fun_l18_n818(x) + if (x < 1) + fun_l19_n227(x) + else + fun_l19_n908(x) + end +end + +def fun_l18_n819(x) + if (x < 1) + fun_l19_n423(x) + else + fun_l19_n511(x) + end +end + +def fun_l18_n820(x) + if (x < 1) + fun_l19_n25(x) + else + fun_l19_n939(x) + end +end + +def fun_l18_n821(x) + if (x < 1) + fun_l19_n709(x) + else + fun_l19_n776(x) + end +end + +def fun_l18_n822(x) + if (x < 1) + fun_l19_n539(x) + else + fun_l19_n41(x) + end +end + +def fun_l18_n823(x) + if (x < 1) + fun_l19_n764(x) + else + fun_l19_n240(x) + end +end + +def fun_l18_n824(x) + if (x < 1) + fun_l19_n508(x) + else + fun_l19_n505(x) + end +end + +def fun_l18_n825(x) + if (x < 1) + fun_l19_n788(x) + else + fun_l19_n245(x) + end +end + +def fun_l18_n826(x) + if (x < 1) + fun_l19_n315(x) + else + fun_l19_n391(x) + end +end + +def fun_l18_n827(x) + if (x < 1) + fun_l19_n210(x) + else + fun_l19_n17(x) + end +end + +def fun_l18_n828(x) + if (x < 1) + fun_l19_n726(x) + else + fun_l19_n57(x) + end +end + +def fun_l18_n829(x) + if (x < 1) + fun_l19_n228(x) + else + fun_l19_n44(x) + end +end + +def fun_l18_n830(x) + if (x < 1) + fun_l19_n5(x) + else + fun_l19_n110(x) + end +end + +def fun_l18_n831(x) + if (x < 1) + fun_l19_n409(x) + else + fun_l19_n874(x) + end +end + +def fun_l18_n832(x) + if (x < 1) + fun_l19_n710(x) + else + fun_l19_n960(x) + end +end + +def fun_l18_n833(x) + if (x < 1) + fun_l19_n92(x) + else + fun_l19_n869(x) + end +end + +def fun_l18_n834(x) + if (x < 1) + fun_l19_n420(x) + else + fun_l19_n616(x) + end +end + +def fun_l18_n835(x) + if (x < 1) + fun_l19_n705(x) + else + fun_l19_n727(x) + end +end + +def fun_l18_n836(x) + if (x < 1) + fun_l19_n78(x) + else + fun_l19_n211(x) + end +end + +def fun_l18_n837(x) + if (x < 1) + fun_l19_n214(x) + else + fun_l19_n504(x) + end +end + +def fun_l18_n838(x) + if (x < 1) + fun_l19_n320(x) + else + fun_l19_n303(x) + end +end + +def fun_l18_n839(x) + if (x < 1) + fun_l19_n168(x) + else + fun_l19_n677(x) + end +end + +def fun_l18_n840(x) + if (x < 1) + fun_l19_n523(x) + else + fun_l19_n183(x) + end +end + +def fun_l18_n841(x) + if (x < 1) + fun_l19_n757(x) + else + fun_l19_n554(x) + end +end + +def fun_l18_n842(x) + if (x < 1) + fun_l19_n309(x) + else + fun_l19_n70(x) + end +end + +def fun_l18_n843(x) + if (x < 1) + fun_l19_n316(x) + else + fun_l19_n758(x) + end +end + +def fun_l18_n844(x) + if (x < 1) + fun_l19_n459(x) + else + fun_l19_n28(x) + end +end + +def fun_l18_n845(x) + if (x < 1) + fun_l19_n458(x) + else + fun_l19_n597(x) + end +end + +def fun_l18_n846(x) + if (x < 1) + fun_l19_n662(x) + else + fun_l19_n480(x) + end +end + +def fun_l18_n847(x) + if (x < 1) + fun_l19_n967(x) + else + fun_l19_n764(x) + end +end + +def fun_l18_n848(x) + if (x < 1) + fun_l19_n248(x) + else + fun_l19_n459(x) + end +end + +def fun_l18_n849(x) + if (x < 1) + fun_l19_n306(x) + else + fun_l19_n892(x) + end +end + +def fun_l18_n850(x) + if (x < 1) + fun_l19_n541(x) + else + fun_l19_n745(x) + end +end + +def fun_l18_n851(x) + if (x < 1) + fun_l19_n974(x) + else + fun_l19_n593(x) + end +end + +def fun_l18_n852(x) + if (x < 1) + fun_l19_n564(x) + else + fun_l19_n598(x) + end +end + +def fun_l18_n853(x) + if (x < 1) + fun_l19_n447(x) + else + fun_l19_n207(x) + end +end + +def fun_l18_n854(x) + if (x < 1) + fun_l19_n261(x) + else + fun_l19_n35(x) + end +end + +def fun_l18_n855(x) + if (x < 1) + fun_l19_n597(x) + else + fun_l19_n898(x) + end +end + +def fun_l18_n856(x) + if (x < 1) + fun_l19_n97(x) + else + fun_l19_n109(x) + end +end + +def fun_l18_n857(x) + if (x < 1) + fun_l19_n487(x) + else + fun_l19_n423(x) + end +end + +def fun_l18_n858(x) + if (x < 1) + fun_l19_n804(x) + else + fun_l19_n250(x) + end +end + +def fun_l18_n859(x) + if (x < 1) + fun_l19_n935(x) + else + fun_l19_n952(x) + end +end + +def fun_l18_n860(x) + if (x < 1) + fun_l19_n149(x) + else + fun_l19_n586(x) + end +end + +def fun_l18_n861(x) + if (x < 1) + fun_l19_n750(x) + else + fun_l19_n962(x) + end +end + +def fun_l18_n862(x) + if (x < 1) + fun_l19_n396(x) + else + fun_l19_n324(x) + end +end + +def fun_l18_n863(x) + if (x < 1) + fun_l19_n231(x) + else + fun_l19_n897(x) + end +end + +def fun_l18_n864(x) + if (x < 1) + fun_l19_n239(x) + else + fun_l19_n118(x) + end +end + +def fun_l18_n865(x) + if (x < 1) + fun_l19_n221(x) + else + fun_l19_n771(x) + end +end + +def fun_l18_n866(x) + if (x < 1) + fun_l19_n258(x) + else + fun_l19_n868(x) + end +end + +def fun_l18_n867(x) + if (x < 1) + fun_l19_n629(x) + else + fun_l19_n491(x) + end +end + +def fun_l18_n868(x) + if (x < 1) + fun_l19_n685(x) + else + fun_l19_n532(x) + end +end + +def fun_l18_n869(x) + if (x < 1) + fun_l19_n45(x) + else + fun_l19_n769(x) + end +end + +def fun_l18_n870(x) + if (x < 1) + fun_l19_n249(x) + else + fun_l19_n677(x) + end +end + +def fun_l18_n871(x) + if (x < 1) + fun_l19_n685(x) + else + fun_l19_n953(x) + end +end + +def fun_l18_n872(x) + if (x < 1) + fun_l19_n270(x) + else + fun_l19_n208(x) + end +end + +def fun_l18_n873(x) + if (x < 1) + fun_l19_n195(x) + else + fun_l19_n811(x) + end +end + +def fun_l18_n874(x) + if (x < 1) + fun_l19_n700(x) + else + fun_l19_n331(x) + end +end + +def fun_l18_n875(x) + if (x < 1) + fun_l19_n209(x) + else + fun_l19_n304(x) + end +end + +def fun_l18_n876(x) + if (x < 1) + fun_l19_n897(x) + else + fun_l19_n98(x) + end +end + +def fun_l18_n877(x) + if (x < 1) + fun_l19_n400(x) + else + fun_l19_n325(x) + end +end + +def fun_l18_n878(x) + if (x < 1) + fun_l19_n312(x) + else + fun_l19_n872(x) + end +end + +def fun_l18_n879(x) + if (x < 1) + fun_l19_n669(x) + else + fun_l19_n729(x) + end +end + +def fun_l18_n880(x) + if (x < 1) + fun_l19_n644(x) + else + fun_l19_n243(x) + end +end + +def fun_l18_n881(x) + if (x < 1) + fun_l19_n440(x) + else + fun_l19_n495(x) + end +end + +def fun_l18_n882(x) + if (x < 1) + fun_l19_n694(x) + else + fun_l19_n189(x) + end +end + +def fun_l18_n883(x) + if (x < 1) + fun_l19_n610(x) + else + fun_l19_n802(x) + end +end + +def fun_l18_n884(x) + if (x < 1) + fun_l19_n69(x) + else + fun_l19_n129(x) + end +end + +def fun_l18_n885(x) + if (x < 1) + fun_l19_n837(x) + else + fun_l19_n521(x) + end +end + +def fun_l18_n886(x) + if (x < 1) + fun_l19_n204(x) + else + fun_l19_n284(x) + end +end + +def fun_l18_n887(x) + if (x < 1) + fun_l19_n2(x) + else + fun_l19_n378(x) + end +end + +def fun_l18_n888(x) + if (x < 1) + fun_l19_n410(x) + else + fun_l19_n871(x) + end +end + +def fun_l18_n889(x) + if (x < 1) + fun_l19_n976(x) + else + fun_l19_n581(x) + end +end + +def fun_l18_n890(x) + if (x < 1) + fun_l19_n274(x) + else + fun_l19_n57(x) + end +end + +def fun_l18_n891(x) + if (x < 1) + fun_l19_n983(x) + else + fun_l19_n900(x) + end +end + +def fun_l18_n892(x) + if (x < 1) + fun_l19_n351(x) + else + fun_l19_n621(x) + end +end + +def fun_l18_n893(x) + if (x < 1) + fun_l19_n539(x) + else + fun_l19_n847(x) + end +end + +def fun_l18_n894(x) + if (x < 1) + fun_l19_n56(x) + else + fun_l19_n918(x) + end +end + +def fun_l18_n895(x) + if (x < 1) + fun_l19_n906(x) + else + fun_l19_n509(x) + end +end + +def fun_l18_n896(x) + if (x < 1) + fun_l19_n64(x) + else + fun_l19_n269(x) + end +end + +def fun_l18_n897(x) + if (x < 1) + fun_l19_n348(x) + else + fun_l19_n983(x) + end +end + +def fun_l18_n898(x) + if (x < 1) + fun_l19_n699(x) + else + fun_l19_n322(x) + end +end + +def fun_l18_n899(x) + if (x < 1) + fun_l19_n754(x) + else + fun_l19_n608(x) + end +end + +def fun_l18_n900(x) + if (x < 1) + fun_l19_n530(x) + else + fun_l19_n919(x) + end +end + +def fun_l18_n901(x) + if (x < 1) + fun_l19_n359(x) + else + fun_l19_n739(x) + end +end + +def fun_l18_n902(x) + if (x < 1) + fun_l19_n647(x) + else + fun_l19_n389(x) + end +end + +def fun_l18_n903(x) + if (x < 1) + fun_l19_n908(x) + else + fun_l19_n680(x) + end +end + +def fun_l18_n904(x) + if (x < 1) + fun_l19_n78(x) + else + fun_l19_n512(x) + end +end + +def fun_l18_n905(x) + if (x < 1) + fun_l19_n514(x) + else + fun_l19_n250(x) + end +end + +def fun_l18_n906(x) + if (x < 1) + fun_l19_n320(x) + else + fun_l19_n393(x) + end +end + +def fun_l18_n907(x) + if (x < 1) + fun_l19_n666(x) + else + fun_l19_n846(x) + end +end + +def fun_l18_n908(x) + if (x < 1) + fun_l19_n757(x) + else + fun_l19_n194(x) + end +end + +def fun_l18_n909(x) + if (x < 1) + fun_l19_n386(x) + else + fun_l19_n965(x) + end +end + +def fun_l18_n910(x) + if (x < 1) + fun_l19_n561(x) + else + fun_l19_n897(x) + end +end + +def fun_l18_n911(x) + if (x < 1) + fun_l19_n281(x) + else + fun_l19_n960(x) + end +end + +def fun_l18_n912(x) + if (x < 1) + fun_l19_n215(x) + else + fun_l19_n54(x) + end +end + +def fun_l18_n913(x) + if (x < 1) + fun_l19_n561(x) + else + fun_l19_n353(x) + end +end + +def fun_l18_n914(x) + if (x < 1) + fun_l19_n780(x) + else + fun_l19_n924(x) + end +end + +def fun_l18_n915(x) + if (x < 1) + fun_l19_n663(x) + else + fun_l19_n112(x) + end +end + +def fun_l18_n916(x) + if (x < 1) + fun_l19_n15(x) + else + fun_l19_n342(x) + end +end + +def fun_l18_n917(x) + if (x < 1) + fun_l19_n226(x) + else + fun_l19_n337(x) + end +end + +def fun_l18_n918(x) + if (x < 1) + fun_l19_n477(x) + else + fun_l19_n12(x) + end +end + +def fun_l18_n919(x) + if (x < 1) + fun_l19_n495(x) + else + fun_l19_n721(x) + end +end + +def fun_l18_n920(x) + if (x < 1) + fun_l19_n551(x) + else + fun_l19_n626(x) + end +end + +def fun_l18_n921(x) + if (x < 1) + fun_l19_n491(x) + else + fun_l19_n442(x) + end +end + +def fun_l18_n922(x) + if (x < 1) + fun_l19_n72(x) + else + fun_l19_n165(x) + end +end + +def fun_l18_n923(x) + if (x < 1) + fun_l19_n475(x) + else + fun_l19_n381(x) + end +end + +def fun_l18_n924(x) + if (x < 1) + fun_l19_n655(x) + else + fun_l19_n95(x) + end +end + +def fun_l18_n925(x) + if (x < 1) + fun_l19_n882(x) + else + fun_l19_n888(x) + end +end + +def fun_l18_n926(x) + if (x < 1) + fun_l19_n620(x) + else + fun_l19_n85(x) + end +end + +def fun_l18_n927(x) + if (x < 1) + fun_l19_n13(x) + else + fun_l19_n776(x) + end +end + +def fun_l18_n928(x) + if (x < 1) + fun_l19_n797(x) + else + fun_l19_n547(x) + end +end + +def fun_l18_n929(x) + if (x < 1) + fun_l19_n34(x) + else + fun_l19_n753(x) + end +end + +def fun_l18_n930(x) + if (x < 1) + fun_l19_n894(x) + else + fun_l19_n527(x) + end +end + +def fun_l18_n931(x) + if (x < 1) + fun_l19_n951(x) + else + fun_l19_n261(x) + end +end + +def fun_l18_n932(x) + if (x < 1) + fun_l19_n178(x) + else + fun_l19_n365(x) + end +end + +def fun_l18_n933(x) + if (x < 1) + fun_l19_n813(x) + else + fun_l19_n404(x) + end +end + +def fun_l18_n934(x) + if (x < 1) + fun_l19_n920(x) + else + fun_l19_n674(x) + end +end + +def fun_l18_n935(x) + if (x < 1) + fun_l19_n155(x) + else + fun_l19_n250(x) + end +end + +def fun_l18_n936(x) + if (x < 1) + fun_l19_n376(x) + else + fun_l19_n29(x) + end +end + +def fun_l18_n937(x) + if (x < 1) + fun_l19_n104(x) + else + fun_l19_n802(x) + end +end + +def fun_l18_n938(x) + if (x < 1) + fun_l19_n340(x) + else + fun_l19_n424(x) + end +end + +def fun_l18_n939(x) + if (x < 1) + fun_l19_n590(x) + else + fun_l19_n525(x) + end +end + +def fun_l18_n940(x) + if (x < 1) + fun_l19_n15(x) + else + fun_l19_n48(x) + end +end + +def fun_l18_n941(x) + if (x < 1) + fun_l19_n83(x) + else + fun_l19_n975(x) + end +end + +def fun_l18_n942(x) + if (x < 1) + fun_l19_n219(x) + else + fun_l19_n173(x) + end +end + +def fun_l18_n943(x) + if (x < 1) + fun_l19_n457(x) + else + fun_l19_n956(x) + end +end + +def fun_l18_n944(x) + if (x < 1) + fun_l19_n900(x) + else + fun_l19_n363(x) + end +end + +def fun_l18_n945(x) + if (x < 1) + fun_l19_n973(x) + else + fun_l19_n279(x) + end +end + +def fun_l18_n946(x) + if (x < 1) + fun_l19_n155(x) + else + fun_l19_n554(x) + end +end + +def fun_l18_n947(x) + if (x < 1) + fun_l19_n744(x) + else + fun_l19_n854(x) + end +end + +def fun_l18_n948(x) + if (x < 1) + fun_l19_n574(x) + else + fun_l19_n385(x) + end +end + +def fun_l18_n949(x) + if (x < 1) + fun_l19_n447(x) + else + fun_l19_n93(x) + end +end + +def fun_l18_n950(x) + if (x < 1) + fun_l19_n621(x) + else + fun_l19_n467(x) + end +end + +def fun_l18_n951(x) + if (x < 1) + fun_l19_n409(x) + else + fun_l19_n260(x) + end +end + +def fun_l18_n952(x) + if (x < 1) + fun_l19_n992(x) + else + fun_l19_n728(x) + end +end + +def fun_l18_n953(x) + if (x < 1) + fun_l19_n760(x) + else + fun_l19_n724(x) + end +end + +def fun_l18_n954(x) + if (x < 1) + fun_l19_n567(x) + else + fun_l19_n857(x) + end +end + +def fun_l18_n955(x) + if (x < 1) + fun_l19_n225(x) + else + fun_l19_n132(x) + end +end + +def fun_l18_n956(x) + if (x < 1) + fun_l19_n856(x) + else + fun_l19_n449(x) + end +end + +def fun_l18_n957(x) + if (x < 1) + fun_l19_n200(x) + else + fun_l19_n216(x) + end +end + +def fun_l18_n958(x) + if (x < 1) + fun_l19_n684(x) + else + fun_l19_n151(x) + end +end + +def fun_l18_n959(x) + if (x < 1) + fun_l19_n989(x) + else + fun_l19_n137(x) + end +end + +def fun_l18_n960(x) + if (x < 1) + fun_l19_n207(x) + else + fun_l19_n736(x) + end +end + +def fun_l18_n961(x) + if (x < 1) + fun_l19_n984(x) + else + fun_l19_n840(x) + end +end + +def fun_l18_n962(x) + if (x < 1) + fun_l19_n367(x) + else + fun_l19_n155(x) + end +end + +def fun_l18_n963(x) + if (x < 1) + fun_l19_n202(x) + else + fun_l19_n237(x) + end +end + +def fun_l18_n964(x) + if (x < 1) + fun_l19_n932(x) + else + fun_l19_n167(x) + end +end + +def fun_l18_n965(x) + if (x < 1) + fun_l19_n269(x) + else + fun_l19_n105(x) + end +end + +def fun_l18_n966(x) + if (x < 1) + fun_l19_n775(x) + else + fun_l19_n776(x) + end +end + +def fun_l18_n967(x) + if (x < 1) + fun_l19_n636(x) + else + fun_l19_n460(x) + end +end + +def fun_l18_n968(x) + if (x < 1) + fun_l19_n335(x) + else + fun_l19_n4(x) + end +end + +def fun_l18_n969(x) + if (x < 1) + fun_l19_n987(x) + else + fun_l19_n935(x) + end +end + +def fun_l18_n970(x) + if (x < 1) + fun_l19_n692(x) + else + fun_l19_n20(x) + end +end + +def fun_l18_n971(x) + if (x < 1) + fun_l19_n805(x) + else + fun_l19_n139(x) + end +end + +def fun_l18_n972(x) + if (x < 1) + fun_l19_n53(x) + else + fun_l19_n539(x) + end +end + +def fun_l18_n973(x) + if (x < 1) + fun_l19_n620(x) + else + fun_l19_n680(x) + end +end + +def fun_l18_n974(x) + if (x < 1) + fun_l19_n662(x) + else + fun_l19_n580(x) + end +end + +def fun_l18_n975(x) + if (x < 1) + fun_l19_n401(x) + else + fun_l19_n428(x) + end +end + +def fun_l18_n976(x) + if (x < 1) + fun_l19_n367(x) + else + fun_l19_n794(x) + end +end + +def fun_l18_n977(x) + if (x < 1) + fun_l19_n204(x) + else + fun_l19_n258(x) + end +end + +def fun_l18_n978(x) + if (x < 1) + fun_l19_n868(x) + else + fun_l19_n300(x) + end +end + +def fun_l18_n979(x) + if (x < 1) + fun_l19_n245(x) + else + fun_l19_n460(x) + end +end + +def fun_l18_n980(x) + if (x < 1) + fun_l19_n965(x) + else + fun_l19_n639(x) + end +end + +def fun_l18_n981(x) + if (x < 1) + fun_l19_n903(x) + else + fun_l19_n139(x) + end +end + +def fun_l18_n982(x) + if (x < 1) + fun_l19_n890(x) + else + fun_l19_n497(x) + end +end + +def fun_l18_n983(x) + if (x < 1) + fun_l19_n723(x) + else + fun_l19_n705(x) + end +end + +def fun_l18_n984(x) + if (x < 1) + fun_l19_n592(x) + else + fun_l19_n965(x) + end +end + +def fun_l18_n985(x) + if (x < 1) + fun_l19_n660(x) + else + fun_l19_n985(x) + end +end + +def fun_l18_n986(x) + if (x < 1) + fun_l19_n230(x) + else + fun_l19_n447(x) + end +end + +def fun_l18_n987(x) + if (x < 1) + fun_l19_n875(x) + else + fun_l19_n86(x) + end +end + +def fun_l18_n988(x) + if (x < 1) + fun_l19_n864(x) + else + fun_l19_n460(x) + end +end + +def fun_l18_n989(x) + if (x < 1) + fun_l19_n834(x) + else + fun_l19_n628(x) + end +end + +def fun_l18_n990(x) + if (x < 1) + fun_l19_n578(x) + else + fun_l19_n160(x) + end +end + +def fun_l18_n991(x) + if (x < 1) + fun_l19_n58(x) + else + fun_l19_n839(x) + end +end + +def fun_l18_n992(x) + if (x < 1) + fun_l19_n282(x) + else + fun_l19_n864(x) + end +end + +def fun_l18_n993(x) + if (x < 1) + fun_l19_n957(x) + else + fun_l19_n280(x) + end +end + +def fun_l18_n994(x) + if (x < 1) + fun_l19_n184(x) + else + fun_l19_n741(x) + end +end + +def fun_l18_n995(x) + if (x < 1) + fun_l19_n458(x) + else + fun_l19_n802(x) + end +end + +def fun_l18_n996(x) + if (x < 1) + fun_l19_n260(x) + else + fun_l19_n840(x) + end +end + +def fun_l18_n997(x) + if (x < 1) + fun_l19_n500(x) + else + fun_l19_n142(x) + end +end + +def fun_l18_n998(x) + if (x < 1) + fun_l19_n712(x) + else + fun_l19_n736(x) + end +end + +def fun_l18_n999(x) + if (x < 1) + fun_l19_n366(x) + else + fun_l19_n726(x) + end +end + +def fun_l19_n0(x) + if (x < 1) + fun_l20_n238(x) + else + fun_l20_n685(x) + end +end + +def fun_l19_n1(x) + if (x < 1) + fun_l20_n892(x) + else + fun_l20_n786(x) + end +end + +def fun_l19_n2(x) + if (x < 1) + fun_l20_n99(x) + else + fun_l20_n337(x) + end +end + +def fun_l19_n3(x) + if (x < 1) + fun_l20_n40(x) + else + fun_l20_n773(x) + end +end + +def fun_l19_n4(x) + if (x < 1) + fun_l20_n815(x) + else + fun_l20_n576(x) + end +end + +def fun_l19_n5(x) + if (x < 1) + fun_l20_n294(x) + else + fun_l20_n362(x) + end +end + +def fun_l19_n6(x) + if (x < 1) + fun_l20_n352(x) + else + fun_l20_n263(x) + end +end + +def fun_l19_n7(x) + if (x < 1) + fun_l20_n920(x) + else + fun_l20_n164(x) + end +end + +def fun_l19_n8(x) + if (x < 1) + fun_l20_n313(x) + else + fun_l20_n663(x) + end +end + +def fun_l19_n9(x) + if (x < 1) + fun_l20_n261(x) + else + fun_l20_n769(x) + end +end + +def fun_l19_n10(x) + if (x < 1) + fun_l20_n85(x) + else + fun_l20_n243(x) + end +end + +def fun_l19_n11(x) + if (x < 1) + fun_l20_n560(x) + else + fun_l20_n969(x) + end +end + +def fun_l19_n12(x) + if (x < 1) + fun_l20_n954(x) + else + fun_l20_n340(x) + end +end + +def fun_l19_n13(x) + if (x < 1) + fun_l20_n548(x) + else + fun_l20_n689(x) + end +end + +def fun_l19_n14(x) + if (x < 1) + fun_l20_n577(x) + else + fun_l20_n954(x) + end +end + +def fun_l19_n15(x) + if (x < 1) + fun_l20_n43(x) + else + fun_l20_n3(x) + end +end + +def fun_l19_n16(x) + if (x < 1) + fun_l20_n15(x) + else + fun_l20_n281(x) + end +end + +def fun_l19_n17(x) + if (x < 1) + fun_l20_n439(x) + else + fun_l20_n26(x) + end +end + +def fun_l19_n18(x) + if (x < 1) + fun_l20_n534(x) + else + fun_l20_n419(x) + end +end + +def fun_l19_n19(x) + if (x < 1) + fun_l20_n456(x) + else + fun_l20_n959(x) + end +end + +def fun_l19_n20(x) + if (x < 1) + fun_l20_n706(x) + else + fun_l20_n404(x) + end +end + +def fun_l19_n21(x) + if (x < 1) + fun_l20_n559(x) + else + fun_l20_n61(x) + end +end + +def fun_l19_n22(x) + if (x < 1) + fun_l20_n986(x) + else + fun_l20_n202(x) + end +end + +def fun_l19_n23(x) + if (x < 1) + fun_l20_n935(x) + else + fun_l20_n804(x) + end +end + +def fun_l19_n24(x) + if (x < 1) + fun_l20_n775(x) + else + fun_l20_n909(x) + end +end + +def fun_l19_n25(x) + if (x < 1) + fun_l20_n28(x) + else + fun_l20_n631(x) + end +end + +def fun_l19_n26(x) + if (x < 1) + fun_l20_n257(x) + else + fun_l20_n822(x) + end +end + +def fun_l19_n27(x) + if (x < 1) + fun_l20_n198(x) + else + fun_l20_n1(x) + end +end + +def fun_l19_n28(x) + if (x < 1) + fun_l20_n534(x) + else + fun_l20_n46(x) + end +end + +def fun_l19_n29(x) + if (x < 1) + fun_l20_n880(x) + else + fun_l20_n995(x) + end +end + +def fun_l19_n30(x) + if (x < 1) + fun_l20_n953(x) + else + fun_l20_n367(x) + end +end + +def fun_l19_n31(x) + if (x < 1) + fun_l20_n165(x) + else + fun_l20_n404(x) + end +end + +def fun_l19_n32(x) + if (x < 1) + fun_l20_n752(x) + else + fun_l20_n570(x) + end +end + +def fun_l19_n33(x) + if (x < 1) + fun_l20_n973(x) + else + fun_l20_n357(x) + end +end + +def fun_l19_n34(x) + if (x < 1) + fun_l20_n897(x) + else + fun_l20_n501(x) + end +end + +def fun_l19_n35(x) + if (x < 1) + fun_l20_n607(x) + else + fun_l20_n679(x) + end +end + +def fun_l19_n36(x) + if (x < 1) + fun_l20_n870(x) + else + fun_l20_n590(x) + end +end + +def fun_l19_n37(x) + if (x < 1) + fun_l20_n620(x) + else + fun_l20_n462(x) + end +end + +def fun_l19_n38(x) + if (x < 1) + fun_l20_n176(x) + else + fun_l20_n891(x) + end +end + +def fun_l19_n39(x) + if (x < 1) + fun_l20_n850(x) + else + fun_l20_n730(x) + end +end + +def fun_l19_n40(x) + if (x < 1) + fun_l20_n193(x) + else + fun_l20_n635(x) + end +end + +def fun_l19_n41(x) + if (x < 1) + fun_l20_n443(x) + else + fun_l20_n398(x) + end +end + +def fun_l19_n42(x) + if (x < 1) + fun_l20_n324(x) + else + fun_l20_n566(x) + end +end + +def fun_l19_n43(x) + if (x < 1) + fun_l20_n817(x) + else + fun_l20_n791(x) + end +end + +def fun_l19_n44(x) + if (x < 1) + fun_l20_n46(x) + else + fun_l20_n375(x) + end +end + +def fun_l19_n45(x) + if (x < 1) + fun_l20_n504(x) + else + fun_l20_n64(x) + end +end + +def fun_l19_n46(x) + if (x < 1) + fun_l20_n174(x) + else + fun_l20_n621(x) + end +end + +def fun_l19_n47(x) + if (x < 1) + fun_l20_n756(x) + else + fun_l20_n857(x) + end +end + +def fun_l19_n48(x) + if (x < 1) + fun_l20_n635(x) + else + fun_l20_n216(x) + end +end + +def fun_l19_n49(x) + if (x < 1) + fun_l20_n806(x) + else + fun_l20_n291(x) + end +end + +def fun_l19_n50(x) + if (x < 1) + fun_l20_n998(x) + else + fun_l20_n46(x) + end +end + +def fun_l19_n51(x) + if (x < 1) + fun_l20_n685(x) + else + fun_l20_n968(x) + end +end + +def fun_l19_n52(x) + if (x < 1) + fun_l20_n906(x) + else + fun_l20_n788(x) + end +end + +def fun_l19_n53(x) + if (x < 1) + fun_l20_n814(x) + else + fun_l20_n343(x) + end +end + +def fun_l19_n54(x) + if (x < 1) + fun_l20_n320(x) + else + fun_l20_n293(x) + end +end + +def fun_l19_n55(x) + if (x < 1) + fun_l20_n608(x) + else + fun_l20_n958(x) + end +end + +def fun_l19_n56(x) + if (x < 1) + fun_l20_n83(x) + else + fun_l20_n839(x) + end +end + +def fun_l19_n57(x) + if (x < 1) + fun_l20_n618(x) + else + fun_l20_n483(x) + end +end + +def fun_l19_n58(x) + if (x < 1) + fun_l20_n647(x) + else + fun_l20_n782(x) + end +end + +def fun_l19_n59(x) + if (x < 1) + fun_l20_n664(x) + else + fun_l20_n3(x) + end +end + +def fun_l19_n60(x) + if (x < 1) + fun_l20_n556(x) + else + fun_l20_n185(x) + end +end + +def fun_l19_n61(x) + if (x < 1) + fun_l20_n657(x) + else + fun_l20_n162(x) + end +end + +def fun_l19_n62(x) + if (x < 1) + fun_l20_n668(x) + else + fun_l20_n585(x) + end +end + +def fun_l19_n63(x) + if (x < 1) + fun_l20_n913(x) + else + fun_l20_n855(x) + end +end + +def fun_l19_n64(x) + if (x < 1) + fun_l20_n331(x) + else + fun_l20_n71(x) + end +end + +def fun_l19_n65(x) + if (x < 1) + fun_l20_n321(x) + else + fun_l20_n314(x) + end +end + +def fun_l19_n66(x) + if (x < 1) + fun_l20_n512(x) + else + fun_l20_n607(x) + end +end + +def fun_l19_n67(x) + if (x < 1) + fun_l20_n649(x) + else + fun_l20_n733(x) + end +end + +def fun_l19_n68(x) + if (x < 1) + fun_l20_n651(x) + else + fun_l20_n844(x) + end +end + +def fun_l19_n69(x) + if (x < 1) + fun_l20_n510(x) + else + fun_l20_n675(x) + end +end + +def fun_l19_n70(x) + if (x < 1) + fun_l20_n830(x) + else + fun_l20_n338(x) + end +end + +def fun_l19_n71(x) + if (x < 1) + fun_l20_n110(x) + else + fun_l20_n806(x) + end +end + +def fun_l19_n72(x) + if (x < 1) + fun_l20_n588(x) + else + fun_l20_n7(x) + end +end + +def fun_l19_n73(x) + if (x < 1) + fun_l20_n495(x) + else + fun_l20_n293(x) + end +end + +def fun_l19_n74(x) + if (x < 1) + fun_l20_n891(x) + else + fun_l20_n514(x) + end +end + +def fun_l19_n75(x) + if (x < 1) + fun_l20_n419(x) + else + fun_l20_n934(x) + end +end + +def fun_l19_n76(x) + if (x < 1) + fun_l20_n476(x) + else + fun_l20_n652(x) + end +end + +def fun_l19_n77(x) + if (x < 1) + fun_l20_n927(x) + else + fun_l20_n656(x) + end +end + +def fun_l19_n78(x) + if (x < 1) + fun_l20_n361(x) + else + fun_l20_n847(x) + end +end + +def fun_l19_n79(x) + if (x < 1) + fun_l20_n584(x) + else + fun_l20_n24(x) + end +end + +def fun_l19_n80(x) + if (x < 1) + fun_l20_n428(x) + else + fun_l20_n219(x) + end +end + +def fun_l19_n81(x) + if (x < 1) + fun_l20_n922(x) + else + fun_l20_n758(x) + end +end + +def fun_l19_n82(x) + if (x < 1) + fun_l20_n188(x) + else + fun_l20_n378(x) + end +end + +def fun_l19_n83(x) + if (x < 1) + fun_l20_n239(x) + else + fun_l20_n690(x) + end +end + +def fun_l19_n84(x) + if (x < 1) + fun_l20_n262(x) + else + fun_l20_n162(x) + end +end + +def fun_l19_n85(x) + if (x < 1) + fun_l20_n117(x) + else + fun_l20_n117(x) + end +end + +def fun_l19_n86(x) + if (x < 1) + fun_l20_n154(x) + else + fun_l20_n564(x) + end +end + +def fun_l19_n87(x) + if (x < 1) + fun_l20_n560(x) + else + fun_l20_n591(x) + end +end + +def fun_l19_n88(x) + if (x < 1) + fun_l20_n529(x) + else + fun_l20_n107(x) + end +end + +def fun_l19_n89(x) + if (x < 1) + fun_l20_n609(x) + else + fun_l20_n287(x) + end +end + +def fun_l19_n90(x) + if (x < 1) + fun_l20_n780(x) + else + fun_l20_n397(x) + end +end + +def fun_l19_n91(x) + if (x < 1) + fun_l20_n587(x) + else + fun_l20_n416(x) + end +end + +def fun_l19_n92(x) + if (x < 1) + fun_l20_n784(x) + else + fun_l20_n413(x) + end +end + +def fun_l19_n93(x) + if (x < 1) + fun_l20_n83(x) + else + fun_l20_n560(x) + end +end + +def fun_l19_n94(x) + if (x < 1) + fun_l20_n126(x) + else + fun_l20_n67(x) + end +end + +def fun_l19_n95(x) + if (x < 1) + fun_l20_n22(x) + else + fun_l20_n865(x) + end +end + +def fun_l19_n96(x) + if (x < 1) + fun_l20_n35(x) + else + fun_l20_n160(x) + end +end + +def fun_l19_n97(x) + if (x < 1) + fun_l20_n701(x) + else + fun_l20_n139(x) + end +end + +def fun_l19_n98(x) + if (x < 1) + fun_l20_n488(x) + else + fun_l20_n407(x) + end +end + +def fun_l19_n99(x) + if (x < 1) + fun_l20_n636(x) + else + fun_l20_n135(x) + end +end + +def fun_l19_n100(x) + if (x < 1) + fun_l20_n83(x) + else + fun_l20_n923(x) + end +end + +def fun_l19_n101(x) + if (x < 1) + fun_l20_n232(x) + else + fun_l20_n955(x) + end +end + +def fun_l19_n102(x) + if (x < 1) + fun_l20_n816(x) + else + fun_l20_n671(x) + end +end + +def fun_l19_n103(x) + if (x < 1) + fun_l20_n366(x) + else + fun_l20_n646(x) + end +end + +def fun_l19_n104(x) + if (x < 1) + fun_l20_n465(x) + else + fun_l20_n659(x) + end +end + +def fun_l19_n105(x) + if (x < 1) + fun_l20_n488(x) + else + fun_l20_n720(x) + end +end + +def fun_l19_n106(x) + if (x < 1) + fun_l20_n278(x) + else + fun_l20_n570(x) + end +end + +def fun_l19_n107(x) + if (x < 1) + fun_l20_n630(x) + else + fun_l20_n280(x) + end +end + +def fun_l19_n108(x) + if (x < 1) + fun_l20_n688(x) + else + fun_l20_n999(x) + end +end + +def fun_l19_n109(x) + if (x < 1) + fun_l20_n175(x) + else + fun_l20_n633(x) + end +end + +def fun_l19_n110(x) + if (x < 1) + fun_l20_n111(x) + else + fun_l20_n130(x) + end +end + +def fun_l19_n111(x) + if (x < 1) + fun_l20_n405(x) + else + fun_l20_n148(x) + end +end + +def fun_l19_n112(x) + if (x < 1) + fun_l20_n645(x) + else + fun_l20_n303(x) + end +end + +def fun_l19_n113(x) + if (x < 1) + fun_l20_n685(x) + else + fun_l20_n122(x) + end +end + +def fun_l19_n114(x) + if (x < 1) + fun_l20_n808(x) + else + fun_l20_n780(x) + end +end + +def fun_l19_n115(x) + if (x < 1) + fun_l20_n136(x) + else + fun_l20_n749(x) + end +end + +def fun_l19_n116(x) + if (x < 1) + fun_l20_n134(x) + else + fun_l20_n291(x) + end +end + +def fun_l19_n117(x) + if (x < 1) + fun_l20_n288(x) + else + fun_l20_n759(x) + end +end + +def fun_l19_n118(x) + if (x < 1) + fun_l20_n617(x) + else + fun_l20_n823(x) + end +end + +def fun_l19_n119(x) + if (x < 1) + fun_l20_n412(x) + else + fun_l20_n548(x) + end +end + +def fun_l19_n120(x) + if (x < 1) + fun_l20_n897(x) + else + fun_l20_n455(x) + end +end + +def fun_l19_n121(x) + if (x < 1) + fun_l20_n105(x) + else + fun_l20_n753(x) + end +end + +def fun_l19_n122(x) + if (x < 1) + fun_l20_n84(x) + else + fun_l20_n575(x) + end +end + +def fun_l19_n123(x) + if (x < 1) + fun_l20_n326(x) + else + fun_l20_n858(x) + end +end + +def fun_l19_n124(x) + if (x < 1) + fun_l20_n878(x) + else + fun_l20_n348(x) + end +end + +def fun_l19_n125(x) + if (x < 1) + fun_l20_n285(x) + else + fun_l20_n182(x) + end +end + +def fun_l19_n126(x) + if (x < 1) + fun_l20_n560(x) + else + fun_l20_n413(x) + end +end + +def fun_l19_n127(x) + if (x < 1) + fun_l20_n597(x) + else + fun_l20_n748(x) + end +end + +def fun_l19_n128(x) + if (x < 1) + fun_l20_n642(x) + else + fun_l20_n529(x) + end +end + +def fun_l19_n129(x) + if (x < 1) + fun_l20_n842(x) + else + fun_l20_n228(x) + end +end + +def fun_l19_n130(x) + if (x < 1) + fun_l20_n283(x) + else + fun_l20_n656(x) + end +end + +def fun_l19_n131(x) + if (x < 1) + fun_l20_n699(x) + else + fun_l20_n135(x) + end +end + +def fun_l19_n132(x) + if (x < 1) + fun_l20_n276(x) + else + fun_l20_n41(x) + end +end + +def fun_l19_n133(x) + if (x < 1) + fun_l20_n734(x) + else + fun_l20_n157(x) + end +end + +def fun_l19_n134(x) + if (x < 1) + fun_l20_n612(x) + else + fun_l20_n318(x) + end +end + +def fun_l19_n135(x) + if (x < 1) + fun_l20_n345(x) + else + fun_l20_n332(x) + end +end + +def fun_l19_n136(x) + if (x < 1) + fun_l20_n131(x) + else + fun_l20_n747(x) + end +end + +def fun_l19_n137(x) + if (x < 1) + fun_l20_n911(x) + else + fun_l20_n84(x) + end +end + +def fun_l19_n138(x) + if (x < 1) + fun_l20_n665(x) + else + fun_l20_n194(x) + end +end + +def fun_l19_n139(x) + if (x < 1) + fun_l20_n301(x) + else + fun_l20_n71(x) + end +end + +def fun_l19_n140(x) + if (x < 1) + fun_l20_n432(x) + else + fun_l20_n679(x) + end +end + +def fun_l19_n141(x) + if (x < 1) + fun_l20_n628(x) + else + fun_l20_n268(x) + end +end + +def fun_l19_n142(x) + if (x < 1) + fun_l20_n982(x) + else + fun_l20_n241(x) + end +end + +def fun_l19_n143(x) + if (x < 1) + fun_l20_n35(x) + else + fun_l20_n593(x) + end +end + +def fun_l19_n144(x) + if (x < 1) + fun_l20_n791(x) + else + fun_l20_n960(x) + end +end + +def fun_l19_n145(x) + if (x < 1) + fun_l20_n613(x) + else + fun_l20_n366(x) + end +end + +def fun_l19_n146(x) + if (x < 1) + fun_l20_n997(x) + else + fun_l20_n7(x) + end +end + +def fun_l19_n147(x) + if (x < 1) + fun_l20_n206(x) + else + fun_l20_n785(x) + end +end + +def fun_l19_n148(x) + if (x < 1) + fun_l20_n822(x) + else + fun_l20_n178(x) + end +end + +def fun_l19_n149(x) + if (x < 1) + fun_l20_n793(x) + else + fun_l20_n860(x) + end +end + +def fun_l19_n150(x) + if (x < 1) + fun_l20_n260(x) + else + fun_l20_n523(x) + end +end + +def fun_l19_n151(x) + if (x < 1) + fun_l20_n848(x) + else + fun_l20_n568(x) + end +end + +def fun_l19_n152(x) + if (x < 1) + fun_l20_n466(x) + else + fun_l20_n959(x) + end +end + +def fun_l19_n153(x) + if (x < 1) + fun_l20_n972(x) + else + fun_l20_n780(x) + end +end + +def fun_l19_n154(x) + if (x < 1) + fun_l20_n349(x) + else + fun_l20_n490(x) + end +end + +def fun_l19_n155(x) + if (x < 1) + fun_l20_n658(x) + else + fun_l20_n766(x) + end +end + +def fun_l19_n156(x) + if (x < 1) + fun_l20_n788(x) + else + fun_l20_n961(x) + end +end + +def fun_l19_n157(x) + if (x < 1) + fun_l20_n32(x) + else + fun_l20_n155(x) + end +end + +def fun_l19_n158(x) + if (x < 1) + fun_l20_n820(x) + else + fun_l20_n317(x) + end +end + +def fun_l19_n159(x) + if (x < 1) + fun_l20_n818(x) + else + fun_l20_n570(x) + end +end + +def fun_l19_n160(x) + if (x < 1) + fun_l20_n82(x) + else + fun_l20_n331(x) + end +end + +def fun_l19_n161(x) + if (x < 1) + fun_l20_n576(x) + else + fun_l20_n134(x) + end +end + +def fun_l19_n162(x) + if (x < 1) + fun_l20_n287(x) + else + fun_l20_n748(x) + end +end + +def fun_l19_n163(x) + if (x < 1) + fun_l20_n855(x) + else + fun_l20_n97(x) + end +end + +def fun_l19_n164(x) + if (x < 1) + fun_l20_n218(x) + else + fun_l20_n195(x) + end +end + +def fun_l19_n165(x) + if (x < 1) + fun_l20_n179(x) + else + fun_l20_n566(x) + end +end + +def fun_l19_n166(x) + if (x < 1) + fun_l20_n833(x) + else + fun_l20_n35(x) + end +end + +def fun_l19_n167(x) + if (x < 1) + fun_l20_n595(x) + else + fun_l20_n344(x) + end +end + +def fun_l19_n168(x) + if (x < 1) + fun_l20_n171(x) + else + fun_l20_n199(x) + end +end + +def fun_l19_n169(x) + if (x < 1) + fun_l20_n531(x) + else + fun_l20_n385(x) + end +end + +def fun_l19_n170(x) + if (x < 1) + fun_l20_n168(x) + else + fun_l20_n911(x) + end +end + +def fun_l19_n171(x) + if (x < 1) + fun_l20_n767(x) + else + fun_l20_n521(x) + end +end + +def fun_l19_n172(x) + if (x < 1) + fun_l20_n769(x) + else + fun_l20_n56(x) + end +end + +def fun_l19_n173(x) + if (x < 1) + fun_l20_n521(x) + else + fun_l20_n600(x) + end +end + +def fun_l19_n174(x) + if (x < 1) + fun_l20_n239(x) + else + fun_l20_n22(x) + end +end + +def fun_l19_n175(x) + if (x < 1) + fun_l20_n963(x) + else + fun_l20_n497(x) + end +end + +def fun_l19_n176(x) + if (x < 1) + fun_l20_n989(x) + else + fun_l20_n748(x) + end +end + +def fun_l19_n177(x) + if (x < 1) + fun_l20_n105(x) + else + fun_l20_n315(x) + end +end + +def fun_l19_n178(x) + if (x < 1) + fun_l20_n48(x) + else + fun_l20_n550(x) + end +end + +def fun_l19_n179(x) + if (x < 1) + fun_l20_n66(x) + else + fun_l20_n595(x) + end +end + +def fun_l19_n180(x) + if (x < 1) + fun_l20_n692(x) + else + fun_l20_n71(x) + end +end + +def fun_l19_n181(x) + if (x < 1) + fun_l20_n639(x) + else + fun_l20_n869(x) + end +end + +def fun_l19_n182(x) + if (x < 1) + fun_l20_n925(x) + else + fun_l20_n868(x) + end +end + +def fun_l19_n183(x) + if (x < 1) + fun_l20_n890(x) + else + fun_l20_n924(x) + end +end + +def fun_l19_n184(x) + if (x < 1) + fun_l20_n579(x) + else + fun_l20_n349(x) + end +end + +def fun_l19_n185(x) + if (x < 1) + fun_l20_n313(x) + else + fun_l20_n16(x) + end +end + +def fun_l19_n186(x) + if (x < 1) + fun_l20_n947(x) + else + fun_l20_n644(x) + end +end + +def fun_l19_n187(x) + if (x < 1) + fun_l20_n424(x) + else + fun_l20_n815(x) + end +end + +def fun_l19_n188(x) + if (x < 1) + fun_l20_n177(x) + else + fun_l20_n230(x) + end +end + +def fun_l19_n189(x) + if (x < 1) + fun_l20_n556(x) + else + fun_l20_n47(x) + end +end + +def fun_l19_n190(x) + if (x < 1) + fun_l20_n804(x) + else + fun_l20_n516(x) + end +end + +def fun_l19_n191(x) + if (x < 1) + fun_l20_n411(x) + else + fun_l20_n779(x) + end +end + +def fun_l19_n192(x) + if (x < 1) + fun_l20_n124(x) + else + fun_l20_n827(x) + end +end + +def fun_l19_n193(x) + if (x < 1) + fun_l20_n514(x) + else + fun_l20_n516(x) + end +end + +def fun_l19_n194(x) + if (x < 1) + fun_l20_n134(x) + else + fun_l20_n356(x) + end +end + +def fun_l19_n195(x) + if (x < 1) + fun_l20_n499(x) + else + fun_l20_n809(x) + end +end + +def fun_l19_n196(x) + if (x < 1) + fun_l20_n958(x) + else + fun_l20_n675(x) + end +end + +def fun_l19_n197(x) + if (x < 1) + fun_l20_n847(x) + else + fun_l20_n418(x) + end +end + +def fun_l19_n198(x) + if (x < 1) + fun_l20_n294(x) + else + fun_l20_n510(x) + end +end + +def fun_l19_n199(x) + if (x < 1) + fun_l20_n365(x) + else + fun_l20_n952(x) + end +end + +def fun_l19_n200(x) + if (x < 1) + fun_l20_n961(x) + else + fun_l20_n747(x) + end +end + +def fun_l19_n201(x) + if (x < 1) + fun_l20_n731(x) + else + fun_l20_n618(x) + end +end + +def fun_l19_n202(x) + if (x < 1) + fun_l20_n825(x) + else + fun_l20_n907(x) + end +end + +def fun_l19_n203(x) + if (x < 1) + fun_l20_n865(x) + else + fun_l20_n886(x) + end +end + +def fun_l19_n204(x) + if (x < 1) + fun_l20_n732(x) + else + fun_l20_n823(x) + end +end + +def fun_l19_n205(x) + if (x < 1) + fun_l20_n305(x) + else + fun_l20_n596(x) + end +end + +def fun_l19_n206(x) + if (x < 1) + fun_l20_n245(x) + else + fun_l20_n370(x) + end +end + +def fun_l19_n207(x) + if (x < 1) + fun_l20_n728(x) + else + fun_l20_n917(x) + end +end + +def fun_l19_n208(x) + if (x < 1) + fun_l20_n448(x) + else + fun_l20_n904(x) + end +end + +def fun_l19_n209(x) + if (x < 1) + fun_l20_n90(x) + else + fun_l20_n181(x) + end +end + +def fun_l19_n210(x) + if (x < 1) + fun_l20_n569(x) + else + fun_l20_n268(x) + end +end + +def fun_l19_n211(x) + if (x < 1) + fun_l20_n772(x) + else + fun_l20_n770(x) + end +end + +def fun_l19_n212(x) + if (x < 1) + fun_l20_n781(x) + else + fun_l20_n603(x) + end +end + +def fun_l19_n213(x) + if (x < 1) + fun_l20_n733(x) + else + fun_l20_n904(x) + end +end + +def fun_l19_n214(x) + if (x < 1) + fun_l20_n303(x) + else + fun_l20_n888(x) + end +end + +def fun_l19_n215(x) + if (x < 1) + fun_l20_n280(x) + else + fun_l20_n428(x) + end +end + +def fun_l19_n216(x) + if (x < 1) + fun_l20_n737(x) + else + fun_l20_n483(x) + end +end + +def fun_l19_n217(x) + if (x < 1) + fun_l20_n780(x) + else + fun_l20_n240(x) + end +end + +def fun_l19_n218(x) + if (x < 1) + fun_l20_n202(x) + else + fun_l20_n580(x) + end +end + +def fun_l19_n219(x) + if (x < 1) + fun_l20_n837(x) + else + fun_l20_n83(x) + end +end + +def fun_l19_n220(x) + if (x < 1) + fun_l20_n68(x) + else + fun_l20_n292(x) + end +end + +def fun_l19_n221(x) + if (x < 1) + fun_l20_n289(x) + else + fun_l20_n655(x) + end +end + +def fun_l19_n222(x) + if (x < 1) + fun_l20_n505(x) + else + fun_l20_n660(x) + end +end + +def fun_l19_n223(x) + if (x < 1) + fun_l20_n534(x) + else + fun_l20_n391(x) + end +end + +def fun_l19_n224(x) + if (x < 1) + fun_l20_n72(x) + else + fun_l20_n81(x) + end +end + +def fun_l19_n225(x) + if (x < 1) + fun_l20_n194(x) + else + fun_l20_n437(x) + end +end + +def fun_l19_n226(x) + if (x < 1) + fun_l20_n629(x) + else + fun_l20_n645(x) + end +end + +def fun_l19_n227(x) + if (x < 1) + fun_l20_n912(x) + else + fun_l20_n425(x) + end +end + +def fun_l19_n228(x) + if (x < 1) + fun_l20_n773(x) + else + fun_l20_n456(x) + end +end + +def fun_l19_n229(x) + if (x < 1) + fun_l20_n247(x) + else + fun_l20_n275(x) + end +end + +def fun_l19_n230(x) + if (x < 1) + fun_l20_n263(x) + else + fun_l20_n482(x) + end +end + +def fun_l19_n231(x) + if (x < 1) + fun_l20_n999(x) + else + fun_l20_n146(x) + end +end + +def fun_l19_n232(x) + if (x < 1) + fun_l20_n117(x) + else + fun_l20_n851(x) + end +end + +def fun_l19_n233(x) + if (x < 1) + fun_l20_n889(x) + else + fun_l20_n441(x) + end +end + +def fun_l19_n234(x) + if (x < 1) + fun_l20_n885(x) + else + fun_l20_n374(x) + end +end + +def fun_l19_n235(x) + if (x < 1) + fun_l20_n703(x) + else + fun_l20_n962(x) + end +end + +def fun_l19_n236(x) + if (x < 1) + fun_l20_n298(x) + else + fun_l20_n57(x) + end +end + +def fun_l19_n237(x) + if (x < 1) + fun_l20_n821(x) + else + fun_l20_n120(x) + end +end + +def fun_l19_n238(x) + if (x < 1) + fun_l20_n437(x) + else + fun_l20_n204(x) + end +end + +def fun_l19_n239(x) + if (x < 1) + fun_l20_n558(x) + else + fun_l20_n645(x) + end +end + +def fun_l19_n240(x) + if (x < 1) + fun_l20_n631(x) + else + fun_l20_n986(x) + end +end + +def fun_l19_n241(x) + if (x < 1) + fun_l20_n418(x) + else + fun_l20_n738(x) + end +end + +def fun_l19_n242(x) + if (x < 1) + fun_l20_n249(x) + else + fun_l20_n322(x) + end +end + +def fun_l19_n243(x) + if (x < 1) + fun_l20_n484(x) + else + fun_l20_n270(x) + end +end + +def fun_l19_n244(x) + if (x < 1) + fun_l20_n749(x) + else + fun_l20_n322(x) + end +end + +def fun_l19_n245(x) + if (x < 1) + fun_l20_n562(x) + else + fun_l20_n353(x) + end +end + +def fun_l19_n246(x) + if (x < 1) + fun_l20_n974(x) + else + fun_l20_n333(x) + end +end + +def fun_l19_n247(x) + if (x < 1) + fun_l20_n929(x) + else + fun_l20_n885(x) + end +end + +def fun_l19_n248(x) + if (x < 1) + fun_l20_n421(x) + else + fun_l20_n576(x) + end +end + +def fun_l19_n249(x) + if (x < 1) + fun_l20_n757(x) + else + fun_l20_n618(x) + end +end + +def fun_l19_n250(x) + if (x < 1) + fun_l20_n108(x) + else + fun_l20_n704(x) + end +end + +def fun_l19_n251(x) + if (x < 1) + fun_l20_n882(x) + else + fun_l20_n994(x) + end +end + +def fun_l19_n252(x) + if (x < 1) + fun_l20_n995(x) + else + fun_l20_n580(x) + end +end + +def fun_l19_n253(x) + if (x < 1) + fun_l20_n869(x) + else + fun_l20_n302(x) + end +end + +def fun_l19_n254(x) + if (x < 1) + fun_l20_n873(x) + else + fun_l20_n315(x) + end +end + +def fun_l19_n255(x) + if (x < 1) + fun_l20_n266(x) + else + fun_l20_n263(x) + end +end + +def fun_l19_n256(x) + if (x < 1) + fun_l20_n450(x) + else + fun_l20_n994(x) + end +end + +def fun_l19_n257(x) + if (x < 1) + fun_l20_n552(x) + else + fun_l20_n407(x) + end +end + +def fun_l19_n258(x) + if (x < 1) + fun_l20_n603(x) + else + fun_l20_n453(x) + end +end + +def fun_l19_n259(x) + if (x < 1) + fun_l20_n933(x) + else + fun_l20_n609(x) + end +end + +def fun_l19_n260(x) + if (x < 1) + fun_l20_n983(x) + else + fun_l20_n404(x) + end +end + +def fun_l19_n261(x) + if (x < 1) + fun_l20_n123(x) + else + fun_l20_n159(x) + end +end + +def fun_l19_n262(x) + if (x < 1) + fun_l20_n890(x) + else + fun_l20_n749(x) + end +end + +def fun_l19_n263(x) + if (x < 1) + fun_l20_n758(x) + else + fun_l20_n123(x) + end +end + +def fun_l19_n264(x) + if (x < 1) + fun_l20_n194(x) + else + fun_l20_n645(x) + end +end + +def fun_l19_n265(x) + if (x < 1) + fun_l20_n71(x) + else + fun_l20_n750(x) + end +end + +def fun_l19_n266(x) + if (x < 1) + fun_l20_n713(x) + else + fun_l20_n125(x) + end +end + +def fun_l19_n267(x) + if (x < 1) + fun_l20_n286(x) + else + fun_l20_n227(x) + end +end + +def fun_l19_n268(x) + if (x < 1) + fun_l20_n220(x) + else + fun_l20_n233(x) + end +end + +def fun_l19_n269(x) + if (x < 1) + fun_l20_n263(x) + else + fun_l20_n306(x) + end +end + +def fun_l19_n270(x) + if (x < 1) + fun_l20_n959(x) + else + fun_l20_n552(x) + end +end + +def fun_l19_n271(x) + if (x < 1) + fun_l20_n154(x) + else + fun_l20_n212(x) + end +end + +def fun_l19_n272(x) + if (x < 1) + fun_l20_n985(x) + else + fun_l20_n370(x) + end +end + +def fun_l19_n273(x) + if (x < 1) + fun_l20_n763(x) + else + fun_l20_n897(x) + end +end + +def fun_l19_n274(x) + if (x < 1) + fun_l20_n582(x) + else + fun_l20_n638(x) + end +end + +def fun_l19_n275(x) + if (x < 1) + fun_l20_n509(x) + else + fun_l20_n366(x) + end +end + +def fun_l19_n276(x) + if (x < 1) + fun_l20_n500(x) + else + fun_l20_n814(x) + end +end + +def fun_l19_n277(x) + if (x < 1) + fun_l20_n726(x) + else + fun_l20_n934(x) + end +end + +def fun_l19_n278(x) + if (x < 1) + fun_l20_n198(x) + else + fun_l20_n852(x) + end +end + +def fun_l19_n279(x) + if (x < 1) + fun_l20_n43(x) + else + fun_l20_n614(x) + end +end + +def fun_l19_n280(x) + if (x < 1) + fun_l20_n79(x) + else + fun_l20_n821(x) + end +end + +def fun_l19_n281(x) + if (x < 1) + fun_l20_n269(x) + else + fun_l20_n697(x) + end +end + +def fun_l19_n282(x) + if (x < 1) + fun_l20_n327(x) + else + fun_l20_n528(x) + end +end + +def fun_l19_n283(x) + if (x < 1) + fun_l20_n77(x) + else + fun_l20_n743(x) + end +end + +def fun_l19_n284(x) + if (x < 1) + fun_l20_n282(x) + else + fun_l20_n406(x) + end +end + +def fun_l19_n285(x) + if (x < 1) + fun_l20_n129(x) + else + fun_l20_n855(x) + end +end + +def fun_l19_n286(x) + if (x < 1) + fun_l20_n897(x) + else + fun_l20_n687(x) + end +end + +def fun_l19_n287(x) + if (x < 1) + fun_l20_n166(x) + else + fun_l20_n5(x) + end +end + +def fun_l19_n288(x) + if (x < 1) + fun_l20_n545(x) + else + fun_l20_n661(x) + end +end + +def fun_l19_n289(x) + if (x < 1) + fun_l20_n630(x) + else + fun_l20_n820(x) + end +end + +def fun_l19_n290(x) + if (x < 1) + fun_l20_n774(x) + else + fun_l20_n125(x) + end +end + +def fun_l19_n291(x) + if (x < 1) + fun_l20_n110(x) + else + fun_l20_n721(x) + end +end + +def fun_l19_n292(x) + if (x < 1) + fun_l20_n777(x) + else + fun_l20_n44(x) + end +end + +def fun_l19_n293(x) + if (x < 1) + fun_l20_n504(x) + else + fun_l20_n478(x) + end +end + +def fun_l19_n294(x) + if (x < 1) + fun_l20_n540(x) + else + fun_l20_n603(x) + end +end + +def fun_l19_n295(x) + if (x < 1) + fun_l20_n576(x) + else + fun_l20_n417(x) + end +end + +def fun_l19_n296(x) + if (x < 1) + fun_l20_n553(x) + else + fun_l20_n295(x) + end +end + +def fun_l19_n297(x) + if (x < 1) + fun_l20_n56(x) + else + fun_l20_n990(x) + end +end + +def fun_l19_n298(x) + if (x < 1) + fun_l20_n362(x) + else + fun_l20_n158(x) + end +end + +def fun_l19_n299(x) + if (x < 1) + fun_l20_n788(x) + else + fun_l20_n70(x) + end +end + +def fun_l19_n300(x) + if (x < 1) + fun_l20_n670(x) + else + fun_l20_n542(x) + end +end + +def fun_l19_n301(x) + if (x < 1) + fun_l20_n960(x) + else + fun_l20_n827(x) + end +end + +def fun_l19_n302(x) + if (x < 1) + fun_l20_n366(x) + else + fun_l20_n325(x) + end +end + +def fun_l19_n303(x) + if (x < 1) + fun_l20_n252(x) + else + fun_l20_n931(x) + end +end + +def fun_l19_n304(x) + if (x < 1) + fun_l20_n124(x) + else + fun_l20_n102(x) + end +end + +def fun_l19_n305(x) + if (x < 1) + fun_l20_n678(x) + else + fun_l20_n299(x) + end +end + +def fun_l19_n306(x) + if (x < 1) + fun_l20_n538(x) + else + fun_l20_n371(x) + end +end + +def fun_l19_n307(x) + if (x < 1) + fun_l20_n452(x) + else + fun_l20_n879(x) + end +end + +def fun_l19_n308(x) + if (x < 1) + fun_l20_n410(x) + else + fun_l20_n156(x) + end +end + +def fun_l19_n309(x) + if (x < 1) + fun_l20_n259(x) + else + fun_l20_n236(x) + end +end + +def fun_l19_n310(x) + if (x < 1) + fun_l20_n710(x) + else + fun_l20_n23(x) + end +end + +def fun_l19_n311(x) + if (x < 1) + fun_l20_n214(x) + else + fun_l20_n649(x) + end +end + +def fun_l19_n312(x) + if (x < 1) + fun_l20_n603(x) + else + fun_l20_n213(x) + end +end + +def fun_l19_n313(x) + if (x < 1) + fun_l20_n874(x) + else + fun_l20_n83(x) + end +end + +def fun_l19_n314(x) + if (x < 1) + fun_l20_n902(x) + else + fun_l20_n303(x) + end +end + +def fun_l19_n315(x) + if (x < 1) + fun_l20_n601(x) + else + fun_l20_n801(x) + end +end + +def fun_l19_n316(x) + if (x < 1) + fun_l20_n76(x) + else + fun_l20_n960(x) + end +end + +def fun_l19_n317(x) + if (x < 1) + fun_l20_n926(x) + else + fun_l20_n700(x) + end +end + +def fun_l19_n318(x) + if (x < 1) + fun_l20_n233(x) + else + fun_l20_n278(x) + end +end + +def fun_l19_n319(x) + if (x < 1) + fun_l20_n724(x) + else + fun_l20_n181(x) + end +end + +def fun_l19_n320(x) + if (x < 1) + fun_l20_n367(x) + else + fun_l20_n511(x) + end +end + +def fun_l19_n321(x) + if (x < 1) + fun_l20_n855(x) + else + fun_l20_n601(x) + end +end + +def fun_l19_n322(x) + if (x < 1) + fun_l20_n173(x) + else + fun_l20_n151(x) + end +end + +def fun_l19_n323(x) + if (x < 1) + fun_l20_n628(x) + else + fun_l20_n790(x) + end +end + +def fun_l19_n324(x) + if (x < 1) + fun_l20_n423(x) + else + fun_l20_n40(x) + end +end + +def fun_l19_n325(x) + if (x < 1) + fun_l20_n850(x) + else + fun_l20_n698(x) + end +end + +def fun_l19_n326(x) + if (x < 1) + fun_l20_n351(x) + else + fun_l20_n562(x) + end +end + +def fun_l19_n327(x) + if (x < 1) + fun_l20_n717(x) + else + fun_l20_n386(x) + end +end + +def fun_l19_n328(x) + if (x < 1) + fun_l20_n461(x) + else + fun_l20_n604(x) + end +end + +def fun_l19_n329(x) + if (x < 1) + fun_l20_n423(x) + else + fun_l20_n506(x) + end +end + +def fun_l19_n330(x) + if (x < 1) + fun_l20_n389(x) + else + fun_l20_n365(x) + end +end + +def fun_l19_n331(x) + if (x < 1) + fun_l20_n858(x) + else + fun_l20_n623(x) + end +end + +def fun_l19_n332(x) + if (x < 1) + fun_l20_n34(x) + else + fun_l20_n598(x) + end +end + +def fun_l19_n333(x) + if (x < 1) + fun_l20_n458(x) + else + fun_l20_n619(x) + end +end + +def fun_l19_n334(x) + if (x < 1) + fun_l20_n203(x) + else + fun_l20_n391(x) + end +end + +def fun_l19_n335(x) + if (x < 1) + fun_l20_n745(x) + else + fun_l20_n197(x) + end +end + +def fun_l19_n336(x) + if (x < 1) + fun_l20_n388(x) + else + fun_l20_n682(x) + end +end + +def fun_l19_n337(x) + if (x < 1) + fun_l20_n340(x) + else + fun_l20_n836(x) + end +end + +def fun_l19_n338(x) + if (x < 1) + fun_l20_n231(x) + else + fun_l20_n508(x) + end +end + +def fun_l19_n339(x) + if (x < 1) + fun_l20_n376(x) + else + fun_l20_n733(x) + end +end + +def fun_l19_n340(x) + if (x < 1) + fun_l20_n162(x) + else + fun_l20_n397(x) + end +end + +def fun_l19_n341(x) + if (x < 1) + fun_l20_n526(x) + else + fun_l20_n431(x) + end +end + +def fun_l19_n342(x) + if (x < 1) + fun_l20_n850(x) + else + fun_l20_n226(x) + end +end + +def fun_l19_n343(x) + if (x < 1) + fun_l20_n936(x) + else + fun_l20_n739(x) + end +end + +def fun_l19_n344(x) + if (x < 1) + fun_l20_n639(x) + else + fun_l20_n844(x) + end +end + +def fun_l19_n345(x) + if (x < 1) + fun_l20_n230(x) + else + fun_l20_n8(x) + end +end + +def fun_l19_n346(x) + if (x < 1) + fun_l20_n156(x) + else + fun_l20_n417(x) + end +end + +def fun_l19_n347(x) + if (x < 1) + fun_l20_n823(x) + else + fun_l20_n843(x) + end +end + +def fun_l19_n348(x) + if (x < 1) + fun_l20_n798(x) + else + fun_l20_n538(x) + end +end + +def fun_l19_n349(x) + if (x < 1) + fun_l20_n701(x) + else + fun_l20_n949(x) + end +end + +def fun_l19_n350(x) + if (x < 1) + fun_l20_n131(x) + else + fun_l20_n727(x) + end +end + +def fun_l19_n351(x) + if (x < 1) + fun_l20_n661(x) + else + fun_l20_n655(x) + end +end + +def fun_l19_n352(x) + if (x < 1) + fun_l20_n824(x) + else + fun_l20_n436(x) + end +end + +def fun_l19_n353(x) + if (x < 1) + fun_l20_n599(x) + else + fun_l20_n581(x) + end +end + +def fun_l19_n354(x) + if (x < 1) + fun_l20_n290(x) + else + fun_l20_n632(x) + end +end + +def fun_l19_n355(x) + if (x < 1) + fun_l20_n495(x) + else + fun_l20_n466(x) + end +end + +def fun_l19_n356(x) + if (x < 1) + fun_l20_n70(x) + else + fun_l20_n270(x) + end +end + +def fun_l19_n357(x) + if (x < 1) + fun_l20_n409(x) + else + fun_l20_n635(x) + end +end + +def fun_l19_n358(x) + if (x < 1) + fun_l20_n396(x) + else + fun_l20_n41(x) + end +end + +def fun_l19_n359(x) + if (x < 1) + fun_l20_n302(x) + else + fun_l20_n209(x) + end +end + +def fun_l19_n360(x) + if (x < 1) + fun_l20_n844(x) + else + fun_l20_n23(x) + end +end + +def fun_l19_n361(x) + if (x < 1) + fun_l20_n18(x) + else + fun_l20_n20(x) + end +end + +def fun_l19_n362(x) + if (x < 1) + fun_l20_n821(x) + else + fun_l20_n806(x) + end +end + +def fun_l19_n363(x) + if (x < 1) + fun_l20_n710(x) + else + fun_l20_n209(x) + end +end + +def fun_l19_n364(x) + if (x < 1) + fun_l20_n979(x) + else + fun_l20_n457(x) + end +end + +def fun_l19_n365(x) + if (x < 1) + fun_l20_n787(x) + else + fun_l20_n582(x) + end +end + +def fun_l19_n366(x) + if (x < 1) + fun_l20_n274(x) + else + fun_l20_n710(x) + end +end + +def fun_l19_n367(x) + if (x < 1) + fun_l20_n461(x) + else + fun_l20_n685(x) + end +end + +def fun_l19_n368(x) + if (x < 1) + fun_l20_n953(x) + else + fun_l20_n477(x) + end +end + +def fun_l19_n369(x) + if (x < 1) + fun_l20_n363(x) + else + fun_l20_n976(x) + end +end + +def fun_l19_n370(x) + if (x < 1) + fun_l20_n934(x) + else + fun_l20_n742(x) + end +end + +def fun_l19_n371(x) + if (x < 1) + fun_l20_n769(x) + else + fun_l20_n358(x) + end +end + +def fun_l19_n372(x) + if (x < 1) + fun_l20_n53(x) + else + fun_l20_n915(x) + end +end + +def fun_l19_n373(x) + if (x < 1) + fun_l20_n678(x) + else + fun_l20_n930(x) + end +end + +def fun_l19_n374(x) + if (x < 1) + fun_l20_n160(x) + else + fun_l20_n937(x) + end +end + +def fun_l19_n375(x) + if (x < 1) + fun_l20_n54(x) + else + fun_l20_n844(x) + end +end + +def fun_l19_n376(x) + if (x < 1) + fun_l20_n911(x) + else + fun_l20_n756(x) + end +end + +def fun_l19_n377(x) + if (x < 1) + fun_l20_n138(x) + else + fun_l20_n673(x) + end +end + +def fun_l19_n378(x) + if (x < 1) + fun_l20_n976(x) + else + fun_l20_n720(x) + end +end + +def fun_l19_n379(x) + if (x < 1) + fun_l20_n704(x) + else + fun_l20_n53(x) + end +end + +def fun_l19_n380(x) + if (x < 1) + fun_l20_n762(x) + else + fun_l20_n340(x) + end +end + +def fun_l19_n381(x) + if (x < 1) + fun_l20_n323(x) + else + fun_l20_n634(x) + end +end + +def fun_l19_n382(x) + if (x < 1) + fun_l20_n515(x) + else + fun_l20_n562(x) + end +end + +def fun_l19_n383(x) + if (x < 1) + fun_l20_n160(x) + else + fun_l20_n826(x) + end +end + +def fun_l19_n384(x) + if (x < 1) + fun_l20_n779(x) + else + fun_l20_n638(x) + end +end + +def fun_l19_n385(x) + if (x < 1) + fun_l20_n401(x) + else + fun_l20_n4(x) + end +end + +def fun_l19_n386(x) + if (x < 1) + fun_l20_n604(x) + else + fun_l20_n820(x) + end +end + +def fun_l19_n387(x) + if (x < 1) + fun_l20_n694(x) + else + fun_l20_n533(x) + end +end + +def fun_l19_n388(x) + if (x < 1) + fun_l20_n687(x) + else + fun_l20_n697(x) + end +end + +def fun_l19_n389(x) + if (x < 1) + fun_l20_n19(x) + else + fun_l20_n457(x) + end +end + +def fun_l19_n390(x) + if (x < 1) + fun_l20_n812(x) + else + fun_l20_n152(x) + end +end + +def fun_l19_n391(x) + if (x < 1) + fun_l20_n773(x) + else + fun_l20_n25(x) + end +end + +def fun_l19_n392(x) + if (x < 1) + fun_l20_n24(x) + else + fun_l20_n930(x) + end +end + +def fun_l19_n393(x) + if (x < 1) + fun_l20_n277(x) + else + fun_l20_n727(x) + end +end + +def fun_l19_n394(x) + if (x < 1) + fun_l20_n272(x) + else + fun_l20_n298(x) + end +end + +def fun_l19_n395(x) + if (x < 1) + fun_l20_n661(x) + else + fun_l20_n269(x) + end +end + +def fun_l19_n396(x) + if (x < 1) + fun_l20_n624(x) + else + fun_l20_n654(x) + end +end + +def fun_l19_n397(x) + if (x < 1) + fun_l20_n501(x) + else + fun_l20_n625(x) + end +end + +def fun_l19_n398(x) + if (x < 1) + fun_l20_n596(x) + else + fun_l20_n160(x) + end +end + +def fun_l19_n399(x) + if (x < 1) + fun_l20_n612(x) + else + fun_l20_n954(x) + end +end + +def fun_l19_n400(x) + if (x < 1) + fun_l20_n911(x) + else + fun_l20_n321(x) + end +end + +def fun_l19_n401(x) + if (x < 1) + fun_l20_n294(x) + else + fun_l20_n382(x) + end +end + +def fun_l19_n402(x) + if (x < 1) + fun_l20_n193(x) + else + fun_l20_n732(x) + end +end + +def fun_l19_n403(x) + if (x < 1) + fun_l20_n929(x) + else + fun_l20_n109(x) + end +end + +def fun_l19_n404(x) + if (x < 1) + fun_l20_n647(x) + else + fun_l20_n497(x) + end +end + +def fun_l19_n405(x) + if (x < 1) + fun_l20_n124(x) + else + fun_l20_n395(x) + end +end + +def fun_l19_n406(x) + if (x < 1) + fun_l20_n949(x) + else + fun_l20_n195(x) + end +end + +def fun_l19_n407(x) + if (x < 1) + fun_l20_n249(x) + else + fun_l20_n771(x) + end +end + +def fun_l19_n408(x) + if (x < 1) + fun_l20_n728(x) + else + fun_l20_n752(x) + end +end + +def fun_l19_n409(x) + if (x < 1) + fun_l20_n135(x) + else + fun_l20_n774(x) + end +end + +def fun_l19_n410(x) + if (x < 1) + fun_l20_n277(x) + else + fun_l20_n499(x) + end +end + +def fun_l19_n411(x) + if (x < 1) + fun_l20_n634(x) + else + fun_l20_n713(x) + end +end + +def fun_l19_n412(x) + if (x < 1) + fun_l20_n118(x) + else + fun_l20_n879(x) + end +end + +def fun_l19_n413(x) + if (x < 1) + fun_l20_n202(x) + else + fun_l20_n146(x) + end +end + +def fun_l19_n414(x) + if (x < 1) + fun_l20_n668(x) + else + fun_l20_n22(x) + end +end + +def fun_l19_n415(x) + if (x < 1) + fun_l20_n673(x) + else + fun_l20_n91(x) + end +end + +def fun_l19_n416(x) + if (x < 1) + fun_l20_n399(x) + else + fun_l20_n288(x) + end +end + +def fun_l19_n417(x) + if (x < 1) + fun_l20_n985(x) + else + fun_l20_n63(x) + end +end + +def fun_l19_n418(x) + if (x < 1) + fun_l20_n973(x) + else + fun_l20_n37(x) + end +end + +def fun_l19_n419(x) + if (x < 1) + fun_l20_n907(x) + else + fun_l20_n274(x) + end +end + +def fun_l19_n420(x) + if (x < 1) + fun_l20_n0(x) + else + fun_l20_n895(x) + end +end + +def fun_l19_n421(x) + if (x < 1) + fun_l20_n138(x) + else + fun_l20_n941(x) + end +end + +def fun_l19_n422(x) + if (x < 1) + fun_l20_n944(x) + else + fun_l20_n393(x) + end +end + +def fun_l19_n423(x) + if (x < 1) + fun_l20_n7(x) + else + fun_l20_n879(x) + end +end + +def fun_l19_n424(x) + if (x < 1) + fun_l20_n855(x) + else + fun_l20_n19(x) + end +end + +def fun_l19_n425(x) + if (x < 1) + fun_l20_n11(x) + else + fun_l20_n12(x) + end +end + +def fun_l19_n426(x) + if (x < 1) + fun_l20_n652(x) + else + fun_l20_n501(x) + end +end + +def fun_l19_n427(x) + if (x < 1) + fun_l20_n825(x) + else + fun_l20_n547(x) + end +end + +def fun_l19_n428(x) + if (x < 1) + fun_l20_n485(x) + else + fun_l20_n905(x) + end +end + +def fun_l19_n429(x) + if (x < 1) + fun_l20_n800(x) + else + fun_l20_n922(x) + end +end + +def fun_l19_n430(x) + if (x < 1) + fun_l20_n122(x) + else + fun_l20_n79(x) + end +end + +def fun_l19_n431(x) + if (x < 1) + fun_l20_n822(x) + else + fun_l20_n228(x) + end +end + +def fun_l19_n432(x) + if (x < 1) + fun_l20_n616(x) + else + fun_l20_n886(x) + end +end + +def fun_l19_n433(x) + if (x < 1) + fun_l20_n232(x) + else + fun_l20_n716(x) + end +end + +def fun_l19_n434(x) + if (x < 1) + fun_l20_n288(x) + else + fun_l20_n497(x) + end +end + +def fun_l19_n435(x) + if (x < 1) + fun_l20_n606(x) + else + fun_l20_n220(x) + end +end + +def fun_l19_n436(x) + if (x < 1) + fun_l20_n185(x) + else + fun_l20_n69(x) + end +end + +def fun_l19_n437(x) + if (x < 1) + fun_l20_n869(x) + else + fun_l20_n264(x) + end +end + +def fun_l19_n438(x) + if (x < 1) + fun_l20_n142(x) + else + fun_l20_n766(x) + end +end + +def fun_l19_n439(x) + if (x < 1) + fun_l20_n155(x) + else + fun_l20_n697(x) + end +end + +def fun_l19_n440(x) + if (x < 1) + fun_l20_n486(x) + else + fun_l20_n442(x) + end +end + +def fun_l19_n441(x) + if (x < 1) + fun_l20_n896(x) + else + fun_l20_n404(x) + end +end + +def fun_l19_n442(x) + if (x < 1) + fun_l20_n944(x) + else + fun_l20_n906(x) + end +end + +def fun_l19_n443(x) + if (x < 1) + fun_l20_n400(x) + else + fun_l20_n230(x) + end +end + +def fun_l19_n444(x) + if (x < 1) + fun_l20_n646(x) + else + fun_l20_n89(x) + end +end + +def fun_l19_n445(x) + if (x < 1) + fun_l20_n683(x) + else + fun_l20_n434(x) + end +end + +def fun_l19_n446(x) + if (x < 1) + fun_l20_n333(x) + else + fun_l20_n164(x) + end +end + +def fun_l19_n447(x) + if (x < 1) + fun_l20_n732(x) + else + fun_l20_n721(x) + end +end + +def fun_l19_n448(x) + if (x < 1) + fun_l20_n948(x) + else + fun_l20_n343(x) + end +end + +def fun_l19_n449(x) + if (x < 1) + fun_l20_n211(x) + else + fun_l20_n754(x) + end +end + +def fun_l19_n450(x) + if (x < 1) + fun_l20_n984(x) + else + fun_l20_n952(x) + end +end + +def fun_l19_n451(x) + if (x < 1) + fun_l20_n349(x) + else + fun_l20_n424(x) + end +end + +def fun_l19_n452(x) + if (x < 1) + fun_l20_n721(x) + else + fun_l20_n475(x) + end +end + +def fun_l19_n453(x) + if (x < 1) + fun_l20_n143(x) + else + fun_l20_n875(x) + end +end + +def fun_l19_n454(x) + if (x < 1) + fun_l20_n561(x) + else + fun_l20_n255(x) + end +end + +def fun_l19_n455(x) + if (x < 1) + fun_l20_n962(x) + else + fun_l20_n489(x) + end +end + +def fun_l19_n456(x) + if (x < 1) + fun_l20_n95(x) + else + fun_l20_n434(x) + end +end + +def fun_l19_n457(x) + if (x < 1) + fun_l20_n863(x) + else + fun_l20_n198(x) + end +end + +def fun_l19_n458(x) + if (x < 1) + fun_l20_n106(x) + else + fun_l20_n786(x) + end +end + +def fun_l19_n459(x) + if (x < 1) + fun_l20_n415(x) + else + fun_l20_n456(x) + end +end + +def fun_l19_n460(x) + if (x < 1) + fun_l20_n706(x) + else + fun_l20_n47(x) + end +end + +def fun_l19_n461(x) + if (x < 1) + fun_l20_n894(x) + else + fun_l20_n119(x) + end +end + +def fun_l19_n462(x) + if (x < 1) + fun_l20_n267(x) + else + fun_l20_n662(x) + end +end + +def fun_l19_n463(x) + if (x < 1) + fun_l20_n689(x) + else + fun_l20_n633(x) + end +end + +def fun_l19_n464(x) + if (x < 1) + fun_l20_n94(x) + else + fun_l20_n967(x) + end +end + +def fun_l19_n465(x) + if (x < 1) + fun_l20_n902(x) + else + fun_l20_n619(x) + end +end + +def fun_l19_n466(x) + if (x < 1) + fun_l20_n574(x) + else + fun_l20_n204(x) + end +end + +def fun_l19_n467(x) + if (x < 1) + fun_l20_n195(x) + else + fun_l20_n455(x) + end +end + +def fun_l19_n468(x) + if (x < 1) + fun_l20_n173(x) + else + fun_l20_n4(x) + end +end + +def fun_l19_n469(x) + if (x < 1) + fun_l20_n769(x) + else + fun_l20_n314(x) + end +end + +def fun_l19_n470(x) + if (x < 1) + fun_l20_n669(x) + else + fun_l20_n648(x) + end +end + +def fun_l19_n471(x) + if (x < 1) + fun_l20_n741(x) + else + fun_l20_n238(x) + end +end + +def fun_l19_n472(x) + if (x < 1) + fun_l20_n370(x) + else + fun_l20_n610(x) + end +end + +def fun_l19_n473(x) + if (x < 1) + fun_l20_n200(x) + else + fun_l20_n698(x) + end +end + +def fun_l19_n474(x) + if (x < 1) + fun_l20_n200(x) + else + fun_l20_n951(x) + end +end + +def fun_l19_n475(x) + if (x < 1) + fun_l20_n47(x) + else + fun_l20_n244(x) + end +end + +def fun_l19_n476(x) + if (x < 1) + fun_l20_n314(x) + else + fun_l20_n163(x) + end +end + +def fun_l19_n477(x) + if (x < 1) + fun_l20_n665(x) + else + fun_l20_n278(x) + end +end + +def fun_l19_n478(x) + if (x < 1) + fun_l20_n539(x) + else + fun_l20_n149(x) + end +end + +def fun_l19_n479(x) + if (x < 1) + fun_l20_n10(x) + else + fun_l20_n686(x) + end +end + +def fun_l19_n480(x) + if (x < 1) + fun_l20_n684(x) + else + fun_l20_n531(x) + end +end + +def fun_l19_n481(x) + if (x < 1) + fun_l20_n579(x) + else + fun_l20_n468(x) + end +end + +def fun_l19_n482(x) + if (x < 1) + fun_l20_n794(x) + else + fun_l20_n116(x) + end +end + +def fun_l19_n483(x) + if (x < 1) + fun_l20_n848(x) + else + fun_l20_n278(x) + end +end + +def fun_l19_n484(x) + if (x < 1) + fun_l20_n965(x) + else + fun_l20_n23(x) + end +end + +def fun_l19_n485(x) + if (x < 1) + fun_l20_n123(x) + else + fun_l20_n905(x) + end +end + +def fun_l19_n486(x) + if (x < 1) + fun_l20_n69(x) + else + fun_l20_n4(x) + end +end + +def fun_l19_n487(x) + if (x < 1) + fun_l20_n234(x) + else + fun_l20_n648(x) + end +end + +def fun_l19_n488(x) + if (x < 1) + fun_l20_n31(x) + else + fun_l20_n127(x) + end +end + +def fun_l19_n489(x) + if (x < 1) + fun_l20_n469(x) + else + fun_l20_n300(x) + end +end + +def fun_l19_n490(x) + if (x < 1) + fun_l20_n855(x) + else + fun_l20_n722(x) + end +end + +def fun_l19_n491(x) + if (x < 1) + fun_l20_n949(x) + else + fun_l20_n567(x) + end +end + +def fun_l19_n492(x) + if (x < 1) + fun_l20_n465(x) + else + fun_l20_n226(x) + end +end + +def fun_l19_n493(x) + if (x < 1) + fun_l20_n436(x) + else + fun_l20_n292(x) + end +end + +def fun_l19_n494(x) + if (x < 1) + fun_l20_n552(x) + else + fun_l20_n81(x) + end +end + +def fun_l19_n495(x) + if (x < 1) + fun_l20_n950(x) + else + fun_l20_n481(x) + end +end + +def fun_l19_n496(x) + if (x < 1) + fun_l20_n382(x) + else + fun_l20_n846(x) + end +end + +def fun_l19_n497(x) + if (x < 1) + fun_l20_n355(x) + else + fun_l20_n546(x) + end +end + +def fun_l19_n498(x) + if (x < 1) + fun_l20_n404(x) + else + fun_l20_n655(x) + end +end + +def fun_l19_n499(x) + if (x < 1) + fun_l20_n794(x) + else + fun_l20_n531(x) + end +end + +def fun_l19_n500(x) + if (x < 1) + fun_l20_n555(x) + else + fun_l20_n37(x) + end +end + +def fun_l19_n501(x) + if (x < 1) + fun_l20_n955(x) + else + fun_l20_n60(x) + end +end + +def fun_l19_n502(x) + if (x < 1) + fun_l20_n957(x) + else + fun_l20_n482(x) + end +end + +def fun_l19_n503(x) + if (x < 1) + fun_l20_n683(x) + else + fun_l20_n374(x) + end +end + +def fun_l19_n504(x) + if (x < 1) + fun_l20_n839(x) + else + fun_l20_n867(x) + end +end + +def fun_l19_n505(x) + if (x < 1) + fun_l20_n956(x) + else + fun_l20_n336(x) + end +end + +def fun_l19_n506(x) + if (x < 1) + fun_l20_n234(x) + else + fun_l20_n50(x) + end +end + +def fun_l19_n507(x) + if (x < 1) + fun_l20_n968(x) + else + fun_l20_n627(x) + end +end + +def fun_l19_n508(x) + if (x < 1) + fun_l20_n680(x) + else + fun_l20_n812(x) + end +end + +def fun_l19_n509(x) + if (x < 1) + fun_l20_n106(x) + else + fun_l20_n428(x) + end +end + +def fun_l19_n510(x) + if (x < 1) + fun_l20_n50(x) + else + fun_l20_n101(x) + end +end + +def fun_l19_n511(x) + if (x < 1) + fun_l20_n75(x) + else + fun_l20_n299(x) + end +end + +def fun_l19_n512(x) + if (x < 1) + fun_l20_n612(x) + else + fun_l20_n367(x) + end +end + +def fun_l19_n513(x) + if (x < 1) + fun_l20_n278(x) + else + fun_l20_n803(x) + end +end + +def fun_l19_n514(x) + if (x < 1) + fun_l20_n637(x) + else + fun_l20_n837(x) + end +end + +def fun_l19_n515(x) + if (x < 1) + fun_l20_n908(x) + else + fun_l20_n410(x) + end +end + +def fun_l19_n516(x) + if (x < 1) + fun_l20_n349(x) + else + fun_l20_n219(x) + end +end + +def fun_l19_n517(x) + if (x < 1) + fun_l20_n869(x) + else + fun_l20_n922(x) + end +end + +def fun_l19_n518(x) + if (x < 1) + fun_l20_n429(x) + else + fun_l20_n332(x) + end +end + +def fun_l19_n519(x) + if (x < 1) + fun_l20_n775(x) + else + fun_l20_n417(x) + end +end + +def fun_l19_n520(x) + if (x < 1) + fun_l20_n551(x) + else + fun_l20_n214(x) + end +end + +def fun_l19_n521(x) + if (x < 1) + fun_l20_n643(x) + else + fun_l20_n74(x) + end +end + +def fun_l19_n522(x) + if (x < 1) + fun_l20_n960(x) + else + fun_l20_n189(x) + end +end + +def fun_l19_n523(x) + if (x < 1) + fun_l20_n815(x) + else + fun_l20_n624(x) + end +end + +def fun_l19_n524(x) + if (x < 1) + fun_l20_n247(x) + else + fun_l20_n679(x) + end +end + +def fun_l19_n525(x) + if (x < 1) + fun_l20_n261(x) + else + fun_l20_n728(x) + end +end + +def fun_l19_n526(x) + if (x < 1) + fun_l20_n361(x) + else + fun_l20_n295(x) + end +end + +def fun_l19_n527(x) + if (x < 1) + fun_l20_n559(x) + else + fun_l20_n763(x) + end +end + +def fun_l19_n528(x) + if (x < 1) + fun_l20_n291(x) + else + fun_l20_n815(x) + end +end + +def fun_l19_n529(x) + if (x < 1) + fun_l20_n224(x) + else + fun_l20_n305(x) + end +end + +def fun_l19_n530(x) + if (x < 1) + fun_l20_n579(x) + else + fun_l20_n370(x) + end +end + +def fun_l19_n531(x) + if (x < 1) + fun_l20_n571(x) + else + fun_l20_n65(x) + end +end + +def fun_l19_n532(x) + if (x < 1) + fun_l20_n815(x) + else + fun_l20_n567(x) + end +end + +def fun_l19_n533(x) + if (x < 1) + fun_l20_n48(x) + else + fun_l20_n386(x) + end +end + +def fun_l19_n534(x) + if (x < 1) + fun_l20_n478(x) + else + fun_l20_n679(x) + end +end + +def fun_l19_n535(x) + if (x < 1) + fun_l20_n241(x) + else + fun_l20_n829(x) + end +end + +def fun_l19_n536(x) + if (x < 1) + fun_l20_n267(x) + else + fun_l20_n160(x) + end +end + +def fun_l19_n537(x) + if (x < 1) + fun_l20_n719(x) + else + fun_l20_n199(x) + end +end + +def fun_l19_n538(x) + if (x < 1) + fun_l20_n477(x) + else + fun_l20_n662(x) + end +end + +def fun_l19_n539(x) + if (x < 1) + fun_l20_n506(x) + else + fun_l20_n856(x) + end +end + +def fun_l19_n540(x) + if (x < 1) + fun_l20_n717(x) + else + fun_l20_n207(x) + end +end + +def fun_l19_n541(x) + if (x < 1) + fun_l20_n94(x) + else + fun_l20_n988(x) + end +end + +def fun_l19_n542(x) + if (x < 1) + fun_l20_n837(x) + else + fun_l20_n334(x) + end +end + +def fun_l19_n543(x) + if (x < 1) + fun_l20_n23(x) + else + fun_l20_n991(x) + end +end + +def fun_l19_n544(x) + if (x < 1) + fun_l20_n558(x) + else + fun_l20_n740(x) + end +end + +def fun_l19_n545(x) + if (x < 1) + fun_l20_n762(x) + else + fun_l20_n79(x) + end +end + +def fun_l19_n546(x) + if (x < 1) + fun_l20_n81(x) + else + fun_l20_n331(x) + end +end + +def fun_l19_n547(x) + if (x < 1) + fun_l20_n9(x) + else + fun_l20_n267(x) + end +end + +def fun_l19_n548(x) + if (x < 1) + fun_l20_n550(x) + else + fun_l20_n98(x) + end +end + +def fun_l19_n549(x) + if (x < 1) + fun_l20_n735(x) + else + fun_l20_n361(x) + end +end + +def fun_l19_n550(x) + if (x < 1) + fun_l20_n155(x) + else + fun_l20_n560(x) + end +end + +def fun_l19_n551(x) + if (x < 1) + fun_l20_n394(x) + else + fun_l20_n793(x) + end +end + +def fun_l19_n552(x) + if (x < 1) + fun_l20_n826(x) + else + fun_l20_n508(x) + end +end + +def fun_l19_n553(x) + if (x < 1) + fun_l20_n569(x) + else + fun_l20_n981(x) + end +end + +def fun_l19_n554(x) + if (x < 1) + fun_l20_n580(x) + else + fun_l20_n848(x) + end +end + +def fun_l19_n555(x) + if (x < 1) + fun_l20_n31(x) + else + fun_l20_n191(x) + end +end + +def fun_l19_n556(x) + if (x < 1) + fun_l20_n283(x) + else + fun_l20_n376(x) + end +end + +def fun_l19_n557(x) + if (x < 1) + fun_l20_n978(x) + else + fun_l20_n554(x) + end +end + +def fun_l19_n558(x) + if (x < 1) + fun_l20_n727(x) + else + fun_l20_n89(x) + end +end + +def fun_l19_n559(x) + if (x < 1) + fun_l20_n204(x) + else + fun_l20_n652(x) + end +end + +def fun_l19_n560(x) + if (x < 1) + fun_l20_n481(x) + else + fun_l20_n114(x) + end +end + +def fun_l19_n561(x) + if (x < 1) + fun_l20_n601(x) + else + fun_l20_n187(x) + end +end + +def fun_l19_n562(x) + if (x < 1) + fun_l20_n682(x) + else + fun_l20_n88(x) + end +end + +def fun_l19_n563(x) + if (x < 1) + fun_l20_n346(x) + else + fun_l20_n190(x) + end +end + +def fun_l19_n564(x) + if (x < 1) + fun_l20_n15(x) + else + fun_l20_n315(x) + end +end + +def fun_l19_n565(x) + if (x < 1) + fun_l20_n555(x) + else + fun_l20_n208(x) + end +end + +def fun_l19_n566(x) + if (x < 1) + fun_l20_n29(x) + else + fun_l20_n511(x) + end +end + +def fun_l19_n567(x) + if (x < 1) + fun_l20_n897(x) + else + fun_l20_n309(x) + end +end + +def fun_l19_n568(x) + if (x < 1) + fun_l20_n586(x) + else + fun_l20_n602(x) + end +end + +def fun_l19_n569(x) + if (x < 1) + fun_l20_n51(x) + else + fun_l20_n483(x) + end +end + +def fun_l19_n570(x) + if (x < 1) + fun_l20_n159(x) + else + fun_l20_n5(x) + end +end + +def fun_l19_n571(x) + if (x < 1) + fun_l20_n892(x) + else + fun_l20_n336(x) + end +end + +def fun_l19_n572(x) + if (x < 1) + fun_l20_n203(x) + else + fun_l20_n287(x) + end +end + +def fun_l19_n573(x) + if (x < 1) + fun_l20_n41(x) + else + fun_l20_n51(x) + end +end + +def fun_l19_n574(x) + if (x < 1) + fun_l20_n977(x) + else + fun_l20_n474(x) + end +end + +def fun_l19_n575(x) + if (x < 1) + fun_l20_n247(x) + else + fun_l20_n281(x) + end +end + +def fun_l19_n576(x) + if (x < 1) + fun_l20_n877(x) + else + fun_l20_n836(x) + end +end + +def fun_l19_n577(x) + if (x < 1) + fun_l20_n527(x) + else + fun_l20_n549(x) + end +end + +def fun_l19_n578(x) + if (x < 1) + fun_l20_n102(x) + else + fun_l20_n906(x) + end +end + +def fun_l19_n579(x) + if (x < 1) + fun_l20_n842(x) + else + fun_l20_n554(x) + end +end + +def fun_l19_n580(x) + if (x < 1) + fun_l20_n371(x) + else + fun_l20_n44(x) + end +end + +def fun_l19_n581(x) + if (x < 1) + fun_l20_n306(x) + else + fun_l20_n571(x) + end +end + +def fun_l19_n582(x) + if (x < 1) + fun_l20_n548(x) + else + fun_l20_n596(x) + end +end + +def fun_l19_n583(x) + if (x < 1) + fun_l20_n724(x) + else + fun_l20_n835(x) + end +end + +def fun_l19_n584(x) + if (x < 1) + fun_l20_n238(x) + else + fun_l20_n408(x) + end +end + +def fun_l19_n585(x) + if (x < 1) + fun_l20_n378(x) + else + fun_l20_n272(x) + end +end + +def fun_l19_n586(x) + if (x < 1) + fun_l20_n647(x) + else + fun_l20_n814(x) + end +end + +def fun_l19_n587(x) + if (x < 1) + fun_l20_n210(x) + else + fun_l20_n801(x) + end +end + +def fun_l19_n588(x) + if (x < 1) + fun_l20_n796(x) + else + fun_l20_n329(x) + end +end + +def fun_l19_n589(x) + if (x < 1) + fun_l20_n403(x) + else + fun_l20_n392(x) + end +end + +def fun_l19_n590(x) + if (x < 1) + fun_l20_n677(x) + else + fun_l20_n574(x) + end +end + +def fun_l19_n591(x) + if (x < 1) + fun_l20_n183(x) + else + fun_l20_n962(x) + end +end + +def fun_l19_n592(x) + if (x < 1) + fun_l20_n230(x) + else + fun_l20_n783(x) + end +end + +def fun_l19_n593(x) + if (x < 1) + fun_l20_n191(x) + else + fun_l20_n42(x) + end +end + +def fun_l19_n594(x) + if (x < 1) + fun_l20_n244(x) + else + fun_l20_n760(x) + end +end + +def fun_l19_n595(x) + if (x < 1) + fun_l20_n754(x) + else + fun_l20_n570(x) + end +end + +def fun_l19_n596(x) + if (x < 1) + fun_l20_n612(x) + else + fun_l20_n287(x) + end +end + +def fun_l19_n597(x) + if (x < 1) + fun_l20_n89(x) + else + fun_l20_n625(x) + end +end + +def fun_l19_n598(x) + if (x < 1) + fun_l20_n782(x) + else + fun_l20_n516(x) + end +end + +def fun_l19_n599(x) + if (x < 1) + fun_l20_n75(x) + else + fun_l20_n857(x) + end +end + +def fun_l19_n600(x) + if (x < 1) + fun_l20_n717(x) + else + fun_l20_n408(x) + end +end + +def fun_l19_n601(x) + if (x < 1) + fun_l20_n528(x) + else + fun_l20_n761(x) + end +end + +def fun_l19_n602(x) + if (x < 1) + fun_l20_n319(x) + else + fun_l20_n645(x) + end +end + +def fun_l19_n603(x) + if (x < 1) + fun_l20_n20(x) + else + fun_l20_n621(x) + end +end + +def fun_l19_n604(x) + if (x < 1) + fun_l20_n118(x) + else + fun_l20_n699(x) + end +end + +def fun_l19_n605(x) + if (x < 1) + fun_l20_n19(x) + else + fun_l20_n63(x) + end +end + +def fun_l19_n606(x) + if (x < 1) + fun_l20_n845(x) + else + fun_l20_n618(x) + end +end + +def fun_l19_n607(x) + if (x < 1) + fun_l20_n733(x) + else + fun_l20_n880(x) + end +end + +def fun_l19_n608(x) + if (x < 1) + fun_l20_n785(x) + else + fun_l20_n254(x) + end +end + +def fun_l19_n609(x) + if (x < 1) + fun_l20_n393(x) + else + fun_l20_n946(x) + end +end + +def fun_l19_n610(x) + if (x < 1) + fun_l20_n635(x) + else + fun_l20_n418(x) + end +end + +def fun_l19_n611(x) + if (x < 1) + fun_l20_n987(x) + else + fun_l20_n703(x) + end +end + +def fun_l19_n612(x) + if (x < 1) + fun_l20_n130(x) + else + fun_l20_n439(x) + end +end + +def fun_l19_n613(x) + if (x < 1) + fun_l20_n516(x) + else + fun_l20_n724(x) + end +end + +def fun_l19_n614(x) + if (x < 1) + fun_l20_n44(x) + else + fun_l20_n102(x) + end +end + +def fun_l19_n615(x) + if (x < 1) + fun_l20_n353(x) + else + fun_l20_n999(x) + end +end + +def fun_l19_n616(x) + if (x < 1) + fun_l20_n191(x) + else + fun_l20_n726(x) + end +end + +def fun_l19_n617(x) + if (x < 1) + fun_l20_n375(x) + else + fun_l20_n575(x) + end +end + +def fun_l19_n618(x) + if (x < 1) + fun_l20_n719(x) + else + fun_l20_n581(x) + end +end + +def fun_l19_n619(x) + if (x < 1) + fun_l20_n960(x) + else + fun_l20_n316(x) + end +end + +def fun_l19_n620(x) + if (x < 1) + fun_l20_n860(x) + else + fun_l20_n784(x) + end +end + +def fun_l19_n621(x) + if (x < 1) + fun_l20_n124(x) + else + fun_l20_n577(x) + end +end + +def fun_l19_n622(x) + if (x < 1) + fun_l20_n547(x) + else + fun_l20_n623(x) + end +end + +def fun_l19_n623(x) + if (x < 1) + fun_l20_n842(x) + else + fun_l20_n380(x) + end +end + +def fun_l19_n624(x) + if (x < 1) + fun_l20_n331(x) + else + fun_l20_n473(x) + end +end + +def fun_l19_n625(x) + if (x < 1) + fun_l20_n118(x) + else + fun_l20_n392(x) + end +end + +def fun_l19_n626(x) + if (x < 1) + fun_l20_n836(x) + else + fun_l20_n988(x) + end +end + +def fun_l19_n627(x) + if (x < 1) + fun_l20_n641(x) + else + fun_l20_n372(x) + end +end + +def fun_l19_n628(x) + if (x < 1) + fun_l20_n377(x) + else + fun_l20_n780(x) + end +end + +def fun_l19_n629(x) + if (x < 1) + fun_l20_n180(x) + else + fun_l20_n670(x) + end +end + +def fun_l19_n630(x) + if (x < 1) + fun_l20_n985(x) + else + fun_l20_n613(x) + end +end + +def fun_l19_n631(x) + if (x < 1) + fun_l20_n149(x) + else + fun_l20_n754(x) + end +end + +def fun_l19_n632(x) + if (x < 1) + fun_l20_n967(x) + else + fun_l20_n940(x) + end +end + +def fun_l19_n633(x) + if (x < 1) + fun_l20_n91(x) + else + fun_l20_n772(x) + end +end + +def fun_l19_n634(x) + if (x < 1) + fun_l20_n637(x) + else + fun_l20_n296(x) + end +end + +def fun_l19_n635(x) + if (x < 1) + fun_l20_n50(x) + else + fun_l20_n314(x) + end +end + +def fun_l19_n636(x) + if (x < 1) + fun_l20_n367(x) + else + fun_l20_n849(x) + end +end + +def fun_l19_n637(x) + if (x < 1) + fun_l20_n229(x) + else + fun_l20_n550(x) + end +end + +def fun_l19_n638(x) + if (x < 1) + fun_l20_n680(x) + else + fun_l20_n783(x) + end +end + +def fun_l19_n639(x) + if (x < 1) + fun_l20_n879(x) + else + fun_l20_n264(x) + end +end + +def fun_l19_n640(x) + if (x < 1) + fun_l20_n143(x) + else + fun_l20_n455(x) + end +end + +def fun_l19_n641(x) + if (x < 1) + fun_l20_n191(x) + else + fun_l20_n110(x) + end +end + +def fun_l19_n642(x) + if (x < 1) + fun_l20_n782(x) + else + fun_l20_n43(x) + end +end + +def fun_l19_n643(x) + if (x < 1) + fun_l20_n320(x) + else + fun_l20_n376(x) + end +end + +def fun_l19_n644(x) + if (x < 1) + fun_l20_n554(x) + else + fun_l20_n667(x) + end +end + +def fun_l19_n645(x) + if (x < 1) + fun_l20_n29(x) + else + fun_l20_n938(x) + end +end + +def fun_l19_n646(x) + if (x < 1) + fun_l20_n789(x) + else + fun_l20_n907(x) + end +end + +def fun_l19_n647(x) + if (x < 1) + fun_l20_n859(x) + else + fun_l20_n138(x) + end +end + +def fun_l19_n648(x) + if (x < 1) + fun_l20_n373(x) + else + fun_l20_n843(x) + end +end + +def fun_l19_n649(x) + if (x < 1) + fun_l20_n50(x) + else + fun_l20_n982(x) + end +end + +def fun_l19_n650(x) + if (x < 1) + fun_l20_n622(x) + else + fun_l20_n368(x) + end +end + +def fun_l19_n651(x) + if (x < 1) + fun_l20_n231(x) + else + fun_l20_n523(x) + end +end + +def fun_l19_n652(x) + if (x < 1) + fun_l20_n233(x) + else + fun_l20_n963(x) + end +end + +def fun_l19_n653(x) + if (x < 1) + fun_l20_n363(x) + else + fun_l20_n177(x) + end +end + +def fun_l19_n654(x) + if (x < 1) + fun_l20_n952(x) + else + fun_l20_n96(x) + end +end + +def fun_l19_n655(x) + if (x < 1) + fun_l20_n98(x) + else + fun_l20_n93(x) + end +end + +def fun_l19_n656(x) + if (x < 1) + fun_l20_n200(x) + else + fun_l20_n137(x) + end +end + +def fun_l19_n657(x) + if (x < 1) + fun_l20_n485(x) + else + fun_l20_n45(x) + end +end + +def fun_l19_n658(x) + if (x < 1) + fun_l20_n234(x) + else + fun_l20_n366(x) + end +end + +def fun_l19_n659(x) + if (x < 1) + fun_l20_n120(x) + else + fun_l20_n850(x) + end +end + +def fun_l19_n660(x) + if (x < 1) + fun_l20_n932(x) + else + fun_l20_n551(x) + end +end + +def fun_l19_n661(x) + if (x < 1) + fun_l20_n952(x) + else + fun_l20_n178(x) + end +end + +def fun_l19_n662(x) + if (x < 1) + fun_l20_n761(x) + else + fun_l20_n2(x) + end +end + +def fun_l19_n663(x) + if (x < 1) + fun_l20_n674(x) + else + fun_l20_n698(x) + end +end + +def fun_l19_n664(x) + if (x < 1) + fun_l20_n669(x) + else + fun_l20_n563(x) + end +end + +def fun_l19_n665(x) + if (x < 1) + fun_l20_n106(x) + else + fun_l20_n442(x) + end +end + +def fun_l19_n666(x) + if (x < 1) + fun_l20_n476(x) + else + fun_l20_n620(x) + end +end + +def fun_l19_n667(x) + if (x < 1) + fun_l20_n813(x) + else + fun_l20_n501(x) + end +end + +def fun_l19_n668(x) + if (x < 1) + fun_l20_n773(x) + else + fun_l20_n485(x) + end +end + +def fun_l19_n669(x) + if (x < 1) + fun_l20_n533(x) + else + fun_l20_n801(x) + end +end + +def fun_l19_n670(x) + if (x < 1) + fun_l20_n64(x) + else + fun_l20_n872(x) + end +end + +def fun_l19_n671(x) + if (x < 1) + fun_l20_n770(x) + else + fun_l20_n101(x) + end +end + +def fun_l19_n672(x) + if (x < 1) + fun_l20_n22(x) + else + fun_l20_n644(x) + end +end + +def fun_l19_n673(x) + if (x < 1) + fun_l20_n634(x) + else + fun_l20_n955(x) + end +end + +def fun_l19_n674(x) + if (x < 1) + fun_l20_n976(x) + else + fun_l20_n665(x) + end +end + +def fun_l19_n675(x) + if (x < 1) + fun_l20_n988(x) + else + fun_l20_n793(x) + end +end + +def fun_l19_n676(x) + if (x < 1) + fun_l20_n235(x) + else + fun_l20_n833(x) + end +end + +def fun_l19_n677(x) + if (x < 1) + fun_l20_n604(x) + else + fun_l20_n797(x) + end +end + +def fun_l19_n678(x) + if (x < 1) + fun_l20_n622(x) + else + fun_l20_n896(x) + end +end + +def fun_l19_n679(x) + if (x < 1) + fun_l20_n190(x) + else + fun_l20_n281(x) + end +end + +def fun_l19_n680(x) + if (x < 1) + fun_l20_n325(x) + else + fun_l20_n669(x) + end +end + +def fun_l19_n681(x) + if (x < 1) + fun_l20_n898(x) + else + fun_l20_n352(x) + end +end + +def fun_l19_n682(x) + if (x < 1) + fun_l20_n820(x) + else + fun_l20_n117(x) + end +end + +def fun_l19_n683(x) + if (x < 1) + fun_l20_n148(x) + else + fun_l20_n842(x) + end +end + +def fun_l19_n684(x) + if (x < 1) + fun_l20_n468(x) + else + fun_l20_n596(x) + end +end + +def fun_l19_n685(x) + if (x < 1) + fun_l20_n285(x) + else + fun_l20_n730(x) + end +end + +def fun_l19_n686(x) + if (x < 1) + fun_l20_n426(x) + else + fun_l20_n657(x) + end +end + +def fun_l19_n687(x) + if (x < 1) + fun_l20_n874(x) + else + fun_l20_n867(x) + end +end + +def fun_l19_n688(x) + if (x < 1) + fun_l20_n451(x) + else + fun_l20_n846(x) + end +end + +def fun_l19_n689(x) + if (x < 1) + fun_l20_n425(x) + else + fun_l20_n796(x) + end +end + +def fun_l19_n690(x) + if (x < 1) + fun_l20_n37(x) + else + fun_l20_n301(x) + end +end + +def fun_l19_n691(x) + if (x < 1) + fun_l20_n886(x) + else + fun_l20_n513(x) + end +end + +def fun_l19_n692(x) + if (x < 1) + fun_l20_n426(x) + else + fun_l20_n46(x) + end +end + +def fun_l19_n693(x) + if (x < 1) + fun_l20_n622(x) + else + fun_l20_n738(x) + end +end + +def fun_l19_n694(x) + if (x < 1) + fun_l20_n530(x) + else + fun_l20_n981(x) + end +end + +def fun_l19_n695(x) + if (x < 1) + fun_l20_n568(x) + else + fun_l20_n934(x) + end +end + +def fun_l19_n696(x) + if (x < 1) + fun_l20_n974(x) + else + fun_l20_n585(x) + end +end + +def fun_l19_n697(x) + if (x < 1) + fun_l20_n780(x) + else + fun_l20_n408(x) + end +end + +def fun_l19_n698(x) + if (x < 1) + fun_l20_n373(x) + else + fun_l20_n163(x) + end +end + +def fun_l19_n699(x) + if (x < 1) + fun_l20_n745(x) + else + fun_l20_n4(x) + end +end + +def fun_l19_n700(x) + if (x < 1) + fun_l20_n307(x) + else + fun_l20_n172(x) + end +end + +def fun_l19_n701(x) + if (x < 1) + fun_l20_n342(x) + else + fun_l20_n381(x) + end +end + +def fun_l19_n702(x) + if (x < 1) + fun_l20_n67(x) + else + fun_l20_n841(x) + end +end + +def fun_l19_n703(x) + if (x < 1) + fun_l20_n697(x) + else + fun_l20_n597(x) + end +end + +def fun_l19_n704(x) + if (x < 1) + fun_l20_n809(x) + else + fun_l20_n306(x) + end +end + +def fun_l19_n705(x) + if (x < 1) + fun_l20_n575(x) + else + fun_l20_n401(x) + end +end + +def fun_l19_n706(x) + if (x < 1) + fun_l20_n651(x) + else + fun_l20_n552(x) + end +end + +def fun_l19_n707(x) + if (x < 1) + fun_l20_n644(x) + else + fun_l20_n697(x) + end +end + +def fun_l19_n708(x) + if (x < 1) + fun_l20_n572(x) + else + fun_l20_n86(x) + end +end + +def fun_l19_n709(x) + if (x < 1) + fun_l20_n239(x) + else + fun_l20_n18(x) + end +end + +def fun_l19_n710(x) + if (x < 1) + fun_l20_n48(x) + else + fun_l20_n822(x) + end +end + +def fun_l19_n711(x) + if (x < 1) + fun_l20_n126(x) + else + fun_l20_n186(x) + end +end + +def fun_l19_n712(x) + if (x < 1) + fun_l20_n552(x) + else + fun_l20_n901(x) + end +end + +def fun_l19_n713(x) + if (x < 1) + fun_l20_n993(x) + else + fun_l20_n313(x) + end +end + +def fun_l19_n714(x) + if (x < 1) + fun_l20_n918(x) + else + fun_l20_n718(x) + end +end + +def fun_l19_n715(x) + if (x < 1) + fun_l20_n442(x) + else + fun_l20_n652(x) + end +end + +def fun_l19_n716(x) + if (x < 1) + fun_l20_n624(x) + else + fun_l20_n492(x) + end +end + +def fun_l19_n717(x) + if (x < 1) + fun_l20_n585(x) + else + fun_l20_n980(x) + end +end + +def fun_l19_n718(x) + if (x < 1) + fun_l20_n159(x) + else + fun_l20_n327(x) + end +end + +def fun_l19_n719(x) + if (x < 1) + fun_l20_n867(x) + else + fun_l20_n239(x) + end +end + +def fun_l19_n720(x) + if (x < 1) + fun_l20_n551(x) + else + fun_l20_n123(x) + end +end + +def fun_l19_n721(x) + if (x < 1) + fun_l20_n794(x) + else + fun_l20_n1(x) + end +end + +def fun_l19_n722(x) + if (x < 1) + fun_l20_n193(x) + else + fun_l20_n847(x) + end +end + +def fun_l19_n723(x) + if (x < 1) + fun_l20_n560(x) + else + fun_l20_n163(x) + end +end + +def fun_l19_n724(x) + if (x < 1) + fun_l20_n338(x) + else + fun_l20_n411(x) + end +end + +def fun_l19_n725(x) + if (x < 1) + fun_l20_n227(x) + else + fun_l20_n437(x) + end +end + +def fun_l19_n726(x) + if (x < 1) + fun_l20_n691(x) + else + fun_l20_n821(x) + end +end + +def fun_l19_n727(x) + if (x < 1) + fun_l20_n578(x) + else + fun_l20_n589(x) + end +end + +def fun_l19_n728(x) + if (x < 1) + fun_l20_n990(x) + else + fun_l20_n164(x) + end +end + +def fun_l19_n729(x) + if (x < 1) + fun_l20_n620(x) + else + fun_l20_n736(x) + end +end + +def fun_l19_n730(x) + if (x < 1) + fun_l20_n980(x) + else + fun_l20_n345(x) + end +end + +def fun_l19_n731(x) + if (x < 1) + fun_l20_n302(x) + else + fun_l20_n75(x) + end +end + +def fun_l19_n732(x) + if (x < 1) + fun_l20_n684(x) + else + fun_l20_n2(x) + end +end + +def fun_l19_n733(x) + if (x < 1) + fun_l20_n11(x) + else + fun_l20_n503(x) + end +end + +def fun_l19_n734(x) + if (x < 1) + fun_l20_n719(x) + else + fun_l20_n745(x) + end +end + +def fun_l19_n735(x) + if (x < 1) + fun_l20_n74(x) + else + fun_l20_n413(x) + end +end + +def fun_l19_n736(x) + if (x < 1) + fun_l20_n858(x) + else + fun_l20_n224(x) + end +end + +def fun_l19_n737(x) + if (x < 1) + fun_l20_n372(x) + else + fun_l20_n1(x) + end +end + +def fun_l19_n738(x) + if (x < 1) + fun_l20_n274(x) + else + fun_l20_n967(x) + end +end + +def fun_l19_n739(x) + if (x < 1) + fun_l20_n191(x) + else + fun_l20_n984(x) + end +end + +def fun_l19_n740(x) + if (x < 1) + fun_l20_n646(x) + else + fun_l20_n279(x) + end +end + +def fun_l19_n741(x) + if (x < 1) + fun_l20_n55(x) + else + fun_l20_n947(x) + end +end + +def fun_l19_n742(x) + if (x < 1) + fun_l20_n306(x) + else + fun_l20_n798(x) + end +end + +def fun_l19_n743(x) + if (x < 1) + fun_l20_n571(x) + else + fun_l20_n905(x) + end +end + +def fun_l19_n744(x) + if (x < 1) + fun_l20_n270(x) + else + fun_l20_n290(x) + end +end + +def fun_l19_n745(x) + if (x < 1) + fun_l20_n39(x) + else + fun_l20_n983(x) + end +end + +def fun_l19_n746(x) + if (x < 1) + fun_l20_n405(x) + else + fun_l20_n727(x) + end +end + +def fun_l19_n747(x) + if (x < 1) + fun_l20_n424(x) + else + fun_l20_n597(x) + end +end + +def fun_l19_n748(x) + if (x < 1) + fun_l20_n602(x) + else + fun_l20_n467(x) + end +end + +def fun_l19_n749(x) + if (x < 1) + fun_l20_n859(x) + else + fun_l20_n76(x) + end +end + +def fun_l19_n750(x) + if (x < 1) + fun_l20_n201(x) + else + fun_l20_n948(x) + end +end + +def fun_l19_n751(x) + if (x < 1) + fun_l20_n998(x) + else + fun_l20_n425(x) + end +end + +def fun_l19_n752(x) + if (x < 1) + fun_l20_n352(x) + else + fun_l20_n762(x) + end +end + +def fun_l19_n753(x) + if (x < 1) + fun_l20_n996(x) + else + fun_l20_n136(x) + end +end + +def fun_l19_n754(x) + if (x < 1) + fun_l20_n462(x) + else + fun_l20_n544(x) + end +end + +def fun_l19_n755(x) + if (x < 1) + fun_l20_n126(x) + else + fun_l20_n857(x) + end +end + +def fun_l19_n756(x) + if (x < 1) + fun_l20_n695(x) + else + fun_l20_n444(x) + end +end + +def fun_l19_n757(x) + if (x < 1) + fun_l20_n694(x) + else + fun_l20_n718(x) + end +end + +def fun_l19_n758(x) + if (x < 1) + fun_l20_n308(x) + else + fun_l20_n867(x) + end +end + +def fun_l19_n759(x) + if (x < 1) + fun_l20_n224(x) + else + fun_l20_n739(x) + end +end + +def fun_l19_n760(x) + if (x < 1) + fun_l20_n286(x) + else + fun_l20_n660(x) + end +end + +def fun_l19_n761(x) + if (x < 1) + fun_l20_n486(x) + else + fun_l20_n614(x) + end +end + +def fun_l19_n762(x) + if (x < 1) + fun_l20_n234(x) + else + fun_l20_n812(x) + end +end + +def fun_l19_n763(x) + if (x < 1) + fun_l20_n663(x) + else + fun_l20_n649(x) + end +end + +def fun_l19_n764(x) + if (x < 1) + fun_l20_n815(x) + else + fun_l20_n436(x) + end +end + +def fun_l19_n765(x) + if (x < 1) + fun_l20_n330(x) + else + fun_l20_n350(x) + end +end + +def fun_l19_n766(x) + if (x < 1) + fun_l20_n532(x) + else + fun_l20_n676(x) + end +end + +def fun_l19_n767(x) + if (x < 1) + fun_l20_n74(x) + else + fun_l20_n182(x) + end +end + +def fun_l19_n768(x) + if (x < 1) + fun_l20_n432(x) + else + fun_l20_n912(x) + end +end + +def fun_l19_n769(x) + if (x < 1) + fun_l20_n413(x) + else + fun_l20_n315(x) + end +end + +def fun_l19_n770(x) + if (x < 1) + fun_l20_n457(x) + else + fun_l20_n917(x) + end +end + +def fun_l19_n771(x) + if (x < 1) + fun_l20_n435(x) + else + fun_l20_n768(x) + end +end + +def fun_l19_n772(x) + if (x < 1) + fun_l20_n994(x) + else + fun_l20_n865(x) + end +end + +def fun_l19_n773(x) + if (x < 1) + fun_l20_n425(x) + else + fun_l20_n347(x) + end +end + +def fun_l19_n774(x) + if (x < 1) + fun_l20_n405(x) + else + fun_l20_n1(x) + end +end + +def fun_l19_n775(x) + if (x < 1) + fun_l20_n460(x) + else + fun_l20_n417(x) + end +end + +def fun_l19_n776(x) + if (x < 1) + fun_l20_n539(x) + else + fun_l20_n825(x) + end +end + +def fun_l19_n777(x) + if (x < 1) + fun_l20_n180(x) + else + fun_l20_n613(x) + end +end + +def fun_l19_n778(x) + if (x < 1) + fun_l20_n452(x) + else + fun_l20_n717(x) + end +end + +def fun_l19_n779(x) + if (x < 1) + fun_l20_n265(x) + else + fun_l20_n802(x) + end +end + +def fun_l19_n780(x) + if (x < 1) + fun_l20_n941(x) + else + fun_l20_n939(x) + end +end + +def fun_l19_n781(x) + if (x < 1) + fun_l20_n777(x) + else + fun_l20_n796(x) + end +end + +def fun_l19_n782(x) + if (x < 1) + fun_l20_n924(x) + else + fun_l20_n442(x) + end +end + +def fun_l19_n783(x) + if (x < 1) + fun_l20_n901(x) + else + fun_l20_n817(x) + end +end + +def fun_l19_n784(x) + if (x < 1) + fun_l20_n101(x) + else + fun_l20_n983(x) + end +end + +def fun_l19_n785(x) + if (x < 1) + fun_l20_n992(x) + else + fun_l20_n790(x) + end +end + +def fun_l19_n786(x) + if (x < 1) + fun_l20_n426(x) + else + fun_l20_n337(x) + end +end + +def fun_l19_n787(x) + if (x < 1) + fun_l20_n812(x) + else + fun_l20_n7(x) + end +end + +def fun_l19_n788(x) + if (x < 1) + fun_l20_n768(x) + else + fun_l20_n25(x) + end +end + +def fun_l19_n789(x) + if (x < 1) + fun_l20_n292(x) + else + fun_l20_n440(x) + end +end + +def fun_l19_n790(x) + if (x < 1) + fun_l20_n855(x) + else + fun_l20_n191(x) + end +end + +def fun_l19_n791(x) + if (x < 1) + fun_l20_n32(x) + else + fun_l20_n855(x) + end +end + +def fun_l19_n792(x) + if (x < 1) + fun_l20_n920(x) + else + fun_l20_n198(x) + end +end + +def fun_l19_n793(x) + if (x < 1) + fun_l20_n411(x) + else + fun_l20_n396(x) + end +end + +def fun_l19_n794(x) + if (x < 1) + fun_l20_n977(x) + else + fun_l20_n712(x) + end +end + +def fun_l19_n795(x) + if (x < 1) + fun_l20_n636(x) + else + fun_l20_n66(x) + end +end + +def fun_l19_n796(x) + if (x < 1) + fun_l20_n137(x) + else + fun_l20_n656(x) + end +end + +def fun_l19_n797(x) + if (x < 1) + fun_l20_n51(x) + else + fun_l20_n244(x) + end +end + +def fun_l19_n798(x) + if (x < 1) + fun_l20_n426(x) + else + fun_l20_n418(x) + end +end + +def fun_l19_n799(x) + if (x < 1) + fun_l20_n272(x) + else + fun_l20_n365(x) + end +end + +def fun_l19_n800(x) + if (x < 1) + fun_l20_n361(x) + else + fun_l20_n952(x) + end +end + +def fun_l19_n801(x) + if (x < 1) + fun_l20_n428(x) + else + fun_l20_n683(x) + end +end + +def fun_l19_n802(x) + if (x < 1) + fun_l20_n54(x) + else + fun_l20_n86(x) + end +end + +def fun_l19_n803(x) + if (x < 1) + fun_l20_n771(x) + else + fun_l20_n555(x) + end +end + +def fun_l19_n804(x) + if (x < 1) + fun_l20_n498(x) + else + fun_l20_n744(x) + end +end + +def fun_l19_n805(x) + if (x < 1) + fun_l20_n30(x) + else + fun_l20_n813(x) + end +end + +def fun_l19_n806(x) + if (x < 1) + fun_l20_n96(x) + else + fun_l20_n295(x) + end +end + +def fun_l19_n807(x) + if (x < 1) + fun_l20_n128(x) + else + fun_l20_n584(x) + end +end + +def fun_l19_n808(x) + if (x < 1) + fun_l20_n818(x) + else + fun_l20_n396(x) + end +end + +def fun_l19_n809(x) + if (x < 1) + fun_l20_n896(x) + else + fun_l20_n779(x) + end +end + +def fun_l19_n810(x) + if (x < 1) + fun_l20_n40(x) + else + fun_l20_n638(x) + end +end + +def fun_l19_n811(x) + if (x < 1) + fun_l20_n925(x) + else + fun_l20_n914(x) + end +end + +def fun_l19_n812(x) + if (x < 1) + fun_l20_n217(x) + else + fun_l20_n833(x) + end +end + +def fun_l19_n813(x) + if (x < 1) + fun_l20_n687(x) + else + fun_l20_n469(x) + end +end + +def fun_l19_n814(x) + if (x < 1) + fun_l20_n709(x) + else + fun_l20_n196(x) + end +end + +def fun_l19_n815(x) + if (x < 1) + fun_l20_n633(x) + else + fun_l20_n622(x) + end +end + +def fun_l19_n816(x) + if (x < 1) + fun_l20_n976(x) + else + fun_l20_n691(x) + end +end + +def fun_l19_n817(x) + if (x < 1) + fun_l20_n260(x) + else + fun_l20_n592(x) + end +end + +def fun_l19_n818(x) + if (x < 1) + fun_l20_n893(x) + else + fun_l20_n353(x) + end +end + +def fun_l19_n819(x) + if (x < 1) + fun_l20_n824(x) + else + fun_l20_n875(x) + end +end + +def fun_l19_n820(x) + if (x < 1) + fun_l20_n605(x) + else + fun_l20_n797(x) + end +end + +def fun_l19_n821(x) + if (x < 1) + fun_l20_n990(x) + else + fun_l20_n272(x) + end +end + +def fun_l19_n822(x) + if (x < 1) + fun_l20_n819(x) + else + fun_l20_n313(x) + end +end + +def fun_l19_n823(x) + if (x < 1) + fun_l20_n838(x) + else + fun_l20_n513(x) + end +end + +def fun_l19_n824(x) + if (x < 1) + fun_l20_n332(x) + else + fun_l20_n838(x) + end +end + +def fun_l19_n825(x) + if (x < 1) + fun_l20_n994(x) + else + fun_l20_n641(x) + end +end + +def fun_l19_n826(x) + if (x < 1) + fun_l20_n820(x) + else + fun_l20_n17(x) + end +end + +def fun_l19_n827(x) + if (x < 1) + fun_l20_n645(x) + else + fun_l20_n587(x) + end +end + +def fun_l19_n828(x) + if (x < 1) + fun_l20_n352(x) + else + fun_l20_n726(x) + end +end + +def fun_l19_n829(x) + if (x < 1) + fun_l20_n33(x) + else + fun_l20_n803(x) + end +end + +def fun_l19_n830(x) + if (x < 1) + fun_l20_n854(x) + else + fun_l20_n468(x) + end +end + +def fun_l19_n831(x) + if (x < 1) + fun_l20_n149(x) + else + fun_l20_n529(x) + end +end + +def fun_l19_n832(x) + if (x < 1) + fun_l20_n442(x) + else + fun_l20_n114(x) + end +end + +def fun_l19_n833(x) + if (x < 1) + fun_l20_n986(x) + else + fun_l20_n778(x) + end +end + +def fun_l19_n834(x) + if (x < 1) + fun_l20_n220(x) + else + fun_l20_n782(x) + end +end + +def fun_l19_n835(x) + if (x < 1) + fun_l20_n330(x) + else + fun_l20_n361(x) + end +end + +def fun_l19_n836(x) + if (x < 1) + fun_l20_n805(x) + else + fun_l20_n204(x) + end +end + +def fun_l19_n837(x) + if (x < 1) + fun_l20_n534(x) + else + fun_l20_n970(x) + end +end + +def fun_l19_n838(x) + if (x < 1) + fun_l20_n890(x) + else + fun_l20_n526(x) + end +end + +def fun_l19_n839(x) + if (x < 1) + fun_l20_n511(x) + else + fun_l20_n743(x) + end +end + +def fun_l19_n840(x) + if (x < 1) + fun_l20_n730(x) + else + fun_l20_n435(x) + end +end + +def fun_l19_n841(x) + if (x < 1) + fun_l20_n34(x) + else + fun_l20_n228(x) + end +end + +def fun_l19_n842(x) + if (x < 1) + fun_l20_n170(x) + else + fun_l20_n162(x) + end +end + +def fun_l19_n843(x) + if (x < 1) + fun_l20_n987(x) + else + fun_l20_n631(x) + end +end + +def fun_l19_n844(x) + if (x < 1) + fun_l20_n193(x) + else + fun_l20_n48(x) + end +end + +def fun_l19_n845(x) + if (x < 1) + fun_l20_n479(x) + else + fun_l20_n295(x) + end +end + +def fun_l19_n846(x) + if (x < 1) + fun_l20_n545(x) + else + fun_l20_n474(x) + end +end + +def fun_l19_n847(x) + if (x < 1) + fun_l20_n155(x) + else + fun_l20_n222(x) + end +end + +def fun_l19_n848(x) + if (x < 1) + fun_l20_n641(x) + else + fun_l20_n151(x) + end +end + +def fun_l19_n849(x) + if (x < 1) + fun_l20_n191(x) + else + fun_l20_n563(x) + end +end + +def fun_l19_n850(x) + if (x < 1) + fun_l20_n891(x) + else + fun_l20_n247(x) + end +end + +def fun_l19_n851(x) + if (x < 1) + fun_l20_n987(x) + else + fun_l20_n296(x) + end +end + +def fun_l19_n852(x) + if (x < 1) + fun_l20_n86(x) + else + fun_l20_n346(x) + end +end + +def fun_l19_n853(x) + if (x < 1) + fun_l20_n93(x) + else + fun_l20_n198(x) + end +end + +def fun_l19_n854(x) + if (x < 1) + fun_l20_n767(x) + else + fun_l20_n759(x) + end +end + +def fun_l19_n855(x) + if (x < 1) + fun_l20_n571(x) + else + fun_l20_n456(x) + end +end + +def fun_l19_n856(x) + if (x < 1) + fun_l20_n722(x) + else + fun_l20_n603(x) + end +end + +def fun_l19_n857(x) + if (x < 1) + fun_l20_n940(x) + else + fun_l20_n163(x) + end +end + +def fun_l19_n858(x) + if (x < 1) + fun_l20_n973(x) + else + fun_l20_n598(x) + end +end + +def fun_l19_n859(x) + if (x < 1) + fun_l20_n79(x) + else + fun_l20_n401(x) + end +end + +def fun_l19_n860(x) + if (x < 1) + fun_l20_n234(x) + else + fun_l20_n769(x) + end +end + +def fun_l19_n861(x) + if (x < 1) + fun_l20_n292(x) + else + fun_l20_n526(x) + end +end + +def fun_l19_n862(x) + if (x < 1) + fun_l20_n554(x) + else + fun_l20_n468(x) + end +end + +def fun_l19_n863(x) + if (x < 1) + fun_l20_n386(x) + else + fun_l20_n946(x) + end +end + +def fun_l19_n864(x) + if (x < 1) + fun_l20_n227(x) + else + fun_l20_n287(x) + end +end + +def fun_l19_n865(x) + if (x < 1) + fun_l20_n485(x) + else + fun_l20_n276(x) + end +end + +def fun_l19_n866(x) + if (x < 1) + fun_l20_n38(x) + else + fun_l20_n329(x) + end +end + +def fun_l19_n867(x) + if (x < 1) + fun_l20_n1(x) + else + fun_l20_n985(x) + end +end + +def fun_l19_n868(x) + if (x < 1) + fun_l20_n13(x) + else + fun_l20_n823(x) + end +end + +def fun_l19_n869(x) + if (x < 1) + fun_l20_n834(x) + else + fun_l20_n959(x) + end +end + +def fun_l19_n870(x) + if (x < 1) + fun_l20_n177(x) + else + fun_l20_n232(x) + end +end + +def fun_l19_n871(x) + if (x < 1) + fun_l20_n56(x) + else + fun_l20_n712(x) + end +end + +def fun_l19_n872(x) + if (x < 1) + fun_l20_n69(x) + else + fun_l20_n850(x) + end +end + +def fun_l19_n873(x) + if (x < 1) + fun_l20_n558(x) + else + fun_l20_n877(x) + end +end + +def fun_l19_n874(x) + if (x < 1) + fun_l20_n34(x) + else + fun_l20_n540(x) + end +end + +def fun_l19_n875(x) + if (x < 1) + fun_l20_n392(x) + else + fun_l20_n904(x) + end +end + +def fun_l19_n876(x) + if (x < 1) + fun_l20_n99(x) + else + fun_l20_n691(x) + end +end + +def fun_l19_n877(x) + if (x < 1) + fun_l20_n799(x) + else + fun_l20_n982(x) + end +end + +def fun_l19_n878(x) + if (x < 1) + fun_l20_n511(x) + else + fun_l20_n869(x) + end +end + +def fun_l19_n879(x) + if (x < 1) + fun_l20_n65(x) + else + fun_l20_n318(x) + end +end + +def fun_l19_n880(x) + if (x < 1) + fun_l20_n335(x) + else + fun_l20_n811(x) + end +end + +def fun_l19_n881(x) + if (x < 1) + fun_l20_n165(x) + else + fun_l20_n870(x) + end +end + +def fun_l19_n882(x) + if (x < 1) + fun_l20_n427(x) + else + fun_l20_n597(x) + end +end + +def fun_l19_n883(x) + if (x < 1) + fun_l20_n319(x) + else + fun_l20_n503(x) + end +end + +def fun_l19_n884(x) + if (x < 1) + fun_l20_n57(x) + else + fun_l20_n620(x) + end +end + +def fun_l19_n885(x) + if (x < 1) + fun_l20_n489(x) + else + fun_l20_n359(x) + end +end + +def fun_l19_n886(x) + if (x < 1) + fun_l20_n773(x) + else + fun_l20_n719(x) + end +end + +def fun_l19_n887(x) + if (x < 1) + fun_l20_n969(x) + else + fun_l20_n32(x) + end +end + +def fun_l19_n888(x) + if (x < 1) + fun_l20_n758(x) + else + fun_l20_n132(x) + end +end + +def fun_l19_n889(x) + if (x < 1) + fun_l20_n130(x) + else + fun_l20_n886(x) + end +end + +def fun_l19_n890(x) + if (x < 1) + fun_l20_n195(x) + else + fun_l20_n258(x) + end +end + +def fun_l19_n891(x) + if (x < 1) + fun_l20_n747(x) + else + fun_l20_n967(x) + end +end + +def fun_l19_n892(x) + if (x < 1) + fun_l20_n403(x) + else + fun_l20_n314(x) + end +end + +def fun_l19_n893(x) + if (x < 1) + fun_l20_n927(x) + else + fun_l20_n923(x) + end +end + +def fun_l19_n894(x) + if (x < 1) + fun_l20_n894(x) + else + fun_l20_n318(x) + end +end + +def fun_l19_n895(x) + if (x < 1) + fun_l20_n825(x) + else + fun_l20_n574(x) + end +end + +def fun_l19_n896(x) + if (x < 1) + fun_l20_n436(x) + else + fun_l20_n321(x) + end +end + +def fun_l19_n897(x) + if (x < 1) + fun_l20_n317(x) + else + fun_l20_n312(x) + end +end + +def fun_l19_n898(x) + if (x < 1) + fun_l20_n219(x) + else + fun_l20_n362(x) + end +end + +def fun_l19_n899(x) + if (x < 1) + fun_l20_n731(x) + else + fun_l20_n1(x) + end +end + +def fun_l19_n900(x) + if (x < 1) + fun_l20_n804(x) + else + fun_l20_n629(x) + end +end + +def fun_l19_n901(x) + if (x < 1) + fun_l20_n152(x) + else + fun_l20_n232(x) + end +end + +def fun_l19_n902(x) + if (x < 1) + fun_l20_n104(x) + else + fun_l20_n579(x) + end +end + +def fun_l19_n903(x) + if (x < 1) + fun_l20_n860(x) + else + fun_l20_n322(x) + end +end + +def fun_l19_n904(x) + if (x < 1) + fun_l20_n55(x) + else + fun_l20_n70(x) + end +end + +def fun_l19_n905(x) + if (x < 1) + fun_l20_n674(x) + else + fun_l20_n713(x) + end +end + +def fun_l19_n906(x) + if (x < 1) + fun_l20_n957(x) + else + fun_l20_n962(x) + end +end + +def fun_l19_n907(x) + if (x < 1) + fun_l20_n656(x) + else + fun_l20_n582(x) + end +end + +def fun_l19_n908(x) + if (x < 1) + fun_l20_n3(x) + else + fun_l20_n323(x) + end +end + +def fun_l19_n909(x) + if (x < 1) + fun_l20_n763(x) + else + fun_l20_n387(x) + end +end + +def fun_l19_n910(x) + if (x < 1) + fun_l20_n434(x) + else + fun_l20_n113(x) + end +end + +def fun_l19_n911(x) + if (x < 1) + fun_l20_n713(x) + else + fun_l20_n4(x) + end +end + +def fun_l19_n912(x) + if (x < 1) + fun_l20_n313(x) + else + fun_l20_n776(x) + end +end + +def fun_l19_n913(x) + if (x < 1) + fun_l20_n541(x) + else + fun_l20_n80(x) + end +end + +def fun_l19_n914(x) + if (x < 1) + fun_l20_n131(x) + else + fun_l20_n982(x) + end +end + +def fun_l19_n915(x) + if (x < 1) + fun_l20_n558(x) + else + fun_l20_n538(x) + end +end + +def fun_l19_n916(x) + if (x < 1) + fun_l20_n715(x) + else + fun_l20_n401(x) + end +end + +def fun_l19_n917(x) + if (x < 1) + fun_l20_n820(x) + else + fun_l20_n576(x) + end +end + +def fun_l19_n918(x) + if (x < 1) + fun_l20_n602(x) + else + fun_l20_n158(x) + end +end + +def fun_l19_n919(x) + if (x < 1) + fun_l20_n127(x) + else + fun_l20_n493(x) + end +end + +def fun_l19_n920(x) + if (x < 1) + fun_l20_n719(x) + else + fun_l20_n895(x) + end +end + +def fun_l19_n921(x) + if (x < 1) + fun_l20_n277(x) + else + fun_l20_n588(x) + end +end + +def fun_l19_n922(x) + if (x < 1) + fun_l20_n479(x) + else + fun_l20_n799(x) + end +end + +def fun_l19_n923(x) + if (x < 1) + fun_l20_n879(x) + else + fun_l20_n809(x) + end +end + +def fun_l19_n924(x) + if (x < 1) + fun_l20_n574(x) + else + fun_l20_n756(x) + end +end + +def fun_l19_n925(x) + if (x < 1) + fun_l20_n774(x) + else + fun_l20_n806(x) + end +end + +def fun_l19_n926(x) + if (x < 1) + fun_l20_n804(x) + else + fun_l20_n87(x) + end +end + +def fun_l19_n927(x) + if (x < 1) + fun_l20_n647(x) + else + fun_l20_n497(x) + end +end + +def fun_l19_n928(x) + if (x < 1) + fun_l20_n134(x) + else + fun_l20_n690(x) + end +end + +def fun_l19_n929(x) + if (x < 1) + fun_l20_n981(x) + else + fun_l20_n590(x) + end +end + +def fun_l19_n930(x) + if (x < 1) + fun_l20_n393(x) + else + fun_l20_n585(x) + end +end + +def fun_l19_n931(x) + if (x < 1) + fun_l20_n408(x) + else + fun_l20_n753(x) + end +end + +def fun_l19_n932(x) + if (x < 1) + fun_l20_n133(x) + else + fun_l20_n289(x) + end +end + +def fun_l19_n933(x) + if (x < 1) + fun_l20_n552(x) + else + fun_l20_n867(x) + end +end + +def fun_l19_n934(x) + if (x < 1) + fun_l20_n232(x) + else + fun_l20_n134(x) + end +end + +def fun_l19_n935(x) + if (x < 1) + fun_l20_n45(x) + else + fun_l20_n100(x) + end +end + +def fun_l19_n936(x) + if (x < 1) + fun_l20_n263(x) + else + fun_l20_n686(x) + end +end + +def fun_l19_n937(x) + if (x < 1) + fun_l20_n63(x) + else + fun_l20_n401(x) + end +end + +def fun_l19_n938(x) + if (x < 1) + fun_l20_n564(x) + else + fun_l20_n265(x) + end +end + +def fun_l19_n939(x) + if (x < 1) + fun_l20_n414(x) + else + fun_l20_n32(x) + end +end + +def fun_l19_n940(x) + if (x < 1) + fun_l20_n686(x) + else + fun_l20_n116(x) + end +end + +def fun_l19_n941(x) + if (x < 1) + fun_l20_n812(x) + else + fun_l20_n438(x) + end +end + +def fun_l19_n942(x) + if (x < 1) + fun_l20_n365(x) + else + fun_l20_n95(x) + end +end + +def fun_l19_n943(x) + if (x < 1) + fun_l20_n159(x) + else + fun_l20_n763(x) + end +end + +def fun_l19_n944(x) + if (x < 1) + fun_l20_n844(x) + else + fun_l20_n958(x) + end +end + +def fun_l19_n945(x) + if (x < 1) + fun_l20_n730(x) + else + fun_l20_n814(x) + end +end + +def fun_l19_n946(x) + if (x < 1) + fun_l20_n963(x) + else + fun_l20_n2(x) + end +end + +def fun_l19_n947(x) + if (x < 1) + fun_l20_n285(x) + else + fun_l20_n605(x) + end +end + +def fun_l19_n948(x) + if (x < 1) + fun_l20_n869(x) + else + fun_l20_n409(x) + end +end + +def fun_l19_n949(x) + if (x < 1) + fun_l20_n313(x) + else + fun_l20_n854(x) + end +end + +def fun_l19_n950(x) + if (x < 1) + fun_l20_n802(x) + else + fun_l20_n411(x) + end +end + +def fun_l19_n951(x) + if (x < 1) + fun_l20_n273(x) + else + fun_l20_n100(x) + end +end + +def fun_l19_n952(x) + if (x < 1) + fun_l20_n283(x) + else + fun_l20_n253(x) + end +end + +def fun_l19_n953(x) + if (x < 1) + fun_l20_n137(x) + else + fun_l20_n535(x) + end +end + +def fun_l19_n954(x) + if (x < 1) + fun_l20_n504(x) + else + fun_l20_n849(x) + end +end + +def fun_l19_n955(x) + if (x < 1) + fun_l20_n568(x) + else + fun_l20_n208(x) + end +end + +def fun_l19_n956(x) + if (x < 1) + fun_l20_n775(x) + else + fun_l20_n781(x) + end +end + +def fun_l19_n957(x) + if (x < 1) + fun_l20_n144(x) + else + fun_l20_n411(x) + end +end + +def fun_l19_n958(x) + if (x < 1) + fun_l20_n791(x) + else + fun_l20_n720(x) + end +end + +def fun_l19_n959(x) + if (x < 1) + fun_l20_n268(x) + else + fun_l20_n251(x) + end +end + +def fun_l19_n960(x) + if (x < 1) + fun_l20_n661(x) + else + fun_l20_n114(x) + end +end + +def fun_l19_n961(x) + if (x < 1) + fun_l20_n559(x) + else + fun_l20_n177(x) + end +end + +def fun_l19_n962(x) + if (x < 1) + fun_l20_n536(x) + else + fun_l20_n671(x) + end +end + +def fun_l19_n963(x) + if (x < 1) + fun_l20_n64(x) + else + fun_l20_n656(x) + end +end + +def fun_l19_n964(x) + if (x < 1) + fun_l20_n618(x) + else + fun_l20_n837(x) + end +end + +def fun_l19_n965(x) + if (x < 1) + fun_l20_n201(x) + else + fun_l20_n562(x) + end +end + +def fun_l19_n966(x) + if (x < 1) + fun_l20_n562(x) + else + fun_l20_n632(x) + end +end + +def fun_l19_n967(x) + if (x < 1) + fun_l20_n183(x) + else + fun_l20_n589(x) + end +end + +def fun_l19_n968(x) + if (x < 1) + fun_l20_n971(x) + else + fun_l20_n619(x) + end +end + +def fun_l19_n969(x) + if (x < 1) + fun_l20_n826(x) + else + fun_l20_n745(x) + end +end + +def fun_l19_n970(x) + if (x < 1) + fun_l20_n140(x) + else + fun_l20_n370(x) + end +end + +def fun_l19_n971(x) + if (x < 1) + fun_l20_n26(x) + else + fun_l20_n243(x) + end +end + +def fun_l19_n972(x) + if (x < 1) + fun_l20_n375(x) + else + fun_l20_n6(x) + end +end + +def fun_l19_n973(x) + if (x < 1) + fun_l20_n289(x) + else + fun_l20_n266(x) + end +end + +def fun_l19_n974(x) + if (x < 1) + fun_l20_n932(x) + else + fun_l20_n602(x) + end +end + +def fun_l19_n975(x) + if (x < 1) + fun_l20_n272(x) + else + fun_l20_n671(x) + end +end + +def fun_l19_n976(x) + if (x < 1) + fun_l20_n653(x) + else + fun_l20_n201(x) + end +end + +def fun_l19_n977(x) + if (x < 1) + fun_l20_n785(x) + else + fun_l20_n976(x) + end +end + +def fun_l19_n978(x) + if (x < 1) + fun_l20_n212(x) + else + fun_l20_n601(x) + end +end + +def fun_l19_n979(x) + if (x < 1) + fun_l20_n218(x) + else + fun_l20_n914(x) + end +end + +def fun_l19_n980(x) + if (x < 1) + fun_l20_n109(x) + else + fun_l20_n147(x) + end +end + +def fun_l19_n981(x) + if (x < 1) + fun_l20_n46(x) + else + fun_l20_n276(x) + end +end + +def fun_l19_n982(x) + if (x < 1) + fun_l20_n727(x) + else + fun_l20_n545(x) + end +end + +def fun_l19_n983(x) + if (x < 1) + fun_l20_n679(x) + else + fun_l20_n731(x) + end +end + +def fun_l19_n984(x) + if (x < 1) + fun_l20_n291(x) + else + fun_l20_n294(x) + end +end + +def fun_l19_n985(x) + if (x < 1) + fun_l20_n741(x) + else + fun_l20_n508(x) + end +end + +def fun_l19_n986(x) + if (x < 1) + fun_l20_n417(x) + else + fun_l20_n169(x) + end +end + +def fun_l19_n987(x) + if (x < 1) + fun_l20_n685(x) + else + fun_l20_n871(x) + end +end + +def fun_l19_n988(x) + if (x < 1) + fun_l20_n386(x) + else + fun_l20_n616(x) + end +end + +def fun_l19_n989(x) + if (x < 1) + fun_l20_n317(x) + else + fun_l20_n954(x) + end +end + +def fun_l19_n990(x) + if (x < 1) + fun_l20_n954(x) + else + fun_l20_n974(x) + end +end + +def fun_l19_n991(x) + if (x < 1) + fun_l20_n251(x) + else + fun_l20_n56(x) + end +end + +def fun_l19_n992(x) + if (x < 1) + fun_l20_n775(x) + else + fun_l20_n175(x) + end +end + +def fun_l19_n993(x) + if (x < 1) + fun_l20_n578(x) + else + fun_l20_n217(x) + end +end + +def fun_l19_n994(x) + if (x < 1) + fun_l20_n483(x) + else + fun_l20_n279(x) + end +end + +def fun_l19_n995(x) + if (x < 1) + fun_l20_n316(x) + else + fun_l20_n343(x) + end +end + +def fun_l19_n996(x) + if (x < 1) + fun_l20_n618(x) + else + fun_l20_n995(x) + end +end + +def fun_l19_n997(x) + if (x < 1) + fun_l20_n396(x) + else + fun_l20_n540(x) + end +end + +def fun_l19_n998(x) + if (x < 1) + fun_l20_n184(x) + else + fun_l20_n380(x) + end +end + +def fun_l19_n999(x) + if (x < 1) + fun_l20_n360(x) + else + fun_l20_n48(x) + end +end + +def fun_l20_n0(x) + if (x < 1) + fun_l21_n609(x) + else + fun_l21_n305(x) + end +end + +def fun_l20_n1(x) + if (x < 1) + fun_l21_n937(x) + else + fun_l21_n174(x) + end +end + +def fun_l20_n2(x) + if (x < 1) + fun_l21_n939(x) + else + fun_l21_n174(x) + end +end + +def fun_l20_n3(x) + if (x < 1) + fun_l21_n163(x) + else + fun_l21_n572(x) + end +end + +def fun_l20_n4(x) + if (x < 1) + fun_l21_n43(x) + else + fun_l21_n384(x) + end +end + +def fun_l20_n5(x) + if (x < 1) + fun_l21_n565(x) + else + fun_l21_n788(x) + end +end + +def fun_l20_n6(x) + if (x < 1) + fun_l21_n539(x) + else + fun_l21_n806(x) + end +end + +def fun_l20_n7(x) + if (x < 1) + fun_l21_n395(x) + else + fun_l21_n9(x) + end +end + +def fun_l20_n8(x) + if (x < 1) + fun_l21_n231(x) + else + fun_l21_n788(x) + end +end + +def fun_l20_n9(x) + if (x < 1) + fun_l21_n511(x) + else + fun_l21_n236(x) + end +end + +def fun_l20_n10(x) + if (x < 1) + fun_l21_n141(x) + else + fun_l21_n34(x) + end +end + +def fun_l20_n11(x) + if (x < 1) + fun_l21_n801(x) + else + fun_l21_n760(x) + end +end + +def fun_l20_n12(x) + if (x < 1) + fun_l21_n627(x) + else + fun_l21_n289(x) + end +end + +def fun_l20_n13(x) + if (x < 1) + fun_l21_n795(x) + else + fun_l21_n183(x) + end +end + +def fun_l20_n14(x) + if (x < 1) + fun_l21_n384(x) + else + fun_l21_n3(x) + end +end + +def fun_l20_n15(x) + if (x < 1) + fun_l21_n823(x) + else + fun_l21_n312(x) + end +end + +def fun_l20_n16(x) + if (x < 1) + fun_l21_n727(x) + else + fun_l21_n897(x) + end +end + +def fun_l20_n17(x) + if (x < 1) + fun_l21_n710(x) + else + fun_l21_n532(x) + end +end + +def fun_l20_n18(x) + if (x < 1) + fun_l21_n373(x) + else + fun_l21_n807(x) + end +end + +def fun_l20_n19(x) + if (x < 1) + fun_l21_n164(x) + else + fun_l21_n472(x) + end +end + +def fun_l20_n20(x) + if (x < 1) + fun_l21_n522(x) + else + fun_l21_n264(x) + end +end + +def fun_l20_n21(x) + if (x < 1) + fun_l21_n122(x) + else + fun_l21_n897(x) + end +end + +def fun_l20_n22(x) + if (x < 1) + fun_l21_n292(x) + else + fun_l21_n873(x) + end +end + +def fun_l20_n23(x) + if (x < 1) + fun_l21_n461(x) + else + fun_l21_n681(x) + end +end + +def fun_l20_n24(x) + if (x < 1) + fun_l21_n80(x) + else + fun_l21_n484(x) + end +end + +def fun_l20_n25(x) + if (x < 1) + fun_l21_n7(x) + else + fun_l21_n444(x) + end +end + +def fun_l20_n26(x) + if (x < 1) + fun_l21_n269(x) + else + fun_l21_n58(x) + end +end + +def fun_l20_n27(x) + if (x < 1) + fun_l21_n318(x) + else + fun_l21_n224(x) + end +end + +def fun_l20_n28(x) + if (x < 1) + fun_l21_n437(x) + else + fun_l21_n621(x) + end +end + +def fun_l20_n29(x) + if (x < 1) + fun_l21_n907(x) + else + fun_l21_n32(x) + end +end + +def fun_l20_n30(x) + if (x < 1) + fun_l21_n525(x) + else + fun_l21_n10(x) + end +end + +def fun_l20_n31(x) + if (x < 1) + fun_l21_n278(x) + else + fun_l21_n243(x) + end +end + +def fun_l20_n32(x) + if (x < 1) + fun_l21_n865(x) + else + fun_l21_n236(x) + end +end + +def fun_l20_n33(x) + if (x < 1) + fun_l21_n732(x) + else + fun_l21_n472(x) + end +end + +def fun_l20_n34(x) + if (x < 1) + fun_l21_n331(x) + else + fun_l21_n162(x) + end +end + +def fun_l20_n35(x) + if (x < 1) + fun_l21_n217(x) + else + fun_l21_n877(x) + end +end + +def fun_l20_n36(x) + if (x < 1) + fun_l21_n125(x) + else + fun_l21_n683(x) + end +end + +def fun_l20_n37(x) + if (x < 1) + fun_l21_n236(x) + else + fun_l21_n79(x) + end +end + +def fun_l20_n38(x) + if (x < 1) + fun_l21_n308(x) + else + fun_l21_n995(x) + end +end + +def fun_l20_n39(x) + if (x < 1) + fun_l21_n923(x) + else + fun_l21_n956(x) + end +end + +def fun_l20_n40(x) + if (x < 1) + fun_l21_n505(x) + else + fun_l21_n47(x) + end +end + +def fun_l20_n41(x) + if (x < 1) + fun_l21_n24(x) + else + fun_l21_n894(x) + end +end + +def fun_l20_n42(x) + if (x < 1) + fun_l21_n824(x) + else + fun_l21_n106(x) + end +end + +def fun_l20_n43(x) + if (x < 1) + fun_l21_n898(x) + else + fun_l21_n576(x) + end +end + +def fun_l20_n44(x) + if (x < 1) + fun_l21_n231(x) + else + fun_l21_n689(x) + end +end + +def fun_l20_n45(x) + if (x < 1) + fun_l21_n340(x) + else + fun_l21_n887(x) + end +end + +def fun_l20_n46(x) + if (x < 1) + fun_l21_n157(x) + else + fun_l21_n551(x) + end +end + +def fun_l20_n47(x) + if (x < 1) + fun_l21_n904(x) + else + fun_l21_n975(x) + end +end + +def fun_l20_n48(x) + if (x < 1) + fun_l21_n392(x) + else + fun_l21_n882(x) + end +end + +def fun_l20_n49(x) + if (x < 1) + fun_l21_n484(x) + else + fun_l21_n810(x) + end +end + +def fun_l20_n50(x) + if (x < 1) + fun_l21_n517(x) + else + fun_l21_n434(x) + end +end + +def fun_l20_n51(x) + if (x < 1) + fun_l21_n115(x) + else + fun_l21_n975(x) + end +end + +def fun_l20_n52(x) + if (x < 1) + fun_l21_n633(x) + else + fun_l21_n799(x) + end +end + +def fun_l20_n53(x) + if (x < 1) + fun_l21_n938(x) + else + fun_l21_n321(x) + end +end + +def fun_l20_n54(x) + if (x < 1) + fun_l21_n98(x) + else + fun_l21_n343(x) + end +end + +def fun_l20_n55(x) + if (x < 1) + fun_l21_n851(x) + else + fun_l21_n794(x) + end +end + +def fun_l20_n56(x) + if (x < 1) + fun_l21_n119(x) + else + fun_l21_n649(x) + end +end + +def fun_l20_n57(x) + if (x < 1) + fun_l21_n799(x) + else + fun_l21_n397(x) + end +end + +def fun_l20_n58(x) + if (x < 1) + fun_l21_n429(x) + else + fun_l21_n781(x) + end +end + +def fun_l20_n59(x) + if (x < 1) + fun_l21_n862(x) + else + fun_l21_n870(x) + end +end + +def fun_l20_n60(x) + if (x < 1) + fun_l21_n864(x) + else + fun_l21_n333(x) + end +end + +def fun_l20_n61(x) + if (x < 1) + fun_l21_n673(x) + else + fun_l21_n481(x) + end +end + +def fun_l20_n62(x) + if (x < 1) + fun_l21_n193(x) + else + fun_l21_n524(x) + end +end + +def fun_l20_n63(x) + if (x < 1) + fun_l21_n976(x) + else + fun_l21_n0(x) + end +end + +def fun_l20_n64(x) + if (x < 1) + fun_l21_n804(x) + else + fun_l21_n833(x) + end +end + +def fun_l20_n65(x) + if (x < 1) + fun_l21_n20(x) + else + fun_l21_n285(x) + end +end + +def fun_l20_n66(x) + if (x < 1) + fun_l21_n70(x) + else + fun_l21_n932(x) + end +end + +def fun_l20_n67(x) + if (x < 1) + fun_l21_n213(x) + else + fun_l21_n196(x) + end +end + +def fun_l20_n68(x) + if (x < 1) + fun_l21_n806(x) + else + fun_l21_n322(x) + end +end + +def fun_l20_n69(x) + if (x < 1) + fun_l21_n583(x) + else + fun_l21_n62(x) + end +end + +def fun_l20_n70(x) + if (x < 1) + fun_l21_n141(x) + else + fun_l21_n490(x) + end +end + +def fun_l20_n71(x) + if (x < 1) + fun_l21_n995(x) + else + fun_l21_n398(x) + end +end + +def fun_l20_n72(x) + if (x < 1) + fun_l21_n436(x) + else + fun_l21_n490(x) + end +end + +def fun_l20_n73(x) + if (x < 1) + fun_l21_n585(x) + else + fun_l21_n275(x) + end +end + +def fun_l20_n74(x) + if (x < 1) + fun_l21_n120(x) + else + fun_l21_n968(x) + end +end + +def fun_l20_n75(x) + if (x < 1) + fun_l21_n562(x) + else + fun_l21_n896(x) + end +end + +def fun_l20_n76(x) + if (x < 1) + fun_l21_n794(x) + else + fun_l21_n224(x) + end +end + +def fun_l20_n77(x) + if (x < 1) + fun_l21_n71(x) + else + fun_l21_n870(x) + end +end + +def fun_l20_n78(x) + if (x < 1) + fun_l21_n0(x) + else + fun_l21_n41(x) + end +end + +def fun_l20_n79(x) + if (x < 1) + fun_l21_n325(x) + else + fun_l21_n814(x) + end +end + +def fun_l20_n80(x) + if (x < 1) + fun_l21_n963(x) + else + fun_l21_n792(x) + end +end + +def fun_l20_n81(x) + if (x < 1) + fun_l21_n415(x) + else + fun_l21_n200(x) + end +end + +def fun_l20_n82(x) + if (x < 1) + fun_l21_n438(x) + else + fun_l21_n506(x) + end +end + +def fun_l20_n83(x) + if (x < 1) + fun_l21_n283(x) + else + fun_l21_n708(x) + end +end + +def fun_l20_n84(x) + if (x < 1) + fun_l21_n968(x) + else + fun_l21_n80(x) + end +end + +def fun_l20_n85(x) + if (x < 1) + fun_l21_n839(x) + else + fun_l21_n808(x) + end +end + +def fun_l20_n86(x) + if (x < 1) + fun_l21_n653(x) + else + fun_l21_n343(x) + end +end + +def fun_l20_n87(x) + if (x < 1) + fun_l21_n580(x) + else + fun_l21_n652(x) + end +end + +def fun_l20_n88(x) + if (x < 1) + fun_l21_n64(x) + else + fun_l21_n899(x) + end +end + +def fun_l20_n89(x) + if (x < 1) + fun_l21_n325(x) + else + fun_l21_n645(x) + end +end + +def fun_l20_n90(x) + if (x < 1) + fun_l21_n251(x) + else + fun_l21_n210(x) + end +end + +def fun_l20_n91(x) + if (x < 1) + fun_l21_n943(x) + else + fun_l21_n451(x) + end +end + +def fun_l20_n92(x) + if (x < 1) + fun_l21_n95(x) + else + fun_l21_n937(x) + end +end + +def fun_l20_n93(x) + if (x < 1) + fun_l21_n263(x) + else + fun_l21_n107(x) + end +end + +def fun_l20_n94(x) + if (x < 1) + fun_l21_n438(x) + else + fun_l21_n213(x) + end +end + +def fun_l20_n95(x) + if (x < 1) + fun_l21_n283(x) + else + fun_l21_n203(x) + end +end + +def fun_l20_n96(x) + if (x < 1) + fun_l21_n809(x) + else + fun_l21_n154(x) + end +end + +def fun_l20_n97(x) + if (x < 1) + fun_l21_n513(x) + else + fun_l21_n15(x) + end +end + +def fun_l20_n98(x) + if (x < 1) + fun_l21_n854(x) + else + fun_l21_n679(x) + end +end + +def fun_l20_n99(x) + if (x < 1) + fun_l21_n102(x) + else + fun_l21_n546(x) + end +end + +def fun_l20_n100(x) + if (x < 1) + fun_l21_n790(x) + else + fun_l21_n143(x) + end +end + +def fun_l20_n101(x) + if (x < 1) + fun_l21_n835(x) + else + fun_l21_n78(x) + end +end + +def fun_l20_n102(x) + if (x < 1) + fun_l21_n96(x) + else + fun_l21_n995(x) + end +end + +def fun_l20_n103(x) + if (x < 1) + fun_l21_n445(x) + else + fun_l21_n332(x) + end +end + +def fun_l20_n104(x) + if (x < 1) + fun_l21_n532(x) + else + fun_l21_n509(x) + end +end + +def fun_l20_n105(x) + if (x < 1) + fun_l21_n592(x) + else + fun_l21_n237(x) + end +end + +def fun_l20_n106(x) + if (x < 1) + fun_l21_n837(x) + else + fun_l21_n13(x) + end +end + +def fun_l20_n107(x) + if (x < 1) + fun_l21_n518(x) + else + fun_l21_n463(x) + end +end + +def fun_l20_n108(x) + if (x < 1) + fun_l21_n373(x) + else + fun_l21_n597(x) + end +end + +def fun_l20_n109(x) + if (x < 1) + fun_l21_n832(x) + else + fun_l21_n784(x) + end +end + +def fun_l20_n110(x) + if (x < 1) + fun_l21_n408(x) + else + fun_l21_n738(x) + end +end + +def fun_l20_n111(x) + if (x < 1) + fun_l21_n243(x) + else + fun_l21_n96(x) + end +end + +def fun_l20_n112(x) + if (x < 1) + fun_l21_n251(x) + else + fun_l21_n151(x) + end +end + +def fun_l20_n113(x) + if (x < 1) + fun_l21_n970(x) + else + fun_l21_n329(x) + end +end + +def fun_l20_n114(x) + if (x < 1) + fun_l21_n691(x) + else + fun_l21_n309(x) + end +end + +def fun_l20_n115(x) + if (x < 1) + fun_l21_n250(x) + else + fun_l21_n927(x) + end +end + +def fun_l20_n116(x) + if (x < 1) + fun_l21_n819(x) + else + fun_l21_n49(x) + end +end + +def fun_l20_n117(x) + if (x < 1) + fun_l21_n761(x) + else + fun_l21_n91(x) + end +end + +def fun_l20_n118(x) + if (x < 1) + fun_l21_n170(x) + else + fun_l21_n317(x) + end +end + +def fun_l20_n119(x) + if (x < 1) + fun_l21_n199(x) + else + fun_l21_n406(x) + end +end + +def fun_l20_n120(x) + if (x < 1) + fun_l21_n983(x) + else + fun_l21_n742(x) + end +end + +def fun_l20_n121(x) + if (x < 1) + fun_l21_n428(x) + else + fun_l21_n887(x) + end +end + +def fun_l20_n122(x) + if (x < 1) + fun_l21_n369(x) + else + fun_l21_n64(x) + end +end + +def fun_l20_n123(x) + if (x < 1) + fun_l21_n727(x) + else + fun_l21_n484(x) + end +end + +def fun_l20_n124(x) + if (x < 1) + fun_l21_n310(x) + else + fun_l21_n198(x) + end +end + +def fun_l20_n125(x) + if (x < 1) + fun_l21_n747(x) + else + fun_l21_n935(x) + end +end + +def fun_l20_n126(x) + if (x < 1) + fun_l21_n389(x) + else + fun_l21_n966(x) + end +end + +def fun_l20_n127(x) + if (x < 1) + fun_l21_n852(x) + else + fun_l21_n128(x) + end +end + +def fun_l20_n128(x) + if (x < 1) + fun_l21_n10(x) + else + fun_l21_n376(x) + end +end + +def fun_l20_n129(x) + if (x < 1) + fun_l21_n413(x) + else + fun_l21_n465(x) + end +end + +def fun_l20_n130(x) + if (x < 1) + fun_l21_n536(x) + else + fun_l21_n689(x) + end +end + +def fun_l20_n131(x) + if (x < 1) + fun_l21_n707(x) + else + fun_l21_n793(x) + end +end + +def fun_l20_n132(x) + if (x < 1) + fun_l21_n328(x) + else + fun_l21_n56(x) + end +end + +def fun_l20_n133(x) + if (x < 1) + fun_l21_n318(x) + else + fun_l21_n570(x) + end +end + +def fun_l20_n134(x) + if (x < 1) + fun_l21_n656(x) + else + fun_l21_n187(x) + end +end + +def fun_l20_n135(x) + if (x < 1) + fun_l21_n259(x) + else + fun_l21_n718(x) + end +end + +def fun_l20_n136(x) + if (x < 1) + fun_l21_n284(x) + else + fun_l21_n167(x) + end +end + +def fun_l20_n137(x) + if (x < 1) + fun_l21_n788(x) + else + fun_l21_n595(x) + end +end + +def fun_l20_n138(x) + if (x < 1) + fun_l21_n431(x) + else + fun_l21_n620(x) + end +end + +def fun_l20_n139(x) + if (x < 1) + fun_l21_n365(x) + else + fun_l21_n995(x) + end +end + +def fun_l20_n140(x) + if (x < 1) + fun_l21_n614(x) + else + fun_l21_n79(x) + end +end + +def fun_l20_n141(x) + if (x < 1) + fun_l21_n138(x) + else + fun_l21_n655(x) + end +end + +def fun_l20_n142(x) + if (x < 1) + fun_l21_n155(x) + else + fun_l21_n34(x) + end +end + +def fun_l20_n143(x) + if (x < 1) + fun_l21_n829(x) + else + fun_l21_n703(x) + end +end + +def fun_l20_n144(x) + if (x < 1) + fun_l21_n290(x) + else + fun_l21_n279(x) + end +end + +def fun_l20_n145(x) + if (x < 1) + fun_l21_n825(x) + else + fun_l21_n720(x) + end +end + +def fun_l20_n146(x) + if (x < 1) + fun_l21_n678(x) + else + fun_l21_n347(x) + end +end + +def fun_l20_n147(x) + if (x < 1) + fun_l21_n967(x) + else + fun_l21_n133(x) + end +end + +def fun_l20_n148(x) + if (x < 1) + fun_l21_n935(x) + else + fun_l21_n438(x) + end +end + +def fun_l20_n149(x) + if (x < 1) + fun_l21_n14(x) + else + fun_l21_n233(x) + end +end + +def fun_l20_n150(x) + if (x < 1) + fun_l21_n42(x) + else + fun_l21_n507(x) + end +end + +def fun_l20_n151(x) + if (x < 1) + fun_l21_n33(x) + else + fun_l21_n404(x) + end +end + +def fun_l20_n152(x) + if (x < 1) + fun_l21_n897(x) + else + fun_l21_n972(x) + end +end + +def fun_l20_n153(x) + if (x < 1) + fun_l21_n221(x) + else + fun_l21_n718(x) + end +end + +def fun_l20_n154(x) + if (x < 1) + fun_l21_n737(x) + else + fun_l21_n257(x) + end +end + +def fun_l20_n155(x) + if (x < 1) + fun_l21_n465(x) + else + fun_l21_n917(x) + end +end + +def fun_l20_n156(x) + if (x < 1) + fun_l21_n338(x) + else + fun_l21_n673(x) + end +end + +def fun_l20_n157(x) + if (x < 1) + fun_l21_n429(x) + else + fun_l21_n23(x) + end +end + +def fun_l20_n158(x) + if (x < 1) + fun_l21_n826(x) + else + fun_l21_n115(x) + end +end + +def fun_l20_n159(x) + if (x < 1) + fun_l21_n713(x) + else + fun_l21_n954(x) + end +end + +def fun_l20_n160(x) + if (x < 1) + fun_l21_n897(x) + else + fun_l21_n46(x) + end +end + +def fun_l20_n161(x) + if (x < 1) + fun_l21_n751(x) + else + fun_l21_n885(x) + end +end + +def fun_l20_n162(x) + if (x < 1) + fun_l21_n935(x) + else + fun_l21_n230(x) + end +end + +def fun_l20_n163(x) + if (x < 1) + fun_l21_n862(x) + else + fun_l21_n874(x) + end +end + +def fun_l20_n164(x) + if (x < 1) + fun_l21_n695(x) + else + fun_l21_n707(x) + end +end + +def fun_l20_n165(x) + if (x < 1) + fun_l21_n539(x) + else + fun_l21_n14(x) + end +end + +def fun_l20_n166(x) + if (x < 1) + fun_l21_n139(x) + else + fun_l21_n766(x) + end +end + +def fun_l20_n167(x) + if (x < 1) + fun_l21_n100(x) + else + fun_l21_n229(x) + end +end + +def fun_l20_n168(x) + if (x < 1) + fun_l21_n88(x) + else + fun_l21_n642(x) + end +end + +def fun_l20_n169(x) + if (x < 1) + fun_l21_n57(x) + else + fun_l21_n252(x) + end +end + +def fun_l20_n170(x) + if (x < 1) + fun_l21_n470(x) + else + fun_l21_n224(x) + end +end + +def fun_l20_n171(x) + if (x < 1) + fun_l21_n163(x) + else + fun_l21_n114(x) + end +end + +def fun_l20_n172(x) + if (x < 1) + fun_l21_n231(x) + else + fun_l21_n405(x) + end +end + +def fun_l20_n173(x) + if (x < 1) + fun_l21_n553(x) + else + fun_l21_n758(x) + end +end + +def fun_l20_n174(x) + if (x < 1) + fun_l21_n874(x) + else + fun_l21_n43(x) + end +end + +def fun_l20_n175(x) + if (x < 1) + fun_l21_n911(x) + else + fun_l21_n644(x) + end +end + +def fun_l20_n176(x) + if (x < 1) + fun_l21_n747(x) + else + fun_l21_n900(x) + end +end + +def fun_l20_n177(x) + if (x < 1) + fun_l21_n956(x) + else + fun_l21_n152(x) + end +end + +def fun_l20_n178(x) + if (x < 1) + fun_l21_n226(x) + else + fun_l21_n654(x) + end +end + +def fun_l20_n179(x) + if (x < 1) + fun_l21_n284(x) + else + fun_l21_n968(x) + end +end + +def fun_l20_n180(x) + if (x < 1) + fun_l21_n181(x) + else + fun_l21_n690(x) + end +end + +def fun_l20_n181(x) + if (x < 1) + fun_l21_n35(x) + else + fun_l21_n500(x) + end +end + +def fun_l20_n182(x) + if (x < 1) + fun_l21_n212(x) + else + fun_l21_n559(x) + end +end + +def fun_l20_n183(x) + if (x < 1) + fun_l21_n981(x) + else + fun_l21_n605(x) + end +end + +def fun_l20_n184(x) + if (x < 1) + fun_l21_n447(x) + else + fun_l21_n718(x) + end +end + +def fun_l20_n185(x) + if (x < 1) + fun_l21_n272(x) + else + fun_l21_n341(x) + end +end + +def fun_l20_n186(x) + if (x < 1) + fun_l21_n5(x) + else + fun_l21_n426(x) + end +end + +def fun_l20_n187(x) + if (x < 1) + fun_l21_n630(x) + else + fun_l21_n62(x) + end +end + +def fun_l20_n188(x) + if (x < 1) + fun_l21_n600(x) + else + fun_l21_n674(x) + end +end + +def fun_l20_n189(x) + if (x < 1) + fun_l21_n645(x) + else + fun_l21_n936(x) + end +end + +def fun_l20_n190(x) + if (x < 1) + fun_l21_n15(x) + else + fun_l21_n158(x) + end +end + +def fun_l20_n191(x) + if (x < 1) + fun_l21_n789(x) + else + fun_l21_n103(x) + end +end + +def fun_l20_n192(x) + if (x < 1) + fun_l21_n501(x) + else + fun_l21_n655(x) + end +end + +def fun_l20_n193(x) + if (x < 1) + fun_l21_n242(x) + else + fun_l21_n241(x) + end +end + +def fun_l20_n194(x) + if (x < 1) + fun_l21_n296(x) + else + fun_l21_n442(x) + end +end + +def fun_l20_n195(x) + if (x < 1) + fun_l21_n288(x) + else + fun_l21_n165(x) + end +end + +def fun_l20_n196(x) + if (x < 1) + fun_l21_n336(x) + else + fun_l21_n328(x) + end +end + +def fun_l20_n197(x) + if (x < 1) + fun_l21_n423(x) + else + fun_l21_n906(x) + end +end + +def fun_l20_n198(x) + if (x < 1) + fun_l21_n875(x) + else + fun_l21_n801(x) + end +end + +def fun_l20_n199(x) + if (x < 1) + fun_l21_n864(x) + else + fun_l21_n594(x) + end +end + +def fun_l20_n200(x) + if (x < 1) + fun_l21_n145(x) + else + fun_l21_n728(x) + end +end + +def fun_l20_n201(x) + if (x < 1) + fun_l21_n941(x) + else + fun_l21_n592(x) + end +end + +def fun_l20_n202(x) + if (x < 1) + fun_l21_n458(x) + else + fun_l21_n839(x) + end +end + +def fun_l20_n203(x) + if (x < 1) + fun_l21_n352(x) + else + fun_l21_n319(x) + end +end + +def fun_l20_n204(x) + if (x < 1) + fun_l21_n453(x) + else + fun_l21_n944(x) + end +end + +def fun_l20_n205(x) + if (x < 1) + fun_l21_n479(x) + else + fun_l21_n409(x) + end +end + +def fun_l20_n206(x) + if (x < 1) + fun_l21_n72(x) + else + fun_l21_n177(x) + end +end + +def fun_l20_n207(x) + if (x < 1) + fun_l21_n895(x) + else + fun_l21_n77(x) + end +end + +def fun_l20_n208(x) + if (x < 1) + fun_l21_n308(x) + else + fun_l21_n181(x) + end +end + +def fun_l20_n209(x) + if (x < 1) + fun_l21_n358(x) + else + fun_l21_n666(x) + end +end + +def fun_l20_n210(x) + if (x < 1) + fun_l21_n275(x) + else + fun_l21_n739(x) + end +end + +def fun_l20_n211(x) + if (x < 1) + fun_l21_n706(x) + else + fun_l21_n722(x) + end +end + +def fun_l20_n212(x) + if (x < 1) + fun_l21_n185(x) + else + fun_l21_n893(x) + end +end + +def fun_l20_n213(x) + if (x < 1) + fun_l21_n307(x) + else + fun_l21_n871(x) + end +end + +def fun_l20_n214(x) + if (x < 1) + fun_l21_n365(x) + else + fun_l21_n311(x) + end +end + +def fun_l20_n215(x) + if (x < 1) + fun_l21_n176(x) + else + fun_l21_n998(x) + end +end + +def fun_l20_n216(x) + if (x < 1) + fun_l21_n542(x) + else + fun_l21_n248(x) + end +end + +def fun_l20_n217(x) + if (x < 1) + fun_l21_n568(x) + else + fun_l21_n671(x) + end +end + +def fun_l20_n218(x) + if (x < 1) + fun_l21_n704(x) + else + fun_l21_n992(x) + end +end + +def fun_l20_n219(x) + if (x < 1) + fun_l21_n500(x) + else + fun_l21_n845(x) + end +end + +def fun_l20_n220(x) + if (x < 1) + fun_l21_n75(x) + else + fun_l21_n365(x) + end +end + +def fun_l20_n221(x) + if (x < 1) + fun_l21_n780(x) + else + fun_l21_n574(x) + end +end + +def fun_l20_n222(x) + if (x < 1) + fun_l21_n778(x) + else + fun_l21_n315(x) + end +end + +def fun_l20_n223(x) + if (x < 1) + fun_l21_n845(x) + else + fun_l21_n521(x) + end +end + +def fun_l20_n224(x) + if (x < 1) + fun_l21_n608(x) + else + fun_l21_n762(x) + end +end + +def fun_l20_n225(x) + if (x < 1) + fun_l21_n912(x) + else + fun_l21_n651(x) + end +end + +def fun_l20_n226(x) + if (x < 1) + fun_l21_n337(x) + else + fun_l21_n723(x) + end +end + +def fun_l20_n227(x) + if (x < 1) + fun_l21_n734(x) + else + fun_l21_n967(x) + end +end + +def fun_l20_n228(x) + if (x < 1) + fun_l21_n342(x) + else + fun_l21_n611(x) + end +end + +def fun_l20_n229(x) + if (x < 1) + fun_l21_n607(x) + else + fun_l21_n317(x) + end +end + +def fun_l20_n230(x) + if (x < 1) + fun_l21_n478(x) + else + fun_l21_n208(x) + end +end + +def fun_l20_n231(x) + if (x < 1) + fun_l21_n481(x) + else + fun_l21_n171(x) + end +end + +def fun_l20_n232(x) + if (x < 1) + fun_l21_n80(x) + else + fun_l21_n810(x) + end +end + +def fun_l20_n233(x) + if (x < 1) + fun_l21_n597(x) + else + fun_l21_n474(x) + end +end + +def fun_l20_n234(x) + if (x < 1) + fun_l21_n997(x) + else + fun_l21_n98(x) + end +end + +def fun_l20_n235(x) + if (x < 1) + fun_l21_n663(x) + else + fun_l21_n103(x) + end +end + +def fun_l20_n236(x) + if (x < 1) + fun_l21_n602(x) + else + fun_l21_n421(x) + end +end + +def fun_l20_n237(x) + if (x < 1) + fun_l21_n888(x) + else + fun_l21_n759(x) + end +end + +def fun_l20_n238(x) + if (x < 1) + fun_l21_n21(x) + else + fun_l21_n56(x) + end +end + +def fun_l20_n239(x) + if (x < 1) + fun_l21_n663(x) + else + fun_l21_n102(x) + end +end + +def fun_l20_n240(x) + if (x < 1) + fun_l21_n244(x) + else + fun_l21_n507(x) + end +end + +def fun_l20_n241(x) + if (x < 1) + fun_l21_n263(x) + else + fun_l21_n382(x) + end +end + +def fun_l20_n242(x) + if (x < 1) + fun_l21_n639(x) + else + fun_l21_n380(x) + end +end + +def fun_l20_n243(x) + if (x < 1) + fun_l21_n99(x) + else + fun_l21_n35(x) + end +end + +def fun_l20_n244(x) + if (x < 1) + fun_l21_n648(x) + else + fun_l21_n266(x) + end +end + +def fun_l20_n245(x) + if (x < 1) + fun_l21_n613(x) + else + fun_l21_n277(x) + end +end + +def fun_l20_n246(x) + if (x < 1) + fun_l21_n886(x) + else + fun_l21_n4(x) + end +end + +def fun_l20_n247(x) + if (x < 1) + fun_l21_n510(x) + else + fun_l21_n146(x) + end +end + +def fun_l20_n248(x) + if (x < 1) + fun_l21_n933(x) + else + fun_l21_n765(x) + end +end + +def fun_l20_n249(x) + if (x < 1) + fun_l21_n323(x) + else + fun_l21_n222(x) + end +end + +def fun_l20_n250(x) + if (x < 1) + fun_l21_n708(x) + else + fun_l21_n241(x) + end +end + +def fun_l20_n251(x) + if (x < 1) + fun_l21_n394(x) + else + fun_l21_n899(x) + end +end + +def fun_l20_n252(x) + if (x < 1) + fun_l21_n253(x) + else + fun_l21_n221(x) + end +end + +def fun_l20_n253(x) + if (x < 1) + fun_l21_n842(x) + else + fun_l21_n594(x) + end +end + +def fun_l20_n254(x) + if (x < 1) + fun_l21_n325(x) + else + fun_l21_n145(x) + end +end + +def fun_l20_n255(x) + if (x < 1) + fun_l21_n568(x) + else + fun_l21_n736(x) + end +end + +def fun_l20_n256(x) + if (x < 1) + fun_l21_n862(x) + else + fun_l21_n388(x) + end +end + +def fun_l20_n257(x) + if (x < 1) + fun_l21_n738(x) + else + fun_l21_n255(x) + end +end + +def fun_l20_n258(x) + if (x < 1) + fun_l21_n704(x) + else + fun_l21_n539(x) + end +end + +def fun_l20_n259(x) + if (x < 1) + fun_l21_n149(x) + else + fun_l21_n940(x) + end +end + +def fun_l20_n260(x) + if (x < 1) + fun_l21_n462(x) + else + fun_l21_n840(x) + end +end + +def fun_l20_n261(x) + if (x < 1) + fun_l21_n549(x) + else + fun_l21_n968(x) + end +end + +def fun_l20_n262(x) + if (x < 1) + fun_l21_n290(x) + else + fun_l21_n127(x) + end +end + +def fun_l20_n263(x) + if (x < 1) + fun_l21_n311(x) + else + fun_l21_n652(x) + end +end + +def fun_l20_n264(x) + if (x < 1) + fun_l21_n544(x) + else + fun_l21_n521(x) + end +end + +def fun_l20_n265(x) + if (x < 1) + fun_l21_n984(x) + else + fun_l21_n957(x) + end +end + +def fun_l20_n266(x) + if (x < 1) + fun_l21_n10(x) + else + fun_l21_n154(x) + end +end + +def fun_l20_n267(x) + if (x < 1) + fun_l21_n707(x) + else + fun_l21_n623(x) + end +end + +def fun_l20_n268(x) + if (x < 1) + fun_l21_n420(x) + else + fun_l21_n31(x) + end +end + +def fun_l20_n269(x) + if (x < 1) + fun_l21_n380(x) + else + fun_l21_n397(x) + end +end + +def fun_l20_n270(x) + if (x < 1) + fun_l21_n95(x) + else + fun_l21_n881(x) + end +end + +def fun_l20_n271(x) + if (x < 1) + fun_l21_n731(x) + else + fun_l21_n521(x) + end +end + +def fun_l20_n272(x) + if (x < 1) + fun_l21_n255(x) + else + fun_l21_n412(x) + end +end + +def fun_l20_n273(x) + if (x < 1) + fun_l21_n455(x) + else + fun_l21_n225(x) + end +end + +def fun_l20_n274(x) + if (x < 1) + fun_l21_n223(x) + else + fun_l21_n71(x) + end +end + +def fun_l20_n275(x) + if (x < 1) + fun_l21_n819(x) + else + fun_l21_n765(x) + end +end + +def fun_l20_n276(x) + if (x < 1) + fun_l21_n379(x) + else + fun_l21_n892(x) + end +end + +def fun_l20_n277(x) + if (x < 1) + fun_l21_n695(x) + else + fun_l21_n856(x) + end +end + +def fun_l20_n278(x) + if (x < 1) + fun_l21_n217(x) + else + fun_l21_n166(x) + end +end + +def fun_l20_n279(x) + if (x < 1) + fun_l21_n708(x) + else + fun_l21_n987(x) + end +end + +def fun_l20_n280(x) + if (x < 1) + fun_l21_n251(x) + else + fun_l21_n144(x) + end +end + +def fun_l20_n281(x) + if (x < 1) + fun_l21_n262(x) + else + fun_l21_n428(x) + end +end + +def fun_l20_n282(x) + if (x < 1) + fun_l21_n439(x) + else + fun_l21_n1(x) + end +end + +def fun_l20_n283(x) + if (x < 1) + fun_l21_n405(x) + else + fun_l21_n413(x) + end +end + +def fun_l20_n284(x) + if (x < 1) + fun_l21_n729(x) + else + fun_l21_n61(x) + end +end + +def fun_l20_n285(x) + if (x < 1) + fun_l21_n255(x) + else + fun_l21_n985(x) + end +end + +def fun_l20_n286(x) + if (x < 1) + fun_l21_n348(x) + else + fun_l21_n54(x) + end +end + +def fun_l20_n287(x) + if (x < 1) + fun_l21_n663(x) + else + fun_l21_n837(x) + end +end + +def fun_l20_n288(x) + if (x < 1) + fun_l21_n444(x) + else + fun_l21_n767(x) + end +end + +def fun_l20_n289(x) + if (x < 1) + fun_l21_n756(x) + else + fun_l21_n246(x) + end +end + +def fun_l20_n290(x) + if (x < 1) + fun_l21_n0(x) + else + fun_l21_n253(x) + end +end + +def fun_l20_n291(x) + if (x < 1) + fun_l21_n867(x) + else + fun_l21_n464(x) + end +end + +def fun_l20_n292(x) + if (x < 1) + fun_l21_n885(x) + else + fun_l21_n588(x) + end +end + +def fun_l20_n293(x) + if (x < 1) + fun_l21_n420(x) + else + fun_l21_n622(x) + end +end + +def fun_l20_n294(x) + if (x < 1) + fun_l21_n411(x) + else + fun_l21_n351(x) + end +end + +def fun_l20_n295(x) + if (x < 1) + fun_l21_n208(x) + else + fun_l21_n0(x) + end +end + +def fun_l20_n296(x) + if (x < 1) + fun_l21_n551(x) + else + fun_l21_n68(x) + end +end + +def fun_l20_n297(x) + if (x < 1) + fun_l21_n351(x) + else + fun_l21_n108(x) + end +end + +def fun_l20_n298(x) + if (x < 1) + fun_l21_n134(x) + else + fun_l21_n893(x) + end +end + +def fun_l20_n299(x) + if (x < 1) + fun_l21_n697(x) + else + fun_l21_n538(x) + end +end + +def fun_l20_n300(x) + if (x < 1) + fun_l21_n61(x) + else + fun_l21_n641(x) + end +end + +def fun_l20_n301(x) + if (x < 1) + fun_l21_n13(x) + else + fun_l21_n103(x) + end +end + +def fun_l20_n302(x) + if (x < 1) + fun_l21_n260(x) + else + fun_l21_n430(x) + end +end + +def fun_l20_n303(x) + if (x < 1) + fun_l21_n63(x) + else + fun_l21_n911(x) + end +end + +def fun_l20_n304(x) + if (x < 1) + fun_l21_n470(x) + else + fun_l21_n407(x) + end +end + +def fun_l20_n305(x) + if (x < 1) + fun_l21_n615(x) + else + fun_l21_n767(x) + end +end + +def fun_l20_n306(x) + if (x < 1) + fun_l21_n898(x) + else + fun_l21_n215(x) + end +end + +def fun_l20_n307(x) + if (x < 1) + fun_l21_n793(x) + else + fun_l21_n468(x) + end +end + +def fun_l20_n308(x) + if (x < 1) + fun_l21_n582(x) + else + fun_l21_n968(x) + end +end + +def fun_l20_n309(x) + if (x < 1) + fun_l21_n7(x) + else + fun_l21_n703(x) + end +end + +def fun_l20_n310(x) + if (x < 1) + fun_l21_n826(x) + else + fun_l21_n735(x) + end +end + +def fun_l20_n311(x) + if (x < 1) + fun_l21_n856(x) + else + fun_l21_n959(x) + end +end + +def fun_l20_n312(x) + if (x < 1) + fun_l21_n194(x) + else + fun_l21_n158(x) + end +end + +def fun_l20_n313(x) + if (x < 1) + fun_l21_n690(x) + else + fun_l21_n813(x) + end +end + +def fun_l20_n314(x) + if (x < 1) + fun_l21_n699(x) + else + fun_l21_n842(x) + end +end + +def fun_l20_n315(x) + if (x < 1) + fun_l21_n485(x) + else + fun_l21_n0(x) + end +end + +def fun_l20_n316(x) + if (x < 1) + fun_l21_n753(x) + else + fun_l21_n306(x) + end +end + +def fun_l20_n317(x) + if (x < 1) + fun_l21_n516(x) + else + fun_l21_n35(x) + end +end + +def fun_l20_n318(x) + if (x < 1) + fun_l21_n78(x) + else + fun_l21_n104(x) + end +end + +def fun_l20_n319(x) + if (x < 1) + fun_l21_n492(x) + else + fun_l21_n211(x) + end +end + +def fun_l20_n320(x) + if (x < 1) + fun_l21_n303(x) + else + fun_l21_n218(x) + end +end + +def fun_l20_n321(x) + if (x < 1) + fun_l21_n614(x) + else + fun_l21_n743(x) + end +end + +def fun_l20_n322(x) + if (x < 1) + fun_l21_n141(x) + else + fun_l21_n320(x) + end +end + +def fun_l20_n323(x) + if (x < 1) + fun_l21_n349(x) + else + fun_l21_n396(x) + end +end + +def fun_l20_n324(x) + if (x < 1) + fun_l21_n189(x) + else + fun_l21_n32(x) + end +end + +def fun_l20_n325(x) + if (x < 1) + fun_l21_n938(x) + else + fun_l21_n747(x) + end +end + +def fun_l20_n326(x) + if (x < 1) + fun_l21_n571(x) + else + fun_l21_n20(x) + end +end + +def fun_l20_n327(x) + if (x < 1) + fun_l21_n905(x) + else + fun_l21_n106(x) + end +end + +def fun_l20_n328(x) + if (x < 1) + fun_l21_n849(x) + else + fun_l21_n747(x) + end +end + +def fun_l20_n329(x) + if (x < 1) + fun_l21_n830(x) + else + fun_l21_n61(x) + end +end + +def fun_l20_n330(x) + if (x < 1) + fun_l21_n613(x) + else + fun_l21_n945(x) + end +end + +def fun_l20_n331(x) + if (x < 1) + fun_l21_n379(x) + else + fun_l21_n920(x) + end +end + +def fun_l20_n332(x) + if (x < 1) + fun_l21_n315(x) + else + fun_l21_n968(x) + end +end + +def fun_l20_n333(x) + if (x < 1) + fun_l21_n256(x) + else + fun_l21_n460(x) + end +end + +def fun_l20_n334(x) + if (x < 1) + fun_l21_n644(x) + else + fun_l21_n372(x) + end +end + +def fun_l20_n335(x) + if (x < 1) + fun_l21_n588(x) + else + fun_l21_n351(x) + end +end + +def fun_l20_n336(x) + if (x < 1) + fun_l21_n516(x) + else + fun_l21_n975(x) + end +end + +def fun_l20_n337(x) + if (x < 1) + fun_l21_n432(x) + else + fun_l21_n47(x) + end +end + +def fun_l20_n338(x) + if (x < 1) + fun_l21_n31(x) + else + fun_l21_n728(x) + end +end + +def fun_l20_n339(x) + if (x < 1) + fun_l21_n700(x) + else + fun_l21_n454(x) + end +end + +def fun_l20_n340(x) + if (x < 1) + fun_l21_n947(x) + else + fun_l21_n880(x) + end +end + +def fun_l20_n341(x) + if (x < 1) + fun_l21_n363(x) + else + fun_l21_n861(x) + end +end + +def fun_l20_n342(x) + if (x < 1) + fun_l21_n338(x) + else + fun_l21_n118(x) + end +end + +def fun_l20_n343(x) + if (x < 1) + fun_l21_n352(x) + else + fun_l21_n402(x) + end +end + +def fun_l20_n344(x) + if (x < 1) + fun_l21_n344(x) + else + fun_l21_n407(x) + end +end + +def fun_l20_n345(x) + if (x < 1) + fun_l21_n869(x) + else + fun_l21_n912(x) + end +end + +def fun_l20_n346(x) + if (x < 1) + fun_l21_n397(x) + else + fun_l21_n429(x) + end +end + +def fun_l20_n347(x) + if (x < 1) + fun_l21_n28(x) + else + fun_l21_n671(x) + end +end + +def fun_l20_n348(x) + if (x < 1) + fun_l21_n215(x) + else + fun_l21_n821(x) + end +end + +def fun_l20_n349(x) + if (x < 1) + fun_l21_n432(x) + else + fun_l21_n250(x) + end +end + +def fun_l20_n350(x) + if (x < 1) + fun_l21_n496(x) + else + fun_l21_n988(x) + end +end + +def fun_l20_n351(x) + if (x < 1) + fun_l21_n317(x) + else + fun_l21_n516(x) + end +end + +def fun_l20_n352(x) + if (x < 1) + fun_l21_n968(x) + else + fun_l21_n638(x) + end +end + +def fun_l20_n353(x) + if (x < 1) + fun_l21_n447(x) + else + fun_l21_n14(x) + end +end + +def fun_l20_n354(x) + if (x < 1) + fun_l21_n151(x) + else + fun_l21_n545(x) + end +end + +def fun_l20_n355(x) + if (x < 1) + fun_l21_n579(x) + else + fun_l21_n934(x) + end +end + +def fun_l20_n356(x) + if (x < 1) + fun_l21_n612(x) + else + fun_l21_n433(x) + end +end + +def fun_l20_n357(x) + if (x < 1) + fun_l21_n969(x) + else + fun_l21_n816(x) + end +end + +def fun_l20_n358(x) + if (x < 1) + fun_l21_n24(x) + else + fun_l21_n272(x) + end +end + +def fun_l20_n359(x) + if (x < 1) + fun_l21_n945(x) + else + fun_l21_n458(x) + end +end + +def fun_l20_n360(x) + if (x < 1) + fun_l21_n294(x) + else + fun_l21_n934(x) + end +end + +def fun_l20_n361(x) + if (x < 1) + fun_l21_n777(x) + else + fun_l21_n499(x) + end +end + +def fun_l20_n362(x) + if (x < 1) + fun_l21_n538(x) + else + fun_l21_n400(x) + end +end + +def fun_l20_n363(x) + if (x < 1) + fun_l21_n660(x) + else + fun_l21_n970(x) + end +end + +def fun_l20_n364(x) + if (x < 1) + fun_l21_n230(x) + else + fun_l21_n977(x) + end +end + +def fun_l20_n365(x) + if (x < 1) + fun_l21_n335(x) + else + fun_l21_n436(x) + end +end + +def fun_l20_n366(x) + if (x < 1) + fun_l21_n596(x) + else + fun_l21_n992(x) + end +end + +def fun_l20_n367(x) + if (x < 1) + fun_l21_n502(x) + else + fun_l21_n251(x) + end +end + +def fun_l20_n368(x) + if (x < 1) + fun_l21_n501(x) + else + fun_l21_n493(x) + end +end + +def fun_l20_n369(x) + if (x < 1) + fun_l21_n48(x) + else + fun_l21_n850(x) + end +end + +def fun_l20_n370(x) + if (x < 1) + fun_l21_n900(x) + else + fun_l21_n919(x) + end +end + +def fun_l20_n371(x) + if (x < 1) + fun_l21_n349(x) + else + fun_l21_n80(x) + end +end + +def fun_l20_n372(x) + if (x < 1) + fun_l21_n275(x) + else + fun_l21_n135(x) + end +end + +def fun_l20_n373(x) + if (x < 1) + fun_l21_n987(x) + else + fun_l21_n472(x) + end +end + +def fun_l20_n374(x) + if (x < 1) + fun_l21_n877(x) + else + fun_l21_n298(x) + end +end + +def fun_l20_n375(x) + if (x < 1) + fun_l21_n518(x) + else + fun_l21_n676(x) + end +end + +def fun_l20_n376(x) + if (x < 1) + fun_l21_n108(x) + else + fun_l21_n470(x) + end +end + +def fun_l20_n377(x) + if (x < 1) + fun_l21_n643(x) + else + fun_l21_n189(x) + end +end + +def fun_l20_n378(x) + if (x < 1) + fun_l21_n608(x) + else + fun_l21_n376(x) + end +end + +def fun_l20_n379(x) + if (x < 1) + fun_l21_n520(x) + else + fun_l21_n651(x) + end +end + +def fun_l20_n380(x) + if (x < 1) + fun_l21_n399(x) + else + fun_l21_n867(x) + end +end + +def fun_l20_n381(x) + if (x < 1) + fun_l21_n815(x) + else + fun_l21_n78(x) + end +end + +def fun_l20_n382(x) + if (x < 1) + fun_l21_n216(x) + else + fun_l21_n379(x) + end +end + +def fun_l20_n383(x) + if (x < 1) + fun_l21_n628(x) + else + fun_l21_n227(x) + end +end + +def fun_l20_n384(x) + if (x < 1) + fun_l21_n699(x) + else + fun_l21_n170(x) + end +end + +def fun_l20_n385(x) + if (x < 1) + fun_l21_n444(x) + else + fun_l21_n603(x) + end +end + +def fun_l20_n386(x) + if (x < 1) + fun_l21_n299(x) + else + fun_l21_n803(x) + end +end + +def fun_l20_n387(x) + if (x < 1) + fun_l21_n708(x) + else + fun_l21_n187(x) + end +end + +def fun_l20_n388(x) + if (x < 1) + fun_l21_n490(x) + else + fun_l21_n75(x) + end +end + +def fun_l20_n389(x) + if (x < 1) + fun_l21_n856(x) + else + fun_l21_n257(x) + end +end + +def fun_l20_n390(x) + if (x < 1) + fun_l21_n394(x) + else + fun_l21_n669(x) + end +end + +def fun_l20_n391(x) + if (x < 1) + fun_l21_n501(x) + else + fun_l21_n555(x) + end +end + +def fun_l20_n392(x) + if (x < 1) + fun_l21_n657(x) + else + fun_l21_n226(x) + end +end + +def fun_l20_n393(x) + if (x < 1) + fun_l21_n229(x) + else + fun_l21_n898(x) + end +end + +def fun_l20_n394(x) + if (x < 1) + fun_l21_n726(x) + else + fun_l21_n349(x) + end +end + +def fun_l20_n395(x) + if (x < 1) + fun_l21_n247(x) + else + fun_l21_n996(x) + end +end + +def fun_l20_n396(x) + if (x < 1) + fun_l21_n136(x) + else + fun_l21_n601(x) + end +end + +def fun_l20_n397(x) + if (x < 1) + fun_l21_n365(x) + else + fun_l21_n203(x) + end +end + +def fun_l20_n398(x) + if (x < 1) + fun_l21_n376(x) + else + fun_l21_n172(x) + end +end + +def fun_l20_n399(x) + if (x < 1) + fun_l21_n23(x) + else + fun_l21_n577(x) + end +end + +def fun_l20_n400(x) + if (x < 1) + fun_l21_n368(x) + else + fun_l21_n448(x) + end +end + +def fun_l20_n401(x) + if (x < 1) + fun_l21_n934(x) + else + fun_l21_n949(x) + end +end + +def fun_l20_n402(x) + if (x < 1) + fun_l21_n127(x) + else + fun_l21_n132(x) + end +end + +def fun_l20_n403(x) + if (x < 1) + fun_l21_n133(x) + else + fun_l21_n389(x) + end +end + +def fun_l20_n404(x) + if (x < 1) + fun_l21_n750(x) + else + fun_l21_n591(x) + end +end + +def fun_l20_n405(x) + if (x < 1) + fun_l21_n492(x) + else + fun_l21_n763(x) + end +end + +def fun_l20_n406(x) + if (x < 1) + fun_l21_n137(x) + else + fun_l21_n552(x) + end +end + +def fun_l20_n407(x) + if (x < 1) + fun_l21_n200(x) + else + fun_l21_n537(x) + end +end + +def fun_l20_n408(x) + if (x < 1) + fun_l21_n681(x) + else + fun_l21_n645(x) + end +end + +def fun_l20_n409(x) + if (x < 1) + fun_l21_n86(x) + else + fun_l21_n239(x) + end +end + +def fun_l20_n410(x) + if (x < 1) + fun_l21_n357(x) + else + fun_l21_n98(x) + end +end + +def fun_l20_n411(x) + if (x < 1) + fun_l21_n889(x) + else + fun_l21_n199(x) + end +end + +def fun_l20_n412(x) + if (x < 1) + fun_l21_n504(x) + else + fun_l21_n950(x) + end +end + +def fun_l20_n413(x) + if (x < 1) + fun_l21_n220(x) + else + fun_l21_n351(x) + end +end + +def fun_l20_n414(x) + if (x < 1) + fun_l21_n287(x) + else + fun_l21_n614(x) + end +end + +def fun_l20_n415(x) + if (x < 1) + fun_l21_n699(x) + else + fun_l21_n464(x) + end +end + +def fun_l20_n416(x) + if (x < 1) + fun_l21_n638(x) + else + fun_l21_n10(x) + end +end + +def fun_l20_n417(x) + if (x < 1) + fun_l21_n52(x) + else + fun_l21_n348(x) + end +end + +def fun_l20_n418(x) + if (x < 1) + fun_l21_n248(x) + else + fun_l21_n703(x) + end +end + +def fun_l20_n419(x) + if (x < 1) + fun_l21_n430(x) + else + fun_l21_n886(x) + end +end + +def fun_l20_n420(x) + if (x < 1) + fun_l21_n695(x) + else + fun_l21_n528(x) + end +end + +def fun_l20_n421(x) + if (x < 1) + fun_l21_n545(x) + else + fun_l21_n521(x) + end +end + +def fun_l20_n422(x) + if (x < 1) + fun_l21_n66(x) + else + fun_l21_n31(x) + end +end + +def fun_l20_n423(x) + if (x < 1) + fun_l21_n411(x) + else + fun_l21_n476(x) + end +end + +def fun_l20_n424(x) + if (x < 1) + fun_l21_n433(x) + else + fun_l21_n940(x) + end +end + +def fun_l20_n425(x) + if (x < 1) + fun_l21_n622(x) + else + fun_l21_n817(x) + end +end + +def fun_l20_n426(x) + if (x < 1) + fun_l21_n516(x) + else + fun_l21_n665(x) + end +end + +def fun_l20_n427(x) + if (x < 1) + fun_l21_n828(x) + else + fun_l21_n47(x) + end +end + +def fun_l20_n428(x) + if (x < 1) + fun_l21_n445(x) + else + fun_l21_n94(x) + end +end + +def fun_l20_n429(x) + if (x < 1) + fun_l21_n799(x) + else + fun_l21_n676(x) + end +end + +def fun_l20_n430(x) + if (x < 1) + fun_l21_n518(x) + else + fun_l21_n988(x) + end +end + +def fun_l20_n431(x) + if (x < 1) + fun_l21_n787(x) + else + fun_l21_n127(x) + end +end + +def fun_l20_n432(x) + if (x < 1) + fun_l21_n502(x) + else + fun_l21_n719(x) + end +end + +def fun_l20_n433(x) + if (x < 1) + fun_l21_n406(x) + else + fun_l21_n828(x) + end +end + +def fun_l20_n434(x) + if (x < 1) + fun_l21_n845(x) + else + fun_l21_n75(x) + end +end + +def fun_l20_n435(x) + if (x < 1) + fun_l21_n425(x) + else + fun_l21_n449(x) + end +end + +def fun_l20_n436(x) + if (x < 1) + fun_l21_n520(x) + else + fun_l21_n68(x) + end +end + +def fun_l20_n437(x) + if (x < 1) + fun_l21_n872(x) + else + fun_l21_n978(x) + end +end + +def fun_l20_n438(x) + if (x < 1) + fun_l21_n522(x) + else + fun_l21_n658(x) + end +end + +def fun_l20_n439(x) + if (x < 1) + fun_l21_n976(x) + else + fun_l21_n224(x) + end +end + +def fun_l20_n440(x) + if (x < 1) + fun_l21_n256(x) + else + fun_l21_n700(x) + end +end + +def fun_l20_n441(x) + if (x < 1) + fun_l21_n722(x) + else + fun_l21_n348(x) + end +end + +def fun_l20_n442(x) + if (x < 1) + fun_l21_n377(x) + else + fun_l21_n966(x) + end +end + +def fun_l20_n443(x) + if (x < 1) + fun_l21_n519(x) + else + fun_l21_n611(x) + end +end + +def fun_l20_n444(x) + if (x < 1) + fun_l21_n318(x) + else + fun_l21_n937(x) + end +end + +def fun_l20_n445(x) + if (x < 1) + fun_l21_n416(x) + else + fun_l21_n874(x) + end +end + +def fun_l20_n446(x) + if (x < 1) + fun_l21_n157(x) + else + fun_l21_n328(x) + end +end + +def fun_l20_n447(x) + if (x < 1) + fun_l21_n540(x) + else + fun_l21_n906(x) + end +end + +def fun_l20_n448(x) + if (x < 1) + fun_l21_n13(x) + else + fun_l21_n325(x) + end +end + +def fun_l20_n449(x) + if (x < 1) + fun_l21_n771(x) + else + fun_l21_n929(x) + end +end + +def fun_l20_n450(x) + if (x < 1) + fun_l21_n770(x) + else + fun_l21_n778(x) + end +end + +def fun_l20_n451(x) + if (x < 1) + fun_l21_n939(x) + else + fun_l21_n493(x) + end +end + +def fun_l20_n452(x) + if (x < 1) + fun_l21_n481(x) + else + fun_l21_n407(x) + end +end + +def fun_l20_n453(x) + if (x < 1) + fun_l21_n759(x) + else + fun_l21_n322(x) + end +end + +def fun_l20_n454(x) + if (x < 1) + fun_l21_n703(x) + else + fun_l21_n409(x) + end +end + +def fun_l20_n455(x) + if (x < 1) + fun_l21_n394(x) + else + fun_l21_n415(x) + end +end + +def fun_l20_n456(x) + if (x < 1) + fun_l21_n583(x) + else + fun_l21_n188(x) + end +end + +def fun_l20_n457(x) + if (x < 1) + fun_l21_n668(x) + else + fun_l21_n46(x) + end +end + +def fun_l20_n458(x) + if (x < 1) + fun_l21_n855(x) + else + fun_l21_n802(x) + end +end + +def fun_l20_n459(x) + if (x < 1) + fun_l21_n720(x) + else + fun_l21_n691(x) + end +end + +def fun_l20_n460(x) + if (x < 1) + fun_l21_n440(x) + else + fun_l21_n353(x) + end +end + +def fun_l20_n461(x) + if (x < 1) + fun_l21_n604(x) + else + fun_l21_n872(x) + end +end + +def fun_l20_n462(x) + if (x < 1) + fun_l21_n355(x) + else + fun_l21_n699(x) + end +end + +def fun_l20_n463(x) + if (x < 1) + fun_l21_n476(x) + else + fun_l21_n447(x) + end +end + +def fun_l20_n464(x) + if (x < 1) + fun_l21_n554(x) + else + fun_l21_n745(x) + end +end + +def fun_l20_n465(x) + if (x < 1) + fun_l21_n632(x) + else + fun_l21_n281(x) + end +end + +def fun_l20_n466(x) + if (x < 1) + fun_l21_n873(x) + else + fun_l21_n449(x) + end +end + +def fun_l20_n467(x) + if (x < 1) + fun_l21_n90(x) + else + fun_l21_n933(x) + end +end + +def fun_l20_n468(x) + if (x < 1) + fun_l21_n915(x) + else + fun_l21_n801(x) + end +end + +def fun_l20_n469(x) + if (x < 1) + fun_l21_n429(x) + else + fun_l21_n139(x) + end +end + +def fun_l20_n470(x) + if (x < 1) + fun_l21_n858(x) + else + fun_l21_n450(x) + end +end + +def fun_l20_n471(x) + if (x < 1) + fun_l21_n556(x) + else + fun_l21_n109(x) + end +end + +def fun_l20_n472(x) + if (x < 1) + fun_l21_n395(x) + else + fun_l21_n129(x) + end +end + +def fun_l20_n473(x) + if (x < 1) + fun_l21_n282(x) + else + fun_l21_n277(x) + end +end + +def fun_l20_n474(x) + if (x < 1) + fun_l21_n90(x) + else + fun_l21_n399(x) + end +end + +def fun_l20_n475(x) + if (x < 1) + fun_l21_n719(x) + else + fun_l21_n698(x) + end +end + +def fun_l20_n476(x) + if (x < 1) + fun_l21_n597(x) + else + fun_l21_n210(x) + end +end + +def fun_l20_n477(x) + if (x < 1) + fun_l21_n722(x) + else + fun_l21_n31(x) + end +end + +def fun_l20_n478(x) + if (x < 1) + fun_l21_n874(x) + else + fun_l21_n527(x) + end +end + +def fun_l20_n479(x) + if (x < 1) + fun_l21_n247(x) + else + fun_l21_n164(x) + end +end + +def fun_l20_n480(x) + if (x < 1) + fun_l21_n449(x) + else + fun_l21_n106(x) + end +end + +def fun_l20_n481(x) + if (x < 1) + fun_l21_n787(x) + else + fun_l21_n678(x) + end +end + +def fun_l20_n482(x) + if (x < 1) + fun_l21_n176(x) + else + fun_l21_n650(x) + end +end + +def fun_l20_n483(x) + if (x < 1) + fun_l21_n314(x) + else + fun_l21_n325(x) + end +end + +def fun_l20_n484(x) + if (x < 1) + fun_l21_n877(x) + else + fun_l21_n539(x) + end +end + +def fun_l20_n485(x) + if (x < 1) + fun_l21_n230(x) + else + fun_l21_n314(x) + end +end + +def fun_l20_n486(x) + if (x < 1) + fun_l21_n778(x) + else + fun_l21_n493(x) + end +end + +def fun_l20_n487(x) + if (x < 1) + fun_l21_n615(x) + else + fun_l21_n111(x) + end +end + +def fun_l20_n488(x) + if (x < 1) + fun_l21_n133(x) + else + fun_l21_n381(x) + end +end + +def fun_l20_n489(x) + if (x < 1) + fun_l21_n332(x) + else + fun_l21_n68(x) + end +end + +def fun_l20_n490(x) + if (x < 1) + fun_l21_n995(x) + else + fun_l21_n861(x) + end +end + +def fun_l20_n491(x) + if (x < 1) + fun_l21_n537(x) + else + fun_l21_n164(x) + end +end + +def fun_l20_n492(x) + if (x < 1) + fun_l21_n759(x) + else + fun_l21_n598(x) + end +end + +def fun_l20_n493(x) + if (x < 1) + fun_l21_n890(x) + else + fun_l21_n644(x) + end +end + +def fun_l20_n494(x) + if (x < 1) + fun_l21_n641(x) + else + fun_l21_n420(x) + end +end + +def fun_l20_n495(x) + if (x < 1) + fun_l21_n826(x) + else + fun_l21_n821(x) + end +end + +def fun_l20_n496(x) + if (x < 1) + fun_l21_n348(x) + else + fun_l21_n277(x) + end +end + +def fun_l20_n497(x) + if (x < 1) + fun_l21_n14(x) + else + fun_l21_n950(x) + end +end + +def fun_l20_n498(x) + if (x < 1) + fun_l21_n43(x) + else + fun_l21_n759(x) + end +end + +def fun_l20_n499(x) + if (x < 1) + fun_l21_n899(x) + else + fun_l21_n730(x) + end +end + +def fun_l20_n500(x) + if (x < 1) + fun_l21_n918(x) + else + fun_l21_n454(x) + end +end + +def fun_l20_n501(x) + if (x < 1) + fun_l21_n821(x) + else + fun_l21_n388(x) + end +end + +def fun_l20_n502(x) + if (x < 1) + fun_l21_n164(x) + else + fun_l21_n718(x) + end +end + +def fun_l20_n503(x) + if (x < 1) + fun_l21_n152(x) + else + fun_l21_n613(x) + end +end + +def fun_l20_n504(x) + if (x < 1) + fun_l21_n931(x) + else + fun_l21_n912(x) + end +end + +def fun_l20_n505(x) + if (x < 1) + fun_l21_n655(x) + else + fun_l21_n38(x) + end +end + +def fun_l20_n506(x) + if (x < 1) + fun_l21_n408(x) + else + fun_l21_n38(x) + end +end + +def fun_l20_n507(x) + if (x < 1) + fun_l21_n960(x) + else + fun_l21_n857(x) + end +end + +def fun_l20_n508(x) + if (x < 1) + fun_l21_n308(x) + else + fun_l21_n210(x) + end +end + +def fun_l20_n509(x) + if (x < 1) + fun_l21_n985(x) + else + fun_l21_n537(x) + end +end + +def fun_l20_n510(x) + if (x < 1) + fun_l21_n200(x) + else + fun_l21_n598(x) + end +end + +def fun_l20_n511(x) + if (x < 1) + fun_l21_n451(x) + else + fun_l21_n958(x) + end +end + +def fun_l20_n512(x) + if (x < 1) + fun_l21_n459(x) + else + fun_l21_n823(x) + end +end + +def fun_l20_n513(x) + if (x < 1) + fun_l21_n153(x) + else + fun_l21_n931(x) + end +end + +def fun_l20_n514(x) + if (x < 1) + fun_l21_n213(x) + else + fun_l21_n336(x) + end +end + +def fun_l20_n515(x) + if (x < 1) + fun_l21_n401(x) + else + fun_l21_n222(x) + end +end + +def fun_l20_n516(x) + if (x < 1) + fun_l21_n582(x) + else + fun_l21_n735(x) + end +end + +def fun_l20_n517(x) + if (x < 1) + fun_l21_n799(x) + else + fun_l21_n139(x) + end +end + +def fun_l20_n518(x) + if (x < 1) + fun_l21_n279(x) + else + fun_l21_n476(x) + end +end + +def fun_l20_n519(x) + if (x < 1) + fun_l21_n624(x) + else + fun_l21_n276(x) + end +end + +def fun_l20_n520(x) + if (x < 1) + fun_l21_n505(x) + else + fun_l21_n523(x) + end +end + +def fun_l20_n521(x) + if (x < 1) + fun_l21_n887(x) + else + fun_l21_n948(x) + end +end + +def fun_l20_n522(x) + if (x < 1) + fun_l21_n969(x) + else + fun_l21_n988(x) + end +end + +def fun_l20_n523(x) + if (x < 1) + fun_l21_n271(x) + else + fun_l21_n189(x) + end +end + +def fun_l20_n524(x) + if (x < 1) + fun_l21_n478(x) + else + fun_l21_n111(x) + end +end + +def fun_l20_n525(x) + if (x < 1) + fun_l21_n808(x) + else + fun_l21_n256(x) + end +end + +def fun_l20_n526(x) + if (x < 1) + fun_l21_n715(x) + else + fun_l21_n508(x) + end +end + +def fun_l20_n527(x) + if (x < 1) + fun_l21_n819(x) + else + fun_l21_n670(x) + end +end + +def fun_l20_n528(x) + if (x < 1) + fun_l21_n598(x) + else + fun_l21_n369(x) + end +end + +def fun_l20_n529(x) + if (x < 1) + fun_l21_n391(x) + else + fun_l21_n651(x) + end +end + +def fun_l20_n530(x) + if (x < 1) + fun_l21_n69(x) + else + fun_l21_n706(x) + end +end + +def fun_l20_n531(x) + if (x < 1) + fun_l21_n786(x) + else + fun_l21_n289(x) + end +end + +def fun_l20_n532(x) + if (x < 1) + fun_l21_n128(x) + else + fun_l21_n789(x) + end +end + +def fun_l20_n533(x) + if (x < 1) + fun_l21_n935(x) + else + fun_l21_n29(x) + end +end + +def fun_l20_n534(x) + if (x < 1) + fun_l21_n735(x) + else + fun_l21_n381(x) + end +end + +def fun_l20_n535(x) + if (x < 1) + fun_l21_n299(x) + else + fun_l21_n932(x) + end +end + +def fun_l20_n536(x) + if (x < 1) + fun_l21_n823(x) + else + fun_l21_n7(x) + end +end + +def fun_l20_n537(x) + if (x < 1) + fun_l21_n152(x) + else + fun_l21_n758(x) + end +end + +def fun_l20_n538(x) + if (x < 1) + fun_l21_n8(x) + else + fun_l21_n772(x) + end +end + +def fun_l20_n539(x) + if (x < 1) + fun_l21_n900(x) + else + fun_l21_n984(x) + end +end + +def fun_l20_n540(x) + if (x < 1) + fun_l21_n726(x) + else + fun_l21_n337(x) + end +end + +def fun_l20_n541(x) + if (x < 1) + fun_l21_n557(x) + else + fun_l21_n998(x) + end +end + +def fun_l20_n542(x) + if (x < 1) + fun_l21_n898(x) + else + fun_l21_n389(x) + end +end + +def fun_l20_n543(x) + if (x < 1) + fun_l21_n71(x) + else + fun_l21_n276(x) + end +end + +def fun_l20_n544(x) + if (x < 1) + fun_l21_n888(x) + else + fun_l21_n525(x) + end +end + +def fun_l20_n545(x) + if (x < 1) + fun_l21_n797(x) + else + fun_l21_n487(x) + end +end + +def fun_l20_n546(x) + if (x < 1) + fun_l21_n825(x) + else + fun_l21_n349(x) + end +end + +def fun_l20_n547(x) + if (x < 1) + fun_l21_n538(x) + else + fun_l21_n817(x) + end +end + +def fun_l20_n548(x) + if (x < 1) + fun_l21_n630(x) + else + fun_l21_n432(x) + end +end + +def fun_l20_n549(x) + if (x < 1) + fun_l21_n553(x) + else + fun_l21_n179(x) + end +end + +def fun_l20_n550(x) + if (x < 1) + fun_l21_n982(x) + else + fun_l21_n350(x) + end +end + +def fun_l20_n551(x) + if (x < 1) + fun_l21_n404(x) + else + fun_l21_n313(x) + end +end + +def fun_l20_n552(x) + if (x < 1) + fun_l21_n893(x) + else + fun_l21_n879(x) + end +end + +def fun_l20_n553(x) + if (x < 1) + fun_l21_n360(x) + else + fun_l21_n403(x) + end +end + +def fun_l20_n554(x) + if (x < 1) + fun_l21_n607(x) + else + fun_l21_n18(x) + end +end + +def fun_l20_n555(x) + if (x < 1) + fun_l21_n269(x) + else + fun_l21_n514(x) + end +end + +def fun_l20_n556(x) + if (x < 1) + fun_l21_n22(x) + else + fun_l21_n164(x) + end +end + +def fun_l20_n557(x) + if (x < 1) + fun_l21_n560(x) + else + fun_l21_n671(x) + end +end + +def fun_l20_n558(x) + if (x < 1) + fun_l21_n857(x) + else + fun_l21_n34(x) + end +end + +def fun_l20_n559(x) + if (x < 1) + fun_l21_n750(x) + else + fun_l21_n267(x) + end +end + +def fun_l20_n560(x) + if (x < 1) + fun_l21_n97(x) + else + fun_l21_n72(x) + end +end + +def fun_l20_n561(x) + if (x < 1) + fun_l21_n482(x) + else + fun_l21_n644(x) + end +end + +def fun_l20_n562(x) + if (x < 1) + fun_l21_n147(x) + else + fun_l21_n524(x) + end +end + +def fun_l20_n563(x) + if (x < 1) + fun_l21_n509(x) + else + fun_l21_n124(x) + end +end + +def fun_l20_n564(x) + if (x < 1) + fun_l21_n183(x) + else + fun_l21_n254(x) + end +end + +def fun_l20_n565(x) + if (x < 1) + fun_l21_n919(x) + else + fun_l21_n727(x) + end +end + +def fun_l20_n566(x) + if (x < 1) + fun_l21_n847(x) + else + fun_l21_n546(x) + end +end + +def fun_l20_n567(x) + if (x < 1) + fun_l21_n214(x) + else + fun_l21_n692(x) + end +end + +def fun_l20_n568(x) + if (x < 1) + fun_l21_n867(x) + else + fun_l21_n747(x) + end +end + +def fun_l20_n569(x) + if (x < 1) + fun_l21_n277(x) + else + fun_l21_n130(x) + end +end + +def fun_l20_n570(x) + if (x < 1) + fun_l21_n472(x) + else + fun_l21_n296(x) + end +end + +def fun_l20_n571(x) + if (x < 1) + fun_l21_n633(x) + else + fun_l21_n704(x) + end +end + +def fun_l20_n572(x) + if (x < 1) + fun_l21_n179(x) + else + fun_l21_n683(x) + end +end + +def fun_l20_n573(x) + if (x < 1) + fun_l21_n607(x) + else + fun_l21_n140(x) + end +end + +def fun_l20_n574(x) + if (x < 1) + fun_l21_n647(x) + else + fun_l21_n233(x) + end +end + +def fun_l20_n575(x) + if (x < 1) + fun_l21_n992(x) + else + fun_l21_n951(x) + end +end + +def fun_l20_n576(x) + if (x < 1) + fun_l21_n750(x) + else + fun_l21_n574(x) + end +end + +def fun_l20_n577(x) + if (x < 1) + fun_l21_n116(x) + else + fun_l21_n488(x) + end +end + +def fun_l20_n578(x) + if (x < 1) + fun_l21_n580(x) + else + fun_l21_n547(x) + end +end + +def fun_l20_n579(x) + if (x < 1) + fun_l21_n576(x) + else + fun_l21_n744(x) + end +end + +def fun_l20_n580(x) + if (x < 1) + fun_l21_n791(x) + else + fun_l21_n495(x) + end +end + +def fun_l20_n581(x) + if (x < 1) + fun_l21_n188(x) + else + fun_l21_n795(x) + end +end + +def fun_l20_n582(x) + if (x < 1) + fun_l21_n477(x) + else + fun_l21_n965(x) + end +end + +def fun_l20_n583(x) + if (x < 1) + fun_l21_n436(x) + else + fun_l21_n169(x) + end +end + +def fun_l20_n584(x) + if (x < 1) + fun_l21_n518(x) + else + fun_l21_n849(x) + end +end + +def fun_l20_n585(x) + if (x < 1) + fun_l21_n747(x) + else + fun_l21_n882(x) + end +end + +def fun_l20_n586(x) + if (x < 1) + fun_l21_n0(x) + else + fun_l21_n481(x) + end +end + +def fun_l20_n587(x) + if (x < 1) + fun_l21_n876(x) + else + fun_l21_n279(x) + end +end + +def fun_l20_n588(x) + if (x < 1) + fun_l21_n355(x) + else + fun_l21_n744(x) + end +end + +def fun_l20_n589(x) + if (x < 1) + fun_l21_n408(x) + else + fun_l21_n27(x) + end +end + +def fun_l20_n590(x) + if (x < 1) + fun_l21_n152(x) + else + fun_l21_n867(x) + end +end + +def fun_l20_n591(x) + if (x < 1) + fun_l21_n543(x) + else + fun_l21_n193(x) + end +end + +def fun_l20_n592(x) + if (x < 1) + fun_l21_n160(x) + else + fun_l21_n185(x) + end +end + +def fun_l20_n593(x) + if (x < 1) + fun_l21_n613(x) + else + fun_l21_n403(x) + end +end + +def fun_l20_n594(x) + if (x < 1) + fun_l21_n660(x) + else + fun_l21_n933(x) + end +end + +def fun_l20_n595(x) + if (x < 1) + fun_l21_n222(x) + else + fun_l21_n922(x) + end +end + +def fun_l20_n596(x) + if (x < 1) + fun_l21_n668(x) + else + fun_l21_n857(x) + end +end + +def fun_l20_n597(x) + if (x < 1) + fun_l21_n846(x) + else + fun_l21_n164(x) + end +end + +def fun_l20_n598(x) + if (x < 1) + fun_l21_n755(x) + else + fun_l21_n591(x) + end +end + +def fun_l20_n599(x) + if (x < 1) + fun_l21_n224(x) + else + fun_l21_n390(x) + end +end + +def fun_l20_n600(x) + if (x < 1) + fun_l21_n713(x) + else + fun_l21_n735(x) + end +end + +def fun_l20_n601(x) + if (x < 1) + fun_l21_n551(x) + else + fun_l21_n57(x) + end +end + +def fun_l20_n602(x) + if (x < 1) + fun_l21_n808(x) + else + fun_l21_n928(x) + end +end + +def fun_l20_n603(x) + if (x < 1) + fun_l21_n471(x) + else + fun_l21_n436(x) + end +end + +def fun_l20_n604(x) + if (x < 1) + fun_l21_n482(x) + else + fun_l21_n445(x) + end +end + +def fun_l20_n605(x) + if (x < 1) + fun_l21_n680(x) + else + fun_l21_n433(x) + end +end + +def fun_l20_n606(x) + if (x < 1) + fun_l21_n687(x) + else + fun_l21_n885(x) + end +end + +def fun_l20_n607(x) + if (x < 1) + fun_l21_n370(x) + else + fun_l21_n414(x) + end +end + +def fun_l20_n608(x) + if (x < 1) + fun_l21_n11(x) + else + fun_l21_n792(x) + end +end + +def fun_l20_n609(x) + if (x < 1) + fun_l21_n490(x) + else + fun_l21_n947(x) + end +end + +def fun_l20_n610(x) + if (x < 1) + fun_l21_n609(x) + else + fun_l21_n514(x) + end +end + +def fun_l20_n611(x) + if (x < 1) + fun_l21_n873(x) + else + fun_l21_n247(x) + end +end + +def fun_l20_n612(x) + if (x < 1) + fun_l21_n199(x) + else + fun_l21_n421(x) + end +end + +def fun_l20_n613(x) + if (x < 1) + fun_l21_n807(x) + else + fun_l21_n905(x) + end +end + +def fun_l20_n614(x) + if (x < 1) + fun_l21_n260(x) + else + fun_l21_n926(x) + end +end + +def fun_l20_n615(x) + if (x < 1) + fun_l21_n288(x) + else + fun_l21_n944(x) + end +end + +def fun_l20_n616(x) + if (x < 1) + fun_l21_n346(x) + else + fun_l21_n949(x) + end +end + +def fun_l20_n617(x) + if (x < 1) + fun_l21_n243(x) + else + fun_l21_n527(x) + end +end + +def fun_l20_n618(x) + if (x < 1) + fun_l21_n193(x) + else + fun_l21_n576(x) + end +end + +def fun_l20_n619(x) + if (x < 1) + fun_l21_n861(x) + else + fun_l21_n19(x) + end +end + +def fun_l20_n620(x) + if (x < 1) + fun_l21_n735(x) + else + fun_l21_n477(x) + end +end + +def fun_l20_n621(x) + if (x < 1) + fun_l21_n368(x) + else + fun_l21_n250(x) + end +end + +def fun_l20_n622(x) + if (x < 1) + fun_l21_n235(x) + else + fun_l21_n461(x) + end +end + +def fun_l20_n623(x) + if (x < 1) + fun_l21_n289(x) + else + fun_l21_n217(x) + end +end + +def fun_l20_n624(x) + if (x < 1) + fun_l21_n951(x) + else + fun_l21_n124(x) + end +end + +def fun_l20_n625(x) + if (x < 1) + fun_l21_n590(x) + else + fun_l21_n163(x) + end +end + +def fun_l20_n626(x) + if (x < 1) + fun_l21_n122(x) + else + fun_l21_n34(x) + end +end + +def fun_l20_n627(x) + if (x < 1) + fun_l21_n139(x) + else + fun_l21_n452(x) + end +end + +def fun_l20_n628(x) + if (x < 1) + fun_l21_n626(x) + else + fun_l21_n816(x) + end +end + +def fun_l20_n629(x) + if (x < 1) + fun_l21_n713(x) + else + fun_l21_n291(x) + end +end + +def fun_l20_n630(x) + if (x < 1) + fun_l21_n896(x) + else + fun_l21_n167(x) + end +end + +def fun_l20_n631(x) + if (x < 1) + fun_l21_n461(x) + else + fun_l21_n965(x) + end +end + +def fun_l20_n632(x) + if (x < 1) + fun_l21_n984(x) + else + fun_l21_n336(x) + end +end + +def fun_l20_n633(x) + if (x < 1) + fun_l21_n525(x) + else + fun_l21_n500(x) + end +end + +def fun_l20_n634(x) + if (x < 1) + fun_l21_n296(x) + else + fun_l21_n535(x) + end +end + +def fun_l20_n635(x) + if (x < 1) + fun_l21_n961(x) + else + fun_l21_n296(x) + end +end + +def fun_l20_n636(x) + if (x < 1) + fun_l21_n736(x) + else + fun_l21_n474(x) + end +end + +def fun_l20_n637(x) + if (x < 1) + fun_l21_n942(x) + else + fun_l21_n503(x) + end +end + +def fun_l20_n638(x) + if (x < 1) + fun_l21_n906(x) + else + fun_l21_n612(x) + end +end + +def fun_l20_n639(x) + if (x < 1) + fun_l21_n152(x) + else + fun_l21_n772(x) + end +end + +def fun_l20_n640(x) + if (x < 1) + fun_l21_n109(x) + else + fun_l21_n416(x) + end +end + +def fun_l20_n641(x) + if (x < 1) + fun_l21_n189(x) + else + fun_l21_n353(x) + end +end + +def fun_l20_n642(x) + if (x < 1) + fun_l21_n414(x) + else + fun_l21_n550(x) + end +end + +def fun_l20_n643(x) + if (x < 1) + fun_l21_n469(x) + else + fun_l21_n542(x) + end +end + +def fun_l20_n644(x) + if (x < 1) + fun_l21_n465(x) + else + fun_l21_n742(x) + end +end + +def fun_l20_n645(x) + if (x < 1) + fun_l21_n139(x) + else + fun_l21_n138(x) + end +end + +def fun_l20_n646(x) + if (x < 1) + fun_l21_n550(x) + else + fun_l21_n910(x) + end +end + +def fun_l20_n647(x) + if (x < 1) + fun_l21_n939(x) + else + fun_l21_n347(x) + end +end + +def fun_l20_n648(x) + if (x < 1) + fun_l21_n391(x) + else + fun_l21_n648(x) + end +end + +def fun_l20_n649(x) + if (x < 1) + fun_l21_n690(x) + else + fun_l21_n627(x) + end +end + +def fun_l20_n650(x) + if (x < 1) + fun_l21_n596(x) + else + fun_l21_n681(x) + end +end + +def fun_l20_n651(x) + if (x < 1) + fun_l21_n686(x) + else + fun_l21_n399(x) + end +end + +def fun_l20_n652(x) + if (x < 1) + fun_l21_n461(x) + else + fun_l21_n851(x) + end +end + +def fun_l20_n653(x) + if (x < 1) + fun_l21_n562(x) + else + fun_l21_n60(x) + end +end + +def fun_l20_n654(x) + if (x < 1) + fun_l21_n269(x) + else + fun_l21_n937(x) + end +end + +def fun_l20_n655(x) + if (x < 1) + fun_l21_n994(x) + else + fun_l21_n386(x) + end +end + +def fun_l20_n656(x) + if (x < 1) + fun_l21_n568(x) + else + fun_l21_n180(x) + end +end + +def fun_l20_n657(x) + if (x < 1) + fun_l21_n334(x) + else + fun_l21_n362(x) + end +end + +def fun_l20_n658(x) + if (x < 1) + fun_l21_n14(x) + else + fun_l21_n311(x) + end +end + +def fun_l20_n659(x) + if (x < 1) + fun_l21_n715(x) + else + fun_l21_n945(x) + end +end + +def fun_l20_n660(x) + if (x < 1) + fun_l21_n739(x) + else + fun_l21_n456(x) + end +end + +def fun_l20_n661(x) + if (x < 1) + fun_l21_n298(x) + else + fun_l21_n344(x) + end +end + +def fun_l20_n662(x) + if (x < 1) + fun_l21_n134(x) + else + fun_l21_n828(x) + end +end + +def fun_l20_n663(x) + if (x < 1) + fun_l21_n831(x) + else + fun_l21_n231(x) + end +end + +def fun_l20_n664(x) + if (x < 1) + fun_l21_n330(x) + else + fun_l21_n733(x) + end +end + +def fun_l20_n665(x) + if (x < 1) + fun_l21_n22(x) + else + fun_l21_n973(x) + end +end + +def fun_l20_n666(x) + if (x < 1) + fun_l21_n277(x) + else + fun_l21_n988(x) + end +end + +def fun_l20_n667(x) + if (x < 1) + fun_l21_n252(x) + else + fun_l21_n8(x) + end +end + +def fun_l20_n668(x) + if (x < 1) + fun_l21_n991(x) + else + fun_l21_n801(x) + end +end + +def fun_l20_n669(x) + if (x < 1) + fun_l21_n811(x) + else + fun_l21_n660(x) + end +end + +def fun_l20_n670(x) + if (x < 1) + fun_l21_n384(x) + else + fun_l21_n596(x) + end +end + +def fun_l20_n671(x) + if (x < 1) + fun_l21_n509(x) + else + fun_l21_n133(x) + end +end + +def fun_l20_n672(x) + if (x < 1) + fun_l21_n650(x) + else + fun_l21_n679(x) + end +end + +def fun_l20_n673(x) + if (x < 1) + fun_l21_n323(x) + else + fun_l21_n824(x) + end +end + +def fun_l20_n674(x) + if (x < 1) + fun_l21_n728(x) + else + fun_l21_n697(x) + end +end + +def fun_l20_n675(x) + if (x < 1) + fun_l21_n367(x) + else + fun_l21_n383(x) + end +end + +def fun_l20_n676(x) + if (x < 1) + fun_l21_n280(x) + else + fun_l21_n309(x) + end +end + +def fun_l20_n677(x) + if (x < 1) + fun_l21_n17(x) + else + fun_l21_n687(x) + end +end + +def fun_l20_n678(x) + if (x < 1) + fun_l21_n133(x) + else + fun_l21_n250(x) + end +end + +def fun_l20_n679(x) + if (x < 1) + fun_l21_n713(x) + else + fun_l21_n630(x) + end +end + +def fun_l20_n680(x) + if (x < 1) + fun_l21_n348(x) + else + fun_l21_n737(x) + end +end + +def fun_l20_n681(x) + if (x < 1) + fun_l21_n450(x) + else + fun_l21_n283(x) + end +end + +def fun_l20_n682(x) + if (x < 1) + fun_l21_n568(x) + else + fun_l21_n22(x) + end +end + +def fun_l20_n683(x) + if (x < 1) + fun_l21_n173(x) + else + fun_l21_n457(x) + end +end + +def fun_l20_n684(x) + if (x < 1) + fun_l21_n846(x) + else + fun_l21_n415(x) + end +end + +def fun_l20_n685(x) + if (x < 1) + fun_l21_n757(x) + else + fun_l21_n817(x) + end +end + +def fun_l20_n686(x) + if (x < 1) + fun_l21_n282(x) + else + fun_l21_n503(x) + end +end + +def fun_l20_n687(x) + if (x < 1) + fun_l21_n337(x) + else + fun_l21_n407(x) + end +end + +def fun_l20_n688(x) + if (x < 1) + fun_l21_n783(x) + else + fun_l21_n307(x) + end +end + +def fun_l20_n689(x) + if (x < 1) + fun_l21_n397(x) + else + fun_l21_n10(x) + end +end + +def fun_l20_n690(x) + if (x < 1) + fun_l21_n100(x) + else + fun_l21_n704(x) + end +end + +def fun_l20_n691(x) + if (x < 1) + fun_l21_n380(x) + else + fun_l21_n780(x) + end +end + +def fun_l20_n692(x) + if (x < 1) + fun_l21_n782(x) + else + fun_l21_n955(x) + end +end + +def fun_l20_n693(x) + if (x < 1) + fun_l21_n40(x) + else + fun_l21_n599(x) + end +end + +def fun_l20_n694(x) + if (x < 1) + fun_l21_n730(x) + else + fun_l21_n215(x) + end +end + +def fun_l20_n695(x) + if (x < 1) + fun_l21_n168(x) + else + fun_l21_n757(x) + end +end + +def fun_l20_n696(x) + if (x < 1) + fun_l21_n622(x) + else + fun_l21_n411(x) + end +end + +def fun_l20_n697(x) + if (x < 1) + fun_l21_n958(x) + else + fun_l21_n832(x) + end +end + +def fun_l20_n698(x) + if (x < 1) + fun_l21_n452(x) + else + fun_l21_n390(x) + end +end + +def fun_l20_n699(x) + if (x < 1) + fun_l21_n669(x) + else + fun_l21_n642(x) + end +end + +def fun_l20_n700(x) + if (x < 1) + fun_l21_n481(x) + else + fun_l21_n273(x) + end +end + +def fun_l20_n701(x) + if (x < 1) + fun_l21_n305(x) + else + fun_l21_n783(x) + end +end + +def fun_l20_n702(x) + if (x < 1) + fun_l21_n766(x) + else + fun_l21_n943(x) + end +end + +def fun_l20_n703(x) + if (x < 1) + fun_l21_n440(x) + else + fun_l21_n875(x) + end +end + +def fun_l20_n704(x) + if (x < 1) + fun_l21_n332(x) + else + fun_l21_n839(x) + end +end + +def fun_l20_n705(x) + if (x < 1) + fun_l21_n459(x) + else + fun_l21_n341(x) + end +end + +def fun_l20_n706(x) + if (x < 1) + fun_l21_n897(x) + else + fun_l21_n235(x) + end +end + +def fun_l20_n707(x) + if (x < 1) + fun_l21_n400(x) + else + fun_l21_n349(x) + end +end + +def fun_l20_n708(x) + if (x < 1) + fun_l21_n121(x) + else + fun_l21_n40(x) + end +end + +def fun_l20_n709(x) + if (x < 1) + fun_l21_n496(x) + else + fun_l21_n473(x) + end +end + +def fun_l20_n710(x) + if (x < 1) + fun_l21_n146(x) + else + fun_l21_n944(x) + end +end + +def fun_l20_n711(x) + if (x < 1) + fun_l21_n497(x) + else + fun_l21_n322(x) + end +end + +def fun_l20_n712(x) + if (x < 1) + fun_l21_n647(x) + else + fun_l21_n76(x) + end +end + +def fun_l20_n713(x) + if (x < 1) + fun_l21_n402(x) + else + fun_l21_n904(x) + end +end + +def fun_l20_n714(x) + if (x < 1) + fun_l21_n834(x) + else + fun_l21_n904(x) + end +end + +def fun_l20_n715(x) + if (x < 1) + fun_l21_n482(x) + else + fun_l21_n399(x) + end +end + +def fun_l20_n716(x) + if (x < 1) + fun_l21_n441(x) + else + fun_l21_n348(x) + end +end + +def fun_l20_n717(x) + if (x < 1) + fun_l21_n577(x) + else + fun_l21_n815(x) + end +end + +def fun_l20_n718(x) + if (x < 1) + fun_l21_n18(x) + else + fun_l21_n399(x) + end +end + +def fun_l20_n719(x) + if (x < 1) + fun_l21_n245(x) + else + fun_l21_n928(x) + end +end + +def fun_l20_n720(x) + if (x < 1) + fun_l21_n373(x) + else + fun_l21_n432(x) + end +end + +def fun_l20_n721(x) + if (x < 1) + fun_l21_n20(x) + else + fun_l21_n485(x) + end +end + +def fun_l20_n722(x) + if (x < 1) + fun_l21_n79(x) + else + fun_l21_n525(x) + end +end + +def fun_l20_n723(x) + if (x < 1) + fun_l21_n474(x) + else + fun_l21_n706(x) + end +end + +def fun_l20_n724(x) + if (x < 1) + fun_l21_n27(x) + else + fun_l21_n833(x) + end +end + +def fun_l20_n725(x) + if (x < 1) + fun_l21_n386(x) + else + fun_l21_n422(x) + end +end + +def fun_l20_n726(x) + if (x < 1) + fun_l21_n816(x) + else + fun_l21_n204(x) + end +end + +def fun_l20_n727(x) + if (x < 1) + fun_l21_n502(x) + else + fun_l21_n554(x) + end +end + +def fun_l20_n728(x) + if (x < 1) + fun_l21_n846(x) + else + fun_l21_n948(x) + end +end + +def fun_l20_n729(x) + if (x < 1) + fun_l21_n308(x) + else + fun_l21_n408(x) + end +end + +def fun_l20_n730(x) + if (x < 1) + fun_l21_n882(x) + else + fun_l21_n151(x) + end +end + +def fun_l20_n731(x) + if (x < 1) + fun_l21_n22(x) + else + fun_l21_n839(x) + end +end + +def fun_l20_n732(x) + if (x < 1) + fun_l21_n482(x) + else + fun_l21_n942(x) + end +end + +def fun_l20_n733(x) + if (x < 1) + fun_l21_n959(x) + else + fun_l21_n615(x) + end +end + +def fun_l20_n734(x) + if (x < 1) + fun_l21_n137(x) + else + fun_l21_n455(x) + end +end + +def fun_l20_n735(x) + if (x < 1) + fun_l21_n388(x) + else + fun_l21_n362(x) + end +end + +def fun_l20_n736(x) + if (x < 1) + fun_l21_n107(x) + else + fun_l21_n883(x) + end +end + +def fun_l20_n737(x) + if (x < 1) + fun_l21_n42(x) + else + fun_l21_n288(x) + end +end + +def fun_l20_n738(x) + if (x < 1) + fun_l21_n885(x) + else + fun_l21_n443(x) + end +end + +def fun_l20_n739(x) + if (x < 1) + fun_l21_n414(x) + else + fun_l21_n976(x) + end +end + +def fun_l20_n740(x) + if (x < 1) + fun_l21_n244(x) + else + fun_l21_n327(x) + end +end + +def fun_l20_n741(x) + if (x < 1) + fun_l21_n832(x) + else + fun_l21_n951(x) + end +end + +def fun_l20_n742(x) + if (x < 1) + fun_l21_n408(x) + else + fun_l21_n978(x) + end +end + +def fun_l20_n743(x) + if (x < 1) + fun_l21_n517(x) + else + fun_l21_n468(x) + end +end + +def fun_l20_n744(x) + if (x < 1) + fun_l21_n281(x) + else + fun_l21_n9(x) + end +end + +def fun_l20_n745(x) + if (x < 1) + fun_l21_n488(x) + else + fun_l21_n526(x) + end +end + +def fun_l20_n746(x) + if (x < 1) + fun_l21_n494(x) + else + fun_l21_n769(x) + end +end + +def fun_l20_n747(x) + if (x < 1) + fun_l21_n277(x) + else + fun_l21_n103(x) + end +end + +def fun_l20_n748(x) + if (x < 1) + fun_l21_n663(x) + else + fun_l21_n281(x) + end +end + +def fun_l20_n749(x) + if (x < 1) + fun_l21_n260(x) + else + fun_l21_n320(x) + end +end + +def fun_l20_n750(x) + if (x < 1) + fun_l21_n781(x) + else + fun_l21_n705(x) + end +end + +def fun_l20_n751(x) + if (x < 1) + fun_l21_n317(x) + else + fun_l21_n728(x) + end +end + +def fun_l20_n752(x) + if (x < 1) + fun_l21_n573(x) + else + fun_l21_n172(x) + end +end + +def fun_l20_n753(x) + if (x < 1) + fun_l21_n352(x) + else + fun_l21_n933(x) + end +end + +def fun_l20_n754(x) + if (x < 1) + fun_l21_n876(x) + else + fun_l21_n180(x) + end +end + +def fun_l20_n755(x) + if (x < 1) + fun_l21_n937(x) + else + fun_l21_n387(x) + end +end + +def fun_l20_n756(x) + if (x < 1) + fun_l21_n154(x) + else + fun_l21_n187(x) + end +end + +def fun_l20_n757(x) + if (x < 1) + fun_l21_n766(x) + else + fun_l21_n259(x) + end +end + +def fun_l20_n758(x) + if (x < 1) + fun_l21_n235(x) + else + fun_l21_n636(x) + end +end + +def fun_l20_n759(x) + if (x < 1) + fun_l21_n872(x) + else + fun_l21_n913(x) + end +end + +def fun_l20_n760(x) + if (x < 1) + fun_l21_n73(x) + else + fun_l21_n743(x) + end +end + +def fun_l20_n761(x) + if (x < 1) + fun_l21_n666(x) + else + fun_l21_n777(x) + end +end + +def fun_l20_n762(x) + if (x < 1) + fun_l21_n829(x) + else + fun_l21_n800(x) + end +end + +def fun_l20_n763(x) + if (x < 1) + fun_l21_n37(x) + else + fun_l21_n152(x) + end +end + +def fun_l20_n764(x) + if (x < 1) + fun_l21_n53(x) + else + fun_l21_n196(x) + end +end + +def fun_l20_n765(x) + if (x < 1) + fun_l21_n511(x) + else + fun_l21_n415(x) + end +end + +def fun_l20_n766(x) + if (x < 1) + fun_l21_n375(x) + else + fun_l21_n885(x) + end +end + +def fun_l20_n767(x) + if (x < 1) + fun_l21_n267(x) + else + fun_l21_n597(x) + end +end + +def fun_l20_n768(x) + if (x < 1) + fun_l21_n920(x) + else + fun_l21_n943(x) + end +end + +def fun_l20_n769(x) + if (x < 1) + fun_l21_n585(x) + else + fun_l21_n659(x) + end +end + +def fun_l20_n770(x) + if (x < 1) + fun_l21_n897(x) + else + fun_l21_n742(x) + end +end + +def fun_l20_n771(x) + if (x < 1) + fun_l21_n41(x) + else + fun_l21_n431(x) + end +end + +def fun_l20_n772(x) + if (x < 1) + fun_l21_n446(x) + else + fun_l21_n22(x) + end +end + +def fun_l20_n773(x) + if (x < 1) + fun_l21_n918(x) + else + fun_l21_n387(x) + end +end + +def fun_l20_n774(x) + if (x < 1) + fun_l21_n88(x) + else + fun_l21_n763(x) + end +end + +def fun_l20_n775(x) + if (x < 1) + fun_l21_n224(x) + else + fun_l21_n886(x) + end +end + +def fun_l20_n776(x) + if (x < 1) + fun_l21_n860(x) + else + fun_l21_n145(x) + end +end + +def fun_l20_n777(x) + if (x < 1) + fun_l21_n198(x) + else + fun_l21_n593(x) + end +end + +def fun_l20_n778(x) + if (x < 1) + fun_l21_n510(x) + else + fun_l21_n146(x) + end +end + +def fun_l20_n779(x) + if (x < 1) + fun_l21_n125(x) + else + fun_l21_n390(x) + end +end + +def fun_l20_n780(x) + if (x < 1) + fun_l21_n278(x) + else + fun_l21_n100(x) + end +end + +def fun_l20_n781(x) + if (x < 1) + fun_l21_n9(x) + else + fun_l21_n312(x) + end +end + +def fun_l20_n782(x) + if (x < 1) + fun_l21_n883(x) + else + fun_l21_n118(x) + end +end + +def fun_l20_n783(x) + if (x < 1) + fun_l21_n314(x) + else + fun_l21_n357(x) + end +end + +def fun_l20_n784(x) + if (x < 1) + fun_l21_n599(x) + else + fun_l21_n211(x) + end +end + +def fun_l20_n785(x) + if (x < 1) + fun_l21_n882(x) + else + fun_l21_n903(x) + end +end + +def fun_l20_n786(x) + if (x < 1) + fun_l21_n741(x) + else + fun_l21_n634(x) + end +end + +def fun_l20_n787(x) + if (x < 1) + fun_l21_n186(x) + else + fun_l21_n68(x) + end +end + +def fun_l20_n788(x) + if (x < 1) + fun_l21_n620(x) + else + fun_l21_n976(x) + end +end + +def fun_l20_n789(x) + if (x < 1) + fun_l21_n692(x) + else + fun_l21_n8(x) + end +end + +def fun_l20_n790(x) + if (x < 1) + fun_l21_n893(x) + else + fun_l21_n916(x) + end +end + +def fun_l20_n791(x) + if (x < 1) + fun_l21_n823(x) + else + fun_l21_n498(x) + end +end + +def fun_l20_n792(x) + if (x < 1) + fun_l21_n390(x) + else + fun_l21_n711(x) + end +end + +def fun_l20_n793(x) + if (x < 1) + fun_l21_n918(x) + else + fun_l21_n819(x) + end +end + +def fun_l20_n794(x) + if (x < 1) + fun_l21_n809(x) + else + fun_l21_n320(x) + end +end + +def fun_l20_n795(x) + if (x < 1) + fun_l21_n387(x) + else + fun_l21_n377(x) + end +end + +def fun_l20_n796(x) + if (x < 1) + fun_l21_n243(x) + else + fun_l21_n555(x) + end +end + +def fun_l20_n797(x) + if (x < 1) + fun_l21_n946(x) + else + fun_l21_n811(x) + end +end + +def fun_l20_n798(x) + if (x < 1) + fun_l21_n492(x) + else + fun_l21_n367(x) + end +end + +def fun_l20_n799(x) + if (x < 1) + fun_l21_n161(x) + else + fun_l21_n818(x) + end +end + +def fun_l20_n800(x) + if (x < 1) + fun_l21_n365(x) + else + fun_l21_n560(x) + end +end + +def fun_l20_n801(x) + if (x < 1) + fun_l21_n456(x) + else + fun_l21_n880(x) + end +end + +def fun_l20_n802(x) + if (x < 1) + fun_l21_n683(x) + else + fun_l21_n71(x) + end +end + +def fun_l20_n803(x) + if (x < 1) + fun_l21_n250(x) + else + fun_l21_n183(x) + end +end + +def fun_l20_n804(x) + if (x < 1) + fun_l21_n900(x) + else + fun_l21_n63(x) + end +end + +def fun_l20_n805(x) + if (x < 1) + fun_l21_n798(x) + else + fun_l21_n91(x) + end +end + +def fun_l20_n806(x) + if (x < 1) + fun_l21_n525(x) + else + fun_l21_n59(x) + end +end + +def fun_l20_n807(x) + if (x < 1) + fun_l21_n515(x) + else + fun_l21_n457(x) + end +end + +def fun_l20_n808(x) + if (x < 1) + fun_l21_n410(x) + else + fun_l21_n172(x) + end +end + +def fun_l20_n809(x) + if (x < 1) + fun_l21_n194(x) + else + fun_l21_n425(x) + end +end + +def fun_l20_n810(x) + if (x < 1) + fun_l21_n660(x) + else + fun_l21_n120(x) + end +end + +def fun_l20_n811(x) + if (x < 1) + fun_l21_n920(x) + else + fun_l21_n97(x) + end +end + +def fun_l20_n812(x) + if (x < 1) + fun_l21_n443(x) + else + fun_l21_n876(x) + end +end + +def fun_l20_n813(x) + if (x < 1) + fun_l21_n935(x) + else + fun_l21_n186(x) + end +end + +def fun_l20_n814(x) + if (x < 1) + fun_l21_n139(x) + else + fun_l21_n313(x) + end +end + +def fun_l20_n815(x) + if (x < 1) + fun_l21_n21(x) + else + fun_l21_n500(x) + end +end + +def fun_l20_n816(x) + if (x < 1) + fun_l21_n682(x) + else + fun_l21_n17(x) + end +end + +def fun_l20_n817(x) + if (x < 1) + fun_l21_n945(x) + else + fun_l21_n472(x) + end +end + +def fun_l20_n818(x) + if (x < 1) + fun_l21_n76(x) + else + fun_l21_n464(x) + end +end + +def fun_l20_n819(x) + if (x < 1) + fun_l21_n696(x) + else + fun_l21_n989(x) + end +end + +def fun_l20_n820(x) + if (x < 1) + fun_l21_n150(x) + else + fun_l21_n459(x) + end +end + +def fun_l20_n821(x) + if (x < 1) + fun_l21_n280(x) + else + fun_l21_n535(x) + end +end + +def fun_l20_n822(x) + if (x < 1) + fun_l21_n120(x) + else + fun_l21_n553(x) + end +end + +def fun_l20_n823(x) + if (x < 1) + fun_l21_n450(x) + else + fun_l21_n168(x) + end +end + +def fun_l20_n824(x) + if (x < 1) + fun_l21_n635(x) + else + fun_l21_n45(x) + end +end + +def fun_l20_n825(x) + if (x < 1) + fun_l21_n245(x) + else + fun_l21_n491(x) + end +end + +def fun_l20_n826(x) + if (x < 1) + fun_l21_n202(x) + else + fun_l21_n307(x) + end +end + +def fun_l20_n827(x) + if (x < 1) + fun_l21_n883(x) + else + fun_l21_n113(x) + end +end + +def fun_l20_n828(x) + if (x < 1) + fun_l21_n864(x) + else + fun_l21_n982(x) + end +end + +def fun_l20_n829(x) + if (x < 1) + fun_l21_n707(x) + else + fun_l21_n909(x) + end +end + +def fun_l20_n830(x) + if (x < 1) + fun_l21_n838(x) + else + fun_l21_n784(x) + end +end + +def fun_l20_n831(x) + if (x < 1) + fun_l21_n179(x) + else + fun_l21_n445(x) + end +end + +def fun_l20_n832(x) + if (x < 1) + fun_l21_n563(x) + else + fun_l21_n981(x) + end +end + +def fun_l20_n833(x) + if (x < 1) + fun_l21_n441(x) + else + fun_l21_n911(x) + end +end + +def fun_l20_n834(x) + if (x < 1) + fun_l21_n46(x) + else + fun_l21_n244(x) + end +end + +def fun_l20_n835(x) + if (x < 1) + fun_l21_n740(x) + else + fun_l21_n877(x) + end +end + +def fun_l20_n836(x) + if (x < 1) + fun_l21_n987(x) + else + fun_l21_n459(x) + end +end + +def fun_l20_n837(x) + if (x < 1) + fun_l21_n51(x) + else + fun_l21_n533(x) + end +end + +def fun_l20_n838(x) + if (x < 1) + fun_l21_n530(x) + else + fun_l21_n916(x) + end +end + +def fun_l20_n839(x) + if (x < 1) + fun_l21_n644(x) + else + fun_l21_n574(x) + end +end + +def fun_l20_n840(x) + if (x < 1) + fun_l21_n167(x) + else + fun_l21_n935(x) + end +end + +def fun_l20_n841(x) + if (x < 1) + fun_l21_n657(x) + else + fun_l21_n914(x) + end +end + +def fun_l20_n842(x) + if (x < 1) + fun_l21_n646(x) + else + fun_l21_n191(x) + end +end + +def fun_l20_n843(x) + if (x < 1) + fun_l21_n881(x) + else + fun_l21_n744(x) + end +end + +def fun_l20_n844(x) + if (x < 1) + fun_l21_n293(x) + else + fun_l21_n474(x) + end +end + +def fun_l20_n845(x) + if (x < 1) + fun_l21_n481(x) + else + fun_l21_n80(x) + end +end + +def fun_l20_n846(x) + if (x < 1) + fun_l21_n785(x) + else + fun_l21_n694(x) + end +end + +def fun_l20_n847(x) + if (x < 1) + fun_l21_n874(x) + else + fun_l21_n465(x) + end +end + +def fun_l20_n848(x) + if (x < 1) + fun_l21_n43(x) + else + fun_l21_n666(x) + end +end + +def fun_l20_n849(x) + if (x < 1) + fun_l21_n868(x) + else + fun_l21_n272(x) + end +end + +def fun_l20_n850(x) + if (x < 1) + fun_l21_n194(x) + else + fun_l21_n995(x) + end +end + +def fun_l20_n851(x) + if (x < 1) + fun_l21_n989(x) + else + fun_l21_n385(x) + end +end + +def fun_l20_n852(x) + if (x < 1) + fun_l21_n396(x) + else + fun_l21_n366(x) + end +end + +def fun_l20_n853(x) + if (x < 1) + fun_l21_n439(x) + else + fun_l21_n141(x) + end +end + +def fun_l20_n854(x) + if (x < 1) + fun_l21_n78(x) + else + fun_l21_n180(x) + end +end + +def fun_l20_n855(x) + if (x < 1) + fun_l21_n203(x) + else + fun_l21_n382(x) + end +end + +def fun_l20_n856(x) + if (x < 1) + fun_l21_n387(x) + else + fun_l21_n696(x) + end +end + +def fun_l20_n857(x) + if (x < 1) + fun_l21_n383(x) + else + fun_l21_n655(x) + end +end + +def fun_l20_n858(x) + if (x < 1) + fun_l21_n375(x) + else + fun_l21_n14(x) + end +end + +def fun_l20_n859(x) + if (x < 1) + fun_l21_n418(x) + else + fun_l21_n435(x) + end +end + +def fun_l20_n860(x) + if (x < 1) + fun_l21_n75(x) + else + fun_l21_n258(x) + end +end + +def fun_l20_n861(x) + if (x < 1) + fun_l21_n509(x) + else + fun_l21_n585(x) + end +end + +def fun_l20_n862(x) + if (x < 1) + fun_l21_n388(x) + else + fun_l21_n962(x) + end +end + +def fun_l20_n863(x) + if (x < 1) + fun_l21_n826(x) + else + fun_l21_n691(x) + end +end + +def fun_l20_n864(x) + if (x < 1) + fun_l21_n230(x) + else + fun_l21_n588(x) + end +end + +def fun_l20_n865(x) + if (x < 1) + fun_l21_n138(x) + else + fun_l21_n779(x) + end +end + +def fun_l20_n866(x) + if (x < 1) + fun_l21_n994(x) + else + fun_l21_n325(x) + end +end + +def fun_l20_n867(x) + if (x < 1) + fun_l21_n169(x) + else + fun_l21_n384(x) + end +end + +def fun_l20_n868(x) + if (x < 1) + fun_l21_n30(x) + else + fun_l21_n922(x) + end +end + +def fun_l20_n869(x) + if (x < 1) + fun_l21_n500(x) + else + fun_l21_n896(x) + end +end + +def fun_l20_n870(x) + if (x < 1) + fun_l21_n25(x) + else + fun_l21_n292(x) + end +end + +def fun_l20_n871(x) + if (x < 1) + fun_l21_n266(x) + else + fun_l21_n58(x) + end +end + +def fun_l20_n872(x) + if (x < 1) + fun_l21_n172(x) + else + fun_l21_n721(x) + end +end + +def fun_l20_n873(x) + if (x < 1) + fun_l21_n87(x) + else + fun_l21_n717(x) + end +end + +def fun_l20_n874(x) + if (x < 1) + fun_l21_n235(x) + else + fun_l21_n891(x) + end +end + +def fun_l20_n875(x) + if (x < 1) + fun_l21_n87(x) + else + fun_l21_n810(x) + end +end + +def fun_l20_n876(x) + if (x < 1) + fun_l21_n785(x) + else + fun_l21_n668(x) + end +end + +def fun_l20_n877(x) + if (x < 1) + fun_l21_n532(x) + else + fun_l21_n505(x) + end +end + +def fun_l20_n878(x) + if (x < 1) + fun_l21_n885(x) + else + fun_l21_n820(x) + end +end + +def fun_l20_n879(x) + if (x < 1) + fun_l21_n986(x) + else + fun_l21_n916(x) + end +end + +def fun_l20_n880(x) + if (x < 1) + fun_l21_n46(x) + else + fun_l21_n751(x) + end +end + +def fun_l20_n881(x) + if (x < 1) + fun_l21_n964(x) + else + fun_l21_n829(x) + end +end + +def fun_l20_n882(x) + if (x < 1) + fun_l21_n938(x) + else + fun_l21_n862(x) + end +end + +def fun_l20_n883(x) + if (x < 1) + fun_l21_n880(x) + else + fun_l21_n548(x) + end +end + +def fun_l20_n884(x) + if (x < 1) + fun_l21_n621(x) + else + fun_l21_n184(x) + end +end + +def fun_l20_n885(x) + if (x < 1) + fun_l21_n587(x) + else + fun_l21_n603(x) + end +end + +def fun_l20_n886(x) + if (x < 1) + fun_l21_n935(x) + else + fun_l21_n105(x) + end +end + +def fun_l20_n887(x) + if (x < 1) + fun_l21_n76(x) + else + fun_l21_n96(x) + end +end + +def fun_l20_n888(x) + if (x < 1) + fun_l21_n241(x) + else + fun_l21_n56(x) + end +end + +def fun_l20_n889(x) + if (x < 1) + fun_l21_n180(x) + else + fun_l21_n360(x) + end +end + +def fun_l20_n890(x) + if (x < 1) + fun_l21_n179(x) + else + fun_l21_n510(x) + end +end + +def fun_l20_n891(x) + if (x < 1) + fun_l21_n641(x) + else + fun_l21_n70(x) + end +end + +def fun_l20_n892(x) + if (x < 1) + fun_l21_n615(x) + else + fun_l21_n30(x) + end +end + +def fun_l20_n893(x) + if (x < 1) + fun_l21_n787(x) + else + fun_l21_n914(x) + end +end + +def fun_l20_n894(x) + if (x < 1) + fun_l21_n949(x) + else + fun_l21_n449(x) + end +end + +def fun_l20_n895(x) + if (x < 1) + fun_l21_n182(x) + else + fun_l21_n935(x) + end +end + +def fun_l20_n896(x) + if (x < 1) + fun_l21_n411(x) + else + fun_l21_n43(x) + end +end + +def fun_l20_n897(x) + if (x < 1) + fun_l21_n70(x) + else + fun_l21_n363(x) + end +end + +def fun_l20_n898(x) + if (x < 1) + fun_l21_n910(x) + else + fun_l21_n271(x) + end +end + +def fun_l20_n899(x) + if (x < 1) + fun_l21_n722(x) + else + fun_l21_n793(x) + end +end + +def fun_l20_n900(x) + if (x < 1) + fun_l21_n356(x) + else + fun_l21_n301(x) + end +end + +def fun_l20_n901(x) + if (x < 1) + fun_l21_n915(x) + else + fun_l21_n373(x) + end +end + +def fun_l20_n902(x) + if (x < 1) + fun_l21_n468(x) + else + fun_l21_n632(x) + end +end + +def fun_l20_n903(x) + if (x < 1) + fun_l21_n970(x) + else + fun_l21_n54(x) + end +end + +def fun_l20_n904(x) + if (x < 1) + fun_l21_n452(x) + else + fun_l21_n536(x) + end +end + +def fun_l20_n905(x) + if (x < 1) + fun_l21_n223(x) + else + fun_l21_n423(x) + end +end + +def fun_l20_n906(x) + if (x < 1) + fun_l21_n102(x) + else + fun_l21_n755(x) + end +end + +def fun_l20_n907(x) + if (x < 1) + fun_l21_n537(x) + else + fun_l21_n84(x) + end +end + +def fun_l20_n908(x) + if (x < 1) + fun_l21_n786(x) + else + fun_l21_n979(x) + end +end + +def fun_l20_n909(x) + if (x < 1) + fun_l21_n573(x) + else + fun_l21_n965(x) + end +end + +def fun_l20_n910(x) + if (x < 1) + fun_l21_n764(x) + else + fun_l21_n375(x) + end +end + +def fun_l20_n911(x) + if (x < 1) + fun_l21_n673(x) + else + fun_l21_n545(x) + end +end + +def fun_l20_n912(x) + if (x < 1) + fun_l21_n616(x) + else + fun_l21_n257(x) + end +end + +def fun_l20_n913(x) + if (x < 1) + fun_l21_n276(x) + else + fun_l21_n670(x) + end +end + +def fun_l20_n914(x) + if (x < 1) + fun_l21_n969(x) + else + fun_l21_n482(x) + end +end + +def fun_l20_n915(x) + if (x < 1) + fun_l21_n603(x) + else + fun_l21_n916(x) + end +end + +def fun_l20_n916(x) + if (x < 1) + fun_l21_n287(x) + else + fun_l21_n253(x) + end +end + +def fun_l20_n917(x) + if (x < 1) + fun_l21_n201(x) + else + fun_l21_n175(x) + end +end + +def fun_l20_n918(x) + if (x < 1) + fun_l21_n557(x) + else + fun_l21_n668(x) + end +end + +def fun_l20_n919(x) + if (x < 1) + fun_l21_n598(x) + else + fun_l21_n85(x) + end +end + +def fun_l20_n920(x) + if (x < 1) + fun_l21_n998(x) + else + fun_l21_n611(x) + end +end + +def fun_l20_n921(x) + if (x < 1) + fun_l21_n22(x) + else + fun_l21_n76(x) + end +end + +def fun_l20_n922(x) + if (x < 1) + fun_l21_n611(x) + else + fun_l21_n823(x) + end +end + +def fun_l20_n923(x) + if (x < 1) + fun_l21_n739(x) + else + fun_l21_n231(x) + end +end + +def fun_l20_n924(x) + if (x < 1) + fun_l21_n806(x) + else + fun_l21_n362(x) + end +end + +def fun_l20_n925(x) + if (x < 1) + fun_l21_n32(x) + else + fun_l21_n593(x) + end +end + +def fun_l20_n926(x) + if (x < 1) + fun_l21_n592(x) + else + fun_l21_n422(x) + end +end + +def fun_l20_n927(x) + if (x < 1) + fun_l21_n624(x) + else + fun_l21_n690(x) + end +end + +def fun_l20_n928(x) + if (x < 1) + fun_l21_n838(x) + else + fun_l21_n351(x) + end +end + +def fun_l20_n929(x) + if (x < 1) + fun_l21_n289(x) + else + fun_l21_n842(x) + end +end + +def fun_l20_n930(x) + if (x < 1) + fun_l21_n948(x) + else + fun_l21_n679(x) + end +end + +def fun_l20_n931(x) + if (x < 1) + fun_l21_n746(x) + else + fun_l21_n267(x) + end +end + +def fun_l20_n932(x) + if (x < 1) + fun_l21_n494(x) + else + fun_l21_n19(x) + end +end + +def fun_l20_n933(x) + if (x < 1) + fun_l21_n8(x) + else + fun_l21_n234(x) + end +end + +def fun_l20_n934(x) + if (x < 1) + fun_l21_n743(x) + else + fun_l21_n175(x) + end +end + +def fun_l20_n935(x) + if (x < 1) + fun_l21_n111(x) + else + fun_l21_n300(x) + end +end + +def fun_l20_n936(x) + if (x < 1) + fun_l21_n482(x) + else + fun_l21_n431(x) + end +end + +def fun_l20_n937(x) + if (x < 1) + fun_l21_n885(x) + else + fun_l21_n523(x) + end +end + +def fun_l20_n938(x) + if (x < 1) + fun_l21_n661(x) + else + fun_l21_n461(x) + end +end + +def fun_l20_n939(x) + if (x < 1) + fun_l21_n809(x) + else + fun_l21_n868(x) + end +end + +def fun_l20_n940(x) + if (x < 1) + fun_l21_n549(x) + else + fun_l21_n287(x) + end +end + +def fun_l20_n941(x) + if (x < 1) + fun_l21_n246(x) + else + fun_l21_n228(x) + end +end + +def fun_l20_n942(x) + if (x < 1) + fun_l21_n656(x) + else + fun_l21_n399(x) + end +end + +def fun_l20_n943(x) + if (x < 1) + fun_l21_n344(x) + else + fun_l21_n77(x) + end +end + +def fun_l20_n944(x) + if (x < 1) + fun_l21_n862(x) + else + fun_l21_n696(x) + end +end + +def fun_l20_n945(x) + if (x < 1) + fun_l21_n892(x) + else + fun_l21_n782(x) + end +end + +def fun_l20_n946(x) + if (x < 1) + fun_l21_n461(x) + else + fun_l21_n946(x) + end +end + +def fun_l20_n947(x) + if (x < 1) + fun_l21_n576(x) + else + fun_l21_n216(x) + end +end + +def fun_l20_n948(x) + if (x < 1) + fun_l21_n136(x) + else + fun_l21_n132(x) + end +end + +def fun_l20_n949(x) + if (x < 1) + fun_l21_n987(x) + else + fun_l21_n615(x) + end +end + +def fun_l20_n950(x) + if (x < 1) + fun_l21_n170(x) + else + fun_l21_n55(x) + end +end + +def fun_l20_n951(x) + if (x < 1) + fun_l21_n260(x) + else + fun_l21_n675(x) + end +end + +def fun_l20_n952(x) + if (x < 1) + fun_l21_n406(x) + else + fun_l21_n569(x) + end +end + +def fun_l20_n953(x) + if (x < 1) + fun_l21_n41(x) + else + fun_l21_n951(x) + end +end + +def fun_l20_n954(x) + if (x < 1) + fun_l21_n467(x) + else + fun_l21_n837(x) + end +end + +def fun_l20_n955(x) + if (x < 1) + fun_l21_n41(x) + else + fun_l21_n349(x) + end +end + +def fun_l20_n956(x) + if (x < 1) + fun_l21_n105(x) + else + fun_l21_n595(x) + end +end + +def fun_l20_n957(x) + if (x < 1) + fun_l21_n132(x) + else + fun_l21_n622(x) + end +end + +def fun_l20_n958(x) + if (x < 1) + fun_l21_n1(x) + else + fun_l21_n770(x) + end +end + +def fun_l20_n959(x) + if (x < 1) + fun_l21_n768(x) + else + fun_l21_n979(x) + end +end + +def fun_l20_n960(x) + if (x < 1) + fun_l21_n954(x) + else + fun_l21_n906(x) + end +end + +def fun_l20_n961(x) + if (x < 1) + fun_l21_n759(x) + else + fun_l21_n381(x) + end +end + +def fun_l20_n962(x) + if (x < 1) + fun_l21_n590(x) + else + fun_l21_n868(x) + end +end + +def fun_l20_n963(x) + if (x < 1) + fun_l21_n119(x) + else + fun_l21_n962(x) + end +end + +def fun_l20_n964(x) + if (x < 1) + fun_l21_n350(x) + else + fun_l21_n930(x) + end +end + +def fun_l20_n965(x) + if (x < 1) + fun_l21_n542(x) + else + fun_l21_n217(x) + end +end + +def fun_l20_n966(x) + if (x < 1) + fun_l21_n375(x) + else + fun_l21_n244(x) + end +end + +def fun_l20_n967(x) + if (x < 1) + fun_l21_n160(x) + else + fun_l21_n610(x) + end +end + +def fun_l20_n968(x) + if (x < 1) + fun_l21_n28(x) + else + fun_l21_n925(x) + end +end + +def fun_l20_n969(x) + if (x < 1) + fun_l21_n661(x) + else + fun_l21_n944(x) + end +end + +def fun_l20_n970(x) + if (x < 1) + fun_l21_n534(x) + else + fun_l21_n872(x) + end +end + +def fun_l20_n971(x) + if (x < 1) + fun_l21_n684(x) + else + fun_l21_n271(x) + end +end + +def fun_l20_n972(x) + if (x < 1) + fun_l21_n493(x) + else + fun_l21_n893(x) + end +end + +def fun_l20_n973(x) + if (x < 1) + fun_l21_n912(x) + else + fun_l21_n385(x) + end +end + +def fun_l20_n974(x) + if (x < 1) + fun_l21_n528(x) + else + fun_l21_n948(x) + end +end + +def fun_l20_n975(x) + if (x < 1) + fun_l21_n263(x) + else + fun_l21_n362(x) + end +end + +def fun_l20_n976(x) + if (x < 1) + fun_l21_n86(x) + else + fun_l21_n937(x) + end +end + +def fun_l20_n977(x) + if (x < 1) + fun_l21_n886(x) + else + fun_l21_n845(x) + end +end + +def fun_l20_n978(x) + if (x < 1) + fun_l21_n681(x) + else + fun_l21_n437(x) + end +end + +def fun_l20_n979(x) + if (x < 1) + fun_l21_n342(x) + else + fun_l21_n333(x) + end +end + +def fun_l20_n980(x) + if (x < 1) + fun_l21_n160(x) + else + fun_l21_n635(x) + end +end + +def fun_l20_n981(x) + if (x < 1) + fun_l21_n580(x) + else + fun_l21_n895(x) + end +end + +def fun_l20_n982(x) + if (x < 1) + fun_l21_n578(x) + else + fun_l21_n669(x) + end +end + +def fun_l20_n983(x) + if (x < 1) + fun_l21_n939(x) + else + fun_l21_n321(x) + end +end + +def fun_l20_n984(x) + if (x < 1) + fun_l21_n465(x) + else + fun_l21_n175(x) + end +end + +def fun_l20_n985(x) + if (x < 1) + fun_l21_n522(x) + else + fun_l21_n108(x) + end +end + +def fun_l20_n986(x) + if (x < 1) + fun_l21_n347(x) + else + fun_l21_n207(x) + end +end + +def fun_l20_n987(x) + if (x < 1) + fun_l21_n844(x) + else + fun_l21_n39(x) + end +end + +def fun_l20_n988(x) + if (x < 1) + fun_l21_n104(x) + else + fun_l21_n528(x) + end +end + +def fun_l20_n989(x) + if (x < 1) + fun_l21_n486(x) + else + fun_l21_n443(x) + end +end + +def fun_l20_n990(x) + if (x < 1) + fun_l21_n643(x) + else + fun_l21_n503(x) + end +end + +def fun_l20_n991(x) + if (x < 1) + fun_l21_n428(x) + else + fun_l21_n813(x) + end +end + +def fun_l20_n992(x) + if (x < 1) + fun_l21_n452(x) + else + fun_l21_n536(x) + end +end + +def fun_l20_n993(x) + if (x < 1) + fun_l21_n247(x) + else + fun_l21_n961(x) + end +end + +def fun_l20_n994(x) + if (x < 1) + fun_l21_n749(x) + else + fun_l21_n554(x) + end +end + +def fun_l20_n995(x) + if (x < 1) + fun_l21_n333(x) + else + fun_l21_n162(x) + end +end + +def fun_l20_n996(x) + if (x < 1) + fun_l21_n686(x) + else + fun_l21_n635(x) + end +end + +def fun_l20_n997(x) + if (x < 1) + fun_l21_n709(x) + else + fun_l21_n953(x) + end +end + +def fun_l20_n998(x) + if (x < 1) + fun_l21_n315(x) + else + fun_l21_n818(x) + end +end + +def fun_l20_n999(x) + if (x < 1) + fun_l21_n543(x) + else + fun_l21_n385(x) + end +end + +def fun_l21_n0(x) + if (x < 1) + fun_l22_n736(x) + else + fun_l22_n837(x) + end +end + +def fun_l21_n1(x) + if (x < 1) + fun_l22_n333(x) + else + fun_l22_n358(x) + end +end + +def fun_l21_n2(x) + if (x < 1) + fun_l22_n150(x) + else + fun_l22_n469(x) + end +end + +def fun_l21_n3(x) + if (x < 1) + fun_l22_n899(x) + else + fun_l22_n917(x) + end +end + +def fun_l21_n4(x) + if (x < 1) + fun_l22_n943(x) + else + fun_l22_n435(x) + end +end + +def fun_l21_n5(x) + if (x < 1) + fun_l22_n56(x) + else + fun_l22_n123(x) + end +end + +def fun_l21_n6(x) + if (x < 1) + fun_l22_n849(x) + else + fun_l22_n475(x) + end +end + +def fun_l21_n7(x) + if (x < 1) + fun_l22_n931(x) + else + fun_l22_n529(x) + end +end + +def fun_l21_n8(x) + if (x < 1) + fun_l22_n192(x) + else + fun_l22_n441(x) + end +end + +def fun_l21_n9(x) + if (x < 1) + fun_l22_n84(x) + else + fun_l22_n428(x) + end +end + +def fun_l21_n10(x) + if (x < 1) + fun_l22_n355(x) + else + fun_l22_n432(x) + end +end + +def fun_l21_n11(x) + if (x < 1) + fun_l22_n380(x) + else + fun_l22_n739(x) + end +end + +def fun_l21_n12(x) + if (x < 1) + fun_l22_n559(x) + else + fun_l22_n492(x) + end +end + +def fun_l21_n13(x) + if (x < 1) + fun_l22_n542(x) + else + fun_l22_n284(x) + end +end + +def fun_l21_n14(x) + if (x < 1) + fun_l22_n106(x) + else + fun_l22_n443(x) + end +end + +def fun_l21_n15(x) + if (x < 1) + fun_l22_n769(x) + else + fun_l22_n111(x) + end +end + +def fun_l21_n16(x) + if (x < 1) + fun_l22_n982(x) + else + fun_l22_n855(x) + end +end + +def fun_l21_n17(x) + if (x < 1) + fun_l22_n994(x) + else + fun_l22_n952(x) + end +end + +def fun_l21_n18(x) + if (x < 1) + fun_l22_n567(x) + else + fun_l22_n741(x) + end +end + +def fun_l21_n19(x) + if (x < 1) + fun_l22_n851(x) + else + fun_l22_n830(x) + end +end + +def fun_l21_n20(x) + if (x < 1) + fun_l22_n353(x) + else + fun_l22_n184(x) + end +end + +def fun_l21_n21(x) + if (x < 1) + fun_l22_n891(x) + else + fun_l22_n629(x) + end +end + +def fun_l21_n22(x) + if (x < 1) + fun_l22_n521(x) + else + fun_l22_n932(x) + end +end + +def fun_l21_n23(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n913(x) + end +end + +def fun_l21_n24(x) + if (x < 1) + fun_l22_n839(x) + else + fun_l22_n402(x) + end +end + +def fun_l21_n25(x) + if (x < 1) + fun_l22_n525(x) + else + fun_l22_n247(x) + end +end + +def fun_l21_n26(x) + if (x < 1) + fun_l22_n906(x) + else + fun_l22_n392(x) + end +end + +def fun_l21_n27(x) + if (x < 1) + fun_l22_n716(x) + else + fun_l22_n804(x) + end +end + +def fun_l21_n28(x) + if (x < 1) + fun_l22_n444(x) + else + fun_l22_n21(x) + end +end + +def fun_l21_n29(x) + if (x < 1) + fun_l22_n674(x) + else + fun_l22_n695(x) + end +end + +def fun_l21_n30(x) + if (x < 1) + fun_l22_n948(x) + else + fun_l22_n447(x) + end +end + +def fun_l21_n31(x) + if (x < 1) + fun_l22_n460(x) + else + fun_l22_n743(x) + end +end + +def fun_l21_n32(x) + if (x < 1) + fun_l22_n369(x) + else + fun_l22_n331(x) + end +end + +def fun_l21_n33(x) + if (x < 1) + fun_l22_n602(x) + else + fun_l22_n934(x) + end +end + +def fun_l21_n34(x) + if (x < 1) + fun_l22_n572(x) + else + fun_l22_n267(x) + end +end + +def fun_l21_n35(x) + if (x < 1) + fun_l22_n517(x) + else + fun_l22_n298(x) + end +end + +def fun_l21_n36(x) + if (x < 1) + fun_l22_n998(x) + else + fun_l22_n561(x) + end +end + +def fun_l21_n37(x) + if (x < 1) + fun_l22_n457(x) + else + fun_l22_n513(x) + end +end + +def fun_l21_n38(x) + if (x < 1) + fun_l22_n378(x) + else + fun_l22_n238(x) + end +end + +def fun_l21_n39(x) + if (x < 1) + fun_l22_n788(x) + else + fun_l22_n45(x) + end +end + +def fun_l21_n40(x) + if (x < 1) + fun_l22_n299(x) + else + fun_l22_n516(x) + end +end + +def fun_l21_n41(x) + if (x < 1) + fun_l22_n454(x) + else + fun_l22_n274(x) + end +end + +def fun_l21_n42(x) + if (x < 1) + fun_l22_n855(x) + else + fun_l22_n360(x) + end +end + +def fun_l21_n43(x) + if (x < 1) + fun_l22_n577(x) + else + fun_l22_n213(x) + end +end + +def fun_l21_n44(x) + if (x < 1) + fun_l22_n569(x) + else + fun_l22_n857(x) + end +end + +def fun_l21_n45(x) + if (x < 1) + fun_l22_n667(x) + else + fun_l22_n285(x) + end +end + +def fun_l21_n46(x) + if (x < 1) + fun_l22_n915(x) + else + fun_l22_n232(x) + end +end + +def fun_l21_n47(x) + if (x < 1) + fun_l22_n124(x) + else + fun_l22_n708(x) + end +end + +def fun_l21_n48(x) + if (x < 1) + fun_l22_n184(x) + else + fun_l22_n272(x) + end +end + +def fun_l21_n49(x) + if (x < 1) + fun_l22_n376(x) + else + fun_l22_n138(x) + end +end + +def fun_l21_n50(x) + if (x < 1) + fun_l22_n897(x) + else + fun_l22_n857(x) + end +end + +def fun_l21_n51(x) + if (x < 1) + fun_l22_n335(x) + else + fun_l22_n614(x) + end +end + +def fun_l21_n52(x) + if (x < 1) + fun_l22_n921(x) + else + fun_l22_n109(x) + end +end + +def fun_l21_n53(x) + if (x < 1) + fun_l22_n27(x) + else + fun_l22_n609(x) + end +end + +def fun_l21_n54(x) + if (x < 1) + fun_l22_n831(x) + else + fun_l22_n769(x) + end +end + +def fun_l21_n55(x) + if (x < 1) + fun_l22_n936(x) + else + fun_l22_n250(x) + end +end + +def fun_l21_n56(x) + if (x < 1) + fun_l22_n261(x) + else + fun_l22_n142(x) + end +end + +def fun_l21_n57(x) + if (x < 1) + fun_l22_n721(x) + else + fun_l22_n604(x) + end +end + +def fun_l21_n58(x) + if (x < 1) + fun_l22_n760(x) + else + fun_l22_n545(x) + end +end + +def fun_l21_n59(x) + if (x < 1) + fun_l22_n934(x) + else + fun_l22_n110(x) + end +end + +def fun_l21_n60(x) + if (x < 1) + fun_l22_n422(x) + else + fun_l22_n31(x) + end +end + +def fun_l21_n61(x) + if (x < 1) + fun_l22_n776(x) + else + fun_l22_n251(x) + end +end + +def fun_l21_n62(x) + if (x < 1) + fun_l22_n76(x) + else + fun_l22_n930(x) + end +end + +def fun_l21_n63(x) + if (x < 1) + fun_l22_n331(x) + else + fun_l22_n550(x) + end +end + +def fun_l21_n64(x) + if (x < 1) + fun_l22_n845(x) + else + fun_l22_n62(x) + end +end + +def fun_l21_n65(x) + if (x < 1) + fun_l22_n887(x) + else + fun_l22_n784(x) + end +end + +def fun_l21_n66(x) + if (x < 1) + fun_l22_n353(x) + else + fun_l22_n918(x) + end +end + +def fun_l21_n67(x) + if (x < 1) + fun_l22_n682(x) + else + fun_l22_n840(x) + end +end + +def fun_l21_n68(x) + if (x < 1) + fun_l22_n966(x) + else + fun_l22_n187(x) + end +end + +def fun_l21_n69(x) + if (x < 1) + fun_l22_n424(x) + else + fun_l22_n674(x) + end +end + +def fun_l21_n70(x) + if (x < 1) + fun_l22_n530(x) + else + fun_l22_n148(x) + end +end + +def fun_l21_n71(x) + if (x < 1) + fun_l22_n616(x) + else + fun_l22_n945(x) + end +end + +def fun_l21_n72(x) + if (x < 1) + fun_l22_n634(x) + else + fun_l22_n945(x) + end +end + +def fun_l21_n73(x) + if (x < 1) + fun_l22_n153(x) + else + fun_l22_n657(x) + end +end + +def fun_l21_n74(x) + if (x < 1) + fun_l22_n284(x) + else + fun_l22_n83(x) + end +end + +def fun_l21_n75(x) + if (x < 1) + fun_l22_n292(x) + else + fun_l22_n440(x) + end +end + +def fun_l21_n76(x) + if (x < 1) + fun_l22_n932(x) + else + fun_l22_n29(x) + end +end + +def fun_l21_n77(x) + if (x < 1) + fun_l22_n292(x) + else + fun_l22_n866(x) + end +end + +def fun_l21_n78(x) + if (x < 1) + fun_l22_n822(x) + else + fun_l22_n838(x) + end +end + +def fun_l21_n79(x) + if (x < 1) + fun_l22_n297(x) + else + fun_l22_n677(x) + end +end + +def fun_l21_n80(x) + if (x < 1) + fun_l22_n540(x) + else + fun_l22_n975(x) + end +end + +def fun_l21_n81(x) + if (x < 1) + fun_l22_n375(x) + else + fun_l22_n735(x) + end +end + +def fun_l21_n82(x) + if (x < 1) + fun_l22_n549(x) + else + fun_l22_n844(x) + end +end + +def fun_l21_n83(x) + if (x < 1) + fun_l22_n763(x) + else + fun_l22_n863(x) + end +end + +def fun_l21_n84(x) + if (x < 1) + fun_l22_n993(x) + else + fun_l22_n155(x) + end +end + +def fun_l21_n85(x) + if (x < 1) + fun_l22_n751(x) + else + fun_l22_n264(x) + end +end + +def fun_l21_n86(x) + if (x < 1) + fun_l22_n517(x) + else + fun_l22_n752(x) + end +end + +def fun_l21_n87(x) + if (x < 1) + fun_l22_n477(x) + else + fun_l22_n486(x) + end +end + +def fun_l21_n88(x) + if (x < 1) + fun_l22_n220(x) + else + fun_l22_n4(x) + end +end + +def fun_l21_n89(x) + if (x < 1) + fun_l22_n678(x) + else + fun_l22_n692(x) + end +end + +def fun_l21_n90(x) + if (x < 1) + fun_l22_n75(x) + else + fun_l22_n306(x) + end +end + +def fun_l21_n91(x) + if (x < 1) + fun_l22_n460(x) + else + fun_l22_n514(x) + end +end + +def fun_l21_n92(x) + if (x < 1) + fun_l22_n446(x) + else + fun_l22_n201(x) + end +end + +def fun_l21_n93(x) + if (x < 1) + fun_l22_n872(x) + else + fun_l22_n611(x) + end +end + +def fun_l21_n94(x) + if (x < 1) + fun_l22_n809(x) + else + fun_l22_n91(x) + end +end + +def fun_l21_n95(x) + if (x < 1) + fun_l22_n565(x) + else + fun_l22_n968(x) + end +end + +def fun_l21_n96(x) + if (x < 1) + fun_l22_n765(x) + else + fun_l22_n622(x) + end +end + +def fun_l21_n97(x) + if (x < 1) + fun_l22_n856(x) + else + fun_l22_n923(x) + end +end + +def fun_l21_n98(x) + if (x < 1) + fun_l22_n14(x) + else + fun_l22_n742(x) + end +end + +def fun_l21_n99(x) + if (x < 1) + fun_l22_n214(x) + else + fun_l22_n118(x) + end +end + +def fun_l21_n100(x) + if (x < 1) + fun_l22_n992(x) + else + fun_l22_n610(x) + end +end + +def fun_l21_n101(x) + if (x < 1) + fun_l22_n603(x) + else + fun_l22_n208(x) + end +end + +def fun_l21_n102(x) + if (x < 1) + fun_l22_n647(x) + else + fun_l22_n753(x) + end +end + +def fun_l21_n103(x) + if (x < 1) + fun_l22_n952(x) + else + fun_l22_n25(x) + end +end + +def fun_l21_n104(x) + if (x < 1) + fun_l22_n635(x) + else + fun_l22_n381(x) + end +end + +def fun_l21_n105(x) + if (x < 1) + fun_l22_n258(x) + else + fun_l22_n346(x) + end +end + +def fun_l21_n106(x) + if (x < 1) + fun_l22_n732(x) + else + fun_l22_n851(x) + end +end + +def fun_l21_n107(x) + if (x < 1) + fun_l22_n67(x) + else + fun_l22_n80(x) + end +end + +def fun_l21_n108(x) + if (x < 1) + fun_l22_n237(x) + else + fun_l22_n600(x) + end +end + +def fun_l21_n109(x) + if (x < 1) + fun_l22_n448(x) + else + fun_l22_n768(x) + end +end + +def fun_l21_n110(x) + if (x < 1) + fun_l22_n52(x) + else + fun_l22_n849(x) + end +end + +def fun_l21_n111(x) + if (x < 1) + fun_l22_n471(x) + else + fun_l22_n400(x) + end +end + +def fun_l21_n112(x) + if (x < 1) + fun_l22_n655(x) + else + fun_l22_n691(x) + end +end + +def fun_l21_n113(x) + if (x < 1) + fun_l22_n325(x) + else + fun_l22_n936(x) + end +end + +def fun_l21_n114(x) + if (x < 1) + fun_l22_n693(x) + else + fun_l22_n118(x) + end +end + +def fun_l21_n115(x) + if (x < 1) + fun_l22_n881(x) + else + fun_l22_n167(x) + end +end + +def fun_l21_n116(x) + if (x < 1) + fun_l22_n958(x) + else + fun_l22_n36(x) + end +end + +def fun_l21_n117(x) + if (x < 1) + fun_l22_n233(x) + else + fun_l22_n649(x) + end +end + +def fun_l21_n118(x) + if (x < 1) + fun_l22_n847(x) + else + fun_l22_n544(x) + end +end + +def fun_l21_n119(x) + if (x < 1) + fun_l22_n392(x) + else + fun_l22_n2(x) + end +end + +def fun_l21_n120(x) + if (x < 1) + fun_l22_n750(x) + else + fun_l22_n481(x) + end +end + +def fun_l21_n121(x) + if (x < 1) + fun_l22_n124(x) + else + fun_l22_n769(x) + end +end + +def fun_l21_n122(x) + if (x < 1) + fun_l22_n483(x) + else + fun_l22_n147(x) + end +end + +def fun_l21_n123(x) + if (x < 1) + fun_l22_n543(x) + else + fun_l22_n454(x) + end +end + +def fun_l21_n124(x) + if (x < 1) + fun_l22_n24(x) + else + fun_l22_n815(x) + end +end + +def fun_l21_n125(x) + if (x < 1) + fun_l22_n315(x) + else + fun_l22_n263(x) + end +end + +def fun_l21_n126(x) + if (x < 1) + fun_l22_n934(x) + else + fun_l22_n351(x) + end +end + +def fun_l21_n127(x) + if (x < 1) + fun_l22_n982(x) + else + fun_l22_n755(x) + end +end + +def fun_l21_n128(x) + if (x < 1) + fun_l22_n146(x) + else + fun_l22_n345(x) + end +end + +def fun_l21_n129(x) + if (x < 1) + fun_l22_n85(x) + else + fun_l22_n356(x) + end +end + +def fun_l21_n130(x) + if (x < 1) + fun_l22_n987(x) + else + fun_l22_n103(x) + end +end + +def fun_l21_n131(x) + if (x < 1) + fun_l22_n413(x) + else + fun_l22_n260(x) + end +end + +def fun_l21_n132(x) + if (x < 1) + fun_l22_n615(x) + else + fun_l22_n742(x) + end +end + +def fun_l21_n133(x) + if (x < 1) + fun_l22_n836(x) + else + fun_l22_n214(x) + end +end + +def fun_l21_n134(x) + if (x < 1) + fun_l22_n85(x) + else + fun_l22_n916(x) + end +end + +def fun_l21_n135(x) + if (x < 1) + fun_l22_n21(x) + else + fun_l22_n902(x) + end +end + +def fun_l21_n136(x) + if (x < 1) + fun_l22_n842(x) + else + fun_l22_n475(x) + end +end + +def fun_l21_n137(x) + if (x < 1) + fun_l22_n573(x) + else + fun_l22_n108(x) + end +end + +def fun_l21_n138(x) + if (x < 1) + fun_l22_n394(x) + else + fun_l22_n783(x) + end +end + +def fun_l21_n139(x) + if (x < 1) + fun_l22_n514(x) + else + fun_l22_n37(x) + end +end + +def fun_l21_n140(x) + if (x < 1) + fun_l22_n358(x) + else + fun_l22_n768(x) + end +end + +def fun_l21_n141(x) + if (x < 1) + fun_l22_n201(x) + else + fun_l22_n981(x) + end +end + +def fun_l21_n142(x) + if (x < 1) + fun_l22_n371(x) + else + fun_l22_n66(x) + end +end + +def fun_l21_n143(x) + if (x < 1) + fun_l22_n41(x) + else + fun_l22_n869(x) + end +end + +def fun_l21_n144(x) + if (x < 1) + fun_l22_n961(x) + else + fun_l22_n488(x) + end +end + +def fun_l21_n145(x) + if (x < 1) + fun_l22_n769(x) + else + fun_l22_n82(x) + end +end + +def fun_l21_n146(x) + if (x < 1) + fun_l22_n700(x) + else + fun_l22_n276(x) + end +end + +def fun_l21_n147(x) + if (x < 1) + fun_l22_n439(x) + else + fun_l22_n654(x) + end +end + +def fun_l21_n148(x) + if (x < 1) + fun_l22_n130(x) + else + fun_l22_n825(x) + end +end + +def fun_l21_n149(x) + if (x < 1) + fun_l22_n174(x) + else + fun_l22_n907(x) + end +end + +def fun_l21_n150(x) + if (x < 1) + fun_l22_n386(x) + else + fun_l22_n760(x) + end +end + +def fun_l21_n151(x) + if (x < 1) + fun_l22_n460(x) + else + fun_l22_n403(x) + end +end + +def fun_l21_n152(x) + if (x < 1) + fun_l22_n861(x) + else + fun_l22_n832(x) + end +end + +def fun_l21_n153(x) + if (x < 1) + fun_l22_n564(x) + else + fun_l22_n604(x) + end +end + +def fun_l21_n154(x) + if (x < 1) + fun_l22_n402(x) + else + fun_l22_n999(x) + end +end + +def fun_l21_n155(x) + if (x < 1) + fun_l22_n645(x) + else + fun_l22_n807(x) + end +end + +def fun_l21_n156(x) + if (x < 1) + fun_l22_n709(x) + else + fun_l22_n930(x) + end +end + +def fun_l21_n157(x) + if (x < 1) + fun_l22_n353(x) + else + fun_l22_n462(x) + end +end + +def fun_l21_n158(x) + if (x < 1) + fun_l22_n697(x) + else + fun_l22_n463(x) + end +end + +def fun_l21_n159(x) + if (x < 1) + fun_l22_n690(x) + else + fun_l22_n309(x) + end +end + +def fun_l21_n160(x) + if (x < 1) + fun_l22_n889(x) + else + fun_l22_n326(x) + end +end + +def fun_l21_n161(x) + if (x < 1) + fun_l22_n952(x) + else + fun_l22_n225(x) + end +end + +def fun_l21_n162(x) + if (x < 1) + fun_l22_n345(x) + else + fun_l22_n168(x) + end +end + +def fun_l21_n163(x) + if (x < 1) + fun_l22_n437(x) + else + fun_l22_n494(x) + end +end + +def fun_l21_n164(x) + if (x < 1) + fun_l22_n151(x) + else + fun_l22_n846(x) + end +end + +def fun_l21_n165(x) + if (x < 1) + fun_l22_n324(x) + else + fun_l22_n999(x) + end +end + +def fun_l21_n166(x) + if (x < 1) + fun_l22_n232(x) + else + fun_l22_n473(x) + end +end + +def fun_l21_n167(x) + if (x < 1) + fun_l22_n934(x) + else + fun_l22_n437(x) + end +end + +def fun_l21_n168(x) + if (x < 1) + fun_l22_n738(x) + else + fun_l22_n410(x) + end +end + +def fun_l21_n169(x) + if (x < 1) + fun_l22_n686(x) + else + fun_l22_n108(x) + end +end + +def fun_l21_n170(x) + if (x < 1) + fun_l22_n595(x) + else + fun_l22_n935(x) + end +end + +def fun_l21_n171(x) + if (x < 1) + fun_l22_n723(x) + else + fun_l22_n478(x) + end +end + +def fun_l21_n172(x) + if (x < 1) + fun_l22_n610(x) + else + fun_l22_n709(x) + end +end + +def fun_l21_n173(x) + if (x < 1) + fun_l22_n539(x) + else + fun_l22_n17(x) + end +end + +def fun_l21_n174(x) + if (x < 1) + fun_l22_n612(x) + else + fun_l22_n235(x) + end +end + +def fun_l21_n175(x) + if (x < 1) + fun_l22_n835(x) + else + fun_l22_n138(x) + end +end + +def fun_l21_n176(x) + if (x < 1) + fun_l22_n997(x) + else + fun_l22_n123(x) + end +end + +def fun_l21_n177(x) + if (x < 1) + fun_l22_n97(x) + else + fun_l22_n997(x) + end +end + +def fun_l21_n178(x) + if (x < 1) + fun_l22_n842(x) + else + fun_l22_n925(x) + end +end + +def fun_l21_n179(x) + if (x < 1) + fun_l22_n159(x) + else + fun_l22_n412(x) + end +end + +def fun_l21_n180(x) + if (x < 1) + fun_l22_n109(x) + else + fun_l22_n691(x) + end +end + +def fun_l21_n181(x) + if (x < 1) + fun_l22_n315(x) + else + fun_l22_n127(x) + end +end + +def fun_l21_n182(x) + if (x < 1) + fun_l22_n220(x) + else + fun_l22_n143(x) + end +end + +def fun_l21_n183(x) + if (x < 1) + fun_l22_n493(x) + else + fun_l22_n895(x) + end +end + +def fun_l21_n184(x) + if (x < 1) + fun_l22_n667(x) + else + fun_l22_n675(x) + end +end + +def fun_l21_n185(x) + if (x < 1) + fun_l22_n995(x) + else + fun_l22_n4(x) + end +end + +def fun_l21_n186(x) + if (x < 1) + fun_l22_n210(x) + else + fun_l22_n690(x) + end +end + +def fun_l21_n187(x) + if (x < 1) + fun_l22_n413(x) + else + fun_l22_n227(x) + end +end + +def fun_l21_n188(x) + if (x < 1) + fun_l22_n562(x) + else + fun_l22_n591(x) + end +end + +def fun_l21_n189(x) + if (x < 1) + fun_l22_n171(x) + else + fun_l22_n891(x) + end +end + +def fun_l21_n190(x) + if (x < 1) + fun_l22_n207(x) + else + fun_l22_n401(x) + end +end + +def fun_l21_n191(x) + if (x < 1) + fun_l22_n703(x) + else + fun_l22_n604(x) + end +end + +def fun_l21_n192(x) + if (x < 1) + fun_l22_n772(x) + else + fun_l22_n321(x) + end +end + +def fun_l21_n193(x) + if (x < 1) + fun_l22_n576(x) + else + fun_l22_n273(x) + end +end + +def fun_l21_n194(x) + if (x < 1) + fun_l22_n897(x) + else + fun_l22_n624(x) + end +end + +def fun_l21_n195(x) + if (x < 1) + fun_l22_n909(x) + else + fun_l22_n216(x) + end +end + +def fun_l21_n196(x) + if (x < 1) + fun_l22_n904(x) + else + fun_l22_n618(x) + end +end + +def fun_l21_n197(x) + if (x < 1) + fun_l22_n410(x) + else + fun_l22_n926(x) + end +end + +def fun_l21_n198(x) + if (x < 1) + fun_l22_n884(x) + else + fun_l22_n174(x) + end +end + +def fun_l21_n199(x) + if (x < 1) + fun_l22_n407(x) + else + fun_l22_n270(x) + end +end + +def fun_l21_n200(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n2(x) + end +end + +def fun_l21_n201(x) + if (x < 1) + fun_l22_n143(x) + else + fun_l22_n93(x) + end +end + +def fun_l21_n202(x) + if (x < 1) + fun_l22_n397(x) + else + fun_l22_n424(x) + end +end + +def fun_l21_n203(x) + if (x < 1) + fun_l22_n183(x) + else + fun_l22_n258(x) + end +end + +def fun_l21_n204(x) + if (x < 1) + fun_l22_n12(x) + else + fun_l22_n50(x) + end +end + +def fun_l21_n205(x) + if (x < 1) + fun_l22_n488(x) + else + fun_l22_n148(x) + end +end + +def fun_l21_n206(x) + if (x < 1) + fun_l22_n516(x) + else + fun_l22_n87(x) + end +end + +def fun_l21_n207(x) + if (x < 1) + fun_l22_n810(x) + else + fun_l22_n773(x) + end +end + +def fun_l21_n208(x) + if (x < 1) + fun_l22_n508(x) + else + fun_l22_n898(x) + end +end + +def fun_l21_n209(x) + if (x < 1) + fun_l22_n188(x) + else + fun_l22_n815(x) + end +end + +def fun_l21_n210(x) + if (x < 1) + fun_l22_n86(x) + else + fun_l22_n615(x) + end +end + +def fun_l21_n211(x) + if (x < 1) + fun_l22_n589(x) + else + fun_l22_n774(x) + end +end + +def fun_l21_n212(x) + if (x < 1) + fun_l22_n926(x) + else + fun_l22_n14(x) + end +end + +def fun_l21_n213(x) + if (x < 1) + fun_l22_n104(x) + else + fun_l22_n723(x) + end +end + +def fun_l21_n214(x) + if (x < 1) + fun_l22_n699(x) + else + fun_l22_n775(x) + end +end + +def fun_l21_n215(x) + if (x < 1) + fun_l22_n941(x) + else + fun_l22_n997(x) + end +end + +def fun_l21_n216(x) + if (x < 1) + fun_l22_n182(x) + else + fun_l22_n409(x) + end +end + +def fun_l21_n217(x) + if (x < 1) + fun_l22_n410(x) + else + fun_l22_n807(x) + end +end + +def fun_l21_n218(x) + if (x < 1) + fun_l22_n787(x) + else + fun_l22_n143(x) + end +end + +def fun_l21_n219(x) + if (x < 1) + fun_l22_n515(x) + else + fun_l22_n558(x) + end +end + +def fun_l21_n220(x) + if (x < 1) + fun_l22_n22(x) + else + fun_l22_n37(x) + end +end + +def fun_l21_n221(x) + if (x < 1) + fun_l22_n366(x) + else + fun_l22_n63(x) + end +end + +def fun_l21_n222(x) + if (x < 1) + fun_l22_n846(x) + else + fun_l22_n655(x) + end +end + +def fun_l21_n223(x) + if (x < 1) + fun_l22_n946(x) + else + fun_l22_n587(x) + end +end + +def fun_l21_n224(x) + if (x < 1) + fun_l22_n841(x) + else + fun_l22_n874(x) + end +end + +def fun_l21_n225(x) + if (x < 1) + fun_l22_n19(x) + else + fun_l22_n142(x) + end +end + +def fun_l21_n226(x) + if (x < 1) + fun_l22_n939(x) + else + fun_l22_n214(x) + end +end + +def fun_l21_n227(x) + if (x < 1) + fun_l22_n900(x) + else + fun_l22_n673(x) + end +end + +def fun_l21_n228(x) + if (x < 1) + fun_l22_n784(x) + else + fun_l22_n258(x) + end +end + +def fun_l21_n229(x) + if (x < 1) + fun_l22_n553(x) + else + fun_l22_n253(x) + end +end + +def fun_l21_n230(x) + if (x < 1) + fun_l22_n927(x) + else + fun_l22_n9(x) + end +end + +def fun_l21_n231(x) + if (x < 1) + fun_l22_n822(x) + else + fun_l22_n870(x) + end +end + +def fun_l21_n232(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n185(x) + end +end + +def fun_l21_n233(x) + if (x < 1) + fun_l22_n691(x) + else + fun_l22_n613(x) + end +end + +def fun_l21_n234(x) + if (x < 1) + fun_l22_n995(x) + else + fun_l22_n73(x) + end +end + +def fun_l21_n235(x) + if (x < 1) + fun_l22_n250(x) + else + fun_l22_n356(x) + end +end + +def fun_l21_n236(x) + if (x < 1) + fun_l22_n531(x) + else + fun_l22_n335(x) + end +end + +def fun_l21_n237(x) + if (x < 1) + fun_l22_n376(x) + else + fun_l22_n732(x) + end +end + +def fun_l21_n238(x) + if (x < 1) + fun_l22_n293(x) + else + fun_l22_n886(x) + end +end + +def fun_l21_n239(x) + if (x < 1) + fun_l22_n266(x) + else + fun_l22_n820(x) + end +end + +def fun_l21_n240(x) + if (x < 1) + fun_l22_n450(x) + else + fun_l22_n418(x) + end +end + +def fun_l21_n241(x) + if (x < 1) + fun_l22_n902(x) + else + fun_l22_n991(x) + end +end + +def fun_l21_n242(x) + if (x < 1) + fun_l22_n521(x) + else + fun_l22_n516(x) + end +end + +def fun_l21_n243(x) + if (x < 1) + fun_l22_n97(x) + else + fun_l22_n388(x) + end +end + +def fun_l21_n244(x) + if (x < 1) + fun_l22_n596(x) + else + fun_l22_n758(x) + end +end + +def fun_l21_n245(x) + if (x < 1) + fun_l22_n370(x) + else + fun_l22_n747(x) + end +end + +def fun_l21_n246(x) + if (x < 1) + fun_l22_n73(x) + else + fun_l22_n84(x) + end +end + +def fun_l21_n247(x) + if (x < 1) + fun_l22_n489(x) + else + fun_l22_n166(x) + end +end + +def fun_l21_n248(x) + if (x < 1) + fun_l22_n419(x) + else + fun_l22_n698(x) + end +end + +def fun_l21_n249(x) + if (x < 1) + fun_l22_n330(x) + else + fun_l22_n995(x) + end +end + +def fun_l21_n250(x) + if (x < 1) + fun_l22_n443(x) + else + fun_l22_n341(x) + end +end + +def fun_l21_n251(x) + if (x < 1) + fun_l22_n442(x) + else + fun_l22_n311(x) + end +end + +def fun_l21_n252(x) + if (x < 1) + fun_l22_n60(x) + else + fun_l22_n399(x) + end +end + +def fun_l21_n253(x) + if (x < 1) + fun_l22_n831(x) + else + fun_l22_n245(x) + end +end + +def fun_l21_n254(x) + if (x < 1) + fun_l22_n946(x) + else + fun_l22_n205(x) + end +end + +def fun_l21_n255(x) + if (x < 1) + fun_l22_n499(x) + else + fun_l22_n476(x) + end +end + +def fun_l21_n256(x) + if (x < 1) + fun_l22_n841(x) + else + fun_l22_n70(x) + end +end + +def fun_l21_n257(x) + if (x < 1) + fun_l22_n289(x) + else + fun_l22_n329(x) + end +end + +def fun_l21_n258(x) + if (x < 1) + fun_l22_n149(x) + else + fun_l22_n270(x) + end +end + +def fun_l21_n259(x) + if (x < 1) + fun_l22_n569(x) + else + fun_l22_n972(x) + end +end + +def fun_l21_n260(x) + if (x < 1) + fun_l22_n313(x) + else + fun_l22_n573(x) + end +end + +def fun_l21_n261(x) + if (x < 1) + fun_l22_n458(x) + else + fun_l22_n964(x) + end +end + +def fun_l21_n262(x) + if (x < 1) + fun_l22_n308(x) + else + fun_l22_n825(x) + end +end + +def fun_l21_n263(x) + if (x < 1) + fun_l22_n810(x) + else + fun_l22_n864(x) + end +end + +def fun_l21_n264(x) + if (x < 1) + fun_l22_n52(x) + else + fun_l22_n486(x) + end +end + +def fun_l21_n265(x) + if (x < 1) + fun_l22_n520(x) + else + fun_l22_n758(x) + end +end + +def fun_l21_n266(x) + if (x < 1) + fun_l22_n954(x) + else + fun_l22_n819(x) + end +end + +def fun_l21_n267(x) + if (x < 1) + fun_l22_n226(x) + else + fun_l22_n893(x) + end +end + +def fun_l21_n268(x) + if (x < 1) + fun_l22_n854(x) + else + fun_l22_n281(x) + end +end + +def fun_l21_n269(x) + if (x < 1) + fun_l22_n354(x) + else + fun_l22_n296(x) + end +end + +def fun_l21_n270(x) + if (x < 1) + fun_l22_n970(x) + else + fun_l22_n898(x) + end +end + +def fun_l21_n271(x) + if (x < 1) + fun_l22_n769(x) + else + fun_l22_n94(x) + end +end + +def fun_l21_n272(x) + if (x < 1) + fun_l22_n100(x) + else + fun_l22_n830(x) + end +end + +def fun_l21_n273(x) + if (x < 1) + fun_l22_n514(x) + else + fun_l22_n522(x) + end +end + +def fun_l21_n274(x) + if (x < 1) + fun_l22_n897(x) + else + fun_l22_n260(x) + end +end + +def fun_l21_n275(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n125(x) + end +end + +def fun_l21_n276(x) + if (x < 1) + fun_l22_n262(x) + else + fun_l22_n617(x) + end +end + +def fun_l21_n277(x) + if (x < 1) + fun_l22_n84(x) + else + fun_l22_n483(x) + end +end + +def fun_l21_n278(x) + if (x < 1) + fun_l22_n657(x) + else + fun_l22_n10(x) + end +end + +def fun_l21_n279(x) + if (x < 1) + fun_l22_n142(x) + else + fun_l22_n666(x) + end +end + +def fun_l21_n280(x) + if (x < 1) + fun_l22_n824(x) + else + fun_l22_n408(x) + end +end + +def fun_l21_n281(x) + if (x < 1) + fun_l22_n39(x) + else + fun_l22_n225(x) + end +end + +def fun_l21_n282(x) + if (x < 1) + fun_l22_n93(x) + else + fun_l22_n410(x) + end +end + +def fun_l21_n283(x) + if (x < 1) + fun_l22_n294(x) + else + fun_l22_n268(x) + end +end + +def fun_l21_n284(x) + if (x < 1) + fun_l22_n636(x) + else + fun_l22_n767(x) + end +end + +def fun_l21_n285(x) + if (x < 1) + fun_l22_n181(x) + else + fun_l22_n317(x) + end +end + +def fun_l21_n286(x) + if (x < 1) + fun_l22_n208(x) + else + fun_l22_n803(x) + end +end + +def fun_l21_n287(x) + if (x < 1) + fun_l22_n910(x) + else + fun_l22_n872(x) + end +end + +def fun_l21_n288(x) + if (x < 1) + fun_l22_n771(x) + else + fun_l22_n858(x) + end +end + +def fun_l21_n289(x) + if (x < 1) + fun_l22_n109(x) + else + fun_l22_n577(x) + end +end + +def fun_l21_n290(x) + if (x < 1) + fun_l22_n474(x) + else + fun_l22_n289(x) + end +end + +def fun_l21_n291(x) + if (x < 1) + fun_l22_n55(x) + else + fun_l22_n448(x) + end +end + +def fun_l21_n292(x) + if (x < 1) + fun_l22_n644(x) + else + fun_l22_n958(x) + end +end + +def fun_l21_n293(x) + if (x < 1) + fun_l22_n775(x) + else + fun_l22_n131(x) + end +end + +def fun_l21_n294(x) + if (x < 1) + fun_l22_n950(x) + else + fun_l22_n216(x) + end +end + +def fun_l21_n295(x) + if (x < 1) + fun_l22_n258(x) + else + fun_l22_n919(x) + end +end + +def fun_l21_n296(x) + if (x < 1) + fun_l22_n298(x) + else + fun_l22_n334(x) + end +end + +def fun_l21_n297(x) + if (x < 1) + fun_l22_n124(x) + else + fun_l22_n704(x) + end +end + +def fun_l21_n298(x) + if (x < 1) + fun_l22_n526(x) + else + fun_l22_n139(x) + end +end + +def fun_l21_n299(x) + if (x < 1) + fun_l22_n133(x) + else + fun_l22_n65(x) + end +end + +def fun_l21_n300(x) + if (x < 1) + fun_l22_n476(x) + else + fun_l22_n858(x) + end +end + +def fun_l21_n301(x) + if (x < 1) + fun_l22_n23(x) + else + fun_l22_n391(x) + end +end + +def fun_l21_n302(x) + if (x < 1) + fun_l22_n292(x) + else + fun_l22_n127(x) + end +end + +def fun_l21_n303(x) + if (x < 1) + fun_l22_n935(x) + else + fun_l22_n399(x) + end +end + +def fun_l21_n304(x) + if (x < 1) + fun_l22_n110(x) + else + fun_l22_n904(x) + end +end + +def fun_l21_n305(x) + if (x < 1) + fun_l22_n865(x) + else + fun_l22_n510(x) + end +end + +def fun_l21_n306(x) + if (x < 1) + fun_l22_n930(x) + else + fun_l22_n892(x) + end +end + +def fun_l21_n307(x) + if (x < 1) + fun_l22_n701(x) + else + fun_l22_n172(x) + end +end + +def fun_l21_n308(x) + if (x < 1) + fun_l22_n424(x) + else + fun_l22_n169(x) + end +end + +def fun_l21_n309(x) + if (x < 1) + fun_l22_n494(x) + else + fun_l22_n608(x) + end +end + +def fun_l21_n310(x) + if (x < 1) + fun_l22_n862(x) + else + fun_l22_n54(x) + end +end + +def fun_l21_n311(x) + if (x < 1) + fun_l22_n679(x) + else + fun_l22_n246(x) + end +end + +def fun_l21_n312(x) + if (x < 1) + fun_l22_n897(x) + else + fun_l22_n581(x) + end +end + +def fun_l21_n313(x) + if (x < 1) + fun_l22_n788(x) + else + fun_l22_n32(x) + end +end + +def fun_l21_n314(x) + if (x < 1) + fun_l22_n68(x) + else + fun_l22_n920(x) + end +end + +def fun_l21_n315(x) + if (x < 1) + fun_l22_n520(x) + else + fun_l22_n814(x) + end +end + +def fun_l21_n316(x) + if (x < 1) + fun_l22_n190(x) + else + fun_l22_n832(x) + end +end + +def fun_l21_n317(x) + if (x < 1) + fun_l22_n500(x) + else + fun_l22_n576(x) + end +end + +def fun_l21_n318(x) + if (x < 1) + fun_l22_n999(x) + else + fun_l22_n423(x) + end +end + +def fun_l21_n319(x) + if (x < 1) + fun_l22_n62(x) + else + fun_l22_n451(x) + end +end + +def fun_l21_n320(x) + if (x < 1) + fun_l22_n265(x) + else + fun_l22_n421(x) + end +end + +def fun_l21_n321(x) + if (x < 1) + fun_l22_n340(x) + else + fun_l22_n297(x) + end +end + +def fun_l21_n322(x) + if (x < 1) + fun_l22_n526(x) + else + fun_l22_n834(x) + end +end + +def fun_l21_n323(x) + if (x < 1) + fun_l22_n305(x) + else + fun_l22_n444(x) + end +end + +def fun_l21_n324(x) + if (x < 1) + fun_l22_n117(x) + else + fun_l22_n617(x) + end +end + +def fun_l21_n325(x) + if (x < 1) + fun_l22_n715(x) + else + fun_l22_n551(x) + end +end + +def fun_l21_n326(x) + if (x < 1) + fun_l22_n921(x) + else + fun_l22_n69(x) + end +end + +def fun_l21_n327(x) + if (x < 1) + fun_l22_n226(x) + else + fun_l22_n21(x) + end +end + +def fun_l21_n328(x) + if (x < 1) + fun_l22_n181(x) + else + fun_l22_n409(x) + end +end + +def fun_l21_n329(x) + if (x < 1) + fun_l22_n894(x) + else + fun_l22_n17(x) + end +end + +def fun_l21_n330(x) + if (x < 1) + fun_l22_n633(x) + else + fun_l22_n370(x) + end +end + +def fun_l21_n331(x) + if (x < 1) + fun_l22_n638(x) + else + fun_l22_n994(x) + end +end + +def fun_l21_n332(x) + if (x < 1) + fun_l22_n663(x) + else + fun_l22_n981(x) + end +end + +def fun_l21_n333(x) + if (x < 1) + fun_l22_n861(x) + else + fun_l22_n472(x) + end +end + +def fun_l21_n334(x) + if (x < 1) + fun_l22_n265(x) + else + fun_l22_n534(x) + end +end + +def fun_l21_n335(x) + if (x < 1) + fun_l22_n43(x) + else + fun_l22_n613(x) + end +end + +def fun_l21_n336(x) + if (x < 1) + fun_l22_n788(x) + else + fun_l22_n649(x) + end +end + +def fun_l21_n337(x) + if (x < 1) + fun_l22_n406(x) + else + fun_l22_n644(x) + end +end + +def fun_l21_n338(x) + if (x < 1) + fun_l22_n582(x) + else + fun_l22_n463(x) + end +end + +def fun_l21_n339(x) + if (x < 1) + fun_l22_n825(x) + else + fun_l22_n775(x) + end +end + +def fun_l21_n340(x) + if (x < 1) + fun_l22_n696(x) + else + fun_l22_n318(x) + end +end + +def fun_l21_n341(x) + if (x < 1) + fun_l22_n21(x) + else + fun_l22_n285(x) + end +end + +def fun_l21_n342(x) + if (x < 1) + fun_l22_n10(x) + else + fun_l22_n423(x) + end +end + +def fun_l21_n343(x) + if (x < 1) + fun_l22_n205(x) + else + fun_l22_n86(x) + end +end + +def fun_l21_n344(x) + if (x < 1) + fun_l22_n437(x) + else + fun_l22_n712(x) + end +end + +def fun_l21_n345(x) + if (x < 1) + fun_l22_n941(x) + else + fun_l22_n655(x) + end +end + +def fun_l21_n346(x) + if (x < 1) + fun_l22_n673(x) + else + fun_l22_n750(x) + end +end + +def fun_l21_n347(x) + if (x < 1) + fun_l22_n728(x) + else + fun_l22_n605(x) + end +end + +def fun_l21_n348(x) + if (x < 1) + fun_l22_n452(x) + else + fun_l22_n968(x) + end +end + +def fun_l21_n349(x) + if (x < 1) + fun_l22_n554(x) + else + fun_l22_n997(x) + end +end + +def fun_l21_n350(x) + if (x < 1) + fun_l22_n784(x) + else + fun_l22_n801(x) + end +end + +def fun_l21_n351(x) + if (x < 1) + fun_l22_n397(x) + else + fun_l22_n636(x) + end +end + +def fun_l21_n352(x) + if (x < 1) + fun_l22_n562(x) + else + fun_l22_n150(x) + end +end + +def fun_l21_n353(x) + if (x < 1) + fun_l22_n142(x) + else + fun_l22_n396(x) + end +end + +def fun_l21_n354(x) + if (x < 1) + fun_l22_n455(x) + else + fun_l22_n424(x) + end +end + +def fun_l21_n355(x) + if (x < 1) + fun_l22_n736(x) + else + fun_l22_n534(x) + end +end + +def fun_l21_n356(x) + if (x < 1) + fun_l22_n111(x) + else + fun_l22_n903(x) + end +end + +def fun_l21_n357(x) + if (x < 1) + fun_l22_n996(x) + else + fun_l22_n350(x) + end +end + +def fun_l21_n358(x) + if (x < 1) + fun_l22_n516(x) + else + fun_l22_n202(x) + end +end + +def fun_l21_n359(x) + if (x < 1) + fun_l22_n68(x) + else + fun_l22_n823(x) + end +end + +def fun_l21_n360(x) + if (x < 1) + fun_l22_n298(x) + else + fun_l22_n873(x) + end +end + +def fun_l21_n361(x) + if (x < 1) + fun_l22_n491(x) + else + fun_l22_n86(x) + end +end + +def fun_l21_n362(x) + if (x < 1) + fun_l22_n340(x) + else + fun_l22_n215(x) + end +end + +def fun_l21_n363(x) + if (x < 1) + fun_l22_n452(x) + else + fun_l22_n416(x) + end +end + +def fun_l21_n364(x) + if (x < 1) + fun_l22_n625(x) + else + fun_l22_n638(x) + end +end + +def fun_l21_n365(x) + if (x < 1) + fun_l22_n166(x) + else + fun_l22_n380(x) + end +end + +def fun_l21_n366(x) + if (x < 1) + fun_l22_n934(x) + else + fun_l22_n937(x) + end +end + +def fun_l21_n367(x) + if (x < 1) + fun_l22_n77(x) + else + fun_l22_n117(x) + end +end + +def fun_l21_n368(x) + if (x < 1) + fun_l22_n688(x) + else + fun_l22_n529(x) + end +end + +def fun_l21_n369(x) + if (x < 1) + fun_l22_n950(x) + else + fun_l22_n148(x) + end +end + +def fun_l21_n370(x) + if (x < 1) + fun_l22_n216(x) + else + fun_l22_n588(x) + end +end + +def fun_l21_n371(x) + if (x < 1) + fun_l22_n127(x) + else + fun_l22_n901(x) + end +end + +def fun_l21_n372(x) + if (x < 1) + fun_l22_n244(x) + else + fun_l22_n516(x) + end +end + +def fun_l21_n373(x) + if (x < 1) + fun_l22_n791(x) + else + fun_l22_n466(x) + end +end + +def fun_l21_n374(x) + if (x < 1) + fun_l22_n469(x) + else + fun_l22_n38(x) + end +end + +def fun_l21_n375(x) + if (x < 1) + fun_l22_n894(x) + else + fun_l22_n82(x) + end +end + +def fun_l21_n376(x) + if (x < 1) + fun_l22_n663(x) + else + fun_l22_n865(x) + end +end + +def fun_l21_n377(x) + if (x < 1) + fun_l22_n782(x) + else + fun_l22_n10(x) + end +end + +def fun_l21_n378(x) + if (x < 1) + fun_l22_n930(x) + else + fun_l22_n767(x) + end +end + +def fun_l21_n379(x) + if (x < 1) + fun_l22_n130(x) + else + fun_l22_n437(x) + end +end + +def fun_l21_n380(x) + if (x < 1) + fun_l22_n496(x) + else + fun_l22_n413(x) + end +end + +def fun_l21_n381(x) + if (x < 1) + fun_l22_n453(x) + else + fun_l22_n542(x) + end +end + +def fun_l21_n382(x) + if (x < 1) + fun_l22_n404(x) + else + fun_l22_n637(x) + end +end + +def fun_l21_n383(x) + if (x < 1) + fun_l22_n829(x) + else + fun_l22_n526(x) + end +end + +def fun_l21_n384(x) + if (x < 1) + fun_l22_n882(x) + else + fun_l22_n922(x) + end +end + +def fun_l21_n385(x) + if (x < 1) + fun_l22_n58(x) + else + fun_l22_n401(x) + end +end + +def fun_l21_n386(x) + if (x < 1) + fun_l22_n936(x) + else + fun_l22_n164(x) + end +end + +def fun_l21_n387(x) + if (x < 1) + fun_l22_n773(x) + else + fun_l22_n323(x) + end +end + +def fun_l21_n388(x) + if (x < 1) + fun_l22_n718(x) + else + fun_l22_n189(x) + end +end + +def fun_l21_n389(x) + if (x < 1) + fun_l22_n950(x) + else + fun_l22_n283(x) + end +end + +def fun_l21_n390(x) + if (x < 1) + fun_l22_n278(x) + else + fun_l22_n325(x) + end +end + +def fun_l21_n391(x) + if (x < 1) + fun_l22_n98(x) + else + fun_l22_n162(x) + end +end + +def fun_l21_n392(x) + if (x < 1) + fun_l22_n268(x) + else + fun_l22_n416(x) + end +end + +def fun_l21_n393(x) + if (x < 1) + fun_l22_n344(x) + else + fun_l22_n680(x) + end +end + +def fun_l21_n394(x) + if (x < 1) + fun_l22_n545(x) + else + fun_l22_n41(x) + end +end + +def fun_l21_n395(x) + if (x < 1) + fun_l22_n149(x) + else + fun_l22_n659(x) + end +end + +def fun_l21_n396(x) + if (x < 1) + fun_l22_n81(x) + else + fun_l22_n316(x) + end +end + +def fun_l21_n397(x) + if (x < 1) + fun_l22_n657(x) + else + fun_l22_n414(x) + end +end + +def fun_l21_n398(x) + if (x < 1) + fun_l22_n262(x) + else + fun_l22_n26(x) + end +end + +def fun_l21_n399(x) + if (x < 1) + fun_l22_n509(x) + else + fun_l22_n658(x) + end +end + +def fun_l21_n400(x) + if (x < 1) + fun_l22_n533(x) + else + fun_l22_n416(x) + end +end + +def fun_l21_n401(x) + if (x < 1) + fun_l22_n631(x) + else + fun_l22_n575(x) + end +end + +def fun_l21_n402(x) + if (x < 1) + fun_l22_n171(x) + else + fun_l22_n727(x) + end +end + +def fun_l21_n403(x) + if (x < 1) + fun_l22_n65(x) + else + fun_l22_n109(x) + end +end + +def fun_l21_n404(x) + if (x < 1) + fun_l22_n818(x) + else + fun_l22_n638(x) + end +end + +def fun_l21_n405(x) + if (x < 1) + fun_l22_n515(x) + else + fun_l22_n86(x) + end +end + +def fun_l21_n406(x) + if (x < 1) + fun_l22_n500(x) + else + fun_l22_n367(x) + end +end + +def fun_l21_n407(x) + if (x < 1) + fun_l22_n609(x) + else + fun_l22_n926(x) + end +end + +def fun_l21_n408(x) + if (x < 1) + fun_l22_n553(x) + else + fun_l22_n494(x) + end +end + +def fun_l21_n409(x) + if (x < 1) + fun_l22_n837(x) + else + fun_l22_n800(x) + end +end + +def fun_l21_n410(x) + if (x < 1) + fun_l22_n511(x) + else + fun_l22_n376(x) + end +end + +def fun_l21_n411(x) + if (x < 1) + fun_l22_n691(x) + else + fun_l22_n135(x) + end +end + +def fun_l21_n412(x) + if (x < 1) + fun_l22_n537(x) + else + fun_l22_n708(x) + end +end + +def fun_l21_n413(x) + if (x < 1) + fun_l22_n858(x) + else + fun_l22_n75(x) + end +end + +def fun_l21_n414(x) + if (x < 1) + fun_l22_n473(x) + else + fun_l22_n26(x) + end +end + +def fun_l21_n415(x) + if (x < 1) + fun_l22_n443(x) + else + fun_l22_n709(x) + end +end + +def fun_l21_n416(x) + if (x < 1) + fun_l22_n464(x) + else + fun_l22_n329(x) + end +end + +def fun_l21_n417(x) + if (x < 1) + fun_l22_n402(x) + else + fun_l22_n438(x) + end +end + +def fun_l21_n418(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n704(x) + end +end + +def fun_l21_n419(x) + if (x < 1) + fun_l22_n949(x) + else + fun_l22_n46(x) + end +end + +def fun_l21_n420(x) + if (x < 1) + fun_l22_n102(x) + else + fun_l22_n20(x) + end +end + +def fun_l21_n421(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n876(x) + end +end + +def fun_l21_n422(x) + if (x < 1) + fun_l22_n881(x) + else + fun_l22_n100(x) + end +end + +def fun_l21_n423(x) + if (x < 1) + fun_l22_n155(x) + else + fun_l22_n99(x) + end +end + +def fun_l21_n424(x) + if (x < 1) + fun_l22_n913(x) + else + fun_l22_n839(x) + end +end + +def fun_l21_n425(x) + if (x < 1) + fun_l22_n981(x) + else + fun_l22_n73(x) + end +end + +def fun_l21_n426(x) + if (x < 1) + fun_l22_n221(x) + else + fun_l22_n548(x) + end +end + +def fun_l21_n427(x) + if (x < 1) + fun_l22_n563(x) + else + fun_l22_n978(x) + end +end + +def fun_l21_n428(x) + if (x < 1) + fun_l22_n310(x) + else + fun_l22_n591(x) + end +end + +def fun_l21_n429(x) + if (x < 1) + fun_l22_n962(x) + else + fun_l22_n156(x) + end +end + +def fun_l21_n430(x) + if (x < 1) + fun_l22_n810(x) + else + fun_l22_n766(x) + end +end + +def fun_l21_n431(x) + if (x < 1) + fun_l22_n675(x) + else + fun_l22_n354(x) + end +end + +def fun_l21_n432(x) + if (x < 1) + fun_l22_n320(x) + else + fun_l22_n474(x) + end +end + +def fun_l21_n433(x) + if (x < 1) + fun_l22_n50(x) + else + fun_l22_n626(x) + end +end + +def fun_l21_n434(x) + if (x < 1) + fun_l22_n956(x) + else + fun_l22_n238(x) + end +end + +def fun_l21_n435(x) + if (x < 1) + fun_l22_n966(x) + else + fun_l22_n729(x) + end +end + +def fun_l21_n436(x) + if (x < 1) + fun_l22_n856(x) + else + fun_l22_n553(x) + end +end + +def fun_l21_n437(x) + if (x < 1) + fun_l22_n833(x) + else + fun_l22_n312(x) + end +end + +def fun_l21_n438(x) + if (x < 1) + fun_l22_n254(x) + else + fun_l22_n515(x) + end +end + +def fun_l21_n439(x) + if (x < 1) + fun_l22_n548(x) + else + fun_l22_n184(x) + end +end + +def fun_l21_n440(x) + if (x < 1) + fun_l22_n922(x) + else + fun_l22_n465(x) + end +end + +def fun_l21_n441(x) + if (x < 1) + fun_l22_n136(x) + else + fun_l22_n739(x) + end +end + +def fun_l21_n442(x) + if (x < 1) + fun_l22_n4(x) + else + fun_l22_n359(x) + end +end + +def fun_l21_n443(x) + if (x < 1) + fun_l22_n269(x) + else + fun_l22_n417(x) + end +end + +def fun_l21_n444(x) + if (x < 1) + fun_l22_n809(x) + else + fun_l22_n430(x) + end +end + +def fun_l21_n445(x) + if (x < 1) + fun_l22_n428(x) + else + fun_l22_n55(x) + end +end + +def fun_l21_n446(x) + if (x < 1) + fun_l22_n265(x) + else + fun_l22_n394(x) + end +end + +def fun_l21_n447(x) + if (x < 1) + fun_l22_n885(x) + else + fun_l22_n139(x) + end +end + +def fun_l21_n448(x) + if (x < 1) + fun_l22_n219(x) + else + fun_l22_n578(x) + end +end + +def fun_l21_n449(x) + if (x < 1) + fun_l22_n458(x) + else + fun_l22_n226(x) + end +end + +def fun_l21_n450(x) + if (x < 1) + fun_l22_n128(x) + else + fun_l22_n790(x) + end +end + +def fun_l21_n451(x) + if (x < 1) + fun_l22_n134(x) + else + fun_l22_n471(x) + end +end + +def fun_l21_n452(x) + if (x < 1) + fun_l22_n180(x) + else + fun_l22_n183(x) + end +end + +def fun_l21_n453(x) + if (x < 1) + fun_l22_n823(x) + else + fun_l22_n667(x) + end +end + +def fun_l21_n454(x) + if (x < 1) + fun_l22_n324(x) + else + fun_l22_n487(x) + end +end + +def fun_l21_n455(x) + if (x < 1) + fun_l22_n341(x) + else + fun_l22_n784(x) + end +end + +def fun_l21_n456(x) + if (x < 1) + fun_l22_n32(x) + else + fun_l22_n227(x) + end +end + +def fun_l21_n457(x) + if (x < 1) + fun_l22_n567(x) + else + fun_l22_n774(x) + end +end + +def fun_l21_n458(x) + if (x < 1) + fun_l22_n342(x) + else + fun_l22_n126(x) + end +end + +def fun_l21_n459(x) + if (x < 1) + fun_l22_n116(x) + else + fun_l22_n367(x) + end +end + +def fun_l21_n460(x) + if (x < 1) + fun_l22_n864(x) + else + fun_l22_n618(x) + end +end + +def fun_l21_n461(x) + if (x < 1) + fun_l22_n823(x) + else + fun_l22_n799(x) + end +end + +def fun_l21_n462(x) + if (x < 1) + fun_l22_n684(x) + else + fun_l22_n758(x) + end +end + +def fun_l21_n463(x) + if (x < 1) + fun_l22_n662(x) + else + fun_l22_n514(x) + end +end + +def fun_l21_n464(x) + if (x < 1) + fun_l22_n736(x) + else + fun_l22_n794(x) + end +end + +def fun_l21_n465(x) + if (x < 1) + fun_l22_n200(x) + else + fun_l22_n565(x) + end +end + +def fun_l21_n466(x) + if (x < 1) + fun_l22_n787(x) + else + fun_l22_n835(x) + end +end + +def fun_l21_n467(x) + if (x < 1) + fun_l22_n927(x) + else + fun_l22_n399(x) + end +end + +def fun_l21_n468(x) + if (x < 1) + fun_l22_n102(x) + else + fun_l22_n738(x) + end +end + +def fun_l21_n469(x) + if (x < 1) + fun_l22_n833(x) + else + fun_l22_n917(x) + end +end + +def fun_l21_n470(x) + if (x < 1) + fun_l22_n422(x) + else + fun_l22_n108(x) + end +end + +def fun_l21_n471(x) + if (x < 1) + fun_l22_n884(x) + else + fun_l22_n19(x) + end +end + +def fun_l21_n472(x) + if (x < 1) + fun_l22_n849(x) + else + fun_l22_n251(x) + end +end + +def fun_l21_n473(x) + if (x < 1) + fun_l22_n636(x) + else + fun_l22_n439(x) + end +end + +def fun_l21_n474(x) + if (x < 1) + fun_l22_n867(x) + else + fun_l22_n227(x) + end +end + +def fun_l21_n475(x) + if (x < 1) + fun_l22_n809(x) + else + fun_l22_n548(x) + end +end + +def fun_l21_n476(x) + if (x < 1) + fun_l22_n213(x) + else + fun_l22_n607(x) + end +end + +def fun_l21_n477(x) + if (x < 1) + fun_l22_n44(x) + else + fun_l22_n38(x) + end +end + +def fun_l21_n478(x) + if (x < 1) + fun_l22_n400(x) + else + fun_l22_n436(x) + end +end + +def fun_l21_n479(x) + if (x < 1) + fun_l22_n701(x) + else + fun_l22_n84(x) + end +end + +def fun_l21_n480(x) + if (x < 1) + fun_l22_n21(x) + else + fun_l22_n215(x) + end +end + +def fun_l21_n481(x) + if (x < 1) + fun_l22_n27(x) + else + fun_l22_n198(x) + end +end + +def fun_l21_n482(x) + if (x < 1) + fun_l22_n803(x) + else + fun_l22_n82(x) + end +end + +def fun_l21_n483(x) + if (x < 1) + fun_l22_n490(x) + else + fun_l22_n126(x) + end +end + +def fun_l21_n484(x) + if (x < 1) + fun_l22_n348(x) + else + fun_l22_n586(x) + end +end + +def fun_l21_n485(x) + if (x < 1) + fun_l22_n279(x) + else + fun_l22_n266(x) + end +end + +def fun_l21_n486(x) + if (x < 1) + fun_l22_n398(x) + else + fun_l22_n26(x) + end +end + +def fun_l21_n487(x) + if (x < 1) + fun_l22_n529(x) + else + fun_l22_n972(x) + end +end + +def fun_l21_n488(x) + if (x < 1) + fun_l22_n390(x) + else + fun_l22_n220(x) + end +end + +def fun_l21_n489(x) + if (x < 1) + fun_l22_n909(x) + else + fun_l22_n777(x) + end +end + +def fun_l21_n490(x) + if (x < 1) + fun_l22_n797(x) + else + fun_l22_n643(x) + end +end + +def fun_l21_n491(x) + if (x < 1) + fun_l22_n920(x) + else + fun_l22_n820(x) + end +end + +def fun_l21_n492(x) + if (x < 1) + fun_l22_n170(x) + else + fun_l22_n236(x) + end +end + +def fun_l21_n493(x) + if (x < 1) + fun_l22_n352(x) + else + fun_l22_n147(x) + end +end + +def fun_l21_n494(x) + if (x < 1) + fun_l22_n938(x) + else + fun_l22_n83(x) + end +end + +def fun_l21_n495(x) + if (x < 1) + fun_l22_n512(x) + else + fun_l22_n798(x) + end +end + +def fun_l21_n496(x) + if (x < 1) + fun_l22_n254(x) + else + fun_l22_n827(x) + end +end + +def fun_l21_n497(x) + if (x < 1) + fun_l22_n730(x) + else + fun_l22_n995(x) + end +end + +def fun_l21_n498(x) + if (x < 1) + fun_l22_n130(x) + else + fun_l22_n269(x) + end +end + +def fun_l21_n499(x) + if (x < 1) + fun_l22_n275(x) + else + fun_l22_n176(x) + end +end + +def fun_l21_n500(x) + if (x < 1) + fun_l22_n493(x) + else + fun_l22_n322(x) + end +end + +def fun_l21_n501(x) + if (x < 1) + fun_l22_n421(x) + else + fun_l22_n859(x) + end +end + +def fun_l21_n502(x) + if (x < 1) + fun_l22_n611(x) + else + fun_l22_n727(x) + end +end + +def fun_l21_n503(x) + if (x < 1) + fun_l22_n42(x) + else + fun_l22_n294(x) + end +end + +def fun_l21_n504(x) + if (x < 1) + fun_l22_n735(x) + else + fun_l22_n145(x) + end +end + +def fun_l21_n505(x) + if (x < 1) + fun_l22_n865(x) + else + fun_l22_n225(x) + end +end + +def fun_l21_n506(x) + if (x < 1) + fun_l22_n922(x) + else + fun_l22_n619(x) + end +end + +def fun_l21_n507(x) + if (x < 1) + fun_l22_n646(x) + else + fun_l22_n145(x) + end +end + +def fun_l21_n508(x) + if (x < 1) + fun_l22_n608(x) + else + fun_l22_n320(x) + end +end + +def fun_l21_n509(x) + if (x < 1) + fun_l22_n624(x) + else + fun_l22_n984(x) + end +end + +def fun_l21_n510(x) + if (x < 1) + fun_l22_n454(x) + else + fun_l22_n988(x) + end +end + +def fun_l21_n511(x) + if (x < 1) + fun_l22_n593(x) + else + fun_l22_n796(x) + end +end + +def fun_l21_n512(x) + if (x < 1) + fun_l22_n922(x) + else + fun_l22_n5(x) + end +end + +def fun_l21_n513(x) + if (x < 1) + fun_l22_n0(x) + else + fun_l22_n338(x) + end +end + +def fun_l21_n514(x) + if (x < 1) + fun_l22_n454(x) + else + fun_l22_n743(x) + end +end + +def fun_l21_n515(x) + if (x < 1) + fun_l22_n215(x) + else + fun_l22_n689(x) + end +end + +def fun_l21_n516(x) + if (x < 1) + fun_l22_n148(x) + else + fun_l22_n850(x) + end +end + +def fun_l21_n517(x) + if (x < 1) + fun_l22_n466(x) + else + fun_l22_n529(x) + end +end + +def fun_l21_n518(x) + if (x < 1) + fun_l22_n967(x) + else + fun_l22_n790(x) + end +end + +def fun_l21_n519(x) + if (x < 1) + fun_l22_n97(x) + else + fun_l22_n461(x) + end +end + +def fun_l21_n520(x) + if (x < 1) + fun_l22_n106(x) + else + fun_l22_n41(x) + end +end + +def fun_l21_n521(x) + if (x < 1) + fun_l22_n561(x) + else + fun_l22_n428(x) + end +end + +def fun_l21_n522(x) + if (x < 1) + fun_l22_n816(x) + else + fun_l22_n42(x) + end +end + +def fun_l21_n523(x) + if (x < 1) + fun_l22_n229(x) + else + fun_l22_n720(x) + end +end + +def fun_l21_n524(x) + if (x < 1) + fun_l22_n341(x) + else + fun_l22_n875(x) + end +end + +def fun_l21_n525(x) + if (x < 1) + fun_l22_n23(x) + else + fun_l22_n227(x) + end +end + +def fun_l21_n526(x) + if (x < 1) + fun_l22_n230(x) + else + fun_l22_n655(x) + end +end + +def fun_l21_n527(x) + if (x < 1) + fun_l22_n19(x) + else + fun_l22_n957(x) + end +end + +def fun_l21_n528(x) + if (x < 1) + fun_l22_n680(x) + else + fun_l22_n142(x) + end +end + +def fun_l21_n529(x) + if (x < 1) + fun_l22_n994(x) + else + fun_l22_n674(x) + end +end + +def fun_l21_n530(x) + if (x < 1) + fun_l22_n762(x) + else + fun_l22_n10(x) + end +end + +def fun_l21_n531(x) + if (x < 1) + fun_l22_n75(x) + else + fun_l22_n43(x) + end +end + +def fun_l21_n532(x) + if (x < 1) + fun_l22_n481(x) + else + fun_l22_n766(x) + end +end + +def fun_l21_n533(x) + if (x < 1) + fun_l22_n261(x) + else + fun_l22_n256(x) + end +end + +def fun_l21_n534(x) + if (x < 1) + fun_l22_n316(x) + else + fun_l22_n547(x) + end +end + +def fun_l21_n535(x) + if (x < 1) + fun_l22_n304(x) + else + fun_l22_n392(x) + end +end + +def fun_l21_n536(x) + if (x < 1) + fun_l22_n83(x) + else + fun_l22_n789(x) + end +end + +def fun_l21_n537(x) + if (x < 1) + fun_l22_n434(x) + else + fun_l22_n783(x) + end +end + +def fun_l21_n538(x) + if (x < 1) + fun_l22_n445(x) + else + fun_l22_n960(x) + end +end + +def fun_l21_n539(x) + if (x < 1) + fun_l22_n398(x) + else + fun_l22_n529(x) + end +end + +def fun_l21_n540(x) + if (x < 1) + fun_l22_n413(x) + else + fun_l22_n684(x) + end +end + +def fun_l21_n541(x) + if (x < 1) + fun_l22_n812(x) + else + fun_l22_n257(x) + end +end + +def fun_l21_n542(x) + if (x < 1) + fun_l22_n186(x) + else + fun_l22_n35(x) + end +end + +def fun_l21_n543(x) + if (x < 1) + fun_l22_n489(x) + else + fun_l22_n93(x) + end +end + +def fun_l21_n544(x) + if (x < 1) + fun_l22_n105(x) + else + fun_l22_n282(x) + end +end + +def fun_l21_n545(x) + if (x < 1) + fun_l22_n586(x) + else + fun_l22_n614(x) + end +end + +def fun_l21_n546(x) + if (x < 1) + fun_l22_n75(x) + else + fun_l22_n589(x) + end +end + +def fun_l21_n547(x) + if (x < 1) + fun_l22_n128(x) + else + fun_l22_n552(x) + end +end + +def fun_l21_n548(x) + if (x < 1) + fun_l22_n961(x) + else + fun_l22_n209(x) + end +end + +def fun_l21_n549(x) + if (x < 1) + fun_l22_n727(x) + else + fun_l22_n615(x) + end +end + +def fun_l21_n550(x) + if (x < 1) + fun_l22_n45(x) + else + fun_l22_n161(x) + end +end + +def fun_l21_n551(x) + if (x < 1) + fun_l22_n480(x) + else + fun_l22_n852(x) + end +end + +def fun_l21_n552(x) + if (x < 1) + fun_l22_n383(x) + else + fun_l22_n698(x) + end +end + +def fun_l21_n553(x) + if (x < 1) + fun_l22_n805(x) + else + fun_l22_n309(x) + end +end + +def fun_l21_n554(x) + if (x < 1) + fun_l22_n635(x) + else + fun_l22_n821(x) + end +end + +def fun_l21_n555(x) + if (x < 1) + fun_l22_n616(x) + else + fun_l22_n52(x) + end +end + +def fun_l21_n556(x) + if (x < 1) + fun_l22_n283(x) + else + fun_l22_n514(x) + end +end + +def fun_l21_n557(x) + if (x < 1) + fun_l22_n6(x) + else + fun_l22_n174(x) + end +end + +def fun_l21_n558(x) + if (x < 1) + fun_l22_n344(x) + else + fun_l22_n932(x) + end +end + +def fun_l21_n559(x) + if (x < 1) + fun_l22_n287(x) + else + fun_l22_n98(x) + end +end + +def fun_l21_n560(x) + if (x < 1) + fun_l22_n510(x) + else + fun_l22_n672(x) + end +end + +def fun_l21_n561(x) + if (x < 1) + fun_l22_n951(x) + else + fun_l22_n984(x) + end +end + +def fun_l21_n562(x) + if (x < 1) + fun_l22_n133(x) + else + fun_l22_n207(x) + end +end + +def fun_l21_n563(x) + if (x < 1) + fun_l22_n780(x) + else + fun_l22_n402(x) + end +end + +def fun_l21_n564(x) + if (x < 1) + fun_l22_n783(x) + else + fun_l22_n189(x) + end +end + +def fun_l21_n565(x) + if (x < 1) + fun_l22_n736(x) + else + fun_l22_n590(x) + end +end + +def fun_l21_n566(x) + if (x < 1) + fun_l22_n724(x) + else + fun_l22_n69(x) + end +end + +def fun_l21_n567(x) + if (x < 1) + fun_l22_n521(x) + else + fun_l22_n242(x) + end +end + +def fun_l21_n568(x) + if (x < 1) + fun_l22_n440(x) + else + fun_l22_n156(x) + end +end + +def fun_l21_n569(x) + if (x < 1) + fun_l22_n776(x) + else + fun_l22_n456(x) + end +end + +def fun_l21_n570(x) + if (x < 1) + fun_l22_n336(x) + else + fun_l22_n615(x) + end +end + +def fun_l21_n571(x) + if (x < 1) + fun_l22_n775(x) + else + fun_l22_n585(x) + end +end + +def fun_l21_n572(x) + if (x < 1) + fun_l22_n466(x) + else + fun_l22_n559(x) + end +end + +def fun_l21_n573(x) + if (x < 1) + fun_l22_n609(x) + else + fun_l22_n177(x) + end +end + +def fun_l21_n574(x) + if (x < 1) + fun_l22_n310(x) + else + fun_l22_n190(x) + end +end + +def fun_l21_n575(x) + if (x < 1) + fun_l22_n861(x) + else + fun_l22_n289(x) + end +end + +def fun_l21_n576(x) + if (x < 1) + fun_l22_n978(x) + else + fun_l22_n460(x) + end +end + +def fun_l21_n577(x) + if (x < 1) + fun_l22_n440(x) + else + fun_l22_n816(x) + end +end + +def fun_l21_n578(x) + if (x < 1) + fun_l22_n522(x) + else + fun_l22_n214(x) + end +end + +def fun_l21_n579(x) + if (x < 1) + fun_l22_n38(x) + else + fun_l22_n166(x) + end +end + +def fun_l21_n580(x) + if (x < 1) + fun_l22_n114(x) + else + fun_l22_n314(x) + end +end + +def fun_l21_n581(x) + if (x < 1) + fun_l22_n233(x) + else + fun_l22_n840(x) + end +end + +def fun_l21_n582(x) + if (x < 1) + fun_l22_n867(x) + else + fun_l22_n213(x) + end +end + +def fun_l21_n583(x) + if (x < 1) + fun_l22_n742(x) + else + fun_l22_n798(x) + end +end + +def fun_l21_n584(x) + if (x < 1) + fun_l22_n772(x) + else + fun_l22_n400(x) + end +end + +def fun_l21_n585(x) + if (x < 1) + fun_l22_n564(x) + else + fun_l22_n70(x) + end +end + +def fun_l21_n586(x) + if (x < 1) + fun_l22_n836(x) + else + fun_l22_n188(x) + end +end + +def fun_l21_n587(x) + if (x < 1) + fun_l22_n624(x) + else + fun_l22_n923(x) + end +end + +def fun_l21_n588(x) + if (x < 1) + fun_l22_n265(x) + else + fun_l22_n733(x) + end +end + +def fun_l21_n589(x) + if (x < 1) + fun_l22_n545(x) + else + fun_l22_n399(x) + end +end + +def fun_l21_n590(x) + if (x < 1) + fun_l22_n22(x) + else + fun_l22_n266(x) + end +end + +def fun_l21_n591(x) + if (x < 1) + fun_l22_n504(x) + else + fun_l22_n798(x) + end +end + +def fun_l21_n592(x) + if (x < 1) + fun_l22_n979(x) + else + fun_l22_n712(x) + end +end + +def fun_l21_n593(x) + if (x < 1) + fun_l22_n343(x) + else + fun_l22_n54(x) + end +end + +def fun_l21_n594(x) + if (x < 1) + fun_l22_n893(x) + else + fun_l22_n465(x) + end +end + +def fun_l21_n595(x) + if (x < 1) + fun_l22_n28(x) + else + fun_l22_n162(x) + end +end + +def fun_l21_n596(x) + if (x < 1) + fun_l22_n609(x) + else + fun_l22_n882(x) + end +end + +def fun_l21_n597(x) + if (x < 1) + fun_l22_n575(x) + else + fun_l22_n951(x) + end +end + +def fun_l21_n598(x) + if (x < 1) + fun_l22_n794(x) + else + fun_l22_n767(x) + end +end + +def fun_l21_n599(x) + if (x < 1) + fun_l22_n605(x) + else + fun_l22_n141(x) + end +end + +def fun_l21_n600(x) + if (x < 1) + fun_l22_n54(x) + else + fun_l22_n958(x) + end +end + +def fun_l21_n601(x) + if (x < 1) + fun_l22_n506(x) + else + fun_l22_n269(x) + end +end + +def fun_l21_n602(x) + if (x < 1) + fun_l22_n401(x) + else + fun_l22_n104(x) + end +end + +def fun_l21_n603(x) + if (x < 1) + fun_l22_n379(x) + else + fun_l22_n489(x) + end +end + +def fun_l21_n604(x) + if (x < 1) + fun_l22_n673(x) + else + fun_l22_n502(x) + end +end + +def fun_l21_n605(x) + if (x < 1) + fun_l22_n355(x) + else + fun_l22_n483(x) + end +end + +def fun_l21_n606(x) + if (x < 1) + fun_l22_n763(x) + else + fun_l22_n160(x) + end +end + +def fun_l21_n607(x) + if (x < 1) + fun_l22_n802(x) + else + fun_l22_n414(x) + end +end + +def fun_l21_n608(x) + if (x < 1) + fun_l22_n401(x) + else + fun_l22_n987(x) + end +end + +def fun_l21_n609(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n511(x) + end +end + +def fun_l21_n610(x) + if (x < 1) + fun_l22_n883(x) + else + fun_l22_n73(x) + end +end + +def fun_l21_n611(x) + if (x < 1) + fun_l22_n105(x) + else + fun_l22_n612(x) + end +end + +def fun_l21_n612(x) + if (x < 1) + fun_l22_n911(x) + else + fun_l22_n764(x) + end +end + +def fun_l21_n613(x) + if (x < 1) + fun_l22_n818(x) + else + fun_l22_n43(x) + end +end + +def fun_l21_n614(x) + if (x < 1) + fun_l22_n388(x) + else + fun_l22_n99(x) + end +end + +def fun_l21_n615(x) + if (x < 1) + fun_l22_n657(x) + else + fun_l22_n231(x) + end +end + +def fun_l21_n616(x) + if (x < 1) + fun_l22_n937(x) + else + fun_l22_n357(x) + end +end + +def fun_l21_n617(x) + if (x < 1) + fun_l22_n691(x) + else + fun_l22_n952(x) + end +end + +def fun_l21_n618(x) + if (x < 1) + fun_l22_n712(x) + else + fun_l22_n84(x) + end +end + +def fun_l21_n619(x) + if (x < 1) + fun_l22_n483(x) + else + fun_l22_n506(x) + end +end + +def fun_l21_n620(x) + if (x < 1) + fun_l22_n804(x) + else + fun_l22_n813(x) + end +end + +def fun_l21_n621(x) + if (x < 1) + fun_l22_n280(x) + else + fun_l22_n626(x) + end +end + +def fun_l21_n622(x) + if (x < 1) + fun_l22_n979(x) + else + fun_l22_n508(x) + end +end + +def fun_l21_n623(x) + if (x < 1) + fun_l22_n482(x) + else + fun_l22_n120(x) + end +end + +def fun_l21_n624(x) + if (x < 1) + fun_l22_n99(x) + else + fun_l22_n975(x) + end +end + +def fun_l21_n625(x) + if (x < 1) + fun_l22_n540(x) + else + fun_l22_n68(x) + end +end + +def fun_l21_n626(x) + if (x < 1) + fun_l22_n818(x) + else + fun_l22_n591(x) + end +end + +def fun_l21_n627(x) + if (x < 1) + fun_l22_n37(x) + else + fun_l22_n984(x) + end +end + +def fun_l21_n628(x) + if (x < 1) + fun_l22_n547(x) + else + fun_l22_n482(x) + end +end + +def fun_l21_n629(x) + if (x < 1) + fun_l22_n851(x) + else + fun_l22_n335(x) + end +end + +def fun_l21_n630(x) + if (x < 1) + fun_l22_n474(x) + else + fun_l22_n402(x) + end +end + +def fun_l21_n631(x) + if (x < 1) + fun_l22_n433(x) + else + fun_l22_n298(x) + end +end + +def fun_l21_n632(x) + if (x < 1) + fun_l22_n376(x) + else + fun_l22_n898(x) + end +end + +def fun_l21_n633(x) + if (x < 1) + fun_l22_n456(x) + else + fun_l22_n753(x) + end +end + +def fun_l21_n634(x) + if (x < 1) + fun_l22_n888(x) + else + fun_l22_n394(x) + end +end + +def fun_l21_n635(x) + if (x < 1) + fun_l22_n555(x) + else + fun_l22_n69(x) + end +end + +def fun_l21_n636(x) + if (x < 1) + fun_l22_n572(x) + else + fun_l22_n822(x) + end +end + +def fun_l21_n637(x) + if (x < 1) + fun_l22_n645(x) + else + fun_l22_n968(x) + end +end + +def fun_l21_n638(x) + if (x < 1) + fun_l22_n406(x) + else + fun_l22_n318(x) + end +end + +def fun_l21_n639(x) + if (x < 1) + fun_l22_n554(x) + else + fun_l22_n591(x) + end +end + +def fun_l21_n640(x) + if (x < 1) + fun_l22_n478(x) + else + fun_l22_n962(x) + end +end + +def fun_l21_n641(x) + if (x < 1) + fun_l22_n688(x) + else + fun_l22_n305(x) + end +end + +def fun_l21_n642(x) + if (x < 1) + fun_l22_n767(x) + else + fun_l22_n156(x) + end +end + +def fun_l21_n643(x) + if (x < 1) + fun_l22_n264(x) + else + fun_l22_n489(x) + end +end + +def fun_l21_n644(x) + if (x < 1) + fun_l22_n678(x) + else + fun_l22_n196(x) + end +end + +def fun_l21_n645(x) + if (x < 1) + fun_l22_n849(x) + else + fun_l22_n488(x) + end +end + +def fun_l21_n646(x) + if (x < 1) + fun_l22_n837(x) + else + fun_l22_n274(x) + end +end + +def fun_l21_n647(x) + if (x < 1) + fun_l22_n58(x) + else + fun_l22_n694(x) + end +end + +def fun_l21_n648(x) + if (x < 1) + fun_l22_n878(x) + else + fun_l22_n356(x) + end +end + +def fun_l21_n649(x) + if (x < 1) + fun_l22_n945(x) + else + fun_l22_n28(x) + end +end + +def fun_l21_n650(x) + if (x < 1) + fun_l22_n10(x) + else + fun_l22_n330(x) + end +end + +def fun_l21_n651(x) + if (x < 1) + fun_l22_n461(x) + else + fun_l22_n872(x) + end +end + +def fun_l21_n652(x) + if (x < 1) + fun_l22_n860(x) + else + fun_l22_n358(x) + end +end + +def fun_l21_n653(x) + if (x < 1) + fun_l22_n11(x) + else + fun_l22_n596(x) + end +end + +def fun_l21_n654(x) + if (x < 1) + fun_l22_n340(x) + else + fun_l22_n335(x) + end +end + +def fun_l21_n655(x) + if (x < 1) + fun_l22_n259(x) + else + fun_l22_n642(x) + end +end + +def fun_l21_n656(x) + if (x < 1) + fun_l22_n78(x) + else + fun_l22_n442(x) + end +end + +def fun_l21_n657(x) + if (x < 1) + fun_l22_n151(x) + else + fun_l22_n122(x) + end +end + +def fun_l21_n658(x) + if (x < 1) + fun_l22_n440(x) + else + fun_l22_n940(x) + end +end + +def fun_l21_n659(x) + if (x < 1) + fun_l22_n237(x) + else + fun_l22_n899(x) + end +end + +def fun_l21_n660(x) + if (x < 1) + fun_l22_n906(x) + else + fun_l22_n789(x) + end +end + +def fun_l21_n661(x) + if (x < 1) + fun_l22_n812(x) + else + fun_l22_n492(x) + end +end + +def fun_l21_n662(x) + if (x < 1) + fun_l22_n241(x) + else + fun_l22_n732(x) + end +end + +def fun_l21_n663(x) + if (x < 1) + fun_l22_n557(x) + else + fun_l22_n570(x) + end +end + +def fun_l21_n664(x) + if (x < 1) + fun_l22_n928(x) + else + fun_l22_n943(x) + end +end + +def fun_l21_n665(x) + if (x < 1) + fun_l22_n400(x) + else + fun_l22_n914(x) + end +end + +def fun_l21_n666(x) + if (x < 1) + fun_l22_n368(x) + else + fun_l22_n434(x) + end +end + +def fun_l21_n667(x) + if (x < 1) + fun_l22_n827(x) + else + fun_l22_n213(x) + end +end + +def fun_l21_n668(x) + if (x < 1) + fun_l22_n729(x) + else + fun_l22_n273(x) + end +end + +def fun_l21_n669(x) + if (x < 1) + fun_l22_n649(x) + else + fun_l22_n29(x) + end +end + +def fun_l21_n670(x) + if (x < 1) + fun_l22_n878(x) + else + fun_l22_n794(x) + end +end + +def fun_l21_n671(x) + if (x < 1) + fun_l22_n474(x) + else + fun_l22_n960(x) + end +end + +def fun_l21_n672(x) + if (x < 1) + fun_l22_n250(x) + else + fun_l22_n935(x) + end +end + +def fun_l21_n673(x) + if (x < 1) + fun_l22_n766(x) + else + fun_l22_n325(x) + end +end + +def fun_l21_n674(x) + if (x < 1) + fun_l22_n64(x) + else + fun_l22_n334(x) + end +end + +def fun_l21_n675(x) + if (x < 1) + fun_l22_n737(x) + else + fun_l22_n983(x) + end +end + +def fun_l21_n676(x) + if (x < 1) + fun_l22_n506(x) + else + fun_l22_n393(x) + end +end + +def fun_l21_n677(x) + if (x < 1) + fun_l22_n348(x) + else + fun_l22_n558(x) + end +end + +def fun_l21_n678(x) + if (x < 1) + fun_l22_n68(x) + else + fun_l22_n483(x) + end +end + +def fun_l21_n679(x) + if (x < 1) + fun_l22_n816(x) + else + fun_l22_n959(x) + end +end + +def fun_l21_n680(x) + if (x < 1) + fun_l22_n128(x) + else + fun_l22_n393(x) + end +end + +def fun_l21_n681(x) + if (x < 1) + fun_l22_n738(x) + else + fun_l22_n609(x) + end +end + +def fun_l21_n682(x) + if (x < 1) + fun_l22_n113(x) + else + fun_l22_n664(x) + end +end + +def fun_l21_n683(x) + if (x < 1) + fun_l22_n904(x) + else + fun_l22_n699(x) + end +end + +def fun_l21_n684(x) + if (x < 1) + fun_l22_n759(x) + else + fun_l22_n277(x) + end +end + +def fun_l21_n685(x) + if (x < 1) + fun_l22_n359(x) + else + fun_l22_n961(x) + end +end + +def fun_l21_n686(x) + if (x < 1) + fun_l22_n269(x) + else + fun_l22_n66(x) + end +end + +def fun_l21_n687(x) + if (x < 1) + fun_l22_n510(x) + else + fun_l22_n935(x) + end +end + +def fun_l21_n688(x) + if (x < 1) + fun_l22_n127(x) + else + fun_l22_n441(x) + end +end + +def fun_l21_n689(x) + if (x < 1) + fun_l22_n515(x) + else + fun_l22_n184(x) + end +end + +def fun_l21_n690(x) + if (x < 1) + fun_l22_n339(x) + else + fun_l22_n121(x) + end +end + +def fun_l21_n691(x) + if (x < 1) + fun_l22_n74(x) + else + fun_l22_n172(x) + end +end + +def fun_l21_n692(x) + if (x < 1) + fun_l22_n156(x) + else + fun_l22_n829(x) + end +end + +def fun_l21_n693(x) + if (x < 1) + fun_l22_n761(x) + else + fun_l22_n322(x) + end +end + +def fun_l21_n694(x) + if (x < 1) + fun_l22_n168(x) + else + fun_l22_n789(x) + end +end + +def fun_l21_n695(x) + if (x < 1) + fun_l22_n896(x) + else + fun_l22_n275(x) + end +end + +def fun_l21_n696(x) + if (x < 1) + fun_l22_n283(x) + else + fun_l22_n195(x) + end +end + +def fun_l21_n697(x) + if (x < 1) + fun_l22_n353(x) + else + fun_l22_n664(x) + end +end + +def fun_l21_n698(x) + if (x < 1) + fun_l22_n801(x) + else + fun_l22_n544(x) + end +end + +def fun_l21_n699(x) + if (x < 1) + fun_l22_n729(x) + else + fun_l22_n323(x) + end +end + +def fun_l21_n700(x) + if (x < 1) + fun_l22_n47(x) + else + fun_l22_n340(x) + end +end + +def fun_l21_n701(x) + if (x < 1) + fun_l22_n132(x) + else + fun_l22_n968(x) + end +end + +def fun_l21_n702(x) + if (x < 1) + fun_l22_n556(x) + else + fun_l22_n23(x) + end +end + +def fun_l21_n703(x) + if (x < 1) + fun_l22_n274(x) + else + fun_l22_n276(x) + end +end + +def fun_l21_n704(x) + if (x < 1) + fun_l22_n152(x) + else + fun_l22_n244(x) + end +end + +def fun_l21_n705(x) + if (x < 1) + fun_l22_n508(x) + else + fun_l22_n350(x) + end +end + +def fun_l21_n706(x) + if (x < 1) + fun_l22_n188(x) + else + fun_l22_n60(x) + end +end + +def fun_l21_n707(x) + if (x < 1) + fun_l22_n970(x) + else + fun_l22_n55(x) + end +end + +def fun_l21_n708(x) + if (x < 1) + fun_l22_n840(x) + else + fun_l22_n990(x) + end +end + +def fun_l21_n709(x) + if (x < 1) + fun_l22_n466(x) + else + fun_l22_n25(x) + end +end + +def fun_l21_n710(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n481(x) + end +end + +def fun_l21_n711(x) + if (x < 1) + fun_l22_n859(x) + else + fun_l22_n58(x) + end +end + +def fun_l21_n712(x) + if (x < 1) + fun_l22_n282(x) + else + fun_l22_n807(x) + end +end + +def fun_l21_n713(x) + if (x < 1) + fun_l22_n387(x) + else + fun_l22_n235(x) + end +end + +def fun_l21_n714(x) + if (x < 1) + fun_l22_n558(x) + else + fun_l22_n494(x) + end +end + +def fun_l21_n715(x) + if (x < 1) + fun_l22_n613(x) + else + fun_l22_n194(x) + end +end + +def fun_l21_n716(x) + if (x < 1) + fun_l22_n120(x) + else + fun_l22_n154(x) + end +end + +def fun_l21_n717(x) + if (x < 1) + fun_l22_n501(x) + else + fun_l22_n540(x) + end +end + +def fun_l21_n718(x) + if (x < 1) + fun_l22_n283(x) + else + fun_l22_n102(x) + end +end + +def fun_l21_n719(x) + if (x < 1) + fun_l22_n569(x) + else + fun_l22_n407(x) + end +end + +def fun_l21_n720(x) + if (x < 1) + fun_l22_n86(x) + else + fun_l22_n99(x) + end +end + +def fun_l21_n721(x) + if (x < 1) + fun_l22_n872(x) + else + fun_l22_n331(x) + end +end + +def fun_l21_n722(x) + if (x < 1) + fun_l22_n772(x) + else + fun_l22_n57(x) + end +end + +def fun_l21_n723(x) + if (x < 1) + fun_l22_n396(x) + else + fun_l22_n534(x) + end +end + +def fun_l21_n724(x) + if (x < 1) + fun_l22_n928(x) + else + fun_l22_n576(x) + end +end + +def fun_l21_n725(x) + if (x < 1) + fun_l22_n650(x) + else + fun_l22_n790(x) + end +end + +def fun_l21_n726(x) + if (x < 1) + fun_l22_n173(x) + else + fun_l22_n480(x) + end +end + +def fun_l21_n727(x) + if (x < 1) + fun_l22_n222(x) + else + fun_l22_n258(x) + end +end + +def fun_l21_n728(x) + if (x < 1) + fun_l22_n797(x) + else + fun_l22_n793(x) + end +end + +def fun_l21_n729(x) + if (x < 1) + fun_l22_n260(x) + else + fun_l22_n737(x) + end +end + +def fun_l21_n730(x) + if (x < 1) + fun_l22_n419(x) + else + fun_l22_n974(x) + end +end + +def fun_l21_n731(x) + if (x < 1) + fun_l22_n837(x) + else + fun_l22_n628(x) + end +end + +def fun_l21_n732(x) + if (x < 1) + fun_l22_n753(x) + else + fun_l22_n380(x) + end +end + +def fun_l21_n733(x) + if (x < 1) + fun_l22_n420(x) + else + fun_l22_n890(x) + end +end + +def fun_l21_n734(x) + if (x < 1) + fun_l22_n993(x) + else + fun_l22_n172(x) + end +end + +def fun_l21_n735(x) + if (x < 1) + fun_l22_n123(x) + else + fun_l22_n290(x) + end +end + +def fun_l21_n736(x) + if (x < 1) + fun_l22_n805(x) + else + fun_l22_n923(x) + end +end + +def fun_l21_n737(x) + if (x < 1) + fun_l22_n124(x) + else + fun_l22_n25(x) + end +end + +def fun_l21_n738(x) + if (x < 1) + fun_l22_n192(x) + else + fun_l22_n258(x) + end +end + +def fun_l21_n739(x) + if (x < 1) + fun_l22_n243(x) + else + fun_l22_n512(x) + end +end + +def fun_l21_n740(x) + if (x < 1) + fun_l22_n577(x) + else + fun_l22_n307(x) + end +end + +def fun_l21_n741(x) + if (x < 1) + fun_l22_n422(x) + else + fun_l22_n51(x) + end +end + +def fun_l21_n742(x) + if (x < 1) + fun_l22_n247(x) + else + fun_l22_n453(x) + end +end + +def fun_l21_n743(x) + if (x < 1) + fun_l22_n369(x) + else + fun_l22_n564(x) + end +end + +def fun_l21_n744(x) + if (x < 1) + fun_l22_n815(x) + else + fun_l22_n894(x) + end +end + +def fun_l21_n745(x) + if (x < 1) + fun_l22_n526(x) + else + fun_l22_n555(x) + end +end + +def fun_l21_n746(x) + if (x < 1) + fun_l22_n281(x) + else + fun_l22_n121(x) + end +end + +def fun_l21_n747(x) + if (x < 1) + fun_l22_n141(x) + else + fun_l22_n335(x) + end +end + +def fun_l21_n748(x) + if (x < 1) + fun_l22_n73(x) + else + fun_l22_n241(x) + end +end + +def fun_l21_n749(x) + if (x < 1) + fun_l22_n201(x) + else + fun_l22_n650(x) + end +end + +def fun_l21_n750(x) + if (x < 1) + fun_l22_n569(x) + else + fun_l22_n231(x) + end +end + +def fun_l21_n751(x) + if (x < 1) + fun_l22_n23(x) + else + fun_l22_n315(x) + end +end + +def fun_l21_n752(x) + if (x < 1) + fun_l22_n951(x) + else + fun_l22_n697(x) + end +end + +def fun_l21_n753(x) + if (x < 1) + fun_l22_n734(x) + else + fun_l22_n991(x) + end +end + +def fun_l21_n754(x) + if (x < 1) + fun_l22_n557(x) + else + fun_l22_n85(x) + end +end + +def fun_l21_n755(x) + if (x < 1) + fun_l22_n213(x) + else + fun_l22_n918(x) + end +end + +def fun_l21_n756(x) + if (x < 1) + fun_l22_n995(x) + else + fun_l22_n134(x) + end +end + +def fun_l21_n757(x) + if (x < 1) + fun_l22_n173(x) + else + fun_l22_n764(x) + end +end + +def fun_l21_n758(x) + if (x < 1) + fun_l22_n503(x) + else + fun_l22_n370(x) + end +end + +def fun_l21_n759(x) + if (x < 1) + fun_l22_n922(x) + else + fun_l22_n819(x) + end +end + +def fun_l21_n760(x) + if (x < 1) + fun_l22_n901(x) + else + fun_l22_n252(x) + end +end + +def fun_l21_n761(x) + if (x < 1) + fun_l22_n928(x) + else + fun_l22_n958(x) + end +end + +def fun_l21_n762(x) + if (x < 1) + fun_l22_n402(x) + else + fun_l22_n756(x) + end +end + +def fun_l21_n763(x) + if (x < 1) + fun_l22_n223(x) + else + fun_l22_n781(x) + end +end + +def fun_l21_n764(x) + if (x < 1) + fun_l22_n692(x) + else + fun_l22_n893(x) + end +end + +def fun_l21_n765(x) + if (x < 1) + fun_l22_n308(x) + else + fun_l22_n485(x) + end +end + +def fun_l21_n766(x) + if (x < 1) + fun_l22_n858(x) + else + fun_l22_n316(x) + end +end + +def fun_l21_n767(x) + if (x < 1) + fun_l22_n546(x) + else + fun_l22_n793(x) + end +end + +def fun_l21_n768(x) + if (x < 1) + fun_l22_n75(x) + else + fun_l22_n999(x) + end +end + +def fun_l21_n769(x) + if (x < 1) + fun_l22_n758(x) + else + fun_l22_n149(x) + end +end + +def fun_l21_n770(x) + if (x < 1) + fun_l22_n801(x) + else + fun_l22_n594(x) + end +end + +def fun_l21_n771(x) + if (x < 1) + fun_l22_n544(x) + else + fun_l22_n477(x) + end +end + +def fun_l21_n772(x) + if (x < 1) + fun_l22_n118(x) + else + fun_l22_n406(x) + end +end + +def fun_l21_n773(x) + if (x < 1) + fun_l22_n741(x) + else + fun_l22_n539(x) + end +end + +def fun_l21_n774(x) + if (x < 1) + fun_l22_n99(x) + else + fun_l22_n636(x) + end +end + +def fun_l21_n775(x) + if (x < 1) + fun_l22_n54(x) + else + fun_l22_n139(x) + end +end + +def fun_l21_n776(x) + if (x < 1) + fun_l22_n990(x) + else + fun_l22_n518(x) + end +end + +def fun_l21_n777(x) + if (x < 1) + fun_l22_n172(x) + else + fun_l22_n432(x) + end +end + +def fun_l21_n778(x) + if (x < 1) + fun_l22_n302(x) + else + fun_l22_n406(x) + end +end + +def fun_l21_n779(x) + if (x < 1) + fun_l22_n199(x) + else + fun_l22_n198(x) + end +end + +def fun_l21_n780(x) + if (x < 1) + fun_l22_n454(x) + else + fun_l22_n547(x) + end +end + +def fun_l21_n781(x) + if (x < 1) + fun_l22_n234(x) + else + fun_l22_n332(x) + end +end + +def fun_l21_n782(x) + if (x < 1) + fun_l22_n693(x) + else + fun_l22_n800(x) + end +end + +def fun_l21_n783(x) + if (x < 1) + fun_l22_n728(x) + else + fun_l22_n799(x) + end +end + +def fun_l21_n784(x) + if (x < 1) + fun_l22_n594(x) + else + fun_l22_n350(x) + end +end + +def fun_l21_n785(x) + if (x < 1) + fun_l22_n695(x) + else + fun_l22_n596(x) + end +end + +def fun_l21_n786(x) + if (x < 1) + fun_l22_n141(x) + else + fun_l22_n372(x) + end +end + +def fun_l21_n787(x) + if (x < 1) + fun_l22_n15(x) + else + fun_l22_n352(x) + end +end + +def fun_l21_n788(x) + if (x < 1) + fun_l22_n769(x) + else + fun_l22_n62(x) + end +end + +def fun_l21_n789(x) + if (x < 1) + fun_l22_n284(x) + else + fun_l22_n119(x) + end +end + +def fun_l21_n790(x) + if (x < 1) + fun_l22_n335(x) + else + fun_l22_n570(x) + end +end + +def fun_l21_n791(x) + if (x < 1) + fun_l22_n779(x) + else + fun_l22_n104(x) + end +end + +def fun_l21_n792(x) + if (x < 1) + fun_l22_n835(x) + else + fun_l22_n612(x) + end +end + +def fun_l21_n793(x) + if (x < 1) + fun_l22_n241(x) + else + fun_l22_n883(x) + end +end + +def fun_l21_n794(x) + if (x < 1) + fun_l22_n957(x) + else + fun_l22_n357(x) + end +end + +def fun_l21_n795(x) + if (x < 1) + fun_l22_n78(x) + else + fun_l22_n392(x) + end +end + +def fun_l21_n796(x) + if (x < 1) + fun_l22_n711(x) + else + fun_l22_n364(x) + end +end + +def fun_l21_n797(x) + if (x < 1) + fun_l22_n909(x) + else + fun_l22_n77(x) + end +end + +def fun_l21_n798(x) + if (x < 1) + fun_l22_n901(x) + else + fun_l22_n483(x) + end +end + +def fun_l21_n799(x) + if (x < 1) + fun_l22_n429(x) + else + fun_l22_n244(x) + end +end + +def fun_l21_n800(x) + if (x < 1) + fun_l22_n394(x) + else + fun_l22_n652(x) + end +end + +def fun_l21_n801(x) + if (x < 1) + fun_l22_n831(x) + else + fun_l22_n698(x) + end +end + +def fun_l21_n802(x) + if (x < 1) + fun_l22_n623(x) + else + fun_l22_n382(x) + end +end + +def fun_l21_n803(x) + if (x < 1) + fun_l22_n803(x) + else + fun_l22_n370(x) + end +end + +def fun_l21_n804(x) + if (x < 1) + fun_l22_n173(x) + else + fun_l22_n697(x) + end +end + +def fun_l21_n805(x) + if (x < 1) + fun_l22_n653(x) + else + fun_l22_n514(x) + end +end + +def fun_l21_n806(x) + if (x < 1) + fun_l22_n703(x) + else + fun_l22_n642(x) + end +end + +def fun_l21_n807(x) + if (x < 1) + fun_l22_n788(x) + else + fun_l22_n594(x) + end +end + +def fun_l21_n808(x) + if (x < 1) + fun_l22_n389(x) + else + fun_l22_n3(x) + end +end + +def fun_l21_n809(x) + if (x < 1) + fun_l22_n548(x) + else + fun_l22_n338(x) + end +end + +def fun_l21_n810(x) + if (x < 1) + fun_l22_n157(x) + else + fun_l22_n967(x) + end +end + +def fun_l21_n811(x) + if (x < 1) + fun_l22_n573(x) + else + fun_l22_n91(x) + end +end + +def fun_l21_n812(x) + if (x < 1) + fun_l22_n594(x) + else + fun_l22_n240(x) + end +end + +def fun_l21_n813(x) + if (x < 1) + fun_l22_n661(x) + else + fun_l22_n557(x) + end +end + +def fun_l21_n814(x) + if (x < 1) + fun_l22_n29(x) + else + fun_l22_n808(x) + end +end + +def fun_l21_n815(x) + if (x < 1) + fun_l22_n212(x) + else + fun_l22_n592(x) + end +end + +def fun_l21_n816(x) + if (x < 1) + fun_l22_n57(x) + else + fun_l22_n248(x) + end +end + +def fun_l21_n817(x) + if (x < 1) + fun_l22_n656(x) + else + fun_l22_n588(x) + end +end + +def fun_l21_n818(x) + if (x < 1) + fun_l22_n949(x) + else + fun_l22_n284(x) + end +end + +def fun_l21_n819(x) + if (x < 1) + fun_l22_n488(x) + else + fun_l22_n543(x) + end +end + +def fun_l21_n820(x) + if (x < 1) + fun_l22_n938(x) + else + fun_l22_n155(x) + end +end + +def fun_l21_n821(x) + if (x < 1) + fun_l22_n4(x) + else + fun_l22_n888(x) + end +end + +def fun_l21_n822(x) + if (x < 1) + fun_l22_n460(x) + else + fun_l22_n249(x) + end +end + +def fun_l21_n823(x) + if (x < 1) + fun_l22_n494(x) + else + fun_l22_n864(x) + end +end + +def fun_l21_n824(x) + if (x < 1) + fun_l22_n239(x) + else + fun_l22_n305(x) + end +end + +def fun_l21_n825(x) + if (x < 1) + fun_l22_n578(x) + else + fun_l22_n568(x) + end +end + +def fun_l21_n826(x) + if (x < 1) + fun_l22_n669(x) + else + fun_l22_n28(x) + end +end + +def fun_l21_n827(x) + if (x < 1) + fun_l22_n928(x) + else + fun_l22_n43(x) + end +end + +def fun_l21_n828(x) + if (x < 1) + fun_l22_n459(x) + else + fun_l22_n450(x) + end +end + +def fun_l21_n829(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n583(x) + end +end + +def fun_l21_n830(x) + if (x < 1) + fun_l22_n655(x) + else + fun_l22_n674(x) + end +end + +def fun_l21_n831(x) + if (x < 1) + fun_l22_n551(x) + else + fun_l22_n367(x) + end +end + +def fun_l21_n832(x) + if (x < 1) + fun_l22_n921(x) + else + fun_l22_n750(x) + end +end + +def fun_l21_n833(x) + if (x < 1) + fun_l22_n255(x) + else + fun_l22_n253(x) + end +end + +def fun_l21_n834(x) + if (x < 1) + fun_l22_n873(x) + else + fun_l22_n84(x) + end +end + +def fun_l21_n835(x) + if (x < 1) + fun_l22_n362(x) + else + fun_l22_n976(x) + end +end + +def fun_l21_n836(x) + if (x < 1) + fun_l22_n677(x) + else + fun_l22_n429(x) + end +end + +def fun_l21_n837(x) + if (x < 1) + fun_l22_n78(x) + else + fun_l22_n782(x) + end +end + +def fun_l21_n838(x) + if (x < 1) + fun_l22_n339(x) + else + fun_l22_n855(x) + end +end + +def fun_l21_n839(x) + if (x < 1) + fun_l22_n73(x) + else + fun_l22_n13(x) + end +end + +def fun_l21_n840(x) + if (x < 1) + fun_l22_n788(x) + else + fun_l22_n701(x) + end +end + +def fun_l21_n841(x) + if (x < 1) + fun_l22_n583(x) + else + fun_l22_n501(x) + end +end + +def fun_l21_n842(x) + if (x < 1) + fun_l22_n532(x) + else + fun_l22_n190(x) + end +end + +def fun_l21_n843(x) + if (x < 1) + fun_l22_n206(x) + else + fun_l22_n718(x) + end +end + +def fun_l21_n844(x) + if (x < 1) + fun_l22_n307(x) + else + fun_l22_n200(x) + end +end + +def fun_l21_n845(x) + if (x < 1) + fun_l22_n83(x) + else + fun_l22_n294(x) + end +end + +def fun_l21_n846(x) + if (x < 1) + fun_l22_n157(x) + else + fun_l22_n225(x) + end +end + +def fun_l21_n847(x) + if (x < 1) + fun_l22_n935(x) + else + fun_l22_n888(x) + end +end + +def fun_l21_n848(x) + if (x < 1) + fun_l22_n840(x) + else + fun_l22_n606(x) + end +end + +def fun_l21_n849(x) + if (x < 1) + fun_l22_n214(x) + else + fun_l22_n198(x) + end +end + +def fun_l21_n850(x) + if (x < 1) + fun_l22_n793(x) + else + fun_l22_n503(x) + end +end + +def fun_l21_n851(x) + if (x < 1) + fun_l22_n210(x) + else + fun_l22_n267(x) + end +end + +def fun_l21_n852(x) + if (x < 1) + fun_l22_n558(x) + else + fun_l22_n226(x) + end +end + +def fun_l21_n853(x) + if (x < 1) + fun_l22_n12(x) + else + fun_l22_n765(x) + end +end + +def fun_l21_n854(x) + if (x < 1) + fun_l22_n136(x) + else + fun_l22_n713(x) + end +end + +def fun_l21_n855(x) + if (x < 1) + fun_l22_n638(x) + else + fun_l22_n999(x) + end +end + +def fun_l21_n856(x) + if (x < 1) + fun_l22_n366(x) + else + fun_l22_n505(x) + end +end + +def fun_l21_n857(x) + if (x < 1) + fun_l22_n935(x) + else + fun_l22_n657(x) + end +end + +def fun_l21_n858(x) + if (x < 1) + fun_l22_n4(x) + else + fun_l22_n732(x) + end +end + +def fun_l21_n859(x) + if (x < 1) + fun_l22_n433(x) + else + fun_l22_n350(x) + end +end + +def fun_l21_n860(x) + if (x < 1) + fun_l22_n988(x) + else + fun_l22_n855(x) + end +end + +def fun_l21_n861(x) + if (x < 1) + fun_l22_n906(x) + else + fun_l22_n118(x) + end +end + +def fun_l21_n862(x) + if (x < 1) + fun_l22_n127(x) + else + fun_l22_n299(x) + end +end + +def fun_l21_n863(x) + if (x < 1) + fun_l22_n324(x) + else + fun_l22_n776(x) + end +end + +def fun_l21_n864(x) + if (x < 1) + fun_l22_n208(x) + else + fun_l22_n827(x) + end +end + +def fun_l21_n865(x) + if (x < 1) + fun_l22_n846(x) + else + fun_l22_n750(x) + end +end + +def fun_l21_n866(x) + if (x < 1) + fun_l22_n275(x) + else + fun_l22_n179(x) + end +end + +def fun_l21_n867(x) + if (x < 1) + fun_l22_n234(x) + else + fun_l22_n809(x) + end +end + +def fun_l21_n868(x) + if (x < 1) + fun_l22_n597(x) + else + fun_l22_n563(x) + end +end + +def fun_l21_n869(x) + if (x < 1) + fun_l22_n987(x) + else + fun_l22_n690(x) + end +end + +def fun_l21_n870(x) + if (x < 1) + fun_l22_n176(x) + else + fun_l22_n991(x) + end +end + +def fun_l21_n871(x) + if (x < 1) + fun_l22_n272(x) + else + fun_l22_n211(x) + end +end + +def fun_l21_n872(x) + if (x < 1) + fun_l22_n976(x) + else + fun_l22_n940(x) + end +end + +def fun_l21_n873(x) + if (x < 1) + fun_l22_n871(x) + else + fun_l22_n866(x) + end +end + +def fun_l21_n874(x) + if (x < 1) + fun_l22_n727(x) + else + fun_l22_n560(x) + end +end + +def fun_l21_n875(x) + if (x < 1) + fun_l22_n201(x) + else + fun_l22_n423(x) + end +end + +def fun_l21_n876(x) + if (x < 1) + fun_l22_n245(x) + else + fun_l22_n33(x) + end +end + +def fun_l21_n877(x) + if (x < 1) + fun_l22_n535(x) + else + fun_l22_n11(x) + end +end + +def fun_l21_n878(x) + if (x < 1) + fun_l22_n11(x) + else + fun_l22_n140(x) + end +end + +def fun_l21_n879(x) + if (x < 1) + fun_l22_n757(x) + else + fun_l22_n64(x) + end +end + +def fun_l21_n880(x) + if (x < 1) + fun_l22_n982(x) + else + fun_l22_n774(x) + end +end + +def fun_l21_n881(x) + if (x < 1) + fun_l22_n324(x) + else + fun_l22_n903(x) + end +end + +def fun_l21_n882(x) + if (x < 1) + fun_l22_n257(x) + else + fun_l22_n232(x) + end +end + +def fun_l21_n883(x) + if (x < 1) + fun_l22_n546(x) + else + fun_l22_n317(x) + end +end + +def fun_l21_n884(x) + if (x < 1) + fun_l22_n40(x) + else + fun_l22_n393(x) + end +end + +def fun_l21_n885(x) + if (x < 1) + fun_l22_n281(x) + else + fun_l22_n572(x) + end +end + +def fun_l21_n886(x) + if (x < 1) + fun_l22_n41(x) + else + fun_l22_n656(x) + end +end + +def fun_l21_n887(x) + if (x < 1) + fun_l22_n911(x) + else + fun_l22_n55(x) + end +end + +def fun_l21_n888(x) + if (x < 1) + fun_l22_n555(x) + else + fun_l22_n60(x) + end +end + +def fun_l21_n889(x) + if (x < 1) + fun_l22_n69(x) + else + fun_l22_n330(x) + end +end + +def fun_l21_n890(x) + if (x < 1) + fun_l22_n332(x) + else + fun_l22_n573(x) + end +end + +def fun_l21_n891(x) + if (x < 1) + fun_l22_n529(x) + else + fun_l22_n555(x) + end +end + +def fun_l21_n892(x) + if (x < 1) + fun_l22_n900(x) + else + fun_l22_n137(x) + end +end + +def fun_l21_n893(x) + if (x < 1) + fun_l22_n479(x) + else + fun_l22_n196(x) + end +end + +def fun_l21_n894(x) + if (x < 1) + fun_l22_n418(x) + else + fun_l22_n124(x) + end +end + +def fun_l21_n895(x) + if (x < 1) + fun_l22_n658(x) + else + fun_l22_n196(x) + end +end + +def fun_l21_n896(x) + if (x < 1) + fun_l22_n739(x) + else + fun_l22_n454(x) + end +end + +def fun_l21_n897(x) + if (x < 1) + fun_l22_n716(x) + else + fun_l22_n150(x) + end +end + +def fun_l21_n898(x) + if (x < 1) + fun_l22_n356(x) + else + fun_l22_n264(x) + end +end + +def fun_l21_n899(x) + if (x < 1) + fun_l22_n667(x) + else + fun_l22_n629(x) + end +end + +def fun_l21_n900(x) + if (x < 1) + fun_l22_n879(x) + else + fun_l22_n237(x) + end +end + +def fun_l21_n901(x) + if (x < 1) + fun_l22_n462(x) + else + fun_l22_n401(x) + end +end + +def fun_l21_n902(x) + if (x < 1) + fun_l22_n902(x) + else + fun_l22_n203(x) + end +end + +def fun_l21_n903(x) + if (x < 1) + fun_l22_n802(x) + else + fun_l22_n383(x) + end +end + +def fun_l21_n904(x) + if (x < 1) + fun_l22_n672(x) + else + fun_l22_n808(x) + end +end + +def fun_l21_n905(x) + if (x < 1) + fun_l22_n625(x) + else + fun_l22_n320(x) + end +end + +def fun_l21_n906(x) + if (x < 1) + fun_l22_n963(x) + else + fun_l22_n101(x) + end +end + +def fun_l21_n907(x) + if (x < 1) + fun_l22_n609(x) + else + fun_l22_n500(x) + end +end + +def fun_l21_n908(x) + if (x < 1) + fun_l22_n79(x) + else + fun_l22_n774(x) + end +end + +def fun_l21_n909(x) + if (x < 1) + fun_l22_n152(x) + else + fun_l22_n245(x) + end +end + +def fun_l21_n910(x) + if (x < 1) + fun_l22_n981(x) + else + fun_l22_n647(x) + end +end + +def fun_l21_n911(x) + if (x < 1) + fun_l22_n457(x) + else + fun_l22_n394(x) + end +end + +def fun_l21_n912(x) + if (x < 1) + fun_l22_n516(x) + else + fun_l22_n411(x) + end +end + +def fun_l21_n913(x) + if (x < 1) + fun_l22_n212(x) + else + fun_l22_n159(x) + end +end + +def fun_l21_n914(x) + if (x < 1) + fun_l22_n756(x) + else + fun_l22_n612(x) + end +end + +def fun_l21_n915(x) + if (x < 1) + fun_l22_n78(x) + else + fun_l22_n387(x) + end +end + +def fun_l21_n916(x) + if (x < 1) + fun_l22_n973(x) + else + fun_l22_n854(x) + end +end + +def fun_l21_n917(x) + if (x < 1) + fun_l22_n613(x) + else + fun_l22_n78(x) + end +end + +def fun_l21_n918(x) + if (x < 1) + fun_l22_n199(x) + else + fun_l22_n637(x) + end +end + +def fun_l21_n919(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n804(x) + end +end + +def fun_l21_n920(x) + if (x < 1) + fun_l22_n410(x) + else + fun_l22_n728(x) + end +end + +def fun_l21_n921(x) + if (x < 1) + fun_l22_n139(x) + else + fun_l22_n236(x) + end +end + +def fun_l21_n922(x) + if (x < 1) + fun_l22_n443(x) + else + fun_l22_n683(x) + end +end + +def fun_l21_n923(x) + if (x < 1) + fun_l22_n226(x) + else + fun_l22_n906(x) + end +end + +def fun_l21_n924(x) + if (x < 1) + fun_l22_n487(x) + else + fun_l22_n551(x) + end +end + +def fun_l21_n925(x) + if (x < 1) + fun_l22_n143(x) + else + fun_l22_n932(x) + end +end + +def fun_l21_n926(x) + if (x < 1) + fun_l22_n533(x) + else + fun_l22_n307(x) + end +end + +def fun_l21_n927(x) + if (x < 1) + fun_l22_n89(x) + else + fun_l22_n278(x) + end +end + +def fun_l21_n928(x) + if (x < 1) + fun_l22_n802(x) + else + fun_l22_n18(x) + end +end + +def fun_l21_n929(x) + if (x < 1) + fun_l22_n266(x) + else + fun_l22_n924(x) + end +end + +def fun_l21_n930(x) + if (x < 1) + fun_l22_n607(x) + else + fun_l22_n47(x) + end +end + +def fun_l21_n931(x) + if (x < 1) + fun_l22_n241(x) + else + fun_l22_n983(x) + end +end + +def fun_l21_n932(x) + if (x < 1) + fun_l22_n264(x) + else + fun_l22_n88(x) + end +end + +def fun_l21_n933(x) + if (x < 1) + fun_l22_n26(x) + else + fun_l22_n940(x) + end +end + +def fun_l21_n934(x) + if (x < 1) + fun_l22_n688(x) + else + fun_l22_n248(x) + end +end + +def fun_l21_n935(x) + if (x < 1) + fun_l22_n704(x) + else + fun_l22_n808(x) + end +end + +def fun_l21_n936(x) + if (x < 1) + fun_l22_n91(x) + else + fun_l22_n650(x) + end +end + +def fun_l21_n937(x) + if (x < 1) + fun_l22_n308(x) + else + fun_l22_n389(x) + end +end + +def fun_l21_n938(x) + if (x < 1) + fun_l22_n63(x) + else + fun_l22_n704(x) + end +end + +def fun_l21_n939(x) + if (x < 1) + fun_l22_n785(x) + else + fun_l22_n852(x) + end +end + +def fun_l21_n940(x) + if (x < 1) + fun_l22_n515(x) + else + fun_l22_n148(x) + end +end + +def fun_l21_n941(x) + if (x < 1) + fun_l22_n607(x) + else + fun_l22_n162(x) + end +end + +def fun_l21_n942(x) + if (x < 1) + fun_l22_n34(x) + else + fun_l22_n167(x) + end +end + +def fun_l21_n943(x) + if (x < 1) + fun_l22_n239(x) + else + fun_l22_n100(x) + end +end + +def fun_l21_n944(x) + if (x < 1) + fun_l22_n724(x) + else + fun_l22_n702(x) + end +end + +def fun_l21_n945(x) + if (x < 1) + fun_l22_n121(x) + else + fun_l22_n89(x) + end +end + +def fun_l21_n946(x) + if (x < 1) + fun_l22_n699(x) + else + fun_l22_n410(x) + end +end + +def fun_l21_n947(x) + if (x < 1) + fun_l22_n33(x) + else + fun_l22_n843(x) + end +end + +def fun_l21_n948(x) + if (x < 1) + fun_l22_n327(x) + else + fun_l22_n702(x) + end +end + +def fun_l21_n949(x) + if (x < 1) + fun_l22_n191(x) + else + fun_l22_n137(x) + end +end + +def fun_l21_n950(x) + if (x < 1) + fun_l22_n834(x) + else + fun_l22_n504(x) + end +end + +def fun_l21_n951(x) + if (x < 1) + fun_l22_n444(x) + else + fun_l22_n857(x) + end +end + +def fun_l21_n952(x) + if (x < 1) + fun_l22_n961(x) + else + fun_l22_n817(x) + end +end + +def fun_l21_n953(x) + if (x < 1) + fun_l22_n166(x) + else + fun_l22_n538(x) + end +end + +def fun_l21_n954(x) + if (x < 1) + fun_l22_n934(x) + else + fun_l22_n552(x) + end +end + +def fun_l21_n955(x) + if (x < 1) + fun_l22_n144(x) + else + fun_l22_n814(x) + end +end + +def fun_l21_n956(x) + if (x < 1) + fun_l22_n965(x) + else + fun_l22_n929(x) + end +end + +def fun_l21_n957(x) + if (x < 1) + fun_l22_n812(x) + else + fun_l22_n529(x) + end +end + +def fun_l21_n958(x) + if (x < 1) + fun_l22_n625(x) + else + fun_l22_n974(x) + end +end + +def fun_l21_n959(x) + if (x < 1) + fun_l22_n627(x) + else + fun_l22_n262(x) + end +end + +def fun_l21_n960(x) + if (x < 1) + fun_l22_n751(x) + else + fun_l22_n858(x) + end +end + +def fun_l21_n961(x) + if (x < 1) + fun_l22_n819(x) + else + fun_l22_n408(x) + end +end + +def fun_l21_n962(x) + if (x < 1) + fun_l22_n635(x) + else + fun_l22_n730(x) + end +end + +def fun_l21_n963(x) + if (x < 1) + fun_l22_n865(x) + else + fun_l22_n919(x) + end +end + +def fun_l21_n964(x) + if (x < 1) + fun_l22_n368(x) + else + fun_l22_n912(x) + end +end + +def fun_l21_n965(x) + if (x < 1) + fun_l22_n202(x) + else + fun_l22_n493(x) + end +end + +def fun_l21_n966(x) + if (x < 1) + fun_l22_n191(x) + else + fun_l22_n632(x) + end +end + +def fun_l21_n967(x) + if (x < 1) + fun_l22_n96(x) + else + fun_l22_n329(x) + end +end + +def fun_l21_n968(x) + if (x < 1) + fun_l22_n42(x) + else + fun_l22_n196(x) + end +end + +def fun_l21_n969(x) + if (x < 1) + fun_l22_n521(x) + else + fun_l22_n875(x) + end +end + +def fun_l21_n970(x) + if (x < 1) + fun_l22_n202(x) + else + fun_l22_n373(x) + end +end + +def fun_l21_n971(x) + if (x < 1) + fun_l22_n647(x) + else + fun_l22_n591(x) + end +end + +def fun_l21_n972(x) + if (x < 1) + fun_l22_n341(x) + else + fun_l22_n935(x) + end +end + +def fun_l21_n973(x) + if (x < 1) + fun_l22_n151(x) + else + fun_l22_n396(x) + end +end + +def fun_l21_n974(x) + if (x < 1) + fun_l22_n65(x) + else + fun_l22_n562(x) + end +end + +def fun_l21_n975(x) + if (x < 1) + fun_l22_n450(x) + else + fun_l22_n482(x) + end +end + +def fun_l21_n976(x) + if (x < 1) + fun_l22_n179(x) + else + fun_l22_n838(x) + end +end + +def fun_l21_n977(x) + if (x < 1) + fun_l22_n571(x) + else + fun_l22_n703(x) + end +end + +def fun_l21_n978(x) + if (x < 1) + fun_l22_n540(x) + else + fun_l22_n728(x) + end +end + +def fun_l21_n979(x) + if (x < 1) + fun_l22_n170(x) + else + fun_l22_n487(x) + end +end + +def fun_l21_n980(x) + if (x < 1) + fun_l22_n12(x) + else + fun_l22_n165(x) + end +end + +def fun_l21_n981(x) + if (x < 1) + fun_l22_n722(x) + else + fun_l22_n456(x) + end +end + +def fun_l21_n982(x) + if (x < 1) + fun_l22_n313(x) + else + fun_l22_n175(x) + end +end + +def fun_l21_n983(x) + if (x < 1) + fun_l22_n473(x) + else + fun_l22_n840(x) + end +end + +def fun_l21_n984(x) + if (x < 1) + fun_l22_n942(x) + else + fun_l22_n804(x) + end +end + +def fun_l21_n985(x) + if (x < 1) + fun_l22_n116(x) + else + fun_l22_n117(x) + end +end + +def fun_l21_n986(x) + if (x < 1) + fun_l22_n610(x) + else + fun_l22_n580(x) + end +end + +def fun_l21_n987(x) + if (x < 1) + fun_l22_n299(x) + else + fun_l22_n416(x) + end +end + +def fun_l21_n988(x) + if (x < 1) + fun_l22_n507(x) + else + fun_l22_n995(x) + end +end + +def fun_l21_n989(x) + if (x < 1) + fun_l22_n239(x) + else + fun_l22_n414(x) + end +end + +def fun_l21_n990(x) + if (x < 1) + fun_l22_n488(x) + else + fun_l22_n874(x) + end +end + +def fun_l21_n991(x) + if (x < 1) + fun_l22_n586(x) + else + fun_l22_n88(x) + end +end + +def fun_l21_n992(x) + if (x < 1) + fun_l22_n391(x) + else + fun_l22_n254(x) + end +end + +def fun_l21_n993(x) + if (x < 1) + fun_l22_n64(x) + else + fun_l22_n485(x) + end +end + +def fun_l21_n994(x) + if (x < 1) + fun_l22_n507(x) + else + fun_l22_n266(x) + end +end + +def fun_l21_n995(x) + if (x < 1) + fun_l22_n660(x) + else + fun_l22_n208(x) + end +end + +def fun_l21_n996(x) + if (x < 1) + fun_l22_n731(x) + else + fun_l22_n882(x) + end +end + +def fun_l21_n997(x) + if (x < 1) + fun_l22_n283(x) + else + fun_l22_n719(x) + end +end + +def fun_l21_n998(x) + if (x < 1) + fun_l22_n794(x) + else + fun_l22_n654(x) + end +end + +def fun_l21_n999(x) + if (x < 1) + fun_l22_n642(x) + else + fun_l22_n158(x) + end +end + +def fun_l22_n0(x) + if (x < 1) + fun_l23_n423(x) + else + fun_l23_n28(x) + end +end + +def fun_l22_n1(x) + if (x < 1) + fun_l23_n494(x) + else + fun_l23_n894(x) + end +end + +def fun_l22_n2(x) + if (x < 1) + fun_l23_n735(x) + else + fun_l23_n584(x) + end +end + +def fun_l22_n3(x) + if (x < 1) + fun_l23_n982(x) + else + fun_l23_n790(x) + end +end + +def fun_l22_n4(x) + if (x < 1) + fun_l23_n281(x) + else + fun_l23_n256(x) + end +end + +def fun_l22_n5(x) + if (x < 1) + fun_l23_n286(x) + else + fun_l23_n48(x) + end +end + +def fun_l22_n6(x) + if (x < 1) + fun_l23_n982(x) + else + fun_l23_n731(x) + end +end + +def fun_l22_n7(x) + if (x < 1) + fun_l23_n83(x) + else + fun_l23_n267(x) + end +end + +def fun_l22_n8(x) + if (x < 1) + fun_l23_n730(x) + else + fun_l23_n47(x) + end +end + +def fun_l22_n9(x) + if (x < 1) + fun_l23_n106(x) + else + fun_l23_n125(x) + end +end + +def fun_l22_n10(x) + if (x < 1) + fun_l23_n392(x) + else + fun_l23_n114(x) + end +end + +def fun_l22_n11(x) + if (x < 1) + fun_l23_n778(x) + else + fun_l23_n103(x) + end +end + +def fun_l22_n12(x) + if (x < 1) + fun_l23_n145(x) + else + fun_l23_n449(x) + end +end + +def fun_l22_n13(x) + if (x < 1) + fun_l23_n106(x) + else + fun_l23_n67(x) + end +end + +def fun_l22_n14(x) + if (x < 1) + fun_l23_n721(x) + else + fun_l23_n844(x) + end +end + +def fun_l22_n15(x) + if (x < 1) + fun_l23_n411(x) + else + fun_l23_n479(x) + end +end + +def fun_l22_n16(x) + if (x < 1) + fun_l23_n718(x) + else + fun_l23_n203(x) + end +end + +def fun_l22_n17(x) + if (x < 1) + fun_l23_n660(x) + else + fun_l23_n606(x) + end +end + +def fun_l22_n18(x) + if (x < 1) + fun_l23_n225(x) + else + fun_l23_n310(x) + end +end + +def fun_l22_n19(x) + if (x < 1) + fun_l23_n923(x) + else + fun_l23_n10(x) + end +end + +def fun_l22_n20(x) + if (x < 1) + fun_l23_n88(x) + else + fun_l23_n488(x) + end +end + +def fun_l22_n21(x) + if (x < 1) + fun_l23_n986(x) + else + fun_l23_n123(x) + end +end + +def fun_l22_n22(x) + if (x < 1) + fun_l23_n91(x) + else + fun_l23_n445(x) + end +end + +def fun_l22_n23(x) + if (x < 1) + fun_l23_n525(x) + else + fun_l23_n454(x) + end +end + +def fun_l22_n24(x) + if (x < 1) + fun_l23_n55(x) + else + fun_l23_n540(x) + end +end + +def fun_l22_n25(x) + if (x < 1) + fun_l23_n562(x) + else + fun_l23_n323(x) + end +end + +def fun_l22_n26(x) + if (x < 1) + fun_l23_n796(x) + else + fun_l23_n443(x) + end +end + +def fun_l22_n27(x) + if (x < 1) + fun_l23_n421(x) + else + fun_l23_n654(x) + end +end + +def fun_l22_n28(x) + if (x < 1) + fun_l23_n910(x) + else + fun_l23_n421(x) + end +end + +def fun_l22_n29(x) + if (x < 1) + fun_l23_n184(x) + else + fun_l23_n24(x) + end +end + +def fun_l22_n30(x) + if (x < 1) + fun_l23_n803(x) + else + fun_l23_n375(x) + end +end + +def fun_l22_n31(x) + if (x < 1) + fun_l23_n662(x) + else + fun_l23_n50(x) + end +end + +def fun_l22_n32(x) + if (x < 1) + fun_l23_n69(x) + else + fun_l23_n198(x) + end +end + +def fun_l22_n33(x) + if (x < 1) + fun_l23_n465(x) + else + fun_l23_n979(x) + end +end + +def fun_l22_n34(x) + if (x < 1) + fun_l23_n743(x) + else + fun_l23_n859(x) + end +end + +def fun_l22_n35(x) + if (x < 1) + fun_l23_n524(x) + else + fun_l23_n157(x) + end +end + +def fun_l22_n36(x) + if (x < 1) + fun_l23_n530(x) + else + fun_l23_n938(x) + end +end + +def fun_l22_n37(x) + if (x < 1) + fun_l23_n386(x) + else + fun_l23_n882(x) + end +end + +def fun_l22_n38(x) + if (x < 1) + fun_l23_n373(x) + else + fun_l23_n220(x) + end +end + +def fun_l22_n39(x) + if (x < 1) + fun_l23_n783(x) + else + fun_l23_n731(x) + end +end + +def fun_l22_n40(x) + if (x < 1) + fun_l23_n911(x) + else + fun_l23_n373(x) + end +end + +def fun_l22_n41(x) + if (x < 1) + fun_l23_n516(x) + else + fun_l23_n586(x) + end +end + +def fun_l22_n42(x) + if (x < 1) + fun_l23_n40(x) + else + fun_l23_n350(x) + end +end + +def fun_l22_n43(x) + if (x < 1) + fun_l23_n690(x) + else + fun_l23_n349(x) + end +end + +def fun_l22_n44(x) + if (x < 1) + fun_l23_n170(x) + else + fun_l23_n758(x) + end +end + +def fun_l22_n45(x) + if (x < 1) + fun_l23_n317(x) + else + fun_l23_n856(x) + end +end + +def fun_l22_n46(x) + if (x < 1) + fun_l23_n692(x) + else + fun_l23_n330(x) + end +end + +def fun_l22_n47(x) + if (x < 1) + fun_l23_n848(x) + else + fun_l23_n767(x) + end +end + +def fun_l22_n48(x) + if (x < 1) + fun_l23_n683(x) + else + fun_l23_n225(x) + end +end + +def fun_l22_n49(x) + if (x < 1) + fun_l23_n967(x) + else + fun_l23_n872(x) + end +end + +def fun_l22_n50(x) + if (x < 1) + fun_l23_n584(x) + else + fun_l23_n799(x) + end +end + +def fun_l22_n51(x) + if (x < 1) + fun_l23_n156(x) + else + fun_l23_n710(x) + end +end + +def fun_l22_n52(x) + if (x < 1) + fun_l23_n129(x) + else + fun_l23_n733(x) + end +end + +def fun_l22_n53(x) + if (x < 1) + fun_l23_n364(x) + else + fun_l23_n460(x) + end +end + +def fun_l22_n54(x) + if (x < 1) + fun_l23_n284(x) + else + fun_l23_n13(x) + end +end + +def fun_l22_n55(x) + if (x < 1) + fun_l23_n734(x) + else + fun_l23_n498(x) + end +end + +def fun_l22_n56(x) + if (x < 1) + fun_l23_n981(x) + else + fun_l23_n602(x) + end +end + +def fun_l22_n57(x) + if (x < 1) + fun_l23_n632(x) + else + fun_l23_n123(x) + end +end + +def fun_l22_n58(x) + if (x < 1) + fun_l23_n602(x) + else + fun_l23_n274(x) + end +end + +def fun_l22_n59(x) + if (x < 1) + fun_l23_n718(x) + else + fun_l23_n351(x) + end +end + +def fun_l22_n60(x) + if (x < 1) + fun_l23_n618(x) + else + fun_l23_n583(x) + end +end + +def fun_l22_n61(x) + if (x < 1) + fun_l23_n63(x) + else + fun_l23_n573(x) + end +end + +def fun_l22_n62(x) + if (x < 1) + fun_l23_n73(x) + else + fun_l23_n429(x) + end +end + +def fun_l22_n63(x) + if (x < 1) + fun_l23_n969(x) + else + fun_l23_n518(x) + end +end + +def fun_l22_n64(x) + if (x < 1) + fun_l23_n493(x) + else + fun_l23_n868(x) + end +end + +def fun_l22_n65(x) + if (x < 1) + fun_l23_n31(x) + else + fun_l23_n366(x) + end +end + +def fun_l22_n66(x) + if (x < 1) + fun_l23_n442(x) + else + fun_l23_n362(x) + end +end + +def fun_l22_n67(x) + if (x < 1) + fun_l23_n804(x) + else + fun_l23_n513(x) + end +end + +def fun_l22_n68(x) + if (x < 1) + fun_l23_n973(x) + else + fun_l23_n723(x) + end +end + +def fun_l22_n69(x) + if (x < 1) + fun_l23_n424(x) + else + fun_l23_n247(x) + end +end + +def fun_l22_n70(x) + if (x < 1) + fun_l23_n992(x) + else + fun_l23_n944(x) + end +end + +def fun_l22_n71(x) + if (x < 1) + fun_l23_n209(x) + else + fun_l23_n645(x) + end +end + +def fun_l22_n72(x) + if (x < 1) + fun_l23_n373(x) + else + fun_l23_n540(x) + end +end + +def fun_l22_n73(x) + if (x < 1) + fun_l23_n785(x) + else + fun_l23_n840(x) + end +end + +def fun_l22_n74(x) + if (x < 1) + fun_l23_n607(x) + else + fun_l23_n584(x) + end +end + +def fun_l22_n75(x) + if (x < 1) + fun_l23_n331(x) + else + fun_l23_n196(x) + end +end + +def fun_l22_n76(x) + if (x < 1) + fun_l23_n453(x) + else + fun_l23_n991(x) + end +end + +def fun_l22_n77(x) + if (x < 1) + fun_l23_n689(x) + else + fun_l23_n222(x) + end +end + +def fun_l22_n78(x) + if (x < 1) + fun_l23_n446(x) + else + fun_l23_n767(x) + end +end + +def fun_l22_n79(x) + if (x < 1) + fun_l23_n648(x) + else + fun_l23_n811(x) + end +end + +def fun_l22_n80(x) + if (x < 1) + fun_l23_n210(x) + else + fun_l23_n52(x) + end +end + +def fun_l22_n81(x) + if (x < 1) + fun_l23_n786(x) + else + fun_l23_n984(x) + end +end + +def fun_l22_n82(x) + if (x < 1) + fun_l23_n693(x) + else + fun_l23_n103(x) + end +end + +def fun_l22_n83(x) + if (x < 1) + fun_l23_n768(x) + else + fun_l23_n794(x) + end +end + +def fun_l22_n84(x) + if (x < 1) + fun_l23_n820(x) + else + fun_l23_n774(x) + end +end + +def fun_l22_n85(x) + if (x < 1) + fun_l23_n972(x) + else + fun_l23_n254(x) + end +end + +def fun_l22_n86(x) + if (x < 1) + fun_l23_n609(x) + else + fun_l23_n524(x) + end +end + +def fun_l22_n87(x) + if (x < 1) + fun_l23_n486(x) + else + fun_l23_n173(x) + end +end + +def fun_l22_n88(x) + if (x < 1) + fun_l23_n236(x) + else + fun_l23_n359(x) + end +end + +def fun_l22_n89(x) + if (x < 1) + fun_l23_n292(x) + else + fun_l23_n232(x) + end +end + +def fun_l22_n90(x) + if (x < 1) + fun_l23_n104(x) + else + fun_l23_n799(x) + end +end + +def fun_l22_n91(x) + if (x < 1) + fun_l23_n957(x) + else + fun_l23_n836(x) + end +end + +def fun_l22_n92(x) + if (x < 1) + fun_l23_n179(x) + else + fun_l23_n416(x) + end +end + +def fun_l22_n93(x) + if (x < 1) + fun_l23_n281(x) + else + fun_l23_n530(x) + end +end + +def fun_l22_n94(x) + if (x < 1) + fun_l23_n627(x) + else + fun_l23_n577(x) + end +end + +def fun_l22_n95(x) + if (x < 1) + fun_l23_n594(x) + else + fun_l23_n949(x) + end +end + +def fun_l22_n96(x) + if (x < 1) + fun_l23_n408(x) + else + fun_l23_n547(x) + end +end + +def fun_l22_n97(x) + if (x < 1) + fun_l23_n276(x) + else + fun_l23_n105(x) + end +end + +def fun_l22_n98(x) + if (x < 1) + fun_l23_n181(x) + else + fun_l23_n659(x) + end +end + +def fun_l22_n99(x) + if (x < 1) + fun_l23_n7(x) + else + fun_l23_n423(x) + end +end + +def fun_l22_n100(x) + if (x < 1) + fun_l23_n123(x) + else + fun_l23_n244(x) + end +end + +def fun_l22_n101(x) + if (x < 1) + fun_l23_n476(x) + else + fun_l23_n319(x) + end +end + +def fun_l22_n102(x) + if (x < 1) + fun_l23_n443(x) + else + fun_l23_n959(x) + end +end + +def fun_l22_n103(x) + if (x < 1) + fun_l23_n78(x) + else + fun_l23_n490(x) + end +end + +def fun_l22_n104(x) + if (x < 1) + fun_l23_n761(x) + else + fun_l23_n23(x) + end +end + +def fun_l22_n105(x) + if (x < 1) + fun_l23_n126(x) + else + fun_l23_n426(x) + end +end + +def fun_l22_n106(x) + if (x < 1) + fun_l23_n740(x) + else + fun_l23_n328(x) + end +end + +def fun_l22_n107(x) + if (x < 1) + fun_l23_n249(x) + else + fun_l23_n890(x) + end +end + +def fun_l22_n108(x) + if (x < 1) + fun_l23_n665(x) + else + fun_l23_n60(x) + end +end + +def fun_l22_n109(x) + if (x < 1) + fun_l23_n617(x) + else + fun_l23_n42(x) + end +end + +def fun_l22_n110(x) + if (x < 1) + fun_l23_n484(x) + else + fun_l23_n480(x) + end +end + +def fun_l22_n111(x) + if (x < 1) + fun_l23_n135(x) + else + fun_l23_n447(x) + end +end + +def fun_l22_n112(x) + if (x < 1) + fun_l23_n881(x) + else + fun_l23_n410(x) + end +end + +def fun_l22_n113(x) + if (x < 1) + fun_l23_n989(x) + else + fun_l23_n849(x) + end +end + +def fun_l22_n114(x) + if (x < 1) + fun_l23_n660(x) + else + fun_l23_n307(x) + end +end + +def fun_l22_n115(x) + if (x < 1) + fun_l23_n372(x) + else + fun_l23_n150(x) + end +end + +def fun_l22_n116(x) + if (x < 1) + fun_l23_n770(x) + else + fun_l23_n109(x) + end +end + +def fun_l22_n117(x) + if (x < 1) + fun_l23_n364(x) + else + fun_l23_n321(x) + end +end + +def fun_l22_n118(x) + if (x < 1) + fun_l23_n363(x) + else + fun_l23_n876(x) + end +end + +def fun_l22_n119(x) + if (x < 1) + fun_l23_n114(x) + else + fun_l23_n25(x) + end +end + +def fun_l22_n120(x) + if (x < 1) + fun_l23_n160(x) + else + fun_l23_n744(x) + end +end + +def fun_l22_n121(x) + if (x < 1) + fun_l23_n265(x) + else + fun_l23_n972(x) + end +end + +def fun_l22_n122(x) + if (x < 1) + fun_l23_n259(x) + else + fun_l23_n203(x) + end +end + +def fun_l22_n123(x) + if (x < 1) + fun_l23_n865(x) + else + fun_l23_n137(x) + end +end + +def fun_l22_n124(x) + if (x < 1) + fun_l23_n427(x) + else + fun_l23_n437(x) + end +end + +def fun_l22_n125(x) + if (x < 1) + fun_l23_n405(x) + else + fun_l23_n603(x) + end +end + +def fun_l22_n126(x) + if (x < 1) + fun_l23_n938(x) + else + fun_l23_n505(x) + end +end + +def fun_l22_n127(x) + if (x < 1) + fun_l23_n307(x) + else + fun_l23_n26(x) + end +end + +def fun_l22_n128(x) + if (x < 1) + fun_l23_n15(x) + else + fun_l23_n406(x) + end +end + +def fun_l22_n129(x) + if (x < 1) + fun_l23_n633(x) + else + fun_l23_n831(x) + end +end + +def fun_l22_n130(x) + if (x < 1) + fun_l23_n805(x) + else + fun_l23_n216(x) + end +end + +def fun_l22_n131(x) + if (x < 1) + fun_l23_n552(x) + else + fun_l23_n864(x) + end +end + +def fun_l22_n132(x) + if (x < 1) + fun_l23_n50(x) + else + fun_l23_n805(x) + end +end + +def fun_l22_n133(x) + if (x < 1) + fun_l23_n823(x) + else + fun_l23_n427(x) + end +end + +def fun_l22_n134(x) + if (x < 1) + fun_l23_n964(x) + else + fun_l23_n214(x) + end +end + +def fun_l22_n135(x) + if (x < 1) + fun_l23_n267(x) + else + fun_l23_n351(x) + end +end + +def fun_l22_n136(x) + if (x < 1) + fun_l23_n557(x) + else + fun_l23_n257(x) + end +end + +def fun_l22_n137(x) + if (x < 1) + fun_l23_n966(x) + else + fun_l23_n248(x) + end +end + +def fun_l22_n138(x) + if (x < 1) + fun_l23_n569(x) + else + fun_l23_n376(x) + end +end + +def fun_l22_n139(x) + if (x < 1) + fun_l23_n198(x) + else + fun_l23_n595(x) + end +end + +def fun_l22_n140(x) + if (x < 1) + fun_l23_n107(x) + else + fun_l23_n134(x) + end +end + +def fun_l22_n141(x) + if (x < 1) + fun_l23_n113(x) + else + fun_l23_n290(x) + end +end + +def fun_l22_n142(x) + if (x < 1) + fun_l23_n721(x) + else + fun_l23_n641(x) + end +end + +def fun_l22_n143(x) + if (x < 1) + fun_l23_n535(x) + else + fun_l23_n103(x) + end +end + +def fun_l22_n144(x) + if (x < 1) + fun_l23_n690(x) + else + fun_l23_n125(x) + end +end + +def fun_l22_n145(x) + if (x < 1) + fun_l23_n514(x) + else + fun_l23_n999(x) + end +end + +def fun_l22_n146(x) + if (x < 1) + fun_l23_n503(x) + else + fun_l23_n951(x) + end +end + +def fun_l22_n147(x) + if (x < 1) + fun_l23_n413(x) + else + fun_l23_n634(x) + end +end + +def fun_l22_n148(x) + if (x < 1) + fun_l23_n818(x) + else + fun_l23_n286(x) + end +end + +def fun_l22_n149(x) + if (x < 1) + fun_l23_n768(x) + else + fun_l23_n832(x) + end +end + +def fun_l22_n150(x) + if (x < 1) + fun_l23_n128(x) + else + fun_l23_n588(x) + end +end + +def fun_l22_n151(x) + if (x < 1) + fun_l23_n787(x) + else + fun_l23_n742(x) + end +end + +def fun_l22_n152(x) + if (x < 1) + fun_l23_n166(x) + else + fun_l23_n856(x) + end +end + +def fun_l22_n153(x) + if (x < 1) + fun_l23_n377(x) + else + fun_l23_n90(x) + end +end + +def fun_l22_n154(x) + if (x < 1) + fun_l23_n851(x) + else + fun_l23_n591(x) + end +end + +def fun_l22_n155(x) + if (x < 1) + fun_l23_n896(x) + else + fun_l23_n372(x) + end +end + +def fun_l22_n156(x) + if (x < 1) + fun_l23_n132(x) + else + fun_l23_n144(x) + end +end + +def fun_l22_n157(x) + if (x < 1) + fun_l23_n251(x) + else + fun_l23_n620(x) + end +end + +def fun_l22_n158(x) + if (x < 1) + fun_l23_n612(x) + else + fun_l23_n246(x) + end +end + +def fun_l22_n159(x) + if (x < 1) + fun_l23_n530(x) + else + fun_l23_n94(x) + end +end + +def fun_l22_n160(x) + if (x < 1) + fun_l23_n310(x) + else + fun_l23_n706(x) + end +end + +def fun_l22_n161(x) + if (x < 1) + fun_l23_n420(x) + else + fun_l23_n576(x) + end +end + +def fun_l22_n162(x) + if (x < 1) + fun_l23_n544(x) + else + fun_l23_n277(x) + end +end + +def fun_l22_n163(x) + if (x < 1) + fun_l23_n770(x) + else + fun_l23_n94(x) + end +end + +def fun_l22_n164(x) + if (x < 1) + fun_l23_n49(x) + else + fun_l23_n576(x) + end +end + +def fun_l22_n165(x) + if (x < 1) + fun_l23_n610(x) + else + fun_l23_n184(x) + end +end + +def fun_l22_n166(x) + if (x < 1) + fun_l23_n974(x) + else + fun_l23_n54(x) + end +end + +def fun_l22_n167(x) + if (x < 1) + fun_l23_n179(x) + else + fun_l23_n485(x) + end +end + +def fun_l22_n168(x) + if (x < 1) + fun_l23_n114(x) + else + fun_l23_n766(x) + end +end + +def fun_l22_n169(x) + if (x < 1) + fun_l23_n399(x) + else + fun_l23_n830(x) + end +end + +def fun_l22_n170(x) + if (x < 1) + fun_l23_n332(x) + else + fun_l23_n536(x) + end +end + +def fun_l22_n171(x) + if (x < 1) + fun_l23_n384(x) + else + fun_l23_n773(x) + end +end + +def fun_l22_n172(x) + if (x < 1) + fun_l23_n52(x) + else + fun_l23_n7(x) + end +end + +def fun_l22_n173(x) + if (x < 1) + fun_l23_n85(x) + else + fun_l23_n803(x) + end +end + +def fun_l22_n174(x) + if (x < 1) + fun_l23_n853(x) + else + fun_l23_n682(x) + end +end + +def fun_l22_n175(x) + if (x < 1) + fun_l23_n112(x) + else + fun_l23_n295(x) + end +end + +def fun_l22_n176(x) + if (x < 1) + fun_l23_n347(x) + else + fun_l23_n908(x) + end +end + +def fun_l22_n177(x) + if (x < 1) + fun_l23_n267(x) + else + fun_l23_n19(x) + end +end + +def fun_l22_n178(x) + if (x < 1) + fun_l23_n8(x) + else + fun_l23_n739(x) + end +end + +def fun_l22_n179(x) + if (x < 1) + fun_l23_n201(x) + else + fun_l23_n321(x) + end +end + +def fun_l22_n180(x) + if (x < 1) + fun_l23_n773(x) + else + fun_l23_n224(x) + end +end + +def fun_l22_n181(x) + if (x < 1) + fun_l23_n966(x) + else + fun_l23_n324(x) + end +end + +def fun_l22_n182(x) + if (x < 1) + fun_l23_n389(x) + else + fun_l23_n190(x) + end +end + +def fun_l22_n183(x) + if (x < 1) + fun_l23_n918(x) + else + fun_l23_n512(x) + end +end + +def fun_l22_n184(x) + if (x < 1) + fun_l23_n360(x) + else + fun_l23_n702(x) + end +end + +def fun_l22_n185(x) + if (x < 1) + fun_l23_n794(x) + else + fun_l23_n51(x) + end +end + +def fun_l22_n186(x) + if (x < 1) + fun_l23_n982(x) + else + fun_l23_n779(x) + end +end + +def fun_l22_n187(x) + if (x < 1) + fun_l23_n263(x) + else + fun_l23_n659(x) + end +end + +def fun_l22_n188(x) + if (x < 1) + fun_l23_n203(x) + else + fun_l23_n705(x) + end +end + +def fun_l22_n189(x) + if (x < 1) + fun_l23_n976(x) + else + fun_l23_n307(x) + end +end + +def fun_l22_n190(x) + if (x < 1) + fun_l23_n281(x) + else + fun_l23_n880(x) + end +end + +def fun_l22_n191(x) + if (x < 1) + fun_l23_n238(x) + else + fun_l23_n752(x) + end +end + +def fun_l22_n192(x) + if (x < 1) + fun_l23_n679(x) + else + fun_l23_n935(x) + end +end + +def fun_l22_n193(x) + if (x < 1) + fun_l23_n823(x) + else + fun_l23_n340(x) + end +end + +def fun_l22_n194(x) + if (x < 1) + fun_l23_n687(x) + else + fun_l23_n71(x) + end +end + +def fun_l22_n195(x) + if (x < 1) + fun_l23_n47(x) + else + fun_l23_n119(x) + end +end + +def fun_l22_n196(x) + if (x < 1) + fun_l23_n702(x) + else + fun_l23_n213(x) + end +end + +def fun_l22_n197(x) + if (x < 1) + fun_l23_n300(x) + else + fun_l23_n52(x) + end +end + +def fun_l22_n198(x) + if (x < 1) + fun_l23_n85(x) + else + fun_l23_n845(x) + end +end + +def fun_l22_n199(x) + if (x < 1) + fun_l23_n503(x) + else + fun_l23_n322(x) + end +end + +def fun_l22_n200(x) + if (x < 1) + fun_l23_n151(x) + else + fun_l23_n743(x) + end +end + +def fun_l22_n201(x) + if (x < 1) + fun_l23_n531(x) + else + fun_l23_n597(x) + end +end + +def fun_l22_n202(x) + if (x < 1) + fun_l23_n120(x) + else + fun_l23_n300(x) + end +end + +def fun_l22_n203(x) + if (x < 1) + fun_l23_n124(x) + else + fun_l23_n609(x) + end +end + +def fun_l22_n204(x) + if (x < 1) + fun_l23_n945(x) + else + fun_l23_n498(x) + end +end + +def fun_l22_n205(x) + if (x < 1) + fun_l23_n983(x) + else + fun_l23_n16(x) + end +end + +def fun_l22_n206(x) + if (x < 1) + fun_l23_n271(x) + else + fun_l23_n612(x) + end +end + +def fun_l22_n207(x) + if (x < 1) + fun_l23_n762(x) + else + fun_l23_n596(x) + end +end + +def fun_l22_n208(x) + if (x < 1) + fun_l23_n992(x) + else + fun_l23_n90(x) + end +end + +def fun_l22_n209(x) + if (x < 1) + fun_l23_n994(x) + else + fun_l23_n265(x) + end +end + +def fun_l22_n210(x) + if (x < 1) + fun_l23_n449(x) + else + fun_l23_n609(x) + end +end + +def fun_l22_n211(x) + if (x < 1) + fun_l23_n816(x) + else + fun_l23_n8(x) + end +end + +def fun_l22_n212(x) + if (x < 1) + fun_l23_n526(x) + else + fun_l23_n982(x) + end +end + +def fun_l22_n213(x) + if (x < 1) + fun_l23_n25(x) + else + fun_l23_n302(x) + end +end + +def fun_l22_n214(x) + if (x < 1) + fun_l23_n868(x) + else + fun_l23_n895(x) + end +end + +def fun_l22_n215(x) + if (x < 1) + fun_l23_n3(x) + else + fun_l23_n914(x) + end +end + +def fun_l22_n216(x) + if (x < 1) + fun_l23_n106(x) + else + fun_l23_n271(x) + end +end + +def fun_l22_n217(x) + if (x < 1) + fun_l23_n567(x) + else + fun_l23_n931(x) + end +end + +def fun_l22_n218(x) + if (x < 1) + fun_l23_n7(x) + else + fun_l23_n319(x) + end +end + +def fun_l22_n219(x) + if (x < 1) + fun_l23_n510(x) + else + fun_l23_n753(x) + end +end + +def fun_l22_n220(x) + if (x < 1) + fun_l23_n529(x) + else + fun_l23_n514(x) + end +end + +def fun_l22_n221(x) + if (x < 1) + fun_l23_n871(x) + else + fun_l23_n571(x) + end +end + +def fun_l22_n222(x) + if (x < 1) + fun_l23_n739(x) + else + fun_l23_n716(x) + end +end + +def fun_l22_n223(x) + if (x < 1) + fun_l23_n781(x) + else + fun_l23_n730(x) + end +end + +def fun_l22_n224(x) + if (x < 1) + fun_l23_n647(x) + else + fun_l23_n647(x) + end +end + +def fun_l22_n225(x) + if (x < 1) + fun_l23_n968(x) + else + fun_l23_n680(x) + end +end + +def fun_l22_n226(x) + if (x < 1) + fun_l23_n400(x) + else + fun_l23_n725(x) + end +end + +def fun_l22_n227(x) + if (x < 1) + fun_l23_n386(x) + else + fun_l23_n859(x) + end +end + +def fun_l22_n228(x) + if (x < 1) + fun_l23_n751(x) + else + fun_l23_n640(x) + end +end + +def fun_l22_n229(x) + if (x < 1) + fun_l23_n273(x) + else + fun_l23_n754(x) + end +end + +def fun_l22_n230(x) + if (x < 1) + fun_l23_n861(x) + else + fun_l23_n783(x) + end +end + +def fun_l22_n231(x) + if (x < 1) + fun_l23_n665(x) + else + fun_l23_n18(x) + end +end + +def fun_l22_n232(x) + if (x < 1) + fun_l23_n680(x) + else + fun_l23_n471(x) + end +end + +def fun_l22_n233(x) + if (x < 1) + fun_l23_n400(x) + else + fun_l23_n935(x) + end +end + +def fun_l22_n234(x) + if (x < 1) + fun_l23_n563(x) + else + fun_l23_n799(x) + end +end + +def fun_l22_n235(x) + if (x < 1) + fun_l23_n712(x) + else + fun_l23_n20(x) + end +end + +def fun_l22_n236(x) + if (x < 1) + fun_l23_n579(x) + else + fun_l23_n152(x) + end +end + +def fun_l22_n237(x) + if (x < 1) + fun_l23_n752(x) + else + fun_l23_n282(x) + end +end + +def fun_l22_n238(x) + if (x < 1) + fun_l23_n609(x) + else + fun_l23_n980(x) + end +end + +def fun_l22_n239(x) + if (x < 1) + fun_l23_n916(x) + else + fun_l23_n52(x) + end +end + +def fun_l22_n240(x) + if (x < 1) + fun_l23_n468(x) + else + fun_l23_n735(x) + end +end + +def fun_l22_n241(x) + if (x < 1) + fun_l23_n894(x) + else + fun_l23_n776(x) + end +end + +def fun_l22_n242(x) + if (x < 1) + fun_l23_n782(x) + else + fun_l23_n406(x) + end +end + +def fun_l22_n243(x) + if (x < 1) + fun_l23_n90(x) + else + fun_l23_n226(x) + end +end + +def fun_l22_n244(x) + if (x < 1) + fun_l23_n967(x) + else + fun_l23_n252(x) + end +end + +def fun_l22_n245(x) + if (x < 1) + fun_l23_n189(x) + else + fun_l23_n252(x) + end +end + +def fun_l22_n246(x) + if (x < 1) + fun_l23_n919(x) + else + fun_l23_n581(x) + end +end + +def fun_l22_n247(x) + if (x < 1) + fun_l23_n212(x) + else + fun_l23_n465(x) + end +end + +def fun_l22_n248(x) + if (x < 1) + fun_l23_n880(x) + else + fun_l23_n823(x) + end +end + +def fun_l22_n249(x) + if (x < 1) + fun_l23_n227(x) + else + fun_l23_n620(x) + end +end + +def fun_l22_n250(x) + if (x < 1) + fun_l23_n875(x) + else + fun_l23_n707(x) + end +end + +def fun_l22_n251(x) + if (x < 1) + fun_l23_n623(x) + else + fun_l23_n132(x) + end +end + +def fun_l22_n252(x) + if (x < 1) + fun_l23_n739(x) + else + fun_l23_n417(x) + end +end + +def fun_l22_n253(x) + if (x < 1) + fun_l23_n977(x) + else + fun_l23_n216(x) + end +end + +def fun_l22_n254(x) + if (x < 1) + fun_l23_n725(x) + else + fun_l23_n168(x) + end +end + +def fun_l22_n255(x) + if (x < 1) + fun_l23_n878(x) + else + fun_l23_n699(x) + end +end + +def fun_l22_n256(x) + if (x < 1) + fun_l23_n423(x) + else + fun_l23_n626(x) + end +end + +def fun_l22_n257(x) + if (x < 1) + fun_l23_n29(x) + else + fun_l23_n248(x) + end +end + +def fun_l22_n258(x) + if (x < 1) + fun_l23_n78(x) + else + fun_l23_n925(x) + end +end + +def fun_l22_n259(x) + if (x < 1) + fun_l23_n798(x) + else + fun_l23_n220(x) + end +end + +def fun_l22_n260(x) + if (x < 1) + fun_l23_n621(x) + else + fun_l23_n936(x) + end +end + +def fun_l22_n261(x) + if (x < 1) + fun_l23_n894(x) + else + fun_l23_n463(x) + end +end + +def fun_l22_n262(x) + if (x < 1) + fun_l23_n336(x) + else + fun_l23_n535(x) + end +end + +def fun_l22_n263(x) + if (x < 1) + fun_l23_n246(x) + else + fun_l23_n676(x) + end +end + +def fun_l22_n264(x) + if (x < 1) + fun_l23_n986(x) + else + fun_l23_n675(x) + end +end + +def fun_l22_n265(x) + if (x < 1) + fun_l23_n92(x) + else + fun_l23_n380(x) + end +end + +def fun_l22_n266(x) + if (x < 1) + fun_l23_n945(x) + else + fun_l23_n842(x) + end +end + +def fun_l22_n267(x) + if (x < 1) + fun_l23_n351(x) + else + fun_l23_n261(x) + end +end + +def fun_l22_n268(x) + if (x < 1) + fun_l23_n784(x) + else + fun_l23_n306(x) + end +end + +def fun_l22_n269(x) + if (x < 1) + fun_l23_n940(x) + else + fun_l23_n129(x) + end +end + +def fun_l22_n270(x) + if (x < 1) + fun_l23_n491(x) + else + fun_l23_n806(x) + end +end + +def fun_l22_n271(x) + if (x < 1) + fun_l23_n68(x) + else + fun_l23_n91(x) + end +end + +def fun_l22_n272(x) + if (x < 1) + fun_l23_n965(x) + else + fun_l23_n665(x) + end +end + +def fun_l22_n273(x) + if (x < 1) + fun_l23_n461(x) + else + fun_l23_n619(x) + end +end + +def fun_l22_n274(x) + if (x < 1) + fun_l23_n635(x) + else + fun_l23_n755(x) + end +end + +def fun_l22_n275(x) + if (x < 1) + fun_l23_n192(x) + else + fun_l23_n729(x) + end +end + +def fun_l22_n276(x) + if (x < 1) + fun_l23_n94(x) + else + fun_l23_n832(x) + end +end + +def fun_l22_n277(x) + if (x < 1) + fun_l23_n619(x) + else + fun_l23_n444(x) + end +end + +def fun_l22_n278(x) + if (x < 1) + fun_l23_n682(x) + else + fun_l23_n579(x) + end +end + +def fun_l22_n279(x) + if (x < 1) + fun_l23_n889(x) + else + fun_l23_n425(x) + end +end + +def fun_l22_n280(x) + if (x < 1) + fun_l23_n101(x) + else + fun_l23_n215(x) + end +end + +def fun_l22_n281(x) + if (x < 1) + fun_l23_n747(x) + else + fun_l23_n436(x) + end +end + +def fun_l22_n282(x) + if (x < 1) + fun_l23_n519(x) + else + fun_l23_n438(x) + end +end + +def fun_l22_n283(x) + if (x < 1) + fun_l23_n312(x) + else + fun_l23_n804(x) + end +end + +def fun_l22_n284(x) + if (x < 1) + fun_l23_n150(x) + else + fun_l23_n71(x) + end +end + +def fun_l22_n285(x) + if (x < 1) + fun_l23_n698(x) + else + fun_l23_n254(x) + end +end + +def fun_l22_n286(x) + if (x < 1) + fun_l23_n97(x) + else + fun_l23_n782(x) + end +end + +def fun_l22_n287(x) + if (x < 1) + fun_l23_n315(x) + else + fun_l23_n164(x) + end +end + +def fun_l22_n288(x) + if (x < 1) + fun_l23_n704(x) + else + fun_l23_n927(x) + end +end + +def fun_l22_n289(x) + if (x < 1) + fun_l23_n447(x) + else + fun_l23_n104(x) + end +end + +def fun_l22_n290(x) + if (x < 1) + fun_l23_n533(x) + else + fun_l23_n687(x) + end +end + +def fun_l22_n291(x) + if (x < 1) + fun_l23_n897(x) + else + fun_l23_n692(x) + end +end + +def fun_l22_n292(x) + if (x < 1) + fun_l23_n515(x) + else + fun_l23_n258(x) + end +end + +def fun_l22_n293(x) + if (x < 1) + fun_l23_n25(x) + else + fun_l23_n608(x) + end +end + +def fun_l22_n294(x) + if (x < 1) + fun_l23_n313(x) + else + fun_l23_n675(x) + end +end + +def fun_l22_n295(x) + if (x < 1) + fun_l23_n154(x) + else + fun_l23_n779(x) + end +end + +def fun_l22_n296(x) + if (x < 1) + fun_l23_n731(x) + else + fun_l23_n310(x) + end +end + +def fun_l22_n297(x) + if (x < 1) + fun_l23_n443(x) + else + fun_l23_n709(x) + end +end + +def fun_l22_n298(x) + if (x < 1) + fun_l23_n100(x) + else + fun_l23_n900(x) + end +end + +def fun_l22_n299(x) + if (x < 1) + fun_l23_n64(x) + else + fun_l23_n80(x) + end +end + +def fun_l22_n300(x) + if (x < 1) + fun_l23_n361(x) + else + fun_l23_n535(x) + end +end + +def fun_l22_n301(x) + if (x < 1) + fun_l23_n628(x) + else + fun_l23_n272(x) + end +end + +def fun_l22_n302(x) + if (x < 1) + fun_l23_n930(x) + else + fun_l23_n795(x) + end +end + +def fun_l22_n303(x) + if (x < 1) + fun_l23_n642(x) + else + fun_l23_n766(x) + end +end + +def fun_l22_n304(x) + if (x < 1) + fun_l23_n191(x) + else + fun_l23_n439(x) + end +end + +def fun_l22_n305(x) + if (x < 1) + fun_l23_n387(x) + else + fun_l23_n999(x) + end +end + +def fun_l22_n306(x) + if (x < 1) + fun_l23_n470(x) + else + fun_l23_n572(x) + end +end + +def fun_l22_n307(x) + if (x < 1) + fun_l23_n942(x) + else + fun_l23_n254(x) + end +end + +def fun_l22_n308(x) + if (x < 1) + fun_l23_n664(x) + else + fun_l23_n73(x) + end +end + +def fun_l22_n309(x) + if (x < 1) + fun_l23_n63(x) + else + fun_l23_n321(x) + end +end + +def fun_l22_n310(x) + if (x < 1) + fun_l23_n348(x) + else + fun_l23_n961(x) + end +end + +def fun_l22_n311(x) + if (x < 1) + fun_l23_n555(x) + else + fun_l23_n315(x) + end +end + +def fun_l22_n312(x) + if (x < 1) + fun_l23_n978(x) + else + fun_l23_n498(x) + end +end + +def fun_l22_n313(x) + if (x < 1) + fun_l23_n880(x) + else + fun_l23_n696(x) + end +end + +def fun_l22_n314(x) + if (x < 1) + fun_l23_n325(x) + else + fun_l23_n43(x) + end +end + +def fun_l22_n315(x) + if (x < 1) + fun_l23_n848(x) + else + fun_l23_n314(x) + end +end + +def fun_l22_n316(x) + if (x < 1) + fun_l23_n660(x) + else + fun_l23_n378(x) + end +end + +def fun_l22_n317(x) + if (x < 1) + fun_l23_n975(x) + else + fun_l23_n503(x) + end +end + +def fun_l22_n318(x) + if (x < 1) + fun_l23_n41(x) + else + fun_l23_n746(x) + end +end + +def fun_l22_n319(x) + if (x < 1) + fun_l23_n325(x) + else + fun_l23_n565(x) + end +end + +def fun_l22_n320(x) + if (x < 1) + fun_l23_n19(x) + else + fun_l23_n922(x) + end +end + +def fun_l22_n321(x) + if (x < 1) + fun_l23_n235(x) + else + fun_l23_n284(x) + end +end + +def fun_l22_n322(x) + if (x < 1) + fun_l23_n591(x) + else + fun_l23_n821(x) + end +end + +def fun_l22_n323(x) + if (x < 1) + fun_l23_n23(x) + else + fun_l23_n151(x) + end +end + +def fun_l22_n324(x) + if (x < 1) + fun_l23_n361(x) + else + fun_l23_n322(x) + end +end + +def fun_l22_n325(x) + if (x < 1) + fun_l23_n245(x) + else + fun_l23_n205(x) + end +end + +def fun_l22_n326(x) + if (x < 1) + fun_l23_n568(x) + else + fun_l23_n133(x) + end +end + +def fun_l22_n327(x) + if (x < 1) + fun_l23_n895(x) + else + fun_l23_n315(x) + end +end + +def fun_l22_n328(x) + if (x < 1) + fun_l23_n473(x) + else + fun_l23_n315(x) + end +end + +def fun_l22_n329(x) + if (x < 1) + fun_l23_n618(x) + else + fun_l23_n196(x) + end +end + +def fun_l22_n330(x) + if (x < 1) + fun_l23_n97(x) + else + fun_l23_n422(x) + end +end + +def fun_l22_n331(x) + if (x < 1) + fun_l23_n101(x) + else + fun_l23_n447(x) + end +end + +def fun_l22_n332(x) + if (x < 1) + fun_l23_n875(x) + else + fun_l23_n197(x) + end +end + +def fun_l22_n333(x) + if (x < 1) + fun_l23_n25(x) + else + fun_l23_n499(x) + end +end + +def fun_l22_n334(x) + if (x < 1) + fun_l23_n602(x) + else + fun_l23_n75(x) + end +end + +def fun_l22_n335(x) + if (x < 1) + fun_l23_n370(x) + else + fun_l23_n150(x) + end +end + +def fun_l22_n336(x) + if (x < 1) + fun_l23_n960(x) + else + fun_l23_n498(x) + end +end + +def fun_l22_n337(x) + if (x < 1) + fun_l23_n675(x) + else + fun_l23_n525(x) + end +end + +def fun_l22_n338(x) + if (x < 1) + fun_l23_n445(x) + else + fun_l23_n581(x) + end +end + +def fun_l22_n339(x) + if (x < 1) + fun_l23_n718(x) + else + fun_l23_n995(x) + end +end + +def fun_l22_n340(x) + if (x < 1) + fun_l23_n790(x) + else + fun_l23_n370(x) + end +end + +def fun_l22_n341(x) + if (x < 1) + fun_l23_n234(x) + else + fun_l23_n187(x) + end +end + +def fun_l22_n342(x) + if (x < 1) + fun_l23_n777(x) + else + fun_l23_n411(x) + end +end + +def fun_l22_n343(x) + if (x < 1) + fun_l23_n258(x) + else + fun_l23_n129(x) + end +end + +def fun_l22_n344(x) + if (x < 1) + fun_l23_n715(x) + else + fun_l23_n381(x) + end +end + +def fun_l22_n345(x) + if (x < 1) + fun_l23_n495(x) + else + fun_l23_n892(x) + end +end + +def fun_l22_n346(x) + if (x < 1) + fun_l23_n433(x) + else + fun_l23_n987(x) + end +end + +def fun_l22_n347(x) + if (x < 1) + fun_l23_n569(x) + else + fun_l23_n832(x) + end +end + +def fun_l22_n348(x) + if (x < 1) + fun_l23_n425(x) + else + fun_l23_n894(x) + end +end + +def fun_l22_n349(x) + if (x < 1) + fun_l23_n186(x) + else + fun_l23_n211(x) + end +end + +def fun_l22_n350(x) + if (x < 1) + fun_l23_n435(x) + else + fun_l23_n393(x) + end +end + +def fun_l22_n351(x) + if (x < 1) + fun_l23_n942(x) + else + fun_l23_n364(x) + end +end + +def fun_l22_n352(x) + if (x < 1) + fun_l23_n29(x) + else + fun_l23_n574(x) + end +end + +def fun_l22_n353(x) + if (x < 1) + fun_l23_n548(x) + else + fun_l23_n663(x) + end +end + +def fun_l22_n354(x) + if (x < 1) + fun_l23_n238(x) + else + fun_l23_n693(x) + end +end + +def fun_l22_n355(x) + if (x < 1) + fun_l23_n459(x) + else + fun_l23_n197(x) + end +end + +def fun_l22_n356(x) + if (x < 1) + fun_l23_n478(x) + else + fun_l23_n905(x) + end +end + +def fun_l22_n357(x) + if (x < 1) + fun_l23_n732(x) + else + fun_l23_n124(x) + end +end + +def fun_l22_n358(x) + if (x < 1) + fun_l23_n716(x) + else + fun_l23_n758(x) + end +end + +def fun_l22_n359(x) + if (x < 1) + fun_l23_n376(x) + else + fun_l23_n883(x) + end +end + +def fun_l22_n360(x) + if (x < 1) + fun_l23_n100(x) + else + fun_l23_n485(x) + end +end + +def fun_l22_n361(x) + if (x < 1) + fun_l23_n62(x) + else + fun_l23_n794(x) + end +end + +def fun_l22_n362(x) + if (x < 1) + fun_l23_n951(x) + else + fun_l23_n23(x) + end +end + +def fun_l22_n363(x) + if (x < 1) + fun_l23_n298(x) + else + fun_l23_n775(x) + end +end + +def fun_l22_n364(x) + if (x < 1) + fun_l23_n53(x) + else + fun_l23_n595(x) + end +end + +def fun_l22_n365(x) + if (x < 1) + fun_l23_n695(x) + else + fun_l23_n401(x) + end +end + +def fun_l22_n366(x) + if (x < 1) + fun_l23_n475(x) + else + fun_l23_n762(x) + end +end + +def fun_l22_n367(x) + if (x < 1) + fun_l23_n706(x) + else + fun_l23_n527(x) + end +end + +def fun_l22_n368(x) + if (x < 1) + fun_l23_n919(x) + else + fun_l23_n301(x) + end +end + +def fun_l22_n369(x) + if (x < 1) + fun_l23_n755(x) + else + fun_l23_n256(x) + end +end + +def fun_l22_n370(x) + if (x < 1) + fun_l23_n592(x) + else + fun_l23_n608(x) + end +end + +def fun_l22_n371(x) + if (x < 1) + fun_l23_n192(x) + else + fun_l23_n10(x) + end +end + +def fun_l22_n372(x) + if (x < 1) + fun_l23_n332(x) + else + fun_l23_n448(x) + end +end + +def fun_l22_n373(x) + if (x < 1) + fun_l23_n135(x) + else + fun_l23_n793(x) + end +end + +def fun_l22_n374(x) + if (x < 1) + fun_l23_n141(x) + else + fun_l23_n669(x) + end +end + +def fun_l22_n375(x) + if (x < 1) + fun_l23_n474(x) + else + fun_l23_n356(x) + end +end + +def fun_l22_n376(x) + if (x < 1) + fun_l23_n69(x) + else + fun_l23_n384(x) + end +end + +def fun_l22_n377(x) + if (x < 1) + fun_l23_n386(x) + else + fun_l23_n552(x) + end +end + +def fun_l22_n378(x) + if (x < 1) + fun_l23_n878(x) + else + fun_l23_n131(x) + end +end + +def fun_l22_n379(x) + if (x < 1) + fun_l23_n929(x) + else + fun_l23_n479(x) + end +end + +def fun_l22_n380(x) + if (x < 1) + fun_l23_n782(x) + else + fun_l23_n745(x) + end +end + +def fun_l22_n381(x) + if (x < 1) + fun_l23_n126(x) + else + fun_l23_n732(x) + end +end + +def fun_l22_n382(x) + if (x < 1) + fun_l23_n694(x) + else + fun_l23_n291(x) + end +end + +def fun_l22_n383(x) + if (x < 1) + fun_l23_n165(x) + else + fun_l23_n49(x) + end +end + +def fun_l22_n384(x) + if (x < 1) + fun_l23_n453(x) + else + fun_l23_n144(x) + end +end + +def fun_l22_n385(x) + if (x < 1) + fun_l23_n182(x) + else + fun_l23_n974(x) + end +end + +def fun_l22_n386(x) + if (x < 1) + fun_l23_n861(x) + else + fun_l23_n185(x) + end +end + +def fun_l22_n387(x) + if (x < 1) + fun_l23_n962(x) + else + fun_l23_n578(x) + end +end + +def fun_l22_n388(x) + if (x < 1) + fun_l23_n88(x) + else + fun_l23_n508(x) + end +end + +def fun_l22_n389(x) + if (x < 1) + fun_l23_n421(x) + else + fun_l23_n886(x) + end +end + +def fun_l22_n390(x) + if (x < 1) + fun_l23_n992(x) + else + fun_l23_n540(x) + end +end + +def fun_l22_n391(x) + if (x < 1) + fun_l23_n996(x) + else + fun_l23_n533(x) + end +end + +def fun_l22_n392(x) + if (x < 1) + fun_l23_n97(x) + else + fun_l23_n803(x) + end +end + +def fun_l22_n393(x) + if (x < 1) + fun_l23_n505(x) + else + fun_l23_n263(x) + end +end + +def fun_l22_n394(x) + if (x < 1) + fun_l23_n52(x) + else + fun_l23_n566(x) + end +end + +def fun_l22_n395(x) + if (x < 1) + fun_l23_n290(x) + else + fun_l23_n558(x) + end +end + +def fun_l22_n396(x) + if (x < 1) + fun_l23_n51(x) + else + fun_l23_n365(x) + end +end + +def fun_l22_n397(x) + if (x < 1) + fun_l23_n505(x) + else + fun_l23_n461(x) + end +end + +def fun_l22_n398(x) + if (x < 1) + fun_l23_n415(x) + else + fun_l23_n460(x) + end +end + +def fun_l22_n399(x) + if (x < 1) + fun_l23_n370(x) + else + fun_l23_n377(x) + end +end + +def fun_l22_n400(x) + if (x < 1) + fun_l23_n644(x) + else + fun_l23_n300(x) + end +end + +def fun_l22_n401(x) + if (x < 1) + fun_l23_n22(x) + else + fun_l23_n348(x) + end +end + +def fun_l22_n402(x) + if (x < 1) + fun_l23_n286(x) + else + fun_l23_n991(x) + end +end + +def fun_l22_n403(x) + if (x < 1) + fun_l23_n928(x) + else + fun_l23_n627(x) + end +end + +def fun_l22_n404(x) + if (x < 1) + fun_l23_n884(x) + else + fun_l23_n326(x) + end +end + +def fun_l22_n405(x) + if (x < 1) + fun_l23_n586(x) + else + fun_l23_n913(x) + end +end + +def fun_l22_n406(x) + if (x < 1) + fun_l23_n732(x) + else + fun_l23_n964(x) + end +end + +def fun_l22_n407(x) + if (x < 1) + fun_l23_n301(x) + else + fun_l23_n946(x) + end +end + +def fun_l22_n408(x) + if (x < 1) + fun_l23_n540(x) + else + fun_l23_n29(x) + end +end + +def fun_l22_n409(x) + if (x < 1) + fun_l23_n793(x) + else + fun_l23_n420(x) + end +end + +def fun_l22_n410(x) + if (x < 1) + fun_l23_n766(x) + else + fun_l23_n473(x) + end +end + +def fun_l22_n411(x) + if (x < 1) + fun_l23_n683(x) + else + fun_l23_n12(x) + end +end + +def fun_l22_n412(x) + if (x < 1) + fun_l23_n273(x) + else + fun_l23_n45(x) + end +end + +def fun_l22_n413(x) + if (x < 1) + fun_l23_n732(x) + else + fun_l23_n313(x) + end +end + +def fun_l22_n414(x) + if (x < 1) + fun_l23_n291(x) + else + fun_l23_n216(x) + end +end + +def fun_l22_n415(x) + if (x < 1) + fun_l23_n6(x) + else + fun_l23_n482(x) + end +end + +def fun_l22_n416(x) + if (x < 1) + fun_l23_n214(x) + else + fun_l23_n341(x) + end +end + +def fun_l22_n417(x) + if (x < 1) + fun_l23_n690(x) + else + fun_l23_n773(x) + end +end + +def fun_l22_n418(x) + if (x < 1) + fun_l23_n437(x) + else + fun_l23_n941(x) + end +end + +def fun_l22_n419(x) + if (x < 1) + fun_l23_n131(x) + else + fun_l23_n14(x) + end +end + +def fun_l22_n420(x) + if (x < 1) + fun_l23_n924(x) + else + fun_l23_n359(x) + end +end + +def fun_l22_n421(x) + if (x < 1) + fun_l23_n653(x) + else + fun_l23_n875(x) + end +end + +def fun_l22_n422(x) + if (x < 1) + fun_l23_n411(x) + else + fun_l23_n981(x) + end +end + +def fun_l22_n423(x) + if (x < 1) + fun_l23_n258(x) + else + fun_l23_n876(x) + end +end + +def fun_l22_n424(x) + if (x < 1) + fun_l23_n430(x) + else + fun_l23_n62(x) + end +end + +def fun_l22_n425(x) + if (x < 1) + fun_l23_n444(x) + else + fun_l23_n48(x) + end +end + +def fun_l22_n426(x) + if (x < 1) + fun_l23_n905(x) + else + fun_l23_n458(x) + end +end + +def fun_l22_n427(x) + if (x < 1) + fun_l23_n440(x) + else + fun_l23_n411(x) + end +end + +def fun_l22_n428(x) + if (x < 1) + fun_l23_n655(x) + else + fun_l23_n622(x) + end +end + +def fun_l22_n429(x) + if (x < 1) + fun_l23_n587(x) + else + fun_l23_n638(x) + end +end + +def fun_l22_n430(x) + if (x < 1) + fun_l23_n156(x) + else + fun_l23_n900(x) + end +end + +def fun_l22_n431(x) + if (x < 1) + fun_l23_n136(x) + else + fun_l23_n562(x) + end +end + +def fun_l22_n432(x) + if (x < 1) + fun_l23_n897(x) + else + fun_l23_n16(x) + end +end + +def fun_l22_n433(x) + if (x < 1) + fun_l23_n28(x) + else + fun_l23_n504(x) + end +end + +def fun_l22_n434(x) + if (x < 1) + fun_l23_n987(x) + else + fun_l23_n640(x) + end +end + +def fun_l22_n435(x) + if (x < 1) + fun_l23_n395(x) + else + fun_l23_n922(x) + end +end + +def fun_l22_n436(x) + if (x < 1) + fun_l23_n679(x) + else + fun_l23_n576(x) + end +end + +def fun_l22_n437(x) + if (x < 1) + fun_l23_n915(x) + else + fun_l23_n240(x) + end +end + +def fun_l22_n438(x) + if (x < 1) + fun_l23_n889(x) + else + fun_l23_n38(x) + end +end + +def fun_l22_n439(x) + if (x < 1) + fun_l23_n522(x) + else + fun_l23_n481(x) + end +end + +def fun_l22_n440(x) + if (x < 1) + fun_l23_n458(x) + else + fun_l23_n81(x) + end +end + +def fun_l22_n441(x) + if (x < 1) + fun_l23_n220(x) + else + fun_l23_n393(x) + end +end + +def fun_l22_n442(x) + if (x < 1) + fun_l23_n404(x) + else + fun_l23_n945(x) + end +end + +def fun_l22_n443(x) + if (x < 1) + fun_l23_n347(x) + else + fun_l23_n377(x) + end +end + +def fun_l22_n444(x) + if (x < 1) + fun_l23_n484(x) + else + fun_l23_n277(x) + end +end + +def fun_l22_n445(x) + if (x < 1) + fun_l23_n118(x) + else + fun_l23_n578(x) + end +end + +def fun_l22_n446(x) + if (x < 1) + fun_l23_n674(x) + else + fun_l23_n238(x) + end +end + +def fun_l22_n447(x) + if (x < 1) + fun_l23_n290(x) + else + fun_l23_n275(x) + end +end + +def fun_l22_n448(x) + if (x < 1) + fun_l23_n358(x) + else + fun_l23_n939(x) + end +end + +def fun_l22_n449(x) + if (x < 1) + fun_l23_n38(x) + else + fun_l23_n122(x) + end +end + +def fun_l22_n450(x) + if (x < 1) + fun_l23_n575(x) + else + fun_l23_n582(x) + end +end + +def fun_l22_n451(x) + if (x < 1) + fun_l23_n657(x) + else + fun_l23_n986(x) + end +end + +def fun_l22_n452(x) + if (x < 1) + fun_l23_n771(x) + else + fun_l23_n603(x) + end +end + +def fun_l22_n453(x) + if (x < 1) + fun_l23_n981(x) + else + fun_l23_n762(x) + end +end + +def fun_l22_n454(x) + if (x < 1) + fun_l23_n93(x) + else + fun_l23_n26(x) + end +end + +def fun_l22_n455(x) + if (x < 1) + fun_l23_n675(x) + else + fun_l23_n332(x) + end +end + +def fun_l22_n456(x) + if (x < 1) + fun_l23_n923(x) + else + fun_l23_n416(x) + end +end + +def fun_l22_n457(x) + if (x < 1) + fun_l23_n179(x) + else + fun_l23_n485(x) + end +end + +def fun_l22_n458(x) + if (x < 1) + fun_l23_n38(x) + else + fun_l23_n319(x) + end +end + +def fun_l22_n459(x) + if (x < 1) + fun_l23_n22(x) + else + fun_l23_n747(x) + end +end + +def fun_l22_n460(x) + if (x < 1) + fun_l23_n643(x) + else + fun_l23_n132(x) + end +end + +def fun_l22_n461(x) + if (x < 1) + fun_l23_n165(x) + else + fun_l23_n673(x) + end +end + +def fun_l22_n462(x) + if (x < 1) + fun_l23_n988(x) + else + fun_l23_n916(x) + end +end + +def fun_l22_n463(x) + if (x < 1) + fun_l23_n331(x) + else + fun_l23_n853(x) + end +end + +def fun_l22_n464(x) + if (x < 1) + fun_l23_n699(x) + else + fun_l23_n771(x) + end +end + +def fun_l22_n465(x) + if (x < 1) + fun_l23_n358(x) + else + fun_l23_n966(x) + end +end + +def fun_l22_n466(x) + if (x < 1) + fun_l23_n723(x) + else + fun_l23_n897(x) + end +end + +def fun_l22_n467(x) + if (x < 1) + fun_l23_n69(x) + else + fun_l23_n186(x) + end +end + +def fun_l22_n468(x) + if (x < 1) + fun_l23_n661(x) + else + fun_l23_n420(x) + end +end + +def fun_l22_n469(x) + if (x < 1) + fun_l23_n175(x) + else + fun_l23_n270(x) + end +end + +def fun_l22_n470(x) + if (x < 1) + fun_l23_n556(x) + else + fun_l23_n344(x) + end +end + +def fun_l22_n471(x) + if (x < 1) + fun_l23_n413(x) + else + fun_l23_n338(x) + end +end + +def fun_l22_n472(x) + if (x < 1) + fun_l23_n456(x) + else + fun_l23_n125(x) + end +end + +def fun_l22_n473(x) + if (x < 1) + fun_l23_n364(x) + else + fun_l23_n347(x) + end +end + +def fun_l22_n474(x) + if (x < 1) + fun_l23_n436(x) + else + fun_l23_n897(x) + end +end + +def fun_l22_n475(x) + if (x < 1) + fun_l23_n613(x) + else + fun_l23_n851(x) + end +end + +def fun_l22_n476(x) + if (x < 1) + fun_l23_n754(x) + else + fun_l23_n755(x) + end +end + +def fun_l22_n477(x) + if (x < 1) + fun_l23_n899(x) + else + fun_l23_n496(x) + end +end + +def fun_l22_n478(x) + if (x < 1) + fun_l23_n183(x) + else + fun_l23_n864(x) + end +end + +def fun_l22_n479(x) + if (x < 1) + fun_l23_n11(x) + else + fun_l23_n679(x) + end +end + +def fun_l22_n480(x) + if (x < 1) + fun_l23_n160(x) + else + fun_l23_n747(x) + end +end + +def fun_l22_n481(x) + if (x < 1) + fun_l23_n138(x) + else + fun_l23_n762(x) + end +end + +def fun_l22_n482(x) + if (x < 1) + fun_l23_n467(x) + else + fun_l23_n148(x) + end +end + +def fun_l22_n483(x) + if (x < 1) + fun_l23_n97(x) + else + fun_l23_n826(x) + end +end + +def fun_l22_n484(x) + if (x < 1) + fun_l23_n754(x) + else + fun_l23_n661(x) + end +end + +def fun_l22_n485(x) + if (x < 1) + fun_l23_n415(x) + else + fun_l23_n531(x) + end +end + +def fun_l22_n486(x) + if (x < 1) + fun_l23_n543(x) + else + fun_l23_n271(x) + end +end + +def fun_l22_n487(x) + if (x < 1) + fun_l23_n240(x) + else + fun_l23_n221(x) + end +end + +def fun_l22_n488(x) + if (x < 1) + fun_l23_n208(x) + else + fun_l23_n633(x) + end +end + +def fun_l22_n489(x) + if (x < 1) + fun_l23_n539(x) + else + fun_l23_n925(x) + end +end + +def fun_l22_n490(x) + if (x < 1) + fun_l23_n141(x) + else + fun_l23_n142(x) + end +end + +def fun_l22_n491(x) + if (x < 1) + fun_l23_n899(x) + else + fun_l23_n407(x) + end +end + +def fun_l22_n492(x) + if (x < 1) + fun_l23_n237(x) + else + fun_l23_n836(x) + end +end + +def fun_l22_n493(x) + if (x < 1) + fun_l23_n23(x) + else + fun_l23_n266(x) + end +end + +def fun_l22_n494(x) + if (x < 1) + fun_l23_n819(x) + else + fun_l23_n473(x) + end +end + +def fun_l22_n495(x) + if (x < 1) + fun_l23_n182(x) + else + fun_l23_n253(x) + end +end + +def fun_l22_n496(x) + if (x < 1) + fun_l23_n459(x) + else + fun_l23_n421(x) + end +end + +def fun_l22_n497(x) + if (x < 1) + fun_l23_n553(x) + else + fun_l23_n207(x) + end +end + +def fun_l22_n498(x) + if (x < 1) + fun_l23_n5(x) + else + fun_l23_n261(x) + end +end + +def fun_l22_n499(x) + if (x < 1) + fun_l23_n53(x) + else + fun_l23_n478(x) + end +end + +def fun_l22_n500(x) + if (x < 1) + fun_l23_n489(x) + else + fun_l23_n77(x) + end +end + +def fun_l22_n501(x) + if (x < 1) + fun_l23_n551(x) + else + fun_l23_n854(x) + end +end + +def fun_l22_n502(x) + if (x < 1) + fun_l23_n32(x) + else + fun_l23_n241(x) + end +end + +def fun_l22_n503(x) + if (x < 1) + fun_l23_n536(x) + else + fun_l23_n820(x) + end +end + +def fun_l22_n504(x) + if (x < 1) + fun_l23_n521(x) + else + fun_l23_n551(x) + end +end + +def fun_l22_n505(x) + if (x < 1) + fun_l23_n812(x) + else + fun_l23_n885(x) + end +end + +def fun_l22_n506(x) + if (x < 1) + fun_l23_n935(x) + else + fun_l23_n38(x) + end +end + +def fun_l22_n507(x) + if (x < 1) + fun_l23_n99(x) + else + fun_l23_n907(x) + end +end + +def fun_l22_n508(x) + if (x < 1) + fun_l23_n89(x) + else + fun_l23_n322(x) + end +end + +def fun_l22_n509(x) + if (x < 1) + fun_l23_n279(x) + else + fun_l23_n103(x) + end +end + +def fun_l22_n510(x) + if (x < 1) + fun_l23_n476(x) + else + fun_l23_n947(x) + end +end + +def fun_l22_n511(x) + if (x < 1) + fun_l23_n872(x) + else + fun_l23_n497(x) + end +end + +def fun_l22_n512(x) + if (x < 1) + fun_l23_n508(x) + else + fun_l23_n548(x) + end +end + +def fun_l22_n513(x) + if (x < 1) + fun_l23_n640(x) + else + fun_l23_n696(x) + end +end + +def fun_l22_n514(x) + if (x < 1) + fun_l23_n694(x) + else + fun_l23_n483(x) + end +end + +def fun_l22_n515(x) + if (x < 1) + fun_l23_n914(x) + else + fun_l23_n772(x) + end +end + +def fun_l22_n516(x) + if (x < 1) + fun_l23_n192(x) + else + fun_l23_n35(x) + end +end + +def fun_l22_n517(x) + if (x < 1) + fun_l23_n597(x) + else + fun_l23_n473(x) + end +end + +def fun_l22_n518(x) + if (x < 1) + fun_l23_n974(x) + else + fun_l23_n315(x) + end +end + +def fun_l22_n519(x) + if (x < 1) + fun_l23_n391(x) + else + fun_l23_n800(x) + end +end + +def fun_l22_n520(x) + if (x < 1) + fun_l23_n106(x) + else + fun_l23_n170(x) + end +end + +def fun_l22_n521(x) + if (x < 1) + fun_l23_n926(x) + else + fun_l23_n495(x) + end +end + +def fun_l22_n522(x) + if (x < 1) + fun_l23_n135(x) + else + fun_l23_n304(x) + end +end + +def fun_l22_n523(x) + if (x < 1) + fun_l23_n765(x) + else + fun_l23_n53(x) + end +end + +def fun_l22_n524(x) + if (x < 1) + fun_l23_n699(x) + else + fun_l23_n158(x) + end +end + +def fun_l22_n525(x) + if (x < 1) + fun_l23_n759(x) + else + fun_l23_n34(x) + end +end + +def fun_l22_n526(x) + if (x < 1) + fun_l23_n813(x) + else + fun_l23_n938(x) + end +end + +def fun_l22_n527(x) + if (x < 1) + fun_l23_n207(x) + else + fun_l23_n549(x) + end +end + +def fun_l22_n528(x) + if (x < 1) + fun_l23_n468(x) + else + fun_l23_n681(x) + end +end + +def fun_l22_n529(x) + if (x < 1) + fun_l23_n643(x) + else + fun_l23_n652(x) + end +end + +def fun_l22_n530(x) + if (x < 1) + fun_l23_n254(x) + else + fun_l23_n283(x) + end +end + +def fun_l22_n531(x) + if (x < 1) + fun_l23_n750(x) + else + fun_l23_n969(x) + end +end + +def fun_l22_n532(x) + if (x < 1) + fun_l23_n343(x) + else + fun_l23_n578(x) + end +end + +def fun_l22_n533(x) + if (x < 1) + fun_l23_n240(x) + else + fun_l23_n698(x) + end +end + +def fun_l22_n534(x) + if (x < 1) + fun_l23_n497(x) + else + fun_l23_n992(x) + end +end + +def fun_l22_n535(x) + if (x < 1) + fun_l23_n554(x) + else + fun_l23_n53(x) + end +end + +def fun_l22_n536(x) + if (x < 1) + fun_l23_n165(x) + else + fun_l23_n467(x) + end +end + +def fun_l22_n537(x) + if (x < 1) + fun_l23_n2(x) + else + fun_l23_n560(x) + end +end + +def fun_l22_n538(x) + if (x < 1) + fun_l23_n151(x) + else + fun_l23_n434(x) + end +end + +def fun_l22_n539(x) + if (x < 1) + fun_l23_n108(x) + else + fun_l23_n108(x) + end +end + +def fun_l22_n540(x) + if (x < 1) + fun_l23_n879(x) + else + fun_l23_n608(x) + end +end + +def fun_l22_n541(x) + if (x < 1) + fun_l23_n160(x) + else + fun_l23_n820(x) + end +end + +def fun_l22_n542(x) + if (x < 1) + fun_l23_n813(x) + else + fun_l23_n169(x) + end +end + +def fun_l22_n543(x) + if (x < 1) + fun_l23_n151(x) + else + fun_l23_n420(x) + end +end + +def fun_l22_n544(x) + if (x < 1) + fun_l23_n81(x) + else + fun_l23_n226(x) + end +end + +def fun_l22_n545(x) + if (x < 1) + fun_l23_n464(x) + else + fun_l23_n602(x) + end +end + +def fun_l22_n546(x) + if (x < 1) + fun_l23_n798(x) + else + fun_l23_n395(x) + end +end + +def fun_l22_n547(x) + if (x < 1) + fun_l23_n597(x) + else + fun_l23_n147(x) + end +end + +def fun_l22_n548(x) + if (x < 1) + fun_l23_n952(x) + else + fun_l23_n515(x) + end +end + +def fun_l22_n549(x) + if (x < 1) + fun_l23_n134(x) + else + fun_l23_n154(x) + end +end + +def fun_l22_n550(x) + if (x < 1) + fun_l23_n35(x) + else + fun_l23_n492(x) + end +end + +def fun_l22_n551(x) + if (x < 1) + fun_l23_n878(x) + else + fun_l23_n899(x) + end +end + +def fun_l22_n552(x) + if (x < 1) + fun_l23_n574(x) + else + fun_l23_n108(x) + end +end + +def fun_l22_n553(x) + if (x < 1) + fun_l23_n386(x) + else + fun_l23_n565(x) + end +end + +def fun_l22_n554(x) + if (x < 1) + fun_l23_n551(x) + else + fun_l23_n905(x) + end +end + +def fun_l22_n555(x) + if (x < 1) + fun_l23_n680(x) + else + fun_l23_n367(x) + end +end + +def fun_l22_n556(x) + if (x < 1) + fun_l23_n452(x) + else + fun_l23_n211(x) + end +end + +def fun_l22_n557(x) + if (x < 1) + fun_l23_n597(x) + else + fun_l23_n112(x) + end +end + +def fun_l22_n558(x) + if (x < 1) + fun_l23_n22(x) + else + fun_l23_n966(x) + end +end + +def fun_l22_n559(x) + if (x < 1) + fun_l23_n512(x) + else + fun_l23_n337(x) + end +end + +def fun_l22_n560(x) + if (x < 1) + fun_l23_n649(x) + else + fun_l23_n361(x) + end +end + +def fun_l22_n561(x) + if (x < 1) + fun_l23_n500(x) + else + fun_l23_n113(x) + end +end + +def fun_l22_n562(x) + if (x < 1) + fun_l23_n455(x) + else + fun_l23_n734(x) + end +end + +def fun_l22_n563(x) + if (x < 1) + fun_l23_n847(x) + else + fun_l23_n86(x) + end +end + +def fun_l22_n564(x) + if (x < 1) + fun_l23_n251(x) + else + fun_l23_n203(x) + end +end + +def fun_l22_n565(x) + if (x < 1) + fun_l23_n977(x) + else + fun_l23_n893(x) + end +end + +def fun_l22_n566(x) + if (x < 1) + fun_l23_n693(x) + else + fun_l23_n507(x) + end +end + +def fun_l22_n567(x) + if (x < 1) + fun_l23_n194(x) + else + fun_l23_n972(x) + end +end + +def fun_l22_n568(x) + if (x < 1) + fun_l23_n44(x) + else + fun_l23_n694(x) + end +end + +def fun_l22_n569(x) + if (x < 1) + fun_l23_n277(x) + else + fun_l23_n317(x) + end +end + +def fun_l22_n570(x) + if (x < 1) + fun_l23_n40(x) + else + fun_l23_n10(x) + end +end + +def fun_l22_n571(x) + if (x < 1) + fun_l23_n199(x) + else + fun_l23_n454(x) + end +end + +def fun_l22_n572(x) + if (x < 1) + fun_l23_n821(x) + else + fun_l23_n556(x) + end +end + +def fun_l22_n573(x) + if (x < 1) + fun_l23_n142(x) + else + fun_l23_n307(x) + end +end + +def fun_l22_n574(x) + if (x < 1) + fun_l23_n291(x) + else + fun_l23_n152(x) + end +end + +def fun_l22_n575(x) + if (x < 1) + fun_l23_n547(x) + else + fun_l23_n580(x) + end +end + +def fun_l22_n576(x) + if (x < 1) + fun_l23_n841(x) + else + fun_l23_n518(x) + end +end + +def fun_l22_n577(x) + if (x < 1) + fun_l23_n91(x) + else + fun_l23_n730(x) + end +end + +def fun_l22_n578(x) + if (x < 1) + fun_l23_n626(x) + else + fun_l23_n403(x) + end +end + +def fun_l22_n579(x) + if (x < 1) + fun_l23_n12(x) + else + fun_l23_n863(x) + end +end + +def fun_l22_n580(x) + if (x < 1) + fun_l23_n878(x) + else + fun_l23_n28(x) + end +end + +def fun_l22_n581(x) + if (x < 1) + fun_l23_n793(x) + else + fun_l23_n942(x) + end +end + +def fun_l22_n582(x) + if (x < 1) + fun_l23_n168(x) + else + fun_l23_n102(x) + end +end + +def fun_l22_n583(x) + if (x < 1) + fun_l23_n40(x) + else + fun_l23_n231(x) + end +end + +def fun_l22_n584(x) + if (x < 1) + fun_l23_n54(x) + else + fun_l23_n734(x) + end +end + +def fun_l22_n585(x) + if (x < 1) + fun_l23_n878(x) + else + fun_l23_n938(x) + end +end + +def fun_l22_n586(x) + if (x < 1) + fun_l23_n89(x) + else + fun_l23_n533(x) + end +end + +def fun_l22_n587(x) + if (x < 1) + fun_l23_n289(x) + else + fun_l23_n587(x) + end +end + +def fun_l22_n588(x) + if (x < 1) + fun_l23_n716(x) + else + fun_l23_n785(x) + end +end + +def fun_l22_n589(x) + if (x < 1) + fun_l23_n22(x) + else + fun_l23_n820(x) + end +end + +def fun_l22_n590(x) + if (x < 1) + fun_l23_n945(x) + else + fun_l23_n644(x) + end +end + +def fun_l22_n591(x) + if (x < 1) + fun_l23_n209(x) + else + fun_l23_n86(x) + end +end + +def fun_l22_n592(x) + if (x < 1) + fun_l23_n209(x) + else + fun_l23_n971(x) + end +end + +def fun_l22_n593(x) + if (x < 1) + fun_l23_n489(x) + else + fun_l23_n725(x) + end +end + +def fun_l22_n594(x) + if (x < 1) + fun_l23_n42(x) + else + fun_l23_n405(x) + end +end + +def fun_l22_n595(x) + if (x < 1) + fun_l23_n162(x) + else + fun_l23_n222(x) + end +end + +def fun_l22_n596(x) + if (x < 1) + fun_l23_n942(x) + else + fun_l23_n193(x) + end +end + +def fun_l22_n597(x) + if (x < 1) + fun_l23_n616(x) + else + fun_l23_n806(x) + end +end + +def fun_l22_n598(x) + if (x < 1) + fun_l23_n278(x) + else + fun_l23_n330(x) + end +end + +def fun_l22_n599(x) + if (x < 1) + fun_l23_n863(x) + else + fun_l23_n428(x) + end +end + +def fun_l22_n600(x) + if (x < 1) + fun_l23_n315(x) + else + fun_l23_n319(x) + end +end + +def fun_l22_n601(x) + if (x < 1) + fun_l23_n409(x) + else + fun_l23_n682(x) + end +end + +def fun_l22_n602(x) + if (x < 1) + fun_l23_n307(x) + else + fun_l23_n47(x) + end +end + +def fun_l22_n603(x) + if (x < 1) + fun_l23_n578(x) + else + fun_l23_n762(x) + end +end + +def fun_l22_n604(x) + if (x < 1) + fun_l23_n208(x) + else + fun_l23_n314(x) + end +end + +def fun_l22_n605(x) + if (x < 1) + fun_l23_n259(x) + else + fun_l23_n720(x) + end +end + +def fun_l22_n606(x) + if (x < 1) + fun_l23_n272(x) + else + fun_l23_n619(x) + end +end + +def fun_l22_n607(x) + if (x < 1) + fun_l23_n550(x) + else + fun_l23_n850(x) + end +end + +def fun_l22_n608(x) + if (x < 1) + fun_l23_n617(x) + else + fun_l23_n999(x) + end +end + +def fun_l22_n609(x) + if (x < 1) + fun_l23_n203(x) + else + fun_l23_n597(x) + end +end + +def fun_l22_n610(x) + if (x < 1) + fun_l23_n547(x) + else + fun_l23_n252(x) + end +end + +def fun_l22_n611(x) + if (x < 1) + fun_l23_n427(x) + else + fun_l23_n16(x) + end +end + +def fun_l22_n612(x) + if (x < 1) + fun_l23_n236(x) + else + fun_l23_n142(x) + end +end + +def fun_l22_n613(x) + if (x < 1) + fun_l23_n94(x) + else + fun_l23_n739(x) + end +end + +def fun_l22_n614(x) + if (x < 1) + fun_l23_n504(x) + else + fun_l23_n101(x) + end +end + +def fun_l22_n615(x) + if (x < 1) + fun_l23_n469(x) + else + fun_l23_n650(x) + end +end + +def fun_l22_n616(x) + if (x < 1) + fun_l23_n752(x) + else + fun_l23_n262(x) + end +end + +def fun_l22_n617(x) + if (x < 1) + fun_l23_n256(x) + else + fun_l23_n269(x) + end +end + +def fun_l22_n618(x) + if (x < 1) + fun_l23_n784(x) + else + fun_l23_n402(x) + end +end + +def fun_l22_n619(x) + if (x < 1) + fun_l23_n405(x) + else + fun_l23_n585(x) + end +end + +def fun_l22_n620(x) + if (x < 1) + fun_l23_n33(x) + else + fun_l23_n357(x) + end +end + +def fun_l22_n621(x) + if (x < 1) + fun_l23_n448(x) + else + fun_l23_n618(x) + end +end + +def fun_l22_n622(x) + if (x < 1) + fun_l23_n520(x) + else + fun_l23_n612(x) + end +end + +def fun_l22_n623(x) + if (x < 1) + fun_l23_n54(x) + else + fun_l23_n872(x) + end +end + +def fun_l22_n624(x) + if (x < 1) + fun_l23_n915(x) + else + fun_l23_n1(x) + end +end + +def fun_l22_n625(x) + if (x < 1) + fun_l23_n274(x) + else + fun_l23_n509(x) + end +end + +def fun_l22_n626(x) + if (x < 1) + fun_l23_n506(x) + else + fun_l23_n938(x) + end +end + +def fun_l22_n627(x) + if (x < 1) + fun_l23_n463(x) + else + fun_l23_n436(x) + end +end + +def fun_l22_n628(x) + if (x < 1) + fun_l23_n33(x) + else + fun_l23_n279(x) + end +end + +def fun_l22_n629(x) + if (x < 1) + fun_l23_n825(x) + else + fun_l23_n11(x) + end +end + +def fun_l22_n630(x) + if (x < 1) + fun_l23_n778(x) + else + fun_l23_n77(x) + end +end + +def fun_l22_n631(x) + if (x < 1) + fun_l23_n826(x) + else + fun_l23_n601(x) + end +end + +def fun_l22_n632(x) + if (x < 1) + fun_l23_n973(x) + else + fun_l23_n444(x) + end +end + +def fun_l22_n633(x) + if (x < 1) + fun_l23_n59(x) + else + fun_l23_n578(x) + end +end + +def fun_l22_n634(x) + if (x < 1) + fun_l23_n366(x) + else + fun_l23_n128(x) + end +end + +def fun_l22_n635(x) + if (x < 1) + fun_l23_n733(x) + else + fun_l23_n486(x) + end +end + +def fun_l22_n636(x) + if (x < 1) + fun_l23_n22(x) + else + fun_l23_n997(x) + end +end + +def fun_l22_n637(x) + if (x < 1) + fun_l23_n286(x) + else + fun_l23_n609(x) + end +end + +def fun_l22_n638(x) + if (x < 1) + fun_l23_n519(x) + else + fun_l23_n381(x) + end +end + +def fun_l22_n639(x) + if (x < 1) + fun_l23_n697(x) + else + fun_l23_n954(x) + end +end + +def fun_l22_n640(x) + if (x < 1) + fun_l23_n348(x) + else + fun_l23_n261(x) + end +end + +def fun_l22_n641(x) + if (x < 1) + fun_l23_n426(x) + else + fun_l23_n166(x) + end +end + +def fun_l22_n642(x) + if (x < 1) + fun_l23_n488(x) + else + fun_l23_n79(x) + end +end + +def fun_l22_n643(x) + if (x < 1) + fun_l23_n186(x) + else + fun_l23_n723(x) + end +end + +def fun_l22_n644(x) + if (x < 1) + fun_l23_n582(x) + else + fun_l23_n365(x) + end +end + +def fun_l22_n645(x) + if (x < 1) + fun_l23_n36(x) + else + fun_l23_n726(x) + end +end + +def fun_l22_n646(x) + if (x < 1) + fun_l23_n585(x) + else + fun_l23_n770(x) + end +end + +def fun_l22_n647(x) + if (x < 1) + fun_l23_n68(x) + else + fun_l23_n261(x) + end +end + +def fun_l22_n648(x) + if (x < 1) + fun_l23_n208(x) + else + fun_l23_n302(x) + end +end + +def fun_l22_n649(x) + if (x < 1) + fun_l23_n539(x) + else + fun_l23_n731(x) + end +end + +def fun_l22_n650(x) + if (x < 1) + fun_l23_n709(x) + else + fun_l23_n144(x) + end +end + +def fun_l22_n651(x) + if (x < 1) + fun_l23_n802(x) + else + fun_l23_n886(x) + end +end + +def fun_l22_n652(x) + if (x < 1) + fun_l23_n796(x) + else + fun_l23_n574(x) + end +end + +def fun_l22_n653(x) + if (x < 1) + fun_l23_n755(x) + else + fun_l23_n960(x) + end +end + +def fun_l22_n654(x) + if (x < 1) + fun_l23_n415(x) + else + fun_l23_n543(x) + end +end + +def fun_l22_n655(x) + if (x < 1) + fun_l23_n932(x) + else + fun_l23_n412(x) + end +end + +def fun_l22_n656(x) + if (x < 1) + fun_l23_n216(x) + else + fun_l23_n869(x) + end +end + +def fun_l22_n657(x) + if (x < 1) + fun_l23_n750(x) + else + fun_l23_n66(x) + end +end + +def fun_l22_n658(x) + if (x < 1) + fun_l23_n400(x) + else + fun_l23_n31(x) + end +end + +def fun_l22_n659(x) + if (x < 1) + fun_l23_n815(x) + else + fun_l23_n866(x) + end +end + +def fun_l22_n660(x) + if (x < 1) + fun_l23_n459(x) + else + fun_l23_n833(x) + end +end + +def fun_l22_n661(x) + if (x < 1) + fun_l23_n167(x) + else + fun_l23_n861(x) + end +end + +def fun_l22_n662(x) + if (x < 1) + fun_l23_n789(x) + else + fun_l23_n543(x) + end +end + +def fun_l22_n663(x) + if (x < 1) + fun_l23_n850(x) + else + fun_l23_n899(x) + end +end + +def fun_l22_n664(x) + if (x < 1) + fun_l23_n986(x) + else + fun_l23_n924(x) + end +end + +def fun_l22_n665(x) + if (x < 1) + fun_l23_n667(x) + else + fun_l23_n510(x) + end +end + +def fun_l22_n666(x) + if (x < 1) + fun_l23_n744(x) + else + fun_l23_n530(x) + end +end + +def fun_l22_n667(x) + if (x < 1) + fun_l23_n930(x) + else + fun_l23_n693(x) + end +end + +def fun_l22_n668(x) + if (x < 1) + fun_l23_n942(x) + else + fun_l23_n785(x) + end +end + +def fun_l22_n669(x) + if (x < 1) + fun_l23_n520(x) + else + fun_l23_n342(x) + end +end + +def fun_l22_n670(x) + if (x < 1) + fun_l23_n865(x) + else + fun_l23_n63(x) + end +end + +def fun_l22_n671(x) + if (x < 1) + fun_l23_n173(x) + else + fun_l23_n142(x) + end +end + +def fun_l22_n672(x) + if (x < 1) + fun_l23_n487(x) + else + fun_l23_n400(x) + end +end + +def fun_l22_n673(x) + if (x < 1) + fun_l23_n330(x) + else + fun_l23_n639(x) + end +end + +def fun_l22_n674(x) + if (x < 1) + fun_l23_n593(x) + else + fun_l23_n653(x) + end +end + +def fun_l22_n675(x) + if (x < 1) + fun_l23_n167(x) + else + fun_l23_n173(x) + end +end + +def fun_l22_n676(x) + if (x < 1) + fun_l23_n288(x) + else + fun_l23_n412(x) + end +end + +def fun_l22_n677(x) + if (x < 1) + fun_l23_n266(x) + else + fun_l23_n728(x) + end +end + +def fun_l22_n678(x) + if (x < 1) + fun_l23_n137(x) + else + fun_l23_n277(x) + end +end + +def fun_l22_n679(x) + if (x < 1) + fun_l23_n732(x) + else + fun_l23_n760(x) + end +end + +def fun_l22_n680(x) + if (x < 1) + fun_l23_n372(x) + else + fun_l23_n26(x) + end +end + +def fun_l22_n681(x) + if (x < 1) + fun_l23_n156(x) + else + fun_l23_n449(x) + end +end + +def fun_l22_n682(x) + if (x < 1) + fun_l23_n117(x) + else + fun_l23_n711(x) + end +end + +def fun_l22_n683(x) + if (x < 1) + fun_l23_n732(x) + else + fun_l23_n922(x) + end +end + +def fun_l22_n684(x) + if (x < 1) + fun_l23_n116(x) + else + fun_l23_n347(x) + end +end + +def fun_l22_n685(x) + if (x < 1) + fun_l23_n277(x) + else + fun_l23_n837(x) + end +end + +def fun_l22_n686(x) + if (x < 1) + fun_l23_n578(x) + else + fun_l23_n290(x) + end +end + +def fun_l22_n687(x) + if (x < 1) + fun_l23_n858(x) + else + fun_l23_n390(x) + end +end + +def fun_l22_n688(x) + if (x < 1) + fun_l23_n52(x) + else + fun_l23_n759(x) + end +end + +def fun_l22_n689(x) + if (x < 1) + fun_l23_n873(x) + else + fun_l23_n25(x) + end +end + +def fun_l22_n690(x) + if (x < 1) + fun_l23_n262(x) + else + fun_l23_n511(x) + end +end + +def fun_l22_n691(x) + if (x < 1) + fun_l23_n654(x) + else + fun_l23_n359(x) + end +end + +def fun_l22_n692(x) + if (x < 1) + fun_l23_n933(x) + else + fun_l23_n369(x) + end +end + +def fun_l22_n693(x) + if (x < 1) + fun_l23_n845(x) + else + fun_l23_n999(x) + end +end + +def fun_l22_n694(x) + if (x < 1) + fun_l23_n479(x) + else + fun_l23_n284(x) + end +end + +def fun_l22_n695(x) + if (x < 1) + fun_l23_n383(x) + else + fun_l23_n91(x) + end +end + +def fun_l22_n696(x) + if (x < 1) + fun_l23_n467(x) + else + fun_l23_n555(x) + end +end + +def fun_l22_n697(x) + if (x < 1) + fun_l23_n590(x) + else + fun_l23_n372(x) + end +end + +def fun_l22_n698(x) + if (x < 1) + fun_l23_n706(x) + else + fun_l23_n195(x) + end +end + +def fun_l22_n699(x) + if (x < 1) + fun_l23_n621(x) + else + fun_l23_n265(x) + end +end + +def fun_l22_n700(x) + if (x < 1) + fun_l23_n505(x) + else + fun_l23_n831(x) + end +end + +def fun_l22_n701(x) + if (x < 1) + fun_l23_n361(x) + else + fun_l23_n74(x) + end +end + +def fun_l22_n702(x) + if (x < 1) + fun_l23_n734(x) + else + fun_l23_n922(x) + end +end + +def fun_l22_n703(x) + if (x < 1) + fun_l23_n457(x) + else + fun_l23_n219(x) + end +end + +def fun_l22_n704(x) + if (x < 1) + fun_l23_n436(x) + else + fun_l23_n733(x) + end +end + +def fun_l22_n705(x) + if (x < 1) + fun_l23_n150(x) + else + fun_l23_n463(x) + end +end + +def fun_l22_n706(x) + if (x < 1) + fun_l23_n486(x) + else + fun_l23_n906(x) + end +end + +def fun_l22_n707(x) + if (x < 1) + fun_l23_n826(x) + else + fun_l23_n829(x) + end +end + +def fun_l22_n708(x) + if (x < 1) + fun_l23_n186(x) + else + fun_l23_n555(x) + end +end + +def fun_l22_n709(x) + if (x < 1) + fun_l23_n186(x) + else + fun_l23_n739(x) + end +end + +def fun_l22_n710(x) + if (x < 1) + fun_l23_n58(x) + else + fun_l23_n395(x) + end +end + +def fun_l22_n711(x) + if (x < 1) + fun_l23_n916(x) + else + fun_l23_n546(x) + end +end + +def fun_l22_n712(x) + if (x < 1) + fun_l23_n309(x) + else + fun_l23_n582(x) + end +end + +def fun_l22_n713(x) + if (x < 1) + fun_l23_n460(x) + else + fun_l23_n1(x) + end +end + +def fun_l22_n714(x) + if (x < 1) + fun_l23_n270(x) + else + fun_l23_n888(x) + end +end + +def fun_l22_n715(x) + if (x < 1) + fun_l23_n564(x) + else + fun_l23_n652(x) + end +end + +def fun_l22_n716(x) + if (x < 1) + fun_l23_n14(x) + else + fun_l23_n862(x) + end +end + +def fun_l22_n717(x) + if (x < 1) + fun_l23_n15(x) + else + fun_l23_n366(x) + end +end + +def fun_l22_n718(x) + if (x < 1) + fun_l23_n580(x) + else + fun_l23_n367(x) + end +end + +def fun_l22_n719(x) + if (x < 1) + fun_l23_n256(x) + else + fun_l23_n385(x) + end +end + +def fun_l22_n720(x) + if (x < 1) + fun_l23_n735(x) + else + fun_l23_n811(x) + end +end + +def fun_l22_n721(x) + if (x < 1) + fun_l23_n348(x) + else + fun_l23_n681(x) + end +end + +def fun_l22_n722(x) + if (x < 1) + fun_l23_n908(x) + else + fun_l23_n80(x) + end +end + +def fun_l22_n723(x) + if (x < 1) + fun_l23_n523(x) + else + fun_l23_n91(x) + end +end + +def fun_l22_n724(x) + if (x < 1) + fun_l23_n212(x) + else + fun_l23_n220(x) + end +end + +def fun_l22_n725(x) + if (x < 1) + fun_l23_n396(x) + else + fun_l23_n855(x) + end +end + +def fun_l22_n726(x) + if (x < 1) + fun_l23_n717(x) + else + fun_l23_n314(x) + end +end + +def fun_l22_n727(x) + if (x < 1) + fun_l23_n152(x) + else + fun_l23_n374(x) + end +end + +def fun_l22_n728(x) + if (x < 1) + fun_l23_n464(x) + else + fun_l23_n439(x) + end +end + +def fun_l22_n729(x) + if (x < 1) + fun_l23_n631(x) + else + fun_l23_n601(x) + end +end + +def fun_l22_n730(x) + if (x < 1) + fun_l23_n689(x) + else + fun_l23_n929(x) + end +end + +def fun_l22_n731(x) + if (x < 1) + fun_l23_n691(x) + else + fun_l23_n868(x) + end +end + +def fun_l22_n732(x) + if (x < 1) + fun_l23_n629(x) + else + fun_l23_n997(x) + end +end + +def fun_l22_n733(x) + if (x < 1) + fun_l23_n815(x) + else + fun_l23_n696(x) + end +end + +def fun_l22_n734(x) + if (x < 1) + fun_l23_n636(x) + else + fun_l23_n858(x) + end +end + +def fun_l22_n735(x) + if (x < 1) + fun_l23_n131(x) + else + fun_l23_n350(x) + end +end + +def fun_l22_n736(x) + if (x < 1) + fun_l23_n509(x) + else + fun_l23_n197(x) + end +end + +def fun_l22_n737(x) + if (x < 1) + fun_l23_n549(x) + else + fun_l23_n16(x) + end +end + +def fun_l22_n738(x) + if (x < 1) + fun_l23_n797(x) + else + fun_l23_n829(x) + end +end + +def fun_l22_n739(x) + if (x < 1) + fun_l23_n78(x) + else + fun_l23_n299(x) + end +end + +def fun_l22_n740(x) + if (x < 1) + fun_l23_n165(x) + else + fun_l23_n822(x) + end +end + +def fun_l22_n741(x) + if (x < 1) + fun_l23_n494(x) + else + fun_l23_n226(x) + end +end + +def fun_l22_n742(x) + if (x < 1) + fun_l23_n930(x) + else + fun_l23_n301(x) + end +end + +def fun_l22_n743(x) + if (x < 1) + fun_l23_n357(x) + else + fun_l23_n399(x) + end +end + +def fun_l22_n744(x) + if (x < 1) + fun_l23_n865(x) + else + fun_l23_n499(x) + end +end + +def fun_l22_n745(x) + if (x < 1) + fun_l23_n437(x) + else + fun_l23_n145(x) + end +end + +def fun_l22_n746(x) + if (x < 1) + fun_l23_n883(x) + else + fun_l23_n269(x) + end +end + +def fun_l22_n747(x) + if (x < 1) + fun_l23_n323(x) + else + fun_l23_n199(x) + end +end + +def fun_l22_n748(x) + if (x < 1) + fun_l23_n843(x) + else + fun_l23_n179(x) + end +end + +def fun_l22_n749(x) + if (x < 1) + fun_l23_n413(x) + else + fun_l23_n195(x) + end +end + +def fun_l22_n750(x) + if (x < 1) + fun_l23_n50(x) + else + fun_l23_n219(x) + end +end + +def fun_l22_n751(x) + if (x < 1) + fun_l23_n574(x) + else + fun_l23_n649(x) + end +end + +def fun_l22_n752(x) + if (x < 1) + fun_l23_n495(x) + else + fun_l23_n664(x) + end +end + +def fun_l22_n753(x) + if (x < 1) + fun_l23_n899(x) + else + fun_l23_n14(x) + end +end + +def fun_l22_n754(x) + if (x < 1) + fun_l23_n230(x) + else + fun_l23_n933(x) + end +end + +def fun_l22_n755(x) + if (x < 1) + fun_l23_n236(x) + else + fun_l23_n854(x) + end +end + +def fun_l22_n756(x) + if (x < 1) + fun_l23_n786(x) + else + fun_l23_n599(x) + end +end + +def fun_l22_n757(x) + if (x < 1) + fun_l23_n921(x) + else + fun_l23_n805(x) + end +end + +def fun_l22_n758(x) + if (x < 1) + fun_l23_n990(x) + else + fun_l23_n724(x) + end +end + +def fun_l22_n759(x) + if (x < 1) + fun_l23_n376(x) + else + fun_l23_n568(x) + end +end + +def fun_l22_n760(x) + if (x < 1) + fun_l23_n676(x) + else + fun_l23_n995(x) + end +end + +def fun_l22_n761(x) + if (x < 1) + fun_l23_n144(x) + else + fun_l23_n104(x) + end +end + +def fun_l22_n762(x) + if (x < 1) + fun_l23_n463(x) + else + fun_l23_n736(x) + end +end + +def fun_l22_n763(x) + if (x < 1) + fun_l23_n436(x) + else + fun_l23_n475(x) + end +end + +def fun_l22_n764(x) + if (x < 1) + fun_l23_n607(x) + else + fun_l23_n737(x) + end +end + +def fun_l22_n765(x) + if (x < 1) + fun_l23_n108(x) + else + fun_l23_n396(x) + end +end + +def fun_l22_n766(x) + if (x < 1) + fun_l23_n35(x) + else + fun_l23_n422(x) + end +end + +def fun_l22_n767(x) + if (x < 1) + fun_l23_n541(x) + else + fun_l23_n756(x) + end +end + +def fun_l22_n768(x) + if (x < 1) + fun_l23_n558(x) + else + fun_l23_n858(x) + end +end + +def fun_l22_n769(x) + if (x < 1) + fun_l23_n153(x) + else + fun_l23_n544(x) + end +end + +def fun_l22_n770(x) + if (x < 1) + fun_l23_n201(x) + else + fun_l23_n905(x) + end +end + +def fun_l22_n771(x) + if (x < 1) + fun_l23_n373(x) + else + fun_l23_n420(x) + end +end + +def fun_l22_n772(x) + if (x < 1) + fun_l23_n635(x) + else + fun_l23_n464(x) + end +end + +def fun_l22_n773(x) + if (x < 1) + fun_l23_n822(x) + else + fun_l23_n803(x) + end +end + +def fun_l22_n774(x) + if (x < 1) + fun_l23_n118(x) + else + fun_l23_n127(x) + end +end + +def fun_l22_n775(x) + if (x < 1) + fun_l23_n364(x) + else + fun_l23_n512(x) + end +end + +def fun_l22_n776(x) + if (x < 1) + fun_l23_n186(x) + else + fun_l23_n275(x) + end +end + +def fun_l22_n777(x) + if (x < 1) + fun_l23_n803(x) + else + fun_l23_n105(x) + end +end + +def fun_l22_n778(x) + if (x < 1) + fun_l23_n535(x) + else + fun_l23_n569(x) + end +end + +def fun_l22_n779(x) + if (x < 1) + fun_l23_n847(x) + else + fun_l23_n505(x) + end +end + +def fun_l22_n780(x) + if (x < 1) + fun_l23_n323(x) + else + fun_l23_n552(x) + end +end + +def fun_l22_n781(x) + if (x < 1) + fun_l23_n294(x) + else + fun_l23_n914(x) + end +end + +def fun_l22_n782(x) + if (x < 1) + fun_l23_n887(x) + else + fun_l23_n214(x) + end +end + +def fun_l22_n783(x) + if (x < 1) + fun_l23_n900(x) + else + fun_l23_n729(x) + end +end + +def fun_l22_n784(x) + if (x < 1) + fun_l23_n458(x) + else + fun_l23_n233(x) + end +end + +def fun_l22_n785(x) + if (x < 1) + fun_l23_n553(x) + else + fun_l23_n306(x) + end +end + +def fun_l22_n786(x) + if (x < 1) + fun_l23_n853(x) + else + fun_l23_n946(x) + end +end + +def fun_l22_n787(x) + if (x < 1) + fun_l23_n595(x) + else + fun_l23_n288(x) + end +end + +def fun_l22_n788(x) + if (x < 1) + fun_l23_n785(x) + else + fun_l23_n752(x) + end +end + +def fun_l22_n789(x) + if (x < 1) + fun_l23_n787(x) + else + fun_l23_n788(x) + end +end + +def fun_l22_n790(x) + if (x < 1) + fun_l23_n461(x) + else + fun_l23_n251(x) + end +end + +def fun_l22_n791(x) + if (x < 1) + fun_l23_n523(x) + else + fun_l23_n328(x) + end +end + +def fun_l22_n792(x) + if (x < 1) + fun_l23_n200(x) + else + fun_l23_n689(x) + end +end + +def fun_l22_n793(x) + if (x < 1) + fun_l23_n612(x) + else + fun_l23_n398(x) + end +end + +def fun_l22_n794(x) + if (x < 1) + fun_l23_n937(x) + else + fun_l23_n965(x) + end +end + +def fun_l22_n795(x) + if (x < 1) + fun_l23_n362(x) + else + fun_l23_n789(x) + end +end + +def fun_l22_n796(x) + if (x < 1) + fun_l23_n145(x) + else + fun_l23_n36(x) + end +end + +def fun_l22_n797(x) + if (x < 1) + fun_l23_n923(x) + else + fun_l23_n251(x) + end +end + +def fun_l22_n798(x) + if (x < 1) + fun_l23_n15(x) + else + fun_l23_n563(x) + end +end + +def fun_l22_n799(x) + if (x < 1) + fun_l23_n554(x) + else + fun_l23_n336(x) + end +end + +def fun_l22_n800(x) + if (x < 1) + fun_l23_n939(x) + else + fun_l23_n993(x) + end +end + +def fun_l22_n801(x) + if (x < 1) + fun_l23_n506(x) + else + fun_l23_n656(x) + end +end + +def fun_l22_n802(x) + if (x < 1) + fun_l23_n591(x) + else + fun_l23_n582(x) + end +end + +def fun_l22_n803(x) + if (x < 1) + fun_l23_n707(x) + else + fun_l23_n235(x) + end +end + +def fun_l22_n804(x) + if (x < 1) + fun_l23_n474(x) + else + fun_l23_n253(x) + end +end + +def fun_l22_n805(x) + if (x < 1) + fun_l23_n707(x) + else + fun_l23_n885(x) + end +end + +def fun_l22_n806(x) + if (x < 1) + fun_l23_n155(x) + else + fun_l23_n210(x) + end +end + +def fun_l22_n807(x) + if (x < 1) + fun_l23_n489(x) + else + fun_l23_n249(x) + end +end + +def fun_l22_n808(x) + if (x < 1) + fun_l23_n840(x) + else + fun_l23_n748(x) + end +end + +def fun_l22_n809(x) + if (x < 1) + fun_l23_n910(x) + else + fun_l23_n884(x) + end +end + +def fun_l22_n810(x) + if (x < 1) + fun_l23_n653(x) + else + fun_l23_n321(x) + end +end + +def fun_l22_n811(x) + if (x < 1) + fun_l23_n310(x) + else + fun_l23_n366(x) + end +end + +def fun_l22_n812(x) + if (x < 1) + fun_l23_n441(x) + else + fun_l23_n795(x) + end +end + +def fun_l22_n813(x) + if (x < 1) + fun_l23_n666(x) + else + fun_l23_n631(x) + end +end + +def fun_l22_n814(x) + if (x < 1) + fun_l23_n680(x) + else + fun_l23_n88(x) + end +end + +def fun_l22_n815(x) + if (x < 1) + fun_l23_n80(x) + else + fun_l23_n989(x) + end +end + +def fun_l22_n816(x) + if (x < 1) + fun_l23_n65(x) + else + fun_l23_n46(x) + end +end + +def fun_l22_n817(x) + if (x < 1) + fun_l23_n427(x) + else + fun_l23_n868(x) + end +end + +def fun_l22_n818(x) + if (x < 1) + fun_l23_n900(x) + else + fun_l23_n213(x) + end +end + +def fun_l22_n819(x) + if (x < 1) + fun_l23_n394(x) + else + fun_l23_n647(x) + end +end + +def fun_l22_n820(x) + if (x < 1) + fun_l23_n981(x) + else + fun_l23_n530(x) + end +end + +def fun_l22_n821(x) + if (x < 1) + fun_l23_n806(x) + else + fun_l23_n511(x) + end +end + +def fun_l22_n822(x) + if (x < 1) + fun_l23_n141(x) + else + fun_l23_n91(x) + end +end + +def fun_l22_n823(x) + if (x < 1) + fun_l23_n604(x) + else + fun_l23_n270(x) + end +end + +def fun_l22_n824(x) + if (x < 1) + fun_l23_n347(x) + else + fun_l23_n937(x) + end +end + +def fun_l22_n825(x) + if (x < 1) + fun_l23_n302(x) + else + fun_l23_n659(x) + end +end + +def fun_l22_n826(x) + if (x < 1) + fun_l23_n386(x) + else + fun_l23_n174(x) + end +end + +def fun_l22_n827(x) + if (x < 1) + fun_l23_n347(x) + else + fun_l23_n659(x) + end +end + +def fun_l22_n828(x) + if (x < 1) + fun_l23_n647(x) + else + fun_l23_n648(x) + end +end + +def fun_l22_n829(x) + if (x < 1) + fun_l23_n892(x) + else + fun_l23_n910(x) + end +end + +def fun_l22_n830(x) + if (x < 1) + fun_l23_n274(x) + else + fun_l23_n739(x) + end +end + +def fun_l22_n831(x) + if (x < 1) + fun_l23_n211(x) + else + fun_l23_n658(x) + end +end + +def fun_l22_n832(x) + if (x < 1) + fun_l23_n584(x) + else + fun_l23_n163(x) + end +end + +def fun_l22_n833(x) + if (x < 1) + fun_l23_n598(x) + else + fun_l23_n735(x) + end +end + +def fun_l22_n834(x) + if (x < 1) + fun_l23_n934(x) + else + fun_l23_n579(x) + end +end + +def fun_l22_n835(x) + if (x < 1) + fun_l23_n483(x) + else + fun_l23_n632(x) + end +end + +def fun_l22_n836(x) + if (x < 1) + fun_l23_n329(x) + else + fun_l23_n799(x) + end +end + +def fun_l22_n837(x) + if (x < 1) + fun_l23_n699(x) + else + fun_l23_n846(x) + end +end + +def fun_l22_n838(x) + if (x < 1) + fun_l23_n40(x) + else + fun_l23_n715(x) + end +end + +def fun_l22_n839(x) + if (x < 1) + fun_l23_n917(x) + else + fun_l23_n595(x) + end +end + +def fun_l22_n840(x) + if (x < 1) + fun_l23_n171(x) + else + fun_l23_n204(x) + end +end + +def fun_l22_n841(x) + if (x < 1) + fun_l23_n652(x) + else + fun_l23_n342(x) + end +end + +def fun_l22_n842(x) + if (x < 1) + fun_l23_n853(x) + else + fun_l23_n981(x) + end +end + +def fun_l22_n843(x) + if (x < 1) + fun_l23_n673(x) + else + fun_l23_n2(x) + end +end + +def fun_l22_n844(x) + if (x < 1) + fun_l23_n799(x) + else + fun_l23_n654(x) + end +end + +def fun_l22_n845(x) + if (x < 1) + fun_l23_n989(x) + else + fun_l23_n563(x) + end +end + +def fun_l22_n846(x) + if (x < 1) + fun_l23_n415(x) + else + fun_l23_n245(x) + end +end + +def fun_l22_n847(x) + if (x < 1) + fun_l23_n836(x) + else + fun_l23_n347(x) + end +end + +def fun_l22_n848(x) + if (x < 1) + fun_l23_n493(x) + else + fun_l23_n712(x) + end +end + +def fun_l22_n849(x) + if (x < 1) + fun_l23_n780(x) + else + fun_l23_n43(x) + end +end + +def fun_l22_n850(x) + if (x < 1) + fun_l23_n511(x) + else + fun_l23_n356(x) + end +end + +def fun_l22_n851(x) + if (x < 1) + fun_l23_n229(x) + else + fun_l23_n355(x) + end +end + +def fun_l22_n852(x) + if (x < 1) + fun_l23_n50(x) + else + fun_l23_n908(x) + end +end + +def fun_l22_n853(x) + if (x < 1) + fun_l23_n156(x) + else + fun_l23_n422(x) + end +end + +def fun_l22_n854(x) + if (x < 1) + fun_l23_n448(x) + else + fun_l23_n763(x) + end +end + +def fun_l22_n855(x) + if (x < 1) + fun_l23_n662(x) + else + fun_l23_n887(x) + end +end + +def fun_l22_n856(x) + if (x < 1) + fun_l23_n511(x) + else + fun_l23_n292(x) + end +end + +def fun_l22_n857(x) + if (x < 1) + fun_l23_n313(x) + else + fun_l23_n207(x) + end +end + +def fun_l22_n858(x) + if (x < 1) + fun_l23_n544(x) + else + fun_l23_n488(x) + end +end + +def fun_l22_n859(x) + if (x < 1) + fun_l23_n34(x) + else + fun_l23_n133(x) + end +end + +def fun_l22_n860(x) + if (x < 1) + fun_l23_n739(x) + else + fun_l23_n127(x) + end +end + +def fun_l22_n861(x) + if (x < 1) + fun_l23_n727(x) + else + fun_l23_n339(x) + end +end + +def fun_l22_n862(x) + if (x < 1) + fun_l23_n78(x) + else + fun_l23_n101(x) + end +end + +def fun_l22_n863(x) + if (x < 1) + fun_l23_n310(x) + else + fun_l23_n884(x) + end +end + +def fun_l22_n864(x) + if (x < 1) + fun_l23_n97(x) + else + fun_l23_n716(x) + end +end + +def fun_l22_n865(x) + if (x < 1) + fun_l23_n63(x) + else + fun_l23_n654(x) + end +end + +def fun_l22_n866(x) + if (x < 1) + fun_l23_n336(x) + else + fun_l23_n334(x) + end +end + +def fun_l22_n867(x) + if (x < 1) + fun_l23_n317(x) + else + fun_l23_n197(x) + end +end + +def fun_l22_n868(x) + if (x < 1) + fun_l23_n98(x) + else + fun_l23_n466(x) + end +end + +def fun_l22_n869(x) + if (x < 1) + fun_l23_n157(x) + else + fun_l23_n43(x) + end +end + +def fun_l22_n870(x) + if (x < 1) + fun_l23_n347(x) + else + fun_l23_n961(x) + end +end + +def fun_l22_n871(x) + if (x < 1) + fun_l23_n460(x) + else + fun_l23_n820(x) + end +end + +def fun_l22_n872(x) + if (x < 1) + fun_l23_n216(x) + else + fun_l23_n419(x) + end +end + +def fun_l22_n873(x) + if (x < 1) + fun_l23_n879(x) + else + fun_l23_n343(x) + end +end + +def fun_l22_n874(x) + if (x < 1) + fun_l23_n507(x) + else + fun_l23_n572(x) + end +end + +def fun_l22_n875(x) + if (x < 1) + fun_l23_n959(x) + else + fun_l23_n750(x) + end +end + +def fun_l22_n876(x) + if (x < 1) + fun_l23_n718(x) + else + fun_l23_n406(x) + end +end + +def fun_l22_n877(x) + if (x < 1) + fun_l23_n733(x) + else + fun_l23_n486(x) + end +end + +def fun_l22_n878(x) + if (x < 1) + fun_l23_n95(x) + else + fun_l23_n842(x) + end +end + +def fun_l22_n879(x) + if (x < 1) + fun_l23_n626(x) + else + fun_l23_n428(x) + end +end + +def fun_l22_n880(x) + if (x < 1) + fun_l23_n194(x) + else + fun_l23_n441(x) + end +end + +def fun_l22_n881(x) + if (x < 1) + fun_l23_n10(x) + else + fun_l23_n727(x) + end +end + +def fun_l22_n882(x) + if (x < 1) + fun_l23_n173(x) + else + fun_l23_n301(x) + end +end + +def fun_l22_n883(x) + if (x < 1) + fun_l23_n338(x) + else + fun_l23_n420(x) + end +end + +def fun_l22_n884(x) + if (x < 1) + fun_l23_n615(x) + else + fun_l23_n923(x) + end +end + +def fun_l22_n885(x) + if (x < 1) + fun_l23_n547(x) + else + fun_l23_n979(x) + end +end + +def fun_l22_n886(x) + if (x < 1) + fun_l23_n28(x) + else + fun_l23_n213(x) + end +end + +def fun_l22_n887(x) + if (x < 1) + fun_l23_n919(x) + else + fun_l23_n228(x) + end +end + +def fun_l22_n888(x) + if (x < 1) + fun_l23_n264(x) + else + fun_l23_n156(x) + end +end + +def fun_l22_n889(x) + if (x < 1) + fun_l23_n137(x) + else + fun_l23_n582(x) + end +end + +def fun_l22_n890(x) + if (x < 1) + fun_l23_n468(x) + else + fun_l23_n409(x) + end +end + +def fun_l22_n891(x) + if (x < 1) + fun_l23_n823(x) + else + fun_l23_n999(x) + end +end + +def fun_l22_n892(x) + if (x < 1) + fun_l23_n248(x) + else + fun_l23_n821(x) + end +end + +def fun_l22_n893(x) + if (x < 1) + fun_l23_n117(x) + else + fun_l23_n127(x) + end +end + +def fun_l22_n894(x) + if (x < 1) + fun_l23_n622(x) + else + fun_l23_n737(x) + end +end + +def fun_l22_n895(x) + if (x < 1) + fun_l23_n66(x) + else + fun_l23_n261(x) + end +end + +def fun_l22_n896(x) + if (x < 1) + fun_l23_n245(x) + else + fun_l23_n18(x) + end +end + +def fun_l22_n897(x) + if (x < 1) + fun_l23_n269(x) + else + fun_l23_n666(x) + end +end + +def fun_l22_n898(x) + if (x < 1) + fun_l23_n807(x) + else + fun_l23_n449(x) + end +end + +def fun_l22_n899(x) + if (x < 1) + fun_l23_n801(x) + else + fun_l23_n34(x) + end +end + +def fun_l22_n900(x) + if (x < 1) + fun_l23_n17(x) + else + fun_l23_n117(x) + end +end + +def fun_l22_n901(x) + if (x < 1) + fun_l23_n677(x) + else + fun_l23_n872(x) + end +end + +def fun_l22_n902(x) + if (x < 1) + fun_l23_n221(x) + else + fun_l23_n685(x) + end +end + +def fun_l22_n903(x) + if (x < 1) + fun_l23_n224(x) + else + fun_l23_n15(x) + end +end + +def fun_l22_n904(x) + if (x < 1) + fun_l23_n353(x) + else + fun_l23_n367(x) + end +end + +def fun_l22_n905(x) + if (x < 1) + fun_l23_n466(x) + else + fun_l23_n466(x) + end +end + +def fun_l22_n906(x) + if (x < 1) + fun_l23_n674(x) + else + fun_l23_n521(x) + end +end + +def fun_l22_n907(x) + if (x < 1) + fun_l23_n978(x) + else + fun_l23_n79(x) + end +end + +def fun_l22_n908(x) + if (x < 1) + fun_l23_n976(x) + else + fun_l23_n513(x) + end +end + +def fun_l22_n909(x) + if (x < 1) + fun_l23_n478(x) + else + fun_l23_n524(x) + end +end + +def fun_l22_n910(x) + if (x < 1) + fun_l23_n744(x) + else + fun_l23_n451(x) + end +end + +def fun_l22_n911(x) + if (x < 1) + fun_l23_n524(x) + else + fun_l23_n409(x) + end +end + +def fun_l22_n912(x) + if (x < 1) + fun_l23_n651(x) + else + fun_l23_n424(x) + end +end + +def fun_l22_n913(x) + if (x < 1) + fun_l23_n740(x) + else + fun_l23_n841(x) + end +end + +def fun_l22_n914(x) + if (x < 1) + fun_l23_n388(x) + else + fun_l23_n790(x) + end +end + +def fun_l22_n915(x) + if (x < 1) + fun_l23_n625(x) + else + fun_l23_n276(x) + end +end + +def fun_l22_n916(x) + if (x < 1) + fun_l23_n322(x) + else + fun_l23_n598(x) + end +end + +def fun_l22_n917(x) + if (x < 1) + fun_l23_n51(x) + else + fun_l23_n286(x) + end +end + +def fun_l22_n918(x) + if (x < 1) + fun_l23_n265(x) + else + fun_l23_n553(x) + end +end + +def fun_l22_n919(x) + if (x < 1) + fun_l23_n525(x) + else + fun_l23_n825(x) + end +end + +def fun_l22_n920(x) + if (x < 1) + fun_l23_n59(x) + else + fun_l23_n643(x) + end +end + +def fun_l22_n921(x) + if (x < 1) + fun_l23_n135(x) + else + fun_l23_n811(x) + end +end + +def fun_l22_n922(x) + if (x < 1) + fun_l23_n587(x) + else + fun_l23_n564(x) + end +end + +def fun_l22_n923(x) + if (x < 1) + fun_l23_n235(x) + else + fun_l23_n337(x) + end +end + +def fun_l22_n924(x) + if (x < 1) + fun_l23_n99(x) + else + fun_l23_n805(x) + end +end + +def fun_l22_n925(x) + if (x < 1) + fun_l23_n360(x) + else + fun_l23_n67(x) + end +end + +def fun_l22_n926(x) + if (x < 1) + fun_l23_n438(x) + else + fun_l23_n948(x) + end +end + +def fun_l22_n927(x) + if (x < 1) + fun_l23_n545(x) + else + fun_l23_n287(x) + end +end + +def fun_l22_n928(x) + if (x < 1) + fun_l23_n632(x) + else + fun_l23_n769(x) + end +end + +def fun_l22_n929(x) + if (x < 1) + fun_l23_n17(x) + else + fun_l23_n240(x) + end +end + +def fun_l22_n930(x) + if (x < 1) + fun_l23_n948(x) + else + fun_l23_n690(x) + end +end + +def fun_l22_n931(x) + if (x < 1) + fun_l23_n12(x) + else + fun_l23_n640(x) + end +end + +def fun_l22_n932(x) + if (x < 1) + fun_l23_n157(x) + else + fun_l23_n594(x) + end +end + +def fun_l22_n933(x) + if (x < 1) + fun_l23_n96(x) + else + fun_l23_n771(x) + end +end + +def fun_l22_n934(x) + if (x < 1) + fun_l23_n237(x) + else + fun_l23_n910(x) + end +end + +def fun_l22_n935(x) + if (x < 1) + fun_l23_n553(x) + else + fun_l23_n300(x) + end +end + +def fun_l22_n936(x) + if (x < 1) + fun_l23_n224(x) + else + fun_l23_n566(x) + end +end + +def fun_l22_n937(x) + if (x < 1) + fun_l23_n314(x) + else + fun_l23_n328(x) + end +end + +def fun_l22_n938(x) + if (x < 1) + fun_l23_n775(x) + else + fun_l23_n72(x) + end +end + +def fun_l22_n939(x) + if (x < 1) + fun_l23_n273(x) + else + fun_l23_n43(x) + end +end + +def fun_l22_n940(x) + if (x < 1) + fun_l23_n215(x) + else + fun_l23_n646(x) + end +end + +def fun_l22_n941(x) + if (x < 1) + fun_l23_n925(x) + else + fun_l23_n97(x) + end +end + +def fun_l22_n942(x) + if (x < 1) + fun_l23_n391(x) + else + fun_l23_n972(x) + end +end + +def fun_l22_n943(x) + if (x < 1) + fun_l23_n276(x) + else + fun_l23_n725(x) + end +end + +def fun_l22_n944(x) + if (x < 1) + fun_l23_n928(x) + else + fun_l23_n94(x) + end +end + +def fun_l22_n945(x) + if (x < 1) + fun_l23_n176(x) + else + fun_l23_n598(x) + end +end + +def fun_l22_n946(x) + if (x < 1) + fun_l23_n530(x) + else + fun_l23_n37(x) + end +end + +def fun_l22_n947(x) + if (x < 1) + fun_l23_n412(x) + else + fun_l23_n718(x) + end +end + +def fun_l22_n948(x) + if (x < 1) + fun_l23_n905(x) + else + fun_l23_n723(x) + end +end + +def fun_l22_n949(x) + if (x < 1) + fun_l23_n451(x) + else + fun_l23_n232(x) + end +end + +def fun_l22_n950(x) + if (x < 1) + fun_l23_n312(x) + else + fun_l23_n556(x) + end +end + +def fun_l22_n951(x) + if (x < 1) + fun_l23_n906(x) + else + fun_l23_n33(x) + end +end + +def fun_l22_n952(x) + if (x < 1) + fun_l23_n964(x) + else + fun_l23_n46(x) + end +end + +def fun_l22_n953(x) + if (x < 1) + fun_l23_n813(x) + else + fun_l23_n494(x) + end +end + +def fun_l22_n954(x) + if (x < 1) + fun_l23_n725(x) + else + fun_l23_n705(x) + end +end + +def fun_l22_n955(x) + if (x < 1) + fun_l23_n525(x) + else + fun_l23_n370(x) + end +end + +def fun_l22_n956(x) + if (x < 1) + fun_l23_n266(x) + else + fun_l23_n872(x) + end +end + +def fun_l22_n957(x) + if (x < 1) + fun_l23_n492(x) + else + fun_l23_n730(x) + end +end + +def fun_l22_n958(x) + if (x < 1) + fun_l23_n950(x) + else + fun_l23_n557(x) + end +end + +def fun_l22_n959(x) + if (x < 1) + fun_l23_n156(x) + else + fun_l23_n379(x) + end +end + +def fun_l22_n960(x) + if (x < 1) + fun_l23_n270(x) + else + fun_l23_n486(x) + end +end + +def fun_l22_n961(x) + if (x < 1) + fun_l23_n789(x) + else + fun_l23_n316(x) + end +end + +def fun_l22_n962(x) + if (x < 1) + fun_l23_n425(x) + else + fun_l23_n470(x) + end +end + +def fun_l22_n963(x) + if (x < 1) + fun_l23_n598(x) + else + fun_l23_n304(x) + end +end + +def fun_l22_n964(x) + if (x < 1) + fun_l23_n249(x) + else + fun_l23_n517(x) + end +end + +def fun_l22_n965(x) + if (x < 1) + fun_l23_n775(x) + else + fun_l23_n892(x) + end +end + +def fun_l22_n966(x) + if (x < 1) + fun_l23_n771(x) + else + fun_l23_n879(x) + end +end + +def fun_l22_n967(x) + if (x < 1) + fun_l23_n596(x) + else + fun_l23_n22(x) + end +end + +def fun_l22_n968(x) + if (x < 1) + fun_l23_n722(x) + else + fun_l23_n203(x) + end +end + +def fun_l22_n969(x) + if (x < 1) + fun_l23_n912(x) + else + fun_l23_n216(x) + end +end + +def fun_l22_n970(x) + if (x < 1) + fun_l23_n230(x) + else + fun_l23_n295(x) + end +end + +def fun_l22_n971(x) + if (x < 1) + fun_l23_n255(x) + else + fun_l23_n407(x) + end +end + +def fun_l22_n972(x) + if (x < 1) + fun_l23_n673(x) + else + fun_l23_n940(x) + end +end + +def fun_l22_n973(x) + if (x < 1) + fun_l23_n793(x) + else + fun_l23_n776(x) + end +end + +def fun_l22_n974(x) + if (x < 1) + fun_l23_n812(x) + else + fun_l23_n653(x) + end +end + +def fun_l22_n975(x) + if (x < 1) + fun_l23_n866(x) + else + fun_l23_n25(x) + end +end + +def fun_l22_n976(x) + if (x < 1) + fun_l23_n143(x) + else + fun_l23_n236(x) + end +end + +def fun_l22_n977(x) + if (x < 1) + fun_l23_n274(x) + else + fun_l23_n414(x) + end +end + +def fun_l22_n978(x) + if (x < 1) + fun_l23_n281(x) + else + fun_l23_n946(x) + end +end + +def fun_l22_n979(x) + if (x < 1) + fun_l23_n255(x) + else + fun_l23_n585(x) + end +end + +def fun_l22_n980(x) + if (x < 1) + fun_l23_n269(x) + else + fun_l23_n182(x) + end +end + +def fun_l22_n981(x) + if (x < 1) + fun_l23_n340(x) + else + fun_l23_n262(x) + end +end + +def fun_l22_n982(x) + if (x < 1) + fun_l23_n713(x) + else + fun_l23_n247(x) + end +end + +def fun_l22_n983(x) + if (x < 1) + fun_l23_n827(x) + else + fun_l23_n821(x) + end +end + +def fun_l22_n984(x) + if (x < 1) + fun_l23_n628(x) + else + fun_l23_n243(x) + end +end + +def fun_l22_n985(x) + if (x < 1) + fun_l23_n479(x) + else + fun_l23_n440(x) + end +end + +def fun_l22_n986(x) + if (x < 1) + fun_l23_n451(x) + else + fun_l23_n299(x) + end +end + +def fun_l22_n987(x) + if (x < 1) + fun_l23_n528(x) + else + fun_l23_n336(x) + end +end + +def fun_l22_n988(x) + if (x < 1) + fun_l23_n825(x) + else + fun_l23_n767(x) + end +end + +def fun_l22_n989(x) + if (x < 1) + fun_l23_n427(x) + else + fun_l23_n996(x) + end +end + +def fun_l22_n990(x) + if (x < 1) + fun_l23_n175(x) + else + fun_l23_n888(x) + end +end + +def fun_l22_n991(x) + if (x < 1) + fun_l23_n351(x) + else + fun_l23_n982(x) + end +end + +def fun_l22_n992(x) + if (x < 1) + fun_l23_n235(x) + else + fun_l23_n91(x) + end +end + +def fun_l22_n993(x) + if (x < 1) + fun_l23_n966(x) + else + fun_l23_n520(x) + end +end + +def fun_l22_n994(x) + if (x < 1) + fun_l23_n854(x) + else + fun_l23_n937(x) + end +end + +def fun_l22_n995(x) + if (x < 1) + fun_l23_n922(x) + else + fun_l23_n176(x) + end +end + +def fun_l22_n996(x) + if (x < 1) + fun_l23_n925(x) + else + fun_l23_n271(x) + end +end + +def fun_l22_n997(x) + if (x < 1) + fun_l23_n513(x) + else + fun_l23_n195(x) + end +end + +def fun_l22_n998(x) + if (x < 1) + fun_l23_n135(x) + else + fun_l23_n834(x) + end +end + +def fun_l22_n999(x) + if (x < 1) + fun_l23_n664(x) + else + fun_l23_n861(x) + end +end + +def fun_l23_n0(x) + if (x < 1) + fun_l24_n327(x) + else + fun_l24_n159(x) + end +end + +def fun_l23_n1(x) + if (x < 1) + fun_l24_n433(x) + else + fun_l24_n862(x) + end +end + +def fun_l23_n2(x) + if (x < 1) + fun_l24_n56(x) + else + fun_l24_n651(x) + end +end + +def fun_l23_n3(x) + if (x < 1) + fun_l24_n267(x) + else + fun_l24_n566(x) + end +end + +def fun_l23_n4(x) + if (x < 1) + fun_l24_n880(x) + else + fun_l24_n886(x) + end +end + +def fun_l23_n5(x) + if (x < 1) + fun_l24_n66(x) + else + fun_l24_n894(x) + end +end + +def fun_l23_n6(x) + if (x < 1) + fun_l24_n965(x) + else + fun_l24_n453(x) + end +end + +def fun_l23_n7(x) + if (x < 1) + fun_l24_n250(x) + else + fun_l24_n42(x) + end +end + +def fun_l23_n8(x) + if (x < 1) + fun_l24_n376(x) + else + fun_l24_n736(x) + end +end + +def fun_l23_n9(x) + if (x < 1) + fun_l24_n434(x) + else + fun_l24_n334(x) + end +end + +def fun_l23_n10(x) + if (x < 1) + fun_l24_n944(x) + else + fun_l24_n70(x) + end +end + +def fun_l23_n11(x) + if (x < 1) + fun_l24_n38(x) + else + fun_l24_n532(x) + end +end + +def fun_l23_n12(x) + if (x < 1) + fun_l24_n603(x) + else + fun_l24_n682(x) + end +end + +def fun_l23_n13(x) + if (x < 1) + fun_l24_n716(x) + else + fun_l24_n754(x) + end +end + +def fun_l23_n14(x) + if (x < 1) + fun_l24_n578(x) + else + fun_l24_n727(x) + end +end + +def fun_l23_n15(x) + if (x < 1) + fun_l24_n166(x) + else + fun_l24_n224(x) + end +end + +def fun_l23_n16(x) + if (x < 1) + fun_l24_n755(x) + else + fun_l24_n548(x) + end +end + +def fun_l23_n17(x) + if (x < 1) + fun_l24_n355(x) + else + fun_l24_n625(x) + end +end + +def fun_l23_n18(x) + if (x < 1) + fun_l24_n400(x) + else + fun_l24_n834(x) + end +end + +def fun_l23_n19(x) + if (x < 1) + fun_l24_n188(x) + else + fun_l24_n305(x) + end +end + +def fun_l23_n20(x) + if (x < 1) + fun_l24_n392(x) + else + fun_l24_n466(x) + end +end + +def fun_l23_n21(x) + if (x < 1) + fun_l24_n937(x) + else + fun_l24_n603(x) + end +end + +def fun_l23_n22(x) + if (x < 1) + fun_l24_n767(x) + else + fun_l24_n750(x) + end +end + +def fun_l23_n23(x) + if (x < 1) + fun_l24_n888(x) + else + fun_l24_n472(x) + end +end + +def fun_l23_n24(x) + if (x < 1) + fun_l24_n937(x) + else + fun_l24_n192(x) + end +end + +def fun_l23_n25(x) + if (x < 1) + fun_l24_n704(x) + else + fun_l24_n839(x) + end +end + +def fun_l23_n26(x) + if (x < 1) + fun_l24_n758(x) + else + fun_l24_n579(x) + end +end + +def fun_l23_n27(x) + if (x < 1) + fun_l24_n161(x) + else + fun_l24_n268(x) + end +end + +def fun_l23_n28(x) + if (x < 1) + fun_l24_n628(x) + else + fun_l24_n413(x) + end +end + +def fun_l23_n29(x) + if (x < 1) + fun_l24_n954(x) + else + fun_l24_n962(x) + end +end + +def fun_l23_n30(x) + if (x < 1) + fun_l24_n723(x) + else + fun_l24_n220(x) + end +end + +def fun_l23_n31(x) + if (x < 1) + fun_l24_n841(x) + else + fun_l24_n331(x) + end +end + +def fun_l23_n32(x) + if (x < 1) + fun_l24_n42(x) + else + fun_l24_n331(x) + end +end + +def fun_l23_n33(x) + if (x < 1) + fun_l24_n873(x) + else + fun_l24_n58(x) + end +end + +def fun_l23_n34(x) + if (x < 1) + fun_l24_n586(x) + else + fun_l24_n981(x) + end +end + +def fun_l23_n35(x) + if (x < 1) + fun_l24_n455(x) + else + fun_l24_n279(x) + end +end + +def fun_l23_n36(x) + if (x < 1) + fun_l24_n401(x) + else + fun_l24_n633(x) + end +end + +def fun_l23_n37(x) + if (x < 1) + fun_l24_n432(x) + else + fun_l24_n389(x) + end +end + +def fun_l23_n38(x) + if (x < 1) + fun_l24_n46(x) + else + fun_l24_n426(x) + end +end + +def fun_l23_n39(x) + if (x < 1) + fun_l24_n679(x) + else + fun_l24_n222(x) + end +end + +def fun_l23_n40(x) + if (x < 1) + fun_l24_n129(x) + else + fun_l24_n2(x) + end +end + +def fun_l23_n41(x) + if (x < 1) + fun_l24_n228(x) + else + fun_l24_n386(x) + end +end + +def fun_l23_n42(x) + if (x < 1) + fun_l24_n740(x) + else + fun_l24_n605(x) + end +end + +def fun_l23_n43(x) + if (x < 1) + fun_l24_n686(x) + else + fun_l24_n755(x) + end +end + +def fun_l23_n44(x) + if (x < 1) + fun_l24_n569(x) + else + fun_l24_n553(x) + end +end + +def fun_l23_n45(x) + if (x < 1) + fun_l24_n908(x) + else + fun_l24_n388(x) + end +end + +def fun_l23_n46(x) + if (x < 1) + fun_l24_n106(x) + else + fun_l24_n335(x) + end +end + +def fun_l23_n47(x) + if (x < 1) + fun_l24_n876(x) + else + fun_l24_n813(x) + end +end + +def fun_l23_n48(x) + if (x < 1) + fun_l24_n337(x) + else + fun_l24_n967(x) + end +end + +def fun_l23_n49(x) + if (x < 1) + fun_l24_n309(x) + else + fun_l24_n988(x) + end +end + +def fun_l23_n50(x) + if (x < 1) + fun_l24_n325(x) + else + fun_l24_n703(x) + end +end + +def fun_l23_n51(x) + if (x < 1) + fun_l24_n755(x) + else + fun_l24_n146(x) + end +end + +def fun_l23_n52(x) + if (x < 1) + fun_l24_n597(x) + else + fun_l24_n764(x) + end +end + +def fun_l23_n53(x) + if (x < 1) + fun_l24_n259(x) + else + fun_l24_n9(x) + end +end + +def fun_l23_n54(x) + if (x < 1) + fun_l24_n73(x) + else + fun_l24_n700(x) + end +end + +def fun_l23_n55(x) + if (x < 1) + fun_l24_n369(x) + else + fun_l24_n632(x) + end +end + +def fun_l23_n56(x) + if (x < 1) + fun_l24_n475(x) + else + fun_l24_n553(x) + end +end + +def fun_l23_n57(x) + if (x < 1) + fun_l24_n473(x) + else + fun_l24_n84(x) + end +end + +def fun_l23_n58(x) + if (x < 1) + fun_l24_n837(x) + else + fun_l24_n164(x) + end +end + +def fun_l23_n59(x) + if (x < 1) + fun_l24_n129(x) + else + fun_l24_n993(x) + end +end + +def fun_l23_n60(x) + if (x < 1) + fun_l24_n201(x) + else + fun_l24_n644(x) + end +end + +def fun_l23_n61(x) + if (x < 1) + fun_l24_n825(x) + else + fun_l24_n513(x) + end +end + +def fun_l23_n62(x) + if (x < 1) + fun_l24_n162(x) + else + fun_l24_n575(x) + end +end + +def fun_l23_n63(x) + if (x < 1) + fun_l24_n959(x) + else + fun_l24_n514(x) + end +end + +def fun_l23_n64(x) + if (x < 1) + fun_l24_n133(x) + else + fun_l24_n731(x) + end +end + +def fun_l23_n65(x) + if (x < 1) + fun_l24_n370(x) + else + fun_l24_n903(x) + end +end + +def fun_l23_n66(x) + if (x < 1) + fun_l24_n787(x) + else + fun_l24_n11(x) + end +end + +def fun_l23_n67(x) + if (x < 1) + fun_l24_n307(x) + else + fun_l24_n7(x) + end +end + +def fun_l23_n68(x) + if (x < 1) + fun_l24_n157(x) + else + fun_l24_n747(x) + end +end + +def fun_l23_n69(x) + if (x < 1) + fun_l24_n435(x) + else + fun_l24_n763(x) + end +end + +def fun_l23_n70(x) + if (x < 1) + fun_l24_n623(x) + else + fun_l24_n279(x) + end +end + +def fun_l23_n71(x) + if (x < 1) + fun_l24_n456(x) + else + fun_l24_n465(x) + end +end + +def fun_l23_n72(x) + if (x < 1) + fun_l24_n411(x) + else + fun_l24_n397(x) + end +end + +def fun_l23_n73(x) + if (x < 1) + fun_l24_n964(x) + else + fun_l24_n144(x) + end +end + +def fun_l23_n74(x) + if (x < 1) + fun_l24_n170(x) + else + fun_l24_n406(x) + end +end + +def fun_l23_n75(x) + if (x < 1) + fun_l24_n838(x) + else + fun_l24_n295(x) + end +end + +def fun_l23_n76(x) + if (x < 1) + fun_l24_n89(x) + else + fun_l24_n803(x) + end +end + +def fun_l23_n77(x) + if (x < 1) + fun_l24_n580(x) + else + fun_l24_n931(x) + end +end + +def fun_l23_n78(x) + if (x < 1) + fun_l24_n504(x) + else + fun_l24_n150(x) + end +end + +def fun_l23_n79(x) + if (x < 1) + fun_l24_n363(x) + else + fun_l24_n717(x) + end +end + +def fun_l23_n80(x) + if (x < 1) + fun_l24_n765(x) + else + fun_l24_n917(x) + end +end + +def fun_l23_n81(x) + if (x < 1) + fun_l24_n673(x) + else + fun_l24_n549(x) + end +end + +def fun_l23_n82(x) + if (x < 1) + fun_l24_n986(x) + else + fun_l24_n177(x) + end +end + +def fun_l23_n83(x) + if (x < 1) + fun_l24_n821(x) + else + fun_l24_n302(x) + end +end + +def fun_l23_n84(x) + if (x < 1) + fun_l24_n530(x) + else + fun_l24_n744(x) + end +end + +def fun_l23_n85(x) + if (x < 1) + fun_l24_n456(x) + else + fun_l24_n964(x) + end +end + +def fun_l23_n86(x) + if (x < 1) + fun_l24_n901(x) + else + fun_l24_n214(x) + end +end + +def fun_l23_n87(x) + if (x < 1) + fun_l24_n308(x) + else + fun_l24_n329(x) + end +end + +def fun_l23_n88(x) + if (x < 1) + fun_l24_n749(x) + else + fun_l24_n822(x) + end +end + +def fun_l23_n89(x) + if (x < 1) + fun_l24_n283(x) + else + fun_l24_n865(x) + end +end + +def fun_l23_n90(x) + if (x < 1) + fun_l24_n834(x) + else + fun_l24_n422(x) + end +end + +def fun_l23_n91(x) + if (x < 1) + fun_l24_n920(x) + else + fun_l24_n799(x) + end +end + +def fun_l23_n92(x) + if (x < 1) + fun_l24_n272(x) + else + fun_l24_n846(x) + end +end + +def fun_l23_n93(x) + if (x < 1) + fun_l24_n447(x) + else + fun_l24_n809(x) + end +end + +def fun_l23_n94(x) + if (x < 1) + fun_l24_n826(x) + else + fun_l24_n521(x) + end +end + +def fun_l23_n95(x) + if (x < 1) + fun_l24_n934(x) + else + fun_l24_n774(x) + end +end + +def fun_l23_n96(x) + if (x < 1) + fun_l24_n440(x) + else + fun_l24_n40(x) + end +end + +def fun_l23_n97(x) + if (x < 1) + fun_l24_n980(x) + else + fun_l24_n801(x) + end +end + +def fun_l23_n98(x) + if (x < 1) + fun_l24_n344(x) + else + fun_l24_n239(x) + end +end + +def fun_l23_n99(x) + if (x < 1) + fun_l24_n918(x) + else + fun_l24_n241(x) + end +end + +def fun_l23_n100(x) + if (x < 1) + fun_l24_n902(x) + else + fun_l24_n12(x) + end +end + +def fun_l23_n101(x) + if (x < 1) + fun_l24_n533(x) + else + fun_l24_n510(x) + end +end + +def fun_l23_n102(x) + if (x < 1) + fun_l24_n337(x) + else + fun_l24_n144(x) + end +end + +def fun_l23_n103(x) + if (x < 1) + fun_l24_n835(x) + else + fun_l24_n268(x) + end +end + +def fun_l23_n104(x) + if (x < 1) + fun_l24_n352(x) + else + fun_l24_n772(x) + end +end + +def fun_l23_n105(x) + if (x < 1) + fun_l24_n135(x) + else + fun_l24_n97(x) + end +end + +def fun_l23_n106(x) + if (x < 1) + fun_l24_n70(x) + else + fun_l24_n528(x) + end +end + +def fun_l23_n107(x) + if (x < 1) + fun_l24_n945(x) + else + fun_l24_n85(x) + end +end + +def fun_l23_n108(x) + if (x < 1) + fun_l24_n233(x) + else + fun_l24_n637(x) + end +end + +def fun_l23_n109(x) + if (x < 1) + fun_l24_n715(x) + else + fun_l24_n111(x) + end +end + +def fun_l23_n110(x) + if (x < 1) + fun_l24_n673(x) + else + fun_l24_n423(x) + end +end + +def fun_l23_n111(x) + if (x < 1) + fun_l24_n408(x) + else + fun_l24_n5(x) + end +end + +def fun_l23_n112(x) + if (x < 1) + fun_l24_n89(x) + else + fun_l24_n669(x) + end +end + +def fun_l23_n113(x) + if (x < 1) + fun_l24_n733(x) + else + fun_l24_n76(x) + end +end + +def fun_l23_n114(x) + if (x < 1) + fun_l24_n767(x) + else + fun_l24_n465(x) + end +end + +def fun_l23_n115(x) + if (x < 1) + fun_l24_n428(x) + else + fun_l24_n948(x) + end +end + +def fun_l23_n116(x) + if (x < 1) + fun_l24_n412(x) + else + fun_l24_n355(x) + end +end + +def fun_l23_n117(x) + if (x < 1) + fun_l24_n550(x) + else + fun_l24_n616(x) + end +end + +def fun_l23_n118(x) + if (x < 1) + fun_l24_n858(x) + else + fun_l24_n74(x) + end +end + +def fun_l23_n119(x) + if (x < 1) + fun_l24_n709(x) + else + fun_l24_n939(x) + end +end + +def fun_l23_n120(x) + if (x < 1) + fun_l24_n712(x) + else + fun_l24_n74(x) + end +end + +def fun_l23_n121(x) + if (x < 1) + fun_l24_n34(x) + else + fun_l24_n532(x) + end +end + +def fun_l23_n122(x) + if (x < 1) + fun_l24_n998(x) + else + fun_l24_n736(x) + end +end + +def fun_l23_n123(x) + if (x < 1) + fun_l24_n33(x) + else + fun_l24_n561(x) + end +end + +def fun_l23_n124(x) + if (x < 1) + fun_l24_n750(x) + else + fun_l24_n634(x) + end +end + +def fun_l23_n125(x) + if (x < 1) + fun_l24_n935(x) + else + fun_l24_n29(x) + end +end + +def fun_l23_n126(x) + if (x < 1) + fun_l24_n249(x) + else + fun_l24_n571(x) + end +end + +def fun_l23_n127(x) + if (x < 1) + fun_l24_n827(x) + else + fun_l24_n892(x) + end +end + +def fun_l23_n128(x) + if (x < 1) + fun_l24_n903(x) + else + fun_l24_n171(x) + end +end + +def fun_l23_n129(x) + if (x < 1) + fun_l24_n725(x) + else + fun_l24_n358(x) + end +end + +def fun_l23_n130(x) + if (x < 1) + fun_l24_n616(x) + else + fun_l24_n795(x) + end +end + +def fun_l23_n131(x) + if (x < 1) + fun_l24_n942(x) + else + fun_l24_n574(x) + end +end + +def fun_l23_n132(x) + if (x < 1) + fun_l24_n290(x) + else + fun_l24_n869(x) + end +end + +def fun_l23_n133(x) + if (x < 1) + fun_l24_n73(x) + else + fun_l24_n542(x) + end +end + +def fun_l23_n134(x) + if (x < 1) + fun_l24_n730(x) + else + fun_l24_n857(x) + end +end + +def fun_l23_n135(x) + if (x < 1) + fun_l24_n754(x) + else + fun_l24_n579(x) + end +end + +def fun_l23_n136(x) + if (x < 1) + fun_l24_n503(x) + else + fun_l24_n574(x) + end +end + +def fun_l23_n137(x) + if (x < 1) + fun_l24_n682(x) + else + fun_l24_n630(x) + end +end + +def fun_l23_n138(x) + if (x < 1) + fun_l24_n918(x) + else + fun_l24_n440(x) + end +end + +def fun_l23_n139(x) + if (x < 1) + fun_l24_n938(x) + else + fun_l24_n524(x) + end +end + +def fun_l23_n140(x) + if (x < 1) + fun_l24_n966(x) + else + fun_l24_n921(x) + end +end + +def fun_l23_n141(x) + if (x < 1) + fun_l24_n87(x) + else + fun_l24_n548(x) + end +end + +def fun_l23_n142(x) + if (x < 1) + fun_l24_n828(x) + else + fun_l24_n708(x) + end +end + +def fun_l23_n143(x) + if (x < 1) + fun_l24_n655(x) + else + fun_l24_n322(x) + end +end + +def fun_l23_n144(x) + if (x < 1) + fun_l24_n382(x) + else + fun_l24_n484(x) + end +end + +def fun_l23_n145(x) + if (x < 1) + fun_l24_n830(x) + else + fun_l24_n755(x) + end +end + +def fun_l23_n146(x) + if (x < 1) + fun_l24_n432(x) + else + fun_l24_n487(x) + end +end + +def fun_l23_n147(x) + if (x < 1) + fun_l24_n954(x) + else + fun_l24_n453(x) + end +end + +def fun_l23_n148(x) + if (x < 1) + fun_l24_n562(x) + else + fun_l24_n872(x) + end +end + +def fun_l23_n149(x) + if (x < 1) + fun_l24_n929(x) + else + fun_l24_n212(x) + end +end + +def fun_l23_n150(x) + if (x < 1) + fun_l24_n143(x) + else + fun_l24_n344(x) + end +end + +def fun_l23_n151(x) + if (x < 1) + fun_l24_n475(x) + else + fun_l24_n379(x) + end +end + +def fun_l23_n152(x) + if (x < 1) + fun_l24_n160(x) + else + fun_l24_n774(x) + end +end + +def fun_l23_n153(x) + if (x < 1) + fun_l24_n689(x) + else + fun_l24_n19(x) + end +end + +def fun_l23_n154(x) + if (x < 1) + fun_l24_n98(x) + else + fun_l24_n572(x) + end +end + +def fun_l23_n155(x) + if (x < 1) + fun_l24_n104(x) + else + fun_l24_n797(x) + end +end + +def fun_l23_n156(x) + if (x < 1) + fun_l24_n892(x) + else + fun_l24_n874(x) + end +end + +def fun_l23_n157(x) + if (x < 1) + fun_l24_n900(x) + else + fun_l24_n458(x) + end +end + +def fun_l23_n158(x) + if (x < 1) + fun_l24_n50(x) + else + fun_l24_n912(x) + end +end + +def fun_l23_n159(x) + if (x < 1) + fun_l24_n303(x) + else + fun_l24_n373(x) + end +end + +def fun_l23_n160(x) + if (x < 1) + fun_l24_n137(x) + else + fun_l24_n102(x) + end +end + +def fun_l23_n161(x) + if (x < 1) + fun_l24_n263(x) + else + fun_l24_n818(x) + end +end + +def fun_l23_n162(x) + if (x < 1) + fun_l24_n618(x) + else + fun_l24_n895(x) + end +end + +def fun_l23_n163(x) + if (x < 1) + fun_l24_n845(x) + else + fun_l24_n26(x) + end +end + +def fun_l23_n164(x) + if (x < 1) + fun_l24_n941(x) + else + fun_l24_n242(x) + end +end + +def fun_l23_n165(x) + if (x < 1) + fun_l24_n145(x) + else + fun_l24_n492(x) + end +end + +def fun_l23_n166(x) + if (x < 1) + fun_l24_n261(x) + else + fun_l24_n235(x) + end +end + +def fun_l23_n167(x) + if (x < 1) + fun_l24_n941(x) + else + fun_l24_n618(x) + end +end + +def fun_l23_n168(x) + if (x < 1) + fun_l24_n709(x) + else + fun_l24_n908(x) + end +end + +def fun_l23_n169(x) + if (x < 1) + fun_l24_n746(x) + else + fun_l24_n116(x) + end +end + +def fun_l23_n170(x) + if (x < 1) + fun_l24_n911(x) + else + fun_l24_n599(x) + end +end + +def fun_l23_n171(x) + if (x < 1) + fun_l24_n526(x) + else + fun_l24_n275(x) + end +end + +def fun_l23_n172(x) + if (x < 1) + fun_l24_n919(x) + else + fun_l24_n525(x) + end +end + +def fun_l23_n173(x) + if (x < 1) + fun_l24_n945(x) + else + fun_l24_n894(x) + end +end + +def fun_l23_n174(x) + if (x < 1) + fun_l24_n349(x) + else + fun_l24_n434(x) + end +end + +def fun_l23_n175(x) + if (x < 1) + fun_l24_n498(x) + else + fun_l24_n679(x) + end +end + +def fun_l23_n176(x) + if (x < 1) + fun_l24_n867(x) + else + fun_l24_n177(x) + end +end + +def fun_l23_n177(x) + if (x < 1) + fun_l24_n680(x) + else + fun_l24_n601(x) + end +end + +def fun_l23_n178(x) + if (x < 1) + fun_l24_n838(x) + else + fun_l24_n5(x) + end +end + +def fun_l23_n179(x) + if (x < 1) + fun_l24_n418(x) + else + fun_l24_n780(x) + end +end + +def fun_l23_n180(x) + if (x < 1) + fun_l24_n88(x) + else + fun_l24_n333(x) + end +end + +def fun_l23_n181(x) + if (x < 1) + fun_l24_n657(x) + else + fun_l24_n787(x) + end +end + +def fun_l23_n182(x) + if (x < 1) + fun_l24_n767(x) + else + fun_l24_n903(x) + end +end + +def fun_l23_n183(x) + if (x < 1) + fun_l24_n878(x) + else + fun_l24_n426(x) + end +end + +def fun_l23_n184(x) + if (x < 1) + fun_l24_n649(x) + else + fun_l24_n221(x) + end +end + +def fun_l23_n185(x) + if (x < 1) + fun_l24_n315(x) + else + fun_l24_n955(x) + end +end + +def fun_l23_n186(x) + if (x < 1) + fun_l24_n599(x) + else + fun_l24_n201(x) + end +end + +def fun_l23_n187(x) + if (x < 1) + fun_l24_n851(x) + else + fun_l24_n294(x) + end +end + +def fun_l23_n188(x) + if (x < 1) + fun_l24_n585(x) + else + fun_l24_n139(x) + end +end + +def fun_l23_n189(x) + if (x < 1) + fun_l24_n893(x) + else + fun_l24_n159(x) + end +end + +def fun_l23_n190(x) + if (x < 1) + fun_l24_n70(x) + else + fun_l24_n50(x) + end +end + +def fun_l23_n191(x) + if (x < 1) + fun_l24_n111(x) + else + fun_l24_n967(x) + end +end + +def fun_l23_n192(x) + if (x < 1) + fun_l24_n979(x) + else + fun_l24_n91(x) + end +end + +def fun_l23_n193(x) + if (x < 1) + fun_l24_n651(x) + else + fun_l24_n321(x) + end +end + +def fun_l23_n194(x) + if (x < 1) + fun_l24_n236(x) + else + fun_l24_n251(x) + end +end + +def fun_l23_n195(x) + if (x < 1) + fun_l24_n947(x) + else + fun_l24_n116(x) + end +end + +def fun_l23_n196(x) + if (x < 1) + fun_l24_n336(x) + else + fun_l24_n637(x) + end +end + +def fun_l23_n197(x) + if (x < 1) + fun_l24_n192(x) + else + fun_l24_n824(x) + end +end + +def fun_l23_n198(x) + if (x < 1) + fun_l24_n747(x) + else + fun_l24_n610(x) + end +end + +def fun_l23_n199(x) + if (x < 1) + fun_l24_n735(x) + else + fun_l24_n347(x) + end +end + +def fun_l23_n200(x) + if (x < 1) + fun_l24_n543(x) + else + fun_l24_n463(x) + end +end + +def fun_l23_n201(x) + if (x < 1) + fun_l24_n933(x) + else + fun_l24_n185(x) + end +end + +def fun_l23_n202(x) + if (x < 1) + fun_l24_n319(x) + else + fun_l24_n739(x) + end +end + +def fun_l23_n203(x) + if (x < 1) + fun_l24_n994(x) + else + fun_l24_n248(x) + end +end + +def fun_l23_n204(x) + if (x < 1) + fun_l24_n980(x) + else + fun_l24_n248(x) + end +end + +def fun_l23_n205(x) + if (x < 1) + fun_l24_n427(x) + else + fun_l24_n670(x) + end +end + +def fun_l23_n206(x) + if (x < 1) + fun_l24_n562(x) + else + fun_l24_n752(x) + end +end + +def fun_l23_n207(x) + if (x < 1) + fun_l24_n424(x) + else + fun_l24_n310(x) + end +end + +def fun_l23_n208(x) + if (x < 1) + fun_l24_n761(x) + else + fun_l24_n562(x) + end +end + +def fun_l23_n209(x) + if (x < 1) + fun_l24_n264(x) + else + fun_l24_n20(x) + end +end + +def fun_l23_n210(x) + if (x < 1) + fun_l24_n886(x) + else + fun_l24_n505(x) + end +end + +def fun_l23_n211(x) + if (x < 1) + fun_l24_n715(x) + else + fun_l24_n641(x) + end +end + +def fun_l23_n212(x) + if (x < 1) + fun_l24_n132(x) + else + fun_l24_n875(x) + end +end + +def fun_l23_n213(x) + if (x < 1) + fun_l24_n121(x) + else + fun_l24_n38(x) + end +end + +def fun_l23_n214(x) + if (x < 1) + fun_l24_n672(x) + else + fun_l24_n497(x) + end +end + +def fun_l23_n215(x) + if (x < 1) + fun_l24_n36(x) + else + fun_l24_n696(x) + end +end + +def fun_l23_n216(x) + if (x < 1) + fun_l24_n559(x) + else + fun_l24_n772(x) + end +end + +def fun_l23_n217(x) + if (x < 1) + fun_l24_n63(x) + else + fun_l24_n990(x) + end +end + +def fun_l23_n218(x) + if (x < 1) + fun_l24_n482(x) + else + fun_l24_n811(x) + end +end + +def fun_l23_n219(x) + if (x < 1) + fun_l24_n572(x) + else + fun_l24_n651(x) + end +end + +def fun_l23_n220(x) + if (x < 1) + fun_l24_n588(x) + else + fun_l24_n87(x) + end +end + +def fun_l23_n221(x) + if (x < 1) + fun_l24_n462(x) + else + fun_l24_n909(x) + end +end + +def fun_l23_n222(x) + if (x < 1) + fun_l24_n729(x) + else + fun_l24_n364(x) + end +end + +def fun_l23_n223(x) + if (x < 1) + fun_l24_n259(x) + else + fun_l24_n661(x) + end +end + +def fun_l23_n224(x) + if (x < 1) + fun_l24_n504(x) + else + fun_l24_n531(x) + end +end + +def fun_l23_n225(x) + if (x < 1) + fun_l24_n114(x) + else + fun_l24_n292(x) + end +end + +def fun_l23_n226(x) + if (x < 1) + fun_l24_n207(x) + else + fun_l24_n206(x) + end +end + +def fun_l23_n227(x) + if (x < 1) + fun_l24_n153(x) + else + fun_l24_n572(x) + end +end + +def fun_l23_n228(x) + if (x < 1) + fun_l24_n738(x) + else + fun_l24_n767(x) + end +end + +def fun_l23_n229(x) + if (x < 1) + fun_l24_n374(x) + else + fun_l24_n336(x) + end +end + +def fun_l23_n230(x) + if (x < 1) + fun_l24_n727(x) + else + fun_l24_n842(x) + end +end + +def fun_l23_n231(x) + if (x < 1) + fun_l24_n506(x) + else + fun_l24_n8(x) + end +end + +def fun_l23_n232(x) + if (x < 1) + fun_l24_n101(x) + else + fun_l24_n502(x) + end +end + +def fun_l23_n233(x) + if (x < 1) + fun_l24_n469(x) + else + fun_l24_n274(x) + end +end + +def fun_l23_n234(x) + if (x < 1) + fun_l24_n67(x) + else + fun_l24_n66(x) + end +end + +def fun_l23_n235(x) + if (x < 1) + fun_l24_n874(x) + else + fun_l24_n104(x) + end +end + +def fun_l23_n236(x) + if (x < 1) + fun_l24_n154(x) + else + fun_l24_n723(x) + end +end + +def fun_l23_n237(x) + if (x < 1) + fun_l24_n300(x) + else + fun_l24_n0(x) + end +end + +def fun_l23_n238(x) + if (x < 1) + fun_l24_n767(x) + else + fun_l24_n134(x) + end +end + +def fun_l23_n239(x) + if (x < 1) + fun_l24_n647(x) + else + fun_l24_n890(x) + end +end + +def fun_l23_n240(x) + if (x < 1) + fun_l24_n258(x) + else + fun_l24_n302(x) + end +end + +def fun_l23_n241(x) + if (x < 1) + fun_l24_n104(x) + else + fun_l24_n335(x) + end +end + +def fun_l23_n242(x) + if (x < 1) + fun_l24_n500(x) + else + fun_l24_n383(x) + end +end + +def fun_l23_n243(x) + if (x < 1) + fun_l24_n63(x) + else + fun_l24_n421(x) + end +end + +def fun_l23_n244(x) + if (x < 1) + fun_l24_n105(x) + else + fun_l24_n451(x) + end +end + +def fun_l23_n245(x) + if (x < 1) + fun_l24_n729(x) + else + fun_l24_n333(x) + end +end + +def fun_l23_n246(x) + if (x < 1) + fun_l24_n966(x) + else + fun_l24_n556(x) + end +end + +def fun_l23_n247(x) + if (x < 1) + fun_l24_n118(x) + else + fun_l24_n565(x) + end +end + +def fun_l23_n248(x) + if (x < 1) + fun_l24_n61(x) + else + fun_l24_n816(x) + end +end + +def fun_l23_n249(x) + if (x < 1) + fun_l24_n769(x) + else + fun_l24_n183(x) + end +end + +def fun_l23_n250(x) + if (x < 1) + fun_l24_n688(x) + else + fun_l24_n60(x) + end +end + +def fun_l23_n251(x) + if (x < 1) + fun_l24_n859(x) + else + fun_l24_n434(x) + end +end + +def fun_l23_n252(x) + if (x < 1) + fun_l24_n650(x) + else + fun_l24_n448(x) + end +end + +def fun_l23_n253(x) + if (x < 1) + fun_l24_n519(x) + else + fun_l24_n963(x) + end +end + +def fun_l23_n254(x) + if (x < 1) + fun_l24_n176(x) + else + fun_l24_n908(x) + end +end + +def fun_l23_n255(x) + if (x < 1) + fun_l24_n146(x) + else + fun_l24_n751(x) + end +end + +def fun_l23_n256(x) + if (x < 1) + fun_l24_n742(x) + else + fun_l24_n928(x) + end +end + +def fun_l23_n257(x) + if (x < 1) + fun_l24_n22(x) + else + fun_l24_n48(x) + end +end + +def fun_l23_n258(x) + if (x < 1) + fun_l24_n158(x) + else + fun_l24_n299(x) + end +end + +def fun_l23_n259(x) + if (x < 1) + fun_l24_n247(x) + else + fun_l24_n419(x) + end +end + +def fun_l23_n260(x) + if (x < 1) + fun_l24_n161(x) + else + fun_l24_n387(x) + end +end + +def fun_l23_n261(x) + if (x < 1) + fun_l24_n627(x) + else + fun_l24_n321(x) + end +end + +def fun_l23_n262(x) + if (x < 1) + fun_l24_n946(x) + else + fun_l24_n617(x) + end +end + +def fun_l23_n263(x) + if (x < 1) + fun_l24_n853(x) + else + fun_l24_n208(x) + end +end + +def fun_l23_n264(x) + if (x < 1) + fun_l24_n213(x) + else + fun_l24_n27(x) + end +end + +def fun_l23_n265(x) + if (x < 1) + fun_l24_n819(x) + else + fun_l24_n438(x) + end +end + +def fun_l23_n266(x) + if (x < 1) + fun_l24_n351(x) + else + fun_l24_n739(x) + end +end + +def fun_l23_n267(x) + if (x < 1) + fun_l24_n333(x) + else + fun_l24_n179(x) + end +end + +def fun_l23_n268(x) + if (x < 1) + fun_l24_n528(x) + else + fun_l24_n397(x) + end +end + +def fun_l23_n269(x) + if (x < 1) + fun_l24_n655(x) + else + fun_l24_n994(x) + end +end + +def fun_l23_n270(x) + if (x < 1) + fun_l24_n257(x) + else + fun_l24_n346(x) + end +end + +def fun_l23_n271(x) + if (x < 1) + fun_l24_n183(x) + else + fun_l24_n908(x) + end +end + +def fun_l23_n272(x) + if (x < 1) + fun_l24_n742(x) + else + fun_l24_n483(x) + end +end + +def fun_l23_n273(x) + if (x < 1) + fun_l24_n803(x) + else + fun_l24_n318(x) + end +end + +def fun_l23_n274(x) + if (x < 1) + fun_l24_n228(x) + else + fun_l24_n540(x) + end +end + +def fun_l23_n275(x) + if (x < 1) + fun_l24_n999(x) + else + fun_l24_n55(x) + end +end + +def fun_l23_n276(x) + if (x < 1) + fun_l24_n129(x) + else + fun_l24_n235(x) + end +end + +def fun_l23_n277(x) + if (x < 1) + fun_l24_n320(x) + else + fun_l24_n211(x) + end +end + +def fun_l23_n278(x) + if (x < 1) + fun_l24_n757(x) + else + fun_l24_n440(x) + end +end + +def fun_l23_n279(x) + if (x < 1) + fun_l24_n784(x) + else + fun_l24_n117(x) + end +end + +def fun_l23_n280(x) + if (x < 1) + fun_l24_n280(x) + else + fun_l24_n560(x) + end +end + +def fun_l23_n281(x) + if (x < 1) + fun_l24_n981(x) + else + fun_l24_n939(x) + end +end + +def fun_l23_n282(x) + if (x < 1) + fun_l24_n500(x) + else + fun_l24_n90(x) + end +end + +def fun_l23_n283(x) + if (x < 1) + fun_l24_n958(x) + else + fun_l24_n415(x) + end +end + +def fun_l23_n284(x) + if (x < 1) + fun_l24_n237(x) + else + fun_l24_n556(x) + end +end + +def fun_l23_n285(x) + if (x < 1) + fun_l24_n87(x) + else + fun_l24_n630(x) + end +end + +def fun_l23_n286(x) + if (x < 1) + fun_l24_n121(x) + else + fun_l24_n974(x) + end +end + +def fun_l23_n287(x) + if (x < 1) + fun_l24_n491(x) + else + fun_l24_n505(x) + end +end + +def fun_l23_n288(x) + if (x < 1) + fun_l24_n342(x) + else + fun_l24_n408(x) + end +end + +def fun_l23_n289(x) + if (x < 1) + fun_l24_n456(x) + else + fun_l24_n768(x) + end +end + +def fun_l23_n290(x) + if (x < 1) + fun_l24_n64(x) + else + fun_l24_n515(x) + end +end + +def fun_l23_n291(x) + if (x < 1) + fun_l24_n86(x) + else + fun_l24_n420(x) + end +end + +def fun_l23_n292(x) + if (x < 1) + fun_l24_n61(x) + else + fun_l24_n295(x) + end +end + +def fun_l23_n293(x) + if (x < 1) + fun_l24_n893(x) + else + fun_l24_n680(x) + end +end + +def fun_l23_n294(x) + if (x < 1) + fun_l24_n81(x) + else + fun_l24_n946(x) + end +end + +def fun_l23_n295(x) + if (x < 1) + fun_l24_n444(x) + else + fun_l24_n205(x) + end +end + +def fun_l23_n296(x) + if (x < 1) + fun_l24_n898(x) + else + fun_l24_n101(x) + end +end + +def fun_l23_n297(x) + if (x < 1) + fun_l24_n617(x) + else + fun_l24_n660(x) + end +end + +def fun_l23_n298(x) + if (x < 1) + fun_l24_n117(x) + else + fun_l24_n806(x) + end +end + +def fun_l23_n299(x) + if (x < 1) + fun_l24_n92(x) + else + fun_l24_n660(x) + end +end + +def fun_l23_n300(x) + if (x < 1) + fun_l24_n202(x) + else + fun_l24_n611(x) + end +end + +def fun_l23_n301(x) + if (x < 1) + fun_l24_n852(x) + else + fun_l24_n569(x) + end +end + +def fun_l23_n302(x) + if (x < 1) + fun_l24_n69(x) + else + fun_l24_n725(x) + end +end + +def fun_l23_n303(x) + if (x < 1) + fun_l24_n183(x) + else + fun_l24_n406(x) + end +end + +def fun_l23_n304(x) + if (x < 1) + fun_l24_n926(x) + else + fun_l24_n838(x) + end +end + +def fun_l23_n305(x) + if (x < 1) + fun_l24_n16(x) + else + fun_l24_n681(x) + end +end + +def fun_l23_n306(x) + if (x < 1) + fun_l24_n43(x) + else + fun_l24_n504(x) + end +end + +def fun_l23_n307(x) + if (x < 1) + fun_l24_n417(x) + else + fun_l24_n239(x) + end +end + +def fun_l23_n308(x) + if (x < 1) + fun_l24_n353(x) + else + fun_l24_n467(x) + end +end + +def fun_l23_n309(x) + if (x < 1) + fun_l24_n633(x) + else + fun_l24_n593(x) + end +end + +def fun_l23_n310(x) + if (x < 1) + fun_l24_n974(x) + else + fun_l24_n894(x) + end +end + +def fun_l23_n311(x) + if (x < 1) + fun_l24_n3(x) + else + fun_l24_n751(x) + end +end + +def fun_l23_n312(x) + if (x < 1) + fun_l24_n728(x) + else + fun_l24_n116(x) + end +end + +def fun_l23_n313(x) + if (x < 1) + fun_l24_n588(x) + else + fun_l24_n636(x) + end +end + +def fun_l23_n314(x) + if (x < 1) + fun_l24_n284(x) + else + fun_l24_n751(x) + end +end + +def fun_l23_n315(x) + if (x < 1) + fun_l24_n567(x) + else + fun_l24_n356(x) + end +end + +def fun_l23_n316(x) + if (x < 1) + fun_l24_n78(x) + else + fun_l24_n714(x) + end +end + +def fun_l23_n317(x) + if (x < 1) + fun_l24_n592(x) + else + fun_l24_n720(x) + end +end + +def fun_l23_n318(x) + if (x < 1) + fun_l24_n273(x) + else + fun_l24_n367(x) + end +end + +def fun_l23_n319(x) + if (x < 1) + fun_l24_n816(x) + else + fun_l24_n964(x) + end +end + +def fun_l23_n320(x) + if (x < 1) + fun_l24_n59(x) + else + fun_l24_n630(x) + end +end + +def fun_l23_n321(x) + if (x < 1) + fun_l24_n298(x) + else + fun_l24_n639(x) + end +end + +def fun_l23_n322(x) + if (x < 1) + fun_l24_n70(x) + else + fun_l24_n714(x) + end +end + +def fun_l23_n323(x) + if (x < 1) + fun_l24_n495(x) + else + fun_l24_n630(x) + end +end + +def fun_l23_n324(x) + if (x < 1) + fun_l24_n780(x) + else + fun_l24_n932(x) + end +end + +def fun_l23_n325(x) + if (x < 1) + fun_l24_n494(x) + else + fun_l24_n610(x) + end +end + +def fun_l23_n326(x) + if (x < 1) + fun_l24_n509(x) + else + fun_l24_n635(x) + end +end + +def fun_l23_n327(x) + if (x < 1) + fun_l24_n991(x) + else + fun_l24_n355(x) + end +end + +def fun_l23_n328(x) + if (x < 1) + fun_l24_n153(x) + else + fun_l24_n234(x) + end +end + +def fun_l23_n329(x) + if (x < 1) + fun_l24_n483(x) + else + fun_l24_n812(x) + end +end + +def fun_l23_n330(x) + if (x < 1) + fun_l24_n123(x) + else + fun_l24_n665(x) + end +end + +def fun_l23_n331(x) + if (x < 1) + fun_l24_n752(x) + else + fun_l24_n471(x) + end +end + +def fun_l23_n332(x) + if (x < 1) + fun_l24_n440(x) + else + fun_l24_n788(x) + end +end + +def fun_l23_n333(x) + if (x < 1) + fun_l24_n381(x) + else + fun_l24_n95(x) + end +end + +def fun_l23_n334(x) + if (x < 1) + fun_l24_n379(x) + else + fun_l24_n982(x) + end +end + +def fun_l23_n335(x) + if (x < 1) + fun_l24_n766(x) + else + fun_l24_n14(x) + end +end + +def fun_l23_n336(x) + if (x < 1) + fun_l24_n733(x) + else + fun_l24_n614(x) + end +end + +def fun_l23_n337(x) + if (x < 1) + fun_l24_n946(x) + else + fun_l24_n408(x) + end +end + +def fun_l23_n338(x) + if (x < 1) + fun_l24_n98(x) + else + fun_l24_n542(x) + end +end + +def fun_l23_n339(x) + if (x < 1) + fun_l24_n60(x) + else + fun_l24_n970(x) + end +end + +def fun_l23_n340(x) + if (x < 1) + fun_l24_n933(x) + else + fun_l24_n517(x) + end +end + +def fun_l23_n341(x) + if (x < 1) + fun_l24_n634(x) + else + fun_l24_n943(x) + end +end + +def fun_l23_n342(x) + if (x < 1) + fun_l24_n50(x) + else + fun_l24_n800(x) + end +end + +def fun_l23_n343(x) + if (x < 1) + fun_l24_n352(x) + else + fun_l24_n450(x) + end +end + +def fun_l23_n344(x) + if (x < 1) + fun_l24_n340(x) + else + fun_l24_n101(x) + end +end + +def fun_l23_n345(x) + if (x < 1) + fun_l24_n383(x) + else + fun_l24_n493(x) + end +end + +def fun_l23_n346(x) + if (x < 1) + fun_l24_n805(x) + else + fun_l24_n845(x) + end +end + +def fun_l23_n347(x) + if (x < 1) + fun_l24_n491(x) + else + fun_l24_n756(x) + end +end + +def fun_l23_n348(x) + if (x < 1) + fun_l24_n508(x) + else + fun_l24_n2(x) + end +end + +def fun_l23_n349(x) + if (x < 1) + fun_l24_n865(x) + else + fun_l24_n55(x) + end +end + +def fun_l23_n350(x) + if (x < 1) + fun_l24_n218(x) + else + fun_l24_n456(x) + end +end + +def fun_l23_n351(x) + if (x < 1) + fun_l24_n162(x) + else + fun_l24_n312(x) + end +end + +def fun_l23_n352(x) + if (x < 1) + fun_l24_n309(x) + else + fun_l24_n431(x) + end +end + +def fun_l23_n353(x) + if (x < 1) + fun_l24_n411(x) + else + fun_l24_n684(x) + end +end + +def fun_l23_n354(x) + if (x < 1) + fun_l24_n381(x) + else + fun_l24_n703(x) + end +end + +def fun_l23_n355(x) + if (x < 1) + fun_l24_n189(x) + else + fun_l24_n217(x) + end +end + +def fun_l23_n356(x) + if (x < 1) + fun_l24_n180(x) + else + fun_l24_n706(x) + end +end + +def fun_l23_n357(x) + if (x < 1) + fun_l24_n76(x) + else + fun_l24_n575(x) + end +end + +def fun_l23_n358(x) + if (x < 1) + fun_l24_n574(x) + else + fun_l24_n842(x) + end +end + +def fun_l23_n359(x) + if (x < 1) + fun_l24_n281(x) + else + fun_l24_n572(x) + end +end + +def fun_l23_n360(x) + if (x < 1) + fun_l24_n2(x) + else + fun_l24_n928(x) + end +end + +def fun_l23_n361(x) + if (x < 1) + fun_l24_n840(x) + else + fun_l24_n794(x) + end +end + +def fun_l23_n362(x) + if (x < 1) + fun_l24_n657(x) + else + fun_l24_n987(x) + end +end + +def fun_l23_n363(x) + if (x < 1) + fun_l24_n400(x) + else + fun_l24_n151(x) + end +end + +def fun_l23_n364(x) + if (x < 1) + fun_l24_n123(x) + else + fun_l24_n873(x) + end +end + +def fun_l23_n365(x) + if (x < 1) + fun_l24_n51(x) + else + fun_l24_n52(x) + end +end + +def fun_l23_n366(x) + if (x < 1) + fun_l24_n809(x) + else + fun_l24_n32(x) + end +end + +def fun_l23_n367(x) + if (x < 1) + fun_l24_n928(x) + else + fun_l24_n618(x) + end +end + +def fun_l23_n368(x) + if (x < 1) + fun_l24_n563(x) + else + fun_l24_n937(x) + end +end + +def fun_l23_n369(x) + if (x < 1) + fun_l24_n312(x) + else + fun_l24_n918(x) + end +end + +def fun_l23_n370(x) + if (x < 1) + fun_l24_n940(x) + else + fun_l24_n994(x) + end +end + +def fun_l23_n371(x) + if (x < 1) + fun_l24_n788(x) + else + fun_l24_n187(x) + end +end + +def fun_l23_n372(x) + if (x < 1) + fun_l24_n110(x) + else + fun_l24_n523(x) + end +end + +def fun_l23_n373(x) + if (x < 1) + fun_l24_n158(x) + else + fun_l24_n656(x) + end +end + +def fun_l23_n374(x) + if (x < 1) + fun_l24_n522(x) + else + fun_l24_n395(x) + end +end + +def fun_l23_n375(x) + if (x < 1) + fun_l24_n90(x) + else + fun_l24_n732(x) + end +end + +def fun_l23_n376(x) + if (x < 1) + fun_l24_n809(x) + else + fun_l24_n513(x) + end +end + +def fun_l23_n377(x) + if (x < 1) + fun_l24_n916(x) + else + fun_l24_n962(x) + end +end + +def fun_l23_n378(x) + if (x < 1) + fun_l24_n852(x) + else + fun_l24_n350(x) + end +end + +def fun_l23_n379(x) + if (x < 1) + fun_l24_n555(x) + else + fun_l24_n375(x) + end +end + +def fun_l23_n380(x) + if (x < 1) + fun_l24_n17(x) + else + fun_l24_n566(x) + end +end + +def fun_l23_n381(x) + if (x < 1) + fun_l24_n332(x) + else + fun_l24_n35(x) + end +end + +def fun_l23_n382(x) + if (x < 1) + fun_l24_n531(x) + else + fun_l24_n368(x) + end +end + +def fun_l23_n383(x) + if (x < 1) + fun_l24_n712(x) + else + fun_l24_n32(x) + end +end + +def fun_l23_n384(x) + if (x < 1) + fun_l24_n239(x) + else + fun_l24_n542(x) + end +end + +def fun_l23_n385(x) + if (x < 1) + fun_l24_n914(x) + else + fun_l24_n820(x) + end +end + +def fun_l23_n386(x) + if (x < 1) + fun_l24_n579(x) + else + fun_l24_n202(x) + end +end + +def fun_l23_n387(x) + if (x < 1) + fun_l24_n36(x) + else + fun_l24_n591(x) + end +end + +def fun_l23_n388(x) + if (x < 1) + fun_l24_n485(x) + else + fun_l24_n707(x) + end +end + +def fun_l23_n389(x) + if (x < 1) + fun_l24_n587(x) + else + fun_l24_n588(x) + end +end + +def fun_l23_n390(x) + if (x < 1) + fun_l24_n837(x) + else + fun_l24_n352(x) + end +end + +def fun_l23_n391(x) + if (x < 1) + fun_l24_n926(x) + else + fun_l24_n553(x) + end +end + +def fun_l23_n392(x) + if (x < 1) + fun_l24_n557(x) + else + fun_l24_n944(x) + end +end + +def fun_l23_n393(x) + if (x < 1) + fun_l24_n870(x) + else + fun_l24_n632(x) + end +end + +def fun_l23_n394(x) + if (x < 1) + fun_l24_n732(x) + else + fun_l24_n285(x) + end +end + +def fun_l23_n395(x) + if (x < 1) + fun_l24_n249(x) + else + fun_l24_n709(x) + end +end + +def fun_l23_n396(x) + if (x < 1) + fun_l24_n674(x) + else + fun_l24_n693(x) + end +end + +def fun_l23_n397(x) + if (x < 1) + fun_l24_n20(x) + else + fun_l24_n367(x) + end +end + +def fun_l23_n398(x) + if (x < 1) + fun_l24_n545(x) + else + fun_l24_n973(x) + end +end + +def fun_l23_n399(x) + if (x < 1) + fun_l24_n460(x) + else + fun_l24_n627(x) + end +end + +def fun_l23_n400(x) + if (x < 1) + fun_l24_n941(x) + else + fun_l24_n679(x) + end +end + +def fun_l23_n401(x) + if (x < 1) + fun_l24_n161(x) + else + fun_l24_n518(x) + end +end + +def fun_l23_n402(x) + if (x < 1) + fun_l24_n738(x) + else + fun_l24_n393(x) + end +end + +def fun_l23_n403(x) + if (x < 1) + fun_l24_n75(x) + else + fun_l24_n776(x) + end +end + +def fun_l23_n404(x) + if (x < 1) + fun_l24_n996(x) + else + fun_l24_n71(x) + end +end + +def fun_l23_n405(x) + if (x < 1) + fun_l24_n732(x) + else + fun_l24_n649(x) + end +end + +def fun_l23_n406(x) + if (x < 1) + fun_l24_n142(x) + else + fun_l24_n563(x) + end +end + +def fun_l23_n407(x) + if (x < 1) + fun_l24_n63(x) + else + fun_l24_n629(x) + end +end + +def fun_l23_n408(x) + if (x < 1) + fun_l24_n734(x) + else + fun_l24_n857(x) + end +end + +def fun_l23_n409(x) + if (x < 1) + fun_l24_n100(x) + else + fun_l24_n340(x) + end +end + +def fun_l23_n410(x) + if (x < 1) + fun_l24_n471(x) + else + fun_l24_n114(x) + end +end + +def fun_l23_n411(x) + if (x < 1) + fun_l24_n316(x) + else + fun_l24_n965(x) + end +end + +def fun_l23_n412(x) + if (x < 1) + fun_l24_n909(x) + else + fun_l24_n779(x) + end +end + +def fun_l23_n413(x) + if (x < 1) + fun_l24_n846(x) + else + fun_l24_n473(x) + end +end + +def fun_l23_n414(x) + if (x < 1) + fun_l24_n117(x) + else + fun_l24_n751(x) + end +end + +def fun_l23_n415(x) + if (x < 1) + fun_l24_n360(x) + else + fun_l24_n285(x) + end +end + +def fun_l23_n416(x) + if (x < 1) + fun_l24_n430(x) + else + fun_l24_n273(x) + end +end + +def fun_l23_n417(x) + if (x < 1) + fun_l24_n925(x) + else + fun_l24_n928(x) + end +end + +def fun_l23_n418(x) + if (x < 1) + fun_l24_n478(x) + else + fun_l24_n511(x) + end +end + +def fun_l23_n419(x) + if (x < 1) + fun_l24_n415(x) + else + fun_l24_n127(x) + end +end + +def fun_l23_n420(x) + if (x < 1) + fun_l24_n33(x) + else + fun_l24_n897(x) + end +end + +def fun_l23_n421(x) + if (x < 1) + fun_l24_n112(x) + else + fun_l24_n87(x) + end +end + +def fun_l23_n422(x) + if (x < 1) + fun_l24_n386(x) + else + fun_l24_n450(x) + end +end + +def fun_l23_n423(x) + if (x < 1) + fun_l24_n430(x) + else + fun_l24_n517(x) + end +end + +def fun_l23_n424(x) + if (x < 1) + fun_l24_n413(x) + else + fun_l24_n799(x) + end +end + +def fun_l23_n425(x) + if (x < 1) + fun_l24_n744(x) + else + fun_l24_n218(x) + end +end + +def fun_l23_n426(x) + if (x < 1) + fun_l24_n231(x) + else + fun_l24_n454(x) + end +end + +def fun_l23_n427(x) + if (x < 1) + fun_l24_n693(x) + else + fun_l24_n28(x) + end +end + +def fun_l23_n428(x) + if (x < 1) + fun_l24_n694(x) + else + fun_l24_n712(x) + end +end + +def fun_l23_n429(x) + if (x < 1) + fun_l24_n949(x) + else + fun_l24_n983(x) + end +end + +def fun_l23_n430(x) + if (x < 1) + fun_l24_n324(x) + else + fun_l24_n818(x) + end +end + +def fun_l23_n431(x) + if (x < 1) + fun_l24_n820(x) + else + fun_l24_n662(x) + end +end + +def fun_l23_n432(x) + if (x < 1) + fun_l24_n391(x) + else + fun_l24_n801(x) + end +end + +def fun_l23_n433(x) + if (x < 1) + fun_l24_n285(x) + else + fun_l24_n79(x) + end +end + +def fun_l23_n434(x) + if (x < 1) + fun_l24_n582(x) + else + fun_l24_n820(x) + end +end + +def fun_l23_n435(x) + if (x < 1) + fun_l24_n324(x) + else + fun_l24_n348(x) + end +end + +def fun_l23_n436(x) + if (x < 1) + fun_l24_n241(x) + else + fun_l24_n568(x) + end +end + +def fun_l23_n437(x) + if (x < 1) + fun_l24_n261(x) + else + fun_l24_n374(x) + end +end + +def fun_l23_n438(x) + if (x < 1) + fun_l24_n886(x) + else + fun_l24_n38(x) + end +end + +def fun_l23_n439(x) + if (x < 1) + fun_l24_n344(x) + else + fun_l24_n991(x) + end +end + +def fun_l23_n440(x) + if (x < 1) + fun_l24_n792(x) + else + fun_l24_n298(x) + end +end + +def fun_l23_n441(x) + if (x < 1) + fun_l24_n728(x) + else + fun_l24_n575(x) + end +end + +def fun_l23_n442(x) + if (x < 1) + fun_l24_n22(x) + else + fun_l24_n804(x) + end +end + +def fun_l23_n443(x) + if (x < 1) + fun_l24_n406(x) + else + fun_l24_n723(x) + end +end + +def fun_l23_n444(x) + if (x < 1) + fun_l24_n921(x) + else + fun_l24_n455(x) + end +end + +def fun_l23_n445(x) + if (x < 1) + fun_l24_n725(x) + else + fun_l24_n799(x) + end +end + +def fun_l23_n446(x) + if (x < 1) + fun_l24_n543(x) + else + fun_l24_n350(x) + end +end + +def fun_l23_n447(x) + if (x < 1) + fun_l24_n849(x) + else + fun_l24_n447(x) + end +end + +def fun_l23_n448(x) + if (x < 1) + fun_l24_n357(x) + else + fun_l24_n915(x) + end +end + +def fun_l23_n449(x) + if (x < 1) + fun_l24_n143(x) + else + fun_l24_n164(x) + end +end + +def fun_l23_n450(x) + if (x < 1) + fun_l24_n702(x) + else + fun_l24_n940(x) + end +end + +def fun_l23_n451(x) + if (x < 1) + fun_l24_n76(x) + else + fun_l24_n229(x) + end +end + +def fun_l23_n452(x) + if (x < 1) + fun_l24_n55(x) + else + fun_l24_n177(x) + end +end + +def fun_l23_n453(x) + if (x < 1) + fun_l24_n65(x) + else + fun_l24_n310(x) + end +end + +def fun_l23_n454(x) + if (x < 1) + fun_l24_n818(x) + else + fun_l24_n1(x) + end +end + +def fun_l23_n455(x) + if (x < 1) + fun_l24_n555(x) + else + fun_l24_n475(x) + end +end + +def fun_l23_n456(x) + if (x < 1) + fun_l24_n867(x) + else + fun_l24_n350(x) + end +end + +def fun_l23_n457(x) + if (x < 1) + fun_l24_n953(x) + else + fun_l24_n932(x) + end +end + +def fun_l23_n458(x) + if (x < 1) + fun_l24_n104(x) + else + fun_l24_n555(x) + end +end + +def fun_l23_n459(x) + if (x < 1) + fun_l24_n259(x) + else + fun_l24_n196(x) + end +end + +def fun_l23_n460(x) + if (x < 1) + fun_l24_n747(x) + else + fun_l24_n788(x) + end +end + +def fun_l23_n461(x) + if (x < 1) + fun_l24_n302(x) + else + fun_l24_n479(x) + end +end + +def fun_l23_n462(x) + if (x < 1) + fun_l24_n292(x) + else + fun_l24_n235(x) + end +end + +def fun_l23_n463(x) + if (x < 1) + fun_l24_n589(x) + else + fun_l24_n277(x) + end +end + +def fun_l23_n464(x) + if (x < 1) + fun_l24_n212(x) + else + fun_l24_n334(x) + end +end + +def fun_l23_n465(x) + if (x < 1) + fun_l24_n878(x) + else + fun_l24_n111(x) + end +end + +def fun_l23_n466(x) + if (x < 1) + fun_l24_n862(x) + else + fun_l24_n736(x) + end +end + +def fun_l23_n467(x) + if (x < 1) + fun_l24_n257(x) + else + fun_l24_n745(x) + end +end + +def fun_l23_n468(x) + if (x < 1) + fun_l24_n922(x) + else + fun_l24_n453(x) + end +end + +def fun_l23_n469(x) + if (x < 1) + fun_l24_n334(x) + else + fun_l24_n23(x) + end +end + +def fun_l23_n470(x) + if (x < 1) + fun_l24_n585(x) + else + fun_l24_n512(x) + end +end + +def fun_l23_n471(x) + if (x < 1) + fun_l24_n135(x) + else + fun_l24_n244(x) + end +end + +def fun_l23_n472(x) + if (x < 1) + fun_l24_n151(x) + else + fun_l24_n479(x) + end +end + +def fun_l23_n473(x) + if (x < 1) + fun_l24_n192(x) + else + fun_l24_n748(x) + end +end + +def fun_l23_n474(x) + if (x < 1) + fun_l24_n729(x) + else + fun_l24_n283(x) + end +end + +def fun_l23_n475(x) + if (x < 1) + fun_l24_n453(x) + else + fun_l24_n244(x) + end +end + +def fun_l23_n476(x) + if (x < 1) + fun_l24_n210(x) + else + fun_l24_n6(x) + end +end + +def fun_l23_n477(x) + if (x < 1) + fun_l24_n387(x) + else + fun_l24_n857(x) + end +end + +def fun_l23_n478(x) + if (x < 1) + fun_l24_n312(x) + else + fun_l24_n378(x) + end +end + +def fun_l23_n479(x) + if (x < 1) + fun_l24_n553(x) + else + fun_l24_n264(x) + end +end + +def fun_l23_n480(x) + if (x < 1) + fun_l24_n903(x) + else + fun_l24_n374(x) + end +end + +def fun_l23_n481(x) + if (x < 1) + fun_l24_n9(x) + else + fun_l24_n494(x) + end +end + +def fun_l23_n482(x) + if (x < 1) + fun_l24_n4(x) + else + fun_l24_n119(x) + end +end + +def fun_l23_n483(x) + if (x < 1) + fun_l24_n969(x) + else + fun_l24_n716(x) + end +end + +def fun_l23_n484(x) + if (x < 1) + fun_l24_n132(x) + else + fun_l24_n950(x) + end +end + +def fun_l23_n485(x) + if (x < 1) + fun_l24_n641(x) + else + fun_l24_n134(x) + end +end + +def fun_l23_n486(x) + if (x < 1) + fun_l24_n499(x) + else + fun_l24_n506(x) + end +end + +def fun_l23_n487(x) + if (x < 1) + fun_l24_n594(x) + else + fun_l24_n508(x) + end +end + +def fun_l23_n488(x) + if (x < 1) + fun_l24_n730(x) + else + fun_l24_n464(x) + end +end + +def fun_l23_n489(x) + if (x < 1) + fun_l24_n564(x) + else + fun_l24_n716(x) + end +end + +def fun_l23_n490(x) + if (x < 1) + fun_l24_n658(x) + else + fun_l24_n63(x) + end +end + +def fun_l23_n491(x) + if (x < 1) + fun_l24_n404(x) + else + fun_l24_n982(x) + end +end + +def fun_l23_n492(x) + if (x < 1) + fun_l24_n182(x) + else + fun_l24_n97(x) + end +end + +def fun_l23_n493(x) + if (x < 1) + fun_l24_n97(x) + else + fun_l24_n765(x) + end +end + +def fun_l23_n494(x) + if (x < 1) + fun_l24_n728(x) + else + fun_l24_n703(x) + end +end + +def fun_l23_n495(x) + if (x < 1) + fun_l24_n327(x) + else + fun_l24_n484(x) + end +end + +def fun_l23_n496(x) + if (x < 1) + fun_l24_n544(x) + else + fun_l24_n814(x) + end +end + +def fun_l23_n497(x) + if (x < 1) + fun_l24_n555(x) + else + fun_l24_n160(x) + end +end + +def fun_l23_n498(x) + if (x < 1) + fun_l24_n336(x) + else + fun_l24_n544(x) + end +end + +def fun_l23_n499(x) + if (x < 1) + fun_l24_n242(x) + else + fun_l24_n337(x) + end +end + +def fun_l23_n500(x) + if (x < 1) + fun_l24_n71(x) + else + fun_l24_n446(x) + end +end + +def fun_l23_n501(x) + if (x < 1) + fun_l24_n726(x) + else + fun_l24_n127(x) + end +end + +def fun_l23_n502(x) + if (x < 1) + fun_l24_n430(x) + else + fun_l24_n136(x) + end +end + +def fun_l23_n503(x) + if (x < 1) + fun_l24_n140(x) + else + fun_l24_n942(x) + end +end + +def fun_l23_n504(x) + if (x < 1) + fun_l24_n135(x) + else + fun_l24_n701(x) + end +end + +def fun_l23_n505(x) + if (x < 1) + fun_l24_n409(x) + else + fun_l24_n825(x) + end +end + +def fun_l23_n506(x) + if (x < 1) + fun_l24_n415(x) + else + fun_l24_n336(x) + end +end + +def fun_l23_n507(x) + if (x < 1) + fun_l24_n118(x) + else + fun_l24_n904(x) + end +end + +def fun_l23_n508(x) + if (x < 1) + fun_l24_n870(x) + else + fun_l24_n473(x) + end +end + +def fun_l23_n509(x) + if (x < 1) + fun_l24_n99(x) + else + fun_l24_n157(x) + end +end + +def fun_l23_n510(x) + if (x < 1) + fun_l24_n484(x) + else + fun_l24_n933(x) + end +end + +def fun_l23_n511(x) + if (x < 1) + fun_l24_n204(x) + else + fun_l24_n95(x) + end +end + +def fun_l23_n512(x) + if (x < 1) + fun_l24_n783(x) + else + fun_l24_n490(x) + end +end + +def fun_l23_n513(x) + if (x < 1) + fun_l24_n642(x) + else + fun_l24_n622(x) + end +end + +def fun_l23_n514(x) + if (x < 1) + fun_l24_n514(x) + else + fun_l24_n287(x) + end +end + +def fun_l23_n515(x) + if (x < 1) + fun_l24_n174(x) + else + fun_l24_n19(x) + end +end + +def fun_l23_n516(x) + if (x < 1) + fun_l24_n840(x) + else + fun_l24_n710(x) + end +end + +def fun_l23_n517(x) + if (x < 1) + fun_l24_n921(x) + else + fun_l24_n11(x) + end +end + +def fun_l23_n518(x) + if (x < 1) + fun_l24_n162(x) + else + fun_l24_n185(x) + end +end + +def fun_l23_n519(x) + if (x < 1) + fun_l24_n654(x) + else + fun_l24_n514(x) + end +end + +def fun_l23_n520(x) + if (x < 1) + fun_l24_n763(x) + else + fun_l24_n158(x) + end +end + +def fun_l23_n521(x) + if (x < 1) + fun_l24_n471(x) + else + fun_l24_n617(x) + end +end + +def fun_l23_n522(x) + if (x < 1) + fun_l24_n146(x) + else + fun_l24_n6(x) + end +end + +def fun_l23_n523(x) + if (x < 1) + fun_l24_n447(x) + else + fun_l24_n981(x) + end +end + +def fun_l23_n524(x) + if (x < 1) + fun_l24_n809(x) + else + fun_l24_n78(x) + end +end + +def fun_l23_n525(x) + if (x < 1) + fun_l24_n554(x) + else + fun_l24_n50(x) + end +end + +def fun_l23_n526(x) + if (x < 1) + fun_l24_n970(x) + else + fun_l24_n600(x) + end +end + +def fun_l23_n527(x) + if (x < 1) + fun_l24_n700(x) + else + fun_l24_n982(x) + end +end + +def fun_l23_n528(x) + if (x < 1) + fun_l24_n947(x) + else + fun_l24_n886(x) + end +end + +def fun_l23_n529(x) + if (x < 1) + fun_l24_n198(x) + else + fun_l24_n283(x) + end +end + +def fun_l23_n530(x) + if (x < 1) + fun_l24_n641(x) + else + fun_l24_n879(x) + end +end + +def fun_l23_n531(x) + if (x < 1) + fun_l24_n393(x) + else + fun_l24_n451(x) + end +end + +def fun_l23_n532(x) + if (x < 1) + fun_l24_n802(x) + else + fun_l24_n271(x) + end +end + +def fun_l23_n533(x) + if (x < 1) + fun_l24_n926(x) + else + fun_l24_n315(x) + end +end + +def fun_l23_n534(x) + if (x < 1) + fun_l24_n544(x) + else + fun_l24_n358(x) + end +end + +def fun_l23_n535(x) + if (x < 1) + fun_l24_n456(x) + else + fun_l24_n569(x) + end +end + +def fun_l23_n536(x) + if (x < 1) + fun_l24_n235(x) + else + fun_l24_n182(x) + end +end + +def fun_l23_n537(x) + if (x < 1) + fun_l24_n159(x) + else + fun_l24_n674(x) + end +end + +def fun_l23_n538(x) + if (x < 1) + fun_l24_n956(x) + else + fun_l24_n145(x) + end +end + +def fun_l23_n539(x) + if (x < 1) + fun_l24_n294(x) + else + fun_l24_n910(x) + end +end + +def fun_l23_n540(x) + if (x < 1) + fun_l24_n434(x) + else + fun_l24_n336(x) + end +end + +def fun_l23_n541(x) + if (x < 1) + fun_l24_n635(x) + else + fun_l24_n182(x) + end +end + +def fun_l23_n542(x) + if (x < 1) + fun_l24_n418(x) + else + fun_l24_n828(x) + end +end + +def fun_l23_n543(x) + if (x < 1) + fun_l24_n337(x) + else + fun_l24_n740(x) + end +end + +def fun_l23_n544(x) + if (x < 1) + fun_l24_n893(x) + else + fun_l24_n402(x) + end +end + +def fun_l23_n545(x) + if (x < 1) + fun_l24_n407(x) + else + fun_l24_n124(x) + end +end + +def fun_l23_n546(x) + if (x < 1) + fun_l24_n170(x) + else + fun_l24_n64(x) + end +end + +def fun_l23_n547(x) + if (x < 1) + fun_l24_n936(x) + else + fun_l24_n876(x) + end +end + +def fun_l23_n548(x) + if (x < 1) + fun_l24_n387(x) + else + fun_l24_n655(x) + end +end + +def fun_l23_n549(x) + if (x < 1) + fun_l24_n162(x) + else + fun_l24_n210(x) + end +end + +def fun_l23_n550(x) + if (x < 1) + fun_l24_n454(x) + else + fun_l24_n695(x) + end +end + +def fun_l23_n551(x) + if (x < 1) + fun_l24_n410(x) + else + fun_l24_n529(x) + end +end + +def fun_l23_n552(x) + if (x < 1) + fun_l24_n726(x) + else + fun_l24_n450(x) + end +end + +def fun_l23_n553(x) + if (x < 1) + fun_l24_n39(x) + else + fun_l24_n37(x) + end +end + +def fun_l23_n554(x) + if (x < 1) + fun_l24_n994(x) + else + fun_l24_n106(x) + end +end + +def fun_l23_n555(x) + if (x < 1) + fun_l24_n929(x) + else + fun_l24_n766(x) + end +end + +def fun_l23_n556(x) + if (x < 1) + fun_l24_n531(x) + else + fun_l24_n502(x) + end +end + +def fun_l23_n557(x) + if (x < 1) + fun_l24_n890(x) + else + fun_l24_n919(x) + end +end + +def fun_l23_n558(x) + if (x < 1) + fun_l24_n803(x) + else + fun_l24_n460(x) + end +end + +def fun_l23_n559(x) + if (x < 1) + fun_l24_n5(x) + else + fun_l24_n464(x) + end +end + +def fun_l23_n560(x) + if (x < 1) + fun_l24_n506(x) + else + fun_l24_n891(x) + end +end + +def fun_l23_n561(x) + if (x < 1) + fun_l24_n98(x) + else + fun_l24_n534(x) + end +end + +def fun_l23_n562(x) + if (x < 1) + fun_l24_n130(x) + else + fun_l24_n54(x) + end +end + +def fun_l23_n563(x) + if (x < 1) + fun_l24_n881(x) + else + fun_l24_n699(x) + end +end + +def fun_l23_n564(x) + if (x < 1) + fun_l24_n192(x) + else + fun_l24_n112(x) + end +end + +def fun_l23_n565(x) + if (x < 1) + fun_l24_n249(x) + else + fun_l24_n796(x) + end +end + +def fun_l23_n566(x) + if (x < 1) + fun_l24_n113(x) + else + fun_l24_n599(x) + end +end + +def fun_l23_n567(x) + if (x < 1) + fun_l24_n334(x) + else + fun_l24_n80(x) + end +end + +def fun_l23_n568(x) + if (x < 1) + fun_l24_n347(x) + else + fun_l24_n726(x) + end +end + +def fun_l23_n569(x) + if (x < 1) + fun_l24_n60(x) + else + fun_l24_n249(x) + end +end + +def fun_l23_n570(x) + if (x < 1) + fun_l24_n400(x) + else + fun_l24_n773(x) + end +end + +def fun_l23_n571(x) + if (x < 1) + fun_l24_n172(x) + else + fun_l24_n787(x) + end +end + +def fun_l23_n572(x) + if (x < 1) + fun_l24_n973(x) + else + fun_l24_n875(x) + end +end + +def fun_l23_n573(x) + if (x < 1) + fun_l24_n290(x) + else + fun_l24_n225(x) + end +end + +def fun_l23_n574(x) + if (x < 1) + fun_l24_n383(x) + else + fun_l24_n714(x) + end +end + +def fun_l23_n575(x) + if (x < 1) + fun_l24_n32(x) + else + fun_l24_n508(x) + end +end + +def fun_l23_n576(x) + if (x < 1) + fun_l24_n74(x) + else + fun_l24_n368(x) + end +end + +def fun_l23_n577(x) + if (x < 1) + fun_l24_n431(x) + else + fun_l24_n2(x) + end +end + +def fun_l23_n578(x) + if (x < 1) + fun_l24_n758(x) + else + fun_l24_n178(x) + end +end + +def fun_l23_n579(x) + if (x < 1) + fun_l24_n130(x) + else + fun_l24_n512(x) + end +end + +def fun_l23_n580(x) + if (x < 1) + fun_l24_n790(x) + else + fun_l24_n280(x) + end +end + +def fun_l23_n581(x) + if (x < 1) + fun_l24_n76(x) + else + fun_l24_n596(x) + end +end + +def fun_l23_n582(x) + if (x < 1) + fun_l24_n643(x) + else + fun_l24_n506(x) + end +end + +def fun_l23_n583(x) + if (x < 1) + fun_l24_n392(x) + else + fun_l24_n671(x) + end +end + +def fun_l23_n584(x) + if (x < 1) + fun_l24_n722(x) + else + fun_l24_n390(x) + end +end + +def fun_l23_n585(x) + if (x < 1) + fun_l24_n613(x) + else + fun_l24_n461(x) + end +end + +def fun_l23_n586(x) + if (x < 1) + fun_l24_n784(x) + else + fun_l24_n426(x) + end +end + +def fun_l23_n587(x) + if (x < 1) + fun_l24_n351(x) + else + fun_l24_n68(x) + end +end + +def fun_l23_n588(x) + if (x < 1) + fun_l24_n8(x) + else + fun_l24_n9(x) + end +end + +def fun_l23_n589(x) + if (x < 1) + fun_l24_n984(x) + else + fun_l24_n704(x) + end +end + +def fun_l23_n590(x) + if (x < 1) + fun_l24_n150(x) + else + fun_l24_n36(x) + end +end + +def fun_l23_n591(x) + if (x < 1) + fun_l24_n232(x) + else + fun_l24_n293(x) + end +end + +def fun_l23_n592(x) + if (x < 1) + fun_l24_n763(x) + else + fun_l24_n444(x) + end +end + +def fun_l23_n593(x) + if (x < 1) + fun_l24_n246(x) + else + fun_l24_n101(x) + end +end + +def fun_l23_n594(x) + if (x < 1) + fun_l24_n145(x) + else + fun_l24_n626(x) + end +end + +def fun_l23_n595(x) + if (x < 1) + fun_l24_n835(x) + else + fun_l24_n827(x) + end +end + +def fun_l23_n596(x) + if (x < 1) + fun_l24_n925(x) + else + fun_l24_n875(x) + end +end + +def fun_l23_n597(x) + if (x < 1) + fun_l24_n600(x) + else + fun_l24_n817(x) + end +end + +def fun_l23_n598(x) + if (x < 1) + fun_l24_n653(x) + else + fun_l24_n632(x) + end +end + +def fun_l23_n599(x) + if (x < 1) + fun_l24_n103(x) + else + fun_l24_n675(x) + end +end + +def fun_l23_n600(x) + if (x < 1) + fun_l24_n1(x) + else + fun_l24_n899(x) + end +end + +def fun_l23_n601(x) + if (x < 1) + fun_l24_n357(x) + else + fun_l24_n88(x) + end +end + +def fun_l23_n602(x) + if (x < 1) + fun_l24_n213(x) + else + fun_l24_n71(x) + end +end + +def fun_l23_n603(x) + if (x < 1) + fun_l24_n299(x) + else + fun_l24_n283(x) + end +end + +def fun_l23_n604(x) + if (x < 1) + fun_l24_n647(x) + else + fun_l24_n891(x) + end +end + +def fun_l23_n605(x) + if (x < 1) + fun_l24_n86(x) + else + fun_l24_n581(x) + end +end + +def fun_l23_n606(x) + if (x < 1) + fun_l24_n749(x) + else + fun_l24_n780(x) + end +end + +def fun_l23_n607(x) + if (x < 1) + fun_l24_n537(x) + else + fun_l24_n22(x) + end +end + +def fun_l23_n608(x) + if (x < 1) + fun_l24_n535(x) + else + fun_l24_n379(x) + end +end + +def fun_l23_n609(x) + if (x < 1) + fun_l24_n860(x) + else + fun_l24_n220(x) + end +end + +def fun_l23_n610(x) + if (x < 1) + fun_l24_n366(x) + else + fun_l24_n216(x) + end +end + +def fun_l23_n611(x) + if (x < 1) + fun_l24_n79(x) + else + fun_l24_n506(x) + end +end + +def fun_l23_n612(x) + if (x < 1) + fun_l24_n600(x) + else + fun_l24_n367(x) + end +end + +def fun_l23_n613(x) + if (x < 1) + fun_l24_n764(x) + else + fun_l24_n167(x) + end +end + +def fun_l23_n614(x) + if (x < 1) + fun_l24_n113(x) + else + fun_l24_n398(x) + end +end + +def fun_l23_n615(x) + if (x < 1) + fun_l24_n292(x) + else + fun_l24_n1(x) + end +end + +def fun_l23_n616(x) + if (x < 1) + fun_l24_n523(x) + else + fun_l24_n344(x) + end +end + +def fun_l23_n617(x) + if (x < 1) + fun_l24_n60(x) + else + fun_l24_n618(x) + end +end + +def fun_l23_n618(x) + if (x < 1) + fun_l24_n252(x) + else + fun_l24_n718(x) + end +end + +def fun_l23_n619(x) + if (x < 1) + fun_l24_n962(x) + else + fun_l24_n69(x) + end +end + +def fun_l23_n620(x) + if (x < 1) + fun_l24_n10(x) + else + fun_l24_n87(x) + end +end + +def fun_l23_n621(x) + if (x < 1) + fun_l24_n128(x) + else + fun_l24_n958(x) + end +end + +def fun_l23_n622(x) + if (x < 1) + fun_l24_n775(x) + else + fun_l24_n205(x) + end +end + +def fun_l23_n623(x) + if (x < 1) + fun_l24_n121(x) + else + fun_l24_n69(x) + end +end + +def fun_l23_n624(x) + if (x < 1) + fun_l24_n768(x) + else + fun_l24_n439(x) + end +end + +def fun_l23_n625(x) + if (x < 1) + fun_l24_n332(x) + else + fun_l24_n73(x) + end +end + +def fun_l23_n626(x) + if (x < 1) + fun_l24_n735(x) + else + fun_l24_n651(x) + end +end + +def fun_l23_n627(x) + if (x < 1) + fun_l24_n661(x) + else + fun_l24_n827(x) + end +end + +def fun_l23_n628(x) + if (x < 1) + fun_l24_n607(x) + else + fun_l24_n343(x) + end +end + +def fun_l23_n629(x) + if (x < 1) + fun_l24_n868(x) + else + fun_l24_n633(x) + end +end + +def fun_l23_n630(x) + if (x < 1) + fun_l24_n321(x) + else + fun_l24_n44(x) + end +end + +def fun_l23_n631(x) + if (x < 1) + fun_l24_n840(x) + else + fun_l24_n265(x) + end +end + +def fun_l23_n632(x) + if (x < 1) + fun_l24_n710(x) + else + fun_l24_n343(x) + end +end + +def fun_l23_n633(x) + if (x < 1) + fun_l24_n640(x) + else + fun_l24_n112(x) + end +end + +def fun_l23_n634(x) + if (x < 1) + fun_l24_n237(x) + else + fun_l24_n83(x) + end +end + +def fun_l23_n635(x) + if (x < 1) + fun_l24_n235(x) + else + fun_l24_n970(x) + end +end + +def fun_l23_n636(x) + if (x < 1) + fun_l24_n576(x) + else + fun_l24_n891(x) + end +end + +def fun_l23_n637(x) + if (x < 1) + fun_l24_n489(x) + else + fun_l24_n136(x) + end +end + +def fun_l23_n638(x) + if (x < 1) + fun_l24_n532(x) + else + fun_l24_n150(x) + end +end + +def fun_l23_n639(x) + if (x < 1) + fun_l24_n496(x) + else + fun_l24_n57(x) + end +end + +def fun_l23_n640(x) + if (x < 1) + fun_l24_n857(x) + else + fun_l24_n564(x) + end +end + +def fun_l23_n641(x) + if (x < 1) + fun_l24_n203(x) + else + fun_l24_n730(x) + end +end + +def fun_l23_n642(x) + if (x < 1) + fun_l24_n38(x) + else + fun_l24_n388(x) + end +end + +def fun_l23_n643(x) + if (x < 1) + fun_l24_n650(x) + else + fun_l24_n672(x) + end +end + +def fun_l23_n644(x) + if (x < 1) + fun_l24_n842(x) + else + fun_l24_n473(x) + end +end + +def fun_l23_n645(x) + if (x < 1) + fun_l24_n650(x) + else + fun_l24_n36(x) + end +end + +def fun_l23_n646(x) + if (x < 1) + fun_l24_n25(x) + else + fun_l24_n696(x) + end +end + +def fun_l23_n647(x) + if (x < 1) + fun_l24_n24(x) + else + fun_l24_n414(x) + end +end + +def fun_l23_n648(x) + if (x < 1) + fun_l24_n778(x) + else + fun_l24_n794(x) + end +end + +def fun_l23_n649(x) + if (x < 1) + fun_l24_n132(x) + else + fun_l24_n833(x) + end +end + +def fun_l23_n650(x) + if (x < 1) + fun_l24_n718(x) + else + fun_l24_n327(x) + end +end + +def fun_l23_n651(x) + if (x < 1) + fun_l24_n969(x) + else + fun_l24_n865(x) + end +end + +def fun_l23_n652(x) + if (x < 1) + fun_l24_n904(x) + else + fun_l24_n4(x) + end +end + +def fun_l23_n653(x) + if (x < 1) + fun_l24_n342(x) + else + fun_l24_n953(x) + end +end + +def fun_l23_n654(x) + if (x < 1) + fun_l24_n393(x) + else + fun_l24_n175(x) + end +end + +def fun_l23_n655(x) + if (x < 1) + fun_l24_n241(x) + else + fun_l24_n835(x) + end +end + +def fun_l23_n656(x) + if (x < 1) + fun_l24_n326(x) + else + fun_l24_n294(x) + end +end + +def fun_l23_n657(x) + if (x < 1) + fun_l24_n8(x) + else + fun_l24_n327(x) + end +end + +def fun_l23_n658(x) + if (x < 1) + fun_l24_n859(x) + else + fun_l24_n138(x) + end +end + +def fun_l23_n659(x) + if (x < 1) + fun_l24_n389(x) + else + fun_l24_n840(x) + end +end + +def fun_l23_n660(x) + if (x < 1) + fun_l24_n171(x) + else + fun_l24_n731(x) + end +end + +def fun_l23_n661(x) + if (x < 1) + fun_l24_n284(x) + else + fun_l24_n358(x) + end +end + +def fun_l23_n662(x) + if (x < 1) + fun_l24_n329(x) + else + fun_l24_n459(x) + end +end + +def fun_l23_n663(x) + if (x < 1) + fun_l24_n6(x) + else + fun_l24_n29(x) + end +end + +def fun_l23_n664(x) + if (x < 1) + fun_l24_n324(x) + else + fun_l24_n58(x) + end +end + +def fun_l23_n665(x) + if (x < 1) + fun_l24_n473(x) + else + fun_l24_n932(x) + end +end + +def fun_l23_n666(x) + if (x < 1) + fun_l24_n425(x) + else + fun_l24_n49(x) + end +end + +def fun_l23_n667(x) + if (x < 1) + fun_l24_n122(x) + else + fun_l24_n515(x) + end +end + +def fun_l23_n668(x) + if (x < 1) + fun_l24_n883(x) + else + fun_l24_n383(x) + end +end + +def fun_l23_n669(x) + if (x < 1) + fun_l24_n316(x) + else + fun_l24_n456(x) + end +end + +def fun_l23_n670(x) + if (x < 1) + fun_l24_n812(x) + else + fun_l24_n625(x) + end +end + +def fun_l23_n671(x) + if (x < 1) + fun_l24_n431(x) + else + fun_l24_n685(x) + end +end + +def fun_l23_n672(x) + if (x < 1) + fun_l24_n68(x) + else + fun_l24_n112(x) + end +end + +def fun_l23_n673(x) + if (x < 1) + fun_l24_n137(x) + else + fun_l24_n349(x) + end +end + +def fun_l23_n674(x) + if (x < 1) + fun_l24_n629(x) + else + fun_l24_n165(x) + end +end + +def fun_l23_n675(x) + if (x < 1) + fun_l24_n484(x) + else + fun_l24_n102(x) + end +end + +def fun_l23_n676(x) + if (x < 1) + fun_l24_n641(x) + else + fun_l24_n912(x) + end +end + +def fun_l23_n677(x) + if (x < 1) + fun_l24_n817(x) + else + fun_l24_n975(x) + end +end + +def fun_l23_n678(x) + if (x < 1) + fun_l24_n510(x) + else + fun_l24_n346(x) + end +end + +def fun_l23_n679(x) + if (x < 1) + fun_l24_n129(x) + else + fun_l24_n602(x) + end +end + +def fun_l23_n680(x) + if (x < 1) + fun_l24_n991(x) + else + fun_l24_n406(x) + end +end + +def fun_l23_n681(x) + if (x < 1) + fun_l24_n433(x) + else + fun_l24_n998(x) + end +end + +def fun_l23_n682(x) + if (x < 1) + fun_l24_n645(x) + else + fun_l24_n275(x) + end +end + +def fun_l23_n683(x) + if (x < 1) + fun_l24_n832(x) + else + fun_l24_n346(x) + end +end + +def fun_l23_n684(x) + if (x < 1) + fun_l24_n769(x) + else + fun_l24_n927(x) + end +end + +def fun_l23_n685(x) + if (x < 1) + fun_l24_n389(x) + else + fun_l24_n777(x) + end +end + +def fun_l23_n686(x) + if (x < 1) + fun_l24_n658(x) + else + fun_l24_n184(x) + end +end + +def fun_l23_n687(x) + if (x < 1) + fun_l24_n134(x) + else + fun_l24_n517(x) + end +end + +def fun_l23_n688(x) + if (x < 1) + fun_l24_n49(x) + else + fun_l24_n392(x) + end +end + +def fun_l23_n689(x) + if (x < 1) + fun_l24_n23(x) + else + fun_l24_n402(x) + end +end + +def fun_l23_n690(x) + if (x < 1) + fun_l24_n719(x) + else + fun_l24_n529(x) + end +end + +def fun_l23_n691(x) + if (x < 1) + fun_l24_n543(x) + else + fun_l24_n789(x) + end +end + +def fun_l23_n692(x) + if (x < 1) + fun_l24_n850(x) + else + fun_l24_n50(x) + end +end + +def fun_l23_n693(x) + if (x < 1) + fun_l24_n728(x) + else + fun_l24_n730(x) + end +end + +def fun_l23_n694(x) + if (x < 1) + fun_l24_n810(x) + else + fun_l24_n999(x) + end +end + +def fun_l23_n695(x) + if (x < 1) + fun_l24_n856(x) + else + fun_l24_n404(x) + end +end + +def fun_l23_n696(x) + if (x < 1) + fun_l24_n405(x) + else + fun_l24_n275(x) + end +end + +def fun_l23_n697(x) + if (x < 1) + fun_l24_n446(x) + else + fun_l24_n773(x) + end +end + +def fun_l23_n698(x) + if (x < 1) + fun_l24_n509(x) + else + fun_l24_n146(x) + end +end + +def fun_l23_n699(x) + if (x < 1) + fun_l24_n770(x) + else + fun_l24_n275(x) + end +end + +def fun_l23_n700(x) + if (x < 1) + fun_l24_n222(x) + else + fun_l24_n60(x) + end +end + +def fun_l23_n701(x) + if (x < 1) + fun_l24_n380(x) + else + fun_l24_n654(x) + end +end + +def fun_l23_n702(x) + if (x < 1) + fun_l24_n417(x) + else + fun_l24_n221(x) + end +end + +def fun_l23_n703(x) + if (x < 1) + fun_l24_n283(x) + else + fun_l24_n171(x) + end +end + +def fun_l23_n704(x) + if (x < 1) + fun_l24_n822(x) + else + fun_l24_n72(x) + end +end + +def fun_l23_n705(x) + if (x < 1) + fun_l24_n171(x) + else + fun_l24_n258(x) + end +end + +def fun_l23_n706(x) + if (x < 1) + fun_l24_n147(x) + else + fun_l24_n518(x) + end +end + +def fun_l23_n707(x) + if (x < 1) + fun_l24_n479(x) + else + fun_l24_n267(x) + end +end + +def fun_l23_n708(x) + if (x < 1) + fun_l24_n424(x) + else + fun_l24_n517(x) + end +end + +def fun_l23_n709(x) + if (x < 1) + fun_l24_n816(x) + else + fun_l24_n329(x) + end +end + +def fun_l23_n710(x) + if (x < 1) + fun_l24_n870(x) + else + fun_l24_n185(x) + end +end + +def fun_l23_n711(x) + if (x < 1) + fun_l24_n726(x) + else + fun_l24_n950(x) + end +end + +def fun_l23_n712(x) + if (x < 1) + fun_l24_n473(x) + else + fun_l24_n179(x) + end +end + +def fun_l23_n713(x) + if (x < 1) + fun_l24_n345(x) + else + fun_l24_n872(x) + end +end + +def fun_l23_n714(x) + if (x < 1) + fun_l24_n757(x) + else + fun_l24_n364(x) + end +end + +def fun_l23_n715(x) + if (x < 1) + fun_l24_n91(x) + else + fun_l24_n999(x) + end +end + +def fun_l23_n716(x) + if (x < 1) + fun_l24_n308(x) + else + fun_l24_n281(x) + end +end + +def fun_l23_n717(x) + if (x < 1) + fun_l24_n855(x) + else + fun_l24_n175(x) + end +end + +def fun_l23_n718(x) + if (x < 1) + fun_l24_n251(x) + else + fun_l24_n532(x) + end +end + +def fun_l23_n719(x) + if (x < 1) + fun_l24_n261(x) + else + fun_l24_n755(x) + end +end + +def fun_l23_n720(x) + if (x < 1) + fun_l24_n182(x) + else + fun_l24_n115(x) + end +end + +def fun_l23_n721(x) + if (x < 1) + fun_l24_n648(x) + else + fun_l24_n728(x) + end +end + +def fun_l23_n722(x) + if (x < 1) + fun_l24_n552(x) + else + fun_l24_n549(x) + end +end + +def fun_l23_n723(x) + if (x < 1) + fun_l24_n24(x) + else + fun_l24_n794(x) + end +end + +def fun_l23_n724(x) + if (x < 1) + fun_l24_n242(x) + else + fun_l24_n980(x) + end +end + +def fun_l23_n725(x) + if (x < 1) + fun_l24_n931(x) + else + fun_l24_n711(x) + end +end + +def fun_l23_n726(x) + if (x < 1) + fun_l24_n659(x) + else + fun_l24_n981(x) + end +end + +def fun_l23_n727(x) + if (x < 1) + fun_l24_n258(x) + else + fun_l24_n915(x) + end +end + +def fun_l23_n728(x) + if (x < 1) + fun_l24_n544(x) + else + fun_l24_n89(x) + end +end + +def fun_l23_n729(x) + if (x < 1) + fun_l24_n497(x) + else + fun_l24_n320(x) + end +end + +def fun_l23_n730(x) + if (x < 1) + fun_l24_n936(x) + else + fun_l24_n209(x) + end +end + +def fun_l23_n731(x) + if (x < 1) + fun_l24_n763(x) + else + fun_l24_n836(x) + end +end + +def fun_l23_n732(x) + if (x < 1) + fun_l24_n60(x) + else + fun_l24_n867(x) + end +end + +def fun_l23_n733(x) + if (x < 1) + fun_l24_n146(x) + else + fun_l24_n294(x) + end +end + +def fun_l23_n734(x) + if (x < 1) + fun_l24_n905(x) + else + fun_l24_n463(x) + end +end + +def fun_l23_n735(x) + if (x < 1) + fun_l24_n566(x) + else + fun_l24_n240(x) + end +end + +def fun_l23_n736(x) + if (x < 1) + fun_l24_n321(x) + else + fun_l24_n597(x) + end +end + +def fun_l23_n737(x) + if (x < 1) + fun_l24_n169(x) + else + fun_l24_n201(x) + end +end + +def fun_l23_n738(x) + if (x < 1) + fun_l24_n157(x) + else + fun_l24_n349(x) + end +end + +def fun_l23_n739(x) + if (x < 1) + fun_l24_n503(x) + else + fun_l24_n342(x) + end +end + +def fun_l23_n740(x) + if (x < 1) + fun_l24_n974(x) + else + fun_l24_n467(x) + end +end + +def fun_l23_n741(x) + if (x < 1) + fun_l24_n566(x) + else + fun_l24_n162(x) + end +end + +def fun_l23_n742(x) + if (x < 1) + fun_l24_n19(x) + else + fun_l24_n750(x) + end +end + +def fun_l23_n743(x) + if (x < 1) + fun_l24_n409(x) + else + fun_l24_n362(x) + end +end + +def fun_l23_n744(x) + if (x < 1) + fun_l24_n281(x) + else + fun_l24_n439(x) + end +end + +def fun_l23_n745(x) + if (x < 1) + fun_l24_n808(x) + else + fun_l24_n794(x) + end +end + +def fun_l23_n746(x) + if (x < 1) + fun_l24_n173(x) + else + fun_l24_n892(x) + end +end + +def fun_l23_n747(x) + if (x < 1) + fun_l24_n762(x) + else + fun_l24_n339(x) + end +end + +def fun_l23_n748(x) + if (x < 1) + fun_l24_n319(x) + else + fun_l24_n753(x) + end +end + +def fun_l23_n749(x) + if (x < 1) + fun_l24_n546(x) + else + fun_l24_n727(x) + end +end + +def fun_l23_n750(x) + if (x < 1) + fun_l24_n699(x) + else + fun_l24_n173(x) + end +end + +def fun_l23_n751(x) + if (x < 1) + fun_l24_n280(x) + else + fun_l24_n468(x) + end +end + +def fun_l23_n752(x) + if (x < 1) + fun_l24_n910(x) + else + fun_l24_n500(x) + end +end + +def fun_l23_n753(x) + if (x < 1) + fun_l24_n463(x) + else + fun_l24_n81(x) + end +end + +def fun_l23_n754(x) + if (x < 1) + fun_l24_n769(x) + else + fun_l24_n584(x) + end +end + +def fun_l23_n755(x) + if (x < 1) + fun_l24_n702(x) + else + fun_l24_n337(x) + end +end + +def fun_l23_n756(x) + if (x < 1) + fun_l24_n12(x) + else + fun_l24_n335(x) + end +end + +def fun_l23_n757(x) + if (x < 1) + fun_l24_n100(x) + else + fun_l24_n743(x) + end +end + +def fun_l23_n758(x) + if (x < 1) + fun_l24_n865(x) + else + fun_l24_n594(x) + end +end + +def fun_l23_n759(x) + if (x < 1) + fun_l24_n948(x) + else + fun_l24_n32(x) + end +end + +def fun_l23_n760(x) + if (x < 1) + fun_l24_n487(x) + else + fun_l24_n72(x) + end +end + +def fun_l23_n761(x) + if (x < 1) + fun_l24_n566(x) + else + fun_l24_n290(x) + end +end + +def fun_l23_n762(x) + if (x < 1) + fun_l24_n896(x) + else + fun_l24_n840(x) + end +end + +def fun_l23_n763(x) + if (x < 1) + fun_l24_n175(x) + else + fun_l24_n50(x) + end +end + +def fun_l23_n764(x) + if (x < 1) + fun_l24_n107(x) + else + fun_l24_n446(x) + end +end + +def fun_l23_n765(x) + if (x < 1) + fun_l24_n238(x) + else + fun_l24_n944(x) + end +end + +def fun_l23_n766(x) + if (x < 1) + fun_l24_n999(x) + else + fun_l24_n419(x) + end +end + +def fun_l23_n767(x) + if (x < 1) + fun_l24_n476(x) + else + fun_l24_n976(x) + end +end + +def fun_l23_n768(x) + if (x < 1) + fun_l24_n328(x) + else + fun_l24_n782(x) + end +end + +def fun_l23_n769(x) + if (x < 1) + fun_l24_n875(x) + else + fun_l24_n847(x) + end +end + +def fun_l23_n770(x) + if (x < 1) + fun_l24_n391(x) + else + fun_l24_n123(x) + end +end + +def fun_l23_n771(x) + if (x < 1) + fun_l24_n968(x) + else + fun_l24_n915(x) + end +end + +def fun_l23_n772(x) + if (x < 1) + fun_l24_n883(x) + else + fun_l24_n604(x) + end +end + +def fun_l23_n773(x) + if (x < 1) + fun_l24_n307(x) + else + fun_l24_n70(x) + end +end + +def fun_l23_n774(x) + if (x < 1) + fun_l24_n615(x) + else + fun_l24_n115(x) + end +end + +def fun_l23_n775(x) + if (x < 1) + fun_l24_n250(x) + else + fun_l24_n178(x) + end +end + +def fun_l23_n776(x) + if (x < 1) + fun_l24_n982(x) + else + fun_l24_n570(x) + end +end + +def fun_l23_n777(x) + if (x < 1) + fun_l24_n317(x) + else + fun_l24_n170(x) + end +end + +def fun_l23_n778(x) + if (x < 1) + fun_l24_n895(x) + else + fun_l24_n147(x) + end +end + +def fun_l23_n779(x) + if (x < 1) + fun_l24_n393(x) + else + fun_l24_n513(x) + end +end + +def fun_l23_n780(x) + if (x < 1) + fun_l24_n635(x) + else + fun_l24_n161(x) + end +end + +def fun_l23_n781(x) + if (x < 1) + fun_l24_n189(x) + else + fun_l24_n225(x) + end +end + +def fun_l23_n782(x) + if (x < 1) + fun_l24_n205(x) + else + fun_l24_n620(x) + end +end + +def fun_l23_n783(x) + if (x < 1) + fun_l24_n203(x) + else + fun_l24_n58(x) + end +end + +def fun_l23_n784(x) + if (x < 1) + fun_l24_n198(x) + else + fun_l24_n948(x) + end +end + +def fun_l23_n785(x) + if (x < 1) + fun_l24_n60(x) + else + fun_l24_n406(x) + end +end + +def fun_l23_n786(x) + if (x < 1) + fun_l24_n538(x) + else + fun_l24_n992(x) + end +end + +def fun_l23_n787(x) + if (x < 1) + fun_l24_n83(x) + else + fun_l24_n544(x) + end +end + +def fun_l23_n788(x) + if (x < 1) + fun_l24_n964(x) + else + fun_l24_n939(x) + end +end + +def fun_l23_n789(x) + if (x < 1) + fun_l24_n120(x) + else + fun_l24_n843(x) + end +end + +def fun_l23_n790(x) + if (x < 1) + fun_l24_n772(x) + else + fun_l24_n111(x) + end +end + +def fun_l23_n791(x) + if (x < 1) + fun_l24_n983(x) + else + fun_l24_n934(x) + end +end + +def fun_l23_n792(x) + if (x < 1) + fun_l24_n475(x) + else + fun_l24_n532(x) + end +end + +def fun_l23_n793(x) + if (x < 1) + fun_l24_n316(x) + else + fun_l24_n400(x) + end +end + +def fun_l23_n794(x) + if (x < 1) + fun_l24_n103(x) + else + fun_l24_n19(x) + end +end + +def fun_l23_n795(x) + if (x < 1) + fun_l24_n371(x) + else + fun_l24_n176(x) + end +end + +def fun_l23_n796(x) + if (x < 1) + fun_l24_n469(x) + else + fun_l24_n958(x) + end +end + +def fun_l23_n797(x) + if (x < 1) + fun_l24_n706(x) + else + fun_l24_n953(x) + end +end + +def fun_l23_n798(x) + if (x < 1) + fun_l24_n384(x) + else + fun_l24_n439(x) + end +end + +def fun_l23_n799(x) + if (x < 1) + fun_l24_n352(x) + else + fun_l24_n36(x) + end +end + +def fun_l23_n800(x) + if (x < 1) + fun_l24_n390(x) + else + fun_l24_n963(x) + end +end + +def fun_l23_n801(x) + if (x < 1) + fun_l24_n470(x) + else + fun_l24_n818(x) + end +end + +def fun_l23_n802(x) + if (x < 1) + fun_l24_n262(x) + else + fun_l24_n893(x) + end +end + +def fun_l23_n803(x) + if (x < 1) + fun_l24_n118(x) + else + fun_l24_n684(x) + end +end + +def fun_l23_n804(x) + if (x < 1) + fun_l24_n484(x) + else + fun_l24_n520(x) + end +end + +def fun_l23_n805(x) + if (x < 1) + fun_l24_n370(x) + else + fun_l24_n80(x) + end +end + +def fun_l23_n806(x) + if (x < 1) + fun_l24_n326(x) + else + fun_l24_n436(x) + end +end + +def fun_l23_n807(x) + if (x < 1) + fun_l24_n490(x) + else + fun_l24_n811(x) + end +end + +def fun_l23_n808(x) + if (x < 1) + fun_l24_n447(x) + else + fun_l24_n150(x) + end +end + +def fun_l23_n809(x) + if (x < 1) + fun_l24_n339(x) + else + fun_l24_n367(x) + end +end + +def fun_l23_n810(x) + if (x < 1) + fun_l24_n221(x) + else + fun_l24_n505(x) + end +end + +def fun_l23_n811(x) + if (x < 1) + fun_l24_n637(x) + else + fun_l24_n101(x) + end +end + +def fun_l23_n812(x) + if (x < 1) + fun_l24_n83(x) + else + fun_l24_n538(x) + end +end + +def fun_l23_n813(x) + if (x < 1) + fun_l24_n927(x) + else + fun_l24_n513(x) + end +end + +def fun_l23_n814(x) + if (x < 1) + fun_l24_n496(x) + else + fun_l24_n290(x) + end +end + +def fun_l23_n815(x) + if (x < 1) + fun_l24_n640(x) + else + fun_l24_n796(x) + end +end + +def fun_l23_n816(x) + if (x < 1) + fun_l24_n999(x) + else + fun_l24_n54(x) + end +end + +def fun_l23_n817(x) + if (x < 1) + fun_l24_n162(x) + else + fun_l24_n617(x) + end +end + +def fun_l23_n818(x) + if (x < 1) + fun_l24_n118(x) + else + fun_l24_n187(x) + end +end + +def fun_l23_n819(x) + if (x < 1) + fun_l24_n334(x) + else + fun_l24_n901(x) + end +end + +def fun_l23_n820(x) + if (x < 1) + fun_l24_n939(x) + else + fun_l24_n896(x) + end +end + +def fun_l23_n821(x) + if (x < 1) + fun_l24_n970(x) + else + fun_l24_n725(x) + end +end + +def fun_l23_n822(x) + if (x < 1) + fun_l24_n357(x) + else + fun_l24_n771(x) + end +end + +def fun_l23_n823(x) + if (x < 1) + fun_l24_n8(x) + else + fun_l24_n214(x) + end +end + +def fun_l23_n824(x) + if (x < 1) + fun_l24_n412(x) + else + fun_l24_n145(x) + end +end + +def fun_l23_n825(x) + if (x < 1) + fun_l24_n218(x) + else + fun_l24_n700(x) + end +end + +def fun_l23_n826(x) + if (x < 1) + fun_l24_n945(x) + else + fun_l24_n523(x) + end +end + +def fun_l23_n827(x) + if (x < 1) + fun_l24_n251(x) + else + fun_l24_n854(x) + end +end + +def fun_l23_n828(x) + if (x < 1) + fun_l24_n704(x) + else + fun_l24_n879(x) + end +end + +def fun_l23_n829(x) + if (x < 1) + fun_l24_n161(x) + else + fun_l24_n529(x) + end +end + +def fun_l23_n830(x) + if (x < 1) + fun_l24_n751(x) + else + fun_l24_n409(x) + end +end + +def fun_l23_n831(x) + if (x < 1) + fun_l24_n883(x) + else + fun_l24_n1(x) + end +end + +def fun_l23_n832(x) + if (x < 1) + fun_l24_n135(x) + else + fun_l24_n738(x) + end +end + +def fun_l23_n833(x) + if (x < 1) + fun_l24_n507(x) + else + fun_l24_n727(x) + end +end + +def fun_l23_n834(x) + if (x < 1) + fun_l24_n677(x) + else + fun_l24_n602(x) + end +end + +def fun_l23_n835(x) + if (x < 1) + fun_l24_n197(x) + else + fun_l24_n481(x) + end +end + +def fun_l23_n836(x) + if (x < 1) + fun_l24_n39(x) + else + fun_l24_n149(x) + end +end + +def fun_l23_n837(x) + if (x < 1) + fun_l24_n950(x) + else + fun_l24_n455(x) + end +end + +def fun_l23_n838(x) + if (x < 1) + fun_l24_n718(x) + else + fun_l24_n264(x) + end +end + +def fun_l23_n839(x) + if (x < 1) + fun_l24_n831(x) + else + fun_l24_n576(x) + end +end + +def fun_l23_n840(x) + if (x < 1) + fun_l24_n813(x) + else + fun_l24_n564(x) + end +end + +def fun_l23_n841(x) + if (x < 1) + fun_l24_n537(x) + else + fun_l24_n880(x) + end +end + +def fun_l23_n842(x) + if (x < 1) + fun_l24_n958(x) + else + fun_l24_n963(x) + end +end + +def fun_l23_n843(x) + if (x < 1) + fun_l24_n879(x) + else + fun_l24_n281(x) + end +end + +def fun_l23_n844(x) + if (x < 1) + fun_l24_n138(x) + else + fun_l24_n562(x) + end +end + +def fun_l23_n845(x) + if (x < 1) + fun_l24_n804(x) + else + fun_l24_n283(x) + end +end + +def fun_l23_n846(x) + if (x < 1) + fun_l24_n253(x) + else + fun_l24_n339(x) + end +end + +def fun_l23_n847(x) + if (x < 1) + fun_l24_n99(x) + else + fun_l24_n623(x) + end +end + +def fun_l23_n848(x) + if (x < 1) + fun_l24_n955(x) + else + fun_l24_n121(x) + end +end + +def fun_l23_n849(x) + if (x < 1) + fun_l24_n437(x) + else + fun_l24_n387(x) + end +end + +def fun_l23_n850(x) + if (x < 1) + fun_l24_n19(x) + else + fun_l24_n790(x) + end +end + +def fun_l23_n851(x) + if (x < 1) + fun_l24_n11(x) + else + fun_l24_n931(x) + end +end + +def fun_l23_n852(x) + if (x < 1) + fun_l24_n506(x) + else + fun_l24_n162(x) + end +end + +def fun_l23_n853(x) + if (x < 1) + fun_l24_n262(x) + else + fun_l24_n1(x) + end +end + +def fun_l23_n854(x) + if (x < 1) + fun_l24_n275(x) + else + fun_l24_n549(x) + end +end + +def fun_l23_n855(x) + if (x < 1) + fun_l24_n865(x) + else + fun_l24_n472(x) + end +end + +def fun_l23_n856(x) + if (x < 1) + fun_l24_n270(x) + else + fun_l24_n312(x) + end +end + +def fun_l23_n857(x) + if (x < 1) + fun_l24_n261(x) + else + fun_l24_n240(x) + end +end + +def fun_l23_n858(x) + if (x < 1) + fun_l24_n166(x) + else + fun_l24_n996(x) + end +end + +def fun_l23_n859(x) + if (x < 1) + fun_l24_n653(x) + else + fun_l24_n464(x) + end +end + +def fun_l23_n860(x) + if (x < 1) + fun_l24_n446(x) + else + fun_l24_n706(x) + end +end + +def fun_l23_n861(x) + if (x < 1) + fun_l24_n744(x) + else + fun_l24_n53(x) + end +end + +def fun_l23_n862(x) + if (x < 1) + fun_l24_n983(x) + else + fun_l24_n188(x) + end +end + +def fun_l23_n863(x) + if (x < 1) + fun_l24_n399(x) + else + fun_l24_n582(x) + end +end + +def fun_l23_n864(x) + if (x < 1) + fun_l24_n392(x) + else + fun_l24_n937(x) + end +end + +def fun_l23_n865(x) + if (x < 1) + fun_l24_n495(x) + else + fun_l24_n557(x) + end +end + +def fun_l23_n866(x) + if (x < 1) + fun_l24_n94(x) + else + fun_l24_n295(x) + end +end + +def fun_l23_n867(x) + if (x < 1) + fun_l24_n628(x) + else + fun_l24_n432(x) + end +end + +def fun_l23_n868(x) + if (x < 1) + fun_l24_n386(x) + else + fun_l24_n385(x) + end +end + +def fun_l23_n869(x) + if (x < 1) + fun_l24_n376(x) + else + fun_l24_n469(x) + end +end + +def fun_l23_n870(x) + if (x < 1) + fun_l24_n74(x) + else + fun_l24_n712(x) + end +end + +def fun_l23_n871(x) + if (x < 1) + fun_l24_n72(x) + else + fun_l24_n642(x) + end +end + +def fun_l23_n872(x) + if (x < 1) + fun_l24_n937(x) + else + fun_l24_n751(x) + end +end + +def fun_l23_n873(x) + if (x < 1) + fun_l24_n385(x) + else + fun_l24_n404(x) + end +end + +def fun_l23_n874(x) + if (x < 1) + fun_l24_n336(x) + else + fun_l24_n226(x) + end +end + +def fun_l23_n875(x) + if (x < 1) + fun_l24_n289(x) + else + fun_l24_n989(x) + end +end + +def fun_l23_n876(x) + if (x < 1) + fun_l24_n45(x) + else + fun_l24_n279(x) + end +end + +def fun_l23_n877(x) + if (x < 1) + fun_l24_n683(x) + else + fun_l24_n342(x) + end +end + +def fun_l23_n878(x) + if (x < 1) + fun_l24_n279(x) + else + fun_l24_n600(x) + end +end + +def fun_l23_n879(x) + if (x < 1) + fun_l24_n82(x) + else + fun_l24_n177(x) + end +end + +def fun_l23_n880(x) + if (x < 1) + fun_l24_n167(x) + else + fun_l24_n912(x) + end +end + +def fun_l23_n881(x) + if (x < 1) + fun_l24_n311(x) + else + fun_l24_n634(x) + end +end + +def fun_l23_n882(x) + if (x < 1) + fun_l24_n127(x) + else + fun_l24_n661(x) + end +end + +def fun_l23_n883(x) + if (x < 1) + fun_l24_n199(x) + else + fun_l24_n999(x) + end +end + +def fun_l23_n884(x) + if (x < 1) + fun_l24_n525(x) + else + fun_l24_n948(x) + end +end + +def fun_l23_n885(x) + if (x < 1) + fun_l24_n590(x) + else + fun_l24_n822(x) + end +end + +def fun_l23_n886(x) + if (x < 1) + fun_l24_n811(x) + else + fun_l24_n975(x) + end +end + +def fun_l23_n887(x) + if (x < 1) + fun_l24_n446(x) + else + fun_l24_n710(x) + end +end + +def fun_l23_n888(x) + if (x < 1) + fun_l24_n31(x) + else + fun_l24_n92(x) + end +end + +def fun_l23_n889(x) + if (x < 1) + fun_l24_n535(x) + else + fun_l24_n819(x) + end +end + +def fun_l23_n890(x) + if (x < 1) + fun_l24_n526(x) + else + fun_l24_n207(x) + end +end + +def fun_l23_n891(x) + if (x < 1) + fun_l24_n752(x) + else + fun_l24_n994(x) + end +end + +def fun_l23_n892(x) + if (x < 1) + fun_l24_n758(x) + else + fun_l24_n292(x) + end +end + +def fun_l23_n893(x) + if (x < 1) + fun_l24_n106(x) + else + fun_l24_n742(x) + end +end + +def fun_l23_n894(x) + if (x < 1) + fun_l24_n385(x) + else + fun_l24_n562(x) + end +end + +def fun_l23_n895(x) + if (x < 1) + fun_l24_n565(x) + else + fun_l24_n242(x) + end +end + +def fun_l23_n896(x) + if (x < 1) + fun_l24_n570(x) + else + fun_l24_n241(x) + end +end + +def fun_l23_n897(x) + if (x < 1) + fun_l24_n840(x) + else + fun_l24_n681(x) + end +end + +def fun_l23_n898(x) + if (x < 1) + fun_l24_n524(x) + else + fun_l24_n9(x) + end +end + +def fun_l23_n899(x) + if (x < 1) + fun_l24_n161(x) + else + fun_l24_n795(x) + end +end + +def fun_l23_n900(x) + if (x < 1) + fun_l24_n64(x) + else + fun_l24_n447(x) + end +end + +def fun_l23_n901(x) + if (x < 1) + fun_l24_n676(x) + else + fun_l24_n286(x) + end +end + +def fun_l23_n902(x) + if (x < 1) + fun_l24_n623(x) + else + fun_l24_n298(x) + end +end + +def fun_l23_n903(x) + if (x < 1) + fun_l24_n795(x) + else + fun_l24_n646(x) + end +end + +def fun_l23_n904(x) + if (x < 1) + fun_l24_n746(x) + else + fun_l24_n7(x) + end +end + +def fun_l23_n905(x) + if (x < 1) + fun_l24_n311(x) + else + fun_l24_n417(x) + end +end + +def fun_l23_n906(x) + if (x < 1) + fun_l24_n338(x) + else + fun_l24_n592(x) + end +end + +def fun_l23_n907(x) + if (x < 1) + fun_l24_n667(x) + else + fun_l24_n370(x) + end +end + +def fun_l23_n908(x) + if (x < 1) + fun_l24_n444(x) + else + fun_l24_n703(x) + end +end + +def fun_l23_n909(x) + if (x < 1) + fun_l24_n325(x) + else + fun_l24_n977(x) + end +end + +def fun_l23_n910(x) + if (x < 1) + fun_l24_n994(x) + else + fun_l24_n765(x) + end +end + +def fun_l23_n911(x) + if (x < 1) + fun_l24_n327(x) + else + fun_l24_n657(x) + end +end + +def fun_l23_n912(x) + if (x < 1) + fun_l24_n932(x) + else + fun_l24_n769(x) + end +end + +def fun_l23_n913(x) + if (x < 1) + fun_l24_n263(x) + else + fun_l24_n729(x) + end +end + +def fun_l23_n914(x) + if (x < 1) + fun_l24_n248(x) + else + fun_l24_n412(x) + end +end + +def fun_l23_n915(x) + if (x < 1) + fun_l24_n793(x) + else + fun_l24_n329(x) + end +end + +def fun_l23_n916(x) + if (x < 1) + fun_l24_n7(x) + else + fun_l24_n460(x) + end +end + +def fun_l23_n917(x) + if (x < 1) + fun_l24_n612(x) + else + fun_l24_n79(x) + end +end + +def fun_l23_n918(x) + if (x < 1) + fun_l24_n450(x) + else + fun_l24_n950(x) + end +end + +def fun_l23_n919(x) + if (x < 1) + fun_l24_n72(x) + else + fun_l24_n550(x) + end +end + +def fun_l23_n920(x) + if (x < 1) + fun_l24_n73(x) + else + fun_l24_n339(x) + end +end + +def fun_l23_n921(x) + if (x < 1) + fun_l24_n6(x) + else + fun_l24_n865(x) + end +end + +def fun_l23_n922(x) + if (x < 1) + fun_l24_n507(x) + else + fun_l24_n475(x) + end +end + +def fun_l23_n923(x) + if (x < 1) + fun_l24_n579(x) + else + fun_l24_n832(x) + end +end + +def fun_l23_n924(x) + if (x < 1) + fun_l24_n681(x) + else + fun_l24_n253(x) + end +end + +def fun_l23_n925(x) + if (x < 1) + fun_l24_n611(x) + else + fun_l24_n831(x) + end +end + +def fun_l23_n926(x) + if (x < 1) + fun_l24_n371(x) + else + fun_l24_n236(x) + end +end + +def fun_l23_n927(x) + if (x < 1) + fun_l24_n941(x) + else + fun_l24_n905(x) + end +end + +def fun_l23_n928(x) + if (x < 1) + fun_l24_n616(x) + else + fun_l24_n421(x) + end +end + +def fun_l23_n929(x) + if (x < 1) + fun_l24_n469(x) + else + fun_l24_n405(x) + end +end + +def fun_l23_n930(x) + if (x < 1) + fun_l24_n584(x) + else + fun_l24_n694(x) + end +end + +def fun_l23_n931(x) + if (x < 1) + fun_l24_n530(x) + else + fun_l24_n112(x) + end +end + +def fun_l23_n932(x) + if (x < 1) + fun_l24_n115(x) + else + fun_l24_n667(x) + end +end + +def fun_l23_n933(x) + if (x < 1) + fun_l24_n23(x) + else + fun_l24_n68(x) + end +end + +def fun_l23_n934(x) + if (x < 1) + fun_l24_n215(x) + else + fun_l24_n459(x) + end +end + +def fun_l23_n935(x) + if (x < 1) + fun_l24_n533(x) + else + fun_l24_n882(x) + end +end + +def fun_l23_n936(x) + if (x < 1) + fun_l24_n918(x) + else + fun_l24_n522(x) + end +end + +def fun_l23_n937(x) + if (x < 1) + fun_l24_n472(x) + else + fun_l24_n322(x) + end +end + +def fun_l23_n938(x) + if (x < 1) + fun_l24_n528(x) + else + fun_l24_n937(x) + end +end + +def fun_l23_n939(x) + if (x < 1) + fun_l24_n426(x) + else + fun_l24_n904(x) + end +end + +def fun_l23_n940(x) + if (x < 1) + fun_l24_n259(x) + else + fun_l24_n350(x) + end +end + +def fun_l23_n941(x) + if (x < 1) + fun_l24_n770(x) + else + fun_l24_n449(x) + end +end + +def fun_l23_n942(x) + if (x < 1) + fun_l24_n159(x) + else + fun_l24_n312(x) + end +end + +def fun_l23_n943(x) + if (x < 1) + fun_l24_n168(x) + else + fun_l24_n820(x) + end +end + +def fun_l23_n944(x) + if (x < 1) + fun_l24_n861(x) + else + fun_l24_n395(x) + end +end + +def fun_l23_n945(x) + if (x < 1) + fun_l24_n802(x) + else + fun_l24_n651(x) + end +end + +def fun_l23_n946(x) + if (x < 1) + fun_l24_n519(x) + else + fun_l24_n736(x) + end +end + +def fun_l23_n947(x) + if (x < 1) + fun_l24_n277(x) + else + fun_l24_n705(x) + end +end + +def fun_l23_n948(x) + if (x < 1) + fun_l24_n658(x) + else + fun_l24_n983(x) + end +end + +def fun_l23_n949(x) + if (x < 1) + fun_l24_n390(x) + else + fun_l24_n365(x) + end +end + +def fun_l23_n950(x) + if (x < 1) + fun_l24_n362(x) + else + fun_l24_n895(x) + end +end + +def fun_l23_n951(x) + if (x < 1) + fun_l24_n431(x) + else + fun_l24_n240(x) + end +end + +def fun_l23_n952(x) + if (x < 1) + fun_l24_n87(x) + else + fun_l24_n923(x) + end +end + +def fun_l23_n953(x) + if (x < 1) + fun_l24_n605(x) + else + fun_l24_n369(x) + end +end + +def fun_l23_n954(x) + if (x < 1) + fun_l24_n659(x) + else + fun_l24_n485(x) + end +end + +def fun_l23_n955(x) + if (x < 1) + fun_l24_n204(x) + else + fun_l24_n719(x) + end +end + +def fun_l23_n956(x) + if (x < 1) + fun_l24_n752(x) + else + fun_l24_n522(x) + end +end + +def fun_l23_n957(x) + if (x < 1) + fun_l24_n827(x) + else + fun_l24_n740(x) + end +end + +def fun_l23_n958(x) + if (x < 1) + fun_l24_n476(x) + else + fun_l24_n766(x) + end +end + +def fun_l23_n959(x) + if (x < 1) + fun_l24_n167(x) + else + fun_l24_n552(x) + end +end + +def fun_l23_n960(x) + if (x < 1) + fun_l24_n352(x) + else + fun_l24_n147(x) + end +end + +def fun_l23_n961(x) + if (x < 1) + fun_l24_n641(x) + else + fun_l24_n263(x) + end +end + +def fun_l23_n962(x) + if (x < 1) + fun_l24_n2(x) + else + fun_l24_n819(x) + end +end + +def fun_l23_n963(x) + if (x < 1) + fun_l24_n649(x) + else + fun_l24_n589(x) + end +end + +def fun_l23_n964(x) + if (x < 1) + fun_l24_n351(x) + else + fun_l24_n170(x) + end +end + +def fun_l23_n965(x) + if (x < 1) + fun_l24_n913(x) + else + fun_l24_n141(x) + end +end + +def fun_l23_n966(x) + if (x < 1) + fun_l24_n230(x) + else + fun_l24_n438(x) + end +end + +def fun_l23_n967(x) + if (x < 1) + fun_l24_n649(x) + else + fun_l24_n867(x) + end +end + +def fun_l23_n968(x) + if (x < 1) + fun_l24_n877(x) + else + fun_l24_n341(x) + end +end + +def fun_l23_n969(x) + if (x < 1) + fun_l24_n802(x) + else + fun_l24_n409(x) + end +end + +def fun_l23_n970(x) + if (x < 1) + fun_l24_n388(x) + else + fun_l24_n521(x) + end +end + +def fun_l23_n971(x) + if (x < 1) + fun_l24_n533(x) + else + fun_l24_n856(x) + end +end + +def fun_l23_n972(x) + if (x < 1) + fun_l24_n409(x) + else + fun_l24_n119(x) + end +end + +def fun_l23_n973(x) + if (x < 1) + fun_l24_n774(x) + else + fun_l24_n561(x) + end +end + +def fun_l23_n974(x) + if (x < 1) + fun_l24_n96(x) + else + fun_l24_n629(x) + end +end + +def fun_l23_n975(x) + if (x < 1) + fun_l24_n985(x) + else + fun_l24_n651(x) + end +end + +def fun_l23_n976(x) + if (x < 1) + fun_l24_n977(x) + else + fun_l24_n274(x) + end +end + +def fun_l23_n977(x) + if (x < 1) + fun_l24_n85(x) + else + fun_l24_n337(x) + end +end + +def fun_l23_n978(x) + if (x < 1) + fun_l24_n312(x) + else + fun_l24_n990(x) + end +end + +def fun_l23_n979(x) + if (x < 1) + fun_l24_n438(x) + else + fun_l24_n42(x) + end +end + +def fun_l23_n980(x) + if (x < 1) + fun_l24_n341(x) + else + fun_l24_n27(x) + end +end + +def fun_l23_n981(x) + if (x < 1) + fun_l24_n300(x) + else + fun_l24_n669(x) + end +end + +def fun_l23_n982(x) + if (x < 1) + fun_l24_n586(x) + else + fun_l24_n822(x) + end +end + +def fun_l23_n983(x) + if (x < 1) + fun_l24_n388(x) + else + fun_l24_n966(x) + end +end + +def fun_l23_n984(x) + if (x < 1) + fun_l24_n661(x) + else + fun_l24_n66(x) + end +end + +def fun_l23_n985(x) + if (x < 1) + fun_l24_n384(x) + else + fun_l24_n419(x) + end +end + +def fun_l23_n986(x) + if (x < 1) + fun_l24_n698(x) + else + fun_l24_n961(x) + end +end + +def fun_l23_n987(x) + if (x < 1) + fun_l24_n820(x) + else + fun_l24_n112(x) + end +end + +def fun_l23_n988(x) + if (x < 1) + fun_l24_n976(x) + else + fun_l24_n232(x) + end +end + +def fun_l23_n989(x) + if (x < 1) + fun_l24_n292(x) + else + fun_l24_n77(x) + end +end + +def fun_l23_n990(x) + if (x < 1) + fun_l24_n572(x) + else + fun_l24_n524(x) + end +end + +def fun_l23_n991(x) + if (x < 1) + fun_l24_n226(x) + else + fun_l24_n821(x) + end +end + +def fun_l23_n992(x) + if (x < 1) + fun_l24_n12(x) + else + fun_l24_n891(x) + end +end + +def fun_l23_n993(x) + if (x < 1) + fun_l24_n101(x) + else + fun_l24_n592(x) + end +end + +def fun_l23_n994(x) + if (x < 1) + fun_l24_n796(x) + else + fun_l24_n594(x) + end +end + +def fun_l23_n995(x) + if (x < 1) + fun_l24_n707(x) + else + fun_l24_n577(x) + end +end + +def fun_l23_n996(x) + if (x < 1) + fun_l24_n123(x) + else + fun_l24_n730(x) + end +end + +def fun_l23_n997(x) + if (x < 1) + fun_l24_n520(x) + else + fun_l24_n888(x) + end +end + +def fun_l23_n998(x) + if (x < 1) + fun_l24_n165(x) + else + fun_l24_n576(x) + end +end + +def fun_l23_n999(x) + if (x < 1) + fun_l24_n496(x) + else + fun_l24_n722(x) + end +end + +def fun_l24_n0(x) + if (x < 1) + fun_l25_n357(x) + else + fun_l25_n144(x) + end +end + +def fun_l24_n1(x) + if (x < 1) + fun_l25_n49(x) + else + fun_l25_n870(x) + end +end + +def fun_l24_n2(x) + if (x < 1) + fun_l25_n547(x) + else + fun_l25_n357(x) + end +end + +def fun_l24_n3(x) + if (x < 1) + fun_l25_n167(x) + else + fun_l25_n908(x) + end +end + +def fun_l24_n4(x) + if (x < 1) + fun_l25_n943(x) + else + fun_l25_n882(x) + end +end + +def fun_l24_n5(x) + if (x < 1) + fun_l25_n635(x) + else + fun_l25_n988(x) + end +end + +def fun_l24_n6(x) + if (x < 1) + fun_l25_n648(x) + else + fun_l25_n62(x) + end +end + +def fun_l24_n7(x) + if (x < 1) + fun_l25_n896(x) + else + fun_l25_n636(x) + end +end + +def fun_l24_n8(x) + if (x < 1) + fun_l25_n666(x) + else + fun_l25_n50(x) + end +end + +def fun_l24_n9(x) + if (x < 1) + fun_l25_n42(x) + else + fun_l25_n216(x) + end +end + +def fun_l24_n10(x) + if (x < 1) + fun_l25_n979(x) + else + fun_l25_n27(x) + end +end + +def fun_l24_n11(x) + if (x < 1) + fun_l25_n421(x) + else + fun_l25_n239(x) + end +end + +def fun_l24_n12(x) + if (x < 1) + fun_l25_n465(x) + else + fun_l25_n483(x) + end +end + +def fun_l24_n13(x) + if (x < 1) + fun_l25_n172(x) + else + fun_l25_n918(x) + end +end + +def fun_l24_n14(x) + if (x < 1) + fun_l25_n130(x) + else + fun_l25_n144(x) + end +end + +def fun_l24_n15(x) + if (x < 1) + fun_l25_n569(x) + else + fun_l25_n319(x) + end +end + +def fun_l24_n16(x) + if (x < 1) + fun_l25_n54(x) + else + fun_l25_n253(x) + end +end + +def fun_l24_n17(x) + if (x < 1) + fun_l25_n127(x) + else + fun_l25_n594(x) + end +end + +def fun_l24_n18(x) + if (x < 1) + fun_l25_n94(x) + else + fun_l25_n486(x) + end +end + +def fun_l24_n19(x) + if (x < 1) + fun_l25_n322(x) + else + fun_l25_n731(x) + end +end + +def fun_l24_n20(x) + if (x < 1) + fun_l25_n828(x) + else + fun_l25_n410(x) + end +end + +def fun_l24_n21(x) + if (x < 1) + fun_l25_n422(x) + else + fun_l25_n265(x) + end +end + +def fun_l24_n22(x) + if (x < 1) + fun_l25_n259(x) + else + fun_l25_n902(x) + end +end + +def fun_l24_n23(x) + if (x < 1) + fun_l25_n660(x) + else + fun_l25_n525(x) + end +end + +def fun_l24_n24(x) + if (x < 1) + fun_l25_n898(x) + else + fun_l25_n231(x) + end +end + +def fun_l24_n25(x) + if (x < 1) + fun_l25_n319(x) + else + fun_l25_n306(x) + end +end + +def fun_l24_n26(x) + if (x < 1) + fun_l25_n447(x) + else + fun_l25_n110(x) + end +end + +def fun_l24_n27(x) + if (x < 1) + fun_l25_n416(x) + else + fun_l25_n335(x) + end +end + +def fun_l24_n28(x) + if (x < 1) + fun_l25_n132(x) + else + fun_l25_n549(x) + end +end + +def fun_l24_n29(x) + if (x < 1) + fun_l25_n878(x) + else + fun_l25_n790(x) + end +end + +def fun_l24_n30(x) + if (x < 1) + fun_l25_n205(x) + else + fun_l25_n328(x) + end +end + +def fun_l24_n31(x) + if (x < 1) + fun_l25_n448(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n32(x) + if (x < 1) + fun_l25_n800(x) + else + fun_l25_n254(x) + end +end + +def fun_l24_n33(x) + if (x < 1) + fun_l25_n377(x) + else + fun_l25_n178(x) + end +end + +def fun_l24_n34(x) + if (x < 1) + fun_l25_n317(x) + else + fun_l25_n271(x) + end +end + +def fun_l24_n35(x) + if (x < 1) + fun_l25_n50(x) + else + fun_l25_n801(x) + end +end + +def fun_l24_n36(x) + if (x < 1) + fun_l25_n720(x) + else + fun_l25_n267(x) + end +end + +def fun_l24_n37(x) + if (x < 1) + fun_l25_n688(x) + else + fun_l25_n901(x) + end +end + +def fun_l24_n38(x) + if (x < 1) + fun_l25_n752(x) + else + fun_l25_n541(x) + end +end + +def fun_l24_n39(x) + if (x < 1) + fun_l25_n716(x) + else + fun_l25_n884(x) + end +end + +def fun_l24_n40(x) + if (x < 1) + fun_l25_n138(x) + else + fun_l25_n536(x) + end +end + +def fun_l24_n41(x) + if (x < 1) + fun_l25_n382(x) + else + fun_l25_n496(x) + end +end + +def fun_l24_n42(x) + if (x < 1) + fun_l25_n729(x) + else + fun_l25_n443(x) + end +end + +def fun_l24_n43(x) + if (x < 1) + fun_l25_n401(x) + else + fun_l25_n300(x) + end +end + +def fun_l24_n44(x) + if (x < 1) + fun_l25_n695(x) + else + fun_l25_n139(x) + end +end + +def fun_l24_n45(x) + if (x < 1) + fun_l25_n186(x) + else + fun_l25_n446(x) + end +end + +def fun_l24_n46(x) + if (x < 1) + fun_l25_n102(x) + else + fun_l25_n415(x) + end +end + +def fun_l24_n47(x) + if (x < 1) + fun_l25_n74(x) + else + fun_l25_n947(x) + end +end + +def fun_l24_n48(x) + if (x < 1) + fun_l25_n720(x) + else + fun_l25_n873(x) + end +end + +def fun_l24_n49(x) + if (x < 1) + fun_l25_n779(x) + else + fun_l25_n61(x) + end +end + +def fun_l24_n50(x) + if (x < 1) + fun_l25_n889(x) + else + fun_l25_n620(x) + end +end + +def fun_l24_n51(x) + if (x < 1) + fun_l25_n323(x) + else + fun_l25_n412(x) + end +end + +def fun_l24_n52(x) + if (x < 1) + fun_l25_n986(x) + else + fun_l25_n950(x) + end +end + +def fun_l24_n53(x) + if (x < 1) + fun_l25_n810(x) + else + fun_l25_n956(x) + end +end + +def fun_l24_n54(x) + if (x < 1) + fun_l25_n89(x) + else + fun_l25_n110(x) + end +end + +def fun_l24_n55(x) + if (x < 1) + fun_l25_n255(x) + else + fun_l25_n953(x) + end +end + +def fun_l24_n56(x) + if (x < 1) + fun_l25_n200(x) + else + fun_l25_n366(x) + end +end + +def fun_l24_n57(x) + if (x < 1) + fun_l25_n431(x) + else + fun_l25_n49(x) + end +end + +def fun_l24_n58(x) + if (x < 1) + fun_l25_n705(x) + else + fun_l25_n362(x) + end +end + +def fun_l24_n59(x) + if (x < 1) + fun_l25_n587(x) + else + fun_l25_n511(x) + end +end + +def fun_l24_n60(x) + if (x < 1) + fun_l25_n72(x) + else + fun_l25_n560(x) + end +end + +def fun_l24_n61(x) + if (x < 1) + fun_l25_n732(x) + else + fun_l25_n214(x) + end +end + +def fun_l24_n62(x) + if (x < 1) + fun_l25_n348(x) + else + fun_l25_n70(x) + end +end + +def fun_l24_n63(x) + if (x < 1) + fun_l25_n371(x) + else + fun_l25_n625(x) + end +end + +def fun_l24_n64(x) + if (x < 1) + fun_l25_n204(x) + else + fun_l25_n249(x) + end +end + +def fun_l24_n65(x) + if (x < 1) + fun_l25_n608(x) + else + fun_l25_n682(x) + end +end + +def fun_l24_n66(x) + if (x < 1) + fun_l25_n450(x) + else + fun_l25_n951(x) + end +end + +def fun_l24_n67(x) + if (x < 1) + fun_l25_n749(x) + else + fun_l25_n39(x) + end +end + +def fun_l24_n68(x) + if (x < 1) + fun_l25_n169(x) + else + fun_l25_n801(x) + end +end + +def fun_l24_n69(x) + if (x < 1) + fun_l25_n55(x) + else + fun_l25_n728(x) + end +end + +def fun_l24_n70(x) + if (x < 1) + fun_l25_n115(x) + else + fun_l25_n689(x) + end +end + +def fun_l24_n71(x) + if (x < 1) + fun_l25_n332(x) + else + fun_l25_n474(x) + end +end + +def fun_l24_n72(x) + if (x < 1) + fun_l25_n846(x) + else + fun_l25_n808(x) + end +end + +def fun_l24_n73(x) + if (x < 1) + fun_l25_n521(x) + else + fun_l25_n229(x) + end +end + +def fun_l24_n74(x) + if (x < 1) + fun_l25_n307(x) + else + fun_l25_n992(x) + end +end + +def fun_l24_n75(x) + if (x < 1) + fun_l25_n564(x) + else + fun_l25_n940(x) + end +end + +def fun_l24_n76(x) + if (x < 1) + fun_l25_n348(x) + else + fun_l25_n453(x) + end +end + +def fun_l24_n77(x) + if (x < 1) + fun_l25_n252(x) + else + fun_l25_n270(x) + end +end + +def fun_l24_n78(x) + if (x < 1) + fun_l25_n333(x) + else + fun_l25_n980(x) + end +end + +def fun_l24_n79(x) + if (x < 1) + fun_l25_n486(x) + else + fun_l25_n276(x) + end +end + +def fun_l24_n80(x) + if (x < 1) + fun_l25_n45(x) + else + fun_l25_n930(x) + end +end + +def fun_l24_n81(x) + if (x < 1) + fun_l25_n527(x) + else + fun_l25_n181(x) + end +end + +def fun_l24_n82(x) + if (x < 1) + fun_l25_n768(x) + else + fun_l25_n869(x) + end +end + +def fun_l24_n83(x) + if (x < 1) + fun_l25_n505(x) + else + fun_l25_n214(x) + end +end + +def fun_l24_n84(x) + if (x < 1) + fun_l25_n41(x) + else + fun_l25_n873(x) + end +end + +def fun_l24_n85(x) + if (x < 1) + fun_l25_n646(x) + else + fun_l25_n105(x) + end +end + +def fun_l24_n86(x) + if (x < 1) + fun_l25_n675(x) + else + fun_l25_n830(x) + end +end + +def fun_l24_n87(x) + if (x < 1) + fun_l25_n953(x) + else + fun_l25_n268(x) + end +end + +def fun_l24_n88(x) + if (x < 1) + fun_l25_n36(x) + else + fun_l25_n31(x) + end +end + +def fun_l24_n89(x) + if (x < 1) + fun_l25_n810(x) + else + fun_l25_n315(x) + end +end + +def fun_l24_n90(x) + if (x < 1) + fun_l25_n100(x) + else + fun_l25_n882(x) + end +end + +def fun_l24_n91(x) + if (x < 1) + fun_l25_n278(x) + else + fun_l25_n720(x) + end +end + +def fun_l24_n92(x) + if (x < 1) + fun_l25_n472(x) + else + fun_l25_n615(x) + end +end + +def fun_l24_n93(x) + if (x < 1) + fun_l25_n42(x) + else + fun_l25_n16(x) + end +end + +def fun_l24_n94(x) + if (x < 1) + fun_l25_n905(x) + else + fun_l25_n988(x) + end +end + +def fun_l24_n95(x) + if (x < 1) + fun_l25_n862(x) + else + fun_l25_n355(x) + end +end + +def fun_l24_n96(x) + if (x < 1) + fun_l25_n931(x) + else + fun_l25_n539(x) + end +end + +def fun_l24_n97(x) + if (x < 1) + fun_l25_n185(x) + else + fun_l25_n868(x) + end +end + +def fun_l24_n98(x) + if (x < 1) + fun_l25_n276(x) + else + fun_l25_n591(x) + end +end + +def fun_l24_n99(x) + if (x < 1) + fun_l25_n695(x) + else + fun_l25_n965(x) + end +end + +def fun_l24_n100(x) + if (x < 1) + fun_l25_n293(x) + else + fun_l25_n127(x) + end +end + +def fun_l24_n101(x) + if (x < 1) + fun_l25_n71(x) + else + fun_l25_n245(x) + end +end + +def fun_l24_n102(x) + if (x < 1) + fun_l25_n397(x) + else + fun_l25_n893(x) + end +end + +def fun_l24_n103(x) + if (x < 1) + fun_l25_n191(x) + else + fun_l25_n101(x) + end +end + +def fun_l24_n104(x) + if (x < 1) + fun_l25_n982(x) + else + fun_l25_n101(x) + end +end + +def fun_l24_n105(x) + if (x < 1) + fun_l25_n385(x) + else + fun_l25_n651(x) + end +end + +def fun_l24_n106(x) + if (x < 1) + fun_l25_n577(x) + else + fun_l25_n241(x) + end +end + +def fun_l24_n107(x) + if (x < 1) + fun_l25_n219(x) + else + fun_l25_n92(x) + end +end + +def fun_l24_n108(x) + if (x < 1) + fun_l25_n202(x) + else + fun_l25_n133(x) + end +end + +def fun_l24_n109(x) + if (x < 1) + fun_l25_n706(x) + else + fun_l25_n970(x) + end +end + +def fun_l24_n110(x) + if (x < 1) + fun_l25_n948(x) + else + fun_l25_n595(x) + end +end + +def fun_l24_n111(x) + if (x < 1) + fun_l25_n775(x) + else + fun_l25_n609(x) + end +end + +def fun_l24_n112(x) + if (x < 1) + fun_l25_n905(x) + else + fun_l25_n11(x) + end +end + +def fun_l24_n113(x) + if (x < 1) + fun_l25_n730(x) + else + fun_l25_n826(x) + end +end + +def fun_l24_n114(x) + if (x < 1) + fun_l25_n403(x) + else + fun_l25_n562(x) + end +end + +def fun_l24_n115(x) + if (x < 1) + fun_l25_n272(x) + else + fun_l25_n844(x) + end +end + +def fun_l24_n116(x) + if (x < 1) + fun_l25_n907(x) + else + fun_l25_n797(x) + end +end + +def fun_l24_n117(x) + if (x < 1) + fun_l25_n910(x) + else + fun_l25_n632(x) + end +end + +def fun_l24_n118(x) + if (x < 1) + fun_l25_n570(x) + else + fun_l25_n645(x) + end +end + +def fun_l24_n119(x) + if (x < 1) + fun_l25_n930(x) + else + fun_l25_n31(x) + end +end + +def fun_l24_n120(x) + if (x < 1) + fun_l25_n228(x) + else + fun_l25_n340(x) + end +end + +def fun_l24_n121(x) + if (x < 1) + fun_l25_n891(x) + else + fun_l25_n395(x) + end +end + +def fun_l24_n122(x) + if (x < 1) + fun_l25_n340(x) + else + fun_l25_n966(x) + end +end + +def fun_l24_n123(x) + if (x < 1) + fun_l25_n835(x) + else + fun_l25_n407(x) + end +end + +def fun_l24_n124(x) + if (x < 1) + fun_l25_n156(x) + else + fun_l25_n151(x) + end +end + +def fun_l24_n125(x) + if (x < 1) + fun_l25_n912(x) + else + fun_l25_n733(x) + end +end + +def fun_l24_n126(x) + if (x < 1) + fun_l25_n385(x) + else + fun_l25_n406(x) + end +end + +def fun_l24_n127(x) + if (x < 1) + fun_l25_n662(x) + else + fun_l25_n932(x) + end +end + +def fun_l24_n128(x) + if (x < 1) + fun_l25_n418(x) + else + fun_l25_n445(x) + end +end + +def fun_l24_n129(x) + if (x < 1) + fun_l25_n659(x) + else + fun_l25_n518(x) + end +end + +def fun_l24_n130(x) + if (x < 1) + fun_l25_n784(x) + else + fun_l25_n342(x) + end +end + +def fun_l24_n131(x) + if (x < 1) + fun_l25_n184(x) + else + fun_l25_n316(x) + end +end + +def fun_l24_n132(x) + if (x < 1) + fun_l25_n76(x) + else + fun_l25_n156(x) + end +end + +def fun_l24_n133(x) + if (x < 1) + fun_l25_n355(x) + else + fun_l25_n430(x) + end +end + +def fun_l24_n134(x) + if (x < 1) + fun_l25_n643(x) + else + fun_l25_n109(x) + end +end + +def fun_l24_n135(x) + if (x < 1) + fun_l25_n277(x) + else + fun_l25_n76(x) + end +end + +def fun_l24_n136(x) + if (x < 1) + fun_l25_n898(x) + else + fun_l25_n870(x) + end +end + +def fun_l24_n137(x) + if (x < 1) + fun_l25_n275(x) + else + fun_l25_n762(x) + end +end + +def fun_l24_n138(x) + if (x < 1) + fun_l25_n109(x) + else + fun_l25_n913(x) + end +end + +def fun_l24_n139(x) + if (x < 1) + fun_l25_n731(x) + else + fun_l25_n767(x) + end +end + +def fun_l24_n140(x) + if (x < 1) + fun_l25_n385(x) + else + fun_l25_n743(x) + end +end + +def fun_l24_n141(x) + if (x < 1) + fun_l25_n518(x) + else + fun_l25_n185(x) + end +end + +def fun_l24_n142(x) + if (x < 1) + fun_l25_n656(x) + else + fun_l25_n614(x) + end +end + +def fun_l24_n143(x) + if (x < 1) + fun_l25_n86(x) + else + fun_l25_n825(x) + end +end + +def fun_l24_n144(x) + if (x < 1) + fun_l25_n982(x) + else + fun_l25_n970(x) + end +end + +def fun_l24_n145(x) + if (x < 1) + fun_l25_n608(x) + else + fun_l25_n970(x) + end +end + +def fun_l24_n146(x) + if (x < 1) + fun_l25_n273(x) + else + fun_l25_n4(x) + end +end + +def fun_l24_n147(x) + if (x < 1) + fun_l25_n366(x) + else + fun_l25_n902(x) + end +end + +def fun_l24_n148(x) + if (x < 1) + fun_l25_n682(x) + else + fun_l25_n210(x) + end +end + +def fun_l24_n149(x) + if (x < 1) + fun_l25_n212(x) + else + fun_l25_n429(x) + end +end + +def fun_l24_n150(x) + if (x < 1) + fun_l25_n680(x) + else + fun_l25_n959(x) + end +end + +def fun_l24_n151(x) + if (x < 1) + fun_l25_n65(x) + else + fun_l25_n654(x) + end +end + +def fun_l24_n152(x) + if (x < 1) + fun_l25_n465(x) + else + fun_l25_n24(x) + end +end + +def fun_l24_n153(x) + if (x < 1) + fun_l25_n254(x) + else + fun_l25_n611(x) + end +end + +def fun_l24_n154(x) + if (x < 1) + fun_l25_n525(x) + else + fun_l25_n25(x) + end +end + +def fun_l24_n155(x) + if (x < 1) + fun_l25_n967(x) + else + fun_l25_n163(x) + end +end + +def fun_l24_n156(x) + if (x < 1) + fun_l25_n191(x) + else + fun_l25_n603(x) + end +end + +def fun_l24_n157(x) + if (x < 1) + fun_l25_n724(x) + else + fun_l25_n537(x) + end +end + +def fun_l24_n158(x) + if (x < 1) + fun_l25_n115(x) + else + fun_l25_n967(x) + end +end + +def fun_l24_n159(x) + if (x < 1) + fun_l25_n247(x) + else + fun_l25_n650(x) + end +end + +def fun_l24_n160(x) + if (x < 1) + fun_l25_n681(x) + else + fun_l25_n754(x) + end +end + +def fun_l24_n161(x) + if (x < 1) + fun_l25_n689(x) + else + fun_l25_n283(x) + end +end + +def fun_l24_n162(x) + if (x < 1) + fun_l25_n697(x) + else + fun_l25_n262(x) + end +end + +def fun_l24_n163(x) + if (x < 1) + fun_l25_n584(x) + else + fun_l25_n502(x) + end +end + +def fun_l24_n164(x) + if (x < 1) + fun_l25_n949(x) + else + fun_l25_n738(x) + end +end + +def fun_l24_n165(x) + if (x < 1) + fun_l25_n847(x) + else + fun_l25_n317(x) + end +end + +def fun_l24_n166(x) + if (x < 1) + fun_l25_n827(x) + else + fun_l25_n831(x) + end +end + +def fun_l24_n167(x) + if (x < 1) + fun_l25_n400(x) + else + fun_l25_n60(x) + end +end + +def fun_l24_n168(x) + if (x < 1) + fun_l25_n411(x) + else + fun_l25_n333(x) + end +end + +def fun_l24_n169(x) + if (x < 1) + fun_l25_n481(x) + else + fun_l25_n336(x) + end +end + +def fun_l24_n170(x) + if (x < 1) + fun_l25_n551(x) + else + fun_l25_n184(x) + end +end + +def fun_l24_n171(x) + if (x < 1) + fun_l25_n700(x) + else + fun_l25_n542(x) + end +end + +def fun_l24_n172(x) + if (x < 1) + fun_l25_n496(x) + else + fun_l25_n494(x) + end +end + +def fun_l24_n173(x) + if (x < 1) + fun_l25_n684(x) + else + fun_l25_n865(x) + end +end + +def fun_l24_n174(x) + if (x < 1) + fun_l25_n304(x) + else + fun_l25_n641(x) + end +end + +def fun_l24_n175(x) + if (x < 1) + fun_l25_n252(x) + else + fun_l25_n573(x) + end +end + +def fun_l24_n176(x) + if (x < 1) + fun_l25_n463(x) + else + fun_l25_n596(x) + end +end + +def fun_l24_n177(x) + if (x < 1) + fun_l25_n864(x) + else + fun_l25_n810(x) + end +end + +def fun_l24_n178(x) + if (x < 1) + fun_l25_n182(x) + else + fun_l25_n900(x) + end +end + +def fun_l24_n179(x) + if (x < 1) + fun_l25_n678(x) + else + fun_l25_n299(x) + end +end + +def fun_l24_n180(x) + if (x < 1) + fun_l25_n423(x) + else + fun_l25_n791(x) + end +end + +def fun_l24_n181(x) + if (x < 1) + fun_l25_n582(x) + else + fun_l25_n382(x) + end +end + +def fun_l24_n182(x) + if (x < 1) + fun_l25_n498(x) + else + fun_l25_n247(x) + end +end + +def fun_l24_n183(x) + if (x < 1) + fun_l25_n534(x) + else + fun_l25_n504(x) + end +end + +def fun_l24_n184(x) + if (x < 1) + fun_l25_n947(x) + else + fun_l25_n708(x) + end +end + +def fun_l24_n185(x) + if (x < 1) + fun_l25_n673(x) + else + fun_l25_n711(x) + end +end + +def fun_l24_n186(x) + if (x < 1) + fun_l25_n155(x) + else + fun_l25_n233(x) + end +end + +def fun_l24_n187(x) + if (x < 1) + fun_l25_n669(x) + else + fun_l25_n558(x) + end +end + +def fun_l24_n188(x) + if (x < 1) + fun_l25_n307(x) + else + fun_l25_n839(x) + end +end + +def fun_l24_n189(x) + if (x < 1) + fun_l25_n623(x) + else + fun_l25_n17(x) + end +end + +def fun_l24_n190(x) + if (x < 1) + fun_l25_n468(x) + else + fun_l25_n391(x) + end +end + +def fun_l24_n191(x) + if (x < 1) + fun_l25_n492(x) + else + fun_l25_n953(x) + end +end + +def fun_l24_n192(x) + if (x < 1) + fun_l25_n644(x) + else + fun_l25_n724(x) + end +end + +def fun_l24_n193(x) + if (x < 1) + fun_l25_n438(x) + else + fun_l25_n110(x) + end +end + +def fun_l24_n194(x) + if (x < 1) + fun_l25_n763(x) + else + fun_l25_n0(x) + end +end + +def fun_l24_n195(x) + if (x < 1) + fun_l25_n766(x) + else + fun_l25_n436(x) + end +end + +def fun_l24_n196(x) + if (x < 1) + fun_l25_n646(x) + else + fun_l25_n264(x) + end +end + +def fun_l24_n197(x) + if (x < 1) + fun_l25_n140(x) + else + fun_l25_n387(x) + end +end + +def fun_l24_n198(x) + if (x < 1) + fun_l25_n890(x) + else + fun_l25_n756(x) + end +end + +def fun_l24_n199(x) + if (x < 1) + fun_l25_n597(x) + else + fun_l25_n330(x) + end +end + +def fun_l24_n200(x) + if (x < 1) + fun_l25_n656(x) + else + fun_l25_n292(x) + end +end + +def fun_l24_n201(x) + if (x < 1) + fun_l25_n224(x) + else + fun_l25_n233(x) + end +end + +def fun_l24_n202(x) + if (x < 1) + fun_l25_n153(x) + else + fun_l25_n926(x) + end +end + +def fun_l24_n203(x) + if (x < 1) + fun_l25_n897(x) + else + fun_l25_n680(x) + end +end + +def fun_l24_n204(x) + if (x < 1) + fun_l25_n610(x) + else + fun_l25_n154(x) + end +end + +def fun_l24_n205(x) + if (x < 1) + fun_l25_n307(x) + else + fun_l25_n451(x) + end +end + +def fun_l24_n206(x) + if (x < 1) + fun_l25_n138(x) + else + fun_l25_n875(x) + end +end + +def fun_l24_n207(x) + if (x < 1) + fun_l25_n306(x) + else + fun_l25_n474(x) + end +end + +def fun_l24_n208(x) + if (x < 1) + fun_l25_n771(x) + else + fun_l25_n105(x) + end +end + +def fun_l24_n209(x) + if (x < 1) + fun_l25_n120(x) + else + fun_l25_n961(x) + end +end + +def fun_l24_n210(x) + if (x < 1) + fun_l25_n455(x) + else + fun_l25_n244(x) + end +end + +def fun_l24_n211(x) + if (x < 1) + fun_l25_n93(x) + else + fun_l25_n31(x) + end +end + +def fun_l24_n212(x) + if (x < 1) + fun_l25_n69(x) + else + fun_l25_n39(x) + end +end + +def fun_l24_n213(x) + if (x < 1) + fun_l25_n379(x) + else + fun_l25_n482(x) + end +end + +def fun_l24_n214(x) + if (x < 1) + fun_l25_n839(x) + else + fun_l25_n669(x) + end +end + +def fun_l24_n215(x) + if (x < 1) + fun_l25_n27(x) + else + fun_l25_n46(x) + end +end + +def fun_l24_n216(x) + if (x < 1) + fun_l25_n290(x) + else + fun_l25_n908(x) + end +end + +def fun_l24_n217(x) + if (x < 1) + fun_l25_n618(x) + else + fun_l25_n242(x) + end +end + +def fun_l24_n218(x) + if (x < 1) + fun_l25_n42(x) + else + fun_l25_n674(x) + end +end + +def fun_l24_n219(x) + if (x < 1) + fun_l25_n510(x) + else + fun_l25_n963(x) + end +end + +def fun_l24_n220(x) + if (x < 1) + fun_l25_n345(x) + else + fun_l25_n666(x) + end +end + +def fun_l24_n221(x) + if (x < 1) + fun_l25_n548(x) + else + fun_l25_n424(x) + end +end + +def fun_l24_n222(x) + if (x < 1) + fun_l25_n387(x) + else + fun_l25_n30(x) + end +end + +def fun_l24_n223(x) + if (x < 1) + fun_l25_n124(x) + else + fun_l25_n374(x) + end +end + +def fun_l24_n224(x) + if (x < 1) + fun_l25_n200(x) + else + fun_l25_n108(x) + end +end + +def fun_l24_n225(x) + if (x < 1) + fun_l25_n462(x) + else + fun_l25_n11(x) + end +end + +def fun_l24_n226(x) + if (x < 1) + fun_l25_n930(x) + else + fun_l25_n791(x) + end +end + +def fun_l24_n227(x) + if (x < 1) + fun_l25_n10(x) + else + fun_l25_n447(x) + end +end + +def fun_l24_n228(x) + if (x < 1) + fun_l25_n858(x) + else + fun_l25_n472(x) + end +end + +def fun_l24_n229(x) + if (x < 1) + fun_l25_n409(x) + else + fun_l25_n228(x) + end +end + +def fun_l24_n230(x) + if (x < 1) + fun_l25_n82(x) + else + fun_l25_n665(x) + end +end + +def fun_l24_n231(x) + if (x < 1) + fun_l25_n148(x) + else + fun_l25_n174(x) + end +end + +def fun_l24_n232(x) + if (x < 1) + fun_l25_n785(x) + else + fun_l25_n996(x) + end +end + +def fun_l24_n233(x) + if (x < 1) + fun_l25_n827(x) + else + fun_l25_n393(x) + end +end + +def fun_l24_n234(x) + if (x < 1) + fun_l25_n619(x) + else + fun_l25_n361(x) + end +end + +def fun_l24_n235(x) + if (x < 1) + fun_l25_n52(x) + else + fun_l25_n420(x) + end +end + +def fun_l24_n236(x) + if (x < 1) + fun_l25_n355(x) + else + fun_l25_n561(x) + end +end + +def fun_l24_n237(x) + if (x < 1) + fun_l25_n36(x) + else + fun_l25_n885(x) + end +end + +def fun_l24_n238(x) + if (x < 1) + fun_l25_n15(x) + else + fun_l25_n19(x) + end +end + +def fun_l24_n239(x) + if (x < 1) + fun_l25_n137(x) + else + fun_l25_n34(x) + end +end + +def fun_l24_n240(x) + if (x < 1) + fun_l25_n776(x) + else + fun_l25_n199(x) + end +end + +def fun_l24_n241(x) + if (x < 1) + fun_l25_n904(x) + else + fun_l25_n396(x) + end +end + +def fun_l24_n242(x) + if (x < 1) + fun_l25_n122(x) + else + fun_l25_n720(x) + end +end + +def fun_l24_n243(x) + if (x < 1) + fun_l25_n513(x) + else + fun_l25_n429(x) + end +end + +def fun_l24_n244(x) + if (x < 1) + fun_l25_n289(x) + else + fun_l25_n265(x) + end +end + +def fun_l24_n245(x) + if (x < 1) + fun_l25_n334(x) + else + fun_l25_n42(x) + end +end + +def fun_l24_n246(x) + if (x < 1) + fun_l25_n55(x) + else + fun_l25_n67(x) + end +end + +def fun_l24_n247(x) + if (x < 1) + fun_l25_n648(x) + else + fun_l25_n38(x) + end +end + +def fun_l24_n248(x) + if (x < 1) + fun_l25_n904(x) + else + fun_l25_n732(x) + end +end + +def fun_l24_n249(x) + if (x < 1) + fun_l25_n243(x) + else + fun_l25_n704(x) + end +end + +def fun_l24_n250(x) + if (x < 1) + fun_l25_n513(x) + else + fun_l25_n326(x) + end +end + +def fun_l24_n251(x) + if (x < 1) + fun_l25_n122(x) + else + fun_l25_n617(x) + end +end + +def fun_l24_n252(x) + if (x < 1) + fun_l25_n837(x) + else + fun_l25_n891(x) + end +end + +def fun_l24_n253(x) + if (x < 1) + fun_l25_n39(x) + else + fun_l25_n318(x) + end +end + +def fun_l24_n254(x) + if (x < 1) + fun_l25_n79(x) + else + fun_l25_n195(x) + end +end + +def fun_l24_n255(x) + if (x < 1) + fun_l25_n671(x) + else + fun_l25_n485(x) + end +end + +def fun_l24_n256(x) + if (x < 1) + fun_l25_n775(x) + else + fun_l25_n187(x) + end +end + +def fun_l24_n257(x) + if (x < 1) + fun_l25_n150(x) + else + fun_l25_n740(x) + end +end + +def fun_l24_n258(x) + if (x < 1) + fun_l25_n131(x) + else + fun_l25_n960(x) + end +end + +def fun_l24_n259(x) + if (x < 1) + fun_l25_n608(x) + else + fun_l25_n931(x) + end +end + +def fun_l24_n260(x) + if (x < 1) + fun_l25_n846(x) + else + fun_l25_n278(x) + end +end + +def fun_l24_n261(x) + if (x < 1) + fun_l25_n532(x) + else + fun_l25_n432(x) + end +end + +def fun_l24_n262(x) + if (x < 1) + fun_l25_n367(x) + else + fun_l25_n847(x) + end +end + +def fun_l24_n263(x) + if (x < 1) + fun_l25_n782(x) + else + fun_l25_n33(x) + end +end + +def fun_l24_n264(x) + if (x < 1) + fun_l25_n822(x) + else + fun_l25_n711(x) + end +end + +def fun_l24_n265(x) + if (x < 1) + fun_l25_n994(x) + else + fun_l25_n573(x) + end +end + +def fun_l24_n266(x) + if (x < 1) + fun_l25_n234(x) + else + fun_l25_n617(x) + end +end + +def fun_l24_n267(x) + if (x < 1) + fun_l25_n52(x) + else + fun_l25_n759(x) + end +end + +def fun_l24_n268(x) + if (x < 1) + fun_l25_n161(x) + else + fun_l25_n167(x) + end +end + +def fun_l24_n269(x) + if (x < 1) + fun_l25_n113(x) + else + fun_l25_n158(x) + end +end + +def fun_l24_n270(x) + if (x < 1) + fun_l25_n151(x) + else + fun_l25_n127(x) + end +end + +def fun_l24_n271(x) + if (x < 1) + fun_l25_n811(x) + else + fun_l25_n81(x) + end +end + +def fun_l24_n272(x) + if (x < 1) + fun_l25_n622(x) + else + fun_l25_n796(x) + end +end + +def fun_l24_n273(x) + if (x < 1) + fun_l25_n106(x) + else + fun_l25_n697(x) + end +end + +def fun_l24_n274(x) + if (x < 1) + fun_l25_n63(x) + else + fun_l25_n599(x) + end +end + +def fun_l24_n275(x) + if (x < 1) + fun_l25_n999(x) + else + fun_l25_n188(x) + end +end + +def fun_l24_n276(x) + if (x < 1) + fun_l25_n491(x) + else + fun_l25_n614(x) + end +end + +def fun_l24_n277(x) + if (x < 1) + fun_l25_n549(x) + else + fun_l25_n141(x) + end +end + +def fun_l24_n278(x) + if (x < 1) + fun_l25_n442(x) + else + fun_l25_n900(x) + end +end + +def fun_l24_n279(x) + if (x < 1) + fun_l25_n816(x) + else + fun_l25_n904(x) + end +end + +def fun_l24_n280(x) + if (x < 1) + fun_l25_n508(x) + else + fun_l25_n569(x) + end +end + +def fun_l24_n281(x) + if (x < 1) + fun_l25_n438(x) + else + fun_l25_n750(x) + end +end + +def fun_l24_n282(x) + if (x < 1) + fun_l25_n984(x) + else + fun_l25_n573(x) + end +end + +def fun_l24_n283(x) + if (x < 1) + fun_l25_n425(x) + else + fun_l25_n963(x) + end +end + +def fun_l24_n284(x) + if (x < 1) + fun_l25_n213(x) + else + fun_l25_n344(x) + end +end + +def fun_l24_n285(x) + if (x < 1) + fun_l25_n1(x) + else + fun_l25_n826(x) + end +end + +def fun_l24_n286(x) + if (x < 1) + fun_l25_n297(x) + else + fun_l25_n266(x) + end +end + +def fun_l24_n287(x) + if (x < 1) + fun_l25_n203(x) + else + fun_l25_n570(x) + end +end + +def fun_l24_n288(x) + if (x < 1) + fun_l25_n849(x) + else + fun_l25_n336(x) + end +end + +def fun_l24_n289(x) + if (x < 1) + fun_l25_n982(x) + else + fun_l25_n38(x) + end +end + +def fun_l24_n290(x) + if (x < 1) + fun_l25_n687(x) + else + fun_l25_n906(x) + end +end + +def fun_l24_n291(x) + if (x < 1) + fun_l25_n921(x) + else + fun_l25_n229(x) + end +end + +def fun_l24_n292(x) + if (x < 1) + fun_l25_n494(x) + else + fun_l25_n138(x) + end +end + +def fun_l24_n293(x) + if (x < 1) + fun_l25_n175(x) + else + fun_l25_n575(x) + end +end + +def fun_l24_n294(x) + if (x < 1) + fun_l25_n126(x) + else + fun_l25_n902(x) + end +end + +def fun_l24_n295(x) + if (x < 1) + fun_l25_n634(x) + else + fun_l25_n199(x) + end +end + +def fun_l24_n296(x) + if (x < 1) + fun_l25_n929(x) + else + fun_l25_n468(x) + end +end + +def fun_l24_n297(x) + if (x < 1) + fun_l25_n856(x) + else + fun_l25_n135(x) + end +end + +def fun_l24_n298(x) + if (x < 1) + fun_l25_n655(x) + else + fun_l25_n545(x) + end +end + +def fun_l24_n299(x) + if (x < 1) + fun_l25_n373(x) + else + fun_l25_n173(x) + end +end + +def fun_l24_n300(x) + if (x < 1) + fun_l25_n874(x) + else + fun_l25_n85(x) + end +end + +def fun_l24_n301(x) + if (x < 1) + fun_l25_n398(x) + else + fun_l25_n43(x) + end +end + +def fun_l24_n302(x) + if (x < 1) + fun_l25_n995(x) + else + fun_l25_n890(x) + end +end + +def fun_l24_n303(x) + if (x < 1) + fun_l25_n971(x) + else + fun_l25_n250(x) + end +end + +def fun_l24_n304(x) + if (x < 1) + fun_l25_n752(x) + else + fun_l25_n681(x) + end +end + +def fun_l24_n305(x) + if (x < 1) + fun_l25_n688(x) + else + fun_l25_n451(x) + end +end + +def fun_l24_n306(x) + if (x < 1) + fun_l25_n167(x) + else + fun_l25_n784(x) + end +end + +def fun_l24_n307(x) + if (x < 1) + fun_l25_n479(x) + else + fun_l25_n295(x) + end +end + +def fun_l24_n308(x) + if (x < 1) + fun_l25_n779(x) + else + fun_l25_n472(x) + end +end + +def fun_l24_n309(x) + if (x < 1) + fun_l25_n10(x) + else + fun_l25_n301(x) + end +end + +def fun_l24_n310(x) + if (x < 1) + fun_l25_n197(x) + else + fun_l25_n152(x) + end +end + +def fun_l24_n311(x) + if (x < 1) + fun_l25_n300(x) + else + fun_l25_n105(x) + end +end + +def fun_l24_n312(x) + if (x < 1) + fun_l25_n1(x) + else + fun_l25_n956(x) + end +end + +def fun_l24_n313(x) + if (x < 1) + fun_l25_n310(x) + else + fun_l25_n701(x) + end +end + +def fun_l24_n314(x) + if (x < 1) + fun_l25_n0(x) + else + fun_l25_n58(x) + end +end + +def fun_l24_n315(x) + if (x < 1) + fun_l25_n31(x) + else + fun_l25_n69(x) + end +end + +def fun_l24_n316(x) + if (x < 1) + fun_l25_n967(x) + else + fun_l25_n130(x) + end +end + +def fun_l24_n317(x) + if (x < 1) + fun_l25_n995(x) + else + fun_l25_n630(x) + end +end + +def fun_l24_n318(x) + if (x < 1) + fun_l25_n349(x) + else + fun_l25_n916(x) + end +end + +def fun_l24_n319(x) + if (x < 1) + fun_l25_n230(x) + else + fun_l25_n880(x) + end +end + +def fun_l24_n320(x) + if (x < 1) + fun_l25_n452(x) + else + fun_l25_n316(x) + end +end + +def fun_l24_n321(x) + if (x < 1) + fun_l25_n581(x) + else + fun_l25_n262(x) + end +end + +def fun_l24_n322(x) + if (x < 1) + fun_l25_n70(x) + else + fun_l25_n674(x) + end +end + +def fun_l24_n323(x) + if (x < 1) + fun_l25_n726(x) + else + fun_l25_n943(x) + end +end + +def fun_l24_n324(x) + if (x < 1) + fun_l25_n779(x) + else + fun_l25_n209(x) + end +end + +def fun_l24_n325(x) + if (x < 1) + fun_l25_n132(x) + else + fun_l25_n301(x) + end +end + +def fun_l24_n326(x) + if (x < 1) + fun_l25_n255(x) + else + fun_l25_n154(x) + end +end + +def fun_l24_n327(x) + if (x < 1) + fun_l25_n248(x) + else + fun_l25_n152(x) + end +end + +def fun_l24_n328(x) + if (x < 1) + fun_l25_n536(x) + else + fun_l25_n703(x) + end +end + +def fun_l24_n329(x) + if (x < 1) + fun_l25_n744(x) + else + fun_l25_n133(x) + end +end + +def fun_l24_n330(x) + if (x < 1) + fun_l25_n455(x) + else + fun_l25_n576(x) + end +end + +def fun_l24_n331(x) + if (x < 1) + fun_l25_n590(x) + else + fun_l25_n357(x) + end +end + +def fun_l24_n332(x) + if (x < 1) + fun_l25_n151(x) + else + fun_l25_n969(x) + end +end + +def fun_l24_n333(x) + if (x < 1) + fun_l25_n725(x) + else + fun_l25_n681(x) + end +end + +def fun_l24_n334(x) + if (x < 1) + fun_l25_n157(x) + else + fun_l25_n643(x) + end +end + +def fun_l24_n335(x) + if (x < 1) + fun_l25_n42(x) + else + fun_l25_n749(x) + end +end + +def fun_l24_n336(x) + if (x < 1) + fun_l25_n831(x) + else + fun_l25_n126(x) + end +end + +def fun_l24_n337(x) + if (x < 1) + fun_l25_n424(x) + else + fun_l25_n559(x) + end +end + +def fun_l24_n338(x) + if (x < 1) + fun_l25_n897(x) + else + fun_l25_n89(x) + end +end + +def fun_l24_n339(x) + if (x < 1) + fun_l25_n755(x) + else + fun_l25_n506(x) + end +end + +def fun_l24_n340(x) + if (x < 1) + fun_l25_n387(x) + else + fun_l25_n631(x) + end +end + +def fun_l24_n341(x) + if (x < 1) + fun_l25_n694(x) + else + fun_l25_n707(x) + end +end + +def fun_l24_n342(x) + if (x < 1) + fun_l25_n65(x) + else + fun_l25_n687(x) + end +end + +def fun_l24_n343(x) + if (x < 1) + fun_l25_n84(x) + else + fun_l25_n738(x) + end +end + +def fun_l24_n344(x) + if (x < 1) + fun_l25_n729(x) + else + fun_l25_n639(x) + end +end + +def fun_l24_n345(x) + if (x < 1) + fun_l25_n102(x) + else + fun_l25_n299(x) + end +end + +def fun_l24_n346(x) + if (x < 1) + fun_l25_n604(x) + else + fun_l25_n94(x) + end +end + +def fun_l24_n347(x) + if (x < 1) + fun_l25_n93(x) + else + fun_l25_n975(x) + end +end + +def fun_l24_n348(x) + if (x < 1) + fun_l25_n124(x) + else + fun_l25_n927(x) + end +end + +def fun_l24_n349(x) + if (x < 1) + fun_l25_n944(x) + else + fun_l25_n162(x) + end +end + +def fun_l24_n350(x) + if (x < 1) + fun_l25_n623(x) + else + fun_l25_n5(x) + end +end + +def fun_l24_n351(x) + if (x < 1) + fun_l25_n885(x) + else + fun_l25_n884(x) + end +end + +def fun_l24_n352(x) + if (x < 1) + fun_l25_n1(x) + else + fun_l25_n366(x) + end +end + +def fun_l24_n353(x) + if (x < 1) + fun_l25_n240(x) + else + fun_l25_n630(x) + end +end + +def fun_l24_n354(x) + if (x < 1) + fun_l25_n232(x) + else + fun_l25_n758(x) + end +end + +def fun_l24_n355(x) + if (x < 1) + fun_l25_n529(x) + else + fun_l25_n810(x) + end +end + +def fun_l24_n356(x) + if (x < 1) + fun_l25_n438(x) + else + fun_l25_n146(x) + end +end + +def fun_l24_n357(x) + if (x < 1) + fun_l25_n551(x) + else + fun_l25_n727(x) + end +end + +def fun_l24_n358(x) + if (x < 1) + fun_l25_n764(x) + else + fun_l25_n379(x) + end +end + +def fun_l24_n359(x) + if (x < 1) + fun_l25_n89(x) + else + fun_l25_n518(x) + end +end + +def fun_l24_n360(x) + if (x < 1) + fun_l25_n567(x) + else + fun_l25_n98(x) + end +end + +def fun_l24_n361(x) + if (x < 1) + fun_l25_n26(x) + else + fun_l25_n818(x) + end +end + +def fun_l24_n362(x) + if (x < 1) + fun_l25_n205(x) + else + fun_l25_n460(x) + end +end + +def fun_l24_n363(x) + if (x < 1) + fun_l25_n19(x) + else + fun_l25_n134(x) + end +end + +def fun_l24_n364(x) + if (x < 1) + fun_l25_n221(x) + else + fun_l25_n391(x) + end +end + +def fun_l24_n365(x) + if (x < 1) + fun_l25_n546(x) + else + fun_l25_n62(x) + end +end + +def fun_l24_n366(x) + if (x < 1) + fun_l25_n412(x) + else + fun_l25_n593(x) + end +end + +def fun_l24_n367(x) + if (x < 1) + fun_l25_n576(x) + else + fun_l25_n798(x) + end +end + +def fun_l24_n368(x) + if (x < 1) + fun_l25_n528(x) + else + fun_l25_n575(x) + end +end + +def fun_l24_n369(x) + if (x < 1) + fun_l25_n914(x) + else + fun_l25_n417(x) + end +end + +def fun_l24_n370(x) + if (x < 1) + fun_l25_n397(x) + else + fun_l25_n684(x) + end +end + +def fun_l24_n371(x) + if (x < 1) + fun_l25_n827(x) + else + fun_l25_n677(x) + end +end + +def fun_l24_n372(x) + if (x < 1) + fun_l25_n256(x) + else + fun_l25_n841(x) + end +end + +def fun_l24_n373(x) + if (x < 1) + fun_l25_n671(x) + else + fun_l25_n712(x) + end +end + +def fun_l24_n374(x) + if (x < 1) + fun_l25_n696(x) + else + fun_l25_n598(x) + end +end + +def fun_l24_n375(x) + if (x < 1) + fun_l25_n384(x) + else + fun_l25_n426(x) + end +end + +def fun_l24_n376(x) + if (x < 1) + fun_l25_n578(x) + else + fun_l25_n555(x) + end +end + +def fun_l24_n377(x) + if (x < 1) + fun_l25_n290(x) + else + fun_l25_n480(x) + end +end + +def fun_l24_n378(x) + if (x < 1) + fun_l25_n481(x) + else + fun_l25_n647(x) + end +end + +def fun_l24_n379(x) + if (x < 1) + fun_l25_n502(x) + else + fun_l25_n985(x) + end +end + +def fun_l24_n380(x) + if (x < 1) + fun_l25_n275(x) + else + fun_l25_n575(x) + end +end + +def fun_l24_n381(x) + if (x < 1) + fun_l25_n901(x) + else + fun_l25_n396(x) + end +end + +def fun_l24_n382(x) + if (x < 1) + fun_l25_n283(x) + else + fun_l25_n544(x) + end +end + +def fun_l24_n383(x) + if (x < 1) + fun_l25_n192(x) + else + fun_l25_n953(x) + end +end + +def fun_l24_n384(x) + if (x < 1) + fun_l25_n862(x) + else + fun_l25_n264(x) + end +end + +def fun_l24_n385(x) + if (x < 1) + fun_l25_n528(x) + else + fun_l25_n429(x) + end +end + +def fun_l24_n386(x) + if (x < 1) + fun_l25_n29(x) + else + fun_l25_n831(x) + end +end + +def fun_l24_n387(x) + if (x < 1) + fun_l25_n152(x) + else + fun_l25_n902(x) + end +end + +def fun_l24_n388(x) + if (x < 1) + fun_l25_n538(x) + else + fun_l25_n468(x) + end +end + +def fun_l24_n389(x) + if (x < 1) + fun_l25_n772(x) + else + fun_l25_n105(x) + end +end + +def fun_l24_n390(x) + if (x < 1) + fun_l25_n875(x) + else + fun_l25_n723(x) + end +end + +def fun_l24_n391(x) + if (x < 1) + fun_l25_n330(x) + else + fun_l25_n659(x) + end +end + +def fun_l24_n392(x) + if (x < 1) + fun_l25_n168(x) + else + fun_l25_n68(x) + end +end + +def fun_l24_n393(x) + if (x < 1) + fun_l25_n481(x) + else + fun_l25_n200(x) + end +end + +def fun_l24_n394(x) + if (x < 1) + fun_l25_n391(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n395(x) + if (x < 1) + fun_l25_n383(x) + else + fun_l25_n250(x) + end +end + +def fun_l24_n396(x) + if (x < 1) + fun_l25_n537(x) + else + fun_l25_n283(x) + end +end + +def fun_l24_n397(x) + if (x < 1) + fun_l25_n504(x) + else + fun_l25_n916(x) + end +end + +def fun_l24_n398(x) + if (x < 1) + fun_l25_n992(x) + else + fun_l25_n504(x) + end +end + +def fun_l24_n399(x) + if (x < 1) + fun_l25_n294(x) + else + fun_l25_n412(x) + end +end + +def fun_l24_n400(x) + if (x < 1) + fun_l25_n686(x) + else + fun_l25_n85(x) + end +end + +def fun_l24_n401(x) + if (x < 1) + fun_l25_n874(x) + else + fun_l25_n980(x) + end +end + +def fun_l24_n402(x) + if (x < 1) + fun_l25_n454(x) + else + fun_l25_n867(x) + end +end + +def fun_l24_n403(x) + if (x < 1) + fun_l25_n594(x) + else + fun_l25_n970(x) + end +end + +def fun_l24_n404(x) + if (x < 1) + fun_l25_n281(x) + else + fun_l25_n881(x) + end +end + +def fun_l24_n405(x) + if (x < 1) + fun_l25_n713(x) + else + fun_l25_n530(x) + end +end + +def fun_l24_n406(x) + if (x < 1) + fun_l25_n874(x) + else + fun_l25_n953(x) + end +end + +def fun_l24_n407(x) + if (x < 1) + fun_l25_n569(x) + else + fun_l25_n991(x) + end +end + +def fun_l24_n408(x) + if (x < 1) + fun_l25_n875(x) + else + fun_l25_n409(x) + end +end + +def fun_l24_n409(x) + if (x < 1) + fun_l25_n604(x) + else + fun_l25_n454(x) + end +end + +def fun_l24_n410(x) + if (x < 1) + fun_l25_n267(x) + else + fun_l25_n100(x) + end +end + +def fun_l24_n411(x) + if (x < 1) + fun_l25_n966(x) + else + fun_l25_n537(x) + end +end + +def fun_l24_n412(x) + if (x < 1) + fun_l25_n261(x) + else + fun_l25_n106(x) + end +end + +def fun_l24_n413(x) + if (x < 1) + fun_l25_n869(x) + else + fun_l25_n890(x) + end +end + +def fun_l24_n414(x) + if (x < 1) + fun_l25_n784(x) + else + fun_l25_n147(x) + end +end + +def fun_l24_n415(x) + if (x < 1) + fun_l25_n6(x) + else + fun_l25_n808(x) + end +end + +def fun_l24_n416(x) + if (x < 1) + fun_l25_n940(x) + else + fun_l25_n680(x) + end +end + +def fun_l24_n417(x) + if (x < 1) + fun_l25_n3(x) + else + fun_l25_n799(x) + end +end + +def fun_l24_n418(x) + if (x < 1) + fun_l25_n196(x) + else + fun_l25_n785(x) + end +end + +def fun_l24_n419(x) + if (x < 1) + fun_l25_n786(x) + else + fun_l25_n607(x) + end +end + +def fun_l24_n420(x) + if (x < 1) + fun_l25_n720(x) + else + fun_l25_n74(x) + end +end + +def fun_l24_n421(x) + if (x < 1) + fun_l25_n962(x) + else + fun_l25_n489(x) + end +end + +def fun_l24_n422(x) + if (x < 1) + fun_l25_n231(x) + else + fun_l25_n878(x) + end +end + +def fun_l24_n423(x) + if (x < 1) + fun_l25_n720(x) + else + fun_l25_n988(x) + end +end + +def fun_l24_n424(x) + if (x < 1) + fun_l25_n883(x) + else + fun_l25_n510(x) + end +end + +def fun_l24_n425(x) + if (x < 1) + fun_l25_n443(x) + else + fun_l25_n533(x) + end +end + +def fun_l24_n426(x) + if (x < 1) + fun_l25_n541(x) + else + fun_l25_n747(x) + end +end + +def fun_l24_n427(x) + if (x < 1) + fun_l25_n308(x) + else + fun_l25_n373(x) + end +end + +def fun_l24_n428(x) + if (x < 1) + fun_l25_n484(x) + else + fun_l25_n632(x) + end +end + +def fun_l24_n429(x) + if (x < 1) + fun_l25_n777(x) + else + fun_l25_n128(x) + end +end + +def fun_l24_n430(x) + if (x < 1) + fun_l25_n729(x) + else + fun_l25_n644(x) + end +end + +def fun_l24_n431(x) + if (x < 1) + fun_l25_n330(x) + else + fun_l25_n947(x) + end +end + +def fun_l24_n432(x) + if (x < 1) + fun_l25_n929(x) + else + fun_l25_n80(x) + end +end + +def fun_l24_n433(x) + if (x < 1) + fun_l25_n269(x) + else + fun_l25_n307(x) + end +end + +def fun_l24_n434(x) + if (x < 1) + fun_l25_n824(x) + else + fun_l25_n451(x) + end +end + +def fun_l24_n435(x) + if (x < 1) + fun_l25_n93(x) + else + fun_l25_n198(x) + end +end + +def fun_l24_n436(x) + if (x < 1) + fun_l25_n359(x) + else + fun_l25_n412(x) + end +end + +def fun_l24_n437(x) + if (x < 1) + fun_l25_n427(x) + else + fun_l25_n321(x) + end +end + +def fun_l24_n438(x) + if (x < 1) + fun_l25_n765(x) + else + fun_l25_n223(x) + end +end + +def fun_l24_n439(x) + if (x < 1) + fun_l25_n918(x) + else + fun_l25_n902(x) + end +end + +def fun_l24_n440(x) + if (x < 1) + fun_l25_n320(x) + else + fun_l25_n428(x) + end +end + +def fun_l24_n441(x) + if (x < 1) + fun_l25_n159(x) + else + fun_l25_n857(x) + end +end + +def fun_l24_n442(x) + if (x < 1) + fun_l25_n505(x) + else + fun_l25_n565(x) + end +end + +def fun_l24_n443(x) + if (x < 1) + fun_l25_n214(x) + else + fun_l25_n861(x) + end +end + +def fun_l24_n444(x) + if (x < 1) + fun_l25_n185(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n445(x) + if (x < 1) + fun_l25_n198(x) + else + fun_l25_n314(x) + end +end + +def fun_l24_n446(x) + if (x < 1) + fun_l25_n334(x) + else + fun_l25_n633(x) + end +end + +def fun_l24_n447(x) + if (x < 1) + fun_l25_n972(x) + else + fun_l25_n671(x) + end +end + +def fun_l24_n448(x) + if (x < 1) + fun_l25_n608(x) + else + fun_l25_n720(x) + end +end + +def fun_l24_n449(x) + if (x < 1) + fun_l25_n71(x) + else + fun_l25_n479(x) + end +end + +def fun_l24_n450(x) + if (x < 1) + fun_l25_n689(x) + else + fun_l25_n716(x) + end +end + +def fun_l24_n451(x) + if (x < 1) + fun_l25_n696(x) + else + fun_l25_n453(x) + end +end + +def fun_l24_n452(x) + if (x < 1) + fun_l25_n804(x) + else + fun_l25_n508(x) + end +end + +def fun_l24_n453(x) + if (x < 1) + fun_l25_n32(x) + else + fun_l25_n180(x) + end +end + +def fun_l24_n454(x) + if (x < 1) + fun_l25_n493(x) + else + fun_l25_n200(x) + end +end + +def fun_l24_n455(x) + if (x < 1) + fun_l25_n763(x) + else + fun_l25_n362(x) + end +end + +def fun_l24_n456(x) + if (x < 1) + fun_l25_n488(x) + else + fun_l25_n202(x) + end +end + +def fun_l24_n457(x) + if (x < 1) + fun_l25_n752(x) + else + fun_l25_n670(x) + end +end + +def fun_l24_n458(x) + if (x < 1) + fun_l25_n462(x) + else + fun_l25_n457(x) + end +end + +def fun_l24_n459(x) + if (x < 1) + fun_l25_n266(x) + else + fun_l25_n455(x) + end +end + +def fun_l24_n460(x) + if (x < 1) + fun_l25_n173(x) + else + fun_l25_n873(x) + end +end + +def fun_l24_n461(x) + if (x < 1) + fun_l25_n127(x) + else + fun_l25_n213(x) + end +end + +def fun_l24_n462(x) + if (x < 1) + fun_l25_n579(x) + else + fun_l25_n44(x) + end +end + +def fun_l24_n463(x) + if (x < 1) + fun_l25_n68(x) + else + fun_l25_n989(x) + end +end + +def fun_l24_n464(x) + if (x < 1) + fun_l25_n826(x) + else + fun_l25_n883(x) + end +end + +def fun_l24_n465(x) + if (x < 1) + fun_l25_n855(x) + else + fun_l25_n131(x) + end +end + +def fun_l24_n466(x) + if (x < 1) + fun_l25_n923(x) + else + fun_l25_n433(x) + end +end + +def fun_l24_n467(x) + if (x < 1) + fun_l25_n84(x) + else + fun_l25_n648(x) + end +end + +def fun_l24_n468(x) + if (x < 1) + fun_l25_n53(x) + else + fun_l25_n766(x) + end +end + +def fun_l24_n469(x) + if (x < 1) + fun_l25_n689(x) + else + fun_l25_n201(x) + end +end + +def fun_l24_n470(x) + if (x < 1) + fun_l25_n361(x) + else + fun_l25_n459(x) + end +end + +def fun_l24_n471(x) + if (x < 1) + fun_l25_n550(x) + else + fun_l25_n522(x) + end +end + +def fun_l24_n472(x) + if (x < 1) + fun_l25_n128(x) + else + fun_l25_n417(x) + end +end + +def fun_l24_n473(x) + if (x < 1) + fun_l25_n600(x) + else + fun_l25_n137(x) + end +end + +def fun_l24_n474(x) + if (x < 1) + fun_l25_n72(x) + else + fun_l25_n548(x) + end +end + +def fun_l24_n475(x) + if (x < 1) + fun_l25_n879(x) + else + fun_l25_n376(x) + end +end + +def fun_l24_n476(x) + if (x < 1) + fun_l25_n822(x) + else + fun_l25_n695(x) + end +end + +def fun_l24_n477(x) + if (x < 1) + fun_l25_n991(x) + else + fun_l25_n208(x) + end +end + +def fun_l24_n478(x) + if (x < 1) + fun_l25_n17(x) + else + fun_l25_n332(x) + end +end + +def fun_l24_n479(x) + if (x < 1) + fun_l25_n353(x) + else + fun_l25_n438(x) + end +end + +def fun_l24_n480(x) + if (x < 1) + fun_l25_n109(x) + else + fun_l25_n360(x) + end +end + +def fun_l24_n481(x) + if (x < 1) + fun_l25_n57(x) + else + fun_l25_n417(x) + end +end + +def fun_l24_n482(x) + if (x < 1) + fun_l25_n903(x) + else + fun_l25_n486(x) + end +end + +def fun_l24_n483(x) + if (x < 1) + fun_l25_n677(x) + else + fun_l25_n77(x) + end +end + +def fun_l24_n484(x) + if (x < 1) + fun_l25_n117(x) + else + fun_l25_n582(x) + end +end + +def fun_l24_n485(x) + if (x < 1) + fun_l25_n454(x) + else + fun_l25_n198(x) + end +end + +def fun_l24_n486(x) + if (x < 1) + fun_l25_n779(x) + else + fun_l25_n301(x) + end +end + +def fun_l24_n487(x) + if (x < 1) + fun_l25_n3(x) + else + fun_l25_n363(x) + end +end + +def fun_l24_n488(x) + if (x < 1) + fun_l25_n84(x) + else + fun_l25_n793(x) + end +end + +def fun_l24_n489(x) + if (x < 1) + fun_l25_n344(x) + else + fun_l25_n342(x) + end +end + +def fun_l24_n490(x) + if (x < 1) + fun_l25_n365(x) + else + fun_l25_n546(x) + end +end + +def fun_l24_n491(x) + if (x < 1) + fun_l25_n431(x) + else + fun_l25_n193(x) + end +end + +def fun_l24_n492(x) + if (x < 1) + fun_l25_n763(x) + else + fun_l25_n174(x) + end +end + +def fun_l24_n493(x) + if (x < 1) + fun_l25_n231(x) + else + fun_l25_n435(x) + end +end + +def fun_l24_n494(x) + if (x < 1) + fun_l25_n408(x) + else + fun_l25_n848(x) + end +end + +def fun_l24_n495(x) + if (x < 1) + fun_l25_n955(x) + else + fun_l25_n232(x) + end +end + +def fun_l24_n496(x) + if (x < 1) + fun_l25_n72(x) + else + fun_l25_n11(x) + end +end + +def fun_l24_n497(x) + if (x < 1) + fun_l25_n196(x) + else + fun_l25_n180(x) + end +end + +def fun_l24_n498(x) + if (x < 1) + fun_l25_n102(x) + else + fun_l25_n360(x) + end +end + +def fun_l24_n499(x) + if (x < 1) + fun_l25_n755(x) + else + fun_l25_n760(x) + end +end + +def fun_l24_n500(x) + if (x < 1) + fun_l25_n676(x) + else + fun_l25_n825(x) + end +end + +def fun_l24_n501(x) + if (x < 1) + fun_l25_n203(x) + else + fun_l25_n731(x) + end +end + +def fun_l24_n502(x) + if (x < 1) + fun_l25_n551(x) + else + fun_l25_n165(x) + end +end + +def fun_l24_n503(x) + if (x < 1) + fun_l25_n702(x) + else + fun_l25_n779(x) + end +end + +def fun_l24_n504(x) + if (x < 1) + fun_l25_n525(x) + else + fun_l25_n846(x) + end +end + +def fun_l24_n505(x) + if (x < 1) + fun_l25_n97(x) + else + fun_l25_n331(x) + end +end + +def fun_l24_n506(x) + if (x < 1) + fun_l25_n572(x) + else + fun_l25_n759(x) + end +end + +def fun_l24_n507(x) + if (x < 1) + fun_l25_n402(x) + else + fun_l25_n460(x) + end +end + +def fun_l24_n508(x) + if (x < 1) + fun_l25_n640(x) + else + fun_l25_n833(x) + end +end + +def fun_l24_n509(x) + if (x < 1) + fun_l25_n190(x) + else + fun_l25_n524(x) + end +end + +def fun_l24_n510(x) + if (x < 1) + fun_l25_n307(x) + else + fun_l25_n92(x) + end +end + +def fun_l24_n511(x) + if (x < 1) + fun_l25_n444(x) + else + fun_l25_n593(x) + end +end + +def fun_l24_n512(x) + if (x < 1) + fun_l25_n684(x) + else + fun_l25_n163(x) + end +end + +def fun_l24_n513(x) + if (x < 1) + fun_l25_n998(x) + else + fun_l25_n582(x) + end +end + +def fun_l24_n514(x) + if (x < 1) + fun_l25_n767(x) + else + fun_l25_n557(x) + end +end + +def fun_l24_n515(x) + if (x < 1) + fun_l25_n893(x) + else + fun_l25_n179(x) + end +end + +def fun_l24_n516(x) + if (x < 1) + fun_l25_n726(x) + else + fun_l25_n651(x) + end +end + +def fun_l24_n517(x) + if (x < 1) + fun_l25_n57(x) + else + fun_l25_n454(x) + end +end + +def fun_l24_n518(x) + if (x < 1) + fun_l25_n598(x) + else + fun_l25_n554(x) + end +end + +def fun_l24_n519(x) + if (x < 1) + fun_l25_n437(x) + else + fun_l25_n349(x) + end +end + +def fun_l24_n520(x) + if (x < 1) + fun_l25_n754(x) + else + fun_l25_n259(x) + end +end + +def fun_l24_n521(x) + if (x < 1) + fun_l25_n856(x) + else + fun_l25_n155(x) + end +end + +def fun_l24_n522(x) + if (x < 1) + fun_l25_n607(x) + else + fun_l25_n751(x) + end +end + +def fun_l24_n523(x) + if (x < 1) + fun_l25_n510(x) + else + fun_l25_n297(x) + end +end + +def fun_l24_n524(x) + if (x < 1) + fun_l25_n433(x) + else + fun_l25_n102(x) + end +end + +def fun_l24_n525(x) + if (x < 1) + fun_l25_n173(x) + else + fun_l25_n487(x) + end +end + +def fun_l24_n526(x) + if (x < 1) + fun_l25_n716(x) + else + fun_l25_n230(x) + end +end + +def fun_l24_n527(x) + if (x < 1) + fun_l25_n511(x) + else + fun_l25_n272(x) + end +end + +def fun_l24_n528(x) + if (x < 1) + fun_l25_n974(x) + else + fun_l25_n954(x) + end +end + +def fun_l24_n529(x) + if (x < 1) + fun_l25_n92(x) + else + fun_l25_n704(x) + end +end + +def fun_l24_n530(x) + if (x < 1) + fun_l25_n117(x) + else + fun_l25_n725(x) + end +end + +def fun_l24_n531(x) + if (x < 1) + fun_l25_n817(x) + else + fun_l25_n6(x) + end +end + +def fun_l24_n532(x) + if (x < 1) + fun_l25_n27(x) + else + fun_l25_n438(x) + end +end + +def fun_l24_n533(x) + if (x < 1) + fun_l25_n964(x) + else + fun_l25_n291(x) + end +end + +def fun_l24_n534(x) + if (x < 1) + fun_l25_n786(x) + else + fun_l25_n871(x) + end +end + +def fun_l24_n535(x) + if (x < 1) + fun_l25_n79(x) + else + fun_l25_n786(x) + end +end + +def fun_l24_n536(x) + if (x < 1) + fun_l25_n403(x) + else + fun_l25_n78(x) + end +end + +def fun_l24_n537(x) + if (x < 1) + fun_l25_n20(x) + else + fun_l25_n239(x) + end +end + +def fun_l24_n538(x) + if (x < 1) + fun_l25_n818(x) + else + fun_l25_n917(x) + end +end + +def fun_l24_n539(x) + if (x < 1) + fun_l25_n598(x) + else + fun_l25_n708(x) + end +end + +def fun_l24_n540(x) + if (x < 1) + fun_l25_n802(x) + else + fun_l25_n208(x) + end +end + +def fun_l24_n541(x) + if (x < 1) + fun_l25_n962(x) + else + fun_l25_n487(x) + end +end + +def fun_l24_n542(x) + if (x < 1) + fun_l25_n690(x) + else + fun_l25_n503(x) + end +end + +def fun_l24_n543(x) + if (x < 1) + fun_l25_n548(x) + else + fun_l25_n295(x) + end +end + +def fun_l24_n544(x) + if (x < 1) + fun_l25_n373(x) + else + fun_l25_n896(x) + end +end + +def fun_l24_n545(x) + if (x < 1) + fun_l25_n759(x) + else + fun_l25_n171(x) + end +end + +def fun_l24_n546(x) + if (x < 1) + fun_l25_n269(x) + else + fun_l25_n153(x) + end +end + +def fun_l24_n547(x) + if (x < 1) + fun_l25_n489(x) + else + fun_l25_n628(x) + end +end + +def fun_l24_n548(x) + if (x < 1) + fun_l25_n540(x) + else + fun_l25_n7(x) + end +end + +def fun_l24_n549(x) + if (x < 1) + fun_l25_n916(x) + else + fun_l25_n365(x) + end +end + +def fun_l24_n550(x) + if (x < 1) + fun_l25_n377(x) + else + fun_l25_n420(x) + end +end + +def fun_l24_n551(x) + if (x < 1) + fun_l25_n331(x) + else + fun_l25_n568(x) + end +end + +def fun_l24_n552(x) + if (x < 1) + fun_l25_n348(x) + else + fun_l25_n934(x) + end +end + +def fun_l24_n553(x) + if (x < 1) + fun_l25_n676(x) + else + fun_l25_n142(x) + end +end + +def fun_l24_n554(x) + if (x < 1) + fun_l25_n913(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n555(x) + if (x < 1) + fun_l25_n873(x) + else + fun_l25_n951(x) + end +end + +def fun_l24_n556(x) + if (x < 1) + fun_l25_n300(x) + else + fun_l25_n969(x) + end +end + +def fun_l24_n557(x) + if (x < 1) + fun_l25_n674(x) + else + fun_l25_n290(x) + end +end + +def fun_l24_n558(x) + if (x < 1) + fun_l25_n323(x) + else + fun_l25_n325(x) + end +end + +def fun_l24_n559(x) + if (x < 1) + fun_l25_n547(x) + else + fun_l25_n207(x) + end +end + +def fun_l24_n560(x) + if (x < 1) + fun_l25_n858(x) + else + fun_l25_n304(x) + end +end + +def fun_l24_n561(x) + if (x < 1) + fun_l25_n831(x) + else + fun_l25_n840(x) + end +end + +def fun_l24_n562(x) + if (x < 1) + fun_l25_n174(x) + else + fun_l25_n162(x) + end +end + +def fun_l24_n563(x) + if (x < 1) + fun_l25_n662(x) + else + fun_l25_n676(x) + end +end + +def fun_l24_n564(x) + if (x < 1) + fun_l25_n474(x) + else + fun_l25_n173(x) + end +end + +def fun_l24_n565(x) + if (x < 1) + fun_l25_n232(x) + else + fun_l25_n57(x) + end +end + +def fun_l24_n566(x) + if (x < 1) + fun_l25_n615(x) + else + fun_l25_n944(x) + end +end + +def fun_l24_n567(x) + if (x < 1) + fun_l25_n586(x) + else + fun_l25_n183(x) + end +end + +def fun_l24_n568(x) + if (x < 1) + fun_l25_n758(x) + else + fun_l25_n376(x) + end +end + +def fun_l24_n569(x) + if (x < 1) + fun_l25_n755(x) + else + fun_l25_n903(x) + end +end + +def fun_l24_n570(x) + if (x < 1) + fun_l25_n562(x) + else + fun_l25_n843(x) + end +end + +def fun_l24_n571(x) + if (x < 1) + fun_l25_n369(x) + else + fun_l25_n712(x) + end +end + +def fun_l24_n572(x) + if (x < 1) + fun_l25_n183(x) + else + fun_l25_n273(x) + end +end + +def fun_l24_n573(x) + if (x < 1) + fun_l25_n150(x) + else + fun_l25_n309(x) + end +end + +def fun_l24_n574(x) + if (x < 1) + fun_l25_n485(x) + else + fun_l25_n20(x) + end +end + +def fun_l24_n575(x) + if (x < 1) + fun_l25_n325(x) + else + fun_l25_n770(x) + end +end + +def fun_l24_n576(x) + if (x < 1) + fun_l25_n528(x) + else + fun_l25_n529(x) + end +end + +def fun_l24_n577(x) + if (x < 1) + fun_l25_n557(x) + else + fun_l25_n416(x) + end +end + +def fun_l24_n578(x) + if (x < 1) + fun_l25_n501(x) + else + fun_l25_n81(x) + end +end + +def fun_l24_n579(x) + if (x < 1) + fun_l25_n355(x) + else + fun_l25_n391(x) + end +end + +def fun_l24_n580(x) + if (x < 1) + fun_l25_n665(x) + else + fun_l25_n656(x) + end +end + +def fun_l24_n581(x) + if (x < 1) + fun_l25_n496(x) + else + fun_l25_n933(x) + end +end + +def fun_l24_n582(x) + if (x < 1) + fun_l25_n71(x) + else + fun_l25_n815(x) + end +end + +def fun_l24_n583(x) + if (x < 1) + fun_l25_n488(x) + else + fun_l25_n587(x) + end +end + +def fun_l24_n584(x) + if (x < 1) + fun_l25_n909(x) + else + fun_l25_n673(x) + end +end + +def fun_l24_n585(x) + if (x < 1) + fun_l25_n452(x) + else + fun_l25_n774(x) + end +end + +def fun_l24_n586(x) + if (x < 1) + fun_l25_n376(x) + else + fun_l25_n855(x) + end +end + +def fun_l24_n587(x) + if (x < 1) + fun_l25_n452(x) + else + fun_l25_n331(x) + end +end + +def fun_l24_n588(x) + if (x < 1) + fun_l25_n718(x) + else + fun_l25_n496(x) + end +end + +def fun_l24_n589(x) + if (x < 1) + fun_l25_n923(x) + else + fun_l25_n633(x) + end +end + +def fun_l24_n590(x) + if (x < 1) + fun_l25_n815(x) + else + fun_l25_n633(x) + end +end + +def fun_l24_n591(x) + if (x < 1) + fun_l25_n699(x) + else + fun_l25_n609(x) + end +end + +def fun_l24_n592(x) + if (x < 1) + fun_l25_n722(x) + else + fun_l25_n884(x) + end +end + +def fun_l24_n593(x) + if (x < 1) + fun_l25_n580(x) + else + fun_l25_n48(x) + end +end + +def fun_l24_n594(x) + if (x < 1) + fun_l25_n245(x) + else + fun_l25_n126(x) + end +end + +def fun_l24_n595(x) + if (x < 1) + fun_l25_n778(x) + else + fun_l25_n989(x) + end +end + +def fun_l24_n596(x) + if (x < 1) + fun_l25_n813(x) + else + fun_l25_n117(x) + end +end + +def fun_l24_n597(x) + if (x < 1) + fun_l25_n622(x) + else + fun_l25_n293(x) + end +end + +def fun_l24_n598(x) + if (x < 1) + fun_l25_n996(x) + else + fun_l25_n704(x) + end +end + +def fun_l24_n599(x) + if (x < 1) + fun_l25_n173(x) + else + fun_l25_n336(x) + end +end + +def fun_l24_n600(x) + if (x < 1) + fun_l25_n295(x) + else + fun_l25_n293(x) + end +end + +def fun_l24_n601(x) + if (x < 1) + fun_l25_n104(x) + else + fun_l25_n907(x) + end +end + +def fun_l24_n602(x) + if (x < 1) + fun_l25_n136(x) + else + fun_l25_n915(x) + end +end + +def fun_l24_n603(x) + if (x < 1) + fun_l25_n19(x) + else + fun_l25_n113(x) + end +end + +def fun_l24_n604(x) + if (x < 1) + fun_l25_n389(x) + else + fun_l25_n863(x) + end +end + +def fun_l24_n605(x) + if (x < 1) + fun_l25_n20(x) + else + fun_l25_n830(x) + end +end + +def fun_l24_n606(x) + if (x < 1) + fun_l25_n723(x) + else + fun_l25_n956(x) + end +end + +def fun_l24_n607(x) + if (x < 1) + fun_l25_n765(x) + else + fun_l25_n27(x) + end +end + +def fun_l24_n608(x) + if (x < 1) + fun_l25_n682(x) + else + fun_l25_n953(x) + end +end + +def fun_l24_n609(x) + if (x < 1) + fun_l25_n501(x) + else + fun_l25_n81(x) + end +end + +def fun_l24_n610(x) + if (x < 1) + fun_l25_n896(x) + else + fun_l25_n192(x) + end +end + +def fun_l24_n611(x) + if (x < 1) + fun_l25_n605(x) + else + fun_l25_n443(x) + end +end + +def fun_l24_n612(x) + if (x < 1) + fun_l25_n298(x) + else + fun_l25_n818(x) + end +end + +def fun_l24_n613(x) + if (x < 1) + fun_l25_n289(x) + else + fun_l25_n227(x) + end +end + +def fun_l24_n614(x) + if (x < 1) + fun_l25_n511(x) + else + fun_l25_n460(x) + end +end + +def fun_l24_n615(x) + if (x < 1) + fun_l25_n774(x) + else + fun_l25_n794(x) + end +end + +def fun_l24_n616(x) + if (x < 1) + fun_l25_n933(x) + else + fun_l25_n448(x) + end +end + +def fun_l24_n617(x) + if (x < 1) + fun_l25_n239(x) + else + fun_l25_n156(x) + end +end + +def fun_l24_n618(x) + if (x < 1) + fun_l25_n713(x) + else + fun_l25_n337(x) + end +end + +def fun_l24_n619(x) + if (x < 1) + fun_l25_n450(x) + else + fun_l25_n282(x) + end +end + +def fun_l24_n620(x) + if (x < 1) + fun_l25_n97(x) + else + fun_l25_n360(x) + end +end + +def fun_l24_n621(x) + if (x < 1) + fun_l25_n197(x) + else + fun_l25_n406(x) + end +end + +def fun_l24_n622(x) + if (x < 1) + fun_l25_n791(x) + else + fun_l25_n876(x) + end +end + +def fun_l24_n623(x) + if (x < 1) + fun_l25_n989(x) + else + fun_l25_n616(x) + end +end + +def fun_l24_n624(x) + if (x < 1) + fun_l25_n754(x) + else + fun_l25_n605(x) + end +end + +def fun_l24_n625(x) + if (x < 1) + fun_l25_n113(x) + else + fun_l25_n400(x) + end +end + +def fun_l24_n626(x) + if (x < 1) + fun_l25_n6(x) + else + fun_l25_n742(x) + end +end + +def fun_l24_n627(x) + if (x < 1) + fun_l25_n916(x) + else + fun_l25_n5(x) + end +end + +def fun_l24_n628(x) + if (x < 1) + fun_l25_n5(x) + else + fun_l25_n327(x) + end +end + +def fun_l24_n629(x) + if (x < 1) + fun_l25_n867(x) + else + fun_l25_n37(x) + end +end + +def fun_l24_n630(x) + if (x < 1) + fun_l25_n409(x) + else + fun_l25_n137(x) + end +end + +def fun_l24_n631(x) + if (x < 1) + fun_l25_n128(x) + else + fun_l25_n499(x) + end +end + +def fun_l24_n632(x) + if (x < 1) + fun_l25_n694(x) + else + fun_l25_n983(x) + end +end + +def fun_l24_n633(x) + if (x < 1) + fun_l25_n62(x) + else + fun_l25_n538(x) + end +end + +def fun_l24_n634(x) + if (x < 1) + fun_l25_n740(x) + else + fun_l25_n795(x) + end +end + +def fun_l24_n635(x) + if (x < 1) + fun_l25_n597(x) + else + fun_l25_n557(x) + end +end + +def fun_l24_n636(x) + if (x < 1) + fun_l25_n642(x) + else + fun_l25_n40(x) + end +end + +def fun_l24_n637(x) + if (x < 1) + fun_l25_n303(x) + else + fun_l25_n931(x) + end +end + +def fun_l24_n638(x) + if (x < 1) + fun_l25_n977(x) + else + fun_l25_n848(x) + end +end + +def fun_l24_n639(x) + if (x < 1) + fun_l25_n983(x) + else + fun_l25_n11(x) + end +end + +def fun_l24_n640(x) + if (x < 1) + fun_l25_n258(x) + else + fun_l25_n280(x) + end +end + +def fun_l24_n641(x) + if (x < 1) + fun_l25_n553(x) + else + fun_l25_n351(x) + end +end + +def fun_l24_n642(x) + if (x < 1) + fun_l25_n4(x) + else + fun_l25_n375(x) + end +end + +def fun_l24_n643(x) + if (x < 1) + fun_l25_n678(x) + else + fun_l25_n139(x) + end +end + +def fun_l24_n644(x) + if (x < 1) + fun_l25_n193(x) + else + fun_l25_n490(x) + end +end + +def fun_l24_n645(x) + if (x < 1) + fun_l25_n146(x) + else + fun_l25_n450(x) + end +end + +def fun_l24_n646(x) + if (x < 1) + fun_l25_n813(x) + else + fun_l25_n59(x) + end +end + +def fun_l24_n647(x) + if (x < 1) + fun_l25_n726(x) + else + fun_l25_n792(x) + end +end + +def fun_l24_n648(x) + if (x < 1) + fun_l25_n508(x) + else + fun_l25_n496(x) + end +end + +def fun_l24_n649(x) + if (x < 1) + fun_l25_n231(x) + else + fun_l25_n688(x) + end +end + +def fun_l24_n650(x) + if (x < 1) + fun_l25_n602(x) + else + fun_l25_n641(x) + end +end + +def fun_l24_n651(x) + if (x < 1) + fun_l25_n101(x) + else + fun_l25_n394(x) + end +end + +def fun_l24_n652(x) + if (x < 1) + fun_l25_n454(x) + else + fun_l25_n466(x) + end +end + +def fun_l24_n653(x) + if (x < 1) + fun_l25_n147(x) + else + fun_l25_n116(x) + end +end + +def fun_l24_n654(x) + if (x < 1) + fun_l25_n83(x) + else + fun_l25_n951(x) + end +end + +def fun_l24_n655(x) + if (x < 1) + fun_l25_n667(x) + else + fun_l25_n293(x) + end +end + +def fun_l24_n656(x) + if (x < 1) + fun_l25_n413(x) + else + fun_l25_n708(x) + end +end + +def fun_l24_n657(x) + if (x < 1) + fun_l25_n495(x) + else + fun_l25_n277(x) + end +end + +def fun_l24_n658(x) + if (x < 1) + fun_l25_n926(x) + else + fun_l25_n624(x) + end +end + +def fun_l24_n659(x) + if (x < 1) + fun_l25_n612(x) + else + fun_l25_n666(x) + end +end + +def fun_l24_n660(x) + if (x < 1) + fun_l25_n32(x) + else + fun_l25_n290(x) + end +end + +def fun_l24_n661(x) + if (x < 1) + fun_l25_n674(x) + else + fun_l25_n937(x) + end +end + +def fun_l24_n662(x) + if (x < 1) + fun_l25_n556(x) + else + fun_l25_n576(x) + end +end + +def fun_l24_n663(x) + if (x < 1) + fun_l25_n763(x) + else + fun_l25_n898(x) + end +end + +def fun_l24_n664(x) + if (x < 1) + fun_l25_n564(x) + else + fun_l25_n478(x) + end +end + +def fun_l24_n665(x) + if (x < 1) + fun_l25_n515(x) + else + fun_l25_n991(x) + end +end + +def fun_l24_n666(x) + if (x < 1) + fun_l25_n737(x) + else + fun_l25_n936(x) + end +end + +def fun_l24_n667(x) + if (x < 1) + fun_l25_n829(x) + else + fun_l25_n350(x) + end +end + +def fun_l24_n668(x) + if (x < 1) + fun_l25_n59(x) + else + fun_l25_n979(x) + end +end + +def fun_l24_n669(x) + if (x < 1) + fun_l25_n866(x) + else + fun_l25_n624(x) + end +end + +def fun_l24_n670(x) + if (x < 1) + fun_l25_n572(x) + else + fun_l25_n203(x) + end +end + +def fun_l24_n671(x) + if (x < 1) + fun_l25_n96(x) + else + fun_l25_n862(x) + end +end + +def fun_l24_n672(x) + if (x < 1) + fun_l25_n979(x) + else + fun_l25_n484(x) + end +end + +def fun_l24_n673(x) + if (x < 1) + fun_l25_n20(x) + else + fun_l25_n201(x) + end +end + +def fun_l24_n674(x) + if (x < 1) + fun_l25_n109(x) + else + fun_l25_n788(x) + end +end + +def fun_l24_n675(x) + if (x < 1) + fun_l25_n792(x) + else + fun_l25_n132(x) + end +end + +def fun_l24_n676(x) + if (x < 1) + fun_l25_n786(x) + else + fun_l25_n77(x) + end +end + +def fun_l24_n677(x) + if (x < 1) + fun_l25_n21(x) + else + fun_l25_n96(x) + end +end + +def fun_l24_n678(x) + if (x < 1) + fun_l25_n299(x) + else + fun_l25_n649(x) + end +end + +def fun_l24_n679(x) + if (x < 1) + fun_l25_n247(x) + else + fun_l25_n607(x) + end +end + +def fun_l24_n680(x) + if (x < 1) + fun_l25_n480(x) + else + fun_l25_n471(x) + end +end + +def fun_l24_n681(x) + if (x < 1) + fun_l25_n277(x) + else + fun_l25_n460(x) + end +end + +def fun_l24_n682(x) + if (x < 1) + fun_l25_n573(x) + else + fun_l25_n193(x) + end +end + +def fun_l24_n683(x) + if (x < 1) + fun_l25_n741(x) + else + fun_l25_n441(x) + end +end + +def fun_l24_n684(x) + if (x < 1) + fun_l25_n821(x) + else + fun_l25_n24(x) + end +end + +def fun_l24_n685(x) + if (x < 1) + fun_l25_n150(x) + else + fun_l25_n530(x) + end +end + +def fun_l24_n686(x) + if (x < 1) + fun_l25_n564(x) + else + fun_l25_n26(x) + end +end + +def fun_l24_n687(x) + if (x < 1) + fun_l25_n872(x) + else + fun_l25_n522(x) + end +end + +def fun_l24_n688(x) + if (x < 1) + fun_l25_n963(x) + else + fun_l25_n422(x) + end +end + +def fun_l24_n689(x) + if (x < 1) + fun_l25_n418(x) + else + fun_l25_n900(x) + end +end + +def fun_l24_n690(x) + if (x < 1) + fun_l25_n117(x) + else + fun_l25_n900(x) + end +end + +def fun_l24_n691(x) + if (x < 1) + fun_l25_n412(x) + else + fun_l25_n466(x) + end +end + +def fun_l24_n692(x) + if (x < 1) + fun_l25_n761(x) + else + fun_l25_n190(x) + end +end + +def fun_l24_n693(x) + if (x < 1) + fun_l25_n875(x) + else + fun_l25_n222(x) + end +end + +def fun_l24_n694(x) + if (x < 1) + fun_l25_n405(x) + else + fun_l25_n66(x) + end +end + +def fun_l24_n695(x) + if (x < 1) + fun_l25_n570(x) + else + fun_l25_n801(x) + end +end + +def fun_l24_n696(x) + if (x < 1) + fun_l25_n591(x) + else + fun_l25_n121(x) + end +end + +def fun_l24_n697(x) + if (x < 1) + fun_l25_n27(x) + else + fun_l25_n610(x) + end +end + +def fun_l24_n698(x) + if (x < 1) + fun_l25_n843(x) + else + fun_l25_n488(x) + end +end + +def fun_l24_n699(x) + if (x < 1) + fun_l25_n946(x) + else + fun_l25_n164(x) + end +end + +def fun_l24_n700(x) + if (x < 1) + fun_l25_n424(x) + else + fun_l25_n614(x) + end +end + +def fun_l24_n701(x) + if (x < 1) + fun_l25_n692(x) + else + fun_l25_n893(x) + end +end + +def fun_l24_n702(x) + if (x < 1) + fun_l25_n39(x) + else + fun_l25_n274(x) + end +end + +def fun_l24_n703(x) + if (x < 1) + fun_l25_n814(x) + else + fun_l25_n281(x) + end +end + +def fun_l24_n704(x) + if (x < 1) + fun_l25_n670(x) + else + fun_l25_n882(x) + end +end + +def fun_l24_n705(x) + if (x < 1) + fun_l25_n498(x) + else + fun_l25_n881(x) + end +end + +def fun_l24_n706(x) + if (x < 1) + fun_l25_n193(x) + else + fun_l25_n10(x) + end +end + +def fun_l24_n707(x) + if (x < 1) + fun_l25_n531(x) + else + fun_l25_n870(x) + end +end + +def fun_l24_n708(x) + if (x < 1) + fun_l25_n106(x) + else + fun_l25_n692(x) + end +end + +def fun_l24_n709(x) + if (x < 1) + fun_l25_n484(x) + else + fun_l25_n700(x) + end +end + +def fun_l24_n710(x) + if (x < 1) + fun_l25_n699(x) + else + fun_l25_n117(x) + end +end + +def fun_l24_n711(x) + if (x < 1) + fun_l25_n138(x) + else + fun_l25_n532(x) + end +end + +def fun_l24_n712(x) + if (x < 1) + fun_l25_n468(x) + else + fun_l25_n350(x) + end +end + +def fun_l24_n713(x) + if (x < 1) + fun_l25_n906(x) + else + fun_l25_n25(x) + end +end + +def fun_l24_n714(x) + if (x < 1) + fun_l25_n23(x) + else + fun_l25_n745(x) + end +end + +def fun_l24_n715(x) + if (x < 1) + fun_l25_n917(x) + else + fun_l25_n942(x) + end +end + +def fun_l24_n716(x) + if (x < 1) + fun_l25_n986(x) + else + fun_l25_n605(x) + end +end + +def fun_l24_n717(x) + if (x < 1) + fun_l25_n771(x) + else + fun_l25_n100(x) + end +end + +def fun_l24_n718(x) + if (x < 1) + fun_l25_n994(x) + else + fun_l25_n249(x) + end +end + +def fun_l24_n719(x) + if (x < 1) + fun_l25_n368(x) + else + fun_l25_n657(x) + end +end + +def fun_l24_n720(x) + if (x < 1) + fun_l25_n856(x) + else + fun_l25_n650(x) + end +end + +def fun_l24_n721(x) + if (x < 1) + fun_l25_n667(x) + else + fun_l25_n609(x) + end +end + +def fun_l24_n722(x) + if (x < 1) + fun_l25_n353(x) + else + fun_l25_n665(x) + end +end + +def fun_l24_n723(x) + if (x < 1) + fun_l25_n520(x) + else + fun_l25_n771(x) + end +end + +def fun_l24_n724(x) + if (x < 1) + fun_l25_n636(x) + else + fun_l25_n34(x) + end +end + +def fun_l24_n725(x) + if (x < 1) + fun_l25_n222(x) + else + fun_l25_n444(x) + end +end + +def fun_l24_n726(x) + if (x < 1) + fun_l25_n519(x) + else + fun_l25_n675(x) + end +end + +def fun_l24_n727(x) + if (x < 1) + fun_l25_n739(x) + else + fun_l25_n910(x) + end +end + +def fun_l24_n728(x) + if (x < 1) + fun_l25_n669(x) + else + fun_l25_n645(x) + end +end + +def fun_l24_n729(x) + if (x < 1) + fun_l25_n358(x) + else + fun_l25_n316(x) + end +end + +def fun_l24_n730(x) + if (x < 1) + fun_l25_n614(x) + else + fun_l25_n484(x) + end +end + +def fun_l24_n731(x) + if (x < 1) + fun_l25_n640(x) + else + fun_l25_n613(x) + end +end + +def fun_l24_n732(x) + if (x < 1) + fun_l25_n16(x) + else + fun_l25_n596(x) + end +end + +def fun_l24_n733(x) + if (x < 1) + fun_l25_n780(x) + else + fun_l25_n673(x) + end +end + +def fun_l24_n734(x) + if (x < 1) + fun_l25_n999(x) + else + fun_l25_n210(x) + end +end + +def fun_l24_n735(x) + if (x < 1) + fun_l25_n915(x) + else + fun_l25_n788(x) + end +end + +def fun_l24_n736(x) + if (x < 1) + fun_l25_n484(x) + else + fun_l25_n369(x) + end +end + +def fun_l24_n737(x) + if (x < 1) + fun_l25_n851(x) + else + fun_l25_n674(x) + end +end + +def fun_l24_n738(x) + if (x < 1) + fun_l25_n830(x) + else + fun_l25_n382(x) + end +end + +def fun_l24_n739(x) + if (x < 1) + fun_l25_n861(x) + else + fun_l25_n482(x) + end +end + +def fun_l24_n740(x) + if (x < 1) + fun_l25_n244(x) + else + fun_l25_n414(x) + end +end + +def fun_l24_n741(x) + if (x < 1) + fun_l25_n829(x) + else + fun_l25_n846(x) + end +end + +def fun_l24_n742(x) + if (x < 1) + fun_l25_n197(x) + else + fun_l25_n943(x) + end +end + +def fun_l24_n743(x) + if (x < 1) + fun_l25_n290(x) + else + fun_l25_n394(x) + end +end + +def fun_l24_n744(x) + if (x < 1) + fun_l25_n965(x) + else + fun_l25_n987(x) + end +end + +def fun_l24_n745(x) + if (x < 1) + fun_l25_n104(x) + else + fun_l25_n369(x) + end +end + +def fun_l24_n746(x) + if (x < 1) + fun_l25_n880(x) + else + fun_l25_n541(x) + end +end + +def fun_l24_n747(x) + if (x < 1) + fun_l25_n345(x) + else + fun_l25_n155(x) + end +end + +def fun_l24_n748(x) + if (x < 1) + fun_l25_n803(x) + else + fun_l25_n383(x) + end +end + +def fun_l24_n749(x) + if (x < 1) + fun_l25_n848(x) + else + fun_l25_n340(x) + end +end + +def fun_l24_n750(x) + if (x < 1) + fun_l25_n197(x) + else + fun_l25_n313(x) + end +end + +def fun_l24_n751(x) + if (x < 1) + fun_l25_n253(x) + else + fun_l25_n99(x) + end +end + +def fun_l24_n752(x) + if (x < 1) + fun_l25_n873(x) + else + fun_l25_n347(x) + end +end + +def fun_l24_n753(x) + if (x < 1) + fun_l25_n849(x) + else + fun_l25_n627(x) + end +end + +def fun_l24_n754(x) + if (x < 1) + fun_l25_n817(x) + else + fun_l25_n441(x) + end +end + +def fun_l24_n755(x) + if (x < 1) + fun_l25_n235(x) + else + fun_l25_n602(x) + end +end + +def fun_l24_n756(x) + if (x < 1) + fun_l25_n950(x) + else + fun_l25_n516(x) + end +end + +def fun_l24_n757(x) + if (x < 1) + fun_l25_n646(x) + else + fun_l25_n996(x) + end +end + +def fun_l24_n758(x) + if (x < 1) + fun_l25_n27(x) + else + fun_l25_n650(x) + end +end + +def fun_l24_n759(x) + if (x < 1) + fun_l25_n290(x) + else + fun_l25_n852(x) + end +end + +def fun_l24_n760(x) + if (x < 1) + fun_l25_n118(x) + else + fun_l25_n871(x) + end +end + +def fun_l24_n761(x) + if (x < 1) + fun_l25_n372(x) + else + fun_l25_n537(x) + end +end + +def fun_l24_n762(x) + if (x < 1) + fun_l25_n124(x) + else + fun_l25_n939(x) + end +end + +def fun_l24_n763(x) + if (x < 1) + fun_l25_n163(x) + else + fun_l25_n787(x) + end +end + +def fun_l24_n764(x) + if (x < 1) + fun_l25_n485(x) + else + fun_l25_n753(x) + end +end + +def fun_l24_n765(x) + if (x < 1) + fun_l25_n181(x) + else + fun_l25_n595(x) + end +end + +def fun_l24_n766(x) + if (x < 1) + fun_l25_n909(x) + else + fun_l25_n734(x) + end +end + +def fun_l24_n767(x) + if (x < 1) + fun_l25_n980(x) + else + fun_l25_n673(x) + end +end + +def fun_l24_n768(x) + if (x < 1) + fun_l25_n756(x) + else + fun_l25_n429(x) + end +end + +def fun_l24_n769(x) + if (x < 1) + fun_l25_n301(x) + else + fun_l25_n197(x) + end +end + +def fun_l24_n770(x) + if (x < 1) + fun_l25_n977(x) + else + fun_l25_n569(x) + end +end + +def fun_l24_n771(x) + if (x < 1) + fun_l25_n829(x) + else + fun_l25_n34(x) + end +end + +def fun_l24_n772(x) + if (x < 1) + fun_l25_n601(x) + else + fun_l25_n762(x) + end +end + +def fun_l24_n773(x) + if (x < 1) + fun_l25_n790(x) + else + fun_l25_n282(x) + end +end + +def fun_l24_n774(x) + if (x < 1) + fun_l25_n464(x) + else + fun_l25_n814(x) + end +end + +def fun_l24_n775(x) + if (x < 1) + fun_l25_n562(x) + else + fun_l25_n543(x) + end +end + +def fun_l24_n776(x) + if (x < 1) + fun_l25_n869(x) + else + fun_l25_n857(x) + end +end + +def fun_l24_n777(x) + if (x < 1) + fun_l25_n206(x) + else + fun_l25_n369(x) + end +end + +def fun_l24_n778(x) + if (x < 1) + fun_l25_n43(x) + else + fun_l25_n405(x) + end +end + +def fun_l24_n779(x) + if (x < 1) + fun_l25_n116(x) + else + fun_l25_n644(x) + end +end + +def fun_l24_n780(x) + if (x < 1) + fun_l25_n455(x) + else + fun_l25_n174(x) + end +end + +def fun_l24_n781(x) + if (x < 1) + fun_l25_n234(x) + else + fun_l25_n887(x) + end +end + +def fun_l24_n782(x) + if (x < 1) + fun_l25_n157(x) + else + fun_l25_n459(x) + end +end + +def fun_l24_n783(x) + if (x < 1) + fun_l25_n441(x) + else + fun_l25_n830(x) + end +end + +def fun_l24_n784(x) + if (x < 1) + fun_l25_n908(x) + else + fun_l25_n363(x) + end +end + +def fun_l24_n785(x) + if (x < 1) + fun_l25_n495(x) + else + fun_l25_n790(x) + end +end + +def fun_l24_n786(x) + if (x < 1) + fun_l25_n365(x) + else + fun_l25_n561(x) + end +end + +def fun_l24_n787(x) + if (x < 1) + fun_l25_n419(x) + else + fun_l25_n471(x) + end +end + +def fun_l24_n788(x) + if (x < 1) + fun_l25_n568(x) + else + fun_l25_n807(x) + end +end + +def fun_l24_n789(x) + if (x < 1) + fun_l25_n148(x) + else + fun_l25_n476(x) + end +end + +def fun_l24_n790(x) + if (x < 1) + fun_l25_n470(x) + else + fun_l25_n662(x) + end +end + +def fun_l24_n791(x) + if (x < 1) + fun_l25_n307(x) + else + fun_l25_n828(x) + end +end + +def fun_l24_n792(x) + if (x < 1) + fun_l25_n227(x) + else + fun_l25_n802(x) + end +end + +def fun_l24_n793(x) + if (x < 1) + fun_l25_n891(x) + else + fun_l25_n561(x) + end +end + +def fun_l24_n794(x) + if (x < 1) + fun_l25_n465(x) + else + fun_l25_n805(x) + end +end + +def fun_l24_n795(x) + if (x < 1) + fun_l25_n869(x) + else + fun_l25_n250(x) + end +end + +def fun_l24_n796(x) + if (x < 1) + fun_l25_n479(x) + else + fun_l25_n996(x) + end +end + +def fun_l24_n797(x) + if (x < 1) + fun_l25_n773(x) + else + fun_l25_n294(x) + end +end + +def fun_l24_n798(x) + if (x < 1) + fun_l25_n601(x) + else + fun_l25_n259(x) + end +end + +def fun_l24_n799(x) + if (x < 1) + fun_l25_n334(x) + else + fun_l25_n696(x) + end +end + +def fun_l24_n800(x) + if (x < 1) + fun_l25_n6(x) + else + fun_l25_n184(x) + end +end + +def fun_l24_n801(x) + if (x < 1) + fun_l25_n345(x) + else + fun_l25_n476(x) + end +end + +def fun_l24_n802(x) + if (x < 1) + fun_l25_n957(x) + else + fun_l25_n893(x) + end +end + +def fun_l24_n803(x) + if (x < 1) + fun_l25_n541(x) + else + fun_l25_n562(x) + end +end + +def fun_l24_n804(x) + if (x < 1) + fun_l25_n403(x) + else + fun_l25_n398(x) + end +end + +def fun_l24_n805(x) + if (x < 1) + fun_l25_n759(x) + else + fun_l25_n861(x) + end +end + +def fun_l24_n806(x) + if (x < 1) + fun_l25_n145(x) + else + fun_l25_n460(x) + end +end + +def fun_l24_n807(x) + if (x < 1) + fun_l25_n960(x) + else + fun_l25_n865(x) + end +end + +def fun_l24_n808(x) + if (x < 1) + fun_l25_n386(x) + else + fun_l25_n443(x) + end +end + +def fun_l24_n809(x) + if (x < 1) + fun_l25_n789(x) + else + fun_l25_n295(x) + end +end + +def fun_l24_n810(x) + if (x < 1) + fun_l25_n985(x) + else + fun_l25_n15(x) + end +end + +def fun_l24_n811(x) + if (x < 1) + fun_l25_n976(x) + else + fun_l25_n636(x) + end +end + +def fun_l24_n812(x) + if (x < 1) + fun_l25_n183(x) + else + fun_l25_n146(x) + end +end + +def fun_l24_n813(x) + if (x < 1) + fun_l25_n457(x) + else + fun_l25_n141(x) + end +end + +def fun_l24_n814(x) + if (x < 1) + fun_l25_n1(x) + else + fun_l25_n708(x) + end +end + +def fun_l24_n815(x) + if (x < 1) + fun_l25_n696(x) + else + fun_l25_n898(x) + end +end + +def fun_l24_n816(x) + if (x < 1) + fun_l25_n423(x) + else + fun_l25_n250(x) + end +end + +def fun_l24_n817(x) + if (x < 1) + fun_l25_n432(x) + else + fun_l25_n918(x) + end +end + +def fun_l24_n818(x) + if (x < 1) + fun_l25_n712(x) + else + fun_l25_n8(x) + end +end + +def fun_l24_n819(x) + if (x < 1) + fun_l25_n331(x) + else + fun_l25_n194(x) + end +end + +def fun_l24_n820(x) + if (x < 1) + fun_l25_n106(x) + else + fun_l25_n588(x) + end +end + +def fun_l24_n821(x) + if (x < 1) + fun_l25_n662(x) + else + fun_l25_n365(x) + end +end + +def fun_l24_n822(x) + if (x < 1) + fun_l25_n461(x) + else + fun_l25_n931(x) + end +end + +def fun_l24_n823(x) + if (x < 1) + fun_l25_n243(x) + else + fun_l25_n26(x) + end +end + +def fun_l24_n824(x) + if (x < 1) + fun_l25_n6(x) + else + fun_l25_n787(x) + end +end + +def fun_l24_n825(x) + if (x < 1) + fun_l25_n536(x) + else + fun_l25_n721(x) + end +end + +def fun_l24_n826(x) + if (x < 1) + fun_l25_n693(x) + else + fun_l25_n649(x) + end +end + +def fun_l24_n827(x) + if (x < 1) + fun_l25_n662(x) + else + fun_l25_n981(x) + end +end + +def fun_l24_n828(x) + if (x < 1) + fun_l25_n594(x) + else + fun_l25_n345(x) + end +end + +def fun_l24_n829(x) + if (x < 1) + fun_l25_n917(x) + else + fun_l25_n665(x) + end +end + +def fun_l24_n830(x) + if (x < 1) + fun_l25_n246(x) + else + fun_l25_n58(x) + end +end + +def fun_l24_n831(x) + if (x < 1) + fun_l25_n415(x) + else + fun_l25_n617(x) + end +end + +def fun_l24_n832(x) + if (x < 1) + fun_l25_n596(x) + else + fun_l25_n858(x) + end +end + +def fun_l24_n833(x) + if (x < 1) + fun_l25_n810(x) + else + fun_l25_n532(x) + end +end + +def fun_l24_n834(x) + if (x < 1) + fun_l25_n298(x) + else + fun_l25_n881(x) + end +end + +def fun_l24_n835(x) + if (x < 1) + fun_l25_n791(x) + else + fun_l25_n344(x) + end +end + +def fun_l24_n836(x) + if (x < 1) + fun_l25_n531(x) + else + fun_l25_n880(x) + end +end + +def fun_l24_n837(x) + if (x < 1) + fun_l25_n571(x) + else + fun_l25_n306(x) + end +end + +def fun_l24_n838(x) + if (x < 1) + fun_l25_n191(x) + else + fun_l25_n450(x) + end +end + +def fun_l24_n839(x) + if (x < 1) + fun_l25_n777(x) + else + fun_l25_n234(x) + end +end + +def fun_l24_n840(x) + if (x < 1) + fun_l25_n876(x) + else + fun_l25_n548(x) + end +end + +def fun_l24_n841(x) + if (x < 1) + fun_l25_n83(x) + else + fun_l25_n346(x) + end +end + +def fun_l24_n842(x) + if (x < 1) + fun_l25_n976(x) + else + fun_l25_n843(x) + end +end + +def fun_l24_n843(x) + if (x < 1) + fun_l25_n559(x) + else + fun_l25_n424(x) + end +end + +def fun_l24_n844(x) + if (x < 1) + fun_l25_n974(x) + else + fun_l25_n906(x) + end +end + +def fun_l24_n845(x) + if (x < 1) + fun_l25_n274(x) + else + fun_l25_n528(x) + end +end + +def fun_l24_n846(x) + if (x < 1) + fun_l25_n773(x) + else + fun_l25_n507(x) + end +end + +def fun_l24_n847(x) + if (x < 1) + fun_l25_n80(x) + else + fun_l25_n274(x) + end +end + +def fun_l24_n848(x) + if (x < 1) + fun_l25_n557(x) + else + fun_l25_n541(x) + end +end + +def fun_l24_n849(x) + if (x < 1) + fun_l25_n208(x) + else + fun_l25_n765(x) + end +end + +def fun_l24_n850(x) + if (x < 1) + fun_l25_n705(x) + else + fun_l25_n81(x) + end +end + +def fun_l24_n851(x) + if (x < 1) + fun_l25_n151(x) + else + fun_l25_n706(x) + end +end + +def fun_l24_n852(x) + if (x < 1) + fun_l25_n723(x) + else + fun_l25_n451(x) + end +end + +def fun_l24_n853(x) + if (x < 1) + fun_l25_n155(x) + else + fun_l25_n48(x) + end +end + +def fun_l24_n854(x) + if (x < 1) + fun_l25_n317(x) + else + fun_l25_n118(x) + end +end + +def fun_l24_n855(x) + if (x < 1) + fun_l25_n794(x) + else + fun_l25_n880(x) + end +end + +def fun_l24_n856(x) + if (x < 1) + fun_l25_n556(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n857(x) + if (x < 1) + fun_l25_n665(x) + else + fun_l25_n640(x) + end +end + +def fun_l24_n858(x) + if (x < 1) + fun_l25_n732(x) + else + fun_l25_n771(x) + end +end + +def fun_l24_n859(x) + if (x < 1) + fun_l25_n367(x) + else + fun_l25_n616(x) + end +end + +def fun_l24_n860(x) + if (x < 1) + fun_l25_n184(x) + else + fun_l25_n912(x) + end +end + +def fun_l24_n861(x) + if (x < 1) + fun_l25_n916(x) + else + fun_l25_n66(x) + end +end + +def fun_l24_n862(x) + if (x < 1) + fun_l25_n526(x) + else + fun_l25_n807(x) + end +end + +def fun_l24_n863(x) + if (x < 1) + fun_l25_n83(x) + else + fun_l25_n180(x) + end +end + +def fun_l24_n864(x) + if (x < 1) + fun_l25_n199(x) + else + fun_l25_n471(x) + end +end + +def fun_l24_n865(x) + if (x < 1) + fun_l25_n763(x) + else + fun_l25_n16(x) + end +end + +def fun_l24_n866(x) + if (x < 1) + fun_l25_n280(x) + else + fun_l25_n66(x) + end +end + +def fun_l24_n867(x) + if (x < 1) + fun_l25_n366(x) + else + fun_l25_n143(x) + end +end + +def fun_l24_n868(x) + if (x < 1) + fun_l25_n110(x) + else + fun_l25_n151(x) + end +end + +def fun_l24_n869(x) + if (x < 1) + fun_l25_n936(x) + else + fun_l25_n153(x) + end +end + +def fun_l24_n870(x) + if (x < 1) + fun_l25_n555(x) + else + fun_l25_n915(x) + end +end + +def fun_l24_n871(x) + if (x < 1) + fun_l25_n199(x) + else + fun_l25_n613(x) + end +end + +def fun_l24_n872(x) + if (x < 1) + fun_l25_n381(x) + else + fun_l25_n899(x) + end +end + +def fun_l24_n873(x) + if (x < 1) + fun_l25_n64(x) + else + fun_l25_n337(x) + end +end + +def fun_l24_n874(x) + if (x < 1) + fun_l25_n753(x) + else + fun_l25_n981(x) + end +end + +def fun_l24_n875(x) + if (x < 1) + fun_l25_n113(x) + else + fun_l25_n126(x) + end +end + +def fun_l24_n876(x) + if (x < 1) + fun_l25_n3(x) + else + fun_l25_n288(x) + end +end + +def fun_l24_n877(x) + if (x < 1) + fun_l25_n359(x) + else + fun_l25_n596(x) + end +end + +def fun_l24_n878(x) + if (x < 1) + fun_l25_n937(x) + else + fun_l25_n72(x) + end +end + +def fun_l24_n879(x) + if (x < 1) + fun_l25_n495(x) + else + fun_l25_n368(x) + end +end + +def fun_l24_n880(x) + if (x < 1) + fun_l25_n524(x) + else + fun_l25_n228(x) + end +end + +def fun_l24_n881(x) + if (x < 1) + fun_l25_n438(x) + else + fun_l25_n986(x) + end +end + +def fun_l24_n882(x) + if (x < 1) + fun_l25_n334(x) + else + fun_l25_n54(x) + end +end + +def fun_l24_n883(x) + if (x < 1) + fun_l25_n612(x) + else + fun_l25_n126(x) + end +end + +def fun_l24_n884(x) + if (x < 1) + fun_l25_n316(x) + else + fun_l25_n222(x) + end +end + +def fun_l24_n885(x) + if (x < 1) + fun_l25_n915(x) + else + fun_l25_n971(x) + end +end + +def fun_l24_n886(x) + if (x < 1) + fun_l25_n987(x) + else + fun_l25_n499(x) + end +end + +def fun_l24_n887(x) + if (x < 1) + fun_l25_n476(x) + else + fun_l25_n280(x) + end +end + +def fun_l24_n888(x) + if (x < 1) + fun_l25_n420(x) + else + fun_l25_n584(x) + end +end + +def fun_l24_n889(x) + if (x < 1) + fun_l25_n560(x) + else + fun_l25_n767(x) + end +end + +def fun_l24_n890(x) + if (x < 1) + fun_l25_n26(x) + else + fun_l25_n431(x) + end +end + +def fun_l24_n891(x) + if (x < 1) + fun_l25_n107(x) + else + fun_l25_n803(x) + end +end + +def fun_l24_n892(x) + if (x < 1) + fun_l25_n225(x) + else + fun_l25_n665(x) + end +end + +def fun_l24_n893(x) + if (x < 1) + fun_l25_n19(x) + else + fun_l25_n507(x) + end +end + +def fun_l24_n894(x) + if (x < 1) + fun_l25_n44(x) + else + fun_l25_n420(x) + end +end + +def fun_l24_n895(x) + if (x < 1) + fun_l25_n526(x) + else + fun_l25_n871(x) + end +end + +def fun_l24_n896(x) + if (x < 1) + fun_l25_n900(x) + else + fun_l25_n824(x) + end +end + +def fun_l24_n897(x) + if (x < 1) + fun_l25_n105(x) + else + fun_l25_n602(x) + end +end + +def fun_l24_n898(x) + if (x < 1) + fun_l25_n228(x) + else + fun_l25_n993(x) + end +end + +def fun_l24_n899(x) + if (x < 1) + fun_l25_n330(x) + else + fun_l25_n60(x) + end +end + +def fun_l24_n900(x) + if (x < 1) + fun_l25_n512(x) + else + fun_l25_n708(x) + end +end + +def fun_l24_n901(x) + if (x < 1) + fun_l25_n791(x) + else + fun_l25_n554(x) + end +end + +def fun_l24_n902(x) + if (x < 1) + fun_l25_n204(x) + else + fun_l25_n439(x) + end +end + +def fun_l24_n903(x) + if (x < 1) + fun_l25_n577(x) + else + fun_l25_n174(x) + end +end + +def fun_l24_n904(x) + if (x < 1) + fun_l25_n713(x) + else + fun_l25_n35(x) + end +end + +def fun_l24_n905(x) + if (x < 1) + fun_l25_n290(x) + else + fun_l25_n342(x) + end +end + +def fun_l24_n906(x) + if (x < 1) + fun_l25_n607(x) + else + fun_l25_n52(x) + end +end + +def fun_l24_n907(x) + if (x < 1) + fun_l25_n72(x) + else + fun_l25_n169(x) + end +end + +def fun_l24_n908(x) + if (x < 1) + fun_l25_n179(x) + else + fun_l25_n383(x) + end +end + +def fun_l24_n909(x) + if (x < 1) + fun_l25_n52(x) + else + fun_l25_n504(x) + end +end + +def fun_l24_n910(x) + if (x < 1) + fun_l25_n346(x) + else + fun_l25_n775(x) + end +end + +def fun_l24_n911(x) + if (x < 1) + fun_l25_n535(x) + else + fun_l25_n210(x) + end +end + +def fun_l24_n912(x) + if (x < 1) + fun_l25_n937(x) + else + fun_l25_n409(x) + end +end + +def fun_l24_n913(x) + if (x < 1) + fun_l25_n889(x) + else + fun_l25_n463(x) + end +end + +def fun_l24_n914(x) + if (x < 1) + fun_l25_n75(x) + else + fun_l25_n817(x) + end +end + +def fun_l24_n915(x) + if (x < 1) + fun_l25_n277(x) + else + fun_l25_n3(x) + end +end + +def fun_l24_n916(x) + if (x < 1) + fun_l25_n97(x) + else + fun_l25_n819(x) + end +end + +def fun_l24_n917(x) + if (x < 1) + fun_l25_n412(x) + else + fun_l25_n851(x) + end +end + +def fun_l24_n918(x) + if (x < 1) + fun_l25_n803(x) + else + fun_l25_n429(x) + end +end + +def fun_l24_n919(x) + if (x < 1) + fun_l25_n12(x) + else + fun_l25_n434(x) + end +end + +def fun_l24_n920(x) + if (x < 1) + fun_l25_n721(x) + else + fun_l25_n553(x) + end +end + +def fun_l24_n921(x) + if (x < 1) + fun_l25_n438(x) + else + fun_l25_n211(x) + end +end + +def fun_l24_n922(x) + if (x < 1) + fun_l25_n123(x) + else + fun_l25_n89(x) + end +end + +def fun_l24_n923(x) + if (x < 1) + fun_l25_n696(x) + else + fun_l25_n78(x) + end +end + +def fun_l24_n924(x) + if (x < 1) + fun_l25_n556(x) + else + fun_l25_n788(x) + end +end + +def fun_l24_n925(x) + if (x < 1) + fun_l25_n928(x) + else + fun_l25_n797(x) + end +end + +def fun_l24_n926(x) + if (x < 1) + fun_l25_n796(x) + else + fun_l25_n84(x) + end +end + +def fun_l24_n927(x) + if (x < 1) + fun_l25_n874(x) + else + fun_l25_n255(x) + end +end + +def fun_l24_n928(x) + if (x < 1) + fun_l25_n715(x) + else + fun_l25_n812(x) + end +end + +def fun_l24_n929(x) + if (x < 1) + fun_l25_n384(x) + else + fun_l25_n859(x) + end +end + +def fun_l24_n930(x) + if (x < 1) + fun_l25_n133(x) + else + fun_l25_n923(x) + end +end + +def fun_l24_n931(x) + if (x < 1) + fun_l25_n712(x) + else + fun_l25_n850(x) + end +end + +def fun_l24_n932(x) + if (x < 1) + fun_l25_n301(x) + else + fun_l25_n743(x) + end +end + +def fun_l24_n933(x) + if (x < 1) + fun_l25_n554(x) + else + fun_l25_n4(x) + end +end + +def fun_l24_n934(x) + if (x < 1) + fun_l25_n407(x) + else + fun_l25_n656(x) + end +end + +def fun_l24_n935(x) + if (x < 1) + fun_l25_n109(x) + else + fun_l25_n356(x) + end +end + +def fun_l24_n936(x) + if (x < 1) + fun_l25_n985(x) + else + fun_l25_n183(x) + end +end + +def fun_l24_n937(x) + if (x < 1) + fun_l25_n365(x) + else + fun_l25_n949(x) + end +end + +def fun_l24_n938(x) + if (x < 1) + fun_l25_n672(x) + else + fun_l25_n417(x) + end +end + +def fun_l24_n939(x) + if (x < 1) + fun_l25_n360(x) + else + fun_l25_n271(x) + end +end + +def fun_l24_n940(x) + if (x < 1) + fun_l25_n654(x) + else + fun_l25_n365(x) + end +end + +def fun_l24_n941(x) + if (x < 1) + fun_l25_n836(x) + else + fun_l25_n303(x) + end +end + +def fun_l24_n942(x) + if (x < 1) + fun_l25_n299(x) + else + fun_l25_n130(x) + end +end + +def fun_l24_n943(x) + if (x < 1) + fun_l25_n566(x) + else + fun_l25_n347(x) + end +end + +def fun_l24_n944(x) + if (x < 1) + fun_l25_n754(x) + else + fun_l25_n670(x) + end +end + +def fun_l24_n945(x) + if (x < 1) + fun_l25_n484(x) + else + fun_l25_n278(x) + end +end + +def fun_l24_n946(x) + if (x < 1) + fun_l25_n35(x) + else + fun_l25_n915(x) + end +end + +def fun_l24_n947(x) + if (x < 1) + fun_l25_n488(x) + else + fun_l25_n664(x) + end +end + +def fun_l24_n948(x) + if (x < 1) + fun_l25_n249(x) + else + fun_l25_n931(x) + end +end + +def fun_l24_n949(x) + if (x < 1) + fun_l25_n165(x) + else + fun_l25_n101(x) + end +end + +def fun_l24_n950(x) + if (x < 1) + fun_l25_n304(x) + else + fun_l25_n668(x) + end +end + +def fun_l24_n951(x) + if (x < 1) + fun_l25_n279(x) + else + fun_l25_n600(x) + end +end + +def fun_l24_n952(x) + if (x < 1) + fun_l25_n70(x) + else + fun_l25_n852(x) + end +end + +def fun_l24_n953(x) + if (x < 1) + fun_l25_n419(x) + else + fun_l25_n856(x) + end +end + +def fun_l24_n954(x) + if (x < 1) + fun_l25_n55(x) + else + fun_l25_n857(x) + end +end + +def fun_l24_n955(x) + if (x < 1) + fun_l25_n122(x) + else + fun_l25_n658(x) + end +end + +def fun_l24_n956(x) + if (x < 1) + fun_l25_n973(x) + else + fun_l25_n421(x) + end +end + +def fun_l24_n957(x) + if (x < 1) + fun_l25_n82(x) + else + fun_l25_n264(x) + end +end + +def fun_l24_n958(x) + if (x < 1) + fun_l25_n608(x) + else + fun_l25_n469(x) + end +end + +def fun_l24_n959(x) + if (x < 1) + fun_l25_n823(x) + else + fun_l25_n320(x) + end +end + +def fun_l24_n960(x) + if (x < 1) + fun_l25_n765(x) + else + fun_l25_n461(x) + end +end + +def fun_l24_n961(x) + if (x < 1) + fun_l25_n343(x) + else + fun_l25_n18(x) + end +end + +def fun_l24_n962(x) + if (x < 1) + fun_l25_n346(x) + else + fun_l25_n821(x) + end +end + +def fun_l24_n963(x) + if (x < 1) + fun_l25_n80(x) + else + fun_l25_n949(x) + end +end + +def fun_l24_n964(x) + if (x < 1) + fun_l25_n171(x) + else + fun_l25_n514(x) + end +end + +def fun_l24_n965(x) + if (x < 1) + fun_l25_n625(x) + else + fun_l25_n768(x) + end +end + +def fun_l24_n966(x) + if (x < 1) + fun_l25_n390(x) + else + fun_l25_n195(x) + end +end + +def fun_l24_n967(x) + if (x < 1) + fun_l25_n774(x) + else + fun_l25_n928(x) + end +end + +def fun_l24_n968(x) + if (x < 1) + fun_l25_n997(x) + else + fun_l25_n441(x) + end +end + +def fun_l24_n969(x) + if (x < 1) + fun_l25_n865(x) + else + fun_l25_n418(x) + end +end + +def fun_l24_n970(x) + if (x < 1) + fun_l25_n238(x) + else + fun_l25_n816(x) + end +end + +def fun_l24_n971(x) + if (x < 1) + fun_l25_n521(x) + else + fun_l25_n427(x) + end +end + +def fun_l24_n972(x) + if (x < 1) + fun_l25_n214(x) + else + fun_l25_n282(x) + end +end + +def fun_l24_n973(x) + if (x < 1) + fun_l25_n611(x) + else + fun_l25_n439(x) + end +end + +def fun_l24_n974(x) + if (x < 1) + fun_l25_n395(x) + else + fun_l25_n593(x) + end +end + +def fun_l24_n975(x) + if (x < 1) + fun_l25_n720(x) + else + fun_l25_n477(x) + end +end + +def fun_l24_n976(x) + if (x < 1) + fun_l25_n204(x) + else + fun_l25_n912(x) + end +end + +def fun_l24_n977(x) + if (x < 1) + fun_l25_n703(x) + else + fun_l25_n651(x) + end +end + +def fun_l24_n978(x) + if (x < 1) + fun_l25_n247(x) + else + fun_l25_n917(x) + end +end + +def fun_l24_n979(x) + if (x < 1) + fun_l25_n792(x) + else + fun_l25_n320(x) + end +end + +def fun_l24_n980(x) + if (x < 1) + fun_l25_n480(x) + else + fun_l25_n128(x) + end +end + +def fun_l24_n981(x) + if (x < 1) + fun_l25_n848(x) + else + fun_l25_n344(x) + end +end + +def fun_l24_n982(x) + if (x < 1) + fun_l25_n84(x) + else + fun_l25_n977(x) + end +end + +def fun_l24_n983(x) + if (x < 1) + fun_l25_n213(x) + else + fun_l25_n131(x) + end +end + +def fun_l24_n984(x) + if (x < 1) + fun_l25_n2(x) + else + fun_l25_n21(x) + end +end + +def fun_l24_n985(x) + if (x < 1) + fun_l25_n301(x) + else + fun_l25_n910(x) + end +end + +def fun_l24_n986(x) + if (x < 1) + fun_l25_n533(x) + else + fun_l25_n397(x) + end +end + +def fun_l24_n987(x) + if (x < 1) + fun_l25_n226(x) + else + fun_l25_n281(x) + end +end + +def fun_l24_n988(x) + if (x < 1) + fun_l25_n402(x) + else + fun_l25_n70(x) + end +end + +def fun_l24_n989(x) + if (x < 1) + fun_l25_n190(x) + else + fun_l25_n70(x) + end +end + +def fun_l24_n990(x) + if (x < 1) + fun_l25_n376(x) + else + fun_l25_n331(x) + end +end + +def fun_l24_n991(x) + if (x < 1) + fun_l25_n915(x) + else + fun_l25_n234(x) + end +end + +def fun_l24_n992(x) + if (x < 1) + fun_l25_n146(x) + else + fun_l25_n825(x) + end +end + +def fun_l24_n993(x) + if (x < 1) + fun_l25_n877(x) + else + fun_l25_n237(x) + end +end + +def fun_l24_n994(x) + if (x < 1) + fun_l25_n454(x) + else + fun_l25_n852(x) + end +end + +def fun_l24_n995(x) + if (x < 1) + fun_l25_n45(x) + else + fun_l25_n337(x) + end +end + +def fun_l24_n996(x) + if (x < 1) + fun_l25_n491(x) + else + fun_l25_n319(x) + end +end + +def fun_l24_n997(x) + if (x < 1) + fun_l25_n216(x) + else + fun_l25_n249(x) + end +end + +def fun_l24_n998(x) + if (x < 1) + fun_l25_n370(x) + else + fun_l25_n747(x) + end +end + +def fun_l24_n999(x) + if (x < 1) + fun_l25_n584(x) + else + fun_l25_n813(x) + end +end + +def fun_l25_n0(x) + if (x < 1) + fun_l26_n818(x) + else + fun_l26_n750(x) + end +end + +def fun_l25_n1(x) + if (x < 1) + fun_l26_n725(x) + else + fun_l26_n848(x) + end +end + +def fun_l25_n2(x) + if (x < 1) + fun_l26_n716(x) + else + fun_l26_n190(x) + end +end + +def fun_l25_n3(x) + if (x < 1) + fun_l26_n977(x) + else + fun_l26_n222(x) + end +end + +def fun_l25_n4(x) + if (x < 1) + fun_l26_n931(x) + else + fun_l26_n615(x) + end +end + +def fun_l25_n5(x) + if (x < 1) + fun_l26_n720(x) + else + fun_l26_n440(x) + end +end + +def fun_l25_n6(x) + if (x < 1) + fun_l26_n400(x) + else + fun_l26_n336(x) + end +end + +def fun_l25_n7(x) + if (x < 1) + fun_l26_n109(x) + else + fun_l26_n74(x) + end +end + +def fun_l25_n8(x) + if (x < 1) + fun_l26_n12(x) + else + fun_l26_n857(x) + end +end + +def fun_l25_n9(x) + if (x < 1) + fun_l26_n778(x) + else + fun_l26_n286(x) + end +end + +def fun_l25_n10(x) + if (x < 1) + fun_l26_n857(x) + else + fun_l26_n311(x) + end +end + +def fun_l25_n11(x) + if (x < 1) + fun_l26_n204(x) + else + fun_l26_n348(x) + end +end + +def fun_l25_n12(x) + if (x < 1) + fun_l26_n626(x) + else + fun_l26_n983(x) + end +end + +def fun_l25_n13(x) + if (x < 1) + fun_l26_n417(x) + else + fun_l26_n334(x) + end +end + +def fun_l25_n14(x) + if (x < 1) + fun_l26_n34(x) + else + fun_l26_n269(x) + end +end + +def fun_l25_n15(x) + if (x < 1) + fun_l26_n184(x) + else + fun_l26_n183(x) + end +end + +def fun_l25_n16(x) + if (x < 1) + fun_l26_n744(x) + else + fun_l26_n450(x) + end +end + +def fun_l25_n17(x) + if (x < 1) + fun_l26_n763(x) + else + fun_l26_n390(x) + end +end + +def fun_l25_n18(x) + if (x < 1) + fun_l26_n926(x) + else + fun_l26_n379(x) + end +end + +def fun_l25_n19(x) + if (x < 1) + fun_l26_n746(x) + else + fun_l26_n946(x) + end +end + +def fun_l25_n20(x) + if (x < 1) + fun_l26_n500(x) + else + fun_l26_n599(x) + end +end + +def fun_l25_n21(x) + if (x < 1) + fun_l26_n757(x) + else + fun_l26_n725(x) + end +end + +def fun_l25_n22(x) + if (x < 1) + fun_l26_n738(x) + else + fun_l26_n24(x) + end +end + +def fun_l25_n23(x) + if (x < 1) + fun_l26_n350(x) + else + fun_l26_n344(x) + end +end + +def fun_l25_n24(x) + if (x < 1) + fun_l26_n521(x) + else + fun_l26_n680(x) + end +end + +def fun_l25_n25(x) + if (x < 1) + fun_l26_n647(x) + else + fun_l26_n604(x) + end +end + +def fun_l25_n26(x) + if (x < 1) + fun_l26_n990(x) + else + fun_l26_n262(x) + end +end + +def fun_l25_n27(x) + if (x < 1) + fun_l26_n309(x) + else + fun_l26_n759(x) + end +end + +def fun_l25_n28(x) + if (x < 1) + fun_l26_n720(x) + else + fun_l26_n11(x) + end +end + +def fun_l25_n29(x) + if (x < 1) + fun_l26_n761(x) + else + fun_l26_n690(x) + end +end + +def fun_l25_n30(x) + if (x < 1) + fun_l26_n729(x) + else + fun_l26_n577(x) + end +end + +def fun_l25_n31(x) + if (x < 1) + fun_l26_n321(x) + else + fun_l26_n608(x) + end +end + +def fun_l25_n32(x) + if (x < 1) + fun_l26_n325(x) + else + fun_l26_n541(x) + end +end + +def fun_l25_n33(x) + if (x < 1) + fun_l26_n644(x) + else + fun_l26_n15(x) + end +end + +def fun_l25_n34(x) + if (x < 1) + fun_l26_n53(x) + else + fun_l26_n887(x) + end +end + +def fun_l25_n35(x) + if (x < 1) + fun_l26_n470(x) + else + fun_l26_n564(x) + end +end + +def fun_l25_n36(x) + if (x < 1) + fun_l26_n198(x) + else + fun_l26_n542(x) + end +end + +def fun_l25_n37(x) + if (x < 1) + fun_l26_n455(x) + else + fun_l26_n373(x) + end +end + +def fun_l25_n38(x) + if (x < 1) + fun_l26_n216(x) + else + fun_l26_n86(x) + end +end + +def fun_l25_n39(x) + if (x < 1) + fun_l26_n417(x) + else + fun_l26_n50(x) + end +end + +def fun_l25_n40(x) + if (x < 1) + fun_l26_n955(x) + else + fun_l26_n979(x) + end +end + +def fun_l25_n41(x) + if (x < 1) + fun_l26_n692(x) + else + fun_l26_n935(x) + end +end + +def fun_l25_n42(x) + if (x < 1) + fun_l26_n360(x) + else + fun_l26_n246(x) + end +end + +def fun_l25_n43(x) + if (x < 1) + fun_l26_n826(x) + else + fun_l26_n433(x) + end +end + +def fun_l25_n44(x) + if (x < 1) + fun_l26_n222(x) + else + fun_l26_n101(x) + end +end + +def fun_l25_n45(x) + if (x < 1) + fun_l26_n590(x) + else + fun_l26_n398(x) + end +end + +def fun_l25_n46(x) + if (x < 1) + fun_l26_n959(x) + else + fun_l26_n620(x) + end +end + +def fun_l25_n47(x) + if (x < 1) + fun_l26_n530(x) + else + fun_l26_n503(x) + end +end + +def fun_l25_n48(x) + if (x < 1) + fun_l26_n615(x) + else + fun_l26_n640(x) + end +end + +def fun_l25_n49(x) + if (x < 1) + fun_l26_n774(x) + else + fun_l26_n23(x) + end +end + +def fun_l25_n50(x) + if (x < 1) + fun_l26_n344(x) + else + fun_l26_n303(x) + end +end + +def fun_l25_n51(x) + if (x < 1) + fun_l26_n54(x) + else + fun_l26_n26(x) + end +end + +def fun_l25_n52(x) + if (x < 1) + fun_l26_n545(x) + else + fun_l26_n791(x) + end +end + +def fun_l25_n53(x) + if (x < 1) + fun_l26_n554(x) + else + fun_l26_n42(x) + end +end + +def fun_l25_n54(x) + if (x < 1) + fun_l26_n419(x) + else + fun_l26_n179(x) + end +end + +def fun_l25_n55(x) + if (x < 1) + fun_l26_n845(x) + else + fun_l26_n641(x) + end +end + +def fun_l25_n56(x) + if (x < 1) + fun_l26_n389(x) + else + fun_l26_n547(x) + end +end + +def fun_l25_n57(x) + if (x < 1) + fun_l26_n744(x) + else + fun_l26_n946(x) + end +end + +def fun_l25_n58(x) + if (x < 1) + fun_l26_n410(x) + else + fun_l26_n909(x) + end +end + +def fun_l25_n59(x) + if (x < 1) + fun_l26_n126(x) + else + fun_l26_n382(x) + end +end + +def fun_l25_n60(x) + if (x < 1) + fun_l26_n355(x) + else + fun_l26_n902(x) + end +end + +def fun_l25_n61(x) + if (x < 1) + fun_l26_n759(x) + else + fun_l26_n445(x) + end +end + +def fun_l25_n62(x) + if (x < 1) + fun_l26_n859(x) + else + fun_l26_n362(x) + end +end + +def fun_l25_n63(x) + if (x < 1) + fun_l26_n488(x) + else + fun_l26_n725(x) + end +end + +def fun_l25_n64(x) + if (x < 1) + fun_l26_n268(x) + else + fun_l26_n865(x) + end +end + +def fun_l25_n65(x) + if (x < 1) + fun_l26_n33(x) + else + fun_l26_n417(x) + end +end + +def fun_l25_n66(x) + if (x < 1) + fun_l26_n281(x) + else + fun_l26_n485(x) + end +end + +def fun_l25_n67(x) + if (x < 1) + fun_l26_n627(x) + else + fun_l26_n200(x) + end +end + +def fun_l25_n68(x) + if (x < 1) + fun_l26_n392(x) + else + fun_l26_n639(x) + end +end + +def fun_l25_n69(x) + if (x < 1) + fun_l26_n799(x) + else + fun_l26_n242(x) + end +end + +def fun_l25_n70(x) + if (x < 1) + fun_l26_n783(x) + else + fun_l26_n564(x) + end +end + +def fun_l25_n71(x) + if (x < 1) + fun_l26_n768(x) + else + fun_l26_n908(x) + end +end + +def fun_l25_n72(x) + if (x < 1) + fun_l26_n567(x) + else + fun_l26_n365(x) + end +end + +def fun_l25_n73(x) + if (x < 1) + fun_l26_n291(x) + else + fun_l26_n887(x) + end +end + +def fun_l25_n74(x) + if (x < 1) + fun_l26_n889(x) + else + fun_l26_n180(x) + end +end + +def fun_l25_n75(x) + if (x < 1) + fun_l26_n142(x) + else + fun_l26_n101(x) + end +end + +def fun_l25_n76(x) + if (x < 1) + fun_l26_n108(x) + else + fun_l26_n863(x) + end +end + +def fun_l25_n77(x) + if (x < 1) + fun_l26_n441(x) + else + fun_l26_n51(x) + end +end + +def fun_l25_n78(x) + if (x < 1) + fun_l26_n787(x) + else + fun_l26_n543(x) + end +end + +def fun_l25_n79(x) + if (x < 1) + fun_l26_n699(x) + else + fun_l26_n513(x) + end +end + +def fun_l25_n80(x) + if (x < 1) + fun_l26_n400(x) + else + fun_l26_n72(x) + end +end + +def fun_l25_n81(x) + if (x < 1) + fun_l26_n814(x) + else + fun_l26_n732(x) + end +end + +def fun_l25_n82(x) + if (x < 1) + fun_l26_n755(x) + else + fun_l26_n606(x) + end +end + +def fun_l25_n83(x) + if (x < 1) + fun_l26_n351(x) + else + fun_l26_n208(x) + end +end + +def fun_l25_n84(x) + if (x < 1) + fun_l26_n124(x) + else + fun_l26_n554(x) + end +end + +def fun_l25_n85(x) + if (x < 1) + fun_l26_n19(x) + else + fun_l26_n58(x) + end +end + +def fun_l25_n86(x) + if (x < 1) + fun_l26_n710(x) + else + fun_l26_n300(x) + end +end + +def fun_l25_n87(x) + if (x < 1) + fun_l26_n833(x) + else + fun_l26_n53(x) + end +end + +def fun_l25_n88(x) + if (x < 1) + fun_l26_n923(x) + else + fun_l26_n445(x) + end +end + +def fun_l25_n89(x) + if (x < 1) + fun_l26_n674(x) + else + fun_l26_n176(x) + end +end + +def fun_l25_n90(x) + if (x < 1) + fun_l26_n78(x) + else + fun_l26_n506(x) + end +end + +def fun_l25_n91(x) + if (x < 1) + fun_l26_n352(x) + else + fun_l26_n312(x) + end +end + +def fun_l25_n92(x) + if (x < 1) + fun_l26_n400(x) + else + fun_l26_n787(x) + end +end + +def fun_l25_n93(x) + if (x < 1) + fun_l26_n897(x) + else + fun_l26_n395(x) + end +end + +def fun_l25_n94(x) + if (x < 1) + fun_l26_n267(x) + else + fun_l26_n974(x) + end +end + +def fun_l25_n95(x) + if (x < 1) + fun_l26_n547(x) + else + fun_l26_n280(x) + end +end + +def fun_l25_n96(x) + if (x < 1) + fun_l26_n281(x) + else + fun_l26_n222(x) + end +end + +def fun_l25_n97(x) + if (x < 1) + fun_l26_n130(x) + else + fun_l26_n232(x) + end +end + +def fun_l25_n98(x) + if (x < 1) + fun_l26_n863(x) + else + fun_l26_n970(x) + end +end + +def fun_l25_n99(x) + if (x < 1) + fun_l26_n28(x) + else + fun_l26_n344(x) + end +end + +def fun_l25_n100(x) + if (x < 1) + fun_l26_n906(x) + else + fun_l26_n818(x) + end +end + +def fun_l25_n101(x) + if (x < 1) + fun_l26_n658(x) + else + fun_l26_n708(x) + end +end + +def fun_l25_n102(x) + if (x < 1) + fun_l26_n545(x) + else + fun_l26_n627(x) + end +end + +def fun_l25_n103(x) + if (x < 1) + fun_l26_n377(x) + else + fun_l26_n555(x) + end +end + +def fun_l25_n104(x) + if (x < 1) + fun_l26_n628(x) + else + fun_l26_n465(x) + end +end + +def fun_l25_n105(x) + if (x < 1) + fun_l26_n208(x) + else + fun_l26_n720(x) + end +end + +def fun_l25_n106(x) + if (x < 1) + fun_l26_n203(x) + else + fun_l26_n984(x) + end +end + +def fun_l25_n107(x) + if (x < 1) + fun_l26_n265(x) + else + fun_l26_n124(x) + end +end + +def fun_l25_n108(x) + if (x < 1) + fun_l26_n786(x) + else + fun_l26_n305(x) + end +end + +def fun_l25_n109(x) + if (x < 1) + fun_l26_n907(x) + else + fun_l26_n57(x) + end +end + +def fun_l25_n110(x) + if (x < 1) + fun_l26_n883(x) + else + fun_l26_n107(x) + end +end + +def fun_l25_n111(x) + if (x < 1) + fun_l26_n783(x) + else + fun_l26_n443(x) + end +end + +def fun_l25_n112(x) + if (x < 1) + fun_l26_n309(x) + else + fun_l26_n127(x) + end +end + +def fun_l25_n113(x) + if (x < 1) + fun_l26_n578(x) + else + fun_l26_n656(x) + end +end + +def fun_l25_n114(x) + if (x < 1) + fun_l26_n352(x) + else + fun_l26_n610(x) + end +end + +def fun_l25_n115(x) + if (x < 1) + fun_l26_n975(x) + else + fun_l26_n580(x) + end +end + +def fun_l25_n116(x) + if (x < 1) + fun_l26_n892(x) + else + fun_l26_n596(x) + end +end + +def fun_l25_n117(x) + if (x < 1) + fun_l26_n80(x) + else + fun_l26_n759(x) + end +end + +def fun_l25_n118(x) + if (x < 1) + fun_l26_n866(x) + else + fun_l26_n964(x) + end +end + +def fun_l25_n119(x) + if (x < 1) + fun_l26_n367(x) + else + fun_l26_n896(x) + end +end + +def fun_l25_n120(x) + if (x < 1) + fun_l26_n787(x) + else + fun_l26_n17(x) + end +end + +def fun_l25_n121(x) + if (x < 1) + fun_l26_n312(x) + else + fun_l26_n247(x) + end +end + +def fun_l25_n122(x) + if (x < 1) + fun_l26_n163(x) + else + fun_l26_n906(x) + end +end + +def fun_l25_n123(x) + if (x < 1) + fun_l26_n706(x) + else + fun_l26_n840(x) + end +end + +def fun_l25_n124(x) + if (x < 1) + fun_l26_n85(x) + else + fun_l26_n200(x) + end +end + +def fun_l25_n125(x) + if (x < 1) + fun_l26_n389(x) + else + fun_l26_n274(x) + end +end + +def fun_l25_n126(x) + if (x < 1) + fun_l26_n509(x) + else + fun_l26_n471(x) + end +end + +def fun_l25_n127(x) + if (x < 1) + fun_l26_n924(x) + else + fun_l26_n132(x) + end +end + +def fun_l25_n128(x) + if (x < 1) + fun_l26_n496(x) + else + fun_l26_n865(x) + end +end + +def fun_l25_n129(x) + if (x < 1) + fun_l26_n775(x) + else + fun_l26_n22(x) + end +end + +def fun_l25_n130(x) + if (x < 1) + fun_l26_n875(x) + else + fun_l26_n771(x) + end +end + +def fun_l25_n131(x) + if (x < 1) + fun_l26_n656(x) + else + fun_l26_n709(x) + end +end + +def fun_l25_n132(x) + if (x < 1) + fun_l26_n733(x) + else + fun_l26_n343(x) + end +end + +def fun_l25_n133(x) + if (x < 1) + fun_l26_n791(x) + else + fun_l26_n954(x) + end +end + +def fun_l25_n134(x) + if (x < 1) + fun_l26_n792(x) + else + fun_l26_n118(x) + end +end + +def fun_l25_n135(x) + if (x < 1) + fun_l26_n93(x) + else + fun_l26_n683(x) + end +end + +def fun_l25_n136(x) + if (x < 1) + fun_l26_n290(x) + else + fun_l26_n787(x) + end +end + +def fun_l25_n137(x) + if (x < 1) + fun_l26_n459(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n138(x) + if (x < 1) + fun_l26_n240(x) + else + fun_l26_n552(x) + end +end + +def fun_l25_n139(x) + if (x < 1) + fun_l26_n323(x) + else + fun_l26_n157(x) + end +end + +def fun_l25_n140(x) + if (x < 1) + fun_l26_n926(x) + else + fun_l26_n446(x) + end +end + +def fun_l25_n141(x) + if (x < 1) + fun_l26_n382(x) + else + fun_l26_n317(x) + end +end + +def fun_l25_n142(x) + if (x < 1) + fun_l26_n296(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n143(x) + if (x < 1) + fun_l26_n313(x) + else + fun_l26_n222(x) + end +end + +def fun_l25_n144(x) + if (x < 1) + fun_l26_n25(x) + else + fun_l26_n260(x) + end +end + +def fun_l25_n145(x) + if (x < 1) + fun_l26_n457(x) + else + fun_l26_n876(x) + end +end + +def fun_l25_n146(x) + if (x < 1) + fun_l26_n503(x) + else + fun_l26_n850(x) + end +end + +def fun_l25_n147(x) + if (x < 1) + fun_l26_n811(x) + else + fun_l26_n293(x) + end +end + +def fun_l25_n148(x) + if (x < 1) + fun_l26_n433(x) + else + fun_l26_n582(x) + end +end + +def fun_l25_n149(x) + if (x < 1) + fun_l26_n860(x) + else + fun_l26_n663(x) + end +end + +def fun_l25_n150(x) + if (x < 1) + fun_l26_n293(x) + else + fun_l26_n341(x) + end +end + +def fun_l25_n151(x) + if (x < 1) + fun_l26_n187(x) + else + fun_l26_n430(x) + end +end + +def fun_l25_n152(x) + if (x < 1) + fun_l26_n914(x) + else + fun_l26_n250(x) + end +end + +def fun_l25_n153(x) + if (x < 1) + fun_l26_n370(x) + else + fun_l26_n378(x) + end +end + +def fun_l25_n154(x) + if (x < 1) + fun_l26_n238(x) + else + fun_l26_n743(x) + end +end + +def fun_l25_n155(x) + if (x < 1) + fun_l26_n149(x) + else + fun_l26_n556(x) + end +end + +def fun_l25_n156(x) + if (x < 1) + fun_l26_n530(x) + else + fun_l26_n543(x) + end +end + +def fun_l25_n157(x) + if (x < 1) + fun_l26_n230(x) + else + fun_l26_n600(x) + end +end + +def fun_l25_n158(x) + if (x < 1) + fun_l26_n110(x) + else + fun_l26_n954(x) + end +end + +def fun_l25_n159(x) + if (x < 1) + fun_l26_n952(x) + else + fun_l26_n110(x) + end +end + +def fun_l25_n160(x) + if (x < 1) + fun_l26_n525(x) + else + fun_l26_n435(x) + end +end + +def fun_l25_n161(x) + if (x < 1) + fun_l26_n511(x) + else + fun_l26_n10(x) + end +end + +def fun_l25_n162(x) + if (x < 1) + fun_l26_n755(x) + else + fun_l26_n567(x) + end +end + +def fun_l25_n163(x) + if (x < 1) + fun_l26_n618(x) + else + fun_l26_n249(x) + end +end + +def fun_l25_n164(x) + if (x < 1) + fun_l26_n803(x) + else + fun_l26_n512(x) + end +end + +def fun_l25_n165(x) + if (x < 1) + fun_l26_n234(x) + else + fun_l26_n806(x) + end +end + +def fun_l25_n166(x) + if (x < 1) + fun_l26_n442(x) + else + fun_l26_n904(x) + end +end + +def fun_l25_n167(x) + if (x < 1) + fun_l26_n369(x) + else + fun_l26_n910(x) + end +end + +def fun_l25_n168(x) + if (x < 1) + fun_l26_n107(x) + else + fun_l26_n125(x) + end +end + +def fun_l25_n169(x) + if (x < 1) + fun_l26_n415(x) + else + fun_l26_n37(x) + end +end + +def fun_l25_n170(x) + if (x < 1) + fun_l26_n315(x) + else + fun_l26_n977(x) + end +end + +def fun_l25_n171(x) + if (x < 1) + fun_l26_n106(x) + else + fun_l26_n908(x) + end +end + +def fun_l25_n172(x) + if (x < 1) + fun_l26_n870(x) + else + fun_l26_n74(x) + end +end + +def fun_l25_n173(x) + if (x < 1) + fun_l26_n290(x) + else + fun_l26_n938(x) + end +end + +def fun_l25_n174(x) + if (x < 1) + fun_l26_n908(x) + else + fun_l26_n215(x) + end +end + +def fun_l25_n175(x) + if (x < 1) + fun_l26_n671(x) + else + fun_l26_n976(x) + end +end + +def fun_l25_n176(x) + if (x < 1) + fun_l26_n727(x) + else + fun_l26_n559(x) + end +end + +def fun_l25_n177(x) + if (x < 1) + fun_l26_n684(x) + else + fun_l26_n353(x) + end +end + +def fun_l25_n178(x) + if (x < 1) + fun_l26_n353(x) + else + fun_l26_n327(x) + end +end + +def fun_l25_n179(x) + if (x < 1) + fun_l26_n393(x) + else + fun_l26_n774(x) + end +end + +def fun_l25_n180(x) + if (x < 1) + fun_l26_n500(x) + else + fun_l26_n23(x) + end +end + +def fun_l25_n181(x) + if (x < 1) + fun_l26_n49(x) + else + fun_l26_n504(x) + end +end + +def fun_l25_n182(x) + if (x < 1) + fun_l26_n631(x) + else + fun_l26_n147(x) + end +end + +def fun_l25_n183(x) + if (x < 1) + fun_l26_n353(x) + else + fun_l26_n64(x) + end +end + +def fun_l25_n184(x) + if (x < 1) + fun_l26_n215(x) + else + fun_l26_n416(x) + end +end + +def fun_l25_n185(x) + if (x < 1) + fun_l26_n701(x) + else + fun_l26_n809(x) + end +end + +def fun_l25_n186(x) + if (x < 1) + fun_l26_n267(x) + else + fun_l26_n197(x) + end +end + +def fun_l25_n187(x) + if (x < 1) + fun_l26_n436(x) + else + fun_l26_n609(x) + end +end + +def fun_l25_n188(x) + if (x < 1) + fun_l26_n993(x) + else + fun_l26_n740(x) + end +end + +def fun_l25_n189(x) + if (x < 1) + fun_l26_n742(x) + else + fun_l26_n507(x) + end +end + +def fun_l25_n190(x) + if (x < 1) + fun_l26_n850(x) + else + fun_l26_n394(x) + end +end + +def fun_l25_n191(x) + if (x < 1) + fun_l26_n494(x) + else + fun_l26_n219(x) + end +end + +def fun_l25_n192(x) + if (x < 1) + fun_l26_n477(x) + else + fun_l26_n115(x) + end +end + +def fun_l25_n193(x) + if (x < 1) + fun_l26_n629(x) + else + fun_l26_n772(x) + end +end + +def fun_l25_n194(x) + if (x < 1) + fun_l26_n995(x) + else + fun_l26_n75(x) + end +end + +def fun_l25_n195(x) + if (x < 1) + fun_l26_n34(x) + else + fun_l26_n590(x) + end +end + +def fun_l25_n196(x) + if (x < 1) + fun_l26_n767(x) + else + fun_l26_n468(x) + end +end + +def fun_l25_n197(x) + if (x < 1) + fun_l26_n883(x) + else + fun_l26_n757(x) + end +end + +def fun_l25_n198(x) + if (x < 1) + fun_l26_n687(x) + else + fun_l26_n288(x) + end +end + +def fun_l25_n199(x) + if (x < 1) + fun_l26_n328(x) + else + fun_l26_n556(x) + end +end + +def fun_l25_n200(x) + if (x < 1) + fun_l26_n894(x) + else + fun_l26_n854(x) + end +end + +def fun_l25_n201(x) + if (x < 1) + fun_l26_n343(x) + else + fun_l26_n889(x) + end +end + +def fun_l25_n202(x) + if (x < 1) + fun_l26_n430(x) + else + fun_l26_n935(x) + end +end + +def fun_l25_n203(x) + if (x < 1) + fun_l26_n384(x) + else + fun_l26_n37(x) + end +end + +def fun_l25_n204(x) + if (x < 1) + fun_l26_n821(x) + else + fun_l26_n509(x) + end +end + +def fun_l25_n205(x) + if (x < 1) + fun_l26_n985(x) + else + fun_l26_n877(x) + end +end + +def fun_l25_n206(x) + if (x < 1) + fun_l26_n184(x) + else + fun_l26_n568(x) + end +end + +def fun_l25_n207(x) + if (x < 1) + fun_l26_n753(x) + else + fun_l26_n922(x) + end +end + +def fun_l25_n208(x) + if (x < 1) + fun_l26_n454(x) + else + fun_l26_n499(x) + end +end + +def fun_l25_n209(x) + if (x < 1) + fun_l26_n695(x) + else + fun_l26_n181(x) + end +end + +def fun_l25_n210(x) + if (x < 1) + fun_l26_n139(x) + else + fun_l26_n456(x) + end +end + +def fun_l25_n211(x) + if (x < 1) + fun_l26_n745(x) + else + fun_l26_n447(x) + end +end + +def fun_l25_n212(x) + if (x < 1) + fun_l26_n785(x) + else + fun_l26_n946(x) + end +end + +def fun_l25_n213(x) + if (x < 1) + fun_l26_n161(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n214(x) + if (x < 1) + fun_l26_n16(x) + else + fun_l26_n450(x) + end +end + +def fun_l25_n215(x) + if (x < 1) + fun_l26_n818(x) + else + fun_l26_n2(x) + end +end + +def fun_l25_n216(x) + if (x < 1) + fun_l26_n242(x) + else + fun_l26_n691(x) + end +end + +def fun_l25_n217(x) + if (x < 1) + fun_l26_n18(x) + else + fun_l26_n522(x) + end +end + +def fun_l25_n218(x) + if (x < 1) + fun_l26_n87(x) + else + fun_l26_n888(x) + end +end + +def fun_l25_n219(x) + if (x < 1) + fun_l26_n317(x) + else + fun_l26_n593(x) + end +end + +def fun_l25_n220(x) + if (x < 1) + fun_l26_n650(x) + else + fun_l26_n258(x) + end +end + +def fun_l25_n221(x) + if (x < 1) + fun_l26_n381(x) + else + fun_l26_n500(x) + end +end + +def fun_l25_n222(x) + if (x < 1) + fun_l26_n607(x) + else + fun_l26_n138(x) + end +end + +def fun_l25_n223(x) + if (x < 1) + fun_l26_n595(x) + else + fun_l26_n657(x) + end +end + +def fun_l25_n224(x) + if (x < 1) + fun_l26_n166(x) + else + fun_l26_n420(x) + end +end + +def fun_l25_n225(x) + if (x < 1) + fun_l26_n744(x) + else + fun_l26_n684(x) + end +end + +def fun_l25_n226(x) + if (x < 1) + fun_l26_n225(x) + else + fun_l26_n264(x) + end +end + +def fun_l25_n227(x) + if (x < 1) + fun_l26_n140(x) + else + fun_l26_n387(x) + end +end + +def fun_l25_n228(x) + if (x < 1) + fun_l26_n563(x) + else + fun_l26_n83(x) + end +end + +def fun_l25_n229(x) + if (x < 1) + fun_l26_n392(x) + else + fun_l26_n130(x) + end +end + +def fun_l25_n230(x) + if (x < 1) + fun_l26_n687(x) + else + fun_l26_n970(x) + end +end + +def fun_l25_n231(x) + if (x < 1) + fun_l26_n328(x) + else + fun_l26_n809(x) + end +end + +def fun_l25_n232(x) + if (x < 1) + fun_l26_n963(x) + else + fun_l26_n429(x) + end +end + +def fun_l25_n233(x) + if (x < 1) + fun_l26_n290(x) + else + fun_l26_n131(x) + end +end + +def fun_l25_n234(x) + if (x < 1) + fun_l26_n877(x) + else + fun_l26_n729(x) + end +end + +def fun_l25_n235(x) + if (x < 1) + fun_l26_n916(x) + else + fun_l26_n694(x) + end +end + +def fun_l25_n236(x) + if (x < 1) + fun_l26_n901(x) + else + fun_l26_n226(x) + end +end + +def fun_l25_n237(x) + if (x < 1) + fun_l26_n65(x) + else + fun_l26_n748(x) + end +end + +def fun_l25_n238(x) + if (x < 1) + fun_l26_n171(x) + else + fun_l26_n858(x) + end +end + +def fun_l25_n239(x) + if (x < 1) + fun_l26_n391(x) + else + fun_l26_n809(x) + end +end + +def fun_l25_n240(x) + if (x < 1) + fun_l26_n336(x) + else + fun_l26_n391(x) + end +end + +def fun_l25_n241(x) + if (x < 1) + fun_l26_n418(x) + else + fun_l26_n133(x) + end +end + +def fun_l25_n242(x) + if (x < 1) + fun_l26_n617(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n243(x) + if (x < 1) + fun_l26_n962(x) + else + fun_l26_n763(x) + end +end + +def fun_l25_n244(x) + if (x < 1) + fun_l26_n34(x) + else + fun_l26_n629(x) + end +end + +def fun_l25_n245(x) + if (x < 1) + fun_l26_n444(x) + else + fun_l26_n271(x) + end +end + +def fun_l25_n246(x) + if (x < 1) + fun_l26_n478(x) + else + fun_l26_n541(x) + end +end + +def fun_l25_n247(x) + if (x < 1) + fun_l26_n796(x) + else + fun_l26_n673(x) + end +end + +def fun_l25_n248(x) + if (x < 1) + fun_l26_n400(x) + else + fun_l26_n602(x) + end +end + +def fun_l25_n249(x) + if (x < 1) + fun_l26_n70(x) + else + fun_l26_n796(x) + end +end + +def fun_l25_n250(x) + if (x < 1) + fun_l26_n187(x) + else + fun_l26_n602(x) + end +end + +def fun_l25_n251(x) + if (x < 1) + fun_l26_n29(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n252(x) + if (x < 1) + fun_l26_n49(x) + else + fun_l26_n522(x) + end +end + +def fun_l25_n253(x) + if (x < 1) + fun_l26_n998(x) + else + fun_l26_n986(x) + end +end + +def fun_l25_n254(x) + if (x < 1) + fun_l26_n586(x) + else + fun_l26_n566(x) + end +end + +def fun_l25_n255(x) + if (x < 1) + fun_l26_n474(x) + else + fun_l26_n279(x) + end +end + +def fun_l25_n256(x) + if (x < 1) + fun_l26_n769(x) + else + fun_l26_n240(x) + end +end + +def fun_l25_n257(x) + if (x < 1) + fun_l26_n212(x) + else + fun_l26_n512(x) + end +end + +def fun_l25_n258(x) + if (x < 1) + fun_l26_n980(x) + else + fun_l26_n715(x) + end +end + +def fun_l25_n259(x) + if (x < 1) + fun_l26_n237(x) + else + fun_l26_n355(x) + end +end + +def fun_l25_n260(x) + if (x < 1) + fun_l26_n406(x) + else + fun_l26_n584(x) + end +end + +def fun_l25_n261(x) + if (x < 1) + fun_l26_n632(x) + else + fun_l26_n28(x) + end +end + +def fun_l25_n262(x) + if (x < 1) + fun_l26_n481(x) + else + fun_l26_n303(x) + end +end + +def fun_l25_n263(x) + if (x < 1) + fun_l26_n676(x) + else + fun_l26_n220(x) + end +end + +def fun_l25_n264(x) + if (x < 1) + fun_l26_n757(x) + else + fun_l26_n58(x) + end +end + +def fun_l25_n265(x) + if (x < 1) + fun_l26_n525(x) + else + fun_l26_n168(x) + end +end + +def fun_l25_n266(x) + if (x < 1) + fun_l26_n832(x) + else + fun_l26_n754(x) + end +end + +def fun_l25_n267(x) + if (x < 1) + fun_l26_n723(x) + else + fun_l26_n830(x) + end +end + +def fun_l25_n268(x) + if (x < 1) + fun_l26_n171(x) + else + fun_l26_n411(x) + end +end + +def fun_l25_n269(x) + if (x < 1) + fun_l26_n150(x) + else + fun_l26_n360(x) + end +end + +def fun_l25_n270(x) + if (x < 1) + fun_l26_n401(x) + else + fun_l26_n767(x) + end +end + +def fun_l25_n271(x) + if (x < 1) + fun_l26_n462(x) + else + fun_l26_n305(x) + end +end + +def fun_l25_n272(x) + if (x < 1) + fun_l26_n989(x) + else + fun_l26_n780(x) + end +end + +def fun_l25_n273(x) + if (x < 1) + fun_l26_n2(x) + else + fun_l26_n735(x) + end +end + +def fun_l25_n274(x) + if (x < 1) + fun_l26_n646(x) + else + fun_l26_n30(x) + end +end + +def fun_l25_n275(x) + if (x < 1) + fun_l26_n197(x) + else + fun_l26_n262(x) + end +end + +def fun_l25_n276(x) + if (x < 1) + fun_l26_n647(x) + else + fun_l26_n715(x) + end +end + +def fun_l25_n277(x) + if (x < 1) + fun_l26_n597(x) + else + fun_l26_n228(x) + end +end + +def fun_l25_n278(x) + if (x < 1) + fun_l26_n880(x) + else + fun_l26_n324(x) + end +end + +def fun_l25_n279(x) + if (x < 1) + fun_l26_n40(x) + else + fun_l26_n615(x) + end +end + +def fun_l25_n280(x) + if (x < 1) + fun_l26_n697(x) + else + fun_l26_n671(x) + end +end + +def fun_l25_n281(x) + if (x < 1) + fun_l26_n819(x) + else + fun_l26_n469(x) + end +end + +def fun_l25_n282(x) + if (x < 1) + fun_l26_n427(x) + else + fun_l26_n295(x) + end +end + +def fun_l25_n283(x) + if (x < 1) + fun_l26_n35(x) + else + fun_l26_n432(x) + end +end + +def fun_l25_n284(x) + if (x < 1) + fun_l26_n691(x) + else + fun_l26_n846(x) + end +end + +def fun_l25_n285(x) + if (x < 1) + fun_l26_n353(x) + else + fun_l26_n473(x) + end +end + +def fun_l25_n286(x) + if (x < 1) + fun_l26_n959(x) + else + fun_l26_n608(x) + end +end + +def fun_l25_n287(x) + if (x < 1) + fun_l26_n728(x) + else + fun_l26_n993(x) + end +end + +def fun_l25_n288(x) + if (x < 1) + fun_l26_n836(x) + else + fun_l26_n587(x) + end +end + +def fun_l25_n289(x) + if (x < 1) + fun_l26_n300(x) + else + fun_l26_n965(x) + end +end + +def fun_l25_n290(x) + if (x < 1) + fun_l26_n925(x) + else + fun_l26_n180(x) + end +end + +def fun_l25_n291(x) + if (x < 1) + fun_l26_n934(x) + else + fun_l26_n579(x) + end +end + +def fun_l25_n292(x) + if (x < 1) + fun_l26_n97(x) + else + fun_l26_n33(x) + end +end + +def fun_l25_n293(x) + if (x < 1) + fun_l26_n653(x) + else + fun_l26_n968(x) + end +end + +def fun_l25_n294(x) + if (x < 1) + fun_l26_n264(x) + else + fun_l26_n68(x) + end +end + +def fun_l25_n295(x) + if (x < 1) + fun_l26_n420(x) + else + fun_l26_n450(x) + end +end + +def fun_l25_n296(x) + if (x < 1) + fun_l26_n200(x) + else + fun_l26_n599(x) + end +end + +def fun_l25_n297(x) + if (x < 1) + fun_l26_n922(x) + else + fun_l26_n36(x) + end +end + +def fun_l25_n298(x) + if (x < 1) + fun_l26_n741(x) + else + fun_l26_n743(x) + end +end + +def fun_l25_n299(x) + if (x < 1) + fun_l26_n989(x) + else + fun_l26_n777(x) + end +end + +def fun_l25_n300(x) + if (x < 1) + fun_l26_n600(x) + else + fun_l26_n228(x) + end +end + +def fun_l25_n301(x) + if (x < 1) + fun_l26_n493(x) + else + fun_l26_n852(x) + end +end + +def fun_l25_n302(x) + if (x < 1) + fun_l26_n552(x) + else + fun_l26_n305(x) + end +end + +def fun_l25_n303(x) + if (x < 1) + fun_l26_n280(x) + else + fun_l26_n373(x) + end +end + +def fun_l25_n304(x) + if (x < 1) + fun_l26_n379(x) + else + fun_l26_n877(x) + end +end + +def fun_l25_n305(x) + if (x < 1) + fun_l26_n562(x) + else + fun_l26_n165(x) + end +end + +def fun_l25_n306(x) + if (x < 1) + fun_l26_n890(x) + else + fun_l26_n24(x) + end +end + +def fun_l25_n307(x) + if (x < 1) + fun_l26_n881(x) + else + fun_l26_n936(x) + end +end + +def fun_l25_n308(x) + if (x < 1) + fun_l26_n31(x) + else + fun_l26_n851(x) + end +end + +def fun_l25_n309(x) + if (x < 1) + fun_l26_n894(x) + else + fun_l26_n496(x) + end +end + +def fun_l25_n310(x) + if (x < 1) + fun_l26_n477(x) + else + fun_l26_n436(x) + end +end + +def fun_l25_n311(x) + if (x < 1) + fun_l26_n943(x) + else + fun_l26_n565(x) + end +end + +def fun_l25_n312(x) + if (x < 1) + fun_l26_n795(x) + else + fun_l26_n416(x) + end +end + +def fun_l25_n313(x) + if (x < 1) + fun_l26_n264(x) + else + fun_l26_n528(x) + end +end + +def fun_l25_n314(x) + if (x < 1) + fun_l26_n269(x) + else + fun_l26_n666(x) + end +end + +def fun_l25_n315(x) + if (x < 1) + fun_l26_n166(x) + else + fun_l26_n633(x) + end +end + +def fun_l25_n316(x) + if (x < 1) + fun_l26_n463(x) + else + fun_l26_n82(x) + end +end + +def fun_l25_n317(x) + if (x < 1) + fun_l26_n379(x) + else + fun_l26_n429(x) + end +end + +def fun_l25_n318(x) + if (x < 1) + fun_l26_n538(x) + else + fun_l26_n714(x) + end +end + +def fun_l25_n319(x) + if (x < 1) + fun_l26_n913(x) + else + fun_l26_n584(x) + end +end + +def fun_l25_n320(x) + if (x < 1) + fun_l26_n833(x) + else + fun_l26_n887(x) + end +end + +def fun_l25_n321(x) + if (x < 1) + fun_l26_n332(x) + else + fun_l26_n720(x) + end +end + +def fun_l25_n322(x) + if (x < 1) + fun_l26_n409(x) + else + fun_l26_n924(x) + end +end + +def fun_l25_n323(x) + if (x < 1) + fun_l26_n201(x) + else + fun_l26_n15(x) + end +end + +def fun_l25_n324(x) + if (x < 1) + fun_l26_n454(x) + else + fun_l26_n348(x) + end +end + +def fun_l25_n325(x) + if (x < 1) + fun_l26_n798(x) + else + fun_l26_n310(x) + end +end + +def fun_l25_n326(x) + if (x < 1) + fun_l26_n70(x) + else + fun_l26_n973(x) + end +end + +def fun_l25_n327(x) + if (x < 1) + fun_l26_n683(x) + else + fun_l26_n857(x) + end +end + +def fun_l25_n328(x) + if (x < 1) + fun_l26_n885(x) + else + fun_l26_n855(x) + end +end + +def fun_l25_n329(x) + if (x < 1) + fun_l26_n725(x) + else + fun_l26_n625(x) + end +end + +def fun_l25_n330(x) + if (x < 1) + fun_l26_n960(x) + else + fun_l26_n710(x) + end +end + +def fun_l25_n331(x) + if (x < 1) + fun_l26_n899(x) + else + fun_l26_n671(x) + end +end + +def fun_l25_n332(x) + if (x < 1) + fun_l26_n743(x) + else + fun_l26_n541(x) + end +end + +def fun_l25_n333(x) + if (x < 1) + fun_l26_n353(x) + else + fun_l26_n336(x) + end +end + +def fun_l25_n334(x) + if (x < 1) + fun_l26_n53(x) + else + fun_l26_n422(x) + end +end + +def fun_l25_n335(x) + if (x < 1) + fun_l26_n291(x) + else + fun_l26_n586(x) + end +end + +def fun_l25_n336(x) + if (x < 1) + fun_l26_n395(x) + else + fun_l26_n716(x) + end +end + +def fun_l25_n337(x) + if (x < 1) + fun_l26_n655(x) + else + fun_l26_n590(x) + end +end + +def fun_l25_n338(x) + if (x < 1) + fun_l26_n443(x) + else + fun_l26_n680(x) + end +end + +def fun_l25_n339(x) + if (x < 1) + fun_l26_n930(x) + else + fun_l26_n828(x) + end +end + +def fun_l25_n340(x) + if (x < 1) + fun_l26_n488(x) + else + fun_l26_n514(x) + end +end + +def fun_l25_n341(x) + if (x < 1) + fun_l26_n504(x) + else + fun_l26_n592(x) + end +end + +def fun_l25_n342(x) + if (x < 1) + fun_l26_n695(x) + else + fun_l26_n945(x) + end +end + +def fun_l25_n343(x) + if (x < 1) + fun_l26_n483(x) + else + fun_l26_n511(x) + end +end + +def fun_l25_n344(x) + if (x < 1) + fun_l26_n958(x) + else + fun_l26_n316(x) + end +end + +def fun_l25_n345(x) + if (x < 1) + fun_l26_n481(x) + else + fun_l26_n473(x) + end +end + +def fun_l25_n346(x) + if (x < 1) + fun_l26_n340(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n347(x) + if (x < 1) + fun_l26_n222(x) + else + fun_l26_n232(x) + end +end + +def fun_l25_n348(x) + if (x < 1) + fun_l26_n162(x) + else + fun_l26_n846(x) + end +end + +def fun_l25_n349(x) + if (x < 1) + fun_l26_n56(x) + else + fun_l26_n93(x) + end +end + +def fun_l25_n350(x) + if (x < 1) + fun_l26_n191(x) + else + fun_l26_n245(x) + end +end + +def fun_l25_n351(x) + if (x < 1) + fun_l26_n294(x) + else + fun_l26_n494(x) + end +end + +def fun_l25_n352(x) + if (x < 1) + fun_l26_n591(x) + else + fun_l26_n524(x) + end +end + +def fun_l25_n353(x) + if (x < 1) + fun_l26_n904(x) + else + fun_l26_n793(x) + end +end + +def fun_l25_n354(x) + if (x < 1) + fun_l26_n1(x) + else + fun_l26_n432(x) + end +end + +def fun_l25_n355(x) + if (x < 1) + fun_l26_n757(x) + else + fun_l26_n733(x) + end +end + +def fun_l25_n356(x) + if (x < 1) + fun_l26_n987(x) + else + fun_l26_n425(x) + end +end + +def fun_l25_n357(x) + if (x < 1) + fun_l26_n288(x) + else + fun_l26_n587(x) + end +end + +def fun_l25_n358(x) + if (x < 1) + fun_l26_n843(x) + else + fun_l26_n731(x) + end +end + +def fun_l25_n359(x) + if (x < 1) + fun_l26_n433(x) + else + fun_l26_n208(x) + end +end + +def fun_l25_n360(x) + if (x < 1) + fun_l26_n473(x) + else + fun_l26_n992(x) + end +end + +def fun_l25_n361(x) + if (x < 1) + fun_l26_n210(x) + else + fun_l26_n704(x) + end +end + +def fun_l25_n362(x) + if (x < 1) + fun_l26_n625(x) + else + fun_l26_n365(x) + end +end + +def fun_l25_n363(x) + if (x < 1) + fun_l26_n55(x) + else + fun_l26_n555(x) + end +end + +def fun_l25_n364(x) + if (x < 1) + fun_l26_n763(x) + else + fun_l26_n417(x) + end +end + +def fun_l25_n365(x) + if (x < 1) + fun_l26_n557(x) + else + fun_l26_n24(x) + end +end + +def fun_l25_n366(x) + if (x < 1) + fun_l26_n791(x) + else + fun_l26_n753(x) + end +end + +def fun_l25_n367(x) + if (x < 1) + fun_l26_n490(x) + else + fun_l26_n765(x) + end +end + +def fun_l25_n368(x) + if (x < 1) + fun_l26_n875(x) + else + fun_l26_n628(x) + end +end + +def fun_l25_n369(x) + if (x < 1) + fun_l26_n544(x) + else + fun_l26_n234(x) + end +end + +def fun_l25_n370(x) + if (x < 1) + fun_l26_n288(x) + else + fun_l26_n524(x) + end +end + +def fun_l25_n371(x) + if (x < 1) + fun_l26_n548(x) + else + fun_l26_n782(x) + end +end + +def fun_l25_n372(x) + if (x < 1) + fun_l26_n112(x) + else + fun_l26_n861(x) + end +end + +def fun_l25_n373(x) + if (x < 1) + fun_l26_n565(x) + else + fun_l26_n442(x) + end +end + +def fun_l25_n374(x) + if (x < 1) + fun_l26_n37(x) + else + fun_l26_n810(x) + end +end + +def fun_l25_n375(x) + if (x < 1) + fun_l26_n384(x) + else + fun_l26_n103(x) + end +end + +def fun_l25_n376(x) + if (x < 1) + fun_l26_n371(x) + else + fun_l26_n219(x) + end +end + +def fun_l25_n377(x) + if (x < 1) + fun_l26_n964(x) + else + fun_l26_n542(x) + end +end + +def fun_l25_n378(x) + if (x < 1) + fun_l26_n617(x) + else + fun_l26_n616(x) + end +end + +def fun_l25_n379(x) + if (x < 1) + fun_l26_n94(x) + else + fun_l26_n870(x) + end +end + +def fun_l25_n380(x) + if (x < 1) + fun_l26_n538(x) + else + fun_l26_n483(x) + end +end + +def fun_l25_n381(x) + if (x < 1) + fun_l26_n395(x) + else + fun_l26_n873(x) + end +end + +def fun_l25_n382(x) + if (x < 1) + fun_l26_n406(x) + else + fun_l26_n843(x) + end +end + +def fun_l25_n383(x) + if (x < 1) + fun_l26_n422(x) + else + fun_l26_n367(x) + end +end + +def fun_l25_n384(x) + if (x < 1) + fun_l26_n472(x) + else + fun_l26_n676(x) + end +end + +def fun_l25_n385(x) + if (x < 1) + fun_l26_n782(x) + else + fun_l26_n995(x) + end +end + +def fun_l25_n386(x) + if (x < 1) + fun_l26_n655(x) + else + fun_l26_n758(x) + end +end + +def fun_l25_n387(x) + if (x < 1) + fun_l26_n665(x) + else + fun_l26_n775(x) + end +end + +def fun_l25_n388(x) + if (x < 1) + fun_l26_n168(x) + else + fun_l26_n604(x) + end +end + +def fun_l25_n389(x) + if (x < 1) + fun_l26_n31(x) + else + fun_l26_n681(x) + end +end + +def fun_l25_n390(x) + if (x < 1) + fun_l26_n758(x) + else + fun_l26_n596(x) + end +end + +def fun_l25_n391(x) + if (x < 1) + fun_l26_n413(x) + else + fun_l26_n528(x) + end +end + +def fun_l25_n392(x) + if (x < 1) + fun_l26_n136(x) + else + fun_l26_n408(x) + end +end + +def fun_l25_n393(x) + if (x < 1) + fun_l26_n493(x) + else + fun_l26_n182(x) + end +end + +def fun_l25_n394(x) + if (x < 1) + fun_l26_n156(x) + else + fun_l26_n775(x) + end +end + +def fun_l25_n395(x) + if (x < 1) + fun_l26_n839(x) + else + fun_l26_n823(x) + end +end + +def fun_l25_n396(x) + if (x < 1) + fun_l26_n248(x) + else + fun_l26_n679(x) + end +end + +def fun_l25_n397(x) + if (x < 1) + fun_l26_n594(x) + else + fun_l26_n117(x) + end +end + +def fun_l25_n398(x) + if (x < 1) + fun_l26_n82(x) + else + fun_l26_n595(x) + end +end + +def fun_l25_n399(x) + if (x < 1) + fun_l26_n978(x) + else + fun_l26_n391(x) + end +end + +def fun_l25_n400(x) + if (x < 1) + fun_l26_n731(x) + else + fun_l26_n252(x) + end +end + +def fun_l25_n401(x) + if (x < 1) + fun_l26_n297(x) + else + fun_l26_n918(x) + end +end + +def fun_l25_n402(x) + if (x < 1) + fun_l26_n745(x) + else + fun_l26_n972(x) + end +end + +def fun_l25_n403(x) + if (x < 1) + fun_l26_n685(x) + else + fun_l26_n555(x) + end +end + +def fun_l25_n404(x) + if (x < 1) + fun_l26_n667(x) + else + fun_l26_n384(x) + end +end + +def fun_l25_n405(x) + if (x < 1) + fun_l26_n330(x) + else + fun_l26_n440(x) + end +end + +def fun_l25_n406(x) + if (x < 1) + fun_l26_n911(x) + else + fun_l26_n580(x) + end +end + +def fun_l25_n407(x) + if (x < 1) + fun_l26_n789(x) + else + fun_l26_n297(x) + end +end + +def fun_l25_n408(x) + if (x < 1) + fun_l26_n879(x) + else + fun_l26_n201(x) + end +end + +def fun_l25_n409(x) + if (x < 1) + fun_l26_n36(x) + else + fun_l26_n885(x) + end +end + +def fun_l25_n410(x) + if (x < 1) + fun_l26_n224(x) + else + fun_l26_n571(x) + end +end + +def fun_l25_n411(x) + if (x < 1) + fun_l26_n395(x) + else + fun_l26_n640(x) + end +end + +def fun_l25_n412(x) + if (x < 1) + fun_l26_n754(x) + else + fun_l26_n754(x) + end +end + +def fun_l25_n413(x) + if (x < 1) + fun_l26_n885(x) + else + fun_l26_n857(x) + end +end + +def fun_l25_n414(x) + if (x < 1) + fun_l26_n464(x) + else + fun_l26_n44(x) + end +end + +def fun_l25_n415(x) + if (x < 1) + fun_l26_n13(x) + else + fun_l26_n546(x) + end +end + +def fun_l25_n416(x) + if (x < 1) + fun_l26_n318(x) + else + fun_l26_n313(x) + end +end + +def fun_l25_n417(x) + if (x < 1) + fun_l26_n98(x) + else + fun_l26_n139(x) + end +end + +def fun_l25_n418(x) + if (x < 1) + fun_l26_n654(x) + else + fun_l26_n602(x) + end +end + +def fun_l25_n419(x) + if (x < 1) + fun_l26_n808(x) + else + fun_l26_n987(x) + end +end + +def fun_l25_n420(x) + if (x < 1) + fun_l26_n878(x) + else + fun_l26_n36(x) + end +end + +def fun_l25_n421(x) + if (x < 1) + fun_l26_n427(x) + else + fun_l26_n620(x) + end +end + +def fun_l25_n422(x) + if (x < 1) + fun_l26_n118(x) + else + fun_l26_n145(x) + end +end + +def fun_l25_n423(x) + if (x < 1) + fun_l26_n131(x) + else + fun_l26_n520(x) + end +end + +def fun_l25_n424(x) + if (x < 1) + fun_l26_n295(x) + else + fun_l26_n197(x) + end +end + +def fun_l25_n425(x) + if (x < 1) + fun_l26_n632(x) + else + fun_l26_n951(x) + end +end + +def fun_l25_n426(x) + if (x < 1) + fun_l26_n92(x) + else + fun_l26_n96(x) + end +end + +def fun_l25_n427(x) + if (x < 1) + fun_l26_n677(x) + else + fun_l26_n5(x) + end +end + +def fun_l25_n428(x) + if (x < 1) + fun_l26_n425(x) + else + fun_l26_n864(x) + end +end + +def fun_l25_n429(x) + if (x < 1) + fun_l26_n187(x) + else + fun_l26_n62(x) + end +end + +def fun_l25_n430(x) + if (x < 1) + fun_l26_n964(x) + else + fun_l26_n704(x) + end +end + +def fun_l25_n431(x) + if (x < 1) + fun_l26_n109(x) + else + fun_l26_n181(x) + end +end + +def fun_l25_n432(x) + if (x < 1) + fun_l26_n620(x) + else + fun_l26_n484(x) + end +end + +def fun_l25_n433(x) + if (x < 1) + fun_l26_n283(x) + else + fun_l26_n622(x) + end +end + +def fun_l25_n434(x) + if (x < 1) + fun_l26_n377(x) + else + fun_l26_n357(x) + end +end + +def fun_l25_n435(x) + if (x < 1) + fun_l26_n375(x) + else + fun_l26_n346(x) + end +end + +def fun_l25_n436(x) + if (x < 1) + fun_l26_n50(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n437(x) + if (x < 1) + fun_l26_n348(x) + else + fun_l26_n465(x) + end +end + +def fun_l25_n438(x) + if (x < 1) + fun_l26_n206(x) + else + fun_l26_n968(x) + end +end + +def fun_l25_n439(x) + if (x < 1) + fun_l26_n878(x) + else + fun_l26_n248(x) + end +end + +def fun_l25_n440(x) + if (x < 1) + fun_l26_n469(x) + else + fun_l26_n842(x) + end +end + +def fun_l25_n441(x) + if (x < 1) + fun_l26_n476(x) + else + fun_l26_n666(x) + end +end + +def fun_l25_n442(x) + if (x < 1) + fun_l26_n491(x) + else + fun_l26_n365(x) + end +end + +def fun_l25_n443(x) + if (x < 1) + fun_l26_n412(x) + else + fun_l26_n308(x) + end +end + +def fun_l25_n444(x) + if (x < 1) + fun_l26_n750(x) + else + fun_l26_n82(x) + end +end + +def fun_l25_n445(x) + if (x < 1) + fun_l26_n434(x) + else + fun_l26_n711(x) + end +end + +def fun_l25_n446(x) + if (x < 1) + fun_l26_n698(x) + else + fun_l26_n407(x) + end +end + +def fun_l25_n447(x) + if (x < 1) + fun_l26_n992(x) + else + fun_l26_n404(x) + end +end + +def fun_l25_n448(x) + if (x < 1) + fun_l26_n723(x) + else + fun_l26_n317(x) + end +end + +def fun_l25_n449(x) + if (x < 1) + fun_l26_n582(x) + else + fun_l26_n384(x) + end +end + +def fun_l25_n450(x) + if (x < 1) + fun_l26_n956(x) + else + fun_l26_n111(x) + end +end + +def fun_l25_n451(x) + if (x < 1) + fun_l26_n506(x) + else + fun_l26_n775(x) + end +end + +def fun_l25_n452(x) + if (x < 1) + fun_l26_n857(x) + else + fun_l26_n884(x) + end +end + +def fun_l25_n453(x) + if (x < 1) + fun_l26_n889(x) + else + fun_l26_n471(x) + end +end + +def fun_l25_n454(x) + if (x < 1) + fun_l26_n850(x) + else + fun_l26_n204(x) + end +end + +def fun_l25_n455(x) + if (x < 1) + fun_l26_n244(x) + else + fun_l26_n507(x) + end +end + +def fun_l25_n456(x) + if (x < 1) + fun_l26_n875(x) + else + fun_l26_n694(x) + end +end + +def fun_l25_n457(x) + if (x < 1) + fun_l26_n517(x) + else + fun_l26_n64(x) + end +end + +def fun_l25_n458(x) + if (x < 1) + fun_l26_n870(x) + else + fun_l26_n495(x) + end +end + +def fun_l25_n459(x) + if (x < 1) + fun_l26_n577(x) + else + fun_l26_n42(x) + end +end + +def fun_l25_n460(x) + if (x < 1) + fun_l26_n919(x) + else + fun_l26_n508(x) + end +end + +def fun_l25_n461(x) + if (x < 1) + fun_l26_n334(x) + else + fun_l26_n720(x) + end +end + +def fun_l25_n462(x) + if (x < 1) + fun_l26_n682(x) + else + fun_l26_n422(x) + end +end + +def fun_l25_n463(x) + if (x < 1) + fun_l26_n415(x) + else + fun_l26_n505(x) + end +end + +def fun_l25_n464(x) + if (x < 1) + fun_l26_n783(x) + else + fun_l26_n269(x) + end +end + +def fun_l25_n465(x) + if (x < 1) + fun_l26_n797(x) + else + fun_l26_n780(x) + end +end + +def fun_l25_n466(x) + if (x < 1) + fun_l26_n806(x) + else + fun_l26_n773(x) + end +end + +def fun_l25_n467(x) + if (x < 1) + fun_l26_n922(x) + else + fun_l26_n45(x) + end +end + +def fun_l25_n468(x) + if (x < 1) + fun_l26_n919(x) + else + fun_l26_n780(x) + end +end + +def fun_l25_n469(x) + if (x < 1) + fun_l26_n354(x) + else + fun_l26_n360(x) + end +end + +def fun_l25_n470(x) + if (x < 1) + fun_l26_n492(x) + else + fun_l26_n230(x) + end +end + +def fun_l25_n471(x) + if (x < 1) + fun_l26_n1(x) + else + fun_l26_n845(x) + end +end + +def fun_l25_n472(x) + if (x < 1) + fun_l26_n854(x) + else + fun_l26_n408(x) + end +end + +def fun_l25_n473(x) + if (x < 1) + fun_l26_n17(x) + else + fun_l26_n570(x) + end +end + +def fun_l25_n474(x) + if (x < 1) + fun_l26_n485(x) + else + fun_l26_n953(x) + end +end + +def fun_l25_n475(x) + if (x < 1) + fun_l26_n398(x) + else + fun_l26_n712(x) + end +end + +def fun_l25_n476(x) + if (x < 1) + fun_l26_n499(x) + else + fun_l26_n218(x) + end +end + +def fun_l25_n477(x) + if (x < 1) + fun_l26_n107(x) + else + fun_l26_n38(x) + end +end + +def fun_l25_n478(x) + if (x < 1) + fun_l26_n234(x) + else + fun_l26_n718(x) + end +end + +def fun_l25_n479(x) + if (x < 1) + fun_l26_n396(x) + else + fun_l26_n247(x) + end +end + +def fun_l25_n480(x) + if (x < 1) + fun_l26_n457(x) + else + fun_l26_n259(x) + end +end + +def fun_l25_n481(x) + if (x < 1) + fun_l26_n581(x) + else + fun_l26_n512(x) + end +end + +def fun_l25_n482(x) + if (x < 1) + fun_l26_n262(x) + else + fun_l26_n790(x) + end +end + +def fun_l25_n483(x) + if (x < 1) + fun_l26_n140(x) + else + fun_l26_n821(x) + end +end + +def fun_l25_n484(x) + if (x < 1) + fun_l26_n133(x) + else + fun_l26_n863(x) + end +end + +def fun_l25_n485(x) + if (x < 1) + fun_l26_n440(x) + else + fun_l26_n265(x) + end +end + +def fun_l25_n486(x) + if (x < 1) + fun_l26_n913(x) + else + fun_l26_n994(x) + end +end + +def fun_l25_n487(x) + if (x < 1) + fun_l26_n186(x) + else + fun_l26_n433(x) + end +end + +def fun_l25_n488(x) + if (x < 1) + fun_l26_n357(x) + else + fun_l26_n16(x) + end +end + +def fun_l25_n489(x) + if (x < 1) + fun_l26_n165(x) + else + fun_l26_n674(x) + end +end + +def fun_l25_n490(x) + if (x < 1) + fun_l26_n772(x) + else + fun_l26_n749(x) + end +end + +def fun_l25_n491(x) + if (x < 1) + fun_l26_n677(x) + else + fun_l26_n36(x) + end +end + +def fun_l25_n492(x) + if (x < 1) + fun_l26_n962(x) + else + fun_l26_n750(x) + end +end + +def fun_l25_n493(x) + if (x < 1) + fun_l26_n22(x) + else + fun_l26_n657(x) + end +end + +def fun_l25_n494(x) + if (x < 1) + fun_l26_n302(x) + else + fun_l26_n394(x) + end +end + +def fun_l25_n495(x) + if (x < 1) + fun_l26_n313(x) + else + fun_l26_n552(x) + end +end + +def fun_l25_n496(x) + if (x < 1) + fun_l26_n946(x) + else + fun_l26_n447(x) + end +end + +def fun_l25_n497(x) + if (x < 1) + fun_l26_n565(x) + else + fun_l26_n242(x) + end +end + +def fun_l25_n498(x) + if (x < 1) + fun_l26_n932(x) + else + fun_l26_n413(x) + end +end + +def fun_l25_n499(x) + if (x < 1) + fun_l26_n751(x) + else + fun_l26_n921(x) + end +end + +def fun_l25_n500(x) + if (x < 1) + fun_l26_n1(x) + else + fun_l26_n722(x) + end +end + +def fun_l25_n501(x) + if (x < 1) + fun_l26_n63(x) + else + fun_l26_n205(x) + end +end + +def fun_l25_n502(x) + if (x < 1) + fun_l26_n67(x) + else + fun_l26_n638(x) + end +end + +def fun_l25_n503(x) + if (x < 1) + fun_l26_n762(x) + else + fun_l26_n688(x) + end +end + +def fun_l25_n504(x) + if (x < 1) + fun_l26_n839(x) + else + fun_l26_n775(x) + end +end + +def fun_l25_n505(x) + if (x < 1) + fun_l26_n773(x) + else + fun_l26_n986(x) + end +end + +def fun_l25_n506(x) + if (x < 1) + fun_l26_n934(x) + else + fun_l26_n117(x) + end +end + +def fun_l25_n507(x) + if (x < 1) + fun_l26_n507(x) + else + fun_l26_n217(x) + end +end + +def fun_l25_n508(x) + if (x < 1) + fun_l26_n833(x) + else + fun_l26_n779(x) + end +end + +def fun_l25_n509(x) + if (x < 1) + fun_l26_n244(x) + else + fun_l26_n71(x) + end +end + +def fun_l25_n510(x) + if (x < 1) + fun_l26_n466(x) + else + fun_l26_n440(x) + end +end + +def fun_l25_n511(x) + if (x < 1) + fun_l26_n829(x) + else + fun_l26_n459(x) + end +end + +def fun_l25_n512(x) + if (x < 1) + fun_l26_n923(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n513(x) + if (x < 1) + fun_l26_n925(x) + else + fun_l26_n758(x) + end +end + +def fun_l25_n514(x) + if (x < 1) + fun_l26_n782(x) + else + fun_l26_n157(x) + end +end + +def fun_l25_n515(x) + if (x < 1) + fun_l26_n987(x) + else + fun_l26_n407(x) + end +end + +def fun_l25_n516(x) + if (x < 1) + fun_l26_n224(x) + else + fun_l26_n531(x) + end +end + +def fun_l25_n517(x) + if (x < 1) + fun_l26_n222(x) + else + fun_l26_n141(x) + end +end + +def fun_l25_n518(x) + if (x < 1) + fun_l26_n723(x) + else + fun_l26_n787(x) + end +end + +def fun_l25_n519(x) + if (x < 1) + fun_l26_n802(x) + else + fun_l26_n448(x) + end +end + +def fun_l25_n520(x) + if (x < 1) + fun_l26_n152(x) + else + fun_l26_n666(x) + end +end + +def fun_l25_n521(x) + if (x < 1) + fun_l26_n476(x) + else + fun_l26_n7(x) + end +end + +def fun_l25_n522(x) + if (x < 1) + fun_l26_n523(x) + else + fun_l26_n326(x) + end +end + +def fun_l25_n523(x) + if (x < 1) + fun_l26_n432(x) + else + fun_l26_n525(x) + end +end + +def fun_l25_n524(x) + if (x < 1) + fun_l26_n403(x) + else + fun_l26_n983(x) + end +end + +def fun_l25_n525(x) + if (x < 1) + fun_l26_n681(x) + else + fun_l26_n326(x) + end +end + +def fun_l25_n526(x) + if (x < 1) + fun_l26_n352(x) + else + fun_l26_n402(x) + end +end + +def fun_l25_n527(x) + if (x < 1) + fun_l26_n870(x) + else + fun_l26_n181(x) + end +end + +def fun_l25_n528(x) + if (x < 1) + fun_l26_n382(x) + else + fun_l26_n880(x) + end +end + +def fun_l25_n529(x) + if (x < 1) + fun_l26_n337(x) + else + fun_l26_n616(x) + end +end + +def fun_l25_n530(x) + if (x < 1) + fun_l26_n959(x) + else + fun_l26_n239(x) + end +end + +def fun_l25_n531(x) + if (x < 1) + fun_l26_n57(x) + else + fun_l26_n896(x) + end +end + +def fun_l25_n532(x) + if (x < 1) + fun_l26_n456(x) + else + fun_l26_n365(x) + end +end + +def fun_l25_n533(x) + if (x < 1) + fun_l26_n73(x) + else + fun_l26_n420(x) + end +end + +def fun_l25_n534(x) + if (x < 1) + fun_l26_n295(x) + else + fun_l26_n663(x) + end +end + +def fun_l25_n535(x) + if (x < 1) + fun_l26_n881(x) + else + fun_l26_n391(x) + end +end + +def fun_l25_n536(x) + if (x < 1) + fun_l26_n775(x) + else + fun_l26_n19(x) + end +end + +def fun_l25_n537(x) + if (x < 1) + fun_l26_n954(x) + else + fun_l26_n97(x) + end +end + +def fun_l25_n538(x) + if (x < 1) + fun_l26_n764(x) + else + fun_l26_n353(x) + end +end + +def fun_l25_n539(x) + if (x < 1) + fun_l26_n220(x) + else + fun_l26_n958(x) + end +end + +def fun_l25_n540(x) + if (x < 1) + fun_l26_n915(x) + else + fun_l26_n792(x) + end +end + +def fun_l25_n541(x) + if (x < 1) + fun_l26_n880(x) + else + fun_l26_n374(x) + end +end + +def fun_l25_n542(x) + if (x < 1) + fun_l26_n655(x) + else + fun_l26_n578(x) + end +end + +def fun_l25_n543(x) + if (x < 1) + fun_l26_n862(x) + else + fun_l26_n177(x) + end +end + +def fun_l25_n544(x) + if (x < 1) + fun_l26_n286(x) + else + fun_l26_n670(x) + end +end + +def fun_l25_n545(x) + if (x < 1) + fun_l26_n862(x) + else + fun_l26_n45(x) + end +end + +def fun_l25_n546(x) + if (x < 1) + fun_l26_n743(x) + else + fun_l26_n575(x) + end +end + +def fun_l25_n547(x) + if (x < 1) + fun_l26_n909(x) + else + fun_l26_n457(x) + end +end + +def fun_l25_n548(x) + if (x < 1) + fun_l26_n784(x) + else + fun_l26_n482(x) + end +end + +def fun_l25_n549(x) + if (x < 1) + fun_l26_n381(x) + else + fun_l26_n560(x) + end +end + +def fun_l25_n550(x) + if (x < 1) + fun_l26_n62(x) + else + fun_l26_n640(x) + end +end + +def fun_l25_n551(x) + if (x < 1) + fun_l26_n714(x) + else + fun_l26_n898(x) + end +end + +def fun_l25_n552(x) + if (x < 1) + fun_l26_n515(x) + else + fun_l26_n221(x) + end +end + +def fun_l25_n553(x) + if (x < 1) + fun_l26_n217(x) + else + fun_l26_n932(x) + end +end + +def fun_l25_n554(x) + if (x < 1) + fun_l26_n583(x) + else + fun_l26_n722(x) + end +end + +def fun_l25_n555(x) + if (x < 1) + fun_l26_n398(x) + else + fun_l26_n503(x) + end +end + +def fun_l25_n556(x) + if (x < 1) + fun_l26_n891(x) + else + fun_l26_n72(x) + end +end + +def fun_l25_n557(x) + if (x < 1) + fun_l26_n367(x) + else + fun_l26_n141(x) + end +end + +def fun_l25_n558(x) + if (x < 1) + fun_l26_n477(x) + else + fun_l26_n40(x) + end +end + +def fun_l25_n559(x) + if (x < 1) + fun_l26_n156(x) + else + fun_l26_n491(x) + end +end + +def fun_l25_n560(x) + if (x < 1) + fun_l26_n859(x) + else + fun_l26_n423(x) + end +end + +def fun_l25_n561(x) + if (x < 1) + fun_l26_n693(x) + else + fun_l26_n281(x) + end +end + +def fun_l25_n562(x) + if (x < 1) + fun_l26_n460(x) + else + fun_l26_n151(x) + end +end + +def fun_l25_n563(x) + if (x < 1) + fun_l26_n14(x) + else + fun_l26_n395(x) + end +end + +def fun_l25_n564(x) + if (x < 1) + fun_l26_n423(x) + else + fun_l26_n198(x) + end +end + +def fun_l25_n565(x) + if (x < 1) + fun_l26_n911(x) + else + fun_l26_n841(x) + end +end + +def fun_l25_n566(x) + if (x < 1) + fun_l26_n273(x) + else + fun_l26_n361(x) + end +end + +def fun_l25_n567(x) + if (x < 1) + fun_l26_n94(x) + else + fun_l26_n932(x) + end +end + +def fun_l25_n568(x) + if (x < 1) + fun_l26_n734(x) + else + fun_l26_n191(x) + end +end + +def fun_l25_n569(x) + if (x < 1) + fun_l26_n699(x) + else + fun_l26_n496(x) + end +end + +def fun_l25_n570(x) + if (x < 1) + fun_l26_n90(x) + else + fun_l26_n574(x) + end +end + +def fun_l25_n571(x) + if (x < 1) + fun_l26_n818(x) + else + fun_l26_n529(x) + end +end + +def fun_l25_n572(x) + if (x < 1) + fun_l26_n459(x) + else + fun_l26_n770(x) + end +end + +def fun_l25_n573(x) + if (x < 1) + fun_l26_n725(x) + else + fun_l26_n896(x) + end +end + +def fun_l25_n574(x) + if (x < 1) + fun_l26_n773(x) + else + fun_l26_n8(x) + end +end + +def fun_l25_n575(x) + if (x < 1) + fun_l26_n582(x) + else + fun_l26_n274(x) + end +end + +def fun_l25_n576(x) + if (x < 1) + fun_l26_n529(x) + else + fun_l26_n434(x) + end +end + +def fun_l25_n577(x) + if (x < 1) + fun_l26_n197(x) + else + fun_l26_n88(x) + end +end + +def fun_l25_n578(x) + if (x < 1) + fun_l26_n938(x) + else + fun_l26_n184(x) + end +end + +def fun_l25_n579(x) + if (x < 1) + fun_l26_n801(x) + else + fun_l26_n990(x) + end +end + +def fun_l25_n580(x) + if (x < 1) + fun_l26_n732(x) + else + fun_l26_n955(x) + end +end + +def fun_l25_n581(x) + if (x < 1) + fun_l26_n130(x) + else + fun_l26_n167(x) + end +end + +def fun_l25_n582(x) + if (x < 1) + fun_l26_n942(x) + else + fun_l26_n352(x) + end +end + +def fun_l25_n583(x) + if (x < 1) + fun_l26_n673(x) + else + fun_l26_n613(x) + end +end + +def fun_l25_n584(x) + if (x < 1) + fun_l26_n386(x) + else + fun_l26_n840(x) + end +end + +def fun_l25_n585(x) + if (x < 1) + fun_l26_n847(x) + else + fun_l26_n372(x) + end +end + +def fun_l25_n586(x) + if (x < 1) + fun_l26_n0(x) + else + fun_l26_n717(x) + end +end + +def fun_l25_n587(x) + if (x < 1) + fun_l26_n403(x) + else + fun_l26_n689(x) + end +end + +def fun_l25_n588(x) + if (x < 1) + fun_l26_n325(x) + else + fun_l26_n75(x) + end +end + +def fun_l25_n589(x) + if (x < 1) + fun_l26_n653(x) + else + fun_l26_n993(x) + end +end + +def fun_l25_n590(x) + if (x < 1) + fun_l26_n413(x) + else + fun_l26_n428(x) + end +end + +def fun_l25_n591(x) + if (x < 1) + fun_l26_n93(x) + else + fun_l26_n264(x) + end +end + +def fun_l25_n592(x) + if (x < 1) + fun_l26_n117(x) + else + fun_l26_n466(x) + end +end + +def fun_l25_n593(x) + if (x < 1) + fun_l26_n463(x) + else + fun_l26_n270(x) + end +end + +def fun_l25_n594(x) + if (x < 1) + fun_l26_n348(x) + else + fun_l26_n844(x) + end +end + +def fun_l25_n595(x) + if (x < 1) + fun_l26_n939(x) + else + fun_l26_n891(x) + end +end + +def fun_l25_n596(x) + if (x < 1) + fun_l26_n949(x) + else + fun_l26_n743(x) + end +end + +def fun_l25_n597(x) + if (x < 1) + fun_l26_n884(x) + else + fun_l26_n831(x) + end +end + +def fun_l25_n598(x) + if (x < 1) + fun_l26_n910(x) + else + fun_l26_n79(x) + end +end + +def fun_l25_n599(x) + if (x < 1) + fun_l26_n491(x) + else + fun_l26_n727(x) + end +end + +def fun_l25_n600(x) + if (x < 1) + fun_l26_n295(x) + else + fun_l26_n929(x) + end +end + +def fun_l25_n601(x) + if (x < 1) + fun_l26_n130(x) + else + fun_l26_n35(x) + end +end + +def fun_l25_n602(x) + if (x < 1) + fun_l26_n673(x) + else + fun_l26_n103(x) + end +end + +def fun_l25_n603(x) + if (x < 1) + fun_l26_n669(x) + else + fun_l26_n449(x) + end +end + +def fun_l25_n604(x) + if (x < 1) + fun_l26_n201(x) + else + fun_l26_n616(x) + end +end + +def fun_l25_n605(x) + if (x < 1) + fun_l26_n326(x) + else + fun_l26_n718(x) + end +end + +def fun_l25_n606(x) + if (x < 1) + fun_l26_n857(x) + else + fun_l26_n188(x) + end +end + +def fun_l25_n607(x) + if (x < 1) + fun_l26_n351(x) + else + fun_l26_n688(x) + end +end + +def fun_l25_n608(x) + if (x < 1) + fun_l26_n652(x) + else + fun_l26_n280(x) + end +end + +def fun_l25_n609(x) + if (x < 1) + fun_l26_n994(x) + else + fun_l26_n341(x) + end +end + +def fun_l25_n610(x) + if (x < 1) + fun_l26_n876(x) + else + fun_l26_n643(x) + end +end + +def fun_l25_n611(x) + if (x < 1) + fun_l26_n825(x) + else + fun_l26_n306(x) + end +end + +def fun_l25_n612(x) + if (x < 1) + fun_l26_n139(x) + else + fun_l26_n452(x) + end +end + +def fun_l25_n613(x) + if (x < 1) + fun_l26_n689(x) + else + fun_l26_n818(x) + end +end + +def fun_l25_n614(x) + if (x < 1) + fun_l26_n171(x) + else + fun_l26_n366(x) + end +end + +def fun_l25_n615(x) + if (x < 1) + fun_l26_n658(x) + else + fun_l26_n603(x) + end +end + +def fun_l25_n616(x) + if (x < 1) + fun_l26_n150(x) + else + fun_l26_n603(x) + end +end + +def fun_l25_n617(x) + if (x < 1) + fun_l26_n432(x) + else + fun_l26_n391(x) + end +end + +def fun_l25_n618(x) + if (x < 1) + fun_l26_n79(x) + else + fun_l26_n416(x) + end +end + +def fun_l25_n619(x) + if (x < 1) + fun_l26_n494(x) + else + fun_l26_n355(x) + end +end + +def fun_l25_n620(x) + if (x < 1) + fun_l26_n868(x) + else + fun_l26_n461(x) + end +end + +def fun_l25_n621(x) + if (x < 1) + fun_l26_n954(x) + else + fun_l26_n31(x) + end +end + +def fun_l25_n622(x) + if (x < 1) + fun_l26_n620(x) + else + fun_l26_n777(x) + end +end + +def fun_l25_n623(x) + if (x < 1) + fun_l26_n938(x) + else + fun_l26_n339(x) + end +end + +def fun_l25_n624(x) + if (x < 1) + fun_l26_n385(x) + else + fun_l26_n462(x) + end +end + +def fun_l25_n625(x) + if (x < 1) + fun_l26_n83(x) + else + fun_l26_n351(x) + end +end + +def fun_l25_n626(x) + if (x < 1) + fun_l26_n317(x) + else + fun_l26_n16(x) + end +end + +def fun_l25_n627(x) + if (x < 1) + fun_l26_n321(x) + else + fun_l26_n955(x) + end +end + +def fun_l25_n628(x) + if (x < 1) + fun_l26_n649(x) + else + fun_l26_n195(x) + end +end + +def fun_l25_n629(x) + if (x < 1) + fun_l26_n351(x) + else + fun_l26_n429(x) + end +end + +def fun_l25_n630(x) + if (x < 1) + fun_l26_n338(x) + else + fun_l26_n334(x) + end +end + +def fun_l25_n631(x) + if (x < 1) + fun_l26_n355(x) + else + fun_l26_n782(x) + end +end + +def fun_l25_n632(x) + if (x < 1) + fun_l26_n619(x) + else + fun_l26_n189(x) + end +end + +def fun_l25_n633(x) + if (x < 1) + fun_l26_n818(x) + else + fun_l26_n740(x) + end +end + +def fun_l25_n634(x) + if (x < 1) + fun_l26_n725(x) + else + fun_l26_n114(x) + end +end + +def fun_l25_n635(x) + if (x < 1) + fun_l26_n948(x) + else + fun_l26_n587(x) + end +end + +def fun_l25_n636(x) + if (x < 1) + fun_l26_n268(x) + else + fun_l26_n871(x) + end +end + +def fun_l25_n637(x) + if (x < 1) + fun_l26_n128(x) + else + fun_l26_n5(x) + end +end + +def fun_l25_n638(x) + if (x < 1) + fun_l26_n981(x) + else + fun_l26_n209(x) + end +end + +def fun_l25_n639(x) + if (x < 1) + fun_l26_n729(x) + else + fun_l26_n786(x) + end +end + +def fun_l25_n640(x) + if (x < 1) + fun_l26_n86(x) + else + fun_l26_n320(x) + end +end + +def fun_l25_n641(x) + if (x < 1) + fun_l26_n59(x) + else + fun_l26_n457(x) + end +end + +def fun_l25_n642(x) + if (x < 1) + fun_l26_n517(x) + else + fun_l26_n249(x) + end +end + +def fun_l25_n643(x) + if (x < 1) + fun_l26_n528(x) + else + fun_l26_n754(x) + end +end + +def fun_l25_n644(x) + if (x < 1) + fun_l26_n254(x) + else + fun_l26_n886(x) + end +end + +def fun_l25_n645(x) + if (x < 1) + fun_l26_n244(x) + else + fun_l26_n364(x) + end +end + +def fun_l25_n646(x) + if (x < 1) + fun_l26_n550(x) + else + fun_l26_n877(x) + end +end + +def fun_l25_n647(x) + if (x < 1) + fun_l26_n274(x) + else + fun_l26_n712(x) + end +end + +def fun_l25_n648(x) + if (x < 1) + fun_l26_n299(x) + else + fun_l26_n957(x) + end +end + +def fun_l25_n649(x) + if (x < 1) + fun_l26_n996(x) + else + fun_l26_n671(x) + end +end + +def fun_l25_n650(x) + if (x < 1) + fun_l26_n91(x) + else + fun_l26_n867(x) + end +end + +def fun_l25_n651(x) + if (x < 1) + fun_l26_n987(x) + else + fun_l26_n643(x) + end +end + +def fun_l25_n652(x) + if (x < 1) + fun_l26_n429(x) + else + fun_l26_n802(x) + end +end + +def fun_l25_n653(x) + if (x < 1) + fun_l26_n967(x) + else + fun_l26_n590(x) + end +end + +def fun_l25_n654(x) + if (x < 1) + fun_l26_n404(x) + else + fun_l26_n283(x) + end +end + +def fun_l25_n655(x) + if (x < 1) + fun_l26_n438(x) + else + fun_l26_n232(x) + end +end + +def fun_l25_n656(x) + if (x < 1) + fun_l26_n295(x) + else + fun_l26_n559(x) + end +end + +def fun_l25_n657(x) + if (x < 1) + fun_l26_n892(x) + else + fun_l26_n46(x) + end +end + +def fun_l25_n658(x) + if (x < 1) + fun_l26_n30(x) + else + fun_l26_n640(x) + end +end + +def fun_l25_n659(x) + if (x < 1) + fun_l26_n323(x) + else + fun_l26_n583(x) + end +end + +def fun_l25_n660(x) + if (x < 1) + fun_l26_n682(x) + else + fun_l26_n668(x) + end +end + +def fun_l25_n661(x) + if (x < 1) + fun_l26_n78(x) + else + fun_l26_n83(x) + end +end + +def fun_l25_n662(x) + if (x < 1) + fun_l26_n457(x) + else + fun_l26_n289(x) + end +end + +def fun_l25_n663(x) + if (x < 1) + fun_l26_n444(x) + else + fun_l26_n159(x) + end +end + +def fun_l25_n664(x) + if (x < 1) + fun_l26_n10(x) + else + fun_l26_n925(x) + end +end + +def fun_l25_n665(x) + if (x < 1) + fun_l26_n870(x) + else + fun_l26_n253(x) + end +end + +def fun_l25_n666(x) + if (x < 1) + fun_l26_n55(x) + else + fun_l26_n705(x) + end +end + +def fun_l25_n667(x) + if (x < 1) + fun_l26_n179(x) + else + fun_l26_n607(x) + end +end + +def fun_l25_n668(x) + if (x < 1) + fun_l26_n359(x) + else + fun_l26_n56(x) + end +end + +def fun_l25_n669(x) + if (x < 1) + fun_l26_n908(x) + else + fun_l26_n997(x) + end +end + +def fun_l25_n670(x) + if (x < 1) + fun_l26_n469(x) + else + fun_l26_n438(x) + end +end + +def fun_l25_n671(x) + if (x < 1) + fun_l26_n740(x) + else + fun_l26_n847(x) + end +end + +def fun_l25_n672(x) + if (x < 1) + fun_l26_n123(x) + else + fun_l26_n636(x) + end +end + +def fun_l25_n673(x) + if (x < 1) + fun_l26_n654(x) + else + fun_l26_n221(x) + end +end + +def fun_l25_n674(x) + if (x < 1) + fun_l26_n14(x) + else + fun_l26_n792(x) + end +end + +def fun_l25_n675(x) + if (x < 1) + fun_l26_n424(x) + else + fun_l26_n999(x) + end +end + +def fun_l25_n676(x) + if (x < 1) + fun_l26_n491(x) + else + fun_l26_n698(x) + end +end + +def fun_l25_n677(x) + if (x < 1) + fun_l26_n859(x) + else + fun_l26_n749(x) + end +end + +def fun_l25_n678(x) + if (x < 1) + fun_l26_n357(x) + else + fun_l26_n861(x) + end +end + +def fun_l25_n679(x) + if (x < 1) + fun_l26_n144(x) + else + fun_l26_n347(x) + end +end + +def fun_l25_n680(x) + if (x < 1) + fun_l26_n42(x) + else + fun_l26_n168(x) + end +end + +def fun_l25_n681(x) + if (x < 1) + fun_l26_n808(x) + else + fun_l26_n639(x) + end +end + +def fun_l25_n682(x) + if (x < 1) + fun_l26_n943(x) + else + fun_l26_n152(x) + end +end + +def fun_l25_n683(x) + if (x < 1) + fun_l26_n668(x) + else + fun_l26_n186(x) + end +end + +def fun_l25_n684(x) + if (x < 1) + fun_l26_n607(x) + else + fun_l26_n141(x) + end +end + +def fun_l25_n685(x) + if (x < 1) + fun_l26_n221(x) + else + fun_l26_n960(x) + end +end + +def fun_l25_n686(x) + if (x < 1) + fun_l26_n85(x) + else + fun_l26_n285(x) + end +end + +def fun_l25_n687(x) + if (x < 1) + fun_l26_n707(x) + else + fun_l26_n638(x) + end +end + +def fun_l25_n688(x) + if (x < 1) + fun_l26_n288(x) + else + fun_l26_n318(x) + end +end + +def fun_l25_n689(x) + if (x < 1) + fun_l26_n505(x) + else + fun_l26_n802(x) + end +end + +def fun_l25_n690(x) + if (x < 1) + fun_l26_n757(x) + else + fun_l26_n988(x) + end +end + +def fun_l25_n691(x) + if (x < 1) + fun_l26_n211(x) + else + fun_l26_n868(x) + end +end + +def fun_l25_n692(x) + if (x < 1) + fun_l26_n945(x) + else + fun_l26_n689(x) + end +end + +def fun_l25_n693(x) + if (x < 1) + fun_l26_n65(x) + else + fun_l26_n326(x) + end +end + +def fun_l25_n694(x) + if (x < 1) + fun_l26_n905(x) + else + fun_l26_n912(x) + end +end + +def fun_l25_n695(x) + if (x < 1) + fun_l26_n408(x) + else + fun_l26_n834(x) + end +end + +def fun_l25_n696(x) + if (x < 1) + fun_l26_n862(x) + else + fun_l26_n827(x) + end +end + +def fun_l25_n697(x) + if (x < 1) + fun_l26_n356(x) + else + fun_l26_n201(x) + end +end + +def fun_l25_n698(x) + if (x < 1) + fun_l26_n819(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n699(x) + if (x < 1) + fun_l26_n252(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n700(x) + if (x < 1) + fun_l26_n620(x) + else + fun_l26_n693(x) + end +end + +def fun_l25_n701(x) + if (x < 1) + fun_l26_n393(x) + else + fun_l26_n246(x) + end +end + +def fun_l25_n702(x) + if (x < 1) + fun_l26_n601(x) + else + fun_l26_n230(x) + end +end + +def fun_l25_n703(x) + if (x < 1) + fun_l26_n583(x) + else + fun_l26_n503(x) + end +end + +def fun_l25_n704(x) + if (x < 1) + fun_l26_n156(x) + else + fun_l26_n951(x) + end +end + +def fun_l25_n705(x) + if (x < 1) + fun_l26_n681(x) + else + fun_l26_n692(x) + end +end + +def fun_l25_n706(x) + if (x < 1) + fun_l26_n176(x) + else + fun_l26_n158(x) + end +end + +def fun_l25_n707(x) + if (x < 1) + fun_l26_n607(x) + else + fun_l26_n3(x) + end +end + +def fun_l25_n708(x) + if (x < 1) + fun_l26_n999(x) + else + fun_l26_n614(x) + end +end + +def fun_l25_n709(x) + if (x < 1) + fun_l26_n930(x) + else + fun_l26_n888(x) + end +end + +def fun_l25_n710(x) + if (x < 1) + fun_l26_n347(x) + else + fun_l26_n106(x) + end +end + +def fun_l25_n711(x) + if (x < 1) + fun_l26_n425(x) + else + fun_l26_n474(x) + end +end + +def fun_l25_n712(x) + if (x < 1) + fun_l26_n265(x) + else + fun_l26_n519(x) + end +end + +def fun_l25_n713(x) + if (x < 1) + fun_l26_n205(x) + else + fun_l26_n76(x) + end +end + +def fun_l25_n714(x) + if (x < 1) + fun_l26_n628(x) + else + fun_l26_n784(x) + end +end + +def fun_l25_n715(x) + if (x < 1) + fun_l26_n217(x) + else + fun_l26_n484(x) + end +end + +def fun_l25_n716(x) + if (x < 1) + fun_l26_n883(x) + else + fun_l26_n5(x) + end +end + +def fun_l25_n717(x) + if (x < 1) + fun_l26_n23(x) + else + fun_l26_n457(x) + end +end + +def fun_l25_n718(x) + if (x < 1) + fun_l26_n370(x) + else + fun_l26_n789(x) + end +end + +def fun_l25_n719(x) + if (x < 1) + fun_l26_n636(x) + else + fun_l26_n776(x) + end +end + +def fun_l25_n720(x) + if (x < 1) + fun_l26_n558(x) + else + fun_l26_n491(x) + end +end + +def fun_l25_n721(x) + if (x < 1) + fun_l26_n867(x) + else + fun_l26_n49(x) + end +end + +def fun_l25_n722(x) + if (x < 1) + fun_l26_n178(x) + else + fun_l26_n835(x) + end +end + +def fun_l25_n723(x) + if (x < 1) + fun_l26_n967(x) + else + fun_l26_n266(x) + end +end + +def fun_l25_n724(x) + if (x < 1) + fun_l26_n191(x) + else + fun_l26_n58(x) + end +end + +def fun_l25_n725(x) + if (x < 1) + fun_l26_n536(x) + else + fun_l26_n78(x) + end +end + +def fun_l25_n726(x) + if (x < 1) + fun_l26_n128(x) + else + fun_l26_n764(x) + end +end + +def fun_l25_n727(x) + if (x < 1) + fun_l26_n243(x) + else + fun_l26_n217(x) + end +end + +def fun_l25_n728(x) + if (x < 1) + fun_l26_n608(x) + else + fun_l26_n613(x) + end +end + +def fun_l25_n729(x) + if (x < 1) + fun_l26_n765(x) + else + fun_l26_n822(x) + end +end + +def fun_l25_n730(x) + if (x < 1) + fun_l26_n445(x) + else + fun_l26_n160(x) + end +end + +def fun_l25_n731(x) + if (x < 1) + fun_l26_n209(x) + else + fun_l26_n980(x) + end +end + +def fun_l25_n732(x) + if (x < 1) + fun_l26_n888(x) + else + fun_l26_n726(x) + end +end + +def fun_l25_n733(x) + if (x < 1) + fun_l26_n232(x) + else + fun_l26_n47(x) + end +end + +def fun_l25_n734(x) + if (x < 1) + fun_l26_n278(x) + else + fun_l26_n878(x) + end +end + +def fun_l25_n735(x) + if (x < 1) + fun_l26_n894(x) + else + fun_l26_n523(x) + end +end + +def fun_l25_n736(x) + if (x < 1) + fun_l26_n334(x) + else + fun_l26_n270(x) + end +end + +def fun_l25_n737(x) + if (x < 1) + fun_l26_n877(x) + else + fun_l26_n105(x) + end +end + +def fun_l25_n738(x) + if (x < 1) + fun_l26_n761(x) + else + fun_l26_n187(x) + end +end + +def fun_l25_n739(x) + if (x < 1) + fun_l26_n668(x) + else + fun_l26_n592(x) + end +end + +def fun_l25_n740(x) + if (x < 1) + fun_l26_n497(x) + else + fun_l26_n98(x) + end +end + +def fun_l25_n741(x) + if (x < 1) + fun_l26_n415(x) + else + fun_l26_n85(x) + end +end + +def fun_l25_n742(x) + if (x < 1) + fun_l26_n883(x) + else + fun_l26_n505(x) + end +end + +def fun_l25_n743(x) + if (x < 1) + fun_l26_n12(x) + else + fun_l26_n91(x) + end +end + +def fun_l25_n744(x) + if (x < 1) + fun_l26_n487(x) + else + fun_l26_n336(x) + end +end + +def fun_l25_n745(x) + if (x < 1) + fun_l26_n489(x) + else + fun_l26_n186(x) + end +end + +def fun_l25_n746(x) + if (x < 1) + fun_l26_n783(x) + else + fun_l26_n233(x) + end +end + +def fun_l25_n747(x) + if (x < 1) + fun_l26_n171(x) + else + fun_l26_n574(x) + end +end + +def fun_l25_n748(x) + if (x < 1) + fun_l26_n171(x) + else + fun_l26_n61(x) + end +end + +def fun_l25_n749(x) + if (x < 1) + fun_l26_n444(x) + else + fun_l26_n89(x) + end +end + +def fun_l25_n750(x) + if (x < 1) + fun_l26_n609(x) + else + fun_l26_n998(x) + end +end + +def fun_l25_n751(x) + if (x < 1) + fun_l26_n914(x) + else + fun_l26_n893(x) + end +end + +def fun_l25_n752(x) + if (x < 1) + fun_l26_n782(x) + else + fun_l26_n984(x) + end +end + +def fun_l25_n753(x) + if (x < 1) + fun_l26_n351(x) + else + fun_l26_n370(x) + end +end + +def fun_l25_n754(x) + if (x < 1) + fun_l26_n689(x) + else + fun_l26_n234(x) + end +end + +def fun_l25_n755(x) + if (x < 1) + fun_l26_n131(x) + else + fun_l26_n960(x) + end +end + +def fun_l25_n756(x) + if (x < 1) + fun_l26_n635(x) + else + fun_l26_n89(x) + end +end + +def fun_l25_n757(x) + if (x < 1) + fun_l26_n309(x) + else + fun_l26_n74(x) + end +end + +def fun_l25_n758(x) + if (x < 1) + fun_l26_n818(x) + else + fun_l26_n520(x) + end +end + +def fun_l25_n759(x) + if (x < 1) + fun_l26_n873(x) + else + fun_l26_n761(x) + end +end + +def fun_l25_n760(x) + if (x < 1) + fun_l26_n216(x) + else + fun_l26_n449(x) + end +end + +def fun_l25_n761(x) + if (x < 1) + fun_l26_n596(x) + else + fun_l26_n617(x) + end +end + +def fun_l25_n762(x) + if (x < 1) + fun_l26_n485(x) + else + fun_l26_n164(x) + end +end + +def fun_l25_n763(x) + if (x < 1) + fun_l26_n434(x) + else + fun_l26_n422(x) + end +end + +def fun_l25_n764(x) + if (x < 1) + fun_l26_n845(x) + else + fun_l26_n678(x) + end +end + +def fun_l25_n765(x) + if (x < 1) + fun_l26_n376(x) + else + fun_l26_n128(x) + end +end + +def fun_l25_n766(x) + if (x < 1) + fun_l26_n217(x) + else + fun_l26_n721(x) + end +end + +def fun_l25_n767(x) + if (x < 1) + fun_l26_n929(x) + else + fun_l26_n425(x) + end +end + +def fun_l25_n768(x) + if (x < 1) + fun_l26_n420(x) + else + fun_l26_n990(x) + end +end + +def fun_l25_n769(x) + if (x < 1) + fun_l26_n310(x) + else + fun_l26_n901(x) + end +end + +def fun_l25_n770(x) + if (x < 1) + fun_l26_n667(x) + else + fun_l26_n627(x) + end +end + +def fun_l25_n771(x) + if (x < 1) + fun_l26_n265(x) + else + fun_l26_n852(x) + end +end + +def fun_l25_n772(x) + if (x < 1) + fun_l26_n520(x) + else + fun_l26_n596(x) + end +end + +def fun_l25_n773(x) + if (x < 1) + fun_l26_n280(x) + else + fun_l26_n0(x) + end +end + +def fun_l25_n774(x) + if (x < 1) + fun_l26_n451(x) + else + fun_l26_n828(x) + end +end + +def fun_l25_n775(x) + if (x < 1) + fun_l26_n814(x) + else + fun_l26_n797(x) + end +end + +def fun_l25_n776(x) + if (x < 1) + fun_l26_n345(x) + else + fun_l26_n223(x) + end +end + +def fun_l25_n777(x) + if (x < 1) + fun_l26_n392(x) + else + fun_l26_n847(x) + end +end + +def fun_l25_n778(x) + if (x < 1) + fun_l26_n957(x) + else + fun_l26_n474(x) + end +end + +def fun_l25_n779(x) + if (x < 1) + fun_l26_n950(x) + else + fun_l26_n804(x) + end +end + +def fun_l25_n780(x) + if (x < 1) + fun_l26_n939(x) + else + fun_l26_n133(x) + end +end + +def fun_l25_n781(x) + if (x < 1) + fun_l26_n176(x) + else + fun_l26_n237(x) + end +end + +def fun_l25_n782(x) + if (x < 1) + fun_l26_n156(x) + else + fun_l26_n268(x) + end +end + +def fun_l25_n783(x) + if (x < 1) + fun_l26_n750(x) + else + fun_l26_n88(x) + end +end + +def fun_l25_n784(x) + if (x < 1) + fun_l26_n638(x) + else + fun_l26_n147(x) + end +end + +def fun_l25_n785(x) + if (x < 1) + fun_l26_n570(x) + else + fun_l26_n698(x) + end +end + +def fun_l25_n786(x) + if (x < 1) + fun_l26_n749(x) + else + fun_l26_n728(x) + end +end + +def fun_l25_n787(x) + if (x < 1) + fun_l26_n183(x) + else + fun_l26_n649(x) + end +end + +def fun_l25_n788(x) + if (x < 1) + fun_l26_n157(x) + else + fun_l26_n55(x) + end +end + +def fun_l25_n789(x) + if (x < 1) + fun_l26_n559(x) + else + fun_l26_n228(x) + end +end + +def fun_l25_n790(x) + if (x < 1) + fun_l26_n690(x) + else + fun_l26_n214(x) + end +end + +def fun_l25_n791(x) + if (x < 1) + fun_l26_n621(x) + else + fun_l26_n184(x) + end +end + +def fun_l25_n792(x) + if (x < 1) + fun_l26_n13(x) + else + fun_l26_n610(x) + end +end + +def fun_l25_n793(x) + if (x < 1) + fun_l26_n709(x) + else + fun_l26_n40(x) + end +end + +def fun_l25_n794(x) + if (x < 1) + fun_l26_n51(x) + else + fun_l26_n288(x) + end +end + +def fun_l25_n795(x) + if (x < 1) + fun_l26_n526(x) + else + fun_l26_n237(x) + end +end + +def fun_l25_n796(x) + if (x < 1) + fun_l26_n279(x) + else + fun_l26_n157(x) + end +end + +def fun_l25_n797(x) + if (x < 1) + fun_l26_n299(x) + else + fun_l26_n999(x) + end +end + +def fun_l25_n798(x) + if (x < 1) + fun_l26_n547(x) + else + fun_l26_n41(x) + end +end + +def fun_l25_n799(x) + if (x < 1) + fun_l26_n522(x) + else + fun_l26_n544(x) + end +end + +def fun_l25_n800(x) + if (x < 1) + fun_l26_n509(x) + else + fun_l26_n364(x) + end +end + +def fun_l25_n801(x) + if (x < 1) + fun_l26_n412(x) + else + fun_l26_n719(x) + end +end + +def fun_l25_n802(x) + if (x < 1) + fun_l26_n844(x) + else + fun_l26_n452(x) + end +end + +def fun_l25_n803(x) + if (x < 1) + fun_l26_n681(x) + else + fun_l26_n217(x) + end +end + +def fun_l25_n804(x) + if (x < 1) + fun_l26_n855(x) + else + fun_l26_n97(x) + end +end + +def fun_l25_n805(x) + if (x < 1) + fun_l26_n32(x) + else + fun_l26_n512(x) + end +end + +def fun_l25_n806(x) + if (x < 1) + fun_l26_n674(x) + else + fun_l26_n675(x) + end +end + +def fun_l25_n807(x) + if (x < 1) + fun_l26_n684(x) + else + fun_l26_n848(x) + end +end + +def fun_l25_n808(x) + if (x < 1) + fun_l26_n784(x) + else + fun_l26_n603(x) + end +end + +def fun_l25_n809(x) + if (x < 1) + fun_l26_n58(x) + else + fun_l26_n20(x) + end +end + +def fun_l25_n810(x) + if (x < 1) + fun_l26_n654(x) + else + fun_l26_n230(x) + end +end + +def fun_l25_n811(x) + if (x < 1) + fun_l26_n627(x) + else + fun_l26_n812(x) + end +end + +def fun_l25_n812(x) + if (x < 1) + fun_l26_n30(x) + else + fun_l26_n315(x) + end +end + +def fun_l25_n813(x) + if (x < 1) + fun_l26_n690(x) + else + fun_l26_n755(x) + end +end + +def fun_l25_n814(x) + if (x < 1) + fun_l26_n566(x) + else + fun_l26_n44(x) + end +end + +def fun_l25_n815(x) + if (x < 1) + fun_l26_n884(x) + else + fun_l26_n954(x) + end +end + +def fun_l25_n816(x) + if (x < 1) + fun_l26_n64(x) + else + fun_l26_n179(x) + end +end + +def fun_l25_n817(x) + if (x < 1) + fun_l26_n341(x) + else + fun_l26_n440(x) + end +end + +def fun_l25_n818(x) + if (x < 1) + fun_l26_n934(x) + else + fun_l26_n678(x) + end +end + +def fun_l25_n819(x) + if (x < 1) + fun_l26_n225(x) + else + fun_l26_n807(x) + end +end + +def fun_l25_n820(x) + if (x < 1) + fun_l26_n625(x) + else + fun_l26_n63(x) + end +end + +def fun_l25_n821(x) + if (x < 1) + fun_l26_n744(x) + else + fun_l26_n68(x) + end +end + +def fun_l25_n822(x) + if (x < 1) + fun_l26_n962(x) + else + fun_l26_n205(x) + end +end + +def fun_l25_n823(x) + if (x < 1) + fun_l26_n715(x) + else + fun_l26_n130(x) + end +end + +def fun_l25_n824(x) + if (x < 1) + fun_l26_n843(x) + else + fun_l26_n853(x) + end +end + +def fun_l25_n825(x) + if (x < 1) + fun_l26_n34(x) + else + fun_l26_n665(x) + end +end + +def fun_l25_n826(x) + if (x < 1) + fun_l26_n540(x) + else + fun_l26_n693(x) + end +end + +def fun_l25_n827(x) + if (x < 1) + fun_l26_n482(x) + else + fun_l26_n527(x) + end +end + +def fun_l25_n828(x) + if (x < 1) + fun_l26_n98(x) + else + fun_l26_n888(x) + end +end + +def fun_l25_n829(x) + if (x < 1) + fun_l26_n681(x) + else + fun_l26_n176(x) + end +end + +def fun_l25_n830(x) + if (x < 1) + fun_l26_n453(x) + else + fun_l26_n455(x) + end +end + +def fun_l25_n831(x) + if (x < 1) + fun_l26_n587(x) + else + fun_l26_n501(x) + end +end + +def fun_l25_n832(x) + if (x < 1) + fun_l26_n725(x) + else + fun_l26_n608(x) + end +end + +def fun_l25_n833(x) + if (x < 1) + fun_l26_n589(x) + else + fun_l26_n945(x) + end +end + +def fun_l25_n834(x) + if (x < 1) + fun_l26_n41(x) + else + fun_l26_n925(x) + end +end + +def fun_l25_n835(x) + if (x < 1) + fun_l26_n858(x) + else + fun_l26_n840(x) + end +end + +def fun_l25_n836(x) + if (x < 1) + fun_l26_n572(x) + else + fun_l26_n360(x) + end +end + +def fun_l25_n837(x) + if (x < 1) + fun_l26_n446(x) + else + fun_l26_n912(x) + end +end + +def fun_l25_n838(x) + if (x < 1) + fun_l26_n104(x) + else + fun_l26_n795(x) + end +end + +def fun_l25_n839(x) + if (x < 1) + fun_l26_n607(x) + else + fun_l26_n803(x) + end +end + +def fun_l25_n840(x) + if (x < 1) + fun_l26_n156(x) + else + fun_l26_n874(x) + end +end + +def fun_l25_n841(x) + if (x < 1) + fun_l26_n314(x) + else + fun_l26_n28(x) + end +end + +def fun_l25_n842(x) + if (x < 1) + fun_l26_n683(x) + else + fun_l26_n695(x) + end +end + +def fun_l25_n843(x) + if (x < 1) + fun_l26_n881(x) + else + fun_l26_n272(x) + end +end + +def fun_l25_n844(x) + if (x < 1) + fun_l26_n354(x) + else + fun_l26_n993(x) + end +end + +def fun_l25_n845(x) + if (x < 1) + fun_l26_n686(x) + else + fun_l26_n594(x) + end +end + +def fun_l25_n846(x) + if (x < 1) + fun_l26_n644(x) + else + fun_l26_n930(x) + end +end + +def fun_l25_n847(x) + if (x < 1) + fun_l26_n417(x) + else + fun_l26_n705(x) + end +end + +def fun_l25_n848(x) + if (x < 1) + fun_l26_n694(x) + else + fun_l26_n331(x) + end +end + +def fun_l25_n849(x) + if (x < 1) + fun_l26_n546(x) + else + fun_l26_n848(x) + end +end + +def fun_l25_n850(x) + if (x < 1) + fun_l26_n199(x) + else + fun_l26_n49(x) + end +end + +def fun_l25_n851(x) + if (x < 1) + fun_l26_n439(x) + else + fun_l26_n406(x) + end +end + +def fun_l25_n852(x) + if (x < 1) + fun_l26_n355(x) + else + fun_l26_n582(x) + end +end + +def fun_l25_n853(x) + if (x < 1) + fun_l26_n839(x) + else + fun_l26_n485(x) + end +end + +def fun_l25_n854(x) + if (x < 1) + fun_l26_n952(x) + else + fun_l26_n781(x) + end +end + +def fun_l25_n855(x) + if (x < 1) + fun_l26_n616(x) + else + fun_l26_n811(x) + end +end + +def fun_l25_n856(x) + if (x < 1) + fun_l26_n590(x) + else + fun_l26_n977(x) + end +end + +def fun_l25_n857(x) + if (x < 1) + fun_l26_n167(x) + else + fun_l26_n329(x) + end +end + +def fun_l25_n858(x) + if (x < 1) + fun_l26_n732(x) + else + fun_l26_n707(x) + end +end + +def fun_l25_n859(x) + if (x < 1) + fun_l26_n956(x) + else + fun_l26_n955(x) + end +end + +def fun_l25_n860(x) + if (x < 1) + fun_l26_n443(x) + else + fun_l26_n816(x) + end +end + +def fun_l25_n861(x) + if (x < 1) + fun_l26_n584(x) + else + fun_l26_n671(x) + end +end + +def fun_l25_n862(x) + if (x < 1) + fun_l26_n43(x) + else + fun_l26_n0(x) + end +end + +def fun_l25_n863(x) + if (x < 1) + fun_l26_n697(x) + else + fun_l26_n842(x) + end +end + +def fun_l25_n864(x) + if (x < 1) + fun_l26_n423(x) + else + fun_l26_n509(x) + end +end + +def fun_l25_n865(x) + if (x < 1) + fun_l26_n239(x) + else + fun_l26_n257(x) + end +end + +def fun_l25_n866(x) + if (x < 1) + fun_l26_n78(x) + else + fun_l26_n450(x) + end +end + +def fun_l25_n867(x) + if (x < 1) + fun_l26_n121(x) + else + fun_l26_n453(x) + end +end + +def fun_l25_n868(x) + if (x < 1) + fun_l26_n844(x) + else + fun_l26_n977(x) + end +end + +def fun_l25_n869(x) + if (x < 1) + fun_l26_n54(x) + else + fun_l26_n869(x) + end +end + +def fun_l25_n870(x) + if (x < 1) + fun_l26_n18(x) + else + fun_l26_n799(x) + end +end + +def fun_l25_n871(x) + if (x < 1) + fun_l26_n990(x) + else + fun_l26_n53(x) + end +end + +def fun_l25_n872(x) + if (x < 1) + fun_l26_n607(x) + else + fun_l26_n822(x) + end +end + +def fun_l25_n873(x) + if (x < 1) + fun_l26_n378(x) + else + fun_l26_n158(x) + end +end + +def fun_l25_n874(x) + if (x < 1) + fun_l26_n206(x) + else + fun_l26_n271(x) + end +end + +def fun_l25_n875(x) + if (x < 1) + fun_l26_n536(x) + else + fun_l26_n850(x) + end +end + +def fun_l25_n876(x) + if (x < 1) + fun_l26_n129(x) + else + fun_l26_n750(x) + end +end + +def fun_l25_n877(x) + if (x < 1) + fun_l26_n553(x) + else + fun_l26_n815(x) + end +end + +def fun_l25_n878(x) + if (x < 1) + fun_l26_n619(x) + else + fun_l26_n182(x) + end +end + +def fun_l25_n879(x) + if (x < 1) + fun_l26_n529(x) + else + fun_l26_n541(x) + end +end + +def fun_l25_n880(x) + if (x < 1) + fun_l26_n228(x) + else + fun_l26_n672(x) + end +end + +def fun_l25_n881(x) + if (x < 1) + fun_l26_n834(x) + else + fun_l26_n830(x) + end +end + +def fun_l25_n882(x) + if (x < 1) + fun_l26_n80(x) + else + fun_l26_n257(x) + end +end + +def fun_l25_n883(x) + if (x < 1) + fun_l26_n805(x) + else + fun_l26_n589(x) + end +end + +def fun_l25_n884(x) + if (x < 1) + fun_l26_n20(x) + else + fun_l26_n880(x) + end +end + +def fun_l25_n885(x) + if (x < 1) + fun_l26_n924(x) + else + fun_l26_n832(x) + end +end + +def fun_l25_n886(x) + if (x < 1) + fun_l26_n262(x) + else + fun_l26_n928(x) + end +end + +def fun_l25_n887(x) + if (x < 1) + fun_l26_n461(x) + else + fun_l26_n81(x) + end +end + +def fun_l25_n888(x) + if (x < 1) + fun_l26_n484(x) + else + fun_l26_n376(x) + end +end + +def fun_l25_n889(x) + if (x < 1) + fun_l26_n26(x) + else + fun_l26_n28(x) + end +end + +def fun_l25_n890(x) + if (x < 1) + fun_l26_n184(x) + else + fun_l26_n623(x) + end +end + +def fun_l25_n891(x) + if (x < 1) + fun_l26_n326(x) + else + fun_l26_n441(x) + end +end + +def fun_l25_n892(x) + if (x < 1) + fun_l26_n35(x) + else + fun_l26_n543(x) + end +end + +def fun_l25_n893(x) + if (x < 1) + fun_l26_n568(x) + else + fun_l26_n229(x) + end +end + +def fun_l25_n894(x) + if (x < 1) + fun_l26_n163(x) + else + fun_l26_n505(x) + end +end + +def fun_l25_n895(x) + if (x < 1) + fun_l26_n675(x) + else + fun_l26_n508(x) + end +end + +def fun_l25_n896(x) + if (x < 1) + fun_l26_n285(x) + else + fun_l26_n936(x) + end +end + +def fun_l25_n897(x) + if (x < 1) + fun_l26_n848(x) + else + fun_l26_n169(x) + end +end + +def fun_l25_n898(x) + if (x < 1) + fun_l26_n139(x) + else + fun_l26_n479(x) + end +end + +def fun_l25_n899(x) + if (x < 1) + fun_l26_n355(x) + else + fun_l26_n49(x) + end +end + +def fun_l25_n900(x) + if (x < 1) + fun_l26_n918(x) + else + fun_l26_n215(x) + end +end + +def fun_l25_n901(x) + if (x < 1) + fun_l26_n55(x) + else + fun_l26_n550(x) + end +end + +def fun_l25_n902(x) + if (x < 1) + fun_l26_n660(x) + else + fun_l26_n117(x) + end +end + +def fun_l25_n903(x) + if (x < 1) + fun_l26_n968(x) + else + fun_l26_n279(x) + end +end + +def fun_l25_n904(x) + if (x < 1) + fun_l26_n693(x) + else + fun_l26_n57(x) + end +end + +def fun_l25_n905(x) + if (x < 1) + fun_l26_n248(x) + else + fun_l26_n154(x) + end +end + +def fun_l25_n906(x) + if (x < 1) + fun_l26_n837(x) + else + fun_l26_n698(x) + end +end + +def fun_l25_n907(x) + if (x < 1) + fun_l26_n630(x) + else + fun_l26_n460(x) + end +end + +def fun_l25_n908(x) + if (x < 1) + fun_l26_n424(x) + else + fun_l26_n243(x) + end +end + +def fun_l25_n909(x) + if (x < 1) + fun_l26_n897(x) + else + fun_l26_n736(x) + end +end + +def fun_l25_n910(x) + if (x < 1) + fun_l26_n573(x) + else + fun_l26_n205(x) + end +end + +def fun_l25_n911(x) + if (x < 1) + fun_l26_n535(x) + else + fun_l26_n970(x) + end +end + +def fun_l25_n912(x) + if (x < 1) + fun_l26_n826(x) + else + fun_l26_n744(x) + end +end + +def fun_l25_n913(x) + if (x < 1) + fun_l26_n244(x) + else + fun_l26_n216(x) + end +end + +def fun_l25_n914(x) + if (x < 1) + fun_l26_n958(x) + else + fun_l26_n617(x) + end +end + +def fun_l25_n915(x) + if (x < 1) + fun_l26_n911(x) + else + fun_l26_n684(x) + end +end + +def fun_l25_n916(x) + if (x < 1) + fun_l26_n294(x) + else + fun_l26_n319(x) + end +end + +def fun_l25_n917(x) + if (x < 1) + fun_l26_n665(x) + else + fun_l26_n867(x) + end +end + +def fun_l25_n918(x) + if (x < 1) + fun_l26_n733(x) + else + fun_l26_n746(x) + end +end + +def fun_l25_n919(x) + if (x < 1) + fun_l26_n243(x) + else + fun_l26_n328(x) + end +end + +def fun_l25_n920(x) + if (x < 1) + fun_l26_n897(x) + else + fun_l26_n197(x) + end +end + +def fun_l25_n921(x) + if (x < 1) + fun_l26_n528(x) + else + fun_l26_n229(x) + end +end + +def fun_l25_n922(x) + if (x < 1) + fun_l26_n897(x) + else + fun_l26_n547(x) + end +end + +def fun_l25_n923(x) + if (x < 1) + fun_l26_n234(x) + else + fun_l26_n920(x) + end +end + +def fun_l25_n924(x) + if (x < 1) + fun_l26_n827(x) + else + fun_l26_n257(x) + end +end + +def fun_l25_n925(x) + if (x < 1) + fun_l26_n847(x) + else + fun_l26_n469(x) + end +end + +def fun_l25_n926(x) + if (x < 1) + fun_l26_n27(x) + else + fun_l26_n974(x) + end +end + +def fun_l25_n927(x) + if (x < 1) + fun_l26_n872(x) + else + fun_l26_n535(x) + end +end + +def fun_l25_n928(x) + if (x < 1) + fun_l26_n870(x) + else + fun_l26_n783(x) + end +end + +def fun_l25_n929(x) + if (x < 1) + fun_l26_n993(x) + else + fun_l26_n168(x) + end +end + +def fun_l25_n930(x) + if (x < 1) + fun_l26_n852(x) + else + fun_l26_n41(x) + end +end + +def fun_l25_n931(x) + if (x < 1) + fun_l26_n290(x) + else + fun_l26_n249(x) + end +end + +def fun_l25_n932(x) + if (x < 1) + fun_l26_n446(x) + else + fun_l26_n841(x) + end +end + +def fun_l25_n933(x) + if (x < 1) + fun_l26_n303(x) + else + fun_l26_n779(x) + end +end + +def fun_l25_n934(x) + if (x < 1) + fun_l26_n352(x) + else + fun_l26_n731(x) + end +end + +def fun_l25_n935(x) + if (x < 1) + fun_l26_n377(x) + else + fun_l26_n214(x) + end +end + +def fun_l25_n936(x) + if (x < 1) + fun_l26_n374(x) + else + fun_l26_n793(x) + end +end + +def fun_l25_n937(x) + if (x < 1) + fun_l26_n656(x) + else + fun_l26_n575(x) + end +end + +def fun_l25_n938(x) + if (x < 1) + fun_l26_n777(x) + else + fun_l26_n773(x) + end +end + +def fun_l25_n939(x) + if (x < 1) + fun_l26_n5(x) + else + fun_l26_n206(x) + end +end + +def fun_l25_n940(x) + if (x < 1) + fun_l26_n780(x) + else + fun_l26_n486(x) + end +end + +def fun_l25_n941(x) + if (x < 1) + fun_l26_n634(x) + else + fun_l26_n727(x) + end +end + +def fun_l25_n942(x) + if (x < 1) + fun_l26_n78(x) + else + fun_l26_n918(x) + end +end + +def fun_l25_n943(x) + if (x < 1) + fun_l26_n616(x) + else + fun_l26_n35(x) + end +end + +def fun_l25_n944(x) + if (x < 1) + fun_l26_n540(x) + else + fun_l26_n837(x) + end +end + +def fun_l25_n945(x) + if (x < 1) + fun_l26_n365(x) + else + fun_l26_n561(x) + end +end + +def fun_l25_n946(x) + if (x < 1) + fun_l26_n519(x) + else + fun_l26_n440(x) + end +end + +def fun_l25_n947(x) + if (x < 1) + fun_l26_n144(x) + else + fun_l26_n426(x) + end +end + +def fun_l25_n948(x) + if (x < 1) + fun_l26_n973(x) + else + fun_l26_n63(x) + end +end + +def fun_l25_n949(x) + if (x < 1) + fun_l26_n258(x) + else + fun_l26_n690(x) + end +end + +def fun_l25_n950(x) + if (x < 1) + fun_l26_n368(x) + else + fun_l26_n307(x) + end +end + +def fun_l25_n951(x) + if (x < 1) + fun_l26_n133(x) + else + fun_l26_n774(x) + end +end + +def fun_l25_n952(x) + if (x < 1) + fun_l26_n866(x) + else + fun_l26_n299(x) + end +end + +def fun_l25_n953(x) + if (x < 1) + fun_l26_n72(x) + else + fun_l26_n421(x) + end +end + +def fun_l25_n954(x) + if (x < 1) + fun_l26_n990(x) + else + fun_l26_n716(x) + end +end + +def fun_l25_n955(x) + if (x < 1) + fun_l26_n138(x) + else + fun_l26_n387(x) + end +end + +def fun_l25_n956(x) + if (x < 1) + fun_l26_n451(x) + else + fun_l26_n965(x) + end +end + +def fun_l25_n957(x) + if (x < 1) + fun_l26_n292(x) + else + fun_l26_n741(x) + end +end + +def fun_l25_n958(x) + if (x < 1) + fun_l26_n835(x) + else + fun_l26_n82(x) + end +end + +def fun_l25_n959(x) + if (x < 1) + fun_l26_n73(x) + else + fun_l26_n987(x) + end +end + +def fun_l25_n960(x) + if (x < 1) + fun_l26_n465(x) + else + fun_l26_n893(x) + end +end + +def fun_l25_n961(x) + if (x < 1) + fun_l26_n277(x) + else + fun_l26_n846(x) + end +end + +def fun_l25_n962(x) + if (x < 1) + fun_l26_n1(x) + else + fun_l26_n408(x) + end +end + +def fun_l25_n963(x) + if (x < 1) + fun_l26_n139(x) + else + fun_l26_n43(x) + end +end + +def fun_l25_n964(x) + if (x < 1) + fun_l26_n238(x) + else + fun_l26_n427(x) + end +end + +def fun_l25_n965(x) + if (x < 1) + fun_l26_n150(x) + else + fun_l26_n60(x) + end +end + +def fun_l25_n966(x) + if (x < 1) + fun_l26_n423(x) + else + fun_l26_n166(x) + end +end + +def fun_l25_n967(x) + if (x < 1) + fun_l26_n102(x) + else + fun_l26_n679(x) + end +end + +def fun_l25_n968(x) + if (x < 1) + fun_l26_n41(x) + else + fun_l26_n553(x) + end +end + +def fun_l25_n969(x) + if (x < 1) + fun_l26_n577(x) + else + fun_l26_n589(x) + end +end + +def fun_l25_n970(x) + if (x < 1) + fun_l26_n569(x) + else + fun_l26_n677(x) + end +end + +def fun_l25_n971(x) + if (x < 1) + fun_l26_n845(x) + else + fun_l26_n237(x) + end +end + +def fun_l25_n972(x) + if (x < 1) + fun_l26_n33(x) + else + fun_l26_n281(x) + end +end + +def fun_l25_n973(x) + if (x < 1) + fun_l26_n432(x) + else + fun_l26_n800(x) + end +end + +def fun_l25_n974(x) + if (x < 1) + fun_l26_n49(x) + else + fun_l26_n864(x) + end +end + +def fun_l25_n975(x) + if (x < 1) + fun_l26_n379(x) + else + fun_l26_n704(x) + end +end + +def fun_l25_n976(x) + if (x < 1) + fun_l26_n778(x) + else + fun_l26_n310(x) + end +end + +def fun_l25_n977(x) + if (x < 1) + fun_l26_n137(x) + else + fun_l26_n261(x) + end +end + +def fun_l25_n978(x) + if (x < 1) + fun_l26_n38(x) + else + fun_l26_n244(x) + end +end + +def fun_l25_n979(x) + if (x < 1) + fun_l26_n665(x) + else + fun_l26_n883(x) + end +end + +def fun_l25_n980(x) + if (x < 1) + fun_l26_n448(x) + else + fun_l26_n619(x) + end +end + +def fun_l25_n981(x) + if (x < 1) + fun_l26_n652(x) + else + fun_l26_n804(x) + end +end + +def fun_l25_n982(x) + if (x < 1) + fun_l26_n804(x) + else + fun_l26_n110(x) + end +end + +def fun_l25_n983(x) + if (x < 1) + fun_l26_n151(x) + else + fun_l26_n588(x) + end +end + +def fun_l25_n984(x) + if (x < 1) + fun_l26_n379(x) + else + fun_l26_n156(x) + end +end + +def fun_l25_n985(x) + if (x < 1) + fun_l26_n936(x) + else + fun_l26_n31(x) + end +end + +def fun_l25_n986(x) + if (x < 1) + fun_l26_n65(x) + else + fun_l26_n303(x) + end +end + +def fun_l25_n987(x) + if (x < 1) + fun_l26_n273(x) + else + fun_l26_n4(x) + end +end + +def fun_l25_n988(x) + if (x < 1) + fun_l26_n538(x) + else + fun_l26_n357(x) + end +end + +def fun_l25_n989(x) + if (x < 1) + fun_l26_n922(x) + else + fun_l26_n457(x) + end +end + +def fun_l25_n990(x) + if (x < 1) + fun_l26_n250(x) + else + fun_l26_n945(x) + end +end + +def fun_l25_n991(x) + if (x < 1) + fun_l26_n878(x) + else + fun_l26_n992(x) + end +end + +def fun_l25_n992(x) + if (x < 1) + fun_l26_n767(x) + else + fun_l26_n132(x) + end +end + +def fun_l25_n993(x) + if (x < 1) + fun_l26_n737(x) + else + fun_l26_n323(x) + end +end + +def fun_l25_n994(x) + if (x < 1) + fun_l26_n173(x) + else + fun_l26_n424(x) + end +end + +def fun_l25_n995(x) + if (x < 1) + fun_l26_n860(x) + else + fun_l26_n390(x) + end +end + +def fun_l25_n996(x) + if (x < 1) + fun_l26_n794(x) + else + fun_l26_n613(x) + end +end + +def fun_l25_n997(x) + if (x < 1) + fun_l26_n807(x) + else + fun_l26_n277(x) + end +end + +def fun_l25_n998(x) + if (x < 1) + fun_l26_n418(x) + else + fun_l26_n830(x) + end +end + +def fun_l25_n999(x) + if (x < 1) + fun_l26_n212(x) + else + fun_l26_n863(x) + end +end + +def fun_l26_n0(x) + if (x < 1) + fun_l27_n276(x) + else + fun_l27_n243(x) + end +end + +def fun_l26_n1(x) + if (x < 1) + fun_l27_n136(x) + else + fun_l27_n625(x) + end +end + +def fun_l26_n2(x) + if (x < 1) + fun_l27_n205(x) + else + fun_l27_n576(x) + end +end + +def fun_l26_n3(x) + if (x < 1) + fun_l27_n97(x) + else + fun_l27_n753(x) + end +end + +def fun_l26_n4(x) + if (x < 1) + fun_l27_n984(x) + else + fun_l27_n827(x) + end +end + +def fun_l26_n5(x) + if (x < 1) + fun_l27_n428(x) + else + fun_l27_n559(x) + end +end + +def fun_l26_n6(x) + if (x < 1) + fun_l27_n148(x) + else + fun_l27_n351(x) + end +end + +def fun_l26_n7(x) + if (x < 1) + fun_l27_n90(x) + else + fun_l27_n241(x) + end +end + +def fun_l26_n8(x) + if (x < 1) + fun_l27_n860(x) + else + fun_l27_n495(x) + end +end + +def fun_l26_n9(x) + if (x < 1) + fun_l27_n245(x) + else + fun_l27_n429(x) + end +end + +def fun_l26_n10(x) + if (x < 1) + fun_l27_n999(x) + else + fun_l27_n536(x) + end +end + +def fun_l26_n11(x) + if (x < 1) + fun_l27_n777(x) + else + fun_l27_n823(x) + end +end + +def fun_l26_n12(x) + if (x < 1) + fun_l27_n158(x) + else + fun_l27_n249(x) + end +end + +def fun_l26_n13(x) + if (x < 1) + fun_l27_n781(x) + else + fun_l27_n710(x) + end +end + +def fun_l26_n14(x) + if (x < 1) + fun_l27_n784(x) + else + fun_l27_n728(x) + end +end + +def fun_l26_n15(x) + if (x < 1) + fun_l27_n225(x) + else + fun_l27_n216(x) + end +end + +def fun_l26_n16(x) + if (x < 1) + fun_l27_n228(x) + else + fun_l27_n219(x) + end +end + +def fun_l26_n17(x) + if (x < 1) + fun_l27_n849(x) + else + fun_l27_n348(x) + end +end + +def fun_l26_n18(x) + if (x < 1) + fun_l27_n722(x) + else + fun_l27_n884(x) + end +end + +def fun_l26_n19(x) + if (x < 1) + fun_l27_n756(x) + else + fun_l27_n715(x) + end +end + +def fun_l26_n20(x) + if (x < 1) + fun_l27_n217(x) + else + fun_l27_n909(x) + end +end + +def fun_l26_n21(x) + if (x < 1) + fun_l27_n239(x) + else + fun_l27_n370(x) + end +end + +def fun_l26_n22(x) + if (x < 1) + fun_l27_n954(x) + else + fun_l27_n223(x) + end +end + +def fun_l26_n23(x) + if (x < 1) + fun_l27_n781(x) + else + fun_l27_n845(x) + end +end + +def fun_l26_n24(x) + if (x < 1) + fun_l27_n80(x) + else + fun_l27_n71(x) + end +end + +def fun_l26_n25(x) + if (x < 1) + fun_l27_n850(x) + else + fun_l27_n715(x) + end +end + +def fun_l26_n26(x) + if (x < 1) + fun_l27_n632(x) + else + fun_l27_n624(x) + end +end + +def fun_l26_n27(x) + if (x < 1) + fun_l27_n342(x) + else + fun_l27_n999(x) + end +end + +def fun_l26_n28(x) + if (x < 1) + fun_l27_n105(x) + else + fun_l27_n390(x) + end +end + +def fun_l26_n29(x) + if (x < 1) + fun_l27_n972(x) + else + fun_l27_n451(x) + end +end + +def fun_l26_n30(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n392(x) + end +end + +def fun_l26_n31(x) + if (x < 1) + fun_l27_n892(x) + else + fun_l27_n874(x) + end +end + +def fun_l26_n32(x) + if (x < 1) + fun_l27_n783(x) + else + fun_l27_n456(x) + end +end + +def fun_l26_n33(x) + if (x < 1) + fun_l27_n491(x) + else + fun_l27_n479(x) + end +end + +def fun_l26_n34(x) + if (x < 1) + fun_l27_n799(x) + else + fun_l27_n438(x) + end +end + +def fun_l26_n35(x) + if (x < 1) + fun_l27_n335(x) + else + fun_l27_n263(x) + end +end + +def fun_l26_n36(x) + if (x < 1) + fun_l27_n935(x) + else + fun_l27_n715(x) + end +end + +def fun_l26_n37(x) + if (x < 1) + fun_l27_n2(x) + else + fun_l27_n13(x) + end +end + +def fun_l26_n38(x) + if (x < 1) + fun_l27_n567(x) + else + fun_l27_n878(x) + end +end + +def fun_l26_n39(x) + if (x < 1) + fun_l27_n144(x) + else + fun_l27_n349(x) + end +end + +def fun_l26_n40(x) + if (x < 1) + fun_l27_n957(x) + else + fun_l27_n990(x) + end +end + +def fun_l26_n41(x) + if (x < 1) + fun_l27_n501(x) + else + fun_l27_n752(x) + end +end + +def fun_l26_n42(x) + if (x < 1) + fun_l27_n23(x) + else + fun_l27_n200(x) + end +end + +def fun_l26_n43(x) + if (x < 1) + fun_l27_n61(x) + else + fun_l27_n306(x) + end +end + +def fun_l26_n44(x) + if (x < 1) + fun_l27_n336(x) + else + fun_l27_n468(x) + end +end + +def fun_l26_n45(x) + if (x < 1) + fun_l27_n350(x) + else + fun_l27_n359(x) + end +end + +def fun_l26_n46(x) + if (x < 1) + fun_l27_n574(x) + else + fun_l27_n791(x) + end +end + +def fun_l26_n47(x) + if (x < 1) + fun_l27_n859(x) + else + fun_l27_n524(x) + end +end + +def fun_l26_n48(x) + if (x < 1) + fun_l27_n530(x) + else + fun_l27_n387(x) + end +end + +def fun_l26_n49(x) + if (x < 1) + fun_l27_n174(x) + else + fun_l27_n673(x) + end +end + +def fun_l26_n50(x) + if (x < 1) + fun_l27_n457(x) + else + fun_l27_n996(x) + end +end + +def fun_l26_n51(x) + if (x < 1) + fun_l27_n757(x) + else + fun_l27_n84(x) + end +end + +def fun_l26_n52(x) + if (x < 1) + fun_l27_n315(x) + else + fun_l27_n790(x) + end +end + +def fun_l26_n53(x) + if (x < 1) + fun_l27_n452(x) + else + fun_l27_n201(x) + end +end + +def fun_l26_n54(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n143(x) + end +end + +def fun_l26_n55(x) + if (x < 1) + fun_l27_n476(x) + else + fun_l27_n149(x) + end +end + +def fun_l26_n56(x) + if (x < 1) + fun_l27_n737(x) + else + fun_l27_n628(x) + end +end + +def fun_l26_n57(x) + if (x < 1) + fun_l27_n780(x) + else + fun_l27_n906(x) + end +end + +def fun_l26_n58(x) + if (x < 1) + fun_l27_n914(x) + else + fun_l27_n197(x) + end +end + +def fun_l26_n59(x) + if (x < 1) + fun_l27_n816(x) + else + fun_l27_n16(x) + end +end + +def fun_l26_n60(x) + if (x < 1) + fun_l27_n643(x) + else + fun_l27_n90(x) + end +end + +def fun_l26_n61(x) + if (x < 1) + fun_l27_n514(x) + else + fun_l27_n156(x) + end +end + +def fun_l26_n62(x) + if (x < 1) + fun_l27_n261(x) + else + fun_l27_n410(x) + end +end + +def fun_l26_n63(x) + if (x < 1) + fun_l27_n82(x) + else + fun_l27_n817(x) + end +end + +def fun_l26_n64(x) + if (x < 1) + fun_l27_n755(x) + else + fun_l27_n438(x) + end +end + +def fun_l26_n65(x) + if (x < 1) + fun_l27_n960(x) + else + fun_l27_n600(x) + end +end + +def fun_l26_n66(x) + if (x < 1) + fun_l27_n100(x) + else + fun_l27_n699(x) + end +end + +def fun_l26_n67(x) + if (x < 1) + fun_l27_n367(x) + else + fun_l27_n783(x) + end +end + +def fun_l26_n68(x) + if (x < 1) + fun_l27_n691(x) + else + fun_l27_n996(x) + end +end + +def fun_l26_n69(x) + if (x < 1) + fun_l27_n989(x) + else + fun_l27_n628(x) + end +end + +def fun_l26_n70(x) + if (x < 1) + fun_l27_n139(x) + else + fun_l27_n4(x) + end +end + +def fun_l26_n71(x) + if (x < 1) + fun_l27_n890(x) + else + fun_l27_n88(x) + end +end + +def fun_l26_n72(x) + if (x < 1) + fun_l27_n35(x) + else + fun_l27_n991(x) + end +end + +def fun_l26_n73(x) + if (x < 1) + fun_l27_n613(x) + else + fun_l27_n836(x) + end +end + +def fun_l26_n74(x) + if (x < 1) + fun_l27_n739(x) + else + fun_l27_n455(x) + end +end + +def fun_l26_n75(x) + if (x < 1) + fun_l27_n382(x) + else + fun_l27_n909(x) + end +end + +def fun_l26_n76(x) + if (x < 1) + fun_l27_n480(x) + else + fun_l27_n178(x) + end +end + +def fun_l26_n77(x) + if (x < 1) + fun_l27_n180(x) + else + fun_l27_n577(x) + end +end + +def fun_l26_n78(x) + if (x < 1) + fun_l27_n910(x) + else + fun_l27_n659(x) + end +end + +def fun_l26_n79(x) + if (x < 1) + fun_l27_n710(x) + else + fun_l27_n159(x) + end +end + +def fun_l26_n80(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n367(x) + end +end + +def fun_l26_n81(x) + if (x < 1) + fun_l27_n935(x) + else + fun_l27_n389(x) + end +end + +def fun_l26_n82(x) + if (x < 1) + fun_l27_n782(x) + else + fun_l27_n333(x) + end +end + +def fun_l26_n83(x) + if (x < 1) + fun_l27_n85(x) + else + fun_l27_n122(x) + end +end + +def fun_l26_n84(x) + if (x < 1) + fun_l27_n722(x) + else + fun_l27_n937(x) + end +end + +def fun_l26_n85(x) + if (x < 1) + fun_l27_n403(x) + else + fun_l27_n270(x) + end +end + +def fun_l26_n86(x) + if (x < 1) + fun_l27_n987(x) + else + fun_l27_n622(x) + end +end + +def fun_l26_n87(x) + if (x < 1) + fun_l27_n316(x) + else + fun_l27_n519(x) + end +end + +def fun_l26_n88(x) + if (x < 1) + fun_l27_n503(x) + else + fun_l27_n320(x) + end +end + +def fun_l26_n89(x) + if (x < 1) + fun_l27_n936(x) + else + fun_l27_n77(x) + end +end + +def fun_l26_n90(x) + if (x < 1) + fun_l27_n875(x) + else + fun_l27_n857(x) + end +end + +def fun_l26_n91(x) + if (x < 1) + fun_l27_n277(x) + else + fun_l27_n231(x) + end +end + +def fun_l26_n92(x) + if (x < 1) + fun_l27_n743(x) + else + fun_l27_n468(x) + end +end + +def fun_l26_n93(x) + if (x < 1) + fun_l27_n997(x) + else + fun_l27_n49(x) + end +end + +def fun_l26_n94(x) + if (x < 1) + fun_l27_n410(x) + else + fun_l27_n123(x) + end +end + +def fun_l26_n95(x) + if (x < 1) + fun_l27_n696(x) + else + fun_l27_n799(x) + end +end + +def fun_l26_n96(x) + if (x < 1) + fun_l27_n47(x) + else + fun_l27_n195(x) + end +end + +def fun_l26_n97(x) + if (x < 1) + fun_l27_n559(x) + else + fun_l27_n242(x) + end +end + +def fun_l26_n98(x) + if (x < 1) + fun_l27_n407(x) + else + fun_l27_n797(x) + end +end + +def fun_l26_n99(x) + if (x < 1) + fun_l27_n886(x) + else + fun_l27_n253(x) + end +end + +def fun_l26_n100(x) + if (x < 1) + fun_l27_n753(x) + else + fun_l27_n103(x) + end +end + +def fun_l26_n101(x) + if (x < 1) + fun_l27_n717(x) + else + fun_l27_n596(x) + end +end + +def fun_l26_n102(x) + if (x < 1) + fun_l27_n88(x) + else + fun_l27_n916(x) + end +end + +def fun_l26_n103(x) + if (x < 1) + fun_l27_n504(x) + else + fun_l27_n91(x) + end +end + +def fun_l26_n104(x) + if (x < 1) + fun_l27_n418(x) + else + fun_l27_n810(x) + end +end + +def fun_l26_n105(x) + if (x < 1) + fun_l27_n736(x) + else + fun_l27_n515(x) + end +end + +def fun_l26_n106(x) + if (x < 1) + fun_l27_n450(x) + else + fun_l27_n778(x) + end +end + +def fun_l26_n107(x) + if (x < 1) + fun_l27_n670(x) + else + fun_l27_n483(x) + end +end + +def fun_l26_n108(x) + if (x < 1) + fun_l27_n592(x) + else + fun_l27_n638(x) + end +end + +def fun_l26_n109(x) + if (x < 1) + fun_l27_n803(x) + else + fun_l27_n865(x) + end +end + +def fun_l26_n110(x) + if (x < 1) + fun_l27_n555(x) + else + fun_l27_n123(x) + end +end + +def fun_l26_n111(x) + if (x < 1) + fun_l27_n5(x) + else + fun_l27_n768(x) + end +end + +def fun_l26_n112(x) + if (x < 1) + fun_l27_n452(x) + else + fun_l27_n356(x) + end +end + +def fun_l26_n113(x) + if (x < 1) + fun_l27_n353(x) + else + fun_l27_n513(x) + end +end + +def fun_l26_n114(x) + if (x < 1) + fun_l27_n859(x) + else + fun_l27_n851(x) + end +end + +def fun_l26_n115(x) + if (x < 1) + fun_l27_n47(x) + else + fun_l27_n206(x) + end +end + +def fun_l26_n116(x) + if (x < 1) + fun_l27_n260(x) + else + fun_l27_n746(x) + end +end + +def fun_l26_n117(x) + if (x < 1) + fun_l27_n733(x) + else + fun_l27_n906(x) + end +end + +def fun_l26_n118(x) + if (x < 1) + fun_l27_n40(x) + else + fun_l27_n467(x) + end +end + +def fun_l26_n119(x) + if (x < 1) + fun_l27_n764(x) + else + fun_l27_n69(x) + end +end + +def fun_l26_n120(x) + if (x < 1) + fun_l27_n851(x) + else + fun_l27_n905(x) + end +end + +def fun_l26_n121(x) + if (x < 1) + fun_l27_n793(x) + else + fun_l27_n169(x) + end +end + +def fun_l26_n122(x) + if (x < 1) + fun_l27_n126(x) + else + fun_l27_n440(x) + end +end + +def fun_l26_n123(x) + if (x < 1) + fun_l27_n147(x) + else + fun_l27_n720(x) + end +end + +def fun_l26_n124(x) + if (x < 1) + fun_l27_n843(x) + else + fun_l27_n789(x) + end +end + +def fun_l26_n125(x) + if (x < 1) + fun_l27_n927(x) + else + fun_l27_n364(x) + end +end + +def fun_l26_n126(x) + if (x < 1) + fun_l27_n203(x) + else + fun_l27_n344(x) + end +end + +def fun_l26_n127(x) + if (x < 1) + fun_l27_n398(x) + else + fun_l27_n202(x) + end +end + +def fun_l26_n128(x) + if (x < 1) + fun_l27_n216(x) + else + fun_l27_n344(x) + end +end + +def fun_l26_n129(x) + if (x < 1) + fun_l27_n496(x) + else + fun_l27_n40(x) + end +end + +def fun_l26_n130(x) + if (x < 1) + fun_l27_n615(x) + else + fun_l27_n762(x) + end +end + +def fun_l26_n131(x) + if (x < 1) + fun_l27_n642(x) + else + fun_l27_n329(x) + end +end + +def fun_l26_n132(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n436(x) + end +end + +def fun_l26_n133(x) + if (x < 1) + fun_l27_n502(x) + else + fun_l27_n176(x) + end +end + +def fun_l26_n134(x) + if (x < 1) + fun_l27_n591(x) + else + fun_l27_n119(x) + end +end + +def fun_l26_n135(x) + if (x < 1) + fun_l27_n946(x) + else + fun_l27_n963(x) + end +end + +def fun_l26_n136(x) + if (x < 1) + fun_l27_n688(x) + else + fun_l27_n44(x) + end +end + +def fun_l26_n137(x) + if (x < 1) + fun_l27_n786(x) + else + fun_l27_n965(x) + end +end + +def fun_l26_n138(x) + if (x < 1) + fun_l27_n259(x) + else + fun_l27_n63(x) + end +end + +def fun_l26_n139(x) + if (x < 1) + fun_l27_n568(x) + else + fun_l27_n129(x) + end +end + +def fun_l26_n140(x) + if (x < 1) + fun_l27_n255(x) + else + fun_l27_n873(x) + end +end + +def fun_l26_n141(x) + if (x < 1) + fun_l27_n777(x) + else + fun_l27_n86(x) + end +end + +def fun_l26_n142(x) + if (x < 1) + fun_l27_n134(x) + else + fun_l27_n569(x) + end +end + +def fun_l26_n143(x) + if (x < 1) + fun_l27_n147(x) + else + fun_l27_n388(x) + end +end + +def fun_l26_n144(x) + if (x < 1) + fun_l27_n633(x) + else + fun_l27_n256(x) + end +end + +def fun_l26_n145(x) + if (x < 1) + fun_l27_n38(x) + else + fun_l27_n94(x) + end +end + +def fun_l26_n146(x) + if (x < 1) + fun_l27_n710(x) + else + fun_l27_n489(x) + end +end + +def fun_l26_n147(x) + if (x < 1) + fun_l27_n187(x) + else + fun_l27_n252(x) + end +end + +def fun_l26_n148(x) + if (x < 1) + fun_l27_n978(x) + else + fun_l27_n835(x) + end +end + +def fun_l26_n149(x) + if (x < 1) + fun_l27_n759(x) + else + fun_l27_n742(x) + end +end + +def fun_l26_n150(x) + if (x < 1) + fun_l27_n438(x) + else + fun_l27_n808(x) + end +end + +def fun_l26_n151(x) + if (x < 1) + fun_l27_n424(x) + else + fun_l27_n54(x) + end +end + +def fun_l26_n152(x) + if (x < 1) + fun_l27_n455(x) + else + fun_l27_n953(x) + end +end + +def fun_l26_n153(x) + if (x < 1) + fun_l27_n13(x) + else + fun_l27_n330(x) + end +end + +def fun_l26_n154(x) + if (x < 1) + fun_l27_n399(x) + else + fun_l27_n81(x) + end +end + +def fun_l26_n155(x) + if (x < 1) + fun_l27_n356(x) + else + fun_l27_n237(x) + end +end + +def fun_l26_n156(x) + if (x < 1) + fun_l27_n636(x) + else + fun_l27_n446(x) + end +end + +def fun_l26_n157(x) + if (x < 1) + fun_l27_n715(x) + else + fun_l27_n800(x) + end +end + +def fun_l26_n158(x) + if (x < 1) + fun_l27_n284(x) + else + fun_l27_n280(x) + end +end + +def fun_l26_n159(x) + if (x < 1) + fun_l27_n41(x) + else + fun_l27_n65(x) + end +end + +def fun_l26_n160(x) + if (x < 1) + fun_l27_n691(x) + else + fun_l27_n76(x) + end +end + +def fun_l26_n161(x) + if (x < 1) + fun_l27_n863(x) + else + fun_l27_n878(x) + end +end + +def fun_l26_n162(x) + if (x < 1) + fun_l27_n694(x) + else + fun_l27_n5(x) + end +end + +def fun_l26_n163(x) + if (x < 1) + fun_l27_n16(x) + else + fun_l27_n644(x) + end +end + +def fun_l26_n164(x) + if (x < 1) + fun_l27_n760(x) + else + fun_l27_n167(x) + end +end + +def fun_l26_n165(x) + if (x < 1) + fun_l27_n884(x) + else + fun_l27_n297(x) + end +end + +def fun_l26_n166(x) + if (x < 1) + fun_l27_n707(x) + else + fun_l27_n456(x) + end +end + +def fun_l26_n167(x) + if (x < 1) + fun_l27_n140(x) + else + fun_l27_n143(x) + end +end + +def fun_l26_n168(x) + if (x < 1) + fun_l27_n581(x) + else + fun_l27_n369(x) + end +end + +def fun_l26_n169(x) + if (x < 1) + fun_l27_n538(x) + else + fun_l27_n276(x) + end +end + +def fun_l26_n170(x) + if (x < 1) + fun_l27_n984(x) + else + fun_l27_n729(x) + end +end + +def fun_l26_n171(x) + if (x < 1) + fun_l27_n274(x) + else + fun_l27_n519(x) + end +end + +def fun_l26_n172(x) + if (x < 1) + fun_l27_n597(x) + else + fun_l27_n632(x) + end +end + +def fun_l26_n173(x) + if (x < 1) + fun_l27_n485(x) + else + fun_l27_n130(x) + end +end + +def fun_l26_n174(x) + if (x < 1) + fun_l27_n460(x) + else + fun_l27_n133(x) + end +end + +def fun_l26_n175(x) + if (x < 1) + fun_l27_n512(x) + else + fun_l27_n252(x) + end +end + +def fun_l26_n176(x) + if (x < 1) + fun_l27_n429(x) + else + fun_l27_n297(x) + end +end + +def fun_l26_n177(x) + if (x < 1) + fun_l27_n497(x) + else + fun_l27_n845(x) + end +end + +def fun_l26_n178(x) + if (x < 1) + fun_l27_n930(x) + else + fun_l27_n923(x) + end +end + +def fun_l26_n179(x) + if (x < 1) + fun_l27_n218(x) + else + fun_l27_n921(x) + end +end + +def fun_l26_n180(x) + if (x < 1) + fun_l27_n793(x) + else + fun_l27_n278(x) + end +end + +def fun_l26_n181(x) + if (x < 1) + fun_l27_n606(x) + else + fun_l27_n9(x) + end +end + +def fun_l26_n182(x) + if (x < 1) + fun_l27_n297(x) + else + fun_l27_n62(x) + end +end + +def fun_l26_n183(x) + if (x < 1) + fun_l27_n174(x) + else + fun_l27_n698(x) + end +end + +def fun_l26_n184(x) + if (x < 1) + fun_l27_n773(x) + else + fun_l27_n312(x) + end +end + +def fun_l26_n185(x) + if (x < 1) + fun_l27_n75(x) + else + fun_l27_n65(x) + end +end + +def fun_l26_n186(x) + if (x < 1) + fun_l27_n389(x) + else + fun_l27_n27(x) + end +end + +def fun_l26_n187(x) + if (x < 1) + fun_l27_n674(x) + else + fun_l27_n70(x) + end +end + +def fun_l26_n188(x) + if (x < 1) + fun_l27_n157(x) + else + fun_l27_n160(x) + end +end + +def fun_l26_n189(x) + if (x < 1) + fun_l27_n401(x) + else + fun_l27_n340(x) + end +end + +def fun_l26_n190(x) + if (x < 1) + fun_l27_n550(x) + else + fun_l27_n551(x) + end +end + +def fun_l26_n191(x) + if (x < 1) + fun_l27_n971(x) + else + fun_l27_n925(x) + end +end + +def fun_l26_n192(x) + if (x < 1) + fun_l27_n370(x) + else + fun_l27_n697(x) + end +end + +def fun_l26_n193(x) + if (x < 1) + fun_l27_n188(x) + else + fun_l27_n989(x) + end +end + +def fun_l26_n194(x) + if (x < 1) + fun_l27_n848(x) + else + fun_l27_n288(x) + end +end + +def fun_l26_n195(x) + if (x < 1) + fun_l27_n886(x) + else + fun_l27_n554(x) + end +end + +def fun_l26_n196(x) + if (x < 1) + fun_l27_n989(x) + else + fun_l27_n577(x) + end +end + +def fun_l26_n197(x) + if (x < 1) + fun_l27_n55(x) + else + fun_l27_n951(x) + end +end + +def fun_l26_n198(x) + if (x < 1) + fun_l27_n750(x) + else + fun_l27_n941(x) + end +end + +def fun_l26_n199(x) + if (x < 1) + fun_l27_n468(x) + else + fun_l27_n64(x) + end +end + +def fun_l26_n200(x) + if (x < 1) + fun_l27_n617(x) + else + fun_l27_n156(x) + end +end + +def fun_l26_n201(x) + if (x < 1) + fun_l27_n119(x) + else + fun_l27_n63(x) + end +end + +def fun_l26_n202(x) + if (x < 1) + fun_l27_n524(x) + else + fun_l27_n455(x) + end +end + +def fun_l26_n203(x) + if (x < 1) + fun_l27_n489(x) + else + fun_l27_n328(x) + end +end + +def fun_l26_n204(x) + if (x < 1) + fun_l27_n854(x) + else + fun_l27_n605(x) + end +end + +def fun_l26_n205(x) + if (x < 1) + fun_l27_n591(x) + else + fun_l27_n787(x) + end +end + +def fun_l26_n206(x) + if (x < 1) + fun_l27_n122(x) + else + fun_l27_n977(x) + end +end + +def fun_l26_n207(x) + if (x < 1) + fun_l27_n204(x) + else + fun_l27_n652(x) + end +end + +def fun_l26_n208(x) + if (x < 1) + fun_l27_n213(x) + else + fun_l27_n699(x) + end +end + +def fun_l26_n209(x) + if (x < 1) + fun_l27_n731(x) + else + fun_l27_n910(x) + end +end + +def fun_l26_n210(x) + if (x < 1) + fun_l27_n398(x) + else + fun_l27_n2(x) + end +end + +def fun_l26_n211(x) + if (x < 1) + fun_l27_n132(x) + else + fun_l27_n574(x) + end +end + +def fun_l26_n212(x) + if (x < 1) + fun_l27_n701(x) + else + fun_l27_n617(x) + end +end + +def fun_l26_n213(x) + if (x < 1) + fun_l27_n486(x) + else + fun_l27_n861(x) + end +end + +def fun_l26_n214(x) + if (x < 1) + fun_l27_n305(x) + else + fun_l27_n20(x) + end +end + +def fun_l26_n215(x) + if (x < 1) + fun_l27_n598(x) + else + fun_l27_n842(x) + end +end + +def fun_l26_n216(x) + if (x < 1) + fun_l27_n948(x) + else + fun_l27_n669(x) + end +end + +def fun_l26_n217(x) + if (x < 1) + fun_l27_n344(x) + else + fun_l27_n101(x) + end +end + +def fun_l26_n218(x) + if (x < 1) + fun_l27_n527(x) + else + fun_l27_n930(x) + end +end + +def fun_l26_n219(x) + if (x < 1) + fun_l27_n889(x) + else + fun_l27_n380(x) + end +end + +def fun_l26_n220(x) + if (x < 1) + fun_l27_n873(x) + else + fun_l27_n925(x) + end +end + +def fun_l26_n221(x) + if (x < 1) + fun_l27_n403(x) + else + fun_l27_n280(x) + end +end + +def fun_l26_n222(x) + if (x < 1) + fun_l27_n614(x) + else + fun_l27_n370(x) + end +end + +def fun_l26_n223(x) + if (x < 1) + fun_l27_n543(x) + else + fun_l27_n543(x) + end +end + +def fun_l26_n224(x) + if (x < 1) + fun_l27_n873(x) + else + fun_l27_n895(x) + end +end + +def fun_l26_n225(x) + if (x < 1) + fun_l27_n665(x) + else + fun_l27_n259(x) + end +end + +def fun_l26_n226(x) + if (x < 1) + fun_l27_n663(x) + else + fun_l27_n271(x) + end +end + +def fun_l26_n227(x) + if (x < 1) + fun_l27_n816(x) + else + fun_l27_n353(x) + end +end + +def fun_l26_n228(x) + if (x < 1) + fun_l27_n941(x) + else + fun_l27_n484(x) + end +end + +def fun_l26_n229(x) + if (x < 1) + fun_l27_n455(x) + else + fun_l27_n385(x) + end +end + +def fun_l26_n230(x) + if (x < 1) + fun_l27_n398(x) + else + fun_l27_n888(x) + end +end + +def fun_l26_n231(x) + if (x < 1) + fun_l27_n93(x) + else + fun_l27_n297(x) + end +end + +def fun_l26_n232(x) + if (x < 1) + fun_l27_n197(x) + else + fun_l27_n779(x) + end +end + +def fun_l26_n233(x) + if (x < 1) + fun_l27_n826(x) + else + fun_l27_n835(x) + end +end + +def fun_l26_n234(x) + if (x < 1) + fun_l27_n32(x) + else + fun_l27_n430(x) + end +end + +def fun_l26_n235(x) + if (x < 1) + fun_l27_n133(x) + else + fun_l27_n743(x) + end +end + +def fun_l26_n236(x) + if (x < 1) + fun_l27_n763(x) + else + fun_l27_n683(x) + end +end + +def fun_l26_n237(x) + if (x < 1) + fun_l27_n211(x) + else + fun_l27_n726(x) + end +end + +def fun_l26_n238(x) + if (x < 1) + fun_l27_n19(x) + else + fun_l27_n404(x) + end +end + +def fun_l26_n239(x) + if (x < 1) + fun_l27_n635(x) + else + fun_l27_n427(x) + end +end + +def fun_l26_n240(x) + if (x < 1) + fun_l27_n102(x) + else + fun_l27_n875(x) + end +end + +def fun_l26_n241(x) + if (x < 1) + fun_l27_n930(x) + else + fun_l27_n189(x) + end +end + +def fun_l26_n242(x) + if (x < 1) + fun_l27_n860(x) + else + fun_l27_n347(x) + end +end + +def fun_l26_n243(x) + if (x < 1) + fun_l27_n826(x) + else + fun_l27_n848(x) + end +end + +def fun_l26_n244(x) + if (x < 1) + fun_l27_n491(x) + else + fun_l27_n797(x) + end +end + +def fun_l26_n245(x) + if (x < 1) + fun_l27_n361(x) + else + fun_l27_n382(x) + end +end + +def fun_l26_n246(x) + if (x < 1) + fun_l27_n391(x) + else + fun_l27_n907(x) + end +end + +def fun_l26_n247(x) + if (x < 1) + fun_l27_n352(x) + else + fun_l27_n501(x) + end +end + +def fun_l26_n248(x) + if (x < 1) + fun_l27_n235(x) + else + fun_l27_n610(x) + end +end + +def fun_l26_n249(x) + if (x < 1) + fun_l27_n970(x) + else + fun_l27_n561(x) + end +end + +def fun_l26_n250(x) + if (x < 1) + fun_l27_n625(x) + else + fun_l27_n526(x) + end +end + +def fun_l26_n251(x) + if (x < 1) + fun_l27_n185(x) + else + fun_l27_n911(x) + end +end + +def fun_l26_n252(x) + if (x < 1) + fun_l27_n426(x) + else + fun_l27_n247(x) + end +end + +def fun_l26_n253(x) + if (x < 1) + fun_l27_n874(x) + else + fun_l27_n28(x) + end +end + +def fun_l26_n254(x) + if (x < 1) + fun_l27_n178(x) + else + fun_l27_n290(x) + end +end + +def fun_l26_n255(x) + if (x < 1) + fun_l27_n218(x) + else + fun_l27_n816(x) + end +end + +def fun_l26_n256(x) + if (x < 1) + fun_l27_n27(x) + else + fun_l27_n896(x) + end +end + +def fun_l26_n257(x) + if (x < 1) + fun_l27_n690(x) + else + fun_l27_n27(x) + end +end + +def fun_l26_n258(x) + if (x < 1) + fun_l27_n549(x) + else + fun_l27_n481(x) + end +end + +def fun_l26_n259(x) + if (x < 1) + fun_l27_n357(x) + else + fun_l27_n604(x) + end +end + +def fun_l26_n260(x) + if (x < 1) + fun_l27_n731(x) + else + fun_l27_n111(x) + end +end + +def fun_l26_n261(x) + if (x < 1) + fun_l27_n849(x) + else + fun_l27_n91(x) + end +end + +def fun_l26_n262(x) + if (x < 1) + fun_l27_n686(x) + else + fun_l27_n969(x) + end +end + +def fun_l26_n263(x) + if (x < 1) + fun_l27_n17(x) + else + fun_l27_n424(x) + end +end + +def fun_l26_n264(x) + if (x < 1) + fun_l27_n25(x) + else + fun_l27_n487(x) + end +end + +def fun_l26_n265(x) + if (x < 1) + fun_l27_n715(x) + else + fun_l27_n210(x) + end +end + +def fun_l26_n266(x) + if (x < 1) + fun_l27_n997(x) + else + fun_l27_n563(x) + end +end + +def fun_l26_n267(x) + if (x < 1) + fun_l27_n489(x) + else + fun_l27_n666(x) + end +end + +def fun_l26_n268(x) + if (x < 1) + fun_l27_n85(x) + else + fun_l27_n780(x) + end +end + +def fun_l26_n269(x) + if (x < 1) + fun_l27_n420(x) + else + fun_l27_n897(x) + end +end + +def fun_l26_n270(x) + if (x < 1) + fun_l27_n152(x) + else + fun_l27_n841(x) + end +end + +def fun_l26_n271(x) + if (x < 1) + fun_l27_n60(x) + else + fun_l27_n808(x) + end +end + +def fun_l26_n272(x) + if (x < 1) + fun_l27_n27(x) + else + fun_l27_n69(x) + end +end + +def fun_l26_n273(x) + if (x < 1) + fun_l27_n992(x) + else + fun_l27_n306(x) + end +end + +def fun_l26_n274(x) + if (x < 1) + fun_l27_n893(x) + else + fun_l27_n837(x) + end +end + +def fun_l26_n275(x) + if (x < 1) + fun_l27_n617(x) + else + fun_l27_n628(x) + end +end + +def fun_l26_n276(x) + if (x < 1) + fun_l27_n402(x) + else + fun_l27_n766(x) + end +end + +def fun_l26_n277(x) + if (x < 1) + fun_l27_n692(x) + else + fun_l27_n999(x) + end +end + +def fun_l26_n278(x) + if (x < 1) + fun_l27_n896(x) + else + fun_l27_n941(x) + end +end + +def fun_l26_n279(x) + if (x < 1) + fun_l27_n440(x) + else + fun_l27_n888(x) + end +end + +def fun_l26_n280(x) + if (x < 1) + fun_l27_n350(x) + else + fun_l27_n19(x) + end +end + +def fun_l26_n281(x) + if (x < 1) + fun_l27_n324(x) + else + fun_l27_n63(x) + end +end + +def fun_l26_n282(x) + if (x < 1) + fun_l27_n422(x) + else + fun_l27_n369(x) + end +end + +def fun_l26_n283(x) + if (x < 1) + fun_l27_n629(x) + else + fun_l27_n200(x) + end +end + +def fun_l26_n284(x) + if (x < 1) + fun_l27_n466(x) + else + fun_l27_n392(x) + end +end + +def fun_l26_n285(x) + if (x < 1) + fun_l27_n995(x) + else + fun_l27_n374(x) + end +end + +def fun_l26_n286(x) + if (x < 1) + fun_l27_n808(x) + else + fun_l27_n529(x) + end +end + +def fun_l26_n287(x) + if (x < 1) + fun_l27_n764(x) + else + fun_l27_n155(x) + end +end + +def fun_l26_n288(x) + if (x < 1) + fun_l27_n282(x) + else + fun_l27_n676(x) + end +end + +def fun_l26_n289(x) + if (x < 1) + fun_l27_n797(x) + else + fun_l27_n462(x) + end +end + +def fun_l26_n290(x) + if (x < 1) + fun_l27_n572(x) + else + fun_l27_n909(x) + end +end + +def fun_l26_n291(x) + if (x < 1) + fun_l27_n401(x) + else + fun_l27_n906(x) + end +end + +def fun_l26_n292(x) + if (x < 1) + fun_l27_n680(x) + else + fun_l27_n922(x) + end +end + +def fun_l26_n293(x) + if (x < 1) + fun_l27_n876(x) + else + fun_l27_n882(x) + end +end + +def fun_l26_n294(x) + if (x < 1) + fun_l27_n40(x) + else + fun_l27_n752(x) + end +end + +def fun_l26_n295(x) + if (x < 1) + fun_l27_n164(x) + else + fun_l27_n479(x) + end +end + +def fun_l26_n296(x) + if (x < 1) + fun_l27_n836(x) + else + fun_l27_n956(x) + end +end + +def fun_l26_n297(x) + if (x < 1) + fun_l27_n197(x) + else + fun_l27_n135(x) + end +end + +def fun_l26_n298(x) + if (x < 1) + fun_l27_n289(x) + else + fun_l27_n314(x) + end +end + +def fun_l26_n299(x) + if (x < 1) + fun_l27_n942(x) + else + fun_l27_n747(x) + end +end + +def fun_l26_n300(x) + if (x < 1) + fun_l27_n4(x) + else + fun_l27_n355(x) + end +end + +def fun_l26_n301(x) + if (x < 1) + fun_l27_n616(x) + else + fun_l27_n681(x) + end +end + +def fun_l26_n302(x) + if (x < 1) + fun_l27_n175(x) + else + fun_l27_n859(x) + end +end + +def fun_l26_n303(x) + if (x < 1) + fun_l27_n323(x) + else + fun_l27_n491(x) + end +end + +def fun_l26_n304(x) + if (x < 1) + fun_l27_n630(x) + else + fun_l27_n821(x) + end +end + +def fun_l26_n305(x) + if (x < 1) + fun_l27_n416(x) + else + fun_l27_n927(x) + end +end + +def fun_l26_n306(x) + if (x < 1) + fun_l27_n80(x) + else + fun_l27_n69(x) + end +end + +def fun_l26_n307(x) + if (x < 1) + fun_l27_n209(x) + else + fun_l27_n476(x) + end +end + +def fun_l26_n308(x) + if (x < 1) + fun_l27_n201(x) + else + fun_l27_n18(x) + end +end + +def fun_l26_n309(x) + if (x < 1) + fun_l27_n712(x) + else + fun_l27_n697(x) + end +end + +def fun_l26_n310(x) + if (x < 1) + fun_l27_n815(x) + else + fun_l27_n626(x) + end +end + +def fun_l26_n311(x) + if (x < 1) + fun_l27_n159(x) + else + fun_l27_n483(x) + end +end + +def fun_l26_n312(x) + if (x < 1) + fun_l27_n304(x) + else + fun_l27_n260(x) + end +end + +def fun_l26_n313(x) + if (x < 1) + fun_l27_n15(x) + else + fun_l27_n50(x) + end +end + +def fun_l26_n314(x) + if (x < 1) + fun_l27_n748(x) + else + fun_l27_n71(x) + end +end + +def fun_l26_n315(x) + if (x < 1) + fun_l27_n957(x) + else + fun_l27_n90(x) + end +end + +def fun_l26_n316(x) + if (x < 1) + fun_l27_n189(x) + else + fun_l27_n276(x) + end +end + +def fun_l26_n317(x) + if (x < 1) + fun_l27_n926(x) + else + fun_l27_n916(x) + end +end + +def fun_l26_n318(x) + if (x < 1) + fun_l27_n74(x) + else + fun_l27_n395(x) + end +end + +def fun_l26_n319(x) + if (x < 1) + fun_l27_n424(x) + else + fun_l27_n826(x) + end +end + +def fun_l26_n320(x) + if (x < 1) + fun_l27_n321(x) + else + fun_l27_n553(x) + end +end + +def fun_l26_n321(x) + if (x < 1) + fun_l27_n906(x) + else + fun_l27_n344(x) + end +end + +def fun_l26_n322(x) + if (x < 1) + fun_l27_n706(x) + else + fun_l27_n189(x) + end +end + +def fun_l26_n323(x) + if (x < 1) + fun_l27_n303(x) + else + fun_l27_n135(x) + end +end + +def fun_l26_n324(x) + if (x < 1) + fun_l27_n103(x) + else + fun_l27_n579(x) + end +end + +def fun_l26_n325(x) + if (x < 1) + fun_l27_n655(x) + else + fun_l27_n619(x) + end +end + +def fun_l26_n326(x) + if (x < 1) + fun_l27_n119(x) + else + fun_l27_n950(x) + end +end + +def fun_l26_n327(x) + if (x < 1) + fun_l27_n402(x) + else + fun_l27_n490(x) + end +end + +def fun_l26_n328(x) + if (x < 1) + fun_l27_n6(x) + else + fun_l27_n844(x) + end +end + +def fun_l26_n329(x) + if (x < 1) + fun_l27_n297(x) + else + fun_l27_n879(x) + end +end + +def fun_l26_n330(x) + if (x < 1) + fun_l27_n747(x) + else + fun_l27_n701(x) + end +end + +def fun_l26_n331(x) + if (x < 1) + fun_l27_n714(x) + else + fun_l27_n770(x) + end +end + +def fun_l26_n332(x) + if (x < 1) + fun_l27_n377(x) + else + fun_l27_n434(x) + end +end + +def fun_l26_n333(x) + if (x < 1) + fun_l27_n530(x) + else + fun_l27_n678(x) + end +end + +def fun_l26_n334(x) + if (x < 1) + fun_l27_n28(x) + else + fun_l27_n154(x) + end +end + +def fun_l26_n335(x) + if (x < 1) + fun_l27_n905(x) + else + fun_l27_n207(x) + end +end + +def fun_l26_n336(x) + if (x < 1) + fun_l27_n537(x) + else + fun_l27_n426(x) + end +end + +def fun_l26_n337(x) + if (x < 1) + fun_l27_n284(x) + else + fun_l27_n118(x) + end +end + +def fun_l26_n338(x) + if (x < 1) + fun_l27_n40(x) + else + fun_l27_n123(x) + end +end + +def fun_l26_n339(x) + if (x < 1) + fun_l27_n620(x) + else + fun_l27_n370(x) + end +end + +def fun_l26_n340(x) + if (x < 1) + fun_l27_n946(x) + else + fun_l27_n994(x) + end +end + +def fun_l26_n341(x) + if (x < 1) + fun_l27_n685(x) + else + fun_l27_n911(x) + end +end + +def fun_l26_n342(x) + if (x < 1) + fun_l27_n641(x) + else + fun_l27_n339(x) + end +end + +def fun_l26_n343(x) + if (x < 1) + fun_l27_n936(x) + else + fun_l27_n344(x) + end +end + +def fun_l26_n344(x) + if (x < 1) + fun_l27_n822(x) + else + fun_l27_n939(x) + end +end + +def fun_l26_n345(x) + if (x < 1) + fun_l27_n608(x) + else + fun_l27_n870(x) + end +end + +def fun_l26_n346(x) + if (x < 1) + fun_l27_n211(x) + else + fun_l27_n124(x) + end +end + +def fun_l26_n347(x) + if (x < 1) + fun_l27_n71(x) + else + fun_l27_n9(x) + end +end + +def fun_l26_n348(x) + if (x < 1) + fun_l27_n68(x) + else + fun_l27_n51(x) + end +end + +def fun_l26_n349(x) + if (x < 1) + fun_l27_n641(x) + else + fun_l27_n665(x) + end +end + +def fun_l26_n350(x) + if (x < 1) + fun_l27_n516(x) + else + fun_l27_n364(x) + end +end + +def fun_l26_n351(x) + if (x < 1) + fun_l27_n104(x) + else + fun_l27_n569(x) + end +end + +def fun_l26_n352(x) + if (x < 1) + fun_l27_n90(x) + else + fun_l27_n565(x) + end +end + +def fun_l26_n353(x) + if (x < 1) + fun_l27_n647(x) + else + fun_l27_n124(x) + end +end + +def fun_l26_n354(x) + if (x < 1) + fun_l27_n332(x) + else + fun_l27_n368(x) + end +end + +def fun_l26_n355(x) + if (x < 1) + fun_l27_n547(x) + else + fun_l27_n797(x) + end +end + +def fun_l26_n356(x) + if (x < 1) + fun_l27_n462(x) + else + fun_l27_n503(x) + end +end + +def fun_l26_n357(x) + if (x < 1) + fun_l27_n25(x) + else + fun_l27_n920(x) + end +end + +def fun_l26_n358(x) + if (x < 1) + fun_l27_n891(x) + else + fun_l27_n136(x) + end +end + +def fun_l26_n359(x) + if (x < 1) + fun_l27_n785(x) + else + fun_l27_n600(x) + end +end + +def fun_l26_n360(x) + if (x < 1) + fun_l27_n945(x) + else + fun_l27_n617(x) + end +end + +def fun_l26_n361(x) + if (x < 1) + fun_l27_n995(x) + else + fun_l27_n781(x) + end +end + +def fun_l26_n362(x) + if (x < 1) + fun_l27_n553(x) + else + fun_l27_n650(x) + end +end + +def fun_l26_n363(x) + if (x < 1) + fun_l27_n937(x) + else + fun_l27_n382(x) + end +end + +def fun_l26_n364(x) + if (x < 1) + fun_l27_n946(x) + else + fun_l27_n980(x) + end +end + +def fun_l26_n365(x) + if (x < 1) + fun_l27_n293(x) + else + fun_l27_n225(x) + end +end + +def fun_l26_n366(x) + if (x < 1) + fun_l27_n872(x) + else + fun_l27_n535(x) + end +end + +def fun_l26_n367(x) + if (x < 1) + fun_l27_n427(x) + else + fun_l27_n175(x) + end +end + +def fun_l26_n368(x) + if (x < 1) + fun_l27_n111(x) + else + fun_l27_n379(x) + end +end + +def fun_l26_n369(x) + if (x < 1) + fun_l27_n735(x) + else + fun_l27_n921(x) + end +end + +def fun_l26_n370(x) + if (x < 1) + fun_l27_n818(x) + else + fun_l27_n189(x) + end +end + +def fun_l26_n371(x) + if (x < 1) + fun_l27_n932(x) + else + fun_l27_n884(x) + end +end + +def fun_l26_n372(x) + if (x < 1) + fun_l27_n40(x) + else + fun_l27_n732(x) + end +end + +def fun_l26_n373(x) + if (x < 1) + fun_l27_n54(x) + else + fun_l27_n365(x) + end +end + +def fun_l26_n374(x) + if (x < 1) + fun_l27_n742(x) + else + fun_l27_n319(x) + end +end + +def fun_l26_n375(x) + if (x < 1) + fun_l27_n149(x) + else + fun_l27_n504(x) + end +end + +def fun_l26_n376(x) + if (x < 1) + fun_l27_n185(x) + else + fun_l27_n458(x) + end +end + +def fun_l26_n377(x) + if (x < 1) + fun_l27_n107(x) + else + fun_l27_n201(x) + end +end + +def fun_l26_n378(x) + if (x < 1) + fun_l27_n94(x) + else + fun_l27_n173(x) + end +end + +def fun_l26_n379(x) + if (x < 1) + fun_l27_n198(x) + else + fun_l27_n885(x) + end +end + +def fun_l26_n380(x) + if (x < 1) + fun_l27_n164(x) + else + fun_l27_n23(x) + end +end + +def fun_l26_n381(x) + if (x < 1) + fun_l27_n170(x) + else + fun_l27_n431(x) + end +end + +def fun_l26_n382(x) + if (x < 1) + fun_l27_n679(x) + else + fun_l27_n613(x) + end +end + +def fun_l26_n383(x) + if (x < 1) + fun_l27_n981(x) + else + fun_l27_n69(x) + end +end + +def fun_l26_n384(x) + if (x < 1) + fun_l27_n600(x) + else + fun_l27_n544(x) + end +end + +def fun_l26_n385(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n332(x) + end +end + +def fun_l26_n386(x) + if (x < 1) + fun_l27_n63(x) + else + fun_l27_n597(x) + end +end + +def fun_l26_n387(x) + if (x < 1) + fun_l27_n259(x) + else + fun_l27_n33(x) + end +end + +def fun_l26_n388(x) + if (x < 1) + fun_l27_n363(x) + else + fun_l27_n765(x) + end +end + +def fun_l26_n389(x) + if (x < 1) + fun_l27_n495(x) + else + fun_l27_n133(x) + end +end + +def fun_l26_n390(x) + if (x < 1) + fun_l27_n62(x) + else + fun_l27_n462(x) + end +end + +def fun_l26_n391(x) + if (x < 1) + fun_l27_n811(x) + else + fun_l27_n30(x) + end +end + +def fun_l26_n392(x) + if (x < 1) + fun_l27_n222(x) + else + fun_l27_n451(x) + end +end + +def fun_l26_n393(x) + if (x < 1) + fun_l27_n286(x) + else + fun_l27_n664(x) + end +end + +def fun_l26_n394(x) + if (x < 1) + fun_l27_n935(x) + else + fun_l27_n392(x) + end +end + +def fun_l26_n395(x) + if (x < 1) + fun_l27_n621(x) + else + fun_l27_n434(x) + end +end + +def fun_l26_n396(x) + if (x < 1) + fun_l27_n318(x) + else + fun_l27_n410(x) + end +end + +def fun_l26_n397(x) + if (x < 1) + fun_l27_n847(x) + else + fun_l27_n727(x) + end +end + +def fun_l26_n398(x) + if (x < 1) + fun_l27_n705(x) + else + fun_l27_n453(x) + end +end + +def fun_l26_n399(x) + if (x < 1) + fun_l27_n787(x) + else + fun_l27_n442(x) + end +end + +def fun_l26_n400(x) + if (x < 1) + fun_l27_n854(x) + else + fun_l27_n885(x) + end +end + +def fun_l26_n401(x) + if (x < 1) + fun_l27_n825(x) + else + fun_l27_n399(x) + end +end + +def fun_l26_n402(x) + if (x < 1) + fun_l27_n420(x) + else + fun_l27_n747(x) + end +end + +def fun_l26_n403(x) + if (x < 1) + fun_l27_n985(x) + else + fun_l27_n875(x) + end +end + +def fun_l26_n404(x) + if (x < 1) + fun_l27_n193(x) + else + fun_l27_n448(x) + end +end + +def fun_l26_n405(x) + if (x < 1) + fun_l27_n594(x) + else + fun_l27_n769(x) + end +end + +def fun_l26_n406(x) + if (x < 1) + fun_l27_n774(x) + else + fun_l27_n44(x) + end +end + +def fun_l26_n407(x) + if (x < 1) + fun_l27_n563(x) + else + fun_l27_n979(x) + end +end + +def fun_l26_n408(x) + if (x < 1) + fun_l27_n369(x) + else + fun_l27_n825(x) + end +end + +def fun_l26_n409(x) + if (x < 1) + fun_l27_n70(x) + else + fun_l27_n894(x) + end +end + +def fun_l26_n410(x) + if (x < 1) + fun_l27_n651(x) + else + fun_l27_n224(x) + end +end + +def fun_l26_n411(x) + if (x < 1) + fun_l27_n219(x) + else + fun_l27_n193(x) + end +end + +def fun_l26_n412(x) + if (x < 1) + fun_l27_n16(x) + else + fun_l27_n113(x) + end +end + +def fun_l26_n413(x) + if (x < 1) + fun_l27_n653(x) + else + fun_l27_n754(x) + end +end + +def fun_l26_n414(x) + if (x < 1) + fun_l27_n682(x) + else + fun_l27_n378(x) + end +end + +def fun_l26_n415(x) + if (x < 1) + fun_l27_n326(x) + else + fun_l27_n534(x) + end +end + +def fun_l26_n416(x) + if (x < 1) + fun_l27_n552(x) + else + fun_l27_n627(x) + end +end + +def fun_l26_n417(x) + if (x < 1) + fun_l27_n486(x) + else + fun_l27_n729(x) + end +end + +def fun_l26_n418(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n220(x) + end +end + +def fun_l26_n419(x) + if (x < 1) + fun_l27_n636(x) + else + fun_l27_n492(x) + end +end + +def fun_l26_n420(x) + if (x < 1) + fun_l27_n692(x) + else + fun_l27_n7(x) + end +end + +def fun_l26_n421(x) + if (x < 1) + fun_l27_n303(x) + else + fun_l27_n396(x) + end +end + +def fun_l26_n422(x) + if (x < 1) + fun_l27_n937(x) + else + fun_l27_n940(x) + end +end + +def fun_l26_n423(x) + if (x < 1) + fun_l27_n581(x) + else + fun_l27_n355(x) + end +end + +def fun_l26_n424(x) + if (x < 1) + fun_l27_n743(x) + else + fun_l27_n636(x) + end +end + +def fun_l26_n425(x) + if (x < 1) + fun_l27_n385(x) + else + fun_l27_n573(x) + end +end + +def fun_l26_n426(x) + if (x < 1) + fun_l27_n595(x) + else + fun_l27_n873(x) + end +end + +def fun_l26_n427(x) + if (x < 1) + fun_l27_n700(x) + else + fun_l27_n541(x) + end +end + +def fun_l26_n428(x) + if (x < 1) + fun_l27_n445(x) + else + fun_l27_n239(x) + end +end + +def fun_l26_n429(x) + if (x < 1) + fun_l27_n500(x) + else + fun_l27_n7(x) + end +end + +def fun_l26_n430(x) + if (x < 1) + fun_l27_n615(x) + else + fun_l27_n383(x) + end +end + +def fun_l26_n431(x) + if (x < 1) + fun_l27_n962(x) + else + fun_l27_n424(x) + end +end + +def fun_l26_n432(x) + if (x < 1) + fun_l27_n289(x) + else + fun_l27_n142(x) + end +end + +def fun_l26_n433(x) + if (x < 1) + fun_l27_n527(x) + else + fun_l27_n112(x) + end +end + +def fun_l26_n434(x) + if (x < 1) + fun_l27_n884(x) + else + fun_l27_n509(x) + end +end + +def fun_l26_n435(x) + if (x < 1) + fun_l27_n65(x) + else + fun_l27_n431(x) + end +end + +def fun_l26_n436(x) + if (x < 1) + fun_l27_n324(x) + else + fun_l27_n885(x) + end +end + +def fun_l26_n437(x) + if (x < 1) + fun_l27_n826(x) + else + fun_l27_n372(x) + end +end + +def fun_l26_n438(x) + if (x < 1) + fun_l27_n291(x) + else + fun_l27_n793(x) + end +end + +def fun_l26_n439(x) + if (x < 1) + fun_l27_n677(x) + else + fun_l27_n31(x) + end +end + +def fun_l26_n440(x) + if (x < 1) + fun_l27_n948(x) + else + fun_l27_n320(x) + end +end + +def fun_l26_n441(x) + if (x < 1) + fun_l27_n951(x) + else + fun_l27_n504(x) + end +end + +def fun_l26_n442(x) + if (x < 1) + fun_l27_n388(x) + else + fun_l27_n1(x) + end +end + +def fun_l26_n443(x) + if (x < 1) + fun_l27_n92(x) + else + fun_l27_n570(x) + end +end + +def fun_l26_n444(x) + if (x < 1) + fun_l27_n956(x) + else + fun_l27_n120(x) + end +end + +def fun_l26_n445(x) + if (x < 1) + fun_l27_n985(x) + else + fun_l27_n233(x) + end +end + +def fun_l26_n446(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n590(x) + end +end + +def fun_l26_n447(x) + if (x < 1) + fun_l27_n793(x) + else + fun_l27_n675(x) + end +end + +def fun_l26_n448(x) + if (x < 1) + fun_l27_n351(x) + else + fun_l27_n781(x) + end +end + +def fun_l26_n449(x) + if (x < 1) + fun_l27_n137(x) + else + fun_l27_n147(x) + end +end + +def fun_l26_n450(x) + if (x < 1) + fun_l27_n138(x) + else + fun_l27_n636(x) + end +end + +def fun_l26_n451(x) + if (x < 1) + fun_l27_n154(x) + else + fun_l27_n755(x) + end +end + +def fun_l26_n452(x) + if (x < 1) + fun_l27_n665(x) + else + fun_l27_n65(x) + end +end + +def fun_l26_n453(x) + if (x < 1) + fun_l27_n769(x) + else + fun_l27_n847(x) + end +end + +def fun_l26_n454(x) + if (x < 1) + fun_l27_n959(x) + else + fun_l27_n731(x) + end +end + +def fun_l26_n455(x) + if (x < 1) + fun_l27_n565(x) + else + fun_l27_n916(x) + end +end + +def fun_l26_n456(x) + if (x < 1) + fun_l27_n421(x) + else + fun_l27_n57(x) + end +end + +def fun_l26_n457(x) + if (x < 1) + fun_l27_n595(x) + else + fun_l27_n920(x) + end +end + +def fun_l26_n458(x) + if (x < 1) + fun_l27_n660(x) + else + fun_l27_n835(x) + end +end + +def fun_l26_n459(x) + if (x < 1) + fun_l27_n114(x) + else + fun_l27_n418(x) + end +end + +def fun_l26_n460(x) + if (x < 1) + fun_l27_n744(x) + else + fun_l27_n674(x) + end +end + +def fun_l26_n461(x) + if (x < 1) + fun_l27_n436(x) + else + fun_l27_n448(x) + end +end + +def fun_l26_n462(x) + if (x < 1) + fun_l27_n796(x) + else + fun_l27_n960(x) + end +end + +def fun_l26_n463(x) + if (x < 1) + fun_l27_n871(x) + else + fun_l27_n300(x) + end +end + +def fun_l26_n464(x) + if (x < 1) + fun_l27_n942(x) + else + fun_l27_n625(x) + end +end + +def fun_l26_n465(x) + if (x < 1) + fun_l27_n219(x) + else + fun_l27_n383(x) + end +end + +def fun_l26_n466(x) + if (x < 1) + fun_l27_n440(x) + else + fun_l27_n177(x) + end +end + +def fun_l26_n467(x) + if (x < 1) + fun_l27_n958(x) + else + fun_l27_n441(x) + end +end + +def fun_l26_n468(x) + if (x < 1) + fun_l27_n899(x) + else + fun_l27_n613(x) + end +end + +def fun_l26_n469(x) + if (x < 1) + fun_l27_n535(x) + else + fun_l27_n439(x) + end +end + +def fun_l26_n470(x) + if (x < 1) + fun_l27_n18(x) + else + fun_l27_n716(x) + end +end + +def fun_l26_n471(x) + if (x < 1) + fun_l27_n768(x) + else + fun_l27_n374(x) + end +end + +def fun_l26_n472(x) + if (x < 1) + fun_l27_n537(x) + else + fun_l27_n434(x) + end +end + +def fun_l26_n473(x) + if (x < 1) + fun_l27_n632(x) + else + fun_l27_n733(x) + end +end + +def fun_l26_n474(x) + if (x < 1) + fun_l27_n347(x) + else + fun_l27_n562(x) + end +end + +def fun_l26_n475(x) + if (x < 1) + fun_l27_n741(x) + else + fun_l27_n684(x) + end +end + +def fun_l26_n476(x) + if (x < 1) + fun_l27_n222(x) + else + fun_l27_n41(x) + end +end + +def fun_l26_n477(x) + if (x < 1) + fun_l27_n23(x) + else + fun_l27_n541(x) + end +end + +def fun_l26_n478(x) + if (x < 1) + fun_l27_n588(x) + else + fun_l27_n394(x) + end +end + +def fun_l26_n479(x) + if (x < 1) + fun_l27_n526(x) + else + fun_l27_n974(x) + end +end + +def fun_l26_n480(x) + if (x < 1) + fun_l27_n845(x) + else + fun_l27_n528(x) + end +end + +def fun_l26_n481(x) + if (x < 1) + fun_l27_n505(x) + else + fun_l27_n913(x) + end +end + +def fun_l26_n482(x) + if (x < 1) + fun_l27_n100(x) + else + fun_l27_n233(x) + end +end + +def fun_l26_n483(x) + if (x < 1) + fun_l27_n87(x) + else + fun_l27_n339(x) + end +end + +def fun_l26_n484(x) + if (x < 1) + fun_l27_n744(x) + else + fun_l27_n404(x) + end +end + +def fun_l26_n485(x) + if (x < 1) + fun_l27_n965(x) + else + fun_l27_n86(x) + end +end + +def fun_l26_n486(x) + if (x < 1) + fun_l27_n826(x) + else + fun_l27_n25(x) + end +end + +def fun_l26_n487(x) + if (x < 1) + fun_l27_n950(x) + else + fun_l27_n876(x) + end +end + +def fun_l26_n488(x) + if (x < 1) + fun_l27_n964(x) + else + fun_l27_n60(x) + end +end + +def fun_l26_n489(x) + if (x < 1) + fun_l27_n171(x) + else + fun_l27_n768(x) + end +end + +def fun_l26_n490(x) + if (x < 1) + fun_l27_n391(x) + else + fun_l27_n308(x) + end +end + +def fun_l26_n491(x) + if (x < 1) + fun_l27_n440(x) + else + fun_l27_n51(x) + end +end + +def fun_l26_n492(x) + if (x < 1) + fun_l27_n403(x) + else + fun_l27_n956(x) + end +end + +def fun_l26_n493(x) + if (x < 1) + fun_l27_n802(x) + else + fun_l27_n931(x) + end +end + +def fun_l26_n494(x) + if (x < 1) + fun_l27_n7(x) + else + fun_l27_n291(x) + end +end + +def fun_l26_n495(x) + if (x < 1) + fun_l27_n149(x) + else + fun_l27_n173(x) + end +end + +def fun_l26_n496(x) + if (x < 1) + fun_l27_n864(x) + else + fun_l27_n488(x) + end +end + +def fun_l26_n497(x) + if (x < 1) + fun_l27_n290(x) + else + fun_l27_n431(x) + end +end + +def fun_l26_n498(x) + if (x < 1) + fun_l27_n269(x) + else + fun_l27_n622(x) + end +end + +def fun_l26_n499(x) + if (x < 1) + fun_l27_n168(x) + else + fun_l27_n225(x) + end +end + +def fun_l26_n500(x) + if (x < 1) + fun_l27_n512(x) + else + fun_l27_n363(x) + end +end + +def fun_l26_n501(x) + if (x < 1) + fun_l27_n844(x) + else + fun_l27_n15(x) + end +end + +def fun_l26_n502(x) + if (x < 1) + fun_l27_n242(x) + else + fun_l27_n479(x) + end +end + +def fun_l26_n503(x) + if (x < 1) + fun_l27_n285(x) + else + fun_l27_n202(x) + end +end + +def fun_l26_n504(x) + if (x < 1) + fun_l27_n64(x) + else + fun_l27_n223(x) + end +end + +def fun_l26_n505(x) + if (x < 1) + fun_l27_n85(x) + else + fun_l27_n477(x) + end +end + +def fun_l26_n506(x) + if (x < 1) + fun_l27_n360(x) + else + fun_l27_n406(x) + end +end + +def fun_l26_n507(x) + if (x < 1) + fun_l27_n515(x) + else + fun_l27_n599(x) + end +end + +def fun_l26_n508(x) + if (x < 1) + fun_l27_n848(x) + else + fun_l27_n832(x) + end +end + +def fun_l26_n509(x) + if (x < 1) + fun_l27_n831(x) + else + fun_l27_n334(x) + end +end + +def fun_l26_n510(x) + if (x < 1) + fun_l27_n53(x) + else + fun_l27_n937(x) + end +end + +def fun_l26_n511(x) + if (x < 1) + fun_l27_n583(x) + else + fun_l27_n901(x) + end +end + +def fun_l26_n512(x) + if (x < 1) + fun_l27_n394(x) + else + fun_l27_n135(x) + end +end + +def fun_l26_n513(x) + if (x < 1) + fun_l27_n175(x) + else + fun_l27_n339(x) + end +end + +def fun_l26_n514(x) + if (x < 1) + fun_l27_n200(x) + else + fun_l27_n124(x) + end +end + +def fun_l26_n515(x) + if (x < 1) + fun_l27_n145(x) + else + fun_l27_n426(x) + end +end + +def fun_l26_n516(x) + if (x < 1) + fun_l27_n803(x) + else + fun_l27_n466(x) + end +end + +def fun_l26_n517(x) + if (x < 1) + fun_l27_n773(x) + else + fun_l27_n296(x) + end +end + +def fun_l26_n518(x) + if (x < 1) + fun_l27_n957(x) + else + fun_l27_n373(x) + end +end + +def fun_l26_n519(x) + if (x < 1) + fun_l27_n887(x) + else + fun_l27_n498(x) + end +end + +def fun_l26_n520(x) + if (x < 1) + fun_l27_n629(x) + else + fun_l27_n477(x) + end +end + +def fun_l26_n521(x) + if (x < 1) + fun_l27_n634(x) + else + fun_l27_n138(x) + end +end + +def fun_l26_n522(x) + if (x < 1) + fun_l27_n942(x) + else + fun_l27_n853(x) + end +end + +def fun_l26_n523(x) + if (x < 1) + fun_l27_n453(x) + else + fun_l27_n520(x) + end +end + +def fun_l26_n524(x) + if (x < 1) + fun_l27_n125(x) + else + fun_l27_n922(x) + end +end + +def fun_l26_n525(x) + if (x < 1) + fun_l27_n629(x) + else + fun_l27_n711(x) + end +end + +def fun_l26_n526(x) + if (x < 1) + fun_l27_n243(x) + else + fun_l27_n374(x) + end +end + +def fun_l26_n527(x) + if (x < 1) + fun_l27_n476(x) + else + fun_l27_n348(x) + end +end + +def fun_l26_n528(x) + if (x < 1) + fun_l27_n532(x) + else + fun_l27_n156(x) + end +end + +def fun_l26_n529(x) + if (x < 1) + fun_l27_n139(x) + else + fun_l27_n976(x) + end +end + +def fun_l26_n530(x) + if (x < 1) + fun_l27_n323(x) + else + fun_l27_n48(x) + end +end + +def fun_l26_n531(x) + if (x < 1) + fun_l27_n626(x) + else + fun_l27_n913(x) + end +end + +def fun_l26_n532(x) + if (x < 1) + fun_l27_n98(x) + else + fun_l27_n369(x) + end +end + +def fun_l26_n533(x) + if (x < 1) + fun_l27_n50(x) + else + fun_l27_n41(x) + end +end + +def fun_l26_n534(x) + if (x < 1) + fun_l27_n163(x) + else + fun_l27_n722(x) + end +end + +def fun_l26_n535(x) + if (x < 1) + fun_l27_n640(x) + else + fun_l27_n622(x) + end +end + +def fun_l26_n536(x) + if (x < 1) + fun_l27_n98(x) + else + fun_l27_n970(x) + end +end + +def fun_l26_n537(x) + if (x < 1) + fun_l27_n828(x) + else + fun_l27_n240(x) + end +end + +def fun_l26_n538(x) + if (x < 1) + fun_l27_n303(x) + else + fun_l27_n116(x) + end +end + +def fun_l26_n539(x) + if (x < 1) + fun_l27_n341(x) + else + fun_l27_n545(x) + end +end + +def fun_l26_n540(x) + if (x < 1) + fun_l27_n476(x) + else + fun_l27_n943(x) + end +end + +def fun_l26_n541(x) + if (x < 1) + fun_l27_n380(x) + else + fun_l27_n894(x) + end +end + +def fun_l26_n542(x) + if (x < 1) + fun_l27_n330(x) + else + fun_l27_n96(x) + end +end + +def fun_l26_n543(x) + if (x < 1) + fun_l27_n676(x) + else + fun_l27_n876(x) + end +end + +def fun_l26_n544(x) + if (x < 1) + fun_l27_n396(x) + else + fun_l27_n116(x) + end +end + +def fun_l26_n545(x) + if (x < 1) + fun_l27_n691(x) + else + fun_l27_n178(x) + end +end + +def fun_l26_n546(x) + if (x < 1) + fun_l27_n118(x) + else + fun_l27_n956(x) + end +end + +def fun_l26_n547(x) + if (x < 1) + fun_l27_n20(x) + else + fun_l27_n777(x) + end +end + +def fun_l26_n548(x) + if (x < 1) + fun_l27_n522(x) + else + fun_l27_n808(x) + end +end + +def fun_l26_n549(x) + if (x < 1) + fun_l27_n624(x) + else + fun_l27_n54(x) + end +end + +def fun_l26_n550(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n243(x) + end +end + +def fun_l26_n551(x) + if (x < 1) + fun_l27_n283(x) + else + fun_l27_n913(x) + end +end + +def fun_l26_n552(x) + if (x < 1) + fun_l27_n101(x) + else + fun_l27_n136(x) + end +end + +def fun_l26_n553(x) + if (x < 1) + fun_l27_n965(x) + else + fun_l27_n453(x) + end +end + +def fun_l26_n554(x) + if (x < 1) + fun_l27_n807(x) + else + fun_l27_n442(x) + end +end + +def fun_l26_n555(x) + if (x < 1) + fun_l27_n987(x) + else + fun_l27_n883(x) + end +end + +def fun_l26_n556(x) + if (x < 1) + fun_l27_n475(x) + else + fun_l27_n439(x) + end +end + +def fun_l26_n557(x) + if (x < 1) + fun_l27_n580(x) + else + fun_l27_n301(x) + end +end + +def fun_l26_n558(x) + if (x < 1) + fun_l27_n91(x) + else + fun_l27_n514(x) + end +end + +def fun_l26_n559(x) + if (x < 1) + fun_l27_n395(x) + else + fun_l27_n583(x) + end +end + +def fun_l26_n560(x) + if (x < 1) + fun_l27_n81(x) + else + fun_l27_n817(x) + end +end + +def fun_l26_n561(x) + if (x < 1) + fun_l27_n816(x) + else + fun_l27_n423(x) + end +end + +def fun_l26_n562(x) + if (x < 1) + fun_l27_n513(x) + else + fun_l27_n577(x) + end +end + +def fun_l26_n563(x) + if (x < 1) + fun_l27_n864(x) + else + fun_l27_n249(x) + end +end + +def fun_l26_n564(x) + if (x < 1) + fun_l27_n408(x) + else + fun_l27_n281(x) + end +end + +def fun_l26_n565(x) + if (x < 1) + fun_l27_n963(x) + else + fun_l27_n736(x) + end +end + +def fun_l26_n566(x) + if (x < 1) + fun_l27_n366(x) + else + fun_l27_n774(x) + end +end + +def fun_l26_n567(x) + if (x < 1) + fun_l27_n239(x) + else + fun_l27_n473(x) + end +end + +def fun_l26_n568(x) + if (x < 1) + fun_l27_n272(x) + else + fun_l27_n790(x) + end +end + +def fun_l26_n569(x) + if (x < 1) + fun_l27_n225(x) + else + fun_l27_n970(x) + end +end + +def fun_l26_n570(x) + if (x < 1) + fun_l27_n631(x) + else + fun_l27_n988(x) + end +end + +def fun_l26_n571(x) + if (x < 1) + fun_l27_n224(x) + else + fun_l27_n286(x) + end +end + +def fun_l26_n572(x) + if (x < 1) + fun_l27_n141(x) + else + fun_l27_n573(x) + end +end + +def fun_l26_n573(x) + if (x < 1) + fun_l27_n493(x) + else + fun_l27_n288(x) + end +end + +def fun_l26_n574(x) + if (x < 1) + fun_l27_n573(x) + else + fun_l27_n88(x) + end +end + +def fun_l26_n575(x) + if (x < 1) + fun_l27_n174(x) + else + fun_l27_n635(x) + end +end + +def fun_l26_n576(x) + if (x < 1) + fun_l27_n146(x) + else + fun_l27_n48(x) + end +end + +def fun_l26_n577(x) + if (x < 1) + fun_l27_n344(x) + else + fun_l27_n668(x) + end +end + +def fun_l26_n578(x) + if (x < 1) + fun_l27_n624(x) + else + fun_l27_n516(x) + end +end + +def fun_l26_n579(x) + if (x < 1) + fun_l27_n349(x) + else + fun_l27_n510(x) + end +end + +def fun_l26_n580(x) + if (x < 1) + fun_l27_n625(x) + else + fun_l27_n474(x) + end +end + +def fun_l26_n581(x) + if (x < 1) + fun_l27_n473(x) + else + fun_l27_n785(x) + end +end + +def fun_l26_n582(x) + if (x < 1) + fun_l27_n246(x) + else + fun_l27_n803(x) + end +end + +def fun_l26_n583(x) + if (x < 1) + fun_l27_n232(x) + else + fun_l27_n981(x) + end +end + +def fun_l26_n584(x) + if (x < 1) + fun_l27_n825(x) + else + fun_l27_n65(x) + end +end + +def fun_l26_n585(x) + if (x < 1) + fun_l27_n258(x) + else + fun_l27_n700(x) + end +end + +def fun_l26_n586(x) + if (x < 1) + fun_l27_n404(x) + else + fun_l27_n124(x) + end +end + +def fun_l26_n587(x) + if (x < 1) + fun_l27_n390(x) + else + fun_l27_n812(x) + end +end + +def fun_l26_n588(x) + if (x < 1) + fun_l27_n874(x) + else + fun_l27_n249(x) + end +end + +def fun_l26_n589(x) + if (x < 1) + fun_l27_n837(x) + else + fun_l27_n480(x) + end +end + +def fun_l26_n590(x) + if (x < 1) + fun_l27_n126(x) + else + fun_l27_n446(x) + end +end + +def fun_l26_n591(x) + if (x < 1) + fun_l27_n838(x) + else + fun_l27_n285(x) + end +end + +def fun_l26_n592(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n821(x) + end +end + +def fun_l26_n593(x) + if (x < 1) + fun_l27_n781(x) + else + fun_l27_n310(x) + end +end + +def fun_l26_n594(x) + if (x < 1) + fun_l27_n343(x) + else + fun_l27_n853(x) + end +end + +def fun_l26_n595(x) + if (x < 1) + fun_l27_n216(x) + else + fun_l27_n334(x) + end +end + +def fun_l26_n596(x) + if (x < 1) + fun_l27_n866(x) + else + fun_l27_n981(x) + end +end + +def fun_l26_n597(x) + if (x < 1) + fun_l27_n551(x) + else + fun_l27_n184(x) + end +end + +def fun_l26_n598(x) + if (x < 1) + fun_l27_n538(x) + else + fun_l27_n878(x) + end +end + +def fun_l26_n599(x) + if (x < 1) + fun_l27_n909(x) + else + fun_l27_n435(x) + end +end + +def fun_l26_n600(x) + if (x < 1) + fun_l27_n695(x) + else + fun_l27_n886(x) + end +end + +def fun_l26_n601(x) + if (x < 1) + fun_l27_n927(x) + else + fun_l27_n303(x) + end +end + +def fun_l26_n602(x) + if (x < 1) + fun_l27_n323(x) + else + fun_l27_n534(x) + end +end + +def fun_l26_n603(x) + if (x < 1) + fun_l27_n803(x) + else + fun_l27_n34(x) + end +end + +def fun_l26_n604(x) + if (x < 1) + fun_l27_n266(x) + else + fun_l27_n800(x) + end +end + +def fun_l26_n605(x) + if (x < 1) + fun_l27_n831(x) + else + fun_l27_n338(x) + end +end + +def fun_l26_n606(x) + if (x < 1) + fun_l27_n97(x) + else + fun_l27_n772(x) + end +end + +def fun_l26_n607(x) + if (x < 1) + fun_l27_n291(x) + else + fun_l27_n756(x) + end +end + +def fun_l26_n608(x) + if (x < 1) + fun_l27_n906(x) + else + fun_l27_n861(x) + end +end + +def fun_l26_n609(x) + if (x < 1) + fun_l27_n793(x) + else + fun_l27_n845(x) + end +end + +def fun_l26_n610(x) + if (x < 1) + fun_l27_n83(x) + else + fun_l27_n359(x) + end +end + +def fun_l26_n611(x) + if (x < 1) + fun_l27_n911(x) + else + fun_l27_n526(x) + end +end + +def fun_l26_n612(x) + if (x < 1) + fun_l27_n377(x) + else + fun_l27_n387(x) + end +end + +def fun_l26_n613(x) + if (x < 1) + fun_l27_n809(x) + else + fun_l27_n802(x) + end +end + +def fun_l26_n614(x) + if (x < 1) + fun_l27_n984(x) + else + fun_l27_n683(x) + end +end + +def fun_l26_n615(x) + if (x < 1) + fun_l27_n330(x) + else + fun_l27_n439(x) + end +end + +def fun_l26_n616(x) + if (x < 1) + fun_l27_n16(x) + else + fun_l27_n831(x) + end +end + +def fun_l26_n617(x) + if (x < 1) + fun_l27_n149(x) + else + fun_l27_n934(x) + end +end + +def fun_l26_n618(x) + if (x < 1) + fun_l27_n383(x) + else + fun_l27_n439(x) + end +end + +def fun_l26_n619(x) + if (x < 1) + fun_l27_n599(x) + else + fun_l27_n855(x) + end +end + +def fun_l26_n620(x) + if (x < 1) + fun_l27_n202(x) + else + fun_l27_n902(x) + end +end + +def fun_l26_n621(x) + if (x < 1) + fun_l27_n219(x) + else + fun_l27_n13(x) + end +end + +def fun_l26_n622(x) + if (x < 1) + fun_l27_n473(x) + else + fun_l27_n12(x) + end +end + +def fun_l26_n623(x) + if (x < 1) + fun_l27_n918(x) + else + fun_l27_n50(x) + end +end + +def fun_l26_n624(x) + if (x < 1) + fun_l27_n585(x) + else + fun_l27_n902(x) + end +end + +def fun_l26_n625(x) + if (x < 1) + fun_l27_n676(x) + else + fun_l27_n533(x) + end +end + +def fun_l26_n626(x) + if (x < 1) + fun_l27_n122(x) + else + fun_l27_n823(x) + end +end + +def fun_l26_n627(x) + if (x < 1) + fun_l27_n214(x) + else + fun_l27_n485(x) + end +end + +def fun_l26_n628(x) + if (x < 1) + fun_l27_n453(x) + else + fun_l27_n312(x) + end +end + +def fun_l26_n629(x) + if (x < 1) + fun_l27_n929(x) + else + fun_l27_n272(x) + end +end + +def fun_l26_n630(x) + if (x < 1) + fun_l27_n546(x) + else + fun_l27_n950(x) + end +end + +def fun_l26_n631(x) + if (x < 1) + fun_l27_n222(x) + else + fun_l27_n780(x) + end +end + +def fun_l26_n632(x) + if (x < 1) + fun_l27_n878(x) + else + fun_l27_n721(x) + end +end + +def fun_l26_n633(x) + if (x < 1) + fun_l27_n611(x) + else + fun_l27_n15(x) + end +end + +def fun_l26_n634(x) + if (x < 1) + fun_l27_n728(x) + else + fun_l27_n848(x) + end +end + +def fun_l26_n635(x) + if (x < 1) + fun_l27_n489(x) + else + fun_l27_n3(x) + end +end + +def fun_l26_n636(x) + if (x < 1) + fun_l27_n138(x) + else + fun_l27_n231(x) + end +end + +def fun_l26_n637(x) + if (x < 1) + fun_l27_n861(x) + else + fun_l27_n115(x) + end +end + +def fun_l26_n638(x) + if (x < 1) + fun_l27_n7(x) + else + fun_l27_n894(x) + end +end + +def fun_l26_n639(x) + if (x < 1) + fun_l27_n683(x) + else + fun_l27_n964(x) + end +end + +def fun_l26_n640(x) + if (x < 1) + fun_l27_n100(x) + else + fun_l27_n40(x) + end +end + +def fun_l26_n641(x) + if (x < 1) + fun_l27_n744(x) + else + fun_l27_n855(x) + end +end + +def fun_l26_n642(x) + if (x < 1) + fun_l27_n923(x) + else + fun_l27_n664(x) + end +end + +def fun_l26_n643(x) + if (x < 1) + fun_l27_n150(x) + else + fun_l27_n713(x) + end +end + +def fun_l26_n644(x) + if (x < 1) + fun_l27_n95(x) + else + fun_l27_n566(x) + end +end + +def fun_l26_n645(x) + if (x < 1) + fun_l27_n886(x) + else + fun_l27_n811(x) + end +end + +def fun_l26_n646(x) + if (x < 1) + fun_l27_n547(x) + else + fun_l27_n412(x) + end +end + +def fun_l26_n647(x) + if (x < 1) + fun_l27_n570(x) + else + fun_l27_n606(x) + end +end + +def fun_l26_n648(x) + if (x < 1) + fun_l27_n181(x) + else + fun_l27_n216(x) + end +end + +def fun_l26_n649(x) + if (x < 1) + fun_l27_n198(x) + else + fun_l27_n988(x) + end +end + +def fun_l26_n650(x) + if (x < 1) + fun_l27_n503(x) + else + fun_l27_n257(x) + end +end + +def fun_l26_n651(x) + if (x < 1) + fun_l27_n799(x) + else + fun_l27_n175(x) + end +end + +def fun_l26_n652(x) + if (x < 1) + fun_l27_n338(x) + else + fun_l27_n560(x) + end +end + +def fun_l26_n653(x) + if (x < 1) + fun_l27_n597(x) + else + fun_l27_n988(x) + end +end + +def fun_l26_n654(x) + if (x < 1) + fun_l27_n319(x) + else + fun_l27_n299(x) + end +end + +def fun_l26_n655(x) + if (x < 1) + fun_l27_n510(x) + else + fun_l27_n375(x) + end +end + +def fun_l26_n656(x) + if (x < 1) + fun_l27_n808(x) + else + fun_l27_n289(x) + end +end + +def fun_l26_n657(x) + if (x < 1) + fun_l27_n170(x) + else + fun_l27_n64(x) + end +end + +def fun_l26_n658(x) + if (x < 1) + fun_l27_n966(x) + else + fun_l27_n487(x) + end +end + +def fun_l26_n659(x) + if (x < 1) + fun_l27_n238(x) + else + fun_l27_n638(x) + end +end + +def fun_l26_n660(x) + if (x < 1) + fun_l27_n814(x) + else + fun_l27_n203(x) + end +end + +def fun_l26_n661(x) + if (x < 1) + fun_l27_n840(x) + else + fun_l27_n867(x) + end +end + +def fun_l26_n662(x) + if (x < 1) + fun_l27_n753(x) + else + fun_l27_n543(x) + end +end + +def fun_l26_n663(x) + if (x < 1) + fun_l27_n850(x) + else + fun_l27_n539(x) + end +end + +def fun_l26_n664(x) + if (x < 1) + fun_l27_n878(x) + else + fun_l27_n648(x) + end +end + +def fun_l26_n665(x) + if (x < 1) + fun_l27_n256(x) + else + fun_l27_n243(x) + end +end + +def fun_l26_n666(x) + if (x < 1) + fun_l27_n833(x) + else + fun_l27_n251(x) + end +end + +def fun_l26_n667(x) + if (x < 1) + fun_l27_n26(x) + else + fun_l27_n206(x) + end +end + +def fun_l26_n668(x) + if (x < 1) + fun_l27_n860(x) + else + fun_l27_n736(x) + end +end + +def fun_l26_n669(x) + if (x < 1) + fun_l27_n794(x) + else + fun_l27_n185(x) + end +end + +def fun_l26_n670(x) + if (x < 1) + fun_l27_n849(x) + else + fun_l27_n218(x) + end +end + +def fun_l26_n671(x) + if (x < 1) + fun_l27_n423(x) + else + fun_l27_n163(x) + end +end + +def fun_l26_n672(x) + if (x < 1) + fun_l27_n94(x) + else + fun_l27_n341(x) + end +end + +def fun_l26_n673(x) + if (x < 1) + fun_l27_n927(x) + else + fun_l27_n721(x) + end +end + +def fun_l26_n674(x) + if (x < 1) + fun_l27_n390(x) + else + fun_l27_n807(x) + end +end + +def fun_l26_n675(x) + if (x < 1) + fun_l27_n818(x) + else + fun_l27_n532(x) + end +end + +def fun_l26_n676(x) + if (x < 1) + fun_l27_n513(x) + else + fun_l27_n414(x) + end +end + +def fun_l26_n677(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n940(x) + end +end + +def fun_l26_n678(x) + if (x < 1) + fun_l27_n178(x) + else + fun_l27_n857(x) + end +end + +def fun_l26_n679(x) + if (x < 1) + fun_l27_n806(x) + else + fun_l27_n838(x) + end +end + +def fun_l26_n680(x) + if (x < 1) + fun_l27_n216(x) + else + fun_l27_n774(x) + end +end + +def fun_l26_n681(x) + if (x < 1) + fun_l27_n969(x) + else + fun_l27_n247(x) + end +end + +def fun_l26_n682(x) + if (x < 1) + fun_l27_n175(x) + else + fun_l27_n588(x) + end +end + +def fun_l26_n683(x) + if (x < 1) + fun_l27_n310(x) + else + fun_l27_n48(x) + end +end + +def fun_l26_n684(x) + if (x < 1) + fun_l27_n669(x) + else + fun_l27_n428(x) + end +end + +def fun_l26_n685(x) + if (x < 1) + fun_l27_n592(x) + else + fun_l27_n535(x) + end +end + +def fun_l26_n686(x) + if (x < 1) + fun_l27_n81(x) + else + fun_l27_n259(x) + end +end + +def fun_l26_n687(x) + if (x < 1) + fun_l27_n498(x) + else + fun_l27_n859(x) + end +end + +def fun_l26_n688(x) + if (x < 1) + fun_l27_n695(x) + else + fun_l27_n67(x) + end +end + +def fun_l26_n689(x) + if (x < 1) + fun_l27_n97(x) + else + fun_l27_n11(x) + end +end + +def fun_l26_n690(x) + if (x < 1) + fun_l27_n901(x) + else + fun_l27_n525(x) + end +end + +def fun_l26_n691(x) + if (x < 1) + fun_l27_n545(x) + else + fun_l27_n649(x) + end +end + +def fun_l26_n692(x) + if (x < 1) + fun_l27_n866(x) + else + fun_l27_n379(x) + end +end + +def fun_l26_n693(x) + if (x < 1) + fun_l27_n475(x) + else + fun_l27_n504(x) + end +end + +def fun_l26_n694(x) + if (x < 1) + fun_l27_n527(x) + else + fun_l27_n701(x) + end +end + +def fun_l26_n695(x) + if (x < 1) + fun_l27_n159(x) + else + fun_l27_n946(x) + end +end + +def fun_l26_n696(x) + if (x < 1) + fun_l27_n850(x) + else + fun_l27_n200(x) + end +end + +def fun_l26_n697(x) + if (x < 1) + fun_l27_n318(x) + else + fun_l27_n55(x) + end +end + +def fun_l26_n698(x) + if (x < 1) + fun_l27_n563(x) + else + fun_l27_n413(x) + end +end + +def fun_l26_n699(x) + if (x < 1) + fun_l27_n976(x) + else + fun_l27_n42(x) + end +end + +def fun_l26_n700(x) + if (x < 1) + fun_l27_n112(x) + else + fun_l27_n764(x) + end +end + +def fun_l26_n701(x) + if (x < 1) + fun_l27_n519(x) + else + fun_l27_n800(x) + end +end + +def fun_l26_n702(x) + if (x < 1) + fun_l27_n701(x) + else + fun_l27_n102(x) + end +end + +def fun_l26_n703(x) + if (x < 1) + fun_l27_n200(x) + else + fun_l27_n685(x) + end +end + +def fun_l26_n704(x) + if (x < 1) + fun_l27_n770(x) + else + fun_l27_n47(x) + end +end + +def fun_l26_n705(x) + if (x < 1) + fun_l27_n479(x) + else + fun_l27_n875(x) + end +end + +def fun_l26_n706(x) + if (x < 1) + fun_l27_n369(x) + else + fun_l27_n53(x) + end +end + +def fun_l26_n707(x) + if (x < 1) + fun_l27_n16(x) + else + fun_l27_n612(x) + end +end + +def fun_l26_n708(x) + if (x < 1) + fun_l27_n235(x) + else + fun_l27_n211(x) + end +end + +def fun_l26_n709(x) + if (x < 1) + fun_l27_n636(x) + else + fun_l27_n890(x) + end +end + +def fun_l26_n710(x) + if (x < 1) + fun_l27_n877(x) + else + fun_l27_n301(x) + end +end + +def fun_l26_n711(x) + if (x < 1) + fun_l27_n783(x) + else + fun_l27_n409(x) + end +end + +def fun_l26_n712(x) + if (x < 1) + fun_l27_n595(x) + else + fun_l27_n968(x) + end +end + +def fun_l26_n713(x) + if (x < 1) + fun_l27_n858(x) + else + fun_l27_n879(x) + end +end + +def fun_l26_n714(x) + if (x < 1) + fun_l27_n66(x) + else + fun_l27_n107(x) + end +end + +def fun_l26_n715(x) + if (x < 1) + fun_l27_n636(x) + else + fun_l27_n912(x) + end +end + +def fun_l26_n716(x) + if (x < 1) + fun_l27_n605(x) + else + fun_l27_n935(x) + end +end + +def fun_l26_n717(x) + if (x < 1) + fun_l27_n186(x) + else + fun_l27_n664(x) + end +end + +def fun_l26_n718(x) + if (x < 1) + fun_l27_n865(x) + else + fun_l27_n462(x) + end +end + +def fun_l26_n719(x) + if (x < 1) + fun_l27_n783(x) + else + fun_l27_n668(x) + end +end + +def fun_l26_n720(x) + if (x < 1) + fun_l27_n697(x) + else + fun_l27_n850(x) + end +end + +def fun_l26_n721(x) + if (x < 1) + fun_l27_n668(x) + else + fun_l27_n493(x) + end +end + +def fun_l26_n722(x) + if (x < 1) + fun_l27_n25(x) + else + fun_l27_n473(x) + end +end + +def fun_l26_n723(x) + if (x < 1) + fun_l27_n311(x) + else + fun_l27_n380(x) + end +end + +def fun_l26_n724(x) + if (x < 1) + fun_l27_n766(x) + else + fun_l27_n303(x) + end +end + +def fun_l26_n725(x) + if (x < 1) + fun_l27_n97(x) + else + fun_l27_n306(x) + end +end + +def fun_l26_n726(x) + if (x < 1) + fun_l27_n333(x) + else + fun_l27_n590(x) + end +end + +def fun_l26_n727(x) + if (x < 1) + fun_l27_n596(x) + else + fun_l27_n509(x) + end +end + +def fun_l26_n728(x) + if (x < 1) + fun_l27_n234(x) + else + fun_l27_n583(x) + end +end + +def fun_l26_n729(x) + if (x < 1) + fun_l27_n692(x) + else + fun_l27_n890(x) + end +end + +def fun_l26_n730(x) + if (x < 1) + fun_l27_n864(x) + else + fun_l27_n433(x) + end +end + +def fun_l26_n731(x) + if (x < 1) + fun_l27_n866(x) + else + fun_l27_n350(x) + end +end + +def fun_l26_n732(x) + if (x < 1) + fun_l27_n913(x) + else + fun_l27_n651(x) + end +end + +def fun_l26_n733(x) + if (x < 1) + fun_l27_n919(x) + else + fun_l27_n902(x) + end +end + +def fun_l26_n734(x) + if (x < 1) + fun_l27_n731(x) + else + fun_l27_n768(x) + end +end + +def fun_l26_n735(x) + if (x < 1) + fun_l27_n613(x) + else + fun_l27_n550(x) + end +end + +def fun_l26_n736(x) + if (x < 1) + fun_l27_n795(x) + else + fun_l27_n152(x) + end +end + +def fun_l26_n737(x) + if (x < 1) + fun_l27_n214(x) + else + fun_l27_n990(x) + end +end + +def fun_l26_n738(x) + if (x < 1) + fun_l27_n521(x) + else + fun_l27_n773(x) + end +end + +def fun_l26_n739(x) + if (x < 1) + fun_l27_n44(x) + else + fun_l27_n580(x) + end +end + +def fun_l26_n740(x) + if (x < 1) + fun_l27_n800(x) + else + fun_l27_n385(x) + end +end + +def fun_l26_n741(x) + if (x < 1) + fun_l27_n412(x) + else + fun_l27_n979(x) + end +end + +def fun_l26_n742(x) + if (x < 1) + fun_l27_n392(x) + else + fun_l27_n627(x) + end +end + +def fun_l26_n743(x) + if (x < 1) + fun_l27_n348(x) + else + fun_l27_n141(x) + end +end + +def fun_l26_n744(x) + if (x < 1) + fun_l27_n199(x) + else + fun_l27_n327(x) + end +end + +def fun_l26_n745(x) + if (x < 1) + fun_l27_n302(x) + else + fun_l27_n708(x) + end +end + +def fun_l26_n746(x) + if (x < 1) + fun_l27_n431(x) + else + fun_l27_n362(x) + end +end + +def fun_l26_n747(x) + if (x < 1) + fun_l27_n409(x) + else + fun_l27_n102(x) + end +end + +def fun_l26_n748(x) + if (x < 1) + fun_l27_n631(x) + else + fun_l27_n415(x) + end +end + +def fun_l26_n749(x) + if (x < 1) + fun_l27_n196(x) + else + fun_l27_n835(x) + end +end + +def fun_l26_n750(x) + if (x < 1) + fun_l27_n731(x) + else + fun_l27_n400(x) + end +end + +def fun_l26_n751(x) + if (x < 1) + fun_l27_n561(x) + else + fun_l27_n444(x) + end +end + +def fun_l26_n752(x) + if (x < 1) + fun_l27_n444(x) + else + fun_l27_n245(x) + end +end + +def fun_l26_n753(x) + if (x < 1) + fun_l27_n784(x) + else + fun_l27_n640(x) + end +end + +def fun_l26_n754(x) + if (x < 1) + fun_l27_n988(x) + else + fun_l27_n335(x) + end +end + +def fun_l26_n755(x) + if (x < 1) + fun_l27_n188(x) + else + fun_l27_n584(x) + end +end + +def fun_l26_n756(x) + if (x < 1) + fun_l27_n356(x) + else + fun_l27_n989(x) + end +end + +def fun_l26_n757(x) + if (x < 1) + fun_l27_n687(x) + else + fun_l27_n409(x) + end +end + +def fun_l26_n758(x) + if (x < 1) + fun_l27_n383(x) + else + fun_l27_n502(x) + end +end + +def fun_l26_n759(x) + if (x < 1) + fun_l27_n507(x) + else + fun_l27_n868(x) + end +end + +def fun_l26_n760(x) + if (x < 1) + fun_l27_n109(x) + else + fun_l27_n641(x) + end +end + +def fun_l26_n761(x) + if (x < 1) + fun_l27_n831(x) + else + fun_l27_n248(x) + end +end + +def fun_l26_n762(x) + if (x < 1) + fun_l27_n150(x) + else + fun_l27_n116(x) + end +end + +def fun_l26_n763(x) + if (x < 1) + fun_l27_n811(x) + else + fun_l27_n680(x) + end +end + +def fun_l26_n764(x) + if (x < 1) + fun_l27_n593(x) + else + fun_l27_n756(x) + end +end + +def fun_l26_n765(x) + if (x < 1) + fun_l27_n468(x) + else + fun_l27_n888(x) + end +end + +def fun_l26_n766(x) + if (x < 1) + fun_l27_n154(x) + else + fun_l27_n65(x) + end +end + +def fun_l26_n767(x) + if (x < 1) + fun_l27_n709(x) + else + fun_l27_n878(x) + end +end + +def fun_l26_n768(x) + if (x < 1) + fun_l27_n270(x) + else + fun_l27_n393(x) + end +end + +def fun_l26_n769(x) + if (x < 1) + fun_l27_n315(x) + else + fun_l27_n46(x) + end +end + +def fun_l26_n770(x) + if (x < 1) + fun_l27_n448(x) + else + fun_l27_n364(x) + end +end + +def fun_l26_n771(x) + if (x < 1) + fun_l27_n865(x) + else + fun_l27_n842(x) + end +end + +def fun_l26_n772(x) + if (x < 1) + fun_l27_n231(x) + else + fun_l27_n731(x) + end +end + +def fun_l26_n773(x) + if (x < 1) + fun_l27_n303(x) + else + fun_l27_n769(x) + end +end + +def fun_l26_n774(x) + if (x < 1) + fun_l27_n257(x) + else + fun_l27_n513(x) + end +end + +def fun_l26_n775(x) + if (x < 1) + fun_l27_n805(x) + else + fun_l27_n947(x) + end +end + +def fun_l26_n776(x) + if (x < 1) + fun_l27_n199(x) + else + fun_l27_n413(x) + end +end + +def fun_l26_n777(x) + if (x < 1) + fun_l27_n631(x) + else + fun_l27_n734(x) + end +end + +def fun_l26_n778(x) + if (x < 1) + fun_l27_n978(x) + else + fun_l27_n638(x) + end +end + +def fun_l26_n779(x) + if (x < 1) + fun_l27_n441(x) + else + fun_l27_n936(x) + end +end + +def fun_l26_n780(x) + if (x < 1) + fun_l27_n120(x) + else + fun_l27_n37(x) + end +end + +def fun_l26_n781(x) + if (x < 1) + fun_l27_n44(x) + else + fun_l27_n240(x) + end +end + +def fun_l26_n782(x) + if (x < 1) + fun_l27_n920(x) + else + fun_l27_n54(x) + end +end + +def fun_l26_n783(x) + if (x < 1) + fun_l27_n488(x) + else + fun_l27_n965(x) + end +end + +def fun_l26_n784(x) + if (x < 1) + fun_l27_n226(x) + else + fun_l27_n449(x) + end +end + +def fun_l26_n785(x) + if (x < 1) + fun_l27_n794(x) + else + fun_l27_n469(x) + end +end + +def fun_l26_n786(x) + if (x < 1) + fun_l27_n287(x) + else + fun_l27_n863(x) + end +end + +def fun_l26_n787(x) + if (x < 1) + fun_l27_n714(x) + else + fun_l27_n606(x) + end +end + +def fun_l26_n788(x) + if (x < 1) + fun_l27_n649(x) + else + fun_l27_n347(x) + end +end + +def fun_l26_n789(x) + if (x < 1) + fun_l27_n176(x) + else + fun_l27_n410(x) + end +end + +def fun_l26_n790(x) + if (x < 1) + fun_l27_n688(x) + else + fun_l27_n248(x) + end +end + +def fun_l26_n791(x) + if (x < 1) + fun_l27_n157(x) + else + fun_l27_n119(x) + end +end + +def fun_l26_n792(x) + if (x < 1) + fun_l27_n470(x) + else + fun_l27_n657(x) + end +end + +def fun_l26_n793(x) + if (x < 1) + fun_l27_n246(x) + else + fun_l27_n262(x) + end +end + +def fun_l26_n794(x) + if (x < 1) + fun_l27_n142(x) + else + fun_l27_n524(x) + end +end + +def fun_l26_n795(x) + if (x < 1) + fun_l27_n695(x) + else + fun_l27_n88(x) + end +end + +def fun_l26_n796(x) + if (x < 1) + fun_l27_n599(x) + else + fun_l27_n776(x) + end +end + +def fun_l26_n797(x) + if (x < 1) + fun_l27_n364(x) + else + fun_l27_n616(x) + end +end + +def fun_l26_n798(x) + if (x < 1) + fun_l27_n793(x) + else + fun_l27_n416(x) + end +end + +def fun_l26_n799(x) + if (x < 1) + fun_l27_n552(x) + else + fun_l27_n490(x) + end +end + +def fun_l26_n800(x) + if (x < 1) + fun_l27_n691(x) + else + fun_l27_n743(x) + end +end + +def fun_l26_n801(x) + if (x < 1) + fun_l27_n257(x) + else + fun_l27_n687(x) + end +end + +def fun_l26_n802(x) + if (x < 1) + fun_l27_n877(x) + else + fun_l27_n273(x) + end +end + +def fun_l26_n803(x) + if (x < 1) + fun_l27_n398(x) + else + fun_l27_n874(x) + end +end + +def fun_l26_n804(x) + if (x < 1) + fun_l27_n114(x) + else + fun_l27_n96(x) + end +end + +def fun_l26_n805(x) + if (x < 1) + fun_l27_n489(x) + else + fun_l27_n537(x) + end +end + +def fun_l26_n806(x) + if (x < 1) + fun_l27_n619(x) + else + fun_l27_n813(x) + end +end + +def fun_l26_n807(x) + if (x < 1) + fun_l27_n335(x) + else + fun_l27_n467(x) + end +end + +def fun_l26_n808(x) + if (x < 1) + fun_l27_n17(x) + else + fun_l27_n133(x) + end +end + +def fun_l26_n809(x) + if (x < 1) + fun_l27_n266(x) + else + fun_l27_n383(x) + end +end + +def fun_l26_n810(x) + if (x < 1) + fun_l27_n391(x) + else + fun_l27_n326(x) + end +end + +def fun_l26_n811(x) + if (x < 1) + fun_l27_n292(x) + else + fun_l27_n444(x) + end +end + +def fun_l26_n812(x) + if (x < 1) + fun_l27_n920(x) + else + fun_l27_n909(x) + end +end + +def fun_l26_n813(x) + if (x < 1) + fun_l27_n575(x) + else + fun_l27_n221(x) + end +end + +def fun_l26_n814(x) + if (x < 1) + fun_l27_n66(x) + else + fun_l27_n241(x) + end +end + +def fun_l26_n815(x) + if (x < 1) + fun_l27_n552(x) + else + fun_l27_n906(x) + end +end + +def fun_l26_n816(x) + if (x < 1) + fun_l27_n301(x) + else + fun_l27_n656(x) + end +end + +def fun_l26_n817(x) + if (x < 1) + fun_l27_n472(x) + else + fun_l27_n688(x) + end +end + +def fun_l26_n818(x) + if (x < 1) + fun_l27_n712(x) + else + fun_l27_n830(x) + end +end + +def fun_l26_n819(x) + if (x < 1) + fun_l27_n102(x) + else + fun_l27_n146(x) + end +end + +def fun_l26_n820(x) + if (x < 1) + fun_l27_n448(x) + else + fun_l27_n207(x) + end +end + +def fun_l26_n821(x) + if (x < 1) + fun_l27_n732(x) + else + fun_l27_n285(x) + end +end + +def fun_l26_n822(x) + if (x < 1) + fun_l27_n973(x) + else + fun_l27_n395(x) + end +end + +def fun_l26_n823(x) + if (x < 1) + fun_l27_n329(x) + else + fun_l27_n748(x) + end +end + +def fun_l26_n824(x) + if (x < 1) + fun_l27_n280(x) + else + fun_l27_n676(x) + end +end + +def fun_l26_n825(x) + if (x < 1) + fun_l27_n867(x) + else + fun_l27_n285(x) + end +end + +def fun_l26_n826(x) + if (x < 1) + fun_l27_n380(x) + else + fun_l27_n720(x) + end +end + +def fun_l26_n827(x) + if (x < 1) + fun_l27_n595(x) + else + fun_l27_n740(x) + end +end + +def fun_l26_n828(x) + if (x < 1) + fun_l27_n356(x) + else + fun_l27_n878(x) + end +end + +def fun_l26_n829(x) + if (x < 1) + fun_l27_n453(x) + else + fun_l27_n234(x) + end +end + +def fun_l26_n830(x) + if (x < 1) + fun_l27_n775(x) + else + fun_l27_n13(x) + end +end + +def fun_l26_n831(x) + if (x < 1) + fun_l27_n242(x) + else + fun_l27_n144(x) + end +end + +def fun_l26_n832(x) + if (x < 1) + fun_l27_n734(x) + else + fun_l27_n432(x) + end +end + +def fun_l26_n833(x) + if (x < 1) + fun_l27_n996(x) + else + fun_l27_n396(x) + end +end + +def fun_l26_n834(x) + if (x < 1) + fun_l27_n367(x) + else + fun_l27_n991(x) + end +end + +def fun_l26_n835(x) + if (x < 1) + fun_l27_n285(x) + else + fun_l27_n526(x) + end +end + +def fun_l26_n836(x) + if (x < 1) + fun_l27_n945(x) + else + fun_l27_n418(x) + end +end + +def fun_l26_n837(x) + if (x < 1) + fun_l27_n622(x) + else + fun_l27_n922(x) + end +end + +def fun_l26_n838(x) + if (x < 1) + fun_l27_n997(x) + else + fun_l27_n786(x) + end +end + +def fun_l26_n839(x) + if (x < 1) + fun_l27_n478(x) + else + fun_l27_n991(x) + end +end + +def fun_l26_n840(x) + if (x < 1) + fun_l27_n473(x) + else + fun_l27_n801(x) + end +end + +def fun_l26_n841(x) + if (x < 1) + fun_l27_n675(x) + else + fun_l27_n486(x) + end +end + +def fun_l26_n842(x) + if (x < 1) + fun_l27_n170(x) + else + fun_l27_n27(x) + end +end + +def fun_l26_n843(x) + if (x < 1) + fun_l27_n699(x) + else + fun_l27_n536(x) + end +end + +def fun_l26_n844(x) + if (x < 1) + fun_l27_n388(x) + else + fun_l27_n431(x) + end +end + +def fun_l26_n845(x) + if (x < 1) + fun_l27_n248(x) + else + fun_l27_n64(x) + end +end + +def fun_l26_n846(x) + if (x < 1) + fun_l27_n64(x) + else + fun_l27_n829(x) + end +end + +def fun_l26_n847(x) + if (x < 1) + fun_l27_n850(x) + else + fun_l27_n626(x) + end +end + +def fun_l26_n848(x) + if (x < 1) + fun_l27_n889(x) + else + fun_l27_n504(x) + end +end + +def fun_l26_n849(x) + if (x < 1) + fun_l27_n121(x) + else + fun_l27_n864(x) + end +end + +def fun_l26_n850(x) + if (x < 1) + fun_l27_n985(x) + else + fun_l27_n447(x) + end +end + +def fun_l26_n851(x) + if (x < 1) + fun_l27_n952(x) + else + fun_l27_n30(x) + end +end + +def fun_l26_n852(x) + if (x < 1) + fun_l27_n444(x) + else + fun_l27_n780(x) + end +end + +def fun_l26_n853(x) + if (x < 1) + fun_l27_n969(x) + else + fun_l27_n400(x) + end +end + +def fun_l26_n854(x) + if (x < 1) + fun_l27_n711(x) + else + fun_l27_n165(x) + end +end + +def fun_l26_n855(x) + if (x < 1) + fun_l27_n514(x) + else + fun_l27_n464(x) + end +end + +def fun_l26_n856(x) + if (x < 1) + fun_l27_n531(x) + else + fun_l27_n548(x) + end +end + +def fun_l26_n857(x) + if (x < 1) + fun_l27_n996(x) + else + fun_l27_n63(x) + end +end + +def fun_l26_n858(x) + if (x < 1) + fun_l27_n516(x) + else + fun_l27_n905(x) + end +end + +def fun_l26_n859(x) + if (x < 1) + fun_l27_n42(x) + else + fun_l27_n327(x) + end +end + +def fun_l26_n860(x) + if (x < 1) + fun_l27_n300(x) + else + fun_l27_n276(x) + end +end + +def fun_l26_n861(x) + if (x < 1) + fun_l27_n734(x) + else + fun_l27_n859(x) + end +end + +def fun_l26_n862(x) + if (x < 1) + fun_l27_n135(x) + else + fun_l27_n821(x) + end +end + +def fun_l26_n863(x) + if (x < 1) + fun_l27_n645(x) + else + fun_l27_n287(x) + end +end + +def fun_l26_n864(x) + if (x < 1) + fun_l27_n243(x) + else + fun_l27_n844(x) + end +end + +def fun_l26_n865(x) + if (x < 1) + fun_l27_n909(x) + else + fun_l27_n291(x) + end +end + +def fun_l26_n866(x) + if (x < 1) + fun_l27_n925(x) + else + fun_l27_n484(x) + end +end + +def fun_l26_n867(x) + if (x < 1) + fun_l27_n678(x) + else + fun_l27_n205(x) + end +end + +def fun_l26_n868(x) + if (x < 1) + fun_l27_n612(x) + else + fun_l27_n339(x) + end +end + +def fun_l26_n869(x) + if (x < 1) + fun_l27_n622(x) + else + fun_l27_n246(x) + end +end + +def fun_l26_n870(x) + if (x < 1) + fun_l27_n431(x) + else + fun_l27_n635(x) + end +end + +def fun_l26_n871(x) + if (x < 1) + fun_l27_n89(x) + else + fun_l27_n969(x) + end +end + +def fun_l26_n872(x) + if (x < 1) + fun_l27_n839(x) + else + fun_l27_n398(x) + end +end + +def fun_l26_n873(x) + if (x < 1) + fun_l27_n230(x) + else + fun_l27_n885(x) + end +end + +def fun_l26_n874(x) + if (x < 1) + fun_l27_n202(x) + else + fun_l27_n530(x) + end +end + +def fun_l26_n875(x) + if (x < 1) + fun_l27_n153(x) + else + fun_l27_n959(x) + end +end + +def fun_l26_n876(x) + if (x < 1) + fun_l27_n891(x) + else + fun_l27_n307(x) + end +end + +def fun_l26_n877(x) + if (x < 1) + fun_l27_n648(x) + else + fun_l27_n767(x) + end +end + +def fun_l26_n878(x) + if (x < 1) + fun_l27_n120(x) + else + fun_l27_n614(x) + end +end + +def fun_l26_n879(x) + if (x < 1) + fun_l27_n46(x) + else + fun_l27_n766(x) + end +end + +def fun_l26_n880(x) + if (x < 1) + fun_l27_n882(x) + else + fun_l27_n745(x) + end +end + +def fun_l26_n881(x) + if (x < 1) + fun_l27_n966(x) + else + fun_l27_n699(x) + end +end + +def fun_l26_n882(x) + if (x < 1) + fun_l27_n354(x) + else + fun_l27_n698(x) + end +end + +def fun_l26_n883(x) + if (x < 1) + fun_l27_n723(x) + else + fun_l27_n507(x) + end +end + +def fun_l26_n884(x) + if (x < 1) + fun_l27_n705(x) + else + fun_l27_n865(x) + end +end + +def fun_l26_n885(x) + if (x < 1) + fun_l27_n609(x) + else + fun_l27_n830(x) + end +end + +def fun_l26_n886(x) + if (x < 1) + fun_l27_n679(x) + else + fun_l27_n359(x) + end +end + +def fun_l26_n887(x) + if (x < 1) + fun_l27_n830(x) + else + fun_l27_n59(x) + end +end + +def fun_l26_n888(x) + if (x < 1) + fun_l27_n160(x) + else + fun_l27_n559(x) + end +end + +def fun_l26_n889(x) + if (x < 1) + fun_l27_n233(x) + else + fun_l27_n148(x) + end +end + +def fun_l26_n890(x) + if (x < 1) + fun_l27_n520(x) + else + fun_l27_n104(x) + end +end + +def fun_l26_n891(x) + if (x < 1) + fun_l27_n826(x) + else + fun_l27_n884(x) + end +end + +def fun_l26_n892(x) + if (x < 1) + fun_l27_n546(x) + else + fun_l27_n651(x) + end +end + +def fun_l26_n893(x) + if (x < 1) + fun_l27_n181(x) + else + fun_l27_n430(x) + end +end + +def fun_l26_n894(x) + if (x < 1) + fun_l27_n540(x) + else + fun_l27_n424(x) + end +end + +def fun_l26_n895(x) + if (x < 1) + fun_l27_n321(x) + else + fun_l27_n72(x) + end +end + +def fun_l26_n896(x) + if (x < 1) + fun_l27_n532(x) + else + fun_l27_n535(x) + end +end + +def fun_l26_n897(x) + if (x < 1) + fun_l27_n171(x) + else + fun_l27_n575(x) + end +end + +def fun_l26_n898(x) + if (x < 1) + fun_l27_n150(x) + else + fun_l27_n539(x) + end +end + +def fun_l26_n899(x) + if (x < 1) + fun_l27_n27(x) + else + fun_l27_n487(x) + end +end + +def fun_l26_n900(x) + if (x < 1) + fun_l27_n484(x) + else + fun_l27_n366(x) + end +end + +def fun_l26_n901(x) + if (x < 1) + fun_l27_n708(x) + else + fun_l27_n624(x) + end +end + +def fun_l26_n902(x) + if (x < 1) + fun_l27_n811(x) + else + fun_l27_n905(x) + end +end + +def fun_l26_n903(x) + if (x < 1) + fun_l27_n474(x) + else + fun_l27_n252(x) + end +end + +def fun_l26_n904(x) + if (x < 1) + fun_l27_n765(x) + else + fun_l27_n86(x) + end +end + +def fun_l26_n905(x) + if (x < 1) + fun_l27_n120(x) + else + fun_l27_n868(x) + end +end + +def fun_l26_n906(x) + if (x < 1) + fun_l27_n824(x) + else + fun_l27_n167(x) + end +end + +def fun_l26_n907(x) + if (x < 1) + fun_l27_n874(x) + else + fun_l27_n428(x) + end +end + +def fun_l26_n908(x) + if (x < 1) + fun_l27_n270(x) + else + fun_l27_n539(x) + end +end + +def fun_l26_n909(x) + if (x < 1) + fun_l27_n451(x) + else + fun_l27_n64(x) + end +end + +def fun_l26_n910(x) + if (x < 1) + fun_l27_n680(x) + else + fun_l27_n556(x) + end +end + +def fun_l26_n911(x) + if (x < 1) + fun_l27_n480(x) + else + fun_l27_n599(x) + end +end + +def fun_l26_n912(x) + if (x < 1) + fun_l27_n861(x) + else + fun_l27_n768(x) + end +end + +def fun_l26_n913(x) + if (x < 1) + fun_l27_n679(x) + else + fun_l27_n541(x) + end +end + +def fun_l26_n914(x) + if (x < 1) + fun_l27_n69(x) + else + fun_l27_n904(x) + end +end + +def fun_l26_n915(x) + if (x < 1) + fun_l27_n658(x) + else + fun_l27_n580(x) + end +end + +def fun_l26_n916(x) + if (x < 1) + fun_l27_n595(x) + else + fun_l27_n194(x) + end +end + +def fun_l26_n917(x) + if (x < 1) + fun_l27_n518(x) + else + fun_l27_n613(x) + end +end + +def fun_l26_n918(x) + if (x < 1) + fun_l27_n46(x) + else + fun_l27_n910(x) + end +end + +def fun_l26_n919(x) + if (x < 1) + fun_l27_n471(x) + else + fun_l27_n562(x) + end +end + +def fun_l26_n920(x) + if (x < 1) + fun_l27_n637(x) + else + fun_l27_n638(x) + end +end + +def fun_l26_n921(x) + if (x < 1) + fun_l27_n77(x) + else + fun_l27_n100(x) + end +end + +def fun_l26_n922(x) + if (x < 1) + fun_l27_n382(x) + else + fun_l27_n235(x) + end +end + +def fun_l26_n923(x) + if (x < 1) + fun_l27_n576(x) + else + fun_l27_n404(x) + end +end + +def fun_l26_n924(x) + if (x < 1) + fun_l27_n338(x) + else + fun_l27_n919(x) + end +end + +def fun_l26_n925(x) + if (x < 1) + fun_l27_n758(x) + else + fun_l27_n141(x) + end +end + +def fun_l26_n926(x) + if (x < 1) + fun_l27_n904(x) + else + fun_l27_n965(x) + end +end + +def fun_l26_n927(x) + if (x < 1) + fun_l27_n149(x) + else + fun_l27_n707(x) + end +end + +def fun_l26_n928(x) + if (x < 1) + fun_l27_n337(x) + else + fun_l27_n601(x) + end +end + +def fun_l26_n929(x) + if (x < 1) + fun_l27_n34(x) + else + fun_l27_n383(x) + end +end + +def fun_l26_n930(x) + if (x < 1) + fun_l27_n937(x) + else + fun_l27_n656(x) + end +end + +def fun_l26_n931(x) + if (x < 1) + fun_l27_n786(x) + else + fun_l27_n73(x) + end +end + +def fun_l26_n932(x) + if (x < 1) + fun_l27_n568(x) + else + fun_l27_n465(x) + end +end + +def fun_l26_n933(x) + if (x < 1) + fun_l27_n552(x) + else + fun_l27_n557(x) + end +end + +def fun_l26_n934(x) + if (x < 1) + fun_l27_n261(x) + else + fun_l27_n612(x) + end +end + +def fun_l26_n935(x) + if (x < 1) + fun_l27_n707(x) + else + fun_l27_n955(x) + end +end + +def fun_l26_n936(x) + if (x < 1) + fun_l27_n948(x) + else + fun_l27_n78(x) + end +end + +def fun_l26_n937(x) + if (x < 1) + fun_l27_n963(x) + else + fun_l27_n203(x) + end +end + +def fun_l26_n938(x) + if (x < 1) + fun_l27_n779(x) + else + fun_l27_n393(x) + end +end + +def fun_l26_n939(x) + if (x < 1) + fun_l27_n403(x) + else + fun_l27_n303(x) + end +end + +def fun_l26_n940(x) + if (x < 1) + fun_l27_n779(x) + else + fun_l27_n934(x) + end +end + +def fun_l26_n941(x) + if (x < 1) + fun_l27_n191(x) + else + fun_l27_n414(x) + end +end + +def fun_l26_n942(x) + if (x < 1) + fun_l27_n22(x) + else + fun_l27_n101(x) + end +end + +def fun_l26_n943(x) + if (x < 1) + fun_l27_n501(x) + else + fun_l27_n43(x) + end +end + +def fun_l26_n944(x) + if (x < 1) + fun_l27_n154(x) + else + fun_l27_n659(x) + end +end + +def fun_l26_n945(x) + if (x < 1) + fun_l27_n346(x) + else + fun_l27_n380(x) + end +end + +def fun_l26_n946(x) + if (x < 1) + fun_l27_n653(x) + else + fun_l27_n762(x) + end +end + +def fun_l26_n947(x) + if (x < 1) + fun_l27_n191(x) + else + fun_l27_n649(x) + end +end + +def fun_l26_n948(x) + if (x < 1) + fun_l27_n645(x) + else + fun_l27_n199(x) + end +end + +def fun_l26_n949(x) + if (x < 1) + fun_l27_n251(x) + else + fun_l27_n461(x) + end +end + +def fun_l26_n950(x) + if (x < 1) + fun_l27_n720(x) + else + fun_l27_n645(x) + end +end + +def fun_l26_n951(x) + if (x < 1) + fun_l27_n200(x) + else + fun_l27_n73(x) + end +end + +def fun_l26_n952(x) + if (x < 1) + fun_l27_n86(x) + else + fun_l27_n526(x) + end +end + +def fun_l26_n953(x) + if (x < 1) + fun_l27_n448(x) + else + fun_l27_n108(x) + end +end + +def fun_l26_n954(x) + if (x < 1) + fun_l27_n931(x) + else + fun_l27_n540(x) + end +end + +def fun_l26_n955(x) + if (x < 1) + fun_l27_n298(x) + else + fun_l27_n836(x) + end +end + +def fun_l26_n956(x) + if (x < 1) + fun_l27_n232(x) + else + fun_l27_n200(x) + end +end + +def fun_l26_n957(x) + if (x < 1) + fun_l27_n342(x) + else + fun_l27_n885(x) + end +end + +def fun_l26_n958(x) + if (x < 1) + fun_l27_n254(x) + else + fun_l27_n764(x) + end +end + +def fun_l26_n959(x) + if (x < 1) + fun_l27_n765(x) + else + fun_l27_n264(x) + end +end + +def fun_l26_n960(x) + if (x < 1) + fun_l27_n45(x) + else + fun_l27_n993(x) + end +end + +def fun_l26_n961(x) + if (x < 1) + fun_l27_n105(x) + else + fun_l27_n100(x) + end +end + +def fun_l26_n962(x) + if (x < 1) + fun_l27_n979(x) + else + fun_l27_n87(x) + end +end + +def fun_l26_n963(x) + if (x < 1) + fun_l27_n103(x) + else + fun_l27_n927(x) + end +end + +def fun_l26_n964(x) + if (x < 1) + fun_l27_n635(x) + else + fun_l27_n489(x) + end +end + +def fun_l26_n965(x) + if (x < 1) + fun_l27_n565(x) + else + fun_l27_n70(x) + end +end + +def fun_l26_n966(x) + if (x < 1) + fun_l27_n370(x) + else + fun_l27_n975(x) + end +end + +def fun_l26_n967(x) + if (x < 1) + fun_l27_n997(x) + else + fun_l27_n132(x) + end +end + +def fun_l26_n968(x) + if (x < 1) + fun_l27_n964(x) + else + fun_l27_n201(x) + end +end + +def fun_l26_n969(x) + if (x < 1) + fun_l27_n710(x) + else + fun_l27_n875(x) + end +end + +def fun_l26_n970(x) + if (x < 1) + fun_l27_n736(x) + else + fun_l27_n338(x) + end +end + +def fun_l26_n971(x) + if (x < 1) + fun_l27_n429(x) + else + fun_l27_n64(x) + end +end + +def fun_l26_n972(x) + if (x < 1) + fun_l27_n986(x) + else + fun_l27_n27(x) + end +end + +def fun_l26_n973(x) + if (x < 1) + fun_l27_n419(x) + else + fun_l27_n579(x) + end +end + +def fun_l26_n974(x) + if (x < 1) + fun_l27_n479(x) + else + fun_l27_n709(x) + end +end + +def fun_l26_n975(x) + if (x < 1) + fun_l27_n524(x) + else + fun_l27_n550(x) + end +end + +def fun_l26_n976(x) + if (x < 1) + fun_l27_n679(x) + else + fun_l27_n822(x) + end +end + +def fun_l26_n977(x) + if (x < 1) + fun_l27_n535(x) + else + fun_l27_n198(x) + end +end + +def fun_l26_n978(x) + if (x < 1) + fun_l27_n226(x) + else + fun_l27_n610(x) + end +end + +def fun_l26_n979(x) + if (x < 1) + fun_l27_n460(x) + else + fun_l27_n562(x) + end +end + +def fun_l26_n980(x) + if (x < 1) + fun_l27_n109(x) + else + fun_l27_n632(x) + end +end + +def fun_l26_n981(x) + if (x < 1) + fun_l27_n936(x) + else + fun_l27_n288(x) + end +end + +def fun_l26_n982(x) + if (x < 1) + fun_l27_n668(x) + else + fun_l27_n5(x) + end +end + +def fun_l26_n983(x) + if (x < 1) + fun_l27_n458(x) + else + fun_l27_n861(x) + end +end + +def fun_l26_n984(x) + if (x < 1) + fun_l27_n722(x) + else + fun_l27_n838(x) + end +end + +def fun_l26_n985(x) + if (x < 1) + fun_l27_n883(x) + else + fun_l27_n124(x) + end +end + +def fun_l26_n986(x) + if (x < 1) + fun_l27_n873(x) + else + fun_l27_n399(x) + end +end + +def fun_l26_n987(x) + if (x < 1) + fun_l27_n449(x) + else + fun_l27_n34(x) + end +end + +def fun_l26_n988(x) + if (x < 1) + fun_l27_n549(x) + else + fun_l27_n304(x) + end +end + +def fun_l26_n989(x) + if (x < 1) + fun_l27_n287(x) + else + fun_l27_n270(x) + end +end + +def fun_l26_n990(x) + if (x < 1) + fun_l27_n950(x) + else + fun_l27_n203(x) + end +end + +def fun_l26_n991(x) + if (x < 1) + fun_l27_n39(x) + else + fun_l27_n284(x) + end +end + +def fun_l26_n992(x) + if (x < 1) + fun_l27_n944(x) + else + fun_l27_n420(x) + end +end + +def fun_l26_n993(x) + if (x < 1) + fun_l27_n254(x) + else + fun_l27_n960(x) + end +end + +def fun_l26_n994(x) + if (x < 1) + fun_l27_n374(x) + else + fun_l27_n354(x) + end +end + +def fun_l26_n995(x) + if (x < 1) + fun_l27_n766(x) + else + fun_l27_n937(x) + end +end + +def fun_l26_n996(x) + if (x < 1) + fun_l27_n299(x) + else + fun_l27_n565(x) + end +end + +def fun_l26_n997(x) + if (x < 1) + fun_l27_n390(x) + else + fun_l27_n924(x) + end +end + +def fun_l26_n998(x) + if (x < 1) + fun_l27_n452(x) + else + fun_l27_n653(x) + end +end + +def fun_l26_n999(x) + if (x < 1) + fun_l27_n110(x) + else + fun_l27_n781(x) + end +end + +def fun_l27_n0(x) + if (x < 1) + fun_l28_n77(x) + else + fun_l28_n170(x) + end +end + +def fun_l27_n1(x) + if (x < 1) + fun_l28_n420(x) + else + fun_l28_n414(x) + end +end + +def fun_l27_n2(x) + if (x < 1) + fun_l28_n802(x) + else + fun_l28_n702(x) + end +end + +def fun_l27_n3(x) + if (x < 1) + fun_l28_n742(x) + else + fun_l28_n819(x) + end +end + +def fun_l27_n4(x) + if (x < 1) + fun_l28_n75(x) + else + fun_l28_n675(x) + end +end + +def fun_l27_n5(x) + if (x < 1) + fun_l28_n276(x) + else + fun_l28_n554(x) + end +end + +def fun_l27_n6(x) + if (x < 1) + fun_l28_n505(x) + else + fun_l28_n462(x) + end +end + +def fun_l27_n7(x) + if (x < 1) + fun_l28_n401(x) + else + fun_l28_n437(x) + end +end + +def fun_l27_n8(x) + if (x < 1) + fun_l28_n987(x) + else + fun_l28_n911(x) + end +end + +def fun_l27_n9(x) + if (x < 1) + fun_l28_n196(x) + else + fun_l28_n507(x) + end +end + +def fun_l27_n10(x) + if (x < 1) + fun_l28_n676(x) + else + fun_l28_n612(x) + end +end + +def fun_l27_n11(x) + if (x < 1) + fun_l28_n630(x) + else + fun_l28_n897(x) + end +end + +def fun_l27_n12(x) + if (x < 1) + fun_l28_n655(x) + else + fun_l28_n58(x) + end +end + +def fun_l27_n13(x) + if (x < 1) + fun_l28_n777(x) + else + fun_l28_n138(x) + end +end + +def fun_l27_n14(x) + if (x < 1) + fun_l28_n233(x) + else + fun_l28_n296(x) + end +end + +def fun_l27_n15(x) + if (x < 1) + fun_l28_n580(x) + else + fun_l28_n538(x) + end +end + +def fun_l27_n16(x) + if (x < 1) + fun_l28_n124(x) + else + fun_l28_n285(x) + end +end + +def fun_l27_n17(x) + if (x < 1) + fun_l28_n250(x) + else + fun_l28_n255(x) + end +end + +def fun_l27_n18(x) + if (x < 1) + fun_l28_n872(x) + else + fun_l28_n242(x) + end +end + +def fun_l27_n19(x) + if (x < 1) + fun_l28_n548(x) + else + fun_l28_n30(x) + end +end + +def fun_l27_n20(x) + if (x < 1) + fun_l28_n411(x) + else + fun_l28_n997(x) + end +end + +def fun_l27_n21(x) + if (x < 1) + fun_l28_n860(x) + else + fun_l28_n22(x) + end +end + +def fun_l27_n22(x) + if (x < 1) + fun_l28_n147(x) + else + fun_l28_n210(x) + end +end + +def fun_l27_n23(x) + if (x < 1) + fun_l28_n763(x) + else + fun_l28_n652(x) + end +end + +def fun_l27_n24(x) + if (x < 1) + fun_l28_n678(x) + else + fun_l28_n637(x) + end +end + +def fun_l27_n25(x) + if (x < 1) + fun_l28_n748(x) + else + fun_l28_n445(x) + end +end + +def fun_l27_n26(x) + if (x < 1) + fun_l28_n796(x) + else + fun_l28_n780(x) + end +end + +def fun_l27_n27(x) + if (x < 1) + fun_l28_n26(x) + else + fun_l28_n737(x) + end +end + +def fun_l27_n28(x) + if (x < 1) + fun_l28_n779(x) + else + fun_l28_n206(x) + end +end + +def fun_l27_n29(x) + if (x < 1) + fun_l28_n236(x) + else + fun_l28_n864(x) + end +end + +def fun_l27_n30(x) + if (x < 1) + fun_l28_n937(x) + else + fun_l28_n524(x) + end +end + +def fun_l27_n31(x) + if (x < 1) + fun_l28_n61(x) + else + fun_l28_n791(x) + end +end + +def fun_l27_n32(x) + if (x < 1) + fun_l28_n891(x) + else + fun_l28_n424(x) + end +end + +def fun_l27_n33(x) + if (x < 1) + fun_l28_n856(x) + else + fun_l28_n544(x) + end +end + +def fun_l27_n34(x) + if (x < 1) + fun_l28_n575(x) + else + fun_l28_n608(x) + end +end + +def fun_l27_n35(x) + if (x < 1) + fun_l28_n546(x) + else + fun_l28_n164(x) + end +end + +def fun_l27_n36(x) + if (x < 1) + fun_l28_n482(x) + else + fun_l28_n854(x) + end +end + +def fun_l27_n37(x) + if (x < 1) + fun_l28_n667(x) + else + fun_l28_n568(x) + end +end + +def fun_l27_n38(x) + if (x < 1) + fun_l28_n8(x) + else + fun_l28_n794(x) + end +end + +def fun_l27_n39(x) + if (x < 1) + fun_l28_n504(x) + else + fun_l28_n199(x) + end +end + +def fun_l27_n40(x) + if (x < 1) + fun_l28_n360(x) + else + fun_l28_n714(x) + end +end + +def fun_l27_n41(x) + if (x < 1) + fun_l28_n758(x) + else + fun_l28_n499(x) + end +end + +def fun_l27_n42(x) + if (x < 1) + fun_l28_n617(x) + else + fun_l28_n239(x) + end +end + +def fun_l27_n43(x) + if (x < 1) + fun_l28_n357(x) + else + fun_l28_n950(x) + end +end + +def fun_l27_n44(x) + if (x < 1) + fun_l28_n308(x) + else + fun_l28_n248(x) + end +end + +def fun_l27_n45(x) + if (x < 1) + fun_l28_n887(x) + else + fun_l28_n541(x) + end +end + +def fun_l27_n46(x) + if (x < 1) + fun_l28_n922(x) + else + fun_l28_n21(x) + end +end + +def fun_l27_n47(x) + if (x < 1) + fun_l28_n398(x) + else + fun_l28_n781(x) + end +end + +def fun_l27_n48(x) + if (x < 1) + fun_l28_n573(x) + else + fun_l28_n22(x) + end +end + +def fun_l27_n49(x) + if (x < 1) + fun_l28_n324(x) + else + fun_l28_n764(x) + end +end + +def fun_l27_n50(x) + if (x < 1) + fun_l28_n428(x) + else + fun_l28_n3(x) + end +end + +def fun_l27_n51(x) + if (x < 1) + fun_l28_n637(x) + else + fun_l28_n871(x) + end +end + +def fun_l27_n52(x) + if (x < 1) + fun_l28_n547(x) + else + fun_l28_n370(x) + end +end + +def fun_l27_n53(x) + if (x < 1) + fun_l28_n864(x) + else + fun_l28_n360(x) + end +end + +def fun_l27_n54(x) + if (x < 1) + fun_l28_n960(x) + else + fun_l28_n80(x) + end +end + +def fun_l27_n55(x) + if (x < 1) + fun_l28_n339(x) + else + fun_l28_n828(x) + end +end + +def fun_l27_n56(x) + if (x < 1) + fun_l28_n613(x) + else + fun_l28_n109(x) + end +end + +def fun_l27_n57(x) + if (x < 1) + fun_l28_n458(x) + else + fun_l28_n339(x) + end +end + +def fun_l27_n58(x) + if (x < 1) + fun_l28_n313(x) + else + fun_l28_n20(x) + end +end + +def fun_l27_n59(x) + if (x < 1) + fun_l28_n642(x) + else + fun_l28_n582(x) + end +end + +def fun_l27_n60(x) + if (x < 1) + fun_l28_n407(x) + else + fun_l28_n182(x) + end +end + +def fun_l27_n61(x) + if (x < 1) + fun_l28_n475(x) + else + fun_l28_n865(x) + end +end + +def fun_l27_n62(x) + if (x < 1) + fun_l28_n867(x) + else + fun_l28_n935(x) + end +end + +def fun_l27_n63(x) + if (x < 1) + fun_l28_n361(x) + else + fun_l28_n675(x) + end +end + +def fun_l27_n64(x) + if (x < 1) + fun_l28_n583(x) + else + fun_l28_n990(x) + end +end + +def fun_l27_n65(x) + if (x < 1) + fun_l28_n305(x) + else + fun_l28_n918(x) + end +end + +def fun_l27_n66(x) + if (x < 1) + fun_l28_n449(x) + else + fun_l28_n172(x) + end +end + +def fun_l27_n67(x) + if (x < 1) + fun_l28_n384(x) + else + fun_l28_n102(x) + end +end + +def fun_l27_n68(x) + if (x < 1) + fun_l28_n27(x) + else + fun_l28_n638(x) + end +end + +def fun_l27_n69(x) + if (x < 1) + fun_l28_n370(x) + else + fun_l28_n305(x) + end +end + +def fun_l27_n70(x) + if (x < 1) + fun_l28_n91(x) + else + fun_l28_n516(x) + end +end + +def fun_l27_n71(x) + if (x < 1) + fun_l28_n835(x) + else + fun_l28_n422(x) + end +end + +def fun_l27_n72(x) + if (x < 1) + fun_l28_n528(x) + else + fun_l28_n924(x) + end +end + +def fun_l27_n73(x) + if (x < 1) + fun_l28_n910(x) + else + fun_l28_n177(x) + end +end + +def fun_l27_n74(x) + if (x < 1) + fun_l28_n424(x) + else + fun_l28_n133(x) + end +end + +def fun_l27_n75(x) + if (x < 1) + fun_l28_n207(x) + else + fun_l28_n206(x) + end +end + +def fun_l27_n76(x) + if (x < 1) + fun_l28_n285(x) + else + fun_l28_n513(x) + end +end + +def fun_l27_n77(x) + if (x < 1) + fun_l28_n446(x) + else + fun_l28_n985(x) + end +end + +def fun_l27_n78(x) + if (x < 1) + fun_l28_n814(x) + else + fun_l28_n43(x) + end +end + +def fun_l27_n79(x) + if (x < 1) + fun_l28_n155(x) + else + fun_l28_n944(x) + end +end + +def fun_l27_n80(x) + if (x < 1) + fun_l28_n22(x) + else + fun_l28_n815(x) + end +end + +def fun_l27_n81(x) + if (x < 1) + fun_l28_n465(x) + else + fun_l28_n132(x) + end +end + +def fun_l27_n82(x) + if (x < 1) + fun_l28_n540(x) + else + fun_l28_n199(x) + end +end + +def fun_l27_n83(x) + if (x < 1) + fun_l28_n28(x) + else + fun_l28_n64(x) + end +end + +def fun_l27_n84(x) + if (x < 1) + fun_l28_n4(x) + else + fun_l28_n782(x) + end +end + +def fun_l27_n85(x) + if (x < 1) + fun_l28_n685(x) + else + fun_l28_n57(x) + end +end + +def fun_l27_n86(x) + if (x < 1) + fun_l28_n755(x) + else + fun_l28_n317(x) + end +end + +def fun_l27_n87(x) + if (x < 1) + fun_l28_n298(x) + else + fun_l28_n645(x) + end +end + +def fun_l27_n88(x) + if (x < 1) + fun_l28_n489(x) + else + fun_l28_n357(x) + end +end + +def fun_l27_n89(x) + if (x < 1) + fun_l28_n225(x) + else + fun_l28_n465(x) + end +end + +def fun_l27_n90(x) + if (x < 1) + fun_l28_n729(x) + else + fun_l28_n688(x) + end +end + +def fun_l27_n91(x) + if (x < 1) + fun_l28_n936(x) + else + fun_l28_n62(x) + end +end + +def fun_l27_n92(x) + if (x < 1) + fun_l28_n564(x) + else + fun_l28_n497(x) + end +end + +def fun_l27_n93(x) + if (x < 1) + fun_l28_n78(x) + else + fun_l28_n167(x) + end +end + +def fun_l27_n94(x) + if (x < 1) + fun_l28_n24(x) + else + fun_l28_n543(x) + end +end + +def fun_l27_n95(x) + if (x < 1) + fun_l28_n56(x) + else + fun_l28_n796(x) + end +end + +def fun_l27_n96(x) + if (x < 1) + fun_l28_n768(x) + else + fun_l28_n909(x) + end +end + +def fun_l27_n97(x) + if (x < 1) + fun_l28_n72(x) + else + fun_l28_n604(x) + end +end + +def fun_l27_n98(x) + if (x < 1) + fun_l28_n903(x) + else + fun_l28_n998(x) + end +end + +def fun_l27_n99(x) + if (x < 1) + fun_l28_n525(x) + else + fun_l28_n158(x) + end +end + +def fun_l27_n100(x) + if (x < 1) + fun_l28_n54(x) + else + fun_l28_n667(x) + end +end + +def fun_l27_n101(x) + if (x < 1) + fun_l28_n894(x) + else + fun_l28_n807(x) + end +end + +def fun_l27_n102(x) + if (x < 1) + fun_l28_n334(x) + else + fun_l28_n479(x) + end +end + +def fun_l27_n103(x) + if (x < 1) + fun_l28_n211(x) + else + fun_l28_n383(x) + end +end + +def fun_l27_n104(x) + if (x < 1) + fun_l28_n598(x) + else + fun_l28_n793(x) + end +end + +def fun_l27_n105(x) + if (x < 1) + fun_l28_n812(x) + else + fun_l28_n806(x) + end +end + +def fun_l27_n106(x) + if (x < 1) + fun_l28_n726(x) + else + fun_l28_n769(x) + end +end + +def fun_l27_n107(x) + if (x < 1) + fun_l28_n593(x) + else + fun_l28_n173(x) + end +end + +def fun_l27_n108(x) + if (x < 1) + fun_l28_n490(x) + else + fun_l28_n681(x) + end +end + +def fun_l27_n109(x) + if (x < 1) + fun_l28_n691(x) + else + fun_l28_n323(x) + end +end + +def fun_l27_n110(x) + if (x < 1) + fun_l28_n710(x) + else + fun_l28_n624(x) + end +end + +def fun_l27_n111(x) + if (x < 1) + fun_l28_n563(x) + else + fun_l28_n335(x) + end +end + +def fun_l27_n112(x) + if (x < 1) + fun_l28_n510(x) + else + fun_l28_n879(x) + end +end + +def fun_l27_n113(x) + if (x < 1) + fun_l28_n900(x) + else + fun_l28_n119(x) + end +end + +def fun_l27_n114(x) + if (x < 1) + fun_l28_n17(x) + else + fun_l28_n8(x) + end +end + +def fun_l27_n115(x) + if (x < 1) + fun_l28_n813(x) + else + fun_l28_n948(x) + end +end + +def fun_l27_n116(x) + if (x < 1) + fun_l28_n644(x) + else + fun_l28_n177(x) + end +end + +def fun_l27_n117(x) + if (x < 1) + fun_l28_n635(x) + else + fun_l28_n489(x) + end +end + +def fun_l27_n118(x) + if (x < 1) + fun_l28_n520(x) + else + fun_l28_n127(x) + end +end + +def fun_l27_n119(x) + if (x < 1) + fun_l28_n859(x) + else + fun_l28_n264(x) + end +end + +def fun_l27_n120(x) + if (x < 1) + fun_l28_n29(x) + else + fun_l28_n984(x) + end +end + +def fun_l27_n121(x) + if (x < 1) + fun_l28_n2(x) + else + fun_l28_n858(x) + end +end + +def fun_l27_n122(x) + if (x < 1) + fun_l28_n907(x) + else + fun_l28_n34(x) + end +end + +def fun_l27_n123(x) + if (x < 1) + fun_l28_n495(x) + else + fun_l28_n144(x) + end +end + +def fun_l27_n124(x) + if (x < 1) + fun_l28_n160(x) + else + fun_l28_n987(x) + end +end + +def fun_l27_n125(x) + if (x < 1) + fun_l28_n60(x) + else + fun_l28_n415(x) + end +end + +def fun_l27_n126(x) + if (x < 1) + fun_l28_n473(x) + else + fun_l28_n461(x) + end +end + +def fun_l27_n127(x) + if (x < 1) + fun_l28_n664(x) + else + fun_l28_n764(x) + end +end + +def fun_l27_n128(x) + if (x < 1) + fun_l28_n815(x) + else + fun_l28_n677(x) + end +end + +def fun_l27_n129(x) + if (x < 1) + fun_l28_n828(x) + else + fun_l28_n575(x) + end +end + +def fun_l27_n130(x) + if (x < 1) + fun_l28_n100(x) + else + fun_l28_n811(x) + end +end + +def fun_l27_n131(x) + if (x < 1) + fun_l28_n789(x) + else + fun_l28_n246(x) + end +end + +def fun_l27_n132(x) + if (x < 1) + fun_l28_n506(x) + else + fun_l28_n555(x) + end +end + +def fun_l27_n133(x) + if (x < 1) + fun_l28_n272(x) + else + fun_l28_n115(x) + end +end + +def fun_l27_n134(x) + if (x < 1) + fun_l28_n925(x) + else + fun_l28_n34(x) + end +end + +def fun_l27_n135(x) + if (x < 1) + fun_l28_n844(x) + else + fun_l28_n725(x) + end +end + +def fun_l27_n136(x) + if (x < 1) + fun_l28_n825(x) + else + fun_l28_n38(x) + end +end + +def fun_l27_n137(x) + if (x < 1) + fun_l28_n607(x) + else + fun_l28_n343(x) + end +end + +def fun_l27_n138(x) + if (x < 1) + fun_l28_n874(x) + else + fun_l28_n449(x) + end +end + +def fun_l27_n139(x) + if (x < 1) + fun_l28_n632(x) + else + fun_l28_n454(x) + end +end + +def fun_l27_n140(x) + if (x < 1) + fun_l28_n902(x) + else + fun_l28_n301(x) + end +end + +def fun_l27_n141(x) + if (x < 1) + fun_l28_n395(x) + else + fun_l28_n890(x) + end +end + +def fun_l27_n142(x) + if (x < 1) + fun_l28_n625(x) + else + fun_l28_n246(x) + end +end + +def fun_l27_n143(x) + if (x < 1) + fun_l28_n312(x) + else + fun_l28_n975(x) + end +end + +def fun_l27_n144(x) + if (x < 1) + fun_l28_n974(x) + else + fun_l28_n451(x) + end +end + +def fun_l27_n145(x) + if (x < 1) + fun_l28_n541(x) + else + fun_l28_n566(x) + end +end + +def fun_l27_n146(x) + if (x < 1) + fun_l28_n285(x) + else + fun_l28_n443(x) + end +end + +def fun_l27_n147(x) + if (x < 1) + fun_l28_n71(x) + else + fun_l28_n200(x) + end +end + +def fun_l27_n148(x) + if (x < 1) + fun_l28_n681(x) + else + fun_l28_n561(x) + end +end + +def fun_l27_n149(x) + if (x < 1) + fun_l28_n470(x) + else + fun_l28_n529(x) + end +end + +def fun_l27_n150(x) + if (x < 1) + fun_l28_n83(x) + else + fun_l28_n755(x) + end +end + +def fun_l27_n151(x) + if (x < 1) + fun_l28_n142(x) + else + fun_l28_n631(x) + end +end + +def fun_l27_n152(x) + if (x < 1) + fun_l28_n49(x) + else + fun_l28_n531(x) + end +end + +def fun_l27_n153(x) + if (x < 1) + fun_l28_n237(x) + else + fun_l28_n241(x) + end +end + +def fun_l27_n154(x) + if (x < 1) + fun_l28_n36(x) + else + fun_l28_n862(x) + end +end + +def fun_l27_n155(x) + if (x < 1) + fun_l28_n310(x) + else + fun_l28_n387(x) + end +end + +def fun_l27_n156(x) + if (x < 1) + fun_l28_n1(x) + else + fun_l28_n131(x) + end +end + +def fun_l27_n157(x) + if (x < 1) + fun_l28_n232(x) + else + fun_l28_n503(x) + end +end + +def fun_l27_n158(x) + if (x < 1) + fun_l28_n48(x) + else + fun_l28_n68(x) + end +end + +def fun_l27_n159(x) + if (x < 1) + fun_l28_n98(x) + else + fun_l28_n82(x) + end +end + +def fun_l27_n160(x) + if (x < 1) + fun_l28_n175(x) + else + fun_l28_n466(x) + end +end + +def fun_l27_n161(x) + if (x < 1) + fun_l28_n105(x) + else + fun_l28_n159(x) + end +end + +def fun_l27_n162(x) + if (x < 1) + fun_l28_n336(x) + else + fun_l28_n314(x) + end +end + +def fun_l27_n163(x) + if (x < 1) + fun_l28_n458(x) + else + fun_l28_n901(x) + end +end + +def fun_l27_n164(x) + if (x < 1) + fun_l28_n621(x) + else + fun_l28_n876(x) + end +end + +def fun_l27_n165(x) + if (x < 1) + fun_l28_n830(x) + else + fun_l28_n468(x) + end +end + +def fun_l27_n166(x) + if (x < 1) + fun_l28_n606(x) + else + fun_l28_n253(x) + end +end + +def fun_l27_n167(x) + if (x < 1) + fun_l28_n905(x) + else + fun_l28_n582(x) + end +end + +def fun_l27_n168(x) + if (x < 1) + fun_l28_n882(x) + else + fun_l28_n280(x) + end +end + +def fun_l27_n169(x) + if (x < 1) + fun_l28_n824(x) + else + fun_l28_n672(x) + end +end + +def fun_l27_n170(x) + if (x < 1) + fun_l28_n455(x) + else + fun_l28_n621(x) + end +end + +def fun_l27_n171(x) + if (x < 1) + fun_l28_n594(x) + else + fun_l28_n143(x) + end +end + +def fun_l27_n172(x) + if (x < 1) + fun_l28_n414(x) + else + fun_l28_n371(x) + end +end + +def fun_l27_n173(x) + if (x < 1) + fun_l28_n2(x) + else + fun_l28_n883(x) + end +end + +def fun_l27_n174(x) + if (x < 1) + fun_l28_n710(x) + else + fun_l28_n322(x) + end +end + +def fun_l27_n175(x) + if (x < 1) + fun_l28_n271(x) + else + fun_l28_n110(x) + end +end + +def fun_l27_n176(x) + if (x < 1) + fun_l28_n100(x) + else + fun_l28_n870(x) + end +end + +def fun_l27_n177(x) + if (x < 1) + fun_l28_n446(x) + else + fun_l28_n742(x) + end +end + +def fun_l27_n178(x) + if (x < 1) + fun_l28_n175(x) + else + fun_l28_n170(x) + end +end + +def fun_l27_n179(x) + if (x < 1) + fun_l28_n724(x) + else + fun_l28_n364(x) + end +end + +def fun_l27_n180(x) + if (x < 1) + fun_l28_n167(x) + else + fun_l28_n826(x) + end +end + +def fun_l27_n181(x) + if (x < 1) + fun_l28_n65(x) + else + fun_l28_n375(x) + end +end + +def fun_l27_n182(x) + if (x < 1) + fun_l28_n709(x) + else + fun_l28_n62(x) + end +end + +def fun_l27_n183(x) + if (x < 1) + fun_l28_n584(x) + else + fun_l28_n611(x) + end +end + +def fun_l27_n184(x) + if (x < 1) + fun_l28_n442(x) + else + fun_l28_n174(x) + end +end + +def fun_l27_n185(x) + if (x < 1) + fun_l28_n684(x) + else + fun_l28_n768(x) + end +end + +def fun_l27_n186(x) + if (x < 1) + fun_l28_n424(x) + else + fun_l28_n207(x) + end +end + +def fun_l27_n187(x) + if (x < 1) + fun_l28_n670(x) + else + fun_l28_n970(x) + end +end + +def fun_l27_n188(x) + if (x < 1) + fun_l28_n470(x) + else + fun_l28_n774(x) + end +end + +def fun_l27_n189(x) + if (x < 1) + fun_l28_n58(x) + else + fun_l28_n578(x) + end +end + +def fun_l27_n190(x) + if (x < 1) + fun_l28_n697(x) + else + fun_l28_n310(x) + end +end + +def fun_l27_n191(x) + if (x < 1) + fun_l28_n493(x) + else + fun_l28_n56(x) + end +end + +def fun_l27_n192(x) + if (x < 1) + fun_l28_n12(x) + else + fun_l28_n471(x) + end +end + +def fun_l27_n193(x) + if (x < 1) + fun_l28_n306(x) + else + fun_l28_n10(x) + end +end + +def fun_l27_n194(x) + if (x < 1) + fun_l28_n87(x) + else + fun_l28_n59(x) + end +end + +def fun_l27_n195(x) + if (x < 1) + fun_l28_n207(x) + else + fun_l28_n555(x) + end +end + +def fun_l27_n196(x) + if (x < 1) + fun_l28_n563(x) + else + fun_l28_n256(x) + end +end + +def fun_l27_n197(x) + if (x < 1) + fun_l28_n14(x) + else + fun_l28_n895(x) + end +end + +def fun_l27_n198(x) + if (x < 1) + fun_l28_n986(x) + else + fun_l28_n287(x) + end +end + +def fun_l27_n199(x) + if (x < 1) + fun_l28_n810(x) + else + fun_l28_n66(x) + end +end + +def fun_l27_n200(x) + if (x < 1) + fun_l28_n457(x) + else + fun_l28_n186(x) + end +end + +def fun_l27_n201(x) + if (x < 1) + fun_l28_n580(x) + else + fun_l28_n248(x) + end +end + +def fun_l27_n202(x) + if (x < 1) + fun_l28_n9(x) + else + fun_l28_n66(x) + end +end + +def fun_l27_n203(x) + if (x < 1) + fun_l28_n659(x) + else + fun_l28_n403(x) + end +end + +def fun_l27_n204(x) + if (x < 1) + fun_l28_n66(x) + else + fun_l28_n524(x) + end +end + +def fun_l27_n205(x) + if (x < 1) + fun_l28_n754(x) + else + fun_l28_n46(x) + end +end + +def fun_l27_n206(x) + if (x < 1) + fun_l28_n32(x) + else + fun_l28_n655(x) + end +end + +def fun_l27_n207(x) + if (x < 1) + fun_l28_n559(x) + else + fun_l28_n619(x) + end +end + +def fun_l27_n208(x) + if (x < 1) + fun_l28_n251(x) + else + fun_l28_n410(x) + end +end + +def fun_l27_n209(x) + if (x < 1) + fun_l28_n339(x) + else + fun_l28_n726(x) + end +end + +def fun_l27_n210(x) + if (x < 1) + fun_l28_n104(x) + else + fun_l28_n733(x) + end +end + +def fun_l27_n211(x) + if (x < 1) + fun_l28_n500(x) + else + fun_l28_n654(x) + end +end + +def fun_l27_n212(x) + if (x < 1) + fun_l28_n244(x) + else + fun_l28_n471(x) + end +end + +def fun_l27_n213(x) + if (x < 1) + fun_l28_n692(x) + else + fun_l28_n56(x) + end +end + +def fun_l27_n214(x) + if (x < 1) + fun_l28_n54(x) + else + fun_l28_n753(x) + end +end + +def fun_l27_n215(x) + if (x < 1) + fun_l28_n770(x) + else + fun_l28_n756(x) + end +end + +def fun_l27_n216(x) + if (x < 1) + fun_l28_n771(x) + else + fun_l28_n407(x) + end +end + +def fun_l27_n217(x) + if (x < 1) + fun_l28_n728(x) + else + fun_l28_n361(x) + end +end + +def fun_l27_n218(x) + if (x < 1) + fun_l28_n983(x) + else + fun_l28_n440(x) + end +end + +def fun_l27_n219(x) + if (x < 1) + fun_l28_n105(x) + else + fun_l28_n906(x) + end +end + +def fun_l27_n220(x) + if (x < 1) + fun_l28_n694(x) + else + fun_l28_n792(x) + end +end + +def fun_l27_n221(x) + if (x < 1) + fun_l28_n325(x) + else + fun_l28_n98(x) + end +end + +def fun_l27_n222(x) + if (x < 1) + fun_l28_n354(x) + else + fun_l28_n683(x) + end +end + +def fun_l27_n223(x) + if (x < 1) + fun_l28_n236(x) + else + fun_l28_n999(x) + end +end + +def fun_l27_n224(x) + if (x < 1) + fun_l28_n671(x) + else + fun_l28_n621(x) + end +end + +def fun_l27_n225(x) + if (x < 1) + fun_l28_n113(x) + else + fun_l28_n532(x) + end +end + +def fun_l27_n226(x) + if (x < 1) + fun_l28_n43(x) + else + fun_l28_n449(x) + end +end + +def fun_l27_n227(x) + if (x < 1) + fun_l28_n402(x) + else + fun_l28_n298(x) + end +end + +def fun_l27_n228(x) + if (x < 1) + fun_l28_n858(x) + else + fun_l28_n626(x) + end +end + +def fun_l27_n229(x) + if (x < 1) + fun_l28_n596(x) + else + fun_l28_n21(x) + end +end + +def fun_l27_n230(x) + if (x < 1) + fun_l28_n713(x) + else + fun_l28_n755(x) + end +end + +def fun_l27_n231(x) + if (x < 1) + fun_l28_n59(x) + else + fun_l28_n695(x) + end +end + +def fun_l27_n232(x) + if (x < 1) + fun_l28_n715(x) + else + fun_l28_n614(x) + end +end + +def fun_l27_n233(x) + if (x < 1) + fun_l28_n124(x) + else + fun_l28_n877(x) + end +end + +def fun_l27_n234(x) + if (x < 1) + fun_l28_n563(x) + else + fun_l28_n273(x) + end +end + +def fun_l27_n235(x) + if (x < 1) + fun_l28_n331(x) + else + fun_l28_n866(x) + end +end + +def fun_l27_n236(x) + if (x < 1) + fun_l28_n950(x) + else + fun_l28_n765(x) + end +end + +def fun_l27_n237(x) + if (x < 1) + fun_l28_n550(x) + else + fun_l28_n133(x) + end +end + +def fun_l27_n238(x) + if (x < 1) + fun_l28_n0(x) + else + fun_l28_n749(x) + end +end + +def fun_l27_n239(x) + if (x < 1) + fun_l28_n578(x) + else + fun_l28_n692(x) + end +end + +def fun_l27_n240(x) + if (x < 1) + fun_l28_n111(x) + else + fun_l28_n301(x) + end +end + +def fun_l27_n241(x) + if (x < 1) + fun_l28_n191(x) + else + fun_l28_n272(x) + end +end + +def fun_l27_n242(x) + if (x < 1) + fun_l28_n547(x) + else + fun_l28_n425(x) + end +end + +def fun_l27_n243(x) + if (x < 1) + fun_l28_n173(x) + else + fun_l28_n101(x) + end +end + +def fun_l27_n244(x) + if (x < 1) + fun_l28_n511(x) + else + fun_l28_n758(x) + end +end + +def fun_l27_n245(x) + if (x < 1) + fun_l28_n272(x) + else + fun_l28_n497(x) + end +end + +def fun_l27_n246(x) + if (x < 1) + fun_l28_n59(x) + else + fun_l28_n348(x) + end +end + +def fun_l27_n247(x) + if (x < 1) + fun_l28_n583(x) + else + fun_l28_n730(x) + end +end + +def fun_l27_n248(x) + if (x < 1) + fun_l28_n635(x) + else + fun_l28_n714(x) + end +end + +def fun_l27_n249(x) + if (x < 1) + fun_l28_n815(x) + else + fun_l28_n844(x) + end +end + +def fun_l27_n250(x) + if (x < 1) + fun_l28_n694(x) + else + fun_l28_n869(x) + end +end + +def fun_l27_n251(x) + if (x < 1) + fun_l28_n681(x) + else + fun_l28_n894(x) + end +end + +def fun_l27_n252(x) + if (x < 1) + fun_l28_n756(x) + else + fun_l28_n657(x) + end +end + +def fun_l27_n253(x) + if (x < 1) + fun_l28_n392(x) + else + fun_l28_n706(x) + end +end + +def fun_l27_n254(x) + if (x < 1) + fun_l28_n267(x) + else + fun_l28_n238(x) + end +end + +def fun_l27_n255(x) + if (x < 1) + fun_l28_n914(x) + else + fun_l28_n574(x) + end +end + +def fun_l27_n256(x) + if (x < 1) + fun_l28_n872(x) + else + fun_l28_n269(x) + end +end + +def fun_l27_n257(x) + if (x < 1) + fun_l28_n454(x) + else + fun_l28_n485(x) + end +end + +def fun_l27_n258(x) + if (x < 1) + fun_l28_n994(x) + else + fun_l28_n83(x) + end +end + +def fun_l27_n259(x) + if (x < 1) + fun_l28_n41(x) + else + fun_l28_n495(x) + end +end + +def fun_l27_n260(x) + if (x < 1) + fun_l28_n75(x) + else + fun_l28_n508(x) + end +end + +def fun_l27_n261(x) + if (x < 1) + fun_l28_n684(x) + else + fun_l28_n524(x) + end +end + +def fun_l27_n262(x) + if (x < 1) + fun_l28_n78(x) + else + fun_l28_n563(x) + end +end + +def fun_l27_n263(x) + if (x < 1) + fun_l28_n227(x) + else + fun_l28_n359(x) + end +end + +def fun_l27_n264(x) + if (x < 1) + fun_l28_n679(x) + else + fun_l28_n711(x) + end +end + +def fun_l27_n265(x) + if (x < 1) + fun_l28_n0(x) + else + fun_l28_n720(x) + end +end + +def fun_l27_n266(x) + if (x < 1) + fun_l28_n384(x) + else + fun_l28_n915(x) + end +end + +def fun_l27_n267(x) + if (x < 1) + fun_l28_n912(x) + else + fun_l28_n24(x) + end +end + +def fun_l27_n268(x) + if (x < 1) + fun_l28_n337(x) + else + fun_l28_n880(x) + end +end + +def fun_l27_n269(x) + if (x < 1) + fun_l28_n84(x) + else + fun_l28_n387(x) + end +end + +def fun_l27_n270(x) + if (x < 1) + fun_l28_n155(x) + else + fun_l28_n705(x) + end +end + +def fun_l27_n271(x) + if (x < 1) + fun_l28_n159(x) + else + fun_l28_n815(x) + end +end + +def fun_l27_n272(x) + if (x < 1) + fun_l28_n182(x) + else + fun_l28_n210(x) + end +end + +def fun_l27_n273(x) + if (x < 1) + fun_l28_n446(x) + else + fun_l28_n524(x) + end +end + +def fun_l27_n274(x) + if (x < 1) + fun_l28_n828(x) + else + fun_l28_n14(x) + end +end + +def fun_l27_n275(x) + if (x < 1) + fun_l28_n176(x) + else + fun_l28_n857(x) + end +end + +def fun_l27_n276(x) + if (x < 1) + fun_l28_n39(x) + else + fun_l28_n973(x) + end +end + +def fun_l27_n277(x) + if (x < 1) + fun_l28_n310(x) + else + fun_l28_n900(x) + end +end + +def fun_l27_n278(x) + if (x < 1) + fun_l28_n729(x) + else + fun_l28_n544(x) + end +end + +def fun_l27_n279(x) + if (x < 1) + fun_l28_n111(x) + else + fun_l28_n939(x) + end +end + +def fun_l27_n280(x) + if (x < 1) + fun_l28_n102(x) + else + fun_l28_n658(x) + end +end + +def fun_l27_n281(x) + if (x < 1) + fun_l28_n186(x) + else + fun_l28_n939(x) + end +end + +def fun_l27_n282(x) + if (x < 1) + fun_l28_n276(x) + else + fun_l28_n428(x) + end +end + +def fun_l27_n283(x) + if (x < 1) + fun_l28_n137(x) + else + fun_l28_n876(x) + end +end + +def fun_l27_n284(x) + if (x < 1) + fun_l28_n31(x) + else + fun_l28_n351(x) + end +end + +def fun_l27_n285(x) + if (x < 1) + fun_l28_n143(x) + else + fun_l28_n192(x) + end +end + +def fun_l27_n286(x) + if (x < 1) + fun_l28_n63(x) + else + fun_l28_n764(x) + end +end + +def fun_l27_n287(x) + if (x < 1) + fun_l28_n361(x) + else + fun_l28_n512(x) + end +end + +def fun_l27_n288(x) + if (x < 1) + fun_l28_n817(x) + else + fun_l28_n997(x) + end +end + +def fun_l27_n289(x) + if (x < 1) + fun_l28_n837(x) + else + fun_l28_n834(x) + end +end + +def fun_l27_n290(x) + if (x < 1) + fun_l28_n436(x) + else + fun_l28_n873(x) + end +end + +def fun_l27_n291(x) + if (x < 1) + fun_l28_n412(x) + else + fun_l28_n494(x) + end +end + +def fun_l27_n292(x) + if (x < 1) + fun_l28_n794(x) + else + fun_l28_n972(x) + end +end + +def fun_l27_n293(x) + if (x < 1) + fun_l28_n486(x) + else + fun_l28_n401(x) + end +end + +def fun_l27_n294(x) + if (x < 1) + fun_l28_n171(x) + else + fun_l28_n334(x) + end +end + +def fun_l27_n295(x) + if (x < 1) + fun_l28_n681(x) + else + fun_l28_n753(x) + end +end + +def fun_l27_n296(x) + if (x < 1) + fun_l28_n541(x) + else + fun_l28_n855(x) + end +end + +def fun_l27_n297(x) + if (x < 1) + fun_l28_n270(x) + else + fun_l28_n257(x) + end +end + +def fun_l27_n298(x) + if (x < 1) + fun_l28_n923(x) + else + fun_l28_n997(x) + end +end + +def fun_l27_n299(x) + if (x < 1) + fun_l28_n508(x) + else + fun_l28_n649(x) + end +end + +def fun_l27_n300(x) + if (x < 1) + fun_l28_n351(x) + else + fun_l28_n966(x) + end +end + +def fun_l27_n301(x) + if (x < 1) + fun_l28_n622(x) + else + fun_l28_n436(x) + end +end + +def fun_l27_n302(x) + if (x < 1) + fun_l28_n723(x) + else + fun_l28_n261(x) + end +end + +def fun_l27_n303(x) + if (x < 1) + fun_l28_n269(x) + else + fun_l28_n483(x) + end +end + +def fun_l27_n304(x) + if (x < 1) + fun_l28_n449(x) + else + fun_l28_n5(x) + end +end + +def fun_l27_n305(x) + if (x < 1) + fun_l28_n967(x) + else + fun_l28_n967(x) + end +end + +def fun_l27_n306(x) + if (x < 1) + fun_l28_n866(x) + else + fun_l28_n590(x) + end +end + +def fun_l27_n307(x) + if (x < 1) + fun_l28_n145(x) + else + fun_l28_n75(x) + end +end + +def fun_l27_n308(x) + if (x < 1) + fun_l28_n329(x) + else + fun_l28_n834(x) + end +end + +def fun_l27_n309(x) + if (x < 1) + fun_l28_n668(x) + else + fun_l28_n909(x) + end +end + +def fun_l27_n310(x) + if (x < 1) + fun_l28_n70(x) + else + fun_l28_n311(x) + end +end + +def fun_l27_n311(x) + if (x < 1) + fun_l28_n669(x) + else + fun_l28_n90(x) + end +end + +def fun_l27_n312(x) + if (x < 1) + fun_l28_n805(x) + else + fun_l28_n558(x) + end +end + +def fun_l27_n313(x) + if (x < 1) + fun_l28_n493(x) + else + fun_l28_n642(x) + end +end + +def fun_l27_n314(x) + if (x < 1) + fun_l28_n285(x) + else + fun_l28_n968(x) + end +end + +def fun_l27_n315(x) + if (x < 1) + fun_l28_n806(x) + else + fun_l28_n731(x) + end +end + +def fun_l27_n316(x) + if (x < 1) + fun_l28_n284(x) + else + fun_l28_n441(x) + end +end + +def fun_l27_n317(x) + if (x < 1) + fun_l28_n644(x) + else + fun_l28_n16(x) + end +end + +def fun_l27_n318(x) + if (x < 1) + fun_l28_n411(x) + else + fun_l28_n739(x) + end +end + +def fun_l27_n319(x) + if (x < 1) + fun_l28_n462(x) + else + fun_l28_n680(x) + end +end + +def fun_l27_n320(x) + if (x < 1) + fun_l28_n126(x) + else + fun_l28_n558(x) + end +end + +def fun_l27_n321(x) + if (x < 1) + fun_l28_n869(x) + else + fun_l28_n581(x) + end +end + +def fun_l27_n322(x) + if (x < 1) + fun_l28_n25(x) + else + fun_l28_n352(x) + end +end + +def fun_l27_n323(x) + if (x < 1) + fun_l28_n203(x) + else + fun_l28_n776(x) + end +end + +def fun_l27_n324(x) + if (x < 1) + fun_l28_n6(x) + else + fun_l28_n833(x) + end +end + +def fun_l27_n325(x) + if (x < 1) + fun_l28_n817(x) + else + fun_l28_n258(x) + end +end + +def fun_l27_n326(x) + if (x < 1) + fun_l28_n607(x) + else + fun_l28_n813(x) + end +end + +def fun_l27_n327(x) + if (x < 1) + fun_l28_n761(x) + else + fun_l28_n893(x) + end +end + +def fun_l27_n328(x) + if (x < 1) + fun_l28_n861(x) + else + fun_l28_n879(x) + end +end + +def fun_l27_n329(x) + if (x < 1) + fun_l28_n682(x) + else + fun_l28_n680(x) + end +end + +def fun_l27_n330(x) + if (x < 1) + fun_l28_n61(x) + else + fun_l28_n481(x) + end +end + +def fun_l27_n331(x) + if (x < 1) + fun_l28_n738(x) + else + fun_l28_n230(x) + end +end + +def fun_l27_n332(x) + if (x < 1) + fun_l28_n45(x) + else + fun_l28_n279(x) + end +end + +def fun_l27_n333(x) + if (x < 1) + fun_l28_n24(x) + else + fun_l28_n561(x) + end +end + +def fun_l27_n334(x) + if (x < 1) + fun_l28_n459(x) + else + fun_l28_n594(x) + end +end + +def fun_l27_n335(x) + if (x < 1) + fun_l28_n695(x) + else + fun_l28_n513(x) + end +end + +def fun_l27_n336(x) + if (x < 1) + fun_l28_n729(x) + else + fun_l28_n89(x) + end +end + +def fun_l27_n337(x) + if (x < 1) + fun_l28_n509(x) + else + fun_l28_n574(x) + end +end + +def fun_l27_n338(x) + if (x < 1) + fun_l28_n80(x) + else + fun_l28_n448(x) + end +end + +def fun_l27_n339(x) + if (x < 1) + fun_l28_n279(x) + else + fun_l28_n177(x) + end +end + +def fun_l27_n340(x) + if (x < 1) + fun_l28_n508(x) + else + fun_l28_n706(x) + end +end + +def fun_l27_n341(x) + if (x < 1) + fun_l28_n790(x) + else + fun_l28_n774(x) + end +end + +def fun_l27_n342(x) + if (x < 1) + fun_l28_n606(x) + else + fun_l28_n642(x) + end +end + +def fun_l27_n343(x) + if (x < 1) + fun_l28_n108(x) + else + fun_l28_n539(x) + end +end + +def fun_l27_n344(x) + if (x < 1) + fun_l28_n418(x) + else + fun_l28_n687(x) + end +end + +def fun_l27_n345(x) + if (x < 1) + fun_l28_n386(x) + else + fun_l28_n170(x) + end +end + +def fun_l27_n346(x) + if (x < 1) + fun_l28_n648(x) + else + fun_l28_n340(x) + end +end + +def fun_l27_n347(x) + if (x < 1) + fun_l28_n516(x) + else + fun_l28_n586(x) + end +end + +def fun_l27_n348(x) + if (x < 1) + fun_l28_n646(x) + else + fun_l28_n448(x) + end +end + +def fun_l27_n349(x) + if (x < 1) + fun_l28_n378(x) + else + fun_l28_n413(x) + end +end + +def fun_l27_n350(x) + if (x < 1) + fun_l28_n885(x) + else + fun_l28_n932(x) + end +end + +def fun_l27_n351(x) + if (x < 1) + fun_l28_n9(x) + else + fun_l28_n843(x) + end +end + +def fun_l27_n352(x) + if (x < 1) + fun_l28_n502(x) + else + fun_l28_n229(x) + end +end + +def fun_l27_n353(x) + if (x < 1) + fun_l28_n752(x) + else + fun_l28_n677(x) + end +end + +def fun_l27_n354(x) + if (x < 1) + fun_l28_n246(x) + else + fun_l28_n32(x) + end +end + +def fun_l27_n355(x) + if (x < 1) + fun_l28_n969(x) + else + fun_l28_n933(x) + end +end + +def fun_l27_n356(x) + if (x < 1) + fun_l28_n44(x) + else + fun_l28_n704(x) + end +end + +def fun_l27_n357(x) + if (x < 1) + fun_l28_n863(x) + else + fun_l28_n324(x) + end +end + +def fun_l27_n358(x) + if (x < 1) + fun_l28_n467(x) + else + fun_l28_n418(x) + end +end + +def fun_l27_n359(x) + if (x < 1) + fun_l28_n222(x) + else + fun_l28_n138(x) + end +end + +def fun_l27_n360(x) + if (x < 1) + fun_l28_n261(x) + else + fun_l28_n605(x) + end +end + +def fun_l27_n361(x) + if (x < 1) + fun_l28_n470(x) + else + fun_l28_n519(x) + end +end + +def fun_l27_n362(x) + if (x < 1) + fun_l28_n717(x) + else + fun_l28_n817(x) + end +end + +def fun_l27_n363(x) + if (x < 1) + fun_l28_n591(x) + else + fun_l28_n537(x) + end +end + +def fun_l27_n364(x) + if (x < 1) + fun_l28_n733(x) + else + fun_l28_n222(x) + end +end + +def fun_l27_n365(x) + if (x < 1) + fun_l28_n137(x) + else + fun_l28_n225(x) + end +end + +def fun_l27_n366(x) + if (x < 1) + fun_l28_n610(x) + else + fun_l28_n870(x) + end +end + +def fun_l27_n367(x) + if (x < 1) + fun_l28_n697(x) + else + fun_l28_n866(x) + end +end + +def fun_l27_n368(x) + if (x < 1) + fun_l28_n902(x) + else + fun_l28_n827(x) + end +end + +def fun_l27_n369(x) + if (x < 1) + fun_l28_n769(x) + else + fun_l28_n238(x) + end +end + +def fun_l27_n370(x) + if (x < 1) + fun_l28_n66(x) + else + fun_l28_n958(x) + end +end + +def fun_l27_n371(x) + if (x < 1) + fun_l28_n847(x) + else + fun_l28_n177(x) + end +end + +def fun_l27_n372(x) + if (x < 1) + fun_l28_n64(x) + else + fun_l28_n198(x) + end +end + +def fun_l27_n373(x) + if (x < 1) + fun_l28_n36(x) + else + fun_l28_n282(x) + end +end + +def fun_l27_n374(x) + if (x < 1) + fun_l28_n647(x) + else + fun_l28_n228(x) + end +end + +def fun_l27_n375(x) + if (x < 1) + fun_l28_n737(x) + else + fun_l28_n689(x) + end +end + +def fun_l27_n376(x) + if (x < 1) + fun_l28_n336(x) + else + fun_l28_n20(x) + end +end + +def fun_l27_n377(x) + if (x < 1) + fun_l28_n859(x) + else + fun_l28_n661(x) + end +end + +def fun_l27_n378(x) + if (x < 1) + fun_l28_n148(x) + else + fun_l28_n197(x) + end +end + +def fun_l27_n379(x) + if (x < 1) + fun_l28_n986(x) + else + fun_l28_n441(x) + end +end + +def fun_l27_n380(x) + if (x < 1) + fun_l28_n966(x) + else + fun_l28_n994(x) + end +end + +def fun_l27_n381(x) + if (x < 1) + fun_l28_n546(x) + else + fun_l28_n687(x) + end +end + +def fun_l27_n382(x) + if (x < 1) + fun_l28_n63(x) + else + fun_l28_n366(x) + end +end + +def fun_l27_n383(x) + if (x < 1) + fun_l28_n146(x) + else + fun_l28_n96(x) + end +end + +def fun_l27_n384(x) + if (x < 1) + fun_l28_n747(x) + else + fun_l28_n168(x) + end +end + +def fun_l27_n385(x) + if (x < 1) + fun_l28_n556(x) + else + fun_l28_n194(x) + end +end + +def fun_l27_n386(x) + if (x < 1) + fun_l28_n180(x) + else + fun_l28_n648(x) + end +end + +def fun_l27_n387(x) + if (x < 1) + fun_l28_n898(x) + else + fun_l28_n499(x) + end +end + +def fun_l27_n388(x) + if (x < 1) + fun_l28_n720(x) + else + fun_l28_n996(x) + end +end + +def fun_l27_n389(x) + if (x < 1) + fun_l28_n743(x) + else + fun_l28_n781(x) + end +end + +def fun_l27_n390(x) + if (x < 1) + fun_l28_n372(x) + else + fun_l28_n907(x) + end +end + +def fun_l27_n391(x) + if (x < 1) + fun_l28_n893(x) + else + fun_l28_n911(x) + end +end + +def fun_l27_n392(x) + if (x < 1) + fun_l28_n304(x) + else + fun_l28_n164(x) + end +end + +def fun_l27_n393(x) + if (x < 1) + fun_l28_n212(x) + else + fun_l28_n575(x) + end +end + +def fun_l27_n394(x) + if (x < 1) + fun_l28_n279(x) + else + fun_l28_n306(x) + end +end + +def fun_l27_n395(x) + if (x < 1) + fun_l28_n662(x) + else + fun_l28_n838(x) + end +end + +def fun_l27_n396(x) + if (x < 1) + fun_l28_n882(x) + else + fun_l28_n321(x) + end +end + +def fun_l27_n397(x) + if (x < 1) + fun_l28_n996(x) + else + fun_l28_n170(x) + end +end + +def fun_l27_n398(x) + if (x < 1) + fun_l28_n309(x) + else + fun_l28_n805(x) + end +end + +def fun_l27_n399(x) + if (x < 1) + fun_l28_n584(x) + else + fun_l28_n304(x) + end +end + +def fun_l27_n400(x) + if (x < 1) + fun_l28_n575(x) + else + fun_l28_n405(x) + end +end + +def fun_l27_n401(x) + if (x < 1) + fun_l28_n507(x) + else + fun_l28_n773(x) + end +end + +def fun_l27_n402(x) + if (x < 1) + fun_l28_n759(x) + else + fun_l28_n583(x) + end +end + +def fun_l27_n403(x) + if (x < 1) + fun_l28_n689(x) + else + fun_l28_n511(x) + end +end + +def fun_l27_n404(x) + if (x < 1) + fun_l28_n706(x) + else + fun_l28_n258(x) + end +end + +def fun_l27_n405(x) + if (x < 1) + fun_l28_n736(x) + else + fun_l28_n482(x) + end +end + +def fun_l27_n406(x) + if (x < 1) + fun_l28_n851(x) + else + fun_l28_n898(x) + end +end + +def fun_l27_n407(x) + if (x < 1) + fun_l28_n86(x) + else + fun_l28_n913(x) + end +end + +def fun_l27_n408(x) + if (x < 1) + fun_l28_n277(x) + else + fun_l28_n960(x) + end +end + +def fun_l27_n409(x) + if (x < 1) + fun_l28_n137(x) + else + fun_l28_n789(x) + end +end + +def fun_l27_n410(x) + if (x < 1) + fun_l28_n23(x) + else + fun_l28_n633(x) + end +end + +def fun_l27_n411(x) + if (x < 1) + fun_l28_n246(x) + else + fun_l28_n560(x) + end +end + +def fun_l27_n412(x) + if (x < 1) + fun_l28_n218(x) + else + fun_l28_n66(x) + end +end + +def fun_l27_n413(x) + if (x < 1) + fun_l28_n680(x) + else + fun_l28_n9(x) + end +end + +def fun_l27_n414(x) + if (x < 1) + fun_l28_n693(x) + else + fun_l28_n625(x) + end +end + +def fun_l27_n415(x) + if (x < 1) + fun_l28_n560(x) + else + fun_l28_n739(x) + end +end + +def fun_l27_n416(x) + if (x < 1) + fun_l28_n467(x) + else + fun_l28_n542(x) + end +end + +def fun_l27_n417(x) + if (x < 1) + fun_l28_n364(x) + else + fun_l28_n468(x) + end +end + +def fun_l27_n418(x) + if (x < 1) + fun_l28_n123(x) + else + fun_l28_n775(x) + end +end + +def fun_l27_n419(x) + if (x < 1) + fun_l28_n17(x) + else + fun_l28_n875(x) + end +end + +def fun_l27_n420(x) + if (x < 1) + fun_l28_n596(x) + else + fun_l28_n163(x) + end +end + +def fun_l27_n421(x) + if (x < 1) + fun_l28_n638(x) + else + fun_l28_n426(x) + end +end + +def fun_l27_n422(x) + if (x < 1) + fun_l28_n637(x) + else + fun_l28_n696(x) + end +end + +def fun_l27_n423(x) + if (x < 1) + fun_l28_n299(x) + else + fun_l28_n218(x) + end +end + +def fun_l27_n424(x) + if (x < 1) + fun_l28_n683(x) + else + fun_l28_n248(x) + end +end + +def fun_l27_n425(x) + if (x < 1) + fun_l28_n272(x) + else + fun_l28_n359(x) + end +end + +def fun_l27_n426(x) + if (x < 1) + fun_l28_n327(x) + else + fun_l28_n984(x) + end +end + +def fun_l27_n427(x) + if (x < 1) + fun_l28_n912(x) + else + fun_l28_n393(x) + end +end + +def fun_l27_n428(x) + if (x < 1) + fun_l28_n842(x) + else + fun_l28_n919(x) + end +end + +def fun_l27_n429(x) + if (x < 1) + fun_l28_n721(x) + else + fun_l28_n36(x) + end +end + +def fun_l27_n430(x) + if (x < 1) + fun_l28_n16(x) + else + fun_l28_n418(x) + end +end + +def fun_l27_n431(x) + if (x < 1) + fun_l28_n747(x) + else + fun_l28_n132(x) + end +end + +def fun_l27_n432(x) + if (x < 1) + fun_l28_n906(x) + else + fun_l28_n718(x) + end +end + +def fun_l27_n433(x) + if (x < 1) + fun_l28_n508(x) + else + fun_l28_n862(x) + end +end + +def fun_l27_n434(x) + if (x < 1) + fun_l28_n478(x) + else + fun_l28_n542(x) + end +end + +def fun_l27_n435(x) + if (x < 1) + fun_l28_n186(x) + else + fun_l28_n976(x) + end +end + +def fun_l27_n436(x) + if (x < 1) + fun_l28_n637(x) + else + fun_l28_n49(x) + end +end + +def fun_l27_n437(x) + if (x < 1) + fun_l28_n242(x) + else + fun_l28_n774(x) + end +end + +def fun_l27_n438(x) + if (x < 1) + fun_l28_n303(x) + else + fun_l28_n175(x) + end +end + +def fun_l27_n439(x) + if (x < 1) + fun_l28_n851(x) + else + fun_l28_n908(x) + end +end + +def fun_l27_n440(x) + if (x < 1) + fun_l28_n139(x) + else + fun_l28_n473(x) + end +end + +def fun_l27_n441(x) + if (x < 1) + fun_l28_n70(x) + else + fun_l28_n406(x) + end +end + +def fun_l27_n442(x) + if (x < 1) + fun_l28_n368(x) + else + fun_l28_n624(x) + end +end + +def fun_l27_n443(x) + if (x < 1) + fun_l28_n900(x) + else + fun_l28_n173(x) + end +end + +def fun_l27_n444(x) + if (x < 1) + fun_l28_n646(x) + else + fun_l28_n733(x) + end +end + +def fun_l27_n445(x) + if (x < 1) + fun_l28_n859(x) + else + fun_l28_n100(x) + end +end + +def fun_l27_n446(x) + if (x < 1) + fun_l28_n418(x) + else + fun_l28_n765(x) + end +end + +def fun_l27_n447(x) + if (x < 1) + fun_l28_n204(x) + else + fun_l28_n541(x) + end +end + +def fun_l27_n448(x) + if (x < 1) + fun_l28_n192(x) + else + fun_l28_n414(x) + end +end + +def fun_l27_n449(x) + if (x < 1) + fun_l28_n904(x) + else + fun_l28_n247(x) + end +end + +def fun_l27_n450(x) + if (x < 1) + fun_l28_n528(x) + else + fun_l28_n24(x) + end +end + +def fun_l27_n451(x) + if (x < 1) + fun_l28_n312(x) + else + fun_l28_n48(x) + end +end + +def fun_l27_n452(x) + if (x < 1) + fun_l28_n169(x) + else + fun_l28_n37(x) + end +end + +def fun_l27_n453(x) + if (x < 1) + fun_l28_n713(x) + else + fun_l28_n168(x) + end +end + +def fun_l27_n454(x) + if (x < 1) + fun_l28_n748(x) + else + fun_l28_n213(x) + end +end + +def fun_l27_n455(x) + if (x < 1) + fun_l28_n157(x) + else + fun_l28_n444(x) + end +end + +def fun_l27_n456(x) + if (x < 1) + fun_l28_n32(x) + else + fun_l28_n475(x) + end +end + +def fun_l27_n457(x) + if (x < 1) + fun_l28_n252(x) + else + fun_l28_n730(x) + end +end + +def fun_l27_n458(x) + if (x < 1) + fun_l28_n261(x) + else + fun_l28_n576(x) + end +end + +def fun_l27_n459(x) + if (x < 1) + fun_l28_n859(x) + else + fun_l28_n401(x) + end +end + +def fun_l27_n460(x) + if (x < 1) + fun_l28_n394(x) + else + fun_l28_n10(x) + end +end + +def fun_l27_n461(x) + if (x < 1) + fun_l28_n89(x) + else + fun_l28_n402(x) + end +end + +def fun_l27_n462(x) + if (x < 1) + fun_l28_n100(x) + else + fun_l28_n207(x) + end +end + +def fun_l27_n463(x) + if (x < 1) + fun_l28_n907(x) + else + fun_l28_n354(x) + end +end + +def fun_l27_n464(x) + if (x < 1) + fun_l28_n612(x) + else + fun_l28_n31(x) + end +end + +def fun_l27_n465(x) + if (x < 1) + fun_l28_n622(x) + else + fun_l28_n342(x) + end +end + +def fun_l27_n466(x) + if (x < 1) + fun_l28_n373(x) + else + fun_l28_n831(x) + end +end + +def fun_l27_n467(x) + if (x < 1) + fun_l28_n858(x) + else + fun_l28_n233(x) + end +end + +def fun_l27_n468(x) + if (x < 1) + fun_l28_n104(x) + else + fun_l28_n918(x) + end +end + +def fun_l27_n469(x) + if (x < 1) + fun_l28_n778(x) + else + fun_l28_n758(x) + end +end + +def fun_l27_n470(x) + if (x < 1) + fun_l28_n695(x) + else + fun_l28_n217(x) + end +end + +def fun_l27_n471(x) + if (x < 1) + fun_l28_n781(x) + else + fun_l28_n584(x) + end +end + +def fun_l27_n472(x) + if (x < 1) + fun_l28_n883(x) + else + fun_l28_n152(x) + end +end + +def fun_l27_n473(x) + if (x < 1) + fun_l28_n525(x) + else + fun_l28_n369(x) + end +end + +def fun_l27_n474(x) + if (x < 1) + fun_l28_n42(x) + else + fun_l28_n299(x) + end +end + +def fun_l27_n475(x) + if (x < 1) + fun_l28_n174(x) + else + fun_l28_n664(x) + end +end + +def fun_l27_n476(x) + if (x < 1) + fun_l28_n489(x) + else + fun_l28_n296(x) + end +end + +def fun_l27_n477(x) + if (x < 1) + fun_l28_n725(x) + else + fun_l28_n384(x) + end +end + +def fun_l27_n478(x) + if (x < 1) + fun_l28_n138(x) + else + fun_l28_n812(x) + end +end + +def fun_l27_n479(x) + if (x < 1) + fun_l28_n161(x) + else + fun_l28_n786(x) + end +end + +def fun_l27_n480(x) + if (x < 1) + fun_l28_n751(x) + else + fun_l28_n91(x) + end +end + +def fun_l27_n481(x) + if (x < 1) + fun_l28_n434(x) + else + fun_l28_n507(x) + end +end + +def fun_l27_n482(x) + if (x < 1) + fun_l28_n101(x) + else + fun_l28_n809(x) + end +end + +def fun_l27_n483(x) + if (x < 1) + fun_l28_n79(x) + else + fun_l28_n565(x) + end +end + +def fun_l27_n484(x) + if (x < 1) + fun_l28_n681(x) + else + fun_l28_n390(x) + end +end + +def fun_l27_n485(x) + if (x < 1) + fun_l28_n950(x) + else + fun_l28_n262(x) + end +end + +def fun_l27_n486(x) + if (x < 1) + fun_l28_n188(x) + else + fun_l28_n731(x) + end +end + +def fun_l27_n487(x) + if (x < 1) + fun_l28_n724(x) + else + fun_l28_n806(x) + end +end + +def fun_l27_n488(x) + if (x < 1) + fun_l28_n680(x) + else + fun_l28_n475(x) + end +end + +def fun_l27_n489(x) + if (x < 1) + fun_l28_n662(x) + else + fun_l28_n242(x) + end +end + +def fun_l27_n490(x) + if (x < 1) + fun_l28_n578(x) + else + fun_l28_n534(x) + end +end + +def fun_l27_n491(x) + if (x < 1) + fun_l28_n173(x) + else + fun_l28_n239(x) + end +end + +def fun_l27_n492(x) + if (x < 1) + fun_l28_n724(x) + else + fun_l28_n579(x) + end +end + +def fun_l27_n493(x) + if (x < 1) + fun_l28_n449(x) + else + fun_l28_n44(x) + end +end + +def fun_l27_n494(x) + if (x < 1) + fun_l28_n180(x) + else + fun_l28_n836(x) + end +end + +def fun_l27_n495(x) + if (x < 1) + fun_l28_n232(x) + else + fun_l28_n371(x) + end +end + +def fun_l27_n496(x) + if (x < 1) + fun_l28_n558(x) + else + fun_l28_n904(x) + end +end + +def fun_l27_n497(x) + if (x < 1) + fun_l28_n324(x) + else + fun_l28_n85(x) + end +end + +def fun_l27_n498(x) + if (x < 1) + fun_l28_n272(x) + else + fun_l28_n469(x) + end +end + +def fun_l27_n499(x) + if (x < 1) + fun_l28_n232(x) + else + fun_l28_n899(x) + end +end + +def fun_l27_n500(x) + if (x < 1) + fun_l28_n654(x) + else + fun_l28_n390(x) + end +end + +def fun_l27_n501(x) + if (x < 1) + fun_l28_n84(x) + else + fun_l28_n74(x) + end +end + +def fun_l27_n502(x) + if (x < 1) + fun_l28_n799(x) + else + fun_l28_n224(x) + end +end + +def fun_l27_n503(x) + if (x < 1) + fun_l28_n635(x) + else + fun_l28_n770(x) + end +end + +def fun_l27_n504(x) + if (x < 1) + fun_l28_n734(x) + else + fun_l28_n451(x) + end +end + +def fun_l27_n505(x) + if (x < 1) + fun_l28_n340(x) + else + fun_l28_n318(x) + end +end + +def fun_l27_n506(x) + if (x < 1) + fun_l28_n521(x) + else + fun_l28_n590(x) + end +end + +def fun_l27_n507(x) + if (x < 1) + fun_l28_n727(x) + else + fun_l28_n825(x) + end +end + +def fun_l27_n508(x) + if (x < 1) + fun_l28_n923(x) + else + fun_l28_n413(x) + end +end + +def fun_l27_n509(x) + if (x < 1) + fun_l28_n825(x) + else + fun_l28_n235(x) + end +end + +def fun_l27_n510(x) + if (x < 1) + fun_l28_n212(x) + else + fun_l28_n509(x) + end +end + +def fun_l27_n511(x) + if (x < 1) + fun_l28_n6(x) + else + fun_l28_n16(x) + end +end + +def fun_l27_n512(x) + if (x < 1) + fun_l28_n409(x) + else + fun_l28_n473(x) + end +end + +def fun_l27_n513(x) + if (x < 1) + fun_l28_n220(x) + else + fun_l28_n383(x) + end +end + +def fun_l27_n514(x) + if (x < 1) + fun_l28_n338(x) + else + fun_l28_n32(x) + end +end + +def fun_l27_n515(x) + if (x < 1) + fun_l28_n218(x) + else + fun_l28_n307(x) + end +end + +def fun_l27_n516(x) + if (x < 1) + fun_l28_n591(x) + else + fun_l28_n545(x) + end +end + +def fun_l27_n517(x) + if (x < 1) + fun_l28_n405(x) + else + fun_l28_n241(x) + end +end + +def fun_l27_n518(x) + if (x < 1) + fun_l28_n545(x) + else + fun_l28_n215(x) + end +end + +def fun_l27_n519(x) + if (x < 1) + fun_l28_n989(x) + else + fun_l28_n480(x) + end +end + +def fun_l27_n520(x) + if (x < 1) + fun_l28_n479(x) + else + fun_l28_n869(x) + end +end + +def fun_l27_n521(x) + if (x < 1) + fun_l28_n376(x) + else + fun_l28_n216(x) + end +end + +def fun_l27_n522(x) + if (x < 1) + fun_l28_n74(x) + else + fun_l28_n370(x) + end +end + +def fun_l27_n523(x) + if (x < 1) + fun_l28_n665(x) + else + fun_l28_n982(x) + end +end + +def fun_l27_n524(x) + if (x < 1) + fun_l28_n412(x) + else + fun_l28_n515(x) + end +end + +def fun_l27_n525(x) + if (x < 1) + fun_l28_n421(x) + else + fun_l28_n718(x) + end +end + +def fun_l27_n526(x) + if (x < 1) + fun_l28_n914(x) + else + fun_l28_n297(x) + end +end + +def fun_l27_n527(x) + if (x < 1) + fun_l28_n134(x) + else + fun_l28_n602(x) + end +end + +def fun_l27_n528(x) + if (x < 1) + fun_l28_n0(x) + else + fun_l28_n23(x) + end +end + +def fun_l27_n529(x) + if (x < 1) + fun_l28_n610(x) + else + fun_l28_n736(x) + end +end + +def fun_l27_n530(x) + if (x < 1) + fun_l28_n350(x) + else + fun_l28_n51(x) + end +end + +def fun_l27_n531(x) + if (x < 1) + fun_l28_n648(x) + else + fun_l28_n382(x) + end +end + +def fun_l27_n532(x) + if (x < 1) + fun_l28_n432(x) + else + fun_l28_n872(x) + end +end + +def fun_l27_n533(x) + if (x < 1) + fun_l28_n747(x) + else + fun_l28_n588(x) + end +end + +def fun_l27_n534(x) + if (x < 1) + fun_l28_n763(x) + else + fun_l28_n846(x) + end +end + +def fun_l27_n535(x) + if (x < 1) + fun_l28_n300(x) + else + fun_l28_n26(x) + end +end + +def fun_l27_n536(x) + if (x < 1) + fun_l28_n851(x) + else + fun_l28_n907(x) + end +end + +def fun_l27_n537(x) + if (x < 1) + fun_l28_n759(x) + else + fun_l28_n927(x) + end +end + +def fun_l27_n538(x) + if (x < 1) + fun_l28_n188(x) + else + fun_l28_n199(x) + end +end + +def fun_l27_n539(x) + if (x < 1) + fun_l28_n496(x) + else + fun_l28_n664(x) + end +end + +def fun_l27_n540(x) + if (x < 1) + fun_l28_n595(x) + else + fun_l28_n651(x) + end +end + +def fun_l27_n541(x) + if (x < 1) + fun_l28_n678(x) + else + fun_l28_n172(x) + end +end + +def fun_l27_n542(x) + if (x < 1) + fun_l28_n37(x) + else + fun_l28_n255(x) + end +end + +def fun_l27_n543(x) + if (x < 1) + fun_l28_n58(x) + else + fun_l28_n367(x) + end +end + +def fun_l27_n544(x) + if (x < 1) + fun_l28_n275(x) + else + fun_l28_n925(x) + end +end + +def fun_l27_n545(x) + if (x < 1) + fun_l28_n469(x) + else + fun_l28_n774(x) + end +end + +def fun_l27_n546(x) + if (x < 1) + fun_l28_n508(x) + else + fun_l28_n267(x) + end +end + +def fun_l27_n547(x) + if (x < 1) + fun_l28_n288(x) + else + fun_l28_n64(x) + end +end + +def fun_l27_n548(x) + if (x < 1) + fun_l28_n941(x) + else + fun_l28_n632(x) + end +end + +def fun_l27_n549(x) + if (x < 1) + fun_l28_n816(x) + else + fun_l28_n551(x) + end +end + +def fun_l27_n550(x) + if (x < 1) + fun_l28_n848(x) + else + fun_l28_n778(x) + end +end + +def fun_l27_n551(x) + if (x < 1) + fun_l28_n273(x) + else + fun_l28_n846(x) + end +end + +def fun_l27_n552(x) + if (x < 1) + fun_l28_n18(x) + else + fun_l28_n530(x) + end +end + +def fun_l27_n553(x) + if (x < 1) + fun_l28_n673(x) + else + fun_l28_n824(x) + end +end + +def fun_l27_n554(x) + if (x < 1) + fun_l28_n376(x) + else + fun_l28_n32(x) + end +end + +def fun_l27_n555(x) + if (x < 1) + fun_l28_n500(x) + else + fun_l28_n389(x) + end +end + +def fun_l27_n556(x) + if (x < 1) + fun_l28_n712(x) + else + fun_l28_n729(x) + end +end + +def fun_l27_n557(x) + if (x < 1) + fun_l28_n951(x) + else + fun_l28_n846(x) + end +end + +def fun_l27_n558(x) + if (x < 1) + fun_l28_n269(x) + else + fun_l28_n538(x) + end +end + +def fun_l27_n559(x) + if (x < 1) + fun_l28_n72(x) + else + fun_l28_n711(x) + end +end + +def fun_l27_n560(x) + if (x < 1) + fun_l28_n510(x) + else + fun_l28_n718(x) + end +end + +def fun_l27_n561(x) + if (x < 1) + fun_l28_n123(x) + else + fun_l28_n983(x) + end +end + +def fun_l27_n562(x) + if (x < 1) + fun_l28_n486(x) + else + fun_l28_n796(x) + end +end + +def fun_l27_n563(x) + if (x < 1) + fun_l28_n925(x) + else + fun_l28_n499(x) + end +end + +def fun_l27_n564(x) + if (x < 1) + fun_l28_n811(x) + else + fun_l28_n604(x) + end +end + +def fun_l27_n565(x) + if (x < 1) + fun_l28_n685(x) + else + fun_l28_n721(x) + end +end + +def fun_l27_n566(x) + if (x < 1) + fun_l28_n946(x) + else + fun_l28_n890(x) + end +end + +def fun_l27_n567(x) + if (x < 1) + fun_l28_n646(x) + else + fun_l28_n2(x) + end +end + +def fun_l27_n568(x) + if (x < 1) + fun_l28_n570(x) + else + fun_l28_n427(x) + end +end + +def fun_l27_n569(x) + if (x < 1) + fun_l28_n435(x) + else + fun_l28_n877(x) + end +end + +def fun_l27_n570(x) + if (x < 1) + fun_l28_n67(x) + else + fun_l28_n879(x) + end +end + +def fun_l27_n571(x) + if (x < 1) + fun_l28_n278(x) + else + fun_l28_n90(x) + end +end + +def fun_l27_n572(x) + if (x < 1) + fun_l28_n748(x) + else + fun_l28_n202(x) + end +end + +def fun_l27_n573(x) + if (x < 1) + fun_l28_n795(x) + else + fun_l28_n862(x) + end +end + +def fun_l27_n574(x) + if (x < 1) + fun_l28_n208(x) + else + fun_l28_n979(x) + end +end + +def fun_l27_n575(x) + if (x < 1) + fun_l28_n134(x) + else + fun_l28_n208(x) + end +end + +def fun_l27_n576(x) + if (x < 1) + fun_l28_n591(x) + else + fun_l28_n400(x) + end +end + +def fun_l27_n577(x) + if (x < 1) + fun_l28_n579(x) + else + fun_l28_n675(x) + end +end + +def fun_l27_n578(x) + if (x < 1) + fun_l28_n186(x) + else + fun_l28_n643(x) + end +end + +def fun_l27_n579(x) + if (x < 1) + fun_l28_n974(x) + else + fun_l28_n716(x) + end +end + +def fun_l27_n580(x) + if (x < 1) + fun_l28_n168(x) + else + fun_l28_n10(x) + end +end + +def fun_l27_n581(x) + if (x < 1) + fun_l28_n124(x) + else + fun_l28_n657(x) + end +end + +def fun_l27_n582(x) + if (x < 1) + fun_l28_n240(x) + else + fun_l28_n335(x) + end +end + +def fun_l27_n583(x) + if (x < 1) + fun_l28_n346(x) + else + fun_l28_n170(x) + end +end + +def fun_l27_n584(x) + if (x < 1) + fun_l28_n854(x) + else + fun_l28_n681(x) + end +end + +def fun_l27_n585(x) + if (x < 1) + fun_l28_n515(x) + else + fun_l28_n884(x) + end +end + +def fun_l27_n586(x) + if (x < 1) + fun_l28_n901(x) + else + fun_l28_n12(x) + end +end + +def fun_l27_n587(x) + if (x < 1) + fun_l28_n300(x) + else + fun_l28_n205(x) + end +end + +def fun_l27_n588(x) + if (x < 1) + fun_l28_n52(x) + else + fun_l28_n823(x) + end +end + +def fun_l27_n589(x) + if (x < 1) + fun_l28_n170(x) + else + fun_l28_n588(x) + end +end + +def fun_l27_n590(x) + if (x < 1) + fun_l28_n777(x) + else + fun_l28_n232(x) + end +end + +def fun_l27_n591(x) + if (x < 1) + fun_l28_n234(x) + else + fun_l28_n552(x) + end +end + +def fun_l27_n592(x) + if (x < 1) + fun_l28_n83(x) + else + fun_l28_n736(x) + end +end + +def fun_l27_n593(x) + if (x < 1) + fun_l28_n623(x) + else + fun_l28_n663(x) + end +end + +def fun_l27_n594(x) + if (x < 1) + fun_l28_n137(x) + else + fun_l28_n858(x) + end +end + +def fun_l27_n595(x) + if (x < 1) + fun_l28_n238(x) + else + fun_l28_n11(x) + end +end + +def fun_l27_n596(x) + if (x < 1) + fun_l28_n692(x) + else + fun_l28_n815(x) + end +end + +def fun_l27_n597(x) + if (x < 1) + fun_l28_n259(x) + else + fun_l28_n535(x) + end +end + +def fun_l27_n598(x) + if (x < 1) + fun_l28_n135(x) + else + fun_l28_n567(x) + end +end + +def fun_l27_n599(x) + if (x < 1) + fun_l28_n725(x) + else + fun_l28_n393(x) + end +end + +def fun_l27_n600(x) + if (x < 1) + fun_l28_n790(x) + else + fun_l28_n478(x) + end +end + +def fun_l27_n601(x) + if (x < 1) + fun_l28_n248(x) + else + fun_l28_n62(x) + end +end + +def fun_l27_n602(x) + if (x < 1) + fun_l28_n790(x) + else + fun_l28_n854(x) + end +end + +def fun_l27_n603(x) + if (x < 1) + fun_l28_n345(x) + else + fun_l28_n795(x) + end +end + +def fun_l27_n604(x) + if (x < 1) + fun_l28_n689(x) + else + fun_l28_n357(x) + end +end + +def fun_l27_n605(x) + if (x < 1) + fun_l28_n314(x) + else + fun_l28_n886(x) + end +end + +def fun_l27_n606(x) + if (x < 1) + fun_l28_n401(x) + else + fun_l28_n688(x) + end +end + +def fun_l27_n607(x) + if (x < 1) + fun_l28_n386(x) + else + fun_l28_n126(x) + end +end + +def fun_l27_n608(x) + if (x < 1) + fun_l28_n232(x) + else + fun_l28_n387(x) + end +end + +def fun_l27_n609(x) + if (x < 1) + fun_l28_n938(x) + else + fun_l28_n657(x) + end +end + +def fun_l27_n610(x) + if (x < 1) + fun_l28_n40(x) + else + fun_l28_n141(x) + end +end + +def fun_l27_n611(x) + if (x < 1) + fun_l28_n909(x) + else + fun_l28_n265(x) + end +end + +def fun_l27_n612(x) + if (x < 1) + fun_l28_n486(x) + else + fun_l28_n470(x) + end +end + +def fun_l27_n613(x) + if (x < 1) + fun_l28_n959(x) + else + fun_l28_n793(x) + end +end + +def fun_l27_n614(x) + if (x < 1) + fun_l28_n422(x) + else + fun_l28_n246(x) + end +end + +def fun_l27_n615(x) + if (x < 1) + fun_l28_n860(x) + else + fun_l28_n315(x) + end +end + +def fun_l27_n616(x) + if (x < 1) + fun_l28_n529(x) + else + fun_l28_n647(x) + end +end + +def fun_l27_n617(x) + if (x < 1) + fun_l28_n860(x) + else + fun_l28_n860(x) + end +end + +def fun_l27_n618(x) + if (x < 1) + fun_l28_n147(x) + else + fun_l28_n814(x) + end +end + +def fun_l27_n619(x) + if (x < 1) + fun_l28_n828(x) + else + fun_l28_n854(x) + end +end + +def fun_l27_n620(x) + if (x < 1) + fun_l28_n464(x) + else + fun_l28_n838(x) + end +end + +def fun_l27_n621(x) + if (x < 1) + fun_l28_n89(x) + else + fun_l28_n884(x) + end +end + +def fun_l27_n622(x) + if (x < 1) + fun_l28_n933(x) + else + fun_l28_n889(x) + end +end + +def fun_l27_n623(x) + if (x < 1) + fun_l28_n638(x) + else + fun_l28_n246(x) + end +end + +def fun_l27_n624(x) + if (x < 1) + fun_l28_n724(x) + else + fun_l28_n305(x) + end +end + +def fun_l27_n625(x) + if (x < 1) + fun_l28_n927(x) + else + fun_l28_n772(x) + end +end + +def fun_l27_n626(x) + if (x < 1) + fun_l28_n612(x) + else + fun_l28_n953(x) + end +end + +def fun_l27_n627(x) + if (x < 1) + fun_l28_n694(x) + else + fun_l28_n529(x) + end +end + +def fun_l27_n628(x) + if (x < 1) + fun_l28_n136(x) + else + fun_l28_n977(x) + end +end + +def fun_l27_n629(x) + if (x < 1) + fun_l28_n108(x) + else + fun_l28_n940(x) + end +end + +def fun_l27_n630(x) + if (x < 1) + fun_l28_n773(x) + else + fun_l28_n62(x) + end +end + +def fun_l27_n631(x) + if (x < 1) + fun_l28_n531(x) + else + fun_l28_n68(x) + end +end + +def fun_l27_n632(x) + if (x < 1) + fun_l28_n910(x) + else + fun_l28_n638(x) + end +end + +def fun_l27_n633(x) + if (x < 1) + fun_l28_n943(x) + else + fun_l28_n530(x) + end +end + +def fun_l27_n634(x) + if (x < 1) + fun_l28_n161(x) + else + fun_l28_n842(x) + end +end + +def fun_l27_n635(x) + if (x < 1) + fun_l28_n252(x) + else + fun_l28_n659(x) + end +end + +def fun_l27_n636(x) + if (x < 1) + fun_l28_n739(x) + else + fun_l28_n116(x) + end +end + +def fun_l27_n637(x) + if (x < 1) + fun_l28_n528(x) + else + fun_l28_n451(x) + end +end + +def fun_l27_n638(x) + if (x < 1) + fun_l28_n772(x) + else + fun_l28_n163(x) + end +end + +def fun_l27_n639(x) + if (x < 1) + fun_l28_n300(x) + else + fun_l28_n174(x) + end +end + +def fun_l27_n640(x) + if (x < 1) + fun_l28_n967(x) + else + fun_l28_n437(x) + end +end + +def fun_l27_n641(x) + if (x < 1) + fun_l28_n716(x) + else + fun_l28_n855(x) + end +end + +def fun_l27_n642(x) + if (x < 1) + fun_l28_n510(x) + else + fun_l28_n958(x) + end +end + +def fun_l27_n643(x) + if (x < 1) + fun_l28_n57(x) + else + fun_l28_n347(x) + end +end + +def fun_l27_n644(x) + if (x < 1) + fun_l28_n145(x) + else + fun_l28_n652(x) + end +end + +def fun_l27_n645(x) + if (x < 1) + fun_l28_n730(x) + else + fun_l28_n388(x) + end +end + +def fun_l27_n646(x) + if (x < 1) + fun_l28_n409(x) + else + fun_l28_n394(x) + end +end + +def fun_l27_n647(x) + if (x < 1) + fun_l28_n484(x) + else + fun_l28_n754(x) + end +end + +def fun_l27_n648(x) + if (x < 1) + fun_l28_n888(x) + else + fun_l28_n229(x) + end +end + +def fun_l27_n649(x) + if (x < 1) + fun_l28_n1(x) + else + fun_l28_n995(x) + end +end + +def fun_l27_n650(x) + if (x < 1) + fun_l28_n992(x) + else + fun_l28_n522(x) + end +end + +def fun_l27_n651(x) + if (x < 1) + fun_l28_n69(x) + else + fun_l28_n696(x) + end +end + +def fun_l27_n652(x) + if (x < 1) + fun_l28_n496(x) + else + fun_l28_n47(x) + end +end + +def fun_l27_n653(x) + if (x < 1) + fun_l28_n176(x) + else + fun_l28_n830(x) + end +end + +def fun_l27_n654(x) + if (x < 1) + fun_l28_n277(x) + else + fun_l28_n311(x) + end +end + +def fun_l27_n655(x) + if (x < 1) + fun_l28_n994(x) + else + fun_l28_n518(x) + end +end + +def fun_l27_n656(x) + if (x < 1) + fun_l28_n238(x) + else + fun_l28_n99(x) + end +end + +def fun_l27_n657(x) + if (x < 1) + fun_l28_n636(x) + else + fun_l28_n734(x) + end +end + +def fun_l27_n658(x) + if (x < 1) + fun_l28_n796(x) + else + fun_l28_n109(x) + end +end + +def fun_l27_n659(x) + if (x < 1) + fun_l28_n271(x) + else + fun_l28_n348(x) + end +end + +def fun_l27_n660(x) + if (x < 1) + fun_l28_n847(x) + else + fun_l28_n926(x) + end +end + +def fun_l27_n661(x) + if (x < 1) + fun_l28_n559(x) + else + fun_l28_n636(x) + end +end + +def fun_l27_n662(x) + if (x < 1) + fun_l28_n528(x) + else + fun_l28_n0(x) + end +end + +def fun_l27_n663(x) + if (x < 1) + fun_l28_n835(x) + else + fun_l28_n41(x) + end +end + +def fun_l27_n664(x) + if (x < 1) + fun_l28_n135(x) + else + fun_l28_n356(x) + end +end + +def fun_l27_n665(x) + if (x < 1) + fun_l28_n825(x) + else + fun_l28_n55(x) + end +end + +def fun_l27_n666(x) + if (x < 1) + fun_l28_n659(x) + else + fun_l28_n384(x) + end +end + +def fun_l27_n667(x) + if (x < 1) + fun_l28_n604(x) + else + fun_l28_n870(x) + end +end + +def fun_l27_n668(x) + if (x < 1) + fun_l28_n136(x) + else + fun_l28_n343(x) + end +end + +def fun_l27_n669(x) + if (x < 1) + fun_l28_n206(x) + else + fun_l28_n341(x) + end +end + +def fun_l27_n670(x) + if (x < 1) + fun_l28_n947(x) + else + fun_l28_n926(x) + end +end + +def fun_l27_n671(x) + if (x < 1) + fun_l28_n303(x) + else + fun_l28_n79(x) + end +end + +def fun_l27_n672(x) + if (x < 1) + fun_l28_n181(x) + else + fun_l28_n937(x) + end +end + +def fun_l27_n673(x) + if (x < 1) + fun_l28_n301(x) + else + fun_l28_n687(x) + end +end + +def fun_l27_n674(x) + if (x < 1) + fun_l28_n992(x) + else + fun_l28_n814(x) + end +end + +def fun_l27_n675(x) + if (x < 1) + fun_l28_n239(x) + else + fun_l28_n248(x) + end +end + +def fun_l27_n676(x) + if (x < 1) + fun_l28_n728(x) + else + fun_l28_n368(x) + end +end + +def fun_l27_n677(x) + if (x < 1) + fun_l28_n411(x) + else + fun_l28_n773(x) + end +end + +def fun_l27_n678(x) + if (x < 1) + fun_l28_n522(x) + else + fun_l28_n754(x) + end +end + +def fun_l27_n679(x) + if (x < 1) + fun_l28_n538(x) + else + fun_l28_n976(x) + end +end + +def fun_l27_n680(x) + if (x < 1) + fun_l28_n744(x) + else + fun_l28_n752(x) + end +end + +def fun_l27_n681(x) + if (x < 1) + fun_l28_n658(x) + else + fun_l28_n19(x) + end +end + +def fun_l27_n682(x) + if (x < 1) + fun_l28_n843(x) + else + fun_l28_n657(x) + end +end + +def fun_l27_n683(x) + if (x < 1) + fun_l28_n256(x) + else + fun_l28_n744(x) + end +end + +def fun_l27_n684(x) + if (x < 1) + fun_l28_n380(x) + else + fun_l28_n223(x) + end +end + +def fun_l27_n685(x) + if (x < 1) + fun_l28_n762(x) + else + fun_l28_n122(x) + end +end + +def fun_l27_n686(x) + if (x < 1) + fun_l28_n860(x) + else + fun_l28_n51(x) + end +end + +def fun_l27_n687(x) + if (x < 1) + fun_l28_n210(x) + else + fun_l28_n658(x) + end +end + +def fun_l27_n688(x) + if (x < 1) + fun_l28_n250(x) + else + fun_l28_n165(x) + end +end + +def fun_l27_n689(x) + if (x < 1) + fun_l28_n955(x) + else + fun_l28_n862(x) + end +end + +def fun_l27_n690(x) + if (x < 1) + fun_l28_n592(x) + else + fun_l28_n54(x) + end +end + +def fun_l27_n691(x) + if (x < 1) + fun_l28_n558(x) + else + fun_l28_n750(x) + end +end + +def fun_l27_n692(x) + if (x < 1) + fun_l28_n307(x) + else + fun_l28_n143(x) + end +end + +def fun_l27_n693(x) + if (x < 1) + fun_l28_n625(x) + else + fun_l28_n743(x) + end +end + +def fun_l27_n694(x) + if (x < 1) + fun_l28_n883(x) + else + fun_l28_n567(x) + end +end + +def fun_l27_n695(x) + if (x < 1) + fun_l28_n889(x) + else + fun_l28_n805(x) + end +end + +def fun_l27_n696(x) + if (x < 1) + fun_l28_n366(x) + else + fun_l28_n112(x) + end +end + +def fun_l27_n697(x) + if (x < 1) + fun_l28_n746(x) + else + fun_l28_n924(x) + end +end + +def fun_l27_n698(x) + if (x < 1) + fun_l28_n694(x) + else + fun_l28_n703(x) + end +end + +def fun_l27_n699(x) + if (x < 1) + fun_l28_n304(x) + else + fun_l28_n200(x) + end +end + +def fun_l27_n700(x) + if (x < 1) + fun_l28_n477(x) + else + fun_l28_n851(x) + end +end + +def fun_l27_n701(x) + if (x < 1) + fun_l28_n940(x) + else + fun_l28_n8(x) + end +end + +def fun_l27_n702(x) + if (x < 1) + fun_l28_n675(x) + else + fun_l28_n631(x) + end +end + +def fun_l27_n703(x) + if (x < 1) + fun_l28_n683(x) + else + fun_l28_n191(x) + end +end + +def fun_l27_n704(x) + if (x < 1) + fun_l28_n431(x) + else + fun_l28_n573(x) + end +end + +def fun_l27_n705(x) + if (x < 1) + fun_l28_n86(x) + else + fun_l28_n89(x) + end +end + +def fun_l27_n706(x) + if (x < 1) + fun_l28_n315(x) + else + fun_l28_n388(x) + end +end + +def fun_l27_n707(x) + if (x < 1) + fun_l28_n94(x) + else + fun_l28_n176(x) + end +end + +def fun_l27_n708(x) + if (x < 1) + fun_l28_n391(x) + else + fun_l28_n187(x) + end +end + +def fun_l27_n709(x) + if (x < 1) + fun_l28_n845(x) + else + fun_l28_n497(x) + end +end + +def fun_l27_n710(x) + if (x < 1) + fun_l28_n195(x) + else + fun_l28_n242(x) + end +end + +def fun_l27_n711(x) + if (x < 1) + fun_l28_n276(x) + else + fun_l28_n856(x) + end +end + +def fun_l27_n712(x) + if (x < 1) + fun_l28_n42(x) + else + fun_l28_n184(x) + end +end + +def fun_l27_n713(x) + if (x < 1) + fun_l28_n270(x) + else + fun_l28_n813(x) + end +end + +def fun_l27_n714(x) + if (x < 1) + fun_l28_n281(x) + else + fun_l28_n54(x) + end +end + +def fun_l27_n715(x) + if (x < 1) + fun_l28_n226(x) + else + fun_l28_n202(x) + end +end + +def fun_l27_n716(x) + if (x < 1) + fun_l28_n391(x) + else + fun_l28_n143(x) + end +end + +def fun_l27_n717(x) + if (x < 1) + fun_l28_n449(x) + else + fun_l28_n530(x) + end +end + +def fun_l27_n718(x) + if (x < 1) + fun_l28_n198(x) + else + fun_l28_n342(x) + end +end + +def fun_l27_n719(x) + if (x < 1) + fun_l28_n741(x) + else + fun_l28_n703(x) + end +end + +def fun_l27_n720(x) + if (x < 1) + fun_l28_n779(x) + else + fun_l28_n706(x) + end +end + +def fun_l27_n721(x) + if (x < 1) + fun_l28_n184(x) + else + fun_l28_n472(x) + end +end + +def fun_l27_n722(x) + if (x < 1) + fun_l28_n752(x) + else + fun_l28_n230(x) + end +end + +def fun_l27_n723(x) + if (x < 1) + fun_l28_n137(x) + else + fun_l28_n228(x) + end +end + +def fun_l27_n724(x) + if (x < 1) + fun_l28_n360(x) + else + fun_l28_n186(x) + end +end + +def fun_l27_n725(x) + if (x < 1) + fun_l28_n791(x) + else + fun_l28_n752(x) + end +end + +def fun_l27_n726(x) + if (x < 1) + fun_l28_n162(x) + else + fun_l28_n492(x) + end +end + +def fun_l27_n727(x) + if (x < 1) + fun_l28_n329(x) + else + fun_l28_n286(x) + end +end + +def fun_l27_n728(x) + if (x < 1) + fun_l28_n262(x) + else + fun_l28_n775(x) + end +end + +def fun_l27_n729(x) + if (x < 1) + fun_l28_n773(x) + else + fun_l28_n424(x) + end +end + +def fun_l27_n730(x) + if (x < 1) + fun_l28_n202(x) + else + fun_l28_n379(x) + end +end + +def fun_l27_n731(x) + if (x < 1) + fun_l28_n761(x) + else + fun_l28_n759(x) + end +end + +def fun_l27_n732(x) + if (x < 1) + fun_l28_n544(x) + else + fun_l28_n980(x) + end +end + +def fun_l27_n733(x) + if (x < 1) + fun_l28_n75(x) + else + fun_l28_n786(x) + end +end + +def fun_l27_n734(x) + if (x < 1) + fun_l28_n708(x) + else + fun_l28_n92(x) + end +end + +def fun_l27_n735(x) + if (x < 1) + fun_l28_n213(x) + else + fun_l28_n966(x) + end +end + +def fun_l27_n736(x) + if (x < 1) + fun_l28_n298(x) + else + fun_l28_n517(x) + end +end + +def fun_l27_n737(x) + if (x < 1) + fun_l28_n665(x) + else + fun_l28_n960(x) + end +end + +def fun_l27_n738(x) + if (x < 1) + fun_l28_n51(x) + else + fun_l28_n605(x) + end +end + +def fun_l27_n739(x) + if (x < 1) + fun_l28_n931(x) + else + fun_l28_n697(x) + end +end + +def fun_l27_n740(x) + if (x < 1) + fun_l28_n341(x) + else + fun_l28_n57(x) + end +end + +def fun_l27_n741(x) + if (x < 1) + fun_l28_n614(x) + else + fun_l28_n623(x) + end +end + +def fun_l27_n742(x) + if (x < 1) + fun_l28_n466(x) + else + fun_l28_n260(x) + end +end + +def fun_l27_n743(x) + if (x < 1) + fun_l28_n741(x) + else + fun_l28_n337(x) + end +end + +def fun_l27_n744(x) + if (x < 1) + fun_l28_n414(x) + else + fun_l28_n277(x) + end +end + +def fun_l27_n745(x) + if (x < 1) + fun_l28_n377(x) + else + fun_l28_n245(x) + end +end + +def fun_l27_n746(x) + if (x < 1) + fun_l28_n441(x) + else + fun_l28_n347(x) + end +end + +def fun_l27_n747(x) + if (x < 1) + fun_l28_n473(x) + else + fun_l28_n54(x) + end +end + +def fun_l27_n748(x) + if (x < 1) + fun_l28_n140(x) + else + fun_l28_n680(x) + end +end + +def fun_l27_n749(x) + if (x < 1) + fun_l28_n491(x) + else + fun_l28_n830(x) + end +end + +def fun_l27_n750(x) + if (x < 1) + fun_l28_n803(x) + else + fun_l28_n917(x) + end +end + +def fun_l27_n751(x) + if (x < 1) + fun_l28_n97(x) + else + fun_l28_n702(x) + end +end + +def fun_l27_n752(x) + if (x < 1) + fun_l28_n113(x) + else + fun_l28_n447(x) + end +end + +def fun_l27_n753(x) + if (x < 1) + fun_l28_n589(x) + else + fun_l28_n933(x) + end +end + +def fun_l27_n754(x) + if (x < 1) + fun_l28_n610(x) + else + fun_l28_n365(x) + end +end + +def fun_l27_n755(x) + if (x < 1) + fun_l28_n813(x) + else + fun_l28_n930(x) + end +end + +def fun_l27_n756(x) + if (x < 1) + fun_l28_n997(x) + else + fun_l28_n112(x) + end +end + +def fun_l27_n757(x) + if (x < 1) + fun_l28_n635(x) + else + fun_l28_n852(x) + end +end + +def fun_l27_n758(x) + if (x < 1) + fun_l28_n735(x) + else + fun_l28_n3(x) + end +end + +def fun_l27_n759(x) + if (x < 1) + fun_l28_n473(x) + else + fun_l28_n276(x) + end +end + +def fun_l27_n760(x) + if (x < 1) + fun_l28_n708(x) + else + fun_l28_n602(x) + end +end + +def fun_l27_n761(x) + if (x < 1) + fun_l28_n178(x) + else + fun_l28_n766(x) + end +end + +def fun_l27_n762(x) + if (x < 1) + fun_l28_n968(x) + else + fun_l28_n935(x) + end +end + +def fun_l27_n763(x) + if (x < 1) + fun_l28_n17(x) + else + fun_l28_n680(x) + end +end + +def fun_l27_n764(x) + if (x < 1) + fun_l28_n465(x) + else + fun_l28_n484(x) + end +end + +def fun_l27_n765(x) + if (x < 1) + fun_l28_n157(x) + else + fun_l28_n33(x) + end +end + +def fun_l27_n766(x) + if (x < 1) + fun_l28_n306(x) + else + fun_l28_n588(x) + end +end + +def fun_l27_n767(x) + if (x < 1) + fun_l28_n73(x) + else + fun_l28_n144(x) + end +end + +def fun_l27_n768(x) + if (x < 1) + fun_l28_n838(x) + else + fun_l28_n984(x) + end +end + +def fun_l27_n769(x) + if (x < 1) + fun_l28_n541(x) + else + fun_l28_n687(x) + end +end + +def fun_l27_n770(x) + if (x < 1) + fun_l28_n129(x) + else + fun_l28_n256(x) + end +end + +def fun_l27_n771(x) + if (x < 1) + fun_l28_n78(x) + else + fun_l28_n617(x) + end +end + +def fun_l27_n772(x) + if (x < 1) + fun_l28_n590(x) + else + fun_l28_n78(x) + end +end + +def fun_l27_n773(x) + if (x < 1) + fun_l28_n609(x) + else + fun_l28_n942(x) + end +end + +def fun_l27_n774(x) + if (x < 1) + fun_l28_n794(x) + else + fun_l28_n361(x) + end +end + +def fun_l27_n775(x) + if (x < 1) + fun_l28_n632(x) + else + fun_l28_n722(x) + end +end + +def fun_l27_n776(x) + if (x < 1) + fun_l28_n655(x) + else + fun_l28_n944(x) + end +end + +def fun_l27_n777(x) + if (x < 1) + fun_l28_n117(x) + else + fun_l28_n725(x) + end +end + +def fun_l27_n778(x) + if (x < 1) + fun_l28_n511(x) + else + fun_l28_n934(x) + end +end + +def fun_l27_n779(x) + if (x < 1) + fun_l28_n11(x) + else + fun_l28_n421(x) + end +end + +def fun_l27_n780(x) + if (x < 1) + fun_l28_n957(x) + else + fun_l28_n941(x) + end +end + +def fun_l27_n781(x) + if (x < 1) + fun_l28_n899(x) + else + fun_l28_n122(x) + end +end + +def fun_l27_n782(x) + if (x < 1) + fun_l28_n42(x) + else + fun_l28_n885(x) + end +end + +def fun_l27_n783(x) + if (x < 1) + fun_l28_n696(x) + else + fun_l28_n25(x) + end +end + +def fun_l27_n784(x) + if (x < 1) + fun_l28_n683(x) + else + fun_l28_n201(x) + end +end + +def fun_l27_n785(x) + if (x < 1) + fun_l28_n337(x) + else + fun_l28_n977(x) + end +end + +def fun_l27_n786(x) + if (x < 1) + fun_l28_n113(x) + else + fun_l28_n946(x) + end +end + +def fun_l27_n787(x) + if (x < 1) + fun_l28_n311(x) + else + fun_l28_n396(x) + end +end + +def fun_l27_n788(x) + if (x < 1) + fun_l28_n963(x) + else + fun_l28_n592(x) + end +end + +def fun_l27_n789(x) + if (x < 1) + fun_l28_n647(x) + else + fun_l28_n614(x) + end +end + +def fun_l27_n790(x) + if (x < 1) + fun_l28_n15(x) + else + fun_l28_n602(x) + end +end + +def fun_l27_n791(x) + if (x < 1) + fun_l28_n648(x) + else + fun_l28_n921(x) + end +end + +def fun_l27_n792(x) + if (x < 1) + fun_l28_n272(x) + else + fun_l28_n585(x) + end +end + +def fun_l27_n793(x) + if (x < 1) + fun_l28_n74(x) + else + fun_l28_n412(x) + end +end + +def fun_l27_n794(x) + if (x < 1) + fun_l28_n610(x) + else + fun_l28_n121(x) + end +end + +def fun_l27_n795(x) + if (x < 1) + fun_l28_n905(x) + else + fun_l28_n620(x) + end +end + +def fun_l27_n796(x) + if (x < 1) + fun_l28_n691(x) + else + fun_l28_n833(x) + end +end + +def fun_l27_n797(x) + if (x < 1) + fun_l28_n148(x) + else + fun_l28_n223(x) + end +end + +def fun_l27_n798(x) + if (x < 1) + fun_l28_n835(x) + else + fun_l28_n59(x) + end +end + +def fun_l27_n799(x) + if (x < 1) + fun_l28_n317(x) + else + fun_l28_n39(x) + end +end + +def fun_l27_n800(x) + if (x < 1) + fun_l28_n694(x) + else + fun_l28_n833(x) + end +end + +def fun_l27_n801(x) + if (x < 1) + fun_l28_n280(x) + else + fun_l28_n322(x) + end +end + +def fun_l27_n802(x) + if (x < 1) + fun_l28_n612(x) + else + fun_l28_n866(x) + end +end + +def fun_l27_n803(x) + if (x < 1) + fun_l28_n114(x) + else + fun_l28_n901(x) + end +end + +def fun_l27_n804(x) + if (x < 1) + fun_l28_n983(x) + else + fun_l28_n837(x) + end +end + +def fun_l27_n805(x) + if (x < 1) + fun_l28_n225(x) + else + fun_l28_n345(x) + end +end + +def fun_l27_n806(x) + if (x < 1) + fun_l28_n879(x) + else + fun_l28_n929(x) + end +end + +def fun_l27_n807(x) + if (x < 1) + fun_l28_n41(x) + else + fun_l28_n670(x) + end +end + +def fun_l27_n808(x) + if (x < 1) + fun_l28_n407(x) + else + fun_l28_n46(x) + end +end + +def fun_l27_n809(x) + if (x < 1) + fun_l28_n377(x) + else + fun_l28_n646(x) + end +end + +def fun_l27_n810(x) + if (x < 1) + fun_l28_n293(x) + else + fun_l28_n40(x) + end +end + +def fun_l27_n811(x) + if (x < 1) + fun_l28_n150(x) + else + fun_l28_n743(x) + end +end + +def fun_l27_n812(x) + if (x < 1) + fun_l28_n285(x) + else + fun_l28_n124(x) + end +end + +def fun_l27_n813(x) + if (x < 1) + fun_l28_n861(x) + else + fun_l28_n641(x) + end +end + +def fun_l27_n814(x) + if (x < 1) + fun_l28_n917(x) + else + fun_l28_n51(x) + end +end + +def fun_l27_n815(x) + if (x < 1) + fun_l28_n573(x) + else + fun_l28_n551(x) + end +end + +def fun_l27_n816(x) + if (x < 1) + fun_l28_n420(x) + else + fun_l28_n155(x) + end +end + +def fun_l27_n817(x) + if (x < 1) + fun_l28_n283(x) + else + fun_l28_n797(x) + end +end + +def fun_l27_n818(x) + if (x < 1) + fun_l28_n744(x) + else + fun_l28_n22(x) + end +end + +def fun_l27_n819(x) + if (x < 1) + fun_l28_n370(x) + else + fun_l28_n287(x) + end +end + +def fun_l27_n820(x) + if (x < 1) + fun_l28_n435(x) + else + fun_l28_n23(x) + end +end + +def fun_l27_n821(x) + if (x < 1) + fun_l28_n947(x) + else + fun_l28_n200(x) + end +end + +def fun_l27_n822(x) + if (x < 1) + fun_l28_n259(x) + else + fun_l28_n444(x) + end +end + +def fun_l27_n823(x) + if (x < 1) + fun_l28_n663(x) + else + fun_l28_n755(x) + end +end + +def fun_l27_n824(x) + if (x < 1) + fun_l28_n564(x) + else + fun_l28_n572(x) + end +end + +def fun_l27_n825(x) + if (x < 1) + fun_l28_n679(x) + else + fun_l28_n351(x) + end +end + +def fun_l27_n826(x) + if (x < 1) + fun_l28_n654(x) + else + fun_l28_n393(x) + end +end + +def fun_l27_n827(x) + if (x < 1) + fun_l28_n454(x) + else + fun_l28_n698(x) + end +end + +def fun_l27_n828(x) + if (x < 1) + fun_l28_n389(x) + else + fun_l28_n118(x) + end +end + +def fun_l27_n829(x) + if (x < 1) + fun_l28_n918(x) + else + fun_l28_n176(x) + end +end + +def fun_l27_n830(x) + if (x < 1) + fun_l28_n158(x) + else + fun_l28_n309(x) + end +end + +def fun_l27_n831(x) + if (x < 1) + fun_l28_n86(x) + else + fun_l28_n250(x) + end +end + +def fun_l27_n832(x) + if (x < 1) + fun_l28_n21(x) + else + fun_l28_n688(x) + end +end + +def fun_l27_n833(x) + if (x < 1) + fun_l28_n587(x) + else + fun_l28_n484(x) + end +end + +def fun_l27_n834(x) + if (x < 1) + fun_l28_n886(x) + else + fun_l28_n579(x) + end +end + +def fun_l27_n835(x) + if (x < 1) + fun_l28_n923(x) + else + fun_l28_n140(x) + end +end + +def fun_l27_n836(x) + if (x < 1) + fun_l28_n120(x) + else + fun_l28_n704(x) + end +end + +def fun_l27_n837(x) + if (x < 1) + fun_l28_n905(x) + else + fun_l28_n918(x) + end +end + +def fun_l27_n838(x) + if (x < 1) + fun_l28_n679(x) + else + fun_l28_n588(x) + end +end + +def fun_l27_n839(x) + if (x < 1) + fun_l28_n445(x) + else + fun_l28_n187(x) + end +end + +def fun_l27_n840(x) + if (x < 1) + fun_l28_n695(x) + else + fun_l28_n86(x) + end +end + +def fun_l27_n841(x) + if (x < 1) + fun_l28_n784(x) + else + fun_l28_n802(x) + end +end + +def fun_l27_n842(x) + if (x < 1) + fun_l28_n854(x) + else + fun_l28_n617(x) + end +end + +def fun_l27_n843(x) + if (x < 1) + fun_l28_n466(x) + else + fun_l28_n261(x) + end +end + +def fun_l27_n844(x) + if (x < 1) + fun_l28_n326(x) + else + fun_l28_n517(x) + end +end + +def fun_l27_n845(x) + if (x < 1) + fun_l28_n686(x) + else + fun_l28_n81(x) + end +end + +def fun_l27_n846(x) + if (x < 1) + fun_l28_n71(x) + else + fun_l28_n685(x) + end +end + +def fun_l27_n847(x) + if (x < 1) + fun_l28_n622(x) + else + fun_l28_n469(x) + end +end + +def fun_l27_n848(x) + if (x < 1) + fun_l28_n125(x) + else + fun_l28_n252(x) + end +end + +def fun_l27_n849(x) + if (x < 1) + fun_l28_n820(x) + else + fun_l28_n752(x) + end +end + +def fun_l27_n850(x) + if (x < 1) + fun_l28_n278(x) + else + fun_l28_n198(x) + end +end + +def fun_l27_n851(x) + if (x < 1) + fun_l28_n631(x) + else + fun_l28_n241(x) + end +end + +def fun_l27_n852(x) + if (x < 1) + fun_l28_n917(x) + else + fun_l28_n95(x) + end +end + +def fun_l27_n853(x) + if (x < 1) + fun_l28_n271(x) + else + fun_l28_n493(x) + end +end + +def fun_l27_n854(x) + if (x < 1) + fun_l28_n578(x) + else + fun_l28_n31(x) + end +end + +def fun_l27_n855(x) + if (x < 1) + fun_l28_n407(x) + else + fun_l28_n694(x) + end +end + +def fun_l27_n856(x) + if (x < 1) + fun_l28_n541(x) + else + fun_l28_n81(x) + end +end + +def fun_l27_n857(x) + if (x < 1) + fun_l28_n144(x) + else + fun_l28_n965(x) + end +end + +def fun_l27_n858(x) + if (x < 1) + fun_l28_n476(x) + else + fun_l28_n44(x) + end +end + +def fun_l27_n859(x) + if (x < 1) + fun_l28_n647(x) + else + fun_l28_n973(x) + end +end + +def fun_l27_n860(x) + if (x < 1) + fun_l28_n641(x) + else + fun_l28_n331(x) + end +end + +def fun_l27_n861(x) + if (x < 1) + fun_l28_n75(x) + else + fun_l28_n10(x) + end +end + +def fun_l27_n862(x) + if (x < 1) + fun_l28_n435(x) + else + fun_l28_n182(x) + end +end + +def fun_l27_n863(x) + if (x < 1) + fun_l28_n244(x) + else + fun_l28_n135(x) + end +end + +def fun_l27_n864(x) + if (x < 1) + fun_l28_n598(x) + else + fun_l28_n495(x) + end +end + +def fun_l27_n865(x) + if (x < 1) + fun_l28_n456(x) + else + fun_l28_n16(x) + end +end + +def fun_l27_n866(x) + if (x < 1) + fun_l28_n43(x) + else + fun_l28_n279(x) + end +end + +def fun_l27_n867(x) + if (x < 1) + fun_l28_n853(x) + else + fun_l28_n906(x) + end +end + +def fun_l27_n868(x) + if (x < 1) + fun_l28_n641(x) + else + fun_l28_n479(x) + end +end + +def fun_l27_n869(x) + if (x < 1) + fun_l28_n78(x) + else + fun_l28_n727(x) + end +end + +def fun_l27_n870(x) + if (x < 1) + fun_l28_n815(x) + else + fun_l28_n803(x) + end +end + +def fun_l27_n871(x) + if (x < 1) + fun_l28_n343(x) + else + fun_l28_n665(x) + end +end + +def fun_l27_n872(x) + if (x < 1) + fun_l28_n907(x) + else + fun_l28_n410(x) + end +end + +def fun_l27_n873(x) + if (x < 1) + fun_l28_n797(x) + else + fun_l28_n626(x) + end +end + +def fun_l27_n874(x) + if (x < 1) + fun_l28_n784(x) + else + fun_l28_n679(x) + end +end + +def fun_l27_n875(x) + if (x < 1) + fun_l28_n247(x) + else + fun_l28_n89(x) + end +end + +def fun_l27_n876(x) + if (x < 1) + fun_l28_n911(x) + else + fun_l28_n503(x) + end +end + +def fun_l27_n877(x) + if (x < 1) + fun_l28_n233(x) + else + fun_l28_n437(x) + end +end + +def fun_l27_n878(x) + if (x < 1) + fun_l28_n913(x) + else + fun_l28_n984(x) + end +end + +def fun_l27_n879(x) + if (x < 1) + fun_l28_n690(x) + else + fun_l28_n642(x) + end +end + +def fun_l27_n880(x) + if (x < 1) + fun_l28_n222(x) + else + fun_l28_n400(x) + end +end + +def fun_l27_n881(x) + if (x < 1) + fun_l28_n611(x) + else + fun_l28_n446(x) + end +end + +def fun_l27_n882(x) + if (x < 1) + fun_l28_n821(x) + else + fun_l28_n784(x) + end +end + +def fun_l27_n883(x) + if (x < 1) + fun_l28_n849(x) + else + fun_l28_n83(x) + end +end + +def fun_l27_n884(x) + if (x < 1) + fun_l28_n366(x) + else + fun_l28_n822(x) + end +end + +def fun_l27_n885(x) + if (x < 1) + fun_l28_n40(x) + else + fun_l28_n626(x) + end +end + +def fun_l27_n886(x) + if (x < 1) + fun_l28_n280(x) + else + fun_l28_n957(x) + end +end + +def fun_l27_n887(x) + if (x < 1) + fun_l28_n466(x) + else + fun_l28_n377(x) + end +end + +def fun_l27_n888(x) + if (x < 1) + fun_l28_n258(x) + else + fun_l28_n816(x) + end +end + +def fun_l27_n889(x) + if (x < 1) + fun_l28_n893(x) + else + fun_l28_n263(x) + end +end + +def fun_l27_n890(x) + if (x < 1) + fun_l28_n366(x) + else + fun_l28_n890(x) + end +end + +def fun_l27_n891(x) + if (x < 1) + fun_l28_n692(x) + else + fun_l28_n781(x) + end +end + +def fun_l27_n892(x) + if (x < 1) + fun_l28_n301(x) + else + fun_l28_n142(x) + end +end + +def fun_l27_n893(x) + if (x < 1) + fun_l28_n275(x) + else + fun_l28_n302(x) + end +end + +def fun_l27_n894(x) + if (x < 1) + fun_l28_n726(x) + else + fun_l28_n445(x) + end +end + +def fun_l27_n895(x) + if (x < 1) + fun_l28_n859(x) + else + fun_l28_n839(x) + end +end + +def fun_l27_n896(x) + if (x < 1) + fun_l28_n252(x) + else + fun_l28_n844(x) + end +end + +def fun_l27_n897(x) + if (x < 1) + fun_l28_n245(x) + else + fun_l28_n133(x) + end +end + +def fun_l27_n898(x) + if (x < 1) + fun_l28_n233(x) + else + fun_l28_n417(x) + end +end + +def fun_l27_n899(x) + if (x < 1) + fun_l28_n171(x) + else + fun_l28_n479(x) + end +end + +def fun_l27_n900(x) + if (x < 1) + fun_l28_n528(x) + else + fun_l28_n196(x) + end +end + +def fun_l27_n901(x) + if (x < 1) + fun_l28_n243(x) + else + fun_l28_n270(x) + end +end + +def fun_l27_n902(x) + if (x < 1) + fun_l28_n319(x) + else + fun_l28_n885(x) + end +end + +def fun_l27_n903(x) + if (x < 1) + fun_l28_n570(x) + else + fun_l28_n321(x) + end +end + +def fun_l27_n904(x) + if (x < 1) + fun_l28_n522(x) + else + fun_l28_n720(x) + end +end + +def fun_l27_n905(x) + if (x < 1) + fun_l28_n820(x) + else + fun_l28_n789(x) + end +end + +def fun_l27_n906(x) + if (x < 1) + fun_l28_n592(x) + else + fun_l28_n113(x) + end +end + +def fun_l27_n907(x) + if (x < 1) + fun_l28_n432(x) + else + fun_l28_n591(x) + end +end + +def fun_l27_n908(x) + if (x < 1) + fun_l28_n538(x) + else + fun_l28_n701(x) + end +end + +def fun_l27_n909(x) + if (x < 1) + fun_l28_n963(x) + else + fun_l28_n756(x) + end +end + +def fun_l27_n910(x) + if (x < 1) + fun_l28_n871(x) + else + fun_l28_n387(x) + end +end + +def fun_l27_n911(x) + if (x < 1) + fun_l28_n779(x) + else + fun_l28_n862(x) + end +end + +def fun_l27_n912(x) + if (x < 1) + fun_l28_n0(x) + else + fun_l28_n208(x) + end +end + +def fun_l27_n913(x) + if (x < 1) + fun_l28_n994(x) + else + fun_l28_n756(x) + end +end + +def fun_l27_n914(x) + if (x < 1) + fun_l28_n950(x) + else + fun_l28_n770(x) + end +end + +def fun_l27_n915(x) + if (x < 1) + fun_l28_n922(x) + else + fun_l28_n372(x) + end +end + +def fun_l27_n916(x) + if (x < 1) + fun_l28_n786(x) + else + fun_l28_n786(x) + end +end + +def fun_l27_n917(x) + if (x < 1) + fun_l28_n745(x) + else + fun_l28_n822(x) + end +end + +def fun_l27_n918(x) + if (x < 1) + fun_l28_n69(x) + else + fun_l28_n669(x) + end +end + +def fun_l27_n919(x) + if (x < 1) + fun_l28_n714(x) + else + fun_l28_n777(x) + end +end + +def fun_l27_n920(x) + if (x < 1) + fun_l28_n934(x) + else + fun_l28_n392(x) + end +end + +def fun_l27_n921(x) + if (x < 1) + fun_l28_n746(x) + else + fun_l28_n355(x) + end +end + +def fun_l27_n922(x) + if (x < 1) + fun_l28_n645(x) + else + fun_l28_n351(x) + end +end + +def fun_l27_n923(x) + if (x < 1) + fun_l28_n48(x) + else + fun_l28_n826(x) + end +end + +def fun_l27_n924(x) + if (x < 1) + fun_l28_n531(x) + else + fun_l28_n577(x) + end +end + +def fun_l27_n925(x) + if (x < 1) + fun_l28_n907(x) + else + fun_l28_n136(x) + end +end + +def fun_l27_n926(x) + if (x < 1) + fun_l28_n256(x) + else + fun_l28_n527(x) + end +end + +def fun_l27_n927(x) + if (x < 1) + fun_l28_n870(x) + else + fun_l28_n475(x) + end +end + +def fun_l27_n928(x) + if (x < 1) + fun_l28_n184(x) + else + fun_l28_n397(x) + end +end + +def fun_l27_n929(x) + if (x < 1) + fun_l28_n99(x) + else + fun_l28_n363(x) + end +end + +def fun_l27_n930(x) + if (x < 1) + fun_l28_n217(x) + else + fun_l28_n978(x) + end +end + +def fun_l27_n931(x) + if (x < 1) + fun_l28_n372(x) + else + fun_l28_n542(x) + end +end + +def fun_l27_n932(x) + if (x < 1) + fun_l28_n337(x) + else + fun_l28_n150(x) + end +end + +def fun_l27_n933(x) + if (x < 1) + fun_l28_n81(x) + else + fun_l28_n206(x) + end +end + +def fun_l27_n934(x) + if (x < 1) + fun_l28_n984(x) + else + fun_l28_n748(x) + end +end + +def fun_l27_n935(x) + if (x < 1) + fun_l28_n746(x) + else + fun_l28_n824(x) + end +end + +def fun_l27_n936(x) + if (x < 1) + fun_l28_n737(x) + else + fun_l28_n353(x) + end +end + +def fun_l27_n937(x) + if (x < 1) + fun_l28_n681(x) + else + fun_l28_n518(x) + end +end + +def fun_l27_n938(x) + if (x < 1) + fun_l28_n401(x) + else + fun_l28_n99(x) + end +end + +def fun_l27_n939(x) + if (x < 1) + fun_l28_n821(x) + else + fun_l28_n456(x) + end +end + +def fun_l27_n940(x) + if (x < 1) + fun_l28_n411(x) + else + fun_l28_n578(x) + end +end + +def fun_l27_n941(x) + if (x < 1) + fun_l28_n318(x) + else + fun_l28_n479(x) + end +end + +def fun_l27_n942(x) + if (x < 1) + fun_l28_n229(x) + else + fun_l28_n338(x) + end +end + +def fun_l27_n943(x) + if (x < 1) + fun_l28_n195(x) + else + fun_l28_n667(x) + end +end + +def fun_l27_n944(x) + if (x < 1) + fun_l28_n256(x) + else + fun_l28_n309(x) + end +end + +def fun_l27_n945(x) + if (x < 1) + fun_l28_n939(x) + else + fun_l28_n284(x) + end +end + +def fun_l27_n946(x) + if (x < 1) + fun_l28_n70(x) + else + fun_l28_n408(x) + end +end + +def fun_l27_n947(x) + if (x < 1) + fun_l28_n586(x) + else + fun_l28_n931(x) + end +end + +def fun_l27_n948(x) + if (x < 1) + fun_l28_n878(x) + else + fun_l28_n95(x) + end +end + +def fun_l27_n949(x) + if (x < 1) + fun_l28_n749(x) + else + fun_l28_n414(x) + end +end + +def fun_l27_n950(x) + if (x < 1) + fun_l28_n913(x) + else + fun_l28_n933(x) + end +end + +def fun_l27_n951(x) + if (x < 1) + fun_l28_n394(x) + else + fun_l28_n121(x) + end +end + +def fun_l27_n952(x) + if (x < 1) + fun_l28_n381(x) + else + fun_l28_n279(x) + end +end + +def fun_l27_n953(x) + if (x < 1) + fun_l28_n302(x) + else + fun_l28_n710(x) + end +end + +def fun_l27_n954(x) + if (x < 1) + fun_l28_n765(x) + else + fun_l28_n254(x) + end +end + +def fun_l27_n955(x) + if (x < 1) + fun_l28_n736(x) + else + fun_l28_n67(x) + end +end + +def fun_l27_n956(x) + if (x < 1) + fun_l28_n61(x) + else + fun_l28_n873(x) + end +end + +def fun_l27_n957(x) + if (x < 1) + fun_l28_n920(x) + else + fun_l28_n261(x) + end +end + +def fun_l27_n958(x) + if (x < 1) + fun_l28_n350(x) + else + fun_l28_n545(x) + end +end + +def fun_l27_n959(x) + if (x < 1) + fun_l28_n538(x) + else + fun_l28_n829(x) + end +end + +def fun_l27_n960(x) + if (x < 1) + fun_l28_n920(x) + else + fun_l28_n534(x) + end +end + +def fun_l27_n961(x) + if (x < 1) + fun_l28_n730(x) + else + fun_l28_n19(x) + end +end + +def fun_l27_n962(x) + if (x < 1) + fun_l28_n293(x) + else + fun_l28_n187(x) + end +end + +def fun_l27_n963(x) + if (x < 1) + fun_l28_n169(x) + else + fun_l28_n751(x) + end +end + +def fun_l27_n964(x) + if (x < 1) + fun_l28_n195(x) + else + fun_l28_n112(x) + end +end + +def fun_l27_n965(x) + if (x < 1) + fun_l28_n756(x) + else + fun_l28_n700(x) + end +end + +def fun_l27_n966(x) + if (x < 1) + fun_l28_n739(x) + else + fun_l28_n320(x) + end +end + +def fun_l27_n967(x) + if (x < 1) + fun_l28_n693(x) + else + fun_l28_n101(x) + end +end + +def fun_l27_n968(x) + if (x < 1) + fun_l28_n94(x) + else + fun_l28_n131(x) + end +end + +def fun_l27_n969(x) + if (x < 1) + fun_l28_n142(x) + else + fun_l28_n839(x) + end +end + +def fun_l27_n970(x) + if (x < 1) + fun_l28_n792(x) + else + fun_l28_n243(x) + end +end + +def fun_l27_n971(x) + if (x < 1) + fun_l28_n268(x) + else + fun_l28_n525(x) + end +end + +def fun_l27_n972(x) + if (x < 1) + fun_l28_n776(x) + else + fun_l28_n117(x) + end +end + +def fun_l27_n973(x) + if (x < 1) + fun_l28_n401(x) + else + fun_l28_n571(x) + end +end + +def fun_l27_n974(x) + if (x < 1) + fun_l28_n515(x) + else + fun_l28_n5(x) + end +end + +def fun_l27_n975(x) + if (x < 1) + fun_l28_n225(x) + else + fun_l28_n956(x) + end +end + +def fun_l27_n976(x) + if (x < 1) + fun_l28_n536(x) + else + fun_l28_n379(x) + end +end + +def fun_l27_n977(x) + if (x < 1) + fun_l28_n942(x) + else + fun_l28_n665(x) + end +end + +def fun_l27_n978(x) + if (x < 1) + fun_l28_n753(x) + else + fun_l28_n807(x) + end +end + +def fun_l27_n979(x) + if (x < 1) + fun_l28_n206(x) + else + fun_l28_n548(x) + end +end + +def fun_l27_n980(x) + if (x < 1) + fun_l28_n149(x) + else + fun_l28_n126(x) + end +end + +def fun_l27_n981(x) + if (x < 1) + fun_l28_n829(x) + else + fun_l28_n384(x) + end +end + +def fun_l27_n982(x) + if (x < 1) + fun_l28_n764(x) + else + fun_l28_n554(x) + end +end + +def fun_l27_n983(x) + if (x < 1) + fun_l28_n868(x) + else + fun_l28_n933(x) + end +end + +def fun_l27_n984(x) + if (x < 1) + fun_l28_n627(x) + else + fun_l28_n791(x) + end +end + +def fun_l27_n985(x) + if (x < 1) + fun_l28_n796(x) + else + fun_l28_n352(x) + end +end + +def fun_l27_n986(x) + if (x < 1) + fun_l28_n213(x) + else + fun_l28_n282(x) + end +end + +def fun_l27_n987(x) + if (x < 1) + fun_l28_n403(x) + else + fun_l28_n504(x) + end +end + +def fun_l27_n988(x) + if (x < 1) + fun_l28_n78(x) + else + fun_l28_n283(x) + end +end + +def fun_l27_n989(x) + if (x < 1) + fun_l28_n364(x) + else + fun_l28_n802(x) + end +end + +def fun_l27_n990(x) + if (x < 1) + fun_l28_n508(x) + else + fun_l28_n561(x) + end +end + +def fun_l27_n991(x) + if (x < 1) + fun_l28_n922(x) + else + fun_l28_n901(x) + end +end + +def fun_l27_n992(x) + if (x < 1) + fun_l28_n103(x) + else + fun_l28_n275(x) + end +end + +def fun_l27_n993(x) + if (x < 1) + fun_l28_n566(x) + else + fun_l28_n88(x) + end +end + +def fun_l27_n994(x) + if (x < 1) + fun_l28_n174(x) + else + fun_l28_n741(x) + end +end + +def fun_l27_n995(x) + if (x < 1) + fun_l28_n40(x) + else + fun_l28_n426(x) + end +end + +def fun_l27_n996(x) + if (x < 1) + fun_l28_n941(x) + else + fun_l28_n941(x) + end +end + +def fun_l27_n997(x) + if (x < 1) + fun_l28_n651(x) + else + fun_l28_n301(x) + end +end + +def fun_l27_n998(x) + if (x < 1) + fun_l28_n789(x) + else + fun_l28_n720(x) + end +end + +def fun_l27_n999(x) + if (x < 1) + fun_l28_n536(x) + else + fun_l28_n903(x) + end +end + +def fun_l28_n0(x) + if (x < 1) + fun_l29_n585(x) + else + fun_l29_n979(x) + end +end + +def fun_l28_n1(x) + if (x < 1) + fun_l29_n182(x) + else + fun_l29_n513(x) + end +end + +def fun_l28_n2(x) + if (x < 1) + fun_l29_n975(x) + else + fun_l29_n445(x) + end +end + +def fun_l28_n3(x) + if (x < 1) + fun_l29_n7(x) + else + fun_l29_n958(x) + end +end + +def fun_l28_n4(x) + if (x < 1) + fun_l29_n751(x) + else + fun_l29_n426(x) + end +end + +def fun_l28_n5(x) + if (x < 1) + fun_l29_n29(x) + else + fun_l29_n840(x) + end +end + +def fun_l28_n6(x) + if (x < 1) + fun_l29_n571(x) + else + fun_l29_n971(x) + end +end + +def fun_l28_n7(x) + if (x < 1) + fun_l29_n384(x) + else + fun_l29_n495(x) + end +end + +def fun_l28_n8(x) + if (x < 1) + fun_l29_n185(x) + else + fun_l29_n507(x) + end +end + +def fun_l28_n9(x) + if (x < 1) + fun_l29_n496(x) + else + fun_l29_n241(x) + end +end + +def fun_l28_n10(x) + if (x < 1) + fun_l29_n494(x) + else + fun_l29_n473(x) + end +end + +def fun_l28_n11(x) + if (x < 1) + fun_l29_n851(x) + else + fun_l29_n809(x) + end +end + +def fun_l28_n12(x) + if (x < 1) + fun_l29_n875(x) + else + fun_l29_n135(x) + end +end + +def fun_l28_n13(x) + if (x < 1) + fun_l29_n957(x) + else + fun_l29_n337(x) + end +end + +def fun_l28_n14(x) + if (x < 1) + fun_l29_n82(x) + else + fun_l29_n901(x) + end +end + +def fun_l28_n15(x) + if (x < 1) + fun_l29_n608(x) + else + fun_l29_n334(x) + end +end + +def fun_l28_n16(x) + if (x < 1) + fun_l29_n772(x) + else + fun_l29_n912(x) + end +end + +def fun_l28_n17(x) + if (x < 1) + fun_l29_n971(x) + else + fun_l29_n127(x) + end +end + +def fun_l28_n18(x) + if (x < 1) + fun_l29_n667(x) + else + fun_l29_n347(x) + end +end + +def fun_l28_n19(x) + if (x < 1) + fun_l29_n453(x) + else + fun_l29_n39(x) + end +end + +def fun_l28_n20(x) + if (x < 1) + fun_l29_n853(x) + else + fun_l29_n747(x) + end +end + +def fun_l28_n21(x) + if (x < 1) + fun_l29_n433(x) + else + fun_l29_n298(x) + end +end + +def fun_l28_n22(x) + if (x < 1) + fun_l29_n94(x) + else + fun_l29_n307(x) + end +end + +def fun_l28_n23(x) + if (x < 1) + fun_l29_n424(x) + else + fun_l29_n599(x) + end +end + +def fun_l28_n24(x) + if (x < 1) + fun_l29_n986(x) + else + fun_l29_n232(x) + end +end + +def fun_l28_n25(x) + if (x < 1) + fun_l29_n658(x) + else + fun_l29_n744(x) + end +end + +def fun_l28_n26(x) + if (x < 1) + fun_l29_n151(x) + else + fun_l29_n855(x) + end +end + +def fun_l28_n27(x) + if (x < 1) + fun_l29_n416(x) + else + fun_l29_n763(x) + end +end + +def fun_l28_n28(x) + if (x < 1) + fun_l29_n489(x) + else + fun_l29_n55(x) + end +end + +def fun_l28_n29(x) + if (x < 1) + fun_l29_n714(x) + else + fun_l29_n489(x) + end +end + +def fun_l28_n30(x) + if (x < 1) + fun_l29_n328(x) + else + fun_l29_n476(x) + end +end + +def fun_l28_n31(x) + if (x < 1) + fun_l29_n317(x) + else + fun_l29_n836(x) + end +end + +def fun_l28_n32(x) + if (x < 1) + fun_l29_n970(x) + else + fun_l29_n48(x) + end +end + +def fun_l28_n33(x) + if (x < 1) + fun_l29_n159(x) + else + fun_l29_n449(x) + end +end + +def fun_l28_n34(x) + if (x < 1) + fun_l29_n80(x) + else + fun_l29_n994(x) + end +end + +def fun_l28_n35(x) + if (x < 1) + fun_l29_n413(x) + else + fun_l29_n718(x) + end +end + +def fun_l28_n36(x) + if (x < 1) + fun_l29_n196(x) + else + fun_l29_n713(x) + end +end + +def fun_l28_n37(x) + if (x < 1) + fun_l29_n815(x) + else + fun_l29_n595(x) + end +end + +def fun_l28_n38(x) + if (x < 1) + fun_l29_n862(x) + else + fun_l29_n546(x) + end +end + +def fun_l28_n39(x) + if (x < 1) + fun_l29_n875(x) + else + fun_l29_n456(x) + end +end + +def fun_l28_n40(x) + if (x < 1) + fun_l29_n424(x) + else + fun_l29_n445(x) + end +end + +def fun_l28_n41(x) + if (x < 1) + fun_l29_n743(x) + else + fun_l29_n498(x) + end +end + +def fun_l28_n42(x) + if (x < 1) + fun_l29_n950(x) + else + fun_l29_n497(x) + end +end + +def fun_l28_n43(x) + if (x < 1) + fun_l29_n792(x) + else + fun_l29_n487(x) + end +end + +def fun_l28_n44(x) + if (x < 1) + fun_l29_n421(x) + else + fun_l29_n484(x) + end +end + +def fun_l28_n45(x) + if (x < 1) + fun_l29_n862(x) + else + fun_l29_n824(x) + end +end + +def fun_l28_n46(x) + if (x < 1) + fun_l29_n163(x) + else + fun_l29_n184(x) + end +end + +def fun_l28_n47(x) + if (x < 1) + fun_l29_n374(x) + else + fun_l29_n954(x) + end +end + +def fun_l28_n48(x) + if (x < 1) + fun_l29_n422(x) + else + fun_l29_n223(x) + end +end + +def fun_l28_n49(x) + if (x < 1) + fun_l29_n885(x) + else + fun_l29_n527(x) + end +end + +def fun_l28_n50(x) + if (x < 1) + fun_l29_n694(x) + else + fun_l29_n702(x) + end +end + +def fun_l28_n51(x) + if (x < 1) + fun_l29_n273(x) + else + fun_l29_n504(x) + end +end + +def fun_l28_n52(x) + if (x < 1) + fun_l29_n330(x) + else + fun_l29_n267(x) + end +end + +def fun_l28_n53(x) + if (x < 1) + fun_l29_n103(x) + else + fun_l29_n407(x) + end +end + +def fun_l28_n54(x) + if (x < 1) + fun_l29_n210(x) + else + fun_l29_n645(x) + end +end + +def fun_l28_n55(x) + if (x < 1) + fun_l29_n871(x) + else + fun_l29_n641(x) + end +end + +def fun_l28_n56(x) + if (x < 1) + fun_l29_n233(x) + else + fun_l29_n715(x) + end +end + +def fun_l28_n57(x) + if (x < 1) + fun_l29_n742(x) + else + fun_l29_n104(x) + end +end + +def fun_l28_n58(x) + if (x < 1) + fun_l29_n713(x) + else + fun_l29_n919(x) + end +end + +def fun_l28_n59(x) + if (x < 1) + fun_l29_n192(x) + else + fun_l29_n988(x) + end +end + +def fun_l28_n60(x) + if (x < 1) + fun_l29_n533(x) + else + fun_l29_n972(x) + end +end + +def fun_l28_n61(x) + if (x < 1) + fun_l29_n286(x) + else + fun_l29_n129(x) + end +end + +def fun_l28_n62(x) + if (x < 1) + fun_l29_n208(x) + else + fun_l29_n715(x) + end +end + +def fun_l28_n63(x) + if (x < 1) + fun_l29_n588(x) + else + fun_l29_n975(x) + end +end + +def fun_l28_n64(x) + if (x < 1) + fun_l29_n202(x) + else + fun_l29_n784(x) + end +end + +def fun_l28_n65(x) + if (x < 1) + fun_l29_n531(x) + else + fun_l29_n758(x) + end +end + +def fun_l28_n66(x) + if (x < 1) + fun_l29_n102(x) + else + fun_l29_n23(x) + end +end + +def fun_l28_n67(x) + if (x < 1) + fun_l29_n546(x) + else + fun_l29_n964(x) + end +end + +def fun_l28_n68(x) + if (x < 1) + fun_l29_n31(x) + else + fun_l29_n223(x) + end +end + +def fun_l28_n69(x) + if (x < 1) + fun_l29_n344(x) + else + fun_l29_n250(x) + end +end + +def fun_l28_n70(x) + if (x < 1) + fun_l29_n910(x) + else + fun_l29_n880(x) + end +end + +def fun_l28_n71(x) + if (x < 1) + fun_l29_n181(x) + else + fun_l29_n950(x) + end +end + +def fun_l28_n72(x) + if (x < 1) + fun_l29_n405(x) + else + fun_l29_n105(x) + end +end + +def fun_l28_n73(x) + if (x < 1) + fun_l29_n419(x) + else + fun_l29_n120(x) + end +end + +def fun_l28_n74(x) + if (x < 1) + fun_l29_n485(x) + else + fun_l29_n616(x) + end +end + +def fun_l28_n75(x) + if (x < 1) + fun_l29_n690(x) + else + fun_l29_n581(x) + end +end + +def fun_l28_n76(x) + if (x < 1) + fun_l29_n68(x) + else + fun_l29_n47(x) + end +end + +def fun_l28_n77(x) + if (x < 1) + fun_l29_n324(x) + else + fun_l29_n102(x) + end +end + +def fun_l28_n78(x) + if (x < 1) + fun_l29_n416(x) + else + fun_l29_n965(x) + end +end + +def fun_l28_n79(x) + if (x < 1) + fun_l29_n584(x) + else + fun_l29_n901(x) + end +end + +def fun_l28_n80(x) + if (x < 1) + fun_l29_n914(x) + else + fun_l29_n890(x) + end +end + +def fun_l28_n81(x) + if (x < 1) + fun_l29_n85(x) + else + fun_l29_n822(x) + end +end + +def fun_l28_n82(x) + if (x < 1) + fun_l29_n311(x) + else + fun_l29_n621(x) + end +end + +def fun_l28_n83(x) + if (x < 1) + fun_l29_n361(x) + else + fun_l29_n336(x) + end +end + +def fun_l28_n84(x) + if (x < 1) + fun_l29_n642(x) + else + fun_l29_n495(x) + end +end + +def fun_l28_n85(x) + if (x < 1) + fun_l29_n688(x) + else + fun_l29_n20(x) + end +end + +def fun_l28_n86(x) + if (x < 1) + fun_l29_n805(x) + else + fun_l29_n363(x) + end +end + +def fun_l28_n87(x) + if (x < 1) + fun_l29_n215(x) + else + fun_l29_n530(x) + end +end + +def fun_l28_n88(x) + if (x < 1) + fun_l29_n355(x) + else + fun_l29_n820(x) + end +end + +def fun_l28_n89(x) + if (x < 1) + fun_l29_n593(x) + else + fun_l29_n443(x) + end +end + +def fun_l28_n90(x) + if (x < 1) + fun_l29_n917(x) + else + fun_l29_n920(x) + end +end + +def fun_l28_n91(x) + if (x < 1) + fun_l29_n571(x) + else + fun_l29_n545(x) + end +end + +def fun_l28_n92(x) + if (x < 1) + fun_l29_n871(x) + else + fun_l29_n497(x) + end +end + +def fun_l28_n93(x) + if (x < 1) + fun_l29_n433(x) + else + fun_l29_n899(x) + end +end + +def fun_l28_n94(x) + if (x < 1) + fun_l29_n139(x) + else + fun_l29_n836(x) + end +end + +def fun_l28_n95(x) + if (x < 1) + fun_l29_n265(x) + else + fun_l29_n297(x) + end +end + +def fun_l28_n96(x) + if (x < 1) + fun_l29_n554(x) + else + fun_l29_n345(x) + end +end + +def fun_l28_n97(x) + if (x < 1) + fun_l29_n674(x) + else + fun_l29_n632(x) + end +end + +def fun_l28_n98(x) + if (x < 1) + fun_l29_n287(x) + else + fun_l29_n606(x) + end +end + +def fun_l28_n99(x) + if (x < 1) + fun_l29_n288(x) + else + fun_l29_n751(x) + end +end + +def fun_l28_n100(x) + if (x < 1) + fun_l29_n673(x) + else + fun_l29_n461(x) + end +end + +def fun_l28_n101(x) + if (x < 1) + fun_l29_n633(x) + else + fun_l29_n688(x) + end +end + +def fun_l28_n102(x) + if (x < 1) + fun_l29_n487(x) + else + fun_l29_n879(x) + end +end + +def fun_l28_n103(x) + if (x < 1) + fun_l29_n12(x) + else + fun_l29_n808(x) + end +end + +def fun_l28_n104(x) + if (x < 1) + fun_l29_n560(x) + else + fun_l29_n174(x) + end +end + +def fun_l28_n105(x) + if (x < 1) + fun_l29_n379(x) + else + fun_l29_n509(x) + end +end + +def fun_l28_n106(x) + if (x < 1) + fun_l29_n848(x) + else + fun_l29_n783(x) + end +end + +def fun_l28_n107(x) + if (x < 1) + fun_l29_n564(x) + else + fun_l29_n584(x) + end +end + +def fun_l28_n108(x) + if (x < 1) + fun_l29_n251(x) + else + fun_l29_n77(x) + end +end + +def fun_l28_n109(x) + if (x < 1) + fun_l29_n588(x) + else + fun_l29_n351(x) + end +end + +def fun_l28_n110(x) + if (x < 1) + fun_l29_n43(x) + else + fun_l29_n102(x) + end +end + +def fun_l28_n111(x) + if (x < 1) + fun_l29_n33(x) + else + fun_l29_n168(x) + end +end + +def fun_l28_n112(x) + if (x < 1) + fun_l29_n977(x) + else + fun_l29_n832(x) + end +end + +def fun_l28_n113(x) + if (x < 1) + fun_l29_n189(x) + else + fun_l29_n657(x) + end +end + +def fun_l28_n114(x) + if (x < 1) + fun_l29_n833(x) + else + fun_l29_n237(x) + end +end + +def fun_l28_n115(x) + if (x < 1) + fun_l29_n621(x) + else + fun_l29_n675(x) + end +end + +def fun_l28_n116(x) + if (x < 1) + fun_l29_n944(x) + else + fun_l29_n469(x) + end +end + +def fun_l28_n117(x) + if (x < 1) + fun_l29_n2(x) + else + fun_l29_n959(x) + end +end + +def fun_l28_n118(x) + if (x < 1) + fun_l29_n260(x) + else + fun_l29_n580(x) + end +end + +def fun_l28_n119(x) + if (x < 1) + fun_l29_n464(x) + else + fun_l29_n411(x) + end +end + +def fun_l28_n120(x) + if (x < 1) + fun_l29_n973(x) + else + fun_l29_n837(x) + end +end + +def fun_l28_n121(x) + if (x < 1) + fun_l29_n511(x) + else + fun_l29_n896(x) + end +end + +def fun_l28_n122(x) + if (x < 1) + fun_l29_n621(x) + else + fun_l29_n952(x) + end +end + +def fun_l28_n123(x) + if (x < 1) + fun_l29_n250(x) + else + fun_l29_n551(x) + end +end + +def fun_l28_n124(x) + if (x < 1) + fun_l29_n761(x) + else + fun_l29_n659(x) + end +end + +def fun_l28_n125(x) + if (x < 1) + fun_l29_n43(x) + else + fun_l29_n265(x) + end +end + +def fun_l28_n126(x) + if (x < 1) + fun_l29_n794(x) + else + fun_l29_n953(x) + end +end + +def fun_l28_n127(x) + if (x < 1) + fun_l29_n858(x) + else + fun_l29_n582(x) + end +end + +def fun_l28_n128(x) + if (x < 1) + fun_l29_n762(x) + else + fun_l29_n710(x) + end +end + +def fun_l28_n129(x) + if (x < 1) + fun_l29_n541(x) + else + fun_l29_n182(x) + end +end + +def fun_l28_n130(x) + if (x < 1) + fun_l29_n325(x) + else + fun_l29_n318(x) + end +end + +def fun_l28_n131(x) + if (x < 1) + fun_l29_n751(x) + else + fun_l29_n499(x) + end +end + +def fun_l28_n132(x) + if (x < 1) + fun_l29_n185(x) + else + fun_l29_n547(x) + end +end + +def fun_l28_n133(x) + if (x < 1) + fun_l29_n155(x) + else + fun_l29_n691(x) + end +end + +def fun_l28_n134(x) + if (x < 1) + fun_l29_n326(x) + else + fun_l29_n950(x) + end +end + +def fun_l28_n135(x) + if (x < 1) + fun_l29_n782(x) + else + fun_l29_n968(x) + end +end + +def fun_l28_n136(x) + if (x < 1) + fun_l29_n349(x) + else + fun_l29_n668(x) + end +end + +def fun_l28_n137(x) + if (x < 1) + fun_l29_n897(x) + else + fun_l29_n243(x) + end +end + +def fun_l28_n138(x) + if (x < 1) + fun_l29_n994(x) + else + fun_l29_n84(x) + end +end + +def fun_l28_n139(x) + if (x < 1) + fun_l29_n95(x) + else + fun_l29_n705(x) + end +end + +def fun_l28_n140(x) + if (x < 1) + fun_l29_n864(x) + else + fun_l29_n636(x) + end +end + +def fun_l28_n141(x) + if (x < 1) + fun_l29_n587(x) + else + fun_l29_n908(x) + end +end + +def fun_l28_n142(x) + if (x < 1) + fun_l29_n255(x) + else + fun_l29_n633(x) + end +end + +def fun_l28_n143(x) + if (x < 1) + fun_l29_n142(x) + else + fun_l29_n305(x) + end +end + +def fun_l28_n144(x) + if (x < 1) + fun_l29_n735(x) + else + fun_l29_n637(x) + end +end + +def fun_l28_n145(x) + if (x < 1) + fun_l29_n637(x) + else + fun_l29_n975(x) + end +end + +def fun_l28_n146(x) + if (x < 1) + fun_l29_n560(x) + else + fun_l29_n534(x) + end +end + +def fun_l28_n147(x) + if (x < 1) + fun_l29_n829(x) + else + fun_l29_n344(x) + end +end + +def fun_l28_n148(x) + if (x < 1) + fun_l29_n38(x) + else + fun_l29_n339(x) + end +end + +def fun_l28_n149(x) + if (x < 1) + fun_l29_n178(x) + else + fun_l29_n178(x) + end +end + +def fun_l28_n150(x) + if (x < 1) + fun_l29_n434(x) + else + fun_l29_n677(x) + end +end + +def fun_l28_n151(x) + if (x < 1) + fun_l29_n910(x) + else + fun_l29_n230(x) + end +end + +def fun_l28_n152(x) + if (x < 1) + fun_l29_n750(x) + else + fun_l29_n534(x) + end +end + +def fun_l28_n153(x) + if (x < 1) + fun_l29_n550(x) + else + fun_l29_n757(x) + end +end + +def fun_l28_n154(x) + if (x < 1) + fun_l29_n832(x) + else + fun_l29_n177(x) + end +end + +def fun_l28_n155(x) + if (x < 1) + fun_l29_n724(x) + else + fun_l29_n669(x) + end +end + +def fun_l28_n156(x) + if (x < 1) + fun_l29_n362(x) + else + fun_l29_n882(x) + end +end + +def fun_l28_n157(x) + if (x < 1) + fun_l29_n164(x) + else + fun_l29_n919(x) + end +end + +def fun_l28_n158(x) + if (x < 1) + fun_l29_n300(x) + else + fun_l29_n343(x) + end +end + +def fun_l28_n159(x) + if (x < 1) + fun_l29_n395(x) + else + fun_l29_n535(x) + end +end + +def fun_l28_n160(x) + if (x < 1) + fun_l29_n127(x) + else + fun_l29_n666(x) + end +end + +def fun_l28_n161(x) + if (x < 1) + fun_l29_n207(x) + else + fun_l29_n935(x) + end +end + +def fun_l28_n162(x) + if (x < 1) + fun_l29_n865(x) + else + fun_l29_n692(x) + end +end + +def fun_l28_n163(x) + if (x < 1) + fun_l29_n429(x) + else + fun_l29_n329(x) + end +end + +def fun_l28_n164(x) + if (x < 1) + fun_l29_n874(x) + else + fun_l29_n650(x) + end +end + +def fun_l28_n165(x) + if (x < 1) + fun_l29_n985(x) + else + fun_l29_n488(x) + end +end + +def fun_l28_n166(x) + if (x < 1) + fun_l29_n425(x) + else + fun_l29_n297(x) + end +end + +def fun_l28_n167(x) + if (x < 1) + fun_l29_n468(x) + else + fun_l29_n331(x) + end +end + +def fun_l28_n168(x) + if (x < 1) + fun_l29_n991(x) + else + fun_l29_n399(x) + end +end + +def fun_l28_n169(x) + if (x < 1) + fun_l29_n402(x) + else + fun_l29_n931(x) + end +end + +def fun_l28_n170(x) + if (x < 1) + fun_l29_n984(x) + else + fun_l29_n586(x) + end +end + +def fun_l28_n171(x) + if (x < 1) + fun_l29_n305(x) + else + fun_l29_n638(x) + end +end + +def fun_l28_n172(x) + if (x < 1) + fun_l29_n251(x) + else + fun_l29_n94(x) + end +end + +def fun_l28_n173(x) + if (x < 1) + fun_l29_n225(x) + else + fun_l29_n466(x) + end +end + +def fun_l28_n174(x) + if (x < 1) + fun_l29_n643(x) + else + fun_l29_n974(x) + end +end + +def fun_l28_n175(x) + if (x < 1) + fun_l29_n634(x) + else + fun_l29_n321(x) + end +end + +def fun_l28_n176(x) + if (x < 1) + fun_l29_n269(x) + else + fun_l29_n237(x) + end +end + +def fun_l28_n177(x) + if (x < 1) + fun_l29_n649(x) + else + fun_l29_n661(x) + end +end + +def fun_l28_n178(x) + if (x < 1) + fun_l29_n919(x) + else + fun_l29_n997(x) + end +end + +def fun_l28_n179(x) + if (x < 1) + fun_l29_n634(x) + else + fun_l29_n967(x) + end +end + +def fun_l28_n180(x) + if (x < 1) + fun_l29_n798(x) + else + fun_l29_n733(x) + end +end + +def fun_l28_n181(x) + if (x < 1) + fun_l29_n975(x) + else + fun_l29_n28(x) + end +end + +def fun_l28_n182(x) + if (x < 1) + fun_l29_n973(x) + else + fun_l29_n616(x) + end +end + +def fun_l28_n183(x) + if (x < 1) + fun_l29_n360(x) + else + fun_l29_n18(x) + end +end + +def fun_l28_n184(x) + if (x < 1) + fun_l29_n281(x) + else + fun_l29_n271(x) + end +end + +def fun_l28_n185(x) + if (x < 1) + fun_l29_n216(x) + else + fun_l29_n193(x) + end +end + +def fun_l28_n186(x) + if (x < 1) + fun_l29_n262(x) + else + fun_l29_n509(x) + end +end + +def fun_l28_n187(x) + if (x < 1) + fun_l29_n160(x) + else + fun_l29_n770(x) + end +end + +def fun_l28_n188(x) + if (x < 1) + fun_l29_n411(x) + else + fun_l29_n605(x) + end +end + +def fun_l28_n189(x) + if (x < 1) + fun_l29_n397(x) + else + fun_l29_n205(x) + end +end + +def fun_l28_n190(x) + if (x < 1) + fun_l29_n529(x) + else + fun_l29_n545(x) + end +end + +def fun_l28_n191(x) + if (x < 1) + fun_l29_n528(x) + else + fun_l29_n472(x) + end +end + +def fun_l28_n192(x) + if (x < 1) + fun_l29_n843(x) + else + fun_l29_n88(x) + end +end + +def fun_l28_n193(x) + if (x < 1) + fun_l29_n827(x) + else + fun_l29_n6(x) + end +end + +def fun_l28_n194(x) + if (x < 1) + fun_l29_n567(x) + else + fun_l29_n622(x) + end +end + +def fun_l28_n195(x) + if (x < 1) + fun_l29_n799(x) + else + fun_l29_n605(x) + end +end + +def fun_l28_n196(x) + if (x < 1) + fun_l29_n930(x) + else + fun_l29_n643(x) + end +end + +def fun_l28_n197(x) + if (x < 1) + fun_l29_n445(x) + else + fun_l29_n226(x) + end +end + +def fun_l28_n198(x) + if (x < 1) + fun_l29_n453(x) + else + fun_l29_n941(x) + end +end + +def fun_l28_n199(x) + if (x < 1) + fun_l29_n40(x) + else + fun_l29_n602(x) + end +end + +def fun_l28_n200(x) + if (x < 1) + fun_l29_n804(x) + else + fun_l29_n355(x) + end +end + +def fun_l28_n201(x) + if (x < 1) + fun_l29_n894(x) + else + fun_l29_n749(x) + end +end + +def fun_l28_n202(x) + if (x < 1) + fun_l29_n105(x) + else + fun_l29_n182(x) + end +end + +def fun_l28_n203(x) + if (x < 1) + fun_l29_n106(x) + else + fun_l29_n670(x) + end +end + +def fun_l28_n204(x) + if (x < 1) + fun_l29_n897(x) + else + fun_l29_n337(x) + end +end + +def fun_l28_n205(x) + if (x < 1) + fun_l29_n149(x) + else + fun_l29_n822(x) + end +end + +def fun_l28_n206(x) + if (x < 1) + fun_l29_n2(x) + else + fun_l29_n370(x) + end +end + +def fun_l28_n207(x) + if (x < 1) + fun_l29_n430(x) + else + fun_l29_n262(x) + end +end + +def fun_l28_n208(x) + if (x < 1) + fun_l29_n275(x) + else + fun_l29_n156(x) + end +end + +def fun_l28_n209(x) + if (x < 1) + fun_l29_n677(x) + else + fun_l29_n620(x) + end +end + +def fun_l28_n210(x) + if (x < 1) + fun_l29_n732(x) + else + fun_l29_n533(x) + end +end + +def fun_l28_n211(x) + if (x < 1) + fun_l29_n934(x) + else + fun_l29_n334(x) + end +end + +def fun_l28_n212(x) + if (x < 1) + fun_l29_n656(x) + else + fun_l29_n889(x) + end +end + +def fun_l28_n213(x) + if (x < 1) + fun_l29_n210(x) + else + fun_l29_n225(x) + end +end + +def fun_l28_n214(x) + if (x < 1) + fun_l29_n496(x) + else + fun_l29_n901(x) + end +end + +def fun_l28_n215(x) + if (x < 1) + fun_l29_n190(x) + else + fun_l29_n254(x) + end +end + +def fun_l28_n216(x) + if (x < 1) + fun_l29_n708(x) + else + fun_l29_n680(x) + end +end + +def fun_l28_n217(x) + if (x < 1) + fun_l29_n616(x) + else + fun_l29_n942(x) + end +end + +def fun_l28_n218(x) + if (x < 1) + fun_l29_n515(x) + else + fun_l29_n269(x) + end +end + +def fun_l28_n219(x) + if (x < 1) + fun_l29_n422(x) + else + fun_l29_n644(x) + end +end + +def fun_l28_n220(x) + if (x < 1) + fun_l29_n114(x) + else + fun_l29_n566(x) + end +end + +def fun_l28_n221(x) + if (x < 1) + fun_l29_n750(x) + else + fun_l29_n799(x) + end +end + +def fun_l28_n222(x) + if (x < 1) + fun_l29_n121(x) + else + fun_l29_n556(x) + end +end + +def fun_l28_n223(x) + if (x < 1) + fun_l29_n161(x) + else + fun_l29_n422(x) + end +end + +def fun_l28_n224(x) + if (x < 1) + fun_l29_n779(x) + else + fun_l29_n214(x) + end +end + +def fun_l28_n225(x) + if (x < 1) + fun_l29_n355(x) + else + fun_l29_n10(x) + end +end + +def fun_l28_n226(x) + if (x < 1) + fun_l29_n923(x) + else + fun_l29_n672(x) + end +end + +def fun_l28_n227(x) + if (x < 1) + fun_l29_n578(x) + else + fun_l29_n809(x) + end +end + +def fun_l28_n228(x) + if (x < 1) + fun_l29_n277(x) + else + fun_l29_n979(x) + end +end + +def fun_l28_n229(x) + if (x < 1) + fun_l29_n248(x) + else + fun_l29_n731(x) + end +end + +def fun_l28_n230(x) + if (x < 1) + fun_l29_n374(x) + else + fun_l29_n675(x) + end +end + +def fun_l28_n231(x) + if (x < 1) + fun_l29_n339(x) + else + fun_l29_n62(x) + end +end + +def fun_l28_n232(x) + if (x < 1) + fun_l29_n350(x) + else + fun_l29_n51(x) + end +end + +def fun_l28_n233(x) + if (x < 1) + fun_l29_n606(x) + else + fun_l29_n460(x) + end +end + +def fun_l28_n234(x) + if (x < 1) + fun_l29_n266(x) + else + fun_l29_n843(x) + end +end + +def fun_l28_n235(x) + if (x < 1) + fun_l29_n762(x) + else + fun_l29_n1(x) + end +end + +def fun_l28_n236(x) + if (x < 1) + fun_l29_n405(x) + else + fun_l29_n867(x) + end +end + +def fun_l28_n237(x) + if (x < 1) + fun_l29_n62(x) + else + fun_l29_n288(x) + end +end + +def fun_l28_n238(x) + if (x < 1) + fun_l29_n120(x) + else + fun_l29_n346(x) + end +end + +def fun_l28_n239(x) + if (x < 1) + fun_l29_n789(x) + else + fun_l29_n633(x) + end +end + +def fun_l28_n240(x) + if (x < 1) + fun_l29_n467(x) + else + fun_l29_n150(x) + end +end + +def fun_l28_n241(x) + if (x < 1) + fun_l29_n487(x) + else + fun_l29_n671(x) + end +end + +def fun_l28_n242(x) + if (x < 1) + fun_l29_n147(x) + else + fun_l29_n636(x) + end +end + +def fun_l28_n243(x) + if (x < 1) + fun_l29_n710(x) + else + fun_l29_n196(x) + end +end + +def fun_l28_n244(x) + if (x < 1) + fun_l29_n943(x) + else + fun_l29_n768(x) + end +end + +def fun_l28_n245(x) + if (x < 1) + fun_l29_n670(x) + else + fun_l29_n522(x) + end +end + +def fun_l28_n246(x) + if (x < 1) + fun_l29_n12(x) + else + fun_l29_n459(x) + end +end + +def fun_l28_n247(x) + if (x < 1) + fun_l29_n901(x) + else + fun_l29_n726(x) + end +end + +def fun_l28_n248(x) + if (x < 1) + fun_l29_n824(x) + else + fun_l29_n327(x) + end +end + +def fun_l28_n249(x) + if (x < 1) + fun_l29_n327(x) + else + fun_l29_n343(x) + end +end + +def fun_l28_n250(x) + if (x < 1) + fun_l29_n242(x) + else + fun_l29_n764(x) + end +end + +def fun_l28_n251(x) + if (x < 1) + fun_l29_n780(x) + else + fun_l29_n117(x) + end +end + +def fun_l28_n252(x) + if (x < 1) + fun_l29_n309(x) + else + fun_l29_n821(x) + end +end + +def fun_l28_n253(x) + if (x < 1) + fun_l29_n250(x) + else + fun_l29_n933(x) + end +end + +def fun_l28_n254(x) + if (x < 1) + fun_l29_n470(x) + else + fun_l29_n808(x) + end +end + +def fun_l28_n255(x) + if (x < 1) + fun_l29_n425(x) + else + fun_l29_n800(x) + end +end + +def fun_l28_n256(x) + if (x < 1) + fun_l29_n913(x) + else + fun_l29_n199(x) + end +end + +def fun_l28_n257(x) + if (x < 1) + fun_l29_n25(x) + else + fun_l29_n412(x) + end +end + +def fun_l28_n258(x) + if (x < 1) + fun_l29_n194(x) + else + fun_l29_n606(x) + end +end + +def fun_l28_n259(x) + if (x < 1) + fun_l29_n653(x) + else + fun_l29_n72(x) + end +end + +def fun_l28_n260(x) + if (x < 1) + fun_l29_n198(x) + else + fun_l29_n742(x) + end +end + +def fun_l28_n261(x) + if (x < 1) + fun_l29_n452(x) + else + fun_l29_n522(x) + end +end + +def fun_l28_n262(x) + if (x < 1) + fun_l29_n214(x) + else + fun_l29_n131(x) + end +end + +def fun_l28_n263(x) + if (x < 1) + fun_l29_n481(x) + else + fun_l29_n848(x) + end +end + +def fun_l28_n264(x) + if (x < 1) + fun_l29_n147(x) + else + fun_l29_n187(x) + end +end + +def fun_l28_n265(x) + if (x < 1) + fun_l29_n476(x) + else + fun_l29_n859(x) + end +end + +def fun_l28_n266(x) + if (x < 1) + fun_l29_n130(x) + else + fun_l29_n356(x) + end +end + +def fun_l28_n267(x) + if (x < 1) + fun_l29_n427(x) + else + fun_l29_n578(x) + end +end + +def fun_l28_n268(x) + if (x < 1) + fun_l29_n810(x) + else + fun_l29_n483(x) + end +end + +def fun_l28_n269(x) + if (x < 1) + fun_l29_n496(x) + else + fun_l29_n548(x) + end +end + +def fun_l28_n270(x) + if (x < 1) + fun_l29_n159(x) + else + fun_l29_n184(x) + end +end + +def fun_l28_n271(x) + if (x < 1) + fun_l29_n407(x) + else + fun_l29_n855(x) + end +end + +def fun_l28_n272(x) + if (x < 1) + fun_l29_n41(x) + else + fun_l29_n493(x) + end +end + +def fun_l28_n273(x) + if (x < 1) + fun_l29_n853(x) + else + fun_l29_n711(x) + end +end + +def fun_l28_n274(x) + if (x < 1) + fun_l29_n397(x) + else + fun_l29_n68(x) + end +end + +def fun_l28_n275(x) + if (x < 1) + fun_l29_n744(x) + else + fun_l29_n944(x) + end +end + +def fun_l28_n276(x) + if (x < 1) + fun_l29_n641(x) + else + fun_l29_n766(x) + end +end + +def fun_l28_n277(x) + if (x < 1) + fun_l29_n983(x) + else + fun_l29_n587(x) + end +end + +def fun_l28_n278(x) + if (x < 1) + fun_l29_n683(x) + else + fun_l29_n192(x) + end +end + +def fun_l28_n279(x) + if (x < 1) + fun_l29_n252(x) + else + fun_l29_n30(x) + end +end + +def fun_l28_n280(x) + if (x < 1) + fun_l29_n129(x) + else + fun_l29_n561(x) + end +end + +def fun_l28_n281(x) + if (x < 1) + fun_l29_n828(x) + else + fun_l29_n697(x) + end +end + +def fun_l28_n282(x) + if (x < 1) + fun_l29_n492(x) + else + fun_l29_n243(x) + end +end + +def fun_l28_n283(x) + if (x < 1) + fun_l29_n642(x) + else + fun_l29_n736(x) + end +end + +def fun_l28_n284(x) + if (x < 1) + fun_l29_n448(x) + else + fun_l29_n838(x) + end +end + +def fun_l28_n285(x) + if (x < 1) + fun_l29_n133(x) + else + fun_l29_n372(x) + end +end + +def fun_l28_n286(x) + if (x < 1) + fun_l29_n318(x) + else + fun_l29_n739(x) + end +end + +def fun_l28_n287(x) + if (x < 1) + fun_l29_n449(x) + else + fun_l29_n743(x) + end +end + +def fun_l28_n288(x) + if (x < 1) + fun_l29_n769(x) + else + fun_l29_n496(x) + end +end + +def fun_l28_n289(x) + if (x < 1) + fun_l29_n455(x) + else + fun_l29_n893(x) + end +end + +def fun_l28_n290(x) + if (x < 1) + fun_l29_n651(x) + else + fun_l29_n865(x) + end +end + +def fun_l28_n291(x) + if (x < 1) + fun_l29_n194(x) + else + fun_l29_n491(x) + end +end + +def fun_l28_n292(x) + if (x < 1) + fun_l29_n178(x) + else + fun_l29_n96(x) + end +end + +def fun_l28_n293(x) + if (x < 1) + fun_l29_n32(x) + else + fun_l29_n262(x) + end +end + +def fun_l28_n294(x) + if (x < 1) + fun_l29_n706(x) + else + fun_l29_n864(x) + end +end + +def fun_l28_n295(x) + if (x < 1) + fun_l29_n209(x) + else + fun_l29_n220(x) + end +end + +def fun_l28_n296(x) + if (x < 1) + fun_l29_n970(x) + else + fun_l29_n194(x) + end +end + +def fun_l28_n297(x) + if (x < 1) + fun_l29_n959(x) + else + fun_l29_n472(x) + end +end + +def fun_l28_n298(x) + if (x < 1) + fun_l29_n778(x) + else + fun_l29_n66(x) + end +end + +def fun_l28_n299(x) + if (x < 1) + fun_l29_n942(x) + else + fun_l29_n461(x) + end +end + +def fun_l28_n300(x) + if (x < 1) + fun_l29_n563(x) + else + fun_l29_n426(x) + end +end + +def fun_l28_n301(x) + if (x < 1) + fun_l29_n603(x) + else + fun_l29_n968(x) + end +end + +def fun_l28_n302(x) + if (x < 1) + fun_l29_n908(x) + else + fun_l29_n767(x) + end +end + +def fun_l28_n303(x) + if (x < 1) + fun_l29_n387(x) + else + fun_l29_n484(x) + end +end + +def fun_l28_n304(x) + if (x < 1) + fun_l29_n744(x) + else + fun_l29_n463(x) + end +end + +def fun_l28_n305(x) + if (x < 1) + fun_l29_n964(x) + else + fun_l29_n43(x) + end +end + +def fun_l28_n306(x) + if (x < 1) + fun_l29_n65(x) + else + fun_l29_n910(x) + end +end + +def fun_l28_n307(x) + if (x < 1) + fun_l29_n318(x) + else + fun_l29_n375(x) + end +end + +def fun_l28_n308(x) + if (x < 1) + fun_l29_n775(x) + else + fun_l29_n588(x) + end +end + +def fun_l28_n309(x) + if (x < 1) + fun_l29_n977(x) + else + fun_l29_n299(x) + end +end + +def fun_l28_n310(x) + if (x < 1) + fun_l29_n497(x) + else + fun_l29_n792(x) + end +end + +def fun_l28_n311(x) + if (x < 1) + fun_l29_n909(x) + else + fun_l29_n740(x) + end +end + +def fun_l28_n312(x) + if (x < 1) + fun_l29_n967(x) + else + fun_l29_n4(x) + end +end + +def fun_l28_n313(x) + if (x < 1) + fun_l29_n455(x) + else + fun_l29_n11(x) + end +end + +def fun_l28_n314(x) + if (x < 1) + fun_l29_n996(x) + else + fun_l29_n851(x) + end +end + +def fun_l28_n315(x) + if (x < 1) + fun_l29_n110(x) + else + fun_l29_n517(x) + end +end + +def fun_l28_n316(x) + if (x < 1) + fun_l29_n648(x) + else + fun_l29_n279(x) + end +end + +def fun_l28_n317(x) + if (x < 1) + fun_l29_n820(x) + else + fun_l29_n157(x) + end +end + +def fun_l28_n318(x) + if (x < 1) + fun_l29_n957(x) + else + fun_l29_n93(x) + end +end + +def fun_l28_n319(x) + if (x < 1) + fun_l29_n681(x) + else + fun_l29_n508(x) + end +end + +def fun_l28_n320(x) + if (x < 1) + fun_l29_n613(x) + else + fun_l29_n274(x) + end +end + +def fun_l28_n321(x) + if (x < 1) + fun_l29_n239(x) + else + fun_l29_n862(x) + end +end + +def fun_l28_n322(x) + if (x < 1) + fun_l29_n101(x) + else + fun_l29_n81(x) + end +end + +def fun_l28_n323(x) + if (x < 1) + fun_l29_n96(x) + else + fun_l29_n908(x) + end +end + +def fun_l28_n324(x) + if (x < 1) + fun_l29_n443(x) + else + fun_l29_n78(x) + end +end + +def fun_l28_n325(x) + if (x < 1) + fun_l29_n857(x) + else + fun_l29_n210(x) + end +end + +def fun_l28_n326(x) + if (x < 1) + fun_l29_n51(x) + else + fun_l29_n524(x) + end +end + +def fun_l28_n327(x) + if (x < 1) + fun_l29_n381(x) + else + fun_l29_n309(x) + end +end + +def fun_l28_n328(x) + if (x < 1) + fun_l29_n787(x) + else + fun_l29_n176(x) + end +end + +def fun_l28_n329(x) + if (x < 1) + fun_l29_n568(x) + else + fun_l29_n652(x) + end +end + +def fun_l28_n330(x) + if (x < 1) + fun_l29_n1(x) + else + fun_l29_n634(x) + end +end + +def fun_l28_n331(x) + if (x < 1) + fun_l29_n491(x) + else + fun_l29_n365(x) + end +end + +def fun_l28_n332(x) + if (x < 1) + fun_l29_n604(x) + else + fun_l29_n586(x) + end +end + +def fun_l28_n333(x) + if (x < 1) + fun_l29_n811(x) + else + fun_l29_n981(x) + end +end + +def fun_l28_n334(x) + if (x < 1) + fun_l29_n485(x) + else + fun_l29_n843(x) + end +end + +def fun_l28_n335(x) + if (x < 1) + fun_l29_n188(x) + else + fun_l29_n805(x) + end +end + +def fun_l28_n336(x) + if (x < 1) + fun_l29_n818(x) + else + fun_l29_n650(x) + end +end + +def fun_l28_n337(x) + if (x < 1) + fun_l29_n829(x) + else + fun_l29_n13(x) + end +end + +def fun_l28_n338(x) + if (x < 1) + fun_l29_n665(x) + else + fun_l29_n7(x) + end +end + +def fun_l28_n339(x) + if (x < 1) + fun_l29_n347(x) + else + fun_l29_n914(x) + end +end + +def fun_l28_n340(x) + if (x < 1) + fun_l29_n819(x) + else + fun_l29_n7(x) + end +end + +def fun_l28_n341(x) + if (x < 1) + fun_l29_n108(x) + else + fun_l29_n838(x) + end +end + +def fun_l28_n342(x) + if (x < 1) + fun_l29_n292(x) + else + fun_l29_n831(x) + end +end + +def fun_l28_n343(x) + if (x < 1) + fun_l29_n892(x) + else + fun_l29_n717(x) + end +end + +def fun_l28_n344(x) + if (x < 1) + fun_l29_n664(x) + else + fun_l29_n422(x) + end +end + +def fun_l28_n345(x) + if (x < 1) + fun_l29_n59(x) + else + fun_l29_n858(x) + end +end + +def fun_l28_n346(x) + if (x < 1) + fun_l29_n88(x) + else + fun_l29_n97(x) + end +end + +def fun_l28_n347(x) + if (x < 1) + fun_l29_n852(x) + else + fun_l29_n37(x) + end +end + +def fun_l28_n348(x) + if (x < 1) + fun_l29_n201(x) + else + fun_l29_n663(x) + end +end + +def fun_l28_n349(x) + if (x < 1) + fun_l29_n928(x) + else + fun_l29_n743(x) + end +end + +def fun_l28_n350(x) + if (x < 1) + fun_l29_n206(x) + else + fun_l29_n609(x) + end +end + +def fun_l28_n351(x) + if (x < 1) + fun_l29_n98(x) + else + fun_l29_n659(x) + end +end + +def fun_l28_n352(x) + if (x < 1) + fun_l29_n350(x) + else + fun_l29_n604(x) + end +end + +def fun_l28_n353(x) + if (x < 1) + fun_l29_n273(x) + else + fun_l29_n831(x) + end +end + +def fun_l28_n354(x) + if (x < 1) + fun_l29_n377(x) + else + fun_l29_n926(x) + end +end + +def fun_l28_n355(x) + if (x < 1) + fun_l29_n783(x) + else + fun_l29_n646(x) + end +end + +def fun_l28_n356(x) + if (x < 1) + fun_l29_n968(x) + else + fun_l29_n587(x) + end +end + +def fun_l28_n357(x) + if (x < 1) + fun_l29_n813(x) + else + fun_l29_n791(x) + end +end + +def fun_l28_n358(x) + if (x < 1) + fun_l29_n130(x) + else + fun_l29_n851(x) + end +end + +def fun_l28_n359(x) + if (x < 1) + fun_l29_n858(x) + else + fun_l29_n112(x) + end +end + +def fun_l28_n360(x) + if (x < 1) + fun_l29_n349(x) + else + fun_l29_n612(x) + end +end + +def fun_l28_n361(x) + if (x < 1) + fun_l29_n282(x) + else + fun_l29_n357(x) + end +end + +def fun_l28_n362(x) + if (x < 1) + fun_l29_n144(x) + else + fun_l29_n426(x) + end +end + +def fun_l28_n363(x) + if (x < 1) + fun_l29_n438(x) + else + fun_l29_n539(x) + end +end + +def fun_l28_n364(x) + if (x < 1) + fun_l29_n321(x) + else + fun_l29_n874(x) + end +end + +def fun_l28_n365(x) + if (x < 1) + fun_l29_n443(x) + else + fun_l29_n985(x) + end +end + +def fun_l28_n366(x) + if (x < 1) + fun_l29_n436(x) + else + fun_l29_n787(x) + end +end + +def fun_l28_n367(x) + if (x < 1) + fun_l29_n354(x) + else + fun_l29_n75(x) + end +end + +def fun_l28_n368(x) + if (x < 1) + fun_l29_n515(x) + else + fun_l29_n57(x) + end +end + +def fun_l28_n369(x) + if (x < 1) + fun_l29_n222(x) + else + fun_l29_n954(x) + end +end + +def fun_l28_n370(x) + if (x < 1) + fun_l29_n37(x) + else + fun_l29_n683(x) + end +end + +def fun_l28_n371(x) + if (x < 1) + fun_l29_n104(x) + else + fun_l29_n721(x) + end +end + +def fun_l28_n372(x) + if (x < 1) + fun_l29_n763(x) + else + fun_l29_n173(x) + end +end + +def fun_l28_n373(x) + if (x < 1) + fun_l29_n693(x) + else + fun_l29_n132(x) + end +end + +def fun_l28_n374(x) + if (x < 1) + fun_l29_n586(x) + else + fun_l29_n992(x) + end +end + +def fun_l28_n375(x) + if (x < 1) + fun_l29_n815(x) + else + fun_l29_n721(x) + end +end + +def fun_l28_n376(x) + if (x < 1) + fun_l29_n653(x) + else + fun_l29_n67(x) + end +end + +def fun_l28_n377(x) + if (x < 1) + fun_l29_n710(x) + else + fun_l29_n787(x) + end +end + +def fun_l28_n378(x) + if (x < 1) + fun_l29_n448(x) + else + fun_l29_n170(x) + end +end + +def fun_l28_n379(x) + if (x < 1) + fun_l29_n433(x) + else + fun_l29_n970(x) + end +end + +def fun_l28_n380(x) + if (x < 1) + fun_l29_n933(x) + else + fun_l29_n995(x) + end +end + +def fun_l28_n381(x) + if (x < 1) + fun_l29_n78(x) + else + fun_l29_n791(x) + end +end + +def fun_l28_n382(x) + if (x < 1) + fun_l29_n101(x) + else + fun_l29_n592(x) + end +end + +def fun_l28_n383(x) + if (x < 1) + fun_l29_n470(x) + else + fun_l29_n988(x) + end +end + +def fun_l28_n384(x) + if (x < 1) + fun_l29_n260(x) + else + fun_l29_n359(x) + end +end + +def fun_l28_n385(x) + if (x < 1) + fun_l29_n743(x) + else + fun_l29_n373(x) + end +end + +def fun_l28_n386(x) + if (x < 1) + fun_l29_n49(x) + else + fun_l29_n591(x) + end +end + +def fun_l28_n387(x) + if (x < 1) + fun_l29_n271(x) + else + fun_l29_n924(x) + end +end + +def fun_l28_n388(x) + if (x < 1) + fun_l29_n876(x) + else + fun_l29_n219(x) + end +end + +def fun_l28_n389(x) + if (x < 1) + fun_l29_n262(x) + else + fun_l29_n857(x) + end +end + +def fun_l28_n390(x) + if (x < 1) + fun_l29_n217(x) + else + fun_l29_n198(x) + end +end + +def fun_l28_n391(x) + if (x < 1) + fun_l29_n603(x) + else + fun_l29_n87(x) + end +end + +def fun_l28_n392(x) + if (x < 1) + fun_l29_n498(x) + else + fun_l29_n913(x) + end +end + +def fun_l28_n393(x) + if (x < 1) + fun_l29_n795(x) + else + fun_l29_n87(x) + end +end + +def fun_l28_n394(x) + if (x < 1) + fun_l29_n528(x) + else + fun_l29_n217(x) + end +end + +def fun_l28_n395(x) + if (x < 1) + fun_l29_n300(x) + else + fun_l29_n725(x) + end +end + +def fun_l28_n396(x) + if (x < 1) + fun_l29_n538(x) + else + fun_l29_n812(x) + end +end + +def fun_l28_n397(x) + if (x < 1) + fun_l29_n179(x) + else + fun_l29_n765(x) + end +end + +def fun_l28_n398(x) + if (x < 1) + fun_l29_n28(x) + else + fun_l29_n475(x) + end +end + +def fun_l28_n399(x) + if (x < 1) + fun_l29_n471(x) + else + fun_l29_n368(x) + end +end + +def fun_l28_n400(x) + if (x < 1) + fun_l29_n241(x) + else + fun_l29_n461(x) + end +end + +def fun_l28_n401(x) + if (x < 1) + fun_l29_n707(x) + else + fun_l29_n502(x) + end +end + +def fun_l28_n402(x) + if (x < 1) + fun_l29_n129(x) + else + fun_l29_n176(x) + end +end + +def fun_l28_n403(x) + if (x < 1) + fun_l29_n410(x) + else + fun_l29_n954(x) + end +end + +def fun_l28_n404(x) + if (x < 1) + fun_l29_n203(x) + else + fun_l29_n455(x) + end +end + +def fun_l28_n405(x) + if (x < 1) + fun_l29_n238(x) + else + fun_l29_n865(x) + end +end + +def fun_l28_n406(x) + if (x < 1) + fun_l29_n836(x) + else + fun_l29_n778(x) + end +end + +def fun_l28_n407(x) + if (x < 1) + fun_l29_n620(x) + else + fun_l29_n879(x) + end +end + +def fun_l28_n408(x) + if (x < 1) + fun_l29_n656(x) + else + fun_l29_n594(x) + end +end + +def fun_l28_n409(x) + if (x < 1) + fun_l29_n382(x) + else + fun_l29_n51(x) + end +end + +def fun_l28_n410(x) + if (x < 1) + fun_l29_n357(x) + else + fun_l29_n660(x) + end +end + +def fun_l28_n411(x) + if (x < 1) + fun_l29_n900(x) + else + fun_l29_n902(x) + end +end + +def fun_l28_n412(x) + if (x < 1) + fun_l29_n645(x) + else + fun_l29_n0(x) + end +end + +def fun_l28_n413(x) + if (x < 1) + fun_l29_n250(x) + else + fun_l29_n499(x) + end +end + +def fun_l28_n414(x) + if (x < 1) + fun_l29_n700(x) + else + fun_l29_n301(x) + end +end + +def fun_l28_n415(x) + if (x < 1) + fun_l29_n711(x) + else + fun_l29_n83(x) + end +end + +def fun_l28_n416(x) + if (x < 1) + fun_l29_n332(x) + else + fun_l29_n237(x) + end +end + +def fun_l28_n417(x) + if (x < 1) + fun_l29_n573(x) + else + fun_l29_n822(x) + end +end + +def fun_l28_n418(x) + if (x < 1) + fun_l29_n766(x) + else + fun_l29_n131(x) + end +end + +def fun_l28_n419(x) + if (x < 1) + fun_l29_n696(x) + else + fun_l29_n772(x) + end +end + +def fun_l28_n420(x) + if (x < 1) + fun_l29_n361(x) + else + fun_l29_n598(x) + end +end + +def fun_l28_n421(x) + if (x < 1) + fun_l29_n941(x) + else + fun_l29_n403(x) + end +end + +def fun_l28_n422(x) + if (x < 1) + fun_l29_n471(x) + else + fun_l29_n636(x) + end +end + +def fun_l28_n423(x) + if (x < 1) + fun_l29_n650(x) + else + fun_l29_n787(x) + end +end + +def fun_l28_n424(x) + if (x < 1) + fun_l29_n982(x) + else + fun_l29_n51(x) + end +end + +def fun_l28_n425(x) + if (x < 1) + fun_l29_n140(x) + else + fun_l29_n255(x) + end +end + +def fun_l28_n426(x) + if (x < 1) + fun_l29_n694(x) + else + fun_l29_n777(x) + end +end + +def fun_l28_n427(x) + if (x < 1) + fun_l29_n984(x) + else + fun_l29_n118(x) + end +end + +def fun_l28_n428(x) + if (x < 1) + fun_l29_n641(x) + else + fun_l29_n904(x) + end +end + +def fun_l28_n429(x) + if (x < 1) + fun_l29_n537(x) + else + fun_l29_n950(x) + end +end + +def fun_l28_n430(x) + if (x < 1) + fun_l29_n844(x) + else + fun_l29_n350(x) + end +end + +def fun_l28_n431(x) + if (x < 1) + fun_l29_n223(x) + else + fun_l29_n711(x) + end +end + +def fun_l28_n432(x) + if (x < 1) + fun_l29_n287(x) + else + fun_l29_n424(x) + end +end + +def fun_l28_n433(x) + if (x < 1) + fun_l29_n447(x) + else + fun_l29_n253(x) + end +end + +def fun_l28_n434(x) + if (x < 1) + fun_l29_n484(x) + else + fun_l29_n377(x) + end +end + +def fun_l28_n435(x) + if (x < 1) + fun_l29_n899(x) + else + fun_l29_n385(x) + end +end + +def fun_l28_n436(x) + if (x < 1) + fun_l29_n13(x) + else + fun_l29_n910(x) + end +end + +def fun_l28_n437(x) + if (x < 1) + fun_l29_n431(x) + else + fun_l29_n505(x) + end +end + +def fun_l28_n438(x) + if (x < 1) + fun_l29_n974(x) + else + fun_l29_n162(x) + end +end + +def fun_l28_n439(x) + if (x < 1) + fun_l29_n833(x) + else + fun_l29_n26(x) + end +end + +def fun_l28_n440(x) + if (x < 1) + fun_l29_n576(x) + else + fun_l29_n783(x) + end +end + +def fun_l28_n441(x) + if (x < 1) + fun_l29_n580(x) + else + fun_l29_n476(x) + end +end + +def fun_l28_n442(x) + if (x < 1) + fun_l29_n415(x) + else + fun_l29_n695(x) + end +end + +def fun_l28_n443(x) + if (x < 1) + fun_l29_n279(x) + else + fun_l29_n442(x) + end +end + +def fun_l28_n444(x) + if (x < 1) + fun_l29_n784(x) + else + fun_l29_n25(x) + end +end + +def fun_l28_n445(x) + if (x < 1) + fun_l29_n682(x) + else + fun_l29_n632(x) + end +end + +def fun_l28_n446(x) + if (x < 1) + fun_l29_n793(x) + else + fun_l29_n199(x) + end +end + +def fun_l28_n447(x) + if (x < 1) + fun_l29_n885(x) + else + fun_l29_n590(x) + end +end + +def fun_l28_n448(x) + if (x < 1) + fun_l29_n457(x) + else + fun_l29_n664(x) + end +end + +def fun_l28_n449(x) + if (x < 1) + fun_l29_n272(x) + else + fun_l29_n207(x) + end +end + +def fun_l28_n450(x) + if (x < 1) + fun_l29_n73(x) + else + fun_l29_n598(x) + end +end + +def fun_l28_n451(x) + if (x < 1) + fun_l29_n674(x) + else + fun_l29_n305(x) + end +end + +def fun_l28_n452(x) + if (x < 1) + fun_l29_n97(x) + else + fun_l29_n472(x) + end +end + +def fun_l28_n453(x) + if (x < 1) + fun_l29_n995(x) + else + fun_l29_n156(x) + end +end + +def fun_l28_n454(x) + if (x < 1) + fun_l29_n890(x) + else + fun_l29_n885(x) + end +end + +def fun_l28_n455(x) + if (x < 1) + fun_l29_n481(x) + else + fun_l29_n712(x) + end +end + +def fun_l28_n456(x) + if (x < 1) + fun_l29_n34(x) + else + fun_l29_n186(x) + end +end + +def fun_l28_n457(x) + if (x < 1) + fun_l29_n767(x) + else + fun_l29_n769(x) + end +end + +def fun_l28_n458(x) + if (x < 1) + fun_l29_n185(x) + else + fun_l29_n55(x) + end +end + +def fun_l28_n459(x) + if (x < 1) + fun_l29_n826(x) + else + fun_l29_n954(x) + end +end + +def fun_l28_n460(x) + if (x < 1) + fun_l29_n111(x) + else + fun_l29_n374(x) + end +end + +def fun_l28_n461(x) + if (x < 1) + fun_l29_n988(x) + else + fun_l29_n719(x) + end +end + +def fun_l28_n462(x) + if (x < 1) + fun_l29_n355(x) + else + fun_l29_n772(x) + end +end + +def fun_l28_n463(x) + if (x < 1) + fun_l29_n348(x) + else + fun_l29_n973(x) + end +end + +def fun_l28_n464(x) + if (x < 1) + fun_l29_n466(x) + else + fun_l29_n661(x) + end +end + +def fun_l28_n465(x) + if (x < 1) + fun_l29_n95(x) + else + fun_l29_n300(x) + end +end + +def fun_l28_n466(x) + if (x < 1) + fun_l29_n373(x) + else + fun_l29_n425(x) + end +end + +def fun_l28_n467(x) + if (x < 1) + fun_l29_n669(x) + else + fun_l29_n990(x) + end +end + +def fun_l28_n468(x) + if (x < 1) + fun_l29_n908(x) + else + fun_l29_n416(x) + end +end + +def fun_l28_n469(x) + if (x < 1) + fun_l29_n795(x) + else + fun_l29_n7(x) + end +end + +def fun_l28_n470(x) + if (x < 1) + fun_l29_n660(x) + else + fun_l29_n938(x) + end +end + +def fun_l28_n471(x) + if (x < 1) + fun_l29_n816(x) + else + fun_l29_n857(x) + end +end + +def fun_l28_n472(x) + if (x < 1) + fun_l29_n685(x) + else + fun_l29_n631(x) + end +end + +def fun_l28_n473(x) + if (x < 1) + fun_l29_n521(x) + else + fun_l29_n21(x) + end +end + +def fun_l28_n474(x) + if (x < 1) + fun_l29_n994(x) + else + fun_l29_n888(x) + end +end + +def fun_l28_n475(x) + if (x < 1) + fun_l29_n819(x) + else + fun_l29_n735(x) + end +end + +def fun_l28_n476(x) + if (x < 1) + fun_l29_n809(x) + else + fun_l29_n265(x) + end +end + +def fun_l28_n477(x) + if (x < 1) + fun_l29_n99(x) + else + fun_l29_n484(x) + end +end + +def fun_l28_n478(x) + if (x < 1) + fun_l29_n985(x) + else + fun_l29_n922(x) + end +end + +def fun_l28_n479(x) + if (x < 1) + fun_l29_n502(x) + else + fun_l29_n475(x) + end +end + +def fun_l28_n480(x) + if (x < 1) + fun_l29_n104(x) + else + fun_l29_n168(x) + end +end + +def fun_l28_n481(x) + if (x < 1) + fun_l29_n176(x) + else + fun_l29_n736(x) + end +end + +def fun_l28_n482(x) + if (x < 1) + fun_l29_n817(x) + else + fun_l29_n155(x) + end +end + +def fun_l28_n483(x) + if (x < 1) + fun_l29_n162(x) + else + fun_l29_n45(x) + end +end + +def fun_l28_n484(x) + if (x < 1) + fun_l29_n733(x) + else + fun_l29_n438(x) + end +end + +def fun_l28_n485(x) + if (x < 1) + fun_l29_n323(x) + else + fun_l29_n410(x) + end +end + +def fun_l28_n486(x) + if (x < 1) + fun_l29_n141(x) + else + fun_l29_n327(x) + end +end + +def fun_l28_n487(x) + if (x < 1) + fun_l29_n122(x) + else + fun_l29_n280(x) + end +end + +def fun_l28_n488(x) + if (x < 1) + fun_l29_n966(x) + else + fun_l29_n407(x) + end +end + +def fun_l28_n489(x) + if (x < 1) + fun_l29_n826(x) + else + fun_l29_n852(x) + end +end + +def fun_l28_n490(x) + if (x < 1) + fun_l29_n823(x) + else + fun_l29_n724(x) + end +end + +def fun_l28_n491(x) + if (x < 1) + fun_l29_n291(x) + else + fun_l29_n151(x) + end +end + +def fun_l28_n492(x) + if (x < 1) + fun_l29_n944(x) + else + fun_l29_n663(x) + end +end + +def fun_l28_n493(x) + if (x < 1) + fun_l29_n552(x) + else + fun_l29_n954(x) + end +end + +def fun_l28_n494(x) + if (x < 1) + fun_l29_n622(x) + else + fun_l29_n378(x) + end +end + +def fun_l28_n495(x) + if (x < 1) + fun_l29_n824(x) + else + fun_l29_n377(x) + end +end + +def fun_l28_n496(x) + if (x < 1) + fun_l29_n939(x) + else + fun_l29_n927(x) + end +end + +def fun_l28_n497(x) + if (x < 1) + fun_l29_n760(x) + else + fun_l29_n215(x) + end +end + +def fun_l28_n498(x) + if (x < 1) + fun_l29_n208(x) + else + fun_l29_n256(x) + end +end + +def fun_l28_n499(x) + if (x < 1) + fun_l29_n19(x) + else + fun_l29_n956(x) + end +end + +def fun_l28_n500(x) + if (x < 1) + fun_l29_n963(x) + else + fun_l29_n322(x) + end +end + +def fun_l28_n501(x) + if (x < 1) + fun_l29_n564(x) + else + fun_l29_n261(x) + end +end + +def fun_l28_n502(x) + if (x < 1) + fun_l29_n105(x) + else + fun_l29_n82(x) + end +end + +def fun_l28_n503(x) + if (x < 1) + fun_l29_n165(x) + else + fun_l29_n101(x) + end +end + +def fun_l28_n504(x) + if (x < 1) + fun_l29_n619(x) + else + fun_l29_n453(x) + end +end + +def fun_l28_n505(x) + if (x < 1) + fun_l29_n20(x) + else + fun_l29_n329(x) + end +end + +def fun_l28_n506(x) + if (x < 1) + fun_l29_n889(x) + else + fun_l29_n392(x) + end +end + +def fun_l28_n507(x) + if (x < 1) + fun_l29_n824(x) + else + fun_l29_n709(x) + end +end + +def fun_l28_n508(x) + if (x < 1) + fun_l29_n838(x) + else + fun_l29_n384(x) + end +end + +def fun_l28_n509(x) + if (x < 1) + fun_l29_n364(x) + else + fun_l29_n789(x) + end +end + +def fun_l28_n510(x) + if (x < 1) + fun_l29_n824(x) + else + fun_l29_n4(x) + end +end + +def fun_l28_n511(x) + if (x < 1) + fun_l29_n481(x) + else + fun_l29_n883(x) + end +end + +def fun_l28_n512(x) + if (x < 1) + fun_l29_n842(x) + else + fun_l29_n959(x) + end +end + +def fun_l28_n513(x) + if (x < 1) + fun_l29_n989(x) + else + fun_l29_n400(x) + end +end + +def fun_l28_n514(x) + if (x < 1) + fun_l29_n952(x) + else + fun_l29_n245(x) + end +end + +def fun_l28_n515(x) + if (x < 1) + fun_l29_n966(x) + else + fun_l29_n91(x) + end +end + +def fun_l28_n516(x) + if (x < 1) + fun_l29_n489(x) + else + fun_l29_n280(x) + end +end + +def fun_l28_n517(x) + if (x < 1) + fun_l29_n128(x) + else + fun_l29_n722(x) + end +end + +def fun_l28_n518(x) + if (x < 1) + fun_l29_n429(x) + else + fun_l29_n412(x) + end +end + +def fun_l28_n519(x) + if (x < 1) + fun_l29_n884(x) + else + fun_l29_n993(x) + end +end + +def fun_l28_n520(x) + if (x < 1) + fun_l29_n470(x) + else + fun_l29_n308(x) + end +end + +def fun_l28_n521(x) + if (x < 1) + fun_l29_n583(x) + else + fun_l29_n683(x) + end +end + +def fun_l28_n522(x) + if (x < 1) + fun_l29_n400(x) + else + fun_l29_n643(x) + end +end + +def fun_l28_n523(x) + if (x < 1) + fun_l29_n750(x) + else + fun_l29_n388(x) + end +end + +def fun_l28_n524(x) + if (x < 1) + fun_l29_n252(x) + else + fun_l29_n426(x) + end +end + +def fun_l28_n525(x) + if (x < 1) + fun_l29_n51(x) + else + fun_l29_n720(x) + end +end + +def fun_l28_n526(x) + if (x < 1) + fun_l29_n633(x) + else + fun_l29_n160(x) + end +end + +def fun_l28_n527(x) + if (x < 1) + fun_l29_n507(x) + else + fun_l29_n630(x) + end +end + +def fun_l28_n528(x) + if (x < 1) + fun_l29_n53(x) + else + fun_l29_n189(x) + end +end + +def fun_l28_n529(x) + if (x < 1) + fun_l29_n191(x) + else + fun_l29_n767(x) + end +end + +def fun_l28_n530(x) + if (x < 1) + fun_l29_n265(x) + else + fun_l29_n130(x) + end +end + +def fun_l28_n531(x) + if (x < 1) + fun_l29_n936(x) + else + fun_l29_n270(x) + end +end + +def fun_l28_n532(x) + if (x < 1) + fun_l29_n910(x) + else + fun_l29_n144(x) + end +end + +def fun_l28_n533(x) + if (x < 1) + fun_l29_n155(x) + else + fun_l29_n947(x) + end +end + +def fun_l28_n534(x) + if (x < 1) + fun_l29_n977(x) + else + fun_l29_n372(x) + end +end + +def fun_l28_n535(x) + if (x < 1) + fun_l29_n728(x) + else + fun_l29_n657(x) + end +end + +def fun_l28_n536(x) + if (x < 1) + fun_l29_n360(x) + else + fun_l29_n154(x) + end +end + +def fun_l28_n537(x) + if (x < 1) + fun_l29_n934(x) + else + fun_l29_n93(x) + end +end + +def fun_l28_n538(x) + if (x < 1) + fun_l29_n254(x) + else + fun_l29_n201(x) + end +end + +def fun_l28_n539(x) + if (x < 1) + fun_l29_n310(x) + else + fun_l29_n104(x) + end +end + +def fun_l28_n540(x) + if (x < 1) + fun_l29_n197(x) + else + fun_l29_n332(x) + end +end + +def fun_l28_n541(x) + if (x < 1) + fun_l29_n144(x) + else + fun_l29_n519(x) + end +end + +def fun_l28_n542(x) + if (x < 1) + fun_l29_n582(x) + else + fun_l29_n257(x) + end +end + +def fun_l28_n543(x) + if (x < 1) + fun_l29_n984(x) + else + fun_l29_n375(x) + end +end + +def fun_l28_n544(x) + if (x < 1) + fun_l29_n201(x) + else + fun_l29_n746(x) + end +end + +def fun_l28_n545(x) + if (x < 1) + fun_l29_n530(x) + else + fun_l29_n209(x) + end +end + +def fun_l28_n546(x) + if (x < 1) + fun_l29_n764(x) + else + fun_l29_n858(x) + end +end + +def fun_l28_n547(x) + if (x < 1) + fun_l29_n830(x) + else + fun_l29_n58(x) + end +end + +def fun_l28_n548(x) + if (x < 1) + fun_l29_n746(x) + else + fun_l29_n374(x) + end +end + +def fun_l28_n549(x) + if (x < 1) + fun_l29_n923(x) + else + fun_l29_n489(x) + end +end + +def fun_l28_n550(x) + if (x < 1) + fun_l29_n188(x) + else + fun_l29_n866(x) + end +end + +def fun_l28_n551(x) + if (x < 1) + fun_l29_n959(x) + else + fun_l29_n493(x) + end +end + +def fun_l28_n552(x) + if (x < 1) + fun_l29_n568(x) + else + fun_l29_n747(x) + end +end + +def fun_l28_n553(x) + if (x < 1) + fun_l29_n972(x) + else + fun_l29_n507(x) + end +end + +def fun_l28_n554(x) + if (x < 1) + fun_l29_n557(x) + else + fun_l29_n765(x) + end +end + +def fun_l28_n555(x) + if (x < 1) + fun_l29_n430(x) + else + fun_l29_n941(x) + end +end + +def fun_l28_n556(x) + if (x < 1) + fun_l29_n631(x) + else + fun_l29_n384(x) + end +end + +def fun_l28_n557(x) + if (x < 1) + fun_l29_n681(x) + else + fun_l29_n976(x) + end +end + +def fun_l28_n558(x) + if (x < 1) + fun_l29_n326(x) + else + fun_l29_n481(x) + end +end + +def fun_l28_n559(x) + if (x < 1) + fun_l29_n882(x) + else + fun_l29_n129(x) + end +end + +def fun_l28_n560(x) + if (x < 1) + fun_l29_n471(x) + else + fun_l29_n156(x) + end +end + +def fun_l28_n561(x) + if (x < 1) + fun_l29_n692(x) + else + fun_l29_n968(x) + end +end + +def fun_l28_n562(x) + if (x < 1) + fun_l29_n207(x) + else + fun_l29_n251(x) + end +end + +def fun_l28_n563(x) + if (x < 1) + fun_l29_n519(x) + else + fun_l29_n749(x) + end +end + +def fun_l28_n564(x) + if (x < 1) + fun_l29_n609(x) + else + fun_l29_n657(x) + end +end + +def fun_l28_n565(x) + if (x < 1) + fun_l29_n100(x) + else + fun_l29_n932(x) + end +end + +def fun_l28_n566(x) + if (x < 1) + fun_l29_n499(x) + else + fun_l29_n455(x) + end +end + +def fun_l28_n567(x) + if (x < 1) + fun_l29_n486(x) + else + fun_l29_n13(x) + end +end + +def fun_l28_n568(x) + if (x < 1) + fun_l29_n855(x) + else + fun_l29_n809(x) + end +end + +def fun_l28_n569(x) + if (x < 1) + fun_l29_n295(x) + else + fun_l29_n576(x) + end +end + +def fun_l28_n570(x) + if (x < 1) + fun_l29_n354(x) + else + fun_l29_n430(x) + end +end + +def fun_l28_n571(x) + if (x < 1) + fun_l29_n307(x) + else + fun_l29_n560(x) + end +end + +def fun_l28_n572(x) + if (x < 1) + fun_l29_n528(x) + else + fun_l29_n642(x) + end +end + +def fun_l28_n573(x) + if (x < 1) + fun_l29_n552(x) + else + fun_l29_n421(x) + end +end + +def fun_l28_n574(x) + if (x < 1) + fun_l29_n238(x) + else + fun_l29_n471(x) + end +end + +def fun_l28_n575(x) + if (x < 1) + fun_l29_n748(x) + else + fun_l29_n381(x) + end +end + +def fun_l28_n576(x) + if (x < 1) + fun_l29_n75(x) + else + fun_l29_n994(x) + end +end + +def fun_l28_n577(x) + if (x < 1) + fun_l29_n159(x) + else + fun_l29_n923(x) + end +end + +def fun_l28_n578(x) + if (x < 1) + fun_l29_n657(x) + else + fun_l29_n984(x) + end +end + +def fun_l28_n579(x) + if (x < 1) + fun_l29_n150(x) + else + fun_l29_n887(x) + end +end + +def fun_l28_n580(x) + if (x < 1) + fun_l29_n362(x) + else + fun_l29_n574(x) + end +end + +def fun_l28_n581(x) + if (x < 1) + fun_l29_n95(x) + else + fun_l29_n258(x) + end +end + +def fun_l28_n582(x) + if (x < 1) + fun_l29_n123(x) + else + fun_l29_n501(x) + end +end + +def fun_l28_n583(x) + if (x < 1) + fun_l29_n934(x) + else + fun_l29_n94(x) + end +end + +def fun_l28_n584(x) + if (x < 1) + fun_l29_n764(x) + else + fun_l29_n350(x) + end +end + +def fun_l28_n585(x) + if (x < 1) + fun_l29_n328(x) + else + fun_l29_n483(x) + end +end + +def fun_l28_n586(x) + if (x < 1) + fun_l29_n533(x) + else + fun_l29_n956(x) + end +end + +def fun_l28_n587(x) + if (x < 1) + fun_l29_n632(x) + else + fun_l29_n243(x) + end +end + +def fun_l28_n588(x) + if (x < 1) + fun_l29_n897(x) + else + fun_l29_n894(x) + end +end + +def fun_l28_n589(x) + if (x < 1) + fun_l29_n867(x) + else + fun_l29_n68(x) + end +end + +def fun_l28_n590(x) + if (x < 1) + fun_l29_n266(x) + else + fun_l29_n763(x) + end +end + +def fun_l28_n591(x) + if (x < 1) + fun_l29_n104(x) + else + fun_l29_n940(x) + end +end + +def fun_l28_n592(x) + if (x < 1) + fun_l29_n409(x) + else + fun_l29_n561(x) + end +end + +def fun_l28_n593(x) + if (x < 1) + fun_l29_n485(x) + else + fun_l29_n780(x) + end +end + +def fun_l28_n594(x) + if (x < 1) + fun_l29_n925(x) + else + fun_l29_n581(x) + end +end + +def fun_l28_n595(x) + if (x < 1) + fun_l29_n566(x) + else + fun_l29_n288(x) + end +end + +def fun_l28_n596(x) + if (x < 1) + fun_l29_n166(x) + else + fun_l29_n702(x) + end +end + +def fun_l28_n597(x) + if (x < 1) + fun_l29_n82(x) + else + fun_l29_n815(x) + end +end + +def fun_l28_n598(x) + if (x < 1) + fun_l29_n913(x) + else + fun_l29_n623(x) + end +end + +def fun_l28_n599(x) + if (x < 1) + fun_l29_n431(x) + else + fun_l29_n216(x) + end +end + +def fun_l28_n600(x) + if (x < 1) + fun_l29_n260(x) + else + fun_l29_n907(x) + end +end + +def fun_l28_n601(x) + if (x < 1) + fun_l29_n232(x) + else + fun_l29_n504(x) + end +end + +def fun_l28_n602(x) + if (x < 1) + fun_l29_n25(x) + else + fun_l29_n844(x) + end +end + +def fun_l28_n603(x) + if (x < 1) + fun_l29_n997(x) + else + fun_l29_n821(x) + end +end + +def fun_l28_n604(x) + if (x < 1) + fun_l29_n732(x) + else + fun_l29_n301(x) + end +end + +def fun_l28_n605(x) + if (x < 1) + fun_l29_n971(x) + else + fun_l29_n522(x) + end +end + +def fun_l28_n606(x) + if (x < 1) + fun_l29_n518(x) + else + fun_l29_n874(x) + end +end + +def fun_l28_n607(x) + if (x < 1) + fun_l29_n104(x) + else + fun_l29_n529(x) + end +end + +def fun_l28_n608(x) + if (x < 1) + fun_l29_n662(x) + else + fun_l29_n830(x) + end +end + +def fun_l28_n609(x) + if (x < 1) + fun_l29_n521(x) + else + fun_l29_n944(x) + end +end + +def fun_l28_n610(x) + if (x < 1) + fun_l29_n231(x) + else + fun_l29_n92(x) + end +end + +def fun_l28_n611(x) + if (x < 1) + fun_l29_n290(x) + else + fun_l29_n261(x) + end +end + +def fun_l28_n612(x) + if (x < 1) + fun_l29_n490(x) + else + fun_l29_n621(x) + end +end + +def fun_l28_n613(x) + if (x < 1) + fun_l29_n131(x) + else + fun_l29_n946(x) + end +end + +def fun_l28_n614(x) + if (x < 1) + fun_l29_n34(x) + else + fun_l29_n159(x) + end +end + +def fun_l28_n615(x) + if (x < 1) + fun_l29_n811(x) + else + fun_l29_n895(x) + end +end + +def fun_l28_n616(x) + if (x < 1) + fun_l29_n713(x) + else + fun_l29_n686(x) + end +end + +def fun_l28_n617(x) + if (x < 1) + fun_l29_n650(x) + else + fun_l29_n256(x) + end +end + +def fun_l28_n618(x) + if (x < 1) + fun_l29_n815(x) + else + fun_l29_n537(x) + end +end + +def fun_l28_n619(x) + if (x < 1) + fun_l29_n739(x) + else + fun_l29_n735(x) + end +end + +def fun_l28_n620(x) + if (x < 1) + fun_l29_n857(x) + else + fun_l29_n863(x) + end +end + +def fun_l28_n621(x) + if (x < 1) + fun_l29_n81(x) + else + fun_l29_n755(x) + end +end + +def fun_l28_n622(x) + if (x < 1) + fun_l29_n841(x) + else + fun_l29_n597(x) + end +end + +def fun_l28_n623(x) + if (x < 1) + fun_l29_n87(x) + else + fun_l29_n676(x) + end +end + +def fun_l28_n624(x) + if (x < 1) + fun_l29_n67(x) + else + fun_l29_n883(x) + end +end + +def fun_l28_n625(x) + if (x < 1) + fun_l29_n223(x) + else + fun_l29_n139(x) + end +end + +def fun_l28_n626(x) + if (x < 1) + fun_l29_n351(x) + else + fun_l29_n11(x) + end +end + +def fun_l28_n627(x) + if (x < 1) + fun_l29_n281(x) + else + fun_l29_n138(x) + end +end + +def fun_l28_n628(x) + if (x < 1) + fun_l29_n118(x) + else + fun_l29_n44(x) + end +end + +def fun_l28_n629(x) + if (x < 1) + fun_l29_n55(x) + else + fun_l29_n249(x) + end +end + +def fun_l28_n630(x) + if (x < 1) + fun_l29_n636(x) + else + fun_l29_n717(x) + end +end + +def fun_l28_n631(x) + if (x < 1) + fun_l29_n88(x) + else + fun_l29_n670(x) + end +end + +def fun_l28_n632(x) + if (x < 1) + fun_l29_n311(x) + else + fun_l29_n337(x) + end +end + +def fun_l28_n633(x) + if (x < 1) + fun_l29_n67(x) + else + fun_l29_n12(x) + end +end + +def fun_l28_n634(x) + if (x < 1) + fun_l29_n581(x) + else + fun_l29_n618(x) + end +end + +def fun_l28_n635(x) + if (x < 1) + fun_l29_n709(x) + else + fun_l29_n120(x) + end +end + +def fun_l28_n636(x) + if (x < 1) + fun_l29_n904(x) + else + fun_l29_n987(x) + end +end + +def fun_l28_n637(x) + if (x < 1) + fun_l29_n274(x) + else + fun_l29_n219(x) + end +end + +def fun_l28_n638(x) + if (x < 1) + fun_l29_n444(x) + else + fun_l29_n609(x) + end +end + +def fun_l28_n639(x) + if (x < 1) + fun_l29_n473(x) + else + fun_l29_n433(x) + end +end + +def fun_l28_n640(x) + if (x < 1) + fun_l29_n344(x) + else + fun_l29_n59(x) + end +end + +def fun_l28_n641(x) + if (x < 1) + fun_l29_n973(x) + else + fun_l29_n506(x) + end +end + +def fun_l28_n642(x) + if (x < 1) + fun_l29_n387(x) + else + fun_l29_n347(x) + end +end + +def fun_l28_n643(x) + if (x < 1) + fun_l29_n138(x) + else + fun_l29_n597(x) + end +end + +def fun_l28_n644(x) + if (x < 1) + fun_l29_n622(x) + else + fun_l29_n276(x) + end +end + +def fun_l28_n645(x) + if (x < 1) + fun_l29_n454(x) + else + fun_l29_n930(x) + end +end + +def fun_l28_n646(x) + if (x < 1) + fun_l29_n586(x) + else + fun_l29_n3(x) + end +end + +def fun_l28_n647(x) + if (x < 1) + fun_l29_n508(x) + else + fun_l29_n489(x) + end +end + +def fun_l28_n648(x) + if (x < 1) + fun_l29_n549(x) + else + fun_l29_n57(x) + end +end + +def fun_l28_n649(x) + if (x < 1) + fun_l29_n32(x) + else + fun_l29_n487(x) + end +end + +def fun_l28_n650(x) + if (x < 1) + fun_l29_n567(x) + else + fun_l29_n733(x) + end +end + +def fun_l28_n651(x) + if (x < 1) + fun_l29_n401(x) + else + fun_l29_n234(x) + end +end + +def fun_l28_n652(x) + if (x < 1) + fun_l29_n124(x) + else + fun_l29_n387(x) + end +end + +def fun_l28_n653(x) + if (x < 1) + fun_l29_n517(x) + else + fun_l29_n150(x) + end +end + +def fun_l28_n654(x) + if (x < 1) + fun_l29_n502(x) + else + fun_l29_n139(x) + end +end + +def fun_l28_n655(x) + if (x < 1) + fun_l29_n304(x) + else + fun_l29_n871(x) + end +end + +def fun_l28_n656(x) + if (x < 1) + fun_l29_n413(x) + else + fun_l29_n759(x) + end +end + +def fun_l28_n657(x) + if (x < 1) + fun_l29_n810(x) + else + fun_l29_n274(x) + end +end + +def fun_l28_n658(x) + if (x < 1) + fun_l29_n706(x) + else + fun_l29_n564(x) + end +end + +def fun_l28_n659(x) + if (x < 1) + fun_l29_n205(x) + else + fun_l29_n857(x) + end +end + +def fun_l28_n660(x) + if (x < 1) + fun_l29_n534(x) + else + fun_l29_n853(x) + end +end + +def fun_l28_n661(x) + if (x < 1) + fun_l29_n436(x) + else + fun_l29_n227(x) + end +end + +def fun_l28_n662(x) + if (x < 1) + fun_l29_n784(x) + else + fun_l29_n352(x) + end +end + +def fun_l28_n663(x) + if (x < 1) + fun_l29_n889(x) + else + fun_l29_n186(x) + end +end + +def fun_l28_n664(x) + if (x < 1) + fun_l29_n872(x) + else + fun_l29_n217(x) + end +end + +def fun_l28_n665(x) + if (x < 1) + fun_l29_n111(x) + else + fun_l29_n355(x) + end +end + +def fun_l28_n666(x) + if (x < 1) + fun_l29_n175(x) + else + fun_l29_n971(x) + end +end + +def fun_l28_n667(x) + if (x < 1) + fun_l29_n823(x) + else + fun_l29_n123(x) + end +end + +def fun_l28_n668(x) + if (x < 1) + fun_l29_n239(x) + else + fun_l29_n58(x) + end +end + +def fun_l28_n669(x) + if (x < 1) + fun_l29_n127(x) + else + fun_l29_n628(x) + end +end + +def fun_l28_n670(x) + if (x < 1) + fun_l29_n967(x) + else + fun_l29_n575(x) + end +end + +def fun_l28_n671(x) + if (x < 1) + fun_l29_n994(x) + else + fun_l29_n352(x) + end +end + +def fun_l28_n672(x) + if (x < 1) + fun_l29_n598(x) + else + fun_l29_n620(x) + end +end + +def fun_l28_n673(x) + if (x < 1) + fun_l29_n407(x) + else + fun_l29_n132(x) + end +end + +def fun_l28_n674(x) + if (x < 1) + fun_l29_n553(x) + else + fun_l29_n807(x) + end +end + +def fun_l28_n675(x) + if (x < 1) + fun_l29_n918(x) + else + fun_l29_n462(x) + end +end + +def fun_l28_n676(x) + if (x < 1) + fun_l29_n340(x) + else + fun_l29_n905(x) + end +end + +def fun_l28_n677(x) + if (x < 1) + fun_l29_n322(x) + else + fun_l29_n657(x) + end +end + +def fun_l28_n678(x) + if (x < 1) + fun_l29_n249(x) + else + fun_l29_n691(x) + end +end + +def fun_l28_n679(x) + if (x < 1) + fun_l29_n227(x) + else + fun_l29_n559(x) + end +end + +def fun_l28_n680(x) + if (x < 1) + fun_l29_n151(x) + else + fun_l29_n191(x) + end +end + +def fun_l28_n681(x) + if (x < 1) + fun_l29_n211(x) + else + fun_l29_n400(x) + end +end + +def fun_l28_n682(x) + if (x < 1) + fun_l29_n124(x) + else + fun_l29_n334(x) + end +end + +def fun_l28_n683(x) + if (x < 1) + fun_l29_n876(x) + else + fun_l29_n839(x) + end +end + +def fun_l28_n684(x) + if (x < 1) + fun_l29_n764(x) + else + fun_l29_n449(x) + end +end + +def fun_l28_n685(x) + if (x < 1) + fun_l29_n316(x) + else + fun_l29_n730(x) + end +end + +def fun_l28_n686(x) + if (x < 1) + fun_l29_n557(x) + else + fun_l29_n851(x) + end +end + +def fun_l28_n687(x) + if (x < 1) + fun_l29_n315(x) + else + fun_l29_n280(x) + end +end + +def fun_l28_n688(x) + if (x < 1) + fun_l29_n467(x) + else + fun_l29_n593(x) + end +end + +def fun_l28_n689(x) + if (x < 1) + fun_l29_n537(x) + else + fun_l29_n37(x) + end +end + +def fun_l28_n690(x) + if (x < 1) + fun_l29_n582(x) + else + fun_l29_n205(x) + end +end + +def fun_l28_n691(x) + if (x < 1) + fun_l29_n672(x) + else + fun_l29_n656(x) + end +end + +def fun_l28_n692(x) + if (x < 1) + fun_l29_n280(x) + else + fun_l29_n404(x) + end +end + +def fun_l28_n693(x) + if (x < 1) + fun_l29_n609(x) + else + fun_l29_n914(x) + end +end + +def fun_l28_n694(x) + if (x < 1) + fun_l29_n563(x) + else + fun_l29_n215(x) + end +end + +def fun_l28_n695(x) + if (x < 1) + fun_l29_n207(x) + else + fun_l29_n548(x) + end +end + +def fun_l28_n696(x) + if (x < 1) + fun_l29_n981(x) + else + fun_l29_n79(x) + end +end + +def fun_l28_n697(x) + if (x < 1) + fun_l29_n747(x) + else + fun_l29_n687(x) + end +end + +def fun_l28_n698(x) + if (x < 1) + fun_l29_n30(x) + else + fun_l29_n104(x) + end +end + +def fun_l28_n699(x) + if (x < 1) + fun_l29_n587(x) + else + fun_l29_n414(x) + end +end + +def fun_l28_n700(x) + if (x < 1) + fun_l29_n956(x) + else + fun_l29_n601(x) + end +end + +def fun_l28_n701(x) + if (x < 1) + fun_l29_n276(x) + else + fun_l29_n815(x) + end +end + +def fun_l28_n702(x) + if (x < 1) + fun_l29_n294(x) + else + fun_l29_n94(x) + end +end + +def fun_l28_n703(x) + if (x < 1) + fun_l29_n161(x) + else + fun_l29_n133(x) + end +end + +def fun_l28_n704(x) + if (x < 1) + fun_l29_n898(x) + else + fun_l29_n483(x) + end +end + +def fun_l28_n705(x) + if (x < 1) + fun_l29_n651(x) + else + fun_l29_n577(x) + end +end + +def fun_l28_n706(x) + if (x < 1) + fun_l29_n389(x) + else + fun_l29_n595(x) + end +end + +def fun_l28_n707(x) + if (x < 1) + fun_l29_n856(x) + else + fun_l29_n65(x) + end +end + +def fun_l28_n708(x) + if (x < 1) + fun_l29_n77(x) + else + fun_l29_n687(x) + end +end + +def fun_l28_n709(x) + if (x < 1) + fun_l29_n962(x) + else + fun_l29_n517(x) + end +end + +def fun_l28_n710(x) + if (x < 1) + fun_l29_n934(x) + else + fun_l29_n804(x) + end +end + +def fun_l28_n711(x) + if (x < 1) + fun_l29_n267(x) + else + fun_l29_n557(x) + end +end + +def fun_l28_n712(x) + if (x < 1) + fun_l29_n691(x) + else + fun_l29_n558(x) + end +end + +def fun_l28_n713(x) + if (x < 1) + fun_l29_n420(x) + else + fun_l29_n150(x) + end +end + +def fun_l28_n714(x) + if (x < 1) + fun_l29_n289(x) + else + fun_l29_n814(x) + end +end + +def fun_l28_n715(x) + if (x < 1) + fun_l29_n579(x) + else + fun_l29_n730(x) + end +end + +def fun_l28_n716(x) + if (x < 1) + fun_l29_n331(x) + else + fun_l29_n178(x) + end +end + +def fun_l28_n717(x) + if (x < 1) + fun_l29_n914(x) + else + fun_l29_n176(x) + end +end + +def fun_l28_n718(x) + if (x < 1) + fun_l29_n261(x) + else + fun_l29_n203(x) + end +end + +def fun_l28_n719(x) + if (x < 1) + fun_l29_n621(x) + else + fun_l29_n236(x) + end +end + +def fun_l28_n720(x) + if (x < 1) + fun_l29_n453(x) + else + fun_l29_n420(x) + end +end + +def fun_l28_n721(x) + if (x < 1) + fun_l29_n39(x) + else + fun_l29_n499(x) + end +end + +def fun_l28_n722(x) + if (x < 1) + fun_l29_n629(x) + else + fun_l29_n23(x) + end +end + +def fun_l28_n723(x) + if (x < 1) + fun_l29_n55(x) + else + fun_l29_n497(x) + end +end + +def fun_l28_n724(x) + if (x < 1) + fun_l29_n934(x) + else + fun_l29_n891(x) + end +end + +def fun_l28_n725(x) + if (x < 1) + fun_l29_n532(x) + else + fun_l29_n959(x) + end +end + +def fun_l28_n726(x) + if (x < 1) + fun_l29_n510(x) + else + fun_l29_n171(x) + end +end + +def fun_l28_n727(x) + if (x < 1) + fun_l29_n42(x) + else + fun_l29_n680(x) + end +end + +def fun_l28_n728(x) + if (x < 1) + fun_l29_n488(x) + else + fun_l29_n994(x) + end +end + +def fun_l28_n729(x) + if (x < 1) + fun_l29_n347(x) + else + fun_l29_n135(x) + end +end + +def fun_l28_n730(x) + if (x < 1) + fun_l29_n97(x) + else + fun_l29_n176(x) + end +end + +def fun_l28_n731(x) + if (x < 1) + fun_l29_n4(x) + else + fun_l29_n330(x) + end +end + +def fun_l28_n732(x) + if (x < 1) + fun_l29_n808(x) + else + fun_l29_n491(x) + end +end + +def fun_l28_n733(x) + if (x < 1) + fun_l29_n147(x) + else + fun_l29_n520(x) + end +end + +def fun_l28_n734(x) + if (x < 1) + fun_l29_n510(x) + else + fun_l29_n980(x) + end +end + +def fun_l28_n735(x) + if (x < 1) + fun_l29_n656(x) + else + fun_l29_n861(x) + end +end + +def fun_l28_n736(x) + if (x < 1) + fun_l29_n445(x) + else + fun_l29_n625(x) + end +end + +def fun_l28_n737(x) + if (x < 1) + fun_l29_n101(x) + else + fun_l29_n874(x) + end +end + +def fun_l28_n738(x) + if (x < 1) + fun_l29_n337(x) + else + fun_l29_n231(x) + end +end + +def fun_l28_n739(x) + if (x < 1) + fun_l29_n518(x) + else + fun_l29_n575(x) + end +end + +def fun_l28_n740(x) + if (x < 1) + fun_l29_n472(x) + else + fun_l29_n401(x) + end +end + +def fun_l28_n741(x) + if (x < 1) + fun_l29_n47(x) + else + fun_l29_n435(x) + end +end + +def fun_l28_n742(x) + if (x < 1) + fun_l29_n113(x) + else + fun_l29_n56(x) + end +end + +def fun_l28_n743(x) + if (x < 1) + fun_l29_n435(x) + else + fun_l29_n972(x) + end +end + +def fun_l28_n744(x) + if (x < 1) + fun_l29_n692(x) + else + fun_l29_n328(x) + end +end + +def fun_l28_n745(x) + if (x < 1) + fun_l29_n830(x) + else + fun_l29_n92(x) + end +end + +def fun_l28_n746(x) + if (x < 1) + fun_l29_n921(x) + else + fun_l29_n340(x) + end +end + +def fun_l28_n747(x) + if (x < 1) + fun_l29_n346(x) + else + fun_l29_n654(x) + end +end + +def fun_l28_n748(x) + if (x < 1) + fun_l29_n850(x) + else + fun_l29_n40(x) + end +end + +def fun_l28_n749(x) + if (x < 1) + fun_l29_n432(x) + else + fun_l29_n445(x) + end +end + +def fun_l28_n750(x) + if (x < 1) + fun_l29_n28(x) + else + fun_l29_n537(x) + end +end + +def fun_l28_n751(x) + if (x < 1) + fun_l29_n858(x) + else + fun_l29_n375(x) + end +end + +def fun_l28_n752(x) + if (x < 1) + fun_l29_n625(x) + else + fun_l29_n581(x) + end +end + +def fun_l28_n753(x) + if (x < 1) + fun_l29_n223(x) + else + fun_l29_n509(x) + end +end + +def fun_l28_n754(x) + if (x < 1) + fun_l29_n655(x) + else + fun_l29_n218(x) + end +end + +def fun_l28_n755(x) + if (x < 1) + fun_l29_n998(x) + else + fun_l29_n177(x) + end +end + +def fun_l28_n756(x) + if (x < 1) + fun_l29_n66(x) + else + fun_l29_n763(x) + end +end + +def fun_l28_n757(x) + if (x < 1) + fun_l29_n112(x) + else + fun_l29_n494(x) + end +end + +def fun_l28_n758(x) + if (x < 1) + fun_l29_n144(x) + else + fun_l29_n402(x) + end +end + +def fun_l28_n759(x) + if (x < 1) + fun_l29_n162(x) + else + fun_l29_n338(x) + end +end + +def fun_l28_n760(x) + if (x < 1) + fun_l29_n975(x) + else + fun_l29_n431(x) + end +end + +def fun_l28_n761(x) + if (x < 1) + fun_l29_n676(x) + else + fun_l29_n787(x) + end +end + +def fun_l28_n762(x) + if (x < 1) + fun_l29_n90(x) + else + fun_l29_n828(x) + end +end + +def fun_l28_n763(x) + if (x < 1) + fun_l29_n816(x) + else + fun_l29_n119(x) + end +end + +def fun_l28_n764(x) + if (x < 1) + fun_l29_n624(x) + else + fun_l29_n885(x) + end +end + +def fun_l28_n765(x) + if (x < 1) + fun_l29_n933(x) + else + fun_l29_n378(x) + end +end + +def fun_l28_n766(x) + if (x < 1) + fun_l29_n967(x) + else + fun_l29_n580(x) + end +end + +def fun_l28_n767(x) + if (x < 1) + fun_l29_n752(x) + else + fun_l29_n607(x) + end +end + +def fun_l28_n768(x) + if (x < 1) + fun_l29_n333(x) + else + fun_l29_n339(x) + end +end + +def fun_l28_n769(x) + if (x < 1) + fun_l29_n720(x) + else + fun_l29_n952(x) + end +end + +def fun_l28_n770(x) + if (x < 1) + fun_l29_n323(x) + else + fun_l29_n542(x) + end +end + +def fun_l28_n771(x) + if (x < 1) + fun_l29_n472(x) + else + fun_l29_n4(x) + end +end + +def fun_l28_n772(x) + if (x < 1) + fun_l29_n962(x) + else + fun_l29_n345(x) + end +end + +def fun_l28_n773(x) + if (x < 1) + fun_l29_n305(x) + else + fun_l29_n106(x) + end +end + +def fun_l28_n774(x) + if (x < 1) + fun_l29_n880(x) + else + fun_l29_n731(x) + end +end + +def fun_l28_n775(x) + if (x < 1) + fun_l29_n760(x) + else + fun_l29_n460(x) + end +end + +def fun_l28_n776(x) + if (x < 1) + fun_l29_n445(x) + else + fun_l29_n725(x) + end +end + +def fun_l28_n777(x) + if (x < 1) + fun_l29_n850(x) + else + fun_l29_n121(x) + end +end + +def fun_l28_n778(x) + if (x < 1) + fun_l29_n270(x) + else + fun_l29_n85(x) + end +end + +def fun_l28_n779(x) + if (x < 1) + fun_l29_n208(x) + else + fun_l29_n822(x) + end +end + +def fun_l28_n780(x) + if (x < 1) + fun_l29_n832(x) + else + fun_l29_n712(x) + end +end + +def fun_l28_n781(x) + if (x < 1) + fun_l29_n456(x) + else + fun_l29_n947(x) + end +end + +def fun_l28_n782(x) + if (x < 1) + fun_l29_n973(x) + else + fun_l29_n912(x) + end +end + +def fun_l28_n783(x) + if (x < 1) + fun_l29_n365(x) + else + fun_l29_n496(x) + end +end + +def fun_l28_n784(x) + if (x < 1) + fun_l29_n717(x) + else + fun_l29_n157(x) + end +end + +def fun_l28_n785(x) + if (x < 1) + fun_l29_n754(x) + else + fun_l29_n462(x) + end +end + +def fun_l28_n786(x) + if (x < 1) + fun_l29_n470(x) + else + fun_l29_n528(x) + end +end + +def fun_l28_n787(x) + if (x < 1) + fun_l29_n463(x) + else + fun_l29_n107(x) + end +end + +def fun_l28_n788(x) + if (x < 1) + fun_l29_n583(x) + else + fun_l29_n387(x) + end +end + +def fun_l28_n789(x) + if (x < 1) + fun_l29_n55(x) + else + fun_l29_n694(x) + end +end + +def fun_l28_n790(x) + if (x < 1) + fun_l29_n834(x) + else + fun_l29_n306(x) + end +end + +def fun_l28_n791(x) + if (x < 1) + fun_l29_n374(x) + else + fun_l29_n502(x) + end +end + +def fun_l28_n792(x) + if (x < 1) + fun_l29_n462(x) + else + fun_l29_n221(x) + end +end + +def fun_l28_n793(x) + if (x < 1) + fun_l29_n680(x) + else + fun_l29_n966(x) + end +end + +def fun_l28_n794(x) + if (x < 1) + fun_l29_n936(x) + else + fun_l29_n911(x) + end +end + +def fun_l28_n795(x) + if (x < 1) + fun_l29_n863(x) + else + fun_l29_n978(x) + end +end + +def fun_l28_n796(x) + if (x < 1) + fun_l29_n1(x) + else + fun_l29_n399(x) + end +end + +def fun_l28_n797(x) + if (x < 1) + fun_l29_n628(x) + else + fun_l29_n603(x) + end +end + +def fun_l28_n798(x) + if (x < 1) + fun_l29_n799(x) + else + fun_l29_n979(x) + end +end + +def fun_l28_n799(x) + if (x < 1) + fun_l29_n856(x) + else + fun_l29_n946(x) + end +end + +def fun_l28_n800(x) + if (x < 1) + fun_l29_n556(x) + else + fun_l29_n816(x) + end +end + +def fun_l28_n801(x) + if (x < 1) + fun_l29_n619(x) + else + fun_l29_n19(x) + end +end + +def fun_l28_n802(x) + if (x < 1) + fun_l29_n143(x) + else + fun_l29_n287(x) + end +end + +def fun_l28_n803(x) + if (x < 1) + fun_l29_n816(x) + else + fun_l29_n271(x) + end +end + +def fun_l28_n804(x) + if (x < 1) + fun_l29_n517(x) + else + fun_l29_n931(x) + end +end + +def fun_l28_n805(x) + if (x < 1) + fun_l29_n298(x) + else + fun_l29_n509(x) + end +end + +def fun_l28_n806(x) + if (x < 1) + fun_l29_n493(x) + else + fun_l29_n341(x) + end +end + +def fun_l28_n807(x) + if (x < 1) + fun_l29_n270(x) + else + fun_l29_n82(x) + end +end + +def fun_l28_n808(x) + if (x < 1) + fun_l29_n980(x) + else + fun_l29_n771(x) + end +end + +def fun_l28_n809(x) + if (x < 1) + fun_l29_n784(x) + else + fun_l29_n696(x) + end +end + +def fun_l28_n810(x) + if (x < 1) + fun_l29_n966(x) + else + fun_l29_n216(x) + end +end + +def fun_l28_n811(x) + if (x < 1) + fun_l29_n374(x) + else + fun_l29_n482(x) + end +end + +def fun_l28_n812(x) + if (x < 1) + fun_l29_n682(x) + else + fun_l29_n42(x) + end +end + +def fun_l28_n813(x) + if (x < 1) + fun_l29_n254(x) + else + fun_l29_n899(x) + end +end + +def fun_l28_n814(x) + if (x < 1) + fun_l29_n115(x) + else + fun_l29_n336(x) + end +end + +def fun_l28_n815(x) + if (x < 1) + fun_l29_n842(x) + else + fun_l29_n201(x) + end +end + +def fun_l28_n816(x) + if (x < 1) + fun_l29_n258(x) + else + fun_l29_n675(x) + end +end + +def fun_l28_n817(x) + if (x < 1) + fun_l29_n594(x) + else + fun_l29_n61(x) + end +end + +def fun_l28_n818(x) + if (x < 1) + fun_l29_n691(x) + else + fun_l29_n627(x) + end +end + +def fun_l28_n819(x) + if (x < 1) + fun_l29_n963(x) + else + fun_l29_n611(x) + end +end + +def fun_l28_n820(x) + if (x < 1) + fun_l29_n455(x) + else + fun_l29_n829(x) + end +end + +def fun_l28_n821(x) + if (x < 1) + fun_l29_n818(x) + else + fun_l29_n242(x) + end +end + +def fun_l28_n822(x) + if (x < 1) + fun_l29_n242(x) + else + fun_l29_n474(x) + end +end + +def fun_l28_n823(x) + if (x < 1) + fun_l29_n847(x) + else + fun_l29_n119(x) + end +end + +def fun_l28_n824(x) + if (x < 1) + fun_l29_n141(x) + else + fun_l29_n371(x) + end +end + +def fun_l28_n825(x) + if (x < 1) + fun_l29_n913(x) + else + fun_l29_n129(x) + end +end + +def fun_l28_n826(x) + if (x < 1) + fun_l29_n440(x) + else + fun_l29_n860(x) + end +end + +def fun_l28_n827(x) + if (x < 1) + fun_l29_n194(x) + else + fun_l29_n940(x) + end +end + +def fun_l28_n828(x) + if (x < 1) + fun_l29_n444(x) + else + fun_l29_n332(x) + end +end + +def fun_l28_n829(x) + if (x < 1) + fun_l29_n435(x) + else + fun_l29_n559(x) + end +end + +def fun_l28_n830(x) + if (x < 1) + fun_l29_n898(x) + else + fun_l29_n418(x) + end +end + +def fun_l28_n831(x) + if (x < 1) + fun_l29_n13(x) + else + fun_l29_n917(x) + end +end + +def fun_l28_n832(x) + if (x < 1) + fun_l29_n705(x) + else + fun_l29_n738(x) + end +end + +def fun_l28_n833(x) + if (x < 1) + fun_l29_n519(x) + else + fun_l29_n35(x) + end +end + +def fun_l28_n834(x) + if (x < 1) + fun_l29_n205(x) + else + fun_l29_n928(x) + end +end + +def fun_l28_n835(x) + if (x < 1) + fun_l29_n401(x) + else + fun_l29_n191(x) + end +end + +def fun_l28_n836(x) + if (x < 1) + fun_l29_n497(x) + else + fun_l29_n789(x) + end +end + +def fun_l28_n837(x) + if (x < 1) + fun_l29_n745(x) + else + fun_l29_n714(x) + end +end + +def fun_l28_n838(x) + if (x < 1) + fun_l29_n885(x) + else + fun_l29_n845(x) + end +end + +def fun_l28_n839(x) + if (x < 1) + fun_l29_n423(x) + else + fun_l29_n835(x) + end +end + +def fun_l28_n840(x) + if (x < 1) + fun_l29_n844(x) + else + fun_l29_n296(x) + end +end + +def fun_l28_n841(x) + if (x < 1) + fun_l29_n980(x) + else + fun_l29_n298(x) + end +end + +def fun_l28_n842(x) + if (x < 1) + fun_l29_n169(x) + else + fun_l29_n613(x) + end +end + +def fun_l28_n843(x) + if (x < 1) + fun_l29_n323(x) + else + fun_l29_n437(x) + end +end + +def fun_l28_n844(x) + if (x < 1) + fun_l29_n532(x) + else + fun_l29_n841(x) + end +end + +def fun_l28_n845(x) + if (x < 1) + fun_l29_n984(x) + else + fun_l29_n696(x) + end +end + +def fun_l28_n846(x) + if (x < 1) + fun_l29_n474(x) + else + fun_l29_n346(x) + end +end + +def fun_l28_n847(x) + if (x < 1) + fun_l29_n725(x) + else + fun_l29_n994(x) + end +end + +def fun_l28_n848(x) + if (x < 1) + fun_l29_n650(x) + else + fun_l29_n920(x) + end +end + +def fun_l28_n849(x) + if (x < 1) + fun_l29_n626(x) + else + fun_l29_n704(x) + end +end + +def fun_l28_n850(x) + if (x < 1) + fun_l29_n506(x) + else + fun_l29_n440(x) + end +end + +def fun_l28_n851(x) + if (x < 1) + fun_l29_n512(x) + else + fun_l29_n811(x) + end +end + +def fun_l28_n852(x) + if (x < 1) + fun_l29_n763(x) + else + fun_l29_n986(x) + end +end + +def fun_l28_n853(x) + if (x < 1) + fun_l29_n866(x) + else + fun_l29_n972(x) + end +end + +def fun_l28_n854(x) + if (x < 1) + fun_l29_n71(x) + else + fun_l29_n347(x) + end +end + +def fun_l28_n855(x) + if (x < 1) + fun_l29_n380(x) + else + fun_l29_n809(x) + end +end + +def fun_l28_n856(x) + if (x < 1) + fun_l29_n802(x) + else + fun_l29_n13(x) + end +end + +def fun_l28_n857(x) + if (x < 1) + fun_l29_n631(x) + else + fun_l29_n636(x) + end +end + +def fun_l28_n858(x) + if (x < 1) + fun_l29_n542(x) + else + fun_l29_n166(x) + end +end + +def fun_l28_n859(x) + if (x < 1) + fun_l29_n393(x) + else + fun_l29_n317(x) + end +end + +def fun_l28_n860(x) + if (x < 1) + fun_l29_n833(x) + else + fun_l29_n424(x) + end +end + +def fun_l28_n861(x) + if (x < 1) + fun_l29_n62(x) + else + fun_l29_n78(x) + end +end + +def fun_l28_n862(x) + if (x < 1) + fun_l29_n145(x) + else + fun_l29_n322(x) + end +end + +def fun_l28_n863(x) + if (x < 1) + fun_l29_n733(x) + else + fun_l29_n171(x) + end +end + +def fun_l28_n864(x) + if (x < 1) + fun_l29_n35(x) + else + fun_l29_n626(x) + end +end + +def fun_l28_n865(x) + if (x < 1) + fun_l29_n356(x) + else + fun_l29_n832(x) + end +end + +def fun_l28_n866(x) + if (x < 1) + fun_l29_n823(x) + else + fun_l29_n480(x) + end +end + +def fun_l28_n867(x) + if (x < 1) + fun_l29_n397(x) + else + fun_l29_n245(x) + end +end + +def fun_l28_n868(x) + if (x < 1) + fun_l29_n403(x) + else + fun_l29_n682(x) + end +end + +def fun_l28_n869(x) + if (x < 1) + fun_l29_n481(x) + else + fun_l29_n543(x) + end +end + +def fun_l28_n870(x) + if (x < 1) + fun_l29_n759(x) + else + fun_l29_n281(x) + end +end + +def fun_l28_n871(x) + if (x < 1) + fun_l29_n671(x) + else + fun_l29_n644(x) + end +end + +def fun_l28_n872(x) + if (x < 1) + fun_l29_n210(x) + else + fun_l29_n76(x) + end +end + +def fun_l28_n873(x) + if (x < 1) + fun_l29_n823(x) + else + fun_l29_n461(x) + end +end + +def fun_l28_n874(x) + if (x < 1) + fun_l29_n269(x) + else + fun_l29_n368(x) + end +end + +def fun_l28_n875(x) + if (x < 1) + fun_l29_n727(x) + else + fun_l29_n37(x) + end +end + +def fun_l28_n876(x) + if (x < 1) + fun_l29_n670(x) + else + fun_l29_n389(x) + end +end + +def fun_l28_n877(x) + if (x < 1) + fun_l29_n844(x) + else + fun_l29_n424(x) + end +end + +def fun_l28_n878(x) + if (x < 1) + fun_l29_n612(x) + else + fun_l29_n201(x) + end +end + +def fun_l28_n879(x) + if (x < 1) + fun_l29_n790(x) + else + fun_l29_n270(x) + end +end + +def fun_l28_n880(x) + if (x < 1) + fun_l29_n976(x) + else + fun_l29_n362(x) + end +end + +def fun_l28_n881(x) + if (x < 1) + fun_l29_n701(x) + else + fun_l29_n846(x) + end +end + +def fun_l28_n882(x) + if (x < 1) + fun_l29_n354(x) + else + fun_l29_n803(x) + end +end + +def fun_l28_n883(x) + if (x < 1) + fun_l29_n40(x) + else + fun_l29_n168(x) + end +end + +def fun_l28_n884(x) + if (x < 1) + fun_l29_n471(x) + else + fun_l29_n15(x) + end +end + +def fun_l28_n885(x) + if (x < 1) + fun_l29_n87(x) + else + fun_l29_n287(x) + end +end + +def fun_l28_n886(x) + if (x < 1) + fun_l29_n659(x) + else + fun_l29_n623(x) + end +end + +def fun_l28_n887(x) + if (x < 1) + fun_l29_n318(x) + else + fun_l29_n377(x) + end +end + +def fun_l28_n888(x) + if (x < 1) + fun_l29_n996(x) + else + fun_l29_n393(x) + end +end + +def fun_l28_n889(x) + if (x < 1) + fun_l29_n999(x) + else + fun_l29_n370(x) + end +end + +def fun_l28_n890(x) + if (x < 1) + fun_l29_n900(x) + else + fun_l29_n902(x) + end +end + +def fun_l28_n891(x) + if (x < 1) + fun_l29_n180(x) + else + fun_l29_n477(x) + end +end + +def fun_l28_n892(x) + if (x < 1) + fun_l29_n254(x) + else + fun_l29_n762(x) + end +end + +def fun_l28_n893(x) + if (x < 1) + fun_l29_n36(x) + else + fun_l29_n198(x) + end +end + +def fun_l28_n894(x) + if (x < 1) + fun_l29_n811(x) + else + fun_l29_n667(x) + end +end + +def fun_l28_n895(x) + if (x < 1) + fun_l29_n711(x) + else + fun_l29_n462(x) + end +end + +def fun_l28_n896(x) + if (x < 1) + fun_l29_n535(x) + else + fun_l29_n759(x) + end +end + +def fun_l28_n897(x) + if (x < 1) + fun_l29_n336(x) + else + fun_l29_n72(x) + end +end + +def fun_l28_n898(x) + if (x < 1) + fun_l29_n556(x) + else + fun_l29_n324(x) + end +end + +def fun_l28_n899(x) + if (x < 1) + fun_l29_n821(x) + else + fun_l29_n520(x) + end +end + +def fun_l28_n900(x) + if (x < 1) + fun_l29_n820(x) + else + fun_l29_n581(x) + end +end + +def fun_l28_n901(x) + if (x < 1) + fun_l29_n416(x) + else + fun_l29_n662(x) + end +end + +def fun_l28_n902(x) + if (x < 1) + fun_l29_n574(x) + else + fun_l29_n472(x) + end +end + +def fun_l28_n903(x) + if (x < 1) + fun_l29_n140(x) + else + fun_l29_n608(x) + end +end + +def fun_l28_n904(x) + if (x < 1) + fun_l29_n492(x) + else + fun_l29_n50(x) + end +end + +def fun_l28_n905(x) + if (x < 1) + fun_l29_n240(x) + else + fun_l29_n308(x) + end +end + +def fun_l28_n906(x) + if (x < 1) + fun_l29_n400(x) + else + fun_l29_n560(x) + end +end + +def fun_l28_n907(x) + if (x < 1) + fun_l29_n974(x) + else + fun_l29_n580(x) + end +end + +def fun_l28_n908(x) + if (x < 1) + fun_l29_n234(x) + else + fun_l29_n921(x) + end +end + +def fun_l28_n909(x) + if (x < 1) + fun_l29_n712(x) + else + fun_l29_n861(x) + end +end + +def fun_l28_n910(x) + if (x < 1) + fun_l29_n716(x) + else + fun_l29_n818(x) + end +end + +def fun_l28_n911(x) + if (x < 1) + fun_l29_n574(x) + else + fun_l29_n668(x) + end +end + +def fun_l28_n912(x) + if (x < 1) + fun_l29_n259(x) + else + fun_l29_n573(x) + end +end + +def fun_l28_n913(x) + if (x < 1) + fun_l29_n427(x) + else + fun_l29_n572(x) + end +end + +def fun_l28_n914(x) + if (x < 1) + fun_l29_n449(x) + else + fun_l29_n25(x) + end +end + +def fun_l28_n915(x) + if (x < 1) + fun_l29_n234(x) + else + fun_l29_n391(x) + end +end + +def fun_l28_n916(x) + if (x < 1) + fun_l29_n115(x) + else + fun_l29_n918(x) + end +end + +def fun_l28_n917(x) + if (x < 1) + fun_l29_n83(x) + else + fun_l29_n295(x) + end +end + +def fun_l28_n918(x) + if (x < 1) + fun_l29_n917(x) + else + fun_l29_n542(x) + end +end + +def fun_l28_n919(x) + if (x < 1) + fun_l29_n836(x) + else + fun_l29_n460(x) + end +end + +def fun_l28_n920(x) + if (x < 1) + fun_l29_n333(x) + else + fun_l29_n622(x) + end +end + +def fun_l28_n921(x) + if (x < 1) + fun_l29_n717(x) + else + fun_l29_n342(x) + end +end + +def fun_l28_n922(x) + if (x < 1) + fun_l29_n670(x) + else + fun_l29_n735(x) + end +end + +def fun_l28_n923(x) + if (x < 1) + fun_l29_n723(x) + else + fun_l29_n994(x) + end +end + +def fun_l28_n924(x) + if (x < 1) + fun_l29_n477(x) + else + fun_l29_n234(x) + end +end + +def fun_l28_n925(x) + if (x < 1) + fun_l29_n514(x) + else + fun_l29_n194(x) + end +end + +def fun_l28_n926(x) + if (x < 1) + fun_l29_n33(x) + else + fun_l29_n149(x) + end +end + +def fun_l28_n927(x) + if (x < 1) + fun_l29_n805(x) + else + fun_l29_n9(x) + end +end + +def fun_l28_n928(x) + if (x < 1) + fun_l29_n351(x) + else + fun_l29_n250(x) + end +end + +def fun_l28_n929(x) + if (x < 1) + fun_l29_n22(x) + else + fun_l29_n294(x) + end +end + +def fun_l28_n930(x) + if (x < 1) + fun_l29_n456(x) + else + fun_l29_n194(x) + end +end + +def fun_l28_n931(x) + if (x < 1) + fun_l29_n354(x) + else + fun_l29_n341(x) + end +end + +def fun_l28_n932(x) + if (x < 1) + fun_l29_n782(x) + else + fun_l29_n159(x) + end +end + +def fun_l28_n933(x) + if (x < 1) + fun_l29_n636(x) + else + fun_l29_n588(x) + end +end + +def fun_l28_n934(x) + if (x < 1) + fun_l29_n473(x) + else + fun_l29_n527(x) + end +end + +def fun_l28_n935(x) + if (x < 1) + fun_l29_n776(x) + else + fun_l29_n349(x) + end +end + +def fun_l28_n936(x) + if (x < 1) + fun_l29_n786(x) + else + fun_l29_n95(x) + end +end + +def fun_l28_n937(x) + if (x < 1) + fun_l29_n276(x) + else + fun_l29_n952(x) + end +end + +def fun_l28_n938(x) + if (x < 1) + fun_l29_n826(x) + else + fun_l29_n183(x) + end +end + +def fun_l28_n939(x) + if (x < 1) + fun_l29_n11(x) + else + fun_l29_n775(x) + end +end + +def fun_l28_n940(x) + if (x < 1) + fun_l29_n161(x) + else + fun_l29_n255(x) + end +end + +def fun_l28_n941(x) + if (x < 1) + fun_l29_n77(x) + else + fun_l29_n673(x) + end +end + +def fun_l28_n942(x) + if (x < 1) + fun_l29_n659(x) + else + fun_l29_n413(x) + end +end + +def fun_l28_n943(x) + if (x < 1) + fun_l29_n827(x) + else + fun_l29_n262(x) + end +end + +def fun_l28_n944(x) + if (x < 1) + fun_l29_n720(x) + else + fun_l29_n476(x) + end +end + +def fun_l28_n945(x) + if (x < 1) + fun_l29_n457(x) + else + fun_l29_n613(x) + end +end + +def fun_l28_n946(x) + if (x < 1) + fun_l29_n137(x) + else + fun_l29_n763(x) + end +end + +def fun_l28_n947(x) + if (x < 1) + fun_l29_n569(x) + else + fun_l29_n331(x) + end +end + +def fun_l28_n948(x) + if (x < 1) + fun_l29_n687(x) + else + fun_l29_n684(x) + end +end + +def fun_l28_n949(x) + if (x < 1) + fun_l29_n532(x) + else + fun_l29_n203(x) + end +end + +def fun_l28_n950(x) + if (x < 1) + fun_l29_n211(x) + else + fun_l29_n606(x) + end +end + +def fun_l28_n951(x) + if (x < 1) + fun_l29_n522(x) + else + fun_l29_n907(x) + end +end + +def fun_l28_n952(x) + if (x < 1) + fun_l29_n64(x) + else + fun_l29_n742(x) + end +end + +def fun_l28_n953(x) + if (x < 1) + fun_l29_n28(x) + else + fun_l29_n712(x) + end +end + +def fun_l28_n954(x) + if (x < 1) + fun_l29_n177(x) + else + fun_l29_n327(x) + end +end + +def fun_l28_n955(x) + if (x < 1) + fun_l29_n274(x) + else + fun_l29_n830(x) + end +end + +def fun_l28_n956(x) + if (x < 1) + fun_l29_n709(x) + else + fun_l29_n115(x) + end +end + +def fun_l28_n957(x) + if (x < 1) + fun_l29_n72(x) + else + fun_l29_n849(x) + end +end + +def fun_l28_n958(x) + if (x < 1) + fun_l29_n347(x) + else + fun_l29_n317(x) + end +end + +def fun_l28_n959(x) + if (x < 1) + fun_l29_n540(x) + else + fun_l29_n226(x) + end +end + +def fun_l28_n960(x) + if (x < 1) + fun_l29_n383(x) + else + fun_l29_n634(x) + end +end + +def fun_l28_n961(x) + if (x < 1) + fun_l29_n616(x) + else + fun_l29_n300(x) + end +end + +def fun_l28_n962(x) + if (x < 1) + fun_l29_n955(x) + else + fun_l29_n861(x) + end +end + +def fun_l28_n963(x) + if (x < 1) + fun_l29_n143(x) + else + fun_l29_n106(x) + end +end + +def fun_l28_n964(x) + if (x < 1) + fun_l29_n883(x) + else + fun_l29_n997(x) + end +end + +def fun_l28_n965(x) + if (x < 1) + fun_l29_n247(x) + else + fun_l29_n471(x) + end +end + +def fun_l28_n966(x) + if (x < 1) + fun_l29_n237(x) + else + fun_l29_n107(x) + end +end + +def fun_l28_n967(x) + if (x < 1) + fun_l29_n754(x) + else + fun_l29_n996(x) + end +end + +def fun_l28_n968(x) + if (x < 1) + fun_l29_n951(x) + else + fun_l29_n216(x) + end +end + +def fun_l28_n969(x) + if (x < 1) + fun_l29_n36(x) + else + fun_l29_n815(x) + end +end + +def fun_l28_n970(x) + if (x < 1) + fun_l29_n362(x) + else + fun_l29_n27(x) + end +end + +def fun_l28_n971(x) + if (x < 1) + fun_l29_n837(x) + else + fun_l29_n230(x) + end +end + +def fun_l28_n972(x) + if (x < 1) + fun_l29_n295(x) + else + fun_l29_n772(x) + end +end + +def fun_l28_n973(x) + if (x < 1) + fun_l29_n570(x) + else + fun_l29_n514(x) + end +end + +def fun_l28_n974(x) + if (x < 1) + fun_l29_n151(x) + else + fun_l29_n368(x) + end +end + +def fun_l28_n975(x) + if (x < 1) + fun_l29_n229(x) + else + fun_l29_n408(x) + end +end + +def fun_l28_n976(x) + if (x < 1) + fun_l29_n209(x) + else + fun_l29_n513(x) + end +end + +def fun_l28_n977(x) + if (x < 1) + fun_l29_n753(x) + else + fun_l29_n36(x) + end +end + +def fun_l28_n978(x) + if (x < 1) + fun_l29_n887(x) + else + fun_l29_n330(x) + end +end + +def fun_l28_n979(x) + if (x < 1) + fun_l29_n880(x) + else + fun_l29_n6(x) + end +end + +def fun_l28_n980(x) + if (x < 1) + fun_l29_n953(x) + else + fun_l29_n573(x) + end +end + +def fun_l28_n981(x) + if (x < 1) + fun_l29_n960(x) + else + fun_l29_n774(x) + end +end + +def fun_l28_n982(x) + if (x < 1) + fun_l29_n769(x) + else + fun_l29_n43(x) + end +end + +def fun_l28_n983(x) + if (x < 1) + fun_l29_n43(x) + else + fun_l29_n168(x) + end +end + +def fun_l28_n984(x) + if (x < 1) + fun_l29_n70(x) + else + fun_l29_n695(x) + end +end + +def fun_l28_n985(x) + if (x < 1) + fun_l29_n421(x) + else + fun_l29_n9(x) + end +end + +def fun_l28_n986(x) + if (x < 1) + fun_l29_n588(x) + else + fun_l29_n916(x) + end +end + +def fun_l28_n987(x) + if (x < 1) + fun_l29_n693(x) + else + fun_l29_n979(x) + end +end + +def fun_l28_n988(x) + if (x < 1) + fun_l29_n684(x) + else + fun_l29_n342(x) + end +end + +def fun_l28_n989(x) + if (x < 1) + fun_l29_n148(x) + else + fun_l29_n348(x) + end +end + +def fun_l28_n990(x) + if (x < 1) + fun_l29_n740(x) + else + fun_l29_n120(x) + end +end + +def fun_l28_n991(x) + if (x < 1) + fun_l29_n258(x) + else + fun_l29_n670(x) + end +end + +def fun_l28_n992(x) + if (x < 1) + fun_l29_n514(x) + else + fun_l29_n198(x) + end +end + +def fun_l28_n993(x) + if (x < 1) + fun_l29_n563(x) + else + fun_l29_n174(x) + end +end + +def fun_l28_n994(x) + if (x < 1) + fun_l29_n391(x) + else + fun_l29_n689(x) + end +end + +def fun_l28_n995(x) + if (x < 1) + fun_l29_n156(x) + else + fun_l29_n579(x) + end +end + +def fun_l28_n996(x) + if (x < 1) + fun_l29_n411(x) + else + fun_l29_n212(x) + end +end + +def fun_l28_n997(x) + if (x < 1) + fun_l29_n709(x) + else + fun_l29_n735(x) + end +end + +def fun_l28_n998(x) + if (x < 1) + fun_l29_n960(x) + else + fun_l29_n813(x) + end +end + +def fun_l28_n999(x) + if (x < 1) + fun_l29_n553(x) + else + fun_l29_n875(x) + end +end + +def fun_l29_n0(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n1(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n2(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n3(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n4(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n5(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n6(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n7(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n8(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n9(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n10(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n11(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n12(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n13(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n14(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n15(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n16(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n17(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n18(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n19(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n20(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n21(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n22(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n23(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n24(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n25(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n26(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n27(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n28(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n29(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n30(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n31(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n32(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n33(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n34(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n35(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n36(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n37(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n38(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n39(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n40(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n41(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n42(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n43(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n44(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n45(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n46(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n47(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n48(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n49(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n50(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n51(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n52(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n53(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n54(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n55(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n56(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n57(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n58(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n59(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n60(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n61(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n62(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n63(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n64(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n65(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n66(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n67(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n68(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n69(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n70(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n71(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n72(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n73(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n74(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n75(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n76(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n77(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n78(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n79(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n80(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n81(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n82(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n83(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n84(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n85(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n86(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n87(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n88(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n89(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n90(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n91(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n92(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n93(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n94(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n95(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n96(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n97(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n98(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n99(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n100(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n101(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n102(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n103(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n104(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n105(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n106(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n107(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n108(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n109(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n110(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n111(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n112(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n113(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n114(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n115(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n116(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n117(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n118(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n119(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n120(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n121(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n122(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n123(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n124(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n125(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n126(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n127(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n128(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n129(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n130(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n131(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n132(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n133(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n134(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n135(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n136(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n137(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n138(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n139(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n140(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n141(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n142(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n143(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n144(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n145(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n146(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n147(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n148(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n149(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n150(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n151(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n152(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n153(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n154(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n155(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n156(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n157(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n158(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n159(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n160(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n161(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n162(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n163(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n164(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n165(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n166(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n167(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n168(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n169(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n170(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n171(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n172(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n173(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n174(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n175(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n176(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n177(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n178(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n179(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n180(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n181(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n182(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n183(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n184(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n185(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n186(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n187(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n188(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n189(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n190(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n191(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n192(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n193(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n194(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n195(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n196(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n197(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n198(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n199(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n200(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n201(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n202(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n203(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n204(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n205(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n206(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n207(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n208(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n209(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n210(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n211(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n212(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n213(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n214(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n215(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n216(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n217(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n218(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n219(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n220(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n221(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n222(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n223(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n224(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n225(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n226(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n227(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n228(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n229(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n230(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n231(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n232(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n233(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n234(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n235(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n236(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n237(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n238(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n239(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n240(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n241(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n242(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n243(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n244(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n245(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n246(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n247(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n248(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n249(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n250(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n251(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n252(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n253(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n254(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n255(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n256(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n257(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n258(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n259(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n260(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n261(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n262(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n263(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n264(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n265(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n266(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n267(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n268(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n269(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n270(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n271(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n272(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n273(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n274(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n275(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n276(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n277(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n278(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n279(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n280(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n281(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n282(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n283(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n284(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n285(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n286(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n287(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n288(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n289(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n290(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n291(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n292(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n293(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n294(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n295(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n296(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n297(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n298(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n299(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n300(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n301(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n302(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n303(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n304(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n305(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n306(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n307(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n308(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n309(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n310(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n311(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n312(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n313(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n314(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n315(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n316(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n317(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n318(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n319(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n320(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n321(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n322(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n323(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n324(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n325(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n326(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n327(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n328(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n329(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n330(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n331(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n332(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n333(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n334(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n335(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n336(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n337(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n338(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n339(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n340(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n341(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n342(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n343(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n344(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n345(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n346(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n347(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n348(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n349(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n350(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n351(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n352(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n353(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n354(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n355(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n356(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n357(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n358(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n359(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n360(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n361(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n362(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n363(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n364(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n365(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n366(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n367(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n368(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n369(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n370(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n371(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n372(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n373(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n374(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n375(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n376(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n377(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n378(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n379(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n380(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n381(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n382(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n383(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n384(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n385(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n386(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n387(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n388(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n389(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n390(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n391(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n392(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n393(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n394(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n395(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n396(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n397(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n398(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n399(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n400(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n401(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n402(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n403(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n404(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n405(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n406(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n407(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n408(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n409(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n410(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n411(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n412(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n413(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n414(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n415(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n416(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n417(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n418(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n419(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n420(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n421(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n422(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n423(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n424(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n425(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n426(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n427(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n428(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n429(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n430(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n431(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n432(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n433(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n434(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n435(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n436(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n437(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n438(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n439(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n440(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n441(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n442(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n443(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n444(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n445(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n446(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n447(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n448(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n449(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n450(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n451(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n452(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n453(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n454(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n455(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n456(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n457(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n458(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n459(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n460(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n461(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n462(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n463(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n464(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n465(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n466(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n467(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n468(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n469(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n470(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n471(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n472(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n473(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n474(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n475(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n476(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n477(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n478(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n479(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n480(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n481(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n482(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n483(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n484(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n485(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n486(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n487(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n488(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n489(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n490(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n491(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n492(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n493(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n494(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n495(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n496(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n497(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n498(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n499(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n500(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n501(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n502(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n503(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n504(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n505(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n506(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n507(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n508(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n509(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n510(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n511(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n512(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n513(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n514(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n515(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n516(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n517(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n518(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n519(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n520(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n521(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n522(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n523(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n524(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n525(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n526(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n527(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n528(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n529(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n530(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n531(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n532(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n533(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n534(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n535(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n536(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n537(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n538(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n539(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n540(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n541(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n542(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n543(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n544(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n545(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n546(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n547(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n548(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n549(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n550(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n551(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n552(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n553(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n554(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n555(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n556(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n557(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n558(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n559(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n560(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n561(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n562(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n563(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n564(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n565(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n566(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n567(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n568(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n569(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n570(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n571(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n572(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n573(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n574(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n575(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n576(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n577(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n578(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n579(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n580(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n581(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n582(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n583(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n584(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n585(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n586(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n587(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n588(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n589(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n590(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n591(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n592(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n593(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n594(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n595(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n596(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n597(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n598(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n599(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n600(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n601(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n602(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n603(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n604(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n605(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n606(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n607(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n608(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n609(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n610(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n611(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n612(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n613(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n614(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n615(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n616(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n617(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n618(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n619(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n620(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n621(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n622(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n623(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n624(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n625(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n626(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n627(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n628(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n629(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n630(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n631(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n632(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n633(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n634(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n635(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n636(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n637(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n638(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n639(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n640(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n641(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n642(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n643(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n644(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n645(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n646(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n647(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n648(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n649(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n650(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n651(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n652(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n653(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n654(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n655(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n656(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n657(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n658(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n659(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n660(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n661(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n662(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n663(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n664(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n665(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n666(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n667(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n668(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n669(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n670(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n671(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n672(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n673(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n674(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n675(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n676(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n677(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n678(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n679(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n680(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n681(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n682(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n683(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n684(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n685(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n686(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n687(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n688(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n689(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n690(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n691(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n692(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n693(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n694(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n695(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n696(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n697(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n698(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n699(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n700(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n701(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n702(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n703(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n704(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n705(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n706(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n707(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n708(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n709(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n710(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n711(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n712(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n713(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n714(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n715(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n716(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n717(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n718(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n719(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n720(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n721(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n722(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n723(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n724(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n725(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n726(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n727(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n728(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n729(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n730(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n731(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n732(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n733(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n734(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n735(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n736(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n737(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n738(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n739(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n740(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n741(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n742(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n743(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n744(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n745(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n746(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n747(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n748(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n749(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n750(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n751(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n752(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n753(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n754(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n755(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n756(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n757(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n758(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n759(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n760(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n761(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n762(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n763(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n764(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n765(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n766(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n767(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n768(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n769(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n770(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n771(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n772(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n773(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n774(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n775(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n776(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n777(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n778(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n779(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n780(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n781(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n782(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n783(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n784(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n785(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n786(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n787(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n788(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n789(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n790(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n791(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n792(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n793(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n794(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n795(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n796(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n797(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n798(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n799(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n800(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n801(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n802(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n803(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n804(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n805(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n806(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n807(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n808(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n809(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n810(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n811(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n812(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n813(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n814(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n815(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n816(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n817(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n818(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n819(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n820(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n821(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n822(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n823(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n824(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n825(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n826(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n827(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n828(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n829(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n830(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n831(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n832(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n833(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n834(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n835(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n836(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n837(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n838(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n839(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n840(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n841(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n842(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n843(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n844(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n845(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n846(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n847(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n848(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n849(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n850(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n851(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n852(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n853(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n854(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n855(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n856(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n857(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n858(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n859(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n860(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n861(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n862(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n863(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n864(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n865(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n866(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n867(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n868(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n869(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n870(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n871(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n872(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n873(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n874(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n875(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n876(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n877(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n878(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n879(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n880(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n881(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n882(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n883(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n884(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n885(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n886(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n887(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n888(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n889(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n890(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n891(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n892(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n893(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n894(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n895(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n896(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n897(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n898(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n899(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n900(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n901(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n902(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n903(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n904(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n905(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n906(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n907(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n908(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n909(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n910(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n911(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n912(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n913(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n914(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n915(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n916(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n917(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n918(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n919(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n920(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n921(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n922(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n923(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n924(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n925(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n926(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n927(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n928(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n929(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n930(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n931(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n932(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n933(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n934(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n935(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n936(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n937(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n938(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n939(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n940(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n941(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n942(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n943(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n944(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n945(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n946(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n947(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n948(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n949(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n950(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n951(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n952(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n953(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n954(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n955(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n956(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n957(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n958(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n959(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n960(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n961(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n962(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n963(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n964(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n965(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n966(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n967(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n968(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n969(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n970(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n971(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n972(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n973(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n974(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n975(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n976(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n977(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n978(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n979(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n980(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n981(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n982(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n983(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n984(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n985(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n986(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n987(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n988(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n989(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n990(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n991(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n992(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n993(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n994(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n995(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n996(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n997(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n998(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +def fun_l29_n999(x) + if (x < 1) + inc(x) + else + inc(x) + end +end + +@a = 0 +@b = 0 +@c = 0 +@d = 0 + +@count = 0 +def inc(x) + @count += 1 +end + +@x = 0 + +100.times do + @x = (@x < 1)? 1:0 + fun_l0_n0(@x) + fun_l0_n1(@x) + fun_l0_n2(@x) + fun_l0_n3(@x) + fun_l0_n4(@x) + fun_l0_n5(@x) + fun_l0_n6(@x) + fun_l0_n7(@x) + fun_l0_n8(@x) + fun_l0_n9(@x) + fun_l0_n10(@x) + fun_l0_n11(@x) + fun_l0_n12(@x) + fun_l0_n13(@x) + fun_l0_n14(@x) + fun_l0_n15(@x) + fun_l0_n16(@x) + fun_l0_n17(@x) + fun_l0_n18(@x) + fun_l0_n19(@x) + fun_l0_n20(@x) + fun_l0_n21(@x) + fun_l0_n22(@x) + fun_l0_n23(@x) + fun_l0_n24(@x) + fun_l0_n25(@x) + fun_l0_n26(@x) + fun_l0_n27(@x) + fun_l0_n28(@x) + fun_l0_n29(@x) + fun_l0_n30(@x) + fun_l0_n31(@x) + fun_l0_n32(@x) + fun_l0_n33(@x) + fun_l0_n34(@x) + fun_l0_n35(@x) + fun_l0_n36(@x) + fun_l0_n37(@x) + fun_l0_n38(@x) + fun_l0_n39(@x) + fun_l0_n40(@x) + fun_l0_n41(@x) + fun_l0_n42(@x) + fun_l0_n43(@x) + fun_l0_n44(@x) + fun_l0_n45(@x) + fun_l0_n46(@x) + fun_l0_n47(@x) + fun_l0_n48(@x) + fun_l0_n49(@x) + fun_l0_n50(@x) + fun_l0_n51(@x) + fun_l0_n52(@x) + fun_l0_n53(@x) + fun_l0_n54(@x) + fun_l0_n55(@x) + fun_l0_n56(@x) + fun_l0_n57(@x) + fun_l0_n58(@x) + fun_l0_n59(@x) + fun_l0_n60(@x) + fun_l0_n61(@x) + fun_l0_n62(@x) + fun_l0_n63(@x) + fun_l0_n64(@x) + fun_l0_n65(@x) + fun_l0_n66(@x) + fun_l0_n67(@x) + fun_l0_n68(@x) + fun_l0_n69(@x) + fun_l0_n70(@x) + fun_l0_n71(@x) + fun_l0_n72(@x) + fun_l0_n73(@x) + fun_l0_n74(@x) + fun_l0_n75(@x) + fun_l0_n76(@x) + fun_l0_n77(@x) + fun_l0_n78(@x) + fun_l0_n79(@x) + fun_l0_n80(@x) + fun_l0_n81(@x) + fun_l0_n82(@x) + fun_l0_n83(@x) + fun_l0_n84(@x) + fun_l0_n85(@x) + fun_l0_n86(@x) + fun_l0_n87(@x) + fun_l0_n88(@x) + fun_l0_n89(@x) + fun_l0_n90(@x) + fun_l0_n91(@x) + fun_l0_n92(@x) + fun_l0_n93(@x) + fun_l0_n94(@x) + fun_l0_n95(@x) + fun_l0_n96(@x) + fun_l0_n97(@x) + fun_l0_n98(@x) + fun_l0_n99(@x) + fun_l0_n100(@x) + fun_l0_n101(@x) + fun_l0_n102(@x) + fun_l0_n103(@x) + fun_l0_n104(@x) + fun_l0_n105(@x) + fun_l0_n106(@x) + fun_l0_n107(@x) + fun_l0_n108(@x) + fun_l0_n109(@x) + fun_l0_n110(@x) + fun_l0_n111(@x) + fun_l0_n112(@x) + fun_l0_n113(@x) + fun_l0_n114(@x) + fun_l0_n115(@x) + fun_l0_n116(@x) + fun_l0_n117(@x) + fun_l0_n118(@x) + fun_l0_n119(@x) + fun_l0_n120(@x) + fun_l0_n121(@x) + fun_l0_n122(@x) + fun_l0_n123(@x) + fun_l0_n124(@x) + fun_l0_n125(@x) + fun_l0_n126(@x) + fun_l0_n127(@x) + fun_l0_n128(@x) + fun_l0_n129(@x) + fun_l0_n130(@x) + fun_l0_n131(@x) + fun_l0_n132(@x) + fun_l0_n133(@x) + fun_l0_n134(@x) + fun_l0_n135(@x) + fun_l0_n136(@x) + fun_l0_n137(@x) + fun_l0_n138(@x) + fun_l0_n139(@x) + fun_l0_n140(@x) + fun_l0_n141(@x) + fun_l0_n142(@x) + fun_l0_n143(@x) + fun_l0_n144(@x) + fun_l0_n145(@x) + fun_l0_n146(@x) + fun_l0_n147(@x) + fun_l0_n148(@x) + fun_l0_n149(@x) + fun_l0_n150(@x) + fun_l0_n151(@x) + fun_l0_n152(@x) + fun_l0_n153(@x) + fun_l0_n154(@x) + fun_l0_n155(@x) + fun_l0_n156(@x) + fun_l0_n157(@x) + fun_l0_n158(@x) + fun_l0_n159(@x) + fun_l0_n160(@x) + fun_l0_n161(@x) + fun_l0_n162(@x) + fun_l0_n163(@x) + fun_l0_n164(@x) + fun_l0_n165(@x) + fun_l0_n166(@x) + fun_l0_n167(@x) + fun_l0_n168(@x) + fun_l0_n169(@x) + fun_l0_n170(@x) + fun_l0_n171(@x) + fun_l0_n172(@x) + fun_l0_n173(@x) + fun_l0_n174(@x) + fun_l0_n175(@x) + fun_l0_n176(@x) + fun_l0_n177(@x) + fun_l0_n178(@x) + fun_l0_n179(@x) + fun_l0_n180(@x) + fun_l0_n181(@x) + fun_l0_n182(@x) + fun_l0_n183(@x) + fun_l0_n184(@x) + fun_l0_n185(@x) + fun_l0_n186(@x) + fun_l0_n187(@x) + fun_l0_n188(@x) + fun_l0_n189(@x) + fun_l0_n190(@x) + fun_l0_n191(@x) + fun_l0_n192(@x) + fun_l0_n193(@x) + fun_l0_n194(@x) + fun_l0_n195(@x) + fun_l0_n196(@x) + fun_l0_n197(@x) + fun_l0_n198(@x) + fun_l0_n199(@x) + fun_l0_n200(@x) + fun_l0_n201(@x) + fun_l0_n202(@x) + fun_l0_n203(@x) + fun_l0_n204(@x) + fun_l0_n205(@x) + fun_l0_n206(@x) + fun_l0_n207(@x) + fun_l0_n208(@x) + fun_l0_n209(@x) + fun_l0_n210(@x) + fun_l0_n211(@x) + fun_l0_n212(@x) + fun_l0_n213(@x) + fun_l0_n214(@x) + fun_l0_n215(@x) + fun_l0_n216(@x) + fun_l0_n217(@x) + fun_l0_n218(@x) + fun_l0_n219(@x) + fun_l0_n220(@x) + fun_l0_n221(@x) + fun_l0_n222(@x) + fun_l0_n223(@x) + fun_l0_n224(@x) + fun_l0_n225(@x) + fun_l0_n226(@x) + fun_l0_n227(@x) + fun_l0_n228(@x) + fun_l0_n229(@x) + fun_l0_n230(@x) + fun_l0_n231(@x) + fun_l0_n232(@x) + fun_l0_n233(@x) + fun_l0_n234(@x) + fun_l0_n235(@x) + fun_l0_n236(@x) + fun_l0_n237(@x) + fun_l0_n238(@x) + fun_l0_n239(@x) + fun_l0_n240(@x) + fun_l0_n241(@x) + fun_l0_n242(@x) + fun_l0_n243(@x) + fun_l0_n244(@x) + fun_l0_n245(@x) + fun_l0_n246(@x) + fun_l0_n247(@x) + fun_l0_n248(@x) + fun_l0_n249(@x) + fun_l0_n250(@x) + fun_l0_n251(@x) + fun_l0_n252(@x) + fun_l0_n253(@x) + fun_l0_n254(@x) + fun_l0_n255(@x) + fun_l0_n256(@x) + fun_l0_n257(@x) + fun_l0_n258(@x) + fun_l0_n259(@x) + fun_l0_n260(@x) + fun_l0_n261(@x) + fun_l0_n262(@x) + fun_l0_n263(@x) + fun_l0_n264(@x) + fun_l0_n265(@x) + fun_l0_n266(@x) + fun_l0_n267(@x) + fun_l0_n268(@x) + fun_l0_n269(@x) + fun_l0_n270(@x) + fun_l0_n271(@x) + fun_l0_n272(@x) + fun_l0_n273(@x) + fun_l0_n274(@x) + fun_l0_n275(@x) + fun_l0_n276(@x) + fun_l0_n277(@x) + fun_l0_n278(@x) + fun_l0_n279(@x) + fun_l0_n280(@x) + fun_l0_n281(@x) + fun_l0_n282(@x) + fun_l0_n283(@x) + fun_l0_n284(@x) + fun_l0_n285(@x) + fun_l0_n286(@x) + fun_l0_n287(@x) + fun_l0_n288(@x) + fun_l0_n289(@x) + fun_l0_n290(@x) + fun_l0_n291(@x) + fun_l0_n292(@x) + fun_l0_n293(@x) + fun_l0_n294(@x) + fun_l0_n295(@x) + fun_l0_n296(@x) + fun_l0_n297(@x) + fun_l0_n298(@x) + fun_l0_n299(@x) + fun_l0_n300(@x) + fun_l0_n301(@x) + fun_l0_n302(@x) + fun_l0_n303(@x) + fun_l0_n304(@x) + fun_l0_n305(@x) + fun_l0_n306(@x) + fun_l0_n307(@x) + fun_l0_n308(@x) + fun_l0_n309(@x) + fun_l0_n310(@x) + fun_l0_n311(@x) + fun_l0_n312(@x) + fun_l0_n313(@x) + fun_l0_n314(@x) + fun_l0_n315(@x) + fun_l0_n316(@x) + fun_l0_n317(@x) + fun_l0_n318(@x) + fun_l0_n319(@x) + fun_l0_n320(@x) + fun_l0_n321(@x) + fun_l0_n322(@x) + fun_l0_n323(@x) + fun_l0_n324(@x) + fun_l0_n325(@x) + fun_l0_n326(@x) + fun_l0_n327(@x) + fun_l0_n328(@x) + fun_l0_n329(@x) + fun_l0_n330(@x) + fun_l0_n331(@x) + fun_l0_n332(@x) + fun_l0_n333(@x) + fun_l0_n334(@x) + fun_l0_n335(@x) + fun_l0_n336(@x) + fun_l0_n337(@x) + fun_l0_n338(@x) + fun_l0_n339(@x) + fun_l0_n340(@x) + fun_l0_n341(@x) + fun_l0_n342(@x) + fun_l0_n343(@x) + fun_l0_n344(@x) + fun_l0_n345(@x) + fun_l0_n346(@x) + fun_l0_n347(@x) + fun_l0_n348(@x) + fun_l0_n349(@x) + fun_l0_n350(@x) + fun_l0_n351(@x) + fun_l0_n352(@x) + fun_l0_n353(@x) + fun_l0_n354(@x) + fun_l0_n355(@x) + fun_l0_n356(@x) + fun_l0_n357(@x) + fun_l0_n358(@x) + fun_l0_n359(@x) + fun_l0_n360(@x) + fun_l0_n361(@x) + fun_l0_n362(@x) + fun_l0_n363(@x) + fun_l0_n364(@x) + fun_l0_n365(@x) + fun_l0_n366(@x) + fun_l0_n367(@x) + fun_l0_n368(@x) + fun_l0_n369(@x) + fun_l0_n370(@x) + fun_l0_n371(@x) + fun_l0_n372(@x) + fun_l0_n373(@x) + fun_l0_n374(@x) + fun_l0_n375(@x) + fun_l0_n376(@x) + fun_l0_n377(@x) + fun_l0_n378(@x) + fun_l0_n379(@x) + fun_l0_n380(@x) + fun_l0_n381(@x) + fun_l0_n382(@x) + fun_l0_n383(@x) + fun_l0_n384(@x) + fun_l0_n385(@x) + fun_l0_n386(@x) + fun_l0_n387(@x) + fun_l0_n388(@x) + fun_l0_n389(@x) + fun_l0_n390(@x) + fun_l0_n391(@x) + fun_l0_n392(@x) + fun_l0_n393(@x) + fun_l0_n394(@x) + fun_l0_n395(@x) + fun_l0_n396(@x) + fun_l0_n397(@x) + fun_l0_n398(@x) + fun_l0_n399(@x) + fun_l0_n400(@x) + fun_l0_n401(@x) + fun_l0_n402(@x) + fun_l0_n403(@x) + fun_l0_n404(@x) + fun_l0_n405(@x) + fun_l0_n406(@x) + fun_l0_n407(@x) + fun_l0_n408(@x) + fun_l0_n409(@x) + fun_l0_n410(@x) + fun_l0_n411(@x) + fun_l0_n412(@x) + fun_l0_n413(@x) + fun_l0_n414(@x) + fun_l0_n415(@x) + fun_l0_n416(@x) + fun_l0_n417(@x) + fun_l0_n418(@x) + fun_l0_n419(@x) + fun_l0_n420(@x) + fun_l0_n421(@x) + fun_l0_n422(@x) + fun_l0_n423(@x) + fun_l0_n424(@x) + fun_l0_n425(@x) + fun_l0_n426(@x) + fun_l0_n427(@x) + fun_l0_n428(@x) + fun_l0_n429(@x) + fun_l0_n430(@x) + fun_l0_n431(@x) + fun_l0_n432(@x) + fun_l0_n433(@x) + fun_l0_n434(@x) + fun_l0_n435(@x) + fun_l0_n436(@x) + fun_l0_n437(@x) + fun_l0_n438(@x) + fun_l0_n439(@x) + fun_l0_n440(@x) + fun_l0_n441(@x) + fun_l0_n442(@x) + fun_l0_n443(@x) + fun_l0_n444(@x) + fun_l0_n445(@x) + fun_l0_n446(@x) + fun_l0_n447(@x) + fun_l0_n448(@x) + fun_l0_n449(@x) + fun_l0_n450(@x) + fun_l0_n451(@x) + fun_l0_n452(@x) + fun_l0_n453(@x) + fun_l0_n454(@x) + fun_l0_n455(@x) + fun_l0_n456(@x) + fun_l0_n457(@x) + fun_l0_n458(@x) + fun_l0_n459(@x) + fun_l0_n460(@x) + fun_l0_n461(@x) + fun_l0_n462(@x) + fun_l0_n463(@x) + fun_l0_n464(@x) + fun_l0_n465(@x) + fun_l0_n466(@x) + fun_l0_n467(@x) + fun_l0_n468(@x) + fun_l0_n469(@x) + fun_l0_n470(@x) + fun_l0_n471(@x) + fun_l0_n472(@x) + fun_l0_n473(@x) + fun_l0_n474(@x) + fun_l0_n475(@x) + fun_l0_n476(@x) + fun_l0_n477(@x) + fun_l0_n478(@x) + fun_l0_n479(@x) + fun_l0_n480(@x) + fun_l0_n481(@x) + fun_l0_n482(@x) + fun_l0_n483(@x) + fun_l0_n484(@x) + fun_l0_n485(@x) + fun_l0_n486(@x) + fun_l0_n487(@x) + fun_l0_n488(@x) + fun_l0_n489(@x) + fun_l0_n490(@x) + fun_l0_n491(@x) + fun_l0_n492(@x) + fun_l0_n493(@x) + fun_l0_n494(@x) + fun_l0_n495(@x) + fun_l0_n496(@x) + fun_l0_n497(@x) + fun_l0_n498(@x) + fun_l0_n499(@x) + fun_l0_n500(@x) + fun_l0_n501(@x) + fun_l0_n502(@x) + fun_l0_n503(@x) + fun_l0_n504(@x) + fun_l0_n505(@x) + fun_l0_n506(@x) + fun_l0_n507(@x) + fun_l0_n508(@x) + fun_l0_n509(@x) + fun_l0_n510(@x) + fun_l0_n511(@x) + fun_l0_n512(@x) + fun_l0_n513(@x) + fun_l0_n514(@x) + fun_l0_n515(@x) + fun_l0_n516(@x) + fun_l0_n517(@x) + fun_l0_n518(@x) + fun_l0_n519(@x) + fun_l0_n520(@x) + fun_l0_n521(@x) + fun_l0_n522(@x) + fun_l0_n523(@x) + fun_l0_n524(@x) + fun_l0_n525(@x) + fun_l0_n526(@x) + fun_l0_n527(@x) + fun_l0_n528(@x) + fun_l0_n529(@x) + fun_l0_n530(@x) + fun_l0_n531(@x) + fun_l0_n532(@x) + fun_l0_n533(@x) + fun_l0_n534(@x) + fun_l0_n535(@x) + fun_l0_n536(@x) + fun_l0_n537(@x) + fun_l0_n538(@x) + fun_l0_n539(@x) + fun_l0_n540(@x) + fun_l0_n541(@x) + fun_l0_n542(@x) + fun_l0_n543(@x) + fun_l0_n544(@x) + fun_l0_n545(@x) + fun_l0_n546(@x) + fun_l0_n547(@x) + fun_l0_n548(@x) + fun_l0_n549(@x) + fun_l0_n550(@x) + fun_l0_n551(@x) + fun_l0_n552(@x) + fun_l0_n553(@x) + fun_l0_n554(@x) + fun_l0_n555(@x) + fun_l0_n556(@x) + fun_l0_n557(@x) + fun_l0_n558(@x) + fun_l0_n559(@x) + fun_l0_n560(@x) + fun_l0_n561(@x) + fun_l0_n562(@x) + fun_l0_n563(@x) + fun_l0_n564(@x) + fun_l0_n565(@x) + fun_l0_n566(@x) + fun_l0_n567(@x) + fun_l0_n568(@x) + fun_l0_n569(@x) + fun_l0_n570(@x) + fun_l0_n571(@x) + fun_l0_n572(@x) + fun_l0_n573(@x) + fun_l0_n574(@x) + fun_l0_n575(@x) + fun_l0_n576(@x) + fun_l0_n577(@x) + fun_l0_n578(@x) + fun_l0_n579(@x) + fun_l0_n580(@x) + fun_l0_n581(@x) + fun_l0_n582(@x) + fun_l0_n583(@x) + fun_l0_n584(@x) + fun_l0_n585(@x) + fun_l0_n586(@x) + fun_l0_n587(@x) + fun_l0_n588(@x) + fun_l0_n589(@x) + fun_l0_n590(@x) + fun_l0_n591(@x) + fun_l0_n592(@x) + fun_l0_n593(@x) + fun_l0_n594(@x) + fun_l0_n595(@x) + fun_l0_n596(@x) + fun_l0_n597(@x) + fun_l0_n598(@x) + fun_l0_n599(@x) + fun_l0_n600(@x) + fun_l0_n601(@x) + fun_l0_n602(@x) + fun_l0_n603(@x) + fun_l0_n604(@x) + fun_l0_n605(@x) + fun_l0_n606(@x) + fun_l0_n607(@x) + fun_l0_n608(@x) + fun_l0_n609(@x) + fun_l0_n610(@x) + fun_l0_n611(@x) + fun_l0_n612(@x) + fun_l0_n613(@x) + fun_l0_n614(@x) + fun_l0_n615(@x) + fun_l0_n616(@x) + fun_l0_n617(@x) + fun_l0_n618(@x) + fun_l0_n619(@x) + fun_l0_n620(@x) + fun_l0_n621(@x) + fun_l0_n622(@x) + fun_l0_n623(@x) + fun_l0_n624(@x) + fun_l0_n625(@x) + fun_l0_n626(@x) + fun_l0_n627(@x) + fun_l0_n628(@x) + fun_l0_n629(@x) + fun_l0_n630(@x) + fun_l0_n631(@x) + fun_l0_n632(@x) + fun_l0_n633(@x) + fun_l0_n634(@x) + fun_l0_n635(@x) + fun_l0_n636(@x) + fun_l0_n637(@x) + fun_l0_n638(@x) + fun_l0_n639(@x) + fun_l0_n640(@x) + fun_l0_n641(@x) + fun_l0_n642(@x) + fun_l0_n643(@x) + fun_l0_n644(@x) + fun_l0_n645(@x) + fun_l0_n646(@x) + fun_l0_n647(@x) + fun_l0_n648(@x) + fun_l0_n649(@x) + fun_l0_n650(@x) + fun_l0_n651(@x) + fun_l0_n652(@x) + fun_l0_n653(@x) + fun_l0_n654(@x) + fun_l0_n655(@x) + fun_l0_n656(@x) + fun_l0_n657(@x) + fun_l0_n658(@x) + fun_l0_n659(@x) + fun_l0_n660(@x) + fun_l0_n661(@x) + fun_l0_n662(@x) + fun_l0_n663(@x) + fun_l0_n664(@x) + fun_l0_n665(@x) + fun_l0_n666(@x) + fun_l0_n667(@x) + fun_l0_n668(@x) + fun_l0_n669(@x) + fun_l0_n670(@x) + fun_l0_n671(@x) + fun_l0_n672(@x) + fun_l0_n673(@x) + fun_l0_n674(@x) + fun_l0_n675(@x) + fun_l0_n676(@x) + fun_l0_n677(@x) + fun_l0_n678(@x) + fun_l0_n679(@x) + fun_l0_n680(@x) + fun_l0_n681(@x) + fun_l0_n682(@x) + fun_l0_n683(@x) + fun_l0_n684(@x) + fun_l0_n685(@x) + fun_l0_n686(@x) + fun_l0_n687(@x) + fun_l0_n688(@x) + fun_l0_n689(@x) + fun_l0_n690(@x) + fun_l0_n691(@x) + fun_l0_n692(@x) + fun_l0_n693(@x) + fun_l0_n694(@x) + fun_l0_n695(@x) + fun_l0_n696(@x) + fun_l0_n697(@x) + fun_l0_n698(@x) + fun_l0_n699(@x) + fun_l0_n700(@x) + fun_l0_n701(@x) + fun_l0_n702(@x) + fun_l0_n703(@x) + fun_l0_n704(@x) + fun_l0_n705(@x) + fun_l0_n706(@x) + fun_l0_n707(@x) + fun_l0_n708(@x) + fun_l0_n709(@x) + fun_l0_n710(@x) + fun_l0_n711(@x) + fun_l0_n712(@x) + fun_l0_n713(@x) + fun_l0_n714(@x) + fun_l0_n715(@x) + fun_l0_n716(@x) + fun_l0_n717(@x) + fun_l0_n718(@x) + fun_l0_n719(@x) + fun_l0_n720(@x) + fun_l0_n721(@x) + fun_l0_n722(@x) + fun_l0_n723(@x) + fun_l0_n724(@x) + fun_l0_n725(@x) + fun_l0_n726(@x) + fun_l0_n727(@x) + fun_l0_n728(@x) + fun_l0_n729(@x) + fun_l0_n730(@x) + fun_l0_n731(@x) + fun_l0_n732(@x) + fun_l0_n733(@x) + fun_l0_n734(@x) + fun_l0_n735(@x) + fun_l0_n736(@x) + fun_l0_n737(@x) + fun_l0_n738(@x) + fun_l0_n739(@x) + fun_l0_n740(@x) + fun_l0_n741(@x) + fun_l0_n742(@x) + fun_l0_n743(@x) + fun_l0_n744(@x) + fun_l0_n745(@x) + fun_l0_n746(@x) + fun_l0_n747(@x) + fun_l0_n748(@x) + fun_l0_n749(@x) + fun_l0_n750(@x) + fun_l0_n751(@x) + fun_l0_n752(@x) + fun_l0_n753(@x) + fun_l0_n754(@x) + fun_l0_n755(@x) + fun_l0_n756(@x) + fun_l0_n757(@x) + fun_l0_n758(@x) + fun_l0_n759(@x) + fun_l0_n760(@x) + fun_l0_n761(@x) + fun_l0_n762(@x) + fun_l0_n763(@x) + fun_l0_n764(@x) + fun_l0_n765(@x) + fun_l0_n766(@x) + fun_l0_n767(@x) + fun_l0_n768(@x) + fun_l0_n769(@x) + fun_l0_n770(@x) + fun_l0_n771(@x) + fun_l0_n772(@x) + fun_l0_n773(@x) + fun_l0_n774(@x) + fun_l0_n775(@x) + fun_l0_n776(@x) + fun_l0_n777(@x) + fun_l0_n778(@x) + fun_l0_n779(@x) + fun_l0_n780(@x) + fun_l0_n781(@x) + fun_l0_n782(@x) + fun_l0_n783(@x) + fun_l0_n784(@x) + fun_l0_n785(@x) + fun_l0_n786(@x) + fun_l0_n787(@x) + fun_l0_n788(@x) + fun_l0_n789(@x) + fun_l0_n790(@x) + fun_l0_n791(@x) + fun_l0_n792(@x) + fun_l0_n793(@x) + fun_l0_n794(@x) + fun_l0_n795(@x) + fun_l0_n796(@x) + fun_l0_n797(@x) + fun_l0_n798(@x) + fun_l0_n799(@x) + fun_l0_n800(@x) + fun_l0_n801(@x) + fun_l0_n802(@x) + fun_l0_n803(@x) + fun_l0_n804(@x) + fun_l0_n805(@x) + fun_l0_n806(@x) + fun_l0_n807(@x) + fun_l0_n808(@x) + fun_l0_n809(@x) + fun_l0_n810(@x) + fun_l0_n811(@x) + fun_l0_n812(@x) + fun_l0_n813(@x) + fun_l0_n814(@x) + fun_l0_n815(@x) + fun_l0_n816(@x) + fun_l0_n817(@x) + fun_l0_n818(@x) + fun_l0_n819(@x) + fun_l0_n820(@x) + fun_l0_n821(@x) + fun_l0_n822(@x) + fun_l0_n823(@x) + fun_l0_n824(@x) + fun_l0_n825(@x) + fun_l0_n826(@x) + fun_l0_n827(@x) + fun_l0_n828(@x) + fun_l0_n829(@x) + fun_l0_n830(@x) + fun_l0_n831(@x) + fun_l0_n832(@x) + fun_l0_n833(@x) + fun_l0_n834(@x) + fun_l0_n835(@x) + fun_l0_n836(@x) + fun_l0_n837(@x) + fun_l0_n838(@x) + fun_l0_n839(@x) + fun_l0_n840(@x) + fun_l0_n841(@x) + fun_l0_n842(@x) + fun_l0_n843(@x) + fun_l0_n844(@x) + fun_l0_n845(@x) + fun_l0_n846(@x) + fun_l0_n847(@x) + fun_l0_n848(@x) + fun_l0_n849(@x) + fun_l0_n850(@x) + fun_l0_n851(@x) + fun_l0_n852(@x) + fun_l0_n853(@x) + fun_l0_n854(@x) + fun_l0_n855(@x) + fun_l0_n856(@x) + fun_l0_n857(@x) + fun_l0_n858(@x) + fun_l0_n859(@x) + fun_l0_n860(@x) + fun_l0_n861(@x) + fun_l0_n862(@x) + fun_l0_n863(@x) + fun_l0_n864(@x) + fun_l0_n865(@x) + fun_l0_n866(@x) + fun_l0_n867(@x) + fun_l0_n868(@x) + fun_l0_n869(@x) + fun_l0_n870(@x) + fun_l0_n871(@x) + fun_l0_n872(@x) + fun_l0_n873(@x) + fun_l0_n874(@x) + fun_l0_n875(@x) + fun_l0_n876(@x) + fun_l0_n877(@x) + fun_l0_n878(@x) + fun_l0_n879(@x) + fun_l0_n880(@x) + fun_l0_n881(@x) + fun_l0_n882(@x) + fun_l0_n883(@x) + fun_l0_n884(@x) + fun_l0_n885(@x) + fun_l0_n886(@x) + fun_l0_n887(@x) + fun_l0_n888(@x) + fun_l0_n889(@x) + fun_l0_n890(@x) + fun_l0_n891(@x) + fun_l0_n892(@x) + fun_l0_n893(@x) + fun_l0_n894(@x) + fun_l0_n895(@x) + fun_l0_n896(@x) + fun_l0_n897(@x) + fun_l0_n898(@x) + fun_l0_n899(@x) + fun_l0_n900(@x) + fun_l0_n901(@x) + fun_l0_n902(@x) + fun_l0_n903(@x) + fun_l0_n904(@x) + fun_l0_n905(@x) + fun_l0_n906(@x) + fun_l0_n907(@x) + fun_l0_n908(@x) + fun_l0_n909(@x) + fun_l0_n910(@x) + fun_l0_n911(@x) + fun_l0_n912(@x) + fun_l0_n913(@x) + fun_l0_n914(@x) + fun_l0_n915(@x) + fun_l0_n916(@x) + fun_l0_n917(@x) + fun_l0_n918(@x) + fun_l0_n919(@x) + fun_l0_n920(@x) + fun_l0_n921(@x) + fun_l0_n922(@x) + fun_l0_n923(@x) + fun_l0_n924(@x) + fun_l0_n925(@x) + fun_l0_n926(@x) + fun_l0_n927(@x) + fun_l0_n928(@x) + fun_l0_n929(@x) + fun_l0_n930(@x) + fun_l0_n931(@x) + fun_l0_n932(@x) + fun_l0_n933(@x) + fun_l0_n934(@x) + fun_l0_n935(@x) + fun_l0_n936(@x) + fun_l0_n937(@x) + fun_l0_n938(@x) + fun_l0_n939(@x) + fun_l0_n940(@x) + fun_l0_n941(@x) + fun_l0_n942(@x) + fun_l0_n943(@x) + fun_l0_n944(@x) + fun_l0_n945(@x) + fun_l0_n946(@x) + fun_l0_n947(@x) + fun_l0_n948(@x) + fun_l0_n949(@x) + fun_l0_n950(@x) + fun_l0_n951(@x) + fun_l0_n952(@x) + fun_l0_n953(@x) + fun_l0_n954(@x) + fun_l0_n955(@x) + fun_l0_n956(@x) + fun_l0_n957(@x) + fun_l0_n958(@x) + fun_l0_n959(@x) + fun_l0_n960(@x) + fun_l0_n961(@x) + fun_l0_n962(@x) + fun_l0_n963(@x) + fun_l0_n964(@x) + fun_l0_n965(@x) + fun_l0_n966(@x) + fun_l0_n967(@x) + fun_l0_n968(@x) + fun_l0_n969(@x) + fun_l0_n970(@x) + fun_l0_n971(@x) + fun_l0_n972(@x) + fun_l0_n973(@x) + fun_l0_n974(@x) + fun_l0_n975(@x) + fun_l0_n976(@x) + fun_l0_n977(@x) + fun_l0_n978(@x) + fun_l0_n979(@x) + fun_l0_n980(@x) + fun_l0_n981(@x) + fun_l0_n982(@x) + fun_l0_n983(@x) + fun_l0_n984(@x) + fun_l0_n985(@x) + fun_l0_n986(@x) + fun_l0_n987(@x) + fun_l0_n988(@x) + fun_l0_n989(@x) + fun_l0_n990(@x) + fun_l0_n991(@x) + fun_l0_n992(@x) + fun_l0_n993(@x) + fun_l0_n994(@x) + fun_l0_n995(@x) + fun_l0_n996(@x) + fun_l0_n997(@x) + fun_l0_n998(@x) + fun_l0_n999(@x) +end + +@count + +} diff --git a/ruby/bootstraptest/test_yjit_30k_methods.rb b/ruby/bootstraptest/test_yjit_30k_methods.rb new file mode 100644 index 000000000..f2acea4ce --- /dev/null +++ b/ruby/bootstraptest/test_yjit_30k_methods.rb @@ -0,0 +1,121018 @@ +# This is a torture test for the JIT. +# There are 30K tiny methods in a 30-deep call hierarchy. +assert_equal '1000000', %q{ + +def fun_l0_n0() + fun_l1_n758 +end + +def fun_l0_n1() + fun_l1_n491 +end + +def fun_l0_n2() + fun_l1_n804 +end + +def fun_l0_n3() + fun_l1_n253 +end + +def fun_l0_n4() + fun_l1_n409 +end + +def fun_l0_n5() + fun_l1_n383 +end + +def fun_l0_n6() + fun_l1_n170 +end + +def fun_l0_n7() + fun_l1_n821 +end + +def fun_l0_n8() + fun_l1_n424 +end + +def fun_l0_n9() + fun_l1_n328 +end + +def fun_l0_n10() + fun_l1_n326 +end + +def fun_l0_n11() + fun_l1_n879 +end + +def fun_l0_n12() + fun_l1_n509 +end + +def fun_l0_n13() + fun_l1_n464 +end + +def fun_l0_n14() + fun_l1_n806 +end + +def fun_l0_n15() + fun_l1_n277 +end + +def fun_l0_n16() + fun_l1_n684 +end + +def fun_l0_n17() + fun_l1_n54 +end + +def fun_l0_n18() + fun_l1_n514 +end + +def fun_l0_n19() + fun_l1_n967 +end + +def fun_l0_n20() + fun_l1_n50 +end + +def fun_l0_n21() + fun_l1_n248 +end + +def fun_l0_n22() + fun_l1_n410 +end + +def fun_l0_n23() + fun_l1_n411 +end + +def fun_l0_n24() + fun_l1_n422 +end + +def fun_l0_n25() + fun_l1_n427 +end + +def fun_l0_n26() + fun_l1_n929 +end + +def fun_l0_n27() + fun_l1_n93 +end + +def fun_l0_n28() + fun_l1_n790 +end + +def fun_l0_n29() + fun_l1_n107 +end + +def fun_l0_n30() + fun_l1_n29 +end + +def fun_l0_n31() + fun_l1_n164 +end + +def fun_l0_n32() + fun_l1_n720 +end + +def fun_l0_n33() + fun_l1_n30 +end + +def fun_l0_n34() + fun_l1_n133 +end + +def fun_l0_n35() + fun_l1_n122 +end + +def fun_l0_n36() + fun_l1_n101 +end + +def fun_l0_n37() + fun_l1_n80 +end + +def fun_l0_n38() + fun_l1_n759 +end + +def fun_l0_n39() + fun_l1_n315 +end + +def fun_l0_n40() + fun_l1_n508 +end + +def fun_l0_n41() + fun_l1_n750 +end + +def fun_l0_n42() + fun_l1_n200 +end + +def fun_l0_n43() + fun_l1_n662 +end + +def fun_l0_n44() + fun_l1_n2 +end + +def fun_l0_n45() + fun_l1_n864 +end + +def fun_l0_n46() + fun_l1_n482 +end + +def fun_l0_n47() + fun_l1_n196 +end + +def fun_l0_n48() + fun_l1_n867 +end + +def fun_l0_n49() + fun_l1_n942 +end + +def fun_l0_n50() + fun_l1_n179 +end + +def fun_l0_n51() + fun_l1_n442 +end + +def fun_l0_n52() + fun_l1_n613 +end + +def fun_l0_n53() + fun_l1_n282 +end + +def fun_l0_n54() + fun_l1_n624 +end + +def fun_l0_n55() + fun_l1_n514 +end + +def fun_l0_n56() + fun_l1_n59 +end + +def fun_l0_n57() + fun_l1_n401 +end + +def fun_l0_n58() + fun_l1_n693 +end + +def fun_l0_n59() + fun_l1_n643 +end + +def fun_l0_n60() + fun_l1_n104 +end + +def fun_l0_n61() + fun_l1_n407 +end + +def fun_l0_n62() + fun_l1_n418 +end + +def fun_l0_n63() + fun_l1_n775 +end + +def fun_l0_n64() + fun_l1_n351 +end + +def fun_l0_n65() + fun_l1_n320 +end + +def fun_l0_n66() + fun_l1_n181 +end + +def fun_l0_n67() + fun_l1_n878 +end + +def fun_l0_n68() + fun_l1_n404 +end + +def fun_l0_n69() + fun_l1_n660 +end + +def fun_l0_n70() + fun_l1_n644 +end + +def fun_l0_n71() + fun_l1_n416 +end + +def fun_l0_n72() + fun_l1_n372 +end + +def fun_l0_n73() + fun_l1_n525 +end + +def fun_l0_n74() + fun_l1_n468 +end + +def fun_l0_n75() + fun_l1_n652 +end + +def fun_l0_n76() + fun_l1_n418 +end + +def fun_l0_n77() + fun_l1_n935 +end + +def fun_l0_n78() + fun_l1_n170 +end + +def fun_l0_n79() + fun_l1_n805 +end + +def fun_l0_n80() + fun_l1_n405 +end + +def fun_l0_n81() + fun_l1_n994 +end + +def fun_l0_n82() + fun_l1_n395 +end + +def fun_l0_n83() + fun_l1_n399 +end + +def fun_l0_n84() + fun_l1_n503 +end + +def fun_l0_n85() + fun_l1_n451 +end + +def fun_l0_n86() + fun_l1_n920 +end + +def fun_l0_n87() + fun_l1_n446 +end + +def fun_l0_n88() + fun_l1_n637 +end + +def fun_l0_n89() + fun_l1_n732 +end + +def fun_l0_n90() + fun_l1_n823 +end + +def fun_l0_n91() + fun_l1_n347 +end + +def fun_l0_n92() + fun_l1_n808 +end + +def fun_l0_n93() + fun_l1_n941 +end + +def fun_l0_n94() + fun_l1_n808 +end + +def fun_l0_n95() + fun_l1_n575 +end + +def fun_l0_n96() + fun_l1_n835 +end + +def fun_l0_n97() + fun_l1_n601 +end + +def fun_l0_n98() + fun_l1_n522 +end + +def fun_l0_n99() + fun_l1_n884 +end + +def fun_l0_n100() + fun_l1_n234 +end + +def fun_l0_n101() + fun_l1_n58 +end + +def fun_l0_n102() + fun_l1_n702 +end + +def fun_l0_n103() + fun_l1_n816 +end + +def fun_l0_n104() + fun_l1_n92 +end + +def fun_l0_n105() + fun_l1_n673 +end + +def fun_l0_n106() + fun_l1_n360 +end + +def fun_l0_n107() + fun_l1_n305 +end + +def fun_l0_n108() + fun_l1_n202 +end + +def fun_l0_n109() + fun_l1_n879 +end + +def fun_l0_n110() + fun_l1_n84 +end + +def fun_l0_n111() + fun_l1_n50 +end + +def fun_l0_n112() + fun_l1_n648 +end + +def fun_l0_n113() + fun_l1_n786 +end + +def fun_l0_n114() + fun_l1_n627 +end + +def fun_l0_n115() + fun_l1_n404 +end + +def fun_l0_n116() + fun_l1_n496 +end + +def fun_l0_n117() + fun_l1_n778 +end + +def fun_l0_n118() + fun_l1_n119 +end + +def fun_l0_n119() + fun_l1_n350 +end + +def fun_l0_n120() + fun_l1_n767 +end + +def fun_l0_n121() + fun_l1_n463 +end + +def fun_l0_n122() + fun_l1_n481 +end + +def fun_l0_n123() + fun_l1_n80 +end + +def fun_l0_n124() + fun_l1_n271 +end + +def fun_l0_n125() + fun_l1_n315 +end + +def fun_l0_n126() + fun_l1_n545 +end + +def fun_l0_n127() + fun_l1_n598 +end + +def fun_l0_n128() + fun_l1_n599 +end + +def fun_l0_n129() + fun_l1_n263 +end + +def fun_l0_n130() + fun_l1_n514 +end + +def fun_l0_n131() + fun_l1_n779 +end + +def fun_l0_n132() + fun_l1_n585 +end + +def fun_l0_n133() + fun_l1_n919 +end + +def fun_l0_n134() + fun_l1_n665 +end + +def fun_l0_n135() + fun_l1_n442 +end + +def fun_l0_n136() + fun_l1_n84 +end + +def fun_l0_n137() + fun_l1_n74 +end + +def fun_l0_n138() + fun_l1_n606 +end + +def fun_l0_n139() + fun_l1_n655 +end + +def fun_l0_n140() + fun_l1_n130 +end + +def fun_l0_n141() + fun_l1_n626 +end + +def fun_l0_n142() + fun_l1_n605 +end + +def fun_l0_n143() + fun_l1_n420 +end + +def fun_l0_n144() + fun_l1_n100 +end + +def fun_l0_n145() + fun_l1_n961 +end + +def fun_l0_n146() + fun_l1_n721 +end + +def fun_l0_n147() + fun_l1_n453 +end + +def fun_l0_n148() + fun_l1_n737 +end + +def fun_l0_n149() + fun_l1_n230 +end + +def fun_l0_n150() + fun_l1_n881 +end + +def fun_l0_n151() + fun_l1_n471 +end + +def fun_l0_n152() + fun_l1_n72 +end + +def fun_l0_n153() + fun_l1_n221 +end + +def fun_l0_n154() + fun_l1_n504 +end + +def fun_l0_n155() + fun_l1_n222 +end + +def fun_l0_n156() + fun_l1_n348 +end + +def fun_l0_n157() + fun_l1_n738 +end + +def fun_l0_n158() + fun_l1_n588 +end + +def fun_l0_n159() + fun_l1_n64 +end + +def fun_l0_n160() + fun_l1_n829 +end + +def fun_l0_n161() + fun_l1_n265 +end + +def fun_l0_n162() + fun_l1_n471 +end + +def fun_l0_n163() + fun_l1_n304 +end + +def fun_l0_n164() + fun_l1_n518 +end + +def fun_l0_n165() + fun_l1_n89 +end + +def fun_l0_n166() + fun_l1_n728 +end + +def fun_l0_n167() + fun_l1_n292 +end + +def fun_l0_n168() + fun_l1_n142 +end + +def fun_l0_n169() + fun_l1_n374 +end + +def fun_l0_n170() + fun_l1_n371 +end + +def fun_l0_n171() + fun_l1_n904 +end + +def fun_l0_n172() + fun_l1_n519 +end + +def fun_l0_n173() + fun_l1_n239 +end + +def fun_l0_n174() + fun_l1_n664 +end + +def fun_l0_n175() + fun_l1_n701 +end + +def fun_l0_n176() + fun_l1_n586 +end + +def fun_l0_n177() + fun_l1_n78 +end + +def fun_l0_n178() + fun_l1_n663 +end + +def fun_l0_n179() + fun_l1_n46 +end + +def fun_l0_n180() + fun_l1_n273 +end + +def fun_l0_n181() + fun_l1_n250 +end + +def fun_l0_n182() + fun_l1_n362 +end + +def fun_l0_n183() + fun_l1_n69 +end + +def fun_l0_n184() + fun_l1_n874 +end + +def fun_l0_n185() + fun_l1_n135 +end + +def fun_l0_n186() + fun_l1_n634 +end + +def fun_l0_n187() + fun_l1_n885 +end + +def fun_l0_n188() + fun_l1_n589 +end + +def fun_l0_n189() + fun_l1_n21 +end + +def fun_l0_n190() + fun_l1_n962 +end + +def fun_l0_n191() + fun_l1_n267 +end + +def fun_l0_n192() + fun_l1_n569 +end + +def fun_l0_n193() + fun_l1_n921 +end + +def fun_l0_n194() + fun_l1_n535 +end + +def fun_l0_n195() + fun_l1_n362 +end + +def fun_l0_n196() + fun_l1_n862 +end + +def fun_l0_n197() + fun_l1_n565 +end + +def fun_l0_n198() + fun_l1_n779 +end + +def fun_l0_n199() + fun_l1_n848 +end + +def fun_l0_n200() + fun_l1_n755 +end + +def fun_l0_n201() + fun_l1_n493 +end + +def fun_l0_n202() + fun_l1_n574 +end + +def fun_l0_n203() + fun_l1_n172 +end + +def fun_l0_n204() + fun_l1_n388 +end + +def fun_l0_n205() + fun_l1_n67 +end + +def fun_l0_n206() + fun_l1_n449 +end + +def fun_l0_n207() + fun_l1_n883 +end + +def fun_l0_n208() + fun_l1_n749 +end + +def fun_l0_n209() + fun_l1_n425 +end + +def fun_l0_n210() + fun_l1_n848 +end + +def fun_l0_n211() + fun_l1_n320 +end + +def fun_l0_n212() + fun_l1_n122 +end + +def fun_l0_n213() + fun_l1_n878 +end + +def fun_l0_n214() + fun_l1_n763 +end + +def fun_l0_n215() + fun_l1_n70 +end + +def fun_l0_n216() + fun_l1_n494 +end + +def fun_l0_n217() + fun_l1_n13 +end + +def fun_l0_n218() + fun_l1_n907 +end + +def fun_l0_n219() + fun_l1_n775 +end + +def fun_l0_n220() + fun_l1_n633 +end + +def fun_l0_n221() + fun_l1_n371 +end + +def fun_l0_n222() + fun_l1_n691 +end + +def fun_l0_n223() + fun_l1_n994 +end + +def fun_l0_n224() + fun_l1_n268 +end + +def fun_l0_n225() + fun_l1_n52 +end + +def fun_l0_n226() + fun_l1_n291 +end + +def fun_l0_n227() + fun_l1_n903 +end + +def fun_l0_n228() + fun_l1_n369 +end + +def fun_l0_n229() + fun_l1_n232 +end + +def fun_l0_n230() + fun_l1_n554 +end + +def fun_l0_n231() + fun_l1_n479 +end + +def fun_l0_n232() + fun_l1_n838 +end + +def fun_l0_n233() + fun_l1_n316 +end + +def fun_l0_n234() + fun_l1_n685 +end + +def fun_l0_n235() + fun_l1_n95 +end + +def fun_l0_n236() + fun_l1_n629 +end + +def fun_l0_n237() + fun_l1_n218 +end + +def fun_l0_n238() + fun_l1_n406 +end + +def fun_l0_n239() + fun_l1_n187 +end + +def fun_l0_n240() + fun_l1_n905 +end + +def fun_l0_n241() + fun_l1_n262 +end + +def fun_l0_n242() + fun_l1_n314 +end + +def fun_l0_n243() + fun_l1_n669 +end + +def fun_l0_n244() + fun_l1_n112 +end + +def fun_l0_n245() + fun_l1_n744 +end + +def fun_l0_n246() + fun_l1_n637 +end + +def fun_l0_n247() + fun_l1_n409 +end + +def fun_l0_n248() + fun_l1_n706 +end + +def fun_l0_n249() + fun_l1_n150 +end + +def fun_l0_n250() + fun_l1_n863 +end + +def fun_l0_n251() + fun_l1_n364 +end + +def fun_l0_n252() + fun_l1_n989 +end + +def fun_l0_n253() + fun_l1_n565 +end + +def fun_l0_n254() + fun_l1_n701 +end + +def fun_l0_n255() + fun_l1_n48 +end + +def fun_l0_n256() + fun_l1_n278 +end + +def fun_l0_n257() + fun_l1_n816 +end + +def fun_l0_n258() + fun_l1_n981 +end + +def fun_l0_n259() + fun_l1_n556 +end + +def fun_l0_n260() + fun_l1_n887 +end + +def fun_l0_n261() + fun_l1_n193 +end + +def fun_l0_n262() + fun_l1_n690 +end + +def fun_l0_n263() + fun_l1_n144 +end + +def fun_l0_n264() + fun_l1_n577 +end + +def fun_l0_n265() + fun_l1_n949 +end + +def fun_l0_n266() + fun_l1_n320 +end + +def fun_l0_n267() + fun_l1_n857 +end + +def fun_l0_n268() + fun_l1_n676 +end + +def fun_l0_n269() + fun_l1_n683 +end + +def fun_l0_n270() + fun_l1_n303 +end + +def fun_l0_n271() + fun_l1_n847 +end + +def fun_l0_n272() + fun_l1_n588 +end + +def fun_l0_n273() + fun_l1_n456 +end + +def fun_l0_n274() + fun_l1_n355 +end + +def fun_l0_n275() + fun_l1_n183 +end + +def fun_l0_n276() + fun_l1_n271 +end + +def fun_l0_n277() + fun_l1_n746 +end + +def fun_l0_n278() + fun_l1_n885 +end + +def fun_l0_n279() + fun_l1_n951 +end + +def fun_l0_n280() + fun_l1_n935 +end + +def fun_l0_n281() + fun_l1_n445 +end + +def fun_l0_n282() + fun_l1_n2 +end + +def fun_l0_n283() + fun_l1_n52 +end + +def fun_l0_n284() + fun_l1_n208 +end + +def fun_l0_n285() + fun_l1_n27 +end + +def fun_l0_n286() + fun_l1_n657 +end + +def fun_l0_n287() + fun_l1_n373 +end + +def fun_l0_n288() + fun_l1_n439 +end + +def fun_l0_n289() + fun_l1_n974 +end + +def fun_l0_n290() + fun_l1_n834 +end + +def fun_l0_n291() + fun_l1_n673 +end + +def fun_l0_n292() + fun_l1_n978 +end + +def fun_l0_n293() + fun_l1_n123 +end + +def fun_l0_n294() + fun_l1_n644 +end + +def fun_l0_n295() + fun_l1_n715 +end + +def fun_l0_n296() + fun_l1_n912 +end + +def fun_l0_n297() + fun_l1_n954 +end + +def fun_l0_n298() + fun_l1_n519 +end + +def fun_l0_n299() + fun_l1_n726 +end + +def fun_l0_n300() + fun_l1_n417 +end + +def fun_l0_n301() + fun_l1_n199 +end + +def fun_l0_n302() + fun_l1_n157 +end + +def fun_l0_n303() + fun_l1_n432 +end + +def fun_l0_n304() + fun_l1_n59 +end + +def fun_l0_n305() + fun_l1_n604 +end + +def fun_l0_n306() + fun_l1_n301 +end + +def fun_l0_n307() + fun_l1_n558 +end + +def fun_l0_n308() + fun_l1_n443 +end + +def fun_l0_n309() + fun_l1_n873 +end + +def fun_l0_n310() + fun_l1_n415 +end + +def fun_l0_n311() + fun_l1_n907 +end + +def fun_l0_n312() + fun_l1_n159 +end + +def fun_l0_n313() + fun_l1_n695 +end + +def fun_l0_n314() + fun_l1_n679 +end + +def fun_l0_n315() + fun_l1_n788 +end + +def fun_l0_n316() + fun_l1_n510 +end + +def fun_l0_n317() + fun_l1_n997 +end + +def fun_l0_n318() + fun_l1_n821 +end + +def fun_l0_n319() + fun_l1_n554 +end + +def fun_l0_n320() + fun_l1_n982 +end + +def fun_l0_n321() + fun_l1_n996 +end + +def fun_l0_n322() + fun_l1_n73 +end + +def fun_l0_n323() + fun_l1_n951 +end + +def fun_l0_n324() + fun_l1_n597 +end + +def fun_l0_n325() + fun_l1_n502 +end + +def fun_l0_n326() + fun_l1_n150 +end + +def fun_l0_n327() + fun_l1_n979 +end + +def fun_l0_n328() + fun_l1_n81 +end + +def fun_l0_n329() + fun_l1_n87 +end + +def fun_l0_n330() + fun_l1_n726 +end + +def fun_l0_n331() + fun_l1_n159 +end + +def fun_l0_n332() + fun_l1_n799 +end + +def fun_l0_n333() + fun_l1_n202 +end + +def fun_l0_n334() + fun_l1_n904 +end + +def fun_l0_n335() + fun_l1_n14 +end + +def fun_l0_n336() + fun_l1_n136 +end + +def fun_l0_n337() + fun_l1_n865 +end + +def fun_l0_n338() + fun_l1_n307 +end + +def fun_l0_n339() + fun_l1_n827 +end + +def fun_l0_n340() + fun_l1_n518 +end + +def fun_l0_n341() + fun_l1_n416 +end + +def fun_l0_n342() + fun_l1_n277 +end + +def fun_l0_n343() + fun_l1_n609 +end + +def fun_l0_n344() + fun_l1_n328 +end + +def fun_l0_n345() + fun_l1_n941 +end + +def fun_l0_n346() + fun_l1_n707 +end + +def fun_l0_n347() + fun_l1_n452 +end + +def fun_l0_n348() + fun_l1_n874 +end + +def fun_l0_n349() + fun_l1_n117 +end + +def fun_l0_n350() + fun_l1_n739 +end + +def fun_l0_n351() + fun_l1_n202 +end + +def fun_l0_n352() + fun_l1_n80 +end + +def fun_l0_n353() + fun_l1_n373 +end + +def fun_l0_n354() + fun_l1_n747 +end + +def fun_l0_n355() + fun_l1_n949 +end + +def fun_l0_n356() + fun_l1_n901 +end + +def fun_l0_n357() + fun_l1_n512 +end + +def fun_l0_n358() + fun_l1_n528 +end + +def fun_l0_n359() + fun_l1_n895 +end + +def fun_l0_n360() + fun_l1_n683 +end + +def fun_l0_n361() + fun_l1_n80 +end + +def fun_l0_n362() + fun_l1_n718 +end + +def fun_l0_n363() + fun_l1_n388 +end + +def fun_l0_n364() + fun_l1_n701 +end + +def fun_l0_n365() + fun_l1_n146 +end + +def fun_l0_n366() + fun_l1_n143 +end + +def fun_l0_n367() + fun_l1_n872 +end + +def fun_l0_n368() + fun_l1_n818 +end + +def fun_l0_n369() + fun_l1_n821 +end + +def fun_l0_n370() + fun_l1_n180 +end + +def fun_l0_n371() + fun_l1_n346 +end + +def fun_l0_n372() + fun_l1_n524 +end + +def fun_l0_n373() + fun_l1_n451 +end + +def fun_l0_n374() + fun_l1_n592 +end + +def fun_l0_n375() + fun_l1_n215 +end + +def fun_l0_n376() + fun_l1_n737 +end + +def fun_l0_n377() + fun_l1_n631 +end + +def fun_l0_n378() + fun_l1_n385 +end + +def fun_l0_n379() + fun_l1_n593 +end + +def fun_l0_n380() + fun_l1_n484 +end + +def fun_l0_n381() + fun_l1_n979 +end + +def fun_l0_n382() + fun_l1_n491 +end + +def fun_l0_n383() + fun_l1_n632 +end + +def fun_l0_n384() + fun_l1_n939 +end + +def fun_l0_n385() + fun_l1_n932 +end + +def fun_l0_n386() + fun_l1_n816 +end + +def fun_l0_n387() + fun_l1_n308 +end + +def fun_l0_n388() + fun_l1_n525 +end + +def fun_l0_n389() + fun_l1_n160 +end + +def fun_l0_n390() + fun_l1_n313 +end + +def fun_l0_n391() + fun_l1_n816 +end + +def fun_l0_n392() + fun_l1_n641 +end + +def fun_l0_n393() + fun_l1_n319 +end + +def fun_l0_n394() + fun_l1_n559 +end + +def fun_l0_n395() + fun_l1_n520 +end + +def fun_l0_n396() + fun_l1_n277 +end + +def fun_l0_n397() + fun_l1_n410 +end + +def fun_l0_n398() + fun_l1_n956 +end + +def fun_l0_n399() + fun_l1_n101 +end + +def fun_l0_n400() + fun_l1_n33 +end + +def fun_l0_n401() + fun_l1_n554 +end + +def fun_l0_n402() + fun_l1_n821 +end + +def fun_l0_n403() + fun_l1_n230 +end + +def fun_l0_n404() + fun_l1_n185 +end + +def fun_l0_n405() + fun_l1_n430 +end + +def fun_l0_n406() + fun_l1_n94 +end + +def fun_l0_n407() + fun_l1_n776 +end + +def fun_l0_n408() + fun_l1_n981 +end + +def fun_l0_n409() + fun_l1_n414 +end + +def fun_l0_n410() + fun_l1_n421 +end + +def fun_l0_n411() + fun_l1_n343 +end + +def fun_l0_n412() + fun_l1_n484 +end + +def fun_l0_n413() + fun_l1_n818 +end + +def fun_l0_n414() + fun_l1_n860 +end + +def fun_l0_n415() + fun_l1_n70 +end + +def fun_l0_n416() + fun_l1_n643 +end + +def fun_l0_n417() + fun_l1_n382 +end + +def fun_l0_n418() + fun_l1_n174 +end + +def fun_l0_n419() + fun_l1_n500 +end + +def fun_l0_n420() + fun_l1_n904 +end + +def fun_l0_n421() + fun_l1_n971 +end + +def fun_l0_n422() + fun_l1_n438 +end + +def fun_l0_n423() + fun_l1_n524 +end + +def fun_l0_n424() + fun_l1_n537 +end + +def fun_l0_n425() + fun_l1_n564 +end + +def fun_l0_n426() + fun_l1_n378 +end + +def fun_l0_n427() + fun_l1_n603 +end + +def fun_l0_n428() + fun_l1_n442 +end + +def fun_l0_n429() + fun_l1_n687 +end + +def fun_l0_n430() + fun_l1_n682 +end + +def fun_l0_n431() + fun_l1_n664 +end + +def fun_l0_n432() + fun_l1_n319 +end + +def fun_l0_n433() + fun_l1_n671 +end + +def fun_l0_n434() + fun_l1_n211 +end + +def fun_l0_n435() + fun_l1_n65 +end + +def fun_l0_n436() + fun_l1_n2 +end + +def fun_l0_n437() + fun_l1_n36 +end + +def fun_l0_n438() + fun_l1_n270 +end + +def fun_l0_n439() + fun_l1_n793 +end + +def fun_l0_n440() + fun_l1_n312 +end + +def fun_l0_n441() + fun_l1_n134 +end + +def fun_l0_n442() + fun_l1_n246 +end + +def fun_l0_n443() + fun_l1_n498 +end + +def fun_l0_n444() + fun_l1_n606 +end + +def fun_l0_n445() + fun_l1_n986 +end + +def fun_l0_n446() + fun_l1_n659 +end + +def fun_l0_n447() + fun_l1_n823 +end + +def fun_l0_n448() + fun_l1_n635 +end + +def fun_l0_n449() + fun_l1_n388 +end + +def fun_l0_n450() + fun_l1_n474 +end + +def fun_l0_n451() + fun_l1_n742 +end + +def fun_l0_n452() + fun_l1_n605 +end + +def fun_l0_n453() + fun_l1_n0 +end + +def fun_l0_n454() + fun_l1_n691 +end + +def fun_l0_n455() + fun_l1_n791 +end + +def fun_l0_n456() + fun_l1_n363 +end + +def fun_l0_n457() + fun_l1_n370 +end + +def fun_l0_n458() + fun_l1_n168 +end + +def fun_l0_n459() + fun_l1_n626 +end + +def fun_l0_n460() + fun_l1_n139 +end + +def fun_l0_n461() + fun_l1_n708 +end + +def fun_l0_n462() + fun_l1_n77 +end + +def fun_l0_n463() + fun_l1_n27 +end + +def fun_l0_n464() + fun_l1_n706 +end + +def fun_l0_n465() + fun_l1_n29 +end + +def fun_l0_n466() + fun_l1_n470 +end + +def fun_l0_n467() + fun_l1_n606 +end + +def fun_l0_n468() + fun_l1_n458 +end + +def fun_l0_n469() + fun_l1_n465 +end + +def fun_l0_n470() + fun_l1_n23 +end + +def fun_l0_n471() + fun_l1_n364 +end + +def fun_l0_n472() + fun_l1_n606 +end + +def fun_l0_n473() + fun_l1_n109 +end + +def fun_l0_n474() + fun_l1_n904 +end + +def fun_l0_n475() + fun_l1_n923 +end + +def fun_l0_n476() + fun_l1_n19 +end + +def fun_l0_n477() + fun_l1_n871 +end + +def fun_l0_n478() + fun_l1_n422 +end + +def fun_l0_n479() + fun_l1_n72 +end + +def fun_l0_n480() + fun_l1_n528 +end + +def fun_l0_n481() + fun_l1_n181 +end + +def fun_l0_n482() + fun_l1_n33 +end + +def fun_l0_n483() + fun_l1_n951 +end + +def fun_l0_n484() + fun_l1_n747 +end + +def fun_l0_n485() + fun_l1_n200 +end + +def fun_l0_n486() + fun_l1_n474 +end + +def fun_l0_n487() + fun_l1_n126 +end + +def fun_l0_n488() + fun_l1_n757 +end + +def fun_l0_n489() + fun_l1_n101 +end + +def fun_l0_n490() + fun_l1_n925 +end + +def fun_l0_n491() + fun_l1_n791 +end + +def fun_l0_n492() + fun_l1_n404 +end + +def fun_l0_n493() + fun_l1_n841 +end + +def fun_l0_n494() + fun_l1_n774 +end + +def fun_l0_n495() + fun_l1_n230 +end + +def fun_l0_n496() + fun_l1_n796 +end + +def fun_l0_n497() + fun_l1_n270 +end + +def fun_l0_n498() + fun_l1_n795 +end + +def fun_l0_n499() + fun_l1_n628 +end + +def fun_l0_n500() + fun_l1_n865 +end + +def fun_l0_n501() + fun_l1_n105 +end + +def fun_l0_n502() + fun_l1_n538 +end + +def fun_l0_n503() + fun_l1_n769 +end + +def fun_l0_n504() + fun_l1_n714 +end + +def fun_l0_n505() + fun_l1_n889 +end + +def fun_l0_n506() + fun_l1_n191 +end + +def fun_l0_n507() + fun_l1_n966 +end + +def fun_l0_n508() + fun_l1_n196 +end + +def fun_l0_n509() + fun_l1_n878 +end + +def fun_l0_n510() + fun_l1_n487 +end + +def fun_l0_n511() + fun_l1_n242 +end + +def fun_l0_n512() + fun_l1_n740 +end + +def fun_l0_n513() + fun_l1_n938 +end + +def fun_l0_n514() + fun_l1_n485 +end + +def fun_l0_n515() + fun_l1_n380 +end + +def fun_l0_n516() + fun_l1_n936 +end + +def fun_l0_n517() + fun_l1_n237 +end + +def fun_l0_n518() + fun_l1_n79 +end + +def fun_l0_n519() + fun_l1_n501 +end + +def fun_l0_n520() + fun_l1_n966 +end + +def fun_l0_n521() + fun_l1_n741 +end + +def fun_l0_n522() + fun_l1_n170 +end + +def fun_l0_n523() + fun_l1_n183 +end + +def fun_l0_n524() + fun_l1_n556 +end + +def fun_l0_n525() + fun_l1_n865 +end + +def fun_l0_n526() + fun_l1_n884 +end + +def fun_l0_n527() + fun_l1_n725 +end + +def fun_l0_n528() + fun_l1_n205 +end + +def fun_l0_n529() + fun_l1_n72 +end + +def fun_l0_n530() + fun_l1_n432 +end + +def fun_l0_n531() + fun_l1_n90 +end + +def fun_l0_n532() + fun_l1_n189 +end + +def fun_l0_n533() + fun_l1_n395 +end + +def fun_l0_n534() + fun_l1_n201 +end + +def fun_l0_n535() + fun_l1_n534 +end + +def fun_l0_n536() + fun_l1_n748 +end + +def fun_l0_n537() + fun_l1_n439 +end + +def fun_l0_n538() + fun_l1_n495 +end + +def fun_l0_n539() + fun_l1_n904 +end + +def fun_l0_n540() + fun_l1_n525 +end + +def fun_l0_n541() + fun_l1_n924 +end + +def fun_l0_n542() + fun_l1_n549 +end + +def fun_l0_n543() + fun_l1_n2 +end + +def fun_l0_n544() + fun_l1_n257 +end + +def fun_l0_n545() + fun_l1_n921 +end + +def fun_l0_n546() + fun_l1_n82 +end + +def fun_l0_n547() + fun_l1_n384 +end + +def fun_l0_n548() + fun_l1_n219 +end + +def fun_l0_n549() + fun_l1_n379 +end + +def fun_l0_n550() + fun_l1_n488 +end + +def fun_l0_n551() + fun_l1_n4 +end + +def fun_l0_n552() + fun_l1_n150 +end + +def fun_l0_n553() + fun_l1_n168 +end + +def fun_l0_n554() + fun_l1_n773 +end + +def fun_l0_n555() + fun_l1_n444 +end + +def fun_l0_n556() + fun_l1_n201 +end + +def fun_l0_n557() + fun_l1_n333 +end + +def fun_l0_n558() + fun_l1_n556 +end + +def fun_l0_n559() + fun_l1_n394 +end + +def fun_l0_n560() + fun_l1_n540 +end + +def fun_l0_n561() + fun_l1_n640 +end + +def fun_l0_n562() + fun_l1_n321 +end + +def fun_l0_n563() + fun_l1_n286 +end + +def fun_l0_n564() + fun_l1_n320 +end + +def fun_l0_n565() + fun_l1_n2 +end + +def fun_l0_n566() + fun_l1_n50 +end + +def fun_l0_n567() + fun_l1_n269 +end + +def fun_l0_n568() + fun_l1_n412 +end + +def fun_l0_n569() + fun_l1_n984 +end + +def fun_l0_n570() + fun_l1_n307 +end + +def fun_l0_n571() + fun_l1_n954 +end + +def fun_l0_n572() + fun_l1_n728 +end + +def fun_l0_n573() + fun_l1_n227 +end + +def fun_l0_n574() + fun_l1_n917 +end + +def fun_l0_n575() + fun_l1_n974 +end + +def fun_l0_n576() + fun_l1_n995 +end + +def fun_l0_n577() + fun_l1_n593 +end + +def fun_l0_n578() + fun_l1_n704 +end + +def fun_l0_n579() + fun_l1_n142 +end + +def fun_l0_n580() + fun_l1_n585 +end + +def fun_l0_n581() + fun_l1_n634 +end + +def fun_l0_n582() + fun_l1_n888 +end + +def fun_l0_n583() + fun_l1_n873 +end + +def fun_l0_n584() + fun_l1_n674 +end + +def fun_l0_n585() + fun_l1_n657 +end + +def fun_l0_n586() + fun_l1_n248 +end + +def fun_l0_n587() + fun_l1_n478 +end + +def fun_l0_n588() + fun_l1_n263 +end + +def fun_l0_n589() + fun_l1_n908 +end + +def fun_l0_n590() + fun_l1_n741 +end + +def fun_l0_n591() + fun_l1_n299 +end + +def fun_l0_n592() + fun_l1_n763 +end + +def fun_l0_n593() + fun_l1_n746 +end + +def fun_l0_n594() + fun_l1_n367 +end + +def fun_l0_n595() + fun_l1_n394 +end + +def fun_l0_n596() + fun_l1_n304 +end + +def fun_l0_n597() + fun_l1_n939 +end + +def fun_l0_n598() + fun_l1_n392 +end + +def fun_l0_n599() + fun_l1_n758 +end + +def fun_l0_n600() + fun_l1_n133 +end + +def fun_l0_n601() + fun_l1_n212 +end + +def fun_l0_n602() + fun_l1_n719 +end + +def fun_l0_n603() + fun_l1_n952 +end + +def fun_l0_n604() + fun_l1_n818 +end + +def fun_l0_n605() + fun_l1_n216 +end + +def fun_l0_n606() + fun_l1_n438 +end + +def fun_l0_n607() + fun_l1_n315 +end + +def fun_l0_n608() + fun_l1_n450 +end + +def fun_l0_n609() + fun_l1_n420 +end + +def fun_l0_n610() + fun_l1_n917 +end + +def fun_l0_n611() + fun_l1_n921 +end + +def fun_l0_n612() + fun_l1_n596 +end + +def fun_l0_n613() + fun_l1_n253 +end + +def fun_l0_n614() + fun_l1_n395 +end + +def fun_l0_n615() + fun_l1_n120 +end + +def fun_l0_n616() + fun_l1_n742 +end + +def fun_l0_n617() + fun_l1_n489 +end + +def fun_l0_n618() + fun_l1_n338 +end + +def fun_l0_n619() + fun_l1_n351 +end + +def fun_l0_n620() + fun_l1_n384 +end + +def fun_l0_n621() + fun_l1_n581 +end + +def fun_l0_n622() + fun_l1_n667 +end + +def fun_l0_n623() + fun_l1_n956 +end + +def fun_l0_n624() + fun_l1_n156 +end + +def fun_l0_n625() + fun_l1_n909 +end + +def fun_l0_n626() + fun_l1_n548 +end + +def fun_l0_n627() + fun_l1_n293 +end + +def fun_l0_n628() + fun_l1_n997 +end + +def fun_l0_n629() + fun_l1_n950 +end + +def fun_l0_n630() + fun_l1_n761 +end + +def fun_l0_n631() + fun_l1_n72 +end + +def fun_l0_n632() + fun_l1_n213 +end + +def fun_l0_n633() + fun_l1_n746 +end + +def fun_l0_n634() + fun_l1_n327 +end + +def fun_l0_n635() + fun_l1_n166 +end + +def fun_l0_n636() + fun_l1_n749 +end + +def fun_l0_n637() + fun_l1_n196 +end + +def fun_l0_n638() + fun_l1_n786 +end + +def fun_l0_n639() + fun_l1_n613 +end + +def fun_l0_n640() + fun_l1_n903 +end + +def fun_l0_n641() + fun_l1_n836 +end + +def fun_l0_n642() + fun_l1_n687 +end + +def fun_l0_n643() + fun_l1_n533 +end + +def fun_l0_n644() + fun_l1_n544 +end + +def fun_l0_n645() + fun_l1_n637 +end + +def fun_l0_n646() + fun_l1_n859 +end + +def fun_l0_n647() + fun_l1_n917 +end + +def fun_l0_n648() + fun_l1_n119 +end + +def fun_l0_n649() + fun_l1_n327 +end + +def fun_l0_n650() + fun_l1_n759 +end + +def fun_l0_n651() + fun_l1_n169 +end + +def fun_l0_n652() + fun_l1_n497 +end + +def fun_l0_n653() + fun_l1_n441 +end + +def fun_l0_n654() + fun_l1_n151 +end + +def fun_l0_n655() + fun_l1_n553 +end + +def fun_l0_n656() + fun_l1_n441 +end + +def fun_l0_n657() + fun_l1_n390 +end + +def fun_l0_n658() + fun_l1_n615 +end + +def fun_l0_n659() + fun_l1_n578 +end + +def fun_l0_n660() + fun_l1_n873 +end + +def fun_l0_n661() + fun_l1_n608 +end + +def fun_l0_n662() + fun_l1_n446 +end + +def fun_l0_n663() + fun_l1_n647 +end + +def fun_l0_n664() + fun_l1_n601 +end + +def fun_l0_n665() + fun_l1_n945 +end + +def fun_l0_n666() + fun_l1_n172 +end + +def fun_l0_n667() + fun_l1_n547 +end + +def fun_l0_n668() + fun_l1_n977 +end + +def fun_l0_n669() + fun_l1_n419 +end + +def fun_l0_n670() + fun_l1_n626 +end + +def fun_l0_n671() + fun_l1_n345 +end + +def fun_l0_n672() + fun_l1_n899 +end + +def fun_l0_n673() + fun_l1_n442 +end + +def fun_l0_n674() + fun_l1_n296 +end + +def fun_l0_n675() + fun_l1_n303 +end + +def fun_l0_n676() + fun_l1_n679 +end + +def fun_l0_n677() + fun_l1_n655 +end + +def fun_l0_n678() + fun_l1_n998 +end + +def fun_l0_n679() + fun_l1_n157 +end + +def fun_l0_n680() + fun_l1_n705 +end + +def fun_l0_n681() + fun_l1_n832 +end + +def fun_l0_n682() + fun_l1_n113 +end + +def fun_l0_n683() + fun_l1_n550 +end + +def fun_l0_n684() + fun_l1_n21 +end + +def fun_l0_n685() + fun_l1_n21 +end + +def fun_l0_n686() + fun_l1_n195 +end + +def fun_l0_n687() + fun_l1_n269 +end + +def fun_l0_n688() + fun_l1_n12 +end + +def fun_l0_n689() + fun_l1_n49 +end + +def fun_l0_n690() + fun_l1_n836 +end + +def fun_l0_n691() + fun_l1_n808 +end + +def fun_l0_n692() + fun_l1_n938 +end + +def fun_l0_n693() + fun_l1_n531 +end + +def fun_l0_n694() + fun_l1_n296 +end + +def fun_l0_n695() + fun_l1_n32 +end + +def fun_l0_n696() + fun_l1_n641 +end + +def fun_l0_n697() + fun_l1_n549 +end + +def fun_l0_n698() + fun_l1_n437 +end + +def fun_l0_n699() + fun_l1_n133 +end + +def fun_l0_n700() + fun_l1_n734 +end + +def fun_l0_n701() + fun_l1_n340 +end + +def fun_l0_n702() + fun_l1_n768 +end + +def fun_l0_n703() + fun_l1_n97 +end + +def fun_l0_n704() + fun_l1_n52 +end + +def fun_l0_n705() + fun_l1_n121 +end + +def fun_l0_n706() + fun_l1_n471 +end + +def fun_l0_n707() + fun_l1_n94 +end + +def fun_l0_n708() + fun_l1_n946 +end + +def fun_l0_n709() + fun_l1_n151 +end + +def fun_l0_n710() + fun_l1_n946 +end + +def fun_l0_n711() + fun_l1_n191 +end + +def fun_l0_n712() + fun_l1_n552 +end + +def fun_l0_n713() + fun_l1_n733 +end + +def fun_l0_n714() + fun_l1_n895 +end + +def fun_l0_n715() + fun_l1_n850 +end + +def fun_l0_n716() + fun_l1_n113 +end + +def fun_l0_n717() + fun_l1_n69 +end + +def fun_l0_n718() + fun_l1_n862 +end + +def fun_l0_n719() + fun_l1_n635 +end + +def fun_l0_n720() + fun_l1_n714 +end + +def fun_l0_n721() + fun_l1_n179 +end + +def fun_l0_n722() + fun_l1_n17 +end + +def fun_l0_n723() + fun_l1_n299 +end + +def fun_l0_n724() + fun_l1_n141 +end + +def fun_l0_n725() + fun_l1_n338 +end + +def fun_l0_n726() + fun_l1_n650 +end + +def fun_l0_n727() + fun_l1_n784 +end + +def fun_l0_n728() + fun_l1_n333 +end + +def fun_l0_n729() + fun_l1_n10 +end + +def fun_l0_n730() + fun_l1_n271 +end + +def fun_l0_n731() + fun_l1_n882 +end + +def fun_l0_n732() + fun_l1_n512 +end + +def fun_l0_n733() + fun_l1_n932 +end + +def fun_l0_n734() + fun_l1_n68 +end + +def fun_l0_n735() + fun_l1_n111 +end + +def fun_l0_n736() + fun_l1_n649 +end + +def fun_l0_n737() + fun_l1_n512 +end + +def fun_l0_n738() + fun_l1_n551 +end + +def fun_l0_n739() + fun_l1_n153 +end + +def fun_l0_n740() + fun_l1_n582 +end + +def fun_l0_n741() + fun_l1_n366 +end + +def fun_l0_n742() + fun_l1_n135 +end + +def fun_l0_n743() + fun_l1_n136 +end + +def fun_l0_n744() + fun_l1_n782 +end + +def fun_l0_n745() + fun_l1_n258 +end + +def fun_l0_n746() + fun_l1_n44 +end + +def fun_l0_n747() + fun_l1_n379 +end + +def fun_l0_n748() + fun_l1_n14 +end + +def fun_l0_n749() + fun_l1_n563 +end + +def fun_l0_n750() + fun_l1_n361 +end + +def fun_l0_n751() + fun_l1_n624 +end + +def fun_l0_n752() + fun_l1_n516 +end + +def fun_l0_n753() + fun_l1_n944 +end + +def fun_l0_n754() + fun_l1_n783 +end + +def fun_l0_n755() + fun_l1_n744 +end + +def fun_l0_n756() + fun_l1_n500 +end + +def fun_l0_n757() + fun_l1_n809 +end + +def fun_l0_n758() + fun_l1_n757 +end + +def fun_l0_n759() + fun_l1_n995 +end + +def fun_l0_n760() + fun_l1_n114 +end + +def fun_l0_n761() + fun_l1_n802 +end + +def fun_l0_n762() + fun_l1_n114 +end + +def fun_l0_n763() + fun_l1_n683 +end + +def fun_l0_n764() + fun_l1_n775 +end + +def fun_l0_n765() + fun_l1_n967 +end + +def fun_l0_n766() + fun_l1_n499 +end + +def fun_l0_n767() + fun_l1_n561 +end + +def fun_l0_n768() + fun_l1_n206 +end + +def fun_l0_n769() + fun_l1_n738 +end + +def fun_l0_n770() + fun_l1_n953 +end + +def fun_l0_n771() + fun_l1_n394 +end + +def fun_l0_n772() + fun_l1_n393 +end + +def fun_l0_n773() + fun_l1_n226 +end + +def fun_l0_n774() + fun_l1_n363 +end + +def fun_l0_n775() + fun_l1_n928 +end + +def fun_l0_n776() + fun_l1_n213 +end + +def fun_l0_n777() + fun_l1_n3 +end + +def fun_l0_n778() + fun_l1_n656 +end + +def fun_l0_n779() + fun_l1_n927 +end + +def fun_l0_n780() + fun_l1_n406 +end + +def fun_l0_n781() + fun_l1_n589 +end + +def fun_l0_n782() + fun_l1_n56 +end + +def fun_l0_n783() + fun_l1_n280 +end + +def fun_l0_n784() + fun_l1_n156 +end + +def fun_l0_n785() + fun_l1_n257 +end + +def fun_l0_n786() + fun_l1_n269 +end + +def fun_l0_n787() + fun_l1_n453 +end + +def fun_l0_n788() + fun_l1_n293 +end + +def fun_l0_n789() + fun_l1_n570 +end + +def fun_l0_n790() + fun_l1_n194 +end + +def fun_l0_n791() + fun_l1_n120 +end + +def fun_l0_n792() + fun_l1_n976 +end + +def fun_l0_n793() + fun_l1_n115 +end + +def fun_l0_n794() + fun_l1_n74 +end + +def fun_l0_n795() + fun_l1_n25 +end + +def fun_l0_n796() + fun_l1_n288 +end + +def fun_l0_n797() + fun_l1_n49 +end + +def fun_l0_n798() + fun_l1_n237 +end + +def fun_l0_n799() + fun_l1_n481 +end + +def fun_l0_n800() + fun_l1_n329 +end + +def fun_l0_n801() + fun_l1_n907 +end + +def fun_l0_n802() + fun_l1_n804 +end + +def fun_l0_n803() + fun_l1_n8 +end + +def fun_l0_n804() + fun_l1_n270 +end + +def fun_l0_n805() + fun_l1_n315 +end + +def fun_l0_n806() + fun_l1_n941 +end + +def fun_l0_n807() + fun_l1_n343 +end + +def fun_l0_n808() + fun_l1_n817 +end + +def fun_l0_n809() + fun_l1_n315 +end + +def fun_l0_n810() + fun_l1_n156 +end + +def fun_l0_n811() + fun_l1_n689 +end + +def fun_l0_n812() + fun_l1_n644 +end + +def fun_l0_n813() + fun_l1_n158 +end + +def fun_l0_n814() + fun_l1_n588 +end + +def fun_l0_n815() + fun_l1_n820 +end + +def fun_l0_n816() + fun_l1_n86 +end + +def fun_l0_n817() + fun_l1_n176 +end + +def fun_l0_n818() + fun_l1_n611 +end + +def fun_l0_n819() + fun_l1_n816 +end + +def fun_l0_n820() + fun_l1_n332 +end + +def fun_l0_n821() + fun_l1_n170 +end + +def fun_l0_n822() + fun_l1_n483 +end + +def fun_l0_n823() + fun_l1_n768 +end + +def fun_l0_n824() + fun_l1_n825 +end + +def fun_l0_n825() + fun_l1_n114 +end + +def fun_l0_n826() + fun_l1_n102 +end + +def fun_l0_n827() + fun_l1_n963 +end + +def fun_l0_n828() + fun_l1_n202 +end + +def fun_l0_n829() + fun_l1_n708 +end + +def fun_l0_n830() + fun_l1_n350 +end + +def fun_l0_n831() + fun_l1_n976 +end + +def fun_l0_n832() + fun_l1_n834 +end + +def fun_l0_n833() + fun_l1_n342 +end + +def fun_l0_n834() + fun_l1_n764 +end + +def fun_l0_n835() + fun_l1_n211 +end + +def fun_l0_n836() + fun_l1_n173 +end + +def fun_l0_n837() + fun_l1_n988 +end + +def fun_l0_n838() + fun_l1_n369 +end + +def fun_l0_n839() + fun_l1_n481 +end + +def fun_l0_n840() + fun_l1_n580 +end + +def fun_l0_n841() + fun_l1_n255 +end + +def fun_l0_n842() + fun_l1_n476 +end + +def fun_l0_n843() + fun_l1_n795 +end + +def fun_l0_n844() + fun_l1_n296 +end + +def fun_l0_n845() + fun_l1_n880 +end + +def fun_l0_n846() + fun_l1_n457 +end + +def fun_l0_n847() + fun_l1_n88 +end + +def fun_l0_n848() + fun_l1_n901 +end + +def fun_l0_n849() + fun_l1_n988 +end + +def fun_l0_n850() + fun_l1_n396 +end + +def fun_l0_n851() + fun_l1_n60 +end + +def fun_l0_n852() + fun_l1_n738 +end + +def fun_l0_n853() + fun_l1_n2 +end + +def fun_l0_n854() + fun_l1_n652 +end + +def fun_l0_n855() + fun_l1_n982 +end + +def fun_l0_n856() + fun_l1_n987 +end + +def fun_l0_n857() + fun_l1_n488 +end + +def fun_l0_n858() + fun_l1_n354 +end + +def fun_l0_n859() + fun_l1_n320 +end + +def fun_l0_n860() + fun_l1_n378 +end + +def fun_l0_n861() + fun_l1_n965 +end + +def fun_l0_n862() + fun_l1_n858 +end + +def fun_l0_n863() + fun_l1_n360 +end + +def fun_l0_n864() + fun_l1_n812 +end + +def fun_l0_n865() + fun_l1_n590 +end + +def fun_l0_n866() + fun_l1_n339 +end + +def fun_l0_n867() + fun_l1_n365 +end + +def fun_l0_n868() + fun_l1_n190 +end + +def fun_l0_n869() + fun_l1_n555 +end + +def fun_l0_n870() + fun_l1_n676 +end + +def fun_l0_n871() + fun_l1_n681 +end + +def fun_l0_n872() + fun_l1_n283 +end + +def fun_l0_n873() + fun_l1_n865 +end + +def fun_l0_n874() + fun_l1_n402 +end + +def fun_l0_n875() + fun_l1_n530 +end + +def fun_l0_n876() + fun_l1_n25 +end + +def fun_l0_n877() + fun_l1_n10 +end + +def fun_l0_n878() + fun_l1_n252 +end + +def fun_l0_n879() + fun_l1_n174 +end + +def fun_l0_n880() + fun_l1_n449 +end + +def fun_l0_n881() + fun_l1_n385 +end + +def fun_l0_n882() + fun_l1_n689 +end + +def fun_l0_n883() + fun_l1_n492 +end + +def fun_l0_n884() + fun_l1_n949 +end + +def fun_l0_n885() + fun_l1_n912 +end + +def fun_l0_n886() + fun_l1_n131 +end + +def fun_l0_n887() + fun_l1_n484 +end + +def fun_l0_n888() + fun_l1_n647 +end + +def fun_l0_n889() + fun_l1_n679 +end + +def fun_l0_n890() + fun_l1_n16 +end + +def fun_l0_n891() + fun_l1_n745 +end + +def fun_l0_n892() + fun_l1_n490 +end + +def fun_l0_n893() + fun_l1_n104 +end + +def fun_l0_n894() + fun_l1_n91 +end + +def fun_l0_n895() + fun_l1_n368 +end + +def fun_l0_n896() + fun_l1_n439 +end + +def fun_l0_n897() + fun_l1_n23 +end + +def fun_l0_n898() + fun_l1_n277 +end + +def fun_l0_n899() + fun_l1_n597 +end + +def fun_l0_n900() + fun_l1_n644 +end + +def fun_l0_n901() + fun_l1_n255 +end + +def fun_l0_n902() + fun_l1_n767 +end + +def fun_l0_n903() + fun_l1_n417 +end + +def fun_l0_n904() + fun_l1_n517 +end + +def fun_l0_n905() + fun_l1_n609 +end + +def fun_l0_n906() + fun_l1_n498 +end + +def fun_l0_n907() + fun_l1_n24 +end + +def fun_l0_n908() + fun_l1_n722 +end + +def fun_l0_n909() + fun_l1_n494 +end + +def fun_l0_n910() + fun_l1_n450 +end + +def fun_l0_n911() + fun_l1_n302 +end + +def fun_l0_n912() + fun_l1_n801 +end + +def fun_l0_n913() + fun_l1_n709 +end + +def fun_l0_n914() + fun_l1_n555 +end + +def fun_l0_n915() + fun_l1_n955 +end + +def fun_l0_n916() + fun_l1_n310 +end + +def fun_l0_n917() + fun_l1_n839 +end + +def fun_l0_n918() + fun_l1_n590 +end + +def fun_l0_n919() + fun_l1_n83 +end + +def fun_l0_n920() + fun_l1_n335 +end + +def fun_l0_n921() + fun_l1_n740 +end + +def fun_l0_n922() + fun_l1_n357 +end + +def fun_l0_n923() + fun_l1_n312 +end + +def fun_l0_n924() + fun_l1_n544 +end + +def fun_l0_n925() + fun_l1_n611 +end + +def fun_l0_n926() + fun_l1_n651 +end + +def fun_l0_n927() + fun_l1_n730 +end + +def fun_l0_n928() + fun_l1_n623 +end + +def fun_l0_n929() + fun_l1_n337 +end + +def fun_l0_n930() + fun_l1_n574 +end + +def fun_l0_n931() + fun_l1_n795 +end + +def fun_l0_n932() + fun_l1_n224 +end + +def fun_l0_n933() + fun_l1_n355 +end + +def fun_l0_n934() + fun_l1_n286 +end + +def fun_l0_n935() + fun_l1_n893 +end + +def fun_l0_n936() + fun_l1_n278 +end + +def fun_l0_n937() + fun_l1_n970 +end + +def fun_l0_n938() + fun_l1_n761 +end + +def fun_l0_n939() + fun_l1_n244 +end + +def fun_l0_n940() + fun_l1_n381 +end + +def fun_l0_n941() + fun_l1_n661 +end + +def fun_l0_n942() + fun_l1_n543 +end + +def fun_l0_n943() + fun_l1_n432 +end + +def fun_l0_n944() + fun_l1_n237 +end + +def fun_l0_n945() + fun_l1_n815 +end + +def fun_l0_n946() + fun_l1_n580 +end + +def fun_l0_n947() + fun_l1_n99 +end + +def fun_l0_n948() + fun_l1_n492 +end + +def fun_l0_n949() + fun_l1_n799 +end + +def fun_l0_n950() + fun_l1_n727 +end + +def fun_l0_n951() + fun_l1_n632 +end + +def fun_l0_n952() + fun_l1_n689 +end + +def fun_l0_n953() + fun_l1_n69 +end + +def fun_l0_n954() + fun_l1_n782 +end + +def fun_l0_n955() + fun_l1_n140 +end + +def fun_l0_n956() + fun_l1_n451 +end + +def fun_l0_n957() + fun_l1_n440 +end + +def fun_l0_n958() + fun_l1_n88 +end + +def fun_l0_n959() + fun_l1_n775 +end + +def fun_l0_n960() + fun_l1_n455 +end + +def fun_l0_n961() + fun_l1_n402 +end + +def fun_l0_n962() + fun_l1_n906 +end + +def fun_l0_n963() + fun_l1_n990 +end + +def fun_l0_n964() + fun_l1_n432 +end + +def fun_l0_n965() + fun_l1_n419 +end + +def fun_l0_n966() + fun_l1_n568 +end + +def fun_l0_n967() + fun_l1_n177 +end + +def fun_l0_n968() + fun_l1_n206 +end + +def fun_l0_n969() + fun_l1_n170 +end + +def fun_l0_n970() + fun_l1_n216 +end + +def fun_l0_n971() + fun_l1_n700 +end + +def fun_l0_n972() + fun_l1_n286 +end + +def fun_l0_n973() + fun_l1_n817 +end + +def fun_l0_n974() + fun_l1_n605 +end + +def fun_l0_n975() + fun_l1_n400 +end + +def fun_l0_n976() + fun_l1_n282 +end + +def fun_l0_n977() + fun_l1_n978 +end + +def fun_l0_n978() + fun_l1_n661 +end + +def fun_l0_n979() + fun_l1_n42 +end + +def fun_l0_n980() + fun_l1_n1 +end + +def fun_l0_n981() + fun_l1_n864 +end + +def fun_l0_n982() + fun_l1_n829 +end + +def fun_l0_n983() + fun_l1_n713 +end + +def fun_l0_n984() + fun_l1_n653 +end + +def fun_l0_n985() + fun_l1_n332 +end + +def fun_l0_n986() + fun_l1_n21 +end + +def fun_l0_n987() + fun_l1_n532 +end + +def fun_l0_n988() + fun_l1_n163 +end + +def fun_l0_n989() + fun_l1_n154 +end + +def fun_l0_n990() + fun_l1_n351 +end + +def fun_l0_n991() + fun_l1_n708 +end + +def fun_l0_n992() + fun_l1_n955 +end + +def fun_l0_n993() + fun_l1_n250 +end + +def fun_l0_n994() + fun_l1_n645 +end + +def fun_l0_n995() + fun_l1_n668 +end + +def fun_l0_n996() + fun_l1_n764 +end + +def fun_l0_n997() + fun_l1_n79 +end + +def fun_l0_n998() + fun_l1_n251 +end + +def fun_l0_n999() + fun_l1_n586 +end + +def fun_l1_n0() + fun_l2_n188 +end + +def fun_l1_n1() + fun_l2_n165 +end + +def fun_l1_n2() + fun_l2_n875 +end + +def fun_l1_n3() + fun_l2_n246 +end + +def fun_l1_n4() + fun_l2_n887 +end + +def fun_l1_n5() + fun_l2_n191 +end + +def fun_l1_n6() + fun_l2_n187 +end + +def fun_l1_n7() + fun_l2_n138 +end + +def fun_l1_n8() + fun_l2_n455 +end + +def fun_l1_n9() + fun_l2_n861 +end + +def fun_l1_n10() + fun_l2_n588 +end + +def fun_l1_n11() + fun_l2_n157 +end + +def fun_l1_n12() + fun_l2_n903 +end + +def fun_l1_n13() + fun_l2_n655 +end + +def fun_l1_n14() + fun_l2_n252 +end + +def fun_l1_n15() + fun_l2_n894 +end + +def fun_l1_n16() + fun_l2_n908 +end + +def fun_l1_n17() + fun_l2_n649 +end + +def fun_l1_n18() + fun_l2_n890 +end + +def fun_l1_n19() + fun_l2_n451 +end + +def fun_l1_n20() + fun_l2_n775 +end + +def fun_l1_n21() + fun_l2_n522 +end + +def fun_l1_n22() + fun_l2_n666 +end + +def fun_l1_n23() + fun_l2_n784 +end + +def fun_l1_n24() + fun_l2_n204 +end + +def fun_l1_n25() + fun_l2_n310 +end + +def fun_l1_n26() + fun_l2_n740 +end + +def fun_l1_n27() + fun_l2_n22 +end + +def fun_l1_n28() + fun_l2_n114 +end + +def fun_l1_n29() + fun_l2_n132 +end + +def fun_l1_n30() + fun_l2_n935 +end + +def fun_l1_n31() + fun_l2_n459 +end + +def fun_l1_n32() + fun_l2_n262 +end + +def fun_l1_n33() + fun_l2_n22 +end + +def fun_l1_n34() + fun_l2_n649 +end + +def fun_l1_n35() + fun_l2_n817 +end + +def fun_l1_n36() + fun_l2_n17 +end + +def fun_l1_n37() + fun_l2_n685 +end + +def fun_l1_n38() + fun_l2_n118 +end + +def fun_l1_n39() + fun_l2_n285 +end + +def fun_l1_n40() + fun_l2_n186 +end + +def fun_l1_n41() + fun_l2_n318 +end + +def fun_l1_n42() + fun_l2_n133 +end + +def fun_l1_n43() + fun_l2_n364 +end + +def fun_l1_n44() + fun_l2_n672 +end + +def fun_l1_n45() + fun_l2_n710 +end + +def fun_l1_n46() + fun_l2_n568 +end + +def fun_l1_n47() + fun_l2_n923 +end + +def fun_l1_n48() + fun_l2_n664 +end + +def fun_l1_n49() + fun_l2_n460 +end + +def fun_l1_n50() + fun_l2_n900 +end + +def fun_l1_n51() + fun_l2_n144 +end + +def fun_l1_n52() + fun_l2_n798 +end + +def fun_l1_n53() + fun_l2_n529 +end + +def fun_l1_n54() + fun_l2_n547 +end + +def fun_l1_n55() + fun_l2_n643 +end + +def fun_l1_n56() + fun_l2_n454 +end + +def fun_l1_n57() + fun_l2_n210 +end + +def fun_l1_n58() + fun_l2_n69 +end + +def fun_l1_n59() + fun_l2_n140 +end + +def fun_l1_n60() + fun_l2_n844 +end + +def fun_l1_n61() + fun_l2_n933 +end + +def fun_l1_n62() + fun_l2_n569 +end + +def fun_l1_n63() + fun_l2_n596 +end + +def fun_l1_n64() + fun_l2_n254 +end + +def fun_l1_n65() + fun_l2_n838 +end + +def fun_l1_n66() + fun_l2_n796 +end + +def fun_l1_n67() + fun_l2_n262 +end + +def fun_l1_n68() + fun_l2_n379 +end + +def fun_l1_n69() + fun_l2_n700 +end + +def fun_l1_n70() + fun_l2_n947 +end + +def fun_l1_n71() + fun_l2_n226 +end + +def fun_l1_n72() + fun_l2_n550 +end + +def fun_l1_n73() + fun_l2_n791 +end + +def fun_l1_n74() + fun_l2_n252 +end + +def fun_l1_n75() + fun_l2_n347 +end + +def fun_l1_n76() + fun_l2_n812 +end + +def fun_l1_n77() + fun_l2_n14 +end + +def fun_l1_n78() + fun_l2_n19 +end + +def fun_l1_n79() + fun_l2_n296 +end + +def fun_l1_n80() + fun_l2_n217 +end + +def fun_l1_n81() + fun_l2_n979 +end + +def fun_l1_n82() + fun_l2_n815 +end + +def fun_l1_n83() + fun_l2_n879 +end + +def fun_l1_n84() + fun_l2_n311 +end + +def fun_l1_n85() + fun_l2_n351 +end + +def fun_l1_n86() + fun_l2_n997 +end + +def fun_l1_n87() + fun_l2_n551 +end + +def fun_l1_n88() + fun_l2_n221 +end + +def fun_l1_n89() + fun_l2_n869 +end + +def fun_l1_n90() + fun_l2_n700 +end + +def fun_l1_n91() + fun_l2_n627 +end + +def fun_l1_n92() + fun_l2_n106 +end + +def fun_l1_n93() + fun_l2_n731 +end + +def fun_l1_n94() + fun_l2_n61 +end + +def fun_l1_n95() + fun_l2_n386 +end + +def fun_l1_n96() + fun_l2_n960 +end + +def fun_l1_n97() + fun_l2_n75 +end + +def fun_l1_n98() + fun_l2_n896 +end + +def fun_l1_n99() + fun_l2_n597 +end + +def fun_l1_n100() + fun_l2_n73 +end + +def fun_l1_n101() + fun_l2_n78 +end + +def fun_l1_n102() + fun_l2_n919 +end + +def fun_l1_n103() + fun_l2_n784 +end + +def fun_l1_n104() + fun_l2_n798 +end + +def fun_l1_n105() + fun_l2_n478 +end + +def fun_l1_n106() + fun_l2_n883 +end + +def fun_l1_n107() + fun_l2_n855 +end + +def fun_l1_n108() + fun_l2_n581 +end + +def fun_l1_n109() + fun_l2_n694 +end + +def fun_l1_n110() + fun_l2_n490 +end + +def fun_l1_n111() + fun_l2_n44 +end + +def fun_l1_n112() + fun_l2_n537 +end + +def fun_l1_n113() + fun_l2_n21 +end + +def fun_l1_n114() + fun_l2_n312 +end + +def fun_l1_n115() + fun_l2_n700 +end + +def fun_l1_n116() + fun_l2_n227 +end + +def fun_l1_n117() + fun_l2_n689 +end + +def fun_l1_n118() + fun_l2_n664 +end + +def fun_l1_n119() + fun_l2_n669 +end + +def fun_l1_n120() + fun_l2_n306 +end + +def fun_l1_n121() + fun_l2_n278 +end + +def fun_l1_n122() + fun_l2_n312 +end + +def fun_l1_n123() + fun_l2_n416 +end + +def fun_l1_n124() + fun_l2_n912 +end + +def fun_l1_n125() + fun_l2_n135 +end + +def fun_l1_n126() + fun_l2_n814 +end + +def fun_l1_n127() + fun_l2_n468 +end + +def fun_l1_n128() + fun_l2_n342 +end + +def fun_l1_n129() + fun_l2_n584 +end + +def fun_l1_n130() + fun_l2_n826 +end + +def fun_l1_n131() + fun_l2_n361 +end + +def fun_l1_n132() + fun_l2_n517 +end + +def fun_l1_n133() + fun_l2_n894 +end + +def fun_l1_n134() + fun_l2_n40 +end + +def fun_l1_n135() + fun_l2_n674 +end + +def fun_l1_n136() + fun_l2_n137 +end + +def fun_l1_n137() + fun_l2_n915 +end + +def fun_l1_n138() + fun_l2_n990 +end + +def fun_l1_n139() + fun_l2_n86 +end + +def fun_l1_n140() + fun_l2_n692 +end + +def fun_l1_n141() + fun_l2_n977 +end + +def fun_l1_n142() + fun_l2_n956 +end + +def fun_l1_n143() + fun_l2_n909 +end + +def fun_l1_n144() + fun_l2_n854 +end + +def fun_l1_n145() + fun_l2_n223 +end + +def fun_l1_n146() + fun_l2_n873 +end + +def fun_l1_n147() + fun_l2_n962 +end + +def fun_l1_n148() + fun_l2_n441 +end + +def fun_l1_n149() + fun_l2_n598 +end + +def fun_l1_n150() + fun_l2_n329 +end + +def fun_l1_n151() + fun_l2_n749 +end + +def fun_l1_n152() + fun_l2_n756 +end + +def fun_l1_n153() + fun_l2_n567 +end + +def fun_l1_n154() + fun_l2_n23 +end + +def fun_l1_n155() + fun_l2_n626 +end + +def fun_l1_n156() + fun_l2_n368 +end + +def fun_l1_n157() + fun_l2_n169 +end + +def fun_l1_n158() + fun_l2_n496 +end + +def fun_l1_n159() + fun_l2_n582 +end + +def fun_l1_n160() + fun_l2_n443 +end + +def fun_l1_n161() + fun_l2_n406 +end + +def fun_l1_n162() + fun_l2_n97 +end + +def fun_l1_n163() + fun_l2_n293 +end + +def fun_l1_n164() + fun_l2_n608 +end + +def fun_l1_n165() + fun_l2_n255 +end + +def fun_l1_n166() + fun_l2_n421 +end + +def fun_l1_n167() + fun_l2_n126 +end + +def fun_l1_n168() + fun_l2_n894 +end + +def fun_l1_n169() + fun_l2_n486 +end + +def fun_l1_n170() + fun_l2_n219 +end + +def fun_l1_n171() + fun_l2_n343 +end + +def fun_l1_n172() + fun_l2_n914 +end + +def fun_l1_n173() + fun_l2_n815 +end + +def fun_l1_n174() + fun_l2_n436 +end + +def fun_l1_n175() + fun_l2_n923 +end + +def fun_l1_n176() + fun_l2_n706 +end + +def fun_l1_n177() + fun_l2_n769 +end + +def fun_l1_n178() + fun_l2_n271 +end + +def fun_l1_n179() + fun_l2_n489 +end + +def fun_l1_n180() + fun_l2_n724 +end + +def fun_l1_n181() + fun_l2_n202 +end + +def fun_l1_n182() + fun_l2_n884 +end + +def fun_l1_n183() + fun_l2_n957 +end + +def fun_l1_n184() + fun_l2_n690 +end + +def fun_l1_n185() + fun_l2_n468 +end + +def fun_l1_n186() + fun_l2_n6 +end + +def fun_l1_n187() + fun_l2_n94 +end + +def fun_l1_n188() + fun_l2_n226 +end + +def fun_l1_n189() + fun_l2_n462 +end + +def fun_l1_n190() + fun_l2_n228 +end + +def fun_l1_n191() + fun_l2_n497 +end + +def fun_l1_n192() + fun_l2_n246 +end + +def fun_l1_n193() + fun_l2_n960 +end + +def fun_l1_n194() + fun_l2_n492 +end + +def fun_l1_n195() + fun_l2_n485 +end + +def fun_l1_n196() + fun_l2_n18 +end + +def fun_l1_n197() + fun_l2_n536 +end + +def fun_l1_n198() + fun_l2_n802 +end + +def fun_l1_n199() + fun_l2_n151 +end + +def fun_l1_n200() + fun_l2_n82 +end + +def fun_l1_n201() + fun_l2_n266 +end + +def fun_l1_n202() + fun_l2_n445 +end + +def fun_l1_n203() + fun_l2_n64 +end + +def fun_l1_n204() + fun_l2_n11 +end + +def fun_l1_n205() + fun_l2_n351 +end + +def fun_l1_n206() + fun_l2_n994 +end + +def fun_l1_n207() + fun_l2_n305 +end + +def fun_l1_n208() + fun_l2_n258 +end + +def fun_l1_n209() + fun_l2_n122 +end + +def fun_l1_n210() + fun_l2_n426 +end + +def fun_l1_n211() + fun_l2_n385 +end + +def fun_l1_n212() + fun_l2_n556 +end + +def fun_l1_n213() + fun_l2_n490 +end + +def fun_l1_n214() + fun_l2_n809 +end + +def fun_l1_n215() + fun_l2_n547 +end + +def fun_l1_n216() + fun_l2_n62 +end + +def fun_l1_n217() + fun_l2_n675 +end + +def fun_l1_n218() + fun_l2_n923 +end + +def fun_l1_n219() + fun_l2_n746 +end + +def fun_l1_n220() + fun_l2_n222 +end + +def fun_l1_n221() + fun_l2_n962 +end + +def fun_l1_n222() + fun_l2_n925 +end + +def fun_l1_n223() + fun_l2_n908 +end + +def fun_l1_n224() + fun_l2_n593 +end + +def fun_l1_n225() + fun_l2_n653 +end + +def fun_l1_n226() + fun_l2_n21 +end + +def fun_l1_n227() + fun_l2_n135 +end + +def fun_l1_n228() + fun_l2_n892 +end + +def fun_l1_n229() + fun_l2_n976 +end + +def fun_l1_n230() + fun_l2_n20 +end + +def fun_l1_n231() + fun_l2_n469 +end + +def fun_l1_n232() + fun_l2_n741 +end + +def fun_l1_n233() + fun_l2_n259 +end + +def fun_l1_n234() + fun_l2_n638 +end + +def fun_l1_n235() + fun_l2_n335 +end + +def fun_l1_n236() + fun_l2_n775 +end + +def fun_l1_n237() + fun_l2_n228 +end + +def fun_l1_n238() + fun_l2_n287 +end + +def fun_l1_n239() + fun_l2_n690 +end + +def fun_l1_n240() + fun_l2_n241 +end + +def fun_l1_n241() + fun_l2_n728 +end + +def fun_l1_n242() + fun_l2_n507 +end + +def fun_l1_n243() + fun_l2_n631 +end + +def fun_l1_n244() + fun_l2_n338 +end + +def fun_l1_n245() + fun_l2_n41 +end + +def fun_l1_n246() + fun_l2_n744 +end + +def fun_l1_n247() + fun_l2_n52 +end + +def fun_l1_n248() + fun_l2_n406 +end + +def fun_l1_n249() + fun_l2_n619 +end + +def fun_l1_n250() + fun_l2_n710 +end + +def fun_l1_n251() + fun_l2_n54 +end + +def fun_l1_n252() + fun_l2_n162 +end + +def fun_l1_n253() + fun_l2_n952 +end + +def fun_l1_n254() + fun_l2_n909 +end + +def fun_l1_n255() + fun_l2_n270 +end + +def fun_l1_n256() + fun_l2_n752 +end + +def fun_l1_n257() + fun_l2_n377 +end + +def fun_l1_n258() + fun_l2_n606 +end + +def fun_l1_n259() + fun_l2_n368 +end + +def fun_l1_n260() + fun_l2_n165 +end + +def fun_l1_n261() + fun_l2_n353 +end + +def fun_l1_n262() + fun_l2_n199 +end + +def fun_l1_n263() + fun_l2_n17 +end + +def fun_l1_n264() + fun_l2_n613 +end + +def fun_l1_n265() + fun_l2_n329 +end + +def fun_l1_n266() + fun_l2_n827 +end + +def fun_l1_n267() + fun_l2_n415 +end + +def fun_l1_n268() + fun_l2_n835 +end + +def fun_l1_n269() + fun_l2_n267 +end + +def fun_l1_n270() + fun_l2_n911 +end + +def fun_l1_n271() + fun_l2_n640 +end + +def fun_l1_n272() + fun_l2_n810 +end + +def fun_l1_n273() + fun_l2_n469 +end + +def fun_l1_n274() + fun_l2_n121 +end + +def fun_l1_n275() + fun_l2_n661 +end + +def fun_l1_n276() + fun_l2_n882 +end + +def fun_l1_n277() + fun_l2_n469 +end + +def fun_l1_n278() + fun_l2_n356 +end + +def fun_l1_n279() + fun_l2_n328 +end + +def fun_l1_n280() + fun_l2_n155 +end + +def fun_l1_n281() + fun_l2_n386 +end + +def fun_l1_n282() + fun_l2_n974 +end + +def fun_l1_n283() + fun_l2_n126 +end + +def fun_l1_n284() + fun_l2_n294 +end + +def fun_l1_n285() + fun_l2_n338 +end + +def fun_l1_n286() + fun_l2_n366 +end + +def fun_l1_n287() + fun_l2_n159 +end + +def fun_l1_n288() + fun_l2_n729 +end + +def fun_l1_n289() + fun_l2_n422 +end + +def fun_l1_n290() + fun_l2_n865 +end + +def fun_l1_n291() + fun_l2_n930 +end + +def fun_l1_n292() + fun_l2_n469 +end + +def fun_l1_n293() + fun_l2_n567 +end + +def fun_l1_n294() + fun_l2_n521 +end + +def fun_l1_n295() + fun_l2_n208 +end + +def fun_l1_n296() + fun_l2_n778 +end + +def fun_l1_n297() + fun_l2_n898 +end + +def fun_l1_n298() + fun_l2_n523 +end + +def fun_l1_n299() + fun_l2_n475 +end + +def fun_l1_n300() + fun_l2_n0 +end + +def fun_l1_n301() + fun_l2_n818 +end + +def fun_l1_n302() + fun_l2_n278 +end + +def fun_l1_n303() + fun_l2_n420 +end + +def fun_l1_n304() + fun_l2_n988 +end + +def fun_l1_n305() + fun_l2_n311 +end + +def fun_l1_n306() + fun_l2_n258 +end + +def fun_l1_n307() + fun_l2_n41 +end + +def fun_l1_n308() + fun_l2_n654 +end + +def fun_l1_n309() + fun_l2_n1 +end + +def fun_l1_n310() + fun_l2_n161 +end + +def fun_l1_n311() + fun_l2_n438 +end + +def fun_l1_n312() + fun_l2_n615 +end + +def fun_l1_n313() + fun_l2_n461 +end + +def fun_l1_n314() + fun_l2_n617 +end + +def fun_l1_n315() + fun_l2_n589 +end + +def fun_l1_n316() + fun_l2_n793 +end + +def fun_l1_n317() + fun_l2_n955 +end + +def fun_l1_n318() + fun_l2_n570 +end + +def fun_l1_n319() + fun_l2_n15 +end + +def fun_l1_n320() + fun_l2_n422 +end + +def fun_l1_n321() + fun_l2_n736 +end + +def fun_l1_n322() + fun_l2_n726 +end + +def fun_l1_n323() + fun_l2_n704 +end + +def fun_l1_n324() + fun_l2_n141 +end + +def fun_l1_n325() + fun_l2_n262 +end + +def fun_l1_n326() + fun_l2_n426 +end + +def fun_l1_n327() + fun_l2_n525 +end + +def fun_l1_n328() + fun_l2_n806 +end + +def fun_l1_n329() + fun_l2_n450 +end + +def fun_l1_n330() + fun_l2_n326 +end + +def fun_l1_n331() + fun_l2_n760 +end + +def fun_l1_n332() + fun_l2_n51 +end + +def fun_l1_n333() + fun_l2_n456 +end + +def fun_l1_n334() + fun_l2_n94 +end + +def fun_l1_n335() + fun_l2_n503 +end + +def fun_l1_n336() + fun_l2_n499 +end + +def fun_l1_n337() + fun_l2_n645 +end + +def fun_l1_n338() + fun_l2_n279 +end + +def fun_l1_n339() + fun_l2_n665 +end + +def fun_l1_n340() + fun_l2_n153 +end + +def fun_l1_n341() + fun_l2_n184 +end + +def fun_l1_n342() + fun_l2_n630 +end + +def fun_l1_n343() + fun_l2_n59 +end + +def fun_l1_n344() + fun_l2_n745 +end + +def fun_l1_n345() + fun_l2_n310 +end + +def fun_l1_n346() + fun_l2_n380 +end + +def fun_l1_n347() + fun_l2_n11 +end + +def fun_l1_n348() + fun_l2_n424 +end + +def fun_l1_n349() + fun_l2_n484 +end + +def fun_l1_n350() + fun_l2_n255 +end + +def fun_l1_n351() + fun_l2_n350 +end + +def fun_l1_n352() + fun_l2_n672 +end + +def fun_l1_n353() + fun_l2_n835 +end + +def fun_l1_n354() + fun_l2_n380 +end + +def fun_l1_n355() + fun_l2_n897 +end + +def fun_l1_n356() + fun_l2_n963 +end + +def fun_l1_n357() + fun_l2_n16 +end + +def fun_l1_n358() + fun_l2_n584 +end + +def fun_l1_n359() + fun_l2_n684 +end + +def fun_l1_n360() + fun_l2_n582 +end + +def fun_l1_n361() + fun_l2_n982 +end + +def fun_l1_n362() + fun_l2_n224 +end + +def fun_l1_n363() + fun_l2_n143 +end + +def fun_l1_n364() + fun_l2_n809 +end + +def fun_l1_n365() + fun_l2_n94 +end + +def fun_l1_n366() + fun_l2_n643 +end + +def fun_l1_n367() + fun_l2_n511 +end + +def fun_l1_n368() + fun_l2_n858 +end + +def fun_l1_n369() + fun_l2_n649 +end + +def fun_l1_n370() + fun_l2_n98 +end + +def fun_l1_n371() + fun_l2_n537 +end + +def fun_l1_n372() + fun_l2_n418 +end + +def fun_l1_n373() + fun_l2_n456 +end + +def fun_l1_n374() + fun_l2_n694 +end + +def fun_l1_n375() + fun_l2_n37 +end + +def fun_l1_n376() + fun_l2_n152 +end + +def fun_l1_n377() + fun_l2_n916 +end + +def fun_l1_n378() + fun_l2_n926 +end + +def fun_l1_n379() + fun_l2_n978 +end + +def fun_l1_n380() + fun_l2_n706 +end + +def fun_l1_n381() + fun_l2_n666 +end + +def fun_l1_n382() + fun_l2_n407 +end + +def fun_l1_n383() + fun_l2_n839 +end + +def fun_l1_n384() + fun_l2_n936 +end + +def fun_l1_n385() + fun_l2_n122 +end + +def fun_l1_n386() + fun_l2_n189 +end + +def fun_l1_n387() + fun_l2_n799 +end + +def fun_l1_n388() + fun_l2_n494 +end + +def fun_l1_n389() + fun_l2_n534 +end + +def fun_l1_n390() + fun_l2_n986 +end + +def fun_l1_n391() + fun_l2_n870 +end + +def fun_l1_n392() + fun_l2_n341 +end + +def fun_l1_n393() + fun_l2_n251 +end + +def fun_l1_n394() + fun_l2_n95 +end + +def fun_l1_n395() + fun_l2_n127 +end + +def fun_l1_n396() + fun_l2_n496 +end + +def fun_l1_n397() + fun_l2_n81 +end + +def fun_l1_n398() + fun_l2_n628 +end + +def fun_l1_n399() + fun_l2_n212 +end + +def fun_l1_n400() + fun_l2_n968 +end + +def fun_l1_n401() + fun_l2_n3 +end + +def fun_l1_n402() + fun_l2_n266 +end + +def fun_l1_n403() + fun_l2_n227 +end + +def fun_l1_n404() + fun_l2_n311 +end + +def fun_l1_n405() + fun_l2_n977 +end + +def fun_l1_n406() + fun_l2_n298 +end + +def fun_l1_n407() + fun_l2_n619 +end + +def fun_l1_n408() + fun_l2_n11 +end + +def fun_l1_n409() + fun_l2_n40 +end + +def fun_l1_n410() + fun_l2_n238 +end + +def fun_l1_n411() + fun_l2_n378 +end + +def fun_l1_n412() + fun_l2_n166 +end + +def fun_l1_n413() + fun_l2_n392 +end + +def fun_l1_n414() + fun_l2_n374 +end + +def fun_l1_n415() + fun_l2_n195 +end + +def fun_l1_n416() + fun_l2_n627 +end + +def fun_l1_n417() + fun_l2_n795 +end + +def fun_l1_n418() + fun_l2_n79 +end + +def fun_l1_n419() + fun_l2_n425 +end + +def fun_l1_n420() + fun_l2_n733 +end + +def fun_l1_n421() + fun_l2_n974 +end + +def fun_l1_n422() + fun_l2_n697 +end + +def fun_l1_n423() + fun_l2_n997 +end + +def fun_l1_n424() + fun_l2_n860 +end + +def fun_l1_n425() + fun_l2_n446 +end + +def fun_l1_n426() + fun_l2_n250 +end + +def fun_l1_n427() + fun_l2_n556 +end + +def fun_l1_n428() + fun_l2_n945 +end + +def fun_l1_n429() + fun_l2_n307 +end + +def fun_l1_n430() + fun_l2_n541 +end + +def fun_l1_n431() + fun_l2_n171 +end + +def fun_l1_n432() + fun_l2_n859 +end + +def fun_l1_n433() + fun_l2_n351 +end + +def fun_l1_n434() + fun_l2_n218 +end + +def fun_l1_n435() + fun_l2_n456 +end + +def fun_l1_n436() + fun_l2_n418 +end + +def fun_l1_n437() + fun_l2_n611 +end + +def fun_l1_n438() + fun_l2_n797 +end + +def fun_l1_n439() + fun_l2_n738 +end + +def fun_l1_n440() + fun_l2_n796 +end + +def fun_l1_n441() + fun_l2_n978 +end + +def fun_l1_n442() + fun_l2_n400 +end + +def fun_l1_n443() + fun_l2_n295 +end + +def fun_l1_n444() + fun_l2_n749 +end + +def fun_l1_n445() + fun_l2_n401 +end + +def fun_l1_n446() + fun_l2_n96 +end + +def fun_l1_n447() + fun_l2_n134 +end + +def fun_l1_n448() + fun_l2_n149 +end + +def fun_l1_n449() + fun_l2_n306 +end + +def fun_l1_n450() + fun_l2_n125 +end + +def fun_l1_n451() + fun_l2_n34 +end + +def fun_l1_n452() + fun_l2_n891 +end + +def fun_l1_n453() + fun_l2_n260 +end + +def fun_l1_n454() + fun_l2_n104 +end + +def fun_l1_n455() + fun_l2_n766 +end + +def fun_l1_n456() + fun_l2_n246 +end + +def fun_l1_n457() + fun_l2_n292 +end + +def fun_l1_n458() + fun_l2_n730 +end + +def fun_l1_n459() + fun_l2_n536 +end + +def fun_l1_n460() + fun_l2_n139 +end + +def fun_l1_n461() + fun_l2_n433 +end + +def fun_l1_n462() + fun_l2_n983 +end + +def fun_l1_n463() + fun_l2_n730 +end + +def fun_l1_n464() + fun_l2_n543 +end + +def fun_l1_n465() + fun_l2_n499 +end + +def fun_l1_n466() + fun_l2_n180 +end + +def fun_l1_n467() + fun_l2_n242 +end + +def fun_l1_n468() + fun_l2_n351 +end + +def fun_l1_n469() + fun_l2_n229 +end + +def fun_l1_n470() + fun_l2_n999 +end + +def fun_l1_n471() + fun_l2_n261 +end + +def fun_l1_n472() + fun_l2_n738 +end + +def fun_l1_n473() + fun_l2_n406 +end + +def fun_l1_n474() + fun_l2_n672 +end + +def fun_l1_n475() + fun_l2_n86 +end + +def fun_l1_n476() + fun_l2_n616 +end + +def fun_l1_n477() + fun_l2_n555 +end + +def fun_l1_n478() + fun_l2_n686 +end + +def fun_l1_n479() + fun_l2_n964 +end + +def fun_l1_n480() + fun_l2_n171 +end + +def fun_l1_n481() + fun_l2_n525 +end + +def fun_l1_n482() + fun_l2_n106 +end + +def fun_l1_n483() + fun_l2_n992 +end + +def fun_l1_n484() + fun_l2_n988 +end + +def fun_l1_n485() + fun_l2_n657 +end + +def fun_l1_n486() + fun_l2_n464 +end + +def fun_l1_n487() + fun_l2_n55 +end + +def fun_l1_n488() + fun_l2_n416 +end + +def fun_l1_n489() + fun_l2_n582 +end + +def fun_l1_n490() + fun_l2_n873 +end + +def fun_l1_n491() + fun_l2_n629 +end + +def fun_l1_n492() + fun_l2_n156 +end + +def fun_l1_n493() + fun_l2_n68 +end + +def fun_l1_n494() + fun_l2_n239 +end + +def fun_l1_n495() + fun_l2_n319 +end + +def fun_l1_n496() + fun_l2_n539 +end + +def fun_l1_n497() + fun_l2_n237 +end + +def fun_l1_n498() + fun_l2_n241 +end + +def fun_l1_n499() + fun_l2_n34 +end + +def fun_l1_n500() + fun_l2_n588 +end + +def fun_l1_n501() + fun_l2_n540 +end + +def fun_l1_n502() + fun_l2_n591 +end + +def fun_l1_n503() + fun_l2_n199 +end + +def fun_l1_n504() + fun_l2_n265 +end + +def fun_l1_n505() + fun_l2_n170 +end + +def fun_l1_n506() + fun_l2_n29 +end + +def fun_l1_n507() + fun_l2_n741 +end + +def fun_l1_n508() + fun_l2_n877 +end + +def fun_l1_n509() + fun_l2_n710 +end + +def fun_l1_n510() + fun_l2_n197 +end + +def fun_l1_n511() + fun_l2_n319 +end + +def fun_l1_n512() + fun_l2_n60 +end + +def fun_l1_n513() + fun_l2_n753 +end + +def fun_l1_n514() + fun_l2_n492 +end + +def fun_l1_n515() + fun_l2_n961 +end + +def fun_l1_n516() + fun_l2_n227 +end + +def fun_l1_n517() + fun_l2_n361 +end + +def fun_l1_n518() + fun_l2_n265 +end + +def fun_l1_n519() + fun_l2_n392 +end + +def fun_l1_n520() + fun_l2_n425 +end + +def fun_l1_n521() + fun_l2_n869 +end + +def fun_l1_n522() + fun_l2_n859 +end + +def fun_l1_n523() + fun_l2_n140 +end + +def fun_l1_n524() + fun_l2_n451 +end + +def fun_l1_n525() + fun_l2_n274 +end + +def fun_l1_n526() + fun_l2_n358 +end + +def fun_l1_n527() + fun_l2_n475 +end + +def fun_l1_n528() + fun_l2_n948 +end + +def fun_l1_n529() + fun_l2_n866 +end + +def fun_l1_n530() + fun_l2_n70 +end + +def fun_l1_n531() + fun_l2_n756 +end + +def fun_l1_n532() + fun_l2_n704 +end + +def fun_l1_n533() + fun_l2_n59 +end + +def fun_l1_n534() + fun_l2_n174 +end + +def fun_l1_n535() + fun_l2_n476 +end + +def fun_l1_n536() + fun_l2_n269 +end + +def fun_l1_n537() + fun_l2_n897 +end + +def fun_l1_n538() + fun_l2_n550 +end + +def fun_l1_n539() + fun_l2_n404 +end + +def fun_l1_n540() + fun_l2_n167 +end + +def fun_l1_n541() + fun_l2_n332 +end + +def fun_l1_n542() + fun_l2_n853 +end + +def fun_l1_n543() + fun_l2_n621 +end + +def fun_l1_n544() + fun_l2_n36 +end + +def fun_l1_n545() + fun_l2_n978 +end + +def fun_l1_n546() + fun_l2_n295 +end + +def fun_l1_n547() + fun_l2_n537 +end + +def fun_l1_n548() + fun_l2_n315 +end + +def fun_l1_n549() + fun_l2_n944 +end + +def fun_l1_n550() + fun_l2_n933 +end + +def fun_l1_n551() + fun_l2_n209 +end + +def fun_l1_n552() + fun_l2_n524 +end + +def fun_l1_n553() + fun_l2_n115 +end + +def fun_l1_n554() + fun_l2_n475 +end + +def fun_l1_n555() + fun_l2_n417 +end + +def fun_l1_n556() + fun_l2_n507 +end + +def fun_l1_n557() + fun_l2_n812 +end + +def fun_l1_n558() + fun_l2_n261 +end + +def fun_l1_n559() + fun_l2_n268 +end + +def fun_l1_n560() + fun_l2_n34 +end + +def fun_l1_n561() + fun_l2_n774 +end + +def fun_l1_n562() + fun_l2_n102 +end + +def fun_l1_n563() + fun_l2_n791 +end + +def fun_l1_n564() + fun_l2_n760 +end + +def fun_l1_n565() + fun_l2_n376 +end + +def fun_l1_n566() + fun_l2_n897 +end + +def fun_l1_n567() + fun_l2_n456 +end + +def fun_l1_n568() + fun_l2_n120 +end + +def fun_l1_n569() + fun_l2_n892 +end + +def fun_l1_n570() + fun_l2_n948 +end + +def fun_l1_n571() + fun_l2_n586 +end + +def fun_l1_n572() + fun_l2_n428 +end + +def fun_l1_n573() + fun_l2_n182 +end + +def fun_l1_n574() + fun_l2_n980 +end + +def fun_l1_n575() + fun_l2_n192 +end + +def fun_l1_n576() + fun_l2_n440 +end + +def fun_l1_n577() + fun_l2_n381 +end + +def fun_l1_n578() + fun_l2_n508 +end + +def fun_l1_n579() + fun_l2_n560 +end + +def fun_l1_n580() + fun_l2_n673 +end + +def fun_l1_n581() + fun_l2_n236 +end + +def fun_l1_n582() + fun_l2_n936 +end + +def fun_l1_n583() + fun_l2_n104 +end + +def fun_l1_n584() + fun_l2_n439 +end + +def fun_l1_n585() + fun_l2_n844 +end + +def fun_l1_n586() + fun_l2_n115 +end + +def fun_l1_n587() + fun_l2_n114 +end + +def fun_l1_n588() + fun_l2_n963 +end + +def fun_l1_n589() + fun_l2_n972 +end + +def fun_l1_n590() + fun_l2_n333 +end + +def fun_l1_n591() + fun_l2_n624 +end + +def fun_l1_n592() + fun_l2_n478 +end + +def fun_l1_n593() + fun_l2_n581 +end + +def fun_l1_n594() + fun_l2_n199 +end + +def fun_l1_n595() + fun_l2_n596 +end + +def fun_l1_n596() + fun_l2_n458 +end + +def fun_l1_n597() + fun_l2_n729 +end + +def fun_l1_n598() + fun_l2_n545 +end + +def fun_l1_n599() + fun_l2_n60 +end + +def fun_l1_n600() + fun_l2_n801 +end + +def fun_l1_n601() + fun_l2_n164 +end + +def fun_l1_n602() + fun_l2_n3 +end + +def fun_l1_n603() + fun_l2_n334 +end + +def fun_l1_n604() + fun_l2_n887 +end + +def fun_l1_n605() + fun_l2_n777 +end + +def fun_l1_n606() + fun_l2_n765 +end + +def fun_l1_n607() + fun_l2_n529 +end + +def fun_l1_n608() + fun_l2_n233 +end + +def fun_l1_n609() + fun_l2_n164 +end + +def fun_l1_n610() + fun_l2_n289 +end + +def fun_l1_n611() + fun_l2_n918 +end + +def fun_l1_n612() + fun_l2_n13 +end + +def fun_l1_n613() + fun_l2_n530 +end + +def fun_l1_n614() + fun_l2_n574 +end + +def fun_l1_n615() + fun_l2_n383 +end + +def fun_l1_n616() + fun_l2_n470 +end + +def fun_l1_n617() + fun_l2_n551 +end + +def fun_l1_n618() + fun_l2_n539 +end + +def fun_l1_n619() + fun_l2_n858 +end + +def fun_l1_n620() + fun_l2_n523 +end + +def fun_l1_n621() + fun_l2_n439 +end + +def fun_l1_n622() + fun_l2_n909 +end + +def fun_l1_n623() + fun_l2_n686 +end + +def fun_l1_n624() + fun_l2_n133 +end + +def fun_l1_n625() + fun_l2_n92 +end + +def fun_l1_n626() + fun_l2_n443 +end + +def fun_l1_n627() + fun_l2_n682 +end + +def fun_l1_n628() + fun_l2_n113 +end + +def fun_l1_n629() + fun_l2_n353 +end + +def fun_l1_n630() + fun_l2_n631 +end + +def fun_l1_n631() + fun_l2_n858 +end + +def fun_l1_n632() + fun_l2_n816 +end + +def fun_l1_n633() + fun_l2_n683 +end + +def fun_l1_n634() + fun_l2_n32 +end + +def fun_l1_n635() + fun_l2_n983 +end + +def fun_l1_n636() + fun_l2_n587 +end + +def fun_l1_n637() + fun_l2_n17 +end + +def fun_l1_n638() + fun_l2_n129 +end + +def fun_l1_n639() + fun_l2_n166 +end + +def fun_l1_n640() + fun_l2_n742 +end + +def fun_l1_n641() + fun_l2_n8 +end + +def fun_l1_n642() + fun_l2_n119 +end + +def fun_l1_n643() + fun_l2_n615 +end + +def fun_l1_n644() + fun_l2_n419 +end + +def fun_l1_n645() + fun_l2_n324 +end + +def fun_l1_n646() + fun_l2_n806 +end + +def fun_l1_n647() + fun_l2_n722 +end + +def fun_l1_n648() + fun_l2_n462 +end + +def fun_l1_n649() + fun_l2_n602 +end + +def fun_l1_n650() + fun_l2_n39 +end + +def fun_l1_n651() + fun_l2_n53 +end + +def fun_l1_n652() + fun_l2_n201 +end + +def fun_l1_n653() + fun_l2_n403 +end + +def fun_l1_n654() + fun_l2_n595 +end + +def fun_l1_n655() + fun_l2_n467 +end + +def fun_l1_n656() + fun_l2_n904 +end + +def fun_l1_n657() + fun_l2_n429 +end + +def fun_l1_n658() + fun_l2_n463 +end + +def fun_l1_n659() + fun_l2_n470 +end + +def fun_l1_n660() + fun_l2_n0 +end + +def fun_l1_n661() + fun_l2_n258 +end + +def fun_l1_n662() + fun_l2_n950 +end + +def fun_l1_n663() + fun_l2_n953 +end + +def fun_l1_n664() + fun_l2_n664 +end + +def fun_l1_n665() + fun_l2_n12 +end + +def fun_l1_n666() + fun_l2_n317 +end + +def fun_l1_n667() + fun_l2_n526 +end + +def fun_l1_n668() + fun_l2_n984 +end + +def fun_l1_n669() + fun_l2_n273 +end + +def fun_l1_n670() + fun_l2_n822 +end + +def fun_l1_n671() + fun_l2_n759 +end + +def fun_l1_n672() + fun_l2_n927 +end + +def fun_l1_n673() + fun_l2_n419 +end + +def fun_l1_n674() + fun_l2_n546 +end + +def fun_l1_n675() + fun_l2_n879 +end + +def fun_l1_n676() + fun_l2_n659 +end + +def fun_l1_n677() + fun_l2_n317 +end + +def fun_l1_n678() + fun_l2_n234 +end + +def fun_l1_n679() + fun_l2_n416 +end + +def fun_l1_n680() + fun_l2_n890 +end + +def fun_l1_n681() + fun_l2_n401 +end + +def fun_l1_n682() + fun_l2_n271 +end + +def fun_l1_n683() + fun_l2_n915 +end + +def fun_l1_n684() + fun_l2_n666 +end + +def fun_l1_n685() + fun_l2_n151 +end + +def fun_l1_n686() + fun_l2_n786 +end + +def fun_l1_n687() + fun_l2_n82 +end + +def fun_l1_n688() + fun_l2_n831 +end + +def fun_l1_n689() + fun_l2_n830 +end + +def fun_l1_n690() + fun_l2_n221 +end + +def fun_l1_n691() + fun_l2_n530 +end + +def fun_l1_n692() + fun_l2_n131 +end + +def fun_l1_n693() + fun_l2_n17 +end + +def fun_l1_n694() + fun_l2_n265 +end + +def fun_l1_n695() + fun_l2_n111 +end + +def fun_l1_n696() + fun_l2_n39 +end + +def fun_l1_n697() + fun_l2_n326 +end + +def fun_l1_n698() + fun_l2_n713 +end + +def fun_l1_n699() + fun_l2_n960 +end + +def fun_l1_n700() + fun_l2_n633 +end + +def fun_l1_n701() + fun_l2_n291 +end + +def fun_l1_n702() + fun_l2_n746 +end + +def fun_l1_n703() + fun_l2_n316 +end + +def fun_l1_n704() + fun_l2_n116 +end + +def fun_l1_n705() + fun_l2_n195 +end + +def fun_l1_n706() + fun_l2_n614 +end + +def fun_l1_n707() + fun_l2_n591 +end + +def fun_l1_n708() + fun_l2_n879 +end + +def fun_l1_n709() + fun_l2_n770 +end + +def fun_l1_n710() + fun_l2_n332 +end + +def fun_l1_n711() + fun_l2_n696 +end + +def fun_l1_n712() + fun_l2_n42 +end + +def fun_l1_n713() + fun_l2_n126 +end + +def fun_l1_n714() + fun_l2_n486 +end + +def fun_l1_n715() + fun_l2_n259 +end + +def fun_l1_n716() + fun_l2_n390 +end + +def fun_l1_n717() + fun_l2_n590 +end + +def fun_l1_n718() + fun_l2_n180 +end + +def fun_l1_n719() + fun_l2_n673 +end + +def fun_l1_n720() + fun_l2_n565 +end + +def fun_l1_n721() + fun_l2_n504 +end + +def fun_l1_n722() + fun_l2_n585 +end + +def fun_l1_n723() + fun_l2_n746 +end + +def fun_l1_n724() + fun_l2_n797 +end + +def fun_l1_n725() + fun_l2_n281 +end + +def fun_l1_n726() + fun_l2_n670 +end + +def fun_l1_n727() + fun_l2_n678 +end + +def fun_l1_n728() + fun_l2_n329 +end + +def fun_l1_n729() + fun_l2_n581 +end + +def fun_l1_n730() + fun_l2_n313 +end + +def fun_l1_n731() + fun_l2_n893 +end + +def fun_l1_n732() + fun_l2_n773 +end + +def fun_l1_n733() + fun_l2_n527 +end + +def fun_l1_n734() + fun_l2_n473 +end + +def fun_l1_n735() + fun_l2_n242 +end + +def fun_l1_n736() + fun_l2_n681 +end + +def fun_l1_n737() + fun_l2_n593 +end + +def fun_l1_n738() + fun_l2_n214 +end + +def fun_l1_n739() + fun_l2_n931 +end + +def fun_l1_n740() + fun_l2_n157 +end + +def fun_l1_n741() + fun_l2_n207 +end + +def fun_l1_n742() + fun_l2_n583 +end + +def fun_l1_n743() + fun_l2_n978 +end + +def fun_l1_n744() + fun_l2_n220 +end + +def fun_l1_n745() + fun_l2_n0 +end + +def fun_l1_n746() + fun_l2_n871 +end + +def fun_l1_n747() + fun_l2_n344 +end + +def fun_l1_n748() + fun_l2_n445 +end + +def fun_l1_n749() + fun_l2_n682 +end + +def fun_l1_n750() + fun_l2_n553 +end + +def fun_l1_n751() + fun_l2_n616 +end + +def fun_l1_n752() + fun_l2_n93 +end + +def fun_l1_n753() + fun_l2_n297 +end + +def fun_l1_n754() + fun_l2_n653 +end + +def fun_l1_n755() + fun_l2_n730 +end + +def fun_l1_n756() + fun_l2_n375 +end + +def fun_l1_n757() + fun_l2_n522 +end + +def fun_l1_n758() + fun_l2_n855 +end + +def fun_l1_n759() + fun_l2_n727 +end + +def fun_l1_n760() + fun_l2_n516 +end + +def fun_l1_n761() + fun_l2_n322 +end + +def fun_l1_n762() + fun_l2_n84 +end + +def fun_l1_n763() + fun_l2_n704 +end + +def fun_l1_n764() + fun_l2_n516 +end + +def fun_l1_n765() + fun_l2_n97 +end + +def fun_l1_n766() + fun_l2_n678 +end + +def fun_l1_n767() + fun_l2_n690 +end + +def fun_l1_n768() + fun_l2_n704 +end + +def fun_l1_n769() + fun_l2_n664 +end + +def fun_l1_n770() + fun_l2_n157 +end + +def fun_l1_n771() + fun_l2_n24 +end + +def fun_l1_n772() + fun_l2_n399 +end + +def fun_l1_n773() + fun_l2_n362 +end + +def fun_l1_n774() + fun_l2_n687 +end + +def fun_l1_n775() + fun_l2_n228 +end + +def fun_l1_n776() + fun_l2_n781 +end + +def fun_l1_n777() + fun_l2_n112 +end + +def fun_l1_n778() + fun_l2_n126 +end + +def fun_l1_n779() + fun_l2_n298 +end + +def fun_l1_n780() + fun_l2_n779 +end + +def fun_l1_n781() + fun_l2_n354 +end + +def fun_l1_n782() + fun_l2_n357 +end + +def fun_l1_n783() + fun_l2_n814 +end + +def fun_l1_n784() + fun_l2_n975 +end + +def fun_l1_n785() + fun_l2_n853 +end + +def fun_l1_n786() + fun_l2_n58 +end + +def fun_l1_n787() + fun_l2_n455 +end + +def fun_l1_n788() + fun_l2_n31 +end + +def fun_l1_n789() + fun_l2_n621 +end + +def fun_l1_n790() + fun_l2_n714 +end + +def fun_l1_n791() + fun_l2_n931 +end + +def fun_l1_n792() + fun_l2_n511 +end + +def fun_l1_n793() + fun_l2_n128 +end + +def fun_l1_n794() + fun_l2_n750 +end + +def fun_l1_n795() + fun_l2_n121 +end + +def fun_l1_n796() + fun_l2_n226 +end + +def fun_l1_n797() + fun_l2_n515 +end + +def fun_l1_n798() + fun_l2_n8 +end + +def fun_l1_n799() + fun_l2_n372 +end + +def fun_l1_n800() + fun_l2_n646 +end + +def fun_l1_n801() + fun_l2_n722 +end + +def fun_l1_n802() + fun_l2_n932 +end + +def fun_l1_n803() + fun_l2_n992 +end + +def fun_l1_n804() + fun_l2_n628 +end + +def fun_l1_n805() + fun_l2_n97 +end + +def fun_l1_n806() + fun_l2_n113 +end + +def fun_l1_n807() + fun_l2_n249 +end + +def fun_l1_n808() + fun_l2_n211 +end + +def fun_l1_n809() + fun_l2_n40 +end + +def fun_l1_n810() + fun_l2_n608 +end + +def fun_l1_n811() + fun_l2_n560 +end + +def fun_l1_n812() + fun_l2_n182 +end + +def fun_l1_n813() + fun_l2_n7 +end + +def fun_l1_n814() + fun_l2_n641 +end + +def fun_l1_n815() + fun_l2_n541 +end + +def fun_l1_n816() + fun_l2_n951 +end + +def fun_l1_n817() + fun_l2_n122 +end + +def fun_l1_n818() + fun_l2_n270 +end + +def fun_l1_n819() + fun_l2_n631 +end + +def fun_l1_n820() + fun_l2_n787 +end + +def fun_l1_n821() + fun_l2_n543 +end + +def fun_l1_n822() + fun_l2_n599 +end + +def fun_l1_n823() + fun_l2_n686 +end + +def fun_l1_n824() + fun_l2_n11 +end + +def fun_l1_n825() + fun_l2_n379 +end + +def fun_l1_n826() + fun_l2_n190 +end + +def fun_l1_n827() + fun_l2_n815 +end + +def fun_l1_n828() + fun_l2_n117 +end + +def fun_l1_n829() + fun_l2_n465 +end + +def fun_l1_n830() + fun_l2_n333 +end + +def fun_l1_n831() + fun_l2_n928 +end + +def fun_l1_n832() + fun_l2_n565 +end + +def fun_l1_n833() + fun_l2_n83 +end + +def fun_l1_n834() + fun_l2_n364 +end + +def fun_l1_n835() + fun_l2_n93 +end + +def fun_l1_n836() + fun_l2_n20 +end + +def fun_l1_n837() + fun_l2_n223 +end + +def fun_l1_n838() + fun_l2_n720 +end + +def fun_l1_n839() + fun_l2_n848 +end + +def fun_l1_n840() + fun_l2_n228 +end + +def fun_l1_n841() + fun_l2_n607 +end + +def fun_l1_n842() + fun_l2_n253 +end + +def fun_l1_n843() + fun_l2_n426 +end + +def fun_l1_n844() + fun_l2_n295 +end + +def fun_l1_n845() + fun_l2_n213 +end + +def fun_l1_n846() + fun_l2_n991 +end + +def fun_l1_n847() + fun_l2_n169 +end + +def fun_l1_n848() + fun_l2_n32 +end + +def fun_l1_n849() + fun_l2_n495 +end + +def fun_l1_n850() + fun_l2_n528 +end + +def fun_l1_n851() + fun_l2_n862 +end + +def fun_l1_n852() + fun_l2_n712 +end + +def fun_l1_n853() + fun_l2_n234 +end + +def fun_l1_n854() + fun_l2_n646 +end + +def fun_l1_n855() + fun_l2_n720 +end + +def fun_l1_n856() + fun_l2_n605 +end + +def fun_l1_n857() + fun_l2_n966 +end + +def fun_l1_n858() + fun_l2_n68 +end + +def fun_l1_n859() + fun_l2_n914 +end + +def fun_l1_n860() + fun_l2_n234 +end + +def fun_l1_n861() + fun_l2_n410 +end + +def fun_l1_n862() + fun_l2_n370 +end + +def fun_l1_n863() + fun_l2_n127 +end + +def fun_l1_n864() + fun_l2_n187 +end + +def fun_l1_n865() + fun_l2_n98 +end + +def fun_l1_n866() + fun_l2_n256 +end + +def fun_l1_n867() + fun_l2_n747 +end + +def fun_l1_n868() + fun_l2_n344 +end + +def fun_l1_n869() + fun_l2_n570 +end + +def fun_l1_n870() + fun_l2_n552 +end + +def fun_l1_n871() + fun_l2_n499 +end + +def fun_l1_n872() + fun_l2_n763 +end + +def fun_l1_n873() + fun_l2_n35 +end + +def fun_l1_n874() + fun_l2_n229 +end + +def fun_l1_n875() + fun_l2_n124 +end + +def fun_l1_n876() + fun_l2_n258 +end + +def fun_l1_n877() + fun_l2_n280 +end + +def fun_l1_n878() + fun_l2_n899 +end + +def fun_l1_n879() + fun_l2_n211 +end + +def fun_l1_n880() + fun_l2_n741 +end + +def fun_l1_n881() + fun_l2_n32 +end + +def fun_l1_n882() + fun_l2_n212 +end + +def fun_l1_n883() + fun_l2_n661 +end + +def fun_l1_n884() + fun_l2_n889 +end + +def fun_l1_n885() + fun_l2_n975 +end + +def fun_l1_n886() + fun_l2_n288 +end + +def fun_l1_n887() + fun_l2_n448 +end + +def fun_l1_n888() + fun_l2_n520 +end + +def fun_l1_n889() + fun_l2_n284 +end + +def fun_l1_n890() + fun_l2_n254 +end + +def fun_l1_n891() + fun_l2_n703 +end + +def fun_l1_n892() + fun_l2_n706 +end + +def fun_l1_n893() + fun_l2_n9 +end + +def fun_l1_n894() + fun_l2_n717 +end + +def fun_l1_n895() + fun_l2_n290 +end + +def fun_l1_n896() + fun_l2_n657 +end + +def fun_l1_n897() + fun_l2_n452 +end + +def fun_l1_n898() + fun_l2_n493 +end + +def fun_l1_n899() + fun_l2_n308 +end + +def fun_l1_n900() + fun_l2_n781 +end + +def fun_l1_n901() + fun_l2_n970 +end + +def fun_l1_n902() + fun_l2_n371 +end + +def fun_l1_n903() + fun_l2_n195 +end + +def fun_l1_n904() + fun_l2_n662 +end + +def fun_l1_n905() + fun_l2_n172 +end + +def fun_l1_n906() + fun_l2_n579 +end + +def fun_l1_n907() + fun_l2_n913 +end + +def fun_l1_n908() + fun_l2_n949 +end + +def fun_l1_n909() + fun_l2_n386 +end + +def fun_l1_n910() + fun_l2_n727 +end + +def fun_l1_n911() + fun_l2_n283 +end + +def fun_l1_n912() + fun_l2_n136 +end + +def fun_l1_n913() + fun_l2_n818 +end + +def fun_l1_n914() + fun_l2_n118 +end + +def fun_l1_n915() + fun_l2_n366 +end + +def fun_l1_n916() + fun_l2_n362 +end + +def fun_l1_n917() + fun_l2_n854 +end + +def fun_l1_n918() + fun_l2_n272 +end + +def fun_l1_n919() + fun_l2_n754 +end + +def fun_l1_n920() + fun_l2_n145 +end + +def fun_l1_n921() + fun_l2_n631 +end + +def fun_l1_n922() + fun_l2_n131 +end + +def fun_l1_n923() + fun_l2_n862 +end + +def fun_l1_n924() + fun_l2_n930 +end + +def fun_l1_n925() + fun_l2_n24 +end + +def fun_l1_n926() + fun_l2_n336 +end + +def fun_l1_n927() + fun_l2_n438 +end + +def fun_l1_n928() + fun_l2_n306 +end + +def fun_l1_n929() + fun_l2_n897 +end + +def fun_l1_n930() + fun_l2_n186 +end + +def fun_l1_n931() + fun_l2_n227 +end + +def fun_l1_n932() + fun_l2_n462 +end + +def fun_l1_n933() + fun_l2_n224 +end + +def fun_l1_n934() + fun_l2_n210 +end + +def fun_l1_n935() + fun_l2_n315 +end + +def fun_l1_n936() + fun_l2_n850 +end + +def fun_l1_n937() + fun_l2_n997 +end + +def fun_l1_n938() + fun_l2_n703 +end + +def fun_l1_n939() + fun_l2_n635 +end + +def fun_l1_n940() + fun_l2_n507 +end + +def fun_l1_n941() + fun_l2_n202 +end + +def fun_l1_n942() + fun_l2_n319 +end + +def fun_l1_n943() + fun_l2_n785 +end + +def fun_l1_n944() + fun_l2_n26 +end + +def fun_l1_n945() + fun_l2_n777 +end + +def fun_l1_n946() + fun_l2_n235 +end + +def fun_l1_n947() + fun_l2_n845 +end + +def fun_l1_n948() + fun_l2_n515 +end + +def fun_l1_n949() + fun_l2_n427 +end + +def fun_l1_n950() + fun_l2_n34 +end + +def fun_l1_n951() + fun_l2_n905 +end + +def fun_l1_n952() + fun_l2_n683 +end + +def fun_l1_n953() + fun_l2_n171 +end + +def fun_l1_n954() + fun_l2_n593 +end + +def fun_l1_n955() + fun_l2_n191 +end + +def fun_l1_n956() + fun_l2_n370 +end + +def fun_l1_n957() + fun_l2_n911 +end + +def fun_l1_n958() + fun_l2_n813 +end + +def fun_l1_n959() + fun_l2_n765 +end + +def fun_l1_n960() + fun_l2_n434 +end + +def fun_l1_n961() + fun_l2_n442 +end + +def fun_l1_n962() + fun_l2_n390 +end + +def fun_l1_n963() + fun_l2_n549 +end + +def fun_l1_n964() + fun_l2_n757 +end + +def fun_l1_n965() + fun_l2_n12 +end + +def fun_l1_n966() + fun_l2_n456 +end + +def fun_l1_n967() + fun_l2_n889 +end + +def fun_l1_n968() + fun_l2_n933 +end + +def fun_l1_n969() + fun_l2_n695 +end + +def fun_l1_n970() + fun_l2_n628 +end + +def fun_l1_n971() + fun_l2_n265 +end + +def fun_l1_n972() + fun_l2_n634 +end + +def fun_l1_n973() + fun_l2_n31 +end + +def fun_l1_n974() + fun_l2_n49 +end + +def fun_l1_n975() + fun_l2_n872 +end + +def fun_l1_n976() + fun_l2_n475 +end + +def fun_l1_n977() + fun_l2_n927 +end + +def fun_l1_n978() + fun_l2_n459 +end + +def fun_l1_n979() + fun_l2_n364 +end + +def fun_l1_n980() + fun_l2_n246 +end + +def fun_l1_n981() + fun_l2_n693 +end + +def fun_l1_n982() + fun_l2_n218 +end + +def fun_l1_n983() + fun_l2_n21 +end + +def fun_l1_n984() + fun_l2_n967 +end + +def fun_l1_n985() + fun_l2_n81 +end + +def fun_l1_n986() + fun_l2_n753 +end + +def fun_l1_n987() + fun_l2_n386 +end + +def fun_l1_n988() + fun_l2_n394 +end + +def fun_l1_n989() + fun_l2_n804 +end + +def fun_l1_n990() + fun_l2_n55 +end + +def fun_l1_n991() + fun_l2_n359 +end + +def fun_l1_n992() + fun_l2_n883 +end + +def fun_l1_n993() + fun_l2_n404 +end + +def fun_l1_n994() + fun_l2_n145 +end + +def fun_l1_n995() + fun_l2_n684 +end + +def fun_l1_n996() + fun_l2_n38 +end + +def fun_l1_n997() + fun_l2_n309 +end + +def fun_l1_n998() + fun_l2_n560 +end + +def fun_l1_n999() + fun_l2_n95 +end + +def fun_l2_n0() + fun_l3_n813 +end + +def fun_l2_n1() + fun_l3_n785 +end + +def fun_l2_n2() + fun_l3_n218 +end + +def fun_l2_n3() + fun_l3_n111 +end + +def fun_l2_n4() + fun_l3_n581 +end + +def fun_l2_n5() + fun_l3_n873 +end + +def fun_l2_n6() + fun_l3_n123 +end + +def fun_l2_n7() + fun_l3_n576 +end + +def fun_l2_n8() + fun_l3_n543 +end + +def fun_l2_n9() + fun_l3_n720 +end + +def fun_l2_n10() + fun_l3_n970 +end + +def fun_l2_n11() + fun_l3_n663 +end + +def fun_l2_n12() + fun_l3_n549 +end + +def fun_l2_n13() + fun_l3_n787 +end + +def fun_l2_n14() + fun_l3_n15 +end + +def fun_l2_n15() + fun_l3_n858 +end + +def fun_l2_n16() + fun_l3_n873 +end + +def fun_l2_n17() + fun_l3_n482 +end + +def fun_l2_n18() + fun_l3_n26 +end + +def fun_l2_n19() + fun_l3_n591 +end + +def fun_l2_n20() + fun_l3_n879 +end + +def fun_l2_n21() + fun_l3_n891 +end + +def fun_l2_n22() + fun_l3_n381 +end + +def fun_l2_n23() + fun_l3_n504 +end + +def fun_l2_n24() + fun_l3_n595 +end + +def fun_l2_n25() + fun_l3_n985 +end + +def fun_l2_n26() + fun_l3_n77 +end + +def fun_l2_n27() + fun_l3_n144 +end + +def fun_l2_n28() + fun_l3_n912 +end + +def fun_l2_n29() + fun_l3_n1 +end + +def fun_l2_n30() + fun_l3_n816 +end + +def fun_l2_n31() + fun_l3_n246 +end + +def fun_l2_n32() + fun_l3_n599 +end + +def fun_l2_n33() + fun_l3_n961 +end + +def fun_l2_n34() + fun_l3_n392 +end + +def fun_l2_n35() + fun_l3_n437 +end + +def fun_l2_n36() + fun_l3_n520 +end + +def fun_l2_n37() + fun_l3_n146 +end + +def fun_l2_n38() + fun_l3_n186 +end + +def fun_l2_n39() + fun_l3_n699 +end + +def fun_l2_n40() + fun_l3_n863 +end + +def fun_l2_n41() + fun_l3_n539 +end + +def fun_l2_n42() + fun_l3_n581 +end + +def fun_l2_n43() + fun_l3_n325 +end + +def fun_l2_n44() + fun_l3_n604 +end + +def fun_l2_n45() + fun_l3_n79 +end + +def fun_l2_n46() + fun_l3_n530 +end + +def fun_l2_n47() + fun_l3_n344 +end + +def fun_l2_n48() + fun_l3_n92 +end + +def fun_l2_n49() + fun_l3_n826 +end + +def fun_l2_n50() + fun_l3_n283 +end + +def fun_l2_n51() + fun_l3_n220 +end + +def fun_l2_n52() + fun_l3_n96 +end + +def fun_l2_n53() + fun_l3_n647 +end + +def fun_l2_n54() + fun_l3_n664 +end + +def fun_l2_n55() + fun_l3_n718 +end + +def fun_l2_n56() + fun_l3_n281 +end + +def fun_l2_n57() + fun_l3_n214 +end + +def fun_l2_n58() + fun_l3_n143 +end + +def fun_l2_n59() + fun_l3_n423 +end + +def fun_l2_n60() + fun_l3_n815 +end + +def fun_l2_n61() + fun_l3_n561 +end + +def fun_l2_n62() + fun_l3_n634 +end + +def fun_l2_n63() + fun_l3_n354 +end + +def fun_l2_n64() + fun_l3_n39 +end + +def fun_l2_n65() + fun_l3_n704 +end + +def fun_l2_n66() + fun_l3_n193 +end + +def fun_l2_n67() + fun_l3_n267 +end + +def fun_l2_n68() + fun_l3_n225 +end + +def fun_l2_n69() + fun_l3_n253 +end + +def fun_l2_n70() + fun_l3_n97 +end + +def fun_l2_n71() + fun_l3_n312 +end + +def fun_l2_n72() + fun_l3_n663 +end + +def fun_l2_n73() + fun_l3_n730 +end + +def fun_l2_n74() + fun_l3_n31 +end + +def fun_l2_n75() + fun_l3_n94 +end + +def fun_l2_n76() + fun_l3_n719 +end + +def fun_l2_n77() + fun_l3_n72 +end + +def fun_l2_n78() + fun_l3_n593 +end + +def fun_l2_n79() + fun_l3_n586 +end + +def fun_l2_n80() + fun_l3_n477 +end + +def fun_l2_n81() + fun_l3_n406 +end + +def fun_l2_n82() + fun_l3_n624 +end + +def fun_l2_n83() + fun_l3_n127 +end + +def fun_l2_n84() + fun_l3_n993 +end + +def fun_l2_n85() + fun_l3_n764 +end + +def fun_l2_n86() + fun_l3_n892 +end + +def fun_l2_n87() + fun_l3_n147 +end + +def fun_l2_n88() + fun_l3_n971 +end + +def fun_l2_n89() + fun_l3_n239 +end + +def fun_l2_n90() + fun_l3_n96 +end + +def fun_l2_n91() + fun_l3_n686 +end + +def fun_l2_n92() + fun_l3_n388 +end + +def fun_l2_n93() + fun_l3_n848 +end + +def fun_l2_n94() + fun_l3_n415 +end + +def fun_l2_n95() + fun_l3_n155 +end + +def fun_l2_n96() + fun_l3_n245 +end + +def fun_l2_n97() + fun_l3_n103 +end + +def fun_l2_n98() + fun_l3_n591 +end + +def fun_l2_n99() + fun_l3_n610 +end + +def fun_l2_n100() + fun_l3_n925 +end + +def fun_l2_n101() + fun_l3_n435 +end + +def fun_l2_n102() + fun_l3_n580 +end + +def fun_l2_n103() + fun_l3_n116 +end + +def fun_l2_n104() + fun_l3_n160 +end + +def fun_l2_n105() + fun_l3_n245 +end + +def fun_l2_n106() + fun_l3_n970 +end + +def fun_l2_n107() + fun_l3_n540 +end + +def fun_l2_n108() + fun_l3_n385 +end + +def fun_l2_n109() + fun_l3_n292 +end + +def fun_l2_n110() + fun_l3_n785 +end + +def fun_l2_n111() + fun_l3_n310 +end + +def fun_l2_n112() + fun_l3_n983 +end + +def fun_l2_n113() + fun_l3_n378 +end + +def fun_l2_n114() + fun_l3_n538 +end + +def fun_l2_n115() + fun_l3_n161 +end + +def fun_l2_n116() + fun_l3_n537 +end + +def fun_l2_n117() + fun_l3_n1 +end + +def fun_l2_n118() + fun_l3_n606 +end + +def fun_l2_n119() + fun_l3_n377 +end + +def fun_l2_n120() + fun_l3_n839 +end + +def fun_l2_n121() + fun_l3_n174 +end + +def fun_l2_n122() + fun_l3_n709 +end + +def fun_l2_n123() + fun_l3_n384 +end + +def fun_l2_n124() + fun_l3_n566 +end + +def fun_l2_n125() + fun_l3_n329 +end + +def fun_l2_n126() + fun_l3_n238 +end + +def fun_l2_n127() + fun_l3_n366 +end + +def fun_l2_n128() + fun_l3_n443 +end + +def fun_l2_n129() + fun_l3_n901 +end + +def fun_l2_n130() + fun_l3_n16 +end + +def fun_l2_n131() + fun_l3_n959 +end + +def fun_l2_n132() + fun_l3_n460 +end + +def fun_l2_n133() + fun_l3_n26 +end + +def fun_l2_n134() + fun_l3_n552 +end + +def fun_l2_n135() + fun_l3_n207 +end + +def fun_l2_n136() + fun_l3_n804 +end + +def fun_l2_n137() + fun_l3_n178 +end + +def fun_l2_n138() + fun_l3_n826 +end + +def fun_l2_n139() + fun_l3_n421 +end + +def fun_l2_n140() + fun_l3_n101 +end + +def fun_l2_n141() + fun_l3_n529 +end + +def fun_l2_n142() + fun_l3_n594 +end + +def fun_l2_n143() + fun_l3_n977 +end + +def fun_l2_n144() + fun_l3_n859 +end + +def fun_l2_n145() + fun_l3_n24 +end + +def fun_l2_n146() + fun_l3_n806 +end + +def fun_l2_n147() + fun_l3_n355 +end + +def fun_l2_n148() + fun_l3_n648 +end + +def fun_l2_n149() + fun_l3_n554 +end + +def fun_l2_n150() + fun_l3_n188 +end + +def fun_l2_n151() + fun_l3_n711 +end + +def fun_l2_n152() + fun_l3_n574 +end + +def fun_l2_n153() + fun_l3_n667 +end + +def fun_l2_n154() + fun_l3_n638 +end + +def fun_l2_n155() + fun_l3_n283 +end + +def fun_l2_n156() + fun_l3_n999 +end + +def fun_l2_n157() + fun_l3_n412 +end + +def fun_l2_n158() + fun_l3_n621 +end + +def fun_l2_n159() + fun_l3_n821 +end + +def fun_l2_n160() + fun_l3_n857 +end + +def fun_l2_n161() + fun_l3_n73 +end + +def fun_l2_n162() + fun_l3_n768 +end + +def fun_l2_n163() + fun_l3_n929 +end + +def fun_l2_n164() + fun_l3_n205 +end + +def fun_l2_n165() + fun_l3_n120 +end + +def fun_l2_n166() + fun_l3_n787 +end + +def fun_l2_n167() + fun_l3_n69 +end + +def fun_l2_n168() + fun_l3_n567 +end + +def fun_l2_n169() + fun_l3_n106 +end + +def fun_l2_n170() + fun_l3_n751 +end + +def fun_l2_n171() + fun_l3_n642 +end + +def fun_l2_n172() + fun_l3_n744 +end + +def fun_l2_n173() + fun_l3_n730 +end + +def fun_l2_n174() + fun_l3_n681 +end + +def fun_l2_n175() + fun_l3_n493 +end + +def fun_l2_n176() + fun_l3_n773 +end + +def fun_l2_n177() + fun_l3_n393 +end + +def fun_l2_n178() + fun_l3_n702 +end + +def fun_l2_n179() + fun_l3_n353 +end + +def fun_l2_n180() + fun_l3_n21 +end + +def fun_l2_n181() + fun_l3_n575 +end + +def fun_l2_n182() + fun_l3_n975 +end + +def fun_l2_n183() + fun_l3_n969 +end + +def fun_l2_n184() + fun_l3_n8 +end + +def fun_l2_n185() + fun_l3_n81 +end + +def fun_l2_n186() + fun_l3_n650 +end + +def fun_l2_n187() + fun_l3_n257 +end + +def fun_l2_n188() + fun_l3_n443 +end + +def fun_l2_n189() + fun_l3_n647 +end + +def fun_l2_n190() + fun_l3_n783 +end + +def fun_l2_n191() + fun_l3_n447 +end + +def fun_l2_n192() + fun_l3_n50 +end + +def fun_l2_n193() + fun_l3_n25 +end + +def fun_l2_n194() + fun_l3_n646 +end + +def fun_l2_n195() + fun_l3_n878 +end + +def fun_l2_n196() + fun_l3_n156 +end + +def fun_l2_n197() + fun_l3_n999 +end + +def fun_l2_n198() + fun_l3_n292 +end + +def fun_l2_n199() + fun_l3_n386 +end + +def fun_l2_n200() + fun_l3_n3 +end + +def fun_l2_n201() + fun_l3_n111 +end + +def fun_l2_n202() + fun_l3_n89 +end + +def fun_l2_n203() + fun_l3_n628 +end + +def fun_l2_n204() + fun_l3_n384 +end + +def fun_l2_n205() + fun_l3_n951 +end + +def fun_l2_n206() + fun_l3_n662 +end + +def fun_l2_n207() + fun_l3_n607 +end + +def fun_l2_n208() + fun_l3_n245 +end + +def fun_l2_n209() + fun_l3_n875 +end + +def fun_l2_n210() + fun_l3_n493 +end + +def fun_l2_n211() + fun_l3_n639 +end + +def fun_l2_n212() + fun_l3_n257 +end + +def fun_l2_n213() + fun_l3_n710 +end + +def fun_l2_n214() + fun_l3_n848 +end + +def fun_l2_n215() + fun_l3_n86 +end + +def fun_l2_n216() + fun_l3_n269 +end + +def fun_l2_n217() + fun_l3_n907 +end + +def fun_l2_n218() + fun_l3_n491 +end + +def fun_l2_n219() + fun_l3_n194 +end + +def fun_l2_n220() + fun_l3_n204 +end + +def fun_l2_n221() + fun_l3_n647 +end + +def fun_l2_n222() + fun_l3_n277 +end + +def fun_l2_n223() + fun_l3_n687 +end + +def fun_l2_n224() + fun_l3_n438 +end + +def fun_l2_n225() + fun_l3_n634 +end + +def fun_l2_n226() + fun_l3_n826 +end + +def fun_l2_n227() + fun_l3_n702 +end + +def fun_l2_n228() + fun_l3_n541 +end + +def fun_l2_n229() + fun_l3_n741 +end + +def fun_l2_n230() + fun_l3_n886 +end + +def fun_l2_n231() + fun_l3_n243 +end + +def fun_l2_n232() + fun_l3_n313 +end + +def fun_l2_n233() + fun_l3_n499 +end + +def fun_l2_n234() + fun_l3_n100 +end + +def fun_l2_n235() + fun_l3_n958 +end + +def fun_l2_n236() + fun_l3_n192 +end + +def fun_l2_n237() + fun_l3_n529 +end + +def fun_l2_n238() + fun_l3_n761 +end + +def fun_l2_n239() + fun_l3_n558 +end + +def fun_l2_n240() + fun_l3_n58 +end + +def fun_l2_n241() + fun_l3_n65 +end + +def fun_l2_n242() + fun_l3_n685 +end + +def fun_l2_n243() + fun_l3_n418 +end + +def fun_l2_n244() + fun_l3_n206 +end + +def fun_l2_n245() + fun_l3_n147 +end + +def fun_l2_n246() + fun_l3_n98 +end + +def fun_l2_n247() + fun_l3_n104 +end + +def fun_l2_n248() + fun_l3_n336 +end + +def fun_l2_n249() + fun_l3_n406 +end + +def fun_l2_n250() + fun_l3_n835 +end + +def fun_l2_n251() + fun_l3_n611 +end + +def fun_l2_n252() + fun_l3_n890 +end + +def fun_l2_n253() + fun_l3_n272 +end + +def fun_l2_n254() + fun_l3_n962 +end + +def fun_l2_n255() + fun_l3_n960 +end + +def fun_l2_n256() + fun_l3_n675 +end + +def fun_l2_n257() + fun_l3_n161 +end + +def fun_l2_n258() + fun_l3_n509 +end + +def fun_l2_n259() + fun_l3_n36 +end + +def fun_l2_n260() + fun_l3_n381 +end + +def fun_l2_n261() + fun_l3_n721 +end + +def fun_l2_n262() + fun_l3_n807 +end + +def fun_l2_n263() + fun_l3_n424 +end + +def fun_l2_n264() + fun_l3_n733 +end + +def fun_l2_n265() + fun_l3_n417 +end + +def fun_l2_n266() + fun_l3_n630 +end + +def fun_l2_n267() + fun_l3_n733 +end + +def fun_l2_n268() + fun_l3_n797 +end + +def fun_l2_n269() + fun_l3_n446 +end + +def fun_l2_n270() + fun_l3_n877 +end + +def fun_l2_n271() + fun_l3_n64 +end + +def fun_l2_n272() + fun_l3_n553 +end + +def fun_l2_n273() + fun_l3_n369 +end + +def fun_l2_n274() + fun_l3_n261 +end + +def fun_l2_n275() + fun_l3_n244 +end + +def fun_l2_n276() + fun_l3_n544 +end + +def fun_l2_n277() + fun_l3_n779 +end + +def fun_l2_n278() + fun_l3_n864 +end + +def fun_l2_n279() + fun_l3_n235 +end + +def fun_l2_n280() + fun_l3_n343 +end + +def fun_l2_n281() + fun_l3_n601 +end + +def fun_l2_n282() + fun_l3_n925 +end + +def fun_l2_n283() + fun_l3_n822 +end + +def fun_l2_n284() + fun_l3_n675 +end + +def fun_l2_n285() + fun_l3_n791 +end + +def fun_l2_n286() + fun_l3_n359 +end + +def fun_l2_n287() + fun_l3_n596 +end + +def fun_l2_n288() + fun_l3_n153 +end + +def fun_l2_n289() + fun_l3_n420 +end + +def fun_l2_n290() + fun_l3_n464 +end + +def fun_l2_n291() + fun_l3_n393 +end + +def fun_l2_n292() + fun_l3_n614 +end + +def fun_l2_n293() + fun_l3_n449 +end + +def fun_l2_n294() + fun_l3_n561 +end + +def fun_l2_n295() + fun_l3_n119 +end + +def fun_l2_n296() + fun_l3_n82 +end + +def fun_l2_n297() + fun_l3_n932 +end + +def fun_l2_n298() + fun_l3_n505 +end + +def fun_l2_n299() + fun_l3_n664 +end + +def fun_l2_n300() + fun_l3_n222 +end + +def fun_l2_n301() + fun_l3_n428 +end + +def fun_l2_n302() + fun_l3_n975 +end + +def fun_l2_n303() + fun_l3_n481 +end + +def fun_l2_n304() + fun_l3_n263 +end + +def fun_l2_n305() + fun_l3_n816 +end + +def fun_l2_n306() + fun_l3_n58 +end + +def fun_l2_n307() + fun_l3_n89 +end + +def fun_l2_n308() + fun_l3_n509 +end + +def fun_l2_n309() + fun_l3_n162 +end + +def fun_l2_n310() + fun_l3_n222 +end + +def fun_l2_n311() + fun_l3_n999 +end + +def fun_l2_n312() + fun_l3_n26 +end + +def fun_l2_n313() + fun_l3_n857 +end + +def fun_l2_n314() + fun_l3_n485 +end + +def fun_l2_n315() + fun_l3_n935 +end + +def fun_l2_n316() + fun_l3_n159 +end + +def fun_l2_n317() + fun_l3_n987 +end + +def fun_l2_n318() + fun_l3_n122 +end + +def fun_l2_n319() + fun_l3_n675 +end + +def fun_l2_n320() + fun_l3_n88 +end + +def fun_l2_n321() + fun_l3_n84 +end + +def fun_l2_n322() + fun_l3_n17 +end + +def fun_l2_n323() + fun_l3_n859 +end + +def fun_l2_n324() + fun_l3_n340 +end + +def fun_l2_n325() + fun_l3_n122 +end + +def fun_l2_n326() + fun_l3_n675 +end + +def fun_l2_n327() + fun_l3_n502 +end + +def fun_l2_n328() + fun_l3_n56 +end + +def fun_l2_n329() + fun_l3_n398 +end + +def fun_l2_n330() + fun_l3_n985 +end + +def fun_l2_n331() + fun_l3_n117 +end + +def fun_l2_n332() + fun_l3_n264 +end + +def fun_l2_n333() + fun_l3_n664 +end + +def fun_l2_n334() + fun_l3_n958 +end + +def fun_l2_n335() + fun_l3_n495 +end + +def fun_l2_n336() + fun_l3_n794 +end + +def fun_l2_n337() + fun_l3_n95 +end + +def fun_l2_n338() + fun_l3_n202 +end + +def fun_l2_n339() + fun_l3_n510 +end + +def fun_l2_n340() + fun_l3_n919 +end + +def fun_l2_n341() + fun_l3_n602 +end + +def fun_l2_n342() + fun_l3_n750 +end + +def fun_l2_n343() + fun_l3_n122 +end + +def fun_l2_n344() + fun_l3_n358 +end + +def fun_l2_n345() + fun_l3_n539 +end + +def fun_l2_n346() + fun_l3_n67 +end + +def fun_l2_n347() + fun_l3_n881 +end + +def fun_l2_n348() + fun_l3_n257 +end + +def fun_l2_n349() + fun_l3_n987 +end + +def fun_l2_n350() + fun_l3_n482 +end + +def fun_l2_n351() + fun_l3_n803 +end + +def fun_l2_n352() + fun_l3_n172 +end + +def fun_l2_n353() + fun_l3_n826 +end + +def fun_l2_n354() + fun_l3_n977 +end + +def fun_l2_n355() + fun_l3_n976 +end + +def fun_l2_n356() + fun_l3_n970 +end + +def fun_l2_n357() + fun_l3_n904 +end + +def fun_l2_n358() + fun_l3_n735 +end + +def fun_l2_n359() + fun_l3_n146 +end + +def fun_l2_n360() + fun_l3_n810 +end + +def fun_l2_n361() + fun_l3_n591 +end + +def fun_l2_n362() + fun_l3_n882 +end + +def fun_l2_n363() + fun_l3_n980 +end + +def fun_l2_n364() + fun_l3_n594 +end + +def fun_l2_n365() + fun_l3_n431 +end + +def fun_l2_n366() + fun_l3_n225 +end + +def fun_l2_n367() + fun_l3_n11 +end + +def fun_l2_n368() + fun_l3_n283 +end + +def fun_l2_n369() + fun_l3_n476 +end + +def fun_l2_n370() + fun_l3_n382 +end + +def fun_l2_n371() + fun_l3_n422 +end + +def fun_l2_n372() + fun_l3_n272 +end + +def fun_l2_n373() + fun_l3_n911 +end + +def fun_l2_n374() + fun_l3_n282 +end + +def fun_l2_n375() + fun_l3_n388 +end + +def fun_l2_n376() + fun_l3_n928 +end + +def fun_l2_n377() + fun_l3_n784 +end + +def fun_l2_n378() + fun_l3_n817 +end + +def fun_l2_n379() + fun_l3_n799 +end + +def fun_l2_n380() + fun_l3_n538 +end + +def fun_l2_n381() + fun_l3_n24 +end + +def fun_l2_n382() + fun_l3_n726 +end + +def fun_l2_n383() + fun_l3_n213 +end + +def fun_l2_n384() + fun_l3_n15 +end + +def fun_l2_n385() + fun_l3_n915 +end + +def fun_l2_n386() + fun_l3_n357 +end + +def fun_l2_n387() + fun_l3_n343 +end + +def fun_l2_n388() + fun_l3_n258 +end + +def fun_l2_n389() + fun_l3_n396 +end + +def fun_l2_n390() + fun_l3_n478 +end + +def fun_l2_n391() + fun_l3_n122 +end + +def fun_l2_n392() + fun_l3_n925 +end + +def fun_l2_n393() + fun_l3_n6 +end + +def fun_l2_n394() + fun_l3_n251 +end + +def fun_l2_n395() + fun_l3_n21 +end + +def fun_l2_n396() + fun_l3_n781 +end + +def fun_l2_n397() + fun_l3_n765 +end + +def fun_l2_n398() + fun_l3_n574 +end + +def fun_l2_n399() + fun_l3_n347 +end + +def fun_l2_n400() + fun_l3_n409 +end + +def fun_l2_n401() + fun_l3_n343 +end + +def fun_l2_n402() + fun_l3_n580 +end + +def fun_l2_n403() + fun_l3_n878 +end + +def fun_l2_n404() + fun_l3_n150 +end + +def fun_l2_n405() + fun_l3_n900 +end + +def fun_l2_n406() + fun_l3_n19 +end + +def fun_l2_n407() + fun_l3_n671 +end + +def fun_l2_n408() + fun_l3_n714 +end + +def fun_l2_n409() + fun_l3_n865 +end + +def fun_l2_n410() + fun_l3_n634 +end + +def fun_l2_n411() + fun_l3_n780 +end + +def fun_l2_n412() + fun_l3_n404 +end + +def fun_l2_n413() + fun_l3_n506 +end + +def fun_l2_n414() + fun_l3_n503 +end + +def fun_l2_n415() + fun_l3_n120 +end + +def fun_l2_n416() + fun_l3_n603 +end + +def fun_l2_n417() + fun_l3_n263 +end + +def fun_l2_n418() + fun_l3_n142 +end + +def fun_l2_n419() + fun_l3_n174 +end + +def fun_l2_n420() + fun_l3_n474 +end + +def fun_l2_n421() + fun_l3_n980 +end + +def fun_l2_n422() + fun_l3_n302 +end + +def fun_l2_n423() + fun_l3_n850 +end + +def fun_l2_n424() + fun_l3_n395 +end + +def fun_l2_n425() + fun_l3_n49 +end + +def fun_l2_n426() + fun_l3_n732 +end + +def fun_l2_n427() + fun_l3_n473 +end + +def fun_l2_n428() + fun_l3_n906 +end + +def fun_l2_n429() + fun_l3_n120 +end + +def fun_l2_n430() + fun_l3_n818 +end + +def fun_l2_n431() + fun_l3_n177 +end + +def fun_l2_n432() + fun_l3_n47 +end + +def fun_l2_n433() + fun_l3_n423 +end + +def fun_l2_n434() + fun_l3_n435 +end + +def fun_l2_n435() + fun_l3_n748 +end + +def fun_l2_n436() + fun_l3_n953 +end + +def fun_l2_n437() + fun_l3_n78 +end + +def fun_l2_n438() + fun_l3_n184 +end + +def fun_l2_n439() + fun_l3_n533 +end + +def fun_l2_n440() + fun_l3_n184 +end + +def fun_l2_n441() + fun_l3_n698 +end + +def fun_l2_n442() + fun_l3_n752 +end + +def fun_l2_n443() + fun_l3_n448 +end + +def fun_l2_n444() + fun_l3_n307 +end + +def fun_l2_n445() + fun_l3_n333 +end + +def fun_l2_n446() + fun_l3_n237 +end + +def fun_l2_n447() + fun_l3_n550 +end + +def fun_l2_n448() + fun_l3_n951 +end + +def fun_l2_n449() + fun_l3_n341 +end + +def fun_l2_n450() + fun_l3_n188 +end + +def fun_l2_n451() + fun_l3_n505 +end + +def fun_l2_n452() + fun_l3_n779 +end + +def fun_l2_n453() + fun_l3_n368 +end + +def fun_l2_n454() + fun_l3_n191 +end + +def fun_l2_n455() + fun_l3_n952 +end + +def fun_l2_n456() + fun_l3_n472 +end + +def fun_l2_n457() + fun_l3_n294 +end + +def fun_l2_n458() + fun_l3_n280 +end + +def fun_l2_n459() + fun_l3_n794 +end + +def fun_l2_n460() + fun_l3_n780 +end + +def fun_l2_n461() + fun_l3_n527 +end + +def fun_l2_n462() + fun_l3_n129 +end + +def fun_l2_n463() + fun_l3_n365 +end + +def fun_l2_n464() + fun_l3_n898 +end + +def fun_l2_n465() + fun_l3_n932 +end + +def fun_l2_n466() + fun_l3_n616 +end + +def fun_l2_n467() + fun_l3_n828 +end + +def fun_l2_n468() + fun_l3_n660 +end + +def fun_l2_n469() + fun_l3_n255 +end + +def fun_l2_n470() + fun_l3_n845 +end + +def fun_l2_n471() + fun_l3_n347 +end + +def fun_l2_n472() + fun_l3_n154 +end + +def fun_l2_n473() + fun_l3_n349 +end + +def fun_l2_n474() + fun_l3_n276 +end + +def fun_l2_n475() + fun_l3_n962 +end + +def fun_l2_n476() + fun_l3_n195 +end + +def fun_l2_n477() + fun_l3_n648 +end + +def fun_l2_n478() + fun_l3_n692 +end + +def fun_l2_n479() + fun_l3_n294 +end + +def fun_l2_n480() + fun_l3_n144 +end + +def fun_l2_n481() + fun_l3_n702 +end + +def fun_l2_n482() + fun_l3_n110 +end + +def fun_l2_n483() + fun_l3_n169 +end + +def fun_l2_n484() + fun_l3_n140 +end + +def fun_l2_n485() + fun_l3_n614 +end + +def fun_l2_n486() + fun_l3_n309 +end + +def fun_l2_n487() + fun_l3_n792 +end + +def fun_l2_n488() + fun_l3_n465 +end + +def fun_l2_n489() + fun_l3_n892 +end + +def fun_l2_n490() + fun_l3_n205 +end + +def fun_l2_n491() + fun_l3_n267 +end + +def fun_l2_n492() + fun_l3_n743 +end + +def fun_l2_n493() + fun_l3_n669 +end + +def fun_l2_n494() + fun_l3_n882 +end + +def fun_l2_n495() + fun_l3_n654 +end + +def fun_l2_n496() + fun_l3_n885 +end + +def fun_l2_n497() + fun_l3_n955 +end + +def fun_l2_n498() + fun_l3_n251 +end + +def fun_l2_n499() + fun_l3_n521 +end + +def fun_l2_n500() + fun_l3_n484 +end + +def fun_l2_n501() + fun_l3_n525 +end + +def fun_l2_n502() + fun_l3_n493 +end + +def fun_l2_n503() + fun_l3_n161 +end + +def fun_l2_n504() + fun_l3_n447 +end + +def fun_l2_n505() + fun_l3_n339 +end + +def fun_l2_n506() + fun_l3_n946 +end + +def fun_l2_n507() + fun_l3_n564 +end + +def fun_l2_n508() + fun_l3_n586 +end + +def fun_l2_n509() + fun_l3_n345 +end + +def fun_l2_n510() + fun_l3_n814 +end + +def fun_l2_n511() + fun_l3_n946 +end + +def fun_l2_n512() + fun_l3_n629 +end + +def fun_l2_n513() + fun_l3_n726 +end + +def fun_l2_n514() + fun_l3_n91 +end + +def fun_l2_n515() + fun_l3_n393 +end + +def fun_l2_n516() + fun_l3_n620 +end + +def fun_l2_n517() + fun_l3_n907 +end + +def fun_l2_n518() + fun_l3_n911 +end + +def fun_l2_n519() + fun_l3_n361 +end + +def fun_l2_n520() + fun_l3_n420 +end + +def fun_l2_n521() + fun_l3_n479 +end + +def fun_l2_n522() + fun_l3_n686 +end + +def fun_l2_n523() + fun_l3_n888 +end + +def fun_l2_n524() + fun_l3_n141 +end + +def fun_l2_n525() + fun_l3_n830 +end + +def fun_l2_n526() + fun_l3_n681 +end + +def fun_l2_n527() + fun_l3_n58 +end + +def fun_l2_n528() + fun_l3_n835 +end + +def fun_l2_n529() + fun_l3_n390 +end + +def fun_l2_n530() + fun_l3_n930 +end + +def fun_l2_n531() + fun_l3_n569 +end + +def fun_l2_n532() + fun_l3_n943 +end + +def fun_l2_n533() + fun_l3_n888 +end + +def fun_l2_n534() + fun_l3_n220 +end + +def fun_l2_n535() + fun_l3_n809 +end + +def fun_l2_n536() + fun_l3_n382 +end + +def fun_l2_n537() + fun_l3_n356 +end + +def fun_l2_n538() + fun_l3_n912 +end + +def fun_l2_n539() + fun_l3_n151 +end + +def fun_l2_n540() + fun_l3_n740 +end + +def fun_l2_n541() + fun_l3_n925 +end + +def fun_l2_n542() + fun_l3_n776 +end + +def fun_l2_n543() + fun_l3_n4 +end + +def fun_l2_n544() + fun_l3_n549 +end + +def fun_l2_n545() + fun_l3_n220 +end + +def fun_l2_n546() + fun_l3_n932 +end + +def fun_l2_n547() + fun_l3_n267 +end + +def fun_l2_n548() + fun_l3_n646 +end + +def fun_l2_n549() + fun_l3_n217 +end + +def fun_l2_n550() + fun_l3_n217 +end + +def fun_l2_n551() + fun_l3_n197 +end + +def fun_l2_n552() + fun_l3_n419 +end + +def fun_l2_n553() + fun_l3_n232 +end + +def fun_l2_n554() + fun_l3_n327 +end + +def fun_l2_n555() + fun_l3_n201 +end + +def fun_l2_n556() + fun_l3_n567 +end + +def fun_l2_n557() + fun_l3_n870 +end + +def fun_l2_n558() + fun_l3_n222 +end + +def fun_l2_n559() + fun_l3_n792 +end + +def fun_l2_n560() + fun_l3_n157 +end + +def fun_l2_n561() + fun_l3_n870 +end + +def fun_l2_n562() + fun_l3_n564 +end + +def fun_l2_n563() + fun_l3_n571 +end + +def fun_l2_n564() + fun_l3_n211 +end + +def fun_l2_n565() + fun_l3_n657 +end + +def fun_l2_n566() + fun_l3_n869 +end + +def fun_l2_n567() + fun_l3_n288 +end + +def fun_l2_n568() + fun_l3_n736 +end + +def fun_l2_n569() + fun_l3_n273 +end + +def fun_l2_n570() + fun_l3_n194 +end + +def fun_l2_n571() + fun_l3_n435 +end + +def fun_l2_n572() + fun_l3_n775 +end + +def fun_l2_n573() + fun_l3_n342 +end + +def fun_l2_n574() + fun_l3_n843 +end + +def fun_l2_n575() + fun_l3_n585 +end + +def fun_l2_n576() + fun_l3_n518 +end + +def fun_l2_n577() + fun_l3_n524 +end + +def fun_l2_n578() + fun_l3_n457 +end + +def fun_l2_n579() + fun_l3_n905 +end + +def fun_l2_n580() + fun_l3_n346 +end + +def fun_l2_n581() + fun_l3_n412 +end + +def fun_l2_n582() + fun_l3_n970 +end + +def fun_l2_n583() + fun_l3_n648 +end + +def fun_l2_n584() + fun_l3_n870 +end + +def fun_l2_n585() + fun_l3_n783 +end + +def fun_l2_n586() + fun_l3_n856 +end + +def fun_l2_n587() + fun_l3_n708 +end + +def fun_l2_n588() + fun_l3_n473 +end + +def fun_l2_n589() + fun_l3_n277 +end + +def fun_l2_n590() + fun_l3_n112 +end + +def fun_l2_n591() + fun_l3_n785 +end + +def fun_l2_n592() + fun_l3_n283 +end + +def fun_l2_n593() + fun_l3_n720 +end + +def fun_l2_n594() + fun_l3_n195 +end + +def fun_l2_n595() + fun_l3_n923 +end + +def fun_l2_n596() + fun_l3_n306 +end + +def fun_l2_n597() + fun_l3_n108 +end + +def fun_l2_n598() + fun_l3_n615 +end + +def fun_l2_n599() + fun_l3_n135 +end + +def fun_l2_n600() + fun_l3_n710 +end + +def fun_l2_n601() + fun_l3_n722 +end + +def fun_l2_n602() + fun_l3_n943 +end + +def fun_l2_n603() + fun_l3_n626 +end + +def fun_l2_n604() + fun_l3_n702 +end + +def fun_l2_n605() + fun_l3_n812 +end + +def fun_l2_n606() + fun_l3_n551 +end + +def fun_l2_n607() + fun_l3_n497 +end + +def fun_l2_n608() + fun_l3_n123 +end + +def fun_l2_n609() + fun_l3_n302 +end + +def fun_l2_n610() + fun_l3_n850 +end + +def fun_l2_n611() + fun_l3_n327 +end + +def fun_l2_n612() + fun_l3_n529 +end + +def fun_l2_n613() + fun_l3_n441 +end + +def fun_l2_n614() + fun_l3_n26 +end + +def fun_l2_n615() + fun_l3_n275 +end + +def fun_l2_n616() + fun_l3_n211 +end + +def fun_l2_n617() + fun_l3_n253 +end + +def fun_l2_n618() + fun_l3_n767 +end + +def fun_l2_n619() + fun_l3_n601 +end + +def fun_l2_n620() + fun_l3_n350 +end + +def fun_l2_n621() + fun_l3_n407 +end + +def fun_l2_n622() + fun_l3_n12 +end + +def fun_l2_n623() + fun_l3_n378 +end + +def fun_l2_n624() + fun_l3_n159 +end + +def fun_l2_n625() + fun_l3_n521 +end + +def fun_l2_n626() + fun_l3_n657 +end + +def fun_l2_n627() + fun_l3_n997 +end + +def fun_l2_n628() + fun_l3_n504 +end + +def fun_l2_n629() + fun_l3_n177 +end + +def fun_l2_n630() + fun_l3_n352 +end + +def fun_l2_n631() + fun_l3_n579 +end + +def fun_l2_n632() + fun_l3_n607 +end + +def fun_l2_n633() + fun_l3_n430 +end + +def fun_l2_n634() + fun_l3_n437 +end + +def fun_l2_n635() + fun_l3_n495 +end + +def fun_l2_n636() + fun_l3_n247 +end + +def fun_l2_n637() + fun_l3_n68 +end + +def fun_l2_n638() + fun_l3_n815 +end + +def fun_l2_n639() + fun_l3_n477 +end + +def fun_l2_n640() + fun_l3_n894 +end + +def fun_l2_n641() + fun_l3_n804 +end + +def fun_l2_n642() + fun_l3_n198 +end + +def fun_l2_n643() + fun_l3_n676 +end + +def fun_l2_n644() + fun_l3_n306 +end + +def fun_l2_n645() + fun_l3_n545 +end + +def fun_l2_n646() + fun_l3_n519 +end + +def fun_l2_n647() + fun_l3_n328 +end + +def fun_l2_n648() + fun_l3_n654 +end + +def fun_l2_n649() + fun_l3_n879 +end + +def fun_l2_n650() + fun_l3_n224 +end + +def fun_l2_n651() + fun_l3_n826 +end + +def fun_l2_n652() + fun_l3_n976 +end + +def fun_l2_n653() + fun_l3_n287 +end + +def fun_l2_n654() + fun_l3_n471 +end + +def fun_l2_n655() + fun_l3_n738 +end + +def fun_l2_n656() + fun_l3_n545 +end + +def fun_l2_n657() + fun_l3_n819 +end + +def fun_l2_n658() + fun_l3_n866 +end + +def fun_l2_n659() + fun_l3_n215 +end + +def fun_l2_n660() + fun_l3_n656 +end + +def fun_l2_n661() + fun_l3_n519 +end + +def fun_l2_n662() + fun_l3_n812 +end + +def fun_l2_n663() + fun_l3_n241 +end + +def fun_l2_n664() + fun_l3_n245 +end + +def fun_l2_n665() + fun_l3_n60 +end + +def fun_l2_n666() + fun_l3_n516 +end + +def fun_l2_n667() + fun_l3_n264 +end + +def fun_l2_n668() + fun_l3_n254 +end + +def fun_l2_n669() + fun_l3_n952 +end + +def fun_l2_n670() + fun_l3_n928 +end + +def fun_l2_n671() + fun_l3_n718 +end + +def fun_l2_n672() + fun_l3_n937 +end + +def fun_l2_n673() + fun_l3_n549 +end + +def fun_l2_n674() + fun_l3_n138 +end + +def fun_l2_n675() + fun_l3_n441 +end + +def fun_l2_n676() + fun_l3_n641 +end + +def fun_l2_n677() + fun_l3_n611 +end + +def fun_l2_n678() + fun_l3_n711 +end + +def fun_l2_n679() + fun_l3_n60 +end + +def fun_l2_n680() + fun_l3_n894 +end + +def fun_l2_n681() + fun_l3_n957 +end + +def fun_l2_n682() + fun_l3_n516 +end + +def fun_l2_n683() + fun_l3_n348 +end + +def fun_l2_n684() + fun_l3_n600 +end + +def fun_l2_n685() + fun_l3_n955 +end + +def fun_l2_n686() + fun_l3_n842 +end + +def fun_l2_n687() + fun_l3_n126 +end + +def fun_l2_n688() + fun_l3_n739 +end + +def fun_l2_n689() + fun_l3_n435 +end + +def fun_l2_n690() + fun_l3_n445 +end + +def fun_l2_n691() + fun_l3_n973 +end + +def fun_l2_n692() + fun_l3_n54 +end + +def fun_l2_n693() + fun_l3_n629 +end + +def fun_l2_n694() + fun_l3_n83 +end + +def fun_l2_n695() + fun_l3_n887 +end + +def fun_l2_n696() + fun_l3_n552 +end + +def fun_l2_n697() + fun_l3_n263 +end + +def fun_l2_n698() + fun_l3_n532 +end + +def fun_l2_n699() + fun_l3_n462 +end + +def fun_l2_n700() + fun_l3_n319 +end + +def fun_l2_n701() + fun_l3_n464 +end + +def fun_l2_n702() + fun_l3_n340 +end + +def fun_l2_n703() + fun_l3_n188 +end + +def fun_l2_n704() + fun_l3_n157 +end + +def fun_l2_n705() + fun_l3_n345 +end + +def fun_l2_n706() + fun_l3_n637 +end + +def fun_l2_n707() + fun_l3_n157 +end + +def fun_l2_n708() + fun_l3_n270 +end + +def fun_l2_n709() + fun_l3_n13 +end + +def fun_l2_n710() + fun_l3_n360 +end + +def fun_l2_n711() + fun_l3_n890 +end + +def fun_l2_n712() + fun_l3_n539 +end + +def fun_l2_n713() + fun_l3_n582 +end + +def fun_l2_n714() + fun_l3_n466 +end + +def fun_l2_n715() + fun_l3_n623 +end + +def fun_l2_n716() + fun_l3_n995 +end + +def fun_l2_n717() + fun_l3_n810 +end + +def fun_l2_n718() + fun_l3_n95 +end + +def fun_l2_n719() + fun_l3_n103 +end + +def fun_l2_n720() + fun_l3_n755 +end + +def fun_l2_n721() + fun_l3_n858 +end + +def fun_l2_n722() + fun_l3_n519 +end + +def fun_l2_n723() + fun_l3_n489 +end + +def fun_l2_n724() + fun_l3_n578 +end + +def fun_l2_n725() + fun_l3_n176 +end + +def fun_l2_n726() + fun_l3_n58 +end + +def fun_l2_n727() + fun_l3_n817 +end + +def fun_l2_n728() + fun_l3_n612 +end + +def fun_l2_n729() + fun_l3_n510 +end + +def fun_l2_n730() + fun_l3_n934 +end + +def fun_l2_n731() + fun_l3_n691 +end + +def fun_l2_n732() + fun_l3_n697 +end + +def fun_l2_n733() + fun_l3_n667 +end + +def fun_l2_n734() + fun_l3_n49 +end + +def fun_l2_n735() + fun_l3_n113 +end + +def fun_l2_n736() + fun_l3_n157 +end + +def fun_l2_n737() + fun_l3_n756 +end + +def fun_l2_n738() + fun_l3_n888 +end + +def fun_l2_n739() + fun_l3_n847 +end + +def fun_l2_n740() + fun_l3_n693 +end + +def fun_l2_n741() + fun_l3_n116 +end + +def fun_l2_n742() + fun_l3_n95 +end + +def fun_l2_n743() + fun_l3_n662 +end + +def fun_l2_n744() + fun_l3_n744 +end + +def fun_l2_n745() + fun_l3_n800 +end + +def fun_l2_n746() + fun_l3_n732 +end + +def fun_l2_n747() + fun_l3_n278 +end + +def fun_l2_n748() + fun_l3_n441 +end + +def fun_l2_n749() + fun_l3_n838 +end + +def fun_l2_n750() + fun_l3_n616 +end + +def fun_l2_n751() + fun_l3_n438 +end + +def fun_l2_n752() + fun_l3_n271 +end + +def fun_l2_n753() + fun_l3_n527 +end + +def fun_l2_n754() + fun_l3_n568 +end + +def fun_l2_n755() + fun_l3_n584 +end + +def fun_l2_n756() + fun_l3_n514 +end + +def fun_l2_n757() + fun_l3_n599 +end + +def fun_l2_n758() + fun_l3_n878 +end + +def fun_l2_n759() + fun_l3_n314 +end + +def fun_l2_n760() + fun_l3_n277 +end + +def fun_l2_n761() + fun_l3_n296 +end + +def fun_l2_n762() + fun_l3_n729 +end + +def fun_l2_n763() + fun_l3_n192 +end + +def fun_l2_n764() + fun_l3_n549 +end + +def fun_l2_n765() + fun_l3_n304 +end + +def fun_l2_n766() + fun_l3_n133 +end + +def fun_l2_n767() + fun_l3_n678 +end + +def fun_l2_n768() + fun_l3_n608 +end + +def fun_l2_n769() + fun_l3_n830 +end + +def fun_l2_n770() + fun_l3_n419 +end + +def fun_l2_n771() + fun_l3_n174 +end + +def fun_l2_n772() + fun_l3_n806 +end + +def fun_l2_n773() + fun_l3_n257 +end + +def fun_l2_n774() + fun_l3_n203 +end + +def fun_l2_n775() + fun_l3_n572 +end + +def fun_l2_n776() + fun_l3_n665 +end + +def fun_l2_n777() + fun_l3_n417 +end + +def fun_l2_n778() + fun_l3_n44 +end + +def fun_l2_n779() + fun_l3_n202 +end + +def fun_l2_n780() + fun_l3_n343 +end + +def fun_l2_n781() + fun_l3_n343 +end + +def fun_l2_n782() + fun_l3_n57 +end + +def fun_l2_n783() + fun_l3_n836 +end + +def fun_l2_n784() + fun_l3_n634 +end + +def fun_l2_n785() + fun_l3_n788 +end + +def fun_l2_n786() + fun_l3_n541 +end + +def fun_l2_n787() + fun_l3_n906 +end + +def fun_l2_n788() + fun_l3_n12 +end + +def fun_l2_n789() + fun_l3_n682 +end + +def fun_l2_n790() + fun_l3_n80 +end + +def fun_l2_n791() + fun_l3_n594 +end + +def fun_l2_n792() + fun_l3_n120 +end + +def fun_l2_n793() + fun_l3_n551 +end + +def fun_l2_n794() + fun_l3_n164 +end + +def fun_l2_n795() + fun_l3_n817 +end + +def fun_l2_n796() + fun_l3_n611 +end + +def fun_l2_n797() + fun_l3_n878 +end + +def fun_l2_n798() + fun_l3_n235 +end + +def fun_l2_n799() + fun_l3_n210 +end + +def fun_l2_n800() + fun_l3_n343 +end + +def fun_l2_n801() + fun_l3_n445 +end + +def fun_l2_n802() + fun_l3_n549 +end + +def fun_l2_n803() + fun_l3_n992 +end + +def fun_l2_n804() + fun_l3_n751 +end + +def fun_l2_n805() + fun_l3_n514 +end + +def fun_l2_n806() + fun_l3_n593 +end + +def fun_l2_n807() + fun_l3_n876 +end + +def fun_l2_n808() + fun_l3_n612 +end + +def fun_l2_n809() + fun_l3_n184 +end + +def fun_l2_n810() + fun_l3_n34 +end + +def fun_l2_n811() + fun_l3_n703 +end + +def fun_l2_n812() + fun_l3_n296 +end + +def fun_l2_n813() + fun_l3_n815 +end + +def fun_l2_n814() + fun_l3_n417 +end + +def fun_l2_n815() + fun_l3_n230 +end + +def fun_l2_n816() + fun_l3_n140 +end + +def fun_l2_n817() + fun_l3_n772 +end + +def fun_l2_n818() + fun_l3_n671 +end + +def fun_l2_n819() + fun_l3_n670 +end + +def fun_l2_n820() + fun_l3_n286 +end + +def fun_l2_n821() + fun_l3_n406 +end + +def fun_l2_n822() + fun_l3_n757 +end + +def fun_l2_n823() + fun_l3_n995 +end + +def fun_l2_n824() + fun_l3_n816 +end + +def fun_l2_n825() + fun_l3_n624 +end + +def fun_l2_n826() + fun_l3_n625 +end + +def fun_l2_n827() + fun_l3_n559 +end + +def fun_l2_n828() + fun_l3_n224 +end + +def fun_l2_n829() + fun_l3_n437 +end + +def fun_l2_n830() + fun_l3_n745 +end + +def fun_l2_n831() + fun_l3_n289 +end + +def fun_l2_n832() + fun_l3_n555 +end + +def fun_l2_n833() + fun_l3_n477 +end + +def fun_l2_n834() + fun_l3_n545 +end + +def fun_l2_n835() + fun_l3_n87 +end + +def fun_l2_n836() + fun_l3_n100 +end + +def fun_l2_n837() + fun_l3_n796 +end + +def fun_l2_n838() + fun_l3_n166 +end + +def fun_l2_n839() + fun_l3_n91 +end + +def fun_l2_n840() + fun_l3_n325 +end + +def fun_l2_n841() + fun_l3_n717 +end + +def fun_l2_n842() + fun_l3_n522 +end + +def fun_l2_n843() + fun_l3_n560 +end + +def fun_l2_n844() + fun_l3_n811 +end + +def fun_l2_n845() + fun_l3_n451 +end + +def fun_l2_n846() + fun_l3_n45 +end + +def fun_l2_n847() + fun_l3_n410 +end + +def fun_l2_n848() + fun_l3_n976 +end + +def fun_l2_n849() + fun_l3_n873 +end + +def fun_l2_n850() + fun_l3_n302 +end + +def fun_l2_n851() + fun_l3_n346 +end + +def fun_l2_n852() + fun_l3_n314 +end + +def fun_l2_n853() + fun_l3_n829 +end + +def fun_l2_n854() + fun_l3_n259 +end + +def fun_l2_n855() + fun_l3_n799 +end + +def fun_l2_n856() + fun_l3_n451 +end + +def fun_l2_n857() + fun_l3_n154 +end + +def fun_l2_n858() + fun_l3_n867 +end + +def fun_l2_n859() + fun_l3_n806 +end + +def fun_l2_n860() + fun_l3_n138 +end + +def fun_l2_n861() + fun_l3_n508 +end + +def fun_l2_n862() + fun_l3_n627 +end + +def fun_l2_n863() + fun_l3_n931 +end + +def fun_l2_n864() + fun_l3_n95 +end + +def fun_l2_n865() + fun_l3_n533 +end + +def fun_l2_n866() + fun_l3_n425 +end + +def fun_l2_n867() + fun_l3_n996 +end + +def fun_l2_n868() + fun_l3_n331 +end + +def fun_l2_n869() + fun_l3_n126 +end + +def fun_l2_n870() + fun_l3_n848 +end + +def fun_l2_n871() + fun_l3_n174 +end + +def fun_l2_n872() + fun_l3_n867 +end + +def fun_l2_n873() + fun_l3_n800 +end + +def fun_l2_n874() + fun_l3_n526 +end + +def fun_l2_n875() + fun_l3_n250 +end + +def fun_l2_n876() + fun_l3_n896 +end + +def fun_l2_n877() + fun_l3_n229 +end + +def fun_l2_n878() + fun_l3_n290 +end + +def fun_l2_n879() + fun_l3_n130 +end + +def fun_l2_n880() + fun_l3_n437 +end + +def fun_l2_n881() + fun_l3_n654 +end + +def fun_l2_n882() + fun_l3_n93 +end + +def fun_l2_n883() + fun_l3_n632 +end + +def fun_l2_n884() + fun_l3_n772 +end + +def fun_l2_n885() + fun_l3_n597 +end + +def fun_l2_n886() + fun_l3_n668 +end + +def fun_l2_n887() + fun_l3_n969 +end + +def fun_l2_n888() + fun_l3_n908 +end + +def fun_l2_n889() + fun_l3_n10 +end + +def fun_l2_n890() + fun_l3_n676 +end + +def fun_l2_n891() + fun_l3_n729 +end + +def fun_l2_n892() + fun_l3_n659 +end + +def fun_l2_n893() + fun_l3_n121 +end + +def fun_l2_n894() + fun_l3_n543 +end + +def fun_l2_n895() + fun_l3_n931 +end + +def fun_l2_n896() + fun_l3_n64 +end + +def fun_l2_n897() + fun_l3_n500 +end + +def fun_l2_n898() + fun_l3_n664 +end + +def fun_l2_n899() + fun_l3_n929 +end + +def fun_l2_n900() + fun_l3_n772 +end + +def fun_l2_n901() + fun_l3_n309 +end + +def fun_l2_n902() + fun_l3_n284 +end + +def fun_l2_n903() + fun_l3_n304 +end + +def fun_l2_n904() + fun_l3_n18 +end + +def fun_l2_n905() + fun_l3_n715 +end + +def fun_l2_n906() + fun_l3_n469 +end + +def fun_l2_n907() + fun_l3_n524 +end + +def fun_l2_n908() + fun_l3_n476 +end + +def fun_l2_n909() + fun_l3_n90 +end + +def fun_l2_n910() + fun_l3_n471 +end + +def fun_l2_n911() + fun_l3_n885 +end + +def fun_l2_n912() + fun_l3_n696 +end + +def fun_l2_n913() + fun_l3_n393 +end + +def fun_l2_n914() + fun_l3_n987 +end + +def fun_l2_n915() + fun_l3_n830 +end + +def fun_l2_n916() + fun_l3_n684 +end + +def fun_l2_n917() + fun_l3_n379 +end + +def fun_l2_n918() + fun_l3_n237 +end + +def fun_l2_n919() + fun_l3_n115 +end + +def fun_l2_n920() + fun_l3_n499 +end + +def fun_l2_n921() + fun_l3_n88 +end + +def fun_l2_n922() + fun_l3_n563 +end + +def fun_l2_n923() + fun_l3_n280 +end + +def fun_l2_n924() + fun_l3_n400 +end + +def fun_l2_n925() + fun_l3_n750 +end + +def fun_l2_n926() + fun_l3_n429 +end + +def fun_l2_n927() + fun_l3_n669 +end + +def fun_l2_n928() + fun_l3_n275 +end + +def fun_l2_n929() + fun_l3_n468 +end + +def fun_l2_n930() + fun_l3_n617 +end + +def fun_l2_n931() + fun_l3_n291 +end + +def fun_l2_n932() + fun_l3_n870 +end + +def fun_l2_n933() + fun_l3_n169 +end + +def fun_l2_n934() + fun_l3_n603 +end + +def fun_l2_n935() + fun_l3_n669 +end + +def fun_l2_n936() + fun_l3_n738 +end + +def fun_l2_n937() + fun_l3_n417 +end + +def fun_l2_n938() + fun_l3_n339 +end + +def fun_l2_n939() + fun_l3_n660 +end + +def fun_l2_n940() + fun_l3_n253 +end + +def fun_l2_n941() + fun_l3_n598 +end + +def fun_l2_n942() + fun_l3_n369 +end + +def fun_l2_n943() + fun_l3_n453 +end + +def fun_l2_n944() + fun_l3_n535 +end + +def fun_l2_n945() + fun_l3_n492 +end + +def fun_l2_n946() + fun_l3_n950 +end + +def fun_l2_n947() + fun_l3_n939 +end + +def fun_l2_n948() + fun_l3_n607 +end + +def fun_l2_n949() + fun_l3_n440 +end + +def fun_l2_n950() + fun_l3_n615 +end + +def fun_l2_n951() + fun_l3_n690 +end + +def fun_l2_n952() + fun_l3_n205 +end + +def fun_l2_n953() + fun_l3_n831 +end + +def fun_l2_n954() + fun_l3_n56 +end + +def fun_l2_n955() + fun_l3_n695 +end + +def fun_l2_n956() + fun_l3_n358 +end + +def fun_l2_n957() + fun_l3_n2 +end + +def fun_l2_n958() + fun_l3_n663 +end + +def fun_l2_n959() + fun_l3_n829 +end + +def fun_l2_n960() + fun_l3_n627 +end + +def fun_l2_n961() + fun_l3_n43 +end + +def fun_l2_n962() + fun_l3_n293 +end + +def fun_l2_n963() + fun_l3_n982 +end + +def fun_l2_n964() + fun_l3_n472 +end + +def fun_l2_n965() + fun_l3_n703 +end + +def fun_l2_n966() + fun_l3_n884 +end + +def fun_l2_n967() + fun_l3_n395 +end + +def fun_l2_n968() + fun_l3_n398 +end + +def fun_l2_n969() + fun_l3_n251 +end + +def fun_l2_n970() + fun_l3_n52 +end + +def fun_l2_n971() + fun_l3_n263 +end + +def fun_l2_n972() + fun_l3_n172 +end + +def fun_l2_n973() + fun_l3_n334 +end + +def fun_l2_n974() + fun_l3_n552 +end + +def fun_l2_n975() + fun_l3_n898 +end + +def fun_l2_n976() + fun_l3_n55 +end + +def fun_l2_n977() + fun_l3_n556 +end + +def fun_l2_n978() + fun_l3_n852 +end + +def fun_l2_n979() + fun_l3_n681 +end + +def fun_l2_n980() + fun_l3_n470 +end + +def fun_l2_n981() + fun_l3_n807 +end + +def fun_l2_n982() + fun_l3_n411 +end + +def fun_l2_n983() + fun_l3_n251 +end + +def fun_l2_n984() + fun_l3_n302 +end + +def fun_l2_n985() + fun_l3_n598 +end + +def fun_l2_n986() + fun_l3_n897 +end + +def fun_l2_n987() + fun_l3_n449 +end + +def fun_l2_n988() + fun_l3_n178 +end + +def fun_l2_n989() + fun_l3_n208 +end + +def fun_l2_n990() + fun_l3_n287 +end + +def fun_l2_n991() + fun_l3_n237 +end + +def fun_l2_n992() + fun_l3_n56 +end + +def fun_l2_n993() + fun_l3_n66 +end + +def fun_l2_n994() + fun_l3_n838 +end + +def fun_l2_n995() + fun_l3_n726 +end + +def fun_l2_n996() + fun_l3_n758 +end + +def fun_l2_n997() + fun_l3_n850 +end + +def fun_l2_n998() + fun_l3_n132 +end + +def fun_l2_n999() + fun_l3_n477 +end + +def fun_l3_n0() + fun_l4_n984 +end + +def fun_l3_n1() + fun_l4_n136 +end + +def fun_l3_n2() + fun_l4_n494 +end + +def fun_l3_n3() + fun_l4_n267 +end + +def fun_l3_n4() + fun_l4_n305 +end + +def fun_l3_n5() + fun_l4_n646 +end + +def fun_l3_n6() + fun_l4_n144 +end + +def fun_l3_n7() + fun_l4_n341 +end + +def fun_l3_n8() + fun_l4_n142 +end + +def fun_l3_n9() + fun_l4_n382 +end + +def fun_l3_n10() + fun_l4_n726 +end + +def fun_l3_n11() + fun_l4_n23 +end + +def fun_l3_n12() + fun_l4_n911 +end + +def fun_l3_n13() + fun_l4_n221 +end + +def fun_l3_n14() + fun_l4_n554 +end + +def fun_l3_n15() + fun_l4_n602 +end + +def fun_l3_n16() + fun_l4_n893 +end + +def fun_l3_n17() + fun_l4_n943 +end + +def fun_l3_n18() + fun_l4_n523 +end + +def fun_l3_n19() + fun_l4_n896 +end + +def fun_l3_n20() + fun_l4_n539 +end + +def fun_l3_n21() + fun_l4_n333 +end + +def fun_l3_n22() + fun_l4_n230 +end + +def fun_l3_n23() + fun_l4_n256 +end + +def fun_l3_n24() + fun_l4_n278 +end + +def fun_l3_n25() + fun_l4_n699 +end + +def fun_l3_n26() + fun_l4_n584 +end + +def fun_l3_n27() + fun_l4_n259 +end + +def fun_l3_n28() + fun_l4_n993 +end + +def fun_l3_n29() + fun_l4_n183 +end + +def fun_l3_n30() + fun_l4_n249 +end + +def fun_l3_n31() + fun_l4_n253 +end + +def fun_l3_n32() + fun_l4_n507 +end + +def fun_l3_n33() + fun_l4_n507 +end + +def fun_l3_n34() + fun_l4_n142 +end + +def fun_l3_n35() + fun_l4_n392 +end + +def fun_l3_n36() + fun_l4_n962 +end + +def fun_l3_n37() + fun_l4_n799 +end + +def fun_l3_n38() + fun_l4_n110 +end + +def fun_l3_n39() + fun_l4_n623 +end + +def fun_l3_n40() + fun_l4_n508 +end + +def fun_l3_n41() + fun_l4_n726 +end + +def fun_l3_n42() + fun_l4_n282 +end + +def fun_l3_n43() + fun_l4_n942 +end + +def fun_l3_n44() + fun_l4_n711 +end + +def fun_l3_n45() + fun_l4_n926 +end + +def fun_l3_n46() + fun_l4_n793 +end + +def fun_l3_n47() + fun_l4_n658 +end + +def fun_l3_n48() + fun_l4_n802 +end + +def fun_l3_n49() + fun_l4_n499 +end + +def fun_l3_n50() + fun_l4_n648 +end + +def fun_l3_n51() + fun_l4_n465 +end + +def fun_l3_n52() + fun_l4_n460 +end + +def fun_l3_n53() + fun_l4_n904 +end + +def fun_l3_n54() + fun_l4_n939 +end + +def fun_l3_n55() + fun_l4_n306 +end + +def fun_l3_n56() + fun_l4_n235 +end + +def fun_l3_n57() + fun_l4_n783 +end + +def fun_l3_n58() + fun_l4_n992 +end + +def fun_l3_n59() + fun_l4_n196 +end + +def fun_l3_n60() + fun_l4_n637 +end + +def fun_l3_n61() + fun_l4_n512 +end + +def fun_l3_n62() + fun_l4_n480 +end + +def fun_l3_n63() + fun_l4_n31 +end + +def fun_l3_n64() + fun_l4_n277 +end + +def fun_l3_n65() + fun_l4_n814 +end + +def fun_l3_n66() + fun_l4_n170 +end + +def fun_l3_n67() + fun_l4_n604 +end + +def fun_l3_n68() + fun_l4_n794 +end + +def fun_l3_n69() + fun_l4_n530 +end + +def fun_l3_n70() + fun_l4_n291 +end + +def fun_l3_n71() + fun_l4_n146 +end + +def fun_l3_n72() + fun_l4_n588 +end + +def fun_l3_n73() + fun_l4_n624 +end + +def fun_l3_n74() + fun_l4_n210 +end + +def fun_l3_n75() + fun_l4_n924 +end + +def fun_l3_n76() + fun_l4_n77 +end + +def fun_l3_n77() + fun_l4_n727 +end + +def fun_l3_n78() + fun_l4_n840 +end + +def fun_l3_n79() + fun_l4_n257 +end + +def fun_l3_n80() + fun_l4_n654 +end + +def fun_l3_n81() + fun_l4_n498 +end + +def fun_l3_n82() + fun_l4_n445 +end + +def fun_l3_n83() + fun_l4_n820 +end + +def fun_l3_n84() + fun_l4_n376 +end + +def fun_l3_n85() + fun_l4_n702 +end + +def fun_l3_n86() + fun_l4_n22 +end + +def fun_l3_n87() + fun_l4_n278 +end + +def fun_l3_n88() + fun_l4_n399 +end + +def fun_l3_n89() + fun_l4_n166 +end + +def fun_l3_n90() + fun_l4_n461 +end + +def fun_l3_n91() + fun_l4_n992 +end + +def fun_l3_n92() + fun_l4_n207 +end + +def fun_l3_n93() + fun_l4_n915 +end + +def fun_l3_n94() + fun_l4_n852 +end + +def fun_l3_n95() + fun_l4_n591 +end + +def fun_l3_n96() + fun_l4_n74 +end + +def fun_l3_n97() + fun_l4_n735 +end + +def fun_l3_n98() + fun_l4_n863 +end + +def fun_l3_n99() + fun_l4_n692 +end + +def fun_l3_n100() + fun_l4_n633 +end + +def fun_l3_n101() + fun_l4_n618 +end + +def fun_l3_n102() + fun_l4_n306 +end + +def fun_l3_n103() + fun_l4_n620 +end + +def fun_l3_n104() + fun_l4_n981 +end + +def fun_l3_n105() + fun_l4_n763 +end + +def fun_l3_n106() + fun_l4_n727 +end + +def fun_l3_n107() + fun_l4_n173 +end + +def fun_l3_n108() + fun_l4_n645 +end + +def fun_l3_n109() + fun_l4_n333 +end + +def fun_l3_n110() + fun_l4_n847 +end + +def fun_l3_n111() + fun_l4_n905 +end + +def fun_l3_n112() + fun_l4_n753 +end + +def fun_l3_n113() + fun_l4_n294 +end + +def fun_l3_n114() + fun_l4_n891 +end + +def fun_l3_n115() + fun_l4_n495 +end + +def fun_l3_n116() + fun_l4_n683 +end + +def fun_l3_n117() + fun_l4_n925 +end + +def fun_l3_n118() + fun_l4_n630 +end + +def fun_l3_n119() + fun_l4_n548 +end + +def fun_l3_n120() + fun_l4_n767 +end + +def fun_l3_n121() + fun_l4_n623 +end + +def fun_l3_n122() + fun_l4_n0 +end + +def fun_l3_n123() + fun_l4_n849 +end + +def fun_l3_n124() + fun_l4_n643 +end + +def fun_l3_n125() + fun_l4_n559 +end + +def fun_l3_n126() + fun_l4_n533 +end + +def fun_l3_n127() + fun_l4_n287 +end + +def fun_l3_n128() + fun_l4_n146 +end + +def fun_l3_n129() + fun_l4_n636 +end + +def fun_l3_n130() + fun_l4_n914 +end + +def fun_l3_n131() + fun_l4_n274 +end + +def fun_l3_n132() + fun_l4_n60 +end + +def fun_l3_n133() + fun_l4_n858 +end + +def fun_l3_n134() + fun_l4_n334 +end + +def fun_l3_n135() + fun_l4_n892 +end + +def fun_l3_n136() + fun_l4_n81 +end + +def fun_l3_n137() + fun_l4_n567 +end + +def fun_l3_n138() + fun_l4_n456 +end + +def fun_l3_n139() + fun_l4_n625 +end + +def fun_l3_n140() + fun_l4_n690 +end + +def fun_l3_n141() + fun_l4_n919 +end + +def fun_l3_n142() + fun_l4_n504 +end + +def fun_l3_n143() + fun_l4_n986 +end + +def fun_l3_n144() + fun_l4_n99 +end + +def fun_l3_n145() + fun_l4_n312 +end + +def fun_l3_n146() + fun_l4_n36 +end + +def fun_l3_n147() + fun_l4_n3 +end + +def fun_l3_n148() + fun_l4_n328 +end + +def fun_l3_n149() + fun_l4_n978 +end + +def fun_l3_n150() + fun_l4_n474 +end + +def fun_l3_n151() + fun_l4_n985 +end + +def fun_l3_n152() + fun_l4_n809 +end + +def fun_l3_n153() + fun_l4_n379 +end + +def fun_l3_n154() + fun_l4_n589 +end + +def fun_l3_n155() + fun_l4_n625 +end + +def fun_l3_n156() + fun_l4_n937 +end + +def fun_l3_n157() + fun_l4_n774 +end + +def fun_l3_n158() + fun_l4_n465 +end + +def fun_l3_n159() + fun_l4_n315 +end + +def fun_l3_n160() + fun_l4_n733 +end + +def fun_l3_n161() + fun_l4_n572 +end + +def fun_l3_n162() + fun_l4_n794 +end + +def fun_l3_n163() + fun_l4_n76 +end + +def fun_l3_n164() + fun_l4_n550 +end + +def fun_l3_n165() + fun_l4_n913 +end + +def fun_l3_n166() + fun_l4_n553 +end + +def fun_l3_n167() + fun_l4_n383 +end + +def fun_l3_n168() + fun_l4_n118 +end + +def fun_l3_n169() + fun_l4_n561 +end + +def fun_l3_n170() + fun_l4_n517 +end + +def fun_l3_n171() + fun_l4_n680 +end + +def fun_l3_n172() + fun_l4_n466 +end + +def fun_l3_n173() + fun_l4_n629 +end + +def fun_l3_n174() + fun_l4_n469 +end + +def fun_l3_n175() + fun_l4_n731 +end + +def fun_l3_n176() + fun_l4_n579 +end + +def fun_l3_n177() + fun_l4_n574 +end + +def fun_l3_n178() + fun_l4_n936 +end + +def fun_l3_n179() + fun_l4_n405 +end + +def fun_l3_n180() + fun_l4_n667 +end + +def fun_l3_n181() + fun_l4_n369 +end + +def fun_l3_n182() + fun_l4_n852 +end + +def fun_l3_n183() + fun_l4_n861 +end + +def fun_l3_n184() + fun_l4_n425 +end + +def fun_l3_n185() + fun_l4_n4 +end + +def fun_l3_n186() + fun_l4_n28 +end + +def fun_l3_n187() + fun_l4_n470 +end + +def fun_l3_n188() + fun_l4_n568 +end + +def fun_l3_n189() + fun_l4_n83 +end + +def fun_l3_n190() + fun_l4_n981 +end + +def fun_l3_n191() + fun_l4_n526 +end + +def fun_l3_n192() + fun_l4_n496 +end + +def fun_l3_n193() + fun_l4_n954 +end + +def fun_l3_n194() + fun_l4_n340 +end + +def fun_l3_n195() + fun_l4_n343 +end + +def fun_l3_n196() + fun_l4_n964 +end + +def fun_l3_n197() + fun_l4_n58 +end + +def fun_l3_n198() + fun_l4_n317 +end + +def fun_l3_n199() + fun_l4_n255 +end + +def fun_l3_n200() + fun_l4_n546 +end + +def fun_l3_n201() + fun_l4_n933 +end + +def fun_l3_n202() + fun_l4_n387 +end + +def fun_l3_n203() + fun_l4_n32 +end + +def fun_l3_n204() + fun_l4_n514 +end + +def fun_l3_n205() + fun_l4_n175 +end + +def fun_l3_n206() + fun_l4_n813 +end + +def fun_l3_n207() + fun_l4_n881 +end + +def fun_l3_n208() + fun_l4_n52 +end + +def fun_l3_n209() + fun_l4_n839 +end + +def fun_l3_n210() + fun_l4_n919 +end + +def fun_l3_n211() + fun_l4_n208 +end + +def fun_l3_n212() + fun_l4_n111 +end + +def fun_l3_n213() + fun_l4_n878 +end + +def fun_l3_n214() + fun_l4_n110 +end + +def fun_l3_n215() + fun_l4_n701 +end + +def fun_l3_n216() + fun_l4_n769 +end + +def fun_l3_n217() + fun_l4_n487 +end + +def fun_l3_n218() + fun_l4_n940 +end + +def fun_l3_n219() + fun_l4_n427 +end + +def fun_l3_n220() + fun_l4_n731 +end + +def fun_l3_n221() + fun_l4_n92 +end + +def fun_l3_n222() + fun_l4_n246 +end + +def fun_l3_n223() + fun_l4_n574 +end + +def fun_l3_n224() + fun_l4_n297 +end + +def fun_l3_n225() + fun_l4_n48 +end + +def fun_l3_n226() + fun_l4_n433 +end + +def fun_l3_n227() + fun_l4_n628 +end + +def fun_l3_n228() + fun_l4_n426 +end + +def fun_l3_n229() + fun_l4_n22 +end + +def fun_l3_n230() + fun_l4_n878 +end + +def fun_l3_n231() + fun_l4_n905 +end + +def fun_l3_n232() + fun_l4_n222 +end + +def fun_l3_n233() + fun_l4_n523 +end + +def fun_l3_n234() + fun_l4_n9 +end + +def fun_l3_n235() + fun_l4_n705 +end + +def fun_l3_n236() + fun_l4_n811 +end + +def fun_l3_n237() + fun_l4_n987 +end + +def fun_l3_n238() + fun_l4_n915 +end + +def fun_l3_n239() + fun_l4_n302 +end + +def fun_l3_n240() + fun_l4_n766 +end + +def fun_l3_n241() + fun_l4_n29 +end + +def fun_l3_n242() + fun_l4_n154 +end + +def fun_l3_n243() + fun_l4_n853 +end + +def fun_l3_n244() + fun_l4_n619 +end + +def fun_l3_n245() + fun_l4_n739 +end + +def fun_l3_n246() + fun_l4_n814 +end + +def fun_l3_n247() + fun_l4_n768 +end + +def fun_l3_n248() + fun_l4_n2 +end + +def fun_l3_n249() + fun_l4_n595 +end + +def fun_l3_n250() + fun_l4_n606 +end + +def fun_l3_n251() + fun_l4_n144 +end + +def fun_l3_n252() + fun_l4_n550 +end + +def fun_l3_n253() + fun_l4_n268 +end + +def fun_l3_n254() + fun_l4_n320 +end + +def fun_l3_n255() + fun_l4_n59 +end + +def fun_l3_n256() + fun_l4_n586 +end + +def fun_l3_n257() + fun_l4_n766 +end + +def fun_l3_n258() + fun_l4_n96 +end + +def fun_l3_n259() + fun_l4_n964 +end + +def fun_l3_n260() + fun_l4_n163 +end + +def fun_l3_n261() + fun_l4_n305 +end + +def fun_l3_n262() + fun_l4_n155 +end + +def fun_l3_n263() + fun_l4_n249 +end + +def fun_l3_n264() + fun_l4_n887 +end + +def fun_l3_n265() + fun_l4_n625 +end + +def fun_l3_n266() + fun_l4_n241 +end + +def fun_l3_n267() + fun_l4_n385 +end + +def fun_l3_n268() + fun_l4_n287 +end + +def fun_l3_n269() + fun_l4_n375 +end + +def fun_l3_n270() + fun_l4_n13 +end + +def fun_l3_n271() + fun_l4_n44 +end + +def fun_l3_n272() + fun_l4_n259 +end + +def fun_l3_n273() + fun_l4_n231 +end + +def fun_l3_n274() + fun_l4_n692 +end + +def fun_l3_n275() + fun_l4_n279 +end + +def fun_l3_n276() + fun_l4_n353 +end + +def fun_l3_n277() + fun_l4_n287 +end + +def fun_l3_n278() + fun_l4_n254 +end + +def fun_l3_n279() + fun_l4_n717 +end + +def fun_l3_n280() + fun_l4_n635 +end + +def fun_l3_n281() + fun_l4_n264 +end + +def fun_l3_n282() + fun_l4_n390 +end + +def fun_l3_n283() + fun_l4_n824 +end + +def fun_l3_n284() + fun_l4_n919 +end + +def fun_l3_n285() + fun_l4_n273 +end + +def fun_l3_n286() + fun_l4_n566 +end + +def fun_l3_n287() + fun_l4_n6 +end + +def fun_l3_n288() + fun_l4_n28 +end + +def fun_l3_n289() + fun_l4_n602 +end + +def fun_l3_n290() + fun_l4_n209 +end + +def fun_l3_n291() + fun_l4_n753 +end + +def fun_l3_n292() + fun_l4_n914 +end + +def fun_l3_n293() + fun_l4_n345 +end + +def fun_l3_n294() + fun_l4_n616 +end + +def fun_l3_n295() + fun_l4_n640 +end + +def fun_l3_n296() + fun_l4_n47 +end + +def fun_l3_n297() + fun_l4_n542 +end + +def fun_l3_n298() + fun_l4_n379 +end + +def fun_l3_n299() + fun_l4_n14 +end + +def fun_l3_n300() + fun_l4_n126 +end + +def fun_l3_n301() + fun_l4_n913 +end + +def fun_l3_n302() + fun_l4_n933 +end + +def fun_l3_n303() + fun_l4_n429 +end + +def fun_l3_n304() + fun_l4_n175 +end + +def fun_l3_n305() + fun_l4_n152 +end + +def fun_l3_n306() + fun_l4_n556 +end + +def fun_l3_n307() + fun_l4_n799 +end + +def fun_l3_n308() + fun_l4_n865 +end + +def fun_l3_n309() + fun_l4_n501 +end + +def fun_l3_n310() + fun_l4_n148 +end + +def fun_l3_n311() + fun_l4_n160 +end + +def fun_l3_n312() + fun_l4_n333 +end + +def fun_l3_n313() + fun_l4_n987 +end + +def fun_l3_n314() + fun_l4_n449 +end + +def fun_l3_n315() + fun_l4_n460 +end + +def fun_l3_n316() + fun_l4_n866 +end + +def fun_l3_n317() + fun_l4_n554 +end + +def fun_l3_n318() + fun_l4_n497 +end + +def fun_l3_n319() + fun_l4_n25 +end + +def fun_l3_n320() + fun_l4_n483 +end + +def fun_l3_n321() + fun_l4_n412 +end + +def fun_l3_n322() + fun_l4_n594 +end + +def fun_l3_n323() + fun_l4_n727 +end + +def fun_l3_n324() + fun_l4_n209 +end + +def fun_l3_n325() + fun_l4_n956 +end + +def fun_l3_n326() + fun_l4_n127 +end + +def fun_l3_n327() + fun_l4_n942 +end + +def fun_l3_n328() + fun_l4_n984 +end + +def fun_l3_n329() + fun_l4_n387 +end + +def fun_l3_n330() + fun_l4_n834 +end + +def fun_l3_n331() + fun_l4_n723 +end + +def fun_l3_n332() + fun_l4_n576 +end + +def fun_l3_n333() + fun_l4_n949 +end + +def fun_l3_n334() + fun_l4_n792 +end + +def fun_l3_n335() + fun_l4_n28 +end + +def fun_l3_n336() + fun_l4_n805 +end + +def fun_l3_n337() + fun_l4_n469 +end + +def fun_l3_n338() + fun_l4_n651 +end + +def fun_l3_n339() + fun_l4_n672 +end + +def fun_l3_n340() + fun_l4_n835 +end + +def fun_l3_n341() + fun_l4_n902 +end + +def fun_l3_n342() + fun_l4_n9 +end + +def fun_l3_n343() + fun_l4_n111 +end + +def fun_l3_n344() + fun_l4_n234 +end + +def fun_l3_n345() + fun_l4_n608 +end + +def fun_l3_n346() + fun_l4_n577 +end + +def fun_l3_n347() + fun_l4_n966 +end + +def fun_l3_n348() + fun_l4_n777 +end + +def fun_l3_n349() + fun_l4_n387 +end + +def fun_l3_n350() + fun_l4_n27 +end + +def fun_l3_n351() + fun_l4_n94 +end + +def fun_l3_n352() + fun_l4_n12 +end + +def fun_l3_n353() + fun_l4_n632 +end + +def fun_l3_n354() + fun_l4_n314 +end + +def fun_l3_n355() + fun_l4_n472 +end + +def fun_l3_n356() + fun_l4_n737 +end + +def fun_l3_n357() + fun_l4_n775 +end + +def fun_l3_n358() + fun_l4_n255 +end + +def fun_l3_n359() + fun_l4_n474 +end + +def fun_l3_n360() + fun_l4_n668 +end + +def fun_l3_n361() + fun_l4_n907 +end + +def fun_l3_n362() + fun_l4_n608 +end + +def fun_l3_n363() + fun_l4_n885 +end + +def fun_l3_n364() + fun_l4_n63 +end + +def fun_l3_n365() + fun_l4_n432 +end + +def fun_l3_n366() + fun_l4_n748 +end + +def fun_l3_n367() + fun_l4_n741 +end + +def fun_l3_n368() + fun_l4_n799 +end + +def fun_l3_n369() + fun_l4_n747 +end + +def fun_l3_n370() + fun_l4_n939 +end + +def fun_l3_n371() + fun_l4_n569 +end + +def fun_l3_n372() + fun_l4_n267 +end + +def fun_l3_n373() + fun_l4_n640 +end + +def fun_l3_n374() + fun_l4_n647 +end + +def fun_l3_n375() + fun_l4_n658 +end + +def fun_l3_n376() + fun_l4_n346 +end + +def fun_l3_n377() + fun_l4_n781 +end + +def fun_l3_n378() + fun_l4_n820 +end + +def fun_l3_n379() + fun_l4_n11 +end + +def fun_l3_n380() + fun_l4_n238 +end + +def fun_l3_n381() + fun_l4_n78 +end + +def fun_l3_n382() + fun_l4_n497 +end + +def fun_l3_n383() + fun_l4_n815 +end + +def fun_l3_n384() + fun_l4_n876 +end + +def fun_l3_n385() + fun_l4_n392 +end + +def fun_l3_n386() + fun_l4_n228 +end + +def fun_l3_n387() + fun_l4_n230 +end + +def fun_l3_n388() + fun_l4_n216 +end + +def fun_l3_n389() + fun_l4_n661 +end + +def fun_l3_n390() + fun_l4_n831 +end + +def fun_l3_n391() + fun_l4_n588 +end + +def fun_l3_n392() + fun_l4_n377 +end + +def fun_l3_n393() + fun_l4_n245 +end + +def fun_l3_n394() + fun_l4_n546 +end + +def fun_l3_n395() + fun_l4_n48 +end + +def fun_l3_n396() + fun_l4_n109 +end + +def fun_l3_n397() + fun_l4_n958 +end + +def fun_l3_n398() + fun_l4_n779 +end + +def fun_l3_n399() + fun_l4_n942 +end + +def fun_l3_n400() + fun_l4_n436 +end + +def fun_l3_n401() + fun_l4_n321 +end + +def fun_l3_n402() + fun_l4_n789 +end + +def fun_l3_n403() + fun_l4_n96 +end + +def fun_l3_n404() + fun_l4_n101 +end + +def fun_l3_n405() + fun_l4_n373 +end + +def fun_l3_n406() + fun_l4_n143 +end + +def fun_l3_n407() + fun_l4_n869 +end + +def fun_l3_n408() + fun_l4_n836 +end + +def fun_l3_n409() + fun_l4_n278 +end + +def fun_l3_n410() + fun_l4_n819 +end + +def fun_l3_n411() + fun_l4_n716 +end + +def fun_l3_n412() + fun_l4_n729 +end + +def fun_l3_n413() + fun_l4_n565 +end + +def fun_l3_n414() + fun_l4_n258 +end + +def fun_l3_n415() + fun_l4_n187 +end + +def fun_l3_n416() + fun_l4_n425 +end + +def fun_l3_n417() + fun_l4_n239 +end + +def fun_l3_n418() + fun_l4_n352 +end + +def fun_l3_n419() + fun_l4_n747 +end + +def fun_l3_n420() + fun_l4_n103 +end + +def fun_l3_n421() + fun_l4_n276 +end + +def fun_l3_n422() + fun_l4_n348 +end + +def fun_l3_n423() + fun_l4_n737 +end + +def fun_l3_n424() + fun_l4_n615 +end + +def fun_l3_n425() + fun_l4_n305 +end + +def fun_l3_n426() + fun_l4_n474 +end + +def fun_l3_n427() + fun_l4_n304 +end + +def fun_l3_n428() + fun_l4_n607 +end + +def fun_l3_n429() + fun_l4_n202 +end + +def fun_l3_n430() + fun_l4_n370 +end + +def fun_l3_n431() + fun_l4_n580 +end + +def fun_l3_n432() + fun_l4_n752 +end + +def fun_l3_n433() + fun_l4_n720 +end + +def fun_l3_n434() + fun_l4_n916 +end + +def fun_l3_n435() + fun_l4_n424 +end + +def fun_l3_n436() + fun_l4_n922 +end + +def fun_l3_n437() + fun_l4_n885 +end + +def fun_l3_n438() + fun_l4_n849 +end + +def fun_l3_n439() + fun_l4_n595 +end + +def fun_l3_n440() + fun_l4_n753 +end + +def fun_l3_n441() + fun_l4_n871 +end + +def fun_l3_n442() + fun_l4_n979 +end + +def fun_l3_n443() + fun_l4_n217 +end + +def fun_l3_n444() + fun_l4_n249 +end + +def fun_l3_n445() + fun_l4_n181 +end + +def fun_l3_n446() + fun_l4_n283 +end + +def fun_l3_n447() + fun_l4_n495 +end + +def fun_l3_n448() + fun_l4_n701 +end + +def fun_l3_n449() + fun_l4_n897 +end + +def fun_l3_n450() + fun_l4_n479 +end + +def fun_l3_n451() + fun_l4_n410 +end + +def fun_l3_n452() + fun_l4_n842 +end + +def fun_l3_n453() + fun_l4_n700 +end + +def fun_l3_n454() + fun_l4_n855 +end + +def fun_l3_n455() + fun_l4_n743 +end + +def fun_l3_n456() + fun_l4_n842 +end + +def fun_l3_n457() + fun_l4_n575 +end + +def fun_l3_n458() + fun_l4_n48 +end + +def fun_l3_n459() + fun_l4_n650 +end + +def fun_l3_n460() + fun_l4_n714 +end + +def fun_l3_n461() + fun_l4_n409 +end + +def fun_l3_n462() + fun_l4_n225 +end + +def fun_l3_n463() + fun_l4_n419 +end + +def fun_l3_n464() + fun_l4_n563 +end + +def fun_l3_n465() + fun_l4_n416 +end + +def fun_l3_n466() + fun_l4_n738 +end + +def fun_l3_n467() + fun_l4_n955 +end + +def fun_l3_n468() + fun_l4_n406 +end + +def fun_l3_n469() + fun_l4_n157 +end + +def fun_l3_n470() + fun_l4_n732 +end + +def fun_l3_n471() + fun_l4_n567 +end + +def fun_l3_n472() + fun_l4_n895 +end + +def fun_l3_n473() + fun_l4_n377 +end + +def fun_l3_n474() + fun_l4_n105 +end + +def fun_l3_n475() + fun_l4_n640 +end + +def fun_l3_n476() + fun_l4_n617 +end + +def fun_l3_n477() + fun_l4_n109 +end + +def fun_l3_n478() + fun_l4_n358 +end + +def fun_l3_n479() + fun_l4_n522 +end + +def fun_l3_n480() + fun_l4_n550 +end + +def fun_l3_n481() + fun_l4_n648 +end + +def fun_l3_n482() + fun_l4_n533 +end + +def fun_l3_n483() + fun_l4_n782 +end + +def fun_l3_n484() + fun_l4_n369 +end + +def fun_l3_n485() + fun_l4_n644 +end + +def fun_l3_n486() + fun_l4_n989 +end + +def fun_l3_n487() + fun_l4_n434 +end + +def fun_l3_n488() + fun_l4_n914 +end + +def fun_l3_n489() + fun_l4_n2 +end + +def fun_l3_n490() + fun_l4_n494 +end + +def fun_l3_n491() + fun_l4_n479 +end + +def fun_l3_n492() + fun_l4_n733 +end + +def fun_l3_n493() + fun_l4_n394 +end + +def fun_l3_n494() + fun_l4_n39 +end + +def fun_l3_n495() + fun_l4_n866 +end + +def fun_l3_n496() + fun_l4_n151 +end + +def fun_l3_n497() + fun_l4_n155 +end + +def fun_l3_n498() + fun_l4_n417 +end + +def fun_l3_n499() + fun_l4_n933 +end + +def fun_l3_n500() + fun_l4_n44 +end + +def fun_l3_n501() + fun_l4_n738 +end + +def fun_l3_n502() + fun_l4_n859 +end + +def fun_l3_n503() + fun_l4_n124 +end + +def fun_l3_n504() + fun_l4_n344 +end + +def fun_l3_n505() + fun_l4_n921 +end + +def fun_l3_n506() + fun_l4_n168 +end + +def fun_l3_n507() + fun_l4_n135 +end + +def fun_l3_n508() + fun_l4_n730 +end + +def fun_l3_n509() + fun_l4_n671 +end + +def fun_l3_n510() + fun_l4_n899 +end + +def fun_l3_n511() + fun_l4_n630 +end + +def fun_l3_n512() + fun_l4_n228 +end + +def fun_l3_n513() + fun_l4_n429 +end + +def fun_l3_n514() + fun_l4_n723 +end + +def fun_l3_n515() + fun_l4_n185 +end + +def fun_l3_n516() + fun_l4_n161 +end + +def fun_l3_n517() + fun_l4_n491 +end + +def fun_l3_n518() + fun_l4_n643 +end + +def fun_l3_n519() + fun_l4_n3 +end + +def fun_l3_n520() + fun_l4_n399 +end + +def fun_l3_n521() + fun_l4_n927 +end + +def fun_l3_n522() + fun_l4_n501 +end + +def fun_l3_n523() + fun_l4_n729 +end + +def fun_l3_n524() + fun_l4_n628 +end + +def fun_l3_n525() + fun_l4_n469 +end + +def fun_l3_n526() + fun_l4_n754 +end + +def fun_l3_n527() + fun_l4_n448 +end + +def fun_l3_n528() + fun_l4_n562 +end + +def fun_l3_n529() + fun_l4_n779 +end + +def fun_l3_n530() + fun_l4_n452 +end + +def fun_l3_n531() + fun_l4_n756 +end + +def fun_l3_n532() + fun_l4_n107 +end + +def fun_l3_n533() + fun_l4_n311 +end + +def fun_l3_n534() + fun_l4_n169 +end + +def fun_l3_n535() + fun_l4_n956 +end + +def fun_l3_n536() + fun_l4_n754 +end + +def fun_l3_n537() + fun_l4_n675 +end + +def fun_l3_n538() + fun_l4_n636 +end + +def fun_l3_n539() + fun_l4_n691 +end + +def fun_l3_n540() + fun_l4_n867 +end + +def fun_l3_n541() + fun_l4_n179 +end + +def fun_l3_n542() + fun_l4_n153 +end + +def fun_l3_n543() + fun_l4_n133 +end + +def fun_l3_n544() + fun_l4_n592 +end + +def fun_l3_n545() + fun_l4_n71 +end + +def fun_l3_n546() + fun_l4_n87 +end + +def fun_l3_n547() + fun_l4_n740 +end + +def fun_l3_n548() + fun_l4_n436 +end + +def fun_l3_n549() + fun_l4_n59 +end + +def fun_l3_n550() + fun_l4_n252 +end + +def fun_l3_n551() + fun_l4_n596 +end + +def fun_l3_n552() + fun_l4_n851 +end + +def fun_l3_n553() + fun_l4_n708 +end + +def fun_l3_n554() + fun_l4_n210 +end + +def fun_l3_n555() + fun_l4_n931 +end + +def fun_l3_n556() + fun_l4_n293 +end + +def fun_l3_n557() + fun_l4_n413 +end + +def fun_l3_n558() + fun_l4_n547 +end + +def fun_l3_n559() + fun_l4_n338 +end + +def fun_l3_n560() + fun_l4_n194 +end + +def fun_l3_n561() + fun_l4_n937 +end + +def fun_l3_n562() + fun_l4_n19 +end + +def fun_l3_n563() + fun_l4_n651 +end + +def fun_l3_n564() + fun_l4_n364 +end + +def fun_l3_n565() + fun_l4_n295 +end + +def fun_l3_n566() + fun_l4_n946 +end + +def fun_l3_n567() + fun_l4_n712 +end + +def fun_l3_n568() + fun_l4_n243 +end + +def fun_l3_n569() + fun_l4_n563 +end + +def fun_l3_n570() + fun_l4_n651 +end + +def fun_l3_n571() + fun_l4_n645 +end + +def fun_l3_n572() + fun_l4_n46 +end + +def fun_l3_n573() + fun_l4_n971 +end + +def fun_l3_n574() + fun_l4_n769 +end + +def fun_l3_n575() + fun_l4_n315 +end + +def fun_l3_n576() + fun_l4_n657 +end + +def fun_l3_n577() + fun_l4_n607 +end + +def fun_l3_n578() + fun_l4_n352 +end + +def fun_l3_n579() + fun_l4_n346 +end + +def fun_l3_n580() + fun_l4_n424 +end + +def fun_l3_n581() + fun_l4_n703 +end + +def fun_l3_n582() + fun_l4_n872 +end + +def fun_l3_n583() + fun_l4_n828 +end + +def fun_l3_n584() + fun_l4_n283 +end + +def fun_l3_n585() + fun_l4_n557 +end + +def fun_l3_n586() + fun_l4_n942 +end + +def fun_l3_n587() + fun_l4_n121 +end + +def fun_l3_n588() + fun_l4_n866 +end + +def fun_l3_n589() + fun_l4_n539 +end + +def fun_l3_n590() + fun_l4_n240 +end + +def fun_l3_n591() + fun_l4_n438 +end + +def fun_l3_n592() + fun_l4_n652 +end + +def fun_l3_n593() + fun_l4_n540 +end + +def fun_l3_n594() + fun_l4_n122 +end + +def fun_l3_n595() + fun_l4_n877 +end + +def fun_l3_n596() + fun_l4_n30 +end + +def fun_l3_n597() + fun_l4_n465 +end + +def fun_l3_n598() + fun_l4_n964 +end + +def fun_l3_n599() + fun_l4_n123 +end + +def fun_l3_n600() + fun_l4_n365 +end + +def fun_l3_n601() + fun_l4_n531 +end + +def fun_l3_n602() + fun_l4_n774 +end + +def fun_l3_n603() + fun_l4_n961 +end + +def fun_l3_n604() + fun_l4_n360 +end + +def fun_l3_n605() + fun_l4_n640 +end + +def fun_l3_n606() + fun_l4_n785 +end + +def fun_l3_n607() + fun_l4_n433 +end + +def fun_l3_n608() + fun_l4_n528 +end + +def fun_l3_n609() + fun_l4_n125 +end + +def fun_l3_n610() + fun_l4_n179 +end + +def fun_l3_n611() + fun_l4_n946 +end + +def fun_l3_n612() + fun_l4_n899 +end + +def fun_l3_n613() + fun_l4_n917 +end + +def fun_l3_n614() + fun_l4_n444 +end + +def fun_l3_n615() + fun_l4_n823 +end + +def fun_l3_n616() + fun_l4_n221 +end + +def fun_l3_n617() + fun_l4_n483 +end + +def fun_l3_n618() + fun_l4_n112 +end + +def fun_l3_n619() + fun_l4_n814 +end + +def fun_l3_n620() + fun_l4_n648 +end + +def fun_l3_n621() + fun_l4_n823 +end + +def fun_l3_n622() + fun_l4_n457 +end + +def fun_l3_n623() + fun_l4_n92 +end + +def fun_l3_n624() + fun_l4_n8 +end + +def fun_l3_n625() + fun_l4_n297 +end + +def fun_l3_n626() + fun_l4_n517 +end + +def fun_l3_n627() + fun_l4_n159 +end + +def fun_l3_n628() + fun_l4_n79 +end + +def fun_l3_n629() + fun_l4_n791 +end + +def fun_l3_n630() + fun_l4_n692 +end + +def fun_l3_n631() + fun_l4_n554 +end + +def fun_l3_n632() + fun_l4_n872 +end + +def fun_l3_n633() + fun_l4_n871 +end + +def fun_l3_n634() + fun_l4_n524 +end + +def fun_l3_n635() + fun_l4_n588 +end + +def fun_l3_n636() + fun_l4_n596 +end + +def fun_l3_n637() + fun_l4_n936 +end + +def fun_l3_n638() + fun_l4_n478 +end + +def fun_l3_n639() + fun_l4_n893 +end + +def fun_l3_n640() + fun_l4_n348 +end + +def fun_l3_n641() + fun_l4_n806 +end + +def fun_l3_n642() + fun_l4_n522 +end + +def fun_l3_n643() + fun_l4_n249 +end + +def fun_l3_n644() + fun_l4_n208 +end + +def fun_l3_n645() + fun_l4_n989 +end + +def fun_l3_n646() + fun_l4_n194 +end + +def fun_l3_n647() + fun_l4_n157 +end + +def fun_l3_n648() + fun_l4_n395 +end + +def fun_l3_n649() + fun_l4_n191 +end + +def fun_l3_n650() + fun_l4_n292 +end + +def fun_l3_n651() + fun_l4_n640 +end + +def fun_l3_n652() + fun_l4_n818 +end + +def fun_l3_n653() + fun_l4_n481 +end + +def fun_l3_n654() + fun_l4_n304 +end + +def fun_l3_n655() + fun_l4_n102 +end + +def fun_l3_n656() + fun_l4_n51 +end + +def fun_l3_n657() + fun_l4_n110 +end + +def fun_l3_n658() + fun_l4_n226 +end + +def fun_l3_n659() + fun_l4_n48 +end + +def fun_l3_n660() + fun_l4_n112 +end + +def fun_l3_n661() + fun_l4_n677 +end + +def fun_l3_n662() + fun_l4_n168 +end + +def fun_l3_n663() + fun_l4_n15 +end + +def fun_l3_n664() + fun_l4_n311 +end + +def fun_l3_n665() + fun_l4_n935 +end + +def fun_l3_n666() + fun_l4_n861 +end + +def fun_l3_n667() + fun_l4_n169 +end + +def fun_l3_n668() + fun_l4_n395 +end + +def fun_l3_n669() + fun_l4_n371 +end + +def fun_l3_n670() + fun_l4_n625 +end + +def fun_l3_n671() + fun_l4_n183 +end + +def fun_l3_n672() + fun_l4_n299 +end + +def fun_l3_n673() + fun_l4_n104 +end + +def fun_l3_n674() + fun_l4_n413 +end + +def fun_l3_n675() + fun_l4_n957 +end + +def fun_l3_n676() + fun_l4_n878 +end + +def fun_l3_n677() + fun_l4_n222 +end + +def fun_l3_n678() + fun_l4_n832 +end + +def fun_l3_n679() + fun_l4_n406 +end + +def fun_l3_n680() + fun_l4_n779 +end + +def fun_l3_n681() + fun_l4_n874 +end + +def fun_l3_n682() + fun_l4_n328 +end + +def fun_l3_n683() + fun_l4_n412 +end + +def fun_l3_n684() + fun_l4_n46 +end + +def fun_l3_n685() + fun_l4_n799 +end + +def fun_l3_n686() + fun_l4_n751 +end + +def fun_l3_n687() + fun_l4_n32 +end + +def fun_l3_n688() + fun_l4_n237 +end + +def fun_l3_n689() + fun_l4_n770 +end + +def fun_l3_n690() + fun_l4_n120 +end + +def fun_l3_n691() + fun_l4_n977 +end + +def fun_l3_n692() + fun_l4_n35 +end + +def fun_l3_n693() + fun_l4_n398 +end + +def fun_l3_n694() + fun_l4_n551 +end + +def fun_l3_n695() + fun_l4_n122 +end + +def fun_l3_n696() + fun_l4_n268 +end + +def fun_l3_n697() + fun_l4_n628 +end + +def fun_l3_n698() + fun_l4_n611 +end + +def fun_l3_n699() + fun_l4_n382 +end + +def fun_l3_n700() + fun_l4_n819 +end + +def fun_l3_n701() + fun_l4_n124 +end + +def fun_l3_n702() + fun_l4_n529 +end + +def fun_l3_n703() + fun_l4_n838 +end + +def fun_l3_n704() + fun_l4_n181 +end + +def fun_l3_n705() + fun_l4_n123 +end + +def fun_l3_n706() + fun_l4_n646 +end + +def fun_l3_n707() + fun_l4_n193 +end + +def fun_l3_n708() + fun_l4_n233 +end + +def fun_l3_n709() + fun_l4_n621 +end + +def fun_l3_n710() + fun_l4_n772 +end + +def fun_l3_n711() + fun_l4_n461 +end + +def fun_l3_n712() + fun_l4_n673 +end + +def fun_l3_n713() + fun_l4_n101 +end + +def fun_l3_n714() + fun_l4_n467 +end + +def fun_l3_n715() + fun_l4_n211 +end + +def fun_l3_n716() + fun_l4_n554 +end + +def fun_l3_n717() + fun_l4_n276 +end + +def fun_l3_n718() + fun_l4_n655 +end + +def fun_l3_n719() + fun_l4_n425 +end + +def fun_l3_n720() + fun_l4_n241 +end + +def fun_l3_n721() + fun_l4_n904 +end + +def fun_l3_n722() + fun_l4_n839 +end + +def fun_l3_n723() + fun_l4_n991 +end + +def fun_l3_n724() + fun_l4_n556 +end + +def fun_l3_n725() + fun_l4_n86 +end + +def fun_l3_n726() + fun_l4_n953 +end + +def fun_l3_n727() + fun_l4_n18 +end + +def fun_l3_n728() + fun_l4_n374 +end + +def fun_l3_n729() + fun_l4_n712 +end + +def fun_l3_n730() + fun_l4_n228 +end + +def fun_l3_n731() + fun_l4_n830 +end + +def fun_l3_n732() + fun_l4_n49 +end + +def fun_l3_n733() + fun_l4_n987 +end + +def fun_l3_n734() + fun_l4_n815 +end + +def fun_l3_n735() + fun_l4_n386 +end + +def fun_l3_n736() + fun_l4_n843 +end + +def fun_l3_n737() + fun_l4_n958 +end + +def fun_l3_n738() + fun_l4_n317 +end + +def fun_l3_n739() + fun_l4_n361 +end + +def fun_l3_n740() + fun_l4_n392 +end + +def fun_l3_n741() + fun_l4_n888 +end + +def fun_l3_n742() + fun_l4_n186 +end + +def fun_l3_n743() + fun_l4_n493 +end + +def fun_l3_n744() + fun_l4_n302 +end + +def fun_l3_n745() + fun_l4_n690 +end + +def fun_l3_n746() + fun_l4_n601 +end + +def fun_l3_n747() + fun_l4_n975 +end + +def fun_l3_n748() + fun_l4_n543 +end + +def fun_l3_n749() + fun_l4_n8 +end + +def fun_l3_n750() + fun_l4_n905 +end + +def fun_l3_n751() + fun_l4_n964 +end + +def fun_l3_n752() + fun_l4_n739 +end + +def fun_l3_n753() + fun_l4_n24 +end + +def fun_l3_n754() + fun_l4_n806 +end + +def fun_l3_n755() + fun_l4_n704 +end + +def fun_l3_n756() + fun_l4_n579 +end + +def fun_l3_n757() + fun_l4_n264 +end + +def fun_l3_n758() + fun_l4_n357 +end + +def fun_l3_n759() + fun_l4_n333 +end + +def fun_l3_n760() + fun_l4_n309 +end + +def fun_l3_n761() + fun_l4_n419 +end + +def fun_l3_n762() + fun_l4_n347 +end + +def fun_l3_n763() + fun_l4_n132 +end + +def fun_l3_n764() + fun_l4_n45 +end + +def fun_l3_n765() + fun_l4_n740 +end + +def fun_l3_n766() + fun_l4_n332 +end + +def fun_l3_n767() + fun_l4_n600 +end + +def fun_l3_n768() + fun_l4_n343 +end + +def fun_l3_n769() + fun_l4_n872 +end + +def fun_l3_n770() + fun_l4_n326 +end + +def fun_l3_n771() + fun_l4_n862 +end + +def fun_l3_n772() + fun_l4_n800 +end + +def fun_l3_n773() + fun_l4_n616 +end + +def fun_l3_n774() + fun_l4_n392 +end + +def fun_l3_n775() + fun_l4_n252 +end + +def fun_l3_n776() + fun_l4_n289 +end + +def fun_l3_n777() + fun_l4_n789 +end + +def fun_l3_n778() + fun_l4_n370 +end + +def fun_l3_n779() + fun_l4_n969 +end + +def fun_l3_n780() + fun_l4_n444 +end + +def fun_l3_n781() + fun_l4_n671 +end + +def fun_l3_n782() + fun_l4_n301 +end + +def fun_l3_n783() + fun_l4_n418 +end + +def fun_l3_n784() + fun_l4_n491 +end + +def fun_l3_n785() + fun_l4_n746 +end + +def fun_l3_n786() + fun_l4_n212 +end + +def fun_l3_n787() + fun_l4_n856 +end + +def fun_l3_n788() + fun_l4_n155 +end + +def fun_l3_n789() + fun_l4_n685 +end + +def fun_l3_n790() + fun_l4_n879 +end + +def fun_l3_n791() + fun_l4_n363 +end + +def fun_l3_n792() + fun_l4_n231 +end + +def fun_l3_n793() + fun_l4_n727 +end + +def fun_l3_n794() + fun_l4_n355 +end + +def fun_l3_n795() + fun_l4_n671 +end + +def fun_l3_n796() + fun_l4_n20 +end + +def fun_l3_n797() + fun_l4_n523 +end + +def fun_l3_n798() + fun_l4_n26 +end + +def fun_l3_n799() + fun_l4_n785 +end + +def fun_l3_n800() + fun_l4_n458 +end + +def fun_l3_n801() + fun_l4_n160 +end + +def fun_l3_n802() + fun_l4_n543 +end + +def fun_l3_n803() + fun_l4_n292 +end + +def fun_l3_n804() + fun_l4_n64 +end + +def fun_l3_n805() + fun_l4_n851 +end + +def fun_l3_n806() + fun_l4_n369 +end + +def fun_l3_n807() + fun_l4_n827 +end + +def fun_l3_n808() + fun_l4_n420 +end + +def fun_l3_n809() + fun_l4_n98 +end + +def fun_l3_n810() + fun_l4_n508 +end + +def fun_l3_n811() + fun_l4_n366 +end + +def fun_l3_n812() + fun_l4_n795 +end + +def fun_l3_n813() + fun_l4_n345 +end + +def fun_l3_n814() + fun_l4_n505 +end + +def fun_l3_n815() + fun_l4_n302 +end + +def fun_l3_n816() + fun_l4_n561 +end + +def fun_l3_n817() + fun_l4_n781 +end + +def fun_l3_n818() + fun_l4_n599 +end + +def fun_l3_n819() + fun_l4_n967 +end + +def fun_l3_n820() + fun_l4_n691 +end + +def fun_l3_n821() + fun_l4_n563 +end + +def fun_l3_n822() + fun_l4_n769 +end + +def fun_l3_n823() + fun_l4_n531 +end + +def fun_l3_n824() + fun_l4_n957 +end + +def fun_l3_n825() + fun_l4_n395 +end + +def fun_l3_n826() + fun_l4_n92 +end + +def fun_l3_n827() + fun_l4_n781 +end + +def fun_l3_n828() + fun_l4_n758 +end + +def fun_l3_n829() + fun_l4_n648 +end + +def fun_l3_n830() + fun_l4_n799 +end + +def fun_l3_n831() + fun_l4_n922 +end + +def fun_l3_n832() + fun_l4_n808 +end + +def fun_l3_n833() + fun_l4_n180 +end + +def fun_l3_n834() + fun_l4_n126 +end + +def fun_l3_n835() + fun_l4_n261 +end + +def fun_l3_n836() + fun_l4_n470 +end + +def fun_l3_n837() + fun_l4_n441 +end + +def fun_l3_n838() + fun_l4_n505 +end + +def fun_l3_n839() + fun_l4_n490 +end + +def fun_l3_n840() + fun_l4_n663 +end + +def fun_l3_n841() + fun_l4_n256 +end + +def fun_l3_n842() + fun_l4_n797 +end + +def fun_l3_n843() + fun_l4_n836 +end + +def fun_l3_n844() + fun_l4_n868 +end + +def fun_l3_n845() + fun_l4_n927 +end + +def fun_l3_n846() + fun_l4_n746 +end + +def fun_l3_n847() + fun_l4_n143 +end + +def fun_l3_n848() + fun_l4_n90 +end + +def fun_l3_n849() + fun_l4_n63 +end + +def fun_l3_n850() + fun_l4_n629 +end + +def fun_l3_n851() + fun_l4_n66 +end + +def fun_l3_n852() + fun_l4_n192 +end + +def fun_l3_n853() + fun_l4_n780 +end + +def fun_l3_n854() + fun_l4_n744 +end + +def fun_l3_n855() + fun_l4_n989 +end + +def fun_l3_n856() + fun_l4_n609 +end + +def fun_l3_n857() + fun_l4_n534 +end + +def fun_l3_n858() + fun_l4_n961 +end + +def fun_l3_n859() + fun_l4_n605 +end + +def fun_l3_n860() + fun_l4_n675 +end + +def fun_l3_n861() + fun_l4_n520 +end + +def fun_l3_n862() + fun_l4_n656 +end + +def fun_l3_n863() + fun_l4_n917 +end + +def fun_l3_n864() + fun_l4_n291 +end + +def fun_l3_n865() + fun_l4_n343 +end + +def fun_l3_n866() + fun_l4_n704 +end + +def fun_l3_n867() + fun_l4_n368 +end + +def fun_l3_n868() + fun_l4_n678 +end + +def fun_l3_n869() + fun_l4_n788 +end + +def fun_l3_n870() + fun_l4_n458 +end + +def fun_l3_n871() + fun_l4_n882 +end + +def fun_l3_n872() + fun_l4_n830 +end + +def fun_l3_n873() + fun_l4_n434 +end + +def fun_l3_n874() + fun_l4_n92 +end + +def fun_l3_n875() + fun_l4_n633 +end + +def fun_l3_n876() + fun_l4_n243 +end + +def fun_l3_n877() + fun_l4_n641 +end + +def fun_l3_n878() + fun_l4_n114 +end + +def fun_l3_n879() + fun_l4_n696 +end + +def fun_l3_n880() + fun_l4_n354 +end + +def fun_l3_n881() + fun_l4_n644 +end + +def fun_l3_n882() + fun_l4_n771 +end + +def fun_l3_n883() + fun_l4_n196 +end + +def fun_l3_n884() + fun_l4_n202 +end + +def fun_l3_n885() + fun_l4_n322 +end + +def fun_l3_n886() + fun_l4_n125 +end + +def fun_l3_n887() + fun_l4_n760 +end + +def fun_l3_n888() + fun_l4_n69 +end + +def fun_l3_n889() + fun_l4_n101 +end + +def fun_l3_n890() + fun_l4_n108 +end + +def fun_l3_n891() + fun_l4_n929 +end + +def fun_l3_n892() + fun_l4_n766 +end + +def fun_l3_n893() + fun_l4_n811 +end + +def fun_l3_n894() + fun_l4_n169 +end + +def fun_l3_n895() + fun_l4_n613 +end + +def fun_l3_n896() + fun_l4_n145 +end + +def fun_l3_n897() + fun_l4_n780 +end + +def fun_l3_n898() + fun_l4_n972 +end + +def fun_l3_n899() + fun_l4_n508 +end + +def fun_l3_n900() + fun_l4_n468 +end + +def fun_l3_n901() + fun_l4_n968 +end + +def fun_l3_n902() + fun_l4_n714 +end + +def fun_l3_n903() + fun_l4_n817 +end + +def fun_l3_n904() + fun_l4_n111 +end + +def fun_l3_n905() + fun_l4_n115 +end + +def fun_l3_n906() + fun_l4_n593 +end + +def fun_l3_n907() + fun_l4_n961 +end + +def fun_l3_n908() + fun_l4_n362 +end + +def fun_l3_n909() + fun_l4_n251 +end + +def fun_l3_n910() + fun_l4_n532 +end + +def fun_l3_n911() + fun_l4_n252 +end + +def fun_l3_n912() + fun_l4_n751 +end + +def fun_l3_n913() + fun_l4_n962 +end + +def fun_l3_n914() + fun_l4_n151 +end + +def fun_l3_n915() + fun_l4_n91 +end + +def fun_l3_n916() + fun_l4_n164 +end + +def fun_l3_n917() + fun_l4_n714 +end + +def fun_l3_n918() + fun_l4_n496 +end + +def fun_l3_n919() + fun_l4_n833 +end + +def fun_l3_n920() + fun_l4_n315 +end + +def fun_l3_n921() + fun_l4_n551 +end + +def fun_l3_n922() + fun_l4_n986 +end + +def fun_l3_n923() + fun_l4_n924 +end + +def fun_l3_n924() + fun_l4_n670 +end + +def fun_l3_n925() + fun_l4_n611 +end + +def fun_l3_n926() + fun_l4_n590 +end + +def fun_l3_n927() + fun_l4_n951 +end + +def fun_l3_n928() + fun_l4_n438 +end + +def fun_l3_n929() + fun_l4_n914 +end + +def fun_l3_n930() + fun_l4_n357 +end + +def fun_l3_n931() + fun_l4_n330 +end + +def fun_l3_n932() + fun_l4_n737 +end + +def fun_l3_n933() + fun_l4_n857 +end + +def fun_l3_n934() + fun_l4_n32 +end + +def fun_l3_n935() + fun_l4_n980 +end + +def fun_l3_n936() + fun_l4_n229 +end + +def fun_l3_n937() + fun_l4_n779 +end + +def fun_l3_n938() + fun_l4_n365 +end + +def fun_l3_n939() + fun_l4_n681 +end + +def fun_l3_n940() + fun_l4_n55 +end + +def fun_l3_n941() + fun_l4_n324 +end + +def fun_l3_n942() + fun_l4_n630 +end + +def fun_l3_n943() + fun_l4_n910 +end + +def fun_l3_n944() + fun_l4_n590 +end + +def fun_l3_n945() + fun_l4_n798 +end + +def fun_l3_n946() + fun_l4_n973 +end + +def fun_l3_n947() + fun_l4_n180 +end + +def fun_l3_n948() + fun_l4_n425 +end + +def fun_l3_n949() + fun_l4_n446 +end + +def fun_l3_n950() + fun_l4_n296 +end + +def fun_l3_n951() + fun_l4_n61 +end + +def fun_l3_n952() + fun_l4_n797 +end + +def fun_l3_n953() + fun_l4_n824 +end + +def fun_l3_n954() + fun_l4_n336 +end + +def fun_l3_n955() + fun_l4_n82 +end + +def fun_l3_n956() + fun_l4_n310 +end + +def fun_l3_n957() + fun_l4_n983 +end + +def fun_l3_n958() + fun_l4_n780 +end + +def fun_l3_n959() + fun_l4_n697 +end + +def fun_l3_n960() + fun_l4_n822 +end + +def fun_l3_n961() + fun_l4_n209 +end + +def fun_l3_n962() + fun_l4_n549 +end + +def fun_l3_n963() + fun_l4_n226 +end + +def fun_l3_n964() + fun_l4_n324 +end + +def fun_l3_n965() + fun_l4_n63 +end + +def fun_l3_n966() + fun_l4_n430 +end + +def fun_l3_n967() + fun_l4_n645 +end + +def fun_l3_n968() + fun_l4_n875 +end + +def fun_l3_n969() + fun_l4_n713 +end + +def fun_l3_n970() + fun_l4_n457 +end + +def fun_l3_n971() + fun_l4_n768 +end + +def fun_l3_n972() + fun_l4_n548 +end + +def fun_l3_n973() + fun_l4_n577 +end + +def fun_l3_n974() + fun_l4_n109 +end + +def fun_l3_n975() + fun_l4_n460 +end + +def fun_l3_n976() + fun_l4_n83 +end + +def fun_l3_n977() + fun_l4_n152 +end + +def fun_l3_n978() + fun_l4_n224 +end + +def fun_l3_n979() + fun_l4_n897 +end + +def fun_l3_n980() + fun_l4_n830 +end + +def fun_l3_n981() + fun_l4_n747 +end + +def fun_l3_n982() + fun_l4_n21 +end + +def fun_l3_n983() + fun_l4_n84 +end + +def fun_l3_n984() + fun_l4_n342 +end + +def fun_l3_n985() + fun_l4_n950 +end + +def fun_l3_n986() + fun_l4_n33 +end + +def fun_l3_n987() + fun_l4_n388 +end + +def fun_l3_n988() + fun_l4_n766 +end + +def fun_l3_n989() + fun_l4_n708 +end + +def fun_l3_n990() + fun_l4_n392 +end + +def fun_l3_n991() + fun_l4_n782 +end + +def fun_l3_n992() + fun_l4_n223 +end + +def fun_l3_n993() + fun_l4_n416 +end + +def fun_l3_n994() + fun_l4_n609 +end + +def fun_l3_n995() + fun_l4_n158 +end + +def fun_l3_n996() + fun_l4_n246 +end + +def fun_l3_n997() + fun_l4_n667 +end + +def fun_l3_n998() + fun_l4_n126 +end + +def fun_l3_n999() + fun_l4_n726 +end + +def fun_l4_n0() + fun_l5_n544 +end + +def fun_l4_n1() + fun_l5_n456 +end + +def fun_l4_n2() + fun_l5_n364 +end + +def fun_l4_n3() + fun_l5_n929 +end + +def fun_l4_n4() + fun_l5_n593 +end + +def fun_l4_n5() + fun_l5_n287 +end + +def fun_l4_n6() + fun_l5_n272 +end + +def fun_l4_n7() + fun_l5_n71 +end + +def fun_l4_n8() + fun_l5_n704 +end + +def fun_l4_n9() + fun_l5_n462 +end + +def fun_l4_n10() + fun_l5_n239 +end + +def fun_l4_n11() + fun_l5_n853 +end + +def fun_l4_n12() + fun_l5_n217 +end + +def fun_l4_n13() + fun_l5_n822 +end + +def fun_l4_n14() + fun_l5_n663 +end + +def fun_l4_n15() + fun_l5_n400 +end + +def fun_l4_n16() + fun_l5_n307 +end + +def fun_l4_n17() + fun_l5_n820 +end + +def fun_l4_n18() + fun_l5_n885 +end + +def fun_l4_n19() + fun_l5_n680 +end + +def fun_l4_n20() + fun_l5_n592 +end + +def fun_l4_n21() + fun_l5_n615 +end + +def fun_l4_n22() + fun_l5_n669 +end + +def fun_l4_n23() + fun_l5_n978 +end + +def fun_l4_n24() + fun_l5_n946 +end + +def fun_l4_n25() + fun_l5_n915 +end + +def fun_l4_n26() + fun_l5_n286 +end + +def fun_l4_n27() + fun_l5_n466 +end + +def fun_l4_n28() + fun_l5_n970 +end + +def fun_l4_n29() + fun_l5_n822 +end + +def fun_l4_n30() + fun_l5_n883 +end + +def fun_l4_n31() + fun_l5_n137 +end + +def fun_l4_n32() + fun_l5_n957 +end + +def fun_l4_n33() + fun_l5_n912 +end + +def fun_l4_n34() + fun_l5_n156 +end + +def fun_l4_n35() + fun_l5_n207 +end + +def fun_l4_n36() + fun_l5_n525 +end + +def fun_l4_n37() + fun_l5_n673 +end + +def fun_l4_n38() + fun_l5_n151 +end + +def fun_l4_n39() + fun_l5_n517 +end + +def fun_l4_n40() + fun_l5_n459 +end + +def fun_l4_n41() + fun_l5_n738 +end + +def fun_l4_n42() + fun_l5_n809 +end + +def fun_l4_n43() + fun_l5_n853 +end + +def fun_l4_n44() + fun_l5_n653 +end + +def fun_l4_n45() + fun_l5_n346 +end + +def fun_l4_n46() + fun_l5_n704 +end + +def fun_l4_n47() + fun_l5_n662 +end + +def fun_l4_n48() + fun_l5_n990 +end + +def fun_l4_n49() + fun_l5_n731 +end + +def fun_l4_n50() + fun_l5_n305 +end + +def fun_l4_n51() + fun_l5_n238 +end + +def fun_l4_n52() + fun_l5_n710 +end + +def fun_l4_n53() + fun_l5_n61 +end + +def fun_l4_n54() + fun_l5_n572 +end + +def fun_l4_n55() + fun_l5_n939 +end + +def fun_l4_n56() + fun_l5_n223 +end + +def fun_l4_n57() + fun_l5_n466 +end + +def fun_l4_n58() + fun_l5_n442 +end + +def fun_l4_n59() + fun_l5_n971 +end + +def fun_l4_n60() + fun_l5_n42 +end + +def fun_l4_n61() + fun_l5_n390 +end + +def fun_l4_n62() + fun_l5_n254 +end + +def fun_l4_n63() + fun_l5_n522 +end + +def fun_l4_n64() + fun_l5_n16 +end + +def fun_l4_n65() + fun_l5_n567 +end + +def fun_l4_n66() + fun_l5_n353 +end + +def fun_l4_n67() + fun_l5_n676 +end + +def fun_l4_n68() + fun_l5_n526 +end + +def fun_l4_n69() + fun_l5_n140 +end + +def fun_l4_n70() + fun_l5_n829 +end + +def fun_l4_n71() + fun_l5_n562 +end + +def fun_l4_n72() + fun_l5_n489 +end + +def fun_l4_n73() + fun_l5_n205 +end + +def fun_l4_n74() + fun_l5_n558 +end + +def fun_l4_n75() + fun_l5_n689 +end + +def fun_l4_n76() + fun_l5_n803 +end + +def fun_l4_n77() + fun_l5_n222 +end + +def fun_l4_n78() + fun_l5_n696 +end + +def fun_l4_n79() + fun_l5_n457 +end + +def fun_l4_n80() + fun_l5_n794 +end + +def fun_l4_n81() + fun_l5_n886 +end + +def fun_l4_n82() + fun_l5_n742 +end + +def fun_l4_n83() + fun_l5_n560 +end + +def fun_l4_n84() + fun_l5_n207 +end + +def fun_l4_n85() + fun_l5_n265 +end + +def fun_l4_n86() + fun_l5_n871 +end + +def fun_l4_n87() + fun_l5_n113 +end + +def fun_l4_n88() + fun_l5_n141 +end + +def fun_l4_n89() + fun_l5_n231 +end + +def fun_l4_n90() + fun_l5_n980 +end + +def fun_l4_n91() + fun_l5_n586 +end + +def fun_l4_n92() + fun_l5_n961 +end + +def fun_l4_n93() + fun_l5_n128 +end + +def fun_l4_n94() + fun_l5_n395 +end + +def fun_l4_n95() + fun_l5_n810 +end + +def fun_l4_n96() + fun_l5_n337 +end + +def fun_l4_n97() + fun_l5_n256 +end + +def fun_l4_n98() + fun_l5_n188 +end + +def fun_l4_n99() + fun_l5_n358 +end + +def fun_l4_n100() + fun_l5_n751 +end + +def fun_l4_n101() + fun_l5_n898 +end + +def fun_l4_n102() + fun_l5_n323 +end + +def fun_l4_n103() + fun_l5_n455 +end + +def fun_l4_n104() + fun_l5_n976 +end + +def fun_l4_n105() + fun_l5_n962 +end + +def fun_l4_n106() + fun_l5_n781 +end + +def fun_l4_n107() + fun_l5_n277 +end + +def fun_l4_n108() + fun_l5_n146 +end + +def fun_l4_n109() + fun_l5_n793 +end + +def fun_l4_n110() + fun_l5_n787 +end + +def fun_l4_n111() + fun_l5_n597 +end + +def fun_l4_n112() + fun_l5_n799 +end + +def fun_l4_n113() + fun_l5_n598 +end + +def fun_l4_n114() + fun_l5_n456 +end + +def fun_l4_n115() + fun_l5_n45 +end + +def fun_l4_n116() + fun_l5_n265 +end + +def fun_l4_n117() + fun_l5_n661 +end + +def fun_l4_n118() + fun_l5_n657 +end + +def fun_l4_n119() + fun_l5_n703 +end + +def fun_l4_n120() + fun_l5_n164 +end + +def fun_l4_n121() + fun_l5_n182 +end + +def fun_l4_n122() + fun_l5_n605 +end + +def fun_l4_n123() + fun_l5_n237 +end + +def fun_l4_n124() + fun_l5_n582 +end + +def fun_l4_n125() + fun_l5_n381 +end + +def fun_l4_n126() + fun_l5_n244 +end + +def fun_l4_n127() + fun_l5_n272 +end + +def fun_l4_n128() + fun_l5_n989 +end + +def fun_l4_n129() + fun_l5_n366 +end + +def fun_l4_n130() + fun_l5_n640 +end + +def fun_l4_n131() + fun_l5_n953 +end + +def fun_l4_n132() + fun_l5_n990 +end + +def fun_l4_n133() + fun_l5_n497 +end + +def fun_l4_n134() + fun_l5_n12 +end + +def fun_l4_n135() + fun_l5_n993 +end + +def fun_l4_n136() + fun_l5_n802 +end + +def fun_l4_n137() + fun_l5_n411 +end + +def fun_l4_n138() + fun_l5_n154 +end + +def fun_l4_n139() + fun_l5_n924 +end + +def fun_l4_n140() + fun_l5_n772 +end + +def fun_l4_n141() + fun_l5_n972 +end + +def fun_l4_n142() + fun_l5_n847 +end + +def fun_l4_n143() + fun_l5_n481 +end + +def fun_l4_n144() + fun_l5_n52 +end + +def fun_l4_n145() + fun_l5_n451 +end + +def fun_l4_n146() + fun_l5_n339 +end + +def fun_l4_n147() + fun_l5_n531 +end + +def fun_l4_n148() + fun_l5_n735 +end + +def fun_l4_n149() + fun_l5_n747 +end + +def fun_l4_n150() + fun_l5_n750 +end + +def fun_l4_n151() + fun_l5_n762 +end + +def fun_l4_n152() + fun_l5_n131 +end + +def fun_l4_n153() + fun_l5_n532 +end + +def fun_l4_n154() + fun_l5_n398 +end + +def fun_l4_n155() + fun_l5_n660 +end + +def fun_l4_n156() + fun_l5_n374 +end + +def fun_l4_n157() + fun_l5_n245 +end + +def fun_l4_n158() + fun_l5_n850 +end + +def fun_l4_n159() + fun_l5_n518 +end + +def fun_l4_n160() + fun_l5_n607 +end + +def fun_l4_n161() + fun_l5_n823 +end + +def fun_l4_n162() + fun_l5_n816 +end + +def fun_l4_n163() + fun_l5_n735 +end + +def fun_l4_n164() + fun_l5_n802 +end + +def fun_l4_n165() + fun_l5_n398 +end + +def fun_l4_n166() + fun_l5_n149 +end + +def fun_l4_n167() + fun_l5_n292 +end + +def fun_l4_n168() + fun_l5_n733 +end + +def fun_l4_n169() + fun_l5_n145 +end + +def fun_l4_n170() + fun_l5_n288 +end + +def fun_l4_n171() + fun_l5_n131 +end + +def fun_l4_n172() + fun_l5_n31 +end + +def fun_l4_n173() + fun_l5_n253 +end + +def fun_l4_n174() + fun_l5_n41 +end + +def fun_l4_n175() + fun_l5_n403 +end + +def fun_l4_n176() + fun_l5_n859 +end + +def fun_l4_n177() + fun_l5_n804 +end + +def fun_l4_n178() + fun_l5_n26 +end + +def fun_l4_n179() + fun_l5_n729 +end + +def fun_l4_n180() + fun_l5_n978 +end + +def fun_l4_n181() + fun_l5_n42 +end + +def fun_l4_n182() + fun_l5_n38 +end + +def fun_l4_n183() + fun_l5_n758 +end + +def fun_l4_n184() + fun_l5_n885 +end + +def fun_l4_n185() + fun_l5_n473 +end + +def fun_l4_n186() + fun_l5_n737 +end + +def fun_l4_n187() + fun_l5_n889 +end + +def fun_l4_n188() + fun_l5_n398 +end + +def fun_l4_n189() + fun_l5_n72 +end + +def fun_l4_n190() + fun_l5_n725 +end + +def fun_l4_n191() + fun_l5_n774 +end + +def fun_l4_n192() + fun_l5_n453 +end + +def fun_l4_n193() + fun_l5_n370 +end + +def fun_l4_n194() + fun_l5_n648 +end + +def fun_l4_n195() + fun_l5_n882 +end + +def fun_l4_n196() + fun_l5_n745 +end + +def fun_l4_n197() + fun_l5_n529 +end + +def fun_l4_n198() + fun_l5_n957 +end + +def fun_l4_n199() + fun_l5_n423 +end + +def fun_l4_n200() + fun_l5_n399 +end + +def fun_l4_n201() + fun_l5_n917 +end + +def fun_l4_n202() + fun_l5_n634 +end + +def fun_l4_n203() + fun_l5_n868 +end + +def fun_l4_n204() + fun_l5_n627 +end + +def fun_l4_n205() + fun_l5_n514 +end + +def fun_l4_n206() + fun_l5_n61 +end + +def fun_l4_n207() + fun_l5_n848 +end + +def fun_l4_n208() + fun_l5_n611 +end + +def fun_l4_n209() + fun_l5_n417 +end + +def fun_l4_n210() + fun_l5_n423 +end + +def fun_l4_n211() + fun_l5_n247 +end + +def fun_l4_n212() + fun_l5_n208 +end + +def fun_l4_n213() + fun_l5_n253 +end + +def fun_l4_n214() + fun_l5_n833 +end + +def fun_l4_n215() + fun_l5_n351 +end + +def fun_l4_n216() + fun_l5_n326 +end + +def fun_l4_n217() + fun_l5_n741 +end + +def fun_l4_n218() + fun_l5_n958 +end + +def fun_l4_n219() + fun_l5_n347 +end + +def fun_l4_n220() + fun_l5_n317 +end + +def fun_l4_n221() + fun_l5_n291 +end + +def fun_l4_n222() + fun_l5_n863 +end + +def fun_l4_n223() + fun_l5_n30 +end + +def fun_l4_n224() + fun_l5_n413 +end + +def fun_l4_n225() + fun_l5_n352 +end + +def fun_l4_n226() + fun_l5_n125 +end + +def fun_l4_n227() + fun_l5_n266 +end + +def fun_l4_n228() + fun_l5_n264 +end + +def fun_l4_n229() + fun_l5_n745 +end + +def fun_l4_n230() + fun_l5_n622 +end + +def fun_l4_n231() + fun_l5_n160 +end + +def fun_l4_n232() + fun_l5_n121 +end + +def fun_l4_n233() + fun_l5_n150 +end + +def fun_l4_n234() + fun_l5_n495 +end + +def fun_l4_n235() + fun_l5_n905 +end + +def fun_l4_n236() + fun_l5_n886 +end + +def fun_l4_n237() + fun_l5_n221 +end + +def fun_l4_n238() + fun_l5_n912 +end + +def fun_l4_n239() + fun_l5_n834 +end + +def fun_l4_n240() + fun_l5_n703 +end + +def fun_l4_n241() + fun_l5_n651 +end + +def fun_l4_n242() + fun_l5_n404 +end + +def fun_l4_n243() + fun_l5_n213 +end + +def fun_l4_n244() + fun_l5_n342 +end + +def fun_l4_n245() + fun_l5_n887 +end + +def fun_l4_n246() + fun_l5_n69 +end + +def fun_l4_n247() + fun_l5_n835 +end + +def fun_l4_n248() + fun_l5_n856 +end + +def fun_l4_n249() + fun_l5_n485 +end + +def fun_l4_n250() + fun_l5_n441 +end + +def fun_l4_n251() + fun_l5_n976 +end + +def fun_l4_n252() + fun_l5_n586 +end + +def fun_l4_n253() + fun_l5_n728 +end + +def fun_l4_n254() + fun_l5_n377 +end + +def fun_l4_n255() + fun_l5_n293 +end + +def fun_l4_n256() + fun_l5_n149 +end + +def fun_l4_n257() + fun_l5_n205 +end + +def fun_l4_n258() + fun_l5_n301 +end + +def fun_l4_n259() + fun_l5_n528 +end + +def fun_l4_n260() + fun_l5_n642 +end + +def fun_l4_n261() + fun_l5_n430 +end + +def fun_l4_n262() + fun_l5_n14 +end + +def fun_l4_n263() + fun_l5_n796 +end + +def fun_l4_n264() + fun_l5_n849 +end + +def fun_l4_n265() + fun_l5_n547 +end + +def fun_l4_n266() + fun_l5_n946 +end + +def fun_l4_n267() + fun_l5_n131 +end + +def fun_l4_n268() + fun_l5_n141 +end + +def fun_l4_n269() + fun_l5_n9 +end + +def fun_l4_n270() + fun_l5_n884 +end + +def fun_l4_n271() + fun_l5_n978 +end + +def fun_l4_n272() + fun_l5_n47 +end + +def fun_l4_n273() + fun_l5_n100 +end + +def fun_l4_n274() + fun_l5_n254 +end + +def fun_l4_n275() + fun_l5_n972 +end + +def fun_l4_n276() + fun_l5_n705 +end + +def fun_l4_n277() + fun_l5_n504 +end + +def fun_l4_n278() + fun_l5_n854 +end + +def fun_l4_n279() + fun_l5_n331 +end + +def fun_l4_n280() + fun_l5_n394 +end + +def fun_l4_n281() + fun_l5_n922 +end + +def fun_l4_n282() + fun_l5_n503 +end + +def fun_l4_n283() + fun_l5_n854 +end + +def fun_l4_n284() + fun_l5_n679 +end + +def fun_l4_n285() + fun_l5_n317 +end + +def fun_l4_n286() + fun_l5_n753 +end + +def fun_l4_n287() + fun_l5_n154 +end + +def fun_l4_n288() + fun_l5_n184 +end + +def fun_l4_n289() + fun_l5_n416 +end + +def fun_l4_n290() + fun_l5_n426 +end + +def fun_l4_n291() + fun_l5_n186 +end + +def fun_l4_n292() + fun_l5_n527 +end + +def fun_l4_n293() + fun_l5_n483 +end + +def fun_l4_n294() + fun_l5_n718 +end + +def fun_l4_n295() + fun_l5_n469 +end + +def fun_l4_n296() + fun_l5_n842 +end + +def fun_l4_n297() + fun_l5_n998 +end + +def fun_l4_n298() + fun_l5_n964 +end + +def fun_l4_n299() + fun_l5_n377 +end + +def fun_l4_n300() + fun_l5_n9 +end + +def fun_l4_n301() + fun_l5_n234 +end + +def fun_l4_n302() + fun_l5_n813 +end + +def fun_l4_n303() + fun_l5_n211 +end + +def fun_l4_n304() + fun_l5_n593 +end + +def fun_l4_n305() + fun_l5_n847 +end + +def fun_l4_n306() + fun_l5_n628 +end + +def fun_l4_n307() + fun_l5_n827 +end + +def fun_l4_n308() + fun_l5_n417 +end + +def fun_l4_n309() + fun_l5_n958 +end + +def fun_l4_n310() + fun_l5_n838 +end + +def fun_l4_n311() + fun_l5_n712 +end + +def fun_l4_n312() + fun_l5_n615 +end + +def fun_l4_n313() + fun_l5_n693 +end + +def fun_l4_n314() + fun_l5_n708 +end + +def fun_l4_n315() + fun_l5_n525 +end + +def fun_l4_n316() + fun_l5_n943 +end + +def fun_l4_n317() + fun_l5_n959 +end + +def fun_l4_n318() + fun_l5_n316 +end + +def fun_l4_n319() + fun_l5_n424 +end + +def fun_l4_n320() + fun_l5_n391 +end + +def fun_l4_n321() + fun_l5_n303 +end + +def fun_l4_n322() + fun_l5_n159 +end + +def fun_l4_n323() + fun_l5_n853 +end + +def fun_l4_n324() + fun_l5_n525 +end + +def fun_l4_n325() + fun_l5_n390 +end + +def fun_l4_n326() + fun_l5_n225 +end + +def fun_l4_n327() + fun_l5_n983 +end + +def fun_l4_n328() + fun_l5_n509 +end + +def fun_l4_n329() + fun_l5_n141 +end + +def fun_l4_n330() + fun_l5_n92 +end + +def fun_l4_n331() + fun_l5_n288 +end + +def fun_l4_n332() + fun_l5_n213 +end + +def fun_l4_n333() + fun_l5_n830 +end + +def fun_l4_n334() + fun_l5_n512 +end + +def fun_l4_n335() + fun_l5_n449 +end + +def fun_l4_n336() + fun_l5_n148 +end + +def fun_l4_n337() + fun_l5_n829 +end + +def fun_l4_n338() + fun_l5_n232 +end + +def fun_l4_n339() + fun_l5_n989 +end + +def fun_l4_n340() + fun_l5_n226 +end + +def fun_l4_n341() + fun_l5_n187 +end + +def fun_l4_n342() + fun_l5_n874 +end + +def fun_l4_n343() + fun_l5_n621 +end + +def fun_l4_n344() + fun_l5_n861 +end + +def fun_l4_n345() + fun_l5_n22 +end + +def fun_l4_n346() + fun_l5_n6 +end + +def fun_l4_n347() + fun_l5_n580 +end + +def fun_l4_n348() + fun_l5_n56 +end + +def fun_l4_n349() + fun_l5_n834 +end + +def fun_l4_n350() + fun_l5_n460 +end + +def fun_l4_n351() + fun_l5_n697 +end + +def fun_l4_n352() + fun_l5_n792 +end + +def fun_l4_n353() + fun_l5_n777 +end + +def fun_l4_n354() + fun_l5_n73 +end + +def fun_l4_n355() + fun_l5_n555 +end + +def fun_l4_n356() + fun_l5_n32 +end + +def fun_l4_n357() + fun_l5_n242 +end + +def fun_l4_n358() + fun_l5_n791 +end + +def fun_l4_n359() + fun_l5_n570 +end + +def fun_l4_n360() + fun_l5_n272 +end + +def fun_l4_n361() + fun_l5_n757 +end + +def fun_l4_n362() + fun_l5_n946 +end + +def fun_l4_n363() + fun_l5_n127 +end + +def fun_l4_n364() + fun_l5_n940 +end + +def fun_l4_n365() + fun_l5_n662 +end + +def fun_l4_n366() + fun_l5_n99 +end + +def fun_l4_n367() + fun_l5_n107 +end + +def fun_l4_n368() + fun_l5_n370 +end + +def fun_l4_n369() + fun_l5_n738 +end + +def fun_l4_n370() + fun_l5_n346 +end + +def fun_l4_n371() + fun_l5_n63 +end + +def fun_l4_n372() + fun_l5_n274 +end + +def fun_l4_n373() + fun_l5_n936 +end + +def fun_l4_n374() + fun_l5_n602 +end + +def fun_l4_n375() + fun_l5_n362 +end + +def fun_l4_n376() + fun_l5_n605 +end + +def fun_l4_n377() + fun_l5_n477 +end + +def fun_l4_n378() + fun_l5_n349 +end + +def fun_l4_n379() + fun_l5_n241 +end + +def fun_l4_n380() + fun_l5_n913 +end + +def fun_l4_n381() + fun_l5_n392 +end + +def fun_l4_n382() + fun_l5_n669 +end + +def fun_l4_n383() + fun_l5_n41 +end + +def fun_l4_n384() + fun_l5_n928 +end + +def fun_l4_n385() + fun_l5_n646 +end + +def fun_l4_n386() + fun_l5_n23 +end + +def fun_l4_n387() + fun_l5_n815 +end + +def fun_l4_n388() + fun_l5_n595 +end + +def fun_l4_n389() + fun_l5_n210 +end + +def fun_l4_n390() + fun_l5_n247 +end + +def fun_l4_n391() + fun_l5_n914 +end + +def fun_l4_n392() + fun_l5_n882 +end + +def fun_l4_n393() + fun_l5_n319 +end + +def fun_l4_n394() + fun_l5_n764 +end + +def fun_l4_n395() + fun_l5_n282 +end + +def fun_l4_n396() + fun_l5_n585 +end + +def fun_l4_n397() + fun_l5_n551 +end + +def fun_l4_n398() + fun_l5_n56 +end + +def fun_l4_n399() + fun_l5_n807 +end + +def fun_l4_n400() + fun_l5_n678 +end + +def fun_l4_n401() + fun_l5_n153 +end + +def fun_l4_n402() + fun_l5_n993 +end + +def fun_l4_n403() + fun_l5_n835 +end + +def fun_l4_n404() + fun_l5_n642 +end + +def fun_l4_n405() + fun_l5_n460 +end + +def fun_l4_n406() + fun_l5_n135 +end + +def fun_l4_n407() + fun_l5_n199 +end + +def fun_l4_n408() + fun_l5_n782 +end + +def fun_l4_n409() + fun_l5_n723 +end + +def fun_l4_n410() + fun_l5_n638 +end + +def fun_l4_n411() + fun_l5_n157 +end + +def fun_l4_n412() + fun_l5_n840 +end + +def fun_l4_n413() + fun_l5_n11 +end + +def fun_l4_n414() + fun_l5_n148 +end + +def fun_l4_n415() + fun_l5_n577 +end + +def fun_l4_n416() + fun_l5_n403 +end + +def fun_l4_n417() + fun_l5_n971 +end + +def fun_l4_n418() + fun_l5_n951 +end + +def fun_l4_n419() + fun_l5_n620 +end + +def fun_l4_n420() + fun_l5_n120 +end + +def fun_l4_n421() + fun_l5_n981 +end + +def fun_l4_n422() + fun_l5_n543 +end + +def fun_l4_n423() + fun_l5_n543 +end + +def fun_l4_n424() + fun_l5_n161 +end + +def fun_l4_n425() + fun_l5_n308 +end + +def fun_l4_n426() + fun_l5_n94 +end + +def fun_l4_n427() + fun_l5_n209 +end + +def fun_l4_n428() + fun_l5_n543 +end + +def fun_l4_n429() + fun_l5_n825 +end + +def fun_l4_n430() + fun_l5_n808 +end + +def fun_l4_n431() + fun_l5_n315 +end + +def fun_l4_n432() + fun_l5_n846 +end + +def fun_l4_n433() + fun_l5_n448 +end + +def fun_l4_n434() + fun_l5_n903 +end + +def fun_l4_n435() + fun_l5_n933 +end + +def fun_l4_n436() + fun_l5_n872 +end + +def fun_l4_n437() + fun_l5_n297 +end + +def fun_l4_n438() + fun_l5_n689 +end + +def fun_l4_n439() + fun_l5_n700 +end + +def fun_l4_n440() + fun_l5_n316 +end + +def fun_l4_n441() + fun_l5_n983 +end + +def fun_l4_n442() + fun_l5_n32 +end + +def fun_l4_n443() + fun_l5_n404 +end + +def fun_l4_n444() + fun_l5_n770 +end + +def fun_l4_n445() + fun_l5_n497 +end + +def fun_l4_n446() + fun_l5_n762 +end + +def fun_l4_n447() + fun_l5_n402 +end + +def fun_l4_n448() + fun_l5_n773 +end + +def fun_l4_n449() + fun_l5_n264 +end + +def fun_l4_n450() + fun_l5_n373 +end + +def fun_l4_n451() + fun_l5_n907 +end + +def fun_l4_n452() + fun_l5_n477 +end + +def fun_l4_n453() + fun_l5_n15 +end + +def fun_l4_n454() + fun_l5_n550 +end + +def fun_l4_n455() + fun_l5_n973 +end + +def fun_l4_n456() + fun_l5_n247 +end + +def fun_l4_n457() + fun_l5_n231 +end + +def fun_l4_n458() + fun_l5_n431 +end + +def fun_l4_n459() + fun_l5_n549 +end + +def fun_l4_n460() + fun_l5_n251 +end + +def fun_l4_n461() + fun_l5_n313 +end + +def fun_l4_n462() + fun_l5_n826 +end + +def fun_l4_n463() + fun_l5_n454 +end + +def fun_l4_n464() + fun_l5_n329 +end + +def fun_l4_n465() + fun_l5_n502 +end + +def fun_l4_n466() + fun_l5_n786 +end + +def fun_l4_n467() + fun_l5_n195 +end + +def fun_l4_n468() + fun_l5_n710 +end + +def fun_l4_n469() + fun_l5_n970 +end + +def fun_l4_n470() + fun_l5_n925 +end + +def fun_l4_n471() + fun_l5_n420 +end + +def fun_l4_n472() + fun_l5_n231 +end + +def fun_l4_n473() + fun_l5_n867 +end + +def fun_l4_n474() + fun_l5_n798 +end + +def fun_l4_n475() + fun_l5_n697 +end + +def fun_l4_n476() + fun_l5_n767 +end + +def fun_l4_n477() + fun_l5_n199 +end + +def fun_l4_n478() + fun_l5_n190 +end + +def fun_l4_n479() + fun_l5_n524 +end + +def fun_l4_n480() + fun_l5_n451 +end + +def fun_l4_n481() + fun_l5_n182 +end + +def fun_l4_n482() + fun_l5_n906 +end + +def fun_l4_n483() + fun_l5_n806 +end + +def fun_l4_n484() + fun_l5_n871 +end + +def fun_l4_n485() + fun_l5_n947 +end + +def fun_l4_n486() + fun_l5_n599 +end + +def fun_l4_n487() + fun_l5_n266 +end + +def fun_l4_n488() + fun_l5_n20 +end + +def fun_l4_n489() + fun_l5_n875 +end + +def fun_l4_n490() + fun_l5_n393 +end + +def fun_l4_n491() + fun_l5_n673 +end + +def fun_l4_n492() + fun_l5_n159 +end + +def fun_l4_n493() + fun_l5_n327 +end + +def fun_l4_n494() + fun_l5_n71 +end + +def fun_l4_n495() + fun_l5_n146 +end + +def fun_l4_n496() + fun_l5_n372 +end + +def fun_l4_n497() + fun_l5_n654 +end + +def fun_l4_n498() + fun_l5_n1 +end + +def fun_l4_n499() + fun_l5_n448 +end + +def fun_l4_n500() + fun_l5_n684 +end + +def fun_l4_n501() + fun_l5_n561 +end + +def fun_l4_n502() + fun_l5_n47 +end + +def fun_l4_n503() + fun_l5_n313 +end + +def fun_l4_n504() + fun_l5_n380 +end + +def fun_l4_n505() + fun_l5_n416 +end + +def fun_l4_n506() + fun_l5_n90 +end + +def fun_l4_n507() + fun_l5_n65 +end + +def fun_l4_n508() + fun_l5_n61 +end + +def fun_l4_n509() + fun_l5_n451 +end + +def fun_l4_n510() + fun_l5_n174 +end + +def fun_l4_n511() + fun_l5_n236 +end + +def fun_l4_n512() + fun_l5_n470 +end + +def fun_l4_n513() + fun_l5_n304 +end + +def fun_l4_n514() + fun_l5_n146 +end + +def fun_l4_n515() + fun_l5_n671 +end + +def fun_l4_n516() + fun_l5_n626 +end + +def fun_l4_n517() + fun_l5_n164 +end + +def fun_l4_n518() + fun_l5_n308 +end + +def fun_l4_n519() + fun_l5_n799 +end + +def fun_l4_n520() + fun_l5_n521 +end + +def fun_l4_n521() + fun_l5_n675 +end + +def fun_l4_n522() + fun_l5_n110 +end + +def fun_l4_n523() + fun_l5_n726 +end + +def fun_l4_n524() + fun_l5_n189 +end + +def fun_l4_n525() + fun_l5_n303 +end + +def fun_l4_n526() + fun_l5_n571 +end + +def fun_l4_n527() + fun_l5_n693 +end + +def fun_l4_n528() + fun_l5_n782 +end + +def fun_l4_n529() + fun_l5_n764 +end + +def fun_l4_n530() + fun_l5_n629 +end + +def fun_l4_n531() + fun_l5_n677 +end + +def fun_l4_n532() + fun_l5_n745 +end + +def fun_l4_n533() + fun_l5_n868 +end + +def fun_l4_n534() + fun_l5_n771 +end + +def fun_l4_n535() + fun_l5_n248 +end + +def fun_l4_n536() + fun_l5_n412 +end + +def fun_l4_n537() + fun_l5_n736 +end + +def fun_l4_n538() + fun_l5_n296 +end + +def fun_l4_n539() + fun_l5_n847 +end + +def fun_l4_n540() + fun_l5_n188 +end + +def fun_l4_n541() + fun_l5_n131 +end + +def fun_l4_n542() + fun_l5_n31 +end + +def fun_l4_n543() + fun_l5_n563 +end + +def fun_l4_n544() + fun_l5_n479 +end + +def fun_l4_n545() + fun_l5_n243 +end + +def fun_l4_n546() + fun_l5_n471 +end + +def fun_l4_n547() + fun_l5_n237 +end + +def fun_l4_n548() + fun_l5_n772 +end + +def fun_l4_n549() + fun_l5_n723 +end + +def fun_l4_n550() + fun_l5_n733 +end + +def fun_l4_n551() + fun_l5_n274 +end + +def fun_l4_n552() + fun_l5_n351 +end + +def fun_l4_n553() + fun_l5_n30 +end + +def fun_l4_n554() + fun_l5_n112 +end + +def fun_l4_n555() + fun_l5_n438 +end + +def fun_l4_n556() + fun_l5_n969 +end + +def fun_l4_n557() + fun_l5_n57 +end + +def fun_l4_n558() + fun_l5_n971 +end + +def fun_l4_n559() + fun_l5_n831 +end + +def fun_l4_n560() + fun_l5_n833 +end + +def fun_l4_n561() + fun_l5_n896 +end + +def fun_l4_n562() + fun_l5_n607 +end + +def fun_l4_n563() + fun_l5_n793 +end + +def fun_l4_n564() + fun_l5_n711 +end + +def fun_l4_n565() + fun_l5_n570 +end + +def fun_l4_n566() + fun_l5_n933 +end + +def fun_l4_n567() + fun_l5_n917 +end + +def fun_l4_n568() + fun_l5_n811 +end + +def fun_l4_n569() + fun_l5_n414 +end + +def fun_l4_n570() + fun_l5_n14 +end + +def fun_l4_n571() + fun_l5_n911 +end + +def fun_l4_n572() + fun_l5_n114 +end + +def fun_l4_n573() + fun_l5_n732 +end + +def fun_l4_n574() + fun_l5_n913 +end + +def fun_l4_n575() + fun_l5_n66 +end + +def fun_l4_n576() + fun_l5_n330 +end + +def fun_l4_n577() + fun_l5_n892 +end + +def fun_l4_n578() + fun_l5_n329 +end + +def fun_l4_n579() + fun_l5_n539 +end + +def fun_l4_n580() + fun_l5_n268 +end + +def fun_l4_n581() + fun_l5_n357 +end + +def fun_l4_n582() + fun_l5_n259 +end + +def fun_l4_n583() + fun_l5_n968 +end + +def fun_l4_n584() + fun_l5_n873 +end + +def fun_l4_n585() + fun_l5_n644 +end + +def fun_l4_n586() + fun_l5_n659 +end + +def fun_l4_n587() + fun_l5_n906 +end + +def fun_l4_n588() + fun_l5_n746 +end + +def fun_l4_n589() + fun_l5_n802 +end + +def fun_l4_n590() + fun_l5_n9 +end + +def fun_l4_n591() + fun_l5_n620 +end + +def fun_l4_n592() + fun_l5_n507 +end + +def fun_l4_n593() + fun_l5_n338 +end + +def fun_l4_n594() + fun_l5_n396 +end + +def fun_l4_n595() + fun_l5_n627 +end + +def fun_l4_n596() + fun_l5_n621 +end + +def fun_l4_n597() + fun_l5_n597 +end + +def fun_l4_n598() + fun_l5_n496 +end + +def fun_l4_n599() + fun_l5_n265 +end + +def fun_l4_n600() + fun_l5_n897 +end + +def fun_l4_n601() + fun_l5_n142 +end + +def fun_l4_n602() + fun_l5_n614 +end + +def fun_l4_n603() + fun_l5_n565 +end + +def fun_l4_n604() + fun_l5_n653 +end + +def fun_l4_n605() + fun_l5_n728 +end + +def fun_l4_n606() + fun_l5_n799 +end + +def fun_l4_n607() + fun_l5_n714 +end + +def fun_l4_n608() + fun_l5_n448 +end + +def fun_l4_n609() + fun_l5_n778 +end + +def fun_l4_n610() + fun_l5_n508 +end + +def fun_l4_n611() + fun_l5_n216 +end + +def fun_l4_n612() + fun_l5_n604 +end + +def fun_l4_n613() + fun_l5_n231 +end + +def fun_l4_n614() + fun_l5_n696 +end + +def fun_l4_n615() + fun_l5_n354 +end + +def fun_l4_n616() + fun_l5_n595 +end + +def fun_l4_n617() + fun_l5_n747 +end + +def fun_l4_n618() + fun_l5_n377 +end + +def fun_l4_n619() + fun_l5_n852 +end + +def fun_l4_n620() + fun_l5_n381 +end + +def fun_l4_n621() + fun_l5_n674 +end + +def fun_l4_n622() + fun_l5_n696 +end + +def fun_l4_n623() + fun_l5_n25 +end + +def fun_l4_n624() + fun_l5_n133 +end + +def fun_l4_n625() + fun_l5_n419 +end + +def fun_l4_n626() + fun_l5_n612 +end + +def fun_l4_n627() + fun_l5_n798 +end + +def fun_l4_n628() + fun_l5_n702 +end + +def fun_l4_n629() + fun_l5_n125 +end + +def fun_l4_n630() + fun_l5_n567 +end + +def fun_l4_n631() + fun_l5_n825 +end + +def fun_l4_n632() + fun_l5_n794 +end + +def fun_l4_n633() + fun_l5_n802 +end + +def fun_l4_n634() + fun_l5_n297 +end + +def fun_l4_n635() + fun_l5_n366 +end + +def fun_l4_n636() + fun_l5_n149 +end + +def fun_l4_n637() + fun_l5_n648 +end + +def fun_l4_n638() + fun_l5_n997 +end + +def fun_l4_n639() + fun_l5_n569 +end + +def fun_l4_n640() + fun_l5_n917 +end + +def fun_l4_n641() + fun_l5_n172 +end + +def fun_l4_n642() + fun_l5_n353 +end + +def fun_l4_n643() + fun_l5_n940 +end + +def fun_l4_n644() + fun_l5_n255 +end + +def fun_l4_n645() + fun_l5_n690 +end + +def fun_l4_n646() + fun_l5_n17 +end + +def fun_l4_n647() + fun_l5_n320 +end + +def fun_l4_n648() + fun_l5_n328 +end + +def fun_l4_n649() + fun_l5_n467 +end + +def fun_l4_n650() + fun_l5_n352 +end + +def fun_l4_n651() + fun_l5_n671 +end + +def fun_l4_n652() + fun_l5_n104 +end + +def fun_l4_n653() + fun_l5_n40 +end + +def fun_l4_n654() + fun_l5_n445 +end + +def fun_l4_n655() + fun_l5_n703 +end + +def fun_l4_n656() + fun_l5_n699 +end + +def fun_l4_n657() + fun_l5_n156 +end + +def fun_l4_n658() + fun_l5_n1 +end + +def fun_l4_n659() + fun_l5_n728 +end + +def fun_l4_n660() + fun_l5_n200 +end + +def fun_l4_n661() + fun_l5_n369 +end + +def fun_l4_n662() + fun_l5_n621 +end + +def fun_l4_n663() + fun_l5_n600 +end + +def fun_l4_n664() + fun_l5_n342 +end + +def fun_l4_n665() + fun_l5_n129 +end + +def fun_l4_n666() + fun_l5_n627 +end + +def fun_l4_n667() + fun_l5_n44 +end + +def fun_l4_n668() + fun_l5_n43 +end + +def fun_l4_n669() + fun_l5_n708 +end + +def fun_l4_n670() + fun_l5_n378 +end + +def fun_l4_n671() + fun_l5_n320 +end + +def fun_l4_n672() + fun_l5_n896 +end + +def fun_l4_n673() + fun_l5_n185 +end + +def fun_l4_n674() + fun_l5_n456 +end + +def fun_l4_n675() + fun_l5_n520 +end + +def fun_l4_n676() + fun_l5_n633 +end + +def fun_l4_n677() + fun_l5_n122 +end + +def fun_l4_n678() + fun_l5_n333 +end + +def fun_l4_n679() + fun_l5_n100 +end + +def fun_l4_n680() + fun_l5_n941 +end + +def fun_l4_n681() + fun_l5_n468 +end + +def fun_l4_n682() + fun_l5_n45 +end + +def fun_l4_n683() + fun_l5_n295 +end + +def fun_l4_n684() + fun_l5_n400 +end + +def fun_l4_n685() + fun_l5_n999 +end + +def fun_l4_n686() + fun_l5_n294 +end + +def fun_l4_n687() + fun_l5_n575 +end + +def fun_l4_n688() + fun_l5_n372 +end + +def fun_l4_n689() + fun_l5_n777 +end + +def fun_l4_n690() + fun_l5_n795 +end + +def fun_l4_n691() + fun_l5_n44 +end + +def fun_l4_n692() + fun_l5_n27 +end + +def fun_l4_n693() + fun_l5_n488 +end + +def fun_l4_n694() + fun_l5_n932 +end + +def fun_l4_n695() + fun_l5_n104 +end + +def fun_l4_n696() + fun_l5_n552 +end + +def fun_l4_n697() + fun_l5_n830 +end + +def fun_l4_n698() + fun_l5_n612 +end + +def fun_l4_n699() + fun_l5_n889 +end + +def fun_l4_n700() + fun_l5_n205 +end + +def fun_l4_n701() + fun_l5_n90 +end + +def fun_l4_n702() + fun_l5_n210 +end + +def fun_l4_n703() + fun_l5_n514 +end + +def fun_l4_n704() + fun_l5_n374 +end + +def fun_l4_n705() + fun_l5_n176 +end + +def fun_l4_n706() + fun_l5_n465 +end + +def fun_l4_n707() + fun_l5_n542 +end + +def fun_l4_n708() + fun_l5_n175 +end + +def fun_l4_n709() + fun_l5_n148 +end + +def fun_l4_n710() + fun_l5_n212 +end + +def fun_l4_n711() + fun_l5_n418 +end + +def fun_l4_n712() + fun_l5_n401 +end + +def fun_l4_n713() + fun_l5_n14 +end + +def fun_l4_n714() + fun_l5_n965 +end + +def fun_l4_n715() + fun_l5_n783 +end + +def fun_l4_n716() + fun_l5_n421 +end + +def fun_l4_n717() + fun_l5_n346 +end + +def fun_l4_n718() + fun_l5_n176 +end + +def fun_l4_n719() + fun_l5_n522 +end + +def fun_l4_n720() + fun_l5_n207 +end + +def fun_l4_n721() + fun_l5_n707 +end + +def fun_l4_n722() + fun_l5_n593 +end + +def fun_l4_n723() + fun_l5_n609 +end + +def fun_l4_n724() + fun_l5_n798 +end + +def fun_l4_n725() + fun_l5_n744 +end + +def fun_l4_n726() + fun_l5_n514 +end + +def fun_l4_n727() + fun_l5_n278 +end + +def fun_l4_n728() + fun_l5_n425 +end + +def fun_l4_n729() + fun_l5_n147 +end + +def fun_l4_n730() + fun_l5_n676 +end + +def fun_l4_n731() + fun_l5_n887 +end + +def fun_l4_n732() + fun_l5_n865 +end + +def fun_l4_n733() + fun_l5_n811 +end + +def fun_l4_n734() + fun_l5_n545 +end + +def fun_l4_n735() + fun_l5_n219 +end + +def fun_l4_n736() + fun_l5_n121 +end + +def fun_l4_n737() + fun_l5_n253 +end + +def fun_l4_n738() + fun_l5_n349 +end + +def fun_l4_n739() + fun_l5_n540 +end + +def fun_l4_n740() + fun_l5_n301 +end + +def fun_l4_n741() + fun_l5_n367 +end + +def fun_l4_n742() + fun_l5_n989 +end + +def fun_l4_n743() + fun_l5_n454 +end + +def fun_l4_n744() + fun_l5_n390 +end + +def fun_l4_n745() + fun_l5_n650 +end + +def fun_l4_n746() + fun_l5_n403 +end + +def fun_l4_n747() + fun_l5_n807 +end + +def fun_l4_n748() + fun_l5_n219 +end + +def fun_l4_n749() + fun_l5_n756 +end + +def fun_l4_n750() + fun_l5_n730 +end + +def fun_l4_n751() + fun_l5_n923 +end + +def fun_l4_n752() + fun_l5_n407 +end + +def fun_l4_n753() + fun_l5_n734 +end + +def fun_l4_n754() + fun_l5_n192 +end + +def fun_l4_n755() + fun_l5_n26 +end + +def fun_l4_n756() + fun_l5_n571 +end + +def fun_l4_n757() + fun_l5_n515 +end + +def fun_l4_n758() + fun_l5_n701 +end + +def fun_l4_n759() + fun_l5_n808 +end + +def fun_l4_n760() + fun_l5_n607 +end + +def fun_l4_n761() + fun_l5_n231 +end + +def fun_l4_n762() + fun_l5_n144 +end + +def fun_l4_n763() + fun_l5_n829 +end + +def fun_l4_n764() + fun_l5_n939 +end + +def fun_l4_n765() + fun_l5_n486 +end + +def fun_l4_n766() + fun_l5_n73 +end + +def fun_l4_n767() + fun_l5_n409 +end + +def fun_l4_n768() + fun_l5_n197 +end + +def fun_l4_n769() + fun_l5_n803 +end + +def fun_l4_n770() + fun_l5_n877 +end + +def fun_l4_n771() + fun_l5_n739 +end + +def fun_l4_n772() + fun_l5_n500 +end + +def fun_l4_n773() + fun_l5_n104 +end + +def fun_l4_n774() + fun_l5_n526 +end + +def fun_l4_n775() + fun_l5_n443 +end + +def fun_l4_n776() + fun_l5_n397 +end + +def fun_l4_n777() + fun_l5_n496 +end + +def fun_l4_n778() + fun_l5_n360 +end + +def fun_l4_n779() + fun_l5_n93 +end + +def fun_l4_n780() + fun_l5_n635 +end + +def fun_l4_n781() + fun_l5_n724 +end + +def fun_l4_n782() + fun_l5_n445 +end + +def fun_l4_n783() + fun_l5_n546 +end + +def fun_l4_n784() + fun_l5_n353 +end + +def fun_l4_n785() + fun_l5_n546 +end + +def fun_l4_n786() + fun_l5_n243 +end + +def fun_l4_n787() + fun_l5_n614 +end + +def fun_l4_n788() + fun_l5_n249 +end + +def fun_l4_n789() + fun_l5_n281 +end + +def fun_l4_n790() + fun_l5_n22 +end + +def fun_l4_n791() + fun_l5_n857 +end + +def fun_l4_n792() + fun_l5_n685 +end + +def fun_l4_n793() + fun_l5_n784 +end + +def fun_l4_n794() + fun_l5_n522 +end + +def fun_l4_n795() + fun_l5_n970 +end + +def fun_l4_n796() + fun_l5_n734 +end + +def fun_l4_n797() + fun_l5_n36 +end + +def fun_l4_n798() + fun_l5_n257 +end + +def fun_l4_n799() + fun_l5_n677 +end + +def fun_l4_n800() + fun_l5_n556 +end + +def fun_l4_n801() + fun_l5_n783 +end + +def fun_l4_n802() + fun_l5_n501 +end + +def fun_l4_n803() + fun_l5_n731 +end + +def fun_l4_n804() + fun_l5_n175 +end + +def fun_l4_n805() + fun_l5_n712 +end + +def fun_l4_n806() + fun_l5_n566 +end + +def fun_l4_n807() + fun_l5_n158 +end + +def fun_l4_n808() + fun_l5_n63 +end + +def fun_l4_n809() + fun_l5_n354 +end + +def fun_l4_n810() + fun_l5_n552 +end + +def fun_l4_n811() + fun_l5_n255 +end + +def fun_l4_n812() + fun_l5_n830 +end + +def fun_l4_n813() + fun_l5_n792 +end + +def fun_l4_n814() + fun_l5_n214 +end + +def fun_l4_n815() + fun_l5_n906 +end + +def fun_l4_n816() + fun_l5_n852 +end + +def fun_l4_n817() + fun_l5_n286 +end + +def fun_l4_n818() + fun_l5_n704 +end + +def fun_l4_n819() + fun_l5_n860 +end + +def fun_l4_n820() + fun_l5_n150 +end + +def fun_l4_n821() + fun_l5_n793 +end + +def fun_l4_n822() + fun_l5_n356 +end + +def fun_l4_n823() + fun_l5_n369 +end + +def fun_l4_n824() + fun_l5_n519 +end + +def fun_l4_n825() + fun_l5_n765 +end + +def fun_l4_n826() + fun_l5_n974 +end + +def fun_l4_n827() + fun_l5_n265 +end + +def fun_l4_n828() + fun_l5_n948 +end + +def fun_l4_n829() + fun_l5_n2 +end + +def fun_l4_n830() + fun_l5_n269 +end + +def fun_l4_n831() + fun_l5_n96 +end + +def fun_l4_n832() + fun_l5_n964 +end + +def fun_l4_n833() + fun_l5_n362 +end + +def fun_l4_n834() + fun_l5_n915 +end + +def fun_l4_n835() + fun_l5_n179 +end + +def fun_l4_n836() + fun_l5_n128 +end + +def fun_l4_n837() + fun_l5_n195 +end + +def fun_l4_n838() + fun_l5_n393 +end + +def fun_l4_n839() + fun_l5_n120 +end + +def fun_l4_n840() + fun_l5_n239 +end + +def fun_l4_n841() + fun_l5_n669 +end + +def fun_l4_n842() + fun_l5_n234 +end + +def fun_l4_n843() + fun_l5_n60 +end + +def fun_l4_n844() + fun_l5_n962 +end + +def fun_l4_n845() + fun_l5_n770 +end + +def fun_l4_n846() + fun_l5_n207 +end + +def fun_l4_n847() + fun_l5_n46 +end + +def fun_l4_n848() + fun_l5_n615 +end + +def fun_l4_n849() + fun_l5_n709 +end + +def fun_l4_n850() + fun_l5_n198 +end + +def fun_l4_n851() + fun_l5_n639 +end + +def fun_l4_n852() + fun_l5_n125 +end + +def fun_l4_n853() + fun_l5_n193 +end + +def fun_l4_n854() + fun_l5_n806 +end + +def fun_l4_n855() + fun_l5_n237 +end + +def fun_l4_n856() + fun_l5_n319 +end + +def fun_l4_n857() + fun_l5_n533 +end + +def fun_l4_n858() + fun_l5_n320 +end + +def fun_l4_n859() + fun_l5_n501 +end + +def fun_l4_n860() + fun_l5_n404 +end + +def fun_l4_n861() + fun_l5_n849 +end + +def fun_l4_n862() + fun_l5_n743 +end + +def fun_l4_n863() + fun_l5_n764 +end + +def fun_l4_n864() + fun_l5_n956 +end + +def fun_l4_n865() + fun_l5_n914 +end + +def fun_l4_n866() + fun_l5_n652 +end + +def fun_l4_n867() + fun_l5_n30 +end + +def fun_l4_n868() + fun_l5_n330 +end + +def fun_l4_n869() + fun_l5_n677 +end + +def fun_l4_n870() + fun_l5_n988 +end + +def fun_l4_n871() + fun_l5_n676 +end + +def fun_l4_n872() + fun_l5_n752 +end + +def fun_l4_n873() + fun_l5_n636 +end + +def fun_l4_n874() + fun_l5_n395 +end + +def fun_l4_n875() + fun_l5_n428 +end + +def fun_l4_n876() + fun_l5_n83 +end + +def fun_l4_n877() + fun_l5_n712 +end + +def fun_l4_n878() + fun_l5_n708 +end + +def fun_l4_n879() + fun_l5_n418 +end + +def fun_l4_n880() + fun_l5_n265 +end + +def fun_l4_n881() + fun_l5_n379 +end + +def fun_l4_n882() + fun_l5_n758 +end + +def fun_l4_n883() + fun_l5_n251 +end + +def fun_l4_n884() + fun_l5_n723 +end + +def fun_l4_n885() + fun_l5_n216 +end + +def fun_l4_n886() + fun_l5_n197 +end + +def fun_l4_n887() + fun_l5_n261 +end + +def fun_l4_n888() + fun_l5_n62 +end + +def fun_l4_n889() + fun_l5_n941 +end + +def fun_l4_n890() + fun_l5_n535 +end + +def fun_l4_n891() + fun_l5_n727 +end + +def fun_l4_n892() + fun_l5_n279 +end + +def fun_l4_n893() + fun_l5_n541 +end + +def fun_l4_n894() + fun_l5_n684 +end + +def fun_l4_n895() + fun_l5_n649 +end + +def fun_l4_n896() + fun_l5_n396 +end + +def fun_l4_n897() + fun_l5_n992 +end + +def fun_l4_n898() + fun_l5_n160 +end + +def fun_l4_n899() + fun_l5_n84 +end + +def fun_l4_n900() + fun_l5_n318 +end + +def fun_l4_n901() + fun_l5_n428 +end + +def fun_l4_n902() + fun_l5_n534 +end + +def fun_l4_n903() + fun_l5_n25 +end + +def fun_l4_n904() + fun_l5_n392 +end + +def fun_l4_n905() + fun_l5_n926 +end + +def fun_l4_n906() + fun_l5_n724 +end + +def fun_l4_n907() + fun_l5_n311 +end + +def fun_l4_n908() + fun_l5_n535 +end + +def fun_l4_n909() + fun_l5_n179 +end + +def fun_l4_n910() + fun_l5_n533 +end + +def fun_l4_n911() + fun_l5_n875 +end + +def fun_l4_n912() + fun_l5_n105 +end + +def fun_l4_n913() + fun_l5_n618 +end + +def fun_l4_n914() + fun_l5_n827 +end + +def fun_l4_n915() + fun_l5_n555 +end + +def fun_l4_n916() + fun_l5_n339 +end + +def fun_l4_n917() + fun_l5_n848 +end + +def fun_l4_n918() + fun_l5_n676 +end + +def fun_l4_n919() + fun_l5_n204 +end + +def fun_l4_n920() + fun_l5_n769 +end + +def fun_l4_n921() + fun_l5_n229 +end + +def fun_l4_n922() + fun_l5_n92 +end + +def fun_l4_n923() + fun_l5_n973 +end + +def fun_l4_n924() + fun_l5_n700 +end + +def fun_l4_n925() + fun_l5_n581 +end + +def fun_l4_n926() + fun_l5_n138 +end + +def fun_l4_n927() + fun_l5_n43 +end + +def fun_l4_n928() + fun_l5_n537 +end + +def fun_l4_n929() + fun_l5_n882 +end + +def fun_l4_n930() + fun_l5_n871 +end + +def fun_l4_n931() + fun_l5_n158 +end + +def fun_l4_n932() + fun_l5_n542 +end + +def fun_l4_n933() + fun_l5_n468 +end + +def fun_l4_n934() + fun_l5_n28 +end + +def fun_l4_n935() + fun_l5_n976 +end + +def fun_l4_n936() + fun_l5_n632 +end + +def fun_l4_n937() + fun_l5_n857 +end + +def fun_l4_n938() + fun_l5_n841 +end + +def fun_l4_n939() + fun_l5_n762 +end + +def fun_l4_n940() + fun_l5_n522 +end + +def fun_l4_n941() + fun_l5_n841 +end + +def fun_l4_n942() + fun_l5_n42 +end + +def fun_l4_n943() + fun_l5_n771 +end + +def fun_l4_n944() + fun_l5_n145 +end + +def fun_l4_n945() + fun_l5_n435 +end + +def fun_l4_n946() + fun_l5_n573 +end + +def fun_l4_n947() + fun_l5_n422 +end + +def fun_l4_n948() + fun_l5_n34 +end + +def fun_l4_n949() + fun_l5_n577 +end + +def fun_l4_n950() + fun_l5_n156 +end + +def fun_l4_n951() + fun_l5_n707 +end + +def fun_l4_n952() + fun_l5_n198 +end + +def fun_l4_n953() + fun_l5_n950 +end + +def fun_l4_n954() + fun_l5_n474 +end + +def fun_l4_n955() + fun_l5_n319 +end + +def fun_l4_n956() + fun_l5_n208 +end + +def fun_l4_n957() + fun_l5_n360 +end + +def fun_l4_n958() + fun_l5_n101 +end + +def fun_l4_n959() + fun_l5_n37 +end + +def fun_l4_n960() + fun_l5_n20 +end + +def fun_l4_n961() + fun_l5_n897 +end + +def fun_l4_n962() + fun_l5_n92 +end + +def fun_l4_n963() + fun_l5_n105 +end + +def fun_l4_n964() + fun_l5_n255 +end + +def fun_l4_n965() + fun_l5_n97 +end + +def fun_l4_n966() + fun_l5_n398 +end + +def fun_l4_n967() + fun_l5_n393 +end + +def fun_l4_n968() + fun_l5_n135 +end + +def fun_l4_n969() + fun_l5_n306 +end + +def fun_l4_n970() + fun_l5_n202 +end + +def fun_l4_n971() + fun_l5_n832 +end + +def fun_l4_n972() + fun_l5_n444 +end + +def fun_l4_n973() + fun_l5_n768 +end + +def fun_l4_n974() + fun_l5_n384 +end + +def fun_l4_n975() + fun_l5_n142 +end + +def fun_l4_n976() + fun_l5_n208 +end + +def fun_l4_n977() + fun_l5_n818 +end + +def fun_l4_n978() + fun_l5_n5 +end + +def fun_l4_n979() + fun_l5_n410 +end + +def fun_l4_n980() + fun_l5_n713 +end + +def fun_l4_n981() + fun_l5_n42 +end + +def fun_l4_n982() + fun_l5_n335 +end + +def fun_l4_n983() + fun_l5_n446 +end + +def fun_l4_n984() + fun_l5_n957 +end + +def fun_l4_n985() + fun_l5_n652 +end + +def fun_l4_n986() + fun_l5_n341 +end + +def fun_l4_n987() + fun_l5_n300 +end + +def fun_l4_n988() + fun_l5_n859 +end + +def fun_l4_n989() + fun_l5_n467 +end + +def fun_l4_n990() + fun_l5_n182 +end + +def fun_l4_n991() + fun_l5_n755 +end + +def fun_l4_n992() + fun_l5_n925 +end + +def fun_l4_n993() + fun_l5_n695 +end + +def fun_l4_n994() + fun_l5_n901 +end + +def fun_l4_n995() + fun_l5_n844 +end + +def fun_l4_n996() + fun_l5_n430 +end + +def fun_l4_n997() + fun_l5_n568 +end + +def fun_l4_n998() + fun_l5_n472 +end + +def fun_l4_n999() + fun_l5_n871 +end + +def fun_l5_n0() + fun_l6_n383 +end + +def fun_l5_n1() + fun_l6_n172 +end + +def fun_l5_n2() + fun_l6_n405 +end + +def fun_l5_n3() + fun_l6_n960 +end + +def fun_l5_n4() + fun_l6_n846 +end + +def fun_l5_n5() + fun_l6_n207 +end + +def fun_l5_n6() + fun_l6_n217 +end + +def fun_l5_n7() + fun_l6_n317 +end + +def fun_l5_n8() + fun_l6_n628 +end + +def fun_l5_n9() + fun_l6_n407 +end + +def fun_l5_n10() + fun_l6_n933 +end + +def fun_l5_n11() + fun_l6_n318 +end + +def fun_l5_n12() + fun_l6_n349 +end + +def fun_l5_n13() + fun_l6_n559 +end + +def fun_l5_n14() + fun_l6_n352 +end + +def fun_l5_n15() + fun_l6_n531 +end + +def fun_l5_n16() + fun_l6_n6 +end + +def fun_l5_n17() + fun_l6_n285 +end + +def fun_l5_n18() + fun_l6_n419 +end + +def fun_l5_n19() + fun_l6_n232 +end + +def fun_l5_n20() + fun_l6_n285 +end + +def fun_l5_n21() + fun_l6_n814 +end + +def fun_l5_n22() + fun_l6_n773 +end + +def fun_l5_n23() + fun_l6_n771 +end + +def fun_l5_n24() + fun_l6_n903 +end + +def fun_l5_n25() + fun_l6_n116 +end + +def fun_l5_n26() + fun_l6_n116 +end + +def fun_l5_n27() + fun_l6_n531 +end + +def fun_l5_n28() + fun_l6_n418 +end + +def fun_l5_n29() + fun_l6_n564 +end + +def fun_l5_n30() + fun_l6_n691 +end + +def fun_l5_n31() + fun_l6_n267 +end + +def fun_l5_n32() + fun_l6_n209 +end + +def fun_l5_n33() + fun_l6_n27 +end + +def fun_l5_n34() + fun_l6_n312 +end + +def fun_l5_n35() + fun_l6_n240 +end + +def fun_l5_n36() + fun_l6_n507 +end + +def fun_l5_n37() + fun_l6_n808 +end + +def fun_l5_n38() + fun_l6_n28 +end + +def fun_l5_n39() + fun_l6_n33 +end + +def fun_l5_n40() + fun_l6_n808 +end + +def fun_l5_n41() + fun_l6_n15 +end + +def fun_l5_n42() + fun_l6_n995 +end + +def fun_l5_n43() + fun_l6_n886 +end + +def fun_l5_n44() + fun_l6_n164 +end + +def fun_l5_n45() + fun_l6_n804 +end + +def fun_l5_n46() + fun_l6_n776 +end + +def fun_l5_n47() + fun_l6_n584 +end + +def fun_l5_n48() + fun_l6_n220 +end + +def fun_l5_n49() + fun_l6_n680 +end + +def fun_l5_n50() + fun_l6_n438 +end + +def fun_l5_n51() + fun_l6_n565 +end + +def fun_l5_n52() + fun_l6_n394 +end + +def fun_l5_n53() + fun_l6_n867 +end + +def fun_l5_n54() + fun_l6_n468 +end + +def fun_l5_n55() + fun_l6_n622 +end + +def fun_l5_n56() + fun_l6_n846 +end + +def fun_l5_n57() + fun_l6_n718 +end + +def fun_l5_n58() + fun_l6_n367 +end + +def fun_l5_n59() + fun_l6_n284 +end + +def fun_l5_n60() + fun_l6_n350 +end + +def fun_l5_n61() + fun_l6_n849 +end + +def fun_l5_n62() + fun_l6_n537 +end + +def fun_l5_n63() + fun_l6_n475 +end + +def fun_l5_n64() + fun_l6_n525 +end + +def fun_l5_n65() + fun_l6_n416 +end + +def fun_l5_n66() + fun_l6_n261 +end + +def fun_l5_n67() + fun_l6_n528 +end + +def fun_l5_n68() + fun_l6_n331 +end + +def fun_l5_n69() + fun_l6_n387 +end + +def fun_l5_n70() + fun_l6_n780 +end + +def fun_l5_n71() + fun_l6_n542 +end + +def fun_l5_n72() + fun_l6_n930 +end + +def fun_l5_n73() + fun_l6_n79 +end + +def fun_l5_n74() + fun_l6_n351 +end + +def fun_l5_n75() + fun_l6_n290 +end + +def fun_l5_n76() + fun_l6_n659 +end + +def fun_l5_n77() + fun_l6_n421 +end + +def fun_l5_n78() + fun_l6_n454 +end + +def fun_l5_n79() + fun_l6_n78 +end + +def fun_l5_n80() + fun_l6_n63 +end + +def fun_l5_n81() + fun_l6_n555 +end + +def fun_l5_n82() + fun_l6_n54 +end + +def fun_l5_n83() + fun_l6_n46 +end + +def fun_l5_n84() + fun_l6_n225 +end + +def fun_l5_n85() + fun_l6_n330 +end + +def fun_l5_n86() + fun_l6_n772 +end + +def fun_l5_n87() + fun_l6_n654 +end + +def fun_l5_n88() + fun_l6_n281 +end + +def fun_l5_n89() + fun_l6_n857 +end + +def fun_l5_n90() + fun_l6_n453 +end + +def fun_l5_n91() + fun_l6_n504 +end + +def fun_l5_n92() + fun_l6_n649 +end + +def fun_l5_n93() + fun_l6_n90 +end + +def fun_l5_n94() + fun_l6_n520 +end + +def fun_l5_n95() + fun_l6_n251 +end + +def fun_l5_n96() + fun_l6_n738 +end + +def fun_l5_n97() + fun_l6_n837 +end + +def fun_l5_n98() + fun_l6_n98 +end + +def fun_l5_n99() + fun_l6_n844 +end + +def fun_l5_n100() + fun_l6_n699 +end + +def fun_l5_n101() + fun_l6_n901 +end + +def fun_l5_n102() + fun_l6_n342 +end + +def fun_l5_n103() + fun_l6_n856 +end + +def fun_l5_n104() + fun_l6_n113 +end + +def fun_l5_n105() + fun_l6_n530 +end + +def fun_l5_n106() + fun_l6_n445 +end + +def fun_l5_n107() + fun_l6_n515 +end + +def fun_l5_n108() + fun_l6_n958 +end + +def fun_l5_n109() + fun_l6_n561 +end + +def fun_l5_n110() + fun_l6_n130 +end + +def fun_l5_n111() + fun_l6_n653 +end + +def fun_l5_n112() + fun_l6_n367 +end + +def fun_l5_n113() + fun_l6_n515 +end + +def fun_l5_n114() + fun_l6_n50 +end + +def fun_l5_n115() + fun_l6_n259 +end + +def fun_l5_n116() + fun_l6_n280 +end + +def fun_l5_n117() + fun_l6_n589 +end + +def fun_l5_n118() + fun_l6_n988 +end + +def fun_l5_n119() + fun_l6_n544 +end + +def fun_l5_n120() + fun_l6_n564 +end + +def fun_l5_n121() + fun_l6_n468 +end + +def fun_l5_n122() + fun_l6_n586 +end + +def fun_l5_n123() + fun_l6_n705 +end + +def fun_l5_n124() + fun_l6_n510 +end + +def fun_l5_n125() + fun_l6_n995 +end + +def fun_l5_n126() + fun_l6_n576 +end + +def fun_l5_n127() + fun_l6_n221 +end + +def fun_l5_n128() + fun_l6_n498 +end + +def fun_l5_n129() + fun_l6_n113 +end + +def fun_l5_n130() + fun_l6_n916 +end + +def fun_l5_n131() + fun_l6_n626 +end + +def fun_l5_n132() + fun_l6_n635 +end + +def fun_l5_n133() + fun_l6_n605 +end + +def fun_l5_n134() + fun_l6_n931 +end + +def fun_l5_n135() + fun_l6_n282 +end + +def fun_l5_n136() + fun_l6_n904 +end + +def fun_l5_n137() + fun_l6_n522 +end + +def fun_l5_n138() + fun_l6_n255 +end + +def fun_l5_n139() + fun_l6_n308 +end + +def fun_l5_n140() + fun_l6_n482 +end + +def fun_l5_n141() + fun_l6_n911 +end + +def fun_l5_n142() + fun_l6_n640 +end + +def fun_l5_n143() + fun_l6_n783 +end + +def fun_l5_n144() + fun_l6_n980 +end + +def fun_l5_n145() + fun_l6_n85 +end + +def fun_l5_n146() + fun_l6_n181 +end + +def fun_l5_n147() + fun_l6_n963 +end + +def fun_l5_n148() + fun_l6_n516 +end + +def fun_l5_n149() + fun_l6_n315 +end + +def fun_l5_n150() + fun_l6_n822 +end + +def fun_l5_n151() + fun_l6_n528 +end + +def fun_l5_n152() + fun_l6_n220 +end + +def fun_l5_n153() + fun_l6_n13 +end + +def fun_l5_n154() + fun_l6_n172 +end + +def fun_l5_n155() + fun_l6_n987 +end + +def fun_l5_n156() + fun_l6_n414 +end + +def fun_l5_n157() + fun_l6_n758 +end + +def fun_l5_n158() + fun_l6_n889 +end + +def fun_l5_n159() + fun_l6_n526 +end + +def fun_l5_n160() + fun_l6_n576 +end + +def fun_l5_n161() + fun_l6_n35 +end + +def fun_l5_n162() + fun_l6_n382 +end + +def fun_l5_n163() + fun_l6_n503 +end + +def fun_l5_n164() + fun_l6_n950 +end + +def fun_l5_n165() + fun_l6_n796 +end + +def fun_l5_n166() + fun_l6_n72 +end + +def fun_l5_n167() + fun_l6_n258 +end + +def fun_l5_n168() + fun_l6_n624 +end + +def fun_l5_n169() + fun_l6_n146 +end + +def fun_l5_n170() + fun_l6_n202 +end + +def fun_l5_n171() + fun_l6_n18 +end + +def fun_l5_n172() + fun_l6_n822 +end + +def fun_l5_n173() + fun_l6_n839 +end + +def fun_l5_n174() + fun_l6_n201 +end + +def fun_l5_n175() + fun_l6_n109 +end + +def fun_l5_n176() + fun_l6_n265 +end + +def fun_l5_n177() + fun_l6_n899 +end + +def fun_l5_n178() + fun_l6_n805 +end + +def fun_l5_n179() + fun_l6_n245 +end + +def fun_l5_n180() + fun_l6_n309 +end + +def fun_l5_n181() + fun_l6_n31 +end + +def fun_l5_n182() + fun_l6_n642 +end + +def fun_l5_n183() + fun_l6_n552 +end + +def fun_l5_n184() + fun_l6_n217 +end + +def fun_l5_n185() + fun_l6_n382 +end + +def fun_l5_n186() + fun_l6_n642 +end + +def fun_l5_n187() + fun_l6_n415 +end + +def fun_l5_n188() + fun_l6_n246 +end + +def fun_l5_n189() + fun_l6_n754 +end + +def fun_l5_n190() + fun_l6_n869 +end + +def fun_l5_n191() + fun_l6_n944 +end + +def fun_l5_n192() + fun_l6_n558 +end + +def fun_l5_n193() + fun_l6_n548 +end + +def fun_l5_n194() + fun_l6_n156 +end + +def fun_l5_n195() + fun_l6_n507 +end + +def fun_l5_n196() + fun_l6_n897 +end + +def fun_l5_n197() + fun_l6_n297 +end + +def fun_l5_n198() + fun_l6_n775 +end + +def fun_l5_n199() + fun_l6_n897 +end + +def fun_l5_n200() + fun_l6_n232 +end + +def fun_l5_n201() + fun_l6_n341 +end + +def fun_l5_n202() + fun_l6_n881 +end + +def fun_l5_n203() + fun_l6_n757 +end + +def fun_l5_n204() + fun_l6_n673 +end + +def fun_l5_n205() + fun_l6_n753 +end + +def fun_l5_n206() + fun_l6_n191 +end + +def fun_l5_n207() + fun_l6_n768 +end + +def fun_l5_n208() + fun_l6_n963 +end + +def fun_l5_n209() + fun_l6_n102 +end + +def fun_l5_n210() + fun_l6_n355 +end + +def fun_l5_n211() + fun_l6_n838 +end + +def fun_l5_n212() + fun_l6_n388 +end + +def fun_l5_n213() + fun_l6_n840 +end + +def fun_l5_n214() + fun_l6_n501 +end + +def fun_l5_n215() + fun_l6_n792 +end + +def fun_l5_n216() + fun_l6_n360 +end + +def fun_l5_n217() + fun_l6_n70 +end + +def fun_l5_n218() + fun_l6_n887 +end + +def fun_l5_n219() + fun_l6_n57 +end + +def fun_l5_n220() + fun_l6_n595 +end + +def fun_l5_n221() + fun_l6_n988 +end + +def fun_l5_n222() + fun_l6_n191 +end + +def fun_l5_n223() + fun_l6_n667 +end + +def fun_l5_n224() + fun_l6_n410 +end + +def fun_l5_n225() + fun_l6_n636 +end + +def fun_l5_n226() + fun_l6_n669 +end + +def fun_l5_n227() + fun_l6_n980 +end + +def fun_l5_n228() + fun_l6_n521 +end + +def fun_l5_n229() + fun_l6_n707 +end + +def fun_l5_n230() + fun_l6_n757 +end + +def fun_l5_n231() + fun_l6_n360 +end + +def fun_l5_n232() + fun_l6_n480 +end + +def fun_l5_n233() + fun_l6_n8 +end + +def fun_l5_n234() + fun_l6_n47 +end + +def fun_l5_n235() + fun_l6_n985 +end + +def fun_l5_n236() + fun_l6_n331 +end + +def fun_l5_n237() + fun_l6_n314 +end + +def fun_l5_n238() + fun_l6_n666 +end + +def fun_l5_n239() + fun_l6_n289 +end + +def fun_l5_n240() + fun_l6_n487 +end + +def fun_l5_n241() + fun_l6_n298 +end + +def fun_l5_n242() + fun_l6_n460 +end + +def fun_l5_n243() + fun_l6_n63 +end + +def fun_l5_n244() + fun_l6_n898 +end + +def fun_l5_n245() + fun_l6_n706 +end + +def fun_l5_n246() + fun_l6_n276 +end + +def fun_l5_n247() + fun_l6_n709 +end + +def fun_l5_n248() + fun_l6_n60 +end + +def fun_l5_n249() + fun_l6_n53 +end + +def fun_l5_n250() + fun_l6_n396 +end + +def fun_l5_n251() + fun_l6_n124 +end + +def fun_l5_n252() + fun_l6_n713 +end + +def fun_l5_n253() + fun_l6_n208 +end + +def fun_l5_n254() + fun_l6_n345 +end + +def fun_l5_n255() + fun_l6_n976 +end + +def fun_l5_n256() + fun_l6_n775 +end + +def fun_l5_n257() + fun_l6_n20 +end + +def fun_l5_n258() + fun_l6_n476 +end + +def fun_l5_n259() + fun_l6_n80 +end + +def fun_l5_n260() + fun_l6_n160 +end + +def fun_l5_n261() + fun_l6_n624 +end + +def fun_l5_n262() + fun_l6_n275 +end + +def fun_l5_n263() + fun_l6_n301 +end + +def fun_l5_n264() + fun_l6_n640 +end + +def fun_l5_n265() + fun_l6_n473 +end + +def fun_l5_n266() + fun_l6_n991 +end + +def fun_l5_n267() + fun_l6_n458 +end + +def fun_l5_n268() + fun_l6_n128 +end + +def fun_l5_n269() + fun_l6_n28 +end + +def fun_l5_n270() + fun_l6_n40 +end + +def fun_l5_n271() + fun_l6_n48 +end + +def fun_l5_n272() + fun_l6_n916 +end + +def fun_l5_n273() + fun_l6_n114 +end + +def fun_l5_n274() + fun_l6_n747 +end + +def fun_l5_n275() + fun_l6_n239 +end + +def fun_l5_n276() + fun_l6_n151 +end + +def fun_l5_n277() + fun_l6_n820 +end + +def fun_l5_n278() + fun_l6_n684 +end + +def fun_l5_n279() + fun_l6_n628 +end + +def fun_l5_n280() + fun_l6_n248 +end + +def fun_l5_n281() + fun_l6_n793 +end + +def fun_l5_n282() + fun_l6_n137 +end + +def fun_l5_n283() + fun_l6_n520 +end + +def fun_l5_n284() + fun_l6_n750 +end + +def fun_l5_n285() + fun_l6_n445 +end + +def fun_l5_n286() + fun_l6_n419 +end + +def fun_l5_n287() + fun_l6_n681 +end + +def fun_l5_n288() + fun_l6_n16 +end + +def fun_l5_n289() + fun_l6_n939 +end + +def fun_l5_n290() + fun_l6_n664 +end + +def fun_l5_n291() + fun_l6_n580 +end + +def fun_l5_n292() + fun_l6_n945 +end + +def fun_l5_n293() + fun_l6_n129 +end + +def fun_l5_n294() + fun_l6_n142 +end + +def fun_l5_n295() + fun_l6_n774 +end + +def fun_l5_n296() + fun_l6_n667 +end + +def fun_l5_n297() + fun_l6_n659 +end + +def fun_l5_n298() + fun_l6_n82 +end + +def fun_l5_n299() + fun_l6_n452 +end + +def fun_l5_n300() + fun_l6_n340 +end + +def fun_l5_n301() + fun_l6_n675 +end + +def fun_l5_n302() + fun_l6_n506 +end + +def fun_l5_n303() + fun_l6_n166 +end + +def fun_l5_n304() + fun_l6_n220 +end + +def fun_l5_n305() + fun_l6_n894 +end + +def fun_l5_n306() + fun_l6_n467 +end + +def fun_l5_n307() + fun_l6_n204 +end + +def fun_l5_n308() + fun_l6_n580 +end + +def fun_l5_n309() + fun_l6_n90 +end + +def fun_l5_n310() + fun_l6_n854 +end + +def fun_l5_n311() + fun_l6_n384 +end + +def fun_l5_n312() + fun_l6_n540 +end + +def fun_l5_n313() + fun_l6_n314 +end + +def fun_l5_n314() + fun_l6_n90 +end + +def fun_l5_n315() + fun_l6_n106 +end + +def fun_l5_n316() + fun_l6_n404 +end + +def fun_l5_n317() + fun_l6_n396 +end + +def fun_l5_n318() + fun_l6_n229 +end + +def fun_l5_n319() + fun_l6_n137 +end + +def fun_l5_n320() + fun_l6_n781 +end + +def fun_l5_n321() + fun_l6_n949 +end + +def fun_l5_n322() + fun_l6_n810 +end + +def fun_l5_n323() + fun_l6_n574 +end + +def fun_l5_n324() + fun_l6_n465 +end + +def fun_l5_n325() + fun_l6_n785 +end + +def fun_l5_n326() + fun_l6_n408 +end + +def fun_l5_n327() + fun_l6_n658 +end + +def fun_l5_n328() + fun_l6_n1 +end + +def fun_l5_n329() + fun_l6_n586 +end + +def fun_l5_n330() + fun_l6_n375 +end + +def fun_l5_n331() + fun_l6_n950 +end + +def fun_l5_n332() + fun_l6_n924 +end + +def fun_l5_n333() + fun_l6_n224 +end + +def fun_l5_n334() + fun_l6_n786 +end + +def fun_l5_n335() + fun_l6_n184 +end + +def fun_l5_n336() + fun_l6_n125 +end + +def fun_l5_n337() + fun_l6_n215 +end + +def fun_l5_n338() + fun_l6_n110 +end + +def fun_l5_n339() + fun_l6_n16 +end + +def fun_l5_n340() + fun_l6_n746 +end + +def fun_l5_n341() + fun_l6_n50 +end + +def fun_l5_n342() + fun_l6_n198 +end + +def fun_l5_n343() + fun_l6_n735 +end + +def fun_l5_n344() + fun_l6_n260 +end + +def fun_l5_n345() + fun_l6_n481 +end + +def fun_l5_n346() + fun_l6_n100 +end + +def fun_l5_n347() + fun_l6_n581 +end + +def fun_l5_n348() + fun_l6_n803 +end + +def fun_l5_n349() + fun_l6_n495 +end + +def fun_l5_n350() + fun_l6_n316 +end + +def fun_l5_n351() + fun_l6_n810 +end + +def fun_l5_n352() + fun_l6_n21 +end + +def fun_l5_n353() + fun_l6_n409 +end + +def fun_l5_n354() + fun_l6_n814 +end + +def fun_l5_n355() + fun_l6_n525 +end + +def fun_l5_n356() + fun_l6_n445 +end + +def fun_l5_n357() + fun_l6_n940 +end + +def fun_l5_n358() + fun_l6_n508 +end + +def fun_l5_n359() + fun_l6_n511 +end + +def fun_l5_n360() + fun_l6_n29 +end + +def fun_l5_n361() + fun_l6_n272 +end + +def fun_l5_n362() + fun_l6_n715 +end + +def fun_l5_n363() + fun_l6_n518 +end + +def fun_l5_n364() + fun_l6_n392 +end + +def fun_l5_n365() + fun_l6_n762 +end + +def fun_l5_n366() + fun_l6_n250 +end + +def fun_l5_n367() + fun_l6_n192 +end + +def fun_l5_n368() + fun_l6_n741 +end + +def fun_l5_n369() + fun_l6_n340 +end + +def fun_l5_n370() + fun_l6_n891 +end + +def fun_l5_n371() + fun_l6_n22 +end + +def fun_l5_n372() + fun_l6_n369 +end + +def fun_l5_n373() + fun_l6_n653 +end + +def fun_l5_n374() + fun_l6_n282 +end + +def fun_l5_n375() + fun_l6_n7 +end + +def fun_l5_n376() + fun_l6_n511 +end + +def fun_l5_n377() + fun_l6_n511 +end + +def fun_l5_n378() + fun_l6_n718 +end + +def fun_l5_n379() + fun_l6_n521 +end + +def fun_l5_n380() + fun_l6_n331 +end + +def fun_l5_n381() + fun_l6_n343 +end + +def fun_l5_n382() + fun_l6_n411 +end + +def fun_l5_n383() + fun_l6_n780 +end + +def fun_l5_n384() + fun_l6_n398 +end + +def fun_l5_n385() + fun_l6_n173 +end + +def fun_l5_n386() + fun_l6_n693 +end + +def fun_l5_n387() + fun_l6_n360 +end + +def fun_l5_n388() + fun_l6_n146 +end + +def fun_l5_n389() + fun_l6_n796 +end + +def fun_l5_n390() + fun_l6_n403 +end + +def fun_l5_n391() + fun_l6_n662 +end + +def fun_l5_n392() + fun_l6_n281 +end + +def fun_l5_n393() + fun_l6_n617 +end + +def fun_l5_n394() + fun_l6_n367 +end + +def fun_l5_n395() + fun_l6_n433 +end + +def fun_l5_n396() + fun_l6_n748 +end + +def fun_l5_n397() + fun_l6_n600 +end + +def fun_l5_n398() + fun_l6_n490 +end + +def fun_l5_n399() + fun_l6_n120 +end + +def fun_l5_n400() + fun_l6_n549 +end + +def fun_l5_n401() + fun_l6_n148 +end + +def fun_l5_n402() + fun_l6_n488 +end + +def fun_l5_n403() + fun_l6_n316 +end + +def fun_l5_n404() + fun_l6_n106 +end + +def fun_l5_n405() + fun_l6_n702 +end + +def fun_l5_n406() + fun_l6_n787 +end + +def fun_l5_n407() + fun_l6_n9 +end + +def fun_l5_n408() + fun_l6_n338 +end + +def fun_l5_n409() + fun_l6_n83 +end + +def fun_l5_n410() + fun_l6_n234 +end + +def fun_l5_n411() + fun_l6_n147 +end + +def fun_l5_n412() + fun_l6_n602 +end + +def fun_l5_n413() + fun_l6_n173 +end + +def fun_l5_n414() + fun_l6_n420 +end + +def fun_l5_n415() + fun_l6_n214 +end + +def fun_l5_n416() + fun_l6_n400 +end + +def fun_l5_n417() + fun_l6_n35 +end + +def fun_l5_n418() + fun_l6_n545 +end + +def fun_l5_n419() + fun_l6_n823 +end + +def fun_l5_n420() + fun_l6_n401 +end + +def fun_l5_n421() + fun_l6_n447 +end + +def fun_l5_n422() + fun_l6_n461 +end + +def fun_l5_n423() + fun_l6_n447 +end + +def fun_l5_n424() + fun_l6_n530 +end + +def fun_l5_n425() + fun_l6_n104 +end + +def fun_l5_n426() + fun_l6_n206 +end + +def fun_l5_n427() + fun_l6_n25 +end + +def fun_l5_n428() + fun_l6_n867 +end + +def fun_l5_n429() + fun_l6_n160 +end + +def fun_l5_n430() + fun_l6_n152 +end + +def fun_l5_n431() + fun_l6_n308 +end + +def fun_l5_n432() + fun_l6_n603 +end + +def fun_l5_n433() + fun_l6_n270 +end + +def fun_l5_n434() + fun_l6_n397 +end + +def fun_l5_n435() + fun_l6_n819 +end + +def fun_l5_n436() + fun_l6_n476 +end + +def fun_l5_n437() + fun_l6_n533 +end + +def fun_l5_n438() + fun_l6_n989 +end + +def fun_l5_n439() + fun_l6_n329 +end + +def fun_l5_n440() + fun_l6_n216 +end + +def fun_l5_n441() + fun_l6_n54 +end + +def fun_l5_n442() + fun_l6_n374 +end + +def fun_l5_n443() + fun_l6_n544 +end + +def fun_l5_n444() + fun_l6_n586 +end + +def fun_l5_n445() + fun_l6_n137 +end + +def fun_l5_n446() + fun_l6_n115 +end + +def fun_l5_n447() + fun_l6_n908 +end + +def fun_l5_n448() + fun_l6_n657 +end + +def fun_l5_n449() + fun_l6_n876 +end + +def fun_l5_n450() + fun_l6_n585 +end + +def fun_l5_n451() + fun_l6_n159 +end + +def fun_l5_n452() + fun_l6_n66 +end + +def fun_l5_n453() + fun_l6_n327 +end + +def fun_l5_n454() + fun_l6_n441 +end + +def fun_l5_n455() + fun_l6_n399 +end + +def fun_l5_n456() + fun_l6_n335 +end + +def fun_l5_n457() + fun_l6_n820 +end + +def fun_l5_n458() + fun_l6_n494 +end + +def fun_l5_n459() + fun_l6_n683 +end + +def fun_l5_n460() + fun_l6_n453 +end + +def fun_l5_n461() + fun_l6_n202 +end + +def fun_l5_n462() + fun_l6_n274 +end + +def fun_l5_n463() + fun_l6_n493 +end + +def fun_l5_n464() + fun_l6_n874 +end + +def fun_l5_n465() + fun_l6_n882 +end + +def fun_l5_n466() + fun_l6_n706 +end + +def fun_l5_n467() + fun_l6_n356 +end + +def fun_l5_n468() + fun_l6_n21 +end + +def fun_l5_n469() + fun_l6_n131 +end + +def fun_l5_n470() + fun_l6_n818 +end + +def fun_l5_n471() + fun_l6_n58 +end + +def fun_l5_n472() + fun_l6_n606 +end + +def fun_l5_n473() + fun_l6_n368 +end + +def fun_l5_n474() + fun_l6_n266 +end + +def fun_l5_n475() + fun_l6_n910 +end + +def fun_l5_n476() + fun_l6_n406 +end + +def fun_l5_n477() + fun_l6_n522 +end + +def fun_l5_n478() + fun_l6_n479 +end + +def fun_l5_n479() + fun_l6_n247 +end + +def fun_l5_n480() + fun_l6_n785 +end + +def fun_l5_n481() + fun_l6_n953 +end + +def fun_l5_n482() + fun_l6_n443 +end + +def fun_l5_n483() + fun_l6_n834 +end + +def fun_l5_n484() + fun_l6_n494 +end + +def fun_l5_n485() + fun_l6_n65 +end + +def fun_l5_n486() + fun_l6_n93 +end + +def fun_l5_n487() + fun_l6_n702 +end + +def fun_l5_n488() + fun_l6_n571 +end + +def fun_l5_n489() + fun_l6_n233 +end + +def fun_l5_n490() + fun_l6_n106 +end + +def fun_l5_n491() + fun_l6_n806 +end + +def fun_l5_n492() + fun_l6_n795 +end + +def fun_l5_n493() + fun_l6_n273 +end + +def fun_l5_n494() + fun_l6_n943 +end + +def fun_l5_n495() + fun_l6_n710 +end + +def fun_l5_n496() + fun_l6_n419 +end + +def fun_l5_n497() + fun_l6_n758 +end + +def fun_l5_n498() + fun_l6_n677 +end + +def fun_l5_n499() + fun_l6_n573 +end + +def fun_l5_n500() + fun_l6_n576 +end + +def fun_l5_n501() + fun_l6_n654 +end + +def fun_l5_n502() + fun_l6_n497 +end + +def fun_l5_n503() + fun_l6_n75 +end + +def fun_l5_n504() + fun_l6_n660 +end + +def fun_l5_n505() + fun_l6_n923 +end + +def fun_l5_n506() + fun_l6_n250 +end + +def fun_l5_n507() + fun_l6_n648 +end + +def fun_l5_n508() + fun_l6_n785 +end + +def fun_l5_n509() + fun_l6_n158 +end + +def fun_l5_n510() + fun_l6_n564 +end + +def fun_l5_n511() + fun_l6_n916 +end + +def fun_l5_n512() + fun_l6_n943 +end + +def fun_l5_n513() + fun_l6_n468 +end + +def fun_l5_n514() + fun_l6_n165 +end + +def fun_l5_n515() + fun_l6_n566 +end + +def fun_l5_n516() + fun_l6_n280 +end + +def fun_l5_n517() + fun_l6_n998 +end + +def fun_l5_n518() + fun_l6_n282 +end + +def fun_l5_n519() + fun_l6_n419 +end + +def fun_l5_n520() + fun_l6_n10 +end + +def fun_l5_n521() + fun_l6_n298 +end + +def fun_l5_n522() + fun_l6_n571 +end + +def fun_l5_n523() + fun_l6_n873 +end + +def fun_l5_n524() + fun_l6_n165 +end + +def fun_l5_n525() + fun_l6_n807 +end + +def fun_l5_n526() + fun_l6_n194 +end + +def fun_l5_n527() + fun_l6_n410 +end + +def fun_l5_n528() + fun_l6_n377 +end + +def fun_l5_n529() + fun_l6_n328 +end + +def fun_l5_n530() + fun_l6_n322 +end + +def fun_l5_n531() + fun_l6_n760 +end + +def fun_l5_n532() + fun_l6_n738 +end + +def fun_l5_n533() + fun_l6_n388 +end + +def fun_l5_n534() + fun_l6_n609 +end + +def fun_l5_n535() + fun_l6_n808 +end + +def fun_l5_n536() + fun_l6_n686 +end + +def fun_l5_n537() + fun_l6_n825 +end + +def fun_l5_n538() + fun_l6_n940 +end + +def fun_l5_n539() + fun_l6_n147 +end + +def fun_l5_n540() + fun_l6_n851 +end + +def fun_l5_n541() + fun_l6_n983 +end + +def fun_l5_n542() + fun_l6_n938 +end + +def fun_l5_n543() + fun_l6_n323 +end + +def fun_l5_n544() + fun_l6_n662 +end + +def fun_l5_n545() + fun_l6_n611 +end + +def fun_l5_n546() + fun_l6_n185 +end + +def fun_l5_n547() + fun_l6_n321 +end + +def fun_l5_n548() + fun_l6_n353 +end + +def fun_l5_n549() + fun_l6_n240 +end + +def fun_l5_n550() + fun_l6_n69 +end + +def fun_l5_n551() + fun_l6_n58 +end + +def fun_l5_n552() + fun_l6_n108 +end + +def fun_l5_n553() + fun_l6_n169 +end + +def fun_l5_n554() + fun_l6_n649 +end + +def fun_l5_n555() + fun_l6_n28 +end + +def fun_l5_n556() + fun_l6_n136 +end + +def fun_l5_n557() + fun_l6_n958 +end + +def fun_l5_n558() + fun_l6_n107 +end + +def fun_l5_n559() + fun_l6_n495 +end + +def fun_l5_n560() + fun_l6_n927 +end + +def fun_l5_n561() + fun_l6_n994 +end + +def fun_l5_n562() + fun_l6_n134 +end + +def fun_l5_n563() + fun_l6_n393 +end + +def fun_l5_n564() + fun_l6_n73 +end + +def fun_l5_n565() + fun_l6_n860 +end + +def fun_l5_n566() + fun_l6_n763 +end + +def fun_l5_n567() + fun_l6_n545 +end + +def fun_l5_n568() + fun_l6_n429 +end + +def fun_l5_n569() + fun_l6_n430 +end + +def fun_l5_n570() + fun_l6_n50 +end + +def fun_l5_n571() + fun_l6_n574 +end + +def fun_l5_n572() + fun_l6_n195 +end + +def fun_l5_n573() + fun_l6_n327 +end + +def fun_l5_n574() + fun_l6_n207 +end + +def fun_l5_n575() + fun_l6_n669 +end + +def fun_l5_n576() + fun_l6_n978 +end + +def fun_l5_n577() + fun_l6_n60 +end + +def fun_l5_n578() + fun_l6_n561 +end + +def fun_l5_n579() + fun_l6_n298 +end + +def fun_l5_n580() + fun_l6_n790 +end + +def fun_l5_n581() + fun_l6_n887 +end + +def fun_l5_n582() + fun_l6_n516 +end + +def fun_l5_n583() + fun_l6_n895 +end + +def fun_l5_n584() + fun_l6_n345 +end + +def fun_l5_n585() + fun_l6_n117 +end + +def fun_l5_n586() + fun_l6_n493 +end + +def fun_l5_n587() + fun_l6_n84 +end + +def fun_l5_n588() + fun_l6_n62 +end + +def fun_l5_n589() + fun_l6_n91 +end + +def fun_l5_n590() + fun_l6_n113 +end + +def fun_l5_n591() + fun_l6_n568 +end + +def fun_l5_n592() + fun_l6_n273 +end + +def fun_l5_n593() + fun_l6_n557 +end + +def fun_l5_n594() + fun_l6_n528 +end + +def fun_l5_n595() + fun_l6_n283 +end + +def fun_l5_n596() + fun_l6_n962 +end + +def fun_l5_n597() + fun_l6_n140 +end + +def fun_l5_n598() + fun_l6_n780 +end + +def fun_l5_n599() + fun_l6_n220 +end + +def fun_l5_n600() + fun_l6_n43 +end + +def fun_l5_n601() + fun_l6_n256 +end + +def fun_l5_n602() + fun_l6_n619 +end + +def fun_l5_n603() + fun_l6_n873 +end + +def fun_l5_n604() + fun_l6_n975 +end + +def fun_l5_n605() + fun_l6_n308 +end + +def fun_l5_n606() + fun_l6_n519 +end + +def fun_l5_n607() + fun_l6_n356 +end + +def fun_l5_n608() + fun_l6_n7 +end + +def fun_l5_n609() + fun_l6_n161 +end + +def fun_l5_n610() + fun_l6_n122 +end + +def fun_l5_n611() + fun_l6_n311 +end + +def fun_l5_n612() + fun_l6_n130 +end + +def fun_l5_n613() + fun_l6_n603 +end + +def fun_l5_n614() + fun_l6_n53 +end + +def fun_l5_n615() + fun_l6_n478 +end + +def fun_l5_n616() + fun_l6_n585 +end + +def fun_l5_n617() + fun_l6_n639 +end + +def fun_l5_n618() + fun_l6_n943 +end + +def fun_l5_n619() + fun_l6_n432 +end + +def fun_l5_n620() + fun_l6_n959 +end + +def fun_l5_n621() + fun_l6_n220 +end + +def fun_l5_n622() + fun_l6_n243 +end + +def fun_l5_n623() + fun_l6_n755 +end + +def fun_l5_n624() + fun_l6_n312 +end + +def fun_l5_n625() + fun_l6_n61 +end + +def fun_l5_n626() + fun_l6_n290 +end + +def fun_l5_n627() + fun_l6_n452 +end + +def fun_l5_n628() + fun_l6_n225 +end + +def fun_l5_n629() + fun_l6_n69 +end + +def fun_l5_n630() + fun_l6_n329 +end + +def fun_l5_n631() + fun_l6_n24 +end + +def fun_l5_n632() + fun_l6_n798 +end + +def fun_l5_n633() + fun_l6_n931 +end + +def fun_l5_n634() + fun_l6_n801 +end + +def fun_l5_n635() + fun_l6_n725 +end + +def fun_l5_n636() + fun_l6_n839 +end + +def fun_l5_n637() + fun_l6_n870 +end + +def fun_l5_n638() + fun_l6_n847 +end + +def fun_l5_n639() + fun_l6_n448 +end + +def fun_l5_n640() + fun_l6_n46 +end + +def fun_l5_n641() + fun_l6_n359 +end + +def fun_l5_n642() + fun_l6_n102 +end + +def fun_l5_n643() + fun_l6_n149 +end + +def fun_l5_n644() + fun_l6_n126 +end + +def fun_l5_n645() + fun_l6_n72 +end + +def fun_l5_n646() + fun_l6_n320 +end + +def fun_l5_n647() + fun_l6_n483 +end + +def fun_l5_n648() + fun_l6_n797 +end + +def fun_l5_n649() + fun_l6_n130 +end + +def fun_l5_n650() + fun_l6_n711 +end + +def fun_l5_n651() + fun_l6_n979 +end + +def fun_l5_n652() + fun_l6_n534 +end + +def fun_l5_n653() + fun_l6_n335 +end + +def fun_l5_n654() + fun_l6_n181 +end + +def fun_l5_n655() + fun_l6_n435 +end + +def fun_l5_n656() + fun_l6_n412 +end + +def fun_l5_n657() + fun_l6_n247 +end + +def fun_l5_n658() + fun_l6_n450 +end + +def fun_l5_n659() + fun_l6_n367 +end + +def fun_l5_n660() + fun_l6_n220 +end + +def fun_l5_n661() + fun_l6_n410 +end + +def fun_l5_n662() + fun_l6_n739 +end + +def fun_l5_n663() + fun_l6_n846 +end + +def fun_l5_n664() + fun_l6_n238 +end + +def fun_l5_n665() + fun_l6_n419 +end + +def fun_l5_n666() + fun_l6_n687 +end + +def fun_l5_n667() + fun_l6_n229 +end + +def fun_l5_n668() + fun_l6_n129 +end + +def fun_l5_n669() + fun_l6_n767 +end + +def fun_l5_n670() + fun_l6_n809 +end + +def fun_l5_n671() + fun_l6_n301 +end + +def fun_l5_n672() + fun_l6_n268 +end + +def fun_l5_n673() + fun_l6_n635 +end + +def fun_l5_n674() + fun_l6_n623 +end + +def fun_l5_n675() + fun_l6_n601 +end + +def fun_l5_n676() + fun_l6_n464 +end + +def fun_l5_n677() + fun_l6_n285 +end + +def fun_l5_n678() + fun_l6_n536 +end + +def fun_l5_n679() + fun_l6_n233 +end + +def fun_l5_n680() + fun_l6_n78 +end + +def fun_l5_n681() + fun_l6_n644 +end + +def fun_l5_n682() + fun_l6_n289 +end + +def fun_l5_n683() + fun_l6_n314 +end + +def fun_l5_n684() + fun_l6_n743 +end + +def fun_l5_n685() + fun_l6_n444 +end + +def fun_l5_n686() + fun_l6_n645 +end + +def fun_l5_n687() + fun_l6_n800 +end + +def fun_l5_n688() + fun_l6_n507 +end + +def fun_l5_n689() + fun_l6_n675 +end + +def fun_l5_n690() + fun_l6_n231 +end + +def fun_l5_n691() + fun_l6_n595 +end + +def fun_l5_n692() + fun_l6_n675 +end + +def fun_l5_n693() + fun_l6_n555 +end + +def fun_l5_n694() + fun_l6_n35 +end + +def fun_l5_n695() + fun_l6_n342 +end + +def fun_l5_n696() + fun_l6_n250 +end + +def fun_l5_n697() + fun_l6_n706 +end + +def fun_l5_n698() + fun_l6_n550 +end + +def fun_l5_n699() + fun_l6_n446 +end + +def fun_l5_n700() + fun_l6_n190 +end + +def fun_l5_n701() + fun_l6_n404 +end + +def fun_l5_n702() + fun_l6_n545 +end + +def fun_l5_n703() + fun_l6_n721 +end + +def fun_l5_n704() + fun_l6_n681 +end + +def fun_l5_n705() + fun_l6_n760 +end + +def fun_l5_n706() + fun_l6_n853 +end + +def fun_l5_n707() + fun_l6_n847 +end + +def fun_l5_n708() + fun_l6_n661 +end + +def fun_l5_n709() + fun_l6_n257 +end + +def fun_l5_n710() + fun_l6_n151 +end + +def fun_l5_n711() + fun_l6_n120 +end + +def fun_l5_n712() + fun_l6_n701 +end + +def fun_l5_n713() + fun_l6_n89 +end + +def fun_l5_n714() + fun_l6_n443 +end + +def fun_l5_n715() + fun_l6_n969 +end + +def fun_l5_n716() + fun_l6_n879 +end + +def fun_l5_n717() + fun_l6_n525 +end + +def fun_l5_n718() + fun_l6_n471 +end + +def fun_l5_n719() + fun_l6_n762 +end + +def fun_l5_n720() + fun_l6_n803 +end + +def fun_l5_n721() + fun_l6_n741 +end + +def fun_l5_n722() + fun_l6_n279 +end + +def fun_l5_n723() + fun_l6_n903 +end + +def fun_l5_n724() + fun_l6_n20 +end + +def fun_l5_n725() + fun_l6_n930 +end + +def fun_l5_n726() + fun_l6_n504 +end + +def fun_l5_n727() + fun_l6_n978 +end + +def fun_l5_n728() + fun_l6_n304 +end + +def fun_l5_n729() + fun_l6_n133 +end + +def fun_l5_n730() + fun_l6_n430 +end + +def fun_l5_n731() + fun_l6_n917 +end + +def fun_l5_n732() + fun_l6_n987 +end + +def fun_l5_n733() + fun_l6_n24 +end + +def fun_l5_n734() + fun_l6_n884 +end + +def fun_l5_n735() + fun_l6_n928 +end + +def fun_l5_n736() + fun_l6_n126 +end + +def fun_l5_n737() + fun_l6_n425 +end + +def fun_l5_n738() + fun_l6_n113 +end + +def fun_l5_n739() + fun_l6_n779 +end + +def fun_l5_n740() + fun_l6_n649 +end + +def fun_l5_n741() + fun_l6_n352 +end + +def fun_l5_n742() + fun_l6_n369 +end + +def fun_l5_n743() + fun_l6_n13 +end + +def fun_l5_n744() + fun_l6_n460 +end + +def fun_l5_n745() + fun_l6_n476 +end + +def fun_l5_n746() + fun_l6_n146 +end + +def fun_l5_n747() + fun_l6_n38 +end + +def fun_l5_n748() + fun_l6_n86 +end + +def fun_l5_n749() + fun_l6_n875 +end + +def fun_l5_n750() + fun_l6_n812 +end + +def fun_l5_n751() + fun_l6_n282 +end + +def fun_l5_n752() + fun_l6_n474 +end + +def fun_l5_n753() + fun_l6_n546 +end + +def fun_l5_n754() + fun_l6_n107 +end + +def fun_l5_n755() + fun_l6_n550 +end + +def fun_l5_n756() + fun_l6_n868 +end + +def fun_l5_n757() + fun_l6_n149 +end + +def fun_l5_n758() + fun_l6_n662 +end + +def fun_l5_n759() + fun_l6_n642 +end + +def fun_l5_n760() + fun_l6_n760 +end + +def fun_l5_n761() + fun_l6_n530 +end + +def fun_l5_n762() + fun_l6_n765 +end + +def fun_l5_n763() + fun_l6_n634 +end + +def fun_l5_n764() + fun_l6_n946 +end + +def fun_l5_n765() + fun_l6_n423 +end + +def fun_l5_n766() + fun_l6_n478 +end + +def fun_l5_n767() + fun_l6_n142 +end + +def fun_l5_n768() + fun_l6_n550 +end + +def fun_l5_n769() + fun_l6_n610 +end + +def fun_l5_n770() + fun_l6_n340 +end + +def fun_l5_n771() + fun_l6_n29 +end + +def fun_l5_n772() + fun_l6_n164 +end + +def fun_l5_n773() + fun_l6_n476 +end + +def fun_l5_n774() + fun_l6_n48 +end + +def fun_l5_n775() + fun_l6_n123 +end + +def fun_l5_n776() + fun_l6_n879 +end + +def fun_l5_n777() + fun_l6_n958 +end + +def fun_l5_n778() + fun_l6_n100 +end + +def fun_l5_n779() + fun_l6_n927 +end + +def fun_l5_n780() + fun_l6_n105 +end + +def fun_l5_n781() + fun_l6_n360 +end + +def fun_l5_n782() + fun_l6_n327 +end + +def fun_l5_n783() + fun_l6_n677 +end + +def fun_l5_n784() + fun_l6_n378 +end + +def fun_l5_n785() + fun_l6_n9 +end + +def fun_l5_n786() + fun_l6_n692 +end + +def fun_l5_n787() + fun_l6_n952 +end + +def fun_l5_n788() + fun_l6_n156 +end + +def fun_l5_n789() + fun_l6_n222 +end + +def fun_l5_n790() + fun_l6_n419 +end + +def fun_l5_n791() + fun_l6_n128 +end + +def fun_l5_n792() + fun_l6_n311 +end + +def fun_l5_n793() + fun_l6_n610 +end + +def fun_l5_n794() + fun_l6_n897 +end + +def fun_l5_n795() + fun_l6_n806 +end + +def fun_l5_n796() + fun_l6_n291 +end + +def fun_l5_n797() + fun_l6_n942 +end + +def fun_l5_n798() + fun_l6_n208 +end + +def fun_l5_n799() + fun_l6_n776 +end + +def fun_l5_n800() + fun_l6_n866 +end + +def fun_l5_n801() + fun_l6_n132 +end + +def fun_l5_n802() + fun_l6_n436 +end + +def fun_l5_n803() + fun_l6_n804 +end + +def fun_l5_n804() + fun_l6_n810 +end + +def fun_l5_n805() + fun_l6_n302 +end + +def fun_l5_n806() + fun_l6_n501 +end + +def fun_l5_n807() + fun_l6_n812 +end + +def fun_l5_n808() + fun_l6_n861 +end + +def fun_l5_n809() + fun_l6_n359 +end + +def fun_l5_n810() + fun_l6_n366 +end + +def fun_l5_n811() + fun_l6_n855 +end + +def fun_l5_n812() + fun_l6_n960 +end + +def fun_l5_n813() + fun_l6_n868 +end + +def fun_l5_n814() + fun_l6_n101 +end + +def fun_l5_n815() + fun_l6_n540 +end + +def fun_l5_n816() + fun_l6_n486 +end + +def fun_l5_n817() + fun_l6_n896 +end + +def fun_l5_n818() + fun_l6_n240 +end + +def fun_l5_n819() + fun_l6_n425 +end + +def fun_l5_n820() + fun_l6_n408 +end + +def fun_l5_n821() + fun_l6_n779 +end + +def fun_l5_n822() + fun_l6_n486 +end + +def fun_l5_n823() + fun_l6_n903 +end + +def fun_l5_n824() + fun_l6_n957 +end + +def fun_l5_n825() + fun_l6_n213 +end + +def fun_l5_n826() + fun_l6_n326 +end + +def fun_l5_n827() + fun_l6_n944 +end + +def fun_l5_n828() + fun_l6_n772 +end + +def fun_l5_n829() + fun_l6_n879 +end + +def fun_l5_n830() + fun_l6_n406 +end + +def fun_l5_n831() + fun_l6_n488 +end + +def fun_l5_n832() + fun_l6_n615 +end + +def fun_l5_n833() + fun_l6_n113 +end + +def fun_l5_n834() + fun_l6_n826 +end + +def fun_l5_n835() + fun_l6_n621 +end + +def fun_l5_n836() + fun_l6_n520 +end + +def fun_l5_n837() + fun_l6_n729 +end + +def fun_l5_n838() + fun_l6_n83 +end + +def fun_l5_n839() + fun_l6_n616 +end + +def fun_l5_n840() + fun_l6_n477 +end + +def fun_l5_n841() + fun_l6_n25 +end + +def fun_l5_n842() + fun_l6_n391 +end + +def fun_l5_n843() + fun_l6_n974 +end + +def fun_l5_n844() + fun_l6_n970 +end + +def fun_l5_n845() + fun_l6_n316 +end + +def fun_l5_n846() + fun_l6_n596 +end + +def fun_l5_n847() + fun_l6_n518 +end + +def fun_l5_n848() + fun_l6_n437 +end + +def fun_l5_n849() + fun_l6_n268 +end + +def fun_l5_n850() + fun_l6_n347 +end + +def fun_l5_n851() + fun_l6_n110 +end + +def fun_l5_n852() + fun_l6_n783 +end + +def fun_l5_n853() + fun_l6_n503 +end + +def fun_l5_n854() + fun_l6_n56 +end + +def fun_l5_n855() + fun_l6_n294 +end + +def fun_l5_n856() + fun_l6_n145 +end + +def fun_l5_n857() + fun_l6_n627 +end + +def fun_l5_n858() + fun_l6_n917 +end + +def fun_l5_n859() + fun_l6_n242 +end + +def fun_l5_n860() + fun_l6_n35 +end + +def fun_l5_n861() + fun_l6_n883 +end + +def fun_l5_n862() + fun_l6_n766 +end + +def fun_l5_n863() + fun_l6_n877 +end + +def fun_l5_n864() + fun_l6_n974 +end + +def fun_l5_n865() + fun_l6_n525 +end + +def fun_l5_n866() + fun_l6_n490 +end + +def fun_l5_n867() + fun_l6_n920 +end + +def fun_l5_n868() + fun_l6_n28 +end + +def fun_l5_n869() + fun_l6_n855 +end + +def fun_l5_n870() + fun_l6_n246 +end + +def fun_l5_n871() + fun_l6_n60 +end + +def fun_l5_n872() + fun_l6_n868 +end + +def fun_l5_n873() + fun_l6_n706 +end + +def fun_l5_n874() + fun_l6_n629 +end + +def fun_l5_n875() + fun_l6_n44 +end + +def fun_l5_n876() + fun_l6_n521 +end + +def fun_l5_n877() + fun_l6_n607 +end + +def fun_l5_n878() + fun_l6_n385 +end + +def fun_l5_n879() + fun_l6_n109 +end + +def fun_l5_n880() + fun_l6_n296 +end + +def fun_l5_n881() + fun_l6_n466 +end + +def fun_l5_n882() + fun_l6_n933 +end + +def fun_l5_n883() + fun_l6_n529 +end + +def fun_l5_n884() + fun_l6_n863 +end + +def fun_l5_n885() + fun_l6_n112 +end + +def fun_l5_n886() + fun_l6_n262 +end + +def fun_l5_n887() + fun_l6_n853 +end + +def fun_l5_n888() + fun_l6_n657 +end + +def fun_l5_n889() + fun_l6_n860 +end + +def fun_l5_n890() + fun_l6_n878 +end + +def fun_l5_n891() + fun_l6_n810 +end + +def fun_l5_n892() + fun_l6_n285 +end + +def fun_l5_n893() + fun_l6_n319 +end + +def fun_l5_n894() + fun_l6_n927 +end + +def fun_l5_n895() + fun_l6_n530 +end + +def fun_l5_n896() + fun_l6_n874 +end + +def fun_l5_n897() + fun_l6_n522 +end + +def fun_l5_n898() + fun_l6_n31 +end + +def fun_l5_n899() + fun_l6_n292 +end + +def fun_l5_n900() + fun_l6_n847 +end + +def fun_l5_n901() + fun_l6_n989 +end + +def fun_l5_n902() + fun_l6_n435 +end + +def fun_l5_n903() + fun_l6_n368 +end + +def fun_l5_n904() + fun_l6_n320 +end + +def fun_l5_n905() + fun_l6_n889 +end + +def fun_l5_n906() + fun_l6_n101 +end + +def fun_l5_n907() + fun_l6_n717 +end + +def fun_l5_n908() + fun_l6_n456 +end + +def fun_l5_n909() + fun_l6_n448 +end + +def fun_l5_n910() + fun_l6_n523 +end + +def fun_l5_n911() + fun_l6_n604 +end + +def fun_l5_n912() + fun_l6_n429 +end + +def fun_l5_n913() + fun_l6_n947 +end + +def fun_l5_n914() + fun_l6_n804 +end + +def fun_l5_n915() + fun_l6_n665 +end + +def fun_l5_n916() + fun_l6_n195 +end + +def fun_l5_n917() + fun_l6_n803 +end + +def fun_l5_n918() + fun_l6_n957 +end + +def fun_l5_n919() + fun_l6_n187 +end + +def fun_l5_n920() + fun_l6_n489 +end + +def fun_l5_n921() + fun_l6_n315 +end + +def fun_l5_n922() + fun_l6_n216 +end + +def fun_l5_n923() + fun_l6_n482 +end + +def fun_l5_n924() + fun_l6_n20 +end + +def fun_l5_n925() + fun_l6_n941 +end + +def fun_l5_n926() + fun_l6_n73 +end + +def fun_l5_n927() + fun_l6_n563 +end + +def fun_l5_n928() + fun_l6_n179 +end + +def fun_l5_n929() + fun_l6_n861 +end + +def fun_l5_n930() + fun_l6_n811 +end + +def fun_l5_n931() + fun_l6_n996 +end + +def fun_l5_n932() + fun_l6_n25 +end + +def fun_l5_n933() + fun_l6_n232 +end + +def fun_l5_n934() + fun_l6_n671 +end + +def fun_l5_n935() + fun_l6_n162 +end + +def fun_l5_n936() + fun_l6_n363 +end + +def fun_l5_n937() + fun_l6_n517 +end + +def fun_l5_n938() + fun_l6_n655 +end + +def fun_l5_n939() + fun_l6_n825 +end + +def fun_l5_n940() + fun_l6_n58 +end + +def fun_l5_n941() + fun_l6_n440 +end + +def fun_l5_n942() + fun_l6_n106 +end + +def fun_l5_n943() + fun_l6_n218 +end + +def fun_l5_n944() + fun_l6_n580 +end + +def fun_l5_n945() + fun_l6_n63 +end + +def fun_l5_n946() + fun_l6_n116 +end + +def fun_l5_n947() + fun_l6_n329 +end + +def fun_l5_n948() + fun_l6_n511 +end + +def fun_l5_n949() + fun_l6_n499 +end + +def fun_l5_n950() + fun_l6_n469 +end + +def fun_l5_n951() + fun_l6_n18 +end + +def fun_l5_n952() + fun_l6_n200 +end + +def fun_l5_n953() + fun_l6_n924 +end + +def fun_l5_n954() + fun_l6_n879 +end + +def fun_l5_n955() + fun_l6_n959 +end + +def fun_l5_n956() + fun_l6_n867 +end + +def fun_l5_n957() + fun_l6_n650 +end + +def fun_l5_n958() + fun_l6_n481 +end + +def fun_l5_n959() + fun_l6_n892 +end + +def fun_l5_n960() + fun_l6_n499 +end + +def fun_l5_n961() + fun_l6_n406 +end + +def fun_l5_n962() + fun_l6_n762 +end + +def fun_l5_n963() + fun_l6_n479 +end + +def fun_l5_n964() + fun_l6_n869 +end + +def fun_l5_n965() + fun_l6_n321 +end + +def fun_l5_n966() + fun_l6_n722 +end + +def fun_l5_n967() + fun_l6_n834 +end + +def fun_l5_n968() + fun_l6_n873 +end + +def fun_l5_n969() + fun_l6_n295 +end + +def fun_l5_n970() + fun_l6_n394 +end + +def fun_l5_n971() + fun_l6_n944 +end + +def fun_l5_n972() + fun_l6_n335 +end + +def fun_l5_n973() + fun_l6_n958 +end + +def fun_l5_n974() + fun_l6_n159 +end + +def fun_l5_n975() + fun_l6_n336 +end + +def fun_l5_n976() + fun_l6_n979 +end + +def fun_l5_n977() + fun_l6_n106 +end + +def fun_l5_n978() + fun_l6_n587 +end + +def fun_l5_n979() + fun_l6_n693 +end + +def fun_l5_n980() + fun_l6_n633 +end + +def fun_l5_n981() + fun_l6_n359 +end + +def fun_l5_n982() + fun_l6_n118 +end + +def fun_l5_n983() + fun_l6_n689 +end + +def fun_l5_n984() + fun_l6_n398 +end + +def fun_l5_n985() + fun_l6_n985 +end + +def fun_l5_n986() + fun_l6_n381 +end + +def fun_l5_n987() + fun_l6_n322 +end + +def fun_l5_n988() + fun_l6_n817 +end + +def fun_l5_n989() + fun_l6_n793 +end + +def fun_l5_n990() + fun_l6_n619 +end + +def fun_l5_n991() + fun_l6_n876 +end + +def fun_l5_n992() + fun_l6_n390 +end + +def fun_l5_n993() + fun_l6_n58 +end + +def fun_l5_n994() + fun_l6_n545 +end + +def fun_l5_n995() + fun_l6_n364 +end + +def fun_l5_n996() + fun_l6_n849 +end + +def fun_l5_n997() + fun_l6_n185 +end + +def fun_l5_n998() + fun_l6_n56 +end + +def fun_l5_n999() + fun_l6_n156 +end + +def fun_l6_n0() + fun_l7_n367 +end + +def fun_l6_n1() + fun_l7_n681 +end + +def fun_l6_n2() + fun_l7_n170 +end + +def fun_l6_n3() + fun_l7_n39 +end + +def fun_l6_n4() + fun_l7_n320 +end + +def fun_l6_n5() + fun_l7_n862 +end + +def fun_l6_n6() + fun_l7_n604 +end + +def fun_l6_n7() + fun_l7_n816 +end + +def fun_l6_n8() + fun_l7_n31 +end + +def fun_l6_n9() + fun_l7_n285 +end + +def fun_l6_n10() + fun_l7_n74 +end + +def fun_l6_n11() + fun_l7_n638 +end + +def fun_l6_n12() + fun_l7_n471 +end + +def fun_l6_n13() + fun_l7_n909 +end + +def fun_l6_n14() + fun_l7_n677 +end + +def fun_l6_n15() + fun_l7_n603 +end + +def fun_l6_n16() + fun_l7_n670 +end + +def fun_l6_n17() + fun_l7_n270 +end + +def fun_l6_n18() + fun_l7_n10 +end + +def fun_l6_n19() + fun_l7_n963 +end + +def fun_l6_n20() + fun_l7_n517 +end + +def fun_l6_n21() + fun_l7_n956 +end + +def fun_l6_n22() + fun_l7_n13 +end + +def fun_l6_n23() + fun_l7_n157 +end + +def fun_l6_n24() + fun_l7_n828 +end + +def fun_l6_n25() + fun_l7_n895 +end + +def fun_l6_n26() + fun_l7_n48 +end + +def fun_l6_n27() + fun_l7_n760 +end + +def fun_l6_n28() + fun_l7_n674 +end + +def fun_l6_n29() + fun_l7_n639 +end + +def fun_l6_n30() + fun_l7_n395 +end + +def fun_l6_n31() + fun_l7_n541 +end + +def fun_l6_n32() + fun_l7_n548 +end + +def fun_l6_n33() + fun_l7_n348 +end + +def fun_l6_n34() + fun_l7_n257 +end + +def fun_l6_n35() + fun_l7_n531 +end + +def fun_l6_n36() + fun_l7_n210 +end + +def fun_l6_n37() + fun_l7_n56 +end + +def fun_l6_n38() + fun_l7_n466 +end + +def fun_l6_n39() + fun_l7_n369 +end + +def fun_l6_n40() + fun_l7_n465 +end + +def fun_l6_n41() + fun_l7_n665 +end + +def fun_l6_n42() + fun_l7_n662 +end + +def fun_l6_n43() + fun_l7_n205 +end + +def fun_l6_n44() + fun_l7_n997 +end + +def fun_l6_n45() + fun_l7_n840 +end + +def fun_l6_n46() + fun_l7_n998 +end + +def fun_l6_n47() + fun_l7_n563 +end + +def fun_l6_n48() + fun_l7_n442 +end + +def fun_l6_n49() + fun_l7_n768 +end + +def fun_l6_n50() + fun_l7_n948 +end + +def fun_l6_n51() + fun_l7_n773 +end + +def fun_l6_n52() + fun_l7_n910 +end + +def fun_l6_n53() + fun_l7_n152 +end + +def fun_l6_n54() + fun_l7_n277 +end + +def fun_l6_n55() + fun_l7_n139 +end + +def fun_l6_n56() + fun_l7_n530 +end + +def fun_l6_n57() + fun_l7_n587 +end + +def fun_l6_n58() + fun_l7_n650 +end + +def fun_l6_n59() + fun_l7_n30 +end + +def fun_l6_n60() + fun_l7_n31 +end + +def fun_l6_n61() + fun_l7_n908 +end + +def fun_l6_n62() + fun_l7_n228 +end + +def fun_l6_n63() + fun_l7_n210 +end + +def fun_l6_n64() + fun_l7_n854 +end + +def fun_l6_n65() + fun_l7_n198 +end + +def fun_l6_n66() + fun_l7_n183 +end + +def fun_l6_n67() + fun_l7_n633 +end + +def fun_l6_n68() + fun_l7_n523 +end + +def fun_l6_n69() + fun_l7_n392 +end + +def fun_l6_n70() + fun_l7_n293 +end + +def fun_l6_n71() + fun_l7_n523 +end + +def fun_l6_n72() + fun_l7_n314 +end + +def fun_l6_n73() + fun_l7_n500 +end + +def fun_l6_n74() + fun_l7_n685 +end + +def fun_l6_n75() + fun_l7_n692 +end + +def fun_l6_n76() + fun_l7_n773 +end + +def fun_l6_n77() + fun_l7_n582 +end + +def fun_l6_n78() + fun_l7_n934 +end + +def fun_l6_n79() + fun_l7_n829 +end + +def fun_l6_n80() + fun_l7_n603 +end + +def fun_l6_n81() + fun_l7_n735 +end + +def fun_l6_n82() + fun_l7_n906 +end + +def fun_l6_n83() + fun_l7_n828 +end + +def fun_l6_n84() + fun_l7_n945 +end + +def fun_l6_n85() + fun_l7_n316 +end + +def fun_l6_n86() + fun_l7_n135 +end + +def fun_l6_n87() + fun_l7_n444 +end + +def fun_l6_n88() + fun_l7_n300 +end + +def fun_l6_n89() + fun_l7_n975 +end + +def fun_l6_n90() + fun_l7_n385 +end + +def fun_l6_n91() + fun_l7_n885 +end + +def fun_l6_n92() + fun_l7_n838 +end + +def fun_l6_n93() + fun_l7_n769 +end + +def fun_l6_n94() + fun_l7_n263 +end + +def fun_l6_n95() + fun_l7_n719 +end + +def fun_l6_n96() + fun_l7_n585 +end + +def fun_l6_n97() + fun_l7_n238 +end + +def fun_l6_n98() + fun_l7_n366 +end + +def fun_l6_n99() + fun_l7_n498 +end + +def fun_l6_n100() + fun_l7_n596 +end + +def fun_l6_n101() + fun_l7_n437 +end + +def fun_l6_n102() + fun_l7_n441 +end + +def fun_l6_n103() + fun_l7_n721 +end + +def fun_l6_n104() + fun_l7_n9 +end + +def fun_l6_n105() + fun_l7_n412 +end + +def fun_l6_n106() + fun_l7_n981 +end + +def fun_l6_n107() + fun_l7_n824 +end + +def fun_l6_n108() + fun_l7_n255 +end + +def fun_l6_n109() + fun_l7_n608 +end + +def fun_l6_n110() + fun_l7_n481 +end + +def fun_l6_n111() + fun_l7_n804 +end + +def fun_l6_n112() + fun_l7_n316 +end + +def fun_l6_n113() + fun_l7_n446 +end + +def fun_l6_n114() + fun_l7_n123 +end + +def fun_l6_n115() + fun_l7_n522 +end + +def fun_l6_n116() + fun_l7_n52 +end + +def fun_l6_n117() + fun_l7_n559 +end + +def fun_l6_n118() + fun_l7_n937 +end + +def fun_l6_n119() + fun_l7_n425 +end + +def fun_l6_n120() + fun_l7_n112 +end + +def fun_l6_n121() + fun_l7_n83 +end + +def fun_l6_n122() + fun_l7_n305 +end + +def fun_l6_n123() + fun_l7_n157 +end + +def fun_l6_n124() + fun_l7_n944 +end + +def fun_l6_n125() + fun_l7_n356 +end + +def fun_l6_n126() + fun_l7_n69 +end + +def fun_l6_n127() + fun_l7_n689 +end + +def fun_l6_n128() + fun_l7_n145 +end + +def fun_l6_n129() + fun_l7_n633 +end + +def fun_l6_n130() + fun_l7_n389 +end + +def fun_l6_n131() + fun_l7_n646 +end + +def fun_l6_n132() + fun_l7_n684 +end + +def fun_l6_n133() + fun_l7_n38 +end + +def fun_l6_n134() + fun_l7_n104 +end + +def fun_l6_n135() + fun_l7_n856 +end + +def fun_l6_n136() + fun_l7_n237 +end + +def fun_l6_n137() + fun_l7_n594 +end + +def fun_l6_n138() + fun_l7_n929 +end + +def fun_l6_n139() + fun_l7_n686 +end + +def fun_l6_n140() + fun_l7_n501 +end + +def fun_l6_n141() + fun_l7_n309 +end + +def fun_l6_n142() + fun_l7_n567 +end + +def fun_l6_n143() + fun_l7_n451 +end + +def fun_l6_n144() + fun_l7_n325 +end + +def fun_l6_n145() + fun_l7_n363 +end + +def fun_l6_n146() + fun_l7_n650 +end + +def fun_l6_n147() + fun_l7_n551 +end + +def fun_l6_n148() + fun_l7_n495 +end + +def fun_l6_n149() + fun_l7_n998 +end + +def fun_l6_n150() + fun_l7_n584 +end + +def fun_l6_n151() + fun_l7_n36 +end + +def fun_l6_n152() + fun_l7_n109 +end + +def fun_l6_n153() + fun_l7_n855 +end + +def fun_l6_n154() + fun_l7_n544 +end + +def fun_l6_n155() + fun_l7_n580 +end + +def fun_l6_n156() + fun_l7_n872 +end + +def fun_l6_n157() + fun_l7_n954 +end + +def fun_l6_n158() + fun_l7_n14 +end + +def fun_l6_n159() + fun_l7_n802 +end + +def fun_l6_n160() + fun_l7_n298 +end + +def fun_l6_n161() + fun_l7_n876 +end + +def fun_l6_n162() + fun_l7_n694 +end + +def fun_l6_n163() + fun_l7_n538 +end + +def fun_l6_n164() + fun_l7_n325 +end + +def fun_l6_n165() + fun_l7_n47 +end + +def fun_l6_n166() + fun_l7_n433 +end + +def fun_l6_n167() + fun_l7_n356 +end + +def fun_l6_n168() + fun_l7_n81 +end + +def fun_l6_n169() + fun_l7_n10 +end + +def fun_l6_n170() + fun_l7_n391 +end + +def fun_l6_n171() + fun_l7_n770 +end + +def fun_l6_n172() + fun_l7_n45 +end + +def fun_l6_n173() + fun_l7_n808 +end + +def fun_l6_n174() + fun_l7_n722 +end + +def fun_l6_n175() + fun_l7_n532 +end + +def fun_l6_n176() + fun_l7_n983 +end + +def fun_l6_n177() + fun_l7_n666 +end + +def fun_l6_n178() + fun_l7_n505 +end + +def fun_l6_n179() + fun_l7_n200 +end + +def fun_l6_n180() + fun_l7_n57 +end + +def fun_l6_n181() + fun_l7_n888 +end + +def fun_l6_n182() + fun_l7_n288 +end + +def fun_l6_n183() + fun_l7_n435 +end + +def fun_l6_n184() + fun_l7_n330 +end + +def fun_l6_n185() + fun_l7_n432 +end + +def fun_l6_n186() + fun_l7_n321 +end + +def fun_l6_n187() + fun_l7_n160 +end + +def fun_l6_n188() + fun_l7_n806 +end + +def fun_l6_n189() + fun_l7_n929 +end + +def fun_l6_n190() + fun_l7_n49 +end + +def fun_l6_n191() + fun_l7_n642 +end + +def fun_l6_n192() + fun_l7_n551 +end + +def fun_l6_n193() + fun_l7_n243 +end + +def fun_l6_n194() + fun_l7_n126 +end + +def fun_l6_n195() + fun_l7_n594 +end + +def fun_l6_n196() + fun_l7_n166 +end + +def fun_l6_n197() + fun_l7_n610 +end + +def fun_l6_n198() + fun_l7_n730 +end + +def fun_l6_n199() + fun_l7_n770 +end + +def fun_l6_n200() + fun_l7_n873 +end + +def fun_l6_n201() + fun_l7_n833 +end + +def fun_l6_n202() + fun_l7_n883 +end + +def fun_l6_n203() + fun_l7_n639 +end + +def fun_l6_n204() + fun_l7_n563 +end + +def fun_l6_n205() + fun_l7_n437 +end + +def fun_l6_n206() + fun_l7_n722 +end + +def fun_l6_n207() + fun_l7_n785 +end + +def fun_l6_n208() + fun_l7_n241 +end + +def fun_l6_n209() + fun_l7_n42 +end + +def fun_l6_n210() + fun_l7_n352 +end + +def fun_l6_n211() + fun_l7_n633 +end + +def fun_l6_n212() + fun_l7_n758 +end + +def fun_l6_n213() + fun_l7_n194 +end + +def fun_l6_n214() + fun_l7_n864 +end + +def fun_l6_n215() + fun_l7_n407 +end + +def fun_l6_n216() + fun_l7_n78 +end + +def fun_l6_n217() + fun_l7_n723 +end + +def fun_l6_n218() + fun_l7_n98 +end + +def fun_l6_n219() + fun_l7_n909 +end + +def fun_l6_n220() + fun_l7_n380 +end + +def fun_l6_n221() + fun_l7_n348 +end + +def fun_l6_n222() + fun_l7_n934 +end + +def fun_l6_n223() + fun_l7_n114 +end + +def fun_l6_n224() + fun_l7_n34 +end + +def fun_l6_n225() + fun_l7_n774 +end + +def fun_l6_n226() + fun_l7_n681 +end + +def fun_l6_n227() + fun_l7_n215 +end + +def fun_l6_n228() + fun_l7_n526 +end + +def fun_l6_n229() + fun_l7_n38 +end + +def fun_l6_n230() + fun_l7_n506 +end + +def fun_l6_n231() + fun_l7_n456 +end + +def fun_l6_n232() + fun_l7_n476 +end + +def fun_l6_n233() + fun_l7_n183 +end + +def fun_l6_n234() + fun_l7_n73 +end + +def fun_l6_n235() + fun_l7_n639 +end + +def fun_l6_n236() + fun_l7_n344 +end + +def fun_l6_n237() + fun_l7_n656 +end + +def fun_l6_n238() + fun_l7_n887 +end + +def fun_l6_n239() + fun_l7_n705 +end + +def fun_l6_n240() + fun_l7_n342 +end + +def fun_l6_n241() + fun_l7_n461 +end + +def fun_l6_n242() + fun_l7_n215 +end + +def fun_l6_n243() + fun_l7_n74 +end + +def fun_l6_n244() + fun_l7_n715 +end + +def fun_l6_n245() + fun_l7_n317 +end + +def fun_l6_n246() + fun_l7_n238 +end + +def fun_l6_n247() + fun_l7_n899 +end + +def fun_l6_n248() + fun_l7_n360 +end + +def fun_l6_n249() + fun_l7_n753 +end + +def fun_l6_n250() + fun_l7_n722 +end + +def fun_l6_n251() + fun_l7_n649 +end + +def fun_l6_n252() + fun_l7_n640 +end + +def fun_l6_n253() + fun_l7_n146 +end + +def fun_l6_n254() + fun_l7_n385 +end + +def fun_l6_n255() + fun_l7_n483 +end + +def fun_l6_n256() + fun_l7_n142 +end + +def fun_l6_n257() + fun_l7_n815 +end + +def fun_l6_n258() + fun_l7_n499 +end + +def fun_l6_n259() + fun_l7_n827 +end + +def fun_l6_n260() + fun_l7_n799 +end + +def fun_l6_n261() + fun_l7_n633 +end + +def fun_l6_n262() + fun_l7_n399 +end + +def fun_l6_n263() + fun_l7_n123 +end + +def fun_l6_n264() + fun_l7_n94 +end + +def fun_l6_n265() + fun_l7_n799 +end + +def fun_l6_n266() + fun_l7_n884 +end + +def fun_l6_n267() + fun_l7_n983 +end + +def fun_l6_n268() + fun_l7_n880 +end + +def fun_l6_n269() + fun_l7_n58 +end + +def fun_l6_n270() + fun_l7_n181 +end + +def fun_l6_n271() + fun_l7_n241 +end + +def fun_l6_n272() + fun_l7_n971 +end + +def fun_l6_n273() + fun_l7_n297 +end + +def fun_l6_n274() + fun_l7_n435 +end + +def fun_l6_n275() + fun_l7_n57 +end + +def fun_l6_n276() + fun_l7_n665 +end + +def fun_l6_n277() + fun_l7_n725 +end + +def fun_l6_n278() + fun_l7_n258 +end + +def fun_l6_n279() + fun_l7_n680 +end + +def fun_l6_n280() + fun_l7_n969 +end + +def fun_l6_n281() + fun_l7_n714 +end + +def fun_l6_n282() + fun_l7_n166 +end + +def fun_l6_n283() + fun_l7_n876 +end + +def fun_l6_n284() + fun_l7_n893 +end + +def fun_l6_n285() + fun_l7_n530 +end + +def fun_l6_n286() + fun_l7_n552 +end + +def fun_l6_n287() + fun_l7_n212 +end + +def fun_l6_n288() + fun_l7_n194 +end + +def fun_l6_n289() + fun_l7_n375 +end + +def fun_l6_n290() + fun_l7_n726 +end + +def fun_l6_n291() + fun_l7_n498 +end + +def fun_l6_n292() + fun_l7_n630 +end + +def fun_l6_n293() + fun_l7_n781 +end + +def fun_l6_n294() + fun_l7_n122 +end + +def fun_l6_n295() + fun_l7_n864 +end + +def fun_l6_n296() + fun_l7_n931 +end + +def fun_l6_n297() + fun_l7_n561 +end + +def fun_l6_n298() + fun_l7_n891 +end + +def fun_l6_n299() + fun_l7_n149 +end + +def fun_l6_n300() + fun_l7_n697 +end + +def fun_l6_n301() + fun_l7_n152 +end + +def fun_l6_n302() + fun_l7_n973 +end + +def fun_l6_n303() + fun_l7_n32 +end + +def fun_l6_n304() + fun_l7_n254 +end + +def fun_l6_n305() + fun_l7_n68 +end + +def fun_l6_n306() + fun_l7_n46 +end + +def fun_l6_n307() + fun_l7_n2 +end + +def fun_l6_n308() + fun_l7_n862 +end + +def fun_l6_n309() + fun_l7_n722 +end + +def fun_l6_n310() + fun_l7_n501 +end + +def fun_l6_n311() + fun_l7_n779 +end + +def fun_l6_n312() + fun_l7_n899 +end + +def fun_l6_n313() + fun_l7_n209 +end + +def fun_l6_n314() + fun_l7_n445 +end + +def fun_l6_n315() + fun_l7_n882 +end + +def fun_l6_n316() + fun_l7_n825 +end + +def fun_l6_n317() + fun_l7_n52 +end + +def fun_l6_n318() + fun_l7_n813 +end + +def fun_l6_n319() + fun_l7_n103 +end + +def fun_l6_n320() + fun_l7_n480 +end + +def fun_l6_n321() + fun_l7_n357 +end + +def fun_l6_n322() + fun_l7_n138 +end + +def fun_l6_n323() + fun_l7_n277 +end + +def fun_l6_n324() + fun_l7_n287 +end + +def fun_l6_n325() + fun_l7_n822 +end + +def fun_l6_n326() + fun_l7_n299 +end + +def fun_l6_n327() + fun_l7_n617 +end + +def fun_l6_n328() + fun_l7_n618 +end + +def fun_l6_n329() + fun_l7_n721 +end + +def fun_l6_n330() + fun_l7_n600 +end + +def fun_l6_n331() + fun_l7_n349 +end + +def fun_l6_n332() + fun_l7_n978 +end + +def fun_l6_n333() + fun_l7_n889 +end + +def fun_l6_n334() + fun_l7_n129 +end + +def fun_l6_n335() + fun_l7_n404 +end + +def fun_l6_n336() + fun_l7_n169 +end + +def fun_l6_n337() + fun_l7_n498 +end + +def fun_l6_n338() + fun_l7_n428 +end + +def fun_l6_n339() + fun_l7_n910 +end + +def fun_l6_n340() + fun_l7_n441 +end + +def fun_l6_n341() + fun_l7_n649 +end + +def fun_l6_n342() + fun_l7_n251 +end + +def fun_l6_n343() + fun_l7_n146 +end + +def fun_l6_n344() + fun_l7_n979 +end + +def fun_l6_n345() + fun_l7_n561 +end + +def fun_l6_n346() + fun_l7_n667 +end + +def fun_l6_n347() + fun_l7_n50 +end + +def fun_l6_n348() + fun_l7_n324 +end + +def fun_l6_n349() + fun_l7_n60 +end + +def fun_l6_n350() + fun_l7_n292 +end + +def fun_l6_n351() + fun_l7_n227 +end + +def fun_l6_n352() + fun_l7_n99 +end + +def fun_l6_n353() + fun_l7_n124 +end + +def fun_l6_n354() + fun_l7_n519 +end + +def fun_l6_n355() + fun_l7_n245 +end + +def fun_l6_n356() + fun_l7_n438 +end + +def fun_l6_n357() + fun_l7_n916 +end + +def fun_l6_n358() + fun_l7_n865 +end + +def fun_l6_n359() + fun_l7_n886 +end + +def fun_l6_n360() + fun_l7_n432 +end + +def fun_l6_n361() + fun_l7_n406 +end + +def fun_l6_n362() + fun_l7_n709 +end + +def fun_l6_n363() + fun_l7_n271 +end + +def fun_l6_n364() + fun_l7_n320 +end + +def fun_l6_n365() + fun_l7_n3 +end + +def fun_l6_n366() + fun_l7_n831 +end + +def fun_l6_n367() + fun_l7_n417 +end + +def fun_l6_n368() + fun_l7_n949 +end + +def fun_l6_n369() + fun_l7_n941 +end + +def fun_l6_n370() + fun_l7_n404 +end + +def fun_l6_n371() + fun_l7_n715 +end + +def fun_l6_n372() + fun_l7_n223 +end + +def fun_l6_n373() + fun_l7_n813 +end + +def fun_l6_n374() + fun_l7_n594 +end + +def fun_l6_n375() + fun_l7_n949 +end + +def fun_l6_n376() + fun_l7_n107 +end + +def fun_l6_n377() + fun_l7_n951 +end + +def fun_l6_n378() + fun_l7_n940 +end + +def fun_l6_n379() + fun_l7_n224 +end + +def fun_l6_n380() + fun_l7_n82 +end + +def fun_l6_n381() + fun_l7_n815 +end + +def fun_l6_n382() + fun_l7_n443 +end + +def fun_l6_n383() + fun_l7_n566 +end + +def fun_l6_n384() + fun_l7_n954 +end + +def fun_l6_n385() + fun_l7_n562 +end + +def fun_l6_n386() + fun_l7_n9 +end + +def fun_l6_n387() + fun_l7_n233 +end + +def fun_l6_n388() + fun_l7_n510 +end + +def fun_l6_n389() + fun_l7_n616 +end + +def fun_l6_n390() + fun_l7_n991 +end + +def fun_l6_n391() + fun_l7_n184 +end + +def fun_l6_n392() + fun_l7_n288 +end + +def fun_l6_n393() + fun_l7_n282 +end + +def fun_l6_n394() + fun_l7_n81 +end + +def fun_l6_n395() + fun_l7_n567 +end + +def fun_l6_n396() + fun_l7_n465 +end + +def fun_l6_n397() + fun_l7_n856 +end + +def fun_l6_n398() + fun_l7_n268 +end + +def fun_l6_n399() + fun_l7_n695 +end + +def fun_l6_n400() + fun_l7_n403 +end + +def fun_l6_n401() + fun_l7_n153 +end + +def fun_l6_n402() + fun_l7_n321 +end + +def fun_l6_n403() + fun_l7_n233 +end + +def fun_l6_n404() + fun_l7_n218 +end + +def fun_l6_n405() + fun_l7_n285 +end + +def fun_l6_n406() + fun_l7_n829 +end + +def fun_l6_n407() + fun_l7_n218 +end + +def fun_l6_n408() + fun_l7_n457 +end + +def fun_l6_n409() + fun_l7_n513 +end + +def fun_l6_n410() + fun_l7_n677 +end + +def fun_l6_n411() + fun_l7_n849 +end + +def fun_l6_n412() + fun_l7_n579 +end + +def fun_l6_n413() + fun_l7_n160 +end + +def fun_l6_n414() + fun_l7_n567 +end + +def fun_l6_n415() + fun_l7_n394 +end + +def fun_l6_n416() + fun_l7_n480 +end + +def fun_l6_n417() + fun_l7_n234 +end + +def fun_l6_n418() + fun_l7_n410 +end + +def fun_l6_n419() + fun_l7_n405 +end + +def fun_l6_n420() + fun_l7_n497 +end + +def fun_l6_n421() + fun_l7_n242 +end + +def fun_l6_n422() + fun_l7_n190 +end + +def fun_l6_n423() + fun_l7_n513 +end + +def fun_l6_n424() + fun_l7_n790 +end + +def fun_l6_n425() + fun_l7_n112 +end + +def fun_l6_n426() + fun_l7_n792 +end + +def fun_l6_n427() + fun_l7_n209 +end + +def fun_l6_n428() + fun_l7_n451 +end + +def fun_l6_n429() + fun_l7_n897 +end + +def fun_l6_n430() + fun_l7_n884 +end + +def fun_l6_n431() + fun_l7_n81 +end + +def fun_l6_n432() + fun_l7_n764 +end + +def fun_l6_n433() + fun_l7_n204 +end + +def fun_l6_n434() + fun_l7_n56 +end + +def fun_l6_n435() + fun_l7_n394 +end + +def fun_l6_n436() + fun_l7_n903 +end + +def fun_l6_n437() + fun_l7_n423 +end + +def fun_l6_n438() + fun_l7_n899 +end + +def fun_l6_n439() + fun_l7_n40 +end + +def fun_l6_n440() + fun_l7_n145 +end + +def fun_l6_n441() + fun_l7_n811 +end + +def fun_l6_n442() + fun_l7_n821 +end + +def fun_l6_n443() + fun_l7_n675 +end + +def fun_l6_n444() + fun_l7_n665 +end + +def fun_l6_n445() + fun_l7_n1 +end + +def fun_l6_n446() + fun_l7_n936 +end + +def fun_l6_n447() + fun_l7_n838 +end + +def fun_l6_n448() + fun_l7_n820 +end + +def fun_l6_n449() + fun_l7_n206 +end + +def fun_l6_n450() + fun_l7_n234 +end + +def fun_l6_n451() + fun_l7_n150 +end + +def fun_l6_n452() + fun_l7_n699 +end + +def fun_l6_n453() + fun_l7_n369 +end + +def fun_l6_n454() + fun_l7_n759 +end + +def fun_l6_n455() + fun_l7_n836 +end + +def fun_l6_n456() + fun_l7_n55 +end + +def fun_l6_n457() + fun_l7_n457 +end + +def fun_l6_n458() + fun_l7_n623 +end + +def fun_l6_n459() + fun_l7_n679 +end + +def fun_l6_n460() + fun_l7_n199 +end + +def fun_l6_n461() + fun_l7_n738 +end + +def fun_l6_n462() + fun_l7_n479 +end + +def fun_l6_n463() + fun_l7_n673 +end + +def fun_l6_n464() + fun_l7_n323 +end + +def fun_l6_n465() + fun_l7_n652 +end + +def fun_l6_n466() + fun_l7_n470 +end + +def fun_l6_n467() + fun_l7_n133 +end + +def fun_l6_n468() + fun_l7_n179 +end + +def fun_l6_n469() + fun_l7_n647 +end + +def fun_l6_n470() + fun_l7_n869 +end + +def fun_l6_n471() + fun_l7_n553 +end + +def fun_l6_n472() + fun_l7_n173 +end + +def fun_l6_n473() + fun_l7_n188 +end + +def fun_l6_n474() + fun_l7_n530 +end + +def fun_l6_n475() + fun_l7_n233 +end + +def fun_l6_n476() + fun_l7_n46 +end + +def fun_l6_n477() + fun_l7_n892 +end + +def fun_l6_n478() + fun_l7_n879 +end + +def fun_l6_n479() + fun_l7_n507 +end + +def fun_l6_n480() + fun_l7_n383 +end + +def fun_l6_n481() + fun_l7_n500 +end + +def fun_l6_n482() + fun_l7_n595 +end + +def fun_l6_n483() + fun_l7_n225 +end + +def fun_l6_n484() + fun_l7_n396 +end + +def fun_l6_n485() + fun_l7_n61 +end + +def fun_l6_n486() + fun_l7_n953 +end + +def fun_l6_n487() + fun_l7_n891 +end + +def fun_l6_n488() + fun_l7_n620 +end + +def fun_l6_n489() + fun_l7_n672 +end + +def fun_l6_n490() + fun_l7_n824 +end + +def fun_l6_n491() + fun_l7_n216 +end + +def fun_l6_n492() + fun_l7_n404 +end + +def fun_l6_n493() + fun_l7_n428 +end + +def fun_l6_n494() + fun_l7_n907 +end + +def fun_l6_n495() + fun_l7_n297 +end + +def fun_l6_n496() + fun_l7_n349 +end + +def fun_l6_n497() + fun_l7_n291 +end + +def fun_l6_n498() + fun_l7_n642 +end + +def fun_l6_n499() + fun_l7_n906 +end + +def fun_l6_n500() + fun_l7_n78 +end + +def fun_l6_n501() + fun_l7_n568 +end + +def fun_l6_n502() + fun_l7_n591 +end + +def fun_l6_n503() + fun_l7_n921 +end + +def fun_l6_n504() + fun_l7_n832 +end + +def fun_l6_n505() + fun_l7_n826 +end + +def fun_l6_n506() + fun_l7_n930 +end + +def fun_l6_n507() + fun_l7_n791 +end + +def fun_l6_n508() + fun_l7_n608 +end + +def fun_l6_n509() + fun_l7_n144 +end + +def fun_l6_n510() + fun_l7_n202 +end + +def fun_l6_n511() + fun_l7_n379 +end + +def fun_l6_n512() + fun_l7_n354 +end + +def fun_l6_n513() + fun_l7_n245 +end + +def fun_l6_n514() + fun_l7_n402 +end + +def fun_l6_n515() + fun_l7_n875 +end + +def fun_l6_n516() + fun_l7_n847 +end + +def fun_l6_n517() + fun_l7_n736 +end + +def fun_l6_n518() + fun_l7_n325 +end + +def fun_l6_n519() + fun_l7_n949 +end + +def fun_l6_n520() + fun_l7_n993 +end + +def fun_l6_n521() + fun_l7_n271 +end + +def fun_l6_n522() + fun_l7_n799 +end + +def fun_l6_n523() + fun_l7_n861 +end + +def fun_l6_n524() + fun_l7_n164 +end + +def fun_l6_n525() + fun_l7_n293 +end + +def fun_l6_n526() + fun_l7_n948 +end + +def fun_l6_n527() + fun_l7_n682 +end + +def fun_l6_n528() + fun_l7_n914 +end + +def fun_l6_n529() + fun_l7_n395 +end + +def fun_l6_n530() + fun_l7_n399 +end + +def fun_l6_n531() + fun_l7_n220 +end + +def fun_l6_n532() + fun_l7_n874 +end + +def fun_l6_n533() + fun_l7_n504 +end + +def fun_l6_n534() + fun_l7_n713 +end + +def fun_l6_n535() + fun_l7_n185 +end + +def fun_l6_n536() + fun_l7_n229 +end + +def fun_l6_n537() + fun_l7_n696 +end + +def fun_l6_n538() + fun_l7_n840 +end + +def fun_l6_n539() + fun_l7_n323 +end + +def fun_l6_n540() + fun_l7_n342 +end + +def fun_l6_n541() + fun_l7_n60 +end + +def fun_l6_n542() + fun_l7_n149 +end + +def fun_l6_n543() + fun_l7_n465 +end + +def fun_l6_n544() + fun_l7_n392 +end + +def fun_l6_n545() + fun_l7_n210 +end + +def fun_l6_n546() + fun_l7_n565 +end + +def fun_l6_n547() + fun_l7_n63 +end + +def fun_l6_n548() + fun_l7_n722 +end + +def fun_l6_n549() + fun_l7_n119 +end + +def fun_l6_n550() + fun_l7_n933 +end + +def fun_l6_n551() + fun_l7_n612 +end + +def fun_l6_n552() + fun_l7_n479 +end + +def fun_l6_n553() + fun_l7_n866 +end + +def fun_l6_n554() + fun_l7_n268 +end + +def fun_l6_n555() + fun_l7_n547 +end + +def fun_l6_n556() + fun_l7_n621 +end + +def fun_l6_n557() + fun_l7_n461 +end + +def fun_l6_n558() + fun_l7_n907 +end + +def fun_l6_n559() + fun_l7_n660 +end + +def fun_l6_n560() + fun_l7_n857 +end + +def fun_l6_n561() + fun_l7_n398 +end + +def fun_l6_n562() + fun_l7_n484 +end + +def fun_l6_n563() + fun_l7_n16 +end + +def fun_l6_n564() + fun_l7_n697 +end + +def fun_l6_n565() + fun_l7_n135 +end + +def fun_l6_n566() + fun_l7_n265 +end + +def fun_l6_n567() + fun_l7_n627 +end + +def fun_l6_n568() + fun_l7_n345 +end + +def fun_l6_n569() + fun_l7_n528 +end + +def fun_l6_n570() + fun_l7_n926 +end + +def fun_l6_n571() + fun_l7_n198 +end + +def fun_l6_n572() + fun_l7_n837 +end + +def fun_l6_n573() + fun_l7_n95 +end + +def fun_l6_n574() + fun_l7_n802 +end + +def fun_l6_n575() + fun_l7_n265 +end + +def fun_l6_n576() + fun_l7_n884 +end + +def fun_l6_n577() + fun_l7_n227 +end + +def fun_l6_n578() + fun_l7_n915 +end + +def fun_l6_n579() + fun_l7_n221 +end + +def fun_l6_n580() + fun_l7_n718 +end + +def fun_l6_n581() + fun_l7_n179 +end + +def fun_l6_n582() + fun_l7_n975 +end + +def fun_l6_n583() + fun_l7_n207 +end + +def fun_l6_n584() + fun_l7_n874 +end + +def fun_l6_n585() + fun_l7_n540 +end + +def fun_l6_n586() + fun_l7_n765 +end + +def fun_l6_n587() + fun_l7_n613 +end + +def fun_l6_n588() + fun_l7_n853 +end + +def fun_l6_n589() + fun_l7_n241 +end + +def fun_l6_n590() + fun_l7_n91 +end + +def fun_l6_n591() + fun_l7_n383 +end + +def fun_l6_n592() + fun_l7_n567 +end + +def fun_l6_n593() + fun_l7_n144 +end + +def fun_l6_n594() + fun_l7_n663 +end + +def fun_l6_n595() + fun_l7_n674 +end + +def fun_l6_n596() + fun_l7_n407 +end + +def fun_l6_n597() + fun_l7_n207 +end + +def fun_l6_n598() + fun_l7_n746 +end + +def fun_l6_n599() + fun_l7_n24 +end + +def fun_l6_n600() + fun_l7_n150 +end + +def fun_l6_n601() + fun_l7_n317 +end + +def fun_l6_n602() + fun_l7_n773 +end + +def fun_l6_n603() + fun_l7_n932 +end + +def fun_l6_n604() + fun_l7_n772 +end + +def fun_l6_n605() + fun_l7_n495 +end + +def fun_l6_n606() + fun_l7_n526 +end + +def fun_l6_n607() + fun_l7_n758 +end + +def fun_l6_n608() + fun_l7_n941 +end + +def fun_l6_n609() + fun_l7_n998 +end + +def fun_l6_n610() + fun_l7_n543 +end + +def fun_l6_n611() + fun_l7_n216 +end + +def fun_l6_n612() + fun_l7_n445 +end + +def fun_l6_n613() + fun_l7_n314 +end + +def fun_l6_n614() + fun_l7_n840 +end + +def fun_l6_n615() + fun_l7_n722 +end + +def fun_l6_n616() + fun_l7_n89 +end + +def fun_l6_n617() + fun_l7_n353 +end + +def fun_l6_n618() + fun_l7_n800 +end + +def fun_l6_n619() + fun_l7_n736 +end + +def fun_l6_n620() + fun_l7_n376 +end + +def fun_l6_n621() + fun_l7_n24 +end + +def fun_l6_n622() + fun_l7_n258 +end + +def fun_l6_n623() + fun_l7_n943 +end + +def fun_l6_n624() + fun_l7_n963 +end + +def fun_l6_n625() + fun_l7_n709 +end + +def fun_l6_n626() + fun_l7_n350 +end + +def fun_l6_n627() + fun_l7_n322 +end + +def fun_l6_n628() + fun_l7_n717 +end + +def fun_l6_n629() + fun_l7_n529 +end + +def fun_l6_n630() + fun_l7_n365 +end + +def fun_l6_n631() + fun_l7_n977 +end + +def fun_l6_n632() + fun_l7_n606 +end + +def fun_l6_n633() + fun_l7_n712 +end + +def fun_l6_n634() + fun_l7_n559 +end + +def fun_l6_n635() + fun_l7_n499 +end + +def fun_l6_n636() + fun_l7_n871 +end + +def fun_l6_n637() + fun_l7_n684 +end + +def fun_l6_n638() + fun_l7_n558 +end + +def fun_l6_n639() + fun_l7_n333 +end + +def fun_l6_n640() + fun_l7_n37 +end + +def fun_l6_n641() + fun_l7_n559 +end + +def fun_l6_n642() + fun_l7_n17 +end + +def fun_l6_n643() + fun_l7_n913 +end + +def fun_l6_n644() + fun_l7_n79 +end + +def fun_l6_n645() + fun_l7_n402 +end + +def fun_l6_n646() + fun_l7_n268 +end + +def fun_l6_n647() + fun_l7_n797 +end + +def fun_l6_n648() + fun_l7_n985 +end + +def fun_l6_n649() + fun_l7_n192 +end + +def fun_l6_n650() + fun_l7_n774 +end + +def fun_l6_n651() + fun_l7_n805 +end + +def fun_l6_n652() + fun_l7_n208 +end + +def fun_l6_n653() + fun_l7_n608 +end + +def fun_l6_n654() + fun_l7_n714 +end + +def fun_l6_n655() + fun_l7_n883 +end + +def fun_l6_n656() + fun_l7_n841 +end + +def fun_l6_n657() + fun_l7_n646 +end + +def fun_l6_n658() + fun_l7_n39 +end + +def fun_l6_n659() + fun_l7_n432 +end + +def fun_l6_n660() + fun_l7_n177 +end + +def fun_l6_n661() + fun_l7_n700 +end + +def fun_l6_n662() + fun_l7_n815 +end + +def fun_l6_n663() + fun_l7_n553 +end + +def fun_l6_n664() + fun_l7_n540 +end + +def fun_l6_n665() + fun_l7_n853 +end + +def fun_l6_n666() + fun_l7_n526 +end + +def fun_l6_n667() + fun_l7_n670 +end + +def fun_l6_n668() + fun_l7_n753 +end + +def fun_l6_n669() + fun_l7_n811 +end + +def fun_l6_n670() + fun_l7_n782 +end + +def fun_l6_n671() + fun_l7_n275 +end + +def fun_l6_n672() + fun_l7_n884 +end + +def fun_l6_n673() + fun_l7_n984 +end + +def fun_l6_n674() + fun_l7_n980 +end + +def fun_l6_n675() + fun_l7_n341 +end + +def fun_l6_n676() + fun_l7_n346 +end + +def fun_l6_n677() + fun_l7_n164 +end + +def fun_l6_n678() + fun_l7_n600 +end + +def fun_l6_n679() + fun_l7_n351 +end + +def fun_l6_n680() + fun_l7_n527 +end + +def fun_l6_n681() + fun_l7_n206 +end + +def fun_l6_n682() + fun_l7_n50 +end + +def fun_l6_n683() + fun_l7_n476 +end + +def fun_l6_n684() + fun_l7_n684 +end + +def fun_l6_n685() + fun_l7_n883 +end + +def fun_l6_n686() + fun_l7_n41 +end + +def fun_l6_n687() + fun_l7_n382 +end + +def fun_l6_n688() + fun_l7_n418 +end + +def fun_l6_n689() + fun_l7_n22 +end + +def fun_l6_n690() + fun_l7_n543 +end + +def fun_l6_n691() + fun_l7_n143 +end + +def fun_l6_n692() + fun_l7_n120 +end + +def fun_l6_n693() + fun_l7_n431 +end + +def fun_l6_n694() + fun_l7_n405 +end + +def fun_l6_n695() + fun_l7_n474 +end + +def fun_l6_n696() + fun_l7_n117 +end + +def fun_l6_n697() + fun_l7_n475 +end + +def fun_l6_n698() + fun_l7_n674 +end + +def fun_l6_n699() + fun_l7_n398 +end + +def fun_l6_n700() + fun_l7_n709 +end + +def fun_l6_n701() + fun_l7_n360 +end + +def fun_l6_n702() + fun_l7_n241 +end + +def fun_l6_n703() + fun_l7_n837 +end + +def fun_l6_n704() + fun_l7_n483 +end + +def fun_l6_n705() + fun_l7_n943 +end + +def fun_l6_n706() + fun_l7_n292 +end + +def fun_l6_n707() + fun_l7_n659 +end + +def fun_l6_n708() + fun_l7_n657 +end + +def fun_l6_n709() + fun_l7_n143 +end + +def fun_l6_n710() + fun_l7_n883 +end + +def fun_l6_n711() + fun_l7_n764 +end + +def fun_l6_n712() + fun_l7_n421 +end + +def fun_l6_n713() + fun_l7_n611 +end + +def fun_l6_n714() + fun_l7_n657 +end + +def fun_l6_n715() + fun_l7_n765 +end + +def fun_l6_n716() + fun_l7_n793 +end + +def fun_l6_n717() + fun_l7_n752 +end + +def fun_l6_n718() + fun_l7_n713 +end + +def fun_l6_n719() + fun_l7_n577 +end + +def fun_l6_n720() + fun_l7_n422 +end + +def fun_l6_n721() + fun_l7_n368 +end + +def fun_l6_n722() + fun_l7_n2 +end + +def fun_l6_n723() + fun_l7_n739 +end + +def fun_l6_n724() + fun_l7_n481 +end + +def fun_l6_n725() + fun_l7_n516 +end + +def fun_l6_n726() + fun_l7_n266 +end + +def fun_l6_n727() + fun_l7_n269 +end + +def fun_l6_n728() + fun_l7_n308 +end + +def fun_l6_n729() + fun_l7_n915 +end + +def fun_l6_n730() + fun_l7_n603 +end + +def fun_l6_n731() + fun_l7_n585 +end + +def fun_l6_n732() + fun_l7_n182 +end + +def fun_l6_n733() + fun_l7_n28 +end + +def fun_l6_n734() + fun_l7_n829 +end + +def fun_l6_n735() + fun_l7_n365 +end + +def fun_l6_n736() + fun_l7_n208 +end + +def fun_l6_n737() + fun_l7_n395 +end + +def fun_l6_n738() + fun_l7_n745 +end + +def fun_l6_n739() + fun_l7_n90 +end + +def fun_l6_n740() + fun_l7_n696 +end + +def fun_l6_n741() + fun_l7_n730 +end + +def fun_l6_n742() + fun_l7_n143 +end + +def fun_l6_n743() + fun_l7_n753 +end + +def fun_l6_n744() + fun_l7_n484 +end + +def fun_l6_n745() + fun_l7_n779 +end + +def fun_l6_n746() + fun_l7_n668 +end + +def fun_l6_n747() + fun_l7_n331 +end + +def fun_l6_n748() + fun_l7_n961 +end + +def fun_l6_n749() + fun_l7_n875 +end + +def fun_l6_n750() + fun_l7_n541 +end + +def fun_l6_n751() + fun_l7_n122 +end + +def fun_l6_n752() + fun_l7_n278 +end + +def fun_l6_n753() + fun_l7_n510 +end + +def fun_l6_n754() + fun_l7_n619 +end + +def fun_l6_n755() + fun_l7_n165 +end + +def fun_l6_n756() + fun_l7_n537 +end + +def fun_l6_n757() + fun_l7_n917 +end + +def fun_l6_n758() + fun_l7_n102 +end + +def fun_l6_n759() + fun_l7_n504 +end + +def fun_l6_n760() + fun_l7_n768 +end + +def fun_l6_n761() + fun_l7_n259 +end + +def fun_l6_n762() + fun_l7_n371 +end + +def fun_l6_n763() + fun_l7_n727 +end + +def fun_l6_n764() + fun_l7_n959 +end + +def fun_l6_n765() + fun_l7_n191 +end + +def fun_l6_n766() + fun_l7_n570 +end + +def fun_l6_n767() + fun_l7_n746 +end + +def fun_l6_n768() + fun_l7_n133 +end + +def fun_l6_n769() + fun_l7_n520 +end + +def fun_l6_n770() + fun_l7_n602 +end + +def fun_l6_n771() + fun_l7_n722 +end + +def fun_l6_n772() + fun_l7_n165 +end + +def fun_l6_n773() + fun_l7_n132 +end + +def fun_l6_n774() + fun_l7_n328 +end + +def fun_l6_n775() + fun_l7_n88 +end + +def fun_l6_n776() + fun_l7_n296 +end + +def fun_l6_n777() + fun_l7_n389 +end + +def fun_l6_n778() + fun_l7_n433 +end + +def fun_l6_n779() + fun_l7_n525 +end + +def fun_l6_n780() + fun_l7_n736 +end + +def fun_l6_n781() + fun_l7_n300 +end + +def fun_l6_n782() + fun_l7_n663 +end + +def fun_l6_n783() + fun_l7_n33 +end + +def fun_l6_n784() + fun_l7_n964 +end + +def fun_l6_n785() + fun_l7_n459 +end + +def fun_l6_n786() + fun_l7_n397 +end + +def fun_l6_n787() + fun_l7_n453 +end + +def fun_l6_n788() + fun_l7_n951 +end + +def fun_l6_n789() + fun_l7_n485 +end + +def fun_l6_n790() + fun_l7_n480 +end + +def fun_l6_n791() + fun_l7_n663 +end + +def fun_l6_n792() + fun_l7_n245 +end + +def fun_l6_n793() + fun_l7_n933 +end + +def fun_l6_n794() + fun_l7_n253 +end + +def fun_l6_n795() + fun_l7_n746 +end + +def fun_l6_n796() + fun_l7_n242 +end + +def fun_l6_n797() + fun_l7_n435 +end + +def fun_l6_n798() + fun_l7_n982 +end + +def fun_l6_n799() + fun_l7_n516 +end + +def fun_l6_n800() + fun_l7_n118 +end + +def fun_l6_n801() + fun_l7_n787 +end + +def fun_l6_n802() + fun_l7_n13 +end + +def fun_l6_n803() + fun_l7_n381 +end + +def fun_l6_n804() + fun_l7_n601 +end + +def fun_l6_n805() + fun_l7_n95 +end + +def fun_l6_n806() + fun_l7_n589 +end + +def fun_l6_n807() + fun_l7_n33 +end + +def fun_l6_n808() + fun_l7_n801 +end + +def fun_l6_n809() + fun_l7_n857 +end + +def fun_l6_n810() + fun_l7_n23 +end + +def fun_l6_n811() + fun_l7_n998 +end + +def fun_l6_n812() + fun_l7_n424 +end + +def fun_l6_n813() + fun_l7_n525 +end + +def fun_l6_n814() + fun_l7_n428 +end + +def fun_l6_n815() + fun_l7_n509 +end + +def fun_l6_n816() + fun_l7_n599 +end + +def fun_l6_n817() + fun_l7_n642 +end + +def fun_l6_n818() + fun_l7_n381 +end + +def fun_l6_n819() + fun_l7_n802 +end + +def fun_l6_n820() + fun_l7_n324 +end + +def fun_l6_n821() + fun_l7_n804 +end + +def fun_l6_n822() + fun_l7_n743 +end + +def fun_l6_n823() + fun_l7_n961 +end + +def fun_l6_n824() + fun_l7_n222 +end + +def fun_l6_n825() + fun_l7_n184 +end + +def fun_l6_n826() + fun_l7_n157 +end + +def fun_l6_n827() + fun_l7_n387 +end + +def fun_l6_n828() + fun_l7_n963 +end + +def fun_l6_n829() + fun_l7_n817 +end + +def fun_l6_n830() + fun_l7_n673 +end + +def fun_l6_n831() + fun_l7_n471 +end + +def fun_l6_n832() + fun_l7_n662 +end + +def fun_l6_n833() + fun_l7_n385 +end + +def fun_l6_n834() + fun_l7_n802 +end + +def fun_l6_n835() + fun_l7_n827 +end + +def fun_l6_n836() + fun_l7_n495 +end + +def fun_l6_n837() + fun_l7_n44 +end + +def fun_l6_n838() + fun_l7_n958 +end + +def fun_l6_n839() + fun_l7_n436 +end + +def fun_l6_n840() + fun_l7_n210 +end + +def fun_l6_n841() + fun_l7_n14 +end + +def fun_l6_n842() + fun_l7_n67 +end + +def fun_l6_n843() + fun_l7_n0 +end + +def fun_l6_n844() + fun_l7_n50 +end + +def fun_l6_n845() + fun_l7_n398 +end + +def fun_l6_n846() + fun_l7_n269 +end + +def fun_l6_n847() + fun_l7_n478 +end + +def fun_l6_n848() + fun_l7_n879 +end + +def fun_l6_n849() + fun_l7_n713 +end + +def fun_l6_n850() + fun_l7_n496 +end + +def fun_l6_n851() + fun_l7_n995 +end + +def fun_l6_n852() + fun_l7_n973 +end + +def fun_l6_n853() + fun_l7_n990 +end + +def fun_l6_n854() + fun_l7_n193 +end + +def fun_l6_n855() + fun_l7_n200 +end + +def fun_l6_n856() + fun_l7_n377 +end + +def fun_l6_n857() + fun_l7_n82 +end + +def fun_l6_n858() + fun_l7_n261 +end + +def fun_l6_n859() + fun_l7_n464 +end + +def fun_l6_n860() + fun_l7_n358 +end + +def fun_l6_n861() + fun_l7_n920 +end + +def fun_l6_n862() + fun_l7_n724 +end + +def fun_l6_n863() + fun_l7_n536 +end + +def fun_l6_n864() + fun_l7_n127 +end + +def fun_l6_n865() + fun_l7_n919 +end + +def fun_l6_n866() + fun_l7_n972 +end + +def fun_l6_n867() + fun_l7_n773 +end + +def fun_l6_n868() + fun_l7_n444 +end + +def fun_l6_n869() + fun_l7_n242 +end + +def fun_l6_n870() + fun_l7_n910 +end + +def fun_l6_n871() + fun_l7_n396 +end + +def fun_l6_n872() + fun_l7_n110 +end + +def fun_l6_n873() + fun_l7_n393 +end + +def fun_l6_n874() + fun_l7_n295 +end + +def fun_l6_n875() + fun_l7_n998 +end + +def fun_l6_n876() + fun_l7_n357 +end + +def fun_l6_n877() + fun_l7_n586 +end + +def fun_l6_n878() + fun_l7_n752 +end + +def fun_l6_n879() + fun_l7_n998 +end + +def fun_l6_n880() + fun_l7_n33 +end + +def fun_l6_n881() + fun_l7_n472 +end + +def fun_l6_n882() + fun_l7_n511 +end + +def fun_l6_n883() + fun_l7_n677 +end + +def fun_l6_n884() + fun_l7_n562 +end + +def fun_l6_n885() + fun_l7_n100 +end + +def fun_l6_n886() + fun_l7_n964 +end + +def fun_l6_n887() + fun_l7_n306 +end + +def fun_l6_n888() + fun_l7_n295 +end + +def fun_l6_n889() + fun_l7_n323 +end + +def fun_l6_n890() + fun_l7_n559 +end + +def fun_l6_n891() + fun_l7_n872 +end + +def fun_l6_n892() + fun_l7_n236 +end + +def fun_l6_n893() + fun_l7_n845 +end + +def fun_l6_n894() + fun_l7_n853 +end + +def fun_l6_n895() + fun_l7_n333 +end + +def fun_l6_n896() + fun_l7_n404 +end + +def fun_l6_n897() + fun_l7_n17 +end + +def fun_l6_n898() + fun_l7_n997 +end + +def fun_l6_n899() + fun_l7_n844 +end + +def fun_l6_n900() + fun_l7_n327 +end + +def fun_l6_n901() + fun_l7_n863 +end + +def fun_l6_n902() + fun_l7_n516 +end + +def fun_l6_n903() + fun_l7_n298 +end + +def fun_l6_n904() + fun_l7_n171 +end + +def fun_l6_n905() + fun_l7_n908 +end + +def fun_l6_n906() + fun_l7_n934 +end + +def fun_l6_n907() + fun_l7_n361 +end + +def fun_l6_n908() + fun_l7_n901 +end + +def fun_l6_n909() + fun_l7_n830 +end + +def fun_l6_n910() + fun_l7_n313 +end + +def fun_l6_n911() + fun_l7_n799 +end + +def fun_l6_n912() + fun_l7_n223 +end + +def fun_l6_n913() + fun_l7_n108 +end + +def fun_l6_n914() + fun_l7_n822 +end + +def fun_l6_n915() + fun_l7_n42 +end + +def fun_l6_n916() + fun_l7_n276 +end + +def fun_l6_n917() + fun_l7_n535 +end + +def fun_l6_n918() + fun_l7_n586 +end + +def fun_l6_n919() + fun_l7_n847 +end + +def fun_l6_n920() + fun_l7_n851 +end + +def fun_l6_n921() + fun_l7_n544 +end + +def fun_l6_n922() + fun_l7_n416 +end + +def fun_l6_n923() + fun_l7_n670 +end + +def fun_l6_n924() + fun_l7_n366 +end + +def fun_l6_n925() + fun_l7_n94 +end + +def fun_l6_n926() + fun_l7_n187 +end + +def fun_l6_n927() + fun_l7_n72 +end + +def fun_l6_n928() + fun_l7_n19 +end + +def fun_l6_n929() + fun_l7_n424 +end + +def fun_l6_n930() + fun_l7_n833 +end + +def fun_l6_n931() + fun_l7_n438 +end + +def fun_l6_n932() + fun_l7_n9 +end + +def fun_l6_n933() + fun_l7_n967 +end + +def fun_l6_n934() + fun_l7_n155 +end + +def fun_l6_n935() + fun_l7_n119 +end + +def fun_l6_n936() + fun_l7_n916 +end + +def fun_l6_n937() + fun_l7_n232 +end + +def fun_l6_n938() + fun_l7_n880 +end + +def fun_l6_n939() + fun_l7_n456 +end + +def fun_l6_n940() + fun_l7_n764 +end + +def fun_l6_n941() + fun_l7_n525 +end + +def fun_l6_n942() + fun_l7_n794 +end + +def fun_l6_n943() + fun_l7_n887 +end + +def fun_l6_n944() + fun_l7_n756 +end + +def fun_l6_n945() + fun_l7_n863 +end + +def fun_l6_n946() + fun_l7_n959 +end + +def fun_l6_n947() + fun_l7_n597 +end + +def fun_l6_n948() + fun_l7_n919 +end + +def fun_l6_n949() + fun_l7_n196 +end + +def fun_l6_n950() + fun_l7_n505 +end + +def fun_l6_n951() + fun_l7_n374 +end + +def fun_l6_n952() + fun_l7_n272 +end + +def fun_l6_n953() + fun_l7_n317 +end + +def fun_l6_n954() + fun_l7_n149 +end + +def fun_l6_n955() + fun_l7_n885 +end + +def fun_l6_n956() + fun_l7_n174 +end + +def fun_l6_n957() + fun_l7_n234 +end + +def fun_l6_n958() + fun_l7_n848 +end + +def fun_l6_n959() + fun_l7_n18 +end + +def fun_l6_n960() + fun_l7_n111 +end + +def fun_l6_n961() + fun_l7_n355 +end + +def fun_l6_n962() + fun_l7_n640 +end + +def fun_l6_n963() + fun_l7_n486 +end + +def fun_l6_n964() + fun_l7_n940 +end + +def fun_l6_n965() + fun_l7_n54 +end + +def fun_l6_n966() + fun_l7_n970 +end + +def fun_l6_n967() + fun_l7_n127 +end + +def fun_l6_n968() + fun_l7_n581 +end + +def fun_l6_n969() + fun_l7_n921 +end + +def fun_l6_n970() + fun_l7_n837 +end + +def fun_l6_n971() + fun_l7_n933 +end + +def fun_l6_n972() + fun_l7_n109 +end + +def fun_l6_n973() + fun_l7_n846 +end + +def fun_l6_n974() + fun_l7_n178 +end + +def fun_l6_n975() + fun_l7_n278 +end + +def fun_l6_n976() + fun_l7_n404 +end + +def fun_l6_n977() + fun_l7_n456 +end + +def fun_l6_n978() + fun_l7_n860 +end + +def fun_l6_n979() + fun_l7_n637 +end + +def fun_l6_n980() + fun_l7_n201 +end + +def fun_l6_n981() + fun_l7_n836 +end + +def fun_l6_n982() + fun_l7_n172 +end + +def fun_l6_n983() + fun_l7_n935 +end + +def fun_l6_n984() + fun_l7_n937 +end + +def fun_l6_n985() + fun_l7_n817 +end + +def fun_l6_n986() + fun_l7_n16 +end + +def fun_l6_n987() + fun_l7_n152 +end + +def fun_l6_n988() + fun_l7_n359 +end + +def fun_l6_n989() + fun_l7_n357 +end + +def fun_l6_n990() + fun_l7_n609 +end + +def fun_l6_n991() + fun_l7_n604 +end + +def fun_l6_n992() + fun_l7_n998 +end + +def fun_l6_n993() + fun_l7_n366 +end + +def fun_l6_n994() + fun_l7_n150 +end + +def fun_l6_n995() + fun_l7_n823 +end + +def fun_l6_n996() + fun_l7_n476 +end + +def fun_l6_n997() + fun_l7_n535 +end + +def fun_l6_n998() + fun_l7_n222 +end + +def fun_l6_n999() + fun_l7_n238 +end + +def fun_l7_n0() + fun_l8_n3 +end + +def fun_l7_n1() + fun_l8_n706 +end + +def fun_l7_n2() + fun_l8_n887 +end + +def fun_l7_n3() + fun_l8_n693 +end + +def fun_l7_n4() + fun_l8_n11 +end + +def fun_l7_n5() + fun_l8_n155 +end + +def fun_l7_n6() + fun_l8_n604 +end + +def fun_l7_n7() + fun_l8_n616 +end + +def fun_l7_n8() + fun_l8_n686 +end + +def fun_l7_n9() + fun_l8_n257 +end + +def fun_l7_n10() + fun_l8_n594 +end + +def fun_l7_n11() + fun_l8_n548 +end + +def fun_l7_n12() + fun_l8_n305 +end + +def fun_l7_n13() + fun_l8_n125 +end + +def fun_l7_n14() + fun_l8_n183 +end + +def fun_l7_n15() + fun_l8_n799 +end + +def fun_l7_n16() + fun_l8_n333 +end + +def fun_l7_n17() + fun_l8_n873 +end + +def fun_l7_n18() + fun_l8_n110 +end + +def fun_l7_n19() + fun_l8_n578 +end + +def fun_l7_n20() + fun_l8_n423 +end + +def fun_l7_n21() + fun_l8_n686 +end + +def fun_l7_n22() + fun_l8_n162 +end + +def fun_l7_n23() + fun_l8_n277 +end + +def fun_l7_n24() + fun_l8_n651 +end + +def fun_l7_n25() + fun_l8_n575 +end + +def fun_l7_n26() + fun_l8_n937 +end + +def fun_l7_n27() + fun_l8_n636 +end + +def fun_l7_n28() + fun_l8_n1 +end + +def fun_l7_n29() + fun_l8_n83 +end + +def fun_l7_n30() + fun_l8_n318 +end + +def fun_l7_n31() + fun_l8_n675 +end + +def fun_l7_n32() + fun_l8_n118 +end + +def fun_l7_n33() + fun_l8_n522 +end + +def fun_l7_n34() + fun_l8_n507 +end + +def fun_l7_n35() + fun_l8_n846 +end + +def fun_l7_n36() + fun_l8_n584 +end + +def fun_l7_n37() + fun_l8_n816 +end + +def fun_l7_n38() + fun_l8_n217 +end + +def fun_l7_n39() + fun_l8_n366 +end + +def fun_l7_n40() + fun_l8_n283 +end + +def fun_l7_n41() + fun_l8_n536 +end + +def fun_l7_n42() + fun_l8_n414 +end + +def fun_l7_n43() + fun_l8_n216 +end + +def fun_l7_n44() + fun_l8_n743 +end + +def fun_l7_n45() + fun_l8_n449 +end + +def fun_l7_n46() + fun_l8_n629 +end + +def fun_l7_n47() + fun_l8_n711 +end + +def fun_l7_n48() + fun_l8_n113 +end + +def fun_l7_n49() + fun_l8_n440 +end + +def fun_l7_n50() + fun_l8_n822 +end + +def fun_l7_n51() + fun_l8_n567 +end + +def fun_l7_n52() + fun_l8_n854 +end + +def fun_l7_n53() + fun_l8_n204 +end + +def fun_l7_n54() + fun_l8_n796 +end + +def fun_l7_n55() + fun_l8_n989 +end + +def fun_l7_n56() + fun_l8_n504 +end + +def fun_l7_n57() + fun_l8_n952 +end + +def fun_l7_n58() + fun_l8_n797 +end + +def fun_l7_n59() + fun_l8_n492 +end + +def fun_l7_n60() + fun_l8_n949 +end + +def fun_l7_n61() + fun_l8_n215 +end + +def fun_l7_n62() + fun_l8_n306 +end + +def fun_l7_n63() + fun_l8_n632 +end + +def fun_l7_n64() + fun_l8_n572 +end + +def fun_l7_n65() + fun_l8_n69 +end + +def fun_l7_n66() + fun_l8_n97 +end + +def fun_l7_n67() + fun_l8_n708 +end + +def fun_l7_n68() + fun_l8_n548 +end + +def fun_l7_n69() + fun_l8_n999 +end + +def fun_l7_n70() + fun_l8_n872 +end + +def fun_l7_n71() + fun_l8_n20 +end + +def fun_l7_n72() + fun_l8_n220 +end + +def fun_l7_n73() + fun_l8_n28 +end + +def fun_l7_n74() + fun_l8_n79 +end + +def fun_l7_n75() + fun_l8_n248 +end + +def fun_l7_n76() + fun_l8_n601 +end + +def fun_l7_n77() + fun_l8_n469 +end + +def fun_l7_n78() + fun_l8_n315 +end + +def fun_l7_n79() + fun_l8_n712 +end + +def fun_l7_n80() + fun_l8_n177 +end + +def fun_l7_n81() + fun_l8_n106 +end + +def fun_l7_n82() + fun_l8_n668 +end + +def fun_l7_n83() + fun_l8_n299 +end + +def fun_l7_n84() + fun_l8_n59 +end + +def fun_l7_n85() + fun_l8_n120 +end + +def fun_l7_n86() + fun_l8_n209 +end + +def fun_l7_n87() + fun_l8_n502 +end + +def fun_l7_n88() + fun_l8_n935 +end + +def fun_l7_n89() + fun_l8_n697 +end + +def fun_l7_n90() + fun_l8_n231 +end + +def fun_l7_n91() + fun_l8_n47 +end + +def fun_l7_n92() + fun_l8_n125 +end + +def fun_l7_n93() + fun_l8_n975 +end + +def fun_l7_n94() + fun_l8_n627 +end + +def fun_l7_n95() + fun_l8_n898 +end + +def fun_l7_n96() + fun_l8_n124 +end + +def fun_l7_n97() + fun_l8_n722 +end + +def fun_l7_n98() + fun_l8_n745 +end + +def fun_l7_n99() + fun_l8_n999 +end + +def fun_l7_n100() + fun_l8_n791 +end + +def fun_l7_n101() + fun_l8_n360 +end + +def fun_l7_n102() + fun_l8_n755 +end + +def fun_l7_n103() + fun_l8_n718 +end + +def fun_l7_n104() + fun_l8_n495 +end + +def fun_l7_n105() + fun_l8_n19 +end + +def fun_l7_n106() + fun_l8_n280 +end + +def fun_l7_n107() + fun_l8_n710 +end + +def fun_l7_n108() + fun_l8_n871 +end + +def fun_l7_n109() + fun_l8_n727 +end + +def fun_l7_n110() + fun_l8_n807 +end + +def fun_l7_n111() + fun_l8_n170 +end + +def fun_l7_n112() + fun_l8_n661 +end + +def fun_l7_n113() + fun_l8_n684 +end + +def fun_l7_n114() + fun_l8_n202 +end + +def fun_l7_n115() + fun_l8_n679 +end + +def fun_l7_n116() + fun_l8_n773 +end + +def fun_l7_n117() + fun_l8_n538 +end + +def fun_l7_n118() + fun_l8_n411 +end + +def fun_l7_n119() + fun_l8_n264 +end + +def fun_l7_n120() + fun_l8_n487 +end + +def fun_l7_n121() + fun_l8_n906 +end + +def fun_l7_n122() + fun_l8_n833 +end + +def fun_l7_n123() + fun_l8_n721 +end + +def fun_l7_n124() + fun_l8_n792 +end + +def fun_l7_n125() + fun_l8_n852 +end + +def fun_l7_n126() + fun_l8_n876 +end + +def fun_l7_n127() + fun_l8_n489 +end + +def fun_l7_n128() + fun_l8_n715 +end + +def fun_l7_n129() + fun_l8_n863 +end + +def fun_l7_n130() + fun_l8_n842 +end + +def fun_l7_n131() + fun_l8_n99 +end + +def fun_l7_n132() + fun_l8_n472 +end + +def fun_l7_n133() + fun_l8_n826 +end + +def fun_l7_n134() + fun_l8_n805 +end + +def fun_l7_n135() + fun_l8_n914 +end + +def fun_l7_n136() + fun_l8_n691 +end + +def fun_l7_n137() + fun_l8_n880 +end + +def fun_l7_n138() + fun_l8_n708 +end + +def fun_l7_n139() + fun_l8_n445 +end + +def fun_l7_n140() + fun_l8_n173 +end + +def fun_l7_n141() + fun_l8_n785 +end + +def fun_l7_n142() + fun_l8_n638 +end + +def fun_l7_n143() + fun_l8_n319 +end + +def fun_l7_n144() + fun_l8_n825 +end + +def fun_l7_n145() + fun_l8_n497 +end + +def fun_l7_n146() + fun_l8_n941 +end + +def fun_l7_n147() + fun_l8_n164 +end + +def fun_l7_n148() + fun_l8_n773 +end + +def fun_l7_n149() + fun_l8_n603 +end + +def fun_l7_n150() + fun_l8_n701 +end + +def fun_l7_n151() + fun_l8_n279 +end + +def fun_l7_n152() + fun_l8_n120 +end + +def fun_l7_n153() + fun_l8_n352 +end + +def fun_l7_n154() + fun_l8_n401 +end + +def fun_l7_n155() + fun_l8_n195 +end + +def fun_l7_n156() + fun_l8_n206 +end + +def fun_l7_n157() + fun_l8_n209 +end + +def fun_l7_n158() + fun_l8_n594 +end + +def fun_l7_n159() + fun_l8_n49 +end + +def fun_l7_n160() + fun_l8_n835 +end + +def fun_l7_n161() + fun_l8_n108 +end + +def fun_l7_n162() + fun_l8_n499 +end + +def fun_l7_n163() + fun_l8_n822 +end + +def fun_l7_n164() + fun_l8_n712 +end + +def fun_l7_n165() + fun_l8_n757 +end + +def fun_l7_n166() + fun_l8_n706 +end + +def fun_l7_n167() + fun_l8_n517 +end + +def fun_l7_n168() + fun_l8_n74 +end + +def fun_l7_n169() + fun_l8_n292 +end + +def fun_l7_n170() + fun_l8_n560 +end + +def fun_l7_n171() + fun_l8_n476 +end + +def fun_l7_n172() + fun_l8_n818 +end + +def fun_l7_n173() + fun_l8_n91 +end + +def fun_l7_n174() + fun_l8_n835 +end + +def fun_l7_n175() + fun_l8_n84 +end + +def fun_l7_n176() + fun_l8_n506 +end + +def fun_l7_n177() + fun_l8_n602 +end + +def fun_l7_n178() + fun_l8_n758 +end + +def fun_l7_n179() + fun_l8_n591 +end + +def fun_l7_n180() + fun_l8_n757 +end + +def fun_l7_n181() + fun_l8_n127 +end + +def fun_l7_n182() + fun_l8_n287 +end + +def fun_l7_n183() + fun_l8_n672 +end + +def fun_l7_n184() + fun_l8_n870 +end + +def fun_l7_n185() + fun_l8_n267 +end + +def fun_l7_n186() + fun_l8_n396 +end + +def fun_l7_n187() + fun_l8_n128 +end + +def fun_l7_n188() + fun_l8_n670 +end + +def fun_l7_n189() + fun_l8_n142 +end + +def fun_l7_n190() + fun_l8_n320 +end + +def fun_l7_n191() + fun_l8_n829 +end + +def fun_l7_n192() + fun_l8_n788 +end + +def fun_l7_n193() + fun_l8_n174 +end + +def fun_l7_n194() + fun_l8_n526 +end + +def fun_l7_n195() + fun_l8_n185 +end + +def fun_l7_n196() + fun_l8_n746 +end + +def fun_l7_n197() + fun_l8_n889 +end + +def fun_l7_n198() + fun_l8_n154 +end + +def fun_l7_n199() + fun_l8_n19 +end + +def fun_l7_n200() + fun_l8_n913 +end + +def fun_l7_n201() + fun_l8_n560 +end + +def fun_l7_n202() + fun_l8_n768 +end + +def fun_l7_n203() + fun_l8_n412 +end + +def fun_l7_n204() + fun_l8_n394 +end + +def fun_l7_n205() + fun_l8_n641 +end + +def fun_l7_n206() + fun_l8_n83 +end + +def fun_l7_n207() + fun_l8_n39 +end + +def fun_l7_n208() + fun_l8_n502 +end + +def fun_l7_n209() + fun_l8_n904 +end + +def fun_l7_n210() + fun_l8_n639 +end + +def fun_l7_n211() + fun_l8_n873 +end + +def fun_l7_n212() + fun_l8_n940 +end + +def fun_l7_n213() + fun_l8_n594 +end + +def fun_l7_n214() + fun_l8_n397 +end + +def fun_l7_n215() + fun_l8_n318 +end + +def fun_l7_n216() + fun_l8_n116 +end + +def fun_l7_n217() + fun_l8_n888 +end + +def fun_l7_n218() + fun_l8_n148 +end + +def fun_l7_n219() + fun_l8_n329 +end + +def fun_l7_n220() + fun_l8_n973 +end + +def fun_l7_n221() + fun_l8_n913 +end + +def fun_l7_n222() + fun_l8_n170 +end + +def fun_l7_n223() + fun_l8_n103 +end + +def fun_l7_n224() + fun_l8_n835 +end + +def fun_l7_n225() + fun_l8_n104 +end + +def fun_l7_n226() + fun_l8_n111 +end + +def fun_l7_n227() + fun_l8_n12 +end + +def fun_l7_n228() + fun_l8_n299 +end + +def fun_l7_n229() + fun_l8_n639 +end + +def fun_l7_n230() + fun_l8_n789 +end + +def fun_l7_n231() + fun_l8_n968 +end + +def fun_l7_n232() + fun_l8_n905 +end + +def fun_l7_n233() + fun_l8_n325 +end + +def fun_l7_n234() + fun_l8_n841 +end + +def fun_l7_n235() + fun_l8_n605 +end + +def fun_l7_n236() + fun_l8_n495 +end + +def fun_l7_n237() + fun_l8_n154 +end + +def fun_l7_n238() + fun_l8_n331 +end + +def fun_l7_n239() + fun_l8_n30 +end + +def fun_l7_n240() + fun_l8_n170 +end + +def fun_l7_n241() + fun_l8_n376 +end + +def fun_l7_n242() + fun_l8_n49 +end + +def fun_l7_n243() + fun_l8_n463 +end + +def fun_l7_n244() + fun_l8_n269 +end + +def fun_l7_n245() + fun_l8_n573 +end + +def fun_l7_n246() + fun_l8_n782 +end + +def fun_l7_n247() + fun_l8_n85 +end + +def fun_l7_n248() + fun_l8_n667 +end + +def fun_l7_n249() + fun_l8_n686 +end + +def fun_l7_n250() + fun_l8_n575 +end + +def fun_l7_n251() + fun_l8_n349 +end + +def fun_l7_n252() + fun_l8_n252 +end + +def fun_l7_n253() + fun_l8_n490 +end + +def fun_l7_n254() + fun_l8_n600 +end + +def fun_l7_n255() + fun_l8_n772 +end + +def fun_l7_n256() + fun_l8_n645 +end + +def fun_l7_n257() + fun_l8_n633 +end + +def fun_l7_n258() + fun_l8_n323 +end + +def fun_l7_n259() + fun_l8_n590 +end + +def fun_l7_n260() + fun_l8_n77 +end + +def fun_l7_n261() + fun_l8_n349 +end + +def fun_l7_n262() + fun_l8_n98 +end + +def fun_l7_n263() + fun_l8_n312 +end + +def fun_l7_n264() + fun_l8_n449 +end + +def fun_l7_n265() + fun_l8_n550 +end + +def fun_l7_n266() + fun_l8_n717 +end + +def fun_l7_n267() + fun_l8_n249 +end + +def fun_l7_n268() + fun_l8_n940 +end + +def fun_l7_n269() + fun_l8_n243 +end + +def fun_l7_n270() + fun_l8_n392 +end + +def fun_l7_n271() + fun_l8_n129 +end + +def fun_l7_n272() + fun_l8_n704 +end + +def fun_l7_n273() + fun_l8_n815 +end + +def fun_l7_n274() + fun_l8_n123 +end + +def fun_l7_n275() + fun_l8_n281 +end + +def fun_l7_n276() + fun_l8_n110 +end + +def fun_l7_n277() + fun_l8_n250 +end + +def fun_l7_n278() + fun_l8_n245 +end + +def fun_l7_n279() + fun_l8_n612 +end + +def fun_l7_n280() + fun_l8_n693 +end + +def fun_l7_n281() + fun_l8_n441 +end + +def fun_l7_n282() + fun_l8_n716 +end + +def fun_l7_n283() + fun_l8_n467 +end + +def fun_l7_n284() + fun_l8_n944 +end + +def fun_l7_n285() + fun_l8_n14 +end + +def fun_l7_n286() + fun_l8_n453 +end + +def fun_l7_n287() + fun_l8_n342 +end + +def fun_l7_n288() + fun_l8_n666 +end + +def fun_l7_n289() + fun_l8_n111 +end + +def fun_l7_n290() + fun_l8_n353 +end + +def fun_l7_n291() + fun_l8_n279 +end + +def fun_l7_n292() + fun_l8_n556 +end + +def fun_l7_n293() + fun_l8_n780 +end + +def fun_l7_n294() + fun_l8_n137 +end + +def fun_l7_n295() + fun_l8_n760 +end + +def fun_l7_n296() + fun_l8_n56 +end + +def fun_l7_n297() + fun_l8_n927 +end + +def fun_l7_n298() + fun_l8_n861 +end + +def fun_l7_n299() + fun_l8_n653 +end + +def fun_l7_n300() + fun_l8_n948 +end + +def fun_l7_n301() + fun_l8_n159 +end + +def fun_l7_n302() + fun_l8_n426 +end + +def fun_l7_n303() + fun_l8_n175 +end + +def fun_l7_n304() + fun_l8_n35 +end + +def fun_l7_n305() + fun_l8_n700 +end + +def fun_l7_n306() + fun_l8_n603 +end + +def fun_l7_n307() + fun_l8_n600 +end + +def fun_l7_n308() + fun_l8_n280 +end + +def fun_l7_n309() + fun_l8_n599 +end + +def fun_l7_n310() + fun_l8_n404 +end + +def fun_l7_n311() + fun_l8_n475 +end + +def fun_l7_n312() + fun_l8_n837 +end + +def fun_l7_n313() + fun_l8_n61 +end + +def fun_l7_n314() + fun_l8_n571 +end + +def fun_l7_n315() + fun_l8_n442 +end + +def fun_l7_n316() + fun_l8_n256 +end + +def fun_l7_n317() + fun_l8_n751 +end + +def fun_l7_n318() + fun_l8_n672 +end + +def fun_l7_n319() + fun_l8_n953 +end + +def fun_l7_n320() + fun_l8_n330 +end + +def fun_l7_n321() + fun_l8_n54 +end + +def fun_l7_n322() + fun_l8_n11 +end + +def fun_l7_n323() + fun_l8_n504 +end + +def fun_l7_n324() + fun_l8_n786 +end + +def fun_l7_n325() + fun_l8_n32 +end + +def fun_l7_n326() + fun_l8_n85 +end + +def fun_l7_n327() + fun_l8_n727 +end + +def fun_l7_n328() + fun_l8_n445 +end + +def fun_l7_n329() + fun_l8_n787 +end + +def fun_l7_n330() + fun_l8_n663 +end + +def fun_l7_n331() + fun_l8_n461 +end + +def fun_l7_n332() + fun_l8_n82 +end + +def fun_l7_n333() + fun_l8_n974 +end + +def fun_l7_n334() + fun_l8_n511 +end + +def fun_l7_n335() + fun_l8_n827 +end + +def fun_l7_n336() + fun_l8_n12 +end + +def fun_l7_n337() + fun_l8_n696 +end + +def fun_l7_n338() + fun_l8_n325 +end + +def fun_l7_n339() + fun_l8_n148 +end + +def fun_l7_n340() + fun_l8_n609 +end + +def fun_l7_n341() + fun_l8_n471 +end + +def fun_l7_n342() + fun_l8_n63 +end + +def fun_l7_n343() + fun_l8_n358 +end + +def fun_l7_n344() + fun_l8_n658 +end + +def fun_l7_n345() + fun_l8_n730 +end + +def fun_l7_n346() + fun_l8_n139 +end + +def fun_l7_n347() + fun_l8_n951 +end + +def fun_l7_n348() + fun_l8_n113 +end + +def fun_l7_n349() + fun_l8_n695 +end + +def fun_l7_n350() + fun_l8_n803 +end + +def fun_l7_n351() + fun_l8_n93 +end + +def fun_l7_n352() + fun_l8_n340 +end + +def fun_l7_n353() + fun_l8_n551 +end + +def fun_l7_n354() + fun_l8_n5 +end + +def fun_l7_n355() + fun_l8_n960 +end + +def fun_l7_n356() + fun_l8_n76 +end + +def fun_l7_n357() + fun_l8_n142 +end + +def fun_l7_n358() + fun_l8_n305 +end + +def fun_l7_n359() + fun_l8_n739 +end + +def fun_l7_n360() + fun_l8_n293 +end + +def fun_l7_n361() + fun_l8_n812 +end + +def fun_l7_n362() + fun_l8_n635 +end + +def fun_l7_n363() + fun_l8_n239 +end + +def fun_l7_n364() + fun_l8_n880 +end + +def fun_l7_n365() + fun_l8_n999 +end + +def fun_l7_n366() + fun_l8_n997 +end + +def fun_l7_n367() + fun_l8_n190 +end + +def fun_l7_n368() + fun_l8_n763 +end + +def fun_l7_n369() + fun_l8_n369 +end + +def fun_l7_n370() + fun_l8_n538 +end + +def fun_l7_n371() + fun_l8_n553 +end + +def fun_l7_n372() + fun_l8_n844 +end + +def fun_l7_n373() + fun_l8_n773 +end + +def fun_l7_n374() + fun_l8_n589 +end + +def fun_l7_n375() + fun_l8_n492 +end + +def fun_l7_n376() + fun_l8_n848 +end + +def fun_l7_n377() + fun_l8_n715 +end + +def fun_l7_n378() + fun_l8_n82 +end + +def fun_l7_n379() + fun_l8_n267 +end + +def fun_l7_n380() + fun_l8_n84 +end + +def fun_l7_n381() + fun_l8_n996 +end + +def fun_l7_n382() + fun_l8_n536 +end + +def fun_l7_n383() + fun_l8_n518 +end + +def fun_l7_n384() + fun_l8_n70 +end + +def fun_l7_n385() + fun_l8_n545 +end + +def fun_l7_n386() + fun_l8_n156 +end + +def fun_l7_n387() + fun_l8_n558 +end + +def fun_l7_n388() + fun_l8_n519 +end + +def fun_l7_n389() + fun_l8_n321 +end + +def fun_l7_n390() + fun_l8_n133 +end + +def fun_l7_n391() + fun_l8_n253 +end + +def fun_l7_n392() + fun_l8_n969 +end + +def fun_l7_n393() + fun_l8_n986 +end + +def fun_l7_n394() + fun_l8_n991 +end + +def fun_l7_n395() + fun_l8_n757 +end + +def fun_l7_n396() + fun_l8_n496 +end + +def fun_l7_n397() + fun_l8_n841 +end + +def fun_l7_n398() + fun_l8_n922 +end + +def fun_l7_n399() + fun_l8_n51 +end + +def fun_l7_n400() + fun_l8_n961 +end + +def fun_l7_n401() + fun_l8_n82 +end + +def fun_l7_n402() + fun_l8_n190 +end + +def fun_l7_n403() + fun_l8_n543 +end + +def fun_l7_n404() + fun_l8_n768 +end + +def fun_l7_n405() + fun_l8_n810 +end + +def fun_l7_n406() + fun_l8_n714 +end + +def fun_l7_n407() + fun_l8_n692 +end + +def fun_l7_n408() + fun_l8_n357 +end + +def fun_l7_n409() + fun_l8_n380 +end + +def fun_l7_n410() + fun_l8_n958 +end + +def fun_l7_n411() + fun_l8_n992 +end + +def fun_l7_n412() + fun_l8_n819 +end + +def fun_l7_n413() + fun_l8_n4 +end + +def fun_l7_n414() + fun_l8_n429 +end + +def fun_l7_n415() + fun_l8_n56 +end + +def fun_l7_n416() + fun_l8_n212 +end + +def fun_l7_n417() + fun_l8_n267 +end + +def fun_l7_n418() + fun_l8_n948 +end + +def fun_l7_n419() + fun_l8_n221 +end + +def fun_l7_n420() + fun_l8_n711 +end + +def fun_l7_n421() + fun_l8_n307 +end + +def fun_l7_n422() + fun_l8_n482 +end + +def fun_l7_n423() + fun_l8_n522 +end + +def fun_l7_n424() + fun_l8_n166 +end + +def fun_l7_n425() + fun_l8_n410 +end + +def fun_l7_n426() + fun_l8_n143 +end + +def fun_l7_n427() + fun_l8_n54 +end + +def fun_l7_n428() + fun_l8_n217 +end + +def fun_l7_n429() + fun_l8_n423 +end + +def fun_l7_n430() + fun_l8_n181 +end + +def fun_l7_n431() + fun_l8_n456 +end + +def fun_l7_n432() + fun_l8_n640 +end + +def fun_l7_n433() + fun_l8_n588 +end + +def fun_l7_n434() + fun_l8_n49 +end + +def fun_l7_n435() + fun_l8_n373 +end + +def fun_l7_n436() + fun_l8_n668 +end + +def fun_l7_n437() + fun_l8_n478 +end + +def fun_l7_n438() + fun_l8_n468 +end + +def fun_l7_n439() + fun_l8_n230 +end + +def fun_l7_n440() + fun_l8_n361 +end + +def fun_l7_n441() + fun_l8_n770 +end + +def fun_l7_n442() + fun_l8_n876 +end + +def fun_l7_n443() + fun_l8_n383 +end + +def fun_l7_n444() + fun_l8_n568 +end + +def fun_l7_n445() + fun_l8_n236 +end + +def fun_l7_n446() + fun_l8_n136 +end + +def fun_l7_n447() + fun_l8_n883 +end + +def fun_l7_n448() + fun_l8_n227 +end + +def fun_l7_n449() + fun_l8_n634 +end + +def fun_l7_n450() + fun_l8_n985 +end + +def fun_l7_n451() + fun_l8_n314 +end + +def fun_l7_n452() + fun_l8_n90 +end + +def fun_l7_n453() + fun_l8_n31 +end + +def fun_l7_n454() + fun_l8_n226 +end + +def fun_l7_n455() + fun_l8_n309 +end + +def fun_l7_n456() + fun_l8_n912 +end + +def fun_l7_n457() + fun_l8_n7 +end + +def fun_l7_n458() + fun_l8_n304 +end + +def fun_l7_n459() + fun_l8_n488 +end + +def fun_l7_n460() + fun_l8_n576 +end + +def fun_l7_n461() + fun_l8_n854 +end + +def fun_l7_n462() + fun_l8_n164 +end + +def fun_l7_n463() + fun_l8_n381 +end + +def fun_l7_n464() + fun_l8_n241 +end + +def fun_l7_n465() + fun_l8_n330 +end + +def fun_l7_n466() + fun_l8_n517 +end + +def fun_l7_n467() + fun_l8_n647 +end + +def fun_l7_n468() + fun_l8_n320 +end + +def fun_l7_n469() + fun_l8_n479 +end + +def fun_l7_n470() + fun_l8_n913 +end + +def fun_l7_n471() + fun_l8_n13 +end + +def fun_l7_n472() + fun_l8_n601 +end + +def fun_l7_n473() + fun_l8_n364 +end + +def fun_l7_n474() + fun_l8_n360 +end + +def fun_l7_n475() + fun_l8_n374 +end + +def fun_l7_n476() + fun_l8_n651 +end + +def fun_l7_n477() + fun_l8_n579 +end + +def fun_l7_n478() + fun_l8_n583 +end + +def fun_l7_n479() + fun_l8_n693 +end + +def fun_l7_n480() + fun_l8_n941 +end + +def fun_l7_n481() + fun_l8_n743 +end + +def fun_l7_n482() + fun_l8_n511 +end + +def fun_l7_n483() + fun_l8_n528 +end + +def fun_l7_n484() + fun_l8_n898 +end + +def fun_l7_n485() + fun_l8_n175 +end + +def fun_l7_n486() + fun_l8_n45 +end + +def fun_l7_n487() + fun_l8_n871 +end + +def fun_l7_n488() + fun_l8_n464 +end + +def fun_l7_n489() + fun_l8_n69 +end + +def fun_l7_n490() + fun_l8_n334 +end + +def fun_l7_n491() + fun_l8_n687 +end + +def fun_l7_n492() + fun_l8_n729 +end + +def fun_l7_n493() + fun_l8_n47 +end + +def fun_l7_n494() + fun_l8_n905 +end + +def fun_l7_n495() + fun_l8_n586 +end + +def fun_l7_n496() + fun_l8_n657 +end + +def fun_l7_n497() + fun_l8_n673 +end + +def fun_l7_n498() + fun_l8_n173 +end + +def fun_l7_n499() + fun_l8_n333 +end + +def fun_l7_n500() + fun_l8_n712 +end + +def fun_l7_n501() + fun_l8_n349 +end + +def fun_l7_n502() + fun_l8_n969 +end + +def fun_l7_n503() + fun_l8_n678 +end + +def fun_l7_n504() + fun_l8_n507 +end + +def fun_l7_n505() + fun_l8_n206 +end + +def fun_l7_n506() + fun_l8_n370 +end + +def fun_l7_n507() + fun_l8_n270 +end + +def fun_l7_n508() + fun_l8_n20 +end + +def fun_l7_n509() + fun_l8_n545 +end + +def fun_l7_n510() + fun_l8_n926 +end + +def fun_l7_n511() + fun_l8_n882 +end + +def fun_l7_n512() + fun_l8_n630 +end + +def fun_l7_n513() + fun_l8_n51 +end + +def fun_l7_n514() + fun_l8_n69 +end + +def fun_l7_n515() + fun_l8_n859 +end + +def fun_l7_n516() + fun_l8_n808 +end + +def fun_l7_n517() + fun_l8_n800 +end + +def fun_l7_n518() + fun_l8_n226 +end + +def fun_l7_n519() + fun_l8_n340 +end + +def fun_l7_n520() + fun_l8_n391 +end + +def fun_l7_n521() + fun_l8_n538 +end + +def fun_l7_n522() + fun_l8_n458 +end + +def fun_l7_n523() + fun_l8_n114 +end + +def fun_l7_n524() + fun_l8_n593 +end + +def fun_l7_n525() + fun_l8_n276 +end + +def fun_l7_n526() + fun_l8_n276 +end + +def fun_l7_n527() + fun_l8_n719 +end + +def fun_l7_n528() + fun_l8_n75 +end + +def fun_l7_n529() + fun_l8_n855 +end + +def fun_l7_n530() + fun_l8_n731 +end + +def fun_l7_n531() + fun_l8_n257 +end + +def fun_l7_n532() + fun_l8_n572 +end + +def fun_l7_n533() + fun_l8_n483 +end + +def fun_l7_n534() + fun_l8_n548 +end + +def fun_l7_n535() + fun_l8_n867 +end + +def fun_l7_n536() + fun_l8_n923 +end + +def fun_l7_n537() + fun_l8_n988 +end + +def fun_l7_n538() + fun_l8_n813 +end + +def fun_l7_n539() + fun_l8_n503 +end + +def fun_l7_n540() + fun_l8_n326 +end + +def fun_l7_n541() + fun_l8_n521 +end + +def fun_l7_n542() + fun_l8_n804 +end + +def fun_l7_n543() + fun_l8_n693 +end + +def fun_l7_n544() + fun_l8_n887 +end + +def fun_l7_n545() + fun_l8_n543 +end + +def fun_l7_n546() + fun_l8_n438 +end + +def fun_l7_n547() + fun_l8_n295 +end + +def fun_l7_n548() + fun_l8_n361 +end + +def fun_l7_n549() + fun_l8_n495 +end + +def fun_l7_n550() + fun_l8_n34 +end + +def fun_l7_n551() + fun_l8_n491 +end + +def fun_l7_n552() + fun_l8_n659 +end + +def fun_l7_n553() + fun_l8_n589 +end + +def fun_l7_n554() + fun_l8_n450 +end + +def fun_l7_n555() + fun_l8_n365 +end + +def fun_l7_n556() + fun_l8_n171 +end + +def fun_l7_n557() + fun_l8_n145 +end + +def fun_l7_n558() + fun_l8_n760 +end + +def fun_l7_n559() + fun_l8_n767 +end + +def fun_l7_n560() + fun_l8_n51 +end + +def fun_l7_n561() + fun_l8_n596 +end + +def fun_l7_n562() + fun_l8_n744 +end + +def fun_l7_n563() + fun_l8_n80 +end + +def fun_l7_n564() + fun_l8_n787 +end + +def fun_l7_n565() + fun_l8_n783 +end + +def fun_l7_n566() + fun_l8_n310 +end + +def fun_l7_n567() + fun_l8_n703 +end + +def fun_l7_n568() + fun_l8_n665 +end + +def fun_l7_n569() + fun_l8_n866 +end + +def fun_l7_n570() + fun_l8_n80 +end + +def fun_l7_n571() + fun_l8_n694 +end + +def fun_l7_n572() + fun_l8_n970 +end + +def fun_l7_n573() + fun_l8_n102 +end + +def fun_l7_n574() + fun_l8_n362 +end + +def fun_l7_n575() + fun_l8_n119 +end + +def fun_l7_n576() + fun_l8_n772 +end + +def fun_l7_n577() + fun_l8_n715 +end + +def fun_l7_n578() + fun_l8_n487 +end + +def fun_l7_n579() + fun_l8_n48 +end + +def fun_l7_n580() + fun_l8_n824 +end + +def fun_l7_n581() + fun_l8_n208 +end + +def fun_l7_n582() + fun_l8_n494 +end + +def fun_l7_n583() + fun_l8_n138 +end + +def fun_l7_n584() + fun_l8_n961 +end + +def fun_l7_n585() + fun_l8_n553 +end + +def fun_l7_n586() + fun_l8_n302 +end + +def fun_l7_n587() + fun_l8_n266 +end + +def fun_l7_n588() + fun_l8_n589 +end + +def fun_l7_n589() + fun_l8_n964 +end + +def fun_l7_n590() + fun_l8_n238 +end + +def fun_l7_n591() + fun_l8_n139 +end + +def fun_l7_n592() + fun_l8_n680 +end + +def fun_l7_n593() + fun_l8_n252 +end + +def fun_l7_n594() + fun_l8_n701 +end + +def fun_l7_n595() + fun_l8_n100 +end + +def fun_l7_n596() + fun_l8_n358 +end + +def fun_l7_n597() + fun_l8_n770 +end + +def fun_l7_n598() + fun_l8_n880 +end + +def fun_l7_n599() + fun_l8_n761 +end + +def fun_l7_n600() + fun_l8_n876 +end + +def fun_l7_n601() + fun_l8_n373 +end + +def fun_l7_n602() + fun_l8_n775 +end + +def fun_l7_n603() + fun_l8_n317 +end + +def fun_l7_n604() + fun_l8_n456 +end + +def fun_l7_n605() + fun_l8_n343 +end + +def fun_l7_n606() + fun_l8_n68 +end + +def fun_l7_n607() + fun_l8_n25 +end + +def fun_l7_n608() + fun_l8_n399 +end + +def fun_l7_n609() + fun_l8_n14 +end + +def fun_l7_n610() + fun_l8_n549 +end + +def fun_l7_n611() + fun_l8_n45 +end + +def fun_l7_n612() + fun_l8_n516 +end + +def fun_l7_n613() + fun_l8_n345 +end + +def fun_l7_n614() + fun_l8_n909 +end + +def fun_l7_n615() + fun_l8_n954 +end + +def fun_l7_n616() + fun_l8_n893 +end + +def fun_l7_n617() + fun_l8_n57 +end + +def fun_l7_n618() + fun_l8_n83 +end + +def fun_l7_n619() + fun_l8_n658 +end + +def fun_l7_n620() + fun_l8_n585 +end + +def fun_l7_n621() + fun_l8_n260 +end + +def fun_l7_n622() + fun_l8_n226 +end + +def fun_l7_n623() + fun_l8_n186 +end + +def fun_l7_n624() + fun_l8_n994 +end + +def fun_l7_n625() + fun_l8_n408 +end + +def fun_l7_n626() + fun_l8_n878 +end + +def fun_l7_n627() + fun_l8_n473 +end + +def fun_l7_n628() + fun_l8_n153 +end + +def fun_l7_n629() + fun_l8_n590 +end + +def fun_l7_n630() + fun_l8_n610 +end + +def fun_l7_n631() + fun_l8_n438 +end + +def fun_l7_n632() + fun_l8_n484 +end + +def fun_l7_n633() + fun_l8_n908 +end + +def fun_l7_n634() + fun_l8_n992 +end + +def fun_l7_n635() + fun_l8_n556 +end + +def fun_l7_n636() + fun_l8_n929 +end + +def fun_l7_n637() + fun_l8_n128 +end + +def fun_l7_n638() + fun_l8_n372 +end + +def fun_l7_n639() + fun_l8_n36 +end + +def fun_l7_n640() + fun_l8_n545 +end + +def fun_l7_n641() + fun_l8_n801 +end + +def fun_l7_n642() + fun_l8_n444 +end + +def fun_l7_n643() + fun_l8_n822 +end + +def fun_l7_n644() + fun_l8_n587 +end + +def fun_l7_n645() + fun_l8_n418 +end + +def fun_l7_n646() + fun_l8_n539 +end + +def fun_l7_n647() + fun_l8_n266 +end + +def fun_l7_n648() + fun_l8_n869 +end + +def fun_l7_n649() + fun_l8_n84 +end + +def fun_l7_n650() + fun_l8_n265 +end + +def fun_l7_n651() + fun_l8_n551 +end + +def fun_l7_n652() + fun_l8_n35 +end + +def fun_l7_n653() + fun_l8_n606 +end + +def fun_l7_n654() + fun_l8_n379 +end + +def fun_l7_n655() + fun_l8_n417 +end + +def fun_l7_n656() + fun_l8_n641 +end + +def fun_l7_n657() + fun_l8_n889 +end + +def fun_l7_n658() + fun_l8_n232 +end + +def fun_l7_n659() + fun_l8_n957 +end + +def fun_l7_n660() + fun_l8_n666 +end + +def fun_l7_n661() + fun_l8_n588 +end + +def fun_l7_n662() + fun_l8_n591 +end + +def fun_l7_n663() + fun_l8_n489 +end + +def fun_l7_n664() + fun_l8_n927 +end + +def fun_l7_n665() + fun_l8_n304 +end + +def fun_l7_n666() + fun_l8_n856 +end + +def fun_l7_n667() + fun_l8_n969 +end + +def fun_l7_n668() + fun_l8_n36 +end + +def fun_l7_n669() + fun_l8_n335 +end + +def fun_l7_n670() + fun_l8_n51 +end + +def fun_l7_n671() + fun_l8_n765 +end + +def fun_l7_n672() + fun_l8_n262 +end + +def fun_l7_n673() + fun_l8_n858 +end + +def fun_l7_n674() + fun_l8_n412 +end + +def fun_l7_n675() + fun_l8_n789 +end + +def fun_l7_n676() + fun_l8_n290 +end + +def fun_l7_n677() + fun_l8_n935 +end + +def fun_l7_n678() + fun_l8_n212 +end + +def fun_l7_n679() + fun_l8_n35 +end + +def fun_l7_n680() + fun_l8_n141 +end + +def fun_l7_n681() + fun_l8_n985 +end + +def fun_l7_n682() + fun_l8_n626 +end + +def fun_l7_n683() + fun_l8_n996 +end + +def fun_l7_n684() + fun_l8_n906 +end + +def fun_l7_n685() + fun_l8_n242 +end + +def fun_l7_n686() + fun_l8_n431 +end + +def fun_l7_n687() + fun_l8_n494 +end + +def fun_l7_n688() + fun_l8_n564 +end + +def fun_l7_n689() + fun_l8_n737 +end + +def fun_l7_n690() + fun_l8_n366 +end + +def fun_l7_n691() + fun_l8_n763 +end + +def fun_l7_n692() + fun_l8_n556 +end + +def fun_l7_n693() + fun_l8_n436 +end + +def fun_l7_n694() + fun_l8_n17 +end + +def fun_l7_n695() + fun_l8_n283 +end + +def fun_l7_n696() + fun_l8_n641 +end + +def fun_l7_n697() + fun_l8_n298 +end + +def fun_l7_n698() + fun_l8_n819 +end + +def fun_l7_n699() + fun_l8_n858 +end + +def fun_l7_n700() + fun_l8_n161 +end + +def fun_l7_n701() + fun_l8_n813 +end + +def fun_l7_n702() + fun_l8_n604 +end + +def fun_l7_n703() + fun_l8_n878 +end + +def fun_l7_n704() + fun_l8_n880 +end + +def fun_l7_n705() + fun_l8_n431 +end + +def fun_l7_n706() + fun_l8_n944 +end + +def fun_l7_n707() + fun_l8_n672 +end + +def fun_l7_n708() + fun_l8_n983 +end + +def fun_l7_n709() + fun_l8_n224 +end + +def fun_l7_n710() + fun_l8_n915 +end + +def fun_l7_n711() + fun_l8_n699 +end + +def fun_l7_n712() + fun_l8_n112 +end + +def fun_l7_n713() + fun_l8_n64 +end + +def fun_l7_n714() + fun_l8_n3 +end + +def fun_l7_n715() + fun_l8_n508 +end + +def fun_l7_n716() + fun_l8_n172 +end + +def fun_l7_n717() + fun_l8_n777 +end + +def fun_l7_n718() + fun_l8_n328 +end + +def fun_l7_n719() + fun_l8_n338 +end + +def fun_l7_n720() + fun_l8_n897 +end + +def fun_l7_n721() + fun_l8_n373 +end + +def fun_l7_n722() + fun_l8_n91 +end + +def fun_l7_n723() + fun_l8_n149 +end + +def fun_l7_n724() + fun_l8_n65 +end + +def fun_l7_n725() + fun_l8_n685 +end + +def fun_l7_n726() + fun_l8_n939 +end + +def fun_l7_n727() + fun_l8_n427 +end + +def fun_l7_n728() + fun_l8_n606 +end + +def fun_l7_n729() + fun_l8_n818 +end + +def fun_l7_n730() + fun_l8_n24 +end + +def fun_l7_n731() + fun_l8_n901 +end + +def fun_l7_n732() + fun_l8_n979 +end + +def fun_l7_n733() + fun_l8_n88 +end + +def fun_l7_n734() + fun_l8_n516 +end + +def fun_l7_n735() + fun_l8_n44 +end + +def fun_l7_n736() + fun_l8_n540 +end + +def fun_l7_n737() + fun_l8_n586 +end + +def fun_l7_n738() + fun_l8_n695 +end + +def fun_l7_n739() + fun_l8_n774 +end + +def fun_l7_n740() + fun_l8_n797 +end + +def fun_l7_n741() + fun_l8_n524 +end + +def fun_l7_n742() + fun_l8_n784 +end + +def fun_l7_n743() + fun_l8_n203 +end + +def fun_l7_n744() + fun_l8_n808 +end + +def fun_l7_n745() + fun_l8_n216 +end + +def fun_l7_n746() + fun_l8_n14 +end + +def fun_l7_n747() + fun_l8_n799 +end + +def fun_l7_n748() + fun_l8_n660 +end + +def fun_l7_n749() + fun_l8_n417 +end + +def fun_l7_n750() + fun_l8_n573 +end + +def fun_l7_n751() + fun_l8_n919 +end + +def fun_l7_n752() + fun_l8_n956 +end + +def fun_l7_n753() + fun_l8_n475 +end + +def fun_l7_n754() + fun_l8_n941 +end + +def fun_l7_n755() + fun_l8_n629 +end + +def fun_l7_n756() + fun_l8_n745 +end + +def fun_l7_n757() + fun_l8_n656 +end + +def fun_l7_n758() + fun_l8_n315 +end + +def fun_l7_n759() + fun_l8_n952 +end + +def fun_l7_n760() + fun_l8_n241 +end + +def fun_l7_n761() + fun_l8_n341 +end + +def fun_l7_n762() + fun_l8_n156 +end + +def fun_l7_n763() + fun_l8_n258 +end + +def fun_l7_n764() + fun_l8_n275 +end + +def fun_l7_n765() + fun_l8_n950 +end + +def fun_l7_n766() + fun_l8_n715 +end + +def fun_l7_n767() + fun_l8_n746 +end + +def fun_l7_n768() + fun_l8_n428 +end + +def fun_l7_n769() + fun_l8_n176 +end + +def fun_l7_n770() + fun_l8_n586 +end + +def fun_l7_n771() + fun_l8_n912 +end + +def fun_l7_n772() + fun_l8_n484 +end + +def fun_l7_n773() + fun_l8_n155 +end + +def fun_l7_n774() + fun_l8_n648 +end + +def fun_l7_n775() + fun_l8_n27 +end + +def fun_l7_n776() + fun_l8_n188 +end + +def fun_l7_n777() + fun_l8_n804 +end + +def fun_l7_n778() + fun_l8_n646 +end + +def fun_l7_n779() + fun_l8_n884 +end + +def fun_l7_n780() + fun_l8_n332 +end + +def fun_l7_n781() + fun_l8_n28 +end + +def fun_l7_n782() + fun_l8_n966 +end + +def fun_l7_n783() + fun_l8_n531 +end + +def fun_l7_n784() + fun_l8_n955 +end + +def fun_l7_n785() + fun_l8_n264 +end + +def fun_l7_n786() + fun_l8_n387 +end + +def fun_l7_n787() + fun_l8_n274 +end + +def fun_l7_n788() + fun_l8_n790 +end + +def fun_l7_n789() + fun_l8_n80 +end + +def fun_l7_n790() + fun_l8_n551 +end + +def fun_l7_n791() + fun_l8_n762 +end + +def fun_l7_n792() + fun_l8_n777 +end + +def fun_l7_n793() + fun_l8_n120 +end + +def fun_l7_n794() + fun_l8_n189 +end + +def fun_l7_n795() + fun_l8_n241 +end + +def fun_l7_n796() + fun_l8_n608 +end + +def fun_l7_n797() + fun_l8_n689 +end + +def fun_l7_n798() + fun_l8_n406 +end + +def fun_l7_n799() + fun_l8_n853 +end + +def fun_l7_n800() + fun_l8_n606 +end + +def fun_l7_n801() + fun_l8_n723 +end + +def fun_l7_n802() + fun_l8_n498 +end + +def fun_l7_n803() + fun_l8_n109 +end + +def fun_l7_n804() + fun_l8_n400 +end + +def fun_l7_n805() + fun_l8_n266 +end + +def fun_l7_n806() + fun_l8_n661 +end + +def fun_l7_n807() + fun_l8_n107 +end + +def fun_l7_n808() + fun_l8_n541 +end + +def fun_l7_n809() + fun_l8_n44 +end + +def fun_l7_n810() + fun_l8_n184 +end + +def fun_l7_n811() + fun_l8_n516 +end + +def fun_l7_n812() + fun_l8_n706 +end + +def fun_l7_n813() + fun_l8_n714 +end + +def fun_l7_n814() + fun_l8_n399 +end + +def fun_l7_n815() + fun_l8_n877 +end + +def fun_l7_n816() + fun_l8_n301 +end + +def fun_l7_n817() + fun_l8_n75 +end + +def fun_l7_n818() + fun_l8_n169 +end + +def fun_l7_n819() + fun_l8_n99 +end + +def fun_l7_n820() + fun_l8_n155 +end + +def fun_l7_n821() + fun_l8_n281 +end + +def fun_l7_n822() + fun_l8_n210 +end + +def fun_l7_n823() + fun_l8_n835 +end + +def fun_l7_n824() + fun_l8_n700 +end + +def fun_l7_n825() + fun_l8_n231 +end + +def fun_l7_n826() + fun_l8_n967 +end + +def fun_l7_n827() + fun_l8_n818 +end + +def fun_l7_n828() + fun_l8_n670 +end + +def fun_l7_n829() + fun_l8_n311 +end + +def fun_l7_n830() + fun_l8_n919 +end + +def fun_l7_n831() + fun_l8_n949 +end + +def fun_l7_n832() + fun_l8_n677 +end + +def fun_l7_n833() + fun_l8_n626 +end + +def fun_l7_n834() + fun_l8_n171 +end + +def fun_l7_n835() + fun_l8_n723 +end + +def fun_l7_n836() + fun_l8_n606 +end + +def fun_l7_n837() + fun_l8_n580 +end + +def fun_l7_n838() + fun_l8_n369 +end + +def fun_l7_n839() + fun_l8_n510 +end + +def fun_l7_n840() + fun_l8_n554 +end + +def fun_l7_n841() + fun_l8_n749 +end + +def fun_l7_n842() + fun_l8_n623 +end + +def fun_l7_n843() + fun_l8_n735 +end + +def fun_l7_n844() + fun_l8_n401 +end + +def fun_l7_n845() + fun_l8_n693 +end + +def fun_l7_n846() + fun_l8_n367 +end + +def fun_l7_n847() + fun_l8_n351 +end + +def fun_l7_n848() + fun_l8_n527 +end + +def fun_l7_n849() + fun_l8_n964 +end + +def fun_l7_n850() + fun_l8_n193 +end + +def fun_l7_n851() + fun_l8_n401 +end + +def fun_l7_n852() + fun_l8_n873 +end + +def fun_l7_n853() + fun_l8_n326 +end + +def fun_l7_n854() + fun_l8_n292 +end + +def fun_l7_n855() + fun_l8_n519 +end + +def fun_l7_n856() + fun_l8_n801 +end + +def fun_l7_n857() + fun_l8_n45 +end + +def fun_l7_n858() + fun_l8_n212 +end + +def fun_l7_n859() + fun_l8_n812 +end + +def fun_l7_n860() + fun_l8_n541 +end + +def fun_l7_n861() + fun_l8_n410 +end + +def fun_l7_n862() + fun_l8_n177 +end + +def fun_l7_n863() + fun_l8_n940 +end + +def fun_l7_n864() + fun_l8_n832 +end + +def fun_l7_n865() + fun_l8_n7 +end + +def fun_l7_n866() + fun_l8_n654 +end + +def fun_l7_n867() + fun_l8_n282 +end + +def fun_l7_n868() + fun_l8_n916 +end + +def fun_l7_n869() + fun_l8_n638 +end + +def fun_l7_n870() + fun_l8_n71 +end + +def fun_l7_n871() + fun_l8_n153 +end + +def fun_l7_n872() + fun_l8_n285 +end + +def fun_l7_n873() + fun_l8_n744 +end + +def fun_l7_n874() + fun_l8_n912 +end + +def fun_l7_n875() + fun_l8_n258 +end + +def fun_l7_n876() + fun_l8_n346 +end + +def fun_l7_n877() + fun_l8_n366 +end + +def fun_l7_n878() + fun_l8_n165 +end + +def fun_l7_n879() + fun_l8_n745 +end + +def fun_l7_n880() + fun_l8_n472 +end + +def fun_l7_n881() + fun_l8_n290 +end + +def fun_l7_n882() + fun_l8_n695 +end + +def fun_l7_n883() + fun_l8_n522 +end + +def fun_l7_n884() + fun_l8_n851 +end + +def fun_l7_n885() + fun_l8_n870 +end + +def fun_l7_n886() + fun_l8_n70 +end + +def fun_l7_n887() + fun_l8_n334 +end + +def fun_l7_n888() + fun_l8_n786 +end + +def fun_l7_n889() + fun_l8_n41 +end + +def fun_l7_n890() + fun_l8_n316 +end + +def fun_l7_n891() + fun_l8_n594 +end + +def fun_l7_n892() + fun_l8_n168 +end + +def fun_l7_n893() + fun_l8_n960 +end + +def fun_l7_n894() + fun_l8_n357 +end + +def fun_l7_n895() + fun_l8_n695 +end + +def fun_l7_n896() + fun_l8_n616 +end + +def fun_l7_n897() + fun_l8_n63 +end + +def fun_l7_n898() + fun_l8_n59 +end + +def fun_l7_n899() + fun_l8_n958 +end + +def fun_l7_n900() + fun_l8_n623 +end + +def fun_l7_n901() + fun_l8_n427 +end + +def fun_l7_n902() + fun_l8_n203 +end + +def fun_l7_n903() + fun_l8_n752 +end + +def fun_l7_n904() + fun_l8_n28 +end + +def fun_l7_n905() + fun_l8_n687 +end + +def fun_l7_n906() + fun_l8_n723 +end + +def fun_l7_n907() + fun_l8_n688 +end + +def fun_l7_n908() + fun_l8_n417 +end + +def fun_l7_n909() + fun_l8_n769 +end + +def fun_l7_n910() + fun_l8_n683 +end + +def fun_l7_n911() + fun_l8_n865 +end + +def fun_l7_n912() + fun_l8_n75 +end + +def fun_l7_n913() + fun_l8_n671 +end + +def fun_l7_n914() + fun_l8_n168 +end + +def fun_l7_n915() + fun_l8_n958 +end + +def fun_l7_n916() + fun_l8_n96 +end + +def fun_l7_n917() + fun_l8_n981 +end + +def fun_l7_n918() + fun_l8_n481 +end + +def fun_l7_n919() + fun_l8_n887 +end + +def fun_l7_n920() + fun_l8_n319 +end + +def fun_l7_n921() + fun_l8_n349 +end + +def fun_l7_n922() + fun_l8_n774 +end + +def fun_l7_n923() + fun_l8_n490 +end + +def fun_l7_n924() + fun_l8_n64 +end + +def fun_l7_n925() + fun_l8_n581 +end + +def fun_l7_n926() + fun_l8_n306 +end + +def fun_l7_n927() + fun_l8_n141 +end + +def fun_l7_n928() + fun_l8_n353 +end + +def fun_l7_n929() + fun_l8_n653 +end + +def fun_l7_n930() + fun_l8_n995 +end + +def fun_l7_n931() + fun_l8_n546 +end + +def fun_l7_n932() + fun_l8_n163 +end + +def fun_l7_n933() + fun_l8_n986 +end + +def fun_l7_n934() + fun_l8_n822 +end + +def fun_l7_n935() + fun_l8_n445 +end + +def fun_l7_n936() + fun_l8_n595 +end + +def fun_l7_n937() + fun_l8_n457 +end + +def fun_l7_n938() + fun_l8_n119 +end + +def fun_l7_n939() + fun_l8_n575 +end + +def fun_l7_n940() + fun_l8_n738 +end + +def fun_l7_n941() + fun_l8_n307 +end + +def fun_l7_n942() + fun_l8_n322 +end + +def fun_l7_n943() + fun_l8_n938 +end + +def fun_l7_n944() + fun_l8_n787 +end + +def fun_l7_n945() + fun_l8_n834 +end + +def fun_l7_n946() + fun_l8_n360 +end + +def fun_l7_n947() + fun_l8_n631 +end + +def fun_l7_n948() + fun_l8_n796 +end + +def fun_l7_n949() + fun_l8_n498 +end + +def fun_l7_n950() + fun_l8_n494 +end + +def fun_l7_n951() + fun_l8_n303 +end + +def fun_l7_n952() + fun_l8_n107 +end + +def fun_l7_n953() + fun_l8_n403 +end + +def fun_l7_n954() + fun_l8_n635 +end + +def fun_l7_n955() + fun_l8_n81 +end + +def fun_l7_n956() + fun_l8_n770 +end + +def fun_l7_n957() + fun_l8_n123 +end + +def fun_l7_n958() + fun_l8_n389 +end + +def fun_l7_n959() + fun_l8_n965 +end + +def fun_l7_n960() + fun_l8_n579 +end + +def fun_l7_n961() + fun_l8_n816 +end + +def fun_l7_n962() + fun_l8_n570 +end + +def fun_l7_n963() + fun_l8_n85 +end + +def fun_l7_n964() + fun_l8_n70 +end + +def fun_l7_n965() + fun_l8_n13 +end + +def fun_l7_n966() + fun_l8_n142 +end + +def fun_l7_n967() + fun_l8_n765 +end + +def fun_l7_n968() + fun_l8_n912 +end + +def fun_l7_n969() + fun_l8_n496 +end + +def fun_l7_n970() + fun_l8_n77 +end + +def fun_l7_n971() + fun_l8_n75 +end + +def fun_l7_n972() + fun_l8_n822 +end + +def fun_l7_n973() + fun_l8_n859 +end + +def fun_l7_n974() + fun_l8_n502 +end + +def fun_l7_n975() + fun_l8_n673 +end + +def fun_l7_n976() + fun_l8_n3 +end + +def fun_l7_n977() + fun_l8_n288 +end + +def fun_l7_n978() + fun_l8_n547 +end + +def fun_l7_n979() + fun_l8_n720 +end + +def fun_l7_n980() + fun_l8_n822 +end + +def fun_l7_n981() + fun_l8_n518 +end + +def fun_l7_n982() + fun_l8_n243 +end + +def fun_l7_n983() + fun_l8_n695 +end + +def fun_l7_n984() + fun_l8_n182 +end + +def fun_l7_n985() + fun_l8_n783 +end + +def fun_l7_n986() + fun_l8_n237 +end + +def fun_l7_n987() + fun_l8_n722 +end + +def fun_l7_n988() + fun_l8_n154 +end + +def fun_l7_n989() + fun_l8_n728 +end + +def fun_l7_n990() + fun_l8_n673 +end + +def fun_l7_n991() + fun_l8_n885 +end + +def fun_l7_n992() + fun_l8_n490 +end + +def fun_l7_n993() + fun_l8_n50 +end + +def fun_l7_n994() + fun_l8_n557 +end + +def fun_l7_n995() + fun_l8_n993 +end + +def fun_l7_n996() + fun_l8_n509 +end + +def fun_l7_n997() + fun_l8_n40 +end + +def fun_l7_n998() + fun_l8_n754 +end + +def fun_l7_n999() + fun_l8_n651 +end + +def fun_l8_n0() + fun_l9_n463 +end + +def fun_l8_n1() + fun_l9_n312 +end + +def fun_l8_n2() + fun_l9_n831 +end + +def fun_l8_n3() + fun_l9_n378 +end + +def fun_l8_n4() + fun_l9_n706 +end + +def fun_l8_n5() + fun_l9_n367 +end + +def fun_l8_n6() + fun_l9_n890 +end + +def fun_l8_n7() + fun_l9_n315 +end + +def fun_l8_n8() + fun_l9_n808 +end + +def fun_l8_n9() + fun_l9_n338 +end + +def fun_l8_n10() + fun_l9_n911 +end + +def fun_l8_n11() + fun_l9_n630 +end + +def fun_l8_n12() + fun_l9_n273 +end + +def fun_l8_n13() + fun_l9_n835 +end + +def fun_l8_n14() + fun_l9_n306 +end + +def fun_l8_n15() + fun_l9_n81 +end + +def fun_l8_n16() + fun_l9_n26 +end + +def fun_l8_n17() + fun_l9_n210 +end + +def fun_l8_n18() + fun_l9_n74 +end + +def fun_l8_n19() + fun_l9_n297 +end + +def fun_l8_n20() + fun_l9_n94 +end + +def fun_l8_n21() + fun_l9_n897 +end + +def fun_l8_n22() + fun_l9_n839 +end + +def fun_l8_n23() + fun_l9_n384 +end + +def fun_l8_n24() + fun_l9_n297 +end + +def fun_l8_n25() + fun_l9_n198 +end + +def fun_l8_n26() + fun_l9_n829 +end + +def fun_l8_n27() + fun_l9_n796 +end + +def fun_l8_n28() + fun_l9_n89 +end + +def fun_l8_n29() + fun_l9_n510 +end + +def fun_l8_n30() + fun_l9_n761 +end + +def fun_l8_n31() + fun_l9_n665 +end + +def fun_l8_n32() + fun_l9_n570 +end + +def fun_l8_n33() + fun_l9_n270 +end + +def fun_l8_n34() + fun_l9_n600 +end + +def fun_l8_n35() + fun_l9_n390 +end + +def fun_l8_n36() + fun_l9_n583 +end + +def fun_l8_n37() + fun_l9_n392 +end + +def fun_l8_n38() + fun_l9_n862 +end + +def fun_l8_n39() + fun_l9_n164 +end + +def fun_l8_n40() + fun_l9_n626 +end + +def fun_l8_n41() + fun_l9_n558 +end + +def fun_l8_n42() + fun_l9_n929 +end + +def fun_l8_n43() + fun_l9_n161 +end + +def fun_l8_n44() + fun_l9_n80 +end + +def fun_l8_n45() + fun_l9_n884 +end + +def fun_l8_n46() + fun_l9_n784 +end + +def fun_l8_n47() + fun_l9_n41 +end + +def fun_l8_n48() + fun_l9_n787 +end + +def fun_l8_n49() + fun_l9_n179 +end + +def fun_l8_n50() + fun_l9_n852 +end + +def fun_l8_n51() + fun_l9_n697 +end + +def fun_l8_n52() + fun_l9_n8 +end + +def fun_l8_n53() + fun_l9_n320 +end + +def fun_l8_n54() + fun_l9_n768 +end + +def fun_l8_n55() + fun_l9_n574 +end + +def fun_l8_n56() + fun_l9_n339 +end + +def fun_l8_n57() + fun_l9_n757 +end + +def fun_l8_n58() + fun_l9_n221 +end + +def fun_l8_n59() + fun_l9_n34 +end + +def fun_l8_n60() + fun_l9_n36 +end + +def fun_l8_n61() + fun_l9_n244 +end + +def fun_l8_n62() + fun_l9_n347 +end + +def fun_l8_n63() + fun_l9_n330 +end + +def fun_l8_n64() + fun_l9_n717 +end + +def fun_l8_n65() + fun_l9_n187 +end + +def fun_l8_n66() + fun_l9_n179 +end + +def fun_l8_n67() + fun_l9_n807 +end + +def fun_l8_n68() + fun_l9_n350 +end + +def fun_l8_n69() + fun_l9_n882 +end + +def fun_l8_n70() + fun_l9_n936 +end + +def fun_l8_n71() + fun_l9_n282 +end + +def fun_l8_n72() + fun_l9_n483 +end + +def fun_l8_n73() + fun_l9_n296 +end + +def fun_l8_n74() + fun_l9_n461 +end + +def fun_l8_n75() + fun_l9_n153 +end + +def fun_l8_n76() + fun_l9_n555 +end + +def fun_l8_n77() + fun_l9_n826 +end + +def fun_l8_n78() + fun_l9_n134 +end + +def fun_l8_n79() + fun_l9_n552 +end + +def fun_l8_n80() + fun_l9_n793 +end + +def fun_l8_n81() + fun_l9_n832 +end + +def fun_l8_n82() + fun_l9_n270 +end + +def fun_l8_n83() + fun_l9_n685 +end + +def fun_l8_n84() + fun_l9_n145 +end + +def fun_l8_n85() + fun_l9_n331 +end + +def fun_l8_n86() + fun_l9_n775 +end + +def fun_l8_n87() + fun_l9_n350 +end + +def fun_l8_n88() + fun_l9_n569 +end + +def fun_l8_n89() + fun_l9_n808 +end + +def fun_l8_n90() + fun_l9_n537 +end + +def fun_l8_n91() + fun_l9_n40 +end + +def fun_l8_n92() + fun_l9_n180 +end + +def fun_l8_n93() + fun_l9_n79 +end + +def fun_l8_n94() + fun_l9_n664 +end + +def fun_l8_n95() + fun_l9_n43 +end + +def fun_l8_n96() + fun_l9_n113 +end + +def fun_l8_n97() + fun_l9_n108 +end + +def fun_l8_n98() + fun_l9_n343 +end + +def fun_l8_n99() + fun_l9_n881 +end + +def fun_l8_n100() + fun_l9_n272 +end + +def fun_l8_n101() + fun_l9_n559 +end + +def fun_l8_n102() + fun_l9_n500 +end + +def fun_l8_n103() + fun_l9_n738 +end + +def fun_l8_n104() + fun_l9_n195 +end + +def fun_l8_n105() + fun_l9_n220 +end + +def fun_l8_n106() + fun_l9_n321 +end + +def fun_l8_n107() + fun_l9_n965 +end + +def fun_l8_n108() + fun_l9_n771 +end + +def fun_l8_n109() + fun_l9_n227 +end + +def fun_l8_n110() + fun_l9_n710 +end + +def fun_l8_n111() + fun_l9_n865 +end + +def fun_l8_n112() + fun_l9_n791 +end + +def fun_l8_n113() + fun_l9_n591 +end + +def fun_l8_n114() + fun_l9_n296 +end + +def fun_l8_n115() + fun_l9_n269 +end + +def fun_l8_n116() + fun_l9_n816 +end + +def fun_l8_n117() + fun_l9_n666 +end + +def fun_l8_n118() + fun_l9_n31 +end + +def fun_l8_n119() + fun_l9_n275 +end + +def fun_l8_n120() + fun_l9_n660 +end + +def fun_l8_n121() + fun_l9_n514 +end + +def fun_l8_n122() + fun_l9_n435 +end + +def fun_l8_n123() + fun_l9_n351 +end + +def fun_l8_n124() + fun_l9_n190 +end + +def fun_l8_n125() + fun_l9_n276 +end + +def fun_l8_n126() + fun_l9_n536 +end + +def fun_l8_n127() + fun_l9_n551 +end + +def fun_l8_n128() + fun_l9_n315 +end + +def fun_l8_n129() + fun_l9_n957 +end + +def fun_l8_n130() + fun_l9_n609 +end + +def fun_l8_n131() + fun_l9_n31 +end + +def fun_l8_n132() + fun_l9_n375 +end + +def fun_l8_n133() + fun_l9_n363 +end + +def fun_l8_n134() + fun_l9_n797 +end + +def fun_l8_n135() + fun_l9_n985 +end + +def fun_l8_n136() + fun_l9_n797 +end + +def fun_l8_n137() + fun_l9_n992 +end + +def fun_l8_n138() + fun_l9_n503 +end + +def fun_l8_n139() + fun_l9_n336 +end + +def fun_l8_n140() + fun_l9_n328 +end + +def fun_l8_n141() + fun_l9_n326 +end + +def fun_l8_n142() + fun_l9_n983 +end + +def fun_l8_n143() + fun_l9_n509 +end + +def fun_l8_n144() + fun_l9_n873 +end + +def fun_l8_n145() + fun_l9_n97 +end + +def fun_l8_n146() + fun_l9_n46 +end + +def fun_l8_n147() + fun_l9_n146 +end + +def fun_l8_n148() + fun_l9_n293 +end + +def fun_l8_n149() + fun_l9_n993 +end + +def fun_l8_n150() + fun_l9_n230 +end + +def fun_l8_n151() + fun_l9_n485 +end + +def fun_l8_n152() + fun_l9_n844 +end + +def fun_l8_n153() + fun_l9_n782 +end + +def fun_l8_n154() + fun_l9_n493 +end + +def fun_l8_n155() + fun_l9_n699 +end + +def fun_l8_n156() + fun_l9_n132 +end + +def fun_l8_n157() + fun_l9_n573 +end + +def fun_l8_n158() + fun_l9_n993 +end + +def fun_l8_n159() + fun_l9_n644 +end + +def fun_l8_n160() + fun_l9_n151 +end + +def fun_l8_n161() + fun_l9_n181 +end + +def fun_l8_n162() + fun_l9_n314 +end + +def fun_l8_n163() + fun_l9_n716 +end + +def fun_l8_n164() + fun_l9_n541 +end + +def fun_l8_n165() + fun_l9_n283 +end + +def fun_l8_n166() + fun_l9_n55 +end + +def fun_l8_n167() + fun_l9_n351 +end + +def fun_l8_n168() + fun_l9_n29 +end + +def fun_l8_n169() + fun_l9_n117 +end + +def fun_l8_n170() + fun_l9_n529 +end + +def fun_l8_n171() + fun_l9_n735 +end + +def fun_l8_n172() + fun_l9_n161 +end + +def fun_l8_n173() + fun_l9_n399 +end + +def fun_l8_n174() + fun_l9_n952 +end + +def fun_l8_n175() + fun_l9_n420 +end + +def fun_l8_n176() + fun_l9_n664 +end + +def fun_l8_n177() + fun_l9_n697 +end + +def fun_l8_n178() + fun_l9_n506 +end + +def fun_l8_n179() + fun_l9_n241 +end + +def fun_l8_n180() + fun_l9_n516 +end + +def fun_l8_n181() + fun_l9_n540 +end + +def fun_l8_n182() + fun_l9_n891 +end + +def fun_l8_n183() + fun_l9_n200 +end + +def fun_l8_n184() + fun_l9_n118 +end + +def fun_l8_n185() + fun_l9_n186 +end + +def fun_l8_n186() + fun_l9_n899 +end + +def fun_l8_n187() + fun_l9_n766 +end + +def fun_l8_n188() + fun_l9_n437 +end + +def fun_l8_n189() + fun_l9_n431 +end + +def fun_l8_n190() + fun_l9_n814 +end + +def fun_l8_n191() + fun_l9_n446 +end + +def fun_l8_n192() + fun_l9_n364 +end + +def fun_l8_n193() + fun_l9_n634 +end + +def fun_l8_n194() + fun_l9_n74 +end + +def fun_l8_n195() + fun_l9_n258 +end + +def fun_l8_n196() + fun_l9_n105 +end + +def fun_l8_n197() + fun_l9_n295 +end + +def fun_l8_n198() + fun_l9_n811 +end + +def fun_l8_n199() + fun_l9_n210 +end + +def fun_l8_n200() + fun_l9_n566 +end + +def fun_l8_n201() + fun_l9_n813 +end + +def fun_l8_n202() + fun_l9_n624 +end + +def fun_l8_n203() + fun_l9_n757 +end + +def fun_l8_n204() + fun_l9_n256 +end + +def fun_l8_n205() + fun_l9_n439 +end + +def fun_l8_n206() + fun_l9_n359 +end + +def fun_l8_n207() + fun_l9_n795 +end + +def fun_l8_n208() + fun_l9_n178 +end + +def fun_l8_n209() + fun_l9_n96 +end + +def fun_l8_n210() + fun_l9_n273 +end + +def fun_l8_n211() + fun_l9_n976 +end + +def fun_l8_n212() + fun_l9_n412 +end + +def fun_l8_n213() + fun_l9_n372 +end + +def fun_l8_n214() + fun_l9_n902 +end + +def fun_l8_n215() + fun_l9_n283 +end + +def fun_l8_n216() + fun_l9_n101 +end + +def fun_l8_n217() + fun_l9_n792 +end + +def fun_l8_n218() + fun_l9_n207 +end + +def fun_l8_n219() + fun_l9_n653 +end + +def fun_l8_n220() + fun_l9_n784 +end + +def fun_l8_n221() + fun_l9_n455 +end + +def fun_l8_n222() + fun_l9_n188 +end + +def fun_l8_n223() + fun_l9_n169 +end + +def fun_l8_n224() + fun_l9_n88 +end + +def fun_l8_n225() + fun_l9_n132 +end + +def fun_l8_n226() + fun_l9_n269 +end + +def fun_l8_n227() + fun_l9_n903 +end + +def fun_l8_n228() + fun_l9_n463 +end + +def fun_l8_n229() + fun_l9_n73 +end + +def fun_l8_n230() + fun_l9_n36 +end + +def fun_l8_n231() + fun_l9_n224 +end + +def fun_l8_n232() + fun_l9_n739 +end + +def fun_l8_n233() + fun_l9_n887 +end + +def fun_l8_n234() + fun_l9_n522 +end + +def fun_l8_n235() + fun_l9_n261 +end + +def fun_l8_n236() + fun_l9_n222 +end + +def fun_l8_n237() + fun_l9_n358 +end + +def fun_l8_n238() + fun_l9_n855 +end + +def fun_l8_n239() + fun_l9_n263 +end + +def fun_l8_n240() + fun_l9_n411 +end + +def fun_l8_n241() + fun_l9_n450 +end + +def fun_l8_n242() + fun_l9_n706 +end + +def fun_l8_n243() + fun_l9_n125 +end + +def fun_l8_n244() + fun_l9_n163 +end + +def fun_l8_n245() + fun_l9_n758 +end + +def fun_l8_n246() + fun_l9_n168 +end + +def fun_l8_n247() + fun_l9_n250 +end + +def fun_l8_n248() + fun_l9_n73 +end + +def fun_l8_n249() + fun_l9_n25 +end + +def fun_l8_n250() + fun_l9_n311 +end + +def fun_l8_n251() + fun_l9_n992 +end + +def fun_l8_n252() + fun_l9_n95 +end + +def fun_l8_n253() + fun_l9_n470 +end + +def fun_l8_n254() + fun_l9_n906 +end + +def fun_l8_n255() + fun_l9_n695 +end + +def fun_l8_n256() + fun_l9_n835 +end + +def fun_l8_n257() + fun_l9_n601 +end + +def fun_l8_n258() + fun_l9_n20 +end + +def fun_l8_n259() + fun_l9_n806 +end + +def fun_l8_n260() + fun_l9_n689 +end + +def fun_l8_n261() + fun_l9_n183 +end + +def fun_l8_n262() + fun_l9_n444 +end + +def fun_l8_n263() + fun_l9_n344 +end + +def fun_l8_n264() + fun_l9_n585 +end + +def fun_l8_n265() + fun_l9_n109 +end + +def fun_l8_n266() + fun_l9_n551 +end + +def fun_l8_n267() + fun_l9_n654 +end + +def fun_l8_n268() + fun_l9_n573 +end + +def fun_l8_n269() + fun_l9_n196 +end + +def fun_l8_n270() + fun_l9_n764 +end + +def fun_l8_n271() + fun_l9_n349 +end + +def fun_l8_n272() + fun_l9_n8 +end + +def fun_l8_n273() + fun_l9_n815 +end + +def fun_l8_n274() + fun_l9_n343 +end + +def fun_l8_n275() + fun_l9_n98 +end + +def fun_l8_n276() + fun_l9_n967 +end + +def fun_l8_n277() + fun_l9_n368 +end + +def fun_l8_n278() + fun_l9_n626 +end + +def fun_l8_n279() + fun_l9_n931 +end + +def fun_l8_n280() + fun_l9_n723 +end + +def fun_l8_n281() + fun_l9_n319 +end + +def fun_l8_n282() + fun_l9_n243 +end + +def fun_l8_n283() + fun_l9_n683 +end + +def fun_l8_n284() + fun_l9_n127 +end + +def fun_l8_n285() + fun_l9_n941 +end + +def fun_l8_n286() + fun_l9_n263 +end + +def fun_l8_n287() + fun_l9_n227 +end + +def fun_l8_n288() + fun_l9_n807 +end + +def fun_l8_n289() + fun_l9_n486 +end + +def fun_l8_n290() + fun_l9_n801 +end + +def fun_l8_n291() + fun_l9_n319 +end + +def fun_l8_n292() + fun_l9_n687 +end + +def fun_l8_n293() + fun_l9_n639 +end + +def fun_l8_n294() + fun_l9_n908 +end + +def fun_l8_n295() + fun_l9_n522 +end + +def fun_l8_n296() + fun_l9_n839 +end + +def fun_l8_n297() + fun_l9_n238 +end + +def fun_l8_n298() + fun_l9_n66 +end + +def fun_l8_n299() + fun_l9_n224 +end + +def fun_l8_n300() + fun_l9_n114 +end + +def fun_l8_n301() + fun_l9_n237 +end + +def fun_l8_n302() + fun_l9_n416 +end + +def fun_l8_n303() + fun_l9_n554 +end + +def fun_l8_n304() + fun_l9_n613 +end + +def fun_l8_n305() + fun_l9_n641 +end + +def fun_l8_n306() + fun_l9_n507 +end + +def fun_l8_n307() + fun_l9_n367 +end + +def fun_l8_n308() + fun_l9_n387 +end + +def fun_l8_n309() + fun_l9_n423 +end + +def fun_l8_n310() + fun_l9_n981 +end + +def fun_l8_n311() + fun_l9_n658 +end + +def fun_l8_n312() + fun_l9_n845 +end + +def fun_l8_n313() + fun_l9_n944 +end + +def fun_l8_n314() + fun_l9_n87 +end + +def fun_l8_n315() + fun_l9_n106 +end + +def fun_l8_n316() + fun_l9_n461 +end + +def fun_l8_n317() + fun_l9_n722 +end + +def fun_l8_n318() + fun_l9_n636 +end + +def fun_l8_n319() + fun_l9_n420 +end + +def fun_l8_n320() + fun_l9_n633 +end + +def fun_l8_n321() + fun_l9_n801 +end + +def fun_l8_n322() + fun_l9_n754 +end + +def fun_l8_n323() + fun_l9_n697 +end + +def fun_l8_n324() + fun_l9_n983 +end + +def fun_l8_n325() + fun_l9_n244 +end + +def fun_l8_n326() + fun_l9_n980 +end + +def fun_l8_n327() + fun_l9_n242 +end + +def fun_l8_n328() + fun_l9_n798 +end + +def fun_l8_n329() + fun_l9_n395 +end + +def fun_l8_n330() + fun_l9_n931 +end + +def fun_l8_n331() + fun_l9_n827 +end + +def fun_l8_n332() + fun_l9_n704 +end + +def fun_l8_n333() + fun_l9_n392 +end + +def fun_l8_n334() + fun_l9_n288 +end + +def fun_l8_n335() + fun_l9_n95 +end + +def fun_l8_n336() + fun_l9_n123 +end + +def fun_l8_n337() + fun_l9_n238 +end + +def fun_l8_n338() + fun_l9_n903 +end + +def fun_l8_n339() + fun_l9_n515 +end + +def fun_l8_n340() + fun_l9_n368 +end + +def fun_l8_n341() + fun_l9_n156 +end + +def fun_l8_n342() + fun_l9_n714 +end + +def fun_l8_n343() + fun_l9_n435 +end + +def fun_l8_n344() + fun_l9_n653 +end + +def fun_l8_n345() + fun_l9_n304 +end + +def fun_l8_n346() + fun_l9_n880 +end + +def fun_l8_n347() + fun_l9_n701 +end + +def fun_l8_n348() + fun_l9_n815 +end + +def fun_l8_n349() + fun_l9_n180 +end + +def fun_l8_n350() + fun_l9_n24 +end + +def fun_l8_n351() + fun_l9_n970 +end + +def fun_l8_n352() + fun_l9_n829 +end + +def fun_l8_n353() + fun_l9_n908 +end + +def fun_l8_n354() + fun_l9_n355 +end + +def fun_l8_n355() + fun_l9_n844 +end + +def fun_l8_n356() + fun_l9_n936 +end + +def fun_l8_n357() + fun_l9_n555 +end + +def fun_l8_n358() + fun_l9_n936 +end + +def fun_l8_n359() + fun_l9_n61 +end + +def fun_l8_n360() + fun_l9_n936 +end + +def fun_l8_n361() + fun_l9_n244 +end + +def fun_l8_n362() + fun_l9_n799 +end + +def fun_l8_n363() + fun_l9_n429 +end + +def fun_l8_n364() + fun_l9_n676 +end + +def fun_l8_n365() + fun_l9_n877 +end + +def fun_l8_n366() + fun_l9_n862 +end + +def fun_l8_n367() + fun_l9_n937 +end + +def fun_l8_n368() + fun_l9_n59 +end + +def fun_l8_n369() + fun_l9_n50 +end + +def fun_l8_n370() + fun_l9_n550 +end + +def fun_l8_n371() + fun_l9_n562 +end + +def fun_l8_n372() + fun_l9_n270 +end + +def fun_l8_n373() + fun_l9_n774 +end + +def fun_l8_n374() + fun_l9_n61 +end + +def fun_l8_n375() + fun_l9_n221 +end + +def fun_l8_n376() + fun_l9_n483 +end + +def fun_l8_n377() + fun_l9_n63 +end + +def fun_l8_n378() + fun_l9_n921 +end + +def fun_l8_n379() + fun_l9_n34 +end + +def fun_l8_n380() + fun_l9_n684 +end + +def fun_l8_n381() + fun_l9_n583 +end + +def fun_l8_n382() + fun_l9_n918 +end + +def fun_l8_n383() + fun_l9_n193 +end + +def fun_l8_n384() + fun_l9_n525 +end + +def fun_l8_n385() + fun_l9_n789 +end + +def fun_l8_n386() + fun_l9_n158 +end + +def fun_l8_n387() + fun_l9_n32 +end + +def fun_l8_n388() + fun_l9_n741 +end + +def fun_l8_n389() + fun_l9_n880 +end + +def fun_l8_n390() + fun_l9_n710 +end + +def fun_l8_n391() + fun_l9_n837 +end + +def fun_l8_n392() + fun_l9_n866 +end + +def fun_l8_n393() + fun_l9_n511 +end + +def fun_l8_n394() + fun_l9_n794 +end + +def fun_l8_n395() + fun_l9_n508 +end + +def fun_l8_n396() + fun_l9_n102 +end + +def fun_l8_n397() + fun_l9_n24 +end + +def fun_l8_n398() + fun_l9_n512 +end + +def fun_l8_n399() + fun_l9_n764 +end + +def fun_l8_n400() + fun_l9_n100 +end + +def fun_l8_n401() + fun_l9_n159 +end + +def fun_l8_n402() + fun_l9_n774 +end + +def fun_l8_n403() + fun_l9_n382 +end + +def fun_l8_n404() + fun_l9_n596 +end + +def fun_l8_n405() + fun_l9_n581 +end + +def fun_l8_n406() + fun_l9_n818 +end + +def fun_l8_n407() + fun_l9_n158 +end + +def fun_l8_n408() + fun_l9_n59 +end + +def fun_l8_n409() + fun_l9_n392 +end + +def fun_l8_n410() + fun_l9_n877 +end + +def fun_l8_n411() + fun_l9_n49 +end + +def fun_l8_n412() + fun_l9_n379 +end + +def fun_l8_n413() + fun_l9_n367 +end + +def fun_l8_n414() + fun_l9_n740 +end + +def fun_l8_n415() + fun_l9_n880 +end + +def fun_l8_n416() + fun_l9_n354 +end + +def fun_l8_n417() + fun_l9_n874 +end + +def fun_l8_n418() + fun_l9_n769 +end + +def fun_l8_n419() + fun_l9_n821 +end + +def fun_l8_n420() + fun_l9_n595 +end + +def fun_l8_n421() + fun_l9_n471 +end + +def fun_l8_n422() + fun_l9_n963 +end + +def fun_l8_n423() + fun_l9_n806 +end + +def fun_l8_n424() + fun_l9_n863 +end + +def fun_l8_n425() + fun_l9_n255 +end + +def fun_l8_n426() + fun_l9_n787 +end + +def fun_l8_n427() + fun_l9_n369 +end + +def fun_l8_n428() + fun_l9_n876 +end + +def fun_l8_n429() + fun_l9_n660 +end + +def fun_l8_n430() + fun_l9_n678 +end + +def fun_l8_n431() + fun_l9_n690 +end + +def fun_l8_n432() + fun_l9_n954 +end + +def fun_l8_n433() + fun_l9_n250 +end + +def fun_l8_n434() + fun_l9_n834 +end + +def fun_l8_n435() + fun_l9_n852 +end + +def fun_l8_n436() + fun_l9_n987 +end + +def fun_l8_n437() + fun_l9_n297 +end + +def fun_l8_n438() + fun_l9_n263 +end + +def fun_l8_n439() + fun_l9_n120 +end + +def fun_l8_n440() + fun_l9_n57 +end + +def fun_l8_n441() + fun_l9_n363 +end + +def fun_l8_n442() + fun_l9_n458 +end + +def fun_l8_n443() + fun_l9_n323 +end + +def fun_l8_n444() + fun_l9_n80 +end + +def fun_l8_n445() + fun_l9_n88 +end + +def fun_l8_n446() + fun_l9_n928 +end + +def fun_l8_n447() + fun_l9_n682 +end + +def fun_l8_n448() + fun_l9_n740 +end + +def fun_l8_n449() + fun_l9_n132 +end + +def fun_l8_n450() + fun_l9_n194 +end + +def fun_l8_n451() + fun_l9_n694 +end + +def fun_l8_n452() + fun_l9_n53 +end + +def fun_l8_n453() + fun_l9_n84 +end + +def fun_l8_n454() + fun_l9_n801 +end + +def fun_l8_n455() + fun_l9_n176 +end + +def fun_l8_n456() + fun_l9_n375 +end + +def fun_l8_n457() + fun_l9_n161 +end + +def fun_l8_n458() + fun_l9_n723 +end + +def fun_l8_n459() + fun_l9_n704 +end + +def fun_l8_n460() + fun_l9_n335 +end + +def fun_l8_n461() + fun_l9_n106 +end + +def fun_l8_n462() + fun_l9_n425 +end + +def fun_l8_n463() + fun_l9_n972 +end + +def fun_l8_n464() + fun_l9_n18 +end + +def fun_l8_n465() + fun_l9_n872 +end + +def fun_l8_n466() + fun_l9_n453 +end + +def fun_l8_n467() + fun_l9_n220 +end + +def fun_l8_n468() + fun_l9_n283 +end + +def fun_l8_n469() + fun_l9_n48 +end + +def fun_l8_n470() + fun_l9_n891 +end + +def fun_l8_n471() + fun_l9_n640 +end + +def fun_l8_n472() + fun_l9_n842 +end + +def fun_l8_n473() + fun_l9_n440 +end + +def fun_l8_n474() + fun_l9_n109 +end + +def fun_l8_n475() + fun_l9_n910 +end + +def fun_l8_n476() + fun_l9_n136 +end + +def fun_l8_n477() + fun_l9_n187 +end + +def fun_l8_n478() + fun_l9_n279 +end + +def fun_l8_n479() + fun_l9_n8 +end + +def fun_l8_n480() + fun_l9_n372 +end + +def fun_l8_n481() + fun_l9_n504 +end + +def fun_l8_n482() + fun_l9_n250 +end + +def fun_l8_n483() + fun_l9_n122 +end + +def fun_l8_n484() + fun_l9_n435 +end + +def fun_l8_n485() + fun_l9_n282 +end + +def fun_l8_n486() + fun_l9_n213 +end + +def fun_l8_n487() + fun_l9_n256 +end + +def fun_l8_n488() + fun_l9_n162 +end + +def fun_l8_n489() + fun_l9_n419 +end + +def fun_l8_n490() + fun_l9_n286 +end + +def fun_l8_n491() + fun_l9_n102 +end + +def fun_l8_n492() + fun_l9_n434 +end + +def fun_l8_n493() + fun_l9_n782 +end + +def fun_l8_n494() + fun_l9_n993 +end + +def fun_l8_n495() + fun_l9_n275 +end + +def fun_l8_n496() + fun_l9_n873 +end + +def fun_l8_n497() + fun_l9_n346 +end + +def fun_l8_n498() + fun_l9_n57 +end + +def fun_l8_n499() + fun_l9_n77 +end + +def fun_l8_n500() + fun_l9_n936 +end + +def fun_l8_n501() + fun_l9_n320 +end + +def fun_l8_n502() + fun_l9_n921 +end + +def fun_l8_n503() + fun_l9_n505 +end + +def fun_l8_n504() + fun_l9_n184 +end + +def fun_l8_n505() + fun_l9_n476 +end + +def fun_l8_n506() + fun_l9_n2 +end + +def fun_l8_n507() + fun_l9_n573 +end + +def fun_l8_n508() + fun_l9_n150 +end + +def fun_l8_n509() + fun_l9_n637 +end + +def fun_l8_n510() + fun_l9_n435 +end + +def fun_l8_n511() + fun_l9_n361 +end + +def fun_l8_n512() + fun_l9_n808 +end + +def fun_l8_n513() + fun_l9_n129 +end + +def fun_l8_n514() + fun_l9_n57 +end + +def fun_l8_n515() + fun_l9_n646 +end + +def fun_l8_n516() + fun_l9_n679 +end + +def fun_l8_n517() + fun_l9_n256 +end + +def fun_l8_n518() + fun_l9_n672 +end + +def fun_l8_n519() + fun_l9_n406 +end + +def fun_l8_n520() + fun_l9_n59 +end + +def fun_l8_n521() + fun_l9_n215 +end + +def fun_l8_n522() + fun_l9_n435 +end + +def fun_l8_n523() + fun_l9_n693 +end + +def fun_l8_n524() + fun_l9_n863 +end + +def fun_l8_n525() + fun_l9_n79 +end + +def fun_l8_n526() + fun_l9_n527 +end + +def fun_l8_n527() + fun_l9_n711 +end + +def fun_l8_n528() + fun_l9_n51 +end + +def fun_l8_n529() + fun_l9_n712 +end + +def fun_l8_n530() + fun_l9_n84 +end + +def fun_l8_n531() + fun_l9_n854 +end + +def fun_l8_n532() + fun_l9_n43 +end + +def fun_l8_n533() + fun_l9_n354 +end + +def fun_l8_n534() + fun_l9_n74 +end + +def fun_l8_n535() + fun_l9_n736 +end + +def fun_l8_n536() + fun_l9_n573 +end + +def fun_l8_n537() + fun_l9_n56 +end + +def fun_l8_n538() + fun_l9_n818 +end + +def fun_l8_n539() + fun_l9_n861 +end + +def fun_l8_n540() + fun_l9_n531 +end + +def fun_l8_n541() + fun_l9_n204 +end + +def fun_l8_n542() + fun_l9_n451 +end + +def fun_l8_n543() + fun_l9_n138 +end + +def fun_l8_n544() + fun_l9_n888 +end + +def fun_l8_n545() + fun_l9_n846 +end + +def fun_l8_n546() + fun_l9_n873 +end + +def fun_l8_n547() + fun_l9_n467 +end + +def fun_l8_n548() + fun_l9_n210 +end + +def fun_l8_n549() + fun_l9_n773 +end + +def fun_l8_n550() + fun_l9_n546 +end + +def fun_l8_n551() + fun_l9_n768 +end + +def fun_l8_n552() + fun_l9_n115 +end + +def fun_l8_n553() + fun_l9_n20 +end + +def fun_l8_n554() + fun_l9_n891 +end + +def fun_l8_n555() + fun_l9_n924 +end + +def fun_l8_n556() + fun_l9_n192 +end + +def fun_l8_n557() + fun_l9_n581 +end + +def fun_l8_n558() + fun_l9_n517 +end + +def fun_l8_n559() + fun_l9_n533 +end + +def fun_l8_n560() + fun_l9_n930 +end + +def fun_l8_n561() + fun_l9_n321 +end + +def fun_l8_n562() + fun_l9_n648 +end + +def fun_l8_n563() + fun_l9_n963 +end + +def fun_l8_n564() + fun_l9_n406 +end + +def fun_l8_n565() + fun_l9_n823 +end + +def fun_l8_n566() + fun_l9_n394 +end + +def fun_l8_n567() + fun_l9_n442 +end + +def fun_l8_n568() + fun_l9_n851 +end + +def fun_l8_n569() + fun_l9_n652 +end + +def fun_l8_n570() + fun_l9_n165 +end + +def fun_l8_n571() + fun_l9_n213 +end + +def fun_l8_n572() + fun_l9_n633 +end + +def fun_l8_n573() + fun_l9_n243 +end + +def fun_l8_n574() + fun_l9_n232 +end + +def fun_l8_n575() + fun_l9_n76 +end + +def fun_l8_n576() + fun_l9_n547 +end + +def fun_l8_n577() + fun_l9_n628 +end + +def fun_l8_n578() + fun_l9_n20 +end + +def fun_l8_n579() + fun_l9_n525 +end + +def fun_l8_n580() + fun_l9_n788 +end + +def fun_l8_n581() + fun_l9_n326 +end + +def fun_l8_n582() + fun_l9_n206 +end + +def fun_l8_n583() + fun_l9_n709 +end + +def fun_l8_n584() + fun_l9_n185 +end + +def fun_l8_n585() + fun_l9_n106 +end + +def fun_l8_n586() + fun_l9_n180 +end + +def fun_l8_n587() + fun_l9_n304 +end + +def fun_l8_n588() + fun_l9_n689 +end + +def fun_l8_n589() + fun_l9_n124 +end + +def fun_l8_n590() + fun_l9_n91 +end + +def fun_l8_n591() + fun_l9_n856 +end + +def fun_l8_n592() + fun_l9_n16 +end + +def fun_l8_n593() + fun_l9_n875 +end + +def fun_l8_n594() + fun_l9_n407 +end + +def fun_l8_n595() + fun_l9_n386 +end + +def fun_l8_n596() + fun_l9_n269 +end + +def fun_l8_n597() + fun_l9_n254 +end + +def fun_l8_n598() + fun_l9_n452 +end + +def fun_l8_n599() + fun_l9_n450 +end + +def fun_l8_n600() + fun_l9_n268 +end + +def fun_l8_n601() + fun_l9_n965 +end + +def fun_l8_n602() + fun_l9_n190 +end + +def fun_l8_n603() + fun_l9_n811 +end + +def fun_l8_n604() + fun_l9_n802 +end + +def fun_l8_n605() + fun_l9_n732 +end + +def fun_l8_n606() + fun_l9_n997 +end + +def fun_l8_n607() + fun_l9_n929 +end + +def fun_l8_n608() + fun_l9_n18 +end + +def fun_l8_n609() + fun_l9_n260 +end + +def fun_l8_n610() + fun_l9_n17 +end + +def fun_l8_n611() + fun_l9_n324 +end + +def fun_l8_n612() + fun_l9_n473 +end + +def fun_l8_n613() + fun_l9_n266 +end + +def fun_l8_n614() + fun_l9_n753 +end + +def fun_l8_n615() + fun_l9_n929 +end + +def fun_l8_n616() + fun_l9_n374 +end + +def fun_l8_n617() + fun_l9_n254 +end + +def fun_l8_n618() + fun_l9_n520 +end + +def fun_l8_n619() + fun_l9_n561 +end + +def fun_l8_n620() + fun_l9_n309 +end + +def fun_l8_n621() + fun_l9_n875 +end + +def fun_l8_n622() + fun_l9_n635 +end + +def fun_l8_n623() + fun_l9_n138 +end + +def fun_l8_n624() + fun_l9_n554 +end + +def fun_l8_n625() + fun_l9_n903 +end + +def fun_l8_n626() + fun_l9_n771 +end + +def fun_l8_n627() + fun_l9_n358 +end + +def fun_l8_n628() + fun_l9_n238 +end + +def fun_l8_n629() + fun_l9_n896 +end + +def fun_l8_n630() + fun_l9_n675 +end + +def fun_l8_n631() + fun_l9_n817 +end + +def fun_l8_n632() + fun_l9_n530 +end + +def fun_l8_n633() + fun_l9_n262 +end + +def fun_l8_n634() + fun_l9_n221 +end + +def fun_l8_n635() + fun_l9_n590 +end + +def fun_l8_n636() + fun_l9_n536 +end + +def fun_l8_n637() + fun_l9_n910 +end + +def fun_l8_n638() + fun_l9_n383 +end + +def fun_l8_n639() + fun_l9_n977 +end + +def fun_l8_n640() + fun_l9_n172 +end + +def fun_l8_n641() + fun_l9_n428 +end + +def fun_l8_n642() + fun_l9_n278 +end + +def fun_l8_n643() + fun_l9_n77 +end + +def fun_l8_n644() + fun_l9_n992 +end + +def fun_l8_n645() + fun_l9_n783 +end + +def fun_l8_n646() + fun_l9_n285 +end + +def fun_l8_n647() + fun_l9_n589 +end + +def fun_l8_n648() + fun_l9_n280 +end + +def fun_l8_n649() + fun_l9_n626 +end + +def fun_l8_n650() + fun_l9_n172 +end + +def fun_l8_n651() + fun_l9_n389 +end + +def fun_l8_n652() + fun_l9_n53 +end + +def fun_l8_n653() + fun_l9_n676 +end + +def fun_l8_n654() + fun_l9_n499 +end + +def fun_l8_n655() + fun_l9_n270 +end + +def fun_l8_n656() + fun_l9_n976 +end + +def fun_l8_n657() + fun_l9_n681 +end + +def fun_l8_n658() + fun_l9_n960 +end + +def fun_l8_n659() + fun_l9_n779 +end + +def fun_l8_n660() + fun_l9_n953 +end + +def fun_l8_n661() + fun_l9_n856 +end + +def fun_l8_n662() + fun_l9_n672 +end + +def fun_l8_n663() + fun_l9_n877 +end + +def fun_l8_n664() + fun_l9_n667 +end + +def fun_l8_n665() + fun_l9_n593 +end + +def fun_l8_n666() + fun_l9_n115 +end + +def fun_l8_n667() + fun_l9_n117 +end + +def fun_l8_n668() + fun_l9_n582 +end + +def fun_l8_n669() + fun_l9_n695 +end + +def fun_l8_n670() + fun_l9_n119 +end + +def fun_l8_n671() + fun_l9_n521 +end + +def fun_l8_n672() + fun_l9_n291 +end + +def fun_l8_n673() + fun_l9_n630 +end + +def fun_l8_n674() + fun_l9_n8 +end + +def fun_l8_n675() + fun_l9_n331 +end + +def fun_l8_n676() + fun_l9_n32 +end + +def fun_l8_n677() + fun_l9_n494 +end + +def fun_l8_n678() + fun_l9_n744 +end + +def fun_l8_n679() + fun_l9_n220 +end + +def fun_l8_n680() + fun_l9_n793 +end + +def fun_l8_n681() + fun_l9_n592 +end + +def fun_l8_n682() + fun_l9_n40 +end + +def fun_l8_n683() + fun_l9_n442 +end + +def fun_l8_n684() + fun_l9_n606 +end + +def fun_l8_n685() + fun_l9_n592 +end + +def fun_l8_n686() + fun_l9_n264 +end + +def fun_l8_n687() + fun_l9_n570 +end + +def fun_l8_n688() + fun_l9_n69 +end + +def fun_l8_n689() + fun_l9_n137 +end + +def fun_l8_n690() + fun_l9_n712 +end + +def fun_l8_n691() + fun_l9_n593 +end + +def fun_l8_n692() + fun_l9_n481 +end + +def fun_l8_n693() + fun_l9_n669 +end + +def fun_l8_n694() + fun_l9_n504 +end + +def fun_l8_n695() + fun_l9_n732 +end + +def fun_l8_n696() + fun_l9_n771 +end + +def fun_l8_n697() + fun_l9_n258 +end + +def fun_l8_n698() + fun_l9_n756 +end + +def fun_l8_n699() + fun_l9_n61 +end + +def fun_l8_n700() + fun_l9_n257 +end + +def fun_l8_n701() + fun_l9_n788 +end + +def fun_l8_n702() + fun_l9_n142 +end + +def fun_l8_n703() + fun_l9_n380 +end + +def fun_l8_n704() + fun_l9_n698 +end + +def fun_l8_n705() + fun_l9_n482 +end + +def fun_l8_n706() + fun_l9_n515 +end + +def fun_l8_n707() + fun_l9_n253 +end + +def fun_l8_n708() + fun_l9_n323 +end + +def fun_l8_n709() + fun_l9_n524 +end + +def fun_l8_n710() + fun_l9_n681 +end + +def fun_l8_n711() + fun_l9_n473 +end + +def fun_l8_n712() + fun_l9_n186 +end + +def fun_l8_n713() + fun_l9_n117 +end + +def fun_l8_n714() + fun_l9_n682 +end + +def fun_l8_n715() + fun_l9_n475 +end + +def fun_l8_n716() + fun_l9_n190 +end + +def fun_l8_n717() + fun_l9_n56 +end + +def fun_l8_n718() + fun_l9_n492 +end + +def fun_l8_n719() + fun_l9_n561 +end + +def fun_l8_n720() + fun_l9_n130 +end + +def fun_l8_n721() + fun_l9_n296 +end + +def fun_l8_n722() + fun_l9_n425 +end + +def fun_l8_n723() + fun_l9_n248 +end + +def fun_l8_n724() + fun_l9_n523 +end + +def fun_l8_n725() + fun_l9_n730 +end + +def fun_l8_n726() + fun_l9_n231 +end + +def fun_l8_n727() + fun_l9_n953 +end + +def fun_l8_n728() + fun_l9_n511 +end + +def fun_l8_n729() + fun_l9_n78 +end + +def fun_l8_n730() + fun_l9_n284 +end + +def fun_l8_n731() + fun_l9_n450 +end + +def fun_l8_n732() + fun_l9_n149 +end + +def fun_l8_n733() + fun_l9_n396 +end + +def fun_l8_n734() + fun_l9_n202 +end + +def fun_l8_n735() + fun_l9_n250 +end + +def fun_l8_n736() + fun_l9_n459 +end + +def fun_l8_n737() + fun_l9_n869 +end + +def fun_l8_n738() + fun_l9_n454 +end + +def fun_l8_n739() + fun_l9_n322 +end + +def fun_l8_n740() + fun_l9_n190 +end + +def fun_l8_n741() + fun_l9_n997 +end + +def fun_l8_n742() + fun_l9_n983 +end + +def fun_l8_n743() + fun_l9_n191 +end + +def fun_l8_n744() + fun_l9_n773 +end + +def fun_l8_n745() + fun_l9_n261 +end + +def fun_l8_n746() + fun_l9_n442 +end + +def fun_l8_n747() + fun_l9_n297 +end + +def fun_l8_n748() + fun_l9_n103 +end + +def fun_l8_n749() + fun_l9_n981 +end + +def fun_l8_n750() + fun_l9_n143 +end + +def fun_l8_n751() + fun_l9_n499 +end + +def fun_l8_n752() + fun_l9_n129 +end + +def fun_l8_n753() + fun_l9_n357 +end + +def fun_l8_n754() + fun_l9_n273 +end + +def fun_l8_n755() + fun_l9_n217 +end + +def fun_l8_n756() + fun_l9_n383 +end + +def fun_l8_n757() + fun_l9_n965 +end + +def fun_l8_n758() + fun_l9_n305 +end + +def fun_l8_n759() + fun_l9_n450 +end + +def fun_l8_n760() + fun_l9_n450 +end + +def fun_l8_n761() + fun_l9_n545 +end + +def fun_l8_n762() + fun_l9_n236 +end + +def fun_l8_n763() + fun_l9_n329 +end + +def fun_l8_n764() + fun_l9_n536 +end + +def fun_l8_n765() + fun_l9_n56 +end + +def fun_l8_n766() + fun_l9_n214 +end + +def fun_l8_n767() + fun_l9_n227 +end + +def fun_l8_n768() + fun_l9_n585 +end + +def fun_l8_n769() + fun_l9_n368 +end + +def fun_l8_n770() + fun_l9_n997 +end + +def fun_l8_n771() + fun_l9_n895 +end + +def fun_l8_n772() + fun_l9_n601 +end + +def fun_l8_n773() + fun_l9_n975 +end + +def fun_l8_n774() + fun_l9_n687 +end + +def fun_l8_n775() + fun_l9_n498 +end + +def fun_l8_n776() + fun_l9_n665 +end + +def fun_l8_n777() + fun_l9_n915 +end + +def fun_l8_n778() + fun_l9_n823 +end + +def fun_l8_n779() + fun_l9_n479 +end + +def fun_l8_n780() + fun_l9_n632 +end + +def fun_l8_n781() + fun_l9_n793 +end + +def fun_l8_n782() + fun_l9_n698 +end + +def fun_l8_n783() + fun_l9_n940 +end + +def fun_l8_n784() + fun_l9_n982 +end + +def fun_l8_n785() + fun_l9_n983 +end + +def fun_l8_n786() + fun_l9_n711 +end + +def fun_l8_n787() + fun_l9_n61 +end + +def fun_l8_n788() + fun_l9_n347 +end + +def fun_l8_n789() + fun_l9_n856 +end + +def fun_l8_n790() + fun_l9_n363 +end + +def fun_l8_n791() + fun_l9_n995 +end + +def fun_l8_n792() + fun_l9_n296 +end + +def fun_l8_n793() + fun_l9_n497 +end + +def fun_l8_n794() + fun_l9_n915 +end + +def fun_l8_n795() + fun_l9_n899 +end + +def fun_l8_n796() + fun_l9_n388 +end + +def fun_l8_n797() + fun_l9_n538 +end + +def fun_l8_n798() + fun_l9_n247 +end + +def fun_l8_n799() + fun_l9_n426 +end + +def fun_l8_n800() + fun_l9_n127 +end + +def fun_l8_n801() + fun_l9_n945 +end + +def fun_l8_n802() + fun_l9_n656 +end + +def fun_l8_n803() + fun_l9_n900 +end + +def fun_l8_n804() + fun_l9_n262 +end + +def fun_l8_n805() + fun_l9_n371 +end + +def fun_l8_n806() + fun_l9_n876 +end + +def fun_l8_n807() + fun_l9_n601 +end + +def fun_l8_n808() + fun_l9_n271 +end + +def fun_l8_n809() + fun_l9_n837 +end + +def fun_l8_n810() + fun_l9_n969 +end + +def fun_l8_n811() + fun_l9_n287 +end + +def fun_l8_n812() + fun_l9_n224 +end + +def fun_l8_n813() + fun_l9_n129 +end + +def fun_l8_n814() + fun_l9_n938 +end + +def fun_l8_n815() + fun_l9_n198 +end + +def fun_l8_n816() + fun_l9_n33 +end + +def fun_l8_n817() + fun_l9_n535 +end + +def fun_l8_n818() + fun_l9_n705 +end + +def fun_l8_n819() + fun_l9_n19 +end + +def fun_l8_n820() + fun_l9_n434 +end + +def fun_l8_n821() + fun_l9_n430 +end + +def fun_l8_n822() + fun_l9_n501 +end + +def fun_l8_n823() + fun_l9_n349 +end + +def fun_l8_n824() + fun_l9_n970 +end + +def fun_l8_n825() + fun_l9_n467 +end + +def fun_l8_n826() + fun_l9_n218 +end + +def fun_l8_n827() + fun_l9_n163 +end + +def fun_l8_n828() + fun_l9_n752 +end + +def fun_l8_n829() + fun_l9_n34 +end + +def fun_l8_n830() + fun_l9_n977 +end + +def fun_l8_n831() + fun_l9_n517 +end + +def fun_l8_n832() + fun_l9_n740 +end + +def fun_l8_n833() + fun_l9_n7 +end + +def fun_l8_n834() + fun_l9_n117 +end + +def fun_l8_n835() + fun_l9_n879 +end + +def fun_l8_n836() + fun_l9_n916 +end + +def fun_l8_n837() + fun_l9_n895 +end + +def fun_l8_n838() + fun_l9_n831 +end + +def fun_l8_n839() + fun_l9_n559 +end + +def fun_l8_n840() + fun_l9_n419 +end + +def fun_l8_n841() + fun_l9_n994 +end + +def fun_l8_n842() + fun_l9_n893 +end + +def fun_l8_n843() + fun_l9_n664 +end + +def fun_l8_n844() + fun_l9_n611 +end + +def fun_l8_n845() + fun_l9_n988 +end + +def fun_l8_n846() + fun_l9_n501 +end + +def fun_l8_n847() + fun_l9_n97 +end + +def fun_l8_n848() + fun_l9_n348 +end + +def fun_l8_n849() + fun_l9_n23 +end + +def fun_l8_n850() + fun_l9_n164 +end + +def fun_l8_n851() + fun_l9_n751 +end + +def fun_l8_n852() + fun_l9_n544 +end + +def fun_l8_n853() + fun_l9_n944 +end + +def fun_l8_n854() + fun_l9_n25 +end + +def fun_l8_n855() + fun_l9_n125 +end + +def fun_l8_n856() + fun_l9_n720 +end + +def fun_l8_n857() + fun_l9_n298 +end + +def fun_l8_n858() + fun_l9_n7 +end + +def fun_l8_n859() + fun_l9_n885 +end + +def fun_l8_n860() + fun_l9_n785 +end + +def fun_l8_n861() + fun_l9_n653 +end + +def fun_l8_n862() + fun_l9_n206 +end + +def fun_l8_n863() + fun_l9_n460 +end + +def fun_l8_n864() + fun_l9_n361 +end + +def fun_l8_n865() + fun_l9_n782 +end + +def fun_l8_n866() + fun_l9_n965 +end + +def fun_l8_n867() + fun_l9_n653 +end + +def fun_l8_n868() + fun_l9_n757 +end + +def fun_l8_n869() + fun_l9_n892 +end + +def fun_l8_n870() + fun_l9_n939 +end + +def fun_l8_n871() + fun_l9_n105 +end + +def fun_l8_n872() + fun_l9_n334 +end + +def fun_l8_n873() + fun_l9_n120 +end + +def fun_l8_n874() + fun_l9_n530 +end + +def fun_l8_n875() + fun_l9_n777 +end + +def fun_l8_n876() + fun_l9_n546 +end + +def fun_l8_n877() + fun_l9_n235 +end + +def fun_l8_n878() + fun_l9_n647 +end + +def fun_l8_n879() + fun_l9_n813 +end + +def fun_l8_n880() + fun_l9_n756 +end + +def fun_l8_n881() + fun_l9_n202 +end + +def fun_l8_n882() + fun_l9_n58 +end + +def fun_l8_n883() + fun_l9_n895 +end + +def fun_l8_n884() + fun_l9_n556 +end + +def fun_l8_n885() + fun_l9_n974 +end + +def fun_l8_n886() + fun_l9_n671 +end + +def fun_l8_n887() + fun_l9_n700 +end + +def fun_l8_n888() + fun_l9_n788 +end + +def fun_l8_n889() + fun_l9_n568 +end + +def fun_l8_n890() + fun_l9_n431 +end + +def fun_l8_n891() + fun_l9_n517 +end + +def fun_l8_n892() + fun_l9_n330 +end + +def fun_l8_n893() + fun_l9_n573 +end + +def fun_l8_n894() + fun_l9_n510 +end + +def fun_l8_n895() + fun_l9_n784 +end + +def fun_l8_n896() + fun_l9_n75 +end + +def fun_l8_n897() + fun_l9_n314 +end + +def fun_l8_n898() + fun_l9_n703 +end + +def fun_l8_n899() + fun_l9_n740 +end + +def fun_l8_n900() + fun_l9_n806 +end + +def fun_l8_n901() + fun_l9_n208 +end + +def fun_l8_n902() + fun_l9_n678 +end + +def fun_l8_n903() + fun_l9_n443 +end + +def fun_l8_n904() + fun_l9_n285 +end + +def fun_l8_n905() + fun_l9_n840 +end + +def fun_l8_n906() + fun_l9_n896 +end + +def fun_l8_n907() + fun_l9_n253 +end + +def fun_l8_n908() + fun_l9_n786 +end + +def fun_l8_n909() + fun_l9_n364 +end + +def fun_l8_n910() + fun_l9_n314 +end + +def fun_l8_n911() + fun_l9_n178 +end + +def fun_l8_n912() + fun_l9_n14 +end + +def fun_l8_n913() + fun_l9_n594 +end + +def fun_l8_n914() + fun_l9_n524 +end + +def fun_l8_n915() + fun_l9_n449 +end + +def fun_l8_n916() + fun_l9_n970 +end + +def fun_l8_n917() + fun_l9_n418 +end + +def fun_l8_n918() + fun_l9_n978 +end + +def fun_l8_n919() + fun_l9_n266 +end + +def fun_l8_n920() + fun_l9_n384 +end + +def fun_l8_n921() + fun_l9_n806 +end + +def fun_l8_n922() + fun_l9_n99 +end + +def fun_l8_n923() + fun_l9_n116 +end + +def fun_l8_n924() + fun_l9_n494 +end + +def fun_l8_n925() + fun_l9_n891 +end + +def fun_l8_n926() + fun_l9_n49 +end + +def fun_l8_n927() + fun_l9_n87 +end + +def fun_l8_n928() + fun_l9_n502 +end + +def fun_l8_n929() + fun_l9_n528 +end + +def fun_l8_n930() + fun_l9_n403 +end + +def fun_l8_n931() + fun_l9_n385 +end + +def fun_l8_n932() + fun_l9_n965 +end + +def fun_l8_n933() + fun_l9_n658 +end + +def fun_l8_n934() + fun_l9_n316 +end + +def fun_l8_n935() + fun_l9_n441 +end + +def fun_l8_n936() + fun_l9_n453 +end + +def fun_l8_n937() + fun_l9_n957 +end + +def fun_l8_n938() + fun_l9_n360 +end + +def fun_l8_n939() + fun_l9_n150 +end + +def fun_l8_n940() + fun_l9_n934 +end + +def fun_l8_n941() + fun_l9_n676 +end + +def fun_l8_n942() + fun_l9_n943 +end + +def fun_l8_n943() + fun_l9_n824 +end + +def fun_l8_n944() + fun_l9_n7 +end + +def fun_l8_n945() + fun_l9_n640 +end + +def fun_l8_n946() + fun_l9_n18 +end + +def fun_l8_n947() + fun_l9_n483 +end + +def fun_l8_n948() + fun_l9_n495 +end + +def fun_l8_n949() + fun_l9_n711 +end + +def fun_l8_n950() + fun_l9_n382 +end + +def fun_l8_n951() + fun_l9_n479 +end + +def fun_l8_n952() + fun_l9_n920 +end + +def fun_l8_n953() + fun_l9_n477 +end + +def fun_l8_n954() + fun_l9_n411 +end + +def fun_l8_n955() + fun_l9_n801 +end + +def fun_l8_n956() + fun_l9_n630 +end + +def fun_l8_n957() + fun_l9_n172 +end + +def fun_l8_n958() + fun_l9_n104 +end + +def fun_l8_n959() + fun_l9_n197 +end + +def fun_l8_n960() + fun_l9_n231 +end + +def fun_l8_n961() + fun_l9_n769 +end + +def fun_l8_n962() + fun_l9_n293 +end + +def fun_l8_n963() + fun_l9_n580 +end + +def fun_l8_n964() + fun_l9_n345 +end + +def fun_l8_n965() + fun_l9_n199 +end + +def fun_l8_n966() + fun_l9_n899 +end + +def fun_l8_n967() + fun_l9_n68 +end + +def fun_l8_n968() + fun_l9_n954 +end + +def fun_l8_n969() + fun_l9_n205 +end + +def fun_l8_n970() + fun_l9_n697 +end + +def fun_l8_n971() + fun_l9_n445 +end + +def fun_l8_n972() + fun_l9_n294 +end + +def fun_l8_n973() + fun_l9_n96 +end + +def fun_l8_n974() + fun_l9_n798 +end + +def fun_l8_n975() + fun_l9_n509 +end + +def fun_l8_n976() + fun_l9_n918 +end + +def fun_l8_n977() + fun_l9_n624 +end + +def fun_l8_n978() + fun_l9_n798 +end + +def fun_l8_n979() + fun_l9_n267 +end + +def fun_l8_n980() + fun_l9_n977 +end + +def fun_l8_n981() + fun_l9_n128 +end + +def fun_l8_n982() + fun_l9_n759 +end + +def fun_l8_n983() + fun_l9_n999 +end + +def fun_l8_n984() + fun_l9_n908 +end + +def fun_l8_n985() + fun_l9_n713 +end + +def fun_l8_n986() + fun_l9_n423 +end + +def fun_l8_n987() + fun_l9_n789 +end + +def fun_l8_n988() + fun_l9_n342 +end + +def fun_l8_n989() + fun_l9_n963 +end + +def fun_l8_n990() + fun_l9_n393 +end + +def fun_l8_n991() + fun_l9_n446 +end + +def fun_l8_n992() + fun_l9_n62 +end + +def fun_l8_n993() + fun_l9_n567 +end + +def fun_l8_n994() + fun_l9_n99 +end + +def fun_l8_n995() + fun_l9_n6 +end + +def fun_l8_n996() + fun_l9_n582 +end + +def fun_l8_n997() + fun_l9_n714 +end + +def fun_l8_n998() + fun_l9_n440 +end + +def fun_l8_n999() + fun_l9_n89 +end + +def fun_l9_n0() + fun_l10_n441 +end + +def fun_l9_n1() + fun_l10_n18 +end + +def fun_l9_n2() + fun_l10_n406 +end + +def fun_l9_n3() + fun_l10_n623 +end + +def fun_l9_n4() + fun_l10_n323 +end + +def fun_l9_n5() + fun_l10_n702 +end + +def fun_l9_n6() + fun_l10_n46 +end + +def fun_l9_n7() + fun_l10_n519 +end + +def fun_l9_n8() + fun_l10_n572 +end + +def fun_l9_n9() + fun_l10_n670 +end + +def fun_l9_n10() + fun_l10_n917 +end + +def fun_l9_n11() + fun_l10_n160 +end + +def fun_l9_n12() + fun_l10_n153 +end + +def fun_l9_n13() + fun_l10_n73 +end + +def fun_l9_n14() + fun_l10_n775 +end + +def fun_l9_n15() + fun_l10_n97 +end + +def fun_l9_n16() + fun_l10_n307 +end + +def fun_l9_n17() + fun_l10_n630 +end + +def fun_l9_n18() + fun_l10_n446 +end + +def fun_l9_n19() + fun_l10_n798 +end + +def fun_l9_n20() + fun_l10_n633 +end + +def fun_l9_n21() + fun_l10_n83 +end + +def fun_l9_n22() + fun_l10_n373 +end + +def fun_l9_n23() + fun_l10_n777 +end + +def fun_l9_n24() + fun_l10_n47 +end + +def fun_l9_n25() + fun_l10_n533 +end + +def fun_l9_n26() + fun_l10_n780 +end + +def fun_l9_n27() + fun_l10_n220 +end + +def fun_l9_n28() + fun_l10_n777 +end + +def fun_l9_n29() + fun_l10_n71 +end + +def fun_l9_n30() + fun_l10_n590 +end + +def fun_l9_n31() + fun_l10_n544 +end + +def fun_l9_n32() + fun_l10_n173 +end + +def fun_l9_n33() + fun_l10_n464 +end + +def fun_l9_n34() + fun_l10_n267 +end + +def fun_l9_n35() + fun_l10_n152 +end + +def fun_l9_n36() + fun_l10_n330 +end + +def fun_l9_n37() + fun_l10_n267 +end + +def fun_l9_n38() + fun_l10_n499 +end + +def fun_l9_n39() + fun_l10_n213 +end + +def fun_l9_n40() + fun_l10_n825 +end + +def fun_l9_n41() + fun_l10_n567 +end + +def fun_l9_n42() + fun_l10_n112 +end + +def fun_l9_n43() + fun_l10_n483 +end + +def fun_l9_n44() + fun_l10_n52 +end + +def fun_l9_n45() + fun_l10_n564 +end + +def fun_l9_n46() + fun_l10_n667 +end + +def fun_l9_n47() + fun_l10_n965 +end + +def fun_l9_n48() + fun_l10_n49 +end + +def fun_l9_n49() + fun_l10_n206 +end + +def fun_l9_n50() + fun_l10_n904 +end + +def fun_l9_n51() + fun_l10_n161 +end + +def fun_l9_n52() + fun_l10_n739 +end + +def fun_l9_n53() + fun_l10_n62 +end + +def fun_l9_n54() + fun_l10_n881 +end + +def fun_l9_n55() + fun_l10_n392 +end + +def fun_l9_n56() + fun_l10_n560 +end + +def fun_l9_n57() + fun_l10_n202 +end + +def fun_l9_n58() + fun_l10_n486 +end + +def fun_l9_n59() + fun_l10_n347 +end + +def fun_l9_n60() + fun_l10_n593 +end + +def fun_l9_n61() + fun_l10_n542 +end + +def fun_l9_n62() + fun_l10_n914 +end + +def fun_l9_n63() + fun_l10_n956 +end + +def fun_l9_n64() + fun_l10_n337 +end + +def fun_l9_n65() + fun_l10_n383 +end + +def fun_l9_n66() + fun_l10_n332 +end + +def fun_l9_n67() + fun_l10_n610 +end + +def fun_l9_n68() + fun_l10_n396 +end + +def fun_l9_n69() + fun_l10_n847 +end + +def fun_l9_n70() + fun_l10_n473 +end + +def fun_l9_n71() + fun_l10_n657 +end + +def fun_l9_n72() + fun_l10_n933 +end + +def fun_l9_n73() + fun_l10_n384 +end + +def fun_l9_n74() + fun_l10_n275 +end + +def fun_l9_n75() + fun_l10_n90 +end + +def fun_l9_n76() + fun_l10_n841 +end + +def fun_l9_n77() + fun_l10_n326 +end + +def fun_l9_n78() + fun_l10_n275 +end + +def fun_l9_n79() + fun_l10_n153 +end + +def fun_l9_n80() + fun_l10_n651 +end + +def fun_l9_n81() + fun_l10_n724 +end + +def fun_l9_n82() + fun_l10_n204 +end + +def fun_l9_n83() + fun_l10_n389 +end + +def fun_l9_n84() + fun_l10_n583 +end + +def fun_l9_n85() + fun_l10_n938 +end + +def fun_l9_n86() + fun_l10_n433 +end + +def fun_l9_n87() + fun_l10_n917 +end + +def fun_l9_n88() + fun_l10_n147 +end + +def fun_l9_n89() + fun_l10_n578 +end + +def fun_l9_n90() + fun_l10_n760 +end + +def fun_l9_n91() + fun_l10_n891 +end + +def fun_l9_n92() + fun_l10_n676 +end + +def fun_l9_n93() + fun_l10_n130 +end + +def fun_l9_n94() + fun_l10_n506 +end + +def fun_l9_n95() + fun_l10_n67 +end + +def fun_l9_n96() + fun_l10_n98 +end + +def fun_l9_n97() + fun_l10_n788 +end + +def fun_l9_n98() + fun_l10_n151 +end + +def fun_l9_n99() + fun_l10_n170 +end + +def fun_l9_n100() + fun_l10_n853 +end + +def fun_l9_n101() + fun_l10_n76 +end + +def fun_l9_n102() + fun_l10_n577 +end + +def fun_l9_n103() + fun_l10_n703 +end + +def fun_l9_n104() + fun_l10_n436 +end + +def fun_l9_n105() + fun_l10_n983 +end + +def fun_l9_n106() + fun_l10_n715 +end + +def fun_l9_n107() + fun_l10_n703 +end + +def fun_l9_n108() + fun_l10_n986 +end + +def fun_l9_n109() + fun_l10_n328 +end + +def fun_l9_n110() + fun_l10_n719 +end + +def fun_l9_n111() + fun_l10_n885 +end + +def fun_l9_n112() + fun_l10_n364 +end + +def fun_l9_n113() + fun_l10_n554 +end + +def fun_l9_n114() + fun_l10_n909 +end + +def fun_l9_n115() + fun_l10_n718 +end + +def fun_l9_n116() + fun_l10_n866 +end + +def fun_l9_n117() + fun_l10_n592 +end + +def fun_l9_n118() + fun_l10_n954 +end + +def fun_l9_n119() + fun_l10_n204 +end + +def fun_l9_n120() + fun_l10_n565 +end + +def fun_l9_n121() + fun_l10_n982 +end + +def fun_l9_n122() + fun_l10_n64 +end + +def fun_l9_n123() + fun_l10_n851 +end + +def fun_l9_n124() + fun_l10_n615 +end + +def fun_l9_n125() + fun_l10_n141 +end + +def fun_l9_n126() + fun_l10_n663 +end + +def fun_l9_n127() + fun_l10_n625 +end + +def fun_l9_n128() + fun_l10_n183 +end + +def fun_l9_n129() + fun_l10_n433 +end + +def fun_l9_n130() + fun_l10_n620 +end + +def fun_l9_n131() + fun_l10_n251 +end + +def fun_l9_n132() + fun_l10_n726 +end + +def fun_l9_n133() + fun_l10_n871 +end + +def fun_l9_n134() + fun_l10_n835 +end + +def fun_l9_n135() + fun_l10_n643 +end + +def fun_l9_n136() + fun_l10_n342 +end + +def fun_l9_n137() + fun_l10_n13 +end + +def fun_l9_n138() + fun_l10_n173 +end + +def fun_l9_n139() + fun_l10_n555 +end + +def fun_l9_n140() + fun_l10_n723 +end + +def fun_l9_n141() + fun_l10_n269 +end + +def fun_l9_n142() + fun_l10_n127 +end + +def fun_l9_n143() + fun_l10_n238 +end + +def fun_l9_n144() + fun_l10_n962 +end + +def fun_l9_n145() + fun_l10_n259 +end + +def fun_l9_n146() + fun_l10_n813 +end + +def fun_l9_n147() + fun_l10_n506 +end + +def fun_l9_n148() + fun_l10_n38 +end + +def fun_l9_n149() + fun_l10_n465 +end + +def fun_l9_n150() + fun_l10_n602 +end + +def fun_l9_n151() + fun_l10_n857 +end + +def fun_l9_n152() + fun_l10_n346 +end + +def fun_l9_n153() + fun_l10_n611 +end + +def fun_l9_n154() + fun_l10_n696 +end + +def fun_l9_n155() + fun_l10_n93 +end + +def fun_l9_n156() + fun_l10_n874 +end + +def fun_l9_n157() + fun_l10_n750 +end + +def fun_l9_n158() + fun_l10_n339 +end + +def fun_l9_n159() + fun_l10_n395 +end + +def fun_l9_n160() + fun_l10_n838 +end + +def fun_l9_n161() + fun_l10_n620 +end + +def fun_l9_n162() + fun_l10_n934 +end + +def fun_l9_n163() + fun_l10_n908 +end + +def fun_l9_n164() + fun_l10_n603 +end + +def fun_l9_n165() + fun_l10_n906 +end + +def fun_l9_n166() + fun_l10_n718 +end + +def fun_l9_n167() + fun_l10_n514 +end + +def fun_l9_n168() + fun_l10_n766 +end + +def fun_l9_n169() + fun_l10_n179 +end + +def fun_l9_n170() + fun_l10_n290 +end + +def fun_l9_n171() + fun_l10_n833 +end + +def fun_l9_n172() + fun_l10_n420 +end + +def fun_l9_n173() + fun_l10_n605 +end + +def fun_l9_n174() + fun_l10_n356 +end + +def fun_l9_n175() + fun_l10_n744 +end + +def fun_l9_n176() + fun_l10_n715 +end + +def fun_l9_n177() + fun_l10_n725 +end + +def fun_l9_n178() + fun_l10_n434 +end + +def fun_l9_n179() + fun_l10_n127 +end + +def fun_l9_n180() + fun_l10_n982 +end + +def fun_l9_n181() + fun_l10_n377 +end + +def fun_l9_n182() + fun_l10_n302 +end + +def fun_l9_n183() + fun_l10_n472 +end + +def fun_l9_n184() + fun_l10_n850 +end + +def fun_l9_n185() + fun_l10_n900 +end + +def fun_l9_n186() + fun_l10_n581 +end + +def fun_l9_n187() + fun_l10_n628 +end + +def fun_l9_n188() + fun_l10_n453 +end + +def fun_l9_n189() + fun_l10_n31 +end + +def fun_l9_n190() + fun_l10_n257 +end + +def fun_l9_n191() + fun_l10_n416 +end + +def fun_l9_n192() + fun_l10_n399 +end + +def fun_l9_n193() + fun_l10_n113 +end + +def fun_l9_n194() + fun_l10_n217 +end + +def fun_l9_n195() + fun_l10_n975 +end + +def fun_l9_n196() + fun_l10_n525 +end + +def fun_l9_n197() + fun_l10_n534 +end + +def fun_l9_n198() + fun_l10_n986 +end + +def fun_l9_n199() + fun_l10_n992 +end + +def fun_l9_n200() + fun_l10_n579 +end + +def fun_l9_n201() + fun_l10_n776 +end + +def fun_l9_n202() + fun_l10_n102 +end + +def fun_l9_n203() + fun_l10_n287 +end + +def fun_l9_n204() + fun_l10_n11 +end + +def fun_l9_n205() + fun_l10_n522 +end + +def fun_l9_n206() + fun_l10_n777 +end + +def fun_l9_n207() + fun_l10_n984 +end + +def fun_l9_n208() + fun_l10_n369 +end + +def fun_l9_n209() + fun_l10_n889 +end + +def fun_l9_n210() + fun_l10_n619 +end + +def fun_l9_n211() + fun_l10_n878 +end + +def fun_l9_n212() + fun_l10_n540 +end + +def fun_l9_n213() + fun_l10_n285 +end + +def fun_l9_n214() + fun_l10_n627 +end + +def fun_l9_n215() + fun_l10_n196 +end + +def fun_l9_n216() + fun_l10_n166 +end + +def fun_l9_n217() + fun_l10_n648 +end + +def fun_l9_n218() + fun_l10_n980 +end + +def fun_l9_n219() + fun_l10_n801 +end + +def fun_l9_n220() + fun_l10_n949 +end + +def fun_l9_n221() + fun_l10_n985 +end + +def fun_l9_n222() + fun_l10_n384 +end + +def fun_l9_n223() + fun_l10_n840 +end + +def fun_l9_n224() + fun_l10_n80 +end + +def fun_l9_n225() + fun_l10_n79 +end + +def fun_l9_n226() + fun_l10_n630 +end + +def fun_l9_n227() + fun_l10_n20 +end + +def fun_l9_n228() + fun_l10_n224 +end + +def fun_l9_n229() + fun_l10_n480 +end + +def fun_l9_n230() + fun_l10_n145 +end + +def fun_l9_n231() + fun_l10_n923 +end + +def fun_l9_n232() + fun_l10_n794 +end + +def fun_l9_n233() + fun_l10_n271 +end + +def fun_l9_n234() + fun_l10_n124 +end + +def fun_l9_n235() + fun_l10_n925 +end + +def fun_l9_n236() + fun_l10_n938 +end + +def fun_l9_n237() + fun_l10_n470 +end + +def fun_l9_n238() + fun_l10_n557 +end + +def fun_l9_n239() + fun_l10_n152 +end + +def fun_l9_n240() + fun_l10_n200 +end + +def fun_l9_n241() + fun_l10_n110 +end + +def fun_l9_n242() + fun_l10_n329 +end + +def fun_l9_n243() + fun_l10_n2 +end + +def fun_l9_n244() + fun_l10_n432 +end + +def fun_l9_n245() + fun_l10_n175 +end + +def fun_l9_n246() + fun_l10_n33 +end + +def fun_l9_n247() + fun_l10_n441 +end + +def fun_l9_n248() + fun_l10_n54 +end + +def fun_l9_n249() + fun_l10_n408 +end + +def fun_l9_n250() + fun_l10_n911 +end + +def fun_l9_n251() + fun_l10_n100 +end + +def fun_l9_n252() + fun_l10_n645 +end + +def fun_l9_n253() + fun_l10_n826 +end + +def fun_l9_n254() + fun_l10_n319 +end + +def fun_l9_n255() + fun_l10_n735 +end + +def fun_l9_n256() + fun_l10_n6 +end + +def fun_l9_n257() + fun_l10_n428 +end + +def fun_l9_n258() + fun_l10_n511 +end + +def fun_l9_n259() + fun_l10_n47 +end + +def fun_l9_n260() + fun_l10_n985 +end + +def fun_l9_n261() + fun_l10_n278 +end + +def fun_l9_n262() + fun_l10_n839 +end + +def fun_l9_n263() + fun_l10_n948 +end + +def fun_l9_n264() + fun_l10_n572 +end + +def fun_l9_n265() + fun_l10_n864 +end + +def fun_l9_n266() + fun_l10_n159 +end + +def fun_l9_n267() + fun_l10_n870 +end + +def fun_l9_n268() + fun_l10_n194 +end + +def fun_l9_n269() + fun_l10_n424 +end + +def fun_l9_n270() + fun_l10_n238 +end + +def fun_l9_n271() + fun_l10_n804 +end + +def fun_l9_n272() + fun_l10_n945 +end + +def fun_l9_n273() + fun_l10_n181 +end + +def fun_l9_n274() + fun_l10_n90 +end + +def fun_l9_n275() + fun_l10_n552 +end + +def fun_l9_n276() + fun_l10_n690 +end + +def fun_l9_n277() + fun_l10_n416 +end + +def fun_l9_n278() + fun_l10_n977 +end + +def fun_l9_n279() + fun_l10_n930 +end + +def fun_l9_n280() + fun_l10_n77 +end + +def fun_l9_n281() + fun_l10_n102 +end + +def fun_l9_n282() + fun_l10_n263 +end + +def fun_l9_n283() + fun_l10_n973 +end + +def fun_l9_n284() + fun_l10_n119 +end + +def fun_l9_n285() + fun_l10_n102 +end + +def fun_l9_n286() + fun_l10_n744 +end + +def fun_l9_n287() + fun_l10_n430 +end + +def fun_l9_n288() + fun_l10_n465 +end + +def fun_l9_n289() + fun_l10_n54 +end + +def fun_l9_n290() + fun_l10_n191 +end + +def fun_l9_n291() + fun_l10_n781 +end + +def fun_l9_n292() + fun_l10_n158 +end + +def fun_l9_n293() + fun_l10_n512 +end + +def fun_l9_n294() + fun_l10_n396 +end + +def fun_l9_n295() + fun_l10_n814 +end + +def fun_l9_n296() + fun_l10_n509 +end + +def fun_l9_n297() + fun_l10_n340 +end + +def fun_l9_n298() + fun_l10_n338 +end + +def fun_l9_n299() + fun_l10_n822 +end + +def fun_l9_n300() + fun_l10_n64 +end + +def fun_l9_n301() + fun_l10_n867 +end + +def fun_l9_n302() + fun_l10_n924 +end + +def fun_l9_n303() + fun_l10_n628 +end + +def fun_l9_n304() + fun_l10_n929 +end + +def fun_l9_n305() + fun_l10_n874 +end + +def fun_l9_n306() + fun_l10_n411 +end + +def fun_l9_n307() + fun_l10_n836 +end + +def fun_l9_n308() + fun_l10_n574 +end + +def fun_l9_n309() + fun_l10_n865 +end + +def fun_l9_n310() + fun_l10_n992 +end + +def fun_l9_n311() + fun_l10_n75 +end + +def fun_l9_n312() + fun_l10_n221 +end + +def fun_l9_n313() + fun_l10_n439 +end + +def fun_l9_n314() + fun_l10_n826 +end + +def fun_l9_n315() + fun_l10_n589 +end + +def fun_l9_n316() + fun_l10_n123 +end + +def fun_l9_n317() + fun_l10_n641 +end + +def fun_l9_n318() + fun_l10_n556 +end + +def fun_l9_n319() + fun_l10_n92 +end + +def fun_l9_n320() + fun_l10_n728 +end + +def fun_l9_n321() + fun_l10_n503 +end + +def fun_l9_n322() + fun_l10_n626 +end + +def fun_l9_n323() + fun_l10_n416 +end + +def fun_l9_n324() + fun_l10_n331 +end + +def fun_l9_n325() + fun_l10_n330 +end + +def fun_l9_n326() + fun_l10_n387 +end + +def fun_l9_n327() + fun_l10_n337 +end + +def fun_l9_n328() + fun_l10_n652 +end + +def fun_l9_n329() + fun_l10_n654 +end + +def fun_l9_n330() + fun_l10_n413 +end + +def fun_l9_n331() + fun_l10_n763 +end + +def fun_l9_n332() + fun_l10_n962 +end + +def fun_l9_n333() + fun_l10_n944 +end + +def fun_l9_n334() + fun_l10_n655 +end + +def fun_l9_n335() + fun_l10_n907 +end + +def fun_l9_n336() + fun_l10_n293 +end + +def fun_l9_n337() + fun_l10_n684 +end + +def fun_l9_n338() + fun_l10_n566 +end + +def fun_l9_n339() + fun_l10_n547 +end + +def fun_l9_n340() + fun_l10_n112 +end + +def fun_l9_n341() + fun_l10_n854 +end + +def fun_l9_n342() + fun_l10_n336 +end + +def fun_l9_n343() + fun_l10_n473 +end + +def fun_l9_n344() + fun_l10_n485 +end + +def fun_l9_n345() + fun_l10_n588 +end + +def fun_l9_n346() + fun_l10_n889 +end + +def fun_l9_n347() + fun_l10_n523 +end + +def fun_l9_n348() + fun_l10_n8 +end + +def fun_l9_n349() + fun_l10_n368 +end + +def fun_l9_n350() + fun_l10_n636 +end + +def fun_l9_n351() + fun_l10_n879 +end + +def fun_l9_n352() + fun_l10_n524 +end + +def fun_l9_n353() + fun_l10_n209 +end + +def fun_l9_n354() + fun_l10_n271 +end + +def fun_l9_n355() + fun_l10_n90 +end + +def fun_l9_n356() + fun_l10_n698 +end + +def fun_l9_n357() + fun_l10_n268 +end + +def fun_l9_n358() + fun_l10_n948 +end + +def fun_l9_n359() + fun_l10_n847 +end + +def fun_l9_n360() + fun_l10_n985 +end + +def fun_l9_n361() + fun_l10_n978 +end + +def fun_l9_n362() + fun_l10_n808 +end + +def fun_l9_n363() + fun_l10_n796 +end + +def fun_l9_n364() + fun_l10_n810 +end + +def fun_l9_n365() + fun_l10_n665 +end + +def fun_l9_n366() + fun_l10_n765 +end + +def fun_l9_n367() + fun_l10_n74 +end + +def fun_l9_n368() + fun_l10_n330 +end + +def fun_l9_n369() + fun_l10_n125 +end + +def fun_l9_n370() + fun_l10_n814 +end + +def fun_l9_n371() + fun_l10_n498 +end + +def fun_l9_n372() + fun_l10_n783 +end + +def fun_l9_n373() + fun_l10_n169 +end + +def fun_l9_n374() + fun_l10_n490 +end + +def fun_l9_n375() + fun_l10_n923 +end + +def fun_l9_n376() + fun_l10_n63 +end + +def fun_l9_n377() + fun_l10_n687 +end + +def fun_l9_n378() + fun_l10_n603 +end + +def fun_l9_n379() + fun_l10_n916 +end + +def fun_l9_n380() + fun_l10_n930 +end + +def fun_l9_n381() + fun_l10_n884 +end + +def fun_l9_n382() + fun_l10_n782 +end + +def fun_l9_n383() + fun_l10_n63 +end + +def fun_l9_n384() + fun_l10_n488 +end + +def fun_l9_n385() + fun_l10_n188 +end + +def fun_l9_n386() + fun_l10_n692 +end + +def fun_l9_n387() + fun_l10_n213 +end + +def fun_l9_n388() + fun_l10_n358 +end + +def fun_l9_n389() + fun_l10_n200 +end + +def fun_l9_n390() + fun_l10_n881 +end + +def fun_l9_n391() + fun_l10_n533 +end + +def fun_l9_n392() + fun_l10_n889 +end + +def fun_l9_n393() + fun_l10_n444 +end + +def fun_l9_n394() + fun_l10_n184 +end + +def fun_l9_n395() + fun_l10_n775 +end + +def fun_l9_n396() + fun_l10_n714 +end + +def fun_l9_n397() + fun_l10_n385 +end + +def fun_l9_n398() + fun_l10_n432 +end + +def fun_l9_n399() + fun_l10_n357 +end + +def fun_l9_n400() + fun_l10_n223 +end + +def fun_l9_n401() + fun_l10_n73 +end + +def fun_l9_n402() + fun_l10_n139 +end + +def fun_l9_n403() + fun_l10_n930 +end + +def fun_l9_n404() + fun_l10_n43 +end + +def fun_l9_n405() + fun_l10_n104 +end + +def fun_l9_n406() + fun_l10_n334 +end + +def fun_l9_n407() + fun_l10_n959 +end + +def fun_l9_n408() + fun_l10_n59 +end + +def fun_l9_n409() + fun_l10_n794 +end + +def fun_l9_n410() + fun_l10_n204 +end + +def fun_l9_n411() + fun_l10_n225 +end + +def fun_l9_n412() + fun_l10_n849 +end + +def fun_l9_n413() + fun_l10_n227 +end + +def fun_l9_n414() + fun_l10_n59 +end + +def fun_l9_n415() + fun_l10_n352 +end + +def fun_l9_n416() + fun_l10_n910 +end + +def fun_l9_n417() + fun_l10_n628 +end + +def fun_l9_n418() + fun_l10_n653 +end + +def fun_l9_n419() + fun_l10_n827 +end + +def fun_l9_n420() + fun_l10_n960 +end + +def fun_l9_n421() + fun_l10_n142 +end + +def fun_l9_n422() + fun_l10_n928 +end + +def fun_l9_n423() + fun_l10_n370 +end + +def fun_l9_n424() + fun_l10_n121 +end + +def fun_l9_n425() + fun_l10_n684 +end + +def fun_l9_n426() + fun_l10_n187 +end + +def fun_l9_n427() + fun_l10_n93 +end + +def fun_l9_n428() + fun_l10_n792 +end + +def fun_l9_n429() + fun_l10_n565 +end + +def fun_l9_n430() + fun_l10_n933 +end + +def fun_l9_n431() + fun_l10_n393 +end + +def fun_l9_n432() + fun_l10_n412 +end + +def fun_l9_n433() + fun_l10_n121 +end + +def fun_l9_n434() + fun_l10_n522 +end + +def fun_l9_n435() + fun_l10_n408 +end + +def fun_l9_n436() + fun_l10_n670 +end + +def fun_l9_n437() + fun_l10_n685 +end + +def fun_l9_n438() + fun_l10_n138 +end + +def fun_l9_n439() + fun_l10_n658 +end + +def fun_l9_n440() + fun_l10_n567 +end + +def fun_l9_n441() + fun_l10_n121 +end + +def fun_l9_n442() + fun_l10_n532 +end + +def fun_l9_n443() + fun_l10_n37 +end + +def fun_l9_n444() + fun_l10_n502 +end + +def fun_l9_n445() + fun_l10_n779 +end + +def fun_l9_n446() + fun_l10_n376 +end + +def fun_l9_n447() + fun_l10_n412 +end + +def fun_l9_n448() + fun_l10_n932 +end + +def fun_l9_n449() + fun_l10_n779 +end + +def fun_l9_n450() + fun_l10_n231 +end + +def fun_l9_n451() + fun_l10_n302 +end + +def fun_l9_n452() + fun_l10_n273 +end + +def fun_l9_n453() + fun_l10_n531 +end + +def fun_l9_n454() + fun_l10_n291 +end + +def fun_l9_n455() + fun_l10_n56 +end + +def fun_l9_n456() + fun_l10_n970 +end + +def fun_l9_n457() + fun_l10_n936 +end + +def fun_l9_n458() + fun_l10_n537 +end + +def fun_l9_n459() + fun_l10_n145 +end + +def fun_l9_n460() + fun_l10_n756 +end + +def fun_l9_n461() + fun_l10_n0 +end + +def fun_l9_n462() + fun_l10_n691 +end + +def fun_l9_n463() + fun_l10_n635 +end + +def fun_l9_n464() + fun_l10_n485 +end + +def fun_l9_n465() + fun_l10_n407 +end + +def fun_l9_n466() + fun_l10_n393 +end + +def fun_l9_n467() + fun_l10_n336 +end + +def fun_l9_n468() + fun_l10_n169 +end + +def fun_l9_n469() + fun_l10_n43 +end + +def fun_l9_n470() + fun_l10_n907 +end + +def fun_l9_n471() + fun_l10_n215 +end + +def fun_l9_n472() + fun_l10_n118 +end + +def fun_l9_n473() + fun_l10_n735 +end + +def fun_l9_n474() + fun_l10_n319 +end + +def fun_l9_n475() + fun_l10_n631 +end + +def fun_l9_n476() + fun_l10_n150 +end + +def fun_l9_n477() + fun_l10_n899 +end + +def fun_l9_n478() + fun_l10_n407 +end + +def fun_l9_n479() + fun_l10_n830 +end + +def fun_l9_n480() + fun_l10_n931 +end + +def fun_l9_n481() + fun_l10_n392 +end + +def fun_l9_n482() + fun_l10_n100 +end + +def fun_l9_n483() + fun_l10_n210 +end + +def fun_l9_n484() + fun_l10_n506 +end + +def fun_l9_n485() + fun_l10_n160 +end + +def fun_l9_n486() + fun_l10_n998 +end + +def fun_l9_n487() + fun_l10_n170 +end + +def fun_l9_n488() + fun_l10_n722 +end + +def fun_l9_n489() + fun_l10_n196 +end + +def fun_l9_n490() + fun_l10_n518 +end + +def fun_l9_n491() + fun_l10_n350 +end + +def fun_l9_n492() + fun_l10_n89 +end + +def fun_l9_n493() + fun_l10_n49 +end + +def fun_l9_n494() + fun_l10_n366 +end + +def fun_l9_n495() + fun_l10_n850 +end + +def fun_l9_n496() + fun_l10_n430 +end + +def fun_l9_n497() + fun_l10_n485 +end + +def fun_l9_n498() + fun_l10_n584 +end + +def fun_l9_n499() + fun_l10_n36 +end + +def fun_l9_n500() + fun_l10_n58 +end + +def fun_l9_n501() + fun_l10_n81 +end + +def fun_l9_n502() + fun_l10_n161 +end + +def fun_l9_n503() + fun_l10_n983 +end + +def fun_l9_n504() + fun_l10_n994 +end + +def fun_l9_n505() + fun_l10_n26 +end + +def fun_l9_n506() + fun_l10_n286 +end + +def fun_l9_n507() + fun_l10_n118 +end + +def fun_l9_n508() + fun_l10_n509 +end + +def fun_l9_n509() + fun_l10_n630 +end + +def fun_l9_n510() + fun_l10_n302 +end + +def fun_l9_n511() + fun_l10_n307 +end + +def fun_l9_n512() + fun_l10_n810 +end + +def fun_l9_n513() + fun_l10_n21 +end + +def fun_l9_n514() + fun_l10_n76 +end + +def fun_l9_n515() + fun_l10_n769 +end + +def fun_l9_n516() + fun_l10_n58 +end + +def fun_l9_n517() + fun_l10_n368 +end + +def fun_l9_n518() + fun_l10_n8 +end + +def fun_l9_n519() + fun_l10_n559 +end + +def fun_l9_n520() + fun_l10_n949 +end + +def fun_l9_n521() + fun_l10_n781 +end + +def fun_l9_n522() + fun_l10_n453 +end + +def fun_l9_n523() + fun_l10_n227 +end + +def fun_l9_n524() + fun_l10_n389 +end + +def fun_l9_n525() + fun_l10_n641 +end + +def fun_l9_n526() + fun_l10_n221 +end + +def fun_l9_n527() + fun_l10_n322 +end + +def fun_l9_n528() + fun_l10_n918 +end + +def fun_l9_n529() + fun_l10_n246 +end + +def fun_l9_n530() + fun_l10_n431 +end + +def fun_l9_n531() + fun_l10_n445 +end + +def fun_l9_n532() + fun_l10_n781 +end + +def fun_l9_n533() + fun_l10_n626 +end + +def fun_l9_n534() + fun_l10_n51 +end + +def fun_l9_n535() + fun_l10_n441 +end + +def fun_l9_n536() + fun_l10_n806 +end + +def fun_l9_n537() + fun_l10_n58 +end + +def fun_l9_n538() + fun_l10_n710 +end + +def fun_l9_n539() + fun_l10_n782 +end + +def fun_l9_n540() + fun_l10_n991 +end + +def fun_l9_n541() + fun_l10_n792 +end + +def fun_l9_n542() + fun_l10_n376 +end + +def fun_l9_n543() + fun_l10_n716 +end + +def fun_l9_n544() + fun_l10_n500 +end + +def fun_l9_n545() + fun_l10_n251 +end + +def fun_l9_n546() + fun_l10_n951 +end + +def fun_l9_n547() + fun_l10_n584 +end + +def fun_l9_n548() + fun_l10_n150 +end + +def fun_l9_n549() + fun_l10_n380 +end + +def fun_l9_n550() + fun_l10_n432 +end + +def fun_l9_n551() + fun_l10_n787 +end + +def fun_l9_n552() + fun_l10_n749 +end + +def fun_l9_n553() + fun_l10_n646 +end + +def fun_l9_n554() + fun_l10_n405 +end + +def fun_l9_n555() + fun_l10_n345 +end + +def fun_l9_n556() + fun_l10_n855 +end + +def fun_l9_n557() + fun_l10_n575 +end + +def fun_l9_n558() + fun_l10_n368 +end + +def fun_l9_n559() + fun_l10_n511 +end + +def fun_l9_n560() + fun_l10_n158 +end + +def fun_l9_n561() + fun_l10_n243 +end + +def fun_l9_n562() + fun_l10_n536 +end + +def fun_l9_n563() + fun_l10_n107 +end + +def fun_l9_n564() + fun_l10_n270 +end + +def fun_l9_n565() + fun_l10_n783 +end + +def fun_l9_n566() + fun_l10_n289 +end + +def fun_l9_n567() + fun_l10_n360 +end + +def fun_l9_n568() + fun_l10_n190 +end + +def fun_l9_n569() + fun_l10_n245 +end + +def fun_l9_n570() + fun_l10_n565 +end + +def fun_l9_n571() + fun_l10_n310 +end + +def fun_l9_n572() + fun_l10_n939 +end + +def fun_l9_n573() + fun_l10_n955 +end + +def fun_l9_n574() + fun_l10_n521 +end + +def fun_l9_n575() + fun_l10_n597 +end + +def fun_l9_n576() + fun_l10_n122 +end + +def fun_l9_n577() + fun_l10_n987 +end + +def fun_l9_n578() + fun_l10_n267 +end + +def fun_l9_n579() + fun_l10_n798 +end + +def fun_l9_n580() + fun_l10_n468 +end + +def fun_l9_n581() + fun_l10_n807 +end + +def fun_l9_n582() + fun_l10_n749 +end + +def fun_l9_n583() + fun_l10_n578 +end + +def fun_l9_n584() + fun_l10_n878 +end + +def fun_l9_n585() + fun_l10_n404 +end + +def fun_l9_n586() + fun_l10_n501 +end + +def fun_l9_n587() + fun_l10_n165 +end + +def fun_l9_n588() + fun_l10_n270 +end + +def fun_l9_n589() + fun_l10_n197 +end + +def fun_l9_n590() + fun_l10_n940 +end + +def fun_l9_n591() + fun_l10_n667 +end + +def fun_l9_n592() + fun_l10_n67 +end + +def fun_l9_n593() + fun_l10_n652 +end + +def fun_l9_n594() + fun_l10_n728 +end + +def fun_l9_n595() + fun_l10_n829 +end + +def fun_l9_n596() + fun_l10_n528 +end + +def fun_l9_n597() + fun_l10_n765 +end + +def fun_l9_n598() + fun_l10_n841 +end + +def fun_l9_n599() + fun_l10_n605 +end + +def fun_l9_n600() + fun_l10_n316 +end + +def fun_l9_n601() + fun_l10_n676 +end + +def fun_l9_n602() + fun_l10_n673 +end + +def fun_l9_n603() + fun_l10_n400 +end + +def fun_l9_n604() + fun_l10_n774 +end + +def fun_l9_n605() + fun_l10_n717 +end + +def fun_l9_n606() + fun_l10_n853 +end + +def fun_l9_n607() + fun_l10_n336 +end + +def fun_l9_n608() + fun_l10_n169 +end + +def fun_l9_n609() + fun_l10_n7 +end + +def fun_l9_n610() + fun_l10_n846 +end + +def fun_l9_n611() + fun_l10_n87 +end + +def fun_l9_n612() + fun_l10_n805 +end + +def fun_l9_n613() + fun_l10_n591 +end + +def fun_l9_n614() + fun_l10_n674 +end + +def fun_l9_n615() + fun_l10_n796 +end + +def fun_l9_n616() + fun_l10_n390 +end + +def fun_l9_n617() + fun_l10_n107 +end + +def fun_l9_n618() + fun_l10_n302 +end + +def fun_l9_n619() + fun_l10_n848 +end + +def fun_l9_n620() + fun_l10_n263 +end + +def fun_l9_n621() + fun_l10_n380 +end + +def fun_l9_n622() + fun_l10_n778 +end + +def fun_l9_n623() + fun_l10_n593 +end + +def fun_l9_n624() + fun_l10_n147 +end + +def fun_l9_n625() + fun_l10_n683 +end + +def fun_l9_n626() + fun_l10_n850 +end + +def fun_l9_n627() + fun_l10_n545 +end + +def fun_l9_n628() + fun_l10_n549 +end + +def fun_l9_n629() + fun_l10_n692 +end + +def fun_l9_n630() + fun_l10_n688 +end + +def fun_l9_n631() + fun_l10_n656 +end + +def fun_l9_n632() + fun_l10_n201 +end + +def fun_l9_n633() + fun_l10_n216 +end + +def fun_l9_n634() + fun_l10_n661 +end + +def fun_l9_n635() + fun_l10_n670 +end + +def fun_l9_n636() + fun_l10_n436 +end + +def fun_l9_n637() + fun_l10_n591 +end + +def fun_l9_n638() + fun_l10_n419 +end + +def fun_l9_n639() + fun_l10_n133 +end + +def fun_l9_n640() + fun_l10_n998 +end + +def fun_l9_n641() + fun_l10_n20 +end + +def fun_l9_n642() + fun_l10_n484 +end + +def fun_l9_n643() + fun_l10_n349 +end + +def fun_l9_n644() + fun_l10_n548 +end + +def fun_l9_n645() + fun_l10_n67 +end + +def fun_l9_n646() + fun_l10_n99 +end + +def fun_l9_n647() + fun_l10_n758 +end + +def fun_l9_n648() + fun_l10_n559 +end + +def fun_l9_n649() + fun_l10_n518 +end + +def fun_l9_n650() + fun_l10_n698 +end + +def fun_l9_n651() + fun_l10_n807 +end + +def fun_l9_n652() + fun_l10_n557 +end + +def fun_l9_n653() + fun_l10_n53 +end + +def fun_l9_n654() + fun_l10_n783 +end + +def fun_l9_n655() + fun_l10_n687 +end + +def fun_l9_n656() + fun_l10_n40 +end + +def fun_l9_n657() + fun_l10_n758 +end + +def fun_l9_n658() + fun_l10_n308 +end + +def fun_l9_n659() + fun_l10_n828 +end + +def fun_l9_n660() + fun_l10_n510 +end + +def fun_l9_n661() + fun_l10_n621 +end + +def fun_l9_n662() + fun_l10_n885 +end + +def fun_l9_n663() + fun_l10_n765 +end + +def fun_l9_n664() + fun_l10_n213 +end + +def fun_l9_n665() + fun_l10_n530 +end + +def fun_l9_n666() + fun_l10_n178 +end + +def fun_l9_n667() + fun_l10_n550 +end + +def fun_l9_n668() + fun_l10_n650 +end + +def fun_l9_n669() + fun_l10_n695 +end + +def fun_l9_n670() + fun_l10_n295 +end + +def fun_l9_n671() + fun_l10_n672 +end + +def fun_l9_n672() + fun_l10_n603 +end + +def fun_l9_n673() + fun_l10_n394 +end + +def fun_l9_n674() + fun_l10_n470 +end + +def fun_l9_n675() + fun_l10_n869 +end + +def fun_l9_n676() + fun_l10_n270 +end + +def fun_l9_n677() + fun_l10_n933 +end + +def fun_l9_n678() + fun_l10_n268 +end + +def fun_l9_n679() + fun_l10_n862 +end + +def fun_l9_n680() + fun_l10_n84 +end + +def fun_l9_n681() + fun_l10_n370 +end + +def fun_l9_n682() + fun_l10_n538 +end + +def fun_l9_n683() + fun_l10_n752 +end + +def fun_l9_n684() + fun_l10_n868 +end + +def fun_l9_n685() + fun_l10_n278 +end + +def fun_l9_n686() + fun_l10_n65 +end + +def fun_l9_n687() + fun_l10_n713 +end + +def fun_l9_n688() + fun_l10_n577 +end + +def fun_l9_n689() + fun_l10_n508 +end + +def fun_l9_n690() + fun_l10_n400 +end + +def fun_l9_n691() + fun_l10_n830 +end + +def fun_l9_n692() + fun_l10_n366 +end + +def fun_l9_n693() + fun_l10_n545 +end + +def fun_l9_n694() + fun_l10_n479 +end + +def fun_l9_n695() + fun_l10_n978 +end + +def fun_l9_n696() + fun_l10_n935 +end + +def fun_l9_n697() + fun_l10_n235 +end + +def fun_l9_n698() + fun_l10_n196 +end + +def fun_l9_n699() + fun_l10_n508 +end + +def fun_l9_n700() + fun_l10_n879 +end + +def fun_l9_n701() + fun_l10_n81 +end + +def fun_l9_n702() + fun_l10_n676 +end + +def fun_l9_n703() + fun_l10_n276 +end + +def fun_l9_n704() + fun_l10_n565 +end + +def fun_l9_n705() + fun_l10_n98 +end + +def fun_l9_n706() + fun_l10_n66 +end + +def fun_l9_n707() + fun_l10_n894 +end + +def fun_l9_n708() + fun_l10_n258 +end + +def fun_l9_n709() + fun_l10_n465 +end + +def fun_l9_n710() + fun_l10_n677 +end + +def fun_l9_n711() + fun_l10_n644 +end + +def fun_l9_n712() + fun_l10_n729 +end + +def fun_l9_n713() + fun_l10_n222 +end + +def fun_l9_n714() + fun_l10_n186 +end + +def fun_l9_n715() + fun_l10_n387 +end + +def fun_l9_n716() + fun_l10_n933 +end + +def fun_l9_n717() + fun_l10_n280 +end + +def fun_l9_n718() + fun_l10_n939 +end + +def fun_l9_n719() + fun_l10_n993 +end + +def fun_l9_n720() + fun_l10_n529 +end + +def fun_l9_n721() + fun_l10_n189 +end + +def fun_l9_n722() + fun_l10_n544 +end + +def fun_l9_n723() + fun_l10_n655 +end + +def fun_l9_n724() + fun_l10_n88 +end + +def fun_l9_n725() + fun_l10_n448 +end + +def fun_l9_n726() + fun_l10_n656 +end + +def fun_l9_n727() + fun_l10_n106 +end + +def fun_l9_n728() + fun_l10_n711 +end + +def fun_l9_n729() + fun_l10_n400 +end + +def fun_l9_n730() + fun_l10_n138 +end + +def fun_l9_n731() + fun_l10_n90 +end + +def fun_l9_n732() + fun_l10_n290 +end + +def fun_l9_n733() + fun_l10_n563 +end + +def fun_l9_n734() + fun_l10_n103 +end + +def fun_l9_n735() + fun_l10_n115 +end + +def fun_l9_n736() + fun_l10_n771 +end + +def fun_l9_n737() + fun_l10_n291 +end + +def fun_l9_n738() + fun_l10_n46 +end + +def fun_l9_n739() + fun_l10_n872 +end + +def fun_l9_n740() + fun_l10_n871 +end + +def fun_l9_n741() + fun_l10_n190 +end + +def fun_l9_n742() + fun_l10_n641 +end + +def fun_l9_n743() + fun_l10_n951 +end + +def fun_l9_n744() + fun_l10_n248 +end + +def fun_l9_n745() + fun_l10_n275 +end + +def fun_l9_n746() + fun_l10_n943 +end + +def fun_l9_n747() + fun_l10_n995 +end + +def fun_l9_n748() + fun_l10_n194 +end + +def fun_l9_n749() + fun_l10_n121 +end + +def fun_l9_n750() + fun_l10_n707 +end + +def fun_l9_n751() + fun_l10_n591 +end + +def fun_l9_n752() + fun_l10_n616 +end + +def fun_l9_n753() + fun_l10_n155 +end + +def fun_l9_n754() + fun_l10_n779 +end + +def fun_l9_n755() + fun_l10_n449 +end + +def fun_l9_n756() + fun_l10_n937 +end + +def fun_l9_n757() + fun_l10_n571 +end + +def fun_l9_n758() + fun_l10_n892 +end + +def fun_l9_n759() + fun_l10_n441 +end + +def fun_l9_n760() + fun_l10_n686 +end + +def fun_l9_n761() + fun_l10_n55 +end + +def fun_l9_n762() + fun_l10_n852 +end + +def fun_l9_n763() + fun_l10_n102 +end + +def fun_l9_n764() + fun_l10_n207 +end + +def fun_l9_n765() + fun_l10_n269 +end + +def fun_l9_n766() + fun_l10_n422 +end + +def fun_l9_n767() + fun_l10_n589 +end + +def fun_l9_n768() + fun_l10_n406 +end + +def fun_l9_n769() + fun_l10_n88 +end + +def fun_l9_n770() + fun_l10_n441 +end + +def fun_l9_n771() + fun_l10_n506 +end + +def fun_l9_n772() + fun_l10_n797 +end + +def fun_l9_n773() + fun_l10_n639 +end + +def fun_l9_n774() + fun_l10_n390 +end + +def fun_l9_n775() + fun_l10_n511 +end + +def fun_l9_n776() + fun_l10_n353 +end + +def fun_l9_n777() + fun_l10_n137 +end + +def fun_l9_n778() + fun_l10_n692 +end + +def fun_l9_n779() + fun_l10_n522 +end + +def fun_l9_n780() + fun_l10_n532 +end + +def fun_l9_n781() + fun_l10_n4 +end + +def fun_l9_n782() + fun_l10_n548 +end + +def fun_l9_n783() + fun_l10_n386 +end + +def fun_l9_n784() + fun_l10_n932 +end + +def fun_l9_n785() + fun_l10_n552 +end + +def fun_l9_n786() + fun_l10_n215 +end + +def fun_l9_n787() + fun_l10_n981 +end + +def fun_l9_n788() + fun_l10_n379 +end + +def fun_l9_n789() + fun_l10_n208 +end + +def fun_l9_n790() + fun_l10_n252 +end + +def fun_l9_n791() + fun_l10_n471 +end + +def fun_l9_n792() + fun_l10_n300 +end + +def fun_l9_n793() + fun_l10_n877 +end + +def fun_l9_n794() + fun_l10_n92 +end + +def fun_l9_n795() + fun_l10_n75 +end + +def fun_l9_n796() + fun_l10_n837 +end + +def fun_l9_n797() + fun_l10_n328 +end + +def fun_l9_n798() + fun_l10_n454 +end + +def fun_l9_n799() + fun_l10_n392 +end + +def fun_l9_n800() + fun_l10_n115 +end + +def fun_l9_n801() + fun_l10_n966 +end + +def fun_l9_n802() + fun_l10_n565 +end + +def fun_l9_n803() + fun_l10_n268 +end + +def fun_l9_n804() + fun_l10_n13 +end + +def fun_l9_n805() + fun_l10_n484 +end + +def fun_l9_n806() + fun_l10_n893 +end + +def fun_l9_n807() + fun_l10_n59 +end + +def fun_l9_n808() + fun_l10_n87 +end + +def fun_l9_n809() + fun_l10_n455 +end + +def fun_l9_n810() + fun_l10_n972 +end + +def fun_l9_n811() + fun_l10_n804 +end + +def fun_l9_n812() + fun_l10_n20 +end + +def fun_l9_n813() + fun_l10_n148 +end + +def fun_l9_n814() + fun_l10_n284 +end + +def fun_l9_n815() + fun_l10_n704 +end + +def fun_l9_n816() + fun_l10_n346 +end + +def fun_l9_n817() + fun_l10_n101 +end + +def fun_l9_n818() + fun_l10_n543 +end + +def fun_l9_n819() + fun_l10_n207 +end + +def fun_l9_n820() + fun_l10_n256 +end + +def fun_l9_n821() + fun_l10_n300 +end + +def fun_l9_n822() + fun_l10_n69 +end + +def fun_l9_n823() + fun_l10_n139 +end + +def fun_l9_n824() + fun_l10_n566 +end + +def fun_l9_n825() + fun_l10_n277 +end + +def fun_l9_n826() + fun_l10_n75 +end + +def fun_l9_n827() + fun_l10_n585 +end + +def fun_l9_n828() + fun_l10_n2 +end + +def fun_l9_n829() + fun_l10_n959 +end + +def fun_l9_n830() + fun_l10_n982 +end + +def fun_l9_n831() + fun_l10_n621 +end + +def fun_l9_n832() + fun_l10_n680 +end + +def fun_l9_n833() + fun_l10_n535 +end + +def fun_l9_n834() + fun_l10_n732 +end + +def fun_l9_n835() + fun_l10_n282 +end + +def fun_l9_n836() + fun_l10_n825 +end + +def fun_l9_n837() + fun_l10_n323 +end + +def fun_l9_n838() + fun_l10_n963 +end + +def fun_l9_n839() + fun_l10_n138 +end + +def fun_l9_n840() + fun_l10_n370 +end + +def fun_l9_n841() + fun_l10_n44 +end + +def fun_l9_n842() + fun_l10_n694 +end + +def fun_l9_n843() + fun_l10_n532 +end + +def fun_l9_n844() + fun_l10_n987 +end + +def fun_l9_n845() + fun_l10_n730 +end + +def fun_l9_n846() + fun_l10_n376 +end + +def fun_l9_n847() + fun_l10_n33 +end + +def fun_l9_n848() + fun_l10_n381 +end + +def fun_l9_n849() + fun_l10_n569 +end + +def fun_l9_n850() + fun_l10_n264 +end + +def fun_l9_n851() + fun_l10_n260 +end + +def fun_l9_n852() + fun_l10_n750 +end + +def fun_l9_n853() + fun_l10_n710 +end + +def fun_l9_n854() + fun_l10_n665 +end + +def fun_l9_n855() + fun_l10_n544 +end + +def fun_l9_n856() + fun_l10_n306 +end + +def fun_l9_n857() + fun_l10_n303 +end + +def fun_l9_n858() + fun_l10_n754 +end + +def fun_l9_n859() + fun_l10_n552 +end + +def fun_l9_n860() + fun_l10_n404 +end + +def fun_l9_n861() + fun_l10_n123 +end + +def fun_l9_n862() + fun_l10_n240 +end + +def fun_l9_n863() + fun_l10_n213 +end + +def fun_l9_n864() + fun_l10_n697 +end + +def fun_l9_n865() + fun_l10_n185 +end + +def fun_l9_n866() + fun_l10_n245 +end + +def fun_l9_n867() + fun_l10_n889 +end + +def fun_l9_n868() + fun_l10_n64 +end + +def fun_l9_n869() + fun_l10_n685 +end + +def fun_l9_n870() + fun_l10_n653 +end + +def fun_l9_n871() + fun_l10_n331 +end + +def fun_l9_n872() + fun_l10_n548 +end + +def fun_l9_n873() + fun_l10_n120 +end + +def fun_l9_n874() + fun_l10_n511 +end + +def fun_l9_n875() + fun_l10_n280 +end + +def fun_l9_n876() + fun_l10_n250 +end + +def fun_l9_n877() + fun_l10_n871 +end + +def fun_l9_n878() + fun_l10_n356 +end + +def fun_l9_n879() + fun_l10_n985 +end + +def fun_l9_n880() + fun_l10_n285 +end + +def fun_l9_n881() + fun_l10_n836 +end + +def fun_l9_n882() + fun_l10_n906 +end + +def fun_l9_n883() + fun_l10_n497 +end + +def fun_l9_n884() + fun_l10_n320 +end + +def fun_l9_n885() + fun_l10_n932 +end + +def fun_l9_n886() + fun_l10_n470 +end + +def fun_l9_n887() + fun_l10_n453 +end + +def fun_l9_n888() + fun_l10_n208 +end + +def fun_l9_n889() + fun_l10_n80 +end + +def fun_l9_n890() + fun_l10_n943 +end + +def fun_l9_n891() + fun_l10_n711 +end + +def fun_l9_n892() + fun_l10_n548 +end + +def fun_l9_n893() + fun_l10_n160 +end + +def fun_l9_n894() + fun_l10_n44 +end + +def fun_l9_n895() + fun_l10_n241 +end + +def fun_l9_n896() + fun_l10_n390 +end + +def fun_l9_n897() + fun_l10_n133 +end + +def fun_l9_n898() + fun_l10_n3 +end + +def fun_l9_n899() + fun_l10_n651 +end + +def fun_l9_n900() + fun_l10_n556 +end + +def fun_l9_n901() + fun_l10_n423 +end + +def fun_l9_n902() + fun_l10_n521 +end + +def fun_l9_n903() + fun_l10_n589 +end + +def fun_l9_n904() + fun_l10_n284 +end + +def fun_l9_n905() + fun_l10_n816 +end + +def fun_l9_n906() + fun_l10_n326 +end + +def fun_l9_n907() + fun_l10_n309 +end + +def fun_l9_n908() + fun_l10_n656 +end + +def fun_l9_n909() + fun_l10_n636 +end + +def fun_l9_n910() + fun_l10_n633 +end + +def fun_l9_n911() + fun_l10_n955 +end + +def fun_l9_n912() + fun_l10_n807 +end + +def fun_l9_n913() + fun_l10_n547 +end + +def fun_l9_n914() + fun_l10_n300 +end + +def fun_l9_n915() + fun_l10_n98 +end + +def fun_l9_n916() + fun_l10_n848 +end + +def fun_l9_n917() + fun_l10_n702 +end + +def fun_l9_n918() + fun_l10_n102 +end + +def fun_l9_n919() + fun_l10_n184 +end + +def fun_l9_n920() + fun_l10_n91 +end + +def fun_l9_n921() + fun_l10_n744 +end + +def fun_l9_n922() + fun_l10_n923 +end + +def fun_l9_n923() + fun_l10_n710 +end + +def fun_l9_n924() + fun_l10_n137 +end + +def fun_l9_n925() + fun_l10_n381 +end + +def fun_l9_n926() + fun_l10_n795 +end + +def fun_l9_n927() + fun_l10_n255 +end + +def fun_l9_n928() + fun_l10_n191 +end + +def fun_l9_n929() + fun_l10_n650 +end + +def fun_l9_n930() + fun_l10_n928 +end + +def fun_l9_n931() + fun_l10_n277 +end + +def fun_l9_n932() + fun_l10_n269 +end + +def fun_l9_n933() + fun_l10_n221 +end + +def fun_l9_n934() + fun_l10_n2 +end + +def fun_l9_n935() + fun_l10_n359 +end + +def fun_l9_n936() + fun_l10_n403 +end + +def fun_l9_n937() + fun_l10_n376 +end + +def fun_l9_n938() + fun_l10_n309 +end + +def fun_l9_n939() + fun_l10_n245 +end + +def fun_l9_n940() + fun_l10_n973 +end + +def fun_l9_n941() + fun_l10_n835 +end + +def fun_l9_n942() + fun_l10_n884 +end + +def fun_l9_n943() + fun_l10_n700 +end + +def fun_l9_n944() + fun_l10_n809 +end + +def fun_l9_n945() + fun_l10_n864 +end + +def fun_l9_n946() + fun_l10_n577 +end + +def fun_l9_n947() + fun_l10_n487 +end + +def fun_l9_n948() + fun_l10_n205 +end + +def fun_l9_n949() + fun_l10_n980 +end + +def fun_l9_n950() + fun_l10_n855 +end + +def fun_l9_n951() + fun_l10_n100 +end + +def fun_l9_n952() + fun_l10_n514 +end + +def fun_l9_n953() + fun_l10_n385 +end + +def fun_l9_n954() + fun_l10_n676 +end + +def fun_l9_n955() + fun_l10_n808 +end + +def fun_l9_n956() + fun_l10_n111 +end + +def fun_l9_n957() + fun_l10_n571 +end + +def fun_l9_n958() + fun_l10_n895 +end + +def fun_l9_n959() + fun_l10_n858 +end + +def fun_l9_n960() + fun_l10_n74 +end + +def fun_l9_n961() + fun_l10_n952 +end + +def fun_l9_n962() + fun_l10_n164 +end + +def fun_l9_n963() + fun_l10_n149 +end + +def fun_l9_n964() + fun_l10_n705 +end + +def fun_l9_n965() + fun_l10_n406 +end + +def fun_l9_n966() + fun_l10_n569 +end + +def fun_l9_n967() + fun_l10_n57 +end + +def fun_l9_n968() + fun_l10_n402 +end + +def fun_l9_n969() + fun_l10_n988 +end + +def fun_l9_n970() + fun_l10_n114 +end + +def fun_l9_n971() + fun_l10_n456 +end + +def fun_l9_n972() + fun_l10_n346 +end + +def fun_l9_n973() + fun_l10_n250 +end + +def fun_l9_n974() + fun_l10_n684 +end + +def fun_l9_n975() + fun_l10_n445 +end + +def fun_l9_n976() + fun_l10_n628 +end + +def fun_l9_n977() + fun_l10_n536 +end + +def fun_l9_n978() + fun_l10_n937 +end + +def fun_l9_n979() + fun_l10_n320 +end + +def fun_l9_n980() + fun_l10_n412 +end + +def fun_l9_n981() + fun_l10_n280 +end + +def fun_l9_n982() + fun_l10_n435 +end + +def fun_l9_n983() + fun_l10_n643 +end + +def fun_l9_n984() + fun_l10_n702 +end + +def fun_l9_n985() + fun_l10_n919 +end + +def fun_l9_n986() + fun_l10_n127 +end + +def fun_l9_n987() + fun_l10_n770 +end + +def fun_l9_n988() + fun_l10_n673 +end + +def fun_l9_n989() + fun_l10_n625 +end + +def fun_l9_n990() + fun_l10_n196 +end + +def fun_l9_n991() + fun_l10_n676 +end + +def fun_l9_n992() + fun_l10_n634 +end + +def fun_l9_n993() + fun_l10_n694 +end + +def fun_l9_n994() + fun_l10_n46 +end + +def fun_l9_n995() + fun_l10_n762 +end + +def fun_l9_n996() + fun_l10_n163 +end + +def fun_l9_n997() + fun_l10_n24 +end + +def fun_l9_n998() + fun_l10_n279 +end + +def fun_l9_n999() + fun_l10_n110 +end + +def fun_l10_n0() + fun_l11_n375 +end + +def fun_l10_n1() + fun_l11_n360 +end + +def fun_l10_n2() + fun_l11_n220 +end + +def fun_l10_n3() + fun_l11_n847 +end + +def fun_l10_n4() + fun_l11_n431 +end + +def fun_l10_n5() + fun_l11_n609 +end + +def fun_l10_n6() + fun_l11_n584 +end + +def fun_l10_n7() + fun_l11_n41 +end + +def fun_l10_n8() + fun_l11_n259 +end + +def fun_l10_n9() + fun_l11_n885 +end + +def fun_l10_n10() + fun_l11_n353 +end + +def fun_l10_n11() + fun_l11_n675 +end + +def fun_l10_n12() + fun_l11_n208 +end + +def fun_l10_n13() + fun_l11_n66 +end + +def fun_l10_n14() + fun_l11_n420 +end + +def fun_l10_n15() + fun_l11_n987 +end + +def fun_l10_n16() + fun_l11_n703 +end + +def fun_l10_n17() + fun_l11_n755 +end + +def fun_l10_n18() + fun_l11_n996 +end + +def fun_l10_n19() + fun_l11_n189 +end + +def fun_l10_n20() + fun_l11_n950 +end + +def fun_l10_n21() + fun_l11_n602 +end + +def fun_l10_n22() + fun_l11_n971 +end + +def fun_l10_n23() + fun_l11_n797 +end + +def fun_l10_n24() + fun_l11_n950 +end + +def fun_l10_n25() + fun_l11_n606 +end + +def fun_l10_n26() + fun_l11_n201 +end + +def fun_l10_n27() + fun_l11_n844 +end + +def fun_l10_n28() + fun_l11_n546 +end + +def fun_l10_n29() + fun_l11_n448 +end + +def fun_l10_n30() + fun_l11_n717 +end + +def fun_l10_n31() + fun_l11_n236 +end + +def fun_l10_n32() + fun_l11_n49 +end + +def fun_l10_n33() + fun_l11_n930 +end + +def fun_l10_n34() + fun_l11_n818 +end + +def fun_l10_n35() + fun_l11_n795 +end + +def fun_l10_n36() + fun_l11_n933 +end + +def fun_l10_n37() + fun_l11_n198 +end + +def fun_l10_n38() + fun_l11_n666 +end + +def fun_l10_n39() + fun_l11_n998 +end + +def fun_l10_n40() + fun_l11_n570 +end + +def fun_l10_n41() + fun_l11_n759 +end + +def fun_l10_n42() + fun_l11_n306 +end + +def fun_l10_n43() + fun_l11_n735 +end + +def fun_l10_n44() + fun_l11_n730 +end + +def fun_l10_n45() + fun_l11_n429 +end + +def fun_l10_n46() + fun_l11_n239 +end + +def fun_l10_n47() + fun_l11_n877 +end + +def fun_l10_n48() + fun_l11_n615 +end + +def fun_l10_n49() + fun_l11_n462 +end + +def fun_l10_n50() + fun_l11_n187 +end + +def fun_l10_n51() + fun_l11_n584 +end + +def fun_l10_n52() + fun_l11_n565 +end + +def fun_l10_n53() + fun_l11_n53 +end + +def fun_l10_n54() + fun_l11_n69 +end + +def fun_l10_n55() + fun_l11_n594 +end + +def fun_l10_n56() + fun_l11_n307 +end + +def fun_l10_n57() + fun_l11_n913 +end + +def fun_l10_n58() + fun_l11_n814 +end + +def fun_l10_n59() + fun_l11_n764 +end + +def fun_l10_n60() + fun_l11_n367 +end + +def fun_l10_n61() + fun_l11_n335 +end + +def fun_l10_n62() + fun_l11_n166 +end + +def fun_l10_n63() + fun_l11_n348 +end + +def fun_l10_n64() + fun_l11_n175 +end + +def fun_l10_n65() + fun_l11_n685 +end + +def fun_l10_n66() + fun_l11_n804 +end + +def fun_l10_n67() + fun_l11_n857 +end + +def fun_l10_n68() + fun_l11_n361 +end + +def fun_l10_n69() + fun_l11_n744 +end + +def fun_l10_n70() + fun_l11_n902 +end + +def fun_l10_n71() + fun_l11_n142 +end + +def fun_l10_n72() + fun_l11_n129 +end + +def fun_l10_n73() + fun_l11_n597 +end + +def fun_l10_n74() + fun_l11_n416 +end + +def fun_l10_n75() + fun_l11_n983 +end + +def fun_l10_n76() + fun_l11_n504 +end + +def fun_l10_n77() + fun_l11_n887 +end + +def fun_l10_n78() + fun_l11_n114 +end + +def fun_l10_n79() + fun_l11_n292 +end + +def fun_l10_n80() + fun_l11_n635 +end + +def fun_l10_n81() + fun_l11_n910 +end + +def fun_l10_n82() + fun_l11_n82 +end + +def fun_l10_n83() + fun_l11_n149 +end + +def fun_l10_n84() + fun_l11_n240 +end + +def fun_l10_n85() + fun_l11_n349 +end + +def fun_l10_n86() + fun_l11_n873 +end + +def fun_l10_n87() + fun_l11_n269 +end + +def fun_l10_n88() + fun_l11_n81 +end + +def fun_l10_n89() + fun_l11_n735 +end + +def fun_l10_n90() + fun_l11_n21 +end + +def fun_l10_n91() + fun_l11_n491 +end + +def fun_l10_n92() + fun_l11_n808 +end + +def fun_l10_n93() + fun_l11_n628 +end + +def fun_l10_n94() + fun_l11_n456 +end + +def fun_l10_n95() + fun_l11_n982 +end + +def fun_l10_n96() + fun_l11_n440 +end + +def fun_l10_n97() + fun_l11_n406 +end + +def fun_l10_n98() + fun_l11_n920 +end + +def fun_l10_n99() + fun_l11_n155 +end + +def fun_l10_n100() + fun_l11_n673 +end + +def fun_l10_n101() + fun_l11_n902 +end + +def fun_l10_n102() + fun_l11_n321 +end + +def fun_l10_n103() + fun_l11_n723 +end + +def fun_l10_n104() + fun_l11_n914 +end + +def fun_l10_n105() + fun_l11_n305 +end + +def fun_l10_n106() + fun_l11_n16 +end + +def fun_l10_n107() + fun_l11_n342 +end + +def fun_l10_n108() + fun_l11_n808 +end + +def fun_l10_n109() + fun_l11_n593 +end + +def fun_l10_n110() + fun_l11_n912 +end + +def fun_l10_n111() + fun_l11_n373 +end + +def fun_l10_n112() + fun_l11_n491 +end + +def fun_l10_n113() + fun_l11_n893 +end + +def fun_l10_n114() + fun_l11_n776 +end + +def fun_l10_n115() + fun_l11_n932 +end + +def fun_l10_n116() + fun_l11_n347 +end + +def fun_l10_n117() + fun_l11_n475 +end + +def fun_l10_n118() + fun_l11_n656 +end + +def fun_l10_n119() + fun_l11_n199 +end + +def fun_l10_n120() + fun_l11_n888 +end + +def fun_l10_n121() + fun_l11_n110 +end + +def fun_l10_n122() + fun_l11_n520 +end + +def fun_l10_n123() + fun_l11_n743 +end + +def fun_l10_n124() + fun_l11_n830 +end + +def fun_l10_n125() + fun_l11_n740 +end + +def fun_l10_n126() + fun_l11_n693 +end + +def fun_l10_n127() + fun_l11_n500 +end + +def fun_l10_n128() + fun_l11_n311 +end + +def fun_l10_n129() + fun_l11_n842 +end + +def fun_l10_n130() + fun_l11_n769 +end + +def fun_l10_n131() + fun_l11_n341 +end + +def fun_l10_n132() + fun_l11_n367 +end + +def fun_l10_n133() + fun_l11_n872 +end + +def fun_l10_n134() + fun_l11_n460 +end + +def fun_l10_n135() + fun_l11_n154 +end + +def fun_l10_n136() + fun_l11_n953 +end + +def fun_l10_n137() + fun_l11_n300 +end + +def fun_l10_n138() + fun_l11_n466 +end + +def fun_l10_n139() + fun_l11_n474 +end + +def fun_l10_n140() + fun_l11_n145 +end + +def fun_l10_n141() + fun_l11_n953 +end + +def fun_l10_n142() + fun_l11_n613 +end + +def fun_l10_n143() + fun_l11_n55 +end + +def fun_l10_n144() + fun_l11_n847 +end + +def fun_l10_n145() + fun_l11_n888 +end + +def fun_l10_n146() + fun_l11_n721 +end + +def fun_l10_n147() + fun_l11_n8 +end + +def fun_l10_n148() + fun_l11_n595 +end + +def fun_l10_n149() + fun_l11_n326 +end + +def fun_l10_n150() + fun_l11_n134 +end + +def fun_l10_n151() + fun_l11_n567 +end + +def fun_l10_n152() + fun_l11_n87 +end + +def fun_l10_n153() + fun_l11_n581 +end + +def fun_l10_n154() + fun_l11_n973 +end + +def fun_l10_n155() + fun_l11_n349 +end + +def fun_l10_n156() + fun_l11_n550 +end + +def fun_l10_n157() + fun_l11_n545 +end + +def fun_l10_n158() + fun_l11_n325 +end + +def fun_l10_n159() + fun_l11_n568 +end + +def fun_l10_n160() + fun_l11_n768 +end + +def fun_l10_n161() + fun_l11_n320 +end + +def fun_l10_n162() + fun_l11_n667 +end + +def fun_l10_n163() + fun_l11_n415 +end + +def fun_l10_n164() + fun_l11_n185 +end + +def fun_l10_n165() + fun_l11_n576 +end + +def fun_l10_n166() + fun_l11_n436 +end + +def fun_l10_n167() + fun_l11_n290 +end + +def fun_l10_n168() + fun_l11_n783 +end + +def fun_l10_n169() + fun_l11_n865 +end + +def fun_l10_n170() + fun_l11_n837 +end + +def fun_l10_n171() + fun_l11_n806 +end + +def fun_l10_n172() + fun_l11_n847 +end + +def fun_l10_n173() + fun_l11_n425 +end + +def fun_l10_n174() + fun_l11_n740 +end + +def fun_l10_n175() + fun_l11_n885 +end + +def fun_l10_n176() + fun_l11_n787 +end + +def fun_l10_n177() + fun_l11_n189 +end + +def fun_l10_n178() + fun_l11_n122 +end + +def fun_l10_n179() + fun_l11_n132 +end + +def fun_l10_n180() + fun_l11_n778 +end + +def fun_l10_n181() + fun_l11_n45 +end + +def fun_l10_n182() + fun_l11_n856 +end + +def fun_l10_n183() + fun_l11_n853 +end + +def fun_l10_n184() + fun_l11_n370 +end + +def fun_l10_n185() + fun_l11_n850 +end + +def fun_l10_n186() + fun_l11_n623 +end + +def fun_l10_n187() + fun_l11_n747 +end + +def fun_l10_n188() + fun_l11_n792 +end + +def fun_l10_n189() + fun_l11_n184 +end + +def fun_l10_n190() + fun_l11_n683 +end + +def fun_l10_n191() + fun_l11_n831 +end + +def fun_l10_n192() + fun_l11_n741 +end + +def fun_l10_n193() + fun_l11_n380 +end + +def fun_l10_n194() + fun_l11_n183 +end + +def fun_l10_n195() + fun_l11_n800 +end + +def fun_l10_n196() + fun_l11_n466 +end + +def fun_l10_n197() + fun_l11_n930 +end + +def fun_l10_n198() + fun_l11_n680 +end + +def fun_l10_n199() + fun_l11_n820 +end + +def fun_l10_n200() + fun_l11_n699 +end + +def fun_l10_n201() + fun_l11_n246 +end + +def fun_l10_n202() + fun_l11_n238 +end + +def fun_l10_n203() + fun_l11_n481 +end + +def fun_l10_n204() + fun_l11_n586 +end + +def fun_l10_n205() + fun_l11_n550 +end + +def fun_l10_n206() + fun_l11_n662 +end + +def fun_l10_n207() + fun_l11_n680 +end + +def fun_l10_n208() + fun_l11_n544 +end + +def fun_l10_n209() + fun_l11_n927 +end + +def fun_l10_n210() + fun_l11_n383 +end + +def fun_l10_n211() + fun_l11_n21 +end + +def fun_l10_n212() + fun_l11_n628 +end + +def fun_l10_n213() + fun_l11_n635 +end + +def fun_l10_n214() + fun_l11_n648 +end + +def fun_l10_n215() + fun_l11_n349 +end + +def fun_l10_n216() + fun_l11_n242 +end + +def fun_l10_n217() + fun_l11_n868 +end + +def fun_l10_n218() + fun_l11_n804 +end + +def fun_l10_n219() + fun_l11_n84 +end + +def fun_l10_n220() + fun_l11_n970 +end + +def fun_l10_n221() + fun_l11_n400 +end + +def fun_l10_n222() + fun_l11_n133 +end + +def fun_l10_n223() + fun_l11_n58 +end + +def fun_l10_n224() + fun_l11_n790 +end + +def fun_l10_n225() + fun_l11_n738 +end + +def fun_l10_n226() + fun_l11_n682 +end + +def fun_l10_n227() + fun_l11_n822 +end + +def fun_l10_n228() + fun_l11_n630 +end + +def fun_l10_n229() + fun_l11_n399 +end + +def fun_l10_n230() + fun_l11_n177 +end + +def fun_l10_n231() + fun_l11_n531 +end + +def fun_l10_n232() + fun_l11_n671 +end + +def fun_l10_n233() + fun_l11_n34 +end + +def fun_l10_n234() + fun_l11_n305 +end + +def fun_l10_n235() + fun_l11_n410 +end + +def fun_l10_n236() + fun_l11_n72 +end + +def fun_l10_n237() + fun_l11_n236 +end + +def fun_l10_n238() + fun_l11_n135 +end + +def fun_l10_n239() + fun_l11_n718 +end + +def fun_l10_n240() + fun_l11_n453 +end + +def fun_l10_n241() + fun_l11_n965 +end + +def fun_l10_n242() + fun_l11_n919 +end + +def fun_l10_n243() + fun_l11_n56 +end + +def fun_l10_n244() + fun_l11_n853 +end + +def fun_l10_n245() + fun_l11_n719 +end + +def fun_l10_n246() + fun_l11_n45 +end + +def fun_l10_n247() + fun_l11_n344 +end + +def fun_l10_n248() + fun_l11_n907 +end + +def fun_l10_n249() + fun_l11_n340 +end + +def fun_l10_n250() + fun_l11_n625 +end + +def fun_l10_n251() + fun_l11_n274 +end + +def fun_l10_n252() + fun_l11_n392 +end + +def fun_l10_n253() + fun_l11_n15 +end + +def fun_l10_n254() + fun_l11_n474 +end + +def fun_l10_n255() + fun_l11_n792 +end + +def fun_l10_n256() + fun_l11_n580 +end + +def fun_l10_n257() + fun_l11_n375 +end + +def fun_l10_n258() + fun_l11_n169 +end + +def fun_l10_n259() + fun_l11_n792 +end + +def fun_l10_n260() + fun_l11_n553 +end + +def fun_l10_n261() + fun_l11_n919 +end + +def fun_l10_n262() + fun_l11_n814 +end + +def fun_l10_n263() + fun_l11_n845 +end + +def fun_l10_n264() + fun_l11_n337 +end + +def fun_l10_n265() + fun_l11_n362 +end + +def fun_l10_n266() + fun_l11_n400 +end + +def fun_l10_n267() + fun_l11_n335 +end + +def fun_l10_n268() + fun_l11_n142 +end + +def fun_l10_n269() + fun_l11_n262 +end + +def fun_l10_n270() + fun_l11_n969 +end + +def fun_l10_n271() + fun_l11_n599 +end + +def fun_l10_n272() + fun_l11_n763 +end + +def fun_l10_n273() + fun_l11_n154 +end + +def fun_l10_n274() + fun_l11_n289 +end + +def fun_l10_n275() + fun_l11_n852 +end + +def fun_l10_n276() + fun_l11_n994 +end + +def fun_l10_n277() + fun_l11_n583 +end + +def fun_l10_n278() + fun_l11_n580 +end + +def fun_l10_n279() + fun_l11_n610 +end + +def fun_l10_n280() + fun_l11_n624 +end + +def fun_l10_n281() + fun_l11_n987 +end + +def fun_l10_n282() + fun_l11_n973 +end + +def fun_l10_n283() + fun_l11_n128 +end + +def fun_l10_n284() + fun_l11_n864 +end + +def fun_l10_n285() + fun_l11_n270 +end + +def fun_l10_n286() + fun_l11_n878 +end + +def fun_l10_n287() + fun_l11_n242 +end + +def fun_l10_n288() + fun_l11_n214 +end + +def fun_l10_n289() + fun_l11_n51 +end + +def fun_l10_n290() + fun_l11_n122 +end + +def fun_l10_n291() + fun_l11_n288 +end + +def fun_l10_n292() + fun_l11_n751 +end + +def fun_l10_n293() + fun_l11_n723 +end + +def fun_l10_n294() + fun_l11_n884 +end + +def fun_l10_n295() + fun_l11_n671 +end + +def fun_l10_n296() + fun_l11_n949 +end + +def fun_l10_n297() + fun_l11_n859 +end + +def fun_l10_n298() + fun_l11_n293 +end + +def fun_l10_n299() + fun_l11_n548 +end + +def fun_l10_n300() + fun_l11_n659 +end + +def fun_l10_n301() + fun_l11_n434 +end + +def fun_l10_n302() + fun_l11_n251 +end + +def fun_l10_n303() + fun_l11_n225 +end + +def fun_l10_n304() + fun_l11_n242 +end + +def fun_l10_n305() + fun_l11_n401 +end + +def fun_l10_n306() + fun_l11_n603 +end + +def fun_l10_n307() + fun_l11_n926 +end + +def fun_l10_n308() + fun_l11_n922 +end + +def fun_l10_n309() + fun_l11_n27 +end + +def fun_l10_n310() + fun_l11_n834 +end + +def fun_l10_n311() + fun_l11_n119 +end + +def fun_l10_n312() + fun_l11_n391 +end + +def fun_l10_n313() + fun_l11_n768 +end + +def fun_l10_n314() + fun_l11_n147 +end + +def fun_l10_n315() + fun_l11_n472 +end + +def fun_l10_n316() + fun_l11_n107 +end + +def fun_l10_n317() + fun_l11_n682 +end + +def fun_l10_n318() + fun_l11_n670 +end + +def fun_l10_n319() + fun_l11_n827 +end + +def fun_l10_n320() + fun_l11_n812 +end + +def fun_l10_n321() + fun_l11_n737 +end + +def fun_l10_n322() + fun_l11_n446 +end + +def fun_l10_n323() + fun_l11_n312 +end + +def fun_l10_n324() + fun_l11_n697 +end + +def fun_l10_n325() + fun_l11_n785 +end + +def fun_l10_n326() + fun_l11_n379 +end + +def fun_l10_n327() + fun_l11_n994 +end + +def fun_l10_n328() + fun_l11_n651 +end + +def fun_l10_n329() + fun_l11_n896 +end + +def fun_l10_n330() + fun_l11_n289 +end + +def fun_l10_n331() + fun_l11_n217 +end + +def fun_l10_n332() + fun_l11_n502 +end + +def fun_l10_n333() + fun_l11_n24 +end + +def fun_l10_n334() + fun_l11_n187 +end + +def fun_l10_n335() + fun_l11_n301 +end + +def fun_l10_n336() + fun_l11_n640 +end + +def fun_l10_n337() + fun_l11_n90 +end + +def fun_l10_n338() + fun_l11_n226 +end + +def fun_l10_n339() + fun_l11_n192 +end + +def fun_l10_n340() + fun_l11_n737 +end + +def fun_l10_n341() + fun_l11_n197 +end + +def fun_l10_n342() + fun_l11_n859 +end + +def fun_l10_n343() + fun_l11_n406 +end + +def fun_l10_n344() + fun_l11_n179 +end + +def fun_l10_n345() + fun_l11_n535 +end + +def fun_l10_n346() + fun_l11_n330 +end + +def fun_l10_n347() + fun_l11_n117 +end + +def fun_l10_n348() + fun_l11_n399 +end + +def fun_l10_n349() + fun_l11_n129 +end + +def fun_l10_n350() + fun_l11_n295 +end + +def fun_l10_n351() + fun_l11_n226 +end + +def fun_l10_n352() + fun_l11_n551 +end + +def fun_l10_n353() + fun_l11_n394 +end + +def fun_l10_n354() + fun_l11_n120 +end + +def fun_l10_n355() + fun_l11_n713 +end + +def fun_l10_n356() + fun_l11_n873 +end + +def fun_l10_n357() + fun_l11_n841 +end + +def fun_l10_n358() + fun_l11_n708 +end + +def fun_l10_n359() + fun_l11_n351 +end + +def fun_l10_n360() + fun_l11_n753 +end + +def fun_l10_n361() + fun_l11_n397 +end + +def fun_l10_n362() + fun_l11_n986 +end + +def fun_l10_n363() + fun_l11_n544 +end + +def fun_l10_n364() + fun_l11_n476 +end + +def fun_l10_n365() + fun_l11_n596 +end + +def fun_l10_n366() + fun_l11_n922 +end + +def fun_l10_n367() + fun_l11_n137 +end + +def fun_l10_n368() + fun_l11_n87 +end + +def fun_l10_n369() + fun_l11_n537 +end + +def fun_l10_n370() + fun_l11_n678 +end + +def fun_l10_n371() + fun_l11_n729 +end + +def fun_l10_n372() + fun_l11_n286 +end + +def fun_l10_n373() + fun_l11_n831 +end + +def fun_l10_n374() + fun_l11_n130 +end + +def fun_l10_n375() + fun_l11_n853 +end + +def fun_l10_n376() + fun_l11_n876 +end + +def fun_l10_n377() + fun_l11_n291 +end + +def fun_l10_n378() + fun_l11_n823 +end + +def fun_l10_n379() + fun_l11_n66 +end + +def fun_l10_n380() + fun_l11_n460 +end + +def fun_l10_n381() + fun_l11_n261 +end + +def fun_l10_n382() + fun_l11_n632 +end + +def fun_l10_n383() + fun_l11_n341 +end + +def fun_l10_n384() + fun_l11_n158 +end + +def fun_l10_n385() + fun_l11_n105 +end + +def fun_l10_n386() + fun_l11_n735 +end + +def fun_l10_n387() + fun_l11_n659 +end + +def fun_l10_n388() + fun_l11_n232 +end + +def fun_l10_n389() + fun_l11_n909 +end + +def fun_l10_n390() + fun_l11_n594 +end + +def fun_l10_n391() + fun_l11_n347 +end + +def fun_l10_n392() + fun_l11_n650 +end + +def fun_l10_n393() + fun_l11_n652 +end + +def fun_l10_n394() + fun_l11_n129 +end + +def fun_l10_n395() + fun_l11_n791 +end + +def fun_l10_n396() + fun_l11_n933 +end + +def fun_l10_n397() + fun_l11_n903 +end + +def fun_l10_n398() + fun_l11_n301 +end + +def fun_l10_n399() + fun_l11_n102 +end + +def fun_l10_n400() + fun_l11_n865 +end + +def fun_l10_n401() + fun_l11_n112 +end + +def fun_l10_n402() + fun_l11_n242 +end + +def fun_l10_n403() + fun_l11_n928 +end + +def fun_l10_n404() + fun_l11_n289 +end + +def fun_l10_n405() + fun_l11_n435 +end + +def fun_l10_n406() + fun_l11_n303 +end + +def fun_l10_n407() + fun_l11_n979 +end + +def fun_l10_n408() + fun_l11_n785 +end + +def fun_l10_n409() + fun_l11_n241 +end + +def fun_l10_n410() + fun_l11_n32 +end + +def fun_l10_n411() + fun_l11_n821 +end + +def fun_l10_n412() + fun_l11_n748 +end + +def fun_l10_n413() + fun_l11_n454 +end + +def fun_l10_n414() + fun_l11_n555 +end + +def fun_l10_n415() + fun_l11_n136 +end + +def fun_l10_n416() + fun_l11_n996 +end + +def fun_l10_n417() + fun_l11_n987 +end + +def fun_l10_n418() + fun_l11_n987 +end + +def fun_l10_n419() + fun_l11_n817 +end + +def fun_l10_n420() + fun_l11_n674 +end + +def fun_l10_n421() + fun_l11_n57 +end + +def fun_l10_n422() + fun_l11_n43 +end + +def fun_l10_n423() + fun_l11_n767 +end + +def fun_l10_n424() + fun_l11_n924 +end + +def fun_l10_n425() + fun_l11_n63 +end + +def fun_l10_n426() + fun_l11_n636 +end + +def fun_l10_n427() + fun_l11_n824 +end + +def fun_l10_n428() + fun_l11_n266 +end + +def fun_l10_n429() + fun_l11_n540 +end + +def fun_l10_n430() + fun_l11_n992 +end + +def fun_l10_n431() + fun_l11_n215 +end + +def fun_l10_n432() + fun_l11_n28 +end + +def fun_l10_n433() + fun_l11_n37 +end + +def fun_l10_n434() + fun_l11_n38 +end + +def fun_l10_n435() + fun_l11_n937 +end + +def fun_l10_n436() + fun_l11_n419 +end + +def fun_l10_n437() + fun_l11_n390 +end + +def fun_l10_n438() + fun_l11_n987 +end + +def fun_l10_n439() + fun_l11_n742 +end + +def fun_l10_n440() + fun_l11_n173 +end + +def fun_l10_n441() + fun_l11_n640 +end + +def fun_l10_n442() + fun_l11_n111 +end + +def fun_l10_n443() + fun_l11_n492 +end + +def fun_l10_n444() + fun_l11_n659 +end + +def fun_l10_n445() + fun_l11_n863 +end + +def fun_l10_n446() + fun_l11_n938 +end + +def fun_l10_n447() + fun_l11_n54 +end + +def fun_l10_n448() + fun_l11_n224 +end + +def fun_l10_n449() + fun_l11_n863 +end + +def fun_l10_n450() + fun_l11_n80 +end + +def fun_l10_n451() + fun_l11_n791 +end + +def fun_l10_n452() + fun_l11_n93 +end + +def fun_l10_n453() + fun_l11_n416 +end + +def fun_l10_n454() + fun_l11_n610 +end + +def fun_l10_n455() + fun_l11_n455 +end + +def fun_l10_n456() + fun_l11_n834 +end + +def fun_l10_n457() + fun_l11_n462 +end + +def fun_l10_n458() + fun_l11_n69 +end + +def fun_l10_n459() + fun_l11_n174 +end + +def fun_l10_n460() + fun_l11_n657 +end + +def fun_l10_n461() + fun_l11_n608 +end + +def fun_l10_n462() + fun_l11_n248 +end + +def fun_l10_n463() + fun_l11_n492 +end + +def fun_l10_n464() + fun_l11_n125 +end + +def fun_l10_n465() + fun_l11_n737 +end + +def fun_l10_n466() + fun_l11_n354 +end + +def fun_l10_n467() + fun_l11_n890 +end + +def fun_l10_n468() + fun_l11_n753 +end + +def fun_l10_n469() + fun_l11_n380 +end + +def fun_l10_n470() + fun_l11_n428 +end + +def fun_l10_n471() + fun_l11_n243 +end + +def fun_l10_n472() + fun_l11_n532 +end + +def fun_l10_n473() + fun_l11_n328 +end + +def fun_l10_n474() + fun_l11_n922 +end + +def fun_l10_n475() + fun_l11_n115 +end + +def fun_l10_n476() + fun_l11_n705 +end + +def fun_l10_n477() + fun_l11_n457 +end + +def fun_l10_n478() + fun_l11_n201 +end + +def fun_l10_n479() + fun_l11_n801 +end + +def fun_l10_n480() + fun_l11_n492 +end + +def fun_l10_n481() + fun_l11_n148 +end + +def fun_l10_n482() + fun_l11_n802 +end + +def fun_l10_n483() + fun_l11_n725 +end + +def fun_l10_n484() + fun_l11_n835 +end + +def fun_l10_n485() + fun_l11_n564 +end + +def fun_l10_n486() + fun_l11_n803 +end + +def fun_l10_n487() + fun_l11_n696 +end + +def fun_l10_n488() + fun_l11_n171 +end + +def fun_l10_n489() + fun_l11_n759 +end + +def fun_l10_n490() + fun_l11_n728 +end + +def fun_l10_n491() + fun_l11_n64 +end + +def fun_l10_n492() + fun_l11_n717 +end + +def fun_l10_n493() + fun_l11_n97 +end + +def fun_l10_n494() + fun_l11_n157 +end + +def fun_l10_n495() + fun_l11_n589 +end + +def fun_l10_n496() + fun_l11_n642 +end + +def fun_l10_n497() + fun_l11_n994 +end + +def fun_l10_n498() + fun_l11_n566 +end + +def fun_l10_n499() + fun_l11_n325 +end + +def fun_l10_n500() + fun_l11_n905 +end + +def fun_l10_n501() + fun_l11_n242 +end + +def fun_l10_n502() + fun_l11_n135 +end + +def fun_l10_n503() + fun_l11_n476 +end + +def fun_l10_n504() + fun_l11_n63 +end + +def fun_l10_n505() + fun_l11_n908 +end + +def fun_l10_n506() + fun_l11_n51 +end + +def fun_l10_n507() + fun_l11_n261 +end + +def fun_l10_n508() + fun_l11_n680 +end + +def fun_l10_n509() + fun_l11_n346 +end + +def fun_l10_n510() + fun_l11_n490 +end + +def fun_l10_n511() + fun_l11_n896 +end + +def fun_l10_n512() + fun_l11_n788 +end + +def fun_l10_n513() + fun_l11_n672 +end + +def fun_l10_n514() + fun_l11_n17 +end + +def fun_l10_n515() + fun_l11_n744 +end + +def fun_l10_n516() + fun_l11_n90 +end + +def fun_l10_n517() + fun_l11_n451 +end + +def fun_l10_n518() + fun_l11_n942 +end + +def fun_l10_n519() + fun_l11_n275 +end + +def fun_l10_n520() + fun_l11_n422 +end + +def fun_l10_n521() + fun_l11_n463 +end + +def fun_l10_n522() + fun_l11_n198 +end + +def fun_l10_n523() + fun_l11_n703 +end + +def fun_l10_n524() + fun_l11_n745 +end + +def fun_l10_n525() + fun_l11_n476 +end + +def fun_l10_n526() + fun_l11_n122 +end + +def fun_l10_n527() + fun_l11_n111 +end + +def fun_l10_n528() + fun_l11_n354 +end + +def fun_l10_n529() + fun_l11_n63 +end + +def fun_l10_n530() + fun_l11_n652 +end + +def fun_l10_n531() + fun_l11_n535 +end + +def fun_l10_n532() + fun_l11_n990 +end + +def fun_l10_n533() + fun_l11_n506 +end + +def fun_l10_n534() + fun_l11_n741 +end + +def fun_l10_n535() + fun_l11_n12 +end + +def fun_l10_n536() + fun_l11_n138 +end + +def fun_l10_n537() + fun_l11_n247 +end + +def fun_l10_n538() + fun_l11_n469 +end + +def fun_l10_n539() + fun_l11_n574 +end + +def fun_l10_n540() + fun_l11_n474 +end + +def fun_l10_n541() + fun_l11_n639 +end + +def fun_l10_n542() + fun_l11_n932 +end + +def fun_l10_n543() + fun_l11_n587 +end + +def fun_l10_n544() + fun_l11_n502 +end + +def fun_l10_n545() + fun_l11_n134 +end + +def fun_l10_n546() + fun_l11_n470 +end + +def fun_l10_n547() + fun_l11_n118 +end + +def fun_l10_n548() + fun_l11_n253 +end + +def fun_l10_n549() + fun_l11_n331 +end + +def fun_l10_n550() + fun_l11_n461 +end + +def fun_l10_n551() + fun_l11_n807 +end + +def fun_l10_n552() + fun_l11_n266 +end + +def fun_l10_n553() + fun_l11_n537 +end + +def fun_l10_n554() + fun_l11_n649 +end + +def fun_l10_n555() + fun_l11_n620 +end + +def fun_l10_n556() + fun_l11_n646 +end + +def fun_l10_n557() + fun_l11_n972 +end + +def fun_l10_n558() + fun_l11_n311 +end + +def fun_l10_n559() + fun_l11_n555 +end + +def fun_l10_n560() + fun_l11_n930 +end + +def fun_l10_n561() + fun_l11_n249 +end + +def fun_l10_n562() + fun_l11_n270 +end + +def fun_l10_n563() + fun_l11_n769 +end + +def fun_l10_n564() + fun_l11_n281 +end + +def fun_l10_n565() + fun_l11_n213 +end + +def fun_l10_n566() + fun_l11_n849 +end + +def fun_l10_n567() + fun_l11_n665 +end + +def fun_l10_n568() + fun_l11_n339 +end + +def fun_l10_n569() + fun_l11_n476 +end + +def fun_l10_n570() + fun_l11_n732 +end + +def fun_l10_n571() + fun_l11_n266 +end + +def fun_l10_n572() + fun_l11_n85 +end + +def fun_l10_n573() + fun_l11_n260 +end + +def fun_l10_n574() + fun_l11_n275 +end + +def fun_l10_n575() + fun_l11_n673 +end + +def fun_l10_n576() + fun_l11_n252 +end + +def fun_l10_n577() + fun_l11_n376 +end + +def fun_l10_n578() + fun_l11_n407 +end + +def fun_l10_n579() + fun_l11_n134 +end + +def fun_l10_n580() + fun_l11_n825 +end + +def fun_l10_n581() + fun_l11_n266 +end + +def fun_l10_n582() + fun_l11_n40 +end + +def fun_l10_n583() + fun_l11_n346 +end + +def fun_l10_n584() + fun_l11_n503 +end + +def fun_l10_n585() + fun_l11_n743 +end + +def fun_l10_n586() + fun_l11_n199 +end + +def fun_l10_n587() + fun_l11_n268 +end + +def fun_l10_n588() + fun_l11_n6 +end + +def fun_l10_n589() + fun_l11_n859 +end + +def fun_l10_n590() + fun_l11_n499 +end + +def fun_l10_n591() + fun_l11_n397 +end + +def fun_l10_n592() + fun_l11_n580 +end + +def fun_l10_n593() + fun_l11_n299 +end + +def fun_l10_n594() + fun_l11_n691 +end + +def fun_l10_n595() + fun_l11_n973 +end + +def fun_l10_n596() + fun_l11_n987 +end + +def fun_l10_n597() + fun_l11_n342 +end + +def fun_l10_n598() + fun_l11_n556 +end + +def fun_l10_n599() + fun_l11_n754 +end + +def fun_l10_n600() + fun_l11_n54 +end + +def fun_l10_n601() + fun_l11_n334 +end + +def fun_l10_n602() + fun_l11_n6 +end + +def fun_l10_n603() + fun_l11_n574 +end + +def fun_l10_n604() + fun_l11_n615 +end + +def fun_l10_n605() + fun_l11_n314 +end + +def fun_l10_n606() + fun_l11_n659 +end + +def fun_l10_n607() + fun_l11_n41 +end + +def fun_l10_n608() + fun_l11_n119 +end + +def fun_l10_n609() + fun_l11_n204 +end + +def fun_l10_n610() + fun_l11_n952 +end + +def fun_l10_n611() + fun_l11_n587 +end + +def fun_l10_n612() + fun_l11_n87 +end + +def fun_l10_n613() + fun_l11_n840 +end + +def fun_l10_n614() + fun_l11_n520 +end + +def fun_l10_n615() + fun_l11_n814 +end + +def fun_l10_n616() + fun_l11_n595 +end + +def fun_l10_n617() + fun_l11_n765 +end + +def fun_l10_n618() + fun_l11_n383 +end + +def fun_l10_n619() + fun_l11_n277 +end + +def fun_l10_n620() + fun_l11_n897 +end + +def fun_l10_n621() + fun_l11_n131 +end + +def fun_l10_n622() + fun_l11_n674 +end + +def fun_l10_n623() + fun_l11_n971 +end + +def fun_l10_n624() + fun_l11_n503 +end + +def fun_l10_n625() + fun_l11_n471 +end + +def fun_l10_n626() + fun_l11_n805 +end + +def fun_l10_n627() + fun_l11_n58 +end + +def fun_l10_n628() + fun_l11_n784 +end + +def fun_l10_n629() + fun_l11_n222 +end + +def fun_l10_n630() + fun_l11_n382 +end + +def fun_l10_n631() + fun_l11_n239 +end + +def fun_l10_n632() + fun_l11_n53 +end + +def fun_l10_n633() + fun_l11_n730 +end + +def fun_l10_n634() + fun_l11_n522 +end + +def fun_l10_n635() + fun_l11_n182 +end + +def fun_l10_n636() + fun_l11_n837 +end + +def fun_l10_n637() + fun_l11_n815 +end + +def fun_l10_n638() + fun_l11_n754 +end + +def fun_l10_n639() + fun_l11_n74 +end + +def fun_l10_n640() + fun_l11_n695 +end + +def fun_l10_n641() + fun_l11_n454 +end + +def fun_l10_n642() + fun_l11_n250 +end + +def fun_l10_n643() + fun_l11_n385 +end + +def fun_l10_n644() + fun_l11_n115 +end + +def fun_l10_n645() + fun_l11_n624 +end + +def fun_l10_n646() + fun_l11_n697 +end + +def fun_l10_n647() + fun_l11_n184 +end + +def fun_l10_n648() + fun_l11_n921 +end + +def fun_l10_n649() + fun_l11_n699 +end + +def fun_l10_n650() + fun_l11_n952 +end + +def fun_l10_n651() + fun_l11_n879 +end + +def fun_l10_n652() + fun_l11_n569 +end + +def fun_l10_n653() + fun_l11_n85 +end + +def fun_l10_n654() + fun_l11_n316 +end + +def fun_l10_n655() + fun_l11_n203 +end + +def fun_l10_n656() + fun_l11_n424 +end + +def fun_l10_n657() + fun_l11_n731 +end + +def fun_l10_n658() + fun_l11_n65 +end + +def fun_l10_n659() + fun_l11_n232 +end + +def fun_l10_n660() + fun_l11_n306 +end + +def fun_l10_n661() + fun_l11_n71 +end + +def fun_l10_n662() + fun_l11_n577 +end + +def fun_l10_n663() + fun_l11_n670 +end + +def fun_l10_n664() + fun_l11_n905 +end + +def fun_l10_n665() + fun_l11_n717 +end + +def fun_l10_n666() + fun_l11_n198 +end + +def fun_l10_n667() + fun_l11_n982 +end + +def fun_l10_n668() + fun_l11_n933 +end + +def fun_l10_n669() + fun_l11_n446 +end + +def fun_l10_n670() + fun_l11_n913 +end + +def fun_l10_n671() + fun_l11_n794 +end + +def fun_l10_n672() + fun_l11_n604 +end + +def fun_l10_n673() + fun_l11_n408 +end + +def fun_l10_n674() + fun_l11_n297 +end + +def fun_l10_n675() + fun_l11_n113 +end + +def fun_l10_n676() + fun_l11_n197 +end + +def fun_l10_n677() + fun_l11_n606 +end + +def fun_l10_n678() + fun_l11_n333 +end + +def fun_l10_n679() + fun_l11_n130 +end + +def fun_l10_n680() + fun_l11_n893 +end + +def fun_l10_n681() + fun_l11_n997 +end + +def fun_l10_n682() + fun_l11_n826 +end + +def fun_l10_n683() + fun_l11_n889 +end + +def fun_l10_n684() + fun_l11_n887 +end + +def fun_l10_n685() + fun_l11_n913 +end + +def fun_l10_n686() + fun_l11_n563 +end + +def fun_l10_n687() + fun_l11_n112 +end + +def fun_l10_n688() + fun_l11_n527 +end + +def fun_l10_n689() + fun_l11_n423 +end + +def fun_l10_n690() + fun_l11_n906 +end + +def fun_l10_n691() + fun_l11_n134 +end + +def fun_l10_n692() + fun_l11_n549 +end + +def fun_l10_n693() + fun_l11_n864 +end + +def fun_l10_n694() + fun_l11_n750 +end + +def fun_l10_n695() + fun_l11_n357 +end + +def fun_l10_n696() + fun_l11_n79 +end + +def fun_l10_n697() + fun_l11_n99 +end + +def fun_l10_n698() + fun_l11_n638 +end + +def fun_l10_n699() + fun_l11_n946 +end + +def fun_l10_n700() + fun_l11_n498 +end + +def fun_l10_n701() + fun_l11_n490 +end + +def fun_l10_n702() + fun_l11_n860 +end + +def fun_l10_n703() + fun_l11_n194 +end + +def fun_l10_n704() + fun_l11_n130 +end + +def fun_l10_n705() + fun_l11_n647 +end + +def fun_l10_n706() + fun_l11_n162 +end + +def fun_l10_n707() + fun_l11_n41 +end + +def fun_l10_n708() + fun_l11_n583 +end + +def fun_l10_n709() + fun_l11_n687 +end + +def fun_l10_n710() + fun_l11_n83 +end + +def fun_l10_n711() + fun_l11_n365 +end + +def fun_l10_n712() + fun_l11_n797 +end + +def fun_l10_n713() + fun_l11_n730 +end + +def fun_l10_n714() + fun_l11_n844 +end + +def fun_l10_n715() + fun_l11_n514 +end + +def fun_l10_n716() + fun_l11_n212 +end + +def fun_l10_n717() + fun_l11_n600 +end + +def fun_l10_n718() + fun_l11_n823 +end + +def fun_l10_n719() + fun_l11_n439 +end + +def fun_l10_n720() + fun_l11_n361 +end + +def fun_l10_n721() + fun_l11_n390 +end + +def fun_l10_n722() + fun_l11_n10 +end + +def fun_l10_n723() + fun_l11_n984 +end + +def fun_l10_n724() + fun_l11_n193 +end + +def fun_l10_n725() + fun_l11_n584 +end + +def fun_l10_n726() + fun_l11_n552 +end + +def fun_l10_n727() + fun_l11_n795 +end + +def fun_l10_n728() + fun_l11_n958 +end + +def fun_l10_n729() + fun_l11_n408 +end + +def fun_l10_n730() + fun_l11_n584 +end + +def fun_l10_n731() + fun_l11_n707 +end + +def fun_l10_n732() + fun_l11_n291 +end + +def fun_l10_n733() + fun_l11_n777 +end + +def fun_l10_n734() + fun_l11_n634 +end + +def fun_l10_n735() + fun_l11_n716 +end + +def fun_l10_n736() + fun_l11_n167 +end + +def fun_l10_n737() + fun_l11_n119 +end + +def fun_l10_n738() + fun_l11_n835 +end + +def fun_l10_n739() + fun_l11_n53 +end + +def fun_l10_n740() + fun_l11_n743 +end + +def fun_l10_n741() + fun_l11_n564 +end + +def fun_l10_n742() + fun_l11_n917 +end + +def fun_l10_n743() + fun_l11_n848 +end + +def fun_l10_n744() + fun_l11_n135 +end + +def fun_l10_n745() + fun_l11_n159 +end + +def fun_l10_n746() + fun_l11_n374 +end + +def fun_l10_n747() + fun_l11_n885 +end + +def fun_l10_n748() + fun_l11_n0 +end + +def fun_l10_n749() + fun_l11_n735 +end + +def fun_l10_n750() + fun_l11_n995 +end + +def fun_l10_n751() + fun_l11_n522 +end + +def fun_l10_n752() + fun_l11_n166 +end + +def fun_l10_n753() + fun_l11_n191 +end + +def fun_l10_n754() + fun_l11_n820 +end + +def fun_l10_n755() + fun_l11_n180 +end + +def fun_l10_n756() + fun_l11_n480 +end + +def fun_l10_n757() + fun_l11_n107 +end + +def fun_l10_n758() + fun_l11_n263 +end + +def fun_l10_n759() + fun_l11_n534 +end + +def fun_l10_n760() + fun_l11_n442 +end + +def fun_l10_n761() + fun_l11_n719 +end + +def fun_l10_n762() + fun_l11_n778 +end + +def fun_l10_n763() + fun_l11_n297 +end + +def fun_l10_n764() + fun_l11_n582 +end + +def fun_l10_n765() + fun_l11_n230 +end + +def fun_l10_n766() + fun_l11_n921 +end + +def fun_l10_n767() + fun_l11_n629 +end + +def fun_l10_n768() + fun_l11_n473 +end + +def fun_l10_n769() + fun_l11_n563 +end + +def fun_l10_n770() + fun_l11_n61 +end + +def fun_l10_n771() + fun_l11_n343 +end + +def fun_l10_n772() + fun_l11_n713 +end + +def fun_l10_n773() + fun_l11_n724 +end + +def fun_l10_n774() + fun_l11_n454 +end + +def fun_l10_n775() + fun_l11_n680 +end + +def fun_l10_n776() + fun_l11_n620 +end + +def fun_l10_n777() + fun_l11_n949 +end + +def fun_l10_n778() + fun_l11_n208 +end + +def fun_l10_n779() + fun_l11_n904 +end + +def fun_l10_n780() + fun_l11_n88 +end + +def fun_l10_n781() + fun_l11_n710 +end + +def fun_l10_n782() + fun_l11_n875 +end + +def fun_l10_n783() + fun_l11_n970 +end + +def fun_l10_n784() + fun_l11_n123 +end + +def fun_l10_n785() + fun_l11_n420 +end + +def fun_l10_n786() + fun_l11_n122 +end + +def fun_l10_n787() + fun_l11_n200 +end + +def fun_l10_n788() + fun_l11_n716 +end + +def fun_l10_n789() + fun_l11_n592 +end + +def fun_l10_n790() + fun_l11_n159 +end + +def fun_l10_n791() + fun_l11_n852 +end + +def fun_l10_n792() + fun_l11_n913 +end + +def fun_l10_n793() + fun_l11_n305 +end + +def fun_l10_n794() + fun_l11_n123 +end + +def fun_l10_n795() + fun_l11_n210 +end + +def fun_l10_n796() + fun_l11_n416 +end + +def fun_l10_n797() + fun_l11_n800 +end + +def fun_l10_n798() + fun_l11_n689 +end + +def fun_l10_n799() + fun_l11_n358 +end + +def fun_l10_n800() + fun_l11_n542 +end + +def fun_l10_n801() + fun_l11_n715 +end + +def fun_l10_n802() + fun_l11_n879 +end + +def fun_l10_n803() + fun_l11_n414 +end + +def fun_l10_n804() + fun_l11_n623 +end + +def fun_l10_n805() + fun_l11_n282 +end + +def fun_l10_n806() + fun_l11_n719 +end + +def fun_l10_n807() + fun_l11_n111 +end + +def fun_l10_n808() + fun_l11_n348 +end + +def fun_l10_n809() + fun_l11_n836 +end + +def fun_l10_n810() + fun_l11_n878 +end + +def fun_l10_n811() + fun_l11_n569 +end + +def fun_l10_n812() + fun_l11_n701 +end + +def fun_l10_n813() + fun_l11_n602 +end + +def fun_l10_n814() + fun_l11_n746 +end + +def fun_l10_n815() + fun_l11_n892 +end + +def fun_l10_n816() + fun_l11_n150 +end + +def fun_l10_n817() + fun_l11_n804 +end + +def fun_l10_n818() + fun_l11_n459 +end + +def fun_l10_n819() + fun_l11_n932 +end + +def fun_l10_n820() + fun_l11_n492 +end + +def fun_l10_n821() + fun_l11_n351 +end + +def fun_l10_n822() + fun_l11_n933 +end + +def fun_l10_n823() + fun_l11_n328 +end + +def fun_l10_n824() + fun_l11_n75 +end + +def fun_l10_n825() + fun_l11_n935 +end + +def fun_l10_n826() + fun_l11_n495 +end + +def fun_l10_n827() + fun_l11_n328 +end + +def fun_l10_n828() + fun_l11_n888 +end + +def fun_l10_n829() + fun_l11_n547 +end + +def fun_l10_n830() + fun_l11_n315 +end + +def fun_l10_n831() + fun_l11_n243 +end + +def fun_l10_n832() + fun_l11_n972 +end + +def fun_l10_n833() + fun_l11_n33 +end + +def fun_l10_n834() + fun_l11_n765 +end + +def fun_l10_n835() + fun_l11_n614 +end + +def fun_l10_n836() + fun_l11_n686 +end + +def fun_l10_n837() + fun_l11_n373 +end + +def fun_l10_n838() + fun_l11_n534 +end + +def fun_l10_n839() + fun_l11_n375 +end + +def fun_l10_n840() + fun_l11_n297 +end + +def fun_l10_n841() + fun_l11_n107 +end + +def fun_l10_n842() + fun_l11_n409 +end + +def fun_l10_n843() + fun_l11_n24 +end + +def fun_l10_n844() + fun_l11_n43 +end + +def fun_l10_n845() + fun_l11_n93 +end + +def fun_l10_n846() + fun_l11_n667 +end + +def fun_l10_n847() + fun_l11_n520 +end + +def fun_l10_n848() + fun_l11_n109 +end + +def fun_l10_n849() + fun_l11_n829 +end + +def fun_l10_n850() + fun_l11_n946 +end + +def fun_l10_n851() + fun_l11_n232 +end + +def fun_l10_n852() + fun_l11_n568 +end + +def fun_l10_n853() + fun_l11_n589 +end + +def fun_l10_n854() + fun_l11_n76 +end + +def fun_l10_n855() + fun_l11_n106 +end + +def fun_l10_n856() + fun_l11_n46 +end + +def fun_l10_n857() + fun_l11_n261 +end + +def fun_l10_n858() + fun_l11_n788 +end + +def fun_l10_n859() + fun_l11_n289 +end + +def fun_l10_n860() + fun_l11_n269 +end + +def fun_l10_n861() + fun_l11_n669 +end + +def fun_l10_n862() + fun_l11_n925 +end + +def fun_l10_n863() + fun_l11_n782 +end + +def fun_l10_n864() + fun_l11_n432 +end + +def fun_l10_n865() + fun_l11_n278 +end + +def fun_l10_n866() + fun_l11_n380 +end + +def fun_l10_n867() + fun_l11_n488 +end + +def fun_l10_n868() + fun_l11_n718 +end + +def fun_l10_n869() + fun_l11_n569 +end + +def fun_l10_n870() + fun_l11_n59 +end + +def fun_l10_n871() + fun_l11_n581 +end + +def fun_l10_n872() + fun_l11_n128 +end + +def fun_l10_n873() + fun_l11_n200 +end + +def fun_l10_n874() + fun_l11_n258 +end + +def fun_l10_n875() + fun_l11_n869 +end + +def fun_l10_n876() + fun_l11_n337 +end + +def fun_l10_n877() + fun_l11_n11 +end + +def fun_l10_n878() + fun_l11_n968 +end + +def fun_l10_n879() + fun_l11_n188 +end + +def fun_l10_n880() + fun_l11_n361 +end + +def fun_l10_n881() + fun_l11_n268 +end + +def fun_l10_n882() + fun_l11_n518 +end + +def fun_l10_n883() + fun_l11_n253 +end + +def fun_l10_n884() + fun_l11_n159 +end + +def fun_l10_n885() + fun_l11_n977 +end + +def fun_l10_n886() + fun_l11_n602 +end + +def fun_l10_n887() + fun_l11_n957 +end + +def fun_l10_n888() + fun_l11_n53 +end + +def fun_l10_n889() + fun_l11_n680 +end + +def fun_l10_n890() + fun_l11_n6 +end + +def fun_l10_n891() + fun_l11_n202 +end + +def fun_l10_n892() + fun_l11_n25 +end + +def fun_l10_n893() + fun_l11_n857 +end + +def fun_l10_n894() + fun_l11_n505 +end + +def fun_l10_n895() + fun_l11_n966 +end + +def fun_l10_n896() + fun_l11_n381 +end + +def fun_l10_n897() + fun_l11_n811 +end + +def fun_l10_n898() + fun_l11_n863 +end + +def fun_l10_n899() + fun_l11_n902 +end + +def fun_l10_n900() + fun_l11_n711 +end + +def fun_l10_n901() + fun_l11_n42 +end + +def fun_l10_n902() + fun_l11_n324 +end + +def fun_l10_n903() + fun_l11_n729 +end + +def fun_l10_n904() + fun_l11_n535 +end + +def fun_l10_n905() + fun_l11_n427 +end + +def fun_l10_n906() + fun_l11_n469 +end + +def fun_l10_n907() + fun_l11_n887 +end + +def fun_l10_n908() + fun_l11_n822 +end + +def fun_l10_n909() + fun_l11_n567 +end + +def fun_l10_n910() + fun_l11_n2 +end + +def fun_l10_n911() + fun_l11_n957 +end + +def fun_l10_n912() + fun_l11_n850 +end + +def fun_l10_n913() + fun_l11_n146 +end + +def fun_l10_n914() + fun_l11_n318 +end + +def fun_l10_n915() + fun_l11_n452 +end + +def fun_l10_n916() + fun_l11_n366 +end + +def fun_l10_n917() + fun_l11_n126 +end + +def fun_l10_n918() + fun_l11_n56 +end + +def fun_l10_n919() + fun_l11_n742 +end + +def fun_l10_n920() + fun_l11_n1 +end + +def fun_l10_n921() + fun_l11_n778 +end + +def fun_l10_n922() + fun_l11_n703 +end + +def fun_l10_n923() + fun_l11_n622 +end + +def fun_l10_n924() + fun_l11_n942 +end + +def fun_l10_n925() + fun_l11_n909 +end + +def fun_l10_n926() + fun_l11_n98 +end + +def fun_l10_n927() + fun_l11_n518 +end + +def fun_l10_n928() + fun_l11_n932 +end + +def fun_l10_n929() + fun_l11_n768 +end + +def fun_l10_n930() + fun_l11_n846 +end + +def fun_l10_n931() + fun_l11_n231 +end + +def fun_l10_n932() + fun_l11_n944 +end + +def fun_l10_n933() + fun_l11_n561 +end + +def fun_l10_n934() + fun_l11_n587 +end + +def fun_l10_n935() + fun_l11_n372 +end + +def fun_l10_n936() + fun_l11_n322 +end + +def fun_l10_n937() + fun_l11_n416 +end + +def fun_l10_n938() + fun_l11_n191 +end + +def fun_l10_n939() + fun_l11_n915 +end + +def fun_l10_n940() + fun_l11_n215 +end + +def fun_l10_n941() + fun_l11_n271 +end + +def fun_l10_n942() + fun_l11_n890 +end + +def fun_l10_n943() + fun_l11_n914 +end + +def fun_l10_n944() + fun_l11_n313 +end + +def fun_l10_n945() + fun_l11_n705 +end + +def fun_l10_n946() + fun_l11_n725 +end + +def fun_l10_n947() + fun_l11_n46 +end + +def fun_l10_n948() + fun_l11_n793 +end + +def fun_l10_n949() + fun_l11_n986 +end + +def fun_l10_n950() + fun_l11_n607 +end + +def fun_l10_n951() + fun_l11_n429 +end + +def fun_l10_n952() + fun_l11_n251 +end + +def fun_l10_n953() + fun_l11_n264 +end + +def fun_l10_n954() + fun_l11_n677 +end + +def fun_l10_n955() + fun_l11_n616 +end + +def fun_l10_n956() + fun_l11_n264 +end + +def fun_l10_n957() + fun_l11_n188 +end + +def fun_l10_n958() + fun_l11_n834 +end + +def fun_l10_n959() + fun_l11_n231 +end + +def fun_l10_n960() + fun_l11_n584 +end + +def fun_l10_n961() + fun_l11_n153 +end + +def fun_l10_n962() + fun_l11_n215 +end + +def fun_l10_n963() + fun_l11_n902 +end + +def fun_l10_n964() + fun_l11_n600 +end + +def fun_l10_n965() + fun_l11_n113 +end + +def fun_l10_n966() + fun_l11_n264 +end + +def fun_l10_n967() + fun_l11_n92 +end + +def fun_l10_n968() + fun_l11_n346 +end + +def fun_l10_n969() + fun_l11_n531 +end + +def fun_l10_n970() + fun_l11_n134 +end + +def fun_l10_n971() + fun_l11_n883 +end + +def fun_l10_n972() + fun_l11_n662 +end + +def fun_l10_n973() + fun_l11_n836 +end + +def fun_l10_n974() + fun_l11_n418 +end + +def fun_l10_n975() + fun_l11_n384 +end + +def fun_l10_n976() + fun_l11_n57 +end + +def fun_l10_n977() + fun_l11_n827 +end + +def fun_l10_n978() + fun_l11_n114 +end + +def fun_l10_n979() + fun_l11_n720 +end + +def fun_l10_n980() + fun_l11_n328 +end + +def fun_l10_n981() + fun_l11_n597 +end + +def fun_l10_n982() + fun_l11_n941 +end + +def fun_l10_n983() + fun_l11_n848 +end + +def fun_l10_n984() + fun_l11_n269 +end + +def fun_l10_n985() + fun_l11_n666 +end + +def fun_l10_n986() + fun_l11_n538 +end + +def fun_l10_n987() + fun_l11_n755 +end + +def fun_l10_n988() + fun_l11_n747 +end + +def fun_l10_n989() + fun_l11_n100 +end + +def fun_l10_n990() + fun_l11_n995 +end + +def fun_l10_n991() + fun_l11_n904 +end + +def fun_l10_n992() + fun_l11_n948 +end + +def fun_l10_n993() + fun_l11_n135 +end + +def fun_l10_n994() + fun_l11_n120 +end + +def fun_l10_n995() + fun_l11_n156 +end + +def fun_l10_n996() + fun_l11_n264 +end + +def fun_l10_n997() + fun_l11_n522 +end + +def fun_l10_n998() + fun_l11_n105 +end + +def fun_l10_n999() + fun_l11_n919 +end + +def fun_l11_n0() + fun_l12_n731 +end + +def fun_l11_n1() + fun_l12_n521 +end + +def fun_l11_n2() + fun_l12_n875 +end + +def fun_l11_n3() + fun_l12_n806 +end + +def fun_l11_n4() + fun_l12_n211 +end + +def fun_l11_n5() + fun_l12_n965 +end + +def fun_l11_n6() + fun_l12_n770 +end + +def fun_l11_n7() + fun_l12_n440 +end + +def fun_l11_n8() + fun_l12_n900 +end + +def fun_l11_n9() + fun_l12_n581 +end + +def fun_l11_n10() + fun_l12_n427 +end + +def fun_l11_n11() + fun_l12_n156 +end + +def fun_l11_n12() + fun_l12_n941 +end + +def fun_l11_n13() + fun_l12_n711 +end + +def fun_l11_n14() + fun_l12_n69 +end + +def fun_l11_n15() + fun_l12_n665 +end + +def fun_l11_n16() + fun_l12_n325 +end + +def fun_l11_n17() + fun_l12_n120 +end + +def fun_l11_n18() + fun_l12_n455 +end + +def fun_l11_n19() + fun_l12_n14 +end + +def fun_l11_n20() + fun_l12_n909 +end + +def fun_l11_n21() + fun_l12_n297 +end + +def fun_l11_n22() + fun_l12_n81 +end + +def fun_l11_n23() + fun_l12_n420 +end + +def fun_l11_n24() + fun_l12_n439 +end + +def fun_l11_n25() + fun_l12_n867 +end + +def fun_l11_n26() + fun_l12_n147 +end + +def fun_l11_n27() + fun_l12_n422 +end + +def fun_l11_n28() + fun_l12_n338 +end + +def fun_l11_n29() + fun_l12_n730 +end + +def fun_l11_n30() + fun_l12_n15 +end + +def fun_l11_n31() + fun_l12_n276 +end + +def fun_l11_n32() + fun_l12_n298 +end + +def fun_l11_n33() + fun_l12_n749 +end + +def fun_l11_n34() + fun_l12_n255 +end + +def fun_l11_n35() + fun_l12_n104 +end + +def fun_l11_n36() + fun_l12_n91 +end + +def fun_l11_n37() + fun_l12_n825 +end + +def fun_l11_n38() + fun_l12_n983 +end + +def fun_l11_n39() + fun_l12_n711 +end + +def fun_l11_n40() + fun_l12_n991 +end + +def fun_l11_n41() + fun_l12_n143 +end + +def fun_l11_n42() + fun_l12_n579 +end + +def fun_l11_n43() + fun_l12_n217 +end + +def fun_l11_n44() + fun_l12_n353 +end + +def fun_l11_n45() + fun_l12_n849 +end + +def fun_l11_n46() + fun_l12_n452 +end + +def fun_l11_n47() + fun_l12_n982 +end + +def fun_l11_n48() + fun_l12_n201 +end + +def fun_l11_n49() + fun_l12_n289 +end + +def fun_l11_n50() + fun_l12_n419 +end + +def fun_l11_n51() + fun_l12_n490 +end + +def fun_l11_n52() + fun_l12_n969 +end + +def fun_l11_n53() + fun_l12_n721 +end + +def fun_l11_n54() + fun_l12_n657 +end + +def fun_l11_n55() + fun_l12_n498 +end + +def fun_l11_n56() + fun_l12_n44 +end + +def fun_l11_n57() + fun_l12_n863 +end + +def fun_l11_n58() + fun_l12_n366 +end + +def fun_l11_n59() + fun_l12_n515 +end + +def fun_l11_n60() + fun_l12_n302 +end + +def fun_l11_n61() + fun_l12_n717 +end + +def fun_l11_n62() + fun_l12_n165 +end + +def fun_l11_n63() + fun_l12_n980 +end + +def fun_l11_n64() + fun_l12_n988 +end + +def fun_l11_n65() + fun_l12_n397 +end + +def fun_l11_n66() + fun_l12_n648 +end + +def fun_l11_n67() + fun_l12_n8 +end + +def fun_l11_n68() + fun_l12_n164 +end + +def fun_l11_n69() + fun_l12_n999 +end + +def fun_l11_n70() + fun_l12_n434 +end + +def fun_l11_n71() + fun_l12_n991 +end + +def fun_l11_n72() + fun_l12_n596 +end + +def fun_l11_n73() + fun_l12_n533 +end + +def fun_l11_n74() + fun_l12_n222 +end + +def fun_l11_n75() + fun_l12_n817 +end + +def fun_l11_n76() + fun_l12_n740 +end + +def fun_l11_n77() + fun_l12_n638 +end + +def fun_l11_n78() + fun_l12_n81 +end + +def fun_l11_n79() + fun_l12_n702 +end + +def fun_l11_n80() + fun_l12_n783 +end + +def fun_l11_n81() + fun_l12_n228 +end + +def fun_l11_n82() + fun_l12_n487 +end + +def fun_l11_n83() + fun_l12_n59 +end + +def fun_l11_n84() + fun_l12_n910 +end + +def fun_l11_n85() + fun_l12_n581 +end + +def fun_l11_n86() + fun_l12_n947 +end + +def fun_l11_n87() + fun_l12_n645 +end + +def fun_l11_n88() + fun_l12_n505 +end + +def fun_l11_n89() + fun_l12_n171 +end + +def fun_l11_n90() + fun_l12_n713 +end + +def fun_l11_n91() + fun_l12_n414 +end + +def fun_l11_n92() + fun_l12_n427 +end + +def fun_l11_n93() + fun_l12_n225 +end + +def fun_l11_n94() + fun_l12_n655 +end + +def fun_l11_n95() + fun_l12_n437 +end + +def fun_l11_n96() + fun_l12_n879 +end + +def fun_l11_n97() + fun_l12_n222 +end + +def fun_l11_n98() + fun_l12_n642 +end + +def fun_l11_n99() + fun_l12_n142 +end + +def fun_l11_n100() + fun_l12_n612 +end + +def fun_l11_n101() + fun_l12_n548 +end + +def fun_l11_n102() + fun_l12_n535 +end + +def fun_l11_n103() + fun_l12_n245 +end + +def fun_l11_n104() + fun_l12_n0 +end + +def fun_l11_n105() + fun_l12_n305 +end + +def fun_l11_n106() + fun_l12_n674 +end + +def fun_l11_n107() + fun_l12_n626 +end + +def fun_l11_n108() + fun_l12_n335 +end + +def fun_l11_n109() + fun_l12_n963 +end + +def fun_l11_n110() + fun_l12_n958 +end + +def fun_l11_n111() + fun_l12_n32 +end + +def fun_l11_n112() + fun_l12_n149 +end + +def fun_l11_n113() + fun_l12_n923 +end + +def fun_l11_n114() + fun_l12_n853 +end + +def fun_l11_n115() + fun_l12_n793 +end + +def fun_l11_n116() + fun_l12_n354 +end + +def fun_l11_n117() + fun_l12_n839 +end + +def fun_l11_n118() + fun_l12_n995 +end + +def fun_l11_n119() + fun_l12_n610 +end + +def fun_l11_n120() + fun_l12_n147 +end + +def fun_l11_n121() + fun_l12_n191 +end + +def fun_l11_n122() + fun_l12_n237 +end + +def fun_l11_n123() + fun_l12_n766 +end + +def fun_l11_n124() + fun_l12_n830 +end + +def fun_l11_n125() + fun_l12_n968 +end + +def fun_l11_n126() + fun_l12_n163 +end + +def fun_l11_n127() + fun_l12_n357 +end + +def fun_l11_n128() + fun_l12_n741 +end + +def fun_l11_n129() + fun_l12_n502 +end + +def fun_l11_n130() + fun_l12_n569 +end + +def fun_l11_n131() + fun_l12_n696 +end + +def fun_l11_n132() + fun_l12_n326 +end + +def fun_l11_n133() + fun_l12_n765 +end + +def fun_l11_n134() + fun_l12_n126 +end + +def fun_l11_n135() + fun_l12_n107 +end + +def fun_l11_n136() + fun_l12_n8 +end + +def fun_l11_n137() + fun_l12_n969 +end + +def fun_l11_n138() + fun_l12_n49 +end + +def fun_l11_n139() + fun_l12_n65 +end + +def fun_l11_n140() + fun_l12_n631 +end + +def fun_l11_n141() + fun_l12_n984 +end + +def fun_l11_n142() + fun_l12_n520 +end + +def fun_l11_n143() + fun_l12_n348 +end + +def fun_l11_n144() + fun_l12_n51 +end + +def fun_l11_n145() + fun_l12_n756 +end + +def fun_l11_n146() + fun_l12_n981 +end + +def fun_l11_n147() + fun_l12_n671 +end + +def fun_l11_n148() + fun_l12_n4 +end + +def fun_l11_n149() + fun_l12_n66 +end + +def fun_l11_n150() + fun_l12_n445 +end + +def fun_l11_n151() + fun_l12_n131 +end + +def fun_l11_n152() + fun_l12_n927 +end + +def fun_l11_n153() + fun_l12_n715 +end + +def fun_l11_n154() + fun_l12_n767 +end + +def fun_l11_n155() + fun_l12_n50 +end + +def fun_l11_n156() + fun_l12_n360 +end + +def fun_l11_n157() + fun_l12_n311 +end + +def fun_l11_n158() + fun_l12_n509 +end + +def fun_l11_n159() + fun_l12_n868 +end + +def fun_l11_n160() + fun_l12_n185 +end + +def fun_l11_n161() + fun_l12_n338 +end + +def fun_l11_n162() + fun_l12_n539 +end + +def fun_l11_n163() + fun_l12_n30 +end + +def fun_l11_n164() + fun_l12_n485 +end + +def fun_l11_n165() + fun_l12_n808 +end + +def fun_l11_n166() + fun_l12_n78 +end + +def fun_l11_n167() + fun_l12_n370 +end + +def fun_l11_n168() + fun_l12_n1 +end + +def fun_l11_n169() + fun_l12_n473 +end + +def fun_l11_n170() + fun_l12_n362 +end + +def fun_l11_n171() + fun_l12_n209 +end + +def fun_l11_n172() + fun_l12_n431 +end + +def fun_l11_n173() + fun_l12_n383 +end + +def fun_l11_n174() + fun_l12_n214 +end + +def fun_l11_n175() + fun_l12_n215 +end + +def fun_l11_n176() + fun_l12_n639 +end + +def fun_l11_n177() + fun_l12_n486 +end + +def fun_l11_n178() + fun_l12_n486 +end + +def fun_l11_n179() + fun_l12_n409 +end + +def fun_l11_n180() + fun_l12_n558 +end + +def fun_l11_n181() + fun_l12_n546 +end + +def fun_l11_n182() + fun_l12_n439 +end + +def fun_l11_n183() + fun_l12_n11 +end + +def fun_l11_n184() + fun_l12_n304 +end + +def fun_l11_n185() + fun_l12_n525 +end + +def fun_l11_n186() + fun_l12_n886 +end + +def fun_l11_n187() + fun_l12_n17 +end + +def fun_l11_n188() + fun_l12_n11 +end + +def fun_l11_n189() + fun_l12_n382 +end + +def fun_l11_n190() + fun_l12_n185 +end + +def fun_l11_n191() + fun_l12_n454 +end + +def fun_l11_n192() + fun_l12_n23 +end + +def fun_l11_n193() + fun_l12_n900 +end + +def fun_l11_n194() + fun_l12_n233 +end + +def fun_l11_n195() + fun_l12_n245 +end + +def fun_l11_n196() + fun_l12_n474 +end + +def fun_l11_n197() + fun_l12_n368 +end + +def fun_l11_n198() + fun_l12_n80 +end + +def fun_l11_n199() + fun_l12_n522 +end + +def fun_l11_n200() + fun_l12_n439 +end + +def fun_l11_n201() + fun_l12_n553 +end + +def fun_l11_n202() + fun_l12_n713 +end + +def fun_l11_n203() + fun_l12_n898 +end + +def fun_l11_n204() + fun_l12_n571 +end + +def fun_l11_n205() + fun_l12_n830 +end + +def fun_l11_n206() + fun_l12_n404 +end + +def fun_l11_n207() + fun_l12_n120 +end + +def fun_l11_n208() + fun_l12_n147 +end + +def fun_l11_n209() + fun_l12_n924 +end + +def fun_l11_n210() + fun_l12_n988 +end + +def fun_l11_n211() + fun_l12_n25 +end + +def fun_l11_n212() + fun_l12_n848 +end + +def fun_l11_n213() + fun_l12_n875 +end + +def fun_l11_n214() + fun_l12_n718 +end + +def fun_l11_n215() + fun_l12_n657 +end + +def fun_l11_n216() + fun_l12_n364 +end + +def fun_l11_n217() + fun_l12_n342 +end + +def fun_l11_n218() + fun_l12_n16 +end + +def fun_l11_n219() + fun_l12_n167 +end + +def fun_l11_n220() + fun_l12_n719 +end + +def fun_l11_n221() + fun_l12_n414 +end + +def fun_l11_n222() + fun_l12_n874 +end + +def fun_l11_n223() + fun_l12_n482 +end + +def fun_l11_n224() + fun_l12_n191 +end + +def fun_l11_n225() + fun_l12_n172 +end + +def fun_l11_n226() + fun_l12_n768 +end + +def fun_l11_n227() + fun_l12_n746 +end + +def fun_l11_n228() + fun_l12_n460 +end + +def fun_l11_n229() + fun_l12_n64 +end + +def fun_l11_n230() + fun_l12_n747 +end + +def fun_l11_n231() + fun_l12_n147 +end + +def fun_l11_n232() + fun_l12_n157 +end + +def fun_l11_n233() + fun_l12_n336 +end + +def fun_l11_n234() + fun_l12_n904 +end + +def fun_l11_n235() + fun_l12_n76 +end + +def fun_l11_n236() + fun_l12_n499 +end + +def fun_l11_n237() + fun_l12_n559 +end + +def fun_l11_n238() + fun_l12_n949 +end + +def fun_l11_n239() + fun_l12_n525 +end + +def fun_l11_n240() + fun_l12_n741 +end + +def fun_l11_n241() + fun_l12_n11 +end + +def fun_l11_n242() + fun_l12_n449 +end + +def fun_l11_n243() + fun_l12_n767 +end + +def fun_l11_n244() + fun_l12_n94 +end + +def fun_l11_n245() + fun_l12_n721 +end + +def fun_l11_n246() + fun_l12_n592 +end + +def fun_l11_n247() + fun_l12_n184 +end + +def fun_l11_n248() + fun_l12_n166 +end + +def fun_l11_n249() + fun_l12_n773 +end + +def fun_l11_n250() + fun_l12_n334 +end + +def fun_l11_n251() + fun_l12_n965 +end + +def fun_l11_n252() + fun_l12_n154 +end + +def fun_l11_n253() + fun_l12_n182 +end + +def fun_l11_n254() + fun_l12_n298 +end + +def fun_l11_n255() + fun_l12_n29 +end + +def fun_l11_n256() + fun_l12_n409 +end + +def fun_l11_n257() + fun_l12_n452 +end + +def fun_l11_n258() + fun_l12_n369 +end + +def fun_l11_n259() + fun_l12_n794 +end + +def fun_l11_n260() + fun_l12_n210 +end + +def fun_l11_n261() + fun_l12_n255 +end + +def fun_l11_n262() + fun_l12_n801 +end + +def fun_l11_n263() + fun_l12_n650 +end + +def fun_l11_n264() + fun_l12_n612 +end + +def fun_l11_n265() + fun_l12_n122 +end + +def fun_l11_n266() + fun_l12_n70 +end + +def fun_l11_n267() + fun_l12_n254 +end + +def fun_l11_n268() + fun_l12_n104 +end + +def fun_l11_n269() + fun_l12_n564 +end + +def fun_l11_n270() + fun_l12_n256 +end + +def fun_l11_n271() + fun_l12_n525 +end + +def fun_l11_n272() + fun_l12_n734 +end + +def fun_l11_n273() + fun_l12_n127 +end + +def fun_l11_n274() + fun_l12_n705 +end + +def fun_l11_n275() + fun_l12_n607 +end + +def fun_l11_n276() + fun_l12_n681 +end + +def fun_l11_n277() + fun_l12_n510 +end + +def fun_l11_n278() + fun_l12_n889 +end + +def fun_l11_n279() + fun_l12_n153 +end + +def fun_l11_n280() + fun_l12_n457 +end + +def fun_l11_n281() + fun_l12_n394 +end + +def fun_l11_n282() + fun_l12_n628 +end + +def fun_l11_n283() + fun_l12_n576 +end + +def fun_l11_n284() + fun_l12_n294 +end + +def fun_l11_n285() + fun_l12_n79 +end + +def fun_l11_n286() + fun_l12_n505 +end + +def fun_l11_n287() + fun_l12_n726 +end + +def fun_l11_n288() + fun_l12_n171 +end + +def fun_l11_n289() + fun_l12_n317 +end + +def fun_l11_n290() + fun_l12_n350 +end + +def fun_l11_n291() + fun_l12_n134 +end + +def fun_l11_n292() + fun_l12_n595 +end + +def fun_l11_n293() + fun_l12_n924 +end + +def fun_l11_n294() + fun_l12_n713 +end + +def fun_l11_n295() + fun_l12_n630 +end + +def fun_l11_n296() + fun_l12_n444 +end + +def fun_l11_n297() + fun_l12_n751 +end + +def fun_l11_n298() + fun_l12_n324 +end + +def fun_l11_n299() + fun_l12_n851 +end + +def fun_l11_n300() + fun_l12_n883 +end + +def fun_l11_n301() + fun_l12_n289 +end + +def fun_l11_n302() + fun_l12_n427 +end + +def fun_l11_n303() + fun_l12_n593 +end + +def fun_l11_n304() + fun_l12_n380 +end + +def fun_l11_n305() + fun_l12_n630 +end + +def fun_l11_n306() + fun_l12_n245 +end + +def fun_l11_n307() + fun_l12_n369 +end + +def fun_l11_n308() + fun_l12_n641 +end + +def fun_l11_n309() + fun_l12_n271 +end + +def fun_l11_n310() + fun_l12_n67 +end + +def fun_l11_n311() + fun_l12_n109 +end + +def fun_l11_n312() + fun_l12_n559 +end + +def fun_l11_n313() + fun_l12_n211 +end + +def fun_l11_n314() + fun_l12_n396 +end + +def fun_l11_n315() + fun_l12_n390 +end + +def fun_l11_n316() + fun_l12_n72 +end + +def fun_l11_n317() + fun_l12_n13 +end + +def fun_l11_n318() + fun_l12_n690 +end + +def fun_l11_n319() + fun_l12_n104 +end + +def fun_l11_n320() + fun_l12_n671 +end + +def fun_l11_n321() + fun_l12_n506 +end + +def fun_l11_n322() + fun_l12_n679 +end + +def fun_l11_n323() + fun_l12_n809 +end + +def fun_l11_n324() + fun_l12_n750 +end + +def fun_l11_n325() + fun_l12_n754 +end + +def fun_l11_n326() + fun_l12_n6 +end + +def fun_l11_n327() + fun_l12_n522 +end + +def fun_l11_n328() + fun_l12_n414 +end + +def fun_l11_n329() + fun_l12_n934 +end + +def fun_l11_n330() + fun_l12_n653 +end + +def fun_l11_n331() + fun_l12_n290 +end + +def fun_l11_n332() + fun_l12_n262 +end + +def fun_l11_n333() + fun_l12_n933 +end + +def fun_l11_n334() + fun_l12_n332 +end + +def fun_l11_n335() + fun_l12_n882 +end + +def fun_l11_n336() + fun_l12_n448 +end + +def fun_l11_n337() + fun_l12_n5 +end + +def fun_l11_n338() + fun_l12_n993 +end + +def fun_l11_n339() + fun_l12_n354 +end + +def fun_l11_n340() + fun_l12_n643 +end + +def fun_l11_n341() + fun_l12_n85 +end + +def fun_l11_n342() + fun_l12_n957 +end + +def fun_l11_n343() + fun_l12_n581 +end + +def fun_l11_n344() + fun_l12_n837 +end + +def fun_l11_n345() + fun_l12_n210 +end + +def fun_l11_n346() + fun_l12_n45 +end + +def fun_l11_n347() + fun_l12_n672 +end + +def fun_l11_n348() + fun_l12_n559 +end + +def fun_l11_n349() + fun_l12_n76 +end + +def fun_l11_n350() + fun_l12_n500 +end + +def fun_l11_n351() + fun_l12_n23 +end + +def fun_l11_n352() + fun_l12_n364 +end + +def fun_l11_n353() + fun_l12_n72 +end + +def fun_l11_n354() + fun_l12_n953 +end + +def fun_l11_n355() + fun_l12_n104 +end + +def fun_l11_n356() + fun_l12_n446 +end + +def fun_l11_n357() + fun_l12_n231 +end + +def fun_l11_n358() + fun_l12_n923 +end + +def fun_l11_n359() + fun_l12_n396 +end + +def fun_l11_n360() + fun_l12_n748 +end + +def fun_l11_n361() + fun_l12_n168 +end + +def fun_l11_n362() + fun_l12_n329 +end + +def fun_l11_n363() + fun_l12_n843 +end + +def fun_l11_n364() + fun_l12_n864 +end + +def fun_l11_n365() + fun_l12_n163 +end + +def fun_l11_n366() + fun_l12_n811 +end + +def fun_l11_n367() + fun_l12_n7 +end + +def fun_l11_n368() + fun_l12_n105 +end + +def fun_l11_n369() + fun_l12_n367 +end + +def fun_l11_n370() + fun_l12_n650 +end + +def fun_l11_n371() + fun_l12_n966 +end + +def fun_l11_n372() + fun_l12_n248 +end + +def fun_l11_n373() + fun_l12_n431 +end + +def fun_l11_n374() + fun_l12_n329 +end + +def fun_l11_n375() + fun_l12_n788 +end + +def fun_l11_n376() + fun_l12_n407 +end + +def fun_l11_n377() + fun_l12_n551 +end + +def fun_l11_n378() + fun_l12_n703 +end + +def fun_l11_n379() + fun_l12_n414 +end + +def fun_l11_n380() + fun_l12_n23 +end + +def fun_l11_n381() + fun_l12_n747 +end + +def fun_l11_n382() + fun_l12_n10 +end + +def fun_l11_n383() + fun_l12_n943 +end + +def fun_l11_n384() + fun_l12_n26 +end + +def fun_l11_n385() + fun_l12_n459 +end + +def fun_l11_n386() + fun_l12_n256 +end + +def fun_l11_n387() + fun_l12_n606 +end + +def fun_l11_n388() + fun_l12_n138 +end + +def fun_l11_n389() + fun_l12_n371 +end + +def fun_l11_n390() + fun_l12_n304 +end + +def fun_l11_n391() + fun_l12_n459 +end + +def fun_l11_n392() + fun_l12_n968 +end + +def fun_l11_n393() + fun_l12_n153 +end + +def fun_l11_n394() + fun_l12_n742 +end + +def fun_l11_n395() + fun_l12_n617 +end + +def fun_l11_n396() + fun_l12_n562 +end + +def fun_l11_n397() + fun_l12_n474 +end + +def fun_l11_n398() + fun_l12_n633 +end + +def fun_l11_n399() + fun_l12_n950 +end + +def fun_l11_n400() + fun_l12_n370 +end + +def fun_l11_n401() + fun_l12_n301 +end + +def fun_l11_n402() + fun_l12_n74 +end + +def fun_l11_n403() + fun_l12_n759 +end + +def fun_l11_n404() + fun_l12_n634 +end + +def fun_l11_n405() + fun_l12_n678 +end + +def fun_l11_n406() + fun_l12_n761 +end + +def fun_l11_n407() + fun_l12_n669 +end + +def fun_l11_n408() + fun_l12_n737 +end + +def fun_l11_n409() + fun_l12_n666 +end + +def fun_l11_n410() + fun_l12_n43 +end + +def fun_l11_n411() + fun_l12_n64 +end + +def fun_l11_n412() + fun_l12_n956 +end + +def fun_l11_n413() + fun_l12_n749 +end + +def fun_l11_n414() + fun_l12_n22 +end + +def fun_l11_n415() + fun_l12_n170 +end + +def fun_l11_n416() + fun_l12_n113 +end + +def fun_l11_n417() + fun_l12_n780 +end + +def fun_l11_n418() + fun_l12_n855 +end + +def fun_l11_n419() + fun_l12_n551 +end + +def fun_l11_n420() + fun_l12_n101 +end + +def fun_l11_n421() + fun_l12_n543 +end + +def fun_l11_n422() + fun_l12_n773 +end + +def fun_l11_n423() + fun_l12_n13 +end + +def fun_l11_n424() + fun_l12_n997 +end + +def fun_l11_n425() + fun_l12_n199 +end + +def fun_l11_n426() + fun_l12_n281 +end + +def fun_l11_n427() + fun_l12_n685 +end + +def fun_l11_n428() + fun_l12_n588 +end + +def fun_l11_n429() + fun_l12_n693 +end + +def fun_l11_n430() + fun_l12_n595 +end + +def fun_l11_n431() + fun_l12_n632 +end + +def fun_l11_n432() + fun_l12_n923 +end + +def fun_l11_n433() + fun_l12_n388 +end + +def fun_l11_n434() + fun_l12_n307 +end + +def fun_l11_n435() + fun_l12_n169 +end + +def fun_l11_n436() + fun_l12_n13 +end + +def fun_l11_n437() + fun_l12_n207 +end + +def fun_l11_n438() + fun_l12_n711 +end + +def fun_l11_n439() + fun_l12_n649 +end + +def fun_l11_n440() + fun_l12_n817 +end + +def fun_l11_n441() + fun_l12_n280 +end + +def fun_l11_n442() + fun_l12_n833 +end + +def fun_l11_n443() + fun_l12_n962 +end + +def fun_l11_n444() + fun_l12_n431 +end + +def fun_l11_n445() + fun_l12_n564 +end + +def fun_l11_n446() + fun_l12_n107 +end + +def fun_l11_n447() + fun_l12_n504 +end + +def fun_l11_n448() + fun_l12_n680 +end + +def fun_l11_n449() + fun_l12_n653 +end + +def fun_l11_n450() + fun_l12_n549 +end + +def fun_l11_n451() + fun_l12_n34 +end + +def fun_l11_n452() + fun_l12_n607 +end + +def fun_l11_n453() + fun_l12_n831 +end + +def fun_l11_n454() + fun_l12_n974 +end + +def fun_l11_n455() + fun_l12_n815 +end + +def fun_l11_n456() + fun_l12_n700 +end + +def fun_l11_n457() + fun_l12_n583 +end + +def fun_l11_n458() + fun_l12_n479 +end + +def fun_l11_n459() + fun_l12_n815 +end + +def fun_l11_n460() + fun_l12_n45 +end + +def fun_l11_n461() + fun_l12_n740 +end + +def fun_l11_n462() + fun_l12_n637 +end + +def fun_l11_n463() + fun_l12_n568 +end + +def fun_l11_n464() + fun_l12_n340 +end + +def fun_l11_n465() + fun_l12_n532 +end + +def fun_l11_n466() + fun_l12_n13 +end + +def fun_l11_n467() + fun_l12_n479 +end + +def fun_l11_n468() + fun_l12_n263 +end + +def fun_l11_n469() + fun_l12_n109 +end + +def fun_l11_n470() + fun_l12_n290 +end + +def fun_l11_n471() + fun_l12_n85 +end + +def fun_l11_n472() + fun_l12_n360 +end + +def fun_l11_n473() + fun_l12_n33 +end + +def fun_l11_n474() + fun_l12_n603 +end + +def fun_l11_n475() + fun_l12_n82 +end + +def fun_l11_n476() + fun_l12_n250 +end + +def fun_l11_n477() + fun_l12_n233 +end + +def fun_l11_n478() + fun_l12_n530 +end + +def fun_l11_n479() + fun_l12_n619 +end + +def fun_l11_n480() + fun_l12_n756 +end + +def fun_l11_n481() + fun_l12_n681 +end + +def fun_l11_n482() + fun_l12_n981 +end + +def fun_l11_n483() + fun_l12_n308 +end + +def fun_l11_n484() + fun_l12_n955 +end + +def fun_l11_n485() + fun_l12_n197 +end + +def fun_l11_n486() + fun_l12_n620 +end + +def fun_l11_n487() + fun_l12_n485 +end + +def fun_l11_n488() + fun_l12_n866 +end + +def fun_l11_n489() + fun_l12_n502 +end + +def fun_l11_n490() + fun_l12_n16 +end + +def fun_l11_n491() + fun_l12_n727 +end + +def fun_l11_n492() + fun_l12_n13 +end + +def fun_l11_n493() + fun_l12_n268 +end + +def fun_l11_n494() + fun_l12_n501 +end + +def fun_l11_n495() + fun_l12_n303 +end + +def fun_l11_n496() + fun_l12_n223 +end + +def fun_l11_n497() + fun_l12_n623 +end + +def fun_l11_n498() + fun_l12_n479 +end + +def fun_l11_n499() + fun_l12_n310 +end + +def fun_l11_n500() + fun_l12_n337 +end + +def fun_l11_n501() + fun_l12_n406 +end + +def fun_l11_n502() + fun_l12_n727 +end + +def fun_l11_n503() + fun_l12_n329 +end + +def fun_l11_n504() + fun_l12_n675 +end + +def fun_l11_n505() + fun_l12_n41 +end + +def fun_l11_n506() + fun_l12_n176 +end + +def fun_l11_n507() + fun_l12_n277 +end + +def fun_l11_n508() + fun_l12_n767 +end + +def fun_l11_n509() + fun_l12_n863 +end + +def fun_l11_n510() + fun_l12_n459 +end + +def fun_l11_n511() + fun_l12_n360 +end + +def fun_l11_n512() + fun_l12_n870 +end + +def fun_l11_n513() + fun_l12_n939 +end + +def fun_l11_n514() + fun_l12_n697 +end + +def fun_l11_n515() + fun_l12_n91 +end + +def fun_l11_n516() + fun_l12_n382 +end + +def fun_l11_n517() + fun_l12_n649 +end + +def fun_l11_n518() + fun_l12_n455 +end + +def fun_l11_n519() + fun_l12_n52 +end + +def fun_l11_n520() + fun_l12_n857 +end + +def fun_l11_n521() + fun_l12_n110 +end + +def fun_l11_n522() + fun_l12_n21 +end + +def fun_l11_n523() + fun_l12_n786 +end + +def fun_l11_n524() + fun_l12_n56 +end + +def fun_l11_n525() + fun_l12_n558 +end + +def fun_l11_n526() + fun_l12_n923 +end + +def fun_l11_n527() + fun_l12_n716 +end + +def fun_l11_n528() + fun_l12_n20 +end + +def fun_l11_n529() + fun_l12_n503 +end + +def fun_l11_n530() + fun_l12_n221 +end + +def fun_l11_n531() + fun_l12_n364 +end + +def fun_l11_n532() + fun_l12_n412 +end + +def fun_l11_n533() + fun_l12_n925 +end + +def fun_l11_n534() + fun_l12_n638 +end + +def fun_l11_n535() + fun_l12_n413 +end + +def fun_l11_n536() + fun_l12_n873 +end + +def fun_l11_n537() + fun_l12_n499 +end + +def fun_l11_n538() + fun_l12_n231 +end + +def fun_l11_n539() + fun_l12_n450 +end + +def fun_l11_n540() + fun_l12_n137 +end + +def fun_l11_n541() + fun_l12_n516 +end + +def fun_l11_n542() + fun_l12_n479 +end + +def fun_l11_n543() + fun_l12_n541 +end + +def fun_l11_n544() + fun_l12_n42 +end + +def fun_l11_n545() + fun_l12_n207 +end + +def fun_l11_n546() + fun_l12_n340 +end + +def fun_l11_n547() + fun_l12_n888 +end + +def fun_l11_n548() + fun_l12_n443 +end + +def fun_l11_n549() + fun_l12_n375 +end + +def fun_l11_n550() + fun_l12_n972 +end + +def fun_l11_n551() + fun_l12_n622 +end + +def fun_l11_n552() + fun_l12_n958 +end + +def fun_l11_n553() + fun_l12_n279 +end + +def fun_l11_n554() + fun_l12_n498 +end + +def fun_l11_n555() + fun_l12_n498 +end + +def fun_l11_n556() + fun_l12_n502 +end + +def fun_l11_n557() + fun_l12_n113 +end + +def fun_l11_n558() + fun_l12_n636 +end + +def fun_l11_n559() + fun_l12_n525 +end + +def fun_l11_n560() + fun_l12_n541 +end + +def fun_l11_n561() + fun_l12_n336 +end + +def fun_l11_n562() + fun_l12_n787 +end + +def fun_l11_n563() + fun_l12_n858 +end + +def fun_l11_n564() + fun_l12_n772 +end + +def fun_l11_n565() + fun_l12_n831 +end + +def fun_l11_n566() + fun_l12_n95 +end + +def fun_l11_n567() + fun_l12_n927 +end + +def fun_l11_n568() + fun_l12_n888 +end + +def fun_l11_n569() + fun_l12_n444 +end + +def fun_l11_n570() + fun_l12_n23 +end + +def fun_l11_n571() + fun_l12_n995 +end + +def fun_l11_n572() + fun_l12_n372 +end + +def fun_l11_n573() + fun_l12_n432 +end + +def fun_l11_n574() + fun_l12_n156 +end + +def fun_l11_n575() + fun_l12_n981 +end + +def fun_l11_n576() + fun_l12_n328 +end + +def fun_l11_n577() + fun_l12_n411 +end + +def fun_l11_n578() + fun_l12_n734 +end + +def fun_l11_n579() + fun_l12_n646 +end + +def fun_l11_n580() + fun_l12_n214 +end + +def fun_l11_n581() + fun_l12_n334 +end + +def fun_l11_n582() + fun_l12_n800 +end + +def fun_l11_n583() + fun_l12_n344 +end + +def fun_l11_n584() + fun_l12_n672 +end + +def fun_l11_n585() + fun_l12_n403 +end + +def fun_l11_n586() + fun_l12_n351 +end + +def fun_l11_n587() + fun_l12_n506 +end + +def fun_l11_n588() + fun_l12_n878 +end + +def fun_l11_n589() + fun_l12_n986 +end + +def fun_l11_n590() + fun_l12_n524 +end + +def fun_l11_n591() + fun_l12_n552 +end + +def fun_l11_n592() + fun_l12_n735 +end + +def fun_l11_n593() + fun_l12_n953 +end + +def fun_l11_n594() + fun_l12_n138 +end + +def fun_l11_n595() + fun_l12_n185 +end + +def fun_l11_n596() + fun_l12_n865 +end + +def fun_l11_n597() + fun_l12_n143 +end + +def fun_l11_n598() + fun_l12_n879 +end + +def fun_l11_n599() + fun_l12_n751 +end + +def fun_l11_n600() + fun_l12_n750 +end + +def fun_l11_n601() + fun_l12_n574 +end + +def fun_l11_n602() + fun_l12_n91 +end + +def fun_l11_n603() + fun_l12_n116 +end + +def fun_l11_n604() + fun_l12_n398 +end + +def fun_l11_n605() + fun_l12_n782 +end + +def fun_l11_n606() + fun_l12_n770 +end + +def fun_l11_n607() + fun_l12_n240 +end + +def fun_l11_n608() + fun_l12_n385 +end + +def fun_l11_n609() + fun_l12_n106 +end + +def fun_l11_n610() + fun_l12_n959 +end + +def fun_l11_n611() + fun_l12_n84 +end + +def fun_l11_n612() + fun_l12_n235 +end + +def fun_l11_n613() + fun_l12_n429 +end + +def fun_l11_n614() + fun_l12_n402 +end + +def fun_l11_n615() + fun_l12_n32 +end + +def fun_l11_n616() + fun_l12_n517 +end + +def fun_l11_n617() + fun_l12_n304 +end + +def fun_l11_n618() + fun_l12_n374 +end + +def fun_l11_n619() + fun_l12_n884 +end + +def fun_l11_n620() + fun_l12_n399 +end + +def fun_l11_n621() + fun_l12_n721 +end + +def fun_l11_n622() + fun_l12_n58 +end + +def fun_l11_n623() + fun_l12_n237 +end + +def fun_l11_n624() + fun_l12_n659 +end + +def fun_l11_n625() + fun_l12_n454 +end + +def fun_l11_n626() + fun_l12_n942 +end + +def fun_l11_n627() + fun_l12_n975 +end + +def fun_l11_n628() + fun_l12_n192 +end + +def fun_l11_n629() + fun_l12_n590 +end + +def fun_l11_n630() + fun_l12_n340 +end + +def fun_l11_n631() + fun_l12_n229 +end + +def fun_l11_n632() + fun_l12_n478 +end + +def fun_l11_n633() + fun_l12_n84 +end + +def fun_l11_n634() + fun_l12_n280 +end + +def fun_l11_n635() + fun_l12_n896 +end + +def fun_l11_n636() + fun_l12_n872 +end + +def fun_l11_n637() + fun_l12_n924 +end + +def fun_l11_n638() + fun_l12_n957 +end + +def fun_l11_n639() + fun_l12_n252 +end + +def fun_l11_n640() + fun_l12_n308 +end + +def fun_l11_n641() + fun_l12_n217 +end + +def fun_l11_n642() + fun_l12_n477 +end + +def fun_l11_n643() + fun_l12_n754 +end + +def fun_l11_n644() + fun_l12_n561 +end + +def fun_l11_n645() + fun_l12_n597 +end + +def fun_l11_n646() + fun_l12_n194 +end + +def fun_l11_n647() + fun_l12_n708 +end + +def fun_l11_n648() + fun_l12_n892 +end + +def fun_l11_n649() + fun_l12_n771 +end + +def fun_l11_n650() + fun_l12_n549 +end + +def fun_l11_n651() + fun_l12_n84 +end + +def fun_l11_n652() + fun_l12_n256 +end + +def fun_l11_n653() + fun_l12_n454 +end + +def fun_l11_n654() + fun_l12_n773 +end + +def fun_l11_n655() + fun_l12_n674 +end + +def fun_l11_n656() + fun_l12_n364 +end + +def fun_l11_n657() + fun_l12_n548 +end + +def fun_l11_n658() + fun_l12_n287 +end + +def fun_l11_n659() + fun_l12_n211 +end + +def fun_l11_n660() + fun_l12_n213 +end + +def fun_l11_n661() + fun_l12_n975 +end + +def fun_l11_n662() + fun_l12_n221 +end + +def fun_l11_n663() + fun_l12_n524 +end + +def fun_l11_n664() + fun_l12_n167 +end + +def fun_l11_n665() + fun_l12_n361 +end + +def fun_l11_n666() + fun_l12_n435 +end + +def fun_l11_n667() + fun_l12_n881 +end + +def fun_l11_n668() + fun_l12_n977 +end + +def fun_l11_n669() + fun_l12_n87 +end + +def fun_l11_n670() + fun_l12_n281 +end + +def fun_l11_n671() + fun_l12_n44 +end + +def fun_l11_n672() + fun_l12_n584 +end + +def fun_l11_n673() + fun_l12_n645 +end + +def fun_l11_n674() + fun_l12_n268 +end + +def fun_l11_n675() + fun_l12_n98 +end + +def fun_l11_n676() + fun_l12_n861 +end + +def fun_l11_n677() + fun_l12_n9 +end + +def fun_l11_n678() + fun_l12_n91 +end + +def fun_l11_n679() + fun_l12_n976 +end + +def fun_l11_n680() + fun_l12_n373 +end + +def fun_l11_n681() + fun_l12_n673 +end + +def fun_l11_n682() + fun_l12_n206 +end + +def fun_l11_n683() + fun_l12_n838 +end + +def fun_l11_n684() + fun_l12_n972 +end + +def fun_l11_n685() + fun_l12_n607 +end + +def fun_l11_n686() + fun_l12_n55 +end + +def fun_l11_n687() + fun_l12_n294 +end + +def fun_l11_n688() + fun_l12_n871 +end + +def fun_l11_n689() + fun_l12_n518 +end + +def fun_l11_n690() + fun_l12_n552 +end + +def fun_l11_n691() + fun_l12_n622 +end + +def fun_l11_n692() + fun_l12_n505 +end + +def fun_l11_n693() + fun_l12_n33 +end + +def fun_l11_n694() + fun_l12_n522 +end + +def fun_l11_n695() + fun_l12_n729 +end + +def fun_l11_n696() + fun_l12_n477 +end + +def fun_l11_n697() + fun_l12_n424 +end + +def fun_l11_n698() + fun_l12_n258 +end + +def fun_l11_n699() + fun_l12_n328 +end + +def fun_l11_n700() + fun_l12_n501 +end + +def fun_l11_n701() + fun_l12_n841 +end + +def fun_l11_n702() + fun_l12_n684 +end + +def fun_l11_n703() + fun_l12_n864 +end + +def fun_l11_n704() + fun_l12_n527 +end + +def fun_l11_n705() + fun_l12_n808 +end + +def fun_l11_n706() + fun_l12_n213 +end + +def fun_l11_n707() + fun_l12_n711 +end + +def fun_l11_n708() + fun_l12_n727 +end + +def fun_l11_n709() + fun_l12_n82 +end + +def fun_l11_n710() + fun_l12_n926 +end + +def fun_l11_n711() + fun_l12_n719 +end + +def fun_l11_n712() + fun_l12_n180 +end + +def fun_l11_n713() + fun_l12_n568 +end + +def fun_l11_n714() + fun_l12_n11 +end + +def fun_l11_n715() + fun_l12_n624 +end + +def fun_l11_n716() + fun_l12_n954 +end + +def fun_l11_n717() + fun_l12_n584 +end + +def fun_l11_n718() + fun_l12_n222 +end + +def fun_l11_n719() + fun_l12_n460 +end + +def fun_l11_n720() + fun_l12_n253 +end + +def fun_l11_n721() + fun_l12_n938 +end + +def fun_l11_n722() + fun_l12_n552 +end + +def fun_l11_n723() + fun_l12_n491 +end + +def fun_l11_n724() + fun_l12_n146 +end + +def fun_l11_n725() + fun_l12_n833 +end + +def fun_l11_n726() + fun_l12_n43 +end + +def fun_l11_n727() + fun_l12_n700 +end + +def fun_l11_n728() + fun_l12_n730 +end + +def fun_l11_n729() + fun_l12_n84 +end + +def fun_l11_n730() + fun_l12_n468 +end + +def fun_l11_n731() + fun_l12_n253 +end + +def fun_l11_n732() + fun_l12_n473 +end + +def fun_l11_n733() + fun_l12_n997 +end + +def fun_l11_n734() + fun_l12_n584 +end + +def fun_l11_n735() + fun_l12_n815 +end + +def fun_l11_n736() + fun_l12_n577 +end + +def fun_l11_n737() + fun_l12_n890 +end + +def fun_l11_n738() + fun_l12_n282 +end + +def fun_l11_n739() + fun_l12_n794 +end + +def fun_l11_n740() + fun_l12_n615 +end + +def fun_l11_n741() + fun_l12_n254 +end + +def fun_l11_n742() + fun_l12_n250 +end + +def fun_l11_n743() + fun_l12_n45 +end + +def fun_l11_n744() + fun_l12_n513 +end + +def fun_l11_n745() + fun_l12_n786 +end + +def fun_l11_n746() + fun_l12_n764 +end + +def fun_l11_n747() + fun_l12_n73 +end + +def fun_l11_n748() + fun_l12_n944 +end + +def fun_l11_n749() + fun_l12_n49 +end + +def fun_l11_n750() + fun_l12_n513 +end + +def fun_l11_n751() + fun_l12_n367 +end + +def fun_l11_n752() + fun_l12_n61 +end + +def fun_l11_n753() + fun_l12_n279 +end + +def fun_l11_n754() + fun_l12_n991 +end + +def fun_l11_n755() + fun_l12_n747 +end + +def fun_l11_n756() + fun_l12_n422 +end + +def fun_l11_n757() + fun_l12_n414 +end + +def fun_l11_n758() + fun_l12_n61 +end + +def fun_l11_n759() + fun_l12_n471 +end + +def fun_l11_n760() + fun_l12_n436 +end + +def fun_l11_n761() + fun_l12_n183 +end + +def fun_l11_n762() + fun_l12_n173 +end + +def fun_l11_n763() + fun_l12_n362 +end + +def fun_l11_n764() + fun_l12_n174 +end + +def fun_l11_n765() + fun_l12_n710 +end + +def fun_l11_n766() + fun_l12_n212 +end + +def fun_l11_n767() + fun_l12_n649 +end + +def fun_l11_n768() + fun_l12_n409 +end + +def fun_l11_n769() + fun_l12_n375 +end + +def fun_l11_n770() + fun_l12_n608 +end + +def fun_l11_n771() + fun_l12_n447 +end + +def fun_l11_n772() + fun_l12_n530 +end + +def fun_l11_n773() + fun_l12_n359 +end + +def fun_l11_n774() + fun_l12_n317 +end + +def fun_l11_n775() + fun_l12_n105 +end + +def fun_l11_n776() + fun_l12_n65 +end + +def fun_l11_n777() + fun_l12_n243 +end + +def fun_l11_n778() + fun_l12_n274 +end + +def fun_l11_n779() + fun_l12_n560 +end + +def fun_l11_n780() + fun_l12_n155 +end + +def fun_l11_n781() + fun_l12_n277 +end + +def fun_l11_n782() + fun_l12_n255 +end + +def fun_l11_n783() + fun_l12_n184 +end + +def fun_l11_n784() + fun_l12_n495 +end + +def fun_l11_n785() + fun_l12_n910 +end + +def fun_l11_n786() + fun_l12_n245 +end + +def fun_l11_n787() + fun_l12_n761 +end + +def fun_l11_n788() + fun_l12_n501 +end + +def fun_l11_n789() + fun_l12_n11 +end + +def fun_l11_n790() + fun_l12_n87 +end + +def fun_l11_n791() + fun_l12_n233 +end + +def fun_l11_n792() + fun_l12_n201 +end + +def fun_l11_n793() + fun_l12_n471 +end + +def fun_l11_n794() + fun_l12_n6 +end + +def fun_l11_n795() + fun_l12_n257 +end + +def fun_l11_n796() + fun_l12_n104 +end + +def fun_l11_n797() + fun_l12_n712 +end + +def fun_l11_n798() + fun_l12_n408 +end + +def fun_l11_n799() + fun_l12_n713 +end + +def fun_l11_n800() + fun_l12_n622 +end + +def fun_l11_n801() + fun_l12_n498 +end + +def fun_l11_n802() + fun_l12_n904 +end + +def fun_l11_n803() + fun_l12_n413 +end + +def fun_l11_n804() + fun_l12_n424 +end + +def fun_l11_n805() + fun_l12_n209 +end + +def fun_l11_n806() + fun_l12_n171 +end + +def fun_l11_n807() + fun_l12_n835 +end + +def fun_l11_n808() + fun_l12_n872 +end + +def fun_l11_n809() + fun_l12_n456 +end + +def fun_l11_n810() + fun_l12_n586 +end + +def fun_l11_n811() + fun_l12_n422 +end + +def fun_l11_n812() + fun_l12_n125 +end + +def fun_l11_n813() + fun_l12_n482 +end + +def fun_l11_n814() + fun_l12_n17 +end + +def fun_l11_n815() + fun_l12_n966 +end + +def fun_l11_n816() + fun_l12_n408 +end + +def fun_l11_n817() + fun_l12_n874 +end + +def fun_l11_n818() + fun_l12_n454 +end + +def fun_l11_n819() + fun_l12_n818 +end + +def fun_l11_n820() + fun_l12_n469 +end + +def fun_l11_n821() + fun_l12_n104 +end + +def fun_l11_n822() + fun_l12_n765 +end + +def fun_l11_n823() + fun_l12_n472 +end + +def fun_l11_n824() + fun_l12_n794 +end + +def fun_l11_n825() + fun_l12_n609 +end + +def fun_l11_n826() + fun_l12_n609 +end + +def fun_l11_n827() + fun_l12_n99 +end + +def fun_l11_n828() + fun_l12_n844 +end + +def fun_l11_n829() + fun_l12_n423 +end + +def fun_l11_n830() + fun_l12_n560 +end + +def fun_l11_n831() + fun_l12_n60 +end + +def fun_l11_n832() + fun_l12_n670 +end + +def fun_l11_n833() + fun_l12_n591 +end + +def fun_l11_n834() + fun_l12_n572 +end + +def fun_l11_n835() + fun_l12_n96 +end + +def fun_l11_n836() + fun_l12_n567 +end + +def fun_l11_n837() + fun_l12_n239 +end + +def fun_l11_n838() + fun_l12_n937 +end + +def fun_l11_n839() + fun_l12_n853 +end + +def fun_l11_n840() + fun_l12_n440 +end + +def fun_l11_n841() + fun_l12_n930 +end + +def fun_l11_n842() + fun_l12_n448 +end + +def fun_l11_n843() + fun_l12_n185 +end + +def fun_l11_n844() + fun_l12_n904 +end + +def fun_l11_n845() + fun_l12_n399 +end + +def fun_l11_n846() + fun_l12_n184 +end + +def fun_l11_n847() + fun_l12_n985 +end + +def fun_l11_n848() + fun_l12_n966 +end + +def fun_l11_n849() + fun_l12_n183 +end + +def fun_l11_n850() + fun_l12_n418 +end + +def fun_l11_n851() + fun_l12_n546 +end + +def fun_l11_n852() + fun_l12_n96 +end + +def fun_l11_n853() + fun_l12_n172 +end + +def fun_l11_n854() + fun_l12_n546 +end + +def fun_l11_n855() + fun_l12_n86 +end + +def fun_l11_n856() + fun_l12_n815 +end + +def fun_l11_n857() + fun_l12_n552 +end + +def fun_l11_n858() + fun_l12_n657 +end + +def fun_l11_n859() + fun_l12_n567 +end + +def fun_l11_n860() + fun_l12_n561 +end + +def fun_l11_n861() + fun_l12_n590 +end + +def fun_l11_n862() + fun_l12_n28 +end + +def fun_l11_n863() + fun_l12_n935 +end + +def fun_l11_n864() + fun_l12_n950 +end + +def fun_l11_n865() + fun_l12_n946 +end + +def fun_l11_n866() + fun_l12_n77 +end + +def fun_l11_n867() + fun_l12_n454 +end + +def fun_l11_n868() + fun_l12_n813 +end + +def fun_l11_n869() + fun_l12_n562 +end + +def fun_l11_n870() + fun_l12_n598 +end + +def fun_l11_n871() + fun_l12_n331 +end + +def fun_l11_n872() + fun_l12_n156 +end + +def fun_l11_n873() + fun_l12_n807 +end + +def fun_l11_n874() + fun_l12_n442 +end + +def fun_l11_n875() + fun_l12_n322 +end + +def fun_l11_n876() + fun_l12_n472 +end + +def fun_l11_n877() + fun_l12_n581 +end + +def fun_l11_n878() + fun_l12_n94 +end + +def fun_l11_n879() + fun_l12_n270 +end + +def fun_l11_n880() + fun_l12_n63 +end + +def fun_l11_n881() + fun_l12_n290 +end + +def fun_l11_n882() + fun_l12_n148 +end + +def fun_l11_n883() + fun_l12_n862 +end + +def fun_l11_n884() + fun_l12_n527 +end + +def fun_l11_n885() + fun_l12_n166 +end + +def fun_l11_n886() + fun_l12_n422 +end + +def fun_l11_n887() + fun_l12_n195 +end + +def fun_l11_n888() + fun_l12_n592 +end + +def fun_l11_n889() + fun_l12_n116 +end + +def fun_l11_n890() + fun_l12_n923 +end + +def fun_l11_n891() + fun_l12_n422 +end + +def fun_l11_n892() + fun_l12_n945 +end + +def fun_l11_n893() + fun_l12_n850 +end + +def fun_l11_n894() + fun_l12_n598 +end + +def fun_l11_n895() + fun_l12_n448 +end + +def fun_l11_n896() + fun_l12_n955 +end + +def fun_l11_n897() + fun_l12_n259 +end + +def fun_l11_n898() + fun_l12_n145 +end + +def fun_l11_n899() + fun_l12_n321 +end + +def fun_l11_n900() + fun_l12_n680 +end + +def fun_l11_n901() + fun_l12_n856 +end + +def fun_l11_n902() + fun_l12_n776 +end + +def fun_l11_n903() + fun_l12_n108 +end + +def fun_l11_n904() + fun_l12_n340 +end + +def fun_l11_n905() + fun_l12_n78 +end + +def fun_l11_n906() + fun_l12_n218 +end + +def fun_l11_n907() + fun_l12_n288 +end + +def fun_l11_n908() + fun_l12_n197 +end + +def fun_l11_n909() + fun_l12_n890 +end + +def fun_l11_n910() + fun_l12_n850 +end + +def fun_l11_n911() + fun_l12_n964 +end + +def fun_l11_n912() + fun_l12_n47 +end + +def fun_l11_n913() + fun_l12_n462 +end + +def fun_l11_n914() + fun_l12_n461 +end + +def fun_l11_n915() + fun_l12_n57 +end + +def fun_l11_n916() + fun_l12_n938 +end + +def fun_l11_n917() + fun_l12_n841 +end + +def fun_l11_n918() + fun_l12_n462 +end + +def fun_l11_n919() + fun_l12_n425 +end + +def fun_l11_n920() + fun_l12_n775 +end + +def fun_l11_n921() + fun_l12_n302 +end + +def fun_l11_n922() + fun_l12_n921 +end + +def fun_l11_n923() + fun_l12_n322 +end + +def fun_l11_n924() + fun_l12_n414 +end + +def fun_l11_n925() + fun_l12_n461 +end + +def fun_l11_n926() + fun_l12_n476 +end + +def fun_l11_n927() + fun_l12_n537 +end + +def fun_l11_n928() + fun_l12_n359 +end + +def fun_l11_n929() + fun_l12_n297 +end + +def fun_l11_n930() + fun_l12_n134 +end + +def fun_l11_n931() + fun_l12_n875 +end + +def fun_l11_n932() + fun_l12_n763 +end + +def fun_l11_n933() + fun_l12_n180 +end + +def fun_l11_n934() + fun_l12_n522 +end + +def fun_l11_n935() + fun_l12_n701 +end + +def fun_l11_n936() + fun_l12_n793 +end + +def fun_l11_n937() + fun_l12_n853 +end + +def fun_l11_n938() + fun_l12_n208 +end + +def fun_l11_n939() + fun_l12_n307 +end + +def fun_l11_n940() + fun_l12_n695 +end + +def fun_l11_n941() + fun_l12_n171 +end + +def fun_l11_n942() + fun_l12_n181 +end + +def fun_l11_n943() + fun_l12_n58 +end + +def fun_l11_n944() + fun_l12_n733 +end + +def fun_l11_n945() + fun_l12_n7 +end + +def fun_l11_n946() + fun_l12_n332 +end + +def fun_l11_n947() + fun_l12_n323 +end + +def fun_l11_n948() + fun_l12_n240 +end + +def fun_l11_n949() + fun_l12_n21 +end + +def fun_l11_n950() + fun_l12_n814 +end + +def fun_l11_n951() + fun_l12_n943 +end + +def fun_l11_n952() + fun_l12_n4 +end + +def fun_l11_n953() + fun_l12_n747 +end + +def fun_l11_n954() + fun_l12_n500 +end + +def fun_l11_n955() + fun_l12_n361 +end + +def fun_l11_n956() + fun_l12_n898 +end + +def fun_l11_n957() + fun_l12_n216 +end + +def fun_l11_n958() + fun_l12_n58 +end + +def fun_l11_n959() + fun_l12_n327 +end + +def fun_l11_n960() + fun_l12_n405 +end + +def fun_l11_n961() + fun_l12_n665 +end + +def fun_l11_n962() + fun_l12_n456 +end + +def fun_l11_n963() + fun_l12_n399 +end + +def fun_l11_n964() + fun_l12_n836 +end + +def fun_l11_n965() + fun_l12_n18 +end + +def fun_l11_n966() + fun_l12_n236 +end + +def fun_l11_n967() + fun_l12_n594 +end + +def fun_l11_n968() + fun_l12_n147 +end + +def fun_l11_n969() + fun_l12_n758 +end + +def fun_l11_n970() + fun_l12_n271 +end + +def fun_l11_n971() + fun_l12_n551 +end + +def fun_l11_n972() + fun_l12_n332 +end + +def fun_l11_n973() + fun_l12_n348 +end + +def fun_l11_n974() + fun_l12_n158 +end + +def fun_l11_n975() + fun_l12_n990 +end + +def fun_l11_n976() + fun_l12_n330 +end + +def fun_l11_n977() + fun_l12_n764 +end + +def fun_l11_n978() + fun_l12_n844 +end + +def fun_l11_n979() + fun_l12_n452 +end + +def fun_l11_n980() + fun_l12_n593 +end + +def fun_l11_n981() + fun_l12_n762 +end + +def fun_l11_n982() + fun_l12_n736 +end + +def fun_l11_n983() + fun_l12_n957 +end + +def fun_l11_n984() + fun_l12_n174 +end + +def fun_l11_n985() + fun_l12_n454 +end + +def fun_l11_n986() + fun_l12_n492 +end + +def fun_l11_n987() + fun_l12_n986 +end + +def fun_l11_n988() + fun_l12_n868 +end + +def fun_l11_n989() + fun_l12_n445 +end + +def fun_l11_n990() + fun_l12_n422 +end + +def fun_l11_n991() + fun_l12_n877 +end + +def fun_l11_n992() + fun_l12_n150 +end + +def fun_l11_n993() + fun_l12_n163 +end + +def fun_l11_n994() + fun_l12_n183 +end + +def fun_l11_n995() + fun_l12_n100 +end + +def fun_l11_n996() + fun_l12_n297 +end + +def fun_l11_n997() + fun_l12_n43 +end + +def fun_l11_n998() + fun_l12_n324 +end + +def fun_l11_n999() + fun_l12_n732 +end + +def fun_l12_n0() + fun_l13_n595 +end + +def fun_l12_n1() + fun_l13_n185 +end + +def fun_l12_n2() + fun_l13_n257 +end + +def fun_l12_n3() + fun_l13_n865 +end + +def fun_l12_n4() + fun_l13_n857 +end + +def fun_l12_n5() + fun_l13_n9 +end + +def fun_l12_n6() + fun_l13_n41 +end + +def fun_l12_n7() + fun_l13_n430 +end + +def fun_l12_n8() + fun_l13_n394 +end + +def fun_l12_n9() + fun_l13_n20 +end + +def fun_l12_n10() + fun_l13_n527 +end + +def fun_l12_n11() + fun_l13_n158 +end + +def fun_l12_n12() + fun_l13_n229 +end + +def fun_l12_n13() + fun_l13_n205 +end + +def fun_l12_n14() + fun_l13_n88 +end + +def fun_l12_n15() + fun_l13_n359 +end + +def fun_l12_n16() + fun_l13_n204 +end + +def fun_l12_n17() + fun_l13_n297 +end + +def fun_l12_n18() + fun_l13_n531 +end + +def fun_l12_n19() + fun_l13_n244 +end + +def fun_l12_n20() + fun_l13_n587 +end + +def fun_l12_n21() + fun_l13_n731 +end + +def fun_l12_n22() + fun_l13_n839 +end + +def fun_l12_n23() + fun_l13_n560 +end + +def fun_l12_n24() + fun_l13_n22 +end + +def fun_l12_n25() + fun_l13_n383 +end + +def fun_l12_n26() + fun_l13_n321 +end + +def fun_l12_n27() + fun_l13_n286 +end + +def fun_l12_n28() + fun_l13_n951 +end + +def fun_l12_n29() + fun_l13_n172 +end + +def fun_l12_n30() + fun_l13_n804 +end + +def fun_l12_n31() + fun_l13_n619 +end + +def fun_l12_n32() + fun_l13_n464 +end + +def fun_l12_n33() + fun_l13_n87 +end + +def fun_l12_n34() + fun_l13_n544 +end + +def fun_l12_n35() + fun_l13_n37 +end + +def fun_l12_n36() + fun_l13_n614 +end + +def fun_l12_n37() + fun_l13_n426 +end + +def fun_l12_n38() + fun_l13_n335 +end + +def fun_l12_n39() + fun_l13_n689 +end + +def fun_l12_n40() + fun_l13_n220 +end + +def fun_l12_n41() + fun_l13_n77 +end + +def fun_l12_n42() + fun_l13_n791 +end + +def fun_l12_n43() + fun_l13_n514 +end + +def fun_l12_n44() + fun_l13_n802 +end + +def fun_l12_n45() + fun_l13_n860 +end + +def fun_l12_n46() + fun_l13_n562 +end + +def fun_l12_n47() + fun_l13_n208 +end + +def fun_l12_n48() + fun_l13_n167 +end + +def fun_l12_n49() + fun_l13_n772 +end + +def fun_l12_n50() + fun_l13_n303 +end + +def fun_l12_n51() + fun_l13_n757 +end + +def fun_l12_n52() + fun_l13_n558 +end + +def fun_l12_n53() + fun_l13_n45 +end + +def fun_l12_n54() + fun_l13_n292 +end + +def fun_l12_n55() + fun_l13_n558 +end + +def fun_l12_n56() + fun_l13_n361 +end + +def fun_l12_n57() + fun_l13_n605 +end + +def fun_l12_n58() + fun_l13_n16 +end + +def fun_l12_n59() + fun_l13_n73 +end + +def fun_l12_n60() + fun_l13_n292 +end + +def fun_l12_n61() + fun_l13_n747 +end + +def fun_l12_n62() + fun_l13_n798 +end + +def fun_l12_n63() + fun_l13_n130 +end + +def fun_l12_n64() + fun_l13_n261 +end + +def fun_l12_n65() + fun_l13_n122 +end + +def fun_l12_n66() + fun_l13_n346 +end + +def fun_l12_n67() + fun_l13_n308 +end + +def fun_l12_n68() + fun_l13_n27 +end + +def fun_l12_n69() + fun_l13_n433 +end + +def fun_l12_n70() + fun_l13_n509 +end + +def fun_l12_n71() + fun_l13_n643 +end + +def fun_l12_n72() + fun_l13_n462 +end + +def fun_l12_n73() + fun_l13_n976 +end + +def fun_l12_n74() + fun_l13_n157 +end + +def fun_l12_n75() + fun_l13_n733 +end + +def fun_l12_n76() + fun_l13_n976 +end + +def fun_l12_n77() + fun_l13_n369 +end + +def fun_l12_n78() + fun_l13_n308 +end + +def fun_l12_n79() + fun_l13_n958 +end + +def fun_l12_n80() + fun_l13_n95 +end + +def fun_l12_n81() + fun_l13_n653 +end + +def fun_l12_n82() + fun_l13_n624 +end + +def fun_l12_n83() + fun_l13_n712 +end + +def fun_l12_n84() + fun_l13_n950 +end + +def fun_l12_n85() + fun_l13_n836 +end + +def fun_l12_n86() + fun_l13_n496 +end + +def fun_l12_n87() + fun_l13_n727 +end + +def fun_l12_n88() + fun_l13_n368 +end + +def fun_l12_n89() + fun_l13_n727 +end + +def fun_l12_n90() + fun_l13_n682 +end + +def fun_l12_n91() + fun_l13_n758 +end + +def fun_l12_n92() + fun_l13_n910 +end + +def fun_l12_n93() + fun_l13_n490 +end + +def fun_l12_n94() + fun_l13_n405 +end + +def fun_l12_n95() + fun_l13_n171 +end + +def fun_l12_n96() + fun_l13_n69 +end + +def fun_l12_n97() + fun_l13_n519 +end + +def fun_l12_n98() + fun_l13_n476 +end + +def fun_l12_n99() + fun_l13_n399 +end + +def fun_l12_n100() + fun_l13_n93 +end + +def fun_l12_n101() + fun_l13_n220 +end + +def fun_l12_n102() + fun_l13_n483 +end + +def fun_l12_n103() + fun_l13_n176 +end + +def fun_l12_n104() + fun_l13_n210 +end + +def fun_l12_n105() + fun_l13_n111 +end + +def fun_l12_n106() + fun_l13_n436 +end + +def fun_l12_n107() + fun_l13_n887 +end + +def fun_l12_n108() + fun_l13_n118 +end + +def fun_l12_n109() + fun_l13_n630 +end + +def fun_l12_n110() + fun_l13_n262 +end + +def fun_l12_n111() + fun_l13_n975 +end + +def fun_l12_n112() + fun_l13_n280 +end + +def fun_l12_n113() + fun_l13_n341 +end + +def fun_l12_n114() + fun_l13_n452 +end + +def fun_l12_n115() + fun_l13_n762 +end + +def fun_l12_n116() + fun_l13_n230 +end + +def fun_l12_n117() + fun_l13_n470 +end + +def fun_l12_n118() + fun_l13_n257 +end + +def fun_l12_n119() + fun_l13_n920 +end + +def fun_l12_n120() + fun_l13_n600 +end + +def fun_l12_n121() + fun_l13_n947 +end + +def fun_l12_n122() + fun_l13_n643 +end + +def fun_l12_n123() + fun_l13_n18 +end + +def fun_l12_n124() + fun_l13_n680 +end + +def fun_l12_n125() + fun_l13_n926 +end + +def fun_l12_n126() + fun_l13_n841 +end + +def fun_l12_n127() + fun_l13_n391 +end + +def fun_l12_n128() + fun_l13_n617 +end + +def fun_l12_n129() + fun_l13_n484 +end + +def fun_l12_n130() + fun_l13_n211 +end + +def fun_l12_n131() + fun_l13_n206 +end + +def fun_l12_n132() + fun_l13_n789 +end + +def fun_l12_n133() + fun_l13_n660 +end + +def fun_l12_n134() + fun_l13_n386 +end + +def fun_l12_n135() + fun_l13_n414 +end + +def fun_l12_n136() + fun_l13_n271 +end + +def fun_l12_n137() + fun_l13_n444 +end + +def fun_l12_n138() + fun_l13_n661 +end + +def fun_l12_n139() + fun_l13_n784 +end + +def fun_l12_n140() + fun_l13_n919 +end + +def fun_l12_n141() + fun_l13_n29 +end + +def fun_l12_n142() + fun_l13_n92 +end + +def fun_l12_n143() + fun_l13_n380 +end + +def fun_l12_n144() + fun_l13_n826 +end + +def fun_l12_n145() + fun_l13_n222 +end + +def fun_l12_n146() + fun_l13_n891 +end + +def fun_l12_n147() + fun_l13_n162 +end + +def fun_l12_n148() + fun_l13_n737 +end + +def fun_l12_n149() + fun_l13_n342 +end + +def fun_l12_n150() + fun_l13_n371 +end + +def fun_l12_n151() + fun_l13_n903 +end + +def fun_l12_n152() + fun_l13_n556 +end + +def fun_l12_n153() + fun_l13_n333 +end + +def fun_l12_n154() + fun_l13_n193 +end + +def fun_l12_n155() + fun_l13_n518 +end + +def fun_l12_n156() + fun_l13_n411 +end + +def fun_l12_n157() + fun_l13_n249 +end + +def fun_l12_n158() + fun_l13_n53 +end + +def fun_l12_n159() + fun_l13_n467 +end + +def fun_l12_n160() + fun_l13_n433 +end + +def fun_l12_n161() + fun_l13_n773 +end + +def fun_l12_n162() + fun_l13_n178 +end + +def fun_l12_n163() + fun_l13_n641 +end + +def fun_l12_n164() + fun_l13_n308 +end + +def fun_l12_n165() + fun_l13_n787 +end + +def fun_l12_n166() + fun_l13_n829 +end + +def fun_l12_n167() + fun_l13_n929 +end + +def fun_l12_n168() + fun_l13_n788 +end + +def fun_l12_n169() + fun_l13_n948 +end + +def fun_l12_n170() + fun_l13_n444 +end + +def fun_l12_n171() + fun_l13_n946 +end + +def fun_l12_n172() + fun_l13_n303 +end + +def fun_l12_n173() + fun_l13_n196 +end + +def fun_l12_n174() + fun_l13_n521 +end + +def fun_l12_n175() + fun_l13_n372 +end + +def fun_l12_n176() + fun_l13_n411 +end + +def fun_l12_n177() + fun_l13_n434 +end + +def fun_l12_n178() + fun_l13_n599 +end + +def fun_l12_n179() + fun_l13_n507 +end + +def fun_l12_n180() + fun_l13_n781 +end + +def fun_l12_n181() + fun_l13_n186 +end + +def fun_l12_n182() + fun_l13_n737 +end + +def fun_l12_n183() + fun_l13_n993 +end + +def fun_l12_n184() + fun_l13_n806 +end + +def fun_l12_n185() + fun_l13_n45 +end + +def fun_l12_n186() + fun_l13_n30 +end + +def fun_l12_n187() + fun_l13_n774 +end + +def fun_l12_n188() + fun_l13_n715 +end + +def fun_l12_n189() + fun_l13_n351 +end + +def fun_l12_n190() + fun_l13_n173 +end + +def fun_l12_n191() + fun_l13_n574 +end + +def fun_l12_n192() + fun_l13_n768 +end + +def fun_l12_n193() + fun_l13_n514 +end + +def fun_l12_n194() + fun_l13_n505 +end + +def fun_l12_n195() + fun_l13_n460 +end + +def fun_l12_n196() + fun_l13_n377 +end + +def fun_l12_n197() + fun_l13_n275 +end + +def fun_l12_n198() + fun_l13_n642 +end + +def fun_l12_n199() + fun_l13_n746 +end + +def fun_l12_n200() + fun_l13_n507 +end + +def fun_l12_n201() + fun_l13_n576 +end + +def fun_l12_n202() + fun_l13_n899 +end + +def fun_l12_n203() + fun_l13_n88 +end + +def fun_l12_n204() + fun_l13_n735 +end + +def fun_l12_n205() + fun_l13_n270 +end + +def fun_l12_n206() + fun_l13_n398 +end + +def fun_l12_n207() + fun_l13_n98 +end + +def fun_l12_n208() + fun_l13_n272 +end + +def fun_l12_n209() + fun_l13_n493 +end + +def fun_l12_n210() + fun_l13_n893 +end + +def fun_l12_n211() + fun_l13_n550 +end + +def fun_l12_n212() + fun_l13_n428 +end + +def fun_l12_n213() + fun_l13_n20 +end + +def fun_l12_n214() + fun_l13_n437 +end + +def fun_l12_n215() + fun_l13_n964 +end + +def fun_l12_n216() + fun_l13_n880 +end + +def fun_l12_n217() + fun_l13_n119 +end + +def fun_l12_n218() + fun_l13_n125 +end + +def fun_l12_n219() + fun_l13_n48 +end + +def fun_l12_n220() + fun_l13_n749 +end + +def fun_l12_n221() + fun_l13_n65 +end + +def fun_l12_n222() + fun_l13_n535 +end + +def fun_l12_n223() + fun_l13_n770 +end + +def fun_l12_n224() + fun_l13_n118 +end + +def fun_l12_n225() + fun_l13_n859 +end + +def fun_l12_n226() + fun_l13_n768 +end + +def fun_l12_n227() + fun_l13_n981 +end + +def fun_l12_n228() + fun_l13_n518 +end + +def fun_l12_n229() + fun_l13_n361 +end + +def fun_l12_n230() + fun_l13_n255 +end + +def fun_l12_n231() + fun_l13_n922 +end + +def fun_l12_n232() + fun_l13_n375 +end + +def fun_l12_n233() + fun_l13_n265 +end + +def fun_l12_n234() + fun_l13_n832 +end + +def fun_l12_n235() + fun_l13_n147 +end + +def fun_l12_n236() + fun_l13_n162 +end + +def fun_l12_n237() + fun_l13_n832 +end + +def fun_l12_n238() + fun_l13_n930 +end + +def fun_l12_n239() + fun_l13_n429 +end + +def fun_l12_n240() + fun_l13_n429 +end + +def fun_l12_n241() + fun_l13_n152 +end + +def fun_l12_n242() + fun_l13_n287 +end + +def fun_l12_n243() + fun_l13_n140 +end + +def fun_l12_n244() + fun_l13_n994 +end + +def fun_l12_n245() + fun_l13_n815 +end + +def fun_l12_n246() + fun_l13_n865 +end + +def fun_l12_n247() + fun_l13_n613 +end + +def fun_l12_n248() + fun_l13_n347 +end + +def fun_l12_n249() + fun_l13_n959 +end + +def fun_l12_n250() + fun_l13_n870 +end + +def fun_l12_n251() + fun_l13_n167 +end + +def fun_l12_n252() + fun_l13_n860 +end + +def fun_l12_n253() + fun_l13_n897 +end + +def fun_l12_n254() + fun_l13_n605 +end + +def fun_l12_n255() + fun_l13_n136 +end + +def fun_l12_n256() + fun_l13_n636 +end + +def fun_l12_n257() + fun_l13_n60 +end + +def fun_l12_n258() + fun_l13_n925 +end + +def fun_l12_n259() + fun_l13_n472 +end + +def fun_l12_n260() + fun_l13_n423 +end + +def fun_l12_n261() + fun_l13_n798 +end + +def fun_l12_n262() + fun_l13_n381 +end + +def fun_l12_n263() + fun_l13_n922 +end + +def fun_l12_n264() + fun_l13_n923 +end + +def fun_l12_n265() + fun_l13_n644 +end + +def fun_l12_n266() + fun_l13_n334 +end + +def fun_l12_n267() + fun_l13_n201 +end + +def fun_l12_n268() + fun_l13_n690 +end + +def fun_l12_n269() + fun_l13_n699 +end + +def fun_l12_n270() + fun_l13_n269 +end + +def fun_l12_n271() + fun_l13_n582 +end + +def fun_l12_n272() + fun_l13_n513 +end + +def fun_l12_n273() + fun_l13_n723 +end + +def fun_l12_n274() + fun_l13_n757 +end + +def fun_l12_n275() + fun_l13_n390 +end + +def fun_l12_n276() + fun_l13_n459 +end + +def fun_l12_n277() + fun_l13_n973 +end + +def fun_l12_n278() + fun_l13_n762 +end + +def fun_l12_n279() + fun_l13_n829 +end + +def fun_l12_n280() + fun_l13_n706 +end + +def fun_l12_n281() + fun_l13_n769 +end + +def fun_l12_n282() + fun_l13_n736 +end + +def fun_l12_n283() + fun_l13_n931 +end + +def fun_l12_n284() + fun_l13_n226 +end + +def fun_l12_n285() + fun_l13_n688 +end + +def fun_l12_n286() + fun_l13_n74 +end + +def fun_l12_n287() + fun_l13_n470 +end + +def fun_l12_n288() + fun_l13_n932 +end + +def fun_l12_n289() + fun_l13_n923 +end + +def fun_l12_n290() + fun_l13_n53 +end + +def fun_l12_n291() + fun_l13_n113 +end + +def fun_l12_n292() + fun_l13_n115 +end + +def fun_l12_n293() + fun_l13_n864 +end + +def fun_l12_n294() + fun_l13_n503 +end + +def fun_l12_n295() + fun_l13_n998 +end + +def fun_l12_n296() + fun_l13_n637 +end + +def fun_l12_n297() + fun_l13_n655 +end + +def fun_l12_n298() + fun_l13_n50 +end + +def fun_l12_n299() + fun_l13_n564 +end + +def fun_l12_n300() + fun_l13_n39 +end + +def fun_l12_n301() + fun_l13_n836 +end + +def fun_l12_n302() + fun_l13_n85 +end + +def fun_l12_n303() + fun_l13_n992 +end + +def fun_l12_n304() + fun_l13_n956 +end + +def fun_l12_n305() + fun_l13_n746 +end + +def fun_l12_n306() + fun_l13_n281 +end + +def fun_l12_n307() + fun_l13_n790 +end + +def fun_l12_n308() + fun_l13_n69 +end + +def fun_l12_n309() + fun_l13_n296 +end + +def fun_l12_n310() + fun_l13_n239 +end + +def fun_l12_n311() + fun_l13_n451 +end + +def fun_l12_n312() + fun_l13_n756 +end + +def fun_l12_n313() + fun_l13_n339 +end + +def fun_l12_n314() + fun_l13_n438 +end + +def fun_l12_n315() + fun_l13_n840 +end + +def fun_l12_n316() + fun_l13_n903 +end + +def fun_l12_n317() + fun_l13_n506 +end + +def fun_l12_n318() + fun_l13_n529 +end + +def fun_l12_n319() + fun_l13_n242 +end + +def fun_l12_n320() + fun_l13_n658 +end + +def fun_l12_n321() + fun_l13_n34 +end + +def fun_l12_n322() + fun_l13_n89 +end + +def fun_l12_n323() + fun_l13_n29 +end + +def fun_l12_n324() + fun_l13_n981 +end + +def fun_l12_n325() + fun_l13_n463 +end + +def fun_l12_n326() + fun_l13_n889 +end + +def fun_l12_n327() + fun_l13_n583 +end + +def fun_l12_n328() + fun_l13_n291 +end + +def fun_l12_n329() + fun_l13_n618 +end + +def fun_l12_n330() + fun_l13_n660 +end + +def fun_l12_n331() + fun_l13_n545 +end + +def fun_l12_n332() + fun_l13_n817 +end + +def fun_l12_n333() + fun_l13_n399 +end + +def fun_l12_n334() + fun_l13_n579 +end + +def fun_l12_n335() + fun_l13_n508 +end + +def fun_l12_n336() + fun_l13_n979 +end + +def fun_l12_n337() + fun_l13_n826 +end + +def fun_l12_n338() + fun_l13_n18 +end + +def fun_l12_n339() + fun_l13_n218 +end + +def fun_l12_n340() + fun_l13_n344 +end + +def fun_l12_n341() + fun_l13_n280 +end + +def fun_l12_n342() + fun_l13_n244 +end + +def fun_l12_n343() + fun_l13_n857 +end + +def fun_l12_n344() + fun_l13_n301 +end + +def fun_l12_n345() + fun_l13_n428 +end + +def fun_l12_n346() + fun_l13_n192 +end + +def fun_l12_n347() + fun_l13_n155 +end + +def fun_l12_n348() + fun_l13_n414 +end + +def fun_l12_n349() + fun_l13_n196 +end + +def fun_l12_n350() + fun_l13_n824 +end + +def fun_l12_n351() + fun_l13_n901 +end + +def fun_l12_n352() + fun_l13_n705 +end + +def fun_l12_n353() + fun_l13_n872 +end + +def fun_l12_n354() + fun_l13_n82 +end + +def fun_l12_n355() + fun_l13_n664 +end + +def fun_l12_n356() + fun_l13_n948 +end + +def fun_l12_n357() + fun_l13_n430 +end + +def fun_l12_n358() + fun_l13_n716 +end + +def fun_l12_n359() + fun_l13_n319 +end + +def fun_l12_n360() + fun_l13_n680 +end + +def fun_l12_n361() + fun_l13_n961 +end + +def fun_l12_n362() + fun_l13_n347 +end + +def fun_l12_n363() + fun_l13_n164 +end + +def fun_l12_n364() + fun_l13_n849 +end + +def fun_l12_n365() + fun_l13_n448 +end + +def fun_l12_n366() + fun_l13_n622 +end + +def fun_l12_n367() + fun_l13_n191 +end + +def fun_l12_n368() + fun_l13_n818 +end + +def fun_l12_n369() + fun_l13_n525 +end + +def fun_l12_n370() + fun_l13_n343 +end + +def fun_l12_n371() + fun_l13_n789 +end + +def fun_l12_n372() + fun_l13_n811 +end + +def fun_l12_n373() + fun_l13_n503 +end + +def fun_l12_n374() + fun_l13_n529 +end + +def fun_l12_n375() + fun_l13_n471 +end + +def fun_l12_n376() + fun_l13_n654 +end + +def fun_l12_n377() + fun_l13_n155 +end + +def fun_l12_n378() + fun_l13_n79 +end + +def fun_l12_n379() + fun_l13_n545 +end + +def fun_l12_n380() + fun_l13_n315 +end + +def fun_l12_n381() + fun_l13_n655 +end + +def fun_l12_n382() + fun_l13_n450 +end + +def fun_l12_n383() + fun_l13_n353 +end + +def fun_l12_n384() + fun_l13_n700 +end + +def fun_l12_n385() + fun_l13_n524 +end + +def fun_l12_n386() + fun_l13_n158 +end + +def fun_l12_n387() + fun_l13_n880 +end + +def fun_l12_n388() + fun_l13_n366 +end + +def fun_l12_n389() + fun_l13_n848 +end + +def fun_l12_n390() + fun_l13_n45 +end + +def fun_l12_n391() + fun_l13_n318 +end + +def fun_l12_n392() + fun_l13_n331 +end + +def fun_l12_n393() + fun_l13_n528 +end + +def fun_l12_n394() + fun_l13_n789 +end + +def fun_l12_n395() + fun_l13_n71 +end + +def fun_l12_n396() + fun_l13_n317 +end + +def fun_l12_n397() + fun_l13_n671 +end + +def fun_l12_n398() + fun_l13_n788 +end + +def fun_l12_n399() + fun_l13_n276 +end + +def fun_l12_n400() + fun_l13_n34 +end + +def fun_l12_n401() + fun_l13_n321 +end + +def fun_l12_n402() + fun_l13_n737 +end + +def fun_l12_n403() + fun_l13_n900 +end + +def fun_l12_n404() + fun_l13_n491 +end + +def fun_l12_n405() + fun_l13_n826 +end + +def fun_l12_n406() + fun_l13_n124 +end + +def fun_l12_n407() + fun_l13_n658 +end + +def fun_l12_n408() + fun_l13_n159 +end + +def fun_l12_n409() + fun_l13_n481 +end + +def fun_l12_n410() + fun_l13_n900 +end + +def fun_l12_n411() + fun_l13_n481 +end + +def fun_l12_n412() + fun_l13_n252 +end + +def fun_l12_n413() + fun_l13_n732 +end + +def fun_l12_n414() + fun_l13_n94 +end + +def fun_l12_n415() + fun_l13_n699 +end + +def fun_l12_n416() + fun_l13_n638 +end + +def fun_l12_n417() + fun_l13_n108 +end + +def fun_l12_n418() + fun_l13_n731 +end + +def fun_l12_n419() + fun_l13_n965 +end + +def fun_l12_n420() + fun_l13_n704 +end + +def fun_l12_n421() + fun_l13_n710 +end + +def fun_l12_n422() + fun_l13_n888 +end + +def fun_l12_n423() + fun_l13_n331 +end + +def fun_l12_n424() + fun_l13_n586 +end + +def fun_l12_n425() + fun_l13_n302 +end + +def fun_l12_n426() + fun_l13_n514 +end + +def fun_l12_n427() + fun_l13_n533 +end + +def fun_l12_n428() + fun_l13_n759 +end + +def fun_l12_n429() + fun_l13_n652 +end + +def fun_l12_n430() + fun_l13_n600 +end + +def fun_l12_n431() + fun_l13_n808 +end + +def fun_l12_n432() + fun_l13_n345 +end + +def fun_l12_n433() + fun_l13_n257 +end + +def fun_l12_n434() + fun_l13_n91 +end + +def fun_l12_n435() + fun_l13_n627 +end + +def fun_l12_n436() + fun_l13_n293 +end + +def fun_l12_n437() + fun_l13_n618 +end + +def fun_l12_n438() + fun_l13_n462 +end + +def fun_l12_n439() + fun_l13_n0 +end + +def fun_l12_n440() + fun_l13_n32 +end + +def fun_l12_n441() + fun_l13_n4 +end + +def fun_l12_n442() + fun_l13_n257 +end + +def fun_l12_n443() + fun_l13_n548 +end + +def fun_l12_n444() + fun_l13_n300 +end + +def fun_l12_n445() + fun_l13_n253 +end + +def fun_l12_n446() + fun_l13_n603 +end + +def fun_l12_n447() + fun_l13_n295 +end + +def fun_l12_n448() + fun_l13_n921 +end + +def fun_l12_n449() + fun_l13_n119 +end + +def fun_l12_n450() + fun_l13_n51 +end + +def fun_l12_n451() + fun_l13_n544 +end + +def fun_l12_n452() + fun_l13_n735 +end + +def fun_l12_n453() + fun_l13_n20 +end + +def fun_l12_n454() + fun_l13_n285 +end + +def fun_l12_n455() + fun_l13_n370 +end + +def fun_l12_n456() + fun_l13_n245 +end + +def fun_l12_n457() + fun_l13_n909 +end + +def fun_l12_n458() + fun_l13_n536 +end + +def fun_l12_n459() + fun_l13_n665 +end + +def fun_l12_n460() + fun_l13_n95 +end + +def fun_l12_n461() + fun_l13_n499 +end + +def fun_l12_n462() + fun_l13_n105 +end + +def fun_l12_n463() + fun_l13_n300 +end + +def fun_l12_n464() + fun_l13_n49 +end + +def fun_l12_n465() + fun_l13_n567 +end + +def fun_l12_n466() + fun_l13_n197 +end + +def fun_l12_n467() + fun_l13_n918 +end + +def fun_l12_n468() + fun_l13_n735 +end + +def fun_l12_n469() + fun_l13_n415 +end + +def fun_l12_n470() + fun_l13_n580 +end + +def fun_l12_n471() + fun_l13_n119 +end + +def fun_l12_n472() + fun_l13_n699 +end + +def fun_l12_n473() + fun_l13_n128 +end + +def fun_l12_n474() + fun_l13_n251 +end + +def fun_l12_n475() + fun_l13_n986 +end + +def fun_l12_n476() + fun_l13_n55 +end + +def fun_l12_n477() + fun_l13_n394 +end + +def fun_l12_n478() + fun_l13_n564 +end + +def fun_l12_n479() + fun_l13_n927 +end + +def fun_l12_n480() + fun_l13_n614 +end + +def fun_l12_n481() + fun_l13_n425 +end + +def fun_l12_n482() + fun_l13_n55 +end + +def fun_l12_n483() + fun_l13_n212 +end + +def fun_l12_n484() + fun_l13_n712 +end + +def fun_l12_n485() + fun_l13_n393 +end + +def fun_l12_n486() + fun_l13_n891 +end + +def fun_l12_n487() + fun_l13_n54 +end + +def fun_l12_n488() + fun_l13_n508 +end + +def fun_l12_n489() + fun_l13_n266 +end + +def fun_l12_n490() + fun_l13_n637 +end + +def fun_l12_n491() + fun_l13_n683 +end + +def fun_l12_n492() + fun_l13_n499 +end + +def fun_l12_n493() + fun_l13_n770 +end + +def fun_l12_n494() + fun_l13_n254 +end + +def fun_l12_n495() + fun_l13_n801 +end + +def fun_l12_n496() + fun_l13_n75 +end + +def fun_l12_n497() + fun_l13_n652 +end + +def fun_l12_n498() + fun_l13_n638 +end + +def fun_l12_n499() + fun_l13_n515 +end + +def fun_l12_n500() + fun_l13_n580 +end + +def fun_l12_n501() + fun_l13_n198 +end + +def fun_l12_n502() + fun_l13_n723 +end + +def fun_l12_n503() + fun_l13_n855 +end + +def fun_l12_n504() + fun_l13_n969 +end + +def fun_l12_n505() + fun_l13_n16 +end + +def fun_l12_n506() + fun_l13_n477 +end + +def fun_l12_n507() + fun_l13_n873 +end + +def fun_l12_n508() + fun_l13_n456 +end + +def fun_l12_n509() + fun_l13_n711 +end + +def fun_l12_n510() + fun_l13_n979 +end + +def fun_l12_n511() + fun_l13_n830 +end + +def fun_l12_n512() + fun_l13_n336 +end + +def fun_l12_n513() + fun_l13_n579 +end + +def fun_l12_n514() + fun_l13_n128 +end + +def fun_l12_n515() + fun_l13_n977 +end + +def fun_l12_n516() + fun_l13_n870 +end + +def fun_l12_n517() + fun_l13_n133 +end + +def fun_l12_n518() + fun_l13_n315 +end + +def fun_l12_n519() + fun_l13_n324 +end + +def fun_l12_n520() + fun_l13_n721 +end + +def fun_l12_n521() + fun_l13_n392 +end + +def fun_l12_n522() + fun_l13_n945 +end + +def fun_l12_n523() + fun_l13_n497 +end + +def fun_l12_n524() + fun_l13_n999 +end + +def fun_l12_n525() + fun_l13_n152 +end + +def fun_l12_n526() + fun_l13_n535 +end + +def fun_l12_n527() + fun_l13_n938 +end + +def fun_l12_n528() + fun_l13_n813 +end + +def fun_l12_n529() + fun_l13_n497 +end + +def fun_l12_n530() + fun_l13_n700 +end + +def fun_l12_n531() + fun_l13_n493 +end + +def fun_l12_n532() + fun_l13_n549 +end + +def fun_l12_n533() + fun_l13_n406 +end + +def fun_l12_n534() + fun_l13_n918 +end + +def fun_l12_n535() + fun_l13_n891 +end + +def fun_l12_n536() + fun_l13_n924 +end + +def fun_l12_n537() + fun_l13_n753 +end + +def fun_l12_n538() + fun_l13_n582 +end + +def fun_l12_n539() + fun_l13_n769 +end + +def fun_l12_n540() + fun_l13_n297 +end + +def fun_l12_n541() + fun_l13_n261 +end + +def fun_l12_n542() + fun_l13_n581 +end + +def fun_l12_n543() + fun_l13_n667 +end + +def fun_l12_n544() + fun_l13_n955 +end + +def fun_l12_n545() + fun_l13_n296 +end + +def fun_l12_n546() + fun_l13_n762 +end + +def fun_l12_n547() + fun_l13_n755 +end + +def fun_l12_n548() + fun_l13_n369 +end + +def fun_l12_n549() + fun_l13_n685 +end + +def fun_l12_n550() + fun_l13_n675 +end + +def fun_l12_n551() + fun_l13_n430 +end + +def fun_l12_n552() + fun_l13_n530 +end + +def fun_l12_n553() + fun_l13_n17 +end + +def fun_l12_n554() + fun_l13_n406 +end + +def fun_l12_n555() + fun_l13_n687 +end + +def fun_l12_n556() + fun_l13_n972 +end + +def fun_l12_n557() + fun_l13_n561 +end + +def fun_l12_n558() + fun_l13_n202 +end + +def fun_l12_n559() + fun_l13_n788 +end + +def fun_l12_n560() + fun_l13_n705 +end + +def fun_l12_n561() + fun_l13_n434 +end + +def fun_l12_n562() + fun_l13_n965 +end + +def fun_l12_n563() + fun_l13_n525 +end + +def fun_l12_n564() + fun_l13_n938 +end + +def fun_l12_n565() + fun_l13_n346 +end + +def fun_l12_n566() + fun_l13_n95 +end + +def fun_l12_n567() + fun_l13_n458 +end + +def fun_l12_n568() + fun_l13_n769 +end + +def fun_l12_n569() + fun_l13_n858 +end + +def fun_l12_n570() + fun_l13_n230 +end + +def fun_l12_n571() + fun_l13_n977 +end + +def fun_l12_n572() + fun_l13_n304 +end + +def fun_l12_n573() + fun_l13_n271 +end + +def fun_l12_n574() + fun_l13_n106 +end + +def fun_l12_n575() + fun_l13_n733 +end + +def fun_l12_n576() + fun_l13_n197 +end + +def fun_l12_n577() + fun_l13_n624 +end + +def fun_l12_n578() + fun_l13_n844 +end + +def fun_l12_n579() + fun_l13_n268 +end + +def fun_l12_n580() + fun_l13_n394 +end + +def fun_l12_n581() + fun_l13_n573 +end + +def fun_l12_n582() + fun_l13_n950 +end + +def fun_l12_n583() + fun_l13_n163 +end + +def fun_l12_n584() + fun_l13_n458 +end + +def fun_l12_n585() + fun_l13_n569 +end + +def fun_l12_n586() + fun_l13_n808 +end + +def fun_l12_n587() + fun_l13_n830 +end + +def fun_l12_n588() + fun_l13_n328 +end + +def fun_l12_n589() + fun_l13_n235 +end + +def fun_l12_n590() + fun_l13_n695 +end + +def fun_l12_n591() + fun_l13_n543 +end + +def fun_l12_n592() + fun_l13_n635 +end + +def fun_l12_n593() + fun_l13_n783 +end + +def fun_l12_n594() + fun_l13_n349 +end + +def fun_l12_n595() + fun_l13_n108 +end + +def fun_l12_n596() + fun_l13_n856 +end + +def fun_l12_n597() + fun_l13_n743 +end + +def fun_l12_n598() + fun_l13_n640 +end + +def fun_l12_n599() + fun_l13_n768 +end + +def fun_l12_n600() + fun_l13_n798 +end + +def fun_l12_n601() + fun_l13_n941 +end + +def fun_l12_n602() + fun_l13_n389 +end + +def fun_l12_n603() + fun_l13_n624 +end + +def fun_l12_n604() + fun_l13_n209 +end + +def fun_l12_n605() + fun_l13_n636 +end + +def fun_l12_n606() + fun_l13_n741 +end + +def fun_l12_n607() + fun_l13_n461 +end + +def fun_l12_n608() + fun_l13_n570 +end + +def fun_l12_n609() + fun_l13_n358 +end + +def fun_l12_n610() + fun_l13_n408 +end + +def fun_l12_n611() + fun_l13_n693 +end + +def fun_l12_n612() + fun_l13_n760 +end + +def fun_l12_n613() + fun_l13_n402 +end + +def fun_l12_n614() + fun_l13_n20 +end + +def fun_l12_n615() + fun_l13_n15 +end + +def fun_l12_n616() + fun_l13_n931 +end + +def fun_l12_n617() + fun_l13_n58 +end + +def fun_l12_n618() + fun_l13_n627 +end + +def fun_l12_n619() + fun_l13_n149 +end + +def fun_l12_n620() + fun_l13_n200 +end + +def fun_l12_n621() + fun_l13_n832 +end + +def fun_l12_n622() + fun_l13_n605 +end + +def fun_l12_n623() + fun_l13_n868 +end + +def fun_l12_n624() + fun_l13_n480 +end + +def fun_l12_n625() + fun_l13_n991 +end + +def fun_l12_n626() + fun_l13_n493 +end + +def fun_l12_n627() + fun_l13_n2 +end + +def fun_l12_n628() + fun_l13_n851 +end + +def fun_l12_n629() + fun_l13_n864 +end + +def fun_l12_n630() + fun_l13_n293 +end + +def fun_l12_n631() + fun_l13_n909 +end + +def fun_l12_n632() + fun_l13_n955 +end + +def fun_l12_n633() + fun_l13_n276 +end + +def fun_l12_n634() + fun_l13_n345 +end + +def fun_l12_n635() + fun_l13_n606 +end + +def fun_l12_n636() + fun_l13_n685 +end + +def fun_l12_n637() + fun_l13_n989 +end + +def fun_l12_n638() + fun_l13_n920 +end + +def fun_l12_n639() + fun_l13_n702 +end + +def fun_l12_n640() + fun_l13_n6 +end + +def fun_l12_n641() + fun_l13_n216 +end + +def fun_l12_n642() + fun_l13_n501 +end + +def fun_l12_n643() + fun_l13_n500 +end + +def fun_l12_n644() + fun_l13_n845 +end + +def fun_l12_n645() + fun_l13_n758 +end + +def fun_l12_n646() + fun_l13_n999 +end + +def fun_l12_n647() + fun_l13_n30 +end + +def fun_l12_n648() + fun_l13_n670 +end + +def fun_l12_n649() + fun_l13_n551 +end + +def fun_l12_n650() + fun_l13_n668 +end + +def fun_l12_n651() + fun_l13_n51 +end + +def fun_l12_n652() + fun_l13_n35 +end + +def fun_l12_n653() + fun_l13_n523 +end + +def fun_l12_n654() + fun_l13_n118 +end + +def fun_l12_n655() + fun_l13_n49 +end + +def fun_l12_n656() + fun_l13_n457 +end + +def fun_l12_n657() + fun_l13_n669 +end + +def fun_l12_n658() + fun_l13_n93 +end + +def fun_l12_n659() + fun_l13_n809 +end + +def fun_l12_n660() + fun_l13_n759 +end + +def fun_l12_n661() + fun_l13_n224 +end + +def fun_l12_n662() + fun_l13_n876 +end + +def fun_l12_n663() + fun_l13_n784 +end + +def fun_l12_n664() + fun_l13_n39 +end + +def fun_l12_n665() + fun_l13_n930 +end + +def fun_l12_n666() + fun_l13_n250 +end + +def fun_l12_n667() + fun_l13_n247 +end + +def fun_l12_n668() + fun_l13_n907 +end + +def fun_l12_n669() + fun_l13_n333 +end + +def fun_l12_n670() + fun_l13_n97 +end + +def fun_l12_n671() + fun_l13_n475 +end + +def fun_l12_n672() + fun_l13_n480 +end + +def fun_l12_n673() + fun_l13_n943 +end + +def fun_l12_n674() + fun_l13_n263 +end + +def fun_l12_n675() + fun_l13_n879 +end + +def fun_l12_n676() + fun_l13_n537 +end + +def fun_l12_n677() + fun_l13_n475 +end + +def fun_l12_n678() + fun_l13_n626 +end + +def fun_l12_n679() + fun_l13_n397 +end + +def fun_l12_n680() + fun_l13_n194 +end + +def fun_l12_n681() + fun_l13_n468 +end + +def fun_l12_n682() + fun_l13_n566 +end + +def fun_l12_n683() + fun_l13_n573 +end + +def fun_l12_n684() + fun_l13_n354 +end + +def fun_l12_n685() + fun_l13_n251 +end + +def fun_l12_n686() + fun_l13_n626 +end + +def fun_l12_n687() + fun_l13_n954 +end + +def fun_l12_n688() + fun_l13_n732 +end + +def fun_l12_n689() + fun_l13_n543 +end + +def fun_l12_n690() + fun_l13_n878 +end + +def fun_l12_n691() + fun_l13_n520 +end + +def fun_l12_n692() + fun_l13_n262 +end + +def fun_l12_n693() + fun_l13_n179 +end + +def fun_l12_n694() + fun_l13_n851 +end + +def fun_l12_n695() + fun_l13_n821 +end + +def fun_l12_n696() + fun_l13_n951 +end + +def fun_l12_n697() + fun_l13_n707 +end + +def fun_l12_n698() + fun_l13_n388 +end + +def fun_l12_n699() + fun_l13_n660 +end + +def fun_l12_n700() + fun_l13_n658 +end + +def fun_l12_n701() + fun_l13_n463 +end + +def fun_l12_n702() + fun_l13_n547 +end + +def fun_l12_n703() + fun_l13_n319 +end + +def fun_l12_n704() + fun_l13_n405 +end + +def fun_l12_n705() + fun_l13_n645 +end + +def fun_l12_n706() + fun_l13_n147 +end + +def fun_l12_n707() + fun_l13_n582 +end + +def fun_l12_n708() + fun_l13_n618 +end + +def fun_l12_n709() + fun_l13_n156 +end + +def fun_l12_n710() + fun_l13_n606 +end + +def fun_l12_n711() + fun_l13_n525 +end + +def fun_l12_n712() + fun_l13_n513 +end + +def fun_l12_n713() + fun_l13_n827 +end + +def fun_l12_n714() + fun_l13_n438 +end + +def fun_l12_n715() + fun_l13_n72 +end + +def fun_l12_n716() + fun_l13_n364 +end + +def fun_l12_n717() + fun_l13_n380 +end + +def fun_l12_n718() + fun_l13_n898 +end + +def fun_l12_n719() + fun_l13_n998 +end + +def fun_l12_n720() + fun_l13_n679 +end + +def fun_l12_n721() + fun_l13_n738 +end + +def fun_l12_n722() + fun_l13_n887 +end + +def fun_l12_n723() + fun_l13_n73 +end + +def fun_l12_n724() + fun_l13_n309 +end + +def fun_l12_n725() + fun_l13_n791 +end + +def fun_l12_n726() + fun_l13_n939 +end + +def fun_l12_n727() + fun_l13_n27 +end + +def fun_l12_n728() + fun_l13_n269 +end + +def fun_l12_n729() + fun_l13_n418 +end + +def fun_l12_n730() + fun_l13_n659 +end + +def fun_l12_n731() + fun_l13_n257 +end + +def fun_l12_n732() + fun_l13_n519 +end + +def fun_l12_n733() + fun_l13_n305 +end + +def fun_l12_n734() + fun_l13_n994 +end + +def fun_l12_n735() + fun_l13_n159 +end + +def fun_l12_n736() + fun_l13_n704 +end + +def fun_l12_n737() + fun_l13_n826 +end + +def fun_l12_n738() + fun_l13_n204 +end + +def fun_l12_n739() + fun_l13_n886 +end + +def fun_l12_n740() + fun_l13_n403 +end + +def fun_l12_n741() + fun_l13_n567 +end + +def fun_l12_n742() + fun_l13_n425 +end + +def fun_l12_n743() + fun_l13_n174 +end + +def fun_l12_n744() + fun_l13_n530 +end + +def fun_l12_n745() + fun_l13_n143 +end + +def fun_l12_n746() + fun_l13_n950 +end + +def fun_l12_n747() + fun_l13_n982 +end + +def fun_l12_n748() + fun_l13_n340 +end + +def fun_l12_n749() + fun_l13_n964 +end + +def fun_l12_n750() + fun_l13_n747 +end + +def fun_l12_n751() + fun_l13_n886 +end + +def fun_l12_n752() + fun_l13_n148 +end + +def fun_l12_n753() + fun_l13_n675 +end + +def fun_l12_n754() + fun_l13_n69 +end + +def fun_l12_n755() + fun_l13_n992 +end + +def fun_l12_n756() + fun_l13_n126 +end + +def fun_l12_n757() + fun_l13_n919 +end + +def fun_l12_n758() + fun_l13_n286 +end + +def fun_l12_n759() + fun_l13_n472 +end + +def fun_l12_n760() + fun_l13_n35 +end + +def fun_l12_n761() + fun_l13_n130 +end + +def fun_l12_n762() + fun_l13_n394 +end + +def fun_l12_n763() + fun_l13_n372 +end + +def fun_l12_n764() + fun_l13_n630 +end + +def fun_l12_n765() + fun_l13_n439 +end + +def fun_l12_n766() + fun_l13_n973 +end + +def fun_l12_n767() + fun_l13_n859 +end + +def fun_l12_n768() + fun_l13_n903 +end + +def fun_l12_n769() + fun_l13_n441 +end + +def fun_l12_n770() + fun_l13_n530 +end + +def fun_l12_n771() + fun_l13_n584 +end + +def fun_l12_n772() + fun_l13_n676 +end + +def fun_l12_n773() + fun_l13_n595 +end + +def fun_l12_n774() + fun_l13_n523 +end + +def fun_l12_n775() + fun_l13_n619 +end + +def fun_l12_n776() + fun_l13_n727 +end + +def fun_l12_n777() + fun_l13_n793 +end + +def fun_l12_n778() + fun_l13_n55 +end + +def fun_l12_n779() + fun_l13_n675 +end + +def fun_l12_n780() + fun_l13_n779 +end + +def fun_l12_n781() + fun_l13_n413 +end + +def fun_l12_n782() + fun_l13_n148 +end + +def fun_l12_n783() + fun_l13_n149 +end + +def fun_l12_n784() + fun_l13_n242 +end + +def fun_l12_n785() + fun_l13_n619 +end + +def fun_l12_n786() + fun_l13_n171 +end + +def fun_l12_n787() + fun_l13_n646 +end + +def fun_l12_n788() + fun_l13_n470 +end + +def fun_l12_n789() + fun_l13_n812 +end + +def fun_l12_n790() + fun_l13_n891 +end + +def fun_l12_n791() + fun_l13_n958 +end + +def fun_l12_n792() + fun_l13_n451 +end + +def fun_l12_n793() + fun_l13_n651 +end + +def fun_l12_n794() + fun_l13_n904 +end + +def fun_l12_n795() + fun_l13_n400 +end + +def fun_l12_n796() + fun_l13_n286 +end + +def fun_l12_n797() + fun_l13_n17 +end + +def fun_l12_n798() + fun_l13_n280 +end + +def fun_l12_n799() + fun_l13_n19 +end + +def fun_l12_n800() + fun_l13_n909 +end + +def fun_l12_n801() + fun_l13_n434 +end + +def fun_l12_n802() + fun_l13_n920 +end + +def fun_l12_n803() + fun_l13_n196 +end + +def fun_l12_n804() + fun_l13_n374 +end + +def fun_l12_n805() + fun_l13_n393 +end + +def fun_l12_n806() + fun_l13_n623 +end + +def fun_l12_n807() + fun_l13_n846 +end + +def fun_l12_n808() + fun_l13_n354 +end + +def fun_l12_n809() + fun_l13_n16 +end + +def fun_l12_n810() + fun_l13_n371 +end + +def fun_l12_n811() + fun_l13_n139 +end + +def fun_l12_n812() + fun_l13_n156 +end + +def fun_l12_n813() + fun_l13_n799 +end + +def fun_l12_n814() + fun_l13_n817 +end + +def fun_l12_n815() + fun_l13_n475 +end + +def fun_l12_n816() + fun_l13_n799 +end + +def fun_l12_n817() + fun_l13_n838 +end + +def fun_l12_n818() + fun_l13_n297 +end + +def fun_l12_n819() + fun_l13_n834 +end + +def fun_l12_n820() + fun_l13_n788 +end + +def fun_l12_n821() + fun_l13_n649 +end + +def fun_l12_n822() + fun_l13_n908 +end + +def fun_l12_n823() + fun_l13_n264 +end + +def fun_l12_n824() + fun_l13_n66 +end + +def fun_l12_n825() + fun_l13_n367 +end + +def fun_l12_n826() + fun_l13_n569 +end + +def fun_l12_n827() + fun_l13_n735 +end + +def fun_l12_n828() + fun_l13_n704 +end + +def fun_l12_n829() + fun_l13_n440 +end + +def fun_l12_n830() + fun_l13_n126 +end + +def fun_l12_n831() + fun_l13_n590 +end + +def fun_l12_n832() + fun_l13_n485 +end + +def fun_l12_n833() + fun_l13_n869 +end + +def fun_l12_n834() + fun_l13_n691 +end + +def fun_l12_n835() + fun_l13_n912 +end + +def fun_l12_n836() + fun_l13_n618 +end + +def fun_l12_n837() + fun_l13_n64 +end + +def fun_l12_n838() + fun_l13_n927 +end + +def fun_l12_n839() + fun_l13_n500 +end + +def fun_l12_n840() + fun_l13_n280 +end + +def fun_l12_n841() + fun_l13_n272 +end + +def fun_l12_n842() + fun_l13_n66 +end + +def fun_l12_n843() + fun_l13_n169 +end + +def fun_l12_n844() + fun_l13_n568 +end + +def fun_l12_n845() + fun_l13_n678 +end + +def fun_l12_n846() + fun_l13_n269 +end + +def fun_l12_n847() + fun_l13_n936 +end + +def fun_l12_n848() + fun_l13_n34 +end + +def fun_l12_n849() + fun_l13_n475 +end + +def fun_l12_n850() + fun_l13_n558 +end + +def fun_l12_n851() + fun_l13_n779 +end + +def fun_l12_n852() + fun_l13_n421 +end + +def fun_l12_n853() + fun_l13_n339 +end + +def fun_l12_n854() + fun_l13_n266 +end + +def fun_l12_n855() + fun_l13_n346 +end + +def fun_l12_n856() + fun_l13_n247 +end + +def fun_l12_n857() + fun_l13_n608 +end + +def fun_l12_n858() + fun_l13_n878 +end + +def fun_l12_n859() + fun_l13_n89 +end + +def fun_l12_n860() + fun_l13_n380 +end + +def fun_l12_n861() + fun_l13_n859 +end + +def fun_l12_n862() + fun_l13_n955 +end + +def fun_l12_n863() + fun_l13_n392 +end + +def fun_l12_n864() + fun_l13_n43 +end + +def fun_l12_n865() + fun_l13_n506 +end + +def fun_l12_n866() + fun_l13_n45 +end + +def fun_l12_n867() + fun_l13_n898 +end + +def fun_l12_n868() + fun_l13_n1 +end + +def fun_l12_n869() + fun_l13_n159 +end + +def fun_l12_n870() + fun_l13_n265 +end + +def fun_l12_n871() + fun_l13_n540 +end + +def fun_l12_n872() + fun_l13_n563 +end + +def fun_l12_n873() + fun_l13_n845 +end + +def fun_l12_n874() + fun_l13_n753 +end + +def fun_l12_n875() + fun_l13_n815 +end + +def fun_l12_n876() + fun_l13_n483 +end + +def fun_l12_n877() + fun_l13_n868 +end + +def fun_l12_n878() + fun_l13_n961 +end + +def fun_l12_n879() + fun_l13_n688 +end + +def fun_l12_n880() + fun_l13_n357 +end + +def fun_l12_n881() + fun_l13_n543 +end + +def fun_l12_n882() + fun_l13_n965 +end + +def fun_l12_n883() + fun_l13_n977 +end + +def fun_l12_n884() + fun_l13_n185 +end + +def fun_l12_n885() + fun_l13_n734 +end + +def fun_l12_n886() + fun_l13_n343 +end + +def fun_l12_n887() + fun_l13_n43 +end + +def fun_l12_n888() + fun_l13_n248 +end + +def fun_l12_n889() + fun_l13_n943 +end + +def fun_l12_n890() + fun_l13_n504 +end + +def fun_l12_n891() + fun_l13_n330 +end + +def fun_l12_n892() + fun_l13_n898 +end + +def fun_l12_n893() + fun_l13_n495 +end + +def fun_l12_n894() + fun_l13_n180 +end + +def fun_l12_n895() + fun_l13_n134 +end + +def fun_l12_n896() + fun_l13_n883 +end + +def fun_l12_n897() + fun_l13_n881 +end + +def fun_l12_n898() + fun_l13_n376 +end + +def fun_l12_n899() + fun_l13_n840 +end + +def fun_l12_n900() + fun_l13_n784 +end + +def fun_l12_n901() + fun_l13_n694 +end + +def fun_l12_n902() + fun_l13_n431 +end + +def fun_l12_n903() + fun_l13_n16 +end + +def fun_l12_n904() + fun_l13_n192 +end + +def fun_l12_n905() + fun_l13_n932 +end + +def fun_l12_n906() + fun_l13_n160 +end + +def fun_l12_n907() + fun_l13_n426 +end + +def fun_l12_n908() + fun_l13_n283 +end + +def fun_l12_n909() + fun_l13_n569 +end + +def fun_l12_n910() + fun_l13_n206 +end + +def fun_l12_n911() + fun_l13_n741 +end + +def fun_l12_n912() + fun_l13_n173 +end + +def fun_l12_n913() + fun_l13_n272 +end + +def fun_l12_n914() + fun_l13_n172 +end + +def fun_l12_n915() + fun_l13_n63 +end + +def fun_l12_n916() + fun_l13_n749 +end + +def fun_l12_n917() + fun_l13_n450 +end + +def fun_l12_n918() + fun_l13_n53 +end + +def fun_l12_n919() + fun_l13_n331 +end + +def fun_l12_n920() + fun_l13_n186 +end + +def fun_l12_n921() + fun_l13_n454 +end + +def fun_l12_n922() + fun_l13_n763 +end + +def fun_l12_n923() + fun_l13_n124 +end + +def fun_l12_n924() + fun_l13_n134 +end + +def fun_l12_n925() + fun_l13_n38 +end + +def fun_l12_n926() + fun_l13_n645 +end + +def fun_l12_n927() + fun_l13_n683 +end + +def fun_l12_n928() + fun_l13_n859 +end + +def fun_l12_n929() + fun_l13_n406 +end + +def fun_l12_n930() + fun_l13_n534 +end + +def fun_l12_n931() + fun_l13_n72 +end + +def fun_l12_n932() + fun_l13_n288 +end + +def fun_l12_n933() + fun_l13_n3 +end + +def fun_l12_n934() + fun_l13_n852 +end + +def fun_l12_n935() + fun_l13_n290 +end + +def fun_l12_n936() + fun_l13_n237 +end + +def fun_l12_n937() + fun_l13_n674 +end + +def fun_l12_n938() + fun_l13_n278 +end + +def fun_l12_n939() + fun_l13_n579 +end + +def fun_l12_n940() + fun_l13_n736 +end + +def fun_l12_n941() + fun_l13_n684 +end + +def fun_l12_n942() + fun_l13_n744 +end + +def fun_l12_n943() + fun_l13_n726 +end + +def fun_l12_n944() + fun_l13_n767 +end + +def fun_l12_n945() + fun_l13_n466 +end + +def fun_l12_n946() + fun_l13_n679 +end + +def fun_l12_n947() + fun_l13_n774 +end + +def fun_l12_n948() + fun_l13_n104 +end + +def fun_l12_n949() + fun_l13_n744 +end + +def fun_l12_n950() + fun_l13_n339 +end + +def fun_l12_n951() + fun_l13_n848 +end + +def fun_l12_n952() + fun_l13_n194 +end + +def fun_l12_n953() + fun_l13_n733 +end + +def fun_l12_n954() + fun_l13_n430 +end + +def fun_l12_n955() + fun_l13_n95 +end + +def fun_l12_n956() + fun_l13_n68 +end + +def fun_l12_n957() + fun_l13_n951 +end + +def fun_l12_n958() + fun_l13_n671 +end + +def fun_l12_n959() + fun_l13_n464 +end + +def fun_l12_n960() + fun_l13_n700 +end + +def fun_l12_n961() + fun_l13_n662 +end + +def fun_l12_n962() + fun_l13_n765 +end + +def fun_l12_n963() + fun_l13_n662 +end + +def fun_l12_n964() + fun_l13_n750 +end + +def fun_l12_n965() + fun_l13_n935 +end + +def fun_l12_n966() + fun_l13_n585 +end + +def fun_l12_n967() + fun_l13_n430 +end + +def fun_l12_n968() + fun_l13_n219 +end + +def fun_l12_n969() + fun_l13_n895 +end + +def fun_l12_n970() + fun_l13_n47 +end + +def fun_l12_n971() + fun_l13_n755 +end + +def fun_l12_n972() + fun_l13_n56 +end + +def fun_l12_n973() + fun_l13_n341 +end + +def fun_l12_n974() + fun_l13_n192 +end + +def fun_l12_n975() + fun_l13_n434 +end + +def fun_l12_n976() + fun_l13_n215 +end + +def fun_l12_n977() + fun_l13_n747 +end + +def fun_l12_n978() + fun_l13_n463 +end + +def fun_l12_n979() + fun_l13_n408 +end + +def fun_l12_n980() + fun_l13_n993 +end + +def fun_l12_n981() + fun_l13_n583 +end + +def fun_l12_n982() + fun_l13_n752 +end + +def fun_l12_n983() + fun_l13_n583 +end + +def fun_l12_n984() + fun_l13_n601 +end + +def fun_l12_n985() + fun_l13_n490 +end + +def fun_l12_n986() + fun_l13_n61 +end + +def fun_l12_n987() + fun_l13_n89 +end + +def fun_l12_n988() + fun_l13_n533 +end + +def fun_l12_n989() + fun_l13_n628 +end + +def fun_l12_n990() + fun_l13_n301 +end + +def fun_l12_n991() + fun_l13_n553 +end + +def fun_l12_n992() + fun_l13_n105 +end + +def fun_l12_n993() + fun_l13_n595 +end + +def fun_l12_n994() + fun_l13_n384 +end + +def fun_l12_n995() + fun_l13_n704 +end + +def fun_l12_n996() + fun_l13_n657 +end + +def fun_l12_n997() + fun_l13_n468 +end + +def fun_l12_n998() + fun_l13_n582 +end + +def fun_l12_n999() + fun_l13_n335 +end + +def fun_l13_n0() + fun_l14_n123 +end + +def fun_l13_n1() + fun_l14_n796 +end + +def fun_l13_n2() + fun_l14_n217 +end + +def fun_l13_n3() + fun_l14_n810 +end + +def fun_l13_n4() + fun_l14_n297 +end + +def fun_l13_n5() + fun_l14_n682 +end + +def fun_l13_n6() + fun_l14_n397 +end + +def fun_l13_n7() + fun_l14_n372 +end + +def fun_l13_n8() + fun_l14_n688 +end + +def fun_l13_n9() + fun_l14_n250 +end + +def fun_l13_n10() + fun_l14_n248 +end + +def fun_l13_n11() + fun_l14_n335 +end + +def fun_l13_n12() + fun_l14_n404 +end + +def fun_l13_n13() + fun_l14_n223 +end + +def fun_l13_n14() + fun_l14_n894 +end + +def fun_l13_n15() + fun_l14_n537 +end + +def fun_l13_n16() + fun_l14_n641 +end + +def fun_l13_n17() + fun_l14_n509 +end + +def fun_l13_n18() + fun_l14_n624 +end + +def fun_l13_n19() + fun_l14_n224 +end + +def fun_l13_n20() + fun_l14_n283 +end + +def fun_l13_n21() + fun_l14_n624 +end + +def fun_l13_n22() + fun_l14_n972 +end + +def fun_l13_n23() + fun_l14_n698 +end + +def fun_l13_n24() + fun_l14_n313 +end + +def fun_l13_n25() + fun_l14_n344 +end + +def fun_l13_n26() + fun_l14_n823 +end + +def fun_l13_n27() + fun_l14_n699 +end + +def fun_l13_n28() + fun_l14_n943 +end + +def fun_l13_n29() + fun_l14_n69 +end + +def fun_l13_n30() + fun_l14_n839 +end + +def fun_l13_n31() + fun_l14_n834 +end + +def fun_l13_n32() + fun_l14_n143 +end + +def fun_l13_n33() + fun_l14_n500 +end + +def fun_l13_n34() + fun_l14_n266 +end + +def fun_l13_n35() + fun_l14_n576 +end + +def fun_l13_n36() + fun_l14_n247 +end + +def fun_l13_n37() + fun_l14_n847 +end + +def fun_l13_n38() + fun_l14_n474 +end + +def fun_l13_n39() + fun_l14_n293 +end + +def fun_l13_n40() + fun_l14_n475 +end + +def fun_l13_n41() + fun_l14_n641 +end + +def fun_l13_n42() + fun_l14_n583 +end + +def fun_l13_n43() + fun_l14_n857 +end + +def fun_l13_n44() + fun_l14_n97 +end + +def fun_l13_n45() + fun_l14_n196 +end + +def fun_l13_n46() + fun_l14_n201 +end + +def fun_l13_n47() + fun_l14_n877 +end + +def fun_l13_n48() + fun_l14_n464 +end + +def fun_l13_n49() + fun_l14_n706 +end + +def fun_l13_n50() + fun_l14_n274 +end + +def fun_l13_n51() + fun_l14_n844 +end + +def fun_l13_n52() + fun_l14_n883 +end + +def fun_l13_n53() + fun_l14_n77 +end + +def fun_l13_n54() + fun_l14_n981 +end + +def fun_l13_n55() + fun_l14_n189 +end + +def fun_l13_n56() + fun_l14_n597 +end + +def fun_l13_n57() + fun_l14_n333 +end + +def fun_l13_n58() + fun_l14_n566 +end + +def fun_l13_n59() + fun_l14_n231 +end + +def fun_l13_n60() + fun_l14_n207 +end + +def fun_l13_n61() + fun_l14_n555 +end + +def fun_l13_n62() + fun_l14_n46 +end + +def fun_l13_n63() + fun_l14_n879 +end + +def fun_l13_n64() + fun_l14_n672 +end + +def fun_l13_n65() + fun_l14_n266 +end + +def fun_l13_n66() + fun_l14_n898 +end + +def fun_l13_n67() + fun_l14_n966 +end + +def fun_l13_n68() + fun_l14_n63 +end + +def fun_l13_n69() + fun_l14_n531 +end + +def fun_l13_n70() + fun_l14_n80 +end + +def fun_l13_n71() + fun_l14_n206 +end + +def fun_l13_n72() + fun_l14_n594 +end + +def fun_l13_n73() + fun_l14_n852 +end + +def fun_l13_n74() + fun_l14_n443 +end + +def fun_l13_n75() + fun_l14_n987 +end + +def fun_l13_n76() + fun_l14_n119 +end + +def fun_l13_n77() + fun_l14_n113 +end + +def fun_l13_n78() + fun_l14_n904 +end + +def fun_l13_n79() + fun_l14_n88 +end + +def fun_l13_n80() + fun_l14_n209 +end + +def fun_l13_n81() + fun_l14_n190 +end + +def fun_l13_n82() + fun_l14_n594 +end + +def fun_l13_n83() + fun_l14_n87 +end + +def fun_l13_n84() + fun_l14_n206 +end + +def fun_l13_n85() + fun_l14_n974 +end + +def fun_l13_n86() + fun_l14_n646 +end + +def fun_l13_n87() + fun_l14_n450 +end + +def fun_l13_n88() + fun_l14_n981 +end + +def fun_l13_n89() + fun_l14_n277 +end + +def fun_l13_n90() + fun_l14_n309 +end + +def fun_l13_n91() + fun_l14_n648 +end + +def fun_l13_n92() + fun_l14_n353 +end + +def fun_l13_n93() + fun_l14_n43 +end + +def fun_l13_n94() + fun_l14_n217 +end + +def fun_l13_n95() + fun_l14_n945 +end + +def fun_l13_n96() + fun_l14_n172 +end + +def fun_l13_n97() + fun_l14_n604 +end + +def fun_l13_n98() + fun_l14_n252 +end + +def fun_l13_n99() + fun_l14_n478 +end + +def fun_l13_n100() + fun_l14_n564 +end + +def fun_l13_n101() + fun_l14_n937 +end + +def fun_l13_n102() + fun_l14_n940 +end + +def fun_l13_n103() + fun_l14_n110 +end + +def fun_l13_n104() + fun_l14_n175 +end + +def fun_l13_n105() + fun_l14_n708 +end + +def fun_l13_n106() + fun_l14_n161 +end + +def fun_l13_n107() + fun_l14_n129 +end + +def fun_l13_n108() + fun_l14_n186 +end + +def fun_l13_n109() + fun_l14_n449 +end + +def fun_l13_n110() + fun_l14_n358 +end + +def fun_l13_n111() + fun_l14_n278 +end + +def fun_l13_n112() + fun_l14_n598 +end + +def fun_l13_n113() + fun_l14_n896 +end + +def fun_l13_n114() + fun_l14_n964 +end + +def fun_l13_n115() + fun_l14_n986 +end + +def fun_l13_n116() + fun_l14_n268 +end + +def fun_l13_n117() + fun_l14_n521 +end + +def fun_l13_n118() + fun_l14_n968 +end + +def fun_l13_n119() + fun_l14_n380 +end + +def fun_l13_n120() + fun_l14_n549 +end + +def fun_l13_n121() + fun_l14_n300 +end + +def fun_l13_n122() + fun_l14_n246 +end + +def fun_l13_n123() + fun_l14_n329 +end + +def fun_l13_n124() + fun_l14_n134 +end + +def fun_l13_n125() + fun_l14_n740 +end + +def fun_l13_n126() + fun_l14_n965 +end + +def fun_l13_n127() + fun_l14_n284 +end + +def fun_l13_n128() + fun_l14_n409 +end + +def fun_l13_n129() + fun_l14_n597 +end + +def fun_l13_n130() + fun_l14_n285 +end + +def fun_l13_n131() + fun_l14_n270 +end + +def fun_l13_n132() + fun_l14_n66 +end + +def fun_l13_n133() + fun_l14_n588 +end + +def fun_l13_n134() + fun_l14_n534 +end + +def fun_l13_n135() + fun_l14_n673 +end + +def fun_l13_n136() + fun_l14_n867 +end + +def fun_l13_n137() + fun_l14_n157 +end + +def fun_l13_n138() + fun_l14_n755 +end + +def fun_l13_n139() + fun_l14_n68 +end + +def fun_l13_n140() + fun_l14_n859 +end + +def fun_l13_n141() + fun_l14_n804 +end + +def fun_l13_n142() + fun_l14_n300 +end + +def fun_l13_n143() + fun_l14_n157 +end + +def fun_l13_n144() + fun_l14_n376 +end + +def fun_l13_n145() + fun_l14_n62 +end + +def fun_l13_n146() + fun_l14_n755 +end + +def fun_l13_n147() + fun_l14_n547 +end + +def fun_l13_n148() + fun_l14_n223 +end + +def fun_l13_n149() + fun_l14_n277 +end + +def fun_l13_n150() + fun_l14_n57 +end + +def fun_l13_n151() + fun_l14_n552 +end + +def fun_l13_n152() + fun_l14_n390 +end + +def fun_l13_n153() + fun_l14_n691 +end + +def fun_l13_n154() + fun_l14_n871 +end + +def fun_l13_n155() + fun_l14_n14 +end + +def fun_l13_n156() + fun_l14_n68 +end + +def fun_l13_n157() + fun_l14_n589 +end + +def fun_l13_n158() + fun_l14_n504 +end + +def fun_l13_n159() + fun_l14_n966 +end + +def fun_l13_n160() + fun_l14_n62 +end + +def fun_l13_n161() + fun_l14_n880 +end + +def fun_l13_n162() + fun_l14_n897 +end + +def fun_l13_n163() + fun_l14_n630 +end + +def fun_l13_n164() + fun_l14_n129 +end + +def fun_l13_n165() + fun_l14_n461 +end + +def fun_l13_n166() + fun_l14_n193 +end + +def fun_l13_n167() + fun_l14_n588 +end + +def fun_l13_n168() + fun_l14_n49 +end + +def fun_l13_n169() + fun_l14_n872 +end + +def fun_l13_n170() + fun_l14_n199 +end + +def fun_l13_n171() + fun_l14_n887 +end + +def fun_l13_n172() + fun_l14_n932 +end + +def fun_l13_n173() + fun_l14_n616 +end + +def fun_l13_n174() + fun_l14_n62 +end + +def fun_l13_n175() + fun_l14_n162 +end + +def fun_l13_n176() + fun_l14_n979 +end + +def fun_l13_n177() + fun_l14_n813 +end + +def fun_l13_n178() + fun_l14_n529 +end + +def fun_l13_n179() + fun_l14_n202 +end + +def fun_l13_n180() + fun_l14_n916 +end + +def fun_l13_n181() + fun_l14_n719 +end + +def fun_l13_n182() + fun_l14_n256 +end + +def fun_l13_n183() + fun_l14_n137 +end + +def fun_l13_n184() + fun_l14_n562 +end + +def fun_l13_n185() + fun_l14_n614 +end + +def fun_l13_n186() + fun_l14_n918 +end + +def fun_l13_n187() + fun_l14_n435 +end + +def fun_l13_n188() + fun_l14_n429 +end + +def fun_l13_n189() + fun_l14_n561 +end + +def fun_l13_n190() + fun_l14_n422 +end + +def fun_l13_n191() + fun_l14_n396 +end + +def fun_l13_n192() + fun_l14_n971 +end + +def fun_l13_n193() + fun_l14_n419 +end + +def fun_l13_n194() + fun_l14_n319 +end + +def fun_l13_n195() + fun_l14_n8 +end + +def fun_l13_n196() + fun_l14_n378 +end + +def fun_l13_n197() + fun_l14_n709 +end + +def fun_l13_n198() + fun_l14_n308 +end + +def fun_l13_n199() + fun_l14_n916 +end + +def fun_l13_n200() + fun_l14_n822 +end + +def fun_l13_n201() + fun_l14_n736 +end + +def fun_l13_n202() + fun_l14_n259 +end + +def fun_l13_n203() + fun_l14_n965 +end + +def fun_l13_n204() + fun_l14_n52 +end + +def fun_l13_n205() + fun_l14_n237 +end + +def fun_l13_n206() + fun_l14_n850 +end + +def fun_l13_n207() + fun_l14_n961 +end + +def fun_l13_n208() + fun_l14_n289 +end + +def fun_l13_n209() + fun_l14_n465 +end + +def fun_l13_n210() + fun_l14_n635 +end + +def fun_l13_n211() + fun_l14_n222 +end + +def fun_l13_n212() + fun_l14_n796 +end + +def fun_l13_n213() + fun_l14_n20 +end + +def fun_l13_n214() + fun_l14_n576 +end + +def fun_l13_n215() + fun_l14_n947 +end + +def fun_l13_n216() + fun_l14_n482 +end + +def fun_l13_n217() + fun_l14_n236 +end + +def fun_l13_n218() + fun_l14_n405 +end + +def fun_l13_n219() + fun_l14_n874 +end + +def fun_l13_n220() + fun_l14_n827 +end + +def fun_l13_n221() + fun_l14_n975 +end + +def fun_l13_n222() + fun_l14_n741 +end + +def fun_l13_n223() + fun_l14_n60 +end + +def fun_l13_n224() + fun_l14_n587 +end + +def fun_l13_n225() + fun_l14_n557 +end + +def fun_l13_n226() + fun_l14_n621 +end + +def fun_l13_n227() + fun_l14_n426 +end + +def fun_l13_n228() + fun_l14_n848 +end + +def fun_l13_n229() + fun_l14_n164 +end + +def fun_l13_n230() + fun_l14_n427 +end + +def fun_l13_n231() + fun_l14_n815 +end + +def fun_l13_n232() + fun_l14_n465 +end + +def fun_l13_n233() + fun_l14_n474 +end + +def fun_l13_n234() + fun_l14_n577 +end + +def fun_l13_n235() + fun_l14_n427 +end + +def fun_l13_n236() + fun_l14_n580 +end + +def fun_l13_n237() + fun_l14_n275 +end + +def fun_l13_n238() + fun_l14_n559 +end + +def fun_l13_n239() + fun_l14_n834 +end + +def fun_l13_n240() + fun_l14_n656 +end + +def fun_l13_n241() + fun_l14_n411 +end + +def fun_l13_n242() + fun_l14_n54 +end + +def fun_l13_n243() + fun_l14_n223 +end + +def fun_l13_n244() + fun_l14_n623 +end + +def fun_l13_n245() + fun_l14_n251 +end + +def fun_l13_n246() + fun_l14_n948 +end + +def fun_l13_n247() + fun_l14_n857 +end + +def fun_l13_n248() + fun_l14_n528 +end + +def fun_l13_n249() + fun_l14_n396 +end + +def fun_l13_n250() + fun_l14_n832 +end + +def fun_l13_n251() + fun_l14_n191 +end + +def fun_l13_n252() + fun_l14_n729 +end + +def fun_l13_n253() + fun_l14_n22 +end + +def fun_l13_n254() + fun_l14_n10 +end + +def fun_l13_n255() + fun_l14_n871 +end + +def fun_l13_n256() + fun_l14_n664 +end + +def fun_l13_n257() + fun_l14_n877 +end + +def fun_l13_n258() + fun_l14_n477 +end + +def fun_l13_n259() + fun_l14_n861 +end + +def fun_l13_n260() + fun_l14_n160 +end + +def fun_l13_n261() + fun_l14_n127 +end + +def fun_l13_n262() + fun_l14_n744 +end + +def fun_l13_n263() + fun_l14_n305 +end + +def fun_l13_n264() + fun_l14_n473 +end + +def fun_l13_n265() + fun_l14_n445 +end + +def fun_l13_n266() + fun_l14_n31 +end + +def fun_l13_n267() + fun_l14_n58 +end + +def fun_l13_n268() + fun_l14_n739 +end + +def fun_l13_n269() + fun_l14_n840 +end + +def fun_l13_n270() + fun_l14_n275 +end + +def fun_l13_n271() + fun_l14_n264 +end + +def fun_l13_n272() + fun_l14_n503 +end + +def fun_l13_n273() + fun_l14_n559 +end + +def fun_l13_n274() + fun_l14_n693 +end + +def fun_l13_n275() + fun_l14_n723 +end + +def fun_l13_n276() + fun_l14_n716 +end + +def fun_l13_n277() + fun_l14_n181 +end + +def fun_l13_n278() + fun_l14_n904 +end + +def fun_l13_n279() + fun_l14_n75 +end + +def fun_l13_n280() + fun_l14_n992 +end + +def fun_l13_n281() + fun_l14_n904 +end + +def fun_l13_n282() + fun_l14_n856 +end + +def fun_l13_n283() + fun_l14_n218 +end + +def fun_l13_n284() + fun_l14_n896 +end + +def fun_l13_n285() + fun_l14_n456 +end + +def fun_l13_n286() + fun_l14_n591 +end + +def fun_l13_n287() + fun_l14_n960 +end + +def fun_l13_n288() + fun_l14_n949 +end + +def fun_l13_n289() + fun_l14_n92 +end + +def fun_l13_n290() + fun_l14_n945 +end + +def fun_l13_n291() + fun_l14_n684 +end + +def fun_l13_n292() + fun_l14_n8 +end + +def fun_l13_n293() + fun_l14_n147 +end + +def fun_l13_n294() + fun_l14_n129 +end + +def fun_l13_n295() + fun_l14_n308 +end + +def fun_l13_n296() + fun_l14_n112 +end + +def fun_l13_n297() + fun_l14_n657 +end + +def fun_l13_n298() + fun_l14_n910 +end + +def fun_l13_n299() + fun_l14_n804 +end + +def fun_l13_n300() + fun_l14_n580 +end + +def fun_l13_n301() + fun_l14_n373 +end + +def fun_l13_n302() + fun_l14_n749 +end + +def fun_l13_n303() + fun_l14_n353 +end + +def fun_l13_n304() + fun_l14_n58 +end + +def fun_l13_n305() + fun_l14_n207 +end + +def fun_l13_n306() + fun_l14_n977 +end + +def fun_l13_n307() + fun_l14_n95 +end + +def fun_l13_n308() + fun_l14_n836 +end + +def fun_l13_n309() + fun_l14_n244 +end + +def fun_l13_n310() + fun_l14_n676 +end + +def fun_l13_n311() + fun_l14_n617 +end + +def fun_l13_n312() + fun_l14_n633 +end + +def fun_l13_n313() + fun_l14_n550 +end + +def fun_l13_n314() + fun_l14_n564 +end + +def fun_l13_n315() + fun_l14_n261 +end + +def fun_l13_n316() + fun_l14_n968 +end + +def fun_l13_n317() + fun_l14_n16 +end + +def fun_l13_n318() + fun_l14_n894 +end + +def fun_l13_n319() + fun_l14_n717 +end + +def fun_l13_n320() + fun_l14_n802 +end + +def fun_l13_n321() + fun_l14_n628 +end + +def fun_l13_n322() + fun_l14_n306 +end + +def fun_l13_n323() + fun_l14_n121 +end + +def fun_l13_n324() + fun_l14_n468 +end + +def fun_l13_n325() + fun_l14_n863 +end + +def fun_l13_n326() + fun_l14_n970 +end + +def fun_l13_n327() + fun_l14_n637 +end + +def fun_l13_n328() + fun_l14_n12 +end + +def fun_l13_n329() + fun_l14_n244 +end + +def fun_l13_n330() + fun_l14_n847 +end + +def fun_l13_n331() + fun_l14_n122 +end + +def fun_l13_n332() + fun_l14_n546 +end + +def fun_l13_n333() + fun_l14_n640 +end + +def fun_l13_n334() + fun_l14_n224 +end + +def fun_l13_n335() + fun_l14_n73 +end + +def fun_l13_n336() + fun_l14_n25 +end + +def fun_l13_n337() + fun_l14_n226 +end + +def fun_l13_n338() + fun_l14_n63 +end + +def fun_l13_n339() + fun_l14_n591 +end + +def fun_l13_n340() + fun_l14_n32 +end + +def fun_l13_n341() + fun_l14_n646 +end + +def fun_l13_n342() + fun_l14_n954 +end + +def fun_l13_n343() + fun_l14_n915 +end + +def fun_l13_n344() + fun_l14_n359 +end + +def fun_l13_n345() + fun_l14_n967 +end + +def fun_l13_n346() + fun_l14_n980 +end + +def fun_l13_n347() + fun_l14_n324 +end + +def fun_l13_n348() + fun_l14_n263 +end + +def fun_l13_n349() + fun_l14_n644 +end + +def fun_l13_n350() + fun_l14_n575 +end + +def fun_l13_n351() + fun_l14_n820 +end + +def fun_l13_n352() + fun_l14_n767 +end + +def fun_l13_n353() + fun_l14_n175 +end + +def fun_l13_n354() + fun_l14_n990 +end + +def fun_l13_n355() + fun_l14_n631 +end + +def fun_l13_n356() + fun_l14_n503 +end + +def fun_l13_n357() + fun_l14_n785 +end + +def fun_l13_n358() + fun_l14_n239 +end + +def fun_l13_n359() + fun_l14_n678 +end + +def fun_l13_n360() + fun_l14_n11 +end + +def fun_l13_n361() + fun_l14_n829 +end + +def fun_l13_n362() + fun_l14_n205 +end + +def fun_l13_n363() + fun_l14_n146 +end + +def fun_l13_n364() + fun_l14_n972 +end + +def fun_l13_n365() + fun_l14_n68 +end + +def fun_l13_n366() + fun_l14_n830 +end + +def fun_l13_n367() + fun_l14_n60 +end + +def fun_l13_n368() + fun_l14_n521 +end + +def fun_l13_n369() + fun_l14_n287 +end + +def fun_l13_n370() + fun_l14_n932 +end + +def fun_l13_n371() + fun_l14_n268 +end + +def fun_l13_n372() + fun_l14_n285 +end + +def fun_l13_n373() + fun_l14_n101 +end + +def fun_l13_n374() + fun_l14_n811 +end + +def fun_l13_n375() + fun_l14_n966 +end + +def fun_l13_n376() + fun_l14_n201 +end + +def fun_l13_n377() + fun_l14_n176 +end + +def fun_l13_n378() + fun_l14_n850 +end + +def fun_l13_n379() + fun_l14_n436 +end + +def fun_l13_n380() + fun_l14_n83 +end + +def fun_l13_n381() + fun_l14_n393 +end + +def fun_l13_n382() + fun_l14_n812 +end + +def fun_l13_n383() + fun_l14_n276 +end + +def fun_l13_n384() + fun_l14_n997 +end + +def fun_l13_n385() + fun_l14_n942 +end + +def fun_l13_n386() + fun_l14_n851 +end + +def fun_l13_n387() + fun_l14_n747 +end + +def fun_l13_n388() + fun_l14_n573 +end + +def fun_l13_n389() + fun_l14_n949 +end + +def fun_l13_n390() + fun_l14_n857 +end + +def fun_l13_n391() + fun_l14_n495 +end + +def fun_l13_n392() + fun_l14_n399 +end + +def fun_l13_n393() + fun_l14_n603 +end + +def fun_l13_n394() + fun_l14_n208 +end + +def fun_l13_n395() + fun_l14_n736 +end + +def fun_l13_n396() + fun_l14_n339 +end + +def fun_l13_n397() + fun_l14_n759 +end + +def fun_l13_n398() + fun_l14_n912 +end + +def fun_l13_n399() + fun_l14_n899 +end + +def fun_l13_n400() + fun_l14_n954 +end + +def fun_l13_n401() + fun_l14_n143 +end + +def fun_l13_n402() + fun_l14_n866 +end + +def fun_l13_n403() + fun_l14_n657 +end + +def fun_l13_n404() + fun_l14_n854 +end + +def fun_l13_n405() + fun_l14_n365 +end + +def fun_l13_n406() + fun_l14_n79 +end + +def fun_l13_n407() + fun_l14_n724 +end + +def fun_l13_n408() + fun_l14_n544 +end + +def fun_l13_n409() + fun_l14_n562 +end + +def fun_l13_n410() + fun_l14_n946 +end + +def fun_l13_n411() + fun_l14_n761 +end + +def fun_l13_n412() + fun_l14_n251 +end + +def fun_l13_n413() + fun_l14_n689 +end + +def fun_l13_n414() + fun_l14_n94 +end + +def fun_l13_n415() + fun_l14_n466 +end + +def fun_l13_n416() + fun_l14_n186 +end + +def fun_l13_n417() + fun_l14_n367 +end + +def fun_l13_n418() + fun_l14_n477 +end + +def fun_l13_n419() + fun_l14_n356 +end + +def fun_l13_n420() + fun_l14_n279 +end + +def fun_l13_n421() + fun_l14_n76 +end + +def fun_l13_n422() + fun_l14_n677 +end + +def fun_l13_n423() + fun_l14_n334 +end + +def fun_l13_n424() + fun_l14_n777 +end + +def fun_l13_n425() + fun_l14_n632 +end + +def fun_l13_n426() + fun_l14_n380 +end + +def fun_l13_n427() + fun_l14_n833 +end + +def fun_l13_n428() + fun_l14_n395 +end + +def fun_l13_n429() + fun_l14_n324 +end + +def fun_l13_n430() + fun_l14_n608 +end + +def fun_l13_n431() + fun_l14_n916 +end + +def fun_l13_n432() + fun_l14_n89 +end + +def fun_l13_n433() + fun_l14_n239 +end + +def fun_l13_n434() + fun_l14_n712 +end + +def fun_l13_n435() + fun_l14_n911 +end + +def fun_l13_n436() + fun_l14_n810 +end + +def fun_l13_n437() + fun_l14_n670 +end + +def fun_l13_n438() + fun_l14_n125 +end + +def fun_l13_n439() + fun_l14_n903 +end + +def fun_l13_n440() + fun_l14_n277 +end + +def fun_l13_n441() + fun_l14_n581 +end + +def fun_l13_n442() + fun_l14_n726 +end + +def fun_l13_n443() + fun_l14_n360 +end + +def fun_l13_n444() + fun_l14_n439 +end + +def fun_l13_n445() + fun_l14_n441 +end + +def fun_l13_n446() + fun_l14_n464 +end + +def fun_l13_n447() + fun_l14_n550 +end + +def fun_l13_n448() + fun_l14_n94 +end + +def fun_l13_n449() + fun_l14_n844 +end + +def fun_l13_n450() + fun_l14_n571 +end + +def fun_l13_n451() + fun_l14_n161 +end + +def fun_l13_n452() + fun_l14_n863 +end + +def fun_l13_n453() + fun_l14_n173 +end + +def fun_l13_n454() + fun_l14_n330 +end + +def fun_l13_n455() + fun_l14_n175 +end + +def fun_l13_n456() + fun_l14_n40 +end + +def fun_l13_n457() + fun_l14_n335 +end + +def fun_l13_n458() + fun_l14_n46 +end + +def fun_l13_n459() + fun_l14_n57 +end + +def fun_l13_n460() + fun_l14_n428 +end + +def fun_l13_n461() + fun_l14_n773 +end + +def fun_l13_n462() + fun_l14_n712 +end + +def fun_l13_n463() + fun_l14_n624 +end + +def fun_l13_n464() + fun_l14_n103 +end + +def fun_l13_n465() + fun_l14_n962 +end + +def fun_l13_n466() + fun_l14_n424 +end + +def fun_l13_n467() + fun_l14_n780 +end + +def fun_l13_n468() + fun_l14_n852 +end + +def fun_l13_n469() + fun_l14_n175 +end + +def fun_l13_n470() + fun_l14_n900 +end + +def fun_l13_n471() + fun_l14_n866 +end + +def fun_l13_n472() + fun_l14_n541 +end + +def fun_l13_n473() + fun_l14_n966 +end + +def fun_l13_n474() + fun_l14_n107 +end + +def fun_l13_n475() + fun_l14_n917 +end + +def fun_l13_n476() + fun_l14_n683 +end + +def fun_l13_n477() + fun_l14_n625 +end + +def fun_l13_n478() + fun_l14_n439 +end + +def fun_l13_n479() + fun_l14_n69 +end + +def fun_l13_n480() + fun_l14_n252 +end + +def fun_l13_n481() + fun_l14_n753 +end + +def fun_l13_n482() + fun_l14_n50 +end + +def fun_l13_n483() + fun_l14_n634 +end + +def fun_l13_n484() + fun_l14_n908 +end + +def fun_l13_n485() + fun_l14_n733 +end + +def fun_l13_n486() + fun_l14_n450 +end + +def fun_l13_n487() + fun_l14_n373 +end + +def fun_l13_n488() + fun_l14_n226 +end + +def fun_l13_n489() + fun_l14_n320 +end + +def fun_l13_n490() + fun_l14_n498 +end + +def fun_l13_n491() + fun_l14_n49 +end + +def fun_l13_n492() + fun_l14_n46 +end + +def fun_l13_n493() + fun_l14_n993 +end + +def fun_l13_n494() + fun_l14_n123 +end + +def fun_l13_n495() + fun_l14_n393 +end + +def fun_l13_n496() + fun_l14_n500 +end + +def fun_l13_n497() + fun_l14_n328 +end + +def fun_l13_n498() + fun_l14_n711 +end + +def fun_l13_n499() + fun_l14_n734 +end + +def fun_l13_n500() + fun_l14_n354 +end + +def fun_l13_n501() + fun_l14_n565 +end + +def fun_l13_n502() + fun_l14_n699 +end + +def fun_l13_n503() + fun_l14_n157 +end + +def fun_l13_n504() + fun_l14_n634 +end + +def fun_l13_n505() + fun_l14_n282 +end + +def fun_l13_n506() + fun_l14_n484 +end + +def fun_l13_n507() + fun_l14_n972 +end + +def fun_l13_n508() + fun_l14_n763 +end + +def fun_l13_n509() + fun_l14_n530 +end + +def fun_l13_n510() + fun_l14_n88 +end + +def fun_l13_n511() + fun_l14_n718 +end + +def fun_l13_n512() + fun_l14_n988 +end + +def fun_l13_n513() + fun_l14_n266 +end + +def fun_l13_n514() + fun_l14_n489 +end + +def fun_l13_n515() + fun_l14_n662 +end + +def fun_l13_n516() + fun_l14_n821 +end + +def fun_l13_n517() + fun_l14_n697 +end + +def fun_l13_n518() + fun_l14_n984 +end + +def fun_l13_n519() + fun_l14_n847 +end + +def fun_l13_n520() + fun_l14_n916 +end + +def fun_l13_n521() + fun_l14_n304 +end + +def fun_l13_n522() + fun_l14_n778 +end + +def fun_l13_n523() + fun_l14_n105 +end + +def fun_l13_n524() + fun_l14_n272 +end + +def fun_l13_n525() + fun_l14_n814 +end + +def fun_l13_n526() + fun_l14_n689 +end + +def fun_l13_n527() + fun_l14_n314 +end + +def fun_l13_n528() + fun_l14_n483 +end + +def fun_l13_n529() + fun_l14_n571 +end + +def fun_l13_n530() + fun_l14_n162 +end + +def fun_l13_n531() + fun_l14_n737 +end + +def fun_l13_n532() + fun_l14_n886 +end + +def fun_l13_n533() + fun_l14_n638 +end + +def fun_l13_n534() + fun_l14_n765 +end + +def fun_l13_n535() + fun_l14_n452 +end + +def fun_l13_n536() + fun_l14_n367 +end + +def fun_l13_n537() + fun_l14_n245 +end + +def fun_l13_n538() + fun_l14_n590 +end + +def fun_l13_n539() + fun_l14_n383 +end + +def fun_l13_n540() + fun_l14_n210 +end + +def fun_l13_n541() + fun_l14_n25 +end + +def fun_l13_n542() + fun_l14_n612 +end + +def fun_l13_n543() + fun_l14_n639 +end + +def fun_l13_n544() + fun_l14_n540 +end + +def fun_l13_n545() + fun_l14_n538 +end + +def fun_l13_n546() + fun_l14_n323 +end + +def fun_l13_n547() + fun_l14_n556 +end + +def fun_l13_n548() + fun_l14_n219 +end + +def fun_l13_n549() + fun_l14_n583 +end + +def fun_l13_n550() + fun_l14_n818 +end + +def fun_l13_n551() + fun_l14_n167 +end + +def fun_l13_n552() + fun_l14_n310 +end + +def fun_l13_n553() + fun_l14_n528 +end + +def fun_l13_n554() + fun_l14_n604 +end + +def fun_l13_n555() + fun_l14_n426 +end + +def fun_l13_n556() + fun_l14_n398 +end + +def fun_l13_n557() + fun_l14_n885 +end + +def fun_l13_n558() + fun_l14_n905 +end + +def fun_l13_n559() + fun_l14_n882 +end + +def fun_l13_n560() + fun_l14_n536 +end + +def fun_l13_n561() + fun_l14_n392 +end + +def fun_l13_n562() + fun_l14_n948 +end + +def fun_l13_n563() + fun_l14_n522 +end + +def fun_l13_n564() + fun_l14_n704 +end + +def fun_l13_n565() + fun_l14_n365 +end + +def fun_l13_n566() + fun_l14_n925 +end + +def fun_l13_n567() + fun_l14_n353 +end + +def fun_l13_n568() + fun_l14_n215 +end + +def fun_l13_n569() + fun_l14_n932 +end + +def fun_l13_n570() + fun_l14_n458 +end + +def fun_l13_n571() + fun_l14_n793 +end + +def fun_l13_n572() + fun_l14_n650 +end + +def fun_l13_n573() + fun_l14_n888 +end + +def fun_l13_n574() + fun_l14_n986 +end + +def fun_l13_n575() + fun_l14_n834 +end + +def fun_l13_n576() + fun_l14_n253 +end + +def fun_l13_n577() + fun_l14_n382 +end + +def fun_l13_n578() + fun_l14_n300 +end + +def fun_l13_n579() + fun_l14_n457 +end + +def fun_l13_n580() + fun_l14_n398 +end + +def fun_l13_n581() + fun_l14_n93 +end + +def fun_l13_n582() + fun_l14_n226 +end + +def fun_l13_n583() + fun_l14_n665 +end + +def fun_l13_n584() + fun_l14_n354 +end + +def fun_l13_n585() + fun_l14_n460 +end + +def fun_l13_n586() + fun_l14_n185 +end + +def fun_l13_n587() + fun_l14_n577 +end + +def fun_l13_n588() + fun_l14_n180 +end + +def fun_l13_n589() + fun_l14_n769 +end + +def fun_l13_n590() + fun_l14_n78 +end + +def fun_l13_n591() + fun_l14_n455 +end + +def fun_l13_n592() + fun_l14_n862 +end + +def fun_l13_n593() + fun_l14_n471 +end + +def fun_l13_n594() + fun_l14_n931 +end + +def fun_l13_n595() + fun_l14_n255 +end + +def fun_l13_n596() + fun_l14_n261 +end + +def fun_l13_n597() + fun_l14_n586 +end + +def fun_l13_n598() + fun_l14_n45 +end + +def fun_l13_n599() + fun_l14_n892 +end + +def fun_l13_n600() + fun_l14_n615 +end + +def fun_l13_n601() + fun_l14_n910 +end + +def fun_l13_n602() + fun_l14_n888 +end + +def fun_l13_n603() + fun_l14_n827 +end + +def fun_l13_n604() + fun_l14_n765 +end + +def fun_l13_n605() + fun_l14_n118 +end + +def fun_l13_n606() + fun_l14_n895 +end + +def fun_l13_n607() + fun_l14_n183 +end + +def fun_l13_n608() + fun_l14_n200 +end + +def fun_l13_n609() + fun_l14_n873 +end + +def fun_l13_n610() + fun_l14_n402 +end + +def fun_l13_n611() + fun_l14_n414 +end + +def fun_l13_n612() + fun_l14_n492 +end + +def fun_l13_n613() + fun_l14_n811 +end + +def fun_l13_n614() + fun_l14_n814 +end + +def fun_l13_n615() + fun_l14_n95 +end + +def fun_l13_n616() + fun_l14_n782 +end + +def fun_l13_n617() + fun_l14_n329 +end + +def fun_l13_n618() + fun_l14_n180 +end + +def fun_l13_n619() + fun_l14_n104 +end + +def fun_l13_n620() + fun_l14_n341 +end + +def fun_l13_n621() + fun_l14_n132 +end + +def fun_l13_n622() + fun_l14_n815 +end + +def fun_l13_n623() + fun_l14_n785 +end + +def fun_l13_n624() + fun_l14_n934 +end + +def fun_l13_n625() + fun_l14_n760 +end + +def fun_l13_n626() + fun_l14_n307 +end + +def fun_l13_n627() + fun_l14_n433 +end + +def fun_l13_n628() + fun_l14_n156 +end + +def fun_l13_n629() + fun_l14_n95 +end + +def fun_l13_n630() + fun_l14_n44 +end + +def fun_l13_n631() + fun_l14_n643 +end + +def fun_l13_n632() + fun_l14_n876 +end + +def fun_l13_n633() + fun_l14_n477 +end + +def fun_l13_n634() + fun_l14_n549 +end + +def fun_l13_n635() + fun_l14_n795 +end + +def fun_l13_n636() + fun_l14_n814 +end + +def fun_l13_n637() + fun_l14_n52 +end + +def fun_l13_n638() + fun_l14_n542 +end + +def fun_l13_n639() + fun_l14_n204 +end + +def fun_l13_n640() + fun_l14_n256 +end + +def fun_l13_n641() + fun_l14_n198 +end + +def fun_l13_n642() + fun_l14_n221 +end + +def fun_l13_n643() + fun_l14_n855 +end + +def fun_l13_n644() + fun_l14_n978 +end + +def fun_l13_n645() + fun_l14_n954 +end + +def fun_l13_n646() + fun_l14_n148 +end + +def fun_l13_n647() + fun_l14_n528 +end + +def fun_l13_n648() + fun_l14_n807 +end + +def fun_l13_n649() + fun_l14_n735 +end + +def fun_l13_n650() + fun_l14_n518 +end + +def fun_l13_n651() + fun_l14_n255 +end + +def fun_l13_n652() + fun_l14_n251 +end + +def fun_l13_n653() + fun_l14_n311 +end + +def fun_l13_n654() + fun_l14_n134 +end + +def fun_l13_n655() + fun_l14_n474 +end + +def fun_l13_n656() + fun_l14_n857 +end + +def fun_l13_n657() + fun_l14_n758 +end + +def fun_l13_n658() + fun_l14_n310 +end + +def fun_l13_n659() + fun_l14_n846 +end + +def fun_l13_n660() + fun_l14_n220 +end + +def fun_l13_n661() + fun_l14_n81 +end + +def fun_l13_n662() + fun_l14_n958 +end + +def fun_l13_n663() + fun_l14_n221 +end + +def fun_l13_n664() + fun_l14_n107 +end + +def fun_l13_n665() + fun_l14_n131 +end + +def fun_l13_n666() + fun_l14_n750 +end + +def fun_l13_n667() + fun_l14_n455 +end + +def fun_l13_n668() + fun_l14_n354 +end + +def fun_l13_n669() + fun_l14_n76 +end + +def fun_l13_n670() + fun_l14_n111 +end + +def fun_l13_n671() + fun_l14_n411 +end + +def fun_l13_n672() + fun_l14_n400 +end + +def fun_l13_n673() + fun_l14_n407 +end + +def fun_l13_n674() + fun_l14_n851 +end + +def fun_l13_n675() + fun_l14_n521 +end + +def fun_l13_n676() + fun_l14_n448 +end + +def fun_l13_n677() + fun_l14_n615 +end + +def fun_l13_n678() + fun_l14_n574 +end + +def fun_l13_n679() + fun_l14_n300 +end + +def fun_l13_n680() + fun_l14_n783 +end + +def fun_l13_n681() + fun_l14_n172 +end + +def fun_l13_n682() + fun_l14_n725 +end + +def fun_l13_n683() + fun_l14_n657 +end + +def fun_l13_n684() + fun_l14_n550 +end + +def fun_l13_n685() + fun_l14_n976 +end + +def fun_l13_n686() + fun_l14_n77 +end + +def fun_l13_n687() + fun_l14_n472 +end + +def fun_l13_n688() + fun_l14_n300 +end + +def fun_l13_n689() + fun_l14_n139 +end + +def fun_l13_n690() + fun_l14_n623 +end + +def fun_l13_n691() + fun_l14_n336 +end + +def fun_l13_n692() + fun_l14_n502 +end + +def fun_l13_n693() + fun_l14_n184 +end + +def fun_l13_n694() + fun_l14_n745 +end + +def fun_l13_n695() + fun_l14_n27 +end + +def fun_l13_n696() + fun_l14_n299 +end + +def fun_l13_n697() + fun_l14_n7 +end + +def fun_l13_n698() + fun_l14_n842 +end + +def fun_l13_n699() + fun_l14_n592 +end + +def fun_l13_n700() + fun_l14_n993 +end + +def fun_l13_n701() + fun_l14_n113 +end + +def fun_l13_n702() + fun_l14_n997 +end + +def fun_l13_n703() + fun_l14_n740 +end + +def fun_l13_n704() + fun_l14_n261 +end + +def fun_l13_n705() + fun_l14_n737 +end + +def fun_l13_n706() + fun_l14_n216 +end + +def fun_l13_n707() + fun_l14_n607 +end + +def fun_l13_n708() + fun_l14_n520 +end + +def fun_l13_n709() + fun_l14_n133 +end + +def fun_l13_n710() + fun_l14_n615 +end + +def fun_l13_n711() + fun_l14_n476 +end + +def fun_l13_n712() + fun_l14_n154 +end + +def fun_l13_n713() + fun_l14_n947 +end + +def fun_l13_n714() + fun_l14_n893 +end + +def fun_l13_n715() + fun_l14_n296 +end + +def fun_l13_n716() + fun_l14_n275 +end + +def fun_l13_n717() + fun_l14_n622 +end + +def fun_l13_n718() + fun_l14_n561 +end + +def fun_l13_n719() + fun_l14_n216 +end + +def fun_l13_n720() + fun_l14_n459 +end + +def fun_l13_n721() + fun_l14_n329 +end + +def fun_l13_n722() + fun_l14_n901 +end + +def fun_l13_n723() + fun_l14_n824 +end + +def fun_l13_n724() + fun_l14_n359 +end + +def fun_l13_n725() + fun_l14_n399 +end + +def fun_l13_n726() + fun_l14_n998 +end + +def fun_l13_n727() + fun_l14_n327 +end + +def fun_l13_n728() + fun_l14_n659 +end + +def fun_l13_n729() + fun_l14_n564 +end + +def fun_l13_n730() + fun_l14_n718 +end + +def fun_l13_n731() + fun_l14_n751 +end + +def fun_l13_n732() + fun_l14_n172 +end + +def fun_l13_n733() + fun_l14_n289 +end + +def fun_l13_n734() + fun_l14_n956 +end + +def fun_l13_n735() + fun_l14_n375 +end + +def fun_l13_n736() + fun_l14_n459 +end + +def fun_l13_n737() + fun_l14_n471 +end + +def fun_l13_n738() + fun_l14_n957 +end + +def fun_l13_n739() + fun_l14_n670 +end + +def fun_l13_n740() + fun_l14_n396 +end + +def fun_l13_n741() + fun_l14_n909 +end + +def fun_l13_n742() + fun_l14_n226 +end + +def fun_l13_n743() + fun_l14_n458 +end + +def fun_l13_n744() + fun_l14_n923 +end + +def fun_l13_n745() + fun_l14_n255 +end + +def fun_l13_n746() + fun_l14_n2 +end + +def fun_l13_n747() + fun_l14_n805 +end + +def fun_l13_n748() + fun_l14_n157 +end + +def fun_l13_n749() + fun_l14_n952 +end + +def fun_l13_n750() + fun_l14_n902 +end + +def fun_l13_n751() + fun_l14_n723 +end + +def fun_l13_n752() + fun_l14_n204 +end + +def fun_l13_n753() + fun_l14_n53 +end + +def fun_l13_n754() + fun_l14_n240 +end + +def fun_l13_n755() + fun_l14_n161 +end + +def fun_l13_n756() + fun_l14_n735 +end + +def fun_l13_n757() + fun_l14_n298 +end + +def fun_l13_n758() + fun_l14_n743 +end + +def fun_l13_n759() + fun_l14_n886 +end + +def fun_l13_n760() + fun_l14_n559 +end + +def fun_l13_n761() + fun_l14_n42 +end + +def fun_l13_n762() + fun_l14_n86 +end + +def fun_l13_n763() + fun_l14_n138 +end + +def fun_l13_n764() + fun_l14_n477 +end + +def fun_l13_n765() + fun_l14_n763 +end + +def fun_l13_n766() + fun_l14_n360 +end + +def fun_l13_n767() + fun_l14_n486 +end + +def fun_l13_n768() + fun_l14_n734 +end + +def fun_l13_n769() + fun_l14_n442 +end + +def fun_l13_n770() + fun_l14_n512 +end + +def fun_l13_n771() + fun_l14_n399 +end + +def fun_l13_n772() + fun_l14_n88 +end + +def fun_l13_n773() + fun_l14_n55 +end + +def fun_l13_n774() + fun_l14_n138 +end + +def fun_l13_n775() + fun_l14_n104 +end + +def fun_l13_n776() + fun_l14_n901 +end + +def fun_l13_n777() + fun_l14_n7 +end + +def fun_l13_n778() + fun_l14_n72 +end + +def fun_l13_n779() + fun_l14_n588 +end + +def fun_l13_n780() + fun_l14_n266 +end + +def fun_l13_n781() + fun_l14_n428 +end + +def fun_l13_n782() + fun_l14_n802 +end + +def fun_l13_n783() + fun_l14_n59 +end + +def fun_l13_n784() + fun_l14_n734 +end + +def fun_l13_n785() + fun_l14_n674 +end + +def fun_l13_n786() + fun_l14_n126 +end + +def fun_l13_n787() + fun_l14_n199 +end + +def fun_l13_n788() + fun_l14_n695 +end + +def fun_l13_n789() + fun_l14_n332 +end + +def fun_l13_n790() + fun_l14_n734 +end + +def fun_l13_n791() + fun_l14_n856 +end + +def fun_l13_n792() + fun_l14_n447 +end + +def fun_l13_n793() + fun_l14_n931 +end + +def fun_l13_n794() + fun_l14_n608 +end + +def fun_l13_n795() + fun_l14_n131 +end + +def fun_l13_n796() + fun_l14_n961 +end + +def fun_l13_n797() + fun_l14_n109 +end + +def fun_l13_n798() + fun_l14_n766 +end + +def fun_l13_n799() + fun_l14_n149 +end + +def fun_l13_n800() + fun_l14_n44 +end + +def fun_l13_n801() + fun_l14_n893 +end + +def fun_l13_n802() + fun_l14_n826 +end + +def fun_l13_n803() + fun_l14_n372 +end + +def fun_l13_n804() + fun_l14_n7 +end + +def fun_l13_n805() + fun_l14_n655 +end + +def fun_l13_n806() + fun_l14_n418 +end + +def fun_l13_n807() + fun_l14_n746 +end + +def fun_l13_n808() + fun_l14_n810 +end + +def fun_l13_n809() + fun_l14_n838 +end + +def fun_l13_n810() + fun_l14_n522 +end + +def fun_l13_n811() + fun_l14_n723 +end + +def fun_l13_n812() + fun_l14_n476 +end + +def fun_l13_n813() + fun_l14_n760 +end + +def fun_l13_n814() + fun_l14_n728 +end + +def fun_l13_n815() + fun_l14_n926 +end + +def fun_l13_n816() + fun_l14_n16 +end + +def fun_l13_n817() + fun_l14_n888 +end + +def fun_l13_n818() + fun_l14_n812 +end + +def fun_l13_n819() + fun_l14_n430 +end + +def fun_l13_n820() + fun_l14_n211 +end + +def fun_l13_n821() + fun_l14_n204 +end + +def fun_l13_n822() + fun_l14_n868 +end + +def fun_l13_n823() + fun_l14_n460 +end + +def fun_l13_n824() + fun_l14_n597 +end + +def fun_l13_n825() + fun_l14_n217 +end + +def fun_l13_n826() + fun_l14_n425 +end + +def fun_l13_n827() + fun_l14_n216 +end + +def fun_l13_n828() + fun_l14_n931 +end + +def fun_l13_n829() + fun_l14_n3 +end + +def fun_l13_n830() + fun_l14_n55 +end + +def fun_l13_n831() + fun_l14_n362 +end + +def fun_l13_n832() + fun_l14_n591 +end + +def fun_l13_n833() + fun_l14_n339 +end + +def fun_l13_n834() + fun_l14_n641 +end + +def fun_l13_n835() + fun_l14_n389 +end + +def fun_l13_n836() + fun_l14_n668 +end + +def fun_l13_n837() + fun_l14_n845 +end + +def fun_l13_n838() + fun_l14_n202 +end + +def fun_l13_n839() + fun_l14_n575 +end + +def fun_l13_n840() + fun_l14_n357 +end + +def fun_l13_n841() + fun_l14_n271 +end + +def fun_l13_n842() + fun_l14_n876 +end + +def fun_l13_n843() + fun_l14_n983 +end + +def fun_l13_n844() + fun_l14_n512 +end + +def fun_l13_n845() + fun_l14_n205 +end + +def fun_l13_n846() + fun_l14_n463 +end + +def fun_l13_n847() + fun_l14_n422 +end + +def fun_l13_n848() + fun_l14_n54 +end + +def fun_l13_n849() + fun_l14_n575 +end + +def fun_l13_n850() + fun_l14_n187 +end + +def fun_l13_n851() + fun_l14_n151 +end + +def fun_l13_n852() + fun_l14_n176 +end + +def fun_l13_n853() + fun_l14_n501 +end + +def fun_l13_n854() + fun_l14_n390 +end + +def fun_l13_n855() + fun_l14_n902 +end + +def fun_l13_n856() + fun_l14_n354 +end + +def fun_l13_n857() + fun_l14_n245 +end + +def fun_l13_n858() + fun_l14_n299 +end + +def fun_l13_n859() + fun_l14_n532 +end + +def fun_l13_n860() + fun_l14_n263 +end + +def fun_l13_n861() + fun_l14_n811 +end + +def fun_l13_n862() + fun_l14_n298 +end + +def fun_l13_n863() + fun_l14_n635 +end + +def fun_l13_n864() + fun_l14_n913 +end + +def fun_l13_n865() + fun_l14_n901 +end + +def fun_l13_n866() + fun_l14_n380 +end + +def fun_l13_n867() + fun_l14_n9 +end + +def fun_l13_n868() + fun_l14_n982 +end + +def fun_l13_n869() + fun_l14_n703 +end + +def fun_l13_n870() + fun_l14_n272 +end + +def fun_l13_n871() + fun_l14_n209 +end + +def fun_l13_n872() + fun_l14_n429 +end + +def fun_l13_n873() + fun_l14_n108 +end + +def fun_l13_n874() + fun_l14_n116 +end + +def fun_l13_n875() + fun_l14_n169 +end + +def fun_l13_n876() + fun_l14_n642 +end + +def fun_l13_n877() + fun_l14_n265 +end + +def fun_l13_n878() + fun_l14_n227 +end + +def fun_l13_n879() + fun_l14_n202 +end + +def fun_l13_n880() + fun_l14_n336 +end + +def fun_l13_n881() + fun_l14_n856 +end + +def fun_l13_n882() + fun_l14_n821 +end + +def fun_l13_n883() + fun_l14_n275 +end + +def fun_l13_n884() + fun_l14_n903 +end + +def fun_l13_n885() + fun_l14_n407 +end + +def fun_l13_n886() + fun_l14_n129 +end + +def fun_l13_n887() + fun_l14_n68 +end + +def fun_l13_n888() + fun_l14_n124 +end + +def fun_l13_n889() + fun_l14_n936 +end + +def fun_l13_n890() + fun_l14_n401 +end + +def fun_l13_n891() + fun_l14_n574 +end + +def fun_l13_n892() + fun_l14_n593 +end + +def fun_l13_n893() + fun_l14_n262 +end + +def fun_l13_n894() + fun_l14_n215 +end + +def fun_l13_n895() + fun_l14_n49 +end + +def fun_l13_n896() + fun_l14_n767 +end + +def fun_l13_n897() + fun_l14_n280 +end + +def fun_l13_n898() + fun_l14_n112 +end + +def fun_l13_n899() + fun_l14_n202 +end + +def fun_l13_n900() + fun_l14_n73 +end + +def fun_l13_n901() + fun_l14_n798 +end + +def fun_l13_n902() + fun_l14_n827 +end + +def fun_l13_n903() + fun_l14_n824 +end + +def fun_l13_n904() + fun_l14_n414 +end + +def fun_l13_n905() + fun_l14_n502 +end + +def fun_l13_n906() + fun_l14_n323 +end + +def fun_l13_n907() + fun_l14_n216 +end + +def fun_l13_n908() + fun_l14_n173 +end + +def fun_l13_n909() + fun_l14_n26 +end + +def fun_l13_n910() + fun_l14_n40 +end + +def fun_l13_n911() + fun_l14_n883 +end + +def fun_l13_n912() + fun_l14_n523 +end + +def fun_l13_n913() + fun_l14_n979 +end + +def fun_l13_n914() + fun_l14_n921 +end + +def fun_l13_n915() + fun_l14_n842 +end + +def fun_l13_n916() + fun_l14_n943 +end + +def fun_l13_n917() + fun_l14_n97 +end + +def fun_l13_n918() + fun_l14_n515 +end + +def fun_l13_n919() + fun_l14_n145 +end + +def fun_l13_n920() + fun_l14_n497 +end + +def fun_l13_n921() + fun_l14_n264 +end + +def fun_l13_n922() + fun_l14_n901 +end + +def fun_l13_n923() + fun_l14_n436 +end + +def fun_l13_n924() + fun_l14_n315 +end + +def fun_l13_n925() + fun_l14_n512 +end + +def fun_l13_n926() + fun_l14_n611 +end + +def fun_l13_n927() + fun_l14_n103 +end + +def fun_l13_n928() + fun_l14_n149 +end + +def fun_l13_n929() + fun_l14_n407 +end + +def fun_l13_n930() + fun_l14_n380 +end + +def fun_l13_n931() + fun_l14_n429 +end + +def fun_l13_n932() + fun_l14_n870 +end + +def fun_l13_n933() + fun_l14_n274 +end + +def fun_l13_n934() + fun_l14_n57 +end + +def fun_l13_n935() + fun_l14_n718 +end + +def fun_l13_n936() + fun_l14_n571 +end + +def fun_l13_n937() + fun_l14_n447 +end + +def fun_l13_n938() + fun_l14_n742 +end + +def fun_l13_n939() + fun_l14_n811 +end + +def fun_l13_n940() + fun_l14_n148 +end + +def fun_l13_n941() + fun_l14_n795 +end + +def fun_l13_n942() + fun_l14_n807 +end + +def fun_l13_n943() + fun_l14_n279 +end + +def fun_l13_n944() + fun_l14_n939 +end + +def fun_l13_n945() + fun_l14_n435 +end + +def fun_l13_n946() + fun_l14_n937 +end + +def fun_l13_n947() + fun_l14_n543 +end + +def fun_l13_n948() + fun_l14_n374 +end + +def fun_l13_n949() + fun_l14_n707 +end + +def fun_l13_n950() + fun_l14_n866 +end + +def fun_l13_n951() + fun_l14_n67 +end + +def fun_l13_n952() + fun_l14_n752 +end + +def fun_l13_n953() + fun_l14_n113 +end + +def fun_l13_n954() + fun_l14_n358 +end + +def fun_l13_n955() + fun_l14_n432 +end + +def fun_l13_n956() + fun_l14_n132 +end + +def fun_l13_n957() + fun_l14_n807 +end + +def fun_l13_n958() + fun_l14_n293 +end + +def fun_l13_n959() + fun_l14_n681 +end + +def fun_l13_n960() + fun_l14_n335 +end + +def fun_l13_n961() + fun_l14_n285 +end + +def fun_l13_n962() + fun_l14_n366 +end + +def fun_l13_n963() + fun_l14_n674 +end + +def fun_l13_n964() + fun_l14_n914 +end + +def fun_l13_n965() + fun_l14_n776 +end + +def fun_l13_n966() + fun_l14_n297 +end + +def fun_l13_n967() + fun_l14_n623 +end + +def fun_l13_n968() + fun_l14_n357 +end + +def fun_l13_n969() + fun_l14_n430 +end + +def fun_l13_n970() + fun_l14_n201 +end + +def fun_l13_n971() + fun_l14_n482 +end + +def fun_l13_n972() + fun_l14_n363 +end + +def fun_l13_n973() + fun_l14_n530 +end + +def fun_l13_n974() + fun_l14_n892 +end + +def fun_l13_n975() + fun_l14_n548 +end + +def fun_l13_n976() + fun_l14_n257 +end + +def fun_l13_n977() + fun_l14_n449 +end + +def fun_l13_n978() + fun_l14_n346 +end + +def fun_l13_n979() + fun_l14_n448 +end + +def fun_l13_n980() + fun_l14_n912 +end + +def fun_l13_n981() + fun_l14_n358 +end + +def fun_l13_n982() + fun_l14_n55 +end + +def fun_l13_n983() + fun_l14_n712 +end + +def fun_l13_n984() + fun_l14_n179 +end + +def fun_l13_n985() + fun_l14_n749 +end + +def fun_l13_n986() + fun_l14_n469 +end + +def fun_l13_n987() + fun_l14_n557 +end + +def fun_l13_n988() + fun_l14_n383 +end + +def fun_l13_n989() + fun_l14_n929 +end + +def fun_l13_n990() + fun_l14_n659 +end + +def fun_l13_n991() + fun_l14_n285 +end + +def fun_l13_n992() + fun_l14_n779 +end + +def fun_l13_n993() + fun_l14_n235 +end + +def fun_l13_n994() + fun_l14_n756 +end + +def fun_l13_n995() + fun_l14_n249 +end + +def fun_l13_n996() + fun_l14_n8 +end + +def fun_l13_n997() + fun_l14_n785 +end + +def fun_l13_n998() + fun_l14_n945 +end + +def fun_l13_n999() + fun_l14_n410 +end + +def fun_l14_n0() + fun_l15_n85 +end + +def fun_l14_n1() + fun_l15_n932 +end + +def fun_l14_n2() + fun_l15_n422 +end + +def fun_l14_n3() + fun_l15_n439 +end + +def fun_l14_n4() + fun_l15_n186 +end + +def fun_l14_n5() + fun_l15_n914 +end + +def fun_l14_n6() + fun_l15_n830 +end + +def fun_l14_n7() + fun_l15_n384 +end + +def fun_l14_n8() + fun_l15_n200 +end + +def fun_l14_n9() + fun_l15_n72 +end + +def fun_l14_n10() + fun_l15_n498 +end + +def fun_l14_n11() + fun_l15_n247 +end + +def fun_l14_n12() + fun_l15_n432 +end + +def fun_l14_n13() + fun_l15_n718 +end + +def fun_l14_n14() + fun_l15_n568 +end + +def fun_l14_n15() + fun_l15_n971 +end + +def fun_l14_n16() + fun_l15_n545 +end + +def fun_l14_n17() + fun_l15_n441 +end + +def fun_l14_n18() + fun_l15_n532 +end + +def fun_l14_n19() + fun_l15_n484 +end + +def fun_l14_n20() + fun_l15_n659 +end + +def fun_l14_n21() + fun_l15_n494 +end + +def fun_l14_n22() + fun_l15_n379 +end + +def fun_l14_n23() + fun_l15_n180 +end + +def fun_l14_n24() + fun_l15_n955 +end + +def fun_l14_n25() + fun_l15_n536 +end + +def fun_l14_n26() + fun_l15_n940 +end + +def fun_l14_n27() + fun_l15_n3 +end + +def fun_l14_n28() + fun_l15_n520 +end + +def fun_l14_n29() + fun_l15_n478 +end + +def fun_l14_n30() + fun_l15_n865 +end + +def fun_l14_n31() + fun_l15_n330 +end + +def fun_l14_n32() + fun_l15_n217 +end + +def fun_l14_n33() + fun_l15_n381 +end + +def fun_l14_n34() + fun_l15_n88 +end + +def fun_l14_n35() + fun_l15_n111 +end + +def fun_l14_n36() + fun_l15_n181 +end + +def fun_l14_n37() + fun_l15_n978 +end + +def fun_l14_n38() + fun_l15_n596 +end + +def fun_l14_n39() + fun_l15_n764 +end + +def fun_l14_n40() + fun_l15_n779 +end + +def fun_l14_n41() + fun_l15_n994 +end + +def fun_l14_n42() + fun_l15_n90 +end + +def fun_l14_n43() + fun_l15_n329 +end + +def fun_l14_n44() + fun_l15_n684 +end + +def fun_l14_n45() + fun_l15_n191 +end + +def fun_l14_n46() + fun_l15_n282 +end + +def fun_l14_n47() + fun_l15_n915 +end + +def fun_l14_n48() + fun_l15_n330 +end + +def fun_l14_n49() + fun_l15_n136 +end + +def fun_l14_n50() + fun_l15_n167 +end + +def fun_l14_n51() + fun_l15_n418 +end + +def fun_l14_n52() + fun_l15_n822 +end + +def fun_l14_n53() + fun_l15_n557 +end + +def fun_l14_n54() + fun_l15_n155 +end + +def fun_l14_n55() + fun_l15_n629 +end + +def fun_l14_n56() + fun_l15_n694 +end + +def fun_l14_n57() + fun_l15_n577 +end + +def fun_l14_n58() + fun_l15_n412 +end + +def fun_l14_n59() + fun_l15_n618 +end + +def fun_l14_n60() + fun_l15_n873 +end + +def fun_l14_n61() + fun_l15_n758 +end + +def fun_l14_n62() + fun_l15_n820 +end + +def fun_l14_n63() + fun_l15_n89 +end + +def fun_l14_n64() + fun_l15_n788 +end + +def fun_l14_n65() + fun_l15_n390 +end + +def fun_l14_n66() + fun_l15_n177 +end + +def fun_l14_n67() + fun_l15_n972 +end + +def fun_l14_n68() + fun_l15_n124 +end + +def fun_l14_n69() + fun_l15_n426 +end + +def fun_l14_n70() + fun_l15_n490 +end + +def fun_l14_n71() + fun_l15_n963 +end + +def fun_l14_n72() + fun_l15_n960 +end + +def fun_l14_n73() + fun_l15_n111 +end + +def fun_l14_n74() + fun_l15_n535 +end + +def fun_l14_n75() + fun_l15_n936 +end + +def fun_l14_n76() + fun_l15_n17 +end + +def fun_l14_n77() + fun_l15_n732 +end + +def fun_l14_n78() + fun_l15_n905 +end + +def fun_l14_n79() + fun_l15_n658 +end + +def fun_l14_n80() + fun_l15_n869 +end + +def fun_l14_n81() + fun_l15_n966 +end + +def fun_l14_n82() + fun_l15_n413 +end + +def fun_l14_n83() + fun_l15_n360 +end + +def fun_l14_n84() + fun_l15_n955 +end + +def fun_l14_n85() + fun_l15_n612 +end + +def fun_l14_n86() + fun_l15_n665 +end + +def fun_l14_n87() + fun_l15_n570 +end + +def fun_l14_n88() + fun_l15_n381 +end + +def fun_l14_n89() + fun_l15_n169 +end + +def fun_l14_n90() + fun_l15_n33 +end + +def fun_l14_n91() + fun_l15_n574 +end + +def fun_l14_n92() + fun_l15_n826 +end + +def fun_l14_n93() + fun_l15_n183 +end + +def fun_l14_n94() + fun_l15_n878 +end + +def fun_l14_n95() + fun_l15_n898 +end + +def fun_l14_n96() + fun_l15_n296 +end + +def fun_l14_n97() + fun_l15_n769 +end + +def fun_l14_n98() + fun_l15_n41 +end + +def fun_l14_n99() + fun_l15_n644 +end + +def fun_l14_n100() + fun_l15_n218 +end + +def fun_l14_n101() + fun_l15_n267 +end + +def fun_l14_n102() + fun_l15_n846 +end + +def fun_l14_n103() + fun_l15_n409 +end + +def fun_l14_n104() + fun_l15_n776 +end + +def fun_l14_n105() + fun_l15_n224 +end + +def fun_l14_n106() + fun_l15_n401 +end + +def fun_l14_n107() + fun_l15_n726 +end + +def fun_l14_n108() + fun_l15_n624 +end + +def fun_l14_n109() + fun_l15_n319 +end + +def fun_l14_n110() + fun_l15_n180 +end + +def fun_l14_n111() + fun_l15_n370 +end + +def fun_l14_n112() + fun_l15_n834 +end + +def fun_l14_n113() + fun_l15_n397 +end + +def fun_l14_n114() + fun_l15_n685 +end + +def fun_l14_n115() + fun_l15_n286 +end + +def fun_l14_n116() + fun_l15_n740 +end + +def fun_l14_n117() + fun_l15_n122 +end + +def fun_l14_n118() + fun_l15_n112 +end + +def fun_l14_n119() + fun_l15_n658 +end + +def fun_l14_n120() + fun_l15_n844 +end + +def fun_l14_n121() + fun_l15_n715 +end + +def fun_l14_n122() + fun_l15_n14 +end + +def fun_l14_n123() + fun_l15_n677 +end + +def fun_l14_n124() + fun_l15_n742 +end + +def fun_l14_n125() + fun_l15_n311 +end + +def fun_l14_n126() + fun_l15_n234 +end + +def fun_l14_n127() + fun_l15_n746 +end + +def fun_l14_n128() + fun_l15_n616 +end + +def fun_l14_n129() + fun_l15_n529 +end + +def fun_l14_n130() + fun_l15_n330 +end + +def fun_l14_n131() + fun_l15_n182 +end + +def fun_l14_n132() + fun_l15_n588 +end + +def fun_l14_n133() + fun_l15_n477 +end + +def fun_l14_n134() + fun_l15_n267 +end + +def fun_l14_n135() + fun_l15_n667 +end + +def fun_l14_n136() + fun_l15_n233 +end + +def fun_l14_n137() + fun_l15_n630 +end + +def fun_l14_n138() + fun_l15_n993 +end + +def fun_l14_n139() + fun_l15_n79 +end + +def fun_l14_n140() + fun_l15_n2 +end + +def fun_l14_n141() + fun_l15_n774 +end + +def fun_l14_n142() + fun_l15_n762 +end + +def fun_l14_n143() + fun_l15_n832 +end + +def fun_l14_n144() + fun_l15_n359 +end + +def fun_l14_n145() + fun_l15_n344 +end + +def fun_l14_n146() + fun_l15_n521 +end + +def fun_l14_n147() + fun_l15_n867 +end + +def fun_l14_n148() + fun_l15_n132 +end + +def fun_l14_n149() + fun_l15_n19 +end + +def fun_l14_n150() + fun_l15_n513 +end + +def fun_l14_n151() + fun_l15_n732 +end + +def fun_l14_n152() + fun_l15_n709 +end + +def fun_l14_n153() + fun_l15_n876 +end + +def fun_l14_n154() + fun_l15_n400 +end + +def fun_l14_n155() + fun_l15_n539 +end + +def fun_l14_n156() + fun_l15_n895 +end + +def fun_l14_n157() + fun_l15_n208 +end + +def fun_l14_n158() + fun_l15_n268 +end + +def fun_l14_n159() + fun_l15_n286 +end + +def fun_l14_n160() + fun_l15_n457 +end + +def fun_l14_n161() + fun_l15_n985 +end + +def fun_l14_n162() + fun_l15_n48 +end + +def fun_l14_n163() + fun_l15_n495 +end + +def fun_l14_n164() + fun_l15_n10 +end + +def fun_l14_n165() + fun_l15_n368 +end + +def fun_l14_n166() + fun_l15_n266 +end + +def fun_l14_n167() + fun_l15_n587 +end + +def fun_l14_n168() + fun_l15_n210 +end + +def fun_l14_n169() + fun_l15_n5 +end + +def fun_l14_n170() + fun_l15_n635 +end + +def fun_l14_n171() + fun_l15_n47 +end + +def fun_l14_n172() + fun_l15_n88 +end + +def fun_l14_n173() + fun_l15_n79 +end + +def fun_l14_n174() + fun_l15_n791 +end + +def fun_l14_n175() + fun_l15_n812 +end + +def fun_l14_n176() + fun_l15_n112 +end + +def fun_l14_n177() + fun_l15_n590 +end + +def fun_l14_n178() + fun_l15_n59 +end + +def fun_l14_n179() + fun_l15_n275 +end + +def fun_l14_n180() + fun_l15_n206 +end + +def fun_l14_n181() + fun_l15_n385 +end + +def fun_l14_n182() + fun_l15_n809 +end + +def fun_l14_n183() + fun_l15_n704 +end + +def fun_l14_n184() + fun_l15_n331 +end + +def fun_l14_n185() + fun_l15_n819 +end + +def fun_l14_n186() + fun_l15_n165 +end + +def fun_l14_n187() + fun_l15_n623 +end + +def fun_l14_n188() + fun_l15_n528 +end + +def fun_l14_n189() + fun_l15_n393 +end + +def fun_l14_n190() + fun_l15_n712 +end + +def fun_l14_n191() + fun_l15_n951 +end + +def fun_l14_n192() + fun_l15_n584 +end + +def fun_l14_n193() + fun_l15_n984 +end + +def fun_l14_n194() + fun_l15_n283 +end + +def fun_l14_n195() + fun_l15_n821 +end + +def fun_l14_n196() + fun_l15_n105 +end + +def fun_l14_n197() + fun_l15_n49 +end + +def fun_l14_n198() + fun_l15_n191 +end + +def fun_l14_n199() + fun_l15_n751 +end + +def fun_l14_n200() + fun_l15_n108 +end + +def fun_l14_n201() + fun_l15_n121 +end + +def fun_l14_n202() + fun_l15_n751 +end + +def fun_l14_n203() + fun_l15_n837 +end + +def fun_l14_n204() + fun_l15_n747 +end + +def fun_l14_n205() + fun_l15_n682 +end + +def fun_l14_n206() + fun_l15_n689 +end + +def fun_l14_n207() + fun_l15_n562 +end + +def fun_l14_n208() + fun_l15_n580 +end + +def fun_l14_n209() + fun_l15_n556 +end + +def fun_l14_n210() + fun_l15_n155 +end + +def fun_l14_n211() + fun_l15_n661 +end + +def fun_l14_n212() + fun_l15_n571 +end + +def fun_l14_n213() + fun_l15_n341 +end + +def fun_l14_n214() + fun_l15_n200 +end + +def fun_l14_n215() + fun_l15_n78 +end + +def fun_l14_n216() + fun_l15_n922 +end + +def fun_l14_n217() + fun_l15_n437 +end + +def fun_l14_n218() + fun_l15_n263 +end + +def fun_l14_n219() + fun_l15_n971 +end + +def fun_l14_n220() + fun_l15_n65 +end + +def fun_l14_n221() + fun_l15_n951 +end + +def fun_l14_n222() + fun_l15_n163 +end + +def fun_l14_n223() + fun_l15_n732 +end + +def fun_l14_n224() + fun_l15_n424 +end + +def fun_l14_n225() + fun_l15_n91 +end + +def fun_l14_n226() + fun_l15_n711 +end + +def fun_l14_n227() + fun_l15_n224 +end + +def fun_l14_n228() + fun_l15_n885 +end + +def fun_l14_n229() + fun_l15_n489 +end + +def fun_l14_n230() + fun_l15_n733 +end + +def fun_l14_n231() + fun_l15_n355 +end + +def fun_l14_n232() + fun_l15_n819 +end + +def fun_l14_n233() + fun_l15_n934 +end + +def fun_l14_n234() + fun_l15_n643 +end + +def fun_l14_n235() + fun_l15_n555 +end + +def fun_l14_n236() + fun_l15_n508 +end + +def fun_l14_n237() + fun_l15_n181 +end + +def fun_l14_n238() + fun_l15_n171 +end + +def fun_l14_n239() + fun_l15_n834 +end + +def fun_l14_n240() + fun_l15_n599 +end + +def fun_l14_n241() + fun_l15_n492 +end + +def fun_l14_n242() + fun_l15_n131 +end + +def fun_l14_n243() + fun_l15_n838 +end + +def fun_l14_n244() + fun_l15_n745 +end + +def fun_l14_n245() + fun_l15_n653 +end + +def fun_l14_n246() + fun_l15_n905 +end + +def fun_l14_n247() + fun_l15_n962 +end + +def fun_l14_n248() + fun_l15_n269 +end + +def fun_l14_n249() + fun_l15_n920 +end + +def fun_l14_n250() + fun_l15_n428 +end + +def fun_l14_n251() + fun_l15_n305 +end + +def fun_l14_n252() + fun_l15_n630 +end + +def fun_l14_n253() + fun_l15_n458 +end + +def fun_l14_n254() + fun_l15_n933 +end + +def fun_l14_n255() + fun_l15_n852 +end + +def fun_l14_n256() + fun_l15_n855 +end + +def fun_l14_n257() + fun_l15_n207 +end + +def fun_l14_n258() + fun_l15_n865 +end + +def fun_l14_n259() + fun_l15_n958 +end + +def fun_l14_n260() + fun_l15_n230 +end + +def fun_l14_n261() + fun_l15_n872 +end + +def fun_l14_n262() + fun_l15_n963 +end + +def fun_l14_n263() + fun_l15_n945 +end + +def fun_l14_n264() + fun_l15_n410 +end + +def fun_l14_n265() + fun_l15_n735 +end + +def fun_l14_n266() + fun_l15_n496 +end + +def fun_l14_n267() + fun_l15_n110 +end + +def fun_l14_n268() + fun_l15_n267 +end + +def fun_l14_n269() + fun_l15_n699 +end + +def fun_l14_n270() + fun_l15_n812 +end + +def fun_l14_n271() + fun_l15_n273 +end + +def fun_l14_n272() + fun_l15_n499 +end + +def fun_l14_n273() + fun_l15_n341 +end + +def fun_l14_n274() + fun_l15_n512 +end + +def fun_l14_n275() + fun_l15_n110 +end + +def fun_l14_n276() + fun_l15_n62 +end + +def fun_l14_n277() + fun_l15_n541 +end + +def fun_l14_n278() + fun_l15_n622 +end + +def fun_l14_n279() + fun_l15_n456 +end + +def fun_l14_n280() + fun_l15_n527 +end + +def fun_l14_n281() + fun_l15_n141 +end + +def fun_l14_n282() + fun_l15_n266 +end + +def fun_l14_n283() + fun_l15_n817 +end + +def fun_l14_n284() + fun_l15_n448 +end + +def fun_l14_n285() + fun_l15_n208 +end + +def fun_l14_n286() + fun_l15_n368 +end + +def fun_l14_n287() + fun_l15_n947 +end + +def fun_l14_n288() + fun_l15_n192 +end + +def fun_l14_n289() + fun_l15_n68 +end + +def fun_l14_n290() + fun_l15_n704 +end + +def fun_l14_n291() + fun_l15_n278 +end + +def fun_l14_n292() + fun_l15_n352 +end + +def fun_l14_n293() + fun_l15_n629 +end + +def fun_l14_n294() + fun_l15_n404 +end + +def fun_l14_n295() + fun_l15_n89 +end + +def fun_l14_n296() + fun_l15_n920 +end + +def fun_l14_n297() + fun_l15_n984 +end + +def fun_l14_n298() + fun_l15_n198 +end + +def fun_l14_n299() + fun_l15_n524 +end + +def fun_l14_n300() + fun_l15_n891 +end + +def fun_l14_n301() + fun_l15_n921 +end + +def fun_l14_n302() + fun_l15_n785 +end + +def fun_l14_n303() + fun_l15_n618 +end + +def fun_l14_n304() + fun_l15_n387 +end + +def fun_l14_n305() + fun_l15_n361 +end + +def fun_l14_n306() + fun_l15_n535 +end + +def fun_l14_n307() + fun_l15_n137 +end + +def fun_l14_n308() + fun_l15_n77 +end + +def fun_l14_n309() + fun_l15_n877 +end + +def fun_l14_n310() + fun_l15_n178 +end + +def fun_l14_n311() + fun_l15_n67 +end + +def fun_l14_n312() + fun_l15_n539 +end + +def fun_l14_n313() + fun_l15_n971 +end + +def fun_l14_n314() + fun_l15_n743 +end + +def fun_l14_n315() + fun_l15_n787 +end + +def fun_l14_n316() + fun_l15_n451 +end + +def fun_l14_n317() + fun_l15_n12 +end + +def fun_l14_n318() + fun_l15_n303 +end + +def fun_l14_n319() + fun_l15_n210 +end + +def fun_l14_n320() + fun_l15_n853 +end + +def fun_l14_n321() + fun_l15_n154 +end + +def fun_l14_n322() + fun_l15_n71 +end + +def fun_l14_n323() + fun_l15_n448 +end + +def fun_l14_n324() + fun_l15_n178 +end + +def fun_l14_n325() + fun_l15_n312 +end + +def fun_l14_n326() + fun_l15_n671 +end + +def fun_l14_n327() + fun_l15_n282 +end + +def fun_l14_n328() + fun_l15_n315 +end + +def fun_l14_n329() + fun_l15_n449 +end + +def fun_l14_n330() + fun_l15_n338 +end + +def fun_l14_n331() + fun_l15_n260 +end + +def fun_l14_n332() + fun_l15_n664 +end + +def fun_l14_n333() + fun_l15_n312 +end + +def fun_l14_n334() + fun_l15_n202 +end + +def fun_l14_n335() + fun_l15_n969 +end + +def fun_l14_n336() + fun_l15_n698 +end + +def fun_l14_n337() + fun_l15_n802 +end + +def fun_l14_n338() + fun_l15_n175 +end + +def fun_l14_n339() + fun_l15_n646 +end + +def fun_l14_n340() + fun_l15_n145 +end + +def fun_l14_n341() + fun_l15_n19 +end + +def fun_l14_n342() + fun_l15_n764 +end + +def fun_l14_n343() + fun_l15_n970 +end + +def fun_l14_n344() + fun_l15_n519 +end + +def fun_l14_n345() + fun_l15_n121 +end + +def fun_l14_n346() + fun_l15_n299 +end + +def fun_l14_n347() + fun_l15_n553 +end + +def fun_l14_n348() + fun_l15_n618 +end + +def fun_l14_n349() + fun_l15_n725 +end + +def fun_l14_n350() + fun_l15_n635 +end + +def fun_l14_n351() + fun_l15_n382 +end + +def fun_l14_n352() + fun_l15_n529 +end + +def fun_l14_n353() + fun_l15_n168 +end + +def fun_l14_n354() + fun_l15_n948 +end + +def fun_l14_n355() + fun_l15_n192 +end + +def fun_l14_n356() + fun_l15_n27 +end + +def fun_l14_n357() + fun_l15_n254 +end + +def fun_l14_n358() + fun_l15_n384 +end + +def fun_l14_n359() + fun_l15_n559 +end + +def fun_l14_n360() + fun_l15_n560 +end + +def fun_l14_n361() + fun_l15_n781 +end + +def fun_l14_n362() + fun_l15_n494 +end + +def fun_l14_n363() + fun_l15_n997 +end + +def fun_l14_n364() + fun_l15_n203 +end + +def fun_l14_n365() + fun_l15_n61 +end + +def fun_l14_n366() + fun_l15_n190 +end + +def fun_l14_n367() + fun_l15_n755 +end + +def fun_l14_n368() + fun_l15_n876 +end + +def fun_l14_n369() + fun_l15_n761 +end + +def fun_l14_n370() + fun_l15_n641 +end + +def fun_l14_n371() + fun_l15_n307 +end + +def fun_l14_n372() + fun_l15_n351 +end + +def fun_l14_n373() + fun_l15_n929 +end + +def fun_l14_n374() + fun_l15_n455 +end + +def fun_l14_n375() + fun_l15_n740 +end + +def fun_l14_n376() + fun_l15_n803 +end + +def fun_l14_n377() + fun_l15_n544 +end + +def fun_l14_n378() + fun_l15_n666 +end + +def fun_l14_n379() + fun_l15_n274 +end + +def fun_l14_n380() + fun_l15_n374 +end + +def fun_l14_n381() + fun_l15_n108 +end + +def fun_l14_n382() + fun_l15_n632 +end + +def fun_l14_n383() + fun_l15_n782 +end + +def fun_l14_n384() + fun_l15_n16 +end + +def fun_l14_n385() + fun_l15_n323 +end + +def fun_l14_n386() + fun_l15_n923 +end + +def fun_l14_n387() + fun_l15_n929 +end + +def fun_l14_n388() + fun_l15_n318 +end + +def fun_l14_n389() + fun_l15_n929 +end + +def fun_l14_n390() + fun_l15_n633 +end + +def fun_l14_n391() + fun_l15_n159 +end + +def fun_l14_n392() + fun_l15_n18 +end + +def fun_l14_n393() + fun_l15_n997 +end + +def fun_l14_n394() + fun_l15_n585 +end + +def fun_l14_n395() + fun_l15_n216 +end + +def fun_l14_n396() + fun_l15_n665 +end + +def fun_l14_n397() + fun_l15_n51 +end + +def fun_l14_n398() + fun_l15_n681 +end + +def fun_l14_n399() + fun_l15_n921 +end + +def fun_l14_n400() + fun_l15_n937 +end + +def fun_l14_n401() + fun_l15_n251 +end + +def fun_l14_n402() + fun_l15_n359 +end + +def fun_l14_n403() + fun_l15_n262 +end + +def fun_l14_n404() + fun_l15_n631 +end + +def fun_l14_n405() + fun_l15_n218 +end + +def fun_l14_n406() + fun_l15_n138 +end + +def fun_l14_n407() + fun_l15_n695 +end + +def fun_l14_n408() + fun_l15_n95 +end + +def fun_l14_n409() + fun_l15_n166 +end + +def fun_l14_n410() + fun_l15_n566 +end + +def fun_l14_n411() + fun_l15_n322 +end + +def fun_l14_n412() + fun_l15_n278 +end + +def fun_l14_n413() + fun_l15_n144 +end + +def fun_l14_n414() + fun_l15_n949 +end + +def fun_l14_n415() + fun_l15_n351 +end + +def fun_l14_n416() + fun_l15_n887 +end + +def fun_l14_n417() + fun_l15_n501 +end + +def fun_l14_n418() + fun_l15_n997 +end + +def fun_l14_n419() + fun_l15_n212 +end + +def fun_l14_n420() + fun_l15_n725 +end + +def fun_l14_n421() + fun_l15_n728 +end + +def fun_l14_n422() + fun_l15_n923 +end + +def fun_l14_n423() + fun_l15_n694 +end + +def fun_l14_n424() + fun_l15_n472 +end + +def fun_l14_n425() + fun_l15_n967 +end + +def fun_l14_n426() + fun_l15_n908 +end + +def fun_l14_n427() + fun_l15_n199 +end + +def fun_l14_n428() + fun_l15_n384 +end + +def fun_l14_n429() + fun_l15_n485 +end + +def fun_l14_n430() + fun_l15_n767 +end + +def fun_l14_n431() + fun_l15_n337 +end + +def fun_l14_n432() + fun_l15_n664 +end + +def fun_l14_n433() + fun_l15_n735 +end + +def fun_l14_n434() + fun_l15_n76 +end + +def fun_l14_n435() + fun_l15_n879 +end + +def fun_l14_n436() + fun_l15_n815 +end + +def fun_l14_n437() + fun_l15_n290 +end + +def fun_l14_n438() + fun_l15_n836 +end + +def fun_l14_n439() + fun_l15_n56 +end + +def fun_l14_n440() + fun_l15_n671 +end + +def fun_l14_n441() + fun_l15_n90 +end + +def fun_l14_n442() + fun_l15_n930 +end + +def fun_l14_n443() + fun_l15_n754 +end + +def fun_l14_n444() + fun_l15_n241 +end + +def fun_l14_n445() + fun_l15_n362 +end + +def fun_l14_n446() + fun_l15_n260 +end + +def fun_l14_n447() + fun_l15_n846 +end + +def fun_l14_n448() + fun_l15_n754 +end + +def fun_l14_n449() + fun_l15_n571 +end + +def fun_l14_n450() + fun_l15_n602 +end + +def fun_l14_n451() + fun_l15_n243 +end + +def fun_l14_n452() + fun_l15_n59 +end + +def fun_l14_n453() + fun_l15_n660 +end + +def fun_l14_n454() + fun_l15_n338 +end + +def fun_l14_n455() + fun_l15_n461 +end + +def fun_l14_n456() + fun_l15_n702 +end + +def fun_l14_n457() + fun_l15_n878 +end + +def fun_l14_n458() + fun_l15_n625 +end + +def fun_l14_n459() + fun_l15_n762 +end + +def fun_l14_n460() + fun_l15_n36 +end + +def fun_l14_n461() + fun_l15_n432 +end + +def fun_l14_n462() + fun_l15_n685 +end + +def fun_l14_n463() + fun_l15_n398 +end + +def fun_l14_n464() + fun_l15_n828 +end + +def fun_l14_n465() + fun_l15_n306 +end + +def fun_l14_n466() + fun_l15_n717 +end + +def fun_l14_n467() + fun_l15_n271 +end + +def fun_l14_n468() + fun_l15_n444 +end + +def fun_l14_n469() + fun_l15_n82 +end + +def fun_l14_n470() + fun_l15_n363 +end + +def fun_l14_n471() + fun_l15_n648 +end + +def fun_l14_n472() + fun_l15_n33 +end + +def fun_l14_n473() + fun_l15_n968 +end + +def fun_l14_n474() + fun_l15_n331 +end + +def fun_l14_n475() + fun_l15_n228 +end + +def fun_l14_n476() + fun_l15_n944 +end + +def fun_l14_n477() + fun_l15_n771 +end + +def fun_l14_n478() + fun_l15_n228 +end + +def fun_l14_n479() + fun_l15_n442 +end + +def fun_l14_n480() + fun_l15_n75 +end + +def fun_l14_n481() + fun_l15_n911 +end + +def fun_l14_n482() + fun_l15_n591 +end + +def fun_l14_n483() + fun_l15_n929 +end + +def fun_l14_n484() + fun_l15_n504 +end + +def fun_l14_n485() + fun_l15_n48 +end + +def fun_l14_n486() + fun_l15_n592 +end + +def fun_l14_n487() + fun_l15_n399 +end + +def fun_l14_n488() + fun_l15_n467 +end + +def fun_l14_n489() + fun_l15_n192 +end + +def fun_l14_n490() + fun_l15_n347 +end + +def fun_l14_n491() + fun_l15_n517 +end + +def fun_l14_n492() + fun_l15_n436 +end + +def fun_l14_n493() + fun_l15_n50 +end + +def fun_l14_n494() + fun_l15_n237 +end + +def fun_l14_n495() + fun_l15_n878 +end + +def fun_l14_n496() + fun_l15_n46 +end + +def fun_l14_n497() + fun_l15_n499 +end + +def fun_l14_n498() + fun_l15_n779 +end + +def fun_l14_n499() + fun_l15_n763 +end + +def fun_l14_n500() + fun_l15_n195 +end + +def fun_l14_n501() + fun_l15_n868 +end + +def fun_l14_n502() + fun_l15_n83 +end + +def fun_l14_n503() + fun_l15_n386 +end + +def fun_l14_n504() + fun_l15_n907 +end + +def fun_l14_n505() + fun_l15_n889 +end + +def fun_l14_n506() + fun_l15_n314 +end + +def fun_l14_n507() + fun_l15_n24 +end + +def fun_l14_n508() + fun_l15_n122 +end + +def fun_l14_n509() + fun_l15_n772 +end + +def fun_l14_n510() + fun_l15_n204 +end + +def fun_l14_n511() + fun_l15_n646 +end + +def fun_l14_n512() + fun_l15_n105 +end + +def fun_l14_n513() + fun_l15_n393 +end + +def fun_l14_n514() + fun_l15_n533 +end + +def fun_l14_n515() + fun_l15_n572 +end + +def fun_l14_n516() + fun_l15_n360 +end + +def fun_l14_n517() + fun_l15_n241 +end + +def fun_l14_n518() + fun_l15_n962 +end + +def fun_l14_n519() + fun_l15_n771 +end + +def fun_l14_n520() + fun_l15_n379 +end + +def fun_l14_n521() + fun_l15_n749 +end + +def fun_l14_n522() + fun_l15_n601 +end + +def fun_l14_n523() + fun_l15_n0 +end + +def fun_l14_n524() + fun_l15_n345 +end + +def fun_l14_n525() + fun_l15_n896 +end + +def fun_l14_n526() + fun_l15_n612 +end + +def fun_l14_n527() + fun_l15_n897 +end + +def fun_l14_n528() + fun_l15_n760 +end + +def fun_l14_n529() + fun_l15_n283 +end + +def fun_l14_n530() + fun_l15_n269 +end + +def fun_l14_n531() + fun_l15_n967 +end + +def fun_l14_n532() + fun_l15_n399 +end + +def fun_l14_n533() + fun_l15_n343 +end + +def fun_l14_n534() + fun_l15_n590 +end + +def fun_l14_n535() + fun_l15_n37 +end + +def fun_l14_n536() + fun_l15_n882 +end + +def fun_l14_n537() + fun_l15_n275 +end + +def fun_l14_n538() + fun_l15_n169 +end + +def fun_l14_n539() + fun_l15_n474 +end + +def fun_l14_n540() + fun_l15_n993 +end + +def fun_l14_n541() + fun_l15_n872 +end + +def fun_l14_n542() + fun_l15_n650 +end + +def fun_l14_n543() + fun_l15_n238 +end + +def fun_l14_n544() + fun_l15_n80 +end + +def fun_l14_n545() + fun_l15_n585 +end + +def fun_l14_n546() + fun_l15_n961 +end + +def fun_l14_n547() + fun_l15_n574 +end + +def fun_l14_n548() + fun_l15_n447 +end + +def fun_l14_n549() + fun_l15_n405 +end + +def fun_l14_n550() + fun_l15_n347 +end + +def fun_l14_n551() + fun_l15_n326 +end + +def fun_l14_n552() + fun_l15_n679 +end + +def fun_l14_n553() + fun_l15_n848 +end + +def fun_l14_n554() + fun_l15_n391 +end + +def fun_l14_n555() + fun_l15_n293 +end + +def fun_l14_n556() + fun_l15_n997 +end + +def fun_l14_n557() + fun_l15_n247 +end + +def fun_l14_n558() + fun_l15_n138 +end + +def fun_l14_n559() + fun_l15_n737 +end + +def fun_l14_n560() + fun_l15_n764 +end + +def fun_l14_n561() + fun_l15_n541 +end + +def fun_l14_n562() + fun_l15_n373 +end + +def fun_l14_n563() + fun_l15_n562 +end + +def fun_l14_n564() + fun_l15_n626 +end + +def fun_l14_n565() + fun_l15_n601 +end + +def fun_l14_n566() + fun_l15_n547 +end + +def fun_l14_n567() + fun_l15_n226 +end + +def fun_l14_n568() + fun_l15_n182 +end + +def fun_l14_n569() + fun_l15_n647 +end + +def fun_l14_n570() + fun_l15_n912 +end + +def fun_l14_n571() + fun_l15_n33 +end + +def fun_l14_n572() + fun_l15_n397 +end + +def fun_l14_n573() + fun_l15_n413 +end + +def fun_l14_n574() + fun_l15_n714 +end + +def fun_l14_n575() + fun_l15_n930 +end + +def fun_l14_n576() + fun_l15_n35 +end + +def fun_l14_n577() + fun_l15_n868 +end + +def fun_l14_n578() + fun_l15_n606 +end + +def fun_l14_n579() + fun_l15_n516 +end + +def fun_l14_n580() + fun_l15_n127 +end + +def fun_l14_n581() + fun_l15_n689 +end + +def fun_l14_n582() + fun_l15_n346 +end + +def fun_l14_n583() + fun_l15_n352 +end + +def fun_l14_n584() + fun_l15_n810 +end + +def fun_l14_n585() + fun_l15_n38 +end + +def fun_l14_n586() + fun_l15_n751 +end + +def fun_l14_n587() + fun_l15_n888 +end + +def fun_l14_n588() + fun_l15_n938 +end + +def fun_l14_n589() + fun_l15_n941 +end + +def fun_l14_n590() + fun_l15_n768 +end + +def fun_l14_n591() + fun_l15_n544 +end + +def fun_l14_n592() + fun_l15_n393 +end + +def fun_l14_n593() + fun_l15_n74 +end + +def fun_l14_n594() + fun_l15_n812 +end + +def fun_l14_n595() + fun_l15_n94 +end + +def fun_l14_n596() + fun_l15_n122 +end + +def fun_l14_n597() + fun_l15_n552 +end + +def fun_l14_n598() + fun_l15_n586 +end + +def fun_l14_n599() + fun_l15_n100 +end + +def fun_l14_n600() + fun_l15_n338 +end + +def fun_l14_n601() + fun_l15_n627 +end + +def fun_l14_n602() + fun_l15_n445 +end + +def fun_l14_n603() + fun_l15_n734 +end + +def fun_l14_n604() + fun_l15_n852 +end + +def fun_l14_n605() + fun_l15_n908 +end + +def fun_l14_n606() + fun_l15_n736 +end + +def fun_l14_n607() + fun_l15_n590 +end + +def fun_l14_n608() + fun_l15_n988 +end + +def fun_l14_n609() + fun_l15_n241 +end + +def fun_l14_n610() + fun_l15_n375 +end + +def fun_l14_n611() + fun_l15_n25 +end + +def fun_l14_n612() + fun_l15_n176 +end + +def fun_l14_n613() + fun_l15_n375 +end + +def fun_l14_n614() + fun_l15_n248 +end + +def fun_l14_n615() + fun_l15_n393 +end + +def fun_l14_n616() + fun_l15_n2 +end + +def fun_l14_n617() + fun_l15_n964 +end + +def fun_l14_n618() + fun_l15_n581 +end + +def fun_l14_n619() + fun_l15_n190 +end + +def fun_l14_n620() + fun_l15_n847 +end + +def fun_l14_n621() + fun_l15_n748 +end + +def fun_l14_n622() + fun_l15_n27 +end + +def fun_l14_n623() + fun_l15_n984 +end + +def fun_l14_n624() + fun_l15_n728 +end + +def fun_l14_n625() + fun_l15_n740 +end + +def fun_l14_n626() + fun_l15_n480 +end + +def fun_l14_n627() + fun_l15_n175 +end + +def fun_l14_n628() + fun_l15_n152 +end + +def fun_l14_n629() + fun_l15_n880 +end + +def fun_l14_n630() + fun_l15_n337 +end + +def fun_l14_n631() + fun_l15_n862 +end + +def fun_l14_n632() + fun_l15_n367 +end + +def fun_l14_n633() + fun_l15_n768 +end + +def fun_l14_n634() + fun_l15_n178 +end + +def fun_l14_n635() + fun_l15_n693 +end + +def fun_l14_n636() + fun_l15_n176 +end + +def fun_l14_n637() + fun_l15_n348 +end + +def fun_l14_n638() + fun_l15_n31 +end + +def fun_l14_n639() + fun_l15_n601 +end + +def fun_l14_n640() + fun_l15_n824 +end + +def fun_l14_n641() + fun_l15_n920 +end + +def fun_l14_n642() + fun_l15_n464 +end + +def fun_l14_n643() + fun_l15_n747 +end + +def fun_l14_n644() + fun_l15_n378 +end + +def fun_l14_n645() + fun_l15_n88 +end + +def fun_l14_n646() + fun_l15_n267 +end + +def fun_l14_n647() + fun_l15_n805 +end + +def fun_l14_n648() + fun_l15_n793 +end + +def fun_l14_n649() + fun_l15_n135 +end + +def fun_l14_n650() + fun_l15_n51 +end + +def fun_l14_n651() + fun_l15_n500 +end + +def fun_l14_n652() + fun_l15_n726 +end + +def fun_l14_n653() + fun_l15_n736 +end + +def fun_l14_n654() + fun_l15_n691 +end + +def fun_l14_n655() + fun_l15_n718 +end + +def fun_l14_n656() + fun_l15_n456 +end + +def fun_l14_n657() + fun_l15_n868 +end + +def fun_l14_n658() + fun_l15_n818 +end + +def fun_l14_n659() + fun_l15_n693 +end + +def fun_l14_n660() + fun_l15_n117 +end + +def fun_l14_n661() + fun_l15_n872 +end + +def fun_l14_n662() + fun_l15_n312 +end + +def fun_l14_n663() + fun_l15_n538 +end + +def fun_l14_n664() + fun_l15_n449 +end + +def fun_l14_n665() + fun_l15_n954 +end + +def fun_l14_n666() + fun_l15_n163 +end + +def fun_l14_n667() + fun_l15_n291 +end + +def fun_l14_n668() + fun_l15_n17 +end + +def fun_l14_n669() + fun_l15_n189 +end + +def fun_l14_n670() + fun_l15_n25 +end + +def fun_l14_n671() + fun_l15_n381 +end + +def fun_l14_n672() + fun_l15_n66 +end + +def fun_l14_n673() + fun_l15_n28 +end + +def fun_l14_n674() + fun_l15_n79 +end + +def fun_l14_n675() + fun_l15_n237 +end + +def fun_l14_n676() + fun_l15_n301 +end + +def fun_l14_n677() + fun_l15_n876 +end + +def fun_l14_n678() + fun_l15_n573 +end + +def fun_l14_n679() + fun_l15_n758 +end + +def fun_l14_n680() + fun_l15_n152 +end + +def fun_l14_n681() + fun_l15_n597 +end + +def fun_l14_n682() + fun_l15_n872 +end + +def fun_l14_n683() + fun_l15_n329 +end + +def fun_l14_n684() + fun_l15_n537 +end + +def fun_l14_n685() + fun_l15_n379 +end + +def fun_l14_n686() + fun_l15_n748 +end + +def fun_l14_n687() + fun_l15_n407 +end + +def fun_l14_n688() + fun_l15_n762 +end + +def fun_l14_n689() + fun_l15_n792 +end + +def fun_l14_n690() + fun_l15_n179 +end + +def fun_l14_n691() + fun_l15_n855 +end + +def fun_l14_n692() + fun_l15_n635 +end + +def fun_l14_n693() + fun_l15_n807 +end + +def fun_l14_n694() + fun_l15_n957 +end + +def fun_l14_n695() + fun_l15_n130 +end + +def fun_l14_n696() + fun_l15_n183 +end + +def fun_l14_n697() + fun_l15_n881 +end + +def fun_l14_n698() + fun_l15_n744 +end + +def fun_l14_n699() + fun_l15_n360 +end + +def fun_l14_n700() + fun_l15_n661 +end + +def fun_l14_n701() + fun_l15_n136 +end + +def fun_l14_n702() + fun_l15_n868 +end + +def fun_l14_n703() + fun_l15_n718 +end + +def fun_l14_n704() + fun_l15_n253 +end + +def fun_l14_n705() + fun_l15_n272 +end + +def fun_l14_n706() + fun_l15_n474 +end + +def fun_l14_n707() + fun_l15_n457 +end + +def fun_l14_n708() + fun_l15_n836 +end + +def fun_l14_n709() + fun_l15_n141 +end + +def fun_l14_n710() + fun_l15_n80 +end + +def fun_l14_n711() + fun_l15_n538 +end + +def fun_l14_n712() + fun_l15_n68 +end + +def fun_l14_n713() + fun_l15_n603 +end + +def fun_l14_n714() + fun_l15_n604 +end + +def fun_l14_n715() + fun_l15_n415 +end + +def fun_l14_n716() + fun_l15_n269 +end + +def fun_l14_n717() + fun_l15_n836 +end + +def fun_l14_n718() + fun_l15_n599 +end + +def fun_l14_n719() + fun_l15_n373 +end + +def fun_l14_n720() + fun_l15_n256 +end + +def fun_l14_n721() + fun_l15_n18 +end + +def fun_l14_n722() + fun_l15_n719 +end + +def fun_l14_n723() + fun_l15_n994 +end + +def fun_l14_n724() + fun_l15_n361 +end + +def fun_l14_n725() + fun_l15_n789 +end + +def fun_l14_n726() + fun_l15_n453 +end + +def fun_l14_n727() + fun_l15_n950 +end + +def fun_l14_n728() + fun_l15_n410 +end + +def fun_l14_n729() + fun_l15_n678 +end + +def fun_l14_n730() + fun_l15_n948 +end + +def fun_l14_n731() + fun_l15_n964 +end + +def fun_l14_n732() + fun_l15_n199 +end + +def fun_l14_n733() + fun_l15_n812 +end + +def fun_l14_n734() + fun_l15_n983 +end + +def fun_l14_n735() + fun_l15_n550 +end + +def fun_l14_n736() + fun_l15_n776 +end + +def fun_l14_n737() + fun_l15_n510 +end + +def fun_l14_n738() + fun_l15_n959 +end + +def fun_l14_n739() + fun_l15_n537 +end + +def fun_l14_n740() + fun_l15_n717 +end + +def fun_l14_n741() + fun_l15_n437 +end + +def fun_l14_n742() + fun_l15_n364 +end + +def fun_l14_n743() + fun_l15_n785 +end + +def fun_l14_n744() + fun_l15_n658 +end + +def fun_l14_n745() + fun_l15_n462 +end + +def fun_l14_n746() + fun_l15_n263 +end + +def fun_l14_n747() + fun_l15_n657 +end + +def fun_l14_n748() + fun_l15_n395 +end + +def fun_l14_n749() + fun_l15_n852 +end + +def fun_l14_n750() + fun_l15_n809 +end + +def fun_l14_n751() + fun_l15_n959 +end + +def fun_l14_n752() + fun_l15_n547 +end + +def fun_l14_n753() + fun_l15_n719 +end + +def fun_l14_n754() + fun_l15_n118 +end + +def fun_l14_n755() + fun_l15_n503 +end + +def fun_l14_n756() + fun_l15_n112 +end + +def fun_l14_n757() + fun_l15_n39 +end + +def fun_l14_n758() + fun_l15_n12 +end + +def fun_l14_n759() + fun_l15_n692 +end + +def fun_l14_n760() + fun_l15_n276 +end + +def fun_l14_n761() + fun_l15_n771 +end + +def fun_l14_n762() + fun_l15_n643 +end + +def fun_l14_n763() + fun_l15_n820 +end + +def fun_l14_n764() + fun_l15_n956 +end + +def fun_l14_n765() + fun_l15_n169 +end + +def fun_l14_n766() + fun_l15_n558 +end + +def fun_l14_n767() + fun_l15_n106 +end + +def fun_l14_n768() + fun_l15_n813 +end + +def fun_l14_n769() + fun_l15_n65 +end + +def fun_l14_n770() + fun_l15_n214 +end + +def fun_l14_n771() + fun_l15_n264 +end + +def fun_l14_n772() + fun_l15_n687 +end + +def fun_l14_n773() + fun_l15_n8 +end + +def fun_l14_n774() + fun_l15_n703 +end + +def fun_l14_n775() + fun_l15_n971 +end + +def fun_l14_n776() + fun_l15_n144 +end + +def fun_l14_n777() + fun_l15_n542 +end + +def fun_l14_n778() + fun_l15_n57 +end + +def fun_l14_n779() + fun_l15_n772 +end + +def fun_l14_n780() + fun_l15_n347 +end + +def fun_l14_n781() + fun_l15_n895 +end + +def fun_l14_n782() + fun_l15_n547 +end + +def fun_l14_n783() + fun_l15_n254 +end + +def fun_l14_n784() + fun_l15_n358 +end + +def fun_l14_n785() + fun_l15_n861 +end + +def fun_l14_n786() + fun_l15_n169 +end + +def fun_l14_n787() + fun_l15_n607 +end + +def fun_l14_n788() + fun_l15_n909 +end + +def fun_l14_n789() + fun_l15_n796 +end + +def fun_l14_n790() + fun_l15_n414 +end + +def fun_l14_n791() + fun_l15_n575 +end + +def fun_l14_n792() + fun_l15_n115 +end + +def fun_l14_n793() + fun_l15_n289 +end + +def fun_l14_n794() + fun_l15_n285 +end + +def fun_l14_n795() + fun_l15_n563 +end + +def fun_l14_n796() + fun_l15_n78 +end + +def fun_l14_n797() + fun_l15_n913 +end + +def fun_l14_n798() + fun_l15_n852 +end + +def fun_l14_n799() + fun_l15_n779 +end + +def fun_l14_n800() + fun_l15_n301 +end + +def fun_l14_n801() + fun_l15_n180 +end + +def fun_l14_n802() + fun_l15_n618 +end + +def fun_l14_n803() + fun_l15_n48 +end + +def fun_l14_n804() + fun_l15_n839 +end + +def fun_l14_n805() + fun_l15_n608 +end + +def fun_l14_n806() + fun_l15_n408 +end + +def fun_l14_n807() + fun_l15_n23 +end + +def fun_l14_n808() + fun_l15_n723 +end + +def fun_l14_n809() + fun_l15_n849 +end + +def fun_l14_n810() + fun_l15_n112 +end + +def fun_l14_n811() + fun_l15_n801 +end + +def fun_l14_n812() + fun_l15_n905 +end + +def fun_l14_n813() + fun_l15_n40 +end + +def fun_l14_n814() + fun_l15_n628 +end + +def fun_l14_n815() + fun_l15_n761 +end + +def fun_l14_n816() + fun_l15_n631 +end + +def fun_l14_n817() + fun_l15_n565 +end + +def fun_l14_n818() + fun_l15_n985 +end + +def fun_l14_n819() + fun_l15_n408 +end + +def fun_l14_n820() + fun_l15_n173 +end + +def fun_l14_n821() + fun_l15_n508 +end + +def fun_l14_n822() + fun_l15_n641 +end + +def fun_l14_n823() + fun_l15_n348 +end + +def fun_l14_n824() + fun_l15_n988 +end + +def fun_l14_n825() + fun_l15_n790 +end + +def fun_l14_n826() + fun_l15_n915 +end + +def fun_l14_n827() + fun_l15_n727 +end + +def fun_l14_n828() + fun_l15_n613 +end + +def fun_l14_n829() + fun_l15_n21 +end + +def fun_l14_n830() + fun_l15_n533 +end + +def fun_l14_n831() + fun_l15_n904 +end + +def fun_l14_n832() + fun_l15_n586 +end + +def fun_l14_n833() + fun_l15_n794 +end + +def fun_l14_n834() + fun_l15_n475 +end + +def fun_l14_n835() + fun_l15_n14 +end + +def fun_l14_n836() + fun_l15_n69 +end + +def fun_l14_n837() + fun_l15_n850 +end + +def fun_l14_n838() + fun_l15_n426 +end + +def fun_l14_n839() + fun_l15_n552 +end + +def fun_l14_n840() + fun_l15_n968 +end + +def fun_l14_n841() + fun_l15_n305 +end + +def fun_l14_n842() + fun_l15_n865 +end + +def fun_l14_n843() + fun_l15_n190 +end + +def fun_l14_n844() + fun_l15_n610 +end + +def fun_l14_n845() + fun_l15_n478 +end + +def fun_l14_n846() + fun_l15_n640 +end + +def fun_l14_n847() + fun_l15_n294 +end + +def fun_l14_n848() + fun_l15_n493 +end + +def fun_l14_n849() + fun_l15_n580 +end + +def fun_l14_n850() + fun_l15_n173 +end + +def fun_l14_n851() + fun_l15_n134 +end + +def fun_l14_n852() + fun_l15_n352 +end + +def fun_l14_n853() + fun_l15_n738 +end + +def fun_l14_n854() + fun_l15_n289 +end + +def fun_l14_n855() + fun_l15_n44 +end + +def fun_l14_n856() + fun_l15_n200 +end + +def fun_l14_n857() + fun_l15_n584 +end + +def fun_l14_n858() + fun_l15_n787 +end + +def fun_l14_n859() + fun_l15_n901 +end + +def fun_l14_n860() + fun_l15_n103 +end + +def fun_l14_n861() + fun_l15_n628 +end + +def fun_l14_n862() + fun_l15_n521 +end + +def fun_l14_n863() + fun_l15_n465 +end + +def fun_l14_n864() + fun_l15_n649 +end + +def fun_l14_n865() + fun_l15_n60 +end + +def fun_l14_n866() + fun_l15_n567 +end + +def fun_l14_n867() + fun_l15_n775 +end + +def fun_l14_n868() + fun_l15_n333 +end + +def fun_l14_n869() + fun_l15_n791 +end + +def fun_l14_n870() + fun_l15_n401 +end + +def fun_l14_n871() + fun_l15_n289 +end + +def fun_l14_n872() + fun_l15_n376 +end + +def fun_l14_n873() + fun_l15_n825 +end + +def fun_l14_n874() + fun_l15_n233 +end + +def fun_l14_n875() + fun_l15_n742 +end + +def fun_l14_n876() + fun_l15_n308 +end + +def fun_l14_n877() + fun_l15_n793 +end + +def fun_l14_n878() + fun_l15_n937 +end + +def fun_l14_n879() + fun_l15_n469 +end + +def fun_l14_n880() + fun_l15_n129 +end + +def fun_l14_n881() + fun_l15_n221 +end + +def fun_l14_n882() + fun_l15_n900 +end + +def fun_l14_n883() + fun_l15_n548 +end + +def fun_l14_n884() + fun_l15_n782 +end + +def fun_l14_n885() + fun_l15_n99 +end + +def fun_l14_n886() + fun_l15_n33 +end + +def fun_l14_n887() + fun_l15_n139 +end + +def fun_l14_n888() + fun_l15_n832 +end + +def fun_l14_n889() + fun_l15_n24 +end + +def fun_l14_n890() + fun_l15_n342 +end + +def fun_l14_n891() + fun_l15_n329 +end + +def fun_l14_n892() + fun_l15_n706 +end + +def fun_l14_n893() + fun_l15_n873 +end + +def fun_l14_n894() + fun_l15_n776 +end + +def fun_l14_n895() + fun_l15_n799 +end + +def fun_l14_n896() + fun_l15_n560 +end + +def fun_l14_n897() + fun_l15_n372 +end + +def fun_l14_n898() + fun_l15_n370 +end + +def fun_l14_n899() + fun_l15_n385 +end + +def fun_l14_n900() + fun_l15_n648 +end + +def fun_l14_n901() + fun_l15_n376 +end + +def fun_l14_n902() + fun_l15_n527 +end + +def fun_l14_n903() + fun_l15_n190 +end + +def fun_l14_n904() + fun_l15_n633 +end + +def fun_l14_n905() + fun_l15_n684 +end + +def fun_l14_n906() + fun_l15_n8 +end + +def fun_l14_n907() + fun_l15_n814 +end + +def fun_l14_n908() + fun_l15_n50 +end + +def fun_l14_n909() + fun_l15_n646 +end + +def fun_l14_n910() + fun_l15_n442 +end + +def fun_l14_n911() + fun_l15_n514 +end + +def fun_l14_n912() + fun_l15_n137 +end + +def fun_l14_n913() + fun_l15_n126 +end + +def fun_l14_n914() + fun_l15_n266 +end + +def fun_l14_n915() + fun_l15_n479 +end + +def fun_l14_n916() + fun_l15_n985 +end + +def fun_l14_n917() + fun_l15_n88 +end + +def fun_l14_n918() + fun_l15_n438 +end + +def fun_l14_n919() + fun_l15_n347 +end + +def fun_l14_n920() + fun_l15_n215 +end + +def fun_l14_n921() + fun_l15_n220 +end + +def fun_l14_n922() + fun_l15_n507 +end + +def fun_l14_n923() + fun_l15_n501 +end + +def fun_l14_n924() + fun_l15_n955 +end + +def fun_l14_n925() + fun_l15_n59 +end + +def fun_l14_n926() + fun_l15_n850 +end + +def fun_l14_n927() + fun_l15_n447 +end + +def fun_l14_n928() + fun_l15_n298 +end + +def fun_l14_n929() + fun_l15_n173 +end + +def fun_l14_n930() + fun_l15_n216 +end + +def fun_l14_n931() + fun_l15_n594 +end + +def fun_l14_n932() + fun_l15_n662 +end + +def fun_l14_n933() + fun_l15_n818 +end + +def fun_l14_n934() + fun_l15_n783 +end + +def fun_l14_n935() + fun_l15_n776 +end + +def fun_l14_n936() + fun_l15_n570 +end + +def fun_l14_n937() + fun_l15_n495 +end + +def fun_l14_n938() + fun_l15_n139 +end + +def fun_l14_n939() + fun_l15_n657 +end + +def fun_l14_n940() + fun_l15_n773 +end + +def fun_l14_n941() + fun_l15_n228 +end + +def fun_l14_n942() + fun_l15_n912 +end + +def fun_l14_n943() + fun_l15_n837 +end + +def fun_l14_n944() + fun_l15_n925 +end + +def fun_l14_n945() + fun_l15_n247 +end + +def fun_l14_n946() + fun_l15_n890 +end + +def fun_l14_n947() + fun_l15_n12 +end + +def fun_l14_n948() + fun_l15_n196 +end + +def fun_l14_n949() + fun_l15_n887 +end + +def fun_l14_n950() + fun_l15_n0 +end + +def fun_l14_n951() + fun_l15_n475 +end + +def fun_l14_n952() + fun_l15_n548 +end + +def fun_l14_n953() + fun_l15_n184 +end + +def fun_l14_n954() + fun_l15_n89 +end + +def fun_l14_n955() + fun_l15_n604 +end + +def fun_l14_n956() + fun_l15_n375 +end + +def fun_l14_n957() + fun_l15_n222 +end + +def fun_l14_n958() + fun_l15_n629 +end + +def fun_l14_n959() + fun_l15_n371 +end + +def fun_l14_n960() + fun_l15_n233 +end + +def fun_l14_n961() + fun_l15_n268 +end + +def fun_l14_n962() + fun_l15_n43 +end + +def fun_l14_n963() + fun_l15_n824 +end + +def fun_l14_n964() + fun_l15_n574 +end + +def fun_l14_n965() + fun_l15_n617 +end + +def fun_l14_n966() + fun_l15_n959 +end + +def fun_l14_n967() + fun_l15_n757 +end + +def fun_l14_n968() + fun_l15_n76 +end + +def fun_l14_n969() + fun_l15_n312 +end + +def fun_l14_n970() + fun_l15_n895 +end + +def fun_l14_n971() + fun_l15_n356 +end + +def fun_l14_n972() + fun_l15_n938 +end + +def fun_l14_n973() + fun_l15_n233 +end + +def fun_l14_n974() + fun_l15_n723 +end + +def fun_l14_n975() + fun_l15_n102 +end + +def fun_l14_n976() + fun_l15_n8 +end + +def fun_l14_n977() + fun_l15_n840 +end + +def fun_l14_n978() + fun_l15_n539 +end + +def fun_l14_n979() + fun_l15_n936 +end + +def fun_l14_n980() + fun_l15_n7 +end + +def fun_l14_n981() + fun_l15_n259 +end + +def fun_l14_n982() + fun_l15_n680 +end + +def fun_l14_n983() + fun_l15_n16 +end + +def fun_l14_n984() + fun_l15_n278 +end + +def fun_l14_n985() + fun_l15_n951 +end + +def fun_l14_n986() + fun_l15_n940 +end + +def fun_l14_n987() + fun_l15_n463 +end + +def fun_l14_n988() + fun_l15_n54 +end + +def fun_l14_n989() + fun_l15_n117 +end + +def fun_l14_n990() + fun_l15_n342 +end + +def fun_l14_n991() + fun_l15_n345 +end + +def fun_l14_n992() + fun_l15_n135 +end + +def fun_l14_n993() + fun_l15_n397 +end + +def fun_l14_n994() + fun_l15_n406 +end + +def fun_l14_n995() + fun_l15_n687 +end + +def fun_l14_n996() + fun_l15_n506 +end + +def fun_l14_n997() + fun_l15_n406 +end + +def fun_l14_n998() + fun_l15_n305 +end + +def fun_l14_n999() + fun_l15_n619 +end + +def fun_l15_n0() + fun_l16_n214 +end + +def fun_l15_n1() + fun_l16_n640 +end + +def fun_l15_n2() + fun_l16_n129 +end + +def fun_l15_n3() + fun_l16_n883 +end + +def fun_l15_n4() + fun_l16_n253 +end + +def fun_l15_n5() + fun_l16_n426 +end + +def fun_l15_n6() + fun_l16_n969 +end + +def fun_l15_n7() + fun_l16_n728 +end + +def fun_l15_n8() + fun_l16_n30 +end + +def fun_l15_n9() + fun_l16_n337 +end + +def fun_l15_n10() + fun_l16_n601 +end + +def fun_l15_n11() + fun_l16_n736 +end + +def fun_l15_n12() + fun_l16_n905 +end + +def fun_l15_n13() + fun_l16_n303 +end + +def fun_l15_n14() + fun_l16_n778 +end + +def fun_l15_n15() + fun_l16_n92 +end + +def fun_l15_n16() + fun_l16_n184 +end + +def fun_l15_n17() + fun_l16_n196 +end + +def fun_l15_n18() + fun_l16_n68 +end + +def fun_l15_n19() + fun_l16_n941 +end + +def fun_l15_n20() + fun_l16_n374 +end + +def fun_l15_n21() + fun_l16_n680 +end + +def fun_l15_n22() + fun_l16_n424 +end + +def fun_l15_n23() + fun_l16_n701 +end + +def fun_l15_n24() + fun_l16_n211 +end + +def fun_l15_n25() + fun_l16_n944 +end + +def fun_l15_n26() + fun_l16_n112 +end + +def fun_l15_n27() + fun_l16_n219 +end + +def fun_l15_n28() + fun_l16_n917 +end + +def fun_l15_n29() + fun_l16_n1 +end + +def fun_l15_n30() + fun_l16_n178 +end + +def fun_l15_n31() + fun_l16_n978 +end + +def fun_l15_n32() + fun_l16_n852 +end + +def fun_l15_n33() + fun_l16_n633 +end + +def fun_l15_n34() + fun_l16_n373 +end + +def fun_l15_n35() + fun_l16_n766 +end + +def fun_l15_n36() + fun_l16_n324 +end + +def fun_l15_n37() + fun_l16_n600 +end + +def fun_l15_n38() + fun_l16_n835 +end + +def fun_l15_n39() + fun_l16_n518 +end + +def fun_l15_n40() + fun_l16_n916 +end + +def fun_l15_n41() + fun_l16_n557 +end + +def fun_l15_n42() + fun_l16_n401 +end + +def fun_l15_n43() + fun_l16_n162 +end + +def fun_l15_n44() + fun_l16_n593 +end + +def fun_l15_n45() + fun_l16_n615 +end + +def fun_l15_n46() + fun_l16_n174 +end + +def fun_l15_n47() + fun_l16_n651 +end + +def fun_l15_n48() + fun_l16_n168 +end + +def fun_l15_n49() + fun_l16_n139 +end + +def fun_l15_n50() + fun_l16_n791 +end + +def fun_l15_n51() + fun_l16_n1 +end + +def fun_l15_n52() + fun_l16_n220 +end + +def fun_l15_n53() + fun_l16_n375 +end + +def fun_l15_n54() + fun_l16_n530 +end + +def fun_l15_n55() + fun_l16_n27 +end + +def fun_l15_n56() + fun_l16_n400 +end + +def fun_l15_n57() + fun_l16_n489 +end + +def fun_l15_n58() + fun_l16_n716 +end + +def fun_l15_n59() + fun_l16_n956 +end + +def fun_l15_n60() + fun_l16_n147 +end + +def fun_l15_n61() + fun_l16_n901 +end + +def fun_l15_n62() + fun_l16_n430 +end + +def fun_l15_n63() + fun_l16_n161 +end + +def fun_l15_n64() + fun_l16_n823 +end + +def fun_l15_n65() + fun_l16_n20 +end + +def fun_l15_n66() + fun_l16_n767 +end + +def fun_l15_n67() + fun_l16_n643 +end + +def fun_l15_n68() + fun_l16_n152 +end + +def fun_l15_n69() + fun_l16_n54 +end + +def fun_l15_n70() + fun_l16_n691 +end + +def fun_l15_n71() + fun_l16_n349 +end + +def fun_l15_n72() + fun_l16_n9 +end + +def fun_l15_n73() + fun_l16_n410 +end + +def fun_l15_n74() + fun_l16_n173 +end + +def fun_l15_n75() + fun_l16_n187 +end + +def fun_l15_n76() + fun_l16_n224 +end + +def fun_l15_n77() + fun_l16_n482 +end + +def fun_l15_n78() + fun_l16_n230 +end + +def fun_l15_n79() + fun_l16_n599 +end + +def fun_l15_n80() + fun_l16_n76 +end + +def fun_l15_n81() + fun_l16_n343 +end + +def fun_l15_n82() + fun_l16_n734 +end + +def fun_l15_n83() + fun_l16_n41 +end + +def fun_l15_n84() + fun_l16_n338 +end + +def fun_l15_n85() + fun_l16_n593 +end + +def fun_l15_n86() + fun_l16_n596 +end + +def fun_l15_n87() + fun_l16_n610 +end + +def fun_l15_n88() + fun_l16_n760 +end + +def fun_l15_n89() + fun_l16_n766 +end + +def fun_l15_n90() + fun_l16_n946 +end + +def fun_l15_n91() + fun_l16_n205 +end + +def fun_l15_n92() + fun_l16_n434 +end + +def fun_l15_n93() + fun_l16_n507 +end + +def fun_l15_n94() + fun_l16_n995 +end + +def fun_l15_n95() + fun_l16_n744 +end + +def fun_l15_n96() + fun_l16_n706 +end + +def fun_l15_n97() + fun_l16_n270 +end + +def fun_l15_n98() + fun_l16_n874 +end + +def fun_l15_n99() + fun_l16_n18 +end + +def fun_l15_n100() + fun_l16_n685 +end + +def fun_l15_n101() + fun_l16_n344 +end + +def fun_l15_n102() + fun_l16_n265 +end + +def fun_l15_n103() + fun_l16_n44 +end + +def fun_l15_n104() + fun_l16_n730 +end + +def fun_l15_n105() + fun_l16_n314 +end + +def fun_l15_n106() + fun_l16_n878 +end + +def fun_l15_n107() + fun_l16_n877 +end + +def fun_l15_n108() + fun_l16_n237 +end + +def fun_l15_n109() + fun_l16_n666 +end + +def fun_l15_n110() + fun_l16_n469 +end + +def fun_l15_n111() + fun_l16_n925 +end + +def fun_l15_n112() + fun_l16_n630 +end + +def fun_l15_n113() + fun_l16_n517 +end + +def fun_l15_n114() + fun_l16_n550 +end + +def fun_l15_n115() + fun_l16_n384 +end + +def fun_l15_n116() + fun_l16_n976 +end + +def fun_l15_n117() + fun_l16_n702 +end + +def fun_l15_n118() + fun_l16_n677 +end + +def fun_l15_n119() + fun_l16_n737 +end + +def fun_l15_n120() + fun_l16_n380 +end + +def fun_l15_n121() + fun_l16_n635 +end + +def fun_l15_n122() + fun_l16_n112 +end + +def fun_l15_n123() + fun_l16_n779 +end + +def fun_l15_n124() + fun_l16_n853 +end + +def fun_l15_n125() + fun_l16_n697 +end + +def fun_l15_n126() + fun_l16_n289 +end + +def fun_l15_n127() + fun_l16_n701 +end + +def fun_l15_n128() + fun_l16_n867 +end + +def fun_l15_n129() + fun_l16_n537 +end + +def fun_l15_n130() + fun_l16_n735 +end + +def fun_l15_n131() + fun_l16_n285 +end + +def fun_l15_n132() + fun_l16_n196 +end + +def fun_l15_n133() + fun_l16_n137 +end + +def fun_l15_n134() + fun_l16_n937 +end + +def fun_l15_n135() + fun_l16_n285 +end + +def fun_l15_n136() + fun_l16_n566 +end + +def fun_l15_n137() + fun_l16_n163 +end + +def fun_l15_n138() + fun_l16_n223 +end + +def fun_l15_n139() + fun_l16_n373 +end + +def fun_l15_n140() + fun_l16_n16 +end + +def fun_l15_n141() + fun_l16_n539 +end + +def fun_l15_n142() + fun_l16_n696 +end + +def fun_l15_n143() + fun_l16_n735 +end + +def fun_l15_n144() + fun_l16_n81 +end + +def fun_l15_n145() + fun_l16_n102 +end + +def fun_l15_n146() + fun_l16_n658 +end + +def fun_l15_n147() + fun_l16_n858 +end + +def fun_l15_n148() + fun_l16_n398 +end + +def fun_l15_n149() + fun_l16_n122 +end + +def fun_l15_n150() + fun_l16_n712 +end + +def fun_l15_n151() + fun_l16_n888 +end + +def fun_l15_n152() + fun_l16_n537 +end + +def fun_l15_n153() + fun_l16_n190 +end + +def fun_l15_n154() + fun_l16_n164 +end + +def fun_l15_n155() + fun_l16_n351 +end + +def fun_l15_n156() + fun_l16_n641 +end + +def fun_l15_n157() + fun_l16_n300 +end + +def fun_l15_n158() + fun_l16_n177 +end + +def fun_l15_n159() + fun_l16_n634 +end + +def fun_l15_n160() + fun_l16_n475 +end + +def fun_l15_n161() + fun_l16_n843 +end + +def fun_l15_n162() + fun_l16_n262 +end + +def fun_l15_n163() + fun_l16_n471 +end + +def fun_l15_n164() + fun_l16_n229 +end + +def fun_l15_n165() + fun_l16_n374 +end + +def fun_l15_n166() + fun_l16_n920 +end + +def fun_l15_n167() + fun_l16_n194 +end + +def fun_l15_n168() + fun_l16_n369 +end + +def fun_l15_n169() + fun_l16_n41 +end + +def fun_l15_n170() + fun_l16_n339 +end + +def fun_l15_n171() + fun_l16_n152 +end + +def fun_l15_n172() + fun_l16_n337 +end + +def fun_l15_n173() + fun_l16_n906 +end + +def fun_l15_n174() + fun_l16_n13 +end + +def fun_l15_n175() + fun_l16_n343 +end + +def fun_l15_n176() + fun_l16_n116 +end + +def fun_l15_n177() + fun_l16_n722 +end + +def fun_l15_n178() + fun_l16_n62 +end + +def fun_l15_n179() + fun_l16_n12 +end + +def fun_l15_n180() + fun_l16_n177 +end + +def fun_l15_n181() + fun_l16_n632 +end + +def fun_l15_n182() + fun_l16_n990 +end + +def fun_l15_n183() + fun_l16_n749 +end + +def fun_l15_n184() + fun_l16_n368 +end + +def fun_l15_n185() + fun_l16_n881 +end + +def fun_l15_n186() + fun_l16_n760 +end + +def fun_l15_n187() + fun_l16_n740 +end + +def fun_l15_n188() + fun_l16_n379 +end + +def fun_l15_n189() + fun_l16_n194 +end + +def fun_l15_n190() + fun_l16_n282 +end + +def fun_l15_n191() + fun_l16_n520 +end + +def fun_l15_n192() + fun_l16_n113 +end + +def fun_l15_n193() + fun_l16_n470 +end + +def fun_l15_n194() + fun_l16_n303 +end + +def fun_l15_n195() + fun_l16_n712 +end + +def fun_l15_n196() + fun_l16_n215 +end + +def fun_l15_n197() + fun_l16_n121 +end + +def fun_l15_n198() + fun_l16_n281 +end + +def fun_l15_n199() + fun_l16_n702 +end + +def fun_l15_n200() + fun_l16_n727 +end + +def fun_l15_n201() + fun_l16_n856 +end + +def fun_l15_n202() + fun_l16_n368 +end + +def fun_l15_n203() + fun_l16_n252 +end + +def fun_l15_n204() + fun_l16_n86 +end + +def fun_l15_n205() + fun_l16_n323 +end + +def fun_l15_n206() + fun_l16_n749 +end + +def fun_l15_n207() + fun_l16_n728 +end + +def fun_l15_n208() + fun_l16_n195 +end + +def fun_l15_n209() + fun_l16_n141 +end + +def fun_l15_n210() + fun_l16_n685 +end + +def fun_l15_n211() + fun_l16_n855 +end + +def fun_l15_n212() + fun_l16_n401 +end + +def fun_l15_n213() + fun_l16_n415 +end + +def fun_l15_n214() + fun_l16_n349 +end + +def fun_l15_n215() + fun_l16_n45 +end + +def fun_l15_n216() + fun_l16_n534 +end + +def fun_l15_n217() + fun_l16_n705 +end + +def fun_l15_n218() + fun_l16_n97 +end + +def fun_l15_n219() + fun_l16_n828 +end + +def fun_l15_n220() + fun_l16_n698 +end + +def fun_l15_n221() + fun_l16_n505 +end + +def fun_l15_n222() + fun_l16_n100 +end + +def fun_l15_n223() + fun_l16_n710 +end + +def fun_l15_n224() + fun_l16_n883 +end + +def fun_l15_n225() + fun_l16_n503 +end + +def fun_l15_n226() + fun_l16_n583 +end + +def fun_l15_n227() + fun_l16_n269 +end + +def fun_l15_n228() + fun_l16_n570 +end + +def fun_l15_n229() + fun_l16_n877 +end + +def fun_l15_n230() + fun_l16_n906 +end + +def fun_l15_n231() + fun_l16_n123 +end + +def fun_l15_n232() + fun_l16_n626 +end + +def fun_l15_n233() + fun_l16_n911 +end + +def fun_l15_n234() + fun_l16_n741 +end + +def fun_l15_n235() + fun_l16_n255 +end + +def fun_l15_n236() + fun_l16_n499 +end + +def fun_l15_n237() + fun_l16_n998 +end + +def fun_l15_n238() + fun_l16_n156 +end + +def fun_l15_n239() + fun_l16_n677 +end + +def fun_l15_n240() + fun_l16_n551 +end + +def fun_l15_n241() + fun_l16_n906 +end + +def fun_l15_n242() + fun_l16_n146 +end + +def fun_l15_n243() + fun_l16_n372 +end + +def fun_l15_n244() + fun_l16_n867 +end + +def fun_l15_n245() + fun_l16_n232 +end + +def fun_l15_n246() + fun_l16_n952 +end + +def fun_l15_n247() + fun_l16_n256 +end + +def fun_l15_n248() + fun_l16_n263 +end + +def fun_l15_n249() + fun_l16_n642 +end + +def fun_l15_n250() + fun_l16_n165 +end + +def fun_l15_n251() + fun_l16_n147 +end + +def fun_l15_n252() + fun_l16_n182 +end + +def fun_l15_n253() + fun_l16_n346 +end + +def fun_l15_n254() + fun_l16_n263 +end + +def fun_l15_n255() + fun_l16_n512 +end + +def fun_l15_n256() + fun_l16_n504 +end + +def fun_l15_n257() + fun_l16_n671 +end + +def fun_l15_n258() + fun_l16_n219 +end + +def fun_l15_n259() + fun_l16_n878 +end + +def fun_l15_n260() + fun_l16_n754 +end + +def fun_l15_n261() + fun_l16_n976 +end + +def fun_l15_n262() + fun_l16_n756 +end + +def fun_l15_n263() + fun_l16_n840 +end + +def fun_l15_n264() + fun_l16_n320 +end + +def fun_l15_n265() + fun_l16_n447 +end + +def fun_l15_n266() + fun_l16_n179 +end + +def fun_l15_n267() + fun_l16_n669 +end + +def fun_l15_n268() + fun_l16_n279 +end + +def fun_l15_n269() + fun_l16_n919 +end + +def fun_l15_n270() + fun_l16_n55 +end + +def fun_l15_n271() + fun_l16_n713 +end + +def fun_l15_n272() + fun_l16_n140 +end + +def fun_l15_n273() + fun_l16_n738 +end + +def fun_l15_n274() + fun_l16_n534 +end + +def fun_l15_n275() + fun_l16_n739 +end + +def fun_l15_n276() + fun_l16_n733 +end + +def fun_l15_n277() + fun_l16_n792 +end + +def fun_l15_n278() + fun_l16_n719 +end + +def fun_l15_n279() + fun_l16_n946 +end + +def fun_l15_n280() + fun_l16_n942 +end + +def fun_l15_n281() + fun_l16_n547 +end + +def fun_l15_n282() + fun_l16_n961 +end + +def fun_l15_n283() + fun_l16_n382 +end + +def fun_l15_n284() + fun_l16_n642 +end + +def fun_l15_n285() + fun_l16_n761 +end + +def fun_l15_n286() + fun_l16_n999 +end + +def fun_l15_n287() + fun_l16_n827 +end + +def fun_l15_n288() + fun_l16_n364 +end + +def fun_l15_n289() + fun_l16_n588 +end + +def fun_l15_n290() + fun_l16_n3 +end + +def fun_l15_n291() + fun_l16_n741 +end + +def fun_l15_n292() + fun_l16_n839 +end + +def fun_l15_n293() + fun_l16_n889 +end + +def fun_l15_n294() + fun_l16_n106 +end + +def fun_l15_n295() + fun_l16_n616 +end + +def fun_l15_n296() + fun_l16_n124 +end + +def fun_l15_n297() + fun_l16_n691 +end + +def fun_l15_n298() + fun_l16_n135 +end + +def fun_l15_n299() + fun_l16_n654 +end + +def fun_l15_n300() + fun_l16_n706 +end + +def fun_l15_n301() + fun_l16_n957 +end + +def fun_l15_n302() + fun_l16_n213 +end + +def fun_l15_n303() + fun_l16_n340 +end + +def fun_l15_n304() + fun_l16_n126 +end + +def fun_l15_n305() + fun_l16_n807 +end + +def fun_l15_n306() + fun_l16_n901 +end + +def fun_l15_n307() + fun_l16_n371 +end + +def fun_l15_n308() + fun_l16_n904 +end + +def fun_l15_n309() + fun_l16_n475 +end + +def fun_l15_n310() + fun_l16_n863 +end + +def fun_l15_n311() + fun_l16_n37 +end + +def fun_l15_n312() + fun_l16_n315 +end + +def fun_l15_n313() + fun_l16_n527 +end + +def fun_l15_n314() + fun_l16_n549 +end + +def fun_l15_n315() + fun_l16_n351 +end + +def fun_l15_n316() + fun_l16_n193 +end + +def fun_l15_n317() + fun_l16_n395 +end + +def fun_l15_n318() + fun_l16_n373 +end + +def fun_l15_n319() + fun_l16_n142 +end + +def fun_l15_n320() + fun_l16_n250 +end + +def fun_l15_n321() + fun_l16_n544 +end + +def fun_l15_n322() + fun_l16_n446 +end + +def fun_l15_n323() + fun_l16_n375 +end + +def fun_l15_n324() + fun_l16_n832 +end + +def fun_l15_n325() + fun_l16_n987 +end + +def fun_l15_n326() + fun_l16_n539 +end + +def fun_l15_n327() + fun_l16_n293 +end + +def fun_l15_n328() + fun_l16_n128 +end + +def fun_l15_n329() + fun_l16_n228 +end + +def fun_l15_n330() + fun_l16_n952 +end + +def fun_l15_n331() + fun_l16_n116 +end + +def fun_l15_n332() + fun_l16_n823 +end + +def fun_l15_n333() + fun_l16_n933 +end + +def fun_l15_n334() + fun_l16_n252 +end + +def fun_l15_n335() + fun_l16_n140 +end + +def fun_l15_n336() + fun_l16_n245 +end + +def fun_l15_n337() + fun_l16_n822 +end + +def fun_l15_n338() + fun_l16_n389 +end + +def fun_l15_n339() + fun_l16_n824 +end + +def fun_l15_n340() + fun_l16_n507 +end + +def fun_l15_n341() + fun_l16_n153 +end + +def fun_l15_n342() + fun_l16_n661 +end + +def fun_l15_n343() + fun_l16_n633 +end + +def fun_l15_n344() + fun_l16_n478 +end + +def fun_l15_n345() + fun_l16_n423 +end + +def fun_l15_n346() + fun_l16_n425 +end + +def fun_l15_n347() + fun_l16_n168 +end + +def fun_l15_n348() + fun_l16_n426 +end + +def fun_l15_n349() + fun_l16_n85 +end + +def fun_l15_n350() + fun_l16_n35 +end + +def fun_l15_n351() + fun_l16_n796 +end + +def fun_l15_n352() + fun_l16_n295 +end + +def fun_l15_n353() + fun_l16_n564 +end + +def fun_l15_n354() + fun_l16_n273 +end + +def fun_l15_n355() + fun_l16_n821 +end + +def fun_l15_n356() + fun_l16_n504 +end + +def fun_l15_n357() + fun_l16_n911 +end + +def fun_l15_n358() + fun_l16_n277 +end + +def fun_l15_n359() + fun_l16_n749 +end + +def fun_l15_n360() + fun_l16_n886 +end + +def fun_l15_n361() + fun_l16_n165 +end + +def fun_l15_n362() + fun_l16_n353 +end + +def fun_l15_n363() + fun_l16_n309 +end + +def fun_l15_n364() + fun_l16_n853 +end + +def fun_l15_n365() + fun_l16_n981 +end + +def fun_l15_n366() + fun_l16_n429 +end + +def fun_l15_n367() + fun_l16_n114 +end + +def fun_l15_n368() + fun_l16_n649 +end + +def fun_l15_n369() + fun_l16_n966 +end + +def fun_l15_n370() + fun_l16_n356 +end + +def fun_l15_n371() + fun_l16_n364 +end + +def fun_l15_n372() + fun_l16_n12 +end + +def fun_l15_n373() + fun_l16_n969 +end + +def fun_l15_n374() + fun_l16_n705 +end + +def fun_l15_n375() + fun_l16_n194 +end + +def fun_l15_n376() + fun_l16_n487 +end + +def fun_l15_n377() + fun_l16_n148 +end + +def fun_l15_n378() + fun_l16_n419 +end + +def fun_l15_n379() + fun_l16_n686 +end + +def fun_l15_n380() + fun_l16_n552 +end + +def fun_l15_n381() + fun_l16_n630 +end + +def fun_l15_n382() + fun_l16_n509 +end + +def fun_l15_n383() + fun_l16_n251 +end + +def fun_l15_n384() + fun_l16_n506 +end + +def fun_l15_n385() + fun_l16_n317 +end + +def fun_l15_n386() + fun_l16_n881 +end + +def fun_l15_n387() + fun_l16_n12 +end + +def fun_l15_n388() + fun_l16_n686 +end + +def fun_l15_n389() + fun_l16_n277 +end + +def fun_l15_n390() + fun_l16_n174 +end + +def fun_l15_n391() + fun_l16_n799 +end + +def fun_l15_n392() + fun_l16_n682 +end + +def fun_l15_n393() + fun_l16_n102 +end + +def fun_l15_n394() + fun_l16_n127 +end + +def fun_l15_n395() + fun_l16_n110 +end + +def fun_l15_n396() + fun_l16_n331 +end + +def fun_l15_n397() + fun_l16_n165 +end + +def fun_l15_n398() + fun_l16_n360 +end + +def fun_l15_n399() + fun_l16_n622 +end + +def fun_l15_n400() + fun_l16_n928 +end + +def fun_l15_n401() + fun_l16_n324 +end + +def fun_l15_n402() + fun_l16_n712 +end + +def fun_l15_n403() + fun_l16_n250 +end + +def fun_l15_n404() + fun_l16_n289 +end + +def fun_l15_n405() + fun_l16_n520 +end + +def fun_l15_n406() + fun_l16_n445 +end + +def fun_l15_n407() + fun_l16_n328 +end + +def fun_l15_n408() + fun_l16_n496 +end + +def fun_l15_n409() + fun_l16_n614 +end + +def fun_l15_n410() + fun_l16_n428 +end + +def fun_l15_n411() + fun_l16_n226 +end + +def fun_l15_n412() + fun_l16_n450 +end + +def fun_l15_n413() + fun_l16_n410 +end + +def fun_l15_n414() + fun_l16_n926 +end + +def fun_l15_n415() + fun_l16_n353 +end + +def fun_l15_n416() + fun_l16_n822 +end + +def fun_l15_n417() + fun_l16_n800 +end + +def fun_l15_n418() + fun_l16_n577 +end + +def fun_l15_n419() + fun_l16_n483 +end + +def fun_l15_n420() + fun_l16_n744 +end + +def fun_l15_n421() + fun_l16_n314 +end + +def fun_l15_n422() + fun_l16_n206 +end + +def fun_l15_n423() + fun_l16_n359 +end + +def fun_l15_n424() + fun_l16_n371 +end + +def fun_l15_n425() + fun_l16_n817 +end + +def fun_l15_n426() + fun_l16_n471 +end + +def fun_l15_n427() + fun_l16_n681 +end + +def fun_l15_n428() + fun_l16_n598 +end + +def fun_l15_n429() + fun_l16_n532 +end + +def fun_l15_n430() + fun_l16_n173 +end + +def fun_l15_n431() + fun_l16_n670 +end + +def fun_l15_n432() + fun_l16_n310 +end + +def fun_l15_n433() + fun_l16_n376 +end + +def fun_l15_n434() + fun_l16_n142 +end + +def fun_l15_n435() + fun_l16_n591 +end + +def fun_l15_n436() + fun_l16_n313 +end + +def fun_l15_n437() + fun_l16_n724 +end + +def fun_l15_n438() + fun_l16_n313 +end + +def fun_l15_n439() + fun_l16_n238 +end + +def fun_l15_n440() + fun_l16_n840 +end + +def fun_l15_n441() + fun_l16_n235 +end + +def fun_l15_n442() + fun_l16_n720 +end + +def fun_l15_n443() + fun_l16_n427 +end + +def fun_l15_n444() + fun_l16_n269 +end + +def fun_l15_n445() + fun_l16_n557 +end + +def fun_l15_n446() + fun_l16_n97 +end + +def fun_l15_n447() + fun_l16_n655 +end + +def fun_l15_n448() + fun_l16_n723 +end + +def fun_l15_n449() + fun_l16_n634 +end + +def fun_l15_n450() + fun_l16_n208 +end + +def fun_l15_n451() + fun_l16_n130 +end + +def fun_l15_n452() + fun_l16_n472 +end + +def fun_l15_n453() + fun_l16_n172 +end + +def fun_l15_n454() + fun_l16_n323 +end + +def fun_l15_n455() + fun_l16_n643 +end + +def fun_l15_n456() + fun_l16_n20 +end + +def fun_l15_n457() + fun_l16_n721 +end + +def fun_l15_n458() + fun_l16_n928 +end + +def fun_l15_n459() + fun_l16_n312 +end + +def fun_l15_n460() + fun_l16_n767 +end + +def fun_l15_n461() + fun_l16_n191 +end + +def fun_l15_n462() + fun_l16_n88 +end + +def fun_l15_n463() + fun_l16_n782 +end + +def fun_l15_n464() + fun_l16_n448 +end + +def fun_l15_n465() + fun_l16_n595 +end + +def fun_l15_n466() + fun_l16_n545 +end + +def fun_l15_n467() + fun_l16_n98 +end + +def fun_l15_n468() + fun_l16_n523 +end + +def fun_l15_n469() + fun_l16_n548 +end + +def fun_l15_n470() + fun_l16_n799 +end + +def fun_l15_n471() + fun_l16_n727 +end + +def fun_l15_n472() + fun_l16_n342 +end + +def fun_l15_n473() + fun_l16_n30 +end + +def fun_l15_n474() + fun_l16_n461 +end + +def fun_l15_n475() + fun_l16_n249 +end + +def fun_l15_n476() + fun_l16_n466 +end + +def fun_l15_n477() + fun_l16_n28 +end + +def fun_l15_n478() + fun_l16_n845 +end + +def fun_l15_n479() + fun_l16_n53 +end + +def fun_l15_n480() + fun_l16_n122 +end + +def fun_l15_n481() + fun_l16_n264 +end + +def fun_l15_n482() + fun_l16_n802 +end + +def fun_l15_n483() + fun_l16_n688 +end + +def fun_l15_n484() + fun_l16_n656 +end + +def fun_l15_n485() + fun_l16_n17 +end + +def fun_l15_n486() + fun_l16_n956 +end + +def fun_l15_n487() + fun_l16_n649 +end + +def fun_l15_n488() + fun_l16_n948 +end + +def fun_l15_n489() + fun_l16_n85 +end + +def fun_l15_n490() + fun_l16_n411 +end + +def fun_l15_n491() + fun_l16_n572 +end + +def fun_l15_n492() + fun_l16_n698 +end + +def fun_l15_n493() + fun_l16_n767 +end + +def fun_l15_n494() + fun_l16_n513 +end + +def fun_l15_n495() + fun_l16_n983 +end + +def fun_l15_n496() + fun_l16_n763 +end + +def fun_l15_n497() + fun_l16_n207 +end + +def fun_l15_n498() + fun_l16_n154 +end + +def fun_l15_n499() + fun_l16_n152 +end + +def fun_l15_n500() + fun_l16_n929 +end + +def fun_l15_n501() + fun_l16_n573 +end + +def fun_l15_n502() + fun_l16_n97 +end + +def fun_l15_n503() + fun_l16_n696 +end + +def fun_l15_n504() + fun_l16_n877 +end + +def fun_l15_n505() + fun_l16_n401 +end + +def fun_l15_n506() + fun_l16_n509 +end + +def fun_l15_n507() + fun_l16_n933 +end + +def fun_l15_n508() + fun_l16_n946 +end + +def fun_l15_n509() + fun_l16_n290 +end + +def fun_l15_n510() + fun_l16_n630 +end + +def fun_l15_n511() + fun_l16_n279 +end + +def fun_l15_n512() + fun_l16_n833 +end + +def fun_l15_n513() + fun_l16_n984 +end + +def fun_l15_n514() + fun_l16_n82 +end + +def fun_l15_n515() + fun_l16_n372 +end + +def fun_l15_n516() + fun_l16_n407 +end + +def fun_l15_n517() + fun_l16_n801 +end + +def fun_l15_n518() + fun_l16_n530 +end + +def fun_l15_n519() + fun_l16_n349 +end + +def fun_l15_n520() + fun_l16_n633 +end + +def fun_l15_n521() + fun_l16_n189 +end + +def fun_l15_n522() + fun_l16_n613 +end + +def fun_l15_n523() + fun_l16_n335 +end + +def fun_l15_n524() + fun_l16_n163 +end + +def fun_l15_n525() + fun_l16_n542 +end + +def fun_l15_n526() + fun_l16_n454 +end + +def fun_l15_n527() + fun_l16_n428 +end + +def fun_l15_n528() + fun_l16_n985 +end + +def fun_l15_n529() + fun_l16_n414 +end + +def fun_l15_n530() + fun_l16_n294 +end + +def fun_l15_n531() + fun_l16_n493 +end + +def fun_l15_n532() + fun_l16_n467 +end + +def fun_l15_n533() + fun_l16_n398 +end + +def fun_l15_n534() + fun_l16_n861 +end + +def fun_l15_n535() + fun_l16_n219 +end + +def fun_l15_n536() + fun_l16_n178 +end + +def fun_l15_n537() + fun_l16_n436 +end + +def fun_l15_n538() + fun_l16_n821 +end + +def fun_l15_n539() + fun_l16_n732 +end + +def fun_l15_n540() + fun_l16_n432 +end + +def fun_l15_n541() + fun_l16_n32 +end + +def fun_l15_n542() + fun_l16_n128 +end + +def fun_l15_n543() + fun_l16_n2 +end + +def fun_l15_n544() + fun_l16_n117 +end + +def fun_l15_n545() + fun_l16_n861 +end + +def fun_l15_n546() + fun_l16_n817 +end + +def fun_l15_n547() + fun_l16_n833 +end + +def fun_l15_n548() + fun_l16_n180 +end + +def fun_l15_n549() + fun_l16_n176 +end + +def fun_l15_n550() + fun_l16_n772 +end + +def fun_l15_n551() + fun_l16_n469 +end + +def fun_l15_n552() + fun_l16_n209 +end + +def fun_l15_n553() + fun_l16_n200 +end + +def fun_l15_n554() + fun_l16_n434 +end + +def fun_l15_n555() + fun_l16_n529 +end + +def fun_l15_n556() + fun_l16_n847 +end + +def fun_l15_n557() + fun_l16_n134 +end + +def fun_l15_n558() + fun_l16_n748 +end + +def fun_l15_n559() + fun_l16_n153 +end + +def fun_l15_n560() + fun_l16_n903 +end + +def fun_l15_n561() + fun_l16_n449 +end + +def fun_l15_n562() + fun_l16_n267 +end + +def fun_l15_n563() + fun_l16_n47 +end + +def fun_l15_n564() + fun_l16_n762 +end + +def fun_l15_n565() + fun_l16_n932 +end + +def fun_l15_n566() + fun_l16_n782 +end + +def fun_l15_n567() + fun_l16_n580 +end + +def fun_l15_n568() + fun_l16_n172 +end + +def fun_l15_n569() + fun_l16_n379 +end + +def fun_l15_n570() + fun_l16_n890 +end + +def fun_l15_n571() + fun_l16_n257 +end + +def fun_l15_n572() + fun_l16_n964 +end + +def fun_l15_n573() + fun_l16_n164 +end + +def fun_l15_n574() + fun_l16_n606 +end + +def fun_l15_n575() + fun_l16_n475 +end + +def fun_l15_n576() + fun_l16_n500 +end + +def fun_l15_n577() + fun_l16_n65 +end + +def fun_l15_n578() + fun_l16_n81 +end + +def fun_l15_n579() + fun_l16_n952 +end + +def fun_l15_n580() + fun_l16_n524 +end + +def fun_l15_n581() + fun_l16_n573 +end + +def fun_l15_n582() + fun_l16_n812 +end + +def fun_l15_n583() + fun_l16_n498 +end + +def fun_l15_n584() + fun_l16_n106 +end + +def fun_l15_n585() + fun_l16_n807 +end + +def fun_l15_n586() + fun_l16_n70 +end + +def fun_l15_n587() + fun_l16_n41 +end + +def fun_l15_n588() + fun_l16_n78 +end + +def fun_l15_n589() + fun_l16_n235 +end + +def fun_l15_n590() + fun_l16_n974 +end + +def fun_l15_n591() + fun_l16_n450 +end + +def fun_l15_n592() + fun_l16_n191 +end + +def fun_l15_n593() + fun_l16_n988 +end + +def fun_l15_n594() + fun_l16_n516 +end + +def fun_l15_n595() + fun_l16_n7 +end + +def fun_l15_n596() + fun_l16_n186 +end + +def fun_l15_n597() + fun_l16_n249 +end + +def fun_l15_n598() + fun_l16_n832 +end + +def fun_l15_n599() + fun_l16_n502 +end + +def fun_l15_n600() + fun_l16_n967 +end + +def fun_l15_n601() + fun_l16_n930 +end + +def fun_l15_n602() + fun_l16_n497 +end + +def fun_l15_n603() + fun_l16_n467 +end + +def fun_l15_n604() + fun_l16_n742 +end + +def fun_l15_n605() + fun_l16_n52 +end + +def fun_l15_n606() + fun_l16_n494 +end + +def fun_l15_n607() + fun_l16_n604 +end + +def fun_l15_n608() + fun_l16_n372 +end + +def fun_l15_n609() + fun_l16_n503 +end + +def fun_l15_n610() + fun_l16_n853 +end + +def fun_l15_n611() + fun_l16_n146 +end + +def fun_l15_n612() + fun_l16_n812 +end + +def fun_l15_n613() + fun_l16_n235 +end + +def fun_l15_n614() + fun_l16_n924 +end + +def fun_l15_n615() + fun_l16_n212 +end + +def fun_l15_n616() + fun_l16_n332 +end + +def fun_l15_n617() + fun_l16_n179 +end + +def fun_l15_n618() + fun_l16_n767 +end + +def fun_l15_n619() + fun_l16_n46 +end + +def fun_l15_n620() + fun_l16_n275 +end + +def fun_l15_n621() + fun_l16_n348 +end + +def fun_l15_n622() + fun_l16_n136 +end + +def fun_l15_n623() + fun_l16_n814 +end + +def fun_l15_n624() + fun_l16_n782 +end + +def fun_l15_n625() + fun_l16_n692 +end + +def fun_l15_n626() + fun_l16_n331 +end + +def fun_l15_n627() + fun_l16_n228 +end + +def fun_l15_n628() + fun_l16_n249 +end + +def fun_l15_n629() + fun_l16_n387 +end + +def fun_l15_n630() + fun_l16_n994 +end + +def fun_l15_n631() + fun_l16_n219 +end + +def fun_l15_n632() + fun_l16_n743 +end + +def fun_l15_n633() + fun_l16_n674 +end + +def fun_l15_n634() + fun_l16_n411 +end + +def fun_l15_n635() + fun_l16_n757 +end + +def fun_l15_n636() + fun_l16_n568 +end + +def fun_l15_n637() + fun_l16_n323 +end + +def fun_l15_n638() + fun_l16_n910 +end + +def fun_l15_n639() + fun_l16_n823 +end + +def fun_l15_n640() + fun_l16_n942 +end + +def fun_l15_n641() + fun_l16_n796 +end + +def fun_l15_n642() + fun_l16_n507 +end + +def fun_l15_n643() + fun_l16_n72 +end + +def fun_l15_n644() + fun_l16_n285 +end + +def fun_l15_n645() + fun_l16_n654 +end + +def fun_l15_n646() + fun_l16_n361 +end + +def fun_l15_n647() + fun_l16_n766 +end + +def fun_l15_n648() + fun_l16_n587 +end + +def fun_l15_n649() + fun_l16_n99 +end + +def fun_l15_n650() + fun_l16_n558 +end + +def fun_l15_n651() + fun_l16_n623 +end + +def fun_l15_n652() + fun_l16_n428 +end + +def fun_l15_n653() + fun_l16_n695 +end + +def fun_l15_n654() + fun_l16_n514 +end + +def fun_l15_n655() + fun_l16_n159 +end + +def fun_l15_n656() + fun_l16_n41 +end + +def fun_l15_n657() + fun_l16_n510 +end + +def fun_l15_n658() + fun_l16_n26 +end + +def fun_l15_n659() + fun_l16_n947 +end + +def fun_l15_n660() + fun_l16_n766 +end + +def fun_l15_n661() + fun_l16_n470 +end + +def fun_l15_n662() + fun_l16_n46 +end + +def fun_l15_n663() + fun_l16_n499 +end + +def fun_l15_n664() + fun_l16_n593 +end + +def fun_l15_n665() + fun_l16_n803 +end + +def fun_l15_n666() + fun_l16_n321 +end + +def fun_l15_n667() + fun_l16_n165 +end + +def fun_l15_n668() + fun_l16_n762 +end + +def fun_l15_n669() + fun_l16_n800 +end + +def fun_l15_n670() + fun_l16_n530 +end + +def fun_l15_n671() + fun_l16_n198 +end + +def fun_l15_n672() + fun_l16_n365 +end + +def fun_l15_n673() + fun_l16_n204 +end + +def fun_l15_n674() + fun_l16_n782 +end + +def fun_l15_n675() + fun_l16_n465 +end + +def fun_l15_n676() + fun_l16_n733 +end + +def fun_l15_n677() + fun_l16_n101 +end + +def fun_l15_n678() + fun_l16_n38 +end + +def fun_l15_n679() + fun_l16_n800 +end + +def fun_l15_n680() + fun_l16_n45 +end + +def fun_l15_n681() + fun_l16_n996 +end + +def fun_l15_n682() + fun_l16_n156 +end + +def fun_l15_n683() + fun_l16_n868 +end + +def fun_l15_n684() + fun_l16_n537 +end + +def fun_l15_n685() + fun_l16_n450 +end + +def fun_l15_n686() + fun_l16_n932 +end + +def fun_l15_n687() + fun_l16_n733 +end + +def fun_l15_n688() + fun_l16_n150 +end + +def fun_l15_n689() + fun_l16_n770 +end + +def fun_l15_n690() + fun_l16_n522 +end + +def fun_l15_n691() + fun_l16_n867 +end + +def fun_l15_n692() + fun_l16_n318 +end + +def fun_l15_n693() + fun_l16_n23 +end + +def fun_l15_n694() + fun_l16_n402 +end + +def fun_l15_n695() + fun_l16_n261 +end + +def fun_l15_n696() + fun_l16_n726 +end + +def fun_l15_n697() + fun_l16_n406 +end + +def fun_l15_n698() + fun_l16_n308 +end + +def fun_l15_n699() + fun_l16_n428 +end + +def fun_l15_n700() + fun_l16_n141 +end + +def fun_l15_n701() + fun_l16_n987 +end + +def fun_l15_n702() + fun_l16_n371 +end + +def fun_l15_n703() + fun_l16_n578 +end + +def fun_l15_n704() + fun_l16_n780 +end + +def fun_l15_n705() + fun_l16_n914 +end + +def fun_l15_n706() + fun_l16_n976 +end + +def fun_l15_n707() + fun_l16_n268 +end + +def fun_l15_n708() + fun_l16_n431 +end + +def fun_l15_n709() + fun_l16_n188 +end + +def fun_l15_n710() + fun_l16_n190 +end + +def fun_l15_n711() + fun_l16_n742 +end + +def fun_l15_n712() + fun_l16_n223 +end + +def fun_l15_n713() + fun_l16_n993 +end + +def fun_l15_n714() + fun_l16_n482 +end + +def fun_l15_n715() + fun_l16_n890 +end + +def fun_l15_n716() + fun_l16_n929 +end + +def fun_l15_n717() + fun_l16_n644 +end + +def fun_l15_n718() + fun_l16_n646 +end + +def fun_l15_n719() + fun_l16_n121 +end + +def fun_l15_n720() + fun_l16_n417 +end + +def fun_l15_n721() + fun_l16_n203 +end + +def fun_l15_n722() + fun_l16_n145 +end + +def fun_l15_n723() + fun_l16_n401 +end + +def fun_l15_n724() + fun_l16_n823 +end + +def fun_l15_n725() + fun_l16_n554 +end + +def fun_l15_n726() + fun_l16_n641 +end + +def fun_l15_n727() + fun_l16_n232 +end + +def fun_l15_n728() + fun_l16_n313 +end + +def fun_l15_n729() + fun_l16_n943 +end + +def fun_l15_n730() + fun_l16_n964 +end + +def fun_l15_n731() + fun_l16_n409 +end + +def fun_l15_n732() + fun_l16_n375 +end + +def fun_l15_n733() + fun_l16_n147 +end + +def fun_l15_n734() + fun_l16_n779 +end + +def fun_l15_n735() + fun_l16_n690 +end + +def fun_l15_n736() + fun_l16_n91 +end + +def fun_l15_n737() + fun_l16_n819 +end + +def fun_l15_n738() + fun_l16_n68 +end + +def fun_l15_n739() + fun_l16_n810 +end + +def fun_l15_n740() + fun_l16_n787 +end + +def fun_l15_n741() + fun_l16_n90 +end + +def fun_l15_n742() + fun_l16_n800 +end + +def fun_l15_n743() + fun_l16_n491 +end + +def fun_l15_n744() + fun_l16_n729 +end + +def fun_l15_n745() + fun_l16_n917 +end + +def fun_l15_n746() + fun_l16_n360 +end + +def fun_l15_n747() + fun_l16_n489 +end + +def fun_l15_n748() + fun_l16_n755 +end + +def fun_l15_n749() + fun_l16_n999 +end + +def fun_l15_n750() + fun_l16_n268 +end + +def fun_l15_n751() + fun_l16_n213 +end + +def fun_l15_n752() + fun_l16_n923 +end + +def fun_l15_n753() + fun_l16_n456 +end + +def fun_l15_n754() + fun_l16_n653 +end + +def fun_l15_n755() + fun_l16_n855 +end + +def fun_l15_n756() + fun_l16_n833 +end + +def fun_l15_n757() + fun_l16_n269 +end + +def fun_l15_n758() + fun_l16_n152 +end + +def fun_l15_n759() + fun_l16_n391 +end + +def fun_l15_n760() + fun_l16_n850 +end + +def fun_l15_n761() + fun_l16_n70 +end + +def fun_l15_n762() + fun_l16_n774 +end + +def fun_l15_n763() + fun_l16_n379 +end + +def fun_l15_n764() + fun_l16_n271 +end + +def fun_l15_n765() + fun_l16_n667 +end + +def fun_l15_n766() + fun_l16_n149 +end + +def fun_l15_n767() + fun_l16_n715 +end + +def fun_l15_n768() + fun_l16_n645 +end + +def fun_l15_n769() + fun_l16_n741 +end + +def fun_l15_n770() + fun_l16_n147 +end + +def fun_l15_n771() + fun_l16_n23 +end + +def fun_l15_n772() + fun_l16_n653 +end + +def fun_l15_n773() + fun_l16_n109 +end + +def fun_l15_n774() + fun_l16_n402 +end + +def fun_l15_n775() + fun_l16_n995 +end + +def fun_l15_n776() + fun_l16_n112 +end + +def fun_l15_n777() + fun_l16_n416 +end + +def fun_l15_n778() + fun_l16_n641 +end + +def fun_l15_n779() + fun_l16_n412 +end + +def fun_l15_n780() + fun_l16_n548 +end + +def fun_l15_n781() + fun_l16_n329 +end + +def fun_l15_n782() + fun_l16_n804 +end + +def fun_l15_n783() + fun_l16_n377 +end + +def fun_l15_n784() + fun_l16_n107 +end + +def fun_l15_n785() + fun_l16_n364 +end + +def fun_l15_n786() + fun_l16_n950 +end + +def fun_l15_n787() + fun_l16_n769 +end + +def fun_l15_n788() + fun_l16_n322 +end + +def fun_l15_n789() + fun_l16_n604 +end + +def fun_l15_n790() + fun_l16_n425 +end + +def fun_l15_n791() + fun_l16_n318 +end + +def fun_l15_n792() + fun_l16_n236 +end + +def fun_l15_n793() + fun_l16_n794 +end + +def fun_l15_n794() + fun_l16_n948 +end + +def fun_l15_n795() + fun_l16_n421 +end + +def fun_l15_n796() + fun_l16_n565 +end + +def fun_l15_n797() + fun_l16_n363 +end + +def fun_l15_n798() + fun_l16_n274 +end + +def fun_l15_n799() + fun_l16_n391 +end + +def fun_l15_n800() + fun_l16_n303 +end + +def fun_l15_n801() + fun_l16_n31 +end + +def fun_l15_n802() + fun_l16_n585 +end + +def fun_l15_n803() + fun_l16_n769 +end + +def fun_l15_n804() + fun_l16_n749 +end + +def fun_l15_n805() + fun_l16_n405 +end + +def fun_l15_n806() + fun_l16_n53 +end + +def fun_l15_n807() + fun_l16_n951 +end + +def fun_l15_n808() + fun_l16_n817 +end + +def fun_l15_n809() + fun_l16_n217 +end + +def fun_l15_n810() + fun_l16_n210 +end + +def fun_l15_n811() + fun_l16_n830 +end + +def fun_l15_n812() + fun_l16_n743 +end + +def fun_l15_n813() + fun_l16_n908 +end + +def fun_l15_n814() + fun_l16_n343 +end + +def fun_l15_n815() + fun_l16_n135 +end + +def fun_l15_n816() + fun_l16_n346 +end + +def fun_l15_n817() + fun_l16_n947 +end + +def fun_l15_n818() + fun_l16_n969 +end + +def fun_l15_n819() + fun_l16_n313 +end + +def fun_l15_n820() + fun_l16_n668 +end + +def fun_l15_n821() + fun_l16_n923 +end + +def fun_l15_n822() + fun_l16_n650 +end + +def fun_l15_n823() + fun_l16_n601 +end + +def fun_l15_n824() + fun_l16_n775 +end + +def fun_l15_n825() + fun_l16_n748 +end + +def fun_l15_n826() + fun_l16_n353 +end + +def fun_l15_n827() + fun_l16_n164 +end + +def fun_l15_n828() + fun_l16_n458 +end + +def fun_l15_n829() + fun_l16_n257 +end + +def fun_l15_n830() + fun_l16_n968 +end + +def fun_l15_n831() + fun_l16_n932 +end + +def fun_l15_n832() + fun_l16_n749 +end + +def fun_l15_n833() + fun_l16_n873 +end + +def fun_l15_n834() + fun_l16_n940 +end + +def fun_l15_n835() + fun_l16_n404 +end + +def fun_l15_n836() + fun_l16_n235 +end + +def fun_l15_n837() + fun_l16_n584 +end + +def fun_l15_n838() + fun_l16_n12 +end + +def fun_l15_n839() + fun_l16_n378 +end + +def fun_l15_n840() + fun_l16_n463 +end + +def fun_l15_n841() + fun_l16_n310 +end + +def fun_l15_n842() + fun_l16_n832 +end + +def fun_l15_n843() + fun_l16_n641 +end + +def fun_l15_n844() + fun_l16_n484 +end + +def fun_l15_n845() + fun_l16_n589 +end + +def fun_l15_n846() + fun_l16_n315 +end + +def fun_l15_n847() + fun_l16_n977 +end + +def fun_l15_n848() + fun_l16_n946 +end + +def fun_l15_n849() + fun_l16_n848 +end + +def fun_l15_n850() + fun_l16_n956 +end + +def fun_l15_n851() + fun_l16_n608 +end + +def fun_l15_n852() + fun_l16_n787 +end + +def fun_l15_n853() + fun_l16_n527 +end + +def fun_l15_n854() + fun_l16_n426 +end + +def fun_l15_n855() + fun_l16_n330 +end + +def fun_l15_n856() + fun_l16_n687 +end + +def fun_l15_n857() + fun_l16_n672 +end + +def fun_l15_n858() + fun_l16_n133 +end + +def fun_l15_n859() + fun_l16_n515 +end + +def fun_l15_n860() + fun_l16_n20 +end + +def fun_l15_n861() + fun_l16_n419 +end + +def fun_l15_n862() + fun_l16_n239 +end + +def fun_l15_n863() + fun_l16_n379 +end + +def fun_l15_n864() + fun_l16_n241 +end + +def fun_l15_n865() + fun_l16_n713 +end + +def fun_l15_n866() + fun_l16_n705 +end + +def fun_l15_n867() + fun_l16_n487 +end + +def fun_l15_n868() + fun_l16_n959 +end + +def fun_l15_n869() + fun_l16_n914 +end + +def fun_l15_n870() + fun_l16_n325 +end + +def fun_l15_n871() + fun_l16_n983 +end + +def fun_l15_n872() + fun_l16_n363 +end + +def fun_l15_n873() + fun_l16_n617 +end + +def fun_l15_n874() + fun_l16_n420 +end + +def fun_l15_n875() + fun_l16_n732 +end + +def fun_l15_n876() + fun_l16_n560 +end + +def fun_l15_n877() + fun_l16_n318 +end + +def fun_l15_n878() + fun_l16_n97 +end + +def fun_l15_n879() + fun_l16_n242 +end + +def fun_l15_n880() + fun_l16_n801 +end + +def fun_l15_n881() + fun_l16_n56 +end + +def fun_l15_n882() + fun_l16_n68 +end + +def fun_l15_n883() + fun_l16_n625 +end + +def fun_l15_n884() + fun_l16_n400 +end + +def fun_l15_n885() + fun_l16_n405 +end + +def fun_l15_n886() + fun_l16_n778 +end + +def fun_l15_n887() + fun_l16_n865 +end + +def fun_l15_n888() + fun_l16_n737 +end + +def fun_l15_n889() + fun_l16_n233 +end + +def fun_l15_n890() + fun_l16_n594 +end + +def fun_l15_n891() + fun_l16_n240 +end + +def fun_l15_n892() + fun_l16_n511 +end + +def fun_l15_n893() + fun_l16_n711 +end + +def fun_l15_n894() + fun_l16_n238 +end + +def fun_l15_n895() + fun_l16_n903 +end + +def fun_l15_n896() + fun_l16_n506 +end + +def fun_l15_n897() + fun_l16_n794 +end + +def fun_l15_n898() + fun_l16_n812 +end + +def fun_l15_n899() + fun_l16_n829 +end + +def fun_l15_n900() + fun_l16_n686 +end + +def fun_l15_n901() + fun_l16_n302 +end + +def fun_l15_n902() + fun_l16_n947 +end + +def fun_l15_n903() + fun_l16_n107 +end + +def fun_l15_n904() + fun_l16_n79 +end + +def fun_l15_n905() + fun_l16_n570 +end + +def fun_l15_n906() + fun_l16_n567 +end + +def fun_l15_n907() + fun_l16_n853 +end + +def fun_l15_n908() + fun_l16_n49 +end + +def fun_l15_n909() + fun_l16_n721 +end + +def fun_l15_n910() + fun_l16_n376 +end + +def fun_l15_n911() + fun_l16_n513 +end + +def fun_l15_n912() + fun_l16_n863 +end + +def fun_l15_n913() + fun_l16_n692 +end + +def fun_l15_n914() + fun_l16_n391 +end + +def fun_l15_n915() + fun_l16_n263 +end + +def fun_l15_n916() + fun_l16_n159 +end + +def fun_l15_n917() + fun_l16_n291 +end + +def fun_l15_n918() + fun_l16_n290 +end + +def fun_l15_n919() + fun_l16_n328 +end + +def fun_l15_n920() + fun_l16_n838 +end + +def fun_l15_n921() + fun_l16_n66 +end + +def fun_l15_n922() + fun_l16_n821 +end + +def fun_l15_n923() + fun_l16_n549 +end + +def fun_l15_n924() + fun_l16_n235 +end + +def fun_l15_n925() + fun_l16_n800 +end + +def fun_l15_n926() + fun_l16_n486 +end + +def fun_l15_n927() + fun_l16_n824 +end + +def fun_l15_n928() + fun_l16_n881 +end + +def fun_l15_n929() + fun_l16_n772 +end + +def fun_l15_n930() + fun_l16_n563 +end + +def fun_l15_n931() + fun_l16_n99 +end + +def fun_l15_n932() + fun_l16_n691 +end + +def fun_l15_n933() + fun_l16_n983 +end + +def fun_l15_n934() + fun_l16_n593 +end + +def fun_l15_n935() + fun_l16_n611 +end + +def fun_l15_n936() + fun_l16_n600 +end + +def fun_l15_n937() + fun_l16_n892 +end + +def fun_l15_n938() + fun_l16_n653 +end + +def fun_l15_n939() + fun_l16_n78 +end + +def fun_l15_n940() + fun_l16_n139 +end + +def fun_l15_n941() + fun_l16_n995 +end + +def fun_l15_n942() + fun_l16_n63 +end + +def fun_l15_n943() + fun_l16_n466 +end + +def fun_l15_n944() + fun_l16_n740 +end + +def fun_l15_n945() + fun_l16_n870 +end + +def fun_l15_n946() + fun_l16_n373 +end + +def fun_l15_n947() + fun_l16_n375 +end + +def fun_l15_n948() + fun_l16_n360 +end + +def fun_l15_n949() + fun_l16_n526 +end + +def fun_l15_n950() + fun_l16_n100 +end + +def fun_l15_n951() + fun_l16_n644 +end + +def fun_l15_n952() + fun_l16_n773 +end + +def fun_l15_n953() + fun_l16_n311 +end + +def fun_l15_n954() + fun_l16_n152 +end + +def fun_l15_n955() + fun_l16_n754 +end + +def fun_l15_n956() + fun_l16_n31 +end + +def fun_l15_n957() + fun_l16_n501 +end + +def fun_l15_n958() + fun_l16_n333 +end + +def fun_l15_n959() + fun_l16_n952 +end + +def fun_l15_n960() + fun_l16_n753 +end + +def fun_l15_n961() + fun_l16_n694 +end + +def fun_l15_n962() + fun_l16_n82 +end + +def fun_l15_n963() + fun_l16_n204 +end + +def fun_l15_n964() + fun_l16_n910 +end + +def fun_l15_n965() + fun_l16_n127 +end + +def fun_l15_n966() + fun_l16_n203 +end + +def fun_l15_n967() + fun_l16_n760 +end + +def fun_l15_n968() + fun_l16_n718 +end + +def fun_l15_n969() + fun_l16_n446 +end + +def fun_l15_n970() + fun_l16_n595 +end + +def fun_l15_n971() + fun_l16_n165 +end + +def fun_l15_n972() + fun_l16_n393 +end + +def fun_l15_n973() + fun_l16_n766 +end + +def fun_l15_n974() + fun_l16_n276 +end + +def fun_l15_n975() + fun_l16_n97 +end + +def fun_l15_n976() + fun_l16_n319 +end + +def fun_l15_n977() + fun_l16_n333 +end + +def fun_l15_n978() + fun_l16_n635 +end + +def fun_l15_n979() + fun_l16_n466 +end + +def fun_l15_n980() + fun_l16_n841 +end + +def fun_l15_n981() + fun_l16_n415 +end + +def fun_l15_n982() + fun_l16_n630 +end + +def fun_l15_n983() + fun_l16_n19 +end + +def fun_l15_n984() + fun_l16_n901 +end + +def fun_l15_n985() + fun_l16_n933 +end + +def fun_l15_n986() + fun_l16_n558 +end + +def fun_l15_n987() + fun_l16_n357 +end + +def fun_l15_n988() + fun_l16_n929 +end + +def fun_l15_n989() + fun_l16_n871 +end + +def fun_l15_n990() + fun_l16_n967 +end + +def fun_l15_n991() + fun_l16_n803 +end + +def fun_l15_n992() + fun_l16_n484 +end + +def fun_l15_n993() + fun_l16_n270 +end + +def fun_l15_n994() + fun_l16_n670 +end + +def fun_l15_n995() + fun_l16_n77 +end + +def fun_l15_n996() + fun_l16_n480 +end + +def fun_l15_n997() + fun_l16_n279 +end + +def fun_l15_n998() + fun_l16_n109 +end + +def fun_l15_n999() + fun_l16_n333 +end + +def fun_l16_n0() + fun_l17_n358 +end + +def fun_l16_n1() + fun_l17_n388 +end + +def fun_l16_n2() + fun_l17_n450 +end + +def fun_l16_n3() + fun_l17_n274 +end + +def fun_l16_n4() + fun_l17_n83 +end + +def fun_l16_n5() + fun_l17_n148 +end + +def fun_l16_n6() + fun_l17_n370 +end + +def fun_l16_n7() + fun_l17_n956 +end + +def fun_l16_n8() + fun_l17_n137 +end + +def fun_l16_n9() + fun_l17_n702 +end + +def fun_l16_n10() + fun_l17_n296 +end + +def fun_l16_n11() + fun_l17_n44 +end + +def fun_l16_n12() + fun_l17_n937 +end + +def fun_l16_n13() + fun_l17_n100 +end + +def fun_l16_n14() + fun_l17_n599 +end + +def fun_l16_n15() + fun_l17_n757 +end + +def fun_l16_n16() + fun_l17_n831 +end + +def fun_l16_n17() + fun_l17_n753 +end + +def fun_l16_n18() + fun_l17_n726 +end + +def fun_l16_n19() + fun_l17_n126 +end + +def fun_l16_n20() + fun_l17_n106 +end + +def fun_l16_n21() + fun_l17_n46 +end + +def fun_l16_n22() + fun_l17_n56 +end + +def fun_l16_n23() + fun_l17_n16 +end + +def fun_l16_n24() + fun_l17_n298 +end + +def fun_l16_n25() + fun_l17_n173 +end + +def fun_l16_n26() + fun_l17_n479 +end + +def fun_l16_n27() + fun_l17_n304 +end + +def fun_l16_n28() + fun_l17_n426 +end + +def fun_l16_n29() + fun_l17_n214 +end + +def fun_l16_n30() + fun_l17_n818 +end + +def fun_l16_n31() + fun_l17_n362 +end + +def fun_l16_n32() + fun_l17_n392 +end + +def fun_l16_n33() + fun_l17_n751 +end + +def fun_l16_n34() + fun_l17_n719 +end + +def fun_l16_n35() + fun_l17_n258 +end + +def fun_l16_n36() + fun_l17_n128 +end + +def fun_l16_n37() + fun_l17_n95 +end + +def fun_l16_n38() + fun_l17_n30 +end + +def fun_l16_n39() + fun_l17_n539 +end + +def fun_l16_n40() + fun_l17_n139 +end + +def fun_l16_n41() + fun_l17_n309 +end + +def fun_l16_n42() + fun_l17_n943 +end + +def fun_l16_n43() + fun_l17_n242 +end + +def fun_l16_n44() + fun_l17_n402 +end + +def fun_l16_n45() + fun_l17_n173 +end + +def fun_l16_n46() + fun_l17_n328 +end + +def fun_l16_n47() + fun_l17_n883 +end + +def fun_l16_n48() + fun_l17_n992 +end + +def fun_l16_n49() + fun_l17_n921 +end + +def fun_l16_n50() + fun_l17_n130 +end + +def fun_l16_n51() + fun_l17_n374 +end + +def fun_l16_n52() + fun_l17_n555 +end + +def fun_l16_n53() + fun_l17_n965 +end + +def fun_l16_n54() + fun_l17_n353 +end + +def fun_l16_n55() + fun_l17_n525 +end + +def fun_l16_n56() + fun_l17_n569 +end + +def fun_l16_n57() + fun_l17_n156 +end + +def fun_l16_n58() + fun_l17_n695 +end + +def fun_l16_n59() + fun_l17_n864 +end + +def fun_l16_n60() + fun_l17_n415 +end + +def fun_l16_n61() + fun_l17_n605 +end + +def fun_l16_n62() + fun_l17_n995 +end + +def fun_l16_n63() + fun_l17_n794 +end + +def fun_l16_n64() + fun_l17_n813 +end + +def fun_l16_n65() + fun_l17_n839 +end + +def fun_l16_n66() + fun_l17_n273 +end + +def fun_l16_n67() + fun_l17_n223 +end + +def fun_l16_n68() + fun_l17_n168 +end + +def fun_l16_n69() + fun_l17_n798 +end + +def fun_l16_n70() + fun_l17_n892 +end + +def fun_l16_n71() + fun_l17_n966 +end + +def fun_l16_n72() + fun_l17_n102 +end + +def fun_l16_n73() + fun_l17_n209 +end + +def fun_l16_n74() + fun_l17_n618 +end + +def fun_l16_n75() + fun_l17_n432 +end + +def fun_l16_n76() + fun_l17_n254 +end + +def fun_l16_n77() + fun_l17_n413 +end + +def fun_l16_n78() + fun_l17_n908 +end + +def fun_l16_n79() + fun_l17_n519 +end + +def fun_l16_n80() + fun_l17_n67 +end + +def fun_l16_n81() + fun_l17_n914 +end + +def fun_l16_n82() + fun_l17_n356 +end + +def fun_l16_n83() + fun_l17_n138 +end + +def fun_l16_n84() + fun_l17_n714 +end + +def fun_l16_n85() + fun_l17_n803 +end + +def fun_l16_n86() + fun_l17_n770 +end + +def fun_l16_n87() + fun_l17_n813 +end + +def fun_l16_n88() + fun_l17_n752 +end + +def fun_l16_n89() + fun_l17_n580 +end + +def fun_l16_n90() + fun_l17_n368 +end + +def fun_l16_n91() + fun_l17_n169 +end + +def fun_l16_n92() + fun_l17_n565 +end + +def fun_l16_n93() + fun_l17_n111 +end + +def fun_l16_n94() + fun_l17_n911 +end + +def fun_l16_n95() + fun_l17_n448 +end + +def fun_l16_n96() + fun_l17_n455 +end + +def fun_l16_n97() + fun_l17_n76 +end + +def fun_l16_n98() + fun_l17_n27 +end + +def fun_l16_n99() + fun_l17_n884 +end + +def fun_l16_n100() + fun_l17_n144 +end + +def fun_l16_n101() + fun_l17_n344 +end + +def fun_l16_n102() + fun_l17_n293 +end + +def fun_l16_n103() + fun_l17_n91 +end + +def fun_l16_n104() + fun_l17_n398 +end + +def fun_l16_n105() + fun_l17_n398 +end + +def fun_l16_n106() + fun_l17_n216 +end + +def fun_l16_n107() + fun_l17_n22 +end + +def fun_l16_n108() + fun_l17_n901 +end + +def fun_l16_n109() + fun_l17_n817 +end + +def fun_l16_n110() + fun_l17_n574 +end + +def fun_l16_n111() + fun_l17_n546 +end + +def fun_l16_n112() + fun_l17_n704 +end + +def fun_l16_n113() + fun_l17_n184 +end + +def fun_l16_n114() + fun_l17_n993 +end + +def fun_l16_n115() + fun_l17_n582 +end + +def fun_l16_n116() + fun_l17_n943 +end + +def fun_l16_n117() + fun_l17_n692 +end + +def fun_l16_n118() + fun_l17_n203 +end + +def fun_l16_n119() + fun_l17_n283 +end + +def fun_l16_n120() + fun_l17_n600 +end + +def fun_l16_n121() + fun_l17_n953 +end + +def fun_l16_n122() + fun_l17_n810 +end + +def fun_l16_n123() + fun_l17_n861 +end + +def fun_l16_n124() + fun_l17_n680 +end + +def fun_l16_n125() + fun_l17_n401 +end + +def fun_l16_n126() + fun_l17_n905 +end + +def fun_l16_n127() + fun_l17_n376 +end + +def fun_l16_n128() + fun_l17_n231 +end + +def fun_l16_n129() + fun_l17_n693 +end + +def fun_l16_n130() + fun_l17_n219 +end + +def fun_l16_n131() + fun_l17_n560 +end + +def fun_l16_n132() + fun_l17_n17 +end + +def fun_l16_n133() + fun_l17_n706 +end + +def fun_l16_n134() + fun_l17_n355 +end + +def fun_l16_n135() + fun_l17_n309 +end + +def fun_l16_n136() + fun_l17_n514 +end + +def fun_l16_n137() + fun_l17_n428 +end + +def fun_l16_n138() + fun_l17_n80 +end + +def fun_l16_n139() + fun_l17_n548 +end + +def fun_l16_n140() + fun_l17_n514 +end + +def fun_l16_n141() + fun_l17_n316 +end + +def fun_l16_n142() + fun_l17_n791 +end + +def fun_l16_n143() + fun_l17_n70 +end + +def fun_l16_n144() + fun_l17_n953 +end + +def fun_l16_n145() + fun_l17_n416 +end + +def fun_l16_n146() + fun_l17_n989 +end + +def fun_l16_n147() + fun_l17_n604 +end + +def fun_l16_n148() + fun_l17_n845 +end + +def fun_l16_n149() + fun_l17_n576 +end + +def fun_l16_n150() + fun_l17_n831 +end + +def fun_l16_n151() + fun_l17_n727 +end + +def fun_l16_n152() + fun_l17_n231 +end + +def fun_l16_n153() + fun_l17_n405 +end + +def fun_l16_n154() + fun_l17_n643 +end + +def fun_l16_n155() + fun_l17_n117 +end + +def fun_l16_n156() + fun_l17_n842 +end + +def fun_l16_n157() + fun_l17_n522 +end + +def fun_l16_n158() + fun_l17_n415 +end + +def fun_l16_n159() + fun_l17_n239 +end + +def fun_l16_n160() + fun_l17_n512 +end + +def fun_l16_n161() + fun_l17_n247 +end + +def fun_l16_n162() + fun_l17_n798 +end + +def fun_l16_n163() + fun_l17_n771 +end + +def fun_l16_n164() + fun_l17_n47 +end + +def fun_l16_n165() + fun_l17_n803 +end + +def fun_l16_n166() + fun_l17_n500 +end + +def fun_l16_n167() + fun_l17_n797 +end + +def fun_l16_n168() + fun_l17_n467 +end + +def fun_l16_n169() + fun_l17_n893 +end + +def fun_l16_n170() + fun_l17_n900 +end + +def fun_l16_n171() + fun_l17_n539 +end + +def fun_l16_n172() + fun_l17_n631 +end + +def fun_l16_n173() + fun_l17_n113 +end + +def fun_l16_n174() + fun_l17_n674 +end + +def fun_l16_n175() + fun_l17_n827 +end + +def fun_l16_n176() + fun_l17_n751 +end + +def fun_l16_n177() + fun_l17_n600 +end + +def fun_l16_n178() + fun_l17_n290 +end + +def fun_l16_n179() + fun_l17_n947 +end + +def fun_l16_n180() + fun_l17_n718 +end + +def fun_l16_n181() + fun_l17_n531 +end + +def fun_l16_n182() + fun_l17_n849 +end + +def fun_l16_n183() + fun_l17_n310 +end + +def fun_l16_n184() + fun_l17_n795 +end + +def fun_l16_n185() + fun_l17_n65 +end + +def fun_l16_n186() + fun_l17_n242 +end + +def fun_l16_n187() + fun_l17_n832 +end + +def fun_l16_n188() + fun_l17_n749 +end + +def fun_l16_n189() + fun_l17_n826 +end + +def fun_l16_n190() + fun_l17_n244 +end + +def fun_l16_n191() + fun_l17_n279 +end + +def fun_l16_n192() + fun_l17_n746 +end + +def fun_l16_n193() + fun_l17_n199 +end + +def fun_l16_n194() + fun_l17_n458 +end + +def fun_l16_n195() + fun_l17_n161 +end + +def fun_l16_n196() + fun_l17_n584 +end + +def fun_l16_n197() + fun_l17_n400 +end + +def fun_l16_n198() + fun_l17_n598 +end + +def fun_l16_n199() + fun_l17_n685 +end + +def fun_l16_n200() + fun_l17_n939 +end + +def fun_l16_n201() + fun_l17_n374 +end + +def fun_l16_n202() + fun_l17_n463 +end + +def fun_l16_n203() + fun_l17_n677 +end + +def fun_l16_n204() + fun_l17_n857 +end + +def fun_l16_n205() + fun_l17_n39 +end + +def fun_l16_n206() + fun_l17_n899 +end + +def fun_l16_n207() + fun_l17_n733 +end + +def fun_l16_n208() + fun_l17_n137 +end + +def fun_l16_n209() + fun_l17_n988 +end + +def fun_l16_n210() + fun_l17_n792 +end + +def fun_l16_n211() + fun_l17_n861 +end + +def fun_l16_n212() + fun_l17_n889 +end + +def fun_l16_n213() + fun_l17_n933 +end + +def fun_l16_n214() + fun_l17_n898 +end + +def fun_l16_n215() + fun_l17_n723 +end + +def fun_l16_n216() + fun_l17_n116 +end + +def fun_l16_n217() + fun_l17_n251 +end + +def fun_l16_n218() + fun_l17_n586 +end + +def fun_l16_n219() + fun_l17_n428 +end + +def fun_l16_n220() + fun_l17_n53 +end + +def fun_l16_n221() + fun_l17_n611 +end + +def fun_l16_n222() + fun_l17_n480 +end + +def fun_l16_n223() + fun_l17_n2 +end + +def fun_l16_n224() + fun_l17_n623 +end + +def fun_l16_n225() + fun_l17_n178 +end + +def fun_l16_n226() + fun_l17_n938 +end + +def fun_l16_n227() + fun_l17_n284 +end + +def fun_l16_n228() + fun_l17_n925 +end + +def fun_l16_n229() + fun_l17_n899 +end + +def fun_l16_n230() + fun_l17_n314 +end + +def fun_l16_n231() + fun_l17_n931 +end + +def fun_l16_n232() + fun_l17_n103 +end + +def fun_l16_n233() + fun_l17_n201 +end + +def fun_l16_n234() + fun_l17_n139 +end + +def fun_l16_n235() + fun_l17_n509 +end + +def fun_l16_n236() + fun_l17_n168 +end + +def fun_l16_n237() + fun_l17_n667 +end + +def fun_l16_n238() + fun_l17_n998 +end + +def fun_l16_n239() + fun_l17_n931 +end + +def fun_l16_n240() + fun_l17_n159 +end + +def fun_l16_n241() + fun_l17_n402 +end + +def fun_l16_n242() + fun_l17_n488 +end + +def fun_l16_n243() + fun_l17_n319 +end + +def fun_l16_n244() + fun_l17_n209 +end + +def fun_l16_n245() + fun_l17_n409 +end + +def fun_l16_n246() + fun_l17_n712 +end + +def fun_l16_n247() + fun_l17_n680 +end + +def fun_l16_n248() + fun_l17_n57 +end + +def fun_l16_n249() + fun_l17_n68 +end + +def fun_l16_n250() + fun_l17_n676 +end + +def fun_l16_n251() + fun_l17_n870 +end + +def fun_l16_n252() + fun_l17_n718 +end + +def fun_l16_n253() + fun_l17_n753 +end + +def fun_l16_n254() + fun_l17_n317 +end + +def fun_l16_n255() + fun_l17_n905 +end + +def fun_l16_n256() + fun_l17_n524 +end + +def fun_l16_n257() + fun_l17_n496 +end + +def fun_l16_n258() + fun_l17_n253 +end + +def fun_l16_n259() + fun_l17_n32 +end + +def fun_l16_n260() + fun_l17_n299 +end + +def fun_l16_n261() + fun_l17_n291 +end + +def fun_l16_n262() + fun_l17_n516 +end + +def fun_l16_n263() + fun_l17_n542 +end + +def fun_l16_n264() + fun_l17_n550 +end + +def fun_l16_n265() + fun_l17_n886 +end + +def fun_l16_n266() + fun_l17_n428 +end + +def fun_l16_n267() + fun_l17_n741 +end + +def fun_l16_n268() + fun_l17_n711 +end + +def fun_l16_n269() + fun_l17_n709 +end + +def fun_l16_n270() + fun_l17_n71 +end + +def fun_l16_n271() + fun_l17_n256 +end + +def fun_l16_n272() + fun_l17_n585 +end + +def fun_l16_n273() + fun_l17_n478 +end + +def fun_l16_n274() + fun_l17_n314 +end + +def fun_l16_n275() + fun_l17_n223 +end + +def fun_l16_n276() + fun_l17_n691 +end + +def fun_l16_n277() + fun_l17_n637 +end + +def fun_l16_n278() + fun_l17_n218 +end + +def fun_l16_n279() + fun_l17_n675 +end + +def fun_l16_n280() + fun_l17_n705 +end + +def fun_l16_n281() + fun_l17_n492 +end + +def fun_l16_n282() + fun_l17_n426 +end + +def fun_l16_n283() + fun_l17_n366 +end + +def fun_l16_n284() + fun_l17_n533 +end + +def fun_l16_n285() + fun_l17_n980 +end + +def fun_l16_n286() + fun_l17_n660 +end + +def fun_l16_n287() + fun_l17_n550 +end + +def fun_l16_n288() + fun_l17_n37 +end + +def fun_l16_n289() + fun_l17_n453 +end + +def fun_l16_n290() + fun_l17_n687 +end + +def fun_l16_n291() + fun_l17_n82 +end + +def fun_l16_n292() + fun_l17_n327 +end + +def fun_l16_n293() + fun_l17_n842 +end + +def fun_l16_n294() + fun_l17_n201 +end + +def fun_l16_n295() + fun_l17_n26 +end + +def fun_l16_n296() + fun_l17_n153 +end + +def fun_l16_n297() + fun_l17_n684 +end + +def fun_l16_n298() + fun_l17_n752 +end + +def fun_l16_n299() + fun_l17_n763 +end + +def fun_l16_n300() + fun_l17_n651 +end + +def fun_l16_n301() + fun_l17_n605 +end + +def fun_l16_n302() + fun_l17_n48 +end + +def fun_l16_n303() + fun_l17_n71 +end + +def fun_l16_n304() + fun_l17_n57 +end + +def fun_l16_n305() + fun_l17_n72 +end + +def fun_l16_n306() + fun_l17_n561 +end + +def fun_l16_n307() + fun_l17_n10 +end + +def fun_l16_n308() + fun_l17_n543 +end + +def fun_l16_n309() + fun_l17_n17 +end + +def fun_l16_n310() + fun_l17_n340 +end + +def fun_l16_n311() + fun_l17_n184 +end + +def fun_l16_n312() + fun_l17_n208 +end + +def fun_l16_n313() + fun_l17_n46 +end + +def fun_l16_n314() + fun_l17_n386 +end + +def fun_l16_n315() + fun_l17_n258 +end + +def fun_l16_n316() + fun_l17_n594 +end + +def fun_l16_n317() + fun_l17_n968 +end + +def fun_l16_n318() + fun_l17_n403 +end + +def fun_l16_n319() + fun_l17_n256 +end + +def fun_l16_n320() + fun_l17_n212 +end + +def fun_l16_n321() + fun_l17_n567 +end + +def fun_l16_n322() + fun_l17_n61 +end + +def fun_l16_n323() + fun_l17_n925 +end + +def fun_l16_n324() + fun_l17_n679 +end + +def fun_l16_n325() + fun_l17_n136 +end + +def fun_l16_n326() + fun_l17_n403 +end + +def fun_l16_n327() + fun_l17_n35 +end + +def fun_l16_n328() + fun_l17_n833 +end + +def fun_l16_n329() + fun_l17_n925 +end + +def fun_l16_n330() + fun_l17_n193 +end + +def fun_l16_n331() + fun_l17_n474 +end + +def fun_l16_n332() + fun_l17_n271 +end + +def fun_l16_n333() + fun_l17_n604 +end + +def fun_l16_n334() + fun_l17_n570 +end + +def fun_l16_n335() + fun_l17_n110 +end + +def fun_l16_n336() + fun_l17_n920 +end + +def fun_l16_n337() + fun_l17_n388 +end + +def fun_l16_n338() + fun_l17_n207 +end + +def fun_l16_n339() + fun_l17_n899 +end + +def fun_l16_n340() + fun_l17_n337 +end + +def fun_l16_n341() + fun_l17_n611 +end + +def fun_l16_n342() + fun_l17_n474 +end + +def fun_l16_n343() + fun_l17_n71 +end + +def fun_l16_n344() + fun_l17_n347 +end + +def fun_l16_n345() + fun_l17_n911 +end + +def fun_l16_n346() + fun_l17_n625 +end + +def fun_l16_n347() + fun_l17_n683 +end + +def fun_l16_n348() + fun_l17_n628 +end + +def fun_l16_n349() + fun_l17_n73 +end + +def fun_l16_n350() + fun_l17_n710 +end + +def fun_l16_n351() + fun_l17_n550 +end + +def fun_l16_n352() + fun_l17_n96 +end + +def fun_l16_n353() + fun_l17_n815 +end + +def fun_l16_n354() + fun_l17_n494 +end + +def fun_l16_n355() + fun_l17_n831 +end + +def fun_l16_n356() + fun_l17_n174 +end + +def fun_l16_n357() + fun_l17_n196 +end + +def fun_l16_n358() + fun_l17_n191 +end + +def fun_l16_n359() + fun_l17_n278 +end + +def fun_l16_n360() + fun_l17_n433 +end + +def fun_l16_n361() + fun_l17_n673 +end + +def fun_l16_n362() + fun_l17_n313 +end + +def fun_l16_n363() + fun_l17_n517 +end + +def fun_l16_n364() + fun_l17_n392 +end + +def fun_l16_n365() + fun_l17_n574 +end + +def fun_l16_n366() + fun_l17_n531 +end + +def fun_l16_n367() + fun_l17_n222 +end + +def fun_l16_n368() + fun_l17_n226 +end + +def fun_l16_n369() + fun_l17_n309 +end + +def fun_l16_n370() + fun_l17_n125 +end + +def fun_l16_n371() + fun_l17_n523 +end + +def fun_l16_n372() + fun_l17_n261 +end + +def fun_l16_n373() + fun_l17_n830 +end + +def fun_l16_n374() + fun_l17_n851 +end + +def fun_l16_n375() + fun_l17_n845 +end + +def fun_l16_n376() + fun_l17_n76 +end + +def fun_l16_n377() + fun_l17_n405 +end + +def fun_l16_n378() + fun_l17_n972 +end + +def fun_l16_n379() + fun_l17_n769 +end + +def fun_l16_n380() + fun_l17_n246 +end + +def fun_l16_n381() + fun_l17_n95 +end + +def fun_l16_n382() + fun_l17_n768 +end + +def fun_l16_n383() + fun_l17_n12 +end + +def fun_l16_n384() + fun_l17_n164 +end + +def fun_l16_n385() + fun_l17_n579 +end + +def fun_l16_n386() + fun_l17_n241 +end + +def fun_l16_n387() + fun_l17_n913 +end + +def fun_l16_n388() + fun_l17_n518 +end + +def fun_l16_n389() + fun_l17_n376 +end + +def fun_l16_n390() + fun_l17_n256 +end + +def fun_l16_n391() + fun_l17_n25 +end + +def fun_l16_n392() + fun_l17_n699 +end + +def fun_l16_n393() + fun_l17_n808 +end + +def fun_l16_n394() + fun_l17_n234 +end + +def fun_l16_n395() + fun_l17_n517 +end + +def fun_l16_n396() + fun_l17_n172 +end + +def fun_l16_n397() + fun_l17_n811 +end + +def fun_l16_n398() + fun_l17_n513 +end + +def fun_l16_n399() + fun_l17_n144 +end + +def fun_l16_n400() + fun_l17_n92 +end + +def fun_l16_n401() + fun_l17_n599 +end + +def fun_l16_n402() + fun_l17_n394 +end + +def fun_l16_n403() + fun_l17_n17 +end + +def fun_l16_n404() + fun_l17_n450 +end + +def fun_l16_n405() + fun_l17_n46 +end + +def fun_l16_n406() + fun_l17_n819 +end + +def fun_l16_n407() + fun_l17_n955 +end + +def fun_l16_n408() + fun_l17_n261 +end + +def fun_l16_n409() + fun_l17_n695 +end + +def fun_l16_n410() + fun_l17_n90 +end + +def fun_l16_n411() + fun_l17_n93 +end + +def fun_l16_n412() + fun_l17_n529 +end + +def fun_l16_n413() + fun_l17_n831 +end + +def fun_l16_n414() + fun_l17_n107 +end + +def fun_l16_n415() + fun_l17_n977 +end + +def fun_l16_n416() + fun_l17_n891 +end + +def fun_l16_n417() + fun_l17_n256 +end + +def fun_l16_n418() + fun_l17_n45 +end + +def fun_l16_n419() + fun_l17_n862 +end + +def fun_l16_n420() + fun_l17_n294 +end + +def fun_l16_n421() + fun_l17_n421 +end + +def fun_l16_n422() + fun_l17_n749 +end + +def fun_l16_n423() + fun_l17_n689 +end + +def fun_l16_n424() + fun_l17_n524 +end + +def fun_l16_n425() + fun_l17_n946 +end + +def fun_l16_n426() + fun_l17_n222 +end + +def fun_l16_n427() + fun_l17_n146 +end + +def fun_l16_n428() + fun_l17_n219 +end + +def fun_l16_n429() + fun_l17_n380 +end + +def fun_l16_n430() + fun_l17_n371 +end + +def fun_l16_n431() + fun_l17_n813 +end + +def fun_l16_n432() + fun_l17_n546 +end + +def fun_l16_n433() + fun_l17_n429 +end + +def fun_l16_n434() + fun_l17_n672 +end + +def fun_l16_n435() + fun_l17_n374 +end + +def fun_l16_n436() + fun_l17_n695 +end + +def fun_l16_n437() + fun_l17_n682 +end + +def fun_l16_n438() + fun_l17_n894 +end + +def fun_l16_n439() + fun_l17_n268 +end + +def fun_l16_n440() + fun_l17_n393 +end + +def fun_l16_n441() + fun_l17_n852 +end + +def fun_l16_n442() + fun_l17_n481 +end + +def fun_l16_n443() + fun_l17_n598 +end + +def fun_l16_n444() + fun_l17_n851 +end + +def fun_l16_n445() + fun_l17_n132 +end + +def fun_l16_n446() + fun_l17_n357 +end + +def fun_l16_n447() + fun_l17_n132 +end + +def fun_l16_n448() + fun_l17_n829 +end + +def fun_l16_n449() + fun_l17_n591 +end + +def fun_l16_n450() + fun_l17_n437 +end + +def fun_l16_n451() + fun_l17_n108 +end + +def fun_l16_n452() + fun_l17_n898 +end + +def fun_l16_n453() + fun_l17_n263 +end + +def fun_l16_n454() + fun_l17_n942 +end + +def fun_l16_n455() + fun_l17_n470 +end + +def fun_l16_n456() + fun_l17_n427 +end + +def fun_l16_n457() + fun_l17_n884 +end + +def fun_l16_n458() + fun_l17_n413 +end + +def fun_l16_n459() + fun_l17_n105 +end + +def fun_l16_n460() + fun_l17_n75 +end + +def fun_l16_n461() + fun_l17_n149 +end + +def fun_l16_n462() + fun_l17_n133 +end + +def fun_l16_n463() + fun_l17_n173 +end + +def fun_l16_n464() + fun_l17_n232 +end + +def fun_l16_n465() + fun_l17_n909 +end + +def fun_l16_n466() + fun_l17_n400 +end + +def fun_l16_n467() + fun_l17_n500 +end + +def fun_l16_n468() + fun_l17_n446 +end + +def fun_l16_n469() + fun_l17_n288 +end + +def fun_l16_n470() + fun_l17_n228 +end + +def fun_l16_n471() + fun_l17_n169 +end + +def fun_l16_n472() + fun_l17_n10 +end + +def fun_l16_n473() + fun_l17_n538 +end + +def fun_l16_n474() + fun_l17_n722 +end + +def fun_l16_n475() + fun_l17_n430 +end + +def fun_l16_n476() + fun_l17_n687 +end + +def fun_l16_n477() + fun_l17_n932 +end + +def fun_l16_n478() + fun_l17_n658 +end + +def fun_l16_n479() + fun_l17_n104 +end + +def fun_l16_n480() + fun_l17_n723 +end + +def fun_l16_n481() + fun_l17_n121 +end + +def fun_l16_n482() + fun_l17_n836 +end + +def fun_l16_n483() + fun_l17_n860 +end + +def fun_l16_n484() + fun_l17_n583 +end + +def fun_l16_n485() + fun_l17_n582 +end + +def fun_l16_n486() + fun_l17_n470 +end + +def fun_l16_n487() + fun_l17_n103 +end + +def fun_l16_n488() + fun_l17_n69 +end + +def fun_l16_n489() + fun_l17_n164 +end + +def fun_l16_n490() + fun_l17_n218 +end + +def fun_l16_n491() + fun_l17_n458 +end + +def fun_l16_n492() + fun_l17_n653 +end + +def fun_l16_n493() + fun_l17_n367 +end + +def fun_l16_n494() + fun_l17_n40 +end + +def fun_l16_n495() + fun_l17_n533 +end + +def fun_l16_n496() + fun_l17_n614 +end + +def fun_l16_n497() + fun_l17_n228 +end + +def fun_l16_n498() + fun_l17_n172 +end + +def fun_l16_n499() + fun_l17_n101 +end + +def fun_l16_n500() + fun_l17_n843 +end + +def fun_l16_n501() + fun_l17_n710 +end + +def fun_l16_n502() + fun_l17_n109 +end + +def fun_l16_n503() + fun_l17_n858 +end + +def fun_l16_n504() + fun_l17_n81 +end + +def fun_l16_n505() + fun_l17_n951 +end + +def fun_l16_n506() + fun_l17_n303 +end + +def fun_l16_n507() + fun_l17_n591 +end + +def fun_l16_n508() + fun_l17_n956 +end + +def fun_l16_n509() + fun_l17_n207 +end + +def fun_l16_n510() + fun_l17_n113 +end + +def fun_l16_n511() + fun_l17_n875 +end + +def fun_l16_n512() + fun_l17_n514 +end + +def fun_l16_n513() + fun_l17_n990 +end + +def fun_l16_n514() + fun_l17_n418 +end + +def fun_l16_n515() + fun_l17_n849 +end + +def fun_l16_n516() + fun_l17_n491 +end + +def fun_l16_n517() + fun_l17_n740 +end + +def fun_l16_n518() + fun_l17_n46 +end + +def fun_l16_n519() + fun_l17_n923 +end + +def fun_l16_n520() + fun_l17_n632 +end + +def fun_l16_n521() + fun_l17_n198 +end + +def fun_l16_n522() + fun_l17_n441 +end + +def fun_l16_n523() + fun_l17_n291 +end + +def fun_l16_n524() + fun_l17_n32 +end + +def fun_l16_n525() + fun_l17_n600 +end + +def fun_l16_n526() + fun_l17_n536 +end + +def fun_l16_n527() + fun_l17_n702 +end + +def fun_l16_n528() + fun_l17_n193 +end + +def fun_l16_n529() + fun_l17_n155 +end + +def fun_l16_n530() + fun_l17_n957 +end + +def fun_l16_n531() + fun_l17_n543 +end + +def fun_l16_n532() + fun_l17_n932 +end + +def fun_l16_n533() + fun_l17_n685 +end + +def fun_l16_n534() + fun_l17_n56 +end + +def fun_l16_n535() + fun_l17_n488 +end + +def fun_l16_n536() + fun_l17_n894 +end + +def fun_l16_n537() + fun_l17_n753 +end + +def fun_l16_n538() + fun_l17_n577 +end + +def fun_l16_n539() + fun_l17_n827 +end + +def fun_l16_n540() + fun_l17_n619 +end + +def fun_l16_n541() + fun_l17_n144 +end + +def fun_l16_n542() + fun_l17_n756 +end + +def fun_l16_n543() + fun_l17_n32 +end + +def fun_l16_n544() + fun_l17_n774 +end + +def fun_l16_n545() + fun_l17_n143 +end + +def fun_l16_n546() + fun_l17_n605 +end + +def fun_l16_n547() + fun_l17_n573 +end + +def fun_l16_n548() + fun_l17_n242 +end + +def fun_l16_n549() + fun_l17_n522 +end + +def fun_l16_n550() + fun_l17_n208 +end + +def fun_l16_n551() + fun_l17_n740 +end + +def fun_l16_n552() + fun_l17_n972 +end + +def fun_l16_n553() + fun_l17_n390 +end + +def fun_l16_n554() + fun_l17_n889 +end + +def fun_l16_n555() + fun_l17_n60 +end + +def fun_l16_n556() + fun_l17_n682 +end + +def fun_l16_n557() + fun_l17_n592 +end + +def fun_l16_n558() + fun_l17_n480 +end + +def fun_l16_n559() + fun_l17_n963 +end + +def fun_l16_n560() + fun_l17_n128 +end + +def fun_l16_n561() + fun_l17_n167 +end + +def fun_l16_n562() + fun_l17_n415 +end + +def fun_l16_n563() + fun_l17_n199 +end + +def fun_l16_n564() + fun_l17_n926 +end + +def fun_l16_n565() + fun_l17_n165 +end + +def fun_l16_n566() + fun_l17_n226 +end + +def fun_l16_n567() + fun_l17_n346 +end + +def fun_l16_n568() + fun_l17_n351 +end + +def fun_l16_n569() + fun_l17_n934 +end + +def fun_l16_n570() + fun_l17_n658 +end + +def fun_l16_n571() + fun_l17_n941 +end + +def fun_l16_n572() + fun_l17_n20 +end + +def fun_l16_n573() + fun_l17_n769 +end + +def fun_l16_n574() + fun_l17_n419 +end + +def fun_l16_n575() + fun_l17_n51 +end + +def fun_l16_n576() + fun_l17_n809 +end + +def fun_l16_n577() + fun_l17_n315 +end + +def fun_l16_n578() + fun_l17_n479 +end + +def fun_l16_n579() + fun_l17_n99 +end + +def fun_l16_n580() + fun_l17_n675 +end + +def fun_l16_n581() + fun_l17_n381 +end + +def fun_l16_n582() + fun_l17_n340 +end + +def fun_l16_n583() + fun_l17_n569 +end + +def fun_l16_n584() + fun_l17_n697 +end + +def fun_l16_n585() + fun_l17_n376 +end + +def fun_l16_n586() + fun_l17_n179 +end + +def fun_l16_n587() + fun_l17_n266 +end + +def fun_l16_n588() + fun_l17_n638 +end + +def fun_l16_n589() + fun_l17_n236 +end + +def fun_l16_n590() + fun_l17_n293 +end + +def fun_l16_n591() + fun_l17_n310 +end + +def fun_l16_n592() + fun_l17_n213 +end + +def fun_l16_n593() + fun_l17_n716 +end + +def fun_l16_n594() + fun_l17_n563 +end + +def fun_l16_n595() + fun_l17_n781 +end + +def fun_l16_n596() + fun_l17_n961 +end + +def fun_l16_n597() + fun_l17_n445 +end + +def fun_l16_n598() + fun_l17_n68 +end + +def fun_l16_n599() + fun_l17_n946 +end + +def fun_l16_n600() + fun_l17_n246 +end + +def fun_l16_n601() + fun_l17_n842 +end + +def fun_l16_n602() + fun_l17_n43 +end + +def fun_l16_n603() + fun_l17_n274 +end + +def fun_l16_n604() + fun_l17_n10 +end + +def fun_l16_n605() + fun_l17_n319 +end + +def fun_l16_n606() + fun_l17_n834 +end + +def fun_l16_n607() + fun_l17_n483 +end + +def fun_l16_n608() + fun_l17_n846 +end + +def fun_l16_n609() + fun_l17_n779 +end + +def fun_l16_n610() + fun_l17_n539 +end + +def fun_l16_n611() + fun_l17_n579 +end + +def fun_l16_n612() + fun_l17_n841 +end + +def fun_l16_n613() + fun_l17_n27 +end + +def fun_l16_n614() + fun_l17_n283 +end + +def fun_l16_n615() + fun_l17_n782 +end + +def fun_l16_n616() + fun_l17_n815 +end + +def fun_l16_n617() + fun_l17_n961 +end + +def fun_l16_n618() + fun_l17_n626 +end + +def fun_l16_n619() + fun_l17_n79 +end + +def fun_l16_n620() + fun_l17_n814 +end + +def fun_l16_n621() + fun_l17_n674 +end + +def fun_l16_n622() + fun_l17_n788 +end + +def fun_l16_n623() + fun_l17_n714 +end + +def fun_l16_n624() + fun_l17_n257 +end + +def fun_l16_n625() + fun_l17_n424 +end + +def fun_l16_n626() + fun_l17_n393 +end + +def fun_l16_n627() + fun_l17_n187 +end + +def fun_l16_n628() + fun_l17_n778 +end + +def fun_l16_n629() + fun_l17_n466 +end + +def fun_l16_n630() + fun_l17_n63 +end + +def fun_l16_n631() + fun_l17_n375 +end + +def fun_l16_n632() + fun_l17_n584 +end + +def fun_l16_n633() + fun_l17_n148 +end + +def fun_l16_n634() + fun_l17_n466 +end + +def fun_l16_n635() + fun_l17_n889 +end + +def fun_l16_n636() + fun_l17_n360 +end + +def fun_l16_n637() + fun_l17_n578 +end + +def fun_l16_n638() + fun_l17_n345 +end + +def fun_l16_n639() + fun_l17_n224 +end + +def fun_l16_n640() + fun_l17_n574 +end + +def fun_l16_n641() + fun_l17_n175 +end + +def fun_l16_n642() + fun_l17_n141 +end + +def fun_l16_n643() + fun_l17_n405 +end + +def fun_l16_n644() + fun_l17_n992 +end + +def fun_l16_n645() + fun_l17_n503 +end + +def fun_l16_n646() + fun_l17_n553 +end + +def fun_l16_n647() + fun_l17_n615 +end + +def fun_l16_n648() + fun_l17_n925 +end + +def fun_l16_n649() + fun_l17_n174 +end + +def fun_l16_n650() + fun_l17_n552 +end + +def fun_l16_n651() + fun_l17_n243 +end + +def fun_l16_n652() + fun_l17_n364 +end + +def fun_l16_n653() + fun_l17_n76 +end + +def fun_l16_n654() + fun_l17_n68 +end + +def fun_l16_n655() + fun_l17_n623 +end + +def fun_l16_n656() + fun_l17_n539 +end + +def fun_l16_n657() + fun_l17_n875 +end + +def fun_l16_n658() + fun_l17_n593 +end + +def fun_l16_n659() + fun_l17_n740 +end + +def fun_l16_n660() + fun_l17_n241 +end + +def fun_l16_n661() + fun_l17_n338 +end + +def fun_l16_n662() + fun_l17_n430 +end + +def fun_l16_n663() + fun_l17_n49 +end + +def fun_l16_n664() + fun_l17_n42 +end + +def fun_l16_n665() + fun_l17_n254 +end + +def fun_l16_n666() + fun_l17_n538 +end + +def fun_l16_n667() + fun_l17_n192 +end + +def fun_l16_n668() + fun_l17_n803 +end + +def fun_l16_n669() + fun_l17_n898 +end + +def fun_l16_n670() + fun_l17_n825 +end + +def fun_l16_n671() + fun_l17_n968 +end + +def fun_l16_n672() + fun_l17_n417 +end + +def fun_l16_n673() + fun_l17_n255 +end + +def fun_l16_n674() + fun_l17_n311 +end + +def fun_l16_n675() + fun_l17_n296 +end + +def fun_l16_n676() + fun_l17_n209 +end + +def fun_l16_n677() + fun_l17_n560 +end + +def fun_l16_n678() + fun_l17_n909 +end + +def fun_l16_n679() + fun_l17_n927 +end + +def fun_l16_n680() + fun_l17_n844 +end + +def fun_l16_n681() + fun_l17_n411 +end + +def fun_l16_n682() + fun_l17_n757 +end + +def fun_l16_n683() + fun_l17_n723 +end + +def fun_l16_n684() + fun_l17_n119 +end + +def fun_l16_n685() + fun_l17_n906 +end + +def fun_l16_n686() + fun_l17_n674 +end + +def fun_l16_n687() + fun_l17_n42 +end + +def fun_l16_n688() + fun_l17_n350 +end + +def fun_l16_n689() + fun_l17_n574 +end + +def fun_l16_n690() + fun_l17_n363 +end + +def fun_l16_n691() + fun_l17_n342 +end + +def fun_l16_n692() + fun_l17_n79 +end + +def fun_l16_n693() + fun_l17_n253 +end + +def fun_l16_n694() + fun_l17_n66 +end + +def fun_l16_n695() + fun_l17_n503 +end + +def fun_l16_n696() + fun_l17_n846 +end + +def fun_l16_n697() + fun_l17_n100 +end + +def fun_l16_n698() + fun_l17_n844 +end + +def fun_l16_n699() + fun_l17_n317 +end + +def fun_l16_n700() + fun_l17_n690 +end + +def fun_l16_n701() + fun_l17_n484 +end + +def fun_l16_n702() + fun_l17_n451 +end + +def fun_l16_n703() + fun_l17_n101 +end + +def fun_l16_n704() + fun_l17_n962 +end + +def fun_l16_n705() + fun_l17_n459 +end + +def fun_l16_n706() + fun_l17_n842 +end + +def fun_l16_n707() + fun_l17_n705 +end + +def fun_l16_n708() + fun_l17_n827 +end + +def fun_l16_n709() + fun_l17_n250 +end + +def fun_l16_n710() + fun_l17_n561 +end + +def fun_l16_n711() + fun_l17_n568 +end + +def fun_l16_n712() + fun_l17_n216 +end + +def fun_l16_n713() + fun_l17_n292 +end + +def fun_l16_n714() + fun_l17_n221 +end + +def fun_l16_n715() + fun_l17_n952 +end + +def fun_l16_n716() + fun_l17_n486 +end + +def fun_l16_n717() + fun_l17_n266 +end + +def fun_l16_n718() + fun_l17_n858 +end + +def fun_l16_n719() + fun_l17_n464 +end + +def fun_l16_n720() + fun_l17_n555 +end + +def fun_l16_n721() + fun_l17_n732 +end + +def fun_l16_n722() + fun_l17_n281 +end + +def fun_l16_n723() + fun_l17_n210 +end + +def fun_l16_n724() + fun_l17_n211 +end + +def fun_l16_n725() + fun_l17_n971 +end + +def fun_l16_n726() + fun_l17_n94 +end + +def fun_l16_n727() + fun_l17_n103 +end + +def fun_l16_n728() + fun_l17_n655 +end + +def fun_l16_n729() + fun_l17_n272 +end + +def fun_l16_n730() + fun_l17_n908 +end + +def fun_l16_n731() + fun_l17_n126 +end + +def fun_l16_n732() + fun_l17_n417 +end + +def fun_l16_n733() + fun_l17_n573 +end + +def fun_l16_n734() + fun_l17_n733 +end + +def fun_l16_n735() + fun_l17_n483 +end + +def fun_l16_n736() + fun_l17_n330 +end + +def fun_l16_n737() + fun_l17_n159 +end + +def fun_l16_n738() + fun_l17_n548 +end + +def fun_l16_n739() + fun_l17_n770 +end + +def fun_l16_n740() + fun_l17_n320 +end + +def fun_l16_n741() + fun_l17_n706 +end + +def fun_l16_n742() + fun_l17_n383 +end + +def fun_l16_n743() + fun_l17_n737 +end + +def fun_l16_n744() + fun_l17_n470 +end + +def fun_l16_n745() + fun_l17_n956 +end + +def fun_l16_n746() + fun_l17_n582 +end + +def fun_l16_n747() + fun_l17_n0 +end + +def fun_l16_n748() + fun_l17_n744 +end + +def fun_l16_n749() + fun_l17_n810 +end + +def fun_l16_n750() + fun_l17_n130 +end + +def fun_l16_n751() + fun_l17_n17 +end + +def fun_l16_n752() + fun_l17_n191 +end + +def fun_l16_n753() + fun_l17_n557 +end + +def fun_l16_n754() + fun_l17_n675 +end + +def fun_l16_n755() + fun_l17_n43 +end + +def fun_l16_n756() + fun_l17_n907 +end + +def fun_l16_n757() + fun_l17_n203 +end + +def fun_l16_n758() + fun_l17_n388 +end + +def fun_l16_n759() + fun_l17_n101 +end + +def fun_l16_n760() + fun_l17_n110 +end + +def fun_l16_n761() + fun_l17_n765 +end + +def fun_l16_n762() + fun_l17_n406 +end + +def fun_l16_n763() + fun_l17_n120 +end + +def fun_l16_n764() + fun_l17_n266 +end + +def fun_l16_n765() + fun_l17_n35 +end + +def fun_l16_n766() + fun_l17_n478 +end + +def fun_l16_n767() + fun_l17_n135 +end + +def fun_l16_n768() + fun_l17_n934 +end + +def fun_l16_n769() + fun_l17_n442 +end + +def fun_l16_n770() + fun_l17_n233 +end + +def fun_l16_n771() + fun_l17_n336 +end + +def fun_l16_n772() + fun_l17_n832 +end + +def fun_l16_n773() + fun_l17_n207 +end + +def fun_l16_n774() + fun_l17_n752 +end + +def fun_l16_n775() + fun_l17_n928 +end + +def fun_l16_n776() + fun_l17_n217 +end + +def fun_l16_n777() + fun_l17_n925 +end + +def fun_l16_n778() + fun_l17_n833 +end + +def fun_l16_n779() + fun_l17_n421 +end + +def fun_l16_n780() + fun_l17_n878 +end + +def fun_l16_n781() + fun_l17_n117 +end + +def fun_l16_n782() + fun_l17_n55 +end + +def fun_l16_n783() + fun_l17_n46 +end + +def fun_l16_n784() + fun_l17_n260 +end + +def fun_l16_n785() + fun_l17_n270 +end + +def fun_l16_n786() + fun_l17_n68 +end + +def fun_l16_n787() + fun_l17_n768 +end + +def fun_l16_n788() + fun_l17_n671 +end + +def fun_l16_n789() + fun_l17_n338 +end + +def fun_l16_n790() + fun_l17_n442 +end + +def fun_l16_n791() + fun_l17_n677 +end + +def fun_l16_n792() + fun_l17_n141 +end + +def fun_l16_n793() + fun_l17_n427 +end + +def fun_l16_n794() + fun_l17_n493 +end + +def fun_l16_n795() + fun_l17_n461 +end + +def fun_l16_n796() + fun_l17_n615 +end + +def fun_l16_n797() + fun_l17_n895 +end + +def fun_l16_n798() + fun_l17_n883 +end + +def fun_l16_n799() + fun_l17_n992 +end + +def fun_l16_n800() + fun_l17_n754 +end + +def fun_l16_n801() + fun_l17_n668 +end + +def fun_l16_n802() + fun_l17_n362 +end + +def fun_l16_n803() + fun_l17_n179 +end + +def fun_l16_n804() + fun_l17_n35 +end + +def fun_l16_n805() + fun_l17_n999 +end + +def fun_l16_n806() + fun_l17_n211 +end + +def fun_l16_n807() + fun_l17_n859 +end + +def fun_l16_n808() + fun_l17_n126 +end + +def fun_l16_n809() + fun_l17_n935 +end + +def fun_l16_n810() + fun_l17_n682 +end + +def fun_l16_n811() + fun_l17_n788 +end + +def fun_l16_n812() + fun_l17_n939 +end + +def fun_l16_n813() + fun_l17_n687 +end + +def fun_l16_n814() + fun_l17_n274 +end + +def fun_l16_n815() + fun_l17_n699 +end + +def fun_l16_n816() + fun_l17_n129 +end + +def fun_l16_n817() + fun_l17_n201 +end + +def fun_l16_n818() + fun_l17_n448 +end + +def fun_l16_n819() + fun_l17_n482 +end + +def fun_l16_n820() + fun_l17_n199 +end + +def fun_l16_n821() + fun_l17_n283 +end + +def fun_l16_n822() + fun_l17_n413 +end + +def fun_l16_n823() + fun_l17_n373 +end + +def fun_l16_n824() + fun_l17_n368 +end + +def fun_l16_n825() + fun_l17_n892 +end + +def fun_l16_n826() + fun_l17_n40 +end + +def fun_l16_n827() + fun_l17_n258 +end + +def fun_l16_n828() + fun_l17_n218 +end + +def fun_l16_n829() + fun_l17_n647 +end + +def fun_l16_n830() + fun_l17_n429 +end + +def fun_l16_n831() + fun_l17_n524 +end + +def fun_l16_n832() + fun_l17_n424 +end + +def fun_l16_n833() + fun_l17_n755 +end + +def fun_l16_n834() + fun_l17_n82 +end + +def fun_l16_n835() + fun_l17_n109 +end + +def fun_l16_n836() + fun_l17_n399 +end + +def fun_l16_n837() + fun_l17_n829 +end + +def fun_l16_n838() + fun_l17_n26 +end + +def fun_l16_n839() + fun_l17_n537 +end + +def fun_l16_n840() + fun_l17_n969 +end + +def fun_l16_n841() + fun_l17_n248 +end + +def fun_l16_n842() + fun_l17_n178 +end + +def fun_l16_n843() + fun_l17_n816 +end + +def fun_l16_n844() + fun_l17_n925 +end + +def fun_l16_n845() + fun_l17_n388 +end + +def fun_l16_n846() + fun_l17_n923 +end + +def fun_l16_n847() + fun_l17_n386 +end + +def fun_l16_n848() + fun_l17_n940 +end + +def fun_l16_n849() + fun_l17_n831 +end + +def fun_l16_n850() + fun_l17_n771 +end + +def fun_l16_n851() + fun_l17_n45 +end + +def fun_l16_n852() + fun_l17_n18 +end + +def fun_l16_n853() + fun_l17_n435 +end + +def fun_l16_n854() + fun_l17_n397 +end + +def fun_l16_n855() + fun_l17_n656 +end + +def fun_l16_n856() + fun_l17_n72 +end + +def fun_l16_n857() + fun_l17_n531 +end + +def fun_l16_n858() + fun_l17_n790 +end + +def fun_l16_n859() + fun_l17_n25 +end + +def fun_l16_n860() + fun_l17_n926 +end + +def fun_l16_n861() + fun_l17_n474 +end + +def fun_l16_n862() + fun_l17_n888 +end + +def fun_l16_n863() + fun_l17_n110 +end + +def fun_l16_n864() + fun_l17_n561 +end + +def fun_l16_n865() + fun_l17_n59 +end + +def fun_l16_n866() + fun_l17_n611 +end + +def fun_l16_n867() + fun_l17_n436 +end + +def fun_l16_n868() + fun_l17_n851 +end + +def fun_l16_n869() + fun_l17_n714 +end + +def fun_l16_n870() + fun_l17_n423 +end + +def fun_l16_n871() + fun_l17_n884 +end + +def fun_l16_n872() + fun_l17_n230 +end + +def fun_l16_n873() + fun_l17_n988 +end + +def fun_l16_n874() + fun_l17_n763 +end + +def fun_l16_n875() + fun_l17_n929 +end + +def fun_l16_n876() + fun_l17_n521 +end + +def fun_l16_n877() + fun_l17_n262 +end + +def fun_l16_n878() + fun_l17_n774 +end + +def fun_l16_n879() + fun_l17_n358 +end + +def fun_l16_n880() + fun_l17_n861 +end + +def fun_l16_n881() + fun_l17_n984 +end + +def fun_l16_n882() + fun_l17_n272 +end + +def fun_l16_n883() + fun_l17_n293 +end + +def fun_l16_n884() + fun_l17_n525 +end + +def fun_l16_n885() + fun_l17_n226 +end + +def fun_l16_n886() + fun_l17_n941 +end + +def fun_l16_n887() + fun_l17_n671 +end + +def fun_l16_n888() + fun_l17_n960 +end + +def fun_l16_n889() + fun_l17_n218 +end + +def fun_l16_n890() + fun_l17_n475 +end + +def fun_l16_n891() + fun_l17_n300 +end + +def fun_l16_n892() + fun_l17_n908 +end + +def fun_l16_n893() + fun_l17_n739 +end + +def fun_l16_n894() + fun_l17_n878 +end + +def fun_l16_n895() + fun_l17_n906 +end + +def fun_l16_n896() + fun_l17_n944 +end + +def fun_l16_n897() + fun_l17_n302 +end + +def fun_l16_n898() + fun_l17_n486 +end + +def fun_l16_n899() + fun_l17_n135 +end + +def fun_l16_n900() + fun_l17_n470 +end + +def fun_l16_n901() + fun_l17_n895 +end + +def fun_l16_n902() + fun_l17_n333 +end + +def fun_l16_n903() + fun_l17_n310 +end + +def fun_l16_n904() + fun_l17_n229 +end + +def fun_l16_n905() + fun_l17_n315 +end + +def fun_l16_n906() + fun_l17_n333 +end + +def fun_l16_n907() + fun_l17_n563 +end + +def fun_l16_n908() + fun_l17_n558 +end + +def fun_l16_n909() + fun_l17_n580 +end + +def fun_l16_n910() + fun_l17_n916 +end + +def fun_l16_n911() + fun_l17_n378 +end + +def fun_l16_n912() + fun_l17_n882 +end + +def fun_l16_n913() + fun_l17_n28 +end + +def fun_l16_n914() + fun_l17_n767 +end + +def fun_l16_n915() + fun_l17_n105 +end + +def fun_l16_n916() + fun_l17_n463 +end + +def fun_l16_n917() + fun_l17_n92 +end + +def fun_l16_n918() + fun_l17_n722 +end + +def fun_l16_n919() + fun_l17_n403 +end + +def fun_l16_n920() + fun_l17_n771 +end + +def fun_l16_n921() + fun_l17_n818 +end + +def fun_l16_n922() + fun_l17_n214 +end + +def fun_l16_n923() + fun_l17_n167 +end + +def fun_l16_n924() + fun_l17_n189 +end + +def fun_l16_n925() + fun_l17_n401 +end + +def fun_l16_n926() + fun_l17_n377 +end + +def fun_l16_n927() + fun_l17_n980 +end + +def fun_l16_n928() + fun_l17_n476 +end + +def fun_l16_n929() + fun_l17_n321 +end + +def fun_l16_n930() + fun_l17_n485 +end + +def fun_l16_n931() + fun_l17_n902 +end + +def fun_l16_n932() + fun_l17_n269 +end + +def fun_l16_n933() + fun_l17_n806 +end + +def fun_l16_n934() + fun_l17_n952 +end + +def fun_l16_n935() + fun_l17_n401 +end + +def fun_l16_n936() + fun_l17_n416 +end + +def fun_l16_n937() + fun_l17_n739 +end + +def fun_l16_n938() + fun_l17_n47 +end + +def fun_l16_n939() + fun_l17_n556 +end + +def fun_l16_n940() + fun_l17_n426 +end + +def fun_l16_n941() + fun_l17_n474 +end + +def fun_l16_n942() + fun_l17_n393 +end + +def fun_l16_n943() + fun_l17_n492 +end + +def fun_l16_n944() + fun_l17_n528 +end + +def fun_l16_n945() + fun_l17_n66 +end + +def fun_l16_n946() + fun_l17_n587 +end + +def fun_l16_n947() + fun_l17_n116 +end + +def fun_l16_n948() + fun_l17_n205 +end + +def fun_l16_n949() + fun_l17_n958 +end + +def fun_l16_n950() + fun_l17_n264 +end + +def fun_l16_n951() + fun_l17_n78 +end + +def fun_l16_n952() + fun_l17_n990 +end + +def fun_l16_n953() + fun_l17_n154 +end + +def fun_l16_n954() + fun_l17_n213 +end + +def fun_l16_n955() + fun_l17_n979 +end + +def fun_l16_n956() + fun_l17_n632 +end + +def fun_l16_n957() + fun_l17_n292 +end + +def fun_l16_n958() + fun_l17_n719 +end + +def fun_l16_n959() + fun_l17_n320 +end + +def fun_l16_n960() + fun_l17_n448 +end + +def fun_l16_n961() + fun_l17_n532 +end + +def fun_l16_n962() + fun_l17_n662 +end + +def fun_l16_n963() + fun_l17_n423 +end + +def fun_l16_n964() + fun_l17_n193 +end + +def fun_l16_n965() + fun_l17_n475 +end + +def fun_l16_n966() + fun_l17_n168 +end + +def fun_l16_n967() + fun_l17_n92 +end + +def fun_l16_n968() + fun_l17_n925 +end + +def fun_l16_n969() + fun_l17_n138 +end + +def fun_l16_n970() + fun_l17_n673 +end + +def fun_l16_n971() + fun_l17_n697 +end + +def fun_l16_n972() + fun_l17_n438 +end + +def fun_l16_n973() + fun_l17_n114 +end + +def fun_l16_n974() + fun_l17_n40 +end + +def fun_l16_n975() + fun_l17_n344 +end + +def fun_l16_n976() + fun_l17_n568 +end + +def fun_l16_n977() + fun_l17_n350 +end + +def fun_l16_n978() + fun_l17_n873 +end + +def fun_l16_n979() + fun_l17_n719 +end + +def fun_l16_n980() + fun_l17_n631 +end + +def fun_l16_n981() + fun_l17_n848 +end + +def fun_l16_n982() + fun_l17_n912 +end + +def fun_l16_n983() + fun_l17_n872 +end + +def fun_l16_n984() + fun_l17_n290 +end + +def fun_l16_n985() + fun_l17_n416 +end + +def fun_l16_n986() + fun_l17_n552 +end + +def fun_l16_n987() + fun_l17_n458 +end + +def fun_l16_n988() + fun_l17_n808 +end + +def fun_l16_n989() + fun_l17_n953 +end + +def fun_l16_n990() + fun_l17_n136 +end + +def fun_l16_n991() + fun_l17_n798 +end + +def fun_l16_n992() + fun_l17_n419 +end + +def fun_l16_n993() + fun_l17_n293 +end + +def fun_l16_n994() + fun_l17_n663 +end + +def fun_l16_n995() + fun_l17_n533 +end + +def fun_l16_n996() + fun_l17_n625 +end + +def fun_l16_n997() + fun_l17_n215 +end + +def fun_l16_n998() + fun_l17_n954 +end + +def fun_l16_n999() + fun_l17_n797 +end + +def fun_l17_n0() + fun_l18_n287 +end + +def fun_l17_n1() + fun_l18_n242 +end + +def fun_l17_n2() + fun_l18_n595 +end + +def fun_l17_n3() + fun_l18_n801 +end + +def fun_l17_n4() + fun_l18_n367 +end + +def fun_l17_n5() + fun_l18_n21 +end + +def fun_l17_n6() + fun_l18_n439 +end + +def fun_l17_n7() + fun_l18_n96 +end + +def fun_l17_n8() + fun_l18_n500 +end + +def fun_l17_n9() + fun_l18_n332 +end + +def fun_l17_n10() + fun_l18_n374 +end + +def fun_l17_n11() + fun_l18_n338 +end + +def fun_l17_n12() + fun_l18_n737 +end + +def fun_l17_n13() + fun_l18_n437 +end + +def fun_l17_n14() + fun_l18_n442 +end + +def fun_l17_n15() + fun_l18_n309 +end + +def fun_l17_n16() + fun_l18_n173 +end + +def fun_l17_n17() + fun_l18_n615 +end + +def fun_l17_n18() + fun_l18_n881 +end + +def fun_l17_n19() + fun_l18_n629 +end + +def fun_l17_n20() + fun_l18_n304 +end + +def fun_l17_n21() + fun_l18_n788 +end + +def fun_l17_n22() + fun_l18_n425 +end + +def fun_l17_n23() + fun_l18_n376 +end + +def fun_l17_n24() + fun_l18_n353 +end + +def fun_l17_n25() + fun_l18_n273 +end + +def fun_l17_n26() + fun_l18_n337 +end + +def fun_l17_n27() + fun_l18_n588 +end + +def fun_l17_n28() + fun_l18_n64 +end + +def fun_l17_n29() + fun_l18_n651 +end + +def fun_l17_n30() + fun_l18_n91 +end + +def fun_l17_n31() + fun_l18_n392 +end + +def fun_l17_n32() + fun_l18_n65 +end + +def fun_l17_n33() + fun_l18_n166 +end + +def fun_l17_n34() + fun_l18_n917 +end + +def fun_l17_n35() + fun_l18_n217 +end + +def fun_l17_n36() + fun_l18_n416 +end + +def fun_l17_n37() + fun_l18_n977 +end + +def fun_l17_n38() + fun_l18_n76 +end + +def fun_l17_n39() + fun_l18_n322 +end + +def fun_l17_n40() + fun_l18_n253 +end + +def fun_l17_n41() + fun_l18_n192 +end + +def fun_l17_n42() + fun_l18_n883 +end + +def fun_l17_n43() + fun_l18_n132 +end + +def fun_l17_n44() + fun_l18_n480 +end + +def fun_l17_n45() + fun_l18_n36 +end + +def fun_l17_n46() + fun_l18_n142 +end + +def fun_l17_n47() + fun_l18_n172 +end + +def fun_l17_n48() + fun_l18_n339 +end + +def fun_l17_n49() + fun_l18_n664 +end + +def fun_l17_n50() + fun_l18_n482 +end + +def fun_l17_n51() + fun_l18_n809 +end + +def fun_l17_n52() + fun_l18_n525 +end + +def fun_l17_n53() + fun_l18_n50 +end + +def fun_l17_n54() + fun_l18_n977 +end + +def fun_l17_n55() + fun_l18_n730 +end + +def fun_l17_n56() + fun_l18_n565 +end + +def fun_l17_n57() + fun_l18_n997 +end + +def fun_l17_n58() + fun_l18_n811 +end + +def fun_l17_n59() + fun_l18_n898 +end + +def fun_l17_n60() + fun_l18_n627 +end + +def fun_l17_n61() + fun_l18_n539 +end + +def fun_l17_n62() + fun_l18_n877 +end + +def fun_l17_n63() + fun_l18_n428 +end + +def fun_l17_n64() + fun_l18_n779 +end + +def fun_l17_n65() + fun_l18_n14 +end + +def fun_l17_n66() + fun_l18_n202 +end + +def fun_l17_n67() + fun_l18_n23 +end + +def fun_l17_n68() + fun_l18_n861 +end + +def fun_l17_n69() + fun_l18_n356 +end + +def fun_l17_n70() + fun_l18_n997 +end + +def fun_l17_n71() + fun_l18_n130 +end + +def fun_l17_n72() + fun_l18_n462 +end + +def fun_l17_n73() + fun_l18_n590 +end + +def fun_l17_n74() + fun_l18_n544 +end + +def fun_l17_n75() + fun_l18_n571 +end + +def fun_l17_n76() + fun_l18_n336 +end + +def fun_l17_n77() + fun_l18_n154 +end + +def fun_l17_n78() + fun_l18_n18 +end + +def fun_l17_n79() + fun_l18_n911 +end + +def fun_l17_n80() + fun_l18_n980 +end + +def fun_l17_n81() + fun_l18_n156 +end + +def fun_l17_n82() + fun_l18_n487 +end + +def fun_l17_n83() + fun_l18_n292 +end + +def fun_l17_n84() + fun_l18_n709 +end + +def fun_l17_n85() + fun_l18_n557 +end + +def fun_l17_n86() + fun_l18_n910 +end + +def fun_l17_n87() + fun_l18_n121 +end + +def fun_l17_n88() + fun_l18_n706 +end + +def fun_l17_n89() + fun_l18_n949 +end + +def fun_l17_n90() + fun_l18_n529 +end + +def fun_l17_n91() + fun_l18_n778 +end + +def fun_l17_n92() + fun_l18_n682 +end + +def fun_l17_n93() + fun_l18_n743 +end + +def fun_l17_n94() + fun_l18_n714 +end + +def fun_l17_n95() + fun_l18_n749 +end + +def fun_l17_n96() + fun_l18_n453 +end + +def fun_l17_n97() + fun_l18_n248 +end + +def fun_l17_n98() + fun_l18_n315 +end + +def fun_l17_n99() + fun_l18_n534 +end + +def fun_l17_n100() + fun_l18_n391 +end + +def fun_l17_n101() + fun_l18_n515 +end + +def fun_l17_n102() + fun_l18_n495 +end + +def fun_l17_n103() + fun_l18_n776 +end + +def fun_l17_n104() + fun_l18_n957 +end + +def fun_l17_n105() + fun_l18_n982 +end + +def fun_l17_n106() + fun_l18_n401 +end + +def fun_l17_n107() + fun_l18_n230 +end + +def fun_l17_n108() + fun_l18_n13 +end + +def fun_l17_n109() + fun_l18_n318 +end + +def fun_l17_n110() + fun_l18_n275 +end + +def fun_l17_n111() + fun_l18_n155 +end + +def fun_l17_n112() + fun_l18_n86 +end + +def fun_l17_n113() + fun_l18_n573 +end + +def fun_l17_n114() + fun_l18_n124 +end + +def fun_l17_n115() + fun_l18_n694 +end + +def fun_l17_n116() + fun_l18_n929 +end + +def fun_l17_n117() + fun_l18_n177 +end + +def fun_l17_n118() + fun_l18_n510 +end + +def fun_l17_n119() + fun_l18_n143 +end + +def fun_l17_n120() + fun_l18_n358 +end + +def fun_l17_n121() + fun_l18_n739 +end + +def fun_l17_n122() + fun_l18_n463 +end + +def fun_l17_n123() + fun_l18_n343 +end + +def fun_l17_n124() + fun_l18_n714 +end + +def fun_l17_n125() + fun_l18_n53 +end + +def fun_l17_n126() + fun_l18_n375 +end + +def fun_l17_n127() + fun_l18_n870 +end + +def fun_l17_n128() + fun_l18_n555 +end + +def fun_l17_n129() + fun_l18_n773 +end + +def fun_l17_n130() + fun_l18_n309 +end + +def fun_l17_n131() + fun_l18_n50 +end + +def fun_l17_n132() + fun_l18_n408 +end + +def fun_l17_n133() + fun_l18_n339 +end + +def fun_l17_n134() + fun_l18_n952 +end + +def fun_l17_n135() + fun_l18_n599 +end + +def fun_l17_n136() + fun_l18_n280 +end + +def fun_l17_n137() + fun_l18_n922 +end + +def fun_l17_n138() + fun_l18_n132 +end + +def fun_l17_n139() + fun_l18_n224 +end + +def fun_l17_n140() + fun_l18_n841 +end + +def fun_l17_n141() + fun_l18_n84 +end + +def fun_l17_n142() + fun_l18_n697 +end + +def fun_l17_n143() + fun_l18_n60 +end + +def fun_l17_n144() + fun_l18_n479 +end + +def fun_l17_n145() + fun_l18_n671 +end + +def fun_l17_n146() + fun_l18_n422 +end + +def fun_l17_n147() + fun_l18_n255 +end + +def fun_l17_n148() + fun_l18_n615 +end + +def fun_l17_n149() + fun_l18_n878 +end + +def fun_l17_n150() + fun_l18_n402 +end + +def fun_l17_n151() + fun_l18_n134 +end + +def fun_l17_n152() + fun_l18_n493 +end + +def fun_l17_n153() + fun_l18_n347 +end + +def fun_l17_n154() + fun_l18_n679 +end + +def fun_l17_n155() + fun_l18_n477 +end + +def fun_l17_n156() + fun_l18_n56 +end + +def fun_l17_n157() + fun_l18_n43 +end + +def fun_l17_n158() + fun_l18_n928 +end + +def fun_l17_n159() + fun_l18_n190 +end + +def fun_l17_n160() + fun_l18_n402 +end + +def fun_l17_n161() + fun_l18_n894 +end + +def fun_l17_n162() + fun_l18_n869 +end + +def fun_l17_n163() + fun_l18_n36 +end + +def fun_l17_n164() + fun_l18_n635 +end + +def fun_l17_n165() + fun_l18_n414 +end + +def fun_l17_n166() + fun_l18_n744 +end + +def fun_l17_n167() + fun_l18_n87 +end + +def fun_l17_n168() + fun_l18_n531 +end + +def fun_l17_n169() + fun_l18_n923 +end + +def fun_l17_n170() + fun_l18_n815 +end + +def fun_l17_n171() + fun_l18_n27 +end + +def fun_l17_n172() + fun_l18_n194 +end + +def fun_l17_n173() + fun_l18_n456 +end + +def fun_l17_n174() + fun_l18_n275 +end + +def fun_l17_n175() + fun_l18_n48 +end + +def fun_l17_n176() + fun_l18_n230 +end + +def fun_l17_n177() + fun_l18_n806 +end + +def fun_l17_n178() + fun_l18_n851 +end + +def fun_l17_n179() + fun_l18_n76 +end + +def fun_l17_n180() + fun_l18_n925 +end + +def fun_l17_n181() + fun_l18_n680 +end + +def fun_l17_n182() + fun_l18_n547 +end + +def fun_l17_n183() + fun_l18_n439 +end + +def fun_l17_n184() + fun_l18_n642 +end + +def fun_l17_n185() + fun_l18_n249 +end + +def fun_l17_n186() + fun_l18_n92 +end + +def fun_l17_n187() + fun_l18_n727 +end + +def fun_l17_n188() + fun_l18_n358 +end + +def fun_l17_n189() + fun_l18_n874 +end + +def fun_l17_n190() + fun_l18_n357 +end + +def fun_l17_n191() + fun_l18_n773 +end + +def fun_l17_n192() + fun_l18_n487 +end + +def fun_l17_n193() + fun_l18_n985 +end + +def fun_l17_n194() + fun_l18_n771 +end + +def fun_l17_n195() + fun_l18_n918 +end + +def fun_l17_n196() + fun_l18_n768 +end + +def fun_l17_n197() + fun_l18_n275 +end + +def fun_l17_n198() + fun_l18_n72 +end + +def fun_l17_n199() + fun_l18_n288 +end + +def fun_l17_n200() + fun_l18_n187 +end + +def fun_l17_n201() + fun_l18_n905 +end + +def fun_l17_n202() + fun_l18_n61 +end + +def fun_l17_n203() + fun_l18_n845 +end + +def fun_l17_n204() + fun_l18_n390 +end + +def fun_l17_n205() + fun_l18_n501 +end + +def fun_l17_n206() + fun_l18_n820 +end + +def fun_l17_n207() + fun_l18_n889 +end + +def fun_l17_n208() + fun_l18_n746 +end + +def fun_l17_n209() + fun_l18_n640 +end + +def fun_l17_n210() + fun_l18_n974 +end + +def fun_l17_n211() + fun_l18_n128 +end + +def fun_l17_n212() + fun_l18_n227 +end + +def fun_l17_n213() + fun_l18_n646 +end + +def fun_l17_n214() + fun_l18_n55 +end + +def fun_l17_n215() + fun_l18_n989 +end + +def fun_l17_n216() + fun_l18_n417 +end + +def fun_l17_n217() + fun_l18_n85 +end + +def fun_l17_n218() + fun_l18_n477 +end + +def fun_l17_n219() + fun_l18_n442 +end + +def fun_l17_n220() + fun_l18_n804 +end + +def fun_l17_n221() + fun_l18_n135 +end + +def fun_l17_n222() + fun_l18_n347 +end + +def fun_l17_n223() + fun_l18_n34 +end + +def fun_l17_n224() + fun_l18_n534 +end + +def fun_l17_n225() + fun_l18_n789 +end + +def fun_l17_n226() + fun_l18_n938 +end + +def fun_l17_n227() + fun_l18_n777 +end + +def fun_l17_n228() + fun_l18_n247 +end + +def fun_l17_n229() + fun_l18_n935 +end + +def fun_l17_n230() + fun_l18_n406 +end + +def fun_l17_n231() + fun_l18_n0 +end + +def fun_l17_n232() + fun_l18_n530 +end + +def fun_l17_n233() + fun_l18_n994 +end + +def fun_l17_n234() + fun_l18_n818 +end + +def fun_l17_n235() + fun_l18_n941 +end + +def fun_l17_n236() + fun_l18_n687 +end + +def fun_l17_n237() + fun_l18_n372 +end + +def fun_l17_n238() + fun_l18_n344 +end + +def fun_l17_n239() + fun_l18_n336 +end + +def fun_l17_n240() + fun_l18_n870 +end + +def fun_l17_n241() + fun_l18_n694 +end + +def fun_l17_n242() + fun_l18_n233 +end + +def fun_l17_n243() + fun_l18_n301 +end + +def fun_l17_n244() + fun_l18_n425 +end + +def fun_l17_n245() + fun_l18_n334 +end + +def fun_l17_n246() + fun_l18_n848 +end + +def fun_l17_n247() + fun_l18_n27 +end + +def fun_l17_n248() + fun_l18_n964 +end + +def fun_l17_n249() + fun_l18_n953 +end + +def fun_l17_n250() + fun_l18_n4 +end + +def fun_l17_n251() + fun_l18_n504 +end + +def fun_l17_n252() + fun_l18_n165 +end + +def fun_l17_n253() + fun_l18_n401 +end + +def fun_l17_n254() + fun_l18_n267 +end + +def fun_l17_n255() + fun_l18_n966 +end + +def fun_l17_n256() + fun_l18_n854 +end + +def fun_l17_n257() + fun_l18_n927 +end + +def fun_l17_n258() + fun_l18_n476 +end + +def fun_l17_n259() + fun_l18_n274 +end + +def fun_l17_n260() + fun_l18_n711 +end + +def fun_l17_n261() + fun_l18_n96 +end + +def fun_l17_n262() + fun_l18_n901 +end + +def fun_l17_n263() + fun_l18_n601 +end + +def fun_l17_n264() + fun_l18_n495 +end + +def fun_l17_n265() + fun_l18_n672 +end + +def fun_l17_n266() + fun_l18_n946 +end + +def fun_l17_n267() + fun_l18_n91 +end + +def fun_l17_n268() + fun_l18_n547 +end + +def fun_l17_n269() + fun_l18_n977 +end + +def fun_l17_n270() + fun_l18_n113 +end + +def fun_l17_n271() + fun_l18_n818 +end + +def fun_l17_n272() + fun_l18_n370 +end + +def fun_l17_n273() + fun_l18_n940 +end + +def fun_l17_n274() + fun_l18_n892 +end + +def fun_l17_n275() + fun_l18_n501 +end + +def fun_l17_n276() + fun_l18_n252 +end + +def fun_l17_n277() + fun_l18_n720 +end + +def fun_l17_n278() + fun_l18_n12 +end + +def fun_l17_n279() + fun_l18_n318 +end + +def fun_l17_n280() + fun_l18_n536 +end + +def fun_l17_n281() + fun_l18_n344 +end + +def fun_l17_n282() + fun_l18_n613 +end + +def fun_l17_n283() + fun_l18_n198 +end + +def fun_l17_n284() + fun_l18_n153 +end + +def fun_l17_n285() + fun_l18_n118 +end + +def fun_l17_n286() + fun_l18_n694 +end + +def fun_l17_n287() + fun_l18_n402 +end + +def fun_l17_n288() + fun_l18_n609 +end + +def fun_l17_n289() + fun_l18_n334 +end + +def fun_l17_n290() + fun_l18_n266 +end + +def fun_l17_n291() + fun_l18_n235 +end + +def fun_l17_n292() + fun_l18_n942 +end + +def fun_l17_n293() + fun_l18_n165 +end + +def fun_l17_n294() + fun_l18_n443 +end + +def fun_l17_n295() + fun_l18_n837 +end + +def fun_l17_n296() + fun_l18_n329 +end + +def fun_l17_n297() + fun_l18_n64 +end + +def fun_l17_n298() + fun_l18_n469 +end + +def fun_l17_n299() + fun_l18_n557 +end + +def fun_l17_n300() + fun_l18_n158 +end + +def fun_l17_n301() + fun_l18_n250 +end + +def fun_l17_n302() + fun_l18_n733 +end + +def fun_l17_n303() + fun_l18_n491 +end + +def fun_l17_n304() + fun_l18_n966 +end + +def fun_l17_n305() + fun_l18_n210 +end + +def fun_l17_n306() + fun_l18_n118 +end + +def fun_l17_n307() + fun_l18_n394 +end + +def fun_l17_n308() + fun_l18_n421 +end + +def fun_l17_n309() + fun_l18_n559 +end + +def fun_l17_n310() + fun_l18_n386 +end + +def fun_l17_n311() + fun_l18_n350 +end + +def fun_l17_n312() + fun_l18_n527 +end + +def fun_l17_n313() + fun_l18_n539 +end + +def fun_l17_n314() + fun_l18_n468 +end + +def fun_l17_n315() + fun_l18_n533 +end + +def fun_l17_n316() + fun_l18_n607 +end + +def fun_l17_n317() + fun_l18_n410 +end + +def fun_l17_n318() + fun_l18_n391 +end + +def fun_l17_n319() + fun_l18_n709 +end + +def fun_l17_n320() + fun_l18_n131 +end + +def fun_l17_n321() + fun_l18_n401 +end + +def fun_l17_n322() + fun_l18_n249 +end + +def fun_l17_n323() + fun_l18_n459 +end + +def fun_l17_n324() + fun_l18_n111 +end + +def fun_l17_n325() + fun_l18_n539 +end + +def fun_l17_n326() + fun_l18_n493 +end + +def fun_l17_n327() + fun_l18_n415 +end + +def fun_l17_n328() + fun_l18_n334 +end + +def fun_l17_n329() + fun_l18_n784 +end + +def fun_l17_n330() + fun_l18_n45 +end + +def fun_l17_n331() + fun_l18_n820 +end + +def fun_l17_n332() + fun_l18_n892 +end + +def fun_l17_n333() + fun_l18_n598 +end + +def fun_l17_n334() + fun_l18_n800 +end + +def fun_l17_n335() + fun_l18_n384 +end + +def fun_l17_n336() + fun_l18_n364 +end + +def fun_l17_n337() + fun_l18_n857 +end + +def fun_l17_n338() + fun_l18_n617 +end + +def fun_l17_n339() + fun_l18_n669 +end + +def fun_l17_n340() + fun_l18_n332 +end + +def fun_l17_n341() + fun_l18_n104 +end + +def fun_l17_n342() + fun_l18_n716 +end + +def fun_l17_n343() + fun_l18_n836 +end + +def fun_l17_n344() + fun_l18_n31 +end + +def fun_l17_n345() + fun_l18_n345 +end + +def fun_l17_n346() + fun_l18_n988 +end + +def fun_l17_n347() + fun_l18_n63 +end + +def fun_l17_n348() + fun_l18_n637 +end + +def fun_l17_n349() + fun_l18_n767 +end + +def fun_l17_n350() + fun_l18_n45 +end + +def fun_l17_n351() + fun_l18_n332 +end + +def fun_l17_n352() + fun_l18_n622 +end + +def fun_l17_n353() + fun_l18_n879 +end + +def fun_l17_n354() + fun_l18_n499 +end + +def fun_l17_n355() + fun_l18_n446 +end + +def fun_l17_n356() + fun_l18_n355 +end + +def fun_l17_n357() + fun_l18_n40 +end + +def fun_l17_n358() + fun_l18_n602 +end + +def fun_l17_n359() + fun_l18_n162 +end + +def fun_l17_n360() + fun_l18_n415 +end + +def fun_l17_n361() + fun_l18_n966 +end + +def fun_l17_n362() + fun_l18_n801 +end + +def fun_l17_n363() + fun_l18_n242 +end + +def fun_l17_n364() + fun_l18_n563 +end + +def fun_l17_n365() + fun_l18_n150 +end + +def fun_l17_n366() + fun_l18_n667 +end + +def fun_l17_n367() + fun_l18_n997 +end + +def fun_l17_n368() + fun_l18_n550 +end + +def fun_l17_n369() + fun_l18_n313 +end + +def fun_l17_n370() + fun_l18_n434 +end + +def fun_l17_n371() + fun_l18_n254 +end + +def fun_l17_n372() + fun_l18_n138 +end + +def fun_l17_n373() + fun_l18_n371 +end + +def fun_l17_n374() + fun_l18_n135 +end + +def fun_l17_n375() + fun_l18_n405 +end + +def fun_l17_n376() + fun_l18_n501 +end + +def fun_l17_n377() + fun_l18_n565 +end + +def fun_l17_n378() + fun_l18_n769 +end + +def fun_l17_n379() + fun_l18_n20 +end + +def fun_l17_n380() + fun_l18_n917 +end + +def fun_l17_n381() + fun_l18_n983 +end + +def fun_l17_n382() + fun_l18_n783 +end + +def fun_l17_n383() + fun_l18_n849 +end + +def fun_l17_n384() + fun_l18_n21 +end + +def fun_l17_n385() + fun_l18_n806 +end + +def fun_l17_n386() + fun_l18_n440 +end + +def fun_l17_n387() + fun_l18_n810 +end + +def fun_l17_n388() + fun_l18_n744 +end + +def fun_l17_n389() + fun_l18_n184 +end + +def fun_l17_n390() + fun_l18_n775 +end + +def fun_l17_n391() + fun_l18_n704 +end + +def fun_l17_n392() + fun_l18_n413 +end + +def fun_l17_n393() + fun_l18_n329 +end + +def fun_l17_n394() + fun_l18_n874 +end + +def fun_l17_n395() + fun_l18_n756 +end + +def fun_l17_n396() + fun_l18_n502 +end + +def fun_l17_n397() + fun_l18_n675 +end + +def fun_l17_n398() + fun_l18_n504 +end + +def fun_l17_n399() + fun_l18_n117 +end + +def fun_l17_n400() + fun_l18_n203 +end + +def fun_l17_n401() + fun_l18_n672 +end + +def fun_l17_n402() + fun_l18_n971 +end + +def fun_l17_n403() + fun_l18_n742 +end + +def fun_l17_n404() + fun_l18_n817 +end + +def fun_l17_n405() + fun_l18_n981 +end + +def fun_l17_n406() + fun_l18_n791 +end + +def fun_l17_n407() + fun_l18_n660 +end + +def fun_l17_n408() + fun_l18_n988 +end + +def fun_l17_n409() + fun_l18_n875 +end + +def fun_l17_n410() + fun_l18_n469 +end + +def fun_l17_n411() + fun_l18_n890 +end + +def fun_l17_n412() + fun_l18_n739 +end + +def fun_l17_n413() + fun_l18_n880 +end + +def fun_l17_n414() + fun_l18_n47 +end + +def fun_l17_n415() + fun_l18_n474 +end + +def fun_l17_n416() + fun_l18_n923 +end + +def fun_l17_n417() + fun_l18_n959 +end + +def fun_l17_n418() + fun_l18_n748 +end + +def fun_l17_n419() + fun_l18_n555 +end + +def fun_l17_n420() + fun_l18_n785 +end + +def fun_l17_n421() + fun_l18_n49 +end + +def fun_l17_n422() + fun_l18_n509 +end + +def fun_l17_n423() + fun_l18_n0 +end + +def fun_l17_n424() + fun_l18_n388 +end + +def fun_l17_n425() + fun_l18_n394 +end + +def fun_l17_n426() + fun_l18_n199 +end + +def fun_l17_n427() + fun_l18_n554 +end + +def fun_l17_n428() + fun_l18_n963 +end + +def fun_l17_n429() + fun_l18_n464 +end + +def fun_l17_n430() + fun_l18_n941 +end + +def fun_l17_n431() + fun_l18_n116 +end + +def fun_l17_n432() + fun_l18_n370 +end + +def fun_l17_n433() + fun_l18_n848 +end + +def fun_l17_n434() + fun_l18_n123 +end + +def fun_l17_n435() + fun_l18_n32 +end + +def fun_l17_n436() + fun_l18_n285 +end + +def fun_l17_n437() + fun_l18_n823 +end + +def fun_l17_n438() + fun_l18_n517 +end + +def fun_l17_n439() + fun_l18_n292 +end + +def fun_l17_n440() + fun_l18_n29 +end + +def fun_l17_n441() + fun_l18_n166 +end + +def fun_l17_n442() + fun_l18_n282 +end + +def fun_l17_n443() + fun_l18_n300 +end + +def fun_l17_n444() + fun_l18_n8 +end + +def fun_l17_n445() + fun_l18_n458 +end + +def fun_l17_n446() + fun_l18_n797 +end + +def fun_l17_n447() + fun_l18_n835 +end + +def fun_l17_n448() + fun_l18_n535 +end + +def fun_l17_n449() + fun_l18_n909 +end + +def fun_l17_n450() + fun_l18_n890 +end + +def fun_l17_n451() + fun_l18_n706 +end + +def fun_l17_n452() + fun_l18_n636 +end + +def fun_l17_n453() + fun_l18_n541 +end + +def fun_l17_n454() + fun_l18_n332 +end + +def fun_l17_n455() + fun_l18_n241 +end + +def fun_l17_n456() + fun_l18_n334 +end + +def fun_l17_n457() + fun_l18_n212 +end + +def fun_l17_n458() + fun_l18_n414 +end + +def fun_l17_n459() + fun_l18_n600 +end + +def fun_l17_n460() + fun_l18_n237 +end + +def fun_l17_n461() + fun_l18_n881 +end + +def fun_l17_n462() + fun_l18_n539 +end + +def fun_l17_n463() + fun_l18_n262 +end + +def fun_l17_n464() + fun_l18_n437 +end + +def fun_l17_n465() + fun_l18_n874 +end + +def fun_l17_n466() + fun_l18_n418 +end + +def fun_l17_n467() + fun_l18_n963 +end + +def fun_l17_n468() + fun_l18_n340 +end + +def fun_l17_n469() + fun_l18_n708 +end + +def fun_l17_n470() + fun_l18_n725 +end + +def fun_l17_n471() + fun_l18_n59 +end + +def fun_l17_n472() + fun_l18_n309 +end + +def fun_l17_n473() + fun_l18_n490 +end + +def fun_l17_n474() + fun_l18_n588 +end + +def fun_l17_n475() + fun_l18_n623 +end + +def fun_l17_n476() + fun_l18_n127 +end + +def fun_l17_n477() + fun_l18_n385 +end + +def fun_l17_n478() + fun_l18_n381 +end + +def fun_l17_n479() + fun_l18_n603 +end + +def fun_l17_n480() + fun_l18_n524 +end + +def fun_l17_n481() + fun_l18_n829 +end + +def fun_l17_n482() + fun_l18_n675 +end + +def fun_l17_n483() + fun_l18_n792 +end + +def fun_l17_n484() + fun_l18_n438 +end + +def fun_l17_n485() + fun_l18_n101 +end + +def fun_l17_n486() + fun_l18_n513 +end + +def fun_l17_n487() + fun_l18_n44 +end + +def fun_l17_n488() + fun_l18_n975 +end + +def fun_l17_n489() + fun_l18_n891 +end + +def fun_l17_n490() + fun_l18_n650 +end + +def fun_l17_n491() + fun_l18_n840 +end + +def fun_l17_n492() + fun_l18_n954 +end + +def fun_l17_n493() + fun_l18_n326 +end + +def fun_l17_n494() + fun_l18_n93 +end + +def fun_l17_n495() + fun_l18_n537 +end + +def fun_l17_n496() + fun_l18_n871 +end + +def fun_l17_n497() + fun_l18_n786 +end + +def fun_l17_n498() + fun_l18_n311 +end + +def fun_l17_n499() + fun_l18_n494 +end + +def fun_l17_n500() + fun_l18_n787 +end + +def fun_l17_n501() + fun_l18_n511 +end + +def fun_l17_n502() + fun_l18_n342 +end + +def fun_l17_n503() + fun_l18_n218 +end + +def fun_l17_n504() + fun_l18_n432 +end + +def fun_l17_n505() + fun_l18_n637 +end + +def fun_l17_n506() + fun_l18_n877 +end + +def fun_l17_n507() + fun_l18_n767 +end + +def fun_l17_n508() + fun_l18_n854 +end + +def fun_l17_n509() + fun_l18_n614 +end + +def fun_l17_n510() + fun_l18_n720 +end + +def fun_l17_n511() + fun_l18_n556 +end + +def fun_l17_n512() + fun_l18_n950 +end + +def fun_l17_n513() + fun_l18_n502 +end + +def fun_l17_n514() + fun_l18_n841 +end + +def fun_l17_n515() + fun_l18_n24 +end + +def fun_l17_n516() + fun_l18_n392 +end + +def fun_l17_n517() + fun_l18_n99 +end + +def fun_l17_n518() + fun_l18_n370 +end + +def fun_l17_n519() + fun_l18_n798 +end + +def fun_l17_n520() + fun_l18_n405 +end + +def fun_l17_n521() + fun_l18_n736 +end + +def fun_l17_n522() + fun_l18_n616 +end + +def fun_l17_n523() + fun_l18_n701 +end + +def fun_l17_n524() + fun_l18_n914 +end + +def fun_l17_n525() + fun_l18_n832 +end + +def fun_l17_n526() + fun_l18_n234 +end + +def fun_l17_n527() + fun_l18_n65 +end + +def fun_l17_n528() + fun_l18_n61 +end + +def fun_l17_n529() + fun_l18_n639 +end + +def fun_l17_n530() + fun_l18_n162 +end + +def fun_l17_n531() + fun_l18_n250 +end + +def fun_l17_n532() + fun_l18_n567 +end + +def fun_l17_n533() + fun_l18_n183 +end + +def fun_l17_n534() + fun_l18_n170 +end + +def fun_l17_n535() + fun_l18_n663 +end + +def fun_l17_n536() + fun_l18_n654 +end + +def fun_l17_n537() + fun_l18_n616 +end + +def fun_l17_n538() + fun_l18_n836 +end + +def fun_l17_n539() + fun_l18_n679 +end + +def fun_l17_n540() + fun_l18_n286 +end + +def fun_l17_n541() + fun_l18_n35 +end + +def fun_l17_n542() + fun_l18_n622 +end + +def fun_l17_n543() + fun_l18_n305 +end + +def fun_l17_n544() + fun_l18_n665 +end + +def fun_l17_n545() + fun_l18_n376 +end + +def fun_l17_n546() + fun_l18_n831 +end + +def fun_l17_n547() + fun_l18_n917 +end + +def fun_l17_n548() + fun_l18_n72 +end + +def fun_l17_n549() + fun_l18_n934 +end + +def fun_l17_n550() + fun_l18_n450 +end + +def fun_l17_n551() + fun_l18_n683 +end + +def fun_l17_n552() + fun_l18_n775 +end + +def fun_l17_n553() + fun_l18_n418 +end + +def fun_l17_n554() + fun_l18_n95 +end + +def fun_l17_n555() + fun_l18_n395 +end + +def fun_l17_n556() + fun_l18_n398 +end + +def fun_l17_n557() + fun_l18_n192 +end + +def fun_l17_n558() + fun_l18_n773 +end + +def fun_l17_n559() + fun_l18_n924 +end + +def fun_l17_n560() + fun_l18_n338 +end + +def fun_l17_n561() + fun_l18_n926 +end + +def fun_l17_n562() + fun_l18_n153 +end + +def fun_l17_n563() + fun_l18_n76 +end + +def fun_l17_n564() + fun_l18_n192 +end + +def fun_l17_n565() + fun_l18_n605 +end + +def fun_l17_n566() + fun_l18_n219 +end + +def fun_l17_n567() + fun_l18_n58 +end + +def fun_l17_n568() + fun_l18_n245 +end + +def fun_l17_n569() + fun_l18_n810 +end + +def fun_l17_n570() + fun_l18_n541 +end + +def fun_l17_n571() + fun_l18_n37 +end + +def fun_l17_n572() + fun_l18_n329 +end + +def fun_l17_n573() + fun_l18_n159 +end + +def fun_l17_n574() + fun_l18_n926 +end + +def fun_l17_n575() + fun_l18_n940 +end + +def fun_l17_n576() + fun_l18_n547 +end + +def fun_l17_n577() + fun_l18_n694 +end + +def fun_l17_n578() + fun_l18_n513 +end + +def fun_l17_n579() + fun_l18_n197 +end + +def fun_l17_n580() + fun_l18_n97 +end + +def fun_l17_n581() + fun_l18_n504 +end + +def fun_l17_n582() + fun_l18_n30 +end + +def fun_l17_n583() + fun_l18_n972 +end + +def fun_l17_n584() + fun_l18_n684 +end + +def fun_l17_n585() + fun_l18_n720 +end + +def fun_l17_n586() + fun_l18_n999 +end + +def fun_l17_n587() + fun_l18_n241 +end + +def fun_l17_n588() + fun_l18_n289 +end + +def fun_l17_n589() + fun_l18_n168 +end + +def fun_l17_n590() + fun_l18_n890 +end + +def fun_l17_n591() + fun_l18_n566 +end + +def fun_l17_n592() + fun_l18_n722 +end + +def fun_l17_n593() + fun_l18_n65 +end + +def fun_l17_n594() + fun_l18_n975 +end + +def fun_l17_n595() + fun_l18_n68 +end + +def fun_l17_n596() + fun_l18_n930 +end + +def fun_l17_n597() + fun_l18_n386 +end + +def fun_l17_n598() + fun_l18_n755 +end + +def fun_l17_n599() + fun_l18_n571 +end + +def fun_l17_n600() + fun_l18_n633 +end + +def fun_l17_n601() + fun_l18_n823 +end + +def fun_l17_n602() + fun_l18_n618 +end + +def fun_l17_n603() + fun_l18_n587 +end + +def fun_l17_n604() + fun_l18_n730 +end + +def fun_l17_n605() + fun_l18_n829 +end + +def fun_l17_n606() + fun_l18_n591 +end + +def fun_l17_n607() + fun_l18_n971 +end + +def fun_l17_n608() + fun_l18_n79 +end + +def fun_l17_n609() + fun_l18_n971 +end + +def fun_l17_n610() + fun_l18_n571 +end + +def fun_l17_n611() + fun_l18_n768 +end + +def fun_l17_n612() + fun_l18_n894 +end + +def fun_l17_n613() + fun_l18_n424 +end + +def fun_l17_n614() + fun_l18_n452 +end + +def fun_l17_n615() + fun_l18_n928 +end + +def fun_l17_n616() + fun_l18_n273 +end + +def fun_l17_n617() + fun_l18_n344 +end + +def fun_l17_n618() + fun_l18_n673 +end + +def fun_l17_n619() + fun_l18_n849 +end + +def fun_l17_n620() + fun_l18_n462 +end + +def fun_l17_n621() + fun_l18_n691 +end + +def fun_l17_n622() + fun_l18_n111 +end + +def fun_l17_n623() + fun_l18_n140 +end + +def fun_l17_n624() + fun_l18_n949 +end + +def fun_l17_n625() + fun_l18_n743 +end + +def fun_l17_n626() + fun_l18_n985 +end + +def fun_l17_n627() + fun_l18_n123 +end + +def fun_l17_n628() + fun_l18_n59 +end + +def fun_l17_n629() + fun_l18_n355 +end + +def fun_l17_n630() + fun_l18_n828 +end + +def fun_l17_n631() + fun_l18_n602 +end + +def fun_l17_n632() + fun_l18_n597 +end + +def fun_l17_n633() + fun_l18_n156 +end + +def fun_l17_n634() + fun_l18_n249 +end + +def fun_l17_n635() + fun_l18_n166 +end + +def fun_l17_n636() + fun_l18_n913 +end + +def fun_l17_n637() + fun_l18_n667 +end + +def fun_l17_n638() + fun_l18_n641 +end + +def fun_l17_n639() + fun_l18_n31 +end + +def fun_l17_n640() + fun_l18_n481 +end + +def fun_l17_n641() + fun_l18_n670 +end + +def fun_l17_n642() + fun_l18_n104 +end + +def fun_l17_n643() + fun_l18_n490 +end + +def fun_l17_n644() + fun_l18_n653 +end + +def fun_l17_n645() + fun_l18_n582 +end + +def fun_l17_n646() + fun_l18_n805 +end + +def fun_l17_n647() + fun_l18_n89 +end + +def fun_l17_n648() + fun_l18_n226 +end + +def fun_l17_n649() + fun_l18_n657 +end + +def fun_l17_n650() + fun_l18_n711 +end + +def fun_l17_n651() + fun_l18_n991 +end + +def fun_l17_n652() + fun_l18_n955 +end + +def fun_l17_n653() + fun_l18_n357 +end + +def fun_l17_n654() + fun_l18_n816 +end + +def fun_l17_n655() + fun_l18_n3 +end + +def fun_l17_n656() + fun_l18_n796 +end + +def fun_l17_n657() + fun_l18_n864 +end + +def fun_l17_n658() + fun_l18_n484 +end + +def fun_l17_n659() + fun_l18_n59 +end + +def fun_l17_n660() + fun_l18_n465 +end + +def fun_l17_n661() + fun_l18_n175 +end + +def fun_l17_n662() + fun_l18_n721 +end + +def fun_l17_n663() + fun_l18_n203 +end + +def fun_l17_n664() + fun_l18_n77 +end + +def fun_l17_n665() + fun_l18_n428 +end + +def fun_l17_n666() + fun_l18_n651 +end + +def fun_l17_n667() + fun_l18_n652 +end + +def fun_l17_n668() + fun_l18_n199 +end + +def fun_l17_n669() + fun_l18_n851 +end + +def fun_l17_n670() + fun_l18_n27 +end + +def fun_l17_n671() + fun_l18_n399 +end + +def fun_l17_n672() + fun_l18_n233 +end + +def fun_l17_n673() + fun_l18_n213 +end + +def fun_l17_n674() + fun_l18_n112 +end + +def fun_l17_n675() + fun_l18_n56 +end + +def fun_l17_n676() + fun_l18_n813 +end + +def fun_l17_n677() + fun_l18_n344 +end + +def fun_l17_n678() + fun_l18_n705 +end + +def fun_l17_n679() + fun_l18_n117 +end + +def fun_l17_n680() + fun_l18_n644 +end + +def fun_l17_n681() + fun_l18_n544 +end + +def fun_l17_n682() + fun_l18_n910 +end + +def fun_l17_n683() + fun_l18_n604 +end + +def fun_l17_n684() + fun_l18_n916 +end + +def fun_l17_n685() + fun_l18_n795 +end + +def fun_l17_n686() + fun_l18_n983 +end + +def fun_l17_n687() + fun_l18_n200 +end + +def fun_l17_n688() + fun_l18_n699 +end + +def fun_l17_n689() + fun_l18_n736 +end + +def fun_l17_n690() + fun_l18_n465 +end + +def fun_l17_n691() + fun_l18_n496 +end + +def fun_l17_n692() + fun_l18_n505 +end + +def fun_l17_n693() + fun_l18_n753 +end + +def fun_l17_n694() + fun_l18_n473 +end + +def fun_l17_n695() + fun_l18_n320 +end + +def fun_l17_n696() + fun_l18_n319 +end + +def fun_l17_n697() + fun_l18_n789 +end + +def fun_l17_n698() + fun_l18_n474 +end + +def fun_l17_n699() + fun_l18_n561 +end + +def fun_l17_n700() + fun_l18_n455 +end + +def fun_l17_n701() + fun_l18_n863 +end + +def fun_l17_n702() + fun_l18_n22 +end + +def fun_l17_n703() + fun_l18_n850 +end + +def fun_l17_n704() + fun_l18_n200 +end + +def fun_l17_n705() + fun_l18_n411 +end + +def fun_l17_n706() + fun_l18_n655 +end + +def fun_l17_n707() + fun_l18_n101 +end + +def fun_l17_n708() + fun_l18_n911 +end + +def fun_l17_n709() + fun_l18_n974 +end + +def fun_l17_n710() + fun_l18_n354 +end + +def fun_l17_n711() + fun_l18_n265 +end + +def fun_l17_n712() + fun_l18_n995 +end + +def fun_l17_n713() + fun_l18_n21 +end + +def fun_l17_n714() + fun_l18_n783 +end + +def fun_l17_n715() + fun_l18_n974 +end + +def fun_l17_n716() + fun_l18_n814 +end + +def fun_l17_n717() + fun_l18_n833 +end + +def fun_l17_n718() + fun_l18_n919 +end + +def fun_l17_n719() + fun_l18_n379 +end + +def fun_l17_n720() + fun_l18_n995 +end + +def fun_l17_n721() + fun_l18_n473 +end + +def fun_l17_n722() + fun_l18_n345 +end + +def fun_l17_n723() + fun_l18_n982 +end + +def fun_l17_n724() + fun_l18_n857 +end + +def fun_l17_n725() + fun_l18_n238 +end + +def fun_l17_n726() + fun_l18_n428 +end + +def fun_l17_n727() + fun_l18_n387 +end + +def fun_l17_n728() + fun_l18_n690 +end + +def fun_l17_n729() + fun_l18_n581 +end + +def fun_l17_n730() + fun_l18_n110 +end + +def fun_l17_n731() + fun_l18_n788 +end + +def fun_l17_n732() + fun_l18_n190 +end + +def fun_l17_n733() + fun_l18_n856 +end + +def fun_l17_n734() + fun_l18_n724 +end + +def fun_l17_n735() + fun_l18_n174 +end + +def fun_l17_n736() + fun_l18_n527 +end + +def fun_l17_n737() + fun_l18_n816 +end + +def fun_l17_n738() + fun_l18_n425 +end + +def fun_l17_n739() + fun_l18_n476 +end + +def fun_l17_n740() + fun_l18_n685 +end + +def fun_l17_n741() + fun_l18_n211 +end + +def fun_l17_n742() + fun_l18_n354 +end + +def fun_l17_n743() + fun_l18_n849 +end + +def fun_l17_n744() + fun_l18_n673 +end + +def fun_l17_n745() + fun_l18_n274 +end + +def fun_l17_n746() + fun_l18_n147 +end + +def fun_l17_n747() + fun_l18_n103 +end + +def fun_l17_n748() + fun_l18_n185 +end + +def fun_l17_n749() + fun_l18_n781 +end + +def fun_l17_n750() + fun_l18_n980 +end + +def fun_l17_n751() + fun_l18_n961 +end + +def fun_l17_n752() + fun_l18_n447 +end + +def fun_l17_n753() + fun_l18_n124 +end + +def fun_l17_n754() + fun_l18_n605 +end + +def fun_l17_n755() + fun_l18_n7 +end + +def fun_l17_n756() + fun_l18_n731 +end + +def fun_l17_n757() + fun_l18_n479 +end + +def fun_l17_n758() + fun_l18_n931 +end + +def fun_l17_n759() + fun_l18_n535 +end + +def fun_l17_n760() + fun_l18_n772 +end + +def fun_l17_n761() + fun_l18_n827 +end + +def fun_l17_n762() + fun_l18_n265 +end + +def fun_l17_n763() + fun_l18_n81 +end + +def fun_l17_n764() + fun_l18_n377 +end + +def fun_l17_n765() + fun_l18_n565 +end + +def fun_l17_n766() + fun_l18_n520 +end + +def fun_l17_n767() + fun_l18_n556 +end + +def fun_l17_n768() + fun_l18_n711 +end + +def fun_l17_n769() + fun_l18_n460 +end + +def fun_l17_n770() + fun_l18_n902 +end + +def fun_l17_n771() + fun_l18_n874 +end + +def fun_l17_n772() + fun_l18_n742 +end + +def fun_l17_n773() + fun_l18_n578 +end + +def fun_l17_n774() + fun_l18_n198 +end + +def fun_l17_n775() + fun_l18_n965 +end + +def fun_l17_n776() + fun_l18_n342 +end + +def fun_l17_n777() + fun_l18_n50 +end + +def fun_l17_n778() + fun_l18_n299 +end + +def fun_l17_n779() + fun_l18_n289 +end + +def fun_l17_n780() + fun_l18_n830 +end + +def fun_l17_n781() + fun_l18_n157 +end + +def fun_l17_n782() + fun_l18_n628 +end + +def fun_l17_n783() + fun_l18_n875 +end + +def fun_l17_n784() + fun_l18_n810 +end + +def fun_l17_n785() + fun_l18_n642 +end + +def fun_l17_n786() + fun_l18_n422 +end + +def fun_l17_n787() + fun_l18_n816 +end + +def fun_l17_n788() + fun_l18_n184 +end + +def fun_l17_n789() + fun_l18_n391 +end + +def fun_l17_n790() + fun_l18_n804 +end + +def fun_l17_n791() + fun_l18_n534 +end + +def fun_l17_n792() + fun_l18_n353 +end + +def fun_l17_n793() + fun_l18_n329 +end + +def fun_l17_n794() + fun_l18_n75 +end + +def fun_l17_n795() + fun_l18_n854 +end + +def fun_l17_n796() + fun_l18_n478 +end + +def fun_l17_n797() + fun_l18_n403 +end + +def fun_l17_n798() + fun_l18_n842 +end + +def fun_l17_n799() + fun_l18_n569 +end + +def fun_l17_n800() + fun_l18_n596 +end + +def fun_l17_n801() + fun_l18_n548 +end + +def fun_l17_n802() + fun_l18_n393 +end + +def fun_l17_n803() + fun_l18_n253 +end + +def fun_l17_n804() + fun_l18_n987 +end + +def fun_l17_n805() + fun_l18_n560 +end + +def fun_l17_n806() + fun_l18_n582 +end + +def fun_l17_n807() + fun_l18_n356 +end + +def fun_l17_n808() + fun_l18_n458 +end + +def fun_l17_n809() + fun_l18_n215 +end + +def fun_l17_n810() + fun_l18_n16 +end + +def fun_l17_n811() + fun_l18_n586 +end + +def fun_l17_n812() + fun_l18_n312 +end + +def fun_l17_n813() + fun_l18_n861 +end + +def fun_l17_n814() + fun_l18_n455 +end + +def fun_l17_n815() + fun_l18_n530 +end + +def fun_l17_n816() + fun_l18_n583 +end + +def fun_l17_n817() + fun_l18_n511 +end + +def fun_l17_n818() + fun_l18_n568 +end + +def fun_l17_n819() + fun_l18_n411 +end + +def fun_l17_n820() + fun_l18_n404 +end + +def fun_l17_n821() + fun_l18_n199 +end + +def fun_l17_n822() + fun_l18_n393 +end + +def fun_l17_n823() + fun_l18_n856 +end + +def fun_l17_n824() + fun_l18_n638 +end + +def fun_l17_n825() + fun_l18_n853 +end + +def fun_l17_n826() + fun_l18_n896 +end + +def fun_l17_n827() + fun_l18_n267 +end + +def fun_l17_n828() + fun_l18_n419 +end + +def fun_l17_n829() + fun_l18_n47 +end + +def fun_l17_n830() + fun_l18_n436 +end + +def fun_l17_n831() + fun_l18_n714 +end + +def fun_l17_n832() + fun_l18_n156 +end + +def fun_l17_n833() + fun_l18_n32 +end + +def fun_l17_n834() + fun_l18_n467 +end + +def fun_l17_n835() + fun_l18_n905 +end + +def fun_l17_n836() + fun_l18_n824 +end + +def fun_l17_n837() + fun_l18_n503 +end + +def fun_l17_n838() + fun_l18_n454 +end + +def fun_l17_n839() + fun_l18_n295 +end + +def fun_l17_n840() + fun_l18_n669 +end + +def fun_l17_n841() + fun_l18_n618 +end + +def fun_l17_n842() + fun_l18_n984 +end + +def fun_l17_n843() + fun_l18_n485 +end + +def fun_l17_n844() + fun_l18_n952 +end + +def fun_l17_n845() + fun_l18_n374 +end + +def fun_l17_n846() + fun_l18_n933 +end + +def fun_l17_n847() + fun_l18_n246 +end + +def fun_l17_n848() + fun_l18_n672 +end + +def fun_l17_n849() + fun_l18_n23 +end + +def fun_l17_n850() + fun_l18_n641 +end + +def fun_l17_n851() + fun_l18_n439 +end + +def fun_l17_n852() + fun_l18_n423 +end + +def fun_l17_n853() + fun_l18_n565 +end + +def fun_l17_n854() + fun_l18_n189 +end + +def fun_l17_n855() + fun_l18_n265 +end + +def fun_l17_n856() + fun_l18_n101 +end + +def fun_l17_n857() + fun_l18_n799 +end + +def fun_l17_n858() + fun_l18_n831 +end + +def fun_l17_n859() + fun_l18_n222 +end + +def fun_l17_n860() + fun_l18_n398 +end + +def fun_l17_n861() + fun_l18_n946 +end + +def fun_l17_n862() + fun_l18_n693 +end + +def fun_l17_n863() + fun_l18_n947 +end + +def fun_l17_n864() + fun_l18_n22 +end + +def fun_l17_n865() + fun_l18_n386 +end + +def fun_l17_n866() + fun_l18_n771 +end + +def fun_l17_n867() + fun_l18_n38 +end + +def fun_l17_n868() + fun_l18_n290 +end + +def fun_l17_n869() + fun_l18_n204 +end + +def fun_l17_n870() + fun_l18_n780 +end + +def fun_l17_n871() + fun_l18_n275 +end + +def fun_l17_n872() + fun_l18_n810 +end + +def fun_l17_n873() + fun_l18_n104 +end + +def fun_l17_n874() + fun_l18_n433 +end + +def fun_l17_n875() + fun_l18_n55 +end + +def fun_l17_n876() + fun_l18_n508 +end + +def fun_l17_n877() + fun_l18_n997 +end + +def fun_l17_n878() + fun_l18_n115 +end + +def fun_l17_n879() + fun_l18_n568 +end + +def fun_l17_n880() + fun_l18_n385 +end + +def fun_l17_n881() + fun_l18_n912 +end + +def fun_l17_n882() + fun_l18_n234 +end + +def fun_l17_n883() + fun_l18_n85 +end + +def fun_l17_n884() + fun_l18_n935 +end + +def fun_l17_n885() + fun_l18_n389 +end + +def fun_l17_n886() + fun_l18_n925 +end + +def fun_l17_n887() + fun_l18_n629 +end + +def fun_l17_n888() + fun_l18_n310 +end + +def fun_l17_n889() + fun_l18_n538 +end + +def fun_l17_n890() + fun_l18_n172 +end + +def fun_l17_n891() + fun_l18_n161 +end + +def fun_l17_n892() + fun_l18_n11 +end + +def fun_l17_n893() + fun_l18_n216 +end + +def fun_l17_n894() + fun_l18_n802 +end + +def fun_l17_n895() + fun_l18_n982 +end + +def fun_l17_n896() + fun_l18_n220 +end + +def fun_l17_n897() + fun_l18_n169 +end + +def fun_l17_n898() + fun_l18_n64 +end + +def fun_l17_n899() + fun_l18_n282 +end + +def fun_l17_n900() + fun_l18_n134 +end + +def fun_l17_n901() + fun_l18_n424 +end + +def fun_l17_n902() + fun_l18_n766 +end + +def fun_l17_n903() + fun_l18_n808 +end + +def fun_l17_n904() + fun_l18_n766 +end + +def fun_l17_n905() + fun_l18_n836 +end + +def fun_l17_n906() + fun_l18_n5 +end + +def fun_l17_n907() + fun_l18_n47 +end + +def fun_l17_n908() + fun_l18_n414 +end + +def fun_l17_n909() + fun_l18_n11 +end + +def fun_l17_n910() + fun_l18_n446 +end + +def fun_l17_n911() + fun_l18_n161 +end + +def fun_l17_n912() + fun_l18_n291 +end + +def fun_l17_n913() + fun_l18_n728 +end + +def fun_l17_n914() + fun_l18_n806 +end + +def fun_l17_n915() + fun_l18_n355 +end + +def fun_l17_n916() + fun_l18_n157 +end + +def fun_l17_n917() + fun_l18_n912 +end + +def fun_l17_n918() + fun_l18_n354 +end + +def fun_l17_n919() + fun_l18_n84 +end + +def fun_l17_n920() + fun_l18_n291 +end + +def fun_l17_n921() + fun_l18_n258 +end + +def fun_l17_n922() + fun_l18_n935 +end + +def fun_l17_n923() + fun_l18_n622 +end + +def fun_l17_n924() + fun_l18_n760 +end + +def fun_l17_n925() + fun_l18_n153 +end + +def fun_l17_n926() + fun_l18_n673 +end + +def fun_l17_n927() + fun_l18_n105 +end + +def fun_l17_n928() + fun_l18_n432 +end + +def fun_l17_n929() + fun_l18_n403 +end + +def fun_l17_n930() + fun_l18_n312 +end + +def fun_l17_n931() + fun_l18_n874 +end + +def fun_l17_n932() + fun_l18_n642 +end + +def fun_l17_n933() + fun_l18_n694 +end + +def fun_l17_n934() + fun_l18_n247 +end + +def fun_l17_n935() + fun_l18_n483 +end + +def fun_l17_n936() + fun_l18_n849 +end + +def fun_l17_n937() + fun_l18_n784 +end + +def fun_l17_n938() + fun_l18_n948 +end + +def fun_l17_n939() + fun_l18_n26 +end + +def fun_l17_n940() + fun_l18_n36 +end + +def fun_l17_n941() + fun_l18_n933 +end + +def fun_l17_n942() + fun_l18_n734 +end + +def fun_l17_n943() + fun_l18_n33 +end + +def fun_l17_n944() + fun_l18_n78 +end + +def fun_l17_n945() + fun_l18_n592 +end + +def fun_l17_n946() + fun_l18_n504 +end + +def fun_l17_n947() + fun_l18_n255 +end + +def fun_l17_n948() + fun_l18_n389 +end + +def fun_l17_n949() + fun_l18_n71 +end + +def fun_l17_n950() + fun_l18_n938 +end + +def fun_l17_n951() + fun_l18_n125 +end + +def fun_l17_n952() + fun_l18_n310 +end + +def fun_l17_n953() + fun_l18_n422 +end + +def fun_l17_n954() + fun_l18_n268 +end + +def fun_l17_n955() + fun_l18_n655 +end + +def fun_l17_n956() + fun_l18_n106 +end + +def fun_l17_n957() + fun_l18_n226 +end + +def fun_l17_n958() + fun_l18_n247 +end + +def fun_l17_n959() + fun_l18_n282 +end + +def fun_l17_n960() + fun_l18_n495 +end + +def fun_l17_n961() + fun_l18_n333 +end + +def fun_l17_n962() + fun_l18_n796 +end + +def fun_l17_n963() + fun_l18_n939 +end + +def fun_l17_n964() + fun_l18_n529 +end + +def fun_l17_n965() + fun_l18_n835 +end + +def fun_l17_n966() + fun_l18_n947 +end + +def fun_l17_n967() + fun_l18_n925 +end + +def fun_l17_n968() + fun_l18_n445 +end + +def fun_l17_n969() + fun_l18_n815 +end + +def fun_l17_n970() + fun_l18_n476 +end + +def fun_l17_n971() + fun_l18_n39 +end + +def fun_l17_n972() + fun_l18_n374 +end + +def fun_l17_n973() + fun_l18_n332 +end + +def fun_l17_n974() + fun_l18_n231 +end + +def fun_l17_n975() + fun_l18_n155 +end + +def fun_l17_n976() + fun_l18_n892 +end + +def fun_l17_n977() + fun_l18_n890 +end + +def fun_l17_n978() + fun_l18_n304 +end + +def fun_l17_n979() + fun_l18_n67 +end + +def fun_l17_n980() + fun_l18_n793 +end + +def fun_l17_n981() + fun_l18_n902 +end + +def fun_l17_n982() + fun_l18_n990 +end + +def fun_l17_n983() + fun_l18_n506 +end + +def fun_l17_n984() + fun_l18_n411 +end + +def fun_l17_n985() + fun_l18_n360 +end + +def fun_l17_n986() + fun_l18_n958 +end + +def fun_l17_n987() + fun_l18_n941 +end + +def fun_l17_n988() + fun_l18_n896 +end + +def fun_l17_n989() + fun_l18_n17 +end + +def fun_l17_n990() + fun_l18_n971 +end + +def fun_l17_n991() + fun_l18_n71 +end + +def fun_l17_n992() + fun_l18_n880 +end + +def fun_l17_n993() + fun_l18_n473 +end + +def fun_l17_n994() + fun_l18_n602 +end + +def fun_l17_n995() + fun_l18_n112 +end + +def fun_l17_n996() + fun_l18_n748 +end + +def fun_l17_n997() + fun_l18_n156 +end + +def fun_l17_n998() + fun_l18_n979 +end + +def fun_l17_n999() + fun_l18_n950 +end + +def fun_l18_n0() + fun_l19_n673 +end + +def fun_l18_n1() + fun_l19_n72 +end + +def fun_l18_n2() + fun_l19_n941 +end + +def fun_l18_n3() + fun_l19_n32 +end + +def fun_l18_n4() + fun_l19_n386 +end + +def fun_l18_n5() + fun_l19_n834 +end + +def fun_l18_n6() + fun_l19_n337 +end + +def fun_l18_n7() + fun_l19_n669 +end + +def fun_l18_n8() + fun_l19_n953 +end + +def fun_l18_n9() + fun_l19_n823 +end + +def fun_l18_n10() + fun_l19_n709 +end + +def fun_l18_n11() + fun_l19_n70 +end + +def fun_l18_n12() + fun_l19_n54 +end + +def fun_l18_n13() + fun_l19_n601 +end + +def fun_l18_n14() + fun_l19_n638 +end + +def fun_l18_n15() + fun_l19_n497 +end + +def fun_l18_n16() + fun_l19_n7 +end + +def fun_l18_n17() + fun_l19_n955 +end + +def fun_l18_n18() + fun_l19_n229 +end + +def fun_l18_n19() + fun_l19_n158 +end + +def fun_l18_n20() + fun_l19_n905 +end + +def fun_l18_n21() + fun_l19_n34 +end + +def fun_l18_n22() + fun_l19_n462 +end + +def fun_l18_n23() + fun_l19_n496 +end + +def fun_l18_n24() + fun_l19_n560 +end + +def fun_l18_n25() + fun_l19_n877 +end + +def fun_l18_n26() + fun_l19_n555 +end + +def fun_l18_n27() + fun_l19_n973 +end + +def fun_l18_n28() + fun_l19_n680 +end + +def fun_l18_n29() + fun_l19_n525 +end + +def fun_l18_n30() + fun_l19_n26 +end + +def fun_l18_n31() + fun_l19_n51 +end + +def fun_l18_n32() + fun_l19_n859 +end + +def fun_l18_n33() + fun_l19_n345 +end + +def fun_l18_n34() + fun_l19_n376 +end + +def fun_l18_n35() + fun_l19_n411 +end + +def fun_l18_n36() + fun_l19_n717 +end + +def fun_l18_n37() + fun_l19_n750 +end + +def fun_l18_n38() + fun_l19_n927 +end + +def fun_l18_n39() + fun_l19_n129 +end + +def fun_l18_n40() + fun_l19_n121 +end + +def fun_l18_n41() + fun_l19_n670 +end + +def fun_l18_n42() + fun_l19_n926 +end + +def fun_l18_n43() + fun_l19_n80 +end + +def fun_l18_n44() + fun_l19_n355 +end + +def fun_l18_n45() + fun_l19_n107 +end + +def fun_l18_n46() + fun_l19_n437 +end + +def fun_l18_n47() + fun_l19_n821 +end + +def fun_l18_n48() + fun_l19_n215 +end + +def fun_l18_n49() + fun_l19_n783 +end + +def fun_l18_n50() + fun_l19_n941 +end + +def fun_l18_n51() + fun_l19_n156 +end + +def fun_l18_n52() + fun_l19_n797 +end + +def fun_l18_n53() + fun_l19_n522 +end + +def fun_l18_n54() + fun_l19_n294 +end + +def fun_l18_n55() + fun_l19_n985 +end + +def fun_l18_n56() + fun_l19_n709 +end + +def fun_l18_n57() + fun_l19_n492 +end + +def fun_l18_n58() + fun_l19_n460 +end + +def fun_l18_n59() + fun_l19_n186 +end + +def fun_l18_n60() + fun_l19_n764 +end + +def fun_l18_n61() + fun_l19_n439 +end + +def fun_l18_n62() + fun_l19_n568 +end + +def fun_l18_n63() + fun_l19_n797 +end + +def fun_l18_n64() + fun_l19_n542 +end + +def fun_l18_n65() + fun_l19_n985 +end + +def fun_l18_n66() + fun_l19_n787 +end + +def fun_l18_n67() + fun_l19_n447 +end + +def fun_l18_n68() + fun_l19_n567 +end + +def fun_l18_n69() + fun_l19_n406 +end + +def fun_l18_n70() + fun_l19_n984 +end + +def fun_l18_n71() + fun_l19_n58 +end + +def fun_l18_n72() + fun_l19_n820 +end + +def fun_l18_n73() + fun_l19_n831 +end + +def fun_l18_n74() + fun_l19_n533 +end + +def fun_l18_n75() + fun_l19_n277 +end + +def fun_l18_n76() + fun_l19_n92 +end + +def fun_l18_n77() + fun_l19_n965 +end + +def fun_l18_n78() + fun_l19_n127 +end + +def fun_l18_n79() + fun_l19_n728 +end + +def fun_l18_n80() + fun_l19_n672 +end + +def fun_l18_n81() + fun_l19_n748 +end + +def fun_l18_n82() + fun_l19_n485 +end + +def fun_l18_n83() + fun_l19_n815 +end + +def fun_l18_n84() + fun_l19_n957 +end + +def fun_l18_n85() + fun_l19_n884 +end + +def fun_l18_n86() + fun_l19_n107 +end + +def fun_l18_n87() + fun_l19_n255 +end + +def fun_l18_n88() + fun_l19_n498 +end + +def fun_l18_n89() + fun_l19_n589 +end + +def fun_l18_n90() + fun_l19_n726 +end + +def fun_l18_n91() + fun_l19_n755 +end + +def fun_l18_n92() + fun_l19_n855 +end + +def fun_l18_n93() + fun_l19_n490 +end + +def fun_l18_n94() + fun_l19_n463 +end + +def fun_l18_n95() + fun_l19_n213 +end + +def fun_l18_n96() + fun_l19_n946 +end + +def fun_l18_n97() + fun_l19_n319 +end + +def fun_l18_n98() + fun_l19_n565 +end + +def fun_l18_n99() + fun_l19_n805 +end + +def fun_l18_n100() + fun_l19_n21 +end + +def fun_l18_n101() + fun_l19_n168 +end + +def fun_l18_n102() + fun_l19_n462 +end + +def fun_l18_n103() + fun_l19_n15 +end + +def fun_l18_n104() + fun_l19_n408 +end + +def fun_l18_n105() + fun_l19_n736 +end + +def fun_l18_n106() + fun_l19_n313 +end + +def fun_l18_n107() + fun_l19_n736 +end + +def fun_l18_n108() + fun_l19_n703 +end + +def fun_l18_n109() + fun_l19_n456 +end + +def fun_l18_n110() + fun_l19_n467 +end + +def fun_l18_n111() + fun_l19_n287 +end + +def fun_l18_n112() + fun_l19_n630 +end + +def fun_l18_n113() + fun_l19_n499 +end + +def fun_l18_n114() + fun_l19_n308 +end + +def fun_l18_n115() + fun_l19_n902 +end + +def fun_l18_n116() + fun_l19_n894 +end + +def fun_l18_n117() + fun_l19_n545 +end + +def fun_l18_n118() + fun_l19_n467 +end + +def fun_l18_n119() + fun_l19_n791 +end + +def fun_l18_n120() + fun_l19_n845 +end + +def fun_l18_n121() + fun_l19_n376 +end + +def fun_l18_n122() + fun_l19_n898 +end + +def fun_l18_n123() + fun_l19_n200 +end + +def fun_l18_n124() + fun_l19_n415 +end + +def fun_l18_n125() + fun_l19_n80 +end + +def fun_l18_n126() + fun_l19_n6 +end + +def fun_l18_n127() + fun_l19_n150 +end + +def fun_l18_n128() + fun_l19_n223 +end + +def fun_l18_n129() + fun_l19_n179 +end + +def fun_l18_n130() + fun_l19_n687 +end + +def fun_l18_n131() + fun_l19_n625 +end + +def fun_l18_n132() + fun_l19_n332 +end + +def fun_l18_n133() + fun_l19_n87 +end + +def fun_l18_n134() + fun_l19_n469 +end + +def fun_l18_n135() + fun_l19_n4 +end + +def fun_l18_n136() + fun_l19_n142 +end + +def fun_l18_n137() + fun_l19_n506 +end + +def fun_l18_n138() + fun_l19_n227 +end + +def fun_l18_n139() + fun_l19_n332 +end + +def fun_l18_n140() + fun_l19_n18 +end + +def fun_l18_n141() + fun_l19_n773 +end + +def fun_l18_n142() + fun_l19_n306 +end + +def fun_l18_n143() + fun_l19_n376 +end + +def fun_l18_n144() + fun_l19_n524 +end + +def fun_l18_n145() + fun_l19_n61 +end + +def fun_l18_n146() + fun_l19_n635 +end + +def fun_l18_n147() + fun_l19_n816 +end + +def fun_l18_n148() + fun_l19_n398 +end + +def fun_l18_n149() + fun_l19_n408 +end + +def fun_l18_n150() + fun_l19_n889 +end + +def fun_l18_n151() + fun_l19_n167 +end + +def fun_l18_n152() + fun_l19_n436 +end + +def fun_l18_n153() + fun_l19_n738 +end + +def fun_l18_n154() + fun_l19_n382 +end + +def fun_l18_n155() + fun_l19_n260 +end + +def fun_l18_n156() + fun_l19_n227 +end + +def fun_l18_n157() + fun_l19_n191 +end + +def fun_l18_n158() + fun_l19_n269 +end + +def fun_l18_n159() + fun_l19_n599 +end + +def fun_l18_n160() + fun_l19_n992 +end + +def fun_l18_n161() + fun_l19_n754 +end + +def fun_l18_n162() + fun_l19_n578 +end + +def fun_l18_n163() + fun_l19_n162 +end + +def fun_l18_n164() + fun_l19_n88 +end + +def fun_l18_n165() + fun_l19_n592 +end + +def fun_l18_n166() + fun_l19_n621 +end + +def fun_l18_n167() + fun_l19_n398 +end + +def fun_l18_n168() + fun_l19_n585 +end + +def fun_l18_n169() + fun_l19_n51 +end + +def fun_l18_n170() + fun_l19_n715 +end + +def fun_l18_n171() + fun_l19_n841 +end + +def fun_l18_n172() + fun_l19_n882 +end + +def fun_l18_n173() + fun_l19_n676 +end + +def fun_l18_n174() + fun_l19_n93 +end + +def fun_l18_n175() + fun_l19_n41 +end + +def fun_l18_n176() + fun_l19_n565 +end + +def fun_l18_n177() + fun_l19_n895 +end + +def fun_l18_n178() + fun_l19_n743 +end + +def fun_l18_n179() + fun_l19_n679 +end + +def fun_l18_n180() + fun_l19_n77 +end + +def fun_l18_n181() + fun_l19_n539 +end + +def fun_l18_n182() + fun_l19_n439 +end + +def fun_l18_n183() + fun_l19_n758 +end + +def fun_l18_n184() + fun_l19_n327 +end + +def fun_l18_n185() + fun_l19_n257 +end + +def fun_l18_n186() + fun_l19_n544 +end + +def fun_l18_n187() + fun_l19_n632 +end + +def fun_l18_n188() + fun_l19_n83 +end + +def fun_l18_n189() + fun_l19_n88 +end + +def fun_l18_n190() + fun_l19_n244 +end + +def fun_l18_n191() + fun_l19_n403 +end + +def fun_l18_n192() + fun_l19_n644 +end + +def fun_l18_n193() + fun_l19_n953 +end + +def fun_l18_n194() + fun_l19_n690 +end + +def fun_l18_n195() + fun_l19_n534 +end + +def fun_l18_n196() + fun_l19_n352 +end + +def fun_l18_n197() + fun_l19_n502 +end + +def fun_l18_n198() + fun_l19_n924 +end + +def fun_l18_n199() + fun_l19_n815 +end + +def fun_l18_n200() + fun_l19_n910 +end + +def fun_l18_n201() + fun_l19_n391 +end + +def fun_l18_n202() + fun_l19_n144 +end + +def fun_l18_n203() + fun_l19_n823 +end + +def fun_l18_n204() + fun_l19_n732 +end + +def fun_l18_n205() + fun_l19_n109 +end + +def fun_l18_n206() + fun_l19_n677 +end + +def fun_l18_n207() + fun_l19_n736 +end + +def fun_l18_n208() + fun_l19_n141 +end + +def fun_l18_n209() + fun_l19_n45 +end + +def fun_l18_n210() + fun_l19_n11 +end + +def fun_l18_n211() + fun_l19_n924 +end + +def fun_l18_n212() + fun_l19_n940 +end + +def fun_l18_n213() + fun_l19_n683 +end + +def fun_l18_n214() + fun_l19_n383 +end + +def fun_l18_n215() + fun_l19_n798 +end + +def fun_l18_n216() + fun_l19_n99 +end + +def fun_l18_n217() + fun_l19_n814 +end + +def fun_l18_n218() + fun_l19_n827 +end + +def fun_l18_n219() + fun_l19_n629 +end + +def fun_l18_n220() + fun_l19_n814 +end + +def fun_l18_n221() + fun_l19_n452 +end + +def fun_l18_n222() + fun_l19_n388 +end + +def fun_l18_n223() + fun_l19_n324 +end + +def fun_l18_n224() + fun_l19_n233 +end + +def fun_l18_n225() + fun_l19_n596 +end + +def fun_l18_n226() + fun_l19_n396 +end + +def fun_l18_n227() + fun_l19_n529 +end + +def fun_l18_n228() + fun_l19_n603 +end + +def fun_l18_n229() + fun_l19_n76 +end + +def fun_l18_n230() + fun_l19_n799 +end + +def fun_l18_n231() + fun_l19_n576 +end + +def fun_l18_n232() + fun_l19_n35 +end + +def fun_l18_n233() + fun_l19_n883 +end + +def fun_l18_n234() + fun_l19_n776 +end + +def fun_l18_n235() + fun_l19_n478 +end + +def fun_l18_n236() + fun_l19_n922 +end + +def fun_l18_n237() + fun_l19_n636 +end + +def fun_l18_n238() + fun_l19_n680 +end + +def fun_l18_n239() + fun_l19_n735 +end + +def fun_l18_n240() + fun_l19_n893 +end + +def fun_l18_n241() + fun_l19_n785 +end + +def fun_l18_n242() + fun_l19_n325 +end + +def fun_l18_n243() + fun_l19_n25 +end + +def fun_l18_n244() + fun_l19_n930 +end + +def fun_l18_n245() + fun_l19_n747 +end + +def fun_l18_n246() + fun_l19_n808 +end + +def fun_l18_n247() + fun_l19_n356 +end + +def fun_l18_n248() + fun_l19_n16 +end + +def fun_l18_n249() + fun_l19_n191 +end + +def fun_l18_n250() + fun_l19_n772 +end + +def fun_l18_n251() + fun_l19_n247 +end + +def fun_l18_n252() + fun_l19_n112 +end + +def fun_l18_n253() + fun_l19_n22 +end + +def fun_l18_n254() + fun_l19_n15 +end + +def fun_l18_n255() + fun_l19_n444 +end + +def fun_l18_n256() + fun_l19_n498 +end + +def fun_l18_n257() + fun_l19_n403 +end + +def fun_l18_n258() + fun_l19_n572 +end + +def fun_l18_n259() + fun_l19_n451 +end + +def fun_l18_n260() + fun_l19_n224 +end + +def fun_l18_n261() + fun_l19_n197 +end + +def fun_l18_n262() + fun_l19_n891 +end + +def fun_l18_n263() + fun_l19_n612 +end + +def fun_l18_n264() + fun_l19_n107 +end + +def fun_l18_n265() + fun_l19_n267 +end + +def fun_l18_n266() + fun_l19_n746 +end + +def fun_l18_n267() + fun_l19_n547 +end + +def fun_l18_n268() + fun_l19_n608 +end + +def fun_l18_n269() + fun_l19_n474 +end + +def fun_l18_n270() + fun_l19_n285 +end + +def fun_l18_n271() + fun_l19_n970 +end + +def fun_l18_n272() + fun_l19_n227 +end + +def fun_l18_n273() + fun_l19_n440 +end + +def fun_l18_n274() + fun_l19_n816 +end + +def fun_l18_n275() + fun_l19_n320 +end + +def fun_l18_n276() + fun_l19_n237 +end + +def fun_l18_n277() + fun_l19_n37 +end + +def fun_l18_n278() + fun_l19_n408 +end + +def fun_l18_n279() + fun_l19_n229 +end + +def fun_l18_n280() + fun_l19_n576 +end + +def fun_l18_n281() + fun_l19_n422 +end + +def fun_l18_n282() + fun_l19_n725 +end + +def fun_l18_n283() + fun_l19_n498 +end + +def fun_l18_n284() + fun_l19_n28 +end + +def fun_l18_n285() + fun_l19_n711 +end + +def fun_l18_n286() + fun_l19_n222 +end + +def fun_l18_n287() + fun_l19_n688 +end + +def fun_l18_n288() + fun_l19_n885 +end + +def fun_l18_n289() + fun_l19_n522 +end + +def fun_l18_n290() + fun_l19_n776 +end + +def fun_l18_n291() + fun_l19_n862 +end + +def fun_l18_n292() + fun_l19_n415 +end + +def fun_l18_n293() + fun_l19_n194 +end + +def fun_l18_n294() + fun_l19_n652 +end + +def fun_l18_n295() + fun_l19_n929 +end + +def fun_l18_n296() + fun_l19_n923 +end + +def fun_l18_n297() + fun_l19_n104 +end + +def fun_l18_n298() + fun_l19_n191 +end + +def fun_l18_n299() + fun_l19_n996 +end + +def fun_l18_n300() + fun_l19_n426 +end + +def fun_l18_n301() + fun_l19_n698 +end + +def fun_l18_n302() + fun_l19_n397 +end + +def fun_l18_n303() + fun_l19_n287 +end + +def fun_l18_n304() + fun_l19_n731 +end + +def fun_l18_n305() + fun_l19_n162 +end + +def fun_l18_n306() + fun_l19_n794 +end + +def fun_l18_n307() + fun_l19_n234 +end + +def fun_l18_n308() + fun_l19_n184 +end + +def fun_l18_n309() + fun_l19_n314 +end + +def fun_l18_n310() + fun_l19_n259 +end + +def fun_l18_n311() + fun_l19_n687 +end + +def fun_l18_n312() + fun_l19_n653 +end + +def fun_l18_n313() + fun_l19_n834 +end + +def fun_l18_n314() + fun_l19_n519 +end + +def fun_l18_n315() + fun_l19_n706 +end + +def fun_l18_n316() + fun_l19_n860 +end + +def fun_l18_n317() + fun_l19_n99 +end + +def fun_l18_n318() + fun_l19_n757 +end + +def fun_l18_n319() + fun_l19_n860 +end + +def fun_l18_n320() + fun_l19_n266 +end + +def fun_l18_n321() + fun_l19_n802 +end + +def fun_l18_n322() + fun_l19_n349 +end + +def fun_l18_n323() + fun_l19_n408 +end + +def fun_l18_n324() + fun_l19_n539 +end + +def fun_l18_n325() + fun_l19_n696 +end + +def fun_l18_n326() + fun_l19_n233 +end + +def fun_l18_n327() + fun_l19_n476 +end + +def fun_l18_n328() + fun_l19_n101 +end + +def fun_l18_n329() + fun_l19_n881 +end + +def fun_l18_n330() + fun_l19_n699 +end + +def fun_l18_n331() + fun_l19_n559 +end + +def fun_l18_n332() + fun_l19_n990 +end + +def fun_l18_n333() + fun_l19_n382 +end + +def fun_l18_n334() + fun_l19_n941 +end + +def fun_l18_n335() + fun_l19_n363 +end + +def fun_l18_n336() + fun_l19_n870 +end + +def fun_l18_n337() + fun_l19_n250 +end + +def fun_l18_n338() + fun_l19_n209 +end + +def fun_l18_n339() + fun_l19_n156 +end + +def fun_l18_n340() + fun_l19_n320 +end + +def fun_l18_n341() + fun_l19_n320 +end + +def fun_l18_n342() + fun_l19_n68 +end + +def fun_l18_n343() + fun_l19_n823 +end + +def fun_l18_n344() + fun_l19_n713 +end + +def fun_l18_n345() + fun_l19_n893 +end + +def fun_l18_n346() + fun_l19_n628 +end + +def fun_l18_n347() + fun_l19_n429 +end + +def fun_l18_n348() + fun_l19_n766 +end + +def fun_l18_n349() + fun_l19_n937 +end + +def fun_l18_n350() + fun_l19_n983 +end + +def fun_l18_n351() + fun_l19_n131 +end + +def fun_l18_n352() + fun_l19_n76 +end + +def fun_l18_n353() + fun_l19_n225 +end + +def fun_l18_n354() + fun_l19_n979 +end + +def fun_l18_n355() + fun_l19_n279 +end + +def fun_l18_n356() + fun_l19_n434 +end + +def fun_l18_n357() + fun_l19_n723 +end + +def fun_l18_n358() + fun_l19_n44 +end + +def fun_l18_n359() + fun_l19_n895 +end + +def fun_l18_n360() + fun_l19_n602 +end + +def fun_l18_n361() + fun_l19_n420 +end + +def fun_l18_n362() + fun_l19_n318 +end + +def fun_l18_n363() + fun_l19_n990 +end + +def fun_l18_n364() + fun_l19_n318 +end + +def fun_l18_n365() + fun_l19_n640 +end + +def fun_l18_n366() + fun_l19_n679 +end + +def fun_l18_n367() + fun_l19_n572 +end + +def fun_l18_n368() + fun_l19_n411 +end + +def fun_l18_n369() + fun_l19_n703 +end + +def fun_l18_n370() + fun_l19_n39 +end + +def fun_l18_n371() + fun_l19_n656 +end + +def fun_l18_n372() + fun_l19_n960 +end + +def fun_l18_n373() + fun_l19_n491 +end + +def fun_l18_n374() + fun_l19_n916 +end + +def fun_l18_n375() + fun_l19_n413 +end + +def fun_l18_n376() + fun_l19_n90 +end + +def fun_l18_n377() + fun_l19_n790 +end + +def fun_l18_n378() + fun_l19_n424 +end + +def fun_l18_n379() + fun_l19_n578 +end + +def fun_l18_n380() + fun_l19_n555 +end + +def fun_l18_n381() + fun_l19_n405 +end + +def fun_l18_n382() + fun_l19_n378 +end + +def fun_l18_n383() + fun_l19_n594 +end + +def fun_l18_n384() + fun_l19_n593 +end + +def fun_l18_n385() + fun_l19_n115 +end + +def fun_l18_n386() + fun_l19_n67 +end + +def fun_l18_n387() + fun_l19_n531 +end + +def fun_l18_n388() + fun_l19_n7 +end + +def fun_l18_n389() + fun_l19_n535 +end + +def fun_l18_n390() + fun_l19_n35 +end + +def fun_l18_n391() + fun_l19_n410 +end + +def fun_l18_n392() + fun_l19_n811 +end + +def fun_l18_n393() + fun_l19_n719 +end + +def fun_l18_n394() + fun_l19_n859 +end + +def fun_l18_n395() + fun_l19_n491 +end + +def fun_l18_n396() + fun_l19_n131 +end + +def fun_l18_n397() + fun_l19_n501 +end + +def fun_l18_n398() + fun_l19_n917 +end + +def fun_l18_n399() + fun_l19_n467 +end + +def fun_l18_n400() + fun_l19_n189 +end + +def fun_l18_n401() + fun_l19_n135 +end + +def fun_l18_n402() + fun_l19_n105 +end + +def fun_l18_n403() + fun_l19_n120 +end + +def fun_l18_n404() + fun_l19_n611 +end + +def fun_l18_n405() + fun_l19_n386 +end + +def fun_l18_n406() + fun_l19_n239 +end + +def fun_l18_n407() + fun_l19_n717 +end + +def fun_l18_n408() + fun_l19_n425 +end + +def fun_l18_n409() + fun_l19_n500 +end + +def fun_l18_n410() + fun_l19_n424 +end + +def fun_l18_n411() + fun_l19_n654 +end + +def fun_l18_n412() + fun_l19_n243 +end + +def fun_l18_n413() + fun_l19_n920 +end + +def fun_l18_n414() + fun_l19_n556 +end + +def fun_l18_n415() + fun_l19_n693 +end + +def fun_l18_n416() + fun_l19_n656 +end + +def fun_l18_n417() + fun_l19_n596 +end + +def fun_l18_n418() + fun_l19_n573 +end + +def fun_l18_n419() + fun_l19_n504 +end + +def fun_l18_n420() + fun_l19_n5 +end + +def fun_l18_n421() + fun_l19_n554 +end + +def fun_l18_n422() + fun_l19_n852 +end + +def fun_l18_n423() + fun_l19_n725 +end + +def fun_l18_n424() + fun_l19_n121 +end + +def fun_l18_n425() + fun_l19_n184 +end + +def fun_l18_n426() + fun_l19_n752 +end + +def fun_l18_n427() + fun_l19_n636 +end + +def fun_l18_n428() + fun_l19_n858 +end + +def fun_l18_n429() + fun_l19_n249 +end + +def fun_l18_n430() + fun_l19_n696 +end + +def fun_l18_n431() + fun_l19_n560 +end + +def fun_l18_n432() + fun_l19_n978 +end + +def fun_l18_n433() + fun_l19_n776 +end + +def fun_l18_n434() + fun_l19_n954 +end + +def fun_l18_n435() + fun_l19_n552 +end + +def fun_l18_n436() + fun_l19_n238 +end + +def fun_l18_n437() + fun_l19_n496 +end + +def fun_l18_n438() + fun_l19_n444 +end + +def fun_l18_n439() + fun_l19_n632 +end + +def fun_l18_n440() + fun_l19_n243 +end + +def fun_l18_n441() + fun_l19_n41 +end + +def fun_l18_n442() + fun_l19_n267 +end + +def fun_l18_n443() + fun_l19_n449 +end + +def fun_l18_n444() + fun_l19_n718 +end + +def fun_l18_n445() + fun_l19_n458 +end + +def fun_l18_n446() + fun_l19_n23 +end + +def fun_l18_n447() + fun_l19_n642 +end + +def fun_l18_n448() + fun_l19_n46 +end + +def fun_l18_n449() + fun_l19_n812 +end + +def fun_l18_n450() + fun_l19_n659 +end + +def fun_l18_n451() + fun_l19_n499 +end + +def fun_l18_n452() + fun_l19_n691 +end + +def fun_l18_n453() + fun_l19_n453 +end + +def fun_l18_n454() + fun_l19_n348 +end + +def fun_l18_n455() + fun_l19_n115 +end + +def fun_l18_n456() + fun_l19_n429 +end + +def fun_l18_n457() + fun_l19_n751 +end + +def fun_l18_n458() + fun_l19_n669 +end + +def fun_l18_n459() + fun_l19_n692 +end + +def fun_l18_n460() + fun_l19_n510 +end + +def fun_l18_n461() + fun_l19_n276 +end + +def fun_l18_n462() + fun_l19_n967 +end + +def fun_l18_n463() + fun_l19_n464 +end + +def fun_l18_n464() + fun_l19_n742 +end + +def fun_l18_n465() + fun_l19_n512 +end + +def fun_l18_n466() + fun_l19_n864 +end + +def fun_l18_n467() + fun_l19_n956 +end + +def fun_l18_n468() + fun_l19_n547 +end + +def fun_l18_n469() + fun_l19_n875 +end + +def fun_l18_n470() + fun_l19_n840 +end + +def fun_l18_n471() + fun_l19_n37 +end + +def fun_l18_n472() + fun_l19_n499 +end + +def fun_l18_n473() + fun_l19_n112 +end + +def fun_l18_n474() + fun_l19_n293 +end + +def fun_l18_n475() + fun_l19_n320 +end + +def fun_l18_n476() + fun_l19_n502 +end + +def fun_l18_n477() + fun_l19_n224 +end + +def fun_l18_n478() + fun_l19_n145 +end + +def fun_l18_n479() + fun_l19_n71 +end + +def fun_l18_n480() + fun_l19_n349 +end + +def fun_l18_n481() + fun_l19_n302 +end + +def fun_l18_n482() + fun_l19_n205 +end + +def fun_l18_n483() + fun_l19_n951 +end + +def fun_l18_n484() + fun_l19_n630 +end + +def fun_l18_n485() + fun_l19_n288 +end + +def fun_l18_n486() + fun_l19_n542 +end + +def fun_l18_n487() + fun_l19_n146 +end + +def fun_l18_n488() + fun_l19_n530 +end + +def fun_l18_n489() + fun_l19_n762 +end + +def fun_l18_n490() + fun_l19_n207 +end + +def fun_l18_n491() + fun_l19_n915 +end + +def fun_l18_n492() + fun_l19_n424 +end + +def fun_l18_n493() + fun_l19_n959 +end + +def fun_l18_n494() + fun_l19_n4 +end + +def fun_l18_n495() + fun_l19_n349 +end + +def fun_l18_n496() + fun_l19_n533 +end + +def fun_l18_n497() + fun_l19_n727 +end + +def fun_l18_n498() + fun_l19_n42 +end + +def fun_l18_n499() + fun_l19_n321 +end + +def fun_l18_n500() + fun_l19_n440 +end + +def fun_l18_n501() + fun_l19_n401 +end + +def fun_l18_n502() + fun_l19_n857 +end + +def fun_l18_n503() + fun_l19_n750 +end + +def fun_l18_n504() + fun_l19_n494 +end + +def fun_l18_n505() + fun_l19_n848 +end + +def fun_l18_n506() + fun_l19_n676 +end + +def fun_l18_n507() + fun_l19_n390 +end + +def fun_l18_n508() + fun_l19_n135 +end + +def fun_l18_n509() + fun_l19_n241 +end + +def fun_l18_n510() + fun_l19_n290 +end + +def fun_l18_n511() + fun_l19_n912 +end + +def fun_l18_n512() + fun_l19_n410 +end + +def fun_l18_n513() + fun_l19_n911 +end + +def fun_l18_n514() + fun_l19_n173 +end + +def fun_l18_n515() + fun_l19_n383 +end + +def fun_l18_n516() + fun_l19_n540 +end + +def fun_l18_n517() + fun_l19_n434 +end + +def fun_l18_n518() + fun_l19_n997 +end + +def fun_l18_n519() + fun_l19_n355 +end + +def fun_l18_n520() + fun_l19_n825 +end + +def fun_l18_n521() + fun_l19_n711 +end + +def fun_l18_n522() + fun_l19_n937 +end + +def fun_l18_n523() + fun_l19_n191 +end + +def fun_l18_n524() + fun_l19_n284 +end + +def fun_l18_n525() + fun_l19_n483 +end + +def fun_l18_n526() + fun_l19_n163 +end + +def fun_l18_n527() + fun_l19_n514 +end + +def fun_l18_n528() + fun_l19_n111 +end + +def fun_l18_n529() + fun_l19_n339 +end + +def fun_l18_n530() + fun_l19_n322 +end + +def fun_l18_n531() + fun_l19_n208 +end + +def fun_l18_n532() + fun_l19_n34 +end + +def fun_l18_n533() + fun_l19_n106 +end + +def fun_l18_n534() + fun_l19_n532 +end + +def fun_l18_n535() + fun_l19_n277 +end + +def fun_l18_n536() + fun_l19_n936 +end + +def fun_l18_n537() + fun_l19_n955 +end + +def fun_l18_n538() + fun_l19_n75 +end + +def fun_l18_n539() + fun_l19_n349 +end + +def fun_l18_n540() + fun_l19_n430 +end + +def fun_l18_n541() + fun_l19_n598 +end + +def fun_l18_n542() + fun_l19_n336 +end + +def fun_l18_n543() + fun_l19_n763 +end + +def fun_l18_n544() + fun_l19_n150 +end + +def fun_l18_n545() + fun_l19_n301 +end + +def fun_l18_n546() + fun_l19_n600 +end + +def fun_l18_n547() + fun_l19_n576 +end + +def fun_l18_n548() + fun_l19_n119 +end + +def fun_l18_n549() + fun_l19_n681 +end + +def fun_l18_n550() + fun_l19_n303 +end + +def fun_l18_n551() + fun_l19_n498 +end + +def fun_l18_n552() + fun_l19_n75 +end + +def fun_l18_n553() + fun_l19_n690 +end + +def fun_l18_n554() + fun_l19_n496 +end + +def fun_l18_n555() + fun_l19_n542 +end + +def fun_l18_n556() + fun_l19_n684 +end + +def fun_l18_n557() + fun_l19_n315 +end + +def fun_l18_n558() + fun_l19_n470 +end + +def fun_l18_n559() + fun_l19_n357 +end + +def fun_l18_n560() + fun_l19_n805 +end + +def fun_l18_n561() + fun_l19_n306 +end + +def fun_l18_n562() + fun_l19_n460 +end + +def fun_l18_n563() + fun_l19_n173 +end + +def fun_l18_n564() + fun_l19_n327 +end + +def fun_l18_n565() + fun_l19_n871 +end + +def fun_l18_n566() + fun_l19_n792 +end + +def fun_l18_n567() + fun_l19_n251 +end + +def fun_l18_n568() + fun_l19_n113 +end + +def fun_l18_n569() + fun_l19_n877 +end + +def fun_l18_n570() + fun_l19_n921 +end + +def fun_l18_n571() + fun_l19_n610 +end + +def fun_l18_n572() + fun_l19_n895 +end + +def fun_l18_n573() + fun_l19_n215 +end + +def fun_l18_n574() + fun_l19_n751 +end + +def fun_l18_n575() + fun_l19_n2 +end + +def fun_l18_n576() + fun_l19_n32 +end + +def fun_l18_n577() + fun_l19_n447 +end + +def fun_l18_n578() + fun_l19_n652 +end + +def fun_l18_n579() + fun_l19_n74 +end + +def fun_l18_n580() + fun_l19_n487 +end + +def fun_l18_n581() + fun_l19_n522 +end + +def fun_l18_n582() + fun_l19_n422 +end + +def fun_l18_n583() + fun_l19_n951 +end + +def fun_l18_n584() + fun_l19_n216 +end + +def fun_l18_n585() + fun_l19_n897 +end + +def fun_l18_n586() + fun_l19_n469 +end + +def fun_l18_n587() + fun_l19_n315 +end + +def fun_l18_n588() + fun_l19_n937 +end + +def fun_l18_n589() + fun_l19_n685 +end + +def fun_l18_n590() + fun_l19_n322 +end + +def fun_l18_n591() + fun_l19_n234 +end + +def fun_l18_n592() + fun_l19_n693 +end + +def fun_l18_n593() + fun_l19_n941 +end + +def fun_l18_n594() + fun_l19_n626 +end + +def fun_l18_n595() + fun_l19_n729 +end + +def fun_l18_n596() + fun_l19_n65 +end + +def fun_l18_n597() + fun_l19_n359 +end + +def fun_l18_n598() + fun_l19_n826 +end + +def fun_l18_n599() + fun_l19_n631 +end + +def fun_l18_n600() + fun_l19_n156 +end + +def fun_l18_n601() + fun_l19_n132 +end + +def fun_l18_n602() + fun_l19_n23 +end + +def fun_l18_n603() + fun_l19_n867 +end + +def fun_l18_n604() + fun_l19_n327 +end + +def fun_l18_n605() + fun_l19_n9 +end + +def fun_l18_n606() + fun_l19_n99 +end + +def fun_l18_n607() + fun_l19_n597 +end + +def fun_l18_n608() + fun_l19_n969 +end + +def fun_l18_n609() + fun_l19_n106 +end + +def fun_l18_n610() + fun_l19_n183 +end + +def fun_l18_n611() + fun_l19_n956 +end + +def fun_l18_n612() + fun_l19_n661 +end + +def fun_l18_n613() + fun_l19_n562 +end + +def fun_l18_n614() + fun_l19_n49 +end + +def fun_l18_n615() + fun_l19_n769 +end + +def fun_l18_n616() + fun_l19_n215 +end + +def fun_l18_n617() + fun_l19_n89 +end + +def fun_l18_n618() + fun_l19_n928 +end + +def fun_l18_n619() + fun_l19_n213 +end + +def fun_l18_n620() + fun_l19_n215 +end + +def fun_l18_n621() + fun_l19_n472 +end + +def fun_l18_n622() + fun_l19_n363 +end + +def fun_l18_n623() + fun_l19_n251 +end + +def fun_l18_n624() + fun_l19_n780 +end + +def fun_l18_n625() + fun_l19_n414 +end + +def fun_l18_n626() + fun_l19_n348 +end + +def fun_l18_n627() + fun_l19_n268 +end + +def fun_l18_n628() + fun_l19_n772 +end + +def fun_l18_n629() + fun_l19_n232 +end + +def fun_l18_n630() + fun_l19_n775 +end + +def fun_l18_n631() + fun_l19_n181 +end + +def fun_l18_n632() + fun_l19_n953 +end + +def fun_l18_n633() + fun_l19_n927 +end + +def fun_l18_n634() + fun_l19_n241 +end + +def fun_l18_n635() + fun_l19_n426 +end + +def fun_l18_n636() + fun_l19_n337 +end + +def fun_l18_n637() + fun_l19_n948 +end + +def fun_l18_n638() + fun_l19_n703 +end + +def fun_l18_n639() + fun_l19_n938 +end + +def fun_l18_n640() + fun_l19_n432 +end + +def fun_l18_n641() + fun_l19_n117 +end + +def fun_l18_n642() + fun_l19_n362 +end + +def fun_l18_n643() + fun_l19_n956 +end + +def fun_l18_n644() + fun_l19_n947 +end + +def fun_l18_n645() + fun_l19_n954 +end + +def fun_l18_n646() + fun_l19_n159 +end + +def fun_l18_n647() + fun_l19_n838 +end + +def fun_l18_n648() + fun_l19_n614 +end + +def fun_l18_n649() + fun_l19_n589 +end + +def fun_l18_n650() + fun_l19_n16 +end + +def fun_l18_n651() + fun_l19_n721 +end + +def fun_l18_n652() + fun_l19_n608 +end + +def fun_l18_n653() + fun_l19_n462 +end + +def fun_l18_n654() + fun_l19_n66 +end + +def fun_l18_n655() + fun_l19_n219 +end + +def fun_l18_n656() + fun_l19_n660 +end + +def fun_l18_n657() + fun_l19_n466 +end + +def fun_l18_n658() + fun_l19_n441 +end + +def fun_l18_n659() + fun_l19_n140 +end + +def fun_l18_n660() + fun_l19_n538 +end + +def fun_l18_n661() + fun_l19_n602 +end + +def fun_l18_n662() + fun_l19_n94 +end + +def fun_l18_n663() + fun_l19_n435 +end + +def fun_l18_n664() + fun_l19_n632 +end + +def fun_l18_n665() + fun_l19_n404 +end + +def fun_l18_n666() + fun_l19_n894 +end + +def fun_l18_n667() + fun_l19_n668 +end + +def fun_l18_n668() + fun_l19_n802 +end + +def fun_l18_n669() + fun_l19_n785 +end + +def fun_l18_n670() + fun_l19_n16 +end + +def fun_l18_n671() + fun_l19_n124 +end + +def fun_l18_n672() + fun_l19_n587 +end + +def fun_l18_n673() + fun_l19_n605 +end + +def fun_l18_n674() + fun_l19_n903 +end + +def fun_l18_n675() + fun_l19_n980 +end + +def fun_l18_n676() + fun_l19_n463 +end + +def fun_l18_n677() + fun_l19_n716 +end + +def fun_l18_n678() + fun_l19_n815 +end + +def fun_l18_n679() + fun_l19_n909 +end + +def fun_l18_n680() + fun_l19_n924 +end + +def fun_l18_n681() + fun_l19_n383 +end + +def fun_l18_n682() + fun_l19_n761 +end + +def fun_l18_n683() + fun_l19_n663 +end + +def fun_l18_n684() + fun_l19_n176 +end + +def fun_l18_n685() + fun_l19_n87 +end + +def fun_l18_n686() + fun_l19_n1 +end + +def fun_l18_n687() + fun_l19_n953 +end + +def fun_l18_n688() + fun_l19_n737 +end + +def fun_l18_n689() + fun_l19_n792 +end + +def fun_l18_n690() + fun_l19_n165 +end + +def fun_l18_n691() + fun_l19_n266 +end + +def fun_l18_n692() + fun_l19_n357 +end + +def fun_l18_n693() + fun_l19_n780 +end + +def fun_l18_n694() + fun_l19_n893 +end + +def fun_l18_n695() + fun_l19_n280 +end + +def fun_l18_n696() + fun_l19_n117 +end + +def fun_l18_n697() + fun_l19_n985 +end + +def fun_l18_n698() + fun_l19_n306 +end + +def fun_l18_n699() + fun_l19_n421 +end + +def fun_l18_n700() + fun_l19_n62 +end + +def fun_l18_n701() + fun_l19_n384 +end + +def fun_l18_n702() + fun_l19_n394 +end + +def fun_l18_n703() + fun_l19_n707 +end + +def fun_l18_n704() + fun_l19_n599 +end + +def fun_l18_n705() + fun_l19_n590 +end + +def fun_l18_n706() + fun_l19_n49 +end + +def fun_l18_n707() + fun_l19_n529 +end + +def fun_l18_n708() + fun_l19_n824 +end + +def fun_l18_n709() + fun_l19_n481 +end + +def fun_l18_n710() + fun_l19_n221 +end + +def fun_l18_n711() + fun_l19_n305 +end + +def fun_l18_n712() + fun_l19_n612 +end + +def fun_l18_n713() + fun_l19_n809 +end + +def fun_l18_n714() + fun_l19_n41 +end + +def fun_l18_n715() + fun_l19_n477 +end + +def fun_l18_n716() + fun_l19_n717 +end + +def fun_l18_n717() + fun_l19_n447 +end + +def fun_l18_n718() + fun_l19_n501 +end + +def fun_l18_n719() + fun_l19_n86 +end + +def fun_l18_n720() + fun_l19_n250 +end + +def fun_l18_n721() + fun_l19_n504 +end + +def fun_l18_n722() + fun_l19_n274 +end + +def fun_l18_n723() + fun_l19_n167 +end + +def fun_l18_n724() + fun_l19_n824 +end + +def fun_l18_n725() + fun_l19_n188 +end + +def fun_l18_n726() + fun_l19_n953 +end + +def fun_l18_n727() + fun_l19_n61 +end + +def fun_l18_n728() + fun_l19_n242 +end + +def fun_l18_n729() + fun_l19_n167 +end + +def fun_l18_n730() + fun_l19_n936 +end + +def fun_l18_n731() + fun_l19_n293 +end + +def fun_l18_n732() + fun_l19_n951 +end + +def fun_l18_n733() + fun_l19_n235 +end + +def fun_l18_n734() + fun_l19_n718 +end + +def fun_l18_n735() + fun_l19_n930 +end + +def fun_l18_n736() + fun_l19_n842 +end + +def fun_l18_n737() + fun_l19_n697 +end + +def fun_l18_n738() + fun_l19_n503 +end + +def fun_l18_n739() + fun_l19_n789 +end + +def fun_l18_n740() + fun_l19_n87 +end + +def fun_l18_n741() + fun_l19_n919 +end + +def fun_l18_n742() + fun_l19_n26 +end + +def fun_l18_n743() + fun_l19_n873 +end + +def fun_l18_n744() + fun_l19_n334 +end + +def fun_l18_n745() + fun_l19_n112 +end + +def fun_l18_n746() + fun_l19_n648 +end + +def fun_l18_n747() + fun_l19_n261 +end + +def fun_l18_n748() + fun_l19_n617 +end + +def fun_l18_n749() + fun_l19_n922 +end + +def fun_l18_n750() + fun_l19_n434 +end + +def fun_l18_n751() + fun_l19_n842 +end + +def fun_l18_n752() + fun_l19_n498 +end + +def fun_l18_n753() + fun_l19_n367 +end + +def fun_l18_n754() + fun_l19_n799 +end + +def fun_l18_n755() + fun_l19_n780 +end + +def fun_l18_n756() + fun_l19_n119 +end + +def fun_l18_n757() + fun_l19_n871 +end + +def fun_l18_n758() + fun_l19_n293 +end + +def fun_l18_n759() + fun_l19_n645 +end + +def fun_l18_n760() + fun_l19_n226 +end + +def fun_l18_n761() + fun_l19_n518 +end + +def fun_l18_n762() + fun_l19_n223 +end + +def fun_l18_n763() + fun_l19_n859 +end + +def fun_l18_n764() + fun_l19_n545 +end + +def fun_l18_n765() + fun_l19_n452 +end + +def fun_l18_n766() + fun_l19_n538 +end + +def fun_l18_n767() + fun_l19_n574 +end + +def fun_l18_n768() + fun_l19_n605 +end + +def fun_l18_n769() + fun_l19_n794 +end + +def fun_l18_n770() + fun_l19_n35 +end + +def fun_l18_n771() + fun_l19_n990 +end + +def fun_l18_n772() + fun_l19_n276 +end + +def fun_l18_n773() + fun_l19_n806 +end + +def fun_l18_n774() + fun_l19_n321 +end + +def fun_l18_n775() + fun_l19_n874 +end + +def fun_l18_n776() + fun_l19_n349 +end + +def fun_l18_n777() + fun_l19_n595 +end + +def fun_l18_n778() + fun_l19_n944 +end + +def fun_l18_n779() + fun_l19_n617 +end + +def fun_l18_n780() + fun_l19_n982 +end + +def fun_l18_n781() + fun_l19_n395 +end + +def fun_l18_n782() + fun_l19_n362 +end + +def fun_l18_n783() + fun_l19_n533 +end + +def fun_l18_n784() + fun_l19_n646 +end + +def fun_l18_n785() + fun_l19_n160 +end + +def fun_l18_n786() + fun_l19_n288 +end + +def fun_l18_n787() + fun_l19_n381 +end + +def fun_l18_n788() + fun_l19_n299 +end + +def fun_l18_n789() + fun_l19_n546 +end + +def fun_l18_n790() + fun_l19_n906 +end + +def fun_l18_n791() + fun_l19_n788 +end + +def fun_l18_n792() + fun_l19_n389 +end + +def fun_l18_n793() + fun_l19_n593 +end + +def fun_l18_n794() + fun_l19_n224 +end + +def fun_l18_n795() + fun_l19_n815 +end + +def fun_l18_n796() + fun_l19_n533 +end + +def fun_l18_n797() + fun_l19_n47 +end + +def fun_l18_n798() + fun_l19_n457 +end + +def fun_l18_n799() + fun_l19_n951 +end + +def fun_l18_n800() + fun_l19_n680 +end + +def fun_l18_n801() + fun_l19_n362 +end + +def fun_l18_n802() + fun_l19_n667 +end + +def fun_l18_n803() + fun_l19_n906 +end + +def fun_l18_n804() + fun_l19_n444 +end + +def fun_l18_n805() + fun_l19_n562 +end + +def fun_l18_n806() + fun_l19_n472 +end + +def fun_l18_n807() + fun_l19_n706 +end + +def fun_l18_n808() + fun_l19_n611 +end + +def fun_l18_n809() + fun_l19_n514 +end + +def fun_l18_n810() + fun_l19_n742 +end + +def fun_l18_n811() + fun_l19_n144 +end + +def fun_l18_n812() + fun_l19_n938 +end + +def fun_l18_n813() + fun_l19_n835 +end + +def fun_l18_n814() + fun_l19_n127 +end + +def fun_l18_n815() + fun_l19_n188 +end + +def fun_l18_n816() + fun_l19_n511 +end + +def fun_l18_n817() + fun_l19_n919 +end + +def fun_l18_n818() + fun_l19_n46 +end + +def fun_l18_n819() + fun_l19_n927 +end + +def fun_l18_n820() + fun_l19_n655 +end + +def fun_l18_n821() + fun_l19_n713 +end + +def fun_l18_n822() + fun_l19_n803 +end + +def fun_l18_n823() + fun_l19_n116 +end + +def fun_l18_n824() + fun_l19_n139 +end + +def fun_l18_n825() + fun_l19_n263 +end + +def fun_l18_n826() + fun_l19_n728 +end + +def fun_l18_n827() + fun_l19_n77 +end + +def fun_l18_n828() + fun_l19_n958 +end + +def fun_l18_n829() + fun_l19_n827 +end + +def fun_l18_n830() + fun_l19_n738 +end + +def fun_l18_n831() + fun_l19_n430 +end + +def fun_l18_n832() + fun_l19_n16 +end + +def fun_l18_n833() + fun_l19_n335 +end + +def fun_l18_n834() + fun_l19_n674 +end + +def fun_l18_n835() + fun_l19_n938 +end + +def fun_l18_n836() + fun_l19_n460 +end + +def fun_l18_n837() + fun_l19_n268 +end + +def fun_l18_n838() + fun_l19_n250 +end + +def fun_l18_n839() + fun_l19_n460 +end + +def fun_l18_n840() + fun_l19_n966 +end + +def fun_l18_n841() + fun_l19_n228 +end + +def fun_l18_n842() + fun_l19_n90 +end + +def fun_l18_n843() + fun_l19_n227 +end + +def fun_l18_n844() + fun_l19_n494 +end + +def fun_l18_n845() + fun_l19_n85 +end + +def fun_l18_n846() + fun_l19_n497 +end + +def fun_l18_n847() + fun_l19_n395 +end + +def fun_l18_n848() + fun_l19_n874 +end + +def fun_l18_n849() + fun_l19_n826 +end + +def fun_l18_n850() + fun_l19_n467 +end + +def fun_l18_n851() + fun_l19_n330 +end + +def fun_l18_n852() + fun_l19_n229 +end + +def fun_l18_n853() + fun_l19_n172 +end + +def fun_l18_n854() + fun_l19_n604 +end + +def fun_l18_n855() + fun_l19_n314 +end + +def fun_l18_n856() + fun_l19_n553 +end + +def fun_l18_n857() + fun_l19_n946 +end + +def fun_l18_n858() + fun_l19_n347 +end + +def fun_l18_n859() + fun_l19_n566 +end + +def fun_l18_n860() + fun_l19_n144 +end + +def fun_l18_n861() + fun_l19_n812 +end + +def fun_l18_n862() + fun_l19_n615 +end + +def fun_l18_n863() + fun_l19_n411 +end + +def fun_l18_n864() + fun_l19_n67 +end + +def fun_l18_n865() + fun_l19_n830 +end + +def fun_l18_n866() + fun_l19_n849 +end + +def fun_l18_n867() + fun_l19_n933 +end + +def fun_l18_n868() + fun_l19_n892 +end + +def fun_l18_n869() + fun_l19_n644 +end + +def fun_l18_n870() + fun_l19_n567 +end + +def fun_l18_n871() + fun_l19_n558 +end + +def fun_l18_n872() + fun_l19_n766 +end + +def fun_l18_n873() + fun_l19_n715 +end + +def fun_l18_n874() + fun_l19_n641 +end + +def fun_l18_n875() + fun_l19_n81 +end + +def fun_l18_n876() + fun_l19_n472 +end + +def fun_l18_n877() + fun_l19_n907 +end + +def fun_l18_n878() + fun_l19_n426 +end + +def fun_l18_n879() + fun_l19_n329 +end + +def fun_l18_n880() + fun_l19_n935 +end + +def fun_l18_n881() + fun_l19_n100 +end + +def fun_l18_n882() + fun_l19_n540 +end + +def fun_l18_n883() + fun_l19_n905 +end + +def fun_l18_n884() + fun_l19_n991 +end + +def fun_l18_n885() + fun_l19_n700 +end + +def fun_l18_n886() + fun_l19_n698 +end + +def fun_l18_n887() + fun_l19_n805 +end + +def fun_l18_n888() + fun_l19_n736 +end + +def fun_l18_n889() + fun_l19_n386 +end + +def fun_l18_n890() + fun_l19_n895 +end + +def fun_l18_n891() + fun_l19_n542 +end + +def fun_l18_n892() + fun_l19_n261 +end + +def fun_l18_n893() + fun_l19_n600 +end + +def fun_l18_n894() + fun_l19_n153 +end + +def fun_l18_n895() + fun_l19_n767 +end + +def fun_l18_n896() + fun_l19_n201 +end + +def fun_l18_n897() + fun_l19_n98 +end + +def fun_l18_n898() + fun_l19_n423 +end + +def fun_l18_n899() + fun_l19_n247 +end + +def fun_l18_n900() + fun_l19_n720 +end + +def fun_l18_n901() + fun_l19_n1 +end + +def fun_l18_n902() + fun_l19_n21 +end + +def fun_l18_n903() + fun_l19_n591 +end + +def fun_l18_n904() + fun_l19_n36 +end + +def fun_l18_n905() + fun_l19_n654 +end + +def fun_l18_n906() + fun_l19_n378 +end + +def fun_l18_n907() + fun_l19_n841 +end + +def fun_l18_n908() + fun_l19_n685 +end + +def fun_l18_n909() + fun_l19_n933 +end + +def fun_l18_n910() + fun_l19_n71 +end + +def fun_l18_n911() + fun_l19_n963 +end + +def fun_l18_n912() + fun_l19_n590 +end + +def fun_l18_n913() + fun_l19_n24 +end + +def fun_l18_n914() + fun_l19_n213 +end + +def fun_l18_n915() + fun_l19_n862 +end + +def fun_l18_n916() + fun_l19_n2 +end + +def fun_l18_n917() + fun_l19_n728 +end + +def fun_l18_n918() + fun_l19_n23 +end + +def fun_l18_n919() + fun_l19_n345 +end + +def fun_l18_n920() + fun_l19_n515 +end + +def fun_l18_n921() + fun_l19_n803 +end + +def fun_l18_n922() + fun_l19_n378 +end + +def fun_l18_n923() + fun_l19_n260 +end + +def fun_l18_n924() + fun_l19_n824 +end + +def fun_l18_n925() + fun_l19_n698 +end + +def fun_l18_n926() + fun_l19_n719 +end + +def fun_l18_n927() + fun_l19_n126 +end + +def fun_l18_n928() + fun_l19_n647 +end + +def fun_l18_n929() + fun_l19_n412 +end + +def fun_l18_n930() + fun_l19_n617 +end + +def fun_l18_n931() + fun_l19_n295 +end + +def fun_l18_n932() + fun_l19_n231 +end + +def fun_l18_n933() + fun_l19_n301 +end + +def fun_l18_n934() + fun_l19_n25 +end + +def fun_l18_n935() + fun_l19_n341 +end + +def fun_l18_n936() + fun_l19_n845 +end + +def fun_l18_n937() + fun_l19_n97 +end + +def fun_l18_n938() + fun_l19_n787 +end + +def fun_l18_n939() + fun_l19_n828 +end + +def fun_l18_n940() + fun_l19_n298 +end + +def fun_l18_n941() + fun_l19_n234 +end + +def fun_l18_n942() + fun_l19_n74 +end + +def fun_l18_n943() + fun_l19_n928 +end + +def fun_l18_n944() + fun_l19_n276 +end + +def fun_l18_n945() + fun_l19_n699 +end + +def fun_l18_n946() + fun_l19_n507 +end + +def fun_l18_n947() + fun_l19_n385 +end + +def fun_l18_n948() + fun_l19_n651 +end + +def fun_l18_n949() + fun_l19_n315 +end + +def fun_l18_n950() + fun_l19_n289 +end + +def fun_l18_n951() + fun_l19_n879 +end + +def fun_l18_n952() + fun_l19_n549 +end + +def fun_l18_n953() + fun_l19_n205 +end + +def fun_l18_n954() + fun_l19_n468 +end + +def fun_l18_n955() + fun_l19_n11 +end + +def fun_l18_n956() + fun_l19_n644 +end + +def fun_l18_n957() + fun_l19_n492 +end + +def fun_l18_n958() + fun_l19_n94 +end + +def fun_l18_n959() + fun_l19_n331 +end + +def fun_l18_n960() + fun_l19_n708 +end + +def fun_l18_n961() + fun_l19_n646 +end + +def fun_l18_n962() + fun_l19_n206 +end + +def fun_l18_n963() + fun_l19_n793 +end + +def fun_l18_n964() + fun_l19_n426 +end + +def fun_l18_n965() + fun_l19_n181 +end + +def fun_l18_n966() + fun_l19_n773 +end + +def fun_l18_n967() + fun_l19_n324 +end + +def fun_l18_n968() + fun_l19_n451 +end + +def fun_l18_n969() + fun_l19_n155 +end + +def fun_l18_n970() + fun_l19_n812 +end + +def fun_l18_n971() + fun_l19_n906 +end + +def fun_l18_n972() + fun_l19_n367 +end + +def fun_l18_n973() + fun_l19_n260 +end + +def fun_l18_n974() + fun_l19_n226 +end + +def fun_l18_n975() + fun_l19_n189 +end + +def fun_l18_n976() + fun_l19_n32 +end + +def fun_l18_n977() + fun_l19_n43 +end + +def fun_l18_n978() + fun_l19_n285 +end + +def fun_l18_n979() + fun_l19_n511 +end + +def fun_l18_n980() + fun_l19_n714 +end + +def fun_l18_n981() + fun_l19_n587 +end + +def fun_l18_n982() + fun_l19_n247 +end + +def fun_l18_n983() + fun_l19_n258 +end + +def fun_l18_n984() + fun_l19_n115 +end + +def fun_l18_n985() + fun_l19_n873 +end + +def fun_l18_n986() + fun_l19_n452 +end + +def fun_l18_n987() + fun_l19_n994 +end + +def fun_l18_n988() + fun_l19_n912 +end + +def fun_l18_n989() + fun_l19_n534 +end + +def fun_l18_n990() + fun_l19_n186 +end + +def fun_l18_n991() + fun_l19_n49 +end + +def fun_l18_n992() + fun_l19_n676 +end + +def fun_l18_n993() + fun_l19_n466 +end + +def fun_l18_n994() + fun_l19_n571 +end + +def fun_l18_n995() + fun_l19_n573 +end + +def fun_l18_n996() + fun_l19_n47 +end + +def fun_l18_n997() + fun_l19_n657 +end + +def fun_l18_n998() + fun_l19_n11 +end + +def fun_l18_n999() + fun_l19_n342 +end + +def fun_l19_n0() + fun_l20_n278 +end + +def fun_l19_n1() + fun_l20_n159 +end + +def fun_l19_n2() + fun_l20_n289 +end + +def fun_l19_n3() + fun_l20_n766 +end + +def fun_l19_n4() + fun_l20_n45 +end + +def fun_l19_n5() + fun_l20_n453 +end + +def fun_l19_n6() + fun_l20_n581 +end + +def fun_l19_n7() + fun_l20_n607 +end + +def fun_l19_n8() + fun_l20_n427 +end + +def fun_l19_n9() + fun_l20_n287 +end + +def fun_l19_n10() + fun_l20_n28 +end + +def fun_l19_n11() + fun_l20_n456 +end + +def fun_l19_n12() + fun_l20_n283 +end + +def fun_l19_n13() + fun_l20_n451 +end + +def fun_l19_n14() + fun_l20_n220 +end + +def fun_l19_n15() + fun_l20_n497 +end + +def fun_l19_n16() + fun_l20_n295 +end + +def fun_l19_n17() + fun_l20_n66 +end + +def fun_l19_n18() + fun_l20_n863 +end + +def fun_l19_n19() + fun_l20_n919 +end + +def fun_l19_n20() + fun_l20_n712 +end + +def fun_l19_n21() + fun_l20_n323 +end + +def fun_l19_n22() + fun_l20_n666 +end + +def fun_l19_n23() + fun_l20_n947 +end + +def fun_l19_n24() + fun_l20_n422 +end + +def fun_l19_n25() + fun_l20_n728 +end + +def fun_l19_n26() + fun_l20_n886 +end + +def fun_l19_n27() + fun_l20_n585 +end + +def fun_l19_n28() + fun_l20_n835 +end + +def fun_l19_n29() + fun_l20_n812 +end + +def fun_l19_n30() + fun_l20_n425 +end + +def fun_l19_n31() + fun_l20_n378 +end + +def fun_l19_n32() + fun_l20_n128 +end + +def fun_l19_n33() + fun_l20_n714 +end + +def fun_l19_n34() + fun_l20_n502 +end + +def fun_l19_n35() + fun_l20_n447 +end + +def fun_l19_n36() + fun_l20_n512 +end + +def fun_l19_n37() + fun_l20_n642 +end + +def fun_l19_n38() + fun_l20_n839 +end + +def fun_l19_n39() + fun_l20_n539 +end + +def fun_l19_n40() + fun_l20_n204 +end + +def fun_l19_n41() + fun_l20_n294 +end + +def fun_l19_n42() + fun_l20_n360 +end + +def fun_l19_n43() + fun_l20_n132 +end + +def fun_l19_n44() + fun_l20_n529 +end + +def fun_l19_n45() + fun_l20_n783 +end + +def fun_l19_n46() + fun_l20_n694 +end + +def fun_l19_n47() + fun_l20_n939 +end + +def fun_l19_n48() + fun_l20_n972 +end + +def fun_l19_n49() + fun_l20_n187 +end + +def fun_l19_n50() + fun_l20_n236 +end + +def fun_l19_n51() + fun_l20_n218 +end + +def fun_l19_n52() + fun_l20_n278 +end + +def fun_l19_n53() + fun_l20_n895 +end + +def fun_l19_n54() + fun_l20_n967 +end + +def fun_l19_n55() + fun_l20_n110 +end + +def fun_l19_n56() + fun_l20_n918 +end + +def fun_l19_n57() + fun_l20_n458 +end + +def fun_l19_n58() + fun_l20_n262 +end + +def fun_l19_n59() + fun_l20_n978 +end + +def fun_l19_n60() + fun_l20_n434 +end + +def fun_l19_n61() + fun_l20_n86 +end + +def fun_l19_n62() + fun_l20_n364 +end + +def fun_l19_n63() + fun_l20_n92 +end + +def fun_l19_n64() + fun_l20_n173 +end + +def fun_l19_n65() + fun_l20_n530 +end + +def fun_l19_n66() + fun_l20_n291 +end + +def fun_l19_n67() + fun_l20_n758 +end + +def fun_l19_n68() + fun_l20_n311 +end + +def fun_l19_n69() + fun_l20_n984 +end + +def fun_l19_n70() + fun_l20_n976 +end + +def fun_l19_n71() + fun_l20_n622 +end + +def fun_l19_n72() + fun_l20_n467 +end + +def fun_l19_n73() + fun_l20_n369 +end + +def fun_l19_n74() + fun_l20_n81 +end + +def fun_l19_n75() + fun_l20_n6 +end + +def fun_l19_n76() + fun_l20_n23 +end + +def fun_l19_n77() + fun_l20_n631 +end + +def fun_l19_n78() + fun_l20_n535 +end + +def fun_l19_n79() + fun_l20_n572 +end + +def fun_l19_n80() + fun_l20_n905 +end + +def fun_l19_n81() + fun_l20_n709 +end + +def fun_l19_n82() + fun_l20_n362 +end + +def fun_l19_n83() + fun_l20_n505 +end + +def fun_l19_n84() + fun_l20_n247 +end + +def fun_l19_n85() + fun_l20_n88 +end + +def fun_l19_n86() + fun_l20_n214 +end + +def fun_l19_n87() + fun_l20_n607 +end + +def fun_l19_n88() + fun_l20_n161 +end + +def fun_l19_n89() + fun_l20_n419 +end + +def fun_l19_n90() + fun_l20_n514 +end + +def fun_l19_n91() + fun_l20_n879 +end + +def fun_l19_n92() + fun_l20_n11 +end + +def fun_l19_n93() + fun_l20_n269 +end + +def fun_l19_n94() + fun_l20_n685 +end + +def fun_l19_n95() + fun_l20_n435 +end + +def fun_l19_n96() + fun_l20_n183 +end + +def fun_l19_n97() + fun_l20_n548 +end + +def fun_l19_n98() + fun_l20_n460 +end + +def fun_l19_n99() + fun_l20_n636 +end + +def fun_l19_n100() + fun_l20_n829 +end + +def fun_l19_n101() + fun_l20_n224 +end + +def fun_l19_n102() + fun_l20_n291 +end + +def fun_l19_n103() + fun_l20_n498 +end + +def fun_l19_n104() + fun_l20_n403 +end + +def fun_l19_n105() + fun_l20_n699 +end + +def fun_l19_n106() + fun_l20_n851 +end + +def fun_l19_n107() + fun_l20_n400 +end + +def fun_l19_n108() + fun_l20_n834 +end + +def fun_l19_n109() + fun_l20_n635 +end + +def fun_l19_n110() + fun_l20_n651 +end + +def fun_l19_n111() + fun_l20_n930 +end + +def fun_l19_n112() + fun_l20_n547 +end + +def fun_l19_n113() + fun_l20_n237 +end + +def fun_l19_n114() + fun_l20_n298 +end + +def fun_l19_n115() + fun_l20_n979 +end + +def fun_l19_n116() + fun_l20_n409 +end + +def fun_l19_n117() + fun_l20_n942 +end + +def fun_l19_n118() + fun_l20_n224 +end + +def fun_l19_n119() + fun_l20_n288 +end + +def fun_l19_n120() + fun_l20_n42 +end + +def fun_l19_n121() + fun_l20_n718 +end + +def fun_l19_n122() + fun_l20_n392 +end + +def fun_l19_n123() + fun_l20_n375 +end + +def fun_l19_n124() + fun_l20_n499 +end + +def fun_l19_n125() + fun_l20_n499 +end + +def fun_l19_n126() + fun_l20_n998 +end + +def fun_l19_n127() + fun_l20_n659 +end + +def fun_l19_n128() + fun_l20_n782 +end + +def fun_l19_n129() + fun_l20_n607 +end + +def fun_l19_n130() + fun_l20_n802 +end + +def fun_l19_n131() + fun_l20_n773 +end + +def fun_l19_n132() + fun_l20_n861 +end + +def fun_l19_n133() + fun_l20_n38 +end + +def fun_l19_n134() + fun_l20_n614 +end + +def fun_l19_n135() + fun_l20_n546 +end + +def fun_l19_n136() + fun_l20_n890 +end + +def fun_l19_n137() + fun_l20_n987 +end + +def fun_l19_n138() + fun_l20_n518 +end + +def fun_l19_n139() + fun_l20_n708 +end + +def fun_l19_n140() + fun_l20_n838 +end + +def fun_l19_n141() + fun_l20_n642 +end + +def fun_l19_n142() + fun_l20_n275 +end + +def fun_l19_n143() + fun_l20_n274 +end + +def fun_l19_n144() + fun_l20_n479 +end + +def fun_l19_n145() + fun_l20_n215 +end + +def fun_l19_n146() + fun_l20_n794 +end + +def fun_l19_n147() + fun_l20_n329 +end + +def fun_l19_n148() + fun_l20_n146 +end + +def fun_l19_n149() + fun_l20_n561 +end + +def fun_l19_n150() + fun_l20_n782 +end + +def fun_l19_n151() + fun_l20_n903 +end + +def fun_l19_n152() + fun_l20_n97 +end + +def fun_l19_n153() + fun_l20_n962 +end + +def fun_l19_n154() + fun_l20_n758 +end + +def fun_l19_n155() + fun_l20_n58 +end + +def fun_l19_n156() + fun_l20_n683 +end + +def fun_l19_n157() + fun_l20_n48 +end + +def fun_l19_n158() + fun_l20_n476 +end + +def fun_l19_n159() + fun_l20_n19 +end + +def fun_l19_n160() + fun_l20_n938 +end + +def fun_l19_n161() + fun_l20_n40 +end + +def fun_l19_n162() + fun_l20_n817 +end + +def fun_l19_n163() + fun_l20_n745 +end + +def fun_l19_n164() + fun_l20_n10 +end + +def fun_l19_n165() + fun_l20_n486 +end + +def fun_l19_n166() + fun_l20_n321 +end + +def fun_l19_n167() + fun_l20_n255 +end + +def fun_l19_n168() + fun_l20_n286 +end + +def fun_l19_n169() + fun_l20_n777 +end + +def fun_l19_n170() + fun_l20_n985 +end + +def fun_l19_n171() + fun_l20_n827 +end + +def fun_l19_n172() + fun_l20_n422 +end + +def fun_l19_n173() + fun_l20_n194 +end + +def fun_l19_n174() + fun_l20_n399 +end + +def fun_l19_n175() + fun_l20_n562 +end + +def fun_l19_n176() + fun_l20_n808 +end + +def fun_l19_n177() + fun_l20_n646 +end + +def fun_l19_n178() + fun_l20_n806 +end + +def fun_l19_n179() + fun_l20_n203 +end + +def fun_l19_n180() + fun_l20_n426 +end + +def fun_l19_n181() + fun_l20_n361 +end + +def fun_l19_n182() + fun_l20_n738 +end + +def fun_l19_n183() + fun_l20_n446 +end + +def fun_l19_n184() + fun_l20_n781 +end + +def fun_l19_n185() + fun_l20_n521 +end + +def fun_l19_n186() + fun_l20_n599 +end + +def fun_l19_n187() + fun_l20_n178 +end + +def fun_l19_n188() + fun_l20_n15 +end + +def fun_l19_n189() + fun_l20_n846 +end + +def fun_l19_n190() + fun_l20_n888 +end + +def fun_l19_n191() + fun_l20_n53 +end + +def fun_l19_n192() + fun_l20_n943 +end + +def fun_l19_n193() + fun_l20_n73 +end + +def fun_l19_n194() + fun_l20_n918 +end + +def fun_l19_n195() + fun_l20_n924 +end + +def fun_l19_n196() + fun_l20_n37 +end + +def fun_l19_n197() + fun_l20_n674 +end + +def fun_l19_n198() + fun_l20_n167 +end + +def fun_l19_n199() + fun_l20_n167 +end + +def fun_l19_n200() + fun_l20_n201 +end + +def fun_l19_n201() + fun_l20_n785 +end + +def fun_l19_n202() + fun_l20_n980 +end + +def fun_l19_n203() + fun_l20_n295 +end + +def fun_l19_n204() + fun_l20_n586 +end + +def fun_l19_n205() + fun_l20_n541 +end + +def fun_l19_n206() + fun_l20_n220 +end + +def fun_l19_n207() + fun_l20_n956 +end + +def fun_l19_n208() + fun_l20_n195 +end + +def fun_l19_n209() + fun_l20_n232 +end + +def fun_l19_n210() + fun_l20_n91 +end + +def fun_l19_n211() + fun_l20_n525 +end + +def fun_l19_n212() + fun_l20_n50 +end + +def fun_l19_n213() + fun_l20_n635 +end + +def fun_l19_n214() + fun_l20_n24 +end + +def fun_l19_n215() + fun_l20_n795 +end + +def fun_l19_n216() + fun_l20_n743 +end + +def fun_l19_n217() + fun_l20_n418 +end + +def fun_l19_n218() + fun_l20_n63 +end + +def fun_l19_n219() + fun_l20_n866 +end + +def fun_l19_n220() + fun_l20_n195 +end + +def fun_l19_n221() + fun_l20_n178 +end + +def fun_l19_n222() + fun_l20_n147 +end + +def fun_l19_n223() + fun_l20_n891 +end + +def fun_l19_n224() + fun_l20_n804 +end + +def fun_l19_n225() + fun_l20_n379 +end + +def fun_l19_n226() + fun_l20_n894 +end + +def fun_l19_n227() + fun_l20_n767 +end + +def fun_l19_n228() + fun_l20_n532 +end + +def fun_l19_n229() + fun_l20_n69 +end + +def fun_l19_n230() + fun_l20_n602 +end + +def fun_l19_n231() + fun_l20_n933 +end + +def fun_l19_n232() + fun_l20_n940 +end + +def fun_l19_n233() + fun_l20_n935 +end + +def fun_l19_n234() + fun_l20_n234 +end + +def fun_l19_n235() + fun_l20_n984 +end + +def fun_l19_n236() + fun_l20_n962 +end + +def fun_l19_n237() + fun_l20_n334 +end + +def fun_l19_n238() + fun_l20_n945 +end + +def fun_l19_n239() + fun_l20_n778 +end + +def fun_l19_n240() + fun_l20_n946 +end + +def fun_l19_n241() + fun_l20_n27 +end + +def fun_l19_n242() + fun_l20_n535 +end + +def fun_l19_n243() + fun_l20_n940 +end + +def fun_l19_n244() + fun_l20_n991 +end + +def fun_l19_n245() + fun_l20_n926 +end + +def fun_l19_n246() + fun_l20_n945 +end + +def fun_l19_n247() + fun_l20_n56 +end + +def fun_l19_n248() + fun_l20_n529 +end + +def fun_l19_n249() + fun_l20_n497 +end + +def fun_l19_n250() + fun_l20_n823 +end + +def fun_l19_n251() + fun_l20_n296 +end + +def fun_l19_n252() + fun_l20_n342 +end + +def fun_l19_n253() + fun_l20_n843 +end + +def fun_l19_n254() + fun_l20_n95 +end + +def fun_l19_n255() + fun_l20_n0 +end + +def fun_l19_n256() + fun_l20_n289 +end + +def fun_l19_n257() + fun_l20_n816 +end + +def fun_l19_n258() + fun_l20_n318 +end + +def fun_l19_n259() + fun_l20_n401 +end + +def fun_l19_n260() + fun_l20_n495 +end + +def fun_l19_n261() + fun_l20_n331 +end + +def fun_l19_n262() + fun_l20_n457 +end + +def fun_l19_n263() + fun_l20_n169 +end + +def fun_l19_n264() + fun_l20_n736 +end + +def fun_l19_n265() + fun_l20_n12 +end + +def fun_l19_n266() + fun_l20_n552 +end + +def fun_l19_n267() + fun_l20_n350 +end + +def fun_l19_n268() + fun_l20_n417 +end + +def fun_l19_n269() + fun_l20_n960 +end + +def fun_l19_n270() + fun_l20_n251 +end + +def fun_l19_n271() + fun_l20_n218 +end + +def fun_l19_n272() + fun_l20_n496 +end + +def fun_l19_n273() + fun_l20_n262 +end + +def fun_l19_n274() + fun_l20_n617 +end + +def fun_l19_n275() + fun_l20_n225 +end + +def fun_l19_n276() + fun_l20_n878 +end + +def fun_l19_n277() + fun_l20_n538 +end + +def fun_l19_n278() + fun_l20_n99 +end + +def fun_l19_n279() + fun_l20_n654 +end + +def fun_l19_n280() + fun_l20_n460 +end + +def fun_l19_n281() + fun_l20_n108 +end + +def fun_l19_n282() + fun_l20_n62 +end + +def fun_l19_n283() + fun_l20_n855 +end + +def fun_l19_n284() + fun_l20_n790 +end + +def fun_l19_n285() + fun_l20_n838 +end + +def fun_l19_n286() + fun_l20_n570 +end + +def fun_l19_n287() + fun_l20_n376 +end + +def fun_l19_n288() + fun_l20_n219 +end + +def fun_l19_n289() + fun_l20_n793 +end + +def fun_l19_n290() + fun_l20_n17 +end + +def fun_l19_n291() + fun_l20_n408 +end + +def fun_l19_n292() + fun_l20_n224 +end + +def fun_l19_n293() + fun_l20_n953 +end + +def fun_l19_n294() + fun_l20_n0 +end + +def fun_l19_n295() + fun_l20_n15 +end + +def fun_l19_n296() + fun_l20_n304 +end + +def fun_l19_n297() + fun_l20_n917 +end + +def fun_l19_n298() + fun_l20_n903 +end + +def fun_l19_n299() + fun_l20_n151 +end + +def fun_l19_n300() + fun_l20_n704 +end + +def fun_l19_n301() + fun_l20_n559 +end + +def fun_l19_n302() + fun_l20_n957 +end + +def fun_l19_n303() + fun_l20_n607 +end + +def fun_l19_n304() + fun_l20_n776 +end + +def fun_l19_n305() + fun_l20_n661 +end + +def fun_l19_n306() + fun_l20_n545 +end + +def fun_l19_n307() + fun_l20_n735 +end + +def fun_l19_n308() + fun_l20_n427 +end + +def fun_l19_n309() + fun_l20_n427 +end + +def fun_l19_n310() + fun_l20_n11 +end + +def fun_l19_n311() + fun_l20_n109 +end + +def fun_l19_n312() + fun_l20_n84 +end + +def fun_l19_n313() + fun_l20_n106 +end + +def fun_l19_n314() + fun_l20_n758 +end + +def fun_l19_n315() + fun_l20_n343 +end + +def fun_l19_n316() + fun_l20_n998 +end + +def fun_l19_n317() + fun_l20_n174 +end + +def fun_l19_n318() + fun_l20_n12 +end + +def fun_l19_n319() + fun_l20_n116 +end + +def fun_l19_n320() + fun_l20_n517 +end + +def fun_l19_n321() + fun_l20_n15 +end + +def fun_l19_n322() + fun_l20_n441 +end + +def fun_l19_n323() + fun_l20_n25 +end + +def fun_l19_n324() + fun_l20_n101 +end + +def fun_l19_n325() + fun_l20_n160 +end + +def fun_l19_n326() + fun_l20_n784 +end + +def fun_l19_n327() + fun_l20_n940 +end + +def fun_l19_n328() + fun_l20_n969 +end + +def fun_l19_n329() + fun_l20_n306 +end + +def fun_l19_n330() + fun_l20_n337 +end + +def fun_l19_n331() + fun_l20_n199 +end + +def fun_l19_n332() + fun_l20_n341 +end + +def fun_l19_n333() + fun_l20_n2 +end + +def fun_l19_n334() + fun_l20_n954 +end + +def fun_l19_n335() + fun_l20_n463 +end + +def fun_l19_n336() + fun_l20_n16 +end + +def fun_l19_n337() + fun_l20_n566 +end + +def fun_l19_n338() + fun_l20_n807 +end + +def fun_l19_n339() + fun_l20_n785 +end + +def fun_l19_n340() + fun_l20_n577 +end + +def fun_l19_n341() + fun_l20_n744 +end + +def fun_l19_n342() + fun_l20_n769 +end + +def fun_l19_n343() + fun_l20_n120 +end + +def fun_l19_n344() + fun_l20_n846 +end + +def fun_l19_n345() + fun_l20_n7 +end + +def fun_l19_n346() + fun_l20_n517 +end + +def fun_l19_n347() + fun_l20_n138 +end + +def fun_l19_n348() + fun_l20_n551 +end + +def fun_l19_n349() + fun_l20_n667 +end + +def fun_l19_n350() + fun_l20_n983 +end + +def fun_l19_n351() + fun_l20_n941 +end + +def fun_l19_n352() + fun_l20_n278 +end + +def fun_l19_n353() + fun_l20_n360 +end + +def fun_l19_n354() + fun_l20_n327 +end + +def fun_l19_n355() + fun_l20_n414 +end + +def fun_l19_n356() + fun_l20_n200 +end + +def fun_l19_n357() + fun_l20_n298 +end + +def fun_l19_n358() + fun_l20_n337 +end + +def fun_l19_n359() + fun_l20_n602 +end + +def fun_l19_n360() + fun_l20_n631 +end + +def fun_l19_n361() + fun_l20_n100 +end + +def fun_l19_n362() + fun_l20_n179 +end + +def fun_l19_n363() + fun_l20_n710 +end + +def fun_l19_n364() + fun_l20_n1 +end + +def fun_l19_n365() + fun_l20_n88 +end + +def fun_l19_n366() + fun_l20_n98 +end + +def fun_l19_n367() + fun_l20_n499 +end + +def fun_l19_n368() + fun_l20_n610 +end + +def fun_l19_n369() + fun_l20_n243 +end + +def fun_l19_n370() + fun_l20_n954 +end + +def fun_l19_n371() + fun_l20_n204 +end + +def fun_l19_n372() + fun_l20_n618 +end + +def fun_l19_n373() + fun_l20_n513 +end + +def fun_l19_n374() + fun_l20_n341 +end + +def fun_l19_n375() + fun_l20_n31 +end + +def fun_l19_n376() + fun_l20_n627 +end + +def fun_l19_n377() + fun_l20_n817 +end + +def fun_l19_n378() + fun_l20_n545 +end + +def fun_l19_n379() + fun_l20_n236 +end + +def fun_l19_n380() + fun_l20_n926 +end + +def fun_l19_n381() + fun_l20_n167 +end + +def fun_l19_n382() + fun_l20_n287 +end + +def fun_l19_n383() + fun_l20_n264 +end + +def fun_l19_n384() + fun_l20_n16 +end + +def fun_l19_n385() + fun_l20_n197 +end + +def fun_l19_n386() + fun_l20_n791 +end + +def fun_l19_n387() + fun_l20_n124 +end + +def fun_l19_n388() + fun_l20_n351 +end + +def fun_l19_n389() + fun_l20_n893 +end + +def fun_l19_n390() + fun_l20_n191 +end + +def fun_l19_n391() + fun_l20_n441 +end + +def fun_l19_n392() + fun_l20_n781 +end + +def fun_l19_n393() + fun_l20_n614 +end + +def fun_l19_n394() + fun_l20_n301 +end + +def fun_l19_n395() + fun_l20_n749 +end + +def fun_l19_n396() + fun_l20_n815 +end + +def fun_l19_n397() + fun_l20_n380 +end + +def fun_l19_n398() + fun_l20_n594 +end + +def fun_l19_n399() + fun_l20_n279 +end + +def fun_l19_n400() + fun_l20_n313 +end + +def fun_l19_n401() + fun_l20_n151 +end + +def fun_l19_n402() + fun_l20_n101 +end + +def fun_l19_n403() + fun_l20_n573 +end + +def fun_l19_n404() + fun_l20_n386 +end + +def fun_l19_n405() + fun_l20_n40 +end + +def fun_l19_n406() + fun_l20_n383 +end + +def fun_l19_n407() + fun_l20_n612 +end + +def fun_l19_n408() + fun_l20_n555 +end + +def fun_l19_n409() + fun_l20_n507 +end + +def fun_l19_n410() + fun_l20_n519 +end + +def fun_l19_n411() + fun_l20_n842 +end + +def fun_l19_n412() + fun_l20_n867 +end + +def fun_l19_n413() + fun_l20_n84 +end + +def fun_l19_n414() + fun_l20_n84 +end + +def fun_l19_n415() + fun_l20_n304 +end + +def fun_l19_n416() + fun_l20_n776 +end + +def fun_l19_n417() + fun_l20_n712 +end + +def fun_l19_n418() + fun_l20_n447 +end + +def fun_l19_n419() + fun_l20_n428 +end + +def fun_l19_n420() + fun_l20_n350 +end + +def fun_l19_n421() + fun_l20_n989 +end + +def fun_l19_n422() + fun_l20_n444 +end + +def fun_l19_n423() + fun_l20_n771 +end + +def fun_l19_n424() + fun_l20_n228 +end + +def fun_l19_n425() + fun_l20_n870 +end + +def fun_l19_n426() + fun_l20_n553 +end + +def fun_l19_n427() + fun_l20_n529 +end + +def fun_l19_n428() + fun_l20_n118 +end + +def fun_l19_n429() + fun_l20_n886 +end + +def fun_l19_n430() + fun_l20_n731 +end + +def fun_l19_n431() + fun_l20_n585 +end + +def fun_l19_n432() + fun_l20_n997 +end + +def fun_l19_n433() + fun_l20_n927 +end + +def fun_l19_n434() + fun_l20_n739 +end + +def fun_l19_n435() + fun_l20_n691 +end + +def fun_l19_n436() + fun_l20_n446 +end + +def fun_l19_n437() + fun_l20_n932 +end + +def fun_l19_n438() + fun_l20_n297 +end + +def fun_l19_n439() + fun_l20_n118 +end + +def fun_l19_n440() + fun_l20_n464 +end + +def fun_l19_n441() + fun_l20_n367 +end + +def fun_l19_n442() + fun_l20_n450 +end + +def fun_l19_n443() + fun_l20_n690 +end + +def fun_l19_n444() + fun_l20_n996 +end + +def fun_l19_n445() + fun_l20_n328 +end + +def fun_l19_n446() + fun_l20_n873 +end + +def fun_l19_n447() + fun_l20_n843 +end + +def fun_l19_n448() + fun_l20_n89 +end + +def fun_l19_n449() + fun_l20_n485 +end + +def fun_l19_n450() + fun_l20_n343 +end + +def fun_l19_n451() + fun_l20_n852 +end + +def fun_l19_n452() + fun_l20_n545 +end + +def fun_l19_n453() + fun_l20_n41 +end + +def fun_l19_n454() + fun_l20_n376 +end + +def fun_l19_n455() + fun_l20_n625 +end + +def fun_l19_n456() + fun_l20_n495 +end + +def fun_l19_n457() + fun_l20_n82 +end + +def fun_l19_n458() + fun_l20_n238 +end + +def fun_l19_n459() + fun_l20_n355 +end + +def fun_l19_n460() + fun_l20_n530 +end + +def fun_l19_n461() + fun_l20_n926 +end + +def fun_l19_n462() + fun_l20_n721 +end + +def fun_l19_n463() + fun_l20_n724 +end + +def fun_l19_n464() + fun_l20_n280 +end + +def fun_l19_n465() + fun_l20_n656 +end + +def fun_l19_n466() + fun_l20_n78 +end + +def fun_l19_n467() + fun_l20_n353 +end + +def fun_l19_n468() + fun_l20_n712 +end + +def fun_l19_n469() + fun_l20_n849 +end + +def fun_l19_n470() + fun_l20_n682 +end + +def fun_l19_n471() + fun_l20_n964 +end + +def fun_l19_n472() + fun_l20_n483 +end + +def fun_l19_n473() + fun_l20_n6 +end + +def fun_l19_n474() + fun_l20_n19 +end + +def fun_l19_n475() + fun_l20_n206 +end + +def fun_l19_n476() + fun_l20_n165 +end + +def fun_l19_n477() + fun_l20_n514 +end + +def fun_l19_n478() + fun_l20_n380 +end + +def fun_l19_n479() + fun_l20_n381 +end + +def fun_l19_n480() + fun_l20_n210 +end + +def fun_l19_n481() + fun_l20_n972 +end + +def fun_l19_n482() + fun_l20_n211 +end + +def fun_l19_n483() + fun_l20_n795 +end + +def fun_l19_n484() + fun_l20_n441 +end + +def fun_l19_n485() + fun_l20_n539 +end + +def fun_l19_n486() + fun_l20_n217 +end + +def fun_l19_n487() + fun_l20_n644 +end + +def fun_l19_n488() + fun_l20_n641 +end + +def fun_l19_n489() + fun_l20_n179 +end + +def fun_l19_n490() + fun_l20_n643 +end + +def fun_l19_n491() + fun_l20_n797 +end + +def fun_l19_n492() + fun_l20_n863 +end + +def fun_l19_n493() + fun_l20_n915 +end + +def fun_l19_n494() + fun_l20_n13 +end + +def fun_l19_n495() + fun_l20_n427 +end + +def fun_l19_n496() + fun_l20_n40 +end + +def fun_l19_n497() + fun_l20_n724 +end + +def fun_l19_n498() + fun_l20_n666 +end + +def fun_l19_n499() + fun_l20_n876 +end + +def fun_l19_n500() + fun_l20_n980 +end + +def fun_l19_n501() + fun_l20_n817 +end + +def fun_l19_n502() + fun_l20_n158 +end + +def fun_l19_n503() + fun_l20_n738 +end + +def fun_l19_n504() + fun_l20_n347 +end + +def fun_l19_n505() + fun_l20_n941 +end + +def fun_l19_n506() + fun_l20_n330 +end + +def fun_l19_n507() + fun_l20_n196 +end + +def fun_l19_n508() + fun_l20_n961 +end + +def fun_l19_n509() + fun_l20_n909 +end + +def fun_l19_n510() + fun_l20_n489 +end + +def fun_l19_n511() + fun_l20_n341 +end + +def fun_l19_n512() + fun_l20_n437 +end + +def fun_l19_n513() + fun_l20_n293 +end + +def fun_l19_n514() + fun_l20_n388 +end + +def fun_l19_n515() + fun_l20_n85 +end + +def fun_l19_n516() + fun_l20_n769 +end + +def fun_l19_n517() + fun_l20_n875 +end + +def fun_l19_n518() + fun_l20_n247 +end + +def fun_l19_n519() + fun_l20_n607 +end + +def fun_l19_n520() + fun_l20_n119 +end + +def fun_l19_n521() + fun_l20_n44 +end + +def fun_l19_n522() + fun_l20_n870 +end + +def fun_l19_n523() + fun_l20_n815 +end + +def fun_l19_n524() + fun_l20_n393 +end + +def fun_l19_n525() + fun_l20_n158 +end + +def fun_l19_n526() + fun_l20_n139 +end + +def fun_l19_n527() + fun_l20_n808 +end + +def fun_l19_n528() + fun_l20_n549 +end + +def fun_l19_n529() + fun_l20_n725 +end + +def fun_l19_n530() + fun_l20_n758 +end + +def fun_l19_n531() + fun_l20_n650 +end + +def fun_l19_n532() + fun_l20_n739 +end + +def fun_l19_n533() + fun_l20_n912 +end + +def fun_l19_n534() + fun_l20_n632 +end + +def fun_l19_n535() + fun_l20_n889 +end + +def fun_l19_n536() + fun_l20_n609 +end + +def fun_l19_n537() + fun_l20_n997 +end + +def fun_l19_n538() + fun_l20_n773 +end + +def fun_l19_n539() + fun_l20_n48 +end + +def fun_l19_n540() + fun_l20_n102 +end + +def fun_l19_n541() + fun_l20_n392 +end + +def fun_l19_n542() + fun_l20_n570 +end + +def fun_l19_n543() + fun_l20_n36 +end + +def fun_l19_n544() + fun_l20_n400 +end + +def fun_l19_n545() + fun_l20_n545 +end + +def fun_l19_n546() + fun_l20_n27 +end + +def fun_l19_n547() + fun_l20_n746 +end + +def fun_l19_n548() + fun_l20_n796 +end + +def fun_l19_n549() + fun_l20_n651 +end + +def fun_l19_n550() + fun_l20_n719 +end + +def fun_l19_n551() + fun_l20_n941 +end + +def fun_l19_n552() + fun_l20_n799 +end + +def fun_l19_n553() + fun_l20_n900 +end + +def fun_l19_n554() + fun_l20_n288 +end + +def fun_l19_n555() + fun_l20_n52 +end + +def fun_l19_n556() + fun_l20_n497 +end + +def fun_l19_n557() + fun_l20_n781 +end + +def fun_l19_n558() + fun_l20_n209 +end + +def fun_l19_n559() + fun_l20_n157 +end + +def fun_l19_n560() + fun_l20_n102 +end + +def fun_l19_n561() + fun_l20_n248 +end + +def fun_l19_n562() + fun_l20_n760 +end + +def fun_l19_n563() + fun_l20_n640 +end + +def fun_l19_n564() + fun_l20_n30 +end + +def fun_l19_n565() + fun_l20_n375 +end + +def fun_l19_n566() + fun_l20_n472 +end + +def fun_l19_n567() + fun_l20_n223 +end + +def fun_l19_n568() + fun_l20_n834 +end + +def fun_l19_n569() + fun_l20_n804 +end + +def fun_l19_n570() + fun_l20_n620 +end + +def fun_l19_n571() + fun_l20_n942 +end + +def fun_l19_n572() + fun_l20_n58 +end + +def fun_l19_n573() + fun_l20_n113 +end + +def fun_l19_n574() + fun_l20_n884 +end + +def fun_l19_n575() + fun_l20_n965 +end + +def fun_l19_n576() + fun_l20_n975 +end + +def fun_l19_n577() + fun_l20_n840 +end + +def fun_l19_n578() + fun_l20_n422 +end + +def fun_l19_n579() + fun_l20_n213 +end + +def fun_l19_n580() + fun_l20_n338 +end + +def fun_l19_n581() + fun_l20_n823 +end + +def fun_l19_n582() + fun_l20_n284 +end + +def fun_l19_n583() + fun_l20_n706 +end + +def fun_l19_n584() + fun_l20_n148 +end + +def fun_l19_n585() + fun_l20_n750 +end + +def fun_l19_n586() + fun_l20_n556 +end + +def fun_l19_n587() + fun_l20_n939 +end + +def fun_l19_n588() + fun_l20_n885 +end + +def fun_l19_n589() + fun_l20_n36 +end + +def fun_l19_n590() + fun_l20_n771 +end + +def fun_l19_n591() + fun_l20_n958 +end + +def fun_l19_n592() + fun_l20_n829 +end + +def fun_l19_n593() + fun_l20_n334 +end + +def fun_l19_n594() + fun_l20_n546 +end + +def fun_l19_n595() + fun_l20_n269 +end + +def fun_l19_n596() + fun_l20_n528 +end + +def fun_l19_n597() + fun_l20_n63 +end + +def fun_l19_n598() + fun_l20_n10 +end + +def fun_l19_n599() + fun_l20_n160 +end + +def fun_l19_n600() + fun_l20_n750 +end + +def fun_l19_n601() + fun_l20_n307 +end + +def fun_l19_n602() + fun_l20_n700 +end + +def fun_l19_n603() + fun_l20_n720 +end + +def fun_l19_n604() + fun_l20_n60 +end + +def fun_l19_n605() + fun_l20_n179 +end + +def fun_l19_n606() + fun_l20_n425 +end + +def fun_l19_n607() + fun_l20_n489 +end + +def fun_l19_n608() + fun_l20_n804 +end + +def fun_l19_n609() + fun_l20_n276 +end + +def fun_l19_n610() + fun_l20_n888 +end + +def fun_l19_n611() + fun_l20_n412 +end + +def fun_l19_n612() + fun_l20_n715 +end + +def fun_l19_n613() + fun_l20_n737 +end + +def fun_l19_n614() + fun_l20_n332 +end + +def fun_l19_n615() + fun_l20_n4 +end + +def fun_l19_n616() + fun_l20_n114 +end + +def fun_l19_n617() + fun_l20_n502 +end + +def fun_l19_n618() + fun_l20_n825 +end + +def fun_l19_n619() + fun_l20_n606 +end + +def fun_l19_n620() + fun_l20_n396 +end + +def fun_l19_n621() + fun_l20_n810 +end + +def fun_l19_n622() + fun_l20_n158 +end + +def fun_l19_n623() + fun_l20_n246 +end + +def fun_l19_n624() + fun_l20_n973 +end + +def fun_l19_n625() + fun_l20_n603 +end + +def fun_l19_n626() + fun_l20_n192 +end + +def fun_l19_n627() + fun_l20_n744 +end + +def fun_l19_n628() + fun_l20_n82 +end + +def fun_l19_n629() + fun_l20_n491 +end + +def fun_l19_n630() + fun_l20_n576 +end + +def fun_l19_n631() + fun_l20_n824 +end + +def fun_l19_n632() + fun_l20_n711 +end + +def fun_l19_n633() + fun_l20_n989 +end + +def fun_l19_n634() + fun_l20_n392 +end + +def fun_l19_n635() + fun_l20_n39 +end + +def fun_l19_n636() + fun_l20_n755 +end + +def fun_l19_n637() + fun_l20_n181 +end + +def fun_l19_n638() + fun_l20_n538 +end + +def fun_l19_n639() + fun_l20_n801 +end + +def fun_l19_n640() + fun_l20_n837 +end + +def fun_l19_n641() + fun_l20_n587 +end + +def fun_l19_n642() + fun_l20_n680 +end + +def fun_l19_n643() + fun_l20_n157 +end + +def fun_l19_n644() + fun_l20_n885 +end + +def fun_l19_n645() + fun_l20_n421 +end + +def fun_l19_n646() + fun_l20_n928 +end + +def fun_l19_n647() + fun_l20_n819 +end + +def fun_l19_n648() + fun_l20_n206 +end + +def fun_l19_n649() + fun_l20_n496 +end + +def fun_l19_n650() + fun_l20_n706 +end + +def fun_l19_n651() + fun_l20_n976 +end + +def fun_l19_n652() + fun_l20_n54 +end + +def fun_l19_n653() + fun_l20_n530 +end + +def fun_l19_n654() + fun_l20_n893 +end + +def fun_l19_n655() + fun_l20_n148 +end + +def fun_l19_n656() + fun_l20_n461 +end + +def fun_l19_n657() + fun_l20_n286 +end + +def fun_l19_n658() + fun_l20_n214 +end + +def fun_l19_n659() + fun_l20_n818 +end + +def fun_l19_n660() + fun_l20_n685 +end + +def fun_l19_n661() + fun_l20_n497 +end + +def fun_l19_n662() + fun_l20_n251 +end + +def fun_l19_n663() + fun_l20_n385 +end + +def fun_l19_n664() + fun_l20_n93 +end + +def fun_l19_n665() + fun_l20_n853 +end + +def fun_l19_n666() + fun_l20_n298 +end + +def fun_l19_n667() + fun_l20_n300 +end + +def fun_l19_n668() + fun_l20_n702 +end + +def fun_l19_n669() + fun_l20_n430 +end + +def fun_l19_n670() + fun_l20_n688 +end + +def fun_l19_n671() + fun_l20_n272 +end + +def fun_l19_n672() + fun_l20_n351 +end + +def fun_l19_n673() + fun_l20_n290 +end + +def fun_l19_n674() + fun_l20_n45 +end + +def fun_l19_n675() + fun_l20_n530 +end + +def fun_l19_n676() + fun_l20_n477 +end + +def fun_l19_n677() + fun_l20_n770 +end + +def fun_l19_n678() + fun_l20_n49 +end + +def fun_l19_n679() + fun_l20_n404 +end + +def fun_l19_n680() + fun_l20_n344 +end + +def fun_l19_n681() + fun_l20_n707 +end + +def fun_l19_n682() + fun_l20_n18 +end + +def fun_l19_n683() + fun_l20_n590 +end + +def fun_l19_n684() + fun_l20_n281 +end + +def fun_l19_n685() + fun_l20_n913 +end + +def fun_l19_n686() + fun_l20_n884 +end + +def fun_l19_n687() + fun_l20_n696 +end + +def fun_l19_n688() + fun_l20_n727 +end + +def fun_l19_n689() + fun_l20_n168 +end + +def fun_l19_n690() + fun_l20_n178 +end + +def fun_l19_n691() + fun_l20_n414 +end + +def fun_l19_n692() + fun_l20_n331 +end + +def fun_l19_n693() + fun_l20_n701 +end + +def fun_l19_n694() + fun_l20_n795 +end + +def fun_l19_n695() + fun_l20_n413 +end + +def fun_l19_n696() + fun_l20_n613 +end + +def fun_l19_n697() + fun_l20_n129 +end + +def fun_l19_n698() + fun_l20_n162 +end + +def fun_l19_n699() + fun_l20_n24 +end + +def fun_l19_n700() + fun_l20_n497 +end + +def fun_l19_n701() + fun_l20_n850 +end + +def fun_l19_n702() + fun_l20_n28 +end + +def fun_l19_n703() + fun_l20_n571 +end + +def fun_l19_n704() + fun_l20_n77 +end + +def fun_l19_n705() + fun_l20_n705 +end + +def fun_l19_n706() + fun_l20_n473 +end + +def fun_l19_n707() + fun_l20_n993 +end + +def fun_l19_n708() + fun_l20_n51 +end + +def fun_l19_n709() + fun_l20_n921 +end + +def fun_l19_n710() + fun_l20_n773 +end + +def fun_l19_n711() + fun_l20_n137 +end + +def fun_l19_n712() + fun_l20_n127 +end + +def fun_l19_n713() + fun_l20_n714 +end + +def fun_l19_n714() + fun_l20_n76 +end + +def fun_l19_n715() + fun_l20_n909 +end + +def fun_l19_n716() + fun_l20_n206 +end + +def fun_l19_n717() + fun_l20_n37 +end + +def fun_l19_n718() + fun_l20_n121 +end + +def fun_l19_n719() + fun_l20_n438 +end + +def fun_l19_n720() + fun_l20_n42 +end + +def fun_l19_n721() + fun_l20_n743 +end + +def fun_l19_n722() + fun_l20_n730 +end + +def fun_l19_n723() + fun_l20_n190 +end + +def fun_l19_n724() + fun_l20_n817 +end + +def fun_l19_n725() + fun_l20_n119 +end + +def fun_l19_n726() + fun_l20_n201 +end + +def fun_l19_n727() + fun_l20_n9 +end + +def fun_l19_n728() + fun_l20_n666 +end + +def fun_l19_n729() + fun_l20_n595 +end + +def fun_l19_n730() + fun_l20_n285 +end + +def fun_l19_n731() + fun_l20_n586 +end + +def fun_l19_n732() + fun_l20_n228 +end + +def fun_l19_n733() + fun_l20_n663 +end + +def fun_l19_n734() + fun_l20_n810 +end + +def fun_l19_n735() + fun_l20_n348 +end + +def fun_l19_n736() + fun_l20_n316 +end + +def fun_l19_n737() + fun_l20_n140 +end + +def fun_l19_n738() + fun_l20_n668 +end + +def fun_l19_n739() + fun_l20_n956 +end + +def fun_l19_n740() + fun_l20_n252 +end + +def fun_l19_n741() + fun_l20_n490 +end + +def fun_l19_n742() + fun_l20_n6 +end + +def fun_l19_n743() + fun_l20_n389 +end + +def fun_l19_n744() + fun_l20_n939 +end + +def fun_l19_n745() + fun_l20_n152 +end + +def fun_l19_n746() + fun_l20_n895 +end + +def fun_l19_n747() + fun_l20_n769 +end + +def fun_l19_n748() + fun_l20_n100 +end + +def fun_l19_n749() + fun_l20_n492 +end + +def fun_l19_n750() + fun_l20_n410 +end + +def fun_l19_n751() + fun_l20_n514 +end + +def fun_l19_n752() + fun_l20_n801 +end + +def fun_l19_n753() + fun_l20_n148 +end + +def fun_l19_n754() + fun_l20_n179 +end + +def fun_l19_n755() + fun_l20_n35 +end + +def fun_l19_n756() + fun_l20_n60 +end + +def fun_l19_n757() + fun_l20_n247 +end + +def fun_l19_n758() + fun_l20_n783 +end + +def fun_l19_n759() + fun_l20_n357 +end + +def fun_l19_n760() + fun_l20_n245 +end + +def fun_l19_n761() + fun_l20_n26 +end + +def fun_l19_n762() + fun_l20_n77 +end + +def fun_l19_n763() + fun_l20_n886 +end + +def fun_l19_n764() + fun_l20_n375 +end + +def fun_l19_n765() + fun_l20_n238 +end + +def fun_l19_n766() + fun_l20_n444 +end + +def fun_l19_n767() + fun_l20_n665 +end + +def fun_l19_n768() + fun_l20_n328 +end + +def fun_l19_n769() + fun_l20_n598 +end + +def fun_l19_n770() + fun_l20_n988 +end + +def fun_l19_n771() + fun_l20_n350 +end + +def fun_l19_n772() + fun_l20_n474 +end + +def fun_l19_n773() + fun_l20_n460 +end + +def fun_l19_n774() + fun_l20_n535 +end + +def fun_l19_n775() + fun_l20_n451 +end + +def fun_l19_n776() + fun_l20_n945 +end + +def fun_l19_n777() + fun_l20_n902 +end + +def fun_l19_n778() + fun_l20_n714 +end + +def fun_l19_n779() + fun_l20_n5 +end + +def fun_l19_n780() + fun_l20_n32 +end + +def fun_l19_n781() + fun_l20_n99 +end + +def fun_l19_n782() + fun_l20_n931 +end + +def fun_l19_n783() + fun_l20_n664 +end + +def fun_l19_n784() + fun_l20_n676 +end + +def fun_l19_n785() + fun_l20_n671 +end + +def fun_l19_n786() + fun_l20_n982 +end + +def fun_l19_n787() + fun_l20_n754 +end + +def fun_l19_n788() + fun_l20_n945 +end + +def fun_l19_n789() + fun_l20_n130 +end + +def fun_l19_n790() + fun_l20_n390 +end + +def fun_l19_n791() + fun_l20_n999 +end + +def fun_l19_n792() + fun_l20_n138 +end + +def fun_l19_n793() + fun_l20_n180 +end + +def fun_l19_n794() + fun_l20_n897 +end + +def fun_l19_n795() + fun_l20_n85 +end + +def fun_l19_n796() + fun_l20_n295 +end + +def fun_l19_n797() + fun_l20_n577 +end + +def fun_l19_n798() + fun_l20_n131 +end + +def fun_l19_n799() + fun_l20_n847 +end + +def fun_l19_n800() + fun_l20_n703 +end + +def fun_l19_n801() + fun_l20_n82 +end + +def fun_l19_n802() + fun_l20_n758 +end + +def fun_l19_n803() + fun_l20_n789 +end + +def fun_l19_n804() + fun_l20_n353 +end + +def fun_l19_n805() + fun_l20_n957 +end + +def fun_l19_n806() + fun_l20_n135 +end + +def fun_l19_n807() + fun_l20_n87 +end + +def fun_l19_n808() + fun_l20_n428 +end + +def fun_l19_n809() + fun_l20_n660 +end + +def fun_l19_n810() + fun_l20_n844 +end + +def fun_l19_n811() + fun_l20_n816 +end + +def fun_l19_n812() + fun_l20_n478 +end + +def fun_l19_n813() + fun_l20_n823 +end + +def fun_l19_n814() + fun_l20_n28 +end + +def fun_l19_n815() + fun_l20_n965 +end + +def fun_l19_n816() + fun_l20_n469 +end + +def fun_l19_n817() + fun_l20_n31 +end + +def fun_l19_n818() + fun_l20_n639 +end + +def fun_l19_n819() + fun_l20_n831 +end + +def fun_l19_n820() + fun_l20_n337 +end + +def fun_l19_n821() + fun_l20_n330 +end + +def fun_l19_n822() + fun_l20_n366 +end + +def fun_l19_n823() + fun_l20_n992 +end + +def fun_l19_n824() + fun_l20_n349 +end + +def fun_l19_n825() + fun_l20_n291 +end + +def fun_l19_n826() + fun_l20_n110 +end + +def fun_l19_n827() + fun_l20_n204 +end + +def fun_l19_n828() + fun_l20_n122 +end + +def fun_l19_n829() + fun_l20_n683 +end + +def fun_l19_n830() + fun_l20_n759 +end + +def fun_l19_n831() + fun_l20_n619 +end + +def fun_l19_n832() + fun_l20_n102 +end + +def fun_l19_n833() + fun_l20_n532 +end + +def fun_l19_n834() + fun_l20_n620 +end + +def fun_l19_n835() + fun_l20_n511 +end + +def fun_l19_n836() + fun_l20_n80 +end + +def fun_l19_n837() + fun_l20_n731 +end + +def fun_l19_n838() + fun_l20_n975 +end + +def fun_l19_n839() + fun_l20_n947 +end + +def fun_l19_n840() + fun_l20_n243 +end + +def fun_l19_n841() + fun_l20_n168 +end + +def fun_l19_n842() + fun_l20_n31 +end + +def fun_l19_n843() + fun_l20_n979 +end + +def fun_l19_n844() + fun_l20_n232 +end + +def fun_l19_n845() + fun_l20_n596 +end + +def fun_l19_n846() + fun_l20_n415 +end + +def fun_l19_n847() + fun_l20_n380 +end + +def fun_l19_n848() + fun_l20_n904 +end + +def fun_l19_n849() + fun_l20_n858 +end + +def fun_l19_n850() + fun_l20_n70 +end + +def fun_l19_n851() + fun_l20_n204 +end + +def fun_l19_n852() + fun_l20_n501 +end + +def fun_l19_n853() + fun_l20_n901 +end + +def fun_l19_n854() + fun_l20_n107 +end + +def fun_l19_n855() + fun_l20_n391 +end + +def fun_l19_n856() + fun_l20_n225 +end + +def fun_l19_n857() + fun_l20_n173 +end + +def fun_l19_n858() + fun_l20_n143 +end + +def fun_l19_n859() + fun_l20_n482 +end + +def fun_l19_n860() + fun_l20_n614 +end + +def fun_l19_n861() + fun_l20_n819 +end + +def fun_l19_n862() + fun_l20_n536 +end + +def fun_l19_n863() + fun_l20_n370 +end + +def fun_l19_n864() + fun_l20_n139 +end + +def fun_l19_n865() + fun_l20_n434 +end + +def fun_l19_n866() + fun_l20_n529 +end + +def fun_l19_n867() + fun_l20_n770 +end + +def fun_l19_n868() + fun_l20_n507 +end + +def fun_l19_n869() + fun_l20_n453 +end + +def fun_l19_n870() + fun_l20_n417 +end + +def fun_l19_n871() + fun_l20_n305 +end + +def fun_l19_n872() + fun_l20_n537 +end + +def fun_l19_n873() + fun_l20_n613 +end + +def fun_l19_n874() + fun_l20_n920 +end + +def fun_l19_n875() + fun_l20_n623 +end + +def fun_l19_n876() + fun_l20_n212 +end + +def fun_l19_n877() + fun_l20_n980 +end + +def fun_l19_n878() + fun_l20_n580 +end + +def fun_l19_n879() + fun_l20_n112 +end + +def fun_l19_n880() + fun_l20_n460 +end + +def fun_l19_n881() + fun_l20_n364 +end + +def fun_l19_n882() + fun_l20_n685 +end + +def fun_l19_n883() + fun_l20_n429 +end + +def fun_l19_n884() + fun_l20_n90 +end + +def fun_l19_n885() + fun_l20_n448 +end + +def fun_l19_n886() + fun_l20_n898 +end + +def fun_l19_n887() + fun_l20_n10 +end + +def fun_l19_n888() + fun_l20_n618 +end + +def fun_l19_n889() + fun_l20_n447 +end + +def fun_l19_n890() + fun_l20_n414 +end + +def fun_l19_n891() + fun_l20_n570 +end + +def fun_l19_n892() + fun_l20_n828 +end + +def fun_l19_n893() + fun_l20_n367 +end + +def fun_l19_n894() + fun_l20_n897 +end + +def fun_l19_n895() + fun_l20_n978 +end + +def fun_l19_n896() + fun_l20_n57 +end + +def fun_l19_n897() + fun_l20_n61 +end + +def fun_l19_n898() + fun_l20_n483 +end + +def fun_l19_n899() + fun_l20_n407 +end + +def fun_l19_n900() + fun_l20_n369 +end + +def fun_l19_n901() + fun_l20_n635 +end + +def fun_l19_n902() + fun_l20_n800 +end + +def fun_l19_n903() + fun_l20_n748 +end + +def fun_l19_n904() + fun_l20_n436 +end + +def fun_l19_n905() + fun_l20_n990 +end + +def fun_l19_n906() + fun_l20_n484 +end + +def fun_l19_n907() + fun_l20_n530 +end + +def fun_l19_n908() + fun_l20_n692 +end + +def fun_l19_n909() + fun_l20_n356 +end + +def fun_l19_n910() + fun_l20_n786 +end + +def fun_l19_n911() + fun_l20_n894 +end + +def fun_l19_n912() + fun_l20_n217 +end + +def fun_l19_n913() + fun_l20_n495 +end + +def fun_l19_n914() + fun_l20_n878 +end + +def fun_l19_n915() + fun_l20_n166 +end + +def fun_l19_n916() + fun_l20_n558 +end + +def fun_l19_n917() + fun_l20_n704 +end + +def fun_l19_n918() + fun_l20_n996 +end + +def fun_l19_n919() + fun_l20_n302 +end + +def fun_l19_n920() + fun_l20_n44 +end + +def fun_l19_n921() + fun_l20_n694 +end + +def fun_l19_n922() + fun_l20_n221 +end + +def fun_l19_n923() + fun_l20_n419 +end + +def fun_l19_n924() + fun_l20_n400 +end + +def fun_l19_n925() + fun_l20_n306 +end + +def fun_l19_n926() + fun_l20_n785 +end + +def fun_l19_n927() + fun_l20_n851 +end + +def fun_l19_n928() + fun_l20_n769 +end + +def fun_l19_n929() + fun_l20_n547 +end + +def fun_l19_n930() + fun_l20_n887 +end + +def fun_l19_n931() + fun_l20_n413 +end + +def fun_l19_n932() + fun_l20_n253 +end + +def fun_l19_n933() + fun_l20_n37 +end + +def fun_l19_n934() + fun_l20_n405 +end + +def fun_l19_n935() + fun_l20_n926 +end + +def fun_l19_n936() + fun_l20_n864 +end + +def fun_l19_n937() + fun_l20_n231 +end + +def fun_l19_n938() + fun_l20_n688 +end + +def fun_l19_n939() + fun_l20_n144 +end + +def fun_l19_n940() + fun_l20_n606 +end + +def fun_l19_n941() + fun_l20_n180 +end + +def fun_l19_n942() + fun_l20_n103 +end + +def fun_l19_n943() + fun_l20_n314 +end + +def fun_l19_n944() + fun_l20_n966 +end + +def fun_l19_n945() + fun_l20_n15 +end + +def fun_l19_n946() + fun_l20_n343 +end + +def fun_l19_n947() + fun_l20_n388 +end + +def fun_l19_n948() + fun_l20_n868 +end + +def fun_l19_n949() + fun_l20_n939 +end + +def fun_l19_n950() + fun_l20_n364 +end + +def fun_l19_n951() + fun_l20_n739 +end + +def fun_l19_n952() + fun_l20_n725 +end + +def fun_l19_n953() + fun_l20_n463 +end + +def fun_l19_n954() + fun_l20_n737 +end + +def fun_l19_n955() + fun_l20_n83 +end + +def fun_l19_n956() + fun_l20_n807 +end + +def fun_l19_n957() + fun_l20_n710 +end + +def fun_l19_n958() + fun_l20_n48 +end + +def fun_l19_n959() + fun_l20_n82 +end + +def fun_l19_n960() + fun_l20_n330 +end + +def fun_l19_n961() + fun_l20_n378 +end + +def fun_l19_n962() + fun_l20_n35 +end + +def fun_l19_n963() + fun_l20_n191 +end + +def fun_l19_n964() + fun_l20_n282 +end + +def fun_l19_n965() + fun_l20_n222 +end + +def fun_l19_n966() + fun_l20_n416 +end + +def fun_l19_n967() + fun_l20_n304 +end + +def fun_l19_n968() + fun_l20_n325 +end + +def fun_l19_n969() + fun_l20_n374 +end + +def fun_l19_n970() + fun_l20_n25 +end + +def fun_l19_n971() + fun_l20_n815 +end + +def fun_l19_n972() + fun_l20_n272 +end + +def fun_l19_n973() + fun_l20_n57 +end + +def fun_l19_n974() + fun_l20_n567 +end + +def fun_l19_n975() + fun_l20_n995 +end + +def fun_l19_n976() + fun_l20_n390 +end + +def fun_l19_n977() + fun_l20_n706 +end + +def fun_l19_n978() + fun_l20_n496 +end + +def fun_l19_n979() + fun_l20_n685 +end + +def fun_l19_n980() + fun_l20_n277 +end + +def fun_l19_n981() + fun_l20_n933 +end + +def fun_l19_n982() + fun_l20_n958 +end + +def fun_l19_n983() + fun_l20_n9 +end + +def fun_l19_n984() + fun_l20_n455 +end + +def fun_l19_n985() + fun_l20_n824 +end + +def fun_l19_n986() + fun_l20_n855 +end + +def fun_l19_n987() + fun_l20_n561 +end + +def fun_l19_n988() + fun_l20_n66 +end + +def fun_l19_n989() + fun_l20_n836 +end + +def fun_l19_n990() + fun_l20_n466 +end + +def fun_l19_n991() + fun_l20_n902 +end + +def fun_l19_n992() + fun_l20_n196 +end + +def fun_l19_n993() + fun_l20_n488 +end + +def fun_l19_n994() + fun_l20_n490 +end + +def fun_l19_n995() + fun_l20_n463 +end + +def fun_l19_n996() + fun_l20_n222 +end + +def fun_l19_n997() + fun_l20_n935 +end + +def fun_l19_n998() + fun_l20_n664 +end + +def fun_l19_n999() + fun_l20_n44 +end + +def fun_l20_n0() + fun_l21_n583 +end + +def fun_l20_n1() + fun_l21_n600 +end + +def fun_l20_n2() + fun_l21_n308 +end + +def fun_l20_n3() + fun_l21_n395 +end + +def fun_l20_n4() + fun_l21_n468 +end + +def fun_l20_n5() + fun_l21_n340 +end + +def fun_l20_n6() + fun_l21_n647 +end + +def fun_l20_n7() + fun_l21_n53 +end + +def fun_l20_n8() + fun_l21_n231 +end + +def fun_l20_n9() + fun_l21_n965 +end + +def fun_l20_n10() + fun_l21_n82 +end + +def fun_l20_n11() + fun_l21_n464 +end + +def fun_l20_n12() + fun_l21_n694 +end + +def fun_l20_n13() + fun_l21_n398 +end + +def fun_l20_n14() + fun_l21_n197 +end + +def fun_l20_n15() + fun_l21_n447 +end + +def fun_l20_n16() + fun_l21_n976 +end + +def fun_l20_n17() + fun_l21_n421 +end + +def fun_l20_n18() + fun_l21_n163 +end + +def fun_l20_n19() + fun_l21_n467 +end + +def fun_l20_n20() + fun_l21_n210 +end + +def fun_l20_n21() + fun_l21_n837 +end + +def fun_l20_n22() + fun_l21_n257 +end + +def fun_l20_n23() + fun_l21_n818 +end + +def fun_l20_n24() + fun_l21_n585 +end + +def fun_l20_n25() + fun_l21_n125 +end + +def fun_l20_n26() + fun_l21_n740 +end + +def fun_l20_n27() + fun_l21_n771 +end + +def fun_l20_n28() + fun_l21_n559 +end + +def fun_l20_n29() + fun_l21_n591 +end + +def fun_l20_n30() + fun_l21_n37 +end + +def fun_l20_n31() + fun_l21_n796 +end + +def fun_l20_n32() + fun_l21_n762 +end + +def fun_l20_n33() + fun_l21_n26 +end + +def fun_l20_n34() + fun_l21_n70 +end + +def fun_l20_n35() + fun_l21_n789 +end + +def fun_l20_n36() + fun_l21_n389 +end + +def fun_l20_n37() + fun_l21_n769 +end + +def fun_l20_n38() + fun_l21_n296 +end + +def fun_l20_n39() + fun_l21_n131 +end + +def fun_l20_n40() + fun_l21_n405 +end + +def fun_l20_n41() + fun_l21_n546 +end + +def fun_l20_n42() + fun_l21_n232 +end + +def fun_l20_n43() + fun_l21_n538 +end + +def fun_l20_n44() + fun_l21_n55 +end + +def fun_l20_n45() + fun_l21_n962 +end + +def fun_l20_n46() + fun_l21_n664 +end + +def fun_l20_n47() + fun_l21_n443 +end + +def fun_l20_n48() + fun_l21_n854 +end + +def fun_l20_n49() + fun_l21_n392 +end + +def fun_l20_n50() + fun_l21_n699 +end + +def fun_l20_n51() + fun_l21_n748 +end + +def fun_l20_n52() + fun_l21_n891 +end + +def fun_l20_n53() + fun_l21_n411 +end + +def fun_l20_n54() + fun_l21_n798 +end + +def fun_l20_n55() + fun_l21_n99 +end + +def fun_l20_n56() + fun_l21_n538 +end + +def fun_l20_n57() + fun_l21_n473 +end + +def fun_l20_n58() + fun_l21_n498 +end + +def fun_l20_n59() + fun_l21_n769 +end + +def fun_l20_n60() + fun_l21_n117 +end + +def fun_l20_n61() + fun_l21_n487 +end + +def fun_l20_n62() + fun_l21_n538 +end + +def fun_l20_n63() + fun_l21_n312 +end + +def fun_l20_n64() + fun_l21_n642 +end + +def fun_l20_n65() + fun_l21_n877 +end + +def fun_l20_n66() + fun_l21_n481 +end + +def fun_l20_n67() + fun_l21_n252 +end + +def fun_l20_n68() + fun_l21_n367 +end + +def fun_l20_n69() + fun_l21_n438 +end + +def fun_l20_n70() + fun_l21_n811 +end + +def fun_l20_n71() + fun_l21_n807 +end + +def fun_l20_n72() + fun_l21_n410 +end + +def fun_l20_n73() + fun_l21_n590 +end + +def fun_l20_n74() + fun_l21_n963 +end + +def fun_l20_n75() + fun_l21_n103 +end + +def fun_l20_n76() + fun_l21_n786 +end + +def fun_l20_n77() + fun_l21_n256 +end + +def fun_l20_n78() + fun_l21_n306 +end + +def fun_l20_n79() + fun_l21_n248 +end + +def fun_l20_n80() + fun_l21_n931 +end + +def fun_l20_n81() + fun_l21_n926 +end + +def fun_l20_n82() + fun_l21_n702 +end + +def fun_l20_n83() + fun_l21_n611 +end + +def fun_l20_n84() + fun_l21_n279 +end + +def fun_l20_n85() + fun_l21_n977 +end + +def fun_l20_n86() + fun_l21_n239 +end + +def fun_l20_n87() + fun_l21_n370 +end + +def fun_l20_n88() + fun_l21_n652 +end + +def fun_l20_n89() + fun_l21_n956 +end + +def fun_l20_n90() + fun_l21_n998 +end + +def fun_l20_n91() + fun_l21_n523 +end + +def fun_l20_n92() + fun_l21_n376 +end + +def fun_l20_n93() + fun_l21_n604 +end + +def fun_l20_n94() + fun_l21_n908 +end + +def fun_l20_n95() + fun_l21_n716 +end + +def fun_l20_n96() + fun_l21_n9 +end + +def fun_l20_n97() + fun_l21_n571 +end + +def fun_l20_n98() + fun_l21_n787 +end + +def fun_l20_n99() + fun_l21_n453 +end + +def fun_l20_n100() + fun_l21_n899 +end + +def fun_l20_n101() + fun_l21_n491 +end + +def fun_l20_n102() + fun_l21_n47 +end + +def fun_l20_n103() + fun_l21_n892 +end + +def fun_l20_n104() + fun_l21_n974 +end + +def fun_l20_n105() + fun_l21_n993 +end + +def fun_l20_n106() + fun_l21_n625 +end + +def fun_l20_n107() + fun_l21_n743 +end + +def fun_l20_n108() + fun_l21_n266 +end + +def fun_l20_n109() + fun_l21_n650 +end + +def fun_l20_n110() + fun_l21_n642 +end + +def fun_l20_n111() + fun_l21_n905 +end + +def fun_l20_n112() + fun_l21_n225 +end + +def fun_l20_n113() + fun_l21_n857 +end + +def fun_l20_n114() + fun_l21_n82 +end + +def fun_l20_n115() + fun_l21_n166 +end + +def fun_l20_n116() + fun_l21_n844 +end + +def fun_l20_n117() + fun_l21_n619 +end + +def fun_l20_n118() + fun_l21_n743 +end + +def fun_l20_n119() + fun_l21_n69 +end + +def fun_l20_n120() + fun_l21_n410 +end + +def fun_l20_n121() + fun_l21_n364 +end + +def fun_l20_n122() + fun_l21_n186 +end + +def fun_l20_n123() + fun_l21_n750 +end + +def fun_l20_n124() + fun_l21_n683 +end + +def fun_l20_n125() + fun_l21_n576 +end + +def fun_l20_n126() + fun_l21_n287 +end + +def fun_l20_n127() + fun_l21_n483 +end + +def fun_l20_n128() + fun_l21_n738 +end + +def fun_l20_n129() + fun_l21_n779 +end + +def fun_l20_n130() + fun_l21_n209 +end + +def fun_l20_n131() + fun_l21_n652 +end + +def fun_l20_n132() + fun_l21_n583 +end + +def fun_l20_n133() + fun_l21_n389 +end + +def fun_l20_n134() + fun_l21_n289 +end + +def fun_l20_n135() + fun_l21_n993 +end + +def fun_l20_n136() + fun_l21_n216 +end + +def fun_l20_n137() + fun_l21_n118 +end + +def fun_l20_n138() + fun_l21_n484 +end + +def fun_l20_n139() + fun_l21_n602 +end + +def fun_l20_n140() + fun_l21_n714 +end + +def fun_l20_n141() + fun_l21_n247 +end + +def fun_l20_n142() + fun_l21_n27 +end + +def fun_l20_n143() + fun_l21_n939 +end + +def fun_l20_n144() + fun_l21_n565 +end + +def fun_l20_n145() + fun_l21_n869 +end + +def fun_l20_n146() + fun_l21_n569 +end + +def fun_l20_n147() + fun_l21_n876 +end + +def fun_l20_n148() + fun_l21_n796 +end + +def fun_l20_n149() + fun_l21_n754 +end + +def fun_l20_n150() + fun_l21_n664 +end + +def fun_l20_n151() + fun_l21_n836 +end + +def fun_l20_n152() + fun_l21_n389 +end + +def fun_l20_n153() + fun_l21_n111 +end + +def fun_l20_n154() + fun_l21_n361 +end + +def fun_l20_n155() + fun_l21_n733 +end + +def fun_l20_n156() + fun_l21_n215 +end + +def fun_l20_n157() + fun_l21_n509 +end + +def fun_l20_n158() + fun_l21_n12 +end + +def fun_l20_n159() + fun_l21_n351 +end + +def fun_l20_n160() + fun_l21_n872 +end + +def fun_l20_n161() + fun_l21_n888 +end + +def fun_l20_n162() + fun_l21_n126 +end + +def fun_l20_n163() + fun_l21_n681 +end + +def fun_l20_n164() + fun_l21_n160 +end + +def fun_l20_n165() + fun_l21_n917 +end + +def fun_l20_n166() + fun_l21_n255 +end + +def fun_l20_n167() + fun_l21_n37 +end + +def fun_l20_n168() + fun_l21_n949 +end + +def fun_l20_n169() + fun_l21_n925 +end + +def fun_l20_n170() + fun_l21_n921 +end + +def fun_l20_n171() + fun_l21_n123 +end + +def fun_l20_n172() + fun_l21_n783 +end + +def fun_l20_n173() + fun_l21_n45 +end + +def fun_l20_n174() + fun_l21_n994 +end + +def fun_l20_n175() + fun_l21_n745 +end + +def fun_l20_n176() + fun_l21_n122 +end + +def fun_l20_n177() + fun_l21_n25 +end + +def fun_l20_n178() + fun_l21_n594 +end + +def fun_l20_n179() + fun_l21_n115 +end + +def fun_l20_n180() + fun_l21_n274 +end + +def fun_l20_n181() + fun_l21_n423 +end + +def fun_l20_n182() + fun_l21_n68 +end + +def fun_l20_n183() + fun_l21_n598 +end + +def fun_l20_n184() + fun_l21_n640 +end + +def fun_l20_n185() + fun_l21_n810 +end + +def fun_l20_n186() + fun_l21_n150 +end + +def fun_l20_n187() + fun_l21_n4 +end + +def fun_l20_n188() + fun_l21_n487 +end + +def fun_l20_n189() + fun_l21_n327 +end + +def fun_l20_n190() + fun_l21_n652 +end + +def fun_l20_n191() + fun_l21_n913 +end + +def fun_l20_n192() + fun_l21_n323 +end + +def fun_l20_n193() + fun_l21_n193 +end + +def fun_l20_n194() + fun_l21_n527 +end + +def fun_l20_n195() + fun_l21_n123 +end + +def fun_l20_n196() + fun_l21_n568 +end + +def fun_l20_n197() + fun_l21_n629 +end + +def fun_l20_n198() + fun_l21_n727 +end + +def fun_l20_n199() + fun_l21_n470 +end + +def fun_l20_n200() + fun_l21_n608 +end + +def fun_l20_n201() + fun_l21_n941 +end + +def fun_l20_n202() + fun_l21_n256 +end + +def fun_l20_n203() + fun_l21_n624 +end + +def fun_l20_n204() + fun_l21_n714 +end + +def fun_l20_n205() + fun_l21_n754 +end + +def fun_l20_n206() + fun_l21_n513 +end + +def fun_l20_n207() + fun_l21_n730 +end + +def fun_l20_n208() + fun_l21_n132 +end + +def fun_l20_n209() + fun_l21_n205 +end + +def fun_l20_n210() + fun_l21_n549 +end + +def fun_l20_n211() + fun_l21_n713 +end + +def fun_l20_n212() + fun_l21_n51 +end + +def fun_l20_n213() + fun_l21_n712 +end + +def fun_l20_n214() + fun_l21_n439 +end + +def fun_l20_n215() + fun_l21_n969 +end + +def fun_l20_n216() + fun_l21_n338 +end + +def fun_l20_n217() + fun_l21_n852 +end + +def fun_l20_n218() + fun_l21_n935 +end + +def fun_l20_n219() + fun_l21_n935 +end + +def fun_l20_n220() + fun_l21_n967 +end + +def fun_l20_n221() + fun_l21_n195 +end + +def fun_l20_n222() + fun_l21_n556 +end + +def fun_l20_n223() + fun_l21_n669 +end + +def fun_l20_n224() + fun_l21_n874 +end + +def fun_l20_n225() + fun_l21_n985 +end + +def fun_l20_n226() + fun_l21_n769 +end + +def fun_l20_n227() + fun_l21_n482 +end + +def fun_l20_n228() + fun_l21_n268 +end + +def fun_l20_n229() + fun_l21_n161 +end + +def fun_l20_n230() + fun_l21_n383 +end + +def fun_l20_n231() + fun_l21_n100 +end + +def fun_l20_n232() + fun_l21_n285 +end + +def fun_l20_n233() + fun_l21_n255 +end + +def fun_l20_n234() + fun_l21_n214 +end + +def fun_l20_n235() + fun_l21_n206 +end + +def fun_l20_n236() + fun_l21_n990 +end + +def fun_l20_n237() + fun_l21_n24 +end + +def fun_l20_n238() + fun_l21_n531 +end + +def fun_l20_n239() + fun_l21_n171 +end + +def fun_l20_n240() + fun_l21_n859 +end + +def fun_l20_n241() + fun_l21_n342 +end + +def fun_l20_n242() + fun_l21_n724 +end + +def fun_l20_n243() + fun_l21_n55 +end + +def fun_l20_n244() + fun_l21_n404 +end + +def fun_l20_n245() + fun_l21_n615 +end + +def fun_l20_n246() + fun_l21_n692 +end + +def fun_l20_n247() + fun_l21_n851 +end + +def fun_l20_n248() + fun_l21_n715 +end + +def fun_l20_n249() + fun_l21_n723 +end + +def fun_l20_n250() + fun_l21_n929 +end + +def fun_l20_n251() + fun_l21_n26 +end + +def fun_l20_n252() + fun_l21_n314 +end + +def fun_l20_n253() + fun_l21_n182 +end + +def fun_l20_n254() + fun_l21_n889 +end + +def fun_l20_n255() + fun_l21_n725 +end + +def fun_l20_n256() + fun_l21_n538 +end + +def fun_l20_n257() + fun_l21_n303 +end + +def fun_l20_n258() + fun_l21_n843 +end + +def fun_l20_n259() + fun_l21_n977 +end + +def fun_l20_n260() + fun_l21_n438 +end + +def fun_l20_n261() + fun_l21_n772 +end + +def fun_l20_n262() + fun_l21_n432 +end + +def fun_l20_n263() + fun_l21_n204 +end + +def fun_l20_n264() + fun_l21_n853 +end + +def fun_l20_n265() + fun_l21_n7 +end + +def fun_l20_n266() + fun_l21_n171 +end + +def fun_l20_n267() + fun_l21_n907 +end + +def fun_l20_n268() + fun_l21_n450 +end + +def fun_l20_n269() + fun_l21_n836 +end + +def fun_l20_n270() + fun_l21_n118 +end + +def fun_l20_n271() + fun_l21_n782 +end + +def fun_l20_n272() + fun_l21_n160 +end + +def fun_l20_n273() + fun_l21_n73 +end + +def fun_l20_n274() + fun_l21_n339 +end + +def fun_l20_n275() + fun_l21_n257 +end + +def fun_l20_n276() + fun_l21_n860 +end + +def fun_l20_n277() + fun_l21_n837 +end + +def fun_l20_n278() + fun_l21_n936 +end + +def fun_l20_n279() + fun_l21_n627 +end + +def fun_l20_n280() + fun_l21_n45 +end + +def fun_l20_n281() + fun_l21_n934 +end + +def fun_l20_n282() + fun_l21_n213 +end + +def fun_l20_n283() + fun_l21_n629 +end + +def fun_l20_n284() + fun_l21_n944 +end + +def fun_l20_n285() + fun_l21_n44 +end + +def fun_l20_n286() + fun_l21_n306 +end + +def fun_l20_n287() + fun_l21_n259 +end + +def fun_l20_n288() + fun_l21_n805 +end + +def fun_l20_n289() + fun_l21_n118 +end + +def fun_l20_n290() + fun_l21_n456 +end + +def fun_l20_n291() + fun_l21_n11 +end + +def fun_l20_n292() + fun_l21_n138 +end + +def fun_l20_n293() + fun_l21_n110 +end + +def fun_l20_n294() + fun_l21_n165 +end + +def fun_l20_n295() + fun_l21_n129 +end + +def fun_l20_n296() + fun_l21_n731 +end + +def fun_l20_n297() + fun_l21_n219 +end + +def fun_l20_n298() + fun_l21_n175 +end + +def fun_l20_n299() + fun_l21_n497 +end + +def fun_l20_n300() + fun_l21_n154 +end + +def fun_l20_n301() + fun_l21_n446 +end + +def fun_l20_n302() + fun_l21_n890 +end + +def fun_l20_n303() + fun_l21_n325 +end + +def fun_l20_n304() + fun_l21_n616 +end + +def fun_l20_n305() + fun_l21_n743 +end + +def fun_l20_n306() + fun_l21_n327 +end + +def fun_l20_n307() + fun_l21_n890 +end + +def fun_l20_n308() + fun_l21_n289 +end + +def fun_l20_n309() + fun_l21_n150 +end + +def fun_l20_n310() + fun_l21_n22 +end + +def fun_l20_n311() + fun_l21_n290 +end + +def fun_l20_n312() + fun_l21_n780 +end + +def fun_l20_n313() + fun_l21_n204 +end + +def fun_l20_n314() + fun_l21_n204 +end + +def fun_l20_n315() + fun_l21_n841 +end + +def fun_l20_n316() + fun_l21_n990 +end + +def fun_l20_n317() + fun_l21_n574 +end + +def fun_l20_n318() + fun_l21_n543 +end + +def fun_l20_n319() + fun_l21_n388 +end + +def fun_l20_n320() + fun_l21_n44 +end + +def fun_l20_n321() + fun_l21_n65 +end + +def fun_l20_n322() + fun_l21_n952 +end + +def fun_l20_n323() + fun_l21_n633 +end + +def fun_l20_n324() + fun_l21_n729 +end + +def fun_l20_n325() + fun_l21_n356 +end + +def fun_l20_n326() + fun_l21_n968 +end + +def fun_l20_n327() + fun_l21_n92 +end + +def fun_l20_n328() + fun_l21_n285 +end + +def fun_l20_n329() + fun_l21_n341 +end + +def fun_l20_n330() + fun_l21_n818 +end + +def fun_l20_n331() + fun_l21_n373 +end + +def fun_l20_n332() + fun_l21_n166 +end + +def fun_l20_n333() + fun_l21_n618 +end + +def fun_l20_n334() + fun_l21_n160 +end + +def fun_l20_n335() + fun_l21_n965 +end + +def fun_l20_n336() + fun_l21_n436 +end + +def fun_l20_n337() + fun_l21_n244 +end + +def fun_l20_n338() + fun_l21_n425 +end + +def fun_l20_n339() + fun_l21_n576 +end + +def fun_l20_n340() + fun_l21_n789 +end + +def fun_l20_n341() + fun_l21_n559 +end + +def fun_l20_n342() + fun_l21_n766 +end + +def fun_l20_n343() + fun_l21_n131 +end + +def fun_l20_n344() + fun_l21_n806 +end + +def fun_l20_n345() + fun_l21_n624 +end + +def fun_l20_n346() + fun_l21_n342 +end + +def fun_l20_n347() + fun_l21_n567 +end + +def fun_l20_n348() + fun_l21_n569 +end + +def fun_l20_n349() + fun_l21_n623 +end + +def fun_l20_n350() + fun_l21_n984 +end + +def fun_l20_n351() + fun_l21_n931 +end + +def fun_l20_n352() + fun_l21_n48 +end + +def fun_l20_n353() + fun_l21_n962 +end + +def fun_l20_n354() + fun_l21_n757 +end + +def fun_l20_n355() + fun_l21_n844 +end + +def fun_l20_n356() + fun_l21_n217 +end + +def fun_l20_n357() + fun_l21_n933 +end + +def fun_l20_n358() + fun_l21_n579 +end + +def fun_l20_n359() + fun_l21_n342 +end + +def fun_l20_n360() + fun_l21_n975 +end + +def fun_l20_n361() + fun_l21_n177 +end + +def fun_l20_n362() + fun_l21_n491 +end + +def fun_l20_n363() + fun_l21_n637 +end + +def fun_l20_n364() + fun_l21_n505 +end + +def fun_l20_n365() + fun_l21_n784 +end + +def fun_l20_n366() + fun_l21_n62 +end + +def fun_l20_n367() + fun_l21_n478 +end + +def fun_l20_n368() + fun_l21_n369 +end + +def fun_l20_n369() + fun_l21_n105 +end + +def fun_l20_n370() + fun_l21_n352 +end + +def fun_l20_n371() + fun_l21_n537 +end + +def fun_l20_n372() + fun_l21_n180 +end + +def fun_l20_n373() + fun_l21_n216 +end + +def fun_l20_n374() + fun_l21_n938 +end + +def fun_l20_n375() + fun_l21_n441 +end + +def fun_l20_n376() + fun_l21_n308 +end + +def fun_l20_n377() + fun_l21_n544 +end + +def fun_l20_n378() + fun_l21_n505 +end + +def fun_l20_n379() + fun_l21_n681 +end + +def fun_l20_n380() + fun_l21_n844 +end + +def fun_l20_n381() + fun_l21_n269 +end + +def fun_l20_n382() + fun_l21_n195 +end + +def fun_l20_n383() + fun_l21_n214 +end + +def fun_l20_n384() + fun_l21_n206 +end + +def fun_l20_n385() + fun_l21_n807 +end + +def fun_l20_n386() + fun_l21_n932 +end + +def fun_l20_n387() + fun_l21_n245 +end + +def fun_l20_n388() + fun_l21_n942 +end + +def fun_l20_n389() + fun_l21_n618 +end + +def fun_l20_n390() + fun_l21_n684 +end + +def fun_l20_n391() + fun_l21_n536 +end + +def fun_l20_n392() + fun_l21_n899 +end + +def fun_l20_n393() + fun_l21_n775 +end + +def fun_l20_n394() + fun_l21_n634 +end + +def fun_l20_n395() + fun_l21_n870 +end + +def fun_l20_n396() + fun_l21_n882 +end + +def fun_l20_n397() + fun_l21_n317 +end + +def fun_l20_n398() + fun_l21_n162 +end + +def fun_l20_n399() + fun_l21_n446 +end + +def fun_l20_n400() + fun_l21_n716 +end + +def fun_l20_n401() + fun_l21_n869 +end + +def fun_l20_n402() + fun_l21_n965 +end + +def fun_l20_n403() + fun_l21_n616 +end + +def fun_l20_n404() + fun_l21_n385 +end + +def fun_l20_n405() + fun_l21_n964 +end + +def fun_l20_n406() + fun_l21_n360 +end + +def fun_l20_n407() + fun_l21_n432 +end + +def fun_l20_n408() + fun_l21_n40 +end + +def fun_l20_n409() + fun_l21_n734 +end + +def fun_l20_n410() + fun_l21_n978 +end + +def fun_l20_n411() + fun_l21_n721 +end + +def fun_l20_n412() + fun_l21_n941 +end + +def fun_l20_n413() + fun_l21_n315 +end + +def fun_l20_n414() + fun_l21_n242 +end + +def fun_l20_n415() + fun_l21_n153 +end + +def fun_l20_n416() + fun_l21_n999 +end + +def fun_l20_n417() + fun_l21_n219 +end + +def fun_l20_n418() + fun_l21_n809 +end + +def fun_l20_n419() + fun_l21_n139 +end + +def fun_l20_n420() + fun_l21_n311 +end + +def fun_l20_n421() + fun_l21_n460 +end + +def fun_l20_n422() + fun_l21_n0 +end + +def fun_l20_n423() + fun_l21_n863 +end + +def fun_l20_n424() + fun_l21_n216 +end + +def fun_l20_n425() + fun_l21_n1 +end + +def fun_l20_n426() + fun_l21_n829 +end + +def fun_l20_n427() + fun_l21_n844 +end + +def fun_l20_n428() + fun_l21_n941 +end + +def fun_l20_n429() + fun_l21_n344 +end + +def fun_l20_n430() + fun_l21_n443 +end + +def fun_l20_n431() + fun_l21_n549 +end + +def fun_l20_n432() + fun_l21_n654 +end + +def fun_l20_n433() + fun_l21_n167 +end + +def fun_l20_n434() + fun_l21_n392 +end + +def fun_l20_n435() + fun_l21_n570 +end + +def fun_l20_n436() + fun_l21_n370 +end + +def fun_l20_n437() + fun_l21_n65 +end + +def fun_l20_n438() + fun_l21_n78 +end + +def fun_l20_n439() + fun_l21_n271 +end + +def fun_l20_n440() + fun_l21_n606 +end + +def fun_l20_n441() + fun_l21_n25 +end + +def fun_l20_n442() + fun_l21_n629 +end + +def fun_l20_n443() + fun_l21_n294 +end + +def fun_l20_n444() + fun_l21_n928 +end + +def fun_l20_n445() + fun_l21_n596 +end + +def fun_l20_n446() + fun_l21_n630 +end + +def fun_l20_n447() + fun_l21_n849 +end + +def fun_l20_n448() + fun_l21_n239 +end + +def fun_l20_n449() + fun_l21_n641 +end + +def fun_l20_n450() + fun_l21_n333 +end + +def fun_l20_n451() + fun_l21_n86 +end + +def fun_l20_n452() + fun_l21_n68 +end + +def fun_l20_n453() + fun_l21_n28 +end + +def fun_l20_n454() + fun_l21_n644 +end + +def fun_l20_n455() + fun_l21_n282 +end + +def fun_l20_n456() + fun_l21_n3 +end + +def fun_l20_n457() + fun_l21_n594 +end + +def fun_l20_n458() + fun_l21_n173 +end + +def fun_l20_n459() + fun_l21_n986 +end + +def fun_l20_n460() + fun_l21_n597 +end + +def fun_l20_n461() + fun_l21_n488 +end + +def fun_l20_n462() + fun_l21_n288 +end + +def fun_l20_n463() + fun_l21_n729 +end + +def fun_l20_n464() + fun_l21_n985 +end + +def fun_l20_n465() + fun_l21_n794 +end + +def fun_l20_n466() + fun_l21_n405 +end + +def fun_l20_n467() + fun_l21_n985 +end + +def fun_l20_n468() + fun_l21_n596 +end + +def fun_l20_n469() + fun_l21_n331 +end + +def fun_l20_n470() + fun_l21_n480 +end + +def fun_l20_n471() + fun_l21_n160 +end + +def fun_l20_n472() + fun_l21_n529 +end + +def fun_l20_n473() + fun_l21_n185 +end + +def fun_l20_n474() + fun_l21_n300 +end + +def fun_l20_n475() + fun_l21_n131 +end + +def fun_l20_n476() + fun_l21_n561 +end + +def fun_l20_n477() + fun_l21_n634 +end + +def fun_l20_n478() + fun_l21_n92 +end + +def fun_l20_n479() + fun_l21_n105 +end + +def fun_l20_n480() + fun_l21_n887 +end + +def fun_l20_n481() + fun_l21_n841 +end + +def fun_l20_n482() + fun_l21_n404 +end + +def fun_l20_n483() + fun_l21_n813 +end + +def fun_l20_n484() + fun_l21_n90 +end + +def fun_l20_n485() + fun_l21_n978 +end + +def fun_l20_n486() + fun_l21_n342 +end + +def fun_l20_n487() + fun_l21_n263 +end + +def fun_l20_n488() + fun_l21_n587 +end + +def fun_l20_n489() + fun_l21_n950 +end + +def fun_l20_n490() + fun_l21_n121 +end + +def fun_l20_n491() + fun_l21_n85 +end + +def fun_l20_n492() + fun_l21_n53 +end + +def fun_l20_n493() + fun_l21_n706 +end + +def fun_l20_n494() + fun_l21_n612 +end + +def fun_l20_n495() + fun_l21_n322 +end + +def fun_l20_n496() + fun_l21_n610 +end + +def fun_l20_n497() + fun_l21_n465 +end + +def fun_l20_n498() + fun_l21_n998 +end + +def fun_l20_n499() + fun_l21_n79 +end + +def fun_l20_n500() + fun_l21_n203 +end + +def fun_l20_n501() + fun_l21_n99 +end + +def fun_l20_n502() + fun_l21_n958 +end + +def fun_l20_n503() + fun_l21_n528 +end + +def fun_l20_n504() + fun_l21_n210 +end + +def fun_l20_n505() + fun_l21_n546 +end + +def fun_l20_n506() + fun_l21_n343 +end + +def fun_l20_n507() + fun_l21_n9 +end + +def fun_l20_n508() + fun_l21_n486 +end + +def fun_l20_n509() + fun_l21_n252 +end + +def fun_l20_n510() + fun_l21_n489 +end + +def fun_l20_n511() + fun_l21_n851 +end + +def fun_l20_n512() + fun_l21_n150 +end + +def fun_l20_n513() + fun_l21_n691 +end + +def fun_l20_n514() + fun_l21_n718 +end + +def fun_l20_n515() + fun_l21_n681 +end + +def fun_l20_n516() + fun_l21_n636 +end + +def fun_l20_n517() + fun_l21_n828 +end + +def fun_l20_n518() + fun_l21_n15 +end + +def fun_l20_n519() + fun_l21_n186 +end + +def fun_l20_n520() + fun_l21_n260 +end + +def fun_l20_n521() + fun_l21_n646 +end + +def fun_l20_n522() + fun_l21_n768 +end + +def fun_l20_n523() + fun_l21_n387 +end + +def fun_l20_n524() + fun_l21_n597 +end + +def fun_l20_n525() + fun_l21_n980 +end + +def fun_l20_n526() + fun_l21_n996 +end + +def fun_l20_n527() + fun_l21_n945 +end + +def fun_l20_n528() + fun_l21_n234 +end + +def fun_l20_n529() + fun_l21_n673 +end + +def fun_l20_n530() + fun_l21_n766 +end + +def fun_l20_n531() + fun_l21_n498 +end + +def fun_l20_n532() + fun_l21_n210 +end + +def fun_l20_n533() + fun_l21_n537 +end + +def fun_l20_n534() + fun_l21_n376 +end + +def fun_l20_n535() + fun_l21_n13 +end + +def fun_l20_n536() + fun_l21_n994 +end + +def fun_l20_n537() + fun_l21_n954 +end + +def fun_l20_n538() + fun_l21_n171 +end + +def fun_l20_n539() + fun_l21_n778 +end + +def fun_l20_n540() + fun_l21_n940 +end + +def fun_l20_n541() + fun_l21_n114 +end + +def fun_l20_n542() + fun_l21_n987 +end + +def fun_l20_n543() + fun_l21_n553 +end + +def fun_l20_n544() + fun_l21_n473 +end + +def fun_l20_n545() + fun_l21_n503 +end + +def fun_l20_n546() + fun_l21_n436 +end + +def fun_l20_n547() + fun_l21_n901 +end + +def fun_l20_n548() + fun_l21_n98 +end + +def fun_l20_n549() + fun_l21_n389 +end + +def fun_l20_n550() + fun_l21_n852 +end + +def fun_l20_n551() + fun_l21_n193 +end + +def fun_l20_n552() + fun_l21_n783 +end + +def fun_l20_n553() + fun_l21_n46 +end + +def fun_l20_n554() + fun_l21_n38 +end + +def fun_l20_n555() + fun_l21_n300 +end + +def fun_l20_n556() + fun_l21_n221 +end + +def fun_l20_n557() + fun_l21_n816 +end + +def fun_l20_n558() + fun_l21_n534 +end + +def fun_l20_n559() + fun_l21_n932 +end + +def fun_l20_n560() + fun_l21_n880 +end + +def fun_l20_n561() + fun_l21_n796 +end + +def fun_l20_n562() + fun_l21_n927 +end + +def fun_l20_n563() + fun_l21_n10 +end + +def fun_l20_n564() + fun_l21_n843 +end + +def fun_l20_n565() + fun_l21_n625 +end + +def fun_l20_n566() + fun_l21_n429 +end + +def fun_l20_n567() + fun_l21_n475 +end + +def fun_l20_n568() + fun_l21_n931 +end + +def fun_l20_n569() + fun_l21_n460 +end + +def fun_l20_n570() + fun_l21_n857 +end + +def fun_l20_n571() + fun_l21_n607 +end + +def fun_l20_n572() + fun_l21_n727 +end + +def fun_l20_n573() + fun_l21_n922 +end + +def fun_l20_n574() + fun_l21_n393 +end + +def fun_l20_n575() + fun_l21_n232 +end + +def fun_l20_n576() + fun_l21_n665 +end + +def fun_l20_n577() + fun_l21_n796 +end + +def fun_l20_n578() + fun_l21_n80 +end + +def fun_l20_n579() + fun_l21_n769 +end + +def fun_l20_n580() + fun_l21_n558 +end + +def fun_l20_n581() + fun_l21_n630 +end + +def fun_l20_n582() + fun_l21_n911 +end + +def fun_l20_n583() + fun_l21_n457 +end + +def fun_l20_n584() + fun_l21_n61 +end + +def fun_l20_n585() + fun_l21_n671 +end + +def fun_l20_n586() + fun_l21_n493 +end + +def fun_l20_n587() + fun_l21_n780 +end + +def fun_l20_n588() + fun_l21_n373 +end + +def fun_l20_n589() + fun_l21_n138 +end + +def fun_l20_n590() + fun_l21_n377 +end + +def fun_l20_n591() + fun_l21_n793 +end + +def fun_l20_n592() + fun_l21_n995 +end + +def fun_l20_n593() + fun_l21_n46 +end + +def fun_l20_n594() + fun_l21_n171 +end + +def fun_l20_n595() + fun_l21_n907 +end + +def fun_l20_n596() + fun_l21_n182 +end + +def fun_l20_n597() + fun_l21_n203 +end + +def fun_l20_n598() + fun_l21_n475 +end + +def fun_l20_n599() + fun_l21_n198 +end + +def fun_l20_n600() + fun_l21_n654 +end + +def fun_l20_n601() + fun_l21_n236 +end + +def fun_l20_n602() + fun_l21_n854 +end + +def fun_l20_n603() + fun_l21_n344 +end + +def fun_l20_n604() + fun_l21_n575 +end + +def fun_l20_n605() + fun_l21_n214 +end + +def fun_l20_n606() + fun_l21_n105 +end + +def fun_l20_n607() + fun_l21_n624 +end + +def fun_l20_n608() + fun_l21_n505 +end + +def fun_l20_n609() + fun_l21_n468 +end + +def fun_l20_n610() + fun_l21_n946 +end + +def fun_l20_n611() + fun_l21_n197 +end + +def fun_l20_n612() + fun_l21_n749 +end + +def fun_l20_n613() + fun_l21_n280 +end + +def fun_l20_n614() + fun_l21_n587 +end + +def fun_l20_n615() + fun_l21_n463 +end + +def fun_l20_n616() + fun_l21_n47 +end + +def fun_l20_n617() + fun_l21_n467 +end + +def fun_l20_n618() + fun_l21_n934 +end + +def fun_l20_n619() + fun_l21_n648 +end + +def fun_l20_n620() + fun_l21_n572 +end + +def fun_l20_n621() + fun_l21_n524 +end + +def fun_l20_n622() + fun_l21_n623 +end + +def fun_l20_n623() + fun_l21_n142 +end + +def fun_l20_n624() + fun_l21_n370 +end + +def fun_l20_n625() + fun_l21_n427 +end + +def fun_l20_n626() + fun_l21_n23 +end + +def fun_l20_n627() + fun_l21_n710 +end + +def fun_l20_n628() + fun_l21_n714 +end + +def fun_l20_n629() + fun_l21_n929 +end + +def fun_l20_n630() + fun_l21_n882 +end + +def fun_l20_n631() + fun_l21_n971 +end + +def fun_l20_n632() + fun_l21_n484 +end + +def fun_l20_n633() + fun_l21_n757 +end + +def fun_l20_n634() + fun_l21_n543 +end + +def fun_l20_n635() + fun_l21_n96 +end + +def fun_l20_n636() + fun_l21_n780 +end + +def fun_l20_n637() + fun_l21_n912 +end + +def fun_l20_n638() + fun_l21_n288 +end + +def fun_l20_n639() + fun_l21_n580 +end + +def fun_l20_n640() + fun_l21_n831 +end + +def fun_l20_n641() + fun_l21_n660 +end + +def fun_l20_n642() + fun_l21_n216 +end + +def fun_l20_n643() + fun_l21_n341 +end + +def fun_l20_n644() + fun_l21_n747 +end + +def fun_l20_n645() + fun_l21_n633 +end + +def fun_l20_n646() + fun_l21_n422 +end + +def fun_l20_n647() + fun_l21_n122 +end + +def fun_l20_n648() + fun_l21_n721 +end + +def fun_l20_n649() + fun_l21_n439 +end + +def fun_l20_n650() + fun_l21_n663 +end + +def fun_l20_n651() + fun_l21_n409 +end + +def fun_l20_n652() + fun_l21_n475 +end + +def fun_l20_n653() + fun_l21_n812 +end + +def fun_l20_n654() + fun_l21_n849 +end + +def fun_l20_n655() + fun_l21_n500 +end + +def fun_l20_n656() + fun_l21_n120 +end + +def fun_l20_n657() + fun_l21_n971 +end + +def fun_l20_n658() + fun_l21_n935 +end + +def fun_l20_n659() + fun_l21_n952 +end + +def fun_l20_n660() + fun_l21_n84 +end + +def fun_l20_n661() + fun_l21_n393 +end + +def fun_l20_n662() + fun_l21_n454 +end + +def fun_l20_n663() + fun_l21_n440 +end + +def fun_l20_n664() + fun_l21_n5 +end + +def fun_l20_n665() + fun_l21_n475 +end + +def fun_l20_n666() + fun_l21_n929 +end + +def fun_l20_n667() + fun_l21_n164 +end + +def fun_l20_n668() + fun_l21_n23 +end + +def fun_l20_n669() + fun_l21_n66 +end + +def fun_l20_n670() + fun_l21_n463 +end + +def fun_l20_n671() + fun_l21_n425 +end + +def fun_l20_n672() + fun_l21_n414 +end + +def fun_l20_n673() + fun_l21_n990 +end + +def fun_l20_n674() + fun_l21_n504 +end + +def fun_l20_n675() + fun_l21_n974 +end + +def fun_l20_n676() + fun_l21_n620 +end + +def fun_l20_n677() + fun_l21_n798 +end + +def fun_l20_n678() + fun_l21_n432 +end + +def fun_l20_n679() + fun_l21_n487 +end + +def fun_l20_n680() + fun_l21_n570 +end + +def fun_l20_n681() + fun_l21_n746 +end + +def fun_l20_n682() + fun_l21_n358 +end + +def fun_l20_n683() + fun_l21_n207 +end + +def fun_l20_n684() + fun_l21_n408 +end + +def fun_l20_n685() + fun_l21_n679 +end + +def fun_l20_n686() + fun_l21_n38 +end + +def fun_l20_n687() + fun_l21_n58 +end + +def fun_l20_n688() + fun_l21_n460 +end + +def fun_l20_n689() + fun_l21_n855 +end + +def fun_l20_n690() + fun_l21_n641 +end + +def fun_l20_n691() + fun_l21_n146 +end + +def fun_l20_n692() + fun_l21_n709 +end + +def fun_l20_n693() + fun_l21_n801 +end + +def fun_l20_n694() + fun_l21_n375 +end + +def fun_l20_n695() + fun_l21_n778 +end + +def fun_l20_n696() + fun_l21_n620 +end + +def fun_l20_n697() + fun_l21_n630 +end + +def fun_l20_n698() + fun_l21_n582 +end + +def fun_l20_n699() + fun_l21_n198 +end + +def fun_l20_n700() + fun_l21_n830 +end + +def fun_l20_n701() + fun_l21_n101 +end + +def fun_l20_n702() + fun_l21_n824 +end + +def fun_l20_n703() + fun_l21_n97 +end + +def fun_l20_n704() + fun_l21_n628 +end + +def fun_l20_n705() + fun_l21_n688 +end + +def fun_l20_n706() + fun_l21_n120 +end + +def fun_l20_n707() + fun_l21_n343 +end + +def fun_l20_n708() + fun_l21_n175 +end + +def fun_l20_n709() + fun_l21_n122 +end + +def fun_l20_n710() + fun_l21_n272 +end + +def fun_l20_n711() + fun_l21_n343 +end + +def fun_l20_n712() + fun_l21_n317 +end + +def fun_l20_n713() + fun_l21_n982 +end + +def fun_l20_n714() + fun_l21_n458 +end + +def fun_l20_n715() + fun_l21_n906 +end + +def fun_l20_n716() + fun_l21_n565 +end + +def fun_l20_n717() + fun_l21_n174 +end + +def fun_l20_n718() + fun_l21_n34 +end + +def fun_l20_n719() + fun_l21_n832 +end + +def fun_l20_n720() + fun_l21_n111 +end + +def fun_l20_n721() + fun_l21_n701 +end + +def fun_l20_n722() + fun_l21_n201 +end + +def fun_l20_n723() + fun_l21_n285 +end + +def fun_l20_n724() + fun_l21_n269 +end + +def fun_l20_n725() + fun_l21_n144 +end + +def fun_l20_n726() + fun_l21_n246 +end + +def fun_l20_n727() + fun_l21_n221 +end + +def fun_l20_n728() + fun_l21_n599 +end + +def fun_l20_n729() + fun_l21_n909 +end + +def fun_l20_n730() + fun_l21_n693 +end + +def fun_l20_n731() + fun_l21_n879 +end + +def fun_l20_n732() + fun_l21_n452 +end + +def fun_l20_n733() + fun_l21_n772 +end + +def fun_l20_n734() + fun_l21_n116 +end + +def fun_l20_n735() + fun_l21_n895 +end + +def fun_l20_n736() + fun_l21_n937 +end + +def fun_l20_n737() + fun_l21_n50 +end + +def fun_l20_n738() + fun_l21_n947 +end + +def fun_l20_n739() + fun_l21_n500 +end + +def fun_l20_n740() + fun_l21_n753 +end + +def fun_l20_n741() + fun_l21_n497 +end + +def fun_l20_n742() + fun_l21_n524 +end + +def fun_l20_n743() + fun_l21_n389 +end + +def fun_l20_n744() + fun_l21_n539 +end + +def fun_l20_n745() + fun_l21_n70 +end + +def fun_l20_n746() + fun_l21_n736 +end + +def fun_l20_n747() + fun_l21_n94 +end + +def fun_l20_n748() + fun_l21_n686 +end + +def fun_l20_n749() + fun_l21_n269 +end + +def fun_l20_n750() + fun_l21_n809 +end + +def fun_l20_n751() + fun_l21_n570 +end + +def fun_l20_n752() + fun_l21_n522 +end + +def fun_l20_n753() + fun_l21_n167 +end + +def fun_l20_n754() + fun_l21_n610 +end + +def fun_l20_n755() + fun_l21_n72 +end + +def fun_l20_n756() + fun_l21_n146 +end + +def fun_l20_n757() + fun_l21_n916 +end + +def fun_l20_n758() + fun_l21_n163 +end + +def fun_l20_n759() + fun_l21_n279 +end + +def fun_l20_n760() + fun_l21_n677 +end + +def fun_l20_n761() + fun_l21_n876 +end + +def fun_l20_n762() + fun_l21_n333 +end + +def fun_l20_n763() + fun_l21_n36 +end + +def fun_l20_n764() + fun_l21_n166 +end + +def fun_l20_n765() + fun_l21_n824 +end + +def fun_l20_n766() + fun_l21_n416 +end + +def fun_l20_n767() + fun_l21_n655 +end + +def fun_l20_n768() + fun_l21_n267 +end + +def fun_l20_n769() + fun_l21_n257 +end + +def fun_l20_n770() + fun_l21_n839 +end + +def fun_l20_n771() + fun_l21_n504 +end + +def fun_l20_n772() + fun_l21_n717 +end + +def fun_l20_n773() + fun_l21_n332 +end + +def fun_l20_n774() + fun_l21_n949 +end + +def fun_l20_n775() + fun_l21_n226 +end + +def fun_l20_n776() + fun_l21_n145 +end + +def fun_l20_n777() + fun_l21_n548 +end + +def fun_l20_n778() + fun_l21_n912 +end + +def fun_l20_n779() + fun_l21_n984 +end + +def fun_l20_n780() + fun_l21_n907 +end + +def fun_l20_n781() + fun_l21_n433 +end + +def fun_l20_n782() + fun_l21_n542 +end + +def fun_l20_n783() + fun_l21_n88 +end + +def fun_l20_n784() + fun_l21_n104 +end + +def fun_l20_n785() + fun_l21_n383 +end + +def fun_l20_n786() + fun_l21_n998 +end + +def fun_l20_n787() + fun_l21_n525 +end + +def fun_l20_n788() + fun_l21_n276 +end + +def fun_l20_n789() + fun_l21_n162 +end + +def fun_l20_n790() + fun_l21_n420 +end + +def fun_l20_n791() + fun_l21_n793 +end + +def fun_l20_n792() + fun_l21_n121 +end + +def fun_l20_n793() + fun_l21_n164 +end + +def fun_l20_n794() + fun_l21_n110 +end + +def fun_l20_n795() + fun_l21_n68 +end + +def fun_l20_n796() + fun_l21_n417 +end + +def fun_l20_n797() + fun_l21_n878 +end + +def fun_l20_n798() + fun_l21_n987 +end + +def fun_l20_n799() + fun_l21_n197 +end + +def fun_l20_n800() + fun_l21_n729 +end + +def fun_l20_n801() + fun_l21_n956 +end + +def fun_l20_n802() + fun_l21_n33 +end + +def fun_l20_n803() + fun_l21_n73 +end + +def fun_l20_n804() + fun_l21_n759 +end + +def fun_l20_n805() + fun_l21_n784 +end + +def fun_l20_n806() + fun_l21_n102 +end + +def fun_l20_n807() + fun_l21_n624 +end + +def fun_l20_n808() + fun_l21_n580 +end + +def fun_l20_n809() + fun_l21_n347 +end + +def fun_l20_n810() + fun_l21_n163 +end + +def fun_l20_n811() + fun_l21_n220 +end + +def fun_l20_n812() + fun_l21_n324 +end + +def fun_l20_n813() + fun_l21_n299 +end + +def fun_l20_n814() + fun_l21_n958 +end + +def fun_l20_n815() + fun_l21_n252 +end + +def fun_l20_n816() + fun_l21_n479 +end + +def fun_l20_n817() + fun_l21_n536 +end + +def fun_l20_n818() + fun_l21_n624 +end + +def fun_l20_n819() + fun_l21_n347 +end + +def fun_l20_n820() + fun_l21_n308 +end + +def fun_l20_n821() + fun_l21_n4 +end + +def fun_l20_n822() + fun_l21_n88 +end + +def fun_l20_n823() + fun_l21_n787 +end + +def fun_l20_n824() + fun_l21_n450 +end + +def fun_l20_n825() + fun_l21_n384 +end + +def fun_l20_n826() + fun_l21_n416 +end + +def fun_l20_n827() + fun_l21_n73 +end + +def fun_l20_n828() + fun_l21_n884 +end + +def fun_l20_n829() + fun_l21_n51 +end + +def fun_l20_n830() + fun_l21_n37 +end + +def fun_l20_n831() + fun_l21_n326 +end + +def fun_l20_n832() + fun_l21_n120 +end + +def fun_l20_n833() + fun_l21_n957 +end + +def fun_l20_n834() + fun_l21_n973 +end + +def fun_l20_n835() + fun_l21_n966 +end + +def fun_l20_n836() + fun_l21_n110 +end + +def fun_l20_n837() + fun_l21_n57 +end + +def fun_l20_n838() + fun_l21_n836 +end + +def fun_l20_n839() + fun_l21_n701 +end + +def fun_l20_n840() + fun_l21_n607 +end + +def fun_l20_n841() + fun_l21_n92 +end + +def fun_l20_n842() + fun_l21_n304 +end + +def fun_l20_n843() + fun_l21_n443 +end + +def fun_l20_n844() + fun_l21_n282 +end + +def fun_l20_n845() + fun_l21_n301 +end + +def fun_l20_n846() + fun_l21_n360 +end + +def fun_l20_n847() + fun_l21_n848 +end + +def fun_l20_n848() + fun_l21_n796 +end + +def fun_l20_n849() + fun_l21_n81 +end + +def fun_l20_n850() + fun_l21_n126 +end + +def fun_l20_n851() + fun_l21_n951 +end + +def fun_l20_n852() + fun_l21_n187 +end + +def fun_l20_n853() + fun_l21_n498 +end + +def fun_l20_n854() + fun_l21_n885 +end + +def fun_l20_n855() + fun_l21_n391 +end + +def fun_l20_n856() + fun_l21_n823 +end + +def fun_l20_n857() + fun_l21_n516 +end + +def fun_l20_n858() + fun_l21_n266 +end + +def fun_l20_n859() + fun_l21_n617 +end + +def fun_l20_n860() + fun_l21_n440 +end + +def fun_l20_n861() + fun_l21_n694 +end + +def fun_l20_n862() + fun_l21_n128 +end + +def fun_l20_n863() + fun_l21_n340 +end + +def fun_l20_n864() + fun_l21_n234 +end + +def fun_l20_n865() + fun_l21_n324 +end + +def fun_l20_n866() + fun_l21_n233 +end + +def fun_l20_n867() + fun_l21_n26 +end + +def fun_l20_n868() + fun_l21_n548 +end + +def fun_l20_n869() + fun_l21_n563 +end + +def fun_l20_n870() + fun_l21_n452 +end + +def fun_l20_n871() + fun_l21_n223 +end + +def fun_l20_n872() + fun_l21_n147 +end + +def fun_l20_n873() + fun_l21_n147 +end + +def fun_l20_n874() + fun_l21_n266 +end + +def fun_l20_n875() + fun_l21_n335 +end + +def fun_l20_n876() + fun_l21_n253 +end + +def fun_l20_n877() + fun_l21_n479 +end + +def fun_l20_n878() + fun_l21_n34 +end + +def fun_l20_n879() + fun_l21_n798 +end + +def fun_l20_n880() + fun_l21_n223 +end + +def fun_l20_n881() + fun_l21_n343 +end + +def fun_l20_n882() + fun_l21_n728 +end + +def fun_l20_n883() + fun_l21_n351 +end + +def fun_l20_n884() + fun_l21_n997 +end + +def fun_l20_n885() + fun_l21_n49 +end + +def fun_l20_n886() + fun_l21_n773 +end + +def fun_l20_n887() + fun_l21_n93 +end + +def fun_l20_n888() + fun_l21_n124 +end + +def fun_l20_n889() + fun_l21_n897 +end + +def fun_l20_n890() + fun_l21_n692 +end + +def fun_l20_n891() + fun_l21_n158 +end + +def fun_l20_n892() + fun_l21_n456 +end + +def fun_l20_n893() + fun_l21_n49 +end + +def fun_l20_n894() + fun_l21_n751 +end + +def fun_l20_n895() + fun_l21_n672 +end + +def fun_l20_n896() + fun_l21_n726 +end + +def fun_l20_n897() + fun_l21_n95 +end + +def fun_l20_n898() + fun_l21_n420 +end + +def fun_l20_n899() + fun_l21_n77 +end + +def fun_l20_n900() + fun_l21_n770 +end + +def fun_l20_n901() + fun_l21_n127 +end + +def fun_l20_n902() + fun_l21_n566 +end + +def fun_l20_n903() + fun_l21_n398 +end + +def fun_l20_n904() + fun_l21_n720 +end + +def fun_l20_n905() + fun_l21_n350 +end + +def fun_l20_n906() + fun_l21_n935 +end + +def fun_l20_n907() + fun_l21_n172 +end + +def fun_l20_n908() + fun_l21_n988 +end + +def fun_l20_n909() + fun_l21_n627 +end + +def fun_l20_n910() + fun_l21_n776 +end + +def fun_l20_n911() + fun_l21_n34 +end + +def fun_l20_n912() + fun_l21_n361 +end + +def fun_l20_n913() + fun_l21_n408 +end + +def fun_l20_n914() + fun_l21_n941 +end + +def fun_l20_n915() + fun_l21_n275 +end + +def fun_l20_n916() + fun_l21_n864 +end + +def fun_l20_n917() + fun_l21_n839 +end + +def fun_l20_n918() + fun_l21_n837 +end + +def fun_l20_n919() + fun_l21_n837 +end + +def fun_l20_n920() + fun_l21_n627 +end + +def fun_l20_n921() + fun_l21_n321 +end + +def fun_l20_n922() + fun_l21_n308 +end + +def fun_l20_n923() + fun_l21_n475 +end + +def fun_l20_n924() + fun_l21_n115 +end + +def fun_l20_n925() + fun_l21_n794 +end + +def fun_l20_n926() + fun_l21_n376 +end + +def fun_l20_n927() + fun_l21_n951 +end + +def fun_l20_n928() + fun_l21_n744 +end + +def fun_l20_n929() + fun_l21_n621 +end + +def fun_l20_n930() + fun_l21_n630 +end + +def fun_l20_n931() + fun_l21_n459 +end + +def fun_l20_n932() + fun_l21_n41 +end + +def fun_l20_n933() + fun_l21_n313 +end + +def fun_l20_n934() + fun_l21_n130 +end + +def fun_l20_n935() + fun_l21_n605 +end + +def fun_l20_n936() + fun_l21_n261 +end + +def fun_l20_n937() + fun_l21_n54 +end + +def fun_l20_n938() + fun_l21_n319 +end + +def fun_l20_n939() + fun_l21_n541 +end + +def fun_l20_n940() + fun_l21_n104 +end + +def fun_l20_n941() + fun_l21_n339 +end + +def fun_l20_n942() + fun_l21_n220 +end + +def fun_l20_n943() + fun_l21_n560 +end + +def fun_l20_n944() + fun_l21_n931 +end + +def fun_l20_n945() + fun_l21_n642 +end + +def fun_l20_n946() + fun_l21_n584 +end + +def fun_l20_n947() + fun_l21_n324 +end + +def fun_l20_n948() + fun_l21_n10 +end + +def fun_l20_n949() + fun_l21_n976 +end + +def fun_l20_n950() + fun_l21_n65 +end + +def fun_l20_n951() + fun_l21_n392 +end + +def fun_l20_n952() + fun_l21_n263 +end + +def fun_l20_n953() + fun_l21_n228 +end + +def fun_l20_n954() + fun_l21_n177 +end + +def fun_l20_n955() + fun_l21_n81 +end + +def fun_l20_n956() + fun_l21_n141 +end + +def fun_l20_n957() + fun_l21_n540 +end + +def fun_l20_n958() + fun_l21_n802 +end + +def fun_l20_n959() + fun_l21_n28 +end + +def fun_l20_n960() + fun_l21_n438 +end + +def fun_l20_n961() + fun_l21_n722 +end + +def fun_l20_n962() + fun_l21_n707 +end + +def fun_l20_n963() + fun_l21_n598 +end + +def fun_l20_n964() + fun_l21_n687 +end + +def fun_l20_n965() + fun_l21_n258 +end + +def fun_l20_n966() + fun_l21_n786 +end + +def fun_l20_n967() + fun_l21_n362 +end + +def fun_l20_n968() + fun_l21_n41 +end + +def fun_l20_n969() + fun_l21_n933 +end + +def fun_l20_n970() + fun_l21_n250 +end + +def fun_l20_n971() + fun_l21_n760 +end + +def fun_l20_n972() + fun_l21_n993 +end + +def fun_l20_n973() + fun_l21_n278 +end + +def fun_l20_n974() + fun_l21_n477 +end + +def fun_l20_n975() + fun_l21_n901 +end + +def fun_l20_n976() + fun_l21_n820 +end + +def fun_l20_n977() + fun_l21_n739 +end + +def fun_l20_n978() + fun_l21_n722 +end + +def fun_l20_n979() + fun_l21_n418 +end + +def fun_l20_n980() + fun_l21_n207 +end + +def fun_l20_n981() + fun_l21_n213 +end + +def fun_l20_n982() + fun_l21_n30 +end + +def fun_l20_n983() + fun_l21_n667 +end + +def fun_l20_n984() + fun_l21_n582 +end + +def fun_l20_n985() + fun_l21_n398 +end + +def fun_l20_n986() + fun_l21_n376 +end + +def fun_l20_n987() + fun_l21_n84 +end + +def fun_l20_n988() + fun_l21_n701 +end + +def fun_l20_n989() + fun_l21_n100 +end + +def fun_l20_n990() + fun_l21_n247 +end + +def fun_l20_n991() + fun_l21_n992 +end + +def fun_l20_n992() + fun_l21_n635 +end + +def fun_l20_n993() + fun_l21_n493 +end + +def fun_l20_n994() + fun_l21_n184 +end + +def fun_l20_n995() + fun_l21_n31 +end + +def fun_l20_n996() + fun_l21_n555 +end + +def fun_l20_n997() + fun_l21_n258 +end + +def fun_l20_n998() + fun_l21_n32 +end + +def fun_l20_n999() + fun_l21_n6 +end + +def fun_l21_n0() + fun_l22_n98 +end + +def fun_l21_n1() + fun_l22_n194 +end + +def fun_l21_n2() + fun_l22_n510 +end + +def fun_l21_n3() + fun_l22_n707 +end + +def fun_l21_n4() + fun_l22_n878 +end + +def fun_l21_n5() + fun_l22_n615 +end + +def fun_l21_n6() + fun_l22_n891 +end + +def fun_l21_n7() + fun_l22_n458 +end + +def fun_l21_n8() + fun_l22_n478 +end + +def fun_l21_n9() + fun_l22_n30 +end + +def fun_l21_n10() + fun_l22_n345 +end + +def fun_l21_n11() + fun_l22_n202 +end + +def fun_l21_n12() + fun_l22_n354 +end + +def fun_l21_n13() + fun_l22_n673 +end + +def fun_l21_n14() + fun_l22_n662 +end + +def fun_l21_n15() + fun_l22_n593 +end + +def fun_l21_n16() + fun_l22_n127 +end + +def fun_l21_n17() + fun_l22_n876 +end + +def fun_l21_n18() + fun_l22_n862 +end + +def fun_l21_n19() + fun_l22_n337 +end + +def fun_l21_n20() + fun_l22_n365 +end + +def fun_l21_n21() + fun_l22_n323 +end + +def fun_l21_n22() + fun_l22_n767 +end + +def fun_l21_n23() + fun_l22_n364 +end + +def fun_l21_n24() + fun_l22_n562 +end + +def fun_l21_n25() + fun_l22_n420 +end + +def fun_l21_n26() + fun_l22_n754 +end + +def fun_l21_n27() + fun_l22_n381 +end + +def fun_l21_n28() + fun_l22_n393 +end + +def fun_l21_n29() + fun_l22_n25 +end + +def fun_l21_n30() + fun_l22_n951 +end + +def fun_l21_n31() + fun_l22_n271 +end + +def fun_l21_n32() + fun_l22_n127 +end + +def fun_l21_n33() + fun_l22_n962 +end + +def fun_l21_n34() + fun_l22_n611 +end + +def fun_l21_n35() + fun_l22_n936 +end + +def fun_l21_n36() + fun_l22_n340 +end + +def fun_l21_n37() + fun_l22_n349 +end + +def fun_l21_n38() + fun_l22_n692 +end + +def fun_l21_n39() + fun_l22_n184 +end + +def fun_l21_n40() + fun_l22_n490 +end + +def fun_l21_n41() + fun_l22_n316 +end + +def fun_l21_n42() + fun_l22_n545 +end + +def fun_l21_n43() + fun_l22_n344 +end + +def fun_l21_n44() + fun_l22_n938 +end + +def fun_l21_n45() + fun_l22_n820 +end + +def fun_l21_n46() + fun_l22_n60 +end + +def fun_l21_n47() + fun_l22_n649 +end + +def fun_l21_n48() + fun_l22_n41 +end + +def fun_l21_n49() + fun_l22_n305 +end + +def fun_l21_n50() + fun_l22_n677 +end + +def fun_l21_n51() + fun_l22_n880 +end + +def fun_l21_n52() + fun_l22_n535 +end + +def fun_l21_n53() + fun_l22_n686 +end + +def fun_l21_n54() + fun_l22_n194 +end + +def fun_l21_n55() + fun_l22_n313 +end + +def fun_l21_n56() + fun_l22_n639 +end + +def fun_l21_n57() + fun_l22_n182 +end + +def fun_l21_n58() + fun_l22_n588 +end + +def fun_l21_n59() + fun_l22_n979 +end + +def fun_l21_n60() + fun_l22_n230 +end + +def fun_l21_n61() + fun_l22_n139 +end + +def fun_l21_n62() + fun_l22_n899 +end + +def fun_l21_n63() + fun_l22_n532 +end + +def fun_l21_n64() + fun_l22_n479 +end + +def fun_l21_n65() + fun_l22_n735 +end + +def fun_l21_n66() + fun_l22_n425 +end + +def fun_l21_n67() + fun_l22_n878 +end + +def fun_l21_n68() + fun_l22_n706 +end + +def fun_l21_n69() + fun_l22_n826 +end + +def fun_l21_n70() + fun_l22_n44 +end + +def fun_l21_n71() + fun_l22_n107 +end + +def fun_l21_n72() + fun_l22_n737 +end + +def fun_l21_n73() + fun_l22_n659 +end + +def fun_l21_n74() + fun_l22_n707 +end + +def fun_l21_n75() + fun_l22_n658 +end + +def fun_l21_n76() + fun_l22_n937 +end + +def fun_l21_n77() + fun_l22_n86 +end + +def fun_l21_n78() + fun_l22_n606 +end + +def fun_l21_n79() + fun_l22_n61 +end + +def fun_l21_n80() + fun_l22_n780 +end + +def fun_l21_n81() + fun_l22_n560 +end + +def fun_l21_n82() + fun_l22_n949 +end + +def fun_l21_n83() + fun_l22_n790 +end + +def fun_l21_n84() + fun_l22_n851 +end + +def fun_l21_n85() + fun_l22_n148 +end + +def fun_l21_n86() + fun_l22_n406 +end + +def fun_l21_n87() + fun_l22_n38 +end + +def fun_l21_n88() + fun_l22_n468 +end + +def fun_l21_n89() + fun_l22_n783 +end + +def fun_l21_n90() + fun_l22_n853 +end + +def fun_l21_n91() + fun_l22_n758 +end + +def fun_l21_n92() + fun_l22_n34 +end + +def fun_l21_n93() + fun_l22_n387 +end + +def fun_l21_n94() + fun_l22_n181 +end + +def fun_l21_n95() + fun_l22_n514 +end + +def fun_l21_n96() + fun_l22_n139 +end + +def fun_l21_n97() + fun_l22_n543 +end + +def fun_l21_n98() + fun_l22_n462 +end + +def fun_l21_n99() + fun_l22_n570 +end + +def fun_l21_n100() + fun_l22_n634 +end + +def fun_l21_n101() + fun_l22_n69 +end + +def fun_l21_n102() + fun_l22_n142 +end + +def fun_l21_n103() + fun_l22_n964 +end + +def fun_l21_n104() + fun_l22_n851 +end + +def fun_l21_n105() + fun_l22_n410 +end + +def fun_l21_n106() + fun_l22_n563 +end + +def fun_l21_n107() + fun_l22_n914 +end + +def fun_l21_n108() + fun_l22_n163 +end + +def fun_l21_n109() + fun_l22_n248 +end + +def fun_l21_n110() + fun_l22_n309 +end + +def fun_l21_n111() + fun_l22_n894 +end + +def fun_l21_n112() + fun_l22_n916 +end + +def fun_l21_n113() + fun_l22_n818 +end + +def fun_l21_n114() + fun_l22_n824 +end + +def fun_l21_n115() + fun_l22_n34 +end + +def fun_l21_n116() + fun_l22_n538 +end + +def fun_l21_n117() + fun_l22_n841 +end + +def fun_l21_n118() + fun_l22_n934 +end + +def fun_l21_n119() + fun_l22_n217 +end + +def fun_l21_n120() + fun_l22_n479 +end + +def fun_l21_n121() + fun_l22_n693 +end + +def fun_l21_n122() + fun_l22_n182 +end + +def fun_l21_n123() + fun_l22_n269 +end + +def fun_l21_n124() + fun_l22_n324 +end + +def fun_l21_n125() + fun_l22_n688 +end + +def fun_l21_n126() + fun_l22_n725 +end + +def fun_l21_n127() + fun_l22_n48 +end + +def fun_l21_n128() + fun_l22_n884 +end + +def fun_l21_n129() + fun_l22_n295 +end + +def fun_l21_n130() + fun_l22_n192 +end + +def fun_l21_n131() + fun_l22_n777 +end + +def fun_l21_n132() + fun_l22_n87 +end + +def fun_l21_n133() + fun_l22_n724 +end + +def fun_l21_n134() + fun_l22_n235 +end + +def fun_l21_n135() + fun_l22_n239 +end + +def fun_l21_n136() + fun_l22_n820 +end + +def fun_l21_n137() + fun_l22_n552 +end + +def fun_l21_n138() + fun_l22_n227 +end + +def fun_l21_n139() + fun_l22_n806 +end + +def fun_l21_n140() + fun_l22_n350 +end + +def fun_l21_n141() + fun_l22_n226 +end + +def fun_l21_n142() + fun_l22_n166 +end + +def fun_l21_n143() + fun_l22_n480 +end + +def fun_l21_n144() + fun_l22_n28 +end + +def fun_l21_n145() + fun_l22_n661 +end + +def fun_l21_n146() + fun_l22_n464 +end + +def fun_l21_n147() + fun_l22_n573 +end + +def fun_l21_n148() + fun_l22_n589 +end + +def fun_l21_n149() + fun_l22_n856 +end + +def fun_l21_n150() + fun_l22_n181 +end + +def fun_l21_n151() + fun_l22_n252 +end + +def fun_l21_n152() + fun_l22_n80 +end + +def fun_l21_n153() + fun_l22_n417 +end + +def fun_l21_n154() + fun_l22_n442 +end + +def fun_l21_n155() + fun_l22_n928 +end + +def fun_l21_n156() + fun_l22_n38 +end + +def fun_l21_n157() + fun_l22_n515 +end + +def fun_l21_n158() + fun_l22_n986 +end + +def fun_l21_n159() + fun_l22_n173 +end + +def fun_l21_n160() + fun_l22_n592 +end + +def fun_l21_n161() + fun_l22_n50 +end + +def fun_l21_n162() + fun_l22_n625 +end + +def fun_l21_n163() + fun_l22_n651 +end + +def fun_l21_n164() + fun_l22_n183 +end + +def fun_l21_n165() + fun_l22_n976 +end + +def fun_l21_n166() + fun_l22_n533 +end + +def fun_l21_n167() + fun_l22_n313 +end + +def fun_l21_n168() + fun_l22_n948 +end + +def fun_l21_n169() + fun_l22_n860 +end + +def fun_l21_n170() + fun_l22_n393 +end + +def fun_l21_n171() + fun_l22_n986 +end + +def fun_l21_n172() + fun_l22_n206 +end + +def fun_l21_n173() + fun_l22_n189 +end + +def fun_l21_n174() + fun_l22_n209 +end + +def fun_l21_n175() + fun_l22_n822 +end + +def fun_l21_n176() + fun_l22_n960 +end + +def fun_l21_n177() + fun_l22_n646 +end + +def fun_l21_n178() + fun_l22_n523 +end + +def fun_l21_n179() + fun_l22_n520 +end + +def fun_l21_n180() + fun_l22_n146 +end + +def fun_l21_n181() + fun_l22_n336 +end + +def fun_l21_n182() + fun_l22_n129 +end + +def fun_l21_n183() + fun_l22_n382 +end + +def fun_l21_n184() + fun_l22_n833 +end + +def fun_l21_n185() + fun_l22_n398 +end + +def fun_l21_n186() + fun_l22_n919 +end + +def fun_l21_n187() + fun_l22_n463 +end + +def fun_l21_n188() + fun_l22_n442 +end + +def fun_l21_n189() + fun_l22_n395 +end + +def fun_l21_n190() + fun_l22_n934 +end + +def fun_l21_n191() + fun_l22_n117 +end + +def fun_l21_n192() + fun_l22_n436 +end + +def fun_l21_n193() + fun_l22_n316 +end + +def fun_l21_n194() + fun_l22_n512 +end + +def fun_l21_n195() + fun_l22_n565 +end + +def fun_l21_n196() + fun_l22_n494 +end + +def fun_l21_n197() + fun_l22_n586 +end + +def fun_l21_n198() + fun_l22_n456 +end + +def fun_l21_n199() + fun_l22_n465 +end + +def fun_l21_n200() + fun_l22_n622 +end + +def fun_l21_n201() + fun_l22_n747 +end + +def fun_l21_n202() + fun_l22_n216 +end + +def fun_l21_n203() + fun_l22_n568 +end + +def fun_l21_n204() + fun_l22_n94 +end + +def fun_l21_n205() + fun_l22_n839 +end + +def fun_l21_n206() + fun_l22_n357 +end + +def fun_l21_n207() + fun_l22_n485 +end + +def fun_l21_n208() + fun_l22_n818 +end + +def fun_l21_n209() + fun_l22_n852 +end + +def fun_l21_n210() + fun_l22_n264 +end + +def fun_l21_n211() + fun_l22_n519 +end + +def fun_l21_n212() + fun_l22_n362 +end + +def fun_l21_n213() + fun_l22_n955 +end + +def fun_l21_n214() + fun_l22_n756 +end + +def fun_l21_n215() + fun_l22_n271 +end + +def fun_l21_n216() + fun_l22_n169 +end + +def fun_l21_n217() + fun_l22_n456 +end + +def fun_l21_n218() + fun_l22_n227 +end + +def fun_l21_n219() + fun_l22_n75 +end + +def fun_l21_n220() + fun_l22_n21 +end + +def fun_l21_n221() + fun_l22_n35 +end + +def fun_l21_n222() + fun_l22_n386 +end + +def fun_l21_n223() + fun_l22_n678 +end + +def fun_l21_n224() + fun_l22_n463 +end + +def fun_l21_n225() + fun_l22_n200 +end + +def fun_l21_n226() + fun_l22_n502 +end + +def fun_l21_n227() + fun_l22_n690 +end + +def fun_l21_n228() + fun_l22_n153 +end + +def fun_l21_n229() + fun_l22_n218 +end + +def fun_l21_n230() + fun_l22_n20 +end + +def fun_l21_n231() + fun_l22_n48 +end + +def fun_l21_n232() + fun_l22_n549 +end + +def fun_l21_n233() + fun_l22_n994 +end + +def fun_l21_n234() + fun_l22_n242 +end + +def fun_l21_n235() + fun_l22_n153 +end + +def fun_l21_n236() + fun_l22_n830 +end + +def fun_l21_n237() + fun_l22_n663 +end + +def fun_l21_n238() + fun_l22_n387 +end + +def fun_l21_n239() + fun_l22_n87 +end + +def fun_l21_n240() + fun_l22_n341 +end + +def fun_l21_n241() + fun_l22_n499 +end + +def fun_l21_n242() + fun_l22_n231 +end + +def fun_l21_n243() + fun_l22_n644 +end + +def fun_l21_n244() + fun_l22_n212 +end + +def fun_l21_n245() + fun_l22_n197 +end + +def fun_l21_n246() + fun_l22_n831 +end + +def fun_l21_n247() + fun_l22_n62 +end + +def fun_l21_n248() + fun_l22_n689 +end + +def fun_l21_n249() + fun_l22_n884 +end + +def fun_l21_n250() + fun_l22_n767 +end + +def fun_l21_n251() + fun_l22_n278 +end + +def fun_l21_n252() + fun_l22_n881 +end + +def fun_l21_n253() + fun_l22_n585 +end + +def fun_l21_n254() + fun_l22_n967 +end + +def fun_l21_n255() + fun_l22_n381 +end + +def fun_l21_n256() + fun_l22_n579 +end + +def fun_l21_n257() + fun_l22_n447 +end + +def fun_l21_n258() + fun_l22_n156 +end + +def fun_l21_n259() + fun_l22_n722 +end + +def fun_l21_n260() + fun_l22_n431 +end + +def fun_l21_n261() + fun_l22_n83 +end + +def fun_l21_n262() + fun_l22_n41 +end + +def fun_l21_n263() + fun_l22_n18 +end + +def fun_l21_n264() + fun_l22_n686 +end + +def fun_l21_n265() + fun_l22_n668 +end + +def fun_l21_n266() + fun_l22_n652 +end + +def fun_l21_n267() + fun_l22_n121 +end + +def fun_l21_n268() + fun_l22_n279 +end + +def fun_l21_n269() + fun_l22_n540 +end + +def fun_l21_n270() + fun_l22_n360 +end + +def fun_l21_n271() + fun_l22_n106 +end + +def fun_l21_n272() + fun_l22_n454 +end + +def fun_l21_n273() + fun_l22_n882 +end + +def fun_l21_n274() + fun_l22_n523 +end + +def fun_l21_n275() + fun_l22_n938 +end + +def fun_l21_n276() + fun_l22_n932 +end + +def fun_l21_n277() + fun_l22_n923 +end + +def fun_l21_n278() + fun_l22_n728 +end + +def fun_l21_n279() + fun_l22_n587 +end + +def fun_l21_n280() + fun_l22_n608 +end + +def fun_l21_n281() + fun_l22_n366 +end + +def fun_l21_n282() + fun_l22_n486 +end + +def fun_l21_n283() + fun_l22_n864 +end + +def fun_l21_n284() + fun_l22_n34 +end + +def fun_l21_n285() + fun_l22_n658 +end + +def fun_l21_n286() + fun_l22_n488 +end + +def fun_l21_n287() + fun_l22_n266 +end + +def fun_l21_n288() + fun_l22_n810 +end + +def fun_l21_n289() + fun_l22_n965 +end + +def fun_l21_n290() + fun_l22_n513 +end + +def fun_l21_n291() + fun_l22_n608 +end + +def fun_l21_n292() + fun_l22_n499 +end + +def fun_l21_n293() + fun_l22_n360 +end + +def fun_l21_n294() + fun_l22_n511 +end + +def fun_l21_n295() + fun_l22_n940 +end + +def fun_l21_n296() + fun_l22_n99 +end + +def fun_l21_n297() + fun_l22_n496 +end + +def fun_l21_n298() + fun_l22_n273 +end + +def fun_l21_n299() + fun_l22_n232 +end + +def fun_l21_n300() + fun_l22_n165 +end + +def fun_l21_n301() + fun_l22_n531 +end + +def fun_l21_n302() + fun_l22_n773 +end + +def fun_l21_n303() + fun_l22_n610 +end + +def fun_l21_n304() + fun_l22_n564 +end + +def fun_l21_n305() + fun_l22_n16 +end + +def fun_l21_n306() + fun_l22_n176 +end + +def fun_l21_n307() + fun_l22_n846 +end + +def fun_l21_n308() + fun_l22_n680 +end + +def fun_l21_n309() + fun_l22_n858 +end + +def fun_l21_n310() + fun_l22_n220 +end + +def fun_l21_n311() + fun_l22_n125 +end + +def fun_l21_n312() + fun_l22_n441 +end + +def fun_l21_n313() + fun_l22_n751 +end + +def fun_l21_n314() + fun_l22_n863 +end + +def fun_l21_n315() + fun_l22_n284 +end + +def fun_l21_n316() + fun_l22_n648 +end + +def fun_l21_n317() + fun_l22_n363 +end + +def fun_l21_n318() + fun_l22_n427 +end + +def fun_l21_n319() + fun_l22_n557 +end + +def fun_l21_n320() + fun_l22_n531 +end + +def fun_l21_n321() + fun_l22_n252 +end + +def fun_l21_n322() + fun_l22_n393 +end + +def fun_l21_n323() + fun_l22_n108 +end + +def fun_l21_n324() + fun_l22_n138 +end + +def fun_l21_n325() + fun_l22_n68 +end + +def fun_l21_n326() + fun_l22_n909 +end + +def fun_l21_n327() + fun_l22_n672 +end + +def fun_l21_n328() + fun_l22_n746 +end + +def fun_l21_n329() + fun_l22_n479 +end + +def fun_l21_n330() + fun_l22_n892 +end + +def fun_l21_n331() + fun_l22_n30 +end + +def fun_l21_n332() + fun_l22_n184 +end + +def fun_l21_n333() + fun_l22_n956 +end + +def fun_l21_n334() + fun_l22_n712 +end + +def fun_l21_n335() + fun_l22_n929 +end + +def fun_l21_n336() + fun_l22_n914 +end + +def fun_l21_n337() + fun_l22_n14 +end + +def fun_l21_n338() + fun_l22_n471 +end + +def fun_l21_n339() + fun_l22_n488 +end + +def fun_l21_n340() + fun_l22_n40 +end + +def fun_l21_n341() + fun_l22_n406 +end + +def fun_l21_n342() + fun_l22_n11 +end + +def fun_l21_n343() + fun_l22_n779 +end + +def fun_l21_n344() + fun_l22_n999 +end + +def fun_l21_n345() + fun_l22_n833 +end + +def fun_l21_n346() + fun_l22_n897 +end + +def fun_l21_n347() + fun_l22_n365 +end + +def fun_l21_n348() + fun_l22_n583 +end + +def fun_l21_n349() + fun_l22_n326 +end + +def fun_l21_n350() + fun_l22_n556 +end + +def fun_l21_n351() + fun_l22_n249 +end + +def fun_l21_n352() + fun_l22_n146 +end + +def fun_l21_n353() + fun_l22_n865 +end + +def fun_l21_n354() + fun_l22_n303 +end + +def fun_l21_n355() + fun_l22_n64 +end + +def fun_l21_n356() + fun_l22_n785 +end + +def fun_l21_n357() + fun_l22_n176 +end + +def fun_l21_n358() + fun_l22_n891 +end + +def fun_l21_n359() + fun_l22_n129 +end + +def fun_l21_n360() + fun_l22_n19 +end + +def fun_l21_n361() + fun_l22_n372 +end + +def fun_l21_n362() + fun_l22_n999 +end + +def fun_l21_n363() + fun_l22_n450 +end + +def fun_l21_n364() + fun_l22_n455 +end + +def fun_l21_n365() + fun_l22_n174 +end + +def fun_l21_n366() + fun_l22_n719 +end + +def fun_l21_n367() + fun_l22_n997 +end + +def fun_l21_n368() + fun_l22_n256 +end + +def fun_l21_n369() + fun_l22_n206 +end + +def fun_l21_n370() + fun_l22_n988 +end + +def fun_l21_n371() + fun_l22_n147 +end + +def fun_l21_n372() + fun_l22_n750 +end + +def fun_l21_n373() + fun_l22_n585 +end + +def fun_l21_n374() + fun_l22_n213 +end + +def fun_l21_n375() + fun_l22_n583 +end + +def fun_l21_n376() + fun_l22_n564 +end + +def fun_l21_n377() + fun_l22_n689 +end + +def fun_l21_n378() + fun_l22_n955 +end + +def fun_l21_n379() + fun_l22_n560 +end + +def fun_l21_n380() + fun_l22_n237 +end + +def fun_l21_n381() + fun_l22_n272 +end + +def fun_l21_n382() + fun_l22_n455 +end + +def fun_l21_n383() + fun_l22_n233 +end + +def fun_l21_n384() + fun_l22_n658 +end + +def fun_l21_n385() + fun_l22_n319 +end + +def fun_l21_n386() + fun_l22_n852 +end + +def fun_l21_n387() + fun_l22_n343 +end + +def fun_l21_n388() + fun_l22_n645 +end + +def fun_l21_n389() + fun_l22_n433 +end + +def fun_l21_n390() + fun_l22_n430 +end + +def fun_l21_n391() + fun_l22_n636 +end + +def fun_l21_n392() + fun_l22_n682 +end + +def fun_l21_n393() + fun_l22_n859 +end + +def fun_l21_n394() + fun_l22_n315 +end + +def fun_l21_n395() + fun_l22_n91 +end + +def fun_l21_n396() + fun_l22_n817 +end + +def fun_l21_n397() + fun_l22_n268 +end + +def fun_l21_n398() + fun_l22_n476 +end + +def fun_l21_n399() + fun_l22_n612 +end + +def fun_l21_n400() + fun_l22_n392 +end + +def fun_l21_n401() + fun_l22_n728 +end + +def fun_l21_n402() + fun_l22_n652 +end + +def fun_l21_n403() + fun_l22_n547 +end + +def fun_l21_n404() + fun_l22_n101 +end + +def fun_l21_n405() + fun_l22_n666 +end + +def fun_l21_n406() + fun_l22_n521 +end + +def fun_l21_n407() + fun_l22_n860 +end + +def fun_l21_n408() + fun_l22_n577 +end + +def fun_l21_n409() + fun_l22_n258 +end + +def fun_l21_n410() + fun_l22_n260 +end + +def fun_l21_n411() + fun_l22_n927 +end + +def fun_l21_n412() + fun_l22_n13 +end + +def fun_l21_n413() + fun_l22_n308 +end + +def fun_l21_n414() + fun_l22_n189 +end + +def fun_l21_n415() + fun_l22_n183 +end + +def fun_l21_n416() + fun_l22_n370 +end + +def fun_l21_n417() + fun_l22_n407 +end + +def fun_l21_n418() + fun_l22_n959 +end + +def fun_l21_n419() + fun_l22_n908 +end + +def fun_l21_n420() + fun_l22_n84 +end + +def fun_l21_n421() + fun_l22_n951 +end + +def fun_l21_n422() + fun_l22_n286 +end + +def fun_l21_n423() + fun_l22_n54 +end + +def fun_l21_n424() + fun_l22_n410 +end + +def fun_l21_n425() + fun_l22_n387 +end + +def fun_l21_n426() + fun_l22_n751 +end + +def fun_l21_n427() + fun_l22_n971 +end + +def fun_l21_n428() + fun_l22_n162 +end + +def fun_l21_n429() + fun_l22_n15 +end + +def fun_l21_n430() + fun_l22_n35 +end + +def fun_l21_n431() + fun_l22_n354 +end + +def fun_l21_n432() + fun_l22_n979 +end + +def fun_l21_n433() + fun_l22_n999 +end + +def fun_l21_n434() + fun_l22_n622 +end + +def fun_l21_n435() + fun_l22_n970 +end + +def fun_l21_n436() + fun_l22_n758 +end + +def fun_l21_n437() + fun_l22_n950 +end + +def fun_l21_n438() + fun_l22_n865 +end + +def fun_l21_n439() + fun_l22_n31 +end + +def fun_l21_n440() + fun_l22_n620 +end + +def fun_l21_n441() + fun_l22_n170 +end + +def fun_l21_n442() + fun_l22_n816 +end + +def fun_l21_n443() + fun_l22_n364 +end + +def fun_l21_n444() + fun_l22_n289 +end + +def fun_l21_n445() + fun_l22_n949 +end + +def fun_l21_n446() + fun_l22_n876 +end + +def fun_l21_n447() + fun_l22_n971 +end + +def fun_l21_n448() + fun_l22_n343 +end + +def fun_l21_n449() + fun_l22_n14 +end + +def fun_l21_n450() + fun_l22_n925 +end + +def fun_l21_n451() + fun_l22_n234 +end + +def fun_l21_n452() + fun_l22_n242 +end + +def fun_l21_n453() + fun_l22_n184 +end + +def fun_l21_n454() + fun_l22_n158 +end + +def fun_l21_n455() + fun_l22_n645 +end + +def fun_l21_n456() + fun_l22_n173 +end + +def fun_l21_n457() + fun_l22_n363 +end + +def fun_l21_n458() + fun_l22_n787 +end + +def fun_l21_n459() + fun_l22_n102 +end + +def fun_l21_n460() + fun_l22_n886 +end + +def fun_l21_n461() + fun_l22_n279 +end + +def fun_l21_n462() + fun_l22_n909 +end + +def fun_l21_n463() + fun_l22_n767 +end + +def fun_l21_n464() + fun_l22_n82 +end + +def fun_l21_n465() + fun_l22_n249 +end + +def fun_l21_n466() + fun_l22_n670 +end + +def fun_l21_n467() + fun_l22_n944 +end + +def fun_l21_n468() + fun_l22_n191 +end + +def fun_l21_n469() + fun_l22_n897 +end + +def fun_l21_n470() + fun_l22_n591 +end + +def fun_l21_n471() + fun_l22_n164 +end + +def fun_l21_n472() + fun_l22_n984 +end + +def fun_l21_n473() + fun_l22_n26 +end + +def fun_l21_n474() + fun_l22_n398 +end + +def fun_l21_n475() + fun_l22_n668 +end + +def fun_l21_n476() + fun_l22_n190 +end + +def fun_l21_n477() + fun_l22_n249 +end + +def fun_l21_n478() + fun_l22_n736 +end + +def fun_l21_n479() + fun_l22_n714 +end + +def fun_l21_n480() + fun_l22_n929 +end + +def fun_l21_n481() + fun_l22_n448 +end + +def fun_l21_n482() + fun_l22_n922 +end + +def fun_l21_n483() + fun_l22_n992 +end + +def fun_l21_n484() + fun_l22_n306 +end + +def fun_l21_n485() + fun_l22_n420 +end + +def fun_l21_n486() + fun_l22_n630 +end + +def fun_l21_n487() + fun_l22_n263 +end + +def fun_l21_n488() + fun_l22_n754 +end + +def fun_l21_n489() + fun_l22_n96 +end + +def fun_l21_n490() + fun_l22_n338 +end + +def fun_l21_n491() + fun_l22_n615 +end + +def fun_l21_n492() + fun_l22_n704 +end + +def fun_l21_n493() + fun_l22_n581 +end + +def fun_l21_n494() + fun_l22_n801 +end + +def fun_l21_n495() + fun_l22_n204 +end + +def fun_l21_n496() + fun_l22_n835 +end + +def fun_l21_n497() + fun_l22_n479 +end + +def fun_l21_n498() + fun_l22_n379 +end + +def fun_l21_n499() + fun_l22_n937 +end + +def fun_l21_n500() + fun_l22_n830 +end + +def fun_l21_n501() + fun_l22_n458 +end + +def fun_l21_n502() + fun_l22_n806 +end + +def fun_l21_n503() + fun_l22_n158 +end + +def fun_l21_n504() + fun_l22_n151 +end + +def fun_l21_n505() + fun_l22_n685 +end + +def fun_l21_n506() + fun_l22_n806 +end + +def fun_l21_n507() + fun_l22_n584 +end + +def fun_l21_n508() + fun_l22_n644 +end + +def fun_l21_n509() + fun_l22_n237 +end + +def fun_l21_n510() + fun_l22_n542 +end + +def fun_l21_n511() + fun_l22_n450 +end + +def fun_l21_n512() + fun_l22_n385 +end + +def fun_l21_n513() + fun_l22_n321 +end + +def fun_l21_n514() + fun_l22_n548 +end + +def fun_l21_n515() + fun_l22_n519 +end + +def fun_l21_n516() + fun_l22_n309 +end + +def fun_l21_n517() + fun_l22_n4 +end + +def fun_l21_n518() + fun_l22_n930 +end + +def fun_l21_n519() + fun_l22_n245 +end + +def fun_l21_n520() + fun_l22_n568 +end + +def fun_l21_n521() + fun_l22_n527 +end + +def fun_l21_n522() + fun_l22_n650 +end + +def fun_l21_n523() + fun_l22_n391 +end + +def fun_l21_n524() + fun_l22_n749 +end + +def fun_l21_n525() + fun_l22_n810 +end + +def fun_l21_n526() + fun_l22_n615 +end + +def fun_l21_n527() + fun_l22_n702 +end + +def fun_l21_n528() + fun_l22_n62 +end + +def fun_l21_n529() + fun_l22_n316 +end + +def fun_l21_n530() + fun_l22_n201 +end + +def fun_l21_n531() + fun_l22_n447 +end + +def fun_l21_n532() + fun_l22_n506 +end + +def fun_l21_n533() + fun_l22_n900 +end + +def fun_l21_n534() + fun_l22_n652 +end + +def fun_l21_n535() + fun_l22_n493 +end + +def fun_l21_n536() + fun_l22_n803 +end + +def fun_l21_n537() + fun_l22_n263 +end + +def fun_l21_n538() + fun_l22_n303 +end + +def fun_l21_n539() + fun_l22_n17 +end + +def fun_l21_n540() + fun_l22_n900 +end + +def fun_l21_n541() + fun_l22_n917 +end + +def fun_l21_n542() + fun_l22_n789 +end + +def fun_l21_n543() + fun_l22_n668 +end + +def fun_l21_n544() + fun_l22_n335 +end + +def fun_l21_n545() + fun_l22_n560 +end + +def fun_l21_n546() + fun_l22_n705 +end + +def fun_l21_n547() + fun_l22_n159 +end + +def fun_l21_n548() + fun_l22_n874 +end + +def fun_l21_n549() + fun_l22_n809 +end + +def fun_l21_n550() + fun_l22_n726 +end + +def fun_l21_n551() + fun_l22_n27 +end + +def fun_l21_n552() + fun_l22_n63 +end + +def fun_l21_n553() + fun_l22_n642 +end + +def fun_l21_n554() + fun_l22_n694 +end + +def fun_l21_n555() + fun_l22_n432 +end + +def fun_l21_n556() + fun_l22_n439 +end + +def fun_l21_n557() + fun_l22_n876 +end + +def fun_l21_n558() + fun_l22_n998 +end + +def fun_l21_n559() + fun_l22_n703 +end + +def fun_l21_n560() + fun_l22_n785 +end + +def fun_l21_n561() + fun_l22_n543 +end + +def fun_l21_n562() + fun_l22_n286 +end + +def fun_l21_n563() + fun_l22_n771 +end + +def fun_l21_n564() + fun_l22_n447 +end + +def fun_l21_n565() + fun_l22_n955 +end + +def fun_l21_n566() + fun_l22_n603 +end + +def fun_l21_n567() + fun_l22_n258 +end + +def fun_l21_n568() + fun_l22_n936 +end + +def fun_l21_n569() + fun_l22_n524 +end + +def fun_l21_n570() + fun_l22_n205 +end + +def fun_l21_n571() + fun_l22_n41 +end + +def fun_l21_n572() + fun_l22_n589 +end + +def fun_l21_n573() + fun_l22_n519 +end + +def fun_l21_n574() + fun_l22_n500 +end + +def fun_l21_n575() + fun_l22_n307 +end + +def fun_l21_n576() + fun_l22_n598 +end + +def fun_l21_n577() + fun_l22_n698 +end + +def fun_l21_n578() + fun_l22_n200 +end + +def fun_l21_n579() + fun_l22_n657 +end + +def fun_l21_n580() + fun_l22_n353 +end + +def fun_l21_n581() + fun_l22_n553 +end + +def fun_l21_n582() + fun_l22_n490 +end + +def fun_l21_n583() + fun_l22_n112 +end + +def fun_l21_n584() + fun_l22_n626 +end + +def fun_l21_n585() + fun_l22_n815 +end + +def fun_l21_n586() + fun_l22_n792 +end + +def fun_l21_n587() + fun_l22_n295 +end + +def fun_l21_n588() + fun_l22_n201 +end + +def fun_l21_n589() + fun_l22_n248 +end + +def fun_l21_n590() + fun_l22_n295 +end + +def fun_l21_n591() + fun_l22_n708 +end + +def fun_l21_n592() + fun_l22_n507 +end + +def fun_l21_n593() + fun_l22_n177 +end + +def fun_l21_n594() + fun_l22_n467 +end + +def fun_l21_n595() + fun_l22_n113 +end + +def fun_l21_n596() + fun_l22_n390 +end + +def fun_l21_n597() + fun_l22_n348 +end + +def fun_l21_n598() + fun_l22_n545 +end + +def fun_l21_n599() + fun_l22_n695 +end + +def fun_l21_n600() + fun_l22_n170 +end + +def fun_l21_n601() + fun_l22_n978 +end + +def fun_l21_n602() + fun_l22_n70 +end + +def fun_l21_n603() + fun_l22_n161 +end + +def fun_l21_n604() + fun_l22_n33 +end + +def fun_l21_n605() + fun_l22_n275 +end + +def fun_l21_n606() + fun_l22_n738 +end + +def fun_l21_n607() + fun_l22_n152 +end + +def fun_l21_n608() + fun_l22_n380 +end + +def fun_l21_n609() + fun_l22_n903 +end + +def fun_l21_n610() + fun_l22_n274 +end + +def fun_l21_n611() + fun_l22_n100 +end + +def fun_l21_n612() + fun_l22_n206 +end + +def fun_l21_n613() + fun_l22_n225 +end + +def fun_l21_n614() + fun_l22_n627 +end + +def fun_l21_n615() + fun_l22_n332 +end + +def fun_l21_n616() + fun_l22_n312 +end + +def fun_l21_n617() + fun_l22_n379 +end + +def fun_l21_n618() + fun_l22_n889 +end + +def fun_l21_n619() + fun_l22_n399 +end + +def fun_l21_n620() + fun_l22_n212 +end + +def fun_l21_n621() + fun_l22_n289 +end + +def fun_l21_n622() + fun_l22_n161 +end + +def fun_l21_n623() + fun_l22_n764 +end + +def fun_l21_n624() + fun_l22_n165 +end + +def fun_l21_n625() + fun_l22_n768 +end + +def fun_l21_n626() + fun_l22_n596 +end + +def fun_l21_n627() + fun_l22_n506 +end + +def fun_l21_n628() + fun_l22_n523 +end + +def fun_l21_n629() + fun_l22_n261 +end + +def fun_l21_n630() + fun_l22_n683 +end + +def fun_l21_n631() + fun_l22_n518 +end + +def fun_l21_n632() + fun_l22_n813 +end + +def fun_l21_n633() + fun_l22_n949 +end + +def fun_l21_n634() + fun_l22_n856 +end + +def fun_l21_n635() + fun_l22_n250 +end + +def fun_l21_n636() + fun_l22_n840 +end + +def fun_l21_n637() + fun_l22_n763 +end + +def fun_l21_n638() + fun_l22_n40 +end + +def fun_l21_n639() + fun_l22_n13 +end + +def fun_l21_n640() + fun_l22_n789 +end + +def fun_l21_n641() + fun_l22_n517 +end + +def fun_l21_n642() + fun_l22_n366 +end + +def fun_l21_n643() + fun_l22_n155 +end + +def fun_l21_n644() + fun_l22_n370 +end + +def fun_l21_n645() + fun_l22_n633 +end + +def fun_l21_n646() + fun_l22_n996 +end + +def fun_l21_n647() + fun_l22_n943 +end + +def fun_l21_n648() + fun_l22_n81 +end + +def fun_l21_n649() + fun_l22_n161 +end + +def fun_l21_n650() + fun_l22_n346 +end + +def fun_l21_n651() + fun_l22_n338 +end + +def fun_l21_n652() + fun_l22_n989 +end + +def fun_l21_n653() + fun_l22_n727 +end + +def fun_l21_n654() + fun_l22_n261 +end + +def fun_l21_n655() + fun_l22_n975 +end + +def fun_l21_n656() + fun_l22_n635 +end + +def fun_l21_n657() + fun_l22_n622 +end + +def fun_l21_n658() + fun_l22_n519 +end + +def fun_l21_n659() + fun_l22_n619 +end + +def fun_l21_n660() + fun_l22_n489 +end + +def fun_l21_n661() + fun_l22_n876 +end + +def fun_l21_n662() + fun_l22_n261 +end + +def fun_l21_n663() + fun_l22_n96 +end + +def fun_l21_n664() + fun_l22_n984 +end + +def fun_l21_n665() + fun_l22_n367 +end + +def fun_l21_n666() + fun_l22_n100 +end + +def fun_l21_n667() + fun_l22_n555 +end + +def fun_l21_n668() + fun_l22_n438 +end + +def fun_l21_n669() + fun_l22_n141 +end + +def fun_l21_n670() + fun_l22_n240 +end + +def fun_l21_n671() + fun_l22_n185 +end + +def fun_l21_n672() + fun_l22_n199 +end + +def fun_l21_n673() + fun_l22_n166 +end + +def fun_l21_n674() + fun_l22_n322 +end + +def fun_l21_n675() + fun_l22_n811 +end + +def fun_l21_n676() + fun_l22_n18 +end + +def fun_l21_n677() + fun_l22_n800 +end + +def fun_l21_n678() + fun_l22_n729 +end + +def fun_l21_n679() + fun_l22_n862 +end + +def fun_l21_n680() + fun_l22_n911 +end + +def fun_l21_n681() + fun_l22_n342 +end + +def fun_l21_n682() + fun_l22_n635 +end + +def fun_l21_n683() + fun_l22_n814 +end + +def fun_l21_n684() + fun_l22_n786 +end + +def fun_l21_n685() + fun_l22_n598 +end + +def fun_l21_n686() + fun_l22_n622 +end + +def fun_l21_n687() + fun_l22_n847 +end + +def fun_l21_n688() + fun_l22_n94 +end + +def fun_l21_n689() + fun_l22_n683 +end + +def fun_l21_n690() + fun_l22_n260 +end + +def fun_l21_n691() + fun_l22_n684 +end + +def fun_l21_n692() + fun_l22_n923 +end + +def fun_l21_n693() + fun_l22_n124 +end + +def fun_l21_n694() + fun_l22_n641 +end + +def fun_l21_n695() + fun_l22_n62 +end + +def fun_l21_n696() + fun_l22_n394 +end + +def fun_l21_n697() + fun_l22_n336 +end + +def fun_l21_n698() + fun_l22_n896 +end + +def fun_l21_n699() + fun_l22_n451 +end + +def fun_l21_n700() + fun_l22_n519 +end + +def fun_l21_n701() + fun_l22_n207 +end + +def fun_l21_n702() + fun_l22_n690 +end + +def fun_l21_n703() + fun_l22_n901 +end + +def fun_l21_n704() + fun_l22_n722 +end + +def fun_l21_n705() + fun_l22_n446 +end + +def fun_l21_n706() + fun_l22_n292 +end + +def fun_l21_n707() + fun_l22_n678 +end + +def fun_l21_n708() + fun_l22_n77 +end + +def fun_l21_n709() + fun_l22_n564 +end + +def fun_l21_n710() + fun_l22_n253 +end + +def fun_l21_n711() + fun_l22_n342 +end + +def fun_l21_n712() + fun_l22_n841 +end + +def fun_l21_n713() + fun_l22_n981 +end + +def fun_l21_n714() + fun_l22_n130 +end + +def fun_l21_n715() + fun_l22_n11 +end + +def fun_l21_n716() + fun_l22_n320 +end + +def fun_l21_n717() + fun_l22_n653 +end + +def fun_l21_n718() + fun_l22_n46 +end + +def fun_l21_n719() + fun_l22_n500 +end + +def fun_l21_n720() + fun_l22_n694 +end + +def fun_l21_n721() + fun_l22_n422 +end + +def fun_l21_n722() + fun_l22_n354 +end + +def fun_l21_n723() + fun_l22_n951 +end + +def fun_l21_n724() + fun_l22_n835 +end + +def fun_l21_n725() + fun_l22_n138 +end + +def fun_l21_n726() + fun_l22_n416 +end + +def fun_l21_n727() + fun_l22_n798 +end + +def fun_l21_n728() + fun_l22_n941 +end + +def fun_l21_n729() + fun_l22_n522 +end + +def fun_l21_n730() + fun_l22_n183 +end + +def fun_l21_n731() + fun_l22_n538 +end + +def fun_l21_n732() + fun_l22_n422 +end + +def fun_l21_n733() + fun_l22_n692 +end + +def fun_l21_n734() + fun_l22_n272 +end + +def fun_l21_n735() + fun_l22_n434 +end + +def fun_l21_n736() + fun_l22_n876 +end + +def fun_l21_n737() + fun_l22_n685 +end + +def fun_l21_n738() + fun_l22_n338 +end + +def fun_l21_n739() + fun_l22_n835 +end + +def fun_l21_n740() + fun_l22_n307 +end + +def fun_l21_n741() + fun_l22_n270 +end + +def fun_l21_n742() + fun_l22_n626 +end + +def fun_l21_n743() + fun_l22_n92 +end + +def fun_l21_n744() + fun_l22_n532 +end + +def fun_l21_n745() + fun_l22_n508 +end + +def fun_l21_n746() + fun_l22_n866 +end + +def fun_l21_n747() + fun_l22_n474 +end + +def fun_l21_n748() + fun_l22_n697 +end + +def fun_l21_n749() + fun_l22_n952 +end + +def fun_l21_n750() + fun_l22_n835 +end + +def fun_l21_n751() + fun_l22_n21 +end + +def fun_l21_n752() + fun_l22_n386 +end + +def fun_l21_n753() + fun_l22_n55 +end + +def fun_l21_n754() + fun_l22_n727 +end + +def fun_l21_n755() + fun_l22_n944 +end + +def fun_l21_n756() + fun_l22_n850 +end + +def fun_l21_n757() + fun_l22_n305 +end + +def fun_l21_n758() + fun_l22_n502 +end + +def fun_l21_n759() + fun_l22_n544 +end + +def fun_l21_n760() + fun_l22_n308 +end + +def fun_l21_n761() + fun_l22_n3 +end + +def fun_l21_n762() + fun_l22_n724 +end + +def fun_l21_n763() + fun_l22_n87 +end + +def fun_l21_n764() + fun_l22_n683 +end + +def fun_l21_n765() + fun_l22_n597 +end + +def fun_l21_n766() + fun_l22_n641 +end + +def fun_l21_n767() + fun_l22_n614 +end + +def fun_l21_n768() + fun_l22_n668 +end + +def fun_l21_n769() + fun_l22_n320 +end + +def fun_l21_n770() + fun_l22_n923 +end + +def fun_l21_n771() + fun_l22_n762 +end + +def fun_l21_n772() + fun_l22_n545 +end + +def fun_l21_n773() + fun_l22_n692 +end + +def fun_l21_n774() + fun_l22_n237 +end + +def fun_l21_n775() + fun_l22_n373 +end + +def fun_l21_n776() + fun_l22_n44 +end + +def fun_l21_n777() + fun_l22_n78 +end + +def fun_l21_n778() + fun_l22_n42 +end + +def fun_l21_n779() + fun_l22_n133 +end + +def fun_l21_n780() + fun_l22_n428 +end + +def fun_l21_n781() + fun_l22_n689 +end + +def fun_l21_n782() + fun_l22_n903 +end + +def fun_l21_n783() + fun_l22_n758 +end + +def fun_l21_n784() + fun_l22_n762 +end + +def fun_l21_n785() + fun_l22_n516 +end + +def fun_l21_n786() + fun_l22_n466 +end + +def fun_l21_n787() + fun_l22_n373 +end + +def fun_l21_n788() + fun_l22_n390 +end + +def fun_l21_n789() + fun_l22_n109 +end + +def fun_l21_n790() + fun_l22_n865 +end + +def fun_l21_n791() + fun_l22_n112 +end + +def fun_l21_n792() + fun_l22_n865 +end + +def fun_l21_n793() + fun_l22_n645 +end + +def fun_l21_n794() + fun_l22_n621 +end + +def fun_l21_n795() + fun_l22_n758 +end + +def fun_l21_n796() + fun_l22_n519 +end + +def fun_l21_n797() + fun_l22_n104 +end + +def fun_l21_n798() + fun_l22_n79 +end + +def fun_l21_n799() + fun_l22_n840 +end + +def fun_l21_n800() + fun_l22_n613 +end + +def fun_l21_n801() + fun_l22_n982 +end + +def fun_l21_n802() + fun_l22_n484 +end + +def fun_l21_n803() + fun_l22_n321 +end + +def fun_l21_n804() + fun_l22_n445 +end + +def fun_l21_n805() + fun_l22_n857 +end + +def fun_l21_n806() + fun_l22_n811 +end + +def fun_l21_n807() + fun_l22_n763 +end + +def fun_l21_n808() + fun_l22_n40 +end + +def fun_l21_n809() + fun_l22_n376 +end + +def fun_l21_n810() + fun_l22_n111 +end + +def fun_l21_n811() + fun_l22_n318 +end + +def fun_l21_n812() + fun_l22_n455 +end + +def fun_l21_n813() + fun_l22_n860 +end + +def fun_l21_n814() + fun_l22_n185 +end + +def fun_l21_n815() + fun_l22_n932 +end + +def fun_l21_n816() + fun_l22_n673 +end + +def fun_l21_n817() + fun_l22_n413 +end + +def fun_l21_n818() + fun_l22_n927 +end + +def fun_l21_n819() + fun_l22_n827 +end + +def fun_l21_n820() + fun_l22_n572 +end + +def fun_l21_n821() + fun_l22_n682 +end + +def fun_l21_n822() + fun_l22_n810 +end + +def fun_l21_n823() + fun_l22_n492 +end + +def fun_l21_n824() + fun_l22_n677 +end + +def fun_l21_n825() + fun_l22_n658 +end + +def fun_l21_n826() + fun_l22_n584 +end + +def fun_l21_n827() + fun_l22_n360 +end + +def fun_l21_n828() + fun_l22_n677 +end + +def fun_l21_n829() + fun_l22_n669 +end + +def fun_l21_n830() + fun_l22_n209 +end + +def fun_l21_n831() + fun_l22_n526 +end + +def fun_l21_n832() + fun_l22_n820 +end + +def fun_l21_n833() + fun_l22_n81 +end + +def fun_l21_n834() + fun_l22_n140 +end + +def fun_l21_n835() + fun_l22_n407 +end + +def fun_l21_n836() + fun_l22_n705 +end + +def fun_l21_n837() + fun_l22_n785 +end + +def fun_l21_n838() + fun_l22_n13 +end + +def fun_l21_n839() + fun_l22_n490 +end + +def fun_l21_n840() + fun_l22_n835 +end + +def fun_l21_n841() + fun_l22_n410 +end + +def fun_l21_n842() + fun_l22_n411 +end + +def fun_l21_n843() + fun_l22_n315 +end + +def fun_l21_n844() + fun_l22_n830 +end + +def fun_l21_n845() + fun_l22_n417 +end + +def fun_l21_n846() + fun_l22_n66 +end + +def fun_l21_n847() + fun_l22_n484 +end + +def fun_l21_n848() + fun_l22_n398 +end + +def fun_l21_n849() + fun_l22_n191 +end + +def fun_l21_n850() + fun_l22_n939 +end + +def fun_l21_n851() + fun_l22_n233 +end + +def fun_l21_n852() + fun_l22_n554 +end + +def fun_l21_n853() + fun_l22_n205 +end + +def fun_l21_n854() + fun_l22_n86 +end + +def fun_l21_n855() + fun_l22_n396 +end + +def fun_l21_n856() + fun_l22_n815 +end + +def fun_l21_n857() + fun_l22_n286 +end + +def fun_l21_n858() + fun_l22_n874 +end + +def fun_l21_n859() + fun_l22_n274 +end + +def fun_l21_n860() + fun_l22_n517 +end + +def fun_l21_n861() + fun_l22_n295 +end + +def fun_l21_n862() + fun_l22_n576 +end + +def fun_l21_n863() + fun_l22_n745 +end + +def fun_l21_n864() + fun_l22_n842 +end + +def fun_l21_n865() + fun_l22_n180 +end + +def fun_l21_n866() + fun_l22_n817 +end + +def fun_l21_n867() + fun_l22_n663 +end + +def fun_l21_n868() + fun_l22_n298 +end + +def fun_l21_n869() + fun_l22_n328 +end + +def fun_l21_n870() + fun_l22_n863 +end + +def fun_l21_n871() + fun_l22_n669 +end + +def fun_l21_n872() + fun_l22_n494 +end + +def fun_l21_n873() + fun_l22_n483 +end + +def fun_l21_n874() + fun_l22_n977 +end + +def fun_l21_n875() + fun_l22_n797 +end + +def fun_l21_n876() + fun_l22_n258 +end + +def fun_l21_n877() + fun_l22_n701 +end + +def fun_l21_n878() + fun_l22_n791 +end + +def fun_l21_n879() + fun_l22_n201 +end + +def fun_l21_n880() + fun_l22_n994 +end + +def fun_l21_n881() + fun_l22_n678 +end + +def fun_l21_n882() + fun_l22_n653 +end + +def fun_l21_n883() + fun_l22_n339 +end + +def fun_l21_n884() + fun_l22_n701 +end + +def fun_l21_n885() + fun_l22_n188 +end + +def fun_l21_n886() + fun_l22_n607 +end + +def fun_l21_n887() + fun_l22_n108 +end + +def fun_l21_n888() + fun_l22_n190 +end + +def fun_l21_n889() + fun_l22_n581 +end + +def fun_l21_n890() + fun_l22_n283 +end + +def fun_l21_n891() + fun_l22_n743 +end + +def fun_l21_n892() + fun_l22_n861 +end + +def fun_l21_n893() + fun_l22_n998 +end + +def fun_l21_n894() + fun_l22_n752 +end + +def fun_l21_n895() + fun_l22_n762 +end + +def fun_l21_n896() + fun_l22_n41 +end + +def fun_l21_n897() + fun_l22_n820 +end + +def fun_l21_n898() + fun_l22_n510 +end + +def fun_l21_n899() + fun_l22_n974 +end + +def fun_l21_n900() + fun_l22_n524 +end + +def fun_l21_n901() + fun_l22_n771 +end + +def fun_l21_n902() + fun_l22_n376 +end + +def fun_l21_n903() + fun_l22_n684 +end + +def fun_l21_n904() + fun_l22_n595 +end + +def fun_l21_n905() + fun_l22_n934 +end + +def fun_l21_n906() + fun_l22_n228 +end + +def fun_l21_n907() + fun_l22_n685 +end + +def fun_l21_n908() + fun_l22_n549 +end + +def fun_l21_n909() + fun_l22_n374 +end + +def fun_l21_n910() + fun_l22_n934 +end + +def fun_l21_n911() + fun_l22_n660 +end + +def fun_l21_n912() + fun_l22_n756 +end + +def fun_l21_n913() + fun_l22_n32 +end + +def fun_l21_n914() + fun_l22_n660 +end + +def fun_l21_n915() + fun_l22_n52 +end + +def fun_l21_n916() + fun_l22_n750 +end + +def fun_l21_n917() + fun_l22_n239 +end + +def fun_l21_n918() + fun_l22_n290 +end + +def fun_l21_n919() + fun_l22_n914 +end + +def fun_l21_n920() + fun_l22_n257 +end + +def fun_l21_n921() + fun_l22_n307 +end + +def fun_l21_n922() + fun_l22_n949 +end + +def fun_l21_n923() + fun_l22_n344 +end + +def fun_l21_n924() + fun_l22_n479 +end + +def fun_l21_n925() + fun_l22_n306 +end + +def fun_l21_n926() + fun_l22_n361 +end + +def fun_l21_n927() + fun_l22_n429 +end + +def fun_l21_n928() + fun_l22_n145 +end + +def fun_l21_n929() + fun_l22_n874 +end + +def fun_l21_n930() + fun_l22_n127 +end + +def fun_l21_n931() + fun_l22_n909 +end + +def fun_l21_n932() + fun_l22_n784 +end + +def fun_l21_n933() + fun_l22_n966 +end + +def fun_l21_n934() + fun_l22_n789 +end + +def fun_l21_n935() + fun_l22_n787 +end + +def fun_l21_n936() + fun_l22_n325 +end + +def fun_l21_n937() + fun_l22_n666 +end + +def fun_l21_n938() + fun_l22_n630 +end + +def fun_l21_n939() + fun_l22_n321 +end + +def fun_l21_n940() + fun_l22_n634 +end + +def fun_l21_n941() + fun_l22_n991 +end + +def fun_l21_n942() + fun_l22_n978 +end + +def fun_l21_n943() + fun_l22_n583 +end + +def fun_l21_n944() + fun_l22_n835 +end + +def fun_l21_n945() + fun_l22_n968 +end + +def fun_l21_n946() + fun_l22_n88 +end + +def fun_l21_n947() + fun_l22_n484 +end + +def fun_l21_n948() + fun_l22_n82 +end + +def fun_l21_n949() + fun_l22_n343 +end + +def fun_l21_n950() + fun_l22_n369 +end + +def fun_l21_n951() + fun_l22_n565 +end + +def fun_l21_n952() + fun_l22_n307 +end + +def fun_l21_n953() + fun_l22_n573 +end + +def fun_l21_n954() + fun_l22_n363 +end + +def fun_l21_n955() + fun_l22_n853 +end + +def fun_l21_n956() + fun_l22_n132 +end + +def fun_l21_n957() + fun_l22_n13 +end + +def fun_l21_n958() + fun_l22_n819 +end + +def fun_l21_n959() + fun_l22_n124 +end + +def fun_l21_n960() + fun_l22_n898 +end + +def fun_l21_n961() + fun_l22_n942 +end + +def fun_l21_n962() + fun_l22_n917 +end + +def fun_l21_n963() + fun_l22_n199 +end + +def fun_l21_n964() + fun_l22_n651 +end + +def fun_l21_n965() + fun_l22_n80 +end + +def fun_l21_n966() + fun_l22_n415 +end + +def fun_l21_n967() + fun_l22_n230 +end + +def fun_l21_n968() + fun_l22_n929 +end + +def fun_l21_n969() + fun_l22_n889 +end + +def fun_l21_n970() + fun_l22_n620 +end + +def fun_l21_n971() + fun_l22_n588 +end + +def fun_l21_n972() + fun_l22_n284 +end + +def fun_l21_n973() + fun_l22_n767 +end + +def fun_l21_n974() + fun_l22_n568 +end + +def fun_l21_n975() + fun_l22_n687 +end + +def fun_l21_n976() + fun_l22_n640 +end + +def fun_l21_n977() + fun_l22_n739 +end + +def fun_l21_n978() + fun_l22_n81 +end + +def fun_l21_n979() + fun_l22_n216 +end + +def fun_l21_n980() + fun_l22_n347 +end + +def fun_l21_n981() + fun_l22_n228 +end + +def fun_l21_n982() + fun_l22_n947 +end + +def fun_l21_n983() + fun_l22_n563 +end + +def fun_l21_n984() + fun_l22_n839 +end + +def fun_l21_n985() + fun_l22_n759 +end + +def fun_l21_n986() + fun_l22_n138 +end + +def fun_l21_n987() + fun_l22_n269 +end + +def fun_l21_n988() + fun_l22_n239 +end + +def fun_l21_n989() + fun_l22_n254 +end + +def fun_l21_n990() + fun_l22_n802 +end + +def fun_l21_n991() + fun_l22_n368 +end + +def fun_l21_n992() + fun_l22_n854 +end + +def fun_l21_n993() + fun_l22_n463 +end + +def fun_l21_n994() + fun_l22_n722 +end + +def fun_l21_n995() + fun_l22_n770 +end + +def fun_l21_n996() + fun_l22_n635 +end + +def fun_l21_n997() + fun_l22_n207 +end + +def fun_l21_n998() + fun_l22_n271 +end + +def fun_l21_n999() + fun_l22_n815 +end + +def fun_l22_n0() + fun_l23_n781 +end + +def fun_l22_n1() + fun_l23_n330 +end + +def fun_l22_n2() + fun_l23_n493 +end + +def fun_l22_n3() + fun_l23_n513 +end + +def fun_l22_n4() + fun_l23_n515 +end + +def fun_l22_n5() + fun_l23_n746 +end + +def fun_l22_n6() + fun_l23_n739 +end + +def fun_l22_n7() + fun_l23_n270 +end + +def fun_l22_n8() + fun_l23_n918 +end + +def fun_l22_n9() + fun_l23_n425 +end + +def fun_l22_n10() + fun_l23_n361 +end + +def fun_l22_n11() + fun_l23_n696 +end + +def fun_l22_n12() + fun_l23_n344 +end + +def fun_l22_n13() + fun_l23_n446 +end + +def fun_l22_n14() + fun_l23_n487 +end + +def fun_l22_n15() + fun_l23_n94 +end + +def fun_l22_n16() + fun_l23_n206 +end + +def fun_l22_n17() + fun_l23_n10 +end + +def fun_l22_n18() + fun_l23_n221 +end + +def fun_l22_n19() + fun_l23_n185 +end + +def fun_l22_n20() + fun_l23_n869 +end + +def fun_l22_n21() + fun_l23_n788 +end + +def fun_l22_n22() + fun_l23_n173 +end + +def fun_l22_n23() + fun_l23_n73 +end + +def fun_l22_n24() + fun_l23_n486 +end + +def fun_l22_n25() + fun_l23_n631 +end + +def fun_l22_n26() + fun_l23_n849 +end + +def fun_l22_n27() + fun_l23_n429 +end + +def fun_l22_n28() + fun_l23_n365 +end + +def fun_l22_n29() + fun_l23_n429 +end + +def fun_l22_n30() + fun_l23_n411 +end + +def fun_l22_n31() + fun_l23_n229 +end + +def fun_l22_n32() + fun_l23_n921 +end + +def fun_l22_n33() + fun_l23_n705 +end + +def fun_l22_n34() + fun_l23_n660 +end + +def fun_l22_n35() + fun_l23_n264 +end + +def fun_l22_n36() + fun_l23_n395 +end + +def fun_l22_n37() + fun_l23_n722 +end + +def fun_l22_n38() + fun_l23_n402 +end + +def fun_l22_n39() + fun_l23_n686 +end + +def fun_l22_n40() + fun_l23_n833 +end + +def fun_l22_n41() + fun_l23_n573 +end + +def fun_l22_n42() + fun_l23_n299 +end + +def fun_l22_n43() + fun_l23_n397 +end + +def fun_l22_n44() + fun_l23_n387 +end + +def fun_l22_n45() + fun_l23_n385 +end + +def fun_l22_n46() + fun_l23_n341 +end + +def fun_l22_n47() + fun_l23_n862 +end + +def fun_l22_n48() + fun_l23_n109 +end + +def fun_l22_n49() + fun_l23_n583 +end + +def fun_l22_n50() + fun_l23_n126 +end + +def fun_l22_n51() + fun_l23_n563 +end + +def fun_l22_n52() + fun_l23_n947 +end + +def fun_l22_n53() + fun_l23_n329 +end + +def fun_l22_n54() + fun_l23_n903 +end + +def fun_l22_n55() + fun_l23_n11 +end + +def fun_l22_n56() + fun_l23_n520 +end + +def fun_l22_n57() + fun_l23_n815 +end + +def fun_l22_n58() + fun_l23_n224 +end + +def fun_l22_n59() + fun_l23_n144 +end + +def fun_l22_n60() + fun_l23_n513 +end + +def fun_l22_n61() + fun_l23_n572 +end + +def fun_l22_n62() + fun_l23_n33 +end + +def fun_l22_n63() + fun_l23_n39 +end + +def fun_l22_n64() + fun_l23_n360 +end + +def fun_l22_n65() + fun_l23_n6 +end + +def fun_l22_n66() + fun_l23_n244 +end + +def fun_l22_n67() + fun_l23_n425 +end + +def fun_l22_n68() + fun_l23_n472 +end + +def fun_l22_n69() + fun_l23_n88 +end + +def fun_l22_n70() + fun_l23_n888 +end + +def fun_l22_n71() + fun_l23_n215 +end + +def fun_l22_n72() + fun_l23_n408 +end + +def fun_l22_n73() + fun_l23_n753 +end + +def fun_l22_n74() + fun_l23_n4 +end + +def fun_l22_n75() + fun_l23_n623 +end + +def fun_l22_n76() + fun_l23_n602 +end + +def fun_l22_n77() + fun_l23_n430 +end + +def fun_l22_n78() + fun_l23_n223 +end + +def fun_l22_n79() + fun_l23_n631 +end + +def fun_l22_n80() + fun_l23_n931 +end + +def fun_l22_n81() + fun_l23_n84 +end + +def fun_l22_n82() + fun_l23_n541 +end + +def fun_l22_n83() + fun_l23_n329 +end + +def fun_l22_n84() + fun_l23_n174 +end + +def fun_l22_n85() + fun_l23_n649 +end + +def fun_l22_n86() + fun_l23_n503 +end + +def fun_l22_n87() + fun_l23_n336 +end + +def fun_l22_n88() + fun_l23_n126 +end + +def fun_l22_n89() + fun_l23_n556 +end + +def fun_l22_n90() + fun_l23_n793 +end + +def fun_l22_n91() + fun_l23_n276 +end + +def fun_l22_n92() + fun_l23_n374 +end + +def fun_l22_n93() + fun_l23_n638 +end + +def fun_l22_n94() + fun_l23_n614 +end + +def fun_l22_n95() + fun_l23_n851 +end + +def fun_l22_n96() + fun_l23_n422 +end + +def fun_l22_n97() + fun_l23_n716 +end + +def fun_l22_n98() + fun_l23_n521 +end + +def fun_l22_n99() + fun_l23_n484 +end + +def fun_l22_n100() + fun_l23_n155 +end + +def fun_l22_n101() + fun_l23_n863 +end + +def fun_l22_n102() + fun_l23_n5 +end + +def fun_l22_n103() + fun_l23_n667 +end + +def fun_l22_n104() + fun_l23_n633 +end + +def fun_l22_n105() + fun_l23_n392 +end + +def fun_l22_n106() + fun_l23_n859 +end + +def fun_l22_n107() + fun_l23_n930 +end + +def fun_l22_n108() + fun_l23_n858 +end + +def fun_l22_n109() + fun_l23_n266 +end + +def fun_l22_n110() + fun_l23_n567 +end + +def fun_l22_n111() + fun_l23_n116 +end + +def fun_l22_n112() + fun_l23_n221 +end + +def fun_l22_n113() + fun_l23_n650 +end + +def fun_l22_n114() + fun_l23_n309 +end + +def fun_l22_n115() + fun_l23_n290 +end + +def fun_l22_n116() + fun_l23_n305 +end + +def fun_l22_n117() + fun_l23_n655 +end + +def fun_l22_n118() + fun_l23_n390 +end + +def fun_l22_n119() + fun_l23_n561 +end + +def fun_l22_n120() + fun_l23_n977 +end + +def fun_l22_n121() + fun_l23_n920 +end + +def fun_l22_n122() + fun_l23_n662 +end + +def fun_l22_n123() + fun_l23_n453 +end + +def fun_l22_n124() + fun_l23_n331 +end + +def fun_l22_n125() + fun_l23_n135 +end + +def fun_l22_n126() + fun_l23_n822 +end + +def fun_l22_n127() + fun_l23_n726 +end + +def fun_l22_n128() + fun_l23_n93 +end + +def fun_l22_n129() + fun_l23_n309 +end + +def fun_l22_n130() + fun_l23_n303 +end + +def fun_l22_n131() + fun_l23_n907 +end + +def fun_l22_n132() + fun_l23_n616 +end + +def fun_l22_n133() + fun_l23_n266 +end + +def fun_l22_n134() + fun_l23_n920 +end + +def fun_l22_n135() + fun_l23_n972 +end + +def fun_l22_n136() + fun_l23_n510 +end + +def fun_l22_n137() + fun_l23_n40 +end + +def fun_l22_n138() + fun_l23_n598 +end + +def fun_l22_n139() + fun_l23_n491 +end + +def fun_l22_n140() + fun_l23_n590 +end + +def fun_l22_n141() + fun_l23_n400 +end + +def fun_l22_n142() + fun_l23_n47 +end + +def fun_l22_n143() + fun_l23_n669 +end + +def fun_l22_n144() + fun_l23_n471 +end + +def fun_l22_n145() + fun_l23_n749 +end + +def fun_l22_n146() + fun_l23_n5 +end + +def fun_l22_n147() + fun_l23_n895 +end + +def fun_l22_n148() + fun_l23_n92 +end + +def fun_l22_n149() + fun_l23_n940 +end + +def fun_l22_n150() + fun_l23_n254 +end + +def fun_l22_n151() + fun_l23_n521 +end + +def fun_l22_n152() + fun_l23_n482 +end + +def fun_l22_n153() + fun_l23_n576 +end + +def fun_l22_n154() + fun_l23_n657 +end + +def fun_l22_n155() + fun_l23_n897 +end + +def fun_l22_n156() + fun_l23_n679 +end + +def fun_l22_n157() + fun_l23_n894 +end + +def fun_l22_n158() + fun_l23_n496 +end + +def fun_l22_n159() + fun_l23_n575 +end + +def fun_l22_n160() + fun_l23_n751 +end + +def fun_l22_n161() + fun_l23_n357 +end + +def fun_l22_n162() + fun_l23_n665 +end + +def fun_l22_n163() + fun_l23_n653 +end + +def fun_l22_n164() + fun_l23_n904 +end + +def fun_l22_n165() + fun_l23_n127 +end + +def fun_l22_n166() + fun_l23_n737 +end + +def fun_l22_n167() + fun_l23_n710 +end + +def fun_l22_n168() + fun_l23_n285 +end + +def fun_l22_n169() + fun_l23_n804 +end + +def fun_l22_n170() + fun_l23_n766 +end + +def fun_l22_n171() + fun_l23_n442 +end + +def fun_l22_n172() + fun_l23_n392 +end + +def fun_l22_n173() + fun_l23_n512 +end + +def fun_l22_n174() + fun_l23_n752 +end + +def fun_l22_n175() + fun_l23_n856 +end + +def fun_l22_n176() + fun_l23_n840 +end + +def fun_l22_n177() + fun_l23_n445 +end + +def fun_l22_n178() + fun_l23_n483 +end + +def fun_l22_n179() + fun_l23_n676 +end + +def fun_l22_n180() + fun_l23_n619 +end + +def fun_l22_n181() + fun_l23_n132 +end + +def fun_l22_n182() + fun_l23_n600 +end + +def fun_l22_n183() + fun_l23_n399 +end + +def fun_l22_n184() + fun_l23_n199 +end + +def fun_l22_n185() + fun_l23_n152 +end + +def fun_l22_n186() + fun_l23_n848 +end + +def fun_l22_n187() + fun_l23_n50 +end + +def fun_l22_n188() + fun_l23_n524 +end + +def fun_l22_n189() + fun_l23_n472 +end + +def fun_l22_n190() + fun_l23_n146 +end + +def fun_l22_n191() + fun_l23_n115 +end + +def fun_l22_n192() + fun_l23_n701 +end + +def fun_l22_n193() + fun_l23_n916 +end + +def fun_l22_n194() + fun_l23_n362 +end + +def fun_l22_n195() + fun_l23_n546 +end + +def fun_l22_n196() + fun_l23_n983 +end + +def fun_l22_n197() + fun_l23_n898 +end + +def fun_l22_n198() + fun_l23_n93 +end + +def fun_l22_n199() + fun_l23_n587 +end + +def fun_l22_n200() + fun_l23_n84 +end + +def fun_l22_n201() + fun_l23_n919 +end + +def fun_l22_n202() + fun_l23_n813 +end + +def fun_l22_n203() + fun_l23_n481 +end + +def fun_l22_n204() + fun_l23_n806 +end + +def fun_l22_n205() + fun_l23_n329 +end + +def fun_l22_n206() + fun_l23_n873 +end + +def fun_l22_n207() + fun_l23_n922 +end + +def fun_l22_n208() + fun_l23_n125 +end + +def fun_l22_n209() + fun_l23_n861 +end + +def fun_l22_n210() + fun_l23_n50 +end + +def fun_l22_n211() + fun_l23_n737 +end + +def fun_l22_n212() + fun_l23_n55 +end + +def fun_l22_n213() + fun_l23_n594 +end + +def fun_l22_n214() + fun_l23_n786 +end + +def fun_l22_n215() + fun_l23_n33 +end + +def fun_l22_n216() + fun_l23_n332 +end + +def fun_l22_n217() + fun_l23_n72 +end + +def fun_l22_n218() + fun_l23_n619 +end + +def fun_l22_n219() + fun_l23_n994 +end + +def fun_l22_n220() + fun_l23_n94 +end + +def fun_l22_n221() + fun_l23_n562 +end + +def fun_l22_n222() + fun_l23_n742 +end + +def fun_l22_n223() + fun_l23_n397 +end + +def fun_l22_n224() + fun_l23_n641 +end + +def fun_l22_n225() + fun_l23_n233 +end + +def fun_l22_n226() + fun_l23_n876 +end + +def fun_l22_n227() + fun_l23_n13 +end + +def fun_l22_n228() + fun_l23_n524 +end + +def fun_l22_n229() + fun_l23_n738 +end + +def fun_l22_n230() + fun_l23_n34 +end + +def fun_l22_n231() + fun_l23_n391 +end + +def fun_l22_n232() + fun_l23_n930 +end + +def fun_l22_n233() + fun_l23_n714 +end + +def fun_l22_n234() + fun_l23_n755 +end + +def fun_l22_n235() + fun_l23_n826 +end + +def fun_l22_n236() + fun_l23_n797 +end + +def fun_l22_n237() + fun_l23_n890 +end + +def fun_l22_n238() + fun_l23_n586 +end + +def fun_l22_n239() + fun_l23_n924 +end + +def fun_l22_n240() + fun_l23_n704 +end + +def fun_l22_n241() + fun_l23_n547 +end + +def fun_l22_n242() + fun_l23_n581 +end + +def fun_l22_n243() + fun_l23_n402 +end + +def fun_l22_n244() + fun_l23_n719 +end + +def fun_l22_n245() + fun_l23_n471 +end + +def fun_l22_n246() + fun_l23_n750 +end + +def fun_l22_n247() + fun_l23_n33 +end + +def fun_l22_n248() + fun_l23_n304 +end + +def fun_l22_n249() + fun_l23_n847 +end + +def fun_l22_n250() + fun_l23_n814 +end + +def fun_l22_n251() + fun_l23_n724 +end + +def fun_l22_n252() + fun_l23_n105 +end + +def fun_l22_n253() + fun_l23_n863 +end + +def fun_l22_n254() + fun_l23_n282 +end + +def fun_l22_n255() + fun_l23_n586 +end + +def fun_l22_n256() + fun_l23_n524 +end + +def fun_l22_n257() + fun_l23_n772 +end + +def fun_l22_n258() + fun_l23_n641 +end + +def fun_l22_n259() + fun_l23_n962 +end + +def fun_l22_n260() + fun_l23_n737 +end + +def fun_l22_n261() + fun_l23_n941 +end + +def fun_l22_n262() + fun_l23_n432 +end + +def fun_l22_n263() + fun_l23_n400 +end + +def fun_l22_n264() + fun_l23_n19 +end + +def fun_l22_n265() + fun_l23_n485 +end + +def fun_l22_n266() + fun_l23_n210 +end + +def fun_l22_n267() + fun_l23_n961 +end + +def fun_l22_n268() + fun_l23_n953 +end + +def fun_l22_n269() + fun_l23_n987 +end + +def fun_l22_n270() + fun_l23_n855 +end + +def fun_l22_n271() + fun_l23_n789 +end + +def fun_l22_n272() + fun_l23_n708 +end + +def fun_l22_n273() + fun_l23_n645 +end + +def fun_l22_n274() + fun_l23_n924 +end + +def fun_l22_n275() + fun_l23_n496 +end + +def fun_l22_n276() + fun_l23_n763 +end + +def fun_l22_n277() + fun_l23_n937 +end + +def fun_l22_n278() + fun_l23_n679 +end + +def fun_l22_n279() + fun_l23_n678 +end + +def fun_l22_n280() + fun_l23_n756 +end + +def fun_l22_n281() + fun_l23_n198 +end + +def fun_l22_n282() + fun_l23_n377 +end + +def fun_l22_n283() + fun_l23_n352 +end + +def fun_l22_n284() + fun_l23_n211 +end + +def fun_l22_n285() + fun_l23_n137 +end + +def fun_l22_n286() + fun_l23_n257 +end + +def fun_l22_n287() + fun_l23_n878 +end + +def fun_l22_n288() + fun_l23_n182 +end + +def fun_l22_n289() + fun_l23_n969 +end + +def fun_l22_n290() + fun_l23_n622 +end + +def fun_l22_n291() + fun_l23_n473 +end + +def fun_l22_n292() + fun_l23_n767 +end + +def fun_l22_n293() + fun_l23_n496 +end + +def fun_l22_n294() + fun_l23_n463 +end + +def fun_l22_n295() + fun_l23_n600 +end + +def fun_l22_n296() + fun_l23_n262 +end + +def fun_l22_n297() + fun_l23_n353 +end + +def fun_l22_n298() + fun_l23_n235 +end + +def fun_l22_n299() + fun_l23_n680 +end + +def fun_l22_n300() + fun_l23_n169 +end + +def fun_l22_n301() + fun_l23_n764 +end + +def fun_l22_n302() + fun_l23_n105 +end + +def fun_l22_n303() + fun_l23_n616 +end + +def fun_l22_n304() + fun_l23_n143 +end + +def fun_l22_n305() + fun_l23_n612 +end + +def fun_l22_n306() + fun_l23_n30 +end + +def fun_l22_n307() + fun_l23_n946 +end + +def fun_l22_n308() + fun_l23_n590 +end + +def fun_l22_n309() + fun_l23_n374 +end + +def fun_l22_n310() + fun_l23_n640 +end + +def fun_l22_n311() + fun_l23_n156 +end + +def fun_l22_n312() + fun_l23_n689 +end + +def fun_l22_n313() + fun_l23_n684 +end + +def fun_l22_n314() + fun_l23_n915 +end + +def fun_l22_n315() + fun_l23_n536 +end + +def fun_l22_n316() + fun_l23_n408 +end + +def fun_l22_n317() + fun_l23_n644 +end + +def fun_l22_n318() + fun_l23_n401 +end + +def fun_l22_n319() + fun_l23_n312 +end + +def fun_l22_n320() + fun_l23_n280 +end + +def fun_l22_n321() + fun_l23_n901 +end + +def fun_l22_n322() + fun_l23_n411 +end + +def fun_l22_n323() + fun_l23_n709 +end + +def fun_l22_n324() + fun_l23_n829 +end + +def fun_l22_n325() + fun_l23_n353 +end + +def fun_l22_n326() + fun_l23_n408 +end + +def fun_l22_n327() + fun_l23_n786 +end + +def fun_l22_n328() + fun_l23_n980 +end + +def fun_l22_n329() + fun_l23_n60 +end + +def fun_l22_n330() + fun_l23_n367 +end + +def fun_l22_n331() + fun_l23_n617 +end + +def fun_l22_n332() + fun_l23_n155 +end + +def fun_l22_n333() + fun_l23_n537 +end + +def fun_l22_n334() + fun_l23_n759 +end + +def fun_l22_n335() + fun_l23_n998 +end + +def fun_l22_n336() + fun_l23_n361 +end + +def fun_l22_n337() + fun_l23_n64 +end + +def fun_l22_n338() + fun_l23_n992 +end + +def fun_l22_n339() + fun_l23_n312 +end + +def fun_l22_n340() + fun_l23_n91 +end + +def fun_l22_n341() + fun_l23_n73 +end + +def fun_l22_n342() + fun_l23_n443 +end + +def fun_l22_n343() + fun_l23_n453 +end + +def fun_l22_n344() + fun_l23_n723 +end + +def fun_l22_n345() + fun_l23_n429 +end + +def fun_l22_n346() + fun_l23_n437 +end + +def fun_l22_n347() + fun_l23_n406 +end + +def fun_l22_n348() + fun_l23_n110 +end + +def fun_l22_n349() + fun_l23_n862 +end + +def fun_l22_n350() + fun_l23_n247 +end + +def fun_l22_n351() + fun_l23_n367 +end + +def fun_l22_n352() + fun_l23_n401 +end + +def fun_l22_n353() + fun_l23_n245 +end + +def fun_l22_n354() + fun_l23_n777 +end + +def fun_l22_n355() + fun_l23_n362 +end + +def fun_l22_n356() + fun_l23_n703 +end + +def fun_l22_n357() + fun_l23_n627 +end + +def fun_l22_n358() + fun_l23_n542 +end + +def fun_l22_n359() + fun_l23_n830 +end + +def fun_l22_n360() + fun_l23_n508 +end + +def fun_l22_n361() + fun_l23_n814 +end + +def fun_l22_n362() + fun_l23_n147 +end + +def fun_l22_n363() + fun_l23_n581 +end + +def fun_l22_n364() + fun_l23_n394 +end + +def fun_l22_n365() + fun_l23_n366 +end + +def fun_l22_n366() + fun_l23_n723 +end + +def fun_l22_n367() + fun_l23_n544 +end + +def fun_l22_n368() + fun_l23_n231 +end + +def fun_l22_n369() + fun_l23_n727 +end + +def fun_l22_n370() + fun_l23_n459 +end + +def fun_l22_n371() + fun_l23_n290 +end + +def fun_l22_n372() + fun_l23_n901 +end + +def fun_l22_n373() + fun_l23_n738 +end + +def fun_l22_n374() + fun_l23_n733 +end + +def fun_l22_n375() + fun_l23_n85 +end + +def fun_l22_n376() + fun_l23_n469 +end + +def fun_l22_n377() + fun_l23_n599 +end + +def fun_l22_n378() + fun_l23_n78 +end + +def fun_l22_n379() + fun_l23_n499 +end + +def fun_l22_n380() + fun_l23_n527 +end + +def fun_l22_n381() + fun_l23_n185 +end + +def fun_l22_n382() + fun_l23_n93 +end + +def fun_l22_n383() + fun_l23_n233 +end + +def fun_l22_n384() + fun_l23_n292 +end + +def fun_l22_n385() + fun_l23_n716 +end + +def fun_l22_n386() + fun_l23_n81 +end + +def fun_l22_n387() + fun_l23_n740 +end + +def fun_l22_n388() + fun_l23_n351 +end + +def fun_l22_n389() + fun_l23_n488 +end + +def fun_l22_n390() + fun_l23_n631 +end + +def fun_l22_n391() + fun_l23_n477 +end + +def fun_l22_n392() + fun_l23_n541 +end + +def fun_l22_n393() + fun_l23_n816 +end + +def fun_l22_n394() + fun_l23_n737 +end + +def fun_l22_n395() + fun_l23_n839 +end + +def fun_l22_n396() + fun_l23_n249 +end + +def fun_l22_n397() + fun_l23_n472 +end + +def fun_l22_n398() + fun_l23_n150 +end + +def fun_l22_n399() + fun_l23_n13 +end + +def fun_l22_n400() + fun_l23_n476 +end + +def fun_l22_n401() + fun_l23_n373 +end + +def fun_l22_n402() + fun_l23_n879 +end + +def fun_l22_n403() + fun_l23_n140 +end + +def fun_l22_n404() + fun_l23_n662 +end + +def fun_l22_n405() + fun_l23_n935 +end + +def fun_l22_n406() + fun_l23_n113 +end + +def fun_l22_n407() + fun_l23_n731 +end + +def fun_l22_n408() + fun_l23_n488 +end + +def fun_l22_n409() + fun_l23_n35 +end + +def fun_l22_n410() + fun_l23_n872 +end + +def fun_l22_n411() + fun_l23_n651 +end + +def fun_l22_n412() + fun_l23_n53 +end + +def fun_l22_n413() + fun_l23_n329 +end + +def fun_l22_n414() + fun_l23_n215 +end + +def fun_l22_n415() + fun_l23_n125 +end + +def fun_l22_n416() + fun_l23_n722 +end + +def fun_l22_n417() + fun_l23_n102 +end + +def fun_l22_n418() + fun_l23_n648 +end + +def fun_l22_n419() + fun_l23_n122 +end + +def fun_l22_n420() + fun_l23_n998 +end + +def fun_l22_n421() + fun_l23_n730 +end + +def fun_l22_n422() + fun_l23_n148 +end + +def fun_l22_n423() + fun_l23_n773 +end + +def fun_l22_n424() + fun_l23_n737 +end + +def fun_l22_n425() + fun_l23_n383 +end + +def fun_l22_n426() + fun_l23_n423 +end + +def fun_l22_n427() + fun_l23_n655 +end + +def fun_l22_n428() + fun_l23_n573 +end + +def fun_l22_n429() + fun_l23_n717 +end + +def fun_l22_n430() + fun_l23_n617 +end + +def fun_l22_n431() + fun_l23_n575 +end + +def fun_l22_n432() + fun_l23_n62 +end + +def fun_l22_n433() + fun_l23_n31 +end + +def fun_l22_n434() + fun_l23_n812 +end + +def fun_l22_n435() + fun_l23_n332 +end + +def fun_l22_n436() + fun_l23_n380 +end + +def fun_l22_n437() + fun_l23_n5 +end + +def fun_l22_n438() + fun_l23_n668 +end + +def fun_l22_n439() + fun_l23_n439 +end + +def fun_l22_n440() + fun_l23_n878 +end + +def fun_l22_n441() + fun_l23_n974 +end + +def fun_l22_n442() + fun_l23_n919 +end + +def fun_l22_n443() + fun_l23_n597 +end + +def fun_l22_n444() + fun_l23_n894 +end + +def fun_l22_n445() + fun_l23_n791 +end + +def fun_l22_n446() + fun_l23_n999 +end + +def fun_l22_n447() + fun_l23_n427 +end + +def fun_l22_n448() + fun_l23_n109 +end + +def fun_l22_n449() + fun_l23_n151 +end + +def fun_l22_n450() + fun_l23_n870 +end + +def fun_l22_n451() + fun_l23_n624 +end + +def fun_l22_n452() + fun_l23_n336 +end + +def fun_l22_n453() + fun_l23_n891 +end + +def fun_l22_n454() + fun_l23_n433 +end + +def fun_l22_n455() + fun_l23_n392 +end + +def fun_l22_n456() + fun_l23_n593 +end + +def fun_l22_n457() + fun_l23_n852 +end + +def fun_l22_n458() + fun_l23_n675 +end + +def fun_l22_n459() + fun_l23_n589 +end + +def fun_l22_n460() + fun_l23_n348 +end + +def fun_l22_n461() + fun_l23_n137 +end + +def fun_l22_n462() + fun_l23_n551 +end + +def fun_l22_n463() + fun_l23_n236 +end + +def fun_l22_n464() + fun_l23_n266 +end + +def fun_l22_n465() + fun_l23_n622 +end + +def fun_l22_n466() + fun_l23_n174 +end + +def fun_l22_n467() + fun_l23_n79 +end + +def fun_l22_n468() + fun_l23_n189 +end + +def fun_l22_n469() + fun_l23_n746 +end + +def fun_l22_n470() + fun_l23_n917 +end + +def fun_l22_n471() + fun_l23_n344 +end + +def fun_l22_n472() + fun_l23_n410 +end + +def fun_l22_n473() + fun_l23_n844 +end + +def fun_l22_n474() + fun_l23_n998 +end + +def fun_l22_n475() + fun_l23_n969 +end + +def fun_l22_n476() + fun_l23_n853 +end + +def fun_l22_n477() + fun_l23_n691 +end + +def fun_l22_n478() + fun_l23_n147 +end + +def fun_l22_n479() + fun_l23_n983 +end + +def fun_l22_n480() + fun_l23_n384 +end + +def fun_l22_n481() + fun_l23_n624 +end + +def fun_l22_n482() + fun_l23_n852 +end + +def fun_l22_n483() + fun_l23_n403 +end + +def fun_l22_n484() + fun_l23_n878 +end + +def fun_l22_n485() + fun_l23_n998 +end + +def fun_l22_n486() + fun_l23_n435 +end + +def fun_l22_n487() + fun_l23_n637 +end + +def fun_l22_n488() + fun_l23_n283 +end + +def fun_l22_n489() + fun_l23_n444 +end + +def fun_l22_n490() + fun_l23_n121 +end + +def fun_l22_n491() + fun_l23_n478 +end + +def fun_l22_n492() + fun_l23_n856 +end + +def fun_l22_n493() + fun_l23_n209 +end + +def fun_l22_n494() + fun_l23_n752 +end + +def fun_l22_n495() + fun_l23_n146 +end + +def fun_l22_n496() + fun_l23_n986 +end + +def fun_l22_n497() + fun_l23_n912 +end + +def fun_l22_n498() + fun_l23_n302 +end + +def fun_l22_n499() + fun_l23_n813 +end + +def fun_l22_n500() + fun_l23_n140 +end + +def fun_l22_n501() + fun_l23_n968 +end + +def fun_l22_n502() + fun_l23_n125 +end + +def fun_l22_n503() + fun_l23_n595 +end + +def fun_l22_n504() + fun_l23_n95 +end + +def fun_l22_n505() + fun_l23_n571 +end + +def fun_l22_n506() + fun_l23_n639 +end + +def fun_l22_n507() + fun_l23_n481 +end + +def fun_l22_n508() + fun_l23_n538 +end + +def fun_l22_n509() + fun_l23_n469 +end + +def fun_l22_n510() + fun_l23_n563 +end + +def fun_l22_n511() + fun_l23_n839 +end + +def fun_l22_n512() + fun_l23_n764 +end + +def fun_l22_n513() + fun_l23_n960 +end + +def fun_l22_n514() + fun_l23_n125 +end + +def fun_l22_n515() + fun_l23_n776 +end + +def fun_l22_n516() + fun_l23_n78 +end + +def fun_l22_n517() + fun_l23_n681 +end + +def fun_l22_n518() + fun_l23_n959 +end + +def fun_l22_n519() + fun_l23_n565 +end + +def fun_l22_n520() + fun_l23_n889 +end + +def fun_l22_n521() + fun_l23_n377 +end + +def fun_l22_n522() + fun_l23_n744 +end + +def fun_l22_n523() + fun_l23_n848 +end + +def fun_l22_n524() + fun_l23_n223 +end + +def fun_l22_n525() + fun_l23_n81 +end + +def fun_l22_n526() + fun_l23_n764 +end + +def fun_l22_n527() + fun_l23_n667 +end + +def fun_l22_n528() + fun_l23_n657 +end + +def fun_l22_n529() + fun_l23_n343 +end + +def fun_l22_n530() + fun_l23_n526 +end + +def fun_l22_n531() + fun_l23_n570 +end + +def fun_l22_n532() + fun_l23_n3 +end + +def fun_l22_n533() + fun_l23_n501 +end + +def fun_l22_n534() + fun_l23_n571 +end + +def fun_l22_n535() + fun_l23_n245 +end + +def fun_l22_n536() + fun_l23_n834 +end + +def fun_l22_n537() + fun_l23_n454 +end + +def fun_l22_n538() + fun_l23_n163 +end + +def fun_l22_n539() + fun_l23_n598 +end + +def fun_l22_n540() + fun_l23_n277 +end + +def fun_l22_n541() + fun_l23_n482 +end + +def fun_l22_n542() + fun_l23_n202 +end + +def fun_l22_n543() + fun_l23_n525 +end + +def fun_l22_n544() + fun_l23_n971 +end + +def fun_l22_n545() + fun_l23_n258 +end + +def fun_l22_n546() + fun_l23_n220 +end + +def fun_l22_n547() + fun_l23_n762 +end + +def fun_l22_n548() + fun_l23_n431 +end + +def fun_l22_n549() + fun_l23_n171 +end + +def fun_l22_n550() + fun_l23_n633 +end + +def fun_l22_n551() + fun_l23_n275 +end + +def fun_l22_n552() + fun_l23_n665 +end + +def fun_l22_n553() + fun_l23_n266 +end + +def fun_l22_n554() + fun_l23_n440 +end + +def fun_l22_n555() + fun_l23_n463 +end + +def fun_l22_n556() + fun_l23_n2 +end + +def fun_l22_n557() + fun_l23_n536 +end + +def fun_l22_n558() + fun_l23_n323 +end + +def fun_l22_n559() + fun_l23_n838 +end + +def fun_l22_n560() + fun_l23_n431 +end + +def fun_l22_n561() + fun_l23_n920 +end + +def fun_l22_n562() + fun_l23_n250 +end + +def fun_l22_n563() + fun_l23_n871 +end + +def fun_l22_n564() + fun_l23_n324 +end + +def fun_l22_n565() + fun_l23_n454 +end + +def fun_l22_n566() + fun_l23_n308 +end + +def fun_l22_n567() + fun_l23_n629 +end + +def fun_l22_n568() + fun_l23_n791 +end + +def fun_l22_n569() + fun_l23_n55 +end + +def fun_l22_n570() + fun_l23_n791 +end + +def fun_l22_n571() + fun_l23_n674 +end + +def fun_l22_n572() + fun_l23_n749 +end + +def fun_l22_n573() + fun_l23_n106 +end + +def fun_l22_n574() + fun_l23_n931 +end + +def fun_l22_n575() + fun_l23_n165 +end + +def fun_l22_n576() + fun_l23_n649 +end + +def fun_l22_n577() + fun_l23_n99 +end + +def fun_l22_n578() + fun_l23_n609 +end + +def fun_l22_n579() + fun_l23_n165 +end + +def fun_l22_n580() + fun_l23_n530 +end + +def fun_l22_n581() + fun_l23_n545 +end + +def fun_l22_n582() + fun_l23_n453 +end + +def fun_l22_n583() + fun_l23_n128 +end + +def fun_l22_n584() + fun_l23_n200 +end + +def fun_l22_n585() + fun_l23_n712 +end + +def fun_l22_n586() + fun_l23_n668 +end + +def fun_l22_n587() + fun_l23_n903 +end + +def fun_l22_n588() + fun_l23_n704 +end + +def fun_l22_n589() + fun_l23_n864 +end + +def fun_l22_n590() + fun_l23_n98 +end + +def fun_l22_n591() + fun_l23_n674 +end + +def fun_l22_n592() + fun_l23_n577 +end + +def fun_l22_n593() + fun_l23_n969 +end + +def fun_l22_n594() + fun_l23_n634 +end + +def fun_l22_n595() + fun_l23_n111 +end + +def fun_l22_n596() + fun_l23_n866 +end + +def fun_l22_n597() + fun_l23_n353 +end + +def fun_l22_n598() + fun_l23_n223 +end + +def fun_l22_n599() + fun_l23_n229 +end + +def fun_l22_n600() + fun_l23_n958 +end + +def fun_l22_n601() + fun_l23_n802 +end + +def fun_l22_n602() + fun_l23_n124 +end + +def fun_l22_n603() + fun_l23_n945 +end + +def fun_l22_n604() + fun_l23_n911 +end + +def fun_l22_n605() + fun_l23_n410 +end + +def fun_l22_n606() + fun_l23_n754 +end + +def fun_l22_n607() + fun_l23_n429 +end + +def fun_l22_n608() + fun_l23_n529 +end + +def fun_l22_n609() + fun_l23_n15 +end + +def fun_l22_n610() + fun_l23_n634 +end + +def fun_l22_n611() + fun_l23_n608 +end + +def fun_l22_n612() + fun_l23_n509 +end + +def fun_l22_n613() + fun_l23_n352 +end + +def fun_l22_n614() + fun_l23_n706 +end + +def fun_l22_n615() + fun_l23_n172 +end + +def fun_l22_n616() + fun_l23_n268 +end + +def fun_l22_n617() + fun_l23_n275 +end + +def fun_l22_n618() + fun_l23_n265 +end + +def fun_l22_n619() + fun_l23_n101 +end + +def fun_l22_n620() + fun_l23_n402 +end + +def fun_l22_n621() + fun_l23_n953 +end + +def fun_l22_n622() + fun_l23_n682 +end + +def fun_l22_n623() + fun_l23_n745 +end + +def fun_l22_n624() + fun_l23_n343 +end + +def fun_l22_n625() + fun_l23_n147 +end + +def fun_l22_n626() + fun_l23_n39 +end + +def fun_l22_n627() + fun_l23_n483 +end + +def fun_l22_n628() + fun_l23_n787 +end + +def fun_l22_n629() + fun_l23_n643 +end + +def fun_l22_n630() + fun_l23_n40 +end + +def fun_l22_n631() + fun_l23_n834 +end + +def fun_l22_n632() + fun_l23_n220 +end + +def fun_l22_n633() + fun_l23_n293 +end + +def fun_l22_n634() + fun_l23_n144 +end + +def fun_l22_n635() + fun_l23_n602 +end + +def fun_l22_n636() + fun_l23_n248 +end + +def fun_l22_n637() + fun_l23_n524 +end + +def fun_l22_n638() + fun_l23_n639 +end + +def fun_l22_n639() + fun_l23_n217 +end + +def fun_l22_n640() + fun_l23_n193 +end + +def fun_l22_n641() + fun_l23_n158 +end + +def fun_l22_n642() + fun_l23_n894 +end + +def fun_l22_n643() + fun_l23_n189 +end + +def fun_l22_n644() + fun_l23_n877 +end + +def fun_l22_n645() + fun_l23_n299 +end + +def fun_l22_n646() + fun_l23_n71 +end + +def fun_l22_n647() + fun_l23_n290 +end + +def fun_l22_n648() + fun_l23_n557 +end + +def fun_l22_n649() + fun_l23_n151 +end + +def fun_l22_n650() + fun_l23_n297 +end + +def fun_l22_n651() + fun_l23_n991 +end + +def fun_l22_n652() + fun_l23_n11 +end + +def fun_l22_n653() + fun_l23_n465 +end + +def fun_l22_n654() + fun_l23_n802 +end + +def fun_l22_n655() + fun_l23_n778 +end + +def fun_l22_n656() + fun_l23_n877 +end + +def fun_l22_n657() + fun_l23_n773 +end + +def fun_l22_n658() + fun_l23_n385 +end + +def fun_l22_n659() + fun_l23_n151 +end + +def fun_l22_n660() + fun_l23_n553 +end + +def fun_l22_n661() + fun_l23_n626 +end + +def fun_l22_n662() + fun_l23_n715 +end + +def fun_l22_n663() + fun_l23_n675 +end + +def fun_l22_n664() + fun_l23_n884 +end + +def fun_l22_n665() + fun_l23_n875 +end + +def fun_l22_n666() + fun_l23_n510 +end + +def fun_l22_n667() + fun_l23_n727 +end + +def fun_l22_n668() + fun_l23_n530 +end + +def fun_l22_n669() + fun_l23_n869 +end + +def fun_l22_n670() + fun_l23_n385 +end + +def fun_l22_n671() + fun_l23_n66 +end + +def fun_l22_n672() + fun_l23_n335 +end + +def fun_l22_n673() + fun_l23_n287 +end + +def fun_l22_n674() + fun_l23_n426 +end + +def fun_l22_n675() + fun_l23_n657 +end + +def fun_l22_n676() + fun_l23_n411 +end + +def fun_l22_n677() + fun_l23_n982 +end + +def fun_l22_n678() + fun_l23_n747 +end + +def fun_l22_n679() + fun_l23_n305 +end + +def fun_l22_n680() + fun_l23_n767 +end + +def fun_l22_n681() + fun_l23_n177 +end + +def fun_l22_n682() + fun_l23_n115 +end + +def fun_l22_n683() + fun_l23_n625 +end + +def fun_l22_n684() + fun_l23_n154 +end + +def fun_l22_n685() + fun_l23_n871 +end + +def fun_l22_n686() + fun_l23_n921 +end + +def fun_l22_n687() + fun_l23_n194 +end + +def fun_l22_n688() + fun_l23_n12 +end + +def fun_l22_n689() + fun_l23_n464 +end + +def fun_l22_n690() + fun_l23_n44 +end + +def fun_l22_n691() + fun_l23_n265 +end + +def fun_l22_n692() + fun_l23_n256 +end + +def fun_l22_n693() + fun_l23_n937 +end + +def fun_l22_n694() + fun_l23_n656 +end + +def fun_l22_n695() + fun_l23_n986 +end + +def fun_l22_n696() + fun_l23_n774 +end + +def fun_l22_n697() + fun_l23_n907 +end + +def fun_l22_n698() + fun_l23_n763 +end + +def fun_l22_n699() + fun_l23_n290 +end + +def fun_l22_n700() + fun_l23_n121 +end + +def fun_l22_n701() + fun_l23_n605 +end + +def fun_l22_n702() + fun_l23_n415 +end + +def fun_l22_n703() + fun_l23_n431 +end + +def fun_l22_n704() + fun_l23_n65 +end + +def fun_l22_n705() + fun_l23_n997 +end + +def fun_l22_n706() + fun_l23_n859 +end + +def fun_l22_n707() + fun_l23_n768 +end + +def fun_l22_n708() + fun_l23_n570 +end + +def fun_l22_n709() + fun_l23_n458 +end + +def fun_l22_n710() + fun_l23_n964 +end + +def fun_l22_n711() + fun_l23_n484 +end + +def fun_l22_n712() + fun_l23_n440 +end + +def fun_l22_n713() + fun_l23_n133 +end + +def fun_l22_n714() + fun_l23_n789 +end + +def fun_l22_n715() + fun_l23_n176 +end + +def fun_l22_n716() + fun_l23_n380 +end + +def fun_l22_n717() + fun_l23_n115 +end + +def fun_l22_n718() + fun_l23_n652 +end + +def fun_l22_n719() + fun_l23_n210 +end + +def fun_l22_n720() + fun_l23_n347 +end + +def fun_l22_n721() + fun_l23_n72 +end + +def fun_l22_n722() + fun_l23_n426 +end + +def fun_l22_n723() + fun_l23_n123 +end + +def fun_l22_n724() + fun_l23_n321 +end + +def fun_l22_n725() + fun_l23_n582 +end + +def fun_l22_n726() + fun_l23_n434 +end + +def fun_l22_n727() + fun_l23_n543 +end + +def fun_l22_n728() + fun_l23_n794 +end + +def fun_l22_n729() + fun_l23_n474 +end + +def fun_l22_n730() + fun_l23_n412 +end + +def fun_l22_n731() + fun_l23_n898 +end + +def fun_l22_n732() + fun_l23_n833 +end + +def fun_l22_n733() + fun_l23_n77 +end + +def fun_l22_n734() + fun_l23_n728 +end + +def fun_l22_n735() + fun_l23_n397 +end + +def fun_l22_n736() + fun_l23_n40 +end + +def fun_l22_n737() + fun_l23_n501 +end + +def fun_l22_n738() + fun_l23_n817 +end + +def fun_l22_n739() + fun_l23_n792 +end + +def fun_l22_n740() + fun_l23_n435 +end + +def fun_l22_n741() + fun_l23_n264 +end + +def fun_l22_n742() + fun_l23_n285 +end + +def fun_l22_n743() + fun_l23_n756 +end + +def fun_l22_n744() + fun_l23_n836 +end + +def fun_l22_n745() + fun_l23_n179 +end + +def fun_l22_n746() + fun_l23_n375 +end + +def fun_l22_n747() + fun_l23_n631 +end + +def fun_l22_n748() + fun_l23_n232 +end + +def fun_l22_n749() + fun_l23_n215 +end + +def fun_l22_n750() + fun_l23_n118 +end + +def fun_l22_n751() + fun_l23_n721 +end + +def fun_l22_n752() + fun_l23_n378 +end + +def fun_l22_n753() + fun_l23_n613 +end + +def fun_l22_n754() + fun_l23_n368 +end + +def fun_l22_n755() + fun_l23_n748 +end + +def fun_l22_n756() + fun_l23_n0 +end + +def fun_l22_n757() + fun_l23_n90 +end + +def fun_l22_n758() + fun_l23_n895 +end + +def fun_l22_n759() + fun_l23_n0 +end + +def fun_l22_n760() + fun_l23_n486 +end + +def fun_l22_n761() + fun_l23_n568 +end + +def fun_l22_n762() + fun_l23_n525 +end + +def fun_l22_n763() + fun_l23_n106 +end + +def fun_l22_n764() + fun_l23_n607 +end + +def fun_l22_n765() + fun_l23_n729 +end + +def fun_l22_n766() + fun_l23_n781 +end + +def fun_l22_n767() + fun_l23_n79 +end + +def fun_l22_n768() + fun_l23_n313 +end + +def fun_l22_n769() + fun_l23_n764 +end + +def fun_l22_n770() + fun_l23_n348 +end + +def fun_l22_n771() + fun_l23_n809 +end + +def fun_l22_n772() + fun_l23_n891 +end + +def fun_l22_n773() + fun_l23_n806 +end + +def fun_l22_n774() + fun_l23_n173 +end + +def fun_l22_n775() + fun_l23_n960 +end + +def fun_l22_n776() + fun_l23_n186 +end + +def fun_l22_n777() + fun_l23_n863 +end + +def fun_l22_n778() + fun_l23_n860 +end + +def fun_l22_n779() + fun_l23_n122 +end + +def fun_l22_n780() + fun_l23_n114 +end + +def fun_l22_n781() + fun_l23_n910 +end + +def fun_l22_n782() + fun_l23_n20 +end + +def fun_l22_n783() + fun_l23_n384 +end + +def fun_l22_n784() + fun_l23_n56 +end + +def fun_l22_n785() + fun_l23_n833 +end + +def fun_l22_n786() + fun_l23_n31 +end + +def fun_l22_n787() + fun_l23_n679 +end + +def fun_l22_n788() + fun_l23_n8 +end + +def fun_l22_n789() + fun_l23_n425 +end + +def fun_l22_n790() + fun_l23_n615 +end + +def fun_l22_n791() + fun_l23_n220 +end + +def fun_l22_n792() + fun_l23_n977 +end + +def fun_l22_n793() + fun_l23_n913 +end + +def fun_l22_n794() + fun_l23_n714 +end + +def fun_l22_n795() + fun_l23_n885 +end + +def fun_l22_n796() + fun_l23_n289 +end + +def fun_l22_n797() + fun_l23_n205 +end + +def fun_l22_n798() + fun_l23_n826 +end + +def fun_l22_n799() + fun_l23_n335 +end + +def fun_l22_n800() + fun_l23_n754 +end + +def fun_l22_n801() + fun_l23_n588 +end + +def fun_l22_n802() + fun_l23_n689 +end + +def fun_l22_n803() + fun_l23_n731 +end + +def fun_l22_n804() + fun_l23_n962 +end + +def fun_l22_n805() + fun_l23_n283 +end + +def fun_l22_n806() + fun_l23_n692 +end + +def fun_l22_n807() + fun_l23_n554 +end + +def fun_l22_n808() + fun_l23_n365 +end + +def fun_l22_n809() + fun_l23_n684 +end + +def fun_l22_n810() + fun_l23_n848 +end + +def fun_l22_n811() + fun_l23_n283 +end + +def fun_l22_n812() + fun_l23_n378 +end + +def fun_l22_n813() + fun_l23_n83 +end + +def fun_l22_n814() + fun_l23_n260 +end + +def fun_l22_n815() + fun_l23_n382 +end + +def fun_l22_n816() + fun_l23_n701 +end + +def fun_l22_n817() + fun_l23_n177 +end + +def fun_l22_n818() + fun_l23_n703 +end + +def fun_l22_n819() + fun_l23_n105 +end + +def fun_l22_n820() + fun_l23_n874 +end + +def fun_l22_n821() + fun_l23_n952 +end + +def fun_l22_n822() + fun_l23_n37 +end + +def fun_l22_n823() + fun_l23_n478 +end + +def fun_l22_n824() + fun_l23_n164 +end + +def fun_l22_n825() + fun_l23_n505 +end + +def fun_l22_n826() + fun_l23_n353 +end + +def fun_l22_n827() + fun_l23_n799 +end + +def fun_l22_n828() + fun_l23_n330 +end + +def fun_l22_n829() + fun_l23_n979 +end + +def fun_l22_n830() + fun_l23_n842 +end + +def fun_l22_n831() + fun_l23_n912 +end + +def fun_l22_n832() + fun_l23_n579 +end + +def fun_l22_n833() + fun_l23_n123 +end + +def fun_l22_n834() + fun_l23_n864 +end + +def fun_l22_n835() + fun_l23_n369 +end + +def fun_l22_n836() + fun_l23_n145 +end + +def fun_l22_n837() + fun_l23_n414 +end + +def fun_l22_n838() + fun_l23_n261 +end + +def fun_l22_n839() + fun_l23_n88 +end + +def fun_l22_n840() + fun_l23_n427 +end + +def fun_l22_n841() + fun_l23_n847 +end + +def fun_l22_n842() + fun_l23_n734 +end + +def fun_l22_n843() + fun_l23_n895 +end + +def fun_l22_n844() + fun_l23_n765 +end + +def fun_l22_n845() + fun_l23_n647 +end + +def fun_l22_n846() + fun_l23_n862 +end + +def fun_l22_n847() + fun_l23_n360 +end + +def fun_l22_n848() + fun_l23_n922 +end + +def fun_l22_n849() + fun_l23_n914 +end + +def fun_l22_n850() + fun_l23_n408 +end + +def fun_l22_n851() + fun_l23_n248 +end + +def fun_l22_n852() + fun_l23_n812 +end + +def fun_l22_n853() + fun_l23_n288 +end + +def fun_l22_n854() + fun_l23_n885 +end + +def fun_l22_n855() + fun_l23_n164 +end + +def fun_l22_n856() + fun_l23_n231 +end + +def fun_l22_n857() + fun_l23_n428 +end + +def fun_l22_n858() + fun_l23_n527 +end + +def fun_l22_n859() + fun_l23_n419 +end + +def fun_l22_n860() + fun_l23_n348 +end + +def fun_l22_n861() + fun_l23_n580 +end + +def fun_l22_n862() + fun_l23_n437 +end + +def fun_l22_n863() + fun_l23_n486 +end + +def fun_l22_n864() + fun_l23_n2 +end + +def fun_l22_n865() + fun_l23_n733 +end + +def fun_l22_n866() + fun_l23_n50 +end + +def fun_l22_n867() + fun_l23_n391 +end + +def fun_l22_n868() + fun_l23_n451 +end + +def fun_l22_n869() + fun_l23_n86 +end + +def fun_l22_n870() + fun_l23_n426 +end + +def fun_l22_n871() + fun_l23_n279 +end + +def fun_l22_n872() + fun_l23_n41 +end + +def fun_l22_n873() + fun_l23_n241 +end + +def fun_l22_n874() + fun_l23_n601 +end + +def fun_l22_n875() + fun_l23_n187 +end + +def fun_l22_n876() + fun_l23_n98 +end + +def fun_l22_n877() + fun_l23_n145 +end + +def fun_l22_n878() + fun_l23_n327 +end + +def fun_l22_n879() + fun_l23_n928 +end + +def fun_l22_n880() + fun_l23_n666 +end + +def fun_l22_n881() + fun_l23_n152 +end + +def fun_l22_n882() + fun_l23_n930 +end + +def fun_l22_n883() + fun_l23_n842 +end + +def fun_l22_n884() + fun_l23_n865 +end + +def fun_l22_n885() + fun_l23_n16 +end + +def fun_l22_n886() + fun_l23_n402 +end + +def fun_l22_n887() + fun_l23_n711 +end + +def fun_l22_n888() + fun_l23_n206 +end + +def fun_l22_n889() + fun_l23_n991 +end + +def fun_l22_n890() + fun_l23_n852 +end + +def fun_l22_n891() + fun_l23_n602 +end + +def fun_l22_n892() + fun_l23_n998 +end + +def fun_l22_n893() + fun_l23_n740 +end + +def fun_l22_n894() + fun_l23_n643 +end + +def fun_l22_n895() + fun_l23_n872 +end + +def fun_l22_n896() + fun_l23_n689 +end + +def fun_l22_n897() + fun_l23_n119 +end + +def fun_l22_n898() + fun_l23_n230 +end + +def fun_l22_n899() + fun_l23_n345 +end + +def fun_l22_n900() + fun_l23_n805 +end + +def fun_l22_n901() + fun_l23_n850 +end + +def fun_l22_n902() + fun_l23_n930 +end + +def fun_l22_n903() + fun_l23_n652 +end + +def fun_l22_n904() + fun_l23_n772 +end + +def fun_l22_n905() + fun_l23_n219 +end + +def fun_l22_n906() + fun_l23_n592 +end + +def fun_l22_n907() + fun_l23_n177 +end + +def fun_l22_n908() + fun_l23_n552 +end + +def fun_l22_n909() + fun_l23_n334 +end + +def fun_l22_n910() + fun_l23_n764 +end + +def fun_l22_n911() + fun_l23_n482 +end + +def fun_l22_n912() + fun_l23_n73 +end + +def fun_l22_n913() + fun_l23_n854 +end + +def fun_l22_n914() + fun_l23_n215 +end + +def fun_l22_n915() + fun_l23_n736 +end + +def fun_l22_n916() + fun_l23_n91 +end + +def fun_l22_n917() + fun_l23_n506 +end + +def fun_l22_n918() + fun_l23_n775 +end + +def fun_l22_n919() + fun_l23_n171 +end + +def fun_l22_n920() + fun_l23_n414 +end + +def fun_l22_n921() + fun_l23_n185 +end + +def fun_l22_n922() + fun_l23_n190 +end + +def fun_l22_n923() + fun_l23_n696 +end + +def fun_l22_n924() + fun_l23_n175 +end + +def fun_l22_n925() + fun_l23_n29 +end + +def fun_l22_n926() + fun_l23_n729 +end + +def fun_l22_n927() + fun_l23_n279 +end + +def fun_l22_n928() + fun_l23_n2 +end + +def fun_l22_n929() + fun_l23_n44 +end + +def fun_l22_n930() + fun_l23_n399 +end + +def fun_l22_n931() + fun_l23_n957 +end + +def fun_l22_n932() + fun_l23_n513 +end + +def fun_l22_n933() + fun_l23_n607 +end + +def fun_l22_n934() + fun_l23_n488 +end + +def fun_l22_n935() + fun_l23_n308 +end + +def fun_l22_n936() + fun_l23_n959 +end + +def fun_l22_n937() + fun_l23_n373 +end + +def fun_l22_n938() + fun_l23_n759 +end + +def fun_l22_n939() + fun_l23_n985 +end + +def fun_l22_n940() + fun_l23_n971 +end + +def fun_l22_n941() + fun_l23_n493 +end + +def fun_l22_n942() + fun_l23_n884 +end + +def fun_l22_n943() + fun_l23_n636 +end + +def fun_l22_n944() + fun_l23_n423 +end + +def fun_l22_n945() + fun_l23_n406 +end + +def fun_l22_n946() + fun_l23_n92 +end + +def fun_l22_n947() + fun_l23_n11 +end + +def fun_l22_n948() + fun_l23_n112 +end + +def fun_l22_n949() + fun_l23_n489 +end + +def fun_l22_n950() + fun_l23_n829 +end + +def fun_l22_n951() + fun_l23_n438 +end + +def fun_l22_n952() + fun_l23_n622 +end + +def fun_l22_n953() + fun_l23_n133 +end + +def fun_l22_n954() + fun_l23_n734 +end + +def fun_l22_n955() + fun_l23_n745 +end + +def fun_l22_n956() + fun_l23_n743 +end + +def fun_l22_n957() + fun_l23_n299 +end + +def fun_l22_n958() + fun_l23_n952 +end + +def fun_l22_n959() + fun_l23_n841 +end + +def fun_l22_n960() + fun_l23_n317 +end + +def fun_l22_n961() + fun_l23_n506 +end + +def fun_l22_n962() + fun_l23_n823 +end + +def fun_l22_n963() + fun_l23_n330 +end + +def fun_l22_n964() + fun_l23_n899 +end + +def fun_l22_n965() + fun_l23_n994 +end + +def fun_l22_n966() + fun_l23_n625 +end + +def fun_l22_n967() + fun_l23_n74 +end + +def fun_l22_n968() + fun_l23_n911 +end + +def fun_l22_n969() + fun_l23_n215 +end + +def fun_l22_n970() + fun_l23_n845 +end + +def fun_l22_n971() + fun_l23_n813 +end + +def fun_l22_n972() + fun_l23_n784 +end + +def fun_l22_n973() + fun_l23_n727 +end + +def fun_l22_n974() + fun_l23_n62 +end + +def fun_l22_n975() + fun_l23_n790 +end + +def fun_l22_n976() + fun_l23_n918 +end + +def fun_l22_n977() + fun_l23_n658 +end + +def fun_l22_n978() + fun_l23_n621 +end + +def fun_l22_n979() + fun_l23_n731 +end + +def fun_l22_n980() + fun_l23_n728 +end + +def fun_l22_n981() + fun_l23_n558 +end + +def fun_l22_n982() + fun_l23_n501 +end + +def fun_l22_n983() + fun_l23_n794 +end + +def fun_l22_n984() + fun_l23_n162 +end + +def fun_l22_n985() + fun_l23_n700 +end + +def fun_l22_n986() + fun_l23_n875 +end + +def fun_l22_n987() + fun_l23_n58 +end + +def fun_l22_n988() + fun_l23_n55 +end + +def fun_l22_n989() + fun_l23_n491 +end + +def fun_l22_n990() + fun_l23_n613 +end + +def fun_l22_n991() + fun_l23_n587 +end + +def fun_l22_n992() + fun_l23_n311 +end + +def fun_l22_n993() + fun_l23_n305 +end + +def fun_l22_n994() + fun_l23_n348 +end + +def fun_l22_n995() + fun_l23_n679 +end + +def fun_l22_n996() + fun_l23_n245 +end + +def fun_l22_n997() + fun_l23_n419 +end + +def fun_l22_n998() + fun_l23_n456 +end + +def fun_l22_n999() + fun_l23_n146 +end + +def fun_l23_n0() + fun_l24_n409 +end + +def fun_l23_n1() + fun_l24_n825 +end + +def fun_l23_n2() + fun_l24_n349 +end + +def fun_l23_n3() + fun_l24_n560 +end + +def fun_l23_n4() + fun_l24_n949 +end + +def fun_l23_n5() + fun_l24_n108 +end + +def fun_l23_n6() + fun_l24_n149 +end + +def fun_l23_n7() + fun_l24_n224 +end + +def fun_l23_n8() + fun_l24_n418 +end + +def fun_l23_n9() + fun_l24_n819 +end + +def fun_l23_n10() + fun_l24_n269 +end + +def fun_l23_n11() + fun_l24_n158 +end + +def fun_l23_n12() + fun_l24_n487 +end + +def fun_l23_n13() + fun_l24_n561 +end + +def fun_l23_n14() + fun_l24_n292 +end + +def fun_l23_n15() + fun_l24_n996 +end + +def fun_l23_n16() + fun_l24_n399 +end + +def fun_l23_n17() + fun_l24_n585 +end + +def fun_l23_n18() + fun_l24_n691 +end + +def fun_l23_n19() + fun_l24_n884 +end + +def fun_l23_n20() + fun_l24_n933 +end + +def fun_l23_n21() + fun_l24_n139 +end + +def fun_l23_n22() + fun_l24_n770 +end + +def fun_l23_n23() + fun_l24_n894 +end + +def fun_l23_n24() + fun_l24_n418 +end + +def fun_l23_n25() + fun_l24_n695 +end + +def fun_l23_n26() + fun_l24_n800 +end + +def fun_l23_n27() + fun_l24_n580 +end + +def fun_l23_n28() + fun_l24_n1 +end + +def fun_l23_n29() + fun_l24_n121 +end + +def fun_l23_n30() + fun_l24_n757 +end + +def fun_l23_n31() + fun_l24_n461 +end + +def fun_l23_n32() + fun_l24_n534 +end + +def fun_l23_n33() + fun_l24_n795 +end + +def fun_l23_n34() + fun_l24_n286 +end + +def fun_l23_n35() + fun_l24_n200 +end + +def fun_l23_n36() + fun_l24_n513 +end + +def fun_l23_n37() + fun_l24_n340 +end + +def fun_l23_n38() + fun_l24_n385 +end + +def fun_l23_n39() + fun_l24_n432 +end + +def fun_l23_n40() + fun_l24_n990 +end + +def fun_l23_n41() + fun_l24_n966 +end + +def fun_l23_n42() + fun_l24_n237 +end + +def fun_l23_n43() + fun_l24_n249 +end + +def fun_l23_n44() + fun_l24_n182 +end + +def fun_l23_n45() + fun_l24_n718 +end + +def fun_l23_n46() + fun_l24_n902 +end + +def fun_l23_n47() + fun_l24_n963 +end + +def fun_l23_n48() + fun_l24_n337 +end + +def fun_l23_n49() + fun_l24_n615 +end + +def fun_l23_n50() + fun_l24_n729 +end + +def fun_l23_n51() + fun_l24_n240 +end + +def fun_l23_n52() + fun_l24_n309 +end + +def fun_l23_n53() + fun_l24_n697 +end + +def fun_l23_n54() + fun_l24_n260 +end + +def fun_l23_n55() + fun_l24_n11 +end + +def fun_l23_n56() + fun_l24_n630 +end + +def fun_l23_n57() + fun_l24_n983 +end + +def fun_l23_n58() + fun_l24_n678 +end + +def fun_l23_n59() + fun_l24_n95 +end + +def fun_l23_n60() + fun_l24_n63 +end + +def fun_l23_n61() + fun_l24_n43 +end + +def fun_l23_n62() + fun_l24_n679 +end + +def fun_l23_n63() + fun_l24_n671 +end + +def fun_l23_n64() + fun_l24_n377 +end + +def fun_l23_n65() + fun_l24_n939 +end + +def fun_l23_n66() + fun_l24_n3 +end + +def fun_l23_n67() + fun_l24_n230 +end + +def fun_l23_n68() + fun_l24_n622 +end + +def fun_l23_n69() + fun_l24_n339 +end + +def fun_l23_n70() + fun_l24_n736 +end + +def fun_l23_n71() + fun_l24_n116 +end + +def fun_l23_n72() + fun_l24_n373 +end + +def fun_l23_n73() + fun_l24_n891 +end + +def fun_l23_n74() + fun_l24_n954 +end + +def fun_l23_n75() + fun_l24_n967 +end + +def fun_l23_n76() + fun_l24_n205 +end + +def fun_l23_n77() + fun_l24_n802 +end + +def fun_l23_n78() + fun_l24_n480 +end + +def fun_l23_n79() + fun_l24_n935 +end + +def fun_l23_n80() + fun_l24_n84 +end + +def fun_l23_n81() + fun_l24_n40 +end + +def fun_l23_n82() + fun_l24_n559 +end + +def fun_l23_n83() + fun_l24_n16 +end + +def fun_l23_n84() + fun_l24_n494 +end + +def fun_l23_n85() + fun_l24_n580 +end + +def fun_l23_n86() + fun_l24_n72 +end + +def fun_l23_n87() + fun_l24_n33 +end + +def fun_l23_n88() + fun_l24_n742 +end + +def fun_l23_n89() + fun_l24_n10 +end + +def fun_l23_n90() + fun_l24_n33 +end + +def fun_l23_n91() + fun_l24_n306 +end + +def fun_l23_n92() + fun_l24_n960 +end + +def fun_l23_n93() + fun_l24_n573 +end + +def fun_l23_n94() + fun_l24_n145 +end + +def fun_l23_n95() + fun_l24_n730 +end + +def fun_l23_n96() + fun_l24_n703 +end + +def fun_l23_n97() + fun_l24_n772 +end + +def fun_l23_n98() + fun_l24_n664 +end + +def fun_l23_n99() + fun_l24_n582 +end + +def fun_l23_n100() + fun_l24_n144 +end + +def fun_l23_n101() + fun_l24_n950 +end + +def fun_l23_n102() + fun_l24_n449 +end + +def fun_l23_n103() + fun_l24_n416 +end + +def fun_l23_n104() + fun_l24_n453 +end + +def fun_l23_n105() + fun_l24_n159 +end + +def fun_l23_n106() + fun_l24_n483 +end + +def fun_l23_n107() + fun_l24_n69 +end + +def fun_l23_n108() + fun_l24_n142 +end + +def fun_l23_n109() + fun_l24_n968 +end + +def fun_l23_n110() + fun_l24_n760 +end + +def fun_l23_n111() + fun_l24_n600 +end + +def fun_l23_n112() + fun_l24_n821 +end + +def fun_l23_n113() + fun_l24_n527 +end + +def fun_l23_n114() + fun_l24_n661 +end + +def fun_l23_n115() + fun_l24_n15 +end + +def fun_l23_n116() + fun_l24_n807 +end + +def fun_l23_n117() + fun_l24_n143 +end + +def fun_l23_n118() + fun_l24_n962 +end + +def fun_l23_n119() + fun_l24_n83 +end + +def fun_l23_n120() + fun_l24_n755 +end + +def fun_l23_n121() + fun_l24_n645 +end + +def fun_l23_n122() + fun_l24_n479 +end + +def fun_l23_n123() + fun_l24_n639 +end + +def fun_l23_n124() + fun_l24_n528 +end + +def fun_l23_n125() + fun_l24_n782 +end + +def fun_l23_n126() + fun_l24_n200 +end + +def fun_l23_n127() + fun_l24_n60 +end + +def fun_l23_n128() + fun_l24_n396 +end + +def fun_l23_n129() + fun_l24_n600 +end + +def fun_l23_n130() + fun_l24_n397 +end + +def fun_l23_n131() + fun_l24_n921 +end + +def fun_l23_n132() + fun_l24_n979 +end + +def fun_l23_n133() + fun_l24_n849 +end + +def fun_l23_n134() + fun_l24_n302 +end + +def fun_l23_n135() + fun_l24_n77 +end + +def fun_l23_n136() + fun_l24_n249 +end + +def fun_l23_n137() + fun_l24_n912 +end + +def fun_l23_n138() + fun_l24_n661 +end + +def fun_l23_n139() + fun_l24_n500 +end + +def fun_l23_n140() + fun_l24_n590 +end + +def fun_l23_n141() + fun_l24_n942 +end + +def fun_l23_n142() + fun_l24_n299 +end + +def fun_l23_n143() + fun_l24_n272 +end + +def fun_l23_n144() + fun_l24_n747 +end + +def fun_l23_n145() + fun_l24_n88 +end + +def fun_l23_n146() + fun_l24_n524 +end + +def fun_l23_n147() + fun_l24_n931 +end + +def fun_l23_n148() + fun_l24_n712 +end + +def fun_l23_n149() + fun_l24_n661 +end + +def fun_l23_n150() + fun_l24_n426 +end + +def fun_l23_n151() + fun_l24_n693 +end + +def fun_l23_n152() + fun_l24_n585 +end + +def fun_l23_n153() + fun_l24_n451 +end + +def fun_l23_n154() + fun_l24_n333 +end + +def fun_l23_n155() + fun_l24_n792 +end + +def fun_l23_n156() + fun_l24_n840 +end + +def fun_l23_n157() + fun_l24_n643 +end + +def fun_l23_n158() + fun_l24_n120 +end + +def fun_l23_n159() + fun_l24_n86 +end + +def fun_l23_n160() + fun_l24_n352 +end + +def fun_l23_n161() + fun_l24_n761 +end + +def fun_l23_n162() + fun_l24_n412 +end + +def fun_l23_n163() + fun_l24_n156 +end + +def fun_l23_n164() + fun_l24_n909 +end + +def fun_l23_n165() + fun_l24_n394 +end + +def fun_l23_n166() + fun_l24_n973 +end + +def fun_l23_n167() + fun_l24_n31 +end + +def fun_l23_n168() + fun_l24_n545 +end + +def fun_l23_n169() + fun_l24_n180 +end + +def fun_l23_n170() + fun_l24_n446 +end + +def fun_l23_n171() + fun_l24_n965 +end + +def fun_l23_n172() + fun_l24_n102 +end + +def fun_l23_n173() + fun_l24_n161 +end + +def fun_l23_n174() + fun_l24_n571 +end + +def fun_l23_n175() + fun_l24_n451 +end + +def fun_l23_n176() + fun_l24_n947 +end + +def fun_l23_n177() + fun_l24_n906 +end + +def fun_l23_n178() + fun_l24_n356 +end + +def fun_l23_n179() + fun_l24_n84 +end + +def fun_l23_n180() + fun_l24_n798 +end + +def fun_l23_n181() + fun_l24_n500 +end + +def fun_l23_n182() + fun_l24_n419 +end + +def fun_l23_n183() + fun_l24_n797 +end + +def fun_l23_n184() + fun_l24_n459 +end + +def fun_l23_n185() + fun_l24_n795 +end + +def fun_l23_n186() + fun_l24_n478 +end + +def fun_l23_n187() + fun_l24_n742 +end + +def fun_l23_n188() + fun_l24_n262 +end + +def fun_l23_n189() + fun_l24_n37 +end + +def fun_l23_n190() + fun_l24_n340 +end + +def fun_l23_n191() + fun_l24_n314 +end + +def fun_l23_n192() + fun_l24_n595 +end + +def fun_l23_n193() + fun_l24_n769 +end + +def fun_l23_n194() + fun_l24_n637 +end + +def fun_l23_n195() + fun_l24_n377 +end + +def fun_l23_n196() + fun_l24_n77 +end + +def fun_l23_n197() + fun_l24_n486 +end + +def fun_l23_n198() + fun_l24_n992 +end + +def fun_l23_n199() + fun_l24_n546 +end + +def fun_l23_n200() + fun_l24_n386 +end + +def fun_l23_n201() + fun_l24_n301 +end + +def fun_l23_n202() + fun_l24_n867 +end + +def fun_l23_n203() + fun_l24_n948 +end + +def fun_l23_n204() + fun_l24_n163 +end + +def fun_l23_n205() + fun_l24_n618 +end + +def fun_l23_n206() + fun_l24_n560 +end + +def fun_l23_n207() + fun_l24_n147 +end + +def fun_l23_n208() + fun_l24_n474 +end + +def fun_l23_n209() + fun_l24_n99 +end + +def fun_l23_n210() + fun_l24_n994 +end + +def fun_l23_n211() + fun_l24_n594 +end + +def fun_l23_n212() + fun_l24_n101 +end + +def fun_l23_n213() + fun_l24_n510 +end + +def fun_l23_n214() + fun_l24_n965 +end + +def fun_l23_n215() + fun_l24_n460 +end + +def fun_l23_n216() + fun_l24_n455 +end + +def fun_l23_n217() + fun_l24_n783 +end + +def fun_l23_n218() + fun_l24_n466 +end + +def fun_l23_n219() + fun_l24_n60 +end + +def fun_l23_n220() + fun_l24_n486 +end + +def fun_l23_n221() + fun_l24_n819 +end + +def fun_l23_n222() + fun_l24_n909 +end + +def fun_l23_n223() + fun_l24_n446 +end + +def fun_l23_n224() + fun_l24_n80 +end + +def fun_l23_n225() + fun_l24_n276 +end + +def fun_l23_n226() + fun_l24_n638 +end + +def fun_l23_n227() + fun_l24_n200 +end + +def fun_l23_n228() + fun_l24_n665 +end + +def fun_l23_n229() + fun_l24_n814 +end + +def fun_l23_n230() + fun_l24_n214 +end + +def fun_l23_n231() + fun_l24_n719 +end + +def fun_l23_n232() + fun_l24_n62 +end + +def fun_l23_n233() + fun_l24_n523 +end + +def fun_l23_n234() + fun_l24_n470 +end + +def fun_l23_n235() + fun_l24_n338 +end + +def fun_l23_n236() + fun_l24_n929 +end + +def fun_l23_n237() + fun_l24_n982 +end + +def fun_l23_n238() + fun_l24_n391 +end + +def fun_l23_n239() + fun_l24_n631 +end + +def fun_l23_n240() + fun_l24_n473 +end + +def fun_l23_n241() + fun_l24_n25 +end + +def fun_l23_n242() + fun_l24_n720 +end + +def fun_l23_n243() + fun_l24_n139 +end + +def fun_l23_n244() + fun_l24_n859 +end + +def fun_l23_n245() + fun_l24_n154 +end + +def fun_l23_n246() + fun_l24_n272 +end + +def fun_l23_n247() + fun_l24_n248 +end + +def fun_l23_n248() + fun_l24_n719 +end + +def fun_l23_n249() + fun_l24_n436 +end + +def fun_l23_n250() + fun_l24_n935 +end + +def fun_l23_n251() + fun_l24_n513 +end + +def fun_l23_n252() + fun_l24_n0 +end + +def fun_l23_n253() + fun_l24_n104 +end + +def fun_l23_n254() + fun_l24_n551 +end + +def fun_l23_n255() + fun_l24_n317 +end + +def fun_l23_n256() + fun_l24_n225 +end + +def fun_l23_n257() + fun_l24_n685 +end + +def fun_l23_n258() + fun_l24_n647 +end + +def fun_l23_n259() + fun_l24_n489 +end + +def fun_l23_n260() + fun_l24_n252 +end + +def fun_l23_n261() + fun_l24_n333 +end + +def fun_l23_n262() + fun_l24_n179 +end + +def fun_l23_n263() + fun_l24_n68 +end + +def fun_l23_n264() + fun_l24_n119 +end + +def fun_l23_n265() + fun_l24_n840 +end + +def fun_l23_n266() + fun_l24_n683 +end + +def fun_l23_n267() + fun_l24_n897 +end + +def fun_l23_n268() + fun_l24_n323 +end + +def fun_l23_n269() + fun_l24_n667 +end + +def fun_l23_n270() + fun_l24_n538 +end + +def fun_l23_n271() + fun_l24_n597 +end + +def fun_l23_n272() + fun_l24_n582 +end + +def fun_l23_n273() + fun_l24_n19 +end + +def fun_l23_n274() + fun_l24_n331 +end + +def fun_l23_n275() + fun_l24_n528 +end + +def fun_l23_n276() + fun_l24_n766 +end + +def fun_l23_n277() + fun_l24_n742 +end + +def fun_l23_n278() + fun_l24_n318 +end + +def fun_l23_n279() + fun_l24_n143 +end + +def fun_l23_n280() + fun_l24_n910 +end + +def fun_l23_n281() + fun_l24_n953 +end + +def fun_l23_n282() + fun_l24_n655 +end + +def fun_l23_n283() + fun_l24_n804 +end + +def fun_l23_n284() + fun_l24_n539 +end + +def fun_l23_n285() + fun_l24_n697 +end + +def fun_l23_n286() + fun_l24_n258 +end + +def fun_l23_n287() + fun_l24_n194 +end + +def fun_l23_n288() + fun_l24_n420 +end + +def fun_l23_n289() + fun_l24_n253 +end + +def fun_l23_n290() + fun_l24_n858 +end + +def fun_l23_n291() + fun_l24_n831 +end + +def fun_l23_n292() + fun_l24_n798 +end + +def fun_l23_n293() + fun_l24_n662 +end + +def fun_l23_n294() + fun_l24_n900 +end + +def fun_l23_n295() + fun_l24_n408 +end + +def fun_l23_n296() + fun_l24_n151 +end + +def fun_l23_n297() + fun_l24_n660 +end + +def fun_l23_n298() + fun_l24_n233 +end + +def fun_l23_n299() + fun_l24_n412 +end + +def fun_l23_n300() + fun_l24_n347 +end + +def fun_l23_n301() + fun_l24_n360 +end + +def fun_l23_n302() + fun_l24_n150 +end + +def fun_l23_n303() + fun_l24_n995 +end + +def fun_l23_n304() + fun_l24_n623 +end + +def fun_l23_n305() + fun_l24_n404 +end + +def fun_l23_n306() + fun_l24_n898 +end + +def fun_l23_n307() + fun_l24_n736 +end + +def fun_l23_n308() + fun_l24_n301 +end + +def fun_l23_n309() + fun_l24_n929 +end + +def fun_l23_n310() + fun_l24_n795 +end + +def fun_l23_n311() + fun_l24_n434 +end + +def fun_l23_n312() + fun_l24_n796 +end + +def fun_l23_n313() + fun_l24_n71 +end + +def fun_l23_n314() + fun_l24_n294 +end + +def fun_l23_n315() + fun_l24_n540 +end + +def fun_l23_n316() + fun_l24_n137 +end + +def fun_l23_n317() + fun_l24_n523 +end + +def fun_l23_n318() + fun_l24_n472 +end + +def fun_l23_n319() + fun_l24_n141 +end + +def fun_l23_n320() + fun_l24_n552 +end + +def fun_l23_n321() + fun_l24_n587 +end + +def fun_l23_n322() + fun_l24_n308 +end + +def fun_l23_n323() + fun_l24_n929 +end + +def fun_l23_n324() + fun_l24_n944 +end + +def fun_l23_n325() + fun_l24_n472 +end + +def fun_l23_n326() + fun_l24_n450 +end + +def fun_l23_n327() + fun_l24_n376 +end + +def fun_l23_n328() + fun_l24_n70 +end + +def fun_l23_n329() + fun_l24_n486 +end + +def fun_l23_n330() + fun_l24_n391 +end + +def fun_l23_n331() + fun_l24_n133 +end + +def fun_l23_n332() + fun_l24_n31 +end + +def fun_l23_n333() + fun_l24_n462 +end + +def fun_l23_n334() + fun_l24_n521 +end + +def fun_l23_n335() + fun_l24_n706 +end + +def fun_l23_n336() + fun_l24_n511 +end + +def fun_l23_n337() + fun_l24_n932 +end + +def fun_l23_n338() + fun_l24_n133 +end + +def fun_l23_n339() + fun_l24_n296 +end + +def fun_l23_n340() + fun_l24_n591 +end + +def fun_l23_n341() + fun_l24_n581 +end + +def fun_l23_n342() + fun_l24_n41 +end + +def fun_l23_n343() + fun_l24_n256 +end + +def fun_l23_n344() + fun_l24_n772 +end + +def fun_l23_n345() + fun_l24_n642 +end + +def fun_l23_n346() + fun_l24_n110 +end + +def fun_l23_n347() + fun_l24_n987 +end + +def fun_l23_n348() + fun_l24_n33 +end + +def fun_l23_n349() + fun_l24_n913 +end + +def fun_l23_n350() + fun_l24_n581 +end + +def fun_l23_n351() + fun_l24_n594 +end + +def fun_l23_n352() + fun_l24_n484 +end + +def fun_l23_n353() + fun_l24_n969 +end + +def fun_l23_n354() + fun_l24_n966 +end + +def fun_l23_n355() + fun_l24_n122 +end + +def fun_l23_n356() + fun_l24_n907 +end + +def fun_l23_n357() + fun_l24_n980 +end + +def fun_l23_n358() + fun_l24_n557 +end + +def fun_l23_n359() + fun_l24_n216 +end + +def fun_l23_n360() + fun_l24_n936 +end + +def fun_l23_n361() + fun_l24_n476 +end + +def fun_l23_n362() + fun_l24_n154 +end + +def fun_l23_n363() + fun_l24_n785 +end + +def fun_l23_n364() + fun_l24_n967 +end + +def fun_l23_n365() + fun_l24_n697 +end + +def fun_l23_n366() + fun_l24_n610 +end + +def fun_l23_n367() + fun_l24_n415 +end + +def fun_l23_n368() + fun_l24_n432 +end + +def fun_l23_n369() + fun_l24_n505 +end + +def fun_l23_n370() + fun_l24_n581 +end + +def fun_l23_n371() + fun_l24_n350 +end + +def fun_l23_n372() + fun_l24_n202 +end + +def fun_l23_n373() + fun_l24_n757 +end + +def fun_l23_n374() + fun_l24_n336 +end + +def fun_l23_n375() + fun_l24_n323 +end + +def fun_l23_n376() + fun_l24_n670 +end + +def fun_l23_n377() + fun_l24_n535 +end + +def fun_l23_n378() + fun_l24_n901 +end + +def fun_l23_n379() + fun_l24_n218 +end + +def fun_l23_n380() + fun_l24_n733 +end + +def fun_l23_n381() + fun_l24_n820 +end + +def fun_l23_n382() + fun_l24_n229 +end + +def fun_l23_n383() + fun_l24_n49 +end + +def fun_l23_n384() + fun_l24_n469 +end + +def fun_l23_n385() + fun_l24_n904 +end + +def fun_l23_n386() + fun_l24_n652 +end + +def fun_l23_n387() + fun_l24_n863 +end + +def fun_l23_n388() + fun_l24_n356 +end + +def fun_l23_n389() + fun_l24_n558 +end + +def fun_l23_n390() + fun_l24_n263 +end + +def fun_l23_n391() + fun_l24_n593 +end + +def fun_l23_n392() + fun_l24_n882 +end + +def fun_l23_n393() + fun_l24_n128 +end + +def fun_l23_n394() + fun_l24_n855 +end + +def fun_l23_n395() + fun_l24_n269 +end + +def fun_l23_n396() + fun_l24_n858 +end + +def fun_l23_n397() + fun_l24_n34 +end + +def fun_l23_n398() + fun_l24_n447 +end + +def fun_l23_n399() + fun_l24_n323 +end + +def fun_l23_n400() + fun_l24_n624 +end + +def fun_l23_n401() + fun_l24_n397 +end + +def fun_l23_n402() + fun_l24_n755 +end + +def fun_l23_n403() + fun_l24_n477 +end + +def fun_l23_n404() + fun_l24_n396 +end + +def fun_l23_n405() + fun_l24_n177 +end + +def fun_l23_n406() + fun_l24_n964 +end + +def fun_l23_n407() + fun_l24_n640 +end + +def fun_l23_n408() + fun_l24_n82 +end + +def fun_l23_n409() + fun_l24_n224 +end + +def fun_l23_n410() + fun_l24_n750 +end + +def fun_l23_n411() + fun_l24_n301 +end + +def fun_l23_n412() + fun_l24_n32 +end + +def fun_l23_n413() + fun_l24_n839 +end + +def fun_l23_n414() + fun_l24_n724 +end + +def fun_l23_n415() + fun_l24_n663 +end + +def fun_l23_n416() + fun_l24_n682 +end + +def fun_l23_n417() + fun_l24_n409 +end + +def fun_l23_n418() + fun_l24_n769 +end + +def fun_l23_n419() + fun_l24_n538 +end + +def fun_l23_n420() + fun_l24_n558 +end + +def fun_l23_n421() + fun_l24_n524 +end + +def fun_l23_n422() + fun_l24_n464 +end + +def fun_l23_n423() + fun_l24_n889 +end + +def fun_l23_n424() + fun_l24_n656 +end + +def fun_l23_n425() + fun_l24_n805 +end + +def fun_l23_n426() + fun_l24_n428 +end + +def fun_l23_n427() + fun_l24_n793 +end + +def fun_l23_n428() + fun_l24_n192 +end + +def fun_l23_n429() + fun_l24_n443 +end + +def fun_l23_n430() + fun_l24_n481 +end + +def fun_l23_n431() + fun_l24_n203 +end + +def fun_l23_n432() + fun_l24_n607 +end + +def fun_l23_n433() + fun_l24_n871 +end + +def fun_l23_n434() + fun_l24_n436 +end + +def fun_l23_n435() + fun_l24_n376 +end + +def fun_l23_n436() + fun_l24_n936 +end + +def fun_l23_n437() + fun_l24_n153 +end + +def fun_l23_n438() + fun_l24_n994 +end + +def fun_l23_n439() + fun_l24_n777 +end + +def fun_l23_n440() + fun_l24_n341 +end + +def fun_l23_n441() + fun_l24_n50 +end + +def fun_l23_n442() + fun_l24_n1 +end + +def fun_l23_n443() + fun_l24_n320 +end + +def fun_l23_n444() + fun_l24_n116 +end + +def fun_l23_n445() + fun_l24_n202 +end + +def fun_l23_n446() + fun_l24_n433 +end + +def fun_l23_n447() + fun_l24_n151 +end + +def fun_l23_n448() + fun_l24_n581 +end + +def fun_l23_n449() + fun_l24_n498 +end + +def fun_l23_n450() + fun_l24_n575 +end + +def fun_l23_n451() + fun_l24_n161 +end + +def fun_l23_n452() + fun_l24_n78 +end + +def fun_l23_n453() + fun_l24_n863 +end + +def fun_l23_n454() + fun_l24_n269 +end + +def fun_l23_n455() + fun_l24_n956 +end + +def fun_l23_n456() + fun_l24_n485 +end + +def fun_l23_n457() + fun_l24_n106 +end + +def fun_l23_n458() + fun_l24_n641 +end + +def fun_l23_n459() + fun_l24_n434 +end + +def fun_l23_n460() + fun_l24_n308 +end + +def fun_l23_n461() + fun_l24_n192 +end + +def fun_l23_n462() + fun_l24_n401 +end + +def fun_l23_n463() + fun_l24_n62 +end + +def fun_l23_n464() + fun_l24_n38 +end + +def fun_l23_n465() + fun_l24_n732 +end + +def fun_l23_n466() + fun_l24_n143 +end + +def fun_l23_n467() + fun_l24_n799 +end + +def fun_l23_n468() + fun_l24_n486 +end + +def fun_l23_n469() + fun_l24_n161 +end + +def fun_l23_n470() + fun_l24_n838 +end + +def fun_l23_n471() + fun_l24_n526 +end + +def fun_l23_n472() + fun_l24_n421 +end + +def fun_l23_n473() + fun_l24_n967 +end + +def fun_l23_n474() + fun_l24_n822 +end + +def fun_l23_n475() + fun_l24_n939 +end + +def fun_l23_n476() + fun_l24_n36 +end + +def fun_l23_n477() + fun_l24_n539 +end + +def fun_l23_n478() + fun_l24_n759 +end + +def fun_l23_n479() + fun_l24_n979 +end + +def fun_l23_n480() + fun_l24_n685 +end + +def fun_l23_n481() + fun_l24_n548 +end + +def fun_l23_n482() + fun_l24_n348 +end + +def fun_l23_n483() + fun_l24_n922 +end + +def fun_l23_n484() + fun_l24_n185 +end + +def fun_l23_n485() + fun_l24_n138 +end + +def fun_l23_n486() + fun_l24_n678 +end + +def fun_l23_n487() + fun_l24_n44 +end + +def fun_l23_n488() + fun_l24_n820 +end + +def fun_l23_n489() + fun_l24_n447 +end + +def fun_l23_n490() + fun_l24_n455 +end + +def fun_l23_n491() + fun_l24_n145 +end + +def fun_l23_n492() + fun_l24_n441 +end + +def fun_l23_n493() + fun_l24_n354 +end + +def fun_l23_n494() + fun_l24_n324 +end + +def fun_l23_n495() + fun_l24_n231 +end + +def fun_l23_n496() + fun_l24_n775 +end + +def fun_l23_n497() + fun_l24_n815 +end + +def fun_l23_n498() + fun_l24_n491 +end + +def fun_l23_n499() + fun_l24_n437 +end + +def fun_l23_n500() + fun_l24_n112 +end + +def fun_l23_n501() + fun_l24_n174 +end + +def fun_l23_n502() + fun_l24_n683 +end + +def fun_l23_n503() + fun_l24_n243 +end + +def fun_l23_n504() + fun_l24_n236 +end + +def fun_l23_n505() + fun_l24_n106 +end + +def fun_l23_n506() + fun_l24_n781 +end + +def fun_l23_n507() + fun_l24_n427 +end + +def fun_l23_n508() + fun_l24_n410 +end + +def fun_l23_n509() + fun_l24_n903 +end + +def fun_l23_n510() + fun_l24_n40 +end + +def fun_l23_n511() + fun_l24_n559 +end + +def fun_l23_n512() + fun_l24_n152 +end + +def fun_l23_n513() + fun_l24_n175 +end + +def fun_l23_n514() + fun_l24_n305 +end + +def fun_l23_n515() + fun_l24_n814 +end + +def fun_l23_n516() + fun_l24_n676 +end + +def fun_l23_n517() + fun_l24_n448 +end + +def fun_l23_n518() + fun_l24_n573 +end + +def fun_l23_n519() + fun_l24_n66 +end + +def fun_l23_n520() + fun_l24_n893 +end + +def fun_l23_n521() + fun_l24_n460 +end + +def fun_l23_n522() + fun_l24_n238 +end + +def fun_l23_n523() + fun_l24_n200 +end + +def fun_l23_n524() + fun_l24_n61 +end + +def fun_l23_n525() + fun_l24_n365 +end + +def fun_l23_n526() + fun_l24_n360 +end + +def fun_l23_n527() + fun_l24_n17 +end + +def fun_l23_n528() + fun_l24_n594 +end + +def fun_l23_n529() + fun_l24_n494 +end + +def fun_l23_n530() + fun_l24_n188 +end + +def fun_l23_n531() + fun_l24_n288 +end + +def fun_l23_n532() + fun_l24_n348 +end + +def fun_l23_n533() + fun_l24_n254 +end + +def fun_l23_n534() + fun_l24_n457 +end + +def fun_l23_n535() + fun_l24_n742 +end + +def fun_l23_n536() + fun_l24_n28 +end + +def fun_l23_n537() + fun_l24_n856 +end + +def fun_l23_n538() + fun_l24_n345 +end + +def fun_l23_n539() + fun_l24_n455 +end + +def fun_l23_n540() + fun_l24_n39 +end + +def fun_l23_n541() + fun_l24_n667 +end + +def fun_l23_n542() + fun_l24_n555 +end + +def fun_l23_n543() + fun_l24_n983 +end + +def fun_l23_n544() + fun_l24_n71 +end + +def fun_l23_n545() + fun_l24_n733 +end + +def fun_l23_n546() + fun_l24_n889 +end + +def fun_l23_n547() + fun_l24_n152 +end + +def fun_l23_n548() + fun_l24_n998 +end + +def fun_l23_n549() + fun_l24_n519 +end + +def fun_l23_n550() + fun_l24_n723 +end + +def fun_l23_n551() + fun_l24_n931 +end + +def fun_l23_n552() + fun_l24_n866 +end + +def fun_l23_n553() + fun_l24_n598 +end + +def fun_l23_n554() + fun_l24_n522 +end + +def fun_l23_n555() + fun_l24_n317 +end + +def fun_l23_n556() + fun_l24_n712 +end + +def fun_l23_n557() + fun_l24_n381 +end + +def fun_l23_n558() + fun_l24_n167 +end + +def fun_l23_n559() + fun_l24_n136 +end + +def fun_l23_n560() + fun_l24_n136 +end + +def fun_l23_n561() + fun_l24_n422 +end + +def fun_l23_n562() + fun_l24_n75 +end + +def fun_l23_n563() + fun_l24_n609 +end + +def fun_l23_n564() + fun_l24_n324 +end + +def fun_l23_n565() + fun_l24_n49 +end + +def fun_l23_n566() + fun_l24_n312 +end + +def fun_l23_n567() + fun_l24_n514 +end + +def fun_l23_n568() + fun_l24_n773 +end + +def fun_l23_n569() + fun_l24_n386 +end + +def fun_l23_n570() + fun_l24_n688 +end + +def fun_l23_n571() + fun_l24_n857 +end + +def fun_l23_n572() + fun_l24_n821 +end + +def fun_l23_n573() + fun_l24_n986 +end + +def fun_l23_n574() + fun_l24_n785 +end + +def fun_l23_n575() + fun_l24_n226 +end + +def fun_l23_n576() + fun_l24_n527 +end + +def fun_l23_n577() + fun_l24_n703 +end + +def fun_l23_n578() + fun_l24_n908 +end + +def fun_l23_n579() + fun_l24_n794 +end + +def fun_l23_n580() + fun_l24_n521 +end + +def fun_l23_n581() + fun_l24_n519 +end + +def fun_l23_n582() + fun_l24_n474 +end + +def fun_l23_n583() + fun_l24_n980 +end + +def fun_l23_n584() + fun_l24_n564 +end + +def fun_l23_n585() + fun_l24_n599 +end + +def fun_l23_n586() + fun_l24_n730 +end + +def fun_l23_n587() + fun_l24_n132 +end + +def fun_l23_n588() + fun_l24_n54 +end + +def fun_l23_n589() + fun_l24_n725 +end + +def fun_l23_n590() + fun_l24_n24 +end + +def fun_l23_n591() + fun_l24_n879 +end + +def fun_l23_n592() + fun_l24_n857 +end + +def fun_l23_n593() + fun_l24_n468 +end + +def fun_l23_n594() + fun_l24_n299 +end + +def fun_l23_n595() + fun_l24_n62 +end + +def fun_l23_n596() + fun_l24_n415 +end + +def fun_l23_n597() + fun_l24_n440 +end + +def fun_l23_n598() + fun_l24_n550 +end + +def fun_l23_n599() + fun_l24_n636 +end + +def fun_l23_n600() + fun_l24_n905 +end + +def fun_l23_n601() + fun_l24_n147 +end + +def fun_l23_n602() + fun_l24_n882 +end + +def fun_l23_n603() + fun_l24_n410 +end + +def fun_l23_n604() + fun_l24_n963 +end + +def fun_l23_n605() + fun_l24_n749 +end + +def fun_l23_n606() + fun_l24_n318 +end + +def fun_l23_n607() + fun_l24_n177 +end + +def fun_l23_n608() + fun_l24_n138 +end + +def fun_l23_n609() + fun_l24_n142 +end + +def fun_l23_n610() + fun_l24_n671 +end + +def fun_l23_n611() + fun_l24_n702 +end + +def fun_l23_n612() + fun_l24_n715 +end + +def fun_l23_n613() + fun_l24_n356 +end + +def fun_l23_n614() + fun_l24_n719 +end + +def fun_l23_n615() + fun_l24_n496 +end + +def fun_l23_n616() + fun_l24_n131 +end + +def fun_l23_n617() + fun_l24_n614 +end + +def fun_l23_n618() + fun_l24_n508 +end + +def fun_l23_n619() + fun_l24_n848 +end + +def fun_l23_n620() + fun_l24_n119 +end + +def fun_l23_n621() + fun_l24_n372 +end + +def fun_l23_n622() + fun_l24_n672 +end + +def fun_l23_n623() + fun_l24_n248 +end + +def fun_l23_n624() + fun_l24_n425 +end + +def fun_l23_n625() + fun_l24_n875 +end + +def fun_l23_n626() + fun_l24_n371 +end + +def fun_l23_n627() + fun_l24_n362 +end + +def fun_l23_n628() + fun_l24_n139 +end + +def fun_l23_n629() + fun_l24_n540 +end + +def fun_l23_n630() + fun_l24_n979 +end + +def fun_l23_n631() + fun_l24_n243 +end + +def fun_l23_n632() + fun_l24_n799 +end + +def fun_l23_n633() + fun_l24_n711 +end + +def fun_l23_n634() + fun_l24_n834 +end + +def fun_l23_n635() + fun_l24_n173 +end + +def fun_l23_n636() + fun_l24_n465 +end + +def fun_l23_n637() + fun_l24_n986 +end + +def fun_l23_n638() + fun_l24_n24 +end + +def fun_l23_n639() + fun_l24_n925 +end + +def fun_l23_n640() + fun_l24_n829 +end + +def fun_l23_n641() + fun_l24_n361 +end + +def fun_l23_n642() + fun_l24_n884 +end + +def fun_l23_n643() + fun_l24_n132 +end + +def fun_l23_n644() + fun_l24_n277 +end + +def fun_l23_n645() + fun_l24_n616 +end + +def fun_l23_n646() + fun_l24_n122 +end + +def fun_l23_n647() + fun_l24_n194 +end + +def fun_l23_n648() + fun_l24_n678 +end + +def fun_l23_n649() + fun_l24_n119 +end + +def fun_l23_n650() + fun_l24_n430 +end + +def fun_l23_n651() + fun_l24_n46 +end + +def fun_l23_n652() + fun_l24_n653 +end + +def fun_l23_n653() + fun_l24_n279 +end + +def fun_l23_n654() + fun_l24_n943 +end + +def fun_l23_n655() + fun_l24_n480 +end + +def fun_l23_n656() + fun_l24_n81 +end + +def fun_l23_n657() + fun_l24_n782 +end + +def fun_l23_n658() + fun_l24_n986 +end + +def fun_l23_n659() + fun_l24_n951 +end + +def fun_l23_n660() + fun_l24_n918 +end + +def fun_l23_n661() + fun_l24_n524 +end + +def fun_l23_n662() + fun_l24_n949 +end + +def fun_l23_n663() + fun_l24_n688 +end + +def fun_l23_n664() + fun_l24_n606 +end + +def fun_l23_n665() + fun_l24_n358 +end + +def fun_l23_n666() + fun_l24_n948 +end + +def fun_l23_n667() + fun_l24_n254 +end + +def fun_l23_n668() + fun_l24_n410 +end + +def fun_l23_n669() + fun_l24_n612 +end + +def fun_l23_n670() + fun_l24_n693 +end + +def fun_l23_n671() + fun_l24_n454 +end + +def fun_l23_n672() + fun_l24_n182 +end + +def fun_l23_n673() + fun_l24_n556 +end + +def fun_l23_n674() + fun_l24_n994 +end + +def fun_l23_n675() + fun_l24_n927 +end + +def fun_l23_n676() + fun_l24_n624 +end + +def fun_l23_n677() + fun_l24_n149 +end + +def fun_l23_n678() + fun_l24_n561 +end + +def fun_l23_n679() + fun_l24_n250 +end + +def fun_l23_n680() + fun_l24_n69 +end + +def fun_l23_n681() + fun_l24_n599 +end + +def fun_l23_n682() + fun_l24_n145 +end + +def fun_l23_n683() + fun_l24_n785 +end + +def fun_l23_n684() + fun_l24_n181 +end + +def fun_l23_n685() + fun_l24_n646 +end + +def fun_l23_n686() + fun_l24_n109 +end + +def fun_l23_n687() + fun_l24_n316 +end + +def fun_l23_n688() + fun_l24_n816 +end + +def fun_l23_n689() + fun_l24_n302 +end + +def fun_l23_n690() + fun_l24_n976 +end + +def fun_l23_n691() + fun_l24_n508 +end + +def fun_l23_n692() + fun_l24_n158 +end + +def fun_l23_n693() + fun_l24_n110 +end + +def fun_l23_n694() + fun_l24_n581 +end + +def fun_l23_n695() + fun_l24_n375 +end + +def fun_l23_n696() + fun_l24_n121 +end + +def fun_l23_n697() + fun_l24_n920 +end + +def fun_l23_n698() + fun_l24_n827 +end + +def fun_l23_n699() + fun_l24_n757 +end + +def fun_l23_n700() + fun_l24_n932 +end + +def fun_l23_n701() + fun_l24_n249 +end + +def fun_l23_n702() + fun_l24_n375 +end + +def fun_l23_n703() + fun_l24_n976 +end + +def fun_l23_n704() + fun_l24_n903 +end + +def fun_l23_n705() + fun_l24_n326 +end + +def fun_l23_n706() + fun_l24_n732 +end + +def fun_l23_n707() + fun_l24_n150 +end + +def fun_l23_n708() + fun_l24_n849 +end + +def fun_l23_n709() + fun_l24_n341 +end + +def fun_l23_n710() + fun_l24_n194 +end + +def fun_l23_n711() + fun_l24_n773 +end + +def fun_l23_n712() + fun_l24_n665 +end + +def fun_l23_n713() + fun_l24_n467 +end + +def fun_l23_n714() + fun_l24_n554 +end + +def fun_l23_n715() + fun_l24_n160 +end + +def fun_l23_n716() + fun_l24_n65 +end + +def fun_l23_n717() + fun_l24_n155 +end + +def fun_l23_n718() + fun_l24_n930 +end + +def fun_l23_n719() + fun_l24_n13 +end + +def fun_l23_n720() + fun_l24_n756 +end + +def fun_l23_n721() + fun_l24_n174 +end + +def fun_l23_n722() + fun_l24_n675 +end + +def fun_l23_n723() + fun_l24_n847 +end + +def fun_l23_n724() + fun_l24_n277 +end + +def fun_l23_n725() + fun_l24_n580 +end + +def fun_l23_n726() + fun_l24_n65 +end + +def fun_l23_n727() + fun_l24_n507 +end + +def fun_l23_n728() + fun_l24_n325 +end + +def fun_l23_n729() + fun_l24_n642 +end + +def fun_l23_n730() + fun_l24_n607 +end + +def fun_l23_n731() + fun_l24_n683 +end + +def fun_l23_n732() + fun_l24_n139 +end + +def fun_l23_n733() + fun_l24_n719 +end + +def fun_l23_n734() + fun_l24_n768 +end + +def fun_l23_n735() + fun_l24_n927 +end + +def fun_l23_n736() + fun_l24_n346 +end + +def fun_l23_n737() + fun_l24_n457 +end + +def fun_l23_n738() + fun_l24_n347 +end + +def fun_l23_n739() + fun_l24_n26 +end + +def fun_l23_n740() + fun_l24_n696 +end + +def fun_l23_n741() + fun_l24_n177 +end + +def fun_l23_n742() + fun_l24_n414 +end + +def fun_l23_n743() + fun_l24_n937 +end + +def fun_l23_n744() + fun_l24_n576 +end + +def fun_l23_n745() + fun_l24_n560 +end + +def fun_l23_n746() + fun_l24_n398 +end + +def fun_l23_n747() + fun_l24_n476 +end + +def fun_l23_n748() + fun_l24_n758 +end + +def fun_l23_n749() + fun_l24_n955 +end + +def fun_l23_n750() + fun_l24_n130 +end + +def fun_l23_n751() + fun_l24_n673 +end + +def fun_l23_n752() + fun_l24_n269 +end + +def fun_l23_n753() + fun_l24_n917 +end + +def fun_l23_n754() + fun_l24_n738 +end + +def fun_l23_n755() + fun_l24_n238 +end + +def fun_l23_n756() + fun_l24_n910 +end + +def fun_l23_n757() + fun_l24_n912 +end + +def fun_l23_n758() + fun_l24_n288 +end + +def fun_l23_n759() + fun_l24_n206 +end + +def fun_l23_n760() + fun_l24_n519 +end + +def fun_l23_n761() + fun_l24_n365 +end + +def fun_l23_n762() + fun_l24_n493 +end + +def fun_l23_n763() + fun_l24_n222 +end + +def fun_l23_n764() + fun_l24_n933 +end + +def fun_l23_n765() + fun_l24_n164 +end + +def fun_l23_n766() + fun_l24_n606 +end + +def fun_l23_n767() + fun_l24_n494 +end + +def fun_l23_n768() + fun_l24_n869 +end + +def fun_l23_n769() + fun_l24_n339 +end + +def fun_l23_n770() + fun_l24_n55 +end + +def fun_l23_n771() + fun_l24_n149 +end + +def fun_l23_n772() + fun_l24_n926 +end + +def fun_l23_n773() + fun_l24_n884 +end + +def fun_l23_n774() + fun_l24_n599 +end + +def fun_l23_n775() + fun_l24_n74 +end + +def fun_l23_n776() + fun_l24_n633 +end + +def fun_l23_n777() + fun_l24_n859 +end + +def fun_l23_n778() + fun_l24_n895 +end + +def fun_l23_n779() + fun_l24_n559 +end + +def fun_l23_n780() + fun_l24_n712 +end + +def fun_l23_n781() + fun_l24_n275 +end + +def fun_l23_n782() + fun_l24_n485 +end + +def fun_l23_n783() + fun_l24_n958 +end + +def fun_l23_n784() + fun_l24_n905 +end + +def fun_l23_n785() + fun_l24_n761 +end + +def fun_l23_n786() + fun_l24_n869 +end + +def fun_l23_n787() + fun_l24_n542 +end + +def fun_l23_n788() + fun_l24_n676 +end + +def fun_l23_n789() + fun_l24_n708 +end + +def fun_l23_n790() + fun_l24_n298 +end + +def fun_l23_n791() + fun_l24_n362 +end + +def fun_l23_n792() + fun_l24_n938 +end + +def fun_l23_n793() + fun_l24_n414 +end + +def fun_l23_n794() + fun_l24_n376 +end + +def fun_l23_n795() + fun_l24_n530 +end + +def fun_l23_n796() + fun_l24_n1 +end + +def fun_l23_n797() + fun_l24_n333 +end + +def fun_l23_n798() + fun_l24_n750 +end + +def fun_l23_n799() + fun_l24_n254 +end + +def fun_l23_n800() + fun_l24_n278 +end + +def fun_l23_n801() + fun_l24_n314 +end + +def fun_l23_n802() + fun_l24_n275 +end + +def fun_l23_n803() + fun_l24_n848 +end + +def fun_l23_n804() + fun_l24_n883 +end + +def fun_l23_n805() + fun_l24_n483 +end + +def fun_l23_n806() + fun_l24_n706 +end + +def fun_l23_n807() + fun_l24_n622 +end + +def fun_l23_n808() + fun_l24_n551 +end + +def fun_l23_n809() + fun_l24_n680 +end + +def fun_l23_n810() + fun_l24_n426 +end + +def fun_l23_n811() + fun_l24_n418 +end + +def fun_l23_n812() + fun_l24_n163 +end + +def fun_l23_n813() + fun_l24_n309 +end + +def fun_l23_n814() + fun_l24_n308 +end + +def fun_l23_n815() + fun_l24_n992 +end + +def fun_l23_n816() + fun_l24_n863 +end + +def fun_l23_n817() + fun_l24_n58 +end + +def fun_l23_n818() + fun_l24_n995 +end + +def fun_l23_n819() + fun_l24_n158 +end + +def fun_l23_n820() + fun_l24_n568 +end + +def fun_l23_n821() + fun_l24_n595 +end + +def fun_l23_n822() + fun_l24_n121 +end + +def fun_l23_n823() + fun_l24_n395 +end + +def fun_l23_n824() + fun_l24_n322 +end + +def fun_l23_n825() + fun_l24_n178 +end + +def fun_l23_n826() + fun_l24_n470 +end + +def fun_l23_n827() + fun_l24_n243 +end + +def fun_l23_n828() + fun_l24_n970 +end + +def fun_l23_n829() + fun_l24_n41 +end + +def fun_l23_n830() + fun_l24_n468 +end + +def fun_l23_n831() + fun_l24_n457 +end + +def fun_l23_n832() + fun_l24_n104 +end + +def fun_l23_n833() + fun_l24_n735 +end + +def fun_l23_n834() + fun_l24_n935 +end + +def fun_l23_n835() + fun_l24_n693 +end + +def fun_l23_n836() + fun_l24_n937 +end + +def fun_l23_n837() + fun_l24_n720 +end + +def fun_l23_n838() + fun_l24_n969 +end + +def fun_l23_n839() + fun_l24_n251 +end + +def fun_l23_n840() + fun_l24_n120 +end + +def fun_l23_n841() + fun_l24_n24 +end + +def fun_l23_n842() + fun_l24_n692 +end + +def fun_l23_n843() + fun_l24_n663 +end + +def fun_l23_n844() + fun_l24_n84 +end + +def fun_l23_n845() + fun_l24_n612 +end + +def fun_l23_n846() + fun_l24_n169 +end + +def fun_l23_n847() + fun_l24_n708 +end + +def fun_l23_n848() + fun_l24_n825 +end + +def fun_l23_n849() + fun_l24_n821 +end + +def fun_l23_n850() + fun_l24_n593 +end + +def fun_l23_n851() + fun_l24_n788 +end + +def fun_l23_n852() + fun_l24_n757 +end + +def fun_l23_n853() + fun_l24_n104 +end + +def fun_l23_n854() + fun_l24_n370 +end + +def fun_l23_n855() + fun_l24_n925 +end + +def fun_l23_n856() + fun_l24_n312 +end + +def fun_l23_n857() + fun_l24_n262 +end + +def fun_l23_n858() + fun_l24_n459 +end + +def fun_l23_n859() + fun_l24_n296 +end + +def fun_l23_n860() + fun_l24_n37 +end + +def fun_l23_n861() + fun_l24_n865 +end + +def fun_l23_n862() + fun_l24_n435 +end + +def fun_l23_n863() + fun_l24_n6 +end + +def fun_l23_n864() + fun_l24_n589 +end + +def fun_l23_n865() + fun_l24_n247 +end + +def fun_l23_n866() + fun_l24_n889 +end + +def fun_l23_n867() + fun_l24_n461 +end + +def fun_l23_n868() + fun_l24_n949 +end + +def fun_l23_n869() + fun_l24_n951 +end + +def fun_l23_n870() + fun_l24_n214 +end + +def fun_l23_n871() + fun_l24_n44 +end + +def fun_l23_n872() + fun_l24_n241 +end + +def fun_l23_n873() + fun_l24_n643 +end + +def fun_l23_n874() + fun_l24_n918 +end + +def fun_l23_n875() + fun_l24_n940 +end + +def fun_l23_n876() + fun_l24_n642 +end + +def fun_l23_n877() + fun_l24_n859 +end + +def fun_l23_n878() + fun_l24_n535 +end + +def fun_l23_n879() + fun_l24_n956 +end + +def fun_l23_n880() + fun_l24_n212 +end + +def fun_l23_n881() + fun_l24_n691 +end + +def fun_l23_n882() + fun_l24_n306 +end + +def fun_l23_n883() + fun_l24_n769 +end + +def fun_l23_n884() + fun_l24_n194 +end + +def fun_l23_n885() + fun_l24_n46 +end + +def fun_l23_n886() + fun_l24_n409 +end + +def fun_l23_n887() + fun_l24_n799 +end + +def fun_l23_n888() + fun_l24_n367 +end + +def fun_l23_n889() + fun_l24_n454 +end + +def fun_l23_n890() + fun_l24_n405 +end + +def fun_l23_n891() + fun_l24_n547 +end + +def fun_l23_n892() + fun_l24_n998 +end + +def fun_l23_n893() + fun_l24_n942 +end + +def fun_l23_n894() + fun_l24_n937 +end + +def fun_l23_n895() + fun_l24_n33 +end + +def fun_l23_n896() + fun_l24_n354 +end + +def fun_l23_n897() + fun_l24_n1 +end + +def fun_l23_n898() + fun_l24_n142 +end + +def fun_l23_n899() + fun_l24_n514 +end + +def fun_l23_n900() + fun_l24_n869 +end + +def fun_l23_n901() + fun_l24_n126 +end + +def fun_l23_n902() + fun_l24_n713 +end + +def fun_l23_n903() + fun_l24_n568 +end + +def fun_l23_n904() + fun_l24_n433 +end + +def fun_l23_n905() + fun_l24_n864 +end + +def fun_l23_n906() + fun_l24_n129 +end + +def fun_l23_n907() + fun_l24_n255 +end + +def fun_l23_n908() + fun_l24_n896 +end + +def fun_l23_n909() + fun_l24_n997 +end + +def fun_l23_n910() + fun_l24_n849 +end + +def fun_l23_n911() + fun_l24_n120 +end + +def fun_l23_n912() + fun_l24_n165 +end + +def fun_l23_n913() + fun_l24_n637 +end + +def fun_l23_n914() + fun_l24_n624 +end + +def fun_l23_n915() + fun_l24_n120 +end + +def fun_l23_n916() + fun_l24_n637 +end + +def fun_l23_n917() + fun_l24_n863 +end + +def fun_l23_n918() + fun_l24_n202 +end + +def fun_l23_n919() + fun_l24_n844 +end + +def fun_l23_n920() + fun_l24_n226 +end + +def fun_l23_n921() + fun_l24_n726 +end + +def fun_l23_n922() + fun_l24_n277 +end + +def fun_l23_n923() + fun_l24_n375 +end + +def fun_l23_n924() + fun_l24_n601 +end + +def fun_l23_n925() + fun_l24_n118 +end + +def fun_l23_n926() + fun_l24_n661 +end + +def fun_l23_n927() + fun_l24_n360 +end + +def fun_l23_n928() + fun_l24_n627 +end + +def fun_l23_n929() + fun_l24_n238 +end + +def fun_l23_n930() + fun_l24_n372 +end + +def fun_l23_n931() + fun_l24_n768 +end + +def fun_l23_n932() + fun_l24_n848 +end + +def fun_l23_n933() + fun_l24_n540 +end + +def fun_l23_n934() + fun_l24_n848 +end + +def fun_l23_n935() + fun_l24_n688 +end + +def fun_l23_n936() + fun_l24_n9 +end + +def fun_l23_n937() + fun_l24_n362 +end + +def fun_l23_n938() + fun_l24_n151 +end + +def fun_l23_n939() + fun_l24_n79 +end + +def fun_l23_n940() + fun_l24_n673 +end + +def fun_l23_n941() + fun_l24_n575 +end + +def fun_l23_n942() + fun_l24_n368 +end + +def fun_l23_n943() + fun_l24_n264 +end + +def fun_l23_n944() + fun_l24_n502 +end + +def fun_l23_n945() + fun_l24_n483 +end + +def fun_l23_n946() + fun_l24_n623 +end + +def fun_l23_n947() + fun_l24_n445 +end + +def fun_l23_n948() + fun_l24_n560 +end + +def fun_l23_n949() + fun_l24_n152 +end + +def fun_l23_n950() + fun_l24_n211 +end + +def fun_l23_n951() + fun_l24_n777 +end + +def fun_l23_n952() + fun_l24_n623 +end + +def fun_l23_n953() + fun_l24_n410 +end + +def fun_l23_n954() + fun_l24_n456 +end + +def fun_l23_n955() + fun_l24_n35 +end + +def fun_l23_n956() + fun_l24_n134 +end + +def fun_l23_n957() + fun_l24_n768 +end + +def fun_l23_n958() + fun_l24_n827 +end + +def fun_l23_n959() + fun_l24_n8 +end + +def fun_l23_n960() + fun_l24_n339 +end + +def fun_l23_n961() + fun_l24_n580 +end + +def fun_l23_n962() + fun_l24_n570 +end + +def fun_l23_n963() + fun_l24_n308 +end + +def fun_l23_n964() + fun_l24_n531 +end + +def fun_l23_n965() + fun_l24_n378 +end + +def fun_l23_n966() + fun_l24_n632 +end + +def fun_l23_n967() + fun_l24_n465 +end + +def fun_l23_n968() + fun_l24_n318 +end + +def fun_l23_n969() + fun_l24_n36 +end + +def fun_l23_n970() + fun_l24_n408 +end + +def fun_l23_n971() + fun_l24_n225 +end + +def fun_l23_n972() + fun_l24_n105 +end + +def fun_l23_n973() + fun_l24_n736 +end + +def fun_l23_n974() + fun_l24_n735 +end + +def fun_l23_n975() + fun_l24_n811 +end + +def fun_l23_n976() + fun_l24_n495 +end + +def fun_l23_n977() + fun_l24_n563 +end + +def fun_l23_n978() + fun_l24_n511 +end + +def fun_l23_n979() + fun_l24_n158 +end + +def fun_l23_n980() + fun_l24_n222 +end + +def fun_l23_n981() + fun_l24_n568 +end + +def fun_l23_n982() + fun_l24_n936 +end + +def fun_l23_n983() + fun_l24_n932 +end + +def fun_l23_n984() + fun_l24_n872 +end + +def fun_l23_n985() + fun_l24_n70 +end + +def fun_l23_n986() + fun_l24_n602 +end + +def fun_l23_n987() + fun_l24_n364 +end + +def fun_l23_n988() + fun_l24_n904 +end + +def fun_l23_n989() + fun_l24_n98 +end + +def fun_l23_n990() + fun_l24_n907 +end + +def fun_l23_n991() + fun_l24_n435 +end + +def fun_l23_n992() + fun_l24_n24 +end + +def fun_l23_n993() + fun_l24_n790 +end + +def fun_l23_n994() + fun_l24_n249 +end + +def fun_l23_n995() + fun_l24_n12 +end + +def fun_l23_n996() + fun_l24_n956 +end + +def fun_l23_n997() + fun_l24_n539 +end + +def fun_l23_n998() + fun_l24_n935 +end + +def fun_l23_n999() + fun_l24_n964 +end + +def fun_l24_n0() + fun_l25_n193 +end + +def fun_l24_n1() + fun_l25_n802 +end + +def fun_l24_n2() + fun_l25_n936 +end + +def fun_l24_n3() + fun_l25_n672 +end + +def fun_l24_n4() + fun_l25_n506 +end + +def fun_l24_n5() + fun_l25_n598 +end + +def fun_l24_n6() + fun_l25_n368 +end + +def fun_l24_n7() + fun_l25_n4 +end + +def fun_l24_n8() + fun_l25_n396 +end + +def fun_l24_n9() + fun_l25_n772 +end + +def fun_l24_n10() + fun_l25_n986 +end + +def fun_l24_n11() + fun_l25_n182 +end + +def fun_l24_n12() + fun_l25_n663 +end + +def fun_l24_n13() + fun_l25_n460 +end + +def fun_l24_n14() + fun_l25_n78 +end + +def fun_l24_n15() + fun_l25_n590 +end + +def fun_l24_n16() + fun_l25_n205 +end + +def fun_l24_n17() + fun_l25_n848 +end + +def fun_l24_n18() + fun_l25_n270 +end + +def fun_l24_n19() + fun_l25_n491 +end + +def fun_l24_n20() + fun_l25_n740 +end + +def fun_l24_n21() + fun_l25_n800 +end + +def fun_l24_n22() + fun_l25_n859 +end + +def fun_l24_n23() + fun_l25_n300 +end + +def fun_l24_n24() + fun_l25_n705 +end + +def fun_l24_n25() + fun_l25_n917 +end + +def fun_l24_n26() + fun_l25_n890 +end + +def fun_l24_n27() + fun_l25_n700 +end + +def fun_l24_n28() + fun_l25_n448 +end + +def fun_l24_n29() + fun_l25_n774 +end + +def fun_l24_n30() + fun_l25_n13 +end + +def fun_l24_n31() + fun_l25_n427 +end + +def fun_l24_n32() + fun_l25_n159 +end + +def fun_l24_n33() + fun_l25_n180 +end + +def fun_l24_n34() + fun_l25_n721 +end + +def fun_l24_n35() + fun_l25_n539 +end + +def fun_l24_n36() + fun_l25_n808 +end + +def fun_l24_n37() + fun_l25_n123 +end + +def fun_l24_n38() + fun_l25_n428 +end + +def fun_l24_n39() + fun_l25_n678 +end + +def fun_l24_n40() + fun_l25_n821 +end + +def fun_l24_n41() + fun_l25_n170 +end + +def fun_l24_n42() + fun_l25_n115 +end + +def fun_l24_n43() + fun_l25_n72 +end + +def fun_l24_n44() + fun_l25_n280 +end + +def fun_l24_n45() + fun_l25_n950 +end + +def fun_l24_n46() + fun_l25_n572 +end + +def fun_l24_n47() + fun_l25_n125 +end + +def fun_l24_n48() + fun_l25_n607 +end + +def fun_l24_n49() + fun_l25_n704 +end + +def fun_l24_n50() + fun_l25_n125 +end + +def fun_l24_n51() + fun_l25_n179 +end + +def fun_l24_n52() + fun_l25_n77 +end + +def fun_l24_n53() + fun_l25_n247 +end + +def fun_l24_n54() + fun_l25_n828 +end + +def fun_l24_n55() + fun_l25_n461 +end + +def fun_l24_n56() + fun_l25_n686 +end + +def fun_l24_n57() + fun_l25_n222 +end + +def fun_l24_n58() + fun_l25_n394 +end + +def fun_l24_n59() + fun_l25_n535 +end + +def fun_l24_n60() + fun_l25_n199 +end + +def fun_l24_n61() + fun_l25_n543 +end + +def fun_l24_n62() + fun_l25_n304 +end + +def fun_l24_n63() + fun_l25_n520 +end + +def fun_l24_n64() + fun_l25_n167 +end + +def fun_l24_n65() + fun_l25_n604 +end + +def fun_l24_n66() + fun_l25_n685 +end + +def fun_l24_n67() + fun_l25_n134 +end + +def fun_l24_n68() + fun_l25_n913 +end + +def fun_l24_n69() + fun_l25_n899 +end + +def fun_l24_n70() + fun_l25_n872 +end + +def fun_l24_n71() + fun_l25_n466 +end + +def fun_l24_n72() + fun_l25_n352 +end + +def fun_l24_n73() + fun_l25_n624 +end + +def fun_l24_n74() + fun_l25_n464 +end + +def fun_l24_n75() + fun_l25_n513 +end + +def fun_l24_n76() + fun_l25_n310 +end + +def fun_l24_n77() + fun_l25_n129 +end + +def fun_l24_n78() + fun_l25_n770 +end + +def fun_l24_n79() + fun_l25_n96 +end + +def fun_l24_n80() + fun_l25_n519 +end + +def fun_l24_n81() + fun_l25_n495 +end + +def fun_l24_n82() + fun_l25_n789 +end + +def fun_l24_n83() + fun_l25_n676 +end + +def fun_l24_n84() + fun_l25_n877 +end + +def fun_l24_n85() + fun_l25_n17 +end + +def fun_l24_n86() + fun_l25_n428 +end + +def fun_l24_n87() + fun_l25_n282 +end + +def fun_l24_n88() + fun_l25_n313 +end + +def fun_l24_n89() + fun_l25_n638 +end + +def fun_l24_n90() + fun_l25_n543 +end + +def fun_l24_n91() + fun_l25_n63 +end + +def fun_l24_n92() + fun_l25_n398 +end + +def fun_l24_n93() + fun_l25_n726 +end + +def fun_l24_n94() + fun_l25_n645 +end + +def fun_l24_n95() + fun_l25_n163 +end + +def fun_l24_n96() + fun_l25_n228 +end + +def fun_l24_n97() + fun_l25_n346 +end + +def fun_l24_n98() + fun_l25_n56 +end + +def fun_l24_n99() + fun_l25_n258 +end + +def fun_l24_n100() + fun_l25_n730 +end + +def fun_l24_n101() + fun_l25_n216 +end + +def fun_l24_n102() + fun_l25_n370 +end + +def fun_l24_n103() + fun_l25_n17 +end + +def fun_l24_n104() + fun_l25_n892 +end + +def fun_l24_n105() + fun_l25_n977 +end + +def fun_l24_n106() + fun_l25_n285 +end + +def fun_l24_n107() + fun_l25_n922 +end + +def fun_l24_n108() + fun_l25_n62 +end + +def fun_l24_n109() + fun_l25_n103 +end + +def fun_l24_n110() + fun_l25_n644 +end + +def fun_l24_n111() + fun_l25_n467 +end + +def fun_l24_n112() + fun_l25_n543 +end + +def fun_l24_n113() + fun_l25_n180 +end + +def fun_l24_n114() + fun_l25_n186 +end + +def fun_l24_n115() + fun_l25_n685 +end + +def fun_l24_n116() + fun_l25_n754 +end + +def fun_l24_n117() + fun_l25_n842 +end + +def fun_l24_n118() + fun_l25_n759 +end + +def fun_l24_n119() + fun_l25_n372 +end + +def fun_l24_n120() + fun_l25_n874 +end + +def fun_l24_n121() + fun_l25_n332 +end + +def fun_l24_n122() + fun_l25_n91 +end + +def fun_l24_n123() + fun_l25_n229 +end + +def fun_l24_n124() + fun_l25_n485 +end + +def fun_l24_n125() + fun_l25_n322 +end + +def fun_l24_n126() + fun_l25_n750 +end + +def fun_l24_n127() + fun_l25_n466 +end + +def fun_l24_n128() + fun_l25_n936 +end + +def fun_l24_n129() + fun_l25_n172 +end + +def fun_l24_n130() + fun_l25_n389 +end + +def fun_l24_n131() + fun_l25_n789 +end + +def fun_l24_n132() + fun_l25_n165 +end + +def fun_l24_n133() + fun_l25_n756 +end + +def fun_l24_n134() + fun_l25_n1 +end + +def fun_l24_n135() + fun_l25_n362 +end + +def fun_l24_n136() + fun_l25_n323 +end + +def fun_l24_n137() + fun_l25_n656 +end + +def fun_l24_n138() + fun_l25_n463 +end + +def fun_l24_n139() + fun_l25_n392 +end + +def fun_l24_n140() + fun_l25_n43 +end + +def fun_l24_n141() + fun_l25_n788 +end + +def fun_l24_n142() + fun_l25_n212 +end + +def fun_l24_n143() + fun_l25_n597 +end + +def fun_l24_n144() + fun_l25_n885 +end + +def fun_l24_n145() + fun_l25_n470 +end + +def fun_l24_n146() + fun_l25_n945 +end + +def fun_l24_n147() + fun_l25_n884 +end + +def fun_l24_n148() + fun_l25_n492 +end + +def fun_l24_n149() + fun_l25_n466 +end + +def fun_l24_n150() + fun_l25_n548 +end + +def fun_l24_n151() + fun_l25_n574 +end + +def fun_l24_n152() + fun_l25_n920 +end + +def fun_l24_n153() + fun_l25_n530 +end + +def fun_l24_n154() + fun_l25_n90 +end + +def fun_l24_n155() + fun_l25_n531 +end + +def fun_l24_n156() + fun_l25_n848 +end + +def fun_l24_n157() + fun_l25_n116 +end + +def fun_l24_n158() + fun_l25_n25 +end + +def fun_l24_n159() + fun_l25_n432 +end + +def fun_l24_n160() + fun_l25_n978 +end + +def fun_l24_n161() + fun_l25_n383 +end + +def fun_l24_n162() + fun_l25_n678 +end + +def fun_l24_n163() + fun_l25_n785 +end + +def fun_l24_n164() + fun_l25_n504 +end + +def fun_l24_n165() + fun_l25_n682 +end + +def fun_l24_n166() + fun_l25_n649 +end + +def fun_l24_n167() + fun_l25_n498 +end + +def fun_l24_n168() + fun_l25_n805 +end + +def fun_l24_n169() + fun_l25_n215 +end + +def fun_l24_n170() + fun_l25_n444 +end + +def fun_l24_n171() + fun_l25_n585 +end + +def fun_l24_n172() + fun_l25_n22 +end + +def fun_l24_n173() + fun_l25_n214 +end + +def fun_l24_n174() + fun_l25_n942 +end + +def fun_l24_n175() + fun_l25_n763 +end + +def fun_l24_n176() + fun_l25_n852 +end + +def fun_l24_n177() + fun_l25_n591 +end + +def fun_l24_n178() + fun_l25_n498 +end + +def fun_l24_n179() + fun_l25_n111 +end + +def fun_l24_n180() + fun_l25_n286 +end + +def fun_l24_n181() + fun_l25_n808 +end + +def fun_l24_n182() + fun_l25_n402 +end + +def fun_l24_n183() + fun_l25_n222 +end + +def fun_l24_n184() + fun_l25_n646 +end + +def fun_l24_n185() + fun_l25_n550 +end + +def fun_l24_n186() + fun_l25_n284 +end + +def fun_l24_n187() + fun_l25_n832 +end + +def fun_l24_n188() + fun_l25_n554 +end + +def fun_l24_n189() + fun_l25_n982 +end + +def fun_l24_n190() + fun_l25_n10 +end + +def fun_l24_n191() + fun_l25_n843 +end + +def fun_l24_n192() + fun_l25_n126 +end + +def fun_l24_n193() + fun_l25_n332 +end + +def fun_l24_n194() + fun_l25_n145 +end + +def fun_l24_n195() + fun_l25_n657 +end + +def fun_l24_n196() + fun_l25_n636 +end + +def fun_l24_n197() + fun_l25_n875 +end + +def fun_l24_n198() + fun_l25_n160 +end + +def fun_l24_n199() + fun_l25_n682 +end + +def fun_l24_n200() + fun_l25_n556 +end + +def fun_l24_n201() + fun_l25_n154 +end + +def fun_l24_n202() + fun_l25_n105 +end + +def fun_l24_n203() + fun_l25_n958 +end + +def fun_l24_n204() + fun_l25_n998 +end + +def fun_l24_n205() + fun_l25_n356 +end + +def fun_l24_n206() + fun_l25_n531 +end + +def fun_l24_n207() + fun_l25_n62 +end + +def fun_l24_n208() + fun_l25_n320 +end + +def fun_l24_n209() + fun_l25_n725 +end + +def fun_l24_n210() + fun_l25_n790 +end + +def fun_l24_n211() + fun_l25_n740 +end + +def fun_l24_n212() + fun_l25_n73 +end + +def fun_l24_n213() + fun_l25_n949 +end + +def fun_l24_n214() + fun_l25_n526 +end + +def fun_l24_n215() + fun_l25_n881 +end + +def fun_l24_n216() + fun_l25_n43 +end + +def fun_l24_n217() + fun_l25_n284 +end + +def fun_l24_n218() + fun_l25_n252 +end + +def fun_l24_n219() + fun_l25_n973 +end + +def fun_l24_n220() + fun_l25_n264 +end + +def fun_l24_n221() + fun_l25_n55 +end + +def fun_l24_n222() + fun_l25_n731 +end + +def fun_l24_n223() + fun_l25_n274 +end + +def fun_l24_n224() + fun_l25_n748 +end + +def fun_l24_n225() + fun_l25_n990 +end + +def fun_l24_n226() + fun_l25_n243 +end + +def fun_l24_n227() + fun_l25_n607 +end + +def fun_l24_n228() + fun_l25_n352 +end + +def fun_l24_n229() + fun_l25_n238 +end + +def fun_l24_n230() + fun_l25_n252 +end + +def fun_l24_n231() + fun_l25_n534 +end + +def fun_l24_n232() + fun_l25_n330 +end + +def fun_l24_n233() + fun_l25_n915 +end + +def fun_l24_n234() + fun_l25_n106 +end + +def fun_l24_n235() + fun_l25_n59 +end + +def fun_l24_n236() + fun_l25_n829 +end + +def fun_l24_n237() + fun_l25_n563 +end + +def fun_l24_n238() + fun_l25_n334 +end + +def fun_l24_n239() + fun_l25_n828 +end + +def fun_l24_n240() + fun_l25_n530 +end + +def fun_l24_n241() + fun_l25_n831 +end + +def fun_l24_n242() + fun_l25_n922 +end + +def fun_l24_n243() + fun_l25_n822 +end + +def fun_l24_n244() + fun_l25_n369 +end + +def fun_l24_n245() + fun_l25_n977 +end + +def fun_l24_n246() + fun_l25_n797 +end + +def fun_l24_n247() + fun_l25_n883 +end + +def fun_l24_n248() + fun_l25_n964 +end + +def fun_l24_n249() + fun_l25_n490 +end + +def fun_l24_n250() + fun_l25_n903 +end + +def fun_l24_n251() + fun_l25_n154 +end + +def fun_l24_n252() + fun_l25_n74 +end + +def fun_l24_n253() + fun_l25_n955 +end + +def fun_l24_n254() + fun_l25_n709 +end + +def fun_l24_n255() + fun_l25_n154 +end + +def fun_l24_n256() + fun_l25_n940 +end + +def fun_l24_n257() + fun_l25_n33 +end + +def fun_l24_n258() + fun_l25_n450 +end + +def fun_l24_n259() + fun_l25_n592 +end + +def fun_l24_n260() + fun_l25_n430 +end + +def fun_l24_n261() + fun_l25_n650 +end + +def fun_l24_n262() + fun_l25_n891 +end + +def fun_l24_n263() + fun_l25_n803 +end + +def fun_l24_n264() + fun_l25_n622 +end + +def fun_l24_n265() + fun_l25_n401 +end + +def fun_l24_n266() + fun_l25_n493 +end + +def fun_l24_n267() + fun_l25_n240 +end + +def fun_l24_n268() + fun_l25_n654 +end + +def fun_l24_n269() + fun_l25_n839 +end + +def fun_l24_n270() + fun_l25_n889 +end + +def fun_l24_n271() + fun_l25_n770 +end + +def fun_l24_n272() + fun_l25_n860 +end + +def fun_l24_n273() + fun_l25_n634 +end + +def fun_l24_n274() + fun_l25_n365 +end + +def fun_l24_n275() + fun_l25_n321 +end + +def fun_l24_n276() + fun_l25_n628 +end + +def fun_l24_n277() + fun_l25_n669 +end + +def fun_l24_n278() + fun_l25_n815 +end + +def fun_l24_n279() + fun_l25_n647 +end + +def fun_l24_n280() + fun_l25_n920 +end + +def fun_l24_n281() + fun_l25_n620 +end + +def fun_l24_n282() + fun_l25_n609 +end + +def fun_l24_n283() + fun_l25_n45 +end + +def fun_l24_n284() + fun_l25_n632 +end + +def fun_l24_n285() + fun_l25_n961 +end + +def fun_l24_n286() + fun_l25_n261 +end + +def fun_l24_n287() + fun_l25_n348 +end + +def fun_l24_n288() + fun_l25_n687 +end + +def fun_l24_n289() + fun_l25_n359 +end + +def fun_l24_n290() + fun_l25_n306 +end + +def fun_l24_n291() + fun_l25_n487 +end + +def fun_l24_n292() + fun_l25_n59 +end + +def fun_l24_n293() + fun_l25_n353 +end + +def fun_l24_n294() + fun_l25_n553 +end + +def fun_l24_n295() + fun_l25_n704 +end + +def fun_l24_n296() + fun_l25_n691 +end + +def fun_l24_n297() + fun_l25_n332 +end + +def fun_l24_n298() + fun_l25_n665 +end + +def fun_l24_n299() + fun_l25_n407 +end + +def fun_l24_n300() + fun_l25_n182 +end + +def fun_l24_n301() + fun_l25_n716 +end + +def fun_l24_n302() + fun_l25_n55 +end + +def fun_l24_n303() + fun_l25_n946 +end + +def fun_l24_n304() + fun_l25_n448 +end + +def fun_l24_n305() + fun_l25_n959 +end + +def fun_l24_n306() + fun_l25_n23 +end + +def fun_l24_n307() + fun_l25_n327 +end + +def fun_l24_n308() + fun_l25_n317 +end + +def fun_l24_n309() + fun_l25_n2 +end + +def fun_l24_n310() + fun_l25_n168 +end + +def fun_l24_n311() + fun_l25_n171 +end + +def fun_l24_n312() + fun_l25_n138 +end + +def fun_l24_n313() + fun_l25_n974 +end + +def fun_l24_n314() + fun_l25_n981 +end + +def fun_l24_n315() + fun_l25_n382 +end + +def fun_l24_n316() + fun_l25_n590 +end + +def fun_l24_n317() + fun_l25_n613 +end + +def fun_l24_n318() + fun_l25_n119 +end + +def fun_l24_n319() + fun_l25_n431 +end + +def fun_l24_n320() + fun_l25_n595 +end + +def fun_l24_n321() + fun_l25_n406 +end + +def fun_l24_n322() + fun_l25_n771 +end + +def fun_l24_n323() + fun_l25_n693 +end + +def fun_l24_n324() + fun_l25_n442 +end + +def fun_l24_n325() + fun_l25_n164 +end + +def fun_l24_n326() + fun_l25_n630 +end + +def fun_l24_n327() + fun_l25_n31 +end + +def fun_l24_n328() + fun_l25_n422 +end + +def fun_l24_n329() + fun_l25_n204 +end + +def fun_l24_n330() + fun_l25_n304 +end + +def fun_l24_n331() + fun_l25_n398 +end + +def fun_l24_n332() + fun_l25_n903 +end + +def fun_l24_n333() + fun_l25_n841 +end + +def fun_l24_n334() + fun_l25_n662 +end + +def fun_l24_n335() + fun_l25_n247 +end + +def fun_l24_n336() + fun_l25_n348 +end + +def fun_l24_n337() + fun_l25_n378 +end + +def fun_l24_n338() + fun_l25_n197 +end + +def fun_l24_n339() + fun_l25_n897 +end + +def fun_l24_n340() + fun_l25_n792 +end + +def fun_l24_n341() + fun_l25_n655 +end + +def fun_l24_n342() + fun_l25_n352 +end + +def fun_l24_n343() + fun_l25_n853 +end + +def fun_l24_n344() + fun_l25_n202 +end + +def fun_l24_n345() + fun_l25_n420 +end + +def fun_l24_n346() + fun_l25_n146 +end + +def fun_l24_n347() + fun_l25_n766 +end + +def fun_l24_n348() + fun_l25_n245 +end + +def fun_l24_n349() + fun_l25_n772 +end + +def fun_l24_n350() + fun_l25_n789 +end + +def fun_l24_n351() + fun_l25_n180 +end + +def fun_l24_n352() + fun_l25_n982 +end + +def fun_l24_n353() + fun_l25_n837 +end + +def fun_l24_n354() + fun_l25_n515 +end + +def fun_l24_n355() + fun_l25_n688 +end + +def fun_l24_n356() + fun_l25_n85 +end + +def fun_l24_n357() + fun_l25_n918 +end + +def fun_l24_n358() + fun_l25_n104 +end + +def fun_l24_n359() + fun_l25_n797 +end + +def fun_l24_n360() + fun_l25_n488 +end + +def fun_l24_n361() + fun_l25_n970 +end + +def fun_l24_n362() + fun_l25_n82 +end + +def fun_l24_n363() + fun_l25_n815 +end + +def fun_l24_n364() + fun_l25_n81 +end + +def fun_l24_n365() + fun_l25_n70 +end + +def fun_l24_n366() + fun_l25_n686 +end + +def fun_l24_n367() + fun_l25_n8 +end + +def fun_l24_n368() + fun_l25_n835 +end + +def fun_l24_n369() + fun_l25_n473 +end + +def fun_l24_n370() + fun_l25_n637 +end + +def fun_l24_n371() + fun_l25_n314 +end + +def fun_l24_n372() + fun_l25_n857 +end + +def fun_l24_n373() + fun_l25_n496 +end + +def fun_l24_n374() + fun_l25_n182 +end + +def fun_l24_n375() + fun_l25_n730 +end + +def fun_l24_n376() + fun_l25_n370 +end + +def fun_l24_n377() + fun_l25_n289 +end + +def fun_l24_n378() + fun_l25_n12 +end + +def fun_l24_n379() + fun_l25_n73 +end + +def fun_l24_n380() + fun_l25_n514 +end + +def fun_l24_n381() + fun_l25_n947 +end + +def fun_l24_n382() + fun_l25_n368 +end + +def fun_l24_n383() + fun_l25_n997 +end + +def fun_l24_n384() + fun_l25_n542 +end + +def fun_l24_n385() + fun_l25_n564 +end + +def fun_l24_n386() + fun_l25_n213 +end + +def fun_l24_n387() + fun_l25_n748 +end + +def fun_l24_n388() + fun_l25_n147 +end + +def fun_l24_n389() + fun_l25_n437 +end + +def fun_l24_n390() + fun_l25_n844 +end + +def fun_l24_n391() + fun_l25_n747 +end + +def fun_l24_n392() + fun_l25_n68 +end + +def fun_l24_n393() + fun_l25_n746 +end + +def fun_l24_n394() + fun_l25_n816 +end + +def fun_l24_n395() + fun_l25_n865 +end + +def fun_l24_n396() + fun_l25_n235 +end + +def fun_l24_n397() + fun_l25_n961 +end + +def fun_l24_n398() + fun_l25_n8 +end + +def fun_l24_n399() + fun_l25_n741 +end + +def fun_l24_n400() + fun_l25_n639 +end + +def fun_l24_n401() + fun_l25_n419 +end + +def fun_l24_n402() + fun_l25_n381 +end + +def fun_l24_n403() + fun_l25_n674 +end + +def fun_l24_n404() + fun_l25_n238 +end + +def fun_l24_n405() + fun_l25_n75 +end + +def fun_l24_n406() + fun_l25_n10 +end + +def fun_l24_n407() + fun_l25_n672 +end + +def fun_l24_n408() + fun_l25_n154 +end + +def fun_l24_n409() + fun_l25_n844 +end + +def fun_l24_n410() + fun_l25_n578 +end + +def fun_l24_n411() + fun_l25_n535 +end + +def fun_l24_n412() + fun_l25_n742 +end + +def fun_l24_n413() + fun_l25_n587 +end + +def fun_l24_n414() + fun_l25_n967 +end + +def fun_l24_n415() + fun_l25_n290 +end + +def fun_l24_n416() + fun_l25_n958 +end + +def fun_l24_n417() + fun_l25_n19 +end + +def fun_l24_n418() + fun_l25_n983 +end + +def fun_l24_n419() + fun_l25_n206 +end + +def fun_l24_n420() + fun_l25_n317 +end + +def fun_l24_n421() + fun_l25_n847 +end + +def fun_l24_n422() + fun_l25_n409 +end + +def fun_l24_n423() + fun_l25_n584 +end + +def fun_l24_n424() + fun_l25_n667 +end + +def fun_l24_n425() + fun_l25_n559 +end + +def fun_l24_n426() + fun_l25_n503 +end + +def fun_l24_n427() + fun_l25_n775 +end + +def fun_l24_n428() + fun_l25_n828 +end + +def fun_l24_n429() + fun_l25_n375 +end + +def fun_l24_n430() + fun_l25_n342 +end + +def fun_l24_n431() + fun_l25_n382 +end + +def fun_l24_n432() + fun_l25_n978 +end + +def fun_l24_n433() + fun_l25_n290 +end + +def fun_l24_n434() + fun_l25_n367 +end + +def fun_l24_n435() + fun_l25_n485 +end + +def fun_l24_n436() + fun_l25_n299 +end + +def fun_l24_n437() + fun_l25_n343 +end + +def fun_l24_n438() + fun_l25_n620 +end + +def fun_l24_n439() + fun_l25_n627 +end + +def fun_l24_n440() + fun_l25_n955 +end + +def fun_l24_n441() + fun_l25_n330 +end + +def fun_l24_n442() + fun_l25_n37 +end + +def fun_l24_n443() + fun_l25_n437 +end + +def fun_l24_n444() + fun_l25_n879 +end + +def fun_l24_n445() + fun_l25_n532 +end + +def fun_l24_n446() + fun_l25_n701 +end + +def fun_l24_n447() + fun_l25_n936 +end + +def fun_l24_n448() + fun_l25_n503 +end + +def fun_l24_n449() + fun_l25_n275 +end + +def fun_l24_n450() + fun_l25_n77 +end + +def fun_l24_n451() + fun_l25_n265 +end + +def fun_l24_n452() + fun_l25_n727 +end + +def fun_l24_n453() + fun_l25_n547 +end + +def fun_l24_n454() + fun_l25_n796 +end + +def fun_l24_n455() + fun_l25_n18 +end + +def fun_l24_n456() + fun_l25_n328 +end + +def fun_l24_n457() + fun_l25_n672 +end + +def fun_l24_n458() + fun_l25_n803 +end + +def fun_l24_n459() + fun_l25_n590 +end + +def fun_l24_n460() + fun_l25_n798 +end + +def fun_l24_n461() + fun_l25_n823 +end + +def fun_l24_n462() + fun_l25_n258 +end + +def fun_l24_n463() + fun_l25_n569 +end + +def fun_l24_n464() + fun_l25_n541 +end + +def fun_l24_n465() + fun_l25_n313 +end + +def fun_l24_n466() + fun_l25_n994 +end + +def fun_l24_n467() + fun_l25_n925 +end + +def fun_l24_n468() + fun_l25_n277 +end + +def fun_l24_n469() + fun_l25_n862 +end + +def fun_l24_n470() + fun_l25_n241 +end + +def fun_l24_n471() + fun_l25_n203 +end + +def fun_l24_n472() + fun_l25_n950 +end + +def fun_l24_n473() + fun_l25_n774 +end + +def fun_l24_n474() + fun_l25_n699 +end + +def fun_l24_n475() + fun_l25_n415 +end + +def fun_l24_n476() + fun_l25_n100 +end + +def fun_l24_n477() + fun_l25_n97 +end + +def fun_l24_n478() + fun_l25_n439 +end + +def fun_l24_n479() + fun_l25_n276 +end + +def fun_l24_n480() + fun_l25_n761 +end + +def fun_l24_n481() + fun_l25_n980 +end + +def fun_l24_n482() + fun_l25_n927 +end + +def fun_l24_n483() + fun_l25_n276 +end + +def fun_l24_n484() + fun_l25_n402 +end + +def fun_l24_n485() + fun_l25_n169 +end + +def fun_l24_n486() + fun_l25_n928 +end + +def fun_l24_n487() + fun_l25_n931 +end + +def fun_l24_n488() + fun_l25_n807 +end + +def fun_l24_n489() + fun_l25_n258 +end + +def fun_l24_n490() + fun_l25_n385 +end + +def fun_l24_n491() + fun_l25_n846 +end + +def fun_l24_n492() + fun_l25_n872 +end + +def fun_l24_n493() + fun_l25_n169 +end + +def fun_l24_n494() + fun_l25_n77 +end + +def fun_l24_n495() + fun_l25_n775 +end + +def fun_l24_n496() + fun_l25_n744 +end + +def fun_l24_n497() + fun_l25_n666 +end + +def fun_l24_n498() + fun_l25_n607 +end + +def fun_l24_n499() + fun_l25_n603 +end + +def fun_l24_n500() + fun_l25_n821 +end + +def fun_l24_n501() + fun_l25_n83 +end + +def fun_l24_n502() + fun_l25_n331 +end + +def fun_l24_n503() + fun_l25_n20 +end + +def fun_l24_n504() + fun_l25_n115 +end + +def fun_l24_n505() + fun_l25_n437 +end + +def fun_l24_n506() + fun_l25_n679 +end + +def fun_l24_n507() + fun_l25_n424 +end + +def fun_l24_n508() + fun_l25_n745 +end + +def fun_l24_n509() + fun_l25_n389 +end + +def fun_l24_n510() + fun_l25_n762 +end + +def fun_l24_n511() + fun_l25_n289 +end + +def fun_l24_n512() + fun_l25_n944 +end + +def fun_l24_n513() + fun_l25_n601 +end + +def fun_l24_n514() + fun_l25_n660 +end + +def fun_l24_n515() + fun_l25_n975 +end + +def fun_l24_n516() + fun_l25_n815 +end + +def fun_l24_n517() + fun_l25_n208 +end + +def fun_l24_n518() + fun_l25_n736 +end + +def fun_l24_n519() + fun_l25_n189 +end + +def fun_l24_n520() + fun_l25_n490 +end + +def fun_l24_n521() + fun_l25_n452 +end + +def fun_l24_n522() + fun_l25_n96 +end + +def fun_l24_n523() + fun_l25_n772 +end + +def fun_l24_n524() + fun_l25_n930 +end + +def fun_l24_n525() + fun_l25_n322 +end + +def fun_l24_n526() + fun_l25_n419 +end + +def fun_l24_n527() + fun_l25_n997 +end + +def fun_l24_n528() + fun_l25_n475 +end + +def fun_l24_n529() + fun_l25_n511 +end + +def fun_l24_n530() + fun_l25_n909 +end + +def fun_l24_n531() + fun_l25_n33 +end + +def fun_l24_n532() + fun_l25_n923 +end + +def fun_l24_n533() + fun_l25_n201 +end + +def fun_l24_n534() + fun_l25_n444 +end + +def fun_l24_n535() + fun_l25_n327 +end + +def fun_l24_n536() + fun_l25_n982 +end + +def fun_l24_n537() + fun_l25_n969 +end + +def fun_l24_n538() + fun_l25_n514 +end + +def fun_l24_n539() + fun_l25_n707 +end + +def fun_l24_n540() + fun_l25_n571 +end + +def fun_l24_n541() + fun_l25_n407 +end + +def fun_l24_n542() + fun_l25_n848 +end + +def fun_l24_n543() + fun_l25_n457 +end + +def fun_l24_n544() + fun_l25_n374 +end + +def fun_l24_n545() + fun_l25_n875 +end + +def fun_l24_n546() + fun_l25_n166 +end + +def fun_l24_n547() + fun_l25_n951 +end + +def fun_l24_n548() + fun_l25_n213 +end + +def fun_l24_n549() + fun_l25_n148 +end + +def fun_l24_n550() + fun_l25_n479 +end + +def fun_l24_n551() + fun_l25_n130 +end + +def fun_l24_n552() + fun_l25_n823 +end + +def fun_l24_n553() + fun_l25_n507 +end + +def fun_l24_n554() + fun_l25_n227 +end + +def fun_l24_n555() + fun_l25_n811 +end + +def fun_l24_n556() + fun_l25_n203 +end + +def fun_l24_n557() + fun_l25_n626 +end + +def fun_l24_n558() + fun_l25_n965 +end + +def fun_l24_n559() + fun_l25_n871 +end + +def fun_l24_n560() + fun_l25_n752 +end + +def fun_l24_n561() + fun_l25_n89 +end + +def fun_l24_n562() + fun_l25_n970 +end + +def fun_l24_n563() + fun_l25_n956 +end + +def fun_l24_n564() + fun_l25_n871 +end + +def fun_l24_n565() + fun_l25_n610 +end + +def fun_l24_n566() + fun_l25_n43 +end + +def fun_l24_n567() + fun_l25_n176 +end + +def fun_l24_n568() + fun_l25_n10 +end + +def fun_l24_n569() + fun_l25_n798 +end + +def fun_l24_n570() + fun_l25_n141 +end + +def fun_l24_n571() + fun_l25_n205 +end + +def fun_l24_n572() + fun_l25_n870 +end + +def fun_l24_n573() + fun_l25_n324 +end + +def fun_l24_n574() + fun_l25_n765 +end + +def fun_l24_n575() + fun_l25_n775 +end + +def fun_l24_n576() + fun_l25_n232 +end + +def fun_l24_n577() + fun_l25_n36 +end + +def fun_l24_n578() + fun_l25_n260 +end + +def fun_l24_n579() + fun_l25_n84 +end + +def fun_l24_n580() + fun_l25_n279 +end + +def fun_l24_n581() + fun_l25_n292 +end + +def fun_l24_n582() + fun_l25_n472 +end + +def fun_l24_n583() + fun_l25_n630 +end + +def fun_l24_n584() + fun_l25_n695 +end + +def fun_l24_n585() + fun_l25_n974 +end + +def fun_l24_n586() + fun_l25_n263 +end + +def fun_l24_n587() + fun_l25_n959 +end + +def fun_l24_n588() + fun_l25_n76 +end + +def fun_l24_n589() + fun_l25_n897 +end + +def fun_l24_n590() + fun_l25_n416 +end + +def fun_l24_n591() + fun_l25_n225 +end + +def fun_l24_n592() + fun_l25_n194 +end + +def fun_l24_n593() + fun_l25_n338 +end + +def fun_l24_n594() + fun_l25_n565 +end + +def fun_l24_n595() + fun_l25_n301 +end + +def fun_l24_n596() + fun_l25_n101 +end + +def fun_l24_n597() + fun_l25_n876 +end + +def fun_l24_n598() + fun_l25_n127 +end + +def fun_l24_n599() + fun_l25_n608 +end + +def fun_l24_n600() + fun_l25_n45 +end + +def fun_l24_n601() + fun_l25_n833 +end + +def fun_l24_n602() + fun_l25_n43 +end + +def fun_l24_n603() + fun_l25_n136 +end + +def fun_l24_n604() + fun_l25_n916 +end + +def fun_l24_n605() + fun_l25_n686 +end + +def fun_l24_n606() + fun_l25_n574 +end + +def fun_l24_n607() + fun_l25_n164 +end + +def fun_l24_n608() + fun_l25_n983 +end + +def fun_l24_n609() + fun_l25_n883 +end + +def fun_l24_n610() + fun_l25_n957 +end + +def fun_l24_n611() + fun_l25_n592 +end + +def fun_l24_n612() + fun_l25_n684 +end + +def fun_l24_n613() + fun_l25_n333 +end + +def fun_l24_n614() + fun_l25_n465 +end + +def fun_l24_n615() + fun_l25_n297 +end + +def fun_l24_n616() + fun_l25_n738 +end + +def fun_l24_n617() + fun_l25_n953 +end + +def fun_l24_n618() + fun_l25_n27 +end + +def fun_l24_n619() + fun_l25_n577 +end + +def fun_l24_n620() + fun_l25_n595 +end + +def fun_l24_n621() + fun_l25_n408 +end + +def fun_l24_n622() + fun_l25_n161 +end + +def fun_l24_n623() + fun_l25_n263 +end + +def fun_l24_n624() + fun_l25_n557 +end + +def fun_l24_n625() + fun_l25_n708 +end + +def fun_l24_n626() + fun_l25_n879 +end + +def fun_l24_n627() + fun_l25_n235 +end + +def fun_l24_n628() + fun_l25_n551 +end + +def fun_l24_n629() + fun_l25_n46 +end + +def fun_l24_n630() + fun_l25_n718 +end + +def fun_l24_n631() + fun_l25_n419 +end + +def fun_l24_n632() + fun_l25_n370 +end + +def fun_l24_n633() + fun_l25_n322 +end + +def fun_l24_n634() + fun_l25_n912 +end + +def fun_l24_n635() + fun_l25_n445 +end + +def fun_l24_n636() + fun_l25_n850 +end + +def fun_l24_n637() + fun_l25_n233 +end + +def fun_l24_n638() + fun_l25_n230 +end + +def fun_l24_n639() + fun_l25_n188 +end + +def fun_l24_n640() + fun_l25_n267 +end + +def fun_l24_n641() + fun_l25_n840 +end + +def fun_l24_n642() + fun_l25_n786 +end + +def fun_l24_n643() + fun_l25_n737 +end + +def fun_l24_n644() + fun_l25_n725 +end + +def fun_l24_n645() + fun_l25_n200 +end + +def fun_l24_n646() + fun_l25_n173 +end + +def fun_l24_n647() + fun_l25_n50 +end + +def fun_l24_n648() + fun_l25_n460 +end + +def fun_l24_n649() + fun_l25_n959 +end + +def fun_l24_n650() + fun_l25_n397 +end + +def fun_l24_n651() + fun_l25_n108 +end + +def fun_l24_n652() + fun_l25_n426 +end + +def fun_l24_n653() + fun_l25_n208 +end + +def fun_l24_n654() + fun_l25_n989 +end + +def fun_l24_n655() + fun_l25_n73 +end + +def fun_l24_n656() + fun_l25_n710 +end + +def fun_l24_n657() + fun_l25_n707 +end + +def fun_l24_n658() + fun_l25_n276 +end + +def fun_l24_n659() + fun_l25_n920 +end + +def fun_l24_n660() + fun_l25_n735 +end + +def fun_l24_n661() + fun_l25_n937 +end + +def fun_l24_n662() + fun_l25_n544 +end + +def fun_l24_n663() + fun_l25_n663 +end + +def fun_l24_n664() + fun_l25_n571 +end + +def fun_l24_n665() + fun_l25_n682 +end + +def fun_l24_n666() + fun_l25_n79 +end + +def fun_l24_n667() + fun_l25_n759 +end + +def fun_l24_n668() + fun_l25_n128 +end + +def fun_l24_n669() + fun_l25_n895 +end + +def fun_l24_n670() + fun_l25_n258 +end + +def fun_l24_n671() + fun_l25_n12 +end + +def fun_l24_n672() + fun_l25_n397 +end + +def fun_l24_n673() + fun_l25_n967 +end + +def fun_l24_n674() + fun_l25_n960 +end + +def fun_l24_n675() + fun_l25_n867 +end + +def fun_l24_n676() + fun_l25_n438 +end + +def fun_l24_n677() + fun_l25_n692 +end + +def fun_l24_n678() + fun_l25_n161 +end + +def fun_l24_n679() + fun_l25_n122 +end + +def fun_l24_n680() + fun_l25_n344 +end + +def fun_l24_n681() + fun_l25_n285 +end + +def fun_l24_n682() + fun_l25_n838 +end + +def fun_l24_n683() + fun_l25_n80 +end + +def fun_l24_n684() + fun_l25_n81 +end + +def fun_l24_n685() + fun_l25_n811 +end + +def fun_l24_n686() + fun_l25_n998 +end + +def fun_l24_n687() + fun_l25_n739 +end + +def fun_l24_n688() + fun_l25_n660 +end + +def fun_l24_n689() + fun_l25_n965 +end + +def fun_l24_n690() + fun_l25_n124 +end + +def fun_l24_n691() + fun_l25_n879 +end + +def fun_l24_n692() + fun_l25_n669 +end + +def fun_l24_n693() + fun_l25_n428 +end + +def fun_l24_n694() + fun_l25_n143 +end + +def fun_l24_n695() + fun_l25_n103 +end + +def fun_l24_n696() + fun_l25_n738 +end + +def fun_l24_n697() + fun_l25_n188 +end + +def fun_l24_n698() + fun_l25_n657 +end + +def fun_l24_n699() + fun_l25_n258 +end + +def fun_l24_n700() + fun_l25_n878 +end + +def fun_l24_n701() + fun_l25_n927 +end + +def fun_l24_n702() + fun_l25_n9 +end + +def fun_l24_n703() + fun_l25_n41 +end + +def fun_l24_n704() + fun_l25_n925 +end + +def fun_l24_n705() + fun_l25_n473 +end + +def fun_l24_n706() + fun_l25_n321 +end + +def fun_l24_n707() + fun_l25_n778 +end + +def fun_l24_n708() + fun_l25_n951 +end + +def fun_l24_n709() + fun_l25_n91 +end + +def fun_l24_n710() + fun_l25_n297 +end + +def fun_l24_n711() + fun_l25_n185 +end + +def fun_l24_n712() + fun_l25_n822 +end + +def fun_l24_n713() + fun_l25_n817 +end + +def fun_l24_n714() + fun_l25_n558 +end + +def fun_l24_n715() + fun_l25_n15 +end + +def fun_l24_n716() + fun_l25_n106 +end + +def fun_l24_n717() + fun_l25_n173 +end + +def fun_l24_n718() + fun_l25_n565 +end + +def fun_l24_n719() + fun_l25_n832 +end + +def fun_l24_n720() + fun_l25_n798 +end + +def fun_l24_n721() + fun_l25_n333 +end + +def fun_l24_n722() + fun_l25_n631 +end + +def fun_l24_n723() + fun_l25_n135 +end + +def fun_l24_n724() + fun_l25_n826 +end + +def fun_l24_n725() + fun_l25_n878 +end + +def fun_l24_n726() + fun_l25_n612 +end + +def fun_l24_n727() + fun_l25_n302 +end + +def fun_l24_n728() + fun_l25_n636 +end + +def fun_l24_n729() + fun_l25_n308 +end + +def fun_l24_n730() + fun_l25_n633 +end + +def fun_l24_n731() + fun_l25_n596 +end + +def fun_l24_n732() + fun_l25_n948 +end + +def fun_l24_n733() + fun_l25_n93 +end + +def fun_l24_n734() + fun_l25_n175 +end + +def fun_l24_n735() + fun_l25_n590 +end + +def fun_l24_n736() + fun_l25_n168 +end + +def fun_l24_n737() + fun_l25_n861 +end + +def fun_l24_n738() + fun_l25_n890 +end + +def fun_l24_n739() + fun_l25_n355 +end + +def fun_l24_n740() + fun_l25_n166 +end + +def fun_l24_n741() + fun_l25_n397 +end + +def fun_l24_n742() + fun_l25_n665 +end + +def fun_l24_n743() + fun_l25_n436 +end + +def fun_l24_n744() + fun_l25_n274 +end + +def fun_l24_n745() + fun_l25_n44 +end + +def fun_l24_n746() + fun_l25_n765 +end + +def fun_l24_n747() + fun_l25_n916 +end + +def fun_l24_n748() + fun_l25_n735 +end + +def fun_l24_n749() + fun_l25_n745 +end + +def fun_l24_n750() + fun_l25_n813 +end + +def fun_l24_n751() + fun_l25_n26 +end + +def fun_l24_n752() + fun_l25_n223 +end + +def fun_l24_n753() + fun_l25_n256 +end + +def fun_l24_n754() + fun_l25_n852 +end + +def fun_l24_n755() + fun_l25_n400 +end + +def fun_l24_n756() + fun_l25_n973 +end + +def fun_l24_n757() + fun_l25_n900 +end + +def fun_l24_n758() + fun_l25_n884 +end + +def fun_l24_n759() + fun_l25_n171 +end + +def fun_l24_n760() + fun_l25_n155 +end + +def fun_l24_n761() + fun_l25_n310 +end + +def fun_l24_n762() + fun_l25_n706 +end + +def fun_l24_n763() + fun_l25_n324 +end + +def fun_l24_n764() + fun_l25_n260 +end + +def fun_l24_n765() + fun_l25_n247 +end + +def fun_l24_n766() + fun_l25_n750 +end + +def fun_l24_n767() + fun_l25_n236 +end + +def fun_l24_n768() + fun_l25_n956 +end + +def fun_l24_n769() + fun_l25_n736 +end + +def fun_l24_n770() + fun_l25_n510 +end + +def fun_l24_n771() + fun_l25_n101 +end + +def fun_l24_n772() + fun_l25_n189 +end + +def fun_l24_n773() + fun_l25_n391 +end + +def fun_l24_n774() + fun_l25_n212 +end + +def fun_l24_n775() + fun_l25_n500 +end + +def fun_l24_n776() + fun_l25_n95 +end + +def fun_l24_n777() + fun_l25_n30 +end + +def fun_l24_n778() + fun_l25_n99 +end + +def fun_l24_n779() + fun_l25_n427 +end + +def fun_l24_n780() + fun_l25_n659 +end + +def fun_l24_n781() + fun_l25_n665 +end + +def fun_l24_n782() + fun_l25_n992 +end + +def fun_l24_n783() + fun_l25_n180 +end + +def fun_l24_n784() + fun_l25_n546 +end + +def fun_l24_n785() + fun_l25_n618 +end + +def fun_l24_n786() + fun_l25_n615 +end + +def fun_l24_n787() + fun_l25_n126 +end + +def fun_l24_n788() + fun_l25_n383 +end + +def fun_l24_n789() + fun_l25_n429 +end + +def fun_l24_n790() + fun_l25_n95 +end + +def fun_l24_n791() + fun_l25_n47 +end + +def fun_l24_n792() + fun_l25_n582 +end + +def fun_l24_n793() + fun_l25_n209 +end + +def fun_l24_n794() + fun_l25_n925 +end + +def fun_l24_n795() + fun_l25_n746 +end + +def fun_l24_n796() + fun_l25_n330 +end + +def fun_l24_n797() + fun_l25_n964 +end + +def fun_l24_n798() + fun_l25_n241 +end + +def fun_l24_n799() + fun_l25_n136 +end + +def fun_l24_n800() + fun_l25_n10 +end + +def fun_l24_n801() + fun_l25_n255 +end + +def fun_l24_n802() + fun_l25_n481 +end + +def fun_l24_n803() + fun_l25_n697 +end + +def fun_l24_n804() + fun_l25_n275 +end + +def fun_l24_n805() + fun_l25_n389 +end + +def fun_l24_n806() + fun_l25_n540 +end + +def fun_l24_n807() + fun_l25_n182 +end + +def fun_l24_n808() + fun_l25_n894 +end + +def fun_l24_n809() + fun_l25_n339 +end + +def fun_l24_n810() + fun_l25_n409 +end + +def fun_l24_n811() + fun_l25_n106 +end + +def fun_l24_n812() + fun_l25_n297 +end + +def fun_l24_n813() + fun_l25_n477 +end + +def fun_l24_n814() + fun_l25_n431 +end + +def fun_l24_n815() + fun_l25_n507 +end + +def fun_l24_n816() + fun_l25_n311 +end + +def fun_l24_n817() + fun_l25_n350 +end + +def fun_l24_n818() + fun_l25_n486 +end + +def fun_l24_n819() + fun_l25_n872 +end + +def fun_l24_n820() + fun_l25_n21 +end + +def fun_l24_n821() + fun_l25_n108 +end + +def fun_l24_n822() + fun_l25_n383 +end + +def fun_l24_n823() + fun_l25_n389 +end + +def fun_l24_n824() + fun_l25_n901 +end + +def fun_l24_n825() + fun_l25_n94 +end + +def fun_l24_n826() + fun_l25_n122 +end + +def fun_l24_n827() + fun_l25_n399 +end + +def fun_l24_n828() + fun_l25_n424 +end + +def fun_l24_n829() + fun_l25_n59 +end + +def fun_l24_n830() + fun_l25_n477 +end + +def fun_l24_n831() + fun_l25_n766 +end + +def fun_l24_n832() + fun_l25_n340 +end + +def fun_l24_n833() + fun_l25_n925 +end + +def fun_l24_n834() + fun_l25_n993 +end + +def fun_l24_n835() + fun_l25_n444 +end + +def fun_l24_n836() + fun_l25_n580 +end + +def fun_l24_n837() + fun_l25_n997 +end + +def fun_l24_n838() + fun_l25_n651 +end + +def fun_l24_n839() + fun_l25_n991 +end + +def fun_l24_n840() + fun_l25_n850 +end + +def fun_l24_n841() + fun_l25_n563 +end + +def fun_l24_n842() + fun_l25_n175 +end + +def fun_l24_n843() + fun_l25_n77 +end + +def fun_l24_n844() + fun_l25_n300 +end + +def fun_l24_n845() + fun_l25_n510 +end + +def fun_l24_n846() + fun_l25_n871 +end + +def fun_l24_n847() + fun_l25_n437 +end + +def fun_l24_n848() + fun_l25_n609 +end + +def fun_l24_n849() + fun_l25_n505 +end + +def fun_l24_n850() + fun_l25_n989 +end + +def fun_l24_n851() + fun_l25_n595 +end + +def fun_l24_n852() + fun_l25_n917 +end + +def fun_l24_n853() + fun_l25_n39 +end + +def fun_l24_n854() + fun_l25_n795 +end + +def fun_l24_n855() + fun_l25_n242 +end + +def fun_l24_n856() + fun_l25_n220 +end + +def fun_l24_n857() + fun_l25_n537 +end + +def fun_l24_n858() + fun_l25_n790 +end + +def fun_l24_n859() + fun_l25_n160 +end + +def fun_l24_n860() + fun_l25_n685 +end + +def fun_l24_n861() + fun_l25_n665 +end + +def fun_l24_n862() + fun_l25_n448 +end + +def fun_l24_n863() + fun_l25_n75 +end + +def fun_l24_n864() + fun_l25_n293 +end + +def fun_l24_n865() + fun_l25_n721 +end + +def fun_l24_n866() + fun_l25_n113 +end + +def fun_l24_n867() + fun_l25_n565 +end + +def fun_l24_n868() + fun_l25_n95 +end + +def fun_l24_n869() + fun_l25_n373 +end + +def fun_l24_n870() + fun_l25_n351 +end + +def fun_l24_n871() + fun_l25_n151 +end + +def fun_l24_n872() + fun_l25_n489 +end + +def fun_l24_n873() + fun_l25_n882 +end + +def fun_l24_n874() + fun_l25_n415 +end + +def fun_l24_n875() + fun_l25_n237 +end + +def fun_l24_n876() + fun_l25_n59 +end + +def fun_l24_n877() + fun_l25_n747 +end + +def fun_l24_n878() + fun_l25_n897 +end + +def fun_l24_n879() + fun_l25_n746 +end + +def fun_l24_n880() + fun_l25_n695 +end + +def fun_l24_n881() + fun_l25_n924 +end + +def fun_l24_n882() + fun_l25_n933 +end + +def fun_l24_n883() + fun_l25_n702 +end + +def fun_l24_n884() + fun_l25_n107 +end + +def fun_l24_n885() + fun_l25_n333 +end + +def fun_l24_n886() + fun_l25_n536 +end + +def fun_l24_n887() + fun_l25_n908 +end + +def fun_l24_n888() + fun_l25_n84 +end + +def fun_l24_n889() + fun_l25_n622 +end + +def fun_l24_n890() + fun_l25_n466 +end + +def fun_l24_n891() + fun_l25_n344 +end + +def fun_l24_n892() + fun_l25_n271 +end + +def fun_l24_n893() + fun_l25_n461 +end + +def fun_l24_n894() + fun_l25_n297 +end + +def fun_l24_n895() + fun_l25_n415 +end + +def fun_l24_n896() + fun_l25_n419 +end + +def fun_l24_n897() + fun_l25_n374 +end + +def fun_l24_n898() + fun_l25_n976 +end + +def fun_l24_n899() + fun_l25_n888 +end + +def fun_l24_n900() + fun_l25_n540 +end + +def fun_l24_n901() + fun_l25_n491 +end + +def fun_l24_n902() + fun_l25_n178 +end + +def fun_l24_n903() + fun_l25_n197 +end + +def fun_l24_n904() + fun_l25_n474 +end + +def fun_l24_n905() + fun_l25_n371 +end + +def fun_l24_n906() + fun_l25_n960 +end + +def fun_l24_n907() + fun_l25_n808 +end + +def fun_l24_n908() + fun_l25_n89 +end + +def fun_l24_n909() + fun_l25_n892 +end + +def fun_l24_n910() + fun_l25_n457 +end + +def fun_l24_n911() + fun_l25_n105 +end + +def fun_l24_n912() + fun_l25_n787 +end + +def fun_l24_n913() + fun_l25_n554 +end + +def fun_l24_n914() + fun_l25_n615 +end + +def fun_l24_n915() + fun_l25_n61 +end + +def fun_l24_n916() + fun_l25_n162 +end + +def fun_l24_n917() + fun_l25_n354 +end + +def fun_l24_n918() + fun_l25_n388 +end + +def fun_l24_n919() + fun_l25_n660 +end + +def fun_l24_n920() + fun_l25_n705 +end + +def fun_l24_n921() + fun_l25_n990 +end + +def fun_l24_n922() + fun_l25_n725 +end + +def fun_l24_n923() + fun_l25_n800 +end + +def fun_l24_n924() + fun_l25_n368 +end + +def fun_l24_n925() + fun_l25_n986 +end + +def fun_l24_n926() + fun_l25_n509 +end + +def fun_l24_n927() + fun_l25_n706 +end + +def fun_l24_n928() + fun_l25_n777 +end + +def fun_l24_n929() + fun_l25_n223 +end + +def fun_l24_n930() + fun_l25_n972 +end + +def fun_l24_n931() + fun_l25_n868 +end + +def fun_l24_n932() + fun_l25_n170 +end + +def fun_l24_n933() + fun_l25_n176 +end + +def fun_l24_n934() + fun_l25_n667 +end + +def fun_l24_n935() + fun_l25_n312 +end + +def fun_l24_n936() + fun_l25_n680 +end + +def fun_l24_n937() + fun_l25_n183 +end + +def fun_l24_n938() + fun_l25_n880 +end + +def fun_l24_n939() + fun_l25_n634 +end + +def fun_l24_n940() + fun_l25_n716 +end + +def fun_l24_n941() + fun_l25_n16 +end + +def fun_l24_n942() + fun_l25_n227 +end + +def fun_l24_n943() + fun_l25_n423 +end + +def fun_l24_n944() + fun_l25_n268 +end + +def fun_l24_n945() + fun_l25_n947 +end + +def fun_l24_n946() + fun_l25_n675 +end + +def fun_l24_n947() + fun_l25_n575 +end + +def fun_l24_n948() + fun_l25_n280 +end + +def fun_l24_n949() + fun_l25_n698 +end + +def fun_l24_n950() + fun_l25_n769 +end + +def fun_l24_n951() + fun_l25_n225 +end + +def fun_l24_n952() + fun_l25_n171 +end + +def fun_l24_n953() + fun_l25_n464 +end + +def fun_l24_n954() + fun_l25_n662 +end + +def fun_l24_n955() + fun_l25_n621 +end + +def fun_l24_n956() + fun_l25_n391 +end + +def fun_l24_n957() + fun_l25_n340 +end + +def fun_l24_n958() + fun_l25_n634 +end + +def fun_l24_n959() + fun_l25_n31 +end + +def fun_l24_n960() + fun_l25_n132 +end + +def fun_l24_n961() + fun_l25_n867 +end + +def fun_l24_n962() + fun_l25_n946 +end + +def fun_l24_n963() + fun_l25_n339 +end + +def fun_l24_n964() + fun_l25_n497 +end + +def fun_l24_n965() + fun_l25_n289 +end + +def fun_l24_n966() + fun_l25_n842 +end + +def fun_l24_n967() + fun_l25_n583 +end + +def fun_l24_n968() + fun_l25_n52 +end + +def fun_l24_n969() + fun_l25_n177 +end + +def fun_l24_n970() + fun_l25_n935 +end + +def fun_l24_n971() + fun_l25_n963 +end + +def fun_l24_n972() + fun_l25_n779 +end + +def fun_l24_n973() + fun_l25_n457 +end + +def fun_l24_n974() + fun_l25_n480 +end + +def fun_l24_n975() + fun_l25_n333 +end + +def fun_l24_n976() + fun_l25_n191 +end + +def fun_l24_n977() + fun_l25_n670 +end + +def fun_l24_n978() + fun_l25_n822 +end + +def fun_l24_n979() + fun_l25_n302 +end + +def fun_l24_n980() + fun_l25_n272 +end + +def fun_l24_n981() + fun_l25_n467 +end + +def fun_l24_n982() + fun_l25_n209 +end + +def fun_l24_n983() + fun_l25_n603 +end + +def fun_l24_n984() + fun_l25_n134 +end + +def fun_l24_n985() + fun_l25_n639 +end + +def fun_l24_n986() + fun_l25_n843 +end + +def fun_l24_n987() + fun_l25_n576 +end + +def fun_l24_n988() + fun_l25_n7 +end + +def fun_l24_n989() + fun_l25_n93 +end + +def fun_l24_n990() + fun_l25_n351 +end + +def fun_l24_n991() + fun_l25_n932 +end + +def fun_l24_n992() + fun_l25_n987 +end + +def fun_l24_n993() + fun_l25_n796 +end + +def fun_l24_n994() + fun_l25_n202 +end + +def fun_l24_n995() + fun_l25_n125 +end + +def fun_l24_n996() + fun_l25_n404 +end + +def fun_l24_n997() + fun_l25_n750 +end + +def fun_l24_n998() + fun_l25_n50 +end + +def fun_l24_n999() + fun_l25_n71 +end + +def fun_l25_n0() + fun_l26_n73 +end + +def fun_l25_n1() + fun_l26_n572 +end + +def fun_l25_n2() + fun_l26_n639 +end + +def fun_l25_n3() + fun_l26_n292 +end + +def fun_l25_n4() + fun_l26_n865 +end + +def fun_l25_n5() + fun_l26_n618 +end + +def fun_l25_n6() + fun_l26_n84 +end + +def fun_l25_n7() + fun_l26_n351 +end + +def fun_l25_n8() + fun_l26_n534 +end + +def fun_l25_n9() + fun_l26_n483 +end + +def fun_l25_n10() + fun_l26_n589 +end + +def fun_l25_n11() + fun_l26_n450 +end + +def fun_l25_n12() + fun_l26_n948 +end + +def fun_l25_n13() + fun_l26_n819 +end + +def fun_l25_n14() + fun_l26_n845 +end + +def fun_l25_n15() + fun_l26_n544 +end + +def fun_l25_n16() + fun_l26_n254 +end + +def fun_l25_n17() + fun_l26_n71 +end + +def fun_l25_n18() + fun_l26_n640 +end + +def fun_l25_n19() + fun_l26_n885 +end + +def fun_l25_n20() + fun_l26_n725 +end + +def fun_l25_n21() + fun_l26_n798 +end + +def fun_l25_n22() + fun_l26_n838 +end + +def fun_l25_n23() + fun_l26_n835 +end + +def fun_l25_n24() + fun_l26_n170 +end + +def fun_l25_n25() + fun_l26_n3 +end + +def fun_l25_n26() + fun_l26_n910 +end + +def fun_l25_n27() + fun_l26_n575 +end + +def fun_l25_n28() + fun_l26_n834 +end + +def fun_l25_n29() + fun_l26_n767 +end + +def fun_l25_n30() + fun_l26_n375 +end + +def fun_l25_n31() + fun_l26_n781 +end + +def fun_l25_n32() + fun_l26_n173 +end + +def fun_l25_n33() + fun_l26_n382 +end + +def fun_l25_n34() + fun_l26_n974 +end + +def fun_l25_n35() + fun_l26_n14 +end + +def fun_l25_n36() + fun_l26_n730 +end + +def fun_l25_n37() + fun_l26_n253 +end + +def fun_l25_n38() + fun_l26_n405 +end + +def fun_l25_n39() + fun_l26_n903 +end + +def fun_l25_n40() + fun_l26_n621 +end + +def fun_l25_n41() + fun_l26_n309 +end + +def fun_l25_n42() + fun_l26_n572 +end + +def fun_l25_n43() + fun_l26_n857 +end + +def fun_l25_n44() + fun_l26_n769 +end + +def fun_l25_n45() + fun_l26_n371 +end + +def fun_l25_n46() + fun_l26_n866 +end + +def fun_l25_n47() + fun_l26_n279 +end + +def fun_l25_n48() + fun_l26_n360 +end + +def fun_l25_n49() + fun_l26_n80 +end + +def fun_l25_n50() + fun_l26_n101 +end + +def fun_l25_n51() + fun_l26_n32 +end + +def fun_l25_n52() + fun_l26_n815 +end + +def fun_l25_n53() + fun_l26_n599 +end + +def fun_l25_n54() + fun_l26_n999 +end + +def fun_l25_n55() + fun_l26_n264 +end + +def fun_l25_n56() + fun_l26_n941 +end + +def fun_l25_n57() + fun_l26_n735 +end + +def fun_l25_n58() + fun_l26_n563 +end + +def fun_l25_n59() + fun_l26_n439 +end + +def fun_l25_n60() + fun_l26_n326 +end + +def fun_l25_n61() + fun_l26_n577 +end + +def fun_l25_n62() + fun_l26_n174 +end + +def fun_l25_n63() + fun_l26_n839 +end + +def fun_l25_n64() + fun_l26_n238 +end + +def fun_l25_n65() + fun_l26_n953 +end + +def fun_l25_n66() + fun_l26_n940 +end + +def fun_l25_n67() + fun_l26_n349 +end + +def fun_l25_n68() + fun_l26_n675 +end + +def fun_l25_n69() + fun_l26_n376 +end + +def fun_l25_n70() + fun_l26_n653 +end + +def fun_l25_n71() + fun_l26_n377 +end + +def fun_l25_n72() + fun_l26_n977 +end + +def fun_l25_n73() + fun_l26_n487 +end + +def fun_l25_n74() + fun_l26_n722 +end + +def fun_l25_n75() + fun_l26_n18 +end + +def fun_l25_n76() + fun_l26_n539 +end + +def fun_l25_n77() + fun_l26_n825 +end + +def fun_l25_n78() + fun_l26_n990 +end + +def fun_l25_n79() + fun_l26_n554 +end + +def fun_l25_n80() + fun_l26_n715 +end + +def fun_l25_n81() + fun_l26_n67 +end + +def fun_l25_n82() + fun_l26_n143 +end + +def fun_l25_n83() + fun_l26_n99 +end + +def fun_l25_n84() + fun_l26_n703 +end + +def fun_l25_n85() + fun_l26_n277 +end + +def fun_l25_n86() + fun_l26_n283 +end + +def fun_l25_n87() + fun_l26_n74 +end + +def fun_l25_n88() + fun_l26_n680 +end + +def fun_l25_n89() + fun_l26_n269 +end + +def fun_l25_n90() + fun_l26_n255 +end + +def fun_l25_n91() + fun_l26_n974 +end + +def fun_l25_n92() + fun_l26_n109 +end + +def fun_l25_n93() + fun_l26_n672 +end + +def fun_l25_n94() + fun_l26_n418 +end + +def fun_l25_n95() + fun_l26_n75 +end + +def fun_l25_n96() + fun_l26_n500 +end + +def fun_l25_n97() + fun_l26_n286 +end + +def fun_l25_n98() + fun_l26_n890 +end + +def fun_l25_n99() + fun_l26_n161 +end + +def fun_l25_n100() + fun_l26_n16 +end + +def fun_l25_n101() + fun_l26_n742 +end + +def fun_l25_n102() + fun_l26_n592 +end + +def fun_l25_n103() + fun_l26_n600 +end + +def fun_l25_n104() + fun_l26_n665 +end + +def fun_l25_n105() + fun_l26_n721 +end + +def fun_l25_n106() + fun_l26_n461 +end + +def fun_l25_n107() + fun_l26_n818 +end + +def fun_l25_n108() + fun_l26_n132 +end + +def fun_l25_n109() + fun_l26_n245 +end + +def fun_l25_n110() + fun_l26_n511 +end + +def fun_l25_n111() + fun_l26_n386 +end + +def fun_l25_n112() + fun_l26_n77 +end + +def fun_l25_n113() + fun_l26_n329 +end + +def fun_l25_n114() + fun_l26_n157 +end + +def fun_l25_n115() + fun_l26_n220 +end + +def fun_l25_n116() + fun_l26_n880 +end + +def fun_l25_n117() + fun_l26_n799 +end + +def fun_l25_n118() + fun_l26_n879 +end + +def fun_l25_n119() + fun_l26_n639 +end + +def fun_l25_n120() + fun_l26_n257 +end + +def fun_l25_n121() + fun_l26_n921 +end + +def fun_l25_n122() + fun_l26_n115 +end + +def fun_l25_n123() + fun_l26_n569 +end + +def fun_l25_n124() + fun_l26_n504 +end + +def fun_l25_n125() + fun_l26_n962 +end + +def fun_l25_n126() + fun_l26_n854 +end + +def fun_l25_n127() + fun_l26_n619 +end + +def fun_l25_n128() + fun_l26_n657 +end + +def fun_l25_n129() + fun_l26_n389 +end + +def fun_l25_n130() + fun_l26_n515 +end + +def fun_l25_n131() + fun_l26_n253 +end + +def fun_l25_n132() + fun_l26_n311 +end + +def fun_l25_n133() + fun_l26_n587 +end + +def fun_l25_n134() + fun_l26_n802 +end + +def fun_l25_n135() + fun_l26_n29 +end + +def fun_l25_n136() + fun_l26_n324 +end + +def fun_l25_n137() + fun_l26_n892 +end + +def fun_l25_n138() + fun_l26_n871 +end + +def fun_l25_n139() + fun_l26_n748 +end + +def fun_l25_n140() + fun_l26_n7 +end + +def fun_l25_n141() + fun_l26_n77 +end + +def fun_l25_n142() + fun_l26_n948 +end + +def fun_l25_n143() + fun_l26_n624 +end + +def fun_l25_n144() + fun_l26_n908 +end + +def fun_l25_n145() + fun_l26_n362 +end + +def fun_l25_n146() + fun_l26_n653 +end + +def fun_l25_n147() + fun_l26_n806 +end + +def fun_l25_n148() + fun_l26_n959 +end + +def fun_l25_n149() + fun_l26_n677 +end + +def fun_l25_n150() + fun_l26_n697 +end + +def fun_l25_n151() + fun_l26_n12 +end + +def fun_l25_n152() + fun_l26_n67 +end + +def fun_l25_n153() + fun_l26_n451 +end + +def fun_l25_n154() + fun_l26_n887 +end + +def fun_l25_n155() + fun_l26_n908 +end + +def fun_l25_n156() + fun_l26_n382 +end + +def fun_l25_n157() + fun_l26_n977 +end + +def fun_l25_n158() + fun_l26_n62 +end + +def fun_l25_n159() + fun_l26_n307 +end + +def fun_l25_n160() + fun_l26_n583 +end + +def fun_l25_n161() + fun_l26_n291 +end + +def fun_l25_n162() + fun_l26_n736 +end + +def fun_l25_n163() + fun_l26_n954 +end + +def fun_l25_n164() + fun_l26_n414 +end + +def fun_l25_n165() + fun_l26_n945 +end + +def fun_l25_n166() + fun_l26_n947 +end + +def fun_l25_n167() + fun_l26_n639 +end + +def fun_l25_n168() + fun_l26_n875 +end + +def fun_l25_n169() + fun_l26_n994 +end + +def fun_l25_n170() + fun_l26_n855 +end + +def fun_l25_n171() + fun_l26_n539 +end + +def fun_l25_n172() + fun_l26_n108 +end + +def fun_l25_n173() + fun_l26_n806 +end + +def fun_l25_n174() + fun_l26_n838 +end + +def fun_l25_n175() + fun_l26_n688 +end + +def fun_l25_n176() + fun_l26_n696 +end + +def fun_l25_n177() + fun_l26_n979 +end + +def fun_l25_n178() + fun_l26_n261 +end + +def fun_l25_n179() + fun_l26_n266 +end + +def fun_l25_n180() + fun_l26_n907 +end + +def fun_l25_n181() + fun_l26_n622 +end + +def fun_l25_n182() + fun_l26_n42 +end + +def fun_l25_n183() + fun_l26_n840 +end + +def fun_l25_n184() + fun_l26_n125 +end + +def fun_l25_n185() + fun_l26_n402 +end + +def fun_l25_n186() + fun_l26_n401 +end + +def fun_l25_n187() + fun_l26_n410 +end + +def fun_l25_n188() + fun_l26_n552 +end + +def fun_l25_n189() + fun_l26_n528 +end + +def fun_l25_n190() + fun_l26_n171 +end + +def fun_l25_n191() + fun_l26_n787 +end + +def fun_l25_n192() + fun_l26_n453 +end + +def fun_l25_n193() + fun_l26_n107 +end + +def fun_l25_n194() + fun_l26_n171 +end + +def fun_l25_n195() + fun_l26_n159 +end + +def fun_l25_n196() + fun_l26_n801 +end + +def fun_l25_n197() + fun_l26_n569 +end + +def fun_l25_n198() + fun_l26_n899 +end + +def fun_l25_n199() + fun_l26_n434 +end + +def fun_l25_n200() + fun_l26_n943 +end + +def fun_l25_n201() + fun_l26_n455 +end + +def fun_l25_n202() + fun_l26_n239 +end + +def fun_l25_n203() + fun_l26_n892 +end + +def fun_l25_n204() + fun_l26_n332 +end + +def fun_l25_n205() + fun_l26_n95 +end + +def fun_l25_n206() + fun_l26_n735 +end + +def fun_l25_n207() + fun_l26_n517 +end + +def fun_l25_n208() + fun_l26_n41 +end + +def fun_l25_n209() + fun_l26_n827 +end + +def fun_l25_n210() + fun_l26_n557 +end + +def fun_l25_n211() + fun_l26_n184 +end + +def fun_l25_n212() + fun_l26_n123 +end + +def fun_l25_n213() + fun_l26_n476 +end + +def fun_l25_n214() + fun_l26_n346 +end + +def fun_l25_n215() + fun_l26_n720 +end + +def fun_l25_n216() + fun_l26_n905 +end + +def fun_l25_n217() + fun_l26_n911 +end + +def fun_l25_n218() + fun_l26_n317 +end + +def fun_l25_n219() + fun_l26_n930 +end + +def fun_l25_n220() + fun_l26_n539 +end + +def fun_l25_n221() + fun_l26_n173 +end + +def fun_l25_n222() + fun_l26_n441 +end + +def fun_l25_n223() + fun_l26_n345 +end + +def fun_l25_n224() + fun_l26_n463 +end + +def fun_l25_n225() + fun_l26_n568 +end + +def fun_l25_n226() + fun_l26_n783 +end + +def fun_l25_n227() + fun_l26_n359 +end + +def fun_l25_n228() + fun_l26_n523 +end + +def fun_l25_n229() + fun_l26_n895 +end + +def fun_l25_n230() + fun_l26_n159 +end + +def fun_l25_n231() + fun_l26_n259 +end + +def fun_l25_n232() + fun_l26_n373 +end + +def fun_l25_n233() + fun_l26_n471 +end + +def fun_l25_n234() + fun_l26_n448 +end + +def fun_l25_n235() + fun_l26_n139 +end + +def fun_l25_n236() + fun_l26_n795 +end + +def fun_l25_n237() + fun_l26_n492 +end + +def fun_l25_n238() + fun_l26_n292 +end + +def fun_l25_n239() + fun_l26_n253 +end + +def fun_l25_n240() + fun_l26_n870 +end + +def fun_l25_n241() + fun_l26_n504 +end + +def fun_l25_n242() + fun_l26_n315 +end + +def fun_l25_n243() + fun_l26_n542 +end + +def fun_l25_n244() + fun_l26_n368 +end + +def fun_l25_n245() + fun_l26_n954 +end + +def fun_l25_n246() + fun_l26_n589 +end + +def fun_l25_n247() + fun_l26_n102 +end + +def fun_l25_n248() + fun_l26_n839 +end + +def fun_l25_n249() + fun_l26_n493 +end + +def fun_l25_n250() + fun_l26_n90 +end + +def fun_l25_n251() + fun_l26_n974 +end + +def fun_l25_n252() + fun_l26_n878 +end + +def fun_l25_n253() + fun_l26_n205 +end + +def fun_l25_n254() + fun_l26_n485 +end + +def fun_l25_n255() + fun_l26_n976 +end + +def fun_l25_n256() + fun_l26_n397 +end + +def fun_l25_n257() + fun_l26_n593 +end + +def fun_l25_n258() + fun_l26_n925 +end + +def fun_l25_n259() + fun_l26_n223 +end + +def fun_l25_n260() + fun_l26_n491 +end + +def fun_l25_n261() + fun_l26_n441 +end + +def fun_l25_n262() + fun_l26_n472 +end + +def fun_l25_n263() + fun_l26_n357 +end + +def fun_l25_n264() + fun_l26_n90 +end + +def fun_l25_n265() + fun_l26_n124 +end + +def fun_l25_n266() + fun_l26_n607 +end + +def fun_l25_n267() + fun_l26_n484 +end + +def fun_l25_n268() + fun_l26_n448 +end + +def fun_l25_n269() + fun_l26_n456 +end + +def fun_l25_n270() + fun_l26_n108 +end + +def fun_l25_n271() + fun_l26_n268 +end + +def fun_l25_n272() + fun_l26_n250 +end + +def fun_l25_n273() + fun_l26_n354 +end + +def fun_l25_n274() + fun_l26_n234 +end + +def fun_l25_n275() + fun_l26_n833 +end + +def fun_l25_n276() + fun_l26_n404 +end + +def fun_l25_n277() + fun_l26_n296 +end + +def fun_l25_n278() + fun_l26_n640 +end + +def fun_l25_n279() + fun_l26_n633 +end + +def fun_l25_n280() + fun_l26_n119 +end + +def fun_l25_n281() + fun_l26_n272 +end + +def fun_l25_n282() + fun_l26_n4 +end + +def fun_l25_n283() + fun_l26_n217 +end + +def fun_l25_n284() + fun_l26_n923 +end + +def fun_l25_n285() + fun_l26_n911 +end + +def fun_l25_n286() + fun_l26_n332 +end + +def fun_l25_n287() + fun_l26_n83 +end + +def fun_l25_n288() + fun_l26_n396 +end + +def fun_l25_n289() + fun_l26_n423 +end + +def fun_l25_n290() + fun_l26_n182 +end + +def fun_l25_n291() + fun_l26_n69 +end + +def fun_l25_n292() + fun_l26_n348 +end + +def fun_l25_n293() + fun_l26_n85 +end + +def fun_l25_n294() + fun_l26_n727 +end + +def fun_l25_n295() + fun_l26_n488 +end + +def fun_l25_n296() + fun_l26_n629 +end + +def fun_l25_n297() + fun_l26_n92 +end + +def fun_l25_n298() + fun_l26_n737 +end + +def fun_l25_n299() + fun_l26_n68 +end + +def fun_l25_n300() + fun_l26_n148 +end + +def fun_l25_n301() + fun_l26_n292 +end + +def fun_l25_n302() + fun_l26_n836 +end + +def fun_l25_n303() + fun_l26_n992 +end + +def fun_l25_n304() + fun_l26_n894 +end + +def fun_l25_n305() + fun_l26_n850 +end + +def fun_l25_n306() + fun_l26_n63 +end + +def fun_l25_n307() + fun_l26_n321 +end + +def fun_l25_n308() + fun_l26_n497 +end + +def fun_l25_n309() + fun_l26_n757 +end + +def fun_l25_n310() + fun_l26_n331 +end + +def fun_l25_n311() + fun_l26_n522 +end + +def fun_l25_n312() + fun_l26_n815 +end + +def fun_l25_n313() + fun_l26_n545 +end + +def fun_l25_n314() + fun_l26_n78 +end + +def fun_l25_n315() + fun_l26_n474 +end + +def fun_l25_n316() + fun_l26_n329 +end + +def fun_l25_n317() + fun_l26_n19 +end + +def fun_l25_n318() + fun_l26_n85 +end + +def fun_l25_n319() + fun_l26_n548 +end + +def fun_l25_n320() + fun_l26_n435 +end + +def fun_l25_n321() + fun_l26_n607 +end + +def fun_l25_n322() + fun_l26_n610 +end + +def fun_l25_n323() + fun_l26_n218 +end + +def fun_l25_n324() + fun_l26_n664 +end + +def fun_l25_n325() + fun_l26_n869 +end + +def fun_l25_n326() + fun_l26_n110 +end + +def fun_l25_n327() + fun_l26_n811 +end + +def fun_l25_n328() + fun_l26_n70 +end + +def fun_l25_n329() + fun_l26_n852 +end + +def fun_l25_n330() + fun_l26_n772 +end + +def fun_l25_n331() + fun_l26_n367 +end + +def fun_l25_n332() + fun_l26_n34 +end + +def fun_l25_n333() + fun_l26_n470 +end + +def fun_l25_n334() + fun_l26_n962 +end + +def fun_l25_n335() + fun_l26_n957 +end + +def fun_l25_n336() + fun_l26_n608 +end + +def fun_l25_n337() + fun_l26_n632 +end + +def fun_l25_n338() + fun_l26_n960 +end + +def fun_l25_n339() + fun_l26_n584 +end + +def fun_l25_n340() + fun_l26_n500 +end + +def fun_l25_n341() + fun_l26_n317 +end + +def fun_l25_n342() + fun_l26_n772 +end + +def fun_l25_n343() + fun_l26_n741 +end + +def fun_l25_n344() + fun_l26_n584 +end + +def fun_l25_n345() + fun_l26_n221 +end + +def fun_l25_n346() + fun_l26_n809 +end + +def fun_l25_n347() + fun_l26_n28 +end + +def fun_l25_n348() + fun_l26_n111 +end + +def fun_l25_n349() + fun_l26_n499 +end + +def fun_l25_n350() + fun_l26_n35 +end + +def fun_l25_n351() + fun_l26_n885 +end + +def fun_l25_n352() + fun_l26_n516 +end + +def fun_l25_n353() + fun_l26_n394 +end + +def fun_l25_n354() + fun_l26_n792 +end + +def fun_l25_n355() + fun_l26_n741 +end + +def fun_l25_n356() + fun_l26_n851 +end + +def fun_l25_n357() + fun_l26_n483 +end + +def fun_l25_n358() + fun_l26_n464 +end + +def fun_l25_n359() + fun_l26_n886 +end + +def fun_l25_n360() + fun_l26_n479 +end + +def fun_l25_n361() + fun_l26_n31 +end + +def fun_l25_n362() + fun_l26_n154 +end + +def fun_l25_n363() + fun_l26_n178 +end + +def fun_l25_n364() + fun_l26_n390 +end + +def fun_l25_n365() + fun_l26_n597 +end + +def fun_l25_n366() + fun_l26_n85 +end + +def fun_l25_n367() + fun_l26_n614 +end + +def fun_l25_n368() + fun_l26_n796 +end + +def fun_l25_n369() + fun_l26_n627 +end + +def fun_l25_n370() + fun_l26_n581 +end + +def fun_l25_n371() + fun_l26_n63 +end + +def fun_l25_n372() + fun_l26_n708 +end + +def fun_l25_n373() + fun_l26_n858 +end + +def fun_l25_n374() + fun_l26_n143 +end + +def fun_l25_n375() + fun_l26_n742 +end + +def fun_l25_n376() + fun_l26_n54 +end + +def fun_l25_n377() + fun_l26_n299 +end + +def fun_l25_n378() + fun_l26_n465 +end + +def fun_l25_n379() + fun_l26_n207 +end + +def fun_l25_n380() + fun_l26_n3 +end + +def fun_l25_n381() + fun_l26_n648 +end + +def fun_l25_n382() + fun_l26_n7 +end + +def fun_l25_n383() + fun_l26_n586 +end + +def fun_l25_n384() + fun_l26_n884 +end + +def fun_l25_n385() + fun_l26_n731 +end + +def fun_l25_n386() + fun_l26_n60 +end + +def fun_l25_n387() + fun_l26_n600 +end + +def fun_l25_n388() + fun_l26_n162 +end + +def fun_l25_n389() + fun_l26_n229 +end + +def fun_l25_n390() + fun_l26_n60 +end + +def fun_l25_n391() + fun_l26_n617 +end + +def fun_l25_n392() + fun_l26_n823 +end + +def fun_l25_n393() + fun_l26_n546 +end + +def fun_l25_n394() + fun_l26_n783 +end + +def fun_l25_n395() + fun_l26_n616 +end + +def fun_l25_n396() + fun_l26_n131 +end + +def fun_l25_n397() + fun_l26_n744 +end + +def fun_l25_n398() + fun_l26_n344 +end + +def fun_l25_n399() + fun_l26_n529 +end + +def fun_l25_n400() + fun_l26_n314 +end + +def fun_l25_n401() + fun_l26_n571 +end + +def fun_l25_n402() + fun_l26_n329 +end + +def fun_l25_n403() + fun_l26_n334 +end + +def fun_l25_n404() + fun_l26_n232 +end + +def fun_l25_n405() + fun_l26_n864 +end + +def fun_l25_n406() + fun_l26_n882 +end + +def fun_l25_n407() + fun_l26_n153 +end + +def fun_l25_n408() + fun_l26_n770 +end + +def fun_l25_n409() + fun_l26_n199 +end + +def fun_l25_n410() + fun_l26_n799 +end + +def fun_l25_n411() + fun_l26_n306 +end + +def fun_l25_n412() + fun_l26_n957 +end + +def fun_l25_n413() + fun_l26_n519 +end + +def fun_l25_n414() + fun_l26_n445 +end + +def fun_l25_n415() + fun_l26_n272 +end + +def fun_l25_n416() + fun_l26_n119 +end + +def fun_l25_n417() + fun_l26_n143 +end + +def fun_l25_n418() + fun_l26_n964 +end + +def fun_l25_n419() + fun_l26_n574 +end + +def fun_l25_n420() + fun_l26_n215 +end + +def fun_l25_n421() + fun_l26_n144 +end + +def fun_l25_n422() + fun_l26_n345 +end + +def fun_l25_n423() + fun_l26_n121 +end + +def fun_l25_n424() + fun_l26_n77 +end + +def fun_l25_n425() + fun_l26_n112 +end + +def fun_l25_n426() + fun_l26_n992 +end + +def fun_l25_n427() + fun_l26_n320 +end + +def fun_l25_n428() + fun_l26_n980 +end + +def fun_l25_n429() + fun_l26_n442 +end + +def fun_l25_n430() + fun_l26_n422 +end + +def fun_l25_n431() + fun_l26_n164 +end + +def fun_l25_n432() + fun_l26_n778 +end + +def fun_l25_n433() + fun_l26_n330 +end + +def fun_l25_n434() + fun_l26_n535 +end + +def fun_l25_n435() + fun_l26_n149 +end + +def fun_l25_n436() + fun_l26_n411 +end + +def fun_l25_n437() + fun_l26_n465 +end + +def fun_l25_n438() + fun_l26_n231 +end + +def fun_l25_n439() + fun_l26_n542 +end + +def fun_l25_n440() + fun_l26_n720 +end + +def fun_l25_n441() + fun_l26_n883 +end + +def fun_l25_n442() + fun_l26_n258 +end + +def fun_l25_n443() + fun_l26_n633 +end + +def fun_l25_n444() + fun_l26_n715 +end + +def fun_l25_n445() + fun_l26_n844 +end + +def fun_l25_n446() + fun_l26_n837 +end + +def fun_l25_n447() + fun_l26_n161 +end + +def fun_l25_n448() + fun_l26_n389 +end + +def fun_l25_n449() + fun_l26_n246 +end + +def fun_l25_n450() + fun_l26_n570 +end + +def fun_l25_n451() + fun_l26_n678 +end + +def fun_l25_n452() + fun_l26_n243 +end + +def fun_l25_n453() + fun_l26_n430 +end + +def fun_l25_n454() + fun_l26_n193 +end + +def fun_l25_n455() + fun_l26_n666 +end + +def fun_l25_n456() + fun_l26_n881 +end + +def fun_l25_n457() + fun_l26_n989 +end + +def fun_l25_n458() + fun_l26_n450 +end + +def fun_l25_n459() + fun_l26_n675 +end + +def fun_l25_n460() + fun_l26_n315 +end + +def fun_l25_n461() + fun_l26_n40 +end + +def fun_l25_n462() + fun_l26_n639 +end + +def fun_l25_n463() + fun_l26_n380 +end + +def fun_l25_n464() + fun_l26_n680 +end + +def fun_l25_n465() + fun_l26_n54 +end + +def fun_l25_n466() + fun_l26_n37 +end + +def fun_l25_n467() + fun_l26_n910 +end + +def fun_l25_n468() + fun_l26_n50 +end + +def fun_l25_n469() + fun_l26_n925 +end + +def fun_l25_n470() + fun_l26_n385 +end + +def fun_l25_n471() + fun_l26_n860 +end + +def fun_l25_n472() + fun_l26_n547 +end + +def fun_l25_n473() + fun_l26_n31 +end + +def fun_l25_n474() + fun_l26_n338 +end + +def fun_l25_n475() + fun_l26_n706 +end + +def fun_l25_n476() + fun_l26_n81 +end + +def fun_l25_n477() + fun_l26_n532 +end + +def fun_l25_n478() + fun_l26_n781 +end + +def fun_l25_n479() + fun_l26_n588 +end + +def fun_l25_n480() + fun_l26_n658 +end + +def fun_l25_n481() + fun_l26_n344 +end + +def fun_l25_n482() + fun_l26_n914 +end + +def fun_l25_n483() + fun_l26_n319 +end + +def fun_l25_n484() + fun_l26_n138 +end + +def fun_l25_n485() + fun_l26_n927 +end + +def fun_l25_n486() + fun_l26_n409 +end + +def fun_l25_n487() + fun_l26_n721 +end + +def fun_l25_n488() + fun_l26_n197 +end + +def fun_l25_n489() + fun_l26_n654 +end + +def fun_l25_n490() + fun_l26_n298 +end + +def fun_l25_n491() + fun_l26_n763 +end + +def fun_l25_n492() + fun_l26_n729 +end + +def fun_l25_n493() + fun_l26_n532 +end + +def fun_l25_n494() + fun_l26_n508 +end + +def fun_l25_n495() + fun_l26_n725 +end + +def fun_l25_n496() + fun_l26_n665 +end + +def fun_l25_n497() + fun_l26_n21 +end + +def fun_l25_n498() + fun_l26_n314 +end + +def fun_l25_n499() + fun_l26_n823 +end + +def fun_l25_n500() + fun_l26_n983 +end + +def fun_l25_n501() + fun_l26_n477 +end + +def fun_l25_n502() + fun_l26_n502 +end + +def fun_l25_n503() + fun_l26_n731 +end + +def fun_l25_n504() + fun_l26_n427 +end + +def fun_l25_n505() + fun_l26_n949 +end + +def fun_l25_n506() + fun_l26_n566 +end + +def fun_l25_n507() + fun_l26_n407 +end + +def fun_l25_n508() + fun_l26_n427 +end + +def fun_l25_n509() + fun_l26_n423 +end + +def fun_l25_n510() + fun_l26_n394 +end + +def fun_l25_n511() + fun_l26_n584 +end + +def fun_l25_n512() + fun_l26_n35 +end + +def fun_l25_n513() + fun_l26_n89 +end + +def fun_l25_n514() + fun_l26_n369 +end + +def fun_l25_n515() + fun_l26_n483 +end + +def fun_l25_n516() + fun_l26_n897 +end + +def fun_l25_n517() + fun_l26_n39 +end + +def fun_l25_n518() + fun_l26_n904 +end + +def fun_l25_n519() + fun_l26_n264 +end + +def fun_l25_n520() + fun_l26_n806 +end + +def fun_l25_n521() + fun_l26_n206 +end + +def fun_l25_n522() + fun_l26_n417 +end + +def fun_l25_n523() + fun_l26_n235 +end + +def fun_l25_n524() + fun_l26_n192 +end + +def fun_l25_n525() + fun_l26_n62 +end + +def fun_l25_n526() + fun_l26_n295 +end + +def fun_l25_n527() + fun_l26_n998 +end + +def fun_l25_n528() + fun_l26_n898 +end + +def fun_l25_n529() + fun_l26_n705 +end + +def fun_l25_n530() + fun_l26_n571 +end + +def fun_l25_n531() + fun_l26_n883 +end + +def fun_l25_n532() + fun_l26_n198 +end + +def fun_l25_n533() + fun_l26_n893 +end + +def fun_l25_n534() + fun_l26_n849 +end + +def fun_l25_n535() + fun_l26_n540 +end + +def fun_l25_n536() + fun_l26_n509 +end + +def fun_l25_n537() + fun_l26_n889 +end + +def fun_l25_n538() + fun_l26_n981 +end + +def fun_l25_n539() + fun_l26_n477 +end + +def fun_l25_n540() + fun_l26_n908 +end + +def fun_l25_n541() + fun_l26_n455 +end + +def fun_l25_n542() + fun_l26_n547 +end + +def fun_l25_n543() + fun_l26_n487 +end + +def fun_l25_n544() + fun_l26_n365 +end + +def fun_l25_n545() + fun_l26_n853 +end + +def fun_l25_n546() + fun_l26_n591 +end + +def fun_l25_n547() + fun_l26_n298 +end + +def fun_l25_n548() + fun_l26_n529 +end + +def fun_l25_n549() + fun_l26_n191 +end + +def fun_l25_n550() + fun_l26_n118 +end + +def fun_l25_n551() + fun_l26_n82 +end + +def fun_l25_n552() + fun_l26_n874 +end + +def fun_l25_n553() + fun_l26_n924 +end + +def fun_l25_n554() + fun_l26_n683 +end + +def fun_l25_n555() + fun_l26_n163 +end + +def fun_l25_n556() + fun_l26_n935 +end + +def fun_l25_n557() + fun_l26_n657 +end + +def fun_l25_n558() + fun_l26_n17 +end + +def fun_l25_n559() + fun_l26_n578 +end + +def fun_l25_n560() + fun_l26_n105 +end + +def fun_l25_n561() + fun_l26_n280 +end + +def fun_l25_n562() + fun_l26_n130 +end + +def fun_l25_n563() + fun_l26_n824 +end + +def fun_l25_n564() + fun_l26_n376 +end + +def fun_l25_n565() + fun_l26_n942 +end + +def fun_l25_n566() + fun_l26_n771 +end + +def fun_l25_n567() + fun_l26_n245 +end + +def fun_l25_n568() + fun_l26_n361 +end + +def fun_l25_n569() + fun_l26_n328 +end + +def fun_l25_n570() + fun_l26_n718 +end + +def fun_l25_n571() + fun_l26_n918 +end + +def fun_l25_n572() + fun_l26_n592 +end + +def fun_l25_n573() + fun_l26_n690 +end + +def fun_l25_n574() + fun_l26_n689 +end + +def fun_l25_n575() + fun_l26_n571 +end + +def fun_l25_n576() + fun_l26_n106 +end + +def fun_l25_n577() + fun_l26_n917 +end + +def fun_l25_n578() + fun_l26_n954 +end + +def fun_l25_n579() + fun_l26_n842 +end + +def fun_l25_n580() + fun_l26_n277 +end + +def fun_l25_n581() + fun_l26_n511 +end + +def fun_l25_n582() + fun_l26_n834 +end + +def fun_l25_n583() + fun_l26_n992 +end + +def fun_l25_n584() + fun_l26_n711 +end + +def fun_l25_n585() + fun_l26_n366 +end + +def fun_l25_n586() + fun_l26_n960 +end + +def fun_l25_n587() + fun_l26_n229 +end + +def fun_l25_n588() + fun_l26_n208 +end + +def fun_l25_n589() + fun_l26_n758 +end + +def fun_l25_n590() + fun_l26_n98 +end + +def fun_l25_n591() + fun_l26_n452 +end + +def fun_l25_n592() + fun_l26_n526 +end + +def fun_l25_n593() + fun_l26_n92 +end + +def fun_l25_n594() + fun_l26_n108 +end + +def fun_l25_n595() + fun_l26_n250 +end + +def fun_l25_n596() + fun_l26_n186 +end + +def fun_l25_n597() + fun_l26_n603 +end + +def fun_l25_n598() + fun_l26_n828 +end + +def fun_l25_n599() + fun_l26_n610 +end + +def fun_l25_n600() + fun_l26_n280 +end + +def fun_l25_n601() + fun_l26_n158 +end + +def fun_l25_n602() + fun_l26_n386 +end + +def fun_l25_n603() + fun_l26_n869 +end + +def fun_l25_n604() + fun_l26_n483 +end + +def fun_l25_n605() + fun_l26_n682 +end + +def fun_l25_n606() + fun_l26_n175 +end + +def fun_l25_n607() + fun_l26_n991 +end + +def fun_l25_n608() + fun_l26_n165 +end + +def fun_l25_n609() + fun_l26_n303 +end + +def fun_l25_n610() + fun_l26_n812 +end + +def fun_l25_n611() + fun_l26_n563 +end + +def fun_l25_n612() + fun_l26_n635 +end + +def fun_l25_n613() + fun_l26_n256 +end + +def fun_l25_n614() + fun_l26_n96 +end + +def fun_l25_n615() + fun_l26_n8 +end + +def fun_l25_n616() + fun_l26_n963 +end + +def fun_l25_n617() + fun_l26_n860 +end + +def fun_l25_n618() + fun_l26_n316 +end + +def fun_l25_n619() + fun_l26_n388 +end + +def fun_l25_n620() + fun_l26_n427 +end + +def fun_l25_n621() + fun_l26_n519 +end + +def fun_l25_n622() + fun_l26_n780 +end + +def fun_l25_n623() + fun_l26_n142 +end + +def fun_l25_n624() + fun_l26_n271 +end + +def fun_l25_n625() + fun_l26_n617 +end + +def fun_l25_n626() + fun_l26_n968 +end + +def fun_l25_n627() + fun_l26_n880 +end + +def fun_l25_n628() + fun_l26_n831 +end + +def fun_l25_n629() + fun_l26_n616 +end + +def fun_l25_n630() + fun_l26_n213 +end + +def fun_l25_n631() + fun_l26_n91 +end + +def fun_l25_n632() + fun_l26_n295 +end + +def fun_l25_n633() + fun_l26_n314 +end + +def fun_l25_n634() + fun_l26_n174 +end + +def fun_l25_n635() + fun_l26_n668 +end + +def fun_l25_n636() + fun_l26_n962 +end + +def fun_l25_n637() + fun_l26_n1 +end + +def fun_l25_n638() + fun_l26_n361 +end + +def fun_l25_n639() + fun_l26_n947 +end + +def fun_l25_n640() + fun_l26_n381 +end + +def fun_l25_n641() + fun_l26_n388 +end + +def fun_l25_n642() + fun_l26_n5 +end + +def fun_l25_n643() + fun_l26_n759 +end + +def fun_l25_n644() + fun_l26_n454 +end + +def fun_l25_n645() + fun_l26_n596 +end + +def fun_l25_n646() + fun_l26_n639 +end + +def fun_l25_n647() + fun_l26_n156 +end + +def fun_l25_n648() + fun_l26_n395 +end + +def fun_l25_n649() + fun_l26_n424 +end + +def fun_l25_n650() + fun_l26_n21 +end + +def fun_l25_n651() + fun_l26_n285 +end + +def fun_l25_n652() + fun_l26_n72 +end + +def fun_l25_n653() + fun_l26_n25 +end + +def fun_l25_n654() + fun_l26_n381 +end + +def fun_l25_n655() + fun_l26_n166 +end + +def fun_l25_n656() + fun_l26_n850 +end + +def fun_l25_n657() + fun_l26_n794 +end + +def fun_l25_n658() + fun_l26_n674 +end + +def fun_l25_n659() + fun_l26_n934 +end + +def fun_l25_n660() + fun_l26_n164 +end + +def fun_l25_n661() + fun_l26_n325 +end + +def fun_l25_n662() + fun_l26_n514 +end + +def fun_l25_n663() + fun_l26_n489 +end + +def fun_l25_n664() + fun_l26_n268 +end + +def fun_l25_n665() + fun_l26_n4 +end + +def fun_l25_n666() + fun_l26_n330 +end + +def fun_l25_n667() + fun_l26_n749 +end + +def fun_l25_n668() + fun_l26_n324 +end + +def fun_l25_n669() + fun_l26_n228 +end + +def fun_l25_n670() + fun_l26_n740 +end + +def fun_l25_n671() + fun_l26_n240 +end + +def fun_l25_n672() + fun_l26_n145 +end + +def fun_l25_n673() + fun_l26_n170 +end + +def fun_l25_n674() + fun_l26_n222 +end + +def fun_l25_n675() + fun_l26_n680 +end + +def fun_l25_n676() + fun_l26_n115 +end + +def fun_l25_n677() + fun_l26_n359 +end + +def fun_l25_n678() + fun_l26_n482 +end + +def fun_l25_n679() + fun_l26_n251 +end + +def fun_l25_n680() + fun_l26_n95 +end + +def fun_l25_n681() + fun_l26_n587 +end + +def fun_l25_n682() + fun_l26_n689 +end + +def fun_l25_n683() + fun_l26_n317 +end + +def fun_l25_n684() + fun_l26_n913 +end + +def fun_l25_n685() + fun_l26_n943 +end + +def fun_l25_n686() + fun_l26_n770 +end + +def fun_l25_n687() + fun_l26_n204 +end + +def fun_l25_n688() + fun_l26_n690 +end + +def fun_l25_n689() + fun_l26_n745 +end + +def fun_l25_n690() + fun_l26_n640 +end + +def fun_l25_n691() + fun_l26_n34 +end + +def fun_l25_n692() + fun_l26_n296 +end + +def fun_l25_n693() + fun_l26_n900 +end + +def fun_l25_n694() + fun_l26_n619 +end + +def fun_l25_n695() + fun_l26_n81 +end + +def fun_l25_n696() + fun_l26_n748 +end + +def fun_l25_n697() + fun_l26_n395 +end + +def fun_l25_n698() + fun_l26_n518 +end + +def fun_l25_n699() + fun_l26_n338 +end + +def fun_l25_n700() + fun_l26_n238 +end + +def fun_l25_n701() + fun_l26_n445 +end + +def fun_l25_n702() + fun_l26_n732 +end + +def fun_l25_n703() + fun_l26_n378 +end + +def fun_l25_n704() + fun_l26_n858 +end + +def fun_l25_n705() + fun_l26_n944 +end + +def fun_l25_n706() + fun_l26_n543 +end + +def fun_l25_n707() + fun_l26_n750 +end + +def fun_l25_n708() + fun_l26_n191 +end + +def fun_l25_n709() + fun_l26_n483 +end + +def fun_l25_n710() + fun_l26_n614 +end + +def fun_l25_n711() + fun_l26_n944 +end + +def fun_l25_n712() + fun_l26_n375 +end + +def fun_l25_n713() + fun_l26_n464 +end + +def fun_l25_n714() + fun_l26_n429 +end + +def fun_l25_n715() + fun_l26_n251 +end + +def fun_l25_n716() + fun_l26_n401 +end + +def fun_l25_n717() + fun_l26_n230 +end + +def fun_l25_n718() + fun_l26_n855 +end + +def fun_l25_n719() + fun_l26_n63 +end + +def fun_l25_n720() + fun_l26_n453 +end + +def fun_l25_n721() + fun_l26_n698 +end + +def fun_l25_n722() + fun_l26_n691 +end + +def fun_l25_n723() + fun_l26_n949 +end + +def fun_l25_n724() + fun_l26_n838 +end + +def fun_l25_n725() + fun_l26_n962 +end + +def fun_l25_n726() + fun_l26_n159 +end + +def fun_l25_n727() + fun_l26_n958 +end + +def fun_l25_n728() + fun_l26_n915 +end + +def fun_l25_n729() + fun_l26_n925 +end + +def fun_l25_n730() + fun_l26_n841 +end + +def fun_l25_n731() + fun_l26_n710 +end + +def fun_l25_n732() + fun_l26_n606 +end + +def fun_l25_n733() + fun_l26_n502 +end + +def fun_l25_n734() + fun_l26_n275 +end + +def fun_l25_n735() + fun_l26_n2 +end + +def fun_l25_n736() + fun_l26_n912 +end + +def fun_l25_n737() + fun_l26_n908 +end + +def fun_l25_n738() + fun_l26_n599 +end + +def fun_l25_n739() + fun_l26_n586 +end + +def fun_l25_n740() + fun_l26_n675 +end + +def fun_l25_n741() + fun_l26_n33 +end + +def fun_l25_n742() + fun_l26_n94 +end + +def fun_l25_n743() + fun_l26_n512 +end + +def fun_l25_n744() + fun_l26_n38 +end + +def fun_l25_n745() + fun_l26_n479 +end + +def fun_l25_n746() + fun_l26_n191 +end + +def fun_l25_n747() + fun_l26_n520 +end + +def fun_l25_n748() + fun_l26_n800 +end + +def fun_l25_n749() + fun_l26_n401 +end + +def fun_l25_n750() + fun_l26_n355 +end + +def fun_l25_n751() + fun_l26_n622 +end + +def fun_l25_n752() + fun_l26_n48 +end + +def fun_l25_n753() + fun_l26_n620 +end + +def fun_l25_n754() + fun_l26_n932 +end + +def fun_l25_n755() + fun_l26_n204 +end + +def fun_l25_n756() + fun_l26_n875 +end + +def fun_l25_n757() + fun_l26_n458 +end + +def fun_l25_n758() + fun_l26_n364 +end + +def fun_l25_n759() + fun_l26_n621 +end + +def fun_l25_n760() + fun_l26_n800 +end + +def fun_l25_n761() + fun_l26_n297 +end + +def fun_l25_n762() + fun_l26_n262 +end + +def fun_l25_n763() + fun_l26_n810 +end + +def fun_l25_n764() + fun_l26_n518 +end + +def fun_l25_n765() + fun_l26_n192 +end + +def fun_l25_n766() + fun_l26_n733 +end + +def fun_l25_n767() + fun_l26_n410 +end + +def fun_l25_n768() + fun_l26_n161 +end + +def fun_l25_n769() + fun_l26_n546 +end + +def fun_l25_n770() + fun_l26_n863 +end + +def fun_l25_n771() + fun_l26_n442 +end + +def fun_l25_n772() + fun_l26_n733 +end + +def fun_l25_n773() + fun_l26_n340 +end + +def fun_l25_n774() + fun_l26_n371 +end + +def fun_l25_n775() + fun_l26_n253 +end + +def fun_l25_n776() + fun_l26_n607 +end + +def fun_l25_n777() + fun_l26_n859 +end + +def fun_l25_n778() + fun_l26_n142 +end + +def fun_l25_n779() + fun_l26_n504 +end + +def fun_l25_n780() + fun_l26_n145 +end + +def fun_l25_n781() + fun_l26_n561 +end + +def fun_l25_n782() + fun_l26_n442 +end + +def fun_l25_n783() + fun_l26_n70 +end + +def fun_l25_n784() + fun_l26_n233 +end + +def fun_l25_n785() + fun_l26_n680 +end + +def fun_l25_n786() + fun_l26_n195 +end + +def fun_l25_n787() + fun_l26_n760 +end + +def fun_l25_n788() + fun_l26_n951 +end + +def fun_l25_n789() + fun_l26_n247 +end + +def fun_l25_n790() + fun_l26_n58 +end + +def fun_l25_n791() + fun_l26_n926 +end + +def fun_l25_n792() + fun_l26_n424 +end + +def fun_l25_n793() + fun_l26_n404 +end + +def fun_l25_n794() + fun_l26_n98 +end + +def fun_l25_n795() + fun_l26_n568 +end + +def fun_l25_n796() + fun_l26_n665 +end + +def fun_l25_n797() + fun_l26_n138 +end + +def fun_l25_n798() + fun_l26_n362 +end + +def fun_l25_n799() + fun_l26_n366 +end + +def fun_l25_n800() + fun_l26_n667 +end + +def fun_l25_n801() + fun_l26_n171 +end + +def fun_l25_n802() + fun_l26_n620 +end + +def fun_l25_n803() + fun_l26_n88 +end + +def fun_l25_n804() + fun_l26_n60 +end + +def fun_l25_n805() + fun_l26_n411 +end + +def fun_l25_n806() + fun_l26_n994 +end + +def fun_l25_n807() + fun_l26_n341 +end + +def fun_l25_n808() + fun_l26_n364 +end + +def fun_l25_n809() + fun_l26_n253 +end + +def fun_l25_n810() + fun_l26_n689 +end + +def fun_l25_n811() + fun_l26_n325 +end + +def fun_l25_n812() + fun_l26_n573 +end + +def fun_l25_n813() + fun_l26_n122 +end + +def fun_l25_n814() + fun_l26_n487 +end + +def fun_l25_n815() + fun_l26_n461 +end + +def fun_l25_n816() + fun_l26_n851 +end + +def fun_l25_n817() + fun_l26_n322 +end + +def fun_l25_n818() + fun_l26_n472 +end + +def fun_l25_n819() + fun_l26_n773 +end + +def fun_l25_n820() + fun_l26_n801 +end + +def fun_l25_n821() + fun_l26_n454 +end + +def fun_l25_n822() + fun_l26_n179 +end + +def fun_l25_n823() + fun_l26_n207 +end + +def fun_l25_n824() + fun_l26_n464 +end + +def fun_l25_n825() + fun_l26_n188 +end + +def fun_l25_n826() + fun_l26_n831 +end + +def fun_l25_n827() + fun_l26_n918 +end + +def fun_l25_n828() + fun_l26_n336 +end + +def fun_l25_n829() + fun_l26_n960 +end + +def fun_l25_n830() + fun_l26_n767 +end + +def fun_l25_n831() + fun_l26_n149 +end + +def fun_l25_n832() + fun_l26_n454 +end + +def fun_l25_n833() + fun_l26_n756 +end + +def fun_l25_n834() + fun_l26_n937 +end + +def fun_l25_n835() + fun_l26_n841 +end + +def fun_l25_n836() + fun_l26_n210 +end + +def fun_l25_n837() + fun_l26_n633 +end + +def fun_l25_n838() + fun_l26_n665 +end + +def fun_l25_n839() + fun_l26_n502 +end + +def fun_l25_n840() + fun_l26_n38 +end + +def fun_l25_n841() + fun_l26_n487 +end + +def fun_l25_n842() + fun_l26_n101 +end + +def fun_l25_n843() + fun_l26_n522 +end + +def fun_l25_n844() + fun_l26_n501 +end + +def fun_l25_n845() + fun_l26_n759 +end + +def fun_l25_n846() + fun_l26_n161 +end + +def fun_l25_n847() + fun_l26_n823 +end + +def fun_l25_n848() + fun_l26_n687 +end + +def fun_l25_n849() + fun_l26_n41 +end + +def fun_l25_n850() + fun_l26_n580 +end + +def fun_l25_n851() + fun_l26_n728 +end + +def fun_l25_n852() + fun_l26_n464 +end + +def fun_l25_n853() + fun_l26_n846 +end + +def fun_l25_n854() + fun_l26_n708 +end + +def fun_l25_n855() + fun_l26_n847 +end + +def fun_l25_n856() + fun_l26_n295 +end + +def fun_l25_n857() + fun_l26_n569 +end + +def fun_l25_n858() + fun_l26_n367 +end + +def fun_l25_n859() + fun_l26_n937 +end + +def fun_l25_n860() + fun_l26_n116 +end + +def fun_l25_n861() + fun_l26_n889 +end + +def fun_l25_n862() + fun_l26_n392 +end + +def fun_l25_n863() + fun_l26_n70 +end + +def fun_l25_n864() + fun_l26_n82 +end + +def fun_l25_n865() + fun_l26_n4 +end + +def fun_l25_n866() + fun_l26_n286 +end + +def fun_l25_n867() + fun_l26_n594 +end + +def fun_l25_n868() + fun_l26_n917 +end + +def fun_l25_n869() + fun_l26_n385 +end + +def fun_l25_n870() + fun_l26_n149 +end + +def fun_l25_n871() + fun_l26_n893 +end + +def fun_l25_n872() + fun_l26_n832 +end + +def fun_l25_n873() + fun_l26_n962 +end + +def fun_l25_n874() + fun_l26_n196 +end + +def fun_l25_n875() + fun_l26_n841 +end + +def fun_l25_n876() + fun_l26_n334 +end + +def fun_l25_n877() + fun_l26_n680 +end + +def fun_l25_n878() + fun_l26_n858 +end + +def fun_l25_n879() + fun_l26_n530 +end + +def fun_l25_n880() + fun_l26_n331 +end + +def fun_l25_n881() + fun_l26_n287 +end + +def fun_l25_n882() + fun_l26_n995 +end + +def fun_l25_n883() + fun_l26_n663 +end + +def fun_l25_n884() + fun_l26_n352 +end + +def fun_l25_n885() + fun_l26_n787 +end + +def fun_l25_n886() + fun_l26_n176 +end + +def fun_l25_n887() + fun_l26_n303 +end + +def fun_l25_n888() + fun_l26_n610 +end + +def fun_l25_n889() + fun_l26_n860 +end + +def fun_l25_n890() + fun_l26_n35 +end + +def fun_l25_n891() + fun_l26_n599 +end + +def fun_l25_n892() + fun_l26_n334 +end + +def fun_l25_n893() + fun_l26_n904 +end + +def fun_l25_n894() + fun_l26_n999 +end + +def fun_l25_n895() + fun_l26_n394 +end + +def fun_l25_n896() + fun_l26_n901 +end + +def fun_l25_n897() + fun_l26_n348 +end + +def fun_l25_n898() + fun_l26_n59 +end + +def fun_l25_n899() + fun_l26_n67 +end + +def fun_l25_n900() + fun_l26_n887 +end + +def fun_l25_n901() + fun_l26_n27 +end + +def fun_l25_n902() + fun_l26_n635 +end + +def fun_l25_n903() + fun_l26_n627 +end + +def fun_l25_n904() + fun_l26_n47 +end + +def fun_l25_n905() + fun_l26_n256 +end + +def fun_l25_n906() + fun_l26_n498 +end + +def fun_l25_n907() + fun_l26_n831 +end + +def fun_l25_n908() + fun_l26_n723 +end + +def fun_l25_n909() + fun_l26_n29 +end + +def fun_l25_n910() + fun_l26_n842 +end + +def fun_l25_n911() + fun_l26_n762 +end + +def fun_l25_n912() + fun_l26_n706 +end + +def fun_l25_n913() + fun_l26_n472 +end + +def fun_l25_n914() + fun_l26_n825 +end + +def fun_l25_n915() + fun_l26_n210 +end + +def fun_l25_n916() + fun_l26_n682 +end + +def fun_l25_n917() + fun_l26_n793 +end + +def fun_l25_n918() + fun_l26_n768 +end + +def fun_l25_n919() + fun_l26_n631 +end + +def fun_l25_n920() + fun_l26_n188 +end + +def fun_l25_n921() + fun_l26_n115 +end + +def fun_l25_n922() + fun_l26_n587 +end + +def fun_l25_n923() + fun_l26_n998 +end + +def fun_l25_n924() + fun_l26_n439 +end + +def fun_l25_n925() + fun_l26_n306 +end + +def fun_l25_n926() + fun_l26_n810 +end + +def fun_l25_n927() + fun_l26_n183 +end + +def fun_l25_n928() + fun_l26_n868 +end + +def fun_l25_n929() + fun_l26_n733 +end + +def fun_l25_n930() + fun_l26_n931 +end + +def fun_l25_n931() + fun_l26_n747 +end + +def fun_l25_n932() + fun_l26_n126 +end + +def fun_l25_n933() + fun_l26_n299 +end + +def fun_l25_n934() + fun_l26_n994 +end + +def fun_l25_n935() + fun_l26_n76 +end + +def fun_l25_n936() + fun_l26_n606 +end + +def fun_l25_n937() + fun_l26_n874 +end + +def fun_l25_n938() + fun_l26_n333 +end + +def fun_l25_n939() + fun_l26_n601 +end + +def fun_l25_n940() + fun_l26_n503 +end + +def fun_l25_n941() + fun_l26_n819 +end + +def fun_l25_n942() + fun_l26_n414 +end + +def fun_l25_n943() + fun_l26_n839 +end + +def fun_l25_n944() + fun_l26_n655 +end + +def fun_l25_n945() + fun_l26_n61 +end + +def fun_l25_n946() + fun_l26_n368 +end + +def fun_l25_n947() + fun_l26_n481 +end + +def fun_l25_n948() + fun_l26_n674 +end + +def fun_l25_n949() + fun_l26_n755 +end + +def fun_l25_n950() + fun_l26_n940 +end + +def fun_l25_n951() + fun_l26_n918 +end + +def fun_l25_n952() + fun_l26_n833 +end + +def fun_l25_n953() + fun_l26_n81 +end + +def fun_l25_n954() + fun_l26_n12 +end + +def fun_l25_n955() + fun_l26_n598 +end + +def fun_l25_n956() + fun_l26_n10 +end + +def fun_l25_n957() + fun_l26_n552 +end + +def fun_l25_n958() + fun_l26_n536 +end + +def fun_l25_n959() + fun_l26_n291 +end + +def fun_l25_n960() + fun_l26_n535 +end + +def fun_l25_n961() + fun_l26_n593 +end + +def fun_l25_n962() + fun_l26_n834 +end + +def fun_l25_n963() + fun_l26_n527 +end + +def fun_l25_n964() + fun_l26_n403 +end + +def fun_l25_n965() + fun_l26_n246 +end + +def fun_l25_n966() + fun_l26_n278 +end + +def fun_l25_n967() + fun_l26_n948 +end + +def fun_l25_n968() + fun_l26_n989 +end + +def fun_l25_n969() + fun_l26_n312 +end + +def fun_l25_n970() + fun_l26_n674 +end + +def fun_l25_n971() + fun_l26_n592 +end + +def fun_l25_n972() + fun_l26_n413 +end + +def fun_l25_n973() + fun_l26_n774 +end + +def fun_l25_n974() + fun_l26_n148 +end + +def fun_l25_n975() + fun_l26_n437 +end + +def fun_l25_n976() + fun_l26_n749 +end + +def fun_l25_n977() + fun_l26_n938 +end + +def fun_l25_n978() + fun_l26_n662 +end + +def fun_l25_n979() + fun_l26_n327 +end + +def fun_l25_n980() + fun_l26_n665 +end + +def fun_l25_n981() + fun_l26_n516 +end + +def fun_l25_n982() + fun_l26_n27 +end + +def fun_l25_n983() + fun_l26_n624 +end + +def fun_l25_n984() + fun_l26_n451 +end + +def fun_l25_n985() + fun_l26_n120 +end + +def fun_l25_n986() + fun_l26_n220 +end + +def fun_l25_n987() + fun_l26_n201 +end + +def fun_l25_n988() + fun_l26_n67 +end + +def fun_l25_n989() + fun_l26_n484 +end + +def fun_l25_n990() + fun_l26_n98 +end + +def fun_l25_n991() + fun_l26_n133 +end + +def fun_l25_n992() + fun_l26_n642 +end + +def fun_l25_n993() + fun_l26_n933 +end + +def fun_l25_n994() + fun_l26_n410 +end + +def fun_l25_n995() + fun_l26_n415 +end + +def fun_l25_n996() + fun_l26_n513 +end + +def fun_l25_n997() + fun_l26_n41 +end + +def fun_l25_n998() + fun_l26_n517 +end + +def fun_l25_n999() + fun_l26_n485 +end + +def fun_l26_n0() + fun_l27_n229 +end + +def fun_l26_n1() + fun_l27_n178 +end + +def fun_l26_n2() + fun_l27_n76 +end + +def fun_l26_n3() + fun_l27_n247 +end + +def fun_l26_n4() + fun_l27_n564 +end + +def fun_l26_n5() + fun_l27_n204 +end + +def fun_l26_n6() + fun_l27_n196 +end + +def fun_l26_n7() + fun_l27_n57 +end + +def fun_l26_n8() + fun_l27_n836 +end + +def fun_l26_n9() + fun_l27_n195 +end + +def fun_l26_n10() + fun_l27_n149 +end + +def fun_l26_n11() + fun_l27_n784 +end + +def fun_l26_n12() + fun_l27_n242 +end + +def fun_l26_n13() + fun_l27_n771 +end + +def fun_l26_n14() + fun_l27_n263 +end + +def fun_l26_n15() + fun_l27_n486 +end + +def fun_l26_n16() + fun_l27_n351 +end + +def fun_l26_n17() + fun_l27_n612 +end + +def fun_l26_n18() + fun_l27_n61 +end + +def fun_l26_n19() + fun_l27_n119 +end + +def fun_l26_n20() + fun_l27_n419 +end + +def fun_l26_n21() + fun_l27_n265 +end + +def fun_l26_n22() + fun_l27_n70 +end + +def fun_l26_n23() + fun_l27_n868 +end + +def fun_l26_n24() + fun_l27_n969 +end + +def fun_l26_n25() + fun_l27_n355 +end + +def fun_l26_n26() + fun_l27_n558 +end + +def fun_l26_n27() + fun_l27_n522 +end + +def fun_l26_n28() + fun_l27_n704 +end + +def fun_l26_n29() + fun_l27_n196 +end + +def fun_l26_n30() + fun_l27_n834 +end + +def fun_l26_n31() + fun_l27_n187 +end + +def fun_l26_n32() + fun_l27_n324 +end + +def fun_l26_n33() + fun_l27_n233 +end + +def fun_l26_n34() + fun_l27_n559 +end + +def fun_l26_n35() + fun_l27_n331 +end + +def fun_l26_n36() + fun_l27_n71 +end + +def fun_l26_n37() + fun_l27_n572 +end + +def fun_l26_n38() + fun_l27_n918 +end + +def fun_l26_n39() + fun_l27_n866 +end + +def fun_l26_n40() + fun_l27_n909 +end + +def fun_l26_n41() + fun_l27_n861 +end + +def fun_l26_n42() + fun_l27_n440 +end + +def fun_l26_n43() + fun_l27_n213 +end + +def fun_l26_n44() + fun_l27_n675 +end + +def fun_l26_n45() + fun_l27_n490 +end + +def fun_l26_n46() + fun_l27_n579 +end + +def fun_l26_n47() + fun_l27_n25 +end + +def fun_l26_n48() + fun_l27_n180 +end + +def fun_l26_n49() + fun_l27_n346 +end + +def fun_l26_n50() + fun_l27_n761 +end + +def fun_l26_n51() + fun_l27_n336 +end + +def fun_l26_n52() + fun_l27_n124 +end + +def fun_l26_n53() + fun_l27_n485 +end + +def fun_l26_n54() + fun_l27_n24 +end + +def fun_l26_n55() + fun_l27_n666 +end + +def fun_l26_n56() + fun_l27_n957 +end + +def fun_l26_n57() + fun_l27_n790 +end + +def fun_l26_n58() + fun_l27_n475 +end + +def fun_l26_n59() + fun_l27_n915 +end + +def fun_l26_n60() + fun_l27_n313 +end + +def fun_l26_n61() + fun_l27_n148 +end + +def fun_l26_n62() + fun_l27_n185 +end + +def fun_l26_n63() + fun_l27_n468 +end + +def fun_l26_n64() + fun_l27_n549 +end + +def fun_l26_n65() + fun_l27_n29 +end + +def fun_l26_n66() + fun_l27_n601 +end + +def fun_l26_n67() + fun_l27_n3 +end + +def fun_l26_n68() + fun_l27_n363 +end + +def fun_l26_n69() + fun_l27_n721 +end + +def fun_l26_n70() + fun_l27_n76 +end + +def fun_l26_n71() + fun_l27_n265 +end + +def fun_l26_n72() + fun_l27_n771 +end + +def fun_l26_n73() + fun_l27_n660 +end + +def fun_l26_n74() + fun_l27_n714 +end + +def fun_l26_n75() + fun_l27_n495 +end + +def fun_l26_n76() + fun_l27_n133 +end + +def fun_l26_n77() + fun_l27_n753 +end + +def fun_l26_n78() + fun_l27_n999 +end + +def fun_l26_n79() + fun_l27_n527 +end + +def fun_l26_n80() + fun_l27_n767 +end + +def fun_l26_n81() + fun_l27_n444 +end + +def fun_l26_n82() + fun_l27_n160 +end + +def fun_l26_n83() + fun_l27_n799 +end + +def fun_l26_n84() + fun_l27_n631 +end + +def fun_l26_n85() + fun_l27_n480 +end + +def fun_l26_n86() + fun_l27_n800 +end + +def fun_l26_n87() + fun_l27_n168 +end + +def fun_l26_n88() + fun_l27_n191 +end + +def fun_l26_n89() + fun_l27_n832 +end + +def fun_l26_n90() + fun_l27_n522 +end + +def fun_l26_n91() + fun_l27_n747 +end + +def fun_l26_n92() + fun_l27_n50 +end + +def fun_l26_n93() + fun_l27_n472 +end + +def fun_l26_n94() + fun_l27_n778 +end + +def fun_l26_n95() + fun_l27_n130 +end + +def fun_l26_n96() + fun_l27_n735 +end + +def fun_l26_n97() + fun_l27_n130 +end + +def fun_l26_n98() + fun_l27_n95 +end + +def fun_l26_n99() + fun_l27_n171 +end + +def fun_l26_n100() + fun_l27_n121 +end + +def fun_l26_n101() + fun_l27_n789 +end + +def fun_l26_n102() + fun_l27_n124 +end + +def fun_l26_n103() + fun_l27_n836 +end + +def fun_l26_n104() + fun_l27_n785 +end + +def fun_l26_n105() + fun_l27_n586 +end + +def fun_l26_n106() + fun_l27_n220 +end + +def fun_l26_n107() + fun_l27_n783 +end + +def fun_l26_n108() + fun_l27_n239 +end + +def fun_l26_n109() + fun_l27_n838 +end + +def fun_l26_n110() + fun_l27_n563 +end + +def fun_l26_n111() + fun_l27_n955 +end + +def fun_l26_n112() + fun_l27_n889 +end + +def fun_l26_n113() + fun_l27_n967 +end + +def fun_l26_n114() + fun_l27_n19 +end + +def fun_l26_n115() + fun_l27_n637 +end + +def fun_l26_n116() + fun_l27_n914 +end + +def fun_l26_n117() + fun_l27_n684 +end + +def fun_l26_n118() + fun_l27_n352 +end + +def fun_l26_n119() + fun_l27_n698 +end + +def fun_l26_n120() + fun_l27_n669 +end + +def fun_l26_n121() + fun_l27_n52 +end + +def fun_l26_n122() + fun_l27_n485 +end + +def fun_l26_n123() + fun_l27_n468 +end + +def fun_l26_n124() + fun_l27_n340 +end + +def fun_l26_n125() + fun_l27_n414 +end + +def fun_l26_n126() + fun_l27_n994 +end + +def fun_l26_n127() + fun_l27_n601 +end + +def fun_l26_n128() + fun_l27_n679 +end + +def fun_l26_n129() + fun_l27_n720 +end + +def fun_l26_n130() + fun_l27_n66 +end + +def fun_l26_n131() + fun_l27_n921 +end + +def fun_l26_n132() + fun_l27_n385 +end + +def fun_l26_n133() + fun_l27_n88 +end + +def fun_l26_n134() + fun_l27_n164 +end + +def fun_l26_n135() + fun_l27_n269 +end + +def fun_l26_n136() + fun_l27_n371 +end + +def fun_l26_n137() + fun_l27_n786 +end + +def fun_l26_n138() + fun_l27_n464 +end + +def fun_l26_n139() + fun_l27_n96 +end + +def fun_l26_n140() + fun_l27_n494 +end + +def fun_l26_n141() + fun_l27_n341 +end + +def fun_l26_n142() + fun_l27_n646 +end + +def fun_l26_n143() + fun_l27_n959 +end + +def fun_l26_n144() + fun_l27_n645 +end + +def fun_l26_n145() + fun_l27_n825 +end + +def fun_l26_n146() + fun_l27_n416 +end + +def fun_l26_n147() + fun_l27_n994 +end + +def fun_l26_n148() + fun_l27_n875 +end + +def fun_l26_n149() + fun_l27_n406 +end + +def fun_l26_n150() + fun_l27_n857 +end + +def fun_l26_n151() + fun_l27_n348 +end + +def fun_l26_n152() + fun_l27_n611 +end + +def fun_l26_n153() + fun_l27_n831 +end + +def fun_l26_n154() + fun_l27_n412 +end + +def fun_l26_n155() + fun_l27_n530 +end + +def fun_l26_n156() + fun_l27_n892 +end + +def fun_l26_n157() + fun_l27_n70 +end + +def fun_l26_n158() + fun_l27_n756 +end + +def fun_l26_n159() + fun_l27_n587 +end + +def fun_l26_n160() + fun_l27_n796 +end + +def fun_l26_n161() + fun_l27_n470 +end + +def fun_l26_n162() + fun_l27_n290 +end + +def fun_l26_n163() + fun_l27_n723 +end + +def fun_l26_n164() + fun_l27_n660 +end + +def fun_l26_n165() + fun_l27_n0 +end + +def fun_l26_n166() + fun_l27_n223 +end + +def fun_l26_n167() + fun_l27_n341 +end + +def fun_l26_n168() + fun_l27_n128 +end + +def fun_l26_n169() + fun_l27_n367 +end + +def fun_l26_n170() + fun_l27_n487 +end + +def fun_l26_n171() + fun_l27_n574 +end + +def fun_l26_n172() + fun_l27_n437 +end + +def fun_l26_n173() + fun_l27_n182 +end + +def fun_l26_n174() + fun_l27_n607 +end + +def fun_l26_n175() + fun_l27_n252 +end + +def fun_l26_n176() + fun_l27_n996 +end + +def fun_l26_n177() + fun_l27_n904 +end + +def fun_l26_n178() + fun_l27_n505 +end + +def fun_l26_n179() + fun_l27_n425 +end + +def fun_l26_n180() + fun_l27_n610 +end + +def fun_l26_n181() + fun_l27_n734 +end + +def fun_l26_n182() + fun_l27_n427 +end + +def fun_l26_n183() + fun_l27_n918 +end + +def fun_l26_n184() + fun_l27_n376 +end + +def fun_l26_n185() + fun_l27_n445 +end + +def fun_l26_n186() + fun_l27_n227 +end + +def fun_l26_n187() + fun_l27_n129 +end + +def fun_l26_n188() + fun_l27_n139 +end + +def fun_l26_n189() + fun_l27_n142 +end + +def fun_l26_n190() + fun_l27_n388 +end + +def fun_l26_n191() + fun_l27_n24 +end + +def fun_l26_n192() + fun_l27_n369 +end + +def fun_l26_n193() + fun_l27_n984 +end + +def fun_l26_n194() + fun_l27_n342 +end + +def fun_l26_n195() + fun_l27_n722 +end + +def fun_l26_n196() + fun_l27_n846 +end + +def fun_l26_n197() + fun_l27_n59 +end + +def fun_l26_n198() + fun_l27_n471 +end + +def fun_l26_n199() + fun_l27_n626 +end + +def fun_l26_n200() + fun_l27_n973 +end + +def fun_l26_n201() + fun_l27_n525 +end + +def fun_l26_n202() + fun_l27_n412 +end + +def fun_l26_n203() + fun_l27_n284 +end + +def fun_l26_n204() + fun_l27_n383 +end + +def fun_l26_n205() + fun_l27_n414 +end + +def fun_l26_n206() + fun_l27_n448 +end + +def fun_l26_n207() + fun_l27_n795 +end + +def fun_l26_n208() + fun_l27_n708 +end + +def fun_l26_n209() + fun_l27_n318 +end + +def fun_l26_n210() + fun_l27_n284 +end + +def fun_l26_n211() + fun_l27_n100 +end + +def fun_l26_n212() + fun_l27_n702 +end + +def fun_l26_n213() + fun_l27_n611 +end + +def fun_l26_n214() + fun_l27_n106 +end + +def fun_l26_n215() + fun_l27_n667 +end + +def fun_l26_n216() + fun_l27_n822 +end + +def fun_l26_n217() + fun_l27_n502 +end + +def fun_l26_n218() + fun_l27_n284 +end + +def fun_l26_n219() + fun_l27_n472 +end + +def fun_l26_n220() + fun_l27_n907 +end + +def fun_l26_n221() + fun_l27_n115 +end + +def fun_l26_n222() + fun_l27_n6 +end + +def fun_l26_n223() + fun_l27_n872 +end + +def fun_l26_n224() + fun_l27_n145 +end + +def fun_l26_n225() + fun_l27_n63 +end + +def fun_l26_n226() + fun_l27_n295 +end + +def fun_l26_n227() + fun_l27_n160 +end + +def fun_l26_n228() + fun_l27_n72 +end + +def fun_l26_n229() + fun_l27_n750 +end + +def fun_l26_n230() + fun_l27_n386 +end + +def fun_l26_n231() + fun_l27_n110 +end + +def fun_l26_n232() + fun_l27_n497 +end + +def fun_l26_n233() + fun_l27_n586 +end + +def fun_l26_n234() + fun_l27_n435 +end + +def fun_l26_n235() + fun_l27_n849 +end + +def fun_l26_n236() + fun_l27_n47 +end + +def fun_l26_n237() + fun_l27_n673 +end + +def fun_l26_n238() + fun_l27_n435 +end + +def fun_l26_n239() + fun_l27_n295 +end + +def fun_l26_n240() + fun_l27_n466 +end + +def fun_l26_n241() + fun_l27_n76 +end + +def fun_l26_n242() + fun_l27_n679 +end + +def fun_l26_n243() + fun_l27_n772 +end + +def fun_l26_n244() + fun_l27_n137 +end + +def fun_l26_n245() + fun_l27_n582 +end + +def fun_l26_n246() + fun_l27_n344 +end + +def fun_l26_n247() + fun_l27_n944 +end + +def fun_l26_n248() + fun_l27_n657 +end + +def fun_l26_n249() + fun_l27_n354 +end + +def fun_l26_n250() + fun_l27_n467 +end + +def fun_l26_n251() + fun_l27_n436 +end + +def fun_l26_n252() + fun_l27_n923 +end + +def fun_l26_n253() + fun_l27_n252 +end + +def fun_l26_n254() + fun_l27_n404 +end + +def fun_l26_n255() + fun_l27_n421 +end + +def fun_l26_n256() + fun_l27_n422 +end + +def fun_l26_n257() + fun_l27_n787 +end + +def fun_l26_n258() + fun_l27_n173 +end + +def fun_l26_n259() + fun_l27_n930 +end + +def fun_l26_n260() + fun_l27_n625 +end + +def fun_l26_n261() + fun_l27_n18 +end + +def fun_l26_n262() + fun_l27_n763 +end + +def fun_l26_n263() + fun_l27_n641 +end + +def fun_l26_n264() + fun_l27_n114 +end + +def fun_l26_n265() + fun_l27_n556 +end + +def fun_l26_n266() + fun_l27_n127 +end + +def fun_l26_n267() + fun_l27_n229 +end + +def fun_l26_n268() + fun_l27_n901 +end + +def fun_l26_n269() + fun_l27_n234 +end + +def fun_l26_n270() + fun_l27_n444 +end + +def fun_l26_n271() + fun_l27_n156 +end + +def fun_l26_n272() + fun_l27_n35 +end + +def fun_l26_n273() + fun_l27_n725 +end + +def fun_l26_n274() + fun_l27_n983 +end + +def fun_l26_n275() + fun_l27_n845 +end + +def fun_l26_n276() + fun_l27_n324 +end + +def fun_l26_n277() + fun_l27_n813 +end + +def fun_l26_n278() + fun_l27_n331 +end + +def fun_l26_n279() + fun_l27_n66 +end + +def fun_l26_n280() + fun_l27_n471 +end + +def fun_l26_n281() + fun_l27_n635 +end + +def fun_l26_n282() + fun_l27_n180 +end + +def fun_l26_n283() + fun_l27_n563 +end + +def fun_l26_n284() + fun_l27_n199 +end + +def fun_l26_n285() + fun_l27_n238 +end + +def fun_l26_n286() + fun_l27_n789 +end + +def fun_l26_n287() + fun_l27_n413 +end + +def fun_l26_n288() + fun_l27_n358 +end + +def fun_l26_n289() + fun_l27_n923 +end + +def fun_l26_n290() + fun_l27_n443 +end + +def fun_l26_n291() + fun_l27_n706 +end + +def fun_l26_n292() + fun_l27_n752 +end + +def fun_l26_n293() + fun_l27_n231 +end + +def fun_l26_n294() + fun_l27_n185 +end + +def fun_l26_n295() + fun_l27_n604 +end + +def fun_l26_n296() + fun_l27_n10 +end + +def fun_l26_n297() + fun_l27_n758 +end + +def fun_l26_n298() + fun_l27_n417 +end + +def fun_l26_n299() + fun_l27_n303 +end + +def fun_l26_n300() + fun_l27_n524 +end + +def fun_l26_n301() + fun_l27_n198 +end + +def fun_l26_n302() + fun_l27_n127 +end + +def fun_l26_n303() + fun_l27_n971 +end + +def fun_l26_n304() + fun_l27_n4 +end + +def fun_l26_n305() + fun_l27_n333 +end + +def fun_l26_n306() + fun_l27_n782 +end + +def fun_l26_n307() + fun_l27_n158 +end + +def fun_l26_n308() + fun_l27_n414 +end + +def fun_l26_n309() + fun_l27_n730 +end + +def fun_l26_n310() + fun_l27_n912 +end + +def fun_l26_n311() + fun_l27_n343 +end + +def fun_l26_n312() + fun_l27_n885 +end + +def fun_l26_n313() + fun_l27_n682 +end + +def fun_l26_n314() + fun_l27_n126 +end + +def fun_l26_n315() + fun_l27_n680 +end + +def fun_l26_n316() + fun_l27_n884 +end + +def fun_l26_n317() + fun_l27_n483 +end + +def fun_l26_n318() + fun_l27_n601 +end + +def fun_l26_n319() + fun_l27_n265 +end + +def fun_l26_n320() + fun_l27_n109 +end + +def fun_l26_n321() + fun_l27_n436 +end + +def fun_l26_n322() + fun_l27_n209 +end + +def fun_l26_n323() + fun_l27_n669 +end + +def fun_l26_n324() + fun_l27_n680 +end + +def fun_l26_n325() + fun_l27_n844 +end + +def fun_l26_n326() + fun_l27_n729 +end + +def fun_l26_n327() + fun_l27_n882 +end + +def fun_l26_n328() + fun_l27_n99 +end + +def fun_l26_n329() + fun_l27_n586 +end + +def fun_l26_n330() + fun_l27_n328 +end + +def fun_l26_n331() + fun_l27_n694 +end + +def fun_l26_n332() + fun_l27_n259 +end + +def fun_l26_n333() + fun_l27_n364 +end + +def fun_l26_n334() + fun_l27_n944 +end + +def fun_l26_n335() + fun_l27_n483 +end + +def fun_l26_n336() + fun_l27_n570 +end + +def fun_l26_n337() + fun_l27_n348 +end + +def fun_l26_n338() + fun_l27_n565 +end + +def fun_l26_n339() + fun_l27_n402 +end + +def fun_l26_n340() + fun_l27_n890 +end + +def fun_l26_n341() + fun_l27_n486 +end + +def fun_l26_n342() + fun_l27_n387 +end + +def fun_l26_n343() + fun_l27_n239 +end + +def fun_l26_n344() + fun_l27_n433 +end + +def fun_l26_n345() + fun_l27_n918 +end + +def fun_l26_n346() + fun_l27_n524 +end + +def fun_l26_n347() + fun_l27_n475 +end + +def fun_l26_n348() + fun_l27_n749 +end + +def fun_l26_n349() + fun_l27_n61 +end + +def fun_l26_n350() + fun_l27_n735 +end + +def fun_l26_n351() + fun_l27_n582 +end + +def fun_l26_n352() + fun_l27_n519 +end + +def fun_l26_n353() + fun_l27_n234 +end + +def fun_l26_n354() + fun_l27_n868 +end + +def fun_l26_n355() + fun_l27_n109 +end + +def fun_l26_n356() + fun_l27_n898 +end + +def fun_l26_n357() + fun_l27_n541 +end + +def fun_l26_n358() + fun_l27_n328 +end + +def fun_l26_n359() + fun_l27_n954 +end + +def fun_l26_n360() + fun_l27_n219 +end + +def fun_l26_n361() + fun_l27_n776 +end + +def fun_l26_n362() + fun_l27_n402 +end + +def fun_l26_n363() + fun_l27_n169 +end + +def fun_l26_n364() + fun_l27_n395 +end + +def fun_l26_n365() + fun_l27_n852 +end + +def fun_l26_n366() + fun_l27_n668 +end + +def fun_l26_n367() + fun_l27_n0 +end + +def fun_l26_n368() + fun_l27_n660 +end + +def fun_l26_n369() + fun_l27_n703 +end + +def fun_l26_n370() + fun_l27_n946 +end + +def fun_l26_n371() + fun_l27_n522 +end + +def fun_l26_n372() + fun_l27_n57 +end + +def fun_l26_n373() + fun_l27_n228 +end + +def fun_l26_n374() + fun_l27_n25 +end + +def fun_l26_n375() + fun_l27_n433 +end + +def fun_l26_n376() + fun_l27_n557 +end + +def fun_l26_n377() + fun_l27_n542 +end + +def fun_l26_n378() + fun_l27_n341 +end + +def fun_l26_n379() + fun_l27_n28 +end + +def fun_l26_n380() + fun_l27_n591 +end + +def fun_l26_n381() + fun_l27_n139 +end + +def fun_l26_n382() + fun_l27_n303 +end + +def fun_l26_n383() + fun_l27_n369 +end + +def fun_l26_n384() + fun_l27_n124 +end + +def fun_l26_n385() + fun_l27_n459 +end + +def fun_l26_n386() + fun_l27_n338 +end + +def fun_l26_n387() + fun_l27_n246 +end + +def fun_l26_n388() + fun_l27_n248 +end + +def fun_l26_n389() + fun_l27_n182 +end + +def fun_l26_n390() + fun_l27_n176 +end + +def fun_l26_n391() + fun_l27_n307 +end + +def fun_l26_n392() + fun_l27_n782 +end + +def fun_l26_n393() + fun_l27_n576 +end + +def fun_l26_n394() + fun_l27_n777 +end + +def fun_l26_n395() + fun_l27_n962 +end + +def fun_l26_n396() + fun_l27_n993 +end + +def fun_l26_n397() + fun_l27_n592 +end + +def fun_l26_n398() + fun_l27_n710 +end + +def fun_l26_n399() + fun_l27_n644 +end + +def fun_l26_n400() + fun_l27_n11 +end + +def fun_l26_n401() + fun_l27_n774 +end + +def fun_l26_n402() + fun_l27_n190 +end + +def fun_l26_n403() + fun_l27_n15 +end + +def fun_l26_n404() + fun_l27_n47 +end + +def fun_l26_n405() + fun_l27_n802 +end + +def fun_l26_n406() + fun_l27_n659 +end + +def fun_l26_n407() + fun_l27_n295 +end + +def fun_l26_n408() + fun_l27_n120 +end + +def fun_l26_n409() + fun_l27_n438 +end + +def fun_l26_n410() + fun_l27_n443 +end + +def fun_l26_n411() + fun_l27_n860 +end + +def fun_l26_n412() + fun_l27_n285 +end + +def fun_l26_n413() + fun_l27_n457 +end + +def fun_l26_n414() + fun_l27_n942 +end + +def fun_l26_n415() + fun_l27_n425 +end + +def fun_l26_n416() + fun_l27_n54 +end + +def fun_l26_n417() + fun_l27_n675 +end + +def fun_l26_n418() + fun_l27_n739 +end + +def fun_l26_n419() + fun_l27_n709 +end + +def fun_l26_n420() + fun_l27_n643 +end + +def fun_l26_n421() + fun_l27_n473 +end + +def fun_l26_n422() + fun_l27_n452 +end + +def fun_l26_n423() + fun_l27_n942 +end + +def fun_l26_n424() + fun_l27_n270 +end + +def fun_l26_n425() + fun_l27_n711 +end + +def fun_l26_n426() + fun_l27_n27 +end + +def fun_l26_n427() + fun_l27_n120 +end + +def fun_l26_n428() + fun_l27_n565 +end + +def fun_l26_n429() + fun_l27_n182 +end + +def fun_l26_n430() + fun_l27_n641 +end + +def fun_l26_n431() + fun_l27_n227 +end + +def fun_l26_n432() + fun_l27_n59 +end + +def fun_l26_n433() + fun_l27_n599 +end + +def fun_l26_n434() + fun_l27_n448 +end + +def fun_l26_n435() + fun_l27_n562 +end + +def fun_l26_n436() + fun_l27_n201 +end + +def fun_l26_n437() + fun_l27_n929 +end + +def fun_l26_n438() + fun_l27_n275 +end + +def fun_l26_n439() + fun_l27_n339 +end + +def fun_l26_n440() + fun_l27_n519 +end + +def fun_l26_n441() + fun_l27_n98 +end + +def fun_l26_n442() + fun_l27_n581 +end + +def fun_l26_n443() + fun_l27_n840 +end + +def fun_l26_n444() + fun_l27_n904 +end + +def fun_l26_n445() + fun_l27_n468 +end + +def fun_l26_n446() + fun_l27_n6 +end + +def fun_l26_n447() + fun_l27_n877 +end + +def fun_l26_n448() + fun_l27_n609 +end + +def fun_l26_n449() + fun_l27_n218 +end + +def fun_l26_n450() + fun_l27_n869 +end + +def fun_l26_n451() + fun_l27_n184 +end + +def fun_l26_n452() + fun_l27_n7 +end + +def fun_l26_n453() + fun_l27_n647 +end + +def fun_l26_n454() + fun_l27_n470 +end + +def fun_l26_n455() + fun_l27_n547 +end + +def fun_l26_n456() + fun_l27_n277 +end + +def fun_l26_n457() + fun_l27_n302 +end + +def fun_l26_n458() + fun_l27_n355 +end + +def fun_l26_n459() + fun_l27_n805 +end + +def fun_l26_n460() + fun_l27_n201 +end + +def fun_l26_n461() + fun_l27_n16 +end + +def fun_l26_n462() + fun_l27_n156 +end + +def fun_l26_n463() + fun_l27_n219 +end + +def fun_l26_n464() + fun_l27_n507 +end + +def fun_l26_n465() + fun_l27_n527 +end + +def fun_l26_n466() + fun_l27_n307 +end + +def fun_l26_n467() + fun_l27_n654 +end + +def fun_l26_n468() + fun_l27_n699 +end + +def fun_l26_n469() + fun_l27_n772 +end + +def fun_l26_n470() + fun_l27_n761 +end + +def fun_l26_n471() + fun_l27_n736 +end + +def fun_l26_n472() + fun_l27_n104 +end + +def fun_l26_n473() + fun_l27_n720 +end + +def fun_l26_n474() + fun_l27_n418 +end + +def fun_l26_n475() + fun_l27_n403 +end + +def fun_l26_n476() + fun_l27_n625 +end + +def fun_l26_n477() + fun_l27_n541 +end + +def fun_l26_n478() + fun_l27_n441 +end + +def fun_l26_n479() + fun_l27_n287 +end + +def fun_l26_n480() + fun_l27_n746 +end + +def fun_l26_n481() + fun_l27_n205 +end + +def fun_l26_n482() + fun_l27_n771 +end + +def fun_l26_n483() + fun_l27_n778 +end + +def fun_l26_n484() + fun_l27_n284 +end + +def fun_l26_n485() + fun_l27_n475 +end + +def fun_l26_n486() + fun_l27_n449 +end + +def fun_l26_n487() + fun_l27_n485 +end + +def fun_l26_n488() + fun_l27_n124 +end + +def fun_l26_n489() + fun_l27_n4 +end + +def fun_l26_n490() + fun_l27_n270 +end + +def fun_l26_n491() + fun_l27_n596 +end + +def fun_l26_n492() + fun_l27_n279 +end + +def fun_l26_n493() + fun_l27_n226 +end + +def fun_l26_n494() + fun_l27_n718 +end + +def fun_l26_n495() + fun_l27_n324 +end + +def fun_l26_n496() + fun_l27_n430 +end + +def fun_l26_n497() + fun_l27_n196 +end + +def fun_l26_n498() + fun_l27_n509 +end + +def fun_l26_n499() + fun_l27_n282 +end + +def fun_l26_n500() + fun_l27_n61 +end + +def fun_l26_n501() + fun_l27_n995 +end + +def fun_l26_n502() + fun_l27_n75 +end + +def fun_l26_n503() + fun_l27_n158 +end + +def fun_l26_n504() + fun_l27_n551 +end + +def fun_l26_n505() + fun_l27_n936 +end + +def fun_l26_n506() + fun_l27_n23 +end + +def fun_l26_n507() + fun_l27_n799 +end + +def fun_l26_n508() + fun_l27_n25 +end + +def fun_l26_n509() + fun_l27_n533 +end + +def fun_l26_n510() + fun_l27_n325 +end + +def fun_l26_n511() + fun_l27_n375 +end + +def fun_l26_n512() + fun_l27_n18 +end + +def fun_l26_n513() + fun_l27_n497 +end + +def fun_l26_n514() + fun_l27_n51 +end + +def fun_l26_n515() + fun_l27_n680 +end + +def fun_l26_n516() + fun_l27_n152 +end + +def fun_l26_n517() + fun_l27_n495 +end + +def fun_l26_n518() + fun_l27_n956 +end + +def fun_l26_n519() + fun_l27_n187 +end + +def fun_l26_n520() + fun_l27_n292 +end + +def fun_l26_n521() + fun_l27_n663 +end + +def fun_l26_n522() + fun_l27_n178 +end + +def fun_l26_n523() + fun_l27_n323 +end + +def fun_l26_n524() + fun_l27_n222 +end + +def fun_l26_n525() + fun_l27_n652 +end + +def fun_l26_n526() + fun_l27_n519 +end + +def fun_l26_n527() + fun_l27_n102 +end + +def fun_l26_n528() + fun_l27_n361 +end + +def fun_l26_n529() + fun_l27_n201 +end + +def fun_l26_n530() + fun_l27_n129 +end + +def fun_l26_n531() + fun_l27_n438 +end + +def fun_l26_n532() + fun_l27_n387 +end + +def fun_l26_n533() + fun_l27_n641 +end + +def fun_l26_n534() + fun_l27_n111 +end + +def fun_l26_n535() + fun_l27_n548 +end + +def fun_l26_n536() + fun_l27_n446 +end + +def fun_l26_n537() + fun_l27_n302 +end + +def fun_l26_n538() + fun_l27_n438 +end + +def fun_l26_n539() + fun_l27_n816 +end + +def fun_l26_n540() + fun_l27_n759 +end + +def fun_l26_n541() + fun_l27_n318 +end + +def fun_l26_n542() + fun_l27_n895 +end + +def fun_l26_n543() + fun_l27_n309 +end + +def fun_l26_n544() + fun_l27_n35 +end + +def fun_l26_n545() + fun_l27_n785 +end + +def fun_l26_n546() + fun_l27_n846 +end + +def fun_l26_n547() + fun_l27_n191 +end + +def fun_l26_n548() + fun_l27_n414 +end + +def fun_l26_n549() + fun_l27_n251 +end + +def fun_l26_n550() + fun_l27_n982 +end + +def fun_l26_n551() + fun_l27_n516 +end + +def fun_l26_n552() + fun_l27_n724 +end + +def fun_l26_n553() + fun_l27_n473 +end + +def fun_l26_n554() + fun_l27_n808 +end + +def fun_l26_n555() + fun_l27_n617 +end + +def fun_l26_n556() + fun_l27_n306 +end + +def fun_l26_n557() + fun_l27_n701 +end + +def fun_l26_n558() + fun_l27_n941 +end + +def fun_l26_n559() + fun_l27_n60 +end + +def fun_l26_n560() + fun_l27_n132 +end + +def fun_l26_n561() + fun_l27_n685 +end + +def fun_l26_n562() + fun_l27_n619 +end + +def fun_l26_n563() + fun_l27_n407 +end + +def fun_l26_n564() + fun_l27_n29 +end + +def fun_l26_n565() + fun_l27_n53 +end + +def fun_l26_n566() + fun_l27_n267 +end + +def fun_l26_n567() + fun_l27_n79 +end + +def fun_l26_n568() + fun_l27_n170 +end + +def fun_l26_n569() + fun_l27_n469 +end + +def fun_l26_n570() + fun_l27_n67 +end + +def fun_l26_n571() + fun_l27_n794 +end + +def fun_l26_n572() + fun_l27_n641 +end + +def fun_l26_n573() + fun_l27_n224 +end + +def fun_l26_n574() + fun_l27_n415 +end + +def fun_l26_n575() + fun_l27_n235 +end + +def fun_l26_n576() + fun_l27_n425 +end + +def fun_l26_n577() + fun_l27_n335 +end + +def fun_l26_n578() + fun_l27_n251 +end + +def fun_l26_n579() + fun_l27_n421 +end + +def fun_l26_n580() + fun_l27_n20 +end + +def fun_l26_n581() + fun_l27_n795 +end + +def fun_l26_n582() + fun_l27_n831 +end + +def fun_l26_n583() + fun_l27_n666 +end + +def fun_l26_n584() + fun_l27_n664 +end + +def fun_l26_n585() + fun_l27_n383 +end + +def fun_l26_n586() + fun_l27_n587 +end + +def fun_l26_n587() + fun_l27_n515 +end + +def fun_l26_n588() + fun_l27_n410 +end + +def fun_l26_n589() + fun_l27_n379 +end + +def fun_l26_n590() + fun_l27_n467 +end + +def fun_l26_n591() + fun_l27_n557 +end + +def fun_l26_n592() + fun_l27_n444 +end + +def fun_l26_n593() + fun_l27_n629 +end + +def fun_l26_n594() + fun_l27_n55 +end + +def fun_l26_n595() + fun_l27_n581 +end + +def fun_l26_n596() + fun_l27_n106 +end + +def fun_l26_n597() + fun_l27_n896 +end + +def fun_l26_n598() + fun_l27_n180 +end + +def fun_l26_n599() + fun_l27_n471 +end + +def fun_l26_n600() + fun_l27_n28 +end + +def fun_l26_n601() + fun_l27_n195 +end + +def fun_l26_n602() + fun_l27_n562 +end + +def fun_l26_n603() + fun_l27_n367 +end + +def fun_l26_n604() + fun_l27_n609 +end + +def fun_l26_n605() + fun_l27_n699 +end + +def fun_l26_n606() + fun_l27_n300 +end + +def fun_l26_n607() + fun_l27_n28 +end + +def fun_l26_n608() + fun_l27_n362 +end + +def fun_l26_n609() + fun_l27_n188 +end + +def fun_l26_n610() + fun_l27_n320 +end + +def fun_l26_n611() + fun_l27_n974 +end + +def fun_l26_n612() + fun_l27_n226 +end + +def fun_l26_n613() + fun_l27_n723 +end + +def fun_l26_n614() + fun_l27_n406 +end + +def fun_l26_n615() + fun_l27_n60 +end + +def fun_l26_n616() + fun_l27_n921 +end + +def fun_l26_n617() + fun_l27_n141 +end + +def fun_l26_n618() + fun_l27_n781 +end + +def fun_l26_n619() + fun_l27_n279 +end + +def fun_l26_n620() + fun_l27_n159 +end + +def fun_l26_n621() + fun_l27_n396 +end + +def fun_l26_n622() + fun_l27_n365 +end + +def fun_l26_n623() + fun_l27_n128 +end + +def fun_l26_n624() + fun_l27_n143 +end + +def fun_l26_n625() + fun_l27_n553 +end + +def fun_l26_n626() + fun_l27_n695 +end + +def fun_l26_n627() + fun_l27_n526 +end + +def fun_l26_n628() + fun_l27_n623 +end + +def fun_l26_n629() + fun_l27_n589 +end + +def fun_l26_n630() + fun_l27_n328 +end + +def fun_l26_n631() + fun_l27_n959 +end + +def fun_l26_n632() + fun_l27_n586 +end + +def fun_l26_n633() + fun_l27_n163 +end + +def fun_l26_n634() + fun_l27_n821 +end + +def fun_l26_n635() + fun_l27_n981 +end + +def fun_l26_n636() + fun_l27_n221 +end + +def fun_l26_n637() + fun_l27_n752 +end + +def fun_l26_n638() + fun_l27_n252 +end + +def fun_l26_n639() + fun_l27_n74 +end + +def fun_l26_n640() + fun_l27_n694 +end + +def fun_l26_n641() + fun_l27_n761 +end + +def fun_l26_n642() + fun_l27_n877 +end + +def fun_l26_n643() + fun_l27_n480 +end + +def fun_l26_n644() + fun_l27_n627 +end + +def fun_l26_n645() + fun_l27_n586 +end + +def fun_l26_n646() + fun_l27_n820 +end + +def fun_l26_n647() + fun_l27_n485 +end + +def fun_l26_n648() + fun_l27_n230 +end + +def fun_l26_n649() + fun_l27_n698 +end + +def fun_l26_n650() + fun_l27_n700 +end + +def fun_l26_n651() + fun_l27_n536 +end + +def fun_l26_n652() + fun_l27_n343 +end + +def fun_l26_n653() + fun_l27_n453 +end + +def fun_l26_n654() + fun_l27_n780 +end + +def fun_l26_n655() + fun_l27_n402 +end + +def fun_l26_n656() + fun_l27_n749 +end + +def fun_l26_n657() + fun_l27_n248 +end + +def fun_l26_n658() + fun_l27_n326 +end + +def fun_l26_n659() + fun_l27_n819 +end + +def fun_l26_n660() + fun_l27_n968 +end + +def fun_l26_n661() + fun_l27_n123 +end + +def fun_l26_n662() + fun_l27_n467 +end + +def fun_l26_n663() + fun_l27_n855 +end + +def fun_l26_n664() + fun_l27_n861 +end + +def fun_l26_n665() + fun_l27_n335 +end + +def fun_l26_n666() + fun_l27_n805 +end + +def fun_l26_n667() + fun_l27_n284 +end + +def fun_l26_n668() + fun_l27_n283 +end + +def fun_l26_n669() + fun_l27_n471 +end + +def fun_l26_n670() + fun_l27_n479 +end + +def fun_l26_n671() + fun_l27_n938 +end + +def fun_l26_n672() + fun_l27_n288 +end + +def fun_l26_n673() + fun_l27_n0 +end + +def fun_l26_n674() + fun_l27_n856 +end + +def fun_l26_n675() + fun_l27_n490 +end + +def fun_l26_n676() + fun_l27_n88 +end + +def fun_l26_n677() + fun_l27_n584 +end + +def fun_l26_n678() + fun_l27_n138 +end + +def fun_l26_n679() + fun_l27_n998 +end + +def fun_l26_n680() + fun_l27_n259 +end + +def fun_l26_n681() + fun_l27_n913 +end + +def fun_l26_n682() + fun_l27_n697 +end + +def fun_l26_n683() + fun_l27_n102 +end + +def fun_l26_n684() + fun_l27_n726 +end + +def fun_l26_n685() + fun_l27_n655 +end + +def fun_l26_n686() + fun_l27_n264 +end + +def fun_l26_n687() + fun_l27_n603 +end + +def fun_l26_n688() + fun_l27_n331 +end + +def fun_l26_n689() + fun_l27_n760 +end + +def fun_l26_n690() + fun_l27_n105 +end + +def fun_l26_n691() + fun_l27_n554 +end + +def fun_l26_n692() + fun_l27_n287 +end + +def fun_l26_n693() + fun_l27_n592 +end + +def fun_l26_n694() + fun_l27_n22 +end + +def fun_l26_n695() + fun_l27_n794 +end + +def fun_l26_n696() + fun_l27_n196 +end + +def fun_l26_n697() + fun_l27_n848 +end + +def fun_l26_n698() + fun_l27_n589 +end + +def fun_l26_n699() + fun_l27_n267 +end + +def fun_l26_n700() + fun_l27_n562 +end + +def fun_l26_n701() + fun_l27_n563 +end + +def fun_l26_n702() + fun_l27_n909 +end + +def fun_l26_n703() + fun_l27_n92 +end + +def fun_l26_n704() + fun_l27_n140 +end + +def fun_l26_n705() + fun_l27_n330 +end + +def fun_l26_n706() + fun_l27_n734 +end + +def fun_l26_n707() + fun_l27_n994 +end + +def fun_l26_n708() + fun_l27_n414 +end + +def fun_l26_n709() + fun_l27_n931 +end + +def fun_l26_n710() + fun_l27_n82 +end + +def fun_l26_n711() + fun_l27_n341 +end + +def fun_l26_n712() + fun_l27_n9 +end + +def fun_l26_n713() + fun_l27_n868 +end + +def fun_l26_n714() + fun_l27_n249 +end + +def fun_l26_n715() + fun_l27_n393 +end + +def fun_l26_n716() + fun_l27_n835 +end + +def fun_l26_n717() + fun_l27_n975 +end + +def fun_l26_n718() + fun_l27_n110 +end + +def fun_l26_n719() + fun_l27_n700 +end + +def fun_l26_n720() + fun_l27_n396 +end + +def fun_l26_n721() + fun_l27_n973 +end + +def fun_l26_n722() + fun_l27_n898 +end + +def fun_l26_n723() + fun_l27_n418 +end + +def fun_l26_n724() + fun_l27_n342 +end + +def fun_l26_n725() + fun_l27_n783 +end + +def fun_l26_n726() + fun_l27_n86 +end + +def fun_l26_n727() + fun_l27_n556 +end + +def fun_l26_n728() + fun_l27_n777 +end + +def fun_l26_n729() + fun_l27_n729 +end + +def fun_l26_n730() + fun_l27_n156 +end + +def fun_l26_n731() + fun_l27_n458 +end + +def fun_l26_n732() + fun_l27_n580 +end + +def fun_l26_n733() + fun_l27_n764 +end + +def fun_l26_n734() + fun_l27_n295 +end + +def fun_l26_n735() + fun_l27_n850 +end + +def fun_l26_n736() + fun_l27_n881 +end + +def fun_l26_n737() + fun_l27_n416 +end + +def fun_l26_n738() + fun_l27_n996 +end + +def fun_l26_n739() + fun_l27_n347 +end + +def fun_l26_n740() + fun_l27_n607 +end + +def fun_l26_n741() + fun_l27_n749 +end + +def fun_l26_n742() + fun_l27_n564 +end + +def fun_l26_n743() + fun_l27_n217 +end + +def fun_l26_n744() + fun_l27_n375 +end + +def fun_l26_n745() + fun_l27_n487 +end + +def fun_l26_n746() + fun_l27_n86 +end + +def fun_l26_n747() + fun_l27_n765 +end + +def fun_l26_n748() + fun_l27_n569 +end + +def fun_l26_n749() + fun_l27_n461 +end + +def fun_l26_n750() + fun_l27_n633 +end + +def fun_l26_n751() + fun_l27_n89 +end + +def fun_l26_n752() + fun_l27_n841 +end + +def fun_l26_n753() + fun_l27_n499 +end + +def fun_l26_n754() + fun_l27_n947 +end + +def fun_l26_n755() + fun_l27_n690 +end + +def fun_l26_n756() + fun_l27_n531 +end + +def fun_l26_n757() + fun_l27_n766 +end + +def fun_l26_n758() + fun_l27_n853 +end + +def fun_l26_n759() + fun_l27_n65 +end + +def fun_l26_n760() + fun_l27_n884 +end + +def fun_l26_n761() + fun_l27_n235 +end + +def fun_l26_n762() + fun_l27_n39 +end + +def fun_l26_n763() + fun_l27_n868 +end + +def fun_l26_n764() + fun_l27_n202 +end + +def fun_l26_n765() + fun_l27_n360 +end + +def fun_l26_n766() + fun_l27_n450 +end + +def fun_l26_n767() + fun_l27_n590 +end + +def fun_l26_n768() + fun_l27_n635 +end + +def fun_l26_n769() + fun_l27_n314 +end + +def fun_l26_n770() + fun_l27_n68 +end + +def fun_l26_n771() + fun_l27_n858 +end + +def fun_l26_n772() + fun_l27_n51 +end + +def fun_l26_n773() + fun_l27_n524 +end + +def fun_l26_n774() + fun_l27_n13 +end + +def fun_l26_n775() + fun_l27_n451 +end + +def fun_l26_n776() + fun_l27_n682 +end + +def fun_l26_n777() + fun_l27_n736 +end + +def fun_l26_n778() + fun_l27_n250 +end + +def fun_l26_n779() + fun_l27_n810 +end + +def fun_l26_n780() + fun_l27_n979 +end + +def fun_l26_n781() + fun_l27_n102 +end + +def fun_l26_n782() + fun_l27_n955 +end + +def fun_l26_n783() + fun_l27_n610 +end + +def fun_l26_n784() + fun_l27_n301 +end + +def fun_l26_n785() + fun_l27_n389 +end + +def fun_l26_n786() + fun_l27_n754 +end + +def fun_l26_n787() + fun_l27_n717 +end + +def fun_l26_n788() + fun_l27_n77 +end + +def fun_l26_n789() + fun_l27_n401 +end + +def fun_l26_n790() + fun_l27_n430 +end + +def fun_l26_n791() + fun_l27_n310 +end + +def fun_l26_n792() + fun_l27_n839 +end + +def fun_l26_n793() + fun_l27_n682 +end + +def fun_l26_n794() + fun_l27_n648 +end + +def fun_l26_n795() + fun_l27_n281 +end + +def fun_l26_n796() + fun_l27_n749 +end + +def fun_l26_n797() + fun_l27_n502 +end + +def fun_l26_n798() + fun_l27_n201 +end + +def fun_l26_n799() + fun_l27_n851 +end + +def fun_l26_n800() + fun_l27_n249 +end + +def fun_l26_n801() + fun_l27_n119 +end + +def fun_l26_n802() + fun_l27_n519 +end + +def fun_l26_n803() + fun_l27_n157 +end + +def fun_l26_n804() + fun_l27_n53 +end + +def fun_l26_n805() + fun_l27_n765 +end + +def fun_l26_n806() + fun_l27_n48 +end + +def fun_l26_n807() + fun_l27_n127 +end + +def fun_l26_n808() + fun_l27_n418 +end + +def fun_l26_n809() + fun_l27_n650 +end + +def fun_l26_n810() + fun_l27_n918 +end + +def fun_l26_n811() + fun_l27_n878 +end + +def fun_l26_n812() + fun_l27_n244 +end + +def fun_l26_n813() + fun_l27_n611 +end + +def fun_l26_n814() + fun_l27_n82 +end + +def fun_l26_n815() + fun_l27_n6 +end + +def fun_l26_n816() + fun_l27_n486 +end + +def fun_l26_n817() + fun_l27_n711 +end + +def fun_l26_n818() + fun_l27_n792 +end + +def fun_l26_n819() + fun_l27_n974 +end + +def fun_l26_n820() + fun_l27_n480 +end + +def fun_l26_n821() + fun_l27_n460 +end + +def fun_l26_n822() + fun_l27_n520 +end + +def fun_l26_n823() + fun_l27_n803 +end + +def fun_l26_n824() + fun_l27_n734 +end + +def fun_l26_n825() + fun_l27_n336 +end + +def fun_l26_n826() + fun_l27_n657 +end + +def fun_l26_n827() + fun_l27_n20 +end + +def fun_l26_n828() + fun_l27_n83 +end + +def fun_l26_n829() + fun_l27_n452 +end + +def fun_l26_n830() + fun_l27_n973 +end + +def fun_l26_n831() + fun_l27_n79 +end + +def fun_l26_n832() + fun_l27_n327 +end + +def fun_l26_n833() + fun_l27_n36 +end + +def fun_l26_n834() + fun_l27_n186 +end + +def fun_l26_n835() + fun_l27_n946 +end + +def fun_l26_n836() + fun_l27_n776 +end + +def fun_l26_n837() + fun_l27_n33 +end + +def fun_l26_n838() + fun_l27_n966 +end + +def fun_l26_n839() + fun_l27_n961 +end + +def fun_l26_n840() + fun_l27_n181 +end + +def fun_l26_n841() + fun_l27_n103 +end + +def fun_l26_n842() + fun_l27_n500 +end + +def fun_l26_n843() + fun_l27_n359 +end + +def fun_l26_n844() + fun_l27_n316 +end + +def fun_l26_n845() + fun_l27_n921 +end + +def fun_l26_n846() + fun_l27_n745 +end + +def fun_l26_n847() + fun_l27_n555 +end + +def fun_l26_n848() + fun_l27_n306 +end + +def fun_l26_n849() + fun_l27_n462 +end + +def fun_l26_n850() + fun_l27_n369 +end + +def fun_l26_n851() + fun_l27_n489 +end + +def fun_l26_n852() + fun_l27_n276 +end + +def fun_l26_n853() + fun_l27_n509 +end + +def fun_l26_n854() + fun_l27_n524 +end + +def fun_l26_n855() + fun_l27_n421 +end + +def fun_l26_n856() + fun_l27_n845 +end + +def fun_l26_n857() + fun_l27_n600 +end + +def fun_l26_n858() + fun_l27_n961 +end + +def fun_l26_n859() + fun_l27_n506 +end + +def fun_l26_n860() + fun_l27_n106 +end + +def fun_l26_n861() + fun_l27_n525 +end + +def fun_l26_n862() + fun_l27_n515 +end + +def fun_l26_n863() + fun_l27_n506 +end + +def fun_l26_n864() + fun_l27_n283 +end + +def fun_l26_n865() + fun_l27_n189 +end + +def fun_l26_n866() + fun_l27_n181 +end + +def fun_l26_n867() + fun_l27_n338 +end + +def fun_l26_n868() + fun_l27_n965 +end + +def fun_l26_n869() + fun_l27_n219 +end + +def fun_l26_n870() + fun_l27_n604 +end + +def fun_l26_n871() + fun_l27_n211 +end + +def fun_l26_n872() + fun_l27_n225 +end + +def fun_l26_n873() + fun_l27_n776 +end + +def fun_l26_n874() + fun_l27_n723 +end + +def fun_l26_n875() + fun_l27_n653 +end + +def fun_l26_n876() + fun_l27_n157 +end + +def fun_l26_n877() + fun_l27_n321 +end + +def fun_l26_n878() + fun_l27_n684 +end + +def fun_l26_n879() + fun_l27_n270 +end + +def fun_l26_n880() + fun_l27_n575 +end + +def fun_l26_n881() + fun_l27_n201 +end + +def fun_l26_n882() + fun_l27_n772 +end + +def fun_l26_n883() + fun_l27_n610 +end + +def fun_l26_n884() + fun_l27_n117 +end + +def fun_l26_n885() + fun_l27_n706 +end + +def fun_l26_n886() + fun_l27_n245 +end + +def fun_l26_n887() + fun_l27_n173 +end + +def fun_l26_n888() + fun_l27_n679 +end + +def fun_l26_n889() + fun_l27_n725 +end + +def fun_l26_n890() + fun_l27_n481 +end + +def fun_l26_n891() + fun_l27_n632 +end + +def fun_l26_n892() + fun_l27_n20 +end + +def fun_l26_n893() + fun_l27_n649 +end + +def fun_l26_n894() + fun_l27_n560 +end + +def fun_l26_n895() + fun_l27_n861 +end + +def fun_l26_n896() + fun_l27_n565 +end + +def fun_l26_n897() + fun_l27_n864 +end + +def fun_l26_n898() + fun_l27_n590 +end + +def fun_l26_n899() + fun_l27_n413 +end + +def fun_l26_n900() + fun_l27_n833 +end + +def fun_l26_n901() + fun_l27_n948 +end + +def fun_l26_n902() + fun_l27_n946 +end + +def fun_l26_n903() + fun_l27_n211 +end + +def fun_l26_n904() + fun_l27_n367 +end + +def fun_l26_n905() + fun_l27_n893 +end + +def fun_l26_n906() + fun_l27_n710 +end + +def fun_l26_n907() + fun_l27_n655 +end + +def fun_l26_n908() + fun_l27_n830 +end + +def fun_l26_n909() + fun_l27_n649 +end + +def fun_l26_n910() + fun_l27_n195 +end + +def fun_l26_n911() + fun_l27_n474 +end + +def fun_l26_n912() + fun_l27_n362 +end + +def fun_l26_n913() + fun_l27_n199 +end + +def fun_l26_n914() + fun_l27_n426 +end + +def fun_l26_n915() + fun_l27_n123 +end + +def fun_l26_n916() + fun_l27_n734 +end + +def fun_l26_n917() + fun_l27_n646 +end + +def fun_l26_n918() + fun_l27_n603 +end + +def fun_l26_n919() + fun_l27_n907 +end + +def fun_l26_n920() + fun_l27_n500 +end + +def fun_l26_n921() + fun_l27_n30 +end + +def fun_l26_n922() + fun_l27_n393 +end + +def fun_l26_n923() + fun_l27_n981 +end + +def fun_l26_n924() + fun_l27_n318 +end + +def fun_l26_n925() + fun_l27_n979 +end + +def fun_l26_n926() + fun_l27_n439 +end + +def fun_l26_n927() + fun_l27_n398 +end + +def fun_l26_n928() + fun_l27_n301 +end + +def fun_l26_n929() + fun_l27_n778 +end + +def fun_l26_n930() + fun_l27_n318 +end + +def fun_l26_n931() + fun_l27_n835 +end + +def fun_l26_n932() + fun_l27_n90 +end + +def fun_l26_n933() + fun_l27_n321 +end + +def fun_l26_n934() + fun_l27_n600 +end + +def fun_l26_n935() + fun_l27_n731 +end + +def fun_l26_n936() + fun_l27_n318 +end + +def fun_l26_n937() + fun_l27_n229 +end + +def fun_l26_n938() + fun_l27_n997 +end + +def fun_l26_n939() + fun_l27_n105 +end + +def fun_l26_n940() + fun_l27_n122 +end + +def fun_l26_n941() + fun_l27_n680 +end + +def fun_l26_n942() + fun_l27_n814 +end + +def fun_l26_n943() + fun_l27_n350 +end + +def fun_l26_n944() + fun_l27_n363 +end + +def fun_l26_n945() + fun_l27_n82 +end + +def fun_l26_n946() + fun_l27_n82 +end + +def fun_l26_n947() + fun_l27_n638 +end + +def fun_l26_n948() + fun_l27_n677 +end + +def fun_l26_n949() + fun_l27_n931 +end + +def fun_l26_n950() + fun_l27_n151 +end + +def fun_l26_n951() + fun_l27_n862 +end + +def fun_l26_n952() + fun_l27_n984 +end + +def fun_l26_n953() + fun_l27_n471 +end + +def fun_l26_n954() + fun_l27_n859 +end + +def fun_l26_n955() + fun_l27_n127 +end + +def fun_l26_n956() + fun_l27_n963 +end + +def fun_l26_n957() + fun_l27_n859 +end + +def fun_l26_n958() + fun_l27_n900 +end + +def fun_l26_n959() + fun_l27_n957 +end + +def fun_l26_n960() + fun_l27_n443 +end + +def fun_l26_n961() + fun_l27_n826 +end + +def fun_l26_n962() + fun_l27_n303 +end + +def fun_l26_n963() + fun_l27_n766 +end + +def fun_l26_n964() + fun_l27_n420 +end + +def fun_l26_n965() + fun_l27_n873 +end + +def fun_l26_n966() + fun_l27_n285 +end + +def fun_l26_n967() + fun_l27_n490 +end + +def fun_l26_n968() + fun_l27_n46 +end + +def fun_l26_n969() + fun_l27_n451 +end + +def fun_l26_n970() + fun_l27_n157 +end + +def fun_l26_n971() + fun_l27_n981 +end + +def fun_l26_n972() + fun_l27_n969 +end + +def fun_l26_n973() + fun_l27_n644 +end + +def fun_l26_n974() + fun_l27_n753 +end + +def fun_l26_n975() + fun_l27_n306 +end + +def fun_l26_n976() + fun_l27_n617 +end + +def fun_l26_n977() + fun_l27_n258 +end + +def fun_l26_n978() + fun_l27_n511 +end + +def fun_l26_n979() + fun_l27_n267 +end + +def fun_l26_n980() + fun_l27_n42 +end + +def fun_l26_n981() + fun_l27_n153 +end + +def fun_l26_n982() + fun_l27_n77 +end + +def fun_l26_n983() + fun_l27_n658 +end + +def fun_l26_n984() + fun_l27_n605 +end + +def fun_l26_n985() + fun_l27_n40 +end + +def fun_l26_n986() + fun_l27_n375 +end + +def fun_l26_n987() + fun_l27_n273 +end + +def fun_l26_n988() + fun_l27_n290 +end + +def fun_l26_n989() + fun_l27_n507 +end + +def fun_l26_n990() + fun_l27_n537 +end + +def fun_l26_n991() + fun_l27_n373 +end + +def fun_l26_n992() + fun_l27_n39 +end + +def fun_l26_n993() + fun_l27_n356 +end + +def fun_l26_n994() + fun_l27_n875 +end + +def fun_l26_n995() + fun_l27_n112 +end + +def fun_l26_n996() + fun_l27_n209 +end + +def fun_l26_n997() + fun_l27_n690 +end + +def fun_l26_n998() + fun_l27_n19 +end + +def fun_l26_n999() + fun_l27_n962 +end + +def fun_l27_n0() + fun_l28_n602 +end + +def fun_l27_n1() + fun_l28_n911 +end + +def fun_l27_n2() + fun_l28_n797 +end + +def fun_l27_n3() + fun_l28_n261 +end + +def fun_l27_n4() + fun_l28_n172 +end + +def fun_l27_n5() + fun_l28_n430 +end + +def fun_l27_n6() + fun_l28_n397 +end + +def fun_l27_n7() + fun_l28_n388 +end + +def fun_l27_n8() + fun_l28_n218 +end + +def fun_l27_n9() + fun_l28_n71 +end + +def fun_l27_n10() + fun_l28_n424 +end + +def fun_l27_n11() + fun_l28_n454 +end + +def fun_l27_n12() + fun_l28_n388 +end + +def fun_l27_n13() + fun_l28_n909 +end + +def fun_l27_n14() + fun_l28_n655 +end + +def fun_l27_n15() + fun_l28_n355 +end + +def fun_l27_n16() + fun_l28_n319 +end + +def fun_l27_n17() + fun_l28_n137 +end + +def fun_l27_n18() + fun_l28_n929 +end + +def fun_l27_n19() + fun_l28_n887 +end + +def fun_l27_n20() + fun_l28_n571 +end + +def fun_l27_n21() + fun_l28_n480 +end + +def fun_l27_n22() + fun_l28_n431 +end + +def fun_l27_n23() + fun_l28_n918 +end + +def fun_l27_n24() + fun_l28_n673 +end + +def fun_l27_n25() + fun_l28_n550 +end + +def fun_l27_n26() + fun_l28_n256 +end + +def fun_l27_n27() + fun_l28_n624 +end + +def fun_l27_n28() + fun_l28_n245 +end + +def fun_l27_n29() + fun_l28_n303 +end + +def fun_l27_n30() + fun_l28_n260 +end + +def fun_l27_n31() + fun_l28_n174 +end + +def fun_l27_n32() + fun_l28_n147 +end + +def fun_l27_n33() + fun_l28_n590 +end + +def fun_l27_n34() + fun_l28_n691 +end + +def fun_l27_n35() + fun_l28_n739 +end + +def fun_l27_n36() + fun_l28_n530 +end + +def fun_l27_n37() + fun_l28_n20 +end + +def fun_l27_n38() + fun_l28_n147 +end + +def fun_l27_n39() + fun_l28_n362 +end + +def fun_l27_n40() + fun_l28_n250 +end + +def fun_l27_n41() + fun_l28_n579 +end + +def fun_l27_n42() + fun_l28_n557 +end + +def fun_l27_n43() + fun_l28_n639 +end + +def fun_l27_n44() + fun_l28_n309 +end + +def fun_l27_n45() + fun_l28_n213 +end + +def fun_l27_n46() + fun_l28_n178 +end + +def fun_l27_n47() + fun_l28_n974 +end + +def fun_l27_n48() + fun_l28_n500 +end + +def fun_l27_n49() + fun_l28_n814 +end + +def fun_l27_n50() + fun_l28_n930 +end + +def fun_l27_n51() + fun_l28_n329 +end + +def fun_l27_n52() + fun_l28_n385 +end + +def fun_l27_n53() + fun_l28_n214 +end + +def fun_l27_n54() + fun_l28_n934 +end + +def fun_l27_n55() + fun_l28_n645 +end + +def fun_l27_n56() + fun_l28_n311 +end + +def fun_l27_n57() + fun_l28_n15 +end + +def fun_l27_n58() + fun_l28_n499 +end + +def fun_l27_n59() + fun_l28_n919 +end + +def fun_l27_n60() + fun_l28_n659 +end + +def fun_l27_n61() + fun_l28_n921 +end + +def fun_l27_n62() + fun_l28_n306 +end + +def fun_l27_n63() + fun_l28_n128 +end + +def fun_l27_n64() + fun_l28_n871 +end + +def fun_l27_n65() + fun_l28_n434 +end + +def fun_l27_n66() + fun_l28_n775 +end + +def fun_l27_n67() + fun_l28_n311 +end + +def fun_l27_n68() + fun_l28_n959 +end + +def fun_l27_n69() + fun_l28_n648 +end + +def fun_l27_n70() + fun_l28_n893 +end + +def fun_l27_n71() + fun_l28_n669 +end + +def fun_l27_n72() + fun_l28_n121 +end + +def fun_l27_n73() + fun_l28_n102 +end + +def fun_l27_n74() + fun_l28_n887 +end + +def fun_l27_n75() + fun_l28_n326 +end + +def fun_l27_n76() + fun_l28_n48 +end + +def fun_l27_n77() + fun_l28_n636 +end + +def fun_l27_n78() + fun_l28_n804 +end + +def fun_l27_n79() + fun_l28_n838 +end + +def fun_l27_n80() + fun_l28_n859 +end + +def fun_l27_n81() + fun_l28_n683 +end + +def fun_l27_n82() + fun_l28_n752 +end + +def fun_l27_n83() + fun_l28_n244 +end + +def fun_l27_n84() + fun_l28_n727 +end + +def fun_l27_n85() + fun_l28_n818 +end + +def fun_l27_n86() + fun_l28_n451 +end + +def fun_l27_n87() + fun_l28_n9 +end + +def fun_l27_n88() + fun_l28_n738 +end + +def fun_l27_n89() + fun_l28_n589 +end + +def fun_l27_n90() + fun_l28_n140 +end + +def fun_l27_n91() + fun_l28_n615 +end + +def fun_l27_n92() + fun_l28_n973 +end + +def fun_l27_n93() + fun_l28_n668 +end + +def fun_l27_n94() + fun_l28_n299 +end + +def fun_l27_n95() + fun_l28_n358 +end + +def fun_l27_n96() + fun_l28_n319 +end + +def fun_l27_n97() + fun_l28_n165 +end + +def fun_l27_n98() + fun_l28_n67 +end + +def fun_l27_n99() + fun_l28_n494 +end + +def fun_l27_n100() + fun_l28_n107 +end + +def fun_l27_n101() + fun_l28_n985 +end + +def fun_l27_n102() + fun_l28_n239 +end + +def fun_l27_n103() + fun_l28_n64 +end + +def fun_l27_n104() + fun_l28_n676 +end + +def fun_l27_n105() + fun_l28_n852 +end + +def fun_l27_n106() + fun_l28_n668 +end + +def fun_l27_n107() + fun_l28_n523 +end + +def fun_l27_n108() + fun_l28_n15 +end + +def fun_l27_n109() + fun_l28_n619 +end + +def fun_l27_n110() + fun_l28_n440 +end + +def fun_l27_n111() + fun_l28_n792 +end + +def fun_l27_n112() + fun_l28_n771 +end + +def fun_l27_n113() + fun_l28_n263 +end + +def fun_l27_n114() + fun_l28_n180 +end + +def fun_l27_n115() + fun_l28_n615 +end + +def fun_l27_n116() + fun_l28_n319 +end + +def fun_l27_n117() + fun_l28_n970 +end + +def fun_l27_n118() + fun_l28_n946 +end + +def fun_l27_n119() + fun_l28_n121 +end + +def fun_l27_n120() + fun_l28_n655 +end + +def fun_l27_n121() + fun_l28_n68 +end + +def fun_l27_n122() + fun_l28_n406 +end + +def fun_l27_n123() + fun_l28_n535 +end + +def fun_l27_n124() + fun_l28_n951 +end + +def fun_l27_n125() + fun_l28_n366 +end + +def fun_l27_n126() + fun_l28_n192 +end + +def fun_l27_n127() + fun_l28_n106 +end + +def fun_l27_n128() + fun_l28_n21 +end + +def fun_l27_n129() + fun_l28_n339 +end + +def fun_l27_n130() + fun_l28_n824 +end + +def fun_l27_n131() + fun_l28_n921 +end + +def fun_l27_n132() + fun_l28_n678 +end + +def fun_l27_n133() + fun_l28_n925 +end + +def fun_l27_n134() + fun_l28_n55 +end + +def fun_l27_n135() + fun_l28_n726 +end + +def fun_l27_n136() + fun_l28_n110 +end + +def fun_l27_n137() + fun_l28_n559 +end + +def fun_l27_n138() + fun_l28_n879 +end + +def fun_l27_n139() + fun_l28_n332 +end + +def fun_l27_n140() + fun_l28_n167 +end + +def fun_l27_n141() + fun_l28_n123 +end + +def fun_l27_n142() + fun_l28_n707 +end + +def fun_l27_n143() + fun_l28_n423 +end + +def fun_l27_n144() + fun_l28_n659 +end + +def fun_l27_n145() + fun_l28_n322 +end + +def fun_l27_n146() + fun_l28_n227 +end + +def fun_l27_n147() + fun_l28_n679 +end + +def fun_l27_n148() + fun_l28_n376 +end + +def fun_l27_n149() + fun_l28_n327 +end + +def fun_l27_n150() + fun_l28_n328 +end + +def fun_l27_n151() + fun_l28_n408 +end + +def fun_l27_n152() + fun_l28_n141 +end + +def fun_l27_n153() + fun_l28_n728 +end + +def fun_l27_n154() + fun_l28_n207 +end + +def fun_l27_n155() + fun_l28_n836 +end + +def fun_l27_n156() + fun_l28_n71 +end + +def fun_l27_n157() + fun_l28_n390 +end + +def fun_l27_n158() + fun_l28_n277 +end + +def fun_l27_n159() + fun_l28_n960 +end + +def fun_l27_n160() + fun_l28_n705 +end + +def fun_l27_n161() + fun_l28_n445 +end + +def fun_l27_n162() + fun_l28_n570 +end + +def fun_l27_n163() + fun_l28_n878 +end + +def fun_l27_n164() + fun_l28_n714 +end + +def fun_l27_n165() + fun_l28_n933 +end + +def fun_l27_n166() + fun_l28_n480 +end + +def fun_l27_n167() + fun_l28_n308 +end + +def fun_l27_n168() + fun_l28_n604 +end + +def fun_l27_n169() + fun_l28_n892 +end + +def fun_l27_n170() + fun_l28_n901 +end + +def fun_l27_n171() + fun_l28_n524 +end + +def fun_l27_n172() + fun_l28_n533 +end + +def fun_l27_n173() + fun_l28_n761 +end + +def fun_l27_n174() + fun_l28_n97 +end + +def fun_l27_n175() + fun_l28_n944 +end + +def fun_l27_n176() + fun_l28_n627 +end + +def fun_l27_n177() + fun_l28_n720 +end + +def fun_l27_n178() + fun_l28_n366 +end + +def fun_l27_n179() + fun_l28_n353 +end + +def fun_l27_n180() + fun_l28_n441 +end + +def fun_l27_n181() + fun_l28_n682 +end + +def fun_l27_n182() + fun_l28_n581 +end + +def fun_l27_n183() + fun_l28_n974 +end + +def fun_l27_n184() + fun_l28_n522 +end + +def fun_l27_n185() + fun_l28_n702 +end + +def fun_l27_n186() + fun_l28_n941 +end + +def fun_l27_n187() + fun_l28_n665 +end + +def fun_l27_n188() + fun_l28_n148 +end + +def fun_l27_n189() + fun_l28_n91 +end + +def fun_l27_n190() + fun_l28_n679 +end + +def fun_l27_n191() + fun_l28_n929 +end + +def fun_l27_n192() + fun_l28_n828 +end + +def fun_l27_n193() + fun_l28_n872 +end + +def fun_l27_n194() + fun_l28_n152 +end + +def fun_l27_n195() + fun_l28_n593 +end + +def fun_l27_n196() + fun_l28_n438 +end + +def fun_l27_n197() + fun_l28_n390 +end + +def fun_l27_n198() + fun_l28_n354 +end + +def fun_l27_n199() + fun_l28_n547 +end + +def fun_l27_n200() + fun_l28_n249 +end + +def fun_l27_n201() + fun_l28_n562 +end + +def fun_l27_n202() + fun_l28_n571 +end + +def fun_l27_n203() + fun_l28_n763 +end + +def fun_l27_n204() + fun_l28_n961 +end + +def fun_l27_n205() + fun_l28_n368 +end + +def fun_l27_n206() + fun_l28_n219 +end + +def fun_l27_n207() + fun_l28_n414 +end + +def fun_l27_n208() + fun_l28_n130 +end + +def fun_l27_n209() + fun_l28_n911 +end + +def fun_l27_n210() + fun_l28_n94 +end + +def fun_l27_n211() + fun_l28_n966 +end + +def fun_l27_n212() + fun_l28_n271 +end + +def fun_l27_n213() + fun_l28_n372 +end + +def fun_l27_n214() + fun_l28_n845 +end + +def fun_l27_n215() + fun_l28_n924 +end + +def fun_l27_n216() + fun_l28_n220 +end + +def fun_l27_n217() + fun_l28_n653 +end + +def fun_l27_n218() + fun_l28_n960 +end + +def fun_l27_n219() + fun_l28_n343 +end + +def fun_l27_n220() + fun_l28_n255 +end + +def fun_l27_n221() + fun_l28_n206 +end + +def fun_l27_n222() + fun_l28_n190 +end + +def fun_l27_n223() + fun_l28_n753 +end + +def fun_l27_n224() + fun_l28_n530 +end + +def fun_l27_n225() + fun_l28_n198 +end + +def fun_l27_n226() + fun_l28_n604 +end + +def fun_l27_n227() + fun_l28_n685 +end + +def fun_l27_n228() + fun_l28_n268 +end + +def fun_l27_n229() + fun_l28_n344 +end + +def fun_l27_n230() + fun_l28_n850 +end + +def fun_l27_n231() + fun_l28_n612 +end + +def fun_l27_n232() + fun_l28_n598 +end + +def fun_l27_n233() + fun_l28_n766 +end + +def fun_l27_n234() + fun_l28_n994 +end + +def fun_l27_n235() + fun_l28_n566 +end + +def fun_l27_n236() + fun_l28_n306 +end + +def fun_l27_n237() + fun_l28_n592 +end + +def fun_l27_n238() + fun_l28_n814 +end + +def fun_l27_n239() + fun_l28_n319 +end + +def fun_l27_n240() + fun_l28_n619 +end + +def fun_l27_n241() + fun_l28_n631 +end + +def fun_l27_n242() + fun_l28_n240 +end + +def fun_l27_n243() + fun_l28_n714 +end + +def fun_l27_n244() + fun_l28_n651 +end + +def fun_l27_n245() + fun_l28_n760 +end + +def fun_l27_n246() + fun_l28_n925 +end + +def fun_l27_n247() + fun_l28_n537 +end + +def fun_l27_n248() + fun_l28_n541 +end + +def fun_l27_n249() + fun_l28_n963 +end + +def fun_l27_n250() + fun_l28_n630 +end + +def fun_l27_n251() + fun_l28_n124 +end + +def fun_l27_n252() + fun_l28_n894 +end + +def fun_l27_n253() + fun_l28_n307 +end + +def fun_l27_n254() + fun_l28_n485 +end + +def fun_l27_n255() + fun_l28_n272 +end + +def fun_l27_n256() + fun_l28_n994 +end + +def fun_l27_n257() + fun_l28_n48 +end + +def fun_l27_n258() + fun_l28_n374 +end + +def fun_l27_n259() + fun_l28_n508 +end + +def fun_l27_n260() + fun_l28_n936 +end + +def fun_l27_n261() + fun_l28_n43 +end + +def fun_l27_n262() + fun_l28_n297 +end + +def fun_l27_n263() + fun_l28_n205 +end + +def fun_l27_n264() + fun_l28_n234 +end + +def fun_l27_n265() + fun_l28_n560 +end + +def fun_l27_n266() + fun_l28_n124 +end + +def fun_l27_n267() + fun_l28_n912 +end + +def fun_l27_n268() + fun_l28_n545 +end + +def fun_l27_n269() + fun_l28_n266 +end + +def fun_l27_n270() + fun_l28_n917 +end + +def fun_l27_n271() + fun_l28_n971 +end + +def fun_l27_n272() + fun_l28_n305 +end + +def fun_l27_n273() + fun_l28_n158 +end + +def fun_l27_n274() + fun_l28_n241 +end + +def fun_l27_n275() + fun_l28_n667 +end + +def fun_l27_n276() + fun_l28_n857 +end + +def fun_l27_n277() + fun_l28_n207 +end + +def fun_l27_n278() + fun_l28_n258 +end + +def fun_l27_n279() + fun_l28_n410 +end + +def fun_l27_n280() + fun_l28_n868 +end + +def fun_l27_n281() + fun_l28_n976 +end + +def fun_l27_n282() + fun_l28_n519 +end + +def fun_l27_n283() + fun_l28_n165 +end + +def fun_l27_n284() + fun_l28_n790 +end + +def fun_l27_n285() + fun_l28_n825 +end + +def fun_l27_n286() + fun_l28_n844 +end + +def fun_l27_n287() + fun_l28_n450 +end + +def fun_l27_n288() + fun_l28_n913 +end + +def fun_l27_n289() + fun_l28_n418 +end + +def fun_l27_n290() + fun_l28_n63 +end + +def fun_l27_n291() + fun_l28_n306 +end + +def fun_l27_n292() + fun_l28_n233 +end + +def fun_l27_n293() + fun_l28_n274 +end + +def fun_l27_n294() + fun_l28_n292 +end + +def fun_l27_n295() + fun_l28_n504 +end + +def fun_l27_n296() + fun_l28_n769 +end + +def fun_l27_n297() + fun_l28_n404 +end + +def fun_l27_n298() + fun_l28_n782 +end + +def fun_l27_n299() + fun_l28_n788 +end + +def fun_l27_n300() + fun_l28_n727 +end + +def fun_l27_n301() + fun_l28_n187 +end + +def fun_l27_n302() + fun_l28_n568 +end + +def fun_l27_n303() + fun_l28_n195 +end + +def fun_l27_n304() + fun_l28_n696 +end + +def fun_l27_n305() + fun_l28_n293 +end + +def fun_l27_n306() + fun_l28_n722 +end + +def fun_l27_n307() + fun_l28_n911 +end + +def fun_l27_n308() + fun_l28_n827 +end + +def fun_l27_n309() + fun_l28_n767 +end + +def fun_l27_n310() + fun_l28_n423 +end + +def fun_l27_n311() + fun_l28_n60 +end + +def fun_l27_n312() + fun_l28_n466 +end + +def fun_l27_n313() + fun_l28_n270 +end + +def fun_l27_n314() + fun_l28_n993 +end + +def fun_l27_n315() + fun_l28_n231 +end + +def fun_l27_n316() + fun_l28_n514 +end + +def fun_l27_n317() + fun_l28_n57 +end + +def fun_l27_n318() + fun_l28_n646 +end + +def fun_l27_n319() + fun_l28_n17 +end + +def fun_l27_n320() + fun_l28_n964 +end + +def fun_l27_n321() + fun_l28_n1 +end + +def fun_l27_n322() + fun_l28_n956 +end + +def fun_l27_n323() + fun_l28_n273 +end + +def fun_l27_n324() + fun_l28_n370 +end + +def fun_l27_n325() + fun_l28_n81 +end + +def fun_l27_n326() + fun_l28_n765 +end + +def fun_l27_n327() + fun_l28_n506 +end + +def fun_l27_n328() + fun_l28_n327 +end + +def fun_l27_n329() + fun_l28_n362 +end + +def fun_l27_n330() + fun_l28_n852 +end + +def fun_l27_n331() + fun_l28_n876 +end + +def fun_l27_n332() + fun_l28_n531 +end + +def fun_l27_n333() + fun_l28_n426 +end + +def fun_l27_n334() + fun_l28_n295 +end + +def fun_l27_n335() + fun_l28_n929 +end + +def fun_l27_n336() + fun_l28_n693 +end + +def fun_l27_n337() + fun_l28_n724 +end + +def fun_l27_n338() + fun_l28_n784 +end + +def fun_l27_n339() + fun_l28_n752 +end + +def fun_l27_n340() + fun_l28_n809 +end + +def fun_l27_n341() + fun_l28_n269 +end + +def fun_l27_n342() + fun_l28_n33 +end + +def fun_l27_n343() + fun_l28_n778 +end + +def fun_l27_n344() + fun_l28_n974 +end + +def fun_l27_n345() + fun_l28_n843 +end + +def fun_l27_n346() + fun_l28_n86 +end + +def fun_l27_n347() + fun_l28_n594 +end + +def fun_l27_n348() + fun_l28_n111 +end + +def fun_l27_n349() + fun_l28_n317 +end + +def fun_l27_n350() + fun_l28_n238 +end + +def fun_l27_n351() + fun_l28_n447 +end + +def fun_l27_n352() + fun_l28_n954 +end + +def fun_l27_n353() + fun_l28_n846 +end + +def fun_l27_n354() + fun_l28_n124 +end + +def fun_l27_n355() + fun_l28_n445 +end + +def fun_l27_n356() + fun_l28_n957 +end + +def fun_l27_n357() + fun_l28_n365 +end + +def fun_l27_n358() + fun_l28_n136 +end + +def fun_l27_n359() + fun_l28_n372 +end + +def fun_l27_n360() + fun_l28_n487 +end + +def fun_l27_n361() + fun_l28_n493 +end + +def fun_l27_n362() + fun_l28_n905 +end + +def fun_l27_n363() + fun_l28_n146 +end + +def fun_l27_n364() + fun_l28_n523 +end + +def fun_l27_n365() + fun_l28_n876 +end + +def fun_l27_n366() + fun_l28_n67 +end + +def fun_l27_n367() + fun_l28_n746 +end + +def fun_l27_n368() + fun_l28_n264 +end + +def fun_l27_n369() + fun_l28_n470 +end + +def fun_l27_n370() + fun_l28_n240 +end + +def fun_l27_n371() + fun_l28_n928 +end + +def fun_l27_n372() + fun_l28_n574 +end + +def fun_l27_n373() + fun_l28_n756 +end + +def fun_l27_n374() + fun_l28_n244 +end + +def fun_l27_n375() + fun_l28_n46 +end + +def fun_l27_n376() + fun_l28_n940 +end + +def fun_l27_n377() + fun_l28_n430 +end + +def fun_l27_n378() + fun_l28_n879 +end + +def fun_l27_n379() + fun_l28_n560 +end + +def fun_l27_n380() + fun_l28_n231 +end + +def fun_l27_n381() + fun_l28_n283 +end + +def fun_l27_n382() + fun_l28_n438 +end + +def fun_l27_n383() + fun_l28_n207 +end + +def fun_l27_n384() + fun_l28_n185 +end + +def fun_l27_n385() + fun_l28_n40 +end + +def fun_l27_n386() + fun_l28_n572 +end + +def fun_l27_n387() + fun_l28_n975 +end + +def fun_l27_n388() + fun_l28_n117 +end + +def fun_l27_n389() + fun_l28_n329 +end + +def fun_l27_n390() + fun_l28_n311 +end + +def fun_l27_n391() + fun_l28_n653 +end + +def fun_l27_n392() + fun_l28_n522 +end + +def fun_l27_n393() + fun_l28_n452 +end + +def fun_l27_n394() + fun_l28_n137 +end + +def fun_l27_n395() + fun_l28_n606 +end + +def fun_l27_n396() + fun_l28_n901 +end + +def fun_l27_n397() + fun_l28_n434 +end + +def fun_l27_n398() + fun_l28_n863 +end + +def fun_l27_n399() + fun_l28_n117 +end + +def fun_l27_n400() + fun_l28_n473 +end + +def fun_l27_n401() + fun_l28_n638 +end + +def fun_l27_n402() + fun_l28_n71 +end + +def fun_l27_n403() + fun_l28_n423 +end + +def fun_l27_n404() + fun_l28_n362 +end + +def fun_l27_n405() + fun_l28_n537 +end + +def fun_l27_n406() + fun_l28_n975 +end + +def fun_l27_n407() + fun_l28_n424 +end + +def fun_l27_n408() + fun_l28_n613 +end + +def fun_l27_n409() + fun_l28_n606 +end + +def fun_l27_n410() + fun_l28_n782 +end + +def fun_l27_n411() + fun_l28_n445 +end + +def fun_l27_n412() + fun_l28_n362 +end + +def fun_l27_n413() + fun_l28_n837 +end + +def fun_l27_n414() + fun_l28_n335 +end + +def fun_l27_n415() + fun_l28_n258 +end + +def fun_l27_n416() + fun_l28_n832 +end + +def fun_l27_n417() + fun_l28_n102 +end + +def fun_l27_n418() + fun_l28_n202 +end + +def fun_l27_n419() + fun_l28_n624 +end + +def fun_l27_n420() + fun_l28_n118 +end + +def fun_l27_n421() + fun_l28_n247 +end + +def fun_l27_n422() + fun_l28_n768 +end + +def fun_l27_n423() + fun_l28_n879 +end + +def fun_l27_n424() + fun_l28_n650 +end + +def fun_l27_n425() + fun_l28_n545 +end + +def fun_l27_n426() + fun_l28_n854 +end + +def fun_l27_n427() + fun_l28_n722 +end + +def fun_l27_n428() + fun_l28_n637 +end + +def fun_l27_n429() + fun_l28_n295 +end + +def fun_l27_n430() + fun_l28_n504 +end + +def fun_l27_n431() + fun_l28_n939 +end + +def fun_l27_n432() + fun_l28_n52 +end + +def fun_l27_n433() + fun_l28_n613 +end + +def fun_l27_n434() + fun_l28_n165 +end + +def fun_l27_n435() + fun_l28_n948 +end + +def fun_l27_n436() + fun_l28_n995 +end + +def fun_l27_n437() + fun_l28_n572 +end + +def fun_l27_n438() + fun_l28_n919 +end + +def fun_l27_n439() + fun_l28_n843 +end + +def fun_l27_n440() + fun_l28_n826 +end + +def fun_l27_n441() + fun_l28_n328 +end + +def fun_l27_n442() + fun_l28_n330 +end + +def fun_l27_n443() + fun_l28_n819 +end + +def fun_l27_n444() + fun_l28_n949 +end + +def fun_l27_n445() + fun_l28_n505 +end + +def fun_l27_n446() + fun_l28_n306 +end + +def fun_l27_n447() + fun_l28_n731 +end + +def fun_l27_n448() + fun_l28_n232 +end + +def fun_l27_n449() + fun_l28_n251 +end + +def fun_l27_n450() + fun_l28_n807 +end + +def fun_l27_n451() + fun_l28_n808 +end + +def fun_l27_n452() + fun_l28_n672 +end + +def fun_l27_n453() + fun_l28_n0 +end + +def fun_l27_n454() + fun_l28_n659 +end + +def fun_l27_n455() + fun_l28_n955 +end + +def fun_l27_n456() + fun_l28_n314 +end + +def fun_l27_n457() + fun_l28_n539 +end + +def fun_l27_n458() + fun_l28_n394 +end + +def fun_l27_n459() + fun_l28_n48 +end + +def fun_l27_n460() + fun_l28_n434 +end + +def fun_l27_n461() + fun_l28_n54 +end + +def fun_l27_n462() + fun_l28_n108 +end + +def fun_l27_n463() + fun_l28_n80 +end + +def fun_l27_n464() + fun_l28_n255 +end + +def fun_l27_n465() + fun_l28_n273 +end + +def fun_l27_n466() + fun_l28_n227 +end + +def fun_l27_n467() + fun_l28_n764 +end + +def fun_l27_n468() + fun_l28_n210 +end + +def fun_l27_n469() + fun_l28_n68 +end + +def fun_l27_n470() + fun_l28_n178 +end + +def fun_l27_n471() + fun_l28_n500 +end + +def fun_l27_n472() + fun_l28_n374 +end + +def fun_l27_n473() + fun_l28_n98 +end + +def fun_l27_n474() + fun_l28_n232 +end + +def fun_l27_n475() + fun_l28_n35 +end + +def fun_l27_n476() + fun_l28_n483 +end + +def fun_l27_n477() + fun_l28_n282 +end + +def fun_l27_n478() + fun_l28_n512 +end + +def fun_l27_n479() + fun_l28_n755 +end + +def fun_l27_n480() + fun_l28_n299 +end + +def fun_l27_n481() + fun_l28_n899 +end + +def fun_l27_n482() + fun_l28_n872 +end + +def fun_l27_n483() + fun_l28_n558 +end + +def fun_l27_n484() + fun_l28_n700 +end + +def fun_l27_n485() + fun_l28_n949 +end + +def fun_l27_n486() + fun_l28_n272 +end + +def fun_l27_n487() + fun_l28_n808 +end + +def fun_l27_n488() + fun_l28_n36 +end + +def fun_l27_n489() + fun_l28_n698 +end + +def fun_l27_n490() + fun_l28_n386 +end + +def fun_l27_n491() + fun_l28_n745 +end + +def fun_l27_n492() + fun_l28_n26 +end + +def fun_l27_n493() + fun_l28_n148 +end + +def fun_l27_n494() + fun_l28_n300 +end + +def fun_l27_n495() + fun_l28_n292 +end + +def fun_l27_n496() + fun_l28_n892 +end + +def fun_l27_n497() + fun_l28_n824 +end + +def fun_l27_n498() + fun_l28_n89 +end + +def fun_l27_n499() + fun_l28_n248 +end + +def fun_l27_n500() + fun_l28_n19 +end + +def fun_l27_n501() + fun_l28_n600 +end + +def fun_l27_n502() + fun_l28_n210 +end + +def fun_l27_n503() + fun_l28_n27 +end + +def fun_l27_n504() + fun_l28_n866 +end + +def fun_l27_n505() + fun_l28_n231 +end + +def fun_l27_n506() + fun_l28_n622 +end + +def fun_l27_n507() + fun_l28_n381 +end + +def fun_l27_n508() + fun_l28_n997 +end + +def fun_l27_n509() + fun_l28_n799 +end + +def fun_l27_n510() + fun_l28_n18 +end + +def fun_l27_n511() + fun_l28_n60 +end + +def fun_l27_n512() + fun_l28_n287 +end + +def fun_l27_n513() + fun_l28_n478 +end + +def fun_l27_n514() + fun_l28_n562 +end + +def fun_l27_n515() + fun_l28_n779 +end + +def fun_l27_n516() + fun_l28_n585 +end + +def fun_l27_n517() + fun_l28_n464 +end + +def fun_l27_n518() + fun_l28_n304 +end + +def fun_l27_n519() + fun_l28_n189 +end + +def fun_l27_n520() + fun_l28_n959 +end + +def fun_l27_n521() + fun_l28_n5 +end + +def fun_l27_n522() + fun_l28_n866 +end + +def fun_l27_n523() + fun_l28_n14 +end + +def fun_l27_n524() + fun_l28_n644 +end + +def fun_l27_n525() + fun_l28_n725 +end + +def fun_l27_n526() + fun_l28_n18 +end + +def fun_l27_n527() + fun_l28_n9 +end + +def fun_l27_n528() + fun_l28_n0 +end + +def fun_l27_n529() + fun_l28_n154 +end + +def fun_l27_n530() + fun_l28_n313 +end + +def fun_l27_n531() + fun_l28_n478 +end + +def fun_l27_n532() + fun_l28_n139 +end + +def fun_l27_n533() + fun_l28_n913 +end + +def fun_l27_n534() + fun_l28_n113 +end + +def fun_l27_n535() + fun_l28_n685 +end + +def fun_l27_n536() + fun_l28_n275 +end + +def fun_l27_n537() + fun_l28_n556 +end + +def fun_l27_n538() + fun_l28_n276 +end + +def fun_l27_n539() + fun_l28_n283 +end + +def fun_l27_n540() + fun_l28_n694 +end + +def fun_l27_n541() + fun_l28_n396 +end + +def fun_l27_n542() + fun_l28_n181 +end + +def fun_l27_n543() + fun_l28_n231 +end + +def fun_l27_n544() + fun_l28_n228 +end + +def fun_l27_n545() + fun_l28_n958 +end + +def fun_l27_n546() + fun_l28_n91 +end + +def fun_l27_n547() + fun_l28_n878 +end + +def fun_l27_n548() + fun_l28_n180 +end + +def fun_l27_n549() + fun_l28_n13 +end + +def fun_l27_n550() + fun_l28_n161 +end + +def fun_l27_n551() + fun_l28_n603 +end + +def fun_l27_n552() + fun_l28_n101 +end + +def fun_l27_n553() + fun_l28_n825 +end + +def fun_l27_n554() + fun_l28_n370 +end + +def fun_l27_n555() + fun_l28_n983 +end + +def fun_l27_n556() + fun_l28_n888 +end + +def fun_l27_n557() + fun_l28_n610 +end + +def fun_l27_n558() + fun_l28_n630 +end + +def fun_l27_n559() + fun_l28_n345 +end + +def fun_l27_n560() + fun_l28_n376 +end + +def fun_l27_n561() + fun_l28_n409 +end + +def fun_l27_n562() + fun_l28_n717 +end + +def fun_l27_n563() + fun_l28_n66 +end + +def fun_l27_n564() + fun_l28_n228 +end + +def fun_l27_n565() + fun_l28_n485 +end + +def fun_l27_n566() + fun_l28_n252 +end + +def fun_l27_n567() + fun_l28_n444 +end + +def fun_l27_n568() + fun_l28_n253 +end + +def fun_l27_n569() + fun_l28_n839 +end + +def fun_l27_n570() + fun_l28_n216 +end + +def fun_l27_n571() + fun_l28_n797 +end + +def fun_l27_n572() + fun_l28_n127 +end + +def fun_l27_n573() + fun_l28_n335 +end + +def fun_l27_n574() + fun_l28_n141 +end + +def fun_l27_n575() + fun_l28_n536 +end + +def fun_l27_n576() + fun_l28_n463 +end + +def fun_l27_n577() + fun_l28_n925 +end + +def fun_l27_n578() + fun_l28_n707 +end + +def fun_l27_n579() + fun_l28_n530 +end + +def fun_l27_n580() + fun_l28_n678 +end + +def fun_l27_n581() + fun_l28_n234 +end + +def fun_l27_n582() + fun_l28_n803 +end + +def fun_l27_n583() + fun_l28_n530 +end + +def fun_l27_n584() + fun_l28_n131 +end + +def fun_l27_n585() + fun_l28_n512 +end + +def fun_l27_n586() + fun_l28_n550 +end + +def fun_l27_n587() + fun_l28_n528 +end + +def fun_l27_n588() + fun_l28_n214 +end + +def fun_l27_n589() + fun_l28_n801 +end + +def fun_l27_n590() + fun_l28_n69 +end + +def fun_l27_n591() + fun_l28_n519 +end + +def fun_l27_n592() + fun_l28_n909 +end + +def fun_l27_n593() + fun_l28_n981 +end + +def fun_l27_n594() + fun_l28_n108 +end + +def fun_l27_n595() + fun_l28_n762 +end + +def fun_l27_n596() + fun_l28_n838 +end + +def fun_l27_n597() + fun_l28_n311 +end + +def fun_l27_n598() + fun_l28_n428 +end + +def fun_l27_n599() + fun_l28_n111 +end + +def fun_l27_n600() + fun_l28_n600 +end + +def fun_l27_n601() + fun_l28_n996 +end + +def fun_l27_n602() + fun_l28_n439 +end + +def fun_l27_n603() + fun_l28_n379 +end + +def fun_l27_n604() + fun_l28_n959 +end + +def fun_l27_n605() + fun_l28_n287 +end + +def fun_l27_n606() + fun_l28_n893 +end + +def fun_l27_n607() + fun_l28_n384 +end + +def fun_l27_n608() + fun_l28_n815 +end + +def fun_l27_n609() + fun_l28_n733 +end + +def fun_l27_n610() + fun_l28_n875 +end + +def fun_l27_n611() + fun_l28_n343 +end + +def fun_l27_n612() + fun_l28_n605 +end + +def fun_l27_n613() + fun_l28_n968 +end + +def fun_l27_n614() + fun_l28_n703 +end + +def fun_l27_n615() + fun_l28_n50 +end + +def fun_l27_n616() + fun_l28_n807 +end + +def fun_l27_n617() + fun_l28_n261 +end + +def fun_l27_n618() + fun_l28_n887 +end + +def fun_l27_n619() + fun_l28_n165 +end + +def fun_l27_n620() + fun_l28_n62 +end + +def fun_l27_n621() + fun_l28_n437 +end + +def fun_l27_n622() + fun_l28_n267 +end + +def fun_l27_n623() + fun_l28_n739 +end + +def fun_l27_n624() + fun_l28_n624 +end + +def fun_l27_n625() + fun_l28_n845 +end + +def fun_l27_n626() + fun_l28_n844 +end + +def fun_l27_n627() + fun_l28_n541 +end + +def fun_l27_n628() + fun_l28_n175 +end + +def fun_l27_n629() + fun_l28_n295 +end + +def fun_l27_n630() + fun_l28_n600 +end + +def fun_l27_n631() + fun_l28_n250 +end + +def fun_l27_n632() + fun_l28_n167 +end + +def fun_l27_n633() + fun_l28_n7 +end + +def fun_l27_n634() + fun_l28_n75 +end + +def fun_l27_n635() + fun_l28_n208 +end + +def fun_l27_n636() + fun_l28_n53 +end + +def fun_l27_n637() + fun_l28_n132 +end + +def fun_l27_n638() + fun_l28_n859 +end + +def fun_l27_n639() + fun_l28_n925 +end + +def fun_l27_n640() + fun_l28_n34 +end + +def fun_l27_n641() + fun_l28_n226 +end + +def fun_l27_n642() + fun_l28_n916 +end + +def fun_l27_n643() + fun_l28_n893 +end + +def fun_l27_n644() + fun_l28_n100 +end + +def fun_l27_n645() + fun_l28_n526 +end + +def fun_l27_n646() + fun_l28_n113 +end + +def fun_l27_n647() + fun_l28_n786 +end + +def fun_l27_n648() + fun_l28_n995 +end + +def fun_l27_n649() + fun_l28_n968 +end + +def fun_l27_n650() + fun_l28_n705 +end + +def fun_l27_n651() + fun_l28_n581 +end + +def fun_l27_n652() + fun_l28_n112 +end + +def fun_l27_n653() + fun_l28_n475 +end + +def fun_l27_n654() + fun_l28_n264 +end + +def fun_l27_n655() + fun_l28_n44 +end + +def fun_l27_n656() + fun_l28_n302 +end + +def fun_l27_n657() + fun_l28_n830 +end + +def fun_l27_n658() + fun_l28_n551 +end + +def fun_l27_n659() + fun_l28_n811 +end + +def fun_l27_n660() + fun_l28_n476 +end + +def fun_l27_n661() + fun_l28_n547 +end + +def fun_l27_n662() + fun_l28_n709 +end + +def fun_l27_n663() + fun_l28_n435 +end + +def fun_l27_n664() + fun_l28_n727 +end + +def fun_l27_n665() + fun_l28_n630 +end + +def fun_l27_n666() + fun_l28_n514 +end + +def fun_l27_n667() + fun_l28_n939 +end + +def fun_l27_n668() + fun_l28_n198 +end + +def fun_l27_n669() + fun_l28_n165 +end + +def fun_l27_n670() + fun_l28_n415 +end + +def fun_l27_n671() + fun_l28_n316 +end + +def fun_l27_n672() + fun_l28_n602 +end + +def fun_l27_n673() + fun_l28_n776 +end + +def fun_l27_n674() + fun_l28_n681 +end + +def fun_l27_n675() + fun_l28_n131 +end + +def fun_l27_n676() + fun_l28_n812 +end + +def fun_l27_n677() + fun_l28_n666 +end + +def fun_l27_n678() + fun_l28_n209 +end + +def fun_l27_n679() + fun_l28_n953 +end + +def fun_l27_n680() + fun_l28_n797 +end + +def fun_l27_n681() + fun_l28_n317 +end + +def fun_l27_n682() + fun_l28_n43 +end + +def fun_l27_n683() + fun_l28_n673 +end + +def fun_l27_n684() + fun_l28_n701 +end + +def fun_l27_n685() + fun_l28_n961 +end + +def fun_l27_n686() + fun_l28_n684 +end + +def fun_l27_n687() + fun_l28_n677 +end + +def fun_l27_n688() + fun_l28_n213 +end + +def fun_l27_n689() + fun_l28_n22 +end + +def fun_l27_n690() + fun_l28_n296 +end + +def fun_l27_n691() + fun_l28_n235 +end + +def fun_l27_n692() + fun_l28_n148 +end + +def fun_l27_n693() + fun_l28_n756 +end + +def fun_l27_n694() + fun_l28_n989 +end + +def fun_l27_n695() + fun_l28_n993 +end + +def fun_l27_n696() + fun_l28_n646 +end + +def fun_l27_n697() + fun_l28_n860 +end + +def fun_l27_n698() + fun_l28_n872 +end + +def fun_l27_n699() + fun_l28_n122 +end + +def fun_l27_n700() + fun_l28_n678 +end + +def fun_l27_n701() + fun_l28_n480 +end + +def fun_l27_n702() + fun_l28_n888 +end + +def fun_l27_n703() + fun_l28_n60 +end + +def fun_l27_n704() + fun_l28_n15 +end + +def fun_l27_n705() + fun_l28_n529 +end + +def fun_l27_n706() + fun_l28_n137 +end + +def fun_l27_n707() + fun_l28_n643 +end + +def fun_l27_n708() + fun_l28_n432 +end + +def fun_l27_n709() + fun_l28_n446 +end + +def fun_l27_n710() + fun_l28_n170 +end + +def fun_l27_n711() + fun_l28_n507 +end + +def fun_l27_n712() + fun_l28_n650 +end + +def fun_l27_n713() + fun_l28_n952 +end + +def fun_l27_n714() + fun_l28_n629 +end + +def fun_l27_n715() + fun_l28_n578 +end + +def fun_l27_n716() + fun_l28_n754 +end + +def fun_l27_n717() + fun_l28_n431 +end + +def fun_l27_n718() + fun_l28_n340 +end + +def fun_l27_n719() + fun_l28_n580 +end + +def fun_l27_n720() + fun_l28_n976 +end + +def fun_l27_n721() + fun_l28_n830 +end + +def fun_l27_n722() + fun_l28_n746 +end + +def fun_l27_n723() + fun_l28_n139 +end + +def fun_l27_n724() + fun_l28_n152 +end + +def fun_l27_n725() + fun_l28_n956 +end + +def fun_l27_n726() + fun_l28_n152 +end + +def fun_l27_n727() + fun_l28_n252 +end + +def fun_l27_n728() + fun_l28_n856 +end + +def fun_l27_n729() + fun_l28_n862 +end + +def fun_l27_n730() + fun_l28_n261 +end + +def fun_l27_n731() + fun_l28_n28 +end + +def fun_l27_n732() + fun_l28_n873 +end + +def fun_l27_n733() + fun_l28_n989 +end + +def fun_l27_n734() + fun_l28_n657 +end + +def fun_l27_n735() + fun_l28_n259 +end + +def fun_l27_n736() + fun_l28_n1 +end + +def fun_l27_n737() + fun_l28_n964 +end + +def fun_l27_n738() + fun_l28_n215 +end + +def fun_l27_n739() + fun_l28_n939 +end + +def fun_l27_n740() + fun_l28_n644 +end + +def fun_l27_n741() + fun_l28_n335 +end + +def fun_l27_n742() + fun_l28_n844 +end + +def fun_l27_n743() + fun_l28_n493 +end + +def fun_l27_n744() + fun_l28_n25 +end + +def fun_l27_n745() + fun_l28_n690 +end + +def fun_l27_n746() + fun_l28_n561 +end + +def fun_l27_n747() + fun_l28_n682 +end + +def fun_l27_n748() + fun_l28_n476 +end + +def fun_l27_n749() + fun_l28_n626 +end + +def fun_l27_n750() + fun_l28_n607 +end + +def fun_l27_n751() + fun_l28_n655 +end + +def fun_l27_n752() + fun_l28_n481 +end + +def fun_l27_n753() + fun_l28_n634 +end + +def fun_l27_n754() + fun_l28_n971 +end + +def fun_l27_n755() + fun_l28_n372 +end + +def fun_l27_n756() + fun_l28_n701 +end + +def fun_l27_n757() + fun_l28_n383 +end + +def fun_l27_n758() + fun_l28_n295 +end + +def fun_l27_n759() + fun_l28_n58 +end + +def fun_l27_n760() + fun_l28_n870 +end + +def fun_l27_n761() + fun_l28_n902 +end + +def fun_l27_n762() + fun_l28_n352 +end + +def fun_l27_n763() + fun_l28_n421 +end + +def fun_l27_n764() + fun_l28_n870 +end + +def fun_l27_n765() + fun_l28_n604 +end + +def fun_l27_n766() + fun_l28_n615 +end + +def fun_l27_n767() + fun_l28_n644 +end + +def fun_l27_n768() + fun_l28_n304 +end + +def fun_l27_n769() + fun_l28_n87 +end + +def fun_l27_n770() + fun_l28_n40 +end + +def fun_l27_n771() + fun_l28_n80 +end + +def fun_l27_n772() + fun_l28_n62 +end + +def fun_l27_n773() + fun_l28_n912 +end + +def fun_l27_n774() + fun_l28_n808 +end + +def fun_l27_n775() + fun_l28_n978 +end + +def fun_l27_n776() + fun_l28_n499 +end + +def fun_l27_n777() + fun_l28_n299 +end + +def fun_l27_n778() + fun_l28_n852 +end + +def fun_l27_n779() + fun_l28_n126 +end + +def fun_l27_n780() + fun_l28_n578 +end + +def fun_l27_n781() + fun_l28_n177 +end + +def fun_l27_n782() + fun_l28_n621 +end + +def fun_l27_n783() + fun_l28_n833 +end + +def fun_l27_n784() + fun_l28_n991 +end + +def fun_l27_n785() + fun_l28_n419 +end + +def fun_l27_n786() + fun_l28_n723 +end + +def fun_l27_n787() + fun_l28_n915 +end + +def fun_l27_n788() + fun_l28_n73 +end + +def fun_l27_n789() + fun_l28_n725 +end + +def fun_l27_n790() + fun_l28_n883 +end + +def fun_l27_n791() + fun_l28_n469 +end + +def fun_l27_n792() + fun_l28_n524 +end + +def fun_l27_n793() + fun_l28_n813 +end + +def fun_l27_n794() + fun_l28_n8 +end + +def fun_l27_n795() + fun_l28_n776 +end + +def fun_l27_n796() + fun_l28_n328 +end + +def fun_l27_n797() + fun_l28_n324 +end + +def fun_l27_n798() + fun_l28_n428 +end + +def fun_l27_n799() + fun_l28_n806 +end + +def fun_l27_n800() + fun_l28_n397 +end + +def fun_l27_n801() + fun_l28_n680 +end + +def fun_l27_n802() + fun_l28_n18 +end + +def fun_l27_n803() + fun_l28_n955 +end + +def fun_l27_n804() + fun_l28_n566 +end + +def fun_l27_n805() + fun_l28_n824 +end + +def fun_l27_n806() + fun_l28_n860 +end + +def fun_l27_n807() + fun_l28_n411 +end + +def fun_l27_n808() + fun_l28_n925 +end + +def fun_l27_n809() + fun_l28_n394 +end + +def fun_l27_n810() + fun_l28_n70 +end + +def fun_l27_n811() + fun_l28_n672 +end + +def fun_l27_n812() + fun_l28_n53 +end + +def fun_l27_n813() + fun_l28_n574 +end + +def fun_l27_n814() + fun_l28_n407 +end + +def fun_l27_n815() + fun_l28_n86 +end + +def fun_l27_n816() + fun_l28_n611 +end + +def fun_l27_n817() + fun_l28_n950 +end + +def fun_l27_n818() + fun_l28_n595 +end + +def fun_l27_n819() + fun_l28_n411 +end + +def fun_l27_n820() + fun_l28_n286 +end + +def fun_l27_n821() + fun_l28_n683 +end + +def fun_l27_n822() + fun_l28_n706 +end + +def fun_l27_n823() + fun_l28_n587 +end + +def fun_l27_n824() + fun_l28_n908 +end + +def fun_l27_n825() + fun_l28_n641 +end + +def fun_l27_n826() + fun_l28_n792 +end + +def fun_l27_n827() + fun_l28_n714 +end + +def fun_l27_n828() + fun_l28_n594 +end + +def fun_l27_n829() + fun_l28_n154 +end + +def fun_l27_n830() + fun_l28_n102 +end + +def fun_l27_n831() + fun_l28_n819 +end + +def fun_l27_n832() + fun_l28_n285 +end + +def fun_l27_n833() + fun_l28_n665 +end + +def fun_l27_n834() + fun_l28_n896 +end + +def fun_l27_n835() + fun_l28_n495 +end + +def fun_l27_n836() + fun_l28_n284 +end + +def fun_l27_n837() + fun_l28_n747 +end + +def fun_l27_n838() + fun_l28_n388 +end + +def fun_l27_n839() + fun_l28_n274 +end + +def fun_l27_n840() + fun_l28_n236 +end + +def fun_l27_n841() + fun_l28_n336 +end + +def fun_l27_n842() + fun_l28_n805 +end + +def fun_l27_n843() + fun_l28_n196 +end + +def fun_l27_n844() + fun_l28_n772 +end + +def fun_l27_n845() + fun_l28_n679 +end + +def fun_l27_n846() + fun_l28_n703 +end + +def fun_l27_n847() + fun_l28_n743 +end + +def fun_l27_n848() + fun_l28_n941 +end + +def fun_l27_n849() + fun_l28_n903 +end + +def fun_l27_n850() + fun_l28_n149 +end + +def fun_l27_n851() + fun_l28_n924 +end + +def fun_l27_n852() + fun_l28_n638 +end + +def fun_l27_n853() + fun_l28_n480 +end + +def fun_l27_n854() + fun_l28_n580 +end + +def fun_l27_n855() + fun_l28_n184 +end + +def fun_l27_n856() + fun_l28_n757 +end + +def fun_l27_n857() + fun_l28_n233 +end + +def fun_l27_n858() + fun_l28_n315 +end + +def fun_l27_n859() + fun_l28_n182 +end + +def fun_l27_n860() + fun_l28_n696 +end + +def fun_l27_n861() + fun_l28_n155 +end + +def fun_l27_n862() + fun_l28_n648 +end + +def fun_l27_n863() + fun_l28_n148 +end + +def fun_l27_n864() + fun_l28_n40 +end + +def fun_l27_n865() + fun_l28_n665 +end + +def fun_l27_n866() + fun_l28_n646 +end + +def fun_l27_n867() + fun_l28_n158 +end + +def fun_l27_n868() + fun_l28_n159 +end + +def fun_l27_n869() + fun_l28_n617 +end + +def fun_l27_n870() + fun_l28_n637 +end + +def fun_l27_n871() + fun_l28_n234 +end + +def fun_l27_n872() + fun_l28_n591 +end + +def fun_l27_n873() + fun_l28_n207 +end + +def fun_l27_n874() + fun_l28_n136 +end + +def fun_l27_n875() + fun_l28_n565 +end + +def fun_l27_n876() + fun_l28_n152 +end + +def fun_l27_n877() + fun_l28_n309 +end + +def fun_l27_n878() + fun_l28_n275 +end + +def fun_l27_n879() + fun_l28_n355 +end + +def fun_l27_n880() + fun_l28_n441 +end + +def fun_l27_n881() + fun_l28_n427 +end + +def fun_l27_n882() + fun_l28_n249 +end + +def fun_l27_n883() + fun_l28_n764 +end + +def fun_l27_n884() + fun_l28_n183 +end + +def fun_l27_n885() + fun_l28_n302 +end + +def fun_l27_n886() + fun_l28_n857 +end + +def fun_l27_n887() + fun_l28_n73 +end + +def fun_l27_n888() + fun_l28_n702 +end + +def fun_l27_n889() + fun_l28_n430 +end + +def fun_l27_n890() + fun_l28_n57 +end + +def fun_l27_n891() + fun_l28_n994 +end + +def fun_l27_n892() + fun_l28_n951 +end + +def fun_l27_n893() + fun_l28_n268 +end + +def fun_l27_n894() + fun_l28_n629 +end + +def fun_l27_n895() + fun_l28_n505 +end + +def fun_l27_n896() + fun_l28_n790 +end + +def fun_l27_n897() + fun_l28_n213 +end + +def fun_l27_n898() + fun_l28_n133 +end + +def fun_l27_n899() + fun_l28_n472 +end + +def fun_l27_n900() + fun_l28_n212 +end + +def fun_l27_n901() + fun_l28_n386 +end + +def fun_l27_n902() + fun_l28_n405 +end + +def fun_l27_n903() + fun_l28_n807 +end + +def fun_l27_n904() + fun_l28_n76 +end + +def fun_l27_n905() + fun_l28_n295 +end + +def fun_l27_n906() + fun_l28_n860 +end + +def fun_l27_n907() + fun_l28_n185 +end + +def fun_l27_n908() + fun_l28_n762 +end + +def fun_l27_n909() + fun_l28_n493 +end + +def fun_l27_n910() + fun_l28_n309 +end + +def fun_l27_n911() + fun_l28_n920 +end + +def fun_l27_n912() + fun_l28_n284 +end + +def fun_l27_n913() + fun_l28_n355 +end + +def fun_l27_n914() + fun_l28_n177 +end + +def fun_l27_n915() + fun_l28_n901 +end + +def fun_l27_n916() + fun_l28_n858 +end + +def fun_l27_n917() + fun_l28_n337 +end + +def fun_l27_n918() + fun_l28_n872 +end + +def fun_l27_n919() + fun_l28_n550 +end + +def fun_l27_n920() + fun_l28_n458 +end + +def fun_l27_n921() + fun_l28_n739 +end + +def fun_l27_n922() + fun_l28_n394 +end + +def fun_l27_n923() + fun_l28_n695 +end + +def fun_l27_n924() + fun_l28_n455 +end + +def fun_l27_n925() + fun_l28_n958 +end + +def fun_l27_n926() + fun_l28_n395 +end + +def fun_l27_n927() + fun_l28_n645 +end + +def fun_l27_n928() + fun_l28_n668 +end + +def fun_l27_n929() + fun_l28_n880 +end + +def fun_l27_n930() + fun_l28_n743 +end + +def fun_l27_n931() + fun_l28_n411 +end + +def fun_l27_n932() + fun_l28_n457 +end + +def fun_l27_n933() + fun_l28_n852 +end + +def fun_l27_n934() + fun_l28_n3 +end + +def fun_l27_n935() + fun_l28_n637 +end + +def fun_l27_n936() + fun_l28_n35 +end + +def fun_l27_n937() + fun_l28_n671 +end + +def fun_l27_n938() + fun_l28_n996 +end + +def fun_l27_n939() + fun_l28_n545 +end + +def fun_l27_n940() + fun_l28_n714 +end + +def fun_l27_n941() + fun_l28_n527 +end + +def fun_l27_n942() + fun_l28_n272 +end + +def fun_l27_n943() + fun_l28_n62 +end + +def fun_l27_n944() + fun_l28_n206 +end + +def fun_l27_n945() + fun_l28_n115 +end + +def fun_l27_n946() + fun_l28_n654 +end + +def fun_l27_n947() + fun_l28_n218 +end + +def fun_l27_n948() + fun_l28_n315 +end + +def fun_l27_n949() + fun_l28_n656 +end + +def fun_l27_n950() + fun_l28_n901 +end + +def fun_l27_n951() + fun_l28_n60 +end + +def fun_l27_n952() + fun_l28_n886 +end + +def fun_l27_n953() + fun_l28_n888 +end + +def fun_l27_n954() + fun_l28_n640 +end + +def fun_l27_n955() + fun_l28_n766 +end + +def fun_l27_n956() + fun_l28_n506 +end + +def fun_l27_n957() + fun_l28_n757 +end + +def fun_l27_n958() + fun_l28_n204 +end + +def fun_l27_n959() + fun_l28_n531 +end + +def fun_l27_n960() + fun_l28_n982 +end + +def fun_l27_n961() + fun_l28_n762 +end + +def fun_l27_n962() + fun_l28_n701 +end + +def fun_l27_n963() + fun_l28_n866 +end + +def fun_l27_n964() + fun_l28_n488 +end + +def fun_l27_n965() + fun_l28_n793 +end + +def fun_l27_n966() + fun_l28_n969 +end + +def fun_l27_n967() + fun_l28_n35 +end + +def fun_l27_n968() + fun_l28_n54 +end + +def fun_l27_n969() + fun_l28_n746 +end + +def fun_l27_n970() + fun_l28_n437 +end + +def fun_l27_n971() + fun_l28_n601 +end + +def fun_l27_n972() + fun_l28_n477 +end + +def fun_l27_n973() + fun_l28_n854 +end + +def fun_l27_n974() + fun_l28_n76 +end + +def fun_l27_n975() + fun_l28_n145 +end + +def fun_l27_n976() + fun_l28_n156 +end + +def fun_l27_n977() + fun_l28_n719 +end + +def fun_l27_n978() + fun_l28_n389 +end + +def fun_l27_n979() + fun_l28_n482 +end + +def fun_l27_n980() + fun_l28_n369 +end + +def fun_l27_n981() + fun_l28_n42 +end + +def fun_l27_n982() + fun_l28_n975 +end + +def fun_l27_n983() + fun_l28_n995 +end + +def fun_l27_n984() + fun_l28_n880 +end + +def fun_l27_n985() + fun_l28_n688 +end + +def fun_l27_n986() + fun_l28_n796 +end + +def fun_l27_n987() + fun_l28_n291 +end + +def fun_l27_n988() + fun_l28_n158 +end + +def fun_l27_n989() + fun_l28_n389 +end + +def fun_l27_n990() + fun_l28_n582 +end + +def fun_l27_n991() + fun_l28_n108 +end + +def fun_l27_n992() + fun_l28_n280 +end + +def fun_l27_n993() + fun_l28_n842 +end + +def fun_l27_n994() + fun_l28_n637 +end + +def fun_l27_n995() + fun_l28_n934 +end + +def fun_l27_n996() + fun_l28_n451 +end + +def fun_l27_n997() + fun_l28_n22 +end + +def fun_l27_n998() + fun_l28_n733 +end + +def fun_l27_n999() + fun_l28_n984 +end + +def fun_l28_n0() + fun_l29_n189 +end + +def fun_l28_n1() + fun_l29_n12 +end + +def fun_l28_n2() + fun_l29_n850 +end + +def fun_l28_n3() + fun_l29_n360 +end + +def fun_l28_n4() + fun_l29_n510 +end + +def fun_l28_n5() + fun_l29_n541 +end + +def fun_l28_n6() + fun_l29_n913 +end + +def fun_l28_n7() + fun_l29_n652 +end + +def fun_l28_n8() + fun_l29_n378 +end + +def fun_l28_n9() + fun_l29_n476 +end + +def fun_l28_n10() + fun_l29_n644 +end + +def fun_l28_n11() + fun_l29_n484 +end + +def fun_l28_n12() + fun_l29_n52 +end + +def fun_l28_n13() + fun_l29_n294 +end + +def fun_l28_n14() + fun_l29_n387 +end + +def fun_l28_n15() + fun_l29_n331 +end + +def fun_l28_n16() + fun_l29_n578 +end + +def fun_l28_n17() + fun_l29_n783 +end + +def fun_l28_n18() + fun_l29_n838 +end + +def fun_l28_n19() + fun_l29_n5 +end + +def fun_l28_n20() + fun_l29_n909 +end + +def fun_l28_n21() + fun_l29_n671 +end + +def fun_l28_n22() + fun_l29_n626 +end + +def fun_l28_n23() + fun_l29_n685 +end + +def fun_l28_n24() + fun_l29_n22 +end + +def fun_l28_n25() + fun_l29_n925 +end + +def fun_l28_n26() + fun_l29_n816 +end + +def fun_l28_n27() + fun_l29_n714 +end + +def fun_l28_n28() + fun_l29_n863 +end + +def fun_l28_n29() + fun_l29_n475 +end + +def fun_l28_n30() + fun_l29_n83 +end + +def fun_l28_n31() + fun_l29_n854 +end + +def fun_l28_n32() + fun_l29_n616 +end + +def fun_l28_n33() + fun_l29_n574 +end + +def fun_l28_n34() + fun_l29_n745 +end + +def fun_l28_n35() + fun_l29_n921 +end + +def fun_l28_n36() + fun_l29_n639 +end + +def fun_l28_n37() + fun_l29_n695 +end + +def fun_l28_n38() + fun_l29_n527 +end + +def fun_l28_n39() + fun_l29_n691 +end + +def fun_l28_n40() + fun_l29_n409 +end + +def fun_l28_n41() + fun_l29_n788 +end + +def fun_l28_n42() + fun_l29_n671 +end + +def fun_l28_n43() + fun_l29_n855 +end + +def fun_l28_n44() + fun_l29_n364 +end + +def fun_l28_n45() + fun_l29_n231 +end + +def fun_l28_n46() + fun_l29_n852 +end + +def fun_l28_n47() + fun_l29_n596 +end + +def fun_l28_n48() + fun_l29_n804 +end + +def fun_l28_n49() + fun_l29_n513 +end + +def fun_l28_n50() + fun_l29_n498 +end + +def fun_l28_n51() + fun_l29_n548 +end + +def fun_l28_n52() + fun_l29_n641 +end + +def fun_l28_n53() + fun_l29_n784 +end + +def fun_l28_n54() + fun_l29_n803 +end + +def fun_l28_n55() + fun_l29_n384 +end + +def fun_l28_n56() + fun_l29_n304 +end + +def fun_l28_n57() + fun_l29_n894 +end + +def fun_l28_n58() + fun_l29_n233 +end + +def fun_l28_n59() + fun_l29_n344 +end + +def fun_l28_n60() + fun_l29_n652 +end + +def fun_l28_n61() + fun_l29_n912 +end + +def fun_l28_n62() + fun_l29_n266 +end + +def fun_l28_n63() + fun_l29_n228 +end + +def fun_l28_n64() + fun_l29_n31 +end + +def fun_l28_n65() + fun_l29_n679 +end + +def fun_l28_n66() + fun_l29_n902 +end + +def fun_l28_n67() + fun_l29_n907 +end + +def fun_l28_n68() + fun_l29_n830 +end + +def fun_l28_n69() + fun_l29_n849 +end + +def fun_l28_n70() + fun_l29_n551 +end + +def fun_l28_n71() + fun_l29_n586 +end + +def fun_l28_n72() + fun_l29_n126 +end + +def fun_l28_n73() + fun_l29_n75 +end + +def fun_l28_n74() + fun_l29_n706 +end + +def fun_l28_n75() + fun_l29_n82 +end + +def fun_l28_n76() + fun_l29_n194 +end + +def fun_l28_n77() + fun_l29_n761 +end + +def fun_l28_n78() + fun_l29_n439 +end + +def fun_l28_n79() + fun_l29_n53 +end + +def fun_l28_n80() + fun_l29_n889 +end + +def fun_l28_n81() + fun_l29_n743 +end + +def fun_l28_n82() + fun_l29_n545 +end + +def fun_l28_n83() + fun_l29_n88 +end + +def fun_l28_n84() + fun_l29_n697 +end + +def fun_l28_n85() + fun_l29_n160 +end + +def fun_l28_n86() + fun_l29_n895 +end + +def fun_l28_n87() + fun_l29_n475 +end + +def fun_l28_n88() + fun_l29_n330 +end + +def fun_l28_n89() + fun_l29_n464 +end + +def fun_l28_n90() + fun_l29_n772 +end + +def fun_l28_n91() + fun_l29_n241 +end + +def fun_l28_n92() + fun_l29_n838 +end + +def fun_l28_n93() + fun_l29_n322 +end + +def fun_l28_n94() + fun_l29_n328 +end + +def fun_l28_n95() + fun_l29_n475 +end + +def fun_l28_n96() + fun_l29_n523 +end + +def fun_l28_n97() + fun_l29_n621 +end + +def fun_l28_n98() + fun_l29_n646 +end + +def fun_l28_n99() + fun_l29_n803 +end + +def fun_l28_n100() + fun_l29_n121 +end + +def fun_l28_n101() + fun_l29_n432 +end + +def fun_l28_n102() + fun_l29_n14 +end + +def fun_l28_n103() + fun_l29_n358 +end + +def fun_l28_n104() + fun_l29_n257 +end + +def fun_l28_n105() + fun_l29_n985 +end + +def fun_l28_n106() + fun_l29_n392 +end + +def fun_l28_n107() + fun_l29_n11 +end + +def fun_l28_n108() + fun_l29_n254 +end + +def fun_l28_n109() + fun_l29_n17 +end + +def fun_l28_n110() + fun_l29_n146 +end + +def fun_l28_n111() + fun_l29_n20 +end + +def fun_l28_n112() + fun_l29_n189 +end + +def fun_l28_n113() + fun_l29_n838 +end + +def fun_l28_n114() + fun_l29_n251 +end + +def fun_l28_n115() + fun_l29_n331 +end + +def fun_l28_n116() + fun_l29_n816 +end + +def fun_l28_n117() + fun_l29_n338 +end + +def fun_l28_n118() + fun_l29_n745 +end + +def fun_l28_n119() + fun_l29_n301 +end + +def fun_l28_n120() + fun_l29_n647 +end + +def fun_l28_n121() + fun_l29_n71 +end + +def fun_l28_n122() + fun_l29_n371 +end + +def fun_l28_n123() + fun_l29_n586 +end + +def fun_l28_n124() + fun_l29_n868 +end + +def fun_l28_n125() + fun_l29_n519 +end + +def fun_l28_n126() + fun_l29_n877 +end + +def fun_l28_n127() + fun_l29_n716 +end + +def fun_l28_n128() + fun_l29_n184 +end + +def fun_l28_n129() + fun_l29_n797 +end + +def fun_l28_n130() + fun_l29_n801 +end + +def fun_l28_n131() + fun_l29_n278 +end + +def fun_l28_n132() + fun_l29_n562 +end + +def fun_l28_n133() + fun_l29_n999 +end + +def fun_l28_n134() + fun_l29_n128 +end + +def fun_l28_n135() + fun_l29_n134 +end + +def fun_l28_n136() + fun_l29_n62 +end + +def fun_l28_n137() + fun_l29_n923 +end + +def fun_l28_n138() + fun_l29_n870 +end + +def fun_l28_n139() + fun_l29_n279 +end + +def fun_l28_n140() + fun_l29_n971 +end + +def fun_l28_n141() + fun_l29_n843 +end + +def fun_l28_n142() + fun_l29_n537 +end + +def fun_l28_n143() + fun_l29_n584 +end + +def fun_l28_n144() + fun_l29_n961 +end + +def fun_l28_n145() + fun_l29_n383 +end + +def fun_l28_n146() + fun_l29_n44 +end + +def fun_l28_n147() + fun_l29_n291 +end + +def fun_l28_n148() + fun_l29_n639 +end + +def fun_l28_n149() + fun_l29_n751 +end + +def fun_l28_n150() + fun_l29_n504 +end + +def fun_l28_n151() + fun_l29_n884 +end + +def fun_l28_n152() + fun_l29_n505 +end + +def fun_l28_n153() + fun_l29_n932 +end + +def fun_l28_n154() + fun_l29_n414 +end + +def fun_l28_n155() + fun_l29_n121 +end + +def fun_l28_n156() + fun_l29_n313 +end + +def fun_l28_n157() + fun_l29_n620 +end + +def fun_l28_n158() + fun_l29_n412 +end + +def fun_l28_n159() + fun_l29_n119 +end + +def fun_l28_n160() + fun_l29_n431 +end + +def fun_l28_n161() + fun_l29_n943 +end + +def fun_l28_n162() + fun_l29_n499 +end + +def fun_l28_n163() + fun_l29_n494 +end + +def fun_l28_n164() + fun_l29_n716 +end + +def fun_l28_n165() + fun_l29_n558 +end + +def fun_l28_n166() + fun_l29_n864 +end + +def fun_l28_n167() + fun_l29_n13 +end + +def fun_l28_n168() + fun_l29_n165 +end + +def fun_l28_n169() + fun_l29_n129 +end + +def fun_l28_n170() + fun_l29_n478 +end + +def fun_l28_n171() + fun_l29_n124 +end + +def fun_l28_n172() + fun_l29_n945 +end + +def fun_l28_n173() + fun_l29_n574 +end + +def fun_l28_n174() + fun_l29_n916 +end + +def fun_l28_n175() + fun_l29_n213 +end + +def fun_l28_n176() + fun_l29_n68 +end + +def fun_l28_n177() + fun_l29_n66 +end + +def fun_l28_n178() + fun_l29_n979 +end + +def fun_l28_n179() + fun_l29_n909 +end + +def fun_l28_n180() + fun_l29_n509 +end + +def fun_l28_n181() + fun_l29_n663 +end + +def fun_l28_n182() + fun_l29_n407 +end + +def fun_l28_n183() + fun_l29_n692 +end + +def fun_l28_n184() + fun_l29_n569 +end + +def fun_l28_n185() + fun_l29_n950 +end + +def fun_l28_n186() + fun_l29_n266 +end + +def fun_l28_n187() + fun_l29_n48 +end + +def fun_l28_n188() + fun_l29_n244 +end + +def fun_l28_n189() + fun_l29_n428 +end + +def fun_l28_n190() + fun_l29_n893 +end + +def fun_l28_n191() + fun_l29_n581 +end + +def fun_l28_n192() + fun_l29_n210 +end + +def fun_l28_n193() + fun_l29_n81 +end + +def fun_l28_n194() + fun_l29_n295 +end + +def fun_l28_n195() + fun_l29_n471 +end + +def fun_l28_n196() + fun_l29_n967 +end + +def fun_l28_n197() + fun_l29_n318 +end + +def fun_l28_n198() + fun_l29_n15 +end + +def fun_l28_n199() + fun_l29_n696 +end + +def fun_l28_n200() + fun_l29_n702 +end + +def fun_l28_n201() + fun_l29_n737 +end + +def fun_l28_n202() + fun_l29_n776 +end + +def fun_l28_n203() + fun_l29_n623 +end + +def fun_l28_n204() + fun_l29_n537 +end + +def fun_l28_n205() + fun_l29_n353 +end + +def fun_l28_n206() + fun_l29_n156 +end + +def fun_l28_n207() + fun_l29_n690 +end + +def fun_l28_n208() + fun_l29_n408 +end + +def fun_l28_n209() + fun_l29_n388 +end + +def fun_l28_n210() + fun_l29_n721 +end + +def fun_l28_n211() + fun_l29_n46 +end + +def fun_l28_n212() + fun_l29_n238 +end + +def fun_l28_n213() + fun_l29_n722 +end + +def fun_l28_n214() + fun_l29_n827 +end + +def fun_l28_n215() + fun_l29_n496 +end + +def fun_l28_n216() + fun_l29_n10 +end + +def fun_l28_n217() + fun_l29_n689 +end + +def fun_l28_n218() + fun_l29_n962 +end + +def fun_l28_n219() + fun_l29_n364 +end + +def fun_l28_n220() + fun_l29_n92 +end + +def fun_l28_n221() + fun_l29_n246 +end + +def fun_l28_n222() + fun_l29_n624 +end + +def fun_l28_n223() + fun_l29_n482 +end + +def fun_l28_n224() + fun_l29_n992 +end + +def fun_l28_n225() + fun_l29_n746 +end + +def fun_l28_n226() + fun_l29_n44 +end + +def fun_l28_n227() + fun_l29_n389 +end + +def fun_l28_n228() + fun_l29_n278 +end + +def fun_l28_n229() + fun_l29_n336 +end + +def fun_l28_n230() + fun_l29_n415 +end + +def fun_l28_n231() + fun_l29_n670 +end + +def fun_l28_n232() + fun_l29_n132 +end + +def fun_l28_n233() + fun_l29_n669 +end + +def fun_l28_n234() + fun_l29_n815 +end + +def fun_l28_n235() + fun_l29_n642 +end + +def fun_l28_n236() + fun_l29_n59 +end + +def fun_l28_n237() + fun_l29_n175 +end + +def fun_l28_n238() + fun_l29_n862 +end + +def fun_l28_n239() + fun_l29_n570 +end + +def fun_l28_n240() + fun_l29_n65 +end + +def fun_l28_n241() + fun_l29_n286 +end + +def fun_l28_n242() + fun_l29_n467 +end + +def fun_l28_n243() + fun_l29_n580 +end + +def fun_l28_n244() + fun_l29_n195 +end + +def fun_l28_n245() + fun_l29_n571 +end + +def fun_l28_n246() + fun_l29_n987 +end + +def fun_l28_n247() + fun_l29_n87 +end + +def fun_l28_n248() + fun_l29_n331 +end + +def fun_l28_n249() + fun_l29_n405 +end + +def fun_l28_n250() + fun_l29_n142 +end + +def fun_l28_n251() + fun_l29_n652 +end + +def fun_l28_n252() + fun_l29_n788 +end + +def fun_l28_n253() + fun_l29_n591 +end + +def fun_l28_n254() + fun_l29_n613 +end + +def fun_l28_n255() + fun_l29_n171 +end + +def fun_l28_n256() + fun_l29_n836 +end + +def fun_l28_n257() + fun_l29_n420 +end + +def fun_l28_n258() + fun_l29_n326 +end + +def fun_l28_n259() + fun_l29_n790 +end + +def fun_l28_n260() + fun_l29_n515 +end + +def fun_l28_n261() + fun_l29_n650 +end + +def fun_l28_n262() + fun_l29_n388 +end + +def fun_l28_n263() + fun_l29_n56 +end + +def fun_l28_n264() + fun_l29_n288 +end + +def fun_l28_n265() + fun_l29_n187 +end + +def fun_l28_n266() + fun_l29_n461 +end + +def fun_l28_n267() + fun_l29_n194 +end + +def fun_l28_n268() + fun_l29_n870 +end + +def fun_l28_n269() + fun_l29_n425 +end + +def fun_l28_n270() + fun_l29_n731 +end + +def fun_l28_n271() + fun_l29_n763 +end + +def fun_l28_n272() + fun_l29_n128 +end + +def fun_l28_n273() + fun_l29_n693 +end + +def fun_l28_n274() + fun_l29_n775 +end + +def fun_l28_n275() + fun_l29_n769 +end + +def fun_l28_n276() + fun_l29_n491 +end + +def fun_l28_n277() + fun_l29_n799 +end + +def fun_l28_n278() + fun_l29_n506 +end + +def fun_l28_n279() + fun_l29_n607 +end + +def fun_l28_n280() + fun_l29_n988 +end + +def fun_l28_n281() + fun_l29_n290 +end + +def fun_l28_n282() + fun_l29_n389 +end + +def fun_l28_n283() + fun_l29_n133 +end + +def fun_l28_n284() + fun_l29_n631 +end + +def fun_l28_n285() + fun_l29_n285 +end + +def fun_l28_n286() + fun_l29_n537 +end + +def fun_l28_n287() + fun_l29_n911 +end + +def fun_l28_n288() + fun_l29_n297 +end + +def fun_l28_n289() + fun_l29_n585 +end + +def fun_l28_n290() + fun_l29_n535 +end + +def fun_l28_n291() + fun_l29_n570 +end + +def fun_l28_n292() + fun_l29_n19 +end + +def fun_l28_n293() + fun_l29_n444 +end + +def fun_l28_n294() + fun_l29_n44 +end + +def fun_l28_n295() + fun_l29_n252 +end + +def fun_l28_n296() + fun_l29_n623 +end + +def fun_l28_n297() + fun_l29_n398 +end + +def fun_l28_n298() + fun_l29_n716 +end + +def fun_l28_n299() + fun_l29_n607 +end + +def fun_l28_n300() + fun_l29_n105 +end + +def fun_l28_n301() + fun_l29_n438 +end + +def fun_l28_n302() + fun_l29_n308 +end + +def fun_l28_n303() + fun_l29_n301 +end + +def fun_l28_n304() + fun_l29_n577 +end + +def fun_l28_n305() + fun_l29_n537 +end + +def fun_l28_n306() + fun_l29_n375 +end + +def fun_l28_n307() + fun_l29_n211 +end + +def fun_l28_n308() + fun_l29_n227 +end + +def fun_l28_n309() + fun_l29_n275 +end + +def fun_l28_n310() + fun_l29_n122 +end + +def fun_l28_n311() + fun_l29_n983 +end + +def fun_l28_n312() + fun_l29_n844 +end + +def fun_l28_n313() + fun_l29_n865 +end + +def fun_l28_n314() + fun_l29_n27 +end + +def fun_l28_n315() + fun_l29_n933 +end + +def fun_l28_n316() + fun_l29_n89 +end + +def fun_l28_n317() + fun_l29_n11 +end + +def fun_l28_n318() + fun_l29_n107 +end + +def fun_l28_n319() + fun_l29_n604 +end + +def fun_l28_n320() + fun_l29_n768 +end + +def fun_l28_n321() + fun_l29_n638 +end + +def fun_l28_n322() + fun_l29_n513 +end + +def fun_l28_n323() + fun_l29_n61 +end + +def fun_l28_n324() + fun_l29_n776 +end + +def fun_l28_n325() + fun_l29_n377 +end + +def fun_l28_n326() + fun_l29_n768 +end + +def fun_l28_n327() + fun_l29_n573 +end + +def fun_l28_n328() + fun_l29_n719 +end + +def fun_l28_n329() + fun_l29_n878 +end + +def fun_l28_n330() + fun_l29_n995 +end + +def fun_l28_n331() + fun_l29_n32 +end + +def fun_l28_n332() + fun_l29_n647 +end + +def fun_l28_n333() + fun_l29_n570 +end + +def fun_l28_n334() + fun_l29_n194 +end + +def fun_l28_n335() + fun_l29_n182 +end + +def fun_l28_n336() + fun_l29_n463 +end + +def fun_l28_n337() + fun_l29_n677 +end + +def fun_l28_n338() + fun_l29_n524 +end + +def fun_l28_n339() + fun_l29_n221 +end + +def fun_l28_n340() + fun_l29_n120 +end + +def fun_l28_n341() + fun_l29_n633 +end + +def fun_l28_n342() + fun_l29_n428 +end + +def fun_l28_n343() + fun_l29_n510 +end + +def fun_l28_n344() + fun_l29_n576 +end + +def fun_l28_n345() + fun_l29_n423 +end + +def fun_l28_n346() + fun_l29_n412 +end + +def fun_l28_n347() + fun_l29_n315 +end + +def fun_l28_n348() + fun_l29_n809 +end + +def fun_l28_n349() + fun_l29_n195 +end + +def fun_l28_n350() + fun_l29_n724 +end + +def fun_l28_n351() + fun_l29_n438 +end + +def fun_l28_n352() + fun_l29_n229 +end + +def fun_l28_n353() + fun_l29_n113 +end + +def fun_l28_n354() + fun_l29_n58 +end + +def fun_l28_n355() + fun_l29_n105 +end + +def fun_l28_n356() + fun_l29_n371 +end + +def fun_l28_n357() + fun_l29_n397 +end + +def fun_l28_n358() + fun_l29_n441 +end + +def fun_l28_n359() + fun_l29_n765 +end + +def fun_l28_n360() + fun_l29_n752 +end + +def fun_l28_n361() + fun_l29_n255 +end + +def fun_l28_n362() + fun_l29_n981 +end + +def fun_l28_n363() + fun_l29_n612 +end + +def fun_l28_n364() + fun_l29_n268 +end + +def fun_l28_n365() + fun_l29_n573 +end + +def fun_l28_n366() + fun_l29_n202 +end + +def fun_l28_n367() + fun_l29_n477 +end + +def fun_l28_n368() + fun_l29_n353 +end + +def fun_l28_n369() + fun_l29_n244 +end + +def fun_l28_n370() + fun_l29_n348 +end + +def fun_l28_n371() + fun_l29_n96 +end + +def fun_l28_n372() + fun_l29_n421 +end + +def fun_l28_n373() + fun_l29_n685 +end + +def fun_l28_n374() + fun_l29_n408 +end + +def fun_l28_n375() + fun_l29_n971 +end + +def fun_l28_n376() + fun_l29_n372 +end + +def fun_l28_n377() + fun_l29_n852 +end + +def fun_l28_n378() + fun_l29_n872 +end + +def fun_l28_n379() + fun_l29_n981 +end + +def fun_l28_n380() + fun_l29_n939 +end + +def fun_l28_n381() + fun_l29_n13 +end + +def fun_l28_n382() + fun_l29_n381 +end + +def fun_l28_n383() + fun_l29_n291 +end + +def fun_l28_n384() + fun_l29_n465 +end + +def fun_l28_n385() + fun_l29_n309 +end + +def fun_l28_n386() + fun_l29_n53 +end + +def fun_l28_n387() + fun_l29_n525 +end + +def fun_l28_n388() + fun_l29_n756 +end + +def fun_l28_n389() + fun_l29_n347 +end + +def fun_l28_n390() + fun_l29_n517 +end + +def fun_l28_n391() + fun_l29_n275 +end + +def fun_l28_n392() + fun_l29_n973 +end + +def fun_l28_n393() + fun_l29_n538 +end + +def fun_l28_n394() + fun_l29_n429 +end + +def fun_l28_n395() + fun_l29_n219 +end + +def fun_l28_n396() + fun_l29_n823 +end + +def fun_l28_n397() + fun_l29_n676 +end + +def fun_l28_n398() + fun_l29_n319 +end + +def fun_l28_n399() + fun_l29_n784 +end + +def fun_l28_n400() + fun_l29_n741 +end + +def fun_l28_n401() + fun_l29_n876 +end + +def fun_l28_n402() + fun_l29_n648 +end + +def fun_l28_n403() + fun_l29_n231 +end + +def fun_l28_n404() + fun_l29_n459 +end + +def fun_l28_n405() + fun_l29_n350 +end + +def fun_l28_n406() + fun_l29_n398 +end + +def fun_l28_n407() + fun_l29_n692 +end + +def fun_l28_n408() + fun_l29_n91 +end + +def fun_l28_n409() + fun_l29_n120 +end + +def fun_l28_n410() + fun_l29_n337 +end + +def fun_l28_n411() + fun_l29_n963 +end + +def fun_l28_n412() + fun_l29_n16 +end + +def fun_l28_n413() + fun_l29_n956 +end + +def fun_l28_n414() + fun_l29_n255 +end + +def fun_l28_n415() + fun_l29_n309 +end + +def fun_l28_n416() + fun_l29_n430 +end + +def fun_l28_n417() + fun_l29_n374 +end + +def fun_l28_n418() + fun_l29_n559 +end + +def fun_l28_n419() + fun_l29_n393 +end + +def fun_l28_n420() + fun_l29_n547 +end + +def fun_l28_n421() + fun_l29_n500 +end + +def fun_l28_n422() + fun_l29_n771 +end + +def fun_l28_n423() + fun_l29_n429 +end + +def fun_l28_n424() + fun_l29_n839 +end + +def fun_l28_n425() + fun_l29_n871 +end + +def fun_l28_n426() + fun_l29_n333 +end + +def fun_l28_n427() + fun_l29_n652 +end + +def fun_l28_n428() + fun_l29_n87 +end + +def fun_l28_n429() + fun_l29_n472 +end + +def fun_l28_n430() + fun_l29_n911 +end + +def fun_l28_n431() + fun_l29_n305 +end + +def fun_l28_n432() + fun_l29_n569 +end + +def fun_l28_n433() + fun_l29_n869 +end + +def fun_l28_n434() + fun_l29_n203 +end + +def fun_l28_n435() + fun_l29_n804 +end + +def fun_l28_n436() + fun_l29_n878 +end + +def fun_l28_n437() + fun_l29_n984 +end + +def fun_l28_n438() + fun_l29_n990 +end + +def fun_l28_n439() + fun_l29_n860 +end + +def fun_l28_n440() + fun_l29_n866 +end + +def fun_l28_n441() + fun_l29_n625 +end + +def fun_l28_n442() + fun_l29_n534 +end + +def fun_l28_n443() + fun_l29_n232 +end + +def fun_l28_n444() + fun_l29_n447 +end + +def fun_l28_n445() + fun_l29_n958 +end + +def fun_l28_n446() + fun_l29_n343 +end + +def fun_l28_n447() + fun_l29_n128 +end + +def fun_l28_n448() + fun_l29_n760 +end + +def fun_l28_n449() + fun_l29_n204 +end + +def fun_l28_n450() + fun_l29_n912 +end + +def fun_l28_n451() + fun_l29_n395 +end + +def fun_l28_n452() + fun_l29_n721 +end + +def fun_l28_n453() + fun_l29_n699 +end + +def fun_l28_n454() + fun_l29_n950 +end + +def fun_l28_n455() + fun_l29_n436 +end + +def fun_l28_n456() + fun_l29_n431 +end + +def fun_l28_n457() + fun_l29_n644 +end + +def fun_l28_n458() + fun_l29_n638 +end + +def fun_l28_n459() + fun_l29_n967 +end + +def fun_l28_n460() + fun_l29_n83 +end + +def fun_l28_n461() + fun_l29_n141 +end + +def fun_l28_n462() + fun_l29_n37 +end + +def fun_l28_n463() + fun_l29_n485 +end + +def fun_l28_n464() + fun_l29_n826 +end + +def fun_l28_n465() + fun_l29_n774 +end + +def fun_l28_n466() + fun_l29_n561 +end + +def fun_l28_n467() + fun_l29_n809 +end + +def fun_l28_n468() + fun_l29_n298 +end + +def fun_l28_n469() + fun_l29_n367 +end + +def fun_l28_n470() + fun_l29_n517 +end + +def fun_l28_n471() + fun_l29_n30 +end + +def fun_l28_n472() + fun_l29_n970 +end + +def fun_l28_n473() + fun_l29_n686 +end + +def fun_l28_n474() + fun_l29_n183 +end + +def fun_l28_n475() + fun_l29_n176 +end + +def fun_l28_n476() + fun_l29_n87 +end + +def fun_l28_n477() + fun_l29_n81 +end + +def fun_l28_n478() + fun_l29_n836 +end + +def fun_l28_n479() + fun_l29_n898 +end + +def fun_l28_n480() + fun_l29_n49 +end + +def fun_l28_n481() + fun_l29_n468 +end + +def fun_l28_n482() + fun_l29_n314 +end + +def fun_l28_n483() + fun_l29_n242 +end + +def fun_l28_n484() + fun_l29_n647 +end + +def fun_l28_n485() + fun_l29_n167 +end + +def fun_l28_n486() + fun_l29_n245 +end + +def fun_l28_n487() + fun_l29_n723 +end + +def fun_l28_n488() + fun_l29_n576 +end + +def fun_l28_n489() + fun_l29_n481 +end + +def fun_l28_n490() + fun_l29_n154 +end + +def fun_l28_n491() + fun_l29_n271 +end + +def fun_l28_n492() + fun_l29_n671 +end + +def fun_l28_n493() + fun_l29_n70 +end + +def fun_l28_n494() + fun_l29_n14 +end + +def fun_l28_n495() + fun_l29_n108 +end + +def fun_l28_n496() + fun_l29_n464 +end + +def fun_l28_n497() + fun_l29_n7 +end + +def fun_l28_n498() + fun_l29_n372 +end + +def fun_l28_n499() + fun_l29_n202 +end + +def fun_l28_n500() + fun_l29_n208 +end + +def fun_l28_n501() + fun_l29_n640 +end + +def fun_l28_n502() + fun_l29_n977 +end + +def fun_l28_n503() + fun_l29_n287 +end + +def fun_l28_n504() + fun_l29_n905 +end + +def fun_l28_n505() + fun_l29_n847 +end + +def fun_l28_n506() + fun_l29_n18 +end + +def fun_l28_n507() + fun_l29_n889 +end + +def fun_l28_n508() + fun_l29_n527 +end + +def fun_l28_n509() + fun_l29_n137 +end + +def fun_l28_n510() + fun_l29_n256 +end + +def fun_l28_n511() + fun_l29_n449 +end + +def fun_l28_n512() + fun_l29_n252 +end + +def fun_l28_n513() + fun_l29_n42 +end + +def fun_l28_n514() + fun_l29_n398 +end + +def fun_l28_n515() + fun_l29_n655 +end + +def fun_l28_n516() + fun_l29_n208 +end + +def fun_l28_n517() + fun_l29_n883 +end + +def fun_l28_n518() + fun_l29_n401 +end + +def fun_l28_n519() + fun_l29_n825 +end + +def fun_l28_n520() + fun_l29_n380 +end + +def fun_l28_n521() + fun_l29_n277 +end + +def fun_l28_n522() + fun_l29_n165 +end + +def fun_l28_n523() + fun_l29_n373 +end + +def fun_l28_n524() + fun_l29_n378 +end + +def fun_l28_n525() + fun_l29_n70 +end + +def fun_l28_n526() + fun_l29_n975 +end + +def fun_l28_n527() + fun_l29_n34 +end + +def fun_l28_n528() + fun_l29_n346 +end + +def fun_l28_n529() + fun_l29_n322 +end + +def fun_l28_n530() + fun_l29_n429 +end + +def fun_l28_n531() + fun_l29_n20 +end + +def fun_l28_n532() + fun_l29_n155 +end + +def fun_l28_n533() + fun_l29_n896 +end + +def fun_l28_n534() + fun_l29_n860 +end + +def fun_l28_n535() + fun_l29_n602 +end + +def fun_l28_n536() + fun_l29_n573 +end + +def fun_l28_n537() + fun_l29_n448 +end + +def fun_l28_n538() + fun_l29_n637 +end + +def fun_l28_n539() + fun_l29_n890 +end + +def fun_l28_n540() + fun_l29_n200 +end + +def fun_l28_n541() + fun_l29_n405 +end + +def fun_l28_n542() + fun_l29_n656 +end + +def fun_l28_n543() + fun_l29_n974 +end + +def fun_l28_n544() + fun_l29_n711 +end + +def fun_l28_n545() + fun_l29_n206 +end + +def fun_l28_n546() + fun_l29_n677 +end + +def fun_l28_n547() + fun_l29_n125 +end + +def fun_l28_n548() + fun_l29_n576 +end + +def fun_l28_n549() + fun_l29_n923 +end + +def fun_l28_n550() + fun_l29_n86 +end + +def fun_l28_n551() + fun_l29_n827 +end + +def fun_l28_n552() + fun_l29_n76 +end + +def fun_l28_n553() + fun_l29_n143 +end + +def fun_l28_n554() + fun_l29_n435 +end + +def fun_l28_n555() + fun_l29_n75 +end + +def fun_l28_n556() + fun_l29_n23 +end + +def fun_l28_n557() + fun_l29_n658 +end + +def fun_l28_n558() + fun_l29_n814 +end + +def fun_l28_n559() + fun_l29_n833 +end + +def fun_l28_n560() + fun_l29_n101 +end + +def fun_l28_n561() + fun_l29_n513 +end + +def fun_l28_n562() + fun_l29_n43 +end + +def fun_l28_n563() + fun_l29_n576 +end + +def fun_l28_n564() + fun_l29_n131 +end + +def fun_l28_n565() + fun_l29_n920 +end + +def fun_l28_n566() + fun_l29_n299 +end + +def fun_l28_n567() + fun_l29_n216 +end + +def fun_l28_n568() + fun_l29_n547 +end + +def fun_l28_n569() + fun_l29_n728 +end + +def fun_l28_n570() + fun_l29_n349 +end + +def fun_l28_n571() + fun_l29_n927 +end + +def fun_l28_n572() + fun_l29_n328 +end + +def fun_l28_n573() + fun_l29_n790 +end + +def fun_l28_n574() + fun_l29_n397 +end + +def fun_l28_n575() + fun_l29_n423 +end + +def fun_l28_n576() + fun_l29_n867 +end + +def fun_l28_n577() + fun_l29_n529 +end + +def fun_l28_n578() + fun_l29_n825 +end + +def fun_l28_n579() + fun_l29_n51 +end + +def fun_l28_n580() + fun_l29_n482 +end + +def fun_l28_n581() + fun_l29_n395 +end + +def fun_l28_n582() + fun_l29_n771 +end + +def fun_l28_n583() + fun_l29_n118 +end + +def fun_l28_n584() + fun_l29_n348 +end + +def fun_l28_n585() + fun_l29_n895 +end + +def fun_l28_n586() + fun_l29_n956 +end + +def fun_l28_n587() + fun_l29_n251 +end + +def fun_l28_n588() + fun_l29_n216 +end + +def fun_l28_n589() + fun_l29_n837 +end + +def fun_l28_n590() + fun_l29_n956 +end + +def fun_l28_n591() + fun_l29_n309 +end + +def fun_l28_n592() + fun_l29_n706 +end + +def fun_l28_n593() + fun_l29_n58 +end + +def fun_l28_n594() + fun_l29_n244 +end + +def fun_l28_n595() + fun_l29_n281 +end + +def fun_l28_n596() + fun_l29_n748 +end + +def fun_l28_n597() + fun_l29_n109 +end + +def fun_l28_n598() + fun_l29_n730 +end + +def fun_l28_n599() + fun_l29_n590 +end + +def fun_l28_n600() + fun_l29_n331 +end + +def fun_l28_n601() + fun_l29_n700 +end + +def fun_l28_n602() + fun_l29_n606 +end + +def fun_l28_n603() + fun_l29_n331 +end + +def fun_l28_n604() + fun_l29_n695 +end + +def fun_l28_n605() + fun_l29_n355 +end + +def fun_l28_n606() + fun_l29_n449 +end + +def fun_l28_n607() + fun_l29_n728 +end + +def fun_l28_n608() + fun_l29_n248 +end + +def fun_l28_n609() + fun_l29_n949 +end + +def fun_l28_n610() + fun_l29_n473 +end + +def fun_l28_n611() + fun_l29_n244 +end + +def fun_l28_n612() + fun_l29_n790 +end + +def fun_l28_n613() + fun_l29_n983 +end + +def fun_l28_n614() + fun_l29_n76 +end + +def fun_l28_n615() + fun_l29_n792 +end + +def fun_l28_n616() + fun_l29_n195 +end + +def fun_l28_n617() + fun_l29_n559 +end + +def fun_l28_n618() + fun_l29_n269 +end + +def fun_l28_n619() + fun_l29_n152 +end + +def fun_l28_n620() + fun_l29_n507 +end + +def fun_l28_n621() + fun_l29_n165 +end + +def fun_l28_n622() + fun_l29_n779 +end + +def fun_l28_n623() + fun_l29_n182 +end + +def fun_l28_n624() + fun_l29_n76 +end + +def fun_l28_n625() + fun_l29_n585 +end + +def fun_l28_n626() + fun_l29_n943 +end + +def fun_l28_n627() + fun_l29_n25 +end + +def fun_l28_n628() + fun_l29_n200 +end + +def fun_l28_n629() + fun_l29_n590 +end + +def fun_l28_n630() + fun_l29_n631 +end + +def fun_l28_n631() + fun_l29_n610 +end + +def fun_l28_n632() + fun_l29_n197 +end + +def fun_l28_n633() + fun_l29_n608 +end + +def fun_l28_n634() + fun_l29_n585 +end + +def fun_l28_n635() + fun_l29_n987 +end + +def fun_l28_n636() + fun_l29_n440 +end + +def fun_l28_n637() + fun_l29_n808 +end + +def fun_l28_n638() + fun_l29_n208 +end + +def fun_l28_n639() + fun_l29_n382 +end + +def fun_l28_n640() + fun_l29_n631 +end + +def fun_l28_n641() + fun_l29_n107 +end + +def fun_l28_n642() + fun_l29_n682 +end + +def fun_l28_n643() + fun_l29_n57 +end + +def fun_l28_n644() + fun_l29_n375 +end + +def fun_l28_n645() + fun_l29_n855 +end + +def fun_l28_n646() + fun_l29_n200 +end + +def fun_l28_n647() + fun_l29_n820 +end + +def fun_l28_n648() + fun_l29_n363 +end + +def fun_l28_n649() + fun_l29_n991 +end + +def fun_l28_n650() + fun_l29_n342 +end + +def fun_l28_n651() + fun_l29_n740 +end + +def fun_l28_n652() + fun_l29_n646 +end + +def fun_l28_n653() + fun_l29_n743 +end + +def fun_l28_n654() + fun_l29_n438 +end + +def fun_l28_n655() + fun_l29_n198 +end + +def fun_l28_n656() + fun_l29_n45 +end + +def fun_l28_n657() + fun_l29_n54 +end + +def fun_l28_n658() + fun_l29_n5 +end + +def fun_l28_n659() + fun_l29_n30 +end + +def fun_l28_n660() + fun_l29_n77 +end + +def fun_l28_n661() + fun_l29_n231 +end + +def fun_l28_n662() + fun_l29_n515 +end + +def fun_l28_n663() + fun_l29_n327 +end + +def fun_l28_n664() + fun_l29_n188 +end + +def fun_l28_n665() + fun_l29_n976 +end + +def fun_l28_n666() + fun_l29_n482 +end + +def fun_l28_n667() + fun_l29_n106 +end + +def fun_l28_n668() + fun_l29_n339 +end + +def fun_l28_n669() + fun_l29_n445 +end + +def fun_l28_n670() + fun_l29_n708 +end + +def fun_l28_n671() + fun_l29_n846 +end + +def fun_l28_n672() + fun_l29_n142 +end + +def fun_l28_n673() + fun_l29_n567 +end + +def fun_l28_n674() + fun_l29_n875 +end + +def fun_l28_n675() + fun_l29_n107 +end + +def fun_l28_n676() + fun_l29_n243 +end + +def fun_l28_n677() + fun_l29_n580 +end + +def fun_l28_n678() + fun_l29_n75 +end + +def fun_l28_n679() + fun_l29_n230 +end + +def fun_l28_n680() + fun_l29_n72 +end + +def fun_l28_n681() + fun_l29_n429 +end + +def fun_l28_n682() + fun_l29_n816 +end + +def fun_l28_n683() + fun_l29_n896 +end + +def fun_l28_n684() + fun_l29_n933 +end + +def fun_l28_n685() + fun_l29_n432 +end + +def fun_l28_n686() + fun_l29_n547 +end + +def fun_l28_n687() + fun_l29_n670 +end + +def fun_l28_n688() + fun_l29_n952 +end + +def fun_l28_n689() + fun_l29_n137 +end + +def fun_l28_n690() + fun_l29_n532 +end + +def fun_l28_n691() + fun_l29_n608 +end + +def fun_l28_n692() + fun_l29_n264 +end + +def fun_l28_n693() + fun_l29_n220 +end + +def fun_l28_n694() + fun_l29_n499 +end + +def fun_l28_n695() + fun_l29_n244 +end + +def fun_l28_n696() + fun_l29_n952 +end + +def fun_l28_n697() + fun_l29_n700 +end + +def fun_l28_n698() + fun_l29_n415 +end + +def fun_l28_n699() + fun_l29_n712 +end + +def fun_l28_n700() + fun_l29_n209 +end + +def fun_l28_n701() + fun_l29_n759 +end + +def fun_l28_n702() + fun_l29_n786 +end + +def fun_l28_n703() + fun_l29_n858 +end + +def fun_l28_n704() + fun_l29_n328 +end + +def fun_l28_n705() + fun_l29_n201 +end + +def fun_l28_n706() + fun_l29_n317 +end + +def fun_l28_n707() + fun_l29_n335 +end + +def fun_l28_n708() + fun_l29_n483 +end + +def fun_l28_n709() + fun_l29_n1 +end + +def fun_l28_n710() + fun_l29_n962 +end + +def fun_l28_n711() + fun_l29_n158 +end + +def fun_l28_n712() + fun_l29_n591 +end + +def fun_l28_n713() + fun_l29_n849 +end + +def fun_l28_n714() + fun_l29_n149 +end + +def fun_l28_n715() + fun_l29_n653 +end + +def fun_l28_n716() + fun_l29_n173 +end + +def fun_l28_n717() + fun_l29_n21 +end + +def fun_l28_n718() + fun_l29_n384 +end + +def fun_l28_n719() + fun_l29_n601 +end + +def fun_l28_n720() + fun_l29_n388 +end + +def fun_l28_n721() + fun_l29_n866 +end + +def fun_l28_n722() + fun_l29_n261 +end + +def fun_l28_n723() + fun_l29_n412 +end + +def fun_l28_n724() + fun_l29_n77 +end + +def fun_l28_n725() + fun_l29_n395 +end + +def fun_l28_n726() + fun_l29_n863 +end + +def fun_l28_n727() + fun_l29_n780 +end + +def fun_l28_n728() + fun_l29_n400 +end + +def fun_l28_n729() + fun_l29_n495 +end + +def fun_l28_n730() + fun_l29_n813 +end + +def fun_l28_n731() + fun_l29_n330 +end + +def fun_l28_n732() + fun_l29_n479 +end + +def fun_l28_n733() + fun_l29_n446 +end + +def fun_l28_n734() + fun_l29_n354 +end + +def fun_l28_n735() + fun_l29_n88 +end + +def fun_l28_n736() + fun_l29_n296 +end + +def fun_l28_n737() + fun_l29_n457 +end + +def fun_l28_n738() + fun_l29_n611 +end + +def fun_l28_n739() + fun_l29_n412 +end + +def fun_l28_n740() + fun_l29_n290 +end + +def fun_l28_n741() + fun_l29_n935 +end + +def fun_l28_n742() + fun_l29_n833 +end + +def fun_l28_n743() + fun_l29_n296 +end + +def fun_l28_n744() + fun_l29_n249 +end + +def fun_l28_n745() + fun_l29_n567 +end + +def fun_l28_n746() + fun_l29_n707 +end + +def fun_l28_n747() + fun_l29_n633 +end + +def fun_l28_n748() + fun_l29_n303 +end + +def fun_l28_n749() + fun_l29_n971 +end + +def fun_l28_n750() + fun_l29_n784 +end + +def fun_l28_n751() + fun_l29_n88 +end + +def fun_l28_n752() + fun_l29_n782 +end + +def fun_l28_n753() + fun_l29_n322 +end + +def fun_l28_n754() + fun_l29_n362 +end + +def fun_l28_n755() + fun_l29_n894 +end + +def fun_l28_n756() + fun_l29_n848 +end + +def fun_l28_n757() + fun_l29_n617 +end + +def fun_l28_n758() + fun_l29_n103 +end + +def fun_l28_n759() + fun_l29_n625 +end + +def fun_l28_n760() + fun_l29_n592 +end + +def fun_l28_n761() + fun_l29_n597 +end + +def fun_l28_n762() + fun_l29_n118 +end + +def fun_l28_n763() + fun_l29_n366 +end + +def fun_l28_n764() + fun_l29_n609 +end + +def fun_l28_n765() + fun_l29_n710 +end + +def fun_l28_n766() + fun_l29_n563 +end + +def fun_l28_n767() + fun_l29_n324 +end + +def fun_l28_n768() + fun_l29_n783 +end + +def fun_l28_n769() + fun_l29_n512 +end + +def fun_l28_n770() + fun_l29_n0 +end + +def fun_l28_n771() + fun_l29_n60 +end + +def fun_l28_n772() + fun_l29_n18 +end + +def fun_l28_n773() + fun_l29_n741 +end + +def fun_l28_n774() + fun_l29_n862 +end + +def fun_l28_n775() + fun_l29_n183 +end + +def fun_l28_n776() + fun_l29_n148 +end + +def fun_l28_n777() + fun_l29_n703 +end + +def fun_l28_n778() + fun_l29_n251 +end + +def fun_l28_n779() + fun_l29_n84 +end + +def fun_l28_n780() + fun_l29_n85 +end + +def fun_l28_n781() + fun_l29_n632 +end + +def fun_l28_n782() + fun_l29_n28 +end + +def fun_l28_n783() + fun_l29_n123 +end + +def fun_l28_n784() + fun_l29_n66 +end + +def fun_l28_n785() + fun_l29_n266 +end + +def fun_l28_n786() + fun_l29_n860 +end + +def fun_l28_n787() + fun_l29_n769 +end + +def fun_l28_n788() + fun_l29_n921 +end + +def fun_l28_n789() + fun_l29_n513 +end + +def fun_l28_n790() + fun_l29_n455 +end + +def fun_l28_n791() + fun_l29_n589 +end + +def fun_l28_n792() + fun_l29_n557 +end + +def fun_l28_n793() + fun_l29_n827 +end + +def fun_l28_n794() + fun_l29_n561 +end + +def fun_l28_n795() + fun_l29_n891 +end + +def fun_l28_n796() + fun_l29_n938 +end + +def fun_l28_n797() + fun_l29_n157 +end + +def fun_l28_n798() + fun_l29_n691 +end + +def fun_l28_n799() + fun_l29_n20 +end + +def fun_l28_n800() + fun_l29_n737 +end + +def fun_l28_n801() + fun_l29_n675 +end + +def fun_l28_n802() + fun_l29_n385 +end + +def fun_l28_n803() + fun_l29_n206 +end + +def fun_l28_n804() + fun_l29_n366 +end + +def fun_l28_n805() + fun_l29_n107 +end + +def fun_l28_n806() + fun_l29_n425 +end + +def fun_l28_n807() + fun_l29_n371 +end + +def fun_l28_n808() + fun_l29_n241 +end + +def fun_l28_n809() + fun_l29_n168 +end + +def fun_l28_n810() + fun_l29_n201 +end + +def fun_l28_n811() + fun_l29_n600 +end + +def fun_l28_n812() + fun_l29_n251 +end + +def fun_l28_n813() + fun_l29_n10 +end + +def fun_l28_n814() + fun_l29_n428 +end + +def fun_l28_n815() + fun_l29_n850 +end + +def fun_l28_n816() + fun_l29_n276 +end + +def fun_l28_n817() + fun_l29_n196 +end + +def fun_l28_n818() + fun_l29_n623 +end + +def fun_l28_n819() + fun_l29_n441 +end + +def fun_l28_n820() + fun_l29_n724 +end + +def fun_l28_n821() + fun_l29_n958 +end + +def fun_l28_n822() + fun_l29_n449 +end + +def fun_l28_n823() + fun_l29_n408 +end + +def fun_l28_n824() + fun_l29_n74 +end + +def fun_l28_n825() + fun_l29_n124 +end + +def fun_l28_n826() + fun_l29_n991 +end + +def fun_l28_n827() + fun_l29_n576 +end + +def fun_l28_n828() + fun_l29_n743 +end + +def fun_l28_n829() + fun_l29_n343 +end + +def fun_l28_n830() + fun_l29_n376 +end + +def fun_l28_n831() + fun_l29_n216 +end + +def fun_l28_n832() + fun_l29_n358 +end + +def fun_l28_n833() + fun_l29_n567 +end + +def fun_l28_n834() + fun_l29_n415 +end + +def fun_l28_n835() + fun_l29_n984 +end + +def fun_l28_n836() + fun_l29_n367 +end + +def fun_l28_n837() + fun_l29_n299 +end + +def fun_l28_n838() + fun_l29_n718 +end + +def fun_l28_n839() + fun_l29_n241 +end + +def fun_l28_n840() + fun_l29_n736 +end + +def fun_l28_n841() + fun_l29_n582 +end + +def fun_l28_n842() + fun_l29_n994 +end + +def fun_l28_n843() + fun_l29_n301 +end + +def fun_l28_n844() + fun_l29_n597 +end + +def fun_l28_n845() + fun_l29_n141 +end + +def fun_l28_n846() + fun_l29_n37 +end + +def fun_l28_n847() + fun_l29_n216 +end + +def fun_l28_n848() + fun_l29_n286 +end + +def fun_l28_n849() + fun_l29_n607 +end + +def fun_l28_n850() + fun_l29_n503 +end + +def fun_l28_n851() + fun_l29_n321 +end + +def fun_l28_n852() + fun_l29_n179 +end + +def fun_l28_n853() + fun_l29_n802 +end + +def fun_l28_n854() + fun_l29_n742 +end + +def fun_l28_n855() + fun_l29_n300 +end + +def fun_l28_n856() + fun_l29_n453 +end + +def fun_l28_n857() + fun_l29_n520 +end + +def fun_l28_n858() + fun_l29_n911 +end + +def fun_l28_n859() + fun_l29_n209 +end + +def fun_l28_n860() + fun_l29_n921 +end + +def fun_l28_n861() + fun_l29_n653 +end + +def fun_l28_n862() + fun_l29_n347 +end + +def fun_l28_n863() + fun_l29_n733 +end + +def fun_l28_n864() + fun_l29_n824 +end + +def fun_l28_n865() + fun_l29_n497 +end + +def fun_l28_n866() + fun_l29_n256 +end + +def fun_l28_n867() + fun_l29_n884 +end + +def fun_l28_n868() + fun_l29_n937 +end + +def fun_l28_n869() + fun_l29_n894 +end + +def fun_l28_n870() + fun_l29_n258 +end + +def fun_l28_n871() + fun_l29_n45 +end + +def fun_l28_n872() + fun_l29_n640 +end + +def fun_l28_n873() + fun_l29_n909 +end + +def fun_l28_n874() + fun_l29_n586 +end + +def fun_l28_n875() + fun_l29_n600 +end + +def fun_l28_n876() + fun_l29_n636 +end + +def fun_l28_n877() + fun_l29_n972 +end + +def fun_l28_n878() + fun_l29_n627 +end + +def fun_l28_n879() + fun_l29_n381 +end + +def fun_l28_n880() + fun_l29_n664 +end + +def fun_l28_n881() + fun_l29_n350 +end + +def fun_l28_n882() + fun_l29_n611 +end + +def fun_l28_n883() + fun_l29_n355 +end + +def fun_l28_n884() + fun_l29_n945 +end + +def fun_l28_n885() + fun_l29_n462 +end + +def fun_l28_n886() + fun_l29_n723 +end + +def fun_l28_n887() + fun_l29_n500 +end + +def fun_l28_n888() + fun_l29_n166 +end + +def fun_l28_n889() + fun_l29_n779 +end + +def fun_l28_n890() + fun_l29_n151 +end + +def fun_l28_n891() + fun_l29_n757 +end + +def fun_l28_n892() + fun_l29_n782 +end + +def fun_l28_n893() + fun_l29_n108 +end + +def fun_l28_n894() + fun_l29_n122 +end + +def fun_l28_n895() + fun_l29_n815 +end + +def fun_l28_n896() + fun_l29_n742 +end + +def fun_l28_n897() + fun_l29_n861 +end + +def fun_l28_n898() + fun_l29_n738 +end + +def fun_l28_n899() + fun_l29_n765 +end + +def fun_l28_n900() + fun_l29_n648 +end + +def fun_l28_n901() + fun_l29_n923 +end + +def fun_l28_n902() + fun_l29_n269 +end + +def fun_l28_n903() + fun_l29_n626 +end + +def fun_l28_n904() + fun_l29_n100 +end + +def fun_l28_n905() + fun_l29_n587 +end + +def fun_l28_n906() + fun_l29_n841 +end + +def fun_l28_n907() + fun_l29_n239 +end + +def fun_l28_n908() + fun_l29_n87 +end + +def fun_l28_n909() + fun_l29_n765 +end + +def fun_l28_n910() + fun_l29_n216 +end + +def fun_l28_n911() + fun_l29_n110 +end + +def fun_l28_n912() + fun_l29_n96 +end + +def fun_l28_n913() + fun_l29_n946 +end + +def fun_l28_n914() + fun_l29_n762 +end + +def fun_l28_n915() + fun_l29_n697 +end + +def fun_l28_n916() + fun_l29_n44 +end + +def fun_l28_n917() + fun_l29_n257 +end + +def fun_l28_n918() + fun_l29_n195 +end + +def fun_l28_n919() + fun_l29_n886 +end + +def fun_l28_n920() + fun_l29_n432 +end + +def fun_l28_n921() + fun_l29_n746 +end + +def fun_l28_n922() + fun_l29_n756 +end + +def fun_l28_n923() + fun_l29_n33 +end + +def fun_l28_n924() + fun_l29_n720 +end + +def fun_l28_n925() + fun_l29_n629 +end + +def fun_l28_n926() + fun_l29_n144 +end + +def fun_l28_n927() + fun_l29_n225 +end + +def fun_l28_n928() + fun_l29_n556 +end + +def fun_l28_n929() + fun_l29_n436 +end + +def fun_l28_n930() + fun_l29_n380 +end + +def fun_l28_n931() + fun_l29_n478 +end + +def fun_l28_n932() + fun_l29_n949 +end + +def fun_l28_n933() + fun_l29_n811 +end + +def fun_l28_n934() + fun_l29_n589 +end + +def fun_l28_n935() + fun_l29_n961 +end + +def fun_l28_n936() + fun_l29_n413 +end + +def fun_l28_n937() + fun_l29_n941 +end + +def fun_l28_n938() + fun_l29_n507 +end + +def fun_l28_n939() + fun_l29_n364 +end + +def fun_l28_n940() + fun_l29_n100 +end + +def fun_l28_n941() + fun_l29_n254 +end + +def fun_l28_n942() + fun_l29_n272 +end + +def fun_l28_n943() + fun_l29_n420 +end + +def fun_l28_n944() + fun_l29_n132 +end + +def fun_l28_n945() + fun_l29_n907 +end + +def fun_l28_n946() + fun_l29_n784 +end + +def fun_l28_n947() + fun_l29_n938 +end + +def fun_l28_n948() + fun_l29_n780 +end + +def fun_l28_n949() + fun_l29_n584 +end + +def fun_l28_n950() + fun_l29_n258 +end + +def fun_l28_n951() + fun_l29_n754 +end + +def fun_l28_n952() + fun_l29_n582 +end + +def fun_l28_n953() + fun_l29_n278 +end + +def fun_l28_n954() + fun_l29_n870 +end + +def fun_l28_n955() + fun_l29_n664 +end + +def fun_l28_n956() + fun_l29_n375 +end + +def fun_l28_n957() + fun_l29_n613 +end + +def fun_l28_n958() + fun_l29_n530 +end + +def fun_l28_n959() + fun_l29_n933 +end + +def fun_l28_n960() + fun_l29_n298 +end + +def fun_l28_n961() + fun_l29_n507 +end + +def fun_l28_n962() + fun_l29_n526 +end + +def fun_l28_n963() + fun_l29_n508 +end + +def fun_l28_n964() + fun_l29_n227 +end + +def fun_l28_n965() + fun_l29_n999 +end + +def fun_l28_n966() + fun_l29_n489 +end + +def fun_l28_n967() + fun_l29_n789 +end + +def fun_l28_n968() + fun_l29_n304 +end + +def fun_l28_n969() + fun_l29_n343 +end + +def fun_l28_n970() + fun_l29_n560 +end + +def fun_l28_n971() + fun_l29_n610 +end + +def fun_l28_n972() + fun_l29_n606 +end + +def fun_l28_n973() + fun_l29_n592 +end + +def fun_l28_n974() + fun_l29_n135 +end + +def fun_l28_n975() + fun_l29_n513 +end + +def fun_l28_n976() + fun_l29_n522 +end + +def fun_l28_n977() + fun_l29_n323 +end + +def fun_l28_n978() + fun_l29_n26 +end + +def fun_l28_n979() + fun_l29_n737 +end + +def fun_l28_n980() + fun_l29_n705 +end + +def fun_l28_n981() + fun_l29_n405 +end + +def fun_l28_n982() + fun_l29_n891 +end + +def fun_l28_n983() + fun_l29_n155 +end + +def fun_l28_n984() + fun_l29_n814 +end + +def fun_l28_n985() + fun_l29_n70 +end + +def fun_l28_n986() + fun_l29_n940 +end + +def fun_l28_n987() + fun_l29_n427 +end + +def fun_l28_n988() + fun_l29_n478 +end + +def fun_l28_n989() + fun_l29_n432 +end + +def fun_l28_n990() + fun_l29_n320 +end + +def fun_l28_n991() + fun_l29_n422 +end + +def fun_l28_n992() + fun_l29_n917 +end + +def fun_l28_n993() + fun_l29_n391 +end + +def fun_l28_n994() + fun_l29_n950 +end + +def fun_l28_n995() + fun_l29_n635 +end + +def fun_l28_n996() + fun_l29_n392 +end + +def fun_l28_n997() + fun_l29_n311 +end + +def fun_l28_n998() + fun_l29_n320 +end + +def fun_l28_n999() + fun_l29_n916 +end + +def fun_l29_n0() + inc +end + +def fun_l29_n1() + inc +end + +def fun_l29_n2() + inc +end + +def fun_l29_n3() + inc +end + +def fun_l29_n4() + inc +end + +def fun_l29_n5() + inc +end + +def fun_l29_n6() + inc +end + +def fun_l29_n7() + inc +end + +def fun_l29_n8() + inc +end + +def fun_l29_n9() + inc +end + +def fun_l29_n10() + inc +end + +def fun_l29_n11() + inc +end + +def fun_l29_n12() + inc +end + +def fun_l29_n13() + inc +end + +def fun_l29_n14() + inc +end + +def fun_l29_n15() + inc +end + +def fun_l29_n16() + inc +end + +def fun_l29_n17() + inc +end + +def fun_l29_n18() + inc +end + +def fun_l29_n19() + inc +end + +def fun_l29_n20() + inc +end + +def fun_l29_n21() + inc +end + +def fun_l29_n22() + inc +end + +def fun_l29_n23() + inc +end + +def fun_l29_n24() + inc +end + +def fun_l29_n25() + inc +end + +def fun_l29_n26() + inc +end + +def fun_l29_n27() + inc +end + +def fun_l29_n28() + inc +end + +def fun_l29_n29() + inc +end + +def fun_l29_n30() + inc +end + +def fun_l29_n31() + inc +end + +def fun_l29_n32() + inc +end + +def fun_l29_n33() + inc +end + +def fun_l29_n34() + inc +end + +def fun_l29_n35() + inc +end + +def fun_l29_n36() + inc +end + +def fun_l29_n37() + inc +end + +def fun_l29_n38() + inc +end + +def fun_l29_n39() + inc +end + +def fun_l29_n40() + inc +end + +def fun_l29_n41() + inc +end + +def fun_l29_n42() + inc +end + +def fun_l29_n43() + inc +end + +def fun_l29_n44() + inc +end + +def fun_l29_n45() + inc +end + +def fun_l29_n46() + inc +end + +def fun_l29_n47() + inc +end + +def fun_l29_n48() + inc +end + +def fun_l29_n49() + inc +end + +def fun_l29_n50() + inc +end + +def fun_l29_n51() + inc +end + +def fun_l29_n52() + inc +end + +def fun_l29_n53() + inc +end + +def fun_l29_n54() + inc +end + +def fun_l29_n55() + inc +end + +def fun_l29_n56() + inc +end + +def fun_l29_n57() + inc +end + +def fun_l29_n58() + inc +end + +def fun_l29_n59() + inc +end + +def fun_l29_n60() + inc +end + +def fun_l29_n61() + inc +end + +def fun_l29_n62() + inc +end + +def fun_l29_n63() + inc +end + +def fun_l29_n64() + inc +end + +def fun_l29_n65() + inc +end + +def fun_l29_n66() + inc +end + +def fun_l29_n67() + inc +end + +def fun_l29_n68() + inc +end + +def fun_l29_n69() + inc +end + +def fun_l29_n70() + inc +end + +def fun_l29_n71() + inc +end + +def fun_l29_n72() + inc +end + +def fun_l29_n73() + inc +end + +def fun_l29_n74() + inc +end + +def fun_l29_n75() + inc +end + +def fun_l29_n76() + inc +end + +def fun_l29_n77() + inc +end + +def fun_l29_n78() + inc +end + +def fun_l29_n79() + inc +end + +def fun_l29_n80() + inc +end + +def fun_l29_n81() + inc +end + +def fun_l29_n82() + inc +end + +def fun_l29_n83() + inc +end + +def fun_l29_n84() + inc +end + +def fun_l29_n85() + inc +end + +def fun_l29_n86() + inc +end + +def fun_l29_n87() + inc +end + +def fun_l29_n88() + inc +end + +def fun_l29_n89() + inc +end + +def fun_l29_n90() + inc +end + +def fun_l29_n91() + inc +end + +def fun_l29_n92() + inc +end + +def fun_l29_n93() + inc +end + +def fun_l29_n94() + inc +end + +def fun_l29_n95() + inc +end + +def fun_l29_n96() + inc +end + +def fun_l29_n97() + inc +end + +def fun_l29_n98() + inc +end + +def fun_l29_n99() + inc +end + +def fun_l29_n100() + inc +end + +def fun_l29_n101() + inc +end + +def fun_l29_n102() + inc +end + +def fun_l29_n103() + inc +end + +def fun_l29_n104() + inc +end + +def fun_l29_n105() + inc +end + +def fun_l29_n106() + inc +end + +def fun_l29_n107() + inc +end + +def fun_l29_n108() + inc +end + +def fun_l29_n109() + inc +end + +def fun_l29_n110() + inc +end + +def fun_l29_n111() + inc +end + +def fun_l29_n112() + inc +end + +def fun_l29_n113() + inc +end + +def fun_l29_n114() + inc +end + +def fun_l29_n115() + inc +end + +def fun_l29_n116() + inc +end + +def fun_l29_n117() + inc +end + +def fun_l29_n118() + inc +end + +def fun_l29_n119() + inc +end + +def fun_l29_n120() + inc +end + +def fun_l29_n121() + inc +end + +def fun_l29_n122() + inc +end + +def fun_l29_n123() + inc +end + +def fun_l29_n124() + inc +end + +def fun_l29_n125() + inc +end + +def fun_l29_n126() + inc +end + +def fun_l29_n127() + inc +end + +def fun_l29_n128() + inc +end + +def fun_l29_n129() + inc +end + +def fun_l29_n130() + inc +end + +def fun_l29_n131() + inc +end + +def fun_l29_n132() + inc +end + +def fun_l29_n133() + inc +end + +def fun_l29_n134() + inc +end + +def fun_l29_n135() + inc +end + +def fun_l29_n136() + inc +end + +def fun_l29_n137() + inc +end + +def fun_l29_n138() + inc +end + +def fun_l29_n139() + inc +end + +def fun_l29_n140() + inc +end + +def fun_l29_n141() + inc +end + +def fun_l29_n142() + inc +end + +def fun_l29_n143() + inc +end + +def fun_l29_n144() + inc +end + +def fun_l29_n145() + inc +end + +def fun_l29_n146() + inc +end + +def fun_l29_n147() + inc +end + +def fun_l29_n148() + inc +end + +def fun_l29_n149() + inc +end + +def fun_l29_n150() + inc +end + +def fun_l29_n151() + inc +end + +def fun_l29_n152() + inc +end + +def fun_l29_n153() + inc +end + +def fun_l29_n154() + inc +end + +def fun_l29_n155() + inc +end + +def fun_l29_n156() + inc +end + +def fun_l29_n157() + inc +end + +def fun_l29_n158() + inc +end + +def fun_l29_n159() + inc +end + +def fun_l29_n160() + inc +end + +def fun_l29_n161() + inc +end + +def fun_l29_n162() + inc +end + +def fun_l29_n163() + inc +end + +def fun_l29_n164() + inc +end + +def fun_l29_n165() + inc +end + +def fun_l29_n166() + inc +end + +def fun_l29_n167() + inc +end + +def fun_l29_n168() + inc +end + +def fun_l29_n169() + inc +end + +def fun_l29_n170() + inc +end + +def fun_l29_n171() + inc +end + +def fun_l29_n172() + inc +end + +def fun_l29_n173() + inc +end + +def fun_l29_n174() + inc +end + +def fun_l29_n175() + inc +end + +def fun_l29_n176() + inc +end + +def fun_l29_n177() + inc +end + +def fun_l29_n178() + inc +end + +def fun_l29_n179() + inc +end + +def fun_l29_n180() + inc +end + +def fun_l29_n181() + inc +end + +def fun_l29_n182() + inc +end + +def fun_l29_n183() + inc +end + +def fun_l29_n184() + inc +end + +def fun_l29_n185() + inc +end + +def fun_l29_n186() + inc +end + +def fun_l29_n187() + inc +end + +def fun_l29_n188() + inc +end + +def fun_l29_n189() + inc +end + +def fun_l29_n190() + inc +end + +def fun_l29_n191() + inc +end + +def fun_l29_n192() + inc +end + +def fun_l29_n193() + inc +end + +def fun_l29_n194() + inc +end + +def fun_l29_n195() + inc +end + +def fun_l29_n196() + inc +end + +def fun_l29_n197() + inc +end + +def fun_l29_n198() + inc +end + +def fun_l29_n199() + inc +end + +def fun_l29_n200() + inc +end + +def fun_l29_n201() + inc +end + +def fun_l29_n202() + inc +end + +def fun_l29_n203() + inc +end + +def fun_l29_n204() + inc +end + +def fun_l29_n205() + inc +end + +def fun_l29_n206() + inc +end + +def fun_l29_n207() + inc +end + +def fun_l29_n208() + inc +end + +def fun_l29_n209() + inc +end + +def fun_l29_n210() + inc +end + +def fun_l29_n211() + inc +end + +def fun_l29_n212() + inc +end + +def fun_l29_n213() + inc +end + +def fun_l29_n214() + inc +end + +def fun_l29_n215() + inc +end + +def fun_l29_n216() + inc +end + +def fun_l29_n217() + inc +end + +def fun_l29_n218() + inc +end + +def fun_l29_n219() + inc +end + +def fun_l29_n220() + inc +end + +def fun_l29_n221() + inc +end + +def fun_l29_n222() + inc +end + +def fun_l29_n223() + inc +end + +def fun_l29_n224() + inc +end + +def fun_l29_n225() + inc +end + +def fun_l29_n226() + inc +end + +def fun_l29_n227() + inc +end + +def fun_l29_n228() + inc +end + +def fun_l29_n229() + inc +end + +def fun_l29_n230() + inc +end + +def fun_l29_n231() + inc +end + +def fun_l29_n232() + inc +end + +def fun_l29_n233() + inc +end + +def fun_l29_n234() + inc +end + +def fun_l29_n235() + inc +end + +def fun_l29_n236() + inc +end + +def fun_l29_n237() + inc +end + +def fun_l29_n238() + inc +end + +def fun_l29_n239() + inc +end + +def fun_l29_n240() + inc +end + +def fun_l29_n241() + inc +end + +def fun_l29_n242() + inc +end + +def fun_l29_n243() + inc +end + +def fun_l29_n244() + inc +end + +def fun_l29_n245() + inc +end + +def fun_l29_n246() + inc +end + +def fun_l29_n247() + inc +end + +def fun_l29_n248() + inc +end + +def fun_l29_n249() + inc +end + +def fun_l29_n250() + inc +end + +def fun_l29_n251() + inc +end + +def fun_l29_n252() + inc +end + +def fun_l29_n253() + inc +end + +def fun_l29_n254() + inc +end + +def fun_l29_n255() + inc +end + +def fun_l29_n256() + inc +end + +def fun_l29_n257() + inc +end + +def fun_l29_n258() + inc +end + +def fun_l29_n259() + inc +end + +def fun_l29_n260() + inc +end + +def fun_l29_n261() + inc +end + +def fun_l29_n262() + inc +end + +def fun_l29_n263() + inc +end + +def fun_l29_n264() + inc +end + +def fun_l29_n265() + inc +end + +def fun_l29_n266() + inc +end + +def fun_l29_n267() + inc +end + +def fun_l29_n268() + inc +end + +def fun_l29_n269() + inc +end + +def fun_l29_n270() + inc +end + +def fun_l29_n271() + inc +end + +def fun_l29_n272() + inc +end + +def fun_l29_n273() + inc +end + +def fun_l29_n274() + inc +end + +def fun_l29_n275() + inc +end + +def fun_l29_n276() + inc +end + +def fun_l29_n277() + inc +end + +def fun_l29_n278() + inc +end + +def fun_l29_n279() + inc +end + +def fun_l29_n280() + inc +end + +def fun_l29_n281() + inc +end + +def fun_l29_n282() + inc +end + +def fun_l29_n283() + inc +end + +def fun_l29_n284() + inc +end + +def fun_l29_n285() + inc +end + +def fun_l29_n286() + inc +end + +def fun_l29_n287() + inc +end + +def fun_l29_n288() + inc +end + +def fun_l29_n289() + inc +end + +def fun_l29_n290() + inc +end + +def fun_l29_n291() + inc +end + +def fun_l29_n292() + inc +end + +def fun_l29_n293() + inc +end + +def fun_l29_n294() + inc +end + +def fun_l29_n295() + inc +end + +def fun_l29_n296() + inc +end + +def fun_l29_n297() + inc +end + +def fun_l29_n298() + inc +end + +def fun_l29_n299() + inc +end + +def fun_l29_n300() + inc +end + +def fun_l29_n301() + inc +end + +def fun_l29_n302() + inc +end + +def fun_l29_n303() + inc +end + +def fun_l29_n304() + inc +end + +def fun_l29_n305() + inc +end + +def fun_l29_n306() + inc +end + +def fun_l29_n307() + inc +end + +def fun_l29_n308() + inc +end + +def fun_l29_n309() + inc +end + +def fun_l29_n310() + inc +end + +def fun_l29_n311() + inc +end + +def fun_l29_n312() + inc +end + +def fun_l29_n313() + inc +end + +def fun_l29_n314() + inc +end + +def fun_l29_n315() + inc +end + +def fun_l29_n316() + inc +end + +def fun_l29_n317() + inc +end + +def fun_l29_n318() + inc +end + +def fun_l29_n319() + inc +end + +def fun_l29_n320() + inc +end + +def fun_l29_n321() + inc +end + +def fun_l29_n322() + inc +end + +def fun_l29_n323() + inc +end + +def fun_l29_n324() + inc +end + +def fun_l29_n325() + inc +end + +def fun_l29_n326() + inc +end + +def fun_l29_n327() + inc +end + +def fun_l29_n328() + inc +end + +def fun_l29_n329() + inc +end + +def fun_l29_n330() + inc +end + +def fun_l29_n331() + inc +end + +def fun_l29_n332() + inc +end + +def fun_l29_n333() + inc +end + +def fun_l29_n334() + inc +end + +def fun_l29_n335() + inc +end + +def fun_l29_n336() + inc +end + +def fun_l29_n337() + inc +end + +def fun_l29_n338() + inc +end + +def fun_l29_n339() + inc +end + +def fun_l29_n340() + inc +end + +def fun_l29_n341() + inc +end + +def fun_l29_n342() + inc +end + +def fun_l29_n343() + inc +end + +def fun_l29_n344() + inc +end + +def fun_l29_n345() + inc +end + +def fun_l29_n346() + inc +end + +def fun_l29_n347() + inc +end + +def fun_l29_n348() + inc +end + +def fun_l29_n349() + inc +end + +def fun_l29_n350() + inc +end + +def fun_l29_n351() + inc +end + +def fun_l29_n352() + inc +end + +def fun_l29_n353() + inc +end + +def fun_l29_n354() + inc +end + +def fun_l29_n355() + inc +end + +def fun_l29_n356() + inc +end + +def fun_l29_n357() + inc +end + +def fun_l29_n358() + inc +end + +def fun_l29_n359() + inc +end + +def fun_l29_n360() + inc +end + +def fun_l29_n361() + inc +end + +def fun_l29_n362() + inc +end + +def fun_l29_n363() + inc +end + +def fun_l29_n364() + inc +end + +def fun_l29_n365() + inc +end + +def fun_l29_n366() + inc +end + +def fun_l29_n367() + inc +end + +def fun_l29_n368() + inc +end + +def fun_l29_n369() + inc +end + +def fun_l29_n370() + inc +end + +def fun_l29_n371() + inc +end + +def fun_l29_n372() + inc +end + +def fun_l29_n373() + inc +end + +def fun_l29_n374() + inc +end + +def fun_l29_n375() + inc +end + +def fun_l29_n376() + inc +end + +def fun_l29_n377() + inc +end + +def fun_l29_n378() + inc +end + +def fun_l29_n379() + inc +end + +def fun_l29_n380() + inc +end + +def fun_l29_n381() + inc +end + +def fun_l29_n382() + inc +end + +def fun_l29_n383() + inc +end + +def fun_l29_n384() + inc +end + +def fun_l29_n385() + inc +end + +def fun_l29_n386() + inc +end + +def fun_l29_n387() + inc +end + +def fun_l29_n388() + inc +end + +def fun_l29_n389() + inc +end + +def fun_l29_n390() + inc +end + +def fun_l29_n391() + inc +end + +def fun_l29_n392() + inc +end + +def fun_l29_n393() + inc +end + +def fun_l29_n394() + inc +end + +def fun_l29_n395() + inc +end + +def fun_l29_n396() + inc +end + +def fun_l29_n397() + inc +end + +def fun_l29_n398() + inc +end + +def fun_l29_n399() + inc +end + +def fun_l29_n400() + inc +end + +def fun_l29_n401() + inc +end + +def fun_l29_n402() + inc +end + +def fun_l29_n403() + inc +end + +def fun_l29_n404() + inc +end + +def fun_l29_n405() + inc +end + +def fun_l29_n406() + inc +end + +def fun_l29_n407() + inc +end + +def fun_l29_n408() + inc +end + +def fun_l29_n409() + inc +end + +def fun_l29_n410() + inc +end + +def fun_l29_n411() + inc +end + +def fun_l29_n412() + inc +end + +def fun_l29_n413() + inc +end + +def fun_l29_n414() + inc +end + +def fun_l29_n415() + inc +end + +def fun_l29_n416() + inc +end + +def fun_l29_n417() + inc +end + +def fun_l29_n418() + inc +end + +def fun_l29_n419() + inc +end + +def fun_l29_n420() + inc +end + +def fun_l29_n421() + inc +end + +def fun_l29_n422() + inc +end + +def fun_l29_n423() + inc +end + +def fun_l29_n424() + inc +end + +def fun_l29_n425() + inc +end + +def fun_l29_n426() + inc +end + +def fun_l29_n427() + inc +end + +def fun_l29_n428() + inc +end + +def fun_l29_n429() + inc +end + +def fun_l29_n430() + inc +end + +def fun_l29_n431() + inc +end + +def fun_l29_n432() + inc +end + +def fun_l29_n433() + inc +end + +def fun_l29_n434() + inc +end + +def fun_l29_n435() + inc +end + +def fun_l29_n436() + inc +end + +def fun_l29_n437() + inc +end + +def fun_l29_n438() + inc +end + +def fun_l29_n439() + inc +end + +def fun_l29_n440() + inc +end + +def fun_l29_n441() + inc +end + +def fun_l29_n442() + inc +end + +def fun_l29_n443() + inc +end + +def fun_l29_n444() + inc +end + +def fun_l29_n445() + inc +end + +def fun_l29_n446() + inc +end + +def fun_l29_n447() + inc +end + +def fun_l29_n448() + inc +end + +def fun_l29_n449() + inc +end + +def fun_l29_n450() + inc +end + +def fun_l29_n451() + inc +end + +def fun_l29_n452() + inc +end + +def fun_l29_n453() + inc +end + +def fun_l29_n454() + inc +end + +def fun_l29_n455() + inc +end + +def fun_l29_n456() + inc +end + +def fun_l29_n457() + inc +end + +def fun_l29_n458() + inc +end + +def fun_l29_n459() + inc +end + +def fun_l29_n460() + inc +end + +def fun_l29_n461() + inc +end + +def fun_l29_n462() + inc +end + +def fun_l29_n463() + inc +end + +def fun_l29_n464() + inc +end + +def fun_l29_n465() + inc +end + +def fun_l29_n466() + inc +end + +def fun_l29_n467() + inc +end + +def fun_l29_n468() + inc +end + +def fun_l29_n469() + inc +end + +def fun_l29_n470() + inc +end + +def fun_l29_n471() + inc +end + +def fun_l29_n472() + inc +end + +def fun_l29_n473() + inc +end + +def fun_l29_n474() + inc +end + +def fun_l29_n475() + inc +end + +def fun_l29_n476() + inc +end + +def fun_l29_n477() + inc +end + +def fun_l29_n478() + inc +end + +def fun_l29_n479() + inc +end + +def fun_l29_n480() + inc +end + +def fun_l29_n481() + inc +end + +def fun_l29_n482() + inc +end + +def fun_l29_n483() + inc +end + +def fun_l29_n484() + inc +end + +def fun_l29_n485() + inc +end + +def fun_l29_n486() + inc +end + +def fun_l29_n487() + inc +end + +def fun_l29_n488() + inc +end + +def fun_l29_n489() + inc +end + +def fun_l29_n490() + inc +end + +def fun_l29_n491() + inc +end + +def fun_l29_n492() + inc +end + +def fun_l29_n493() + inc +end + +def fun_l29_n494() + inc +end + +def fun_l29_n495() + inc +end + +def fun_l29_n496() + inc +end + +def fun_l29_n497() + inc +end + +def fun_l29_n498() + inc +end + +def fun_l29_n499() + inc +end + +def fun_l29_n500() + inc +end + +def fun_l29_n501() + inc +end + +def fun_l29_n502() + inc +end + +def fun_l29_n503() + inc +end + +def fun_l29_n504() + inc +end + +def fun_l29_n505() + inc +end + +def fun_l29_n506() + inc +end + +def fun_l29_n507() + inc +end + +def fun_l29_n508() + inc +end + +def fun_l29_n509() + inc +end + +def fun_l29_n510() + inc +end + +def fun_l29_n511() + inc +end + +def fun_l29_n512() + inc +end + +def fun_l29_n513() + inc +end + +def fun_l29_n514() + inc +end + +def fun_l29_n515() + inc +end + +def fun_l29_n516() + inc +end + +def fun_l29_n517() + inc +end + +def fun_l29_n518() + inc +end + +def fun_l29_n519() + inc +end + +def fun_l29_n520() + inc +end + +def fun_l29_n521() + inc +end + +def fun_l29_n522() + inc +end + +def fun_l29_n523() + inc +end + +def fun_l29_n524() + inc +end + +def fun_l29_n525() + inc +end + +def fun_l29_n526() + inc +end + +def fun_l29_n527() + inc +end + +def fun_l29_n528() + inc +end + +def fun_l29_n529() + inc +end + +def fun_l29_n530() + inc +end + +def fun_l29_n531() + inc +end + +def fun_l29_n532() + inc +end + +def fun_l29_n533() + inc +end + +def fun_l29_n534() + inc +end + +def fun_l29_n535() + inc +end + +def fun_l29_n536() + inc +end + +def fun_l29_n537() + inc +end + +def fun_l29_n538() + inc +end + +def fun_l29_n539() + inc +end + +def fun_l29_n540() + inc +end + +def fun_l29_n541() + inc +end + +def fun_l29_n542() + inc +end + +def fun_l29_n543() + inc +end + +def fun_l29_n544() + inc +end + +def fun_l29_n545() + inc +end + +def fun_l29_n546() + inc +end + +def fun_l29_n547() + inc +end + +def fun_l29_n548() + inc +end + +def fun_l29_n549() + inc +end + +def fun_l29_n550() + inc +end + +def fun_l29_n551() + inc +end + +def fun_l29_n552() + inc +end + +def fun_l29_n553() + inc +end + +def fun_l29_n554() + inc +end + +def fun_l29_n555() + inc +end + +def fun_l29_n556() + inc +end + +def fun_l29_n557() + inc +end + +def fun_l29_n558() + inc +end + +def fun_l29_n559() + inc +end + +def fun_l29_n560() + inc +end + +def fun_l29_n561() + inc +end + +def fun_l29_n562() + inc +end + +def fun_l29_n563() + inc +end + +def fun_l29_n564() + inc +end + +def fun_l29_n565() + inc +end + +def fun_l29_n566() + inc +end + +def fun_l29_n567() + inc +end + +def fun_l29_n568() + inc +end + +def fun_l29_n569() + inc +end + +def fun_l29_n570() + inc +end + +def fun_l29_n571() + inc +end + +def fun_l29_n572() + inc +end + +def fun_l29_n573() + inc +end + +def fun_l29_n574() + inc +end + +def fun_l29_n575() + inc +end + +def fun_l29_n576() + inc +end + +def fun_l29_n577() + inc +end + +def fun_l29_n578() + inc +end + +def fun_l29_n579() + inc +end + +def fun_l29_n580() + inc +end + +def fun_l29_n581() + inc +end + +def fun_l29_n582() + inc +end + +def fun_l29_n583() + inc +end + +def fun_l29_n584() + inc +end + +def fun_l29_n585() + inc +end + +def fun_l29_n586() + inc +end + +def fun_l29_n587() + inc +end + +def fun_l29_n588() + inc +end + +def fun_l29_n589() + inc +end + +def fun_l29_n590() + inc +end + +def fun_l29_n591() + inc +end + +def fun_l29_n592() + inc +end + +def fun_l29_n593() + inc +end + +def fun_l29_n594() + inc +end + +def fun_l29_n595() + inc +end + +def fun_l29_n596() + inc +end + +def fun_l29_n597() + inc +end + +def fun_l29_n598() + inc +end + +def fun_l29_n599() + inc +end + +def fun_l29_n600() + inc +end + +def fun_l29_n601() + inc +end + +def fun_l29_n602() + inc +end + +def fun_l29_n603() + inc +end + +def fun_l29_n604() + inc +end + +def fun_l29_n605() + inc +end + +def fun_l29_n606() + inc +end + +def fun_l29_n607() + inc +end + +def fun_l29_n608() + inc +end + +def fun_l29_n609() + inc +end + +def fun_l29_n610() + inc +end + +def fun_l29_n611() + inc +end + +def fun_l29_n612() + inc +end + +def fun_l29_n613() + inc +end + +def fun_l29_n614() + inc +end + +def fun_l29_n615() + inc +end + +def fun_l29_n616() + inc +end + +def fun_l29_n617() + inc +end + +def fun_l29_n618() + inc +end + +def fun_l29_n619() + inc +end + +def fun_l29_n620() + inc +end + +def fun_l29_n621() + inc +end + +def fun_l29_n622() + inc +end + +def fun_l29_n623() + inc +end + +def fun_l29_n624() + inc +end + +def fun_l29_n625() + inc +end + +def fun_l29_n626() + inc +end + +def fun_l29_n627() + inc +end + +def fun_l29_n628() + inc +end + +def fun_l29_n629() + inc +end + +def fun_l29_n630() + inc +end + +def fun_l29_n631() + inc +end + +def fun_l29_n632() + inc +end + +def fun_l29_n633() + inc +end + +def fun_l29_n634() + inc +end + +def fun_l29_n635() + inc +end + +def fun_l29_n636() + inc +end + +def fun_l29_n637() + inc +end + +def fun_l29_n638() + inc +end + +def fun_l29_n639() + inc +end + +def fun_l29_n640() + inc +end + +def fun_l29_n641() + inc +end + +def fun_l29_n642() + inc +end + +def fun_l29_n643() + inc +end + +def fun_l29_n644() + inc +end + +def fun_l29_n645() + inc +end + +def fun_l29_n646() + inc +end + +def fun_l29_n647() + inc +end + +def fun_l29_n648() + inc +end + +def fun_l29_n649() + inc +end + +def fun_l29_n650() + inc +end + +def fun_l29_n651() + inc +end + +def fun_l29_n652() + inc +end + +def fun_l29_n653() + inc +end + +def fun_l29_n654() + inc +end + +def fun_l29_n655() + inc +end + +def fun_l29_n656() + inc +end + +def fun_l29_n657() + inc +end + +def fun_l29_n658() + inc +end + +def fun_l29_n659() + inc +end + +def fun_l29_n660() + inc +end + +def fun_l29_n661() + inc +end + +def fun_l29_n662() + inc +end + +def fun_l29_n663() + inc +end + +def fun_l29_n664() + inc +end + +def fun_l29_n665() + inc +end + +def fun_l29_n666() + inc +end + +def fun_l29_n667() + inc +end + +def fun_l29_n668() + inc +end + +def fun_l29_n669() + inc +end + +def fun_l29_n670() + inc +end + +def fun_l29_n671() + inc +end + +def fun_l29_n672() + inc +end + +def fun_l29_n673() + inc +end + +def fun_l29_n674() + inc +end + +def fun_l29_n675() + inc +end + +def fun_l29_n676() + inc +end + +def fun_l29_n677() + inc +end + +def fun_l29_n678() + inc +end + +def fun_l29_n679() + inc +end + +def fun_l29_n680() + inc +end + +def fun_l29_n681() + inc +end + +def fun_l29_n682() + inc +end + +def fun_l29_n683() + inc +end + +def fun_l29_n684() + inc +end + +def fun_l29_n685() + inc +end + +def fun_l29_n686() + inc +end + +def fun_l29_n687() + inc +end + +def fun_l29_n688() + inc +end + +def fun_l29_n689() + inc +end + +def fun_l29_n690() + inc +end + +def fun_l29_n691() + inc +end + +def fun_l29_n692() + inc +end + +def fun_l29_n693() + inc +end + +def fun_l29_n694() + inc +end + +def fun_l29_n695() + inc +end + +def fun_l29_n696() + inc +end + +def fun_l29_n697() + inc +end + +def fun_l29_n698() + inc +end + +def fun_l29_n699() + inc +end + +def fun_l29_n700() + inc +end + +def fun_l29_n701() + inc +end + +def fun_l29_n702() + inc +end + +def fun_l29_n703() + inc +end + +def fun_l29_n704() + inc +end + +def fun_l29_n705() + inc +end + +def fun_l29_n706() + inc +end + +def fun_l29_n707() + inc +end + +def fun_l29_n708() + inc +end + +def fun_l29_n709() + inc +end + +def fun_l29_n710() + inc +end + +def fun_l29_n711() + inc +end + +def fun_l29_n712() + inc +end + +def fun_l29_n713() + inc +end + +def fun_l29_n714() + inc +end + +def fun_l29_n715() + inc +end + +def fun_l29_n716() + inc +end + +def fun_l29_n717() + inc +end + +def fun_l29_n718() + inc +end + +def fun_l29_n719() + inc +end + +def fun_l29_n720() + inc +end + +def fun_l29_n721() + inc +end + +def fun_l29_n722() + inc +end + +def fun_l29_n723() + inc +end + +def fun_l29_n724() + inc +end + +def fun_l29_n725() + inc +end + +def fun_l29_n726() + inc +end + +def fun_l29_n727() + inc +end + +def fun_l29_n728() + inc +end + +def fun_l29_n729() + inc +end + +def fun_l29_n730() + inc +end + +def fun_l29_n731() + inc +end + +def fun_l29_n732() + inc +end + +def fun_l29_n733() + inc +end + +def fun_l29_n734() + inc +end + +def fun_l29_n735() + inc +end + +def fun_l29_n736() + inc +end + +def fun_l29_n737() + inc +end + +def fun_l29_n738() + inc +end + +def fun_l29_n739() + inc +end + +def fun_l29_n740() + inc +end + +def fun_l29_n741() + inc +end + +def fun_l29_n742() + inc +end + +def fun_l29_n743() + inc +end + +def fun_l29_n744() + inc +end + +def fun_l29_n745() + inc +end + +def fun_l29_n746() + inc +end + +def fun_l29_n747() + inc +end + +def fun_l29_n748() + inc +end + +def fun_l29_n749() + inc +end + +def fun_l29_n750() + inc +end + +def fun_l29_n751() + inc +end + +def fun_l29_n752() + inc +end + +def fun_l29_n753() + inc +end + +def fun_l29_n754() + inc +end + +def fun_l29_n755() + inc +end + +def fun_l29_n756() + inc +end + +def fun_l29_n757() + inc +end + +def fun_l29_n758() + inc +end + +def fun_l29_n759() + inc +end + +def fun_l29_n760() + inc +end + +def fun_l29_n761() + inc +end + +def fun_l29_n762() + inc +end + +def fun_l29_n763() + inc +end + +def fun_l29_n764() + inc +end + +def fun_l29_n765() + inc +end + +def fun_l29_n766() + inc +end + +def fun_l29_n767() + inc +end + +def fun_l29_n768() + inc +end + +def fun_l29_n769() + inc +end + +def fun_l29_n770() + inc +end + +def fun_l29_n771() + inc +end + +def fun_l29_n772() + inc +end + +def fun_l29_n773() + inc +end + +def fun_l29_n774() + inc +end + +def fun_l29_n775() + inc +end + +def fun_l29_n776() + inc +end + +def fun_l29_n777() + inc +end + +def fun_l29_n778() + inc +end + +def fun_l29_n779() + inc +end + +def fun_l29_n780() + inc +end + +def fun_l29_n781() + inc +end + +def fun_l29_n782() + inc +end + +def fun_l29_n783() + inc +end + +def fun_l29_n784() + inc +end + +def fun_l29_n785() + inc +end + +def fun_l29_n786() + inc +end + +def fun_l29_n787() + inc +end + +def fun_l29_n788() + inc +end + +def fun_l29_n789() + inc +end + +def fun_l29_n790() + inc +end + +def fun_l29_n791() + inc +end + +def fun_l29_n792() + inc +end + +def fun_l29_n793() + inc +end + +def fun_l29_n794() + inc +end + +def fun_l29_n795() + inc +end + +def fun_l29_n796() + inc +end + +def fun_l29_n797() + inc +end + +def fun_l29_n798() + inc +end + +def fun_l29_n799() + inc +end + +def fun_l29_n800() + inc +end + +def fun_l29_n801() + inc +end + +def fun_l29_n802() + inc +end + +def fun_l29_n803() + inc +end + +def fun_l29_n804() + inc +end + +def fun_l29_n805() + inc +end + +def fun_l29_n806() + inc +end + +def fun_l29_n807() + inc +end + +def fun_l29_n808() + inc +end + +def fun_l29_n809() + inc +end + +def fun_l29_n810() + inc +end + +def fun_l29_n811() + inc +end + +def fun_l29_n812() + inc +end + +def fun_l29_n813() + inc +end + +def fun_l29_n814() + inc +end + +def fun_l29_n815() + inc +end + +def fun_l29_n816() + inc +end + +def fun_l29_n817() + inc +end + +def fun_l29_n818() + inc +end + +def fun_l29_n819() + inc +end + +def fun_l29_n820() + inc +end + +def fun_l29_n821() + inc +end + +def fun_l29_n822() + inc +end + +def fun_l29_n823() + inc +end + +def fun_l29_n824() + inc +end + +def fun_l29_n825() + inc +end + +def fun_l29_n826() + inc +end + +def fun_l29_n827() + inc +end + +def fun_l29_n828() + inc +end + +def fun_l29_n829() + inc +end + +def fun_l29_n830() + inc +end + +def fun_l29_n831() + inc +end + +def fun_l29_n832() + inc +end + +def fun_l29_n833() + inc +end + +def fun_l29_n834() + inc +end + +def fun_l29_n835() + inc +end + +def fun_l29_n836() + inc +end + +def fun_l29_n837() + inc +end + +def fun_l29_n838() + inc +end + +def fun_l29_n839() + inc +end + +def fun_l29_n840() + inc +end + +def fun_l29_n841() + inc +end + +def fun_l29_n842() + inc +end + +def fun_l29_n843() + inc +end + +def fun_l29_n844() + inc +end + +def fun_l29_n845() + inc +end + +def fun_l29_n846() + inc +end + +def fun_l29_n847() + inc +end + +def fun_l29_n848() + inc +end + +def fun_l29_n849() + inc +end + +def fun_l29_n850() + inc +end + +def fun_l29_n851() + inc +end + +def fun_l29_n852() + inc +end + +def fun_l29_n853() + inc +end + +def fun_l29_n854() + inc +end + +def fun_l29_n855() + inc +end + +def fun_l29_n856() + inc +end + +def fun_l29_n857() + inc +end + +def fun_l29_n858() + inc +end + +def fun_l29_n859() + inc +end + +def fun_l29_n860() + inc +end + +def fun_l29_n861() + inc +end + +def fun_l29_n862() + inc +end + +def fun_l29_n863() + inc +end + +def fun_l29_n864() + inc +end + +def fun_l29_n865() + inc +end + +def fun_l29_n866() + inc +end + +def fun_l29_n867() + inc +end + +def fun_l29_n868() + inc +end + +def fun_l29_n869() + inc +end + +def fun_l29_n870() + inc +end + +def fun_l29_n871() + inc +end + +def fun_l29_n872() + inc +end + +def fun_l29_n873() + inc +end + +def fun_l29_n874() + inc +end + +def fun_l29_n875() + inc +end + +def fun_l29_n876() + inc +end + +def fun_l29_n877() + inc +end + +def fun_l29_n878() + inc +end + +def fun_l29_n879() + inc +end + +def fun_l29_n880() + inc +end + +def fun_l29_n881() + inc +end + +def fun_l29_n882() + inc +end + +def fun_l29_n883() + inc +end + +def fun_l29_n884() + inc +end + +def fun_l29_n885() + inc +end + +def fun_l29_n886() + inc +end + +def fun_l29_n887() + inc +end + +def fun_l29_n888() + inc +end + +def fun_l29_n889() + inc +end + +def fun_l29_n890() + inc +end + +def fun_l29_n891() + inc +end + +def fun_l29_n892() + inc +end + +def fun_l29_n893() + inc +end + +def fun_l29_n894() + inc +end + +def fun_l29_n895() + inc +end + +def fun_l29_n896() + inc +end + +def fun_l29_n897() + inc +end + +def fun_l29_n898() + inc +end + +def fun_l29_n899() + inc +end + +def fun_l29_n900() + inc +end + +def fun_l29_n901() + inc +end + +def fun_l29_n902() + inc +end + +def fun_l29_n903() + inc +end + +def fun_l29_n904() + inc +end + +def fun_l29_n905() + inc +end + +def fun_l29_n906() + inc +end + +def fun_l29_n907() + inc +end + +def fun_l29_n908() + inc +end + +def fun_l29_n909() + inc +end + +def fun_l29_n910() + inc +end + +def fun_l29_n911() + inc +end + +def fun_l29_n912() + inc +end + +def fun_l29_n913() + inc +end + +def fun_l29_n914() + inc +end + +def fun_l29_n915() + inc +end + +def fun_l29_n916() + inc +end + +def fun_l29_n917() + inc +end + +def fun_l29_n918() + inc +end + +def fun_l29_n919() + inc +end + +def fun_l29_n920() + inc +end + +def fun_l29_n921() + inc +end + +def fun_l29_n922() + inc +end + +def fun_l29_n923() + inc +end + +def fun_l29_n924() + inc +end + +def fun_l29_n925() + inc +end + +def fun_l29_n926() + inc +end + +def fun_l29_n927() + inc +end + +def fun_l29_n928() + inc +end + +def fun_l29_n929() + inc +end + +def fun_l29_n930() + inc +end + +def fun_l29_n931() + inc +end + +def fun_l29_n932() + inc +end + +def fun_l29_n933() + inc +end + +def fun_l29_n934() + inc +end + +def fun_l29_n935() + inc +end + +def fun_l29_n936() + inc +end + +def fun_l29_n937() + inc +end + +def fun_l29_n938() + inc +end + +def fun_l29_n939() + inc +end + +def fun_l29_n940() + inc +end + +def fun_l29_n941() + inc +end + +def fun_l29_n942() + inc +end + +def fun_l29_n943() + inc +end + +def fun_l29_n944() + inc +end + +def fun_l29_n945() + inc +end + +def fun_l29_n946() + inc +end + +def fun_l29_n947() + inc +end + +def fun_l29_n948() + inc +end + +def fun_l29_n949() + inc +end + +def fun_l29_n950() + inc +end + +def fun_l29_n951() + inc +end + +def fun_l29_n952() + inc +end + +def fun_l29_n953() + inc +end + +def fun_l29_n954() + inc +end + +def fun_l29_n955() + inc +end + +def fun_l29_n956() + inc +end + +def fun_l29_n957() + inc +end + +def fun_l29_n958() + inc +end + +def fun_l29_n959() + inc +end + +def fun_l29_n960() + inc +end + +def fun_l29_n961() + inc +end + +def fun_l29_n962() + inc +end + +def fun_l29_n963() + inc +end + +def fun_l29_n964() + inc +end + +def fun_l29_n965() + inc +end + +def fun_l29_n966() + inc +end + +def fun_l29_n967() + inc +end + +def fun_l29_n968() + inc +end + +def fun_l29_n969() + inc +end + +def fun_l29_n970() + inc +end + +def fun_l29_n971() + inc +end + +def fun_l29_n972() + inc +end + +def fun_l29_n973() + inc +end + +def fun_l29_n974() + inc +end + +def fun_l29_n975() + inc +end + +def fun_l29_n976() + inc +end + +def fun_l29_n977() + inc +end + +def fun_l29_n978() + inc +end + +def fun_l29_n979() + inc +end + +def fun_l29_n980() + inc +end + +def fun_l29_n981() + inc +end + +def fun_l29_n982() + inc +end + +def fun_l29_n983() + inc +end + +def fun_l29_n984() + inc +end + +def fun_l29_n985() + inc +end + +def fun_l29_n986() + inc +end + +def fun_l29_n987() + inc +end + +def fun_l29_n988() + inc +end + +def fun_l29_n989() + inc +end + +def fun_l29_n990() + inc +end + +def fun_l29_n991() + inc +end + +def fun_l29_n992() + inc +end + +def fun_l29_n993() + inc +end + +def fun_l29_n994() + inc +end + +def fun_l29_n995() + inc +end + +def fun_l29_n996() + inc +end + +def fun_l29_n997() + inc +end + +def fun_l29_n998() + inc +end + +def fun_l29_n999() + inc +end + +@a = 0 +@b = 0 +@c = 0 +@d = 0 +@count = 0 +def inc() + @count += 1 +end +1000.times do + fun_l0_n0 + fun_l0_n1 + fun_l0_n2 + fun_l0_n3 + fun_l0_n4 + fun_l0_n5 + fun_l0_n6 + fun_l0_n7 + fun_l0_n8 + fun_l0_n9 + fun_l0_n10 + fun_l0_n11 + fun_l0_n12 + fun_l0_n13 + fun_l0_n14 + fun_l0_n15 + fun_l0_n16 + fun_l0_n17 + fun_l0_n18 + fun_l0_n19 + fun_l0_n20 + fun_l0_n21 + fun_l0_n22 + fun_l0_n23 + fun_l0_n24 + fun_l0_n25 + fun_l0_n26 + fun_l0_n27 + fun_l0_n28 + fun_l0_n29 + fun_l0_n30 + fun_l0_n31 + fun_l0_n32 + fun_l0_n33 + fun_l0_n34 + fun_l0_n35 + fun_l0_n36 + fun_l0_n37 + fun_l0_n38 + fun_l0_n39 + fun_l0_n40 + fun_l0_n41 + fun_l0_n42 + fun_l0_n43 + fun_l0_n44 + fun_l0_n45 + fun_l0_n46 + fun_l0_n47 + fun_l0_n48 + fun_l0_n49 + fun_l0_n50 + fun_l0_n51 + fun_l0_n52 + fun_l0_n53 + fun_l0_n54 + fun_l0_n55 + fun_l0_n56 + fun_l0_n57 + fun_l0_n58 + fun_l0_n59 + fun_l0_n60 + fun_l0_n61 + fun_l0_n62 + fun_l0_n63 + fun_l0_n64 + fun_l0_n65 + fun_l0_n66 + fun_l0_n67 + fun_l0_n68 + fun_l0_n69 + fun_l0_n70 + fun_l0_n71 + fun_l0_n72 + fun_l0_n73 + fun_l0_n74 + fun_l0_n75 + fun_l0_n76 + fun_l0_n77 + fun_l0_n78 + fun_l0_n79 + fun_l0_n80 + fun_l0_n81 + fun_l0_n82 + fun_l0_n83 + fun_l0_n84 + fun_l0_n85 + fun_l0_n86 + fun_l0_n87 + fun_l0_n88 + fun_l0_n89 + fun_l0_n90 + fun_l0_n91 + fun_l0_n92 + fun_l0_n93 + fun_l0_n94 + fun_l0_n95 + fun_l0_n96 + fun_l0_n97 + fun_l0_n98 + fun_l0_n99 + fun_l0_n100 + fun_l0_n101 + fun_l0_n102 + fun_l0_n103 + fun_l0_n104 + fun_l0_n105 + fun_l0_n106 + fun_l0_n107 + fun_l0_n108 + fun_l0_n109 + fun_l0_n110 + fun_l0_n111 + fun_l0_n112 + fun_l0_n113 + fun_l0_n114 + fun_l0_n115 + fun_l0_n116 + fun_l0_n117 + fun_l0_n118 + fun_l0_n119 + fun_l0_n120 + fun_l0_n121 + fun_l0_n122 + fun_l0_n123 + fun_l0_n124 + fun_l0_n125 + fun_l0_n126 + fun_l0_n127 + fun_l0_n128 + fun_l0_n129 + fun_l0_n130 + fun_l0_n131 + fun_l0_n132 + fun_l0_n133 + fun_l0_n134 + fun_l0_n135 + fun_l0_n136 + fun_l0_n137 + fun_l0_n138 + fun_l0_n139 + fun_l0_n140 + fun_l0_n141 + fun_l0_n142 + fun_l0_n143 + fun_l0_n144 + fun_l0_n145 + fun_l0_n146 + fun_l0_n147 + fun_l0_n148 + fun_l0_n149 + fun_l0_n150 + fun_l0_n151 + fun_l0_n152 + fun_l0_n153 + fun_l0_n154 + fun_l0_n155 + fun_l0_n156 + fun_l0_n157 + fun_l0_n158 + fun_l0_n159 + fun_l0_n160 + fun_l0_n161 + fun_l0_n162 + fun_l0_n163 + fun_l0_n164 + fun_l0_n165 + fun_l0_n166 + fun_l0_n167 + fun_l0_n168 + fun_l0_n169 + fun_l0_n170 + fun_l0_n171 + fun_l0_n172 + fun_l0_n173 + fun_l0_n174 + fun_l0_n175 + fun_l0_n176 + fun_l0_n177 + fun_l0_n178 + fun_l0_n179 + fun_l0_n180 + fun_l0_n181 + fun_l0_n182 + fun_l0_n183 + fun_l0_n184 + fun_l0_n185 + fun_l0_n186 + fun_l0_n187 + fun_l0_n188 + fun_l0_n189 + fun_l0_n190 + fun_l0_n191 + fun_l0_n192 + fun_l0_n193 + fun_l0_n194 + fun_l0_n195 + fun_l0_n196 + fun_l0_n197 + fun_l0_n198 + fun_l0_n199 + fun_l0_n200 + fun_l0_n201 + fun_l0_n202 + fun_l0_n203 + fun_l0_n204 + fun_l0_n205 + fun_l0_n206 + fun_l0_n207 + fun_l0_n208 + fun_l0_n209 + fun_l0_n210 + fun_l0_n211 + fun_l0_n212 + fun_l0_n213 + fun_l0_n214 + fun_l0_n215 + fun_l0_n216 + fun_l0_n217 + fun_l0_n218 + fun_l0_n219 + fun_l0_n220 + fun_l0_n221 + fun_l0_n222 + fun_l0_n223 + fun_l0_n224 + fun_l0_n225 + fun_l0_n226 + fun_l0_n227 + fun_l0_n228 + fun_l0_n229 + fun_l0_n230 + fun_l0_n231 + fun_l0_n232 + fun_l0_n233 + fun_l0_n234 + fun_l0_n235 + fun_l0_n236 + fun_l0_n237 + fun_l0_n238 + fun_l0_n239 + fun_l0_n240 + fun_l0_n241 + fun_l0_n242 + fun_l0_n243 + fun_l0_n244 + fun_l0_n245 + fun_l0_n246 + fun_l0_n247 + fun_l0_n248 + fun_l0_n249 + fun_l0_n250 + fun_l0_n251 + fun_l0_n252 + fun_l0_n253 + fun_l0_n254 + fun_l0_n255 + fun_l0_n256 + fun_l0_n257 + fun_l0_n258 + fun_l0_n259 + fun_l0_n260 + fun_l0_n261 + fun_l0_n262 + fun_l0_n263 + fun_l0_n264 + fun_l0_n265 + fun_l0_n266 + fun_l0_n267 + fun_l0_n268 + fun_l0_n269 + fun_l0_n270 + fun_l0_n271 + fun_l0_n272 + fun_l0_n273 + fun_l0_n274 + fun_l0_n275 + fun_l0_n276 + fun_l0_n277 + fun_l0_n278 + fun_l0_n279 + fun_l0_n280 + fun_l0_n281 + fun_l0_n282 + fun_l0_n283 + fun_l0_n284 + fun_l0_n285 + fun_l0_n286 + fun_l0_n287 + fun_l0_n288 + fun_l0_n289 + fun_l0_n290 + fun_l0_n291 + fun_l0_n292 + fun_l0_n293 + fun_l0_n294 + fun_l0_n295 + fun_l0_n296 + fun_l0_n297 + fun_l0_n298 + fun_l0_n299 + fun_l0_n300 + fun_l0_n301 + fun_l0_n302 + fun_l0_n303 + fun_l0_n304 + fun_l0_n305 + fun_l0_n306 + fun_l0_n307 + fun_l0_n308 + fun_l0_n309 + fun_l0_n310 + fun_l0_n311 + fun_l0_n312 + fun_l0_n313 + fun_l0_n314 + fun_l0_n315 + fun_l0_n316 + fun_l0_n317 + fun_l0_n318 + fun_l0_n319 + fun_l0_n320 + fun_l0_n321 + fun_l0_n322 + fun_l0_n323 + fun_l0_n324 + fun_l0_n325 + fun_l0_n326 + fun_l0_n327 + fun_l0_n328 + fun_l0_n329 + fun_l0_n330 + fun_l0_n331 + fun_l0_n332 + fun_l0_n333 + fun_l0_n334 + fun_l0_n335 + fun_l0_n336 + fun_l0_n337 + fun_l0_n338 + fun_l0_n339 + fun_l0_n340 + fun_l0_n341 + fun_l0_n342 + fun_l0_n343 + fun_l0_n344 + fun_l0_n345 + fun_l0_n346 + fun_l0_n347 + fun_l0_n348 + fun_l0_n349 + fun_l0_n350 + fun_l0_n351 + fun_l0_n352 + fun_l0_n353 + fun_l0_n354 + fun_l0_n355 + fun_l0_n356 + fun_l0_n357 + fun_l0_n358 + fun_l0_n359 + fun_l0_n360 + fun_l0_n361 + fun_l0_n362 + fun_l0_n363 + fun_l0_n364 + fun_l0_n365 + fun_l0_n366 + fun_l0_n367 + fun_l0_n368 + fun_l0_n369 + fun_l0_n370 + fun_l0_n371 + fun_l0_n372 + fun_l0_n373 + fun_l0_n374 + fun_l0_n375 + fun_l0_n376 + fun_l0_n377 + fun_l0_n378 + fun_l0_n379 + fun_l0_n380 + fun_l0_n381 + fun_l0_n382 + fun_l0_n383 + fun_l0_n384 + fun_l0_n385 + fun_l0_n386 + fun_l0_n387 + fun_l0_n388 + fun_l0_n389 + fun_l0_n390 + fun_l0_n391 + fun_l0_n392 + fun_l0_n393 + fun_l0_n394 + fun_l0_n395 + fun_l0_n396 + fun_l0_n397 + fun_l0_n398 + fun_l0_n399 + fun_l0_n400 + fun_l0_n401 + fun_l0_n402 + fun_l0_n403 + fun_l0_n404 + fun_l0_n405 + fun_l0_n406 + fun_l0_n407 + fun_l0_n408 + fun_l0_n409 + fun_l0_n410 + fun_l0_n411 + fun_l0_n412 + fun_l0_n413 + fun_l0_n414 + fun_l0_n415 + fun_l0_n416 + fun_l0_n417 + fun_l0_n418 + fun_l0_n419 + fun_l0_n420 + fun_l0_n421 + fun_l0_n422 + fun_l0_n423 + fun_l0_n424 + fun_l0_n425 + fun_l0_n426 + fun_l0_n427 + fun_l0_n428 + fun_l0_n429 + fun_l0_n430 + fun_l0_n431 + fun_l0_n432 + fun_l0_n433 + fun_l0_n434 + fun_l0_n435 + fun_l0_n436 + fun_l0_n437 + fun_l0_n438 + fun_l0_n439 + fun_l0_n440 + fun_l0_n441 + fun_l0_n442 + fun_l0_n443 + fun_l0_n444 + fun_l0_n445 + fun_l0_n446 + fun_l0_n447 + fun_l0_n448 + fun_l0_n449 + fun_l0_n450 + fun_l0_n451 + fun_l0_n452 + fun_l0_n453 + fun_l0_n454 + fun_l0_n455 + fun_l0_n456 + fun_l0_n457 + fun_l0_n458 + fun_l0_n459 + fun_l0_n460 + fun_l0_n461 + fun_l0_n462 + fun_l0_n463 + fun_l0_n464 + fun_l0_n465 + fun_l0_n466 + fun_l0_n467 + fun_l0_n468 + fun_l0_n469 + fun_l0_n470 + fun_l0_n471 + fun_l0_n472 + fun_l0_n473 + fun_l0_n474 + fun_l0_n475 + fun_l0_n476 + fun_l0_n477 + fun_l0_n478 + fun_l0_n479 + fun_l0_n480 + fun_l0_n481 + fun_l0_n482 + fun_l0_n483 + fun_l0_n484 + fun_l0_n485 + fun_l0_n486 + fun_l0_n487 + fun_l0_n488 + fun_l0_n489 + fun_l0_n490 + fun_l0_n491 + fun_l0_n492 + fun_l0_n493 + fun_l0_n494 + fun_l0_n495 + fun_l0_n496 + fun_l0_n497 + fun_l0_n498 + fun_l0_n499 + fun_l0_n500 + fun_l0_n501 + fun_l0_n502 + fun_l0_n503 + fun_l0_n504 + fun_l0_n505 + fun_l0_n506 + fun_l0_n507 + fun_l0_n508 + fun_l0_n509 + fun_l0_n510 + fun_l0_n511 + fun_l0_n512 + fun_l0_n513 + fun_l0_n514 + fun_l0_n515 + fun_l0_n516 + fun_l0_n517 + fun_l0_n518 + fun_l0_n519 + fun_l0_n520 + fun_l0_n521 + fun_l0_n522 + fun_l0_n523 + fun_l0_n524 + fun_l0_n525 + fun_l0_n526 + fun_l0_n527 + fun_l0_n528 + fun_l0_n529 + fun_l0_n530 + fun_l0_n531 + fun_l0_n532 + fun_l0_n533 + fun_l0_n534 + fun_l0_n535 + fun_l0_n536 + fun_l0_n537 + fun_l0_n538 + fun_l0_n539 + fun_l0_n540 + fun_l0_n541 + fun_l0_n542 + fun_l0_n543 + fun_l0_n544 + fun_l0_n545 + fun_l0_n546 + fun_l0_n547 + fun_l0_n548 + fun_l0_n549 + fun_l0_n550 + fun_l0_n551 + fun_l0_n552 + fun_l0_n553 + fun_l0_n554 + fun_l0_n555 + fun_l0_n556 + fun_l0_n557 + fun_l0_n558 + fun_l0_n559 + fun_l0_n560 + fun_l0_n561 + fun_l0_n562 + fun_l0_n563 + fun_l0_n564 + fun_l0_n565 + fun_l0_n566 + fun_l0_n567 + fun_l0_n568 + fun_l0_n569 + fun_l0_n570 + fun_l0_n571 + fun_l0_n572 + fun_l0_n573 + fun_l0_n574 + fun_l0_n575 + fun_l0_n576 + fun_l0_n577 + fun_l0_n578 + fun_l0_n579 + fun_l0_n580 + fun_l0_n581 + fun_l0_n582 + fun_l0_n583 + fun_l0_n584 + fun_l0_n585 + fun_l0_n586 + fun_l0_n587 + fun_l0_n588 + fun_l0_n589 + fun_l0_n590 + fun_l0_n591 + fun_l0_n592 + fun_l0_n593 + fun_l0_n594 + fun_l0_n595 + fun_l0_n596 + fun_l0_n597 + fun_l0_n598 + fun_l0_n599 + fun_l0_n600 + fun_l0_n601 + fun_l0_n602 + fun_l0_n603 + fun_l0_n604 + fun_l0_n605 + fun_l0_n606 + fun_l0_n607 + fun_l0_n608 + fun_l0_n609 + fun_l0_n610 + fun_l0_n611 + fun_l0_n612 + fun_l0_n613 + fun_l0_n614 + fun_l0_n615 + fun_l0_n616 + fun_l0_n617 + fun_l0_n618 + fun_l0_n619 + fun_l0_n620 + fun_l0_n621 + fun_l0_n622 + fun_l0_n623 + fun_l0_n624 + fun_l0_n625 + fun_l0_n626 + fun_l0_n627 + fun_l0_n628 + fun_l0_n629 + fun_l0_n630 + fun_l0_n631 + fun_l0_n632 + fun_l0_n633 + fun_l0_n634 + fun_l0_n635 + fun_l0_n636 + fun_l0_n637 + fun_l0_n638 + fun_l0_n639 + fun_l0_n640 + fun_l0_n641 + fun_l0_n642 + fun_l0_n643 + fun_l0_n644 + fun_l0_n645 + fun_l0_n646 + fun_l0_n647 + fun_l0_n648 + fun_l0_n649 + fun_l0_n650 + fun_l0_n651 + fun_l0_n652 + fun_l0_n653 + fun_l0_n654 + fun_l0_n655 + fun_l0_n656 + fun_l0_n657 + fun_l0_n658 + fun_l0_n659 + fun_l0_n660 + fun_l0_n661 + fun_l0_n662 + fun_l0_n663 + fun_l0_n664 + fun_l0_n665 + fun_l0_n666 + fun_l0_n667 + fun_l0_n668 + fun_l0_n669 + fun_l0_n670 + fun_l0_n671 + fun_l0_n672 + fun_l0_n673 + fun_l0_n674 + fun_l0_n675 + fun_l0_n676 + fun_l0_n677 + fun_l0_n678 + fun_l0_n679 + fun_l0_n680 + fun_l0_n681 + fun_l0_n682 + fun_l0_n683 + fun_l0_n684 + fun_l0_n685 + fun_l0_n686 + fun_l0_n687 + fun_l0_n688 + fun_l0_n689 + fun_l0_n690 + fun_l0_n691 + fun_l0_n692 + fun_l0_n693 + fun_l0_n694 + fun_l0_n695 + fun_l0_n696 + fun_l0_n697 + fun_l0_n698 + fun_l0_n699 + fun_l0_n700 + fun_l0_n701 + fun_l0_n702 + fun_l0_n703 + fun_l0_n704 + fun_l0_n705 + fun_l0_n706 + fun_l0_n707 + fun_l0_n708 + fun_l0_n709 + fun_l0_n710 + fun_l0_n711 + fun_l0_n712 + fun_l0_n713 + fun_l0_n714 + fun_l0_n715 + fun_l0_n716 + fun_l0_n717 + fun_l0_n718 + fun_l0_n719 + fun_l0_n720 + fun_l0_n721 + fun_l0_n722 + fun_l0_n723 + fun_l0_n724 + fun_l0_n725 + fun_l0_n726 + fun_l0_n727 + fun_l0_n728 + fun_l0_n729 + fun_l0_n730 + fun_l0_n731 + fun_l0_n732 + fun_l0_n733 + fun_l0_n734 + fun_l0_n735 + fun_l0_n736 + fun_l0_n737 + fun_l0_n738 + fun_l0_n739 + fun_l0_n740 + fun_l0_n741 + fun_l0_n742 + fun_l0_n743 + fun_l0_n744 + fun_l0_n745 + fun_l0_n746 + fun_l0_n747 + fun_l0_n748 + fun_l0_n749 + fun_l0_n750 + fun_l0_n751 + fun_l0_n752 + fun_l0_n753 + fun_l0_n754 + fun_l0_n755 + fun_l0_n756 + fun_l0_n757 + fun_l0_n758 + fun_l0_n759 + fun_l0_n760 + fun_l0_n761 + fun_l0_n762 + fun_l0_n763 + fun_l0_n764 + fun_l0_n765 + fun_l0_n766 + fun_l0_n767 + fun_l0_n768 + fun_l0_n769 + fun_l0_n770 + fun_l0_n771 + fun_l0_n772 + fun_l0_n773 + fun_l0_n774 + fun_l0_n775 + fun_l0_n776 + fun_l0_n777 + fun_l0_n778 + fun_l0_n779 + fun_l0_n780 + fun_l0_n781 + fun_l0_n782 + fun_l0_n783 + fun_l0_n784 + fun_l0_n785 + fun_l0_n786 + fun_l0_n787 + fun_l0_n788 + fun_l0_n789 + fun_l0_n790 + fun_l0_n791 + fun_l0_n792 + fun_l0_n793 + fun_l0_n794 + fun_l0_n795 + fun_l0_n796 + fun_l0_n797 + fun_l0_n798 + fun_l0_n799 + fun_l0_n800 + fun_l0_n801 + fun_l0_n802 + fun_l0_n803 + fun_l0_n804 + fun_l0_n805 + fun_l0_n806 + fun_l0_n807 + fun_l0_n808 + fun_l0_n809 + fun_l0_n810 + fun_l0_n811 + fun_l0_n812 + fun_l0_n813 + fun_l0_n814 + fun_l0_n815 + fun_l0_n816 + fun_l0_n817 + fun_l0_n818 + fun_l0_n819 + fun_l0_n820 + fun_l0_n821 + fun_l0_n822 + fun_l0_n823 + fun_l0_n824 + fun_l0_n825 + fun_l0_n826 + fun_l0_n827 + fun_l0_n828 + fun_l0_n829 + fun_l0_n830 + fun_l0_n831 + fun_l0_n832 + fun_l0_n833 + fun_l0_n834 + fun_l0_n835 + fun_l0_n836 + fun_l0_n837 + fun_l0_n838 + fun_l0_n839 + fun_l0_n840 + fun_l0_n841 + fun_l0_n842 + fun_l0_n843 + fun_l0_n844 + fun_l0_n845 + fun_l0_n846 + fun_l0_n847 + fun_l0_n848 + fun_l0_n849 + fun_l0_n850 + fun_l0_n851 + fun_l0_n852 + fun_l0_n853 + fun_l0_n854 + fun_l0_n855 + fun_l0_n856 + fun_l0_n857 + fun_l0_n858 + fun_l0_n859 + fun_l0_n860 + fun_l0_n861 + fun_l0_n862 + fun_l0_n863 + fun_l0_n864 + fun_l0_n865 + fun_l0_n866 + fun_l0_n867 + fun_l0_n868 + fun_l0_n869 + fun_l0_n870 + fun_l0_n871 + fun_l0_n872 + fun_l0_n873 + fun_l0_n874 + fun_l0_n875 + fun_l0_n876 + fun_l0_n877 + fun_l0_n878 + fun_l0_n879 + fun_l0_n880 + fun_l0_n881 + fun_l0_n882 + fun_l0_n883 + fun_l0_n884 + fun_l0_n885 + fun_l0_n886 + fun_l0_n887 + fun_l0_n888 + fun_l0_n889 + fun_l0_n890 + fun_l0_n891 + fun_l0_n892 + fun_l0_n893 + fun_l0_n894 + fun_l0_n895 + fun_l0_n896 + fun_l0_n897 + fun_l0_n898 + fun_l0_n899 + fun_l0_n900 + fun_l0_n901 + fun_l0_n902 + fun_l0_n903 + fun_l0_n904 + fun_l0_n905 + fun_l0_n906 + fun_l0_n907 + fun_l0_n908 + fun_l0_n909 + fun_l0_n910 + fun_l0_n911 + fun_l0_n912 + fun_l0_n913 + fun_l0_n914 + fun_l0_n915 + fun_l0_n916 + fun_l0_n917 + fun_l0_n918 + fun_l0_n919 + fun_l0_n920 + fun_l0_n921 + fun_l0_n922 + fun_l0_n923 + fun_l0_n924 + fun_l0_n925 + fun_l0_n926 + fun_l0_n927 + fun_l0_n928 + fun_l0_n929 + fun_l0_n930 + fun_l0_n931 + fun_l0_n932 + fun_l0_n933 + fun_l0_n934 + fun_l0_n935 + fun_l0_n936 + fun_l0_n937 + fun_l0_n938 + fun_l0_n939 + fun_l0_n940 + fun_l0_n941 + fun_l0_n942 + fun_l0_n943 + fun_l0_n944 + fun_l0_n945 + fun_l0_n946 + fun_l0_n947 + fun_l0_n948 + fun_l0_n949 + fun_l0_n950 + fun_l0_n951 + fun_l0_n952 + fun_l0_n953 + fun_l0_n954 + fun_l0_n955 + fun_l0_n956 + fun_l0_n957 + fun_l0_n958 + fun_l0_n959 + fun_l0_n960 + fun_l0_n961 + fun_l0_n962 + fun_l0_n963 + fun_l0_n964 + fun_l0_n965 + fun_l0_n966 + fun_l0_n967 + fun_l0_n968 + fun_l0_n969 + fun_l0_n970 + fun_l0_n971 + fun_l0_n972 + fun_l0_n973 + fun_l0_n974 + fun_l0_n975 + fun_l0_n976 + fun_l0_n977 + fun_l0_n978 + fun_l0_n979 + fun_l0_n980 + fun_l0_n981 + fun_l0_n982 + fun_l0_n983 + fun_l0_n984 + fun_l0_n985 + fun_l0_n986 + fun_l0_n987 + fun_l0_n988 + fun_l0_n989 + fun_l0_n990 + fun_l0_n991 + fun_l0_n992 + fun_l0_n993 + fun_l0_n994 + fun_l0_n995 + fun_l0_n996 + fun_l0_n997 + fun_l0_n998 + fun_l0_n999 +end + +@count + +} diff --git a/ruby/builtin.c b/ruby/builtin.c index 6de77228d..21fff9565 100644 --- a/ruby/builtin.c +++ b/ruby/builtin.c @@ -3,7 +3,7 @@ #include "iseq.h" #include "builtin.h" -#if CROSS_COMPILING +#ifdef CROSS_COMPILING #define INCLUDED_BY_BUILTIN_C 1 #include "mini_builtin.c" @@ -12,27 +12,24 @@ #include "builtin_binary.inc" +static const unsigned char * +bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize) +{ + *psize = bb->bin_size; + return strcmp(bb->feature, feature) ? NULL : bb->bin; +} + static const unsigned char* builtin_lookup(const char *feature, size_t *psize) { static int index = 0; - int i = index++; + const unsigned char *bin = bin4feature(&builtin_binary[index++], feature, psize); // usually, `builtin_binary` order is loading order at miniruby. - if (LIKELY(strcmp(builtin_binary[i].feature, feature) == 0)) { - found: - *psize = builtin_binary[i].bin_size; - return builtin_binary[i].bin; + for (const struct builtin_binary *bb = &builtin_binary[0]; bb->feature &&! bin; bb++) { + bin = bin4feature(bb++, feature, psize); } - else { - if (0) fprintf(stderr, "builtin_lookup: cached index miss (index:%d)\n", i); - for (i=0; icfp->ep[index]; #else return rb_vm_lvar_exposed(ec, index); diff --git a/ruby/ccan/list/list.h b/ruby/ccan/list/list.h index 7d219307b..c434ad810 100644 --- a/ruby/ccan/list/list.h +++ b/ruby/ccan/list/list.h @@ -658,7 +658,7 @@ static inline void list_prepend_list_(struct list_head *to, * @off: offset(relative to @i) at which list node data resides. * * This is a low-level wrapper to iterate @i over the entire list, used to - * implement all oher, more high-level, for-each constructs. It's a for loop, + * implement all other, more high-level, for-each constructs. It's a for loop, * so you can break and continue as normal. * * WARNING! Being the low-level macro that it is, this wrapper doesn't know diff --git a/ruby/class.c b/ruby/class.c index c866d1d72..65a989f9d 100644 --- a/ruby/class.c +++ b/ruby/class.c @@ -10,115 +10,148 @@ **********************************************************************/ /*! - * \defgroup class Classes and their hierarchy. - * \par Terminology - * - class: same as in Ruby. - * - singleton class: class for a particular object - * - eigenclass: = singleton class - * - metaclass: class of a class. metaclass is a kind of singleton class. - * - metametaclass: class of a metaclass. - * - meta^(n)-class: class of a meta^(n-1)-class. - * - attached object: A singleton class knows its unique instance. - * The instance is called the attached object for the singleton class. + * \addtogroup class * \{ */ +#include "ruby/internal/config.h" +#include + +#include "constant.h" +#include "debug_counter.h" +#include "id_table.h" #include "internal.h" +#include "internal/class.h" +#include "internal/eval.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/string.h" +#include "internal/variable.h" #include "ruby/st.h" -#include "constant.h" #include "vm_core.h" -#include "id_table.h" -#include #define id_attached id__attached__ -void -rb_class_subclass_add(VALUE super, VALUE klass) +#define METACLASS_OF(k) RBASIC(k)->klass +#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls) + +RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state; + +static rb_subclass_entry_t * +push_subclass_entry_to_list(VALUE super, VALUE klass) { rb_subclass_entry_t *entry, *head; - if (super && super != Qundef) { - entry = ALLOC(rb_subclass_entry_t); - entry->klass = klass; - entry->next = NULL; - - head = RCLASS_EXT(super)->subclasses; - if (head) { - entry->next = head; - RCLASS_EXT(head->klass)->parent_subclasses = &entry->next; - } + 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; + + if (head->next) { + head->next->prev = entry; + } + head->next = entry; - RCLASS_EXT(super)->subclasses = entry; - RCLASS_EXT(klass)->parent_subclasses = &RCLASS_EXT(super)->subclasses; + return entry; +} + +void +rb_class_subclass_add(VALUE super, VALUE klass) +{ + if (super && super != Qundef) { + rb_subclass_entry_t *entry = push_subclass_entry_to_list(super, klass); + RCLASS_SUBCLASS_ENTRY(klass) = entry; } } static void rb_module_add_to_subclasses_list(VALUE module, VALUE iclass) { - rb_subclass_entry_t *entry, *head; + rb_subclass_entry_t *entry = push_subclass_entry_to_list(module, iclass); + RCLASS_MODULE_SUBCLASS_ENTRY(iclass) = entry; +} - entry = ALLOC(rb_subclass_entry_t); - entry->klass = iclass; - entry->next = NULL; +void +rb_class_remove_subclass_head(VALUE klass) +{ + rb_subclass_entry_t *head = RCLASS_SUBCLASSES(klass); - head = RCLASS_EXT(module)->subclasses; if (head) { - entry->next = head; - RCLASS_EXT(head->klass)->module_subclasses = &entry->next; + if (head->next) { + head->next->prev = NULL; + } + RCLASS_SUBCLASSES(klass) = NULL; + xfree(head); } - - RCLASS_EXT(module)->subclasses = entry; - RCLASS_EXT(iclass)->module_subclasses = &RCLASS_EXT(module)->subclasses; } void rb_class_remove_from_super_subclasses(VALUE klass) { - rb_subclass_entry_t *entry; + rb_subclass_entry_t *entry = RCLASS_SUBCLASS_ENTRY(klass); - if (RCLASS_EXT(klass)->parent_subclasses) { - entry = *RCLASS_EXT(klass)->parent_subclasses; + if (entry) { + rb_subclass_entry_t *prev = entry->prev, *next = entry->next; + + if (prev) { + prev->next = next; + } + if (next) { + next->prev = prev; + } - *RCLASS_EXT(klass)->parent_subclasses = entry->next; - if (entry->next) { - RCLASS_EXT(entry->next->klass)->parent_subclasses = RCLASS_EXT(klass)->parent_subclasses; - } xfree(entry); } - RCLASS_EXT(klass)->parent_subclasses = NULL; + RCLASS_SUBCLASS_ENTRY(klass) = NULL; } void rb_class_remove_from_module_subclasses(VALUE klass) { - rb_subclass_entry_t *entry; + rb_subclass_entry_t *entry = RCLASS_MODULE_SUBCLASS_ENTRY(klass); - if (RCLASS_EXT(klass)->module_subclasses) { - entry = *RCLASS_EXT(klass)->module_subclasses; - *RCLASS_EXT(klass)->module_subclasses = entry->next; + if (entry) { + rb_subclass_entry_t *prev = entry->prev, *next = entry->next; - if (entry->next) { - RCLASS_EXT(entry->next->klass)->module_subclasses = RCLASS_EXT(klass)->module_subclasses; + if (prev) { + prev->next = next; + } + if (next) { + next->prev = prev; } xfree(entry); } - RCLASS_EXT(klass)->module_subclasses = NULL; + RCLASS_MODULE_SUBCLASS_ENTRY(klass) = NULL; } void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg) { - rb_subclass_entry_t *cur = RCLASS_EXT(klass)->subclasses; + // 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; + } /* 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; + // do not trigger GC during f, otherwise the cur will become + // a dangling pointer if the subclass is collected f(curklass, arg); } } @@ -162,22 +195,37 @@ rb_class_detach_module_subclasses(VALUE klass) static VALUE class_alloc(VALUE flags, VALUE klass) { - NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | FL_PROMOTED1 /* start from age == 2 */ | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0)); + size_t alloc_size = sizeof(struct RClass); + +#if USE_RVARGC + alloc_size += sizeof(rb_classext_t); +#endif + + flags &= T_MASK; + flags |= FL_PROMOTED1 /* start from age == 2 */; + if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED; + RVARGC_NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size); + +#if USE_RVARGC + memset(RCLASS_EXT(obj), 0, sizeof(rb_classext_t)); +#else obj->ptr = ZALLOC(rb_classext_t); +#endif + /* ZALLOC RCLASS_IV_TBL(obj) = 0; RCLASS_CONST_TBL(obj) = 0; RCLASS_M_TBL(obj) = 0; RCLASS_IV_INDEX_TBL(obj) = 0; RCLASS_SET_SUPER((VALUE)obj, 0); - RCLASS_EXT(obj)->subclasses = NULL; - RCLASS_EXT(obj)->parent_subclasses = NULL; - RCLASS_EXT(obj)->module_subclasses = NULL; + RCLASS_SUBCLASSES(obj) = NULL; + RCLASS_PARENT_SUBCLASSES(obj) = NULL; + RCLASS_MODULE_SUBCLASSES(obj) = NULL; */ RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj); RCLASS_SERIAL(obj) = rb_next_class_serial(); RB_OBJ_WRITE(obj, &RCLASS_REFINED_CLASS(obj), Qnil); - RCLASS_EXT(obj)->allocator = 0; + RCLASS_ALLOCATOR(obj) = 0; return (VALUE)obj; } @@ -208,18 +256,11 @@ rb_class_boot(VALUE super) return (VALUE)klass; } - -/*! - * Ensures a class can be derived from super. - * - * \param super a reference to an object. - * \exception TypeError if \a super is not a Class or \a super is a singleton class. - */ void rb_check_inheritable(VALUE super) { if (!RB_TYPE_P(super, T_CLASS)) { - rb_raise(rb_eTypeError, "superclass must be a Class (%"PRIsVALUE" given)", + 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) { @@ -230,13 +271,6 @@ rb_check_inheritable(VALUE super) } } - -/*! - * Creates a new class. - * \param super a class from which the new class derives. - * \exception TypeError \a super is not inheritable. - * \exception TypeError \a super is the Class class. - */ VALUE rb_class_new(VALUE super) { @@ -245,6 +279,12 @@ rb_class_new(VALUE super) return rb_class_boot(super); } +VALUE +rb_class_s_alloc(VALUE klass) +{ + return rb_class_boot(0); +} + static void clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me) { @@ -308,26 +348,9 @@ class_init_copy_check(VALUE clone, VALUE orig) } } -/* :nodoc: */ -VALUE -rb_mod_init_copy(VALUE clone, VALUE orig) +static void +copy_tables(VALUE clone, VALUE orig) { - /* cloned flag is refer at constant inline cache - * see vm_get_const_key_cref() in vm_insnhelper.c - */ - FL_SET(clone, RCLASS_CLONED); - FL_SET(orig , RCLASS_CLONED); - - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } - if (!OBJ_INIT_COPY(clone, orig)) return clone; - if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { - RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig)); - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig)); - RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator; if (RCLASS_IV_TBL(clone)) { st_free_table(RCLASS_IV_TBL(clone)); RCLASS_IV_TBL(clone) = 0; @@ -355,6 +378,66 @@ rb_mod_init_copy(VALUE clone, VALUE orig) arg.klass = clone; rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg); } +} + +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_USER5}; + +static inline bool +RMODULE_UNINITIALIZED(VALUE module) +{ + return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); +} + +void +rb_module_set_initialized(VALUE mod) +{ + FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); + /* no more re-initialization */ +} + +void +rb_module_check_initializable(VALUE mod) +{ + if (!RMODULE_UNINITIALIZED(mod)) { + rb_raise(rb_eTypeError, "already initialized module"); + } + RB_OBJ_WRITE(mod, &RCLASS(mod)->super, 0); +} + +/* :nodoc: */ +VALUE +rb_mod_init_copy(VALUE clone, VALUE orig) +{ + switch (BUILTIN_TYPE(clone)) { + case T_CLASS: + case T_ICLASS: + class_init_copy_check(clone, orig); + break; + case T_MODULE: + rb_module_check_initializable(clone); + break; + default: + break; + } + if (!OBJ_INIT_COPY(clone, orig)) return clone; + + /* cloned flag is refer at constant inline cache + * see vm_get_const_key_cref() in vm_insnhelper.c + */ + FL_SET(clone, RCLASS_CLONED); + FL_SET(orig , RCLASS_CLONED); + + if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { + RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig)); + rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); + } + RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(orig); + copy_tables(clone, orig); if (RCLASS_M_TBL(orig)) { struct clone_method_arg arg; arg.old_klass = orig; @@ -363,6 +446,75 @@ rb_mod_init_copy(VALUE clone, VALUE orig) rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg); } + if (RCLASS_ORIGIN(orig) == orig) { + RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig)); + } + else { + VALUE p = RCLASS_SUPER(orig); + VALUE orig_origin = RCLASS_ORIGIN(orig); + VALUE prev_clone_p = clone; + VALUE origin_stack = rb_ary_tmp_new(2); + VALUE origin[2]; + VALUE clone_p = 0; + long origin_len; + int add_subclass; + VALUE clone_origin; + + ensure_origin(clone); + clone_origin = RCLASS_ORIGIN(clone); + + while (p && p != orig_origin) { + if (BUILTIN_TYPE(p) != T_ICLASS) { + rb_bug("non iclass between module/class and origin"); + } + clone_p = class_alloc(RBASIC(p)->flags, RBASIC(p)->klass); + RCLASS_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_IV_TBL(clone_p) = RCLASS_IV_TBL(p); + RCLASS_ALLOCATOR(clone_p) = RCLASS_ALLOCATOR(p); + if (RB_TYPE_P(clone, T_CLASS)) { + RCLASS_SET_INCLUDER(clone_p, clone); + } + add_subclass = TRUE; + if (p != RCLASS_ORIGIN(p)) { + origin[0] = clone_p; + origin[1] = RCLASS_ORIGIN(p); + rb_ary_cat(origin_stack, origin, 2); + } + 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); + rb_ary_resize(origin_stack, origin_len); + add_subclass = FALSE; + } + if (add_subclass) { + rb_module_add_to_subclasses_list(RBASIC(p)->klass, clone_p); + } + p = RCLASS_SUPER(p); + } + + if (p == orig_origin) { + if (clone_p) { + RCLASS_SET_SUPER(clone_p, clone_origin); + RCLASS_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); + rb_id_table_foreach(RCLASS_M_TBL(orig_origin), clone_method_i, &arg); + } + } + else { + rb_bug("no origin for class that has origin"); + } + } + return clone; } @@ -372,26 +524,39 @@ rb_singleton_class_clone(VALUE obj) return rb_singleton_class_clone_and_attach(obj, Qundef); } +// Clone and return the singleton class of `obj` if it has been created and is attached to `obj`. VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) { const VALUE klass = RBASIC(obj)->klass; - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; + // Note that `rb_singleton_class()` can create situations where `klass` is + // 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) && rb_attr_get(klass, id_attached) == 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); if (BUILTIN_TYPE(obj) == T_CLASS) { + klass_of_clone_is_new = true; RBASIC_SET_CLASS(clone, clone); } else { - RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass)); + VALUE klass_metaclass_clone = rb_singleton_class_clone(klass); + // When `METACLASS_OF(klass) == klass_metaclass_clone`, it means the + // recursive call did not clone `METACLASS_OF(klass)`. + klass_of_clone_is_new = (METACLASS_OF(klass) != klass_metaclass_clone); + RBASIC_SET_CLASS(clone, klass_metaclass_clone); } RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass)); - RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator; + RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(klass); if (RCLASS_IV_TBL(klass)) { rb_iv_tbl_copy(clone, klass); } @@ -411,33 +576,23 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) arg.new_klass = clone; rb_id_table_foreach(RCLASS_M_TBL(klass), clone_method_i, &arg); } - rb_singleton_class_attached(RBASIC(clone)->klass, clone); + if (klass_of_clone_is_new) { + rb_singleton_class_attached(RBASIC(clone)->klass, clone); + } FL_SET(clone, FL_SINGLETON); return clone; } } -/*! - * Attach a object to a singleton class. - * @pre \a klass is the singleton class of \a obj. - */ void rb_singleton_class_attached(VALUE klass, VALUE obj) { if (FL_TEST(klass, FL_SINGLETON)) { - if (!RCLASS_IV_TBL(klass)) { - RCLASS_IV_TBL(klass) = st_init_numtable(); - } rb_class_ivar_set(klass, id_attached, obj); } } - - -#define METACLASS_OF(k) RBASIC(k)->klass -#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls) - /*! * whether k is a meta^(n)-class of Class class * @retval 1 if \a k is a meta^(n)-class of Class class (n >= 0) @@ -541,10 +696,62 @@ 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(id, obj); + rb_vm_add_root_module(obj); return obj; } +/*********************************************************************** + * + * Document-class: Refinement + * + * Refinement is a class of the +self+ (current context) inside +refine+ + * statement. It allows to import methods from other modules, see #import_methods. + */ + +#if 0 /* for RDoc */ +/* + * Document-method: Refinement#import_methods + * + * call-seq: + * import_methods(module, ...) -> self + * + * Imports methods from modules. Unlike Module#include, + * Refinement#import_methods copies methods and adds them into the refinement, + * so the refinement is activated in the imported methods. + * + * Note that due to method copying, only methods defined in Ruby code can be imported. + * + * module StrUtils + * def indent(level) + * ' ' * level + self + * end + * end + * + * module M + * refine String do + * import_methods StrUtils + * end + * end + * + * using M + * "foo".indent(3) + * #=> " foo" + * + * module M + * refine String do + * import_methods Enumerable + * # Can't import method which is not defined with Ruby code: Enumerable#drop + * end + * end + * + */ + +static VALUE +refinement_import_methods(int argc, VALUE *argv, VALUE refinement) +{ +} +# endif + void Init_class_hierarchy(void) { @@ -557,12 +764,21 @@ Init_class_hierarchy(void) rb_cModule = boot_defclass("Module", rb_cObject); rb_cClass = boot_defclass("Class", rb_cModule); + rb_cRefinement = boot_defclass("Refinement", rb_cModule); + +#if 0 /* for RDoc */ + // we pretend it to be public, otherwise RDoc will ignore it + rb_define_method(rb_cRefinement, "import_methods", refinement_import_methods, -1); +#endif rb_const_set(rb_cObject, rb_intern_const("BasicObject"), rb_cBasicObject); RBASIC_SET_CLASS(rb_cClass, rb_cClass); RBASIC_SET_CLASS(rb_cModule, rb_cClass); RBASIC_SET_CLASS(rb_cObject, rb_cClass); + RBASIC_SET_CLASS(rb_cRefinement, rb_cClass); RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass); + + ENSURE_EIGENCLASS(rb_cRefinement); } @@ -587,17 +803,6 @@ rb_make_metaclass(VALUE obj, VALUE unused) } } - -/*! - * Defines a new class. - * \param id ignored - * \param super A class from which the new class will derive. NULL means \c Object class. - * \return the created class - * \throw TypeError if super is not a \c Class object. - * - * \note the returned class will not be associated with \a id. - * You must explicitly set a class name if necessary. - */ VALUE rb_define_class_id(ID id, VALUE super) { @@ -628,23 +833,6 @@ rb_class_inherited(VALUE super, VALUE klass) return rb_funcall(super, inherited, 1, klass); } - - -/*! - * Defines a top-level class. - * \param name name of the class - * \param super a class from which the new class will derive. - * \return the created class - * \throw TypeError if the constant name \a name is already taken but - * the constant is not a \c Class. - * \throw TypeError if the class is already defined but the class can not - * be reopened because its superclass is not \a super. - * \throw ArgumentError if the \a super is NULL. - * \post top-level constant named \a name refers the returned class. - * - * \note if a class named \a name is already defined and its superclass is - * \a super, the function just returns the defined class. - */ VALUE rb_define_class(const char *name, VALUE super) { @@ -663,60 +851,26 @@ rb_define_class(const char *name, VALUE super) } /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(id, klass); + rb_vm_add_root_module(klass); return klass; } if (!super) { rb_raise(rb_eArgError, "no super class for `%s'", name); } klass = rb_define_class_id(id, super); - rb_vm_add_root_module(id, klass); + rb_vm_add_root_module(klass); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); return klass; } - -/*! - * Defines a class under the namespace of \a outer. - * \param outer a class which contains the new class. - * \param name name of the new class - * \param super a class from which the new class will derive. - * NULL means \c Object class. - * \return the created class - * \throw TypeError if the constant name \a name is already taken but - * the constant is not a \c Class. - * \throw TypeError if the class is already defined but the class can not - * be reopened because its superclass is not \a super. - * \post top-level constant named \a name refers the returned class. - * - * \note if a class named \a name is already defined and its superclass is - * \a super, the function just returns the defined class. - */ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { return rb_define_class_id_under(outer, rb_intern(name), super); } - -/*! - * Defines a class under the namespace of \a outer. - * \param outer a class which contains the new class. - * \param id name of the new class - * \param super a class from which the new class will derive. - * NULL means \c Object class. - * \return the created class - * \throw TypeError if the constant name \a name is already taken but - * the constant is not a \c Class. - * \throw TypeError if the class is already defined but the class can not - * be reopened because its superclass is not \a super. - * \post top-level constant named \a name refers the returned class. - * - * \note if a class named \a name is already defined and its superclass is - * \a super, the function just returns the defined class. - */ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super) { @@ -736,7 +890,7 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) outer, rb_id2str(id), RCLASS_SUPER(klass), super); } /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(id, klass); + rb_vm_add_root_module(klass); return klass; } @@ -748,20 +902,42 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE 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(id, klass); - rb_gc_register_mark_object(klass); + rb_vm_add_root_module(klass); return klass; } VALUE -rb_module_new(void) +rb_module_s_alloc(VALUE klass) { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); + VALUE mod = class_alloc(T_MODULE, klass); + RCLASS_M_TBL_INIT(mod); + FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); + RB_OBJ_WRITE(mod, &RCLASS(mod)->super, 0); + return mod; +} + +static inline VALUE +module_new(VALUE klass) +{ + VALUE mdl = class_alloc(T_MODULE, klass); RCLASS_M_TBL_INIT(mdl); return (VALUE)mdl; } +VALUE +rb_module_new(void) +{ + return module_new(rb_cModule); +} + +VALUE +rb_refinement_new(void) +{ + return module_new(rb_cRefinement); +} + +// Kept for compatibility. Use rb_module_new() instead. VALUE rb_define_module_id(ID id) { @@ -782,12 +958,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(id, module); + rb_vm_add_root_module(module); return module; } - module = rb_define_module_id(id); - rb_vm_add_root_module(id, module); - rb_gc_register_mark_object(module); + module = rb_module_new(); + rb_vm_add_root_module(module); rb_const_set(rb_cObject, id, module); return module; @@ -811,9 +986,11 @@ rb_define_module_id_under(VALUE outer, ID id) " (%"PRIsVALUE")", 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); return module; } - module = rb_define_module_id(id); + 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); @@ -826,13 +1003,13 @@ rb_include_class_new(VALUE module, VALUE super) { VALUE klass = class_alloc(T_ICLASS, rb_cClass); - RCLASS_M_TBL(OBJ_WB_UNPROTECT(klass)) = - RCLASS_M_TBL(OBJ_WB_UNPROTECT(module)); /* TODO: unprotected? */ + RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); - RCLASS_SET_ORIGIN(klass, module == RCLASS_ORIGIN(module) ? klass : RCLASS_ORIGIN(module)); + RCLASS_SET_ORIGIN(klass, klass); if (BUILTIN_TYPE(module) == T_ICLASS) { module = RBASIC(module)->klass; } + RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS)); if (!RCLASS_IV_TBL(module)) { RCLASS_IV_TBL(module) = st_init_numtable(); } @@ -840,15 +1017,11 @@ rb_include_class_new(VALUE module, VALUE super) RCLASS_CONST_TBL(module) = rb_id_table_create(0); } RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); + RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module); RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); RCLASS_SET_SUPER(klass, super); - if (RB_TYPE_P(module, T_ICLASS)) { - RBASIC_SET_CLASS(klass, RBASIC(module)->klass); - } - else { - RBASIC_SET_CLASS(klass, module); - } + RBASIC_SET_CLASS(klass, module); return (VALUE)klass; } @@ -860,6 +1033,7 @@ ensure_includable(VALUE klass, VALUE module) { rb_class_modify_check(klass); Check_Type(module, T_MODULE); + rb_module_set_initialized(module); if (!NIL_P(rb_refinement_module_get_refined_class(module))) { rb_raise(rb_eArgError, "refinement module is not allowed"); } @@ -875,6 +1049,31 @@ rb_include_module(VALUE klass, VALUE module) changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module, TRUE); if (changed < 0) 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 && !iclass->klass) { + iclass = iclass->next; + } + + int do_include = 1; + while (iclass) { + VALUE check_class = iclass->klass; + while (check_class) { + if (RB_TYPE_P(check_class, T_ICLASS) && + (RBASIC(check_class)->klass == module)) { + do_include = 0; + } + check_class = RCLASS_SUPER(check_class); + } + + if (do_include) { + include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE); + } + iclass = iclass->next; + } + } } static enum rb_id_table_iterator_result @@ -884,93 +1083,160 @@ add_refined_method_entry_i(ID key, VALUE value, void *data) return ID_TABLE_CONTINUE; } -static void ensure_origin(VALUE klass); +static enum rb_id_table_iterator_result +clear_module_cache_i(ID id, VALUE val, void *data) +{ + VALUE klass = (VALUE)data; + rb_clear_method_cache(klass, id); + return ID_TABLE_CONTINUE; +} -static int -include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) +static bool +module_in_super_chain(const VALUE klass, VALUE module) { - VALUE p, iclass; - int method_changed = 0, constant_changed = 0; struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass)); - - if (FL_TEST(module, RCLASS_REFINED_BY_ANY)) { - ensure_origin(module); + if (klass_m_tbl) { + while (module) { + if (klass_m_tbl == RCLASS_M_TBL(module)) + return true; + module = RCLASS_SUPER(module); + } } + return false; +} + +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, constant_changed = 0, add_subclass; + long origin_len; + VALUE klass_origin = RCLASS_ORIGIN(klass); + VALUE original_klass = klass; + + if (check_cyclic && module_in_super_chain(klass, module)) + return -1; while (module) { + int c_seen = FALSE; int superclass_seen = FALSE; struct rb_id_table *tbl; - if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module)) - return -1; - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - int type = BUILTIN_TYPE(p); - if (type == T_ICLASS) { - if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } - goto skip; - } - } - else if (type == T_CLASS) { - if (!search_super) break; - superclass_seen = TRUE; - } - } - iclass = rb_include_class_new(module, RCLASS_SUPER(c)); + if (klass == c) { + c_seen = TRUE; + } + if (klass_origin != c || search_super) { + /* ignore if the module included already in superclasses for include, + * ignore if the module included before origin class for prepend + */ + for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { + int type = BUILTIN_TYPE(p); + if (klass_origin == p && !search_super) + break; + if (c == p) + c_seen = TRUE; + if (type == T_ICLASS) { + if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { + if (!superclass_seen && c_seen) { + c = p; /* move insertion point */ + } + goto skip; + } + } + else if (type == T_CLASS) { + superclass_seen = TRUE; + } + } + } + + VALUE super_class = RCLASS_SUPER(c); + + // invalidate inline method cache + RB_DEBUG_COUNTER_INC(cvar_include_invalidate); + ruby_vm_global_cvar_state++; + tbl = RCLASS_M_TBL(module); + if (tbl && rb_id_table_size(tbl)) { + if (search_super) { // include + if (super_class && !RB_TYPE_P(super_class, T_MODULE)) { + rb_id_table_foreach(tbl, clear_module_cache_i, (void *)super_class); + } + } + else { // prepend + if (!RB_TYPE_P(original_klass, T_MODULE)) { + rb_id_table_foreach(tbl, clear_module_cache_i, (void *)original_klass); + } + } + method_changed = 1; + } + + // setup T_ICLASS for the include/prepend module + iclass = rb_include_class_new(module, super_class); c = RCLASS_SET_SUPER(c, iclass); RCLASS_SET_INCLUDER(iclass, klass); + add_subclass = TRUE; + if (module != RCLASS_ORIGIN(module)) { + if (!origin_stack) origin_stack = rb_ary_tmp_new(2); + VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)}; + rb_ary_cat(origin_stack, origin, 2); + } + 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); + rb_ary_resize(origin_stack, origin_len); + add_subclass = FALSE; + } - { + if (add_subclass) { VALUE m = module; - if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass; - rb_module_add_to_subclasses_list(m, iclass); + if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass; + rb_module_add_to_subclasses_list(m, iclass); } if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); - rb_id_table_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (void *)refined_class); + rb_id_table_foreach(RCLASS_M_TBL(module), add_refined_method_entry_i, (void *)refined_class); FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT); } - tbl = RMODULE_M_TBL(module); - if (tbl && rb_id_table_size(tbl)) method_changed = 1; - - tbl = RMODULE_CONST_TBL(module); + tbl = RCLASS_CONST_TBL(module); if (tbl && rb_id_table_size(tbl)) constant_changed = 1; skip: module = RCLASS_SUPER(module); } - if (method_changed) rb_clear_method_cache_by_class(klass); if (constant_changed) rb_clear_constant_cache(); return method_changed; } +static int +include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) +{ + return do_include_modules_at(klass, c, module, search_super, true); +} + static enum rb_id_table_iterator_result move_refined_method(ID key, VALUE value, void *data) { - rb_method_entry_t *me = (rb_method_entry_t *) value; - VALUE klass = (VALUE)data; - struct rb_id_table *tbl = RCLASS_M_TBL(klass); + rb_method_entry_t *me = (rb_method_entry_t *)value; if (me->def->type == VM_METHOD_TYPE_REFINED) { - if (me->def->body.refined.orig_me) { + VALUE klass = (VALUE)data; + struct rb_id_table *tbl = RCLASS_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; RB_OBJ_WRITE(me, &me->def->body.refined.orig_me, NULL); new_me = rb_method_entry_clone(me); - rb_id_table_insert(tbl, key, (VALUE)new_me); - RB_OBJ_WRITTEN(klass, Qundef, new_me); + rb_method_table_insert(klass, tbl, key, new_me); rb_method_entry_copy(me, orig_me); return ID_TABLE_CONTINUE; } else { - rb_id_table_insert(tbl, key, (VALUE)me); + rb_method_table_insert(klass, tbl, key, me); return ID_TABLE_DELETE; } } @@ -979,52 +1245,103 @@ move_refined_method(ID key, VALUE value, void *data) } } -static void +static enum rb_id_table_iterator_result +cache_clear_refined_method(ID key, VALUE value, void *data) +{ + rb_method_entry_t *me = (rb_method_entry_t *) value; + + if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) { + VALUE klass = (VALUE)data; + rb_clear_method_cache(klass, me->called_id); + } + // Refined method entries without an orig_me is going to stay in the method + // table of klass, like before the move, so no need to clear the cache. + + return ID_TABLE_CONTINUE; +} + +static bool ensure_origin(VALUE klass) { VALUE origin = RCLASS_ORIGIN(klass); if (origin == klass) { origin = class_alloc(T_ICLASS, klass); - OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */ 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); + 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; } + return false; } void rb_prepend_module(VALUE klass, VALUE module) { - int changed = 0; + int changed; + bool klass_had_no_origin; ensure_includable(klass, module); - ensure_origin(klass); - changed = include_modules_at(klass, klass, module, FALSE); - if (changed < 0) - rb_raise(rb_eArgError, "cyclic prepend detected"); + if (module_in_super_chain(klass, module)) + rb_raise(rb_eArgError, "cyclic prepend detected"); + + klass_had_no_origin = ensure_origin(klass); + changed = do_include_modules_at(klass, klass, module, FALSE, false); + RUBY_ASSERT(changed >= 0); // already checked for cyclic prepend above if (changed) { 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 && iclass->next) { + RUBY_ASSERT(!iclass->klass); + iclass = iclass->next; + } + + 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); + while (iclass) { + if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) { + // backfill an origin iclass to handle refinements and future prepends + rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass); + RCLASS_M_TBL(iclass->klass) = klass_m_tbl; + VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass)); + RCLASS_SET_SUPER(iclass->klass, origin); + RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass)); + RCLASS_SET_ORIGIN(iclass->klass, origin); + RICLASS_SET_ORIGIN_SHARED_MTBL(origin); + } + include_modules_at(iclass->klass, iclass->klass, module, FALSE); + iclass = iclass->next; + } + } } /* * call-seq: * mod.included_modules -> array * - * Returns the list of modules included in mod. + * Returns the list of modules included or prepended in mod + * or one of mod's ancestors. + * + * module Sub + * end * * module Mixin + * prepend Sub * end * * module Outer * include Mixin * end * - * Mixin.included_modules #=> [] - * Outer.included_modules #=> [Mixin] + * Mixin.included_modules #=> [Sub] + * Outer.included_modules #=> [Sub, Mixin] */ VALUE @@ -1035,7 +1352,7 @@ rb_mod_included_modules(VALUE mod) VALUE origin = RCLASS_ORIGIN(mod); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { - if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) { + if (p != origin && RCLASS_ORIGIN(p) == p && BUILTIN_TYPE(p) == T_ICLASS) { VALUE m = RBASIC(p)->klass; if (RB_TYPE_P(m, T_MODULE)) rb_ary_push(ary, m); @@ -1048,8 +1365,8 @@ rb_mod_included_modules(VALUE mod) * call-seq: * mod.include?(module) -> true or false * - * Returns true if module is included in - * mod or one of mod's ancestors. + * Returns true if module is included + * or prepended in mod or one of mod's ancestors. * * module A * end @@ -1070,7 +1387,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) { + if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) { if (RBASIC(p)->klass == mod2) return Qtrue; } } @@ -1099,8 +1416,13 @@ VALUE rb_mod_ancestors(VALUE mod) { VALUE p, ary = rb_ary_new(); + VALUE refined_class = Qnil; + if (FL_TEST(mod, RMODULE_IS_REFINEMENT)) { + refined_class = rb_refinement_module_get_refined_class(mod); + } for (p = mod; p; p = RCLASS_SUPER(p)) { + if (p == refined_class) break; if (p != RCLASS_ORIGIN(p)) continue; if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); @@ -1112,6 +1434,83 @@ rb_mod_ancestors(VALUE mod) return ary; } +struct subclass_traverse_data +{ + VALUE buffer; + long count; + long maxcount; + bool immediate_only; +}; + +static void +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 (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); + } + data->count++; + if (!data->immediate_only) { + rb_class_foreach_subclass(klass, class_descendants_recursive, v); + } + } + else { + rb_class_foreach_subclass(klass, class_descendants_recursive, v); + } +} + +static VALUE +class_descendants(VALUE klass, bool immediate_only) +{ + struct subclass_traverse_data data = { Qfalse, 0, -1, immediate_only }; + + // estimate the count of subclasses + rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data); + + // the following allocation may cause GC which may change the number of subclasses + data.buffer = rb_ary_new_capa(data.count); + data.maxcount = data.count; + data.count = 0; + + size_t gc_count = rb_gc_count(); + + // enumerate subclasses + rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data); + + if (gc_count != rb_gc_count()) { + rb_bug("GC must not occur during the subclass iteration of Class#descendants"); + } + + return data.buffer; +} + +/* + * call-seq: + * subclasses -> array + * + * Returns an array of classes where the receiver is the + * direct superclass of the class, excluding singleton classes. + * The order of the returned array is not defined. + * + * class A; end + * class B < A; end + * class C < B; end + * class D < A; end + * + * A.subclasses #=> [D, B] + * B.subclasses #=> [C] + * C.subclasses #=> [] + */ + +VALUE +rb_class_subclasses(VALUE klass) +{ + return class_descendants(klass, true); +} + static void ins_methods_push(st_data_t name, st_data_t ary) { @@ -1133,30 +1532,30 @@ ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) } static int -ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) +ins_methods_type_i(st_data_t name, st_data_t type, st_data_t ary, rb_method_visibility_t visi) { - if ((rb_method_visibility_t)type == METHOD_VISI_PROTECTED) { + if ((rb_method_visibility_t)type == visi) { ins_methods_push(name, ary); } return ST_CONTINUE; } +static int +ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) +{ + return ins_methods_type_i(name, type, ary, METHOD_VISI_PROTECTED); +} + static int ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) { - if ((rb_method_visibility_t)type == METHOD_VISI_PRIVATE) { - ins_methods_push(name, ary); - } - return ST_CONTINUE; + return ins_methods_type_i(name, type, ary, METHOD_VISI_PRIVATE); } static int ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) { - if ((rb_method_visibility_t)type == METHOD_VISI_PUBLIC) { - ins_methods_push(name, ary); - } - return ST_CONTINUE; + return ins_methods_type_i(name, type, ary, METHOD_VISI_PUBLIC); } struct method_entry_arg { @@ -1183,6 +1582,7 @@ method_entry_i(ID key, VALUE value, void *data) } else { type = METHOD_ENTRY_VISI(me); + RUBY_ASSERT(type != METHOD_VISI_UNDEF); } st_add_direct(arg->list, key, (st_data_t)type); } @@ -1482,56 +1882,7 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj) * \} */ /*! - * \defgroup defmethod Defining methods - * There are some APIs to define a method from C. - * These API takes a C function as a method body. - * - * \par Method body functions - * Method body functions must return a VALUE and - * can be one of the following form: - *
- *
Fixed number of parameters
- *
- * This form is a normal C function, excepting it takes - * a receiver object as the first argument. - * - * \code - * static VALUE my_method(VALUE self, VALUE x, VALUE y); - * \endcode - *
- *
argc and argv style
- *
- * This form takes three parameters: \a argc, \a argv and \a self. - * \a self is the receiver. \a argc is the number of arguments. - * \a argv is a pointer to an array of the arguments. - * - * \code - * static VALUE my_method(int argc, VALUE *argv, VALUE self); - * \endcode - *
- *
Ruby array style
- *
- * This form takes two parameters: self and args. - * \a self is the receiver. \a args is an Array object which - * contains the arguments. - * - * \code - * static VALUE my_method(VALUE self, VALUE args); - * \endcode - *
- * - * \par Number of parameters - * Method defining APIs takes the number of parameters which the - * method will takes. This number is called \a argc. - * \a argc can be: - *
- *
zero or positive number
- *
This means the method body function takes a fixed number of parameters
- *
-1
- *
This means the method body function is "argc and argv" style.
- *
-2
- *
This means the method body function is "self and args" style.
- *
+ * \addtogroup defmethod * \{ */ @@ -1602,19 +1953,15 @@ rb_undef_methods_from(VALUE klass, VALUE super) * \{ */ -#define SPECIAL_SINGLETON(x,c) do {\ - if (obj == (x)) {\ - return (c);\ - }\ -} while (0) - static inline VALUE special_singleton_class_of(VALUE obj) { - SPECIAL_SINGLETON(Qnil, rb_cNilClass); - SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); - SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); - return Qnil; + switch (obj) { + case Qnil: return rb_cNilClass; + case Qfalse: return rb_cFalseClass; + case Qtrue: return rb_cTrueClass; + default: return Qnil; + } } VALUE @@ -1637,29 +1984,30 @@ singleton_class_of(VALUE obj) { VALUE klass; - if (FIXNUM_P(obj) || FLONUM_P(obj) || STATIC_SYM_P(obj)) { - no_singleton: + switch (TYPE(obj)) { + case T_FIXNUM: + case T_BIGNUM: + case T_FLOAT: + case T_SYMBOL: rb_raise(rb_eTypeError, "can't define singleton"); - } - if (SPECIAL_CONST_P(obj)) { + + case T_FALSE: + case T_TRUE: + case T_NIL: klass = special_singleton_class_of(obj); if (NIL_P(klass)) rb_bug("unknown immediate %p", (void *)obj); return klass; - } - else { - switch (BUILTIN_TYPE(obj)) { - case T_FLOAT: case T_BIGNUM: case T_SYMBOL: - goto no_singleton; - case T_STRING: - if (FL_TEST_RAW(obj, RSTRING_FSTR)) goto no_singleton; - break; - } + + case T_STRING: + if (FL_TEST_RAW(obj, RSTRING_FSTR)) { + rb_raise(rb_eTypeError, "can't define singleton"); + } } klass = RBASIC(obj)->klass; if (!(FL_TEST(klass, FL_SINGLETON) && - rb_ivar_get(klass, id_attached) == obj)) { + rb_attr_get(klass, id_attached) == obj)) { rb_serial_t serial = RCLASS_SERIAL(klass); klass = rb_make_metaclass(obj, klass); RCLASS_SERIAL(klass) = serial; @@ -1700,27 +2048,10 @@ rb_singleton_class_get(VALUE obj) } klass = RBASIC(obj)->klass; if (!FL_TEST(klass, FL_SINGLETON)) return Qnil; - if (rb_ivar_get(klass, id_attached) != obj) return Qnil; + if (rb_attr_get(klass, id_attached) != obj) return Qnil; return klass; } -/*! - * Returns the singleton class of \a obj. Creates it if necessary. - * - * \param obj an arbitrary object. - * \throw TypeError if \a obj is a Integer or a Symbol. - * \return the singleton class. - * - * \post \a obj has its own singleton class. - * \post if \a obj is a class, - * the returned singleton class also has its own - * singleton class in order to keep consistency of the - * inheritance structure of metaclasses. - * \note a new singleton class will be created - * if \a obj does not have it. - * \note the singleton classes for nil, true and false are: - * NilClass, TrueClass and FalseClass. - */ VALUE rb_singleton_class(VALUE obj) { @@ -1744,13 +2075,6 @@ rb_singleton_class(VALUE obj) #ifdef rb_define_singleton_method #undef rb_define_singleton_method #endif -/*! - * Defines a singleton method for \a obj. - * \param obj an arbitrary object - * \param name name of the singleton method - * \param func the method body - * \param argc the number of parameters, or -1 or -2. see \ref defmethod. - */ void rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc) { @@ -1760,13 +2084,6 @@ rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), #ifdef rb_define_module_function #undef rb_define_module_function #endif -/*! - * Defines a module function for \a module. - * \param module an module or a class. - * \param name name of the function - * \param func the method body - * \param argc the number of parameters, or -1 or -2. see \ref defmethod. - */ void rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc) { @@ -1777,38 +2094,18 @@ rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS) #ifdef rb_define_global_function #undef rb_define_global_function #endif -/*! - * Defines a global function - * \param name name of the function - * \param func the method body - * \param argc the number of parameters, or -1 or -2. see \ref defmethod. - */ void rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc) { rb_define_module_function(rb_mKernel, name, func, argc); } - -/*! - * Defines an alias of a method. - * \param klass the class which the original method belongs to - * \param name1 a new name for the method - * \param name2 the original name of the method - */ void rb_define_alias(VALUE klass, const char *name1, const char *name2) { rb_alias(klass, rb_intern(name1), rb_intern(name2)); } -/*! - * Defines (a) public accessor method(s) for an attribute. - * \param klass the class which the attribute will belongs to - * \param name name of the attribute - * \param read a getter method for the attribute will be defined if \a read is non-zero. - * \param write a setter method for the attribute will be defined if \a write is non-zero. - */ void rb_define_attr(VALUE klass, const char *name, int read, int write) { @@ -1939,52 +2236,22 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V } struct rb_scan_args_t { - int argc; - const VALUE *argv; - va_list vargs; - int f_var; - int f_hash; - int f_block; + int kw_flag; int n_lead; int n_opt; int n_trail; - int n_mand; - int argi; - int last_idx; - VALUE hash; - VALUE last_hash; - VALUE *tmp_buffer; + bool f_var; + bool f_hash; + bool f_block; }; static void -rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, struct rb_scan_args_t *arg) +rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg) { const char *p = fmt; - VALUE *tmp_buffer = arg->tmp_buffer; - int keyword_given = 0; - int empty_keyword_given = 0; - int last_hash_keyword = 0; memset(arg, 0, sizeof(*arg)); - arg->last_idx = -1; - arg->hash = Qnil; - - switch (kw_flag) { - case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: - if (!(keyword_given = rb_keyword_given_p())) { - empty_keyword_given = rb_empty_keyword_given_p(); - } - break; - case RB_SCAN_ARGS_KEYWORDS: - keyword_given = 1; - break; - case RB_SCAN_ARGS_EMPTY_KEYWORDS: - empty_keyword_given = 1; - break; - case RB_SCAN_ARGS_LAST_HASH_KEYWORDS: - last_hash_keyword = 1; - break; - } + arg->kw_flag = kw_flag; if (ISDIGIT(*p)) { arg->n_lead = *p - '0'; @@ -2013,97 +2280,47 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st if (*p != '\0') { rb_fatal("bad scan arg format: %s", fmt); } - arg->n_mand = arg->n_lead + arg->n_trail; +} - /* capture an option hash - phase 1: pop */ - /* Ignore final positional hash if empty keywords given */ - if (argc > 0 && !(arg->f_hash && empty_keyword_given)) { +static int +rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *const argv, va_list vargs) +{ + int i, argi = 0; + VALUE *var, hash = Qnil; +#define rb_scan_args_next_param() va_arg(vargs, VALUE *) + const int kw_flag = arg->kw_flag; + const int n_lead = arg->n_lead; + const int n_opt = arg->n_opt; + const int n_trail = arg->n_trail; + const int n_mand = n_lead + n_trail; + const bool f_var = arg->f_var; + const bool f_hash = arg->f_hash; + const bool f_block = arg->f_block; + + /* capture an option hash - phase 1: pop from the argv */ + if (f_hash && argc > 0) { VALUE last = argv[argc - 1]; - - if (arg->f_hash && arg->n_mand < argc) { - if (keyword_given) { - if (!RB_TYPE_P(last, T_HASH)) { - rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash"); - } - else { - arg->hash = last; - } - } - else if (NIL_P(last)) { - /* For backwards compatibility, nil is taken as an empty - option hash only if it is not ambiguous; i.e. '*' is - not specified and arguments are given more than sufficient. - This will be removed in Ruby 3. */ - if (!arg->f_var && arg->n_mand + arg->n_opt < argc) { - rb_warn("The last argument is nil, treating as empty keywords"); - argc--; - } - } - else { - arg->hash = rb_check_hash_type(last); - } - - /* Ruby 3: Remove if branch, as it will not attempt to split hashes */ - if (!NIL_P(arg->hash)) { - VALUE opts = rb_extract_keywords(&arg->hash); - - if (!(arg->last_hash = arg->hash)) { - if (!keyword_given && !last_hash_keyword) { - /* Warn if treating positional as keyword, as in Ruby 3, - this will be an error */ - rb_warn("Using the last argument as keyword parameters is deprecated"); - } - argc--; - } - else { - /* Warn if splitting either positional hash to keywords or keywords - to positional hash, as in Ruby 3, no splitting will be done */ - rb_warn("The last argument is split into positional and keyword parameters"); - arg->last_idx = argc - 1; - } - arg->hash = opts ? opts : Qnil; - } + if (rb_scan_args_keyword_p(kw_flag, last)) { + hash = rb_hash_dup(last); + argc--; } - else if (arg->f_hash && keyword_given && arg->n_mand == argc) { - /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */ - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - } - } - if (arg->f_hash && arg->n_mand == argc+1 && empty_keyword_given) { - VALUE *ptr = rb_alloc_tmp_buffer2(tmp_buffer, argc+1, sizeof(VALUE)); - memcpy(ptr, argv, sizeof(VALUE)*argc); - ptr[argc] = rb_hash_new(); - argc++; - *(&argv) = ptr; - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); } - arg->argc = argc; - arg->argv = argv; -} - -static int -rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) -{ - int argi = 0; - int i; - VALUE *var; - - if (arg->argc < arg->n_mand) { - return 1; + if (argc < n_mand) { + goto argc_error; } /* capture leading mandatory arguments */ - for (i = arg->n_lead; i-- > 0; ) { - var = va_arg(vargs, VALUE *); - if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi]; + for (i = 0; i < n_lead; i++) { + var = rb_scan_args_next_param(); + if (var) *var = argv[argi]; argi++; } /* capture optional arguments */ - for (i = arg->n_opt; i-- > 0; ) { - var = va_arg(vargs, VALUE *); - if (argi < arg->argc - arg->n_trail) { - if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi]; + for (i = 0; i < n_opt; i++) { + var = rb_scan_args_next_param(); + if (argi < argc - n_trail) { + if (var) *var = argv[argi]; argi++; } else { @@ -2111,16 +2328,12 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) } } /* capture variable length arguments */ - if (arg->f_var) { - int n_var = arg->argc - argi - arg->n_trail; + if (f_var) { + int n_var = argc - argi - n_trail; - var = va_arg(vargs, VALUE *); + var = rb_scan_args_next_param(); if (0 < n_var) { - if (var) { - int f_last = (arg->last_idx + 1 == arg->argc - arg->n_trail); - *var = rb_ary_new4(n_var - f_last, &arg->argv[argi]); - if (f_last) rb_ary_push(*var, arg->last_hash); - } + if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]); argi += n_var; } else { @@ -2128,19 +2341,19 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) } } /* capture trailing mandatory arguments */ - for (i = arg->n_trail; i-- > 0; ) { - var = va_arg(vargs, VALUE *); - if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi]; + for (i = 0; i < n_trail; i++) { + var = rb_scan_args_next_param(); + if (var) *var = argv[argi]; argi++; } /* capture an option hash - phase 2: assignment */ - if (arg->f_hash) { - var = va_arg(vargs, VALUE *); - if (var) *var = arg->hash; + if (f_hash) { + var = rb_scan_args_next_param(); + if (var) *var = hash; } /* capture iterator block */ - if (arg->f_block) { - var = va_arg(vargs, VALUE *); + if (f_block) { + var = rb_scan_args_next_param(); if (rb_block_given_p()) { *var = rb_block_proc(); } @@ -2149,58 +2362,57 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs) } } - if (argi < arg->argc) return 1; + if (argi == argc) { + return argc; + } - return 0; + argc_error: + return -(argc + 1); +#undef rb_scan_args_next_param +} + +static int +rb_scan_args_result(const struct rb_scan_args_t *const arg, int argc) +{ + const int n_lead = arg->n_lead; + const int n_opt = arg->n_opt; + const int n_trail = arg->n_trail; + const int n_mand = n_lead + n_trail; + const bool f_var = arg->f_var; + + if (argc >= 0) { + return argc; + } + + argc = -argc - 1; + rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); + UNREACHABLE_RETURN(-1); } #undef rb_scan_args int rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...) { - int error; va_list vargs; - VALUE tmp_buffer = 0; struct rb_scan_args_t arg; - arg.tmp_buffer = &tmp_buffer; - rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, fmt, &arg); + rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, fmt, &arg); va_start(vargs,fmt); - error = rb_scan_args_assign(&arg, vargs); + argc = rb_scan_args_assign(&arg, argc, argv, vargs); va_end(vargs); - if (tmp_buffer) { - rb_free_tmp_buffer(&tmp_buffer); - } - if (error) { - rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt); - } - return arg.argc; + return rb_scan_args_result(&arg, argc); } +#undef rb_scan_args_kw int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...) { - int error; va_list vargs; - VALUE tmp_buffer = 0; struct rb_scan_args_t arg; - arg.tmp_buffer = &tmp_buffer; - rb_scan_args_parse(kw_flag, argc, argv, fmt, &arg); + rb_scan_args_parse(kw_flag, fmt, &arg); va_start(vargs,fmt); - error = rb_scan_args_assign(&arg, vargs); + argc = rb_scan_args_assign(&arg, argc, argv, vargs); va_end(vargs); - if (tmp_buffer) { - rb_free_tmp_buffer(&tmp_buffer); - } - if (error) { - rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt); - } - return arg.argc; -} - -int -rb_class_has_methods(VALUE c) -{ - return rb_id_table_size(RCLASS_M_TBL(c)) == 0 ? FALSE : TRUE; + return rb_scan_args_result(&arg, argc); } /*! diff --git a/ruby/common.mk b/ruby/common.mk index 8c1f865ea..e7a63fea5 100644 --- a/ruby/common.mk +++ b/ruby/common.mk @@ -8,6 +8,7 @@ dll: $(LIBRUBY_SO) # V=0 quiet, V=1 verbose. other values don't work. V = 0 +V0 = $(V:0=) Q1 = $(V:1=) Q = $(Q1:0=@) ECHO0 = $(ECHO1:0=echo) @@ -17,8 +18,8 @@ mflags = $(MFLAGS) gnumake_recursive = enable_shared = $(ENABLE_SHARED:no=) -UNICODE_VERSION = 12.1.0 -UNICODE_EMOJI_VERSION = 12.1 +UNICODE_VERSION = 13.0.0 +UNICODE_EMOJI_VERSION = 13.1 UNICODE_BETA = NO ### set the following environment variable or uncomment the line if @@ -38,7 +39,7 @@ RUBYLIB = $(PATH_SEPARATOR) RUBYOPT = - RUN_OPTS = --disable-gems -GITPULLOPTIONS = --rebase +# GITPULLOPTIONS = --no-tags INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(UNICODE_HDR_DIR) @@ -47,7 +48,7 @@ GEM_PATH = GEM_VENDOR = BENCHMARK_DRIVER_GIT_URL = https://github.com/benchmark-driver/benchmark-driver -BENCHMARK_DRIVER_GIT_REF = v0.15.6 +BENCHMARK_DRIVER_GIT_REF = v0.15.17 SIMPLECOV_GIT_URL = https://github.com/colszowka/simplecov.git SIMPLECOV_GIT_REF = v0.17.0 SIMPLECOV_HTML_GIT_URL = https://github.com/colszowka/simplecov-html.git @@ -81,29 +82,7 @@ ENC_MK = enc.mk MAKE_ENC = -f $(ENC_MK) V="$(V)" UNICODE_HDR_DIR="$(UNICODE_HDR_DIR)" \ RUBY="$(MINIRUBY)" MINIRUBY="$(MINIRUBY)" $(mflags) -COMMONOBJS = squash_cache.$(OBJEXT) \ - squash_decompress.$(OBJEXT) \ - squash_dir.$(OBJEXT) \ - squash_dirent.$(OBJEXT) \ - squash_extract.$(OBJEXT) \ - squash_fd.$(OBJEXT) \ - squash_file.$(OBJEXT) \ - squash_fs.$(OBJEXT) \ - squash_hash.$(OBJEXT) \ - squash_mutex.$(OBJEXT) \ - squash_nonstd-makedev.$(OBJEXT) \ - squash_nonstd-stat.$(OBJEXT) \ - squash_private.$(OBJEXT) \ - squash_readlink.$(OBJEXT) \ - squash_scandir.$(OBJEXT) \ - squash_stack.$(OBJEXT) \ - squash_stat.$(OBJEXT) \ - squash_table.$(OBJEXT) \ - squash_traverse.$(OBJEXT) \ - squash_util.$(OBJEXT) \ - enclose_io_unix.$(OBJEXT) \ - enclose_io_win32.$(OBJEXT) \ - array.$(OBJEXT) \ +COMMONOBJS = array.$(OBJEXT) \ ast.$(OBJEXT) \ bignum.$(OBJEXT) \ class.$(OBJEXT) \ @@ -125,10 +104,12 @@ COMMONOBJS = squash_cache.$(OBJEXT) \ hash.$(OBJEXT) \ inits.$(OBJEXT) \ io.$(OBJEXT) \ + io_buffer.$(OBJEXT) \ iseq.$(OBJEXT) \ load.$(OBJEXT) \ marshal.$(OBJEXT) \ math.$(OBJEXT) \ + memory_view.$(OBJEXT) \ mjit.$(OBJEXT) \ mjit_compile.$(OBJEXT) \ node.$(OBJEXT) \ @@ -138,6 +119,7 @@ COMMONOBJS = squash_cache.$(OBJEXT) \ parse.$(OBJEXT) \ proc.$(OBJEXT) \ process.$(OBJEXT) \ + ractor.$(OBJEXT) \ random.$(OBJEXT) \ range.$(OBJEXT) \ rational.$(OBJEXT) \ @@ -149,7 +131,7 @@ COMMONOBJS = squash_cache.$(OBJEXT) \ regparse.$(OBJEXT) \ regsyntax.$(OBJEXT) \ ruby.$(OBJEXT) \ - safe.$(OBJEXT) \ + scheduler.$(OBJEXT) \ signal.$(OBJEXT) \ sprintf.$(OBJEXT) \ st.$(OBJEXT) \ @@ -167,7 +149,9 @@ COMMONOBJS = squash_cache.$(OBJEXT) \ vm.$(OBJEXT) \ vm_backtrace.$(OBJEXT) \ vm_dump.$(OBJEXT) \ + vm_sync.$(OBJEXT) \ vm_trace.$(OBJEXT) \ + yjit.$(OBJEXT) \ $(COROUTINE_OBJ) \ $(DTRACE_OBJ) \ $(BUILTIN_ENCOBJS) \ @@ -182,7 +166,7 @@ EXPORTOBJS = $(DLNOBJ) \ OBJS = $(EXPORTOBJS) builtin.$(OBJEXT) ALLOBJS = $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(INITOBJS) -GOLFOBJS = goruby.$(OBJEXT) golf_prelude.$(OBJEXT) +GOLFOBJS = goruby.$(OBJEXT) DEFAULT_PRELUDES = $(GEM_PRELUDE) PRELUDE_SCRIPTS = $(DEFAULT_PRELUDES) @@ -192,32 +176,35 @@ GOLFPRELUDES = {$(srcdir)}golf_prelude.c SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \ --extout="$(EXTOUT)" \ + --ext-build-dir="./ext" \ --mflags="$(MFLAGS)" \ --make-flags="$(MAKEFLAGS)" EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) \ --make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" \ --gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \ -- -INSTRUBY = $(SUDO) $(RUNRUBY) -r./$(arch)-fake $(srcdir)/tool/rbinstall.rb +INSTRUBY = $(SUDO) $(INSTRUBY_ENV) $(RUNRUBY) -r./$(arch)-fake $(tooldir)/rbinstall.rb INSTRUBY_ARGS = $(SCRIPT_ARGS) \ --data-mode=$(INSTALL_DATA_MODE) \ --prog-mode=$(INSTALL_PROG_MODE) \ --installed-list $(INSTALLED_LIST) \ - --mantype="$(MANTYPE)" + --mantype="$(MANTYPE)" \ + $(INSTRUBY_OPTS) INSTALL_PROG_MODE = 0755 INSTALL_DATA_MODE = 0644 TESTSDIR = $(srcdir)/test -TOOL_TESTSDIR = $(srcdir)/tool/test +TOOL_TESTSDIR = $(tooldir)/test TEST_EXCLUDES = --excludes-dir=$(TESTSDIR)/excludes --name=!/memory_leak/ TESTWORKDIR = testwork TESTOPTS = $(RUBY_TESTOPTS) TESTRUN_SCRIPT = $(srcdir)/test.rb -COMPILE_PRELUDE = $(srcdir)/tool/generic_erb.rb $(srcdir)/template/prelude.c.tmpl +COMPILE_PRELUDE = $(tooldir)/generic_erb.rb $(srcdir)/template/prelude.c.tmpl \ + $(tooldir)/ruby_vm/helpers/c_escape.rb -SHOWFLAGS = showflags +SHOWFLAGS = $(no_silence:no=showflags) MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \ -e "src, dest = ARGV" \ @@ -247,19 +234,20 @@ mjit_config.h: Makefile # Other `-Dxxx`s preceding `-DMJIT_HEADER` will be removed in transform_mjit_header.rb. # So `-DMJIT_HEADER` should be passed first when rb_mjit_header.h is generated. $(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time: probes.h vm.$(OBJEXT) \ - $(TIMESTAMPDIR)/$(arch)/.time + $(TIMESTAMPDIR)/$(arch)/.time $(tooldir)/mjit_tabs.rb $(PREP) $(RBCONFIG) $(ECHO) building $(@F:.time=.h) - $(Q) $(CPP) -DMJIT_HEADER $(MJIT_HEADER_FLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/vm.c $(CPPOUTFLAG)$(@F:.time=.h).new + $(Q)$(MINIRUBY) $(tooldir)/mjit_tabs.rb "$(MJIT_TABS)" \ + $(CPP) -DMJIT_HEADER $(MJIT_HEADER_FLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/vm.c $(CPPOUTFLAG)$(@F:.time=.h).new $(Q) $(IFCHANGE) "--timestamp=$@" $(@F:.time=.h) $(@F:.time=.h).new $(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h: $(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time $(MJIT_MIN_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h: \ $(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time \ - $(srcdir)/tool/transform_mjit_header.rb $(PREP) \ + $(tooldir)/transform_mjit_header.rb $(PREP) \ $(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h $(ECHO) building $@ - $(MINIRUBY) $(srcdir)/tool/transform_mjit_header.rb "$(CC) $(ARCH_FLAG) $(CFLAGS)" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@ + $(Q)$(MINIRUBY) $(tooldir)/transform_mjit_header.rb "$(CC) $(CFLAGS) -w" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@ $(Q) $(MAKEDIRS) $(MJIT_HEADER_INSTALL_DIR) $(Q) $(MAKE_LINK) $@ $(MJIT_HEADER_INSTALL_DIR)/$(@F) @@ -300,14 +288,14 @@ $(EXTS_MK): ext/configure-ext.mk $(srcdir)/template/exts.mk.tmpl \ gnumake=$(gnumake) MINIRUBY="$(MINIRUBY)" \ EXTLDFLAGS="$(EXTLDFLAGS)" srcdir="$(srcdir)" $(ECHO) generating makefile $@ - $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \ - $(srcdir)/template/exts.mk.tmpl --gnumake=$(gnumake) + $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \ + $(srcdir)/template/exts.mk.tmpl --gnumake=$(gnumake) --configure-exts=ext/configure-ext.mk ext/configure-ext.mk: $(PREP) all-incs $(MKFILES) $(RBCONFIG) $(LIBRUBY) \ $(srcdir)/template/configure-ext.mk.tmpl $(ECHO) generating makefiles $@ $(Q)$(MAKEDIRS) $(@D) - $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \ + $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \ $(srcdir)/template/$(@F).tmpl --srcdir="$(srcdir)" \ --miniruby="$(MINIRUBY)" --script-args='$(SCRIPT_ARGS)' @@ -321,12 +309,13 @@ build-ext: $(EXTS_MK) exts-note: $(EXTS_MK) $(Q)$(MAKE) $(EXTS_NOTE) -ext/extinit.c: $(srcdir)/template/extinit.c.tmpl - $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \ +ext/extinit.c: $(srcdir)/template/extinit.c.tmpl $(PREP) + $(MAKEDIRS) $(@D) + $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \ $(srcdir)/template/extinit.c.tmpl $(EXTINITS) prog: program wprogram -programs: $(PROGRAM) $(WPROGRAM) +programs: $(PROGRAM) $(WPROGRAM) $(arch)-fake.rb $(PREP): $(MKFILES) @@ -341,7 +330,6 @@ $(GOLF): $(LIBRUBY) $(GOLFOBJS) PHONY $(Q) $(MAKE) $(mflags) \ GOLF=_dummy_golf_target_to_avoid_conflict_just_in_case_ \ MAINOBJ=goruby.$(OBJEXT) \ - EXTOBJS="golf_prelude.$(OBJEXT) $(EXTOBJS)" \ PROGRAM=$(GORUBY)$(EXEEXT) \ V=$(V) \ program @@ -353,9 +341,9 @@ $(CAPIOUT)/.timestamp: Doxyfile $(PREP) -$(Q) $(DOXYGEN) -b $(Q) $(MINIRUBY) -e 'File.open(ARGV[0], "w"){'"|f|"' f.puts(Time.now)}' "$@" -Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(srcdir)/tool/generic_erb.rb $(RBCONFIG) +Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(tooldir)/generic_erb.rb $(RBCONFIG) $(ECHO) generating $@ - $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \ + $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \ --srcdir="$(srcdir)" --miniruby="$(MINIRUBY)" program: $(SHOWFLAGS) $(PROGRAM) @@ -373,12 +361,12 @@ $(LIBRUBY_EXTS): $(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) $(Q)$(RM) $@ - $(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS) enclose_io_memfs.$(OBJEXT) + $(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS) ruby.imp: $(COMMONOBJS) $(Q){ \ $(NM) -Pgp $(COMMONOBJS) | \ - awk 'BEGIN{print "#!"}; $$2~/^[BDT]$$/&&$$1!~/^$(SYMBOL_PREFIX)(Init_|InitVM_|ruby_static_id_|.*_threadptr_|rb_ec_)|^\./{print $$1}'; \ + 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 '/^MJIT_FUNC_EXPORTED/!d;N;s/.*\n\(rb_[a-zA-Z_0-9]*\).*/$(SYMBOL_PREFIX)\1/p' cont.c gc.c thread*c vm*.c) \ } | \ @@ -390,17 +378,17 @@ 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 -pre-install-all:: all pre-install-local pre-install-ext pre-install-doc +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_DOC_OPTS) -post-install-all:: post-install-local post-install-ext post-install-doc + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --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-nodoc:: pre-install-local pre-install-ext pre-install-gem do-install-nodoc: main pre-install-nodoc - $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --exclude=doc -post-install-nodoc:: post-install-local post-install-ext + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --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 pre-install-local:: pre-install-bin pre-install-lib pre-install-man @@ -479,7 +467,7 @@ post-no-install-all:: post-no-install-local post-no-install-ext post-no-install- @$(NULLCMD) uninstall: $(INSTALLED_LIST) sudo-precheck - $(Q)$(SUDO) $(MINIRUBY) $(srcdir)/tool/rbuninstall.rb --destdir=$(DESTDIR) $(INSTALLED_LIST) + $(Q)$(SUDO) $(MINIRUBY) $(tooldir)/rbuninstall.rb --destdir=$(DESTDIR) $(INSTALLED_LIST) reinstall: all uninstall install @@ -487,7 +475,7 @@ what-where-nodoc: no-install-nodoc no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext dont-install-nodoc: $(PREP) - $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) + $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) --exclude=doc post-no-install-nodoc:: post-no-install-local post-no-install-ext what-where-local: no-install-local @@ -566,12 +554,19 @@ post-install-doc:: @$(NULLCMD) install-gem: pre-install-gem do-install-gem post-install-gem -pre-install-gem:: pre-install-bin pre-install-lib pre-install-man +pre-install-gem:: prepare-gems pre-install-bin pre-install-lib pre-install-man do-install-gem: $(PROGRAM) pre-install-gem $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=gem post-install-gem:: @$(NULLCMD) +install-dbg: pre-install-dbg do-install-dbg post-install-dbg +pre-install-dbg:: +do-install-dbg: $(PROGRAM) pre-install-dbg + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=dbg +post-install-dbg:: + @$(NULLCMD) + rdoc: PHONY main @echo Generating RDoc documentation $(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)" @@ -616,8 +611,8 @@ clean-local:: clean-runnable $(Q)$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(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 - $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) + $(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) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine 2> $(NULL) || $(NULLCMD) bin/clean-runnable:: PHONY @@ -634,7 +629,7 @@ clean-html: PHONY clean-capi: PHONY clean-platform: PHONY clean-extout: PHONY - -$(Q)$(RMDIR) $(EXTOUT)/$(arch) $(EXTOUT) 2> $(NULL) || $(NULLCMD) + -$(Q)$(RMDIR) $(EXTOUT)/$(arch) $(RUBYCOMMONDIR) $(EXTOUT) 2> $(NULL) || $(NULLCMD) clean-docs: clean-rdoc clean-html clean-capi clean-spec: PHONY clean-rubyspec: clean-spec @@ -734,7 +729,7 @@ clean-capi distclean-capi realclean-capi: @echo $(@:-capi=ing) capi $(Q)$(RMALL) $(CAPIOUT) -clean-platform: +clean-platform distclean-platform realclean-platform: $(Q) $(RM) $(PLATFORM_D) -$(Q) $(RMDIR) $(PLATFORM_DIR) 2> $(NULL) || $(NULLCMD) @@ -742,11 +737,15 @@ RUBYSPEC_CAPIEXT = spec/ruby/optional/capi/ext clean-spec: PHONY -$(Q) $(RM) $(RUBYSPEC_CAPIEXT)/*.$(OBJEXT) $(RUBYSPEC_CAPIEXT)/*.$(DLEXT) -$(Q) $(RMDIRS) $(RUBYSPEC_CAPIEXT) 2> $(NULL) || $(NULLCMD) + -$(Q) $(RMALL) rubyspec_temp check: main test test-tool test-all test-spec $(ECHO) check succeeded - -$(Q) if [ x"$(GIT)" != x ] && $(CHDIR) "$(srcdir)" && $(GIT) rev-parse > /dev/null 2>&1; then \ - set -x; $(GIT) --no-pager log --format=oneline -G "^ *# *include" origin/master..HEAD; \ + -$(Q) : : "run only on sh"; \ + if [ x"$(GIT)" != x ] && $(CHDIR) "$(srcdir)" && \ + b=`$(GIT) symbolic-ref --short HEAD 2>&1` && \ + u=`$(GIT) branch --list --format='%(upstream:short)' $$b`; then \ + set -x; $(GIT) --no-pager log --format=oneline -G '^ *# *include *("| parse.tmp.y - $(Q)$(BASERUBY) $(srcdir)/tool/pure_parser.rb parse.tmp.y $(YACC) + $(Q)$(BASERUBY) $(tooldir)/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ --vpath=$(VPATH) id.h $(SRC_FILE) > parse.tmp.y + $(Q)$(BASERUBY) $(tooldir)/pure_parser.rb parse.tmp.y $(YACC) + $(Q)$(RM) parse.tmp.y.bak $(Q)$(YACC) -d $(YFLAGS) -o y.tab.c parse.tmp.y $(Q)$(RM) parse.tmp.y - $(Q)sed -f $(srcdir)/tool/ytab.sed -e "/^#/s|parse\.tmp\.[iy]|$(SRC_FILE)|" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new + $(Q)sed -f $(tooldir)/ytab.sed -e "/^#/s|parse\.tmp\.[iy]|$(SRC_FILE)|" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new $(Q)$(MV) $@.new $@ $(Q)sed -e "/^#line.*y\.tab\.h/d;/^#line.*parse.*\.y/d" y.tab.h > $(@:.c=.h) $(Q)$(RM) y.tab.c y.tab.h @@ -941,23 +963,28 @@ RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \ acosh.$(OBJEXT): {$(VPATH)}acosh.c alloca.$(OBJEXT): {$(VPATH)}alloca.c {$(VPATH)}config.h +cbrt.$(OBJEXT): {$(VPATH)}cbrt.c +close.$(OBJEXT): {$(VPATH)}close.c crypt.$(OBJEXT): {$(VPATH)}crypt.c {$(VPATH)}crypt.h {$(VPATH)}missing/des_tables.c -dup2.$(OBJEXT): {$(VPATH)}dup2.c erf.$(OBJEXT): {$(VPATH)}erf.c explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c -finite.$(OBJEXT): {$(VPATH)}finite.c +ffs.$(OBJEXT): {$(VPATH)}ffs.c flock.$(OBJEXT): {$(VPATH)}flock.c +hypot.$(OBJEXT): {$(VPATH)}hypot.c +langinfo.$(OBJEXT): {$(VPATH)}langinfo.c +lgamma_r.$(OBJEXT): {$(VPATH)}lgamma_r.c memcmp.$(OBJEXT): {$(VPATH)}memcmp.c memmove.$(OBJEXT): {$(VPATH)}memmove.c -mkdir.$(OBJEXT): {$(VPATH)}mkdir.c +nan.$(OBJEXT): {$(VPATH)}nan.c +nextafter.$(OBJEXT): {$(VPATH)}nextafter.c +procstat_vm.$(OBJEXT): {$(VPATH)}procstat_vm.c setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c strchr.$(OBJEXT): {$(VPATH)}strchr.c -strdup.$(OBJEXT): {$(VPATH)}strdup.c strerror.$(OBJEXT): {$(VPATH)}strerror.c strlcat.$(OBJEXT): {$(VPATH)}strlcat.c strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c strstr.$(OBJEXT): {$(VPATH)}strstr.c -nt.$(OBJEXT): {$(VPATH)}nt.c +tgamma.$(OBJEXT): {$(VPATH)}tgamma.c .coroutine_obj $(COROUTINE_OBJ): \ {$(VPATH)}$(COROUTINE_SRC) \ @@ -982,14 +1009,14 @@ win32/win32.$(OBJEXT): {$(VPATH)}win32/win32.c {$(VPATH)}win32/file.h \ win32/file.$(OBJEXT): {$(VPATH)}win32/file.c {$(VPATH)}win32/file.h \ $(RUBY_H_INCLUDES) $(PLATFORM_D) -$(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(srcdir)/tool/transcode-tblgen.rb +$(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(tooldir)/transcode-tblgen.rb $(Q) $(MAKEDIRS) $(@D) - $(Q) $(BASERUBY) "$(srcdir)/tool/transcode-tblgen.rb" -vo $@ $(srcdir)/enc/trans/newline.trans + $(Q) $(BASERUBY) "$(tooldir)/transcode-tblgen.rb" -vo $@ $(srcdir)/enc/trans/newline.trans enc/trans/newline.$(OBJEXT): $(NEWLINE_C) -verconf.h: $(srcdir)/template/verconf.h.tmpl $(srcdir)/tool/generic_erb.rb +verconf.h: $(srcdir)/template/verconf.h.tmpl $(tooldir)/generic_erb.rb $(RBCONFIG) $(ECHO) creating $@ - $(Q) $(BOOTSTRAPRUBY) "$(srcdir)/tool/generic_erb.rb" -o $@ $(srcdir)/template/verconf.h.tmpl + $(Q) $(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ $(srcdir)/template/verconf.h.tmpl ruby-glommed.$(OBJEXT): $(OBJS) @@ -999,33 +1026,43 @@ INSNS2VMOPT = --srcdir="$(srcdir)" srcs_vpath = {$(VPATH)} -inc_common_headers = $(srcdir)/tool/ruby_vm/views/_copyright.erb $(srcdir)/tool/ruby_vm/views/_notice.erb -$(srcs_vpath)opt_sc.inc: $(srcdir)/tool/ruby_vm/views/opt_sc.inc.erb $(inc_common_headers) -$(srcs_vpath)optinsn.inc: $(srcdir)/tool/ruby_vm/views/optinsn.inc.erb $(inc_common_headers) -$(srcs_vpath)optunifs.inc: $(srcdir)/tool/ruby_vm/views/optunifs.inc.erb $(inc_common_headers) -$(srcs_vpath)insns.inc: $(srcdir)/tool/ruby_vm/views/insns.inc.erb $(inc_common_headers) -$(srcs_vpath)insns_info.inc: $(srcdir)/tool/ruby_vm/views/insns_info.inc.erb $(inc_common_headers) \ - $(srcdir)/tool/ruby_vm/views/_insn_type_chars.erb $(srcdir)/tool/ruby_vm/views/_insn_name_info.erb \ - $(srcdir)/tool/ruby_vm/views/_insn_len_info.erb $(srcdir)/tool/ruby_vm/views/_insn_operand_info.erb \ - $(srcdir)/tool/ruby_vm/views/_attributes.erb $(srcdir)/tool/ruby_vm/views/_comptime_insn_stack_increase.erb \ - $(srcdir)/tool/ruby_vm/views/_insn_sp_pc_dependency.erb -$(srcs_vpath)vmtc.inc: $(srcdir)/tool/ruby_vm/views/vmtc.inc.erb $(inc_common_headers) -$(srcs_vpath)vm.inc: $(srcdir)/tool/ruby_vm/views/vm.inc.erb $(inc_common_headers) \ - $(srcdir)/tool/ruby_vm/views/_insn_entry.erb $(srcdir)/tool/ruby_vm/views/_trace_instruction.erb -$(srcs_vpath)mjit_compile.inc: $(srcdir)/tool/ruby_vm/views/mjit_compile.inc.erb $(inc_common_headers) \ - $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_send.erb \ - $(srcdir)/tool/ruby_vm/views/_mjit_compile_ivar.erb \ - $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn_body.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb +inc_common_headers = $(tooldir)/ruby_vm/views/_copyright.erb $(tooldir)/ruby_vm/views/_notice.erb +$(srcs_vpath)opt_sc.inc: $(tooldir)/ruby_vm/views/opt_sc.inc.erb $(inc_common_headers) +$(srcs_vpath)optinsn.inc: $(tooldir)/ruby_vm/views/optinsn.inc.erb $(inc_common_headers) +$(srcs_vpath)optunifs.inc: $(tooldir)/ruby_vm/views/optunifs.inc.erb $(inc_common_headers) +$(srcs_vpath)insns.inc: $(tooldir)/ruby_vm/views/insns.inc.erb $(inc_common_headers) +$(srcs_vpath)insns_info.inc: $(tooldir)/ruby_vm/views/insns_info.inc.erb $(inc_common_headers) \ + $(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 +$(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 +$(srcs_vpath)mjit_compile.inc: $(tooldir)/ruby_vm/views/mjit_compile.inc.erb $(inc_common_headers) \ + $(tooldir)/ruby_vm/views/_mjit_compile_insn.erb $(tooldir)/ruby_vm/views/_mjit_compile_send.erb \ + $(tooldir)/ruby_vm/views/_mjit_compile_ivar.erb \ + $(tooldir)/ruby_vm/views/_mjit_compile_insn_body.erb $(tooldir)/ruby_vm/views/_mjit_compile_pc_and_sp.erb \ + $(tooldir)/ruby_vm/views/_mjit_compile_invokebuiltin.erb $(tooldir)/ruby_vm/views/_mjit_compile_getinlinecache.erb BUILTIN_RB_SRCS = \ $(srcdir)/ast.rb \ + $(srcdir)/dir.rb \ $(srcdir)/gc.rb \ + $(srcdir)/numeric.rb \ $(srcdir)/io.rb \ + $(srcdir)/marshal.rb \ $(srcdir)/pack.rb \ $(srcdir)/trace_point.rb \ $(srcdir)/warning.rb \ + $(srcdir)/array.rb \ + $(srcdir)/kernel.rb \ + $(srcdir)/ractor.rb \ + $(srcdir)/timev.rb \ + $(srcdir)/nilclass.rb \ $(srcdir)/prelude.rb \ $(srcdir)/gem_prelude.rb \ + $(srcdir)/yjit.rb \ $(empty) BUILTIN_RB_INCS = $(BUILTIN_RB_SRCS:.rb=.rbinc) @@ -1068,51 +1105,51 @@ all-incs: incs {$(VPATH)}encdb.h {$(VPATH)}transdb.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) $(srcdir)/enc/jis/props.h \ + $(UNICODE_DATA_HEADERS) $(ENC_HEADERS) \ {$(VPATH)}id.h {$(VPATH)}probes.dmyh insns: $(INSNS) -id.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def +id.h: $(tooldir)/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def $(ECHO) generating $@ - $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \ + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \ $(srcdir)/template/id.h.tmpl -id.c: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def +id.c: $(tooldir)/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def $(ECHO) generating $@ - $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \ + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \ $(srcdir)/template/id.c.tmpl -node_name.inc: $(srcdir)/tool/node_name.rb $(srcdir)/node.h +node_name.inc: $(tooldir)/node_name.rb $(srcdir)/node.h $(ECHO) generating $@ - $(Q) $(BASERUBY) -n $(srcdir)/tool/node_name.rb < $(srcdir)/node.h > $@ + $(Q) $(BASERUBY) -n $(tooldir)/node_name.rb < $(srcdir)/node.h > $@ -encdb.h: $(PREP) $(srcdir)/tool/generic_erb.rb $(srcdir)/template/encdb.h.tmpl +encdb.h: $(PREP) $(tooldir)/generic_erb.rb $(srcdir)/template/encdb.h.tmpl $(ECHO) generating $@ - $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc + $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc -transdb.h: $(PREP) srcs-enc $(srcdir)/tool/generic_erb.rb $(srcdir)/template/transdb.h.tmpl +transdb.h: $(PREP) srcs-enc $(tooldir)/generic_erb.rb $(srcdir)/template/transdb.h.tmpl $(ECHO) generating $@ - $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/transdb.h.tmpl $(srcdir)/enc/trans enc/trans + $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/transdb.h.tmpl $(srcdir)/enc/trans enc/trans enc/encinit.c: $(ENC_MK) $(srcdir)/enc/encinit.c.erb known_errors.inc: $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def $(ECHO) generating $@ - $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def -vm_call_iseq_optimized.inc: $(srcdir)/tool/mk_call_iseq_optimized.rb +vm_call_iseq_optimized.inc: $(srcdir)/template/call_iseq_optimized.inc.tmpl $(ECHO) generating $@ - $(Q) $(BASERUBY) $(srcdir)/tool/mk_call_iseq_optimized.rb > $@ + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/call_iseq_optimized.inc.tmpl $(MINIPRELUDE_C): $(COMPILE_PRELUDE) $(BUILTIN_RB_SRCS) $(ECHO) generating $@ - $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -o $@ \ + $(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) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -c -o $@ \ + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -c -o $@ \ $(srcdir)/template/prelude.c.tmpl golf_prelude.rb MAINCPPFLAGS = $(ENABLE_DEBUG_ENV:yes=-DRUBY_DEBUG_ENV=1) @@ -1121,10 +1158,10 @@ $(MAINOBJ): $(srcdir)/$(MAINSRC) $(ECHO) compiling $(srcdir)/$(MAINSRC) $(Q) $(CC) $(MAINCPPFLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(srcdir)/$(MAINSRC) -{$(VPATH)}probes.dmyh: {$(srcdir)}probes.d $(srcdir)/tool/gen_dummy_probes.rb +{$(VPATH)}probes.dmyh: {$(srcdir)}probes.d $(tooldir)/gen_dummy_probes.rb probes.dmyh: - $(BASERUBY) $(srcdir)/tool/gen_dummy_probes.rb $(srcdir)/probes.d > $@ + $(BASERUBY) $(tooldir)/gen_dummy_probes.rb $(srcdir)/probes.d > $@ probes.h: {$(VPATH)}probes.$(DTRACE_EXT) @@ -1135,32 +1172,34 @@ preludes: {$(srcdir)}golf_prelude.c {$(srcdir)}.rb.rbinc: $(ECHO) making $@ - $(Q) $(BASERUBY) $(srcdir)/tool/mk_builtin_loader.rb $< + $(Q) $(BASERUBY) $(tooldir)/mk_builtin_loader.rb $< -builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/tool/mk_builtin_binary.rb - $(Q) $(MINIRUBY) $(srcdir)/tool/mk_builtin_binary.rb --cross=$(CROSS_COMPILING) +builtin_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) $(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb $(srcdir)/revision.h: - $(Q)$(gnumake:yes=#) $(RM) $(@F) - $(Q)$(gnumake:yes=#) $(NULLCMD) > $@ || $(NULLCMD) > $(@F) +$(srcdir)/revision.h$(gnumake:yes=-nongnumake): + $(Q)$(RM) $(@F) + $(Q)$(NULLCMD) > $@ || $(NULLCMD) > $(@F) revision.tmp:: $(Q) $(NULLCMD) > $@ -revision.$(HAVE_BASERUBY:yes=tmp):: $(srcdir)/version.h $(srcdir)/tool/file2lastrev.rb $(REVISION_FORCE) - $(Q) $(BASERUBY) $(srcdir)/tool/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" > $@ +revision.$(HAVE_BASERUBY:yes=tmp):: $(srcdir)/version.h $(tooldir)/file2lastrev.rb $(REVISION_FORCE) + $(Q) $(BASERUBY) $(tooldir)/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" > $@ $(REVISION_H): revision.tmp $(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp $(srcdir)/ext/ripper/ripper.c: $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/parse.y id.h $(srcdir)/ext/ripper/depend $(ECHO) generating $@ - $(Q) VPATH=$${PWD-`pwd`} && $(CHDIR) $(@D) && \ + $(Q) $(CHDIR) $(@D) && \ sed -e 's/{\$$([^(){}]*)[^{}]*}//g' -e /AUTOGENERATED/q depend | \ $(exec) $(MAKE) -f - $(mflags) \ - Q=$(Q) ECHO=$(ECHO) RM="$(RM)" BISON=$(YACC) top_srcdir=../.. srcdir=. VPATH="$${VPATH}" \ - RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)" + Q=$(Q) ECHO=$(ECHO) RM="$(RM1)" BISON=$(YACC) top_srcdir=../.. srcdir=. VPATH=../.. \ + RUBY="$(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 $@ @@ -1173,7 +1212,7 @@ $(srcdir)/ext/date/zonetab.h: $(srcdir)/ext/date/zonetab.list $(srcdir)/ext/date Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. BASERUBY="$(BASERUBY)" $(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \ - $(srcdir)/tool/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.ac + $(tooldir)/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.ac $(ECHO) generating $@ $(Q) $(CHDIR) $(@D) && \ sed '/AUTOGENERATED/q' depend | \ @@ -1181,7 +1220,7 @@ $(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \ Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F) $(srcdir)/ext/rbconfig/sizeof/limits.c: $(srcdir)/ext/rbconfig/sizeof/depend \ - $(srcdir)/tool/generic_erb.rb $(srcdir)/template/limits.c.tmpl + $(tooldir)/generic_erb.rb $(srcdir)/template/limits.c.tmpl $(ECHO) generating $@ $(Q) $(CHDIR) $(@D) && \ sed '/AUTOGENERATED/q' depend | \ @@ -1203,22 +1242,26 @@ $(srcdir)/ext/etc/constdefs.h: $(srcdir)/ext/etc/depend ## run: fake miniruby$(EXEEXT) PHONY - $(BTESTRUBY) $(TESTRUN_SCRIPT) $(RUNOPT) + $(BTESTRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) runruby: $(PROGRAM) PHONY - $(RUNRUBY) $(TESTRUN_SCRIPT) + 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) parse: fake miniruby$(EXEEXT) PHONY $(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT) bisect: PHONY - $(srcdir)/tool/bisect.sh miniruby $(srcdir) + $(tooldir)/bisect.sh miniruby $(srcdir) bisect-ruby: PHONY - $(srcdir)/tool/bisect.sh ruby $(srcdir) + $(tooldir)/bisect.sh ruby $(srcdir) COMPARE_RUBY = $(BASERUBY) BENCH_RUBY = $(RUNRUBY) +BENCH_OPTS = --output=markdown --output-compare -v ITEM = ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '$(ITEM)' -o -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb' | sort) OPTS = @@ -1228,10 +1271,12 @@ benchmark: miniruby$(EXEEXT) update-benchmark-driver PHONY $(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \ --executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \ --executables="built-ruby::$(BENCH_RUBY) --disable-gem" \ - $(ARGS) $(OPTS) + $(BENCH_OPTS) $(ARGS) $(OPTS) run.gdb: echo set breakpoint pending on > run.gdb + echo b rb_assert_failure >> run.gdb + echo b rb_bug >> run.gdb echo b ruby_debug_breakpoint >> run.gdb echo '# handle SIGINT nostop' >> run.gdb echo '# handle SIGPIPE nostop' >> run.gdb @@ -1246,37 +1291,36 @@ run.gdb: gdb: miniruby$(EXEEXT) run.gdb PHONY - gdb -x run.gdb --quiet --args $(MINIRUBY) $(TESTRUN_SCRIPT) + gdb -x run.gdb --quiet --args $(MINIRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) gdb-ruby: $(PROGRAM) run.gdb PHONY - $(Q) $(RUNRUBY_COMMAND) $(RUNRUBY_DEBUGGER) -- $(TESTRUN_SCRIPT) + $(Q) $(RUNRUBY_COMMAND) $(RUNRUBY_DEBUGGER) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) LLDB_INIT = command script import -r $(srcdir)/misc/lldb_cruby.py lldb: miniruby$(EXEEXT) PHONY - lldb -o '$(LLDB_INIT)' miniruby$(EXEEXT) -- $(TESTRUN_SCRIPT) + lldb -o '$(LLDB_INIT)' miniruby$(EXEEXT) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) lldb-ruby: $(PROGRAM) PHONY - lldb $(enable_shared:yes=-o 'target modules add ${LIBRUBY_SO}') -o '$(LLDB_INIT)' $(PROGRAM) -- $(TESTRUN_SCRIPT) + lldb $(enable_shared:yes=-o 'target modules add ${LIBRUBY_SO}') -o '$(LLDB_INIT)' $(PROGRAM) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) DISTPKGS = gzip,zip,all +PKGSDIR = tmp dist: - $(BASERUBY) $(srcdir)/tool/make-snapshot \ + $(BASERUBY) $(tooldir)/make-snapshot \ -srcdir=$(srcdir) -packages=$(DISTPKGS) \ -unicode-version=$(UNICODE_VERSION) \ - tmp $(RELNAME) + $(DISTOPTS) $(PKGSDIR) $(RELNAME) up:: update-remote up:: - -$(Q)$(MAKE) $(mflags) Q=$(Q) REVISION_FORCE=PHONY "$(REVISION_H)" - -up:: - -$(Q)$(MAKE) $(mflags) Q=$(Q) after-update + -$(Q)$(MAKE) $(mflags) Q=$(Q) REVISION_FORCE=PHONY ALWAYS_UPDATE_UNICODE= after-update yes:: no:: +after-update:: $(REVISION_H) after-update:: extract-extlibs after-update:: extract-gems @@ -1292,13 +1336,15 @@ update-config_files: PHONY $(Q) $(BASERUBY) -C "$(srcdir)" tool/downloader.rb -d tool --cache-dir=$(CACHE_DIR) -e gnu \ config.guess config.sub -refresh-gems: update-bundled_gems update-gems extract-gems +refresh-gems: update-bundled_gems prepare-gems +prepare-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=extract-gems) -update-gems: PHONY +update-gems$(gnumake:yes=-nongnumake): PHONY $(ECHO) Downloading bundled gem files... $(Q) $(BASERUBY) -C "$(srcdir)" \ -I./tool -rdownloader -answ \ -e 'gem, ver = *$$F' \ + -e 'next if !ver or /^#/=~gem' \ -e 'old = Dir.glob("gems/#{gem}-*.gem")' \ -e 'gem = "#{gem}-#{ver}.gem"' \ -e 'Downloader::RubyGems.download(gem, "gems", nil) and' \ @@ -1307,35 +1353,40 @@ update-gems: PHONY -e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' \ gems/bundled_gems -extract-gems: PHONY +extract-gems$(gnumake:yes=-nongnumake): PHONY $(ECHO) Extracting bundled gem files... - $(Q) $(RUNRUBY) -C "$(srcdir)/gems" \ - -I../tool -rgem-unpack -answ \ + $(Q) $(RUNRUBY) -C "$(srcdir)" \ + -Itool -rgem-unpack -answ \ + -e 'BEGIN {FileUtils.mkdir_p(d = ".bundle/gems")}' \ -e 'gem, ver = *$$F' \ - -e 'Gem.unpack("#{gem}-#{ver}.gem")' \ - bundled_gems + -e 'next if !ver or /^#/=~gem' \ + -e 'g = "#{gem}-#{ver}"' \ + -e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", d)' \ + gems/bundled_gems update-bundled_gems: PHONY $(Q) $(RUNRUBY) -rrubygems \ - -pla \ - -e '(gem,src), = Gem::SpecFetcher.fetcher.detect(:latest) {'"|s|" \ - -e 's.platform=="ruby"&&s.name==$$F[0]' \ - -e '}' \ - -e 'gem = src.fetch_spec(gem)' \ - -e 'uri = gem.metadata["source_code_uri"]||gem.homepage' \ - -e 'uri = uri.sub(%r[\Ahttps://github\.com/[^/]+/[^/]+\K/tree/.*], "")' \ - -e '$$_ = [gem.name, gem.version, uri].join(" ")' \ + $(tooldir)/update-bundled_gems.rb \ "$(srcdir)/gems/bundled_gems" | \ - "$(IFCHANGE)" "$(srcdir)/gems/bundled_gems" - + $(IFCHANGE) "$(srcdir)/gems/bundled_gems" - + git -C "$(srcdir)" diff --no-ext-diff --ignore-submodules --exit-code || \ + git -C "$(srcdir)" commit -m "Update bundled_gems" gems/bundled_gems -test-bundled-gems-precheck: $(arch)-fake.rb programs +test-bundled-gems-precheck: $(TEST_RUNNABLE)-test-bundled-gems-precheck +yes-test-bundled-gems-precheck: main +no-test-bundled-gems-precheck: test-bundled-gems-fetch: $(PREP) $(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems test-bundled-gems-prepare: test-bundled-gems-precheck 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 + $(ACTIONS_GROUP) $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ - --install-dir .bundle --conservative "bundler" "minitest:~> 5" 'test-unit' 'rake' 'hoe' 'yard' 'pry' 'packnga' + --install-dir .bundle --conservative "bundler" "minitest:~> 5" "test-unit" "rake" "hoe" "yard" "pry" "packnga" "rexml" "json-schema" "test-unit-rr" + $(ACTIONS_ENDGROUP) PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems @@ -1345,14 +1396,24 @@ no-test-bundled-gems: # Override this to allow failure of specific gems on CI # TEST_BUNDLED_GEMS_ALLOW_FAILURES = +BUNDLED_GEMS = test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS) - $(Q) $(XRUBY) $(srcdir)/tool/test-bundled-gems.rb - -test-bundler-precheck: $(arch)-fake.rb programs - -yes-test-bundler-prepare: test-bundler-precheck - $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ - --install-dir .bundle --conservative "rspec:~> 3.5" "rake:~> 12.0" "parallel_tests:~> 2.29" + $(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS) + +test-bundler-precheck: $(TEST_RUNNABLE)-test-bundler-precheck +no-test-bundler-precheck: +yes-test-bundler-precheck: main + +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 --gemfile=tool/bundler/dev_gems.rb + $(ACTIONS_ENDGROUP) RSPECOPTS = BUNDLER_SPECS = @@ -1365,9 +1426,16 @@ no-test-bundler: PARALLELRSPECOPTS = --runtime-log $(srcdir)/tmp/parallel_runtime_rspec.log test-bundler-parallel: $(TEST_RUNNABLE)-test-bundler-parallel yes-test-bundler-parallel: yes-test-bundler-prepare - $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/parallel_rspec \ - -o "--require $(srcdir)/spec/bundler/spec_helper --require $(srcdir)/spec/bundler/support/parallel" \ - $(PARALLELRSPECOPTS) spec/bundler/$(BUNDLER_SPECS) + $(XRUBY) \ + -e "ARGV[-1] = File.expand_path(ARGV[-1])" \ + -e "exec(*ARGV)" -- \ + $(XRUBY) -I$(srcdir)/spec/bundler \ + -e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ARGV.shift" \ + -e "load ARGV.shift" \ + "$(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec" \ + $(srcdir)/.bundle/bin/parallel_rspec \ + -o "--require spec_helper" \ + $(PARALLELRSPECOPTS) $(srcdir)/spec/bundler/$(BUNDLER_SPECS) no-test-bundler-parallel: GEM = up @@ -1396,34 +1464,44 @@ UNICODE_AUXILIARY_FILES = \ $(UNICODE_SRC_DATA_DIR)/auxiliary/GraphemeBreakTest.txt \ $(empty) +UNICODE_UCD_EMOJI_FILES = \ + $(UNICODE_SRC_DATA_DIR)/emoji/emoji-data.txt \ + $(UNICODE_SRC_DATA_DIR)/emoji/emoji-variation-sequences.txt \ + $(empty) + UNICODE_EMOJI_FILES = \ - $(UNICODE_SRC_EMOJI_DATA_DIR)/emoji-data.txt \ $(UNICODE_SRC_EMOJI_DATA_DIR)/emoji-sequences.txt \ $(UNICODE_SRC_EMOJI_DATA_DIR)/emoji-test.txt \ - $(UNICODE_SRC_EMOJI_DATA_DIR)/emoji-variation-sequences.txt \ $(UNICODE_SRC_EMOJI_DATA_DIR)/emoji-zwj-sequences.txt \ $(empty) update-unicode: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) \ - $(UNICODE_AUXILIARY_FILES) $(UNICODE_EMOJI_FILES) + $(UNICODE_AUXILIARY_FILES) $(UNICODE_UCD_EMOJI_FILES) $(UNICODE_EMOJI_FILES) CACHE_DIR = $(srcdir)/.downloaded-cache UNICODE_DOWNLOAD = \ - $(BASERUBY) $(srcdir)/tool/downloader.rb \ + $(BASERUBY) $(tooldir)/downloader.rb \ --cache-dir=$(CACHE_DIR) \ --unicode-beta $(UNICODE_BETA) \ -d $(UNICODE_SRC_DATA_DIR) \ -p $(UNICODE_VERSION)/ucd \ -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode UNICODE_AUXILIARY_DOWNLOAD = \ - $(BASERUBY) $(srcdir)/tool/downloader.rb \ + $(BASERUBY) $(tooldir)/downloader.rb \ --cache-dir=$(CACHE_DIR) \ --unicode-beta $(UNICODE_BETA) \ -d $(UNICODE_SRC_DATA_DIR)/auxiliary \ -p $(UNICODE_VERSION)/ucd/auxiliary \ -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode +UNICODE_UCD_EMOJI_DOWNLOAD = \ + $(BASERUBY) $(tooldir)/downloader.rb \ + --cache-dir=$(CACHE_DIR) \ + --unicode-beta $(UNICODE_BETA) \ + -d $(UNICODE_SRC_DATA_DIR)/emoji \ + -p $(UNICODE_VERSION)/ucd/emoji \ + -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode UNICODE_EMOJI_DOWNLOAD = \ - $(BASERUBY) $(srcdir)/tool/downloader.rb \ + $(BASERUBY) $(tooldir)/downloader.rb \ --cache-dir=$(CACHE_DIR) \ --unicode-beta $(UNICODE_BETA) \ -d $(UNICODE_SRC_EMOJI_DATA_DIR) \ @@ -1432,7 +1510,7 @@ UNICODE_EMOJI_DOWNLOAD = \ $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES): update-unicode-files update-unicode-files: - $(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files... + $(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files... $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)" $(Q) $(UNICODE_DOWNLOAD) $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) @@ -1442,29 +1520,35 @@ update-unicode-auxiliary-files: $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary" $(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $(UNICODE_AUXILIARY_FILES) +$(UNICODE_UCD_EMOJI_FILES): update-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) + $(UNICODE_EMOJI_FILES): update-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) -$(srcdir)/lib/unicode_normalize/$(HAVE_BASERUBY:yes=tables.rb): \ - $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time +$(srcdir)/lib/unicode_normalize/$(ALWAYS_UPDATE_UNICODE:yes=tables.rb): \ + $(UNICODE_SRC_DATA_DIR)/$(HAVE_BASERUBY:yes=.unicode-tables.time) $(UNICODE_SRC_DATA_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=.unicode-tables.time): \ $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) \ - $(UNICODE_AUXILIARY_FILES) $(UNICODE_EMOJI_FILES) + $(UNICODE_AUXILIARY_FILES) $(UNICODE_UCD_EMOJI_FILES) $(UNICODE_EMOJI_FILES) touch-unicode-files: $(MAKEDIRS) $(UNICODE_SRC_DATA_DIR) touch $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time $(UNICODE_DATA_HEADERS) UNICODE_TABLES_TIMESTAMP = yes -$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: $(srcdir)/tool/generic_erb.rb \ +$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: $(tooldir)/generic_erb.rb \ $(srcdir)/template/unicode_norm_gen.tmpl \ $(ALWAYS_UPDATE_UNICODE:yes=update-unicode) $(Q) $(MAKE) $(@D) - $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb \ + $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb \ -c $(UNICODE_TABLES_TIMESTAMP:yes=-t$@) \ -o $(srcdir)/lib/unicode_normalize/tables.rb \ -I $(srcdir) \ @@ -1475,14 +1559,14 @@ $(UNICODE_SRC_DATA_DIR): $(gnumake_recursive)$(Q) $(MAKEDIRS) $@ $(UNICODE_HDR_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=name2ctype.h): \ - $(srcdir)/tool/enc-unicode.rb \ + $(tooldir)/enc-unicode.rb \ $(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \ $(UNICODE_PROPERTY_FILES) \ $(UNICODE_EMOJI_FILES) $(UNICODE_HDR_DIR)/name2ctype.h: $(MAKEDIRS) $(@D) - $(BOOTSTRAPRUBY) $(srcdir)/tool/enc-unicode.rb --header \ + $(BOOTSTRAPRUBY) $(tooldir)/enc-unicode.rb --header \ $(UNICODE_SRC_DATA_DIR) $(UNICODE_SRC_EMOJI_DATA_DIR) > $@.new $(MV) $@.new $@ @@ -1540,11 +1624,18 @@ sudo-precheck: PHONY @$(SUDO) echo > $(NULL) update-man-date: PHONY - -$(Q) $(BASERUBY) -I"$(srcdir)/tool/lib" -rvcs -i -p \ + -$(Q) $(BASERUBY) -I"$(tooldir)/lib" -rvcs -i -p \ -e 'BEGIN{@vcs=VCS.detect(ARGV.shift)}' \ -e '$$_.sub!(/^(\.Dd ).*/){$$1+@vcs.modified(ARGF.path).strftime("%B %d, %Y")}' \ "$(srcdir)" "$(srcdir)"/man/*.1 +.PHONY: ChangeLog +ChangeLog: + $(ECHO) Generating $@ + -$(Q) $(BASERUBY) -I"$(tooldir)/lib" -rvcs \ + -e 'VCS.detect(ARGV[0]).export_changelog("@", nil, nil, ARGV[1])' \ + "$(srcdir)" $@ + HELP_EXTRA_TASKS = "" help: PHONY @@ -1572,7 +1663,7 @@ help: PHONY " test-tool: tests under the tool/test" \ " update-gems: download files of the bundled gems" \ " update-bundled_gems: update the latest version of bundled gems" \ - " sync-default-gems: sync default gems from upstream [GEM=]" \ + " sync-default-gems: sync default gems from upstream [GEM=]" \ " up: update local copy and autogenerated files" \ " benchmark: benchmark this ruby and COMPARE_RUBY." \ " gcbench: gc benchmark [GCBENCH_ITEM=]" \ @@ -1590,20 +1681,246 @@ help: PHONY # AUTOGENERATED DEPENDENCIES START addr2line.$(OBJEXT): {$(VPATH)}addr2line.c addr2line.$(OBJEXT): {$(VPATH)}addr2line.h +addr2line.$(OBJEXT): {$(VPATH)}assert.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/assume.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/bool.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +addr2line.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h addr2line.$(OBJEXT): {$(VPATH)}config.h addr2line.$(OBJEXT): {$(VPATH)}defines.h +addr2line.$(OBJEXT): {$(VPATH)}internal/assume.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/const.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/error.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/format.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +addr2line.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +addr2line.$(OBJEXT): {$(VPATH)}internal/cast.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +addr2line.$(OBJEXT): {$(VPATH)}internal/config.h +addr2line.$(OBJEXT): {$(VPATH)}internal/dllexport.h +addr2line.$(OBJEXT): {$(VPATH)}internal/dosish.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/extension.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/feature.h +addr2line.$(OBJEXT): {$(VPATH)}internal/has/warning.h +addr2line.$(OBJEXT): {$(VPATH)}internal/stdalign.h +addr2line.$(OBJEXT): {$(VPATH)}internal/stdbool.h +addr2line.$(OBJEXT): {$(VPATH)}internal/warning_push.h +addr2line.$(OBJEXT): {$(VPATH)}internal/xmalloc.h addr2line.$(OBJEXT): {$(VPATH)}missing.h -array.$(OBJEXT): $(hdrdir)/ruby.h array.$(OBJEXT): $(hdrdir)/ruby/ruby.h +array.$(OBJEXT): $(top_srcdir)/internal/array.h +array.$(OBJEXT): $(top_srcdir)/internal/bignum.h +array.$(OBJEXT): $(top_srcdir)/internal/bits.h +array.$(OBJEXT): $(top_srcdir)/internal/class.h +array.$(OBJEXT): $(top_srcdir)/internal/compar.h +array.$(OBJEXT): $(top_srcdir)/internal/compilers.h +array.$(OBJEXT): $(top_srcdir)/internal/enum.h +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/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/serial.h +array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +array.$(OBJEXT): $(top_srcdir)/internal/vm.h +array.$(OBJEXT): $(top_srcdir)/internal/warnings.h array.$(OBJEXT): {$(VPATH)}array.c +array.$(OBJEXT): {$(VPATH)}array.rbinc array.$(OBJEXT): {$(VPATH)}assert.h +array.$(OBJEXT): {$(VPATH)}backward/2/assume.h +array.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +array.$(OBJEXT): {$(VPATH)}backward/2/bool.h +array.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +array.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +array.$(OBJEXT): {$(VPATH)}backward/2/limits.h +array.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +array.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +array.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +array.$(OBJEXT): {$(VPATH)}builtin.h array.$(OBJEXT): {$(VPATH)}config.h array.$(OBJEXT): {$(VPATH)}debug_counter.h array.$(OBJEXT): {$(VPATH)}defines.h array.$(OBJEXT): {$(VPATH)}encoding.h array.$(OBJEXT): {$(VPATH)}id.h +array.$(OBJEXT): {$(VPATH)}id_table.h array.$(OBJEXT): {$(VPATH)}intern.h array.$(OBJEXT): {$(VPATH)}internal.h +array.$(OBJEXT): {$(VPATH)}internal/anyargs.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +array.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +array.$(OBJEXT): {$(VPATH)}internal/assume.h +array.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +array.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +array.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +array.$(OBJEXT): {$(VPATH)}internal/attr/const.h +array.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +array.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +array.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +array.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +array.$(OBJEXT): {$(VPATH)}internal/attr/error.h +array.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +array.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +array.$(OBJEXT): {$(VPATH)}internal/attr/format.h +array.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +array.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +array.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +array.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +array.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +array.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +array.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +array.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +array.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +array.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +array.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +array.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +array.$(OBJEXT): {$(VPATH)}internal/cast.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +array.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +array.$(OBJEXT): {$(VPATH)}internal/config.h +array.$(OBJEXT): {$(VPATH)}internal/constant_p.h +array.$(OBJEXT): {$(VPATH)}internal/core.h +array.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +array.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +array.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +array.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +array.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +array.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +array.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +array.$(OBJEXT): {$(VPATH)}internal/core/robject.h +array.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +array.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +array.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +array.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +array.$(OBJEXT): {$(VPATH)}internal/ctype.h +array.$(OBJEXT): {$(VPATH)}internal/dllexport.h +array.$(OBJEXT): {$(VPATH)}internal/dosish.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +array.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +array.$(OBJEXT): {$(VPATH)}internal/error.h +array.$(OBJEXT): {$(VPATH)}internal/eval.h +array.$(OBJEXT): {$(VPATH)}internal/event.h +array.$(OBJEXT): {$(VPATH)}internal/fl_type.h +array.$(OBJEXT): {$(VPATH)}internal/gc.h +array.$(OBJEXT): {$(VPATH)}internal/glob.h +array.$(OBJEXT): {$(VPATH)}internal/globals.h +array.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +array.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +array.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +array.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +array.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +array.$(OBJEXT): {$(VPATH)}internal/has/extension.h +array.$(OBJEXT): {$(VPATH)}internal/has/feature.h +array.$(OBJEXT): {$(VPATH)}internal/has/warning.h +array.$(OBJEXT): {$(VPATH)}internal/intern/array.h +array.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +array.$(OBJEXT): {$(VPATH)}internal/intern/class.h +array.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +array.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +array.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +array.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +array.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +array.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +array.$(OBJEXT): {$(VPATH)}internal/intern/error.h +array.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +array.$(OBJEXT): {$(VPATH)}internal/intern/file.h +array.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +array.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +array.$(OBJEXT): {$(VPATH)}internal/intern/io.h +array.$(OBJEXT): {$(VPATH)}internal/intern/load.h +array.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +array.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +array.$(OBJEXT): {$(VPATH)}internal/intern/object.h +array.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +array.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +array.$(OBJEXT): {$(VPATH)}internal/intern/process.h +array.$(OBJEXT): {$(VPATH)}internal/intern/random.h +array.$(OBJEXT): {$(VPATH)}internal/intern/range.h +array.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +array.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +array.$(OBJEXT): {$(VPATH)}internal/intern/string.h +array.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +array.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +array.$(OBJEXT): {$(VPATH)}internal/intern/time.h +array.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +array.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +array.$(OBJEXT): {$(VPATH)}internal/interpreter.h +array.$(OBJEXT): {$(VPATH)}internal/iterator.h +array.$(OBJEXT): {$(VPATH)}internal/memory.h +array.$(OBJEXT): {$(VPATH)}internal/method.h +array.$(OBJEXT): {$(VPATH)}internal/module.h +array.$(OBJEXT): {$(VPATH)}internal/newobj.h +array.$(OBJEXT): {$(VPATH)}internal/rgengc.h +array.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +array.$(OBJEXT): {$(VPATH)}internal/value.h +array.$(OBJEXT): {$(VPATH)}internal/value_type.h +array.$(OBJEXT): {$(VPATH)}internal/variable.h +array.$(OBJEXT): {$(VPATH)}internal/warning_push.h +array.$(OBJEXT): {$(VPATH)}internal/xmalloc.h array.$(OBJEXT): {$(VPATH)}missing.h array.$(OBJEXT): {$(VPATH)}onigmo.h array.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -1620,16 +1937,185 @@ ast.$(OBJEXT): $(CCAN_DIR)/list/list.h ast.$(OBJEXT): $(CCAN_DIR)/str/str.h ast.$(OBJEXT): $(hdrdir)/ruby.h ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h +ast.$(OBJEXT): $(top_srcdir)/internal/array.h +ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ast.$(OBJEXT): $(top_srcdir)/internal/gc.h +ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ast.$(OBJEXT): $(top_srcdir)/internal/parse.h +ast.$(OBJEXT): $(top_srcdir)/internal/serial.h +ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h +ast.$(OBJEXT): $(top_srcdir)/internal/vm.h +ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h ast.$(OBJEXT): {$(VPATH)}assert.h ast.$(OBJEXT): {$(VPATH)}ast.c ast.$(OBJEXT): {$(VPATH)}ast.rbinc +ast.$(OBJEXT): {$(VPATH)}atomic.h +ast.$(OBJEXT): {$(VPATH)}backward/2/assume.h +ast.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +ast.$(OBJEXT): {$(VPATH)}backward/2/bool.h +ast.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +ast.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +ast.$(OBJEXT): {$(VPATH)}backward/2/limits.h +ast.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +ast.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +ast.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h ast.$(OBJEXT): {$(VPATH)}builtin.h ast.$(OBJEXT): {$(VPATH)}config.h +ast.$(OBJEXT): {$(VPATH)}darray.h ast.$(OBJEXT): {$(VPATH)}defines.h ast.$(OBJEXT): {$(VPATH)}encoding.h ast.$(OBJEXT): {$(VPATH)}id.h ast.$(OBJEXT): {$(VPATH)}intern.h ast.$(OBJEXT): {$(VPATH)}internal.h +ast.$(OBJEXT): {$(VPATH)}internal/anyargs.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +ast.$(OBJEXT): {$(VPATH)}internal/assume.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/const.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/error.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/format.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +ast.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +ast.$(OBJEXT): {$(VPATH)}internal/cast.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +ast.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +ast.$(OBJEXT): {$(VPATH)}internal/config.h +ast.$(OBJEXT): {$(VPATH)}internal/constant_p.h +ast.$(OBJEXT): {$(VPATH)}internal/core.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +ast.$(OBJEXT): {$(VPATH)}internal/core/robject.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +ast.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +ast.$(OBJEXT): {$(VPATH)}internal/ctype.h +ast.$(OBJEXT): {$(VPATH)}internal/dllexport.h +ast.$(OBJEXT): {$(VPATH)}internal/dosish.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +ast.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +ast.$(OBJEXT): {$(VPATH)}internal/error.h +ast.$(OBJEXT): {$(VPATH)}internal/eval.h +ast.$(OBJEXT): {$(VPATH)}internal/event.h +ast.$(OBJEXT): {$(VPATH)}internal/fl_type.h +ast.$(OBJEXT): {$(VPATH)}internal/gc.h +ast.$(OBJEXT): {$(VPATH)}internal/glob.h +ast.$(OBJEXT): {$(VPATH)}internal/globals.h +ast.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +ast.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +ast.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +ast.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +ast.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +ast.$(OBJEXT): {$(VPATH)}internal/has/extension.h +ast.$(OBJEXT): {$(VPATH)}internal/has/feature.h +ast.$(OBJEXT): {$(VPATH)}internal/has/warning.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/array.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/class.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/error.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/file.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/io.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/load.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/object.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/process.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/random.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/range.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/string.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/time.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +ast.$(OBJEXT): {$(VPATH)}internal/interpreter.h +ast.$(OBJEXT): {$(VPATH)}internal/iterator.h +ast.$(OBJEXT): {$(VPATH)}internal/memory.h +ast.$(OBJEXT): {$(VPATH)}internal/method.h +ast.$(OBJEXT): {$(VPATH)}internal/module.h +ast.$(OBJEXT): {$(VPATH)}internal/newobj.h +ast.$(OBJEXT): {$(VPATH)}internal/rgengc.h +ast.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +ast.$(OBJEXT): {$(VPATH)}internal/value.h +ast.$(OBJEXT): {$(VPATH)}internal/value_type.h +ast.$(OBJEXT): {$(VPATH)}internal/variable.h +ast.$(OBJEXT): {$(VPATH)}internal/warning_push.h +ast.$(OBJEXT): {$(VPATH)}internal/xmalloc.h ast.$(OBJEXT): {$(VPATH)}iseq.h ast.$(OBJEXT): {$(VPATH)}method.h ast.$(OBJEXT): {$(VPATH)}missing.h @@ -1645,15 +2131,179 @@ ast.$(OBJEXT): {$(VPATH)}thread_native.h ast.$(OBJEXT): {$(VPATH)}util.h ast.$(OBJEXT): {$(VPATH)}vm_core.h ast.$(OBJEXT): {$(VPATH)}vm_opts.h -bignum.$(OBJEXT): $(hdrdir)/ruby.h bignum.$(OBJEXT): $(hdrdir)/ruby/ruby.h +bignum.$(OBJEXT): $(top_srcdir)/internal/bignum.h +bignum.$(OBJEXT): $(top_srcdir)/internal/bits.h +bignum.$(OBJEXT): $(top_srcdir)/internal/class.h +bignum.$(OBJEXT): $(top_srcdir)/internal/compilers.h +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/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/static_assert.h +bignum.$(OBJEXT): $(top_srcdir)/internal/variable.h +bignum.$(OBJEXT): $(top_srcdir)/internal/vm.h +bignum.$(OBJEXT): $(top_srcdir)/internal/warnings.h bignum.$(OBJEXT): {$(VPATH)}assert.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/assume.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/bool.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/limits.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +bignum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h bignum.$(OBJEXT): {$(VPATH)}bignum.c bignum.$(OBJEXT): {$(VPATH)}config.h +bignum.$(OBJEXT): {$(VPATH)}constant.h bignum.$(OBJEXT): {$(VPATH)}defines.h bignum.$(OBJEXT): {$(VPATH)}id.h +bignum.$(OBJEXT): {$(VPATH)}id_table.h bignum.$(OBJEXT): {$(VPATH)}intern.h bignum.$(OBJEXT): {$(VPATH)}internal.h +bignum.$(OBJEXT): {$(VPATH)}internal/anyargs.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +bignum.$(OBJEXT): {$(VPATH)}internal/assume.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/const.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/error.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/format.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +bignum.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +bignum.$(OBJEXT): {$(VPATH)}internal/cast.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +bignum.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +bignum.$(OBJEXT): {$(VPATH)}internal/config.h +bignum.$(OBJEXT): {$(VPATH)}internal/constant_p.h +bignum.$(OBJEXT): {$(VPATH)}internal/core.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/robject.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +bignum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +bignum.$(OBJEXT): {$(VPATH)}internal/ctype.h +bignum.$(OBJEXT): {$(VPATH)}internal/dllexport.h +bignum.$(OBJEXT): {$(VPATH)}internal/dosish.h +bignum.$(OBJEXT): {$(VPATH)}internal/error.h +bignum.$(OBJEXT): {$(VPATH)}internal/eval.h +bignum.$(OBJEXT): {$(VPATH)}internal/event.h +bignum.$(OBJEXT): {$(VPATH)}internal/fl_type.h +bignum.$(OBJEXT): {$(VPATH)}internal/gc.h +bignum.$(OBJEXT): {$(VPATH)}internal/glob.h +bignum.$(OBJEXT): {$(VPATH)}internal/globals.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/extension.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/feature.h +bignum.$(OBJEXT): {$(VPATH)}internal/has/warning.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/array.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/class.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/error.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/file.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/io.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/load.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/object.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/process.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/random.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/range.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/string.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/time.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +bignum.$(OBJEXT): {$(VPATH)}internal/interpreter.h +bignum.$(OBJEXT): {$(VPATH)}internal/iterator.h +bignum.$(OBJEXT): {$(VPATH)}internal/memory.h +bignum.$(OBJEXT): {$(VPATH)}internal/method.h +bignum.$(OBJEXT): {$(VPATH)}internal/module.h +bignum.$(OBJEXT): {$(VPATH)}internal/newobj.h +bignum.$(OBJEXT): {$(VPATH)}internal/rgengc.h +bignum.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +bignum.$(OBJEXT): {$(VPATH)}internal/value.h +bignum.$(OBJEXT): {$(VPATH)}internal/value_type.h +bignum.$(OBJEXT): {$(VPATH)}internal/variable.h +bignum.$(OBJEXT): {$(VPATH)}internal/warning_push.h +bignum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h bignum.$(OBJEXT): {$(VPATH)}missing.h bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h bignum.$(OBJEXT): {$(VPATH)}st.h @@ -1664,17 +2314,174 @@ builtin.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h builtin.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h builtin.$(OBJEXT): $(CCAN_DIR)/list/list.h builtin.$(OBJEXT): $(CCAN_DIR)/str/str.h -builtin.$(OBJEXT): $(hdrdir)/ruby.h builtin.$(OBJEXT): $(hdrdir)/ruby/ruby.h +builtin.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.h +builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h +builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h builtin.$(OBJEXT): {$(VPATH)}assert.h +builtin.$(OBJEXT): {$(VPATH)}atomic.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/bool.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/limits.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +builtin.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h builtin.$(OBJEXT): {$(VPATH)}builtin.c builtin.$(OBJEXT): {$(VPATH)}builtin.h builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc builtin.$(OBJEXT): {$(VPATH)}config.h +builtin.$(OBJEXT): {$(VPATH)}darray.h builtin.$(OBJEXT): {$(VPATH)}defines.h builtin.$(OBJEXT): {$(VPATH)}id.h builtin.$(OBJEXT): {$(VPATH)}intern.h builtin.$(OBJEXT): {$(VPATH)}internal.h +builtin.$(OBJEXT): {$(VPATH)}internal/anyargs.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +builtin.$(OBJEXT): {$(VPATH)}internal/assume.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/const.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/error.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/format.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +builtin.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +builtin.$(OBJEXT): {$(VPATH)}internal/cast.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +builtin.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +builtin.$(OBJEXT): {$(VPATH)}internal/config.h +builtin.$(OBJEXT): {$(VPATH)}internal/constant_p.h +builtin.$(OBJEXT): {$(VPATH)}internal/core.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/robject.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +builtin.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +builtin.$(OBJEXT): {$(VPATH)}internal/ctype.h +builtin.$(OBJEXT): {$(VPATH)}internal/dllexport.h +builtin.$(OBJEXT): {$(VPATH)}internal/dosish.h +builtin.$(OBJEXT): {$(VPATH)}internal/error.h +builtin.$(OBJEXT): {$(VPATH)}internal/eval.h +builtin.$(OBJEXT): {$(VPATH)}internal/event.h +builtin.$(OBJEXT): {$(VPATH)}internal/fl_type.h +builtin.$(OBJEXT): {$(VPATH)}internal/gc.h +builtin.$(OBJEXT): {$(VPATH)}internal/glob.h +builtin.$(OBJEXT): {$(VPATH)}internal/globals.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/extension.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/feature.h +builtin.$(OBJEXT): {$(VPATH)}internal/has/warning.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/array.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/class.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/error.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/file.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/io.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/load.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/object.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/process.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/random.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/range.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/string.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/time.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +builtin.$(OBJEXT): {$(VPATH)}internal/interpreter.h +builtin.$(OBJEXT): {$(VPATH)}internal/iterator.h +builtin.$(OBJEXT): {$(VPATH)}internal/memory.h +builtin.$(OBJEXT): {$(VPATH)}internal/method.h +builtin.$(OBJEXT): {$(VPATH)}internal/module.h +builtin.$(OBJEXT): {$(VPATH)}internal/newobj.h +builtin.$(OBJEXT): {$(VPATH)}internal/rgengc.h +builtin.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +builtin.$(OBJEXT): {$(VPATH)}internal/value.h +builtin.$(OBJEXT): {$(VPATH)}internal/value_type.h +builtin.$(OBJEXT): {$(VPATH)}internal/variable.h +builtin.$(OBJEXT): {$(VPATH)}internal/warning_push.h +builtin.$(OBJEXT): {$(VPATH)}internal/xmalloc.h builtin.$(OBJEXT): {$(VPATH)}iseq.h builtin.$(OBJEXT): {$(VPATH)}method.h builtin.$(OBJEXT): {$(VPATH)}missing.h @@ -1691,20 +2498,196 @@ class.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h class.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h class.$(OBJEXT): $(CCAN_DIR)/list/list.h class.$(OBJEXT): $(CCAN_DIR)/str/str.h -class.$(OBJEXT): $(hdrdir)/ruby.h class.$(OBJEXT): $(hdrdir)/ruby/ruby.h +class.$(OBJEXT): $(top_srcdir)/internal/array.h +class.$(OBJEXT): $(top_srcdir)/internal/class.h +class.$(OBJEXT): $(top_srcdir)/internal/compilers.h +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/object.h +class.$(OBJEXT): $(top_srcdir)/internal/serial.h +class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +class.$(OBJEXT): $(top_srcdir)/internal/string.h +class.$(OBJEXT): $(top_srcdir)/internal/variable.h +class.$(OBJEXT): $(top_srcdir)/internal/vm.h +class.$(OBJEXT): $(top_srcdir)/internal/warnings.h class.$(OBJEXT): {$(VPATH)}assert.h +class.$(OBJEXT): {$(VPATH)}atomic.h +class.$(OBJEXT): {$(VPATH)}backward/2/assume.h +class.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +class.$(OBJEXT): {$(VPATH)}backward/2/bool.h +class.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +class.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +class.$(OBJEXT): {$(VPATH)}backward/2/limits.h +class.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +class.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +class.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h class.$(OBJEXT): {$(VPATH)}class.c class.$(OBJEXT): {$(VPATH)}config.h class.$(OBJEXT): {$(VPATH)}constant.h +class.$(OBJEXT): {$(VPATH)}darray.h +class.$(OBJEXT): {$(VPATH)}debug_counter.h class.$(OBJEXT): {$(VPATH)}defines.h +class.$(OBJEXT): {$(VPATH)}encoding.h class.$(OBJEXT): {$(VPATH)}id.h class.$(OBJEXT): {$(VPATH)}id_table.h class.$(OBJEXT): {$(VPATH)}intern.h class.$(OBJEXT): {$(VPATH)}internal.h +class.$(OBJEXT): {$(VPATH)}internal/anyargs.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +class.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +class.$(OBJEXT): {$(VPATH)}internal/assume.h +class.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +class.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +class.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +class.$(OBJEXT): {$(VPATH)}internal/attr/const.h +class.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +class.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +class.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +class.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +class.$(OBJEXT): {$(VPATH)}internal/attr/error.h +class.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +class.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +class.$(OBJEXT): {$(VPATH)}internal/attr/format.h +class.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +class.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +class.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +class.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +class.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +class.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +class.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +class.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +class.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +class.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +class.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +class.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +class.$(OBJEXT): {$(VPATH)}internal/cast.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +class.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +class.$(OBJEXT): {$(VPATH)}internal/config.h +class.$(OBJEXT): {$(VPATH)}internal/constant_p.h +class.$(OBJEXT): {$(VPATH)}internal/core.h +class.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +class.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +class.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +class.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +class.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +class.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +class.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +class.$(OBJEXT): {$(VPATH)}internal/core/robject.h +class.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +class.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +class.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +class.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +class.$(OBJEXT): {$(VPATH)}internal/ctype.h +class.$(OBJEXT): {$(VPATH)}internal/dllexport.h +class.$(OBJEXT): {$(VPATH)}internal/dosish.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +class.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +class.$(OBJEXT): {$(VPATH)}internal/error.h +class.$(OBJEXT): {$(VPATH)}internal/eval.h +class.$(OBJEXT): {$(VPATH)}internal/event.h +class.$(OBJEXT): {$(VPATH)}internal/fl_type.h +class.$(OBJEXT): {$(VPATH)}internal/gc.h +class.$(OBJEXT): {$(VPATH)}internal/glob.h +class.$(OBJEXT): {$(VPATH)}internal/globals.h +class.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +class.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +class.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +class.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +class.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +class.$(OBJEXT): {$(VPATH)}internal/has/extension.h +class.$(OBJEXT): {$(VPATH)}internal/has/feature.h +class.$(OBJEXT): {$(VPATH)}internal/has/warning.h +class.$(OBJEXT): {$(VPATH)}internal/intern/array.h +class.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +class.$(OBJEXT): {$(VPATH)}internal/intern/class.h +class.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +class.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +class.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +class.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +class.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +class.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +class.$(OBJEXT): {$(VPATH)}internal/intern/error.h +class.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +class.$(OBJEXT): {$(VPATH)}internal/intern/file.h +class.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +class.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +class.$(OBJEXT): {$(VPATH)}internal/intern/io.h +class.$(OBJEXT): {$(VPATH)}internal/intern/load.h +class.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +class.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +class.$(OBJEXT): {$(VPATH)}internal/intern/object.h +class.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +class.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +class.$(OBJEXT): {$(VPATH)}internal/intern/process.h +class.$(OBJEXT): {$(VPATH)}internal/intern/random.h +class.$(OBJEXT): {$(VPATH)}internal/intern/range.h +class.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +class.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +class.$(OBJEXT): {$(VPATH)}internal/intern/string.h +class.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +class.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +class.$(OBJEXT): {$(VPATH)}internal/intern/time.h +class.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +class.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +class.$(OBJEXT): {$(VPATH)}internal/interpreter.h +class.$(OBJEXT): {$(VPATH)}internal/iterator.h +class.$(OBJEXT): {$(VPATH)}internal/memory.h +class.$(OBJEXT): {$(VPATH)}internal/method.h +class.$(OBJEXT): {$(VPATH)}internal/module.h +class.$(OBJEXT): {$(VPATH)}internal/newobj.h +class.$(OBJEXT): {$(VPATH)}internal/rgengc.h +class.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +class.$(OBJEXT): {$(VPATH)}internal/value.h +class.$(OBJEXT): {$(VPATH)}internal/value_type.h +class.$(OBJEXT): {$(VPATH)}internal/variable.h +class.$(OBJEXT): {$(VPATH)}internal/warning_push.h +class.$(OBJEXT): {$(VPATH)}internal/xmalloc.h class.$(OBJEXT): {$(VPATH)}method.h class.$(OBJEXT): {$(VPATH)}missing.h class.$(OBJEXT): {$(VPATH)}node.h +class.$(OBJEXT): {$(VPATH)}onigmo.h +class.$(OBJEXT): {$(VPATH)}oniguruma.h class.$(OBJEXT): {$(VPATH)}ruby_assert.h class.$(OBJEXT): {$(VPATH)}ruby_atomic.h class.$(OBJEXT): {$(VPATH)}st.h @@ -1713,28 +2696,231 @@ class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h class.$(OBJEXT): {$(VPATH)}thread_native.h class.$(OBJEXT): {$(VPATH)}vm_core.h class.$(OBJEXT): {$(VPATH)}vm_opts.h -compar.$(OBJEXT): $(hdrdir)/ruby.h compar.$(OBJEXT): $(hdrdir)/ruby/ruby.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/static_assert.h +compar.$(OBJEXT): $(top_srcdir)/internal/string.h +compar.$(OBJEXT): $(top_srcdir)/internal/vm.h compar.$(OBJEXT): {$(VPATH)}assert.h +compar.$(OBJEXT): {$(VPATH)}backward/2/assume.h +compar.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +compar.$(OBJEXT): {$(VPATH)}backward/2/bool.h +compar.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +compar.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +compar.$(OBJEXT): {$(VPATH)}backward/2/limits.h +compar.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +compar.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +compar.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h compar.$(OBJEXT): {$(VPATH)}compar.c compar.$(OBJEXT): {$(VPATH)}config.h compar.$(OBJEXT): {$(VPATH)}defines.h +compar.$(OBJEXT): {$(VPATH)}encoding.h compar.$(OBJEXT): {$(VPATH)}id.h compar.$(OBJEXT): {$(VPATH)}intern.h compar.$(OBJEXT): {$(VPATH)}internal.h +compar.$(OBJEXT): {$(VPATH)}internal/anyargs.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +compar.$(OBJEXT): {$(VPATH)}internal/assume.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/const.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/error.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/format.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +compar.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +compar.$(OBJEXT): {$(VPATH)}internal/cast.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +compar.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +compar.$(OBJEXT): {$(VPATH)}internal/config.h +compar.$(OBJEXT): {$(VPATH)}internal/constant_p.h +compar.$(OBJEXT): {$(VPATH)}internal/core.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +compar.$(OBJEXT): {$(VPATH)}internal/core/robject.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +compar.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +compar.$(OBJEXT): {$(VPATH)}internal/ctype.h +compar.$(OBJEXT): {$(VPATH)}internal/dllexport.h +compar.$(OBJEXT): {$(VPATH)}internal/dosish.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +compar.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +compar.$(OBJEXT): {$(VPATH)}internal/error.h +compar.$(OBJEXT): {$(VPATH)}internal/eval.h +compar.$(OBJEXT): {$(VPATH)}internal/event.h +compar.$(OBJEXT): {$(VPATH)}internal/fl_type.h +compar.$(OBJEXT): {$(VPATH)}internal/gc.h +compar.$(OBJEXT): {$(VPATH)}internal/glob.h +compar.$(OBJEXT): {$(VPATH)}internal/globals.h +compar.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +compar.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +compar.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +compar.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +compar.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +compar.$(OBJEXT): {$(VPATH)}internal/has/extension.h +compar.$(OBJEXT): {$(VPATH)}internal/has/feature.h +compar.$(OBJEXT): {$(VPATH)}internal/has/warning.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/array.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/class.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/error.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/file.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/io.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/load.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/object.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/process.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/random.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/range.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/string.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/time.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +compar.$(OBJEXT): {$(VPATH)}internal/interpreter.h +compar.$(OBJEXT): {$(VPATH)}internal/iterator.h +compar.$(OBJEXT): {$(VPATH)}internal/memory.h +compar.$(OBJEXT): {$(VPATH)}internal/method.h +compar.$(OBJEXT): {$(VPATH)}internal/module.h +compar.$(OBJEXT): {$(VPATH)}internal/newobj.h +compar.$(OBJEXT): {$(VPATH)}internal/rgengc.h +compar.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +compar.$(OBJEXT): {$(VPATH)}internal/value.h +compar.$(OBJEXT): {$(VPATH)}internal/value_type.h +compar.$(OBJEXT): {$(VPATH)}internal/variable.h +compar.$(OBJEXT): {$(VPATH)}internal/warning_push.h +compar.$(OBJEXT): {$(VPATH)}internal/xmalloc.h compar.$(OBJEXT): {$(VPATH)}missing.h +compar.$(OBJEXT): {$(VPATH)}onigmo.h +compar.$(OBJEXT): {$(VPATH)}oniguruma.h compar.$(OBJEXT): {$(VPATH)}st.h compar.$(OBJEXT): {$(VPATH)}subst.h compile.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h +compile.$(OBJEXT): $(top_srcdir)/internal/array.h +compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h +compile.$(OBJEXT): $(top_srcdir)/internal/bits.h +compile.$(OBJEXT): $(top_srcdir)/internal/class.h +compile.$(OBJEXT): $(top_srcdir)/internal/compile.h +compile.$(OBJEXT): $(top_srcdir)/internal/compilers.h +compile.$(OBJEXT): $(top_srcdir)/internal/complex.h +compile.$(OBJEXT): $(top_srcdir)/internal/encoding.h +compile.$(OBJEXT): $(top_srcdir)/internal/error.h +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/numeric.h +compile.$(OBJEXT): $(top_srcdir)/internal/object.h +compile.$(OBJEXT): $(top_srcdir)/internal/rational.h +compile.$(OBJEXT): $(top_srcdir)/internal/re.h +compile.$(OBJEXT): $(top_srcdir)/internal/serial.h +compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +compile.$(OBJEXT): $(top_srcdir)/internal/string.h +compile.$(OBJEXT): $(top_srcdir)/internal/symbol.h +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): {$(VPATH)}assert.h +compile.$(OBJEXT): {$(VPATH)}atomic.h +compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h +compile.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +compile.$(OBJEXT): {$(VPATH)}backward/2/bool.h +compile.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +compile.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +compile.$(OBJEXT): {$(VPATH)}backward/2/limits.h +compile.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +compile.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +compile.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h compile.$(OBJEXT): {$(VPATH)}builtin.h compile.$(OBJEXT): {$(VPATH)}compile.c compile.$(OBJEXT): {$(VPATH)}config.h +compile.$(OBJEXT): {$(VPATH)}constant.h +compile.$(OBJEXT): {$(VPATH)}darray.h +compile.$(OBJEXT): {$(VPATH)}debug_counter.h compile.$(OBJEXT): {$(VPATH)}defines.h compile.$(OBJEXT): {$(VPATH)}encindex.h compile.$(OBJEXT): {$(VPATH)}encoding.h @@ -1746,15 +2932,162 @@ compile.$(OBJEXT): {$(VPATH)}insns.inc compile.$(OBJEXT): {$(VPATH)}insns_info.inc compile.$(OBJEXT): {$(VPATH)}intern.h compile.$(OBJEXT): {$(VPATH)}internal.h +compile.$(OBJEXT): {$(VPATH)}internal/anyargs.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +compile.$(OBJEXT): {$(VPATH)}internal/assume.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/const.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/error.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/format.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +compile.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +compile.$(OBJEXT): {$(VPATH)}internal/cast.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +compile.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +compile.$(OBJEXT): {$(VPATH)}internal/config.h +compile.$(OBJEXT): {$(VPATH)}internal/constant_p.h +compile.$(OBJEXT): {$(VPATH)}internal/core.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h +compile.$(OBJEXT): {$(VPATH)}internal/core/robject.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +compile.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +compile.$(OBJEXT): {$(VPATH)}internal/ctype.h +compile.$(OBJEXT): {$(VPATH)}internal/dllexport.h +compile.$(OBJEXT): {$(VPATH)}internal/dosish.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +compile.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +compile.$(OBJEXT): {$(VPATH)}internal/error.h +compile.$(OBJEXT): {$(VPATH)}internal/eval.h +compile.$(OBJEXT): {$(VPATH)}internal/event.h +compile.$(OBJEXT): {$(VPATH)}internal/fl_type.h +compile.$(OBJEXT): {$(VPATH)}internal/gc.h +compile.$(OBJEXT): {$(VPATH)}internal/glob.h +compile.$(OBJEXT): {$(VPATH)}internal/globals.h +compile.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +compile.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +compile.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +compile.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +compile.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +compile.$(OBJEXT): {$(VPATH)}internal/has/extension.h +compile.$(OBJEXT): {$(VPATH)}internal/has/feature.h +compile.$(OBJEXT): {$(VPATH)}internal/has/warning.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/array.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/class.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/error.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/file.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/io.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/load.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/object.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/process.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/random.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/range.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/string.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/time.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +compile.$(OBJEXT): {$(VPATH)}internal/interpreter.h +compile.$(OBJEXT): {$(VPATH)}internal/iterator.h +compile.$(OBJEXT): {$(VPATH)}internal/memory.h +compile.$(OBJEXT): {$(VPATH)}internal/method.h +compile.$(OBJEXT): {$(VPATH)}internal/module.h +compile.$(OBJEXT): {$(VPATH)}internal/newobj.h +compile.$(OBJEXT): {$(VPATH)}internal/rgengc.h +compile.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/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)}iseq.h compile.$(OBJEXT): {$(VPATH)}method.h compile.$(OBJEXT): {$(VPATH)}missing.h compile.$(OBJEXT): {$(VPATH)}node.h compile.$(OBJEXT): {$(VPATH)}onigmo.h compile.$(OBJEXT): {$(VPATH)}oniguruma.h -compile.$(OBJEXT): {$(VPATH)}opt_sc.inc compile.$(OBJEXT): {$(VPATH)}optinsn.inc -compile.$(OBJEXT): {$(VPATH)}optunifs.inc compile.$(OBJEXT): {$(VPATH)}re.h compile.$(OBJEXT): {$(VPATH)}regex.h compile.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -1764,18 +3097,183 @@ compile.$(OBJEXT): {$(VPATH)}subst.h compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h compile.$(OBJEXT): {$(VPATH)}thread_native.h compile.$(OBJEXT): {$(VPATH)}util.h +compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h compile.$(OBJEXT): {$(VPATH)}vm_core.h compile.$(OBJEXT): {$(VPATH)}vm_debug.h compile.$(OBJEXT): {$(VPATH)}vm_opts.h -complex.$(OBJEXT): $(hdrdir)/ruby.h complex.$(OBJEXT): $(hdrdir)/ruby/ruby.h +complex.$(OBJEXT): $(top_srcdir)/internal/array.h +complex.$(OBJEXT): $(top_srcdir)/internal/bignum.h +complex.$(OBJEXT): $(top_srcdir)/internal/bits.h +complex.$(OBJEXT): $(top_srcdir)/internal/class.h +complex.$(OBJEXT): $(top_srcdir)/internal/compilers.h +complex.$(OBJEXT): $(top_srcdir)/internal/complex.h +complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +complex.$(OBJEXT): $(top_srcdir)/internal/gc.h +complex.$(OBJEXT): $(top_srcdir)/internal/math.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/serial.h +complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +complex.$(OBJEXT): $(top_srcdir)/internal/vm.h +complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h complex.$(OBJEXT): {$(VPATH)}assert.h +complex.$(OBJEXT): {$(VPATH)}backward/2/assume.h +complex.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +complex.$(OBJEXT): {$(VPATH)}backward/2/bool.h +complex.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +complex.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +complex.$(OBJEXT): {$(VPATH)}backward/2/limits.h +complex.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +complex.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h complex.$(OBJEXT): {$(VPATH)}complex.c complex.$(OBJEXT): {$(VPATH)}config.h complex.$(OBJEXT): {$(VPATH)}defines.h complex.$(OBJEXT): {$(VPATH)}id.h +complex.$(OBJEXT): {$(VPATH)}id_table.h complex.$(OBJEXT): {$(VPATH)}intern.h complex.$(OBJEXT): {$(VPATH)}internal.h +complex.$(OBJEXT): {$(VPATH)}internal/anyargs.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +complex.$(OBJEXT): {$(VPATH)}internal/assume.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/const.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/error.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/format.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +complex.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +complex.$(OBJEXT): {$(VPATH)}internal/cast.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +complex.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +complex.$(OBJEXT): {$(VPATH)}internal/config.h +complex.$(OBJEXT): {$(VPATH)}internal/constant_p.h +complex.$(OBJEXT): {$(VPATH)}internal/core.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +complex.$(OBJEXT): {$(VPATH)}internal/core/robject.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +complex.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +complex.$(OBJEXT): {$(VPATH)}internal/ctype.h +complex.$(OBJEXT): {$(VPATH)}internal/dllexport.h +complex.$(OBJEXT): {$(VPATH)}internal/dosish.h +complex.$(OBJEXT): {$(VPATH)}internal/error.h +complex.$(OBJEXT): {$(VPATH)}internal/eval.h +complex.$(OBJEXT): {$(VPATH)}internal/event.h +complex.$(OBJEXT): {$(VPATH)}internal/fl_type.h +complex.$(OBJEXT): {$(VPATH)}internal/gc.h +complex.$(OBJEXT): {$(VPATH)}internal/glob.h +complex.$(OBJEXT): {$(VPATH)}internal/globals.h +complex.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +complex.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +complex.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +complex.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +complex.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +complex.$(OBJEXT): {$(VPATH)}internal/has/extension.h +complex.$(OBJEXT): {$(VPATH)}internal/has/feature.h +complex.$(OBJEXT): {$(VPATH)}internal/has/warning.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/array.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/class.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/error.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/file.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/io.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/load.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/object.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/process.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/random.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/range.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/string.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/time.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +complex.$(OBJEXT): {$(VPATH)}internal/interpreter.h +complex.$(OBJEXT): {$(VPATH)}internal/iterator.h +complex.$(OBJEXT): {$(VPATH)}internal/memory.h +complex.$(OBJEXT): {$(VPATH)}internal/method.h +complex.$(OBJEXT): {$(VPATH)}internal/module.h +complex.$(OBJEXT): {$(VPATH)}internal/newobj.h +complex.$(OBJEXT): {$(VPATH)}internal/rgengc.h +complex.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +complex.$(OBJEXT): {$(VPATH)}internal/value.h +complex.$(OBJEXT): {$(VPATH)}internal/value_type.h +complex.$(OBJEXT): {$(VPATH)}internal/variable.h +complex.$(OBJEXT): {$(VPATH)}internal/warning_push.h +complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h complex.$(OBJEXT): {$(VPATH)}missing.h complex.$(OBJEXT): {$(VPATH)}ruby_assert.h complex.$(OBJEXT): {$(VPATH)}st.h @@ -1786,21 +3284,185 @@ 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): $(top_srcdir)/internal/array.h +cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h +cont.$(OBJEXT): $(top_srcdir)/internal/cont.h +cont.$(OBJEXT): $(top_srcdir)/internal/gc.h +cont.$(OBJEXT): $(top_srcdir)/internal/imemo.h +cont.$(OBJEXT): $(top_srcdir)/internal/proc.h +cont.$(OBJEXT): $(top_srcdir)/internal/serial.h +cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +cont.$(OBJEXT): $(top_srcdir)/internal/vm.h +cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H) cont.$(OBJEXT): {$(VPATH)}assert.h +cont.$(OBJEXT): {$(VPATH)}atomic.h +cont.$(OBJEXT): {$(VPATH)}backward/2/assume.h +cont.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +cont.$(OBJEXT): {$(VPATH)}backward/2/bool.h +cont.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +cont.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +cont.$(OBJEXT): {$(VPATH)}backward/2/limits.h +cont.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +cont.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +cont.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h cont.$(OBJEXT): {$(VPATH)}config.h cont.$(OBJEXT): {$(VPATH)}cont.c +cont.$(OBJEXT): {$(VPATH)}darray.h cont.$(OBJEXT): {$(VPATH)}debug_counter.h cont.$(OBJEXT): {$(VPATH)}defines.h cont.$(OBJEXT): {$(VPATH)}eval_intern.h +cont.$(OBJEXT): {$(VPATH)}fiber/scheduler.h cont.$(OBJEXT): {$(VPATH)}gc.h cont.$(OBJEXT): {$(VPATH)}id.h +cont.$(OBJEXT): {$(VPATH)}id_table.h cont.$(OBJEXT): {$(VPATH)}intern.h cont.$(OBJEXT): {$(VPATH)}internal.h +cont.$(OBJEXT): {$(VPATH)}internal/anyargs.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +cont.$(OBJEXT): {$(VPATH)}internal/assume.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/const.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/error.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/format.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +cont.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +cont.$(OBJEXT): {$(VPATH)}internal/cast.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +cont.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +cont.$(OBJEXT): {$(VPATH)}internal/config.h +cont.$(OBJEXT): {$(VPATH)}internal/constant_p.h +cont.$(OBJEXT): {$(VPATH)}internal/core.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +cont.$(OBJEXT): {$(VPATH)}internal/core/robject.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +cont.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +cont.$(OBJEXT): {$(VPATH)}internal/ctype.h +cont.$(OBJEXT): {$(VPATH)}internal/dllexport.h +cont.$(OBJEXT): {$(VPATH)}internal/dosish.h +cont.$(OBJEXT): {$(VPATH)}internal/error.h +cont.$(OBJEXT): {$(VPATH)}internal/eval.h +cont.$(OBJEXT): {$(VPATH)}internal/event.h +cont.$(OBJEXT): {$(VPATH)}internal/fl_type.h +cont.$(OBJEXT): {$(VPATH)}internal/gc.h +cont.$(OBJEXT): {$(VPATH)}internal/glob.h +cont.$(OBJEXT): {$(VPATH)}internal/globals.h +cont.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +cont.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +cont.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +cont.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +cont.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +cont.$(OBJEXT): {$(VPATH)}internal/has/extension.h +cont.$(OBJEXT): {$(VPATH)}internal/has/feature.h +cont.$(OBJEXT): {$(VPATH)}internal/has/warning.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/array.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/class.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/error.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/file.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/io.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/load.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/object.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/process.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/random.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/range.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/string.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/time.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +cont.$(OBJEXT): {$(VPATH)}internal/interpreter.h +cont.$(OBJEXT): {$(VPATH)}internal/iterator.h +cont.$(OBJEXT): {$(VPATH)}internal/memory.h +cont.$(OBJEXT): {$(VPATH)}internal/method.h +cont.$(OBJEXT): {$(VPATH)}internal/module.h +cont.$(OBJEXT): {$(VPATH)}internal/newobj.h +cont.$(OBJEXT): {$(VPATH)}internal/rgengc.h +cont.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +cont.$(OBJEXT): {$(VPATH)}internal/value.h +cont.$(OBJEXT): {$(VPATH)}internal/value_type.h +cont.$(OBJEXT): {$(VPATH)}internal/variable.h +cont.$(OBJEXT): {$(VPATH)}internal/warning_push.h +cont.$(OBJEXT): {$(VPATH)}internal/xmalloc.h cont.$(OBJEXT): {$(VPATH)}method.h cont.$(OBJEXT): {$(VPATH)}missing.h cont.$(OBJEXT): {$(VPATH)}mjit.h cont.$(OBJEXT): {$(VPATH)}node.h +cont.$(OBJEXT): {$(VPATH)}ractor.h +cont.$(OBJEXT): {$(VPATH)}ractor_core.h cont.$(OBJEXT): {$(VPATH)}ruby_assert.h cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h cont.$(OBJEXT): {$(VPATH)}st.h @@ -1808,29 +3470,203 @@ cont.$(OBJEXT): {$(VPATH)}subst.h cont.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h cont.$(OBJEXT): {$(VPATH)}thread_native.h cont.$(OBJEXT): {$(VPATH)}vm_core.h +cont.$(OBJEXT): {$(VPATH)}vm_debug.h cont.$(OBJEXT): {$(VPATH)}vm_opts.h +cont.$(OBJEXT): {$(VPATH)}yjit.h debug.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h debug.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h debug.$(OBJEXT): $(CCAN_DIR)/list/list.h debug.$(OBJEXT): $(CCAN_DIR)/str/str.h -debug.$(OBJEXT): $(hdrdir)/ruby.h debug.$(OBJEXT): $(hdrdir)/ruby/ruby.h +debug.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.h +debug.$(OBJEXT): $(top_srcdir)/internal/signal.h +debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +debug.$(OBJEXT): $(top_srcdir)/internal/vm.h +debug.$(OBJEXT): $(top_srcdir)/internal/warnings.h debug.$(OBJEXT): {$(VPATH)}assert.h +debug.$(OBJEXT): {$(VPATH)}atomic.h +debug.$(OBJEXT): {$(VPATH)}backward/2/assume.h +debug.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +debug.$(OBJEXT): {$(VPATH)}backward/2/bool.h +debug.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +debug.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +debug.$(OBJEXT): {$(VPATH)}backward/2/limits.h +debug.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +debug.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +debug.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h debug.$(OBJEXT): {$(VPATH)}config.h +debug.$(OBJEXT): {$(VPATH)}darray.h debug.$(OBJEXT): {$(VPATH)}debug.c +debug.$(OBJEXT): {$(VPATH)}debug_counter.h debug.$(OBJEXT): {$(VPATH)}defines.h +debug.$(OBJEXT): {$(VPATH)}encindex.h debug.$(OBJEXT): {$(VPATH)}encoding.h debug.$(OBJEXT): {$(VPATH)}eval_intern.h debug.$(OBJEXT): {$(VPATH)}gc.h debug.$(OBJEXT): {$(VPATH)}id.h +debug.$(OBJEXT): {$(VPATH)}id_table.h debug.$(OBJEXT): {$(VPATH)}intern.h debug.$(OBJEXT): {$(VPATH)}internal.h +debug.$(OBJEXT): {$(VPATH)}internal/anyargs.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +debug.$(OBJEXT): {$(VPATH)}internal/assume.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/const.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/error.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/format.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +debug.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +debug.$(OBJEXT): {$(VPATH)}internal/cast.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +debug.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +debug.$(OBJEXT): {$(VPATH)}internal/config.h +debug.$(OBJEXT): {$(VPATH)}internal/constant_p.h +debug.$(OBJEXT): {$(VPATH)}internal/core.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +debug.$(OBJEXT): {$(VPATH)}internal/core/robject.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +debug.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +debug.$(OBJEXT): {$(VPATH)}internal/ctype.h +debug.$(OBJEXT): {$(VPATH)}internal/dllexport.h +debug.$(OBJEXT): {$(VPATH)}internal/dosish.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +debug.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +debug.$(OBJEXT): {$(VPATH)}internal/error.h +debug.$(OBJEXT): {$(VPATH)}internal/eval.h +debug.$(OBJEXT): {$(VPATH)}internal/event.h +debug.$(OBJEXT): {$(VPATH)}internal/fl_type.h +debug.$(OBJEXT): {$(VPATH)}internal/gc.h +debug.$(OBJEXT): {$(VPATH)}internal/glob.h +debug.$(OBJEXT): {$(VPATH)}internal/globals.h +debug.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +debug.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +debug.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +debug.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +debug.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +debug.$(OBJEXT): {$(VPATH)}internal/has/extension.h +debug.$(OBJEXT): {$(VPATH)}internal/has/feature.h +debug.$(OBJEXT): {$(VPATH)}internal/has/warning.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/array.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/class.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/error.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/file.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/io.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/load.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/object.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/process.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/random.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/range.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/string.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/time.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +debug.$(OBJEXT): {$(VPATH)}internal/interpreter.h +debug.$(OBJEXT): {$(VPATH)}internal/iterator.h +debug.$(OBJEXT): {$(VPATH)}internal/memory.h +debug.$(OBJEXT): {$(VPATH)}internal/method.h +debug.$(OBJEXT): {$(VPATH)}internal/module.h +debug.$(OBJEXT): {$(VPATH)}internal/newobj.h +debug.$(OBJEXT): {$(VPATH)}internal/rgengc.h +debug.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +debug.$(OBJEXT): {$(VPATH)}internal/value.h +debug.$(OBJEXT): {$(VPATH)}internal/value_type.h +debug.$(OBJEXT): {$(VPATH)}internal/variable.h +debug.$(OBJEXT): {$(VPATH)}internal/warning_push.h +debug.$(OBJEXT): {$(VPATH)}internal/xmalloc.h debug.$(OBJEXT): {$(VPATH)}io.h debug.$(OBJEXT): {$(VPATH)}method.h debug.$(OBJEXT): {$(VPATH)}missing.h debug.$(OBJEXT): {$(VPATH)}node.h debug.$(OBJEXT): {$(VPATH)}onigmo.h debug.$(OBJEXT): {$(VPATH)}oniguruma.h +debug.$(OBJEXT): {$(VPATH)}ractor.h +debug.$(OBJEXT): {$(VPATH)}ractor_core.h debug.$(OBJEXT): {$(VPATH)}ruby_assert.h debug.$(OBJEXT): {$(VPATH)}ruby_atomic.h debug.$(OBJEXT): {$(VPATH)}st.h @@ -1839,32 +3675,355 @@ debug.$(OBJEXT): {$(VPATH)}symbol.h debug.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h debug.$(OBJEXT): {$(VPATH)}thread_native.h debug.$(OBJEXT): {$(VPATH)}util.h +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_counter.$(OBJEXT): $(hdrdir)/ruby.h debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h debug_counter.$(OBJEXT): {$(VPATH)}assert.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/bool.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/limits.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +debug_counter.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h debug_counter.$(OBJEXT): {$(VPATH)}config.h debug_counter.$(OBJEXT): {$(VPATH)}debug_counter.c debug_counter.$(OBJEXT): {$(VPATH)}debug_counter.h debug_counter.$(OBJEXT): {$(VPATH)}defines.h debug_counter.$(OBJEXT): {$(VPATH)}intern.h debug_counter.$(OBJEXT): {$(VPATH)}internal.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/anyargs.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/assume.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/const.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/error.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/format.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/cast.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/config.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/constant_p.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/robject.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/ctype.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/dllexport.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/dosish.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/error.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/eval.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/event.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/fl_type.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/gc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/glob.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/globals.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/extension.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/feature.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/has/warning.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/array.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/class.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/error.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/file.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/io.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/load.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/object.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/process.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/random.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/range.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/string.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/time.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/interpreter.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/iterator.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/memory.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/method.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/module.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/newobj.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/rgengc.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/value.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/value_type.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/variable.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/warning_push.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/xmalloc.h debug_counter.$(OBJEXT): {$(VPATH)}missing.h debug_counter.$(OBJEXT): {$(VPATH)}st.h debug_counter.$(OBJEXT): {$(VPATH)}subst.h -dir.$(OBJEXT): $(hdrdir)/ruby.h +debug_counter.$(OBJEXT): {$(VPATH)}thread_native.h dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h +dir.$(OBJEXT): $(top_srcdir)/internal/array.h +dir.$(OBJEXT): $(top_srcdir)/internal/class.h +dir.$(OBJEXT): $(top_srcdir)/internal/compilers.h +dir.$(OBJEXT): $(top_srcdir)/internal/dir.h +dir.$(OBJEXT): $(top_srcdir)/internal/encoding.h +dir.$(OBJEXT): $(top_srcdir)/internal/error.h +dir.$(OBJEXT): $(top_srcdir)/internal/file.h +dir.$(OBJEXT): $(top_srcdir)/internal/gc.h +dir.$(OBJEXT): $(top_srcdir)/internal/io.h +dir.$(OBJEXT): $(top_srcdir)/internal/object.h +dir.$(OBJEXT): $(top_srcdir)/internal/serial.h +dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +dir.$(OBJEXT): $(top_srcdir)/internal/string.h +dir.$(OBJEXT): $(top_srcdir)/internal/vm.h +dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h dir.$(OBJEXT): {$(VPATH)}assert.h +dir.$(OBJEXT): {$(VPATH)}backward/2/assume.h +dir.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +dir.$(OBJEXT): {$(VPATH)}backward/2/bool.h +dir.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +dir.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +dir.$(OBJEXT): {$(VPATH)}backward/2/limits.h +dir.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +dir.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +dir.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +dir.$(OBJEXT): {$(VPATH)}builtin.h dir.$(OBJEXT): {$(VPATH)}config.h dir.$(OBJEXT): {$(VPATH)}defines.h dir.$(OBJEXT): {$(VPATH)}dir.c +dir.$(OBJEXT): {$(VPATH)}dir.rbinc dir.$(OBJEXT): {$(VPATH)}encindex.h dir.$(OBJEXT): {$(VPATH)}encoding.h dir.$(OBJEXT): {$(VPATH)}id.h +dir.$(OBJEXT): {$(VPATH)}id_table.h dir.$(OBJEXT): {$(VPATH)}intern.h dir.$(OBJEXT): {$(VPATH)}internal.h +dir.$(OBJEXT): {$(VPATH)}internal/anyargs.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +dir.$(OBJEXT): {$(VPATH)}internal/assume.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/const.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/error.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/format.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +dir.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +dir.$(OBJEXT): {$(VPATH)}internal/cast.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +dir.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +dir.$(OBJEXT): {$(VPATH)}internal/config.h +dir.$(OBJEXT): {$(VPATH)}internal/constant_p.h +dir.$(OBJEXT): {$(VPATH)}internal/core.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +dir.$(OBJEXT): {$(VPATH)}internal/core/robject.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +dir.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +dir.$(OBJEXT): {$(VPATH)}internal/ctype.h +dir.$(OBJEXT): {$(VPATH)}internal/dllexport.h +dir.$(OBJEXT): {$(VPATH)}internal/dosish.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +dir.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +dir.$(OBJEXT): {$(VPATH)}internal/error.h +dir.$(OBJEXT): {$(VPATH)}internal/eval.h +dir.$(OBJEXT): {$(VPATH)}internal/event.h +dir.$(OBJEXT): {$(VPATH)}internal/fl_type.h +dir.$(OBJEXT): {$(VPATH)}internal/gc.h +dir.$(OBJEXT): {$(VPATH)}internal/glob.h +dir.$(OBJEXT): {$(VPATH)}internal/globals.h +dir.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +dir.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +dir.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +dir.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +dir.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +dir.$(OBJEXT): {$(VPATH)}internal/has/extension.h +dir.$(OBJEXT): {$(VPATH)}internal/has/feature.h +dir.$(OBJEXT): {$(VPATH)}internal/has/warning.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/array.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/class.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/error.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/file.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/io.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/load.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/object.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/process.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/random.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/range.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/string.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/time.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +dir.$(OBJEXT): {$(VPATH)}internal/interpreter.h +dir.$(OBJEXT): {$(VPATH)}internal/iterator.h +dir.$(OBJEXT): {$(VPATH)}internal/memory.h +dir.$(OBJEXT): {$(VPATH)}internal/method.h +dir.$(OBJEXT): {$(VPATH)}internal/module.h +dir.$(OBJEXT): {$(VPATH)}internal/newobj.h +dir.$(OBJEXT): {$(VPATH)}internal/rgengc.h +dir.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +dir.$(OBJEXT): {$(VPATH)}internal/value.h +dir.$(OBJEXT): {$(VPATH)}internal/value_type.h +dir.$(OBJEXT): {$(VPATH)}internal/variable.h +dir.$(OBJEXT): {$(VPATH)}internal/warning_push.h +dir.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +dir.$(OBJEXT): {$(VPATH)}io.h dir.$(OBJEXT): {$(VPATH)}missing.h dir.$(OBJEXT): {$(VPATH)}onigmo.h dir.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -1872,50 +4031,805 @@ dir.$(OBJEXT): {$(VPATH)}st.h dir.$(OBJEXT): {$(VPATH)}subst.h dir.$(OBJEXT): {$(VPATH)}thread.h dir.$(OBJEXT): {$(VPATH)}util.h -dln.$(OBJEXT): $(hdrdir)/ruby.h dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h +dln.$(OBJEXT): $(top_srcdir)/internal/compilers.h +dln.$(OBJEXT): $(top_srcdir)/internal/warnings.h dln.$(OBJEXT): {$(VPATH)}assert.h +dln.$(OBJEXT): {$(VPATH)}backward/2/assume.h +dln.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +dln.$(OBJEXT): {$(VPATH)}backward/2/bool.h +dln.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +dln.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +dln.$(OBJEXT): {$(VPATH)}backward/2/limits.h +dln.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +dln.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +dln.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h dln.$(OBJEXT): {$(VPATH)}config.h dln.$(OBJEXT): {$(VPATH)}defines.h dln.$(OBJEXT): {$(VPATH)}dln.c dln.$(OBJEXT): {$(VPATH)}dln.h dln.$(OBJEXT): {$(VPATH)}intern.h dln.$(OBJEXT): {$(VPATH)}internal.h +dln.$(OBJEXT): {$(VPATH)}internal/anyargs.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +dln.$(OBJEXT): {$(VPATH)}internal/assume.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/const.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/error.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/format.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +dln.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +dln.$(OBJEXT): {$(VPATH)}internal/cast.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +dln.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +dln.$(OBJEXT): {$(VPATH)}internal/config.h +dln.$(OBJEXT): {$(VPATH)}internal/constant_p.h +dln.$(OBJEXT): {$(VPATH)}internal/core.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +dln.$(OBJEXT): {$(VPATH)}internal/core/robject.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +dln.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +dln.$(OBJEXT): {$(VPATH)}internal/ctype.h +dln.$(OBJEXT): {$(VPATH)}internal/dllexport.h +dln.$(OBJEXT): {$(VPATH)}internal/dosish.h +dln.$(OBJEXT): {$(VPATH)}internal/error.h +dln.$(OBJEXT): {$(VPATH)}internal/eval.h +dln.$(OBJEXT): {$(VPATH)}internal/event.h +dln.$(OBJEXT): {$(VPATH)}internal/fl_type.h +dln.$(OBJEXT): {$(VPATH)}internal/gc.h +dln.$(OBJEXT): {$(VPATH)}internal/glob.h +dln.$(OBJEXT): {$(VPATH)}internal/globals.h +dln.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +dln.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +dln.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +dln.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +dln.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +dln.$(OBJEXT): {$(VPATH)}internal/has/extension.h +dln.$(OBJEXT): {$(VPATH)}internal/has/feature.h +dln.$(OBJEXT): {$(VPATH)}internal/has/warning.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/array.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/class.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/error.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/file.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/io.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/load.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/object.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/process.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/random.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/range.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/string.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/time.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +dln.$(OBJEXT): {$(VPATH)}internal/interpreter.h +dln.$(OBJEXT): {$(VPATH)}internal/iterator.h +dln.$(OBJEXT): {$(VPATH)}internal/memory.h +dln.$(OBJEXT): {$(VPATH)}internal/method.h +dln.$(OBJEXT): {$(VPATH)}internal/module.h +dln.$(OBJEXT): {$(VPATH)}internal/newobj.h +dln.$(OBJEXT): {$(VPATH)}internal/rgengc.h +dln.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +dln.$(OBJEXT): {$(VPATH)}internal/value.h +dln.$(OBJEXT): {$(VPATH)}internal/value_type.h +dln.$(OBJEXT): {$(VPATH)}internal/variable.h +dln.$(OBJEXT): {$(VPATH)}internal/warning_push.h +dln.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dln.$(OBJEXT): {$(VPATH)}missing.h dln.$(OBJEXT): {$(VPATH)}st.h dln.$(OBJEXT): {$(VPATH)}subst.h dln_find.$(OBJEXT): $(hdrdir)/ruby/ruby.h dln_find.$(OBJEXT): {$(VPATH)}assert.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/assume.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/bool.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/limits.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +dln_find.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h dln_find.$(OBJEXT): {$(VPATH)}config.h dln_find.$(OBJEXT): {$(VPATH)}defines.h dln_find.$(OBJEXT): {$(VPATH)}dln.h dln_find.$(OBJEXT): {$(VPATH)}dln_find.c dln_find.$(OBJEXT): {$(VPATH)}intern.h +dln_find.$(OBJEXT): {$(VPATH)}internal/anyargs.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +dln_find.$(OBJEXT): {$(VPATH)}internal/assume.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/const.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/error.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/format.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +dln_find.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +dln_find.$(OBJEXT): {$(VPATH)}internal/cast.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +dln_find.$(OBJEXT): {$(VPATH)}internal/config.h +dln_find.$(OBJEXT): {$(VPATH)}internal/constant_p.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/robject.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +dln_find.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +dln_find.$(OBJEXT): {$(VPATH)}internal/ctype.h +dln_find.$(OBJEXT): {$(VPATH)}internal/dllexport.h +dln_find.$(OBJEXT): {$(VPATH)}internal/dosish.h +dln_find.$(OBJEXT): {$(VPATH)}internal/error.h +dln_find.$(OBJEXT): {$(VPATH)}internal/eval.h +dln_find.$(OBJEXT): {$(VPATH)}internal/event.h +dln_find.$(OBJEXT): {$(VPATH)}internal/fl_type.h +dln_find.$(OBJEXT): {$(VPATH)}internal/gc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/glob.h +dln_find.$(OBJEXT): {$(VPATH)}internal/globals.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/extension.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/feature.h +dln_find.$(OBJEXT): {$(VPATH)}internal/has/warning.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/array.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/class.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/error.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/file.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/io.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/load.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/object.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/process.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/random.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/range.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/string.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/time.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +dln_find.$(OBJEXT): {$(VPATH)}internal/interpreter.h +dln_find.$(OBJEXT): {$(VPATH)}internal/iterator.h +dln_find.$(OBJEXT): {$(VPATH)}internal/memory.h +dln_find.$(OBJEXT): {$(VPATH)}internal/method.h +dln_find.$(OBJEXT): {$(VPATH)}internal/module.h +dln_find.$(OBJEXT): {$(VPATH)}internal/newobj.h +dln_find.$(OBJEXT): {$(VPATH)}internal/rgengc.h +dln_find.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +dln_find.$(OBJEXT): {$(VPATH)}internal/value.h +dln_find.$(OBJEXT): {$(VPATH)}internal/value_type.h +dln_find.$(OBJEXT): {$(VPATH)}internal/variable.h +dln_find.$(OBJEXT): {$(VPATH)}internal/warning_push.h +dln_find.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dln_find.$(OBJEXT): {$(VPATH)}missing.h dln_find.$(OBJEXT): {$(VPATH)}st.h dln_find.$(OBJEXT): {$(VPATH)}subst.h dmydln.$(OBJEXT): $(hdrdir)/ruby/ruby.h dmydln.$(OBJEXT): {$(VPATH)}assert.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/assume.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/bool.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/limits.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +dmydln.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h dmydln.$(OBJEXT): {$(VPATH)}config.h dmydln.$(OBJEXT): {$(VPATH)}defines.h dmydln.$(OBJEXT): {$(VPATH)}dmydln.c dmydln.$(OBJEXT): {$(VPATH)}intern.h +dmydln.$(OBJEXT): {$(VPATH)}internal/anyargs.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +dmydln.$(OBJEXT): {$(VPATH)}internal/assume.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/const.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/error.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/format.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +dmydln.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +dmydln.$(OBJEXT): {$(VPATH)}internal/cast.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +dmydln.$(OBJEXT): {$(VPATH)}internal/config.h +dmydln.$(OBJEXT): {$(VPATH)}internal/constant_p.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/robject.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +dmydln.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +dmydln.$(OBJEXT): {$(VPATH)}internal/ctype.h +dmydln.$(OBJEXT): {$(VPATH)}internal/dllexport.h +dmydln.$(OBJEXT): {$(VPATH)}internal/dosish.h +dmydln.$(OBJEXT): {$(VPATH)}internal/error.h +dmydln.$(OBJEXT): {$(VPATH)}internal/eval.h +dmydln.$(OBJEXT): {$(VPATH)}internal/event.h +dmydln.$(OBJEXT): {$(VPATH)}internal/fl_type.h +dmydln.$(OBJEXT): {$(VPATH)}internal/gc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/glob.h +dmydln.$(OBJEXT): {$(VPATH)}internal/globals.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/extension.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/feature.h +dmydln.$(OBJEXT): {$(VPATH)}internal/has/warning.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/array.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/class.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/error.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/file.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/io.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/load.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/object.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/process.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/random.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/range.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/string.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/time.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +dmydln.$(OBJEXT): {$(VPATH)}internal/interpreter.h +dmydln.$(OBJEXT): {$(VPATH)}internal/iterator.h +dmydln.$(OBJEXT): {$(VPATH)}internal/memory.h +dmydln.$(OBJEXT): {$(VPATH)}internal/method.h +dmydln.$(OBJEXT): {$(VPATH)}internal/module.h +dmydln.$(OBJEXT): {$(VPATH)}internal/newobj.h +dmydln.$(OBJEXT): {$(VPATH)}internal/rgengc.h +dmydln.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +dmydln.$(OBJEXT): {$(VPATH)}internal/value.h +dmydln.$(OBJEXT): {$(VPATH)}internal/value_type.h +dmydln.$(OBJEXT): {$(VPATH)}internal/variable.h +dmydln.$(OBJEXT): {$(VPATH)}internal/warning_push.h +dmydln.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dmydln.$(OBJEXT): {$(VPATH)}missing.h dmydln.$(OBJEXT): {$(VPATH)}st.h dmydln.$(OBJEXT): {$(VPATH)}subst.h dmyenc.$(OBJEXT): {$(VPATH)}dmyenc.c dmyext.$(OBJEXT): {$(VPATH)}dmyext.c +enc/ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enc/ascii.$(OBJEXT): {$(VPATH)}assert.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enc/ascii.$(OBJEXT): {$(VPATH)}config.h enc/ascii.$(OBJEXT): {$(VPATH)}defines.h enc/ascii.$(OBJEXT): {$(VPATH)}enc/ascii.c enc/ascii.$(OBJEXT): {$(VPATH)}encindex.h +enc/ascii.$(OBJEXT): {$(VPATH)}encoding.h +enc/ascii.$(OBJEXT): {$(VPATH)}intern.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/assume.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/cast.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/config.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/ctype.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/dosish.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/error.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/eval.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/event.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/gc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/glob.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/globals.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/re.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/select.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/iterator.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/memory.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/method.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/module.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/newobj.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/scan_args.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/special_consts.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/static_assert.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/stdalign.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/symbol.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/value.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/value_type.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/variable.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enc/ascii.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enc/ascii.$(OBJEXT): {$(VPATH)}missing.h +enc/ascii.$(OBJEXT): {$(VPATH)}onigmo.h +enc/ascii.$(OBJEXT): {$(VPATH)}oniguruma.h enc/ascii.$(OBJEXT): {$(VPATH)}regenc.h +enc/ascii.$(OBJEXT): {$(VPATH)}st.h +enc/ascii.$(OBJEXT): {$(VPATH)}subst.h enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}assert.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enc/trans/newline.$(OBJEXT): {$(VPATH)}config.h enc/trans/newline.$(OBJEXT): {$(VPATH)}defines.h enc/trans/newline.$(OBJEXT): {$(VPATH)}enc/trans/newline.c enc/trans/newline.$(OBJEXT): {$(VPATH)}intern.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/assume.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/cast.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/config.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/ctype.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/dosish.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/error.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/eval.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/event.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/gc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/glob.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/globals.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/re.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/select.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/iterator.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/memory.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/method.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/module.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/newobj.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/scan_args.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/special_consts.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/static_assert.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/stdalign.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/symbol.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/value.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/value_type.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/variable.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enc/trans/newline.$(OBJEXT): {$(VPATH)}missing.h enc/trans/newline.$(OBJEXT): {$(VPATH)}st.h enc/trans/newline.$(OBJEXT): {$(VPATH)}subst.h @@ -1923,38 +4837,685 @@ enc/trans/newline.$(OBJEXT): {$(VPATH)}transcode_data.h enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/casefold.h enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/name2ctype.h enc/unicode.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enc/unicode.$(OBJEXT): {$(VPATH)}assert.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enc/unicode.$(OBJEXT): {$(VPATH)}config.h enc/unicode.$(OBJEXT): {$(VPATH)}defines.h enc/unicode.$(OBJEXT): {$(VPATH)}enc/unicode.c enc/unicode.$(OBJEXT): {$(VPATH)}intern.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/assume.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/cast.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/config.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/ctype.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/dosish.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/error.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/eval.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/event.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/gc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/glob.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/globals.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/re.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/select.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/iterator.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/memory.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/method.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/module.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/newobj.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/scan_args.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/special_consts.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/static_assert.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/stdalign.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/symbol.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/value.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/value_type.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/variable.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enc/unicode.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enc/unicode.$(OBJEXT): {$(VPATH)}missing.h enc/unicode.$(OBJEXT): {$(VPATH)}onigmo.h enc/unicode.$(OBJEXT): {$(VPATH)}regenc.h enc/unicode.$(OBJEXT): {$(VPATH)}regint.h enc/unicode.$(OBJEXT): {$(VPATH)}st.h enc/unicode.$(OBJEXT): {$(VPATH)}subst.h +enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}assert.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enc/us_ascii.$(OBJEXT): {$(VPATH)}config.h enc/us_ascii.$(OBJEXT): {$(VPATH)}defines.h enc/us_ascii.$(OBJEXT): {$(VPATH)}enc/us_ascii.c enc/us_ascii.$(OBJEXT): {$(VPATH)}encindex.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}encoding.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}intern.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/assume.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/cast.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/config.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/ctype.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/dosish.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/error.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/eval.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/event.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/gc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/glob.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/globals.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/re.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/select.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/iterator.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/memory.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/method.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/module.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/newobj.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/scan_args.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/special_consts.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/static_assert.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/stdalign.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/symbol.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/value.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/value_type.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/variable.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enc/us_ascii.$(OBJEXT): {$(VPATH)}missing.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}onigmo.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}oniguruma.h enc/us_ascii.$(OBJEXT): {$(VPATH)}regenc.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}st.h +enc/us_ascii.$(OBJEXT): {$(VPATH)}subst.h +enc/utf_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enc/utf_8.$(OBJEXT): {$(VPATH)}assert.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enc/utf_8.$(OBJEXT): {$(VPATH)}config.h enc/utf_8.$(OBJEXT): {$(VPATH)}defines.h enc/utf_8.$(OBJEXT): {$(VPATH)}enc/utf_8.c enc/utf_8.$(OBJEXT): {$(VPATH)}encindex.h +enc/utf_8.$(OBJEXT): {$(VPATH)}encoding.h +enc/utf_8.$(OBJEXT): {$(VPATH)}intern.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/assume.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/cast.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/config.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/ctype.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/dosish.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/error.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/eval.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/event.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/gc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/glob.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/globals.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/re.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/select.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/iterator.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/memory.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/method.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/module.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/newobj.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/scan_args.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/special_consts.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/static_assert.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/stdalign.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/symbol.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/value.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/value_type.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/variable.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enc/utf_8.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enc/utf_8.$(OBJEXT): {$(VPATH)}missing.h +enc/utf_8.$(OBJEXT): {$(VPATH)}onigmo.h +enc/utf_8.$(OBJEXT): {$(VPATH)}oniguruma.h enc/utf_8.$(OBJEXT): {$(VPATH)}regenc.h -encoding.$(OBJEXT): $(hdrdir)/ruby.h +enc/utf_8.$(OBJEXT): {$(VPATH)}st.h +enc/utf_8.$(OBJEXT): {$(VPATH)}subst.h encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.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/gc.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/static_assert.h +encoding.$(OBJEXT): $(top_srcdir)/internal/string.h +encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h +encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h encoding.$(OBJEXT): {$(VPATH)}assert.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/limits.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +encoding.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h encoding.$(OBJEXT): {$(VPATH)}config.h +encoding.$(OBJEXT): {$(VPATH)}debug_counter.h encoding.$(OBJEXT): {$(VPATH)}defines.h encoding.$(OBJEXT): {$(VPATH)}encindex.h encoding.$(OBJEXT): {$(VPATH)}encoding.c encoding.$(OBJEXT): {$(VPATH)}encoding.h +encoding.$(OBJEXT): {$(VPATH)}id_table.h encoding.$(OBJEXT): {$(VPATH)}intern.h encoding.$(OBJEXT): {$(VPATH)}internal.h +encoding.$(OBJEXT): {$(VPATH)}internal/anyargs.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +encoding.$(OBJEXT): {$(VPATH)}internal/assume.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/const.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/error.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/format.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +encoding.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +encoding.$(OBJEXT): {$(VPATH)}internal/cast.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +encoding.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +encoding.$(OBJEXT): {$(VPATH)}internal/config.h +encoding.$(OBJEXT): {$(VPATH)}internal/constant_p.h +encoding.$(OBJEXT): {$(VPATH)}internal/core.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/robject.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +encoding.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +encoding.$(OBJEXT): {$(VPATH)}internal/ctype.h +encoding.$(OBJEXT): {$(VPATH)}internal/dllexport.h +encoding.$(OBJEXT): {$(VPATH)}internal/dosish.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +encoding.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +encoding.$(OBJEXT): {$(VPATH)}internal/error.h +encoding.$(OBJEXT): {$(VPATH)}internal/eval.h +encoding.$(OBJEXT): {$(VPATH)}internal/event.h +encoding.$(OBJEXT): {$(VPATH)}internal/fl_type.h +encoding.$(OBJEXT): {$(VPATH)}internal/gc.h +encoding.$(OBJEXT): {$(VPATH)}internal/glob.h +encoding.$(OBJEXT): {$(VPATH)}internal/globals.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/extension.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/feature.h +encoding.$(OBJEXT): {$(VPATH)}internal/has/warning.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/array.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/class.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/error.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/file.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/io.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/load.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/object.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/process.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/random.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/range.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/string.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/time.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +encoding.$(OBJEXT): {$(VPATH)}internal/interpreter.h +encoding.$(OBJEXT): {$(VPATH)}internal/iterator.h +encoding.$(OBJEXT): {$(VPATH)}internal/memory.h +encoding.$(OBJEXT): {$(VPATH)}internal/method.h +encoding.$(OBJEXT): {$(VPATH)}internal/module.h +encoding.$(OBJEXT): {$(VPATH)}internal/newobj.h +encoding.$(OBJEXT): {$(VPATH)}internal/rgengc.h +encoding.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/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)}missing.h encoding.$(OBJEXT): {$(VPATH)}onigmo.h encoding.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -1963,51 +5524,589 @@ encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h encoding.$(OBJEXT): {$(VPATH)}st.h encoding.$(OBJEXT): {$(VPATH)}subst.h encoding.$(OBJEXT): {$(VPATH)}util.h -enum.$(OBJEXT): $(hdrdir)/ruby.h +encoding.$(OBJEXT): {$(VPATH)}vm_debug.h +encoding.$(OBJEXT): {$(VPATH)}vm_sync.h enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enum.$(OBJEXT): $(top_srcdir)/internal/array.h +enum.$(OBJEXT): $(top_srcdir)/internal/bignum.h +enum.$(OBJEXT): $(top_srcdir)/internal/bits.h +enum.$(OBJEXT): $(top_srcdir)/internal/class.h +enum.$(OBJEXT): $(top_srcdir)/internal/compar.h +enum.$(OBJEXT): $(top_srcdir)/internal/compilers.h +enum.$(OBJEXT): $(top_srcdir)/internal/enum.h +enum.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +enum.$(OBJEXT): $(top_srcdir)/internal/gc.h +enum.$(OBJEXT): $(top_srcdir)/internal/hash.h +enum.$(OBJEXT): $(top_srcdir)/internal/imemo.h +enum.$(OBJEXT): $(top_srcdir)/internal/numeric.h +enum.$(OBJEXT): $(top_srcdir)/internal/object.h +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/static_assert.h +enum.$(OBJEXT): $(top_srcdir)/internal/vm.h +enum.$(OBJEXT): $(top_srcdir)/internal/warnings.h enum.$(OBJEXT): {$(VPATH)}assert.h +enum.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enum.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enum.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enum.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +enum.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enum.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enum.$(OBJEXT): {$(VPATH)}config.h enum.$(OBJEXT): {$(VPATH)}defines.h enum.$(OBJEXT): {$(VPATH)}encoding.h enum.$(OBJEXT): {$(VPATH)}enum.c enum.$(OBJEXT): {$(VPATH)}id.h +enum.$(OBJEXT): {$(VPATH)}id_table.h enum.$(OBJEXT): {$(VPATH)}intern.h enum.$(OBJEXT): {$(VPATH)}internal.h +enum.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enum.$(OBJEXT): {$(VPATH)}internal/assume.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enum.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enum.$(OBJEXT): {$(VPATH)}internal/cast.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enum.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enum.$(OBJEXT): {$(VPATH)}internal/config.h +enum.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enum.$(OBJEXT): {$(VPATH)}internal/core.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enum.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enum.$(OBJEXT): {$(VPATH)}internal/ctype.h +enum.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enum.$(OBJEXT): {$(VPATH)}internal/dosish.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +enum.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +enum.$(OBJEXT): {$(VPATH)}internal/error.h +enum.$(OBJEXT): {$(VPATH)}internal/eval.h +enum.$(OBJEXT): {$(VPATH)}internal/event.h +enum.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enum.$(OBJEXT): {$(VPATH)}internal/gc.h +enum.$(OBJEXT): {$(VPATH)}internal/glob.h +enum.$(OBJEXT): {$(VPATH)}internal/globals.h +enum.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enum.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enum.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enum.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enum.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enum.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enum.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enum.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enum.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enum.$(OBJEXT): {$(VPATH)}internal/iterator.h +enum.$(OBJEXT): {$(VPATH)}internal/memory.h +enum.$(OBJEXT): {$(VPATH)}internal/method.h +enum.$(OBJEXT): {$(VPATH)}internal/module.h +enum.$(OBJEXT): {$(VPATH)}internal/newobj.h +enum.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enum.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +enum.$(OBJEXT): {$(VPATH)}internal/value.h +enum.$(OBJEXT): {$(VPATH)}internal/value_type.h +enum.$(OBJEXT): {$(VPATH)}internal/variable.h +enum.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enum.$(OBJEXT): {$(VPATH)}missing.h enum.$(OBJEXT): {$(VPATH)}onigmo.h enum.$(OBJEXT): {$(VPATH)}oniguruma.h +enum.$(OBJEXT): {$(VPATH)}ruby_assert.h enum.$(OBJEXT): {$(VPATH)}st.h enum.$(OBJEXT): {$(VPATH)}subst.h enum.$(OBJEXT): {$(VPATH)}symbol.h enum.$(OBJEXT): {$(VPATH)}util.h -enumerator.$(OBJEXT): $(hdrdir)/ruby.h enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/bits.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/compilers.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/enumerator.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/error.h +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/numeric.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/struct.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/vm.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/warnings.h enumerator.$(OBJEXT): {$(VPATH)}assert.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/assume.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/bool.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/limits.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enumerator.$(OBJEXT): {$(VPATH)}config.h enumerator.$(OBJEXT): {$(VPATH)}defines.h +enumerator.$(OBJEXT): {$(VPATH)}encoding.h enumerator.$(OBJEXT): {$(VPATH)}enumerator.c enumerator.$(OBJEXT): {$(VPATH)}id.h enumerator.$(OBJEXT): {$(VPATH)}intern.h enumerator.$(OBJEXT): {$(VPATH)}internal.h +enumerator.$(OBJEXT): {$(VPATH)}internal/anyargs.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +enumerator.$(OBJEXT): {$(VPATH)}internal/assume.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/const.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/error.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/format.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +enumerator.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +enumerator.$(OBJEXT): {$(VPATH)}internal/cast.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +enumerator.$(OBJEXT): {$(VPATH)}internal/config.h +enumerator.$(OBJEXT): {$(VPATH)}internal/constant_p.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/robject.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +enumerator.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +enumerator.$(OBJEXT): {$(VPATH)}internal/ctype.h +enumerator.$(OBJEXT): {$(VPATH)}internal/dllexport.h +enumerator.$(OBJEXT): {$(VPATH)}internal/dosish.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +enumerator.$(OBJEXT): {$(VPATH)}internal/error.h +enumerator.$(OBJEXT): {$(VPATH)}internal/eval.h +enumerator.$(OBJEXT): {$(VPATH)}internal/event.h +enumerator.$(OBJEXT): {$(VPATH)}internal/fl_type.h +enumerator.$(OBJEXT): {$(VPATH)}internal/gc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/glob.h +enumerator.$(OBJEXT): {$(VPATH)}internal/globals.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/extension.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/feature.h +enumerator.$(OBJEXT): {$(VPATH)}internal/has/warning.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/array.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/class.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/error.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/file.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/io.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/load.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/object.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/process.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/random.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/range.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/string.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/time.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +enumerator.$(OBJEXT): {$(VPATH)}internal/interpreter.h +enumerator.$(OBJEXT): {$(VPATH)}internal/iterator.h +enumerator.$(OBJEXT): {$(VPATH)}internal/memory.h +enumerator.$(OBJEXT): {$(VPATH)}internal/method.h +enumerator.$(OBJEXT): {$(VPATH)}internal/module.h +enumerator.$(OBJEXT): {$(VPATH)}internal/newobj.h +enumerator.$(OBJEXT): {$(VPATH)}internal/rgengc.h +enumerator.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +enumerator.$(OBJEXT): {$(VPATH)}internal/value.h +enumerator.$(OBJEXT): {$(VPATH)}internal/value_type.h +enumerator.$(OBJEXT): {$(VPATH)}internal/variable.h +enumerator.$(OBJEXT): {$(VPATH)}internal/warning_push.h +enumerator.$(OBJEXT): {$(VPATH)}internal/xmalloc.h enumerator.$(OBJEXT): {$(VPATH)}missing.h +enumerator.$(OBJEXT): {$(VPATH)}onigmo.h +enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h +enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h enumerator.$(OBJEXT): {$(VPATH)}st.h enumerator.$(OBJEXT): {$(VPATH)}subst.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.h error.$(OBJEXT): $(hdrdir)/ruby/ruby.h +error.$(OBJEXT): $(top_srcdir)/internal/array.h +error.$(OBJEXT): $(top_srcdir)/internal/class.h +error.$(OBJEXT): $(top_srcdir)/internal/compilers.h +error.$(OBJEXT): $(top_srcdir)/internal/error.h +error.$(OBJEXT): $(top_srcdir)/internal/eval.h +error.$(OBJEXT): $(top_srcdir)/internal/gc.h +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/object.h +error.$(OBJEXT): $(top_srcdir)/internal/serial.h +error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +error.$(OBJEXT): $(top_srcdir)/internal/string.h +error.$(OBJEXT): $(top_srcdir)/internal/symbol.h +error.$(OBJEXT): $(top_srcdir)/internal/thread.h +error.$(OBJEXT): $(top_srcdir)/internal/variable.h +error.$(OBJEXT): $(top_srcdir)/internal/vm.h +error.$(OBJEXT): $(top_srcdir)/internal/warnings.h error.$(OBJEXT): {$(VPATH)}assert.h +error.$(OBJEXT): {$(VPATH)}atomic.h +error.$(OBJEXT): {$(VPATH)}backward/2/assume.h +error.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +error.$(OBJEXT): {$(VPATH)}backward/2/bool.h +error.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +error.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +error.$(OBJEXT): {$(VPATH)}backward/2/limits.h +error.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +error.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +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)}darray.h error.$(OBJEXT): {$(VPATH)}defines.h error.$(OBJEXT): {$(VPATH)}encoding.h error.$(OBJEXT): {$(VPATH)}error.c -error.$(OBJEXT): {$(VPATH)}eval_intern.h error.$(OBJEXT): {$(VPATH)}id.h +error.$(OBJEXT): {$(VPATH)}id_table.h error.$(OBJEXT): {$(VPATH)}intern.h error.$(OBJEXT): {$(VPATH)}internal.h +error.$(OBJEXT): {$(VPATH)}internal/anyargs.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +error.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +error.$(OBJEXT): {$(VPATH)}internal/assume.h +error.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +error.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +error.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +error.$(OBJEXT): {$(VPATH)}internal/attr/const.h +error.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +error.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +error.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +error.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +error.$(OBJEXT): {$(VPATH)}internal/attr/error.h +error.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +error.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +error.$(OBJEXT): {$(VPATH)}internal/attr/format.h +error.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +error.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +error.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +error.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +error.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +error.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +error.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +error.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +error.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +error.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +error.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +error.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +error.$(OBJEXT): {$(VPATH)}internal/cast.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +error.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +error.$(OBJEXT): {$(VPATH)}internal/config.h +error.$(OBJEXT): {$(VPATH)}internal/constant_p.h +error.$(OBJEXT): {$(VPATH)}internal/core.h +error.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +error.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +error.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +error.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +error.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +error.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +error.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +error.$(OBJEXT): {$(VPATH)}internal/core/robject.h +error.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +error.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +error.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +error.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +error.$(OBJEXT): {$(VPATH)}internal/ctype.h +error.$(OBJEXT): {$(VPATH)}internal/dllexport.h +error.$(OBJEXT): {$(VPATH)}internal/dosish.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +error.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +error.$(OBJEXT): {$(VPATH)}internal/error.h +error.$(OBJEXT): {$(VPATH)}internal/eval.h +error.$(OBJEXT): {$(VPATH)}internal/event.h +error.$(OBJEXT): {$(VPATH)}internal/fl_type.h +error.$(OBJEXT): {$(VPATH)}internal/gc.h +error.$(OBJEXT): {$(VPATH)}internal/glob.h +error.$(OBJEXT): {$(VPATH)}internal/globals.h +error.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +error.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +error.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +error.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +error.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +error.$(OBJEXT): {$(VPATH)}internal/has/extension.h +error.$(OBJEXT): {$(VPATH)}internal/has/feature.h +error.$(OBJEXT): {$(VPATH)}internal/has/warning.h +error.$(OBJEXT): {$(VPATH)}internal/intern/array.h +error.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +error.$(OBJEXT): {$(VPATH)}internal/intern/class.h +error.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +error.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +error.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +error.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +error.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +error.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +error.$(OBJEXT): {$(VPATH)}internal/intern/error.h +error.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +error.$(OBJEXT): {$(VPATH)}internal/intern/file.h +error.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +error.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +error.$(OBJEXT): {$(VPATH)}internal/intern/io.h +error.$(OBJEXT): {$(VPATH)}internal/intern/load.h +error.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +error.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +error.$(OBJEXT): {$(VPATH)}internal/intern/object.h +error.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +error.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +error.$(OBJEXT): {$(VPATH)}internal/intern/process.h +error.$(OBJEXT): {$(VPATH)}internal/intern/random.h +error.$(OBJEXT): {$(VPATH)}internal/intern/range.h +error.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +error.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +error.$(OBJEXT): {$(VPATH)}internal/intern/string.h +error.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +error.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +error.$(OBJEXT): {$(VPATH)}internal/intern/time.h +error.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +error.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +error.$(OBJEXT): {$(VPATH)}internal/interpreter.h +error.$(OBJEXT): {$(VPATH)}internal/iterator.h +error.$(OBJEXT): {$(VPATH)}internal/memory.h +error.$(OBJEXT): {$(VPATH)}internal/method.h +error.$(OBJEXT): {$(VPATH)}internal/module.h +error.$(OBJEXT): {$(VPATH)}internal/newobj.h +error.$(OBJEXT): {$(VPATH)}internal/rgengc.h +error.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +error.$(OBJEXT): {$(VPATH)}internal/value.h +error.$(OBJEXT): {$(VPATH)}internal/value_type.h +error.$(OBJEXT): {$(VPATH)}internal/variable.h +error.$(OBJEXT): {$(VPATH)}internal/warning_push.h +error.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +error.$(OBJEXT): {$(VPATH)}io.h error.$(OBJEXT): {$(VPATH)}known_errors.inc error.$(OBJEXT): {$(VPATH)}method.h error.$(OBJEXT): {$(VPATH)}missing.h @@ -2029,26 +6128,212 @@ 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): $(top_srcdir)/internal/array.h +eval.$(OBJEXT): $(top_srcdir)/internal/class.h +eval.$(OBJEXT): $(top_srcdir)/internal/compilers.h +eval.$(OBJEXT): $(top_srcdir)/internal/error.h +eval.$(OBJEXT): $(top_srcdir)/internal/eval.h +eval.$(OBJEXT): $(top_srcdir)/internal/gc.h +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/object.h +eval.$(OBJEXT): $(top_srcdir)/internal/serial.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): {$(VPATH)}assert.h +eval.$(OBJEXT): {$(VPATH)}atomic.h +eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h +eval.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +eval.$(OBJEXT): {$(VPATH)}backward/2/bool.h +eval.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +eval.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +eval.$(OBJEXT): {$(VPATH)}backward/2/limits.h +eval.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +eval.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +eval.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h eval.$(OBJEXT): {$(VPATH)}config.h +eval.$(OBJEXT): {$(VPATH)}constant.h +eval.$(OBJEXT): {$(VPATH)}darray.h eval.$(OBJEXT): {$(VPATH)}debug_counter.h eval.$(OBJEXT): {$(VPATH)}defines.h +eval.$(OBJEXT): {$(VPATH)}encoding.h eval.$(OBJEXT): {$(VPATH)}eval.c eval.$(OBJEXT): {$(VPATH)}eval_error.c eval.$(OBJEXT): {$(VPATH)}eval_intern.h eval.$(OBJEXT): {$(VPATH)}eval_jump.c +eval.$(OBJEXT): {$(VPATH)}fiber/scheduler.h eval.$(OBJEXT): {$(VPATH)}gc.h eval.$(OBJEXT): {$(VPATH)}id.h +eval.$(OBJEXT): {$(VPATH)}id_table.h eval.$(OBJEXT): {$(VPATH)}intern.h eval.$(OBJEXT): {$(VPATH)}internal.h +eval.$(OBJEXT): {$(VPATH)}internal/anyargs.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +eval.$(OBJEXT): {$(VPATH)}internal/assume.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/const.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/error.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/format.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +eval.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +eval.$(OBJEXT): {$(VPATH)}internal/cast.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +eval.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +eval.$(OBJEXT): {$(VPATH)}internal/config.h +eval.$(OBJEXT): {$(VPATH)}internal/constant_p.h +eval.$(OBJEXT): {$(VPATH)}internal/core.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +eval.$(OBJEXT): {$(VPATH)}internal/core/robject.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +eval.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +eval.$(OBJEXT): {$(VPATH)}internal/ctype.h +eval.$(OBJEXT): {$(VPATH)}internal/dllexport.h +eval.$(OBJEXT): {$(VPATH)}internal/dosish.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +eval.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +eval.$(OBJEXT): {$(VPATH)}internal/error.h +eval.$(OBJEXT): {$(VPATH)}internal/eval.h +eval.$(OBJEXT): {$(VPATH)}internal/event.h +eval.$(OBJEXT): {$(VPATH)}internal/fl_type.h +eval.$(OBJEXT): {$(VPATH)}internal/gc.h +eval.$(OBJEXT): {$(VPATH)}internal/glob.h +eval.$(OBJEXT): {$(VPATH)}internal/globals.h +eval.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +eval.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +eval.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +eval.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +eval.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +eval.$(OBJEXT): {$(VPATH)}internal/has/extension.h +eval.$(OBJEXT): {$(VPATH)}internal/has/feature.h +eval.$(OBJEXT): {$(VPATH)}internal/has/warning.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/array.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/class.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/error.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/file.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/io.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/load.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/object.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/process.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/random.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/range.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/string.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/time.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +eval.$(OBJEXT): {$(VPATH)}internal/interpreter.h +eval.$(OBJEXT): {$(VPATH)}internal/iterator.h +eval.$(OBJEXT): {$(VPATH)}internal/memory.h +eval.$(OBJEXT): {$(VPATH)}internal/method.h +eval.$(OBJEXT): {$(VPATH)}internal/module.h +eval.$(OBJEXT): {$(VPATH)}internal/newobj.h +eval.$(OBJEXT): {$(VPATH)}internal/rgengc.h +eval.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +eval.$(OBJEXT): {$(VPATH)}internal/value.h +eval.$(OBJEXT): {$(VPATH)}internal/value_type.h +eval.$(OBJEXT): {$(VPATH)}internal/variable.h +eval.$(OBJEXT): {$(VPATH)}internal/warning_push.h +eval.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +eval.$(OBJEXT): {$(VPATH)}io.h eval.$(OBJEXT): {$(VPATH)}iseq.h eval.$(OBJEXT): {$(VPATH)}method.h eval.$(OBJEXT): {$(VPATH)}missing.h eval.$(OBJEXT): {$(VPATH)}mjit.h eval.$(OBJEXT): {$(VPATH)}node.h +eval.$(OBJEXT): {$(VPATH)}onigmo.h +eval.$(OBJEXT): {$(VPATH)}oniguruma.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)}ruby_assert.h eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h eval.$(OBJEXT): {$(VPATH)}st.h @@ -2057,13 +6342,53 @@ eval.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h eval.$(OBJEXT): {$(VPATH)}thread_native.h 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)}yjit.h explicit_bzero.$(OBJEXT): {$(VPATH)}config.h explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/attr/format.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/config.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/dllexport.h +explicit_bzero.$(OBJEXT): {$(VPATH)}internal/has/attribute.h explicit_bzero.$(OBJEXT): {$(VPATH)}missing.h -file.$(OBJEXT): $(hdrdir)/ruby.h file.$(OBJEXT): $(hdrdir)/ruby/ruby.h +file.$(OBJEXT): $(top_srcdir)/internal/array.h +file.$(OBJEXT): $(top_srcdir)/internal/class.h +file.$(OBJEXT): $(top_srcdir)/internal/compilers.h +file.$(OBJEXT): $(top_srcdir)/internal/dir.h +file.$(OBJEXT): $(top_srcdir)/internal/error.h +file.$(OBJEXT): $(top_srcdir)/internal/file.h +file.$(OBJEXT): $(top_srcdir)/internal/gc.h +file.$(OBJEXT): $(top_srcdir)/internal/imemo.h +file.$(OBJEXT): $(top_srcdir)/internal/io.h +file.$(OBJEXT): $(top_srcdir)/internal/load.h +file.$(OBJEXT): $(top_srcdir)/internal/object.h +file.$(OBJEXT): $(top_srcdir)/internal/process.h +file.$(OBJEXT): $(top_srcdir)/internal/serial.h +file.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +file.$(OBJEXT): $(top_srcdir)/internal/string.h +file.$(OBJEXT): $(top_srcdir)/internal/thread.h +file.$(OBJEXT): $(top_srcdir)/internal/vm.h +file.$(OBJEXT): $(top_srcdir)/internal/warnings.h file.$(OBJEXT): {$(VPATH)}assert.h +file.$(OBJEXT): {$(VPATH)}backward/2/assume.h +file.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +file.$(OBJEXT): {$(VPATH)}backward/2/bool.h +file.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +file.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +file.$(OBJEXT): {$(VPATH)}backward/2/limits.h +file.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +file.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +file.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h file.$(OBJEXT): {$(VPATH)}config.h file.$(OBJEXT): {$(VPATH)}defines.h file.$(OBJEXT): {$(VPATH)}dln.h @@ -2071,8 +6396,157 @@ file.$(OBJEXT): {$(VPATH)}encindex.h file.$(OBJEXT): {$(VPATH)}encoding.h file.$(OBJEXT): {$(VPATH)}file.c file.$(OBJEXT): {$(VPATH)}id.h +file.$(OBJEXT): {$(VPATH)}id_table.h file.$(OBJEXT): {$(VPATH)}intern.h file.$(OBJEXT): {$(VPATH)}internal.h +file.$(OBJEXT): {$(VPATH)}internal/anyargs.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +file.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +file.$(OBJEXT): {$(VPATH)}internal/assume.h +file.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +file.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +file.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +file.$(OBJEXT): {$(VPATH)}internal/attr/const.h +file.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +file.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +file.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +file.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +file.$(OBJEXT): {$(VPATH)}internal/attr/error.h +file.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +file.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +file.$(OBJEXT): {$(VPATH)}internal/attr/format.h +file.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +file.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +file.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +file.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +file.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +file.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +file.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +file.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +file.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +file.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +file.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +file.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +file.$(OBJEXT): {$(VPATH)}internal/cast.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +file.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +file.$(OBJEXT): {$(VPATH)}internal/config.h +file.$(OBJEXT): {$(VPATH)}internal/constant_p.h +file.$(OBJEXT): {$(VPATH)}internal/core.h +file.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +file.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +file.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +file.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +file.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +file.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +file.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +file.$(OBJEXT): {$(VPATH)}internal/core/robject.h +file.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +file.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +file.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +file.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +file.$(OBJEXT): {$(VPATH)}internal/ctype.h +file.$(OBJEXT): {$(VPATH)}internal/dllexport.h +file.$(OBJEXT): {$(VPATH)}internal/dosish.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +file.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +file.$(OBJEXT): {$(VPATH)}internal/error.h +file.$(OBJEXT): {$(VPATH)}internal/eval.h +file.$(OBJEXT): {$(VPATH)}internal/event.h +file.$(OBJEXT): {$(VPATH)}internal/fl_type.h +file.$(OBJEXT): {$(VPATH)}internal/gc.h +file.$(OBJEXT): {$(VPATH)}internal/glob.h +file.$(OBJEXT): {$(VPATH)}internal/globals.h +file.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +file.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +file.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +file.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +file.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +file.$(OBJEXT): {$(VPATH)}internal/has/extension.h +file.$(OBJEXT): {$(VPATH)}internal/has/feature.h +file.$(OBJEXT): {$(VPATH)}internal/has/warning.h +file.$(OBJEXT): {$(VPATH)}internal/intern/array.h +file.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +file.$(OBJEXT): {$(VPATH)}internal/intern/class.h +file.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +file.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +file.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +file.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +file.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +file.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +file.$(OBJEXT): {$(VPATH)}internal/intern/error.h +file.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +file.$(OBJEXT): {$(VPATH)}internal/intern/file.h +file.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +file.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +file.$(OBJEXT): {$(VPATH)}internal/intern/io.h +file.$(OBJEXT): {$(VPATH)}internal/intern/load.h +file.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +file.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +file.$(OBJEXT): {$(VPATH)}internal/intern/object.h +file.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +file.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +file.$(OBJEXT): {$(VPATH)}internal/intern/process.h +file.$(OBJEXT): {$(VPATH)}internal/intern/random.h +file.$(OBJEXT): {$(VPATH)}internal/intern/range.h +file.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +file.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +file.$(OBJEXT): {$(VPATH)}internal/intern/string.h +file.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +file.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +file.$(OBJEXT): {$(VPATH)}internal/intern/time.h +file.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +file.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +file.$(OBJEXT): {$(VPATH)}internal/interpreter.h +file.$(OBJEXT): {$(VPATH)}internal/iterator.h +file.$(OBJEXT): {$(VPATH)}internal/memory.h +file.$(OBJEXT): {$(VPATH)}internal/method.h +file.$(OBJEXT): {$(VPATH)}internal/module.h +file.$(OBJEXT): {$(VPATH)}internal/newobj.h +file.$(OBJEXT): {$(VPATH)}internal/rgengc.h +file.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +file.$(OBJEXT): {$(VPATH)}internal/value.h +file.$(OBJEXT): {$(VPATH)}internal/value_type.h +file.$(OBJEXT): {$(VPATH)}internal/variable.h +file.$(OBJEXT): {$(VPATH)}internal/warning_push.h +file.$(OBJEXT): {$(VPATH)}internal/xmalloc.h file.$(OBJEXT): {$(VPATH)}io.h file.$(OBJEXT): {$(VPATH)}missing.h file.$(OBJEXT): {$(VPATH)}onigmo.h @@ -2087,10 +6561,49 @@ 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): $(top_srcdir)/internal/array.h +gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h +gc.$(OBJEXT): $(top_srcdir)/internal/bits.h +gc.$(OBJEXT): $(top_srcdir)/internal/class.h +gc.$(OBJEXT): $(top_srcdir)/internal/compilers.h +gc.$(OBJEXT): $(top_srcdir)/internal/complex.h +gc.$(OBJEXT): $(top_srcdir)/internal/cont.h +gc.$(OBJEXT): $(top_srcdir)/internal/error.h +gc.$(OBJEXT): $(top_srcdir)/internal/eval.h +gc.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +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/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/static_assert.h +gc.$(OBJEXT): $(top_srcdir)/internal/string.h +gc.$(OBJEXT): $(top_srcdir)/internal/struct.h +gc.$(OBJEXT): $(top_srcdir)/internal/symbol.h +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): {$(VPATH)}assert.h +gc.$(OBJEXT): {$(VPATH)}atomic.h +gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h +gc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +gc.$(OBJEXT): {$(VPATH)}backward/2/bool.h +gc.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +gc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +gc.$(OBJEXT): {$(VPATH)}backward/2/limits.h +gc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +gc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +gc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h gc.$(OBJEXT): {$(VPATH)}builtin.h gc.$(OBJEXT): {$(VPATH)}config.h gc.$(OBJEXT): {$(VPATH)}constant.h +gc.$(OBJEXT): {$(VPATH)}darray.h gc.$(OBJEXT): {$(VPATH)}debug.h gc.$(OBJEXT): {$(VPATH)}debug_counter.h gc.$(OBJEXT): {$(VPATH)}defines.h @@ -2098,11 +6611,161 @@ gc.$(OBJEXT): {$(VPATH)}encoding.h gc.$(OBJEXT): {$(VPATH)}eval_intern.h gc.$(OBJEXT): {$(VPATH)}gc.c gc.$(OBJEXT): {$(VPATH)}gc.h +gc.$(OBJEXT): {$(VPATH)}gc.rb gc.$(OBJEXT): {$(VPATH)}gc.rbinc gc.$(OBJEXT): {$(VPATH)}id.h gc.$(OBJEXT): {$(VPATH)}id_table.h gc.$(OBJEXT): {$(VPATH)}intern.h gc.$(OBJEXT): {$(VPATH)}internal.h +gc.$(OBJEXT): {$(VPATH)}internal/anyargs.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +gc.$(OBJEXT): {$(VPATH)}internal/assume.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/const.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/error.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/format.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +gc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +gc.$(OBJEXT): {$(VPATH)}internal/cast.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +gc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +gc.$(OBJEXT): {$(VPATH)}internal/config.h +gc.$(OBJEXT): {$(VPATH)}internal/constant_p.h +gc.$(OBJEXT): {$(VPATH)}internal/core.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h +gc.$(OBJEXT): {$(VPATH)}internal/core/robject.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +gc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +gc.$(OBJEXT): {$(VPATH)}internal/ctype.h +gc.$(OBJEXT): {$(VPATH)}internal/dllexport.h +gc.$(OBJEXT): {$(VPATH)}internal/dosish.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +gc.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +gc.$(OBJEXT): {$(VPATH)}internal/error.h +gc.$(OBJEXT): {$(VPATH)}internal/eval.h +gc.$(OBJEXT): {$(VPATH)}internal/event.h +gc.$(OBJEXT): {$(VPATH)}internal/fl_type.h +gc.$(OBJEXT): {$(VPATH)}internal/gc.h +gc.$(OBJEXT): {$(VPATH)}internal/glob.h +gc.$(OBJEXT): {$(VPATH)}internal/globals.h +gc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +gc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +gc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +gc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +gc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +gc.$(OBJEXT): {$(VPATH)}internal/has/extension.h +gc.$(OBJEXT): {$(VPATH)}internal/has/feature.h +gc.$(OBJEXT): {$(VPATH)}internal/has/warning.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/array.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/class.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/error.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/file.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/io.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/load.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/object.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/process.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/random.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/range.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/string.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/time.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +gc.$(OBJEXT): {$(VPATH)}internal/interpreter.h +gc.$(OBJEXT): {$(VPATH)}internal/iterator.h +gc.$(OBJEXT): {$(VPATH)}internal/memory.h +gc.$(OBJEXT): {$(VPATH)}internal/method.h +gc.$(OBJEXT): {$(VPATH)}internal/module.h +gc.$(OBJEXT): {$(VPATH)}internal/newobj.h +gc.$(OBJEXT): {$(VPATH)}internal/rgengc.h +gc.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +gc.$(OBJEXT): {$(VPATH)}internal/value.h +gc.$(OBJEXT): {$(VPATH)}internal/value_type.h +gc.$(OBJEXT): {$(VPATH)}internal/variable.h +gc.$(OBJEXT): {$(VPATH)}internal/warning_push.h +gc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h gc.$(OBJEXT): {$(VPATH)}io.h gc.$(OBJEXT): {$(VPATH)}method.h gc.$(OBJEXT): {$(VPATH)}missing.h @@ -2112,6 +6775,8 @@ gc.$(OBJEXT): {$(VPATH)}onigmo.h gc.$(OBJEXT): {$(VPATH)}oniguruma.h gc.$(OBJEXT): {$(VPATH)}probes.dmyh gc.$(OBJEXT): {$(VPATH)}probes.h +gc.$(OBJEXT): {$(VPATH)}ractor.h +gc.$(OBJEXT): {$(VPATH)}ractor_core.h gc.$(OBJEXT): {$(VPATH)}re.h gc.$(OBJEXT): {$(VPATH)}regenc.h gc.$(OBJEXT): {$(VPATH)}regex.h @@ -2126,79 +6791,560 @@ gc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h gc.$(OBJEXT): {$(VPATH)}thread_native.h gc.$(OBJEXT): {$(VPATH)}transient_heap.h gc.$(OBJEXT): {$(VPATH)}util.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 -golf_prelude.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h -golf_prelude.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h -golf_prelude.$(OBJEXT): $(CCAN_DIR)/list/list.h -golf_prelude.$(OBJEXT): $(CCAN_DIR)/str/str.h -golf_prelude.$(OBJEXT): $(hdrdir)/ruby.h -golf_prelude.$(OBJEXT): $(hdrdir)/ruby/ruby.h -golf_prelude.$(OBJEXT): {$(VPATH)}assert.h -golf_prelude.$(OBJEXT): {$(VPATH)}config.h -golf_prelude.$(OBJEXT): {$(VPATH)}defines.h -golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c -golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.rb -golf_prelude.$(OBJEXT): {$(VPATH)}id.h -golf_prelude.$(OBJEXT): {$(VPATH)}intern.h -golf_prelude.$(OBJEXT): {$(VPATH)}internal.h -golf_prelude.$(OBJEXT): {$(VPATH)}iseq.h -golf_prelude.$(OBJEXT): {$(VPATH)}method.h -golf_prelude.$(OBJEXT): {$(VPATH)}missing.h -golf_prelude.$(OBJEXT): {$(VPATH)}node.h -golf_prelude.$(OBJEXT): {$(VPATH)}ruby_assert.h -golf_prelude.$(OBJEXT): {$(VPATH)}ruby_atomic.h -golf_prelude.$(OBJEXT): {$(VPATH)}st.h -golf_prelude.$(OBJEXT): {$(VPATH)}subst.h -golf_prelude.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h -golf_prelude.$(OBJEXT): {$(VPATH)}thread_native.h -golf_prelude.$(OBJEXT): {$(VPATH)}vm_core.h -golf_prelude.$(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 +goruby.$(OBJEXT): $(CCAN_DIR)/str/str.h goruby.$(OBJEXT): $(hdrdir)/ruby.h goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h +goruby.$(OBJEXT): $(top_srcdir)/internal/array.h +goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h +goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h +goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h +goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h +goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h goruby.$(OBJEXT): {$(VPATH)}assert.h +goruby.$(OBJEXT): {$(VPATH)}atomic.h goruby.$(OBJEXT): {$(VPATH)}backward.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/bool.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/limits.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +goruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h goruby.$(OBJEXT): {$(VPATH)}config.h +goruby.$(OBJEXT): {$(VPATH)}darray.h goruby.$(OBJEXT): {$(VPATH)}defines.h +goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c +goruby.$(OBJEXT): {$(VPATH)}golf_prelude.rb goruby.$(OBJEXT): {$(VPATH)}goruby.c +goruby.$(OBJEXT): {$(VPATH)}id.h goruby.$(OBJEXT): {$(VPATH)}intern.h +goruby.$(OBJEXT): {$(VPATH)}internal.h +goruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +goruby.$(OBJEXT): {$(VPATH)}internal/assume.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/const.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/error.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/format.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +goruby.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +goruby.$(OBJEXT): {$(VPATH)}internal/cast.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +goruby.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +goruby.$(OBJEXT): {$(VPATH)}internal/config.h +goruby.$(OBJEXT): {$(VPATH)}internal/constant_p.h +goruby.$(OBJEXT): {$(VPATH)}internal/core.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/robject.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +goruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +goruby.$(OBJEXT): {$(VPATH)}internal/ctype.h +goruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h +goruby.$(OBJEXT): {$(VPATH)}internal/dosish.h +goruby.$(OBJEXT): {$(VPATH)}internal/error.h +goruby.$(OBJEXT): {$(VPATH)}internal/eval.h +goruby.$(OBJEXT): {$(VPATH)}internal/event.h +goruby.$(OBJEXT): {$(VPATH)}internal/fl_type.h +goruby.$(OBJEXT): {$(VPATH)}internal/gc.h +goruby.$(OBJEXT): {$(VPATH)}internal/glob.h +goruby.$(OBJEXT): {$(VPATH)}internal/globals.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/extension.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/feature.h +goruby.$(OBJEXT): {$(VPATH)}internal/has/warning.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/array.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/class.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/error.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/file.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/io.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/load.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/object.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/process.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/random.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/range.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/time.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +goruby.$(OBJEXT): {$(VPATH)}internal/interpreter.h +goruby.$(OBJEXT): {$(VPATH)}internal/iterator.h +goruby.$(OBJEXT): {$(VPATH)}internal/memory.h +goruby.$(OBJEXT): {$(VPATH)}internal/method.h +goruby.$(OBJEXT): {$(VPATH)}internal/module.h +goruby.$(OBJEXT): {$(VPATH)}internal/newobj.h +goruby.$(OBJEXT): {$(VPATH)}internal/rgengc.h +goruby.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +goruby.$(OBJEXT): {$(VPATH)}internal/value.h +goruby.$(OBJEXT): {$(VPATH)}internal/value_type.h +goruby.$(OBJEXT): {$(VPATH)}internal/variable.h +goruby.$(OBJEXT): {$(VPATH)}internal/warning_push.h +goruby.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +goruby.$(OBJEXT): {$(VPATH)}iseq.h goruby.$(OBJEXT): {$(VPATH)}main.c +goruby.$(OBJEXT): {$(VPATH)}method.h goruby.$(OBJEXT): {$(VPATH)}missing.h goruby.$(OBJEXT): {$(VPATH)}node.h +goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h +goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h goruby.$(OBJEXT): {$(VPATH)}st.h goruby.$(OBJEXT): {$(VPATH)}subst.h +goruby.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +goruby.$(OBJEXT): {$(VPATH)}thread_native.h +goruby.$(OBJEXT): {$(VPATH)}vm_core.h goruby.$(OBJEXT): {$(VPATH)}vm_debug.h -hash.$(OBJEXT): $(hdrdir)/ruby.h +goruby.$(OBJEXT): {$(VPATH)}vm_opts.h hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h +hash.$(OBJEXT): $(top_srcdir)/internal/array.h +hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h +hash.$(OBJEXT): $(top_srcdir)/internal/bits.h +hash.$(OBJEXT): $(top_srcdir)/internal/class.h +hash.$(OBJEXT): $(top_srcdir)/internal/compilers.h +hash.$(OBJEXT): $(top_srcdir)/internal/cont.h +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/object.h +hash.$(OBJEXT): $(top_srcdir)/internal/proc.h +hash.$(OBJEXT): $(top_srcdir)/internal/serial.h +hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +hash.$(OBJEXT): $(top_srcdir)/internal/string.h +hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h +hash.$(OBJEXT): $(top_srcdir)/internal/time.h +hash.$(OBJEXT): $(top_srcdir)/internal/vm.h +hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h hash.$(OBJEXT): {$(VPATH)}assert.h +hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h +hash.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +hash.$(OBJEXT): {$(VPATH)}backward/2/bool.h +hash.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +hash.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +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)}config.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)}id.h +hash.$(OBJEXT): {$(VPATH)}id_table.h hash.$(OBJEXT): {$(VPATH)}intern.h hash.$(OBJEXT): {$(VPATH)}internal.h +hash.$(OBJEXT): {$(VPATH)}internal/anyargs.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +hash.$(OBJEXT): {$(VPATH)}internal/assume.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/const.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/error.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/format.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +hash.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +hash.$(OBJEXT): {$(VPATH)}internal/cast.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +hash.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +hash.$(OBJEXT): {$(VPATH)}internal/config.h +hash.$(OBJEXT): {$(VPATH)}internal/constant_p.h +hash.$(OBJEXT): {$(VPATH)}internal/core.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +hash.$(OBJEXT): {$(VPATH)}internal/core/robject.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +hash.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +hash.$(OBJEXT): {$(VPATH)}internal/ctype.h +hash.$(OBJEXT): {$(VPATH)}internal/dllexport.h +hash.$(OBJEXT): {$(VPATH)}internal/dosish.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +hash.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +hash.$(OBJEXT): {$(VPATH)}internal/error.h +hash.$(OBJEXT): {$(VPATH)}internal/eval.h +hash.$(OBJEXT): {$(VPATH)}internal/event.h +hash.$(OBJEXT): {$(VPATH)}internal/fl_type.h +hash.$(OBJEXT): {$(VPATH)}internal/gc.h +hash.$(OBJEXT): {$(VPATH)}internal/glob.h +hash.$(OBJEXT): {$(VPATH)}internal/globals.h +hash.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +hash.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +hash.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +hash.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +hash.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +hash.$(OBJEXT): {$(VPATH)}internal/has/extension.h +hash.$(OBJEXT): {$(VPATH)}internal/has/feature.h +hash.$(OBJEXT): {$(VPATH)}internal/has/warning.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/array.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/class.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/error.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/file.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/io.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/load.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/object.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/process.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/random.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/range.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/string.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/time.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +hash.$(OBJEXT): {$(VPATH)}internal/interpreter.h +hash.$(OBJEXT): {$(VPATH)}internal/iterator.h +hash.$(OBJEXT): {$(VPATH)}internal/memory.h +hash.$(OBJEXT): {$(VPATH)}internal/method.h +hash.$(OBJEXT): {$(VPATH)}internal/module.h +hash.$(OBJEXT): {$(VPATH)}internal/newobj.h +hash.$(OBJEXT): {$(VPATH)}internal/rgengc.h +hash.$(OBJEXT): {$(VPATH)}internal/scan_args.h +hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h +hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h +hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h +hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h +hash.$(OBJEXT): {$(VPATH)}internal/symbol.h +hash.$(OBJEXT): {$(VPATH)}internal/value.h +hash.$(OBJEXT): {$(VPATH)}internal/value_type.h +hash.$(OBJEXT): {$(VPATH)}internal/variable.h +hash.$(OBJEXT): {$(VPATH)}internal/warning_push.h +hash.$(OBJEXT): {$(VPATH)}internal/xmalloc.h hash.$(OBJEXT): {$(VPATH)}missing.h hash.$(OBJEXT): {$(VPATH)}onigmo.h hash.$(OBJEXT): {$(VPATH)}oniguruma.h hash.$(OBJEXT): {$(VPATH)}probes.dmyh hash.$(OBJEXT): {$(VPATH)}probes.h +hash.$(OBJEXT): {$(VPATH)}ractor.h hash.$(OBJEXT): {$(VPATH)}ruby_assert.h hash.$(OBJEXT): {$(VPATH)}st.h hash.$(OBJEXT): {$(VPATH)}subst.h hash.$(OBJEXT): {$(VPATH)}symbol.h +hash.$(OBJEXT): {$(VPATH)}thread_native.h hash.$(OBJEXT): {$(VPATH)}transient_heap.h hash.$(OBJEXT): {$(VPATH)}util.h +hash.$(OBJEXT): {$(VPATH)}vm_debug.h +hash.$(OBJEXT): {$(VPATH)}vm_sync.h inits.$(OBJEXT): $(hdrdir)/ruby.h inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h +inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h +inits.$(OBJEXT): $(top_srcdir)/internal/inits.h +inits.$(OBJEXT): $(top_srcdir)/internal/warnings.h inits.$(OBJEXT): {$(VPATH)}assert.h +inits.$(OBJEXT): {$(VPATH)}backward/2/assume.h +inits.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +inits.$(OBJEXT): {$(VPATH)}backward/2/bool.h +inits.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +inits.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +inits.$(OBJEXT): {$(VPATH)}backward/2/limits.h +inits.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +inits.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +inits.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h inits.$(OBJEXT): {$(VPATH)}builtin.h inits.$(OBJEXT): {$(VPATH)}config.h inits.$(OBJEXT): {$(VPATH)}defines.h inits.$(OBJEXT): {$(VPATH)}inits.c inits.$(OBJEXT): {$(VPATH)}intern.h -inits.$(OBJEXT): {$(VPATH)}internal.h +inits.$(OBJEXT): {$(VPATH)}internal/anyargs.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +inits.$(OBJEXT): {$(VPATH)}internal/assume.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/const.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/error.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/format.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +inits.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +inits.$(OBJEXT): {$(VPATH)}internal/cast.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +inits.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +inits.$(OBJEXT): {$(VPATH)}internal/config.h +inits.$(OBJEXT): {$(VPATH)}internal/constant_p.h +inits.$(OBJEXT): {$(VPATH)}internal/core.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +inits.$(OBJEXT): {$(VPATH)}internal/core/robject.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +inits.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +inits.$(OBJEXT): {$(VPATH)}internal/ctype.h +inits.$(OBJEXT): {$(VPATH)}internal/dllexport.h +inits.$(OBJEXT): {$(VPATH)}internal/dosish.h +inits.$(OBJEXT): {$(VPATH)}internal/error.h +inits.$(OBJEXT): {$(VPATH)}internal/eval.h +inits.$(OBJEXT): {$(VPATH)}internal/event.h +inits.$(OBJEXT): {$(VPATH)}internal/fl_type.h +inits.$(OBJEXT): {$(VPATH)}internal/gc.h +inits.$(OBJEXT): {$(VPATH)}internal/glob.h +inits.$(OBJEXT): {$(VPATH)}internal/globals.h +inits.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +inits.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +inits.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +inits.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +inits.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +inits.$(OBJEXT): {$(VPATH)}internal/has/extension.h +inits.$(OBJEXT): {$(VPATH)}internal/has/feature.h +inits.$(OBJEXT): {$(VPATH)}internal/has/warning.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/array.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/class.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/error.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/file.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/io.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/load.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/object.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/process.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/random.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/range.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/string.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/time.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +inits.$(OBJEXT): {$(VPATH)}internal/interpreter.h +inits.$(OBJEXT): {$(VPATH)}internal/iterator.h +inits.$(OBJEXT): {$(VPATH)}internal/memory.h +inits.$(OBJEXT): {$(VPATH)}internal/method.h +inits.$(OBJEXT): {$(VPATH)}internal/module.h +inits.$(OBJEXT): {$(VPATH)}internal/newobj.h +inits.$(OBJEXT): {$(VPATH)}internal/rgengc.h +inits.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +inits.$(OBJEXT): {$(VPATH)}internal/value.h +inits.$(OBJEXT): {$(VPATH)}internal/value_type.h +inits.$(OBJEXT): {$(VPATH)}internal/variable.h +inits.$(OBJEXT): {$(VPATH)}internal/warning_push.h +inits.$(OBJEXT): {$(VPATH)}internal/xmalloc.h inits.$(OBJEXT): {$(VPATH)}missing.h inits.$(OBJEXT): {$(VPATH)}prelude.rbinc inits.$(OBJEXT): {$(VPATH)}st.h @@ -2207,26 +7353,212 @@ io.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h io.$(OBJEXT): $(hdrdir)/ruby/ruby.h +io.$(OBJEXT): $(top_srcdir)/internal/array.h +io.$(OBJEXT): $(top_srcdir)/internal/bignum.h +io.$(OBJEXT): $(top_srcdir)/internal/bits.h +io.$(OBJEXT): $(top_srcdir)/internal/class.h +io.$(OBJEXT): $(top_srcdir)/internal/compilers.h +io.$(OBJEXT): $(top_srcdir)/internal/encoding.h +io.$(OBJEXT): $(top_srcdir)/internal/error.h +io.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +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/numeric.h +io.$(OBJEXT): $(top_srcdir)/internal/object.h +io.$(OBJEXT): $(top_srcdir)/internal/process.h +io.$(OBJEXT): $(top_srcdir)/internal/serial.h +io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +io.$(OBJEXT): $(top_srcdir)/internal/string.h +io.$(OBJEXT): $(top_srcdir)/internal/thread.h +io.$(OBJEXT): $(top_srcdir)/internal/transcode.h +io.$(OBJEXT): $(top_srcdir)/internal/variable.h +io.$(OBJEXT): $(top_srcdir)/internal/vm.h +io.$(OBJEXT): $(top_srcdir)/internal/warnings.h io.$(OBJEXT): {$(VPATH)}assert.h +io.$(OBJEXT): {$(VPATH)}atomic.h +io.$(OBJEXT): {$(VPATH)}backward/2/assume.h +io.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +io.$(OBJEXT): {$(VPATH)}backward/2/bool.h +io.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +io.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +io.$(OBJEXT): {$(VPATH)}backward/2/limits.h +io.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +io.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +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)}darray.h io.$(OBJEXT): {$(VPATH)}defines.h io.$(OBJEXT): {$(VPATH)}dln.h io.$(OBJEXT): {$(VPATH)}encindex.h io.$(OBJEXT): {$(VPATH)}encoding.h +io.$(OBJEXT): {$(VPATH)}fiber/scheduler.h io.$(OBJEXT): {$(VPATH)}id.h +io.$(OBJEXT): {$(VPATH)}id_table.h io.$(OBJEXT): {$(VPATH)}intern.h io.$(OBJEXT): {$(VPATH)}internal.h +io.$(OBJEXT): {$(VPATH)}internal/anyargs.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +io.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +io.$(OBJEXT): {$(VPATH)}internal/assume.h +io.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +io.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +io.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +io.$(OBJEXT): {$(VPATH)}internal/attr/const.h +io.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +io.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +io.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +io.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +io.$(OBJEXT): {$(VPATH)}internal/attr/error.h +io.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +io.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +io.$(OBJEXT): {$(VPATH)}internal/attr/format.h +io.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +io.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +io.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +io.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +io.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +io.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +io.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +io.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +io.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +io.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +io.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +io.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +io.$(OBJEXT): {$(VPATH)}internal/cast.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +io.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +io.$(OBJEXT): {$(VPATH)}internal/config.h +io.$(OBJEXT): {$(VPATH)}internal/constant_p.h +io.$(OBJEXT): {$(VPATH)}internal/core.h +io.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +io.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +io.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +io.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +io.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +io.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +io.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +io.$(OBJEXT): {$(VPATH)}internal/core/robject.h +io.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +io.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +io.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +io.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +io.$(OBJEXT): {$(VPATH)}internal/ctype.h +io.$(OBJEXT): {$(VPATH)}internal/dllexport.h +io.$(OBJEXT): {$(VPATH)}internal/dosish.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +io.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +io.$(OBJEXT): {$(VPATH)}internal/error.h +io.$(OBJEXT): {$(VPATH)}internal/eval.h +io.$(OBJEXT): {$(VPATH)}internal/event.h +io.$(OBJEXT): {$(VPATH)}internal/fl_type.h +io.$(OBJEXT): {$(VPATH)}internal/gc.h +io.$(OBJEXT): {$(VPATH)}internal/glob.h +io.$(OBJEXT): {$(VPATH)}internal/globals.h +io.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +io.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +io.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +io.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +io.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +io.$(OBJEXT): {$(VPATH)}internal/has/extension.h +io.$(OBJEXT): {$(VPATH)}internal/has/feature.h +io.$(OBJEXT): {$(VPATH)}internal/has/warning.h +io.$(OBJEXT): {$(VPATH)}internal/intern/array.h +io.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +io.$(OBJEXT): {$(VPATH)}internal/intern/class.h +io.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +io.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +io.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +io.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +io.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +io.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +io.$(OBJEXT): {$(VPATH)}internal/intern/error.h +io.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +io.$(OBJEXT): {$(VPATH)}internal/intern/file.h +io.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +io.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +io.$(OBJEXT): {$(VPATH)}internal/intern/io.h +io.$(OBJEXT): {$(VPATH)}internal/intern/load.h +io.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +io.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +io.$(OBJEXT): {$(VPATH)}internal/intern/object.h +io.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +io.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +io.$(OBJEXT): {$(VPATH)}internal/intern/process.h +io.$(OBJEXT): {$(VPATH)}internal/intern/random.h +io.$(OBJEXT): {$(VPATH)}internal/intern/range.h +io.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +io.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +io.$(OBJEXT): {$(VPATH)}internal/intern/string.h +io.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +io.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +io.$(OBJEXT): {$(VPATH)}internal/intern/time.h +io.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +io.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +io.$(OBJEXT): {$(VPATH)}internal/interpreter.h +io.$(OBJEXT): {$(VPATH)}internal/iterator.h +io.$(OBJEXT): {$(VPATH)}internal/memory.h +io.$(OBJEXT): {$(VPATH)}internal/method.h +io.$(OBJEXT): {$(VPATH)}internal/module.h +io.$(OBJEXT): {$(VPATH)}internal/newobj.h +io.$(OBJEXT): {$(VPATH)}internal/rgengc.h +io.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +io.$(OBJEXT): {$(VPATH)}internal/value.h +io.$(OBJEXT): {$(VPATH)}internal/value_type.h +io.$(OBJEXT): {$(VPATH)}internal/variable.h +io.$(OBJEXT): {$(VPATH)}internal/warning_push.h +io.$(OBJEXT): {$(VPATH)}internal/xmalloc.h io.$(OBJEXT): {$(VPATH)}io.c io.$(OBJEXT): {$(VPATH)}io.h io.$(OBJEXT): {$(VPATH)}io.rbinc +io.$(OBJEXT): {$(VPATH)}io/buffer.h io.$(OBJEXT): {$(VPATH)}method.h io.$(OBJEXT): {$(VPATH)}missing.h io.$(OBJEXT): {$(VPATH)}node.h io.$(OBJEXT): {$(VPATH)}onigmo.h io.$(OBJEXT): {$(VPATH)}oniguruma.h +io.$(OBJEXT): {$(VPATH)}ractor.h io.$(OBJEXT): {$(VPATH)}ruby_assert.h io.$(OBJEXT): {$(VPATH)}ruby_atomic.h io.$(OBJEXT): {$(VPATH)}st.h @@ -2237,17 +7569,228 @@ io.$(OBJEXT): {$(VPATH)}thread_native.h io.$(OBJEXT): {$(VPATH)}util.h io.$(OBJEXT): {$(VPATH)}vm_core.h io.$(OBJEXT): {$(VPATH)}vm_opts.h +io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.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/static_assert.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/string.h +io_buffer.$(OBJEXT): {$(VPATH)}assert.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 +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/limits.h +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +io_buffer.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +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)}intern.h +io_buffer.$(OBJEXT): {$(VPATH)}internal.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/anyargs.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/assume.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/const.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/error.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/format.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/cast.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/config.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/constant_p.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/robject.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/ctype.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/dllexport.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/dosish.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/error.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/eval.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/event.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/fl_type.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/gc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/glob.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/globals.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/extension.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/feature.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/has/warning.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/array.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/class.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/error.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/file.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/io.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/load.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/object.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/process.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/random.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/range.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/string.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/time.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/interpreter.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/iterator.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/memory.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/method.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/module.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/newobj.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/rgengc.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/value.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/value_type.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/variable.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/warning_push.h +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)}missing.h +io_buffer.$(OBJEXT): {$(VPATH)}onigmo.h +io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h +io_buffer.$(OBJEXT): {$(VPATH)}st.h +io_buffer.$(OBJEXT): {$(VPATH)}subst.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): $(top_srcdir)/internal/array.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/error.h +iseq.$(OBJEXT): $(top_srcdir)/internal/file.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/parse.h +iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h +iseq.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +iseq.$(OBJEXT): $(top_srcdir)/internal/string.h +iseq.$(OBJEXT): $(top_srcdir)/internal/symbol.h +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): {$(VPATH)}assert.h +iseq.$(OBJEXT): {$(VPATH)}atomic.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/bool.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/limits.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +iseq.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h iseq.$(OBJEXT): {$(VPATH)}builtin.h iseq.$(OBJEXT): {$(VPATH)}config.h +iseq.$(OBJEXT): {$(VPATH)}constant.h +iseq.$(OBJEXT): {$(VPATH)}darray.h iseq.$(OBJEXT): {$(VPATH)}debug_counter.h iseq.$(OBJEXT): {$(VPATH)}defines.h +iseq.$(OBJEXT): {$(VPATH)}encoding.h iseq.$(OBJEXT): {$(VPATH)}eval_intern.h iseq.$(OBJEXT): {$(VPATH)}gc.h iseq.$(OBJEXT): {$(VPATH)}id.h @@ -2257,6 +7800,154 @@ iseq.$(OBJEXT): {$(VPATH)}insns.inc iseq.$(OBJEXT): {$(VPATH)}insns_info.inc iseq.$(OBJEXT): {$(VPATH)}intern.h iseq.$(OBJEXT): {$(VPATH)}internal.h +iseq.$(OBJEXT): {$(VPATH)}internal/anyargs.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +iseq.$(OBJEXT): {$(VPATH)}internal/assume.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/const.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/error.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/format.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +iseq.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +iseq.$(OBJEXT): {$(VPATH)}internal/cast.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +iseq.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +iseq.$(OBJEXT): {$(VPATH)}internal/config.h +iseq.$(OBJEXT): {$(VPATH)}internal/constant_p.h +iseq.$(OBJEXT): {$(VPATH)}internal/core.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/robject.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +iseq.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +iseq.$(OBJEXT): {$(VPATH)}internal/ctype.h +iseq.$(OBJEXT): {$(VPATH)}internal/dllexport.h +iseq.$(OBJEXT): {$(VPATH)}internal/dosish.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +iseq.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +iseq.$(OBJEXT): {$(VPATH)}internal/error.h +iseq.$(OBJEXT): {$(VPATH)}internal/eval.h +iseq.$(OBJEXT): {$(VPATH)}internal/event.h +iseq.$(OBJEXT): {$(VPATH)}internal/fl_type.h +iseq.$(OBJEXT): {$(VPATH)}internal/gc.h +iseq.$(OBJEXT): {$(VPATH)}internal/glob.h +iseq.$(OBJEXT): {$(VPATH)}internal/globals.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/extension.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/feature.h +iseq.$(OBJEXT): {$(VPATH)}internal/has/warning.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/array.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/class.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/error.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/file.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/io.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/load.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/object.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/process.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/random.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/range.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/string.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/time.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +iseq.$(OBJEXT): {$(VPATH)}internal/interpreter.h +iseq.$(OBJEXT): {$(VPATH)}internal/iterator.h +iseq.$(OBJEXT): {$(VPATH)}internal/memory.h +iseq.$(OBJEXT): {$(VPATH)}internal/method.h +iseq.$(OBJEXT): {$(VPATH)}internal/module.h +iseq.$(OBJEXT): {$(VPATH)}internal/newobj.h +iseq.$(OBJEXT): {$(VPATH)}internal/rgengc.h +iseq.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/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)}iseq.c iseq.$(OBJEXT): {$(VPATH)}iseq.h iseq.$(OBJEXT): {$(VPATH)}method.h @@ -2264,6 +7955,9 @@ iseq.$(OBJEXT): {$(VPATH)}missing.h iseq.$(OBJEXT): {$(VPATH)}mjit.h iseq.$(OBJEXT): {$(VPATH)}node.h iseq.$(OBJEXT): {$(VPATH)}node_name.inc +iseq.$(OBJEXT): {$(VPATH)}onigmo.h +iseq.$(OBJEXT): {$(VPATH)}oniguruma.h +iseq.$(OBJEXT): {$(VPATH)}ractor.h iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h iseq.$(OBJEXT): {$(VPATH)}st.h @@ -2271,23 +7965,201 @@ iseq.$(OBJEXT): {$(VPATH)}subst.h iseq.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h 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_opts.h +iseq.$(OBJEXT): {$(VPATH)}yjit.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.h load.$(OBJEXT): $(hdrdir)/ruby/ruby.h +load.$(OBJEXT): $(top_srcdir)/internal/array.h +load.$(OBJEXT): $(top_srcdir)/internal/compilers.h +load.$(OBJEXT): $(top_srcdir)/internal/dir.h +load.$(OBJEXT): $(top_srcdir)/internal/error.h +load.$(OBJEXT): $(top_srcdir)/internal/file.h +load.$(OBJEXT): $(top_srcdir)/internal/gc.h +load.$(OBJEXT): $(top_srcdir)/internal/imemo.h +load.$(OBJEXT): $(top_srcdir)/internal/load.h +load.$(OBJEXT): $(top_srcdir)/internal/parse.h +load.$(OBJEXT): $(top_srcdir)/internal/serial.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): {$(VPATH)}assert.h +load.$(OBJEXT): {$(VPATH)}atomic.h +load.$(OBJEXT): {$(VPATH)}backward/2/assume.h +load.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +load.$(OBJEXT): {$(VPATH)}backward/2/bool.h +load.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +load.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +load.$(OBJEXT): {$(VPATH)}backward/2/limits.h +load.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +load.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +load.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h load.$(OBJEXT): {$(VPATH)}config.h +load.$(OBJEXT): {$(VPATH)}constant.h +load.$(OBJEXT): {$(VPATH)}darray.h load.$(OBJEXT): {$(VPATH)}defines.h load.$(OBJEXT): {$(VPATH)}dln.h load.$(OBJEXT): {$(VPATH)}encoding.h load.$(OBJEXT): {$(VPATH)}eval_intern.h load.$(OBJEXT): {$(VPATH)}id.h +load.$(OBJEXT): {$(VPATH)}id_table.h load.$(OBJEXT): {$(VPATH)}intern.h load.$(OBJEXT): {$(VPATH)}internal.h +load.$(OBJEXT): {$(VPATH)}internal/anyargs.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +load.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +load.$(OBJEXT): {$(VPATH)}internal/assume.h +load.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +load.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +load.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +load.$(OBJEXT): {$(VPATH)}internal/attr/const.h +load.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +load.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +load.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +load.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +load.$(OBJEXT): {$(VPATH)}internal/attr/error.h +load.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +load.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +load.$(OBJEXT): {$(VPATH)}internal/attr/format.h +load.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +load.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +load.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +load.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +load.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +load.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +load.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +load.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +load.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +load.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +load.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +load.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +load.$(OBJEXT): {$(VPATH)}internal/cast.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +load.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +load.$(OBJEXT): {$(VPATH)}internal/config.h +load.$(OBJEXT): {$(VPATH)}internal/constant_p.h +load.$(OBJEXT): {$(VPATH)}internal/core.h +load.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +load.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +load.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +load.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +load.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +load.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +load.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +load.$(OBJEXT): {$(VPATH)}internal/core/robject.h +load.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +load.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +load.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +load.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +load.$(OBJEXT): {$(VPATH)}internal/ctype.h +load.$(OBJEXT): {$(VPATH)}internal/dllexport.h +load.$(OBJEXT): {$(VPATH)}internal/dosish.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +load.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +load.$(OBJEXT): {$(VPATH)}internal/error.h +load.$(OBJEXT): {$(VPATH)}internal/eval.h +load.$(OBJEXT): {$(VPATH)}internal/event.h +load.$(OBJEXT): {$(VPATH)}internal/fl_type.h +load.$(OBJEXT): {$(VPATH)}internal/gc.h +load.$(OBJEXT): {$(VPATH)}internal/glob.h +load.$(OBJEXT): {$(VPATH)}internal/globals.h +load.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +load.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +load.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +load.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +load.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +load.$(OBJEXT): {$(VPATH)}internal/has/extension.h +load.$(OBJEXT): {$(VPATH)}internal/has/feature.h +load.$(OBJEXT): {$(VPATH)}internal/has/warning.h +load.$(OBJEXT): {$(VPATH)}internal/intern/array.h +load.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +load.$(OBJEXT): {$(VPATH)}internal/intern/class.h +load.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +load.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +load.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +load.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +load.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +load.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +load.$(OBJEXT): {$(VPATH)}internal/intern/error.h +load.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +load.$(OBJEXT): {$(VPATH)}internal/intern/file.h +load.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +load.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +load.$(OBJEXT): {$(VPATH)}internal/intern/io.h +load.$(OBJEXT): {$(VPATH)}internal/intern/load.h +load.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +load.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +load.$(OBJEXT): {$(VPATH)}internal/intern/object.h +load.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +load.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +load.$(OBJEXT): {$(VPATH)}internal/intern/process.h +load.$(OBJEXT): {$(VPATH)}internal/intern/random.h +load.$(OBJEXT): {$(VPATH)}internal/intern/range.h +load.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +load.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +load.$(OBJEXT): {$(VPATH)}internal/intern/string.h +load.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +load.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +load.$(OBJEXT): {$(VPATH)}internal/intern/time.h +load.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +load.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +load.$(OBJEXT): {$(VPATH)}internal/interpreter.h +load.$(OBJEXT): {$(VPATH)}internal/iterator.h +load.$(OBJEXT): {$(VPATH)}internal/memory.h +load.$(OBJEXT): {$(VPATH)}internal/method.h +load.$(OBJEXT): {$(VPATH)}internal/module.h +load.$(OBJEXT): {$(VPATH)}internal/newobj.h +load.$(OBJEXT): {$(VPATH)}internal/rgengc.h +load.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +load.$(OBJEXT): {$(VPATH)}internal/value.h +load.$(OBJEXT): {$(VPATH)}internal/value_type.h +load.$(OBJEXT): {$(VPATH)}internal/variable.h +load.$(OBJEXT): {$(VPATH)}internal/warning_push.h +load.$(OBJEXT): {$(VPATH)}internal/xmalloc.h load.$(OBJEXT): {$(VPATH)}iseq.h load.$(OBJEXT): {$(VPATH)}load.c load.$(OBJEXT): {$(VPATH)}method.h @@ -2310,23 +8182,325 @@ loadpath.$(OBJEXT): $(hdrdir)/ruby/ruby.h loadpath.$(OBJEXT): $(hdrdir)/ruby/version.h loadpath.$(OBJEXT): $(top_srcdir)/version.h loadpath.$(OBJEXT): {$(VPATH)}assert.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/assume.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/bool.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/limits.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +loadpath.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h loadpath.$(OBJEXT): {$(VPATH)}config.h loadpath.$(OBJEXT): {$(VPATH)}defines.h loadpath.$(OBJEXT): {$(VPATH)}intern.h +loadpath.$(OBJEXT): {$(VPATH)}internal/anyargs.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +loadpath.$(OBJEXT): {$(VPATH)}internal/assume.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/const.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/error.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/format.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +loadpath.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +loadpath.$(OBJEXT): {$(VPATH)}internal/cast.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +loadpath.$(OBJEXT): {$(VPATH)}internal/config.h +loadpath.$(OBJEXT): {$(VPATH)}internal/constant_p.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/robject.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +loadpath.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +loadpath.$(OBJEXT): {$(VPATH)}internal/ctype.h +loadpath.$(OBJEXT): {$(VPATH)}internal/dllexport.h +loadpath.$(OBJEXT): {$(VPATH)}internal/dosish.h +loadpath.$(OBJEXT): {$(VPATH)}internal/error.h +loadpath.$(OBJEXT): {$(VPATH)}internal/eval.h +loadpath.$(OBJEXT): {$(VPATH)}internal/event.h +loadpath.$(OBJEXT): {$(VPATH)}internal/fl_type.h +loadpath.$(OBJEXT): {$(VPATH)}internal/gc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/glob.h +loadpath.$(OBJEXT): {$(VPATH)}internal/globals.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/extension.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/feature.h +loadpath.$(OBJEXT): {$(VPATH)}internal/has/warning.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/array.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/class.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/error.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/file.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/io.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/load.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/object.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/process.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/random.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/range.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/string.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/time.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +loadpath.$(OBJEXT): {$(VPATH)}internal/interpreter.h +loadpath.$(OBJEXT): {$(VPATH)}internal/iterator.h +loadpath.$(OBJEXT): {$(VPATH)}internal/memory.h +loadpath.$(OBJEXT): {$(VPATH)}internal/method.h +loadpath.$(OBJEXT): {$(VPATH)}internal/module.h +loadpath.$(OBJEXT): {$(VPATH)}internal/newobj.h +loadpath.$(OBJEXT): {$(VPATH)}internal/rgengc.h +loadpath.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +loadpath.$(OBJEXT): {$(VPATH)}internal/value.h +loadpath.$(OBJEXT): {$(VPATH)}internal/value_type.h +loadpath.$(OBJEXT): {$(VPATH)}internal/variable.h +loadpath.$(OBJEXT): {$(VPATH)}internal/warning_push.h +loadpath.$(OBJEXT): {$(VPATH)}internal/xmalloc.h loadpath.$(OBJEXT): {$(VPATH)}loadpath.c loadpath.$(OBJEXT): {$(VPATH)}missing.h loadpath.$(OBJEXT): {$(VPATH)}st.h loadpath.$(OBJEXT): {$(VPATH)}subst.h loadpath.$(OBJEXT): {$(VPATH)}verconf.h -localeinit.$(OBJEXT): $(hdrdir)/ruby.h localeinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h localeinit.$(OBJEXT): {$(VPATH)}assert.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +localeinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h localeinit.$(OBJEXT): {$(VPATH)}config.h localeinit.$(OBJEXT): {$(VPATH)}defines.h localeinit.$(OBJEXT): {$(VPATH)}encindex.h localeinit.$(OBJEXT): {$(VPATH)}encoding.h localeinit.$(OBJEXT): {$(VPATH)}intern.h localeinit.$(OBJEXT): {$(VPATH)}internal.h +localeinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +localeinit.$(OBJEXT): {$(VPATH)}internal/assume.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +localeinit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +localeinit.$(OBJEXT): {$(VPATH)}internal/cast.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +localeinit.$(OBJEXT): {$(VPATH)}internal/config.h +localeinit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +localeinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +localeinit.$(OBJEXT): {$(VPATH)}internal/ctype.h +localeinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +localeinit.$(OBJEXT): {$(VPATH)}internal/dosish.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +localeinit.$(OBJEXT): {$(VPATH)}internal/error.h +localeinit.$(OBJEXT): {$(VPATH)}internal/eval.h +localeinit.$(OBJEXT): {$(VPATH)}internal/event.h +localeinit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +localeinit.$(OBJEXT): {$(VPATH)}internal/gc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/glob.h +localeinit.$(OBJEXT): {$(VPATH)}internal/globals.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +localeinit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +localeinit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +localeinit.$(OBJEXT): {$(VPATH)}internal/iterator.h +localeinit.$(OBJEXT): {$(VPATH)}internal/memory.h +localeinit.$(OBJEXT): {$(VPATH)}internal/method.h +localeinit.$(OBJEXT): {$(VPATH)}internal/module.h +localeinit.$(OBJEXT): {$(VPATH)}internal/newobj.h +localeinit.$(OBJEXT): {$(VPATH)}internal/rgengc.h +localeinit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +localeinit.$(OBJEXT): {$(VPATH)}internal/value.h +localeinit.$(OBJEXT): {$(VPATH)}internal/value_type.h +localeinit.$(OBJEXT): {$(VPATH)}internal/variable.h +localeinit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +localeinit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h localeinit.$(OBJEXT): {$(VPATH)}localeinit.c localeinit.$(OBJEXT): {$(VPATH)}missing.h localeinit.$(OBJEXT): {$(VPATH)}onigmo.h @@ -2337,18 +8511,190 @@ main.$(OBJEXT): $(hdrdir)/ruby.h main.$(OBJEXT): $(hdrdir)/ruby/ruby.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/inttypes.h +main.$(OBJEXT): {$(VPATH)}backward/2/limits.h +main.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +main.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +main.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h main.$(OBJEXT): {$(VPATH)}config.h main.$(OBJEXT): {$(VPATH)}defines.h main.$(OBJEXT): {$(VPATH)}intern.h +main.$(OBJEXT): {$(VPATH)}internal/anyargs.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +main.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +main.$(OBJEXT): {$(VPATH)}internal/assume.h +main.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +main.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +main.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +main.$(OBJEXT): {$(VPATH)}internal/attr/const.h +main.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +main.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +main.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +main.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +main.$(OBJEXT): {$(VPATH)}internal/attr/error.h +main.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +main.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +main.$(OBJEXT): {$(VPATH)}internal/attr/format.h +main.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +main.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +main.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +main.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +main.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +main.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +main.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +main.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +main.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +main.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +main.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +main.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +main.$(OBJEXT): {$(VPATH)}internal/cast.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +main.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +main.$(OBJEXT): {$(VPATH)}internal/config.h +main.$(OBJEXT): {$(VPATH)}internal/constant_p.h +main.$(OBJEXT): {$(VPATH)}internal/core.h +main.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +main.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +main.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +main.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +main.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +main.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +main.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +main.$(OBJEXT): {$(VPATH)}internal/core/robject.h +main.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +main.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +main.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +main.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +main.$(OBJEXT): {$(VPATH)}internal/ctype.h +main.$(OBJEXT): {$(VPATH)}internal/dllexport.h +main.$(OBJEXT): {$(VPATH)}internal/dosish.h +main.$(OBJEXT): {$(VPATH)}internal/error.h +main.$(OBJEXT): {$(VPATH)}internal/eval.h +main.$(OBJEXT): {$(VPATH)}internal/event.h +main.$(OBJEXT): {$(VPATH)}internal/fl_type.h +main.$(OBJEXT): {$(VPATH)}internal/gc.h +main.$(OBJEXT): {$(VPATH)}internal/glob.h +main.$(OBJEXT): {$(VPATH)}internal/globals.h +main.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +main.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +main.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +main.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +main.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +main.$(OBJEXT): {$(VPATH)}internal/has/extension.h +main.$(OBJEXT): {$(VPATH)}internal/has/feature.h +main.$(OBJEXT): {$(VPATH)}internal/has/warning.h +main.$(OBJEXT): {$(VPATH)}internal/intern/array.h +main.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +main.$(OBJEXT): {$(VPATH)}internal/intern/class.h +main.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +main.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +main.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +main.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +main.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +main.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +main.$(OBJEXT): {$(VPATH)}internal/intern/error.h +main.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +main.$(OBJEXT): {$(VPATH)}internal/intern/file.h +main.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +main.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +main.$(OBJEXT): {$(VPATH)}internal/intern/io.h +main.$(OBJEXT): {$(VPATH)}internal/intern/load.h +main.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +main.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +main.$(OBJEXT): {$(VPATH)}internal/intern/object.h +main.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +main.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +main.$(OBJEXT): {$(VPATH)}internal/intern/process.h +main.$(OBJEXT): {$(VPATH)}internal/intern/random.h +main.$(OBJEXT): {$(VPATH)}internal/intern/range.h +main.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +main.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +main.$(OBJEXT): {$(VPATH)}internal/intern/string.h +main.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +main.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +main.$(OBJEXT): {$(VPATH)}internal/intern/time.h +main.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +main.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +main.$(OBJEXT): {$(VPATH)}internal/interpreter.h +main.$(OBJEXT): {$(VPATH)}internal/iterator.h +main.$(OBJEXT): {$(VPATH)}internal/memory.h +main.$(OBJEXT): {$(VPATH)}internal/method.h +main.$(OBJEXT): {$(VPATH)}internal/module.h +main.$(OBJEXT): {$(VPATH)}internal/newobj.h +main.$(OBJEXT): {$(VPATH)}internal/rgengc.h +main.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +main.$(OBJEXT): {$(VPATH)}internal/value.h +main.$(OBJEXT): {$(VPATH)}internal/value_type.h +main.$(OBJEXT): {$(VPATH)}internal/variable.h +main.$(OBJEXT): {$(VPATH)}internal/warning_push.h +main.$(OBJEXT): {$(VPATH)}internal/xmalloc.h main.$(OBJEXT): {$(VPATH)}main.c main.$(OBJEXT): {$(VPATH)}missing.h -main.$(OBJEXT): {$(VPATH)}node.h main.$(OBJEXT): {$(VPATH)}st.h main.$(OBJEXT): {$(VPATH)}subst.h main.$(OBJEXT): {$(VPATH)}vm_debug.h -marshal.$(OBJEXT): $(hdrdir)/ruby.h marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h +marshal.$(OBJEXT): $(top_srcdir)/internal/array.h +marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h +marshal.$(OBJEXT): $(top_srcdir)/internal/class.h +marshal.$(OBJEXT): $(top_srcdir)/internal/compilers.h +marshal.$(OBJEXT): $(top_srcdir)/internal/encoding.h +marshal.$(OBJEXT): $(top_srcdir)/internal/error.h +marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h +marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h +marshal.$(OBJEXT): $(top_srcdir)/internal/object.h +marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h +marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +marshal.$(OBJEXT): $(top_srcdir)/internal/string.h +marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h +marshal.$(OBJEXT): $(top_srcdir)/internal/symbol.h +marshal.$(OBJEXT): $(top_srcdir)/internal/util.h +marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h +marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h marshal.$(OBJEXT): {$(VPATH)}assert.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/assume.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/bool.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/limits.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +marshal.$(OBJEXT): {$(VPATH)}builtin.h marshal.$(OBJEXT): {$(VPATH)}config.h marshal.$(OBJEXT): {$(VPATH)}defines.h marshal.$(OBJEXT): {$(VPATH)}encindex.h @@ -2356,82 +8702,910 @@ marshal.$(OBJEXT): {$(VPATH)}encoding.h marshal.$(OBJEXT): {$(VPATH)}id_table.h marshal.$(OBJEXT): {$(VPATH)}intern.h marshal.$(OBJEXT): {$(VPATH)}internal.h +marshal.$(OBJEXT): {$(VPATH)}internal/anyargs.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +marshal.$(OBJEXT): {$(VPATH)}internal/assume.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/const.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/error.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/format.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +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/noreturn.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +marshal.$(OBJEXT): {$(VPATH)}internal/cast.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +marshal.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +marshal.$(OBJEXT): {$(VPATH)}internal/config.h +marshal.$(OBJEXT): {$(VPATH)}internal/constant_p.h +marshal.$(OBJEXT): {$(VPATH)}internal/core.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/robject.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +marshal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +marshal.$(OBJEXT): {$(VPATH)}internal/ctype.h +marshal.$(OBJEXT): {$(VPATH)}internal/dllexport.h +marshal.$(OBJEXT): {$(VPATH)}internal/dosish.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +marshal.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +marshal.$(OBJEXT): {$(VPATH)}internal/error.h +marshal.$(OBJEXT): {$(VPATH)}internal/eval.h +marshal.$(OBJEXT): {$(VPATH)}internal/event.h +marshal.$(OBJEXT): {$(VPATH)}internal/fl_type.h +marshal.$(OBJEXT): {$(VPATH)}internal/gc.h +marshal.$(OBJEXT): {$(VPATH)}internal/glob.h +marshal.$(OBJEXT): {$(VPATH)}internal/globals.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/extension.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/feature.h +marshal.$(OBJEXT): {$(VPATH)}internal/has/warning.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/array.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/class.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/error.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/file.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/io.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/load.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/object.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/process.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/random.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/range.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/string.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/time.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +marshal.$(OBJEXT): {$(VPATH)}internal/interpreter.h +marshal.$(OBJEXT): {$(VPATH)}internal/iterator.h +marshal.$(OBJEXT): {$(VPATH)}internal/memory.h +marshal.$(OBJEXT): {$(VPATH)}internal/method.h +marshal.$(OBJEXT): {$(VPATH)}internal/module.h +marshal.$(OBJEXT): {$(VPATH)}internal/newobj.h +marshal.$(OBJEXT): {$(VPATH)}internal/rgengc.h +marshal.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +marshal.$(OBJEXT): {$(VPATH)}internal/value.h +marshal.$(OBJEXT): {$(VPATH)}internal/value_type.h +marshal.$(OBJEXT): {$(VPATH)}internal/variable.h +marshal.$(OBJEXT): {$(VPATH)}internal/warning_push.h +marshal.$(OBJEXT): {$(VPATH)}internal/xmalloc.h marshal.$(OBJEXT): {$(VPATH)}io.h marshal.$(OBJEXT): {$(VPATH)}marshal.c +marshal.$(OBJEXT): {$(VPATH)}marshal.rbinc marshal.$(OBJEXT): {$(VPATH)}missing.h marshal.$(OBJEXT): {$(VPATH)}onigmo.h marshal.$(OBJEXT): {$(VPATH)}oniguruma.h marshal.$(OBJEXT): {$(VPATH)}st.h marshal.$(OBJEXT): {$(VPATH)}subst.h marshal.$(OBJEXT): {$(VPATH)}util.h -math.$(OBJEXT): $(hdrdir)/ruby.h math.$(OBJEXT): $(hdrdir)/ruby/ruby.h +math.$(OBJEXT): $(top_srcdir)/internal/bignum.h +math.$(OBJEXT): $(top_srcdir)/internal/class.h +math.$(OBJEXT): $(top_srcdir)/internal/compilers.h +math.$(OBJEXT): $(top_srcdir)/internal/complex.h +math.$(OBJEXT): $(top_srcdir)/internal/gc.h +math.$(OBJEXT): $(top_srcdir)/internal/math.h +math.$(OBJEXT): $(top_srcdir)/internal/object.h +math.$(OBJEXT): $(top_srcdir)/internal/serial.h +math.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +math.$(OBJEXT): $(top_srcdir)/internal/vm.h +math.$(OBJEXT): $(top_srcdir)/internal/warnings.h math.$(OBJEXT): {$(VPATH)}assert.h +math.$(OBJEXT): {$(VPATH)}backward/2/assume.h +math.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +math.$(OBJEXT): {$(VPATH)}backward/2/bool.h +math.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +math.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +math.$(OBJEXT): {$(VPATH)}backward/2/limits.h +math.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +math.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +math.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h math.$(OBJEXT): {$(VPATH)}config.h math.$(OBJEXT): {$(VPATH)}defines.h +math.$(OBJEXT): {$(VPATH)}id_table.h math.$(OBJEXT): {$(VPATH)}intern.h math.$(OBJEXT): {$(VPATH)}internal.h +math.$(OBJEXT): {$(VPATH)}internal/anyargs.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +math.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +math.$(OBJEXT): {$(VPATH)}internal/assume.h +math.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +math.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +math.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +math.$(OBJEXT): {$(VPATH)}internal/attr/const.h +math.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +math.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +math.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +math.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +math.$(OBJEXT): {$(VPATH)}internal/attr/error.h +math.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +math.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +math.$(OBJEXT): {$(VPATH)}internal/attr/format.h +math.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +math.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +math.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +math.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +math.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +math.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +math.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +math.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +math.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +math.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +math.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +math.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +math.$(OBJEXT): {$(VPATH)}internal/cast.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +math.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +math.$(OBJEXT): {$(VPATH)}internal/config.h +math.$(OBJEXT): {$(VPATH)}internal/constant_p.h +math.$(OBJEXT): {$(VPATH)}internal/core.h +math.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +math.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +math.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +math.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +math.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +math.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +math.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +math.$(OBJEXT): {$(VPATH)}internal/core/robject.h +math.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +math.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +math.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +math.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +math.$(OBJEXT): {$(VPATH)}internal/ctype.h +math.$(OBJEXT): {$(VPATH)}internal/dllexport.h +math.$(OBJEXT): {$(VPATH)}internal/dosish.h +math.$(OBJEXT): {$(VPATH)}internal/error.h +math.$(OBJEXT): {$(VPATH)}internal/eval.h +math.$(OBJEXT): {$(VPATH)}internal/event.h +math.$(OBJEXT): {$(VPATH)}internal/fl_type.h +math.$(OBJEXT): {$(VPATH)}internal/gc.h +math.$(OBJEXT): {$(VPATH)}internal/glob.h +math.$(OBJEXT): {$(VPATH)}internal/globals.h +math.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +math.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +math.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +math.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +math.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +math.$(OBJEXT): {$(VPATH)}internal/has/extension.h +math.$(OBJEXT): {$(VPATH)}internal/has/feature.h +math.$(OBJEXT): {$(VPATH)}internal/has/warning.h +math.$(OBJEXT): {$(VPATH)}internal/intern/array.h +math.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +math.$(OBJEXT): {$(VPATH)}internal/intern/class.h +math.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +math.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +math.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +math.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +math.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +math.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +math.$(OBJEXT): {$(VPATH)}internal/intern/error.h +math.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +math.$(OBJEXT): {$(VPATH)}internal/intern/file.h +math.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +math.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +math.$(OBJEXT): {$(VPATH)}internal/intern/io.h +math.$(OBJEXT): {$(VPATH)}internal/intern/load.h +math.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +math.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +math.$(OBJEXT): {$(VPATH)}internal/intern/object.h +math.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +math.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +math.$(OBJEXT): {$(VPATH)}internal/intern/process.h +math.$(OBJEXT): {$(VPATH)}internal/intern/random.h +math.$(OBJEXT): {$(VPATH)}internal/intern/range.h +math.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +math.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +math.$(OBJEXT): {$(VPATH)}internal/intern/string.h +math.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +math.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +math.$(OBJEXT): {$(VPATH)}internal/intern/time.h +math.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +math.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +math.$(OBJEXT): {$(VPATH)}internal/interpreter.h +math.$(OBJEXT): {$(VPATH)}internal/iterator.h +math.$(OBJEXT): {$(VPATH)}internal/memory.h +math.$(OBJEXT): {$(VPATH)}internal/method.h +math.$(OBJEXT): {$(VPATH)}internal/module.h +math.$(OBJEXT): {$(VPATH)}internal/newobj.h +math.$(OBJEXT): {$(VPATH)}internal/rgengc.h +math.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +math.$(OBJEXT): {$(VPATH)}internal/value.h +math.$(OBJEXT): {$(VPATH)}internal/value_type.h +math.$(OBJEXT): {$(VPATH)}internal/variable.h +math.$(OBJEXT): {$(VPATH)}internal/warning_push.h +math.$(OBJEXT): {$(VPATH)}internal/xmalloc.h math.$(OBJEXT): {$(VPATH)}math.c math.$(OBJEXT): {$(VPATH)}missing.h math.$(OBJEXT): {$(VPATH)}st.h math.$(OBJEXT): {$(VPATH)}subst.h +memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h +memory_view.$(OBJEXT): {$(VPATH)}assert.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/assume.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/bool.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/limits.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +memory_view.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +memory_view.$(OBJEXT): {$(VPATH)}config.h +memory_view.$(OBJEXT): {$(VPATH)}constant.h +memory_view.$(OBJEXT): {$(VPATH)}debug_counter.h +memory_view.$(OBJEXT): {$(VPATH)}defines.h +memory_view.$(OBJEXT): {$(VPATH)}id_table.h +memory_view.$(OBJEXT): {$(VPATH)}intern.h +memory_view.$(OBJEXT): {$(VPATH)}internal.h +memory_view.$(OBJEXT): {$(VPATH)}internal/anyargs.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +memory_view.$(OBJEXT): {$(VPATH)}internal/assume.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/const.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/error.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/format.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +memory_view.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +memory_view.$(OBJEXT): {$(VPATH)}internal/cast.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +memory_view.$(OBJEXT): {$(VPATH)}internal/config.h +memory_view.$(OBJEXT): {$(VPATH)}internal/constant_p.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/robject.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +memory_view.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +memory_view.$(OBJEXT): {$(VPATH)}internal/ctype.h +memory_view.$(OBJEXT): {$(VPATH)}internal/dllexport.h +memory_view.$(OBJEXT): {$(VPATH)}internal/dosish.h +memory_view.$(OBJEXT): {$(VPATH)}internal/error.h +memory_view.$(OBJEXT): {$(VPATH)}internal/eval.h +memory_view.$(OBJEXT): {$(VPATH)}internal/event.h +memory_view.$(OBJEXT): {$(VPATH)}internal/fl_type.h +memory_view.$(OBJEXT): {$(VPATH)}internal/gc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/glob.h +memory_view.$(OBJEXT): {$(VPATH)}internal/globals.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/extension.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/feature.h +memory_view.$(OBJEXT): {$(VPATH)}internal/has/warning.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/array.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/class.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/error.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/file.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/io.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/load.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/object.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/process.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/random.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/range.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/string.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/time.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +memory_view.$(OBJEXT): {$(VPATH)}internal/interpreter.h +memory_view.$(OBJEXT): {$(VPATH)}internal/iterator.h +memory_view.$(OBJEXT): {$(VPATH)}internal/memory.h +memory_view.$(OBJEXT): {$(VPATH)}internal/method.h +memory_view.$(OBJEXT): {$(VPATH)}internal/module.h +memory_view.$(OBJEXT): {$(VPATH)}internal/newobj.h +memory_view.$(OBJEXT): {$(VPATH)}internal/rgengc.h +memory_view.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +memory_view.$(OBJEXT): {$(VPATH)}internal/value.h +memory_view.$(OBJEXT): {$(VPATH)}internal/value_type.h +memory_view.$(OBJEXT): {$(VPATH)}internal/variable.h +memory_view.$(OBJEXT): {$(VPATH)}internal/warning_push.h +memory_view.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +memory_view.$(OBJEXT): {$(VPATH)}memory_view.c +memory_view.$(OBJEXT): {$(VPATH)}memory_view.h +memory_view.$(OBJEXT): {$(VPATH)}missing.h +memory_view.$(OBJEXT): {$(VPATH)}st.h +memory_view.$(OBJEXT): {$(VPATH)}subst.h +memory_view.$(OBJEXT): {$(VPATH)}util.h +memory_view.$(OBJEXT): {$(VPATH)}vm_debug.h +memory_view.$(OBJEXT): {$(VPATH)}vm_sync.h miniinit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +miniinit.$(OBJEXT): {$(VPATH)}array.rb miniinit.$(OBJEXT): {$(VPATH)}assert.h miniinit.$(OBJEXT): {$(VPATH)}ast.rb +miniinit.$(OBJEXT): {$(VPATH)}atomic.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h miniinit.$(OBJEXT): {$(VPATH)}builtin.h miniinit.$(OBJEXT): {$(VPATH)}config.h +miniinit.$(OBJEXT): {$(VPATH)}darray.h miniinit.$(OBJEXT): {$(VPATH)}defines.h +miniinit.$(OBJEXT): {$(VPATH)}dir.rb miniinit.$(OBJEXT): {$(VPATH)}encoding.h miniinit.$(OBJEXT): {$(VPATH)}gc.rb miniinit.$(OBJEXT): {$(VPATH)}gem_prelude.rb miniinit.$(OBJEXT): {$(VPATH)}id.h miniinit.$(OBJEXT): {$(VPATH)}intern.h miniinit.$(OBJEXT): {$(VPATH)}internal.h +miniinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +miniinit.$(OBJEXT): {$(VPATH)}internal/assume.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +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/noreturn.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +miniinit.$(OBJEXT): {$(VPATH)}internal/cast.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +miniinit.$(OBJEXT): {$(VPATH)}internal/config.h +miniinit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +miniinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +miniinit.$(OBJEXT): {$(VPATH)}internal/ctype.h +miniinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +miniinit.$(OBJEXT): {$(VPATH)}internal/dosish.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +miniinit.$(OBJEXT): {$(VPATH)}internal/error.h +miniinit.$(OBJEXT): {$(VPATH)}internal/eval.h +miniinit.$(OBJEXT): {$(VPATH)}internal/event.h +miniinit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +miniinit.$(OBJEXT): {$(VPATH)}internal/gc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/glob.h +miniinit.$(OBJEXT): {$(VPATH)}internal/globals.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +miniinit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +miniinit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +miniinit.$(OBJEXT): {$(VPATH)}internal/iterator.h +miniinit.$(OBJEXT): {$(VPATH)}internal/memory.h +miniinit.$(OBJEXT): {$(VPATH)}internal/method.h +miniinit.$(OBJEXT): {$(VPATH)}internal/module.h +miniinit.$(OBJEXT): {$(VPATH)}internal/newobj.h +miniinit.$(OBJEXT): {$(VPATH)}internal/rgengc.h +miniinit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +miniinit.$(OBJEXT): {$(VPATH)}internal/value.h +miniinit.$(OBJEXT): {$(VPATH)}internal/value_type.h +miniinit.$(OBJEXT): {$(VPATH)}internal/variable.h +miniinit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +miniinit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h miniinit.$(OBJEXT): {$(VPATH)}io.rb miniinit.$(OBJEXT): {$(VPATH)}iseq.h +miniinit.$(OBJEXT): {$(VPATH)}kernel.rb +miniinit.$(OBJEXT): {$(VPATH)}marshal.rb miniinit.$(OBJEXT): {$(VPATH)}method.h miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c miniinit.$(OBJEXT): {$(VPATH)}miniinit.c miniinit.$(OBJEXT): {$(VPATH)}miniprelude.c miniinit.$(OBJEXT): {$(VPATH)}missing.h +miniinit.$(OBJEXT): {$(VPATH)}nilclass.rb miniinit.$(OBJEXT): {$(VPATH)}node.h +miniinit.$(OBJEXT): {$(VPATH)}numeric.rb miniinit.$(OBJEXT): {$(VPATH)}onigmo.h miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h miniinit.$(OBJEXT): {$(VPATH)}pack.rb miniinit.$(OBJEXT): {$(VPATH)}prelude.rb +miniinit.$(OBJEXT): {$(VPATH)}ractor.rb miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h miniinit.$(OBJEXT): {$(VPATH)}st.h miniinit.$(OBJEXT): {$(VPATH)}subst.h miniinit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h miniinit.$(OBJEXT): {$(VPATH)}thread_native.h +miniinit.$(OBJEXT): {$(VPATH)}timev.rb miniinit.$(OBJEXT): {$(VPATH)}trace_point.rb miniinit.$(OBJEXT): {$(VPATH)}vm_core.h miniinit.$(OBJEXT): {$(VPATH)}vm_opts.h miniinit.$(OBJEXT): {$(VPATH)}warning.rb +miniinit.$(OBJEXT): {$(VPATH)}yjit.rb mjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h mjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h mjit.$(OBJEXT): $(CCAN_DIR)/list/list.h mjit.$(OBJEXT): $(CCAN_DIR)/str/str.h mjit.$(OBJEXT): $(hdrdir)/ruby.h mjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +mjit.$(OBJEXT): $(hdrdir)/ruby/version.h +mjit.$(OBJEXT): $(top_srcdir)/internal/array.h +mjit.$(OBJEXT): $(top_srcdir)/internal/class.h +mjit.$(OBJEXT): $(top_srcdir)/internal/compile.h +mjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +mjit.$(OBJEXT): $(top_srcdir)/internal/cont.h +mjit.$(OBJEXT): $(top_srcdir)/internal/file.h +mjit.$(OBJEXT): $(top_srcdir)/internal/gc.h +mjit.$(OBJEXT): $(top_srcdir)/internal/hash.h +mjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +mjit.$(OBJEXT): $(top_srcdir)/internal/serial.h +mjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +mjit.$(OBJEXT): $(top_srcdir)/internal/vm.h +mjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h mjit.$(OBJEXT): {$(VPATH)}assert.h +mjit.$(OBJEXT): {$(VPATH)}atomic.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +mjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +mjit.$(OBJEXT): {$(VPATH)}builtin.h mjit.$(OBJEXT): {$(VPATH)}config.h mjit.$(OBJEXT): {$(VPATH)}constant.h +mjit.$(OBJEXT): {$(VPATH)}darray.h mjit.$(OBJEXT): {$(VPATH)}debug.h mjit.$(OBJEXT): {$(VPATH)}debug_counter.h mjit.$(OBJEXT): {$(VPATH)}defines.h mjit.$(OBJEXT): {$(VPATH)}dln.h +mjit.$(OBJEXT): {$(VPATH)}encoding.h mjit.$(OBJEXT): {$(VPATH)}gc.h mjit.$(OBJEXT): {$(VPATH)}id.h mjit.$(OBJEXT): {$(VPATH)}id_table.h +mjit.$(OBJEXT): {$(VPATH)}insns.def +mjit.$(OBJEXT): {$(VPATH)}insns.inc +mjit.$(OBJEXT): {$(VPATH)}insns_info.inc mjit.$(OBJEXT): {$(VPATH)}intern.h mjit.$(OBJEXT): {$(VPATH)}internal.h +mjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +mjit.$(OBJEXT): {$(VPATH)}internal/assume.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +mjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +mjit.$(OBJEXT): {$(VPATH)}internal/cast.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +mjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +mjit.$(OBJEXT): {$(VPATH)}internal/config.h +mjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +mjit.$(OBJEXT): {$(VPATH)}internal/core.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +mjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +mjit.$(OBJEXT): {$(VPATH)}internal/ctype.h +mjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +mjit.$(OBJEXT): {$(VPATH)}internal/dosish.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +mjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +mjit.$(OBJEXT): {$(VPATH)}internal/error.h +mjit.$(OBJEXT): {$(VPATH)}internal/eval.h +mjit.$(OBJEXT): {$(VPATH)}internal/event.h +mjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +mjit.$(OBJEXT): {$(VPATH)}internal/gc.h +mjit.$(OBJEXT): {$(VPATH)}internal/glob.h +mjit.$(OBJEXT): {$(VPATH)}internal/globals.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +mjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +mjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +mjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +mjit.$(OBJEXT): {$(VPATH)}internal/iterator.h +mjit.$(OBJEXT): {$(VPATH)}internal/memory.h +mjit.$(OBJEXT): {$(VPATH)}internal/method.h +mjit.$(OBJEXT): {$(VPATH)}internal/module.h +mjit.$(OBJEXT): {$(VPATH)}internal/newobj.h +mjit.$(OBJEXT): {$(VPATH)}internal/rgengc.h +mjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +mjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h +mjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h +mjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h +mjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +mjit.$(OBJEXT): {$(VPATH)}internal/symbol.h +mjit.$(OBJEXT): {$(VPATH)}internal/value.h +mjit.$(OBJEXT): {$(VPATH)}internal/value_type.h +mjit.$(OBJEXT): {$(VPATH)}internal/variable.h +mjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +mjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +mjit.$(OBJEXT): {$(VPATH)}iseq.h mjit.$(OBJEXT): {$(VPATH)}method.h mjit.$(OBJEXT): {$(VPATH)}missing.h mjit.$(OBJEXT): {$(VPATH)}mjit.c @@ -2439,6 +9613,8 @@ mjit.$(OBJEXT): {$(VPATH)}mjit.h mjit.$(OBJEXT): {$(VPATH)}mjit_config.h mjit.$(OBJEXT): {$(VPATH)}mjit_worker.c mjit.$(OBJEXT): {$(VPATH)}node.h +mjit.$(OBJEXT): {$(VPATH)}onigmo.h +mjit.$(OBJEXT): {$(VPATH)}oniguruma.h mjit.$(OBJEXT): {$(VPATH)}ruby_assert.h mjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h mjit.$(OBJEXT): {$(VPATH)}st.h @@ -2447,25 +9623,194 @@ mjit.$(OBJEXT): {$(VPATH)}thread.h mjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h mjit.$(OBJEXT): {$(VPATH)}thread_native.h mjit.$(OBJEXT): {$(VPATH)}util.h +mjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h mjit.$(OBJEXT): {$(VPATH)}vm_core.h +mjit.$(OBJEXT): {$(VPATH)}vm_debug.h mjit.$(OBJEXT): {$(VPATH)}vm_opts.h +mjit.$(OBJEXT): {$(VPATH)}vm_sync.h +mjit.$(OBJEXT): {$(VPATH)}yjit.h mjit_compile.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h mjit_compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h mjit_compile.$(OBJEXT): $(CCAN_DIR)/list/list.h mjit_compile.$(OBJEXT): $(CCAN_DIR)/str/str.h mjit_compile.$(OBJEXT): $(hdrdir)/ruby.h mjit_compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/array.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/class.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compile.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compilers.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/gc.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/hash.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/object.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/serial.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/variable.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/vm.h +mjit_compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h mjit_compile.$(OBJEXT): {$(VPATH)}assert.h +mjit_compile.$(OBJEXT): {$(VPATH)}atomic.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/bool.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/limits.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h mjit_compile.$(OBJEXT): {$(VPATH)}builtin.h mjit_compile.$(OBJEXT): {$(VPATH)}config.h +mjit_compile.$(OBJEXT): {$(VPATH)}constant.h +mjit_compile.$(OBJEXT): {$(VPATH)}darray.h mjit_compile.$(OBJEXT): {$(VPATH)}debug_counter.h mjit_compile.$(OBJEXT): {$(VPATH)}defines.h mjit_compile.$(OBJEXT): {$(VPATH)}id.h +mjit_compile.$(OBJEXT): {$(VPATH)}id_table.h mjit_compile.$(OBJEXT): {$(VPATH)}insns.def mjit_compile.$(OBJEXT): {$(VPATH)}insns.inc mjit_compile.$(OBJEXT): {$(VPATH)}insns_info.inc mjit_compile.$(OBJEXT): {$(VPATH)}intern.h mjit_compile.$(OBJEXT): {$(VPATH)}internal.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/anyargs.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/assume.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/const.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/error.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/format.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/cast.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/config.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/constant_p.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/robject.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/ctype.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/dllexport.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/dosish.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/error.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/eval.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/event.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/fl_type.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/gc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/glob.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/globals.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/extension.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/feature.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/warning.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/array.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/class.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/error.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/file.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/io.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/load.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/object.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/process.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/random.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/range.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/re.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/select.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/string.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/time.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/interpreter.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/iterator.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/memory.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/method.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/module.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/newobj.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/rgengc.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/scan_args.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/special_consts.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/static_assert.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/stdalign.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/stdbool.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/symbol.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/value.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/value_type.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/variable.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h +mjit_compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h mjit_compile.$(OBJEXT): {$(VPATH)}iseq.h mjit_compile.$(OBJEXT): {$(VPATH)}method.h mjit_compile.$(OBJEXT): {$(VPATH)}missing.h @@ -2479,22 +9824,185 @@ mjit_compile.$(OBJEXT): {$(VPATH)}st.h mjit_compile.$(OBJEXT): {$(VPATH)}subst.h mjit_compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h mjit_compile.$(OBJEXT): {$(VPATH)}thread_native.h +mjit_compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h mjit_compile.$(OBJEXT): {$(VPATH)}vm_core.h mjit_compile.$(OBJEXT): {$(VPATH)}vm_exec.h mjit_compile.$(OBJEXT): {$(VPATH)}vm_insnhelper.h mjit_compile.$(OBJEXT): {$(VPATH)}vm_opts.h +mjit_compile.$(OBJEXT): {$(VPATH)}yjit.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 node.$(OBJEXT): $(CCAN_DIR)/str/str.h -node.$(OBJEXT): $(hdrdir)/ruby.h node.$(OBJEXT): $(hdrdir)/ruby/ruby.h +node.$(OBJEXT): $(top_srcdir)/internal/array.h +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/serial.h +node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +node.$(OBJEXT): $(top_srcdir)/internal/variable.h +node.$(OBJEXT): $(top_srcdir)/internal/vm.h +node.$(OBJEXT): $(top_srcdir)/internal/warnings.h node.$(OBJEXT): {$(VPATH)}assert.h +node.$(OBJEXT): {$(VPATH)}atomic.h +node.$(OBJEXT): {$(VPATH)}backward/2/assume.h +node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +node.$(OBJEXT): {$(VPATH)}backward/2/bool.h +node.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +node.$(OBJEXT): {$(VPATH)}backward/2/limits.h +node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h node.$(OBJEXT): {$(VPATH)}config.h +node.$(OBJEXT): {$(VPATH)}constant.h +node.$(OBJEXT): {$(VPATH)}darray.h node.$(OBJEXT): {$(VPATH)}defines.h node.$(OBJEXT): {$(VPATH)}id.h +node.$(OBJEXT): {$(VPATH)}id_table.h node.$(OBJEXT): {$(VPATH)}intern.h node.$(OBJEXT): {$(VPATH)}internal.h +node.$(OBJEXT): {$(VPATH)}internal/anyargs.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +node.$(OBJEXT): {$(VPATH)}internal/assume.h +node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +node.$(OBJEXT): {$(VPATH)}internal/attr/const.h +node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +node.$(OBJEXT): {$(VPATH)}internal/attr/error.h +node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +node.$(OBJEXT): {$(VPATH)}internal/attr/format.h +node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +node.$(OBJEXT): {$(VPATH)}internal/cast.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +node.$(OBJEXT): {$(VPATH)}internal/config.h +node.$(OBJEXT): {$(VPATH)}internal/constant_p.h +node.$(OBJEXT): {$(VPATH)}internal/core.h +node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +node.$(OBJEXT): {$(VPATH)}internal/core/robject.h +node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +node.$(OBJEXT): {$(VPATH)}internal/ctype.h +node.$(OBJEXT): {$(VPATH)}internal/dllexport.h +node.$(OBJEXT): {$(VPATH)}internal/dosish.h +node.$(OBJEXT): {$(VPATH)}internal/error.h +node.$(OBJEXT): {$(VPATH)}internal/eval.h +node.$(OBJEXT): {$(VPATH)}internal/event.h +node.$(OBJEXT): {$(VPATH)}internal/fl_type.h +node.$(OBJEXT): {$(VPATH)}internal/gc.h +node.$(OBJEXT): {$(VPATH)}internal/glob.h +node.$(OBJEXT): {$(VPATH)}internal/globals.h +node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +node.$(OBJEXT): {$(VPATH)}internal/has/extension.h +node.$(OBJEXT): {$(VPATH)}internal/has/feature.h +node.$(OBJEXT): {$(VPATH)}internal/has/warning.h +node.$(OBJEXT): {$(VPATH)}internal/intern/array.h +node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +node.$(OBJEXT): {$(VPATH)}internal/intern/class.h +node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +node.$(OBJEXT): {$(VPATH)}internal/intern/error.h +node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +node.$(OBJEXT): {$(VPATH)}internal/intern/file.h +node.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +node.$(OBJEXT): {$(VPATH)}internal/intern/io.h +node.$(OBJEXT): {$(VPATH)}internal/intern/load.h +node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +node.$(OBJEXT): {$(VPATH)}internal/intern/object.h +node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +node.$(OBJEXT): {$(VPATH)}internal/intern/process.h +node.$(OBJEXT): {$(VPATH)}internal/intern/random.h +node.$(OBJEXT): {$(VPATH)}internal/intern/range.h +node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +node.$(OBJEXT): {$(VPATH)}internal/intern/string.h +node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +node.$(OBJEXT): {$(VPATH)}internal/intern/time.h +node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +node.$(OBJEXT): {$(VPATH)}internal/interpreter.h +node.$(OBJEXT): {$(VPATH)}internal/iterator.h +node.$(OBJEXT): {$(VPATH)}internal/memory.h +node.$(OBJEXT): {$(VPATH)}internal/method.h +node.$(OBJEXT): {$(VPATH)}internal/module.h +node.$(OBJEXT): {$(VPATH)}internal/newobj.h +node.$(OBJEXT): {$(VPATH)}internal/rgengc.h +node.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +node.$(OBJEXT): {$(VPATH)}internal/value.h +node.$(OBJEXT): {$(VPATH)}internal/value_type.h +node.$(OBJEXT): {$(VPATH)}internal/variable.h +node.$(OBJEXT): {$(VPATH)}internal/warning_push.h +node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h node.$(OBJEXT): {$(VPATH)}method.h node.$(OBJEXT): {$(VPATH)}missing.h node.$(OBJEXT): {$(VPATH)}node.c @@ -2507,33 +10015,396 @@ node.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h node.$(OBJEXT): {$(VPATH)}thread_native.h node.$(OBJEXT): {$(VPATH)}vm_core.h node.$(OBJEXT): {$(VPATH)}vm_opts.h -numeric.$(OBJEXT): $(hdrdir)/ruby.h numeric.$(OBJEXT): $(hdrdir)/ruby/ruby.h +numeric.$(OBJEXT): $(top_srcdir)/internal/array.h +numeric.$(OBJEXT): $(top_srcdir)/internal/bignum.h +numeric.$(OBJEXT): $(top_srcdir)/internal/bits.h +numeric.$(OBJEXT): $(top_srcdir)/internal/class.h +numeric.$(OBJEXT): $(top_srcdir)/internal/compilers.h +numeric.$(OBJEXT): $(top_srcdir)/internal/complex.h +numeric.$(OBJEXT): $(top_srcdir)/internal/enumerator.h +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/numeric.h +numeric.$(OBJEXT): $(top_srcdir)/internal/object.h +numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h +numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h +numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +numeric.$(OBJEXT): $(top_srcdir)/internal/string.h +numeric.$(OBJEXT): $(top_srcdir)/internal/util.h +numeric.$(OBJEXT): $(top_srcdir)/internal/variable.h +numeric.$(OBJEXT): $(top_srcdir)/internal/vm.h +numeric.$(OBJEXT): $(top_srcdir)/internal/warnings.h numeric.$(OBJEXT): {$(VPATH)}assert.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/assume.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/bool.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/limits.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +numeric.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +numeric.$(OBJEXT): {$(VPATH)}builtin.h numeric.$(OBJEXT): {$(VPATH)}config.h +numeric.$(OBJEXT): {$(VPATH)}constant.h numeric.$(OBJEXT): {$(VPATH)}defines.h numeric.$(OBJEXT): {$(VPATH)}encoding.h numeric.$(OBJEXT): {$(VPATH)}id.h +numeric.$(OBJEXT): {$(VPATH)}id_table.h numeric.$(OBJEXT): {$(VPATH)}intern.h numeric.$(OBJEXT): {$(VPATH)}internal.h +numeric.$(OBJEXT): {$(VPATH)}internal/anyargs.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +numeric.$(OBJEXT): {$(VPATH)}internal/assume.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/const.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/error.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/format.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +numeric.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +numeric.$(OBJEXT): {$(VPATH)}internal/cast.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +numeric.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +numeric.$(OBJEXT): {$(VPATH)}internal/config.h +numeric.$(OBJEXT): {$(VPATH)}internal/constant_p.h +numeric.$(OBJEXT): {$(VPATH)}internal/core.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/robject.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +numeric.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +numeric.$(OBJEXT): {$(VPATH)}internal/ctype.h +numeric.$(OBJEXT): {$(VPATH)}internal/dllexport.h +numeric.$(OBJEXT): {$(VPATH)}internal/dosish.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +numeric.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +numeric.$(OBJEXT): {$(VPATH)}internal/error.h +numeric.$(OBJEXT): {$(VPATH)}internal/eval.h +numeric.$(OBJEXT): {$(VPATH)}internal/event.h +numeric.$(OBJEXT): {$(VPATH)}internal/fl_type.h +numeric.$(OBJEXT): {$(VPATH)}internal/gc.h +numeric.$(OBJEXT): {$(VPATH)}internal/glob.h +numeric.$(OBJEXT): {$(VPATH)}internal/globals.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/extension.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/feature.h +numeric.$(OBJEXT): {$(VPATH)}internal/has/warning.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/array.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/class.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/error.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/file.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/io.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/load.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/object.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/process.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/random.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/range.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/string.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/time.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +numeric.$(OBJEXT): {$(VPATH)}internal/interpreter.h +numeric.$(OBJEXT): {$(VPATH)}internal/iterator.h +numeric.$(OBJEXT): {$(VPATH)}internal/memory.h +numeric.$(OBJEXT): {$(VPATH)}internal/method.h +numeric.$(OBJEXT): {$(VPATH)}internal/module.h +numeric.$(OBJEXT): {$(VPATH)}internal/newobj.h +numeric.$(OBJEXT): {$(VPATH)}internal/rgengc.h +numeric.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +numeric.$(OBJEXT): {$(VPATH)}internal/value.h +numeric.$(OBJEXT): {$(VPATH)}internal/value_type.h +numeric.$(OBJEXT): {$(VPATH)}internal/variable.h +numeric.$(OBJEXT): {$(VPATH)}internal/warning_push.h +numeric.$(OBJEXT): {$(VPATH)}internal/xmalloc.h numeric.$(OBJEXT): {$(VPATH)}missing.h numeric.$(OBJEXT): {$(VPATH)}numeric.c +numeric.$(OBJEXT): {$(VPATH)}numeric.rb +numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc numeric.$(OBJEXT): {$(VPATH)}onigmo.h numeric.$(OBJEXT): {$(VPATH)}oniguruma.h +numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h numeric.$(OBJEXT): {$(VPATH)}st.h numeric.$(OBJEXT): {$(VPATH)}subst.h numeric.$(OBJEXT): {$(VPATH)}util.h -object.$(OBJEXT): $(hdrdir)/ruby.h object.$(OBJEXT): $(hdrdir)/ruby/ruby.h +object.$(OBJEXT): $(top_srcdir)/internal/array.h +object.$(OBJEXT): $(top_srcdir)/internal/bignum.h +object.$(OBJEXT): $(top_srcdir)/internal/bits.h +object.$(OBJEXT): $(top_srcdir)/internal/class.h +object.$(OBJEXT): $(top_srcdir)/internal/compilers.h +object.$(OBJEXT): $(top_srcdir)/internal/error.h +object.$(OBJEXT): $(top_srcdir)/internal/eval.h +object.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +object.$(OBJEXT): $(top_srcdir)/internal/gc.h +object.$(OBJEXT): $(top_srcdir)/internal/inits.h +object.$(OBJEXT): $(top_srcdir)/internal/numeric.h +object.$(OBJEXT): $(top_srcdir)/internal/object.h +object.$(OBJEXT): $(top_srcdir)/internal/serial.h +object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +object.$(OBJEXT): $(top_srcdir)/internal/string.h +object.$(OBJEXT): $(top_srcdir)/internal/struct.h +object.$(OBJEXT): $(top_srcdir)/internal/symbol.h +object.$(OBJEXT): $(top_srcdir)/internal/variable.h +object.$(OBJEXT): $(top_srcdir)/internal/vm.h +object.$(OBJEXT): $(top_srcdir)/internal/warnings.h object.$(OBJEXT): {$(VPATH)}assert.h +object.$(OBJEXT): {$(VPATH)}backward/2/assume.h +object.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +object.$(OBJEXT): {$(VPATH)}backward/2/bool.h +object.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +object.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +object.$(OBJEXT): {$(VPATH)}backward/2/limits.h +object.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +object.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +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)}defines.h object.$(OBJEXT): {$(VPATH)}encoding.h object.$(OBJEXT): {$(VPATH)}id.h +object.$(OBJEXT): {$(VPATH)}id_table.h object.$(OBJEXT): {$(VPATH)}intern.h object.$(OBJEXT): {$(VPATH)}internal.h +object.$(OBJEXT): {$(VPATH)}internal/anyargs.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +object.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +object.$(OBJEXT): {$(VPATH)}internal/assume.h +object.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +object.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +object.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +object.$(OBJEXT): {$(VPATH)}internal/attr/const.h +object.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +object.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +object.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +object.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +object.$(OBJEXT): {$(VPATH)}internal/attr/error.h +object.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +object.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +object.$(OBJEXT): {$(VPATH)}internal/attr/format.h +object.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +object.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +object.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +object.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +object.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +object.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +object.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +object.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +object.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +object.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +object.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +object.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +object.$(OBJEXT): {$(VPATH)}internal/cast.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +object.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +object.$(OBJEXT): {$(VPATH)}internal/config.h +object.$(OBJEXT): {$(VPATH)}internal/constant_p.h +object.$(OBJEXT): {$(VPATH)}internal/core.h +object.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +object.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +object.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +object.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +object.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +object.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +object.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +object.$(OBJEXT): {$(VPATH)}internal/core/robject.h +object.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +object.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +object.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +object.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +object.$(OBJEXT): {$(VPATH)}internal/ctype.h +object.$(OBJEXT): {$(VPATH)}internal/dllexport.h +object.$(OBJEXT): {$(VPATH)}internal/dosish.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +object.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +object.$(OBJEXT): {$(VPATH)}internal/error.h +object.$(OBJEXT): {$(VPATH)}internal/eval.h +object.$(OBJEXT): {$(VPATH)}internal/event.h +object.$(OBJEXT): {$(VPATH)}internal/fl_type.h +object.$(OBJEXT): {$(VPATH)}internal/gc.h +object.$(OBJEXT): {$(VPATH)}internal/glob.h +object.$(OBJEXT): {$(VPATH)}internal/globals.h +object.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +object.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +object.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +object.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +object.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +object.$(OBJEXT): {$(VPATH)}internal/has/extension.h +object.$(OBJEXT): {$(VPATH)}internal/has/feature.h +object.$(OBJEXT): {$(VPATH)}internal/has/warning.h +object.$(OBJEXT): {$(VPATH)}internal/intern/array.h +object.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +object.$(OBJEXT): {$(VPATH)}internal/intern/class.h +object.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +object.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +object.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +object.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +object.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +object.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +object.$(OBJEXT): {$(VPATH)}internal/intern/error.h +object.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +object.$(OBJEXT): {$(VPATH)}internal/intern/file.h +object.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +object.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +object.$(OBJEXT): {$(VPATH)}internal/intern/io.h +object.$(OBJEXT): {$(VPATH)}internal/intern/load.h +object.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +object.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +object.$(OBJEXT): {$(VPATH)}internal/intern/object.h +object.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +object.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +object.$(OBJEXT): {$(VPATH)}internal/intern/process.h +object.$(OBJEXT): {$(VPATH)}internal/intern/random.h +object.$(OBJEXT): {$(VPATH)}internal/intern/range.h +object.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +object.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +object.$(OBJEXT): {$(VPATH)}internal/intern/string.h +object.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +object.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +object.$(OBJEXT): {$(VPATH)}internal/intern/time.h +object.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +object.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +object.$(OBJEXT): {$(VPATH)}internal/interpreter.h +object.$(OBJEXT): {$(VPATH)}internal/iterator.h +object.$(OBJEXT): {$(VPATH)}internal/memory.h +object.$(OBJEXT): {$(VPATH)}internal/method.h +object.$(OBJEXT): {$(VPATH)}internal/module.h +object.$(OBJEXT): {$(VPATH)}internal/newobj.h +object.$(OBJEXT): {$(VPATH)}internal/rgengc.h +object.$(OBJEXT): {$(VPATH)}internal/scan_args.h +object.$(OBJEXT): {$(VPATH)}internal/special_consts.h +object.$(OBJEXT): {$(VPATH)}internal/static_assert.h +object.$(OBJEXT): {$(VPATH)}internal/stdalign.h +object.$(OBJEXT): {$(VPATH)}internal/stdbool.h +object.$(OBJEXT): {$(VPATH)}internal/symbol.h +object.$(OBJEXT): {$(VPATH)}internal/value.h +object.$(OBJEXT): {$(VPATH)}internal/value_type.h +object.$(OBJEXT): {$(VPATH)}internal/variable.h +object.$(OBJEXT): {$(VPATH)}internal/warning_push.h +object.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +object.$(OBJEXT): {$(VPATH)}kernel.rb +object.$(OBJEXT): {$(VPATH)}kernel.rbinc object.$(OBJEXT): {$(VPATH)}missing.h +object.$(OBJEXT): {$(VPATH)}nilclass.rbinc object.$(OBJEXT): {$(VPATH)}object.c object.$(OBJEXT): {$(VPATH)}onigmo.h object.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2542,15 +10413,181 @@ object.$(OBJEXT): {$(VPATH)}probes.h object.$(OBJEXT): {$(VPATH)}st.h object.$(OBJEXT): {$(VPATH)}subst.h object.$(OBJEXT): {$(VPATH)}util.h -pack.$(OBJEXT): $(hdrdir)/ruby.h pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h +pack.$(OBJEXT): $(top_srcdir)/internal/array.h +pack.$(OBJEXT): $(top_srcdir)/internal/bits.h +pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h +pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +pack.$(OBJEXT): $(top_srcdir)/internal/string.h +pack.$(OBJEXT): $(top_srcdir)/internal/symbol.h +pack.$(OBJEXT): $(top_srcdir)/internal/variable.h +pack.$(OBJEXT): $(top_srcdir)/internal/warnings.h pack.$(OBJEXT): {$(VPATH)}assert.h +pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h +pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h +pack.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h +pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h pack.$(OBJEXT): {$(VPATH)}builtin.h pack.$(OBJEXT): {$(VPATH)}config.h +pack.$(OBJEXT): {$(VPATH)}constant.h pack.$(OBJEXT): {$(VPATH)}defines.h pack.$(OBJEXT): {$(VPATH)}encoding.h +pack.$(OBJEXT): {$(VPATH)}id_table.h pack.$(OBJEXT): {$(VPATH)}intern.h pack.$(OBJEXT): {$(VPATH)}internal.h +pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +pack.$(OBJEXT): {$(VPATH)}internal/assume.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +pack.$(OBJEXT): {$(VPATH)}internal/cast.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +pack.$(OBJEXT): {$(VPATH)}internal/config.h +pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h +pack.$(OBJEXT): {$(VPATH)}internal/core.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +pack.$(OBJEXT): {$(VPATH)}internal/ctype.h +pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h +pack.$(OBJEXT): {$(VPATH)}internal/dosish.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +pack.$(OBJEXT): {$(VPATH)}internal/error.h +pack.$(OBJEXT): {$(VPATH)}internal/eval.h +pack.$(OBJEXT): {$(VPATH)}internal/event.h +pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h +pack.$(OBJEXT): {$(VPATH)}internal/gc.h +pack.$(OBJEXT): {$(VPATH)}internal/glob.h +pack.$(OBJEXT): {$(VPATH)}internal/globals.h +pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h +pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h +pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h +pack.$(OBJEXT): {$(VPATH)}internal/iterator.h +pack.$(OBJEXT): {$(VPATH)}internal/memory.h +pack.$(OBJEXT): {$(VPATH)}internal/method.h +pack.$(OBJEXT): {$(VPATH)}internal/module.h +pack.$(OBJEXT): {$(VPATH)}internal/newobj.h +pack.$(OBJEXT): {$(VPATH)}internal/rgengc.h +pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +pack.$(OBJEXT): {$(VPATH)}internal/value.h +pack.$(OBJEXT): {$(VPATH)}internal/value_type.h +pack.$(OBJEXT): {$(VPATH)}internal/variable.h +pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h +pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h pack.$(OBJEXT): {$(VPATH)}missing.h pack.$(OBJEXT): {$(VPATH)}onigmo.h pack.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2558,16 +10595,200 @@ pack.$(OBJEXT): {$(VPATH)}pack.c pack.$(OBJEXT): {$(VPATH)}pack.rbinc pack.$(OBJEXT): {$(VPATH)}st.h pack.$(OBJEXT): {$(VPATH)}subst.h -parse.$(OBJEXT): $(hdrdir)/ruby.h +pack.$(OBJEXT): {$(VPATH)}util.h parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h +parse.$(OBJEXT): $(top_srcdir)/internal/array.h +parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h +parse.$(OBJEXT): $(top_srcdir)/internal/bits.h +parse.$(OBJEXT): $(top_srcdir)/internal/compile.h +parse.$(OBJEXT): $(top_srcdir)/internal/compilers.h +parse.$(OBJEXT): $(top_srcdir)/internal/complex.h +parse.$(OBJEXT): $(top_srcdir)/internal/error.h +parse.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +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/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/serial.h +parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +parse.$(OBJEXT): $(top_srcdir)/internal/string.h +parse.$(OBJEXT): $(top_srcdir)/internal/symbol.h +parse.$(OBJEXT): $(top_srcdir)/internal/thread.h +parse.$(OBJEXT): $(top_srcdir)/internal/variable.h +parse.$(OBJEXT): $(top_srcdir)/internal/vm.h +parse.$(OBJEXT): $(top_srcdir)/internal/warnings.h parse.$(OBJEXT): {$(VPATH)}assert.h +parse.$(OBJEXT): {$(VPATH)}backward/2/assume.h +parse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +parse.$(OBJEXT): {$(VPATH)}backward/2/bool.h +parse.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +parse.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +parse.$(OBJEXT): {$(VPATH)}backward/2/limits.h +parse.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +parse.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +parse.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h parse.$(OBJEXT): {$(VPATH)}config.h +parse.$(OBJEXT): {$(VPATH)}constant.h parse.$(OBJEXT): {$(VPATH)}defines.h parse.$(OBJEXT): {$(VPATH)}defs/keywords parse.$(OBJEXT): {$(VPATH)}encoding.h parse.$(OBJEXT): {$(VPATH)}id.h +parse.$(OBJEXT): {$(VPATH)}id_table.h parse.$(OBJEXT): {$(VPATH)}intern.h parse.$(OBJEXT): {$(VPATH)}internal.h +parse.$(OBJEXT): {$(VPATH)}internal/anyargs.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +parse.$(OBJEXT): {$(VPATH)}internal/assume.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/const.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/error.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/format.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +parse.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +parse.$(OBJEXT): {$(VPATH)}internal/cast.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +parse.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +parse.$(OBJEXT): {$(VPATH)}internal/config.h +parse.$(OBJEXT): {$(VPATH)}internal/constant_p.h +parse.$(OBJEXT): {$(VPATH)}internal/core.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +parse.$(OBJEXT): {$(VPATH)}internal/core/robject.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +parse.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +parse.$(OBJEXT): {$(VPATH)}internal/ctype.h +parse.$(OBJEXT): {$(VPATH)}internal/dllexport.h +parse.$(OBJEXT): {$(VPATH)}internal/dosish.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +parse.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +parse.$(OBJEXT): {$(VPATH)}internal/error.h +parse.$(OBJEXT): {$(VPATH)}internal/eval.h +parse.$(OBJEXT): {$(VPATH)}internal/event.h +parse.$(OBJEXT): {$(VPATH)}internal/fl_type.h +parse.$(OBJEXT): {$(VPATH)}internal/gc.h +parse.$(OBJEXT): {$(VPATH)}internal/glob.h +parse.$(OBJEXT): {$(VPATH)}internal/globals.h +parse.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +parse.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +parse.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +parse.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +parse.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +parse.$(OBJEXT): {$(VPATH)}internal/has/extension.h +parse.$(OBJEXT): {$(VPATH)}internal/has/feature.h +parse.$(OBJEXT): {$(VPATH)}internal/has/warning.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/array.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/class.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/error.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/file.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/io.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/load.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/object.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/process.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/random.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/range.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/string.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/time.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +parse.$(OBJEXT): {$(VPATH)}internal/interpreter.h +parse.$(OBJEXT): {$(VPATH)}internal/iterator.h +parse.$(OBJEXT): {$(VPATH)}internal/memory.h +parse.$(OBJEXT): {$(VPATH)}internal/method.h +parse.$(OBJEXT): {$(VPATH)}internal/module.h +parse.$(OBJEXT): {$(VPATH)}internal/newobj.h +parse.$(OBJEXT): {$(VPATH)}internal/rgengc.h +parse.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +parse.$(OBJEXT): {$(VPATH)}internal/value.h +parse.$(OBJEXT): {$(VPATH)}internal/value_type.h +parse.$(OBJEXT): {$(VPATH)}internal/variable.h +parse.$(OBJEXT): {$(VPATH)}internal/warning_push.h +parse.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +parse.$(OBJEXT): {$(VPATH)}io.h parse.$(OBJEXT): {$(VPATH)}lex.c parse.$(OBJEXT): {$(VPATH)}missing.h parse.$(OBJEXT): {$(VPATH)}node.h @@ -2578,8 +10799,10 @@ parse.$(OBJEXT): {$(VPATH)}parse.h parse.$(OBJEXT): {$(VPATH)}parse.y parse.$(OBJEXT): {$(VPATH)}probes.dmyh parse.$(OBJEXT): {$(VPATH)}probes.h +parse.$(OBJEXT): {$(VPATH)}ractor.h parse.$(OBJEXT): {$(VPATH)}regenc.h parse.$(OBJEXT): {$(VPATH)}regex.h +parse.$(OBJEXT): {$(VPATH)}ruby_assert.h parse.$(OBJEXT): {$(VPATH)}st.h parse.$(OBJEXT): {$(VPATH)}subst.h parse.$(OBJEXT): {$(VPATH)}symbol.h @@ -2588,20 +10811,197 @@ 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.h proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h +proc.$(OBJEXT): $(top_srcdir)/internal/array.h +proc.$(OBJEXT): $(top_srcdir)/internal/class.h +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/imemo.h +proc.$(OBJEXT): $(top_srcdir)/internal/object.h +proc.$(OBJEXT): $(top_srcdir)/internal/proc.h +proc.$(OBJEXT): $(top_srcdir)/internal/serial.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/vm.h +proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h proc.$(OBJEXT): {$(VPATH)}assert.h +proc.$(OBJEXT): {$(VPATH)}atomic.h +proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h +proc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +proc.$(OBJEXT): {$(VPATH)}backward/2/bool.h +proc.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +proc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +proc.$(OBJEXT): {$(VPATH)}backward/2/limits.h +proc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h proc.$(OBJEXT): {$(VPATH)}config.h +proc.$(OBJEXT): {$(VPATH)}darray.h proc.$(OBJEXT): {$(VPATH)}defines.h +proc.$(OBJEXT): {$(VPATH)}encoding.h proc.$(OBJEXT): {$(VPATH)}eval_intern.h proc.$(OBJEXT): {$(VPATH)}gc.h proc.$(OBJEXT): {$(VPATH)}id.h +proc.$(OBJEXT): {$(VPATH)}id_table.h proc.$(OBJEXT): {$(VPATH)}intern.h proc.$(OBJEXT): {$(VPATH)}internal.h +proc.$(OBJEXT): {$(VPATH)}internal/anyargs.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +proc.$(OBJEXT): {$(VPATH)}internal/assume.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/const.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/error.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/format.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +proc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +proc.$(OBJEXT): {$(VPATH)}internal/cast.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +proc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +proc.$(OBJEXT): {$(VPATH)}internal/config.h +proc.$(OBJEXT): {$(VPATH)}internal/constant_p.h +proc.$(OBJEXT): {$(VPATH)}internal/core.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +proc.$(OBJEXT): {$(VPATH)}internal/core/robject.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +proc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +proc.$(OBJEXT): {$(VPATH)}internal/ctype.h +proc.$(OBJEXT): {$(VPATH)}internal/dllexport.h +proc.$(OBJEXT): {$(VPATH)}internal/dosish.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +proc.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +proc.$(OBJEXT): {$(VPATH)}internal/error.h +proc.$(OBJEXT): {$(VPATH)}internal/eval.h +proc.$(OBJEXT): {$(VPATH)}internal/event.h +proc.$(OBJEXT): {$(VPATH)}internal/fl_type.h +proc.$(OBJEXT): {$(VPATH)}internal/gc.h +proc.$(OBJEXT): {$(VPATH)}internal/glob.h +proc.$(OBJEXT): {$(VPATH)}internal/globals.h +proc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +proc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +proc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +proc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +proc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +proc.$(OBJEXT): {$(VPATH)}internal/has/extension.h +proc.$(OBJEXT): {$(VPATH)}internal/has/feature.h +proc.$(OBJEXT): {$(VPATH)}internal/has/warning.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/array.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/class.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/error.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/file.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/io.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/load.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/object.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/process.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/random.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/range.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/string.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/time.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +proc.$(OBJEXT): {$(VPATH)}internal/interpreter.h +proc.$(OBJEXT): {$(VPATH)}internal/iterator.h +proc.$(OBJEXT): {$(VPATH)}internal/memory.h +proc.$(OBJEXT): {$(VPATH)}internal/method.h +proc.$(OBJEXT): {$(VPATH)}internal/module.h +proc.$(OBJEXT): {$(VPATH)}internal/newobj.h +proc.$(OBJEXT): {$(VPATH)}internal/rgengc.h +proc.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +proc.$(OBJEXT): {$(VPATH)}internal/value.h +proc.$(OBJEXT): {$(VPATH)}internal/value_type.h +proc.$(OBJEXT): {$(VPATH)}internal/variable.h +proc.$(OBJEXT): {$(VPATH)}internal/warning_push.h +proc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h proc.$(OBJEXT): {$(VPATH)}iseq.h proc.$(OBJEXT): {$(VPATH)}method.h proc.$(OBJEXT): {$(VPATH)}missing.h proc.$(OBJEXT): {$(VPATH)}node.h +proc.$(OBJEXT): {$(VPATH)}onigmo.h +proc.$(OBJEXT): {$(VPATH)}oniguruma.h proc.$(OBJEXT): {$(VPATH)}proc.c proc.$(OBJEXT): {$(VPATH)}ruby_assert.h proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -2611,28 +11011,216 @@ proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h proc.$(OBJEXT): {$(VPATH)}thread_native.h proc.$(OBJEXT): {$(VPATH)}vm_core.h proc.$(OBJEXT): {$(VPATH)}vm_opts.h +proc.$(OBJEXT): {$(VPATH)}yjit.h process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h 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): $(top_srcdir)/internal/array.h +process.$(OBJEXT): $(top_srcdir)/internal/bignum.h +process.$(OBJEXT): $(top_srcdir)/internal/bits.h +process.$(OBJEXT): $(top_srcdir)/internal/class.h +process.$(OBJEXT): $(top_srcdir)/internal/compilers.h +process.$(OBJEXT): $(top_srcdir)/internal/dir.h +process.$(OBJEXT): $(top_srcdir)/internal/error.h +process.$(OBJEXT): $(top_srcdir)/internal/eval.h +process.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +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/numeric.h +process.$(OBJEXT): $(top_srcdir)/internal/object.h +process.$(OBJEXT): $(top_srcdir)/internal/process.h +process.$(OBJEXT): $(top_srcdir)/internal/serial.h +process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +process.$(OBJEXT): $(top_srcdir)/internal/string.h +process.$(OBJEXT): $(top_srcdir)/internal/thread.h +process.$(OBJEXT): $(top_srcdir)/internal/variable.h +process.$(OBJEXT): $(top_srcdir)/internal/vm.h +process.$(OBJEXT): $(top_srcdir)/internal/warnings.h process.$(OBJEXT): {$(VPATH)}assert.h +process.$(OBJEXT): {$(VPATH)}atomic.h +process.$(OBJEXT): {$(VPATH)}backward/2/assume.h +process.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +process.$(OBJEXT): {$(VPATH)}backward/2/bool.h +process.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +process.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +process.$(OBJEXT): {$(VPATH)}backward/2/limits.h +process.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +process.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +process.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h process.$(OBJEXT): {$(VPATH)}config.h +process.$(OBJEXT): {$(VPATH)}constant.h +process.$(OBJEXT): {$(VPATH)}darray.h +process.$(OBJEXT): {$(VPATH)}debug_counter.h process.$(OBJEXT): {$(VPATH)}defines.h process.$(OBJEXT): {$(VPATH)}dln.h process.$(OBJEXT): {$(VPATH)}encoding.h +process.$(OBJEXT): {$(VPATH)}fiber/scheduler.h process.$(OBJEXT): {$(VPATH)}hrtime.h process.$(OBJEXT): {$(VPATH)}id.h +process.$(OBJEXT): {$(VPATH)}id_table.h process.$(OBJEXT): {$(VPATH)}intern.h process.$(OBJEXT): {$(VPATH)}internal.h +process.$(OBJEXT): {$(VPATH)}internal/anyargs.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +process.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +process.$(OBJEXT): {$(VPATH)}internal/assume.h +process.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +process.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +process.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +process.$(OBJEXT): {$(VPATH)}internal/attr/const.h +process.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +process.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +process.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +process.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +process.$(OBJEXT): {$(VPATH)}internal/attr/error.h +process.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +process.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +process.$(OBJEXT): {$(VPATH)}internal/attr/format.h +process.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +process.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +process.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +process.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +process.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +process.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +process.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +process.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +process.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +process.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +process.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +process.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +process.$(OBJEXT): {$(VPATH)}internal/cast.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +process.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +process.$(OBJEXT): {$(VPATH)}internal/config.h +process.$(OBJEXT): {$(VPATH)}internal/constant_p.h +process.$(OBJEXT): {$(VPATH)}internal/core.h +process.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +process.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +process.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +process.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +process.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +process.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +process.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +process.$(OBJEXT): {$(VPATH)}internal/core/robject.h +process.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +process.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +process.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +process.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +process.$(OBJEXT): {$(VPATH)}internal/ctype.h +process.$(OBJEXT): {$(VPATH)}internal/dllexport.h +process.$(OBJEXT): {$(VPATH)}internal/dosish.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +process.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +process.$(OBJEXT): {$(VPATH)}internal/error.h +process.$(OBJEXT): {$(VPATH)}internal/eval.h +process.$(OBJEXT): {$(VPATH)}internal/event.h +process.$(OBJEXT): {$(VPATH)}internal/fl_type.h +process.$(OBJEXT): {$(VPATH)}internal/gc.h +process.$(OBJEXT): {$(VPATH)}internal/glob.h +process.$(OBJEXT): {$(VPATH)}internal/globals.h +process.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +process.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +process.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +process.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +process.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +process.$(OBJEXT): {$(VPATH)}internal/has/extension.h +process.$(OBJEXT): {$(VPATH)}internal/has/feature.h +process.$(OBJEXT): {$(VPATH)}internal/has/warning.h +process.$(OBJEXT): {$(VPATH)}internal/intern/array.h +process.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +process.$(OBJEXT): {$(VPATH)}internal/intern/class.h +process.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +process.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +process.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +process.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +process.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +process.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +process.$(OBJEXT): {$(VPATH)}internal/intern/error.h +process.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +process.$(OBJEXT): {$(VPATH)}internal/intern/file.h +process.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +process.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +process.$(OBJEXT): {$(VPATH)}internal/intern/io.h +process.$(OBJEXT): {$(VPATH)}internal/intern/load.h +process.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +process.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +process.$(OBJEXT): {$(VPATH)}internal/intern/object.h +process.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +process.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +process.$(OBJEXT): {$(VPATH)}internal/intern/process.h +process.$(OBJEXT): {$(VPATH)}internal/intern/random.h +process.$(OBJEXT): {$(VPATH)}internal/intern/range.h +process.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +process.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +process.$(OBJEXT): {$(VPATH)}internal/intern/string.h +process.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +process.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +process.$(OBJEXT): {$(VPATH)}internal/intern/time.h +process.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +process.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +process.$(OBJEXT): {$(VPATH)}internal/interpreter.h +process.$(OBJEXT): {$(VPATH)}internal/iterator.h +process.$(OBJEXT): {$(VPATH)}internal/memory.h +process.$(OBJEXT): {$(VPATH)}internal/method.h +process.$(OBJEXT): {$(VPATH)}internal/module.h +process.$(OBJEXT): {$(VPATH)}internal/newobj.h +process.$(OBJEXT): {$(VPATH)}internal/rgengc.h +process.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +process.$(OBJEXT): {$(VPATH)}internal/value.h +process.$(OBJEXT): {$(VPATH)}internal/value_type.h +process.$(OBJEXT): {$(VPATH)}internal/variable.h +process.$(OBJEXT): {$(VPATH)}internal/warning_push.h +process.$(OBJEXT): {$(VPATH)}internal/xmalloc.h process.$(OBJEXT): {$(VPATH)}io.h process.$(OBJEXT): {$(VPATH)}method.h process.$(OBJEXT): {$(VPATH)}missing.h +process.$(OBJEXT): {$(VPATH)}mjit.h process.$(OBJEXT): {$(VPATH)}node.h process.$(OBJEXT): {$(VPATH)}onigmo.h process.$(OBJEXT): {$(VPATH)}oniguruma.h process.$(OBJEXT): {$(VPATH)}process.c +process.$(OBJEXT): {$(VPATH)}ractor.h process.$(OBJEXT): {$(VPATH)}ruby_assert.h process.$(OBJEXT): {$(VPATH)}ruby_atomic.h process.$(OBJEXT): {$(VPATH)}st.h @@ -2643,55 +11231,948 @@ process.$(OBJEXT): {$(VPATH)}thread_native.h process.$(OBJEXT): {$(VPATH)}util.h process.$(OBJEXT): {$(VPATH)}vm_core.h process.$(OBJEXT): {$(VPATH)}vm_opts.h -random.$(OBJEXT): $(hdrdir)/ruby.h +process.$(OBJEXT): {$(VPATH)}yjit.h +ractor.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +ractor.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h +ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h +ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h +ractor.$(OBJEXT): $(top_srcdir)/internal/array.h +ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ractor.$(OBJEXT): $(top_srcdir)/internal/bits.h +ractor.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ractor.$(OBJEXT): $(top_srcdir)/internal/complex.h +ractor.$(OBJEXT): $(top_srcdir)/internal/error.h +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/numeric.h +ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h +ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h +ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +ractor.$(OBJEXT): $(top_srcdir)/internal/string.h +ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h +ractor.$(OBJEXT): $(top_srcdir)/internal/thread.h +ractor.$(OBJEXT): $(top_srcdir)/internal/vm.h +ractor.$(OBJEXT): $(top_srcdir)/internal/warnings.h +ractor.$(OBJEXT): {$(VPATH)}assert.h +ractor.$(OBJEXT): {$(VPATH)}atomic.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/assume.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/bool.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/limits.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +ractor.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +ractor.$(OBJEXT): {$(VPATH)}builtin.h +ractor.$(OBJEXT): {$(VPATH)}config.h +ractor.$(OBJEXT): {$(VPATH)}darray.h +ractor.$(OBJEXT): {$(VPATH)}debug_counter.h +ractor.$(OBJEXT): {$(VPATH)}defines.h +ractor.$(OBJEXT): {$(VPATH)}encoding.h +ractor.$(OBJEXT): {$(VPATH)}gc.h +ractor.$(OBJEXT): {$(VPATH)}id.h +ractor.$(OBJEXT): {$(VPATH)}id_table.h +ractor.$(OBJEXT): {$(VPATH)}intern.h +ractor.$(OBJEXT): {$(VPATH)}internal.h +ractor.$(OBJEXT): {$(VPATH)}internal/anyargs.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +ractor.$(OBJEXT): {$(VPATH)}internal/assume.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/const.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/error.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/format.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +ractor.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +ractor.$(OBJEXT): {$(VPATH)}internal/cast.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +ractor.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +ractor.$(OBJEXT): {$(VPATH)}internal/config.h +ractor.$(OBJEXT): {$(VPATH)}internal/constant_p.h +ractor.$(OBJEXT): {$(VPATH)}internal/core.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/robject.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +ractor.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +ractor.$(OBJEXT): {$(VPATH)}internal/ctype.h +ractor.$(OBJEXT): {$(VPATH)}internal/dllexport.h +ractor.$(OBJEXT): {$(VPATH)}internal/dosish.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +ractor.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +ractor.$(OBJEXT): {$(VPATH)}internal/error.h +ractor.$(OBJEXT): {$(VPATH)}internal/eval.h +ractor.$(OBJEXT): {$(VPATH)}internal/event.h +ractor.$(OBJEXT): {$(VPATH)}internal/fl_type.h +ractor.$(OBJEXT): {$(VPATH)}internal/gc.h +ractor.$(OBJEXT): {$(VPATH)}internal/glob.h +ractor.$(OBJEXT): {$(VPATH)}internal/globals.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/extension.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/feature.h +ractor.$(OBJEXT): {$(VPATH)}internal/has/warning.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/array.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/class.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/error.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/file.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/io.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/load.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/object.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/process.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/random.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/range.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/string.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/time.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +ractor.$(OBJEXT): {$(VPATH)}internal/interpreter.h +ractor.$(OBJEXT): {$(VPATH)}internal/iterator.h +ractor.$(OBJEXT): {$(VPATH)}internal/memory.h +ractor.$(OBJEXT): {$(VPATH)}internal/method.h +ractor.$(OBJEXT): {$(VPATH)}internal/module.h +ractor.$(OBJEXT): {$(VPATH)}internal/newobj.h +ractor.$(OBJEXT): {$(VPATH)}internal/rgengc.h +ractor.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +ractor.$(OBJEXT): {$(VPATH)}internal/value.h +ractor.$(OBJEXT): {$(VPATH)}internal/value_type.h +ractor.$(OBJEXT): {$(VPATH)}internal/variable.h +ractor.$(OBJEXT): {$(VPATH)}internal/warning_push.h +ractor.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +ractor.$(OBJEXT): {$(VPATH)}method.h +ractor.$(OBJEXT): {$(VPATH)}missing.h +ractor.$(OBJEXT): {$(VPATH)}node.h +ractor.$(OBJEXT): {$(VPATH)}onigmo.h +ractor.$(OBJEXT): {$(VPATH)}oniguruma.h +ractor.$(OBJEXT): {$(VPATH)}ractor.c +ractor.$(OBJEXT): {$(VPATH)}ractor.h +ractor.$(OBJEXT): {$(VPATH)}ractor.rb +ractor.$(OBJEXT): {$(VPATH)}ractor.rbinc +ractor.$(OBJEXT): {$(VPATH)}ractor_core.h +ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h +ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h +ractor.$(OBJEXT): {$(VPATH)}st.h +ractor.$(OBJEXT): {$(VPATH)}subst.h +ractor.$(OBJEXT): {$(VPATH)}thread.h +ractor.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +ractor.$(OBJEXT): {$(VPATH)}thread_native.h +ractor.$(OBJEXT): {$(VPATH)}transient_heap.h +ractor.$(OBJEXT): {$(VPATH)}variable.h +ractor.$(OBJEXT): {$(VPATH)}vm_core.h +ractor.$(OBJEXT): {$(VPATH)}vm_debug.h +ractor.$(OBJEXT): {$(VPATH)}vm_opts.h +ractor.$(OBJEXT): {$(VPATH)}vm_sync.h +ractor.$(OBJEXT): {$(VPATH)}yjit.h random.$(OBJEXT): $(hdrdir)/ruby/ruby.h +random.$(OBJEXT): $(top_srcdir)/internal/array.h +random.$(OBJEXT): $(top_srcdir)/internal/bignum.h +random.$(OBJEXT): $(top_srcdir)/internal/bits.h +random.$(OBJEXT): $(top_srcdir)/internal/compilers.h +random.$(OBJEXT): $(top_srcdir)/internal/fixnum.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/static_assert.h +random.$(OBJEXT): $(top_srcdir)/internal/variable.h +random.$(OBJEXT): $(top_srcdir)/internal/vm.h +random.$(OBJEXT): $(top_srcdir)/internal/warnings.h random.$(OBJEXT): {$(VPATH)}assert.h +random.$(OBJEXT): {$(VPATH)}atomic.h +random.$(OBJEXT): {$(VPATH)}backward/2/assume.h +random.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +random.$(OBJEXT): {$(VPATH)}backward/2/bool.h +random.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +random.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +random.$(OBJEXT): {$(VPATH)}backward/2/limits.h +random.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +random.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +random.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h random.$(OBJEXT): {$(VPATH)}config.h +random.$(OBJEXT): {$(VPATH)}constant.h random.$(OBJEXT): {$(VPATH)}defines.h +random.$(OBJEXT): {$(VPATH)}id_table.h random.$(OBJEXT): {$(VPATH)}intern.h random.$(OBJEXT): {$(VPATH)}internal.h +random.$(OBJEXT): {$(VPATH)}internal/anyargs.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +random.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +random.$(OBJEXT): {$(VPATH)}internal/assume.h +random.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +random.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +random.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +random.$(OBJEXT): {$(VPATH)}internal/attr/const.h +random.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +random.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +random.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +random.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +random.$(OBJEXT): {$(VPATH)}internal/attr/error.h +random.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +random.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +random.$(OBJEXT): {$(VPATH)}internal/attr/format.h +random.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +random.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +random.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +random.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +random.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +random.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +random.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +random.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +random.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +random.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +random.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +random.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +random.$(OBJEXT): {$(VPATH)}internal/cast.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +random.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +random.$(OBJEXT): {$(VPATH)}internal/config.h +random.$(OBJEXT): {$(VPATH)}internal/constant_p.h +random.$(OBJEXT): {$(VPATH)}internal/core.h +random.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +random.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +random.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +random.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +random.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +random.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +random.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +random.$(OBJEXT): {$(VPATH)}internal/core/robject.h +random.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +random.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +random.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +random.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +random.$(OBJEXT): {$(VPATH)}internal/ctype.h +random.$(OBJEXT): {$(VPATH)}internal/dllexport.h +random.$(OBJEXT): {$(VPATH)}internal/dosish.h +random.$(OBJEXT): {$(VPATH)}internal/error.h +random.$(OBJEXT): {$(VPATH)}internal/eval.h +random.$(OBJEXT): {$(VPATH)}internal/event.h +random.$(OBJEXT): {$(VPATH)}internal/fl_type.h +random.$(OBJEXT): {$(VPATH)}internal/gc.h +random.$(OBJEXT): {$(VPATH)}internal/glob.h +random.$(OBJEXT): {$(VPATH)}internal/globals.h +random.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +random.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +random.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +random.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +random.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +random.$(OBJEXT): {$(VPATH)}internal/has/extension.h +random.$(OBJEXT): {$(VPATH)}internal/has/feature.h +random.$(OBJEXT): {$(VPATH)}internal/has/warning.h +random.$(OBJEXT): {$(VPATH)}internal/intern/array.h +random.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +random.$(OBJEXT): {$(VPATH)}internal/intern/class.h +random.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +random.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +random.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +random.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +random.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +random.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +random.$(OBJEXT): {$(VPATH)}internal/intern/error.h +random.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +random.$(OBJEXT): {$(VPATH)}internal/intern/file.h +random.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +random.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +random.$(OBJEXT): {$(VPATH)}internal/intern/io.h +random.$(OBJEXT): {$(VPATH)}internal/intern/load.h +random.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +random.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +random.$(OBJEXT): {$(VPATH)}internal/intern/object.h +random.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +random.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +random.$(OBJEXT): {$(VPATH)}internal/intern/process.h +random.$(OBJEXT): {$(VPATH)}internal/intern/random.h +random.$(OBJEXT): {$(VPATH)}internal/intern/range.h +random.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +random.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +random.$(OBJEXT): {$(VPATH)}internal/intern/string.h +random.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +random.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +random.$(OBJEXT): {$(VPATH)}internal/intern/time.h +random.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +random.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +random.$(OBJEXT): {$(VPATH)}internal/interpreter.h +random.$(OBJEXT): {$(VPATH)}internal/iterator.h +random.$(OBJEXT): {$(VPATH)}internal/memory.h +random.$(OBJEXT): {$(VPATH)}internal/method.h +random.$(OBJEXT): {$(VPATH)}internal/module.h +random.$(OBJEXT): {$(VPATH)}internal/newobj.h +random.$(OBJEXT): {$(VPATH)}internal/rgengc.h +random.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +random.$(OBJEXT): {$(VPATH)}internal/value.h +random.$(OBJEXT): {$(VPATH)}internal/value_type.h +random.$(OBJEXT): {$(VPATH)}internal/variable.h +random.$(OBJEXT): {$(VPATH)}internal/warning_push.h +random.$(OBJEXT): {$(VPATH)}internal/xmalloc.h random.$(OBJEXT): {$(VPATH)}missing.h random.$(OBJEXT): {$(VPATH)}mt19937.c +random.$(OBJEXT): {$(VPATH)}ractor.h random.$(OBJEXT): {$(VPATH)}random.c +random.$(OBJEXT): {$(VPATH)}random.h random.$(OBJEXT): {$(VPATH)}ruby_atomic.h random.$(OBJEXT): {$(VPATH)}siphash.c random.$(OBJEXT): {$(VPATH)}siphash.h random.$(OBJEXT): {$(VPATH)}st.h random.$(OBJEXT): {$(VPATH)}subst.h -range.$(OBJEXT): $(hdrdir)/ruby.h range.$(OBJEXT): $(hdrdir)/ruby/ruby.h +range.$(OBJEXT): $(top_srcdir)/internal/array.h +range.$(OBJEXT): $(top_srcdir)/internal/bignum.h +range.$(OBJEXT): $(top_srcdir)/internal/bits.h +range.$(OBJEXT): $(top_srcdir)/internal/compar.h +range.$(OBJEXT): $(top_srcdir)/internal/compilers.h +range.$(OBJEXT): $(top_srcdir)/internal/enum.h +range.$(OBJEXT): $(top_srcdir)/internal/enumerator.h +range.$(OBJEXT): $(top_srcdir)/internal/error.h +range.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +range.$(OBJEXT): $(top_srcdir)/internal/gc.h +range.$(OBJEXT): $(top_srcdir)/internal/numeric.h +range.$(OBJEXT): $(top_srcdir)/internal/range.h +range.$(OBJEXT): $(top_srcdir)/internal/serial.h +range.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +range.$(OBJEXT): $(top_srcdir)/internal/string.h +range.$(OBJEXT): $(top_srcdir)/internal/struct.h +range.$(OBJEXT): $(top_srcdir)/internal/vm.h +range.$(OBJEXT): $(top_srcdir)/internal/warnings.h range.$(OBJEXT): {$(VPATH)}assert.h +range.$(OBJEXT): {$(VPATH)}backward/2/assume.h +range.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +range.$(OBJEXT): {$(VPATH)}backward/2/bool.h +range.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +range.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +range.$(OBJEXT): {$(VPATH)}backward/2/limits.h +range.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +range.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +range.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h range.$(OBJEXT): {$(VPATH)}config.h range.$(OBJEXT): {$(VPATH)}defines.h +range.$(OBJEXT): {$(VPATH)}encoding.h range.$(OBJEXT): {$(VPATH)}id.h range.$(OBJEXT): {$(VPATH)}intern.h range.$(OBJEXT): {$(VPATH)}internal.h +range.$(OBJEXT): {$(VPATH)}internal/anyargs.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +range.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +range.$(OBJEXT): {$(VPATH)}internal/assume.h +range.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +range.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +range.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +range.$(OBJEXT): {$(VPATH)}internal/attr/const.h +range.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +range.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +range.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +range.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +range.$(OBJEXT): {$(VPATH)}internal/attr/error.h +range.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +range.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +range.$(OBJEXT): {$(VPATH)}internal/attr/format.h +range.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +range.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +range.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +range.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +range.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +range.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +range.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +range.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +range.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +range.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +range.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +range.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +range.$(OBJEXT): {$(VPATH)}internal/cast.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +range.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +range.$(OBJEXT): {$(VPATH)}internal/config.h +range.$(OBJEXT): {$(VPATH)}internal/constant_p.h +range.$(OBJEXT): {$(VPATH)}internal/core.h +range.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +range.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +range.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +range.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +range.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +range.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +range.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +range.$(OBJEXT): {$(VPATH)}internal/core/robject.h +range.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +range.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +range.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +range.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +range.$(OBJEXT): {$(VPATH)}internal/ctype.h +range.$(OBJEXT): {$(VPATH)}internal/dllexport.h +range.$(OBJEXT): {$(VPATH)}internal/dosish.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +range.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +range.$(OBJEXT): {$(VPATH)}internal/error.h +range.$(OBJEXT): {$(VPATH)}internal/eval.h +range.$(OBJEXT): {$(VPATH)}internal/event.h +range.$(OBJEXT): {$(VPATH)}internal/fl_type.h +range.$(OBJEXT): {$(VPATH)}internal/gc.h +range.$(OBJEXT): {$(VPATH)}internal/glob.h +range.$(OBJEXT): {$(VPATH)}internal/globals.h +range.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +range.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +range.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +range.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +range.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +range.$(OBJEXT): {$(VPATH)}internal/has/extension.h +range.$(OBJEXT): {$(VPATH)}internal/has/feature.h +range.$(OBJEXT): {$(VPATH)}internal/has/warning.h +range.$(OBJEXT): {$(VPATH)}internal/intern/array.h +range.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +range.$(OBJEXT): {$(VPATH)}internal/intern/class.h +range.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +range.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +range.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +range.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +range.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +range.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +range.$(OBJEXT): {$(VPATH)}internal/intern/error.h +range.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +range.$(OBJEXT): {$(VPATH)}internal/intern/file.h +range.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +range.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +range.$(OBJEXT): {$(VPATH)}internal/intern/io.h +range.$(OBJEXT): {$(VPATH)}internal/intern/load.h +range.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +range.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +range.$(OBJEXT): {$(VPATH)}internal/intern/object.h +range.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +range.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +range.$(OBJEXT): {$(VPATH)}internal/intern/process.h +range.$(OBJEXT): {$(VPATH)}internal/intern/random.h +range.$(OBJEXT): {$(VPATH)}internal/intern/range.h +range.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +range.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +range.$(OBJEXT): {$(VPATH)}internal/intern/string.h +range.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +range.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +range.$(OBJEXT): {$(VPATH)}internal/intern/time.h +range.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +range.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +range.$(OBJEXT): {$(VPATH)}internal/interpreter.h +range.$(OBJEXT): {$(VPATH)}internal/iterator.h +range.$(OBJEXT): {$(VPATH)}internal/memory.h +range.$(OBJEXT): {$(VPATH)}internal/method.h +range.$(OBJEXT): {$(VPATH)}internal/module.h +range.$(OBJEXT): {$(VPATH)}internal/newobj.h +range.$(OBJEXT): {$(VPATH)}internal/rgengc.h +range.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +range.$(OBJEXT): {$(VPATH)}internal/value.h +range.$(OBJEXT): {$(VPATH)}internal/value_type.h +range.$(OBJEXT): {$(VPATH)}internal/variable.h +range.$(OBJEXT): {$(VPATH)}internal/warning_push.h +range.$(OBJEXT): {$(VPATH)}internal/xmalloc.h range.$(OBJEXT): {$(VPATH)}missing.h +range.$(OBJEXT): {$(VPATH)}onigmo.h +range.$(OBJEXT): {$(VPATH)}oniguruma.h range.$(OBJEXT): {$(VPATH)}range.c range.$(OBJEXT): {$(VPATH)}st.h range.$(OBJEXT): {$(VPATH)}subst.h -rational.$(OBJEXT): $(hdrdir)/ruby.h rational.$(OBJEXT): $(hdrdir)/ruby/ruby.h +rational.$(OBJEXT): $(top_srcdir)/internal/array.h +rational.$(OBJEXT): $(top_srcdir)/internal/bignum.h +rational.$(OBJEXT): $(top_srcdir)/internal/bits.h +rational.$(OBJEXT): $(top_srcdir)/internal/class.h +rational.$(OBJEXT): $(top_srcdir)/internal/compilers.h +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/numeric.h +rational.$(OBJEXT): $(top_srcdir)/internal/object.h +rational.$(OBJEXT): $(top_srcdir)/internal/rational.h +rational.$(OBJEXT): $(top_srcdir)/internal/serial.h +rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +rational.$(OBJEXT): $(top_srcdir)/internal/vm.h +rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h rational.$(OBJEXT): {$(VPATH)}assert.h +rational.$(OBJEXT): {$(VPATH)}backward/2/assume.h +rational.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +rational.$(OBJEXT): {$(VPATH)}backward/2/bool.h +rational.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +rational.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +rational.$(OBJEXT): {$(VPATH)}backward/2/limits.h +rational.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +rational.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h rational.$(OBJEXT): {$(VPATH)}config.h rational.$(OBJEXT): {$(VPATH)}defines.h rational.$(OBJEXT): {$(VPATH)}id.h +rational.$(OBJEXT): {$(VPATH)}id_table.h rational.$(OBJEXT): {$(VPATH)}intern.h rational.$(OBJEXT): {$(VPATH)}internal.h +rational.$(OBJEXT): {$(VPATH)}internal/anyargs.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +rational.$(OBJEXT): {$(VPATH)}internal/assume.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/const.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/error.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/format.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +rational.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +rational.$(OBJEXT): {$(VPATH)}internal/cast.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +rational.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +rational.$(OBJEXT): {$(VPATH)}internal/config.h +rational.$(OBJEXT): {$(VPATH)}internal/constant_p.h +rational.$(OBJEXT): {$(VPATH)}internal/core.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +rational.$(OBJEXT): {$(VPATH)}internal/core/robject.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +rational.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +rational.$(OBJEXT): {$(VPATH)}internal/ctype.h +rational.$(OBJEXT): {$(VPATH)}internal/dllexport.h +rational.$(OBJEXT): {$(VPATH)}internal/dosish.h +rational.$(OBJEXT): {$(VPATH)}internal/error.h +rational.$(OBJEXT): {$(VPATH)}internal/eval.h +rational.$(OBJEXT): {$(VPATH)}internal/event.h +rational.$(OBJEXT): {$(VPATH)}internal/fl_type.h +rational.$(OBJEXT): {$(VPATH)}internal/gc.h +rational.$(OBJEXT): {$(VPATH)}internal/glob.h +rational.$(OBJEXT): {$(VPATH)}internal/globals.h +rational.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +rational.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +rational.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +rational.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +rational.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +rational.$(OBJEXT): {$(VPATH)}internal/has/extension.h +rational.$(OBJEXT): {$(VPATH)}internal/has/feature.h +rational.$(OBJEXT): {$(VPATH)}internal/has/warning.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/array.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/class.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/error.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/file.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/io.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/load.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/object.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/process.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/random.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/range.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/string.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/time.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +rational.$(OBJEXT): {$(VPATH)}internal/interpreter.h +rational.$(OBJEXT): {$(VPATH)}internal/iterator.h +rational.$(OBJEXT): {$(VPATH)}internal/memory.h +rational.$(OBJEXT): {$(VPATH)}internal/method.h +rational.$(OBJEXT): {$(VPATH)}internal/module.h +rational.$(OBJEXT): {$(VPATH)}internal/newobj.h +rational.$(OBJEXT): {$(VPATH)}internal/rgengc.h +rational.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +rational.$(OBJEXT): {$(VPATH)}internal/value.h +rational.$(OBJEXT): {$(VPATH)}internal/value_type.h +rational.$(OBJEXT): {$(VPATH)}internal/variable.h +rational.$(OBJEXT): {$(VPATH)}internal/warning_push.h +rational.$(OBJEXT): {$(VPATH)}internal/xmalloc.h rational.$(OBJEXT): {$(VPATH)}missing.h rational.$(OBJEXT): {$(VPATH)}rational.c rational.$(OBJEXT): {$(VPATH)}ruby_assert.h rational.$(OBJEXT): {$(VPATH)}st.h rational.$(OBJEXT): {$(VPATH)}subst.h -re.$(OBJEXT): $(hdrdir)/ruby.h re.$(OBJEXT): $(hdrdir)/ruby/ruby.h +re.$(OBJEXT): $(top_srcdir)/internal/array.h +re.$(OBJEXT): $(top_srcdir)/internal/compilers.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/re.h +re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +re.$(OBJEXT): $(top_srcdir)/internal/string.h +re.$(OBJEXT): $(top_srcdir)/internal/variable.h +re.$(OBJEXT): $(top_srcdir)/internal/warnings.h re.$(OBJEXT): {$(VPATH)}assert.h +re.$(OBJEXT): {$(VPATH)}backward/2/assume.h +re.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +re.$(OBJEXT): {$(VPATH)}backward/2/bool.h +re.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +re.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +re.$(OBJEXT): {$(VPATH)}backward/2/limits.h +re.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +re.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +re.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h re.$(OBJEXT): {$(VPATH)}config.h +re.$(OBJEXT): {$(VPATH)}constant.h re.$(OBJEXT): {$(VPATH)}defines.h re.$(OBJEXT): {$(VPATH)}encindex.h re.$(OBJEXT): {$(VPATH)}encoding.h +re.$(OBJEXT): {$(VPATH)}id_table.h re.$(OBJEXT): {$(VPATH)}intern.h re.$(OBJEXT): {$(VPATH)}internal.h +re.$(OBJEXT): {$(VPATH)}internal/anyargs.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +re.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +re.$(OBJEXT): {$(VPATH)}internal/assume.h +re.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +re.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +re.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +re.$(OBJEXT): {$(VPATH)}internal/attr/const.h +re.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +re.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +re.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +re.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +re.$(OBJEXT): {$(VPATH)}internal/attr/error.h +re.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +re.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +re.$(OBJEXT): {$(VPATH)}internal/attr/format.h +re.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +re.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +re.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +re.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +re.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +re.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +re.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +re.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +re.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +re.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +re.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +re.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +re.$(OBJEXT): {$(VPATH)}internal/cast.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +re.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +re.$(OBJEXT): {$(VPATH)}internal/config.h +re.$(OBJEXT): {$(VPATH)}internal/constant_p.h +re.$(OBJEXT): {$(VPATH)}internal/core.h +re.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +re.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +re.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +re.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +re.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +re.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +re.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +re.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h +re.$(OBJEXT): {$(VPATH)}internal/core/robject.h +re.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +re.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +re.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +re.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +re.$(OBJEXT): {$(VPATH)}internal/ctype.h +re.$(OBJEXT): {$(VPATH)}internal/dllexport.h +re.$(OBJEXT): {$(VPATH)}internal/dosish.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +re.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +re.$(OBJEXT): {$(VPATH)}internal/error.h +re.$(OBJEXT): {$(VPATH)}internal/eval.h +re.$(OBJEXT): {$(VPATH)}internal/event.h +re.$(OBJEXT): {$(VPATH)}internal/fl_type.h +re.$(OBJEXT): {$(VPATH)}internal/gc.h +re.$(OBJEXT): {$(VPATH)}internal/glob.h +re.$(OBJEXT): {$(VPATH)}internal/globals.h +re.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +re.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +re.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +re.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +re.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +re.$(OBJEXT): {$(VPATH)}internal/has/extension.h +re.$(OBJEXT): {$(VPATH)}internal/has/feature.h +re.$(OBJEXT): {$(VPATH)}internal/has/warning.h +re.$(OBJEXT): {$(VPATH)}internal/intern/array.h +re.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +re.$(OBJEXT): {$(VPATH)}internal/intern/class.h +re.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +re.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +re.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +re.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +re.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +re.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +re.$(OBJEXT): {$(VPATH)}internal/intern/error.h +re.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +re.$(OBJEXT): {$(VPATH)}internal/intern/file.h +re.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +re.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +re.$(OBJEXT): {$(VPATH)}internal/intern/io.h +re.$(OBJEXT): {$(VPATH)}internal/intern/load.h +re.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +re.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +re.$(OBJEXT): {$(VPATH)}internal/intern/object.h +re.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +re.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +re.$(OBJEXT): {$(VPATH)}internal/intern/process.h +re.$(OBJEXT): {$(VPATH)}internal/intern/random.h +re.$(OBJEXT): {$(VPATH)}internal/intern/range.h +re.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +re.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +re.$(OBJEXT): {$(VPATH)}internal/intern/string.h +re.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +re.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +re.$(OBJEXT): {$(VPATH)}internal/intern/time.h +re.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +re.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +re.$(OBJEXT): {$(VPATH)}internal/interpreter.h +re.$(OBJEXT): {$(VPATH)}internal/iterator.h +re.$(OBJEXT): {$(VPATH)}internal/memory.h +re.$(OBJEXT): {$(VPATH)}internal/method.h +re.$(OBJEXT): {$(VPATH)}internal/module.h +re.$(OBJEXT): {$(VPATH)}internal/newobj.h +re.$(OBJEXT): {$(VPATH)}internal/rgengc.h +re.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +re.$(OBJEXT): {$(VPATH)}internal/value.h +re.$(OBJEXT): {$(VPATH)}internal/value_type.h +re.$(OBJEXT): {$(VPATH)}internal/variable.h +re.$(OBJEXT): {$(VPATH)}internal/warning_push.h +re.$(OBJEXT): {$(VPATH)}internal/xmalloc.h re.$(OBJEXT): {$(VPATH)}missing.h re.$(OBJEXT): {$(VPATH)}onigmo.h re.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2705,9 +12186,156 @@ re.$(OBJEXT): {$(VPATH)}subst.h re.$(OBJEXT): {$(VPATH)}util.h regcomp.$(OBJEXT): $(hdrdir)/ruby/ruby.h regcomp.$(OBJEXT): {$(VPATH)}assert.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regcomp.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regcomp.$(OBJEXT): {$(VPATH)}config.h regcomp.$(OBJEXT): {$(VPATH)}defines.h regcomp.$(OBJEXT): {$(VPATH)}intern.h +regcomp.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regcomp.$(OBJEXT): {$(VPATH)}internal/assume.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regcomp.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regcomp.$(OBJEXT): {$(VPATH)}internal/cast.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regcomp.$(OBJEXT): {$(VPATH)}internal/config.h +regcomp.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regcomp.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regcomp.$(OBJEXT): {$(VPATH)}internal/ctype.h +regcomp.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regcomp.$(OBJEXT): {$(VPATH)}internal/dosish.h +regcomp.$(OBJEXT): {$(VPATH)}internal/error.h +regcomp.$(OBJEXT): {$(VPATH)}internal/eval.h +regcomp.$(OBJEXT): {$(VPATH)}internal/event.h +regcomp.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regcomp.$(OBJEXT): {$(VPATH)}internal/gc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/glob.h +regcomp.$(OBJEXT): {$(VPATH)}internal/globals.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regcomp.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regcomp.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regcomp.$(OBJEXT): {$(VPATH)}internal/iterator.h +regcomp.$(OBJEXT): {$(VPATH)}internal/memory.h +regcomp.$(OBJEXT): {$(VPATH)}internal/method.h +regcomp.$(OBJEXT): {$(VPATH)}internal/module.h +regcomp.$(OBJEXT): {$(VPATH)}internal/newobj.h +regcomp.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regcomp.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regcomp.$(OBJEXT): {$(VPATH)}internal/value.h +regcomp.$(OBJEXT): {$(VPATH)}internal/value_type.h +regcomp.$(OBJEXT): {$(VPATH)}internal/variable.h +regcomp.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regcomp.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regcomp.$(OBJEXT): {$(VPATH)}missing.h regcomp.$(OBJEXT): {$(VPATH)}onigmo.h regcomp.$(OBJEXT): {$(VPATH)}regcomp.c @@ -2718,9 +12346,156 @@ regcomp.$(OBJEXT): {$(VPATH)}st.h regcomp.$(OBJEXT): {$(VPATH)}subst.h regenc.$(OBJEXT): $(hdrdir)/ruby/ruby.h regenc.$(OBJEXT): {$(VPATH)}assert.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regenc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regenc.$(OBJEXT): {$(VPATH)}config.h regenc.$(OBJEXT): {$(VPATH)}defines.h regenc.$(OBJEXT): {$(VPATH)}intern.h +regenc.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regenc.$(OBJEXT): {$(VPATH)}internal/assume.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regenc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regenc.$(OBJEXT): {$(VPATH)}internal/cast.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regenc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regenc.$(OBJEXT): {$(VPATH)}internal/config.h +regenc.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regenc.$(OBJEXT): {$(VPATH)}internal/core.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regenc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regenc.$(OBJEXT): {$(VPATH)}internal/ctype.h +regenc.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regenc.$(OBJEXT): {$(VPATH)}internal/dosish.h +regenc.$(OBJEXT): {$(VPATH)}internal/error.h +regenc.$(OBJEXT): {$(VPATH)}internal/eval.h +regenc.$(OBJEXT): {$(VPATH)}internal/event.h +regenc.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regenc.$(OBJEXT): {$(VPATH)}internal/gc.h +regenc.$(OBJEXT): {$(VPATH)}internal/glob.h +regenc.$(OBJEXT): {$(VPATH)}internal/globals.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regenc.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regenc.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regenc.$(OBJEXT): {$(VPATH)}internal/iterator.h +regenc.$(OBJEXT): {$(VPATH)}internal/memory.h +regenc.$(OBJEXT): {$(VPATH)}internal/method.h +regenc.$(OBJEXT): {$(VPATH)}internal/module.h +regenc.$(OBJEXT): {$(VPATH)}internal/newobj.h +regenc.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regenc.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regenc.$(OBJEXT): {$(VPATH)}internal/value.h +regenc.$(OBJEXT): {$(VPATH)}internal/value_type.h +regenc.$(OBJEXT): {$(VPATH)}internal/variable.h +regenc.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regenc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regenc.$(OBJEXT): {$(VPATH)}missing.h regenc.$(OBJEXT): {$(VPATH)}onigmo.h regenc.$(OBJEXT): {$(VPATH)}regenc.c @@ -2730,9 +12505,156 @@ regenc.$(OBJEXT): {$(VPATH)}st.h regenc.$(OBJEXT): {$(VPATH)}subst.h regerror.$(OBJEXT): $(hdrdir)/ruby/ruby.h regerror.$(OBJEXT): {$(VPATH)}assert.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regerror.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regerror.$(OBJEXT): {$(VPATH)}config.h regerror.$(OBJEXT): {$(VPATH)}defines.h regerror.$(OBJEXT): {$(VPATH)}intern.h +regerror.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regerror.$(OBJEXT): {$(VPATH)}internal/assume.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regerror.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regerror.$(OBJEXT): {$(VPATH)}internal/cast.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regerror.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regerror.$(OBJEXT): {$(VPATH)}internal/config.h +regerror.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regerror.$(OBJEXT): {$(VPATH)}internal/core.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regerror.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regerror.$(OBJEXT): {$(VPATH)}internal/ctype.h +regerror.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regerror.$(OBJEXT): {$(VPATH)}internal/dosish.h +regerror.$(OBJEXT): {$(VPATH)}internal/error.h +regerror.$(OBJEXT): {$(VPATH)}internal/eval.h +regerror.$(OBJEXT): {$(VPATH)}internal/event.h +regerror.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regerror.$(OBJEXT): {$(VPATH)}internal/gc.h +regerror.$(OBJEXT): {$(VPATH)}internal/glob.h +regerror.$(OBJEXT): {$(VPATH)}internal/globals.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regerror.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regerror.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regerror.$(OBJEXT): {$(VPATH)}internal/iterator.h +regerror.$(OBJEXT): {$(VPATH)}internal/memory.h +regerror.$(OBJEXT): {$(VPATH)}internal/method.h +regerror.$(OBJEXT): {$(VPATH)}internal/module.h +regerror.$(OBJEXT): {$(VPATH)}internal/newobj.h +regerror.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regerror.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regerror.$(OBJEXT): {$(VPATH)}internal/value.h +regerror.$(OBJEXT): {$(VPATH)}internal/value_type.h +regerror.$(OBJEXT): {$(VPATH)}internal/variable.h +regerror.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regerror.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regerror.$(OBJEXT): {$(VPATH)}missing.h regerror.$(OBJEXT): {$(VPATH)}onigmo.h regerror.$(OBJEXT): {$(VPATH)}regenc.h @@ -2742,9 +12664,156 @@ regerror.$(OBJEXT): {$(VPATH)}st.h regerror.$(OBJEXT): {$(VPATH)}subst.h regexec.$(OBJEXT): $(hdrdir)/ruby/ruby.h regexec.$(OBJEXT): {$(VPATH)}assert.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regexec.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regexec.$(OBJEXT): {$(VPATH)}config.h regexec.$(OBJEXT): {$(VPATH)}defines.h regexec.$(OBJEXT): {$(VPATH)}intern.h +regexec.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regexec.$(OBJEXT): {$(VPATH)}internal/assume.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regexec.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regexec.$(OBJEXT): {$(VPATH)}internal/cast.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regexec.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regexec.$(OBJEXT): {$(VPATH)}internal/config.h +regexec.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regexec.$(OBJEXT): {$(VPATH)}internal/core.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regexec.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regexec.$(OBJEXT): {$(VPATH)}internal/ctype.h +regexec.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regexec.$(OBJEXT): {$(VPATH)}internal/dosish.h +regexec.$(OBJEXT): {$(VPATH)}internal/error.h +regexec.$(OBJEXT): {$(VPATH)}internal/eval.h +regexec.$(OBJEXT): {$(VPATH)}internal/event.h +regexec.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regexec.$(OBJEXT): {$(VPATH)}internal/gc.h +regexec.$(OBJEXT): {$(VPATH)}internal/glob.h +regexec.$(OBJEXT): {$(VPATH)}internal/globals.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regexec.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regexec.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regexec.$(OBJEXT): {$(VPATH)}internal/iterator.h +regexec.$(OBJEXT): {$(VPATH)}internal/memory.h +regexec.$(OBJEXT): {$(VPATH)}internal/method.h +regexec.$(OBJEXT): {$(VPATH)}internal/module.h +regexec.$(OBJEXT): {$(VPATH)}internal/newobj.h +regexec.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regexec.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regexec.$(OBJEXT): {$(VPATH)}internal/value.h +regexec.$(OBJEXT): {$(VPATH)}internal/value_type.h +regexec.$(OBJEXT): {$(VPATH)}internal/variable.h +regexec.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regexec.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regexec.$(OBJEXT): {$(VPATH)}missing.h regexec.$(OBJEXT): {$(VPATH)}onigmo.h regexec.$(OBJEXT): {$(VPATH)}regenc.h @@ -2754,9 +12823,156 @@ regexec.$(OBJEXT): {$(VPATH)}st.h regexec.$(OBJEXT): {$(VPATH)}subst.h regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h regparse.$(OBJEXT): {$(VPATH)}assert.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regparse.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regparse.$(OBJEXT): {$(VPATH)}config.h regparse.$(OBJEXT): {$(VPATH)}defines.h regparse.$(OBJEXT): {$(VPATH)}intern.h +regparse.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regparse.$(OBJEXT): {$(VPATH)}internal/assume.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regparse.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regparse.$(OBJEXT): {$(VPATH)}internal/cast.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regparse.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regparse.$(OBJEXT): {$(VPATH)}internal/config.h +regparse.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regparse.$(OBJEXT): {$(VPATH)}internal/core.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regparse.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regparse.$(OBJEXT): {$(VPATH)}internal/ctype.h +regparse.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regparse.$(OBJEXT): {$(VPATH)}internal/dosish.h +regparse.$(OBJEXT): {$(VPATH)}internal/error.h +regparse.$(OBJEXT): {$(VPATH)}internal/eval.h +regparse.$(OBJEXT): {$(VPATH)}internal/event.h +regparse.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regparse.$(OBJEXT): {$(VPATH)}internal/gc.h +regparse.$(OBJEXT): {$(VPATH)}internal/glob.h +regparse.$(OBJEXT): {$(VPATH)}internal/globals.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regparse.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regparse.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regparse.$(OBJEXT): {$(VPATH)}internal/iterator.h +regparse.$(OBJEXT): {$(VPATH)}internal/memory.h +regparse.$(OBJEXT): {$(VPATH)}internal/method.h +regparse.$(OBJEXT): {$(VPATH)}internal/module.h +regparse.$(OBJEXT): {$(VPATH)}internal/newobj.h +regparse.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regparse.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regparse.$(OBJEXT): {$(VPATH)}internal/value.h +regparse.$(OBJEXT): {$(VPATH)}internal/value_type.h +regparse.$(OBJEXT): {$(VPATH)}internal/variable.h +regparse.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regparse.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regparse.$(OBJEXT): {$(VPATH)}missing.h regparse.$(OBJEXT): {$(VPATH)}onigmo.h regparse.$(OBJEXT): {$(VPATH)}regenc.h @@ -2767,9 +12983,156 @@ regparse.$(OBJEXT): {$(VPATH)}st.h regparse.$(OBJEXT): {$(VPATH)}subst.h regsyntax.$(OBJEXT): $(hdrdir)/ruby/ruby.h regsyntax.$(OBJEXT): {$(VPATH)}assert.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/assume.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/bool.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/limits.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +regsyntax.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h regsyntax.$(OBJEXT): {$(VPATH)}config.h regsyntax.$(OBJEXT): {$(VPATH)}defines.h regsyntax.$(OBJEXT): {$(VPATH)}intern.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/anyargs.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/assume.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/const.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/error.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/format.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/cast.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/config.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/constant_p.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/robject.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/ctype.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/dllexport.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/dosish.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/error.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/eval.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/event.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/fl_type.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/gc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/glob.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/globals.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/extension.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/feature.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/has/warning.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/array.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/class.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/error.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/file.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/io.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/load.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/object.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/process.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/random.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/range.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/string.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/time.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/interpreter.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/iterator.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/memory.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/method.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/module.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/newobj.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/rgengc.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/value.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/value_type.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/variable.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/warning_push.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/xmalloc.h regsyntax.$(OBJEXT): {$(VPATH)}missing.h regsyntax.$(OBJEXT): {$(VPATH)}onigmo.h regsyntax.$(OBJEXT): {$(VPATH)}regenc.h @@ -2778,6 +13141,15 @@ regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c regsyntax.$(OBJEXT): {$(VPATH)}st.h regsyntax.$(OBJEXT): {$(VPATH)}subst.h ruby-runner.$(OBJEXT): {$(VPATH)}config.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +ruby-runner.$(OBJEXT): {$(VPATH)}internal/config.h ruby-runner.$(OBJEXT): {$(VPATH)}ruby-runner.c ruby-runner.$(OBJEXT): {$(VPATH)}ruby-runner.h ruby.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h @@ -2787,16 +13159,199 @@ ruby.$(OBJEXT): $(CCAN_DIR)/str/str.h ruby.$(OBJEXT): $(hdrdir)/ruby.h ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h ruby.$(OBJEXT): $(hdrdir)/ruby/version.h +ruby.$(OBJEXT): $(top_srcdir)/internal/array.h +ruby.$(OBJEXT): $(top_srcdir)/internal/class.h +ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ruby.$(OBJEXT): $(top_srcdir)/internal/error.h +ruby.$(OBJEXT): $(top_srcdir)/internal/file.h +ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h +ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h +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/object.h +ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h +ruby.$(OBJEXT): $(top_srcdir)/internal/process.h +ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h +ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +ruby.$(OBJEXT): $(top_srcdir)/internal/string.h +ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h +ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h +ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h ruby.$(OBJEXT): {$(VPATH)}assert.h +ruby.$(OBJEXT): {$(VPATH)}atomic.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/bool.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/limits.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +ruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h ruby.$(OBJEXT): {$(VPATH)}config.h +ruby.$(OBJEXT): {$(VPATH)}constant.h +ruby.$(OBJEXT): {$(VPATH)}darray.h ruby.$(OBJEXT): {$(VPATH)}debug_counter.h ruby.$(OBJEXT): {$(VPATH)}defines.h ruby.$(OBJEXT): {$(VPATH)}dln.h ruby.$(OBJEXT): {$(VPATH)}encoding.h ruby.$(OBJEXT): {$(VPATH)}eval_intern.h ruby.$(OBJEXT): {$(VPATH)}id.h +ruby.$(OBJEXT): {$(VPATH)}id_table.h ruby.$(OBJEXT): {$(VPATH)}intern.h ruby.$(OBJEXT): {$(VPATH)}internal.h +ruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +ruby.$(OBJEXT): {$(VPATH)}internal/assume.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/const.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/error.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/format.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +ruby.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +ruby.$(OBJEXT): {$(VPATH)}internal/cast.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +ruby.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +ruby.$(OBJEXT): {$(VPATH)}internal/config.h +ruby.$(OBJEXT): {$(VPATH)}internal/constant_p.h +ruby.$(OBJEXT): {$(VPATH)}internal/core.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/robject.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +ruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +ruby.$(OBJEXT): {$(VPATH)}internal/ctype.h +ruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h +ruby.$(OBJEXT): {$(VPATH)}internal/dosish.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +ruby.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +ruby.$(OBJEXT): {$(VPATH)}internal/error.h +ruby.$(OBJEXT): {$(VPATH)}internal/eval.h +ruby.$(OBJEXT): {$(VPATH)}internal/event.h +ruby.$(OBJEXT): {$(VPATH)}internal/fl_type.h +ruby.$(OBJEXT): {$(VPATH)}internal/gc.h +ruby.$(OBJEXT): {$(VPATH)}internal/glob.h +ruby.$(OBJEXT): {$(VPATH)}internal/globals.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/extension.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/feature.h +ruby.$(OBJEXT): {$(VPATH)}internal/has/warning.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/array.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/class.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/error.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/file.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/io.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/load.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/object.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/process.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/random.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/range.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/time.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +ruby.$(OBJEXT): {$(VPATH)}internal/interpreter.h +ruby.$(OBJEXT): {$(VPATH)}internal/iterator.h +ruby.$(OBJEXT): {$(VPATH)}internal/memory.h +ruby.$(OBJEXT): {$(VPATH)}internal/method.h +ruby.$(OBJEXT): {$(VPATH)}internal/module.h +ruby.$(OBJEXT): {$(VPATH)}internal/newobj.h +ruby.$(OBJEXT): {$(VPATH)}internal/rgengc.h +ruby.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +ruby.$(OBJEXT): {$(VPATH)}internal/value.h +ruby.$(OBJEXT): {$(VPATH)}internal/value_type.h +ruby.$(OBJEXT): {$(VPATH)}internal/variable.h +ruby.$(OBJEXT): {$(VPATH)}internal/warning_push.h +ruby.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +ruby.$(OBJEXT): {$(VPATH)}io.h ruby.$(OBJEXT): {$(VPATH)}method.h ruby.$(OBJEXT): {$(VPATH)}missing.h ruby.$(OBJEXT): {$(VPATH)}mjit.h @@ -2814,36 +13369,357 @@ ruby.$(OBJEXT): {$(VPATH)}thread_native.h ruby.$(OBJEXT): {$(VPATH)}util.h ruby.$(OBJEXT): {$(VPATH)}vm_core.h ruby.$(OBJEXT): {$(VPATH)}vm_opts.h -safe.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h -safe.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h -safe.$(OBJEXT): $(CCAN_DIR)/list/list.h -safe.$(OBJEXT): $(CCAN_DIR)/str/str.h -safe.$(OBJEXT): $(hdrdir)/ruby.h -safe.$(OBJEXT): $(hdrdir)/ruby/ruby.h -safe.$(OBJEXT): {$(VPATH)}assert.h -safe.$(OBJEXT): {$(VPATH)}config.h -safe.$(OBJEXT): {$(VPATH)}defines.h -safe.$(OBJEXT): {$(VPATH)}id.h -safe.$(OBJEXT): {$(VPATH)}intern.h -safe.$(OBJEXT): {$(VPATH)}internal.h -safe.$(OBJEXT): {$(VPATH)}method.h -safe.$(OBJEXT): {$(VPATH)}missing.h -safe.$(OBJEXT): {$(VPATH)}node.h -safe.$(OBJEXT): {$(VPATH)}ruby_assert.h -safe.$(OBJEXT): {$(VPATH)}ruby_atomic.h -safe.$(OBJEXT): {$(VPATH)}safe.c -safe.$(OBJEXT): {$(VPATH)}st.h -safe.$(OBJEXT): {$(VPATH)}subst.h -safe.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h -safe.$(OBJEXT): {$(VPATH)}thread_native.h -safe.$(OBJEXT): {$(VPATH)}vm_core.h -safe.$(OBJEXT): {$(VPATH)}vm_opts.h +ruby.$(OBJEXT): {$(VPATH)}yjit.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 +scheduler.$(OBJEXT): $(CCAN_DIR)/str/str.h +scheduler.$(OBJEXT): $(hdrdir)/ruby/ruby.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/vm.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/warnings.h +scheduler.$(OBJEXT): {$(VPATH)}assert.h +scheduler.$(OBJEXT): {$(VPATH)}atomic.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/assume.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/bool.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/limits.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +scheduler.$(OBJEXT): {$(VPATH)}config.h +scheduler.$(OBJEXT): {$(VPATH)}darray.h +scheduler.$(OBJEXT): {$(VPATH)}defines.h +scheduler.$(OBJEXT): {$(VPATH)}encoding.h +scheduler.$(OBJEXT): {$(VPATH)}fiber/scheduler.h +scheduler.$(OBJEXT): {$(VPATH)}id.h +scheduler.$(OBJEXT): {$(VPATH)}intern.h +scheduler.$(OBJEXT): {$(VPATH)}internal.h +scheduler.$(OBJEXT): {$(VPATH)}internal/anyargs.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +scheduler.$(OBJEXT): {$(VPATH)}internal/assume.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/const.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/error.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/format.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +scheduler.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +scheduler.$(OBJEXT): {$(VPATH)}internal/cast.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +scheduler.$(OBJEXT): {$(VPATH)}internal/config.h +scheduler.$(OBJEXT): {$(VPATH)}internal/constant_p.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/robject.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +scheduler.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +scheduler.$(OBJEXT): {$(VPATH)}internal/ctype.h +scheduler.$(OBJEXT): {$(VPATH)}internal/dllexport.h +scheduler.$(OBJEXT): {$(VPATH)}internal/dosish.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +scheduler.$(OBJEXT): {$(VPATH)}internal/error.h +scheduler.$(OBJEXT): {$(VPATH)}internal/eval.h +scheduler.$(OBJEXT): {$(VPATH)}internal/event.h +scheduler.$(OBJEXT): {$(VPATH)}internal/fl_type.h +scheduler.$(OBJEXT): {$(VPATH)}internal/gc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/glob.h +scheduler.$(OBJEXT): {$(VPATH)}internal/globals.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/extension.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/feature.h +scheduler.$(OBJEXT): {$(VPATH)}internal/has/warning.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/array.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/class.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/error.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/file.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/io.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/load.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/object.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/process.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/random.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/range.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/string.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/time.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +scheduler.$(OBJEXT): {$(VPATH)}internal/interpreter.h +scheduler.$(OBJEXT): {$(VPATH)}internal/iterator.h +scheduler.$(OBJEXT): {$(VPATH)}internal/memory.h +scheduler.$(OBJEXT): {$(VPATH)}internal/method.h +scheduler.$(OBJEXT): {$(VPATH)}internal/module.h +scheduler.$(OBJEXT): {$(VPATH)}internal/newobj.h +scheduler.$(OBJEXT): {$(VPATH)}internal/rgengc.h +scheduler.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +scheduler.$(OBJEXT): {$(VPATH)}internal/value.h +scheduler.$(OBJEXT): {$(VPATH)}internal/value_type.h +scheduler.$(OBJEXT): {$(VPATH)}internal/variable.h +scheduler.$(OBJEXT): {$(VPATH)}internal/warning_push.h +scheduler.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +scheduler.$(OBJEXT): {$(VPATH)}io.h +scheduler.$(OBJEXT): {$(VPATH)}io/buffer.h +scheduler.$(OBJEXT): {$(VPATH)}method.h +scheduler.$(OBJEXT): {$(VPATH)}missing.h +scheduler.$(OBJEXT): {$(VPATH)}node.h +scheduler.$(OBJEXT): {$(VPATH)}onigmo.h +scheduler.$(OBJEXT): {$(VPATH)}oniguruma.h +scheduler.$(OBJEXT): {$(VPATH)}ruby_assert.h +scheduler.$(OBJEXT): {$(VPATH)}ruby_atomic.h +scheduler.$(OBJEXT): {$(VPATH)}scheduler.c +scheduler.$(OBJEXT): {$(VPATH)}st.h +scheduler.$(OBJEXT): {$(VPATH)}subst.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 setproctitle.$(OBJEXT): $(hdrdir)/ruby.h setproctitle.$(OBJEXT): $(hdrdir)/ruby/ruby.h setproctitle.$(OBJEXT): {$(VPATH)}assert.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/assume.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/bool.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/limits.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +setproctitle.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h setproctitle.$(OBJEXT): {$(VPATH)}config.h setproctitle.$(OBJEXT): {$(VPATH)}defines.h setproctitle.$(OBJEXT): {$(VPATH)}intern.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/anyargs.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/assume.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/const.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/error.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/format.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/cast.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/config.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/constant_p.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/robject.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/ctype.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/dllexport.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/dosish.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/error.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/eval.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/event.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/fl_type.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/gc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/glob.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/globals.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/extension.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/feature.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/has/warning.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/array.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/class.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/error.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/file.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/io.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/load.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/object.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/process.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/random.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/range.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/string.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/time.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/interpreter.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/iterator.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/memory.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/method.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/module.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/newobj.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/rgengc.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/value.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/value_type.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/variable.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/warning_push.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/xmalloc.h setproctitle.$(OBJEXT): {$(VPATH)}missing.h setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c setproctitle.$(OBJEXT): {$(VPATH)}st.h @@ -2853,19 +13729,196 @@ signal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h signal.$(OBJEXT): $(hdrdir)/ruby/ruby.h +signal.$(OBJEXT): $(top_srcdir)/internal/array.h +signal.$(OBJEXT): $(top_srcdir)/internal/compilers.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/sanitizers.h +signal.$(OBJEXT): $(top_srcdir)/internal/serial.h +signal.$(OBJEXT): $(top_srcdir)/internal/signal.h +signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +signal.$(OBJEXT): $(top_srcdir)/internal/string.h +signal.$(OBJEXT): $(top_srcdir)/internal/thread.h +signal.$(OBJEXT): $(top_srcdir)/internal/vm.h +signal.$(OBJEXT): $(top_srcdir)/internal/warnings.h signal.$(OBJEXT): {$(VPATH)}assert.h +signal.$(OBJEXT): {$(VPATH)}atomic.h +signal.$(OBJEXT): {$(VPATH)}backward/2/assume.h +signal.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +signal.$(OBJEXT): {$(VPATH)}backward/2/bool.h +signal.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +signal.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +signal.$(OBJEXT): {$(VPATH)}backward/2/limits.h +signal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +signal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +signal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h signal.$(OBJEXT): {$(VPATH)}config.h +signal.$(OBJEXT): {$(VPATH)}darray.h signal.$(OBJEXT): {$(VPATH)}debug_counter.h signal.$(OBJEXT): {$(VPATH)}defines.h +signal.$(OBJEXT): {$(VPATH)}encoding.h signal.$(OBJEXT): {$(VPATH)}eval_intern.h signal.$(OBJEXT): {$(VPATH)}id.h +signal.$(OBJEXT): {$(VPATH)}id_table.h signal.$(OBJEXT): {$(VPATH)}intern.h signal.$(OBJEXT): {$(VPATH)}internal.h +signal.$(OBJEXT): {$(VPATH)}internal/anyargs.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +signal.$(OBJEXT): {$(VPATH)}internal/assume.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/const.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/error.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/format.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +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/noreturn.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +signal.$(OBJEXT): {$(VPATH)}internal/cast.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +signal.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +signal.$(OBJEXT): {$(VPATH)}internal/config.h +signal.$(OBJEXT): {$(VPATH)}internal/constant_p.h +signal.$(OBJEXT): {$(VPATH)}internal/core.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +signal.$(OBJEXT): {$(VPATH)}internal/core/robject.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +signal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +signal.$(OBJEXT): {$(VPATH)}internal/ctype.h +signal.$(OBJEXT): {$(VPATH)}internal/dllexport.h +signal.$(OBJEXT): {$(VPATH)}internal/dosish.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +signal.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +signal.$(OBJEXT): {$(VPATH)}internal/error.h +signal.$(OBJEXT): {$(VPATH)}internal/eval.h +signal.$(OBJEXT): {$(VPATH)}internal/event.h +signal.$(OBJEXT): {$(VPATH)}internal/fl_type.h +signal.$(OBJEXT): {$(VPATH)}internal/gc.h +signal.$(OBJEXT): {$(VPATH)}internal/glob.h +signal.$(OBJEXT): {$(VPATH)}internal/globals.h +signal.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +signal.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +signal.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +signal.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +signal.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +signal.$(OBJEXT): {$(VPATH)}internal/has/extension.h +signal.$(OBJEXT): {$(VPATH)}internal/has/feature.h +signal.$(OBJEXT): {$(VPATH)}internal/has/warning.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/array.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/class.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/error.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/file.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/io.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/load.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/object.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/process.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/random.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/range.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/string.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/time.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +signal.$(OBJEXT): {$(VPATH)}internal/interpreter.h +signal.$(OBJEXT): {$(VPATH)}internal/iterator.h +signal.$(OBJEXT): {$(VPATH)}internal/memory.h +signal.$(OBJEXT): {$(VPATH)}internal/method.h +signal.$(OBJEXT): {$(VPATH)}internal/module.h +signal.$(OBJEXT): {$(VPATH)}internal/newobj.h +signal.$(OBJEXT): {$(VPATH)}internal/rgengc.h +signal.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +signal.$(OBJEXT): {$(VPATH)}internal/value.h +signal.$(OBJEXT): {$(VPATH)}internal/value_type.h +signal.$(OBJEXT): {$(VPATH)}internal/variable.h +signal.$(OBJEXT): {$(VPATH)}internal/warning_push.h +signal.$(OBJEXT): {$(VPATH)}internal/xmalloc.h signal.$(OBJEXT): {$(VPATH)}method.h signal.$(OBJEXT): {$(VPATH)}missing.h signal.$(OBJEXT): {$(VPATH)}node.h +signal.$(OBJEXT): {$(VPATH)}onigmo.h +signal.$(OBJEXT): {$(VPATH)}oniguruma.h +signal.$(OBJEXT): {$(VPATH)}ractor.h +signal.$(OBJEXT): {$(VPATH)}ractor_core.h signal.$(OBJEXT): {$(VPATH)}ruby_assert.h signal.$(OBJEXT): {$(VPATH)}ruby_atomic.h signal.$(OBJEXT): {$(VPATH)}signal.c @@ -2874,16 +13927,192 @@ signal.$(OBJEXT): {$(VPATH)}subst.h signal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h signal.$(OBJEXT): {$(VPATH)}thread_native.h signal.$(OBJEXT): {$(VPATH)}vm_core.h +signal.$(OBJEXT): {$(VPATH)}vm_debug.h signal.$(OBJEXT): {$(VPATH)}vm_opts.h -sprintf.$(OBJEXT): $(hdrdir)/ruby.h sprintf.$(OBJEXT): $(hdrdir)/ruby/ruby.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/compilers.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/error.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/gc.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/hash.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/numeric.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/object.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/serial.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/string.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/symbol.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/vm.h +sprintf.$(OBJEXT): $(top_srcdir)/internal/warnings.h sprintf.$(OBJEXT): {$(VPATH)}assert.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/assume.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/bool.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/limits.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h sprintf.$(OBJEXT): {$(VPATH)}config.h sprintf.$(OBJEXT): {$(VPATH)}defines.h sprintf.$(OBJEXT): {$(VPATH)}encoding.h sprintf.$(OBJEXT): {$(VPATH)}id.h +sprintf.$(OBJEXT): {$(VPATH)}id_table.h sprintf.$(OBJEXT): {$(VPATH)}intern.h sprintf.$(OBJEXT): {$(VPATH)}internal.h +sprintf.$(OBJEXT): {$(VPATH)}internal/anyargs.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +sprintf.$(OBJEXT): {$(VPATH)}internal/assume.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/const.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/error.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/format.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +sprintf.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +sprintf.$(OBJEXT): {$(VPATH)}internal/cast.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +sprintf.$(OBJEXT): {$(VPATH)}internal/config.h +sprintf.$(OBJEXT): {$(VPATH)}internal/constant_p.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/robject.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +sprintf.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +sprintf.$(OBJEXT): {$(VPATH)}internal/ctype.h +sprintf.$(OBJEXT): {$(VPATH)}internal/dllexport.h +sprintf.$(OBJEXT): {$(VPATH)}internal/dosish.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +sprintf.$(OBJEXT): {$(VPATH)}internal/error.h +sprintf.$(OBJEXT): {$(VPATH)}internal/eval.h +sprintf.$(OBJEXT): {$(VPATH)}internal/event.h +sprintf.$(OBJEXT): {$(VPATH)}internal/fl_type.h +sprintf.$(OBJEXT): {$(VPATH)}internal/gc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/glob.h +sprintf.$(OBJEXT): {$(VPATH)}internal/globals.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/extension.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/feature.h +sprintf.$(OBJEXT): {$(VPATH)}internal/has/warning.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/array.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/class.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/error.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/file.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/io.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/load.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/object.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/process.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/random.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/range.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/string.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/time.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +sprintf.$(OBJEXT): {$(VPATH)}internal/interpreter.h +sprintf.$(OBJEXT): {$(VPATH)}internal/iterator.h +sprintf.$(OBJEXT): {$(VPATH)}internal/memory.h +sprintf.$(OBJEXT): {$(VPATH)}internal/method.h +sprintf.$(OBJEXT): {$(VPATH)}internal/module.h +sprintf.$(OBJEXT): {$(VPATH)}internal/newobj.h +sprintf.$(OBJEXT): {$(VPATH)}internal/rgengc.h +sprintf.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +sprintf.$(OBJEXT): {$(VPATH)}internal/value.h +sprintf.$(OBJEXT): {$(VPATH)}internal/value_type.h +sprintf.$(OBJEXT): {$(VPATH)}internal/variable.h +sprintf.$(OBJEXT): {$(VPATH)}internal/warning_push.h +sprintf.$(OBJEXT): {$(VPATH)}internal/xmalloc.h sprintf.$(OBJEXT): {$(VPATH)}missing.h sprintf.$(OBJEXT): {$(VPATH)}onigmo.h sprintf.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2892,26 +14121,341 @@ sprintf.$(OBJEXT): {$(VPATH)}regex.h sprintf.$(OBJEXT): {$(VPATH)}sprintf.c sprintf.$(OBJEXT): {$(VPATH)}st.h sprintf.$(OBJEXT): {$(VPATH)}subst.h +sprintf.$(OBJEXT): {$(VPATH)}util.h sprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c -st.$(OBJEXT): $(hdrdir)/ruby.h st.$(OBJEXT): $(hdrdir)/ruby/ruby.h +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/static_assert.h +st.$(OBJEXT): $(top_srcdir)/internal/warnings.h st.$(OBJEXT): {$(VPATH)}assert.h +st.$(OBJEXT): {$(VPATH)}backward/2/assume.h +st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +st.$(OBJEXT): {$(VPATH)}backward/2/bool.h +st.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +st.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +st.$(OBJEXT): {$(VPATH)}backward/2/limits.h +st.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h st.$(OBJEXT): {$(VPATH)}config.h st.$(OBJEXT): {$(VPATH)}defines.h st.$(OBJEXT): {$(VPATH)}intern.h st.$(OBJEXT): {$(VPATH)}internal.h +st.$(OBJEXT): {$(VPATH)}internal/anyargs.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +st.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +st.$(OBJEXT): {$(VPATH)}internal/assume.h +st.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +st.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +st.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +st.$(OBJEXT): {$(VPATH)}internal/attr/const.h +st.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +st.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +st.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +st.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +st.$(OBJEXT): {$(VPATH)}internal/attr/error.h +st.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +st.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +st.$(OBJEXT): {$(VPATH)}internal/attr/format.h +st.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +st.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +st.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +st.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +st.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +st.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +st.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +st.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +st.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +st.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +st.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +st.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +st.$(OBJEXT): {$(VPATH)}internal/cast.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +st.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +st.$(OBJEXT): {$(VPATH)}internal/config.h +st.$(OBJEXT): {$(VPATH)}internal/constant_p.h +st.$(OBJEXT): {$(VPATH)}internal/core.h +st.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +st.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +st.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +st.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +st.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +st.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +st.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +st.$(OBJEXT): {$(VPATH)}internal/core/robject.h +st.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +st.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +st.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +st.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +st.$(OBJEXT): {$(VPATH)}internal/ctype.h +st.$(OBJEXT): {$(VPATH)}internal/dllexport.h +st.$(OBJEXT): {$(VPATH)}internal/dosish.h +st.$(OBJEXT): {$(VPATH)}internal/error.h +st.$(OBJEXT): {$(VPATH)}internal/eval.h +st.$(OBJEXT): {$(VPATH)}internal/event.h +st.$(OBJEXT): {$(VPATH)}internal/fl_type.h +st.$(OBJEXT): {$(VPATH)}internal/gc.h +st.$(OBJEXT): {$(VPATH)}internal/glob.h +st.$(OBJEXT): {$(VPATH)}internal/globals.h +st.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +st.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +st.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +st.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +st.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +st.$(OBJEXT): {$(VPATH)}internal/has/extension.h +st.$(OBJEXT): {$(VPATH)}internal/has/feature.h +st.$(OBJEXT): {$(VPATH)}internal/has/warning.h +st.$(OBJEXT): {$(VPATH)}internal/intern/array.h +st.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +st.$(OBJEXT): {$(VPATH)}internal/intern/class.h +st.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +st.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +st.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +st.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +st.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +st.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +st.$(OBJEXT): {$(VPATH)}internal/intern/error.h +st.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +st.$(OBJEXT): {$(VPATH)}internal/intern/file.h +st.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +st.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +st.$(OBJEXT): {$(VPATH)}internal/intern/io.h +st.$(OBJEXT): {$(VPATH)}internal/intern/load.h +st.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +st.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +st.$(OBJEXT): {$(VPATH)}internal/intern/object.h +st.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +st.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +st.$(OBJEXT): {$(VPATH)}internal/intern/process.h +st.$(OBJEXT): {$(VPATH)}internal/intern/random.h +st.$(OBJEXT): {$(VPATH)}internal/intern/range.h +st.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +st.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +st.$(OBJEXT): {$(VPATH)}internal/intern/string.h +st.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +st.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +st.$(OBJEXT): {$(VPATH)}internal/intern/time.h +st.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +st.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +st.$(OBJEXT): {$(VPATH)}internal/interpreter.h +st.$(OBJEXT): {$(VPATH)}internal/iterator.h +st.$(OBJEXT): {$(VPATH)}internal/memory.h +st.$(OBJEXT): {$(VPATH)}internal/method.h +st.$(OBJEXT): {$(VPATH)}internal/module.h +st.$(OBJEXT): {$(VPATH)}internal/newobj.h +st.$(OBJEXT): {$(VPATH)}internal/rgengc.h +st.$(OBJEXT): {$(VPATH)}internal/scan_args.h +st.$(OBJEXT): {$(VPATH)}internal/special_consts.h +st.$(OBJEXT): {$(VPATH)}internal/static_assert.h +st.$(OBJEXT): {$(VPATH)}internal/stdalign.h +st.$(OBJEXT): {$(VPATH)}internal/stdbool.h +st.$(OBJEXT): {$(VPATH)}internal/symbol.h +st.$(OBJEXT): {$(VPATH)}internal/value.h +st.$(OBJEXT): {$(VPATH)}internal/value_type.h +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)}st.c st.$(OBJEXT): {$(VPATH)}st.h st.$(OBJEXT): {$(VPATH)}subst.h -strftime.$(OBJEXT): $(hdrdir)/ruby.h strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h +strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h +strftime.$(OBJEXT): $(top_srcdir)/internal/serial.h +strftime.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +strftime.$(OBJEXT): $(top_srcdir)/internal/string.h +strftime.$(OBJEXT): $(top_srcdir)/internal/vm.h strftime.$(OBJEXT): {$(VPATH)}assert.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/assume.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/bool.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/limits.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +strftime.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h strftime.$(OBJEXT): {$(VPATH)}config.h strftime.$(OBJEXT): {$(VPATH)}defines.h strftime.$(OBJEXT): {$(VPATH)}encoding.h strftime.$(OBJEXT): {$(VPATH)}intern.h strftime.$(OBJEXT): {$(VPATH)}internal.h +strftime.$(OBJEXT): {$(VPATH)}internal/anyargs.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +strftime.$(OBJEXT): {$(VPATH)}internal/assume.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/const.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/error.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/format.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +strftime.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +strftime.$(OBJEXT): {$(VPATH)}internal/cast.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +strftime.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +strftime.$(OBJEXT): {$(VPATH)}internal/config.h +strftime.$(OBJEXT): {$(VPATH)}internal/constant_p.h +strftime.$(OBJEXT): {$(VPATH)}internal/core.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/robject.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +strftime.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +strftime.$(OBJEXT): {$(VPATH)}internal/ctype.h +strftime.$(OBJEXT): {$(VPATH)}internal/dllexport.h +strftime.$(OBJEXT): {$(VPATH)}internal/dosish.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +strftime.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +strftime.$(OBJEXT): {$(VPATH)}internal/error.h +strftime.$(OBJEXT): {$(VPATH)}internal/eval.h +strftime.$(OBJEXT): {$(VPATH)}internal/event.h +strftime.$(OBJEXT): {$(VPATH)}internal/fl_type.h +strftime.$(OBJEXT): {$(VPATH)}internal/gc.h +strftime.$(OBJEXT): {$(VPATH)}internal/glob.h +strftime.$(OBJEXT): {$(VPATH)}internal/globals.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/extension.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/feature.h +strftime.$(OBJEXT): {$(VPATH)}internal/has/warning.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/array.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/class.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/error.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/file.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/io.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/load.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/object.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/process.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/random.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/range.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/string.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/time.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +strftime.$(OBJEXT): {$(VPATH)}internal/interpreter.h +strftime.$(OBJEXT): {$(VPATH)}internal/iterator.h +strftime.$(OBJEXT): {$(VPATH)}internal/memory.h +strftime.$(OBJEXT): {$(VPATH)}internal/method.h +strftime.$(OBJEXT): {$(VPATH)}internal/module.h +strftime.$(OBJEXT): {$(VPATH)}internal/newobj.h +strftime.$(OBJEXT): {$(VPATH)}internal/rgengc.h +strftime.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +strftime.$(OBJEXT): {$(VPATH)}internal/value.h +strftime.$(OBJEXT): {$(VPATH)}internal/value_type.h +strftime.$(OBJEXT): {$(VPATH)}internal/variable.h +strftime.$(OBJEXT): {$(VPATH)}internal/warning_push.h +strftime.$(OBJEXT): {$(VPATH)}internal/xmalloc.h strftime.$(OBJEXT): {$(VPATH)}missing.h strftime.$(OBJEXT): {$(VPATH)}onigmo.h strftime.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2919,19 +14463,199 @@ strftime.$(OBJEXT): {$(VPATH)}st.h strftime.$(OBJEXT): {$(VPATH)}strftime.c strftime.$(OBJEXT): {$(VPATH)}subst.h strftime.$(OBJEXT): {$(VPATH)}timev.h -string.$(OBJEXT): $(hdrdir)/ruby.h +strftime.$(OBJEXT): {$(VPATH)}util.h string.$(OBJEXT): $(hdrdir)/ruby/ruby.h +string.$(OBJEXT): $(top_srcdir)/internal/array.h +string.$(OBJEXT): $(top_srcdir)/internal/bignum.h +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/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/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/static_assert.h +string.$(OBJEXT): $(top_srcdir)/internal/string.h +string.$(OBJEXT): $(top_srcdir)/internal/transcode.h +string.$(OBJEXT): $(top_srcdir)/internal/vm.h +string.$(OBJEXT): $(top_srcdir)/internal/warnings.h string.$(OBJEXT): {$(VPATH)}assert.h +string.$(OBJEXT): {$(VPATH)}atomic.h +string.$(OBJEXT): {$(VPATH)}backward/2/assume.h +string.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +string.$(OBJEXT): {$(VPATH)}backward/2/bool.h +string.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +string.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +string.$(OBJEXT): {$(VPATH)}backward/2/limits.h +string.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +string.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +string.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h string.$(OBJEXT): {$(VPATH)}config.h -string.$(OBJEXT): {$(VPATH)}crypt.h string.$(OBJEXT): {$(VPATH)}debug_counter.h string.$(OBJEXT): {$(VPATH)}defines.h string.$(OBJEXT): {$(VPATH)}encindex.h string.$(OBJEXT): {$(VPATH)}encoding.h string.$(OBJEXT): {$(VPATH)}gc.h string.$(OBJEXT): {$(VPATH)}id.h +string.$(OBJEXT): {$(VPATH)}id_table.h string.$(OBJEXT): {$(VPATH)}intern.h string.$(OBJEXT): {$(VPATH)}internal.h +string.$(OBJEXT): {$(VPATH)}internal/anyargs.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +string.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +string.$(OBJEXT): {$(VPATH)}internal/assume.h +string.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +string.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +string.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +string.$(OBJEXT): {$(VPATH)}internal/attr/const.h +string.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +string.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +string.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +string.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +string.$(OBJEXT): {$(VPATH)}internal/attr/error.h +string.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +string.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +string.$(OBJEXT): {$(VPATH)}internal/attr/format.h +string.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +string.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +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/noreturn.h +string.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +string.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +string.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +string.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +string.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +string.$(OBJEXT): {$(VPATH)}internal/cast.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +string.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +string.$(OBJEXT): {$(VPATH)}internal/config.h +string.$(OBJEXT): {$(VPATH)}internal/constant_p.h +string.$(OBJEXT): {$(VPATH)}internal/core.h +string.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +string.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +string.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +string.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +string.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +string.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +string.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +string.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h +string.$(OBJEXT): {$(VPATH)}internal/core/robject.h +string.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +string.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +string.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +string.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +string.$(OBJEXT): {$(VPATH)}internal/ctype.h +string.$(OBJEXT): {$(VPATH)}internal/dllexport.h +string.$(OBJEXT): {$(VPATH)}internal/dosish.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +string.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +string.$(OBJEXT): {$(VPATH)}internal/error.h +string.$(OBJEXT): {$(VPATH)}internal/eval.h +string.$(OBJEXT): {$(VPATH)}internal/event.h +string.$(OBJEXT): {$(VPATH)}internal/fl_type.h +string.$(OBJEXT): {$(VPATH)}internal/gc.h +string.$(OBJEXT): {$(VPATH)}internal/glob.h +string.$(OBJEXT): {$(VPATH)}internal/globals.h +string.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +string.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +string.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +string.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +string.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +string.$(OBJEXT): {$(VPATH)}internal/has/extension.h +string.$(OBJEXT): {$(VPATH)}internal/has/feature.h +string.$(OBJEXT): {$(VPATH)}internal/has/warning.h +string.$(OBJEXT): {$(VPATH)}internal/intern/array.h +string.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +string.$(OBJEXT): {$(VPATH)}internal/intern/class.h +string.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +string.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +string.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +string.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +string.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +string.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +string.$(OBJEXT): {$(VPATH)}internal/intern/error.h +string.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +string.$(OBJEXT): {$(VPATH)}internal/intern/file.h +string.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +string.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +string.$(OBJEXT): {$(VPATH)}internal/intern/io.h +string.$(OBJEXT): {$(VPATH)}internal/intern/load.h +string.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +string.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +string.$(OBJEXT): {$(VPATH)}internal/intern/object.h +string.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +string.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +string.$(OBJEXT): {$(VPATH)}internal/intern/process.h +string.$(OBJEXT): {$(VPATH)}internal/intern/random.h +string.$(OBJEXT): {$(VPATH)}internal/intern/range.h +string.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +string.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +string.$(OBJEXT): {$(VPATH)}internal/intern/string.h +string.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +string.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +string.$(OBJEXT): {$(VPATH)}internal/intern/time.h +string.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +string.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +string.$(OBJEXT): {$(VPATH)}internal/interpreter.h +string.$(OBJEXT): {$(VPATH)}internal/iterator.h +string.$(OBJEXT): {$(VPATH)}internal/memory.h +string.$(OBJEXT): {$(VPATH)}internal/method.h +string.$(OBJEXT): {$(VPATH)}internal/module.h +string.$(OBJEXT): {$(VPATH)}internal/newobj.h +string.$(OBJEXT): {$(VPATH)}internal/rgengc.h +string.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +string.$(OBJEXT): {$(VPATH)}internal/value.h +string.$(OBJEXT): {$(VPATH)}internal/value_type.h +string.$(OBJEXT): {$(VPATH)}internal/variable.h +string.$(OBJEXT): {$(VPATH)}internal/warning_push.h +string.$(OBJEXT): {$(VPATH)}internal/xmalloc.h string.$(OBJEXT): {$(VPATH)}missing.h string.$(OBJEXT): {$(VPATH)}onigmo.h string.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2943,28 +14667,234 @@ string.$(OBJEXT): {$(VPATH)}ruby_assert.h string.$(OBJEXT): {$(VPATH)}st.h string.$(OBJEXT): {$(VPATH)}string.c string.$(OBJEXT): {$(VPATH)}subst.h +string.$(OBJEXT): {$(VPATH)}thread_native.h string.$(OBJEXT): {$(VPATH)}util.h +string.$(OBJEXT): {$(VPATH)}vm_debug.h +string.$(OBJEXT): {$(VPATH)}vm_sync.h strlcat.$(OBJEXT): {$(VPATH)}config.h +strlcat.$(OBJEXT): {$(VPATH)}internal/attr/format.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +strlcat.$(OBJEXT): {$(VPATH)}internal/config.h +strlcat.$(OBJEXT): {$(VPATH)}internal/dllexport.h +strlcat.$(OBJEXT): {$(VPATH)}internal/has/attribute.h strlcat.$(OBJEXT): {$(VPATH)}missing.h strlcat.$(OBJEXT): {$(VPATH)}strlcat.c strlcpy.$(OBJEXT): {$(VPATH)}config.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/attr/format.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/config.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/dllexport.h +strlcpy.$(OBJEXT): {$(VPATH)}internal/has/attribute.h strlcpy.$(OBJEXT): {$(VPATH)}missing.h strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c struct.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h struct.$(OBJEXT): $(hdrdir)/ruby/ruby.h +struct.$(OBJEXT): $(top_srcdir)/internal/array.h +struct.$(OBJEXT): $(top_srcdir)/internal/class.h +struct.$(OBJEXT): $(top_srcdir)/internal/compilers.h +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/object.h +struct.$(OBJEXT): $(top_srcdir)/internal/proc.h +struct.$(OBJEXT): $(top_srcdir)/internal/serial.h +struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +struct.$(OBJEXT): $(top_srcdir)/internal/string.h +struct.$(OBJEXT): $(top_srcdir)/internal/struct.h +struct.$(OBJEXT): $(top_srcdir)/internal/symbol.h +struct.$(OBJEXT): $(top_srcdir)/internal/vm.h +struct.$(OBJEXT): $(top_srcdir)/internal/warnings.h struct.$(OBJEXT): {$(VPATH)}assert.h +struct.$(OBJEXT): {$(VPATH)}atomic.h +struct.$(OBJEXT): {$(VPATH)}backward/2/assume.h +struct.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +struct.$(OBJEXT): {$(VPATH)}backward/2/bool.h +struct.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +struct.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +struct.$(OBJEXT): {$(VPATH)}backward/2/limits.h +struct.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +struct.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +struct.$(OBJEXT): {$(VPATH)}builtin.h struct.$(OBJEXT): {$(VPATH)}config.h +struct.$(OBJEXT): {$(VPATH)}darray.h struct.$(OBJEXT): {$(VPATH)}defines.h +struct.$(OBJEXT): {$(VPATH)}encoding.h struct.$(OBJEXT): {$(VPATH)}id.h +struct.$(OBJEXT): {$(VPATH)}id_table.h struct.$(OBJEXT): {$(VPATH)}intern.h struct.$(OBJEXT): {$(VPATH)}internal.h +struct.$(OBJEXT): {$(VPATH)}internal/anyargs.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +struct.$(OBJEXT): {$(VPATH)}internal/assume.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/const.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/error.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/format.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +struct.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +struct.$(OBJEXT): {$(VPATH)}internal/cast.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +struct.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +struct.$(OBJEXT): {$(VPATH)}internal/config.h +struct.$(OBJEXT): {$(VPATH)}internal/constant_p.h +struct.$(OBJEXT): {$(VPATH)}internal/core.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +struct.$(OBJEXT): {$(VPATH)}internal/core/robject.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +struct.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +struct.$(OBJEXT): {$(VPATH)}internal/ctype.h +struct.$(OBJEXT): {$(VPATH)}internal/dllexport.h +struct.$(OBJEXT): {$(VPATH)}internal/dosish.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +struct.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +struct.$(OBJEXT): {$(VPATH)}internal/error.h +struct.$(OBJEXT): {$(VPATH)}internal/eval.h +struct.$(OBJEXT): {$(VPATH)}internal/event.h +struct.$(OBJEXT): {$(VPATH)}internal/fl_type.h +struct.$(OBJEXT): {$(VPATH)}internal/gc.h +struct.$(OBJEXT): {$(VPATH)}internal/glob.h +struct.$(OBJEXT): {$(VPATH)}internal/globals.h +struct.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +struct.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +struct.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +struct.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +struct.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +struct.$(OBJEXT): {$(VPATH)}internal/has/extension.h +struct.$(OBJEXT): {$(VPATH)}internal/has/feature.h +struct.$(OBJEXT): {$(VPATH)}internal/has/warning.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/array.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/class.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/error.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/file.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/io.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/load.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/object.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/process.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/random.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/range.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/string.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/time.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +struct.$(OBJEXT): {$(VPATH)}internal/interpreter.h +struct.$(OBJEXT): {$(VPATH)}internal/iterator.h +struct.$(OBJEXT): {$(VPATH)}internal/memory.h +struct.$(OBJEXT): {$(VPATH)}internal/method.h +struct.$(OBJEXT): {$(VPATH)}internal/module.h +struct.$(OBJEXT): {$(VPATH)}internal/newobj.h +struct.$(OBJEXT): {$(VPATH)}internal/rgengc.h +struct.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +struct.$(OBJEXT): {$(VPATH)}internal/value.h +struct.$(OBJEXT): {$(VPATH)}internal/value_type.h +struct.$(OBJEXT): {$(VPATH)}internal/variable.h +struct.$(OBJEXT): {$(VPATH)}internal/warning_push.h +struct.$(OBJEXT): {$(VPATH)}internal/xmalloc.h struct.$(OBJEXT): {$(VPATH)}method.h struct.$(OBJEXT): {$(VPATH)}missing.h struct.$(OBJEXT): {$(VPATH)}node.h +struct.$(OBJEXT): {$(VPATH)}onigmo.h +struct.$(OBJEXT): {$(VPATH)}oniguruma.h struct.$(OBJEXT): {$(VPATH)}ruby_assert.h struct.$(OBJEXT): {$(VPATH)}ruby_atomic.h struct.$(OBJEXT): {$(VPATH)}st.h @@ -2975,10 +14905,31 @@ struct.$(OBJEXT): {$(VPATH)}thread_native.h struct.$(OBJEXT): {$(VPATH)}transient_heap.h struct.$(OBJEXT): {$(VPATH)}vm_core.h struct.$(OBJEXT): {$(VPATH)}vm_opts.h -symbol.$(OBJEXT): $(hdrdir)/ruby.h symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h +symbol.$(OBJEXT): $(top_srcdir)/internal/class.h +symbol.$(OBJEXT): $(top_srcdir)/internal/compilers.h +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/object.h +symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h +symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +symbol.$(OBJEXT): $(top_srcdir)/internal/string.h +symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h +symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h +symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h symbol.$(OBJEXT): {$(VPATH)}assert.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/assume.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/bool.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/limits.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +symbol.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h symbol.$(OBJEXT): {$(VPATH)}config.h +symbol.$(OBJEXT): {$(VPATH)}debug_counter.h symbol.$(OBJEXT): {$(VPATH)}defines.h symbol.$(OBJEXT): {$(VPATH)}encoding.h symbol.$(OBJEXT): {$(VPATH)}gc.h @@ -2988,6 +14939,154 @@ symbol.$(OBJEXT): {$(VPATH)}id_table.c symbol.$(OBJEXT): {$(VPATH)}id_table.h symbol.$(OBJEXT): {$(VPATH)}intern.h symbol.$(OBJEXT): {$(VPATH)}internal.h +symbol.$(OBJEXT): {$(VPATH)}internal/anyargs.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +symbol.$(OBJEXT): {$(VPATH)}internal/assume.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/const.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/error.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/format.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +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/noreturn.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +symbol.$(OBJEXT): {$(VPATH)}internal/cast.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +symbol.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +symbol.$(OBJEXT): {$(VPATH)}internal/config.h +symbol.$(OBJEXT): {$(VPATH)}internal/constant_p.h +symbol.$(OBJEXT): {$(VPATH)}internal/core.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/robject.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +symbol.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +symbol.$(OBJEXT): {$(VPATH)}internal/ctype.h +symbol.$(OBJEXT): {$(VPATH)}internal/dllexport.h +symbol.$(OBJEXT): {$(VPATH)}internal/dosish.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +symbol.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +symbol.$(OBJEXT): {$(VPATH)}internal/error.h +symbol.$(OBJEXT): {$(VPATH)}internal/eval.h +symbol.$(OBJEXT): {$(VPATH)}internal/event.h +symbol.$(OBJEXT): {$(VPATH)}internal/fl_type.h +symbol.$(OBJEXT): {$(VPATH)}internal/gc.h +symbol.$(OBJEXT): {$(VPATH)}internal/glob.h +symbol.$(OBJEXT): {$(VPATH)}internal/globals.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/extension.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/feature.h +symbol.$(OBJEXT): {$(VPATH)}internal/has/warning.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/array.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/class.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/error.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/file.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/io.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/load.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/object.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/process.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/random.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/range.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/string.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/time.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +symbol.$(OBJEXT): {$(VPATH)}internal/interpreter.h +symbol.$(OBJEXT): {$(VPATH)}internal/iterator.h +symbol.$(OBJEXT): {$(VPATH)}internal/memory.h +symbol.$(OBJEXT): {$(VPATH)}internal/method.h +symbol.$(OBJEXT): {$(VPATH)}internal/module.h +symbol.$(OBJEXT): {$(VPATH)}internal/newobj.h +symbol.$(OBJEXT): {$(VPATH)}internal/rgengc.h +symbol.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +symbol.$(OBJEXT): {$(VPATH)}internal/value.h +symbol.$(OBJEXT): {$(VPATH)}internal/value_type.h +symbol.$(OBJEXT): {$(VPATH)}internal/variable.h +symbol.$(OBJEXT): {$(VPATH)}internal/warning_push.h +symbol.$(OBJEXT): {$(VPATH)}internal/xmalloc.h symbol.$(OBJEXT): {$(VPATH)}missing.h symbol.$(OBJEXT): {$(VPATH)}onigmo.h symbol.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -2998,24 +15097,207 @@ symbol.$(OBJEXT): {$(VPATH)}st.h symbol.$(OBJEXT): {$(VPATH)}subst.h symbol.$(OBJEXT): {$(VPATH)}symbol.c symbol.$(OBJEXT): {$(VPATH)}symbol.h +symbol.$(OBJEXT): {$(VPATH)}vm_debug.h +symbol.$(OBJEXT): {$(VPATH)}vm_sync.h thread.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h thread.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h 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): $(top_srcdir)/internal/array.h +thread.$(OBJEXT): $(top_srcdir)/internal/bits.h +thread.$(OBJEXT): $(top_srcdir)/internal/class.h +thread.$(OBJEXT): $(top_srcdir)/internal/compilers.h +thread.$(OBJEXT): $(top_srcdir)/internal/cont.h +thread.$(OBJEXT): $(top_srcdir)/internal/error.h +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/object.h +thread.$(OBJEXT): $(top_srcdir)/internal/proc.h +thread.$(OBJEXT): $(top_srcdir)/internal/serial.h +thread.$(OBJEXT): $(top_srcdir)/internal/signal.h +thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +thread.$(OBJEXT): $(top_srcdir)/internal/string.h +thread.$(OBJEXT): $(top_srcdir)/internal/thread.h +thread.$(OBJEXT): $(top_srcdir)/internal/time.h +thread.$(OBJEXT): $(top_srcdir)/internal/vm.h +thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h thread.$(OBJEXT): {$(VPATH)}assert.h +thread.$(OBJEXT): {$(VPATH)}atomic.h +thread.$(OBJEXT): {$(VPATH)}backward/2/assume.h +thread.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +thread.$(OBJEXT): {$(VPATH)}backward/2/bool.h +thread.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +thread.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +thread.$(OBJEXT): {$(VPATH)}backward/2/limits.h +thread.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +thread.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +thread.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h thread.$(OBJEXT): {$(VPATH)}config.h +thread.$(OBJEXT): {$(VPATH)}darray.h thread.$(OBJEXT): {$(VPATH)}debug.h thread.$(OBJEXT): {$(VPATH)}debug_counter.h thread.$(OBJEXT): {$(VPATH)}defines.h thread.$(OBJEXT): {$(VPATH)}encoding.h thread.$(OBJEXT): {$(VPATH)}eval_intern.h +thread.$(OBJEXT): {$(VPATH)}fiber/scheduler.h thread.$(OBJEXT): {$(VPATH)}gc.h thread.$(OBJEXT): {$(VPATH)}hrtime.h thread.$(OBJEXT): {$(VPATH)}id.h +thread.$(OBJEXT): {$(VPATH)}id_table.h thread.$(OBJEXT): {$(VPATH)}intern.h thread.$(OBJEXT): {$(VPATH)}internal.h +thread.$(OBJEXT): {$(VPATH)}internal/anyargs.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +thread.$(OBJEXT): {$(VPATH)}internal/assume.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/const.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/error.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/format.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +thread.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +thread.$(OBJEXT): {$(VPATH)}internal/cast.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +thread.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +thread.$(OBJEXT): {$(VPATH)}internal/config.h +thread.$(OBJEXT): {$(VPATH)}internal/constant_p.h +thread.$(OBJEXT): {$(VPATH)}internal/core.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +thread.$(OBJEXT): {$(VPATH)}internal/core/robject.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +thread.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +thread.$(OBJEXT): {$(VPATH)}internal/ctype.h +thread.$(OBJEXT): {$(VPATH)}internal/dllexport.h +thread.$(OBJEXT): {$(VPATH)}internal/dosish.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +thread.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +thread.$(OBJEXT): {$(VPATH)}internal/error.h +thread.$(OBJEXT): {$(VPATH)}internal/eval.h +thread.$(OBJEXT): {$(VPATH)}internal/event.h +thread.$(OBJEXT): {$(VPATH)}internal/fl_type.h +thread.$(OBJEXT): {$(VPATH)}internal/gc.h +thread.$(OBJEXT): {$(VPATH)}internal/glob.h +thread.$(OBJEXT): {$(VPATH)}internal/globals.h +thread.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +thread.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +thread.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +thread.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +thread.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +thread.$(OBJEXT): {$(VPATH)}internal/has/extension.h +thread.$(OBJEXT): {$(VPATH)}internal/has/feature.h +thread.$(OBJEXT): {$(VPATH)}internal/has/warning.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/array.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/class.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/error.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/file.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/io.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/load.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/object.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/process.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/random.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/range.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/string.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/time.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +thread.$(OBJEXT): {$(VPATH)}internal/interpreter.h +thread.$(OBJEXT): {$(VPATH)}internal/iterator.h +thread.$(OBJEXT): {$(VPATH)}internal/memory.h +thread.$(OBJEXT): {$(VPATH)}internal/method.h +thread.$(OBJEXT): {$(VPATH)}internal/module.h +thread.$(OBJEXT): {$(VPATH)}internal/newobj.h +thread.$(OBJEXT): {$(VPATH)}internal/rgengc.h +thread.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +thread.$(OBJEXT): {$(VPATH)}internal/value.h +thread.$(OBJEXT): {$(VPATH)}internal/value_type.h +thread.$(OBJEXT): {$(VPATH)}internal/variable.h +thread.$(OBJEXT): {$(VPATH)}internal/warning_push.h +thread.$(OBJEXT): {$(VPATH)}internal/xmalloc.h thread.$(OBJEXT): {$(VPATH)}io.h thread.$(OBJEXT): {$(VPATH)}iseq.h thread.$(OBJEXT): {$(VPATH)}method.h @@ -3024,6 +15306,8 @@ thread.$(OBJEXT): {$(VPATH)}mjit.h thread.$(OBJEXT): {$(VPATH)}node.h thread.$(OBJEXT): {$(VPATH)}onigmo.h thread.$(OBJEXT): {$(VPATH)}oniguruma.h +thread.$(OBJEXT): {$(VPATH)}ractor.h +thread.$(OBJEXT): {$(VPATH)}ractor_core.h thread.$(OBJEXT): {$(VPATH)}ruby_assert.h thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h thread.$(OBJEXT): {$(VPATH)}st.h @@ -3036,32 +15320,380 @@ thread.$(OBJEXT): {$(VPATH)}thread_native.h thread.$(OBJEXT): {$(VPATH)}thread_sync.c thread.$(OBJEXT): {$(VPATH)}timev.h thread.$(OBJEXT): {$(VPATH)}vm_core.h +thread.$(OBJEXT): {$(VPATH)}vm_debug.h thread.$(OBJEXT): {$(VPATH)}vm_opts.h -time.$(OBJEXT): $(hdrdir)/ruby.h +thread.$(OBJEXT): {$(VPATH)}vm_sync.h +thread.$(OBJEXT): {$(VPATH)}yjit.h time.$(OBJEXT): $(hdrdir)/ruby/ruby.h +time.$(OBJEXT): $(top_srcdir)/internal/array.h +time.$(OBJEXT): $(top_srcdir)/internal/bignum.h +time.$(OBJEXT): $(top_srcdir)/internal/bits.h +time.$(OBJEXT): $(top_srcdir)/internal/compar.h +time.$(OBJEXT): $(top_srcdir)/internal/compilers.h +time.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +time.$(OBJEXT): $(top_srcdir)/internal/gc.h +time.$(OBJEXT): $(top_srcdir)/internal/numeric.h +time.$(OBJEXT): $(top_srcdir)/internal/rational.h +time.$(OBJEXT): $(top_srcdir)/internal/serial.h +time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +time.$(OBJEXT): $(top_srcdir)/internal/string.h +time.$(OBJEXT): $(top_srcdir)/internal/time.h +time.$(OBJEXT): $(top_srcdir)/internal/variable.h +time.$(OBJEXT): $(top_srcdir)/internal/vm.h +time.$(OBJEXT): $(top_srcdir)/internal/warnings.h time.$(OBJEXT): {$(VPATH)}assert.h +time.$(OBJEXT): {$(VPATH)}backward/2/assume.h +time.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +time.$(OBJEXT): {$(VPATH)}backward/2/bool.h +time.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +time.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +time.$(OBJEXT): {$(VPATH)}backward/2/limits.h +time.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +time.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +time.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +time.$(OBJEXT): {$(VPATH)}builtin.h time.$(OBJEXT): {$(VPATH)}config.h +time.$(OBJEXT): {$(VPATH)}constant.h time.$(OBJEXT): {$(VPATH)}defines.h time.$(OBJEXT): {$(VPATH)}encoding.h time.$(OBJEXT): {$(VPATH)}id.h +time.$(OBJEXT): {$(VPATH)}id_table.h time.$(OBJEXT): {$(VPATH)}intern.h time.$(OBJEXT): {$(VPATH)}internal.h +time.$(OBJEXT): {$(VPATH)}internal/anyargs.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +time.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +time.$(OBJEXT): {$(VPATH)}internal/assume.h +time.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +time.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +time.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +time.$(OBJEXT): {$(VPATH)}internal/attr/const.h +time.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +time.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +time.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +time.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +time.$(OBJEXT): {$(VPATH)}internal/attr/error.h +time.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +time.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +time.$(OBJEXT): {$(VPATH)}internal/attr/format.h +time.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +time.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +time.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +time.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +time.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +time.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +time.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +time.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +time.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +time.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +time.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +time.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +time.$(OBJEXT): {$(VPATH)}internal/cast.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +time.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +time.$(OBJEXT): {$(VPATH)}internal/config.h +time.$(OBJEXT): {$(VPATH)}internal/constant_p.h +time.$(OBJEXT): {$(VPATH)}internal/core.h +time.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +time.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +time.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +time.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +time.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +time.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +time.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +time.$(OBJEXT): {$(VPATH)}internal/core/robject.h +time.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +time.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +time.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +time.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +time.$(OBJEXT): {$(VPATH)}internal/ctype.h +time.$(OBJEXT): {$(VPATH)}internal/dllexport.h +time.$(OBJEXT): {$(VPATH)}internal/dosish.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +time.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +time.$(OBJEXT): {$(VPATH)}internal/error.h +time.$(OBJEXT): {$(VPATH)}internal/eval.h +time.$(OBJEXT): {$(VPATH)}internal/event.h +time.$(OBJEXT): {$(VPATH)}internal/fl_type.h +time.$(OBJEXT): {$(VPATH)}internal/gc.h +time.$(OBJEXT): {$(VPATH)}internal/glob.h +time.$(OBJEXT): {$(VPATH)}internal/globals.h +time.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +time.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +time.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +time.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +time.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +time.$(OBJEXT): {$(VPATH)}internal/has/extension.h +time.$(OBJEXT): {$(VPATH)}internal/has/feature.h +time.$(OBJEXT): {$(VPATH)}internal/has/warning.h +time.$(OBJEXT): {$(VPATH)}internal/intern/array.h +time.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +time.$(OBJEXT): {$(VPATH)}internal/intern/class.h +time.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +time.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +time.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +time.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +time.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +time.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +time.$(OBJEXT): {$(VPATH)}internal/intern/error.h +time.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +time.$(OBJEXT): {$(VPATH)}internal/intern/file.h +time.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +time.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +time.$(OBJEXT): {$(VPATH)}internal/intern/io.h +time.$(OBJEXT): {$(VPATH)}internal/intern/load.h +time.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +time.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +time.$(OBJEXT): {$(VPATH)}internal/intern/object.h +time.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +time.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +time.$(OBJEXT): {$(VPATH)}internal/intern/process.h +time.$(OBJEXT): {$(VPATH)}internal/intern/random.h +time.$(OBJEXT): {$(VPATH)}internal/intern/range.h +time.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +time.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +time.$(OBJEXT): {$(VPATH)}internal/intern/string.h +time.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +time.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +time.$(OBJEXT): {$(VPATH)}internal/intern/time.h +time.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +time.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +time.$(OBJEXT): {$(VPATH)}internal/interpreter.h +time.$(OBJEXT): {$(VPATH)}internal/iterator.h +time.$(OBJEXT): {$(VPATH)}internal/memory.h +time.$(OBJEXT): {$(VPATH)}internal/method.h +time.$(OBJEXT): {$(VPATH)}internal/module.h +time.$(OBJEXT): {$(VPATH)}internal/newobj.h +time.$(OBJEXT): {$(VPATH)}internal/rgengc.h +time.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +time.$(OBJEXT): {$(VPATH)}internal/value.h +time.$(OBJEXT): {$(VPATH)}internal/value_type.h +time.$(OBJEXT): {$(VPATH)}internal/variable.h +time.$(OBJEXT): {$(VPATH)}internal/warning_push.h +time.$(OBJEXT): {$(VPATH)}internal/xmalloc.h time.$(OBJEXT): {$(VPATH)}missing.h time.$(OBJEXT): {$(VPATH)}onigmo.h time.$(OBJEXT): {$(VPATH)}oniguruma.h +time.$(OBJEXT): {$(VPATH)}ruby_assert.h time.$(OBJEXT): {$(VPATH)}st.h time.$(OBJEXT): {$(VPATH)}subst.h time.$(OBJEXT): {$(VPATH)}time.c time.$(OBJEXT): {$(VPATH)}timev.h -transcode.$(OBJEXT): $(hdrdir)/ruby.h +time.$(OBJEXT): {$(VPATH)}timev.rbinc transcode.$(OBJEXT): $(hdrdir)/ruby/ruby.h +transcode.$(OBJEXT): $(top_srcdir)/internal/array.h +transcode.$(OBJEXT): $(top_srcdir)/internal/class.h +transcode.$(OBJEXT): $(top_srcdir)/internal/compilers.h +transcode.$(OBJEXT): $(top_srcdir)/internal/gc.h +transcode.$(OBJEXT): $(top_srcdir)/internal/inits.h +transcode.$(OBJEXT): $(top_srcdir)/internal/object.h +transcode.$(OBJEXT): $(top_srcdir)/internal/serial.h +transcode.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +transcode.$(OBJEXT): $(top_srcdir)/internal/string.h +transcode.$(OBJEXT): $(top_srcdir)/internal/transcode.h +transcode.$(OBJEXT): $(top_srcdir)/internal/warnings.h transcode.$(OBJEXT): {$(VPATH)}assert.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/assume.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/bool.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/limits.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +transcode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h transcode.$(OBJEXT): {$(VPATH)}config.h transcode.$(OBJEXT): {$(VPATH)}defines.h transcode.$(OBJEXT): {$(VPATH)}encoding.h transcode.$(OBJEXT): {$(VPATH)}id.h +transcode.$(OBJEXT): {$(VPATH)}id_table.h transcode.$(OBJEXT): {$(VPATH)}intern.h transcode.$(OBJEXT): {$(VPATH)}internal.h +transcode.$(OBJEXT): {$(VPATH)}internal/anyargs.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +transcode.$(OBJEXT): {$(VPATH)}internal/assume.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/const.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/error.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/format.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +transcode.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +transcode.$(OBJEXT): {$(VPATH)}internal/cast.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +transcode.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +transcode.$(OBJEXT): {$(VPATH)}internal/config.h +transcode.$(OBJEXT): {$(VPATH)}internal/constant_p.h +transcode.$(OBJEXT): {$(VPATH)}internal/core.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/robject.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +transcode.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +transcode.$(OBJEXT): {$(VPATH)}internal/ctype.h +transcode.$(OBJEXT): {$(VPATH)}internal/dllexport.h +transcode.$(OBJEXT): {$(VPATH)}internal/dosish.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +transcode.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +transcode.$(OBJEXT): {$(VPATH)}internal/error.h +transcode.$(OBJEXT): {$(VPATH)}internal/eval.h +transcode.$(OBJEXT): {$(VPATH)}internal/event.h +transcode.$(OBJEXT): {$(VPATH)}internal/fl_type.h +transcode.$(OBJEXT): {$(VPATH)}internal/gc.h +transcode.$(OBJEXT): {$(VPATH)}internal/glob.h +transcode.$(OBJEXT): {$(VPATH)}internal/globals.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/extension.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/feature.h +transcode.$(OBJEXT): {$(VPATH)}internal/has/warning.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/array.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/class.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/error.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/file.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/io.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/load.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/object.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/process.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/random.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/range.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/string.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/time.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +transcode.$(OBJEXT): {$(VPATH)}internal/interpreter.h +transcode.$(OBJEXT): {$(VPATH)}internal/iterator.h +transcode.$(OBJEXT): {$(VPATH)}internal/memory.h +transcode.$(OBJEXT): {$(VPATH)}internal/method.h +transcode.$(OBJEXT): {$(VPATH)}internal/module.h +transcode.$(OBJEXT): {$(VPATH)}internal/newobj.h +transcode.$(OBJEXT): {$(VPATH)}internal/rgengc.h +transcode.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +transcode.$(OBJEXT): {$(VPATH)}internal/value.h +transcode.$(OBJEXT): {$(VPATH)}internal/value_type.h +transcode.$(OBJEXT): {$(VPATH)}internal/variable.h +transcode.$(OBJEXT): {$(VPATH)}internal/warning_push.h +transcode.$(OBJEXT): {$(VPATH)}internal/xmalloc.h transcode.$(OBJEXT): {$(VPATH)}missing.h transcode.$(OBJEXT): {$(VPATH)}onigmo.h transcode.$(OBJEXT): {$(VPATH)}oniguruma.h @@ -3069,33 +15701,343 @@ transcode.$(OBJEXT): {$(VPATH)}st.h transcode.$(OBJEXT): {$(VPATH)}subst.h transcode.$(OBJEXT): {$(VPATH)}transcode.c transcode.$(OBJEXT): {$(VPATH)}transcode_data.h -transient_heap.$(OBJEXT): $(hdrdir)/ruby.h transient_heap.$(OBJEXT): $(hdrdir)/ruby/ruby.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/compilers.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/gc.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/hash.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/struct.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/variable.h +transient_heap.$(OBJEXT): $(top_srcdir)/internal/warnings.h transient_heap.$(OBJEXT): {$(VPATH)}assert.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/assume.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/bool.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/limits.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +transient_heap.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h transient_heap.$(OBJEXT): {$(VPATH)}config.h +transient_heap.$(OBJEXT): {$(VPATH)}constant.h transient_heap.$(OBJEXT): {$(VPATH)}debug.h transient_heap.$(OBJEXT): {$(VPATH)}debug_counter.h transient_heap.$(OBJEXT): {$(VPATH)}defines.h transient_heap.$(OBJEXT): {$(VPATH)}gc.h +transient_heap.$(OBJEXT): {$(VPATH)}id_table.h transient_heap.$(OBJEXT): {$(VPATH)}intern.h transient_heap.$(OBJEXT): {$(VPATH)}internal.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/anyargs.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/assume.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/const.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/error.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/format.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/cast.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/config.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/constant_p.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/robject.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/ctype.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/dllexport.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/dosish.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/error.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/eval.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/event.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/fl_type.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/gc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/glob.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/globals.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/extension.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/feature.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/has/warning.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/array.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/class.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/error.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/file.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/io.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/load.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/object.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/process.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/random.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/range.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/re.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/select.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/string.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/time.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/interpreter.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/iterator.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/memory.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/method.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/module.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/newobj.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/rgengc.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/scan_args.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/special_consts.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/static_assert.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/stdalign.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/stdbool.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/symbol.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/value.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/value_type.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/variable.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/warning_push.h +transient_heap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h transient_heap.$(OBJEXT): {$(VPATH)}missing.h -transient_heap.$(OBJEXT): {$(VPATH)}node.h transient_heap.$(OBJEXT): {$(VPATH)}ruby_assert.h transient_heap.$(OBJEXT): {$(VPATH)}st.h transient_heap.$(OBJEXT): {$(VPATH)}subst.h transient_heap.$(OBJEXT): {$(VPATH)}transient_heap.c transient_heap.$(OBJEXT): {$(VPATH)}transient_heap.h transient_heap.$(OBJEXT): {$(VPATH)}vm_debug.h -util.$(OBJEXT): $(hdrdir)/ruby.h +transient_heap.$(OBJEXT): {$(VPATH)}vm_sync.h util.$(OBJEXT): $(hdrdir)/ruby/ruby.h +util.$(OBJEXT): $(top_srcdir)/internal/compilers.h +util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +util.$(OBJEXT): $(top_srcdir)/internal/util.h +util.$(OBJEXT): $(top_srcdir)/internal/warnings.h util.$(OBJEXT): {$(VPATH)}assert.h +util.$(OBJEXT): {$(VPATH)}atomic.h +util.$(OBJEXT): {$(VPATH)}backward/2/assume.h +util.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +util.$(OBJEXT): {$(VPATH)}backward/2/bool.h +util.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +util.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +util.$(OBJEXT): {$(VPATH)}backward/2/limits.h +util.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +util.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +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)}intern.h util.$(OBJEXT): {$(VPATH)}internal.h +util.$(OBJEXT): {$(VPATH)}internal/anyargs.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +util.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +util.$(OBJEXT): {$(VPATH)}internal/assume.h +util.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +util.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +util.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +util.$(OBJEXT): {$(VPATH)}internal/attr/const.h +util.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +util.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +util.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +util.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +util.$(OBJEXT): {$(VPATH)}internal/attr/error.h +util.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +util.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +util.$(OBJEXT): {$(VPATH)}internal/attr/format.h +util.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +util.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +util.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +util.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +util.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +util.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +util.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +util.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +util.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +util.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +util.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +util.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +util.$(OBJEXT): {$(VPATH)}internal/cast.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +util.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +util.$(OBJEXT): {$(VPATH)}internal/config.h +util.$(OBJEXT): {$(VPATH)}internal/constant_p.h +util.$(OBJEXT): {$(VPATH)}internal/core.h +util.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +util.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +util.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +util.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +util.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +util.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +util.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +util.$(OBJEXT): {$(VPATH)}internal/core/robject.h +util.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +util.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +util.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +util.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +util.$(OBJEXT): {$(VPATH)}internal/ctype.h +util.$(OBJEXT): {$(VPATH)}internal/dllexport.h +util.$(OBJEXT): {$(VPATH)}internal/dosish.h +util.$(OBJEXT): {$(VPATH)}internal/error.h +util.$(OBJEXT): {$(VPATH)}internal/eval.h +util.$(OBJEXT): {$(VPATH)}internal/event.h +util.$(OBJEXT): {$(VPATH)}internal/fl_type.h +util.$(OBJEXT): {$(VPATH)}internal/gc.h +util.$(OBJEXT): {$(VPATH)}internal/glob.h +util.$(OBJEXT): {$(VPATH)}internal/globals.h +util.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +util.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +util.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +util.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +util.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +util.$(OBJEXT): {$(VPATH)}internal/has/extension.h +util.$(OBJEXT): {$(VPATH)}internal/has/feature.h +util.$(OBJEXT): {$(VPATH)}internal/has/warning.h +util.$(OBJEXT): {$(VPATH)}internal/intern/array.h +util.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +util.$(OBJEXT): {$(VPATH)}internal/intern/class.h +util.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +util.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +util.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +util.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +util.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +util.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +util.$(OBJEXT): {$(VPATH)}internal/intern/error.h +util.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +util.$(OBJEXT): {$(VPATH)}internal/intern/file.h +util.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +util.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +util.$(OBJEXT): {$(VPATH)}internal/intern/io.h +util.$(OBJEXT): {$(VPATH)}internal/intern/load.h +util.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +util.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +util.$(OBJEXT): {$(VPATH)}internal/intern/object.h +util.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +util.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +util.$(OBJEXT): {$(VPATH)}internal/intern/process.h +util.$(OBJEXT): {$(VPATH)}internal/intern/random.h +util.$(OBJEXT): {$(VPATH)}internal/intern/range.h +util.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +util.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +util.$(OBJEXT): {$(VPATH)}internal/intern/string.h +util.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +util.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +util.$(OBJEXT): {$(VPATH)}internal/intern/time.h +util.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +util.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +util.$(OBJEXT): {$(VPATH)}internal/interpreter.h +util.$(OBJEXT): {$(VPATH)}internal/iterator.h +util.$(OBJEXT): {$(VPATH)}internal/memory.h +util.$(OBJEXT): {$(VPATH)}internal/method.h +util.$(OBJEXT): {$(VPATH)}internal/module.h +util.$(OBJEXT): {$(VPATH)}internal/newobj.h +util.$(OBJEXT): {$(VPATH)}internal/rgengc.h +util.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +util.$(OBJEXT): {$(VPATH)}internal/value.h +util.$(OBJEXT): {$(VPATH)}internal/value_type.h +util.$(OBJEXT): {$(VPATH)}internal/variable.h +util.$(OBJEXT): {$(VPATH)}internal/warning_push.h +util.$(OBJEXT): {$(VPATH)}internal/xmalloc.h util.$(OBJEXT): {$(VPATH)}missing.h +util.$(OBJEXT): {$(VPATH)}ruby_atomic.h util.$(OBJEXT): {$(VPATH)}st.h util.$(OBJEXT): {$(VPATH)}subst.h util.$(OBJEXT): {$(VPATH)}util.c @@ -3104,11 +16046,39 @@ variable.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h 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.h variable.$(OBJEXT): $(hdrdir)/ruby/ruby.h +variable.$(OBJEXT): $(top_srcdir)/internal/array.h +variable.$(OBJEXT): $(top_srcdir)/internal/class.h +variable.$(OBJEXT): $(top_srcdir)/internal/compilers.h +variable.$(OBJEXT): $(top_srcdir)/internal/error.h +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/object.h +variable.$(OBJEXT): $(top_srcdir)/internal/re.h +variable.$(OBJEXT): $(top_srcdir)/internal/serial.h +variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +variable.$(OBJEXT): $(top_srcdir)/internal/string.h +variable.$(OBJEXT): $(top_srcdir)/internal/symbol.h +variable.$(OBJEXT): $(top_srcdir)/internal/thread.h +variable.$(OBJEXT): $(top_srcdir)/internal/variable.h +variable.$(OBJEXT): $(top_srcdir)/internal/vm.h +variable.$(OBJEXT): $(top_srcdir)/internal/warnings.h variable.$(OBJEXT): {$(VPATH)}assert.h +variable.$(OBJEXT): {$(VPATH)}atomic.h +variable.$(OBJEXT): {$(VPATH)}backward/2/assume.h +variable.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +variable.$(OBJEXT): {$(VPATH)}backward/2/bool.h +variable.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +variable.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +variable.$(OBJEXT): {$(VPATH)}backward/2/limits.h +variable.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +variable.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +variable.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h variable.$(OBJEXT): {$(VPATH)}config.h variable.$(OBJEXT): {$(VPATH)}constant.h +variable.$(OBJEXT): {$(VPATH)}darray.h variable.$(OBJEXT): {$(VPATH)}debug_counter.h variable.$(OBJEXT): {$(VPATH)}defines.h variable.$(OBJEXT): {$(VPATH)}encoding.h @@ -3116,11 +16086,161 @@ variable.$(OBJEXT): {$(VPATH)}id.h variable.$(OBJEXT): {$(VPATH)}id_table.h variable.$(OBJEXT): {$(VPATH)}intern.h variable.$(OBJEXT): {$(VPATH)}internal.h +variable.$(OBJEXT): {$(VPATH)}internal/anyargs.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +variable.$(OBJEXT): {$(VPATH)}internal/assume.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/const.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/error.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/format.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +variable.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +variable.$(OBJEXT): {$(VPATH)}internal/cast.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +variable.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +variable.$(OBJEXT): {$(VPATH)}internal/config.h +variable.$(OBJEXT): {$(VPATH)}internal/constant_p.h +variable.$(OBJEXT): {$(VPATH)}internal/core.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +variable.$(OBJEXT): {$(VPATH)}internal/core/robject.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +variable.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +variable.$(OBJEXT): {$(VPATH)}internal/ctype.h +variable.$(OBJEXT): {$(VPATH)}internal/dllexport.h +variable.$(OBJEXT): {$(VPATH)}internal/dosish.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +variable.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +variable.$(OBJEXT): {$(VPATH)}internal/error.h +variable.$(OBJEXT): {$(VPATH)}internal/eval.h +variable.$(OBJEXT): {$(VPATH)}internal/event.h +variable.$(OBJEXT): {$(VPATH)}internal/fl_type.h +variable.$(OBJEXT): {$(VPATH)}internal/gc.h +variable.$(OBJEXT): {$(VPATH)}internal/glob.h +variable.$(OBJEXT): {$(VPATH)}internal/globals.h +variable.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +variable.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +variable.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +variable.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +variable.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +variable.$(OBJEXT): {$(VPATH)}internal/has/extension.h +variable.$(OBJEXT): {$(VPATH)}internal/has/feature.h +variable.$(OBJEXT): {$(VPATH)}internal/has/warning.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/array.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/class.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/error.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/file.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/io.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/load.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/object.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/process.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/random.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/range.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/string.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/time.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +variable.$(OBJEXT): {$(VPATH)}internal/interpreter.h +variable.$(OBJEXT): {$(VPATH)}internal/iterator.h +variable.$(OBJEXT): {$(VPATH)}internal/memory.h +variable.$(OBJEXT): {$(VPATH)}internal/method.h +variable.$(OBJEXT): {$(VPATH)}internal/module.h +variable.$(OBJEXT): {$(VPATH)}internal/newobj.h +variable.$(OBJEXT): {$(VPATH)}internal/rgengc.h +variable.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +variable.$(OBJEXT): {$(VPATH)}internal/value.h +variable.$(OBJEXT): {$(VPATH)}internal/value_type.h +variable.$(OBJEXT): {$(VPATH)}internal/variable.h +variable.$(OBJEXT): {$(VPATH)}internal/warning_push.h +variable.$(OBJEXT): {$(VPATH)}internal/xmalloc.h variable.$(OBJEXT): {$(VPATH)}method.h variable.$(OBJEXT): {$(VPATH)}missing.h variable.$(OBJEXT): {$(VPATH)}node.h variable.$(OBJEXT): {$(VPATH)}onigmo.h variable.$(OBJEXT): {$(VPATH)}oniguruma.h +variable.$(OBJEXT): {$(VPATH)}ractor.h +variable.$(OBJEXT): {$(VPATH)}ractor_core.h variable.$(OBJEXT): {$(VPATH)}ruby_assert.h variable.$(OBJEXT): {$(VPATH)}ruby_atomic.h variable.$(OBJEXT): {$(VPATH)}st.h @@ -3132,7 +16252,9 @@ variable.$(OBJEXT): {$(VPATH)}util.h variable.$(OBJEXT): {$(VPATH)}variable.c variable.$(OBJEXT): {$(VPATH)}variable.h variable.$(OBJEXT): {$(VPATH)}vm_core.h +variable.$(OBJEXT): {$(VPATH)}vm_debug.h variable.$(OBJEXT): {$(VPATH)}vm_opts.h +variable.$(OBJEXT): {$(VPATH)}vm_sync.h version.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h version.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h version.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -3140,15 +16262,173 @@ version.$(OBJEXT): $(CCAN_DIR)/str/str.h version.$(OBJEXT): $(hdrdir)/ruby.h version.$(OBJEXT): $(hdrdir)/ruby/ruby.h version.$(OBJEXT): $(hdrdir)/ruby/version.h +version.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.h +version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +version.$(OBJEXT): $(top_srcdir)/internal/vm.h +version.$(OBJEXT): $(top_srcdir)/internal/warnings.h version.$(OBJEXT): $(top_srcdir)/revision.h version.$(OBJEXT): $(top_srcdir)/version.h version.$(OBJEXT): {$(VPATH)}assert.h +version.$(OBJEXT): {$(VPATH)}atomic.h +version.$(OBJEXT): {$(VPATH)}backward/2/assume.h +version.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +version.$(OBJEXT): {$(VPATH)}backward/2/bool.h +version.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +version.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +version.$(OBJEXT): {$(VPATH)}backward/2/limits.h +version.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +version.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +version.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h version.$(OBJEXT): {$(VPATH)}config.h +version.$(OBJEXT): {$(VPATH)}darray.h version.$(OBJEXT): {$(VPATH)}debug_counter.h version.$(OBJEXT): {$(VPATH)}defines.h version.$(OBJEXT): {$(VPATH)}id.h version.$(OBJEXT): {$(VPATH)}intern.h version.$(OBJEXT): {$(VPATH)}internal.h +version.$(OBJEXT): {$(VPATH)}internal/anyargs.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +version.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +version.$(OBJEXT): {$(VPATH)}internal/assume.h +version.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +version.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +version.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +version.$(OBJEXT): {$(VPATH)}internal/attr/const.h +version.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +version.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +version.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +version.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +version.$(OBJEXT): {$(VPATH)}internal/attr/error.h +version.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +version.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +version.$(OBJEXT): {$(VPATH)}internal/attr/format.h +version.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +version.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +version.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +version.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +version.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +version.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +version.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +version.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +version.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +version.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +version.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +version.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +version.$(OBJEXT): {$(VPATH)}internal/cast.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +version.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +version.$(OBJEXT): {$(VPATH)}internal/config.h +version.$(OBJEXT): {$(VPATH)}internal/constant_p.h +version.$(OBJEXT): {$(VPATH)}internal/core.h +version.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +version.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +version.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +version.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +version.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +version.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +version.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +version.$(OBJEXT): {$(VPATH)}internal/core/robject.h +version.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +version.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +version.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +version.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +version.$(OBJEXT): {$(VPATH)}internal/ctype.h +version.$(OBJEXT): {$(VPATH)}internal/dllexport.h +version.$(OBJEXT): {$(VPATH)}internal/dosish.h +version.$(OBJEXT): {$(VPATH)}internal/error.h +version.$(OBJEXT): {$(VPATH)}internal/eval.h +version.$(OBJEXT): {$(VPATH)}internal/event.h +version.$(OBJEXT): {$(VPATH)}internal/fl_type.h +version.$(OBJEXT): {$(VPATH)}internal/gc.h +version.$(OBJEXT): {$(VPATH)}internal/glob.h +version.$(OBJEXT): {$(VPATH)}internal/globals.h +version.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +version.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +version.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +version.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +version.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +version.$(OBJEXT): {$(VPATH)}internal/has/extension.h +version.$(OBJEXT): {$(VPATH)}internal/has/feature.h +version.$(OBJEXT): {$(VPATH)}internal/has/warning.h +version.$(OBJEXT): {$(VPATH)}internal/intern/array.h +version.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +version.$(OBJEXT): {$(VPATH)}internal/intern/class.h +version.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +version.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +version.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +version.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +version.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +version.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +version.$(OBJEXT): {$(VPATH)}internal/intern/error.h +version.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +version.$(OBJEXT): {$(VPATH)}internal/intern/file.h +version.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +version.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +version.$(OBJEXT): {$(VPATH)}internal/intern/io.h +version.$(OBJEXT): {$(VPATH)}internal/intern/load.h +version.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +version.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +version.$(OBJEXT): {$(VPATH)}internal/intern/object.h +version.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +version.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +version.$(OBJEXT): {$(VPATH)}internal/intern/process.h +version.$(OBJEXT): {$(VPATH)}internal/intern/random.h +version.$(OBJEXT): {$(VPATH)}internal/intern/range.h +version.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +version.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +version.$(OBJEXT): {$(VPATH)}internal/intern/string.h +version.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +version.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +version.$(OBJEXT): {$(VPATH)}internal/intern/time.h +version.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +version.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +version.$(OBJEXT): {$(VPATH)}internal/interpreter.h +version.$(OBJEXT): {$(VPATH)}internal/iterator.h +version.$(OBJEXT): {$(VPATH)}internal/memory.h +version.$(OBJEXT): {$(VPATH)}internal/method.h +version.$(OBJEXT): {$(VPATH)}internal/module.h +version.$(OBJEXT): {$(VPATH)}internal/newobj.h +version.$(OBJEXT): {$(VPATH)}internal/rgengc.h +version.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +version.$(OBJEXT): {$(VPATH)}internal/value.h +version.$(OBJEXT): {$(VPATH)}internal/value_type.h +version.$(OBJEXT): {$(VPATH)}internal/variable.h +version.$(OBJEXT): {$(VPATH)}internal/warning_push.h +version.$(OBJEXT): {$(VPATH)}internal/xmalloc.h version.$(OBJEXT): {$(VPATH)}method.h version.$(OBJEXT): {$(VPATH)}missing.h version.$(OBJEXT): {$(VPATH)}mjit.h @@ -3162,19 +16442,63 @@ version.$(OBJEXT): {$(VPATH)}thread_native.h version.$(OBJEXT): {$(VPATH)}version.c version.$(OBJEXT): {$(VPATH)}vm_core.h version.$(OBJEXT): {$(VPATH)}vm_opts.h +version.$(OBJEXT): {$(VPATH)}yjit.h vm.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h vm.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h 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): $(top_srcdir)/internal/array.h +vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h +vm.$(OBJEXT): $(top_srcdir)/internal/bits.h +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/cont.h +vm.$(OBJEXT): $(top_srcdir)/internal/error.h +vm.$(OBJEXT): $(top_srcdir)/internal/eval.h +vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +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/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/re.h +vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +vm.$(OBJEXT): $(top_srcdir)/internal/serial.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/variable.h +vm.$(OBJEXT): $(top_srcdir)/internal/vm.h +vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h vm.$(OBJEXT): {$(VPATH)}assert.h +vm.$(OBJEXT): {$(VPATH)}atomic.h +vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h +vm.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +vm.$(OBJEXT): {$(VPATH)}backward/2/bool.h +vm.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +vm.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +vm.$(OBJEXT): {$(VPATH)}backward/2/limits.h +vm.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +vm.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +vm.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h vm.$(OBJEXT): {$(VPATH)}builtin.h vm.$(OBJEXT): {$(VPATH)}config.h vm.$(OBJEXT): {$(VPATH)}constant.h +vm.$(OBJEXT): {$(VPATH)}darray.h vm.$(OBJEXT): {$(VPATH)}debug_counter.h vm.$(OBJEXT): {$(VPATH)}defines.h vm.$(OBJEXT): {$(VPATH)}defs/opt_operand.def +vm.$(OBJEXT): {$(VPATH)}encoding.h vm.$(OBJEXT): {$(VPATH)}eval_intern.h vm.$(OBJEXT): {$(VPATH)}gc.h vm.$(OBJEXT): {$(VPATH)}id.h @@ -3184,14 +16508,166 @@ vm.$(OBJEXT): {$(VPATH)}insns.inc vm.$(OBJEXT): {$(VPATH)}insns_info.inc vm.$(OBJEXT): {$(VPATH)}intern.h vm.$(OBJEXT): {$(VPATH)}internal.h +vm.$(OBJEXT): {$(VPATH)}internal/anyargs.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +vm.$(OBJEXT): {$(VPATH)}internal/assume.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/const.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/error.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/format.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +vm.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +vm.$(OBJEXT): {$(VPATH)}internal/cast.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +vm.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +vm.$(OBJEXT): {$(VPATH)}internal/config.h +vm.$(OBJEXT): {$(VPATH)}internal/constant_p.h +vm.$(OBJEXT): {$(VPATH)}internal/core.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +vm.$(OBJEXT): {$(VPATH)}internal/core/robject.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +vm.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +vm.$(OBJEXT): {$(VPATH)}internal/ctype.h +vm.$(OBJEXT): {$(VPATH)}internal/dllexport.h +vm.$(OBJEXT): {$(VPATH)}internal/dosish.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +vm.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +vm.$(OBJEXT): {$(VPATH)}internal/error.h +vm.$(OBJEXT): {$(VPATH)}internal/eval.h +vm.$(OBJEXT): {$(VPATH)}internal/event.h +vm.$(OBJEXT): {$(VPATH)}internal/fl_type.h +vm.$(OBJEXT): {$(VPATH)}internal/gc.h +vm.$(OBJEXT): {$(VPATH)}internal/glob.h +vm.$(OBJEXT): {$(VPATH)}internal/globals.h +vm.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +vm.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +vm.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +vm.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +vm.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +vm.$(OBJEXT): {$(VPATH)}internal/has/extension.h +vm.$(OBJEXT): {$(VPATH)}internal/has/feature.h +vm.$(OBJEXT): {$(VPATH)}internal/has/warning.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/array.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/class.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/error.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/file.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/io.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/load.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/object.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/process.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/random.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/range.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/string.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/time.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +vm.$(OBJEXT): {$(VPATH)}internal/interpreter.h +vm.$(OBJEXT): {$(VPATH)}internal/iterator.h +vm.$(OBJEXT): {$(VPATH)}internal/memory.h +vm.$(OBJEXT): {$(VPATH)}internal/method.h +vm.$(OBJEXT): {$(VPATH)}internal/module.h +vm.$(OBJEXT): {$(VPATH)}internal/newobj.h +vm.$(OBJEXT): {$(VPATH)}internal/rgengc.h +vm.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +vm.$(OBJEXT): {$(VPATH)}internal/value.h +vm.$(OBJEXT): {$(VPATH)}internal/value_type.h +vm.$(OBJEXT): {$(VPATH)}internal/variable.h +vm.$(OBJEXT): {$(VPATH)}internal/warning_push.h +vm.$(OBJEXT): {$(VPATH)}internal/xmalloc.h vm.$(OBJEXT): {$(VPATH)}iseq.h vm.$(OBJEXT): {$(VPATH)}method.h vm.$(OBJEXT): {$(VPATH)}missing.h vm.$(OBJEXT): {$(VPATH)}mjit.h vm.$(OBJEXT): {$(VPATH)}node.h +vm.$(OBJEXT): {$(VPATH)}onigmo.h +vm.$(OBJEXT): {$(VPATH)}oniguruma.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)}ruby_assert.h vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm.$(OBJEXT): {$(VPATH)}st.h @@ -3204,6 +16680,7 @@ vm.$(OBJEXT): {$(VPATH)}vm.h vm.$(OBJEXT): {$(VPATH)}vm.inc vm.$(OBJEXT): {$(VPATH)}vm_args.c vm.$(OBJEXT): {$(VPATH)}vm_call_iseq_optimized.inc +vm.$(OBJEXT): {$(VPATH)}vm_callinfo.h vm.$(OBJEXT): {$(VPATH)}vm_core.h vm.$(OBJEXT): {$(VPATH)}vm_debug.h vm.$(OBJEXT): {$(VPATH)}vm_eval.c @@ -3213,15 +16690,37 @@ vm.$(OBJEXT): {$(VPATH)}vm_insnhelper.c vm.$(OBJEXT): {$(VPATH)}vm_insnhelper.h vm.$(OBJEXT): {$(VPATH)}vm_method.c vm.$(OBJEXT): {$(VPATH)}vm_opts.h +vm.$(OBJEXT): {$(VPATH)}vm_sync.h vm.$(OBJEXT): {$(VPATH)}vmtc.inc +vm.$(OBJEXT): {$(VPATH)}yjit.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.h vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h +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/serial.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h +vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/bool.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/limits.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h vm_backtrace.$(OBJEXT): {$(VPATH)}config.h +vm_backtrace.$(OBJEXT): {$(VPATH)}darray.h vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h @@ -3229,6 +16728,154 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h vm_backtrace.$(OBJEXT): {$(VPATH)}id.h vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/anyargs.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/assume.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/const.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/error.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/format.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/cast.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/config.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/constant_p.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/robject.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/ctype.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dllexport.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dosish.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/error.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/eval.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/event.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/fl_type.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/gc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/glob.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/globals.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/extension.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/feature.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/warning.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/array.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/class.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/error.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/file.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/io.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/load.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/object.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/process.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/random.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/range.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/string.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/time.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/interpreter.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/iterator.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/memory.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/method.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/module.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/newobj.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/rgengc.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value_type.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/variable.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/warning_push.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/xmalloc.h vm_backtrace.$(OBJEXT): {$(VPATH)}iseq.h vm_backtrace.$(OBJEXT): {$(VPATH)}method.h vm_backtrace.$(OBJEXT): {$(VPATH)}missing.h @@ -3248,21 +16895,183 @@ 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 vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h -vm_dump.$(OBJEXT): $(hdrdir)/ruby.h vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.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): {$(VPATH)}addr2line.h vm_dump.$(OBJEXT): {$(VPATH)}assert.h +vm_dump.$(OBJEXT): {$(VPATH)}atomic.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/assume.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/bool.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/limits.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h vm_dump.$(OBJEXT): {$(VPATH)}config.h +vm_dump.$(OBJEXT): {$(VPATH)}constant.h +vm_dump.$(OBJEXT): {$(VPATH)}darray.h vm_dump.$(OBJEXT): {$(VPATH)}defines.h vm_dump.$(OBJEXT): {$(VPATH)}gc.h vm_dump.$(OBJEXT): {$(VPATH)}id.h +vm_dump.$(OBJEXT): {$(VPATH)}id_table.h vm_dump.$(OBJEXT): {$(VPATH)}intern.h vm_dump.$(OBJEXT): {$(VPATH)}internal.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/assume.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/const.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/error.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/format.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/cast.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/config.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/constant_p.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/robject.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/error.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/eval.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/event.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/fl_type.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/gc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/glob.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/globals.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/extension.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/feature.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/has/warning.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/array.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/class.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/error.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/file.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/io.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/load.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/object.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/process.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/random.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/range.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/time.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/interpreter.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/iterator.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/memory.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/method.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/module.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/newobj.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/rgengc.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/value.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/variable.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/warning_push.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/xmalloc.h vm_dump.$(OBJEXT): {$(VPATH)}iseq.h vm_dump.$(OBJEXT): {$(VPATH)}method.h vm_dump.$(OBJEXT): {$(VPATH)}missing.h vm_dump.$(OBJEXT): {$(VPATH)}node.h vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c +vm_dump.$(OBJEXT): {$(VPATH)}ractor.h +vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm_dump.$(OBJEXT): {$(VPATH)}st.h @@ -3270,29 +17079,391 @@ vm_dump.$(OBJEXT): {$(VPATH)}subst.h vm_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h vm_dump.$(OBJEXT): {$(VPATH)}thread_native.h vm_dump.$(OBJEXT): {$(VPATH)}vm_core.h +vm_dump.$(OBJEXT): {$(VPATH)}vm_debug.h vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c vm_dump.$(OBJEXT): {$(VPATH)}vm_opts.h +vm_sync.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +vm_sync.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +vm_sync.$(OBJEXT): $(CCAN_DIR)/list/list.h +vm_sync.$(OBJEXT): $(CCAN_DIR)/str/str.h +vm_sync.$(OBJEXT): $(hdrdir)/ruby/ruby.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/array.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/serial.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/vm.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_sync.$(OBJEXT): {$(VPATH)}assert.h +vm_sync.$(OBJEXT): {$(VPATH)}atomic.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/assume.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/bool.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/limits.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +vm_sync.$(OBJEXT): {$(VPATH)}config.h +vm_sync.$(OBJEXT): {$(VPATH)}darray.h +vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h +vm_sync.$(OBJEXT): {$(VPATH)}defines.h +vm_sync.$(OBJEXT): {$(VPATH)}gc.h +vm_sync.$(OBJEXT): {$(VPATH)}id.h +vm_sync.$(OBJEXT): {$(VPATH)}id_table.h +vm_sync.$(OBJEXT): {$(VPATH)}intern.h +vm_sync.$(OBJEXT): {$(VPATH)}internal.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/anyargs.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/assume.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/const.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/error.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/format.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/cast.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/config.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/constant_p.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/robject.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/ctype.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/dllexport.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/dosish.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/error.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/eval.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/event.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/fl_type.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/gc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/glob.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/globals.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/extension.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/feature.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/has/warning.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/array.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/class.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/error.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/file.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/io.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/load.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/object.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/process.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/random.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/range.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/string.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/time.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/interpreter.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/iterator.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/memory.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/method.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/module.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/newobj.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/rgengc.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/value.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/value_type.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/variable.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/warning_push.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +vm_sync.$(OBJEXT): {$(VPATH)}method.h +vm_sync.$(OBJEXT): {$(VPATH)}missing.h +vm_sync.$(OBJEXT): {$(VPATH)}node.h +vm_sync.$(OBJEXT): {$(VPATH)}ractor.h +vm_sync.$(OBJEXT): {$(VPATH)}ractor_core.h +vm_sync.$(OBJEXT): {$(VPATH)}ruby_assert.h +vm_sync.$(OBJEXT): {$(VPATH)}ruby_atomic.h +vm_sync.$(OBJEXT): {$(VPATH)}st.h +vm_sync.$(OBJEXT): {$(VPATH)}subst.h +vm_sync.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +vm_sync.$(OBJEXT): {$(VPATH)}thread_native.h +vm_sync.$(OBJEXT): {$(VPATH)}vm_core.h +vm_sync.$(OBJEXT): {$(VPATH)}vm_debug.h +vm_sync.$(OBJEXT): {$(VPATH)}vm_opts.h +vm_sync.$(OBJEXT): {$(VPATH)}vm_sync.c +vm_sync.$(OBJEXT): {$(VPATH)}vm_sync.h vm_trace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h vm_trace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h vm_trace.$(OBJEXT): $(CCAN_DIR)/list/list.h vm_trace.$(OBJEXT): $(CCAN_DIR)/str/str.h 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/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/serial.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h vm_trace.$(OBJEXT): {$(VPATH)}assert.h +vm_trace.$(OBJEXT): {$(VPATH)}atomic.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/bool.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/limits.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h vm_trace.$(OBJEXT): {$(VPATH)}builtin.h vm_trace.$(OBJEXT): {$(VPATH)}config.h +vm_trace.$(OBJEXT): {$(VPATH)}darray.h vm_trace.$(OBJEXT): {$(VPATH)}debug.h vm_trace.$(OBJEXT): {$(VPATH)}debug_counter.h vm_trace.$(OBJEXT): {$(VPATH)}defines.h +vm_trace.$(OBJEXT): {$(VPATH)}encoding.h vm_trace.$(OBJEXT): {$(VPATH)}eval_intern.h vm_trace.$(OBJEXT): {$(VPATH)}id.h vm_trace.$(OBJEXT): {$(VPATH)}intern.h vm_trace.$(OBJEXT): {$(VPATH)}internal.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/anyargs.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/assume.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/const.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/error.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/format.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/cast.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/config.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/constant_p.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/robject.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/ctype.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/dllexport.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/dosish.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/error.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/eval.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/event.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/fl_type.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/gc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/glob.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/globals.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/extension.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/feature.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/has/warning.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/array.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/class.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/error.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/file.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/io.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/load.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/object.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/process.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/random.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/range.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/string.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/time.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/interpreter.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/iterator.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/memory.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/method.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/module.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/newobj.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/rgengc.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/value.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/value_type.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/variable.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/warning_push.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/xmalloc.h vm_trace.$(OBJEXT): {$(VPATH)}iseq.h vm_trace.$(OBJEXT): {$(VPATH)}method.h vm_trace.$(OBJEXT): {$(VPATH)}missing.h vm_trace.$(OBJEXT): {$(VPATH)}mjit.h vm_trace.$(OBJEXT): {$(VPATH)}node.h +vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h +vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_trace.$(OBJEXT): {$(VPATH)}ractor.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm_trace.$(OBJEXT): {$(VPATH)}st.h @@ -3303,4 +17474,234 @@ vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c +vm_trace.$(OBJEXT): {$(VPATH)}yjit.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 +yjit.$(OBJEXT): $(CCAN_DIR)/str/str.h +yjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +yjit.$(OBJEXT): $(top_srcdir)/internal/array.h +yjit.$(OBJEXT): $(top_srcdir)/internal/class.h +yjit.$(OBJEXT): $(top_srcdir)/internal/compile.h +yjit.$(OBJEXT): $(top_srcdir)/internal/compilers.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/object.h +yjit.$(OBJEXT): $(top_srcdir)/internal/re.h +yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h +yjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +yjit.$(OBJEXT): $(top_srcdir)/internal/string.h +yjit.$(OBJEXT): $(top_srcdir)/internal/struct.h +yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h +yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h +yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +yjit.$(OBJEXT): {$(VPATH)}assert.h +yjit.$(OBJEXT): {$(VPATH)}atomic.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +yjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +yjit.$(OBJEXT): {$(VPATH)}builtin.h +yjit.$(OBJEXT): {$(VPATH)}config.h +yjit.$(OBJEXT): {$(VPATH)}constant.h +yjit.$(OBJEXT): {$(VPATH)}darray.h +yjit.$(OBJEXT): {$(VPATH)}debug_counter.h +yjit.$(OBJEXT): {$(VPATH)}defines.h +yjit.$(OBJEXT): {$(VPATH)}encoding.h +yjit.$(OBJEXT): {$(VPATH)}gc.h +yjit.$(OBJEXT): {$(VPATH)}id.h +yjit.$(OBJEXT): {$(VPATH)}id_table.h +yjit.$(OBJEXT): {$(VPATH)}insns.def +yjit.$(OBJEXT): {$(VPATH)}insns.inc +yjit.$(OBJEXT): {$(VPATH)}insns_info.inc +yjit.$(OBJEXT): {$(VPATH)}intern.h +yjit.$(OBJEXT): {$(VPATH)}internal.h +yjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +yjit.$(OBJEXT): {$(VPATH)}internal/assume.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +yjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +yjit.$(OBJEXT): {$(VPATH)}internal/cast.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +yjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +yjit.$(OBJEXT): {$(VPATH)}internal/config.h +yjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +yjit.$(OBJEXT): {$(VPATH)}internal/core.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +yjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +yjit.$(OBJEXT): {$(VPATH)}internal/ctype.h +yjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +yjit.$(OBJEXT): {$(VPATH)}internal/dosish.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +yjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +yjit.$(OBJEXT): {$(VPATH)}internal/error.h +yjit.$(OBJEXT): {$(VPATH)}internal/eval.h +yjit.$(OBJEXT): {$(VPATH)}internal/event.h +yjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +yjit.$(OBJEXT): {$(VPATH)}internal/gc.h +yjit.$(OBJEXT): {$(VPATH)}internal/glob.h +yjit.$(OBJEXT): {$(VPATH)}internal/globals.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +yjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +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/signal.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +yjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +yjit.$(OBJEXT): {$(VPATH)}internal/iterator.h +yjit.$(OBJEXT): {$(VPATH)}internal/memory.h +yjit.$(OBJEXT): {$(VPATH)}internal/method.h +yjit.$(OBJEXT): {$(VPATH)}internal/module.h +yjit.$(OBJEXT): {$(VPATH)}internal/newobj.h +yjit.$(OBJEXT): {$(VPATH)}internal/rgengc.h +yjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +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/symbol.h +yjit.$(OBJEXT): {$(VPATH)}internal/value.h +yjit.$(OBJEXT): {$(VPATH)}internal/value_type.h +yjit.$(OBJEXT): {$(VPATH)}internal/variable.h +yjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +yjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +yjit.$(OBJEXT): {$(VPATH)}iseq.h +yjit.$(OBJEXT): {$(VPATH)}method.h +yjit.$(OBJEXT): {$(VPATH)}missing.h +yjit.$(OBJEXT): {$(VPATH)}node.h +yjit.$(OBJEXT): {$(VPATH)}onigmo.h +yjit.$(OBJEXT): {$(VPATH)}oniguruma.h +yjit.$(OBJEXT): {$(VPATH)}probes.dmyh +yjit.$(OBJEXT): {$(VPATH)}probes.h +yjit.$(OBJEXT): {$(VPATH)}probes_helper.h +yjit.$(OBJEXT): {$(VPATH)}ruby_assert.h +yjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h +yjit.$(OBJEXT): {$(VPATH)}st.h +yjit.$(OBJEXT): {$(VPATH)}subst.h +yjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +yjit.$(OBJEXT): {$(VPATH)}thread_native.h +yjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h +yjit.$(OBJEXT): {$(VPATH)}vm_core.h +yjit.$(OBJEXT): {$(VPATH)}vm_debug.h +yjit.$(OBJEXT): {$(VPATH)}vm_opts.h +yjit.$(OBJEXT): {$(VPATH)}vm_sync.h +yjit.$(OBJEXT): {$(VPATH)}yjit.c +yjit.$(OBJEXT): {$(VPATH)}yjit.h +yjit.$(OBJEXT): {$(VPATH)}yjit.rb +yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc +yjit.$(OBJEXT): {$(VPATH)}yjit_asm.c +yjit.$(OBJEXT): {$(VPATH)}yjit_asm.h +yjit.$(OBJEXT): {$(VPATH)}yjit_codegen.c +yjit.$(OBJEXT): {$(VPATH)}yjit_codegen.h +yjit.$(OBJEXT): {$(VPATH)}yjit_core.c +yjit.$(OBJEXT): {$(VPATH)}yjit_core.h +yjit.$(OBJEXT): {$(VPATH)}yjit_iface.c +yjit.$(OBJEXT): {$(VPATH)}yjit_iface.h +yjit.$(OBJEXT): {$(VPATH)}yjit_utils.c # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/compar.c b/ruby/compar.c index 94072c9fc..e9d1ac41f 100644 --- a/ruby/compar.c +++ b/ruby/compar.c @@ -9,9 +9,12 @@ **********************************************************************/ -#include "ruby/ruby.h" #include "id.h" #include "internal.h" +#include "internal/compar.h" +#include "internal/error.h" +#include "internal/vm.h" +#include "ruby/ruby.h" VALUE rb_mComparable; @@ -81,8 +84,7 @@ cmp_equal(VALUE x, VALUE y) c = rb_exec_recursive_paired_outer(cmp_eq_recursive, x, y, y); if (NIL_P(c)) return Qfalse; - if (rb_cmpint(c, x, y) == 0) return Qtrue; - return Qfalse; + return RBOOL(rb_cmpint(c, x, y) == 0); } static int @@ -102,8 +104,7 @@ cmpint(VALUE x, VALUE y) static VALUE cmp_gt(VALUE x, VALUE y) { - if (cmpint(x, y) > 0) return Qtrue; - return Qfalse; + return RBOOL(cmpint(x, y) > 0); } /* @@ -117,8 +118,7 @@ cmp_gt(VALUE x, VALUE y) static VALUE cmp_ge(VALUE x, VALUE y) { - if (cmpint(x, y) >= 0) return Qtrue; - return Qfalse; + return RBOOL(cmpint(x, y) >= 0); } /* @@ -132,8 +132,7 @@ cmp_ge(VALUE x, VALUE y) static VALUE cmp_lt(VALUE x, VALUE y) { - if (cmpint(x, y) < 0) return Qtrue; - return Qfalse; + return RBOOL(cmpint(x, y) < 0); } /* @@ -147,8 +146,7 @@ cmp_lt(VALUE x, VALUE y) static VALUE cmp_le(VALUE x, VALUE y) { - if (cmpint(x, y) <= 0) return Qtrue; - return Qfalse; + return RBOOL(cmpint(x, y) <= 0); } /* @@ -230,11 +228,9 @@ cmp_clamp(int argc, VALUE *argv, VALUE x) } if (!NIL_P(max)) { if (excl) rb_raise(rb_eArgError, "cannot clamp with an exclusive range"); - if (!NIL_P(min) && cmpint(min, max) > 0) goto arg_error; } } - else if (cmpint(min, max) > 0) { - arg_error: + if (!NIL_P(min) && !NIL_P(max) && cmpint(min, max) > 0) { rb_raise(rb_eArgError, "min argument must be smaller than max argument"); } @@ -288,14 +284,27 @@ cmp_clamp(int argc, VALUE *argv, VALUE x) * s4.between?(s3, s5) #=> true * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV] * + * == What's Here + * + * \Module \Comparable provides these methods, all of which use method <=>: + * + * - {<}[#method-i-3C]:: Returns whether +self+ is less than the given object. + * - {<=}[#method-i-3C-3D]:: Returns whether +self+ is less than or equal to + * the given object. + * - {==}[#method-i-3D-3D]:: Returns whether +self+ is equal to the given object. + * - {>}[#method-i-3E]:: Returns whether +self+ is greater than or equal to + * the given object. + * - {>=}[#method-i-3E-3D]:: Returns whether +self+ is greater than the given object. + * - #between? Returns +true+ if +self+ is between two given objects. + * - #clamp:: For given objects +min+ and +max+, or range (min..max), returns: + * - +min+ if (self <=> min) < 0. + * - +max+ if (self <=> max) > 0. + * - +self+ otherwise. */ void Init_Comparable(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - rb_mComparable = rb_define_module("Comparable"); rb_define_method(rb_mComparable, "==", cmp_equal, 1); rb_define_method(rb_mComparable, ">", cmp_gt, 1); diff --git a/ruby/compile.c b/ruby/compile.c index 7043ba9a7..83389947c 100644 --- a/ruby/compile.c +++ b/ruby/compile.c @@ -9,25 +9,40 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/re.h" -#include "ruby/util.h" -#include "internal.h" -#include "encindex.h" +#include "ruby/internal/config.h" #include +#ifdef HAVE_DLADDR +# include +#endif + +#include "encindex.h" +#include "gc.h" +#include "id_table.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compile.h" +#include "internal/complex.h" +#include "internal/encoding.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/rational.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "iseq.h" +#include "ruby/re.h" +#include "ruby/util.h" #include "vm_core.h" +#include "vm_callinfo.h" #include "vm_debug.h" + #include "builtin.h" -#include "iseq.h" #include "insns.inc" #include "insns_info.inc" -#include "id_table.h" -#include "gc.h" - -#ifdef HAVE_DLADDR -# include -#endif #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 @@ -79,6 +94,7 @@ typedef struct iseq_insn_data { VALUE *operands; struct { int line_no; + int node_id; rb_event_flag_t events; } insn_info; } INSN; @@ -176,6 +192,7 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO}; #endif #if CPDEBUG > 1 || CPDEBUG < 0 +#undef printf #define printf ruby_debug_printf #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v)) @@ -201,112 +218,77 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO}; APPEND_LIST((seq1), (seq2)) /* add an instruction */ -#define ADD_INSN(seq, line, insn) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) +#define ADD_INSN(seq, line_node, insn) \ + ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) /* insert an instruction before next */ -#define INSERT_BEFORE_INSN(next, line, insn) \ - ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) +#define INSERT_BEFORE_INSN(next, line_node, insn) \ + ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) /* insert an instruction after prev */ -#define INSERT_AFTER_INSN(prev, line, insn) \ - ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) +#define INSERT_AFTER_INSN(prev, line_node, insn) \ + ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) /* add an instruction with some operands (1, 2, 3, 5) */ -#define ADD_INSN1(seq, line, insn, op1) \ +#define ADD_INSN1(seq, line_node, insn, op1) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, (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, insn, op1) \ +#define INSERT_BEFORE_INSN1(next, line_node, insn, op1) \ ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \ - new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1))) /* insert an instruction with some operands (1, 2, 3, 5) after prev */ -#define INSERT_AFTER_INSN1(prev, line, insn, op1) \ +#define INSERT_AFTER_INSN1(prev, line_node, insn, op1) \ ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \ - new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1))) #define LABEL_REF(label) ((label)->refcnt++) /* add an instruction with label operand (alias of ADD_INSN1) */ -#define ADD_INSNL(seq, line, insn, label) (ADD_INSN1(seq, line, insn, label), LABEL_REF(label)) +#define ADD_INSNL(seq, line_node, insn, label) (ADD_INSN1(seq, line_node, insn, label), LABEL_REF(label)) -#define ADD_INSN2(seq, line, insn, op1, op2) \ +#define ADD_INSN2(seq, line_node, insn, op1, op2) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) + new_insn_body(iseq, (line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) -#define ADD_INSN3(seq, line, insn, op1, op2, op3) \ +#define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) + new_insn_body(iseq, (line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) /* Specific Insn factory */ -#define ADD_SEND(seq, line, id, argc) \ - ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL) +#define ADD_SEND(seq, line_node, id, argc) \ + ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL) -#define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \ - ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL) +#define ADD_SEND_WITH_FLAG(seq, line_node, id, argc, flag) \ + ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)(flag), NULL) -#define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \ - ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL) +#define ADD_SEND_WITH_BLOCK(seq, line_node, id, argc, block) \ + ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(0), NULL) -#define ADD_CALL_RECEIVER(seq, line) \ - ADD_INSN((seq), (line), putself) +#define ADD_CALL_RECEIVER(seq, line_node) \ + ADD_INSN((seq), (line_node), putself) -#define ADD_CALL(seq, line, id, argc) \ - ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL) +#define ADD_CALL(seq, line_node, id, argc) \ + ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL) -#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ - ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL) +#define ADD_CALL_WITH_BLOCK(seq, line_node, id, argc, block) \ + ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL) -#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) +#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))) #define ADD_TRACE(seq, event) \ ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0)) #define ADD_TRACE_WITH_DATA(seq, event, data) \ ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data))) +static void iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level); +static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level); -#define DECL_BRANCH_BASE(branches, first_line, first_column, last_line, last_column, type) \ - do { \ - if (ISEQ_COVERAGE(iseq) && \ - ISEQ_BRANCH_COVERAGE(iseq) && \ - (first_line) > 0) { \ - VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0); \ - branches = rb_ary_tmp_new(5); \ - rb_ary_push(structure, branches); \ - rb_ary_push(branches, ID2SYM(rb_intern(type))); \ - rb_ary_push(branches, INT2FIX(first_line)); \ - rb_ary_push(branches, INT2FIX(first_column)); \ - rb_ary_push(branches, INT2FIX(last_line)); \ - rb_ary_push(branches, INT2FIX(last_column)); \ - } \ - } while (0) -#define ADD_TRACE_BRANCH_COVERAGE(seq, first_line, first_column, last_line, last_column, type, branches) \ - do { \ - if (ISEQ_COVERAGE(iseq) && \ - ISEQ_BRANCH_COVERAGE(iseq) && \ - (first_line) > 0) { \ - VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); \ - long counter_idx = RARRAY_LEN(counters); \ - rb_ary_push(counters, INT2FIX(0)); \ - rb_ary_push(branches, ID2SYM(rb_intern(type))); \ - rb_ary_push(branches, INT2FIX(first_line)); \ - rb_ary_push(branches, INT2FIX(first_column)); \ - rb_ary_push(branches, INT2FIX(last_line)); \ - rb_ary_push(branches, INT2FIX(last_column)); \ - rb_ary_push(branches, INT2FIX(counter_idx)); \ - ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx); \ - ADD_INSN(seq, last_line, nop); \ - } \ - } while (0) - -static void iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level); -static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level); - -#define ADD_GETLOCAL(seq, line, idx, level) iseq_add_getlocal(iseq, (seq), (line), (idx), (level)) -#define ADD_SETLOCAL(seq, line, idx, level) iseq_add_setlocal(iseq, (seq), (line), (idx), (level)) +#define ADD_GETLOCAL(seq, line_node, idx, level) iseq_add_getlocal(iseq, (seq), (line_node), (idx), (level)) +#define ADD_SETLOCAL(seq, line_node, idx, level) iseq_add_setlocal(iseq, (seq), (line_node), (idx), (level)) /* add label */ #define ADD_LABEL(seq, label) \ @@ -315,8 +297,8 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, #define APPEND_LABEL(seq, before, label) \ APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label)) -#define ADD_ADJUST(seq, line, label) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line))) +#define ADD_ADJUST(seq, line_node, label) \ + ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), nd_line(line_node))) #define ADD_ADJUST_RESTORE(seq, label) \ ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1)) @@ -352,7 +334,7 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, #define COMPILE_RECV(anchor, desc, node) \ (private_recv_p(node) ? \ - (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \ + (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \ COMPILE(anchor, desc, node->nd_recv) ? 0 : -1) #define OPERAND_AT(insn, idx) \ @@ -371,9 +353,9 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, /* error */ #if CPDEBUG > 0 -NORETURN(static void append_compile_error(const rb_iseq_t *iseq, int line, const char *fmt, ...)); +RBIMPL_ATTR_NORETURN() #endif - +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) static void append_compile_error(const rb_iseq_t *iseq, int line, const char *fmt, ...) { @@ -488,7 +470,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, int line_no, enum ruby_vminsn_type insn_id, int argc, ...); +static INSN *new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, 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); @@ -500,7 +482,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 ID *tbl); +static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl); 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); @@ -510,6 +492,7 @@ 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_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped); /* * To make Array to LinkedList, use link_anchor @@ -551,6 +534,8 @@ static void verify_call_cache(rb_iseq_t *iseq) { #if CPDEBUG + // fprintf(stderr, "ci_size:%d\t", iseq->body->ci_size); rp(iseq); + VALUE *original = rb_iseq_original_iseq(iseq); size_t i = 0; while (i < iseq->body->iseq_size) { @@ -559,16 +544,27 @@ verify_call_cache(rb_iseq_t *iseq) for (int j=0; types[j]; j++) { if (types[j] == TS_CALLDATA) { - struct rb_call_cache cc; struct rb_call_data *cd = (struct rb_call_data *)original[i+j+1]; - MEMZERO(&cc, cc, 1); - if (memcmp(&cc, &cd->cc, sizeof(cc))) { - rb_bug("call cache not zero for fresh iseq"); + const struct rb_callinfo *ci = cd->ci; + const struct rb_callcache *cc = cd->cc; + if (cc != vm_cc_empty()) { + vm_ci_dump(ci); + rb_bug("call cache is not initialized by vm_cc_empty()"); } } } i += insn_len(insn); } + + for (unsigned int i=0; ibody->ci_size; i++) { + struct rb_call_data *cd = &iseq->body->call_data[i]; + const struct rb_callinfo *ci = cd->ci; + const struct rb_callcache *cc = cd->cc; + if (cc != NULL && cc != vm_cc_empty()) { + vm_ci_dump(ci); + rb_bug("call cache is not initialized by vm_cc_empty()"); + } + } #endif } @@ -602,6 +598,107 @@ APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LI #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem)) #endif +static int +branch_coverage_valid_p(rb_iseq_t *iseq, int first_line) +{ + if (!ISEQ_COVERAGE(iseq)) return 0; + if (!ISEQ_BRANCH_COVERAGE(iseq)) return 0; + if (first_line <= 0) return 0; + return 1; +} + +static VALUE +decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type) +{ + 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 Qundef; + + /* + * if !structure[node] + * structure[node] = [type, first_lineno, first_column, last_lineno, last_column, branches = {}] + * else + * branches = structure[node][5] + * end + */ + + 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_tmp_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)); + branches = rb_hash_new(); + rb_obj_hide(branches); + rb_ary_push(branch_base, branches); + } + else { + branches = RARRAY_AREF(branch_base, 5); + } + + return branches; +} + +static NODE +generate_dummy_line_node(int lineno, int node_id) +{ + NODE dummy = { 0 }; + nd_set_line(&dummy, lineno); + nd_set_node_id(&dummy, node_id); + return dummy; +} + +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) +{ + 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 !branches[branch_id] + * branches[branch_id] = [type, first_lineno, first_column, last_lineno, last_column, counter_idx] + * else + * counter_idx= branches[branch_id][5] + * end + */ + + VALUE key = INT2FIX(branch_id); + VALUE branch = rb_hash_aref(branches, key); + long counter_idx; + + if (NIL_P(branch)) { + branch = rb_ary_tmp_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)); + VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); + counter_idx = RARRAY_LEN(counters); + rb_ary_push(branch, LONG2FIX(counter_idx)); + rb_ary_push(counters, INT2FIX(0)); + } + else { + counter_idx = FIX2LONG(RARRAY_AREF(branch, 5)); + } + + 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); +} + #define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line) static int @@ -634,7 +731,8 @@ rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback (*ifunc->func)(iseq, ret, ifunc->data); - ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, leave); + NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1); + ADD_INSN(ret, &dummy_line_node, leave); CHECK(iseq_setup_insn(iseq, ret)); return iseq_setup(iseq, ret); @@ -646,7 +744,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) DECL_ANCHOR(ret); INIT_ANCHOR(ret); - if (imemo_type_p((VALUE)node, imemo_ifunc)) { + if (IMEMO_TYPE_P(node, imemo_ifunc)) { rb_raise(rb_eArgError, "unexpected imemo_ifunc"); } @@ -655,7 +753,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) iseq_set_local_table(iseq, 0); } /* assume node is T_NODE */ - else if (nd_type(node) == NODE_SCOPE) { + 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); @@ -670,7 +768,8 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) end->rescued = LABEL_RESCUE_END; ADD_TRACE(ret, RUBY_EVENT_B_CALL); - ADD_INSN (ret, FIX2INT(iseq->body->location.first_lineno), nop); + NODE dummy_line_node = generate_dummy_line_node(FIX2INT(iseq->body->location.first_lineno), -1); + ADD_INSN (ret, &dummy_line_node, nop); ADD_LABEL(ret, start); CHECK(COMPILE(ret, "block body", node->nd_body)); ADD_LABEL(ret, end); @@ -692,8 +791,10 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) } case ISEQ_TYPE_METHOD: { + ISEQ_COMPILE_DATA(iseq)->root_node = 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; ADD_TRACE(ret, RUBY_EVENT_RETURN); ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node); break; @@ -737,11 +838,13 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) } if (iseq->body->type == ISEQ_TYPE_RESCUE || iseq->body->type == ISEQ_TYPE_ENSURE) { - ADD_GETLOCAL(ret, 0, LVAR_ERRINFO, 0); - ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ ); + NODE dummy_line_node = generate_dummy_line_node(0, -1); + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ ); } else { - ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, leave); + NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1); + ADD_INSN(ret, &dummy_line_node, leave); } #if OPT_SUPPORT_JOKE @@ -769,7 +872,7 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) encoded[i] = (VALUE)table[insn]; i += len; } - FL_SET(iseq, ISEQ_TRANSLATED); + FL_SET((VALUE)iseq, ISEQ_TRANSLATED); #endif return COMPILE_OK; } @@ -813,6 +916,16 @@ rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */ #define STRICT_ALIGNMENT #endif +/* + * Some OpenBSD platforms (including sparc64) require strict alignment. + */ +#if defined(__OpenBSD__) + #include + #ifdef __STRICT_ALIGNMENT + #define STRICT_ALIGNMENT + #endif +#endif + #ifdef STRICT_ALIGNMENT #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE #define ALIGNMENT_SIZE SIZEOF_LONG_LONG @@ -905,6 +1018,15 @@ compile_data_alloc2(rb_iseq_t *iseq, size_t x, size_t y) return compile_data_alloc(iseq, size); } +static inline void * +compile_data_calloc2(rb_iseq_t *iseq, size_t x, size_t y) +{ + size_t size = rb_size_mul_or_raise(x, y, rb_eRuntimeError); + void *p = compile_data_alloc(iseq, size); + memset(p, 0, size); + return p; +} + static INSN * compile_data_alloc_insn(rb_iseq_t *iseq) { @@ -995,19 +1117,6 @@ LAST_ELEMENT(LINK_ANCHOR *const anchor) return anchor->last; } -static LINK_ELEMENT * -POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor) -{ - LINK_ELEMENT *elem = anchor->last; - anchor->last = anchor->last->prev; - anchor->last->next = 0; - verify_list("pop", anchor); - return elem; -} -#if CPDEBUG < 0 -#define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor)) -#endif - static LINK_ELEMENT * ELEM_FIRST_INSN(LINK_ELEMENT *elem) { @@ -1070,27 +1179,27 @@ APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2) #if CPDEBUG && 0 static void -debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor) +debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *cur) { LINK_ELEMENT *list = FIRST_ELEMENT(anchor); printf("----\n"); - printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor, - anchor->anchor.next, anchor->last); + printf("anch: %p, frst: %p, last: %p\n", (void *)&anchor->anchor, + (void *)anchor->anchor.next, (void *)anchor->last); while (list) { - printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next, - list->prev, FIX2INT(list->type)); + printf("curr: %p, next: %p, prev: %p, type: %d\n", (void *)list, (void *)list->next, + (void *)list->prev, (int)list->type); list = list->next; } printf("----\n"); - dump_disasm_list(anchor->anchor.next); + dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0); verify_list("debug list", anchor); } #if CPDEBUG < 0 -#define debug_list(anc) debug_list(iseq, (anc)) +#define debug_list(anc, cur) debug_list(iseq, (anc), (cur)) #endif #else -#define debug_list(anc) ((void)0) +#define debug_list(anc, cur) ((void)0) #endif static TRACE * @@ -1137,17 +1246,18 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line) } static INSN * -new_insn_core(rb_iseq_t *iseq, int line_no, +new_insn_core(rb_iseq_t *iseq, const NODE *line_node, int insn_id, int argc, VALUE *argv) { INSN *iobj = compile_data_alloc_insn(iseq); - /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */ + /* printf("insn_id: %d, line: %d\n", insn_id, nd_line(line_node)); */ iobj->link.type = ISEQ_ELEMENT_INSN; iobj->link.next = 0; iobj->insn_id = insn_id; - iobj->insn_info.line_no = line_no; + iobj->insn_info.line_no = nd_line(line_node); + iobj->insn_info.node_id = nd_node_id(line_node); iobj->insn_info.events = 0; iobj->operands = argv; iobj->operand_size = argc; @@ -1156,13 +1266,13 @@ new_insn_core(rb_iseq_t *iseq, int line_no, } static INSN * -new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int argc, ...) +new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_type insn_id, int argc, ...) { VALUE *operands = 0; va_list argv; if (argc > 0) { int i; - va_init_list(argv, argc); + va_start(argv, argc); operands = compile_data_alloc2(iseq, sizeof(VALUE), argc); for (i = 0; i < argc; i++) { VALUE v = va_arg(argv, VALUE); @@ -1170,44 +1280,45 @@ new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int a } va_end(argv); } - return new_insn_core(iseq, line_no, insn_id, argc, operands); + return new_insn_core(iseq, line_node, insn_id, argc, operands); } -static struct rb_call_info * -new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_call_info_kw_arg *kw_arg, int has_blockiseq) +static const struct rb_callinfo * +new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_callinfo_kwarg *kw_arg, int has_blockiseq) { - size_t size = kw_arg != NULL ? sizeof(struct rb_call_info_with_kwarg) : sizeof(struct rb_call_info); - struct rb_call_info *ci = (struct rb_call_info *)compile_data_alloc(iseq, size); - struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci; + VM_ASSERT(argc >= 0); - ci->mid = mid; - ci->flag = flag; - ci->orig_argc = argc; + 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) { - ci->flag |= VM_CALL_KWARG; - ci_kw->kw_arg = kw_arg; - ci->orig_argc += kw_arg->keyword_len; - iseq->body->ci_kw_size++; - } - else { - iseq->body->ci_size++; + flag |= VM_CALL_KWARG; + argc += kw_arg->keyword_len; } - if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) && - kw_arg == NULL && !has_blockiseq) { - ci->flag |= VM_CALL_ARGS_SIMPLE; - } + // fprintf(stderr, "[%d] id:%s\t", (int)iseq->body->ci_size, rb_id2name(mid)); rp(iseq); + iseq->body->ci_size++; + const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg); + RB_OBJ_WRITTEN(iseq, Qundef, ci); return ci; } static INSN * -new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_call_info_kw_arg *keywords) +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) { - VALUE *operands = compile_data_alloc2(iseq, sizeof(VALUE), 2); - operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL); + VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2); + VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL); + operands[0] = ci; operands[1] = (VALUE)blockiseq; - return new_insn_core(iseq, line_no, BIN(send), 2, operands); + if (blockiseq) { + RB_OBJ_WRITTEN(iseq, Qundef, blockiseq); + } + INSN *insn = new_insn_core(iseq, line_node, BIN(send), 2, operands); + RB_OBJ_WRITTEN(iseq, Qundef, ci); + RB_GC_GUARD(ci); + return insn; } static rb_iseq_t * @@ -1219,12 +1330,15 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, ast.root = node; ast.compile_option = 0; - ast.line_count = -1; + ast.script_lines = iseq->body->variable.script_lines; debugs("[new_child_iseq]> ---------------------------------------\n"); + int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; ret_iseq = rb_iseq_new_with_opt(&ast, name, rb_iseq_path(iseq), rb_iseq_realpath(iseq), - INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); + INT2FIX(line_no), parent, + isolated_depth ? isolated_depth + 1 : 0, + type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq]< ---------------------------------------\n"); return ret_iseq; } @@ -1271,11 +1385,7 @@ update_catch_except_flags(struct rb_iseq_constant_body *body) BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */ pos = 0; while (pos < body->iseq_size) { -#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]); -#else - insn = (int)body->iseq_encoded[pos]; -#endif + insn = rb_vm_insn_decode(body->iseq_encoded[pos]); if (insn == BIN(throw)) { set_catch_except_p(body); break; @@ -1310,11 +1420,20 @@ iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq) LINK_ELEMENT *end = (LINK_ELEMENT *)(ptr[2] & ~1); LINK_ELEMENT *cont = (LINK_ELEMENT *)(ptr[4] & ~1); LINK_ELEMENT *e; - for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) { - if (e == cont) { - INSN *nop = new_insn_core(iseq, 0, BIN(nop), 0, 0); - ELEM_INSERT_NEXT(end, &nop->link); - break; + + enum catch_type ct = (enum catch_type)(ptr[0] & 0xffff); + + if (ct != CATCH_TYPE_BREAK + && ct != CATCH_TYPE_NEXT + && ct != CATCH_TYPE_REDO) { + + 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); + ELEM_INSERT_NEXT(end, &nop->link); + break; + } } } } @@ -1353,6 +1472,8 @@ iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) debugs("[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n"); iseq_insert_nop_between_end_and_cont(iseq); + if (compile_debug > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); return COMPILE_OK; } @@ -1377,8 +1498,22 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) debugs("[compile step 5 (iseq_translate_threaded_code)] \n"); if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG; + debugs("[compile step 6 (update_catch_except_flags)] \n"); update_catch_except_flags(iseq->body); + debugs("[compile step 6.1 (remove unused catch tables)] \n"); + if (!iseq->body->catch_except_p && iseq->body->catch_table) { + xfree(iseq->body->catch_table); + iseq->body->catch_table = NULL; + } + +#if VM_INSN_INFO_TABLE_IMPL == 2 + if (iseq->body->insns_info.succ_index_table == NULL) { + debugs("[compile step 7 (rb_iseq_insns_info_encode_positions)] \n"); + rb_iseq_insns_info_encode_positions(iseq); + } +#endif + if (compile_debug > 1) { VALUE str = rb_iseq_disasm(iseq); printf("%s\n", StringValueCStr(str)); @@ -1494,25 +1629,74 @@ iseq_block_param_id_p(const rb_iseq_t *iseq, ID id, int *pidx, int *plevel) } static void -iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level) +access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write) +{ + int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; + + if (isolated_depth && level >= isolated_depth) { + if (id == rb_intern("yield")) { + 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)); + } + } + + for (int i=0; ibody->outer_variables; + + if (!ovs) { + ovs = iseq->body->outer_variables = rb_id_table_create(8); + } + + if (rb_id_table_lookup(iseq->body->outer_variables, id, &val)) { + if (write && !val) { + rb_id_table_insert(iseq->body->outer_variables, id, Qtrue); + } + } + else { + rb_id_table_insert(iseq->body->outer_variables, id, RBOOL(write)); + } + + iseq = iseq->body->parent_iseq; + } +} + +static ID +iseq_lvar_id(const rb_iseq_t *iseq, int idx, int level) +{ + for (int i=0; ibody->parent_iseq; + } + + ID id = iseq->body->local_table[iseq->body->local_table_size - idx]; + // fprintf(stderr, "idx:%d level:%d ID:%s\n", idx, level, rb_id2name(id)); + return id; +} + +static void +iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level) { if (iseq_local_block_param_p(iseq, idx, level)) { - ADD_INSN2(seq, line, getblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); + ADD_INSN2(seq, line_node, getblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); } else { - ADD_INSN2(seq, line, getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); + ADD_INSN2(seq, line_node, getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); } + if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qfalse); } static void -iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level) +iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level) { if (iseq_local_block_param_p(iseq, idx, level)) { - ADD_INSN2(seq, line, setblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); + ADD_INSN2(seq, line_node, setblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); } else { - ADD_INSN2(seq, line, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); + ADD_INSN2(seq, line_node, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); } + if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qtrue); } @@ -1599,7 +1783,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(node) == NODE_KW_ARG */ + NO_CHECK(COMPILE_POPPED(optargs, "kwarg", node)); /* nd_type_p(node, NODE_KW_ARG) */ dv = complex_mark; } @@ -1762,21 +1946,13 @@ 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 ID *tbl) +iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl) { - unsigned int size; - - if (tbl) { - size = (unsigned int)*tbl; - tbl++; - } - else { - size = 0; - } + unsigned int size = tbl ? tbl->size : 0; if (size > 0) { ID *ids = (ID *)ALLOC_N(ID, size); - MEMCPY(ids, tbl, ID, size); + MEMCPY(ids, tbl->ids, ID, size); iseq->body->local_table = ids; } iseq->body->local_table_size = size; @@ -1785,8 +1961,8 @@ iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl) return COMPILE_OK; } -static int -cdhash_cmp(VALUE val, VALUE lit) +int +rb_iseq_cdhash_cmp(VALUE val, VALUE lit) { int tval, tlit; @@ -1819,13 +1995,26 @@ cdhash_cmp(VALUE val, VALUE lit) else if (tlit == T_FLOAT) { return rb_float_cmp(lit, val); } + else if (tlit == T_RATIONAL) { + const struct RRational *rat1 = RRATIONAL(val); + const struct RRational *rat2 = RRATIONAL(lit); + return rb_iseq_cdhash_cmp(rat1->num, rat2->num) || rb_iseq_cdhash_cmp(rat1->den, rat2->den); + } + else if (tlit == T_COMPLEX) { + const struct RComplex *comp1 = RCOMPLEX(val); + const struct RComplex *comp2 = RCOMPLEX(lit); + return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag); + } + else if (tlit == T_REGEXP) { + return rb_reg_equal(val, lit) ? 0 : -1; + } else { UNREACHABLE_RETURN(-1); } } -static st_index_t -cdhash_hash(VALUE a) +st_index_t +rb_iseq_cdhash_hash(VALUE a) { switch (OBJ_BUILTIN_TYPE(a)) { case -1: @@ -1837,14 +2026,20 @@ cdhash_hash(VALUE a) return FIX2LONG(rb_big_hash(a)); case T_FLOAT: return rb_dbl_long_hash(RFLOAT_VALUE(a)); + case T_RATIONAL: + return rb_rational_hash(a); + case T_COMPLEX: + return rb_complex_hash(a); + case T_REGEXP: + return NUM2LONG(rb_reg_hash(a)); default: UNREACHABLE_RETURN(0); } } static const struct st_hash_type cdhash_type = { - cdhash_cmp, - cdhash_hash, + rb_iseq_cdhash_cmp, + rb_iseq_cdhash_hash, }; struct cdhash_set_label_struct { @@ -1954,7 +2149,12 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) } if (lobj->sp == -1) { lobj->sp = sp; - } + } + else if (lobj->sp != sp) { + debugs("%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n", + RSTRING_PTR(rb_iseq_path(iseq)), line, + lobj->label_no, lobj->sp, sp); + } } } break; @@ -1966,6 +2166,11 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) lobj->sp = sp; } else { + if (lobj->sp != sp) { + debugs("%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n", + RSTRING_PTR(rb_iseq_path(iseq)), line, + lobj->label_no, lobj->sp, sp); + } sp = lobj->sp; } break; @@ -2005,8 +2210,14 @@ add_insn_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions, { if (insns_info_index == 0 || insns_info[insns_info_index-1].line_no != iobj->insn_info.line_no || +#ifdef USE_ISEQ_NODE_ID + insns_info[insns_info_index-1].node_id != iobj->insn_info.node_id || +#endif insns_info[insns_info_index-1].events != iobj->insn_info.events) { insns_info[insns_info_index].line_no = iobj->insn_info.line_no; +#ifdef USE_ISEQ_NODE_ID + insns_info[insns_info_index].node_id = iobj->insn_info.node_id; +#endif insns_info[insns_info_index].events = iobj->insn_info.events; positions[insns_info_index] = code_index; return TRUE; @@ -2034,6 +2245,7 @@ add_adjust_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { + VALUE iseqv = (VALUE)iseq; struct iseq_insn_info_entry *insns_info; struct rb_iseq_constant_body *const body = iseq->body; unsigned int *positions; @@ -2082,6 +2294,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { LABEL *lobj = (LABEL *)list; lobj->position = code_index; + if (lobj->sp != sp) { + debugs("%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n", + RSTRING_PTR(rb_iseq_path(iseq)), + lobj->label_no, lobj->sp, sp); + } sp = lobj->sp; break; } @@ -2115,11 +2332,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) 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, body->is_size); - body->call_data = - rb_xcalloc_mul_add_mul( - sizeof(struct rb_call_data), body->ci_size, - sizeof(struct rb_kwarg_call_data), body->ci_kw_size); - ISEQ_COMPILE_DATA(iseq)->ci_index = ISEQ_COMPILE_DATA(iseq)->ci_kw_index = 0; + body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size); + ISEQ_COMPILE_DATA(iseq)->ci_index = 0; list = FIRST_ELEMENT(anchor); insns_info_index = code_index = sp = 0; @@ -2166,7 +2380,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) freeze_hide_obj(map); generated_iseq[code_index + 1 + j] = map; RB_OBJ_WRITTEN(iseq, Qundef, map); - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); break; } case TS_LINDEX: @@ -2181,15 +2395,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) /* to mark ruby object */ if (!SPECIAL_CONST_P(v)) { RB_OBJ_WRITTEN(iseq, Qundef, v); - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); } break; } - case TS_ISE: /* inline storage entry */ - /* Treated as an IC, but may contain a markable VALUE */ - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); - /* fall through */ case TS_IC: /* inline cache */ + case TS_ISE: /* inline storage entry */ case TS_IVC: /* inline ivar cache */ { unsigned int ic_index = FIX2UINT(operands[j]); @@ -2201,39 +2412,28 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) ic_index, body->is_size); } generated_iseq[code_index + 1 + j] = (VALUE)ic; + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); + + if (insn == BIN(opt_getinlinecache) && type == TS_IC) { + // Store the instruction index for opt_getinlinecache on the IC for + // YJIT to invalidate code when opt_setinlinecache runs. + ic->get_insn_idx = (unsigned int)code_index; + } break; } case TS_CALLDATA: { - struct rb_call_info *source_ci = (struct rb_call_info *)operands[j]; - struct rb_call_data *cd; - - if (source_ci->flag & VM_CALL_KWARG) { - struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size]; - struct rb_kwarg_call_data *cd_kw = &kw_calls[ISEQ_COMPILE_DATA(iseq)->ci_kw_index++]; - cd_kw->ci_kw = *((struct rb_call_info_with_kwarg *)source_ci); - cd = (struct rb_call_data *)cd_kw; - assert(ISEQ_COMPILE_DATA(iseq)->ci_kw_index <= body->ci_kw_size); - } - else { - cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++]; - cd->ci = *source_ci; - assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size); - } - + const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j]; + 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; break; } case TS_ID: /* ID */ generated_iseq[code_index + 1 + j] = SYM2ID(operands[j]); break; - case TS_GENTRY: - { - struct rb_global_entry *entry = - (struct rb_global_entry *)(operands[j] & (~1)); - generated_iseq[code_index + 1 + j] = (VALUE)entry; - } - break; case TS_FUNCPTR: generated_iseq[code_index + 1 + j] = operands[j]; break; @@ -2253,6 +2453,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) case ISEQ_ELEMENT_LABEL: { LABEL *lobj = (LABEL *)list; + if (lobj->sp != sp) { + debugs("%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n", + RSTRING_PTR(rb_iseq_path(iseq)), + lobj->label_no, lobj->sp, sp); + } sp = lobj->sp; break; } @@ -2285,7 +2490,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) xfree(generated_iseq); xfree(insns_info); xfree(positions); - debug_list(anchor); + debug_list(anchor, list); COMPILE_ERROR(iseq, adjust->line_no, "iseq_set_sequence: adjust bug to %d %d < %d", label_no, orig_sp, sp); @@ -2337,7 +2542,8 @@ iseq_set_exception_table(rb_iseq_t *iseq) unsigned int tlen, i; struct iseq_catch_table_entry *entry; - if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) goto no_catch_table; + iseq->body->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_TRANSIENT(ISEQ_COMPILE_DATA(iseq)->catch_table_ary); @@ -2374,10 +2580,6 @@ iseq_set_exception_table(rb_iseq_t *iseq) iseq->body->catch_table = table; RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */ } - else { - no_catch_table: - iseq->body->catch_table = NULL; - } return COMPILE_OK; } @@ -2551,10 +2753,7 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i) unref_destination((INSN *)i, pos); break; case TS_CALLDATA: - if (((struct rb_call_info *)OPERAND_AT(i, pos))->flag & VM_CALL_KWARG) - --(body->ci_kw_size); - else - --(body->ci_size); + --(body->ci_size); break; } } @@ -2580,21 +2779,6 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj) } } -static int -same_debug_pos_p(LINK_ELEMENT *iobj1, LINK_ELEMENT *iobj2) -{ - VALUE debug1 = OPERAND_AT(iobj1, 0); - VALUE debug2 = OPERAND_AT(iobj2, 0); - if (debug1 == debug2) return TRUE; - if (!RB_TYPE_P(debug1, T_ARRAY)) return FALSE; - if (!RB_TYPE_P(debug2, T_ARRAY)) return FALSE; - if (RARRAY_LEN(debug1) != 2) return FALSE; - if (RARRAY_LEN(debug2) != 2) return FALSE; - if (RARRAY_AREF(debug1, 0) != RARRAY_AREF(debug2, 0)) return FALSE; - if (RARRAY_AREF(debug1, 1) != RARRAY_AREF(debug2, 1)) return FALSE; - return TRUE; -} - static int is_frozen_putstring(INSN *insn, VALUE *op) { @@ -2633,7 +2817,7 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) * jump L2 * L2: */ - int line; + int line, node_id; INSN *niobj, *ciobj, *dup = 0; LABEL *dest = 0; VALUE type; @@ -2661,7 +2845,6 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) if (!ciobj || !IS_INSN_ID(ciobj, checktype)) return FALSE; niobj = (INSN *)get_next_insn(ciobj); if (!niobj) { - no_branch: /* TODO: putobject true/false */ return FALSE; } @@ -2677,9 +2860,11 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) } break; default: - goto no_branch; + return FALSE; } 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 */ @@ -2689,12 +2874,34 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) ELEM_INSERT_NEXT(&niobj->link, &dest->link); } } - INSERT_AFTER_INSN1(iobj, line, jump, dest); + INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest); LABEL_REF(dest); - if (!dup) INSERT_AFTER_INSN(iobj, line, pop); + if (!dup) INSERT_AFTER_INSN(iobj, &dummy_line_node, pop); return TRUE; } +static const struct rb_callinfo * +ci_flag_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, unsigned int add) +{ + const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci), + vm_ci_flag(ci) | add, + vm_ci_argc(ci), + vm_ci_kwarg(ci)); + RB_OBJ_WRITTEN(iseq, ci, nci); + return nci; +} + +static const struct rb_callinfo * +ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc) +{ + const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci), + vm_ci_flag(ci), + argc, + vm_ci_kwarg(ci)); + RB_OBJ_WRITTEN(iseq, ci, nci); + return nci; +} + static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) { @@ -2719,8 +2926,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal ELEM_REMOVE(&iobj->link); return COMPILE_OK; } - else if (iobj != diobj && IS_INSN_ID(diobj, jump) && - OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) { + else if (iobj != diobj && IS_INSN(&diobj->link) && + IS_INSN_ID(diobj, jump) && + OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0) && + diobj->insn_info.events == 0) { /* * useless jump elimination: * jump LABEL1 @@ -2736,7 +2945,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal goto again; } else if (IS_INSN_ID(diobj, leave)) { - INSN *pop; /* * jump LABEL * ... @@ -2744,7 +2952,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * leave * => * leave - * pop * ... * LABEL: * leave @@ -2754,12 +2961,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal iobj->insn_id = BIN(leave); iobj->operand_size = 0; iobj->insn_info = diobj->insn_info; - /* adjust stack depth */ - pop = new_insn_body(iseq, diobj->insn_info.line_no, BIN(pop), 0); - ELEM_INSERT_NEXT(&iobj->link, &pop->link); goto again; } - else if (IS_INSN(iobj->link.prev) && + else if (IS_INSN(iobj->link.prev) && (piobj = (INSN *)iobj->link.prev) && (IS_INSN_ID(piobj, branchif) || IS_INSN_ID(piobj, branchunless))) { @@ -2806,8 +3010,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * pop * jump L1 */ - INSN *popiobj = new_insn_core(iseq, iobj->insn_info.line_no, - BIN(pop), 0, 0); + 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); ELEM_REPLACE(&piobj->link, &popiobj->link); } } @@ -2825,13 +3029,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * * putobject "beg".."end" */ - if (IS_INSN_ID(iobj, checkmatch)) { - INSN *range = (INSN *)get_prev_insn(iobj); + if (IS_INSN_ID(iobj, newrange)) { + INSN *const range = iobj; INSN *beg, *end; VALUE str_beg, str_end; - if (range && IS_INSN_ID(range, newrange) && - (end = (INSN *)get_prev_insn(range)) != 0 && + if ((end = (INSN *)get_prev_insn(range)) != 0 && is_frozen_putstring(end, &str_end) && (beg = (INSN *)get_prev_insn(end)) != 0 && is_frozen_putstring(beg, &str_beg)) { @@ -2850,6 +3053,22 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal remove_unreachable_chunk(iseq, iobj->link.next); } + /* + * ... + * duparray [...] + * concatarray + * => + * ... + * putobject [...] + * concatarray + */ + if (IS_INSN_ID(iobj, duparray)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) { + iobj->insn_id = BIN(putobject); + } + } + if (IS_INSN_ID(iobj, branchif) || IS_INSN_ID(iobj, branchnil) || IS_INSN_ID(iobj, branchunless)) { @@ -2885,6 +3104,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal */ int stop_optimization = ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq) && + nobj->link.type == ISEQ_ELEMENT_INSN && nobj->insn_info.events; if (!stop_optimization) { INSN *pobj = (INSN *)iobj->link.prev; @@ -2897,7 +3117,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } for (;;) { - if (IS_INSN_ID(nobj, jump)) { + if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) { replace_destination(iobj, nobj); } else if (prev_dup && IS_INSN_ID(nobj, dup) && @@ -2970,12 +3190,14 @@ 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)) { - pobj = new_insn_core(iseq, pobj->insn_info.line_no, BIN(pop), 0, NULL); + 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); ELEM_INSERT_PREV(&iobj->link, &pobj->link); } if (cond) { if (prev_dup) { - pobj = new_insn_core(iseq, pobj->insn_info.line_no, BIN(putnil), 0, NULL); + 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); ELEM_INSERT_NEXT(&iobj->link, &pobj->link); } iobj->insn_id = BIN(jump); @@ -3021,7 +3243,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } else if (previ == BIN(concatarray)) { INSN *piobj = (INSN *)prev; - INSERT_BEFORE_INSN1(piobj, piobj->insn_info.line_no, splatarray, Qfalse); + 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); INSN_OF(piobj) = BIN(pop); } else if (previ == BIN(concatstrings)) { @@ -3056,13 +3279,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } - if (IS_INSN_ID(iobj, tostring)) { + if (IS_INSN_ID(iobj, anytostring)) { LINK_ELEMENT *next = iobj->link.next; /* - * tostring + * anytostring * concatstrings 1 * => - * tostring + * anytostring */ if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) && OPERAND_AT(next, 0) == INT2FIX(1)) { @@ -3095,10 +3318,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * => * concatstrings N+M-1 */ - LINK_ELEMENT *next = iobj->link.next, *freeze = 0; + LINK_ELEMENT *next = iobj->link.next; INSN *jump = 0; - if (IS_INSN(next) && IS_INSN_ID(next, freezestring)) - next = (freeze = next)->next; if (IS_INSN(next) && IS_INSN_ID(next, jump)) next = get_destination_insn(jump = (INSN *)next); if (IS_INSN(next) && IS_INSN_ID(next, concatstrings)) { @@ -3114,43 +3335,15 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal OPERAND_AT(jump, 0) = (VALUE)label; } label->refcnt++; - if (freeze && IS_NEXT_INSN_ID(next, freezestring)) { - if (same_debug_pos_p(freeze, next->next)) { - ELEM_REMOVE(freeze); - } - else { - next = next->next; - } - } ELEM_INSERT_NEXT(next, &label->link); CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt)); } else { - if (freeze) ELEM_REMOVE(freeze); ELEM_REMOVE(next); } } } - if (IS_INSN_ID(iobj, freezestring) && - NIL_P(OPERAND_AT(iobj, 0)) && - IS_NEXT_INSN_ID(&iobj->link, send)) { - INSN *niobj = (INSN *)iobj->link.next; - struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0); - /* - * freezestring nil # no debug_info - * send <:+@, 0, ARG_SIMPLE> # :-@, too - * => - * send <:+@, 0, ARG_SIMPLE> # :-@, too - */ - if ((ci->mid == idUPlus || ci->mid == idUMinus) && - (ci->flag & VM_CALL_ARGS_SIMPLE) && - ci->orig_argc == 0) { - ELEM_REMOVE(list); - return COMPILE_OK; - } - } - if (do_tailcallopt && (IS_INSN_ID(iobj, send) || IS_INSN_ID(iobj, opt_aref_with) || @@ -3193,14 +3386,19 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } if (piobj) { - struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(piobj, 0); - if (IS_INSN_ID(piobj, send) || IS_INSN_ID(piobj, invokesuper)) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(piobj, 0); + if (IS_INSN_ID(piobj, send) || + IS_INSN_ID(piobj, invokesuper)) { if (OPERAND_AT(piobj, 1) == 0) { /* no blockiseq */ - ci->flag |= VM_CALL_TAILCALL; + ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL); + OPERAND_AT(piobj, 0) = (VALUE)ci; + RB_OBJ_WRITTEN(iseq, Qundef, ci); } } else { - ci->flag |= VM_CALL_TAILCALL; + ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL); + OPERAND_AT(piobj, 0) = (VALUE)ci; + RB_OBJ_WRITTEN(iseq, Qundef, ci); } } } @@ -3259,13 +3457,14 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id) { iobj->insn_id = insn_id; iobj->operand_size = insn_len(insn_id) - 1; + iobj->insn_info.events |= RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN; if (insn_id == BIN(opt_neq)) { - VALUE *old_operands = iobj->operands; + VALUE original_ci = iobj->operands[0]; iobj->operand_size = 2; - iobj->operands = compile_data_alloc2(iseq, iobj->operand_size, sizeof(VALUE)); + iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE)); iobj->operands[0] = (VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE); - iobj->operands[1] = old_operands[0]; + iobj->operands[1] = original_ci; } return COMPILE_OK; @@ -3281,9 +3480,9 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) */ INSN *niobj = (INSN *)iobj->link.next; if (IS_INSN_ID(niobj, send)) { - struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0); - if ((ci->flag & VM_CALL_ARGS_SIMPLE) && ci->orig_argc == 0) { - switch (ci->mid) { + 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) { + switch (vm_ci_mid(ci)) { case idMax: iobj->insn_id = BIN(opt_newarray_max); ELEM_REMOVE(&niobj->link); @@ -3298,14 +3497,14 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) } if (IS_INSN_ID(iobj, send)) { - struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, 0); + 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 (ci->flag & VM_CALL_ARGS_SIMPLE) { - switch (ci->orig_argc) { + if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) { + switch (vm_ci_argc(ci)) { case 0: - switch (ci->mid) { + switch (vm_ci_mid(ci)) { case idLength: SP_INSN(length); return COMPILE_OK; case idSize: SP_INSN(size); return COMPILE_OK; case idEmptyP: SP_INSN(empty_p);return COMPILE_OK; @@ -3315,7 +3514,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) } break; case 1: - switch (ci->mid) { + switch (vm_ci_mid(ci)) { case idPLUS: SP_INSN(plus); return COMPILE_OK; case idMINUS: SP_INSN(minus); return COMPILE_OK; case idMULT: SP_INSN(mult); return COMPILE_OK; @@ -3335,14 +3534,14 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) } break; case 2: - switch (ci->mid) { + switch (vm_ci_mid(ci)) { case idASET: SP_INSN(aset); return COMPILE_OK; } break; } } - if ((ci->flag & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) { + if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) { iobj->insn_id = BIN(opt_send_without_block); iobj->operand_size = insn_len(iobj->insn_id) - 1; } @@ -3383,6 +3582,12 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) list = FIRST_ELEMENT(anchor); + int do_block_optimization = 0; + + if (iseq->body->type == ISEQ_TYPE_BLOCK && !iseq->body->catch_except_p) { + do_block_optimization = 1; + } + while (list) { if (IS_INSN(list)) { if (do_peepholeopt) { @@ -3394,6 +3599,13 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) if (do_ou) { insn_operands_unification((INSN *)list); } + + if (do_block_optimization) { + INSN * item = (INSN *)list; + if (IS_INSN_ID(item, jump)) { + do_block_optimization = 0; + } + } } if (IS_LABEL(list)) { switch (((LABEL *)list)->rescued) { @@ -3408,6 +3620,13 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) } list = list->next; } + + if (do_block_optimization) { + LINK_ELEMENT * le = FIRST_ELEMENT(anchor)->next; + if (IS_INSN(le) && IS_INSN_ID((INSN *)le, nop)) { + ELEM_REMOVE(le); + } + } return COMPILE_OK; } @@ -3430,8 +3649,7 @@ new_unified_insn(rb_iseq_t *iseq, } if (argc > 0) { - ptr = operands = - compile_data_alloc2(iseq, sizeof(VALUE), argc); + ptr = operands = compile_data_alloc2(iseq, sizeof(VALUE), argc); } /* copy operands */ @@ -3443,7 +3661,8 @@ new_unified_insn(rb_iseq_t *iseq, list = list->next; } - return new_insn_core(iseq, iobj->insn_info.line_no, insn_id, argc, operands); + 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); } #endif @@ -3594,8 +3813,9 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { /* exception merge point */ if (state != SCS_AX) { + NODE dummy_line_node = generate_dummy_line_node(0, -1); INSN *rpobj = - new_insn_body(iseq, 0, BIN(reput), 0); + new_insn_body(iseq, &dummy_line_node, BIN(reput), 0); /* replace this insn */ ELEM_REPLACE(list, (LINK_ELEMENT *)rpobj); @@ -3703,16 +3923,16 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons return COMPILE_NG; } lit = rb_fstring(lit); - ADD_INSN1(ret, nd_line(node), putobject, lit); + ADD_INSN1(ret, node, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret); } while (list) { const NODE *const head = list->nd_head; - if (nd_type(head) == NODE_STR) { + if (nd_type_p(head, NODE_STR)) { lit = rb_fstring(head->nd_lit); - ADD_INSN1(ret, nd_line(head), putobject, lit); + ADD_INSN1(ret, head, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); lit = Qnil; } @@ -3731,12 +3951,33 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons return COMPILE_OK; } +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; + } + if (node) { + CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped)); + } + return COMPILE_OK; +} + static int compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node) { int cnt; - CHECK(compile_dstr_fragments(iseq, ret, node, &cnt)); - ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt)); + if (!node->nd_next) { + VALUE lit = rb_fstring(node->nd_lit); + ADD_INSN1(ret, node, putstring, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + else { + CHECK(compile_dstr_fragments(iseq, ret, node, &cnt)); + ADD_INSN1(ret, node, concatstrings, INT2FIX(cnt)); + } return COMPILE_OK; } @@ -3745,7 +3986,7 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node) { int cnt; CHECK(compile_dstr_fragments(iseq, ret, node, &cnt)); - ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt)); + ADD_INSN2(ret, node, toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt)); return COMPILE_OK; } @@ -3759,25 +4000,25 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod + VM_SVAR_FLIPFLOP_START; VALUE key = INT2FIX(cnt); - ADD_INSN2(ret, line, getspecial, key, INT2FIX(0)); - ADD_INSNL(ret, line, branchif, lend); + ADD_INSN2(ret, node, getspecial, key, INT2FIX(0)); + ADD_INSNL(ret, node, branchif, lend); /* *flip == 0 */ CHECK(COMPILE(ret, "flip2 beg", node->nd_beg)); - ADD_INSNL(ret, line, branchunless, else_label); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSN1(ret, line, setspecial, key); + ADD_INSNL(ret, node, branchunless, else_label); + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSN1(ret, node, setspecial, key); if (!again) { - ADD_INSNL(ret, line, jump, then_label); + ADD_INSNL(ret, node, jump, then_label); } /* *flip == 1 */ ADD_LABEL(ret, lend); CHECK(COMPILE(ret, "flip2 end", node->nd_end)); - ADD_INSNL(ret, line, branchunless, then_label); - ADD_INSN1(ret, line, putobject, Qfalse); - ADD_INSN1(ret, line, setspecial, key); - ADD_INSNL(ret, line, jump, then_label); + ADD_INSNL(ret, node, branchunless, then_label); + ADD_INSN1(ret, node, putobject, Qfalse); + ADD_INSN1(ret, node, setspecial, key); + ADD_INSNL(ret, node, jump, then_label); return COMPILE_OK; } @@ -3793,7 +4034,10 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co LABEL *label = NEW_LABEL(nd_line(cond)); CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label, else_label)); - if (!label->refcnt) break; + if (!label->refcnt) { + ADD_INSN(ret, cond, putnil); + break; + } ADD_LABEL(ret, label); cond = cond->nd_2nd; goto again; @@ -3803,7 +4047,10 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co LABEL *label = NEW_LABEL(nd_line(cond)); CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label, label)); - if (!label->refcnt) break; + if (!label->refcnt) { + ADD_INSN(ret, cond, putnil); + break; + } ADD_LABEL(ret, label); cond = cond->nd_2nd; goto again; @@ -3814,69 +4061,78 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co case NODE_ZLIST: case NODE_LAMBDA: /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ - ADD_INSNL(ret, nd_line(cond), jump, then_label); - break; + ADD_INSNL(ret, cond, jump, then_label); + return COMPILE_OK; case NODE_FALSE: case NODE_NIL: /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ - ADD_INSNL(ret, nd_line(cond), jump, else_label); - break; + ADD_INSNL(ret, cond, jump, else_label); + return COMPILE_OK; case NODE_LIST: case NODE_ARGSCAT: case NODE_DREGX: case NODE_DSTR: CHECK(COMPILE_POPPED(ret, "branch condition", cond)); - ADD_INSNL(ret, nd_line(cond), jump, then_label); - break; + ADD_INSNL(ret, cond, jump, then_label); + return COMPILE_OK; case NODE_FLIP2: CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label)); - break; + return COMPILE_OK; case NODE_FLIP3: CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label)); - break; + return COMPILE_OK; case NODE_DEFINED: CHECK(compile_defined_expr(iseq, ret, cond, Qfalse)); - goto branch; + break; default: CHECK(COMPILE(ret, "branch condition", cond)); - branch: - ADD_INSNL(ret, nd_line(cond), branchunless, else_label); - ADD_INSNL(ret, nd_line(cond), jump, then_label); - break; + break; } + + ADD_INSNL(ret, cond, branchunless, else_label); + ADD_INSNL(ret, cond, jump, then_label); return COMPILE_OK; } +#define HASH_BRACE 1 + static int keyword_node_p(const NODE *const node) { - return nd_type(node) == NODE_HASH && node->nd_brace == FALSE; + return nd_type_p(node, NODE_HASH) && (node->nd_brace & HASH_BRACE) != HASH_BRACE; } static int compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const root_node, - struct rb_call_info_kw_arg **const kw_arg_ptr, + struct rb_callinfo_kwarg **const kw_arg_ptr, unsigned int *flag) { if (kw_arg_ptr == NULL) return FALSE; - if (keyword_node_p(root_node) && root_node->nd_head && nd_type(root_node->nd_head) == NODE_LIST) { + if (root_node->nd_head && nd_type_p(root_node->nd_head, NODE_LIST)) { const NODE *node = root_node->nd_head; + int seen_nodes = 0; while (node) { const NODE *key_node = node->nd_head; + seen_nodes++; - assert(nd_type(node) == NODE_LIST); - if (!key_node) { - if (flag) *flag |= VM_CALL_KW_SPLAT; - return FALSE; - } - else if (nd_type(key_node) == NODE_LIT && RB_TYPE_P(key_node->nd_lit, T_SYMBOL)) { + assert(nd_type_p(node, NODE_LIST)); + if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(key_node->nd_lit)) { /* can be keywords */ } else { - if (flag) *flag |= VM_CALL_KW_SPLAT; + if (flag) { + *flag |= VM_CALL_KW_SPLAT; + if (seen_nodes > 1 || 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. + */ + *flag |= VM_CALL_KW_SPLAT_MUT; + } + } return FALSE; } node = node->nd_next; /* skip value node */ @@ -3887,8 +4143,8 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, node = root_node->nd_head; { int len = (int)node->nd_alen / 2; - struct rb_call_info_kw_arg *kw_arg = - rb_xmalloc_mul_add(len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg)); + 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; kw_arg->keyword_len = len; @@ -3910,7 +4166,7 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, static int compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, - struct rb_call_info_kw_arg **keywords_ptr, unsigned int *flag) + struct rb_callinfo_kwarg **keywords_ptr, unsigned int *flag) { int len = 0; @@ -3919,9 +4175,13 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, EXPECT_NODE("compile_args", node, NODE_LIST, -1); } - if (node->nd_next == NULL /* last node */ && - compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) { - len--; + if (node->nd_next == NULL && keyword_node_p(node->nd_head)) { /* last node */ + if (compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) { + len--; + } + else { + compile_hash(iseq, ret, node->nd_head, TRUE, FALSE); + } } else { NO_CHECK(COMPILE_(ret, "array element", node->nd_head, FALSE)); @@ -3934,7 +4194,6 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, static inline int static_literal_node_p(const NODE *node, const rb_iseq_t *iseq) { - node = node->nd_head; switch (nd_type(node)) { case NODE_LIT: case NODE_NIL: @@ -3951,7 +4210,6 @@ static_literal_node_p(const NODE *node, const rb_iseq_t *iseq) static inline VALUE static_literal_value(const NODE *node, rb_iseq_t *iseq) { - node = node->nd_head; switch (nd_type(node)) { case NODE_NIL: return Qnil; @@ -3978,11 +4236,11 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq) static int compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) { - int line = (int)nd_line(node); + const NODE *line_node = node; - if (nd_type(node) == NODE_ZLIST) { + if (nd_type_p(node, NODE_ZLIST)) { if (!popped) { - ADD_INSN1(ret, line, newarray, INT2FIX(0)); + ADD_INSN1(ret, line_node, newarray, INT2FIX(0)); } return 0; } @@ -4041,8 +4299,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop /* Convert pushed elements to an array, and concatarray if needed */ #define FLUSH_CHUNK(newarrayinsn) \ if (stack_len) { \ - ADD_INSN1(ret, line, newarrayinsn, INT2FIX(stack_len)); \ - if (!first_chunk) ADD_INSN(ret, line, concatarray); \ + ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \ + if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \ first_chunk = stack_len = 0; \ } @@ -4050,10 +4308,10 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop int count = 1; /* pre-allocation check (this branch can be omittable) */ - if (static_literal_node_p(node, iseq)) { + if (static_literal_node_p(node->nd_head, iseq)) { /* count the elements that are optimizable */ const NODE *node_tmp = node->nd_next; - for (; node_tmp && static_literal_node_p(node_tmp, iseq); node_tmp = node_tmp->nd_next) + for (; node_tmp && static_literal_node_p(node_tmp->nd_head, iseq); node_tmp = node_tmp->nd_next) count++; if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) { @@ -4062,18 +4320,18 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop /* Create a hidden array */ for (; count; count--, node = node->nd_next) - rb_ary_push(ary, static_literal_value(node, iseq)); + rb_ary_push(ary, static_literal_value(node->nd_head, iseq)); OBJ_FREEZE(ary); /* Emit optimized code */ FLUSH_CHUNK(newarray); if (first_chunk) { - ADD_INSN1(ret, line, duparray, ary); + ADD_INSN1(ret, line_node, duparray, ary); first_chunk = 0; } else { - ADD_INSN1(ret, line, putobject, ary); - ADD_INSN(ret, line, concatarray); + ADD_INSN1(ret, line_node, putobject, ary); + ADD_INSN(ret, line_node, concatarray); } RB_OBJ_WRITTEN(iseq, Qundef, ary); } @@ -4104,22 +4362,41 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop 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_tmp_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, iseq) && static_literal_node_p(node->nd_next, iseq); + return node->nd_head && static_literal_node_p(node->nd_head, iseq) && static_literal_node_p(node->nd_next->nd_head, iseq); } static int -compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) +compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped) { - int line = (int)nd_line(node); + const NODE *line_node = node; node = node->nd_head; - if (!node || nd_type(node) == NODE_ZLIST) { + if (!node || nd_type_p(node, NODE_ZLIST)) { if (!popped) { - ADD_INSN1(ret, line, newhash, INT2FIX(0)); + ADD_INSN1(ret, line_node, newhash, INT2FIX(0)); } return 0; } @@ -4163,13 +4440,13 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp if (stack_len) { \ if (first_chunk) { \ APPEND_LIST(ret, anchor); \ - ADD_INSN1(ret, line, newhash, INT2FIX(stack_len)); \ + ADD_INSN1(ret, line_node, newhash, INT2FIX(stack_len)); \ } \ else { \ - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \ - ADD_INSN(ret, line, swap); \ + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \ + ADD_INSN(ret, line_node, swap); \ APPEND_LIST(ret, anchor); \ - ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \ + ADD_SEND(ret, line_node, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \ } \ INIT_ANCHOR(anchor); \ first_chunk = stack_len = 0; \ @@ -4192,8 +4469,8 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp /* Create a hidden hash */ for (; count; count--, node = node->nd_next->nd_next) { VALUE elem[2]; - elem[0] = static_literal_value(node, iseq); - elem[1] = static_literal_value(node->nd_next, iseq); + elem[0] = static_literal_value(node->nd_head, iseq); + elem[1] = static_literal_value(node->nd_next->nd_head, iseq); rb_ary_cat(ary, elem, 2); } VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2); @@ -4204,16 +4481,16 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp /* Emit optimized code */ FLUSH_CHUNK(); if (first_chunk) { - ADD_INSN1(ret, line, duphash, hash); + ADD_INSN1(ret, line_node, duphash, hash); first_chunk = 0; } else { - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN(ret, line, swap); + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN(ret, line_node, swap); - ADD_INSN1(ret, line, putobject, hash); + ADD_INSN1(ret, line_node, putobject, hash); - ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2)); + ADD_SEND(ret, line_node, id_core_hash_merge_kwd, INT2FIX(2)); } RB_OBJ_WRITTEN(iseq, Qundef, hash); } @@ -4240,39 +4517,55 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp FLUSH_CHUNK(); const NODE *kw = node->nd_next->nd_head; - int empty_kw = nd_type(kw) == NODE_LIT; /* foo( ..., **{}, ...) */ + int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(kw->nd_lit, T_HASH); /* 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 only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */ if (empty_kw) { - if (only_kw) { - /* **{} appears at the last, so it won't be modified. + if (only_kw && method_call_keywords) { + /* **{} appears at the only keyword argument in method call, + * so it won't be modified. * kw is a special NODE_LIT that contains a special empty hash, - * so this emits: putobject {} + * so this emits: putobject {}. + * This is only done for method calls and not for literal hashes, + * because literal hashes should always result in a new hash. */ NO_CHECK(COMPILE(ret, "keyword splat", kw)); } else if (first_kw) { - /* **{} appears at the first, so it may be modified. + /* **{} appears as the first keyword argument, so it may be modified. * We need to create a fresh hash object. */ - ADD_INSN1(ret, line, newhash, INT2FIX(0)); + ADD_INSN1(ret, line_node, newhash, INT2FIX(0)); } + /* Any empty keyword splats that are not the first can be ignored. + * since merging an empty hash into the existing hash is the same + * as not merging it. */ } else { - /* This is not empty hash: **{k:1}. - * We need to clone the hash (if first), or merge the hash to - * the accumulated hash (if not first). - */ - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (first_kw) ADD_INSN1(ret, line, newhash, INT2FIX(0)); - else ADD_INSN(ret, line, swap); - - NO_CHECK(COMPILE(ret, "keyword splat", kw)); - - ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2)); - } + if (only_kw && method_call_keywords) { + /* **kw is only keyword argument in method call. + * Use directly. This will be not be flagged as mutable. + * This is only done for method calls and not for literal hashes, + * because literal hashes should always result in a new hash. + */ + NO_CHECK(COMPILE(ret, "keyword splat", kw)); + } + else { + /* There is more than one keyword argument, or this is not a method + * call. In that case, we need to add an empty hash (if first keyword), + * or merge the hash to the accumulated hash (if not the first keyword). + */ + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (first_kw) ADD_INSN1(ret, line_node, newhash, INT2FIX(0)); + else ADD_INSN(ret, line_node, swap); + + NO_CHECK(COMPILE(ret, "keyword splat", kw)); + + ADD_SEND(ret, line_node, id_core_hash_merge_kwd, INT2FIX(2)); + } + } first_chunk = 0; } @@ -4291,10 +4584,13 @@ rb_node_case_when_optimizable_literal(const NODE *const node) case NODE_LIT: { VALUE v = node->nd_lit; double ival; - if (RB_TYPE_P(v, T_FLOAT) && + if (RB_FLOAT_TYPE_P(v) && 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; } @@ -4327,20 +4623,20 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, rb_hash_aset(literals, lit, (VALUE)(l1) | 1); } - ADD_INSN(cond_seq, nd_line(val), dup); /* dup target */ - - if (nd_type(val) == NODE_STR) { + if (nd_type_p(val, NODE_STR)) { debugp_param("nd_lit", val->nd_lit); lit = rb_fstring(val->nd_lit); - ADD_INSN1(cond_seq, nd_line(val), putobject, lit); + ADD_INSN1(cond_seq, val, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); } else { if (!COMPILE(cond_seq, "when cond", val)) return -1; } - ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); - ADD_INSNL(cond_seq, nd_line(val), branchif, l1); + // Emit patern === target + 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; } return only_special_literals; @@ -4350,7 +4646,7 @@ static int when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, LABEL *l1, int only_special_literals, VALUE literals) { - const int line = nd_line(vals); + const NODE *line_node = vals; switch (nd_type(vals)) { case NODE_LIST: @@ -4358,11 +4654,11 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, return COMPILE_NG; break; case NODE_SPLAT: - ADD_INSN (cond_seq, line, dup); + ADD_INSN (cond_seq, line_node, dup); CHECK(COMPILE(cond_seq, "when splat", vals->nd_head)); - ADD_INSN1(cond_seq, line, splatarray, Qfalse); - ADD_INSN1(cond_seq, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); - ADD_INSNL(cond_seq, line, branchif, l1); + 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)); @@ -4370,55 +4666,213 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, break; case NODE_ARGSPUSH: CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals)); - ADD_INSN (cond_seq, line, dup); + ADD_INSN (cond_seq, line_node, dup); CHECK(COMPILE(cond_seq, "when argspush body", vals->nd_body)); - ADD_INSN1(cond_seq, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); - ADD_INSNL(cond_seq, line, branchif, l1); + ADD_INSN1(cond_seq, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); + ADD_INSNL(cond_seq, line_node, branchif, l1); break; default: - ADD_INSN (cond_seq, line, dup); + ADD_INSN (cond_seq, line_node, dup); CHECK(COMPILE(cond_seq, "when val", vals)); - ADD_INSN1(cond_seq, line, splatarray, Qfalse); - ADD_INSN1(cond_seq, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); - ADD_INSNL(cond_seq, line, branchif, l1); + 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; } return COMPILE_OK; } +/* Multiple Assignment Handling + * + * In order to handle evaluation of multiple assignment such that the left hand side + * is evaluated before the right hand side, we need to process the left hand side + * and see if there are any attributes that need to be assigned. If so, we add + * instructions to evaluate the receiver of any assigned attributes before we + * process the right hand side. + * + * For a multiple assignment such as: + * + * l1.m1, l2[0] = r3, r4 + * + * We start off evaluating l1 and l2, then we evaluate r3 and r4, then we + * assign the result of r3 to l1.m1, and then the result of r4 to l2.m2. + * On the VM stack, this looks like: + * + * self # putself + * l1 # send + * l1, self # putself + * l1, l2 # send + * l1, l2, 0 # putobject 0 + * l1, l2, 0, [r3, r4] # after evaluation of RHS + * l1, l2, 0, [r3, r4], r4, r3 # expandarray + * l1, l2, 0, [r3, r4], r4, r3, l1 # topn 5 + * l1, l2, 0, [r3, r4], r4, l1, r3 # swap + * l1, l2, 0, [r3, r4], r4, m1= # send + * l1, l2, 0, [r3, r4], r4 # pop + * l1, l2, 0, [r3, r4], r4, l2 # topn 3 + * l1, l2, 0, [r3, r4], r4, l2, 0 # topn 3 + * l1, l2, 0, [r3, r4], r4, l2, 0, r4 # topn 2 + * l1, l2, 0, [r3, r4], r4, []= # send + * l1, l2, 0, [r3, r4], r4 # pop + * l1, l2, 0, [r3, r4] # pop + * [r3, r4], l2, 0, [r3, r4] # setn 3 + * [r3, r4], l2, 0 # pop + * [r3, r4], l2 # pop + * [r3, r4] # pop + * + * This is made more complex when you have to handle splats, post args, + * and arbitrary levels of nesting. You need to keep track of the total + * number of attributes to set, and for each attribute, how many entries + * are on the stack before the final attribute, in order to correctly + * calculate the topn value to use to get the receiver of the attribute + * setter method. + * + * A brief description of the VM stack for simple multiple assignment + * with no splat (rhs_array will not be present if the return value of + * the multiple assignment is not needed): + * + * lhs_attr1, lhs_attr2, ..., rhs_array, ..., rhs_arg2, rhs_arg1 + * + * For multiple assignment with splats, while processing the part before + * the splat (splat+post here is an array of the splat and the post arguments): + * + * lhs_attr1, lhs_attr2, ..., rhs_array, splat+post, ..., rhs_arg2, rhs_arg1 + * + * When processing the splat and post arguments: + * + * lhs_attr1, lhs_attr2, ..., rhs_array, ..., post_arg2, post_arg1, splat + * + * When processing nested multiple assignment, existing values on the stack + * are kept. So for: + * + * (l1.m1, l2.m2), l3.m3, l4* = [r1, r2], r3, r4 + * + * The stack layout would be the following before processing the nested + * multiple assignment: + * + * l1, l2, [[r1, r2], r3, r4], [r4], r3, [r1, r2] + * + * In order to handle this correctly, we need to keep track of the nesting + * level for each attribute assignment, as well as the attribute number + * (left hand side attributes are processed left to right) and number of + * arguments to pass to the setter method. struct masgn_attrasgn tracks + * this information. + * + * We also need to track information for the entire multiple assignment, such + * as the total number of arguments, and the current nesting level, to + * handle both nested multiple assignment as well as cases where the + * rhs is not needed. We also need to keep track of all attribute + * assignments in this, which we do using a linked listed. struct masgn_state + * tracks this information. + */ + +struct masgn_attrasgn { + INSN *before_insn; + struct masgn_attrasgn *next; + const NODE *line_node; + int argn; + int num_args; + int lhs_pos; +}; + +struct masgn_state { + struct masgn_attrasgn *first_memo; + struct masgn_attrasgn *last_memo; + int lhs_level; + int num_args; + bool nested; +}; + +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); static int -compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node) +compile_massign_lhs(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 lhs_pos) { switch (nd_type(node)) { case NODE_ATTRASGN: { + if (!state) { + rb_bug("no masgn_state"); + } + INSN *iobj; - struct rb_call_info *ci; - VALUE dupidx; - int line = nd_line(node); + const NODE *line_node = node; - CHECK(COMPILE_POPPED(ret, "masgn lhs (NODE_ATTRASGN)", node)); + CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node)); - iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */ - ci = (struct rb_call_info *)OPERAND_AT(iobj, 0); - ci->orig_argc += 1; - dupidx = INT2FIX(ci->orig_argc); + 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; - INSERT_BEFORE_INSN1(iobj, line, topn, dupidx); - if (ci->flag & VM_CALL_ARGS_SPLAT) { - --ci->orig_argc; - INSERT_BEFORE_INSN1(iobj, line, newarray, INT2FIX(1)); - INSERT_BEFORE_INSN(iobj, line, concatarray); - } - ADD_INSN(ret, line, pop); /* result */ + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0); + int argc = vm_ci_argc(ci) + 1; + ci = ci_argc_set(iseq, ci, argc); + OPERAND_AT(iobj, 0) = (VALUE)ci; + RB_OBJ_WRITTEN(iseq, Qundef, ci); + + if (argc == 1) { + ADD_INSN(lhs, line_node, swap); + } + else { + ADD_INSN1(lhs, line_node, topn, INT2FIX(argc)); + } + + struct masgn_attrasgn *memo; + memo = malloc(sizeof(struct masgn_attrasgn)); + if (!memo) { + return 0; + } + memo->before_insn = (INSN *)LAST_ELEMENT(lhs); + memo->line_node = line_node; + memo->argn = state->num_args + 1; + memo->num_args = argc; + state->num_args += argc; + memo->lhs_pos = lhs_pos; + memo->next = NULL; + if (!state->first_memo) { + state->first_memo = memo; + } + else { + state->last_memo->next = memo; + } + state->last_memo = memo; + + ADD_ELEM(lhs, (LINK_ELEMENT *)iobj); + if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { + int argc = vm_ci_argc(ci); + ci = ci_argc_set(iseq, ci, argc - 1); + 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); + } + 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); + } break; } case NODE_MASGN: { - DECL_ANCHOR(anchor); - INIT_ANCHOR(anchor); - CHECK(COMPILE_POPPED(anchor, "nest masgn lhs", node)); - ELEM_REMOVE(FIRST_ELEMENT(anchor)); - ADD_SEQ(ret, anchor); + DECL_ANCHOR(nest_rhs); + INIT_ANCHOR(nest_rhs); + DECL_ANCHOR(nest_lhs); + INIT_ANCHOR(nest_lhs); + + int prev_level = state->lhs_level; + bool prev_nested = state->nested; + state->nested = 1; + state->lhs_level = lhs_pos - 1; + CHECK(compile_massign0(iseq, pre, nest_rhs, nest_lhs, post, node, state, 1)); + state->lhs_level = prev_level; + state->nested = prev_nested; + + ADD_SEQ(lhs, nest_rhs); + ADD_SEQ(lhs, nest_lhs); break; } default: { @@ -4426,7 +4880,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const n INIT_ANCHOR(anchor); CHECK(COMPILE_POPPED(anchor, "masgn lhs", node)); ELEM_REMOVE(FIRST_ELEMENT(anchor)); - ADD_SEQ(ret, anchor); + ADD_SEQ(lhs, anchor); } } @@ -4438,7 +4892,7 @@ compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *lhs { if (lhsn) { CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next)); - CHECK(compile_massign_lhs(iseq, ret, lhsn->nd_head)); + CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, lhsn->nd_head, NULL, 0)); } return COMPILE_OK; } @@ -4463,7 +4917,7 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, mem[memindex++] = (v); \ } - if (rhsn == 0 || nd_type(rhsn) != NODE_LIST) { + if (rhsn == 0 || !nd_type_p(rhsn, NODE_LIST)) { return 0; } @@ -4474,7 +4928,6 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, MEMORY(ln->nd_vid); break; case NODE_DASGN: - case NODE_DASGN_CURR: case NODE_IASGN: case NODE_CVASGN: MEMORY(ln->nd_vid); @@ -4499,7 +4952,7 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, if (llen > rlen) { for (i=0; i llen) { - do {ADD_INSN(ret, line, pop);} while (--rlen > llen); - } -} - static int -compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +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 *lhsn_count = lhsn; int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0; - if (!popped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) { - int llen = 0; - int expand = 1; - DECL_ANCHOR(lhsseq); + int llen = 0; + int lpos = 0; + int expand = 1; + + while (lhsn_count) { + llen++; + lhsn_count = 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)); + lpos++; + lhsn = lhsn->nd_next; + } - INIT_ANCHOR(lhsseq); + 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; + int ppos = 0; + int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00); - while (lhsn) { - CHECK(compile_massign_lhs(iseq, lhsseq, lhsn->nd_head)); - llen += 1; - lhsn = lhsn->nd_next; - } + ADD_INSN2(lhs, splatn, expandarray, INT2FIX(plen), INT2FIX(flag)); - NO_CHECK(COMPILE(ret, "normal masgn rhs", rhsn)); + if (NODE_NAMED_REST_P(restn)) { + 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)); + ppos++; + postn = postn->nd_next; + } + } + else { + /* a, b, *r */ + CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, splatn, state, 1 + state->lhs_level)); + } + } - if (!popped) { - ADD_INSN(ret, nd_line(node), dup); - } - else if (!lhs_splat) { - INSN *last = (INSN*)ret->last; - if (IS_INSN(&last->link) && - IS_INSN_ID(last, newarray) && - last->operand_size == 1) { - int rlen = FIX2INT(OPERAND_AT(last, 0)); - /* special case: assign to aset or attrset */ - if (llen == 2) { - POP_ELEMENT(ret); - adjust_stack(iseq, ret, nd_line(node), rlen, llen); - ADD_INSN(ret, nd_line(node), swap); - expand = 0; - } - else if (llen > 2 && llen != rlen) { - POP_ELEMENT(ret); - adjust_stack(iseq, ret, nd_line(node), rlen, llen); - ADD_INSN1(ret, nd_line(node), reverse, INT2FIX(llen)); - expand = 0; - } - else if (llen > 2) { - last->insn_id = BIN(reverse); - expand = 0; - } - } - } - if (expand) { - ADD_INSN2(ret, nd_line(node), expandarray, - INT2FIX(llen), INT2FIX(lhs_splat)); - } - ADD_SEQ(ret, lhsseq); - if (lhs_splat) { - if (nd_type(splatn) == NODE_POSTARG) { - /*a, b, *r, p1, p2 */ - const NODE *postn = splatn->nd_2nd; - const NODE *restn = splatn->nd_1st; - int num = (int)postn->nd_alen; - int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00); + if (!state->nested) { + NO_CHECK(COMPILE(rhs, "normal masgn rhs", rhsn)); + } - ADD_INSN2(ret, nd_line(splatn), expandarray, - INT2FIX(num), INT2FIX(flag)); + if (!popped) { + ADD_INSN(rhs, node, dup); + } + if (expand) { + ADD_INSN2(rhs, node, expandarray, INT2FIX(llen), INT2FIX(lhs_splat)); + } + return COMPILE_OK; +} - if (NODE_NAMED_REST_P(restn)) { - CHECK(compile_massign_lhs(iseq, ret, restn)); - } - while (postn) { - CHECK(compile_massign_lhs(iseq, ret, postn->nd_head)); - postn = postn->nd_next; - } - } - else { - /* a, b, *r */ - CHECK(compile_massign_lhs(iseq, ret, splatn)); - } - } +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)) { + struct masgn_state state; + state.lhs_level = popped ? 0 : 1; + state.nested = 0; + state.num_args = 0; + state.first_memo = NULL; + state.last_memo = NULL; + + DECL_ANCHOR(pre); + INIT_ANCHOR(pre); + DECL_ANCHOR(rhs); + INIT_ANCHOR(rhs); + DECL_ANCHOR(lhs); + INIT_ANCHOR(lhs); + DECL_ANCHOR(post); + INIT_ANCHOR(post); + int ok = compile_massign0(iseq, pre, rhs, lhs, post, node, &state, popped); + + struct masgn_attrasgn *memo = state.first_memo, *tmp_memo; + 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); + } + tmp_memo = memo->next; + free(memo); + memo = tmp_memo; + } + CHECK(ok); + + ADD_SEQ(ret, pre); + ADD_SEQ(ret, rhs); + ADD_SEQ(ret, lhs); + if (!popped && state.num_args >= 1) { + /* make sure rhs array is returned before popping */ + ADD_INSN1(ret, node, setn, INT2FIX(state.num_args)); + } + ADD_SEQ(ret, post); } return COMPILE_OK; } @@ -4610,21 +5075,21 @@ 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); - ADD_INSN1(body, nd_line(node), putobject, Qtrue); - ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(body, node, putobject, Qtrue); + ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_vid)); break; case NODE_COLON3: debugi("compile_const_prefix - colon3", node->nd_mid); - ADD_INSN(body, nd_line(node), pop); - ADD_INSN1(body, nd_line(node), putobject, rb_cObject); - ADD_INSN1(body, nd_line(node), putobject, Qtrue); - ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(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)); break; case NODE_COLON2: CHECK(compile_const_prefix(iseq, node->nd_head, pref, body)); debugi("compile_const_prefix - colon2", node->nd_mid); - ADD_INSN1(body, nd_line(node), putobject, Qfalse); - ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); + ADD_INSN1(body, node, putobject, Qfalse); + ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid)); break; default: CHECK(COMPILE(pref, "const colon2 prefix", node)); @@ -4636,9 +5101,9 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node, static int compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath) { - if (nd_type(cpath) == NODE_COLON3) { + if (nd_type_p(cpath, NODE_COLON3)) { /* toplevel class ::Foo */ - ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject); + ADD_INSN1(ret, cpath, putobject, rb_cObject); return VM_DEFINECLASS_FLAG_SCOPED; } else if (cpath->nd_head) { @@ -4648,7 +5113,7 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath) } else { /* class at cbase Foo */ - ADD_INSN1(ret, nd_line(cpath), putspecialobject, + ADD_INSN1(ret, cpath, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); return 0; } @@ -4657,7 +5122,7 @@ 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(node->nd_recv) == NODE_SELF) { + if (nd_type_p(node->nd_recv, NODE_SELF)) { NODE *self = node->nd_recv; return self->nd_state != 0; } @@ -4668,13 +5133,18 @@ static void defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL **lfinish, VALUE needstr); +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); + static void defined_expr0(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 keep_result) { enum defined_type expr_type = DEFINED_NOT_DEFINED; enum node_type type; const int line = nd_line(node); + const NODE *line_node = node; switch (type = nd_type(node)) { @@ -4696,12 +5166,12 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *vals = node; do { - defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse); + defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse, false); if (!lfinish[1]) { lfinish[1] = NEW_LABEL(line); } - ADD_INSNL(ret, line, branchunless, lfinish[1]); + ADD_INSNL(ret, line_node, branchunless, lfinish[1]); } while ((vals = vals->nd_next) != NULL); } /* fall through */ @@ -4720,46 +5190,51 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, expr_type = DEFINED_LVAR; break; +#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type)) case NODE_IVAR: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_IVAR), - ID2SYM(node->nd_vid), needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_IVAR), + ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_IVAR)); return; case NODE_GVAR: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_GVAR), - ID2SYM(node->nd_entry->id), needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_GVAR), + ID2SYM(node->nd_entry), PUSH_VAL(DEFINED_GVAR)); return; case NODE_CVAR: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CVAR), - ID2SYM(node->nd_vid), needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CVAR), + ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR)); return; case NODE_CONST: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST), - ID2SYM(node->nd_vid), needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST), + ID2SYM(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); - ADD_INSNL(ret, line, branchunless, lfinish[1]); + defined_expr0(iseq, ret, 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)); - ADD_INSN3(ret, line, defined, - (rb_is_const_id(node->nd_mid) ? - INT2FIX(DEFINED_CONST_FROM) : INT2FIX(DEFINED_METHOD)), - ID2SYM(node->nd_mid), needstr); + if (rb_is_const_id(node->nd_mid)) { + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST_FROM), + ID2SYM(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)); + } return; case NODE_COLON3: - ADD_INSN1(ret, line, putobject, rb_cObject); - ADD_INSN3(ret, line, defined, - INT2FIX(DEFINED_CONST_FROM), ID2SYM(node->nd_mid), needstr); + 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)); return; /* method dispatch */ @@ -4772,49 +5247,73 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, (type == NODE_CALL || type == NODE_OPCALL || (type == NODE_ATTRASGN && !private_recv_p(node))); - if (!lfinish[1] && (node->nd_args || explicit_receiver)) { - lfinish[1] = NEW_LABEL(line); - } + if (node->nd_args || explicit_receiver) { + if (!lfinish[1]) { + lfinish[1] = NEW_LABEL(line); + } + if (!lfinish[2]) { + lfinish[2] = NEW_LABEL(line); + } + } if (node->nd_args) { - defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse); - ADD_INSNL(ret, line, branchunless, lfinish[1]); + defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse, false); + ADD_INSNL(ret, line_node, branchunless, lfinish[1]); } if (explicit_receiver) { - defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse); - ADD_INSNL(ret, line, branchunless, lfinish[1]); - NO_CHECK(COMPILE(ret, "defined/recv", node->nd_recv)); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_METHOD), - ID2SYM(node->nd_mid), needstr); + defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse, true); + switch (nd_type(node->nd_recv)) { + 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); + break; + default: + ADD_INSNL(ret, line_node, branchunless, lfinish[1]); + NO_CHECK(COMPILE(ret, "defined/recv", node->nd_recv)); + 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)); } else { - ADD_INSN(ret, line, putself); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_FUNC), - ID2SYM(node->nd_mid), needstr); + ADD_INSN(ret, line_node, putself); + if (keep_result) { + ADD_INSN(ret, line_node, dup); + } + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC), + ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD)); } return; } case NODE_YIELD: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_YIELD), 0, - needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0, + PUSH_VAL(DEFINED_YIELD)); return; case NODE_BACK_REF: case NODE_NTH_REF: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_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)), - needstr); + PUSH_VAL(DEFINED_GVAR)); return; case NODE_SUPER: case NODE_ZSUPER: - ADD_INSN(ret, line, putnil); - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_ZSUPER), 0, - needstr); + ADD_INSN(ret, line_node, putnil); + ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_ZSUPER), 0, + PUSH_VAL(DEFINED_ZSUPER)); return; +#undef PUSH_VAL case NODE_OP_ASGN1: case NODE_OP_ASGN2: case NODE_OP_ASGN_OR: @@ -4822,7 +5321,6 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, case NODE_MASGN: case NODE_LASGN: case NODE_DASGN: - case NODE_DASGN_CURR: case NODE_GASGN: case NODE_IASGN: case NODE_CDECL: @@ -4835,17 +5333,18 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, if (needstr != Qfalse) { VALUE str = rb_iseq_defined_string(expr_type); - ADD_INSN1(ret, line, putobject, str); + ADD_INSN1(ret, line_node, putobject, str); } else { - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_INSN1(ret, line_node, putobject, Qtrue); } } static void build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const void *unused) { - ADD_INSN(ret, 0, putnil); + NODE dummy_line_node = generate_dummy_line_node(0, -1); + ADD_INSN(ret, &dummy_line_node, putnil); iseq_set_exception_local_table(iseq); } @@ -4854,7 +5353,7 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL **lfinish, VALUE needstr) { LINK_ELEMENT *lcur = ret->last; - defined_expr0(iseq, ret, node, lfinish, needstr); + defined_expr0(iseq, ret, node, lfinish, needstr, false); if (lfinish[1]) { int line = nd_line(node); LABEL *lstart = NEW_LABEL(line); @@ -4878,20 +5377,25 @@ static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr) { const int line = nd_line(node); + const NODE *line_node = node; if (!node->nd_head) { VALUE str = rb_iseq_defined_string(DEFINED_NIL); - ADD_INSN1(ret, line, putobject, str); + ADD_INSN1(ret, line_node, putobject, str); } else { - LABEL *lfinish[2]; + LABEL *lfinish[3]; LINK_ELEMENT *last = ret->last; lfinish[0] = NEW_LABEL(line); lfinish[1] = 0; + lfinish[2] = 0; defined_expr(iseq, ret, node->nd_head, lfinish, needstr); if (lfinish[1]) { - ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line, BIN(putnil), 0)->link); - ADD_INSN(ret, line, swap); - ADD_INSN(ret, line, pop); + ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link); + ADD_INSN(ret, line_node, swap); + if (lfinish[2]) { + ADD_LABEL(ret, lfinish[2]); + } + ADD_INSN(ret, line_node, pop); ADD_LABEL(ret, lfinish[1]); } ADD_LABEL(ret, lfinish[0]); @@ -4951,9 +5455,24 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, erange->next = ne; } +static bool +can_add_ensure_iseq(const rb_iseq_t *iseq) +{ + struct iseq_compile_data_ensure_node_stack *e; + if (ISEQ_COMPILE_DATA(iseq)->in_rescue && (e = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) != NULL) { + while (e) { + if (e->ensure_node) return false; + e = e->prev; + } + } + return true; +} + static void add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return) { + assert(can_add_ensure_iseq(iseq)); + struct iseq_compile_data_ensure_node_stack *enlp = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack; struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp; @@ -4991,7 +5510,7 @@ check_keyword(const NODE *node) { /* This check is essentially a code clone of compile_keyword_arg. */ - if (nd_type(node) == NODE_LIST) { + if (nd_type_p(node, NODE_LIST)) { while (node->nd_next) { node = node->nd_next; } @@ -5003,24 +5522,24 @@ check_keyword(const NODE *node) static VALUE setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, - int dup_rest, unsigned int *flag, struct rb_call_info_kw_arg **keywords) + int dup_rest, unsigned int *flag, struct rb_callinfo_kwarg **keywords) { if (argn) { switch (nd_type(argn)) { case NODE_SPLAT: { NO_CHECK(COMPILE(args, "args (splat)", argn->nd_head)); - ADD_INSN1(args, nd_line(argn), splatarray, dup_rest ? Qtrue : Qfalse); + ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest)); if (flag) *flag |= VM_CALL_ARGS_SPLAT; return INT2FIX(1); } case NODE_ARGSCAT: case NODE_ARGSPUSH: { - int next_is_list = (nd_type(argn->nd_head) == NODE_LIST); + int next_is_list = (nd_type_p(argn->nd_head, NODE_LIST)); VALUE argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL); - if (nd_type(argn->nd_body) == NODE_LIST) { + if (nd_type_p(argn->nd_body, NODE_LIST)) { /* This branch is needed to avoid "newarraykwsplat" [Bug #16442] */ int rest_len = compile_args(iseq, args, argn->nd_body, NULL, NULL); - ADD_INSN1(args, nd_line(argn), newarray, INT2FIX(rest_len)); + ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); } else { NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body)); @@ -5032,20 +5551,20 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, if (check_keyword(argn->nd_body)) *flag |= VM_CALL_KW_SPLAT; } - if (nd_type(argn) == NODE_ARGSCAT) { + if (nd_type_p(argn, NODE_ARGSCAT)) { if (next_is_list) { - ADD_INSN1(args, nd_line(argn), splatarray, Qtrue); + ADD_INSN1(args, argn, splatarray, Qtrue); return INT2FIX(FIX2INT(argc) + 1); } else { - ADD_INSN1(args, nd_line(argn), splatarray, Qfalse); - ADD_INSN(args, nd_line(argn), concatarray); + ADD_INSN1(args, argn, splatarray, Qfalse); + ADD_INSN(args, argn, concatarray); return argc; } } else { - ADD_INSN1(args, nd_line(argn), newarray, INT2FIX(1)); - ADD_INSN(args, nd_line(argn), concatarray); + ADD_INSN1(args, argn, newarray, INT2FIX(1)); + ADD_INSN(args, argn, concatarray); return argc; } } @@ -5063,16 +5582,16 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, static VALUE setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, - unsigned int *flag, struct rb_call_info_kw_arg **keywords) + unsigned int *flag, struct rb_callinfo_kwarg **keywords) { VALUE ret; - if (argn && nd_type(argn) == NODE_BLOCK_PASS) { + 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)); *flag |= VM_CALL_ARGS_BLOCKARG; - ret = setup_args_core(iseq, args, argn->nd_head, 0, flag, keywords); if (LIST_INSN_SIZE_ONE(arg_block)) { LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block); @@ -5081,8 +5600,10 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, if (iobj->insn_id == BIN(getblockparam)) { iobj->insn_id = BIN(getblockparamproxy); } + dup_rest = 0; } } + ret = setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords); ADD_SEQ(args, arg_block); } else { @@ -5099,8 +5620,8 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *ptr) VALUE argc = INT2FIX(0); const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(iseq->body->parent_iseq), ISEQ_TYPE_BLOCK, line); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_CALL_WITH_BLOCK(ret, line, id_core_set_postexe, argc, block); + 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); } @@ -5111,25 +5632,26 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE const NODE *vars; LINK_ELEMENT *last; int line = nd_line(node); + const NODE *line_node = node; LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line); #if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0) - ADD_INSN1(ret, line, getglobal, ((VALUE)rb_global_entry(idBACKREF) | 1)); + ADD_INSN1(ret, line_node, getglobal, ID2SYM(idBACKREF)); #else - ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, INT2FIX(0)); + ADD_INSN2(ret, line_node, getspecial, INT2FIX(1) /* '~' */, INT2FIX(0)); #endif - ADD_INSN(ret, line, dup); - ADD_INSNL(ret, line, branchunless, fail_label); + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchunless, fail_label); for (vars = node; vars; vars = vars->nd_next) { INSN *cap; if (vars->nd_next) { - ADD_INSN(ret, line, dup); + ADD_INSN(ret, line_node, dup); } last = ret->last; NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head)); last = last->next; /* putobject :var */ - cap = new_insn_send(iseq, line, idAREF, INT2FIX(1), + cap = new_insn_send(iseq, 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 @@ -5138,11 +5660,11 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE DECL_ANCHOR(nom); INIT_ANCHOR(nom); - ADD_INSNL(nom, line, jump, end_label); + ADD_INSNL(nom, line_node, jump, end_label); ADD_LABEL(nom, fail_label); # if 0 /* $~ must be MatchData or nil */ - ADD_INSN(nom, line, pop); - ADD_INSN(nom, line, putnil); + ADD_INSN(nom, line_node, pop); + ADD_INSN(nom, line_node, putnil); # endif ADD_LABEL(nom, end_label); (nom->last->next = cap->link.next)->prev = nom->last; @@ -5151,9 +5673,9 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE } #endif } - ADD_INSNL(ret, line, jump, end_label); + ADD_INSNL(ret, line_node, jump, end_label); ADD_LABEL(ret, fail_label); - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); for (vars = node; vars; vars = vars->nd_next) { last = ret->last; NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head)); @@ -5165,9 +5687,17 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE } static int -number_literal_p(const NODE *n) +optimizable_range_item_p(const NODE *n) { - return (n && nd_type(n) == NODE_LIT && RB_INTEGER_TYPE_P(n->nd_lit)); + if (!n) return FALSE; + switch (nd_type(n)) { + case NODE_LIT: + return RB_INTEGER_TYPE_P(n->nd_lit); + case NODE_NIL: + return TRUE; + default: + return FALSE; + } } static int @@ -5178,16 +5708,13 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int const NODE *const node_else = type == NODE_IF ? node->nd_else : node->nd_body; const int line = nd_line(node); - const int lineno = nd_first_lineno(node); - const int column = nd_first_column(node); - const int last_lineno = nd_last_lineno(node); - const int last_column = nd_last_column(node); + const NODE *line_node = node; DECL_ANCHOR(cond_seq); DECL_ANCHOR(then_seq); DECL_ANCHOR(else_seq); LABEL *then_label, *else_label, *end_label; VALUE branches = Qfalse; - int ci_size, ci_kw_size; + int ci_size; VALUE catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary; long catch_table_size = NIL_P(catch_table) ? 0 : RARRAY_LEN(catch_table); @@ -5202,12 +5729,10 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int then_label, else_label); ci_size = body->ci_size; - ci_kw_size = body->ci_kw_size; CHECK(COMPILE_(then_seq, "then", node_body, popped)); catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary; if (!then_label->refcnt) { body->ci_size = ci_size; - body->ci_kw_size = ci_kw_size; if (!NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size); } else { @@ -5215,12 +5740,10 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int } ci_size = body->ci_size; - ci_kw_size = body->ci_kw_size; CHECK(COMPILE_(else_seq, "else", node_else, popped)); catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary; if (!else_label->refcnt) { body->ci_size = ci_size; - body->ci_kw_size = ci_kw_size; if (!NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size); } else { @@ -5230,22 +5753,24 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int ADD_SEQ(ret, cond_seq); if (then_label->refcnt && else_label->refcnt) { - DECL_BRANCH_BASE(branches, lineno, column, last_lineno, last_column, type == NODE_IF ? "if" : "unless"); + branches = decl_branch_base(iseq, node, type == NODE_IF ? "if" : "unless"); } if (then_label->refcnt) { ADD_LABEL(ret, then_label); if (else_label->refcnt) { - ADD_TRACE_BRANCH_COVERAGE( + add_trace_branch_coverage( + iseq, ret, - node_body ? nd_first_lineno(node_body) : lineno, - node_body ? nd_first_column(node_body) : column, - node_body ? nd_last_lineno(node_body) : last_lineno, - node_body ? nd_last_column(node_body) : last_column, + node_body ? node_body : node, + 0, type == NODE_IF ? "then" : "else", branches); end_label = NEW_LABEL(line); - ADD_INSNL(then_seq, line, jump, end_label); + ADD_INSNL(then_seq, line_node, jump, end_label); + if (!popped) { + ADD_INSN(then_seq, line_node, pop); + } } ADD_SEQ(ret, then_seq); } @@ -5253,12 +5778,11 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int if (else_label->refcnt) { ADD_LABEL(ret, else_label); if (then_label->refcnt) { - ADD_TRACE_BRANCH_COVERAGE( + add_trace_branch_coverage( + iseq, ret, - node_else ? nd_first_lineno(node_else) : lineno, - node_else ? nd_first_column(node_else) : column, - node_else ? nd_last_lineno(node_else) : last_lineno, - node_else ? nd_last_column(node_else) : last_column, + node_else ? node_else : node, + 1, type == NODE_IF ? "else" : "then", branches); } @@ -5283,9 +5807,11 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod DECL_ANCHOR(cond_seq); int only_special_literals = 1; VALUE literals = rb_hash_new(); - int line, lineno, column, last_lineno, last_column; + int line; enum node_type type; + const NODE *line_node; VALUE branches = Qfalse; + int branch_id = 0; INIT_ANCHOR(head); INIT_ANCHOR(body_seq); @@ -5295,16 +5821,13 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod CHECK(COMPILE(head, "case base", node->nd_head)); - DECL_BRANCH_BASE(branches, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "case"); + branches = decl_branch_base(iseq, node, "case"); node = node->nd_body; EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG); type = nd_type(node); line = nd_line(node); - lineno = nd_first_lineno(node); - column = nd_first_column(node); - last_lineno = nd_last_lineno(node); - last_column = nd_last_column(node); + line_node = node; endlabel = NEW_LABEL(line); elselabel = NEW_LABEL(line); @@ -5316,17 +5839,16 @@ 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, pop); - ADD_TRACE_BRANCH_COVERAGE( + ADD_INSN(body_seq, line_node, pop); + add_trace_branch_coverage( + iseq, body_seq, - node->nd_body ? nd_first_lineno(node->nd_body) : lineno, - node->nd_body ? nd_first_column(node->nd_body) : column, - node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno, - node->nd_body ? nd_last_column(node->nd_body) : last_column, + node->nd_body ? node->nd_body : node, + branch_id++, "when", branches); CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped)); - ADD_INSNL(body_seq, line, jump, endlabel); + ADD_INSNL(body_seq, line_node, jump, endlabel); vals = node->nd_head; if (vals) { @@ -5355,33 +5877,30 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod } type = nd_type(node); line = nd_line(node); - lineno = nd_first_lineno(node); - column = nd_first_column(node); - last_lineno = nd_last_lineno(node); - last_column = nd_last_column(node); + line_node = node; } /* else */ if (node) { ADD_LABEL(cond_seq, elselabel); - ADD_INSN(cond_seq, line, pop); - ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "else", branches); + ADD_INSN(cond_seq, line_node, pop); + add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches); CHECK(COMPILE_(cond_seq, "else", node, popped)); - ADD_INSNL(cond_seq, line, jump, endlabel); + ADD_INSNL(cond_seq, line_node, jump, endlabel); } else { debugs("== else (implicit)\n"); ADD_LABEL(cond_seq, elselabel); - ADD_INSN(cond_seq, nd_line(orig_node), pop); - ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "else", branches); + ADD_INSN(cond_seq, orig_node, pop); + add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches); if (!popped) { - ADD_INSN(cond_seq, nd_line(orig_node), putnil); + ADD_INSN(cond_seq, orig_node, putnil); } - ADD_INSNL(cond_seq, nd_line(orig_node), jump, endlabel); + ADD_INSNL(cond_seq, orig_node, jump, endlabel); } if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { - ADD_INSN(ret, nd_line(orig_node), dup); - ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel); + ADD_INSN(ret, orig_node, dup); + ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel); RB_OBJ_WRITTEN(iseq, Qundef, literals); LABEL_REF(elselabel); } @@ -5401,30 +5920,26 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no LABEL *endlabel; DECL_ANCHOR(body_seq); VALUE branches = Qfalse; + int branch_id = 0; - DECL_BRANCH_BASE(branches, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "case"); + branches = decl_branch_base(iseq, orig_node, "case"); INIT_ANCHOR(body_seq); endlabel = NEW_LABEL(nd_line(node)); - while (node && nd_type(node) == NODE_WHEN) { + while (node && nd_type_p(node, NODE_WHEN)) { const int line = nd_line(node); - const int lineno = nd_first_lineno(node); - const int column = nd_first_column(node); - const int last_lineno = nd_last_lineno(node); - const int last_column = nd_last_column(node); LABEL *l1 = NEW_LABEL(line); ADD_LABEL(body_seq, l1); - ADD_TRACE_BRANCH_COVERAGE( + add_trace_branch_coverage( + iseq, body_seq, - node->nd_body ? nd_first_lineno(node->nd_body) : lineno, - node->nd_body ? nd_first_column(node->nd_body) : column, - node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno, - node->nd_body ? nd_last_column(node->nd_body) : last_column, + node->nd_body ? node->nd_body : node, + branch_id++, "when", branches); CHECK(COMPILE_(body_seq, "when", node->nd_body, popped)); - ADD_INSNL(body_seq, line, jump, endlabel); + ADD_INSNL(body_seq, node, jump, endlabel); vals = node->nd_head; if (!vals) { @@ -5445,10 +5960,10 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no case NODE_SPLAT: case NODE_ARGSCAT: case NODE_ARGSPUSH: - ADD_INSN(ret, nd_line(vals), putnil); + ADD_INSN(ret, vals, putnil); CHECK(COMPILE(ret, "when2/cond splat", vals)); - ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); - ADD_INSNL(ret, nd_line(vals), branchif, l1); + ADD_INSN1(ret, vals, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); + ADD_INSNL(ret, vals, branchif, l1); break; default: UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG); @@ -5456,26 +5971,40 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no node = node->nd_next; } /* else */ - ADD_TRACE_BRANCH_COVERAGE( + add_trace_branch_coverage( + iseq, ret, - node ? nd_first_lineno(node) : nd_first_lineno(orig_node), - node ? nd_first_column(node) : nd_first_column(orig_node), - node ? nd_last_lineno(node) : nd_last_lineno(orig_node), - node ? nd_last_column(node) : nd_last_column(orig_node), + node ? node : orig_node, + branch_id, "else", branches); CHECK(COMPILE_(ret, "else", node, popped)); - ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); + ADD_INSNL(ret, orig_node, jump, endlabel); ADD_SEQ(ret, body_seq); ADD_LABEL(ret, endlabel); return COMPILE_OK; } +static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache); + +static int iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *match_failed, bool in_single_pattern, int base_index); +static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, bool in_single_pattern, int base_index, bool use_deconstructed_cache); +static int iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, int base_index); +static int iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, VALUE pattern_length, int base_index); +static int iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int base_index); + +#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0 +#define CASE3_BI_OFFSET_ERROR_STRING 1 +#define CASE3_BI_OFFSET_KEY_ERROR_P 2 +#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE 3 +#define CASE3_BI_OFFSET_KEY_ERROR_KEY 4 + static int -iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int in_alt_pattern) +iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache) { const int line = nd_line(node); + const NODE *line_node = node; switch (nd_type(node)) { case NODE_ARYPTN: { @@ -5525,13 +6054,11 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c * goto match_failed * end * end - * true - * goto fin + * goto matched * type_error: * FrozenCore.raise TypeError * match_failed: - * false - * fin: + * goto unmatched */ struct rb_ary_pattern_info *apinfo = node->nd_apinfo; const NODE *args = apinfo->pre_args; @@ -5542,110 +6069,276 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c 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)); - LABEL *match_failed, *type_error, *fin; + LABEL *match_failed, *type_error, *deconstruct, *deconstructed; int i; match_failed = NEW_LABEL(line); type_error = NEW_LABEL(line); - fin = NEW_LABEL(line); + deconstruct = NEW_LABEL(line); + deconstructed = NEW_LABEL(line); if (use_rest_num) { - ADD_INSN1(ret, line, putobject, INT2FIX(0)); /* allocate stack for rest_num */ - ADD_INSN(ret, line, swap); - } - - if (node->nd_pconst) { - ADD_INSN(ret, line, dup); - CHECK(COMPILE(ret, "constant", node->nd_pconst)); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for rest_num */ + ADD_INSN(ret, line_node, swap); + if (base_index) { + base_index++; + } } - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, ID2SYM(rb_intern("deconstruct"))); - ADD_SEND(ret, line, idRespond_to, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, match_failed); + CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index)); - ADD_SEND(ret, line, rb_intern("deconstruct"), INT2FIX(0)); + CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache)); - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, checktype, INT2FIX(T_ARRAY)); - ADD_INSNL(ret, line, branchunless, type_error); - - ADD_INSN(ret, line, dup); - ADD_SEND(ret, line, idLength, INT2FIX(0)); - ADD_INSN1(ret, line, putobject, INT2FIX(min_argc)); - ADD_SEND(ret, line, apinfo->rest_arg ? idGE : idEq, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, match_failed); + 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) + 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+)") : + rb_fstring_lit("%p length mismatch (given %p, expected %p)"), + INT2FIX(min_argc), base_index + 1 /* (1) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); for (i = 0; i < pre_args_num; i++) { - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(i)); - ADD_SEND(ret, line, idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern); + 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; - ADD_INSNL(ret, line, branchunless, match_failed); } if (apinfo->rest_arg) { if (NODE_NAMED_REST_P(apinfo->rest_arg)) { - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(pre_args_num)); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - ADD_SEND(ret, line, idLength, INT2FIX(0)); - ADD_INSN1(ret, line, putobject, INT2FIX(min_argc)); - ADD_SEND(ret, line, idMINUS, INT2FIX(1)); - ADD_INSN1(ret, line, setn, INT2FIX(4)); - ADD_SEND(ret, line, idAREF, INT2FIX(2)); - - iseq_compile_pattern_each(iseq, ret, apinfo->rest_arg, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, putobject, INT2FIX(pre_args_num)); + ADD_INSN1(ret, line_node, topn, INT2FIX(1)); + ADD_SEND(ret, line_node, idLength, INT2FIX(0)); + ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc)); + ADD_SEND(ret, line_node, idMINUS, INT2FIX(1)); + 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)); } else { if (post_args_num > 0) { - ADD_INSN(ret, line, dup); - ADD_SEND(ret, line, idLength, INT2FIX(0)); - ADD_INSN1(ret, line, putobject, INT2FIX(min_argc)); - ADD_SEND(ret, line, idMINUS, INT2FIX(1)); - ADD_INSN1(ret, line, setn, INT2FIX(2)); - ADD_INSN(ret, line, pop); + 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, idMINUS, INT2FIX(1)); + ADD_INSN1(ret, line_node, setn, INT2FIX(2)); + ADD_INSN(ret, line_node, pop); } } } args = apinfo->post_args; for (i = 0; i < post_args_num; i++) { - ADD_INSN(ret, line, dup); + ADD_INSN(ret, line_node, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(pre_args_num + i)); - ADD_INSN1(ret, line, topn, INT2FIX(3)); - ADD_SEND(ret, line, idPLUS, INT2FIX(1)); + ADD_INSN1(ret, line_node, putobject, INT2FIX(pre_args_num + i)); + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); + ADD_SEND(ret, line_node, idPLUS, INT2FIX(1)); - ADD_SEND(ret, line, idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern); + 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; - ADD_INSNL(ret, line, branchunless, match_failed); } - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); + if (use_rest_num) { + ADD_INSN(ret, line_node, pop); + } + ADD_INSNL(ret, line_node, jump, matched); + ADD_INSN(ret, line_node, putnil); if (use_rest_num) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, putnil); } - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); ADD_LABEL(ret, type_error); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, line, putobject, rb_eTypeError); - ADD_INSN1(ret, line, putobject, rb_fstring_lit("deconstruct must return Array")); - ADD_SEND(ret, line, id_core_raise, INT2FIX(2)); + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, rb_eTypeError); + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("deconstruct must return Array")); + ADD_SEND(ret, line_node, id_core_raise, INT2FIX(2)); + ADD_INSN(ret, line_node, pop); ADD_LABEL(ret, match_failed); - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); if (use_rest_num) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } - ADD_INSN1(ret, line, putobject, Qfalse); - ADD_LABEL(ret, fin); + ADD_INSNL(ret, line_node, jump, unmatched); + + break; + } + case NODE_FNDPTN: { + /* + * if pattern.has_constant_node? + * unless pattern.constant === obj + * goto match_failed + * end + * end + * unless obj.respond_to?(:deconstruct) + * goto match_failed + * end + * d = obj.deconstruct + * unless Array === d + * goto type_error + * end + * unless d.length >= pattern.args_num + * goto match_failed + * end + * + * begin + * len = d.length + * limit = d.length - pattern.args_num + * i = 0 + * while i <= limit + * if pattern.args_num.times.all? {|j| pattern.args[j].match?(d[i+j]) } + * if pattern.has_pre_rest_arg_id + * unless pattern.pre_rest_arg.match?(d[0, i]) + * goto find_failed + * end + * end + * if pattern.has_post_rest_arg_id + * unless pattern.post_rest_arg.match?(d[i+pattern.args_num, len]) + * goto find_failed + * end + * end + * goto find_succeeded + * end + * i+=1 + * end + * find_failed: + * goto match_failed + * find_succeeded: + * end + * + * goto matched + * type_error: + * FrozenCore.raise TypeError + * 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; + + LABEL *match_failed, *type_error, *deconstruct, *deconstructed; + match_failed = NEW_LABEL(line); + type_error = NEW_LABEL(line); + deconstruct = NEW_LABEL(line); + deconstructed = NEW_LABEL(line); + + CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index)); + + CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache)); + + ADD_INSN(ret, line_node, dup); + ADD_SEND(ret, line_node, idLength, INT2FIX(0)); + ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num)); + ADD_SEND(ret, line_node, idGE, INT2FIX(1)); // (1) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node, rb_fstring_lit("%p length mismatch (given %p, expected %p+)"), INT2FIX(args_num), base_index + 1 /* (1) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); + + { + LABEL *while_begin = NEW_LABEL(nd_line(node)); + LABEL *next_loop = NEW_LABEL(nd_line(node)); + LABEL *find_succeeded = NEW_LABEL(line); + LABEL *find_failed = NEW_LABEL(nd_line(node)); + int j; + + ADD_INSN(ret, line_node, dup); /* allocate stack for len */ + ADD_SEND(ret, line_node, idLength, INT2FIX(0)); // (2) + + ADD_INSN(ret, line_node, dup); /* allocate stack for limit */ + ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num)); + ADD_SEND(ret, line_node, idMINUS, INT2FIX(1)); // (3) + + ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for i */ // (4) + + ADD_LABEL(ret, while_begin); + + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, topn, INT2FIX(2)); + ADD_SEND(ret, line_node, idLE, INT2FIX(1)); + ADD_INSNL(ret, line_node, branchunless, find_failed); + + for (j = 0; j < args_num; j++) { + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); + ADD_INSN1(ret, line_node, topn, INT2FIX(1)); + if (j != 0) { + ADD_INSN1(ret, line_node, putobject, INT2FIX(j)); + ADD_SEND(ret, line_node, idPLUS, INT2FIX(1)); + } + 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; + } + + if (NODE_NAMED_REST_P(fpinfo->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)); + } + if (NODE_NAMED_REST_P(fpinfo->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)); + } + ADD_INSNL(ret, line_node, jump, find_succeeded); + + ADD_LABEL(ret, next_loop); + ADD_INSN1(ret, line_node, putobject, INT2FIX(1)); + ADD_SEND(ret, line_node, idPLUS, INT2FIX(1)); + ADD_INSNL(ret, line_node, jump, while_begin); + + ADD_LABEL(ret, find_failed); + ADD_INSN1(ret, line_node, adjuststack, INT2FIX(3)); + if (in_single_pattern) { + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("%p does not match to find pattern")); + ADD_INSN1(ret, line_node, topn, INT2FIX(2)); + ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(2)); // (8) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (8) */)); // (9) + + ADD_INSN1(ret, line_node, putobject, Qfalse); + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (8), (9) */)); + + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + } + ADD_INSNL(ret, line_node, jump, match_failed); + ADD_INSN1(ret, line_node, dupn, INT2FIX(3)); + + ADD_LABEL(ret, find_succeeded); + ADD_INSN1(ret, line_node, adjuststack, INT2FIX(3)); + } + + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, matched); + ADD_INSN(ret, line_node, putnil); + + ADD_LABEL(ret, type_error); + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, rb_eTypeError); + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("deconstruct must return Array")); + ADD_SEND(ret, line_node, id_core_raise, INT2FIX(2)); + ADD_INSN(ret, line_node, pop); + + ADD_LABEL(ret, match_failed); + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, unmatched); break; } @@ -5703,20 +6396,17 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c * end * end * end - * true - * goto fin + * goto matched * type_error: * FrozenCore.raise TypeError * match_failed: - * false - * fin: + * goto unmatched */ - LABEL *match_failed, *type_error, *fin; + LABEL *match_failed, *type_error; VALUE keys = Qnil; match_failed = NEW_LABEL(line); type_error = NEW_LABEL(line); - fin = NEW_LABEL(line); if (node->nd_pkwargs && !node->nd_pkwrestarg) { const NODE *kw_args = node->nd_pkwargs->nd_head; @@ -5727,33 +6417,31 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } } - if (node->nd_pconst) { - ADD_INSN(ret, line, dup); - CHECK(COMPILE(ret, "constant", node->nd_pconst)); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); - ADD_INSNL(ret, line, branchunless, match_failed); - } + CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index)); - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, ID2SYM(rb_intern("deconstruct_keys"))); - ADD_SEND(ret, line, idRespond_to, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, putobject, ID2SYM(rb_intern("deconstruct_keys"))); + ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1)); // (1) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p does not respond to #deconstruct_keys"), base_index + 1 /* (1) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); if (NIL_P(keys)) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } else { - ADD_INSN1(ret, line, duparray, keys); + ADD_INSN1(ret, line_node, duparray, keys); RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_hide(keys)); } - ADD_SEND(ret, line, rb_intern("deconstruct_keys"), INT2FIX(1)); + ADD_SEND(ret, line_node, rb_intern("deconstruct_keys"), INT2FIX(1)); // (2) - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, checktype, INT2FIX(T_HASH)); - ADD_INSNL(ret, line, branchunless, type_error); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, checktype, INT2FIX(T_HASH)); + ADD_INSNL(ret, line_node, branchunless, type_error); if (node->nd_pkwrestarg) { - ADD_SEND(ret, line, rb_intern("dup"), INT2FIX(0)); + ADD_SEND(ret, line_node, rb_intern("dup"), INT2FIX(0)); } if (node->nd_pkwargs) { @@ -5770,60 +6458,83 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c NODE *value_node = args->nd_next->nd_head; VALUE key; - if (nd_type(key_node) != NODE_LIT) { + if (!nd_type_p(key_node, NODE_LIT)) { UNKNOWN_NODE("NODE_IN", key_node, COMPILE_NG); } key = key_node->nd_lit; - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, key); - ADD_SEND(ret, line, rb_intern("key?"), INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, putobject, key); + ADD_SEND(ret, line_node, rb_intern("key?"), INT2FIX(1)); // (3) + if (in_single_pattern) { + LABEL *match_succeeded; + match_succeeded = NEW_LABEL(line); + + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchif, match_succeeded); + + ADD_INSN1(ret, line_node, putobject, rb_str_freeze(rb_sprintf("key not found: %+"PRIsVALUE, key))); // (4) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 2 /* (3), (4) */)); + ADD_INSN1(ret, line_node, putobject, Qtrue); // (5) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 3 /* (3), (4), (5) */)); + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); // (6) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4 /* (3), (4), (5), (6) */)); + ADD_INSN1(ret, line_node, putobject, key); // (7) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_KEY + 5 /* (3), (4), (5), (6), (7) */)); + + ADD_INSN1(ret, line_node, adjuststack, INT2FIX(4)); - ADD_INSN(match_values, line, dup); - ADD_INSN1(match_values, line, putobject, key); - ADD_SEND(match_values, line, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, match_values, value_node, in_alt_pattern); - ADD_INSNL(match_values, line, branchunless, match_failed); + ADD_LABEL(ret, match_succeeded); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); + + 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) + 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; } ADD_SEQ(ret, match_values); } } else { - ADD_INSN(ret, line, dup); - ADD_SEND(ret, line, idEmptyP, INT2FIX(0)); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN(ret, line_node, dup); + ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (9) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p is not empty"), base_index + 1 /* (9) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); } if (node->nd_pkwrestarg) { if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) { - ADD_INSN(ret, line, dup); - ADD_SEND(ret, line, idEmptyP, INT2FIX(0)); - ADD_INSNL(ret, line, branchunless, match_failed); + ADD_INSN(ret, line_node, dup); + ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (10) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("rest of %p is not empty"), base_index + 1 /* (10) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); } else { - ADD_INSN(ret, line, dup); - iseq_compile_pattern_each(iseq, ret, node->nd_pkwrestarg, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + 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)); } } - ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, matched); + ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, type_error); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, line, putobject, rb_eTypeError); - ADD_INSN1(ret, line, putobject, rb_fstring_lit("deconstruct_keys must return Hash")); - ADD_SEND(ret, line, id_core_raise, INT2FIX(2)); + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, rb_eTypeError); + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("deconstruct_keys must return Hash")); + ADD_SEND(ret, line_node, id_core_raise, INT2FIX(2)); + ADD_INSN(ret, line_node, pop); ADD_LABEL(ret, match_failed); - ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qfalse); - - ADD_LABEL(ret, fin); + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, unmatched); break; } case NODE_LIT: @@ -5840,14 +6551,26 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_CONST: case NODE_LVAR: case NODE_DVAR: + case NODE_IVAR: + case NODE_CVAR: + case NODE_GVAR: case NODE_TRUE: case NODE_FALSE: case NODE_SELF: case NODE_NIL: case NODE_COLON2: case NODE_COLON3: - CHECK(COMPILE(ret, "case in literal", node)); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); + case NODE_BEGIN: + CHECK(COMPILE(ret, "case in literal", node)); // (1) + if (in_single_pattern) { + ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); + } + ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); // (2) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 2 /* (1), (2) */)); + } + ADD_INSNL(ret, line_node, branchif, matched); + ADD_INSNL(ret, line_node, jump, unmatched); break; case NODE_LASGN: { struct rb_iseq_constant_body *const body = iseq->body; @@ -5863,12 +6586,11 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } } - ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq)); - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_SETLOCAL(ret, line_node, idx, get_lvar_level(iseq)); + ADD_INSNL(ret, line_node, jump, matched); break; } - case NODE_DASGN: - case NODE_DASGN_CURR: { + case NODE_DASGN: { int idx, lv, ls; ID id = node->nd_vid; @@ -5884,60 +6606,70 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } if (idx < 0) { - COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")", + COMPILE_ERROR(ERROR_ARGS "NODE_DASGN: unknown id (%"PRIsVALUE")", rb_id2str(id)); return COMPILE_NG; } - ADD_SETLOCAL(ret, line, ls - idx, lv); - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_SETLOCAL(ret, line_node, ls - idx, lv); + ADD_INSNL(ret, line_node, jump, matched); break; } case NODE_IF: case NODE_UNLESS: { - LABEL *match_failed, *fin; - match_failed = NEW_LABEL(line); - fin = NEW_LABEL(line); - iseq_compile_pattern_each(iseq, ret, node->nd_body, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + 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)); - if (nd_type(node) == NODE_IF) { - ADD_INSNL(ret, line, branchunless, match_failed); + if (in_single_pattern) { + LABEL *match_succeeded; + match_succeeded = NEW_LABEL(line); + + ADD_INSN(ret, line_node, dup); + if (nd_type_p(node, NODE_IF)) { + ADD_INSNL(ret, line_node, branchif, match_succeeded); + } + else { + ADD_INSNL(ret, line_node, branchunless, match_succeeded); + } + + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("guard clause does not return true")); // (1) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2) + ADD_INSN1(ret, line_node, putobject, Qfalse); + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */)); + + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + + ADD_LABEL(ret, match_succeeded); + } + if (nd_type_p(node, NODE_IF)) { + ADD_INSNL(ret, line_node, branchunless, match_failed); } else { - ADD_INSNL(ret, line, branchif, match_failed); + ADD_INSNL(ret, line_node, branchif, match_failed); } - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); - - ADD_LABEL(ret, match_failed); - ADD_INSN1(ret, line, putobject, Qfalse); - - ADD_LABEL(ret, fin); + ADD_INSNL(ret, line_node, jump, matched); break; } case NODE_HASH: { NODE *n; - LABEL *match_failed, *fin; + LABEL *match_failed; match_failed = NEW_LABEL(line); - fin = NEW_LABEL(line); n = node->nd_head; - if (! (nd_type(n) == NODE_LIST && n->nd_alen == 2)) { + if (! (nd_type_p(n, NODE_LIST) && n->nd_alen == 2)) { COMPILE_ERROR(ERROR_ARGS "unexpected node"); return COMPILE_NG; } - ADD_INSN(ret, line, dup); - iseq_compile_pattern_each(iseq, ret, n->nd_head, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); - iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, in_alt_pattern); - ADD_INSNL(ret, line, jump, fin); + 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)); + ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, match_failed); - ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qfalse); - - ADD_LABEL(ret, fin); + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, unmatched); break; } case NODE_OR: { @@ -5945,17 +6677,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c match_succeeded = NEW_LABEL(line); fin = NEW_LABEL(line); - ADD_INSN(ret, line, dup); - iseq_compile_pattern_each(iseq, ret, node->nd_1st, TRUE); - ADD_INSNL(ret, line, branchif, match_succeeded); - iseq_compile_pattern_each(iseq, ret, node->nd_2nd, TRUE); - ADD_INSNL(ret, line, jump, fin); - + 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)); ADD_LABEL(ret, match_succeeded); - ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qtrue); - + 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)); break; } default: @@ -5965,62 +6694,275 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } static int -compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped) +iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache) { - const NODE *pattern; - const NODE *node = orig_node; - LABEL *endlabel, *elselabel; - DECL_ANCHOR(head); - DECL_ANCHOR(body_seq); - DECL_ANCHOR(cond_seq); - int line, lineno, column, last_lineno, last_column; - enum node_type type; - VALUE branches = 0; + LABEL *fin = NEW_LABEL(nd_line(node)); + CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache)); + ADD_LABEL(ret, fin); + return COMPILE_OK; +} - INIT_ANCHOR(head); - INIT_ANCHOR(body_seq); - INIT_ANCHOR(cond_seq); +static int +iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *match_failed, bool in_single_pattern, int base_index) +{ + const NODE *line_node = node; - CHECK(COMPILE(head, "case base", node->nd_head)); + if (node->nd_pconst) { + ADD_INSN(ret, line_node, dup); // (1) + CHECK(COMPILE(ret, "constant", node->nd_pconst)); // (2) + if (in_single_pattern) { + ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); + } + ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); // (3) + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 3 /* (1), (2), (3) */)); + } + ADD_INSNL(ret, line_node, branchunless, match_failed); + } + return COMPILE_OK; +} - DECL_BRANCH_BASE(branches, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "case"); - node = node->nd_body; - EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG); - type = nd_type(node); +static int +iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, bool in_single_pattern, int base_index, bool use_deconstructed_cache) +{ + const NODE *line_node = node; + + // NOTE: this optimization allows us to re-use the #deconstruct value + // (or its absence). + if (use_deconstructed_cache) { + // If value is nil then we haven't tried to deconstruct + ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE)); + ADD_INSNL(ret, line_node, branchnil, deconstruct); + + // If false then the value is not deconstructable + ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE)); + ADD_INSNL(ret, line_node, branchunless, match_failed); + + // Drop value, add deconstructed to the stack and jump + ADD_INSN(ret, line_node, pop); // (1) + ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE - 1 /* (1) */)); + ADD_INSNL(ret, line_node, jump, deconstructed); + } + else { + ADD_INSNL(ret, line_node, jump, deconstruct); + } + + ADD_LABEL(ret, deconstruct); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, putobject, ID2SYM(rb_intern("deconstruct"))); + ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1)); // (2) + + // Cache the result of respond_to? (in case it's false is stays there, if true - it's overwritten after #deconstruct) + if (use_deconstructed_cache) { + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE + 1 /* (2) */)); + } + + if (in_single_pattern) { + CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p does not respond to #deconstruct"), base_index + 1 /* (2) */)); + } + + ADD_INSNL(ret, line_node, branchunless, match_failed); + + ADD_SEND(ret, line_node, rb_intern("deconstruct"), INT2FIX(0)); + + // Cache the result (if it's cacheable - currently, only top-level array patterns) + if (use_deconstructed_cache) { + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE)); + } + + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, checktype, INT2FIX(T_ARRAY)); + ADD_INSNL(ret, line_node, branchunless, type_error); + + ADD_LABEL(ret, deconstructed); + + return COMPILE_OK; +} + +static int +iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, int base_index) +{ + /* + * if match_succeeded? + * goto match_succeeded + * end + * error_string = FrozenCore.sprintf(errmsg, matchee) + * key_error_p = false + * match_succeeded: + */ + const int line = nd_line(node); + const NODE *line_node = node; + LABEL *match_succeeded = NEW_LABEL(line); + + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchif, match_succeeded); + + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, errmsg); + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); + ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(2)); // (1) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2) + + ADD_INSN1(ret, line_node, putobject, Qfalse); + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */)); + + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + ADD_LABEL(ret, match_succeeded); + + return COMPILE_OK; +} + +static int +iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, VALUE pattern_length, int base_index) +{ + /* + * if match_succeeded? + * goto match_succeeded + * end + * error_string = FrozenCore.sprintf(errmsg, matchee, matchee.length, pat.length) + * key_error_p = false + * match_succeeded: + */ + const int line = nd_line(node); + const NODE *line_node = node; + LABEL *match_succeeded = NEW_LABEL(line); + + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchif, match_succeeded); + + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, errmsg); + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); + ADD_INSN(ret, line_node, dup); + ADD_SEND(ret, line_node, idLength, INT2FIX(0)); + ADD_INSN1(ret, line_node, putobject, pattern_length); + ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(4)); // (1) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2) + + ADD_INSN1(ret, line_node, putobject, Qfalse); + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2/* (1), (2) */)); + + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + ADD_LABEL(ret, match_succeeded); + + return COMPILE_OK; +} + +static int +iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int base_index) +{ + /* + * if match_succeeded? + * goto match_succeeded + * end + * error_string = FrozenCore.sprintf("%p === %p does not return true", pat, matchee) + * key_error_p = false + * match_succeeded: + */ + const int line = nd_line(node); + const NODE *line_node = node; + LABEL *match_succeeded = NEW_LABEL(line); + + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchif, match_succeeded); + + ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("%p === %p does not return true")); + ADD_INSN1(ret, line_node, topn, INT2FIX(3)); + ADD_INSN1(ret, line_node, topn, INT2FIX(5)); + ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(3)); // (1) + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2) + + ADD_INSN1(ret, line_node, putobject, Qfalse); + ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */)); + + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + + ADD_LABEL(ret, match_succeeded); + ADD_INSN1(ret, line_node, setn, INT2FIX(2)); + ADD_INSN(ret, line_node, pop); + ADD_INSN(ret, line_node, pop); + + return COMPILE_OK; +} + +static int +compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped) +{ + const NODE *pattern; + const NODE *node = orig_node; + LABEL *endlabel, *elselabel; + DECL_ANCHOR(head); + DECL_ANCHOR(body_seq); + DECL_ANCHOR(cond_seq); + int line; + enum node_type type; + const NODE *line_node; + VALUE branches = 0; + int branch_id = 0; + bool single_pattern; + + INIT_ANCHOR(head); + INIT_ANCHOR(body_seq); + INIT_ANCHOR(cond_seq); + + branches = decl_branch_base(iseq, node, "case"); + + node = node->nd_body; + EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG); + type = nd_type(node); line = nd_line(node); - lineno = nd_first_lineno(node); - column = nd_first_column(node); - last_lineno = nd_last_lineno(node); - last_column = nd_last_column(node); + line_node = node; + single_pattern = !node->nd_next; endlabel = NEW_LABEL(line); elselabel = NEW_LABEL(line); + if (single_pattern) { + /* allocate stack for ... */ + ADD_INSN(head, line_node, putnil); /* key_error_key */ + ADD_INSN(head, line_node, putnil); /* key_error_matchee */ + ADD_INSN1(head, line_node, putobject, Qfalse); /* key_error_p */ + ADD_INSN(head, line_node, putnil); /* error_string */ + } + ADD_INSN(head, line_node, putnil); /* allocate stack for cached #deconstruct value */ + + CHECK(COMPILE(head, "case base", orig_node->nd_head)); + ADD_SEQ(ret, head); /* case VAL */ while (type == NODE_IN) { LABEL *l1; + if (branch_id) { + ADD_INSN(body_seq, line_node, putnil); + } l1 = NEW_LABEL(line); ADD_LABEL(body_seq, l1); - ADD_INSN(body_seq, line, pop); - ADD_TRACE_BRANCH_COVERAGE( + ADD_INSN1(body_seq, line_node, adjuststack, INT2FIX(single_pattern ? 6 : 2)); + add_trace_branch_coverage( + iseq, body_seq, - node->nd_body ? nd_first_lineno(node->nd_body) : lineno, - node->nd_body ? nd_first_column(node->nd_body) : column, - node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno, - node->nd_body ? nd_last_column(node->nd_body) : last_column, + node->nd_body ? node->nd_body : node, + branch_id++, "in", branches); CHECK(COMPILE_(body_seq, "in body", node->nd_body, popped)); - ADD_INSNL(body_seq, line, jump, endlabel); + ADD_INSNL(body_seq, line_node, jump, endlabel); pattern = node->nd_head; if (pattern) { - ADD_INSN (cond_seq, nd_line(pattern), dup); - iseq_compile_pattern_each(iseq, cond_seq, pattern, FALSE); - ADD_INSNL(cond_seq, nd_line(pattern), branchif, l1); + int pat_line = nd_line(pattern); + LABEL *next_pat = NEW_LABEL(pat_line); + ADD_INSN (cond_seq, pattern, dup); /* dup case VAL */ + // NOTE: set base_index (it's "under" the matchee value, so it's position is 2) + CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, single_pattern, false, 2, true)); + ADD_LABEL(cond_seq, next_pat); + LABEL_UNREMOVABLE(next_pat); } else { COMPILE_ERROR(ERROR_ARGS "unexpected node"); @@ -6033,33 +6975,85 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no } type = nd_type(node); line = nd_line(node); - lineno = nd_first_lineno(node); - column = nd_first_column(node); - last_lineno = nd_last_lineno(node); - last_column = nd_last_column(node); + line_node = node; } /* else */ if (node) { ADD_LABEL(cond_seq, elselabel); - ADD_INSN(cond_seq, line, pop); - ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "else", branches); + 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); CHECK(COMPILE_(cond_seq, "else", node, popped)); - ADD_INSNL(cond_seq, line, jump, endlabel); + ADD_INSNL(cond_seq, line_node, jump, endlabel); + ADD_INSN(cond_seq, line_node, putnil); + if (popped) { + ADD_INSN(cond_seq, line_node, putnil); + } } else { debugs("== else (implicit)\n"); ADD_LABEL(cond_seq, elselabel); - ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "else", branches); - ADD_INSN1(cond_seq, nd_line(orig_node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(cond_seq, nd_line(orig_node), putobject, rb_eNoMatchingPatternError); - ADD_INSN1(cond_seq, nd_line(orig_node), topn, INT2FIX(2)); - ADD_SEND(cond_seq, nd_line(orig_node), id_core_raise, INT2FIX(2)); - ADD_INSN(cond_seq, nd_line(orig_node), pop); - ADD_INSN(cond_seq, nd_line(orig_node), pop); + add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches); + ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + + if (single_pattern) { + /* + * if key_error_p + * FrozenCore.raise NoMatchingPatternKeyError.new(FrozenCore.sprintf("%p: %s", case_val, error_string), matchee: key_error_matchee, key: key_error_key) + * else + * FrozenCore.raise NoMatchingPatternError, FrozenCore.sprintf("%p: %s", case_val, error_string) + * end + */ + LABEL *key_error, *fin; + struct rb_callinfo_kwarg *kw_arg; + + key_error = NEW_LABEL(line); + fin = NEW_LABEL(line); + + kw_arg = rb_xmalloc_mul_add(2, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); + kw_arg->keyword_len = 2; + kw_arg->keywords[0] = ID2SYM(rb_intern("matchee")); + kw_arg->keywords[1] = ID2SYM(rb_intern("key")); + + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_P + 2)); + ADD_INSNL(cond_seq, orig_node, branchif, key_error); + ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternError); + ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit("%p: %s")); + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(4)); /* case VAL */ + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6)); + ADD_SEND(cond_seq, orig_node, id_core_sprintf, INT2FIX(3)); + ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(2)); + ADD_INSNL(cond_seq, orig_node, jump, fin); + + ADD_LABEL(cond_seq, key_error); + ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternKeyError); + ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit("%p: %s")); + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(4)); /* case VAL */ + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6)); + ADD_SEND(cond_seq, orig_node, id_core_sprintf, INT2FIX(3)); + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4)); + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_KEY + 5)); + ADD_SEND_R(cond_seq, orig_node, rb_intern("new"), INT2FIX(1), NULL, INT2FIX(VM_CALL_KWARG), kw_arg); + ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(1)); + + ADD_LABEL(cond_seq, fin); + } + else { + ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternError); + ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(2)); + ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(2)); + } + ADD_INSN1(cond_seq, orig_node, adjuststack, INT2FIX(single_pattern ? 7 : 3)); if (!popped) { - ADD_INSN(cond_seq, nd_line(orig_node), putnil); + ADD_INSN(cond_seq, orig_node, putnil); + } + ADD_INSNL(cond_seq, orig_node, jump, endlabel); + ADD_INSN1(cond_seq, orig_node, dupn, INT2FIX(single_pattern ? 5 : 1)); + if (popped) { + ADD_INSN(cond_seq, line_node, putnil); } - ADD_INSNL(cond_seq, nd_line(orig_node), jump, endlabel); } ADD_SEQ(ret, cond_seq); @@ -6068,14 +7062,18 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no return COMPILE_OK; } +#undef CASE3_BI_OFFSET_DECONSTRUCTED_CACHE +#undef CASE3_BI_OFFSET_ERROR_STRING +#undef CASE3_BI_OFFSET_KEY_ERROR_P +#undef CASE3_BI_OFFSET_KEY_ERROR_MATCHEE +#undef CASE3_BI_OFFSET_KEY_ERROR_KEY + static int compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type) { const int line = (int)nd_line(node); - const int lineno = nd_first_lineno(node); - const int column = nd_first_column(node); - const int last_lineno = nd_last_lineno(node); - const int last_column = nd_last_column(node); + const NODE *line_node = node; + LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label; LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label; LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label; @@ -6097,27 +7095,26 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in push_ensure_entry(iseq, &enl, NULL, NULL); if (node->nd_state == 1) { - ADD_INSNL(ret, line, jump, next_label); + ADD_INSNL(ret, line_node, jump, next_label); } else { tmp_label = NEW_LABEL(line); - ADD_INSNL(ret, line, jump, tmp_label); + ADD_INSNL(ret, line_node, jump, tmp_label); } ADD_LABEL(ret, adjust_label); - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, next_catch_label); - ADD_INSN(ret, line, pop); - ADD_INSNL(ret, line, jump, next_label); + ADD_INSN(ret, line_node, pop); + ADD_INSNL(ret, line_node, jump, next_label); if (tmp_label) ADD_LABEL(ret, tmp_label); ADD_LABEL(ret, redo_label); - DECL_BRANCH_BASE(branches, lineno, column, last_lineno, last_column, type == NODE_WHILE ? "while" : "until"); - ADD_TRACE_BRANCH_COVERAGE( + branches = decl_branch_base(iseq, node, type == NODE_WHILE ? "while" : "until"); + add_trace_branch_coverage( + iseq, ret, - node->nd_body ? nd_first_lineno(node->nd_body) : lineno, - node->nd_body ? nd_first_column(node->nd_body) : column, - node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno, - node->nd_body ? nd_last_column(node->nd_body) : last_column, + node->nd_body ? node->nd_body : node, + 0, "body", branches); CHECK(COMPILE_POPPED(ret, "while body", node->nd_body)); @@ -6137,18 +7134,18 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ADD_ADJUST_RESTORE(ret, adjust_label); if (node->nd_state == Qundef) { - /* ADD_INSN(ret, line, putundef); */ + /* ADD_INSN(ret, line_node, putundef); */ COMPILE_ERROR(ERROR_ARGS "unsupported: putundef"); return COMPILE_NG; } else { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } ADD_LABEL(ret, break_label); /* break */ if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL, @@ -6170,19 +7167,20 @@ static int compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { const int line = nd_line(node); + const NODE *line_node = node; const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block; LABEL *retry_label = NEW_LABEL(line); LABEL *retry_end_l = NEW_LABEL(line); const rb_iseq_t *child_iseq; ADD_LABEL(ret, retry_label); - if (nd_type(node) == NODE_FOR) { + if (nd_type_p(node, NODE_FOR)) { CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter)); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); - ADD_SEND_WITH_BLOCK(ret, line, idEach, INT2FIX(0), child_iseq); + ADD_SEND_WITH_BLOCK(ret, line_node, idEach, INT2FIX(0), child_iseq); } else { ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq = @@ -6193,7 +7191,7 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ADD_LABEL(ret, retry_end_l); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } ISEQ_COMPILE_DATA(iseq)->current_block = prevblock; @@ -6208,27 +7206,27 @@ compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod /* massign to var in "for" * (args.length == 1 && Array.try_convert(args[0])) || args */ - const int line = nd_line(node); + const NODE *line_node = node; const NODE *var = 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)); - ADD_INSN(ret, line, dup); - ADD_CALL(ret, line, idLength, INT2FIX(0)); - ADD_INSN1(ret, line, putobject, INT2FIX(1)); - ADD_CALL(ret, line, idEq, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, not_single); - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(0)); - ADD_CALL(ret, line, idAREF, INT2FIX(1)); - ADD_INSN1(ret, line, putobject, rb_cArray); - ADD_INSN(ret, line, swap); - ADD_CALL(ret, line, rb_intern("try_convert"), INT2FIX(1)); - ADD_INSN(ret, line, dup); - ADD_INSNL(ret, line, branchunless, not_ary); - ADD_INSN(ret, line, swap); + ADD_INSN(ret, line_node, dup); + ADD_CALL(ret, line_node, idLength, INT2FIX(0)); + ADD_INSN1(ret, line_node, putobject, INT2FIX(1)); + ADD_CALL(ret, line_node, idEq, INT2FIX(1)); + ADD_INSNL(ret, line_node, branchunless, not_single); + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); + ADD_CALL(ret, line_node, idAREF, INT2FIX(1)); + ADD_INSN1(ret, line_node, putobject, rb_cArray); + ADD_INSN(ret, line_node, swap); + ADD_CALL(ret, line_node, rb_intern("try_convert"), INT2FIX(1)); + ADD_INSN(ret, line_node, dup); + ADD_INSNL(ret, line_node, branchunless, not_ary); + ADD_INSN(ret, line_node, swap); ADD_LABEL(ret, not_ary); - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); ADD_LABEL(ret, not_single); return COMPILE_OK; } @@ -6236,40 +7234,26 @@ compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod static int compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const NODE *line_node = node; unsigned long throw_flag = 0; - if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) { + if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) { /* while/until */ LABEL *splabel = NEW_LABEL(0); ADD_LABEL(ret, splabel); - ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label); + ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label); CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts, ISEQ_COMPILE_DATA(iseq)->loopval_popped)); add_ensure_iseq(ret, iseq, 0); - ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label); + ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label); ADD_ADJUST_RESTORE(ret, splabel); if (!popped) { - ADD_INSN(ret, line, putnil); - } - } - else if (iseq->body->type == ISEQ_TYPE_BLOCK) { - break_by_insn: - /* escape from block */ - CHECK(COMPILE(ret, "break val (block)", node->nd_stts)); - ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_BREAK)); - if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, putnil); } } - else if (iseq->body->type == ISEQ_TYPE_EVAL) { - break_in_eval: - COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break"); - return COMPILE_NG; - } else { - const rb_iseq_t *ip = iseq->body->parent_iseq; + const rb_iseq_t *ip = iseq; while (ip) { if (!ISEQ_COMPILE_DATA(ip)) { @@ -6279,16 +7263,26 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) { throw_flag = VM_THROW_NO_ESCAPE_FLAG; - goto break_by_insn; } else if (ip->body->type == ISEQ_TYPE_BLOCK) { - goto break_by_insn; + throw_flag = 0; } else if (ip->body->type == ISEQ_TYPE_EVAL) { - goto break_in_eval; + COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break"); + return COMPILE_NG; } + else { + ip = ip->body->parent_iseq; + continue; + } - ip = ip->body->parent_iseq; + /* escape from block */ + CHECK(COMPILE(ret, "break val (block)", node->nd_stts)); + ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_BREAK)); + if (popped) { + ADD_INSN(ret, line_node, pop); + } + return COMPILE_OK; } COMPILE_ERROR(ERROR_ARGS "Invalid break"); return COMPILE_NG; @@ -6299,42 +7293,37 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i static int compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const NODE *line_node = node; unsigned long throw_flag = 0; - if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) { + if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) { 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)); add_ensure_iseq(ret, iseq, 0); - ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label); - ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label); + ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label); + ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label); ADD_ADJUST_RESTORE(ret, splabel); if (!popped) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } } - else if (ISEQ_COMPILE_DATA(iseq)->end_label) { + else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) { LABEL *splabel = NEW_LABEL(0); debugs("next in block\n"); ADD_LABEL(ret, splabel); - ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label); + ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label); CHECK(COMPILE(ret, "next val", node->nd_stts)); add_ensure_iseq(ret, iseq, 0); - ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label); + 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, putnil); + ADD_INSN(ret, line_node, putnil); } } - else if (iseq->body->type == ISEQ_TYPE_EVAL) { - next_in_eval: - COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next"); - return COMPILE_NG; - } else { const rb_iseq_t *ip = iseq; @@ -6353,17 +7342,18 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in break; } else if (ip->body->type == ISEQ_TYPE_EVAL) { - goto next_in_eval; + COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next"); + return COMPILE_NG; } ip = ip->body->parent_iseq; } if (ip != 0) { CHECK(COMPILE(ret, "next val", node->nd_stts)); - ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_NEXT)); + ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_NEXT)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } } else { @@ -6377,37 +7367,32 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in static int compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const NODE *line_node = node; - if (ISEQ_COMPILE_DATA(iseq)->redo_label) { + if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) { LABEL *splabel = NEW_LABEL(0); debugs("redo in while"); ADD_LABEL(ret, splabel); - ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label); + ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label); add_ensure_iseq(ret, iseq, 0); - ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->redo_label); + ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label); ADD_ADJUST_RESTORE(ret, splabel); if (!popped) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } } - else if (iseq->body->type == ISEQ_TYPE_EVAL) { - redo_in_eval: - COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo"); - return COMPILE_NG; - } - else if (ISEQ_COMPILE_DATA(iseq)->start_label) { + else if (iseq->body->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) { LABEL *splabel = NEW_LABEL(0); debugs("redo in block"); ADD_LABEL(ret, splabel); add_ensure_iseq(ret, iseq, 0); - ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label); - ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label); + ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label); + ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label); ADD_ADJUST_RESTORE(ret, splabel); if (!popped) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } } else { @@ -6426,17 +7411,18 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in break; } else if (ip->body->type == ISEQ_TYPE_EVAL) { - goto redo_in_eval; + COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo"); + return COMPILE_NG; } ip = ip->body->parent_iseq; } if (ip != 0) { - ADD_INSN(ret, line, putnil); - ADD_INSN1(ret, line, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO)); + ADD_INSN(ret, line_node, putnil); + ADD_INSN1(ret, line_node, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } } else { @@ -6450,14 +7436,14 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in static int compile_retry(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const NODE *line_node = node; if (iseq->body->type == ISEQ_TYPE_RESCUE) { - ADD_INSN(ret, line, putnil); - ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETRY)); + ADD_INSN(ret, line_node, putnil); + ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETRY)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } } else { @@ -6471,6 +7457,7 @@ static int compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { const int line = nd_line(node); + const NODE *line_node = node; LABEL *lstart = NEW_LABEL(line); LABEL *lend = NEW_LABEL(line); LABEL *lcont = NEW_LABEL(line); @@ -6481,17 +7468,24 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, lstart->rescued = LABEL_RESCUE_BEG; lend->rescued = LABEL_RESCUE_END; ADD_LABEL(ret, lstart); - CHECK(COMPILE(ret, "rescue head", node->nd_head)); + + 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)); + } + ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue; + ADD_LABEL(ret, lend); if (node->nd_else) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); CHECK(COMPILE(ret, "rescue else", node->nd_else)); } - ADD_INSN(ret, line, nop); + ADD_INSN(ret, line_node, nop); ADD_LABEL(ret, lcont); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } /* register catch entry */ @@ -6504,6 +7498,7 @@ static int compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { const int line = nd_line(node); + const NODE *line_node = node; const NODE *resq = node; const NODE *narg; LABEL *label_miss, *label_hit; @@ -6517,38 +7512,38 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, switch (nd_type(narg)) { case NODE_LIST: while (narg) { - ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); + ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0); CHECK(COMPILE(ret, "rescue arg", narg->nd_head)); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSNL(ret, line, branchif, label_hit); + ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); + ADD_INSNL(ret, line_node, branchif, label_hit); narg = narg->nd_next; } break; case NODE_SPLAT: case NODE_ARGSCAT: case NODE_ARGSPUSH: - ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); + ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0); CHECK(COMPILE(ret, "rescue/cond splat", narg)); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY)); - ADD_INSNL(ret, line, branchif, label_hit); + ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY)); + ADD_INSNL(ret, line_node, branchif, label_hit); break; default: UNKNOWN_NODE("NODE_RESBODY", narg, COMPILE_NG); } } else { - ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); - ADD_INSN1(ret, line, putobject, rb_eStandardError); - ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSNL(ret, line, branchif, label_hit); + ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0); + ADD_INSN1(ret, line_node, putobject, rb_eStandardError); + ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); + ADD_INSNL(ret, line_node, branchif, label_hit); } - ADD_INSNL(ret, line, jump, label_miss); + ADD_INSNL(ret, line_node, jump, label_miss); ADD_LABEL(ret, label_hit); CHECK(COMPILE(ret, "resbody body", resq->nd_body)); if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) { - ADD_INSN(ret, line, nop); + ADD_INSN(ret, line_node, nop); } - ADD_INSN(ret, line, leave); + ADD_INSN(ret, line_node, leave); ADD_LABEL(ret, label_miss); resq = resq->nd_head; } @@ -6559,6 +7554,7 @@ 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 NODE *line_node = node; DECL_ANCHOR(ensr); const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr, rb_str_concat(rb_str_new2 ("ensure in "), iseq->body->location.label), @@ -6586,9 +7582,9 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave))); ADD_LABEL(ret, lend); ADD_SEQ(ret, ensr); - if (!popped && last_leave) ADD_INSN(ret, line, putnil); + if (!popped && last_leave) ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, lcont); - if (last_leave) ADD_INSN(ret, line, pop); + if (last_leave) ADD_INSN(ret, line_node, pop); erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange; if (lstart->link.next != &lend->link) { @@ -6606,7 +7602,7 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, static int compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const NODE *line_node = node; if (iseq) { enum iseq_type type = iseq->body->type; @@ -6637,25 +7633,25 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, if (type == ISEQ_TYPE_METHOD) { splabel = NEW_LABEL(0); ADD_LABEL(ret, splabel); - ADD_ADJUST(ret, line, 0); + ADD_ADJUST(ret, line_node, 0); } CHECK(COMPILE(ret, "return nd_stts (return val)", retval)); - if (type == ISEQ_TYPE_METHOD) { + if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) { add_ensure_iseq(ret, iseq, 1); ADD_TRACE(ret, RUBY_EVENT_RETURN); - ADD_INSN(ret, line, leave); + ADD_INSN(ret, line_node, leave); ADD_ADJUST_RESTORE(ret, splabel); if (!popped) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, line_node, putnil); } } else { - ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETURN)); + ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETURN)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } } } @@ -6668,72 +7664,76 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i CHECK(COMPILE_(ret, "nd_body", node, popped)); if (!popped && !all_string_result_p(node)) { - const int line = nd_line(node); + const NODE *line_node = node; const unsigned int flag = VM_CALL_FCALL; - LABEL *isstr = NEW_LABEL(line); - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, checktype, INT2FIX(T_STRING)); - ADD_INSNL(ret, line, branchif, isstr); - ADD_INSN(ret, line, dup); - ADD_SEND_R(ret, line, idTo_s, INT2FIX(0), NULL, INT2FIX(flag), NULL); - ADD_INSN(ret, line, tostring); - ADD_LABEL(ret, isstr); + + // Note, this dup could be removed if we are willing to change anytostring. It pops + // two VALUEs off the stack when it could work by replacing the top most VALUE. + ADD_INSN(ret, line_node, dup); + ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE)); + ADD_INSN(ret, line_node, anytostring); } return COMPILE_OK; } +static void +compile_lvar(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *line_node, ID id) +{ + int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id); + + debugs("id: %s idx: %d\n", rb_id2name(id), idx); + ADD_GETLOCAL(ret, line_node, idx, get_lvar_level(iseq)); +} + static LABEL * -qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, const NODE *node, int line) +qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, const NODE *node, const NODE *line_node) { - LABEL *else_label = NEW_LABEL(line); - 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); + LABEL *else_label = NEW_LABEL(nd_line(line_node)); VALUE br = 0; - DECL_BRANCH_BASE(br, first_lineno, first_column, last_lineno, last_column, "&."); + br = decl_branch_base(iseq, node, "&."); *branches = br; - ADD_INSN(recv, line, dup); - ADD_INSNL(recv, line, branchnil, else_label); - ADD_TRACE_BRANCH_COVERAGE(recv, first_lineno, first_column, last_lineno, last_column, "then", 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); return else_label; } static void -qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *else_label, VALUE branches, const NODE *node, int line) +qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *else_label, VALUE branches, const NODE *node, const NODE *line_node) { LABEL *end_label; if (!else_label) return; - end_label = NEW_LABEL(line); - ADD_INSNL(ret, line, jump, end_label); + 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(ret, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), - "else", branches); + add_trace_branch_coverage(iseq, ret, node, 1, "else", branches); ADD_LABEL(ret, end_label); } static int -compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int line, int popped) +compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped) { /* optimization shortcut * "literal".freeze -> opt_str_freeze("literal") */ - if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR && + if (node->nd_recv && nd_type_p(node->nd_recv, NODE_STR) && (node->nd_mid == idFreeze || node->nd_mid == idUMinus) && node->nd_args == 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) { - ADD_INSN2(ret, line, opt_str_uminus, str, + ADD_INSN2(ret, line_node, opt_str_uminus, str, new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE)); } else { - ADD_INSN2(ret, line, opt_str_freeze, str, + ADD_INSN2(ret, line_node, opt_str_freeze, str, new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE)); } RB_OBJ_WRITTEN(iseq, Qundef, str); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } return TRUE; } @@ -6741,18 +7741,18 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE * obj["literal"] -> opt_aref_with(obj, "literal") */ if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args && - nd_type(node->nd_args) == NODE_LIST && node->nd_args->nd_alen == 1 && - nd_type(node->nd_args->nd_head) == NODE_STR && + nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 1 && + 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)); - ADD_INSN2(ret, line, opt_aref_with, str, + ADD_INSN2(ret, line_node, opt_aref_with, str, new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE)); RB_OBJ_WRITTEN(iseq, Qundef, str); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } return TRUE; } @@ -6779,18 +7779,39 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name) } static const char * -iseq_builtin_function_name(ID mid) +iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid) { const char *name = rb_id2name(mid); static const char prefix[] = "__builtin_"; const size_t prefix_len = sizeof(prefix) - 1; - if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) { - return &name[prefix_len]; - } - else { - return NULL; + switch (type) { + case NODE_CALL: + if (recv) { + switch (nd_type(recv)) { + case NODE_VCALL: + if (recv->nd_mid == rb_intern("__builtin")) { + return name; + } + break; + case NODE_CONST: + if (recv->nd_vid == rb_intern("Primitive")) { + return name; + } + break; + default: break; + } + } + break; + case NODE_VCALL: + case NODE_FCALL: + if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) { + return &name[prefix_len]; + } + break; + default: break; } + return NULL; } static int @@ -6856,7 +7877,199 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg } static int -compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int type, int line, int popped) +compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, const NODE *line_node, int popped) +{ + 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 (!node) goto no_arg; + if (!nd_type_p(node, NODE_LIT)) goto bad_arg; + VALUE name = node->nd_lit; + if (!SYMBOL_P(name)) goto non_symbol_arg; + if (!popped) { + compile_lvar(iseq, ret, line_node, SYM2ID(name)); + } + return COMPILE_OK; + no_arg: + COMPILE_ERROR(ERROR_ARGS "arg!: no argument"); + return COMPILE_NG; + too_many_arg: + COMPILE_ERROR(ERROR_ARGS "arg!: too many argument"); + return COMPILE_NG; + non_symbol_arg: + COMPILE_ERROR(ERROR_ARGS "non symbol argument to arg!: %s", + rb_builtin_class_name(name)); + return COMPILE_NG; + bad_arg: + UNKNOWN_NODE("arg!", node, COMPILE_NG); +} + +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; + } + else { + rb_bug("mandatory_node: can't find mandatory node"); + } +} + +static int +compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const NODE *line_node) +{ + // arguments + struct rb_args_info args = { + .pre_args_num = iseq->body->param.lead_num, + }; + NODE args_node; + rb_node_init(&args_node, NODE_ARGS, 0, 0, (VALUE)&args); + + // local table without non-mandatory parameters + const int skip_local_size = iseq->body->param.size - iseq->body->param.lead_num; + const int table_size = iseq->body->local_table_size - skip_local_size; + + VALUE idtmp = 0; + rb_ast_id_table_t *tbl = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + table_size * sizeof(ID)); + tbl->size = table_size; + + int i; + + // lead parameters + for (i=0; ibody->param.lead_num; i++) { + tbl->ids[i] = iseq->body->local_table[i]; + } + // local variables + for (; iids[i] = iseq->body->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_ast_body_t ast = { + .root = &scope_node, + .compile_option = 0, + .script_lines = iseq->body->variable.script_lines, + }; + + int prev_inline_index = GET_VM()->builtin_inline_index; + + iseq->body->mandatory_only_iseq = + rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq), + rb_iseq_path(iseq), rb_iseq_realpath(iseq), + INT2FIX(nd_line(line_node)), NULL, 0, + ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option); + + GET_VM()->builtin_inline_index = prev_inline_index; + ALLOCV_END(idtmp); + return COMPILE_OK; +} + +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; + + if (parent_block != NULL) { + COMPILE_ERROR(iseq, nd_line(line_node), "should not call builtins here."); + return COMPILE_NG; + } + else { +# define BUILTIN_INLINE_PREFIX "_bi" + char inline_func[DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT) + sizeof(BUILTIN_INLINE_PREFIX)]; + bool cconst = false; + retry:; + const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func); + + if (bf == NULL) { + if (strcmp("cstmt!", builtin_func) == 0 || + strcmp("cexpr!", builtin_func) == 0) { + // ok + } + else if (strcmp("cconst!", builtin_func) == 0) { + cconst = true; + } + else if (strcmp("cinit!", builtin_func) == 0) { + // ignore + GET_VM()->builtin_inline_index++; + return COMPILE_OK; + } + else if (strcmp("attr!", builtin_func) == 0) { + // There's only "inline" attribute for now + iseq->body->builtin_inline_p = true; + return COMPILE_OK; + } + else if (strcmp("arg!", builtin_func) == 0) { + return compile_builtin_arg(iseq, ret, args_node, line_node, popped); + } + else if (strcmp("mandatory_only?", builtin_func) == 0) { + if (popped) { + rb_bug("mandatory_only? should be in if condition"); + } + else if (!LIST_INSN_SIZE_ZERO(ret)) { + rb_bug("mandatory_only? should be put on top"); + } + + ADD_INSN1(ret, line_node, putobject, Qfalse); + return compile_builtin_mandatory_only_method(iseq, node, line_node); + } + else if (1) { + rb_bug("can't find builtin function:%s", builtin_func); + } + else { + COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func); + 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++; + snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index); + builtin_func = inline_func; + args_node = NULL; + goto retry; + } + + if (cconst) { + typedef VALUE(*builtin_func0)(void *, VALUE); + VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil); + ADD_INSN1(ret, line_node, putobject, const_val); + return COMPILE_OK; + } + + // fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr); + + unsigned int flag = 0; + struct rb_callinfo_kwarg *keywords = NULL; + VALUE argc = setup_args(iseq, args, args_node, &flag, &keywords); + + if (FIX2INT(argc) != bf->argc) { + COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)", + builtin_func, bf->argc, FIX2INT(argc)); + return COMPILE_NG; + } + + unsigned int start_index; + if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) { + ADD_INSN2(ret, line_node, opt_invokebuiltin_delegate, bf, INT2FIX(start_index)); + } + else { + ADD_SEQ(ret, args); + ADD_INSN1(ret, line_node, invokebuiltin, bf); + } + + if (popped) ADD_INSN(ret, line_node, pop); + return COMPILE_OK; + } +} + +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) { /* call: obj.method(...) * fcall: func(...) @@ -6867,7 +8080,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ID mid = node->nd_mid; VALUE argc; unsigned int flag = 0; - struct rb_call_info_kw_arg *keywords = NULL; + struct rb_callinfo_kwarg *keywords = NULL; const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block; LABEL *else_label = NULL; VALUE branches = Qfalse; @@ -6877,7 +8090,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in INIT_ANCHOR(recv); INIT_ANCHOR(args); #if OPT_SUPPORT_JOKE - if (nd_type(node) == NODE_VCALL) { + if (nd_type_p(node, NODE_VCALL)) { ID id_bitblt; ID id_answer; @@ -6885,11 +8098,11 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything"); if (mid == id_bitblt) { - ADD_INSN(ret, line, bitblt); + ADD_INSN(ret, line_node, bitblt); return COMPILE_OK; } else if (mid == id_answer) { - ADD_INSN(ret, line, answer); + ADD_INSN(ret, line_node, answer); return COMPILE_OK; } } @@ -6901,7 +8114,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in CONST_ID(goto_id, "__goto__"); CONST_ID(label_id, "__label__"); - if (nd_type(node) == NODE_FCALL && + if (nd_type_p(node, NODE_FCALL) && (mid == goto_id || mid == label_id)) { LABEL *label; st_data_t data; @@ -6912,13 +8125,13 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in labels_table = st_init_numtable(); ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table; } - if (nd_type(node->nd_args->nd_head) == NODE_LIT && + 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(line); - label->position = line; + 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 { @@ -6931,7 +8144,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in } if (mid == goto_id) { - ADD_INSNL(ret, line, jump, label); + ADD_INSNL(ret, line_node, jump, label); } else { ADD_LABEL(ret, label); @@ -6940,106 +8153,38 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in } } #endif - const char *builtin_func; - NODE *args_node = node->nd_args; + const char *builtin_func; if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && - (builtin_func = iseq_builtin_function_name(mid)) != NULL) { - - if (parent_block != NULL) { - COMPILE_ERROR(iseq, line, "should not call builtins here."); - return COMPILE_NG; - } - else { - char inline_func[0x20]; - bool cconst = false; - retry:; - const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func); - - if (bf == NULL) { - if (strcmp("cstmt!", builtin_func) == 0 || - strcmp("cexpr!", builtin_func) == 0) { - inlinec:; - int inline_index = GET_VM()->builtin_inline_index++; - snprintf(inline_func, 0x20, "_bi%d", inline_index); - builtin_func = inline_func; - args_node = NULL; - goto retry; - } - else if (strcmp("cconst!", builtin_func) == 0) { - cconst = true; - goto inlinec; - } - else if (strcmp("cinit!", builtin_func) == 0) { - // ignore - GET_VM()->builtin_inline_index++; - return COMPILE_OK; - } - - if (1) { - rb_bug("can't find builtin function:%s", builtin_func); - } - else { - COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func); - } - return COMPILE_NG; - } - - if (cconst) { - typedef VALUE(*builtin_func0)(void *, VALUE); - VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil); - ADD_INSN1(ret, line, putobject, const_val); - return COMPILE_OK; - } - - // fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr); - - argc = setup_args(iseq, args, args_node, &flag, &keywords); + (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) { + return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func); + } - if (FIX2INT(argc) != bf->argc) { - COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)", - builtin_func, bf->argc, FIX2INT(argc)); - return COMPILE_NG; + /* receiver */ + if (!assume_receiver) { + if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) { + 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)); } - - unsigned int start_index; - if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) { - ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf, INT2FIX(start_index)); + else if (private_recv_p(node)) { + ADD_INSN(recv, node, putself); + flag |= VM_CALL_FCALL; } else { - ADD_SEQ(ret, args); - ADD_INSN1(ret,line, invokebuiltin, bf); + CHECK(COMPILE(recv, "recv", node->nd_recv)); } - if (popped) ADD_INSN(ret, line, pop); - return COMPILE_OK; + if (type == NODE_QCALL) { + else_label = qcall_branch_start(iseq, recv, &branches, node, line_node); + } + } + else if (type == NODE_FCALL || type == NODE_VCALL) { + ADD_CALL_RECEIVER(recv, line_node); } - } - - - /* receiver */ - if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) { - int idx, level; - - if (mid == idCall && - nd_type(node->nd_recv) == NODE_LVAR && - iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) { - ADD_INSN2(recv, nd_line(node->nd_recv), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); - } - else if (private_recv_p(node)) { - ADD_INSN(recv, nd_line(node), putself); - flag |= VM_CALL_FCALL; - } - else { - CHECK(COMPILE(recv, "recv", node->nd_recv)); - } - - if (type == NODE_QCALL) { - else_label = qcall_branch_start(iseq, recv, &branches, node, line); - } - } - else if (type == NODE_FCALL || type == NODE_VCALL) { - ADD_CALL_RECEIVER(recv, line); } /* args */ @@ -7065,17 +8210,851 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in flag |= VM_CALL_FCALL; } - ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords); + ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords); - qcall_branch_end(iseq, ret, else_label, branches, node, line); + qcall_branch_end(iseq, ret, else_label, branches, node, line_node); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, line_node, pop); } return COMPILE_OK; } +static int +compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + const int line = nd_line(node); + VALUE argc; + unsigned int flag = 0; + int asgnflag = 0; + ID id = node->nd_mid; + int boff = 0; + + /* + * a[x] (op)= y + * + * nil # nil + * eval a # nil a + * eval x # nil a x + * dupn 2 # nil a x a x + * send :[] # nil a x a[x] + * eval y # nil a x a[x] y + * send op # nil a x ret + * setn 3 # ret a x ret + * send []= # ret ? + * pop # ret + */ + + /* + * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head; + * NODE_OP_ASGN nd_recv + * nd_args->nd_head + * nd_args->nd_body + * nd_mid + */ + + if (!popped) { + ADD_INSN(ret, node, putnil); + } + asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node); + CHECK(asgnflag != -1); + switch (nd_type(node->nd_args->nd_head)) { + 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); + CHECK(!NIL_P(argc)); + } + ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff)); + flag |= asgnflag; + ADD_SEND_WITH_FLAG(ret, node, idAREF, argc, INT2FIX(flag)); + + if (id == idOROP || id == idANDOP) { + /* a[x] ||= y or a[x] &&= y + + unless/if a[x] + a[x]= y + else + nil + end + */ + LABEL *label = NEW_LABEL(line); + LABEL *lfin = NEW_LABEL(line); + + ADD_INSN(ret, node, dup); + if (id == idOROP) { + ADD_INSNL(ret, node, branchif, label); + } + else { /* idANDOP */ + ADD_INSNL(ret, node, branchunless, label); + } + ADD_INSN(ret, node, pop); -static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped); + CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); + if (!popped) { + ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff)); + } + if (flag & VM_CALL_ARGS_SPLAT) { + ADD_INSN1(ret, node, newarray, INT2FIX(1)); + if (boff > 0) { + ADD_INSN1(ret, node, dupn, INT2FIX(3)); + 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_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag)); + } + else { + if (boff > 0) + ADD_INSN(ret, node, swap); + ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); + } + 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, adjuststack, FIXNUM_INC(argc, 2+boff)); + ADD_LABEL(ret, lfin); + } + else { + CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); + ADD_SEND(ret, node, id, INT2FIX(1)); + if (!popped) { + ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff)); + } + if (flag & VM_CALL_ARGS_SPLAT) { + ADD_INSN1(ret, node, newarray, INT2FIX(1)); + if (boff > 0) { + ADD_INSN1(ret, node, dupn, INT2FIX(3)); + 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_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag)); + } + else { + if (boff > 0) + ADD_INSN(ret, node, swap); + ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); + } + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +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); + int asgnflag; + LABEL *lfin = NEW_LABEL(line); + LABEL *lcfin = NEW_LABEL(line); + LABEL *lskip = 0; + /* + class C; attr_accessor :c; end + r = C.new + r.a &&= v # asgn2 + + eval r # r + dup # r r + eval r.a # r o + + # or + dup # r o o + if lcfin # r o + pop # r + eval v # r v + swap # v r + topn 1 # v r v + send a= # v ? + jump lfin # v ? + + lcfin: # r o + swap # o r + + lfin: # o ? + pop # o + + # and + dup # r o o + unless lcfin + pop # r + eval v # r v + swap # v r + topn 1 # v r v + send a= # v ? + jump lfin # v ? + + # others + eval v # r o v + send ?? # r w + send a= # w + + */ + + asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node); + CHECK(asgnflag != -1); + if (node->nd_next->nd_aid) { + lskip = NEW_LABEL(line); + ADD_INSN(ret, node, dup); + ADD_INSNL(ret, node, branchnil, lskip); + } + ADD_INSN(ret, node, dup); + ADD_SEND_WITH_FLAG(ret, node, vid, INT2FIX(0), INT2FIX(asgnflag)); + + if (atype == idOROP || atype == idANDOP) { + ADD_INSN(ret, node, dup); + if (atype == idOROP) { + ADD_INSNL(ret, node, branchif, lcfin); + } + else { /* idANDOP */ + ADD_INSNL(ret, node, branchunless, lcfin); + } + ADD_INSN(ret, node, pop); + CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, topn, INT2FIX(1)); + ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag)); + ADD_INSNL(ret, node, jump, lfin); + + ADD_LABEL(ret, lcfin); + ADD_INSN(ret, node, swap); + + ADD_LABEL(ret, lfin); + ADD_INSN(ret, node, pop); + if (lskip) { + ADD_LABEL(ret, lskip); + } + if (popped) { + /* we can apply more optimize */ + ADD_INSN(ret, node, pop); + } + } + else { + CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); + ADD_SEND(ret, node, atype, INT2FIX(1)); + if (!popped) { + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, topn, INT2FIX(1)); + } + ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag)); + if (lskip && popped) { + ADD_LABEL(ret, lskip); + } + ADD_INSN(ret, node, pop); + if (lskip && !popped) { + ADD_LABEL(ret, lskip); + } + } + return COMPILE_OK; +} + +static int +compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + const int line = nd_line(node); + LABEL *lfin = 0; + LABEL *lassign = 0; + ID mid; + + switch (nd_type(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)); + break; + default: + COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL", + ruby_node_name(nd_type(node->nd_head))); + return COMPILE_NG; + } + mid = node->nd_head->nd_mid; + /* cref */ + if (node->nd_aid == idOROP) { + lassign = NEW_LABEL(line); + ADD_INSN(ret, node, dup); /* cref cref */ + ADD_INSN3(ret, node, defined, INT2FIX(DEFINED_CONST_FROM), + ID2SYM(mid), Qtrue); /* cref bool */ + ADD_INSNL(ret, node, branchunless, lassign); /* cref */ + } + ADD_INSN(ret, node, dup); /* cref cref */ + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSN1(ret, node, getconstant, ID2SYM(mid)); /* cref obj */ + + if (node->nd_aid == idOROP || node->nd_aid == idANDOP) { + lfin = NEW_LABEL(line); + if (!popped) ADD_INSN(ret, node, dup); /* cref [obj] obj */ + if (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)); + /* cref value */ + if (popped) + ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */ + else { + ADD_INSN1(ret, node, dupn, INT2FIX(2)); /* cref value cref value */ + ADD_INSN(ret, node, swap); /* cref value value cref */ + } + ADD_INSN1(ret, node, setconstant, ID2SYM(mid)); /* cref [value] */ + ADD_LABEL(ret, lfin); /* cref [value] */ + if (!popped) ADD_INSN(ret, node, swap); /* [value] cref */ + ADD_INSN(ret, node, pop); /* [value] */ + } + else { + CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value)); + /* cref obj value */ + ADD_CALL(ret, node, node->nd_aid, INT2FIX(1)); + /* cref value */ + ADD_INSN(ret, node, swap); /* value cref */ + if (!popped) { + ADD_INSN1(ret, node, topn, INT2FIX(1)); /* value cref value */ + ADD_INSN(ret, node, swap); /* value value cref */ + } + ADD_INSN1(ret, node, setconstant, ID2SYM(mid)); + } + return COMPILE_OK; +} + +static int +compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type) +{ + const int line = nd_line(node); + LABEL *lfin = NEW_LABEL(line); + LABEL *lassign; + + if (type == NODE_OP_ASGN_OR && !nd_type_p(node->nd_head, NODE_IVAR)) { + LABEL *lfinish[2]; + lfinish[0] = lfin; + lfinish[1] = 0; + defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); + lassign = lfinish[1]; + if (!lassign) { + lassign = NEW_LABEL(line); + } + ADD_INSNL(ret, node, branchunless, lassign); + } + else { + lassign = NEW_LABEL(line); + } + + CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head)); + ADD_INSN(ret, node, dup); + + if (type == NODE_OP_ASGN_AND) { + ADD_INSNL(ret, node, branchunless, lfin); + } + else { + ADD_INSNL(ret, node, branchif, lfin); + } + + ADD_INSN(ret, node, pop); + ADD_LABEL(ret, lassign); + CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value)); + ADD_LABEL(ret, lfin); + + if (popped) { + /* we can apply more optimize */ + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +static int +compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type) +{ + struct rb_iseq_constant_body *const body = iseq->body; + DECL_ANCHOR(args); + int argc; + unsigned int flag = 0; + struct rb_callinfo_kwarg *keywords = NULL; + const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block; + + 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); + CHECK(!NIL_P(vargc)); + argc = FIX2INT(vargc); + } + else { + /* NODE_ZSUPER */ + int i; + const rb_iseq_t *liseq = body->local_iseq; + const struct rb_iseq_constant_body *const local_body = liseq->body; + const struct rb_iseq_param_keyword *const local_kwd = local_body->param.keyword; + int lvar_level = get_lvar_level(iseq); + + argc = local_body->param.lead_num; + + /* normal arguments */ + for (i = 0; i < local_body->param.lead_num; i++) { + int idx = local_body->local_table_size - i; + ADD_GETLOCAL(args, node, idx, lvar_level); + } + + if (local_body->param.flags.has_opt) { + /* optional arguments */ + int j; + for (j = 0; j < local_body->param.opt_num; j++) { + int idx = local_body->local_table_size - (i + j); + ADD_GETLOCAL(args, node, idx, lvar_level); + } + i += j; + argc = i; + } + if (local_body->param.flags.has_rest) { + /* 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); + + argc = local_body->param.rest_start + 1; + flag |= VM_CALL_ARGS_SPLAT; + } + if (local_body->param.flags.has_post) { + /* post arguments */ + int post_len = local_body->param.post_num; + int post_start = local_body->param.post_start; + + if (local_body->param.flags.has_rest) { + int j; + for (j=0; jlocal_table_size - (post_start + j); + ADD_GETLOCAL(args, node, idx, lvar_level); + } + ADD_INSN1(args, node, newarray, INT2FIX(j)); + ADD_INSN (args, node, concatarray); + /* argc is settled at above */ + } + else { + int j; + for (j=0; jlocal_table_size - (post_start + j); + ADD_GETLOCAL(args, node, idx, lvar_level); + } + argc = post_len + post_start; + } + } + + if (local_body->param.flags.has_kw) { /* TODO: support keywords */ + int local_size = local_body->local_table_size; + argc++; + + ADD_INSN1(args, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + + 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; + } + } + 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]; + int idx = local_size - get_local_var_idx(liseq, id); + ADD_INSN1(args, node, putobject, ID2SYM(id)); + ADD_GETLOCAL(args, node, idx, lvar_level); + } + ADD_SEND(args, node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1)); + if (local_body->param.flags.has_rest) { + ADD_INSN1(args, node, newarray, INT2FIX(1)); + ADD_INSN (args, node, concatarray); + --argc; + } + flag |= VM_CALL_KW_SPLAT; + } + 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); + + if (local_body->param.flags.has_rest) { + ADD_INSN1(args, node, newarray, INT2FIX(1)); + ADD_INSN (args, node, concatarray); + } + else { + argc++; + } + flag |= VM_CALL_KW_SPLAT; + } + } + + 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); + + if (popped) { + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +static int +compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + DECL_ANCHOR(args); + VALUE argc; + unsigned int flag = 0; + struct rb_callinfo_kwarg *keywords = NULL; + + INIT_ANCHOR(args); + + switch (iseq->body->local_iseq->body->type) { + case ISEQ_TYPE_TOP: + case ISEQ_TYPE_MAIN: + case ISEQ_TYPE_CLASS: + COMPILE_ERROR(ERROR_ARGS "Invalid yield"); + return COMPILE_NG; + default: /* valid */; + } + + if (node->nd_head) { + argc = setup_args(iseq, args, node->nd_head, &flag, &keywords); + CHECK(!NIL_P(argc)); + } + else { + argc = INT2FIX(0); + } + + ADD_SEQ(ret, args); + ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE)); + + if (popped) { + ADD_INSN(ret, node, pop); + } + + int level = 0; + const rb_iseq_t *tmp_iseq = iseq; + for (; tmp_iseq != iseq->body->local_iseq; level++ ) { + tmp_iseq = tmp_iseq->body->parent_iseq; + } + if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true); + + return COMPILE_OK; +} + +static int +compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type) +{ + DECL_ANCHOR(recv); + DECL_ANCHOR(val); + + INIT_ANCHOR(recv); + INIT_ANCHOR(val); + switch ((int)type) { + case NODE_MATCH: + ADD_INSN1(recv, node, putobject, node->nd_lit); + 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)); + break; + case NODE_MATCH3: + CHECK(COMPILE(recv, "receiver", node->nd_value)); + CHECK(COMPILE(val, "value", node->nd_recv)); + break; + } + + ADD_SEQ(ret, recv); + 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 (popped) { + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +static int +compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + const int line = nd_line(node); + if (rb_is_const_id(node->nd_mid)) { + /* constant */ + LABEL *lend = NEW_LABEL(line); + int ic_index = iseq->body->is_size++; + + DECL_ANCHOR(pref); + DECL_ANCHOR(body); + + INIT_ANCHOR(pref); + INIT_ANCHOR(body); + CHECK(compile_const_prefix(iseq, node, pref, body)); + if (LIST_INSN_SIZE_ZERO(pref)) { + if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { + ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index)); + } + else { + ADD_INSN(ret, node, putnil); + } + + ADD_SEQ(ret, body); + + if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { + ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index)); + ADD_LABEL(ret, lend); + } + } + else { + ADD_SEQ(ret, pref); + ADD_SEQ(ret, body); + } + } + 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)); + } + if (popped) { + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +static int +compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + const int line = nd_line(node); + LABEL *lend = NEW_LABEL(line); + int ic_index = iseq->body->is_size++; + + debugi("colon3#nd_mid", node->nd_mid); + + /* add cache insn */ + if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { + ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index)); + ADD_INSN(ret, node, pop); + } + + ADD_INSN1(ret, node, putobject, rb_cObject); + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_mid)); + + if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { + ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index)); + ADD_LABEL(ret, lend); + } + + if (popped) { + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; +} + +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; + + 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 val = rb_range_new(bv, ev, excl); + ADD_INSN1(ret, node, putobject, val); + RB_OBJ_WRITTEN(iseq, Qundef, val); + } + } + else { + CHECK(COMPILE_(ret, "min", b, popped)); + CHECK(COMPILE_(ret, "max", e, popped)); + if (!popped) { + ADD_INSN1(ret, node, newrange, flag); + } + } + return COMPILE_OK; +} + +static int +compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + if (!popped) { + if (iseq->body->type == ISEQ_TYPE_RESCUE) { + ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0); + } + else { + const rb_iseq_t *ip = iseq; + int level = 0; + while (ip) { + if (ip->body->type == ISEQ_TYPE_RESCUE) { + break; + } + ip = ip->body->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; + LABEL *end_label = NEW_LABEL(nd_line(node)); + const NODE *default_value = node->nd_body->nd_value; + + 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_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; + } + 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); + } + 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 = node->nd_mid; + VALUE argc; + LABEL *else_label = NULL; + VALUE branches = Qfalse; + + /* 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); + 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); + + 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); + } + 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 iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped); /** compile each node @@ -7091,7 +9070,8 @@ 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"); - ADD_INSN(ret, lineno, putnil); + NODE dummy_line_node = generate_dummy_line_node(lineno, -1); + ADD_INSN(ret, &dummy_line_node, putnil); } return COMPILE_OK; } @@ -7099,27 +9079,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int poppe } static int -check_yield_place(const rb_iseq_t *iseq, int line) -{ - VALUE file; - switch (iseq->body->local_iseq->body->type) { - case ISEQ_TYPE_TOP: - case ISEQ_TYPE_MAIN: - return FALSE; - case ISEQ_TYPE_CLASS: - file = rb_iseq_path(iseq); - if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) { - rb_compile_warn(RSTRING_PTR(file), line, - "`yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]"); - } - return TRUE; - default: - return TRUE; - } -} - -static int -iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) +iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { const int line = (int)nd_line(node); const enum node_type type = nd_type(node); @@ -7144,17 +9104,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in #define BEFORE_RETURN debug_node_end() switch (type) { - case NODE_BLOCK:{ - while (node && nd_type(node) == NODE_BLOCK) { - CHECK(COMPILE_(ret, "BLOCK body", node->nd_head, - (node->nd_next ? 1 : popped))); - node = node->nd_next; - } - if (node) { - CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped)); - } + case NODE_BLOCK: + CHECK(compile_block(iseq, ret, node, popped)); break; - } case NODE_IF: case NODE_UNLESS: CHECK(compile_if(iseq, ret, node, popped, type)); @@ -7210,16 +9162,16 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in LABEL *end_label = NEW_LABEL(line); CHECK(COMPILE(ret, "nd_1st", node->nd_1st)); if (!popped) { - ADD_INSN(ret, line, dup); + ADD_INSN(ret, node, dup); } if (type == NODE_AND) { - ADD_INSNL(ret, line, branchunless, end_label); + ADD_INSNL(ret, node, branchunless, end_label); } else { - ADD_INSNL(ret, line, branchif, end_label); + ADD_INSNL(ret, node, branchif, end_label); } if (!popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped)); ADD_LABEL(ret, end_label); @@ -7239,577 +9191,114 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in CHECK(COMPILE(ret, "rvalue", node->nd_value)); if (!popped) { - ADD_INSN(ret, line, dup); - } - ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq)); - break; - } - case NODE_DASGN: - case NODE_DASGN_CURR:{ - int idx, lv, ls; - ID id = node->nd_vid; - CHECK(COMPILE(ret, "dvalue", node->nd_value)); - debugi("dassn id", rb_id2str(id) ? id : '*'); - - if (!popped) { - ADD_INSN(ret, line, dup); - } - - idx = get_dyna_var_idx(iseq, id, &lv, &ls); - - if (idx < 0) { - COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")", - rb_id2str(id)); - goto ng; - } - ADD_SETLOCAL(ret, line, ls - idx, lv); - break; - } - case NODE_GASGN:{ - CHECK(COMPILE(ret, "lvalue", node->nd_value)); - - if (!popped) { - ADD_INSN(ret, line, dup); - } - ADD_INSN1(ret, line, setglobal, - ((VALUE)node->nd_entry | 1)); - break; - } - case NODE_IASGN:{ - CHECK(COMPILE(ret, "lvalue", node->nd_value)); - if (!popped) { - ADD_INSN(ret, line, dup); - } - ADD_INSN2(ret, line, setinstancevariable, - ID2SYM(node->nd_vid), - get_ivar_ic_value(iseq,node->nd_vid)); - break; - } - case NODE_CDECL:{ - CHECK(COMPILE(ret, "lvalue", node->nd_value)); - - if (!popped) { - ADD_INSN(ret, line, dup); - } - - if (node->nd_vid) { - ADD_INSN1(ret, line, putspecialobject, - INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_vid)); - } - else { - compile_cpath(ret, iseq, node->nd_else); - ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_else->nd_mid)); - } - break; - } - case NODE_CVASGN:{ - CHECK(COMPILE(ret, "cvasgn val", node->nd_value)); - if (!popped) { - ADD_INSN(ret, line, dup); - } - ADD_INSN1(ret, line, setclassvariable, - ID2SYM(node->nd_vid)); - break; - } - case NODE_OP_ASGN1: { - VALUE argc; - unsigned int flag = 0; - int asgnflag = 0; - ID id = node->nd_mid; - int boff = 0; - - /* - * a[x] (op)= y - * - * nil # nil - * eval a # nil a - * eval x # nil a x - * dupn 2 # nil a x a x - * send :[] # nil a x a[x] - * eval y # nil a x a[x] y - * send op # nil a x ret - * setn 3 # ret a x ret - * send []= # ret ? - * pop # ret - */ - - /* - * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head; - * NODE_OP_ASGN nd_recv - * nd_args->nd_head - * nd_args->nd_body - * nd_mid - */ - - if (!popped) { - ADD_INSN(ret, line, putnil); - } - asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node); - CHECK(asgnflag != -1); - switch (nd_type(node->nd_args->nd_head)) { - 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); - CHECK(!NIL_P(argc)); - } - ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff)); - flag |= asgnflag; - ADD_SEND_WITH_FLAG(ret, line, idAREF, argc, INT2FIX(flag)); - - if (id == idOROP || id == idANDOP) { - /* a[x] ||= y or a[x] &&= y - - unless/if a[x] - a[x]= y - else - nil - end - */ - LABEL *label = NEW_LABEL(line); - LABEL *lfin = NEW_LABEL(line); - - ADD_INSN(ret, line, dup); - if (id == idOROP) { - ADD_INSNL(ret, line, branchif, label); - } - else { /* idANDOP */ - ADD_INSNL(ret, line, branchunless, label); - } - ADD_INSN(ret, line, pop); - - CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); - if (!popped) { - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); - } - if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, line, newarray, INT2FIX(1)); - if (boff > 0) { - ADD_INSN1(ret, line, dupn, INT2FIX(3)); - ADD_INSN(ret, line, swap); - ADD_INSN(ret, line, pop); - } - ADD_INSN(ret, line, concatarray); - if (boff > 0) { - ADD_INSN1(ret, line, setn, INT2FIX(3)); - ADD_INSN(ret, line, pop); - ADD_INSN(ret, line, pop); - } - ADD_SEND_WITH_FLAG(ret, line, idASET, argc, INT2FIX(flag)); - } - else { - if (boff > 0) - ADD_INSN(ret, line, swap); - ADD_SEND_WITH_FLAG(ret, line, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); - } - ADD_INSN(ret, line, pop); - ADD_INSNL(ret, line, jump, lfin); - ADD_LABEL(ret, label); - if (!popped) { - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); - } - ADD_INSN1(ret, line, adjuststack, FIXNUM_INC(argc, 2+boff)); - ADD_LABEL(ret, lfin); - } - else { - CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); - ADD_SEND(ret, line, id, INT2FIX(1)); - if (!popped) { - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); - } - if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, line, newarray, INT2FIX(1)); - if (boff > 0) { - ADD_INSN1(ret, line, dupn, INT2FIX(3)); - ADD_INSN(ret, line, swap); - ADD_INSN(ret, line, pop); - } - ADD_INSN(ret, line, concatarray); - if (boff > 0) { - ADD_INSN1(ret, line, setn, INT2FIX(3)); - ADD_INSN(ret, line, pop); - ADD_INSN(ret, line, pop); - } - ADD_SEND_WITH_FLAG(ret, line, idASET, argc, INT2FIX(flag)); - } - else { - if (boff > 0) - ADD_INSN(ret, line, swap); - ADD_SEND_WITH_FLAG(ret, line, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); - } - ADD_INSN(ret, line, pop); - } - - break; - } - case NODE_OP_ASGN2:{ - ID atype = node->nd_next->nd_mid; - ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid); - int asgnflag; - LABEL *lfin = NEW_LABEL(line); - LABEL *lcfin = NEW_LABEL(line); - LABEL *lskip = 0; - /* - class C; attr_accessor :c; end - r = C.new - r.a &&= v # asgn2 - - eval r # r - dup # r r - eval r.a # r o - - # or - dup # r o o - if lcfin # r o - pop # r - eval v # r v - swap # v r - topn 1 # v r v - send a= # v ? - jump lfin # v ? - - lcfin: # r o - swap # o r - - lfin: # o ? - pop # o - - # and - dup # r o o - unless lcfin - pop # r - eval v # r v - swap # v r - topn 1 # v r v - send a= # v ? - jump lfin # v ? - - # others - eval v # r o v - send ?? # r w - send a= # w - - */ - - asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node); - CHECK(asgnflag != -1); - if (node->nd_next->nd_aid) { - lskip = NEW_LABEL(line); - ADD_INSN(ret, line, dup); - ADD_INSNL(ret, line, branchnil, lskip); - } - ADD_INSN(ret, line, dup); - ADD_SEND_WITH_FLAG(ret, line, vid, INT2FIX(0), INT2FIX(asgnflag)); - - if (atype == idOROP || atype == idANDOP) { - ADD_INSN(ret, line, dup); - if (atype == idOROP) { - ADD_INSNL(ret, line, branchif, lcfin); - } - else { /* idANDOP */ - ADD_INSNL(ret, line, branchunless, lcfin); - } - ADD_INSN(ret, line, pop); - CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); - ADD_INSN(ret, line, swap); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag)); - ADD_INSNL(ret, line, jump, lfin); - - ADD_LABEL(ret, lcfin); - ADD_INSN(ret, line, swap); - - ADD_LABEL(ret, lfin); - ADD_INSN(ret, line, pop); - if (lskip) { - ADD_LABEL(ret, lskip); - } - if (popped) { - /* we can apply more optimize */ - ADD_INSN(ret, line, pop); - } - } - else { - CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); - ADD_SEND(ret, line, atype, INT2FIX(1)); - if (!popped) { - ADD_INSN(ret, line, swap); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - } - ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag)); - if (lskip && popped) { - ADD_LABEL(ret, lskip); - } - ADD_INSN(ret, line, pop); - if (lskip && !popped) { - ADD_LABEL(ret, lskip); - } + ADD_INSN(ret, node, dup); } + ADD_SETLOCAL(ret, node, idx, get_lvar_level(iseq)); break; } - case NODE_OP_CDECL: { - LABEL *lfin = 0; - LABEL *lassign = 0; - ID mid; - - switch (nd_type(node->nd_head)) { - case NODE_COLON3: - ADD_INSN1(ret, line, putobject, rb_cObject); - break; - case NODE_COLON2: - CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", 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))); - goto ng; - } - mid = node->nd_head->nd_mid; - /* cref */ - if (node->nd_aid == idOROP) { - lassign = NEW_LABEL(line); - ADD_INSN(ret, line, dup); /* cref cref */ - ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST_FROM), - ID2SYM(mid), Qfalse); /* cref bool */ - ADD_INSNL(ret, line, branchunless, lassign); /* cref */ - } - ADD_INSN(ret, line, dup); /* cref cref */ - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */ - - if (node->nd_aid == idOROP || node->nd_aid == idANDOP) { - lfin = NEW_LABEL(line); - if (!popped) ADD_INSN(ret, line, dup); /* cref [obj] obj */ - if (node->nd_aid == idOROP) - ADD_INSNL(ret, line, branchif, lfin); - else /* idANDOP */ - ADD_INSNL(ret, line, branchunless, lfin); - /* cref [obj] */ - if (!popped) ADD_INSN(ret, line, pop); /* cref */ - if (lassign) ADD_LABEL(ret, lassign); - CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value)); - /* cref value */ - if (popped) - ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */ - else { - ADD_INSN1(ret, line, dupn, INT2FIX(2)); /* cref value cref value */ - ADD_INSN(ret, line, swap); /* cref value value cref */ - } - ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); /* cref [value] */ - ADD_LABEL(ret, lfin); /* cref [value] */ - if (!popped) ADD_INSN(ret, line, swap); /* [value] cref */ - ADD_INSN(ret, line, pop); /* [value] */ + case NODE_DASGN: { + int idx, lv, ls; + ID id = node->nd_vid; + CHECK(COMPILE(ret, "dvalue", node->nd_value)); + debugi("dassn id", rb_id2str(id) ? id : '*'); + + if (!popped) { + ADD_INSN(ret, node, dup); } - else { - CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value)); - /* cref obj value */ - ADD_CALL(ret, line, node->nd_aid, INT2FIX(1)); - /* cref value */ - ADD_INSN(ret, line, swap); /* value cref */ - if (!popped) { - ADD_INSN1(ret, line, topn, INT2FIX(1)); /* value cref value */ - ADD_INSN(ret, line, swap); /* value value cref */ - } - ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); + + idx = get_dyna_var_idx(iseq, id, &lv, &ls); + + if (idx < 0) { + COMPILE_ERROR(ERROR_ARGS "NODE_DASGN: unknown id (%"PRIsVALUE")", + rb_id2str(id)); + goto ng; } + ADD_SETLOCAL(ret, node, ls - idx, lv); break; } - case NODE_OP_ASGN_AND: - case NODE_OP_ASGN_OR:{ - LABEL *lfin = NEW_LABEL(line); - LABEL *lassign; - - if (nd_type(node) == NODE_OP_ASGN_OR) { - LABEL *lfinish[2]; - lfinish[0] = lfin; - lfinish[1] = 0; - defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); - lassign = lfinish[1]; - if (!lassign) { - lassign = NEW_LABEL(line); - } - ADD_INSNL(ret, line, branchunless, lassign); + case NODE_GASGN:{ + CHECK(COMPILE(ret, "lvalue", node->nd_value)); + + if (!popped) { + ADD_INSN(ret, node, dup); } - else { - lassign = NEW_LABEL(line); + ADD_INSN1(ret, node, setglobal, ID2SYM(node->nd_entry)); + break; + } + case NODE_IASGN:{ + CHECK(COMPILE(ret, "lvalue", 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)); + break; + } + case NODE_CDECL:{ + CHECK(COMPILE(ret, "lvalue", node->nd_value)); - CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head)); - ADD_INSN(ret, line, dup); + if (!popped) { + ADD_INSN(ret, node, dup); + } - if (nd_type(node) == NODE_OP_ASGN_AND) { - ADD_INSNL(ret, line, branchunless, lfin); + if (node->nd_vid) { + ADD_INSN1(ret, node, putspecialobject, + INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_vid)); } else { - ADD_INSNL(ret, line, branchif, lfin); + compile_cpath(ret, iseq, node->nd_else); + ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_else->nd_mid)); } - - ADD_INSN(ret, line, pop); - ADD_LABEL(ret, lassign); - CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value)); - ADD_LABEL(ret, lfin); - - if (popped) { - /* we can apply more optimize */ - ADD_INSN(ret, line, pop); + break; + } + case NODE_CVASGN:{ + CHECK(COMPILE(ret, "cvasgn val", node->nd_value)); + if (!popped) { + ADD_INSN(ret, node, dup); } + ADD_INSN2(ret, node, setclassvariable, + ID2SYM(node->nd_vid), + get_ivar_ic_value(iseq,node->nd_vid)); break; } + case NODE_OP_ASGN1: + CHECK(compile_op_asgn1(iseq, ret, node, popped)); + break; + case NODE_OP_ASGN2: + CHECK(compile_op_asgn2(iseq, ret, node, popped)); + break; + case NODE_OP_CDECL: + CHECK(compile_op_cdecl(iseq, ret, node, popped)); + break; + case NODE_OP_ASGN_AND: + case NODE_OP_ASGN_OR: + CHECK(compile_op_log(iseq, ret, node, popped, type)); + break; case NODE_CALL: /* obj.foo */ case NODE_OPCALL: /* foo[] */ - if (compile_call_precheck_freeze(iseq, ret, node, line, popped) == TRUE) { + if (compile_call_precheck_freeze(iseq, ret, node, node, popped) == TRUE) { break; } case NODE_QCALL: /* obj&.foo */ case NODE_FCALL: /* foo() */ case NODE_VCALL: /* foo (variable or call) */ - if (compile_call(iseq, ret, node, type, line, popped) == COMPILE_NG) { + if (compile_call(iseq, ret, node, type, node, popped, false) == COMPILE_NG) { goto ng; } break; case NODE_SUPER: - case NODE_ZSUPER:{ - DECL_ANCHOR(args); - int argc; - unsigned int flag = 0; - struct rb_call_info_kw_arg *keywords = NULL; - const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block; - - 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); - CHECK(!NIL_P(vargc)); - argc = FIX2INT(vargc); - } - else { - /* NODE_ZSUPER */ - int i; - const rb_iseq_t *liseq = body->local_iseq; - const struct rb_iseq_constant_body *const local_body = liseq->body; - const struct rb_iseq_param_keyword *const local_kwd = local_body->param.keyword; - int lvar_level = get_lvar_level(iseq); - - argc = local_body->param.lead_num; - - /* normal arguments */ - for (i = 0; i < local_body->param.lead_num; i++) { - int idx = local_body->local_table_size - i; - ADD_GETLOCAL(args, line, idx, lvar_level); - } - - if (local_body->param.flags.has_opt) { - /* optional arguments */ - int j; - for (j = 0; j < local_body->param.opt_num; j++) { - int idx = local_body->local_table_size - (i + j); - ADD_GETLOCAL(args, line, idx, lvar_level); - } - i += j; - argc = i; - } - if (local_body->param.flags.has_rest) { - /* rest argument */ - int idx = local_body->local_table_size - local_body->param.rest_start; - - ADD_GETLOCAL(args, line, idx, lvar_level); - ADD_INSN1(args, line, splatarray, Qfalse); - - argc = local_body->param.rest_start + 1; - flag |= VM_CALL_ARGS_SPLAT; - } - if (local_body->param.flags.has_post) { - /* post arguments */ - int post_len = local_body->param.post_num; - int post_start = local_body->param.post_start; - - if (local_body->param.flags.has_rest) { - int j; - for (j=0; jlocal_table_size - (post_start + j); - ADD_GETLOCAL(args, line, idx, lvar_level); - } - ADD_INSN1(args, line, newarray, INT2FIX(j)); - ADD_INSN (args, line, concatarray); - /* argc is settled at above */ - } - else { - int j; - for (j=0; jlocal_table_size - (post_start + j); - ADD_GETLOCAL(args, line, idx, lvar_level); - } - argc = post_len + post_start; - } - } - - if (local_body->param.flags.has_kw) { /* TODO: support keywords */ - int local_size = local_body->local_table_size; - argc++; - - ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - - if (local_body->param.flags.has_kwrest) { - int idx = local_body->local_table_size - local_kwd->rest_start; - ADD_GETLOCAL(args, line, idx, lvar_level); - ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0)); - } - else { - ADD_INSN1(args, line, newhash, INT2FIX(0)); - } - for (i = 0; i < local_kwd->num; ++i) { - ID id = local_kwd->table[i]; - int idx = local_size - get_local_var_idx(liseq, id); - ADD_INSN1(args, line, putobject, ID2SYM(id)); - ADD_GETLOCAL(args, line, idx, lvar_level); - } - ADD_SEND(args, line, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1)); - if (local_body->param.flags.has_rest) { - ADD_INSN1(args, line, newarray, INT2FIX(1)); - ADD_INSN (args, line, concatarray); - --argc; - } - flag |= VM_CALL_KW_SPLAT; - } - else if (local_body->param.flags.has_kwrest) { - int idx = local_body->local_table_size - local_kwd->rest_start; - ADD_GETLOCAL(args, line, idx, lvar_level); - - ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0)); - if (local_body->param.flags.has_rest) { - ADD_INSN1(args, line, newarray, INT2FIX(1)); - ADD_INSN (args, line, concatarray); - } - else { - argc++; - } - flag |= VM_CALL_KW_SPLAT; - } - } - - ADD_INSN(ret, line, putself); - ADD_SEQ(ret, args); - ADD_INSN2(ret, line, invokesuper, - new_callinfo(iseq, 0, argc, flag | VM_CALL_SUPER | (type == NODE_ZSUPER ? VM_CALL_ZSUPER : 0) | VM_CALL_FCALL, keywords, parent_block != NULL), - parent_block); - - if (popped) { - ADD_INSN(ret, line, pop); - } + case NODE_ZSUPER: + CHECK(compile_super(iseq, ret, node, popped, type)); break; - } case NODE_LIST:{ CHECK(compile_array(iseq, ret, node, popped) >= 0); break; } case NODE_ZLIST:{ if (!popped) { - ADD_INSN1(ret, line, newarray, INT2FIX(0)); + ADD_INSN1(ret, node, newarray, INT2FIX(0)); } break; } @@ -7822,51 +9311,21 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in CHECK(COMPILE(ret, "values item", n->nd_head)); n = n->nd_next; } - ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen)); + ADD_INSN1(ret, node, newarray, INT2FIX(node->nd_alen)); break; } case NODE_HASH: - CHECK(compile_hash(iseq, ret, node, popped) >= 0); + CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0); break; case NODE_RETURN: CHECK(compile_return(iseq, ret, node, popped)); break; - case NODE_YIELD:{ - DECL_ANCHOR(args); - VALUE argc; - unsigned int flag = 0; - struct rb_call_info_kw_arg *keywords = NULL; - - INIT_ANCHOR(args); - - if (check_yield_place(iseq, line) == FALSE) { - COMPILE_ERROR(ERROR_ARGS "Invalid yield"); - goto ng; - } - - if (node->nd_head) { - argc = setup_args(iseq, args, node->nd_head, &flag, &keywords); - CHECK(!NIL_P(argc)); - } - else { - argc = INT2FIX(0); - } - - ADD_SEQ(ret, args); - ADD_INSN1(ret, line, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE)); - - if (popped) { - ADD_INSN(ret, line, pop); - } + case NODE_YIELD: + CHECK(compile_yield(iseq, ret, node, popped)); break; - } case NODE_LVAR:{ if (!popped) { - ID id = node->nd_vid; - int idx = body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id); - - debugs("id: %s idx: %d\n", rb_id2name(id), idx); - ADD_GETLOCAL(ret, line, idx, get_lvar_level(iseq)); + compile_lvar(iseq, ret, node, node->nd_vid); } break; } @@ -7880,22 +9339,21 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in rb_id2str(node->nd_vid)); goto ng; } - ADD_GETLOCAL(ret, line, ls - idx, lv); + ADD_GETLOCAL(ret, node, ls - idx, lv); } break; } case NODE_GVAR:{ - ADD_INSN1(ret, line, getglobal, - ((VALUE)node->nd_entry | 1)); + ADD_INSN1(ret, node, getglobal, ID2SYM(node->nd_entry)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_IVAR:{ debugi("nd_vid", node->nd_vid); if (!popped) { - ADD_INSN2(ret, line, getinstancevariable, + ADD_INSN2(ret, node, getinstancevariable, ID2SYM(node->nd_vid), get_ivar_ic_value(iseq,node->nd_vid)); } @@ -7908,89 +9366,59 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in LABEL *lend = NEW_LABEL(line); int ic_index = body->is_size++; - ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index)); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); - ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index)); + ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index)); + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); } else { - ADD_INSN(ret, line, putnil); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); + ADD_INSN(ret, node, putnil); + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid)); } if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_CVAR:{ if (!popped) { - ADD_INSN1(ret, line, getclassvariable, - ID2SYM(node->nd_vid)); + ADD_INSN2(ret, node, getclassvariable, + ID2SYM(node->nd_vid), + get_ivar_ic_value(iseq,node->nd_vid)); } break; } case NODE_NTH_REF:{ if (!popped) { if (!node->nd_nth) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, node, putnil); break; } - ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, + ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */, INT2FIX(node->nd_nth << 1)); } break; } case NODE_BACK_REF:{ if (!popped) { - ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, + ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */, INT2FIX(0x01 | (node->nd_nth << 1))); } break; } case NODE_MATCH: case NODE_MATCH2: - case NODE_MATCH3:{ - DECL_ANCHOR(recv); - DECL_ANCHOR(val); - - INIT_ANCHOR(recv); - INIT_ANCHOR(val); - switch (nd_type(node)) { - case NODE_MATCH: - ADD_INSN1(recv, line, putobject, node->nd_lit); - ADD_INSN2(val, line, getspecial, INT2FIX(0), - INT2FIX(0)); - break; - case NODE_MATCH2: - CHECK(COMPILE(recv, "receiver", node->nd_recv)); - CHECK(COMPILE(val, "value", node->nd_value)); - break; - case NODE_MATCH3: - CHECK(COMPILE(recv, "receiver", node->nd_value)); - CHECK(COMPILE(val, "value", node->nd_recv)); - break; - } - - ADD_SEQ(ret, recv); - ADD_SEQ(ret, val); - ADD_SEND(ret, line, idEqTilde, INT2FIX(1)); - - if (node->nd_args) { - compile_named_capture_assign(iseq, ret, node->nd_args); - } - - if (popped) { - ADD_INSN(ret, line, pop); - } + case NODE_MATCH3: + CHECK(compile_match(iseq, ret, node, popped, type)); break; - } case NODE_LIT:{ debugp_param("lit", node->nd_lit); if (!popped) { - ADD_INSN1(ret, line, putobject, node->nd_lit); + ADD_INSN1(ret, node, putobject, node->nd_lit); + RB_OBJ_WRITTEN(iseq, Qundef, node->nd_lit); } break; } @@ -8000,7 +9428,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in VALUE lit = node->nd_lit; if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) { lit = rb_fstring(lit); - ADD_INSN1(ret, line, putstring, lit); + ADD_INSN1(ret, node, putstring, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); } else { @@ -8013,7 +9441,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in else { lit = rb_fstring(lit); } - ADD_INSN1(ret, line, putobject, lit); + ADD_INSN1(ret, node, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); } } @@ -8023,41 +9451,29 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in compile_dstr(iseq, ret, node); if (popped) { - ADD_INSN(ret, line, pop); - } - else { - if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) { - VALUE debug_info = Qnil; - if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { - debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line)); - } - ADD_INSN1(ret, line, freezestring, debug_info); - if (!NIL_P(debug_info)) { - RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_freeze(debug_info)); - } - } + ADD_INSN(ret, node, pop); } break; } case NODE_XSTR:{ - ADD_CALL_RECEIVER(ret, line); + ADD_CALL_RECEIVER(ret, node); VALUE str = rb_fstring(node->nd_lit); - ADD_INSN1(ret, line, putobject, str); + ADD_INSN1(ret, node, putobject, str); RB_OBJ_WRITTEN(iseq, Qundef, str); - ADD_CALL(ret, line, idBackquote, INT2FIX(1)); + ADD_CALL(ret, node, idBackquote, INT2FIX(1)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_DXSTR:{ - ADD_CALL_RECEIVER(ret, line); + ADD_CALL_RECEIVER(ret, node); compile_dstr(iseq, ret, node); - ADD_CALL(ret, line, idBackquote, INT2FIX(1)); + ADD_CALL(ret, node, idBackquote, INT2FIX(1)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } @@ -8068,7 +9484,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in compile_dregx(iseq, ret, node); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } @@ -8077,51 +9493,50 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in const rb_iseq_t *block_iseq; block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line); - ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index)); + ADD_INSN2(ret, node, once, block_iseq, INT2FIX(ic_index)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block_iseq); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_ARGSCAT:{ if (popped) { CHECK(COMPILE(ret, "argscat head", node->nd_head)); - ADD_INSN1(ret, line, splatarray, Qfalse); - ADD_INSN(ret, line, pop); + ADD_INSN1(ret, node, splatarray, Qfalse); + ADD_INSN(ret, node, pop); CHECK(COMPILE(ret, "argscat body", node->nd_body)); - ADD_INSN1(ret, line, splatarray, Qfalse); - ADD_INSN(ret, line, pop); + 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, line, concatarray); + ADD_INSN(ret, node, concatarray); } break; } case NODE_ARGSPUSH:{ if (popped) { - CHECK(COMPILE(ret, "arsgpush head", node->nd_head)); - ADD_INSN1(ret, line, splatarray, Qfalse); - ADD_INSN(ret, line, pop); + CHECK(COMPILE(ret, "argspush head", node->nd_head)); + ADD_INSN1(ret, node, splatarray, Qfalse); + ADD_INSN(ret, node, pop); CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped)); } else { - CHECK(COMPILE(ret, "arsgpush head", node->nd_head)); - CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped)); - ADD_INSN1(ret, line, newarray, INT2FIX(1)); - ADD_INSN(ret, line, concatarray); + CHECK(COMPILE(ret, "argspush head", node->nd_head)); + CHECK(compile_array_1(iseq, ret, node->nd_body)); + ADD_INSN(ret, node, concatarray); } break; } case NODE_SPLAT:{ CHECK(COMPILE(ret, "splat", node->nd_head)); - ADD_INSN1(ret, line, splatarray, Qtrue); + ADD_INSN1(ret, node, splatarray, Qtrue); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } @@ -8132,11 +9547,11 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in ISEQ_TYPE_METHOD, line); debugp_param("defn/iseq", rb_iseqw_new(method_iseq)); - ADD_INSN2(ret, line, definemethod, ID2SYM(mid), method_iseq); + ADD_INSN2(ret, node, definemethod, ID2SYM(mid), method_iseq); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)method_iseq); if (!popped) { - ADD_INSN1(ret, line, putobject, ID2SYM(mid)); + ADD_INSN1(ret, node, putobject, ID2SYM(mid)); } break; @@ -8149,78 +9564,78 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq)); CHECK(COMPILE(ret, "defs: recv", node->nd_recv)); - ADD_INSN2(ret, line, definesmethod, ID2SYM(mid), singleton_method_iseq); + ADD_INSN2(ret, node, definesmethod, ID2SYM(mid), singleton_method_iseq); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_method_iseq); if (!popped) { - ADD_INSN1(ret, line, putobject, ID2SYM(mid)); + ADD_INSN1(ret, node, putobject, ID2SYM(mid)); } break; } case NODE_ALIAS:{ - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); + 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)); - ADD_SEND(ret, line, id_core_set_method_alias, INT2FIX(3)); + ADD_SEND(ret, node, id_core_set_method_alias, INT2FIX(3)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_VALIAS:{ - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_alias)); - ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_orig)); - ADD_SEND(ret, line, id_core_set_variable_alias, INT2FIX(2)); + 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_SEND(ret, node, id_core_set_variable_alias, INT2FIX(2)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_UNDEF:{ - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); + 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, line, id_core_undef_method, INT2FIX(2)); + ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2)); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_CLASS:{ const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body, - rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid)), + rb_str_freeze(rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid))), 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); CHECK(COMPILE(ret, "super", node->nd_super)); - ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags)); + ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)class_iseq); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } case NODE_MODULE:{ const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body, - rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid)), + rb_str_freeze(rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid))), ISEQ_TYPE_CLASS, line); const int flags = VM_DEFINECLASS_TYPE_MODULE | compile_cpath(ret, iseq, node->nd_cpath); - ADD_INSN (ret, line, putnil); /* dummy */ - ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags)); + ADD_INSN (ret, node, putnil); /* dummy */ + ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)module_iseq); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } @@ -8230,109 +9645,30 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in ISEQ_TYPE_CLASS, line); CHECK(COMPILE(ret, "sclass#recv", node->nd_recv)); - ADD_INSN (ret, line, putnil); + ADD_INSN (ret, node, putnil); CONST_ID(singletonclass, "singletonclass"); - ADD_INSN3(ret, line, defineclass, + ADD_INSN3(ret, node, defineclass, ID2SYM(singletonclass), singleton_class, INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_class); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } - case NODE_COLON2:{ - if (rb_is_const_id(node->nd_mid)) { - /* constant */ - LABEL *lend = NEW_LABEL(line); - int ic_index = body->is_size++; - - DECL_ANCHOR(pref); - DECL_ANCHOR(body); - - INIT_ANCHOR(pref); - INIT_ANCHOR(body); - CHECK(compile_const_prefix(iseq, node, pref, body)); - if (LIST_INSN_SIZE_ZERO(pref)) { - if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { - ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index)); - } - else { - ADD_INSN(ret, line, putnil); - } - - ADD_SEQ(ret, body); - - if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { - ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index)); - ADD_LABEL(ret, lend); - } - } - else { - ADD_SEQ(ret, pref); - ADD_SEQ(ret, body); - } - } - else { - /* function call */ - ADD_CALL_RECEIVER(ret, line); - CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head)); - ADD_CALL(ret, line, node->nd_mid, INT2FIX(1)); - } - if (popped) { - ADD_INSN(ret, line, pop); - } + case NODE_COLON2: + CHECK(compile_colon2(iseq, ret, node, popped)); break; - } - case NODE_COLON3:{ - LABEL *lend = NEW_LABEL(line); - int ic_index = body->is_size++; - - debugi("colon3#nd_mid", node->nd_mid); - - /* add cache insn */ - if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { - ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index)); - ADD_INSN(ret, line, pop); - } - - ADD_INSN1(ret, line, putobject, rb_cObject); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid)); - - if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { - ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index)); - ADD_LABEL(ret, lend); - } - - if (popped) { - ADD_INSN(ret, line, pop); - } + case NODE_COLON3: + CHECK(compile_colon3(iseq, ret, node, popped)); break; - } case NODE_DOT2: - case NODE_DOT3:{ - int excl = type == NODE_DOT3; - VALUE flag = INT2FIX(excl); - const NODE *b = node->nd_beg; - const NODE *e = node->nd_end; - if (number_literal_p(b) && number_literal_p(e)) { - if (!popped) { - VALUE val = rb_range_new(b->nd_lit, e->nd_lit, excl); - ADD_INSN1(ret, line, putobject, val); - RB_OBJ_WRITTEN(iseq, Qundef, val); - } - } - else { - CHECK(COMPILE_(ret, "min", b, popped)); - CHECK(COMPILE_(ret, "max", e, popped)); - if (!popped) { - ADD_INSN1(ret, line, newrange, flag); - } - } + CHECK(compile_dots(iseq, ret, node, popped, FALSE)); + break; + case NODE_DOT3: + CHECK(compile_dots(iseq, ret, node, popped, TRUE)); break; - } case NODE_FLIP2: case NODE_FLIP3:{ LABEL *lend = NEW_LABEL(line); @@ -8341,225 +9677,91 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in CHECK(compile_flip_flop(iseq, ret, node, type == NODE_FLIP2, ltrue, lfalse)); ADD_LABEL(ret, ltrue); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, lend); + ADD_INSN1(ret, node, putobject, Qtrue); + ADD_INSNL(ret, node, jump, lend); ADD_LABEL(ret, lfalse); - ADD_INSN1(ret, line, putobject, Qfalse); + ADD_INSN1(ret, node, putobject, Qfalse); ADD_LABEL(ret, lend); break; } case NODE_SELF:{ if (!popped) { - ADD_INSN(ret, line, putself); + ADD_INSN(ret, node, putself); } break; } case NODE_NIL:{ if (!popped) { - ADD_INSN(ret, line, putnil); + ADD_INSN(ret, node, putnil); } break; } case NODE_TRUE:{ if (!popped) { - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_INSN1(ret, node, putobject, Qtrue); } break; } case NODE_FALSE:{ if (!popped) { - ADD_INSN1(ret, line, putobject, Qfalse); + ADD_INSN1(ret, node, putobject, Qfalse); } break; } - case NODE_ERRINFO:{ - if (!popped) { - if (body->type == ISEQ_TYPE_RESCUE) { - ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); - } - else { - const rb_iseq_t *ip = iseq; - int level = 0; - while (ip) { - if (ip->body->type == ISEQ_TYPE_RESCUE) { - break; - } - ip = ip->body->parent_iseq; - level++; - } - if (ip) { - ADD_GETLOCAL(ret, line, LVAR_ERRINFO, level); - } - else { - ADD_INSN(ret, line, putnil); - } - } - } + case NODE_ERRINFO: + CHECK(compile_errinfo(iseq, ret, node, popped)); break; - } case NODE_DEFINED: if (!popped) { CHECK(compile_defined_expr(iseq, ret, node, Qtrue)); - } - break; - case NODE_POSTEXE:{ - /* compiled to: - * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } } - */ - int is_index = body->is_size++; - struct rb_iseq_new_with_callback_callback_func *ifunc = - rb_iseq_new_with_callback_new_callback(build_postexe_iseq, 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); - - ADD_INSN2(ret, line, once, once_iseq, INT2FIX(is_index)); - RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)once_iseq); - - if (popped) { - ADD_INSN(ret, line, pop); - } - break; - } - case NODE_KW_ARG: - { - LABEL *end_label = NEW_LABEL(nd_line(node)); - const NODE *default_value = node->nd_body->nd_value; - - if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) { - /* required argument. do nothing */ - COMPILE_ERROR(ERROR_ARGS "unreachable"); - goto ng; - } - else if (nd_type(default_value) == NODE_LIT || - nd_type(default_value) == NODE_NIL || - nd_type(default_value) == NODE_TRUE || - nd_type(default_value) == NODE_FALSE) { - COMPILE_ERROR(ERROR_ARGS "unreachable"); - goto 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, line, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx)); - ADD_INSNL(ret, line, branchif, end_label); - CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body)); - ADD_LABEL(ret, end_label); - } - - break; - } - case NODE_DSYM:{ - compile_dstr(iseq, ret, node); - if (!popped) { - ADD_INSN(ret, line, intern); - } - else { - ADD_INSN(ret, line, pop); - } - break; - } - case NODE_ATTRASGN:{ - DECL_ANCHOR(recv); - DECL_ANCHOR(args); - unsigned int flag = 0; - ID mid = node->nd_mid; - VALUE argc; - LABEL *else_label = NULL; - VALUE branches = Qfalse; - - /* optimization shortcut - * obj["literal"] = value -> opt_aset_with(obj, "literal", value) - */ - if (mid == idASET && !private_recv_p(node) && node->nd_args && - nd_type(node->nd_args) == NODE_LIST && node->nd_args->nd_alen == 2 && - nd_type(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, line, swap); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - } - ADD_INSN2(ret, line, opt_aset_with, str, - new_callinfo(iseq, idASET, 2, 0, NULL, FALSE)); - RB_OBJ_WRITTEN(iseq, Qundef, str); - ADD_INSN(ret, line, pop); - break; - } - - 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; + } + break; + case NODE_POSTEXE:{ + /* compiled to: + * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } } + */ + int is_index = body->is_size++; + struct rb_iseq_new_with_callback_callback_func *ifunc = + rb_iseq_new_with_callback_new_callback(build_postexe_iseq, 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); - debugp_param("argc", argc); - debugp_param("nd_mid", ID2SYM(mid)); + ADD_INSN2(ret, node, once, once_iseq, INT2FIX(is_index)); + RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)once_iseq); - if (!rb_is_attrset_id(mid)) { - /* safe nav attr */ - mid = rb_id_attrset(mid); - else_label = qcall_branch_start(iseq, recv, &branches, node, line); + if (popped) { + ADD_INSN(ret, node, pop); } + break; + } + case NODE_KW_ARG: + CHECK(compile_kw_arg(iseq, ret, node, popped)); + break; + case NODE_DSYM:{ + compile_dstr(iseq, ret, node); if (!popped) { - ADD_INSN(ret, line, putnil); - ADD_SEQ(ret, recv); - ADD_SEQ(ret, args); - - if (flag & VM_CALL_ARGS_BLOCKARG) { - ADD_INSN1(ret, line, topn, INT2FIX(1)); - if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, line, putobject, INT2FIX(-1)); - ADD_SEND_WITH_FLAG(ret, line, idAREF, INT2FIX(1), INT2FIX(asgnflag)); - } - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 3)); - ADD_INSN (ret, line, pop); - } - else if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(-1)); - ADD_SEND_WITH_FLAG(ret, line, idAREF, INT2FIX(1), INT2FIX(asgnflag)); - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2)); - ADD_INSN (ret, line, pop); - } - else { - ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 1)); - } + ADD_INSN(ret, node, intern); } else { - ADD_SEQ(ret, recv); - ADD_SEQ(ret, args); + ADD_INSN(ret, node, pop); } - ADD_SEND_WITH_FLAG(ret, line, mid, argc, INT2FIX(flag)); - qcall_branch_end(iseq, ret, else_label, branches, node, line); - ADD_INSN(ret, line, pop); - break; } + case NODE_ATTRASGN: + CHECK(compile_attrasgn(iseq, ret, node, popped)); + 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); VALUE argc = INT2FIX(0); - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_CALL_WITH_BLOCK(ret, line, idLambda, argc, block); + ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_CALL_WITH_BLOCK(ret, node, idLambda, argc, block); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block); if (popped) { - ADD_INSN(ret, line, pop); + ADD_INSN(ret, node, pop); } break; } @@ -8593,15 +9795,16 @@ calc_sp_depth(int depth, INSN *insn) static VALUE opobj_inspect(VALUE obj) { - struct RBasic *r = (struct RBasic *) obj; - if (!SPECIAL_CONST_P(r) && r->klass == 0) { - switch (BUILTIN_TYPE(r)) { + if (!SPECIAL_CONST_P(obj) && !RBASIC_CLASS(obj)) { + switch (BUILTIN_TYPE(obj)) { case T_STRING: obj = rb_str_new_cstr(RSTRING_PTR(obj)); break; case T_ARRAY: obj = rb_ary_dup(obj); break; + default: + break; } } return rb_inspect(obj); @@ -8644,19 +9847,16 @@ insn_data_to_s_detail(INSN *iobj) case TS_VALUE: /* VALUE */ { VALUE v = OPERAND_AT(iobj, j); - rb_str_concat(str, opobj_inspect(v)); + if (!CLASS_OF(v)) + rb_str_cat2(str, ""); + else { + rb_str_concat(str, opobj_inspect(v)); + } break; } case TS_ID: /* ID */ rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j))); break; - case TS_GENTRY: - { - struct rb_global_entry *entry = (struct rb_global_entry *) - (OPERAND_AT(iobj, j) & (~1)); - rb_str_append(str, rb_id2str(entry->id)); - break; - } case TS_IC: /* inline cache */ case TS_IVC: /* inline ivar cache */ case TS_ISE: /* inline storage entry */ @@ -8664,10 +9864,10 @@ insn_data_to_s_detail(INSN *iobj) break; case TS_CALLDATA: /* we store these as call infos at compile time */ { - const struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, j); + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, j); rb_str_cat2(str, "mid) rb_str_catf(str, "%"PRIsVALUE, rb_id2str(ci->mid)); - rb_str_catf(str, ", %d>", ci->orig_argc); + if (vm_ci_mid(ci)) rb_str_catf(str, "%"PRIsVALUE, rb_id2str(vm_ci_mid(ci))); + rb_str_catf(str, ", %d>", vm_ci_argc(ci)); break; } case TS_CDHASH: /* case/when condition cache */ @@ -8687,7 +9887,7 @@ insn_data_to_s_detail(INSN *iobj) } break; case TS_BUILTIN: - rb_bug("unsupported: TS_BUILTIN"); + rb_str_cat2(str, ""); break; default:{ rb_raise(rb_eSyntaxError, "unknown operand type: %c", type); @@ -8724,7 +9924,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, { iobj = (INSN *)link; str = insn_data_to_s_detail(iobj); - printf("%04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no); + printf(" %04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no); pos += insn_data_length(iobj); break; } @@ -8738,13 +9938,13 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, case ISEQ_ELEMENT_TRACE: { TRACE *trace = (TRACE *)link; - printf("trace: %0x\n", trace->event); + printf(" trace: %0x\n", trace->event); break; } case ISEQ_ELEMENT_ADJUST: { ADJUST *adjust = (ADJUST *)link; - printf("adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1); + printf(" adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1); break; } default: @@ -8795,18 +9995,16 @@ register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj) static VALUE get_exception_sym2type(VALUE sym) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) static VALUE symRescue, symEnsure, symRetry; static VALUE symBreak, symRedo, symNext; if (symRescue == 0) { - symRescue = ID2SYM(rb_intern("rescue")); - symEnsure = ID2SYM(rb_intern("ensure")); - symRetry = ID2SYM(rb_intern("retry")); - symBreak = ID2SYM(rb_intern("break")); - symRedo = ID2SYM(rb_intern("redo")); - symNext = ID2SYM(rb_intern("next")); + symRescue = ID2SYM(rb_intern_const("rescue")); + symEnsure = ID2SYM(rb_intern_const("ensure")); + symRetry = ID2SYM(rb_intern_const("retry")); + symBreak = ID2SYM(rb_intern_const("break")); + symRedo = ID2SYM(rb_intern_const("redo")); + symNext = ID2SYM(rb_intern_const("next")); } if (sym == symRescue) return CATCH_TYPE_RESCUE; @@ -8836,7 +10034,7 @@ iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, rb_raise(rb_eSyntaxError, "wrong exception entry"); } type = get_exception_sym2type(RARRAY_AREF(v, 0)); - if (RARRAY_AREF(v, 1) == Qnil) { + if (NIL_P(RARRAY_AREF(v, 1))) { eiseq = NULL; } else { @@ -8872,7 +10070,7 @@ insn_make_insn_table(void) table = st_init_numtable_with_size(VM_INSTRUCTION_SIZE); for (i=0; ikeyword_len = len; @@ -8931,13 +10129,15 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op) } } - return (VALUE)new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0); + const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0); + RB_OBJ_WRITTEN(iseq, Qundef, ci); + return (VALUE)ci; } static rb_event_flag_t event_name_to_flag(VALUE sym) { -#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern(#ev))) return ev; +#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev; CHECK_EVENT(RUBY_EVENT_LINE); CHECK_EVENT(RUBY_EVENT_CLASS); CHECK_EVENT(RUBY_EVENT_END); @@ -8951,13 +10151,13 @@ event_name_to_flag(VALUE sym) static int iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, - VALUE body, VALUE labels_wrapper) + VALUE body, VALUE node_ids, VALUE labels_wrapper) { /* TODO: body should be frozen */ long i, len = RARRAY_LEN(body); struct st_table *labels_table = DATA_PTR(labels_wrapper); int j; - int line_no = 0; + int line_no = 0, node_id = -1, insn_idx = 0; int ret = COMPILE_OK; /* @@ -8991,6 +10191,10 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, st_data_t insn_id; VALUE insn; + if (node_ids) { + node_id = NUM2INT(rb_ary_entry(node_ids, insn_idx++)); + } + insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0); if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) { /* TODO: exception */ @@ -9008,7 +10212,14 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, } if (argc > 0) { - argv = compile_data_alloc2(iseq, sizeof(VALUE), argc); + 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, + (enum ruby_vminsn_type)insn_id, argc, argv)); + for (j=0; j= iseq->body->is_size) { iseq->body->is_size = NUM2INT(op) + 1; } + FL_SET((VALUE)iseq, ISEQ_MARKABLE_ISEQ); break; case TS_CALLDATA: argv[j] = iseq_build_callinfo_from_hash(iseq, op); @@ -9092,9 +10298,12 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, } } } - ADD_ELEM(anchor, - (LINK_ELEMENT*)new_insn_core(iseq, line_no, - (enum ruby_vminsn_type)insn_id, argc, argv)); + else { + NODE dummy_line_node = generate_dummy_line_node(line_no, node_id); + ADD_ELEM(anchor, + (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node, + (enum ruby_vminsn_type)insn_id, argc, NULL)); + } } else { rb_raise(rb_eTypeError, "unexpected object for instruction"); @@ -9138,7 +10347,7 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords) iseq->body->param.flags.has_kw = TRUE; keyword->num = len; -#define SYM(s) ID2SYM(rb_intern(#s)) +#define SYM(s) ID2SYM(rb_intern_const(#s)) (void)int_param(&keyword->bits_start, params, SYM(kwbits)); i = keyword->bits_start - keyword->num; ids = (ID *)&iseq->body->local_table[i]; @@ -9228,13 +10437,15 @@ rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage) case TS_CDHASH: case TS_ISEQ: case TS_VALUE: + case TS_CALLDATA: // ci is stored. { VALUE op = OPERAND_AT(iobj, j); + if (!SPECIAL_CONST_P(op)) { rb_gc_mark(op); } - break; } + break; default: break; } @@ -9249,7 +10460,7 @@ void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body) { -#define SYM(s) ID2SYM(rb_intern(#s)) +#define SYM(s) ID2SYM(rb_intern_const(#s)) int i, len; unsigned int arg_size, local_size, stack_max; ID *tbl; @@ -9257,7 +10468,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, 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("#arg_rest")); + VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest")); DECL_ANCHOR(anchor); INIT_ANCHOR(anchor); @@ -9294,6 +10505,14 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, #undef INT_PARAM } + VALUE node_ids = Qfalse; +#ifdef USE_ISEQ_NODE_ID + node_ids = rb_hash_aref(misc, ID2SYM(rb_intern("node_ids"))); + if (!RB_TYPE_P(node_ids, T_ARRAY)) { + rb_raise(rb_eTypeError, "node_ids is not an array"); + } +#endif + if (RB_TYPE_P(arg_opt_labels, T_ARRAY)) { len = RARRAY_LENINT(arg_opt_labels); iseq->body->param.flags.has_opt = !!(len - 1 >= 0); @@ -9343,7 +10562,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, iseq_build_from_ary_exception(iseq, labels_table, exception); /* body */ - iseq_build_from_ary_body(iseq, anchor, body, labels_wrapper); + iseq_build_from_ary_body(iseq, anchor, body, node_ids, labels_wrapper); iseq->body->param.size = arg_size; iseq->body->local_table_size = local_size; @@ -9393,100 +10612,6 @@ rb_local_defined(ID id, const rb_iseq_t *iseq) return 0; } -static int -caller_location(VALUE *path, VALUE *realpath) -{ - const rb_execution_context_t *ec = GET_EC(); - const rb_control_frame_t *const cfp = - rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); - - if (cfp) { - int line = rb_vm_get_sourceline(cfp); - *path = rb_iseq_path(cfp->iseq); - *realpath = rb_iseq_realpath(cfp->iseq); - return line; - } - else { - *path = rb_fstring_lit(""); - *realpath = *path; - return 1; - } -} - -typedef struct { - VALUE arg; - rb_insn_func_t func; - int line; -} accessor_args; - -static const rb_iseq_t * -method_for_self(VALUE name, VALUE arg, rb_insn_func_t func, - void (*build)(rb_iseq_t *, LINK_ANCHOR *, const void *)) -{ - VALUE path, realpath; - accessor_args acc; - - acc.arg = arg; - acc.func = func; - acc.line = caller_location(&path, &realpath); - struct rb_iseq_new_with_callback_callback_func *ifunc = - rb_iseq_new_with_callback_new_callback(build, &acc); - return rb_iseq_new_with_callback(ifunc, - rb_sym2str(name), path, realpath, - INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0); -} - -static void -for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a) -{ - const accessor_args *const args = (void *)a; - const int line = args->line; - struct rb_iseq_constant_body *const body = iseq->body; - - iseq_set_local_table(iseq, 0); - body->param.lead_num = 0; - body->param.size = 0; - - ADD_INSN1(ret, line, putobject, args->arg); - ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func); -} - -static void -for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a) -{ - const accessor_args *const args = (void *)a; - const int line = args->line; - struct rb_iseq_constant_body *const body = iseq->body; - static const ID vars[] = {1, idUScore}; - - iseq_set_local_table(iseq, vars); - body->param.lead_num = 1; - body->param.size = 1; - - ADD_GETLOCAL(ret, line, numberof(vars)-1, 0); - ADD_INSN1(ret, line, putobject, args->arg); - ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func); - ADD_INSN(ret, line, pop); -} - -/* - * func (index) -> (value) - */ -const rb_iseq_t * -rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func) -{ - return method_for_self(name, arg, func, for_self_aref); -} - -/* - * func (index, value) -> (index, value) - */ -const rb_iseq_t * -rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func) -{ - return method_for_self(name, arg, func, for_self_aset); -} - /* ISeq binary format */ #ifndef IBF_ISEQ_DEBUG @@ -9502,7 +10627,7 @@ typedef unsigned int ibf_offset_t; #define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION #if RUBY_DEVEL -#define IBF_DEVEL_VERSION 2 +#define IBF_DEVEL_VERSION 3 #define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION) #else #define IBF_MINOR_VERSION ISEQ_MINOR_VERSION @@ -9523,11 +10648,10 @@ struct ibf_header { struct ibf_dump_buffer { VALUE str; - VALUE obj_list; /* [objs] */ + st_table *obj_table; /* obj -> obj number */ }; struct ibf_dump { - VALUE iseq_list; /* [iseqs] */ st_table *iseq_table; /* iseq -> iseq number */ struct ibf_dump_buffer global_buffer; struct ibf_dump_buffer *current_buffer; @@ -9554,6 +10678,85 @@ struct ibf_load { struct ibf_load_buffer *current_buffer; }; +struct pinned_list { + long size; + VALUE * buffer; +}; + +static void +pinned_list_mark(void *ptr) +{ + long i; + struct pinned_list *list = (struct pinned_list *)ptr; + for (i = 0; i < list->size; i++) { + if (list->buffer[i]) { + rb_gc_mark(list->buffer[i]); + } + } +} + +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 +}; + +static VALUE +pinned_list_fetch(VALUE list, long offset) +{ + struct pinned_list * ptr; + + TypedData_Get_Struct(list, struct pinned_list, &pinned_list_type, ptr); + + if (offset >= ptr->size) { + rb_raise(rb_eIndexError, "object index out of range: %ld", offset); + } + + return ptr->buffer[offset]; +} + +static void +pinned_list_store(VALUE list, long offset, VALUE object) +{ + struct pinned_list * ptr; + + TypedData_Get_Struct(list, struct pinned_list, &pinned_list_type, ptr); + + if (offset >= ptr->size) { + rb_raise(rb_eIndexError, "object index out of range: %ld", offset); + } + + RB_OBJ_WRITE(list, &ptr->buffer[offset], 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)); + ptr->size = size; + + return obj_list; +} + static ibf_offset_t ibf_dump_pos(struct ibf_dump *dump) { @@ -9649,7 +10852,7 @@ ibf_table_lookup(struct st_table *table, st_data_t key) } static int -ibf_table_index(struct st_table *table, st_data_t key) +ibf_table_find_or_insert(struct st_table *table, st_data_t key) { int index = ibf_table_lookup(table, key); @@ -9668,26 +10871,19 @@ static void ibf_dump_object_list(struct ibf_dump *dump, ibf_offset_t *obj_list_o static VALUE ibf_load_object(const struct ibf_load *load, VALUE object_index); static rb_iseq_t *ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq); -static VALUE -ibf_dump_object_list_new(void) +static st_table * +ibf_dump_object_table_new(void) { - VALUE obj_list = rb_ary_tmp_new(1); - rb_ary_push(obj_list, Qnil); /* 0th is nil */ + st_table *obj_table = st_init_numtable(); /* need free */ + st_insert(obj_table, (st_data_t)Qnil, (st_data_t)0); /* 0th is nil */ - return obj_list; + return obj_table; } static VALUE ibf_dump_object(struct ibf_dump *dump, VALUE obj) { - VALUE obj_list = dump->current_buffer->obj_list; - long index = RARRAY_LEN(obj_list); - long i; - for (i=0; icurrent_buffer->obj_table, (st_data_t)obj); } static VALUE @@ -9711,12 +10907,6 @@ ibf_load_id(const struct ibf_load *load, const ID id_index) /* dump/load: code */ -static VALUE -ibf_dump_calldata(struct ibf_dump *dump, const struct rb_call_data *cd) -{ - return (cd->ci.flag & VM_CALL_KWARG) ? Qtrue : Qfalse; -} - static ibf_offset_t ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq); static int @@ -9726,28 +10916,10 @@ ibf_dump_iseq(struct ibf_dump *dump, const rb_iseq_t *iseq) return -1; } else { - int iseq_index = ibf_table_lookup(dump->iseq_table, (st_data_t)iseq); - if (iseq_index < 0) { - iseq_index = ibf_table_index(dump->iseq_table, (st_data_t)iseq); - rb_ary_push(dump->iseq_list, (VALUE)iseq); - } - return iseq_index; + return ibf_table_find_or_insert(dump->iseq_table, (st_data_t)iseq); } } -static VALUE -ibf_dump_gentry(struct ibf_dump *dump, const struct rb_global_entry *entry) -{ - return (VALUE)ibf_dump_id(dump, entry->id); -} - -static VALUE -ibf_load_gentry(const struct ibf_load *load, const struct rb_global_entry *entry) -{ - ID gid = ibf_load_id(load, (ID)(VALUE)entry); - return (VALUE)rb_global_entry(gid); -} - static unsigned char ibf_load_byte(const struct ibf_load *load, ibf_offset_t *offset) { @@ -9770,6 +10942,7 @@ ibf_dump_write_small_value(struct ibf_dump *dump, VALUE x) { if (sizeof(VALUE) > 8 || CHAR_BIT != 8) { ibf_dump_write(dump, &x, sizeof(VALUE)); + return; } enum { max_byte_length = sizeof(VALUE) + 1 }; @@ -9848,14 +11021,13 @@ ibf_load_builtin(const struct ibf_load *load, ibf_offset_t *offset) const char *name = (char *)ibf_load_ptr(load, offset, len); if (0) { - for (int i=0; ibuiltin_function_table; - if (table == NULL) rb_bug("%s: table is not provided.", RUBY_FUNCTION_NAME_STRING); + if (table == NULL) rb_raise(rb_eArgError, "builtin function table is not provided"); if (strncmp(table[i].name, name, len) != 0) { - rb_bug("%s: index (%d) mismatch (expect %s but %s).", RUBY_FUNCTION_NAME_STRING, i, name, table[i].name); + rb_raise(rb_eArgError, "builtin function index (%d) mismatch (expect %s but %s)", i, name, table[i].name); } // fprintf(stderr, "load-builtin: name:%s(%d)\n", table[i].name, table[i].argc); @@ -9909,17 +11081,11 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) break; case TS_CALLDATA: { - /* ibf_dump_calldata() always returns either Qtrue or Qfalse */ - char c = ibf_dump_calldata(dump, (const struct rb_call_data *)op) == Qtrue; // 1 or 0 - ibf_dump_write_byte(dump, c); goto skip_wv; } case TS_ID: wv = ibf_dump_id(dump, (ID)op); break; - case TS_GENTRY: - wv = ibf_dump_gentry(dump, (const struct rb_global_entry *)op); - break; case TS_FUNCPTR: rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported"); goto skip_wv; @@ -9940,63 +11106,89 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) } static VALUE * -ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size, unsigned int iseq_size) +ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size, unsigned int iseq_size) { + VALUE iseqv = (VALUE)iseq; unsigned int code_index; ibf_offset_t reading_pos = bytecode_offset; VALUE *code = ALLOC_N(VALUE, iseq_size); struct rb_iseq_constant_body *load_body = iseq->body; struct rb_call_data *cd_entries = load_body->call_data; - struct rb_kwarg_call_data *cd_kw_entries = (struct rb_kwarg_call_data *)&load_body->call_data[load_body->ci_size]; union iseq_inline_storage_entry *is_entries = load_body->is_entries; for (code_index=0; code_indextype = &cdhash_type; + rb_hash_rehash(v); // hash function changed + freeze_hide_obj(v); + + // Overwrite the existing hash in the object list. This + // is to keep the object alive during load time. + // [Bug #17984] [ruby-core:104259] + pinned_list_store(load->current_buffer->obj_list, (long)op, v); + + code[code_index] = v; + RB_OBJ_WRITTEN(iseqv, Qundef, v); + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); + break; + } case TS_ISEQ: { VALUE op = (VALUE)ibf_load_small_value(load, &reading_pos); VALUE v = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op); code[code_index] = v; if (!SPECIAL_CONST_P(v)) { - RB_OBJ_WRITTEN(iseq, Qundef, v); - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + RB_OBJ_WRITTEN(iseqv, Qundef, v); + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); } break; } case TS_ISE: - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); - /* fall through */ case TS_IC: case TS_IVC: { VALUE op = ibf_load_small_value(load, &reading_pos); code[code_index] = (VALUE)&is_entries[op]; + + if (insn == BIN(opt_getinlinecache) && operand_type == TS_IC) { + // Store the instruction index for opt_getinlinecache on the IC for + // YJIT to invalidate code when opt_setinlinecache runs. + is_entries[op].ic_cache.get_insn_idx = insn_index; + } } + FL_SET(iseqv, ISEQ_MARKABLE_ISEQ); break; case TS_CALLDATA: { - unsigned char op = ibf_load_byte(load, &reading_pos); - code[code_index] = op ? (VALUE)cd_kw_entries++ : (VALUE)cd_entries++; /* op is 1 (kw) or 0 (!kw) */ + code[code_index] = (VALUE)cd_entries++; } break; case TS_ID: @@ -10005,12 +11197,6 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t b code[code_index] = ibf_load_id(load, (ID)(VALUE)op); } break; - case TS_GENTRY: - { - VALUE op = ibf_load_small_value(load, &reading_pos); - code[code_index] = ibf_load_gentry(load, (const struct rb_global_entry *)(VALUE)op); - } - break; case TS_FUNCPTR: rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported"); break; @@ -10121,6 +11307,9 @@ ibf_dump_insns_info_body(struct ibf_dump *dump, const rb_iseq_t *iseq) unsigned int i; for (i = 0; i < iseq->body->insns_info.size; i++) { ibf_dump_write_small_value(dump, entries[i].line_no); +#ifdef USE_ISEQ_NODE_ID + ibf_dump_write_small_value(dump, entries[i].node_id); +#endif ibf_dump_write_small_value(dump, entries[i].events); } @@ -10136,6 +11325,9 @@ ibf_load_insns_info_body(const struct ibf_load *load, ibf_offset_t body_offset, unsigned int i; for (i = 0; i < size; i++) { entries[i].line_no = (int)ibf_load_small_value(load, &reading_pos); +#ifdef USE_ISEQ_NODE_ID + entries[i].node_id = (int)ibf_load_small_value(load, &reading_pos); +#endif entries[i].events = (rb_event_flag_t)ibf_load_small_value(load, &reading_pos); } @@ -10268,92 +11460,133 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq) { const struct rb_iseq_constant_body *const body = iseq->body; const unsigned int ci_size = body->ci_size; - const unsigned int ci_kw_size = body->ci_kw_size; - const struct rb_call_data *calls = body->call_data; - const struct rb_kwarg_call_data *kw_calls = (const struct rb_kwarg_call_data *)&body->call_data[ci_size]; + const struct rb_call_data *cds = body->call_data; ibf_offset_t offset = ibf_dump_pos(dump); unsigned int i; for (i = 0; i < ci_size; i++) { - VALUE mid = ibf_dump_id(dump, calls[i].ci.mid); - - ibf_dump_write_small_value(dump, mid); - ibf_dump_write_small_value(dump, calls[i].ci.flag); - ibf_dump_write_small_value(dump, calls[i].ci.orig_argc); + const struct rb_callinfo *ci = cds[i].ci; + if (ci != NULL) { + ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci))); + ibf_dump_write_small_value(dump, vm_ci_flag(ci)); + ibf_dump_write_small_value(dump, vm_ci_argc(ci)); + + const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci); + if (kwarg) { + int len = kwarg->keyword_len; + ibf_dump_write_small_value(dump, len); + for (int j=0; jkeywords[j]); + ibf_dump_write_small_value(dump, keyword); + } + } + else { + ibf_dump_write_small_value(dump, 0); + } + } + else { + // TODO: truncate NULL ci from call_data. + ibf_dump_write_small_value(dump, (VALUE)-1); + } } - for (i = 0; i < ci_kw_size; i++) { - const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg; + return offset; +} - VALUE mid = ibf_dump_id(dump, kw_calls[i].ci_kw.ci.mid); +static enum rb_id_table_iterator_result +dump_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); - ibf_dump_write_small_value(dump, mid); - ibf_dump_write_small_value(dump, kw_calls[i].ci_kw.ci.flag); - ibf_dump_write_small_value(dump, kw_calls[i].ci_kw.ci.orig_argc); + return ID_TABLE_CONTINUE; +} - ibf_dump_write_small_value(dump, kw_arg->keyword_len); +static ibf_offset_t +ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq) +{ + struct rb_id_table * ovs = iseq->body->outer_variables; - int j; - for (j = 0; j < kw_calls[i].ci_kw.kw_arg->keyword_len; j++) { - VALUE keyword = ibf_dump_object(dump, kw_arg->keywords[j]); /* kw_arg->keywords[n] is Symbol */ + ibf_offset_t offset = ibf_dump_pos(dump); - ibf_dump_write_small_value(dump, keyword); - } + 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); } return offset; } /* note that we dump out rb_call_info but load back rb_call_data */ -static struct rb_call_data * +static void ibf_load_ci_entries(const struct ibf_load *load, ibf_offset_t ci_entries_offset, unsigned int ci_size, - unsigned int ci_kw_size) + struct rb_call_data **cd_ptr) { ibf_offset_t reading_pos = ci_entries_offset; unsigned int i; - struct rb_call_data *calls = - rb_xcalloc_mul_add_mul( - sizeof(struct rb_call_data), ci_size, - sizeof(struct rb_kwarg_call_data), ci_kw_size); - struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&calls[ci_size]; + struct rb_call_data *cds = ZALLOC_N(struct rb_call_data, ci_size); + *cd_ptr = cds; for (i = 0; i < ci_size; i++) { VALUE mid_index = ibf_load_small_value(load, &reading_pos); + if (mid_index != (VALUE)-1) { + ID mid = ibf_load_id(load, mid_index); + unsigned int flag = (unsigned int)ibf_load_small_value(load, &reading_pos); + unsigned int argc = (unsigned int)ibf_load_small_value(load, &reading_pos); + + struct rb_callinfo_kwarg *kwarg = NULL; + 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->keyword_len = kwlen; + for (int j=0; jkeywords[j] = ibf_load_object(load, keyword); + } + } - calls[i].ci.mid = ibf_load_id(load, mid_index); - calls[i].ci.flag = (unsigned int)ibf_load_small_value(load, &reading_pos); - calls[i].ci.orig_argc = (int)ibf_load_small_value(load, &reading_pos); + cds[i].ci = vm_ci_new(mid, flag, argc, kwarg); + RB_OBJ_WRITTEN(load->iseq, Qundef, cds[i].ci); + cds[i].cc = vm_cc_empty(); + } + else { + // NULL ci + cds[i].ci = NULL; + cds[i].cc = NULL; + } } +} - for (i = 0; i < ci_kw_size; i++) { - VALUE mid_index = ibf_load_small_value(load, &reading_pos); - - kw_calls[i].ci_kw.ci.mid = ibf_load_id(load, mid_index); - kw_calls[i].ci_kw.ci.flag = (unsigned int)ibf_load_small_value(load, &reading_pos); - kw_calls[i].ci_kw.ci.orig_argc = (int)ibf_load_small_value(load, &reading_pos); - - int keyword_len = (int)ibf_load_small_value(load, &reading_pos); +static struct rb_id_table * +ibf_load_outer_variables(const struct ibf_load * load, ibf_offset_t outer_variables_offset) +{ + ibf_offset_t reading_pos = outer_variables_offset; - kw_calls[i].ci_kw.kw_arg = - rb_xmalloc_mul_add(keyword_len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg)); + struct rb_id_table *tbl = NULL; - kw_calls[i].ci_kw.kw_arg->keyword_len = keyword_len; + size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos); - int j; - for (j = 0; j < kw_calls[i].ci_kw.kw_arg->keyword_len; j++) { - VALUE keyword = ibf_load_small_value(load, &reading_pos); + if (table_size > 0) { + tbl = rb_id_table_create(table_size); + } - kw_calls[i].ci_kw.kw_arg->keywords[j] = ibf_load_object(load, keyword); - } + for (size_t i = 0; i < table_size; i++) { + ID key = ibf_load_id(load, (ID)ibf_load_small_value(load, &reading_pos)); + VALUE value = ibf_load_small_value(load, &reading_pos); + if (!key) key = rb_make_temporary_id(i); + rb_id_table_insert(tbl, key, value); } - return calls; + return tbl; } static ibf_offset_t @@ -10375,7 +11608,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) struct ibf_dump_buffer *saved_buffer = dump->current_buffer; struct ibf_dump_buffer buffer; buffer.str = rb_str_new(0, 0); - buffer.obj_list = ibf_dump_object_list_new(); + buffer.obj_table = ibf_dump_object_table_new(); dump->current_buffer = &buffer; #endif @@ -10394,7 +11627,9 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq); const int parent_iseq_index = ibf_dump_iseq(dump, iseq->body->parent_iseq); const int local_iseq_index = ibf_dump_iseq(dump, iseq->body->local_iseq); + const int mandatory_only_iseq_index = ibf_dump_iseq(dump, iseq->body->mandatory_only_iseq); const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq); + const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq); #if IBF_ISEQ_ENABLE_LOCAL_BUFFER ibf_offset_t local_obj_list_offset; @@ -10455,14 +11690,16 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset)); ibf_dump_write_small_value(dump, parent_iseq_index); ibf_dump_write_small_value(dump, local_iseq_index); + ibf_dump_write_small_value(dump, mandatory_only_iseq_index); ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset)); + ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset)); ibf_dump_write_small_value(dump, body->variable.flip_count); ibf_dump_write_small_value(dump, body->local_table_size); ibf_dump_write_small_value(dump, body->is_size); ibf_dump_write_small_value(dump, body->ci_size); - ibf_dump_write_small_value(dump, body->ci_kw_size); ibf_dump_write_small_value(dump, body->stack_max); ibf_dump_write_small_value(dump, body->catch_except_p); + ibf_dump_write_small_value(dump, body->builtin_inline_p); #undef IBF_BODY_OFFSET @@ -10480,6 +11717,8 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_dump_write_small_value(dump, local_obj_list_offset); ibf_dump_write_small_value(dump, local_obj_list_size); + st_free_table(buffer.obj_table); // TODO: this leaks in case of exception + return offset; #else return body_offset; @@ -10507,17 +11746,16 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) struct ibf_load_buffer *saved_buffer = load->current_buffer; load->current_buffer = &load->global_buffer; - const ibf_offset_t iseq_start = ibf_load_small_value(load, &reading_pos); - const ibf_offset_t iseq_length_bytes = ibf_load_small_value(load, &reading_pos); - const ibf_offset_t body_offset = ibf_load_small_value(load, &reading_pos); + const ibf_offset_t iseq_start = (ibf_offset_t)ibf_load_small_value(load, &reading_pos); + const ibf_offset_t iseq_length_bytes = (ibf_offset_t)ibf_load_small_value(load, &reading_pos); + const ibf_offset_t body_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos); struct ibf_load_buffer buffer; buffer.buff = load->global_buffer.buff + iseq_start; buffer.size = iseq_length_bytes; - buffer.obj_list_offset = ibf_load_small_value(load, &reading_pos); - buffer.obj_list_size = ibf_load_small_value(load, &reading_pos); - buffer.obj_list = rb_ary_tmp_new(buffer.obj_list_size); - rb_ary_resize(buffer.obj_list, buffer.obj_list_size); + buffer.obj_list_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos); + buffer.obj_list_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos); + buffer.obj_list = pinned_list_new(buffer.obj_list_size); load->current_buffer = &buffer; reading_pos = body_offset; @@ -10560,14 +11798,16 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) const ibf_offset_t catch_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos)); const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos); const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos); + const int mandatory_only_iseq_index = (int)ibf_load_small_value(load, &reading_pos); const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos)); + const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos)); const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos); const unsigned int local_table_size = (unsigned int)ibf_load_small_value(load, &reading_pos); const unsigned int is_size = (unsigned int)ibf_load_small_value(load, &reading_pos); const unsigned int ci_size = (unsigned int)ibf_load_small_value(load, &reading_pos); - const unsigned int ci_kw_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 char catch_except_p = (char)ibf_load_small_value(load, &reading_pos); + const bool builtin_inline_p = (bool)ibf_load_small_value(load, &reading_pos); #undef IBF_BODY_OFFSET @@ -10593,12 +11833,12 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->local_table_size = local_table_size; load_body->is_size = is_size; load_body->ci_size = ci_size; - load_body->ci_kw_size = ci_kw_size; load_body->insns_info.size = insns_info_size; ISEQ_COVERAGE_SET(iseq, Qnil); ISEQ_ORIGINAL_ISEQ_CLEAR(iseq); - iseq->body->variable.flip_count = variable_flip_count; + load_body->variable.flip_count = variable_flip_count; + load_body->variable.script_lines = Qnil; load_body->location.first_lineno = location_first_lineno; load_body->location.node_id = location_node_id; @@ -10607,9 +11847,11 @@ 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->catch_except_p = catch_except_p; + load_body->builtin_inline_p = builtin_inline_p; load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, is_size); - load_body->call_data = ibf_load_ci_entries(load, ci_entries_offset, ci_size, ci_kw_size); + 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); load_body->param.keyword = ibf_load_param_keyword(load, param_keyword_offset); load_body->param.flags.has_kw = (param_flags >> 4) & 1; @@ -10619,6 +11861,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) 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_code(load, iseq, bytecode_offset, bytecode_size, iseq_size); #if VM_INSN_INFO_TABLE_IMPL == 2 @@ -10667,22 +11910,41 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) verify_call_cache(iseq); } +struct ibf_dump_iseq_list_arg +{ + struct ibf_dump *dump; + VALUE offset_list; +}; + +static int +ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr) +{ + const rb_iseq_t *iseq = (const rb_iseq_t *)key; + struct ibf_dump_iseq_list_arg *args = (struct ibf_dump_iseq_list_arg *)ptr; + + ibf_offset_t offset = ibf_dump_iseq_each(args->dump, iseq); + rb_ary_push(args->offset_list, UINT2NUM(offset)); + + return ST_CONTINUE; +} + static void ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header) { - VALUE list = rb_ary_tmp_new(RARRAY_LEN(dump->iseq_list)); - long i; + VALUE offset_list = rb_ary_tmp_new(dump->iseq_table->num_entries); - for (i = 0; i < RARRAY_LEN(dump->iseq_list); i++) { - ibf_offset_t offset = ibf_dump_iseq_each(dump, (rb_iseq_t *)RARRAY_AREF(dump->iseq_list, i)); - rb_ary_push(list, UINT2NUM(offset)); - } + struct ibf_dump_iseq_list_arg args; + args.dump = dump; + args.offset_list = offset_list; + + st_foreach(dump->iseq_table, ibf_dump_iseq_list_i, (st_data_t)&args); - long size = RARRAY_LEN(dump->iseq_list); + st_index_t i; + st_index_t size = dump->iseq_table->num_entries; ibf_offset_t *offsets = ALLOCA_N(ibf_offset_t, size); for (i = 0; i < size; i++) { - offsets[i] = NUM2UINT(RARRAY_AREF(list, i)); + offsets[i] = NUM2UINT(RARRAY_AREF(offset_list, i)); } ibf_dump_align(dump, sizeof(ibf_offset_t)); @@ -10711,6 +11973,7 @@ enum ibf_object_class_index { IBF_OBJECT_CLASS_STANDARD_ERROR, IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR, IBF_OBJECT_CLASS_TYPE_ERROR, + IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR, }; struct ibf_object_regexp { @@ -10772,11 +12035,13 @@ ibf_dump_object_unsupported(struct ibf_dump *dump, VALUE obj) rb_raise(rb_eNotImpError, "ibf_dump_object_unsupported: %s", buff); } +NORETURN(static VALUE ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)); + static VALUE ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset) { rb_raise(rb_eArgError, "unsupported"); - return Qnil; + UNREACHABLE_RETURN(Qnil); } static void @@ -10798,6 +12063,9 @@ ibf_dump_object_class(struct ibf_dump *dump, VALUE obj) else if (obj == rb_eTypeError) { cindex = IBF_OBJECT_CLASS_TYPE_ERROR; } + else if (obj == rb_eNoMatchingPatternKeyError) { + cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR; + } else { rb_obj_info_dump(obj); rb_p(obj); @@ -10822,6 +12090,8 @@ ibf_load_object_class(const struct ibf_load *load, const struct ibf_object_heade return rb_eNoMatchingPatternError; case IBF_OBJECT_CLASS_TYPE_ERROR: return rb_eTypeError; + case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR: + return rb_eNoMatchingPatternKeyError; } rb_raise(rb_eArgError, "ibf_load_object_class: unknown class (%d)", (int)cindex); @@ -10869,17 +12139,21 @@ ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_head const long len = (long)ibf_load_small_value(load, &reading_pos); const char *ptr = load->current_buffer->buff + reading_pos; - VALUE str = rb_str_new(ptr, len); - if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) { VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX); encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str)); } - rb_enc_associate_index(str, encindex); - if (header->internal) rb_obj_hide(str); - if (header->frozen) str = rb_fstring(str); + VALUE str; + if (header->frozen && !header->internal) { + str = rb_enc_interned_str(ptr, len, rb_enc_from_index(encindex)); + } + else { + str = rb_enc_str_new(ptr, len, rb_enc_from_index(encindex)); + if (header->internal) rb_obj_hide(str); + if (header->frozen) str = rb_fstring(str); + } return str; } @@ -11111,18 +12385,24 @@ ibf_load_object_complex_rational(const struct ibf_load *load, const struct ibf_o static void ibf_dump_object_symbol(struct ibf_dump *dump, VALUE obj) { - VALUE str = rb_sym2str(obj); - VALUE str_index = ibf_dump_object(dump, str); - - ibf_dump_write_small_value(dump, str_index); + ibf_dump_object_string(dump, rb_sym2str(obj)); } static VALUE ibf_load_object_symbol(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset) { - VALUE str_index = ibf_load_small_value(load, &offset); - VALUE str = ibf_load_object(load, str_index); - ID id = rb_intern_str(str); + ibf_offset_t reading_pos = offset; + + int encindex = (int)ibf_load_small_value(load, &reading_pos); + const long len = (long)ibf_load_small_value(load, &reading_pos); + const char *ptr = load->current_buffer->buff + reading_pos; + + if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) { + VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX); + encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str)); + } + + ID id = rb_intern3(ptr, len, rb_enc_from_index(encindex)); return ID2SYM(id); } @@ -11189,7 +12469,7 @@ ibf_load_object_object_header(const struct ibf_load *load, ibf_offset_t *offset) } static ibf_offset_t -ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj) +ibf_dump_object_object(struct ibf_dump *dump, VALUE obj) { struct ibf_object_header obj_header; ibf_offset_t current_offset; @@ -11199,12 +12479,9 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj) IBF_W_ALIGN(ibf_offset_t); current_offset = ibf_dump_pos(dump); - if (SPECIAL_CONST_P(obj)) { - if (RB_TYPE_P(obj, T_SYMBOL) || - RB_TYPE_P(obj, T_FLOAT)) { - obj_header.internal = FALSE; - goto dump_object; - } + if (SPECIAL_CONST_P(obj) && + ! (SYMBOL_P(obj) || + RB_FLOAT_TYPE_P(obj))) { obj_header.special_const = TRUE; obj_header.frozen = TRUE; obj_header.internal = TRUE; @@ -11212,8 +12489,7 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj) ibf_dump_write_small_value(dump, obj); } else { - obj_header.internal = (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE; - dump_object: + 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; ibf_dump_object_object_header(dump, obj_header); @@ -11265,12 +12541,9 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index) if (object_index == 0) { return Qnil; } - else if (object_index >= (VALUE)RARRAY_LEN(load->current_buffer->obj_list)) { - rb_raise(rb_eIndexError, "object index out of range: %"PRIdVALUE, object_index); - } else { - VALUE obj = rb_ary_entry(load->current_buffer->obj_list, (long)object_index); - if (obj == Qnil) { /* TODO: avoid multiple Qnil load */ + VALUE obj = pinned_list_fetch(load->current_buffer->obj_list, (long)object_index); + if (!obj) { ibf_offset_t *offsets = (ibf_offset_t *)(load->current_buffer->obj_list_offset + load->current_buffer->buff); ibf_offset_t offset = offsets[object_index]; const struct ibf_object_header header = ibf_load_object_object_header(load, &offset); @@ -11294,7 +12567,7 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index) obj = (*load_object_functions[header.type])(load, &header, offset); } - rb_ary_store(load->current_buffer->obj_list, (long)object_index, obj); + pinned_list_store(load->current_buffer->obj_list, (long)object_index, obj); } #if IBF_ISEQ_DEBUG fprintf(stderr, "ibf_load_object: index=%#"PRIxVALUE" obj=%#"PRIxVALUE"\n", @@ -11304,28 +12577,48 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index) } } +struct ibf_dump_object_list_arg +{ + struct ibf_dump *dump; + VALUE offset_list; +}; + +static int +ibf_dump_object_list_i(st_data_t key, st_data_t val, st_data_t ptr) +{ + VALUE obj = (VALUE)key; + struct ibf_dump_object_list_arg *args = (struct ibf_dump_object_list_arg *)ptr; + + ibf_offset_t offset = ibf_dump_object_object(args->dump, obj); + rb_ary_push(args->offset_list, UINT2NUM(offset)); + + return ST_CONTINUE; +} + static void ibf_dump_object_list(struct ibf_dump *dump, ibf_offset_t *obj_list_offset, unsigned int *obj_list_size) { - VALUE obj_list = dump->current_buffer->obj_list; - VALUE list = rb_ary_tmp_new(RARRAY_LEN(obj_list)); - int i, size; + st_table *obj_table = dump->current_buffer->obj_table; + VALUE offset_list = rb_ary_tmp_new(obj_table->num_entries); + + struct ibf_dump_object_list_arg args; + args.dump = dump; + args.offset_list = offset_list; + + st_foreach(obj_table, ibf_dump_object_list_i, (st_data_t)&args); - for (i=0; inum_entries; + st_index_t i; + for (i=0; iglobal_buffer.str); - rb_gc_mark(dump->global_buffer.obj_list); - rb_gc_mark(dump->iseq_list); + + rb_mark_set(dump->global_buffer.obj_table); + rb_mark_set(dump->iseq_table); } static void ibf_dump_free(void *ptr) { struct ibf_dump *dump = (struct ibf_dump *)ptr; + if (dump->global_buffer.obj_table) { + st_free_table(dump->global_buffer.obj_table); + dump->global_buffer.obj_table = 0; + } if (dump->iseq_table) { st_free_table(dump->iseq_table); dump->iseq_table = 0; @@ -11354,6 +12652,7 @@ ibf_dump_memsize(const void *ptr) struct ibf_dump *dump = (struct ibf_dump *)ptr; size_t size = sizeof(*dump); 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; } @@ -11366,9 +12665,11 @@ static const rb_data_type_t ibf_dump_type = { static void ibf_dump_setup(struct ibf_dump *dump, VALUE dumper_obj) { - RB_OBJ_WRITE(dumper_obj, &dump->iseq_list, rb_ary_tmp_new(0)); - RB_OBJ_WRITE(dumper_obj, &dump->global_buffer.obj_list, ibf_dump_object_list_new()); + dump->global_buffer.obj_table = NULL; // GC may run before a value is assigned + dump->iseq_table = NULL; + RB_OBJ_WRITE(dumper_obj, &dump->global_buffer.str, rb_str_new(0, 0)); + dump->global_buffer.obj_table = ibf_dump_object_table_new(); dump->iseq_table = st_init_numtable(); /* need free */ dump->current_buffer = &dump->global_buffer; @@ -11446,7 +12747,7 @@ rb_ibf_load_iseq_complete(rb_iseq_t *iseq) #endif ibf_load_iseq_each(load, iseq, offset); ISEQ_COMPILE_DATA_CLEAR(iseq); - FL_UNSET(iseq, ISEQ_NOT_LOADED_YET); + FL_UNSET((VALUE)iseq, ISEQ_NOT_LOADED_YET); rb_iseq_init_trace(iseq); load->iseq = prev_src_iseq; } @@ -11473,12 +12774,12 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq) return NULL; } else { - VALUE iseqv = rb_ary_entry(load->iseq_list, iseq_index); + VALUE iseqv = pinned_list_fetch(load->iseq_list, iseq_index); #if IBF_ISEQ_DEBUG fprintf(stderr, "ibf_load_iseq: iseqv=%p\n", (void *)iseqv); #endif - if (iseqv != Qnil) { + if (iseqv) { return (rb_iseq_t *)iseqv; } else { @@ -11486,14 +12787,14 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq) #if IBF_ISEQ_DEBUG fprintf(stderr, "ibf_load_iseq: new iseq=%p\n", (void *)iseq); #endif - FL_SET(iseq, ISEQ_NOT_LOADED_YET); + FL_SET((VALUE)iseq, ISEQ_NOT_LOADED_YET); iseq->aux.loader.obj = load->loader_obj; iseq->aux.loader.index = iseq_index; #if IBF_ISEQ_DEBUG fprintf(stderr, "ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n", (void *)iseq, (void *)load->loader_obj, iseq_index); #endif - rb_ary_store(load->iseq_list, iseq_index, (VALUE)iseq); + pinned_list_store(load->iseq_list, iseq_index, (VALUE)iseq); #if !USE_LAZY_LOAD #if IBF_ISEQ_DEBUG @@ -11524,9 +12825,8 @@ ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes, 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, rb_ary_tmp_new(0)); - RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, rb_ary_tmp_new(load->global_buffer.obj_list_size)); - rb_ary_resize(load->global_buffer.obj_list, load->global_buffer.obj_list_size); + RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(load->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; diff --git a/ruby/complex.c b/ruby/complex.c index cdd5edc50..a3dda4d0e 100644 --- a/ruby/complex.c +++ b/ruby/complex.c @@ -5,16 +5,25 @@ which is written in ruby. */ -#include "ruby/config.h" +#include "ruby/internal/config.h" + #if defined _MSC_VER /* Microsoft Visual C does not define M_PI and others by default */ # define _USE_MATH_DEFINES 1 #endif + +#include #include -#include "internal.h" -#include "id.h" -#define NDEBUG +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/class.h" +#include "internal/complex.h" +#include "internal/math.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/rational.h" #include "ruby_assert.h" #define ZERO INT2FIX(0) @@ -25,10 +34,6 @@ #else static VALUE RFLOAT_0; #endif -#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \ - !defined(signbit) -extern int signbit(double); -#endif VALUE rb_cComplex; @@ -45,8 +50,6 @@ static ID id_abs, id_arg, #define id_quo idQuo #define id_fdiv idFdiv -#define f_boolcast(x) ((x) ? Qtrue : Qfalse) - #define fun1(n) \ inline static VALUE \ f_##n(VALUE x)\ @@ -331,36 +334,36 @@ f_zero_p(VALUE x) #define f_nonzero_p(x) (!f_zero_p(x)) -VALUE rb_flo_is_finite_p(VALUE num); +static inline bool +always_finite_type_p(VALUE x) +{ + if (FIXNUM_P(x)) return true; + if (FLONUM_P(x)) return true; /* Infinity can't be a flonum */ + return (RB_INTEGER_TYPE_P(x) || RB_TYPE_P(x, T_RATIONAL)); +} + inline static int f_finite_p(VALUE x) { - if (RB_INTEGER_TYPE_P(x)) { + if (always_finite_type_p(x)) { return TRUE; } else if (RB_FLOAT_TYPE_P(x)) { - return (int)rb_flo_is_finite_p(x); - } - else if (RB_TYPE_P(x, T_RATIONAL)) { - return TRUE; + return isfinite(RFLOAT_VALUE(x)); } return RTEST(rb_funcallv(x, id_finite_p, 0, 0)); } -VALUE rb_flo_is_infinite_p(VALUE num); -inline static VALUE +inline static int f_infinite_p(VALUE x) { - if (RB_INTEGER_TYPE_P(x)) { - return Qnil; + if (always_finite_type_p(x)) { + return FALSE; } else if (RB_FLOAT_TYPE_P(x)) { - return rb_flo_is_infinite_p(x); + return isinf(RFLOAT_VALUE(x)); } - else if (RB_TYPE_P(x, T_RATIONAL)) { - return Qnil; - } - return rb_funcallv(x, id_infinite_p, 0, 0); + return RTEST(rb_funcallv(x, id_infinite_p, 0, 0)); } inline static int @@ -392,7 +395,7 @@ nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag) RCOMPLEX_SET_REAL(obj, real); RCOMPLEX_SET_IMAG(obj, imag); - OBJ_FREEZE_RAW(obj); + OBJ_FREEZE_RAW((VALUE)obj); return (VALUE)obj; } @@ -418,18 +421,6 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y) return nucomp_s_new_internal(klass, x, y); } -#ifdef CANONICALIZATION_FOR_MATHN -static int canonicalization = 0; - -RUBY_FUNC_EXPORTED void -nucomp_canonicalization(int f) -{ - canonicalization = f; -} -#else -#define canonicalization 0 -#endif - inline static void nucomp_real_check(VALUE num) { @@ -445,10 +436,6 @@ inline static VALUE nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag) { int complex_r, complex_i; -#ifdef CANONICALIZATION_FOR_MATHN - if (k_exact_zero_p(imag) && canonicalization) - return real; -#endif complex_r = RB_TYPE_P(real, T_COMPLEX); complex_i = RB_TYPE_P(imag, T_COMPLEX); if (!complex_r && !complex_i) { @@ -625,14 +612,12 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y) assert(!RB_TYPE_P(x, T_COMPLEX)); assert(!RB_TYPE_P(y, T_COMPLEX)); if (f_zero_p(x) || f_zero_p(y)) { - if (canonicalization) return x; return nucomp_s_new_internal(klass, x, RFLOAT_0); } if (RB_FLOAT_TYPE_P(y)) { const double arg = RFLOAT_VALUE(y); if (arg == M_PI) { x = f_negate(x); - if (canonicalization) return x; y = RFLOAT_0; } else if (arg == M_PI_2) { @@ -647,13 +632,12 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y) const double abs = RFLOAT_VALUE(x); const double real = abs * cos(arg), imag = abs * sin(arg); x = DBL2NUM(real); - if (canonicalization && imag == 0.0) return x; y = DBL2NUM(imag); } else { - y = f_mul(x, DBL2NUM(sin(arg))); - x = f_mul(x, DBL2NUM(cos(arg))); - if (canonicalization && f_zero_p(y)) return x; + const double ax = sin(arg), ay = cos(arg); + y = f_mul(x, DBL2NUM(ax)); + x = f_mul(x, DBL2NUM(ay)); } return nucomp_s_new_internal(klass, x, y); } @@ -662,6 +646,16 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y) f_mul(x, m_sin(y))); } +#ifdef HAVE___COSPI +# define cospi(x) __cospi(x) +#else +# define cospi(x) cos((x) * M_PI) +#endif +#ifdef HAVE___SINPI +# define sinpi(x) __sinpi(x) +#else +# define sinpi(x) sin((x) * M_PI) +#endif /* returns a Complex or Float of ang*PI-rotated abs */ VALUE rb_dbl_complex_new_polar_pi(double abs, double ang) @@ -679,8 +673,8 @@ rb_dbl_complex_new_polar_pi(double abs, double ang) return DBL2NUM(abs); } else { - ang *= M_PI; - return rb_complex_new(DBL2NUM(abs * cos(ang)), DBL2NUM(abs * sin(ang))); + const double real = abs * cospi(ang), imag = abs * sinpi(ang); + return rb_complex_new(DBL2NUM(real), DBL2NUM(imag)); } } @@ -703,13 +697,20 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass) switch (rb_scan_args(argc, argv, "11", &abs, &arg)) { case 1: nucomp_real_check(abs); - if (canonicalization) return abs; return nucomp_s_new_internal(klass, abs, ZERO); default: nucomp_real_check(abs); nucomp_real_check(arg); break; } + if (RB_TYPE_P(abs, T_COMPLEX)) { + get_dat1(abs); + abs = dat->real; + } + if (RB_TYPE_P(arg, T_COMPLEX)) { + get_dat1(arg); + arg = dat->real; + } return f_complex_polar(klass, abs, arg); } @@ -1055,7 +1056,7 @@ rb_complex_pow(VALUE self, VALUE other) if (k_numeric_p(other) && f_real_p(other)) { VALUE r, theta; - if (RB_TYPE_P(other, T_BIGNUM)) + if (RB_BIGNUM_TYPE_P(other)) rb_warn("in a**b, b may be too big"); r = f_abs(self); @@ -1085,15 +1086,15 @@ nucomp_eqeq_p(VALUE self, VALUE other) if (RB_TYPE_P(other, T_COMPLEX)) { get_dat2(self, other); - return f_boolcast(f_eqeq_p(adat->real, bdat->real) && + return RBOOL(f_eqeq_p(adat->real, bdat->real) && f_eqeq_p(adat->imag, bdat->imag)); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); - return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag)); + return RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag)); } - return f_boolcast(f_eqeq_p(other, self)); + return RBOOL(f_eqeq_p(other, self)); } static bool @@ -1265,7 +1266,7 @@ rb_complex_conjugate(VALUE self) * Returns false, even if the complex number has no imaginary part. */ static VALUE -nucomp_false(VALUE self) +nucomp_real_p_m(VALUE self) { return Qfalse; } @@ -1319,8 +1320,8 @@ nucomp_numerator(VALUE self) } /* :nodoc: */ -static VALUE -nucomp_hash(VALUE self) +st_index_t +rb_complex_hash(VALUE self) { st_index_t v, h[2]; VALUE n; @@ -1331,7 +1332,13 @@ nucomp_hash(VALUE self) n = rb_hash(dat->imag); h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); - return ST2FIX(v); + return v; +} + +static VALUE +nucomp_hash(VALUE self) +{ + return ST2FIX(rb_complex_hash(self)); } /* :nodoc: */ @@ -1341,7 +1348,7 @@ nucomp_eql_p(VALUE self, VALUE other) if (RB_TYPE_P(other, T_COMPLEX)) { get_dat2(self, other); - return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) && + return RBOOL((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) && (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) && f_eqeq_p(self, other)); @@ -1442,10 +1449,7 @@ rb_complex_finite_p(VALUE self) { get_dat1(self); - if (f_finite_p(dat->real) && f_finite_p(dat->imag)) { - return Qtrue; - } - return Qfalse; + return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag)); } /* @@ -1465,7 +1469,7 @@ rb_complex_infinite_p(VALUE self) { get_dat1(self); - if (NIL_P(f_infinite_p(dat->real)) && NIL_P(f_infinite_p(dat->imag))) { + if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) { return Qnil; } return ONE; @@ -1515,8 +1519,6 @@ nucomp_marshal_load(VALUE self, VALUE a) return self; } -/* --- */ - VALUE rb_complex_raw(VALUE x, VALUE y) { @@ -1550,13 +1552,6 @@ rb_Complex(VALUE x, VALUE y) return nucomp_s_convert(2, a, rb_cComplex); } -/*! - * Creates a Complex object. - * - * \param real real part value - * \param imag imaginary part value - * \return a new Complex object - */ VALUE rb_dbl_complex_new(double real, double imag) { @@ -1700,8 +1695,6 @@ numeric_to_c(VALUE self) return rb_complex_new1(self); } -#include - inline static int issign(int c) { @@ -2141,8 +2134,6 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass) return nucomp_convert(klass, a1, a2, TRUE); } -/* --- */ - /* * call-seq: * num.real -> self @@ -2209,8 +2200,6 @@ numeric_rect(VALUE self) return rb_assoc_new(self, INT2FIX(0)); } -static VALUE float_arg(VALUE self); - /* * call-seq: * num.polar -> array @@ -2278,6 +2267,14 @@ float_arg(VALUE self) * and i is imaginary unit. Real a equals complex a+0i * mathematically. * + * You can create a \Complex object explicitly with: + * + * - A {complex literal}[doc/syntax/literals_rdoc.html#label-Complex+Literals]. + * + * You can convert certain objects to \Complex objects with: + * + * - \Method {Complex}[Kernel.html#method-i-Complex]. + * * Complex object can be created as literal, and also by using * Kernel#Complex, Complex::rect, Complex::polar or to_c method. * @@ -2309,20 +2306,17 @@ void Init_Complex(void) { VALUE compat; -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - id_abs = rb_intern("abs"); - id_arg = rb_intern("arg"); - id_denominator = rb_intern("denominator"); - id_numerator = rb_intern("numerator"); - id_real_p = rb_intern("real?"); - id_i_real = rb_intern("@real"); - id_i_imag = rb_intern("@image"); /* @image, not @imag */ - id_finite_p = rb_intern("finite?"); - id_infinite_p = rb_intern("infinite?"); - id_rationalize = rb_intern("rationalize"); - id_PI = rb_intern("PI"); + id_abs = rb_intern_const("abs"); + id_arg = rb_intern_const("arg"); + id_denominator = rb_intern_const("denominator"); + id_numerator = rb_intern_const("numerator"); + id_real_p = rb_intern_const("real?"); + id_i_real = rb_intern_const("@real"); + id_i_imag = rb_intern_const("@image"); /* @image, not @imag */ + id_finite_p = rb_intern_const("finite?"); + id_infinite_p = rb_intern_const("infinite?"); + id_rationalize = rb_intern_const("rationalize"); + id_PI = rb_intern_const("PI"); rb_cComplex = rb_define_class("Complex", rb_cNumeric); @@ -2337,7 +2331,7 @@ Init_Complex(void) rb_define_global_function("Complex", nucomp_f_complex, -1); - rb_undef_methods_from(rb_cComplex, rb_mComparable); + rb_undef_methods_from(rb_cComplex, RCLASS_ORIGIN(rb_mComparable)); rb_undef_method(rb_cComplex, "%"); rb_undef_method(rb_cComplex, "div"); rb_undef_method(rb_cComplex, "divmod"); @@ -2379,7 +2373,7 @@ Init_Complex(void) rb_define_method(rb_cComplex, "conjugate", rb_complex_conjugate, 0); rb_define_method(rb_cComplex, "conj", rb_complex_conjugate, 0); - rb_define_method(rb_cComplex, "real?", nucomp_false, 0); + rb_define_method(rb_cComplex, "real?", nucomp_real_p_m, 0); rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0); rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0); @@ -2402,8 +2396,6 @@ Init_Complex(void) rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1); rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader); - /* --- */ - rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0); rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0); rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0); @@ -2416,8 +2408,6 @@ Init_Complex(void) rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1); - /* --- */ - rb_define_method(rb_cNumeric, "real", numeric_real, 0); rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0); rb_define_method(rb_cNumeric, "imag", numeric_imag, 0); diff --git a/ruby/configure b/ruby/configure index 2a8d30973..24d09e97f 100755 --- a/ruby/configure +++ b/ruby/configure @@ -909,7 +909,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -1045,7 +1044,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' @@ -1298,15 +1296,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1444,7 +1433,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1597,7 +1586,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -6312,6 +6300,14 @@ else fi + + # if $CC is in /usr/lib/ccache/$CC, search original $CC (disable ccache) + if echo $RUBY_DEBUG | grep ci > /dev/null && + echo $MJIT_CC | grep ^/usr/lib/ccache > /dev/null; then : + + PATH=`echo $PATH | sed "s/\/usr\/lib\/ccache://"` MJIT_CC=`which $CC` +fi + case $target_os in #( *mingw*) : command -v cygpath > /dev/null && MJIT_CC=`cygpath -ma $MJIT_CC` ;; #( @@ -8396,6 +8392,68 @@ else fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fdeclspec is accepted as CFLAGS" >&5 +$as_echo_n "checking whether -fdeclspec is accepted as CFLAGS... " >&6; } + save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $rb_cv_warnflags" +if test "${ac_c_werror_flag+set}"; then : + + rb_c_werror_flag="$ac_c_werror_flag" + +else + + unset rb_c_werror_flag + +fi +ac_c_werror_flag=yes + + CFLAGS="$CFLAGS -fdeclspec" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # RUBY_APPEND_OPTIONS(XCFLAGS) + for rb_opt in -fdeclspec; do + case " ${XCFLAGS-} " in #( + *" ${rb_opt} "*) : + ;; #( + ' ') : + XCFLAGS="${rb_opt}" ;; #( + *) : + XCFLAGS="$XCFLAGS ${rb_opt}" ;; +esac + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + $as_echo "${msg_result_yes}yes${msg_reset}" >&6 ; } +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + $as_echo "${msg_result_no}no${msg_reset}" >&6 ; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +CFLAGS="$save_CFLAGS" +save_CFLAGS= +if test "${rb_c_werror_flag+set}"; then : + + ac_c_werror_flag="$rb_c_werror_flag" + +else + + unset ac_c_werror_flag + +fi + + case $RUBY_PATCHLEVEL in #( -*) : RUBY_DEVEL=yes ;; #( @@ -11730,6 +11788,18 @@ fi done +for ac_header in x86intrin.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "x86intrin.h" "ac_cv_header_x86intrin_h" "$ac_includes_default" +if test "x$ac_cv_header_x86intrin_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X86INTRIN_H 1 +_ACEOF + +fi + +done + # Check whether --with-gmp was given. @@ -11982,7 +12052,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12028,7 +12098,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12052,7 +12122,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12097,7 +12167,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12121,7 +12191,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -18667,8 +18737,15 @@ $as_echo_n "checking for function name string predefined identifier... " >&6; } if ${rb_cv_function_name_string+:} false; then : $as_echo_n "(cached) " >&6 else - rb_cv_function_name_string=no - save_CFLAGS="$CFLAGS" + case "$target_os" in #( + openbsd*) : + + rb_cv_function_name_string=__func__ + ;; #( + *) : + + rb_cv_function_name_string=no + save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $rb_cv_warnflags" if test "${ac_c_werror_flag+set}"; then : @@ -18681,8 +18758,8 @@ else fi ac_c_werror_flag=yes - for func in __func__ __FUNCTION__; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + for func in __func__ __FUNCTION__; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -18695,11 +18772,11 @@ puts($func); _ACEOF if ac_fn_c_try_link "$LINENO"; then : rb_cv_function_name_string=$func - break + break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - done + done CFLAGS="$save_CFLAGS" save_CFLAGS= @@ -18711,7 +18788,8 @@ else unset ac_c_werror_flag -fi +fi ;; +esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $rb_cv_function_name_string" >&5 diff --git a/ruby/configure.ac b/ruby/configure.ac index f1ed36bb9..5a6b074f8 100644 --- a/ruby/configure.ac +++ b/ruby/configure.ac @@ -1,23 +1,52 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT() +AC_INIT { AC_CONFIG_AUX_DIR(tool) -AC_CONFIG_MACRO_DIRS(tool/m4) AC_PREREQ(2.67) -dnl override AC_CHECKING -dnl placed here due to aclocal(1)'s -dnl ignoring this definition in separate files -AC_DEFUN([AC_CHECKING],[dnl -AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl -AS_MESSAGE([checking ${msg_checking}$1${msg_reset}...])])dnl +tooldir="$srcdir/tool" AC_DISABLE_OPTION_CHECKING -AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)]) -AC_ARG_VAR([cppflags], [additional CPPFLAGS (ignored when CPPFLAGS is given)]) -AC_ARG_VAR([cxxflags], [additional CXXFLAGS (ignored when CXXFLAGS is given)]) +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_replace_funcs.m4])dnl +m4_include([tool/m4/ruby_replace_type.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_werror_flag.m4])dnl + +AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)])dnl +AC_ARG_VAR([cppflags], [additional CPPFLAGS (ignored when CPPFLAGS is given)])dnl +AC_ARG_VAR([cxxflags], [additional CXXFLAGS (ignored when CXXFLAGS is given)])dnl : "environment section" && { HAVE_BASERUBY=yes @@ -32,11 +61,9 @@ AC_ARG_WITH(baseruby, [ AC_PATH_PROG([BASERUBY], [ruby], [false]) ]) -AS_IF([test "$HAVE_BASERUBY" = yes -a "`RUBYOPT=- $BASERUBY -e 'print 42' 2>/dev/null`" = 42], [ - AS_IF([test "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42' 2>/dev/null`" = 42], [ - BASERUBY="$BASERUBY --disable=gems" - BASERUBY_VERSION=`$BASERUBY -v` - ]) +AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.2"' 2>/dev/null`" = 42], [ + BASERUBY="$BASERUBY --disable=gems" + BASERUBY_VERSION=`$BASERUBY -v` $BASERUBY -C "$srcdir" tool/downloader.rb -d tool -e gnu config.guess config.sub >&AS_MESSAGE_FD ], [ BASERUBY="echo executable host ruby is required. use --with-baseruby option.; false" @@ -71,8 +98,31 @@ AC_SUBST(TEENY) AC_SUBST(RUBY_API_VERSION, '$(MAJOR).$(MINOR)') AC_SUBST(RUBY_PROGRAM_VERSION, '$(MAJOR).$(MINOR).$(TEENY)') +AS_IF([test "$program_prefix" = NONE], [ + program_prefix= +]) +AS_IF([test "$prefix" -ef .], [ + AC_MSG_ERROR(--prefix cannot be the current working directory.) +]) +RUBY_BASE_NAME=`echo ruby | sed "$program_transform_name"` +RUBYW_BASE_NAME=`echo rubyw | sed "$program_transform_name"` +AC_SUBST(RUBY_BASE_NAME) +AC_SUBST(RUBYW_BASE_NAME) +AC_SUBST(RUBY_VERSION_NAME, '${RUBY_BASE_NAME}-${ruby_version}') + dnl checks for alternative programs AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AS_CASE(["$target_cpu-$target_os"], + [aarch64-darwin*], [ + target_cpu=arm64 + AS_CASE(["$target_vendor"], [unknown], [target_vendor=apple target=${target/-unknown-/-apple-}]) + target="${target/aarch64/arm64}" + target_alias="${target_alias/aarch64/arm64}" + ]) + +AC_ARG_PROGRAM RUBY_RM_RECURSIVE AC_ARG_WITH(gcc, AS_HELP_STRING([--without-gcc], [never use gcc]), @@ -86,21 +136,112 @@ AS_IF([test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"], [ AC_MSG_ERROR(cached CC is different -- throw away $cache_file (it is also a good idea to do 'make clean' before compiling)) ]) -test -z "$CC" || ac_cv_prog_CC="$CC" - -AS_IF([test "$program_prefix" = NONE], [ - program_prefix= +AS_CASE(["${build_os}"], +[linux*|cygwin*|msys*], [ + # Naruse prefers GCC on Linux + AC_CHECK_TOOLS([CC], [gcc clang cc]) +], +[solaris*], [ + # Clang on Solaris is largely untested. + # https://bugs.ruby-lang.org/issues/17949 + AC_CHECK_TOOLS([CC], [cc gcc]) +], [ + # OpenBSD wants to prefer cc over gcc. + # See https://github.com/ruby/ruby/pull/2443 + AC_CHECK_TOOLS([CC], [cl.exe clang cc gcc c99 /usr/ucb/cc]) +]) + +AC_ARG_VAR([AR], [Archiver command]) +AC_ARG_VAR([AS], [Assembler command]) +AC_ARG_VAR([CC], [C compiler command]) +AC_ARG_VAR([CXX], [C++ compiler command]) +AC_ARG_VAR([LD], [Linker command]) +AC_ARG_VAR([NM], [Symbol list command]) +AC_ARG_VAR([OBJCOPY], [Objcopy command]) +AC_ARG_VAR([OBJDUMP], [Objdump command]) +AC_ARG_VAR([RANLIB], [Ranlib command]) +AC_ARG_VAR([STRIP], [Strip command]) + +# We don't want to bother things like `ccache gcc`, `clang -shared-libgcc`, ... +set rb_dummy ${CC} +rb_CC=$2 +AS_CASE(["/${rb_CC} "], +[*@<:@\ /@:>@"cc "*], [ + # Don't try g++/clang++ when CC=cc + AC_CHECK_TOOLS([CXX], [cl.exe CC c++]) +], +[*icc*], [ + # Intel C++ has interprocedural optimizations. It tends to come with its + # own linker etc. + AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/icc/xiar/`]) + AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/icc/icpc/`]) + AC_CHECK_TOOL([LD], [`echo "${rb_CC}" | sed s/icc/xild/`]) +], +[*gcc*], [ + # Dito for GCC. + AC_CHECK_TOOL([LD], [`echo "${rb_CC}" | sed s/gcc/ld/`]) + AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/gcc/gcc-ar/`]) + AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/gcc/g++/`]) + AC_CHECK_TOOL([NM], [`echo "${rb_CC}" | sed s/gcc/gcc-nm/`]) + AC_CHECK_TOOL([RANLIB], [`echo "${rb_CC}" | sed s/gcc/gcc-ranlib/`]) +], +[*clang*], [ + # Dito for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode + # assembler that does not target your machine native binary. + : ${LD:="${CC}"} # ... try -fuse-ld=lld ? + AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/clang/llvm-ar/`]) +# AC_CHECK_TOOL([AS], [`echo "${rb_CC}" | sed s/clang/llvm-as/`]) + AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/clang/clang++/`]) + AC_CHECK_TOOL([NM], [`echo "${rb_CC}" | sed s/clang/llvm-nm/`]) + AC_CHECK_TOOL([OBJCOPY], [`echo "${rb_CC}" | sed s/clang/llvm-objcopy/`]) + AC_CHECK_TOOL([OBJDUMP], [`echo "${rb_CC}" | sed s/clang/llvm-objdump/`]) + AC_CHECK_TOOL([RANLIB], [`echo "${rb_CC}" | sed s/clang/llvm-ranlib/`]) + AC_CHECK_TOOL([STRIP], [`echo "${rb_CC}" | sed s/clang/llvm-strip/`]) +]) +AS_UNSET(rb_CC) +AS_UNSET(rb_dummy) + +AS_CASE(["${build_os}"], +[solaris*], [ + AC_PATH_TOOL([LD], [ld], [/usr/ccs/bin/ld], [/usr/ccs/bin:$PATH]) +], +[aix*], [ + AC_PATH_TOOL([NM], [nm], [/usr/ccs/bin/nm], [/usr/ccs/bin:$PATH]) ]) -AS_IF([test "$prefix" -ef .], [ - AC_MSG_ERROR(--prefix cannot be the current working directory.) +AS_CASE(["${target_os}"], +[cygwin*|msys*|mingw*], [ + ac_cv_prog_ac_ct_OBJCOPY=":" +]) + +rb_test_CFLAGS=${CFLAGS+yes} +rb_test_CXXFLAGS=${CXXFLAGS+yes} + +# BSD's ports and MacPorts prefix GNU binutils with 'g' + +dnl Seems necessarily in order to add -std=gnu99 option for gcc 4.9. +m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_C99]) + +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_RANLIB +AC_CHECK_TOOLS([AR], [gar ar]) +AC_CHECK_TOOLS([AS], [gas as]) +AC_CHECK_TOOLS([LD], [gld ld]) # ... try gold ? +AC_CHECK_TOOLS([NM], [gnm nm]) +AC_CHECK_TOOLS([OBJCOPY], [gobjcopy objcopy]) +AC_CHECK_TOOLS([OBJDUMP], [gobjdump objdump]) +AC_CHECK_TOOLS([STRIP], [gstrip strip], [:]) + +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) + +AS_IF([test "${CXX}" = "g++" -a -z "${GXX}"], [ + # AC_PROG_CXX sets $CXX to "g++" when it purposefully finds that there is + # _no_ g++. This brain-damaged design must be worked around. Thankfully, + # similar thing doesn't happen for AC_PROG_CC. + rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us=true ]) -RUBY_BASE_NAME=`echo ruby | sed "$program_transform_name"` -RUBYW_BASE_NAME=`echo rubyw | sed "$program_transform_name"` -AC_SUBST(RUBY_BASE_NAME) -AC_SUBST(RUBYW_BASE_NAME) -AC_SUBST(RUBY_VERSION_NAME, '${RUBY_BASE_NAME}-${ruby_version}') -AC_CANONICAL_TARGET test x"$target_alias" = x && target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'` ac_install_sh='' # unusable for extension libraries. @@ -148,7 +289,8 @@ AC_ARG_ENABLE(load-relative, AS_HELP_STRING([--enable-load-relative], [resolve load paths at run time]), [load_relative=$enableval]) -AC_ARG_PROGRAM +# checks for UNIX variants that set C preprocessor variables +AC_USE_SYSTEM_EXTENSIONS dnl Checks for programs. @@ -172,76 +314,37 @@ dnl ]) AS_CASE(["$host_os:$build_os"], [darwin*:darwin*], [ - AC_CHECK_TOOLS(CC, [clang gcc cc]) # Following Apple deployed clang are broken # clang version 1.0 (http://llvm.org/svn/llvm-project/cfe/tags/Apple/clang-23 exported) # Apple clang version 2.0 (tags/Apple/clang-137) (based on LLVM 2.9svn) # Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn) - AS_IF([! $CC -E -xc - </dev/null], [ - @%:@if defined __APPLE_CC__ && defined __clang_major__ && __clang_major__ < 3 - @%:@error premature clang - @%:@endif -SRC - AC_MSG_ERROR([clang version 3.0 or later is required]) - ])], -[openbsd*:openbsd*], [ - AC_CHECK_TOOLS(CC, [cc]) -]) -AS_IF([test x"${build}" != x"${host}"], [ - AC_CHECK_TOOL(CC, gcc) -]) - -AC_PROG_CC_C99 -AS_CASE([$CC], -[gcc-*], [ - gcc_prefix=gcc- gcc_suffix=`echo "$CC" | sed 's/^gcc//'` - AC_PROG_CXX(g++${gcc_suffix})], -[clang-*|clang], [ - gcc_prefix=clang- gcc_suffix=`echo "$CC" | sed 's/^clang//'` - AC_PROG_CXX(clang++${gcc_suffix})], -[gcc_prefix= gcc_suffix=]) - -dnl Select the appropriate C++ compiler in OS X -AS_CASE(["$build_os:${CXX}"], - [darwin1*.*:], [ - AC_MSG_CHECKING([CXX for $CC]) - AS_CASE(["/$CC "], - [*@<:@\ /@:>@"gcc-4.2 "*], [pat='gcc-4\.2' CXX=g++-4.2], - [*@<:@\ /@:>@"gcc "*], [pat=gcc CXX=g++], - [*@<:@\ /@:>@"cc "*], [pat=cc CXX=c++], - [*@<:@\ /@:>@"icc "*], [pat=icc CXX=icpc], - [*@<:@\ /@:>@"clang "*], [pat=clang CXX=clang++]) - AS_IF([test "${CXX}"], [ - CXX=`echo "/$CC " | sed ["s:\([ /]\)${pat}:\1$CXX:; s:^/::; s: *$::"]` - ]) - AC_MSG_RESULT([$CXX])], - [openbsd*:*], [ - AC_CHECK_TOOLS(CXX, [c++]) - ]) -test -z "$CXX" || ac_cv_prog_CXX="$CXX" + AC_PREPROC_IFELSE( + [AC_LANG_PROGRAM([ + @%:@if defined __APPLE_CC__ && defined __clang_major__ && __clang_major__ < 3 + @%:@error premature clang + @%:@endif + ])], + [], + [AC_MSG_ERROR([clang version 3.0 or later is required])]) +]) AS_CASE(["$target_os"], [darwin*], [ AC_MSG_CHECKING(if minimum required OS X version is supported) - AC_TRY_CPP([@%:@include + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[@%:@include @%:@if MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_5 @%:@error pre OS X 10.5 [!<===== pre OS X 10.5 =====>] @%:@endif - ], + ]])], [macosx_min_required=yes], [AC_MSG_RESULT(no) AC_MSG_ERROR([Unsupported OS X version is required])]) AC_MSG_RESULT(${macosx_min_required}) ]) -AC_PROG_CXX RUBY_MINGW32 -AC_PROG_GCC_TRADITIONAL AC_SUBST(GCC) -AS_CASE(["$target_os"], -[solaris*], [AC_PATH_TOOL([LD], [ld], [/usr/ccs/bin/ld], [/usr/ccs/bin:$PATH])], -[AC_CHECK_TOOL([LD], [ld], [ld])]) AC_SUBST(LD) AS_IF([test "$GCC" = yes], [ linker_flag=-Wl, @@ -274,6 +377,12 @@ AC_SUBST(CSRCFLAG) : ${MJIT_CC=$CC} AS_IF([test "x$cross_compiling" = xno], [ AC_PATH_PROG([MJIT_CC], ${MJIT_CC}) + + # if $CC is in /usr/lib/ccache/$CC, search original $CC (disable ccache) + AS_IF([echo $RUBY_DEBUG | grep ci > /dev/null && + echo $MJIT_CC | grep ^/usr/lib/ccache > /dev/null], [ + PATH=`echo $PATH | sed "s/\/usr\/lib\/ccache://"` MJIT_CC=`which $CC`]) + AS_CASE([$target_os], [*mingw*], [command -v cygpath > /dev/null && MJIT_CC=`cygpath -ma $MJIT_CC`]) shift 2 @@ -288,7 +397,7 @@ AS_CASE(["$build_os"], 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 "$srcdir/tool" && pwd`/darwin-cc + CC_WRAPPER=`cd -P "${tooldir}" && pwd`/darwin-cc CC="$CC_WRAPPER $CC" ]) rm -fr conftest* @@ -309,40 +418,24 @@ 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], [ +AS_IF([test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "$cross_compiling" = no -a "${universal_binary:-no}" = no], [ RUBY_DEFAULT_ARCH("$target_cpu") ]) +host_os=$target_os +host_vendor=$target_vendor +host_cpu=$target_cpu +host=$target +host_alias=$target_alias -AS_CASE(["$target_os"], [darwin*], [ -if libtool 2>&1 | grep no_warning_for_no_symbols > /dev/null; then - ac_cv_prog_ac_ct_RANLIB=: - ac_cv_prog_ac_ct_AR='libtool -static' - rb_cv_arflags='-no_warning_for_no_symbols -o' -fi -]) -AC_CHECK_TOOLS(RANLIB, [${gcc_prefix}ranlib${gcc_suffix} ranlib], :) -AC_CHECK_TOOLS(AR, [${gcc_prefix}ar${gcc_suffix} ar]) -AS_IF([test -z "$AR"], [ - AC_CHECK_PROGS(AR, aal, ar) -]) AC_CACHE_CHECK([for $AR flags], [rb_cv_arflags], [ AS_IF([$AR rcD conftest.a > /dev/null 2>&1 && rm conftest.a], [rb_cv_arflags=rcD], [rb_cv_arflags=rcu]) ]) AC_SUBST(ARFLAGS, ["$rb_cv_arflags "]) - -AC_CHECK_TOOL(AS, as) -ASFLAGS=$ASFLAGS AC_SUBST(ASFLAGS) -AS_CASE(["$target_os"],[cygwin*|mingw*], [ac_cv_prog_ac_ct_OBJCOPY=":"]) - -# BSD's ports and MacPorts prefix GNU binutils with 'g' -AC_CHECK_TOOLS(OBJDUMP, [objdump gobjdump]) -AC_CHECK_TOOLS(OBJCOPY, [objcopy gobjcopy]) - AS_CASE(["$target_os"], -[cygwin*|mingw*], [ +[cygwin*|msys*|mingw*], [ AC_CHECK_TOOL(WINDRES, windres) AC_CHECK_TOOL(DLLWRAP, dllwrap) target=`echo $target | sed "s/^$target_cpu-/-/"` @@ -354,23 +447,23 @@ AS_CASE(["$target_os"], [mingw*], [ test "$rb_cv_msvcrt" = "" && unset rb_cv_msvcrt AC_CACHE_CHECK(for mingw32 runtime DLL, rb_cv_msvcrt, [ - AC_TRY_LINK([@%:@include ], - [FILE* volatile f = stdin; return 0;], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[FILE* volatile f = stdin; return 0;]])], [rb_cv_msvcrt=`$OBJDUMP -p conftest$ac_exeext | tr A-Z a-z | - sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}'`], + sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}; + /^[[ ]]*dll name: \(ucrtbase\|api-ms-win-crt-.*\)\.dll$/{s//ucrt/p;q;}'`], [rb_cv_msvcrt=msvcrt]) test "$rb_cv_msvcrt" = "" && rb_cv_msvcrt=msvcrt]) RT_VER=`echo "$rb_cv_msvcrt" | tr -cd [0-9]` test "$RT_VER" = "" && RT_VER=60 + test "$rb_cv_msvcrt" = "ucrt" && RT_VER=140 AC_DEFINE_UNQUOTED(RUBY_MSVCRT_VERSION, $RT_VER) sysconfdir= ]) : ${enable_shared=yes} ], -[aix*], [AC_CHECK_TOOL(NM, nm, /usr/ccs/bin/nm, /usr/ccs/bin:$PATH)], [hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi -AC_CHECK_TOOLS(NM, [${gcc_prefix}nm${gcc_suffix} nm]) AC_PROG_LN_S AC_PROG_MAKE_SET @@ -395,11 +488,30 @@ AS_IF([test "$cross_compiling:$ac_cv_prog_DTRACE" = no: -a -n "$ac_tool_prefix"] AC_CHECK_PROGS(DOT, dot) AC_CHECK_PROGS(DOXYGEN, doxygen) -AC_CHECK_PROG(PKG_CONFIG, pkg-config, [pkg-config], [], [], - [`"$as_dir/$ac_word$ac_exec_ext" --print-errors --version > /dev/null 2>&1 || echo "$as_dir/$ac_word$ac_exec_ext"`]) +for prog in ${ac_tool_prefix:+${ac_tool_prefix}pkg-config} pkg-config; do + AC_CHECK_PROG(PKG_CONFIG, $prog, [$prog], [], [], + [`"$as_dir/$ac_word$ac_exec_ext" --print-errors --version > /dev/null 2>&1 || echo "$as_dir/$ac_word$ac_exec_ext"`]) + test -z "${PKG_CONFIG}" || break +done -# checks for UNIX variants that set C preprocessor variables -AC_USE_SYSTEM_EXTENSIONS +AC_MSG_CHECKING([whether it is Android]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + @%:@ifndef __ANDROID__ + @%:@error Not android + @%:@endif +]], [[]])], +[ + AC_MSG_RESULT(yes) + target_os=${target_os}-android + AS_IF([test "x$cross_compiling" = xno], [ + AC_MSG_CHECKING([for Android API version]) + # hacky workaround: https://github.com/termux/termux-packages/issues/6176 + rb_android_api=`getprop ro.build.version.sdk` + AC_MSG_RESULT($rb_android_api) + RUBY_APPEND_OPTIONS(CPPFLAGS, -D__ANDROID_API__=$rb_android_api -Wno-macro-redefined) + ]) +], +[AC_MSG_RESULT(no)]) AC_SUBST(RM, ['rm -f']) AC_SUBST(CP, ['cp']) @@ -436,7 +548,7 @@ AC_SUBST(CHDIR) : "compiler section" && { RUBY_WERROR_FLAG([ AC_MSG_CHECKING([whether CFLAGS is valid]) - AC_TRY_COMPILE([], [], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) @@ -452,7 +564,7 @@ RUBY_WERROR_FLAG([ echo 'CFBundleIdentifier' > Info.plist && : } || AC_MSG_ERROR([failed to make temporary directory]) - AC_TRY_LINK([], [], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [AC_MSG_RESULT(yes)], [ cd .. && rm -fr tmp.$$.try_link @@ -481,6 +593,17 @@ AS_IF([test x"${RPATHFLAG}" = x], [ rpathflag=`echo "$RPATHFLAG" | sed 's/%.*//'` ]) +RUBY_TRY_LDFLAGS(-fdeclspec, [fdeclspec=yes], [fdeclspec=no]) +AS_IF([test "$fdeclspec" = yes], [ + RUBY_APPEND_OPTIONS(CFLAGS, -fdeclspec) + RUBY_APPEND_OPTIONS(cflags, -fdeclspec) + RUBY_APPEND_OPTIONS(orig_cflags, -fdeclspec) +]) +RUBY_TRY_CXXFLAGS(-fdeclspec, [fdeclspec=yes], [fdeclspec=no]) +AS_IF([test "$fdeclspec" = yes], [ + RUBY_APPEND_OPTIONS(CXXFLAGS, -fdeclspec) +]) + AS_CASE([$RUBY_PATCHLEVEL], [-*], [RUBY_DEVEL=yes], [RUBY_DEVEL=no]) particular_werror_flags=$RUBY_DEVEL @@ -514,6 +637,7 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"], -Werror=pointer-arith \ -Werror=shorten-64-to-32 \ -Werror=write-strings \ + -Werror=old-style-definition \ -Wimplicit-fallthrough=0 \ -Wmissing-noreturn \ -Wno-cast-function-type \ @@ -530,7 +654,7 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"], -Wsuggest-attribute=format \ -Wsuggest-attribute=noreturn \ -Wunused-variable \ - -diag-disable=175,188,2259 \ + -diag-disable=175,188,1684,2259,2312 \ $extra_warnflags \ ; do AS_IF([test "$particular_werror_flags" != yes], [ @@ -549,6 +673,18 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"], ]) ]) done + AS_IF([test "$particular_werror_flags" = "yes"], [ + wflag=-Werror=undef + ], [ + wflag=-Wundef + ]) + RUBY_TRY_CFLAGS($wflag, [ + RUBY_APPEND_OPTIONS(warnflags, $wflag) + ], [], [ + @%:@if !defined(RUBY_CONFIG_TEST_NEVER_DEFINED_SYMBOL) + @%:@elif RUBY_CONFIG_TEST_NEVER_DEFINED_SYMBOL + @%:@endif + ]) AS_CASE([" $warnflags "],[*" -Wno-missing-field-initializers "*], [wflag="-Wall -Wextra"], [wflag=-Wall]) RUBY_TRY_CFLAGS($wflag, [warnflags="$wflag${warnflags+ $warnflags}"]) @@ -557,6 +693,22 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"], warnflags= ]) RUBY_TRY_CFLAGS(-Qunused-arguments, [RUBY_APPEND_OPTIONS(rb_cv_wsuppress_flags, -Qunused-arguments)]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ +@%:@if !(defined(__SUNPRO_C)||defined(__SUNPRO_CC)) +@%:@error not sunpro +@%:@endif],[])], [ + for e in \ + E_STATEMENT_NOT_REACHED \ + E_INIT_SIGN_EXTEND \ + E_INIT_DOES_NOT_FIT \ + E_INITIALIZATION_TYPE_MISMATCH + do + RUBY_TRY_CFLAGS([-erroff=${e}], [ + RUBY_APPEND_OPTIONS(rb_cv_warnflags, [-erroff=${e}]) + ]) + done +]) AC_ARG_WITH(compress-debug-sections, AS_HELP_STRING([--with-compress-debug-sections=type], @@ -580,14 +732,15 @@ AS_IF([test "$GCC" = yes], [ [disable -D_FORTIFY_SOURCE=2 option, which causes link error on mingw]), [fortify_source=$enableval]) AS_IF([test "x$fortify_source" != xno], [ - RUBY_TRY_CFLAGS(-D_FORTIFY_SOURCE=2, [RUBY_APPEND_OPTION(XCFLAGS, -D_FORTIFY_SOURCE=2)]) + RUBY_TRY_CFLAGS([$optflags -D_FORTIFY_SOURCE=2], [RUBY_APPEND_OPTION(XCFLAGS, -D_FORTIFY_SOURCE=2)], [], + [@%:@include ]) ]) : ${MJIT_HEADER_FLAGS='-P -dD'} # -fstack-protector AS_CASE(["$target_os"], - [mingw*], [ + [mingw*|emscripten*], [ stack_protector=no ]) AS_IF([test -z "${stack_protector+set}"], [ @@ -634,13 +787,13 @@ AS_IF([test "$GCC" = yes], [ ], [ CFLAGS="$CFLAGS -Werror -Wuninitialized" ]) - AC_TRY_COMPILE([@%:@include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include int foo(double x) { int exp; frexp(x, &exp); return exp; - }], [if (foo(0.0)) return 1;], + }]], [[if (foo(0.0)) return 1;]])], [rb_cv_mingw64_broken_frexp_modf=no], [rb_cv_mingw64_broken_frexp_modf=yes]) CFLAGS="$save_CFLAGS" @@ -649,8 +802,8 @@ AS_IF([test "$GCC" = yes], [ AC_DEFINE(RUBY_MINGW64_BROKEN_FREXP_MODF) ]) ], - [cygwin*|darwin*|netbsd*], [ - # need lgamma_r(), finite() + [cygwin*|msys*|darwin*|netbsd*], [ + # need lgamma_r() ]) # ANSI (no XCFLAGS because this is C only) @@ -721,7 +874,7 @@ AS_IF([test "$GCC" = yes], [ # disable fast-math for oflag in -fno-fast-math; do - RUBY_TRY_CFLAGS($oflag, [RUBY_APPEND_OPTION(CFLAGS, $oflag)]) + RUBY_TRY_CFLAGS($oflag, [RUBY_APPEND_OPTION(optflags, $oflag)]) done for oflag in -fexcess-precision=standard -fp-model\ precise; do RUBY_TRY_CFLAGS($oflag, [RUBY_APPEND_OPTION(XCFLAGS, $oflag)]) @@ -730,13 +883,13 @@ AS_IF([test "$GCC" = yes], [ AS_CASE(["$target_cpu"], [[i[3-6]86*]], [ AC_CACHE_CHECK([for __sync_val_compare_and_swap], [rb_cv_gcc_compiler_cas], [ - AC_TRY_LINK([unsigned long atomic_var;], - [__sync_val_compare_and_swap(&atomic_var, 0, 1);], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[unsigned long atomic_var;]], + [[__sync_val_compare_and_swap(&atomic_var, 0, 1);]])], [rb_cv_gcc_compiler_cas=yes], [ save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -march=i486" - AC_TRY_LINK([unsigned long atomic_var;], - [__sync_val_compare_and_swap(&atomic_var, 0, 1);], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[unsigned long atomic_var;]], + [[__sync_val_compare_and_swap(&atomic_var, 0, 1);]])], [rb_cv_gcc_compiler_cas=i486], [rb_cv_gcc_compiler_cas=no]) CFLAGS="$save_CFLAGS" @@ -763,7 +916,7 @@ test -z "${ac_env_CXXFLAGS_set}" -a -n "${cxxflags+set}" && eval CXXFLAGS="\"$cx AC_CACHE_CHECK([whether compiler has statement and declarations in expressions], rb_cv_have_stmt_and_decl_in_expr, - [AC_TRY_COMPILE([],[ __extension__ ({ int a = 0; a; }); ], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[ __extension__ ({ int a = 0; a; }); ]])], [rb_cv_have_stmt_and_decl_in_expr=yes], [rb_cv_have_stmt_and_decl_in_expr=no])]) AS_IF([test "$rb_cv_have_stmt_and_decl_in_expr" = yes], [ @@ -784,12 +937,12 @@ AS_CASE(["$target_os"], [freebsd*], [ AC_CACHE_CHECK([whether pthread should be enabled by default], rb_cv_enable_pthread_default, - [AC_TRY_CPP([ + [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ #include #if __FreeBSD_version < 502102 #error pthread should be disabled on this platform #endif - ], + ]])], rb_cv_enable_pthread_default=yes, rb_cv_enable_pthread_default=no)]) enable_pthread=$rb_cv_enable_pthread_default @@ -804,9 +957,17 @@ AS_CASE(["$target_os"], dnl Checks for libraries. AS_CASE(["$target_os"],[*bsd*|dragonfly*],[],[ac_cv_func_daemon=no]) +AS_CASE(["$target_os"], [*android*], [ + AS_CASE(["$target_cpu"], [arm*], [ + ac_cv_func___builtin_setjmp=no + ]) +]) + AS_UNSET(ORIG_LIBS) POSTLINK=: AC_SUBST(POSTLINK) +cleanlibs= +AC_SUBST(cleanlibs) AS_CASE(["$target_os"], [nextstep*], [ ], [openstep*], [ ], @@ -817,8 +978,8 @@ AS_CASE(["$target_os"], RUBY_APPEND_OPTIONS(CPPFLAGS, -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT) AC_CACHE_CHECK([whether syscall(2) is deprecated], rb_cv_syscall_deprecated, [RUBY_WERROR_FLAG([ - AC_TRY_COMPILE([@%:@include ], - [if (syscall(0)) return 1;], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[if (syscall(0)) return 1;]])], [rb_cv_syscall_deprecated=no], [rb_cv_syscall_deprecated=yes])])]) AS_IF([test $rb_cv_syscall_deprecated = yes], [ @@ -845,7 +1006,7 @@ AS_CASE(["$target_os"], ]) with_setjmp_type=sigsetjmp # to hijack SIGCHLD handler AC_CACHE_CHECK(for broken crypt with 8bit chars, rb_cv_broken_crypt, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -882,7 +1043,7 @@ main() } return 0; } -], +]])], rb_cv_broken_crypt=no, rb_cv_broken_crypt=yes, rb_cv_broken_crypt=yes)]) @@ -905,17 +1066,18 @@ main() AC_CHECK_HEADERS(crt_externs.h, [], [], [ #include ]) + cleanlibs='$(TARGET_SO).dSYM' ], [hpux*], [ LIBS="-lm $LIBS" ac_cv_c_inline=no], [solaris*], [ LIBS="-lm $LIBS" ac_cv_func_vfork=no AC_MSG_CHECKING(whether _XOPEN_SOURCE is already given) - AC_TRY_COMPILE([#include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #ifndef _XOPEN_SOURCE #error _XOPEN_SOURCE is not defined #endif - ], [], + ]], [[]])], [given_xopen_source=yes], [given_xopen_source=no]) AC_MSG_RESULT($given_xopen_source) AS_IF([test $given_xopen_source = no], [ @@ -925,13 +1087,13 @@ main() AS_IF([test x"$define_xopen_source" != x], [ break ]) - RUBY_WERROR_FLAG([AC_TRY_COMPILE([ + RUBY_WERROR_FLAG([AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _XOPEN_SOURCE ${tmp_xpg}00 #include #ifndef _XPG${tmp_xpg} #error _XPG${tmp_xpg} should be defined by _XOPEN_SOURCE=${tmp_xpg}00 #endif - ], [], + ]], [[]])], [define_xopen_source=${tmp_xpg}00], []) ]) done @@ -941,19 +1103,33 @@ main() AC_MSG_RESULT($define_xopen_source) AS_IF([test x"$define_xopen_source" != xno], [ RUBY_APPEND_OPTIONS(CPPFLAGS, -D_XOPEN_SOURCE=$define_xopen_source) + # _XOPEN_SOURCE should not be defined for C++ on Solaris. + RUBY_APPEND_OPTIONS(CXXFLAGS, -U_XOPEN_SOURCE) + ]) + ]) + AC_CHECK_TYPES([caddr_t],[],[],[@%:@include ]) + AC_CACHE_CHECK([whether madvise declaration is needed], rb_cv_madvice_prototype_using_caddr_t, + [RUBY_WERROR_FLAG([AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + @%:@include + @%:@include + @%:@include + extern int madvise(caddr_t, size_t, int); + ]], [[]])], + [rb_cv_madvice_prototype_using_caddr_t=yes], [rb_cv_madvice_prototype_using_caddr_t=no]) ]) ]) + AS_IF([test $rb_cv_madvice_prototype_using_caddr_t = yes], [AC_DEFINE(NEED_MADVICE_PROTOTYPE_USING_CADDR_T, 1)]) ], [haiku*], [ LIBS="$LIBS" # m lib is include in root ], -[cygwin*], [ ac_cv_header_langinfo_h=yes +[cygwin*|msys*], [ + ac_cv_header_langinfo_h=yes RUBY_APPEND_OPTIONS(CPPFLAGS, -D_XOPEN_SOURCE -D_GNU_SOURCE) AC_CHECK_FUNCS(cygwin_conv_path) AC_LIBOBJ([langinfo]) ], -[mingw*], [ LIBS="-lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi $LIBS" - ac_cv_header_a_out_h=no +[mingw*], [ LIBS="-lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi -lbcrypt $LIBS" ac_cv_header_pwd_h=no ac_cv_header_utime_h=no ac_cv_header_sys_ioctl_h=no @@ -978,7 +1154,7 @@ main() ac_cv_func_memcmp_working=yes ac_cv_lib_dl_dlopen=no rb_cv_binary_elf=no - rb_cv_negative_time_t=no + rb_cv_negative_time_t=yes ac_cv_func_fcntl=yes ac_cv_func_flock=yes ac_cv_func_gmtime_r=yes @@ -992,10 +1168,9 @@ main() AS_IF([test "$target_cpu" = x64], [ ac_cv_func___builtin_setjmp=yes ac_cv_func_round=no - rb_cv_coroutine=yes + coroutine_type=yes ]) ac_cv_func_tgamma=no - rb_cv_negative_time_t=yes AC_CHECK_TYPE([NET_LUID], [], [], [@%:@include @%:@include ]) @@ -1037,21 +1212,53 @@ main() ac_cv_func___builtin_setjmp=no ]) ], +[emscripten*], [LIBS="-lm -lc $LIBS" + RUBY_APPEND_OPTIONS(LDFLAGS, "-sALLOW_MEMORY_GROWTH=1") + RUBY_APPEND_OPTIONS(LDFLAGS, "-sASYNCIFY") + RUBY_APPEND_OPTIONS(LDFLAGS, "-sFORCE_FILESYSTEM=1") + ac_cv_func_shutdown=no + ], [ LIBS="-lm $LIBS"]) : ${ORIG_LIBS=$LIBS} +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.]) +], +[test -n "${CXX}"], [ + RUBY_WERROR_FLAG([ + AC_MSG_CHECKING([whether CXXFLAGS is valid]) + AC_LANG_PUSH(C++) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], [[]])], + [AC_MSG_RESULT(yes)],[ + AC_MSG_RESULT(no) + # The message mentions CXXFLAGS, but CPPFLAGS might also affects. + AC_MSG_WARN([something wrong with CXXFLAGS="$CXXFLAGS"]) + CXX=false + ]) + AC_LANG_POP(C++) + ]) +]) + AC_CHECK_LIB(crypt, crypt) # glibc (GNU/Linux, GNU/Hurd, GNU/kFreeBSD) AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX AC_CHECK_LIB(socket, shutdown) # SunOS/Solaris +if pkg-config --exists capstone; then + CAPSTONE_CFLAGS=`pkg-config --cflags capstone` + CAPSTONE_LIB_L=`pkg-config --libs-only-L capstone` + LDFLAGS="$LDFLAGS $CAPSTONE_LIB_L" + CFLAGS="$CFLAGS $CAPSTONE_CFLAGS" +fi + +AC_CHECK_LIB(capstone, cs_open) # Capstone disassembler for debugging YJIT + dnl Checks for header files. AC_HEADER_DIRENT dnl AC_HEADER_STDC has been checked in AC_USE_SYSTEM_EXTENSIONS AC_HEADER_STDBOOL AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(a.out.h) AC_CHECK_HEADERS(atomic.h) AC_CHECK_HEADERS(copyfile.h) AC_CHECK_HEADERS(direct.h) @@ -1082,6 +1289,7 @@ AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/mkdev.h) AC_CHECK_HEADERS(sys/param.h) AC_CHECK_HEADERS(sys/prctl.h) +AC_CHECK_HEADERS(sys/random.h) AC_CHECK_HEADERS(sys/resource.h) AC_CHECK_HEADERS(sys/select.h) AC_CHECK_HEADERS(sys/sendfile.h) @@ -1096,6 +1304,10 @@ 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(x86intrin.h) +]) +RUBY_UNIVERSAL_CHECK_HEADER([x86_64, i386], x86intrin.h) AC_ARG_WITH([gmp], [AS_HELP_STRING([--without-gmp], @@ -1112,42 +1324,54 @@ AC_ARG_WITH([jemalloc], [AS_HELP_STRING([--with-jemalloc],[use jemalloc allocator])], [with_jemalloc=$withval], [with_jemalloc=no]) AS_IF([test "x$with_jemalloc" != xno],[ - AC_SEARCH_LIBS([malloc_conf], [jemalloc], - [ - AC_DEFINE(HAVE_LIBJEMALLOC, 1) - with_jemalloc=yes - ], - [test x$with_jemalloc = xyes && with_jemalloc=no]) - AC_CHECK_HEADER(jemalloc/jemalloc.h, [ - AC_DEFINE(RUBY_ALTERNATIVE_MALLOC_HEADER, []) - ], - [test x$with_jemalloc = xyes && with_jemalloc=no]) - AS_IF([test "x$with_jemalloc" != xyes], [ - AC_CACHE_CHECK([for jemalloc with JEMALLOC_MANGLE], rb_cv_jemalloc_demangle, - [AC_LINK_IFELSE([AC_LANG_PROGRAM([@%:@define JEMALLOC_MANGLE 1 - @%:@ifdef RUBY_ALTERNATIVE_MALLOC_HEADER - @%:@include RUBY_ALTERNATIVE_MALLOC_HEADER - @%:@else - @%:@include - @%:@endif], [return !&malloc_conf])], - [rb_cv_jemalloc_demangle=yes], - [rb_cv_jemalloc_demangle=no]) - ]) + # find jemalloc header first + malloc_header= + AC_CHECK_HEADER(jemalloc/jemalloc.h, [malloc_header=jemalloc/jemalloc.h], [ + AC_CHECK_HEADER(jemalloc.h, [malloc_header=jemalloc.h]) ]) - AS_IF([test "x$rb_cv_jemalloc_demangle" = xyes], [ - AC_DEFINE(JEMALLOC_MANGLE) - with_jemalloc=yes + AS_IF([test "$malloc_header" != ""], [ + AC_DEFINE_UNQUOTED(RUBY_ALTERNATIVE_MALLOC_HEADER, [<$malloc_header>]) ]) + save_LIBS="$LIBS" + AC_CACHE_CHECK([for jemalloc library], rb_cv_jemalloc_library, [ + rb_cv_jemalloc_library=no + # try [with mangle, without mangle] x [no more additional + # libraries, adding jemalloc] combination, using the jemalloc + # header found above. + for mangle in '' mangle; do + for lib in '' -ljemalloc; do + LIBS="${lib:+$lib }$LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([${mangle:+@%:@define JEMALLOC_MANGLE 1} + @%:@include + @%:@ifdef RUBY_ALTERNATIVE_MALLOC_HEADER + @%:@include RUBY_ALTERNATIVE_MALLOC_HEADER + @%:@else + extern const char *malloc_conf; + @%:@endif], + [/* access at runtime not to be optimized away */ + if (malloc_conf) printf("malloc_conf=%s\n", malloc_conf);])], + [rb_cv_jemalloc_library="${lib:-none required}${mangle:+ with mangle}"]) + LIBS="$save_LIBS" + test "${rb_cv_jemalloc_library}" = no || break 2 + done + done + ]) + with_jemalloc=${rb_cv_jemalloc_library} AS_CASE(["$with_jemalloc"], - [yes], - [ - AC_DEFINE(HAVE_MALLOC_CONF) - ac_cv_func_malloc_usable_size=yes - ], - [no], - [AC_MSG_ERROR([jemalloc requested but not found]) + [no], + [AC_MSG_ERROR([jemalloc requested but not found])], + [-l*], [ + set dummy $with_jemalloc + LIBS="$2 $LIBS" + DLDLIBS="$2${DLDLIBS:+ $DLDLIBS}" # probably needed also in extension libraries ]) -]) + AS_CASE(["$with_jemalloc"], + [*" with mangle"], [ + AC_DEFINE(JEMALLOC_MANGLE) + ]) + AC_DEFINE(HAVE_MALLOC_CONF) + ac_cv_func_malloc_usable_size=yes +]) # with_jemalloc dnl check for large file stuff mv confdefs.h confdefs1.h @@ -1187,7 +1411,7 @@ AS_CASE(["$target_os"], ]) ]) -AC_C_BIGENDIAN +AC_C_BIGENDIAN([], [], [], [AC_DEFINE(AC_APPLE_UNIVERSAL_BUILD, 1)]) AC_C_CONST AC_C_CHAR_UNSIGNED AC_C_INLINE @@ -1225,8 +1449,8 @@ AC_CACHE_CHECK(packed struct attribute, rb_cv_packed_struct, "__pragma(pack(push, 1)) x __pragma(pack(pop))" \ "x __attribute__((packed))" \ ; do - AC_TRY_COMPILE([@%:@define PACKED_STRUCT(x) $mac - PACKED_STRUCT(struct { int a; });], [], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@define PACKED_STRUCT(x) $mac + PACKED_STRUCT(struct { int a; });]], [[]])], [rb_cv_packed_struct=$mac; break]) done]) AS_IF([test "$rb_cv_packed_struct" != no], [ @@ -1265,132 +1489,58 @@ RUBY_REPLACE_TYPE(clockid_t, [], CLOCKID, [@%:@ifdef HAVE_TIME_H @%:@ include @%:@endif]) -AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes, - [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);], - rb_cv_have_prototypes=yes, - rb_cv_have_prototypes=no)]) -AS_IF([test "$rb_cv_have_prototypes" = yes], [ - AC_DEFINE(HAVE_PROTOTYPES) -]) - -AC_CACHE_CHECK(token paste string, rb_cv_tokenpaste, - [AC_TRY_COMPILE([@%:@define paste(a,b) a@%:@@%:@b], - [int xy = 1; return paste(x,y);], - rb_cv_tokenpaste=ansi, - rb_cv_tokenpaste=knr)]) -AS_IF([test "$rb_cv_tokenpaste" = ansi], [ - AC_DEFINE(TOKEN_PASTE(x,y),[x@%:@@%:@y]) -], [ - AC_DEFINE(TOKEN_PASTE(x,y),[x/**/y]) -]) - -AC_CACHE_CHECK(stringization, rb_cv_stringization, [ - rb_cv_stringization=no - for string in "#expr" '"expr"'; do - AC_COMPILE_IFELSE([ - AC_LANG_BOOL_COMPILE_TRY([ -#define STRINGIZE0(expr) $string -#define STRINGIZE(expr) STRINGIZE0(expr) -#undef real_test_for_stringization -#define test_for_stringization -.real_test_for_stringization.- -const char stringized[[]] = STRINGIZE(test_for_stringization); -], [sizeof(stringized) == 32])], - [rb_cv_stringization="$string"; break], - [rb_cv_stringization=no]) - done] -) -AC_DEFINE(STRINGIZE(expr),STRINGIZE0(expr)) -AS_IF([test x"$rb_cv_stringization" != xno -a "$rb_cv_stringization" != "#expr"], [ - AC_DEFINE_UNQUOTED(STRINGIZE0(expr),$rb_cv_stringization) - AC_DEFINE(OLD_FASHIONED_STRINGIZATION,1) -]) - -AC_CACHE_CHECK([string literal concatenation], - rb_cv_string_literal_concatenation, [ - AC_COMPILE_IFELSE([ - AC_LANG_BOOL_COMPILE_TRY([ -const char concatenated_literal[[]] = "literals" "to" - "be" "concatenated."; -], [sizeof(concatenated_literal) == 26])], - [rb_cv_string_literal_concatenation=yes], - [rb_cv_string_literal_concatenation=no])] -) -AS_IF([test "$rb_cv_string_literal_concatenation" = no], [ - AC_MSG_ERROR([No string literal concatenation]) -]) - -AC_CACHE_CHECK(for variable length prototypes and stdarg.h, rb_cv_stdarg, - [AC_TRY_COMPILE([ -#include -int foo(int x, ...) { - va_list va; - va_start(va, x); - va_arg(va, int); - va_arg(va, char *); - va_arg(va, double); - return 0; -} -], [return foo(10, "", 3.14);], - rb_cv_stdarg=yes, - rb_cv_stdarg=no)]) -AS_IF([test "$rb_cv_stdarg" = yes], [ - AC_DEFINE(HAVE_STDARG_PROTOTYPES) -]) - +# __VA_ARGS__ is also tested in AC_PROG_CC_C99 since autoconf 2.60a (around +# 2006). The check below is redundant and should always success. Remain not +# deleted for backward compat. AC_CACHE_CHECK(for variable length macro, rb_cv_va_args_macro, - [AC_TRY_COMPILE([ -int foo(int x, ...); -@%:@define FOO(a, ...) foo(a, @%:@@%:@__VA_ARGS__) -], [FOO(1);FOO(1,2);FOO(1,2,3);], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +int foo(const char*); +@%:@define FOO(...) foo(@%:@__VA_ARGS__) +]], [[FOO(1);FOO(1,2);FOO(1,2,3);]])], rb_cv_va_args_macro=yes, rb_cv_va_args_macro=no)]) AS_IF([test "$rb_cv_va_args_macro" = yes], [ AC_DEFINE(HAVE_VA_ARGS_MACRO) ]) -AC_CACHE_CHECK([for alignas() syntax], rb_cv_have_alignas, [ -rb_cv_have_alignas=no -RUBY_WERROR_FLAG([ -for attr in \ - "_Alignas(x)" \ - "alignas(x)" \ - "@<:@@<:@alignas(x)@:>@@:>@" \ - "__declspec(aligned(x))" \ - "__attribute__((__aligned__(x)))" \ -; -do - # C11 _Alignas and GCC __attribute__((__aligned__)) behave - # slightly differently. What we want is GCC's. Check that - # here by something C11 does not allow (`struct ALIGNAS ...`) - AC_TRY_COMPILE( - [@%:@define ALIGNAS(x) $attr - struct ALIGNAS(128) conftest_tag { int foo; } foo; ], [], - [rb_cv_have_alignas="$attr"; break], []) -done -])]) -AS_IF([test "$rb_cv_have_alignas" != no], [ - AC_DEFINE_UNQUOTED([RUBY_ALIGNAS(x)], $rb_cv_have_alignas) +# We want C11's `_Alignof`. GCC (and alike) have `__alignof__`, which behave +# slightly differently than the C11's. We cannot use `__alignof__` for our +# purpose. The problem is, however, that old gcc and old clang had both +# implemented `_Alignof` as a synonym of `__alignof__`. They are not what we +# want. We have to check sanity. +# +# See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 +# See also: https://bugs.llvm.org/show_bug.cgi?id=26547 +AC_CACHE_CHECK([if _Alignof() works], rb_cv_have__alignof,[ + rb_cv_have__alignof=no + RUBY_WERROR_FLAG([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + @%:@ifdef HAVE_STDALIGN_H + @%:@include + @%:@endif + @%:@ifdef STDC_HEADERS + @%:@include + @%:@endif + @%:@ifndef __GNUC__ + @%:@define __extension__ + @%:@endif + ]], [[ + typedef struct conftest_tag { + char _; + double d; + } T; + static int conftest_ary@<:@ + offsetof(T, d) == __extension__ _Alignof(double) + ? 1 : -1 + @:>@; + return conftest_ary@<:@0@:>@; + ]])],[ + rb_cv_have__alignof=yes + ],[]) + ]) ]) - -AC_CACHE_CHECK([for alignof() syntax], rb_cv_have_alignof,[ -rb_cv_have_alignof=no -RUBY_WERROR_FLAG([ -for expr in \ - "alignof" \ - "_Alignof" \ - "__alignof" \ - "__alignof__" \ -; -do - AC_TRY_COMPILE([ - @%:@ifdef HAVE_STDALIGN_H - @%:@include - @%:@endif],[return (int)$expr(int);], - [rb_cv_have_alignof="$expr"; break], []) -done -])]) -AS_IF([test "$rb_cv_have_alignof" != no], [ - AC_DEFINE_UNQUOTED(RUBY_ALIGNOF, $rb_cv_have_alignof) +AS_IF([test "$rb_cv_have__alignof" != no], [ + AC_DEFINE(HAVE__ALIGNOF) ]) RUBY_FUNC_ATTRIBUTE(__const__, CONSTFUNC) @@ -1398,7 +1548,6 @@ RUBY_FUNC_ATTRIBUTE(__pure__, PUREFUNC) RUBY_FUNC_ATTRIBUTE(__noreturn__, NORETURN) RUBY_FUNC_ATTRIBUTE(__deprecated__, DEPRECATED) RUBY_FUNC_ATTRIBUTE(__deprecated__("by "@%:@n), DEPRECATED_BY(n,x), rb_cv_func_deprecated_by) -RUBY_TYPE_ATTRIBUTE(__deprecated__ mesg, DEPRECATED_TYPE(mesg,x), rb_cv_type_deprecated) RUBY_FUNC_ATTRIBUTE(__noinline__, NOINLINE) RUBY_FUNC_ATTRIBUTE(__always_inline__, ALWAYS_INLINE) RUBY_FUNC_ATTRIBUTE(__no_sanitize__(san), NO_SANITIZE(san, x), rb_cv_func_no_sanitize) @@ -1428,6 +1577,17 @@ AS_IF([test "$rb_cv_CentOS6_CXX_workaround" != no],[ AC_DEFINE([RUBY_CXX_DEPRECATED(msg)], [__attribute__((__deprecated__(msg)))])]) +AC_CACHE_CHECK([for std::nullptr_t], rb_cv_CXX_nullptr, [ + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [@%:@include ], + [static std::nullptr_t const *const conftest = nullptr;])], + [rb_cv_CXX_nullptr=yes], + [rb_cv_CXX_nullptr=no]) + AC_LANG_POP()]) +AS_IF([test "$rb_cv_CXX_nullptr" != no],[AC_DEFINE(HAVE_NULLPTR)]) + if_i386=${universal_binary+[defined __i386__]} RUBY_FUNC_ATTRIBUTE(__stdcall__, FUNC_STDCALL, rb_cv_func_stdcall, ${if_i386}) RUBY_FUNC_ATTRIBUTE(__cdecl__, FUNC_CDECL, rb_cv_func_cdecl, ${if_i386}) @@ -1439,8 +1599,8 @@ AS_IF([test "$GCC" = yes], [ AC_CACHE_CHECK([for function alias], [rb_cv_gcc_function_alias], [rb_cv_gcc_function_alias=no for a in alias weak,alias; do - AC_TRY_LINK([void foo(void) {} - void bar(void) __attribute__(($a("foo")));], [bar()], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[void foo(void) {} + void bar(void) __attribute__(($a("foo")));]], [[bar()]])], [rb_cv_gcc_function_alias=$a; break]) done]) AS_IF([test "$rb_cv_gcc_function_alias" != no], [ @@ -1450,16 +1610,18 @@ AS_IF([test "$GCC" = yes], [ AC_DEFINE_UNQUOTED([RUBY_ALIAS_FUNCTION_VOID(prot, name, args)], [RUBY_ALIAS_FUNCTION_TYPE(void, prot, name, args)]) ]) +]) +{ AC_CACHE_CHECK([for __atomic builtins], [rb_cv_gcc_atomic_builtins], [ - AC_TRY_LINK([unsigned char atomic_var;], - [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[unsigned int atomic_var;]], + [[ __atomic_exchange_n(&atomic_var, 0, __ATOMIC_SEQ_CST); __atomic_exchange_n(&atomic_var, 1, __ATOMIC_SEQ_CST); __atomic_fetch_add(&atomic_var, 1, __ATOMIC_SEQ_CST); __atomic_fetch_sub(&atomic_var, 1, __ATOMIC_SEQ_CST); __atomic_or_fetch(&atomic_var, 1, __ATOMIC_SEQ_CST); - ], + ]])], [rb_cv_gcc_atomic_builtins=yes], [rb_cv_gcc_atomic_builtins=no])]) AS_IF([test "$rb_cv_gcc_atomic_builtins" = yes], [ @@ -1467,15 +1629,15 @@ AS_IF([test "$GCC" = yes], [ ]) AC_CACHE_CHECK([for __sync builtins], [rb_cv_gcc_sync_builtins], [ - AC_TRY_LINK([unsigned char atomic_var;], - [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[unsigned int atomic_var;]], + [[ __sync_lock_test_and_set(&atomic_var, 0); __sync_lock_test_and_set(&atomic_var, 1); __sync_fetch_and_add(&atomic_var, 1); __sync_fetch_and_sub(&atomic_var, 1); __sync_or_and_fetch(&atomic_var, 1); __sync_val_compare_and_swap(&atomic_var, 0, 1); - ], + ]])], [rb_cv_gcc_sync_builtins=yes], [rb_cv_gcc_sync_builtins=no])]) AS_IF([test "$rb_cv_gcc_sync_builtins" = yes], [ @@ -1484,8 +1646,8 @@ AS_IF([test "$GCC" = yes], [ AC_CACHE_CHECK(for __builtin_unreachable, rb_cv_func___builtin_unreachable, [RUBY_WERROR_FLAG( - [AC_TRY_LINK([volatile int zero;], - [if (zero) __builtin_unreachable();], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[volatile int zero;]], + [[if (zero) __builtin_unreachable();]])], [rb_cv_func___builtin_unreachable=yes], [rb_cv_func___builtin_unreachable=no]) ]) @@ -1493,14 +1655,14 @@ AS_IF([test "$GCC" = yes], [ AS_IF([test "$rb_cv_func___builtin_unreachable" = yes], [ AC_DEFINE_UNQUOTED(UNREACHABLE, [__builtin_unreachable()]) ]) -]) +} 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 - AC_TRY_COMPILE([@%:@define RUBY_FUNC_EXPORTED $mac extern - RUBY_FUNC_EXPORTED void conftest_attribute_check(void);], [], + 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]) done ])]) @@ -1516,22 +1678,23 @@ RUBY_DECL_ATTRIBUTE([__nonnull__(n)], [RUBY_FUNC_NONNULL(n,x)], [rb_cv_func_nonn RUBY_APPEND_OPTION(XCFLAGS, -DRUBY_EXPORT) AC_ARG_ENABLE(mathn, - AS_HELP_STRING([--disable-mathn], [disable canonicalization for mathn]), - [mathn=$enableval], [mathn=yes]) -test "x$mathn" = xyes || mathn= -AC_SUBST(MATHN, $mathn) + AS_HELP_STRING([--enable-mathn], [enable canonicalization for mathn]), + [AC_MSG_ERROR([mathn support has been dropped])]) AC_CACHE_CHECK(for function name string predefined identifier, rb_cv_function_name_string, - [rb_cv_function_name_string=no - RUBY_WERROR_FLAG([ - for func in __func__ __FUNCTION__; do - AC_TRY_LINK([@%:@include ], - [puts($func);], - [rb_cv_function_name_string=$func - break]) - done - ])] + [AS_CASE(["$target_os"],[openbsd*],[ + rb_cv_function_name_string=__func__ + ],[ + rb_cv_function_name_string=no + RUBY_WERROR_FLAG([ + for func in __func__ __FUNCTION__; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[puts($func);]])], + [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]) @@ -1591,16 +1754,21 @@ RUBY_CHECK_SIGNEDNESS(size_t, [AC_MSG_ERROR(size_t is signed)], [], [@%:@include ]) RUBY_CHECK_SIZEOF(size_t, [int long void*], [], [@%:@include ]) RUBY_CHECK_SIZEOF(ptrdiff_t, size_t, [], [@%:@include ]) +RUBY_CHECK_SIZEOF(dev_t) RUBY_CHECK_PRINTF_PREFIX(size_t, z) RUBY_CHECK_PRINTF_PREFIX(ptrdiff_t, t) -AC_STRUCT_ST_BLKSIZE -AC_STRUCT_ST_BLOCKS -AC_STRUCT_ST_RDEV +AC_CHECK_MEMBERS([struct stat.st_blksize]) +AC_CHECK_MEMBERS([struct stat.st_blocks]) +AC_CHECK_MEMBERS([struct stat.st_rdev]) RUBY_CHECK_SIZEOF([struct stat.st_size], [off_t int long "long long"], [], [@%:@include ]) AS_IF([test "$ac_cv_member_struct_stat_st_blocks" = yes], [ RUBY_CHECK_SIZEOF([struct stat.st_blocks], [off_t int long "long long"], [], [@%:@include ]) ]) RUBY_CHECK_SIZEOF([struct stat.st_ino], [long "long long"], [], [@%:@include ]) +RUBY_CHECK_SIZEOF([struct stat.st_dev], [dev_t int long "long long"], [], [@%:@include ]) +AS_IF([test "$ac_cv_member_struct_stat_st_rdev" = yes], [ + RUBY_CHECK_SIZEOF([struct stat.st_rdev], [dev_t int long "long long"], [], [@%:@include ]) +]) AC_CHECK_MEMBERS([struct stat.st_atim]) AC_CHECK_MEMBERS([struct stat.st_atimespec]) AC_CHECK_MEMBERS([struct stat.st_atimensec]) @@ -1684,9 +1852,9 @@ AS_IF([test "x$rb_cv_type_int64_t" != xno], [ AC_CACHE_CHECK(for stack end address, rb_cv_stack_end_address, [rb_cv_stack_end_address=no - AC_TRY_LINK( - [extern void *__libc_stack_end;], - [if (!__libc_stack_end) return 1;], + AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[extern void *__libc_stack_end;]], + [[if (!__libc_stack_end) return 1;]])], [rb_cv_stack_end_address="__libc_stack_end"]) ]) AS_IF([test $rb_cv_stack_end_address != no], [ @@ -1695,7 +1863,6 @@ AS_IF([test $rb_cv_stack_end_address != no], [ dnl Checks for library functions. AC_TYPE_GETGROUPS -AC_TYPE_SIGNAL AS_CASE(["${target_cpu}-${target_os}:${target_archs}"], [powerpc-darwin*], [ AC_LIBSOURCES(alloca.c) @@ -1715,14 +1882,14 @@ AS_CASE(["${target_cpu}-${target_os}:${target_archs}"], AS_IF([test "x$ALLOCA" = "x"], [ AC_CACHE_CHECK([for dynamic size alloca], rb_cv_dynamic_alloca, [ for chk in ok __chkstk; do - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@ifdef HAVE_ALLOCA_H @%:@include @%:@endif void $chk() {} int dynamic_alloca_test; - int dynamic_alloca_result;], - [dynamic_alloca_result = alloca(dynamic_alloca_test) != 0;], + int dynamic_alloca_result;]], + [[dynamic_alloca_result = alloca(dynamic_alloca_test) != 0;]])], [rb_cv_dynamic_alloca=$chk; break]) done]) AS_IF([test "x$rb_cv_dynamic_alloca" = "x__chkstk"], [ @@ -1740,10 +1907,16 @@ AS_CASE(["$target_os"],[freebsd*],[ AC_REPLACE_FUNCS(close) ]) +AC_DEFUN([RUBY_REQUIRE_FUNC], [ + AC_CHECK_FUNCS([$1]) + AS_IF([test "$ac_cv_func_[]AS_TR_SH($1)" = yes], [], + [AC_MSG_ERROR($1[() must be supported])]) +]) +m4_map_args_w([dup dup2], [RUBY_REQUIRE_FUNC(], [)]) + AC_REPLACE_FUNCS(acosh) AC_REPLACE_FUNCS(cbrt) AC_REPLACE_FUNCS(crypt) -AC_REPLACE_FUNCS(dup2) AC_REPLACE_FUNCS(erf) AC_REPLACE_FUNCS(explicit_bzero) AC_REPLACE_FUNCS(ffs) @@ -1761,9 +1934,7 @@ AC_REPLACE_FUNCS(strlcpy) AC_REPLACE_FUNCS(strstr) AC_REPLACE_FUNCS(tgamma) -RUBY_REPLACE_FUNC([finite], [@%:@include ]) -RUBY_REPLACE_FUNC([isinf], [@%:@include ]) -RUBY_REPLACE_FUNC([isnan], [@%:@include ]) +AC_DEFINE(HAVE_ISFINITE) # C99; backward compatibility # for missing/setproctitle.c AS_CASE(["$target_os"], @@ -1773,17 +1944,7 @@ AS_CASE(["$target_os"], AC_CHECK_HEADERS(sys/pstat.h) -AC_CACHE_CHECK(for signbit, rb_cv_have_signbit, - [AC_TRY_LINK([ -#include -], [int v = signbit(-0.0);], - rb_cv_have_signbit=yes, - rb_cv_have_signbit=no)]) -AS_IF([test "$rb_cv_have_signbit" = yes], [ - AC_DEFINE(HAVE_SIGNBIT) -], [ - AC_LIBOBJ([signbit]) -]) +AC_DEFINE(HAVE_SIGNBIT) # C99; backward compatibility AC_FUNC_FORK @@ -1804,7 +1965,6 @@ AC_CHECK_FUNCS(dirfd) AC_CHECK_FUNCS(dl_iterate_phdr) AC_CHECK_FUNCS(dlopen) AC_CHECK_FUNCS(dladdr) -AC_CHECK_FUNCS(dup) AC_CHECK_FUNCS(dup3) AC_CHECK_FUNCS(eaccess) AC_CHECK_FUNCS(endgrent) @@ -1824,14 +1984,20 @@ AC_CHECK_FUNCS(ftruncate) AC_CHECK_FUNCS(ftruncate64) # used for Win32 platform AC_CHECK_FUNCS(getattrlist) AC_CHECK_FUNCS(getcwd) +AC_CHECK_FUNCS(getentropy) AC_CHECK_FUNCS(getgidx) AC_CHECK_FUNCS(getgrnam) AC_CHECK_FUNCS(getgrnam_r) AC_CHECK_FUNCS(getgroups) +AC_CHECK_FUNCS(getlogin) +AC_CHECK_FUNCS(getlogin_r) AC_CHECK_FUNCS(getpgid) AC_CHECK_FUNCS(getpgrp) AC_CHECK_FUNCS(getpriority) +AC_CHECK_FUNCS(getpwnam) AC_CHECK_FUNCS(getpwnam_r) +AC_CHECK_FUNCS(getpwuid) +AC_CHECK_FUNCS(getpwuid_r) AC_CHECK_FUNCS(getrandom) AC_CHECK_FUNCS(getresgid) AC_CHECK_FUNCS(getresuid) @@ -1865,6 +2031,7 @@ AC_CHECK_FUNCS(memmem) AC_CHECK_FUNCS(mkfifo) AC_CHECK_FUNCS(mknod) AC_CHECK_FUNCS(mktime) +AC_CHECK_FUNCS(mmap) AC_CHECK_FUNCS(openat) AC_CHECK_FUNCS(pipe2) AC_CHECK_FUNCS(poll) @@ -1918,6 +2085,8 @@ AC_CHECK_FUNCS(utimensat) AC_CHECK_FUNCS(utimes) AC_CHECK_FUNCS(wait4) AC_CHECK_FUNCS(waitpid) +AC_CHECK_FUNCS(__cospi) +AC_CHECK_FUNCS(__sinpi) AS_IF([test "x$ac_cv_member_struct_statx_stx_btime" = xyes], [AC_CHECK_FUNCS(statx)]) @@ -1927,7 +2096,7 @@ AS_CASE(["$ac_cv_func_memset_s:$ac_cv_func_qsort_s"], [*yes*], AS_IF([test "$ac_cv_func_getcwd" = yes], [ AC_CACHE_CHECK(if getcwd allocates buffer if NULL is given, [rb_cv_getcwd_malloc], - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ @%:@include @%:@include @%:@ifdef HAVE_UNISTD_H @@ -1946,11 +2115,11 @@ main(int argc, char **argv) if (!getcwd(NULL, 0)) return EXIT_FAILURE; return EXIT_SUCCESS; } -], +]])], rb_cv_getcwd_malloc=yes, rb_cv_getcwd_malloc=no, AS_CASE($target_os, - [linux*|darwin*|*bsd|cygwin*|mingw*|mswin*], + [linux*|darwin*|*bsd|cygwin*|msys*|mingw*|mswin*], [rb_cv_getcwd_malloc=yes], [rb_cv_getcwd_malloc=no]))]) AS_IF([test "$rb_cv_getcwd_malloc" = no], [AC_DEFINE(NO_GETCWD_MALLOC, 1)]) @@ -1991,24 +2160,25 @@ AS_IF([test x$rb_cv_builtin___builtin_choose_expr = xyes], [ ]) RUBY_CHECK_BUILTIN_FUNC(__builtin_types_compatible_p, [__builtin_types_compatible_p(int, int)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_trap, [__builtin_trap()]) +RUBY_CHECK_BUILTIN_FUNC(__builtin_expect, [__builtin_expect(0, 0)]) AS_IF([test "$ac_cv_func_qsort_r" != no], [ AC_CACHE_CHECK(whether qsort_r is GNU version, rb_cv_gnu_qsort_r, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include void (qsort_r)(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg); -],[ ], +]], [[ ]])], [rb_cv_gnu_qsort_r=yes], [rb_cv_gnu_qsort_r=no]) ]) AC_CACHE_CHECK(whether qsort_r is BSD version, rb_cv_bsd_qsort_r, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include void (qsort_r)(void *base, size_t nmemb, size_t size, void *arg, int (*compar)(void *, const void *, const void *)); -],[ ], +]], [[ ]])], [rb_cv_bsd_qsort_r=yes], [rb_cv_bsd_qsort_r=no]) ]) @@ -2023,7 +2193,7 @@ void (qsort_r)(void *base, size_t nmemb, size_t size, AC_CACHE_CHECK(whether atan2 handles Inf as C99, rb_cv_atan2_inf_c99, [ AS_IF([test $ac_cv_func_atan2f:$ac_cv_func_atan2l = yes:yes], [ - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ @%:@include @%:@ifdef HAVE_UNISTD_H @%:@include @@ -2041,7 +2211,7 @@ main(int argc, char **argv) if (fabs(atan2(INFINITY, INFINITY) - M_PI_4) <= 0.01) return EXIT_SUCCESS; return EXIT_FAILURE; } -], +]])], [rb_cv_atan2_inf_c99=yes], [rb_cv_atan2_inf_c99=no], [AS_CASE($target_os, [mingw*|mswin*], [rb_cv_atan2_inf_c99=no], [rb_cv_atan2_inf_c99=yes])] @@ -2070,9 +2240,9 @@ AS_IF([test x"$ac_cv_lib_rt_timer_settime" = xyes], [ ]) AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -], [int v = unsetenv("foo");], +]], [[int v = unsetenv("foo");]])], rb_cv_unsetenv_return_value=yes, rb_cv_unsetenv_return_value=no)]) AS_IF([test "$rb_cv_unsetenv_return_value" = no], [ @@ -2090,21 +2260,21 @@ AS_IF([test "$use_setreuid" = yes], [ ]) AC_STRUCT_TIMEZONE AC_CACHE_CHECK(for struct tm.tm_gmtoff, rb_cv_member_struct_tm_tm_gmtoff, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@define _BSD_SOURCE @%:@define _DEFAULT_SOURCE @%:@include - ], - [struct tm t; t.tm_gmtoff = 3600;], + ]], + [[struct tm t; t.tm_gmtoff = 3600;]])], [rb_cv_member_struct_tm_tm_gmtoff=yes], [rb_cv_member_struct_tm_tm_gmtoff=no])]) AS_IF([test "$rb_cv_member_struct_tm_tm_gmtoff" = yes], [ AC_DEFINE(HAVE_STRUCT_TM_TM_GMTOFF) ]) AC_CACHE_CHECK(for external int daylight, rb_cv_have_daylight, - [AC_TRY_LINK([#include - int i;], - [i = daylight;], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include + int i;]], + [[i = daylight;]])], rb_cv_have_daylight=yes, rb_cv_have_daylight=no)]) AS_IF([test "$rb_cv_have_daylight" = yes], [ @@ -2112,7 +2282,7 @@ AS_IF([test "$rb_cv_have_daylight" = yes], [ ]) AC_CACHE_CHECK(for negative time_t for gmtime(3), rb_cv_negative_time_t, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -2142,7 +2312,7 @@ main() check(gmtime(&t), 1, 12, 13, 20, 52); return 0; } -], +]])], rb_cv_negative_time_t=yes, rb_cv_negative_time_t=no, rb_cv_negative_time_t=yes)]) @@ -2153,7 +2323,7 @@ AS_IF([test "$rb_cv_negative_time_t" = yes], [ # [ruby-dev:40910] overflow of time on FreeBSD # http://www.freebsd.org/cgi/query-pr.cgi?pr=145341 AC_CACHE_CHECK(for localtime(3) overflow correctly, rb_cv_localtime_overflow, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -2185,7 +2355,7 @@ main() check(t); return 0; } -], +]])], rb_cv_localtime_overflow=yes, rb_cv_localtime_overflow=no, rb_cv_localtime_overflow=no)]) @@ -2198,7 +2368,7 @@ AS_IF([test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = ye ], [ AC_CHECK_FUNCS(sigsetmask) AC_CACHE_CHECK(for BSD signal semantics, rb_cv_bsd_signal, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -2216,7 +2386,7 @@ main() kill(getpid(), SIGINT); return 0; } -], +]])], rb_cv_bsd_signal=yes, rb_cv_bsd_signal=no, rb_cv_bsd_signal=$ac_cv_func_sigsetmask)]) @@ -2259,6 +2429,45 @@ AS_IF([test "$rb_cv_rshift_sign" = yes], [ AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>(int)(y)) : (x)>>(int)(y))) ]) +AS_IF([test "$ac_cv_func_copy_file_range" = no], [ + AC_CACHE_CHECK([for copy_file_range], + rb_cv_use_copy_file_range, + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include +#include +#include + +#ifndef O_TMPFILE + #define O_TMPFILE __O_TMPFILE +#endif + +int +main() +{ +#ifdef __NR_copy_file_range + int ret, fd_in, fd_out; + fd_in = open("/tmp", O_TMPFILE|O_RDWR, S_IRUSR); + fd_out = open("/tmp", O_TMPFILE|O_WRONLY, S_IWUSR); + ret = syscall(__NR_copy_file_range, fd_in, NULL, fd_out, NULL, 0, 0); + close(fd_in); + close(fd_out); + if (ret == -1) { return 1; } + return 0; +#else + return 1; +#endif +} + ]])], + [rb_cv_use_copy_file_range=yes], + [rb_cv_use_copy_file_range=no], + [rb_cv_use_copy_file_range=no])]) +]) +AS_CASE(["$ac_cv_func_copy_file_range:$rb_cv_use_copy_file_range"], [*yes*], [ + AC_DEFINE(USE_COPY_FILE_RANGE) +]) + AS_CASE(["$ac_cv_func_gettimeofday:$ac_cv_func_clock_gettime"], [*yes*], [], [ @@ -2302,62 +2511,99 @@ AS_IF([test "${universal_binary-no}" = yes ], [ AC_ARG_WITH(coroutine, AS_HELP_STRING([--with-coroutine=IMPLEMENTATION], [specify the coroutine implementation to use]), - [rb_cv_coroutine=$withval]) -AS_CASE([$rb_cv_coroutine], [yes|''], [ - AC_MSG_CHECKING(native coroutine implementation for ${target_cpu}-${target_os}) + [coroutine_type=$withval], [coroutine_type=]) +AS_CASE([$coroutine_type], [yes|''], [ + coroutine_type= AS_CASE(["$target_cpu-$target_os"], + [universal-darwin*], [ + coroutine_type=universal + ], [x*64-darwin*], [ - rb_cv_coroutine=amd64 + coroutine_type=amd64 + ], + [arm64-darwin*], [ + coroutine_type=arm64 ], [x*64-linux*], [ AS_CASE(["$ac_cv_sizeof_voidp"], - [8], [ rb_cv_coroutine=amd64 ], - [4], [ rb_cv_coroutine=x86 ], - [*], [ rb_cv_coroutine= ] + [8], [ coroutine_type=amd64 ], + [4], [ coroutine_type=x86 ], + dnl unknown pointer size, bail out as no Context.h soon. ) ], [*86-linux*], [ - rb_cv_coroutine=x86 + coroutine_type=x86 ], - [x64-mingw32], [ - rb_cv_coroutine=win64 + [x64-mingw*], [ + coroutine_type=win64 ], - [*86-mingw32], [ - rb_cv_coroutine=win32 + [*86-mingw*], [ + coroutine_type=win32 ], - [armv7*-linux*], [ - rb_cv_coroutine=ucontext + [arm*-linux*], [ + coroutine_type=arm32 ], [aarch64-linux*], [ - rb_cv_coroutine=arm64 + coroutine_type=arm64 ], [powerpc64le-linux*], [ - rb_cv_coroutine=ppc64le + coroutine_type=ppc64le + ], + [riscv64-linux*], [ + coroutine_type=riscv64 + ], + [x86_64-freebsd*], [ + coroutine_type=amd64 + ], + [i386-freebsd*], [ + coroutine_type=x86 + ], + [aarch64-freebsd*], [ + coroutine_type=arm64 + ], + [x86_64-netbsd*], [ + coroutine_type=amd64 + ], + [i386-netbsd*], [ + coroutine_type=x86 + ], + [aarch64-netbsd*], [ + coroutine_type=arm64 ], [x86_64-openbsd*], [ - rb_cv_coroutine=amd64 + coroutine_type=amd64 ], [i386-openbsd*], [ - rb_cv_coroutine=x86 + coroutine_type=x86 ], [*-openbsd*], [ - rb_cv_coroutine=copy + coroutine_type=pthread + ], + [x86_64-dragonfly*], [ + coroutine_type=amd64 ], - [*], [ - rb_cv_coroutine=ucontext + [*-haiku*], [ + coroutine_type=pthread + ], + [*-emscripten*], [ + coroutine_type=emscripten + ], + [ + AC_CHECK_FUNCS([getcontext swapcontext makecontext], + [coroutine_type=ucontext], + [coroutine_type=pthread; break] + ) ] ) - AC_MSG_RESULT(${rb_cv_coroutine}) -]) -COROUTINE_H=coroutine/$rb_cv_coroutine/Context.h -AS_CASE([$rb_cv_coroutine], - [copy|ucontext], [ - COROUTINE_SRC=coroutine/$rb_cv_coroutine/Context.c - ], - [*], [ - COROUTINE_SRC=coroutine/$rb_cv_coroutine/Context.'$(ASMEXT)' - ], -) + AC_MSG_CHECKING(native coroutine implementation for ${target_cpu}-${target_os}) + AC_MSG_RESULT(${coroutine_type}) +]) +COROUTINE_H=coroutine/$coroutine_type/Context.h +AS_IF([test ! -f "$srcdir/$COROUTINE_H"], + [AC_MSG_ERROR('$coroutine_type' is not supported as coroutine)]) +COROUTINE_SRC=coroutine/$coroutine_type/Context.c +AS_IF([test ! -f "$srcdir/$COROUTINE_SRC"], + [COROUTINE_SRC=coroutine/$coroutine_type/Context.'$(ASMEXT)']) AC_DEFINE_UNQUOTED(COROUTINE_H, ["$COROUTINE_H"]) AC_SUBST(X_COROUTINE_H, [$COROUTINE_H]) AC_SUBST(X_COROUTINE_SRC, [$COROUTINE_SRC]) @@ -2382,13 +2628,13 @@ AS_IF([test x"$enable_pthread" = xyes], [ AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled") ]) AC_CACHE_CHECK([whether pthread_t is scalar type], [rb_cv_scalar_pthread_t], [ - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include - ], [ + ]], [[ pthread_t thread_id; thread_id = 0; if (!thread_id) return 0; - ], [rb_cv_scalar_pthread_t=yes], [rb_cv_scalar_pthread_t=no]) + ]])],[rb_cv_scalar_pthread_t=yes],[rb_cv_scalar_pthread_t=no]) ]) AS_IF([test x"$rb_cv_scalar_pthread_t" = xyes], [ : # RUBY_CHECK_SIZEOF(pthread_t, [void* int long], [], [@%:@include ]) @@ -2400,28 +2646,29 @@ AS_IF([test x"$enable_pthread" = xyes], [ pthread_get_stackaddr_np pthread_get_stacksize_np \ thr_stksegment pthread_stackseg_np pthread_getthrds_np \ pthread_condattr_setclock \ - pthread_sigmask pthread_setname_np pthread_set_name_np) + pthread_setname_np pthread_set_name_np) + AS_CASE(["$target_os"],[emscripten*],[ac_cv_func_pthread_sigmask=no],[AC_CHECK_FUNCS(pthread_sigmask)]) AS_CASE(["$target_os"],[aix*],[ac_cv_func_pthread_getattr_np=no],[AC_CHECK_FUNCS(pthread_getattr_np)]) set_current_thread_name= AS_IF([test "$ac_cv_func_pthread_setname_np" = yes], [ AC_CACHE_CHECK([arguments of pthread_setname_np], [rb_cv_func_pthread_setname_np_arguments], [rb_cv_func_pthread_setname_np_arguments= # Linux,AIX, (pthread_self(), name) - # NetBSD (pthread_self(), name, \"%s\") + # NetBSD (pthread_self(), \"%s\", name) # Darwin (name) for mac in \ "(pthread_self(), name)" \ - "(pthread_self(), name, \"%s\")" \ + "(pthread_self(), \"%s\", name)" \ "(name)" \ ; do - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include @%:@ifdef HAVE_PTHREAD_NP_H @%:@include @%:@endif @%:@define SET_THREAD_NAME(name) pthread_setname_np${mac} - ], - [if (SET_THREAD_NAME("conftest")) return 1;], + ]], + [[if (SET_THREAD_NAME("conftest")) return 1;]])], [rb_cv_func_pthread_setname_np_arguments="${mac}" break]) done @@ -2445,8 +2692,8 @@ AS_IF([test x"$enable_pthread" = xyes], [ AS_IF([test x"$ac_cv_header_ucontext_h" = xno], [ AC_CACHE_CHECK([if signal.h defines ucontext_t], [rb_cv_ucontext_in_signal_h], - [AC_TRY_COMPILE([@%:@include ], - [size_t size = sizeof(ucontext_t);], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[size_t size = sizeof(ucontext_t);]])], [rb_cv_ucontext_in_signal_h=yes], [rb_cv_ucontext_in_signal_h=no])]) AS_IF([test x"$rb_cv_ucontext_in_signal_h" = xyes], [ AC_DEFINE_UNQUOTED(UCONTEXT_IN_SIGNAL_H, 1) @@ -2454,14 +2701,14 @@ AS_IF([test x"$ac_cv_header_ucontext_h" = xno], [ ]) AS_IF([test x"$ac_cv_header_ucontext_h" = xyes -o x"$rb_cv_ucontext_in_signal_h" = xyes], [ AC_CACHE_CHECK([if mcontext_t is a pointer], [rb_cv_mcontext_t_ptr], - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include @%:@ifdef HAVE_UCONTEXT_H @%:@include @%:@endif mcontext_t test(mcontext_t mc) {return mc+1;} - ], - [test(0);], + ]], + [[test(0);]])], [rb_cv_mcontext_t_ptr=yes], [rb_cv_mcontext_t_ptr=no])]) AS_IF([test x"$rb_cv_mcontext_t_ptr" = xyes], [ AC_DEFINE_UNQUOTED(DEFINE_MCONTEXT_PTR(mc, uc), mcontext_t mc = (uc)->uc_mcontext) @@ -2475,7 +2722,7 @@ AS_IF([test x"$ac_cv_header_ucontext_h" = xyes -o x"$rb_cv_ucontext_in_signal_h" AS_IF([test "$ac_cv_func_fork_works" = "yes" -a "$rb_with_pthread" = "yes"], [ AC_CACHE_CHECK([if fork works with pthread], rb_cv_fork_with_pthread, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -2531,45 +2778,82 @@ main(int argc, char *argv[]) } return EXIT_SUCCESS; -}], +}]])], rb_cv_fork_with_pthread=yes, rb_cv_fork_with_pthread=no, rb_cv_fork_with_pthread=yes)]) test x$rb_cv_fork_with_pthread = xyes || AC_DEFINE(CANNOT_FORK_WITH_PTHREAD) ]) + +AC_CHECK_HEADERS([sys/user.h]) +AS_IF([test "x$ac_cv_func_mmap" = xyes], [ + AC_CACHE_CHECK([whether PAGE_SIZE is compile-time const], rb_cv_const_page_size, + [malloc_headers=`sed -n '/MALLOC_HEADERS_BEGIN/,/MALLOC_HEADERS_END/p' ${srcdir}/gc.c` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$malloc_headers + typedef char conftest_page[PAGE_SIZE]; + ]], [[]])], + [rb_cv_const_page_size=yes], + [rb_cv_const_page_size=no])]) +]) +AS_IF([test "x$rb_cv_const_page_size" = xyes], + [AC_DEFINE(HAVE_CONST_PAGE_SIZE, 1)], + [AC_DEFINE(HAVE_CONST_PAGE_SIZE, 0)] +) + +AS_IF([test "x$ac_cv_func_ioctl" = xyes], [ + AC_CACHE_CHECK([ioctl request type], rb_cv_ioctl_request_type, + [rb_cv_ioctl_request_type=no + dnl corresponding NUM2IOCTLREQ needs to be defined + for type in "unsigned long:ULONG_MAX" int:INT_MAX; do + max=`echo $type | sed 's/.*://'` + type=`echo $type | sed 's/:.*//'` + RUBY_WERROR_FLAG([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + @%:@include + @%:@include + @%:@if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32) + @%:@include + @%:@endif + ]], [[ + $type req = $max; + if (ioctl(0, req)) {/* do nothing*/}; + ]])], + [rb_cv_ioctl_request_type="$type"]) + ]) + test "x$rb_cv_ioctl_request_type" = xno || break + done]) + AS_CASE(["$rb_cv_ioctl_request_type"], [no|int], [], + ["unsigned long"], [ + AC_DEFINE_UNQUOTED(IOCTL_REQ_TYPE, [$rb_cv_ioctl_request_type]) + AC_DEFINE_UNQUOTED(NUM2IOCTLREQ(num), [NUM2ULONG(num)]) + ]) +]) + } : "runtime section" && { dnl wheather use dln_a_out or not AC_ARG_WITH(dln-a-out, - AS_HELP_STRING([--with-dln-a-out], [use dln_a_out if possible]), + AS_HELP_STRING([--with-dln-a-out], [dln_a_out is deprecated]), [ AS_CASE([$withval], [yes], [ - AS_IF([test "$enable_shared" = yes], [ - AC_MSG_ERROR(dln_a_out can not make shared library) - ]) - with_dln_a_out=yes], - [ - with_dln_a_out=no])], [with_dln_a_out=no]) + AC_MSG_ERROR(dln_a_out no longer supported) + ]) +]) AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf, -[AC_TRY_LINK([],[], [ +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[ AS_CASE(["`head -1 conftest$EXEEXT | tr -dc '\177ELF' | tr '\177' .`"], [.ELF*], [rb_cv_binary_elf=yes], [rb_cv_binary_elf=no])], rb_cv_binary_elf=no)]) AS_IF([test "$rb_cv_binary_elf" = yes], [ AC_DEFINE(USE_ELF) - AS_IF([test "$with_dln_a_out" = yes], [ - AC_MSG_ERROR(dln_a_out does not work with ELF) - ]) AC_CHECK_HEADERS([elf.h elf_abi.h]) AS_IF([test $ac_cv_header_elf_h = yes -o $ac_cv_header_elf_abi_h = yes], [ AC_LIBOBJ([addr2line]) - AS_IF([test "x$compress_debug_sections" = xzlib], [ - AC_CHECK_LIB([z], [uncompress]) - ]) + AC_CHECK_LIB([z], [uncompress]) ]) ]) @@ -2581,20 +2865,24 @@ AS_IF([test "$ac_cv_header_mach_o_loader_h" = yes], [ AS_CASE(["$target_os"], [linux* | gnu* | k*bsd*-gnu | bsdi* | kopensolaris*-gnu], [ AS_IF([test "$rb_cv_binary_elf" = no], [ - with_dln_a_out=yes + AC_MSG_ERROR(Not ELF) ], [ LDFLAGS="$LDFLAGS -rdynamic" ])]) LIBEXT=a +AC_ARG_WITH(mjit-tabs, + AS_HELP_STRING([--without-mjit-tabs], [expand tabs in mjit header]), + [AS_IF([test $withval = no], [MJIT_TABS=false])]) +AC_SUBST(MJIT_TABS)dnl AC_SUBST(DLDFLAGS)dnl AC_SUBST(ARCH_FLAG)dnl AC_SUBST(MJIT_HEADER_FLAGS)dnl AC_SUBST(MJIT_HEADER_INSTALL_DIR)dnl AC_SUBST(MJIT_CC)dnl -AS_IF([test "$GCC" = "yes"], [ - AS_CASE(["$target_os"],[aix*],[mjit_std_cflag="-std=gnu99"]) -]) +AS_CASE(["$GCC:$target_os"], + [yes:aix*], [mjit_std_cflag="-std=gnu99"], + [mjit_std_cflag=]) AC_SUBST(MJIT_CFLAGS, [${MJIT_CFLAGS-"-w ${mjit_std_cflag} ${orig_cflags}"}])dnl AC_SUBST(MJIT_OPTFLAGS, [${MJIT_OPTFLAGS-'$(optflags)'}])dnl AC_SUBST(MJIT_DEBUGFLAGS, [${MJIT_DEBUGFLAGS-'$(debugflags)'}])dnl @@ -2605,13 +2893,12 @@ AC_SUBST(CCDLFLAGS)dnl AC_SUBST(LDSHARED)dnl AC_SUBST(LDSHAREDXX)dnl AC_SUBST(DLEXT)dnl -AC_SUBST(DLEXT2)dnl AC_SUBST(LIBEXT)dnl AC_SUBST(ASMEXT, S)dnl STATIC= -AS_IF([test "$with_dln_a_out" != yes], [ +: "dlopen" && { rb_cv_dlopen=unknown AC_MSG_CHECKING(whether OS depend dynamic link works) AS_IF([test "$GCC" = yes], [ @@ -2625,7 +2912,7 @@ AS_IF([test "$with_dln_a_out" != yes], [ # mkmf.rb's have_header() to fail if the desired resource happens to be # installed in the /usr/local tree. RUBY_APPEND_OPTION(CCDLFLAGS, -fno-common)], - [bsdi*|cygwin*|mingw*|aix*|interix*], [ ], + [bsdi*|cygwin*|msys*|mingw*|aix*|interix*], [ ], [ RUBY_APPEND_OPTION(CCDLFLAGS, -fPIC)]) ], [ @@ -2636,8 +2923,9 @@ AS_IF([test "$with_dln_a_out" != yes], [ [esix*|uxpds*], [CCDLFLAGS="$CCDLFLAGS -KPIC"], [: ${CCDLFLAGS=""}]) ]) +} - +: "rpath" && { AC_ARG_ENABLE(rpath, AS_HELP_STRING([--enable-rpath], [embed run path into extension libraries. enabled by default on ELF platforms]), @@ -2729,7 +3017,7 @@ AS_IF([test "$with_dln_a_out" != yes], [ : ${LDSHARED='$(LD) -Bshareable -x'} LDFLAGS="$LDFLAGS -L/lib -L/usr/lib -L/usr/local/lib" rb_cv_dlopen=yes], - [cygwin*|mingw*], [ + [cygwin*|msys*|mingw*], [ : ${LDSHARED='$(CC) -shared'} XLDFLAGS="$XLDFLAGS -Wl,--stack,0x00200000,--enable-auto-import" DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-image-base,--enable-auto-import" @@ -2763,7 +3051,8 @@ AS_IF([test "$with_dln_a_out" != yes], [ RPATHFLAG=" ${rpathflag}%1\$-s" ]) ]) -]) +} + AS_IF([test "${LDSHAREDXX}" = ""], [ AS_CASE(["${LDSHARED}"], [*'$(CC)'*], [ @@ -2829,7 +3118,7 @@ AC_CHECK_FUNCS(backtrace) AS_IF([test "x$ac_cv_func_backtrace" = xyes], [ AC_CACHE_CHECK(for broken backtrace, rb_cv_broken_backtrace, - [AC_TRY_RUN([ + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -2838,6 +3127,7 @@ AS_IF([test "x$ac_cv_func_backtrace" = xyes], [ #include #include +]`grep '^@%:@ *define *RUBY_SIGALTSTACK_SIZE' ${srcdir}/signal.c`[ #define TRACE_SIZE 256 void sigsegv(int signum, siginfo_t *info, void *ctx){ @@ -2857,12 +3147,12 @@ main(void) stack_t ss; struct sigaction sa; - ss.ss_sp = malloc(SIGSTKSZ); + ss.ss_sp = malloc(RUBY_SIGALTSTACK_SIZE); if (ss.ss_sp == NULL) { fprintf(stderr, "cannot allocate memory for sigaltstack\n"); return EXIT_FAILURE; } - ss.ss_size = SIGSTKSZ; + ss.ss_size = RUBY_SIGALTSTACK_SIZE; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) == -1) { fprintf(stderr, "sigaltstack failed\n"); @@ -2877,7 +3167,7 @@ main(void) a[0] = 1; return EXIT_SUCCESS; } -], +]])], rb_cv_broken_backtrace=no, rb_cv_broken_backtrace=yes, rb_cv_broken_backtrace=no)]) @@ -2892,49 +3182,23 @@ AC_ARG_WITH(valgrind, AS_IF([test x$with_valgrind != xno], [AC_CHECK_HEADERS(valgrind/memcheck.h)]) -dln_a_out_works=no -AS_IF([test "$ac_cv_header_a_out_h" = yes], [ - AS_IF([test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown], [ - cat confdefs.h > config.h - AC_CACHE_CHECK(whether matz's dln works, rb_cv_dln_a_out, - [AC_TRY_COMPILE([ -#define USE_DLN_A_OUT -#include "dln.c" -], - [], - rb_cv_dln_a_out=yes, - rb_cv_dln_a_out=no)]) - AS_IF([test "$rb_cv_dln_a_out" = yes], [ - dln_a_out_works=yes - AC_DEFINE(USE_DLN_A_OUT) - ]) - ]) -]) - -AS_IF([test "$dln_a_out_works" = yes], [ - AS_IF([test "$GCC" = yes], [ - STATIC=-static - ], [ - STATIC=-Bstatic - ]) - DLEXT=so - CCDLFLAGS= -], [ +: "dlext & soext" && { AS_CASE(["$target_os"], [hpux*], [ DLEXT=sl], [darwin*], [ SOEXT=dylib DLEXT=bundle], - [cygwin*|mingw*|*djgpp*], [ + [cygwin*|msys*|mingw*|*djgpp*], [ LOAD_RELATIVE=1 SOEXT=dll DLEXT=so], [ 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], [ LOAD_RELATIVE=1 @@ -2948,29 +3212,31 @@ AS_IF([test x"$LOAD_RELATIVE" = x1], [ len=2 # .rb n=`expr "$DLEXT" : '.*'`; test "$n" -gt "$len" && len=$n -n=`expr "$DLEXT2" : '.*'`; test "$n" -gt "$len" && len=$n AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`) test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT") -test ".$DLEXT2" = "." || AC_DEFINE_UNQUOTED(DLEXT2, ".$DLEXT2") AC_SUBST(DLEXT) -AS_IF([test "$with_dln_a_out" = yes], [ - STRIP=true -], [ - AC_CHECK_TOOL(STRIP, strip, :)dnl -]) - -AS_CASE(["$target_os"], - [linux* | gnu* | k*bsd*-gnu | kopensolaris*-gnu], [ - STRIP="$STRIP -S -x"], - [darwin*], [ - STRIP="$STRIP -A -n"]) +: "strip" && { + AC_MSG_CHECKING([for $STRIP flags]) + AC_LINK_IFELSE([AC_LANG_PROGRAM], [AS_IF( + ["${STRIP}" -A -n conftest$ac_exeext 2>/dev/null], [ + AC_MSG_RESULT([-A -n]) + STRIP="${STRIP} -A -n" + ], + ["${STRIP}" -S -x conftest$ac_exeext 2>/dev/null], [ + AC_MSG_RESULT([-S -x]) + STRIP="${STRIP} -S -x" + ], [ + AC_MSG_RESULT([none needed]) + ]) + ]) +} AC_ARG_WITH(ext, - AC_HELP_STRING([--with-ext=EXTS], + AS_HELP_STRING([--with-ext=EXTS], [pass to --with-ext option of extmk.rb])) AC_ARG_WITH(out-ext, - AC_HELP_STRING([--with-out-ext=EXTS], + AS_HELP_STRING([--with-out-ext=EXTS], [pass to --without-ext option of extmk.rb])) EXTSTATIC= AC_SUBST(EXTSTATIC)dnl @@ -3031,7 +3297,7 @@ AS_IF([test x"${exec_prefix}" != xNONE], [ RUBY_EXEC_PREFIX=$ac_default_prefix ]) pat=`echo "${RUBY_EXEC_PREFIX}" | tr -c '\012' .`'\(.*\)' -for var in bindir libdir rubylibprefix; do +for var in bindir includedir libdir rubylibprefix; do eval val='"$'$var'"' AS_CASE(["$val"], ["${RUBY_EXEC_PREFIX}"*], [val='${exec_prefix}'"`expr \"$val\" : \"$pat\"`"]) eval $var='"$val"' @@ -3058,7 +3324,7 @@ AS_IF([test x"$cross_compiling" = xyes], [ MINIRUBY='./miniruby$(EXEEXT) -I$(srcdir)/lib -I.' MINIRUBY="$MINIRUBY"' -I$(EXTOUT)/common' PREP='miniruby$(EXEEXT)' - RUNRUBY_COMMAND='$(MINIRUBY) $(srcdir)/tool/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)' + RUNRUBY_COMMAND='$(MINIRUBY) $(tooldir)/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)' RUNRUBY='$(RUNRUBY_COMMAND) --' XRUBY='$(RUNRUBY)' AS_CASE(["$HAVE_BASERUBY:$build_os"], [no:*|*:mingw*], [BOOTSTRAPRUBY='$(MINIRUBY)']) @@ -3084,11 +3350,11 @@ LIBRUBYARG='$(LIBRUBYARG_STATIC)' SOLIBS='$(MAINLIBS)' AS_CASE(["$target_os"], - [cygwin*|mingw*|haiku*|darwin*], [ + [cygwin*|msys*|mingw*|haiku*|darwin*], [ : ${DLDLIBS=""} ], [ - DLDLIBS="$DLDLIBS -lc" + DLDLIBS="${DLDLIBS:+$DLDLIBS }-lc" ]) AC_ARG_ENABLE(multiarch, @@ -3154,6 +3420,17 @@ AS_CASE("$enable_shared", [yes], [ AC_DEFINE_UNQUOTED(LIBDIR_BASENAME, ["${libdir_basename}"]) libdir_basename="${libdir_basename}"${multiarch+'/${arch}'} + # Debian bullseye reportedly has its ld(1) patched, which breaks + # --enable-shared --with-jemalloc combination. We might have to deal with + # the ld(1) change sooner or later, but in the meantime let us force it + # the old way. + # + # See https://github.com/ruby/ruby/pull/4627 + RUBY_TRY_LDFLAGS([${linker_flag}--no-as-needed], [no_as_needed=yes], [no_as_needed=no]) + AS_IF([test "$no_as_needed" = yes], [ + RUBY_APPEND_OPTIONS(LDFLAGS, [${linker_flag}--no-as-needed]) + ]) + AS_CASE(["$target_os"], [freebsd*|dragonfly*], [], [ @@ -3184,6 +3461,10 @@ AS_CASE("$enable_shared", [yes], [ AS_IF([test "$rb_cv_binary_elf" != "yes" ], [ LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)" LIBRUBY_ALIASES='' + ], [test "$load_relative" = yes], [ + libprefix="'\$\$ORIGIN/../${libdir_basename}'" + LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}" + LIBRUBY_RELATIVE=yes ]) ], [netbsd*], [ @@ -3204,7 +3485,13 @@ AS_CASE("$enable_shared", [yes], [ LIBRUBY_SONAME='lib$(RUBY_SO_NAME).$(SOEXT).$(RUBY_PROGRAM_VERSION)' LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)' RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)']) - XLDFLAGS="$XLDFLAGS "'-R${libdir}' + AS_IF([test "$load_relative" = yes], [ + libprefix="'\$\$ORIGIN/../${libdir_basename}'" + LIBRUBY_RPATHFLAGS="-R${libprefix}" + LIBRUBY_RELATIVE=yes + ], [ + LIBRUBY_RPATHFLAGS='-R${libdir}' + ]) ], [hpux*], [ XLDFLAGS="$XLDFLAGS "'-Wl,+s,+b,$(libdir)' @@ -3236,7 +3523,7 @@ AS_CASE("$enable_shared", [yes], [ [interix*], [ LIBRUBYARG_SHARED='-L. -L${libdir} -l$(RUBY_SO_NAME)' ], - [mingw*|cygwin*|mswin*], [ + [cygwin*|msys*|mingw*|mswin*], [ LIBRUBY_RELATIVE=yes ]) ], [ @@ -3313,6 +3600,9 @@ AS_CASE(["${enable_dtrace}"], ], [ rb_cv_dtrace_available=no ]) +AS_CASE(["$target_os"],[freebsd*],[ + rb_cv_dtrace_available=no + ]) AS_IF([test "${enable_dtrace}" = yes], [dnl AS_IF([test -z "$DTRACE"], [dnl AC_MSG_ERROR([dtrace(1) is missing]) @@ -3419,17 +3709,17 @@ AC_SUBST(MJIT_SUPPORT) AC_ARG_ENABLE(install-static-library, AS_HELP_STRING([--disable-install-static-library], [do not install static ruby library]), - [INSTALL_STATIC_LIBRARY=$enableval], + [INSTALL_STATIC_LIBRARY=$enableval + AS_IF([test x"$enable_shared" = xno -a x"$INSTALL_STATIC_LIBRARY" = xno], + [AC_MSG_ERROR([must install either static or shared library])], + [])], AS_IF([test x"$enable_shared" = xyes], [INSTALL_STATIC_LIBRARY=no], [INSTALL_STATIC_LIBRARY=yes])) AC_SUBST(INSTALL_STATIC_LIBRARY) -AS_IF([test "$rb_with_pthread" = "yes"], [ - THREAD_MODEL=pthread -]) AC_CACHE_CHECK([for prefix of external symbols], rb_cv_symbol_prefix, [ - AC_TRY_COMPILE([extern void conftest_external(void) {}], [], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[extern void conftest_external(void) {}]], [[]])],[ rb_cv_symbol_prefix=`$NM conftest.$ac_objext | sed -n ['/.*T[ ]\([^ ]*\)conftest_external.*/!d;s//\1/p;q']` ], @@ -3440,7 +3730,7 @@ SYMBOL_PREFIX="$rb_cv_symbol_prefix" test "x$SYMBOL_PREFIX" = xNONE && SYMBOL_PREFIX='' DLNOBJ=dln.o AC_ARG_ENABLE(dln, - AC_HELP_STRING([--disable-dln], [disable dynamic link feature]), + AS_HELP_STRING([--disable-dln], [disable dynamic link feature]), [test "$enableval" = yes || DLNOBJ=dmydln.o]) AC_SUBST(DLNOBJ) MINIDLNOBJ=dmydln.o @@ -3455,14 +3745,15 @@ AS_CASE(["$target_os"], RUBY_APPEND_OPTION(CFLAGS, -pipe) AC_COMPILE_IFELSE([ AC_LANG_BOOL_COMPILE_TRY([@%:@include ], - [MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7])], + [MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 && + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10])], [dnl RUBY_APPEND_OPTION(XLDFLAGS, [-framework Security]) RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework Security]) ]dnl ) - RUBY_APPEND_OPTION(XLDFLAGS, [-framework Foundation]) - RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework Foundation]) + RUBY_APPEND_OPTION(XLDFLAGS, [-framework CoreFoundation]) + RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework CoreFoundation]) ], [osf*], [ AS_IF([test "$GCC" != "yes" ], [ @@ -3479,7 +3770,7 @@ AS_CASE(["$target_os"], CFLAGS="$CFLAGS -std" ]) ], - [cygwin*|mingw*], [ + [cygwin*|msys*|mingw*], [ LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)' AS_CASE(["$target_os"], [cygwin*], [ @@ -3494,13 +3785,12 @@ AS_CASE(["$target_os"], LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' $(RUBYDEF)' ]) EXPORT_PREFIX=' ' - DLDFLAGS="${DLDFLAGS}"' $(DEFFILE)' + EXTDLDFLAGS='$(DEFFILE)' AC_LIBOBJ([win32/win32]) AC_LIBOBJ([win32/file]) COMMON_LIBS=m # COMMON_MACROS="WIN32_LEAN_AND_MEAN=" COMMON_HEADERS="winsock2.h windows.h" - THREAD_MODEL=win32 PLATFORM_DIR=win32 ]) LIBRUBY_ALIASES='' @@ -3522,11 +3812,7 @@ AS_CASE(["$target_os"], MINIOBJS="$MINIDLNOBJ" -AS_CASE(["$THREAD_MODEL"], -[pthread], [AC_CHECK_HEADERS(pthread.h)], -[win32], [], -[""], [AC_MSG_ERROR(thread model is missing)], - [AC_MSG_ERROR(unknown thread model $THREAD_MODEL)]) +RUBY_THREAD AC_ARG_ENABLE(debug-env, AS_HELP_STRING([--enable-debug-env], [enable RUBY_DEBUG environment variable]), @@ -3572,13 +3858,12 @@ AS_IF([test "${universal_binary-no}" = yes ], [ AC_CACHE_CHECK([for architecture macros], rb_cv_architecture_macros, [ mv confdefs.h confdefs1.h : > confdefs.h - AC_TRY_COMPILE([@%:@if defined __`echo ${universal_archnames} | + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@if defined __`echo ${universal_archnames} | sed 's/=[^ ]*//g;s/ /__ || defined __/g'`__ @%:@else @%:@error >>>>>><<<<<< -@%:@endif], [], -[ +@%:@endif]], [[]])],[ rb_cv_architecture_macros=yes mv -f confdefs1.h confdefs.h ], [ @@ -3591,16 +3876,17 @@ AS_IF([test "${universal_binary-no}" = yes ], [ CFLAGS="$new_cflags -arch $archs" archs="__${archs}__" AC_MSG_CHECKING([for macro ${archs} on ${cpu}]) - AC_TRY_COMPILE([@%:@ifndef ${archs} + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@ifndef ${archs} @%:@error -@%:@endif], [], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) +@%:@endif]], [[]])], + [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) done mv -f confdefs1.h confdefs.h AC_MSG_ERROR([failed]) ])]) AC_CACHE_CHECK(whether __ARCHITECTURE__ is available, rb_cv_architecture_available, - AC_TRY_COMPILE([@%:@include - const char arch[[]] = __ARCHITECTURE__;], [puts(arch);], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include + const char arch[[]] = __ARCHITECTURE__;]], [[puts(arch);]])], [rb_cv_architecture_available=yes], [rb_cv_architecture_available=no])) ]) @@ -3686,7 +3972,7 @@ test "$program_suffix" != NONE && RUBY_INSTALL_NAME="${ri_prefix}"'$(RUBY_BASE_NAME)'"${ri_suffix}" AS_CASE(["$target_os"], - [cygwin*|mingw*], [ + [cygwin*|msys*|mingw*], [ RUBYW_INSTALL_NAME="${ri_prefix}"'$(RUBYW_BASE_NAME)'"${ri_suffix}" rubyw_install_name='$(RUBYW_INSTALL_NAME)' ]) @@ -3813,7 +4099,11 @@ AS_IF([test "${universal_binary-no}" = yes ], [ AC_DEFINE_UNQUOTED(RUBY_ARCH, "universal-" RUBY_PLATFORM_OS) AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "universal." RUBY_PLATFORM_CPU "-" RUBY_PLATFORM_OS) ], [ - arch="${target_cpu}-${target_os}" + AS_IF([test "${target_os}-${rb_cv_msvcrt}" = "mingw32-ucrt" ], [ + arch="${target_cpu}-mingw-ucrt" + ], [ + arch="${target_cpu}-${target_os}" + ]) AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "$arch") ]) @@ -3917,7 +4207,7 @@ guard=INCLUDE_RUBY_CONFIG_H } | tr -d '\015' | ( AS_IF([test "x$CONFIGURE_TTY" = xyes], [color=--color], [color=]) - exec ${srcdir}/tool/ifchange $color "${config_h}" - + exec ${SHELL} ${tooldir}/ifchange $color "${config_h}" - ) >&AS_MESSAGE_FD || AC_MSG_ERROR([failed to create ${config_h}]) tr -d '\015' < largefile.h > confdefs.h rm largefile.h @@ -3970,7 +4260,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [ VCS='echo cannot' ]) AS_CASE("$VCS", - ['$(GIT)'|git], [VCSUP='$(VCS) pull $(GITPULLOPTIONS)'], + ['$(GIT)'|git], [VCSUP='$(VCS) pull --rebase $(GITPULLOPTIONS)'], [VCSUP='$(VCS)']) sed -n \ -e '[/^@%:@define \(RUBY_RELEASE_[A-Z]*\) \([0-9][0-9]*\)/]{' \ @@ -4000,10 +4290,10 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [ echo 'ruby: $(PROGRAM);' >> $tmpmk test "$tmpmk" = "$tmpgmk" || rm -f "$tmpgmk" ]) && mv -f $tmpmk Makefile], -[EXEEXT='$EXEEXT' gnumake='$gnumake' GIT='$GIT']) +[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT']) AC_ARG_WITH([ruby-pc], - AC_HELP_STRING([--with-ruby-pc=FILENAME], [pc file basename]), + AS_HELP_STRING([--with-ruby-pc=FILENAME], [pc file basename]), [ruby_pc="$withval"], [ruby_pc="${RUBY_BASE_NAME}-${MAJOR}.${MINOR}.pc"]) AC_SUBST(ruby_pc) @@ -4014,21 +4304,6 @@ AC_ARG_WITH(destdir, [DESTDIR="$withval"]) AC_SUBST(DESTDIR) -AC_CONFIG_FILES($ruby_pc:template/ruby.pc.in, - [ - AS_IF([sed ['s/\$(\([A-Za-z_][A-Za-z0-9_]*\))/${\1}/g;s/@[A-Za-z_][A-Za-z0-9_]*@//'] $ruby_pc > ruby.tmp.pc && - { - test -z "$PKG_CONFIG" || - PKG_CONFIG_PATH=. $PKG_CONFIG --print-errors ruby.tmp - }], - [ - mv -f ruby.tmp.pc $ruby_pc - ], [ - exit 1 - ]) - ], - [ruby_pc='$ruby_pc' PKG_CONFIG='$PKG_CONFIG']) - AC_OUTPUT } } @@ -4067,7 +4342,7 @@ config_summary "vendor path" "$vendordir" config_summary "target OS" "$target_os" config_summary "compiler" "$CC" config_summary "with pthread" "$enable_pthread" -config_summary "with coroutine" "$rb_cv_coroutine" +config_summary "with coroutine" "$coroutine_type" config_summary "enable shared libs" "$ENABLE_SHARED" config_summary "dynamic library ext" "$DLEXT" config_summary "CFLAGS" "$cflags" diff --git a/ruby/constant.h b/ruby/constant.h index 3f1418df1..e0d36909e 100644 --- a/ruby/constant.h +++ b/ruby/constant.h @@ -1,3 +1,5 @@ +#ifndef CONSTANT_H +#define CONSTANT_H /********************************************************************** constant.h - @@ -8,8 +10,8 @@ Copyright (C) 2009 Yusuke Endoh **********************************************************************/ -#ifndef CONSTANT_H -#define CONSTANT_H +#include "ruby/ruby.h" +#include "id_table.h" typedef enum { CONST_DEPRECATED = 0x100, @@ -39,12 +41,15 @@ VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj); VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj); VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj); void rb_free_const_table(struct rb_id_table *tbl); +VALUE rb_const_source_location(VALUE, ID); + +MJIT_SYMBOL_EXPORT_BEGIN +int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag); +rb_const_entry_t *rb_const_lookup(VALUE klass, ID id); VALUE rb_public_const_get_at(VALUE klass, ID id); VALUE rb_public_const_get_from(VALUE klass, ID id); int rb_public_const_defined_from(VALUE klass, ID id); -rb_const_entry_t *rb_const_lookup(VALUE klass, ID id); -int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag); -VALUE rb_const_source_location(VALUE, ID); VALUE rb_const_source_location_at(VALUE, ID); +MJIT_SYMBOL_EXPORT_END #endif /* CONSTANT_H */ diff --git a/ruby/cont.c b/ruby/cont.c index a8321abcc..2d33ff402 100644 --- a/ruby/cont.c +++ b/ruby/cont.c @@ -9,19 +9,34 @@ **********************************************************************/ -#include "internal.h" -#include "vm_core.h" -#include "gc.h" -#include "eval_intern.h" -#include "mjit.h" - -#include COROUTINE_H +#include "ruby/internal/config.h" #ifndef _WIN32 #include #include #endif +// On Solaris, madvise() is NOT declared for SUS (XPG4v2) or later, +// but MADV_* macros are defined when __EXTENSIONS__ is defined. +#ifdef NEED_MADVICE_PROTOTYPE_USING_CADDR_T +#include +extern int madvise(caddr_t, size_t, int); +#endif + +#include COROUTINE_H + +#include "eval_intern.h" +#include "gc.h" +#include "internal.h" +#include "internal/cont.h" +#include "internal/proc.h" +#include "internal/warnings.h" +#include "ruby/fiber/scheduler.h" +#include "mjit.h" +#include "vm_core.h" +#include "id_table.h" +#include "ractor_core.h" + static const int DEBUG = 0; #define RB_PAGE_SIZE (pagesize) @@ -227,12 +242,12 @@ struct rb_fiber_struct { rb_context_t cont; VALUE first_proc; struct rb_fiber_struct *prev; + struct rb_fiber_struct *resuming_fiber; + BITFIELD(enum fiber_status, status, 2); - /* If a fiber invokes by "transfer", - * then this fiber can't be invoked by "resume" any more after that. - * You shouldn't mix "transfer" and "resume". - */ - unsigned int transferred : 1; + /* Whether the fiber is allowed to implicitly yield. */ + unsigned int yielding : 1; + unsigned int blocking : 1; struct coroutine_context context; struct fiber_pool_stack stack; @@ -240,6 +255,8 @@ struct rb_fiber_struct { static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0}; +static ID fiber_initialize_keywords[2] = {0}; + /* * FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL * if MAP_STACK is passed. @@ -324,6 +341,7 @@ fiber_pool_vacancy_push(struct fiber_pool_vacancy * vacancy, struct fiber_pool_v #ifdef FIBER_POOL_ALLOCATION_FREE if (head) { head->previous = vacancy; + vacancy->previous = NULL; } #endif @@ -422,6 +440,12 @@ fiber_pool_allocate_memory(size_t * count, size_t stride) *count = (*count) >> 1; } else { +#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); +#endif return base; } #endif @@ -544,7 +568,7 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation) VM_ASSERT(allocation->used == 0); - if (DEBUG) fprintf(stderr, "fiber_pool_allocation_free: %p base=%p count=%"PRIuSIZE"\n", allocation, allocation->base, allocation->count); + if (DEBUG) fprintf(stderr, "fiber_pool_allocation_free: %p base=%p count=%"PRIuSIZE"\n", (void*)allocation, allocation->base, allocation->count); size_t i; for (i = 0; i < allocation->count; i += 1) { @@ -582,7 +606,8 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation) // Acquire a stack from the given fiber pool. If none are available, allocate more. static struct fiber_pool_stack -fiber_pool_stack_acquire(struct fiber_pool * fiber_pool) { +fiber_pool_stack_acquire(struct fiber_pool * fiber_pool) +{ struct fiber_pool_vacancy * 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); @@ -634,8 +659,14 @@ fiber_pool_stack_free(struct fiber_pool_stack * stack) #if VM_CHECK_MODE > 0 && defined(MADV_DONTNEED) // This immediately discards the pages and the memory is reset to zero. madvise(base, size, MADV_DONTNEED); +#elif defined(POSIX_MADV_DONTNEED) + posix_madvise(base, size, POSIX_MADV_DONTNEED); #elif defined(MADV_FREE_REUSABLE) - madvise(base, size, MADV_FREE_REUSABLE); + // Acknowledge the kernel down to the task info api we make this + // page reusable for future use. + // As for MADV_FREE_REUSE below we ensure in the rare occasions the task was not + // completed at the time of the call to re-iterate. + while (madvise(base, size, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN); #elif defined(MADV_FREE) madvise(base, size, MADV_FREE); #elif defined(MADV_DONTNEED) @@ -687,10 +718,49 @@ fiber_pool_stack_release(struct fiber_pool_stack * stack) #endif } +static inline void +ec_switch(rb_thread_t *th, rb_fiber_t *fiber) +{ + rb_execution_context_t *ec = &fiber->cont.saved_ec; + rb_ractor_set_current_ec(th->ractor, th->ec = ec); + // ruby_current_execution_context_ptr = th->ec = ec; + + /* + * timer-thread may set trap interrupt on previous th->ec at any time; + * ensure we do not delay (or lose) the trap interrupt handling. + */ + if (th->vm->ractor.main_thread == th && + rb_signal_buff_size() > 0) { + RUBY_VM_SET_TRAP_INTERRUPT(ec); + } + + VM_ASSERT(ec->fiber_ptr->cont.self == 0 || ec->vm_stack != NULL); +} + +static inline void +fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber) +{ + ec_switch(th, fiber); + VM_ASSERT(th->ec->fiber_ptr == fiber); +} + static COROUTINE fiber_entry(struct coroutine_context * from, struct coroutine_context * to) { - rb_fiber_start(); + rb_fiber_t *fiber = to->argument; + rb_thread_t *thread = fiber->cont.saved_ec.thread_ptr; + +#ifdef COROUTINE_PTHREAD_CONTEXT + ruby_thread_set_native(thread); +#endif + + fiber_restore_thread(thread, fiber); + + rb_fiber_start(fiber); + +#ifndef COROUTINE_PTHREAD_CONTEXT + VM_UNREACHABLE(fiber_entry); +#endif } // Initialize a fiber's coroutine's machine stack and vm stack. @@ -707,22 +777,13 @@ fiber_initialize_coroutine(rb_fiber_t *fiber, size_t * vm_stack_size) vm_stack = fiber_pool_stack_alloca(&fiber->stack, fiber_pool->vm_stack_size); *vm_stack_size = fiber_pool->vm_stack_size; -#ifdef COROUTINE_PRIVATE_STACK - coroutine_initialize(&fiber->context, fiber_entry, fiber_pool_stack_base(&fiber->stack), fiber->stack.available, sec->machine.stack_start); - // The stack for this execution context is still the main machine stack, so don't adjust it. - // If this is not managed correctly, you will fail in `rb_ec_stack_check`. - - // We limit the machine stack usage to the fiber stack size. - if (sec->machine.stack_maxsize > fiber->stack.available) { - sec->machine.stack_maxsize = fiber->stack.available; - } -#else coroutine_initialize(&fiber->context, fiber_entry, fiber_pool_stack_base(&fiber->stack), fiber->stack.available); // The stack for this execution context is the one we allocated: sec->machine.stack_start = fiber->stack.current; sec->machine.stack_maxsize = fiber->stack.available; -#endif + + fiber->context.argument = (void*)fiber; return vm_stack; } @@ -791,24 +852,6 @@ fiber_status_set(rb_fiber_t *fiber, enum fiber_status s) fiber->status = s; } -static inline void -ec_switch(rb_thread_t *th, rb_fiber_t *fiber) -{ - rb_execution_context_t *ec = &fiber->cont.saved_ec; - - ruby_current_execution_context_ptr = th->ec = ec; - - /* - * timer-thread may set trap interrupt on previous th->ec at any time; - * ensure we do not delay (or lose) the trap interrupt handling. - */ - if (th->vm->main_thread == th && rb_signal_buff_size() > 0) { - RUBY_VM_SET_TRAP_INTERRUPT(ec); - } - - VM_ASSERT(ec->fiber_ptr->cont.self == 0 || ec->vm_stack != NULL); -} - static rb_context_t * cont_ptr(VALUE obj) { @@ -836,6 +879,12 @@ NOINLINE(static VALUE cont_capture(volatile int *volatile stat)); if (!(th)->ec->tag) rb_raise(rb_eThreadError, "not running thread"); \ } while (0) +rb_thread_t* +rb_fiber_threadptr(const rb_fiber_t *fiber) +{ + return fiber->cont.saved_ec.thread_ptr; +} + static VALUE cont_thread_value(const rb_context_t *cont) { @@ -898,11 +947,13 @@ cont_mark(void *ptr) RUBY_MARK_LEAVE("cont"); } +#if 0 static int fiber_is_root_p(const rb_fiber_t *fiber) { return fiber == fiber->cont.saved_ec.thread_ptr->root_fiber; } +#endif static void cont_free(void *ptr) @@ -919,14 +970,13 @@ cont_free(void *ptr) else { rb_fiber_t *fiber = (rb_fiber_t*)cont; coroutine_destroy(&fiber->context); - if (!fiber_is_root_p(fiber)) { - fiber_stack_release(fiber); - } + fiber_stack_release(fiber); } RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr); - if (mjit_enabled && cont->mjit_cont != NULL) { + if (mjit_enabled) { + VM_ASSERT(cont->mjit_cont != NULL); mjit_cont_free(cont->mjit_cont); } /* free rb_cont_t or rb_fiber_t */ @@ -1009,10 +1059,10 @@ fiber_free(void *ptr) rb_fiber_t *fiber = ptr; RUBY_FREE_ENTER("fiber"); - //if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base); + if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", (void *)fiber, fiber->stack.base); if (fiber->cont.saved_ec.local_storage) { - st_free_table(fiber->cont.saved_ec.local_storage); + rb_id_table_free(fiber->cont.saved_ec.local_storage); } cont_free(&fiber->cont); @@ -1031,7 +1081,7 @@ fiber_memsize(const void *ptr) * vm.c::thread_memsize already counts th->ec->local_storage */ if (saved_ec->local_storage && fiber != th->root_fiber) { - size += st_memsize(saved_ec->local_storage); + size += rb_id_table_memsize(saved_ec->local_storage); } size += cont_memsize(&fiber->cont); return size; @@ -1040,12 +1090,7 @@ fiber_memsize(const void *ptr) VALUE rb_obj_is_fiber(VALUE obj) { - if (rb_typeddata_is_kind_of(obj, &fiber_data_type)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_typeddata_is_kind_of(obj, &fiber_data_type)); } static void @@ -1131,11 +1176,22 @@ cont_new(VALUE klass) return cont; } +VALUE +rb_fiberptr_self(struct rb_fiber_struct *fiber) +{ + return fiber->cont.self; +} + +unsigned int +rb_fiberptr_blocking(struct rb_fiber_struct *fiber) +{ + return fiber->blocking; +} + +// This is used for root_fiber because other fibers call cont_init_mjit_cont through cont_new. void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber) { - // Currently this function is meant for root_fiber. Others go through cont_new. - // XXX: Is this mjit_cont `mjit_cont_free`d? cont_init_mjit_cont(&fiber->cont); } @@ -1236,13 +1292,6 @@ cont_capture(volatile int *volatile stat) } COMPILER_WARNING_POP -static inline void -fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber) -{ - ec_switch(th, fiber); - VM_ASSERT(th->ec->fiber_ptr == fiber); -} - static inline void cont_restore_thread(rb_context_t *cont) { @@ -1285,7 +1334,6 @@ cont_restore_thread(rb_context_t *cont) th->ec->cfp = sec->cfp; th->ec->raised_flag = sec->raised_flag; th->ec->tag = sec->tag; - th->ec->protect_tag = sec->protect_tag; th->ec->root_lep = sec->root_lep; th->ec->root_svar = sec->root_svar; th->ec->ensure_list = sec->ensure_list; @@ -1326,16 +1374,20 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber) /* old_fiber->machine.stack_end should be NULL */ old_fiber->cont.saved_ec.machine.stack_end = NULL; - /* restore thread context */ - fiber_restore_thread(th, new_fiber); - - // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] -> %p[%p]\n", old_fiber, old_fiber->stack.base, new_fiber, new_fiber->stack.base); + // 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); /* swap machine context */ - coroutine_transfer(&old_fiber->context, &new_fiber->context); + struct coroutine_context * from = coroutine_transfer(&old_fiber->context, &new_fiber->context); + + if (from == NULL) { + rb_syserr_fail(errno, "coroutine_transfer"); + } + + /* restore thread context */ + fiber_restore_thread(th, old_fiber); // It's possible to get here, and new_fiber is already freed. - // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] <- %p[%p]\n", old_fiber, old_fiber->stack.base, new_fiber, new_fiber->stack.base); + // 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); } NOINLINE(NORETURN(static void cont_restore_1(rb_context_t *))); @@ -1603,6 +1655,8 @@ rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *ta } } +NORETURN(static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval)); + /* * call-seq: * cont.call(args, ...) @@ -1627,9 +1681,6 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) if (cont_thread_value(cont) != th->self) { rb_raise(rb_eRuntimeError, "continuation called across threads"); } - if (cont->saved_ec.protect_tag != th->ec->protect_tag) { - rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier"); - } if (cont->saved_ec.fiber_ptr) { if (th->ec->fiber_ptr != cont->saved_ec.fiber_ptr) { rb_raise(rb_eRuntimeError, "continuation called across fiber"); @@ -1641,7 +1692,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) cont->value = make_passing_arg(argc, argv); cont_restore_0(cont, &contval); - return Qnil; /* unreachable */ + UNREACHABLE_RETURN(Qnil); } /*********/ @@ -1709,6 +1760,26 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) * 1000000 * FiberError: dead fiber called * + * == 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 + * 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. + * + * For a Fiber to behave as non-blocking, it need to be created in Fiber.new with + * blocking: false (which is the default), and Fiber.scheduler + * should be set with Fiber.set_scheduler. If Fiber.scheduler is not set in + * the current thread, blocking and non-blocking fibers' behavior is identical. + * + * Ruby doesn't provide a scheduler class: it is expected to be implemented by + * the user and correspond to Fiber::SchedulerInterface. + * + * There is also Fiber.schedule method, which is expected to immediately perform + * the given block in a non-blocking manner. Its actual implementation is up to + * the scheduler. + * */ static const rb_data_type_t fiber_data_type = { @@ -1724,7 +1795,7 @@ fiber_alloc(VALUE klass) } static rb_fiber_t* -fiber_t_alloc(VALUE fiber_value) +fiber_t_alloc(VALUE fiber_value, unsigned int blocking) { rb_fiber_t *fiber; rb_thread_t *th = GET_THREAD(); @@ -1737,6 +1808,7 @@ fiber_t_alloc(VALUE fiber_value) fiber = ZALLOC(rb_fiber_t); fiber->cont.self = fiber_value; fiber->cont.type = FIBER_CONTEXT; + fiber->blocking = blocking; cont_init(&fiber->cont, th); fiber->cont.saved_ec.fiber_ptr = fiber; @@ -1754,9 +1826,9 @@ fiber_t_alloc(VALUE fiber_value) } static VALUE -fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool) +fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool, unsigned int blocking) { - rb_fiber_t *fiber = fiber_t_alloc(self); + rb_fiber_t *fiber = fiber_t_alloc(self, blocking); fiber->first_proc = proc; fiber->stack.base = NULL; @@ -1784,41 +1856,212 @@ fiber_prepare_stack(rb_fiber_t *fiber) sec->local_storage_recursive_hash_for_trace = Qnil; } +static struct fiber_pool * +rb_fiber_pool_default(VALUE pool) +{ + return &shared_fiber_pool; +} + /* :nodoc: */ static VALUE +rb_fiber_initialize_kw(int argc, VALUE* argv, VALUE self, int kw_splat) +{ + VALUE pool = Qnil; + VALUE blocking = Qfalse; + + if (kw_splat != RB_NO_KEYWORDS) { + VALUE options = Qnil; + VALUE arguments[2] = {Qundef}; + + argc = rb_scan_args_kw(kw_splat, argc, argv, ":", &options); + rb_get_kwargs(options, fiber_initialize_keywords, 0, 2, arguments); + + if (arguments[0] != Qundef) { + blocking = arguments[0]; + } + + if (arguments[1] != Qundef) { + pool = arguments[1]; + } + } + + return fiber_initialize(self, rb_block_proc(), rb_fiber_pool_default(pool), RTEST(blocking)); +} + +/* + * call-seq: + * Fiber.new(blocking: false) { |*args| ... } -> fiber + * + * Creates new Fiber. Initially, the fiber is not running and can be resumed with + * #resume. Arguments to the first #resume call will be passed to the block: + * + * f = Fiber.new do |initial| + * current = initial + * loop do + * puts "current: #{current.inspect}" + * current = Fiber.yield + * end + * end + * f.resume(100) # prints: current: 100 + * f.resume(1, 2, 3) # prints: current: [1, 2, 3] + * f.resume # prints: current: nil + * # ... and so on ... + * + * If blocking: false is passed to Fiber.new, _and_ current thread + * has a Fiber.scheduler defined, the Fiber becomes non-blocking (see "Non-blocking + * Fibers" section in class docs). + */ +static VALUE rb_fiber_initialize(int argc, VALUE* argv, VALUE self) { - return fiber_initialize(self, rb_block_proc(), &shared_fiber_pool); + return rb_fiber_initialize_kw(argc, argv, self, rb_keyword_given_p()); } VALUE rb_fiber_new(rb_block_call_func_t func, VALUE obj) { - return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), &shared_fiber_pool); + return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 1); +} + +static VALUE +rb_fiber_s_schedule_kw(int argc, VALUE* argv, int kw_splat) +{ + rb_thread_t * th = GET_THREAD(); + VALUE scheduler = th->scheduler; + VALUE fiber = Qnil; + + if (scheduler != Qnil) { + fiber = rb_funcall_passing_block_kw(scheduler, rb_intern("fiber"), argc, argv, kw_splat); + } + else { + rb_raise(rb_eRuntimeError, "No scheduler is available!"); + } + + return fiber; +} + +/* + * call-seq: + * Fiber.schedule { |*args| ... } -> fiber + * + * The method is expected to immediately run the provided block of code in a + * separate non-blocking fiber. + * + * puts "Go to sleep!" + * + * Fiber.set_scheduler(MyScheduler.new) + * + * Fiber.schedule do + * puts "Going to sleep" + * sleep(1) + * puts "I slept well" + * end + * + * puts "Wakey-wakey, sleepyhead" + * + * Assuming MyScheduler is properly implemented, this program will produce: + * + * Go to sleep! + * Going to sleep + * Wakey-wakey, sleepyhead + * ...1 sec pause here... + * I slept well + * + * ...e.g. on the first blocking operation inside the Fiber (sleep(1)), + * the control is yielded to the outside code (main fiber), and at the end + * of that execution, the scheduler takes care of properly resuming all the + * blocked fibers. + * + * Note that the behavior described above is how the method is expected + * to behave, actual behavior is up to the current scheduler's implementation of + * Fiber::SchedulerInterface#fiber method. Ruby doesn't enforce this method to + * behave in any particular way. + * + * If the scheduler is not set, the method raises + * RuntimeError (No scheduler is available!). + * + */ +static VALUE +rb_fiber_s_schedule(int argc, VALUE *argv, VALUE obj) +{ + return rb_fiber_s_schedule_kw(argc, argv, rb_keyword_given_p()); +} + +/* + * call-seq: + * Fiber.scheduler -> obj or nil + * + * Returns the Fiber scheduler, that was last set for the current thread with Fiber.set_scheduler. + * Returns +nil+ if no scheduler is set (which is the default), and non-blocking fibers' + # behavior is the same as blocking. + * (see "Non-blocking fibers" section in class docs for details about the scheduler concept). + * + */ +static VALUE +rb_fiber_s_scheduler(VALUE klass) +{ + return rb_fiber_scheduler_get(); +} + +/* + * call-seq: + * Fiber.current_scheduler -> obj or nil + * + * Returns the Fiber scheduler, that was last set for the current thread with Fiber.set_scheduler + * if and only if the current fiber is non-blocking. + * + */ +static VALUE +rb_fiber_current_scheduler(VALUE klass) +{ + return rb_fiber_scheduler_current(); } -static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt); +/* + * call-seq: + * Fiber.set_scheduler(scheduler) -> scheduler + * + * Sets the Fiber scheduler for the current thread. If the scheduler is set, non-blocking + * fibers (created by Fiber.new with blocking: false, or by Fiber.schedule) + * call that scheduler's hook methods on potentially blocking operations, and the current + * thread will call scheduler's +close+ method on finalization (allowing the scheduler to + * properly manage all non-finished fibers). + * + * +scheduler+ can be an object of any class corresponding to Fiber::SchedulerInterface. Its + * implementation is up to the user. + * + * See also the "Non-blocking fibers" section in class docs. + * + */ +static VALUE +rb_fiber_set_scheduler(VALUE klass, VALUE scheduler) +{ + return rb_fiber_scheduler_set(scheduler); +} -#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p()) +NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err)); void -rb_fiber_start(void) +rb_fiber_start(rb_fiber_t *fiber) { - rb_thread_t * volatile th = GET_THREAD(); - rb_fiber_t *fiber = th->ec->fiber_ptr; + rb_thread_t * volatile th = fiber->cont.saved_ec.thread_ptr; + rb_proc_t *proc; enum ruby_tag_type state; int need_interrupt = TRUE; - VM_ASSERT(th->ec == ruby_current_execution_context_ptr); + VM_ASSERT(th->ec == GET_EC()); VM_ASSERT(FIBER_RESUMED_P(fiber)); + if (fiber->blocking) { + th->blocking += 1; + } + EC_PUSH_TAG(th->ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { rb_context_t *cont = &VAR_FROM_MEMORY(fiber)->cont; int argc; const VALUE *argv, args = cont->value; - int kw_splat = cont->kw_splat; GetProcPtr(fiber->first_proc, proc); argv = (argc = cont->argc) > 1 ? RARRAY_CONST_PTR(args) : &args; cont->value = Qnil; @@ -1827,29 +2070,28 @@ rb_fiber_start(void) th->ec->root_svar = Qfalse; EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil); - rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE); + cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, cont->kw_splat, VM_BLOCK_HANDLER_NONE); } EC_POP_TAG(); + VALUE err = Qfalse; if (state) { - VALUE err = th->ec->errinfo; + err = th->ec->errinfo; VM_ASSERT(FIBER_RESUMED_P(fiber)); - if (state == TAG_RAISE || state == TAG_FATAL) { + if (state == TAG_RAISE) { + // noop... + } + else if (state == TAG_FATAL) { rb_threadptr_pending_interrupt_enque(th, err); } else { err = rb_vm_make_jump_tag_but_local_jump(state, err); - if (!NIL_P(err)) { - rb_threadptr_pending_interrupt_enque(th, err); - } } need_interrupt = TRUE; } - rb_fiber_terminate(fiber, need_interrupt); - VM_UNREACHABLE(rb_fiber_start); + rb_fiber_terminate(fiber, need_interrupt, err); } static rb_fiber_t * @@ -1866,12 +2108,7 @@ root_fiber_alloc(rb_thread_t *th) DATA_PTR(fiber_value) = fiber; fiber->cont.self = fiber_value; -#ifdef COROUTINE_PRIVATE_STACK - fiber->stack = fiber_pool_stack_acquire(&shared_fiber_pool); - coroutine_initialize_main(&fiber->context, fiber_pool_stack_base(&fiber->stack), fiber->stack.available, th->ec->machine.stack_start); -#else coroutine_initialize_main(&fiber->context); -#endif return fiber; } @@ -1887,8 +2124,12 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th) fiber->cont.type = FIBER_CONTEXT; fiber->cont.saved_ec.fiber_ptr = fiber; fiber->cont.saved_ec.thread_ptr = th; + fiber->blocking = 1; fiber_status_set(fiber, FIBER_RESUMED); /* skip CREATED */ th->ec = &fiber->cont.saved_ec; + // This skips mjit_cont_new for the initial thread because mjit_enabled is always false + // at this point. mjit_init calls rb_fiber_init_mjit_cont again for this root_fiber. + rb_fiber_init_mjit_cont(fiber); } void @@ -1898,13 +2139,15 @@ 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(); + VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT); VM_ASSERT(th->ec->fiber_ptr->cont.self == 0); - fiber_free(th->ec->fiber_ptr); - if (th->ec == ruby_current_execution_context_ptr) { - ruby_current_execution_context_ptr = NULL; + if (th->ec == ec) { + rb_ractor_set_current_ec(th->ractor, NULL); } + fiber_free(th->ec->fiber_ptr); th->ec = NULL; } } @@ -1931,25 +2174,31 @@ fiber_current(void) } static inline rb_fiber_t* -return_fiber(void) +return_fiber(bool terminate) { rb_fiber_t *fiber = fiber_current(); rb_fiber_t *prev = fiber->prev; - if (!prev) { + if (prev) { + fiber->prev = NULL; + prev->resuming_fiber = NULL; + return prev; + } + else { + if (!terminate) { + rb_raise(rb_eFiberError, "attempt to yield on a not resumed fiber"); + } + rb_thread_t *th = GET_THREAD(); rb_fiber_t *root_fiber = th->root_fiber; VM_ASSERT(root_fiber != NULL); - if (root_fiber == fiber) { - rb_raise(rb_eFiberError, "can't yield from root fiber"); + // search resuming fiber + for (fiber = root_fiber; fiber->resuming_fiber; fiber = fiber->resuming_fiber) { } - return root_fiber; - } - else { - fiber->prev = NULL; - return prev; + + return fiber; } } @@ -1960,7 +2209,7 @@ rb_fiber_current(void) } // Prepare to execute next_fiber on the given thread. -static inline VALUE +static inline void fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th) { rb_fiber_t *fiber; @@ -1984,17 +2233,10 @@ fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th) fiber_status_set(next_fiber, FIBER_RESUMED); fiber_setcontext(next_fiber, fiber); - - fiber = th->ec->fiber_ptr; - - /* Raise an exception if that was the result of executing the fiber */ - if (fiber->cont.argc == -1) rb_exc_raise(fiber->cont.value); - - return fiber->cont.value; } static inline VALUE -fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int kw_splat) +fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, rb_fiber_t *resuming_fiber, bool yielding) { VALUE value; rb_context_t *cont = &fiber->cont; @@ -2005,7 +2247,7 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int if (th->ec->fiber_ptr == fiber) { /* ignore fiber context switch - * because destination fiber is same as current fiber + * because destination fiber is the same as current fiber */ return make_passing_arg(argc, argv); } @@ -2013,10 +2255,8 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int if (cont_thread_value(cont) != th->self) { rb_raise(rb_eFiberError, "fiber called across threads"); } - else if (cont->saved_ec.protect_tag != th->ec->protect_tag) { - rb_raise(rb_eFiberError, "fiber called across stack rewinding barrier"); - } - else if (FIBER_TERMINATED_P(fiber)) { + + if (FIBER_TERMINATED_P(fiber)) { value = rb_exc_new2(rb_eFiberError, "dead fiber called"); if (!FIBER_TERMINATED_P(th->ec->fiber_ptr)) { @@ -2039,33 +2279,108 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int } } - if (is_resume) { + VM_ASSERT(FIBER_RUNNABLE_P(fiber)); + + rb_fiber_t *current_fiber = fiber_current(); + + VM_ASSERT(!current_fiber->resuming_fiber); + + if (resuming_fiber) { + current_fiber->resuming_fiber = resuming_fiber; fiber->prev = fiber_current(); + fiber->yielding = 0; } - VM_ASSERT(FIBER_RUNNABLE_P(fiber)); + VM_ASSERT(!current_fiber->yielding); + if (yielding) { + current_fiber->yielding = 1; + } + + if (current_fiber->blocking) { + th->blocking -= 1; + } cont->argc = argc; cont->kw_splat = kw_splat; cont->value = make_passing_arg(argc, argv); - value = fiber_store(fiber, th); + fiber_store(fiber, th); - if (is_resume && FIBER_TERMINATED_P(fiber)) { + // We cannot free the stack until the pthread is joined: +#ifndef COROUTINE_PTHREAD_CONTEXT + if (resuming_fiber && FIBER_TERMINATED_P(fiber)) { fiber_stack_release(fiber); } +#endif + + if (fiber_current()->blocking) { + th->blocking += 1; + } RUBY_VM_CHECK_INTS(th->ec); EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil); + current_fiber = th->ec->fiber_ptr; + value = current_fiber->cont.value; + if (current_fiber->cont.argc == -1) rb_exc_raise(value); return value; } VALUE rb_fiber_transfer(VALUE fiber_value, int argc, const VALUE *argv) { - return fiber_switch(fiber_ptr(fiber_value), argc, argv, 0, RB_NO_KEYWORDS); + return fiber_switch(fiber_ptr(fiber_value), argc, argv, RB_NO_KEYWORDS, NULL, false); +} + +/* + * call-seq: + * fiber.blocking? -> true or false + * + * Returns +true+ if +fiber+ is blocking and +false+ otherwise. + * Fiber is non-blocking if it was created via passing blocking: false + * to Fiber.new, or via Fiber.schedule. + * + * Note that, even if the method returns +false+, the fiber behaves differently + * only if Fiber.scheduler is set in the current thread. + * + * See the "Non-blocking fibers" section in class docs for details. + * + */ +VALUE +rb_fiber_blocking_p(VALUE fiber) +{ + return RBOOL(fiber_ptr(fiber)->blocking != 0); +} + +/* + * call-seq: + * Fiber.blocking? -> false or 1 + * + * Returns +false+ if the current fiber is non-blocking. + * Fiber is non-blocking if it was created via passing blocking: false + * to Fiber.new, or via Fiber.schedule. + * + * If the current Fiber is blocking, the method returns 1. + * Future developments may allow for situations where larger integers + * could be returned. + * + * Note that, even if the method returns +false+, Fiber behaves differently + * only if Fiber.scheduler is set in the current thread. + * + * See the "Non-blocking fibers" section in class docs for details. + * + */ +static VALUE +rb_fiber_s_blocking_p(VALUE klass) +{ + rb_thread_t *thread = GET_THREAD(); + unsigned blocking = thread->blocking; + + if (blocking == 0) + return Qfalse; + + return INT2NUM(blocking); } void @@ -2075,60 +2390,79 @@ rb_fiber_close(rb_fiber_t *fiber) } static void -rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt) +rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE error) { VALUE value = fiber->cont.value; - rb_fiber_t *next_fiber; VM_ASSERT(FIBER_RESUMED_P(fiber)); rb_fiber_close(fiber); - coroutine_destroy(&fiber->context); - fiber->cont.machine.stack = NULL; fiber->cont.machine.stack_size = 0; - next_fiber = return_fiber(); + rb_fiber_t *next_fiber = return_fiber(true); + if (need_interrupt) RUBY_VM_SET_INTERRUPT(&next_fiber->cont.saved_ec); - fiber_switch(next_fiber, 1, &value, 0, RB_NO_KEYWORDS); + + if (RTEST(error)) + fiber_switch(next_fiber, -1, &error, RB_NO_KEYWORDS, NULL, false); + else + fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, NULL, false); + ruby_stop(0); } -VALUE -rb_fiber_resume_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat) +static VALUE +fiber_resume_kw(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat) { - rb_fiber_t *fiber = fiber_ptr(fiber_value); + rb_fiber_t *current_fiber = fiber_current(); if (argc == -1 && FIBER_CREATED_P(fiber)) { rb_raise(rb_eFiberError, "cannot raise exception on unborn fiber"); } - - if (fiber->prev != 0 || fiber_is_root_p(fiber)) { - rb_raise(rb_eFiberError, "double resume"); + else if (FIBER_TERMINATED_P(fiber)) { + rb_raise(rb_eFiberError, "attempt to resume a terminated fiber"); } - - if (fiber->transferred != 0) { - rb_raise(rb_eFiberError, "cannot resume transferred Fiber"); + else if (fiber == current_fiber) { + rb_raise(rb_eFiberError, "attempt to resume the current fiber"); + } + else if (fiber->prev != NULL) { + rb_raise(rb_eFiberError, "attempt to resume a resumed fiber (double resume)"); + } + else if (fiber->resuming_fiber) { + rb_raise(rb_eFiberError, "attempt to resume a resuming fiber"); } + else if (fiber->prev == NULL && + (!fiber->yielding && fiber->status != FIBER_CREATED)) { + rb_raise(rb_eFiberError, "attempt to resume a transferring fiber"); + } + + VALUE result = fiber_switch(fiber, argc, argv, kw_splat, fiber, false); + + return result; +} - return fiber_switch(fiber, argc, argv, 1, kw_splat); +VALUE +rb_fiber_resume_kw(VALUE self, int argc, const VALUE *argv, int kw_splat) +{ + return fiber_resume_kw(fiber_ptr(self), argc, argv, kw_splat); } VALUE -rb_fiber_resume(VALUE fiber_value, int argc, const VALUE *argv) +rb_fiber_resume(VALUE self, int argc, const VALUE *argv) { - return rb_fiber_resume_kw(fiber_value, argc, argv, RB_NO_KEYWORDS); + return fiber_resume_kw(fiber_ptr(self), argc, argv, RB_NO_KEYWORDS); } VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat) { - return fiber_switch(return_fiber(), argc, argv, 0, kw_splat); + return fiber_switch(return_fiber(false), argc, argv, kw_splat, NULL, true); } VALUE rb_fiber_yield(int argc, const VALUE *argv) { - return fiber_switch(return_fiber(), argc, argv, 0, RB_NO_KEYWORDS); + return fiber_switch(return_fiber(false), argc, argv, RB_NO_KEYWORDS, NULL, true); } void @@ -2145,8 +2479,7 @@ rb_fiber_reset_root_local_storage(rb_thread_t *th) * * Returns true if the fiber can still be resumed (or transferred * to). After finishing execution of the fiber block this method will - * always return false. You need to require 'fiber' - * before using this method. + * always return +false+. */ VALUE rb_fiber_alive_p(VALUE fiber_value) @@ -2172,33 +2505,84 @@ rb_fiber_alive_p(VALUE fiber_value) static VALUE rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber) { - return rb_fiber_resume_kw(fiber, argc, argv, PASS_KW_SPLAT); + return rb_fiber_resume_kw(fiber, argc, argv, rb_keyword_given_p()); } /* * call-seq: - * fiber.raise -> obj - * fiber.raise(string) -> obj - * fiber.raise(exception [, string [, array]]) -> obj + * fiber.backtrace -> array + * fiber.backtrace(start) -> array + * fiber.backtrace(start, count) -> array + * fiber.backtrace(start..end) -> array + * + * Returns the current execution stack of the fiber. +start+, +count+ and +end+ allow + * to select only parts of the backtrace. + * + * def level3 + * Fiber.yield + * end + * + * def level2 + * level3 + * end + * + * def level1 + * level2 + * end + * + * f = Fiber.new { level1 } + * + * # It is empty before the fiber started + * f.backtrace + * #=> [] + * + * f.resume + * + * f.backtrace + * #=> ["test.rb:2:in `yield'", "test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'", "test.rb:13:in `block in
'"] + * p f.backtrace(1) # start from the item 1 + * #=> ["test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'", "test.rb:13:in `block in
'"] + * p f.backtrace(2, 2) # start from item 2, take 2 + * #=> ["test.rb:6:in `level2'", "test.rb:10:in `level1'"] + * p f.backtrace(1..3) # take items from 1 to 3 + * #=> ["test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'"] + * + * f.resume + * + * # It is nil after the fiber is finished + * f.backtrace + * #=> nil + * + */ +static VALUE +rb_fiber_backtrace(int argc, VALUE *argv, VALUE fiber) +{ + return rb_vm_backtrace(argc, argv, &fiber_ptr(fiber)->cont.saved_ec); +} + +/* + * call-seq: + * fiber.backtrace_locations -> array + * fiber.backtrace_locations(start) -> array + * fiber.backtrace_locations(start, count) -> array + * fiber.backtrace_locations(start..end) -> array + * + * Like #backtrace, but returns each line of the execution stack as a + * Thread::Backtrace::Location. Accepts the same arguments as #backtrace. + * + * f = Fiber.new { Fiber.yield } + * f.resume + * loc = f.backtrace_locations.first + * loc.label #=> "yield" + * loc.path #=> "test.rb" + * loc.lineno #=> 1 * - * Raises an exception in the fiber at the point at which the last - * Fiber.yield was called, or at the start if neither +resume+ - * nor +raise+ were called before. * - * With no arguments, raises a +RuntimeError+. With a single +String+ - * argument, raises a +RuntimeError+ with the string as a message. Otherwise, - * the first parameter should be the name of an +Exception+ class (or an - * object that returns an +Exception+ object when sent an +exception+ - * message). The optional second parameter sets the message associated with - * the exception, and the third parameter is an array of callback information. - * Exceptions are caught by the +rescue+ clause of begin...end - * blocks. */ static VALUE -rb_fiber_raise(int argc, VALUE *argv, VALUE fiber) +rb_fiber_backtrace_locations(int argc, VALUE *argv, VALUE fiber) { - VALUE exc = rb_make_exception(argc, argv); - return rb_fiber_resume_kw(fiber, -1, &exc, RB_NO_KEYWORDS); + return rb_vm_backtrace_locations(argc, argv, &fiber_ptr(fiber)->cont.saved_ec); } /* @@ -2208,57 +2592,105 @@ rb_fiber_raise(int argc, VALUE *argv, VALUE fiber) * Transfer control to another fiber, resuming it from where it last * stopped or starting it if it was not resumed before. The calling * fiber will be suspended much like in a call to - * Fiber.yield. You need to require 'fiber' - * before using this method. + * Fiber.yield. * - * The fiber which receives the transfer call is treats it much like + * The fiber which receives the transfer call treats it much like * a resume call. Arguments passed to transfer are treated like those * passed to resume. * - * You cannot call +resume+ on a fiber that has been transferred to. - * If you call +transfer+ on a fiber, and later call +resume+ on the - * the fiber, a +FiberError+ will be raised. Once you call +transfer+ on - * a fiber, the only way to resume processing the fiber is to - * call +transfer+ on it again. + * The two style of control passing to and from fiber (one is #resume and + * Fiber::yield, another is #transfer to and from fiber) can't be freely + * mixed. + * + * * If the Fiber's lifecycle had started with transfer, it will never + * be able to yield or be resumed control passing, only + * finish or transfer back. (It still can resume other fibers that + * are allowed to be resumed.) + * * If the Fiber's lifecycle had started with resume, it can yield + * or transfer to another Fiber, but can receive control back only + * the way compatible with the way it was given away: if it had + * transferred, it only can be transferred back, and if it had + * yielded, it only can be resumed back. After that, it again can + * transfer or yield. + * + * If those rules are broken FiberError is raised. + * + * For an individual Fiber design, yield/resume is easier to use + * (the Fiber just gives away control, it doesn't need to think + * about who the control is given to), while transfer is more flexible + * for complex cases, allowing to build arbitrary graphs of Fibers + * dependent on each other. + * * * Example: * - * fiber1 = Fiber.new do - * puts "In Fiber 1" - * Fiber.yield - * puts "In Fiber 1 again" - * end + * manager = nil # For local var to be visible inside worker block * - * fiber2 = Fiber.new do - * puts "In Fiber 2" - * fiber1.transfer - * puts "Never see this message" - * end + * # This fiber would be started with transfer + * # It can't yield, and can't be resumed + * worker = Fiber.new { |work| + * puts "Worker: starts" + * puts "Worker: Performed #{work.inspect}, transferring back" + * # Fiber.yield # this would raise FiberError: attempt to yield on a not resumed fiber + * # manager.resume # this would raise FiberError: attempt to resume a resumed fiber (double resume) + * manager.transfer(work.capitalize) + * } * - * fiber3 = Fiber.new do - * puts "In Fiber 3" - * end + * # This fiber would be started with resume + * # It can yield or transfer, and can be transferred + * # back or resumed + * manager = Fiber.new { + * puts "Manager: starts" + * puts "Manager: transferring 'something' to worker" + * result = worker.transfer('something') + * puts "Manager: worker returned #{result.inspect}" + * # worker.resume # this would raise FiberError: attempt to resume a transferring fiber + * Fiber.yield # this is OK, the fiber transferred from and to, now it can yield + * puts "Manager: finished" + * } * - * fiber2.resume - * fiber3.resume - * fiber1.resume rescue (p $!) - * fiber1.transfer + * puts "Starting the manager" + * manager.resume + * puts "Resuming the manager" + * # manager.transfer # this would raise FiberError: attempt to transfer to a yielding fiber + * manager.resume * * produces * - * In Fiber 2 - * In Fiber 1 - * In Fiber 3 - * # - * In Fiber 1 again + * Starting the manager + * Manager: starts + * Manager: transferring 'something' to worker + * Worker: starts + * Worker: Performed "something", transferring back + * Manager: worker returned "Something" + * Resuming the manager + * Manager: finished * */ static VALUE -rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value) +rb_fiber_m_transfer(int argc, VALUE *argv, VALUE self) { - rb_fiber_t *fiber = fiber_ptr(fiber_value); - fiber->transferred = 1; - return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT); + return rb_fiber_transfer_kw(self, argc, argv, rb_keyword_given_p()); +} + +static VALUE +fiber_transfer_kw(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat) +{ + if (fiber->resuming_fiber) { + rb_raise(rb_eFiberError, "attempt to transfer to a resuming fiber"); + } + + if (fiber->yielding) { + rb_raise(rb_eFiberError, "attempt to transfer to a yielding fiber"); + } + + return fiber_switch(fiber, argc, argv, kw_splat, NULL, false); +} + +VALUE +rb_fiber_transfer_kw(VALUE self, int argc, const VALUE *argv, int kw_splat) +{ + return fiber_transfer_kw(fiber_ptr(self), argc, argv, kw_splat); } /* @@ -2274,30 +2706,70 @@ rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value) static VALUE rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass) { - return rb_fiber_yield_kw(argc, argv, PASS_KW_SPLAT); + return rb_fiber_yield_kw(argc, argv, rb_keyword_given_p()); +} + +static VALUE +fiber_raise(rb_fiber_t *fiber, int argc, const VALUE *argv) +{ + VALUE exception = rb_make_exception(argc, argv); + + if (fiber->resuming_fiber) { + rb_raise(rb_eFiberError, "attempt to raise a resuming fiber"); + } + else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { + return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS); + } + else { + return fiber_resume_kw(fiber, -1, &exception, RB_NO_KEYWORDS); + } +} + +VALUE +rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv) +{ + return fiber_raise(fiber_ptr(fiber), argc, argv); } /* * call-seq: - * Fiber.current() -> fiber + * fiber.raise -> obj + * fiber.raise(string) -> obj + * fiber.raise(exception [, string [, array]]) -> obj * - * Returns the current fiber. You need to require 'fiber' - * before using this method. If you are not running in the context of - * a fiber this method will return the root fiber. + * Raises an exception in the fiber at the point at which the last + * +Fiber.yield+ was called. If the fiber has not been started or has + * already run to completion, raises +FiberError+. If the fiber is + * yielding, it is resumed. If it is transferring, it is transferred into. + * But if it is resuming, raises +FiberError+. + * + * With no arguments, raises a +RuntimeError+. With a single +String+ + * argument, raises a +RuntimeError+ with the string as a message. Otherwise, + * the first parameter should be the name of an +Exception+ class (or an + * object that returns an +Exception+ object when sent an +exception+ + * message). The optional second parameter sets the message associated with + * the exception, and the third parameter is an array of callback information. + * Exceptions are caught by the +rescue+ clause of begin...end + * blocks. */ static VALUE -rb_fiber_s_current(VALUE klass) +rb_fiber_m_raise(int argc, VALUE *argv, VALUE self) { - return rb_fiber_current(); + return rb_fiber_raise(self, argc, argv); } /* - * call-seq: - * fiber.to_s -> string - * - * Returns fiber information string. + * call-seq: + * Fiber.current -> fiber * + * Returns the current fiber. If you are not running in the context of + * a fiber this method will return the root fiber. */ +static VALUE +rb_fiber_s_current(VALUE klass) +{ + return rb_fiber_current(); +} static VALUE fiber_to_s(VALUE fiber_value) @@ -2306,8 +2778,8 @@ fiber_to_s(VALUE fiber_value) const rb_proc_t *proc; char status_info[0x20]; - if (fiber->transferred) { - snprintf(status_info, 0x20, " (%s, transferred)", fiber_status_name(fiber->status)); + if (fiber->resuming_fiber) { + snprintf(status_info, 0x20, " (%s by resuming)", fiber_status_name(fiber->status)); } else { snprintf(status_info, 0x20, " (%s)", fiber_status_name(fiber->status)); @@ -2418,6 +2890,329 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self) * fiber.resume #=> FiberError: dead fiber called */ +/* + * Document-class: Fiber::SchedulerInterface + * + * This is not an existing class, but documentation of the interface that Scheduler + * object should comply to in order to be used as argument to Fiber.scheduler and handle non-blocking + * fibers. See also the "Non-blocking fibers" section in Fiber class docs for explanations + * of some concepts. + * + * Scheduler's behavior and usage are expected to be as follows: + * + * * When the execution in the non-blocking Fiber reaches some blocking operation (like + * sleep, wait for a process, or a non-ready I/O), it calls some of the scheduler's + * hook methods, listed below. + * * Scheduler somehow registers what the current fiber is waiting on, and yields control + * to other fibers with Fiber.yield (so the fiber would be suspended while expecting its + * wait to end, and other fibers in the same thread can perform) + * * At the end of the current thread execution, the scheduler's method #close is called + * * The scheduler runs into a wait loop, checking all the blocked fibers (which it has + * registered on hook calls) and resuming them when the awaited resource is ready + * (e.g. I/O ready or sleep time elapsed). + * + * A typical implementation would probably rely for this closing loop on a gem like + * EventMachine[https://github.com/eventmachine/eventmachine] or + * Async[https://github.com/socketry/async]. + * + * This way concurrent execution will be achieved transparently for every + * individual Fiber's code. + * + * Hook methods are: + * + * * #io_wait, #io_read, and #io_write + * * #process_wait + * * #kernel_sleep + * * #timeout_after + * * #address_resolve + * * #block and #unblock + * * (the list is expanded as Ruby developers make more methods having non-blocking calls) + * + * When not specified otherwise, the hook implementations are mandatory: if they are not + * implemented, the methods trying to call hook will fail. To provide backward compatibility, + * in the future hooks will be optional (if they are not implemented, due to the scheduler + * being created for the older Ruby version, the code which needs this hook will not fail, + * and will just behave in a blocking fashion). + * + * It is also strongly recommended that the scheduler implements the #fiber method, which is + * delegated to by Fiber.schedule. + * + * Sample _toy_ implementation of the scheduler can be found in Ruby's code, in + * test/fiber/scheduler.rb + * + */ + +#if 0 /* for RDoc */ +/* + * + * Document-method: Fiber::SchedulerInterface#close + * + * Called when the current thread exits. The scheduler is expected to implement this + * method in order to allow all waiting fibers to finalize their execution. + * + * The suggested pattern is to implement the main event loop in the #close method. + * + */ +static VALUE +rb_fiber_scheduler_interface_close(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#process_wait + * call-seq: process_wait(pid, flags) + * + * Invoked by Process::Status.wait in order to wait for a specified process. + * See that method description for arguments description. + * + * Suggested minimal implementation: + * + * Thread.new do + * Process::Status.wait(pid, flags) + * end.value + * + * This hook is optional: if it is not present in the current scheduler, + * Process::Status.wait will behave as a blocking method. + * + * Expected to return a Process::Status instance. + */ +static VALUE +rb_fiber_scheduler_interface_process_wait(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#io_wait + * call-seq: io_wait(io, events, timeout) + * + * Invoked by IO#wait, IO#wait_readable, IO#wait_writable to ask whether the + * specified descriptor is ready for specified events within + * the specified +timeout+. + * + * +events+ is a bit mask of IO::READABLE, IO::WRITABLE, and + * IO::PRIORITY. + * + * Suggested implementation should register which Fiber is waiting for which + * resources and immediately calling Fiber.yield to pass control to other + * fibers. Then, in the #close method, the scheduler might dispatch all the + * I/O resources to fibers waiting for it. + * + * Expected to return the subset of events that are ready immediately. + * + */ +static VALUE +rb_fiber_scheduler_interface_io_wait(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#io_read + * call-seq: io_read(io, buffer, length) -> read length or -errno + * + * Invoked by IO#read to read +length+ bytes from +io+ into a specified + * +buffer+ (see IO::Buffer). + * + * The +length+ argument is the "minimum length to be read". + * If the IO buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to + * 8KiB might be read, but at least 1KiB will be. + * Generally, the only case where less data than +length+ will be read is if + * there is an error reading the data. + * + * Specifying a +length+ of 0 is valid and means try reading at least once + * and return any available data. + * + * Suggested implementation should try to read from +io+ in a non-blocking + * manner and call #io_wait if the +io+ is not ready (which will yield control + * to other fibers). + * + * See IO::Buffer for an interface available to return data. + * + * Expected to return number of bytes read, or, in case of an error, -errno + * (negated number corresponding to system's error code). + * + * The method should be considered _experimental_. + */ +static VALUE +rb_fiber_scheduler_interface_io_read(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#io_write + * call-seq: io_write(io, buffer, length) -> written length or -errno + * + * Invoked by IO#write to write +length+ bytes to +io+ from + * from a specified +buffer+ (see IO::Buffer). + * + * The +length+ argument is the "(minimum) length to be written". + * If the IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB), + * at most 8KiB will be written, but at least 1KiB will be. + * Generally, the only case where less data than +length+ will be written is if + * there is an error writing the data. + * + * Specifying a +length+ of 0 is valid and means try writing at least once, + * as much data as possible. + * + * Suggested implementation should try to write to +io+ in a non-blocking + * manner and call #io_wait if the +io+ is not ready (which will yield control + * to other fibers). + * + * See IO::Buffer for an interface available to get data from buffer efficiently. + * + * Expected to return number of bytes written, or, in case of an error, -errno + * (negated number corresponding to system's error code). + * + * The method should be considered _experimental_. + */ +static VALUE +rb_fiber_scheduler_interface_io_write(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#kernel_sleep + * call-seq: kernel_sleep(duration = nil) + * + * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide + * an implementation of sleeping in a non-blocking way. Implementation might + * register the current fiber in some list of "which fiber wait until what + * moment", call Fiber.yield to pass control, and then in #close resume + * the fibers whose wait period has elapsed. + * + */ +static VALUE +rb_fiber_scheduler_interface_kernel_sleep(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#address_resolve + * call-seq: address_resolve(hostname) -> array_of_strings or nil + * + * Invoked by any method that performs a non-reverse DNS lookup. The most + * notable method is Addrinfo.getaddrinfo, but there are many other. + * + * The method is expected to return an array of strings corresponding to ip + * addresses the +hostname+ is resolved to, or +nil+ if it can not be resolved. + * + * Fairly exhaustive list of all possible call-sites: + * + * - Addrinfo.getaddrinfo + * - Addrinfo.tcp + * - Addrinfo.udp + * - Addrinfo.ip + * - Addrinfo.new + * - Addrinfo.marshal_load + * - SOCKSSocket.new + * - TCPServer.new + * - TCPSocket.new + * - IPSocket.getaddress + * - TCPSocket.gethostbyname + * - UDPSocket#connect + * - UDPSocket#bind + * - UDPSocket#send + * - Socket.getaddrinfo + * - Socket.gethostbyname + * - Socket.pack_sockaddr_in + * - Socket.sockaddr_in + * - Socket.unpack_sockaddr_in + */ +static VALUE +rb_fiber_scheduler_interface_address_resolve(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#timeout_after + * call-seq: timeout_after(duration, exception_class, *exception_arguments, &block) -> result of block + * + * Invoked by Timeout.timeout to execute the given +block+ within the given + * +duration+. It can also be invoked directly by the scheduler or user code. + * + * Attempt to limit the execution time of a given +block+ to the given + * +duration+ if possible. When a non-blocking operation causes the +block+'s + * execution time to exceed the specified +duration+, that non-blocking + * operation should be interrupted by raising the specified +exception_class+ + * constructed with the given +exception_arguments+. + * + * General execution timeouts are often considered risky. This implementation + * will only interrupt non-blocking operations. This is by design because it's + * expected that non-blocking operations can fail for a variety of + * unpredictable reasons, so applications should already be robust in handling + * these conditions and by implication timeouts. + * + * However, as a result of this design, if the +block+ does not invoke any + * non-blocking operations, it will be impossible to interrupt it. If you + * desire to provide predictable points for timeouts, consider adding + * +sleep(0)+. + * + * If the block is executed successfully, its result will be returned. + * + * The exception will typically be raised using Fiber#raise. + */ +static VALUE +rb_fiber_scheduler_interface_timeout_after(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#block + * call-seq: block(blocker, timeout = nil) + * + * Invoked by methods like Thread.join, and by Mutex, to signify that current + * Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has + * elapsed. + * + * +blocker+ is what we are waiting on, informational only (for debugging and + * logging). There are no guarantee about its value. + * + * Expected to return boolean, specifying whether the blocking operation was + * successful or not. + */ +static VALUE +rb_fiber_scheduler_interface_block(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#unblock + * call-seq: unblock(blocker, fiber) + * + * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock + * calls #block and Mutex#unlock calls #unblock). The scheduler should use + * the +fiber+ parameter to understand which fiber is unblocked. + * + * +blocker+ is what was awaited for, but it is informational only (for debugging + * and logging), and it is not guaranteed to be the same value as the +blocker+ for + * #block. + * + */ +static VALUE +rb_fiber_scheduler_interface_unblock(VALUE self) +{ +} + +/* + * Document-method: SchedulerInterface#fiber + * call-seq: fiber(&block) + * + * Implementation of the Fiber.schedule. The method is expected to immediately + * run the given block of code in a separate non-blocking fiber, and to return that Fiber. + * + * Minimal suggested implementation is: + * + * def fiber(&block) + * fiber = Fiber.new(blocking: false, &block) + * fiber.resume + * fiber + * end + */ +static VALUE +rb_fiber_scheduler_interface_fiber(VALUE self) +{ +} +#endif + void Init_Cont(void) { @@ -2437,7 +3232,10 @@ Init_Cont(void) fiber_pool_initialize(&shared_fiber_pool, stack_size, FIBER_POOL_INITIAL_SIZE, vm_stack_size); - char * fiber_shared_fiber_pool_free_stacks = getenv("RUBY_SHARED_FIBER_POOL_FREE_STACKS"); + fiber_initialize_keywords[0] = rb_intern_const("blocking"); + fiber_initialize_keywords[1] = rb_intern_const("pool"); + + const char *fiber_shared_fiber_pool_free_stacks = getenv("RUBY_SHARED_FIBER_POOL_FREE_STACKS"); if (fiber_shared_fiber_pool_free_stacks) { shared_fiber_pool.free_stacks = atoi(fiber_shared_fiber_pool_free_stacks); } @@ -2446,17 +3244,47 @@ Init_Cont(void) rb_define_alloc_func(rb_cFiber, fiber_alloc); rb_eFiberError = rb_define_class("FiberError", rb_eStandardError); rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1); + rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0); rb_define_method(rb_cFiber, "initialize", rb_fiber_initialize, -1); + rb_define_method(rb_cFiber, "blocking?", rb_fiber_blocking_p, 0); rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1); - rb_define_method(rb_cFiber, "raise", rb_fiber_raise, -1); + rb_define_method(rb_cFiber, "raise", rb_fiber_m_raise, -1); + rb_define_method(rb_cFiber, "backtrace", rb_fiber_backtrace, -1); + rb_define_method(rb_cFiber, "backtrace_locations", rb_fiber_backtrace_locations, -1); rb_define_method(rb_cFiber, "to_s", fiber_to_s, 0); rb_define_alias(rb_cFiber, "inspect", "to_s"); + rb_define_method(rb_cFiber, "transfer", rb_fiber_m_transfer, -1); + rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0); + + rb_define_singleton_method(rb_cFiber, "blocking?", rb_fiber_s_blocking_p, 0); + rb_define_singleton_method(rb_cFiber, "scheduler", rb_fiber_s_scheduler, 0); + rb_define_singleton_method(rb_cFiber, "set_scheduler", rb_fiber_set_scheduler, 1); + rb_define_singleton_method(rb_cFiber, "current_scheduler", rb_fiber_current_scheduler, 0); + + rb_define_singleton_method(rb_cFiber, "schedule", rb_fiber_s_schedule, -1); + +#if 0 /* for RDoc */ + rb_cFiberScheduler = rb_define_class_under(rb_cFiber, "SchedulerInterface", rb_cObject); + rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_interface_close, 0); + rb_define_method(rb_cFiberScheduler, "process_wait", rb_fiber_scheduler_interface_process_wait, 0); + rb_define_method(rb_cFiberScheduler, "io_wait", rb_fiber_scheduler_interface_io_wait, 0); + rb_define_method(rb_cFiberScheduler, "io_read", rb_fiber_scheduler_interface_io_read, 0); + rb_define_method(rb_cFiberScheduler, "io_write", rb_fiber_scheduler_interface_io_write, 0); + rb_define_method(rb_cFiberScheduler, "kernel_sleep", rb_fiber_scheduler_interface_kernel_sleep, 0); + rb_define_method(rb_cFiberScheduler, "address_resolve", rb_fiber_scheduler_interface_address_resolve, 0); + rb_define_method(rb_cFiberScheduler, "timeout_after", rb_fiber_scheduler_interface_timeout_after, 0); + rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_interface_block, 0); + rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_interface_unblock, 0); + rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler_interface_fiber, 0); +#endif #ifdef RB_EXPERIMENTAL_FIBER_POOL rb_cFiberPool = rb_define_class("Pool", rb_cFiber); rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc); rb_define_method(rb_cFiberPool, "initialize", rb_fiber_pool_initialize, -1); #endif + + rb_provide("fiber.so"); } RUBY_SYMBOL_EXPORT_BEGIN @@ -2472,12 +3300,4 @@ ruby_Init_Continuation_body(void) rb_define_global_function("callcc", rb_callcc, 0); } -void -ruby_Init_Fiber_as_Coroutine(void) -{ - rb_define_method(rb_cFiber, "transfer", rb_fiber_m_transfer, -1); - rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0); - rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0); -} - RUBY_SYMBOL_EXPORT_END diff --git a/ruby/coroutine/amd64/Context.S b/ruby/coroutine/amd64/Context.S index ac986b2aa..d50732adb 100644 --- a/ruby/coroutine/amd64/Context.S +++ b/ruby/coroutine/amd64/Context.S @@ -2,7 +2,7 @@ ## This file is part of the "Coroutine" project and released under the MIT License. ## ## Created by Samuel Williams on 10/5/2018. -## Copyright, 2018, by Samuel Williams. All rights reserved. +## Copyright, 2018, by Samuel Williams. ## #define TOKEN_PASTE(x,y) x##y @@ -41,6 +41,6 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # We pop the return address and jump to it ret -#if defined(__linux__) && defined(__ELF__) +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif diff --git a/ruby/coroutine/amd64/Context.h b/ruby/coroutine/amd64/Context.h index 8fe323c1a..f626a4722 100644 --- a/ruby/coroutine/amd64/Context.h +++ b/ruby/coroutine/amd64/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_AMD64_CONTEXT_H +#define COROUTINE_AMD64_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 10/5/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __attribute__((noreturn)) void @@ -17,6 +22,7 @@ enum {COROUTINE_REGISTERS = 6}; struct coroutine_context { void **stack_pointer; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -50,3 +56,5 @@ static inline void coroutine_destroy(struct coroutine_context * context) { context->stack_pointer = NULL; } + +#endif /* COROUTINE_AMD64_CONTEXT_H */ diff --git a/ruby/coroutine/arm32/Context.S b/ruby/coroutine/arm32/Context.S index 4308e1d1d..1850c4c40 100644 --- a/ruby/coroutine/arm32/Context.S +++ b/ruby/coroutine/arm32/Context.S @@ -2,21 +2,32 @@ ## This file is part of the "Coroutine" project and released under the MIT License. ## ## Created by Samuel Williams on 10/5/2018. -## Copyright, 2018, by Samuel Williams. All rights reserved. +## Copyright, 2018, by Samuel Williams. ## +#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) +.align 2 +.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer),%function +.syntax unified -.globl coroutine_transfer -coroutine_transfer: +PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # Save caller state (8 registers + return address) push {r4-r11,lr} - + # Save caller stack pointer str sp, [r0] - + # Restore callee stack pointer ldr sp, [r1] - + # Restore callee state (8 registers program counter) pop {r4-r11,pc} + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/ruby/coroutine/arm32/Context.h b/ruby/coroutine/arm32/Context.h index e29fe1bb6..09410eb25 100644 --- a/ruby/coroutine/arm32/Context.h +++ b/ruby/coroutine/arm32/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_ARM32_CONTEXT_H +#define COROUTINE_ARM32_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 10/5/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __attribute__((noreturn)) void @@ -18,6 +23,7 @@ enum {COROUTINE_REGISTERS = 8}; struct coroutine_context { void **stack_pointer; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -49,3 +55,5 @@ struct coroutine_context * coroutine_transfer(struct coroutine_context * current static inline void coroutine_destroy(struct coroutine_context * context) { } + +#endif /* COROUTINE_ARM32_CONTEXT_H */ diff --git a/ruby/coroutine/arm64/Context.S b/ruby/coroutine/arm64/Context.S index f6e5f0a6b..07d50d30d 100644 --- a/ruby/coroutine/arm64/Context.S +++ b/ruby/coroutine/arm64/Context.S @@ -2,18 +2,28 @@ ## This file is part of the "Coroutine" project and released under the MIT License. ## ## Created by Samuel Williams on 10/5/2018. -## Copyright, 2018, by Samuel Williams. All rights reserved. +## Copyright, 2018, by Samuel Williams. ## +#define TOKEN_PASTE(x,y) x##y +#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) + +#if defined(__APPLE__) +#define x29 fp +#define x30 lr +.text +.p2align 2 +#else .text .align 2 +#endif -.global coroutine_transfer -coroutine_transfer: +.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # Make space on the stack for caller registers sub sp, sp, 0xb0 - + # Save caller registers stp d8, d9, [sp, 0x00] stp d10, d11, [sp, 0x10] @@ -57,3 +67,7 @@ coroutine_transfer: # Jump to return address (in x4) ret x4 + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/ruby/coroutine/arm64/Context.h b/ruby/coroutine/arm64/Context.h index a1ae92114..dbc6ac94f 100644 --- a/ruby/coroutine/arm64/Context.h +++ b/ruby/coroutine/arm64/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_ARM64_CONTEXT_H +#define COROUTINE_ARM64_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 10/5/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __attribute__((noreturn)) void @@ -17,6 +22,7 @@ enum {COROUTINE_REGISTERS = 0xb0 / 8}; struct coroutine_context { void **stack_pointer; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -48,3 +54,5 @@ struct coroutine_context * coroutine_transfer(struct coroutine_context * current static inline void coroutine_destroy(struct coroutine_context * context) { } + +#endif /* COROUTINE_ARM64_CONTEXT_H */ diff --git a/ruby/coroutine/copy/Context.c b/ruby/coroutine/copy/Context.c deleted file mode 100644 index a1b8a7120..000000000 --- a/ruby/coroutine/copy/Context.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of the "Coroutine" project and released under the MIT License. - * - * Created by Samuel Williams on 24/6/2019. - * Copyright, 2019, by Samuel Williams. All rights reserved. -*/ - -#include "Context.h" - -// http://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html -#ifndef __GNUC__ -#define __asm__ asm -#endif - -#if defined(__sparc) -__attribute__((noinline)) -// https://marc.info/?l=linux-sparc&m=131914569320660&w=2 -static void coroutine_flush_register_windows() { - __asm__ -#ifdef __GNUC__ - __volatile__ -#endif -#if defined(__sparcv9) || defined(__sparc_v9__) || defined(__arch64__) -#ifdef __GNUC__ - ("flushw" : : : "%o7") -#else - ("flushw") -#endif -#else - ("ta 0x03") -#endif - ; -} -#else -static void coroutine_flush_register_windows() {} -#endif - -int coroutine_save_stack(struct coroutine_context * context) { - void *stack_pointer = &stack_pointer; - - assert(context->stack); - assert(context->base); - - // At this point, you may need to ensure on architectures that use register windows, that all registers are flushed to the stack. - coroutine_flush_register_windows(); - - // Save stack to private area: - if (stack_pointer < context->base) { - size_t size = (char*)context->base - (char*)stack_pointer; - assert(size <= context->size); - - memcpy(context->stack, stack_pointer, size); - context->used = size; - } else { - size_t size = (char*)stack_pointer - (char*)context->base; - assert(size <= context->size); - - memcpy(context->stack, context->base, size); - context->used = size; - } - - // Save registers / restore point: - return _setjmp(context->state); -} - -__attribute__((noreturn, noinline)) -static void coroutine_restore_stack_padded(struct coroutine_context *context, void * buffer) { - void *stack_pointer = &stack_pointer; - - assert(context->base); - - // Restore stack from private area: - if (stack_pointer < context->base) { - void * bottom = (char*)context->base - context->used; - assert(bottom > stack_pointer); - - memcpy(bottom, context->stack, context->used); - } else { - void * top = (char*)context->base + context->used; - assert(top < stack_pointer); - - memcpy(context->base, context->stack, context->used); - } - - // Restore registers: - // The `| (int)buffer` is to force the compiler NOT to elide he buffer and `alloca`. - _longjmp(context->state, 1 | (int)buffer); -} - -static const size_t GAP = 128; - -// In order to swap between coroutines, we need to swap the stack and registers. -// `setjmp` and `longjmp` are able to swap registers, but what about swapping stacks? You can use `memcpy` to copy the current stack to a private area and `memcpy` to copy the private stack of the next coroutine to the main stack. -// But if the stack yop are copying in to the main stack is bigger than the currently executing stack, the `memcpy` will clobber the current stack frame (including the context argument). So we use `alloca` to push the current stack frame *beyond* the stack we are about to copy in. This ensures the current stack frame in `coroutine_restore_stack_padded` remains valid for calling `longjmp`. -__attribute__((noreturn)) -void coroutine_restore_stack(struct coroutine_context *context) { - void *stack_pointer = &stack_pointer; - void *buffer = NULL; - ssize_t offset = 0; - - // We must ensure that the next stack frame is BEYOND the stack we are restoring: - if (stack_pointer < context->base) { - offset = (char*)stack_pointer - ((char*)context->base - context->used) + GAP; - if (offset > 0) buffer = alloca(offset); - } else { - offset = ((char*)context->base + context->used) - (char*)stack_pointer + GAP; - if (offset > 0) buffer = alloca(offset); - } - - assert(context->used > 0); - - coroutine_restore_stack_padded(context, buffer); -} - -struct coroutine_context *coroutine_transfer(struct coroutine_context *current, struct coroutine_context *target) -{ - struct coroutine_context *previous = target->from; - - // In theory, either this condition holds true, or we should assign the base address to target: - assert(current->base == target->base); - // If you are trying to copy the coroutine to a different thread - // target->base = current->base - - target->from = current; - - assert(current != target); - - // It's possible to come here, even thought the current fiber has been terminated. We are never going to return so we don't bother saving the stack. - - if (current->stack) { - if (coroutine_save_stack(current) == 0) { - coroutine_restore_stack(target); - } - } else { - coroutine_restore_stack(target); - } - - target->from = previous; - - return target; -} diff --git a/ruby/coroutine/copy/Context.h b/ruby/coroutine/copy/Context.h deleted file mode 100644 index 1319f55d1..000000000 --- a/ruby/coroutine/copy/Context.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of the "Coroutine" project and released under the MIT License. - * - * Created by Samuel Williams on 27/6/2019. - * Copyright, 2019, by Samuel Williams. All rights reserved. -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include - -#define COROUTINE __attribute__((noreturn)) void - -#if INTPTR_MAX <= INT32_MAX -#define COROUTINE_LIMITED_ADDRESS_SPACE -#endif - -// This stack copying implementation which uses a private stack for each coroutine, including the main one. -#define COROUTINE_PRIVATE_STACK - -struct coroutine_context -{ - // Private stack: - void *stack; - size_t size, used; - - // The top (or bottom) of the currently executing stack: - void *base; - - jmp_buf state; - - struct coroutine_context *from; -}; - -typedef COROUTINE(*coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); - -int coroutine_save_stack(struct coroutine_context * context); -COROUTINE coroutine_restore_stack(struct coroutine_context *context); - -// @param stack The private stack area memory allocation (pointer to lowest address). -// @param size The size of the private stack area. -// @param base A stack pointer to the base of the main stack. On x86 hardware, this is the upper extent of the region that will be copied to the private stack. -static inline void coroutine_initialize_main(struct coroutine_context *context, void *stack, size_t size, void *base) { - assert(stack); - assert(size >= 1024); - - context->stack = stack; - context->size = size; - context->used = 0; - - assert(base); - context->base = base; - - context->from = NULL; -} - -// @param start The start function to invoke. -static inline void coroutine_initialize( - struct coroutine_context *context, - coroutine_start start, - void *stack, - size_t size, - void *base -) { - assert(start); - - coroutine_initialize_main(context, stack, size, base); - - if (coroutine_save_stack(context)) { - start(context->from, context); - } -} - -struct coroutine_context *coroutine_transfer(struct coroutine_context *current, register struct coroutine_context *target); - -static inline void coroutine_destroy(struct coroutine_context *context) -{ - context->stack = NULL; - context->size = 0; - context->from = NULL; -} diff --git a/ruby/coroutine/emscripten/Context.c b/ruby/coroutine/emscripten/Context.c new file mode 100644 index 000000000..75c088daa --- /dev/null +++ b/ruby/coroutine/emscripten/Context.c @@ -0,0 +1,8 @@ +#include "Context.h" + +void coroutine_trampoline(void * _context) +{ + struct coroutine_context * context = _context; + + context->entry_func(context->from, context); +} diff --git a/ruby/coroutine/emscripten/Context.h b/ruby/coroutine/emscripten/Context.h new file mode 100644 index 000000000..361e24168 --- /dev/null +++ b/ruby/coroutine/emscripten/Context.h @@ -0,0 +1,77 @@ +#ifndef COROUTINE_EMSCRIPTEN_CONTEXT_H +#define COROUTINE_EMSCRIPTEN_CONTEXT_H 1 + +/* An experimental coroutine wrapper for emscripten + * Contact on Yusuke Endoh if you encounter any problem about this + */ + +#pragma once + +#include +#include +#include + +#define COROUTINE __attribute__((noreturn)) void + +#if INTPTR_MAX <= INT32_MAX +#define COROUTINE_LIMITED_ADDRESS_SPACE +#endif + +struct coroutine_context; + +typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); + +struct coroutine_context +{ + emscripten_fiber_t state; + coroutine_start entry_func; + struct coroutine_context * from; + void *argument; +}; + +COROUTINE coroutine_trampoline(void * _context); + +#define MAIN_ASYNCIFY_STACK_SIZE 65536 +static inline void coroutine_initialize_main(struct coroutine_context * context) { + static char asyncify_stack[MAIN_ASYNCIFY_STACK_SIZE]; + emscripten_fiber_init_from_current_context(&context->state, asyncify_stack, MAIN_ASYNCIFY_STACK_SIZE); +} +#undef MAIN_ASYNCIFY_STACK_SIZE + +static inline void coroutine_initialize( + struct coroutine_context *context, + coroutine_start start, + void *stack, + size_t size +) { + assert(start && stack && size >= 1024); + + uintptr_t addr = (uintptr_t)stack; + size_t offset = addr & 0xF; + void *c_stack = (void*)((addr + 0xF) & ~0xF); + size -= offset; + size_t c_stack_size = (size / 2) & ~0xF; + void *asyncify_stack = (void*)((uintptr_t)c_stack + c_stack_size); + size_t asyncify_stack_size = size - c_stack_size; + context->entry_func = start; + + emscripten_fiber_init(&context->state, coroutine_trampoline, context, c_stack, c_stack_size, asyncify_stack, asyncify_stack_size); +} + +static inline struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target) +{ + struct coroutine_context * previous = target->from; + + target->from = current; + emscripten_fiber_swap(¤t->state, &target->state); + target->from = previous; + + return target; +} + +static inline void coroutine_destroy(struct coroutine_context * context) +{ + context->from = NULL; +} + +#endif /* COROUTINE_EMSCRIPTEN_CONTEXT_H */ diff --git a/ruby/coroutine/ppc64le/Context.S b/ruby/coroutine/ppc64le/Context.S index 1b39086f8..61be9efcf 100644 --- a/ruby/coroutine/ppc64le/Context.S +++ b/ruby/coroutine/ppc64le/Context.S @@ -1,9 +1,12 @@ +#define TOKEN_PASTE(x,y) x##y +#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) + .text .align 2 -.globl coroutine_transfer -.type coroutine_transfer, @function -coroutine_transfer: +.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer), @function +PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # Make space on the stack for caller registers addi 1,1,-152 diff --git a/ruby/coroutine/ppc64le/Context.h b/ruby/coroutine/ppc64le/Context.h index adf21b4fd..fbfaa2ee6 100644 --- a/ruby/coroutine/ppc64le/Context.h +++ b/ruby/coroutine/ppc64le/Context.h @@ -1,6 +1,11 @@ +#ifndef COROUTINE_PPC64LE_CONTEXT_H +#define COROUTINE_PPC64LE_CONTEXT_H 1 + #pragma once #include +#include +#include #include #define COROUTINE __attribute__((noreturn)) void @@ -14,6 +19,7 @@ enum { struct coroutine_context { void **stack_pointer; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -47,3 +53,5 @@ static inline void coroutine_destroy(struct coroutine_context * context) { context->stack_pointer = NULL; } + +#endif /* COROUTINE_PPC64LE_CONTEXT_H */ diff --git a/ruby/coroutine/pthread/Context.c b/ruby/coroutine/pthread/Context.c new file mode 100644 index 000000000..38774cda0 --- /dev/null +++ b/ruby/coroutine/pthread/Context.c @@ -0,0 +1,272 @@ +/* + * This file is part of the "Coroutine" project and released under the MIT License. + * + * Created by Samuel Williams on 24/6/2021. + * Copyright, 2021, by Samuel Williams. +*/ + +#include "Context.h" +#include +#include +#include + +static const int DEBUG = 0; + +static +int check(const char * message, int result) { + if (result) { + switch (result) { + case EDEADLK: + if (DEBUG) fprintf(stderr, "deadlock detected result=%d errno=%d\n", result, errno); + break; + default: + if (DEBUG) fprintf(stderr, "error detected result=%d errno=%d\n", result, errno); + perror(message); + } + } + + assert(result == 0); + + return result; +} + +void coroutine_initialize_main(struct coroutine_context * context) { + context->id = pthread_self(); + + check("coroutine_initialize_main:pthread_cond_init", + pthread_cond_init(&context->schedule, NULL) + ); + + context->shared = (struct coroutine_shared*)malloc(sizeof(struct coroutine_shared)); + assert(context->shared); + + context->shared->main = context; + context->shared->count = 1; + + if (DEBUG) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + + check("coroutine_initialize_main:pthread_mutex_init", + pthread_mutex_init(&context->shared->guard, &attr) + ); + } else { + check("coroutine_initialize_main:pthread_mutex_init", + pthread_mutex_init(&context->shared->guard, NULL) + ); + } +} + +static +void coroutine_release(struct coroutine_context *context) { + if (context->shared) { + size_t count = (context->shared->count -= 1); + + if (count == 0) { + if (DEBUG) fprintf(stderr, "coroutine_release:pthread_mutex_destroy(%p)\n", &context->shared->guard); + pthread_mutex_destroy(&context->shared->guard); + free(context->shared); + } + + context->shared = NULL; + + if (DEBUG) fprintf(stderr, "coroutine_release:pthread_cond_destroy(%p)\n", &context->schedule); + pthread_cond_destroy(&context->schedule); + } +} + +void coroutine_initialize( + struct coroutine_context *context, + coroutine_start start, + void *stack, + size_t size +) { + assert(start && stack && size >= 1024); + + // We will create the thread when we first transfer, but save the details now: + context->shared = NULL; + context->start = start; + context->stack = stack; + context->size = size; +} + +static +int is_locked(pthread_mutex_t * mutex) { + int result = pthread_mutex_trylock(mutex); + + // If we could successfully lock the mutex: + if (result == 0) { + pthread_mutex_unlock(mutex); + // We could lock the mutex, so it wasn't locked: + return 0; + } else { + // Otherwise we couldn't lock it because it's already locked: + return 1; + } +} + +static +void coroutine_guard_unlock(void * _context) +{ + struct coroutine_context * context = _context; + + if (DEBUG) fprintf(stderr, "coroutine_guard_unlock:pthread_mutex_unlock\n"); + + check("coroutine_guard_unlock:pthread_mutex_unlock", + pthread_mutex_unlock(&context->shared->guard) + ); +} + +static +void coroutine_wait(struct coroutine_context *context) +{ + if (DEBUG) fprintf(stderr, "coroutine_wait:pthread_mutex_lock(guard=%p is_locked=%d)\n", &context->shared->guard, is_locked(&context->shared->guard)); + check("coroutine_wait:pthread_mutex_lock", + pthread_mutex_lock(&context->shared->guard) + ); + + if (DEBUG) fprintf(stderr, "coroutine_wait:pthread_mutex_unlock(guard)\n"); + pthread_mutex_unlock(&context->shared->guard); +} + +static +void coroutine_trampoline_cleanup(void *_context) { + struct coroutine_context * context = _context; + coroutine_release(context); +} + +void * coroutine_trampoline(void * _context) +{ + struct coroutine_context * context = _context; + assert(context->shared); + + pthread_cleanup_push(coroutine_trampoline_cleanup, context); + + coroutine_wait(context); + + context->start(context->from, context); + + pthread_cleanup_pop(1); + + return NULL; +} + +static +int coroutine_create_thread(struct coroutine_context *context) +{ + int result; + + pthread_attr_t attr; + result = pthread_attr_init(&attr); + if (result != 0) { + return result; + } + + result = pthread_attr_setstack(&attr, context->stack, (size_t)context->size); + if (result != 0) { + pthread_attr_destroy(&attr); + return result; + } + + result = pthread_cond_init(&context->schedule, NULL); + if (result != 0) { + pthread_attr_destroy(&attr); + return result; + } + + result = pthread_create(&context->id, &attr, coroutine_trampoline, context); + if (result != 0) { + pthread_attr_destroy(&attr); + if (DEBUG) fprintf(stderr, "coroutine_create_thread:pthread_cond_destroy(%p)\n", &context->schedule); + pthread_cond_destroy(&context->schedule); + return result; + } + + context->shared->count += 1; + + return result; +} + +struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target) +{ + assert(current->shared); + + struct coroutine_context * previous = target->from; + target->from = current; + + if (DEBUG) fprintf(stderr, "coroutine_transfer:pthread_mutex_lock(guard=%p is_locked=%d)\n", ¤t->shared->guard, is_locked(¤t->shared->guard)); + pthread_mutex_lock(¤t->shared->guard); + pthread_cleanup_push(coroutine_guard_unlock, current); + + // First transfer: + if (target->shared == NULL) { + target->shared = current->shared; + + if (DEBUG) fprintf(stderr, "coroutine_transfer:coroutine_create_thread...\n"); + if (coroutine_create_thread(target)) { + if (DEBUG) fprintf(stderr, "coroutine_transfer:coroutine_create_thread failed\n"); + target->shared = NULL; + target->from = previous; + return NULL; + } + } else { + if (DEBUG) fprintf(stderr, "coroutine_transfer:pthread_cond_signal(target)\n"); + pthread_cond_signal(&target->schedule); + } + + // A side effect of acting upon a cancellation request while in a condition wait is that the mutex is (in effect) re-acquired before calling the first cancellation cleanup handler. If cancelled, pthread_cond_wait immediately invokes cleanup handlers. + if (DEBUG) fprintf(stderr, "coroutine_transfer:pthread_cond_wait(schedule=%p, guard=%p, is_locked=%d)\n", ¤t->schedule, ¤t->shared->guard, is_locked(¤t->shared->guard)); + check("coroutine_transfer:pthread_cond_wait", + pthread_cond_wait(¤t->schedule, ¤t->shared->guard) + ); + + if (DEBUG) fprintf(stderr, "coroutine_transfer:pthread_cleanup_pop\n"); + pthread_cleanup_pop(1); + +#ifdef __FreeBSD__ + // Apparently required for FreeBSD: + pthread_testcancel(); +#endif + + target->from = previous; + + return target; +} + +static +void coroutine_join(struct coroutine_context * context) { + if (DEBUG) fprintf(stderr, "coroutine_join:pthread_cancel\n"); + int result = pthread_cancel(context->id); + if (result == -1 && errno == ESRCH) { + // The thread may be dead due to fork, so it cannot be joined and this doesn't represent a real error: + return; + } + + check("coroutine_join:pthread_cancel", result); + + if (DEBUG) fprintf(stderr, "coroutine_join:pthread_join\n"); + check("coroutine_join:pthread_join", + pthread_join(context->id, NULL) + ); + + if (DEBUG) fprintf(stderr, "coroutine_join:pthread_join done\n"); +} + +void coroutine_destroy(struct coroutine_context * context) +{ + if (DEBUG) fprintf(stderr, "coroutine_destroy\n"); + + assert(context); + + // We are already destroyed or never created: + if (context->shared == NULL) return; + + if (context == context->shared->main) { + context->shared->main = NULL; + coroutine_release(context); + } else { + coroutine_join(context); + assert(context->shared == NULL); + } +} diff --git a/ruby/coroutine/pthread/Context.h b/ruby/coroutine/pthread/Context.h new file mode 100644 index 000000000..6d551ee9d --- /dev/null +++ b/ruby/coroutine/pthread/Context.h @@ -0,0 +1,63 @@ +/* + * This file is part of the "Coroutine" project and released under the MIT License. + * + * Created by Samuel Williams on 24/6/2021. + * Copyright, 2021, by Samuel Williams. +*/ + +#pragma once + +#include +#include +#include + +#define COROUTINE void + +#define COROUTINE_PTHREAD_CONTEXT + +#ifdef HAVE_STDINT_H +#include +#if INTPTR_MAX <= INT32_MAX +#define COROUTINE_LIMITED_ADDRESS_SPACE +#endif +#endif + +struct coroutine_context; + +struct coroutine_shared +{ + pthread_mutex_t guard; + struct coroutine_context * main; + + size_t count; +}; + +typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); + +struct coroutine_context +{ + struct coroutine_shared * shared; + + coroutine_start start; + void *argument; + + void *stack; + size_t size; + + pthread_t id; + pthread_cond_t schedule; + struct coroutine_context * from; +}; + +void coroutine_initialize_main(struct coroutine_context * context); + +void coroutine_initialize( + struct coroutine_context *context, + coroutine_start start, + void *stack, + size_t size +); + +struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); + +void coroutine_destroy(struct coroutine_context * context); diff --git a/ruby/coroutine/riscv64/Context.S b/ruby/coroutine/riscv64/Context.S new file mode 100644 index 000000000..cc4e872f8 --- /dev/null +++ b/ruby/coroutine/riscv64/Context.S @@ -0,0 +1,87 @@ +#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): + + # Make space on the stack for caller registers + addi sp, sp, -0xd0 + + # Save caller registers + sd s0, 0x00(sp) + sd s1, 0x08(sp) + sd s2, 0x10(sp) + sd s3, 0x18(sp) + sd s4, 0x20(sp) + sd s5, 0x28(sp) + sd s6, 0x30(sp) + sd s7, 0x38(sp) + sd s8, 0x40(sp) + sd s9, 0x48(sp) + sd s10, 0x50(sp) + sd s11, 0x58(sp) + fsd fs0, 0x60(sp) + fsd fs1, 0x68(sp) + fsd fs2, 0x70(sp) + fsd fs3, 0x78(sp) + fsd fs4, 0x80(sp) + fsd fs5, 0x88(sp) + fsd fs6, 0x90(sp) + fsd fs7, 0x98(sp) + fsd fs8, 0xa0(sp) + fsd fs9, 0xa8(sp) + fsd fs10, 0xb0(sp) + fsd fs11, 0xb8(sp) + + # Save return address + sd ra, 0xc0(sp) + + # Save stack pointer to a0 (first argument) + mv a2, sp + sd a2, (a0) + + # Load stack pointer from a1 (second argument) + ld a3, (a1) + mv sp, a3 + + # Restore caller registers + ld s0, 0x00(sp) + ld s1, 0x08(sp) + ld s2, 0x10(sp) + ld s3, 0x18(sp) + ld s4, 0x20(sp) + ld s5, 0x28(sp) + ld s6, 0x30(sp) + ld s7, 0x38(sp) + ld s8, 0x40(sp) + ld s9, 0x48(sp) + ld s10, 0x50(sp) + ld s11, 0x58(sp) + fld fs0, 0x60(sp) + fld fs1, 0x68(sp) + fld fs2, 0x70(sp) + fld fs3, 0x78(sp) + fld fs4, 0x80(sp) + fld fs5, 0x88(sp) + fld fs6, 0x90(sp) + fld fs7, 0x98(sp) + fld fs8, 0xa0(sp) + fld fs9, 0xa8(sp) + fld fs10, 0xb0(sp) + fld fs11, 0xb8(sp) + + # Load return address + ld ra, 0xc0(sp) + + # Pop stack frame + addi sp, sp, 0xd0 + + # Jump to return address + ret + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/ruby/coroutine/riscv64/Context.h b/ruby/coroutine/riscv64/Context.h new file mode 100644 index 000000000..9ce1140e0 --- /dev/null +++ b/ruby/coroutine/riscv64/Context.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include + +#define COROUTINE __attribute__((noreturn)) void + +enum {COROUTINE_REGISTERS = 0xd0 / 8}; + +struct coroutine_context +{ + void **stack_pointer; + void *argument; +}; + +typedef COROUTINE(* 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 coroutine_initialize( + struct coroutine_context *context, + coroutine_start start, + void *stack, + size_t size +) { + assert(start && stack && size >= 1024); + + // Stack grows down. Force 16-byte alignment. + char * top = (char*)stack + size; + context->stack_pointer = (void**)((uintptr_t)top & ~0xF); + + context->stack_pointer -= COROUTINE_REGISTERS; + memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); + + context->stack_pointer[0xc0 / 8] = (void*)start; +} + +struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); + +static inline void coroutine_destroy(struct coroutine_context * context) +{ +} diff --git a/ruby/coroutine/ucontext/Context.c b/ruby/coroutine/ucontext/Context.c index eec4ef395..5d728d554 100644 --- a/ruby/coroutine/ucontext/Context.c +++ b/ruby/coroutine/ucontext/Context.c @@ -2,7 +2,7 @@ * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 24/6/2019. - * Copyright, 2019, by Samuel Williams. All rights reserved. + * Copyright, 2019, by Samuel Williams. */ /* According to Solaris' ucontext.h, makecontext, etc. are removed in SUSv4. @@ -11,11 +11,12 @@ #if defined(__sun) && !defined(__EXTENSIONS__) #define __EXTENSIONS__ #endif + #include "Context.h" void coroutine_trampoline(void * _start, void * _context) { - coroutine_start start = _start; + coroutine_start start = (coroutine_start)_start; struct coroutine_context * context = _context; start(context->from, context); diff --git a/ruby/coroutine/ucontext/Context.h b/ruby/coroutine/ucontext/Context.h index 6cf16c860..d338d8de6 100644 --- a/ruby/coroutine/ucontext/Context.h +++ b/ruby/coroutine/ucontext/Context.h @@ -1,8 +1,11 @@ +#ifndef COROUTINE_UCONTEXT_CONTEXT_H +#define COROUTINE_UCONTEXT_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 24/6/2019. - * Copyright, 2019, by Samuel Williams. All rights reserved. + * Copyright, 2019, by Samuel Williams. */ #pragma once @@ -13,14 +16,18 @@ #define COROUTINE __attribute__((noreturn)) void +#ifdef HAVE_STDINT_H +#include #if INTPTR_MAX <= INT32_MAX #define COROUTINE_LIMITED_ADDRESS_SPACE #endif +#endif struct coroutine_context { ucontext_t state; struct coroutine_context * from; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -68,3 +75,5 @@ static inline void coroutine_destroy(struct coroutine_context * context) context->state.uc_stack.ss_size = 0; context->from = NULL; } + +#endif /* COROUTINE_UCONTEXT_CONTEXT_H */ diff --git a/ruby/coroutine/universal/Context.S b/ruby/coroutine/universal/Context.S new file mode 100644 index 000000000..0fd8c01e7 --- /dev/null +++ b/ruby/coroutine/universal/Context.S @@ -0,0 +1,12 @@ +#if 0 +#elif defined __x86_64__ +# include "coroutine/amd64/Context.S" +#elif defined __i386__ +# include "coroutine/x86/Context.S" +#elif defined __ppc64__ +# include "coroutine/ppc64le/Context.S" +#elif defined __arm64__ +# include "coroutine/arm64/Context.S" +#else +# error "Unsupported CPU" +#endif diff --git a/ruby/coroutine/universal/Context.h b/ruby/coroutine/universal/Context.h new file mode 100644 index 000000000..9a2ef425d --- /dev/null +++ b/ruby/coroutine/universal/Context.h @@ -0,0 +1,17 @@ +#ifndef COROUTINE_UNIVERSAL_CONTEXT_H +#define COROUTINE_UNIVERSAL_CONTEXT_H 1 + +#if 0 +#elif defined __x86_64__ +# include "coroutine/amd64/Context.h" +#elif defined __i386__ +# include "coroutine/x86/Context.h" +#elif defined __ppc64__ +# include "coroutine/ppc64le/Context.h" +#elif defined __arm64__ +# include "coroutine/arm64/Context.h" +#else +# error "Unsupported CPU" +#endif + +#endif /* COROUTINE_UNIVERSAL_CONTEXT_H */ diff --git a/ruby/coroutine/win32/Context.asm b/ruby/coroutine/win32/Context.asm index 2647ea4bc..f8f431239 100644 --- a/ruby/coroutine/win32/Context.asm +++ b/ruby/coroutine/win32/Context.asm @@ -2,7 +2,7 @@ ;; This file is part of the "Coroutine" project and released under the MIT License. ;; ;; Created by Samuel Williams on 10/5/2018. -;; Copyright, 2018, by Samuel Williams. All rights reserved. +;; Copyright, 2018, by Samuel Williams. ;; .386 diff --git a/ruby/coroutine/win32/Context.h b/ruby/coroutine/win32/Context.h index 299515ed9..902fd1246 100644 --- a/ruby/coroutine/win32/Context.h +++ b/ruby/coroutine/win32/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_WIN32_CONTEXT_H +#define COROUTINE_WIN32_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 10/5/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __declspec(noreturn) void __fastcall @@ -19,6 +24,7 @@ enum {COROUTINE_REGISTERS = 4}; struct coroutine_context { void **stack_pointer; + void *argument; }; typedef void(__fastcall * coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -55,3 +61,5 @@ struct coroutine_context * __fastcall coroutine_transfer(struct coroutine_contex static inline void coroutine_destroy(struct coroutine_context * context) { } + +#endif /* COROUTINE_WIN32_CONTEXT_H */ diff --git a/ruby/coroutine/win64/Context.S b/ruby/coroutine/win64/Context.S index 4b16e0ce8..e0ee38e00 100644 --- a/ruby/coroutine/win64/Context.S +++ b/ruby/coroutine/win64/Context.S @@ -2,7 +2,7 @@ ## This file is part of the "Coroutine" project and released under the MIT License. ## ## Created by Samuel Williams on 4/11/2018. -## Copyright, 2018, by Samuel Williams. All rights reserved. +## Copyright, 2018, by Samuel Williams. ## .text diff --git a/ruby/coroutine/win64/Context.asm b/ruby/coroutine/win64/Context.asm index 59673ffa3..8c4dea1c9 100644 --- a/ruby/coroutine/win64/Context.asm +++ b/ruby/coroutine/win64/Context.asm @@ -2,7 +2,7 @@ ;; This file is part of the "Coroutine" project and released under the MIT License. ;; ;; Created by Samuel Williams on 10/5/2018. -;; Copyright, 2018, by Samuel Williams. All rights reserved. +;; Copyright, 2018, by Samuel Williams. ;; .code diff --git a/ruby/coroutine/win64/Context.h b/ruby/coroutine/win64/Context.h index 6bf2dc5b3..aaa4caeaf 100644 --- a/ruby/coroutine/win64/Context.h +++ b/ruby/coroutine/win64/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_WIN64_CONTEXT_H +#define COROUTINE_WIN64_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 10/5/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __declspec(noreturn) void @@ -20,6 +25,7 @@ enum { struct coroutine_context { void **stack_pointer; + void *argument; }; typedef void(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); @@ -65,3 +71,5 @@ struct coroutine_context * coroutine_transfer(struct coroutine_context * current static inline void coroutine_destroy(struct coroutine_context * context) { } + +#endif /* COROUTINE_WIN64_CONTEXT_H */ diff --git a/ruby/coroutine/x86/Context.S b/ruby/coroutine/x86/Context.S index 001b699a3..f06a41708 100644 --- a/ruby/coroutine/x86/Context.S +++ b/ruby/coroutine/x86/Context.S @@ -2,7 +2,7 @@ ## This file is part of the "Coroutine" project and released under the MIT License. ## ## Created by Samuel Williams on 3/11/2018. -## Copyright, 2018, by Samuel Williams. All rights reserved. +## Copyright, 2018, by Samuel Williams. ## #define TOKEN_PASTE(x,y) x##y @@ -37,6 +37,6 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # Jump to the address on the stack ret -#if defined(__linux__) && defined(__ELF__) +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif diff --git a/ruby/coroutine/x86/Context.h b/ruby/coroutine/x86/Context.h index 6d3a56eaa..d98eaf648 100644 --- a/ruby/coroutine/x86/Context.h +++ b/ruby/coroutine/x86/Context.h @@ -1,13 +1,18 @@ +#ifndef COROUTINE_X86_CONTEXT_H +#define COROUTINE_X86_CONTEXT_H 1 + /* * This file is part of the "Coroutine" project and released under the MIT License. * * Created by Samuel Williams on 3/11/2018. - * Copyright, 2018, by Samuel Williams. All rights reserved. + * Copyright, 2018, by Samuel Williams. */ #pragma once #include +#include +#include #include #define COROUTINE __attribute__((noreturn, fastcall)) void @@ -18,6 +23,7 @@ enum {COROUTINE_REGISTERS = 4}; struct coroutine_context { void **stack_pointer; + void *argument; }; typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self) __attribute__((fastcall)); @@ -51,3 +57,5 @@ static inline void coroutine_destroy(struct coroutine_context * context) { context->stack_pointer = NULL; } + +#endif /* COROUTINE_X86_CONTEXT_H */ diff --git a/ruby/coverage/README b/ruby/coverage/README index 78a01826a..a4c3dfcb0 100644 --- a/ruby/coverage/README +++ b/ruby/coverage/README @@ -13,5 +13,5 @@ Limitation TODO - * more reduce bundled simplecov(additional configuration, formatter, etc) + * more reduce bundled simplecov(additional configuration, formatter, etc.) * measure rubyspec coverage diff --git a/ruby/cygwin/GNUmakefile.in b/ruby/cygwin/GNUmakefile.in index 192cf43b3..b13c3d9c8 100644 --- a/ruby/cygwin/GNUmakefile.in +++ b/ruby/cygwin/GNUmakefile.in @@ -1,8 +1,13 @@ +gnumake = yes + include Makefile ENABLE_SHARED=@ENABLE_SHARED@ DLLWRAP = @DLLWRAP@ --target=@target_os@ --driver-name="$(CC)" -WINDRES = @WINDRES@ --preprocessor="$(CPP) -xc" -DRC_INVOKED +windres-cpp := $(CPP) -xc +windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \ + $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp))) +WINDRES = @WINDRES@ $(windres-cpp) -DRC_INVOKED STRIP = @STRIP@ ifeq (@target_os@,cygwin) @@ -11,6 +16,9 @@ else DLL_BASE_NAME := $(RUBY_SO_NAME) DLLWRAP += -mno-cygwin VPATH := $(VPATH):$(srcdir)/win32 + ifneq ($(filter -flto%,$(LDFLAGS)),) + miniruby$(EXEEXT): XLDFLAGS += -Wno-maybe-uninitialized + endif endif ifneq ($(ENABLE_SHARED),yes) @@ -28,9 +36,7 @@ endif WPROGRAM = $(RUBYW_INSTALL_NAME)$(EXEEXT) --include uncommon.mk - -include $(srcdir)/defs/gmake.mk +include $(srcdir)/template/GNUmakefile.in SOLIBS := $(DLL_BASE_NAME).res.@OBJEXT@ $(SOLIBS) override EXTOBJS += $(if $(filter-out $(RUBYW_INSTALL_NAME),$(@:$(EXEEXT)=)),$(RUBY_INSTALL_NAME),$(@:$(EXEEXT)=)).res.$(OBJEXT) @@ -94,13 +100,5 @@ $(RUBYDEF): $(LIBRUBY_A) $(PREP) $(RBCONFIG) clean-local:: @$(RM) $(RUBYDEF) - -ifeq (@target_os@,cygwin) -cygwin-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR)0.dll: $(LIBRUBY_A) $(RUBYDEF) - $(ECHO) generating $@ - $(Q) @DLLWRAP@ -s --def=$(RUBYDEF) -o $@ -endif - -clean-local:: @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@) @$(RM) $(RCFILES) diff --git a/ruby/darray.h b/ruby/darray.h new file mode 100644 index 000000000..ed6085fbc --- /dev/null +++ b/ruby/darray.h @@ -0,0 +1,198 @@ +#ifndef RUBY_DARRAY_H +#define RUBY_DARRAY_H + +#include +#include +#include + +// 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. +// +// NULL is a valid empty dynamic array. +// +// Example: +// rb_darray(char) char_array = NULL; +// if (!rb_darray_append(&char_array, 'e')) abort(); +// printf("pushed %c\n", *rb_darray_ref(char_array, 0)); +// rb_darray_free(char_array); +// +#define rb_darray(T) struct { rb_darray_meta_t meta; T data[]; } * + +// Copy an element out of the array. Warning: not bounds checked. +// +// T rb_darray_get(rb_darray(T) ary, int32_t idx); +// +#define rb_darray_get(ary, idx) ((ary)->data[(idx)]) + +// Assign to an element. Warning: not bounds checked. +// +// void rb_darray_set(rb_darray(T) ary, int32_t idx, T element); +// +#define rb_darray_set(ary, idx, element) ((ary)->data[(idx)] = (element)) + +// Get a pointer to an element. Warning: not bounds checked. +// +// T *rb_darray_ref(rb_darray(T) ary, int32_t idx); +// +#define rb_darray_ref(ary, idx) (&((ary)->data[(idx)])) + +// Copy a new element into the array. Return 1 on success and 0 on failure. +// ptr_to_ary is evaluated multiple times. +// +// bool rb_darray_append(rb_darray(T) *ptr_to_ary, T element); +// +#define rb_darray_append(ptr_to_ary, element) ( \ + rb_darray_ensure_space((ptr_to_ary), sizeof(**(ptr_to_ary)), sizeof((*(ptr_to_ary))->data[0])) ? ( \ + rb_darray_set(*(ptr_to_ary), \ + (*(ptr_to_ary))->meta.size, \ + (element)), \ + ++((*(ptr_to_ary))->meta.size), \ + 1 \ + ) : 0) + +// Last element of the array +// +#define rb_darray_back(ary) ((ary)->data[(ary)->meta.size - 1]) + +// Remove the last element of the array. +// +#define rb_darray_pop_back(ary) ((ary)->meta.size--) + +// Remove element at idx and replace it by the last element +#define rb_darray_remove_unordered(ary, idx) do { \ + rb_darray_set(ary, idx, rb_darray_back(ary)); \ + rb_darray_pop_back(ary); \ +} while (0); + +// Iterate over items of the array in a for loop +// +#define rb_darray_foreach(ary, idx_name, elem_ptr_var) \ + for (int idx_name = 0; idx_name < rb_darray_size(ary) && ((elem_ptr_var) = rb_darray_ref(ary, idx_name)); ++idx_name) + +// Iterate over valid indicies in the array in a for loop +// +#define rb_darray_for(ary, idx_name) \ + for (int idx_name = 0; idx_name < rb_darray_size(ary); ++idx_name) + +// Make a dynamic array of a certain size. All bytes backing the elements are set to zero. +// Return 1 on success and 0 on failure. +// +// Note that NULL is a valid empty dynamic array. +// +// bool rb_darray_make(rb_darray(T) *ptr_to_ary, int32_t size); +// +#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])) + +// Set the size of the array to zero without freeing the backing memory. +// Allows reusing the same array. +// +#define rb_darray_clear(ary) (ary->meta.size = 0) + +typedef struct rb_darray_meta { + int32_t size; + int32_t capa; +} rb_darray_meta_t; + +// Get the size of the dynamic array. +// +static inline int32_t +rb_darray_size(const void *ary) +{ + const rb_darray_meta_t *meta = ary; + return meta ? meta->size : 0; +} + +// Get the capacity of the dynamic array. +// +static inline int32_t +rb_darray_capa(const void *ary) +{ + const rb_darray_meta_t *meta = ary; + return meta ? meta->capa : 0; +} + +// Free the dynamic array. +// +static inline void +rb_darray_free(void *ary) +{ + free(ary); +} + +// Internal function. Calculate buffer size on malloc heap. +static inline size_t +rb_darray_buffer_size(int32_t capacity, size_t header_size, size_t element_size) +{ + if (capacity == 0) return 0; + return header_size + (size_t)capacity * element_size; +} + +// Internal function +// Ensure there is space for one more element. Return 1 on success and 0 on failure. +// Note: header_size can be bigger than sizeof(rb_darray_meta_t) when T is __int128_t, for example. +static inline int +rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size) +{ + rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary; + rb_darray_meta_t *meta = *ptr_to_ptr_to_meta; + int32_t current_capa = rb_darray_capa(meta); + if (rb_darray_size(meta) < current_capa) return 1; + + int32_t new_capa; + // Calculate new capacity + if (current_capa == 0) { + new_capa = 1; + } + else { + int64_t doubled = 2 * (int64_t)current_capa; + new_capa = (int32_t)doubled; + if (new_capa != doubled) return 0; + } + + // Calculate new buffer size + size_t current_buffer_size = rb_darray_buffer_size(current_capa, header_size, element_size); + size_t new_buffer_size = rb_darray_buffer_size(new_capa, header_size, element_size); + if (new_buffer_size <= current_buffer_size) return 0; + + rb_darray_meta_t *doubled_ary = realloc(meta, new_buffer_size); + if (!doubled_ary) return 0; + + if (meta == NULL) { + // First allocation. Initialize size. On subsequence allocations + // realloc takes care of carrying over the size. + doubled_ary->size = 0; + } + + doubled_ary->capa = new_capa; + + // We don't have access to the type of the dynamic array in function context. + // Write out result with memcpy to avoid strict aliasing issue. + memcpy(ptr_to_ary, &doubled_ary, sizeof(doubled_ary)); + return 1; +} + +static inline int +rb_darray_make_impl(void *ptr_to_ary, int32_t array_size, size_t header_size, size_t element_size) +{ + rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary; + if (array_size < 0) return 0; + if (array_size == 0) { + *ptr_to_ptr_to_meta = NULL; + return 1; + } + + size_t buffer_size = rb_darray_buffer_size(array_size, header_size, element_size); + rb_darray_meta_t *meta = calloc(buffer_size, 1); + if (!meta) return 0; + + meta->size = array_size; + meta->capa = array_size; + + // We don't have access to the type of the dynamic array in function context. + // Write out result with memcpy to avoid strict aliasing issue. + memcpy(ptr_to_ary, &meta, sizeof(meta)); + return 1; +} + +#endif /* RUBY_DARRAY_H */ diff --git a/ruby/debug.c b/ruby/debug.c index a54be2715..a5e6ce475 100644 --- a/ruby/debug.c +++ b/ruby/debug.c @@ -9,15 +9,33 @@ **********************************************************************/ -#include "ruby/ruby.h" +#include "ruby/internal/config.h" + +#include + +#include "eval_intern.h" +#include "encindex.h" +#include "id.h" +#include "internal/signal.h" #include "ruby/encoding.h" #include "ruby/io.h" +#include "ruby/ruby.h" #include "ruby/util.h" -#include "vm_debug.h" -#include "eval_intern.h" -#include "vm_core.h" #include "symbol.h" -#include "id.h" +#include "vm_core.h" +#include "vm_debug.h" +#include "vm_callinfo.h" +#include "ruby/thread_native.h" +#include "ractor_core.h" + +/* This is the only place struct RIMemo is actually used */ +struct RIMemo { + VALUE flags; + VALUE v0; + VALUE v1; + VALUE v2; + VALUE v3; +}; /* for gdb */ const union { @@ -28,13 +46,21 @@ const union { enum ruby_method_ids method_ids; enum ruby_id_types id_types; enum ruby_fl_type fl_types; + enum ruby_fl_ushift fl_ushift; enum ruby_encoding_consts encoding_consts; enum ruby_coderange_type enc_coderange_types; enum ruby_econv_flag_type econv_flag_types; + rb_econv_result_t econv_result; + enum ruby_preserved_encindex encoding_index; enum ruby_robject_flags robject_flags; + enum ruby_robject_consts robject_consts; enum ruby_rmodule_flags rmodule_flags; enum ruby_rstring_flags rstring_flags; +#if !USE_RVARGC + enum ruby_rstring_consts rstring_consts; +#endif enum ruby_rarray_flags rarray_flags; + enum ruby_rarray_consts rarray_consts; enum { RUBY_FMODE_READABLE = FMODE_READABLE, RUBY_FMODE_WRITABLE = FMODE_WRITABLE, @@ -222,8 +248,267 @@ set_debug_option(const char *str, int len, void *arg) } } +#ifdef USE_RUBY_DEBUG_LOG +STATIC_ASSERT(USE_RUBY_DEBUG_LOG, USE_RUBY_DEBUG_LOG ? RUBY_DEVEL : 1); +#endif + +#if RUBY_DEVEL +static void setup_debug_log(void); +#else +#define setup_debug_log() +#endif + void ruby_set_debug_option(const char *str) { ruby_each_words(str, set_debug_option, 0); + setup_debug_log(); +} + +#if RUBY_DEVEL + +// RUBY_DEBUG_LOG features +// See vm_debug.h comments for details. + +#define MAX_DEBUG_LOG 0x1000 +#define MAX_DEBUG_LOG_MESSAGE_LEN 0x0200 +#define MAX_DEBUG_LOG_FILTER 0x0010 + +enum ruby_debug_log_mode ruby_debug_log_mode; + +static struct { + char *mem; + unsigned int cnt; + char filters[MAX_DEBUG_LOG_FILTER][MAX_DEBUG_LOG_FILTER]; + unsigned int filters_num; + rb_nativethread_lock_t lock; + FILE *output; +} debug_log; + +static char * +RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index) +{ + return &debug_log.mem[MAX_DEBUG_LOG_MESSAGE_LEN * index]; +} + +static void +setup_debug_log(void) +{ + // check RUBY_DEBUG_LOG + const char *log_config = getenv("RUBY_DEBUG_LOG"); + if (log_config) { + fprintf(stderr, "RUBY_DEBUG_LOG=%s\n", log_config); + + if (strcmp(log_config, "mem") == 0) { + debug_log.mem = (char *)malloc(MAX_DEBUG_LOG * MAX_DEBUG_LOG_MESSAGE_LEN); + if (debug_log.mem == NULL) { + fprintf(stderr, "setup_debug_log failed (can't allocate memory)\n"); + exit(1); + } + ruby_debug_log_mode |= ruby_debug_log_memory; + } + else if (strcmp(log_config, "stderr") == 0) { + ruby_debug_log_mode |= ruby_debug_log_stderr; + } + else { + ruby_debug_log_mode |= ruby_debug_log_file; + if ((debug_log.output = fopen(log_config, "w")) == NULL) { + fprintf(stderr, "can not open %s for RUBY_DEBUG_LOG\n", log_config); + exit(1); + } + setvbuf(debug_log.output, NULL, _IONBF, 0); + } + + rb_nativethread_lock_initialize(&debug_log.lock); + } + + // check RUBY_DEBUG_LOG_FILTER + const char *filter_config = getenv("RUBY_DEBUG_LOG_FILTER"); + if (filter_config && strlen(filter_config) > 0) { + unsigned int i; + for (i=0; i= MAX_DEBUG_LOG_FILTER) { + fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER); + exit(1); + } + strncpy(debug_log.filters[i], filter_config, MAX_DEBUG_LOG_FILTER - 1); + i++; + break; + } + else { + size_t n = p - filter_config; + if (n >= MAX_DEBUG_LOG_FILTER) { + fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER); + exit(1); + } + strncpy(debug_log.filters[i], filter_config, n); + filter_config = p+1; + } + } + debug_log.filters_num = i; + for (i=0; i 0) { + for (unsigned int i = 0; iractor.cnt); + if (r < 0) rb_bug("ruby_debug_log returns %d\n", r); + len += r; + } + } + + // thread information + if (!rb_thread_alone()) { + const rb_thread_t *th = GET_THREAD(); + if (r && len < MAX_DEBUG_LOG_MESSAGE_LEN) { + r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tth:%p", (void *)th); + if (r < 0) rb_bug("ruby_debug_log returns %d\n", r); + len += r; + } + } + + rb_nativethread_lock_lock(&debug_log.lock); + { + unsigned int cnt = debug_log.cnt++; + + if (ruby_debug_log_mode & ruby_debug_log_memory) { + unsigned int index = cnt % MAX_DEBUG_LOG; + char *dst = RUBY_DEBUG_LOG_MEM_ENTRY(index); + strncpy(dst, buff, MAX_DEBUG_LOG_MESSAGE_LEN); + } + if (ruby_debug_log_mode & ruby_debug_log_stderr) { + fprintf(stderr, "%4u: %s\n", cnt, buff); + } + if (ruby_debug_log_mode & ruby_debug_log_file) { + fprintf(debug_log.output, "%u\t%s\n", cnt, buff); + } + } + rb_nativethread_lock_unlock(&debug_log.lock); +} + +// for debugger +static void +debug_log_dump(FILE *out, unsigned int n) +{ + if (ruby_debug_log_mode & ruby_debug_log_memory) { + unsigned int size = debug_log.cnt > MAX_DEBUG_LOG ? MAX_DEBUG_LOG : debug_log.cnt; + unsigned int current_index = debug_log.cnt % MAX_DEBUG_LOG; + if (n == 0) n = size; + if (n > size) n = size; + + for (unsigned int i=0; i #include +#include "ruby/thread_native.h" #if USE_DEBUG_COUNTER + static const char *const debug_counter_names[] = { "" #define RB_DEBUG_COUNTER(name) #name, @@ -23,8 +25,28 @@ static const char *const debug_counter_names[] = { MJIT_SYMBOL_EXPORT_BEGIN size_t rb_debug_counter[numberof(debug_counter_names)]; +void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add); MJIT_SYMBOL_EXPORT_END +rb_nativethread_lock_t debug_counter_lock; + +__attribute__((constructor)) +static void +debug_counter_setup(void) +{ + rb_nativethread_lock_initialize(&debug_counter_lock); +} + +void +rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add) +{ + rb_nativethread_lock_lock(&debug_counter_lock); + { + rb_debug_counter[(int)type] += add; + } + rb_nativethread_lock_unlock(&debug_counter_lock); +} + int debug_counter_disable_show_at_exit = 0; // note that this operation is not atomic. @@ -92,7 +114,8 @@ rb_debug_counter_show_results(const char *msg) VALUE rb_debug_counter_show(RB_UNUSED_VAR(VALUE klass)) { - rb_debug_counter_show_results("method call"); + rb_debug_counter_show_results("show_debug_counters"); + ruby_debug_counter_show_at_exit(FALSE); return Qnil; } @@ -111,7 +134,9 @@ debug_counter_show_results_at_exit(void) rb_debug_counter_show_results("normal exit."); } } + #else + void rb_debug_counter_show_results(const char *msg) { diff --git a/ruby/debug_counter.h b/ruby/debug_counter.h index 066533d1d..3f0dec948 100644 --- a/ruby/debug_counter.h +++ b/ruby/debug_counter.h @@ -14,40 +14,67 @@ #ifdef RB_DEBUG_COUNTER -/* - * method cache (mc) counts. - * - * * mc_inline_hit/miss: inline mc hit/miss counts (VM send insn) - * * mc_global_hit/miss: global method cache hit/miss counts - * two types: (1) inline cache miss (VM send insn) - * (2) called from C (rb_funcall). - * * mc_global_state_miss: inline mc miss by global_state miss. - * * mc_class_serial_miss: ... by mc_class_serial_miss - * * mc_cme_complement: callable_method_entry complement counts. - * * mc_cme_complement_hit: callable_method_entry cache hit counts. - * * mc_search_super: search_method() call counts. - * * mc_miss_by_nome: inline mc miss by no ment. - * * mc_miss_by_distinct: ... by distinct ment. - * * mc_miss_by_refine: ... by ment being refined. - * * mc_miss_by_visi: ... by visibility change. - * * mc_miss_spurious: spurious inline mc misshit. - * * mc_miss_reuse_call: count of reuse of cc->call. - */ -RB_DEBUG_COUNTER(mc_inline_hit) -RB_DEBUG_COUNTER(mc_inline_miss) -RB_DEBUG_COUNTER(mc_global_hit) -RB_DEBUG_COUNTER(mc_global_miss) -RB_DEBUG_COUNTER(mc_global_state_miss) -RB_DEBUG_COUNTER(mc_class_serial_miss) -RB_DEBUG_COUNTER(mc_cme_complement) -RB_DEBUG_COUNTER(mc_cme_complement_hit) -RB_DEBUG_COUNTER(mc_search_super) -RB_DEBUG_COUNTER(mc_miss_by_nome) -RB_DEBUG_COUNTER(mc_miss_by_distinct) -RB_DEBUG_COUNTER(mc_miss_by_refine) -RB_DEBUG_COUNTER(mc_miss_by_visi) -RB_DEBUG_COUNTER(mc_miss_spurious) -RB_DEBUG_COUNTER(mc_miss_reuse_call) +// method cache (IMC: inline method cache) +RB_DEBUG_COUNTER(mc_inline_hit) // IMC hit +RB_DEBUG_COUNTER(mc_inline_miss_klass) // IMC miss by different class +RB_DEBUG_COUNTER(mc_inline_miss_invalidated) // IMC miss by invalidated ME +RB_DEBUG_COUNTER(mc_inline_miss_empty) // IMC miss because prev is empty slot +RB_DEBUG_COUNTER(mc_inline_miss_same_cc) // IMC miss, but same CC +RB_DEBUG_COUNTER(mc_inline_miss_same_cme) // IMC miss, but same CME +RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition +RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods + +RB_DEBUG_COUNTER(cvar_write_inline_hit) // cvar cache hit on write +RB_DEBUG_COUNTER(cvar_read_inline_hit) // cvar cache hit on read +RB_DEBUG_COUNTER(cvar_inline_miss) // miss inline cache +RB_DEBUG_COUNTER(cvar_class_invalidate) // invalidate cvar cache when define a cvar that's defined on a subclass +RB_DEBUG_COUNTER(cvar_include_invalidate) // invalidate cvar cache on module include or prepend + +RB_DEBUG_COUNTER(mc_cme_complement) // number of acquiring complement CME +RB_DEBUG_COUNTER(mc_cme_complement_hit) // number of cache hit for complemented CME + +RB_DEBUG_COUNTER(mc_search) // count for method lookup in class tree +RB_DEBUG_COUNTER(mc_search_notfound) // method lookup, but not found +RB_DEBUG_COUNTER(mc_search_super) // total traversed classes + +// callinfo +RB_DEBUG_COUNTER(ci_packed) // number of packed CI +RB_DEBUG_COUNTER(ci_kw) // non-packed CI w/ keywords +RB_DEBUG_COUNTER(ci_nokw) // non-packed CI w/o keywords +RB_DEBUG_COUNTER(ci_runtime) // creating temporary CI + +// callcache +RB_DEBUG_COUNTER(cc_new) // number of CC +RB_DEBUG_COUNTER(cc_temp) // dummy CC (stack-allocated) +RB_DEBUG_COUNTER(cc_found_in_ccs) // count for CC lookup success in CCS +RB_DEBUG_COUNTER(cc_not_found_in_ccs) // count for CC lookup success in CCS + +RB_DEBUG_COUNTER(cc_ent_invalidate) // count for invalidating cc (cc->klass = 0) +RB_DEBUG_COUNTER(cc_cme_invalidate) // count for invalidating CME + +RB_DEBUG_COUNTER(cc_invalidate_leaf) // count for invalidating klass if klass has no-subclasses +RB_DEBUG_COUNTER(cc_invalidate_leaf_ccs) // corresponding CCS +RB_DEBUG_COUNTER(cc_invalidate_leaf_callable) // complimented cache (no-subclasses) +RB_DEBUG_COUNTER(cc_invalidate_tree) // count for invalidating klass if klass has subclasses +RB_DEBUG_COUNTER(cc_invalidate_tree_cme) // cme if cme is found in this class or superclasses +RB_DEBUG_COUNTER(cc_invalidate_tree_callable) // complimented cache (subclasses) +RB_DEBUG_COUNTER(cc_invalidate_negative) // count for invalidating negative cache + +RB_DEBUG_COUNTER(ccs_free) // count for free'ing ccs +RB_DEBUG_COUNTER(ccs_maxlen) // maximum length of ccs +RB_DEBUG_COUNTER(ccs_found) // count for finding corresponding ccs on method lookup +RB_DEBUG_COUNTER(ccs_not_found) // count for not found corresponding ccs on method lookup + +// vm_eval.c +RB_DEBUG_COUNTER(call0_public) +RB_DEBUG_COUNTER(call0_other) +RB_DEBUG_COUNTER(gccct_hit) +RB_DEBUG_COUNTER(gccct_miss) +RB_DEBUG_COUNTER(gccct_null) + +// iseq +RB_DEBUG_COUNTER(iseq_num) // number of total created iseq +RB_DEBUG_COUNTER(iseq_cd_num) // number of total created cd (call_data) /* * call cache fastpath usage @@ -61,6 +88,7 @@ RB_DEBUG_COUNTER(ccf_iseq_opt) /* has_opt == TRUE (has optional parameters), but RB_DEBUG_COUNTER(ccf_iseq_kw1) /* vm_call_iseq_setup_kwparm_kwarg() */ RB_DEBUG_COUNTER(ccf_iseq_kw2) /* vm_call_iseq_setup_kwparm_nokwarg() */ RB_DEBUG_COUNTER(ccf_cfunc) +RB_DEBUG_COUNTER(ccf_cfunc_with_frame) RB_DEBUG_COUNTER(ccf_ivar) /* attr_reader */ RB_DEBUG_COUNTER(ccf_attrset) /* attr_writer */ RB_DEBUG_COUNTER(ccf_method_missing) @@ -69,6 +97,8 @@ RB_DEBUG_COUNTER(ccf_bmethod) RB_DEBUG_COUNTER(ccf_opt_send) RB_DEBUG_COUNTER(ccf_opt_call) RB_DEBUG_COUNTER(ccf_opt_block_call) +RB_DEBUG_COUNTER(ccf_opt_struct_aref) +RB_DEBUG_COUNTER(ccf_opt_struct_aset) RB_DEBUG_COUNTER(ccf_super_method) /* @@ -117,7 +147,7 @@ RB_DEBUG_COUNTER(ivar_set_ic_hit) RB_DEBUG_COUNTER(ivar_set_ic_miss) RB_DEBUG_COUNTER(ivar_set_ic_miss_serial) RB_DEBUG_COUNTER(ivar_set_ic_miss_unset) -RB_DEBUG_COUNTER(ivar_set_ic_miss_oorange) +RB_DEBUG_COUNTER(ivar_set_ic_miss_iv_hit) RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject) RB_DEBUG_COUNTER(ivar_get_base) RB_DEBUG_COUNTER(ivar_set_base) @@ -155,6 +185,12 @@ RB_DEBUG_COUNTER(gc_major_shady) RB_DEBUG_COUNTER(gc_major_force) RB_DEBUG_COUNTER(gc_major_oldmalloc) +RB_DEBUG_COUNTER(gc_enter_start) +RB_DEBUG_COUNTER(gc_enter_mark_continue) +RB_DEBUG_COUNTER(gc_enter_sweep_continue) +RB_DEBUG_COUNTER(gc_enter_rest) +RB_DEBUG_COUNTER(gc_enter_finalizer) + RB_DEBUG_COUNTER(gc_isptr_trial) RB_DEBUG_COUNTER(gc_isptr_range) RB_DEBUG_COUNTER(gc_isptr_align) @@ -164,7 +200,7 @@ RB_DEBUG_COUNTER(gc_isptr_maybe) * * * obj_newobj: newobj counts * * obj_newobj_slowpath: newobj with slowpath counts - * * obj_newobj_wb_unprotected: newobj for wb_unprotecte. + * * obj_newobj_wb_unprotected: newobj for wb_unprotected. * * obj_free: obj_free() counts * * obj_promote: promoted counts (oldgen) * * obj_wb_unprotect: wb unprotect counts @@ -282,6 +318,9 @@ RB_DEBUG_COUNTER(obj_imemo_throw_data) RB_DEBUG_COUNTER(obj_imemo_ifunc) RB_DEBUG_COUNTER(obj_imemo_memo) 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) /* ar_table */ RB_DEBUG_COUNTER(artable_hint_hit) @@ -301,14 +340,24 @@ RB_DEBUG_COUNTER(theap_alloc) RB_DEBUG_COUNTER(theap_alloc_fail) RB_DEBUG_COUNTER(theap_evacuate) +// VM sync +RB_DEBUG_COUNTER(vm_sync_lock) +RB_DEBUG_COUNTER(vm_sync_lock_enter) +RB_DEBUG_COUNTER(vm_sync_lock_enter_nb) +RB_DEBUG_COUNTER(vm_sync_lock_enter_cr) +RB_DEBUG_COUNTER(vm_sync_barrier) + /* mjit_exec() counts */ RB_DEBUG_COUNTER(mjit_exec) RB_DEBUG_COUNTER(mjit_exec_not_added) -RB_DEBUG_COUNTER(mjit_exec_not_added_add_iseq) RB_DEBUG_COUNTER(mjit_exec_not_ready) RB_DEBUG_COUNTER(mjit_exec_not_compiled) RB_DEBUG_COUNTER(mjit_exec_call_func) +/* MJIT enqueue / unload */ +RB_DEBUG_COUNTER(mjit_add_iseq_to_process) +RB_DEBUG_COUNTER(mjit_unload_units) + /* MJIT <-> VM frame push counts */ RB_DEBUG_COUNTER(mjit_frame_VM2VM) RB_DEBUG_COUNTER(mjit_frame_VM2JT) @@ -318,9 +367,11 @@ RB_DEBUG_COUNTER(mjit_frame_JT2VM) /* MJIT cancel counters */ RB_DEBUG_COUNTER(mjit_cancel) RB_DEBUG_COUNTER(mjit_cancel_ivar_inline) +RB_DEBUG_COUNTER(mjit_cancel_exivar_inline) RB_DEBUG_COUNTER(mjit_cancel_send_inline) RB_DEBUG_COUNTER(mjit_cancel_opt_insn) /* CALL_SIMPLE_METHOD */ RB_DEBUG_COUNTER(mjit_cancel_invalidate_all) +RB_DEBUG_COUNTER(mjit_cancel_leave) /* rb_mjit_unit_list length */ RB_DEBUG_COUNTER(mjit_length_unit_queue) @@ -341,6 +392,10 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath) #ifndef RUBY_DEBUG_COUNTER_H #define RUBY_DEBUG_COUNTER_H 1 +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "ruby/ruby.h" /* for VALUE */ + #if !defined(__GNUC__) && USE_DEBUG_COUNTER #error "USE_DEBUG_COUNTER is not supported by other than __GNUC__" #endif @@ -354,27 +409,51 @@ enum rb_debug_counter_type { #if USE_DEBUG_COUNTER extern size_t rb_debug_counter[]; +RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; +RUBY_EXTERN void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add); inline static int rb_debug_counter_add(enum rb_debug_counter_type type, int add, int cond) { if (cond) { - rb_debug_counter[(int)type] += add; + if (ruby_single_main_ractor != NULL) { + rb_debug_counter[(int)type] += add; + } + else { + rb_debug_counter_add_atomic(type, add); + } } return cond; } +inline static int +rb_debug_counter_max(enum rb_debug_counter_type type, unsigned int num) +{ + // TODO: sync + if (rb_debug_counter[(int)type] < num) { + rb_debug_counter[(int)type] = num; + return 1; + } + else { + return 0; + } +} + VALUE rb_debug_counter_reset(VALUE klass); VALUE rb_debug_counter_show(VALUE klass); #define RB_DEBUG_COUNTER_INC(type) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, 1) #define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !(cond))) -#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, (cond)) +#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !!(cond)) +#define RB_DEBUG_COUNTER_ADD(type, num) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, (num), 1) +#define RB_DEBUG_COUNTER_SETMAX(type, num) rb_debug_counter_max(RB_DEBUG_COUNTER_##type, (unsigned int)(num)) #else #define RB_DEBUG_COUNTER_INC(type) ((void)0) -#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (cond) -#define RB_DEBUG_COUNTER_INC_IF(type, cond) (cond) +#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!!(cond)) +#define RB_DEBUG_COUNTER_INC_IF(type, cond) (!!(cond)) +#define RB_DEBUG_COUNTER_ADD(type, num) ((void)0) +#define RB_DEBUG_COUNTER_SETMAX(type, num) 0 #endif void rb_debug_counter_show_results(const char *msg); diff --git a/ruby/defs/gmake.mk b/ruby/defs/gmake.mk index 226e1066a..dd7da5f77 100644 --- a/ruby/defs/gmake.mk +++ b/ruby/defs/gmake.mk @@ -1,9 +1,20 @@ # -*- mode: makefile-gmake; indent-tabs-mode: t -*- -gnumake = yes +reconfig config.status: export MAKE:=$(MAKE) override gnumake_recursive := $(if $(findstring n,$(firstword $(MFLAGS))),,+) override mflags := $(filter-out -j%,$(MFLAGS)) MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j) +nproc = $(subst -j,,$(filter -j%,$(MFLAGS))) + +ifeq ($(GITHUB_ACTIONS),true) +override ACTIONS_GROUP = @echo "\#\#[group]$(@:yes-=)" +override ACTIONS_ENDGROUP = @echo "\#\#[endgroup]" +endif + +ifneq ($(filter %darwin%,$(arch)),) +INSTRUBY_ENV += SDKROOT=/ +endif +INSTRUBY_ARGS += --gnumake CHECK_TARGETS := great exam love check test check% test% btest% # expand test targets, and those dependents @@ -67,7 +78,7 @@ endif ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \ btest-ruby test-knownbug test-basic \ test-testframework test-tool test-ruby test-all \ - test-spec test-bundler-prepare test-bundler \ + test-spec test-bundler-prepare test-bundler test-bundler-parallel \ ) prev_test := $(if $(filter test-spec,$(ORDERED_TEST_TARGETS)),test-spec-precheck) $(foreach test,$(ORDERED_TEST_TARGETS), \ @@ -90,15 +101,21 @@ sudo-precheck: test yes-test-testframework no-test-testframework install-prereq: sudo-precheck yes-test-all no-test-all: install endif +yes-test-bundler-parallel: PARALLELRSPECOPTS += $(if $(nproc),-n$(shell expr $(nproc) + $(nproc) / 2)) + # Cross reference needs to parse all files at once love install reinstall: RDOCFLAGS = --force-update +ifneq ($(if $(filter -flto%,$(CFLAGS)),$(subst darwin,,$(arch)),$(arch)),$(arch)) +override EXE_LDFLAGS = $(filter-out -g%,$(LDFLAGS)) +endif + $(srcdir)/missing/des_tables.c: $(srcdir)/missing/crypt.c ifeq ($(if $(filter yes,$(CROSS_COMPILING)),,$(CC)),) touch $@ else @$(ECHO) building make_des_table - $(CC) $(INCFLAGS) $(CPPFLAGS) -DDUMP $(LDFLAGS) $(XLDFLAGS) $(LIBS) -omake_des_table $(srcdir)/missing/crypt.c + $(CC) $(INCFLAGS) $(CPPFLAGS) -DDUMP $(EXE_LDFLAGS) $(XLDFLAGS) $(LIBS) -omake_des_table $(srcdir)/missing/crypt.c @[ -x ./make_des_table ] @$(ECHO) generating $@ $(Q) $(MAKEDIRS) $(@D) @@ -107,6 +124,8 @@ else $(Q) $(RMALL) make_des_table* endif +config.status: $(wildcard config.cache) + STUBPROGRAM = rubystub$(EXEEXT) IGNOREDPATTERNS = %~ .% %.orig %.rej \#%\# SCRIPTBINDIR := $(if $(EXEEXT),,exec/) @@ -125,7 +144,7 @@ $(STUBPROGRAM): rubystub.$(OBJEXT) $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SE rubystub$(EXEEXT): @rm -f $@ $(ECHO) linking $@ - $(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) rubystub.$(OBJEXT) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@ + $(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) rubystub.$(OBJEXT) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@ $(Q) $(POSTLINK) $(if $(STRIP),$(Q) $(STRIP) $@) @@ -214,6 +233,7 @@ define pull-github $(eval GITHUB_MERGE_BASE := $(shell git -C "$(srcdir)" log -1 --format=format:%H)) $(eval GITHUB_MERGE_BRANCH := $(shell git -C "$(srcdir)" symbolic-ref --short HEAD)) $(eval GITHUB_MERGE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(1)-XXXXXX")) + git -C "$(srcdir)" worktree prune git -C "$(srcdir)" worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)" git -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH) $(eval COMMIT_GPG_SIGN := $(COMMIT_GPG_SIGN)) @@ -241,16 +261,43 @@ HELP_EXTRA_TASKS = \ " update-github: merge master branch and push it to Pull Request [PR=1234]" \ "" -ifneq ($(filter refresh-gems,$(MAKECMDGOALS)),) -extract-gems: update-gems +extract-gems: $(HAVE_BASERUBY:yes=update-gems) + +bundled-gems := $(shell sed '/^[ ]*\#/d;/^[ ]*$$/d;s/[ ][ ]*/-/;s/[ ].*//' $(srcdir)/gems/bundled_gems) + +update-gems: | $(patsubst %,gems/%.gem,$(bundled-gems)) + +test-bundler-precheck: | $(srcdir)/.bundle/cache + +$(srcdir)/.bundle/cache: + $(MAKEDIRS) $(@D) $(CACHE_DIR) + $(LN_S) ../.downloaded-cache $@ + +gems/%.gem: + $(ECHO) Downloading bundled gem $*... + $(Q) $(BASERUBY) -C "$(srcdir)" \ + -I./tool -rdownloader \ + -e 'gem = "$(@F)"' \ + -e 'old = Dir.glob("gems/"+gem.sub(/-[^-]*$$/, "-*.gem"))' \ + -e 'Downloader::RubyGems.download(gem, "gems", nil) and' \ + -e '(old.delete("gems/#{gem}"); !old.empty?) and' \ + -e 'File.unlink(*old) and' \ + -e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' + +extract-gems: | $(patsubst %,.bundle/gems/%,$(bundled-gems)) + +.bundle/gems/%: gems/%.gem | .bundle/gems + $(ECHO) Extracting bundle gem $*... + $(Q) $(BASERUBY) -C "$(srcdir)" \ + -Itool -rgem-unpack \ + -e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems")' + +$(srcdir)/.bundle/gems: + $(MAKEDIRS) $@ + +ifneq ($(filter update-bundled_gems refresh-gems,$(MAKECMDGOALS)),) update-gems: update-bundled_gems endif -ifneq ($(filter extract-gems,$(MAKECMDGOALS)),) -extract-gems: $(filter update-gems update-bundled_gems,$(MAKECMDGOALS)) -endif -ifneq ($(filter update-gems,$(MAKECMDGOALS)),) -update-gems: $(filter update-bundled_gems,$(MAKECMDGOALS)) -endif ifeq ($(filter 0 1,$(words $(arch_flags))),) $(foreach x,$(patsubst -arch=%,%,$(arch_flags)), \ @@ -291,8 +338,13 @@ $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: \ $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) endif +ifeq ($(wildcard $(srcdir)/revision.h),) +REVISION_IN_HEADER := none +REVISION_LATEST := update +else REVISION_IN_HEADER := $(shell sed -n 's/^\#define RUBY_FULL_REVISION "\(.*\)"/\1/p' $(srcdir)/revision.h 2>/dev/null) REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && git log -1 --format=%H 2>/dev/null) +endif ifneq ($(REVISION_IN_HEADER),$(REVISION_LATEST)) # GNU make treat the target as unmodified when its dependents get # updated but it is not updated, while others may not. @@ -306,19 +358,25 @@ rdoc\:%: PHONY $(Q)$(RUNRUBY) $(srcdir)/libexec/ri --no-standard-docs --doc-dir=$(RDOCOUT) $(patsubst rdoc:%,%,$@) test_%.rb test/%: programs PHONY - +$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) -- $(patsubst test/%,%,$@) + $(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) -- $(patsubst test/%,%,$@) spec/bundler/%: PHONY - +$(Q)$(exec) $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec --require spec_helper $(RSPECOPTS) $@ + $(Q)$(exec) $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec --require spec_helper $(RSPECOPTS) $@ -spec/%: programs exts PHONY - +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@) +spec/bundler: test-bundler-parallel + $(Q)$(NULLCMD) + +# workaround to avoid matching non ruby files with "spec/%/" under GNU make 3.81 +spec/%_spec.c: + $(empty) +$(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h: + $(empty) benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY $(Q)$(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \ --executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \ --executables="built-ruby::$(BENCH_RUBY) --disable-gem" \ - $(srcdir)/$@ $(OPTS) + $(srcdir)/$@ $(BENCH_OPTS) $(OPTS) clean-srcs-ext:: $(Q)$(RM) $(patsubst $(srcdir)/%,%,$(EXT_SRCS)) @@ -328,7 +386,7 @@ clean-srcs-extra:: ifneq ($(filter $(VCS),git),) update-src:: - @$(BASERUBY) $(srcdir)/tool/lib/colorize.rb pass "Latest commit hash = $(shell $(filter-out svn,$(VCS)) -C $(srcdir) rev-parse --short=10 HEAD)" + @$(BASERUBY) $(tooldir)/lib/colorize.rb pass "Latest commit hash = $(shell $(filter-out svn,$(VCS)) -C $(srcdir) rev-parse --short=10 HEAD)" endif # Update dependencies and commit the updates to the current branch. @@ -337,7 +395,7 @@ update-deps: $(eval deps_dir := $(shell mktemp -d)/$(update_deps)) $(eval GIT_DIR := $(shell git -C $(srcdir) rev-parse --absolute-git-dir)) git --git-dir=$(GIT_DIR) worktree add $(deps_dir) - cp $(srcdir)/tool/config.guess $(srcdir)/tool/config.sub $(deps_dir)/tool + cp $(tooldir)/config.guess $(tooldir)/config.sub $(deps_dir)/tool [ -f config.status ] && cp config.status $(deps_dir) cd $(deps_dir) && autoconf && \ exec ./configure -q -C --enable-load-relative --disable-install-doc --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g' @@ -348,3 +406,23 @@ update-deps: $(RMDIR) $(dir $(deps_dir)) git --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps) git --git-dir=$(GIT_DIR) branch --delete $(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) + $(ECHO) building $@ + $(Q) $(MAKEDIRS) $(@D) + $(Q) $(DLDSHARED) $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG) + $(Q) $(RMALL) $@.* + +rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c))) + @ $(NULLCMD) + +ifeq ($(ENABLE_SHARED),yes) +exts: rubyspec-capiext +endif + +spec/%/ spec/%_spec.rb: programs exts PHONY + +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@) + +ruby.pc: $(filter-out ruby.pc,$(ruby_pc)) diff --git a/ruby/defs/id.def b/ruby/defs/id.def index fc7a04ffb..8df6cf12e 100644 --- a/ruby/defs/id.def +++ b/ruby/defs/id.def @@ -25,6 +25,7 @@ firstline, predefined = __LINE__+1, %[\ send __send__ __attached__ + __recursive_key__ initialize initialize_copy initialize_clone @@ -86,6 +87,7 @@ firstline, predefined = __LINE__+1, %[\ core#hash_merge_ptr core#hash_merge_kwd core#raise + core#sprintf - debug#created_info @@ -138,6 +140,21 @@ class KeywordError < RuntimeError end end +def id2varname(token, prefix = nil) + if /#/ =~ token + token = "_#{token.gsub(/\W+/, '_')}" + else + token = token.sub(/\?/, 'P') + token = prefix + token if prefix + token.sub!(/\A[a-z]/) {$&.upcase} + token.sub!(/\A\$/, "_G_") + token.sub!(/\A@@/, "_C_") + token.sub!(/\A@/, "_I_") + token.gsub!(/\W+/, "") + end + token +end + predefined_ids = {} preserved_ids = [] local_ids = [] @@ -153,16 +170,7 @@ predefined.split(/^/).each_with_index do |line, num| line.sub!(/\s+#.*/, '') name, token = line.split next unless name - token ||= name - if /#/ =~ token - token = "_#{token.gsub(/\W+/, '_')}" - else - token = token.sub(/\?/, 'P').sub(/\A[a-z]/) {$&.upcase} - token.sub!(/\A\$/, "_G_") - token.sub!(/\A@@/, "_C_") - token.sub!(/\A@/, "_I_") - token.gsub!(/\W+/, "") - end + token = id2varname(token || name) if name == '-' preserved_ids << token next diff --git a/ruby/dir.c b/ruby/dir.c index d773ba018..184dbf007 100644 --- a/ruby/dir.c +++ b/ruby/dir.c @@ -11,12 +11,10 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/thread.h" -#include "internal.h" -#include "id.h" -#include "encindex.h" +#include "ruby/internal/config.h" +#include +#include #include #include @@ -36,12 +34,10 @@ # define USE_OPENDIR_AT 0 # endif #endif + #if USE_OPENDIR_AT # include #endif -#ifndef AT_FDCWD -# define AT_FDCWD -1 -#endif #undef HAVE_DIRENT_NAMLEN #if defined HAVE_DIRENT_H && !defined _WIN32 @@ -54,13 +50,13 @@ # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # define HAVE_DIRENT_NAMLEN 1 -# if HAVE_SYS_NDIR_H +# ifdef HAVE_SYS_NDIR_H # include # endif -# if HAVE_SYS_DIR_H +# ifdef HAVE_SYS_DIR_H # include # endif -# if HAVE_NDIR_H +# ifdef HAVE_NDIR_H # include # endif # ifdef _WIN32 @@ -68,8 +64,6 @@ # endif #endif -#include - #ifndef HAVE_STDLIB_H char *getenv(); #endif @@ -78,28 +72,6 @@ char *getenv(); char *strchr(char*,char); #endif -#include - -#include "ruby/util.h" - -#define vm_initialized rb_cThread - -/* define system APIs */ -#ifdef _WIN32 -#undef chdir -#define chdir(p) rb_w32_uchdir(p) -#undef mkdir -#define mkdir(p, m) rb_w32_umkdir((p), (m)) -#undef rmdir -#define rmdir(p) rb_w32_urmdir(p) -#undef opendir -#define opendir(p) rb_w32_uopendir(p) -#define ruby_getcwd() rb_w32_ugetcwd(NULL, 0) -#define IS_WIN32 1 -#else -#define IS_WIN32 0 -#endif - #ifdef HAVE_SYS_ATTR_H #include #endif @@ -123,19 +95,54 @@ char *strchr(char*,char); #ifdef __APPLE__ # define NORMALIZE_UTF8PATH 1 +# include +# include +# include #else # define NORMALIZE_UTF8PATH 0 #endif -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- +#include "encindex.h" +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/dir.h" +#include "internal/encoding.h" +#include "internal/error.h" +#include "internal/file.h" +#include "internal/gc.h" +#include "internal/io.h" +#include "internal/object.h" +#include "internal/vm.h" +#include "ruby/encoding.h" +#include "ruby/ruby.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "builtin.h" -#if NORMALIZE_UTF8PATH -#include -#include -#include +#ifndef AT_FDCWD +# define AT_FDCWD -1 +#endif +#define vm_initialized rb_cThread + +/* define system APIs */ +#ifdef _WIN32 +# undef chdir +# define chdir(p) rb_w32_uchdir(p) +# undef mkdir +# define mkdir(p, m) rb_w32_umkdir((p), (m)) +# undef rmdir +# define rmdir(p) rb_w32_urmdir(p) +# undef opendir +# define opendir(p) rb_w32_uopendir(p) +# define ruby_getcwd() rb_w32_ugetcwd(NULL, 0) +# define IS_WIN32 1 +#else +# define IS_WIN32 0 +#endif + +#if NORMALIZE_UTF8PATH # if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST # define need_normalization(dirp, path) need_normalization(dirp) # else @@ -148,10 +155,8 @@ need_normalization(DIR *dirp, const char *path) u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,}; # if defined HAVE_FGETATTRLIST - if (squash_find_entry(dirp)) { return FALSE; } int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0); # else - if (enclose_io_is_path(path)) { return FALSE; } int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0); # endif if (!ret) { @@ -212,11 +217,13 @@ typedef enum { #else #define FNM_SYSCASE 0 #endif -#if _WIN32 +#ifdef _WIN32 #define FNM_SHORTNAME 0x20 #else #define FNM_SHORTNAME 0 #endif +#define FNM_GLOB_NOSORT 0x40 +#define FNM_GLOB_SKIPDOT 0x80 #define FNM_NOMATCH 1 #define FNM_ERROR 2 @@ -517,40 +524,13 @@ opendir_without_gvl(const char *path) return opendir(path); } -/* - * call-seq: - * Dir.new( string ) -> aDir - * Dir.new( string, encoding: enc ) -> aDir - * - * Returns a new directory object for the named directory. - * - * The optional encoding keyword argument specifies the encoding of the directory. - * If not specified, the filesystem encoding is used. - */ static VALUE -dir_initialize(int argc, VALUE *argv, VALUE dir) +dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) { struct dir_data *dp; - rb_encoding *fsenc; - VALUE dirname, opt, orig; - static ID keyword_ids[1]; + VALUE orig; const char *path; - - if (!keyword_ids[0]) { - keyword_ids[0] = rb_id_encoding(); - } - - fsenc = rb_filesystem_encoding(); - - rb_scan_args(argc, argv, "1:", &dirname, &opt); - - if (!NIL_P(opt)) { - VALUE enc; - rb_get_kwargs(opt, keyword_ids, 0, 1, &enc); - if (enc != Qundef && !NIL_P(enc)) { - fsenc = rb_to_encoding(enc); - } - } + rb_encoding *fsenc = NIL_P(enc) ? rb_filesystem_encoding() : rb_to_encoding(enc); FilePathValue(dirname); orig = rb_str_dup_frozen(dirname); @@ -573,12 +553,7 @@ dir_initialize(int argc, VALUE *argv, VALUE dir) else if (e == EIO) { u_int32_t attrbuf[1]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0}; - if (enclose_io_is_path(path)) { - struct stat buf; - if (0 == squash_lstat(enclose_io_fs, path, &buf)) { - dp->dir = opendir_without_gvl(path); - } - } else if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) { + if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) { dp->dir = opendir_without_gvl(path); } } @@ -593,35 +568,23 @@ dir_initialize(int argc, VALUE *argv, VALUE dir) return dir; } -/* - * call-seq: - * Dir.open( string ) -> aDir - * Dir.open( string, encoding: enc ) -> aDir - * Dir.open( string ) {| aDir | block } -> anObject - * Dir.open( string, encoding: enc ) {| aDir | block } -> anObject - * - * The optional encoding keyword argument specifies the encoding of the directory. - * If not specified, the filesystem encoding is used. - * - * With no block, open is a synonym for Dir::new. If a - * block is present, it is passed aDir as a parameter. The - * directory is closed at the end of the block, and Dir::open returns - * the value of the block. - */ static VALUE -dir_s_open(int argc, VALUE *argv, VALUE klass) +dir_s_open(rb_execution_context_t *ec, VALUE klass, VALUE dirname, VALUE enc) { struct dir_data *dp; VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp); - dir_initialize(argc, argv, dir); - if (rb_block_given_p()) { - return rb_ensure(rb_yield, dir, dir_close, dir); - } + dir_initialize(ec, dir, dirname, enc); return dir; } +static VALUE +dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir) +{ + return dir_close(dir); +} + NORETURN(static void dir_closed(void)); static void @@ -1027,7 +990,7 @@ chdir_yield(VALUE v) dir_chdir(args->new_path); args->done = TRUE; chdir_blocking++; - if (chdir_thread == Qnil) + if (NIL_P(chdir_thread)) chdir_thread = rb_thread_current(); return rb_yield(args->new_path); } @@ -1063,7 +1026,8 @@ chdir_restore(VALUE v) * block. chdir blocks can be nested, but in a * multi-threaded program an error will be raised if a thread attempts * to open a chdir block while another thread has one - * open. + * open or a call to chdir without a block occurs inside + * a block passed to chdir (even in the same thread). * * Dir.chdir("/var/spool/mail") * puts Dir.pwd @@ -1102,8 +1066,10 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj) } if (chdir_blocking > 0) { - if (!rb_block_given_p() || rb_thread_current() != chdir_thread) - rb_warn("conflicting chdir during another chdir block"); + 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()) { @@ -1353,21 +1319,34 @@ sys_enc_warning_in(const char *func, const char *mesg, rb_encoding *enc) #define sys_warning(val, enc) \ ((flags & GLOB_VERBOSE) ? sys_enc_warning_in(RUBY_FUNCTION_NAME_STRING, (val), (enc)) :(void)0) -static inline void * -glob_alloc_n(size_t x, size_t y) +static inline size_t +glob_alloc_size(size_t x, size_t y) { size_t z; if (rb_mul_size_overflow(x, y, SSIZE_MAX, &z)) { rb_memerror(); /* or...? */ } else { - return malloc(z); + return z; } } +static inline void * +glob_alloc_n(size_t x, size_t y) +{ + return malloc(glob_alloc_size(x, y)); +} + +static inline void * +glob_realloc_n(void *p, size_t x, size_t y) +{ + return realloc(p, glob_alloc_size(x, y)); +} + #define GLOB_ALLOC(type) ((type *)malloc(sizeof(type))) #define GLOB_ALLOC_N(type, n) ((type *)glob_alloc_n(sizeof(type), n)) #define GLOB_REALLOC(ptr, size) realloc((ptr), (size)) +#define GLOB_REALLOC_N(ptr, n) glob_realloc_n(ptr, sizeof(*(ptr)), n) #define GLOB_FREE(ptr) free(ptr) #define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status)) @@ -1451,7 +1430,7 @@ with_gvl_gc_for_fd(void *ptr) { int *e = ptr; - return (void *)(rb_gc_for_fd(*e) ? Qtrue : Qfalse); + return (void *)RBOOL(rb_gc_for_fd(*e)); } static int @@ -1460,7 +1439,7 @@ gc_for_fd_with_gvl(int e) if (vm_initialized) return (int)(VALUE)rb_thread_call_with_gvl(with_gvl_gc_for_fd, &e); else - return rb_gc_for_fd(e) ? Qtrue : Qfalse; + return RBOOL(rb_gc_for_fd(e)); } static void * @@ -1732,10 +1711,7 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc) tmp = GLOB_ALLOC(struct glob_pattern); if (!tmp) { - error: - *tail = 0; - glob_free_pattern(list); - return 0; + goto error; } tmp->type = dirsep ? MATCH_DIR : MATCH_ALL; tmp->str = 0; @@ -1743,6 +1719,11 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc) tmp->next = 0; return list; + + error: + *tail = 0; + glob_free_pattern(list); + return 0; } static void @@ -1790,8 +1771,6 @@ is_case_sensitive(DIR *dirp, const char *path) const int idx = VOL_CAPABILITIES_FORMAT; const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE; - if (squash_find_entry(dirp)) { return 1; } - # if defined HAVE_FGETATTRLIST if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) return -1; @@ -1995,13 +1974,15 @@ rb_glob_warning(const char *path, VALUE a, const void *enc, int error) } #endif +NORETURN(static VALUE glob_func_error(VALUE val)); + static VALUE glob_func_error(VALUE val) { struct glob_error_args *arg = (struct glob_error_args *)val; VALUE path = rb_enc_str_new_cstr(arg->path, arg->enc); rb_syserr_fail_str(arg->error, path); - return Qnil; + UNREACHABLE_RETURN(Qnil); } static int @@ -2021,8 +2002,17 @@ rb_glob_error(const char *path, VALUE a, const void *enc, int error) return status; } +typedef struct rb_dirent { + long d_namlen; + const char *d_name; +#ifdef _WIN32 + const char *d_altname; +#endif + uint8_t d_type; +} rb_dirent_t; + static inline int -dirent_match(const char *pat, rb_encoding *enc, const char *name, const struct dirent *dp, int flags) +dirent_match(const char *pat, rb_encoding *enc, const char *name, const rb_dirent_t *dp, int flags) { if (fnmatch(pat, enc, name, flags) == 0) return 1; #ifdef _WIN32 @@ -2047,7 +2037,7 @@ struct push_glob_args { struct dirent_brace_args { const char *name; - const struct dirent *dp; + const rb_dirent_t *dp; int flags; }; @@ -2110,6 +2100,159 @@ static int push_caller(const char *path, VALUE val, void *enc); static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc, VALUE var); +static const size_t rb_dirent_name_offset = + offsetof(rb_dirent_t, d_type) + sizeof(uint8_t); + +static rb_dirent_t * +dirent_copy(const struct dirent *dp, rb_dirent_t *rdp) +{ + if (!dp) return NULL; + size_t namlen = NAMLEN(dp); + const size_t altlen = +#ifdef _WIN32 + dp->d_altlen ? dp->d_altlen + 1 : +#endif + 0; + rb_dirent_t *newrdp = rdp; + if (!rdp && !(newrdp = malloc(rb_dirent_name_offset + namlen + 1 + altlen))) + return NULL; + newrdp->d_namlen = namlen; + if (!rdp) { + char *name = (char *)newrdp + rb_dirent_name_offset; + memcpy(name, dp->d_name, namlen); + name[namlen] = '\0'; +#ifdef _WIN32 + newrdp->d_altname = NULL; + if (altlen) { + char *const altname = name + namlen + 1; + memcpy(altname, dp->d_altname, altlen - 1); + altname[altlen - 1] = '\0'; + newrdp->d_altname = altname; + } +#endif + newrdp->d_name = name; + } + else { + newrdp->d_name = dp->d_name; +#ifdef _WIN32 + newrdp->d_altname = dp->d_altname; +#endif + } +#ifdef DT_UNKNOWN + newrdp->d_type = dp->d_type; +#else + newrdp->d_type = 0; +#endif + return newrdp; +} + +typedef union { + struct { + DIR *dirp; + rb_dirent_t ent; + } nosort; + struct { + size_t count, idx; + rb_dirent_t **entries; + } sort; +} ruby_glob_entries_t; + +static int +glob_sort_cmp(const void *a, const void *b, void *e) +{ + const rb_dirent_t *ent1 = *(void **)a; + const rb_dirent_t *ent2 = *(void **)b; + return strcmp(ent1->d_name, ent2->d_name); +} + +static void +glob_dir_finish(ruby_glob_entries_t *ent, int flags) +{ + if (flags & FNM_GLOB_NOSORT) { + closedir(ent->nosort.dirp); + ent->nosort.dirp = NULL; + } + else if (ent->sort.entries) { + for (size_t i = 0, count = ent->sort.count; i < count;) { + GLOB_FREE(ent->sort.entries[i++]); + } + GLOB_FREE(ent->sort.entries); + ent->sort.entries = NULL; + ent->sort.count = ent->sort.idx = 0; + } +} + +static ruby_glob_entries_t * +glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) +{ + MEMZERO(ent, ruby_glob_entries_t, 1); + if (flags & FNM_GLOB_NOSORT) { + ent->nosort.dirp = dirp; + return ent; + } + else { + void *newp; + struct dirent *dp; + size_t count = 0, capacity = 0; + ent->sort.count = 0; + ent->sort.idx = 0; + ent->sort.entries = 0; +#ifdef _WIN32 + if ((capacity = dirp->nfiles) > 0) { + if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) { + closedir(dirp); + return NULL; + } + ent->sort.entries = newp; + } +#endif + while ((dp = READDIR(dirp, enc)) != NULL) { + rb_dirent_t *rdp = dirent_copy(dp, NULL); + if (!rdp) { + goto nomem; + } + if (count >= capacity) { + capacity += 256; + if (!(newp = GLOB_REALLOC_N(ent->sort.entries, capacity))) + goto nomem; + ent->sort.entries = newp; + } + ent->sort.entries[count++] = rdp; + ent->sort.count = count; + } + closedir(dirp); + if (count < capacity) { + if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) { + glob_dir_finish(ent, 0); + return NULL; + } + ent->sort.entries = newp; + } + ruby_qsort(ent->sort.entries, ent->sort.count, sizeof(ent->sort.entries[0]), + glob_sort_cmp, NULL); + return ent; + } + + nomem: + glob_dir_finish(ent, 0); + closedir(dirp); + return NULL; +} + +static rb_dirent_t * +glob_getent(ruby_glob_entries_t *ent, int flags, rb_encoding *enc) +{ + if (flags & FNM_GLOB_NOSORT) { + return dirent_copy(READDIR(ent->nosort.dirp, enc), &ent->nosort.ent); + } + else if (ent->sort.idx < ent->sort.count) { + return ent->sort.entries[ent->sort.idx++]; + } + else { + return NULL; + } +} + static int glob_helper( int fd, @@ -2132,6 +2275,8 @@ glob_helper( int escape = !(flags & FNM_NOESCAPE); size_t pathlen = baselen + namelen; + rb_check_stack_overflow(); + for (cur = beg; cur < end; ++cur) { struct glob_pattern *p = *cur; if (p->type == RECURSIVE) { @@ -2222,7 +2367,7 @@ glob_helper( if (pathtype == path_noent) return 0; if (magical || recursive) { - struct dirent *dp; + rb_dirent_t *dp; DIR *dirp; # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH char *plainname = 0; @@ -2261,7 +2406,22 @@ glob_helper( if (is_case_sensitive(dirp, path) == 0) flags |= FNM_CASEFOLD; # endif - while ((dp = READDIR(dirp, enc)) != NULL) { + ruby_glob_entries_t globent; + if (!glob_opendir(&globent, dirp, flags, enc)) { + status = 0; + if (funcs->error) { + status = (*funcs->error)(path, arg, enc, ENOMEM); + } + else { + sys_warning(path, enc); + } + return status; + } + + int skipdot = (flags & FNM_GLOB_SKIPDOT); + flags |= FNM_GLOB_SKIPDOT; + + while ((dp = glob_getent(&globent, flags, enc)) != NULL) { char *buf; rb_pathtype_t new_pathtype = path_unknown; const char *name; @@ -2270,12 +2430,13 @@ glob_helper( IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil); name = dp->d_name; - namlen = NAMLEN(dp); - if (recursive && name[0] == '.') { + namlen = dp->d_namlen; + if (name[0] == '.') { ++dotfile; if (namlen == 1) { /* unless DOTMATCH, skip current directories not to recurse infinitely */ - if (!(flags & FNM_DOTMATCH)) continue; + if (recursive && !(flags & FNM_DOTMATCH)) continue; + if (skipdot) continue; ++dotfile; new_pathtype = path_directory; /* force to skip stat/lstat */ } @@ -2365,7 +2526,7 @@ glob_helper( if (status) break; } - closedir(dirp); + glob_dir_finish(&globent, flags); } else if (plain) { struct glob_pattern **copy_beg, **copy_end, **cur2; @@ -2415,7 +2576,7 @@ glob_helper( break; } #if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME - if ((*cur)->type == ALPHA && !enclose_io_if(buf)) { + if ((*cur)->type == ALPHA) { buf = replace_real_basename(buf, pathlen + (dirsep != 0), enc, IF_NORMALIZE_UTF8PATH(1)+0, flags, &new_pathtype); @@ -2535,7 +2696,7 @@ ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg) { ruby_glob_funcs_t funcs; funcs.match = func; - funcs.error = NULL; + funcs.error = 0; return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE, &funcs, arg, rb_ascii8bit_encoding()); } @@ -2664,7 +2825,7 @@ ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE flags &= ~GLOB_VERBOSE; args.funcs.match = func; - args.funcs.error = NULL; + args.funcs.error = 0; args.value = arg; args.flags = flags; return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc, Qfalse); @@ -2741,177 +2902,67 @@ rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */ } static VALUE -dir_globs(long argc, const VALUE *argv, VALUE base, int flags) +dir_globs(VALUE args, VALUE base, int flags) { VALUE ary = rb_ary_new(); long i; - for (i = 0; i < argc; ++i) { + for (i = 0; i < RARRAY_LEN(args); ++i) { int status; - VALUE str = argv[i]; + VALUE str = RARRAY_AREF(args, i); FilePathValue(str); status = push_glob(ary, str, base, flags); if (status) GLOB_JUMP_TAG(status); } + RB_GC_GUARD(args); return ary; } -static void -dir_glob_options(VALUE opt, VALUE *base, int *flags) +static VALUE +dir_glob_option_base(VALUE base) { - ID kw[2]; - VALUE args[2]; - kw[0] = rb_intern("base"); - if (flags) kw[1] = rb_intern("flags"); - rb_get_kwargs(opt, kw, 0, flags ? 2 : 1, args); - if (args[0] == Qundef || NIL_P(args[0])) { - *base = Qnil; + if (base == Qundef || NIL_P(base)) { + return Qnil; } #if USE_OPENDIR_AT - else if (rb_typeddata_is_kind_of(args[0], &dir_data_type)) { - *base = args[0]; + if (rb_typeddata_is_kind_of(base, &dir_data_type)) { + return base; } #endif - else { - FilePathValue(args[0]); - if (!RSTRING_LEN(args[0])) args[0] = Qnil; - *base = args[0]; - } - if (flags && args[1] != Qundef) { - *flags = NUM2INT(args[1]); - } + FilePathValue(base); + if (!RSTRING_LEN(base)) return Qnil; + return base; +} + +static int +dir_glob_option_sort(VALUE sort) +{ + return (rb_bool_expected(sort, "sort") ? 0 : FNM_GLOB_NOSORT); } -/* - * call-seq: - * Dir[ string [, string ...] [, base: path] ] -> array - * - * Equivalent to calling - * Dir.glob([string,...], 0). - * - */ static VALUE -dir_s_aref(int argc, VALUE *argv, VALUE obj) +dir_s_aref(rb_execution_context_t *ec, VALUE obj, VALUE args, VALUE base, VALUE sort) { - VALUE opts, base; - argc = rb_scan_args(argc, argv, "*:", NULL, &opts); - dir_glob_options(opts, &base, NULL); - if (argc == 1) { - return rb_push_glob(argv[0], base, 0); + const int flags = dir_glob_option_sort(sort); + base = dir_glob_option_base(base); + if (RARRAY_LEN(args) == 1) { + return rb_push_glob(RARRAY_AREF(args, 0), base, flags); } - return dir_globs(argc, argv, base, 0); + return dir_globs(args, base, flags); } -/* - * call-seq: - * Dir.glob( pattern, [flags], [base: path] ) -> array - * Dir.glob( pattern, [flags], [base: path] ) { |filename| block } -> nil - * - * Expands +pattern+, which is a pattern string or an Array of pattern - * strings, and returns an array containing the matching filenames. - * If a block is given, calls the block once for each matching filename, - * passing the filename as a parameter to the block. - * - * The optional +base+ keyword argument specifies the base directory for - * interpreting relative pathnames instead of the current working directory. - * As the results are not prefixed with the base directory name in this - * case, you will need to prepend the base directory name if you want real - * paths. - * - * Note that the pattern is not a regexp, it's closer to a shell glob. - * See File::fnmatch for the meaning of the +flags+ parameter. - * Case sensitivity depends on your system (File::FNM_CASEFOLD is ignored), - * as does the order in which the results are returned. - * - * *:: - * Matches any file. Can be restricted by other values in the glob. - * Equivalent to / .* /mx in regexp. - * - * *:: Matches all files - * c*:: Matches all files beginning with c - * *c:: Matches all files ending with c - * \*c\*:: Match all files that have c in them - * (including at the beginning or end). - * - * Note, this will not match Unix-like hidden files (dotfiles). In order - * to include those in the match results, you must use the - * File::FNM_DOTMATCH flag or something like "{*,.*}". - * - * **:: - * Matches directories recursively. - * - * ?:: - * Matches any one character. Equivalent to /.{1}/ in regexp. - * - * [set]:: - * Matches any one character in +set+. Behaves exactly like character sets - * in Regexp, including set negation ([^a-z]). - * - * {p,q}:: - * Matches either literal p or literal q. - * Equivalent to pattern alternation in regexp. - * - * Matching literals may be more than one character in length. More than - * two literals may be specified. - * - * \\ :: - * Escapes the next metacharacter. - * - * Note that this means you cannot use backslash on windows as part of a - * glob, i.e. Dir["c:\\foo*"] will not work, use - * Dir["c:/foo*"] instead. - * - * Examples: - * - * Dir["config.?"] #=> ["config.h"] - * Dir.glob("config.?") #=> ["config.h"] - * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"] - * Dir.glob("*.[^r]*") #=> ["config.h"] - * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"] - * Dir.glob("*") #=> ["config.h", "main.rb"] - * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"] - * Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"] - * - * rbfiles = File.join("**", "*.rb") - * Dir.glob(rbfiles) #=> ["main.rb", - * # "lib/song.rb", - * # "lib/song/karaoke.rb"] - * - * Dir.glob(rbfiles, base: "lib") #=> ["song.rb", - * # "song/karaoke.rb"] - * - * libdirs = File.join("**", "lib") - * Dir.glob(libdirs) #=> ["lib"] - * - * librbfiles = File.join("**", "lib", "**", "*.rb") - * Dir.glob(librbfiles) #=> ["lib/song.rb", - * # "lib/song/karaoke.rb"] - * - * librbfiles = File.join("**", "lib", "*.rb") - * Dir.glob(librbfiles) #=> ["lib/song.rb"] - */ static VALUE -dir_s_glob(int argc, VALUE *argv, VALUE obj) +dir_s_glob(rb_execution_context_t *ec, VALUE obj, VALUE str, VALUE rflags, VALUE base, VALUE sort) { - VALUE str, rflags, ary, opts, base; - int flags; - - argc = rb_scan_args(argc, argv, "11:", &str, &rflags, &opts); - if (argc == 2) - flags = NUM2INT(rflags); - else - flags = 0; - dir_glob_options(opts, &base, &flags); - - ary = rb_check_array_type(str); + VALUE ary = rb_check_array_type(str); + const int flags = (NUM2INT(rflags) | dir_glob_option_sort(sort)) & ~FNM_CASEFOLD; + base = dir_glob_option_base(base); if (NIL_P(ary)) { ary = rb_push_glob(str, base, flags); } else { - VALUE v = ary; - ary = dir_globs(RARRAY_LEN(v), RARRAY_CONST_PTR(v), base, flags); - RB_GC_GUARD(v); + ary = dir_globs(ary, base, flags); } if (rb_block_given_p()) { @@ -3036,7 +3087,7 @@ dir_s_each_child(int argc, VALUE *argv, VALUE io) /* * call-seq: - * dir.each_child {| filename | block } -> nil + * dir.each_child {| filename | block } -> dir * dir.each_child -> an_enumerator * * Calls the block once for each entry except for "." and ".." in @@ -3130,100 +3181,7 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc) return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0); } -/* - * call-seq: - * File.fnmatch( pattern, path, [flags] ) -> (true or false) - * File.fnmatch?( pattern, path, [flags] ) -> (true or false) - * - * Returns true if +path+ matches against +pattern+. The pattern is not a - * regular expression; instead it follows rules similar to shell filename - * globbing. It may contain the following metacharacters: - * - * *:: - * Matches any file. Can be restricted by other values in the glob. - * Equivalent to / .* /x in regexp. - * - * *:: Matches all files regular files - * c*:: Matches all files beginning with c - * *c:: Matches all files ending with c - * \*c*:: Matches all files that have c in them - * (including at the beginning or end). - * - * To match hidden files (that start with a . set the - * File::FNM_DOTMATCH flag. - * - * **:: - * Matches directories recursively or files expansively. - * - * ?:: - * Matches any one character. Equivalent to /.{1}/ in regexp. - * - * [set]:: - * Matches any one character in +set+. Behaves exactly like character sets - * in Regexp, including set negation ([^a-z]). - * - * \ :: - * Escapes the next metacharacter. - * - * {a,b}:: - * Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled. - * Behaves like a Regexp union ((?:a|b)). - * - * +flags+ is a bitwise OR of the FNM_XXX constants. The same - * glob pattern and flags are used by Dir::glob. - * - * Examples: - * - * File.fnmatch('cat', 'cat') #=> true # match entire string - * File.fnmatch('cat', 'category') #=> false # only match partial string - * - * File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default - * File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB - * - * File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character - * File.fnmatch('c??t', 'cat') #=> false # ditto - * File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters - * File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto - * File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression - * File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!') - * - * File.fnmatch('cat', 'CAT') #=> false # case sensitive - * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive - * File.fnmatch('cat', 'CAT', File::FNM_SYSCASE) #=> true or false # depends on the system default - * - * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME - * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto - * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto - * - * File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary - * File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary - * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary - * File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression - * - * File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading - * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default. - * File.fnmatch('.*', '.profile') #=> true - * - * rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string. - * File.fnmatch(rbfiles, 'main.rb') #=> false - * File.fnmatch(rbfiles, './main.rb') #=> false - * File.fnmatch(rbfiles, 'lib/song.rb') #=> true - * File.fnmatch('**.rb', 'main.rb') #=> true - * File.fnmatch('**.rb', './main.rb') #=> false - * File.fnmatch('**.rb', 'lib/song.rb') #=> true - * File.fnmatch('*', 'dave/.profile') #=> true - * - * pattern = '*' '/' '*' - * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false - * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true - * - * pattern = '**' '/' 'foo' - * File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true - * File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true - * File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true - * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false - * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true - */ +/* :nodoc: */ static VALUE file_s_fnmatch(int argc, VALUE *argv, VALUE obj) { @@ -3302,16 +3260,11 @@ rb_file_directory_p(void) } #endif -/* - * call-seq: - * Dir.exists?(file_name) -> true or false - * - * Deprecated method. Don't use. - */ +/* :nodoc: */ static VALUE rb_dir_exists_p(VALUE obj, VALUE fname) { - rb_warning("Dir.exists? is a deprecated name, use Dir.exist? instead"); + rb_warn_deprecated("Dir.exists?", "Dir.exist?"); return rb_file_directory_p(obj, fname); } @@ -3368,7 +3321,7 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) path = RSTRING_PTR(dirname); #if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT - if (!enclose_io_is_path(path)) { + { 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) @@ -3394,16 +3347,6 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) return result; } -/* - * Objects of class Dir are directory streams representing - * directories in the underlying file system. They provide a variety - * of ways to list directories and their contents. See also File. - * - * The directory used in these examples contains the two regular files - * (config.h and main.rb), the parent - * directory (..), and the directory itself - * (.). - */ void Init_Dir(void) { @@ -3412,13 +3355,11 @@ Init_Dir(void) rb_include_module(rb_cDir, rb_mEnumerable); rb_define_alloc_func(rb_cDir, dir_s_alloc); - rb_define_singleton_method(rb_cDir, "open", dir_s_open, -1); rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, -1); rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1); rb_define_singleton_method(rb_cDir, "each_child", dir_s_each_child, -1); rb_define_singleton_method(rb_cDir, "children", dir_s_children, -1); - rb_define_method(rb_cDir,"initialize", dir_initialize, -1); rb_define_method(rb_cDir,"fileno", dir_fileno, 0); rb_define_method(rb_cDir,"path", dir_path, 0); rb_define_method(rb_cDir,"to_path", dir_path, 0); @@ -3444,8 +3385,6 @@ Init_Dir(void) rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1); rb_define_singleton_method(rb_cDir,"home", dir_s_home, -1); - rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1); - rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1); rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1); rb_define_singleton_method(rb_cDir,"exists?", rb_dir_exists_p, 1); rb_define_singleton_method(rb_cDir,"empty?", rb_dir_s_empty_p, 1); @@ -3500,3 +3439,5 @@ Init_Dir(void) */ rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME)); } + +#include "dir.rbinc" diff --git a/ruby/dir.rb b/ruby/dir.rb new file mode 100644 index 000000000..115f06877 --- /dev/null +++ b/ruby/dir.rb @@ -0,0 +1,314 @@ +# Objects of class Dir are directory streams representing +# directories in the underlying file system. They provide a variety +# of ways to list directories and their contents. See also File. +# +# The directory used in these examples contains the two regular files +# (config.h and main.rb), the parent +# directory (..), and the directory itself +# (.). +# +# == What's Here +# +# First, what's elsewhere. \Class \Dir: +# +# - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. +# - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], +# which provides dozens of additional methods. +# +# Here, class \Dir provides methods that are useful for: +# +# - {Reading}[#class-Dir-label-Reading] +# - {Setting}[#class-Dir-label-Setting] +# - {Querying}[#class-Dir-label-Querying] +# - {Iterating}[#class-Dir-label-Iterating] +# - {Other}[#class-Dir-label-Other] +# +# === Reading +# +# - #close:: Closes the directory stream for +self+. +# - #pos=:: Sets the position in the directory stream for +self+. +# - #read:: Reads and returns the next entry in the directory stream for +self+. +# - #rewind:: Sets the position in the directory stream for +self+ to the first entry. +# - #seek:: Sets the position in the directory stream for +self+ +# the entry at the given offset. +# +# === Setting +# +# - ::chdir:: Changes the working directory of the current process +# to the given directory. +# - ::chroot:: Changes the file-system root for the current process +# to the given directory. +# +# === Querying +# +# - ::[]:: Same as ::glob without the ability to pass flags. +# - ::children:: Returns an array of names of the children +# (both files and directories) of the given directory, +# but not including . or ... +# - ::empty?:: Returns whether the given path is an empty directory. +# - ::entries:: Returns an array of names of the children +# (both files and directories) of the given directory, +# including . and ... +# - ::exist?:: Returns whether the given path is a directory. +# - ::getwd (aliased as #pwd):: Returns the path to the current working directory. +# - ::glob:: Returns an array of file paths matching the given pattern and flags. +# - ::home:: Returns the home directory path for a given user or the current user. +# - #children:: Returns an array of names of the children +# (both files and directories) of +self+, +# but not including . or ... +# - #fileno:: Returns the integer file descriptor for +self+. +# - #path (aliased as #to_path):: Returns the path used to create +self+. +# - #tell (aliased as #pos):: Returns the integer position +# in the directory stream for +self+. +# +# === Iterating +# +# - ::each_child:: Calls the given block with each entry in the given directory, +# but not including . or ... +# - ::foreach:: Calls the given block with each entryin the given directory, +# including . and ... +# - #each:: Calls the given block with each entry in +self+, +# including . and ... +# - #each_child:: Calls the given block with each entry in +self+, +# but not including . or ... +# +# === Other +# +# - ::mkdir:: Creates a directory at the given path, with optional permissions. +# - ::new:: Returns a new \Dir for the given path, with optional encoding. +# - ::open:: Same as ::new, but if a block is given, yields the \Dir to the block, +# closing it upon block exit. +# - ::unlink (aliased as ::delete and ::rmdir):: Removes the given directory. +# - #inspect:: Returns a string description of +self+. +class Dir + # call-seq: + # Dir.open( string ) -> aDir + # Dir.open( string, encoding: enc ) -> aDir + # Dir.open( string ) {| aDir | block } -> anObject + # Dir.open( string, encoding: enc ) {| aDir | block } -> anObject + # + # The optional encoding keyword argument specifies the encoding of the directory. + # If not specified, the filesystem encoding is used. + # + # With no block, open is a synonym for Dir::new. If a + # block is present, it is passed aDir as a parameter. The + # directory is closed at the end of the block, and Dir::open returns + # the value of the block. + def self.open(name, encoding: nil, &block) + dir = Primitive.dir_s_open(name, encoding) + if block + begin + yield dir + ensure + Primitive.dir_s_close(dir) + end + else + dir + end + end + + # call-seq: + # Dir.new( string ) -> aDir + # Dir.new( string, encoding: enc ) -> aDir + # + # Returns a new directory object for the named directory. + # + # The optional encoding keyword argument specifies the encoding of the directory. + # If not specified, the filesystem encoding is used. + def initialize(name, encoding: nil) + Primitive.dir_initialize(name, encoding) + end + + # call-seq: + # Dir[ string [, string ...] [, base: path] [, sort: true] ] -> array + # + # Equivalent to calling + # Dir.glob([string,...], 0). + def self.[](*args, base: nil, sort: true) + Primitive.dir_s_aref(args, base, sort) + end + + # call-seq: + # Dir.glob( pattern, [flags], [base: path] [, sort: true] ) -> array + # Dir.glob( pattern, [flags], [base: path] [, sort: true] ) { |filename| block } -> nil + # + # Expands +pattern+, which is a pattern string or an Array of pattern + # strings, and returns an array containing the matching filenames. + # If a block is given, calls the block once for each matching filename, + # passing the filename as a parameter to the block. + # + # The optional +base+ keyword argument specifies the base directory for + # interpreting relative pathnames instead of the current working directory. + # As the results are not prefixed with the base directory name in this + # case, you will need to prepend the base directory name if you want real + # paths. + # + # The results which matched single wildcard or character set are sorted in + # binary ascending order, unless +false+ is given as the optional +sort+ + # keyword argument. The order of an Array of pattern strings and braces + # are preserved. + # + # Note that the pattern is not a regexp, it's closer to a shell glob. + # See File::fnmatch for the meaning of the +flags+ parameter. + # Case sensitivity depends on your system (+File::FNM_CASEFOLD+ is ignored). + # + # *:: + # Matches any file. Can be restricted by other values in the glob. + # Equivalent to /.*/mx in regexp. + # + # *:: Matches all files + # c*:: Matches all files beginning with c + # *c:: Matches all files ending with c + # \*c\*:: Match all files that have c in them + # (including at the beginning or end). + # + # Note, this will not match Unix-like hidden files (dotfiles). In order + # to include those in the match results, you must use the + # File::FNM_DOTMATCH flag or something like "{*,.*}". + # + # **:: + # Matches directories recursively if followed by /. If + # this path segment contains any other characters, it is the same as the + # usual *. + # + # ?:: + # Matches any one character. Equivalent to /.{1}/ in regexp. + # + # [set]:: + # Matches any one character in +set+. Behaves exactly like character sets + # in Regexp, including set negation ([^a-z]). + # + # {p,q}:: + # Matches either literal p or literal q. + # Equivalent to pattern alternation in regexp. + # + # Matching literals may be more than one character in length. More than + # two literals may be specified. + # + # \\:: + # Escapes the next metacharacter. + # + # Note that this means you cannot use backslash on windows as part of a + # glob, i.e. Dir["c:\\foo*"] will not work, use + # Dir["c:/foo*"] instead. + # + # Examples: + # + # Dir["config.?"] #=> ["config.h"] + # Dir.glob("config.?") #=> ["config.h"] + # Dir.glob("*.[a-z][a-z]") #=> ["main.rb"] + # Dir.glob("*.[^r]*") #=> ["config.h"] + # Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"] + # Dir.glob("*") #=> ["config.h", "main.rb"] + # Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "config.h", "main.rb"] + # Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"] + # + # Dir.glob("**/*.rb") #=> ["main.rb", + # # "lib/song.rb", + # # "lib/song/karaoke.rb"] + # + # Dir.glob("**/*.rb", base: "lib") #=> ["song.rb", + # # "song/karaoke.rb"] + # + # Dir.glob("**/lib") #=> ["lib"] + # + # Dir.glob("**/lib/**/*.rb") #=> ["lib/song.rb", + # # "lib/song/karaoke.rb"] + # + # Dir.glob("**/lib/*.rb") #=> ["lib/song.rb"] + def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true) + Primitive.dir_s_glob(pattern, flags, base, sort) + end +end + +class << File + # call-seq: + # File.fnmatch( pattern, path, [flags] ) -> (true or false) + # File.fnmatch?( pattern, path, [flags] ) -> (true or false) + # + # Returns true if +path+ matches against +pattern+. The pattern is not a + # regular expression; instead it follows rules similar to shell filename + # globbing. It may contain the following metacharacters: + # + # *:: + # Matches any file. Can be restricted by other values in the glob. + # Equivalent to /.*/x in regexp. + # + # *:: Matches all regular files + # c*:: Matches all files beginning with c + # *c:: Matches all files ending with c + # \*c*:: Matches all files that have c in them + # (including at the beginning or end). + # + # To match hidden files (that start with a .) set the + # File::FNM_DOTMATCH flag. + # + # **:: + # Matches directories recursively or files expansively. + # + # ?:: + # Matches any one character. Equivalent to /.{1}/ in regexp. + # + # [set]:: + # Matches any one character in +set+. Behaves exactly like character sets + # in Regexp, including set negation ([^a-z]). + # + # \\:: + # Escapes the next metacharacter. + # + # {a,b}:: + # Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled. + # Behaves like a Regexp union ((?:a|b)). + # + # +flags+ is a bitwise OR of the FNM_XXX constants. The same + # glob pattern and flags are used by Dir::glob. + # + # Examples: + # + # File.fnmatch('cat', 'cat') #=> true # match entire string + # File.fnmatch('cat', 'category') #=> false # only match partial string + # + # File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default + # File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB + # + # File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character + # File.fnmatch('c??t', 'cat') #=> false # ditto + # File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters + # File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto + # File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression + # File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!') + # + # File.fnmatch('cat', 'CAT') #=> false # case sensitive + # File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive + # File.fnmatch('cat', 'CAT', File::FNM_SYSCASE) #=> true or false # depends on the system default + # + # File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME + # File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto + # File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto + # + # File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary + # File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary + # File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary + # File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression + # + # File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading + # File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default. + # File.fnmatch('.*', '.profile') #=> true + # + # File.fnmatch('**/*.rb', 'main.rb') #=> false + # File.fnmatch('**/*.rb', './main.rb') #=> false + # File.fnmatch('**/*.rb', 'lib/song.rb') #=> true + # File.fnmatch('**.rb', 'main.rb') #=> true + # File.fnmatch('**.rb', './main.rb') #=> false + # File.fnmatch('**.rb', 'lib/song.rb') #=> true + # File.fnmatch('*', 'dave/.profile') #=> true + # + # File.fnmatch('**/foo', 'a/b/c/foo', File::FNM_PATHNAME) #=> true + # File.fnmatch('**/foo', '/a/b/c/foo', File::FNM_PATHNAME) #=> true + # File.fnmatch('**/foo', 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true + # File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME) #=> false + # File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true + def fnmatch(pattern, path, flags = 0) + end + alias fnmatch? fnmatch +end if false diff --git a/ruby/dln.c b/ruby/dln.c index eb738deeb..44e8c06d0 100644 --- a/ruby/dln.c +++ b/ruby/dln.c @@ -23,15 +23,12 @@ static void dln_loaderror(const char *format, ...); #endif #include "dln.h" #include "internal.h" +#include "internal/compilers.h" #ifdef HAVE_STDLIB_H # include #endif -#ifdef USE_DLN_A_OUT -char *dln_argv0; -#endif - #if defined(HAVE_ALLOCA_H) #include #endif @@ -98,7 +95,7 @@ dln_loaderror(const char *format, ...) } #endif -#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP) +#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP) /* dynamic load with dlopen() */ # define USE_DLN_DLOPEN #endif @@ -116,10 +113,6 @@ dln_loaderror(const char *format, ...) #define isdirsep(x) ((x) == '/') #endif -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - static size_t init_funcname_len(const char **file) { @@ -151,943 +144,6 @@ static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX *(buf) = tmp;\ } while (0) -#ifdef USE_DLN_A_OUT - -#ifndef LIBC_NAME -# define LIBC_NAME "libc.a" -#endif - -#ifndef DLN_DEFAULT_LIB_PATH -# define DLN_DEFAULT_LIB_PATH "/lib:/usr/lib:/usr/local/lib:." -#endif - -#include - -static int dln_errno; - -#define DLN_ENOEXEC ENOEXEC /* Exec format error */ -#define DLN_ECONFL 1201 /* Symbol name conflict */ -#define DLN_ENOINIT 1202 /* No initializer given */ -#define DLN_EUNDEF 1203 /* Undefine symbol remains */ -#define DLN_ENOTLIB 1204 /* Not a library file */ -#define DLN_EBADLIB 1205 /* Malformed library file */ -#define DLN_EINIT 1206 /* Not initialized */ - -static int dln_init_p = 0; - -#include -#include -#ifndef N_COMM -# define N_COMM 0x12 -#endif -#ifndef N_MAGIC -# define N_MAGIC(x) (x).a_magic -#endif - -#define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC) - -#include "ruby/util.h" -#include "ruby/st.h" - -static st_table *sym_tbl; -static st_table *undef_tbl; - -static int load_lib(); - -static int -load_header(int fd, struct exec *hdrp, long disp) -{ - int size; - - lseek(fd, disp, 0); - size = read(fd, hdrp, sizeof(struct exec)); - if (size == -1) { - dln_errno = errno; - return -1; - } - if (size != sizeof(struct exec) || N_BADMAG(*hdrp)) { - dln_errno = DLN_ENOEXEC; - return -1; - } - return 0; -} - -#if defined(sequent) -#define RELOC_SYMBOL(r) ((r)->r_symbolnum) -#define RELOC_MEMORY_SUB_P(r) ((r)->r_bsr) -#define RELOC_PCREL_P(r) ((r)->r_pcrel || (r)->r_bsr) -#define RELOC_TARGET_SIZE(r) ((r)->r_length) -#endif - -/* Default macros */ -#ifndef RELOC_ADDRESS -#define RELOC_ADDRESS(r) ((r)->r_address) -#define RELOC_EXTERN_P(r) ((r)->r_extern) -#define RELOC_SYMBOL(r) ((r)->r_symbolnum) -#define RELOC_MEMORY_SUB_P(r) 0 -#define RELOC_PCREL_P(r) ((r)->r_pcrel) -#define RELOC_TARGET_SIZE(r) ((r)->r_length) -#endif - -#if defined(__sun) && defined(__sparc) -/* Sparc (Sun 4) macros */ -# undef relocation_info -# define relocation_info reloc_info_sparc -# define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type]) -# define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type]) -# define R_LENGTH(r) (reloc_r_length[(r)->r_type]) -static const int reloc_r_rightshift[] = { - 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0, -}; -static const int reloc_r_bitsize[] = { - 8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16, -}; -static const int reloc_r_length[] = { - 0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -}; -# define R_PCREL(r) \ - ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22) -# define R_SYMBOL(r) ((r)->r_index) -#endif - -#if defined(sequent) -#define R_SYMBOL(r) ((r)->r_symbolnum) -#define R_MEMORY_SUB(r) ((r)->r_bsr) -#define R_PCREL(r) ((r)->r_pcrel || (r)->r_bsr) -#define R_LENGTH(r) ((r)->r_length) -#endif - -#ifndef R_SYMBOL -# define R_SYMBOL(r) ((r)->r_symbolnum) -# define R_MEMORY_SUB(r) 0 -# define R_PCREL(r) ((r)->r_pcrel) -# define R_LENGTH(r) ((r)->r_length) -#endif - -static struct relocation_info * -load_reloc(int fd, struct exec *hdrp, long disp) -{ - struct relocation_info *reloc; - int size; - - lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0); - size = hdrp->a_trsize + hdrp->a_drsize; - reloc = (struct relocation_info*)xmalloc(size); - if (reloc == NULL) { - dln_errno = errno; - return NULL; - } - - if (read(fd, reloc, size) != size) { - dln_errno = errno; - free(reloc); - return NULL; - } - - return reloc; -} - -static struct nlist * -load_sym(int fd, struct exec *hdrp, long disp) -{ - struct nlist * buffer; - struct nlist * sym; - struct nlist * end; - long displ; - int size; - - lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0); - if (read(fd, &size, sizeof(int)) != sizeof(int)) { - goto err_noexec; - } - - buffer = (struct nlist*)xmalloc(hdrp->a_syms + size); - if (buffer == NULL) { - dln_errno = errno; - return NULL; - } - - lseek(fd, disp + N_SYMOFF(*hdrp), 0); - if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) { - free(buffer); - goto err_noexec; - } - - sym = buffer; - end = sym + hdrp->a_syms / sizeof(struct nlist); - displ = (long)buffer + (long)(hdrp->a_syms); - - while (sym < end) { - sym->n_un.n_name = (char*)sym->n_un.n_strx + displ; - sym++; - } - return buffer; - - err_noexec: - dln_errno = DLN_ENOEXEC; - return NULL; -} - -static st_table * -sym_hash(struct exec *hdrp, struct nlist *syms) -{ - st_table *tbl; - struct nlist *sym = syms; - struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist)); - - tbl = st_init_strtable(); - if (tbl == NULL) { - dln_errno = errno; - return NULL; - } - - while (sym < end) { - st_insert(tbl, sym->n_un.n_name, sym); - sym++; - } - return tbl; -} - -static int -dln_init(const char *prog) -{ - char *file, fbuf[MAXPATHLEN]; - int fd; - struct exec hdr; - struct nlist *syms; - - if (dln_init_p == 1) return 0; - - file = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)); - if (file == NULL || (fd = open(file, O_RDONLY)) < 0) { - dln_errno = errno; - return -1; - } - - if (load_header(fd, &hdr, 0) == -1) return -1; - syms = load_sym(fd, &hdr, 0); - if (syms == NULL) { - close(fd); - return -1; - } - sym_tbl = sym_hash(&hdr, syms); - if (sym_tbl == NULL) { /* file may be start with #! */ - char c = '\0'; - char buf[MAXPATHLEN]; - char *p; - - free(syms); - lseek(fd, 0L, 0); - if (read(fd, &c, 1) == -1) { - dln_errno = errno; - return -1; - } - if (c != '#') goto err_noexec; - if (read(fd, &c, 1) == -1) { - dln_errno = errno; - return -1; - } - if (c != '!') goto err_noexec; - - p = buf; - /* skip forwarding spaces */ - while (read(fd, &c, 1) == 1) { - if (c == '\n') goto err_noexec; - if (c != '\t' && c != ' ') { - *p++ = c; - break; - } - } - /* read in command name */ - while (read(fd, p, 1) == 1) { - if (*p == '\n' || *p == '\t' || *p == ' ') break; - p++; - if (p-buf >= MAXPATHLEN) { - dln_errno = ENAMETOOLONG; - return -1; - } - } - *p = '\0'; - - return dln_init(buf); - } - dln_init_p = 1; - undef_tbl = st_init_strtable(); - close(fd); - return 0; - - err_noexec: - close(fd); - dln_errno = DLN_ENOEXEC; - return -1; -} - -static long -load_text_data(int fd, struct exec *hdrp, int bss, long disp) -{ - int size; - unsigned char* addr; - - lseek(fd, disp + N_TXTOFF(*hdrp), 0); - size = hdrp->a_text + hdrp->a_data; - - if (bss == -1) size += hdrp->a_bss; - else if (bss > 1) size += bss; - - addr = (unsigned char*)xmalloc(size); - if (addr == NULL) { - dln_errno = errno; - return 0; - } - - if (read(fd, addr, size) != size) { - dln_errno = errno; - free(addr); - return 0; - } - - if (bss == -1) { - memset(addr + hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss); - } - else if (bss > 0) { - memset(addr + hdrp->a_text + hdrp->a_data, 0, bss); - } - - return (long)addr; -} - -static int -undef_print(char *key, char *value) -{ - fprintf(stderr, " %s\n", key); - return ST_CONTINUE; -} - -static void -dln_print_undef(void) -{ - fprintf(stderr, " Undefined symbols:\n"); - st_foreach(undef_tbl, undef_print, NULL); -} - -static void -dln_undefined(void) -{ - if (undef_tbl->num_entries > 0) { - fprintf(stderr, "dln: Calling undefined function\n"); - dln_print_undef(); - dln_exit(1); - } -} - -struct undef { - char *name; - struct relocation_info reloc; - long base; - char *addr; - union { - char c; - short s; - long l; - } u; -}; - -static st_table *reloc_tbl = NULL; -static void -link_undef(const char *name, long base, struct relocation_info *reloc) -{ - static int u_no = 0; - struct undef *obj; - char *addr = (char*)(reloc->r_address + base); - - obj = (struct undef*)xmalloc(sizeof(struct undef)); - obj->name = strdup(name); - obj->reloc = *reloc; - obj->base = base; - switch (R_LENGTH(reloc)) { - case 0: /* byte */ - obj->u.c = *addr; - break; - case 1: /* word */ - obj->u.s = *(short*)addr; - break; - case 2: /* long */ - obj->u.l = *(long*)addr; - break; - } - if (reloc_tbl == NULL) { - reloc_tbl = st_init_numtable(); - } - st_insert(reloc_tbl, u_no++, obj); -} - -struct reloc_arg { - const char *name; - long value; -}; - -static int -reloc_undef(int no, struct undef *undef, struct reloc_arg *arg) -{ - int datum; - char *address; -#if defined(__sun) && defined(__sparc) - unsigned int mask = 0; -#endif - - if (strcmp(arg->name, undef->name) != 0) return ST_CONTINUE; - address = (char*)(undef->base + undef->reloc.r_address); - datum = arg->value; - - if (R_PCREL(&(undef->reloc))) datum -= undef->base; -#if defined(__sun) && defined(__sparc) - datum += undef->reloc.r_addend; - datum >>= R_RIGHTSHIFT(&(undef->reloc)); - mask = (1 << R_BITSIZE(&(undef->reloc))) - 1; - mask |= mask -1; - datum &= mask; - switch (R_LENGTH(&(undef->reloc))) { - case 0: - *address = undef->u.c; - *address &= ~mask; - *address |= datum; - break; - case 1: - *(short *)address = undef->u.s; - *(short *)address &= ~mask; - *(short *)address |= datum; - break; - case 2: - *(long *)address = undef->u.l; - *(long *)address &= ~mask; - *(long *)address |= datum; - break; - } -#else - switch (R_LENGTH(&(undef->reloc))) { - case 0: /* byte */ - if (R_MEMORY_SUB(&(undef->reloc))) - *address = datum - *address; - else *address = undef->u.c + datum; - break; - case 1: /* word */ - if (R_MEMORY_SUB(&(undef->reloc))) - *(short*)address = datum - *(short*)address; - else *(short*)address = undef->u.s + datum; - break; - case 2: /* long */ - if (R_MEMORY_SUB(&(undef->reloc))) - *(long*)address = datum - *(long*)address; - else *(long*)address = undef->u.l + datum; - break; - } -#endif - free(undef->name); - free(undef); - return ST_DELETE; -} - -static void -unlink_undef(const char *name, long value) -{ - struct reloc_arg arg; - - arg.name = name; - arg.value = value; - st_foreach(reloc_tbl, reloc_undef, &arg); -} - -#ifdef N_INDR -struct indr_data { - char *name0, *name1; -}; - -static int -reloc_repl(int no, struct undef *undef, struct indr_data *data) -{ - if (strcmp(data->name0, undef->name) == 0) { - free(undef->name); - undef->name = strdup(data->name1); - } - return ST_CONTINUE; -} -#endif - -static int -load_1(int fd, long disp, const char *need_init) -{ - static const char *libc = LIBC_NAME; - struct exec hdr; - struct relocation_info *reloc = NULL; - long block = 0; - long new_common = 0; /* Length of new common */ - struct nlist *syms = NULL; - struct nlist *sym; - struct nlist *end; - int init_p = 0; - - if (load_header(fd, &hdr, disp) == -1) return -1; - if (INVALID_OBJECT(hdr)) { - dln_errno = DLN_ENOEXEC; - return -1; - } - reloc = load_reloc(fd, &hdr, disp); - if (reloc == NULL) return -1; - - syms = load_sym(fd, &hdr, disp); - if (syms == NULL) { - free(reloc); - return -1; - } - - sym = syms; - end = syms + (hdr.a_syms / sizeof(struct nlist)); - while (sym < end) { - struct nlist *old_sym; - int value = sym->n_value; - -#ifdef N_INDR - if (sym->n_type == (N_INDR | N_EXT)) { - char *key = sym->n_un.n_name; - - if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) { - if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) { - unlink_undef(key, old_sym->n_value); - free(key); - } - } - else { - struct indr_data data; - - data.name0 = sym->n_un.n_name; - data.name1 = sym[1].n_un.n_name; - st_foreach(reloc_tbl, reloc_repl, &data); - - st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL); - if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) { - free(key); - } - } - sym += 2; - continue; - } -#endif - if (sym->n_type == (N_UNDF | N_EXT)) { - if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) { - old_sym = NULL; - } - - if (value) { - if (old_sym) { - sym->n_type = N_EXT | N_COMM; - sym->n_value = old_sym->n_value; - } - else { - int rnd = - value >= sizeof(double) ? sizeof(double) - 1 - : value >= sizeof(long) ? sizeof(long) - 1 - : sizeof(short) - 1; - - sym->n_type = N_COMM; - new_common += rnd; - new_common &= ~(long)rnd; - sym->n_value = new_common; - new_common += value; - } - } - else { - if (old_sym) { - sym->n_type = N_EXT | N_COMM; - sym->n_value = old_sym->n_value; - } - else { - sym->n_value = (long)dln_undefined; - st_insert(undef_tbl, strdup(sym->n_un.n_name), NULL); - } - } - } - sym++; - } - - block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp); - if (block == 0) goto err_exit; - - sym = syms; - while (sym < end) { - struct nlist *new_sym; - char *key; - - switch (sym->n_type) { - case N_COMM: - sym->n_value += hdr.a_text + hdr.a_data; - case N_TEXT|N_EXT: - case N_DATA|N_EXT: - - sym->n_value += block; - - if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0 - && new_sym->n_value != (long)dln_undefined) { - dln_errno = DLN_ECONFL; - goto err_exit; - } - - key = sym->n_un.n_name; - if (st_delete(undef_tbl, (st_data_t*)&key, NULL) != 0) { - unlink_undef(key, sym->n_value); - free(key); - } - - new_sym = (struct nlist*)xmalloc(sizeof(struct nlist)); - *new_sym = *sym; - new_sym->n_un.n_name = strdup(sym->n_un.n_name); - st_insert(sym_tbl, new_sym->n_un.n_name, new_sym); - break; - - case N_TEXT: - case N_DATA: - sym->n_value += block; - break; - } - sym++; - } - - /* - * First comes the text-relocation - */ - { - struct relocation_info * rel = reloc; - struct relocation_info * rel_beg = reloc + - (hdr.a_trsize/sizeof(struct relocation_info)); - struct relocation_info * rel_end = reloc + - (hdr.a_trsize+hdr.a_drsize)/sizeof(struct relocation_info); - - while (rel < rel_end) { - char *address = (char*)(rel->r_address + block); - long datum = 0; -#if defined(__sun) && defined(__sparc) - unsigned int mask = 0; -#endif - - if (rel >= rel_beg) - address += hdr.a_text; - - if (rel->r_extern) { /* Look it up in symbol-table */ - sym = &(syms[R_SYMBOL(rel)]); - switch (sym->n_type) { - case N_EXT|N_UNDF: - link_undef(sym->n_un.n_name, block, rel); - case N_EXT|N_COMM: - case N_COMM: - datum = sym->n_value; - break; - default: - goto err_exit; - } - } /* end.. look it up */ - else { /* is static */ - switch (R_SYMBOL(rel)) { - case N_TEXT: - case N_DATA: - datum = block; - break; - case N_BSS: - datum = block + new_common; - break; - case N_ABS: - break; - } - } /* end .. is static */ - if (R_PCREL(rel)) datum -= block; - -#if defined(__sun) && defined(__sparc) - datum += rel->r_addend; - datum >>= R_RIGHTSHIFT(rel); - mask = (1 << R_BITSIZE(rel)) - 1; - mask |= mask -1; - datum &= mask; - - switch (R_LENGTH(rel)) { - case 0: - *address &= ~mask; - *address |= datum; - break; - case 1: - *(short *)address &= ~mask; - *(short *)address |= datum; - break; - case 2: - *(long *)address &= ~mask; - *(long *)address |= datum; - break; - } -#else - switch (R_LENGTH(rel)) { - case 0: /* byte */ - if (datum < -128 || datum > 127) goto err_exit; - *address += datum; - break; - case 1: /* word */ - *(short *)address += datum; - break; - case 2: /* long */ - *(long *)address += datum; - break; - } -#endif - rel++; - } - } - - if (need_init) { - int len; - char **libs_to_be_linked = 0; - char *buf; - - if (undef_tbl->num_entries > 0) { - if (load_lib(libc) == -1) goto err_exit; - } - - init_funcname(&buf, need_init); - len = strlen(buf); - - for (sym = syms; symn_un.n_name; - if (name[0] == '_' && sym->n_value >= block) { - if (strcmp(name+1, "dln_libs_to_be_linked") == 0) { - libs_to_be_linked = (char**)sym->n_value; - } - else if (strcmp(name+1, buf) == 0) { - init_p = 1; - ((int (*)())sym->n_value)(); - } - } - } - if (libs_to_be_linked && undef_tbl->num_entries > 0) { - while (*libs_to_be_linked) { - load_lib(*libs_to_be_linked); - libs_to_be_linked++; - } - } - } - free(reloc); - free(syms); - if (need_init) { - if (init_p == 0) { - dln_errno = DLN_ENOINIT; - return -1; - } - if (undef_tbl->num_entries > 0) { - if (load_lib(libc) == -1) goto err_exit; - if (undef_tbl->num_entries > 0) { - dln_errno = DLN_EUNDEF; - return -1; - } - } - } - return 0; - - err_exit: - if (syms) free(syms); - if (reloc) free(reloc); - if (block) free((char*)block); - return -1; -} - -static int target_offset; -static int -search_undef(const char *key, int value, st_table *lib_tbl) -{ - long offset; - - if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE; - target_offset = offset; - return ST_STOP; -} - -struct symdef { - int rb_str_index; - int lib_offset; -}; - -const char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH; - -static int -load_lib(const char *lib) -{ - char *path, *file, fbuf[MAXPATHLEN]; - char *envpath = 0; - char armagic[SARMAG]; - int fd, size; - struct ar_hdr ahdr; - st_table *lib_tbl = NULL; - int *data, nsym; - struct symdef *base; - char *name_base; - - if (dln_init_p == 0) { - dln_errno = DLN_ENOINIT; - return -1; - } - - if (undef_tbl->num_entries == 0) return 0; - dln_errno = DLN_EBADLIB; - - if (lib[0] == '-' && lib[1] == 'l') { - long len = strlen(lib) + 4; - char *p = alloca(len); - snprintf(p, len, "lib%s.a", lib+2); - lib = p; - } - - /* library search path: */ - /* look for environment variable DLN_LIBRARY_PATH first. */ - /* then variable dln_librrb_ary_path. */ - /* if path is still NULL, use "." for path. */ - path = getenv("DLN_LIBRARY_PATH"); - if (path == NULL) path = dln_librrb_ary_path; - else path = envpath = strdup(path); - - file = dln_find_file_r(lib, path, fbuf, sizeof(fbuf)); - if (envpath) free(envpath); - fd = open(file, O_RDONLY); - if (fd == -1) goto syserr; - size = read(fd, armagic, SARMAG); - if (size == -1) goto syserr; - - if (size != SARMAG) { - dln_errno = DLN_ENOTLIB; - goto badlib; - } - size = read(fd, &ahdr, sizeof(ahdr)); - if (size == -1) goto syserr; - if (size != sizeof(ahdr) || sscanf(ahdr.ar_size, "%d", &size) != 1) { - goto badlib; - } - - if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) { - /* make hash table from __.SYMDEF */ - - lib_tbl = st_init_strtable(); - data = (int*)xmalloc(size); - if (data == NULL) goto syserr; - size = read(fd, data, size); - nsym = *data / sizeof(struct symdef); - base = (struct symdef*)(data + 1); - name_base = (char*)(base + nsym) + sizeof(int); - while (nsym > 0) { - char *name = name_base + base->rb_str_index; - - st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr)); - nsym--; - base++; - } - for (;;) { - target_offset = -1; - st_foreach(undef_tbl, search_undef, lib_tbl); - if (target_offset == -1) break; - if (load_1(fd, target_offset, 0) == -1) { - st_free_table(lib_tbl); - free(data); - goto badlib; - } - if (undef_tbl->num_entries == 0) break; - } - free(data); - st_free_table(lib_tbl); - } - else { - /* linear library, need to scan (FUTURE) */ - - for (;;) { - int offset = SARMAG; - int found = 0; - struct exec hdr; - struct nlist *syms, *sym, *end; - - while (undef_tbl->num_entries > 0) { - found = 0; - lseek(fd, offset, 0); - size = read(fd, &ahdr, sizeof(ahdr)); - if (size == -1) goto syserr; - if (size == 0) break; - if (size != sizeof(ahdr) - || sscanf(ahdr.ar_size, "%d", &size) != 1) { - goto badlib; - } - offset += sizeof(ahdr); - if (load_header(fd, &hdr, offset) == -1) - goto badlib; - syms = load_sym(fd, &hdr, offset); - if (syms == NULL) goto badlib; - sym = syms; - end = syms + (hdr.a_syms / sizeof(struct nlist)); - while (sym < end) { - if (sym->n_type == N_EXT|N_TEXT - && st_lookup(undef_tbl, sym->n_un.n_name, NULL)) { - break; - } - sym++; - } - if (sym < end) { - found++; - free(syms); - if (load_1(fd, offset, 0) == -1) { - goto badlib; - } - } - offset += size; - if (offset & 1) offset++; - } - if (found) break; - } - } - close(fd); - return 0; - - syserr: - dln_errno = errno; - badlib: - if (fd >= 0) close(fd); - return -1; -} - -static int -load(const char *file) -{ - int fd; - int result; - - if (dln_init_p == 0) { - if (dln_init(dln_argv0) == -1) return -1; - } - result = strlen(file); - if (file[result-1] == 'a') { - return load_lib(file); - } - - fd = open(file, O_RDONLY); - if (fd == -1) { - dln_errno = errno; - return -1; - } - result = load_1(fd, 0, file); - close(fd); - - return result; -} - -void* -dln_sym(const char *name) -{ - struct nlist *sym; - - if (st_lookup(sym_tbl, name, &sym)) - return (void*)sym->n_value; - return NULL; -} - -#endif /* USE_DLN_A_OUT */ - #ifdef USE_DLN_DLOPEN # include #endif @@ -1144,34 +200,11 @@ dln_strerror(char *message, size_t size) return message; } #define dln_strerror() dln_strerror(message, sizeof message) -#elif ! defined _AIX +#elif defined USE_DLN_DLOPEN static const char * dln_strerror(void) { -#ifdef USE_DLN_A_OUT - char *strerror(); - - switch (dln_errno) { - case DLN_ECONFL: - return "Symbol name conflict"; - case DLN_ENOINIT: - return "No initializer given"; - case DLN_EUNDEF: - return "Unresolved symbols"; - case DLN_ENOTLIB: - return "Not a library file"; - case DLN_EBADLIB: - return "Malformed library file"; - case DLN_EINIT: - return "Not initialized"; - default: - return strerror(dln_errno); - } -#endif - -#ifdef USE_DLN_DLOPEN return (char*)dlerror(); -#endif } #endif @@ -1248,6 +281,8 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine) #endif #ifdef USE_DLN_DLOPEN +# include "ruby/internal/stdbool.h" +# include "internal/warnings.h" COMPILER_WARNING_PUSH #if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0) COMPILER_WARNING_IGNORED(-Wpedantic) @@ -1256,7 +291,8 @@ static bool dln_incompatible_library_p(void *handle) { void *ex = dlsym(handle, EXTERNAL_PREFIX"ruby_xmalloc"); - return ex && ex != ruby_xmalloc; + void *const fp = (void *)ruby_xmalloc; + return ex && ex != fp; } COMPILER_WARNING_POP #endif @@ -1267,7 +303,7 @@ dln_load(const char *file) #if (defined _WIN32 || defined USE_DLN_DLOPEN) && defined RUBY_EXPORT static const char incompatible[] = "incompatible library version"; #endif -#if !defined(_AIX) && !defined(NeXT) +#if defined _WIN32 || defined USE_DLN_DLOPEN const char *error = 0; #endif @@ -1275,7 +311,7 @@ dln_load(const char *file) HINSTANCE handle; WCHAR *winfile; char message[1024]; - void (*init_fct)(); + void (*init_fct)(void); char *buf; /* Load the file as an object one */ @@ -1304,7 +340,7 @@ dln_load(const char *file) } #endif - if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) { + if ((init_fct = (void(*)(void))GetProcAddress(handle, buf)) == NULL) { dln_loaderror("%s - %s\n%s", dln_strerror(), buf, file); } @@ -1312,14 +348,6 @@ dln_load(const char *file) (*init_fct)(); return handle; #else -#ifdef USE_DLN_A_OUT - if (load(file) == -1) { - error = dln_strerror(); - goto failed; - } - return 0; -#else - char *buf; /* Load the file as an object one */ init_funcname(&buf, file); @@ -1329,7 +357,7 @@ dln_load(const char *file) #define DLN_DEFINED { void *handle; - void (*init_fct)(); + void (*init_fct)(void); #ifndef RTLD_LAZY # define RTLD_LAZY 1 @@ -1364,7 +392,7 @@ dln_load(const char *file) } # endif - init_fct = (void(*)())(VALUE)dlsym(handle, buf); + init_fct = (void(*)(void))(VALUE)dlsym(handle, buf); if (init_fct == NULL) { const size_t errlen = strlen(error = dln_strerror()) + 1; error = memcpy(ALLOCA_N(char, errlen), error, errlen); @@ -1383,7 +411,7 @@ dln_load(const char *file) { shl_t lib = NULL; int flags; - void (*init_fct)(); + void (*init_fct)(void); flags = BIND_DEFERRED; lib = shl_load(file, flags, 0); @@ -1407,9 +435,9 @@ dln_load(const char *file) #if defined(_AIX) #define DLN_DEFINED { - void (*init_fct)(); + void (*init_fct)(void); - init_fct = (void(*)())load((char*)file, 1, 0); + init_fct = (void(*)(void))load((char*)file, 1, 0); if (init_fct == NULL) { aix_loaderror(file); } @@ -1438,7 +466,7 @@ dln_load(const char *file) /* "file" is module file name . "buf" is pointer to initial function name with "_" . */ - void (*init_fct)(); + void (*init_fct)(void); dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file); @@ -1464,9 +492,8 @@ dln_load(const char *file) dln_notimplement(); #endif -#endif /* USE_DLN_A_OUT */ #endif -#if !defined(_AIX) && !defined(NeXT) +#if defined(_WIN32) || defined(USE_DLN_DLOPEN) failed: dln_loaderror("%s - %s", error, file); #endif diff --git a/ruby/dln.h b/ruby/dln.h index d98b2607e..902f75345 100644 --- a/ruby/dln.h +++ b/ruby/dln.h @@ -1,3 +1,5 @@ +#ifndef DLN_H +#define DLN_H /********************************************************************** dln.h - @@ -9,24 +11,7 @@ **********************************************************************/ -#ifndef DLN_H -#define DLN_H - -#ifdef __cplusplus -# ifndef HAVE_PROTOTYPES -# define HAVE_PROTOTYPES 1 -# endif -# ifndef HAVE_STDARG_PROTOTYPES -# define HAVE_STDARG_PROTOTYPES 1 -# endif -#endif - -#undef _ -#ifdef HAVE_PROTOTYPES -# define _(args) args -#else -# define _(args) () -#endif +#include "ruby/defines.h" /* for RUBY_SYMBOL_EXPORT_BEGIN */ RUBY_SYMBOL_EXPORT_BEGIN @@ -39,11 +24,6 @@ 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); - -#ifdef USE_DLN_A_OUT -extern char *dln_argv0; -#endif - void *dln_load(const char*); RUBY_SYMBOL_EXPORT_END diff --git a/ruby/dln_find.c b/ruby/dln_find.c index b08612764..96e06d34c 100644 --- a/ruby/dln_find.c +++ b/ruby/dln_find.c @@ -23,10 +23,6 @@ # include #endif -#ifdef USE_DLN_A_OUT -char *dln_argv0; -#endif - #if defined(HAVE_ALLOCA_H) #include #endif @@ -218,7 +214,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, dp[1] == '\\' || #endif dp[1] == '/')) { - char *home; + const char *home; home = getenv("HOME"); if (home != NULL) { @@ -248,26 +244,14 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, /* now append the file name */ i = fnlen; if (fspace < i) { - toolong: - PATHNAME_TOO_LONG(); - goto next; + goto toolong; } fspace -= i; memcpy(bp, fname, i + 1); #if defined(DOSISH) if (exe_flag && !ext) { - needs_extension: - for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) { - if (fspace < strlen(extension[j])) { - PATHNAME_TOO_LONG(); - continue; - } - strlcpy(bp + i, extension[j], fspace); - if (stat(fbuf, &st) == 0) - return fbuf; - } - goto next; + goto needs_extension; } #endif @@ -284,7 +268,25 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, if (*ep == '\0') { return NULL; } + continue; + toolong: + PATHNAME_TOO_LONG(); + goto next; + +#if defined(DOSISH) + needs_extension: + for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) { + if (fspace < strlen(extension[j])) { + PATHNAME_TOO_LONG(); + continue; + } + strlcpy(bp + i, extension[j], fspace); + if (stat(fbuf, &st) == 0) + return fbuf; + } + goto next; +#endif /* otherwise try the next component in the search path */ } } diff --git a/ruby/doc/.document b/ruby/doc/.document index d739c9f6b..ad17aada6 100644 --- a/ruby/doc/.document +++ b/ruby/doc/.document @@ -1,3 +1,4 @@ +*.md *.rdoc NEWS-* syntax diff --git a/ruby/doc/ChangeLog-0.60_to_1.1 b/ruby/doc/ChangeLog-0.60_to_1.1 index bd5f140dc..ff3c376f4 100644 --- a/ruby/doc/ChangeLog-0.60_to_1.1 +++ b/ruby/doc/ChangeLog-0.60_to_1.1 @@ -28,7 +28,7 @@ Fri Aug 8 11:16:50 1997 Yukihiro Matsumoto Thu Aug 7 11:40:01 1997 Yukihiro Matsumoto - * variable.c (mod_constants): lists constants defiend in the + * variable.c (mod_constants): lists constants defined in the modules/classes. * variable.c (rb_const_set): no longer warns about constant @@ -49,7 +49,7 @@ Mon Aug 4 11:50:28 1997 Yukihiro Matsumoto classes (or modules) dynamically. * variable.c (rb_class_path): scan class constants for anonymous - classes/modules to make up pathes. + classes/modules to make up paths. Wed Jul 30 08:45:12 1997 Yukihiro Matsumoto @@ -76,7 +76,7 @@ Wed Jul 23 09:56:55 1997 Yukihiro Matsumoto specified object. * class.c (mod_instance_methods): returns list of method names of - the class instnace. + the class instance. Fri Jul 11 22:38:55 1997 Yukihiro Matsumoto @@ -538,7 +538,7 @@ Wed Mar 12 10:20:30 1997 Yukihiro Matsumoto Mon Mar 10 20:44:22 1997 Yukihiro Matsumoto * re.c (reg_regsub): \& for substitution. \`, \', and \+ are - avaiable also. + available also. Thu Mar 6 01:47:03 1997 Yukihiro Matsumoto diff --git a/ruby/doc/ChangeLog-1.9.3 b/ruby/doc/ChangeLog-1.9.3 index eecfc4432..58e3b6f67 100644 --- a/ruby/doc/ChangeLog-1.9.3 +++ b/ruby/doc/ChangeLog-1.9.3 @@ -5746,7 +5746,7 @@ Wed Mar 2 14:06:01 2011 NARUSE, Yui Wed Mar 2 14:02:29 2011 Shota Fukumori * test/testunit/test_parallel.rb(TestParallel#spawn_runner): - Fix outputing empty line in running test. + Fix outputting empty line in running test. * test/testunit/tests_for_parallel/test_third.rb: Remove `sleep` @@ -5765,7 +5765,7 @@ Tue Mar 1 21:48:22 2011 Shota Fukumori * test/testunit/test_parallel.rb(TestParallelWorker#test_quit_in_test): Fix for above specification change. * test/testunit/test_parallel.rb(TestParallel#spawn_runner): - Fix outputing empty line in running test. + Fix outputting empty line in running test. Tue Mar 1 20:51:57 2011 KOSAKI Motohiro @@ -7541,7 +7541,7 @@ Tue Jan 11 20:32:59 2011 Tanaka Akira Tue Jan 11 13:06:38 2011 NAKAMURA Usaku - * array.c (rb_ary_resize): should care of embeded array when extending + * array.c (rb_ary_resize): should care of embedded array when extending the array. * array.c (rb_ary_resize): need to set capa when changing the real @@ -9563,7 +9563,7 @@ Wed Nov 17 16:09:52 2010 Yuki Sonoda (Yugui) Wed Nov 17 16:04:23 2010 Yuki Sonoda (Yugui) - * test/ruby/envutil.rb (Test::Unit::Assersions#assert_warn): + * test/ruby/envutil.rb (Test::Unit::Assertions#assert_warn): new assertion to assert that a particular warning message is displayed. forward port from branches/ruby_1_9_2@29795. @@ -9781,7 +9781,7 @@ Wed Nov 10 07:20:10 2010 Nobuyoshi Nakada Tue Nov 9 21:57:45 2010 Nobuyoshi Nakada * dln.c (init_funcname): allocate and build initialization - funciton name at once. + function name at once. Tue Nov 9 21:14:54 2010 Nobuyoshi Nakada @@ -62969,7 +62969,7 @@ Thu Jul 12 12:24:29 2007 Nobuyoshi Nakada Thu Jul 12 10:30:46 2007 Nobuyoshi Nakada - * thread.c (thread_start_func_2): moved prototye from thread_*.ci. + * thread.c (thread_start_func_2): moved prototype from thread_*.ci. * thread_pthread.ci (thread_start_func_2): not use a directive inside a macro argument. [ruby-talk:258763] @@ -73273,7 +73273,7 @@ Fri Nov 18 17:35:09 2005 Hidetoshi NAGAI * ext/tk/lib/multi-tk.rb: add restriction to access the entried command table and manipulate other IPs (for reason of security). - Now, a IP object can be controlled by only its master IP or the + Now, an IP object can be controlled by only its master IP or the default IP. * ext/tk/lib/remote-tk.rb: add restriction to manipulate. @@ -76346,7 +76346,7 @@ Tue Jul 5 14:52:56 2005 Hidetoshi NAGAI * ext/tk/lib/tk/validation.rb: ditto. - * ext/tk/lib/tk/namespace.rb: arguemnts for TclTkIp#_merge_tklist + * ext/tk/lib/tk/namespace.rb: arguments for TclTkIp#_merge_tklist should be UTF-8 strings. Mon Jul 4 19:29:32 2005 Hirokazu Yamamoto @@ -77285,7 +77285,7 @@ Sun May 15 09:57:30 2005 Nobuyoshi Nakada Sat May 14 23:59:11 2005 Nobuyoshi Nakada * error.c (exc_exception, {exit,name_err,syserr}_initialize): call - Execption#initialize. fixed: [ruby-talk:142593] + Exception#initialize. fixed: [ruby-talk:142593] Sat May 14 23:56:41 2005 Erik Huelsmann @@ -77435,7 +77435,7 @@ Sat Apr 30 06:57:39 2005 GOTOU Yuuzou (suggested by Tatsuki Sugiura) * lib/webrick/cgi.rb - (WEBrick::CGI#initalize): set a dummy to @config[:ServerSoftware] + (WEBrick::CGI#initialize): set a dummy to @config[:ServerSoftware] if SERVER_SOFTWARE environment variable is not given. (WEBrick::CGI#start): req.path_info must be a String. (WEBrick::CGI::Socket#request_line): treat REQUEST_METHOD, PATH_INFO @@ -82696,7 +82696,7 @@ Tue Sep 14 20:24:49 2004 Minero Aoki * ext/ripper/depend: Borland make does not accept pipes in Makefile rules. [ruby-dev:24589] - * ext/ripper/depend: separate rules for developpers. + * ext/ripper/depend: separate rules for developers. * ext/ripper/Makefile.dev: new file. @@ -82931,7 +82931,7 @@ Wed Sep 8 18:44:03 2004 Nobuyoshi Nakada Wed Sep 8 15:19:49 2004 Hidetoshi NAGAI - * ext/tcltklib/tcltklib.c (ip_init): cannot create a IP at level 4 + * ext/tcltklib/tcltklib.c (ip_init): cannot create an IP at level 4 * ext/tk/lib/multi-tk.rb: improve 'exit' operation, security check, and error treatment @@ -88452,7 +88452,7 @@ Tue Dec 16 03:17:29 2003 why the lucky stiff Tue Dec 16 01:14:44 2003 Nobuyoshi Nakada - * eval.c (catch_timer): check rb_thread_crtical in main native + * eval.c (catch_timer): check rb_thread_critical in main native thread. * eval.c (thread_timer): just sends signals periodically, to @@ -92076,7 +92076,7 @@ Mon Sep 1 16:59:10 2003 Nobuyoshi Nakada * eval.c (rb_thread_start_0): should not error_print() within terminated thread, because $stderr used by it might be - overriden now. [ruby-dev:21280] + overridden now. [ruby-dev:21280] Sun Aug 31 22:46:55 2003 WATANABE Hirofumi @@ -92616,7 +92616,7 @@ Fri Aug 8 03:22:28 2003 GOTOU Yuuzou Thu Aug 7 14:40:37 2003 WATANABE Hirofumi - * cygwin/GNUmakefile: better --disbale-shared option support. + * cygwin/GNUmakefile: better --disable-shared option support. * cygwin/GNUmakefile: add forwarding DLL target for cygwin. diff --git a/ruby/doc/ChangeLog-2.0.0 b/ruby/doc/ChangeLog-2.0.0 index a1a79b8dc..b51d74220 100644 --- a/ruby/doc/ChangeLog-2.0.0 +++ b/ruby/doc/ChangeLog-2.0.0 @@ -9758,7 +9758,7 @@ Thu Aug 23 16:20:04 2012 Koichi Sasada are b10. If flonum is activated, then USE_FLONUM macro is 1. I'll write detailed in this technique on - https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/Flonum_tech + https://bugs.ruby-lang.org/projects/ruby-master/wiki/Flonum_tech * benchmark/bmx_temp.rb: add an benchmark for simple Float calculation. @@ -13008,7 +13008,7 @@ Thu Jun 7 15:53:03 2012 Koichi Sasada * .gdbinit: add function `trace_machine_instructions' to trace in native machine assemble. - See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MachineInstructionsTraceWithGDB + See https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB for more details. Wed Jun 6 21:31:21 2012 Tanaka Akira @@ -14711,7 +14711,7 @@ Fri Apr 27 01:45:05 2012 NARUSE, Yui (22) main thread waits at gvl_yield:112 (native_cond_wait) As described above, the main thread can't escape from rb_threadptr_execute_interrupts_common. - See extended memo: http://bugs.ruby-lang.org/projects/ruby-trunk/wiki/R35480_ExtendedMemo + See extended memo: http://bugs.ruby-lang.org/projects/ruby-master/wiki/R35480_ExtendedMemo Fri Apr 27 07:15:07 2012 Tanaka Akira diff --git a/ruby/doc/ChangeLog-2.1.0 b/ruby/doc/ChangeLog-2.1.0 index 76edfd3ce..5b670b31c 100644 --- a/ruby/doc/ChangeLog-2.1.0 +++ b/ruby/doc/ChangeLog-2.1.0 @@ -3596,7 +3596,7 @@ Tue Oct 22 19:19:05 2013 Koichi Sasada maintains all pages. For example, pages are allocated from the heap_pages. - See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/GC_design + See https://bugs.ruby-lang.org/projects/ruby-master/wiki/GC_design and https://bugs.ruby-lang.org/attachments/4015/data-heap_structure_with_multiple_heaps.png for more details. @@ -8612,7 +8612,7 @@ Wed Jul 17 14:31:13 2013 Koichi Sasada (4) heap::sorted is an array of "slots", sorted by an address of slot::body. - See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/GC_design + See https://bugs.ruby-lang.org/projects/ruby-master/wiki/GC_design for more details (figure). * gc.c: Avoid "heaps" terminology. It is ambiguous. diff --git a/ruby/doc/ChangeLog-2.4.0 b/ruby/doc/ChangeLog-2.4.0 index 96b5ecb07..a297a579d 100644 --- a/ruby/doc/ChangeLog-2.4.0 +++ b/ruby/doc/ChangeLog-2.4.0 @@ -792,7 +792,7 @@ Wed Oct 5 12:57:21 2016 Richard Schneeman Wed Oct 5 11:47:19 2016 SHIBATA Hiroshi - * io.c: Fixed equivalent ruby code with core implemention. + * io.c: Fixed equivalent ruby code with core implementation. [fix GH-1429][ci skip] Patch by @sos4nt Wed Oct 5 11:36:21 2016 SHIBATA Hiroshi @@ -888,7 +888,7 @@ Sun Oct 2 02:03:06 2016 NAKAMURA Usaku Sat Oct 1 23:08:47 2016 NAKAMURA Usaku - * ext/date/date_parse.c (date_zone_to_diff): it's nonsence and really + * ext/date/date_parse.c (date_zone_to_diff): it's nonsense and really harm that to use unary minus operator with unsigned value. get rid of test failures introduced at r56312. diff --git a/ruby/doc/ChangeLog-YARV b/ruby/doc/ChangeLog-YARV index a8b999dff..83df05c52 100644 --- a/ruby/doc/ChangeLog-YARV +++ b/ruby/doc/ChangeLog-YARV @@ -493,7 +493,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * thread.c : remove some line break - * yarvcore.c : reoder initialize sequence to mark main thread + * yarvcore.c : reorder initialize sequence to mark main thread 2006-08-18(Fri) 16:51:34 +0900 Koichi Sasada @@ -1481,7 +1481,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * yarvcore.c : ditto - * yarvtest/test_thread.rb : separete assersions to tests + * yarvtest/test_thread.rb : separate assertions to tests 2006-02-21(Tue) 02:13:33 +900 Yukihiro Matsumoto @@ -1503,7 +1503,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * yarvcore.c : support Proc#dup/clone, Binding#dup/clone - * sample/test.rb : remove unsupport features (Proc as Binding) + * sample/test.rb : remove unsupported features (Proc as Binding) 2006-02-20(Mon) 16:28:59 +0900 Koichi Sasada @@ -1560,7 +1560,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * yarvtest/test_thread.rb : add a test for above * vm.h, vm.c, vm_dump.c, insns.def : add FRAME_MAGIC_LAMBDA and - support return from lambda (especially retrun from method defined + support return from lambda (especially return from method defined by "define_method") * yarvtest/test_method.rb : add a test for above @@ -1606,7 +1606,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * vm.c : "return" from lambda{} break block - * eval.c : Unsupport Proc as Binding + * eval.c : Unsupported Proc as Binding * test/ruby/test_eval.rb : apply above changes @@ -3816,7 +3816,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2005-12-29(Thu) 12:27:12 +0900 Koichi Sasada * compile.c, yarvcore.h : - remvoe needless yarv_iseq_t#rewind_frame_size + remove needless yarv_iseq_t#rewind_frame_size 2005-12-29(Thu) 11:17:58 +0900 Koichi Sasada @@ -4530,7 +4530,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * vm.c : fix return process - * vm_macro.def : fix option prameters + * vm_macro.def : fix option parameters * yarvtest/test_method.rb : add tests for above @@ -4555,7 +4555,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * eval_intern.h : fix PASS_PASSED_BLOCK() - * eval_load.c : fix re-enter require (temporalily) + * eval_load.c : fix re-enter require (temporarily) * insns.def : permit re-open class when superclass is same @@ -4729,7 +4729,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * eval.c, eval_intern.h, vm.c, eval_jump.h, yarvcore.h : re-define PUSH/POP/EXEC/JUMP_TAG to use thread local tag - * inits.c, yarvcore.c : fix boostrap + * inits.c, yarvcore.c : fix bootstrap 2005-10-03(Mon) 22:28:24 +0900 Koichi Sasada @@ -4909,7 +4909,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2005-09-14(Wed) 06:11:43 +0900 Koichi Sasada * yarvcore.h, vm_evalbody.h, vm.h, vm_dump.c, - compile.c, yarvcore.c : use #ifdef insted of #if for recognize + compile.c, yarvcore.c : use #ifdef instead of #if for recognize vm options * vm_opts.h : fix default options @@ -4973,13 +4973,13 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * common.mk : rule test -> test2, test1 -> test - * compile.c : fix when clause bug and splat arugment + * compile.c : fix when clause bug and splat argument 2005-08-17(Wed) 05:22:31 +0900 Koichi Sasada * compile.c : fix block local parameter setting routine and support - massign in block parameter initialze + massign in block parameter initialize * yarvtest/test_yield.rb : add tests for above @@ -5394,7 +5394,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * tmpl/vmtc.inc.tmpl : add const prefix - * /rb/asm_parse.rb, extconf.rb : added and make assembler analised output + * /rb/asm_parse.rb, extconf.rb : added and make assembler analysed output * opt_operand.def : add send operands unification @@ -5654,7 +5654,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2005-03-01(Tue) 13:50:04 +0900 Koichi Sasada * yarvcore.c (yarvcore_eval_parsed) : added - (separeted from yarvcore_eval) + (separated from yarvcore_eval) * yarvcore.c, compile.c : iseq_translate_direct_threaded_code is moved to compile.c @@ -5806,7 +5806,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * compiled.c : add constant pool - * vm_evalbody.inc, call_cfunc.inc, vm.c : separeted from vm.c + * vm_evalbody.inc, call_cfunc.inc, vm.c : separated from vm.c * insns.def : fix return val @@ -5840,7 +5840,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * depend : fixed for above - * extconf.rb : add option --(enable|disalbe)-opt-insns-unification + * extconf.rb : add option --(enable|disable)-opt-insns-unification 2005-02-11(Fri) 12:14:39 +0900 Koichi Sasada @@ -5957,7 +5957,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * evalc.patch : fix for above - * benchmark/bm_lists.rb : fix (unsupport block passing) + * benchmark/bm_lists.rb : fix (unsupported block passing) * benchmark/run.rb : use full path to ruby @@ -6014,7 +6014,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * test/test_block.rb (test_ifunc) : test for above - * vm.c (get_block_objec, thread_make_env_object) : fixed bugs + * vm.c (get_block_object, thread_make_env_object) : fixed bugs * test/test_bin.rb (test_xstr) : remove `ls` test @@ -6067,7 +6067,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2005-01-04(Tue) 06:25:45 +0900 Koichi Sasada - * compile.h : COMPILE_ERROR break contol (instead of return) + * compile.h : COMPILE_ERROR break control (instead of return) * compile.c : support NODE_MASGN @@ -6108,7 +6108,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * insns.def : support super, zsuper (currently, super can't handle with block) - * test/test_bin.rb : add test for op_asgin2, op_assgin_and/or + * test/test_bin.rb : add test for op_assign2, op_assign_and/or * test/test_class.rb : add test for super, zsuper @@ -6272,7 +6272,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * opt_operand.def : add unification insn send * rb/insns2vm.rb : define symbol instead of declare const - variable (for more optmize on VC) + variable (for more optimize on VC) * insns.def : move enter point in send @@ -6322,7 +6322,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2004-12-02(Thu) 13:20:41 +0900 Koichi Sasada * yarvcore.c, vm.h, vm.c, insns.def, insnhelper.h, yarvutil.rb : - add usage analisys framework + add usage analysis framework * disasm.c : insn_operand_intern to separate function @@ -6489,7 +6489,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada 2004-11-01(Mon) 04:45:54 +0900 Koichi Sasada * yarvcore.h, compile.c, debug.c, version.h : - redesgin gc debug scheme (GC_CHECK()) + redesign gc debug scheme (GC_CHECK()) * yarvcore.c : mark iseqobj->current_block on GC @@ -6820,7 +6820,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada * depend : add tbench rule - * yarvcore.h : add 'exten ID idBackquote' + * yarvcore.h : add 'extern ID idBackquote' 2004-05-18(Tue) 00:09:48 +0900 Koichi Sasada diff --git a/ruby/doc/NEWS-2.0.0 b/ruby/doc/NEWS-2.0.0 index 414789dcd..e070b1997 100644 --- a/ruby/doc/NEWS-2.0.0 +++ b/ruby/doc/NEWS-2.0.0 @@ -116,8 +116,7 @@ with all sufficient information, see the ChangeLog file. corresponding method in the prepending module. * added Module.prepended and Module.prepend_features, similar to included and append_features. - * added Module#refine, which extends a class or module locally. - [experimental] + * added Module#refine, which extends a class or module locally. [experimental] * extended method: * Module#define_method accepts a UnboundMethod from a Module. * Module#const_get accepts a qualified constant string, e.g. @@ -377,7 +376,7 @@ with all sufficient information, see the ChangeLog file. :TLSv1_2, :TLSv1_2_server, :TLSv1_2_client or :TLSv1_1, :TLSv1_1_server :TLSv1_1_client. The version being effectively used can be queried with OpenSSL::SSL#ssl_version. Furthermore, it is also possible to - blacklist the new TLS versions with OpenSSL::SSL:OP_NO_TLSv1_1 and + blacklist the new TLS versions with OpenSSL::SSL::OP_NO_TLSv1_1 and OpenSSL::SSL::OP_NO_TLSv1_2. * Added OpenSSL::SSL::SSLContext#renegotiation_cb. A user-defined callback may be set which gets called whenever a new handshake is negotiated. This diff --git a/ruby/doc/NEWS-2.1.0 b/ruby/doc/NEWS-2.1.0 index 5d4152b8d..26f2374e9 100644 --- a/ruby/doc/NEWS-2.1.0 +++ b/ruby/doc/NEWS-2.1.0 @@ -155,7 +155,7 @@ with all sufficient information, see the ChangeLog file. Foo#foo private. * Kernel#untrusted?, untrust, and trust - * These methods are deprecated and their behavior is same as tainted?, + * These methods are deprecated and their behavior is the same as tainted?, taint, and untaint, respectively. If $VERBOSE is true, they show warnings. * Module#ancestors diff --git a/ruby/doc/NEWS-2.2.0 b/ruby/doc/NEWS-2.2.0 index 5564c606a..8b2bd0ba0 100644 --- a/ruby/doc/NEWS-2.2.0 +++ b/ruby/doc/NEWS-2.2.0 @@ -90,7 +90,7 @@ with all sufficient information, see the ChangeLog file. * Method * New methods: - * Method#curry([arity]) returns a curried Proc. + * Method#curry([ arity ]) returns a curried Proc. * Method#super_method returns a Method of superclass, which would be called when super is used. @@ -250,8 +250,7 @@ with all sufficient information, see the ChangeLog file. * Logger::Application is extracted to logger-application gem. It's unmaintain code. * ObjectSpace (after requiring "objspace") - * ObjectSpace.memsize_of(obj) returns a size includes sizeof(RVALUE). - [Bug #8984] + * ObjectSpace.memsize_of(obj) returns a size includes sizeof(RVALUE). [Bug #8984] * Prime * incompatible changes: @@ -319,7 +318,7 @@ with all sufficient information, see the ChangeLog file. * rb_sym2str() added. This is almost same as `rb_id2str(SYM2ID(sym))` but not pinning a dynamic symbol. -* rb_str_cat_cstr() added. This is same as `rb_str_cat2()`. +* rb_str_cat_cstr() added. This is the same as `rb_str_cat2()`. * `rb_str_substr()` and `rb_str_subseq()` will share middle of a string, but not only the end of a string, in the future. Therefore, result @@ -353,8 +352,7 @@ with all sufficient information, see the ChangeLog file. * VM * Use frozen string literals for Hash#[] and Hash#[]= * Fast keyword arguments passing [Feature #10440] - * Allow to receive huge splatted array by a rest argument - [Feature #10440] + * Allow to receive huge splatted array by a rest argument [Feature #10440] * Process * Process creation methods, such as spawn(), uses vfork() system call. diff --git a/ruby/doc/NEWS-2.3.0 b/ruby/doc/NEWS-2.3.0 index 489aba4a8..065515257 100644 --- a/ruby/doc/NEWS-2.3.0 +++ b/ruby/doc/NEWS-2.3.0 @@ -16,20 +16,19 @@ with all sufficient information, see the ChangeLog file or Redmine * frozen-string-literal pragma: - * new pragma, frozen-string-literal has been experimentally introduced. - [Feature #8976] + * new pragma, frozen-string-literal has been experimentally introduced. [Feature #8976] * besides, --enable/--disable=frozen-string-literal options also have been introduced. [Feature #8976] * command line options --debug or --debug=frozen-string-literal enable additional debugging mode which shows created location with at frozen - object error (RuntimeError). - [Feature #11725] + object error (RuntimeError). [Feature #11725] * safe navigation operator: * new method call syntax, `object&.foo', method #foo is called on - `object' if it is not nil. - this is similar to `try!' in Active Support, except: + `object' if it is not nil. [Feature #11537] + + This is similar to `try!' in Active Support, except: * method name is syntactically required obj.try! {} # valid obj&. {} # syntax error @@ -38,7 +37,6 @@ with all sufficient information, see the ChangeLog file or Redmine obj&.foo(bar()) # bar() is conditionally evaluated * attribute assignment is valid obj&.attr += 1 - [Feature #11537] * the did_you_mean gem: @@ -53,15 +51,13 @@ with all sufficient information, see the ChangeLog file or Redmine * indented here document: * new string literal, here document starts with `<<~`. - refer doc/syntax/literals.rdoc for more details. - [Feature #9098] + refer doc/syntax/literals.rdoc for more details. [Feature #9098] === Core classes updates (outstanding ones only) * ARGF - * ARGF.read_nonblock supports `exception: false' like IO#read_nonblock. - [Feature #11358] + * ARGF.read_nonblock supports `exception: false' like IO#read_nonblock. [Feature #11358] * Array @@ -78,8 +74,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Enumerable - * Enumerable#grep_v is added as inverse version of Enumerable#grep. - [Feature #11049] + * Enumerable#grep_v is added as inverse version of Enumerable#grep. [Feature #11049] * Enumerable#chunk_while [Feature #10769] * Enumerator::Lazy @@ -105,8 +100,7 @@ with all sufficient information, see the ChangeLog file or Redmine this affect only files opened as binary. [Feature #11218] * new option parameter `flags' is added. - this parameter is bitwise-ORed to oflags generated by normal mode argument. - [Feature #11253] + this parameter is bitwise-ORed to oflags generated by normal mode argument. [Feature #11253] * IO#advise no longer raises Errno::ENOSYS in cases where it was detected at build time but not available at runtime. [Feature #11806] @@ -125,8 +119,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Numeric * Numeric#positive? and Numeric#negative? are added, which return - true when the receiver is positive and negative respectively. - [Feature #11151] + true when the receiver is positive and negative respectively. [Feature #11151] * Proc @@ -152,11 +145,9 @@ with all sufficient information, see the ChangeLog file or Redmine * String - * String#+@ and String#-@ are added to get mutable/frozen strings. - [Feature #11782] + * String#+@ and String#-@ are added to get mutable/frozen strings. [Feature #11782] - * String.new now accepts new option parameter `encoding'. - [Feature #11785] + * String.new now accepts new option parameter `encoding'. [Feature #11785] * Struct * Struct#dig [Feature #11688] @@ -233,12 +224,10 @@ with all sufficient information, see the ChangeLog file or Redmine * OpenSSL * OpenSSL::SSL::SSLSocket#accept_nonblock and - OpenSSL::SSL::SSLSocket#connect_nonblock supports `exception: false`. - [Feature #10532] + OpenSSL::SSL::SSLSocket#connect_nonblock supports `exception: false`. [Feature #10532] * Pathname - * Pathname#descend and Pathname#ascend supported blockless form. - [Feature #11052] + * Pathname#descend and Pathname#ascend supported blockless form. [Feature #11052] * Socket * Socket#connect_nonblock, Socket#accept_nonblock, @@ -246,8 +235,7 @@ with all sufficient information, see the ChangeLog file or Redmine BasicSocket#recv_nonblock, BasicSocket#recvmsg_nonblock, BasicSocket#sendmsg_nonblock all support `exception: false` to return :wait_readable or :wait_writable symbols instead of raising - IO::WaitReadable or IO::WaitWritable exceptions - [Feature #10532] [Feature #11229] + IO::WaitReadable or IO::WaitWritable exceptions [Feature #10532] [Feature #11229] * BasicSocket#recv and BasicSocket#recv_nonblock allow an output String buffer argument like IO#read and IO#read_nonblock to reduce GC overhead [Feature #11242] @@ -255,8 +243,7 @@ with all sufficient information, see the ChangeLog file or Redmine * StringIO * In read-only mode, StringIO#set_encoding no longer sets the encoding of its buffer string. Setting the encoding of the string directly - without StringIO#set_encoding may cause unpredictable behavior now. - [Bug #11827] + without StringIO#set_encoding may cause unpredictable behavior now. [Bug #11827] * timeout * Object#timeout is now warned as deprecated when called. @@ -297,8 +284,7 @@ with all sufficient information, see the ChangeLog file or Redmine * default value of Net::HTTP#open_timeout is now 60 (was nil). * Net::Telnet - * Net::Telnet is extracted to net-telnet gem. It's unmaintain code. - [Feature #11083] + * Net::Telnet is extracted to net-telnet gem. It's unmaintain code. [Feature #11083] * Psych * Updated to Psych 2.0.17 @@ -330,8 +316,7 @@ with all sufficient information, see the ChangeLog file or Redmine class is already defined but its superclass does not match the given superclass, as well as definitions in ruby level. -* rb_timespec_now() is added to fetch current datetime as struct timespec. - [Feature #11558] +* rb_timespec_now() is added to fetch current datetime as struct timespec. [Feature #11558] * rb_time_timespec_new() is added to create a time object with epoch, nanosecond, and UTC/localtime/time offset arguments. [Feature #11558] @@ -354,11 +339,9 @@ with all sufficient information, see the ChangeLog file or Redmine === Implementation improvements -* Optimize Proc#call to eliminate method frame construction. - [Feature #11569] +* Optimize Proc#call to eliminate method frame construction. [Feature #11569] -* Reconsidering method entry data structure. - [Bug #11278] +* Reconsidering method entry data structure. [Bug #11278] * Introducing new table data structure for ID keys tables used by method table and so on. New table structure is simple and fast @@ -367,13 +350,11 @@ with all sufficient information, see the ChangeLog file or Redmine * Machine code level tuning for object allocation and method calling code. r52099, r52254 -* RubyVM::InstructionSequence is extended for future improvement. - [Feature #11788] +* RubyVM::InstructionSequence is extended for future improvement. [Feature #11788] * Case dispatch is now optimized for all special constant literals including nil, true, and false. Previously, only literal strings, - symbols, integers and floats compiled to optimized case dispatch. - [Feature #11769] + symbols, integers and floats compiled to optimized case dispatch. [Feature #11769] * Instance variables on non-pure Ruby classes (T_DATA, T_FILE, etc..) is less expensive to store than before. [Feature #11170] @@ -382,8 +363,7 @@ with all sufficient information, see the ChangeLog file or Redmine constant-time. Previously, Struct elements beyond the first 10 elements used a linear scan. [Feature #10585] -* The Set class got several speed up. - [Misc #10754], [r52591] +* The Set class got several speed up. [Misc #10754], [r52591] * Socket and I/O-related improvements @@ -397,8 +377,8 @@ with all sufficient information, see the ChangeLog file or Redmine addition to reducing expensive exceptions. [Feature #11044] * (Linux-only) waiting on a single FD anywhere in the stdlib no longer - uses select(2), making it immune to slowdowns with high-numbered FDs. - [Feature #11081] [Feature #11377] + uses select(2), making it immune to slowdowns with high-numbered + FDs. [Feature #11081] [Feature #11377] * CGI.escapeHTML is optimized with C extension. https://github.com/ruby/ruby/pull/1164 diff --git a/ruby/doc/NEWS-2.4.0 b/ruby/doc/NEWS-2.4.0 index 28e855cde..8a02f0380 100644 --- a/ruby/doc/NEWS-2.4.0 +++ b/ruby/doc/NEWS-2.4.0 @@ -14,16 +14,13 @@ with all sufficient information, see the ChangeLog file or Redmine === Language changes -* Multiple assignment in conditional expression is now allowed. - [Feature #10617] +* Multiple assignment in conditional expression is now allowed. [Feature #10617] * Refinements is enabled at method by Symbol#to_proc. [Feature #9451] -* Refinements is enabled with Kernel#send and BasicObject#__send__. - [Feature #11476] +* Refinements is enabled with Kernel#send and BasicObject#__send__. [Feature #11476] -* Rescue modifier now applicable to method arguments. - [Feature #12686] +* Rescue modifier now applicable to method arguments. [Feature #12686] * Toplevel return is now allowed. [Feature #4840] @@ -32,17 +29,21 @@ with all sufficient information, see the ChangeLog file or Redmine * Array * Array#concat [Feature #12333] + Now takes multiple arguments. * Array#max and Array#min. [Feature #12172] + This may cause a tiny incompatibility: if you redefine Enumerable#max and call max to an Array, your redefinition will be now ignored. You should also redefine Array#max. * Array#pack [Feature #12754] + Now takes optional argument `buffer:' to reuse already allocated buffer. * Array#sum [Feature #12217] + This is different from Enumerable#sum in that Array#sum doesn't depend on the definition of each method. @@ -56,8 +57,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Enumerable - * Enumerable#chunk called without a block now return an Enumerator - [Feature #2172] + * Enumerable#chunk called without a block now return an Enumerator [Feature #2172] * Enumerable#sum [Feature #12217] * Enumerable#uniq [Feature #11090] @@ -95,6 +95,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Integer#round now takes an optional keyword argument, half option, and the default behavior is round-up now. [Bug #12548] [Bug #12958] + half option can be one of :even, :up, and :down. [Feature #12953] * IO @@ -104,8 +105,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Kernel - * Kernel#clone now takes an optional keyword argument, freeze flag. - [Feature #12300] + * Kernel#clone now takes an optional keyword argument, freeze flag. [Feature #12300] * MatchData @@ -138,6 +138,7 @@ with all sufficient information, see the ChangeLog file or Redmine for UTR #51 Unicode Emoji, Version 4.0 emoji zwj sequences. * Regexp#match? [Feature #8110] + This returns bool and doesn't save backref. * Update to Onigmo 6.0.0. @@ -153,6 +154,7 @@ with all sufficient information, see the ChangeLog file or Redmine * String#casecmp? [Feature #12786] * String#concat, String#prepend [Feature #12333] + Now takes multiple arguments. * String#each_line, String#lines now takes an optional keyword argument, @@ -189,8 +191,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Thread - * Thread#report_on_exception and Thread.report_on_exception - [Feature #6647] + * Thread#report_on_exception and Thread.report_on_exception [Feature #6647] * TracePoint @@ -200,8 +201,7 @@ with all sufficient information, see the ChangeLog file or Redmine * New module named Warning is introduced. By default it has only one singleton method, named warn. This makes it possible for - 3rd-party libraries to control the way warnings are handled. - [Feature #12299] + 3rd-party libraries to control the way warnings are handled. [Feature #12299] === Stdlib updates (outstanding ones only) @@ -215,8 +215,7 @@ with all sufficient information, see the ChangeLog file or Redmine * IPAddr - * IPAddr#== and IPAddr#<=> no longer raise an exception if coercion fails. - [Bug #12799] + * IPAddr#== and IPAddr#<=> no longer raise an exception if coercion fails. [Bug #12799] * IRB @@ -256,8 +255,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Readline - * Readline.quoting_detection_proc and Readline.quoting_detection_proc= - [Feature #12659] + * Readline.quoting_detection_proc and Readline.quoting_detection_proc= [Feature #12659] * REXML @@ -267,8 +265,7 @@ with all sufficient information, see the ChangeLog file or Redmine * set - * New methods: Set#compare_by_identity and Set#compare_by_identity?. - [Feature #12210] + * New methods: Set#compare_by_identity and Set#compare_by_identity?. [Feature #12210] * WEBrick @@ -277,6 +274,7 @@ with all sufficient information, see the ChangeLog file or Redmine === Compatibility issues (excluding feature bug fixes) * Array#sum and Enumerable#sum are implemented. [Feature #12217] + Ruby itself has no compatibility problem because Ruby didn't have sum method for arrays before Ruby 2.4. However many third party gems, activesupport, facets, simple_stats, etc, @@ -286,6 +284,7 @@ with all sufficient information, see the ChangeLog file or Redmine be perfectly compatible with all of them. * Fixnum and Bignum are unified into Integer [Feature #12005] + Fixnum class and Bignum class is removed. Integer class is changed from abstract class to concrete class. For example, 0 is an instance of Integer: 0.class returns Integer. @@ -300,6 +299,7 @@ with all sufficient information, see the ChangeLog file or Redmine * String/Symbol#upcase/downcase/swapcase/capitalize(!) now work for all of Unicode, not only for ASCII. [Feature #10085] + No change is needed if the data is in ASCII anyway or if the limitation to ASCII was only tolerated while waiting for a more extensive implementation. A change (using the :ascii option) is needed in cases where Unicode data @@ -307,6 +307,7 @@ with all sufficient information, see the ChangeLog file or Redmine A good example of this are internationalized domain names. * TRUE / FALSE / NIL + These constants are now obsoleted. [Feature #12574] Use true / false / nil resp. instead. @@ -332,8 +333,7 @@ with all sufficient information, see the ChangeLog file or Redmine * Shellwords.shellwords (shellsplit) treats the backslash as escape character only when followed by one of the following characters: - $ ` " \ - [Bug #10055] + $ ` " \ [Bug #10055] * Time @@ -348,11 +348,13 @@ with all sufficient information, see the ChangeLog file or Redmine * Tk * Tk is removed from stdlib. [Feature #8539] + https://github.com/ruby/tk is the new upstream. * XMLRPC * XMLRPC is removed from stdlib, and bundled as gem. [Feature #12160][ruby-core:74239] + https://github.com/ruby/xmlrpc is the new upstream. * Zlib @@ -390,8 +392,8 @@ with all sufficient information, see the ChangeLog file or Redmine === Miscellaneous changes * ChangeLog is removed from the repository. + It is generated from commit messages in Subversion by `make dist`. Also note that now people should follow Git style commit message. - The template is written at - [Short (50 chars or less) summary of changes](https://git-scm.com/book/ch5-2.html). - [Feature #12283] + The template is written at {Short (50 chars or less) summary of + changes}[https://git-scm.com/book/ch5-2.html]. [Feature #12283] diff --git a/ruby/doc/NEWS-2.5.0 b/ruby/doc/NEWS-2.5.0 index c891317b6..af7f3ada0 100644 --- a/ruby/doc/NEWS-2.5.0 +++ b/ruby/doc/NEWS-2.5.0 @@ -466,7 +466,7 @@ with all sufficient information, see the ChangeLog file or Redmine === Compatibility issues (excluding feature bug fixes) -* Socket +* BasicSocket * BasicSocket#read_nonblock and BasicSocket#write_nonblock no longer set the O_NONBLOCK file description flag as side effect diff --git a/ruby/doc/NEWS-2.6.0 b/ruby/doc/NEWS-2.6.0 index 2303a5bd4..6e70696de 100644 --- a/ruby/doc/NEWS-2.6.0 +++ b/ruby/doc/NEWS-2.6.0 @@ -50,24 +50,24 @@ sufficient information, see the ChangeLog file or Redmine === Core classes updates (outstanding ones only) -Array:: +[Array] - New methods:: + [New methods] * Added Array#union and Array#difference instance methods. [Feature #14097] - Modified method:: + [Modified method] * Array#to_h now accepts a block that maps elements to new key/value pairs. [Feature #15143] - Aliased methods:: + [Aliased methods] * Array#filter is a new alias for Array#select. [Feature #13784] * Array#filter! is a new alias for Array#select!. [Feature #13784] -Binding:: +[Binding] - New method:: + [New method] * Added Binding#source_location. [Feature #14230] @@ -79,97 +79,97 @@ Binding:: binding's source location [Bug #4352]. So, users should use this newly-introduced method instead of Kernel#eval. -Dir:: +[Dir] - New methods:: + [New methods] * Added Dir#each_child and Dir#children instance methods. [Feature #13969] -Enumerable:: +[Enumerable] - New method:: + [New method] * Enumerable#chain returns an enumerator object that iterates over the elements of the receiver and then those of each argument in sequence. [Feature #15144] - Modified method:: + [Modified method] * Enumerable#to_h now accepts a block that maps elements to new key/value pairs. [Feature #15143] - Aliased method:: + [Aliased method] * Enumerable#filter is a new alias for Enumerable#select. [Feature #13784] -Enumerator::ArithmeticSequence:: +[Enumerator::ArithmeticSequence] * This is a new class to represent a generator of an arithmetic sequence, that is a number sequence defined by a common difference. It can be used for representing what is similar to Python's slice. You can get an instance of this class from Numeric#step and Range#step. -Enumerator::Chain:: +[Enumerator::Chain] * This is a new class to represent a chain of enumerables that works as a single enumerator, generated by such methods as Enumerable#chain and Enumerator#+. -Enumerator::Lazy:: +[Enumerator::Lazy] - Aliased method:: + [Aliased method] * Enumerator::Lazy#filter is a new alias for Enumerator::Lazy#select. [Feature #13784] -Enumerator:: +[Enumerator] - New methods:: + [New methods] * Enumerator#+ returns an enumerator object that iterates over the elements of the receiver and then those of the other operand. [Feature #15144] -ENV:: +[ENV] - Modified method:: + [Modified method] * ENV.to_h now accepts a block that maps names and values to new keys and values. [Feature #15143] -Exception:: +[Exception] - New options:: + [New options] * Exception#full_message takes +:highlight+ and +:order+ options. [Bug #14324] -Hash:: +[Hash] - Modified methods:: + [Modified methods] * Hash#merge, Hash#merge!, and Hash#update now accept multiple arguments. [Feature #15111] * Hash#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143] - Aliased methods:: + [Aliased methods] * Hash#filter is a new alias for Hash#select. [Feature #13784] * Hash#filter! is a new alias for Hash#select!. [Feature #13784] -IO:: +[IO] - New option:: + [New option] * Added new mode character 'x' to open files for exclusive access. [Feature #11258] -Kernel:: +[Kernel] - Aliased method:: + [Aliased method] * Kernel#then is a new alias for Kernel#yield_self. [Feature #14594] - New options:: + [New options] * Kernel#Complex, Kernel#Float, Kernel#Integer, and Kernel#Rational take an +:exception+ option to specify the way of @@ -178,98 +178,98 @@ Kernel:: * Kernel#system takes an +:exception+ option to raise an exception on failure. [Feature #14386] - Incompatible changes:: + [Incompatible changes] * Kernel#system and Kernel#exec do not close non-standard file descriptors (the default of the +:close_others+ option is changed to +false+, but we still set the +FD_CLOEXEC+ flag on descriptors we create). [Misc #14907] -KeyError:: +[KeyError] - New options:: + [New options] * KeyError.new accepts +:receiver+ and +:key+ options to set receiver and key in Ruby code. [Feature #14313] -Method:: +[Method] - New methods:: + [New methods] * Added Method#<< and Method#>> for Proc composition. [Feature #6284] -Module:: +[Module] - Modified methods:: + [Modified methods] * Module#method_defined?, Module#private_method_defined?, and Module#protected_method_defined? now accept the second parameter as optional. If it is +true+ (the default value), it checks ancestor modules/classes, or checks only the class itself. [Feature #14944] -NameError:: +[NameError] - New option:: + [New option] * NameError.new accepts a +:receiver+ option to set receiver in Ruby code. [Feature #14313] -NilClass:: +[NilClass] - New method:: + [New method] * NilClass#=~ is added for compatibility. [Feature #15231] -NoMethodError:: +[NoMethodError] - New option:: + [New option] * NoMethodError.new accepts a +:receiver+ option to set receiver in Ruby code. [Feature #14313] -Numeric:: +[Numeric] - Incompatible changes:: + [Incompatible changes] * Numeric#step now returns an instance of the Enumerator::ArithmeticSequence class rather than one of the Enumerator class. -OpenStruct:: +[OpenStruct] - Modified method:: + [Modified method] * OpenStruct#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143] -Proc:: +[Proc] - New methods:: + [New methods] * Added Proc#<< and Proc#>> for Proc composition. [Feature #6284] - Incompatible changes:: + [Incompatible changes] * Proc#call doesn't change $SAFE any more. [Feature #14250] -Random:: +[Random] - New method:: + [New method] * Added Random.bytes. [Feature #4938] -Range:: +[Range] - New method:: + [New method] * Added Range#% instance method. [Feature #14697] - Incompatible changes:: + [Incompatible changes] * Range#=== now uses the +#cover?+ instead of the +#include?+ method. [Feature #14575] * Range#cover? now accepts a Range object. [Feature #14473] * Range#step now returns an instance of the Enumerator::ArithmeticSequence class rather than one of the Enumerator class. -Regexp/String:: +[Regexp/String] * Update Unicode version from 10.0.0 to 11.0.0. [Feature #14802] @@ -278,9 +278,9 @@ Regexp/String:: * Update Emoji version from 5.0 to 11.0.0 [Feature #14802] -RubyVM::AbstractSyntaxTree:: +[RubyVM::AbstractSyntaxTree] - New methods:: + [New methods] * RubyVM::AbstractSyntaxTree.parse parses a given string and returns AST nodes. [experimental] @@ -291,46 +291,46 @@ RubyVM::AbstractSyntaxTree:: * RubyVM::AbstractSyntaxTree.of returns AST nodes of the given proc or method. [experimental] -RubyVM:: +[RubyVM] - New method:: + [New method] * RubyVM.resolve_feature_path identifies the file that will be loaded by "require(feature)". [experimental] [Feature #15230] -String:: +[String] * String#crypt is now deprecated. [Feature #14915] - New features:: + [New features] * String#split yields each substring to the block if given. [Feature #4780] -Struct:: +[Struct] - Modified method:: + [Modified method] * Struct#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143] - Aliased method:: + [Aliased method] * Struct#filter is a new alias for Struct#select. [Feature #13784] -Time:: +[Time] - New features:: + [New features] * Time.new and Time#getlocal accept a timezone object as well as a UTC offset string. Time#+, Time#-, and Time#succ also preserve the timezone. [Feature #14850] -TracePoint:: +[TracePoint] - New features:: + [New features] * "script_compiled" event is supported. [Feature #15287] - New methods:: + [New methods] * TracePoint#parameters [Feature #14694] @@ -338,23 +338,23 @@ TracePoint:: * TracePoint#eval_script [Feature #15287] - Modified method:: + [Modified method] * TracePoint#enable accepts new keywords "target:" and "target_line:". [Feature #15289] === Stdlib updates (outstanding ones only) -BigDecimal:: +[BigDecimal] Update to version 1.4.0. This version includes several compatibility issues, see Compatibility issues section below for details. - Modified method:: + [Modified method] * BigDecimal() accepts the new keyword "exception:" similar to Float(). - Note for the differences among recent versions:: + [Note for the differences among recent versions] You should want to know the differences among recent versions of bigdecimal. Please select the suitable version of bigdecimal according to the following @@ -371,13 +371,13 @@ BigDecimal:: * 2.0.0 will be released soon after releasing Ruby 2.6.0. This version will not have the BigDecimal.new method. -Bundler:: +[Bundler] * Add Bundler to Standard Library. [Feature #12733] * Use 1.17.2, the latest stable version. -Coverage:: +[Coverage] A oneshot_lines mode is added. [Feature #15022] @@ -386,7 +386,7 @@ Coverage:: A hook for each line is fired at most once, and after it is fired the hook flag is removed, i.e., it runs with zero overhead. - New options:: + [New options] * Add +:oneshot_lines+ keyword argument to Coverage.start. @@ -394,20 +394,20 @@ Coverage:: If +clear+ is true, it clears the counters to zero. If +stop+ is true, it disables coverage measurement. - New methods:: + [New methods] * Coverage.line_stub, which is a simple helper function that creates the "stub" of line coverage from a given source code. -CSV:: +[CSV] * Upgrade to 3.0.2. This includes performance improvements especially for writing. Writing is about 2 times faster. See https://github.com/ruby/csv/blob/master/NEWS.md. -ERB:: +[ERB] - New options:: + [New options] * Add +:trim_mode+ and +:eoutvar+ keyword arguments to ERB.new. Now non-keyword arguments other than the first one are softly deprecated @@ -416,15 +416,15 @@ ERB:: * erb command's -S option is deprecated, and will be removed in the next version. -FileUtils:: +[FileUtils] - New methods:: + [New methods] * FileUtils#cp_lr. [Feature #4189] -Matrix:: +[Matrix] - New methods:: + [New methods] * Matrix#antisymmetric?, Matrix#skew_symmetric? @@ -436,30 +436,30 @@ Matrix:: * Vector#[]= -Net:: +[Net] - New options:: + [New options] * Add +:write_timeout+ keyword argument to Net::HTTP.new. [Feature #13396] - New methods:: + [New methods] * Add Net::HTTP#write_timeout and Net::HTTP#write_timeout=. [Feature #13396] - New constant:: + [New constant] * Add Net::HTTPClientException to deprecate Net::HTTPServerException, whose name is misleading. [Bug #14688] -NKF:: +[NKF] * Upgrade to nkf v2.1.5 -Psych:: +[Psych] * Upgrade to Psych 3.1.0 -RDoc:: +[RDoc] * Become about 2 times faster. @@ -478,12 +478,12 @@ RDoc:: * Fix many parsing bugs. -REXML:: +[REXML] * Upgrade to REXML 3.1.9. See https://github.com/ruby/rexml/blob/master/NEWS.md. - Improved some XPath implementations:: + [Improved some XPath implementations] * concat() function: Stringify all arguments before concatenating. @@ -493,7 +493,7 @@ REXML:: * Support "*:#{ELEMENT_NAME}" syntax in XPath 2.0. - Fixed some XPath implementations:: + [Fixed some XPath implementations] * "//#{ELEMENT_NAME}[#{POSITION}]" case @@ -517,14 +517,14 @@ REXML:: * "name(#{NODE_SET})" case -RSS:: +[RSS] - New options:: + [New options] * RSS::Parser.parse now accepts options as Hash. +:validate+ , +:ignore_unknown_element+ , +:parser_class+ options are available. -RubyGems:: +[RubyGems] * Upgrade to RubyGems 3.0.1 @@ -532,32 +532,32 @@ RubyGems:: * https://blog.rubygems.org/2018/12/23/3.0.1-released.html -Set:: +[Set] - Aliased method:: + [Aliased method] * Set#filter! is a new alias for Set#select!. [Feature #13784] -URI:: +[URI] - New constant:: + [New constant] * Add URI::File to handle the file URI scheme. [Feature #14035] === Compatibility issues (excluding feature bug fixes) -Dir:: +[Dir] * Dir.glob with '\0'-separated pattern list will be deprecated, and is now warned. [Feature #14643] -File:: +[File] * File.read, File.binread, File.write, File.binwrite, File.foreach, and File.readlines do not invoke external commands even if the path starts with the pipe character '|'. [Feature #14245] -Object:: +[Object] * Object#=~ is deprecated. [Feature #15231] @@ -580,7 +580,7 @@ Object:: * thwait * tracer -BigDecimal:: +[BigDecimal] * The following methods are removed. @@ -595,7 +595,7 @@ BigDecimal:: * BigDecimal.new will be removed in version 2.0. -Pathname:: +[Pathname] * Pathname#read, Pathname#binread, Pathname#write, Pathname#binwrite, Pathname#each_line and Pathname#readlines do not invoke external @@ -650,12 +650,12 @@ Pathname:: in their names. This eliminates the burden of each teeny upgrade on the platform that users need to rebuild every extension library. - Before:: + [Before] * libruby.2.6.0.dylib * libruby.2.6.dylib -> libruby.2.6.0.dylib * libruby.dylib -> libruby.2.6.0.dylib - After:: + [After] * libruby.2.6.dylib * libruby.dylib -> libruby.2.6.dylib diff --git a/ruby/doc/NEWS-2.7.0 b/ruby/doc/NEWS-2.7.0 new file mode 100644 index 000000000..184b47fb8 --- /dev/null +++ b/ruby/doc/NEWS-2.7.0 @@ -0,0 +1,835 @@ +# -*- rdoc -*- + += NEWS for Ruby 2.7.0 + +This document is a list of user visible feature changes made between +releases except for bug fixes. + +Note that each entry is kept so brief that no reason behind or reference +information is supplied with. For a full list of changes with all +sufficient information, see the ChangeLog file or Redmine +(e.g. https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER). + +== Changes since the 2.6.0 release + +=== Language changes + +==== Pattern matching + +* Pattern matching is introduced as an experimental feature. [Feature #14912] + + case [0, [1, 2, 3]] + in [a, [b, *c]] + p a #=> 0 + p b #=> 1 + p c #=> [2, 3] + end + + case {a: 0, b: 1} + in {a: 0, x: 1} + :unreachable + in {a: 0, b: var} + p var #=> 1 + end + + case -1 + in 0 then :unreachable + in 1 then :unreachable + end #=> NoMatchingPatternError + + json = < "Bob" + p age #=> 2 + + JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]} + #=> NoMatchingPatternError + +* See the following slides for more details: + * https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7 + * Note that the slides are slightly obsolete. + +* The warning against pattern matching can be suppressed with + {-W:no-experimental option}[#label-Warning+option]. + +==== The spec of keyword arguments is changed towards 3.0 + +* Automatic conversion of keyword arguments and positional arguments is + deprecated, and conversion will be removed in Ruby 3. [Feature #14183] + + * When a method call passes a Hash at the last argument, and when it + passes no keywords, and when the called method accepts keywords, + a warning is emitted. To continue treating the hash as keywords, + add a double splat operator to avoid the warning and ensure + correct behavior in Ruby 3. + + def foo(key: 42); end; foo({key: 42}) # warned + def foo(**kw); end; foo({key: 42}) # warned + def foo(key: 42); end; foo(**{key: 42}) # OK + def foo(**kw); end; foo(**{key: 42}) # OK + + * When a method call passes keywords to a method that accepts keywords, + but it does not pass enough required positional arguments, the + keywords are treated as a final required positional argument, and a + warning is emitted. Pass the argument as a hash instead of keywords + to avoid the warning and ensure correct behavior in Ruby 3. + + def foo(h, **kw); end; foo(key: 42) # warned + def foo(h, key: 42); end; foo(key: 42) # warned + def foo(h, **kw); end; foo({key: 42}) # OK + def foo(h, key: 42); end; foo({key: 42}) # OK + + * When a method accepts specific keywords but not a keyword splat, and + a hash or keywords splat is passed to the method that includes both + Symbol and non-Symbol keys, the hash will continue to be split, and + a warning will be emitted. You will need to update the calling code + to pass separate hashes to ensure correct behavior in Ruby 3. + + def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned + def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned + def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK + + * If a method does not accept keywords, and is called with keywords, + the keywords are still treated as a positional hash, with no warning. + This behavior will continue to work in Ruby 3. + + def foo(opt={}); end; foo( key: 42 ) # OK + +* Non-symbols are allowed as keyword argument keys if the method accepts + arbitrary keywords. [Feature #14183] + + * Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0, + but are now allowed again. [Bug #15658] + + def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1} + +* **nil is allowed in method definitions to explicitly mark + that the method accepts no keywords. Calling such a method with keywords + will result in an ArgumentError. [Feature #14183] + + def foo(h, **nil); end; foo(key: 1) # ArgumentError + def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError + def foo(h, **nil); end; foo("str" => 1) # ArgumentError + def foo(h, **nil); end; foo({key: 1}) # OK + def foo(h, **nil); end; foo({"str" => 1}) # OK + +* Passing an empty keyword splat to a method that does not accept keywords + no longer passes an empty hash, unless the empty hash is necessary for + a required parameter, in which case a warning will be emitted. Remove + the double splat to continue passing a positional hash. [Feature #14183] + + h = {}; def foo(*a) a end; foo(**h) # [] + h = {}; def foo(a) a end; foo(**h) # {} and warning + h = {}; def foo(*a) a end; foo(h) # [{}] + h = {}; def foo(a) a end; foo(h) # {} + +* Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option]. + +==== Numbered parameters + +* Numbered parameters as default block parameters are introduced. [Feature #4475] + + [1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"] + [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7] + + You can still define a local variable named +_1+ and so on, + and that is honored when present, but renders a warning. + + _1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name + [1].each { p _1 } # prints 0 instead of 1 + +==== proc/lambda without block is deprecated + +* Proc.new and Kernel#proc with no block in a method called with a block will + now display a warning. + + def foo + proc + end + foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead + + This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. + +* Kernel#lambda with no block in a method called with a block raises an exception. + + def bar + lambda + end + bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError) + +==== Other miscellaneous changes + +* A beginless range is experimentally introduced. It might be useful + in +case+, new call-sequence of the Comparable#clamp, + constants and DSLs. [Feature #14799] + + ary[..3] # identical to ary[0..3] + + case RUBY_VERSION + when ..."2.4" then puts "EOL" + # ... + end + + age.clamp(..100) + + where(sales: ..100) + +* Setting $; to a non-nil value will now display a warning. [Feature #14240] + This includes the usage in String#split. + This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. + +* Setting $, to a non-nil value will now display a warning. [Feature #14240] + This includes the usage in Array#join. + This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. + +* Quoted here-document identifiers must end within the same line. + + <<"EOS + " # This had been warned since 2.4; Now it raises a SyntaxError + EOS + +* The flip-flop syntax deprecation is reverted. [Feature #5400] + +* Comment lines can be placed between fluent dot now. + + foo + # .bar + .baz # => foo.baz + +* Calling a private method with a literal +self+ as the receiver + is now allowed. [Feature #11297] [Feature #16123] + +* Modifier rescue now operates the same for multiple assignment as single + assignment. [Bug #8279] + + a, b = raise rescue [1, 2] + # Previously parsed as: (a, b = raise) rescue [1, 2] + # Now parsed as: a, b = (raise rescue [1, 2]) + +* +yield+ in singleton class syntax will now display a warning. This behavior + will soon be deprecated. [Feature #15575]. + + def foo + class << Object.new + yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575] + end + end + foo { p :ok } + + This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option]. + +* Argument forwarding by (...) is introduced. [Feature #16253] + + def foo(...) + bar(...) + end + + All arguments to +foo+ are forwarded to +bar+, including keyword and + block arguments. + Note that the parentheses are mandatory. bar ... is parsed + as an endless range. + +* Access and setting of $SAFE will now always display a warning. + $SAFE will become a normal global variable in Ruby 3.0. [Feature #16131] + +* Object#{taint,untaint,trust,untrust} and related functions in the C-API + no longer have an effect (all objects are always considered untainted), and will now + display a warning in verbose mode. This warning will be disabled even in non-verbose mode in + Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. [Feature #16131] + +* Refinements take place at Object#method and Module#instance_method. [Feature #15373] + +=== Command line options + +==== Warning option + +The +-W+ option has been extended with a following +:+, to manage categorized +warnings. [Feature #16345] [Feature #16420] + +* To suppress deprecation warnings: + + $ ruby -e '$; = ""' + -e:1: warning: `$;' is deprecated + + $ ruby -W:no-deprecated -e '$; = //' + +* It works with the +RUBYOPT+ environment variable: + + $ RUBYOPT=-W:no-deprecated ruby -e '$; = //' + +* To suppress experimental feature warnings: + + $ ruby -e '0 in a' + -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby! + + $ ruby -W:no-experimental -e '0 in a' + +* To suppress both by using +RUBYOPT+, set space separated values: + + $ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a' + +See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29]. + +=== Core classes updates (outstanding ones only) + +[Array] + + [New methods] + + * Added Array#intersection. [Feature #16155] + + * Added Array#minmax, with a faster implementation than Enumerable#minmax. [Bug #15929] + +[Comparable] + + [Modified method] + + * Comparable#clamp now accepts a Range argument. [Feature #14784] + + -1.clamp(0..2) #=> 0 + 1.clamp(0..2) #=> 1 + 3.clamp(0..2) #=> 2 + # With beginless and endless ranges: + -1.clamp(0..) #=> 0 + 3.clamp(..2) #=> 2 + + +[Complex] + + [New method] + + * Added Complex#<=>. + So 0 <=> 0i will not raise NoMethodError. [Bug #15857] + +[Dir] + + [Modified methods] + + * Dir.glob and Dir.[] no longer allow NUL-separated glob pattern. + Use Array instead. [Feature #14643] + +[Encoding] + + [New encoding] + + * Added new encoding CESU-8. [Feature #15931] + +[Enumerable] + + [New methods] + + * Added Enumerable#filter_map. [Feature #15323] + + [1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"] + + * Added Enumerable#tally. [Feature #11076] + + ["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1} + +[Enumerator] + + [New methods] + + * Added Enumerator.produce to generate an Enumerator from any custom + data transformation. [Feature #14781] + + require "date" + dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates + dates.detect(&:tuesday?) #=> next Tuesday + + * Added Enumerator::Lazy#eager that generates a non-lazy enumerator + from a lazy enumerator. [Feature #15901] + + a = %w(foo bar baz) + e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager + p e.class #=> Enumerator + p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"] + + * Added Enumerator::Yielder#to_proc so that a Yielder object + can be directly passed to another method as a block + argument. [Feature #15618] + +[Fiber] + + [New method] + + * Added Fiber#raise that behaves like Fiber#resume but raises an + exception on the resumed fiber. [Feature #10344] + +[File] + + [New method] + + * Added File.absolute_path? to check whether a path is absolute or + not in a portable way. [Feature #15868] + + File.absolute_path?("/foo") # => true (on *nix) + File.absolute_path?("C:/foo") # => true (on Windows) + File.absolute_path?("foo") # => false + + [Modified method] + + * File.extname now returns a dot string for names ending with a dot on + non-Windows platforms. [Bug #15267] + + File.extname("foo.") #=> "." + +[FrozenError] + + [New method] + + * Added FrozenError#receiver to return the frozen object on which + modification was attempted. To set this object when raising + FrozenError in Ruby code, FrozenError.new accepts a +:receiver+ + option. [Feature #15751] + +[GC] + + [New method] + + * Added GC.compact method for compacting the heap. + This function compacts live objects in the heap so that fewer pages may + be used, and the heap may be more CoW (copy-on-write) friendly. [Feature #15626] + + Details on the algorithm and caveats can be found here: + https://bugs.ruby-lang.org/issues/15626 + +[IO] + + [New method] + + * Added IO#set_encoding_by_bom to check the BOM and set the external + encoding. [Bug #15210] + +[Integer] + + [Modified method] + + * Integer#[] now supports range operations. [Feature #8842] + + 0b01001101[2, 4] #=> 0b0011 + 0b01001100[2..5] #=> 0b0011 + 0b01001100[2...6] #=> 0b0011 + # ^^^^ + +[Method] + + [Modified method] + + * Method#inspect shows more information. [Feature #14145] + +[Module] + + [New methods] + + * Added Module#const_source_location to retrieve the location where a + constant is defined. [Feature #10771] + + * Added Module#ruby2_keywords for marking a method as passing keyword + arguments through a regular argument splat, useful when delegating + all arguments to another method in a way that can be backwards + compatible with older Ruby versions. [Bug #16154] + + [Modified methods] + + * Module#autoload? now takes an +inherit+ optional argument, like + Module#const_defined?. [Feature #15777] + + * Module#name now always returns a frozen String. The returned String is + always the same for a given Module. This change is + experimental. [Feature #16150] + +[NilClass / TrueClass / FalseClass] + + [Modified methods] + + * NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a + frozen String. The returned String is always the same for each of these + values. This change is experimental. [Feature #16150] + +[ObjectSpace::WeakMap] + + [Modified method] + + * ObjectSpace::WeakMap#[]= now accepts special objects as either key or + values. [Feature #16035] + +[Proc] + + [New method] + + * Added Proc#ruby2_keywords for marking the proc as passing keyword + arguments through a regular argument splat, useful when delegating + all arguments to another method or proc in a way that can be backwards + compatible with older Ruby versions. [Feature #16404] + +[Range] + + [New method] + + * Added Range#minmax, with a faster implementation than Enumerable#minmax. + It returns a maximum that now corresponds to Range#max. [Bug #15807] + + [Modified method] + + * Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was + changed from Range#include? for all types except strings). [Bug #15449] + + +[RubyVM] + + [Removed method] + + * +RubyVM.resolve_feature_path+ moved to + $LOAD_PATH.resolve_feature_path. [Feature #15903] [Feature #15230] + +[String] + + [Unicode] + + * Update Unicode version and Emoji version from 11.0.0 to + 12.0.0. [Feature #15321] + + * Update Unicode version to 12.1.0, adding support for + U+32FF SQUARE ERA NAME REIWA. [Feature #15195] + + * Update Unicode Emoji version to 12.1. [Feature #16272] + +[Symbol] + + [New methods] + + * Added Symbol#start_with? and Symbol#end_with? methods. [Feature #16348] + +[Time] + + [New methods] + + * Added Time#ceil method. [Feature #15772] + + * Added Time#floor method. [Feature #15653] + + [Modified method] + + * Time#inspect is separated from Time#to_s and it shows + the time's sub second. [Feature #15958] + +[UnboundMethod] + + [New method] + + * Added UnboundMethod#bind_call method. [Feature #15955] + + umethod.bind_call(obj, ...) is semantically equivalent + to umethod.bind(obj).call(...). This idiom is used in + some libraries to call a method that is overridden. The added + method does the same without allocation of an intermediate Method + object. + + class Foo + def add_1(x) + x + 1 + end + end + class Bar < Foo + def add_1(x) # override + x + 2 + end + end + + obj = Bar.new + p obj.add_1(1) #=> 3 + p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2 + p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2 + +[Warning] + + [New methods] + + * Added Warning.[] and Warning.[]= to manage emitting/suppressing + some categories of warnings. [Feature #16345] [Feature #16420] + +[$LOAD_PATH] + + [New method] + + * Added $LOAD_PATH.resolve_feature_path. [Feature #15903] [Feature #15230] + +=== Stdlib updates (outstanding ones only) + +[Bundler] + + * Upgrade to Bundler 2.1.2. + See https://github.com/bundler/bundler/releases/tag/v2.1.2 + +[CGI] + + * CGI.escapeHTML becomes 2~5x faster when there is at least one escaped character. + See https://github.com/ruby/ruby/pull/2226 + +[CSV] + + * Upgrade to 3.1.2. + See https://github.com/ruby/csv/blob/master/NEWS.md. + +[Date] + + * Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese + era. [Feature #15742] + +[Delegator] + + * Object#DelegateClass accepts a block and module_evals it in the context + of the returned class, similar to Class.new and Struct.new. + +[ERB] + + * Prohibit marshaling ERB instance. + +[IRB] + + * Introduce syntax highlighting inspired by the Pry gem to Binding#irb + source lines, REPL input, and inspect output of some core-class objects. + + * Introduce multiline editing mode provided by Reline. + + * Show documentation when completion. + + * Enable auto indent and save/load history by default. + +[JSON] + + * Upgrade to 2.3.0. + +[Net::FTP] + + * Add Net::FTP#features to check available features, and Net::FTP#option to + enable/disable each of them. [Feature #15964] + +[Net::HTTP] + + * Add +ipaddr+ optional parameter to Net::HTTP#start to replace the address for + the TCP/IP connection. [Feature #5180] + +[Net::IMAP] + + * Add Server Name Indication (SNI) support. [Feature #15594] + +[open-uri] + + * Warn open-uri's "open" method at Kernel. + Use URI.open instead. [Misc #15893] + + * The default charset of "text/*" media type is UTF-8 instead of + ISO-8859-1. [Bug #15933] + +[OptionParser] + + * Now show "Did you mean?" for unknown options. [Feature #16256] + + test.rb: + + require "optparse" + OptionParser.new do |opts| + opts.on("-f", "--foo", "foo") {|v| } + opts.on("-b", "--bar", "bar") {|v| } + opts.on("-c", "--baz", "baz") {|v| } + end.parse! + + example: + + $ ruby test.rb --baa + Traceback (most recent call last): + test.rb:7:in `
': invalid option: --baa (OptionParser::InvalidOption) + Did you mean? baz + bar + +[Pathname] + + * Pathname.glob now delegates 3 arguments to Dir.glob + to accept +base+ keyword. [Feature #14405] + +[Racc] + + * Merge 1.4.15 from upstream repository and added cli of racc. + +[Reline] + + * New stdlib that is compatible with the readline stdlib but is + implemented in pure Ruby. It also provides a multiline editing mode. + +[REXML] + + * Upgrade to 3.2.3. + See https://github.com/ruby/rexml/blob/master/NEWS.md. + +[RSS] + + * Upgrade to RSS 0.2.8. + See https://github.com/ruby/rss/blob/master/NEWS.md. + +[RubyGems] + + * Upgrade to RubyGems 3.1.2. + * https://github.com/rubygems/rubygems/releases/tag/v3.1.0 + * https://github.com/rubygems/rubygems/releases/tag/v3.1.1 + * https://github.com/rubygems/rubygems/releases/tag/v3.1.2 + +[StringScanner] + + * Upgrade to 1.0.3. + See https://github.com/ruby/strscan/blob/master/NEWS.md. + +=== Compatibility issues (excluding feature bug fixes) + +* The following libraries are no longer bundled gems. + Install corresponding gems to use these features. + * CMath (cmath gem) + * Scanf (scanf gem) + * Shell (shell gem) + * Synchronizer (sync gem) + * ThreadsWait (thwait gem) + * E2MM (e2mmap gem) + +[Proc] + * The Proc#to_s format was changed. [Feature #16101] + +[Range] + * Range#minmax used to iterate on the range to determine the maximum. + It now uses the same algorithm as Range#max. In rare cases (e.g. + ranges of Floats or Strings), this may yield different results. [Bug #15807] + +=== Stdlib compatibility issues (excluding feature bug fixes) + +* Promote stdlib to default gems + * The following default gems were published on rubygems.org + * benchmark + * cgi + * delegate + * getoptlong + * net-pop + * net-smtp + * open3 + * pstore + * readline + * readline-ext + * singleton + * The following default gems were only promoted at ruby-core, + but not yet published on rubygems.org. + * monitor + * observer + * timeout + * tracer + * uri + * yaml +* The did_you_mean gem has been promoted up to a default gem from a bundled gem + +[pathname] + + * Kernel#Pathname when called with a Pathname argument now returns + the argument instead of creating a new Pathname. This is more + similar to other Kernel methods, but can break code that modifies + the return value and expects the argument not to be modified. + +[profile.rb, Profiler__] + + * Removed from standard library. It was unmaintained since Ruby 2.0.0. + +=== C API updates + +* Many *_kw functions have been added for setting whether + the final argument being passed should be treated as keywords. You + may need to switch to these functions to avoid keyword argument + separation warnings, and to ensure correct behavior in Ruby 3. + +* The : character in rb_scan_args format string is now + treated as keyword arguments. Passing a positional hash instead of + keyword arguments will emit a deprecation warning. + +* C API declarations with +ANYARGS+ are changed not to use +ANYARGS+. + See https://github.com/ruby/ruby/pull/2404 + +=== Implementation improvements + +[Fiber] + + * Allow selecting different coroutine implementations by using + +--with-coroutine=+, e.g. + + $ ./configure --with-coroutine=ucontext + $ ./configure --with-coroutine=copy + + * Replace previous stack cache with fiber pool cache. The fiber pool + allocates many stacks in a single memory region. Stack allocation + becomes O(log N) and fiber creation is amortized O(1). Around 10x + performance improvement was measured in micro-benchmarks. + https://github.com/ruby/ruby/pull/2224 + +[File] + * File.realpath now uses realpath(3) on many platforms, which can + significantly improve performance. [Feature #15797] + +[Hash] + * Change data structure of small Hash objects. [Feature #15602] + +[Monitor] + * Monitor class is written in C-extension. [Feature #16255] + +[Thread] + + * VM stack memory allocation is now combined with native thread stack, + improving thread allocation performance and reducing allocation related + failures. Around 10x performance improvement was measured in micro-benchmarks. + +[JIT] + + * JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated. + + * Method inlining is performed when a method is considered as pure. + This optimization is still experimental and many methods are NOT considered as pure yet. + + * The default value of +--jit-max-cache+ is changed from 1,000 to 100. + + * The default value of +--jit-min-calls+ is changed from 5 to 10,000. + +[RubyVM] + + * Per-call-site method cache, which has been there since around 1.9, was + improved: cache hit rate raised from 89% to 94%. + See https://github.com/ruby/ruby/pull/2583 + +[RubyVM::InstructionSequence] + + * RubyVM::InstructionSequence#to_binary method generates compiled binary. + The binary size is reduced. [Feature #16163] + +=== Miscellaneous changes + +* Support for IA64 architecture has been removed. Hardware for testing was + difficult to find, native fiber code is difficult to implement, and it added + non-trivial complexity to the interpreter. [Feature #15894] + +* Require compilers to support C99. [Misc #15347] + + * Details of our dialect: https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99 + +* Ruby's upstream repository is changed from Subversion to Git. + + * https://git.ruby-lang.org/ruby.git + + * RUBY_REVISION class is changed from Integer to String. + + * RUBY_DESCRIPTION includes Git revision instead of Subversion's one. + +* Support built-in methods in Ruby with the _\_builtin_ syntax. [Feature #16254] + + Some methods are defined in *.rb (such as trace_point.rb). + For example, it is easy to define a method which accepts keyword arguments. diff --git a/ruby/doc/NEWS-3.0.0.md b/ruby/doc/NEWS-3.0.0.md new file mode 100644 index 000000000..00c26fe58 --- /dev/null +++ b/ruby/doc/NEWS-3.0.0.md @@ -0,0 +1,817 @@ +# NEWS for Ruby 3.0.0 + +This document is a list of user visible feature changes +since the **2.7.0** release, except for bug fixes. + +Note that each entry is kept to a minimum, see links for details. + +## Language changes + +* Keyword arguments are now separated from positional arguments. + Code that resulted in deprecation warnings in Ruby 2.7 will now + result in ArgumentError or different behavior. [[Feature #14183]] + +* Procs accepting a single rest argument and keywords are no longer + subject to autosplatting. This now matches the behavior of Procs + accepting a single rest argument and no keywords. + [[Feature #16166]] + + ```ruby + pr = proc{|*a, **kw| [a, kw]} + + pr.call([1]) + # 2.7 => [[1], {}] + # 3.0 => [[[1]], {}] + + pr.call([1, {a: 1}]) + # 2.7 => [[1], {:a=>1}] # and deprecation warning + # 3.0 => [[[1, {:a=>1}]], {}] + ``` + +* Arguments forwarding (`...`) now supports leading arguments. + [[Feature #16378]] + + ```ruby + def method_missing(meth, ...) + send(:"do_#{meth}", ...) + end + ``` + +* Pattern matching (`case/in`) is no longer experimental. [[Feature #17260]] + +* One-line pattern matching is redesigned. [EXPERIMENTAL] + + * `=>` is added. It can be used like a rightward assignment. + [[Feature #17260]] + + ```ruby + 0 => a + p a #=> 0 + + {b: 0, c: 1} => {b:} + p b #=> 0 + ``` + + * `in` is changed to return `true` or `false`. [[Feature #17371]] + + ```ruby + # version 3.0 + 0 in 1 #=> false + + # version 2.7 + 0 in 1 #=> raise NoMatchingPatternError + ``` + +* Find-pattern is added. [EXPERIMENTAL] + [[Feature #16828]] + + ```ruby + case ["a", 1, "b", "c", 2, "d", "e", "f", 3] + in [*pre, String => x, String => y, *post] + p pre #=> ["a", 1] + p x #=> "b" + p y #=> "c" + p post #=> [2, "d", "e", "f", 3] + end + ``` + +* Endless method definition is added. [EXPERIMENTAL] + [[Feature #16746]] + + ```ruby + def square(x) = x * x + ``` + +* Interpolated String literals are no longer frozen when + `# frozen-string-literal: true` is used. [[Feature #17104]] + +* Magic comment `shareable_constant_value` added to freeze constants. + See {Magic Comments}[rdoc-ref:syntax/comments.rdoc@Magic+Comments] for more details. + [[Feature #17273]] + +* A {static analysis}[rdoc-label:label-Static+analysis] foundation is + introduced. + * {RBS}[rdoc-label:label-RBS] is introduced. It is a type definition + language for Ruby programs. + * {TypeProf}[rdoc-label:label-TypeProf] is experimentally bundled. It is a + type analysis tool for Ruby programs. + +* Deprecation warnings are no longer shown by default (since Ruby 2.7.2). + Turn them on with `-W:deprecated` (or with `-w` to show other warnings too). + [[Feature #16345]] + +* `$SAFE` and `$KCODE` are now normal global variables with no special behavior. + C-API methods related to `$SAFE` have been removed. + [[Feature #16131]] [[Feature #17136]] + +* yield in singleton class definitions in methods is now a SyntaxError + instead of a warning. yield in a class definition outside of a method + is now a SyntaxError instead of a LocalJumpError. [[Feature #15575]] + +* When a class variable is overtaken by the same definition in an + ancestor class/module, a RuntimeError is now raised (previously, + it only issued a warning in verbose mode). Additionally, accessing a + class variable from the toplevel scope is now a RuntimeError. + [[Bug #14541]] + +* Assigning to a numbered parameter is now a SyntaxError instead of + a warning. + +## Command line options + +### `--help` option + +When the environment variable `RUBY_PAGER` or `PAGER` is present and has +a non-empty value, and the standard input and output are tty, the `--help` +option shows the help message via the pager designated by the value. +[[Feature #16754]] + +### `--backtrace-limit` option + +The `--backtrace-limit` option limits the maximum length of a backtrace. +[[Feature #8661]] + +## Core classes updates + +Outstanding ones only. + +* Array + + * The following methods now return Array instances instead of + subclass instances when called on subclass instances: + [[Bug #6087]] + + * Array#drop + * Array#drop_while + * Array#flatten + * Array#slice! + * Array#slice / Array#[] + * Array#take + * Array#take_while + * Array#uniq + * Array#* + + * Can be sliced with Enumerator::ArithmeticSequence + + ```ruby + dirty_data = ['--', 'data1', '--', 'data2', '--', 'data3'] + dirty_data[(1..).step(2)] # take each second element + # => ["data1", "data2", "data3"] + ``` + +* Binding + + * Binding#eval when called with one argument will use `"(eval)"` + for `__FILE__` and `1` for `__LINE__` in the evaluated code. + [[Bug #4352]] [[Bug #17419]] + +* ConditionVariable + + * ConditionVariable#wait may now invoke the `block`/`unblock` scheduler + hooks in a non-blocking context. [[Feature #16786]] + +* Dir + + * Dir.glob and Dir.[] now sort the results by default, and + accept the `sort:` keyword option. [[Feature #8709]] + +* ENV + + * ENV.except has been added, which returns a hash excluding the + given keys and their values. [[Feature #15822]] + + * Windows: Read ENV names and values as UTF-8 encoded Strings + [[Feature #12650]] + +* Encoding + + * Added new encoding IBM720. [[Feature #16233]] + + * Changed default for Encoding.default_external to UTF-8 on Windows + [[Feature #16604]] + +* Fiber + + * Fiber.new(blocking: true/false) allows you to create non-blocking + execution contexts. [[Feature #16786]] + + * Fiber#blocking? tells whether the fiber is non-blocking. [[Feature #16786]] + + * Fiber#backtrace and Fiber#backtrace_locations provide per-fiber backtrace. + [[Feature #16815]] + + * The limitation of Fiber#transfer is relaxed. [[Bug #17221]] + +* GC + + * GC.auto_compact= and GC.auto_compact have been added to control + when compaction runs. Setting `auto_compact=` to `true` will cause + compaction to occur during major collections. At the moment, + compaction adds significant overhead to major collections, so please + test first! [[Feature #17176]] + +* Hash + + * Hash#transform_keys and Hash#transform_keys! now accept a hash that maps + keys to new keys. [[Feature #16274]] + + * Hash#except has been added, which returns a hash excluding the + given keys and their values. [[Feature #15822]] + +* IO + + * IO#nonblock? now defaults to `true`. [[Feature #16786]] + + * IO#wait_readable, IO#wait_writable, IO#read, IO#write and other + related methods (e.g. IO#puts, IO#gets) may invoke the scheduler hook + `#io_wait(io, events, timeout)` in a non-blocking execution context. + [[Feature #16786]] + +* Kernel + + * Kernel#clone when called with the `freeze: false` keyword will call + `#initialize_clone` with the `freeze: false` keyword. + [[Bug #14266]] + + * Kernel#clone when called with the `freeze: true` keyword will call + `#initialize_clone` with the `freeze: true` keyword, and will + return a frozen copy even if the receiver is unfrozen. + [[Feature #16175]] + + * Kernel#eval when called with two arguments will use `"(eval)"` + for `__FILE__` and `1` for `__LINE__` in the evaluated code. + [[Bug #4352]] + + * Kernel#lambda now warns if called without a literal block. + [[Feature #15973]] + + * Kernel.sleep invokes the scheduler hook `#kernel_sleep(...)` in a + non-blocking execution context. [[Feature #16786]] + +* Module + + * Module#include and Module#prepend now affect classes and modules + that have already included or prepended the receiver, mirroring the + behavior if the arguments were included in the receiver before + the other modules and classes included or prepended the receiver. + [[Feature #9573]] + + ```ruby + class C; end + module M1; end + module M2; end + C.include M1 + M1.include M2 + p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject] + ``` + + * Module#public, Module#protected, Module#private, Module#public_class_method, + Module#private_class_method, toplevel "private" and "public" methods + now accept single array argument with a list of method names. [[Feature #17314]] + + * Module#attr_accessor, Module#attr_reader, Module#attr_writer and Module#attr + methods now return an array of defined method names as symbols. + [[Feature #17314]] + + * Module#alias_method now returns the defined alias as a symbol. + [[Feature #17314]] + +* Mutex + + * `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change + should be compatible for essentially all usages and avoids blocking when + using a scheduler. [[Feature #16792]] + +* Proc + + * Proc#== and Proc#eql? are now defined and will return true for + separate Proc instances if the procs were created from the same block. + [[Feature #14267]] + +* Queue / SizedQueue + + * Queue#pop, SizedQueue#push and related methods may now invoke the + `block`/`unblock` scheduler hooks in a non-blocking context. + [[Feature #16786]] + +* Ractor + + * New class added to enable parallel execution. See rdoc-ref:ractor.md for + more details. + +* Random + + * `Random::DEFAULT` now refers to the `Random` class instead of being a `Random` instance, + so it can work with `Ractor`. + [[Feature #17322]] + + * `Random::DEFAULT` is deprecated since its value is now confusing and it is no longer global, + use `Kernel.rand`/`Random.rand` directly, or create a `Random` instance with `Random.new` instead. + [[Feature #17351]] + + +* String + + * The following methods now return or yield String instances + instead of subclass instances when called on subclass instances: + [[Bug #10845]] + + * String#* + * String#capitalize + * String#center + * String#chomp + * String#chop + * String#delete + * String#delete_prefix + * String#delete_suffix + * String#downcase + * String#dump + * String#each_char + * String#each_grapheme_cluster + * String#each_line + * String#gsub + * String#ljust + * String#lstrip + * String#partition + * String#reverse + * String#rjust + * String#rpartition + * String#rstrip + * String#scrub + * String#slice! + * String#slice / String#[] + * String#split + * String#squeeze + * String#strip + * String#sub + * String#succ / String#next + * String#swapcase + * String#tr + * String#tr_s + * String#upcase + +* Symbol + + * Symbol#to_proc now returns a lambda Proc. [[Feature #16260]] + + * Symbol#name has been added, which returns the name of the symbol + if it is named. The returned string is frozen. [[Feature #16150]] + +* Fiber + + * Introduce Fiber.set_scheduler for intercepting blocking operations and + Fiber.scheduler for accessing the current scheduler. See + rdoc-ref:fiber.md for more details about what operations are supported and + how to implement the scheduler hooks. [[Feature #16786]] + + * Fiber.blocking? tells whether the current execution context is + blocking. [[Feature #16786]] + + * Thread#join invokes the scheduler hooks `block`/`unblock` in a + non-blocking execution context. [[Feature #16786]] + +* Thread + + * Thread.ignore_deadlock accessor has been added for disabling the + default deadlock detection, allowing the use of signal handlers to + break deadlock. [[Bug #13768]] + +* Warning + + * Warning#warn now supports a category keyword argument. + [[Feature #17122]] + +## Stdlib updates + +Outstanding ones only. + +* BigDecimal + + * Update to BigDecimal 3.0.0 + + * This version is Ractor compatible. + +* Bundler + + * Update to Bundler 2.2.3 + +* CGI + + * Update to 0.2.0 + + * This version is Ractor compatible. + +* CSV + + * Update to CSV 3.1.9 + +* Date + + * Update to Date 3.1.1 + + * This version is Ractor compatible. + +* Digest + + * Update to Digest 3.0.0 + + * This version is Ractor compatible. + +* Etc + + * Update to Etc 1.2.0 + + * This version is Ractor compatible. + +* Fiddle + + * Update to Fiddle 1.0.5 + +* IRB + + * Update to IRB 1.2.6 + +* JSON + + * Update to JSON 2.5.0 + + * This version is Ractor compatible. + +* Set + + * Update to set 1.0.0 + + * SortedSet has been removed for dependency and performance reasons. + + * Set#join is added as a shorthand for `.to_a.join`. + + * Set#<=> is added. + +* Socket + + * Add :connect_timeout to TCPSocket.new [[Feature #17187]] + +* Net::HTTP + + * Net::HTTP#verify_hostname= and Net::HTTP#verify_hostname have been + added to skip hostname verification. [[Feature #16555]] + + * Net::HTTP.get, Net::HTTP.get_response, and Net::HTTP.get_print + can take the request headers as a Hash in the second argument when the + first argument is a URI. [[Feature #16686]] + +* Net::SMTP + + * Add SNI support. + + * Net::SMTP.start arguments are keyword arguments. + + * TLS should not check the host name by default. + +* OpenStruct + + * Initialization is no longer lazy. [[Bug #12136]] + + * Builtin methods can now be overridden safely. [[Bug #15409]] + + * Implementation uses only methods ending with `!`. + + * Ractor compatible. + + * Improved support for YAML. [[Bug #8382]] + + * Use officially discouraged. Read OpenStruct@Caveats section. + +* Pathname + + * Ractor compatible. + +* Psych + + * Update to Psych 3.3.0 + + * This version is Ractor compatible. + +* Reline + + * Update to Reline 0.1.5 + +* RubyGems + + * Update to RubyGems 3.2.3 + +* StringIO + + * Update to StringIO 3.0.0 + + * This version is Ractor compatible. + +* StringScanner + + * Update to StringScanner 3.0.0 + + * This version is Ractor compatible. + +## Compatibility issues + +Excluding feature bug fixes. + +* Regexp literals and all Range objects are frozen. [[Feature #8948]] [[Feature #16377]] [[Feature #15504]] + + ```ruby + /foo/.frozen? #=> true + (42...).frozen? # => true + ``` + +* EXPERIMENTAL: Hash#each consistently yields a 2-element array. [[Bug #12706]] + + * Now `{ a: 1 }.each(&->(k, v) { })` raises an ArgumentError + due to lambda's arity check. + +* When writing to STDOUT redirected to a closed pipe, no broken pipe + error message will be shown now. [[Feature #14413]] + +* `TRUE`/`FALSE`/`NIL` constants are no longer defined. + +* Integer#zero? overrides Numeric#zero? for optimization. [[Misc #16961]] + +* Enumerable#grep and Enumerable#grep_v when passed a Regexp and no block no longer modify + Regexp.last_match. [[Bug #17030]] + +* Requiring 'open-uri' no longer redefines `Kernel#open`. + Call `URI.open` directly or `use URI#open` instead. [[Misc #15893]] + +* SortedSet has been removed for dependency and performance reasons. + +## Stdlib compatibility issues + +* Default gems + + * The following libraries are promoted to default gems from stdlib. + + * English + * abbrev + * base64 + * drb + * debug + * erb + * find + * net-ftp + * net-http + * net-imap + * net-protocol + * open-uri + * optparse + * pp + * prettyprint + * resolv-replace + * resolv + * rinda + * set + * securerandom + * shellwords + * tempfile + * tmpdir + * time + * tsort + * un + * weakref + + * The following extensions are promoted to default gems from stdlib. + + * digest + * io-nonblock + * io-wait + * nkf + * pathname + * syslog + * win32ole + +* Bundled gems + + * net-telnet and xmlrpc have been removed from the bundled gems. + If you are interested in maintaining them, please comment on + your plan to https://github.com/ruby/xmlrpc + or https://github.com/ruby/net-telnet. + +* SDBM has been removed from the Ruby standard library. [[Bug #8446]] + + * The issues of sdbm will be handled at https://github.com/ruby/sdbm + +* WEBrick has been removed from the Ruby standard library. [[Feature #17303]] + + * The issues of WEBrick will be handled at https://github.com/ruby/webrick + +## C API updates + +* C API functions related to `$SAFE` have been removed. + [[Feature #16131]] + +* C API header file `ruby/ruby.h` was split. [[GH-2991]] + + This should have no impact on extension libraries, + but users might experience slow compilations. + +* Memory view interface [EXPERIMENTAL] + + * The memory view interface is a C-API set to exchange a raw memory area, + such as a numeric array or a bitmap image, between extension libraries. + The extension libraries can share also the metadata of the memory area + that consists of the shape, the element format, and so on. + Using these kinds of metadata, the extension libraries can share even + a multidimensional array appropriately. + This feature is designed by referring to Python's buffer protocol. + [[Feature #13767]] [[Feature #14722]] + +* Ractor related C APIs are introduced (experimental) in "include/ruby/ractor.h". + +## Implementation improvements + +* New method cache mechanism for Ractor. [[Feature #16614]] + + * Inline method caches pointed from ISeq can be accessed by multiple Ractors + in parallel and synchronization is needed even for method caches. However, + such synchronization can be overhead so introducing new inline method cache + mechanisms, (1) Disposable inline method cache (2) per-Class method cache + and (3) new invalidation mechanism. (1) can avoid per-method call + synchronization because it only uses atomic operations. + See the ticket for more details. + +* The number of hashes allocated when using a keyword splat in + a method call has been reduced to a maximum of 1, and passing + a keyword splat to a method that accepts specific keywords + does not allocate a hash. + +* `super` is optimized when the same type of method is called in the previous call + if it's not refinements or an attr reader or writer. + +### JIT + +* Performance improvements of JIT-ed code + + * Microarchitectural optimizations + + * Native functions shared by multiple methods are deduplicated on JIT compaction. + + * Decrease code size of hot paths by some optimizations and partitioning cold paths. + + * Instance variables + + * Eliminate some redundant checks. + + * Skip checking a class and a object multiple times in a method when possible. + + * Optimize accesses in some core classes like Hash and their subclasses. + + * Method inlining support for some C methods + + * `Kernel`: `#class`, `#frozen?` + + * `Integer`: `#-@`, `#~`, `#abs`, `#bit_length`, `#even?`, `#integer?`, `#magnitude`, + `#odd?`, `#ord`, `#to_i`, `#to_int`, `#zero?` + + * `Struct`: reader methods for 10th or later members + + * Constant references are inlined. + + * Always generate appropriate code for `==`, `nil?`, and `!` calls depending on + a receiver class. + + * Reduce the number of PC accesses on branches and method returns. + + * Optimize C method calls a little. + +* Compilation process improvements + + * It does not keep temporary files in /tmp anymore. + + * Throttle GC and compaction of JIT-ed code. + + * Avoid GC-ing JIT-ed code when not necessary. + + * GC-ing JIT-ed code is executed in a background thread. + + * Reduce the number of locks between Ruby and JIT threads. + +## Static analysis + +### RBS + +* RBS is a new language for type definition of Ruby programs. + It allows writing types of classes and modules with advanced + types including union types, overloading, generics, and + _interface types_ for duck typing. + +* Ruby ships with type definitions for core/stdlib classes. + +* `rbs` gem is bundled to load and process RBS files. + +### TypeProf + +* TypeProf is a type analysis tool for Ruby code based on abstract interpretation. + + * It reads non-annotated Ruby code, tries inferring its type signature, and prints + the analysis result in RBS format. + + * Though it supports only a subset of the Ruby language yet, we will continuously + improve the coverage of language features, analysis performance, and usability. + +```ruby +# test.rb +def foo(x) + if x > 10 + x.to_s + else + nil + end +end + +foo(42) +``` + +``` +$ typeprof test.rb +# Classes +class Object + def foo : (Integer) -> String? +end +``` + +## Miscellaneous changes + +* Methods using `ruby2_keywords` will no longer keep empty keyword + splats, those are now removed just as they are for methods not + using `ruby2_keywords`. + +* When an exception is caught in the default handler, the error + message and backtrace are printed in order from the innermost. + [[Feature #8661]] + +* Accessing an uninitialized instance variable no longer emits a + warning in verbose mode. [[Feature #17055]] + +[Bug #4352]: https://bugs.ruby-lang.org/issues/4352 +[Bug #6087]: https://bugs.ruby-lang.org/issues/6087 +[Bug #8382]: https://bugs.ruby-lang.org/issues/8382 +[Bug #8446]: https://bugs.ruby-lang.org/issues/8446 +[Feature #8661]: https://bugs.ruby-lang.org/issues/8661 +[Feature #8709]: https://bugs.ruby-lang.org/issues/8709 +[Feature #8948]: https://bugs.ruby-lang.org/issues/8948 +[Feature #9573]: https://bugs.ruby-lang.org/issues/9573 +[Bug #10845]: https://bugs.ruby-lang.org/issues/10845 +[Bug #12136]: https://bugs.ruby-lang.org/issues/12136 +[Feature #12650]: https://bugs.ruby-lang.org/issues/12650 +[Bug #12706]: https://bugs.ruby-lang.org/issues/12706 +[Feature #13767]: https://bugs.ruby-lang.org/issues/13767 +[Bug #13768]: https://bugs.ruby-lang.org/issues/13768 +[Feature #14183]: https://bugs.ruby-lang.org/issues/14183 +[Bug #14266]: https://bugs.ruby-lang.org/issues/14266 +[Feature #14267]: https://bugs.ruby-lang.org/issues/14267 +[Feature #14413]: https://bugs.ruby-lang.org/issues/14413 +[Bug #14541]: https://bugs.ruby-lang.org/issues/14541 +[Feature #14722]: https://bugs.ruby-lang.org/issues/14722 +[Bug #15409]: https://bugs.ruby-lang.org/issues/15409 +[Feature #15504]: https://bugs.ruby-lang.org/issues/15504 +[Feature #15575]: https://bugs.ruby-lang.org/issues/15575 +[Feature #15822]: https://bugs.ruby-lang.org/issues/15822 +[Misc #15893]: https://bugs.ruby-lang.org/issues/15893 +[Feature #15921]: https://bugs.ruby-lang.org/issues/15921 +[Feature #15973]: https://bugs.ruby-lang.org/issues/15973 +[Feature #16131]: https://bugs.ruby-lang.org/issues/16131 +[Feature #16150]: https://bugs.ruby-lang.org/issues/16150 +[Feature #16166]: https://bugs.ruby-lang.org/issues/16166 +[Feature #16175]: https://bugs.ruby-lang.org/issues/16175 +[Feature #16233]: https://bugs.ruby-lang.org/issues/16233 +[Feature #16260]: https://bugs.ruby-lang.org/issues/16260 +[Feature #16274]: https://bugs.ruby-lang.org/issues/16274 +[Feature #16345]: https://bugs.ruby-lang.org/issues/16345 +[Feature #16377]: https://bugs.ruby-lang.org/issues/16377 +[Feature #16378]: https://bugs.ruby-lang.org/issues/16378 +[Feature #16555]: https://bugs.ruby-lang.org/issues/16555 +[Feature #16604]: https://bugs.ruby-lang.org/issues/16604 +[Feature #16614]: https://bugs.ruby-lang.org/issues/16614 +[Feature #16686]: https://bugs.ruby-lang.org/issues/16686 +[Feature #16746]: https://bugs.ruby-lang.org/issues/16746 +[Feature #16754]: https://bugs.ruby-lang.org/issues/16754 +[Feature #16786]: https://bugs.ruby-lang.org/issues/16786 +[Feature #16792]: https://bugs.ruby-lang.org/issues/16792 +[Feature #16815]: https://bugs.ruby-lang.org/issues/16815 +[Feature #16828]: https://bugs.ruby-lang.org/issues/16828 +[Misc #16961]: https://bugs.ruby-lang.org/issues/16961 +[Bug #17030]: https://bugs.ruby-lang.org/issues/17030 +[Feature #17055]: https://bugs.ruby-lang.org/issues/17055 +[Feature #17104]: https://bugs.ruby-lang.org/issues/17104 +[Feature #17122]: https://bugs.ruby-lang.org/issues/17122 +[Feature #17136]: https://bugs.ruby-lang.org/issues/17136 +[Feature #17176]: https://bugs.ruby-lang.org/issues/17176 +[Feature #17187]: https://bugs.ruby-lang.org/issues/17187 +[Bug #17221]: https://bugs.ruby-lang.org/issues/17221 +[Feature #17260]: https://bugs.ruby-lang.org/issues/17260 +[Feature #17273]: https://bugs.ruby-lang.org/issues/17273 +[Feature #17303]: https://bugs.ruby-lang.org/issues/17303 +[Feature #17314]: https://bugs.ruby-lang.org/issues/17314 +[Feature #17322]: https://bugs.ruby-lang.org/issues/17322 +[Feature #17351]: https://bugs.ruby-lang.org/issues/17351 +[Feature #17371]: https://bugs.ruby-lang.org/issues/17371 +[Bug #17419]: https://bugs.ruby-lang.org/issues/17419 +[GH-2991]: https://github.com/ruby/ruby/pull/2991 diff --git a/ruby/doc/bsearch.rdoc b/ruby/doc/bsearch.rdoc new file mode 100644 index 000000000..ca8091fc0 --- /dev/null +++ b/ruby/doc/bsearch.rdoc @@ -0,0 +1,120 @@ +== Binary Searching + +A few Ruby methods support binary searching in a collection: + +Array#bsearch:: Returns an element selected via a binary search + as determined by a given block. +Array#bsearch_index:: Returns the index of an element selected via a binary search + as determined by a given block. +Range#bsearch:: Returns an element selected via a binary search + as determined by a given block. + +Each of these methods returns an enumerator if no block is given. + +Given a block, each of these methods returns an element (or element index) from +self+ +as determined by a binary search. +The search finds an element of +self+ which meets +the given condition in O(log n) operations, where +n+ is the count of elements. ++self+ should be sorted, but this is not checked. + +There are two search modes: + +Find-minimum mode:: method +bsearch+ returns the first element for which + the block returns +true+; + the block must return +true+ or +false+. +Find-any mode:: method +bsearch+ some element, if any, for which + the block returns zero. + the block must return a numeric value. + +The block should not mix the modes by sometimes returning +true+ or +false+ +and other times returning a numeric value, but this is not checked. + +Find-Minimum Mode + +In find-minimum mode, the block must return +true+ or +false+. +The further requirement (though not checked) is that +there are no indexes +i+ and +j+ such that: + +- 0 <= i < j <= self.size. +- The block returns +true+ for self[i] and +false+ for self[j]. + +Less formally: the block is such that all +false+-evaluating elements +precede all +true+-evaluating elements. + +In find-minimum mode, method +bsearch+ returns the first element +for which the block returns +true+. + +Examples: + + a = [0, 4, 7, 10, 12] + a.bsearch {|x| x >= 4 } # => 4 + a.bsearch {|x| x >= 6 } # => 7 + a.bsearch {|x| x >= -1 } # => 0 + a.bsearch {|x| x >= 100 } # => nil + + r = (0...a.size) + r.bsearch {|i| a[i] >= 4 } #=> 1 + r.bsearch {|i| a[i] >= 6 } #=> 2 + r.bsearch {|i| a[i] >= 8 } #=> 3 + r.bsearch {|i| a[i] >= 100 } #=> nil + r = (0.0...Float::INFINITY) + r.bsearch {|x| Math.log(x) >= 0 } #=> 1.0 + +These blocks make sense in find-minimum mode: + + a = [0, 4, 7, 10, 12] + a.map {|x| x >= 4 } # => [false, true, true, true, true] + a.map {|x| x >= 6 } # => [false, false, true, true, true] + a.map {|x| x >= -1 } # => [true, true, true, true, true] + a.map {|x| x >= 100 } # => [false, false, false, false, false] + +This would not make sense: + + a.map {|x| x == 7 } # => [false, false, true, false, false] + +Find-Any Mode + +In find-any mode, the block must return a numeric value. +The further requirement (though not checked) is that +there are no indexes +i+ and +j+ such that: + +- 0 <= i < j <= self.size. +- The block returns a negative value for self[i] + and a positive value for self[j]. +- The block returns a negative value for self[i] and zero self[j]. +- The block returns zero for self[i] and a positive value for self[j]. + +Less formally: the block is such that: + +- All positive-evaluating elements precede all zero-evaluating elements. +- All positive-evaluating elements precede all negative-evaluating elements. +- All zero-evaluating elements precede all negative-evaluating elements. + +In find-any mode, method +bsearch+ returns some element +for which the block returns zero, or +nil+ if no such element is found. + +Examples: + + a = [0, 4, 7, 10, 12] + a.bsearch {|element| 7 <=> element } # => 7 + a.bsearch {|element| -1 <=> element } # => nil + a.bsearch {|element| 5 <=> element } # => nil + a.bsearch {|element| 15 <=> element } # => nil + + a = [0, 100, 100, 100, 200] + r = (0..4) + r.bsearch {|i| 100 - a[i] } #=> 1, 2 or 3 + r.bsearch {|i| 300 - a[i] } #=> nil + r.bsearch {|i| 50 - a[i] } #=> nil + +These blocks make sense in find-any mode: + + a = [0, 4, 7, 10, 12] + a.map {|element| 7 <=> element } # => [1, 1, 0, -1, -1] + a.map {|element| -1 <=> element } # => [-1, -1, -1, -1, -1] + a.map {|element| 5 <=> element } # => [1, 1, -1, -1, -1] + a.map {|element| 15 <=> element } # => [1, 1, 1, 1, 1] + +This would not make sense: + + a.map {|element| element <=> 7 } # => [-1, -1, 0, 1, 1] diff --git a/ruby/doc/case_mapping.rdoc b/ruby/doc/case_mapping.rdoc new file mode 100644 index 000000000..29d7bc6c3 --- /dev/null +++ b/ruby/doc/case_mapping.rdoc @@ -0,0 +1,116 @@ +== Case Mapping + +Some string-oriented methods use case mapping. + +In String: + +- String#capitalize +- String#capitalize! +- String#casecmp +- String#casecmp? +- String#downcase +- String#downcase! +- String#swapcase +- String#swapcase! +- String#upcase +- String#upcase! + +In Symbol: + +- Symbol#capitalize +- Symbol#casecmp +- Symbol#casecmp? +- Symbol#downcase +- Symbol#swapcase +- Symbol#upcase + +=== Default Case Mapping + +By default, all of these methods use full Unicode case mapping, +which is suitable for most languages. +See {Unicode Latin Case Chart}[https://www.unicode.org/charts/case]. + +Non-ASCII case mapping and folding are supported for UTF-8, +UTF-16BE/LE, UTF-32BE/LE, and ISO-8859-1~16 Strings/Symbols. + +Context-dependent case mapping as described in +{Table 3-17 of the Unicode standard}[https://www.unicode.org/versions/Unicode13.0.0/ch03.pdf] +is currently not supported. + +In most cases, case conversions of a string have the same number of characters. +There are exceptions (see also +:fold+ below): + + s = "\u00DF" # => "ß" + s.upcase # => "SS" + s = "\u0149" # => "ʼn" + s.upcase # => "ʼN" + +Case mapping may also depend on locale (see also +:turkic+ below): + + s = "\u0049" # => "I" + s.downcase # => "i" # Dot above. + s.downcase(:turkic) # => "ı" # No dot above. + +Case changes may not be reversible: + + s = 'Hello World!' # => "Hello World!" + s.downcase # => "hello world!" + s.downcase.upcase # => "HELLO WORLD!" # Different from original s. + +Case changing methods may not maintain Unicode normalization. +See String#unicode_normalize). + +=== Options for Case Mapping + +Except for +casecmp+ and +casecmp?+, +each of the case-mapping methods listed above +accepts optional arguments, *options. + +The arguments may be: + +- +: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); + other characters are not changed + + s = "Foo \u00D8 \u00F8 Bar" # => "Foo Ø ø Bar" + s.upcase # => "FOO Ø Ø BAR" + s.downcase # => "foo ø ø bar" + s.upcase(:ascii) # => "FOO Ø ø BAR" + s.downcase(:ascii) # => "foo Ø ø bar" + +- +:turkic+: + Full Unicode case mapping, adapted for the Turkic languages + that distinguish dotted and dotless I, for example Turkish and Azeri. + + s = 'Türkiye' # => "Türkiye" + s.upcase # => "TÜRKIYE" + s.upcase(:turkic) # => "TÜRKİYE" # Dot above. + + s = 'TÜRKIYE' # => "TÜRKIYE" + 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): + Unicode case folding, + which is more far-reaching than Unicode case mapping. + + s = "\u00DF" # => "ß" + s.downcase # => "ß" + s.downcase(:fold) # => "ss" + s.upcase # => "SS" + + s = "\uFB04" # => "ffl" + s.downcase # => "ffl" + s.upcase # => "FFL" + s.downcase(:fold) # => "ffl" diff --git a/ruby/doc/contributing.rdoc b/ruby/doc/contributing.rdoc index 68dda66e4..00875d142 100644 --- a/ruby/doc/contributing.rdoc +++ b/ruby/doc/contributing.rdoc @@ -27,10 +27,10 @@ on your ticket. stable release. See {Downloading Ruby}[https://www.ruby-lang.org/en/downloads/]. * Look to see if anyone already reported your issue, try - {searching on redmine}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues] + {searching on redmine}[https://bugs.ruby-lang.org/projects/ruby-master/issues] for your problem. * If you can't find a ticket addressing your issue, - {create a new one}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues/new]. + {create a new one}[https://bugs.ruby-lang.org/projects/ruby-master/issues/new]. * Choose the target version, usually current. Bugs will be first fixed in the current release and then {backported}[rdoc-label:label-Backport+Requests]. * Fill in the Ruby version you're using when experiencing this issue @@ -59,32 +59,6 @@ You can report downstream issues for the following distributions via their bug t * {macports}[https://trac.macports.org/query?status=assigned&status=new&status=reopened&port=~ruby] * etc (add your distribution bug tracker here) -=== Platform Maintainers - -For platform specific bugs in Ruby, you can assign your ticket to the current -maintainer for a specific platform. - -The current active platform maintainers are as follows: - -[mswin64 (Microsoft Windows)] - NAKAMURA Usaku (usa) -[mingw32 (Minimalist GNU for Windows)] - Nobuyoshi Nakada (nobu) -[AIX] - Yutaka Kanemoto (kanemoto) -[FreeBSD] - Akinori MUSHA (knu) -[Solaris] - Naohisa Goto (ngoto) -[RHEL, CentOS] - KOSAKI Motohiro (kosaki) -[macOS] - Kenta Murata (mrkn) -[OpenBSD] - Jeremy Evans (jeremyevans0) -[cygwin, bcc32, djgpp, wince, ...] - none. (Maintainer WANTED) - == Reporting Security Issues Security vulnerabilities receive special treatment since they may negatively @@ -116,7 +90,7 @@ these? Quite a bit, actually: When a bug report goes for a while without any feedback, it goes to the bug graveyard which is unfortunate. If you check the {issues -list}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues] you will find lots +list}[https://bugs.ruby-lang.org/projects/ruby-master/issues] you will find lots of delinquent bugs that require attention. You can help by verifying the existing tickets, try to reproduce the reported @@ -156,7 +130,7 @@ If there's a new feature that you want to see added to Ruby, you will need to write a convincing proposal and patch to implement the feature. For new features in CRuby, use the {'Feature' -tracker}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues?set_filter=1&tracker_id=2] +tracker}[https://bugs.ruby-lang.org/projects/ruby-master/issues?set_filter=1&tracker_id=2] on ruby-master. For non-CRuby dependent features, features that would apply to alternate Ruby implementations such as JRuby and Rubinius, use the {CommonRuby tracker}[https://bugs.ruby-lang.org/projects/common-ruby]. @@ -195,25 +169,6 @@ A good template for a feature proposal should look something like this: [See also] Links to the other related resources -=== Slideshow - -At the Ruby Developer Meeting in Japan, committers discuss Feature Proposals together in Tokyo. We will judge proposals and then accept, reject, or give feedback for them. -If you have a stalled proposal, making a slide to submit is good way to get feedback. - -Slides should be: - -* One-page slide -* Include a corresponding ticket number -* MUST include a figure and/or short example code -* SHOULD have less sentence in natural language (try to write less than 140 characters) -* It is RECOMMENDED to itemize: motivation/use case, proposal, pros/cons, corner case -* PDF or Image (Web browsers can show it) - -Please note: - -* Even if the proposal is generally acceptable, it won't be accepted without writing corner cases in the ticket -* Slide's example: DevelopersMeeting20130727Japan - == Backport Requests When a new version of Ruby is released, it starts at patch level 0 (p0), and @@ -260,8 +215,8 @@ run tests. * autoconf - 2.67 or later, preferably 2.69. * bison - 2.0 or later, preferably 3.4. * gperf - 3.0.3 or later, preferably 3.1. -* ruby - Ruby itself is prerequisite in order to build Ruby from source. It - can be 1.8. +* ruby - Ruby itself is prerequisite in order to build Ruby from source. + You should use [a maintained version of Ruby](https://www.ruby-lang.org/en/downloads/). You should also have access to development headers for the following libraries, but these are not required: @@ -284,7 +239,7 @@ Now let's build CRuby: * Generate the configuration files and build: cd ruby-master - autoconf + ./autogen.sh mkdir build && cd build # its good practice to build outside of source dir mkdir ~/.rubies # we will install to .rubies/ruby-master in our home dir ../configure --prefix="${HOME}/.rubies/ruby-master" diff --git a/ruby/doc/contributors.rdoc b/ruby/doc/contributors.rdoc deleted file mode 100644 index 7c3722032..000000000 --- a/ruby/doc/contributors.rdoc +++ /dev/null @@ -1,793 +0,0 @@ -= Contributors to Ruby - -The following list might be incomplete. Feel free to add your name if your -patch was accepted into Ruby. - -== A - -Ayumu AIZAWA (ayumin) -* committer - -AKIYOSHI, Masamichi (akiyoshi) -* committer -* He had maintained the VMS support on 2003-2004. - -Muhammad Ali -* wrote rdoc for Fiber - -Minero Aoki (aamine) -* committer -* He is the maintainer of: - * fileutils - * net/http, net/https - * net/pop - * net/smtp - * racc - * ripper - * strscan - -Wakou Aoyama (wakou) -* committer -* He was the maintainer of some standard libraries. - -Koji Arai -* committer - -arton -* He is the distributor of ActiveScriptRuby and experimental 1.9.0-x installers for win32. -* Wrote patches for win32ole, gc.c, tmpdir.rb - -Sergey Avseyev -* Added IO#pread and IO#pwrite. - -== B - -Daniel Berger -* a patch for irb -* documentation -* He wrote forwardable.rb - -David Black (dblack) -* committer -* He is the maintainer of scanf - -Ken Bloom -* a patch for REXML. - -Oliver M. Bolzer -* a patch for soap - -Alexey Borzenkov -* a patch for mkmf.rb - -Evan Brodie -* a patch for documentation of Float#round - -Richard Brown -* a patch for configure.in - -Dirkjan Bussink -* a patch for date.rb - -Daniel Bovensiepen -* documentation -* a patch for irb - -== C - -Brian Candler -* a patch for configure.in, net/telnet - -keith cascio -* a patch for optparse.rb - -Frederick Cheung -* a patch for test/ruby/test_symbol.rb - -Christoph -* patches for set.rb - -Sean Chittenden -* patches for net/http, cgi - -William D. Clinger -* ruby_strtod is based on his paper. - -== D - -Ryan Davis (ryan) -* committer -* He wrote and is the maintainer of miniunit - -Guy Decoux (ts) -* committer - -Zach Dennis - -Martin Duerst (duerst) -* committer -* M17N - -Paul Duncan -* patches for rdoc - -Alexander Dymo -* a patch for lib/benchmark.rb - -== E - -Yusuke Endoh (mame) -* committer -* He wrote and is the maintainer of base64 library (1.9) -* did much upon YARV compiler. - -erlercw -* wrote Integer::gcd2 - -== F - -Frank S.Fejes -* a patch for net/pop - -Fundakowski Feldman -* a patch for process.c - -Mauricio Fernandez -* patches for parse.y - -David Flanagan (davidflanagan) -* committer -* M17N - -Takeyuki Fujioka (xibbar) -* committer -* He is the maintainer of cgi/* - -FUKUMOTO, Atsushi -* a patch for tracer.rb - -Shota Fukumori (sorah) -* committer -* #4415 parallel unit/test - -Tadayoshi Funaba (tadf) -* committer -* He wrote and is the maintainer of - * date - * parsedate (1.8) -* He ported rational.rb and complex.rb, which 1.8 contains, into rational.c and complex.c of 1.9. - -== G - -David M. Gay -* ruby_strtod - -Florian Gilcher -* documentation - -GOTOU, Kentaro (gotoken) -* committer -* He wrote benchmark.rb -* He is the maintainer of: - * benchmark.rb - * open3 - -GOTOU, Yuuzou (gotoyuzo) -* committer - -James Edward Gray II (jeg2) -* committer -* He wrote the faster implementation of CSV and is the maintainer of csv. -* Wrote documentation for rdoc - -== H - -Phil Hagelberg -* patch for ruby-mode.el's documentation. - -Kirk Haines (wyhaines) -* committer -* the maintainer of ruby_1_8_6 branch - -Shinichiro Hamaji -* fixed memory leaks (marshal.c, string.c) - -Shin-ichiro HARA -* the developer and the sysop of ruby-{dev,list,core,talk} archive. -* a patch for numeric.c - -Chris Heath (traumdeutung) -* a patch for proc.c - -HIROKAWA Hisashi -* fixed socket/socket.c - -Daniel Hob -* He wrote: - * SMTP-TLS support for net/smtp. - * POP3S support - -Eric Hodel (drbrain) -* committer -* He is the maintainer of: - * rdoc - * ri - * rubygems - -Erik Hollensbe -* a patch for delegate.rb - -Johan Holmberg -* a patch for dir.c -* documentation - -Erik Huelsmann - -Dae San Hwang -* built a continuous integration environment on OpenSolaris. - -== I - -Nobuhiro IMAI -* a patch for logger.rb - -"incorporate" -* a patch for sprintf.c - -Keiju Ishitsuka (keiju) -* committer -* He wrote and is the maintainer of: - * cmath.rb (1.9) - * complex.rb (1.8) - * e2mmap.rb - * forwardable.rb - * irb - * mathn - * matrix.rb - * mutex_m.rb - * rational.rb (1.8) - * sync.rb - * shell/* - * thwait.rb - * tracer.rb - -== J - -Curtis Jackson -* missing/dup2.c - -Alan Johnson -* a patch for net/ftp - -Lyle Johnson -* patches for nkf, bigdecimal, numeric.c - -== K - -Yoshihiro Kambayashi -* a patch for enc/trans/single_byte.trans. -* He wrote supports for some encodings. - -Yutaka Kanemoto -* patches for common.mk, AIX AF_INET6 support - -Motoyuki Kasahara -* He wrote getoptlong.rb - -Masahiro Kawato -* a patch for shellwords.rb - -Wataru Kimura -* a patch for configure.in - -Michael Klishin -* patch for make help. - -Noritada Kobayashi -* a patch for optparse.rb - -Shigeo Kobayashi (shigek) -* committer -* He is the maintainer of bigdecimal - -KONISHI, Hiromasa (H_Konishi) -* committer -* He had maintained the bcc32 support in 2004. - -Kornelius "murphy" Kalnbach -* documentation - -K.Kosako (kosako) -* committer -* He wrote Oniguruma. - -Takehiro Kubo -* patches for dl 64bit support. - -== L - -Marc-Andre Lafortune (marcandre) -* committer -* patches for hash.c, array.c, thread.c, enumc, string.c, range.c and rdoc documentation. - -Hongli Lai -* improved pstore.rb -* patch for tool/file2lastrev.rb. - -raspberry lemon -* a patch for webrick/httpproxy.rb. - -Christian Loew -* a patch for fileutils.rb - -== M - -Shugo Maeda (shugo) -* committer -* A system administrator of ruby-lang.org servers. -* He wrote and is the maintainer of: - * monitor.rb - * net/ftp - * net/imap - -Stephan Maka (mathew) -* documentation - -Yukihiro Matsumoto (matz) -* Matz -- the founder, language designer of Ruby. -* committer -* Ruby itself, most of Ruby. -* He is the maintainer of: - * singleton - * timeout - * gdbm - * sdbm - -Konrad Meyer -* documentation - -Mib Software -* missing/vsnprintf.c - -Todd C. Miller -* missing/strlcat.c -* missing/strlcpy.c - -MIYASAKA, Masaru -* a patch for cgi.rb - -Stefan Monnier -* regex.c was fixed with based on his Emacs21 patch. - -Marcel Moolenaar -* patches for eval.c and gc.c. - -moonwolf -* a patch for REXML, xmlrpc - -Hiroshi Moriyama -* a patch for yaml. - -Kyosuke Morohashi -* a patch for gem_prelude.rb - -Kenta Murata -* patches for json, bignum.c - -Akinori MUSHA (knu) -* committer -* He wrote and is the maintainer of: - * abbrev.rb - * generator (1.8) - * enumerator (1.8) - * set - * ipaddr.rb - * digest/* - * syslog -* He is the branch maintainer of ruby_1_8, the release manager of 1.8 series. - -== N - -Hidetoshi NAGAI (nagai) -* committer -* He is the maintainer of tk/* - -Nobuyoshi Nakada (nobu) -* committer -* a.k.a. the "patch monster" -* He wrote and is the maintainer of: - * optparse - * stringio - * io/wait - * iconv - -Satoshi Nakagawa -* patches for util.c - -Narihiro Nakamura (nari) -* committer -* a.k.a. authorNari -* working at GC - -NAKAMURA, Hiroshi (nahi) -* committer -* He is the maintainer of: - * csv.rb (1.8) - * logger.rb - * soap/* (1.8) - * wsdl/* (1.8) - * xsd/* (1.8) - -NAKAMURA, Usaku (usa) -* committer -* a.k.a. unak -* He is the maintainer of mswin32 and mswin64 support. - -NARUSE, Yui (naruse) -* committer -* a.k.a. "nurse" -* Did much upon m17n. -* He is the maintainer of: - * json - * nkf - -Christian Neukirchen -* a patch for webrick/httputils - -Michael Neumann (mneumann) -* committer -* He is the maintainer of - * xmlrpc (1.8) - * gserver (1.8) - -NISHIO Hirokazu -* wrote a patch for CVE-2010-0541 - -Kazuhiro NISHIYAMA (kazu) -* committer -* a.k.a. znz - -Go Noguchi - -Martin Nordholts -* misc/rdebug.el - -nmu -* a patch for socket - -== O - -okkez -* He is a sysop of the Ruby Reference Manual Renewal Project. -* fixed ipaddr.rb, ext/etc - -Haruhiko Okumura -* some of missing/* is based on his book: - * missing/erf.c - * missing/lgamma_r.c - * missing/tgamma.c - -OMAE, jun -* a patch for debug.rb - -Eugene Ossintsev -* documentation - -== P - -Heesob Park -* a patch for win32/win32.c. - -pegacorn -* a patch for instruby.rb - -== Q - -== R - -Gaston Ramos -* documentation - -The Regents of the University of California -* missing/crypt.c -* missing/vsnprintf.c - -Sam Roberts -* patch for socket -* documentation - -Michal Rokos (michal) -* committer -* He was the maintainer of DJGPP support. - -rubikitch -* a patch for io.c - -Marcus Rueckert -* a patch for mkconfig.rb. - -Run Paint Run Run -* patch for enc/unicode.c -* documentation - -Sean Russell (ser) -* committer -* He wrote and is the maintainer of REXML. - -== S - -Kazuo Saito (ksaito) -* committer -* M17N - -Tadashi Saito -* patches for test/ruby/test_math.rb, thread_*.c, bignum.c -* working upon BigDecimal. -* did much upon documentation - -Masahiro Sakai -* a patch for io.c - -Laurent Sansonetti -* a patch for tool/ytab.sed - -Jeff Saracco -* documentation - -Koichi Sasada (ko1) -* committer -* He wrote YARV. - -Hugh Sasse -* a patch for net/http -* documentation - -Charlie Savage -* a patch for win32/Makefile.sub - -Michael Scholz -* a patch for ruby-mode.el - -Arthur Schreiber -* patch for net/http and rdoc. - -Masatoshi SEKI (seki) -* committer -* He wrote and is the maintainer of: - * drb/* - * erb - * rinda - -Roman Shterenzon -* a patch for open-uri. - -Kent Sibilev - -Gavin Sinclair (gsinclair) -* committer - -John W. Small -* He wrote gserver.rb - -Yuki Sonoda (yugui) -* committer -* She is the maintainer of man/* manual pages and is the release manager of 1.9 series. -* She wrote prime.rb. -* A developer and a sysop of redmine.ruby-lang.org. - -SOUMA, Yutaka -* a patch for pack.c. - -Tatsuki Sugiura -* WebDAV support for net/http - -Masaki Suketa (suke) -* committer -* He is the maintainer of win32ole - -sheepman -* patches for ruby.c, thread.c, stringio, enum.c, webrick, net/http - -Siena. (siena) -* committer - -Kirill A. Shutemov -* a patch for parse.y - -Darren Smith -* a patch for golf_prelude.rb - -Richard M. Stallman -* missing/alloca.c - -Robin Stocker -* documentation - -Joshua Stowers -* a patch for array.c - -Marcus Stollsteimer (stomar) -* committer -* a maintainer of www.ruby-lang.org -* patches for cgi (HTML5 tag maker), numeric.c, bigdecimal, ostruct.rb, prime.rb, and others -* documentation - -Adam Strzelecki -* a patch for compile.c - -Masashi Sumi -* improved net/pop.rb - -Eric Sunshine -* NeXT OpenStep, Rhapsody support - -Kouhei Sutou (kou) -* committer -* He wrote and is the maintainer of rss/* - -David Symonds -* documentation - -== T - -TAKANO Mitsuhiro (takano32) -* committer -* He is the maintainer of IA-64 support. -* BigDecimal - -TAKAO, Kouji (kouji) -* committer -* He is the maintainer of readline. - -Nathaniel Talbott (ntalbott) -* committer -* He was the maintainer of test/unit, runit, rubyunit. - -TANAKA, Akira (akr) -* committer -* Did much upon m17n. -* And he is the maintainer of: - * open-uri - * pathname - * pp - * resolv-replace - * resolv - * time - * tsort - -Takaaki Tateishi (ttate) -* committer -* He was the maintainer of dl - -Technorama Ltd. (technoroma) -* committer -* openssl - -Andrew Thompson -* a patch for socket.c IRIX support. - -Dave Thomas (dave) -* committer -* a.k.a. the Pragmatic Programmer. -* He wrote rdoc. - -Tietew -* patches for win32 support - -Masahiro Tomita -* a patch for cgi.rb - -Jakub Travnik -* a patch for eval.c - -Tom Truscott -* missing/crypt.c - -== U - -UEDA, Satoshi -* a patch for uri - -Takaaki Uematsu (uema2) -* committer -* He was the maintainer of WinCE support. - -UENO, Katsuhiro (katsu) -* committer -* He is the maintainer of zlib - -Hajimu UMEMOTO -* He wrote ipaddr.rb - -URABE, Shyouhei (shyouhei) -* committer -* a.k.a. mput. -* He is the branch maintainer of ruby_1_8_6 and ruby_1_8_7 -* and is the release manager of 1.8.x-pXXX. - -== V - -Joel VanderWerf -* a patch for numeric.c - -Peter Vanbroekhoven - -Corinna Vinschen - -== W - -wanabe (wanabe) -* committer -* fixed YARV and Oniguruma. - -Chun Wang -* a patch for time.rb - -WATANABE, Hirofumi (eban) -* committer -* He is the maintainer of - * ftools (1.8) - * tmpdir - * un - * Win32API - -WATANABE, Tetsuya -* a patch for ruby.c - -William Webber (wew) -* committer - -Jim Weirich (jim) -* committer -* He wrote Rake. - -Nathan Weizenbaum -* fixed misc/ruby-mode.el. - -why the lukky stiff (why) -* committer -* He is the maintainer of syck - -Caley Woods -* documentation - -Gary Wright -* documentation - -== X - -== Y - -Akira Yamada (akira) -* committer -* He is the maintainer of ruby related packages at Debian project. - -Keita Yamaguchi -* patches for enum.c, parse.y -* documentation - -Hirokazu Yamamoto (ocean) -* committer - -Hirotaka Yoshioka -* a patch for improving SEGV handling - -== Z - -Aristarkh A Zagorodnikov -* a patch for io.c - -Alexander Zavorine -* committer -* He is the maintainer for Symbian OS. - -Chiyuan Zhang -* a patch for misc/ruby-mode.el. - -Dee Zsombor (zunda) -* a patch for thread_pthread.c - -Dan Zwell -* a patch for net/pop - - diff --git a/ruby/doc/csv/arguments/io.rdoc b/ruby/doc/csv/arguments/io.rdoc new file mode 100644 index 000000000..f5fe1d197 --- /dev/null +++ b/ruby/doc/csv/arguments/io.rdoc @@ -0,0 +1,5 @@ +* Argument +io+ should be an IO object that is: + * Open for reading; on return, the IO object will be closed. + * Positioned at the beginning. + To position at the end, for appending, use method CSV.generate. + For any other positioning, pass a preset \StringIO object instead. diff --git a/ruby/doc/csv/options/common/col_sep.rdoc b/ruby/doc/csv/options/common/col_sep.rdoc new file mode 100644 index 000000000..05769b577 --- /dev/null +++ b/ruby/doc/csv/options/common/col_sep.rdoc @@ -0,0 +1,63 @@ +====== Option +col_sep+ + +Specifies the \String field separator to be used +for both parsing and generating. +The \String will be transcoded into the data's \Encoding before use. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma) + +Using the default (comma): + str = CSV.generate do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0\nbar,1\nbaz,2\n" + ary = CSV.parse(str) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using +:+ (colon): + col_sep = ':' + str = CSV.generate(col_sep: col_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo:0\nbar:1\nbaz:2\n" + ary = CSV.parse(str, col_sep: col_sep) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using +::+ (two colons): + col_sep = '::' + str = CSV.generate(col_sep: col_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo::0\nbar::1\nbaz::2\n" + ary = CSV.parse(str, col_sep: col_sep) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using '' (empty string): + col_sep = '' + str = CSV.generate(col_sep: col_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo0\nbar1\nbaz2\n" + +--- + +Raises an exception if parsing with the empty \String: + col_sep = '' + # Raises ArgumentError (:col_sep must be 1 or more characters: "") + CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep) + +Raises an exception if the given value is not String-convertible: + col_sep = BasicObject.new + # Raises NoMethodError (undefined method `to_s' for #) + CSV.generate(line, col_sep: col_sep) + # Raises NoMethodError (undefined method `to_s' for #) + CSV.parse(str, col_sep: col_sep) diff --git a/ruby/doc/csv/options/common/quote_char.rdoc b/ruby/doc/csv/options/common/quote_char.rdoc new file mode 100644 index 000000000..67fd3af68 --- /dev/null +++ b/ruby/doc/csv/options/common/quote_char.rdoc @@ -0,0 +1,42 @@ +====== Option +quote_char+ + +Specifies the character (\String of length 1) used used to quote fields +in both parsing and generating. +This String will be transcoded into the data's \Encoding before use. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote) + +This is useful for an application that incorrectly uses ' (single-quote) +to quote fields, instead of the correct " (double-quote). + +Using the default (double quote): + str = CSV.generate do |csv| + csv << ['foo', 0] + csv << ["'bar'", 1] + csv << ['"baz"', 2] + end + str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n" + ary = CSV.parse(str) + ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] + +Using ' (single-quote): + quote_char = "'" + str = CSV.generate(quote_char: quote_char) do |csv| + csv << ['foo', 0] + csv << ["'bar'", 1] + csv << ['"baz"', 2] + end + str # => "foo,0\n'''bar''',1\n\"baz\",2\n" + ary = CSV.parse(str, quote_char: quote_char) + ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] + +--- + +Raises an exception if the \String length is greater than 1: + # Raises ArgumentError (:quote_char has to be nil or a single character String) + CSV.new('', quote_char: 'xx') + +Raises an exception if the value is not a \String: + # Raises ArgumentError (:quote_char has to be nil or a single character String) + CSV.new('', quote_char: :foo) diff --git a/ruby/doc/csv/options/common/row_sep.rdoc b/ruby/doc/csv/options/common/row_sep.rdoc new file mode 100644 index 000000000..872d9d1f3 --- /dev/null +++ b/ruby/doc/csv/options/common/row_sep.rdoc @@ -0,0 +1,100 @@ +====== Option +row_sep+ + +Specifies the row separator, a \String or the \Symbol :auto (see below), +to be used for both parsing and generating. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto + +--- + +When +row_sep+ is a \String, that \String becomes the row separator. +The String will be transcoded into the data's Encoding before use. + +Using "\n": + row_sep = "\n" + str = CSV.generate(row_sep: row_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0\nbar,1\nbaz,2\n" + ary = CSV.parse(str) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using | (pipe): + row_sep = '|' + str = CSV.generate(row_sep: row_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0|bar,1|baz,2|" + ary = CSV.parse(str, row_sep: row_sep) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using -- (two hyphens): + row_sep = '--' + str = CSV.generate(row_sep: row_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0--bar,1--baz,2--" + ary = CSV.parse(str, row_sep: row_sep) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using '' (empty string): + row_sep = '' + str = CSV.generate(row_sep: row_sep) do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0bar,1baz,2" + ary = CSV.parse(str, row_sep: row_sep) + ary # => [["foo", "0bar", "1baz", "2"]] + +--- + +When +row_sep+ is the \Symbol +:auto+ (the default), +generating uses "\n" as the row separator: + str = CSV.generate do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0\nbar,1\nbaz,2\n" + +Parsing, on the other hand, invokes auto-discovery of the row separator. + +Auto-discovery reads ahead in the data looking for the next \r\n, +\n+, or +\r+ sequence. +The sequence will be selected even if it occurs in a quoted field, +assuming that you would have the same line endings there. + +Example: + str = CSV.generate do |csv| + csv << [:foo, 0] + csv << [:bar, 1] + csv << [:baz, 2] + end + str # => "foo,0\nbar,1\nbaz,2\n" + ary = CSV.parse(str) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +The default $INPUT_RECORD_SEPARATOR ($/) is used +if any of the following is true: +* None of those sequences is found. +* Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+. +* The stream is only available for output. + +Obviously, discovery takes a little time. Set manually if speed is important. Also note that IO objects should be opened in binary mode on Windows if this feature will be used as the line-ending translation can cause problems with resetting the document position to where it was before the read ahead. + +--- + +Raises an exception if the given value is not String-convertible: + row_sep = BasicObject.new + # Raises NoMethodError (undefined method `to_s' for #) + CSV.generate(ary, row_sep: row_sep) + # Raises NoMethodError (undefined method `to_s' for #) + CSV.parse(str, row_sep: row_sep) diff --git a/ruby/doc/csv/options/generating/force_quotes.rdoc b/ruby/doc/csv/options/generating/force_quotes.rdoc new file mode 100644 index 000000000..11afd1a16 --- /dev/null +++ b/ruby/doc/csv/options/generating/force_quotes.rdoc @@ -0,0 +1,17 @@ +====== Option +force_quotes+ + +Specifies the boolean that determines whether each output field is to be double-quoted. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false + +For examples in this section: + ary = ['foo', 0, nil] + +Using the default, +false+: + str = CSV.generate_line(ary) + str # => "foo,0,\n" + +Using +true+: + str = CSV.generate_line(ary, force_quotes: true) + str # => "\"foo\",\"0\",\"\"\n" diff --git a/ruby/doc/csv/options/generating/quote_empty.rdoc b/ruby/doc/csv/options/generating/quote_empty.rdoc new file mode 100644 index 000000000..4c5645c66 --- /dev/null +++ b/ruby/doc/csv/options/generating/quote_empty.rdoc @@ -0,0 +1,12 @@ +====== Option +quote_empty+ + +Specifies the boolean that determines whether an empty value is to be double-quoted. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true + +With the default +true+: + CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n" + +With +false+: + CSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n" diff --git a/ruby/doc/csv/options/generating/write_converters.rdoc b/ruby/doc/csv/options/generating/write_converters.rdoc new file mode 100644 index 000000000..6e5fae5fd --- /dev/null +++ b/ruby/doc/csv/options/generating/write_converters.rdoc @@ -0,0 +1,33 @@ +====== Option +write_converters+ + +Specifies converters to be used in generating fields. +See {Write Converters}[#class-CSV-label-Write+Converters] + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil + +With no write converter: + str = CSV.generate_line(["\na\n", "\tb\t", " c "]) + str # => "\"\na\n\",\tb\t, c \n" + +With a write converter: + strip_converter = proc {|field| field.strip } + str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter) + str # => "a,b,c\n" + +With two write converters (called in order): + upcase_converter = proc {|field| field.upcase } + downcase_converter = proc {|field| field.downcase } + write_converters = [upcase_converter, downcase_converter] + str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters) + str # => "a,b,c\n" + +See also {Write Converters}[#class-CSV-label-Write+Converters] + +--- + +Raises an exception if the converter returns a value that is neither +nil+ +nor \String-convertible: + bad_converter = proc {|field| BasicObject.new } + # Raises NoMethodError (undefined method `is_a?' for #) + CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter) \ No newline at end of file diff --git a/ruby/doc/csv/options/generating/write_empty_value.rdoc b/ruby/doc/csv/options/generating/write_empty_value.rdoc new file mode 100644 index 000000000..67be5662c --- /dev/null +++ b/ruby/doc/csv/options/generating/write_empty_value.rdoc @@ -0,0 +1,15 @@ +====== Option +write_empty_value+ + +Specifies the object that is to be substituted for each field +that has an empty \String. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => "" + +Without the option: + str = CSV.generate_line(['a', '', 'c', '']) + str # => "a,\"\",c,\"\"\n" + +With the option: + str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x") + str # => "a,x,c,x\n" diff --git a/ruby/doc/csv/options/generating/write_headers.rdoc b/ruby/doc/csv/options/generating/write_headers.rdoc new file mode 100644 index 000000000..f9faa9d43 --- /dev/null +++ b/ruby/doc/csv/options/generating/write_headers.rdoc @@ -0,0 +1,29 @@ +====== Option +write_headers+ + +Specifies the boolean that determines whether a header row is included in the output; +ignored if there are no headers. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil + +Without +write_headers+: + file_path = 't.csv' + CSV.open(file_path,'w', + :headers => ['Name','Value'] + ) do |csv| + csv << ['foo', '0'] + end + CSV.open(file_path) do |csv| + csv.shift + end # => ["foo", "0"] + +With +write_headers+": + CSV.open(file_path,'w', + :write_headers=> true, + :headers => ['Name','Value'] + ) do |csv| + csv << ['foo', '0'] + end + CSV.open(file_path) do |csv| + csv.shift + end # => ["Name", "Value"] diff --git a/ruby/doc/csv/options/generating/write_nil_value.rdoc b/ruby/doc/csv/options/generating/write_nil_value.rdoc new file mode 100644 index 000000000..65d33ff54 --- /dev/null +++ b/ruby/doc/csv/options/generating/write_nil_value.rdoc @@ -0,0 +1,14 @@ +====== Option +write_nil_value+ + +Specifies the object that is to be substituted for each +nil+-valued field. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil + +Without the option: + str = CSV.generate_line(['a', nil, 'c', nil]) + str # => "a,,c,\n" + +With the option: + str = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x") + str # => "a,x,c,x\n" diff --git a/ruby/doc/csv/options/parsing/converters.rdoc b/ruby/doc/csv/options/parsing/converters.rdoc new file mode 100644 index 000000000..211fa48de --- /dev/null +++ b/ruby/doc/csv/options/parsing/converters.rdoc @@ -0,0 +1,46 @@ +====== Option +converters+ + +Specifies converters to be used in parsing fields. +See {Field Converters}[#class-CSV-label-Field+Converters] + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil + +The value may be a field converter name +(see {Stored Converters}[#class-CSV-label-Stored+Converters]): + str = '1,2,3' + # Without a converter + array = CSV.parse_line(str) + array # => ["1", "2", "3"] + # With built-in converter :integer + array = CSV.parse_line(str, converters: :integer) + array # => [1, 2, 3] + +The value may be a converter list +(see {Converter Lists}[#class-CSV-label-Converter+Lists]): + str = '1,3.14159' + # Without converters + array = CSV.parse_line(str) + array # => ["1", "3.14159"] + # With built-in converters + array = CSV.parse_line(str, converters: [:integer, :float]) + array # => [1, 3.14159] + +The value may be a \Proc custom converter: +(see {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]): + str = ' foo , bar , baz ' + # Without a converter + array = CSV.parse_line(str) + array # => [" foo ", " bar ", " baz "] + # With a custom converter + array = CSV.parse_line(str, converters: proc {|field| field.strip }) + array # => ["foo", "bar", "baz"] + +See also {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters] + +--- + +Raises an exception if the converter is not a converter name or a \Proc: + str = 'foo,0' + # Raises NoMethodError (undefined method `arity' for nil:NilClass) + CSV.parse(str, converters: :foo) diff --git a/ruby/doc/csv/options/parsing/empty_value.rdoc b/ruby/doc/csv/options/parsing/empty_value.rdoc new file mode 100644 index 000000000..7d3bcc078 --- /dev/null +++ b/ruby/doc/csv/options/parsing/empty_value.rdoc @@ -0,0 +1,13 @@ +====== Option +empty_value+ + +Specifies the object that is to be substituted +for each field that has an empty \String. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string) + +With the default, "": + CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"] + +With a different object: + CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"] diff --git a/ruby/doc/csv/options/parsing/field_size_limit.rdoc b/ruby/doc/csv/options/parsing/field_size_limit.rdoc new file mode 100644 index 000000000..797c5776f --- /dev/null +++ b/ruby/doc/csv/options/parsing/field_size_limit.rdoc @@ -0,0 +1,39 @@ +====== Option +field_size_limit+ + +Specifies the \Integer field size limit. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil + +This is a maximum size CSV will read ahead looking for the closing quote for a field. +(In truth, it reads to the first line ending beyond this size.) +If a quote cannot be found within the limit CSV will raise a MalformedCSVError, +assuming the data is faulty. +You can use this limit to prevent what are effectively DoS attacks on the parser. +However, this limit can cause a legitimate parse to fail; +therefore the default value is +nil+ (no limit). + +For the examples in this section: + str = <<~EOT + "a","b" + " + 2345 + ","" + EOT + str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n" + +Using the default +nil+: + ary = CSV.parse(str) + ary # => [["a", "b"], ["\n2345\n", ""]] + +Using 50: + field_size_limit = 50 + ary = CSV.parse(str, field_size_limit: field_size_limit) + ary # => [["a", "b"], ["\n2345\n", ""]] + +--- + +Raises an exception if a field is too long: + big_str = "123456789\n" * 1024 + # Raises CSV::MalformedCSVError (Field size exceeded in line 1.) + CSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048) diff --git a/ruby/doc/csv/options/parsing/header_converters.rdoc b/ruby/doc/csv/options/parsing/header_converters.rdoc new file mode 100644 index 000000000..309180805 --- /dev/null +++ b/ruby/doc/csv/options/parsing/header_converters.rdoc @@ -0,0 +1,43 @@ +====== Option +header_converters+ + +Specifies converters to be used in parsing headers. +See {Header Converters}[#class-CSV-label-Header+Converters] + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil + +Identical in functionality to option {converters}[#class-CSV-label-Option+converters] +except that: +- The converters apply only to the header row. +- The built-in header converters are +:downcase+ and +:symbol+. + +This section assumes prior execution of: + str = <<-EOT + Name,Value + foo,0 + bar,1 + baz,2 + EOT + # With no header converter + table = CSV.parse(str, headers: true) + table.headers # => ["Name", "Value"] + +The value may be a header converter name +(see {Stored Converters}[#class-CSV-label-Stored+Converters]): + table = CSV.parse(str, headers: true, header_converters: :downcase) + table.headers # => ["name", "value"] + +The value may be a converter list +(see {Converter Lists}[#class-CSV-label-Converter+Lists]): + header_converters = [:downcase, :symbol] + table = CSV.parse(str, headers: true, header_converters: header_converters) + table.headers # => [:name, :value] + +The value may be a \Proc custom converter +(see {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]): + upcase_converter = proc {|field| field.upcase } + table = CSV.parse(str, headers: true, header_converters: upcase_converter) + table.headers # => ["NAME", "VALUE"] + +See also {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters] + diff --git a/ruby/doc/csv/options/parsing/headers.rdoc b/ruby/doc/csv/options/parsing/headers.rdoc new file mode 100644 index 000000000..0ea151f24 --- /dev/null +++ b/ruby/doc/csv/options/parsing/headers.rdoc @@ -0,0 +1,63 @@ +====== Option +headers+ + +Specifies a boolean, \Symbol, \Array, or \String to be used +to define column headers. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:headers) # => false + +--- + +Without +headers+: + str = <<-EOT + Name,Count + foo,0 + bar,1 + bax,2 + EOT + csv = CSV.new(str) + csv # => # + csv.headers # => nil + csv.shift # => ["Name", "Count"] + +--- + +If set to +true+ or the \Symbol +:first_row+, +the first row of the data is treated as a row of headers: + str = <<-EOT + Name,Count + foo,0 + bar,1 + bax,2 + EOT + csv = CSV.new(str, headers: true) + csv # => # + csv.headers # => ["Name", "Count"] + csv.shift # => # + +--- + +If set to an \Array, the \Array elements are treated as headers: + str = <<-EOT + foo,0 + bar,1 + bax,2 + EOT + csv = CSV.new(str, headers: ['Name', 'Count']) + csv + csv.headers # => ["Name", "Count"] + csv.shift # => # + +--- + +If set to a \String +str+, method CSV::parse_line(str, options) is called +with the current +options+, and the returned \Array is treated as headers: + str = <<-EOT + foo,0 + bar,1 + bax,2 + EOT + csv = CSV.new(str, headers: 'Name,Count') + csv + csv.headers # => ["Name", "Count"] + csv.shift # => # diff --git a/ruby/doc/csv/options/parsing/liberal_parsing.rdoc b/ruby/doc/csv/options/parsing/liberal_parsing.rdoc new file mode 100644 index 000000000..b8b9b00c9 --- /dev/null +++ b/ruby/doc/csv/options/parsing/liberal_parsing.rdoc @@ -0,0 +1,19 @@ +====== Option +liberal_parsing+ + +Specifies the boolean value that determines whether +CSV will attempt to parse input not conformant with RFC 4180, +such as double quotes in unquoted fields. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false + +For examples in this section: + str = 'is,this "three, or four",fields' + +Without +liberal_parsing+: + # Raises CSV::MalformedCSVError (Illegal quoting in str 1.) + CSV.parse_line(str) + +With +liberal_parsing+: + ary = CSV.parse_line(str, liberal_parsing: true) + ary # => ["is", "this \"three", " or four\"", "fields"] diff --git a/ruby/doc/csv/options/parsing/nil_value.rdoc b/ruby/doc/csv/options/parsing/nil_value.rdoc new file mode 100644 index 000000000..412e8795e --- /dev/null +++ b/ruby/doc/csv/options/parsing/nil_value.rdoc @@ -0,0 +1,12 @@ +====== Option +nil_value+ + +Specifies the object that is to be substituted for each null (no-text) field. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil + +With the default, +nil+: + CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"] + +With a different object: + CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"] diff --git a/ruby/doc/csv/options/parsing/return_headers.rdoc b/ruby/doc/csv/options/parsing/return_headers.rdoc new file mode 100644 index 000000000..45d2e3f3d --- /dev/null +++ b/ruby/doc/csv/options/parsing/return_headers.rdoc @@ -0,0 +1,22 @@ +====== Option +return_headers+ + +Specifies the boolean that determines whether method #shift +returns or ignores the header row. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false + +Examples: + str = <<-EOT + Name,Count + foo,0 + bar,1 + bax,2 + EOT + # Without return_headers first row is str. + csv = CSV.new(str, headers: true) + csv.shift # => # + # With return_headers first row is headers. + csv = CSV.new(str, headers: true, return_headers: true) + csv.shift # => # + diff --git a/ruby/doc/csv/options/parsing/skip_blanks.rdoc b/ruby/doc/csv/options/parsing/skip_blanks.rdoc new file mode 100644 index 000000000..2c8f7b7bb --- /dev/null +++ b/ruby/doc/csv/options/parsing/skip_blanks.rdoc @@ -0,0 +1,31 @@ +====== Option +skip_blanks+ + +Specifies a boolean that determines whether blank lines in the input will be ignored; +a line that contains a column separator is not considered to be blank. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false + +See also option {skiplines}[#class-CSV-label-Option+skip_lines]. + +For examples in this section: + str = <<-EOT + foo,0 + + bar,1 + baz,2 + + , + EOT + +Using the default, +false+: + ary = CSV.parse(str) + ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]] + +Using +true+: + ary = CSV.parse(str, skip_blanks: true) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] + +Using a truthy value: + ary = CSV.parse(str, skip_blanks: :foo) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] diff --git a/ruby/doc/csv/options/parsing/skip_lines.rdoc b/ruby/doc/csv/options/parsing/skip_lines.rdoc new file mode 100644 index 000000000..1481c40a5 --- /dev/null +++ b/ruby/doc/csv/options/parsing/skip_lines.rdoc @@ -0,0 +1,37 @@ +====== Option +skip_lines+ + +Specifies an object to use in identifying comment lines in the input that are to be ignored: +* If a \Regexp, ignores lines that match it. +* If a \String, converts it to a \Regexp, ignores lines that match it. +* If +nil+, no lines are considered to be comments. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil + +For examples in this section: + str = <<-EOT + # Comment + foo,0 + bar,1 + baz,2 + # Another comment + EOT + str # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n" + +Using the default, +nil+: + ary = CSV.parse(str) + ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]] + +Using a \Regexp: + ary = CSV.parse(str, skip_lines: /^#/) + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Using a \String: + ary = CSV.parse(str, skip_lines: '#') + ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +--- + +Raises an exception if given an object that is not a \Regexp, a \String, or +nil+: + # Raises ArgumentError (:skip_lines has to respond to #match: 0) + CSV.parse(str, skip_lines: 0) diff --git a/ruby/doc/csv/options/parsing/strip.rdoc b/ruby/doc/csv/options/parsing/strip.rdoc new file mode 100644 index 000000000..56ae4310c --- /dev/null +++ b/ruby/doc/csv/options/parsing/strip.rdoc @@ -0,0 +1,15 @@ +====== Option +strip+ + +Specifies the boolean value that determines whether +whitespace is stripped from each input field. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:strip) # => false + +With default value +false+: + ary = CSV.parse_line(' a , b ') + ary # => [" a ", " b "] + +With value +true+: + ary = CSV.parse_line(' a , b ', strip: true) + ary # => ["a", "b"] diff --git a/ruby/doc/csv/options/parsing/unconverted_fields.rdoc b/ruby/doc/csv/options/parsing/unconverted_fields.rdoc new file mode 100644 index 000000000..3e7f839d4 --- /dev/null +++ b/ruby/doc/csv/options/parsing/unconverted_fields.rdoc @@ -0,0 +1,27 @@ +====== Option +unconverted_fields+ + +Specifies the boolean that determines whether unconverted field values are to be available. + +Default value: + CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil + +The unconverted field values are those found in the source data, +prior to any conversions performed via option +converters+. + +When option +unconverted_fields+ is +true+, +each returned row (\Array or \CSV::Row) has an added method, ++unconverted_fields+, that returns the unconverted field values: + str = <<-EOT + foo,0 + bar,1 + baz,2 + EOT + # Without unconverted_fields + csv = CSV.parse(str, converters: :integer) + csv # => [["foo", 0], ["bar", 1], ["baz", 2]] + csv.first.respond_to?(:unconverted_fields) # => false + # With unconverted_fields + csv = CSV.parse(str, converters: :integer, unconverted_fields: true) + csv # => [["foo", 0], ["bar", 1], ["baz", 2]] + csv.first.respond_to?(:unconverted_fields) # => true + csv.first.unconverted_fields # => ["foo", "0"] diff --git a/ruby/doc/csv/recipes/filtering.rdoc b/ruby/doc/csv/recipes/filtering.rdoc new file mode 100644 index 000000000..470649d09 --- /dev/null +++ b/ruby/doc/csv/recipes/filtering.rdoc @@ -0,0 +1,156 @@ +== Recipes for Filtering \CSV + +For other recipes, see {Recipes for CSV}[./recipes_rdoc.html]. + +All code snippets on this page assume that the following has been executed: + require 'csv' + +=== Contents + +- {Source and Output Formats}[#label-Source+and+Output+Formats] + - {Filtering String to String}[#label-Filtering+String+to+String] + - {Recipe: Filter String to String with Headers}[#label-Recipe-3A+Filter+String+to+String+with+Headers] + - {Recipe: Filter String to String Without Headers}[#label-Recipe-3A+Filter+String+to+String+Without+Headers] + - {Filtering String to IO Stream}[#label-Filtering+String+to+IO+Stream] + - {Recipe: Filter String to IO Stream with Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+with+Headers] + - {Recipe: Filter String to IO Stream Without Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+Without+Headers] + - {Filtering IO Stream to String}[#label-Filtering+IO+Stream+to+String] + - {Recipe: Filter IO Stream to String with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+with+Headers] + - {Recipe: Filter IO Stream to String Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+Without+Headers] + - {Filtering IO Stream to IO Stream}[#label-Filtering+IO+Stream+to+IO+Stream] + - {Recipe: Filter IO Stream to IO Stream with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+with+Headers] + - {Recipe: Filter IO Stream to IO Stream Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+Without+Headers] + +=== Source and Output Formats + +You can use a Unix-style "filter" for \CSV data. +The filter reads source \CSV data and writes output \CSV data as modified by the filter. +The input and output \CSV data may be any mixture of \Strings and \IO streams. + +==== Filtering \String to \String + +You can filter one \String to another, with or without headers. + +===== Recipe: Filter \String to \String with Headers + +Use class method CSV.filter with option +headers+ to filter a \String to another \String: + in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + out_string = '' + CSV.filter(in_string, out_string, headers: true) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" + +===== Recipe: Filter \String to \String Without Headers + +Use class method CSV.filter without option +headers+ to filter a \String to another \String: + 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" + +==== Filtering \String to \IO Stream + +You can filter a \String to an \IO stream, with or without headers. + +===== Recipe: Filter \String to \IO Stream with Headers + +Use class method CSV.filter with option +headers+ to filter a \String to an \IO stream: + in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.open(path, 'w') do |out_io| + CSV.filter(in_string, out_io, headers: true) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + p File.read(path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" + +===== Recipe: Filter \String to \IO Stream Without Headers + +Use class method CSV.filter without option +headers+ to filter a \String to an \IO stream: + in_string = "foo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.open(path, 'w') do |out_io| + CSV.filter(in_string, out_io) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + p File.read(path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n" + +==== Filtering \IO Stream to \String + +You can filter an \IO stream to a \String, with or without headers. + +===== Recipe: Filter \IO Stream to \String with Headers + +Use class method CSV.filter with option +headers+ to filter an \IO stream to a \String: + in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, in_string) + out_string = '' + File.open(path, headers: true) do |in_io| + CSV.filter(in_io, out_string, headers: true) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" + +===== Recipe: Filter \IO Stream to \String Without Headers + +Use class method CSV.filter without option +headers+ to filter an \IO stream to a \String: + in_string = "foo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, in_string) + out_string = '' + File.open(path) do |in_io| + CSV.filter(in_io, out_string) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" + +==== Filtering \IO Stream to \IO Stream + +You can filter an \IO stream to another \IO stream, with or without headers. + +===== Recipe: Filter \IO Stream to \IO Stream with Headers + +Use class method CSV.filter with option +headers+ to filter an \IO stream to another \IO stream: + in_path = 't.csv' + in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + File.write(in_path, in_string) + out_path = 'u.csv' + File.open(in_path) do |in_io| + File.open(out_path, 'w') do |out_io| + CSV.filter(in_io, out_io, headers: true) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + end + p File.read(out_path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" + +===== Recipe: Filter \IO Stream to \IO Stream Without Headers + +Use class method CSV.filter without option +headers+ to filter an \IO stream to another \IO stream: + in_path = 't.csv' + in_string = "foo,0\nbar,1\nbaz,2\n" + File.write(in_path, in_string) + out_path = 'u.csv' + File.open(in_path) do |in_io| + File.open(out_path, 'w') do |out_io| + CSV.filter(in_io, out_io) do |row| + row[0] = row[0].upcase + row[1] *= 4 + end + end + end + p File.read(out_path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n" diff --git a/ruby/doc/csv/recipes/generating.rdoc b/ruby/doc/csv/recipes/generating.rdoc new file mode 100644 index 000000000..3ef6df99b --- /dev/null +++ b/ruby/doc/csv/recipes/generating.rdoc @@ -0,0 +1,244 @@ +== Recipes for Generating \CSV + +For other recipes, see {Recipes for CSV}[./recipes_rdoc.html]. + +All code snippets on this page assume that the following has been executed: + require 'csv' + +=== Contents + +- {Output Formats}[#label-Output+Formats] + - {Generating to a String}[#label-Generating+to+a+String] + - {Recipe: Generate to String with Headers}[#label-Recipe-3A+Generate+to+String+with+Headers] + - {Recipe: Generate to String Without Headers}[#label-Recipe-3A+Generate+to+String+Without+Headers] + - {Generating to a File}[#label-Generating+to+a+File] + - {Recipe: Generate to File with Headers}[#label-Recipe-3A+Generate+to+File+with+Headers] + - {Recipe: Generate to File Without Headers}[#label-Recipe-3A+Generate+to+File+Without+Headers] + - {Generating to IO an Stream}[#label-Generating+to+an+IO+Stream] + - {Recipe: Generate to IO Stream with Headers}[#label-Recipe-3A+Generate+to+IO+Stream+with+Headers] + - {Recipe: Generate to IO Stream Without Headers}[#label-Recipe-3A+Generate+to+IO+Stream+Without+Headers] +- {Converting Fields}[#label-Converting+Fields] + - {Recipe: Filter Generated Field Strings}[#label-Recipe-3A+Filter+Generated+Field+Strings] + - {Recipe: Specify Multiple Write Converters}[#label-Recipe-3A+Specify+Multiple+Write+Converters] +- {RFC 4180 Compliance}[#label-RFC+4180+Compliance] + - {Row Separator}[#label-Row+Separator] + - {Recipe: Generate Compliant Row Separator}[#label-Recipe-3A+Generate+Compliant+Row+Separator] + - {Recipe: Generate Non-Compliant Row Separator}[#label-Recipe-3A+Generate+Non-Compliant+Row+Separator] + - {Column Separator}[#label-Column+Separator] + - {Recipe: Generate Compliant Column Separator}[#label-Recipe-3A+Generate+Compliant+Column+Separator] + - {Recipe: Generate Non-Compliant Column Separator}[#label-Recipe-3A+Generate+Non-Compliant+Column+Separator] + - {Quote Character}[#label-Quote+Character] + - {Recipe: Generate Compliant Quote Character}[#label-Recipe-3A+Generate+Compliant+Quote+Character] + - {Recipe: Generate Non-Compliant Quote Character}[#label-Recipe-3A+Generate+Non-Compliant+Quote+Character] + +=== Output Formats + +You can generate \CSV output to a \String, to a \File (via its path), or to an \IO stream. + +==== Generating to a \String + +You can generate \CSV output to a \String, with or without headers. + +===== Recipe: Generate to \String with Headers + +Use class method CSV.generate with option +headers+ to generate to a \String. + +This example uses method CSV#<< to append the rows +that are to be generated: + output_string = CSV.generate('', headers: ['Name', 'Value'], write_headers: true) do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n" + +===== Recipe: Generate to \String Without Headers + +Use class method CSV.generate without option +headers+ to generate to 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" + +==== Generating to a \File + +You can generate /CSV data to a \File, with or without headers. + +===== Recipe: Generate to \File with Headers + +Use class method CSV.open with option +headers+ generate to a \File. + +This example uses method CSV#<< to append the rows +that are to be generated: + path = 't.csv' + CSV.open(path, 'w', headers: ['Name', 'Value'], write_headers: true) do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n" + +===== Recipe: Generate to \File Without Headers + +Use class method CSV.open without option +headers+ to generate to a \File. + +This example uses method CSV#<< to append the rows +that are to be generated: + path = 't.csv' + CSV.open(path, 'w') do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n" + +==== Generating to an \IO Stream + +You can generate \CSV data to an \IO stream, with or without headers. + +==== Recipe: Generate to \IO Stream with Headers + +Use class method CSV.new with option +headers+ to generate \CSV data to an \IO stream: + path = 't.csv' + File.open(path, 'w') do |file| + csv = CSV.new(file, headers: ['Name', 'Value'], write_headers: true) + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n" + +===== Recipe: Generate to \IO Stream Without Headers + +Use class method CSV.new without option +headers+ to generate \CSV data to an \IO stream: + path = 't.csv' + File.open(path, 'w') do |file| + csv = CSV.new(file) + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n" + +=== Converting Fields + +You can use _write_ _converters_ to convert fields when generating \CSV. + +==== Recipe: Filter Generated Field Strings + +Use option :write_converters and a custom converter to convert field values when generating \CSV. + +This example defines and uses a custom write converter to strip whitespace from generated fields: + strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } + output_string = CSV.generate(write_converters: strip_converter) do |csv| + csv << [' foo ', 0] + csv << [' bar ', 1] + csv << [' baz ', 2] + end + output_string # => "foo,0\nbar,1\nbaz,2\n" + +==== Recipe: Specify Multiple Write Converters + +Use option :write_converters and multiple custom coverters +to convert field values when generating \CSV. + +This example defines and uses two custom write converters to strip and upcase generated fields: + strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } + upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } + converters = [strip_converter, upcase_converter] + output_string = CSV.generate(write_converters: converters) do |csv| + csv << [' foo ', 0] + csv << [' bar ', 1] + csv << [' baz ', 2] + end + output_string # => "FOO,0\nBAR,1\nBAZ,2\n" + +=== RFC 4180 Compliance + +By default, \CSV generates data that is compliant with +{RFC 4180}[https://tools.ietf.org/html/rfc4180] +with respect to: +- Column separator. +- Quote character. + +==== Row Separator + +RFC 4180 specifies the row separator CRLF (Ruby "\r\n"). + +===== Recipe: Generate Compliant Row Separator + +For strict compliance, use option +:row_sep+ to specify row separator "\r\n": + output_string = CSV.generate('', row_sep: "\r\n") do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "Foo,0\r\nBar,1\r\nBaz,2\r\n" + +===== Recipe: Generate Non-Compliant Row Separator + +For data with non-compliant row separators, use option +:row_sep+ with a different value: +This example source uses semicolon (";') as its row separator: + output_string = CSV.generate('', row_sep: ";") do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "Foo,0;Bar,1;Baz,2;" + +==== Column Separator + +RFC 4180 specifies column separator COMMA (Ruby ","). + +===== Recipe: Generate Compliant Column Separator + +Because the \CSV default comma separator is ",", +you need not specify option +:col_sep+ for compliant data: + 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" + +===== Recipe: Generate Non-Compliant Column Separator + +For data with non-compliant column separators, use option +:col_sep+. +This example source uses TAB ("\t") as its column separator: + output_string = CSV.generate('', col_sep: "\t") do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "Foo\t0\nBar\t1\nBaz\t2\n" + +==== Quote Character + +RFC 4180 specifies quote character DQUOTE (Ruby "\""). + +===== Recipe: Generate Compliant Quote Character + +Because the \CSV default quote character is "\"", +you need not specify option +:quote_char+ for compliant data: + output_string = CSV.generate('', force_quotes: true) do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "\"Foo\",\"0\"\n\"Bar\",\"1\"\n\"Baz\",\"2\"\n" + +===== Recipe: Generate Non-Compliant Quote Character + +For data with non-compliant quote characters, use option +:quote_char+. +This example source uses SQUOTE ("'") as its quote character: + output_string = CSV.generate('', quote_char: "'", force_quotes: true) do |csv| + csv << ['Foo', 0] + csv << ['Bar', 1] + csv << ['Baz', 2] + end + output_string # => "'Foo','0'\n'Bar','1'\n'Baz','2'\n" diff --git a/ruby/doc/csv/recipes/parsing.rdoc b/ruby/doc/csv/recipes/parsing.rdoc new file mode 100644 index 000000000..7ac96a934 --- /dev/null +++ b/ruby/doc/csv/recipes/parsing.rdoc @@ -0,0 +1,543 @@ +== Recipes for Parsing \CSV + +For other recipes, see {Recipes for CSV}[./recipes_rdoc.html]. + +All code snippets on this page assume that the following has been executed: + require 'csv' + +=== Contents + +- {Source Formats}[#label-Source+Formats] + - {Parsing from a String}[#label-Parsing+from+a+String] + - {Recipe: Parse from String with Headers}[#label-Recipe-3A+Parse+from+String+with+Headers] + - {Recipe: Parse from String Without Headers}[#label-Recipe-3A+Parse+from+String+Without+Headers] + - {Parsing from a File}[#label-Parsing+from+a+File] + - {Recipe: Parse from File with Headers}[#label-Recipe-3A+Parse+from+File+with+Headers] + - {Recipe: Parse from File Without Headers}[#label-Recipe-3A+Parse+from+File+Without+Headers] + - {Parsing from an IO Stream}[#label-Parsing+from+an+IO+Stream] + - {Recipe: Parse from IO Stream with Headers}[#label-Recipe-3A+Parse+from+IO+Stream+with+Headers] + - {Recipe: Parse from IO Stream Without Headers}[#label-Recipe-3A+Parse+from+IO+Stream+Without+Headers] +- {RFC 4180 Compliance}[#label-RFC+4180+Compliance] + - {Row Separator}[#label-Row+Separator] + - {Recipe: Handle Compliant Row Separator}[#label-Recipe-3A+Handle+Compliant+Row+Separator] + - {Recipe: Handle Non-Compliant Row Separator}[#label-Recipe-3A+Handle+Non-Compliant+Row+Separator] + - {Column Separator}[#label-Column+Separator] + - {Recipe: Handle Compliant Column Separator}[#label-Recipe-3A+Handle+Compliant+Column+Separator] + - {Recipe: Handle Non-Compliant Column Separator}[#label-Recipe-3A+Handle+Non-Compliant+Column+Separator] + - {Quote Character}[#label-Quote+Character] + - {Recipe: Handle Compliant Quote Character}[#label-Recipe-3A+Handle+Compliant+Quote+Character] + - {Recipe: Handle Non-Compliant Quote Character}[#label-Recipe-3A+Handle+Non-Compliant+Quote+Character] + - {Recipe: Allow Liberal Parsing}[#label-Recipe-3A+Allow+Liberal+Parsing] +- {Special Handling}[#label-Special+Handling] + - {Special Line Handling}[#label-Special+Line+Handling] + - {Recipe: Ignore Blank Lines}[#label-Recipe-3A+Ignore+Blank+Lines] + - {Recipe: Ignore Selected Lines}[#label-Recipe-3A+Ignore+Selected+Lines] + - {Special Field Handling}[#label-Special+Field+Handling] + - {Recipe: Strip Fields}[#label-Recipe-3A+Strip+Fields] + - {Recipe: Handle Null Fields}[#label-Recipe-3A+Handle+Null+Fields] + - {Recipe: Handle Empty Fields}[#label-Recipe-3A+Handle+Empty+Fields] +- {Converting Fields}[#label-Converting+Fields] + - {Converting Fields to Objects}[#label-Converting+Fields+to+Objects] + - {Recipe: Convert Fields to Integers}[#label-Recipe-3A+Convert+Fields+to+Integers] + - {Recipe: Convert Fields to Floats}[#label-Recipe-3A+Convert+Fields+to+Floats] + - {Recipe: Convert Fields to Numerics}[#label-Recipe-3A+Convert+Fields+to+Numerics] + - {Recipe: Convert Fields to Dates}[#label-Recipe-3A+Convert+Fields+to+Dates] + - {Recipe: Convert Fields to DateTimes}[#label-Recipe-3A+Convert+Fields+to+DateTimes] + - {Recipe: Convert Assorted Fields to Objects}[#label-Recipe-3A+Convert+Assorted+Fields+to+Objects] + - {Recipe: Convert Fields to Other Objects}[#label-Recipe-3A+Convert+Fields+to+Other+Objects] + - {Recipe: Filter Field Strings}[#label-Recipe-3A+Filter+Field+Strings] + - {Recipe: Register Field Converters}[#label-Recipe-3A+Register+Field+Converters] + - {Using Multiple Field Converters}[#label-Using+Multiple+Field+Converters] + - {Recipe: Specify Multiple Field Converters in Option :converters}[#label-Recipe-3A+Specify+Multiple+Field+Converters+in+Option+-3Aconverters] + - {Recipe: Specify Multiple Field Converters in a Custom Converter List}[#label-Recipe-3A+Specify+Multiple+Field+Converters+in+a+Custom+Converter+List] +- {Converting Headers}[#label-Converting+Headers] + - {Recipe: Convert Headers to Lowercase}[#label-Recipe-3A+Convert+Headers+to+Lowercase] + - {Recipe: Convert Headers to Symbols}[#label-Recipe-3A+Convert+Headers+to+Symbols] + - {Recipe: Filter Header Strings}[#label-Recipe-3A+Filter+Header+Strings] + - {Recipe: Register Header Converters}[#label-Recipe-3A+Register+Header+Converters] + - {Using Multiple Header Converters}[#label-Using+Multiple+Header+Converters] + - {Recipe: Specify Multiple Header Converters in Option :header_converters}[#label-Recipe-3A+Specify+Multiple+Header+Converters+in+Option+-3Aheader_converters] + - {Recipe: Specify Multiple Header Converters in a Custom Header Converter List}[#label-Recipe-3A+Specify+Multiple+Header+Converters+in+a+Custom+Header+Converter+List] +- {Diagnostics}[#label-Diagnostics] + - {Recipe: Capture Unconverted Fields}[#label-Recipe-3A+Capture+Unconverted+Fields] + - {Recipe: Capture Field Info}[#label-Recipe-3A+Capture+Field+Info] + +=== Source Formats + +You can parse \CSV data from a \String, from a \File (via its path), or from an \IO stream. + +==== Parsing from a \String + +You can parse \CSV data from a \String, with or without headers. + +===== Recipe: Parse from \String with Headers + +Use class method CSV.parse with option +headers+ to read a source \String all at once +(may have memory resource implications): + string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + CSV.parse(string, headers: true) # => # + +Use instance method CSV#each with option +headers+ to read a source \String one row at a time: + CSV.new(string, headers: true).each do |row| + p row + end +Output: + # + # + # + +===== Recipe: Parse from \String Without Headers + +Use class method CSV.parse without option +headers+ to read a source \String all at once +(may have memory resource implications): + string = "foo,0\nbar,1\nbaz,2\n" + CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Use instance method CSV#each without option +headers+ to read a source \String one row at a time: + CSV.new(string).each do |row| + p row + end +Output: + ["foo", "0"] + ["bar", "1"] + ["baz", "2"] + +==== Parsing from a \File + +You can parse \CSV data from a \File, with or without headers. + +===== Recipe: Parse from \File with Headers + +Use instance method CSV#read with option +headers+ to read a file all at once: + string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, string) + CSV.read(path, headers: true) # => # + +Use class method CSV.foreach with option +headers+ to read one row at a time: + CSV.foreach(path, headers: true) do |row| + p row + end +Output: + # + # + # + +===== Recipe: Parse from \File Without Headers + +Use class method CSV.read without option +headers+ to read a file all at once: + string = "foo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, string) + CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Use class method CSV.foreach without option +headers+ to read one row at a time: + CSV.foreach(path) do |row| + p row + end +Output: + ["foo", "0"] + ["bar", "1"] + ["baz", "2"] + +==== Parsing from an \IO Stream + +You can parse \CSV data from an \IO stream, with or without headers. + +===== Recipe: Parse from \IO Stream with Headers + +Use class method CSV.parse with option +headers+ to read an \IO stream all at once: + string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, string) + File.open(path) do |file| + CSV.parse(file, headers: true) + end # => # + +Use class method CSV.foreach with option +headers+ to read one row at a time: + File.open(path) do |file| + CSV.foreach(file, headers: true) do |row| + p row + end + end +Output: + # + # + # + +===== Recipe: Parse from \IO Stream Without Headers + +Use class method CSV.parse without option +headers+ to read an \IO stream all at once: + string = "foo,0\nbar,1\nbaz,2\n" + path = 't.csv' + File.write(path, string) + File.open(path) do |file| + CSV.parse(file) + end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +Use class method CSV.foreach without option +headers+ to read one row at a time: + File.open(path) do |file| + CSV.foreach(file) do |row| + p row + end + end +Output: + ["foo", "0"] + ["bar", "1"] + ["baz", "2"] + +=== RFC 4180 Compliance + +By default, \CSV parses data that is compliant with +{RFC 4180}[https://tools.ietf.org/html/rfc4180] +with respect to: +- Row separator. +- Column separator. +- Quote character. + +==== Row Separator + +RFC 4180 specifies the row separator CRLF (Ruby "\r\n"). + +Although the \CSV default row separator is "\n", +the parser also by default handles row separator "\r" and the RFC-compliant "\r\n". + +===== Recipe: Handle Compliant Row Separator + +For strict compliance, use option +:row_sep+ to specify row separator "\r\n", +which allows the compliant row separator: + source = "foo,1\r\nbar,1\r\nbaz,2\r\n" + CSV.parse(source, row_sep: "\r\n") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] +But rejects other row separators: + source = "foo,1\nbar,1\nbaz,2\n" + CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError + source = "foo,1\rbar,1\rbaz,2\r" + CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError + source = "foo,1\n\rbar,1\n\rbaz,2\n\r" + CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError + +===== Recipe: Handle Non-Compliant Row Separator + +For data with non-compliant row separators, use option +:row_sep+. +This example source uses semicolon (";") as its row separator: + source = "foo,1;bar,1;baz,2;" + CSV.parse(source, row_sep: ';') # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] + +==== Column Separator + +RFC 4180 specifies column separator COMMA (Ruby ","). + +===== Recipe: Handle Compliant Column Separator + +Because the \CSV default comma separator is ',', +you need not specify option +:col_sep+ for compliant data: + source = "foo,1\nbar,1\nbaz,2\n" + CSV.parse(source) # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] + +===== Recipe: Handle Non-Compliant Column Separator + +For data with non-compliant column separators, use option +:col_sep+. +This example source uses TAB ("\t") as its column separator: + source = "foo,1\tbar,1\tbaz,2" + CSV.parse(source, col_sep: "\t") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] + +==== Quote Character + +RFC 4180 specifies quote character DQUOTE (Ruby "\""). + +===== Recipe: Handle Compliant Quote Character + +Because the \CSV default quote character is "\"", +you need not specify option +:quote_char+ for compliant data: + source = "\"foo\",\"1\"\n\"bar\",\"1\"\n\"baz\",\"2\"\n" + CSV.parse(source) # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] + +===== Recipe: Handle Non-Compliant Quote Character + +For data with non-compliant quote characters, use option +:quote_char+. +This example source uses SQUOTE ("'") as its quote character: + source = "'foo','1'\n'bar','1'\n'baz','2'\n" + CSV.parse(source, quote_char: "'") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]] + +==== Recipe: Allow Liberal Parsing + +Use option +:liberal_parsing+ to specify that \CSV should +attempt to parse input not conformant with RFC 4180, such as double quotes in unquoted fields: + source = 'is,this "three, or four",fields' + CSV.parse(source) # Raises MalformedCSVError + CSV.parse(source, liberal_parsing: true) # => [["is", "this \"three", " or four\"", "fields"]] + +=== Special Handling + +You can use parsing options to specify special handling for certain lines and fields. + +==== Special Line Handling + +Use parsing options to specify special handling for blank lines, or for other selected lines. + +===== Recipe: Ignore Blank Lines + +Use option +:skip_blanks+ to ignore blank lines: + source = <<-EOT + foo,0 + + bar,1 + baz,2 + + , + EOT + parsed = CSV.parse(source, skip_blanks: true) + parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] + +===== Recipe: Ignore Selected Lines + +Use option +:skip_lines+ to ignore selected lines. + source = <<-EOT + # Comment + foo,0 + bar,1 + baz,2 + # Another comment + EOT + parsed = CSV.parse(source, skip_lines: /^#/) + parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + +==== Special Field Handling + +Use parsing options to specify special handling for certain field values. + +===== Recipe: Strip Fields + +Use option +:strip+ to strip parsed field values: + CSV.parse_line(' a , b ', strip: true) # => ["a", "b"] + +===== Recipe: Handle Null Fields + +Use option +:nil_value+ to specify a value that will replace each field +that is null (no text): + CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"] + +===== Recipe: Handle Empty Fields + +Use option +:empty_value+ to specify a value that will replace each field +that is empty (\String of length 0); + CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"] + +=== Converting Fields + +You can use field converters to change parsed \String fields into other objects, +or to otherwise modify the \String fields. + +==== Converting Fields to Objects + +Use field converters to change parsed \String objects into other, more specific, objects. + +There are built-in field converters for converting to objects of certain classes: +- \Float +- \Integer +- \Date +- \DateTime + +Other built-in field converters include: +- +:numeric+: converts to \Integer and \Float. +- +:all+: converts to \DateTime, \Integer, \Float. + +You can also define field converters to convert to objects of other classes. + +===== Recipe: Convert Fields to Integers + +Convert fields to \Integer objects using built-in converter +:integer+: + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, converters: :integer) + parsed.map {|row| row['Value'].class} # => [Integer, Integer, Integer] + +===== Recipe: Convert Fields to Floats + +Convert fields to \Float objects using built-in converter +:float+: + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, converters: :float) + parsed.map {|row| row['Value'].class} # => [Float, Float, Float] + +===== Recipe: Convert Fields to Numerics + +Convert fields to \Integer and \Float objects using built-in converter +:numeric+: + source = "Name,Value\nfoo,0\nbar,1.1\nbaz,2.2\n" + parsed = CSV.parse(source, headers: true, converters: :numeric) + parsed.map {|row| row['Value'].class} # => [Integer, Float, Float] + +===== Recipe: Convert Fields to Dates + +Convert fields to \Date objects using built-in converter +:date+: + source = "Name,Date\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2001-02-03\n" + parsed = CSV.parse(source, headers: true, converters: :date) + parsed.map {|row| row['Date'].class} # => [Date, Date, Date] + +===== Recipe: Convert Fields to DateTimes + +Convert fields to \DateTime objects using built-in converter +:date_time+: + source = "Name,DateTime\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2020-05-07T14:59:00-05:00\n" + parsed = CSV.parse(source, headers: true, converters: :date_time) + parsed.map {|row| row['DateTime'].class} # => [DateTime, DateTime, DateTime] + +===== Recipe: Convert Assorted Fields to Objects + +Convert assorted fields to objects using built-in converter +:all+: + source = "Type,Value\nInteger,0\nFloat,1.0\nDateTime,2001-02-04\n" + parsed = CSV.parse(source, headers: true, converters: :all) + parsed.map {|row| row['Value'].class} # => [Integer, Float, DateTime] + +===== Recipe: Convert Fields to Other Objects + +Define a custom field converter to convert \String fields into other objects. +This example defines and uses a custom field converter +that converts each column-1 value to a \Rational object: + rational_converter = proc do |field, field_context| + field_context.index == 1 ? field.to_r : field + end + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, converters: rational_converter) + parsed.map {|row| row['Value'].class} # => [Rational, Rational, Rational] + +==== Recipe: Filter Field Strings + +Define a custom field converter to modify \String fields. +This example defines and uses a custom field converter +that strips whitespace from each field value: + strip_converter = proc {|field| field.strip } + source = "Name,Value\n foo , 0 \n bar , 1 \n baz , 2 \n" + parsed = CSV.parse(source, headers: true, converters: strip_converter) + parsed['Name'] # => ["foo", "bar", "baz"] + parsed['Value'] # => ["0", "1", "2"] + +==== Recipe: Register Field Converters + +Register a custom field converter, assigning it a name; +then refer to the converter by its name: + rational_converter = proc do |field, field_context| + field_context.index == 1 ? field.to_r : field + end + CSV::Converters[:rational] = rational_converter + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, converters: :rational) + parsed['Value'] # => [(0/1), (1/1), (2/1)] + +==== Using Multiple Field Converters + +You can use multiple field converters in either of these ways: +- Specify converters in option +:converters+. +- Specify converters in a custom converter list. + +===== Recipe: Specify Multiple Field Converters in Option +:converters+ + +Apply multiple field converters by specifying them in option +:converters+: + source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n" + parsed = CSV.parse(source, headers: true, converters: [:integer, :float]) + parsed['Value'] # => [0, 1.0, 2.0] + +===== Recipe: Specify Multiple Field Converters in a Custom Converter List + +Apply multiple field converters by defining and registering a custom converter list: + strip_converter = proc {|field| field.strip } + CSV::Converters[:strip] = strip_converter + CSV::Converters[:my_converters] = [:integer, :float, :strip] + source = "Name,Value\n foo , 0 \n bar , 1.0 \n baz , 2.0 \n" + parsed = CSV.parse(source, headers: true, converters: :my_converters) + parsed['Name'] # => ["foo", "bar", "baz"] + parsed['Value'] # => [0, 1.0, 2.0] + +=== Converting Headers + +You can use header converters to modify parsed \String headers. + +Built-in header converters include: +- +:symbol+: converts \String header to \Symbol. +- +:downcase+: converts \String header to lowercase. + +You can also define header converters to otherwise modify header \Strings. + +==== Recipe: Convert Headers to Lowercase + +Convert headers to lowercase using built-in converter +:downcase+: + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, header_converters: :downcase) + parsed.headers # => ["name", "value"] + +==== Recipe: Convert Headers to Symbols + +Convert headers to downcased Symbols using built-in converter +:symbol+: + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, header_converters: :symbol) + parsed.headers # => [:name, :value] + parsed.headers.map {|header| header.class} # => [Symbol, Symbol] + +==== Recipe: Filter Header Strings + +Define a custom header converter to modify \String fields. +This example defines and uses a custom header converter +that capitalizes each header \String: + capitalize_converter = proc {|header| header.capitalize } + source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, header_converters: capitalize_converter) + parsed.headers # => ["Name", "Value"] + +==== Recipe: Register Header Converters + +Register a custom header converter, assigning it a name; +then refer to the converter by its name: + capitalize_converter = proc {|header| header.capitalize } + CSV::HeaderConverters[:capitalize] = capitalize_converter + source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, headers: true, header_converters: :capitalize) + parsed.headers # => ["Name", "Value"] + +==== Using Multiple Header Converters + +You can use multiple header converters in either of these ways: +- Specify header converters in option +:header_converters+. +- Specify header converters in a custom header converter list. + +===== Recipe: Specify Multiple Header Converters in Option :header_converters + +Apply multiple header converters by specifying them in option +:header_converters+: + source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n" + parsed = CSV.parse(source, headers: true, header_converters: [:downcase, :symbol]) + parsed.headers # => [:name, :value] + +===== Recipe: Specify Multiple Header Converters in a Custom Header Converter List + +Apply multiple header converters by defining and registering a custom header converter list: + CSV::HeaderConverters[:my_header_converters] = [:symbol, :downcase] + source = "NAME,VALUE\nfoo,0\nbar,1.0\nbaz,2.0\n" + parsed = CSV.parse(source, headers: true, header_converters: :my_header_converters) + parsed.headers # => [:name, :value] + +=== Diagnostics + +==== Recipe: Capture Unconverted Fields + +To capture unconverted field values, use option +:unconverted_fields+: + source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" + parsed = CSV.parse(source, converters: :integer, unconverted_fields: true) + parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] + parsed.each {|row| p row.unconverted_fields } +Output: + ["Name", "Value"] + ["foo", "0"] + ["bar", "1"] + ["baz", "2"] + +==== Recipe: Capture Field Info + +To capture field info in a custom converter, accept two block arguments. +The first is the field value; the second is a +CSV::FieldInfo+ object: + strip_converter = proc {|field, field_info| p field_info; field.strip } + source = " foo , 0 \n bar , 1 \n baz , 2 \n" + parsed = CSV.parse(source, converters: strip_converter) + parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] +Output: + # + # + # + # + # + # diff --git a/ruby/doc/csv/recipes/recipes.rdoc b/ruby/doc/csv/recipes/recipes.rdoc new file mode 100644 index 000000000..9e4eaa1da --- /dev/null +++ b/ruby/doc/csv/recipes/recipes.rdoc @@ -0,0 +1,6 @@ +== Recipes for \CSV + +See: +- {Recipes for Parsing CSV}[./parsing_rdoc.html] +- {Recipes for Generating CSV}[./generating_rdoc.html] +- {Recipes for Filtering CSV}[./filtering_rdoc.html] diff --git a/ruby/doc/dig_methods.rdoc b/ruby/doc/dig_methods.rdoc new file mode 100644 index 000000000..366275d45 --- /dev/null +++ b/ruby/doc/dig_methods.rdoc @@ -0,0 +1,82 @@ += Dig Methods + +Ruby's +dig+ methods are useful for accessing nested data structures. + +Consider this data: + item = { + id: "0001", + type: "donut", + name: "Cake", + ppu: 0.55, + batters: { + batter: [ + {id: "1001", type: "Regular"}, + {id: "1002", type: "Chocolate"}, + {id: "1003", type: "Blueberry"}, + {id: "1004", type: "Devil's Food"} + ] + }, + topping: [ + {id: "5001", type: "None"}, + {id: "5002", type: "Glazed"}, + {id: "5005", type: "Sugar"}, + {id: "5007", type: "Powdered Sugar"}, + {id: "5006", type: "Chocolate with Sprinkles"}, + {id: "5003", type: "Chocolate"}, + {id: "5004", type: "Maple"} + ] + } + +Without a +dig+ method, you can write: + item[:batters][:batter][1][:type] # => "Chocolate" + +With a +dig+ method, you can write: + item.dig(:batters, :batter, 1, :type) # => "Chocolate" + +Without a +dig+ method, you can write, erroneously +(raises NoMethodError (undefined method `[]' for nil:NilClass)): + item[:batters][:BATTER][1][:type] + +With a +dig+ method, you can write (still erroneously, but avoiding the exception): + item.dig(:batters, :BATTER, 1, :type) # => nil + +== Why Is +dig+ Better? + +- It has fewer syntactical elements (to get wrong). +- It reads better. +- It does not raise an exception if an item is not found. + +== How Does +dig+ Work? + +The call sequence is: + obj.dig(*identifiers) + +The +identifiers+ define a "path" into the nested data structures: +- For each identifier in +identifiers+, calls method \#dig on a receiver + with that identifier. +- The first receiver is +self+. +- Each successive receiver is the value returned by the previous call to +dig+. +- The value finally returned is the value returned by the last call to +dig+. + +A +dig+ method raises an exception if any receiver does not respond to \#dig: + h = { foo: 1 } + # Raises TypeError (Integer does not have #dig method): + h.dig(:foo, :bar) + +== What Else? + +The structure above has \Hash objects and \Array objects, +both of which have instance method +dig+. + +Altogether there are six built-in Ruby classes that have method +dig+, +three in the core classes and three in the standard library. + +In the core: +- Array#dig: the first argument is an \Integer index. +- Hash#dig: the first argument is a key. +- Struct#dig: the first argument is a key. + +In the standard library: +- OpenStruct#dig: the first argument is a \String name. +- CSV::Table#dig: the first argument is an \Integer index or a \String header. +- CSV::Row#dig: the first argument is an \Integer index or a \String header. diff --git a/ruby/doc/documentation_guide.rdoc b/ruby/doc/documentation_guide.rdoc new file mode 100644 index 000000000..38438e94b --- /dev/null +++ b/ruby/doc/documentation_guide.rdoc @@ -0,0 +1,281 @@ += Documentation Guide + +This guide discusses recommendations for documenting +classes, modules, and methods +in the Ruby core and in the Ruby standard library. + +== Goal + +The goal of Ruby documentation is to impart the most important +and relevant in the shortest time. +The reader should be able to quickly understand the usefulness +of the subject code and how to use it. + +Providing too little information is bad, but providing unimportant +information or unnecessary examples is not good either. +Use your judgment about what the user needs to know. + +== General Guidelines + +- Keep in mind that the reader may not be fluent in \English. +- Write short declarative or imperative sentences. +- Group sentences into (ideally short) paragraphs, + each covering a single topic. +- Organize material with + {headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers]. +- Refer to authoritative and relevant sources using + {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-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}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists]. + - Idioms and culture-specific references. + - Overuse of headers. + +=== \RDoc + +Ruby is documented using RDoc. +For information on \RDoc syntax and features, see the +{RDoc Markup Reference}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-RDoc+Markup+Reference]. + +=== Output from irb + +For code examples, consider using interactive Ruby, +{irb}[https://ruby-doc.org/stdlib/libdoc/irb/rdoc/IRB.html]. + +For a code example that includes +irb+ output, +consider aligning # => ... in successive lines. +Alignment may sometimes aid readability: + + a = [1, 2, 3] #=> [1, 2, 3] + a.shuffle! #=> [2, 3, 1] + a #=> [2, 3, 1] + +=== Headers + +Organize a long discussion with +{headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers]. + +=== Blank Lines + +A blank line begins a new paragraph. + +A {code block}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Paragraphs+and+Verbatim] +or {list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists] +should be preceded by and followed by a blank line. +This is unnecessary for the HTML output, but helps in the +ri+ output. + +=== Auto-Linking + +In general, \RDoc's auto-linking should not be suppressed. +For example, we should write +Array+, not \Array. + +We might consider whether to suppress when: + +- 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). + +== Documenting Classes and Modules + +The general structure of the class or module documentation should be: + +* Synopsis +* Common uses, with examples +* "What's Here" summary (optional) + +=== Synopsis + +The synopsis is a short description of what the class or module does +and why the reader might want to use it. +Avoid details in the synopsis. + +=== Common Uses + +Show common uses of the class or module. +Depending on the class or module, this section may vary greatly +in both length and complexity. + +=== What's Here Summary + +The documentation for a class or module may include a "What's Here" section. + +Guidelines: + +- The section title is What's Here. +- Consider listing the parent class and any included modules; consider + {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links] + to their "What's Here" sections if those exist. +- List methods as a {labeled list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists]. +- Each list entry's label is a method name; + if the method has aliases, include those with the "base" method method, + and do not list them separately. +- Check the rendered documentation to determine whether \RDoc has recognized + the method and linked to it; if not, manually insert a + {link}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links]. +- Each entry's description is a 1-line synopsis for the method. +- Keep the description short. +- If there are more entries, consider gouping them into subsections with headers. +- If there are more than a few such subsections, + consider adding a table of contents just below the main section title. + +== Documenting Methods + +=== General Structure + +The general structure of the method documentation should be: + +* Calling sequence (for methods written in C). +* Synopsis (short description). +* Details and examples. +* Argument description (if necessary). +* Corner cases and exceptions. +* Aliases. +* Related methods (optional). + +=== Calling Sequence (for methods written in C) + +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:}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Method+arguments]. + +Example: + + * call-seq: + * array.count -> integer + * array.count(obj) -> integer + * array.count {|element| ... } -> integer + +When creating the call-seq, use the form + + receiver_type.method_name(arguments) {|block_arguments|} -> return_type + +Omit the parentheses for cases where the method does not accept arguments, +and omit the block for cases where a block is not accepted. + +In the cases where method can return multiple different types, separate the +types with "or". If the method can return any type, use "object". If the +method returns the receiver, use "self". + +In cases where the method accepts optional arguments, use a call-seq +with an optional argument if the method has the same behavior when an argument +is omitted as when the argument is passed with the default value. For example, +use: + + * obj.respond_to?(symbol, include_all=false) -> true or false + +Instead of: + + * obj.respond_to?(symbol) -> true or false + * obj.respond_to?(symbol, include_all) -> true or false + +However, as shown above for Array#count, use separate lines if the +behavior is different if the argument is omitted. + +Omit aliases from the call-seq, but mention them near the end (see below). + + +A +call-seq+ block should have {|x| ... }, not {|x| block } or {|x| code }. + +A +call-seq+ output should: + +- Have +self+, not +receiver+ or +array+. +- Begin with +new_+ if and only if the output object is a new instance + of the receiver's class, to emphasize that the output object is not +self+. + +=== Synopsis + +The synopsis comes next, and is a short description of what the +method does and why you would want to use it. Ideally, this +is a single sentence, but for more complex methods it may require +an entire paragraph. + +For Array#count, the synopsis is: + + 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. + +=== Details and Examples + +Most non-trivial methods benefit from examples, as well as details +beyond what is given in the synopsis. In the details and examples +section, you can document how the method handles different types +of arguments, and provides examples on proper usage. In this +section, focus on how to use the method properly, not on how the +method handles improper arguments or corner cases. + +Not every behavior of a method requires an example. If the method +is documented to return +self+, you don't need to provide an example +showing the return value is the same as the receiver. If the method +is documented to return +nil+, you don't need to provide an example +showing that it returns +nil+. If the details mention that for a +certain argument type, an empty array is returned, you don't need +to provide an example for that. + +Only add an example if it provides the user additional information, +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. + +=== Argument Description (if necessary) + +For methods that require arguments, if not obvious and not explicitly +mentioned in the details or implicitly shown in the examples, you can +provide details about the types of arguments supported. When discussing +the types of arguments, use simple language even if less-precise, such +as "level must be an integer", not "level must be an Integer-convertible +object". The vast majority of use will be with the expected type, not an +argument that is explicitly convertible to the expected type, and +documenting the difference is not important. + +For methods that take blocks, it can be useful to document the type of +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}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists]} + +=== Corner Cases and Exceptions + +For corner cases of methods, such as atypical usage, briefly mention +the behavior, but do not provide any examples. + +Only document exceptions raised if they are not obvious. For example, +if you have stated earlier than an argument type must be an integer, +you do not need to document that a \TypeError is raised if a non-integer +is passed. Do not provide examples of exceptions being raised unless +that is a common case, such as \Hash#fetch raising a \KeyError. + +=== Aliases + +Mention aliases in the form + + Array#find_index is an alias for Array#index. + +=== Related Methods (optional) + +In some cases, it is useful to document which methods are related to +the current method. For example, documentation for \Hash#[] might +mention \Hash#fetch as a related method, and \Hash#merge might mention +\Hash#merge! as a related method. Consider which methods may be related +to the current method, and if you think the reader would benefit it, +at the end of the method documentation, add a line starting with +"Related: " (e.g. "Related: #fetch"). Don't list more than three +related methods. If you think more than three methods are related, +pick the three you think are most important and list those three. + +=== Methods Accepting Multiple Argument Types + +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. diff --git a/ruby/doc/dtrace_probes.rdoc b/ruby/doc/dtrace_probes.rdoc index d2cdd5690..1b20597ab 100644 --- a/ruby/doc/dtrace_probes.rdoc +++ b/ruby/doc/dtrace_probes.rdoc @@ -52,15 +52,21 @@ with when they are fired and the arguments they take: [ruby:::method-entry(classname, methodname, filename, lineno);] This probe is fired just before a method is entered. - classname name of the class (a string) - methodname name of the method about to be executed (a string) - filename the file name where the method is _being called_ (a string) - lineno the line number where the method is _being called_ (an int) + classname:: name of the class (a string) + methodname:: name of the method about to be executed (a string) + filename:: the file name where the method is _being called_ (a string) + lineno:: the line number where the method is _being called_ (an int) + + *NOTE*: will only be fired if tracing is enabled, e.g. with: TracePoint.new{}.enable. + See Feature#14104[https://bugs.ruby-lang.org/issues/14104] for more details. [ruby:::method-return(classname, methodname, filename, lineno);] This probe is fired just after a method has returned. The arguments are the same as "ruby:::method-entry". + *NOTE*: will only be fired if tracing is enabled, e.g. with: TracePoint.new{}.enable. + See Feature#14104[https://bugs.ruby-lang.org/issues/14104] for more details. + [ruby:::cmethod-entry(classname, methodname, filename, lineno);] This probe is fired just before a C method is entered. The arguments are the same as "ruby:::method-entry". @@ -72,9 +78,9 @@ with when they are fired and the arguments they take: [ruby:::require-entry(requiredfile, filename, lineno);] This probe is fired on calls to rb_require_safe (when a file is required). - requiredfile is the name of the file to be required (string). - filename is the file that called "require" (string). - lineno is the line number where the call to require was made (int). + requiredfile:: the name of the file to be required (string). + filename:: the file that called "+require+" (string). + lineno:: the line number where the call to require was made (int). [ruby:::require-return(requiredfile, filename, lineno);] This probe is fired just before rb_require_safe (when a file is required) @@ -84,11 +90,11 @@ with when they are fired and the arguments they take: [ruby:::find-require-entry(requiredfile, filename, lineno);] This probe is fired right before search_required is called. search_required determines whether the file has already been required by searching loaded - features ($"), and if not, figures out which file must be loaded. + features ($"), and if not, figures out which file must be loaded. - requiredfile is the file to be required (string). - filename is the file that called "require" (string). - lineno is the line number where the call to require was made (int). + requiredfile:: the file to be required (string). + filename:: the file that called "require" (string). + lineno:: the line number where the call to require was made (int). [ruby:::find-require-return(requiredfile, filename, lineno);] This probe is fired right after search_required returns. See the @@ -106,56 +112,56 @@ with when they are fired and the arguments they take: [ruby:::raise(classname, filename, lineno);] This probe is fired when an exception is raised. - classname is the class name of the raised exception (string) - filename the name of the file where the exception was raised (string) - lineno the line number in the file where the exception was raised (int) + classname:: the class name of the raised exception (string) + filename:: the name of the file where the exception was raised (string) + lineno:: the line number in the file where the exception was raised (int) [ruby:::object-create(classname, filename, lineno);] This probe is fired when an object is about to be allocated. - classname the class of the allocated object (string) - filename the name of the file where the object is allocated (string) - lineno the line number in the file where the object is allocated (int) + classname:: the class of the allocated object (string) + filename:: the name of the file where the object is allocated (string) + lineno:: the line number in the file where the object is allocated (int) [ruby:::array-create(length, filename, lineno);] This probe is fired when an Array is about to be allocated. - length the size of the array (long) - filename the name of the file where the array is allocated (string) - lineno the line number in the file where the array is allocated (int) + length:: the size of the array (long) + filename:: the name of the file where the array is allocated (string) + lineno:: the line number in the file where the array is allocated (int) [ruby:::hash-create(length, filename, lineno);] This probe is fired when a Hash is about to be allocated. - length the size of the hash (long) - filename the name of the file where the hash is allocated (string) - lineno the line number in the file where the hash is allocated (int) + length:: the size of the hash (long) + filename:: the name of the file where the hash is allocated (string) + lineno:: the line number in the file where the hash is allocated (int) [ruby:::string-create(length, filename, lineno);] This probe is fired when a String is about to be allocated. - length the size of the string (long) - filename the name of the file where the string is allocated (string) - lineno the line number in the file where the string is allocated (int) + length:: the size of the string (long) + filename:: the name of the file where the string is allocated (string) + lineno:: the line number in the file where the string is allocated (int) [ruby:::symbol-create(str, filename, lineno);] This probe is fired when a Symbol is about to be allocated. - str the contents of the symbol (string) - filename the name of the file where the string is allocated (string) - lineno the line number in the file where the string is allocated (int) + str:: the contents of the symbol (string) + filename:: the name of the file where the string is allocated (string) + lineno:: the line number in the file where the string is allocated (int) [ruby:::parse-begin(sourcefile, lineno);] Fired just before parsing and compiling a source file. - sourcefile the file being parsed (string) - lineno the line number where the source starts (int) + sourcefile:: the file being parsed (string) + lineno:: the line number where the source starts (int) [ruby:::parse-end(sourcefile, lineno);] Fired just after parsing and compiling a source file. - sourcefile the file being parsed (string) - lineno the line number where the source ended (int) + sourcefile:: the file being parsed (string) + lineno:: the line number where the source ended (int) [ruby:::gc-mark-begin();] Fired at the beginning of a mark phase. @@ -172,7 +178,7 @@ with when they are fired and the arguments they take: [ruby:::method-cache-clear(class, sourcefile, lineno);] Fired when the method cache is cleared. - class is the classname being cleared, or "global" (string) - sourcefile the file being parsed (string) - lineno the line number where the source ended (int) + class:: the classname being cleared, or "global" (string) + sourcefile:: the file being parsed (string) + lineno:: the line number where the source ended (int) diff --git a/ruby/doc/extension.ja.rdoc b/ruby/doc/extension.ja.rdoc index 47303ec40..feae7b97d 100644 --- a/ruby/doc/extension.ja.rdoc +++ b/ruby/doc/extension.ja.rdoc @@ -190,6 +190,21 @@ INT2NUM() :: ä»»æ„ã®æ•´æ•°ã‹ã‚‰VALUE㸠INT2NUM()ã¯æ•´æ•°ãŒFIXNUMã®ç¯„囲ã«åŽã¾ã‚‰ãªã„å ´åˆï¼ŒBignumã«å¤‰æ› ã—ã¦ãれã¾ã™(ãŒï¼Œå°‘ã—é…ã„). +Cã®çœŸå½å€¤ã‚’Rubyã® +true+ ã¾ãŸã¯ +false+ ã«å¤‰æ›ã™ã‚‹ + +RBOOL() :: + +RBOOL(v) 㯠_v_ ãŒéž0ã®ã¨ã +Qtrue+ ,ãれ以外 +ã® _v_ ãŒ0ã®ã¨ã +Qfalse+ ã‚’è¿”ã—ã¾ã™ï¼Ž + +注æ„: RBOOLã¯å®šç¾©ã•れã¦ã„ã‚‹ã®ã¯Ruby 3.1以é™ãªã®ã§ï¼Œãれより +å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’サãƒãƒ¼ãƒˆã™ã‚‹ãƒ—ログラム中ã§ä½¿ã„ãŸã„ã¨ãã¯ï¼Œä»¥ +下ã®ã‚ˆã†ãªå®šç¾©ã‚’追加ã—ã¦ãŠãå¿…è¦ãŒã‚ã‚‹ã§ã—ょã†ï¼Ž + + #ifndef RBOOL + #define RBOOL(v) ((v) ? Qtrue : Qfalse) + #endif + === Rubyã®ãƒ‡ãƒ¼ã‚¿ã‚’æ“作ã™ã‚‹ 先程も述ã¹ãŸé€šã‚Šï¼ŒRubyã®æ§‹é€ ä½“をアクセスã™ã‚‹æ™‚ã«å†…å®¹ã®æ›´æ–°ã‚’ @@ -617,12 +632,14 @@ C言語ã¨Rubyã®é–“ã§æƒ…報を共有ã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦è§£èª¬ã—ã¾ã™ï¼Ž Qtrue :: Qfalse :: - 真å½å€¤ï¼ŽQfalseã¯C言語ã§ã‚‚å½ã¨ã¿ãªã•れã¾ã™(ã¤ã¾ã‚Š0). + 真å½å€¤ï¼ŽC言語ã‹ã‚‰è¦‹ãŸã€Œtrueã€ã¨ã€Œfalseã€ï¼Ž Qnil :: C言語ã‹ã‚‰è¦‹ãŸã€Œnilã€ï¼Ž +RTEST(obj)ã¨ã„ã†ãƒžã‚¯ãƒ­ã¯objãŒQfalseã‹Qnilã®ã¨ã0ã‚’è¿”ã—ã¾ã™ï¼Ž + === Cã¨Rubyã§å…±æœ‰ã•れる大域変数 Cã¨Rubyã§å¤§åŸŸå¤‰æ•°ã‚’使ã£ã¦æƒ…報を共有ã§ãã¾ã™ï¼Žå…±æœ‰ã§ãる大域 @@ -697,30 +714,28 @@ Cã®ä¸–界ã§å®šç¾©ã•れãŸãƒ‡ãƒ¼ã‚¿(構造体)ã‚’Rubyã®ã‚ªãƒ–ジェクト㨠ã“ã®ãƒžã‚¯ãƒ­ã®æˆ»ã‚Šå€¤ã¯ç”Ÿæˆã•れãŸã‚ªãƒ–ジェクトを表ã™VALUE値ã§ã™ï¼Ž -klassã¯ã“ã®ã‚ªãƒ–ジェクトã®ã‚¯ãƒ©ã‚¹ã§ã™ï¼Ždata_typeã¯ã“ã®æ§‹é€ ä½“ã‚’ -RubyãŒç®¡ç†ã™ã‚‹ãŸã‚ã®æƒ…報を記述ã—ãŸconst rb_data_type_tåž‹ã¸ã® -ãƒã‚¤ãƒ³ã‚¿ã§ã™ï¼Ž +klassã¯ã“ã®ã‚ªãƒ–ジェクトã®ã‚¯ãƒ©ã‚¹ã§ã™ï¼Žklassã¯, Objectクラス㋠+ら派生ã—, å¿…ãšrb_define_alloc_funcã‹rb_undef_alloc_funcを呼 +ã³å‡ºã—ã¦allocatorを設定ã—ã¦ãã ã•ã„. -ãªãŠ, klassã¯, Objectã‚„ä»–ã®ã‚¯ãƒ©ã‚¹ã§ã¯ãªãData (rb_cData)ã¨ã„ -ã†ç‰¹åˆ¥ãªã‚¯ãƒ©ã‚¹ã‹ã‚‰æ´¾ç”Ÿã™ã‚‹ã“ã¨ãŒæŽ¨å¥¨ã•れã¾ã™ï¼Ž -Dataã‹ã‚‰æ´¾ç”Ÿã—ãªã„å ´åˆã«ã¯, å¿…ãšrb_undef_alloc_func(klass) -を呼ã³å‡ºã—ã¦ãã ã•ã„. +data_typeã¯ã“ã®æ§‹é€ ä½“ã‚’RubyãŒç®¡ç†ã™ã‚‹ãŸã‚ã®æƒ…報を記述ã—㟠+const rb_data_type_tåž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã™ï¼Ž rb_data_type_tã¯æ¬¡ã®ã‚ˆã†ã«å®šç¾©ã•れã¦ã„ã¾ã™ï¼Ž typedef struct rb_data_type_struct rb_data_type_t; struct rb_data_type_struct { - const char *wrap_struct_name; - struct { - void (*dmark)(void*); - void (*dfree)(void*); - size_t (*dsize)(const void *); - void *reserved[2]; - } function; - const rb_data_type_t *parent; - void *data; - VALUE flags; + const char *wrap_struct_name; + struct { + void (*dmark)(void*); + void (*dfree)(void*); + size_t (*dsize)(const void *); + void *reserved[2]; + } function; + const rb_data_type_t *parent; + void *data; + VALUE flags; }; wrap_struct_nameã¯ã“ã®æ§‹é€ ä½“を識別ã™ã‚‹åå‰ã§ã™ï¼Žä¸»ã«çµ±è¨ˆæƒ…å ± @@ -743,8 +758,8 @@ dmarkã¯ã‚¬ãƒ¼ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ãŒã‚ªãƒ–ジェクトã¸ã®å‚照をマーク ++ dfreeã¯ã“ã®æ§‹é€ ä½“ãŒã‚‚ã†ä¸è¦ã«ãªã£ãŸæ™‚ã«å‘¼ã°ã‚Œã‚‹é–¢æ•°ã§ã™ï¼Žã“ -ã®é–¢æ•°ãŒã‚¬ãƒ¼ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã‹ã‚‰å‘¼ã°ã‚Œã¾ã™ï¼Žã“れãŒ-1ã®å ´åˆã¯ï¼Œ -å˜ç´”ã«æ§‹é€ ä½“ãŒè§£æ”¾ã•れã¾ã™ï¼Ž +ã®é–¢æ•°ãŒã‚¬ãƒ¼ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã‹ã‚‰å‘¼ã°ã‚Œã¾ã™ï¼Žã“れ㌠+RUBY_DEFAULT_FREEã®å ´åˆã¯ï¼Œå˜ç´”ã«æ§‹é€ ä½“ãŒè§£æ”¾ã•れã¾ã™ï¼Ž dsizeã¯æ§‹é€ ä½“ãŒæ¶ˆè²»ã—ã¦ã„るメモリã®ãƒã‚¤ãƒˆæ•°ã‚’è¿”ã™é–¢æ•°ã§ã™ï¼Ž 引数ã¨ã—ã¦æ§‹é€ ä½“ã¸ã®ãƒã‚¤ãƒ³ã‚¿ãŒæ¸¡ã•れã¾ã™ï¼Žå®Ÿè£…困難ã§ã‚れã°0 @@ -1108,9 +1123,8 @@ lex.c :: è‡ªå‹•ç”Ÿæˆ -> opt*.inc : è‡ªå‹•ç”Ÿæˆ -> vm.inc : è‡ªå‹•ç”Ÿæˆ -=== æ­£è¦è¡¨ç¾ã‚¨ãƒ³ã‚¸ãƒ³ (鬼車) +=== æ­£è¦è¡¨ç¾ã‚¨ãƒ³ã‚¸ãƒ³ (鬼雲) - regex.c regcomp.c regenc.c regerror.c @@ -1829,6 +1843,17 @@ rb_ary_store() ãªã©ã®ï¼Œé©åˆ‡ãª API 関数を利用ã™ã‚‹ã‚ˆã†ã«ã—ã¦ä¸‹ ãã®ã»ã‹ï¼Œå¯¾å¿œã«ã¤ã„ã¦ã®è©³ç´°ã¯ extension.rdoc ã®ã€ŒAppendix D. Generational GCã€ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„. +== Appendix E. Ractor サãƒãƒ¼ãƒˆ + +Ruby 3.0 ã‹ã‚‰ã€Ruby プログラムを並列ã«å®Ÿè¡Œã™ã‚‹ãŸã‚ã®ä»•組ã¿ã§ã‚ã‚‹ Ractor +ãŒå°Žå…¥ã•れã¾ã—ãŸã€‚é©åˆ‡ã«ä¸¦åˆ—ã«å®Ÿè¡Œã™ã‚‹ãŸã‚ã«ã¯ã€Ractor サãƒãƒ¼ãƒˆãŒå¿…è¦ã« +ãªã‚Šã¾ã™ã€‚サãƒãƒ¼ãƒˆã—ã¦ã„ãªã„ライブラリã¯ã€ãƒ¡ã‚¤ãƒ³ Ractor 以外ã§å®Ÿè¡Œã™ã‚‹ã¨ +エラーã«ãªã‚Šã¾ã™ï¼ˆRactor::UnsafeError)。 + +Ractor をサãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã®è©³ç´°ã¯ã€extension.rdoc ã®ã€ŒAppendix F. Ractor +supportã€ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + + :enddoc: Local variables: :enddoc: fill-column: 60 :enddoc: end: diff --git a/ruby/doc/extension.rdoc b/ruby/doc/extension.rdoc index 79eb96d51..3bb00c154 100644 --- a/ruby/doc/extension.rdoc +++ b/ruby/doc/extension.rdoc @@ -93,7 +93,9 @@ There are also faster check macros for fixnums and nil. The data for type T_NIL, T_FALSE, T_TRUE are nil, false, true respectively. They are singletons for the data type. The equivalent C constants are: Qnil, Qfalse, Qtrue. -Note that Qfalse is false in C also (i.e. 0), but not Qnil. +RTEST() will return true if a VALUE is neither Qfalse nor Qnil. +If you need to differentiate Qfalse from Qnil, +specifically test against Qfalse. The T_FIXNUM data is a 31bit or 63bit length fixed integer. This size depends on the size of long: if long is 32bit then @@ -167,6 +169,21 @@ INT2NUM() :: for arbitrary sized integers. INT2NUM() converts an integer into a Bignum if it is out of the FIXNUM range, but is a bit slower. +To convert C boolean to Ruby +true+ or +false+ : + +RBOOL() :: + +RBOOL(v) returns +Qtrue+ if _v_ is not 0, or +Qfalse+ +otherwisze _v_ is 0. + +Notice: RBOOL is defined since Ruby 3.1, if you want to use it in a +program which supports older versions, the fallback definition will be +needed, like as the following. + + #ifndef RBOOL + #define RBOOL(v) ((v) ? Qtrue : Qfalse) + #endif + === Manipulating Ruby Data As I already mentioned, it is not recommended to modify an object's @@ -450,15 +467,13 @@ you may rely on: To specify whether keyword arguments are passed when calling super: - VALUE rb_call_super(int argc, const VALUE *argv, int kw_splat) + VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat) +kw_splat+ can have these possible values (used by all methods that accept +kw_splat+ argument): RB_NO_KEYWORDS :: Do not pass keywords RB_PASS_KEYWORDS :: Pass keywords, final argument should be a hash of keywords -RB_PASS_EMPTY_KEYWORDS :: Pass empty keywords (not included in arguments) - (this will be removed in Ruby 3.0) RB_PASS_CALLED_KEYWORDS :: Pass keywords if current method was called with keywords, useful for argument delegation @@ -659,30 +674,30 @@ with the next macro. TypedData_Wrap_Struct() returns a created Ruby object as a VALUE. -The klass argument is the class for the object. +The klass argument is the class for the object. The klass should +derive from rb_cObject, and the allocator must be set by calling +rb_define_alloc_func or rb_undef_alloc_func. + data_type is a pointer to a const rb_data_type_t which describes how Ruby should manage the struct. -It is recommended that klass derives from a special class called -Data (rb_cData) but not from Object or other ordinal classes. -If it doesn't, you have to call rb_undef_alloc_func(klass). - rb_data_type_t is defined like this. Let's take a look at each member of the struct. typedef struct rb_data_type_struct rb_data_type_t; struct rb_data_type_struct { - const char *wrap_struct_name; - struct { - void (*dmark)(void*); - void (*dfree)(void*); - size_t (*dsize)(const void *); - void *reserved[2]; - } function; - const rb_data_type_t *parent; - void *data; - VALUE flags; + const char *wrap_struct_name; + struct { + void (*dmark)(void*); + void (*dfree)(void*); + size_t (*dsize)(const void *); + void (*dcompact)(void*); + void *reserved[1]; + } function; + const rb_data_type_t *parent; + void *data; + VALUE flags; }; wrap_struct_name is an identifier of this instance of the struct. @@ -703,14 +718,22 @@ Note that it is recommended to avoid such a reference. ++ dfree is a function to free the pointer allocation. -If this is -1, the pointer will be just freed. +If this is RUBY_DEFAULT_FREE, the pointer will be just freed. dsize calculates memory consumption in bytes by the struct. Its parameter is a pointer to your struct. You can pass 0 as dsize if it is hard to implement such a function. But it is still recommended to avoid 0. -You have to fill reserved and parent with 0. +dcompact is invoked when memory compaction took place. +Referred Ruby objects that were marked by rb_gc_mark_movable() +can here be updated per rb_gc_location(). + +You have to fill reserved with 0. + +parent can point to another C type definition that the Ruby object +is inherited from. Then TypedData_Get_Struct() does also accept +derived objects. You can fill "data" with an arbitrary value for your use. Ruby does nothing with the member. @@ -742,6 +765,14 @@ RUBY_TYPED_WB_PROTECTED :: More about write barriers can be found in "Generational GC" in Appendix D. +RUBY_TYPED_FROZEN_SHAREABLE :: + + This flag indicates that the object is shareable object + if the object is frozen. See Appendix F 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. TypedData_Make_Struct(klass, type, data_type, sval) @@ -799,11 +830,14 @@ the library. Here's the example of an initializing function. + #include void Init_dbm(void) { /* define DBM class */ VALUE cDBM = rb_define_class("DBM", rb_cObject); + /* Redefine DBM.allocate + rb_define_alloc_func(cDBM, fdbm_alloc); /* DBM includes Enumerable module */ rb_include_module(cDBM, rb_mEnumerable); @@ -813,7 +847,7 @@ Here's the example of an initializing function. /* DBM instance method close(): no args */ rb_define_method(cDBM, "close", fdbm_close, 0); /* DBM instance method []: 1 argument */ - rb_define_method(cDBM, "[]", fdbm_fetch, 1); + rb_define_method(cDBM, "[]", fdbm_aref, 1); /* ... */ @@ -836,10 +870,19 @@ TypedData_Make_Struct. RUBY_TYPED_FREE_IMMEDIATELY, }; - obj = TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp); + static VALUE + fdbm_alloc(VALUE klass) + { + struct dbmdata *dbmp; + /* Allocate T_DATA object and C struct and fill struct with zero bytes */ + return TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp); + } This code wraps the dbmdata structure into a Ruby object. We avoid wrapping DBM* directly, because we want to cache size information. +Since Object.allocate allocates an ordinary T_OBJECT type (instead +of T_DATA), it's important to either use rb_define_alloc_func() to +overwrite it or rb_undef_alloc_func() to delete it. To retrieve the dbmdata structure from a Ruby object, we define the following macro: @@ -857,9 +900,13 @@ There are three kinds of way to receive method arguments. First, methods with a fixed number of arguments receive arguments like this: static VALUE - fdbm_delete(VALUE obj, VALUE keystr) + fdbm_aref(VALUE obj, VALUE keystr) { - /* ... */ + struct dbmdata *dbmp; + GetDBM(obj, dbmp); + /* Use dbmp to access the key */ + dbm_fetch(dbmp->di_dbm, StringValueCStr(keystr)); + /* ... */ } The first argument of the C function is the self, the rest are the @@ -1005,7 +1052,24 @@ You can do anything you want with your library. The author of Ruby will not claim any restrictions on your code depending on the Ruby API. Feel free to use, modify, distribute or sell your program. -== Appendix A. Ruby Source Files Overview +== Appendix A. Ruby Header and Source Files Overview + +=== Ruby Header Files + +Everything under $repo_root/include/ruby is installed with +make install. +It should be included per #include from C extensions. +All symbols are public API with the exception of symbols prefixed with ++rbimpl_+ or +RBIMPL_+. They are implementation details and shouldn't +be used by C extensions. + +Only $repo_root/include/ruby/*.h are allowed to be #include-d +by C extensions. Files under $repo_root/include/ruby/internal +should not be #include-d directly. + +Header files under $repo_root/internal/ or directly under the +root $repo_root/*.h are not make-installed. +They are internal headers with only internal APIs. === Ruby Language Core @@ -1049,9 +1113,8 @@ lex.c :: automatically generated from keywords -> opt*.inc : automatically generated -> vm.inc : automatically generated -=== Regular Expression Engine (Oniguruma) +=== Regular Expression Engine (Onigumo) - regex.c regcomp.c regenc.c regerror.c @@ -1423,28 +1486,6 @@ rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) :: ; argument captured as a hash. ; If keyword arguments are not ; provided, returns nil. - ; - ; Currently, will also consider - ; final argument as keywords if - ; it is a hash or can be - ; converted to a hash with - ; #to_hash. When the last - ; argument is nil, it is - ; captured if it is not - ; ambiguous to take it as - ; empty option hash; i.e. '*' - ; is not specified and - ; arguments are given more - ; than sufficient. - ; - ; However, handling final - ; argument as keywords if - ; method was not called with - ; keywords (whether final - ; argument is hash or nil) is - ; deprecated. In that case, a - ; warning will be emitted, and - ; in Ruby 3.0 it will be an error. sym-for-block-arg := "&" ; Indicates that an iterator ; block should be captured if ; given @@ -1469,8 +1510,6 @@ rb_scan_args_kw(int kw_splat, int argc, VALUE *argv, const char *fmt, ...) :: RB_SCAN_ARGS_PASS_CALLED_KEYWORDS :: Same behavior as +rb_scan_args+. RB_SCAN_ARGS_KEYWORDS :: The final argument should be a hash treated as keywords. - RB_SCAN_ARGS_EMPTY_KEYWORDS :: Don't treat a final hash as keywords. - (this will be removed in Ruby 3.0) RB_SCAN_ARGS_LAST_HASH_KEYWORDS :: Treat a final argument as keywords if it is a hash, and not as keywords otherwise. @@ -1877,13 +1916,13 @@ NORETURN_STYLE_NEW :: HAVE_RB_DEFINE_ALLOC_FUNC :: Means that function rb_define_alloc_func() is provided, that means the - allocation framework is used. This is same as the result of + allocation framework is used. This is the same as the result of have_func("rb_define_alloc_func", "ruby.h"). HAVE_RB_REG_NEW_STR :: Means that function rb_reg_new_str() is provided, that creates Regexp - object from String object. This is same as the result of + object from String object. This is the same as the result of have_func("rb_reg_new_str", "ruby.h"). HAVE_RB_IO_T :: @@ -1946,6 +1985,7 @@ the *_kw functions introduced in Ruby 2.7. #define rb_proc_call_with_block_kw(p, c, v, b, kw) rb_proc_call_with_block(p, c, v, b) #define rb_method_call_kw(c, v, m, kw) rb_method_call(c, v, m) #define rb_method_call_with_block_kw(c, v, m, b, kw) rb_method_call_with_block(c, v, m, b) + #define rb_eval_cmd_kwd(c, a, kw) rb_eval_cmd(c, a, 0) #endif == Appendix C. Functions available for use in extconf.rb @@ -2049,7 +2089,7 @@ Before inserting write barriers, you need to know about RGenGC algorithm available in include/ruby/ruby.h. An example is available in iseq.c. For a complete guide for RGenGC and write barriers, please refer to -. +. == Appendix E. RB_GC_GUARD to protect from premature GC @@ -2100,6 +2140,89 @@ keyword in C. RB_GC_GUARD has the following advantages: compilers and architectures. RB_GC_GUARD is customizable for broken systems/compilers without negatively affecting other systems. +== Appendix F. Ractor support + +Ractor is parallel execution mechanism introduced from Ruby 3.0. All +ractrors can run in parallel by different OS thread (underlying system +provided thread), so the C extension should be thread-safe. Now we call +the property that C extension can run in multiple ractors "Ractor-safe". + +By default, all C extensions are recognized as Ractor-unsafe. If C +extension becomes Ractor-safe, the extension should call +rb_ext_ractor_safe(true) at the Init_ function and all defined method +marked as Ractor-safe. Ractor-unsafe C-methods only been called from +main-ractor. If non-main ractor calls it, then Ractor::UnsafeError is +raised. + +BTW non-"Ractor-safe" extensions raises an error on non-main ractors, so +that it is "safe" because unsafe operations are not allowed. +"Ractor-safe" property means "multi-Ractor-ready" or "safe on +multi-ractors execution". "Ractor-safe" term comes from "Thread-safe". + +To make "Ractor-safe" C extension, we need to check the following points: + +(1) Do not share 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; } + +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. + +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 + +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; + } + +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. + +On the Ractor mechanism, most of objects given by the method parameters +or the receiver are isolated by Ractor's boundary, it is easy to make +thread-safe code than usual thread-programming in general. For example, +we don't need to lock an array object to access the element of it. + +(3) Check the thread-safety of using library + +If an extension relies on the external library libfoo and the function +foo(), the function foo() should be thread safe. + +(4) Make an object shareable + +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. + +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 + +Maybe there are more points which should be considered to make +Ractor-safe extension, so this document will be extended. + :enddoc: Local variables: :enddoc: fill-column: 70 :enddoc: end: diff --git a/ruby/doc/fiber.md b/ruby/doc/fiber.md new file mode 100644 index 000000000..a334faf73 --- /dev/null +++ b/ruby/doc/fiber.md @@ -0,0 +1,232 @@ +# Fiber + +Fibers provide a mechanism for cooperative concurrency. + +## Context Switching + +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 +#!/usr/bin/env ruby + +puts "1: Start program." + +f = Fiber.new do + puts "3: Entered fiber." + Fiber.yield + puts "5: Resumed fiber." +end + +puts "2: Resume fiber first time." +f.resume + +puts "4: Resume fiber second time." +f.resume + +puts "6: Finished." +``` + +This program demonstrates the flow control of fibers. + +## Scheduler + +The scheduler interface is used to intercept blocking operations. A typical +implementation would be a wrapper for a gem like `EventMachine` or `Async`. This +design provides separation of concerns between the event loop implementation +and application code. It also allows for layered schedulers which can perform +instrumentation. + +To set the scheduler for the current thread: + +``` ruby +Fiber.set_scheduler(MyScheduler.new) +``` + +When the thread exits, there is an implicit call to `set_scheduler`: + +``` ruby +Fiber.set_scheduler(nil) +``` + +### Design + +The scheduler interface is designed to be a un-opinionated light-weight layer +between user code and blocking operations. The scheduler hooks should avoid +translating or converting arguments or return values. Ideally, the exact same +arguments from the user code are provided directly to the scheduler hook with +no changes. + +### Interface + +This is the interface you need to implement. + +``` ruby +class Scheduler + # Wait for the specified process ID to exit. + # This hook is optional. + # @parameter pid [Integer] The process ID to wait for. + # @parameter flags [Integer] A bit-mask of flags suitable for `Process::Status.wait`. + # @returns [Process::Status] A process status instance. + def process_wait(pid, flags) + Thread.new do + Process::Status.wait(pid, flags) + end.value + end + + # Wait for the given io readiness to match the specified events within + # the specified timeout. + # @parameter event [Integer] A bit mask of `IO::READABLE`, + # `IO::WRITABLE` and `IO::PRIORITY`. + # @parameter timeout [Numeric] The amount of time to wait for the event in seconds. + # @returns [Integer] The subset of events that are ready. + def io_wait(io, events, timeout) + end + + # Read from the given io into the specified buffer. + # WARNING: Experimental hook! Do not use in production code! + # @parameter io [IO] The io to read from. + # @parameter buffer [IO::Buffer] The buffer to read into. + # @parameter length [Integer] The minimum amount to read. + def io_read(io, buffer, length) + end + + # Write from the given buffer into the specified IO. + # WARNING: Experimental hook! Do not use in production code! + # @parameter io [IO] The io to write to. + # @parameter buffer [IO::Buffer] The buffer to write from. + # @parameter length [Integer] The minimum amount to write. + def io_write(io, buffer, length) + end + + # Sleep the current task for the specified duration, or forever if not + # specified. + # @parameter duration [Numeric] The amount of time to sleep in seconds. + def kernel_sleep(duration = nil) + end + + # Execute the given block. If the block execution exceeds the given timeout, + # the specified exception `klass` will be raised. Typically, only non-blocking + # methods which enter the scheduler will raise such exceptions. + # @parameter duration [Integer] The amount of time to wait, after which an exception will be raised. + # @parameter klass [Class] The exception class to raise. + # @parameter *arguments [Array] The arguments to send to the constructor of the exception. + # @yields {...} The user code to execute. + def timeout_after(duration, klass, *arguments, &block) + end + + # Resolve hostname to an array of IP addresses. + # This hook is optional. + # @parameter hostname [String] Example: "www.ruby-lang.org". + # @returns [Array] An array of IPv4 and/or IPv6 address strings that the hostname resolves to. + def address_resolve(hostname) + end + + # Block the calling fiber. + # @parameter blocker [Object] What we are waiting on, informational only. + # @parameter timeout [Numeric | Nil] The amount of time to wait for in seconds. + # @returns [Boolean] Whether the blocking operation was successful or not. + def block(blocker, timeout = nil) + end + + # Unblock the specified fiber. + # @parameter blocker [Object] What we are waiting on, informational only. + # @parameter fiber [Fiber] The fiber to unblock. + # @reentrant Thread safe. + def unblock(blocker, fiber) + end + + # Intercept the creation of a non-blocking fiber. + # @returns [Fiber] + def fiber(&block) + Fiber.new(blocking: false, &block) + end + + # Invoked when the thread exits. + def close + self.run + end + + def run + # Implement event loop here. + end +end +``` + +Additional hooks may be introduced in the future, we will use feature detection +in order to enable these hooks. + +### Non-blocking Execution + +The scheduler hooks will only be used in special non-blocking execution +contexts. Non-blocking execution contexts introduce non-determinism because the +execution of scheduler hooks may introduce context switching points into your +program. + +#### Fibers + +Fibers can be used to create non-blocking execution contexts. + +``` ruby +Fiber.new do + puts Fiber.current.blocking? # false + + # May invoke `Fiber.scheduler&.io_wait`. + io.read(...) + + # May invoke `Fiber.scheduler&.io_wait`. + io.write(...) + + # Will invoke `Fiber.scheduler&.kernel_sleep`. + sleep(n) +end.resume +``` + +We also introduce a new method which simplifies the creation of these +non-blocking fibers: + +``` ruby +Fiber.schedule do + puts Fiber.current.blocking? # false +end +``` + +The purpose of this method is to allow the scheduler to internally decide the +policy for when to start the fiber, and whether to use symmetric or asymmetric +fibers. + +You can also create blocking execution contexts: + +``` ruby +Fiber.new(blocking: true) do + # Won't use the scheduler: + sleep(n) +end +``` + +However you should generally avoid this unless you are implementing a scheduler. + +#### IO + +By default, I/O is non-blocking. Not all operating systems support non-blocking +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. + +#### Mutex + +The `Mutex` class can be used in a non-blocking context and is fiber specific. + +#### ConditionVariable + +The `ConditionVariable` class can be used in a non-blocking context and is +fiber-specific. + +#### Queue / SizedQueue + +The `Queue` and `SizedQueue` classes can be used in a non-blocking context and +are fiber-specific. + +#### Thread + +The `Thread#join` operation can be used in a non-blocking context and is +fiber-specific. diff --git a/ruby/doc/globals.rdoc b/ruby/doc/globals.rdoc index 89b94e9a8..1d7cda69f 100644 --- a/ruby/doc/globals.rdoc +++ b/ruby/doc/globals.rdoc @@ -50,9 +50,6 @@ $-p:: True if option -p is set. Read-only variable. == Pre-defined global constants -TRUE:: The typical true value. Deprecated. -FALSE:: The +false+ itself. Deprecated. -NIL:: The +nil+ itself. Deprecated. 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. diff --git a/ruby/doc/hacking.md b/ruby/doc/hacking.md new file mode 100644 index 000000000..5bbb04b17 --- /dev/null +++ b/ruby/doc/hacking.md @@ -0,0 +1,85 @@ +# Ruby Hacking Guide + +This document gives some helpful instructions which should make your experience as a Ruby core developer easier. + +## Setup + +### Make + +It's common to want to compile things as quickly as possible. Ensuring `make` has 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 +# On macOS with Fish shell: +export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu) + +# On macOS with Bash/ZSH shell: +export MAKEFLAGS="--jobs $(sysctl -n hw.ncpu)" + +# On Linux with Fish shell: +export MAKEFLAGS="--jobs "(nproc) + +# On Linux with Bash/ZSH shell: +export MAKEFLAGS="--jobs $(nproc)" +``` + +## Configure Ruby + +It's generally advisable to use a build directory. + +``` shell +./autogen.sh +mkdir build +cd build +../configure --prefix $HOME/.rubies/ruby-head +make install +``` + +### Without Documentation + +If you are frequently building Ruby, this will reduce the time it takes to `make install`. + +``` shell +../configure --disable-install-doc +``` + +## Running Ruby + +### Run Local Test Script + +You can create a file in the Ruby source root called `test.rb`. You can build `miniruby` and execute this script: + +``` shell +make run +``` + +If you want more of the standard library, you can use `runruby` instead of `run`. + +### Run Bootstrap Tests + +There are a set of tests in `bootstraptest/` which cover most basic features of the core Ruby language. + +``` shell +make test +``` + +### Run Extensive Tests + +There are extensive tests in `test/` which cover a wide range of features of the Ruby core language. + +``` shell +make test-all +``` + +You can run specific tests by specifying their path: + +``` shell +make test-all TESTS=../test/fiber/test_io.rb +``` + +### Run RubySpec Tests + +RubySpec is a project to write a complete, executable specification for the Ruby programming language. + +``` shell +make test-all test-rubyspec +``` diff --git a/ruby/doc/implicit_conversion.rdoc b/ruby/doc/implicit_conversion.rdoc new file mode 100644 index 000000000..0c2a1d497 --- /dev/null +++ b/ruby/doc/implicit_conversion.rdoc @@ -0,0 +1,198 @@ +== Implicit Conversions + +Some Ruby methods accept one or more objects +that can be either: +* Of a given class, and so accepted as is. +* Implicitly convertible to that class, in which case + the called method converts the object. + +For each of the relevant classes, the conversion is done by calling +a specific conversion method: + +* Array: +to_ary+ +* Hash: +to_hash+ +* Integer: +to_int+ +* String: +to_str+ + +=== Array-Convertible Objects + +An Array-convertible object is an object that: +* Has instance method +to_ary+. +* The method accepts no arguments. +* The method returns an object +obj+ for which obj.kind_of?(Array) returns +true+. + +The examples in this section use method Array#replace, +which accepts an Array-convertible argument. + +This class is Array-convertible: + + class ArrayConvertible + def to_ary + [:foo, 'bar', 2] + end + end + a = [] + a.replace(ArrayConvertible.new) # => [:foo, "bar", 2] + +This class is not Array-convertible (no +to_ary+ method): + + class NotArrayConvertible; end + a = [] + # Raises TypeError (no implicit conversion of NotArrayConvertible into Array) + a.replace(NotArrayConvertible.new) + +This class is not Array-convertible (method +to_ary+ takes arguments): + + class NotArrayConvertible + def to_ary(x) + [:foo, 'bar', 2] + end + end + a = [] + # Raises ArgumentError (wrong number of arguments (given 0, expected 1)) + a.replace(NotArrayConvertible.new) + +This class is not Array-convertible (method +to_ary+ returns non-Array): + + class NotArrayConvertible + def to_ary + :foo + end + end + a = [] + # Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol)) + a.replace(NotArrayConvertible.new) + +=== Hash-Convertible Objects + +A Hash-convertible object is an object that: +* Has instance method +to_hash+. +* The method accepts no arguments. +* The method returns an object +obj+ for which obj.kind_of?(Hash) returns +true+. + +The examples in this section use method Hash#merge, +which accepts a Hash-convertible argument. + +This class is Hash-convertible: + + class HashConvertible + def to_hash + {foo: 0, bar: 1, baz: 2} + end + end + h = {} + h.merge(HashConvertible.new) # => {:foo=>0, :bar=>1, :baz=>2} + +This class is not Hash-convertible (no +to_hash+ method): + + class NotHashConvertible; end + h = {} + # Raises TypeError (no implicit conversion of NotHashConvertible into Hash) + h.merge(NotHashConvertible.new) + +This class is not Hash-convertible (method +to_hash+ takes arguments): + + class NotHashConvertible + def to_hash(x) + {foo: 0, bar: 1, baz: 2} + end + end + h = {} + # Raises ArgumentError (wrong number of arguments (given 0, expected 1)) + h.merge(NotHashConvertible.new) + +This class is not Hash-convertible (method +to_hash+ returns non-Hash): + + class NotHashConvertible + def to_hash + :foo + end + end + h = {} + # Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol)) + h.merge(NotHashConvertible.new) + +=== Integer-Convertible Objects + +An Integer-convertible object is an object that: +* Has instance method +to_int+. +* The method accepts no arguments. +* The method returns an object +obj+ for which obj.kind_of?(Integer) returns +true+. + +The examples in this section use method Array.new, +which accepts an Integer-convertible argument. + +This user-defined class is Integer-convertible: + + class IntegerConvertible + def to_int + 3 + end + end + a = Array.new(IntegerConvertible.new).size + a # => 3 + +This class is not Integer-convertible (method +to_int+ takes arguments): + + class NotIntegerConvertible + def to_int(x) + 3 + end + end + # Raises ArgumentError (wrong number of arguments (given 0, expected 1)) + Array.new(NotIntegerConvertible.new) + +This class is not Integer-convertible (method +to_int+ returns non-Integer): + + class NotIntegerConvertible + def to_int + :foo + end + end + # Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol)) + Array.new(NotIntegerConvertible.new) + +=== String-Convertible Objects + +A String-convertible object is an object that: +* Has instance method +to_str+. +* The method accepts no arguments. +* The method returns an object +obj+ for which obj.kind_of?(String) returns +true+. + +The examples in this section use method String::new, +which accepts a String-convertible argument. + +This class is String-convertible: + + class StringConvertible + def to_str + 'foo' + end + end + String.new(StringConvertible.new) # => "foo" + +This class is not String-convertible (no +to_str+ method): + + class NotStringConvertible; end + # Raises TypeError (no implicit conversion of NotStringConvertible into String) + String.new(NotStringConvertible.new) + +This class is not String-convertible (method +to_str+ takes arguments): + + class NotStringConvertible + def to_str(x) + 'foo' + end + end + # Raises ArgumentError (wrong number of arguments (given 0, expected 1)) + String.new(NotStringConvertible.new) + +This class is not String-convertible (method +to_str+ returns non-String): + + class NotStringConvertible + def to_str + :foo + end + end + # Raises TypeError (can't convert NotStringConvertible to String (NotStringConvertible#to_str gives Symbol)) + String.new(NotStringConvertible.new) diff --git a/ruby/doc/irb/irb.rd.ja b/ruby/doc/irb/irb.rd.ja index 81247ce4b..633c08cbd 100644 --- a/ruby/doc/irb/irb.rd.ja +++ b/ruby/doc/irb/irb.rd.ja @@ -51,6 +51,12 @@ irbã®ä½¿ã„æ–¹ã¯, Rubyã•ãˆçŸ¥ã£ã¦ã„れã°ã„ãŸã£ã¦ç°¡å˜ã§ã™. 基本 オブジェクトã®ä½œæˆæ–¹æ³•ã‚’ 0 ã‹ã‚‰ 3 ã®ã„ãšã‚Œã‹ã«è¨­å®šã™ã‚‹. --echo å®Ÿè¡Œçµæžœã‚’表示ã™ã‚‹(デフォルト). --noecho å®Ÿè¡Œçµæžœã‚’表示ã—ãªã„. + --echo-on-assignment + 代入時ã«å®Ÿè¡Œçµæžœã‚’表示ã™ã‚‹. + --noecho-on-assignment + 代入時ã«å®Ÿè¡Œçµæžœã‚’表示ã—ãªã„. + --truncate-echo-on-assignment + 代入時ã«çœç•¥ã•れãŸå®Ÿè¡Œçµæžœã‚’表示ã™ã‚‹(デフォルト). --inspect çµæžœå‡ºåŠ›ã«inspectを用ã„ã‚‹. --noinspect çµæžœå‡ºåŠ›ã«inspectを用ã„ãªã„. --singleline シングルラインエディタを利用ã™ã‚‹. @@ -59,7 +65,10 @@ irbã®ä½¿ã„æ–¹ã¯, Rubyã•ãˆçŸ¥ã£ã¦ã„れã°ã„ãŸã£ã¦ç°¡å˜ã§ã™. 基本 用ã—よã†ã¨ã™ã‚‹. --colorize 色付ã‘を利用ã™ã‚‹. --nocolorize 色付ã‘を利用ã—ãªã„. - --prompt prompt-mode/--prompt-mode prompt-mode + --autocomplete オートコンプリートを利用ã™ã‚‹. + --noautocomplete オートコンプリートを利用ã—ãªã„. + --prompt prompt-mode + --prompt-mode prompt-mode プロンプトモードを切替ãˆã¾ã™. ç¾åœ¨å®šç¾©ã•れã¦ã„るプ ロンプトモードã¯, default, simple, xmp, inf-ruby㌠用æ„ã•れã¦ã„ã¾ã™. @@ -144,12 +153,12 @@ PROMPT_I, PROMPT_N, PROMPT_S, PROMPT_Cã¯, フォーマットを指定ã—ã¾ã™. 例ãˆã°, デフォルトã®ãƒ—ロンプトモードã¯: - IRB.conf[:PROMPT_MODE][:DEFAULT] = { + IRB.conf[:PROMPT][:DEFAULT] = { :PROMPT_I => "%N(%m):%03n:%i> ", :PROMPT_N => "%N(%m):%03n:%i> ", :PROMPT_S => "%N(%m):%03n:%i%l ", :PROMPT_C => "%N(%m):%03n:%i* ", - :RETURN => "%s\n" + :RETURN => "=> %s\n" } ã¨ãªã£ã¦ã„ã¾ã™. @@ -381,7 +390,7 @@ rubyã§ã¯, 以下ã®ãƒ—ログラムã¯ã‚¨ãƒ©ãƒ¼ã«ãªã‚Šã¾ã™. パイルã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«å¤‰æ•°ã‚’決定ã™ã‚‹ã‹ã‚‰ã§ã™. ãれã«å¯¾ã—, irbã¯å®Ÿè¡Œå¯èƒ½ã« ãªã‚‹(å¼ãŒé–‰ã˜ã‚‹)ã¨è‡ªå‹•çš„ã«è©•価ã—ã¦ã„ã‚‹ã‹ã‚‰ã§ã™. 上記ã®ä¾‹ã§ã¯, - evel "foo = 0" + eval "foo = 0" を行ãªã£ãŸæ™‚点ã§è©•価を行ãªã„, ãã®æ™‚点ã§å¤‰æ•°ãŒå®šç¾©ã•れるãŸã‚, 次å¼ã§ 変数fooã¯å®šç¾©ã•れã¦ã„ã‚‹ã‹ã‚‰ã§ã™. diff --git a/ruby/doc/keywords.rdoc b/ruby/doc/keywords.rdoc index a74126823..cb1cff33f 100644 --- a/ruby/doc/keywords.rdoc +++ b/ruby/doc/keywords.rdoc @@ -82,6 +82,8 @@ if:: in:: Used to separate the iterable object and iterator variable in a +for+ loop. See {control expressions}[rdoc-ref:syntax/control_expressions.rdoc] + It also serves as a pattern in a +case+ expression. + See {pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc] module:: Creates or opens a module. See {modules and classes diff --git a/ruby/doc/maintainers.rdoc b/ruby/doc/maintainers.rdoc index 98de9f254..b56a3d887 100644 --- a/ruby/doc/maintainers.rdoc +++ b/ruby/doc/maintainers.rdoc @@ -13,7 +13,7 @@ A module maintainer is responsible for a certain part of Ruby. * They have "developer" role on the Redmine to modify issues. * They have authority to decide the feature of their part. But they should always respect discussions on ruby-core/ruby-dev. -A submaintainer of a module is like a maintainer. But The submaintainer does +A submaintainer of a module is like a maintainer. But the submaintainer does not have authority to change/add a feature on his/her part. They need consensus on ruby-core/ruby-dev before changing/adding. Some of submaintainers have commit right, others don't. @@ -30,77 +30,17 @@ Koichi Sasada (ko1) Yukihiro Matsumoto (matz) -=== Documentation - -Zachary Scott (zzak) - == Standard Library Maintainers === Libraries -[lib/English.rb] - _unmaintained_ -[lib/abbrev.rb] - Akinori MUSHA (knu) -[lib/base64.rb] - Yusuke Endoh (mame) -[lib/drb.rb, lib/drb/*] - Masatoshi SEKI (seki) -[lib/debug.rb] - _unmaintained_ -[lib/erb.rb] - Masatoshi SEKI (seki), Takashi Kokubun (k0kubun) -[lib/find.rb] - Kazuki Tsujimoto (ktsj) [lib/mkmf.rb] _unmaintained_ -[lib/monitor.rb] - Shugo Maeda (shugo) -[lib/net/ftp.rb] - Shugo Maeda (shugo) -[lib/net/imap.rb] - Shugo Maeda (shugo) -[lib/net/http.rb, lib/net/https.rb] - NARUSE, Yui (naruse) -[lib/net/protocol.rb] - _unmaintained_ -[lib/open-uri.rb] - Tanaka Akira (akr) -[lib/optparse.rb, lib/optparse/*] - Nobuyuki Nakada (nobu) -[lib/pp.rb] - Tanaka Akira (akr) -[lib/prettyprint.rb] - Tanaka Akira (akr) -[lib/resolv-replace.rb] - Tanaka Akira (akr) -[lib/resolv.rb] - Tanaka Akira (akr) -[lib/rinda/*] - Masatoshi SEKI (seki) [lib/rubygems.rb, lib/rubygems/*] Eric Hodel (drbrain), Hiroshi SHIBATA (hsbt) https://github.com/rubygems/rubygems -[lib/set.rb] - Akinori MUSHA (knu) -[lib/securerandom.rb] - Tanaka Akira (akr) -[lib/shellwords.rb] - Akinori MUSHA (knu) -[lib/tempfile.rb] - _unmaintained_ -[lib/tmpdir.rb] - _unmaintained_ -[lib/time.rb] - Tanaka Akira (akr) -[lib/tsort.rb] - Tanaka Akira (akr) -[lib/un.rb] - WATANABE Hirofumi (eban) [lib/unicode_normalize.rb, lib/unicode_normalize/*] Martin J. Dürst -[lib/weakref.rb] - _unmaintained_ === Extensions @@ -108,56 +48,57 @@ Zachary Scott (zzak) Koichi Sasada (ko1) [ext/coverage] Yusuke Endoh (mame) -[ext/digest, ext/digest/*] - Akinori MUSHA (knu) [ext/fiber] Koichi Sasada (ko1) -[ext/io/nonblock] - Nobuyuki Nakada (nobu) -[ext/io/wait] - Nobuyuki Nakada (nobu) -[ext/nkf] - NARUSE, Yui (naruse) +[ext/monitor] + Koichi Sasada (ko1) [ext/objspace] _unmaintained_ -[ext/pathname] - Tanaka Akira (akr) [ext/pty] _unmaintained_ -[ext/readline] - TAKAO Kouji (kouji) [ext/ripper] _unmaintained_ [ext/socket] * Tanaka Akira (akr) * API change needs matz's approval -[ext/syslog] - Akinori MUSHA (knu) [ext/win32] NAKAMURA Usaku (usa) -[ext/win32ole] - Masaki Suketa (suke) == Default gems Maintainers === Libraries +[lib/abbrev.rb] + Akinori MUSHA (knu) + https://github.com/ruby/abbrev + https://rubygems.org/gems/abbrev +[lib/base64.rb] + Yusuke Endoh (mame) + https://github.com/ruby/base64 + https://rubygems.org/gems/base64 [lib/benchmark.rb] _unmaintained_ - https://github.com/bundler/benchmark + https://github.com/ruby/benchmark https://rubygems.org/gems/benchmark [lib/bundler.rb, lib/bundler/*] Hiroshi SHIBATA (hsbt) - https://github.com/bundler/bundler + https://github.com/rubygems/rubygems https://rubygems.org/gems/bundler [lib/cgi.rb, lib/cgi/*] - Takeyuki Fujioka (xibbar) + _unmaintained_ https://github.com/ruby/cgi https://rubygems.org/gems/cgi [lib/csv.rb] Kenta Murata (mrkn), Kouhei Sutou (kou) https://github.com/ruby/csv https://rubygems.org/gems/csv +[lib/English.rb] + _unmaintained_ + https://github.com/ruby/English + https://rubygems.org/gems/English +[lib/debug.rb] + _unmaintained_ + https://github.com/ruby/debug [lib/delegate.rb] _unmaintained_ https://github.com/ruby/delegate @@ -165,10 +106,27 @@ Zachary Scott (zzak) [lib/did_you_mean.rb] Yuki Nishijima (yuki24) https://github.com/ruby/did_you_mean + https://rubygems.org/gems/did_you_mean +[ext/digest, ext/digest/*] + 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) + https://github.com/ruby/erb + https://rubygems.org/gems/erb [lib/fileutils.rb] _unmaintained_ https://github.com/ruby/fileutils https://rubygems.org/gems/fileutils +[lib/find.rb] + Kazuki Tsujimoto (ktsj) + https://github.com/ruby/find + https://rubygems.org/gems/find [lib/forwardable.rb] Keiju ISHITSUKA (keiju) https://github.com/ruby/forwardable @@ -182,43 +140,51 @@ Zachary Scott (zzak) https://github.com/ruby/ipaddr https://rubygems.org/gems/ipaddr [lib/irb.rb, lib/irb/*] - Keiju ISHITSUKA (keiju) + 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/matrix.rb] - Marc-Andre Lafortune (marcandre) - https://github.com/ruby/matrix - https://rubygems.org/gems/matrix [lib/mutex_m.rb] Keiju ISHITSUKA (keiju) https://github.com/ruby/mutex_m https://rubygems.org/gems/mutex_m -[lib/net/pop.rb] - _unmaintained_ - https://github.com/ruby/net-pop - https://rubygems.org/gems/net-pop -[lib/net/smtp.rb] +[lib/net/http.rb, lib/net/https.rb] + NARUSE, Yui (naruse) + https://github.com/ruby/net-http + https://rubygems.org/gems/net-http +[lib/net/protocol.rb] _unmaintained_ - https://github.com/ruby/net-smtp - https://rubygems.org/gems/net-smtp + 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-Andre Lafortune (marcandre) + Marc-André Lafortune (marcandre) https://github.com/ruby/ostruct https://rubygems.org/gems/ostruct -[lib/prime.rb] - Yuki Sonoda (yugui) - https://github.com/ruby/prime +[lib/pp.rb] + Tanaka Akira (akr) + https://github.com/ruby/pp + https://rubygems.org/gems/pp +[lib/prettyprint.rb] + Tanaka Akira (akr) + https://github.com/ruby/prettyprint + https://rubygems.org/gems/prettyprint [lib/pstore.rb] _unmaintained_ https://github.com/ruby/pstore @@ -231,6 +197,14 @@ Zachary Scott (zzak) aycabta https://github.com/ruby/readline https://rubygems.org/gems/readline +[lib/resolv.rb] + 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 @@ -239,38 +213,66 @@ Zachary Scott (zzak) aycabta https://github.com/ruby/reline https://rubygems.org/gems/reline -[lib/rexml/*] - Kouhei Sutou (kou) - https://github.com/ruby/rexml - https://rubygems.org/gems/rexml -[lib/rss.rb, lib/rss/*] - Kouhei Sutou (kou) - https://github.com/ruby/rss - https://rubygems.org/gems/rss +[lib/rinda/*] + Masatoshi SEKI (seki) + https://github.com/ruby/rinda + https://rubygems.org/gems/rinda +[lib/securerandom.rb] + 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) + https://github.com/ruby/shellwords + https://rubygems.org/gems/shellwords [lib/singleton.rb] 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) + https://github.com/ruby/time + https://rubygems.org/gems/time [lib/timeout.rb] Yukihiro Matsumoto (matz) https://github.com/ruby/timeout + https://rubygems.org/gems/timeout [lib/thwait.rb] Keiju ISHITSUKA (keiju) https://github.com/ruby/thwait https://rubygems.org/gems/thwait -[lib/tracer.rb] - Keiju ISHITSUKA (keiju) - https://github.com/ruby/tracer +[lib/tmpdir.rb] + _unmaintained_ + https://github.com/ruby/tmpdir + https://rubygems.org/gems/tmpdir +[lib/tsort.rb] + Tanaka Akira (akr) + https://github.com/ruby/tsort + https://rubygems.org/gems/tsort +[lib/un.rb] + WATANABE Hirofumi (eban) + https://github.com/ruby/un + https://rubygems.org/gems/un [lib/uri.rb, lib/uri/*] YAMADA, Akira (akira) https://github.com/ruby/uri -[lib/webrick.rb, lib/webrick/*] - Eric Wong (normalperson) - https://bugs.ruby-lang.org/ - https://rubygems.org/gems/webrick + https://rubygems.org/gems/uri [lib/yaml.rb, lib/yaml/*] 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 @@ -286,10 +288,6 @@ Zachary Scott (zzak) _unmaintained_ https://github.com/ruby/date https://rubygems.org/gems/date -[ext/dbm] - _unmaintained_ - https://github.com/ruby/dbm - https://rubygems.org/gems/dbm [ext/etc] Ruby core team https://github.com/ruby/etc @@ -302,22 +300,34 @@ Zachary Scott (zzak) Aaron Patterson (tenderlove) https://github.com/ruby/fiddle https://rubygems.org/gems/fiddle -[ext/gdbm] - Yukihiro Matsumoto (matz) - https://github.com/ruby/gdbm - https://rubygems.org/gems/gdbm [ext/io/console] Nobuyuki Nakada (nobu) https://github.com/ruby/io-console https://rubygems.org/gems/io-console +[ext/io/nonblock] + Nobuyuki Nakada (nobu) + https://github.com/ruby/io-nonblock + https://rubygems.org/gems/io-nonblock +[ext/io/wait] + 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 [ext/openssl] Kazuki Yamaguchi (rhe) https://github.com/ruby/openssl https://rubygems.org/gems/openssl +[ext/pathname] + Tanaka Akira (akr) + https://github.com/ruby/pathname + https://rubygems.org/gems/pathname [ext/psych] Aaron Patterson (tenderlove), Hiroshi SHIBATA (hsbt) https://github.com/ruby/psych @@ -326,10 +336,10 @@ Zachary Scott (zzak) Aaron Patterson (tenderlove), Hiroshi SHIBATA (hsbt) https://github.com/ruby/racc https://rubygems.org/gems/racc -[ext/sdbm] - Yukihiro Matsumoto (matz) - https://github.com/ruby/sdbm - https://rubygems.org/gems/sdbm +[ext/readline] + TAKAO Kouji (kouji) + https://github.com/ruby/readline-ext + https://rubygems.org/gems/readline-ext [ext/stringio] Nobuyuki Nakada (nobu) https://github.com/ruby/stringio @@ -338,6 +348,14 @@ Zachary Scott (zzak) 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) https://github.com/ruby/zlib @@ -347,13 +365,50 @@ Zachary Scott (zzak) [minitest] https://github.com/seattlerb/minitest -[net-telnet] - https://github.com/ruby/net-telnet [power_assert] - https://github.com/k-tsj/power_assert + https://github.com/ruby/power_assert [rake] https://github.com/ruby/rake [test-unit] https://github.com/test-unit/test-unit -[xmlrpc] - https://github.com/ruby/xmlrpc +[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 + +=== Platform Maintainers + +[mswin64 (Microsoft Windows)] + NAKAMURA Usaku (usa) +[mingw32 (Minimalist GNU for Windows)] + Nobuyoshi Nakada (nobu) +[AIX] + Yutaka Kanemoto (kanemoto) +[FreeBSD] + Akinori MUSHA (knu) +[Solaris] + Naohisa Goto (ngoto) +[RHEL, CentOS] + KOSAKI Motohiro (kosaki) +[macOS] + Kenta Murata (mrkn) +[OpenBSD] + Jeremy Evans (jeremyevans0) +[cygwin, ...] + none. (Maintainer WANTED) diff --git a/ruby/doc/make_cheatsheet.md b/ruby/doc/make_cheatsheet.md new file mode 100644 index 000000000..6b056a4f0 --- /dev/null +++ b/ruby/doc/make_cheatsheet.md @@ -0,0 +1,124 @@ +# How to use "configure" and "make" commands for Ruby + +This is for developers of Ruby. +If you are a user of Ruby, please see README.md. + +## In-place build + +``` +$ ./autogen.sh +$ ./configure --prefix=$PWD/local +$ make +$ make install +$ ./local/bin/ruby -e 'puts "Hello"' +Hello +``` + +## Out-of-place build + +``` +$ ./autogen.sh +$ mkdir ../ruby-build +$ cd ../ruby-build +$ ../ruby-src/configure --prefix=$PWD/local +$ make +$ make install +$ ./local/bin/ruby -e 'puts "Hello"' +Hello +``` + +## How to run the whole test suite + +``` +$ make check +``` + +It runs (about) three test suites: + +* `make test` (a test suite for the interpreter core) +* `make test-all` (for all builtin classes and libraries) +* `make test-spec` (a conformance test suite for Ruby implementations) +* `make test-bundler` (a test suite for the bundler examples) + +## How to run the test suite with log + +``` +$ make test OPTS=-v + +$ make test-all TESTS=-v + +$ make test-spec MSPECOPT=-Vfs +``` + +## How to run a part of the test suite + +### Runs a directory +``` +$ make test-all TESTS=test/rubygems +$ make test-all TESTS=rubygems +``` + +### Runs a file +``` +$ make test-all TESTS=test/ruby/test_foo.rb +$ make test-all TESTS=ruby/foo +``` + +### Runs a test whose name includes test_bar +``` +$ make test-all TESTS="test/ruby/test_foo.rb -n /test_bar/" +``` + +### Runs a file or directory with GNU make +``` +$ make test/ruby/test_foo.rb +$ make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/" +``` + +### Runs a ruby-spec directory +``` +$ make test-spec MSPECOPT=spec/ruby/core/foo +``` + +### Runs a ruby-spec file +``` +$ make test-spec MSPECOPT=spec/ruby/core/foo/bar_spec.rb +``` + +### Runs a ruby-spec file or directory with GNU make +``` +$ make spec/ruby/core/foo/bar_spec.rb +``` + +### Runs a bundler spec file +``` +$ make test-bundler BUNDLER_SPECS=commands/exec_spec.rb:58 +``` + +## How to measure coverage of C and Ruby code + +You need to be able to use gcc (gcov) and lcov visualizer. + +``` +$ ./autogen.sh +$ ./configure --enable-gcov +$ make +$ make update-coverage +$ rm -f test-coverage.dat +$ make test-all COVERAGE=true +$ 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 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 + +## How to benchmark + +see https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark diff --git a/ruby/doc/marshal.rdoc b/ruby/doc/marshal.rdoc index a51f1bf87..abf946726 100644 --- a/ruby/doc/marshal.rdoc +++ b/ruby/doc/marshal.rdoc @@ -73,7 +73,7 @@ The first byte has the following special values: a positive little-endian integer. "\xfd":: - The total size of the integer is two bytes. The following three bytes are a + The total size of the integer is four bytes. The following three bytes are a negative little-endian integer. "\x04":: @@ -83,7 +83,7 @@ The first byte has the following special values: of stream objects full precision may be used. "\xfc":: - The total size of the integer is two bytes. The following four bytes are a + The total size of the integer is five bytes. The following four bytes are a negative little-endian integer. For compatibility with 32 bit ruby, only Fixnums greater than -10737341824 should be represented this way. For sizes of stream objects full precision may be used. diff --git a/ruby/doc/memory_view.md b/ruby/doc/memory_view.md new file mode 100644 index 000000000..a24700d0b --- /dev/null +++ b/ruby/doc/memory_view.md @@ -0,0 +1,167 @@ +# MemoryView + +MemoryView provides the features to share multidimensional homogeneous arrays of +fixed-size element on memory among extension libraries. + +## Disclaimer + +* This feature is still experimental. The specification described here can be changed in the future. + +* This document is under construction. Please refer the master branch of ruby for the latest version of this document. + +## Overview + +We sometimes deal with certain kinds of objects that have arrays of the same typed fixed-size elements on a contiguous memory area as its internal representation. +Numo::NArray in numo-narray and Magick::Image in rmagick are typical examples of such objects. +MemoryView plays the role of the hub to share the internal data of such objects without copy among such libraries. + +Copy-less sharing of data is very important in some field such as data analysis, machine learning, and image processing. In these field, people need to handle large amount of on-memory data with several libraries. If we are forced to copy to exchange large data among libraries, a large amount of the data processing time must be occupied by copying data. You can avoid such wasting time by using MemoryView. + +MemoryView has two categories of APIs: + +1. Producer API + + Classes can register own MemoryView entry which allows objects of that classes to expose their MemoryView + +2. Consumer API + + Consumer API allows us to obtain and manage the MemoryView of an object + +## MemoryView structure + +A MemoryView structure, `rb_memory_view_t`, is used for exporting objects' MemoryView. +This structure contains the reference of the object, which is the owner of the MemoryView, the pointer to the head of exported memory, and the metadata that describes the structure of the memory. The metadata can describe multidimensional arrays with strides. + +### The member of MemoryView structure + +The MemoryView structure consists of the following members. + +- `VALUE obj` + + The reference to the original object that has the memory exported via the MemoryView. + + RubyVM manages the reference count of the MemoryView-exported objects to guard them from the garbage collection. The consumers do not have to struggle to guard this object from GC. + +- `void *data` + + The pointer to the head of the exported memory. + +- `ssize_t byte_size` + + The numbero f bytes in the memory pointed by `data`. + +- `bool readonly` + + `true` for readonly memory, `false` for writable memory. + +- `const char *format` + + A string to describeth e format of an element, or NULL for unsigned byte. + +- `ssize_t item_size` + + The number of bytes in each element. + +- `const rb_memory_view_item_component_t *item_desc.components` + + The array of the metadata of the component in an element. + +- `size_t item_desc.length` + + The number of items in `item_desc.components`. + +- `ssize_t ndim` + + The number of dimensions. + +- `const ssize_t *shape` + + A `ndim` size array indicating the number of elements in each dimension. + This can be `NULL` when `ndim` is 1. + +- `const ssize_t *strides` + + A `ndim` size array indicating the number of bytes to skip to go to the next element in each dimension. + This can be `NULL` when `ndim` is 1. + +- `const ssize_t *sub_offsets` + + A `ndim` size array consisting of the offsets in each dimension when the MemoryView exposes a nested array. + This can be `NULL` when the MemoryView exposes a flat array. + +- `void *private_data` + + The private data that MemoryView provider uses internally. + This can be `NULL` when any private data is unnecessary. + +## MemoryView APIs + +### For consumers + +- `bool rb_memory_view_available_p(VALUE obj)` + + Return `true` if `obj` supports to export a MemoryView. Return `false` otherwise. + + If this function returns `true`, it doesn't mean the function `rb_memory_view_get` will succeed. + +- `bool rb_memory_view_get(VALUE obj, rb_memory_view_t *view, int flags)` + + If the given `obj` supports to export a MemoryView that conforms the given `flags`, this function fills `view` by the information of the MemoryView and returns `true`. In this case, the reference count of `obj` is increased. + + If the given combination of `obj` and `flags` cannot export a MemoryView, this function returns `false`. The content of `view` is not touched in this case. + + The exported MemoryView must be released by `rb_memory_view_release` when the MemoryView is no longer needed. + +- `bool rb_memory_view_release(rb_memory_view_t *view)` + + Release the given MemoryView `view` and decrement the reference count of `view->obj`. + + Consumers must call this function when the MemoryView is no longer needed. Missing to call this function leads memory leak. + +- `ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err)` + + Calculate the number of bytes occupied by an element. + + When the calculation fails, the failed location in `format` is stored into `err`, and returns `-1`. + +- `void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices)` + + Calculate the location of the item indicated by the given `indices`. + The length of `indices` must equal to `view->ndim`. + This function initializes `view->item_desc` if needed. + +- `VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)` + + Return the Ruby object representation of the item indicated by the given `indices`. + The length of `indices` must equal to `view->ndim`. + This function uses `rb_memory_view_get_item_pointer`. + +- `rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)` + + Fill the members of `view` as an 1-dimensional byte array. + +- `void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)` + + Fill the `strides` array with byte-Strides of a contiguous array of the given shape with the given element size. + +- `void rb_memory_view_prepare_item_desc(rb_memory_view_t *view)` + + Fill the `item_desc` member of `view`. + +- `bool rb_memory_view_is_contiguous(const rb_memory_view_t *view)` + + Return `true` if the data in the MemoryView `view` is row-major or column-major contiguous. + + Return `false` otherwise. + +- `bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view)` + + Return `true` if the data in the MemoryView `view` is row-major contiguous. + + Return `false` otherwise. + +- `bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view)` + + Return `true` if the data in the MemoryView `view` is column-major contiguous. + + Return `false` otherwise. diff --git a/ruby/doc/optparse/argument_converters.rdoc b/ruby/doc/optparse/argument_converters.rdoc new file mode 100644 index 000000000..ac659da8c --- /dev/null +++ b/ruby/doc/optparse/argument_converters.rdoc @@ -0,0 +1,380 @@ +== Argument Converters + +An option can specify that its argument is to be converted +from the default \String to an instance of another class. + +=== Contents + +- {Built-In Argument Converters}[#label-Built-In+Argument+Converters] + - {Date}[#label-Date] + - {DateTime}[#label-DateTime] + - {Time}[#label-Time] + - {URI}[#label-URI] + - {Shellwords}[#label-Shellwords] + - {Integer}[#label-Integer] + - {Float}[#label-Float] + - {Numeric}[#label-Numeric] + - {DecimalInteger}[#label-DecimalInteger] + - {OctalInteger}[#label-OctalInteger] + - {DecimalNumeric}[#label-DecimalNumeric] + - {TrueClass}[#label-TrueClass] + - {FalseClass}[#label-FalseClass] + - {Object}[#label-Object] + - {String}[#label-String] + - {Array}[#label-Array] + - {Regexp}[#label-Regexp] +- {Custom Argument Converters}[#label-Custom+Argument+Converters] + +=== Built-In Argument Converters + +\OptionParser has a number of built-in argument converters, +which are demonstrated below. + +==== \Date + +File +date.rb+ +defines an option whose argument is to be converted to a \Date object. +The argument is converted by method Date#parse. + + :include: ruby/date.rb + +Executions: + + $ ruby date.rb --date 2001-02-03 + [#, Date] + $ ruby date.rb --date 20010203 + [#, Date] + $ ruby date.rb --date "3rd Feb 2001" + [#, Date] + +==== \DateTime + +File +datetime.rb+ +defines an option whose argument is to be converted to a \DateTime object. +The argument is converted by method DateTime#parse. + + :include: ruby/datetime.rb + +Executions: + + $ ruby datetime.rb --datetime 2001-02-03T04:05:06+07:00 + [#, DateTime] + $ ruby datetime.rb --datetime 20010203T040506+0700 + [#, DateTime] + $ ruby datetime.rb --datetime "3rd Feb 2001 04:05:06 PM" + [#, DateTime] + +==== \Time + +File +time.rb+ +defines an option whose argument is to be converted to a \Time object. +The argument is converted by method Time#httpdate or Time#parse. + + :include: ruby/time.rb + +Executions: + + $ ruby time.rb --time "Thu, 06 Oct 2011 02:26:12 GMT" + [2011-10-06 02:26:12 UTC, Time] + $ ruby time.rb --time 2010-10-31 + [2010-10-31 00:00:00 -0500, Time] + +==== \URI + +File +uri.rb+ +defines an option whose argument is to be converted to a \URI object. +The argument is converted by method URI#parse. + + :include: ruby/uri.rb + +Executions: + + $ ruby uri.rb --uri https://github.com + [#, URI::HTTPS] + $ ruby uri.rb --uri http://github.com + [#, URI::HTTP] + $ ruby uri.rb --uri file://~/var + [#, URI::File] + +==== \Shellwords + +File +shellwords.rb+ +defines an option whose argument is to be converted to an \Array object by method +Shellwords#shellwords. + + :include: ruby/shellwords.rb + +Executions: + + $ ruby shellwords.rb --shellwords "ruby my_prog.rb | less" + [["ruby", "my_prog.rb", "|", "less"], Array] + $ ruby shellwords.rb --shellwords "here are 'two words'" + [["here", "are", "two words"], Array] + +==== \Integer + +File +integer.rb+ +defines an option whose argument is to be converted to an \Integer object. +The argument is converted by method Kernel#Integer. + + :include: ruby/integer.rb + +Executions: + + $ ruby integer.rb --integer 100 + [100, Integer] + $ ruby integer.rb --integer -100 + [-100, Integer] + $ ruby integer.rb --integer 0100 + [64, Integer] + $ ruby integer.rb --integer 0x100 + [256, Integer] + $ ruby integer.rb --integer 0b100 + [4, Integer] + +==== \Float + +File +float.rb+ +defines an option whose argument is to be converted to a \Float object. +The argument is converted by method Kernel#Float. + + :include: ruby/float.rb + +Executions: + + $ ruby float.rb --float 1 + [1.0, Float] + $ ruby float.rb --float 3.14159 + [3.14159, Float] + $ ruby float.rb --float 1.234E2 + [123.4, Float] + $ ruby float.rb --float 1.234E-2 + [0.01234, Float] + +==== \Numeric + +File +numeric.rb+ +defines an option whose argument is to be converted to an instance +of \Rational, \Float, or \Integer. +The argument is converted by method Kernel#Rational, +Kernel#Float, or Kernel#Integer. + + :include: ruby/numeric.rb + +Executions: + + $ ruby numeric.rb --numeric 1/3 + [(1/3), Rational] + $ ruby numeric.rb --numeric 3.333E-1 + [0.3333, Float] + $ ruby numeric.rb --numeric 3 + [3, Integer] + +==== \DecimalInteger + +File +decimal_integer.rb+ +defines an option whose argument is to be converted to an \Integer object. +The argument is converted by method Kernel#Integer. + + :include: ruby/decimal_integer.rb + +The argument may not be in a binary or hexadecimal format; +a leading zero is ignored (not parsed as octal). + +Executions: + + $ ruby decimal_integer.rb --decimal_integer 100 + [100, Integer] + $ ruby decimal_integer.rb --decimal_integer -100 + [-100, Integer] + $ ruby decimal_integer.rb --decimal_integer 0100 + [100, Integer] + $ ruby decimal_integer.rb --decimal_integer -0100 + [-100, Integer] + +==== \OctalInteger + +File +octal_integer.rb+ +defines an option whose argument is to be converted to an \Integer object. +The argument is converted by method Kernel#Integer. + + :include: ruby/octal_integer.rb + +The argument may not be in a binary or hexadecimal format; +it is parsed as octal, regardless of whether it has a leading zero. + +Executions: + + $ ruby octal_integer.rb --octal_integer 100 + [64, Integer] + $ ruby octal_integer.rb --octal_integer -100 + [-64, Integer] + $ ruby octal_integer.rb --octal_integer 0100 + [64, Integer] + +==== \DecimalNumeric + +File +decimal_numeric.rb+ +defines an option whose argument is to be converted to an \Integer object. +The argument is converted by method Kernel#Integer + + :include: ruby/decimal_numeric.rb + +The argument may not be in a binary or hexadecimal format; +a leading zero causes the argument to be parsed as octal. + +Executions: + + $ ruby decimal_numeric.rb --decimal_numeric 100 + [100, Integer] + $ ruby decimal_numeric.rb --decimal_numeric -100 + [-100, Integer] + $ ruby decimal_numeric.rb --decimal_numeric 0100 + [64, Integer] + +==== \TrueClass + +File +true_class.rb+ +defines an option whose argument is to be converted to +true+ or +false+. +The argument is evaluated by method Object#nil?. + + :include: ruby/true_class.rb + +The argument may be any of those shown in the examples below. + +Executions: + + $ ruby true_class.rb --true_class true + [true, TrueClass] + $ ruby true_class.rb --true_class yes + [true, TrueClass] + $ ruby true_class.rb --true_class + + [true, TrueClass] + $ ruby true_class.rb --true_class false + [false, FalseClass] + $ ruby true_class.rb --true_class no + [false, FalseClass] + $ ruby true_class.rb --true_class - + [false, FalseClass] + $ ruby true_class.rb --true_class nil + [false, FalseClass] + +==== \FalseClass + +File +false_class.rb+ +defines an option whose argument is to be converted to +true+ or +false+. +The argument is evaluated by method Object#nil?. + + :include: ruby/false_class.rb + +The argument may be any of those shown in the examples below. + +Executions: + + $ ruby false_class.rb --false_class false + [false, FalseClass] + $ ruby false_class.rb --false_class no + [false, FalseClass] + $ ruby false_class.rb --false_class - + [false, FalseClass] + $ ruby false_class.rb --false_class nil + [false, FalseClass] + $ ruby false_class.rb --false_class true + [true, TrueClass] + $ ruby false_class.rb --false_class yes + [true, TrueClass] + $ ruby false_class.rb --false_class + + [true, TrueClass] + +==== \Object + +File +object.rb+ +defines an option whose argument is not to be converted from \String. + + :include: ruby/object.rb + +Executions: + + $ ruby object.rb --object foo + ["foo", String] + $ ruby object.rb --object nil + ["nil", String] + +==== \String + +File +string.rb+ +defines an option whose argument is not to be converted from \String. + + :include: ruby/string.rb + +Executions: + + $ ruby string.rb --string foo + ["foo", String] + $ ruby string.rb --string nil + ["nil", String] + +==== \Array + +File +array.rb+ +defines an option whose argument is to be converted from \String +to an array of strings, based on comma-separated substrings. + + :include: ruby/array.rb + +Executions: + + $ ruby array.rb --array "" + [[], Array] + $ ruby array.rb --array foo,bar,baz + [["foo", "bar", "baz"], Array] + $ ruby array.rb --array "foo, bar, baz" + [["foo", " bar", " baz"], Array] + +==== \Regexp + +File +regexp.rb+ +defines an option whose argument is to be converted to a \Regexp object. + + :include: ruby/regexp.rb + +Executions: + + $ ruby regexp.rb --regexp foo + +=== Custom Argument Converters + +You can create custom argument converters. +To create a custom converter, call OptionParser#accept with: + +- An identifier, which may be any object. +- An optional match pattern, which defaults to /.*/m. +- A block that accepts the argument and returns the converted value. + +This custom converter accepts any argument and converts it, +if possible, to a \Complex object. + + :include: ruby/custom_converter.rb + +Executions: + + $ ruby custom_converter.rb --complex 0 + [(0+0i), Complex] + $ ruby custom_converter.rb --complex 1 + [(1+0i), Complex] + $ ruby custom_converter.rb --complex 1+2i + [(1+2i), Complex] + $ ruby custom_converter.rb --complex 0.3-0.5i + [(0.3-0.5i), Complex] + +This custom converter accepts any 1-word argument +and capitalizes it, if possible. + + :include: ruby/match_converter.rb + +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) diff --git a/ruby/doc/optparse/creates_option.rdoc b/ruby/doc/optparse/creates_option.rdoc new file mode 100644 index 000000000..ad52c6671 --- /dev/null +++ b/ruby/doc/optparse/creates_option.rdoc @@ -0,0 +1,7 @@ +Creates an option from the given parameters +params+. +See {Parameters for New Options}[./option_params.rdoc]. + +The block, if given, is the handler for the created option. +When the option is encountered during command-line parsing, +the block is called with the argument given for the option, if any. +See {Option Handlers}[./option_params.rdoc#label-Option+Handlers]. diff --git a/ruby/doc/optparse/option_params.rdoc b/ruby/doc/optparse/option_params.rdoc new file mode 100644 index 000000000..b2e4e1a33 --- /dev/null +++ b/ruby/doc/optparse/option_params.rdoc @@ -0,0 +1,509 @@ +== Parameters for New Options + +Option-creating methods in \OptionParser +accept arguments that determine the behavior of a new option: + +- OptionParser#on +- OptionParser#on_head +- OptionParser#on_tail +- OptionParser#define +- OptionParser#define_head +- OptionParser#define_tail +- OptionParser#make_switch + +The code examples on this page use: + +- OptionParser#on, to define options. +- OptionParser#parse!, to parse the command line. +- Built-in option --help, to display defined options. + +Contents: + +- {Option Names}[#label-Option+Names] + - {Short Names}[#label-Short+Names] + - {Simple Short Names}[#label-Simple+Short+Names] + - {Short Names with Required Arguments}[#label-Short+Names+with+Required+Arguments] + - {Short Names with Optional Arguments}[#label-Short+Names+with+Optional+Arguments] + - {Short Names from Range}[#label-Short+Names+from+Range] + - {Long Names}[#label-Long+Names] + - {Simple Long Names}[#label-Simple+Long+Names] + - {Long Names with Required Arguments}[#label-Long+Names+with+Required+Arguments] + - {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 Values}[#label-Argument+Values] + - {Explicit Argument Values}[#label-Explicit+Argument+Values] + - {Explicit Values in Array}[#label-Explicit+Values+in+Array] + - {Explicit Values in Hash}[#label-Explicit+Values+in+Hash] + - {Argument Value Patterns}[#label-Argument+Value+Patterns] +- {Argument Converters}[#label-Argument+Converters] +- {Descriptions}[#label-Descriptions] +- {Option Handlers}[#label-Option+Handlers] + - {Handler Blocks}[#label-Handler+Blocks] + - {Handler Procs}[#label-Handler+Procs] + - {Handler Methods}[#label-Handler+Methods] + +=== Option Names + +There are two kinds of option names: + +- Short option name, consisting of a single hyphen and a single character. +- Long option name, consisting of two hyphens and one or more characters. + +==== Short Names + +===== Simple Short Names + +File +short_simple.rb+ defines two options: + +- One with short name -x. +- The other with two short names, in effect, aliases, -1 and -%. + + :include: ruby/short_simple.rb + +Executions: + + $ ruby short_simple.rb --help + Usage: short_simple [options] + -x One short name + -1, -% Two short names (aliases) + $ ruby short_simple.rb -x + ["-x", true] + $ ruby short_simple.rb -1 -x -% + ["-1 or -%", true] + ["-x", true] + ["-1 or -%", true] + +===== Short Names with Required Arguments + +A short name followed (no whitespace) by a dummy word +defines an option that requires an argument. + +File +short_required.rb+ defines an option -x +that requires an argument. + + :include: ruby/short_required.rb + +Executions: + + $ ruby short_required.rb --help + 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) + $ ruby short_required.rb -x FOO + ["-x", "FOO"] + +===== Short Names with Optional Arguments + +A short name followed (with whitespace) by a dummy word in square brackets +defines an option that allows an optional argument. + +File +short_optional.rb+ defines an option -x +that allows an optional argument. + + :include: ruby/short_optional.rb + +Executions: + + $ ruby short_optional.rb --help + Usage: short_optional [options] + -x [XXX] Short name with optional argument + $ ruby short_optional.rb -x + ["-x", nil] + $ ruby short_optional.rb -x FOO + ["-x", "FOO"] + +===== Short Names from Range + +You can define an option with multiple short names +taken from a range of characters. +The parser yields both the actual character cited and the value. + +File +short_range.rb+ defines an option with short names +for all printable characters from ! to ~: + + :include: ruby/short_range.rb + +Executions: + + $ ruby short_range.rb --help + Usage: short_range [options] + -[!-~] Short names in (very large) range + $ ruby short_range.rb -! + ["!-~", "!", nil] + $ ruby short_range.rb -! + ["!-~", "!", nil] + $ ruby short_range.rb -A + ["!-~", "A", nil] + $ ruby short_range.rb -z + ["!-~", "z", nil] + +==== Long Names + +===== Simple Long Names + +File +long_simple.rb+ defines two options: + +- One with long name -xxx. +- The other with two long names, in effect, aliases, + --y1% and --z2#. + + :include: ruby/long_simple.rb + +Executions: + + $ ruby long_simple.rb --help + Usage: long_simple [options] + --xxx One long name + --y1%, --z2# Two long names (aliases) + $ ruby long_simple.rb --xxx + ["--xxx", true] + $ ruby long_simple.rb --y1% --xxx --z2# + ["--y1% or --z2#", true] + ["--xxx", true] + ["--y1% or --z2#", true] + +===== Long Names with Required Arguments + +A long name followed (with whitespace) by a dummy word +defines an option that requires an argument. + +File +long_required.rb+ defines an option --xxx +that requires an argument. + + :include: ruby/long_required.rb + +Executions: + + $ ruby long_required.rb --help + 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) + $ ruby long_required.rb --xxx FOO + ["--xxx", "FOO"] + +===== Long Names with Optional Arguments + +A long name followed (with whitespace) by a dummy word in square brackets +defines an option that allows an optional argument. + +File +long_optional.rb+ defines an option --xxx +that allows an optional argument. + + :include: ruby/long_optional.rb + +Executions: + + $ ruby long_optional.rb --help + Usage: long_optional [options] + --xxx [XXX] Long name with optional argument + $ ruby long_optional.rb --xxx + ["--xxx", nil] + $ ruby long_optional.rb --xxx FOO + ["--xxx", "FOO"] + +===== Long Names with Negation + +A long name may be defined with both positive and negative senses. + +File +long_with_negation.rb+ defines an option that has both senses. + + :include: ruby/long_with_negation.rb + +Executions: + + $ ruby long_with_negation.rb --help + Usage: long_with_negation [options] + --[no-]binary Long name with negation + $ ruby long_with_negation.rb --binary + [true, TrueClass] + $ ruby long_with_negation.rb --no-binary + [false, FalseClass] + +==== Mixed Names + +An option may have both short and long names. + +File +mixed_names.rb+ defines a mixture of short and long names. + + :include: ruby/mixed_names.rb + +Executions: + + $ ruby mixed_names.rb --help +Usage: mixed_names [options] + -x, --xxx Short and long, no argument + -y, --yyyYYY Short and long, required argument + -z, --zzz [ZZZ] Short and long, optional argument + $ ruby mixed_names.rb -x + ["--xxx", true] + $ ruby mixed_names.rb --xxx + ["--xxx", true] + $ ruby mixed_names.rb -y + 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) + $ ruby mixed_names.rb --yyy BAR + ["--yyy", "BAR"] + $ ruby mixed_names.rb -z + ["--zzz", nil] + $ ruby mixed_names.rb -z BAZ + ["--zzz", "BAZ"] + $ ruby mixed_names.rb --zzz + ["--zzz", nil] + $ ruby mixed_names.rb --zzz BAT + ["--zzz", "BAT"] + +=== Argument Keywords + +As seen above, a given option name string may itself +indicate whether the option has no argument, a required argument, +or an optional argument. + +An alternative is to use a separate symbol keyword, +which is one of :NONE (the default), +:REQUIRED, :OPTIONAL. + +File +argument_keywords.rb+ defines an option with a required argument. + + :include: ruby/argument_keywords.rb + +Executions: + + $ ruby argument_keywords.rb --help + Usage: argument_keywords [options] + -x, --xxx Required argument + $ ruby argument_styles.rb --xxx + argument_styles.rb:6:in `
': missing argument: --xxx (OptionParser::MissingArgument) + $ ruby argument_styles.rb --xxx FOO + ["--xxx", "FOO"] + +=== Argument Strings + +Still another way to specify a required argument +is to define it in a string separate from the name string. + +File +argument_strings.rb+ defines an option with a required argument. + + :include: ruby/argument_strings.rb + +Executions: + + $ ruby argument_strings.rb --help + Usage: argument_strings [options] + -x, --xxx=XXX Required argument + $ ruby argument_strings.rb --xxx + argument_strings.rb:9:in `
': missing argument: --xxx (OptionParser::MissingArgument) + $ ruby argument_strings.rb --xxx FOO + ["--xxx", "FOO"] + +=== Argument Values + +Permissible argument values may be restricted +either by specifying explicit values +or by providing a pattern that the given value must match. + +==== Explicit Argument Values + +You can specify argument values in either of two ways: + +- Specify values an array of strings. +- Specify values a hash. + +===== Explicit Values in Array + +You can specify explicit argument values in an array of strings. +The argument value must be one of those strings, or an unambiguous abbreviation. + +File +explicit_array_values.rb+ defines options with explicit argument values. + + :include: ruby/explicit_array_values.rb + +Executions: + + $ ruby explicit_array_values.rb --help + Usage: explicit_array_values [options] + -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) + $ ruby explicit_array_values.rb -x foo + ["-x", "foo"] + $ ruby explicit_array_values.rb -x f + ["-x", "foo"] + $ 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) + $ ruby explicit_array_values.rb -x baz + explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + + +===== Explicit Values in Hash + +You can specify explicit argument values in a hash with string keys. +The value passed must be one of those keys, or an unambiguous abbreviation; +the value yielded will be the value for that key. + +File +explicit_hash_values.rb+ defines options with explicit argument values. + + :include: ruby/explicit_hash_values.rb + +Executions: + + $ ruby explicit_hash_values.rb --help + Usage: explicit_hash_values [options] + -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) + $ ruby explicit_hash_values.rb -x foo + ["-x", 0] + $ ruby explicit_hash_values.rb -x f + ["-x", 0] + $ 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) + $ ruby explicit_hash_values.rb -y + ["-y", nil] + $ ruby explicit_hash_values.rb -y baz + ["-y", 2] + $ 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) + $ 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. + +File +matched_values.rb+ defines options with matched argument values. + + :include: ruby/matched_values.rb + +Executions: + + $ ruby matched_values.rb --help + Usage: matched_values [options] + --xxx XXX Matched values + $ 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) + +=== Argument Converters + +An option can specify that its argument is to be converted +from the default \String to an instance of another class. + +There are a number of built-in converters. +You can also define custom converters. + +See {Argument Converters}[./argument_converters.rdoc]. + +=== Descriptions + +A description parameter is any string parameter +that is not recognized as an +{option name}[#label-Option+Names] or a +{terminator}[#label-Terminators]; +in other words, it does not begin with a hypnen. + +You may give any number of description parameters; +each becomes a line in the text generated by option --help. + +File +descriptions.rb+ has six strings in its array +descriptions+. +These are all passed as parameters to OptionParser#on, so that they +all, line for line, become the option's description. + + :include: ruby/descriptions.rb + +Executions: + + $ ruby descriptions.rb --help + Usage: descriptions [options] + --xxx Lorem ipsum dolor sit amet, consectetuer + adipiscing elit. Aenean commodo ligula eget. + Aenean massa. Cum sociis natoque penatibus + et magnis dis parturient montes, nascetur + ridiculus mus. Donec quam felis, ultricies + nec, pellentesque eu, pretium quis, sem. + $ ruby descriptions.rb --xxx + ["--xxx", true] + +=== Option Handlers + +The handler for an option is an executable that will be called +when the option is encountered. The handler may be: + +- A block (this is most often seen). +- A proc. +- A method. + +==== Handler Blocks + +An option hadler may be a block. + +File +block.rb+ defines an option that has a handler block. + + :include: ruby/block.rb + +Executions: + + $ ruby block.rb --help + Usage: block [options] + --xxx Option with no argument + --yyy YYY Option with required argument + $ ruby block.rb --xxx + ["Handler block for -xxx called with value:", true] + $ ruby block.rb --yyy FOO + ["Handler block for -yyy called with value:", "FOO"] + +==== Handler Procs + +An option handler may be a Proc. + +File +proc.rb+ defines an option that has a handler proc. + + :include: ruby/proc.rb + +Executions: + + $ ruby proc.rb --help + Usage: proc [options] + --xxx Option with no argument + --yyy YYY Option with required argument + $ ruby proc.rb --xxx + ["Handler proc for -xxx called with value:", true] + $ ruby proc.rb --yyy FOO + ["Handler proc for -yyy called with value:", "FOO"] + +==== Handler Methods + +An option handler may be a Method. + +File +proc.rb+ defines an option that has a handler method. + + :include: ruby/method.rb + +Executions: + + $ ruby method.rb --help + Usage: method [options] + --xxx Option with no argument + --yyy YYY Option with required argument + $ ruby method.rb --xxx + ["Handler method for -xxx called with value:", true] + $ ruby method.rb --yyy FOO + ["Handler method for -yyy called with value:", "FOO"] diff --git a/ruby/doc/optparse/ruby/argument_keywords.rb b/ruby/doc/optparse/ruby/argument_keywords.rb new file mode 100644 index 000000000..8533257c6 --- /dev/null +++ b/ruby/doc/optparse/ruby/argument_keywords.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', :REQUIRED, 'Required argument') do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/argument_strings.rb b/ruby/doc/optparse/ruby/argument_strings.rb new file mode 100644 index 000000000..77861dda3 --- /dev/null +++ b/ruby/doc/optparse/ruby/argument_strings.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', '=XXX', 'Required argument') do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/argv.rb b/ruby/doc/optparse/ruby/argv.rb new file mode 100644 index 000000000..12495cfa1 --- /dev/null +++ b/ruby/doc/optparse/ruby/argv.rb @@ -0,0 +1,2 @@ +p ARGV + diff --git a/ruby/doc/optparse/ruby/array.rb b/ruby/doc/optparse/ruby/array.rb new file mode 100644 index 000000000..7c6c14fad --- /dev/null +++ b/ruby/doc/optparse/ruby/array.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--array=ARRAY', Array) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/basic.rb b/ruby/doc/optparse/ruby/basic.rb new file mode 100644 index 000000000..91d37627c --- /dev/null +++ b/ruby/doc/optparse/ruby/basic.rb @@ -0,0 +1,17 @@ +# Require the OptionParser code. +require 'optparse' +# Create an OptionParser object. +parser = OptionParser.new +# Define one or more options. +parser.on('-x', 'Whether to X') do |value| + p ['x', value] +end +parser.on('-y', 'Whether to Y') do |value| + p ['y', value] +end +parser.on('-z', 'Whether to Z') do |value| + p ['z', value] +end +# Parse the command line and return pared-down ARGV. +p parser.parse! + diff --git a/ruby/doc/optparse/ruby/block.rb b/ruby/doc/optparse/ruby/block.rb new file mode 100644 index 000000000..c4dfdeb31 --- /dev/null +++ b/ruby/doc/optparse/ruby/block.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx', 'Option with no argument') do |value| + p ['Handler block for -xxx called with value:', value] +end +parser.on('--yyy YYY', 'Option with required argument') do |value| + p ['Handler block for -yyy called with value:', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/collected_options.rb b/ruby/doc/optparse/ruby/collected_options.rb new file mode 100644 index 000000000..2115e03a9 --- /dev/null +++ b/ruby/doc/optparse/ruby/collected_options.rb @@ -0,0 +1,8 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', 'Short and long, no argument') +parser.on('-yYYY', '--yyy', 'Short and long, required argument') +parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') +options = {} +parser.parse!(into: options) +p options diff --git a/ruby/doc/optparse/ruby/custom_converter.rb b/ruby/doc/optparse/ruby/custom_converter.rb new file mode 100644 index 000000000..029da08c4 --- /dev/null +++ b/ruby/doc/optparse/ruby/custom_converter.rb @@ -0,0 +1,9 @@ +require 'optparse/date' +parser = OptionParser.new +parser.accept(Complex) do |value| + value.to_c +end +parser.on('--complex COMPLEX', Complex) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/date.rb b/ruby/doc/optparse/ruby/date.rb new file mode 100644 index 000000000..5994ad6a8 --- /dev/null +++ b/ruby/doc/optparse/ruby/date.rb @@ -0,0 +1,6 @@ +require 'optparse/date' +parser = OptionParser.new +parser.on('--date=DATE', Date) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/datetime.rb b/ruby/doc/optparse/ruby/datetime.rb new file mode 100644 index 000000000..b9b591d5f --- /dev/null +++ b/ruby/doc/optparse/ruby/datetime.rb @@ -0,0 +1,6 @@ +require 'optparse/date' +parser = OptionParser.new +parser.on('--datetime=DATETIME', DateTime) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/decimal_integer.rb b/ruby/doc/optparse/ruby/decimal_integer.rb new file mode 100644 index 000000000..360bd284f --- /dev/null +++ b/ruby/doc/optparse/ruby/decimal_integer.rb @@ -0,0 +1,7 @@ +require 'optparse' +include OptionParser::Acceptables +parser = OptionParser.new +parser.on('--decimal_integer=DECIMAL_INTEGER', DecimalInteger) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/decimal_numeric.rb b/ruby/doc/optparse/ruby/decimal_numeric.rb new file mode 100644 index 000000000..954da1356 --- /dev/null +++ b/ruby/doc/optparse/ruby/decimal_numeric.rb @@ -0,0 +1,7 @@ +require 'optparse' +include OptionParser::Acceptables +parser = OptionParser.new +parser.on('--decimal_numeric=DECIMAL_NUMERIC', DecimalNumeric) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/default_values.rb b/ruby/doc/optparse/ruby/default_values.rb new file mode 100644 index 000000000..24c26faea --- /dev/null +++ b/ruby/doc/optparse/ruby/default_values.rb @@ -0,0 +1,8 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', 'Short and long, no argument') +parser.on('-yYYY', '--yyy', 'Short and long, required argument') +parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') +options = {yyy: 'AAA', zzz: 'BBB'} +parser.parse!(into: options) +p options diff --git a/ruby/doc/optparse/ruby/descriptions.rb b/ruby/doc/optparse/ruby/descriptions.rb new file mode 100644 index 000000000..9aec80aae --- /dev/null +++ b/ruby/doc/optparse/ruby/descriptions.rb @@ -0,0 +1,15 @@ +require 'optparse' +parser = OptionParser.new +description = <<-EOT +Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Aenean commodo ligula eget. +Aenean massa. Cum sociis natoque penatibus +et magnis dis parturient montes, nascetur +ridiculus mus. Donec quam felis, ultricies +nec, pellentesque eu, pretium quis, sem. +EOT +descriptions = description.split($/) +parser.on('--xxx', *descriptions) do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/explicit_array_values.rb b/ruby/doc/optparse/ruby/explicit_array_values.rb new file mode 100644 index 000000000..64f930a4b --- /dev/null +++ b/ruby/doc/optparse/ruby/explicit_array_values.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-xXXX', ['foo', 'bar'], 'Values for required argument' ) do |value| + p ['-x', value] +end +parser.on('-y [YYY]', ['baz', 'bat'], 'Values for optional argument') do |value| + p ['-y', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/explicit_hash_values.rb b/ruby/doc/optparse/ruby/explicit_hash_values.rb new file mode 100644 index 000000000..9c9e6a48e --- /dev/null +++ b/ruby/doc/optparse/ruby/explicit_hash_values.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-xXXX', {foo: 0, bar: 1}, 'Values for required argument' ) do |value| + p ['-x', value] +end +parser.on('-y [YYY]', {baz: 2, bat: 3}, 'Values for optional argument') do |value| + p ['-y', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/false_class.rb b/ruby/doc/optparse/ruby/false_class.rb new file mode 100644 index 000000000..04fe335ed --- /dev/null +++ b/ruby/doc/optparse/ruby/false_class.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--false_class=FALSE_CLASS', FalseClass) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/float.rb b/ruby/doc/optparse/ruby/float.rb new file mode 100644 index 000000000..390df7f7b --- /dev/null +++ b/ruby/doc/optparse/ruby/float.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--float=FLOAT', Float) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/help.rb b/ruby/doc/optparse/ruby/help.rb new file mode 100644 index 000000000..95bcde1d7 --- /dev/null +++ b/ruby/doc/optparse/ruby/help.rb @@ -0,0 +1,18 @@ +require 'optparse' +parser = OptionParser.new +parser.on( + '-x', '--xxx', + 'Adipiscing elit. Aenean commodo ligula eget.', + 'Aenean massa. Cum sociis natoque penatibus', + ) +parser.on( + '-y', '--yyy YYY', + 'Lorem ipsum dolor sit amet, consectetuer.' +) +parser.on( + '-z', '--zzz [ZZZ]', + 'Et magnis dis parturient montes, nascetur', + 'ridiculus mus. Donec quam felis, ultricies', + 'nec, pellentesque eu, pretium quis, sem.', + ) +parser.parse! diff --git a/ruby/doc/optparse/ruby/help_banner.rb b/ruby/doc/optparse/ruby/help_banner.rb new file mode 100644 index 000000000..0943a3e02 --- /dev/null +++ b/ruby/doc/optparse/ruby/help_banner.rb @@ -0,0 +1,7 @@ +require 'optparse' +parser = OptionParser.new +parser.banner = "Usage: ruby help_banner.rb" +parser.parse! + + + diff --git a/ruby/doc/optparse/ruby/help_format.rb b/ruby/doc/optparse/ruby/help_format.rb new file mode 100644 index 000000000..a2f1e85b0 --- /dev/null +++ b/ruby/doc/optparse/ruby/help_format.rb @@ -0,0 +1,25 @@ +require 'optparse' +parser = OptionParser.new( + 'ruby help_format.rb [options]', # Banner + 20, # Width of options field + ' ' * 2 # Indentation +) +parser.on( + '-x', '--xxx', + 'Adipiscing elit. Aenean commodo ligula eget.', + 'Aenean massa. Cum sociis natoque penatibus', + ) +parser.on( + '-y', '--yyy YYY', + 'Lorem ipsum dolor sit amet, consectetuer.' +) +parser.on( + '-z', '--zzz [ZZZ]', + 'Et magnis dis parturient montes, nascetur', + 'ridiculus mus. Donec quam felis, ultricies', + 'nec, pellentesque eu, pretium quis, sem.', + ) +parser.parse! + + + diff --git a/ruby/doc/optparse/ruby/help_program_name.rb b/ruby/doc/optparse/ruby/help_program_name.rb new file mode 100644 index 000000000..7b3fbff06 --- /dev/null +++ b/ruby/doc/optparse/ruby/help_program_name.rb @@ -0,0 +1,7 @@ +require 'optparse' +parser = OptionParser.new +parser.program_name = 'help_program_name.rb' +parser.parse! + + + diff --git a/ruby/doc/optparse/ruby/integer.rb b/ruby/doc/optparse/ruby/integer.rb new file mode 100644 index 000000000..f10656ff1 --- /dev/null +++ b/ruby/doc/optparse/ruby/integer.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--integer=INTEGER', Integer) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/long_names.rb b/ruby/doc/optparse/ruby/long_names.rb new file mode 100644 index 000000000..a49dbda69 --- /dev/null +++ b/ruby/doc/optparse/ruby/long_names.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx', 'Long name') do |value| + p ['-xxx', value] +end +parser.on('--y1%', '--z2#', "Two long names") do |value| + p ['--y1% or --z2#', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/long_optional.rb b/ruby/doc/optparse/ruby/long_optional.rb new file mode 100644 index 000000000..38dd82166 --- /dev/null +++ b/ruby/doc/optparse/ruby/long_optional.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx [XXX]', 'Long name with optional argument') do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/long_required.rb b/ruby/doc/optparse/ruby/long_required.rb new file mode 100644 index 000000000..b76c99733 --- /dev/null +++ b/ruby/doc/optparse/ruby/long_required.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx XXX', 'Long name with required argument') do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/long_simple.rb b/ruby/doc/optparse/ruby/long_simple.rb new file mode 100644 index 000000000..4e489c43e --- /dev/null +++ b/ruby/doc/optparse/ruby/long_simple.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx', 'One long name') do |value| + p ['--xxx', value] +end +parser.on('--y1%', '--z2#', 'Two long names (aliases)') do |value| + p ['--y1% or --z2#', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/long_with_negation.rb b/ruby/doc/optparse/ruby/long_with_negation.rb new file mode 100644 index 000000000..3f2913c36 --- /dev/null +++ b/ruby/doc/optparse/ruby/long_with_negation.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--[no-]binary', 'Long name with negation') do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/match_converter.rb b/ruby/doc/optparse/ruby/match_converter.rb new file mode 100644 index 000000000..13dc5fcb5 --- /dev/null +++ b/ruby/doc/optparse/ruby/match_converter.rb @@ -0,0 +1,9 @@ +require 'optparse/date' +parser = OptionParser.new +parser.accept(:capitalize, /\w*/) do |value| + value.capitalize +end +parser.on('--capitalize XXX', :capitalize) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/matched_values.rb b/ruby/doc/optparse/ruby/matched_values.rb new file mode 100644 index 000000000..f184ca847 --- /dev/null +++ b/ruby/doc/optparse/ruby/matched_values.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx XXX', /foo/i, 'Matched values') do |value| + p ['--xxx', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/method.rb b/ruby/doc/optparse/ruby/method.rb new file mode 100644 index 000000000..3f02ff579 --- /dev/null +++ b/ruby/doc/optparse/ruby/method.rb @@ -0,0 +1,11 @@ +require 'optparse' +parser = OptionParser.new +def xxx_handler(value) + p ['Handler method for -xxx called with value:', value] +end +parser.on('--xxx', 'Option with no argument', method(:xxx_handler)) +def yyy_handler(value) + p ['Handler method for -yyy called with value:', value] +end +parser.on('--yyy YYY', 'Option with required argument', method(:yyy_handler)) +parser.parse! diff --git a/ruby/doc/optparse/ruby/missing_options.rb b/ruby/doc/optparse/ruby/missing_options.rb new file mode 100644 index 000000000..9428463cf --- /dev/null +++ b/ruby/doc/optparse/ruby/missing_options.rb @@ -0,0 +1,12 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', 'Short and long, no argument') +parser.on('-yYYY', '--yyy', 'Short and long, required argument') +parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') +options = {} +parser.parse!(into: options) +required_options = [:xxx, :zzz] +missing_options = required_options - options.keys +unless missing_options.empty? + fail "Missing required options: #{missing_options}" +end diff --git a/ruby/doc/optparse/ruby/mixed_names.rb b/ruby/doc/optparse/ruby/mixed_names.rb new file mode 100644 index 000000000..67f81e7e8 --- /dev/null +++ b/ruby/doc/optparse/ruby/mixed_names.rb @@ -0,0 +1,12 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx', 'Short and long, no argument') do |value| + p ['--xxx', value] +end +parser.on('-yYYY', '--yyy', 'Short and long, required argument') do |value| + p ['--yyy', value] +end +parser.on('-z [ZZZ]', '--zzz', 'Short and long, optional argument') do |value| + p ['--zzz', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/name_abbrev.rb b/ruby/doc/optparse/ruby/name_abbrev.rb new file mode 100644 index 000000000..b438c1b3d --- /dev/null +++ b/ruby/doc/optparse/ruby/name_abbrev.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-n', '--dry-run',) do |value| + p ['--dry-run', value] +end +parser.on('-d', '--draft',) do |value| + p ['--draft', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/no_abbreviation.rb b/ruby/doc/optparse/ruby/no_abbreviation.rb new file mode 100644 index 000000000..546449270 --- /dev/null +++ b/ruby/doc/optparse/ruby/no_abbreviation.rb @@ -0,0 +1,10 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-n', '--dry-run',) do |value| + p ['--dry-run', value] +end +parser.on('-d', '--draft',) do |value| + p ['--draft', value] +end +parser.require_exact = true +parser.parse! diff --git a/ruby/doc/optparse/ruby/numeric.rb b/ruby/doc/optparse/ruby/numeric.rb new file mode 100644 index 000000000..d7021f154 --- /dev/null +++ b/ruby/doc/optparse/ruby/numeric.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--numeric=NUMERIC', Numeric) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/object.rb b/ruby/doc/optparse/ruby/object.rb new file mode 100644 index 000000000..0f5ae8b92 --- /dev/null +++ b/ruby/doc/optparse/ruby/object.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--object=OBJECT', Object) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/octal_integer.rb b/ruby/doc/optparse/ruby/octal_integer.rb new file mode 100644 index 000000000..b9644a076 --- /dev/null +++ b/ruby/doc/optparse/ruby/octal_integer.rb @@ -0,0 +1,7 @@ +require 'optparse' +include OptionParser::Acceptables +parser = OptionParser.new +parser.on('--octal_integer=OCTAL_INTEGER', OctalInteger) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/optional_argument.rb b/ruby/doc/optparse/ruby/optional_argument.rb new file mode 100644 index 000000000..456368a8b --- /dev/null +++ b/ruby/doc/optparse/ruby/optional_argument.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x [XXX]', '--xxx', 'Optional argument via short name') do |value| + p ['--xxx', value] +end +parser.on('-y', '--yyy [YYY]', 'Optional argument via long name') do |value| + p ['--yyy', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/parse.rb b/ruby/doc/optparse/ruby/parse.rb new file mode 100644 index 000000000..a5d432948 --- /dev/null +++ b/ruby/doc/optparse/ruby/parse.rb @@ -0,0 +1,13 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx') do |value| + p ['--xxx', value] +end +parser.on('--yyy YYY') do |value| + p ['--yyy', value] +end +parser.on('--zzz [ZZZ]') do |value| + p ['--zzz', value] +end +ret = parser.parse(ARGV) +puts "Returned: #{ret} (#{ret.class})" diff --git a/ruby/doc/optparse/ruby/parse_bang.rb b/ruby/doc/optparse/ruby/parse_bang.rb new file mode 100644 index 000000000..567bc733c --- /dev/null +++ b/ruby/doc/optparse/ruby/parse_bang.rb @@ -0,0 +1,13 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--xxx') do |value| + p ['--xxx', value] +end +parser.on('--yyy YYY') do |value| + p ['--yyy', value] +end +parser.on('--zzz [ZZZ]') do |value| + p ['--zzz', value] +end +ret = parser.parse! +puts "Returned: #{ret} (#{ret.class})" diff --git a/ruby/doc/optparse/ruby/proc.rb b/ruby/doc/optparse/ruby/proc.rb new file mode 100644 index 000000000..9c669fdc9 --- /dev/null +++ b/ruby/doc/optparse/ruby/proc.rb @@ -0,0 +1,13 @@ +require 'optparse' +parser = OptionParser.new +parser.on( + '--xxx', + 'Option with no argument', + ->(value) {p ['Handler proc for -xxx called with value:', value]} +) +parser.on( + '--yyy YYY', + 'Option with required argument', + ->(value) {p ['Handler proc for -yyy called with value:', value]} +) +parser.parse! diff --git a/ruby/doc/optparse/ruby/regexp.rb b/ruby/doc/optparse/ruby/regexp.rb new file mode 100644 index 000000000..6aba45ce7 --- /dev/null +++ b/ruby/doc/optparse/ruby/regexp.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--regexp=REGEXP', Regexp) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/required_argument.rb b/ruby/doc/optparse/ruby/required_argument.rb new file mode 100644 index 000000000..228a492c3 --- /dev/null +++ b/ruby/doc/optparse/ruby/required_argument.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x XXX', '--xxx', 'Required argument via short name') do |value| + p ['--xxx', value] +end +parser.on('-y', '--y YYY', 'Required argument via long name') do |value| + p ['--yyy', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/shellwords.rb b/ruby/doc/optparse/ruby/shellwords.rb new file mode 100644 index 000000000..d181d4a4f --- /dev/null +++ b/ruby/doc/optparse/ruby/shellwords.rb @@ -0,0 +1,6 @@ +require 'optparse/shellwords' +parser = OptionParser.new +parser.on('--shellwords=SHELLWORDS', Shellwords) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/short_names.rb b/ruby/doc/optparse/ruby/short_names.rb new file mode 100644 index 000000000..4a756518f --- /dev/null +++ b/ruby/doc/optparse/ruby/short_names.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', 'Short name') do |value| + p ['x', value] +end +parser.on('-1', '-%', 'Two short names') do |value| + p ['-1 or -%', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/short_optional.rb b/ruby/doc/optparse/ruby/short_optional.rb new file mode 100644 index 000000000..6eebf01c5 --- /dev/null +++ b/ruby/doc/optparse/ruby/short_optional.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x [XXX]', 'Short name with optional argument') do |value| + p ['-x', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/short_range.rb b/ruby/doc/optparse/ruby/short_range.rb new file mode 100644 index 000000000..f5b870a4b --- /dev/null +++ b/ruby/doc/optparse/ruby/short_range.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-[!-~]', 'Short names in (very large) range') do |name, value| + p ['!-~', name, value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/short_required.rb b/ruby/doc/optparse/ruby/short_required.rb new file mode 100644 index 000000000..867c02c9f --- /dev/null +++ b/ruby/doc/optparse/ruby/short_required.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-xXXX', 'Short name with required argument') do |value| + p ['-x', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/short_simple.rb b/ruby/doc/optparse/ruby/short_simple.rb new file mode 100644 index 000000000..d3d489e2d --- /dev/null +++ b/ruby/doc/optparse/ruby/short_simple.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', 'One short name') do |value| + p ['-x', value] +end +parser.on('-1', '-%', 'Two short names (aliases)') do |value| + p ['-1 or -%', value] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/string.rb b/ruby/doc/optparse/ruby/string.rb new file mode 100644 index 000000000..fee84a17e --- /dev/null +++ b/ruby/doc/optparse/ruby/string.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--string=STRING', String) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/terminator.rb b/ruby/doc/optparse/ruby/terminator.rb new file mode 100644 index 000000000..c718ac1a9 --- /dev/null +++ b/ruby/doc/optparse/ruby/terminator.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--my_option XXX') do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/time.rb b/ruby/doc/optparse/ruby/time.rb new file mode 100644 index 000000000..aa8b0cfa1 --- /dev/null +++ b/ruby/doc/optparse/ruby/time.rb @@ -0,0 +1,6 @@ +require 'optparse/time' +parser = OptionParser.new +parser.on('--time=TIME', Time) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/true_class.rb b/ruby/doc/optparse/ruby/true_class.rb new file mode 100644 index 000000000..40db9d07c --- /dev/null +++ b/ruby/doc/optparse/ruby/true_class.rb @@ -0,0 +1,6 @@ +require 'optparse' +parser = OptionParser.new +parser.on('--true_class=TRUE_CLASS', TrueClass) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/ruby/uri.rb b/ruby/doc/optparse/ruby/uri.rb new file mode 100644 index 000000000..b492835b4 --- /dev/null +++ b/ruby/doc/optparse/ruby/uri.rb @@ -0,0 +1,6 @@ +require 'optparse/uri' +parser = OptionParser.new +parser.on('--uri=URI', URI) do |value| + p [value, value.class] +end +parser.parse! diff --git a/ruby/doc/optparse/tutorial.rdoc b/ruby/doc/optparse/tutorial.rdoc new file mode 100644 index 000000000..19c86b93d --- /dev/null +++ b/ruby/doc/optparse/tutorial.rdoc @@ -0,0 +1,835 @@ +== Tutorial + +=== Why \OptionParser? + +When a Ruby program executes, it captures its command-line arguments +and options into variable ARGV. +This simple program just prints its \ARGV: + + :include: ruby/argv.rb + +Execution, with arguments and options: + + $ ruby argv.rb foo --bar --baz bat bam + ["foo", "--bar", "--baz", "bat", "bam"] + +The executing program is responsible for parsing and handling +the command-line options. + +OptionParser offers methods for parsing and handling those options. + +With \OptionParser, you can define options so that for each option: + +- The code that defines the option and code that handles that option + are in the same place. +- The option may take no argument, a required argument, or an optional argument. +- The argument may be automatically converted to a specified class. +- The argument may be restricted to specified _forms_. +- The argument may be restricted to specified _values_. + +The class also has method #help, which displays automatically-generated help text. + +=== Contents + +- {To Begin With}[#label-To+Begin+With] +- {Defining Options}[#label-Defining+Options] +- {Option Names}[#label-Option+Names] + - {Short Option Names}[#label-Short+Option+Names] + - {Long Option Names}[#label-Long+Option+Names] + - {Mixing Option Names}[#label-Mixing+Option+Names] + - {Option Name Abbreviations}[#label-Option+Name+Abbreviations] +- {Option Arguments}[#label-Option+Arguments] + - {Option with No Argument}[#label-Option+with+No+Argument] + - {Option with Required Argument}[#label-Option+with+Required+Argument] + - {Option with Optional Argument}[#label-Option+with+Optional+Argument] + - {Argument Abbreviations}[#label-Argument+Abbreviations] +- {Argument Values}[#label-Argument+Values] + - {Explicit Argument Values}[#label-Explicit+Argument+Values] + - {Explicit Values in Array}[#label-Explicit+Values+in+Array] + - {Explicit Values in Hash}[#label-Explicit+Values+in+Hash] + - {Argument Value Patterns}[#label-Argument+Value+Patterns] +- {Keyword Argument into}[#label-Keyword+Argument+into] + - {Collecting Options}[#label-Collecting+Options] + - {Checking for Missing Options}[#label-Checking+for+Missing+Options] + - {Default Values for Options}[#label-Default+Values+for+Options] +- {Argument Converters}[#label-Argument+Converters] +- {Help}[#label-Help] +- {Top List and Base List}[#label-Top+List+and+Base+List] +- {Defining Options}[#label-Defining+Options] +- {Parsing}[#label-Parsing] + - {Method parse!}[#label-Method+parse-21] + - {Method parse}[#label-Method+parse] + - {Method order!}[#label-Method+order-21] + - {Method order}[#label-Method+order] + - {Method permute!}[#label-Method+permute-21] + - {Method permute}[#label-Method+permute] + +=== To Begin With + +To use \OptionParser: + +1. Require the \OptionParser code. +2. Create an \OptionParser object. +3. Define one or more options. +4. Parse the command line. + +File +basic.rb+ defines three options, -x, +-y, and -z, each with a descriptive string, +and each with a block. + + :include: ruby/basic.rb + +From these defined options, the parser automatically builds help text: + + $ ruby basic.rb --help + Usage: basic [options] + -x Whether to X + -y Whether to Y + -z Whether to Z + +When an option is found during parsing, +the block defined for the option is called with the argument value. +An invalid option raises an exception. + +Method #parse!, which is used most often in this tutorial, +removes from \ARGV the options and arguments it finds, +leaving other non-option arguments for the program to handle on its own. +The method returns the possibly-reduced \ARGV array. + +Executions: + + $ ruby basic.rb -x -z + ["x", true] + ["z", true] + [] + $ ruby basic.rb -z -y -x + ["z", true] + ["y", true] + ["x", true] + [] + $ ruby basic.rb -x input_file.txt output_file.txt + ["x", true] + ["input_file.txt", "output_file.txt"] + $ ruby basic.rb -a + basic.rb:16:in `
': invalid option: -a (OptionParser::InvalidOption) + +=== Defining Options + +A common way to define an option in \OptionParser +is with instance method OptionParser#on. + +The method may be called with any number of arguments +(whose order does not matter), +and may also have a trailing optional keyword argument +into+. + +The given arguments determine the characteristics of the new option. +These may include: + +- One or more short option names. +- One or more long option names. +- Whether the option takes no argument, an optional argument, or a required argument. +- Acceptable _forms_ for the argument. +- Acceptable _values_ for the argument. +- A proc or method to be called when the parser encounters the option. +- String descriptions for the option. + +=== Option Names + +You can give an option one or more names of two types: + +- Short (1-character) name, beginning with one hyphen (-). +- Long (multi-character) name, beginning with two hyphens (--). + +==== Short Option Names + +A short option name consists of a hyphen and a single character. + +File +short_names.rb+ +defines an option with a short name, -x, +and an option with two short names (aliases, in effect) -y and -z. + + :include: ruby/short_names.rb + +Executions: + + $ ruby short_names.rb --help + Usage: short_names [options] + -x Short name + -1, -% Two short names + $ ruby short_names.rb -x + ["x", true] + $ ruby short_names.rb -1 + ["-1 or -%", true] + $ ruby short_names.rb -% + ["-1 or -%", true] + +Multiple short names can "share" a hyphen: + + $ ruby short_names.rb -x1% + ["x", true] + ["-1 or -%", true] + ["-1 or -%", true] + +==== Long Option Names + +A long option name consists of two hyphens and a one or more characters +(usually two or more characters). + +File +long_names.rb+ +defines an option with a long name, --xxx, +and an option with two long names (aliases, in effect) --y1% and --z2#. + + :include: ruby/long_names.rb + +Executions: + + $ ruby long_names.rb --help + Usage: long_names [options] + --xxx Long name + --y1%, --z2# Two long names + $ ruby long_names.rb --xxx + ["-xxx", true] + $ ruby long_names.rb --y1% + ["--y1% or --z2#", true] + $ ruby long_names.rb --z2# + ["--y1% or --z2#", true] + +A long name may be defined with both positive and negative senses. + +File +long_with_negation.rb+ defines an option that has both senses. + + :include: ruby/long_with_negation.rb + +Executions: + + $ ruby long_with_negation.rb --help + Usage: long_with_negation [options] + --[no-]binary Long name with negation + $ ruby long_with_negation.rb --binary + [true, TrueClass] + $ ruby long_with_negation.rb --no-binary + [false, FalseClass] + +==== Mixing Option Names + +Many developers like to mix short and long option names, +so that a short name is in effect an abbreviation of a long name. + +File +mixed_names.rb+ +defines options that each have both a short and a long name. + + :include: ruby/mixed_names.rb + +Executions: + + $ ruby mixed_names.rb --help + Usage: mixed_names [options] + -x, --xxx Short and long, no argument + -y, --yyyYYY Short and long, required argument + -z, --zzz [ZZZ] Short and long, optional argument + $ ruby mixed_names.rb -x + ["--xxx", true] + $ ruby mixed_names.rb --xxx + ["--xxx", true] + $ ruby mixed_names.rb -y + 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) + $ ruby mixed_names.rb --yyy BAR + ["--yyy", "BAR"] + $ ruby mixed_names.rb -z + ["--zzz", nil] + $ ruby mixed_names.rb -z BAZ + ["--zzz", "BAZ"] + $ ruby mixed_names.rb --zzz + ["--zzz", nil] + $ ruby mixed_names.rb --zzz BAT + ["--zzz", "BAT"] + +==== Option Name Abbreviations + +By default, abbreviated option names on the command-line are allowed. +An abbreviated name is valid if it is unique among abbreviated option names. + + :include: ruby/name_abbrev.rb + +Executions: + + $ ruby name_abbrev.rb --help + Usage: name_abbrev [options] + -n, --dry-run + -d, --draft + $ ruby name_abbrev.rb -n + ["--dry-run", true] + $ ruby name_abbrev.rb --dry-run + ["--dry-run", true] + $ ruby name_abbrev.rb -d + ["--draft", true] + $ ruby name_abbrev.rb --draft + ["--draft", true] + $ ruby name_abbrev.rb --d + 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) + $ ruby name_abbrev.rb --dry + ["--dry-run", true] + $ ruby name_abbrev.rb --dra + ["--draft", true] + +You can disable abbreviation using method +require_exact+. + + :include: ruby/no_abbreviation.rb + +Executions: + + $ ruby no_abbreviation.rb --dry-ru + no_abbreviation.rb:10:in `
': invalid option: --dry-ru (OptionParser::InvalidOption) + $ ruby no_abbreviation.rb --dry-run + ["--dry-run", true] + +=== Option Arguments + +An option may take no argument, a required argument, or an optional argument. + +==== Option with No Argument + +All the examples above define options with no argument. + +==== Option with Required Argument + +Specify a required argument for an option by adding a dummy word +to its name definition. + +File +required_argument.rb+ defines two options; +each has a required argument because the name definition has a following dummy word. + + :include: ruby/required_argument.rb + +When an option is found, the given argument is yielded. + +Executions: + + $ ruby required_argument.rb --help + Usage: required_argument [options] + -x, --xxx XXX Required argument via short name + -y, --y YYY Required argument via long name + $ ruby required_argument.rb -x AAA + ["--xxx", "AAA"] + $ ruby required_argument.rb -y BBB + ["--yyy", "BBB"] + +Omitting a required argument raises an error: + + $ ruby required_argument.rb -x + required_argument.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + +==== Option with Optional Argument + +Specify an optional argument for an option by adding a dummy word +enclosed in square brackets to its name definition. + +File +optional_argument.rb+ defines two options; +each has an optional argument because the name definition has a following dummy word +in square brackets. + + :include: ruby/optional_argument.rb + +When an option with an argument is found, the given argument yielded. + +Executions: + + $ ruby optional_argument.rb --help + Usage: optional_argument [options] + -x, --xxx [XXX] Optional argument via short name + -y, --yyy [YYY] Optional argument via long name + $ ruby optional_argument.rb -x AAA + ["--xxx", "AAA"] + $ ruby optional_argument.rb -y BBB + ["--yyy", "BBB"] + +Omitting an optional argument does not raise an error. + +=== Argument Values + +Permissible argument values may be restricted +either by specifying explicit values +or by providing a pattern that the given value must match. + +==== Explicit Argument Values + +You can specify argument values in either of two ways: + +- Specify values an array of strings. +- Specify values a hash. + +===== Explicit Values in Array + +You can specify explicit argument values in an array of strings. +The argument value must be one of those strings, or an unambiguous abbreviation. + +File +explicit_array_values.rb+ defines options with explicit argument values. + + :include: ruby/explicit_array_values.rb + +Executions: + + $ ruby explicit_array_values.rb --help + Usage: explicit_array_values [options] + -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) + $ ruby explicit_array_values.rb -x foo + ["-x", "foo"] + $ ruby explicit_array_values.rb -x f + ["-x", "foo"] + $ 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) + $ ruby explicit_array_values.rb -x baz + explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + + +===== Explicit Values in Hash + +You can specify explicit argument values in a hash with string keys. +The value passed must be one of those keys, or an unambiguous abbreviation; +the value yielded will be the value for that key. + +File +explicit_hash_values.rb+ defines options with explicit argument values. + + :include: ruby/explicit_hash_values.rb + +Executions: + + $ ruby explicit_hash_values.rb --help + Usage: explicit_hash_values [options] + -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) + $ ruby explicit_hash_values.rb -x foo + ["-x", 0] + $ ruby explicit_hash_values.rb -x f + ["-x", 0] + $ 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) + $ ruby explicit_hash_values.rb -y + ["-y", nil] + $ ruby explicit_hash_values.rb -y baz + ["-y", 2] + $ 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) + $ 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. + +File +matched_values.rb+ defines options with matched argument values. + + :include: ruby/matched_values.rb + +Executions: + + $ ruby matched_values.rb --help + Usage: matched_values [options] + --xxx XXX Matched values + $ 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) + +=== Keyword Argument +into+ + +In parsing options, you can add keyword option +into+ with a hash-like argument; +each parsed option will be added as a name/value pair. + +This is useful for: + +- Collecting options. +- Checking for missing options. +- Providing default values for options. + +==== Collecting Options + +Use keyword argument +into+ to collect options. + + :include: ruby/collected_options.rb + +Executions: + + $ ruby collected_options.rb --help + Usage: into [options] + -x, --xxx Short and long, no argument + -y, --yyyYYY Short and long, required argument + -z, --zzz [ZZZ] Short and long, optional argument + $ ruby collected_options.rb --xxx + {:xxx=>true} + $ ruby collected_options.rb --xxx --yyy FOO + {:xxx=>true, :yyy=>"FOO"} + $ ruby collected_options.rb --xxx --yyy FOO --zzz Bar + {:xxx=>true, :yyy=>"FOO", :zzz=>"Bar"} + $ ruby collected_options.rb --xxx --yyy FOO --yyy BAR + {:xxx=>true, :yyy=>"BAR"} + +Note in the last execution that the argument value for option --yyy +was overwritten. + +==== Checking for Missing Options + +Use the collected options to check for missing options. + + :include: ruby/missing_options.rb + +Executions: + + $ ruby missing_options.rb --help + Usage: missing_options [options] + -x, --xxx Short and long, no argument + -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) + +==== Default Values for Options + +Initialize the +into+ argument to define default values for options. + + :include: ruby/default_values.rb + +Executions: + + $ ruby default_values.rb --help + Usage: default_values [options] + -x, --xxx Short and long, no argument + -y, --yyyYYY Short and long, required argument + -z, --zzz [ZZZ] Short and long, optional argument + $ ruby default_values.rb --yyy FOO + {:yyy=>"FOO", :zzz=>"BBB"} + +=== Argument Converters + +An option can specify that its argument is to be converted +from the default \String to an instance of another class. +There are a number of built-in converters. + +Example: File +date.rb+ +defines an option whose argument is to be converted to a \Date object. +The argument is converted by method Date#parse. + + :include: ruby/date.rb + +Executions: + + $ ruby date.rb --date 2001-02-03 + [#, Date] + $ ruby date.rb --date 20010203 + [#, Date] + $ ruby date.rb --date "3rd Feb 2001" + [#, Date] + +You can also define custom converters. +See {Argument Converters}[./argument_converters.rdoc] +for both built-in and custom converters. + +=== Help + +\OptionParser makes automatically generated help text available. + +The help text consists of: + +- A banner, showing the usage. +- Option short and long names. +- Option dummy argument names. +- Option descriptions. + +Example code: + + :include: ruby/help.rb + +The option names and dummy argument names are defined as described above. + +The option description consists of the strings that are not themselves option names; +An option can have more than one description string. +Execution: + + Usage: help [options] + -x, --xxx Adipiscing elit. Aenean commodo ligula eget. + Aenean massa. Cum sociis natoque penatibus + -y, --yyy YYY Lorem ipsum dolor sit amet, consectetuer. + -z, --zzz [ZZZ] Et magnis dis parturient montes, nascetur + ridiculus mus. Donec quam felis, ultricies + nec, pellentesque eu, pretium quis, sem. + +The program name is included in the default banner: +Usage: #{program_name} [options]; +you can change the program name. + + :include: ruby/help_program_name.rb + +Execution: + + $ ruby help_program_name.rb --help + Usage: help_program_name.rb [options] + +You can also change the entire banner. + + :include: ruby/help_banner.rb + +Execution: + + $ ruby help_banner.rb --help + Usage: ruby help_banner.rb + +By default, the option names are indented 4 spaces +and the width of the option-names field is 32 spaces. + +You can change these values, along with the banner, +by passing parameters to OptionParser.new. + + :include: ruby/help_format.rb + +Execution: + + $ ruby help_format.rb --help + ruby help_format.rb [options] + -x, --xxx Adipiscing elit. Aenean commodo ligula eget. + Aenean massa. Cum sociis natoque penatibus + -y, --yyy YYY Lorem ipsum dolor sit amet, consectetuer. + -z, --zzz [ZZZ] Et magnis dis parturient montes, nascetur + ridiculus mus. Donec quam felis, ultricies + nec, pellentesque eu, pretium quis, sem. + +=== Top List and Base List + +An \OptionParser object maintains a stack of \OptionParser::List objects, +each of which has a collection of zero or more options. +It is unlikely that you'll need to add or take away from that stack. + +The stack includes: + +- The top list, given by \OptionParser#top. +- The base list, given by \OptionParser#base. + +When \OptionParser builds its help text, the options in the top list +precede those in the base list. + +=== Defining Options + +Option-defining methods allow you to create an option, and also append/prepend it +to the top list or append it to the base list. + +Each of these next three methods accepts a sequence of parameter arguments and a block, +creates an option object using method \Option#make_switch (see below), +and returns the created option: + +- \Method \OptionParser#define appends the created option to the top list. + +- \Method \OptionParser#define_head prepends the created option to the top list. + +- \Method \OptionParser#define_tail appends the created option to the base list. + +These next three methods are identical to the three above, +except for their return values: + +- \Method \OptionParser#on is identical to method \OptionParser#define, + except that it returns the parser object +self+. + +- \Method \OptionParser#on_head is identical to method \OptionParser#define_head, + except that it returns the parser object +self+. + +- \Method \OptionParser#on_tail is identical to method \OptionParser#define_tail, + except that it returns the parser object +self+. + +Though you may never need to call it directly, +here's the core method for defining an option: + +- \Method \OptionParser#make_switch accepts an array of parameters and a block. + See {Parameters for New Options}[./option_params.rdoc]. + This method is unlike others here in that it: + - Accepts an array of parameters; + others accept a sequence of parameter arguments. + - Returns an array containing the created option object, + option names, and other values; + others return either the created option object + or the parser object +self+. + +=== Parsing + +\OptionParser has six instance methods for parsing. + +Three have names ending with a "bang" (!): + +- parse! +- order! +- permute! + +Each of these methods: + +- Accepts an optional array of string arguments +argv+; + if not given, +argv+ defaults to the value of OptionParser#default_argv, + whose initial value is ARGV. +- Accepts an optional keyword argument +into+ + (see {Keyword Argument into}[#label-Keyword+Argument+into]). +- Returns +argv+, possibly with some elements removed. + +The three other methods have names _not_ ending with a "bang": + +- parse +- order +- permute + +Each of these methods: + +- Accepts an array of string arguments + _or_ zero or more string arguments. +- Accepts an optional keyword argument +into+ and its value _into_. + (see {Keyword Argument into}[#label-Keyword+Argument+into]). +- Returns +argv+, possibly with some elements removed. + +==== \Method parse! + +\Method parse!: + +- Accepts an optional array of string arguments +argv+; + if not given, +argv+ defaults to the value of OptionParser#default_argv, + whose initial value is ARGV. +- Accepts an optional keyword argument +into+ + (see {Keyword Argument into}[#label-Keyword+Argument+into]). +- Returns +argv+, possibly with some elements removed. + +The method processes the elements in +argv+ beginning at argv[0], +and ending, by default, at the end. + +Otherwise processing ends and the method returns when: + +- The terminator argument -- is found; + the terminator argument is removed before the return. +- Environment variable +POSIXLY_CORRECT+ is defined + and a non-option argument is found; + the non-option argument is not removed. + Note that the _value_ of that variable does not matter, + as only its existence is checked. + +File +parse_bang.rb+: + + :include: ruby/parse_bang.rb + +Help: + + $ ruby parse_bang.rb --help + Usage: parse_bang [options] + --xxx + --yyy YYY + --zzz [ZZZ] + +Default behavior: + + $ ruby parse_bang.rb input_file.txt output_file.txt --xxx --yyy FOO --zzz BAR + ["--xxx", true] + ["--yyy", "FOO"] + ["--zzz", "BAR"] + Returned: ["input_file.txt", "output_file.txt"] (Array) + +Processing ended by terminator argument: + + $ ruby parse_bang.rb input_file.txt output_file.txt --xxx --yyy FOO -- --zzz BAR + ["--xxx", true] + ["--yyy", "FOO"] + Returned: ["input_file.txt", "output_file.txt", "--zzz", "BAR"] (Array) + +Processing ended by non-option found when +POSIXLY_CORRECT+ is defined: + + $ POSIXLY_CORRECT=true ruby parse_bang.rb --xxx input_file.txt output_file.txt -yyy FOO + ["--xxx", true] + Returned: ["input_file.txt", "output_file.txt", "-yyy", "FOO"] (Array) + +==== \Method parse + +\Method parse: + +- Accepts an array of string arguments + _or_ zero or more string arguments. +- Accepts an optional keyword argument +into+ and its value _into_. + (see {Keyword Argument into}[#label-Keyword+Argument+into]). +- Returns +argv+, possibly with some elements removed. + +If given an array +ary+, the method forms array +argv+ as ary.dup. +If given zero or more string arguments, those arguments are formed +into array +argv+. + +The method calls + + parse!(argv, into: into) + +Note that environment variable +POSIXLY_CORRECT+ +and the terminator argument -- are honored. + +File +parse.rb+: + + :include: ruby/parse.rb + +Help: + + $ ruby parse.rb --help + Usage: parse [options] + --xxx + --yyy YYY + --zzz [ZZZ] + +Default behavior: + + $ ruby parse.rb input_file.txt output_file.txt --xxx --yyy FOO --zzz BAR + ["--xxx", true] + ["--yyy", "FOO"] + ["--zzz", "BAR"] + Returned: ["input_file.txt", "output_file.txt"] (Array) + +Processing ended by terminator argument: + + $ ruby parse.rb input_file.txt output_file.txt --xxx --yyy FOO -- --zzz BAR + ["--xxx", true] + ["--yyy", "FOO"] + Returned: ["input_file.txt", "output_file.txt", "--zzz", "BAR"] (Array) + +Processing ended by non-option found when +POSIXLY_CORRECT+ is defined: + + $ POSIXLY_CORRECT=true ruby parse.rb --xxx input_file.txt output_file.txt -yyy FOO + ["--xxx", true] + Returned: ["input_file.txt", "output_file.txt", "-yyy", "FOO"] (Array) + +==== \Method order! + +Calling method OptionParser#order! gives exactly the same result as +calling method OptionParser#parse! with environment variable ++POSIXLY_CORRECT+ defined. + +==== \Method order + +Calling method OptionParser#order gives exactly the same result as +calling method OptionParser#parse with environment variable ++POSIXLY_CORRECT+ defined. + +==== \Method permute! + +Calling method OptionParser#permute! gives exactly the same result as +calling method OptionParser#parse! with environment variable ++POSIXLY_CORRECT+ _not_ defined. + +==== \Method permute + +Calling method OptionParser#permute gives exactly the same result as +calling method OptionParser#parse with environment variable ++POSIXLY_CORRECT+ _not_ defined. diff --git a/ruby/doc/ractor.md b/ruby/doc/ractor.md new file mode 100644 index 000000000..f5b1fb540 --- /dev/null +++ b/ruby/doc/ractor.md @@ -0,0 +1,952 @@ +# Ractor - Ruby's Actor-like concurrent abstraction + +Ractor is designed to provide a parallel execution feature of Ruby without thread-safety concerns. + +## Summary + +### Multiple Ractors in an interpreter process + +You can make multiple Ractors and they run in parallel. + +* `Ractor.new{ expr }` creates a new Ractor and `expr` is run in parallel on a parallel computer. +* Interpreter invokes with the first Ractor (called *main Ractor*). +* If main Ractor terminated, all Ractors receive terminate request like Threads (if main thread (first invoked Thread), Ruby interpreter sends all running threads to terminate execution). +* Each Ractor has 1 or more Threads. + * Threads in a Ractor shares a Ractor-wide global lock like GIL (GVL in MRI terminology), so they can't run in parallel (without releasing GVL explicitly in C-level). Threads in different ractors run in parallel. + * The overhead of creating a Ractor is similar to overhead of one Thread creation. + +### Limited sharing between multiple ractors + +Ractors don't share everything, unlike threads. + +* Most objects are *Unshareable objects*, so you don't need to care about thread-safety problems which are caused by sharing. +* Some objects are *Shareable objects*. + * Immutable objects: frozen objects which don't refer to unshareable-objects. + * `i = 123`: `i` is an immutable object. + * `s = "str".freeze`: `s` is an immutable object. + * `a = [1, [2], 3].freeze`: `a` is not an immutable object because `a` refers unshareable-object `[2]` (which is not frozen). + * `h = {c: Object}.freeze`: `h` is an immutable object because `h` refers Symbol `:c` and shareable `Object` class object which is not frozen. + * Class/Module objects + * Special shareable objects + * Ractor object itself. + * And more... + +### Two-types communication between Ractors + +Ractors communicate with each other and synchronize the execution by message exchanging between Ractors. There are two message exchange protocols: push type (message passing) and pull type. + +* Push type message passing: `Ractor#send(obj)` and `Ractor.receive()` pair. + * Sender ractor passes the `obj` to the ractor `r` by `r.send(obj)` and receiver ractor receives the message with `Ractor.receive`. + * Sender knows the destination Ractor `r` and the receiver does not know the sender (accept all messages from any ractors). + * Receiver has infinite queue and sender enqueues the message. Sender doesn't block to put message into this queue. + * This type of message exchanging is employed by many other Actor-based languages. + * `Ractor.receive_if{ filter_expr }` is a variant of `Ractor.receive` to select a message. +* Pull type communication: `Ractor.yield(obj)` and `Ractor#take()` pair. + * Sender ractor declare to yield the `obj` by `Ractor.yield(obj)` and receiver Ractor take it with `r.take`. + * Sender doesn't know a destination Ractor and receiver knows the sender Ractor `r`. + * Sender or receiver will block if there is no other side. + +### Copy & Move semantics to send messages + +To send unshareable objects as messages, objects are copied or moved. + +* Copy: use deep-copy. +* Move: move membership. + * Sender can not access the moved object after moving the object. + * Guarantee that at least only 1 Ractor can access the object. + +### Thread-safety + +Ractor helps to write a thread-safe concurrent program, but we can make thread-unsafe programs with Ractors. + +* GOOD: Sharing limitation + * Most objects are unshareable, so we can't make data-racy and race-conditional programs. + * Shareable objects are protected by an interpreter or locking mechanism. +* BAD: Class/Module can violate this assumption + * To make it compatible with old behavior, classes and modules can introduce data-race and so on. + * Ruby programmers should take care if they modify class/module objects on multi Ractor programs. +* BAD: Ractor can't solve all thread-safety problems + * There are several blocking operations (waiting send, waiting yield and waiting take) so you can make a program which has dead-lock and live-lock issues. + * Some kind of shareable objects can introduce transactions (STM, for example). However, misusing transactions will generate inconsistent state. + +Without Ractor, we need to trace all state-mutations to debug thread-safety issues. +With Ractor, you can concentrate on suspicious code which are shared with Ractors. + +## Creation and termination + +### `Ractor.new` + +* `Ractor.new{ expr }` generates another Ractor. + +```ruby +# Ractor.new with a block creates new Ractor +r = Ractor.new do + # This block will be run in parallel with other ractors +end + +# You can name a Ractor with `name:` argument. +r = Ractor.new name: 'test-name' do +end + +# and Ractor#name returns its name. +r.name #=> 'test-name' +``` + +### Given block isolation + +The Ractor executes given `expr` in a given block. +Given block will be isolated from outer scope by the `Proc#isolate` method (not exposed yet for Ruby users). To prevent sharing unshareable objects between ractors, block outer-variables, `self` and other information are isolated. + +`Proc#isolate` is called at Ractor creation time (when `Ractor.new` is called). If given Proc object is not able to isolate because of outer variables and so on, an error will be raised. + +```ruby +begin + a = true + r = Ractor.new do + a #=> ArgumentError because this block accesses `a`. + end + r.take # see later +rescue ArgumentError +end +``` + +* The `self` of the given block is the `Ractor` object itself. + +```ruby +r = Ractor.new do + p self.class #=> Ractor + self.object_id +end +r.take == self.object_id #=> false +``` + +Passed arguments to `Ractor.new()` becomes block parameters for the given block. However, an interpreter does not pass the parameter object references, but send them as messages (see below for details). + +```ruby +r = Ractor.new 'ok' do |msg| + msg #=> 'ok' +end +r.take #=> 'ok' +``` + +```ruby +# almost similar to the last example +r = Ractor.new do + msg = Ractor.receive + msg +end +r.send 'ok' +r.take #=> 'ok' +``` + +### An execution result of given block + +Return value of the given block becomes an outgoing message (see below for details). + +```ruby +r = Ractor.new do + 'ok' +end +r.take #=> `ok` +``` + +```ruby +# almost similar to the last example +r = Ractor.new do + Ractor.yield 'ok' +end +r.take #=> 'ok' +``` + +Error in the given block will be propagated to the receiver of an outgoing message. + +```ruby +r = Ractor.new do + raise 'ok' # exception will be transferred to the receiver +end + +begin + r.take +rescue Ractor::RemoteError => e + e.cause.class #=> RuntimeError + e.cause.message #=> 'ok' + e.ractor #=> r +end +``` + +## Communication between Ractors + +Communication between Ractors is achieved by sending and receiving messages. There are two ways to communicate with each other. + +* (1) Message sending/receiving + * (1-1) push type send/receive (sender knows receiver). similar to the Actor model. + * (1-2) pull type yield/take (receiver knows sender). +* (2) Using shareable container objects + * Ractor::TVar gem ([ko1/ractor-tvar](https://github.com/ko1/ractor-tvar)) + * more? + +Users can control program execution timing with (1), but should not control with (2) (only manage as critical section). + +For message sending and receiving, there are two types of APIs: push type and pull type. + +* (1-1) send/receive (push type) + * `Ractor#send(obj)` (`Ractor#<<(obj)` is an alias) send a message to the Ractor's incoming port. Incoming port is connected to the infinite size incoming queue so `Ractor#send` will never block. + * `Ractor.receive` dequeue a message from its own incoming queue. If the incoming queue is empty, `Ractor.receive` calling will block. + * `Ractor.receive_if{|msg| filter_expr }` is variant of `Ractor.receive`. `receive_if` only receives a message which `filter_expr` is true (So `Ractor.receive` is the same as `Ractor.receive_if{ true }`. +* (1-2) yield/take (pull type) + * `Ractor.yield(obj)` send an message to a Ractor which are calling `Ractor#take` via outgoing port . If no Ractors are waiting for it, the `Ractor.yield(obj)` will block. If multiple Ractors are waiting for `Ractor.yield(obj)`, only one Ractor can receive the message. + * `Ractor#take` receives a message which is waiting by `Ractor.yield(obj)` method from the specified Ractor. If the Ractor does not call `Ractor.yield` yet, the `Ractor#take` call will block. +* `Ractor.select()` can wait for the success of `take`, `yield` and `receive`. +* You can close the incoming port or outgoing port. + * You can close then with `Ractor#close_incoming` and `Ractor#close_outgoing`. + * If the incoming port is closed for a Ractor, you can't `send` to the Ractor. If `Ractor.receive` is blocked for the closed incoming port, then it will raise an exception. + * If the outgoing port is closed for a Ractor, you can't call `Ractor#take` and `Ractor.yield` on the Ractor. If ractors are blocking by `Ractor#take` or `Ractor.yield`, closing outgoing port will raise an exception on these blocking ractors. + * 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. + * 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 + +Each Ractor has _incoming-port_ and _outgoing-port_. Incoming-port is connected to the infinite sized incoming queue. + +``` + Ractor r + +-------------------------------------------+ + | incoming outgoing | + | port port | + r.send(obj) ->*->[incoming queue] Ractor.yield(obj) ->*-> r.take + | | | + | v | + | Ractor.receive | + +-------------------------------------------+ + + +Connection example: r2.send obj on r1ã€Ractor.receive on r2 + +----+ +----+ + * r1 |---->* r2 * + +----+ +----+ + + +Connection example: Ractor.yield(obj) on r1, r1.take on r2 + +----+ +----+ + * r1 *---->- r2 * + +----+ +----+ + +Connection example: Ractor.yield(obj) on r1 and r2, + and waiting for both simultaneously by Ractor.select(r1, r2) + + +----+ + * r1 *------+ + +----+ | + +----> Ractor.select(r1, r2) + +----+ | + * r2 *------| + +----+ +``` + +```ruby +r = Ractor.new do + msg = Ractor.receive # Receive from r's incoming queue + msg # send back msg as block return value +end +r.send 'ok' # Send 'ok' to r's incoming port -> incoming queue +r.take # Receive from r's outgoing port +``` + +The last example shows the following ractor network. + +``` + + +------+ +---+ + * main |------> * r *---+ + +------+ +---+ | + ^ | + +-------------------+ +``` + +And this code can be simplified by using an argument for `Ractor.new`. + +```ruby +# Actual argument 'ok' for `Ractor.new()` will be sent to created Ractor. +r = Ractor.new 'ok' do |msg| + # Values for formal parameters will be received from incoming queue. + # Similar to: msg = Ractor.receive + + msg # Return value of the given block will be sent via outgoing port +end + +# receive from the r's outgoing port. +r.take #=> `ok` +``` + +### Return value of a block for `Ractor.new` + +As already explained, the return value of `Ractor.new` (an evaluated value of `expr` in `Ractor.new{ expr }`) can be taken by `Ractor#take`. + +```ruby +Ractor.new{ 42 }.take #=> 42 +``` + +When the block return value is available, the Ractor is dead so that no ractors except taken Ractor can touch the return value, so any values can be sent with this communication path without any modification. + +```ruby +r = Ractor.new do + a = "hello" + binding +end + +r.take.eval("p a") #=> "hello" (other communication path can not send a Binding object directly) +``` + +### Wait for multiple Ractors with `Ractor.select` + +You can wait multiple Ractor's `yield` with `Ractor.select(*ractors)`. +The return value of `Ractor.select()` is `[r, msg]` where `r` is yielding Ractor and `msg` is yielded message. + +Wait for a single ractor (same as `Ractor.take`): + +```ruby +r1 = Ractor.new{'r1'} + +r, obj = Ractor.select(r1) +r == r1 and obj == 'r1' #=> true +``` + +Wait for two ractors: + +```ruby +r1 = Ractor.new{'r1'} +r2 = Ractor.new{'r2'} +rs = [r1, r2] +as = [] + +# Wait for r1 or r2's Ractor.yield +r, obj = Ractor.select(*rs) +rs.delete(r) +as << obj + +# Second try (rs only contain not-closed ractors) +r, obj = Ractor.select(*rs) +rs.delete(r) +as << obj +as.sort == ['r1', 'r2'] #=> true +``` + +Complex example: + +```ruby +pipe = Ractor.new do + loop do + Ractor.yield Ractor.receive + end +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 #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +``` + +Multiple Ractors can send to one Ractor. + +```ruby +# Create 10 ractors and they send objects to pipe ractor. +# pipe ractor yield received objects + +pipe = Ractor.new do + loop do + Ractor.yield Ractor.receive + end +end + +RN = 10 +rs = RN.times.map{|i| + Ractor.new pipe, i do |pipe, i| + pipe << i + end +} + +RN.times.map{ + pipe.take +}.sort #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +``` + +TODO: Current `Ractor.select()` has the same issue of `select(2)`, so this interface should be refined. + +TODO: `select` syntax of go-language uses round-robin technique to make fair scheduling. Now `Ractor.select()` doesn't use it. + +### Closing Ractor's ports + +* `Ractor#close_incoming/outgoing` close incoming/outgoing ports (similar to `Queue#close`). +* `Ractor#close_incoming` + * `r.send(obj) ` where `r`'s incoming port is closed, will raise an exception. + * When the incoming queue is empty and incoming port is closed, `Ractor.receive` raises an exception. If the incoming queue is not empty, it dequeues an object without exceptions. +* `Ractor#close_outgoing` + * `Ractor.yield` on a Ractor which closed the outgoing port, it will raise an exception. + * `Ractor#take` for a Ractor which closed the outgoing port, it will raise an exception. If `Ractor#take` is blocking, it will raise an exception. +* When a Ractor terminates, the ports are closed automatically. + * Return value of the Ractor's block will be yielded as `Ractor.yield(ret_val)`, even if the implementation terminates the based native thread. + +Example (try to take from closed Ractor): + +```ruby +r = Ractor.new do + 'finish' +end +r.take # success (will return 'finish') +begin + o = r.take # try to take from closed Ractor +rescue Ractor::ClosedError + 'ok' +else + "ng: #{o}" +end +``` + +Example (try to send to closed (terminated) Ractor): + +```ruby +r = Ractor.new do +end + +r.take # wait terminate + +begin + r.send(1) +rescue Ractor::ClosedError + 'ok' +else + 'ng' +end +``` + +When multiple Ractors are waiting for `Ractor.yield()`, `Ractor#close_outgoing` will cancel all blocking by raising an exception (`ClosedError`). + +### Send a message by copying + +`Ractor#send(obj)` or `Ractor.yield(obj)` copy `obj` deeply if `obj` is an unshareable object. + +```ruby +obj = 'str'.dup +r = Ractor.new obj do |msg| + # return received msg's object_id + msg.object_id +end + +obj.object_id == r.take #=> false +``` + +Some objects are not supported to copy the value, and raise an exception. + +```ruby +obj = Thread.new{} +begin + Ractor.new obj do |msg| + msg + end +rescue TypeError => e + e.message #=> # +else + 'ng' # unreachable here +end +``` + +### Send a message by moving + +`Ractor#send(obj, move: true)` or `Ractor.yield(obj, move: true)` move `obj` to the destination Ractor. +If the source Ractor touches the moved object (for example, call the method like `obj.foo()`), it will be an error. + +```ruby +# move with Ractor#send +r = Ractor.new do + obj = Ractor.receive + obj << ' world' +end + +str = 'hello' +r.send str, move: true +modified = r.take #=> 'hello world' + +# str is moved, and accessing str from this Ractor is prohibited + +begin + # Error because it touches moved str. + str << ' exception' # raise Ractor::MovedError +rescue Ractor::MovedError + modified #=> 'hello world' +else + raise 'unreachable' +end +``` + +```ruby +# move with Ractor.yield +r = Ractor.new do + obj = 'hello' + Ractor.yield obj, move: true + obj << 'world' # raise Ractor::MovedError +end + +str = r.take +begin + r.take +rescue Ractor::RemoteError + p str #=> "hello" +end +``` + +Some objects are not supported to move, and an exception will be raised. + +```ruby +r = Ractor.new do + Ractor.receive +end + +r.send(Thread.new{}, move: true) #=> allocator undefined for Thread (TypeError) +``` + +To achieve the access prohibition for moved objects, _class replacement_ technique is used to implement it. + +### Shareable objects + +The following objects are shareable. + +* Immutable objects + * Small integers, some symbols, `true`, `false`, `nil` (a.k.a. `SPECIAL_CONST_P()` objects in internal) + * Frozen native objects + * Numeric objects: `Float`, `Complex`, `Rational`, big integers (`T_BIGNUM` in internal) + * All Symbols. + * Frozen `String` and `Regexp` objects (their instance variables should refer only shareable objects) +* Class, Module objects (`T_CLASS`, `T_MODULE` and `T_ICLASS` in internal) +* `Ractor` and other special objects which care about synchronization. + +Implementation: Now shareable objects (`RVALUE`) have `FL_SHAREABLE` flag. This flag can be added lazily. + +To make shareable objects, `Ractor.make_shareable(obj)` method is provided. In this case, try to make sharaeble by freezing `obj` and recursively travasible objects. This method accepts `copy:` keyword (default value is false).`Ractor.make_shareable(obj, copy: true)` tries to make a deep copy of `obj` and make the copied object shareable. + +## Language changes to isolate unshareable objects between Ractors + +To isolate unshareable objects between Ractors, we introduced additional language semantics on multi-Ractor Ruby programs. + +Note that without using Ractors, these additional semantics is not needed (100% compatible with Ruby 2). + +### Global variables + +Only the main Ractor (a Ractor created at starting of interpreter) can access global variables. + +```ruby +$gv = 1 +r = Ractor.new do + $gv +end + +begin + r.take +rescue Ractor::RemoteError => e + e.cause.message #=> 'can not access global variables from non-main Ractors' +end +``` + +Note that some special global variables are ractor-local, like `$stdin`, `$stdout`, `$stderr`. See [[Bug #17268]](https://bugs.ruby-lang.org/issues/17268) for more details. + +### Instance variables of shareable objects + +Instance variables of classes/modules can be get from non-main Ractors if the referring values are shareable objects. + +```ruby +class C + @iv = 1 +end + +p Ractor.new do + class C + @iv + end +end.take #=> 1 +``` + +Otherwise, only the main Ractor can access instance variables of shareable objects. + +```ruby +class C + @iv = [] # unshareable object +end + +Ractor.new do + class C + begin + p @iv + rescue Ractor::IsolationError + p $!.message + #=> "can not get unshareable values from instance variables of classes/modules from non-main Ractors" + end + + begin + @iv = 42 + rescue Ractor::IsolationError + p $!.message + #=> "can not set instance variables of classes/modules by non-main Ractors" + end + end +end.take +``` + + + +```ruby +shared = Ractor.new{} +shared.instance_variable_set(:@iv, 'str') + +r = Ractor.new shared do |shared| + p shared.instance_variable_get(:@iv) +end + +begin + r.take +rescue Ractor::RemoteError => e + e.cause.message #=> can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) +end +``` + +Note that instance variables for class/module objects are also prohibited on Ractors. + +### Class variables + +Only the main Ractor can access class variables. + +```ruby +class C + @@cv = 'str' +end + +r = Ractor.new do + class C + p @@cv + end +end + + +begin + r.take +rescue => e + e.class #=> Ractor::IsolationError +end +``` + +### Constants + +Only the main Ractor can read constants which refer to the unshareable object. + +```ruby +class C + CONST = 'str' +end +r = Ractor.new do + C::CONST +end +begin + r.take +rescue => e + e.class #=> Ractor::IsolationError +end +``` + +Only the main Ractor can define constants which refer to the unshareable object. + +```ruby +class C +end +r = Ractor.new do + C::CONST = 'str' +end +begin + r.take +rescue => e + e.class #=> Ractor::IsolationError +end +``` + +To make multi-ractor supported library, the constants should only refer shareable objects. + +```ruby +TABLE = {a: 'ko1', b: 'ko2', c: 'ko3'} +``` + +In this case, `TABLE` references an unshareable Hash object. So that other ractors can not refer `TABLE` constant. To make it shareable, we can use `Ractor.make_shareable()` like that. + +```ruby +TABLE = Ractor.make_shareable( {a: 'ko1', b: 'ko2', c: 'ko3'} ) +``` + +To make it easy, Ruby 3.0 introduced new `shareable_constant_value` Directive. + +```ruby +# shareable_constant_value: literal + +TABLE = {a: 'ko1', b: 'ko2', c: 'ko3'} +#=> Same as: TABLE = Ractor.make_shareable( {a: 'ko1', b: 'ko2', c: 'ko3'} ) +``` + +`shareable_constant_value` directive accepts the following modes (descriptions use the example: `CONST = expr`): + +* none: Do nothing. Same as: `CONST = expr` +* literal: + * if `expr` is consites of literals, replaced to `CONST = Ractor.make_shareable(expr)`. + * otherwise: replaced to `CONST = expr.tap{|o| raise unless Ractor.shareable?}`. +* experimental_everything: replaced to `CONST = Ractor.make_shareable(expr)`. +* experimental_copy: replaced to `CONST = Ractor.make_shareable(expr, copy: true)`. + +Except the `none` mode (default), it is guaranteed that the assigned constants refer to only shareable objects. + +See [doc/syntax/comments.rdoc](syntax/comments.rdoc) for more details. + +## Implementation note + +* Each Ractor has its own thread, it means each Ractor has at least 1 native thread. +* Each Ractor has its own ID (`rb_ractor_t::pub::id`). + * On debug mode, all unshareable objects are labeled with current Ractor's id, and it is checked to detect unshareable object leak (access an object from different Ractor) in VM. + +## Examples + +### Traditional Ring example in Actor-model + +```ruby +RN = 1_000 +CR = Ractor.current + +r = Ractor.new do + p Ractor.receive + CR << :fin +end + +RN.times{ + r = Ractor.new r do |next_r| + next_r << Ractor.receive + end +} + +p :setup_ok +r << 1 +p Ractor.receive +``` + +### Fork-join + +```ruby +def fib n + if n < 2 + 1 + else + fib(n-2) + fib(n-1) + end +end + +RN = 10 +rs = (1..RN).map do |i| + Ractor.new i do |i| + [i, fib(i)] + end +end + +until rs.empty? + r, v = Ractor.select(*rs) + rs.delete r + p answer: v +end +``` + +### Worker pool + +```ruby +require 'prime' + +pipe = Ractor.new do + loop do + Ractor.yield Ractor.receive + end +end + +N = 1000 +RN = 10 +workers = (1..RN).map do + Ractor.new pipe do |pipe| + while n = pipe.take + Ractor.yield [n, n.prime?] + end + end +end + +(1..N).each{|i| + pipe << i +} + +pp (1..N).map{ + _r, (n, b) = Ractor.select(*workers) + [n, b] +}.sort_by{|(n, b)| n} +``` + +### Pipeline + +```ruby +# pipeline with yield/take +r1 = Ractor.new do + 'r1' +end + +r2 = Ractor.new r1 do |r1| + r1.take + 'r2' +end + +r3 = Ractor.new r2 do |r2| + r2.take + 'r3' +end + +p r3.take #=> 'r1r2r3' +``` + +```ruby +# pipeline with send/receive + +r3 = Ractor.new Ractor.current do |cr| + cr.send Ractor.receive + 'r3' +end + +r2 = Ractor.new r3 do |r3| + r3.send Ractor.receive + 'r2' +end + +r1 = Ractor.new r2 do |r2| + r2.send Ractor.receive + 'r1' +end + +r1 << 'r0' +p Ractor.receive #=> "r0r1r2r3" +``` + +### Supervise + +```ruby +# ring example again + +r = Ractor.current +(1..10).map{|i| + r = Ractor.new r, i do |r, i| + r.send Ractor.receive + "r#{i}" + end +} + +r.send "r0" +p Ractor.receive #=> "r0r10r9r8r7r6r5r4r3r2r1" +``` + +```ruby +# ring example with an error + +r = Ractor.current +rs = (1..10).map{|i| + r = Ractor.new r, i do |r, i| + loop do + msg = Ractor.receive + raise if /e/ =~ msg + r.send msg + "r#{i}" + end + end +} + +r.send "r0" +p Ractor.receive #=> "r0r10r9r8r7r6r5r4r3r2r1" +r.send "r0" +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) +``` + +```ruby +# resend non-error message + +r = Ractor.current +rs = (1..10).map{|i| + r = Ractor.new r, i do |r, i| + loop do + msg = Ractor.receive + raise if /e/ =~ msg + r.send msg + "r#{i}" + end + end +} + +r.send "r0" +p Ractor.receive #=> "r0r10r9r8r7r6r5r4r3r2r1" +r.send "r0" +p Ractor.select(*rs, Ractor.current) +[:receive, "r0r10r9r8r7r6r5r4r3r2r1"] +msg = 'e0' +begin + r.send msg + p Ractor.select(*rs, Ractor.current) +rescue Ractor::RemoteError + msg = 'r0' + retry +end + +#=> :100:in `send': The incoming-port is already closed (Ractor::ClosedError) +# because r == r[-1] is terminated. +``` + +```ruby +# ring example with supervisor and re-start + +def make_ractor r, i + Ractor.new r, i do |r, i| + loop do + msg = Ractor.receive + raise if /e/ =~ msg + r.send msg + "r#{i}" + end + end +end + +r = Ractor.current +rs = (1..10).map{|i| + r = make_ractor(r, i) +} + +msg = 'e0' # error causing message +begin + r.send msg + p Ractor.select(*rs, Ractor.current) +rescue Ractor::RemoteError + r = rs[-1] = make_ractor(rs[-2], rs.size-1) + msg = 'x0' + retry +end + +#=> [:receive, "x0r9r9r8r7r6r5r4r3r2r1"] +``` diff --git a/ruby/doc/regexp.rdoc b/ruby/doc/regexp.rdoc index d84cae177..23fe7113b 100644 --- a/ruby/doc/regexp.rdoc +++ b/ruby/doc/regexp.rdoc @@ -190,6 +190,8 @@ At least one uppercase character ('H'), at least one lowercase character "Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> # +=== Greedy match + Repetition is greedy by default: as many occurrences as possible are matched while still allowing the overall match to succeed. By contrast, lazy matching makes the minimal amount of matches @@ -206,21 +208,27 @@ Both patterns below match the string. The first uses a greedy quantifier so /<.+>/.match("") #=> #"> /<.+?>/.match("") #=> #"> +=== Possessive match + A quantifier followed by + matches possessively: once it has matched it does not backtrack. They behave like greedy quantifiers, but having matched they refuse to "give up" their match even if this jeopardises the overall match. + /<.*><.+>/.match("") #=> #"> + /<.*+><.+>/.match("") #=> nil + /<.*><.++>/.match("") #=> nil + == Capturing Parentheses can be used for capturing. The text enclosed by the -nth group of parentheses can be subsequently referred to +nth group of parentheses can be subsequently referred to with n. Within a pattern use the backreference -\n; outside of the pattern use -MatchData[n]. +\n (e.g. \1); outside of the pattern use +MatchData[n] (e.g. MatchData[1]). -'at' is captured by the first group of parentheses, then referred to later -with \1: +In this example, 'at' is captured by the first group of +parentheses, then referred to later with \1: /[csh](..) [csh]\1 in/.match("The cat sat in the hat") #=> # @@ -230,6 +238,23 @@ available with its #[] method: /[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at' +While Ruby supports an arbitrary number of numbered captured groups, +only groups 1-9 are supported using the \n backreference +syntax. + +Ruby also supports \0 as a special backreference, which +references the entire matched string. This is also available at +MatchData[0]. Note that the \0 backreference cannot +be used inside the regexp, as backreferences can only be used after the +end of the capture group, and the \0 backreference uses the +implicit capture group of the entire match. However, you can use +this backreference when doing substitution: + + "The cat sat in the hat".gsub(/[csh]at/, '\0s') + # => "The cats sats in the hats" + +=== Named captures + Capture groups can be referred to by name when defined with the (?<name>) or (?'name') constructs. @@ -362,8 +387,8 @@ then matches a literal ): == Alternation -The vertical bar metacharacter (|) combines two expressions into -a single one that matches either of the expressions. Each expression is an +The vertical bar metacharacter (|) combines several expressions into +a single one that matches any of the expressions. Each expression is an alternative. /\w(and|or)\w/.match("Feliformia") #=> # @@ -514,6 +539,17 @@ characters, anchoring the match to a specific position. * (?pat) - Negative lookbehind assertion: ensures that the preceding characters do not match pat, but doesn't include those characters in the matched text +* \K - Uses an positive lookbehind of the content preceding + \K in the regexp. For example, the following two regexps are + almost equivalent: + + /ab\Kc/ + /(?<=ab)c/ + + As are the following two regexps: + + /(a)\K(b)\Kc/ + /(?<=(?<=(a))(b))c/ If a pattern isn't anchored it can begin at any point in the string: diff --git a/ruby/doc/standard_library.rdoc b/ruby/doc/standard_library.rdoc index f71cedebf..1d3580163 100644 --- a/ruby/doc/standard_library.rdoc +++ b/ruby/doc/standard_library.rdoc @@ -8,105 +8,91 @@ description. == 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 -DEBUGGER__:: Debugging functionality for Ruby -DRb:: Distributed object system for Ruby -English.rb:: Require 'English.rb' to reference global variables with less cryptic names -ERB:: An easy to use but powerful templating system for Ruby -Find:: This module supports top-down traversal of a set of file paths MakeMakefile:: Module used to generate a Makefile for C extensions -Monitor:: Provides an object or module to use safely by more than one thread -Net::FTP:: Support for the File Transfer Protocol -Net::HTTP:: HTTP client api for Ruby -Net::IMAP:: Ruby client api for Internet Message Access Protocol -OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP -OptionParser:: Ruby-oriented class for command-line option analysis -PP:: Provides a PrettyPrinter for Ruby objects -PrettyPrinter:: Implements a pretty printing algorithm for readable structure RbConfig:: Information of your configure and build of Ruby -resolv-replace.rb:: Replace Socket DNS with Resolv -Resolv:: Thread-aware DNS resolver library in Ruby -Rinda:: The Linda distributed computing paradigm in Ruby Gem:: Package management framework for 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 -Tempfile:: A utility class for managing temporary files -Time:: Extends the Time class with methods for parsing and conversion -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 -WeakRef:: Allows a referenced object to be garbage-collected == Extensions Coverage:: Provides coverage measurement for Ruby -Digest:: Provides a framework for message digest libraries -IO:: Extensions for Ruby IO class, including #wait and ::console -NKF:: Ruby extension for Network Kanji Filter +Monitor:: Provides an object or module to use safely by more than one thread objspace:: Extends ObjectSpace module to add methods for internal statistics -Pathname:: Representation of the name of a file or directory on the filesystem PTY:: Creates and manages pseudo terminals Ripper:: Provides an interface for parsing Ruby programs into S-expressions Socket:: Access underlying OS socket implementations -Syslog:: Ruby interface for the POSIX system logging facility -WIN32OLE:: Provides an interface for OLE Automation in Ruby = Default gems == 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 +DEBUGGER__:: Debugging functionality for Ruby 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 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 -Matrix:: Represents a mathematical matrix. Mutex_m:: Mixin to extend objects to be handled like a Mutex -Net::POP3:: Ruby client library for POP3 -Net::SMTP:: Simple Mail Transfer Protocol client library for Ruby +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 -Prime:: Prime numbers and factorization library +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 -Racc:: A LALR(1) parser generator written in Ruby. +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 -REXML:: An XML toolkit for Ruby -RSS:: Family of libraries that support various formats of XML "feeds" +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 -Tracer:: Outputs a source level execution trace of a Ruby program +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 -WEBrick:: An HTTP server toolkit for Ruby 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 -DBM:: Provides a wrapper for the UNIX-style Database Manager Library +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 -GDBM:: Ruby extension for the GNU dbm (gdbm) library -IO::console:: Console interface +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 +Racc:: A LALR(1) parser generator written in Ruby. Readline:: Provides an interface for GNU Readline and Edit Line (libedit) -SDBM:: Provides a simple file-based key-value store with String keys and values 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 @@ -114,8 +100,16 @@ Zlib:: Ruby interface for the zlib compression/decompression library == Libraries MiniTest:: A test suite with TDD, BDD, mocking and benchmarking -Net::Telnet:: Telnet client library for Ruby PowerAssert:: Power Assert for Ruby. Rake:: Ruby build program with capabilities similar to make Test::Unit:: A compatibility layer for MiniTest -XMLRPC:: Remote Procedure Call over HTTP support for Ruby +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 diff --git a/ruby/doc/syntax.rdoc b/ruby/doc/syntax.rdoc index 2463c12a6..5895673f3 100644 --- a/ruby/doc/syntax.rdoc +++ b/ruby/doc/syntax.rdoc @@ -11,6 +11,9 @@ Assignment[rdoc-ref:syntax/assignment.rdoc] :: {Control Expressions}[rdoc-ref:syntax/control_expressions.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 + Methods[rdoc-ref:syntax/methods.rdoc] :: Method and method argument syntax @@ -27,7 +30,7 @@ Precedence[rdoc-ref:syntax/precedence.rdoc] :: Precedence of ruby operators Refinements[rdoc-ref:syntax/refinements.rdoc] :: - Use and behavior of the experimental refinements feature + Use and behavior of the refinements feature Miscellaneous[rdoc-ref:syntax/miscellaneous.rdoc] :: +alias+, +undef+, +BEGIN+, +END+ diff --git a/ruby/doc/syntax/calling_methods.rdoc b/ruby/doc/syntax/calling_methods.rdoc index 5abecc69d..da061dbfd 100644 --- a/ruby/doc/syntax/calling_methods.rdoc +++ b/ruby/doc/syntax/calling_methods.rdoc @@ -30,7 +30,41 @@ NoMethodError. You may also use :: to designate a receiver, but this is rarely used due to the potential for confusion with :: for namespaces. -=== Safe navigation operator +=== Chaining \Method Calls + +You can "chain" method calls by immediately following one method call with another. + +This example chains methods Array#append and Array#compact: + + a = [:foo, 'bar', 2] + a1 = [:baz, nil, :bam, nil] + a2 = a.append(*a1).compact + a2 # => [:foo, "bar", 2, :baz, :bam] + +Details: + +- First method merge creates a copy of a, + appends (separately) each element of a1 to the copy, and returns + [:foo, "bar", 2, :baz, nil, :bam, nil] +- Chained method compact creates a copy of that return value, + removes its nil-valued entries, and returns + [:foo, "bar", 2, :baz, :bam] + +You can chain methods that are in different classes. +This example chains methods Hash#to_a and Array#reverse: + + h = {foo: 0, bar: 1, baz: 2} + h.to_a.reverse # => [[:baz, 2], [:bar, 1], [:foo, 0]] + +Details: + +- First method Hash#to_a converts a to an \Array, and returns + [[:foo, 0], [:bar, 1], [:baz, 2]] +- Chained method Array#reverse creates copy of that return value, + reverses it, and returns + [[:baz, 2], [:bar, 1], [:foo, 0]] + +=== Safe Navigation Operator &., called "safe navigation operator", allows to skip method call when receiver is +nil+. It returns +nil+ and doesn't evaluate method's arguments @@ -176,6 +210,24 @@ 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 +from the context by the name of the key + + keyword1 = 'some value' + my_method(positional1, keyword1:) + # ...is the same as + my_method(positional1, keyword1: keyword1) + +Be aware that when method parenthesis are omitted, too, the parsing order might +be unexpected: + + my_method positional1, keyword1: + + some_other_expression + + # ...is actually parsed as + my_method(positional1, keyword1: some_other_expression) + === Block Argument The block argument sends a closure from the calling scope to the method. diff --git a/ruby/doc/syntax/comments.rdoc b/ruby/doc/syntax/comments.rdoc index a07dd4149..dbc781698 100644 --- a/ruby/doc/syntax/comments.rdoc +++ b/ruby/doc/syntax/comments.rdoc @@ -35,3 +35,219 @@ syntax error: Will not work =end end + +== Magic Comments + +While comments are typically ignored by Ruby, special "magic comments" contain +directives that affect how the code is interpreted. + +Top-level magic comments must appear in the first comment section of a file. + +NOTE: Magic comments affect only the file in which they appear; +other files are unaffected. + + # frozen_string_literal: true + + var = 'hello' + var.frozen? # => true + +=== Alternative syntax + +Magic comments may consist of a single directive (as in the example above). +Alternatively, multiple directives may appear on the same line if separated by ";" +and wrapped between "-*-" (see Emacs' {file variables}[https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html]). + + # emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*- + + p 'hello'.frozen? # => true + p 'hello'.encoding # => # + +=== +encoding+ Directive + +Indicates which string encoding should be used for string literals, +regexp literals and __ENCODING__: + + # encoding: big5 + + ''.encoding # => # + +Default encoding is UTF-8. + +Top-level magic comments must start on the first line, or on the second line if +the first line looks like #! shebang line. + +The word "coding" may be used instead of "encoding". + +=== +frozen_string_literal+ Directive + +Indicates that string literals should be allocated once at parse time and frozen. + + # frozen_string_literal: true + + 3.times do + p 'hello'.object_id # => prints same number + end + p 'world'.frozen? # => true + +The default is false; this can be changed with --enable=frozen-string-literal. +Without the directive, or with # frozen_string_literal: false, +the example above would print 3 different numbers and "false". + +Starting in Ruby 3.0, string literals that are dynamic are not frozen nor reused: + + # frozen_string_literal: true + + p "Addition: #{2 + 2}".frozen? # => false + +It must appear in the first comment section of a file. + +=== +warn_indent+ Directive + +This directive can turn on detection of bad indentation for statements that follow it: + + def foo + end # => no warning + + # warn_indent: true + def bar + end # => warning: mismatched indentations at 'end' with 'def' at 6 + +Another way to get these warnings to show is by running Ruby with warnings (ruby -w). Using a directive to set this false will prevent these warnings to show. + +=== +shareable_constant_value+ Directive + +Note: This directive is experimental in Ruby 3.0 and may change in future releases. + +This special directive helps to create constants that hold only immutable objects, or {Ractor-shareable}[rdoc-ref:Ractor@Shareable+and+unshareable+objects] constants. + +The directive can specify special treatment for values assigned to constants: + +* +none+: (default) +* +literal+: literals are implicitly frozen, others must be Ractor-shareable +* +experimental_everything+: all made shareable +* +experimental_copy+: copy deeply and make it shareable + +==== Mode +none+ (default) + +No special treatment in this mode (as in Ruby 2.x): no automatic freezing and no checks. + +It has always been a good idea to deep-freeze constants; Ractor makes this +an even better idea as only the main ractor can access non-shareable constants: + + # shareable_constant_value: none + A = {foo: []} + A.frozen? # => false + Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor. + +==== Mode +literal+ + +In "literal" mode, constants assigned to literals will be deeply-frozen: + + # shareable_constant_value: literal + X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze + +Other values must be shareable: + + # shareable_constant_value: literal + X = Object.new # => cannot assign unshareable object to X + +Note that only literals directly assigned to constants, or recursively held in such literals will be frozen: + + # shareable_constant_value: literal + var = [{foo: []}] + var.frozen? # => false (assignment was made to local variable) + X = var # => cannot assign unshareable object to X + + X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X + # (`Set[...]` is not a literal and + # `{foo: []}` is an argument to `Set.[]`) + +The method Module#const_set is not affected. + +==== Mode +experimental_everything+ + +In this mode, all values assigned to constants are made shareable. + + # shareable_constant_value: experimental_everything + FOO = Set[1, 2, {foo: []}] + # same as FOO = Ractor.make_sharable(...) + # OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze` + + var = [{foo: []}] + var.frozen? # => false (assignment was made to local variable) + X = var # => calls `Ractor.make_shareable(var)` + var.frozen? # => true + +This mode is "experimental", because it might be error prone, for +example by deep-freezing the constants of an external resource which +could cause errors: + + # shareable_constant_value: experimental_everything + FOO = SomeGem::Something::FOO + # => deep freezes the gem's constant! + +This will be revisited before Ruby 3.1 to either allow `everything` +or to instead remove this mode. + +The method Module#const_set is not affected. + +==== Mode +experimental_copy+ + +In this mode, all values assigned to constants are deeply copied and +made shareable. It is safer mode than +experimental_everything+. + + # shareable_constant_value: experimental_everything + var = [{foo: []}] + var.frozen? # => false (assignment was made to local variable) + X = var # => calls `Ractor.make_shareable(var, copy: true)` + var.frozen? # => false + Ractor.shareable?(X) #=> true + var.object_id == X.object_id #=> false + +This mode is "experimental" and has not been discussed thoroughly. +This will be revisited before Ruby 3.1 to either allow `copy` +or to instead remove this mode. + +The method Module#const_set is not affected. + +==== Scope + +This directive can be used multiple times in the same file: + + # shareable_constant_value: none + A = {foo: []} + A.frozen? # => false + Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor. + + # shareable_constant_value: literal + B = {foo: []} + B.frozen? # => true + B[:foo].frozen? # => true + + C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError) + + D = [Object.new.freeze] + D.frozen? # => true + + # shareable_constant_value: experimental_everything + E = Set[1, 2, Object.new] + E.frozen? # => true + E.all(&:frozen?) # => true + +The directive affects only subsequent constants and only for the current scope: + + module Mod + # shareable_constant_value: literal + A = [1, 2, 3] + module Sub + B = [4, 5] + end + end + + C = [4, 5] + + module Mod + D = [6] + end + p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true + p C.frozen?, Mod::D.frozen? # => false, false diff --git a/ruby/doc/syntax/control_expressions.rdoc b/ruby/doc/syntax/control_expressions.rdoc index f7e6d5492..e91b03e72 100644 --- a/ruby/doc/syntax/control_expressions.rdoc +++ b/ruby/doc/syntax/control_expressions.rdoc @@ -232,7 +232,7 @@ You may use +then+ after the +when+ condition. This is most frequently used to place the body of the +when+ on a single line. case a - when 1, 2 then puts "a is one or two + when 1, 2 then puts "a is one or two" when 3 then puts "a is three" else puts "I don't know what a is" end @@ -255,6 +255,20 @@ 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 +pattern matching feature via the +in+ keyword: + + case {a: 1, b: 2, c: 3} + in a: Integer => m + "matched: #{m}" + else + "not matched" + end + # => "matched: 1" + +The pattern matching syntax is described on +{its own page}[rdoc-ref:syntax/pattern_matching.rdoc]. + == +while+ Loop The +while+ loop executes while a condition is true: diff --git a/ruby/doc/syntax/literals.rdoc b/ruby/doc/syntax/literals.rdoc index 38bfa3867..32fe5110c 100644 --- a/ruby/doc/syntax/literals.rdoc +++ b/ruby/doc/syntax/literals.rdoc @@ -2,17 +2,33 @@ Literals create objects you can use in your program. Literals include: -* Booleans and nil -* Numbers -* Strings -* Symbols -* Arrays -* Hashes -* Ranges -* Regular Expressions -* Procs - -== Booleans and nil +* {Boolean and Nil Literals}[#label-Boolean+and+Nil+Literals] +* {Number Literals}[#label-Number+Literals] + + * {Integer Literals}[#label-Integer+Literals] + * {Float Literals}[#label-Float+Literals] + * {Rational Literals}[#label-Rational+Literals] + * {Complex Literals}[#label-Complex+Literals] + +* {String Literals}[#label-String+Literals] +* {Here Document Literals}[#label-Here+Document+Literals] +* {Symbol Literals}[#label-Symbol+Literals] +* {Array Literals}[#label-Array+Literals] +* {Hash Literals}[#label-Hash+Literals] +* {Range Literals}[#label-Range+Literals] +* {Regexp Literals}[#label-Regexp+Literals] +* {Lambda Proc Literals}[#label-Lambda+Proc+Literals] +* {Percent Literals}[#label-Percent+Literals] + + * {%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] + * {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals] + * {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals] + * {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals] + * {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals] + * {%x: Backtick Literals}[#label-25x-3A+Backtick+Literals] + +== Boolean and Nil Literals +nil+ and +false+ are both false values. +nil+ is sometimes used to indicate "no value" or "unknown" but evaluates to +false+ in conditional expressions. @@ -20,10 +36,9 @@ Literals create objects you can use in your program. Literals include: +true+ is a true value. All objects except +nil+ and +false+ evaluate to a true value in conditional expressions. -(There are also the constants +TRUE+, +FALSE+ and +NIL+, but the lowercase -literal forms are preferred.) +== Number Literals -== Numbers +=== \Integer Literals You can write integers of any size as follows: @@ -34,15 +49,6 @@ These numbers have the same value, 1,234. The underscore may be used to enhance readability for humans. You may place an underscore anywhere in the number. -Floating point numbers may be written as follows: - - 12.34 - 1234e-2 - 1.234E1 - -These numbers have the same value, 12.34. You may use underscores in floating -point numbers as well. - You can use a special prefix to write numbers in decimal, hexadecimal, octal or binary formats. For decimal numbers use a prefix of 0d, for hexadecimal numbers use a prefix of 0x, for octal numbers use a @@ -71,35 +77,48 @@ Examples: All these numbers have the same decimal value, 170. Like integers and floats you may use an underscore for readability. -=== Rational numbers +=== \Float Literals + +Floating-point numbers may be written as follows: + + 12.34 + 1234e-2 + 1.234E1 + +These numbers have the same value, 12.34. You may use underscores in floating +point numbers as well. + +=== \Rational Literals -Numbers suffixed by +r+ are Rational numbers. +You can write a Rational number as follows (suffixed +r+): 12r #=> (12/1) 12.3r #=> (123/10) -Rational numbers are exact, whereas Float numbers are inexact. +A \Rational number is exact, whereas a \Float number may be inexact. 0.1r + 0.2r #=> (3/10) 0.1 + 0.2 #=> 0.30000000000000004 -=== Complex numbers +=== \Complex Literals -Numbers suffixed by +i+ are Complex (or imaginary) numbers. +You can write a Complex number as follows (suffixed +i+): 1i #=> (0+1i) 1i * 1i #=> (-1+0i) -Also Rational numbers may be imaginary numbers. +Also \Rational numbers may be imaginary numbers. 12.3ri #=> (0+(123/10)*i) -+i+ must be placed after +r+, the opposite is not allowed. ++i+ must be placed after +r+; the opposite is not allowed. - 12.3ir #=> syntax error + 12.3ir #=> Syntax error == Strings +=== \String Literals + The most common way of writing strings is using ": "This is a string." @@ -146,6 +165,10 @@ Double-quote strings allow interpolation of other values using Any expression may be placed inside the interpolated section, but it's best to keep the expression small for readability. +You can also use #@foo, #@@foo and #$foo as a +shorthand for, respectively, #{ @foo }, #{ @@foo } and +#{ $foo }. + Interpolation may be disabled by escaping the "#" character or using single-quote strings: @@ -155,15 +178,6 @@ In addition to disabling interpolation, single-quoted strings also disable all escape sequences except for the single-quote (\') and backslash (\\\\). -You may also create strings using %: - - %(1 + 1 is #{1 + 1}) #=> "1 + 1 is 2" - -There are two different types of % strings %q(...) behaves -like a single-quote string (no interpolation or character escaping), while -%Q behaves as a double-quote string. See Percent Strings below for -more discussion of the syntax of percent strings. - Adjacent string literals are automatically concatenated by the interpreter: "con" "cat" "en" "at" "ion" #=> "concatenation" @@ -193,7 +207,12 @@ a single codepoint in the script encoding: ?\C-\M-a #=> "\x81", same as above ?ã‚ #=> "ã‚" -=== Here Documents (heredocs) +See also: + +* {%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] + +=== Here Document Literals If you are writing a large block of text you may use a "here document" or "heredoc": @@ -219,7 +238,7 @@ You may indent the ending identifier if you place a "-" after <<: That might span many lines INDENTED_HEREDOC -Note that the while the closing identifier may be indented, the content is +Note that while the closing identifier may be indented, the content is always treated as if it is flush left. If you indent the content those spaces will appear in the output. @@ -273,7 +292,7 @@ read: content for heredoc two TWO -== Symbols +== \Symbol Literals A Symbol represents a name inside the ruby interpreter. See Symbol for more details on what symbols are and when ruby creates them internally. @@ -292,7 +311,12 @@ Like strings, a single-quote may be used to disable interpolation: When creating a Hash, there is a special syntax for referencing a Symbol as well. -== Arrays +See also: + +* {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals] + + +== \Array Literals An array is created using the objects between [ and ]: @@ -303,9 +327,14 @@ You may place expressions inside the array: [1, 1 + 1, 1 + 2] [1, [1 + 1, [1 + 2]]] +See also: + +* {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals] +* {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals] + See Array for the methods you may use with an array. -== Hashes +== \Hash Literals A hash is created using key-value pairs between { and }: @@ -327,9 +356,17 @@ is equal to { :"a 1" => 1, :"b 2" => 2 } +Hash values can be omitted, meaning that value will be fetched from the context +by the name of the key: + + x = 100 + y = 200 + h = { x:, y: } + #=> {:x=>100, :y=>200} + See Hash for the methods you may use with a hash. -== Ranges +== \Range Literals A range represents an interval of values. The range may include or exclude its ending value. @@ -342,7 +379,7 @@ its ending value. You may create a range of any object. See the Range documentation for details on the methods you need to implement. -== Regular Expressions +== \Regexp Literals A regular expression is created using "/": @@ -358,11 +395,15 @@ Interpolation may be used inside regular expressions along with escaped characters. Note that a regular expression may require additional escaped characters than a string. +See also: + +* {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals] + See Regexp for a description of the syntax of regular expressions. -== Procs +== Lambda Proc Literals -A proc can be created with ->: +A lambda proc can be created with ->: -> { 1 + 1 } @@ -374,27 +415,83 @@ You can require arguments for the proc as follows: This proc will add one to its argument. -== Percent Strings +== Percent Literals + +Each of the literals in described in this section +may use these paired delimiters: + +* [ and ]. +* ( and ). +* { and }. +* < and >. +* Any other character, as both beginning and ending delimiters. + +These are demonstrated in the next section. + +=== %q: Non-Interpolable String Literals + +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(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation. + +=== % and %Q: Interpolable String Literals + +You can write an interpolable string with %Q +or with its alias %: + + %[foo bar baz] # => "foo bar baz" + %(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation. + +=== %w and %W: String-Array Literals + +You can write an array of strings 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(#{1 + 1}) # => ["\#{1", "+", "1}"] + %W(#{1 + 1}) # => ["2"] + +=== %i and %I: Symbol-Array Literals + +You can write an array of symbols 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(#{1 + 1}) # => [:"\#{1", :+, :"1}"] + %I(#{1 + 1}) # => [:"2"] + +=== %s: Symbol Literals + +You can write a symbol with %s: + + %s[foo] # => :foo + %s[foo bar] # => :"foo bar" + +=== %r: Regexp Literals -Besides %(...) which creates a String, the % may create -other types of object. As with strings, an uppercase letter allows -interpolation and escaped characters while a lowercase letter disables them. +You can write a regular expression with %r: -These are the types of percent strings in ruby: + r = %r[foo\sbar] # => /foo\sbar/ + 'foo bar'.match(r) # => # + r = %r[foo\sbar]i # => /foo\sbar/i + 'FOO BAR'.match(r) # => # -%i :: Array of Symbols -%q :: String -%r :: Regular Expression -%s :: Symbol -%w :: Array of Strings -%x :: Backtick (capture subshell result) -For the two array forms of percent string, if you wish to include a space in -one of the array entries you must escape it with a "\\" character: +=== %x: Backtick Literals - %w[one one-hundred\ one] - #=> ["one", "one-hundred one"] +You can write and execute a shell command with %x: -If you are using "(", "[", "{", "<" you must close it with ")", "]", "}", ">" -respectively. You may use most other non-alphanumeric characters for percent -string delimiters such as "%", "|", "^", etc. + %x(echo 1) # => "1\n" diff --git a/ruby/doc/syntax/methods.rdoc b/ruby/doc/syntax/methods.rdoc index c11bd449b..2bb350def 100644 --- a/ruby/doc/syntax/methods.rdoc +++ b/ruby/doc/syntax/methods.rdoc @@ -11,6 +11,11 @@ A method definition consists of the +def+ keyword, a method name, the body of the method, +return+ value and the +end+ keyword. When called the method will execute the body of the method. This method returns +2+. +Since Ruby 3.0, there is also a shorthand syntax for methods consisting +of exactly one expression: + + def one_plus_one = 1 + 1 + This section only covers defining methods. See also the {syntax documentation on calling methods}[rdoc-ref:syntax/calling_methods.rdoc]. @@ -64,6 +69,23 @@ object to indicate a true value (or "truthy" value). Methods that end with an equals sign indicate an assignment method. + class C + def attr + @attr + end + + def attr=(val) + @attr = val + end + end + + c = C.new + c.attr #=> nil + c.attr = 10 # calls "attr=(10)" + c.attr #=> 10 + +Assignment methods can not be defined using the shorthand syntax. + These are method names for the various Ruby operators. Each of these operators accepts only one argument. Following the operator is the typical use or name of the operator. Creating an alternate meaning for the operator @@ -258,6 +280,13 @@ The parentheses around the arguments are optional: value + 1 end +The parentheses are mandatory in shorthand method definitions: + + # OK + def add_one(value) = value + 1 + # SyntaxError + def add_one value = value + 1 + Multiple arguments are separated by a comma: def add_values(a, b) @@ -389,8 +418,8 @@ It is possible to gather arguments at the beginning or in the middle: gather_arguments 1, 2, 3, 4 # prints [2, 3] -The array argument will capture a Hash as the last entry if a hash was sent by -the caller after all positional arguments. +The array argument will capture a Hash as the last entry if keywords were +provided by the caller after all positional arguments. def gather_arguments(*arguments) p arguments @@ -462,107 +491,105 @@ Calling such a method with keywords or a non-empty keyword splat will result in an ArgumentError. This syntax is supported so that keywords can be added to the method later without affected backwards compatibility. -=== Keyword and Positional Argument Separation - -Between Ruby 2.0 and 2.6, keyword and positional arguments were not -separated, and a keyword argument could be used as a positional argument -and vice-versa. In Ruby 3.0, keyword and positional arguments will -be separated if the method definition includes keyword arguments. -In Ruby 3.0, if the method definition does not include keyword arguments, -keyword arguments provided when calling the method will continue to be -treated as a final positional hash argument. - -Currently, the keyword and positional arguments are not separated, -but cases where behavior will change in Ruby 3.0 will result in a -warning being emitted. +If a method definition does not accept any keywords, and the +**nil syntax is not used, any keywords provided when calling +the method will be converted to a Hash positional argument: -There are a few different types of keyword argument separation issues. + def meth(arg) + arg + end + meth(a: 1) + # => {:a=>1} -==== Conversion of Hash to Keywords +=== Block Argument -If a method is called with the hash, the hash could be treated as -keywords: +The block argument is indicated by & and must come last: - def my_method(**keywords) - keywords + def my_method(&my_block) + my_block.call(self) end - my_method({a: 1}) # {:a => 1} -This occurs even if the hash could be an optional positional argument -or an element of a rest argument: +Most frequently the block argument is used to pass a block to another method: - def my_method(hash=nil, **keywords) - [hash, keywords] + def each_item(&block) + @items.each(&block) end - my_method({a: 1}) # [nil, {:a => 1}] - def my_method(*args, **keywords) - [args, keywords] +You are not required to give a name to the block if you will just be passing +it to another method: + + def each_item(&) + @items.each(&) end - my_method({a: 1}) # [[], {:a => 1}] -However, if the hash is needed for a mandatory positional argument, -it would not be treated as keywords: +If you are only going to call the block and will not otherwise manipulate it +or send it to another method, using yield without an explicit +block parameter is preferred. This method is equivalent to the first method +in this section: - def my_method(hash, **keywords) - [hash, keywords] + def my_method + yield self end - my_method({a: 1}) # [{:a => 1}, {}] -==== Conversion of Keywords to Positional Arguments +=== Argument Forwarding -If a method is called with keywords, but it is missing one -mandatory positional argument, the keywords are converted to -a hash and the hash used as the mandatory positional argument: +Since Ruby 2.7, an all-arguments forwarding syntax is available: - def my_method(hash, **keywords) - [hash, keywords] + def concrete_method(*positional_args, **keyword_args, &block) + [positional_args, keyword_args, block] end - my_method(a: 1) # [{:a => 1}, {}] - -This is also true for empty keyword splats: - kw = {} - my_method(**kw) # [{}, {}] + def forwarding_method(...) + concrete_method(...) + end -==== Splitting of Positional Hashes or Keywords + forwarding_method(1, b: 2) { puts 3 } + #=> [[1], {:b=>2}, #] -If a method definition accepts specific keywords and not arbitrary keywords, -keywords or a positional hash may be split if the hash includes both Symbol -keys and non-Symbol keys and the keywords or positional hash are not needed -as a mandatory positional argument. In this case, the non-Symbol keys are -separated into a positional argument hash, and the Symbol keys are used -as the keyword arguments: +Calling with forwarding ... is available only in methods +defined with .... - def my_method(hash=3, a: 4) - [hash, a] + def regular_method(arg, **kwarg) + concrete_method(...) # Syntax error end - my_method(a: 1, 'a' => 2) # [{"a"=>2}, 1] - my_method({a: 1, 'a' => 2}) # [{"a"=>2}, 1] -== Block Argument +Since Ruby 3.0, there can be leading arguments before ... +both in definitions and in invocations (but in definitions they can be +only positional arguments without default values). -The block argument is indicated by & and must come last: + def request(method, path, **headers) + puts "#{method.upcase} #{path} #{headers}" + end - def my_method(&my_block) - my_block.call(self) + def get(...) + request(:GET, ...) # leading argument in invoking end -Most frequently the block argument is used to pass a block to another method: + get('http://ruby-lang.org', 'Accept' => 'text/html') + # Prints: GET http://ruby-lang.org {"Accept"=>"text/html"} - def each_item(&block) - @items.each(&block) + def logged_get(msg, ...) # leading argument in definition + puts "Invoking #get: #{msg}" + get(...) end -If you are only going to call the block and will not otherwise manipulate it -or send it to another method using yield without an explicit -block parameter is preferred. This method is equivalent to the first method -in this section: + logged_get('Ruby site', 'http://ruby-lang.org') + # Prints: + # Invoking #get: Ruby site + # GET http://ruby-lang.org {} - def my_method - yield self +Note that omitting parentheses in forwarding calls may lead to +unexpected results: + + def log(...) + puts ... # This would be treated as `puts()...', + # i.e. endless range from puts result end + log("test") + # Prints: warning: ... at EOL, should be parenthesized? + # ...and then empty line + == Exception Handling Methods have an implied exception handling block so you do not need to use diff --git a/ruby/doc/syntax/miscellaneous.rdoc b/ruby/doc/syntax/miscellaneous.rdoc index 87ec059ae..d5cfd3e47 100644 --- a/ruby/doc/syntax/miscellaneous.rdoc +++ b/ruby/doc/syntax/miscellaneous.rdoc @@ -83,6 +83,36 @@ Using the specific reflection methods such as instance_variable_defined? for instance variables or const_defined? for constants is less error prone than using +defined?+. ++defined?+ handles some regexp global variables specially based on whether +there is an active regexp match and how many capture groups there are: + + /b/ =~ 'a' + defined?($~) # => "global-variable" + defined?($&) # => nil + defined?($`) # => nil + defined?($') # => nil + defined?($+) # => nil + defined?($1) # => nil + defined?($2) # => nil + + /./ =~ 'a' + defined?($~) # => "global-variable" + defined?($&) # => "global-variable" + defined?($`) # => "global-variable" + defined?($') # => "global-variable" + defined?($+) # => nil + defined?($1) # => nil + defined?($2) # => nil + + /(.)/ =~ 'a' + defined?($~) # => "global-variable" + defined?($&) # => "global-variable" + defined?($`) # => "global-variable" + defined?($') # => "global-variable" + defined?($+) # => "global-variable" + defined?($1) # => "global-variable" + defined?($2) # => nil + == +BEGIN+ and +END+ +BEGIN+ defines a block that is run before any other code in the current file. diff --git a/ruby/doc/syntax/pattern_matching.rdoc b/ruby/doc/syntax/pattern_matching.rdoc new file mode 100644 index 000000000..b7d614770 --- /dev/null +++ b/ruby/doc/syntax/pattern_matching.rdoc @@ -0,0 +1,540 @@ += Pattern matching + +Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. + +Pattern matching in Ruby is implemented with the +case+/+in+ expression: + + case + in + ... + in + ... + in + ... + else + ... + end + +(Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.) + +Or with the => operator and the +in+ operator, which can be used in a standalone expression: + + => + + in + +The +case+/+in+ expression is _exhaustive_: if the value of the expression does not match any branch of the +case+ expression (and the +else+ branch is absent), +NoMatchingPatternError+ is raised. + +Therefore, the +case+ expression might be used for conditional matching and unpacking: + + config = {db: {user: 'admin', password: 'abc123'}} + + case config + in db: {user:} # matches subhash and puts matched value in variable user + puts "Connect with user '#{user}'" + in connection: {username: } + puts "Connect with user '#{username}'" + else + puts "Unrecognized structure of config" + end + # Prints: "Connect with user 'admin'" + +whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: + + config = {db: {user: 'admin', password: 'abc123'}} + + config => {db: {user:}} # will raise if the config's structure is unexpected + + puts "Connect with user '#{user}'" + # Prints: "Connect with user 'admin'" + + in is the same as case ; in ; true; else false; end. +You can use it when you only want to know if a pattern has been matched or not: + + users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] + users.any? {|user| user in {name: /B/, age: 20..} } #=> true + +See below for more examples and explanations of the syntax. + +== Patterns + +Patterns can be: + +* any Ruby object (matched by the === operator, like in +when+); (Value pattern) +* array pattern: [, , , ...]; (Array pattern) +* find pattern: [*variable, , , , ..., *variable]; (Find pattern) +* hash pattern: {key: , key: , ...}; (Hash pattern) +* combination of patterns with |; (Alternative pattern) +* variable capture: => variable or variable; (As pattern, Variable pattern) + +Any pattern can be nested inside array/find/hash patterns where is specified. + +Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). +Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see below about the latter). Note that only symbol keys are supported for hash patterns. + +An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: + + case [1, 2, 3] + in [Integer, Integer] + "matched" + else + "not matched" + end + #=> "not matched" + +while the hash matches even if there are other keys besides the specified part: + + case {a: 1, b: 2, c: 3} + in {a: Integer} + "matched" + else + "not matched" + end + #=> "matched" + +{} is the only exclusion from this rule. It matches only if an empty hash is given: + + case {a: 1, b: 2, c: 3} + in {} + "matched" + else + "not matched" + end + #=> "not matched" + + case {} + in {} + "matched" + else + "not matched" + end + #=> "matched" + +There is also a way to specify there should be no other keys in the matched hash except those explicitly specified by the pattern, with **nil: + + case {a: 1, b: 2} + in {a: Integer, **nil} # this will not match the pattern having keys other than a: + "matched a part" + in {a: Integer, b: Integer, **nil} + "matched a whole" + else + "not matched" + end + #=> "matched a whole" + +Both array and hash patterns support "rest" specification: + + case [1, 2, 3] + in [Integer, *] + "matched" + else + "not matched" + end + #=> "matched" + + case {a: 1, b: 2, c: 3} + in {a: Integer, **} + "matched" + else + "not matched" + end + #=> "matched" + +Parentheses around both kinds of patterns could be omitted: + + case [1, 2] + in Integer, Integer + "matched" + else + "not matched" + end + #=> "matched" + + case {a: 1, b: 2, c: 3} + in a: Integer + "matched" + else + "not matched" + end + #=> "matched" + + [1, 2] => a, b + [1, 2] in a, b + + {a: 1, b: 2, c: 3} => a: + {a: 1, b: 2, c: 3} in a: + +Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern: + + case ["a", 1, "b", "c", 2] + in [*, String, String, *] + "matched" + else + "not matched" + end + +== Variable binding + +Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): + + case [1, 2] + in Integer => a, Integer + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + + case {a: 1, b: 2, c: 3} + in a: Integer => m + "matched: #{m}" + else + "not matched" + end + #=> "matched: 1" + +If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: + + case [1, 2] + in a, Integer + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + + case {a: 1, b: 2, c: 3} + in a: m + "matched: #{m}" + else + "not matched" + end + #=> "matched: 1" + +For hash patterns, even a simpler form exists: key-only specification (without any sub-pattern) binds the local variable with the key's name, too: + + case {a: 1, b: 2, c: 3} + in a: + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + +Binding works for nested patterns as well: + + case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} + in name:, friends: [{name: first_friend}, *] + "matched: #{first_friend}" + else + "not matched" + end + #=> "matched: Jane" + +The "rest" part of a pattern also can be bound to a variable: + + case [1, 2, 3] + in a, *rest + "matched: #{a}, #{rest}" + else + "not matched" + end + #=> "matched: 1, [2, 3]" + + case {a: 1, b: 2, c: 3} + in a:, **rest + "matched: #{a}, #{rest}" + else + "not matched" + end + #=> "matched: 1, {:b=>2, :c=>3}" + +Binding to variables currently does NOT work for alternative patterns joined with |: + + case {a: 1, b: 2} + in {a: } | Array + "matched: #{a}" + else + "not matched" + end + # SyntaxError (illegal variable in alternative pattern (a)) + +Variables that start with _ are the only exclusions from this rule: + + case {a: 1, b: 2} + in {a: _, b: _foo} | Array + "matched: #{_}, #{_foo}" + else + "not matched" + end + # => "matched: 1, 2" + +It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. + +== Variable pinning + +Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: + + expectation = 18 + + case [1, 2] + in expectation, *rest + "matched. expectation was: #{expectation}" + else + "not matched. expectation was: #{expectation}" + end + # expected: "not matched. expectation was: 18" + # real: "matched. expectation was: 1" -- local variable just rewritten + +For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": + + expectation = 18 + case [1, 2] + in ^expectation, *rest + "matched. expectation was: #{expectation}" + else + "not matched. expectation was: #{expectation}" + end + #=> "not matched. expectation was: 18" + +One important usage of variable pinning is specifying that the same value should occur in the pattern several times: + + jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} + john = {school: 'high', schools: [{id: 1, level: 'middle'}]} + + case jane + in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match + "matched. school: #{id}" + else + "not matched" + end + #=> "matched. school: 2" + + case john # the specified school level is "high", but last school does not match + in school:, schools: [*, {id:, level: ^school}] + "matched. school: #{id}" + else + "not matched" + end + #=> "not matched" + +In addition to pinning local variables, you can also pin instance, global, and class variables: + + $gvar = 1 + class A + @ivar = 2 + @@cvar = 3 + case [1, 2, 3] + in ^$gvar, ^@ivar, ^@@cvar + "matched" + else + "not matched" + end + #=> "matched" + end + +You can also pin the result of arbitrary expressions using parentheses: + + a = 1 + b = 2 + case 3 + in ^(a + b) + "matched" + else + "not matched" + end + #=> "matched" + +== Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ + +As already mentioned above, array, find, and hash patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns). + + class Point + def initialize(x, y) + @x, @y = x, y + end + + def deconstruct + puts "deconstruct called" + [@x, @y] + end + + def deconstruct_keys(keys) + puts "deconstruct_keys called with #{keys.inspect}" + {x: @x, y: @y} + end + end + + case Point.new(1, -2) + in px, Integer # sub-patterns and variable binding works + "matched: #{px}" + else + "not matched" + end + # prints "deconstruct called" + "matched: 1" + + case Point.new(1, -2) + in x: 0.. => px + "matched: #{px}" + else + "not matched" + end + # prints: deconstruct_keys called with [:x] + #=> "matched: 1" + ++keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: + + case Point.new(1, -2) + in x: 0.. => px, **rest + "matched: #{px}" + else + "not matched" + end + # prints: deconstruct_keys called with nil + #=> "matched: 1" + +Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === + + class SuperPoint < Point + end + + case Point.new(1, -2) + in SuperPoint(x: 0.. => px) + "matched: #{px}" + else + "not matched" + end + #=> "not matched" + + case SuperPoint.new(1, -2) + in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed + "matched: #{px}" + else + "not matched" + end + #=> "matched: 1" + +== Guard clauses + ++if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: + + case [1, 2] + in a, b if b == a*2 + "matched" + else + "not matched" + end + #=> "matched" + + case [1, 1] + in a, b if b == a*2 + "matched" + else + "not matched" + end + #=> "not matched" + ++unless+ works, too: + + case [1, 1] + in a, b unless b == a*2 + "matched" + else + "not matched" + end + #=> "matched" + +== Current feature status + +As of Ruby 3.1, find patterns are considered _experimental_: its syntax can change in the future. Every time you use these features in code, a warning will be printed: + + [0] => [*, 0, *] + # warning: Find pattern is experimental, and the behavior may change in future versions of Ruby! + # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! + +To suppress this warning, one may use the Warning::[]= method: + + Warning[:experimental] = false + eval('[0] => [*, 0, *]') + # ...no warning printed... + +Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: + + Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted + [0] => [*, 0, *] + +So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. + +Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. + +== Appendix A. Pattern syntax + +Approximate syntax is: + + pattern: value_pattern + | variable_pattern + | alternative_pattern + | as_pattern + | array_pattern + | find_pattern + | hash_pattern + + value_pattern: literal + | Constant + | ^local_variable + | ^instance_variable + | ^class_variable + | ^global_variable + | ^(expression) + + variable_pattern: variable + + alternative_pattern: pattern | pattern | ... + + as_pattern: pattern => variable + + array_pattern: [pattern, ..., *variable] + | Constant(pattern, ..., *variable) + | Constant[pattern, ..., *variable] + + find_pattern: [*variable, pattern, ..., *variable] + | Constant(*variable, pattern, ..., *variable) + | Constant[*variable, pattern, ..., *variable] + + hash_pattern: {key: pattern, key:, ..., **variable} + | Constant(key: pattern, key:, ..., **variable) + | Constant[key: pattern, key:, ..., **variable] + +== Appendix B. Some undefined behavior examples + +To leave room for optimization in the future, the specification contains some undefined behavior. + +Use of a variable in an unmatched pattern: + + case [0, 1] + in [a, 2] + "not matched" + in b + "matched" + in c + "not matched" + end + a #=> undefined + c #=> undefined + +Number of +deconstruct+, +deconstruct_keys+ method calls: + + $i = 0 + ary = [0] + def ary.deconstruct + $i += 1 + self + end + case ary + in [0, 1] + "not matched" + in [0] + "matched" + end + $i #=> undefined diff --git a/ruby/doc/syntax/refinements.rdoc b/ruby/doc/syntax/refinements.rdoc index fc554bb47..c900ab1bd 100644 --- a/ruby/doc/syntax/refinements.rdoc +++ b/ruby/doc/syntax/refinements.rdoc @@ -245,7 +245,8 @@ When +super+ is invoked method lookup checks: Note that +super+ in a method of a refinement invokes the method in the refined class even if there is another refinement which has been activated in -the same context. +the same context. This is only true for +super+ in a method of a refinement, it +does not apply to +super+ in a method in a module that is included in a refinement. == Methods Introspection @@ -278,6 +279,6 @@ Refinements in descendants have higher precedence than those of ancestors. == Further Reading -See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec for the +See https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec for the current specification for implementing refinements. The specification also contains more details. diff --git a/ruby/doc/time/in.rdoc b/ruby/doc/time/in.rdoc new file mode 100644 index 000000000..f47db76a3 --- /dev/null +++ b/ruby/doc/time/in.rdoc @@ -0,0 +1,7 @@ +- in: zone: a timezone _zone_, which may be: + - A string offset from UTC. + - A single letter offset from UTC, in the range 'A'..'Z', + 'J' (the so-called military timezone) excluded. + - An integer number of seconds. + - A timezone object; + see {Timezone Argument}[#class-Time-label-Timezone+Argument] for details. diff --git a/ruby/doc/time/mon-min.rdoc b/ruby/doc/time/mon-min.rdoc new file mode 100644 index 000000000..5bd430c74 --- /dev/null +++ b/ruby/doc/time/mon-min.rdoc @@ -0,0 +1,8 @@ +- +month+: a month value, which may be: + - An integer month in the range 1..12. + - A 3-character string that matches regular expression + /jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/i. +- +day+: an integer day in the range 1..31 + (less than 31 for some months). +- +hour+: an integer hour in the range 0..23. +- +min+: an integer minute in the range 0..59. diff --git a/ruby/doc/time/msec.rdoc b/ruby/doc/time/msec.rdoc new file mode 100644 index 000000000..ce5d1e614 --- /dev/null +++ b/ruby/doc/time/msec.rdoc @@ -0,0 +1,2 @@ +- +msec+ is the number of milliseconds (Integer, Float, or Rational) + in the range 0..1000. diff --git a/ruby/doc/time/nsec.rdoc b/ruby/doc/time/nsec.rdoc new file mode 100644 index 000000000..a2dfe2d60 --- /dev/null +++ b/ruby/doc/time/nsec.rdoc @@ -0,0 +1,2 @@ +- +nsec+ is the number of nanoseconds (Integer, Float, or Rational) + in the range 0..1000000000. diff --git a/ruby/doc/time/sec.rdoc b/ruby/doc/time/sec.rdoc new file mode 100644 index 000000000..049c71211 --- /dev/null +++ b/ruby/doc/time/sec.rdoc @@ -0,0 +1,2 @@ +- +sec+ is the number of seconds (Integer, Float, or Rational) + in the range 0..60. diff --git a/ruby/doc/time/sec_i.rdoc b/ruby/doc/time/sec_i.rdoc new file mode 100644 index 000000000..99c8eddc6 --- /dev/null +++ b/ruby/doc/time/sec_i.rdoc @@ -0,0 +1 @@ +- +isec_i+ is the integer number of seconds in the range 0..60. diff --git a/ruby/doc/time/usec.rdoc b/ruby/doc/time/usec.rdoc new file mode 100644 index 000000000..bb5a46419 --- /dev/null +++ b/ruby/doc/time/usec.rdoc @@ -0,0 +1,2 @@ +- +usec+ is the number of microseconds (Integer, Float, or Rational) + in the range 0..1000000. diff --git a/ruby/doc/time/year.rdoc b/ruby/doc/time/year.rdoc new file mode 100644 index 000000000..2222b830d --- /dev/null +++ b/ruby/doc/time/year.rdoc @@ -0,0 +1 @@ +- +year+: an integer year. diff --git a/ruby/doc/time/zone_and_in.rdoc b/ruby/doc/time/zone_and_in.rdoc new file mode 100644 index 000000000..e09e22874 --- /dev/null +++ b/ruby/doc/time/zone_and_in.rdoc @@ -0,0 +1,8 @@ +- +zone+: a timezone, which may be: + - A string offset from UTC. + - A single letter offset from UTC, in the range 'A'..'Z', + 'J' (the so-called military timezone) excluded. + - An integer number of seconds. + - A timezone object; + see {Timezone Argument}[#class-Time-label-Timezone+Argument] for details. +- in: zone: a timezone _zone_, which may be as above. diff --git a/ruby/doc/yjit/yjit.md b/ruby/doc/yjit/yjit.md new file mode 100644 index 000000000..a56aec652 --- /dev/null +++ b/ruby/doc/yjit/yjit.md @@ -0,0 +1,233 @@ + + + +YJIT - Yet Another Ruby JIT +=========================== + +**DISCLAIMER: Please note that this project is experimental. It is very much a work in progress, it may cause your software to crash, and current performance results will vary widely, especially on larger applications.** + +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, an area where MJIT has not yet managed to deliver speedups. +To simplify development, we currently support only macOS and Linux on x86-64, but an ARM64 backend +is part of future plans. +This project is open source and falls under the same license as CRuby. + +If you wish to learn more about the approach taken, here are some conference talks and publications: +- 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/) +- 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) +- ECOOP 2016 paper: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://drops.dagstuhl.de/opus/volltexte/2016/6101/pdf/LIPIcs-ECOOP-2016-7.pdf) +- 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 this repository in your publications, please use this bibtex snippet: + +``` +@misc{yjit_ruby_jit, + author = {Chevalier-Boisvert, Maxime and Wu, Alan and Patterson, Aaron}, + title = {YJIT - Yet Another Ruby JIT}, + year = {2021}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/Shopify/yjit}}, +} +``` + +## Current Limitations + +YJIT is a work in progress and as such may not yet be mature enough for mission-critical software. Below is a list of known limitations, all of which we plan to eventually address: + +- No garbage collection for generated code. +- Currently supports only macOS and Linux. +- Currently supports only x86-64 CPUs. + +Because there is no GC for generated code yet, your software could run out of executable memory if it is large enough. You can change how much executable memory is allocated using [YJIT's command-line options](https://github.com/Shopify/yjit#command-line-options). + +## Installation + +Current YJIT versions are installed by default with CRuby. Make sure to specify the "--yjit" command line option to enable it at runtime. + +Experimental YJIT patches that have not yet been merged with CRuby can be found in ruby-build: + +``` +ruby-build yjit-dev ~/.rubies/ruby-yjit-dev +``` + +They can also be found in the Shopify/yjit repository, which is cloned and build like CRuby. + +Start by cloning the `Shopify/yjit` repository: + +``` +git clone https://github.com/Shopify/yjit +cd yjit +``` + +The YJIT `ruby` binary can be built with either GCC or Clang. For development, we recommend enabling debug symbols so that assertions are enabled as this makes debugging easier. Enabling debug mode will also make it possible for you to disassemble code generated by YJIT. However, this causes a performance hit. For maximum performance, compile with GCC, without the `DRUBY_DEBUG` or `YJIT_STATS` build options. More detailed build instructions are provided in the [Ruby README](https://github.com/ruby/ruby#how-to-compile-and-install). +To support disassembly of the generated code, `libcapstone` is also required (`brew install capstone` on MacOS, `sudo apt-get install -y libcapstone-dev` on Ubuntu/Debian and `sudo dnf -y install capstone-devel` on Fedora). + +``` +# Configure with debugging/stats options for development, build and install +./autogen.sh +./configure cppflags="-DRUBY_DEBUG -DYJIT_STATS" --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --disable--install-rdoc +make -j16 install +``` + +On macOS, you may need to specify where to find openssl, libyaml and gdbm: + +``` +# Configure with debugging/stats options for development, build and install +./configure cppflags="-DRUBY_DEBUG -DYJIT_STATS" --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --disable--install-rdoc --with-opt-dir=$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml):$(brew --prefix gdbm) +make -j16 install +``` + +Typically configure will choose default C compiler. To specify the C compiler, use +``` +# Choosing a specific c compiler +export CC=/path/to/my/choosen/c/compiler +``` +before running `./configure`. + +You can test that YJIT works correctly by running: + +``` +# Quick tests found in /bootstraptest +make btest + +# Complete set of tests +make -j16 test-all +``` + +## Usage + +### Examples + +Once YJIT is built, you can either use `./miniruby` from within your build directory, or switch to the YJIT version of `ruby` +by using the `chruby` tool: + +``` +chruby ruby-yjit +ruby myscript.rb +``` + +You can dump statistics about compilation and execution by running YJIT with the `--yjit-stats` command-line option: + +``` +./miniruby --yjit-stats 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 + +YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options: + +- `--disable-yjit`: turn off YJIT (enabled by default) +- `--yjit-stats`: produce statistics after the execution of a program (must compile with `cppflags=-DRUBY_DEBUG` to use this) +- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate (default 256 MiB) +- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function (default 2) +- `--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) + +### 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. + +### Performance 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, but you can profile your code using a tool such as [stackprof](https://github.com/tmm1/stackprof) and refactor the specific methods that make up the largest fractions of the execution time. + +- Use exceptions for error recovery only, not as part of normal control-flow +- 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 +- Use while loops if you can, instead of `integer.times` +- Minimize layers of indirection + - Avoid classes that wrap objects if you can + - Avoid methods that just call another method, trivial one liner methods +- CRuby method calls are costly. Favor larger methods over smaller methods. +- Try to write code so that the same variables always have the same type + +You can also compile YJIT in debug mode and 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. + +## Contributing + +We welcome open source contributors. 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 +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. + +### Source Code Organization + +The YJIT source code is divided between: +- `yjit_asm.c`: x86 in-memory assembler we use to generate machine code +- `yjit_codegen.c`: logic for translating Ruby bytecode to machine code +- `yjit_core.c`: basic block versioning logic, core structure of YJIT +- `yjit_iface.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 +- `misc/test_yjit_asm.sh`: script to compile and run the in-memory assembler tests +- `misc/yjit_asm_tests.c`: tests for the in-memory assembler + +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 + +### Coding & Debugging Protips + +There are 3 test suites: +- `make btest` (see `/bootstraptest`) +- `make test-all` +- `make test-spec` +- `make check` runs all of the above + +The tests can be run in parallel like this: + +``` +make -j16 test-all RUN_OPTS="--yjit-call-threshold=1" +``` + +Or single-threaded like this, to more easily identify which specific test is failing: + +``` +make test-all TESTOPTS=--verbose RUN_OPTS="--yjit-call-threshold=1" +``` + +To debug a single test in `test-all`: + +``` +make test-all TESTS='test/-ext-/marshal/test_usrmarshal.rb' RUNRUBYOPT=--debugger=lldb RUN_OPTS="--yjit-call-threshold=1" +``` + +You can also run one specific test in `btest`: + +``` +make btest BTESTS=bootstraptest/test_ractor.rb RUN_OPTS="--yjit-call-threshold=1" +``` + +There are shortcuts to run/debug your own test/repro in `test.rb`: + +``` +make run # runs ./miniruby test.rb +make lldb # launches ./miniruby test.rb in lldb +``` + +You can use the Intel syntax for disassembly in LLDB, keeping it consistent with YJIT's disassembly: + +``` +echo "settings set target.x86-disassembly-flavor intel" >> ~/.lldbinit +``` diff --git a/ruby/doc/yjit/yjit_hacking.md b/ruby/doc/yjit/yjit_hacking.md new file mode 100644 index 000000000..4c4d742b7 --- /dev/null +++ b/ruby/doc/yjit/yjit_hacking.md @@ -0,0 +1,75 @@ +# 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/ruby/enc/Makefile.in b/ruby/enc/Makefile.in index 838523649..5e5d39cd7 100644 --- a/ruby/enc/Makefile.in +++ b/ruby/enc/Makefile.in @@ -1,4 +1,5 @@ V = 0 +V0 = $(V:0=) Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@@NULLCMD@) @@ -11,6 +12,7 @@ exec_prefix = @exec_prefix@ libdir = @libdir@ top_srcdir = $(encsrcdir:/enc=) srcdir = $(top_srcdir) +tooldir = $(top_srcdir)/tool arch = @arch@ EXTOUT = @EXTOUT@ hdrdir = $(srcdir)/include diff --git a/ruby/enc/ascii.c b/ruby/enc/ascii.c index 8b32c414f..a2fef2f87 100644 --- a/ruby/enc/ascii.c +++ b/ruby/enc/ascii.c @@ -61,6 +61,8 @@ OnigEncodingDefine(ascii, ASCII) = { ENC_ALIAS("BINARY", "ASCII-8BIT") ENC_REPLICATE("IBM437", "ASCII-8BIT") ENC_ALIAS("CP437", "IBM437") +ENC_REPLICATE("IBM720", "ASCII-8BIT") +ENC_ALIAS("CP720", "IBM720") ENC_REPLICATE("IBM737", "ASCII-8BIT") ENC_ALIAS("CP737", "IBM737") ENC_REPLICATE("IBM775", "ASCII-8BIT") diff --git a/ruby/enc/cp949.c b/ruby/enc/cp949.c index bd2c8d21a..1600d0cd5 100644 --- a/ruby/enc/cp949.c +++ b/ruby/enc/cp949.c @@ -218,5 +218,5 @@ OnigEncodingDefine(cp949, CP949) = { /* * Name: CP949 * Link: http://www.microsoft.com/globaldev/reference/dbcs/949.mspx - * Link: http://en.wikipedia.org/wiki/EUC-KR#EUC-KR + * Link: https://en.wikipedia.org/wiki/EUC-KR#EUC-KR */ diff --git a/ruby/enc/depend b/ruby/enc/depend index 0fffcc273..8922b2b25 100644 --- a/ruby/enc/depend +++ b/ruby/enc/depend @@ -18,6 +18,7 @@ % else % pathrep = proc {|path| path} % end +% ignore_error = $ignore_error VPATH = <%=%w[$(arch_hdrdir)/ruby $(hdrdir)/ruby $(srcdir) $(encsrcdir)].join(CONFIG["PATH_SEPARATOR"])%> LIBPATH = <%=libpathflag($DEFLIBPATH)%> @@ -73,12 +74,12 @@ $(LIBENC): $(ENCOBJS) @$(RM) $@ $(ECHO) linking statically-linked encoding library $@ $(Q) $(AR) $(ARFLAGS)$@ $(ENCOBJS) - @-$(RANLIB) $@ 2> /dev/null || true + @-$(RANLIB) $@<%=ignore_error%> $(LIBTRANS): $(TRANSOBJS) @$(RM) $@ $(ECHO) linking statically-linked transcoder library $@ $(Q) $(AR) $(ARFLAGS)$@ $(TRANSOBJS) - @-$(RANLIB) $@ 2> /dev/null || true + @-$(RANLIB) $@<%=ignore_error%> enc trans $(ENCSOS) $(TRANSSOS): config.status @@ -97,7 +98,7 @@ $(ENCSOS) $(TRANSSOS): $(ENC_TRANS_SO_D) <%=transvpath_prefix%>.trans<%=transvpath_prefix%>.c: $(ECHO) generating table from $@ - $(Q)$(MINIRUBY) "$(srcdir)/tool/transcode-tblgen.rb" -vo "$@" "$<" + $(Q)$(MINIRUBY) "$(tooldir)/transcode-tblgen.rb" -v$(V0:1=v)o "$@" "$<" % unless ENCS.empty? or TRANS.empty? @@ -113,7 +114,7 @@ enc/<%=e%>.$(OBJEXT): <%=deps.map {|n| rule_subst % n}.join(' ')%> % if src.empty? % src = trans.scan(/^\s*transcode_tblgen_\w+\s+[\'\"]([^\'\"]*)/).flatten.map{|c|c.downcase+"-tbl.rb"} % end -<%=transvpath % "#{e}.c"%>: <%= src.map {|s| transvpath % "#{s}"}.join(" ")%> $(srcdir)/tool/transcode-tblgen.rb +<%=transvpath % "#{e}.c"%>: <%= src.map {|s| transvpath % "#{s}"}.join(" ")%> $(tooldir)/transcode-tblgen.rb % end % end @@ -156,240 +157,2194 @@ 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]%> % end -% @ignore_error = $nmake ? '' : ' 2> /dev/null || true' % unless inplace $(Q)$(RM) enc/unicode/*/casefold.h enc/unicode/*/name2ctype.h $(Q)$(RM) enc/jis/props.h - -$(Q)$(RMDIR) enc/unicode<%=@ignore_error%> + -$(Q)$(RMDIR) enc/unicode<%=ignore_error%> % end % workdirs.reverse_each do|d| - -$(Q)$(RMDIR) <%=pathrep[d]%><%=@ignore_error%> + -$(Q)$(RMDIR) <%=pathrep[d]%><%=ignore_error%> % end clean-srcs: $(Q)$(RM) <%=pathrep['$(TRANSCSRCS)']%> - -$(Q)$(RMDIR) <%=pathrep['enc/trans']%><%=@ignore_error%> + -$(Q)$(RMDIR) <%=pathrep['enc/trans']%><%=ignore_error%> $(Q)$(RM) enc/unicode/*/casefold.h enc/unicode/*/name2ctype.h $(Q)$(RM) enc/jis/props.h - -$(Q)$(RMDIR) <%=pathrep['enc/unicode']%><%=@ignore_error%> - -$(Q)$(RMDIR) <%=pathrep['enc/props']%><%=@ignore_error%> - -$(Q)$(RMDIR) <%=pathrep['enc']%><%=@ignore_error%> + -$(Q)$(RMDIR) <%=pathrep['enc/unicode']%><%=ignore_error%> + -$(Q)$(RMDIR) <%=pathrep['enc/props']%><%=ignore_error%> + -$(Q)$(RMDIR) <%=pathrep['enc']%><%=ignore_error%> <%# vim: set ft=eruby noexpandtab ts=8 sw=2 : -%> # AUTOGENERATED DEPENDENCIES START +enc/ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/ascii.$(OBJEXT): $(top_srcdir)/encindex.h enc/ascii.$(OBJEXT): $(top_srcdir)/regenc.h +enc/ascii.$(OBJEXT): assert.h +enc/ascii.$(OBJEXT): backward/2/assume.h +enc/ascii.$(OBJEXT): backward/2/attributes.h +enc/ascii.$(OBJEXT): backward/2/bool.h +enc/ascii.$(OBJEXT): backward/2/inttypes.h +enc/ascii.$(OBJEXT): backward/2/limits.h +enc/ascii.$(OBJEXT): backward/2/long_long.h +enc/ascii.$(OBJEXT): backward/2/stdalign.h +enc/ascii.$(OBJEXT): backward/2/stdarg.h enc/ascii.$(OBJEXT): config.h enc/ascii.$(OBJEXT): defines.h enc/ascii.$(OBJEXT): enc/ascii.c +enc/ascii.$(OBJEXT): encoding.h +enc/ascii.$(OBJEXT): intern.h +enc/ascii.$(OBJEXT): internal/anyargs.h +enc/ascii.$(OBJEXT): internal/arithmetic.h +enc/ascii.$(OBJEXT): internal/arithmetic/char.h +enc/ascii.$(OBJEXT): internal/arithmetic/double.h +enc/ascii.$(OBJEXT): internal/arithmetic/fixnum.h +enc/ascii.$(OBJEXT): internal/arithmetic/gid_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/int.h +enc/ascii.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/long.h +enc/ascii.$(OBJEXT): internal/arithmetic/long_long.h +enc/ascii.$(OBJEXT): internal/arithmetic/mode_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/off_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/pid_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/short.h +enc/ascii.$(OBJEXT): internal/arithmetic/size_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/ascii.$(OBJEXT): internal/arithmetic/uid_t.h +enc/ascii.$(OBJEXT): internal/assume.h +enc/ascii.$(OBJEXT): internal/attr/alloc_size.h +enc/ascii.$(OBJEXT): internal/attr/artificial.h +enc/ascii.$(OBJEXT): internal/attr/cold.h +enc/ascii.$(OBJEXT): internal/attr/const.h +enc/ascii.$(OBJEXT): internal/attr/constexpr.h +enc/ascii.$(OBJEXT): internal/attr/deprecated.h +enc/ascii.$(OBJEXT): internal/attr/diagnose_if.h +enc/ascii.$(OBJEXT): internal/attr/enum_extensibility.h +enc/ascii.$(OBJEXT): internal/attr/error.h +enc/ascii.$(OBJEXT): internal/attr/flag_enum.h +enc/ascii.$(OBJEXT): internal/attr/forceinline.h +enc/ascii.$(OBJEXT): internal/attr/format.h +enc/ascii.$(OBJEXT): internal/attr/maybe_unused.h +enc/ascii.$(OBJEXT): internal/attr/noalias.h +enc/ascii.$(OBJEXT): internal/attr/nodiscard.h +enc/ascii.$(OBJEXT): internal/attr/noexcept.h +enc/ascii.$(OBJEXT): internal/attr/noinline.h +enc/ascii.$(OBJEXT): internal/attr/nonnull.h +enc/ascii.$(OBJEXT): internal/attr/noreturn.h +enc/ascii.$(OBJEXT): internal/attr/pure.h +enc/ascii.$(OBJEXT): internal/attr/restrict.h +enc/ascii.$(OBJEXT): internal/attr/returns_nonnull.h +enc/ascii.$(OBJEXT): internal/attr/warning.h +enc/ascii.$(OBJEXT): internal/attr/weakref.h +enc/ascii.$(OBJEXT): internal/cast.h +enc/ascii.$(OBJEXT): internal/compiler_is.h +enc/ascii.$(OBJEXT): internal/compiler_is/apple.h +enc/ascii.$(OBJEXT): internal/compiler_is/clang.h +enc/ascii.$(OBJEXT): internal/compiler_is/gcc.h +enc/ascii.$(OBJEXT): internal/compiler_is/intel.h +enc/ascii.$(OBJEXT): internal/compiler_is/msvc.h +enc/ascii.$(OBJEXT): internal/compiler_is/sunpro.h +enc/ascii.$(OBJEXT): internal/compiler_since.h +enc/ascii.$(OBJEXT): internal/config.h +enc/ascii.$(OBJEXT): internal/constant_p.h +enc/ascii.$(OBJEXT): internal/core.h +enc/ascii.$(OBJEXT): internal/core/rarray.h +enc/ascii.$(OBJEXT): internal/core/rbasic.h +enc/ascii.$(OBJEXT): internal/core/rbignum.h +enc/ascii.$(OBJEXT): internal/core/rclass.h +enc/ascii.$(OBJEXT): internal/core/rdata.h +enc/ascii.$(OBJEXT): internal/core/rfile.h +enc/ascii.$(OBJEXT): internal/core/rhash.h +enc/ascii.$(OBJEXT): internal/core/robject.h +enc/ascii.$(OBJEXT): internal/core/rregexp.h +enc/ascii.$(OBJEXT): internal/core/rstring.h +enc/ascii.$(OBJEXT): internal/core/rstruct.h +enc/ascii.$(OBJEXT): internal/core/rtypeddata.h +enc/ascii.$(OBJEXT): internal/ctype.h +enc/ascii.$(OBJEXT): internal/dllexport.h +enc/ascii.$(OBJEXT): internal/dosish.h +enc/ascii.$(OBJEXT): internal/encoding/coderange.h +enc/ascii.$(OBJEXT): internal/encoding/ctype.h +enc/ascii.$(OBJEXT): internal/encoding/encoding.h +enc/ascii.$(OBJEXT): internal/encoding/pathname.h +enc/ascii.$(OBJEXT): internal/encoding/re.h +enc/ascii.$(OBJEXT): internal/encoding/sprintf.h +enc/ascii.$(OBJEXT): internal/encoding/string.h +enc/ascii.$(OBJEXT): internal/encoding/symbol.h +enc/ascii.$(OBJEXT): internal/encoding/transcode.h +enc/ascii.$(OBJEXT): internal/error.h +enc/ascii.$(OBJEXT): internal/eval.h +enc/ascii.$(OBJEXT): internal/event.h +enc/ascii.$(OBJEXT): internal/fl_type.h +enc/ascii.$(OBJEXT): internal/gc.h +enc/ascii.$(OBJEXT): internal/glob.h +enc/ascii.$(OBJEXT): internal/globals.h +enc/ascii.$(OBJEXT): internal/has/attribute.h +enc/ascii.$(OBJEXT): internal/has/builtin.h +enc/ascii.$(OBJEXT): internal/has/c_attribute.h +enc/ascii.$(OBJEXT): internal/has/cpp_attribute.h +enc/ascii.$(OBJEXT): internal/has/declspec_attribute.h +enc/ascii.$(OBJEXT): internal/has/extension.h +enc/ascii.$(OBJEXT): internal/has/feature.h +enc/ascii.$(OBJEXT): internal/has/warning.h +enc/ascii.$(OBJEXT): internal/intern/array.h +enc/ascii.$(OBJEXT): internal/intern/bignum.h +enc/ascii.$(OBJEXT): internal/intern/class.h +enc/ascii.$(OBJEXT): internal/intern/compar.h +enc/ascii.$(OBJEXT): internal/intern/complex.h +enc/ascii.$(OBJEXT): internal/intern/cont.h +enc/ascii.$(OBJEXT): internal/intern/dir.h +enc/ascii.$(OBJEXT): internal/intern/enum.h +enc/ascii.$(OBJEXT): internal/intern/enumerator.h +enc/ascii.$(OBJEXT): internal/intern/error.h +enc/ascii.$(OBJEXT): internal/intern/eval.h +enc/ascii.$(OBJEXT): internal/intern/file.h +enc/ascii.$(OBJEXT): internal/intern/gc.h +enc/ascii.$(OBJEXT): internal/intern/hash.h +enc/ascii.$(OBJEXT): internal/intern/io.h +enc/ascii.$(OBJEXT): internal/intern/load.h +enc/ascii.$(OBJEXT): internal/intern/marshal.h +enc/ascii.$(OBJEXT): internal/intern/numeric.h +enc/ascii.$(OBJEXT): internal/intern/object.h +enc/ascii.$(OBJEXT): internal/intern/parse.h +enc/ascii.$(OBJEXT): internal/intern/proc.h +enc/ascii.$(OBJEXT): internal/intern/process.h +enc/ascii.$(OBJEXT): internal/intern/random.h +enc/ascii.$(OBJEXT): internal/intern/range.h +enc/ascii.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/ascii.$(OBJEXT): internal/intern/sprintf.h +enc/ascii.$(OBJEXT): internal/intern/string.h +enc/ascii.$(OBJEXT): internal/intern/struct.h +enc/ascii.$(OBJEXT): internal/intern/thread.h +enc/ascii.$(OBJEXT): internal/intern/time.h +enc/ascii.$(OBJEXT): internal/intern/variable.h +enc/ascii.$(OBJEXT): internal/intern/vm.h +enc/ascii.$(OBJEXT): internal/interpreter.h +enc/ascii.$(OBJEXT): internal/iterator.h +enc/ascii.$(OBJEXT): internal/memory.h +enc/ascii.$(OBJEXT): internal/method.h +enc/ascii.$(OBJEXT): internal/module.h +enc/ascii.$(OBJEXT): internal/newobj.h +enc/ascii.$(OBJEXT): internal/rgengc.h +enc/ascii.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/ascii.$(OBJEXT): internal/value.h +enc/ascii.$(OBJEXT): internal/value_type.h +enc/ascii.$(OBJEXT): internal/variable.h +enc/ascii.$(OBJEXT): internal/warning_push.h +enc/ascii.$(OBJEXT): internal/xmalloc.h enc/ascii.$(OBJEXT): missing.h enc/ascii.$(OBJEXT): onigmo.h +enc/ascii.$(OBJEXT): oniguruma.h +enc/ascii.$(OBJEXT): st.h +enc/ascii.$(OBJEXT): subst.h enc/big5.$(OBJEXT): $(top_srcdir)/regenc.h +enc/big5.$(OBJEXT): assert.h +enc/big5.$(OBJEXT): backward/2/assume.h +enc/big5.$(OBJEXT): backward/2/attributes.h +enc/big5.$(OBJEXT): backward/2/bool.h +enc/big5.$(OBJEXT): backward/2/long_long.h +enc/big5.$(OBJEXT): backward/2/stdalign.h +enc/big5.$(OBJEXT): backward/2/stdarg.h enc/big5.$(OBJEXT): config.h enc/big5.$(OBJEXT): defines.h enc/big5.$(OBJEXT): enc/big5.c +enc/big5.$(OBJEXT): internal/assume.h +enc/big5.$(OBJEXT): internal/attr/alloc_size.h +enc/big5.$(OBJEXT): internal/attr/cold.h +enc/big5.$(OBJEXT): internal/attr/const.h +enc/big5.$(OBJEXT): internal/attr/deprecated.h +enc/big5.$(OBJEXT): internal/attr/error.h +enc/big5.$(OBJEXT): internal/attr/forceinline.h +enc/big5.$(OBJEXT): internal/attr/format.h +enc/big5.$(OBJEXT): internal/attr/maybe_unused.h +enc/big5.$(OBJEXT): internal/attr/nodiscard.h +enc/big5.$(OBJEXT): internal/attr/noexcept.h +enc/big5.$(OBJEXT): internal/attr/noinline.h +enc/big5.$(OBJEXT): internal/attr/nonnull.h +enc/big5.$(OBJEXT): internal/attr/noreturn.h +enc/big5.$(OBJEXT): internal/attr/pure.h +enc/big5.$(OBJEXT): internal/attr/restrict.h +enc/big5.$(OBJEXT): internal/attr/returns_nonnull.h +enc/big5.$(OBJEXT): internal/attr/warning.h +enc/big5.$(OBJEXT): internal/cast.h +enc/big5.$(OBJEXT): internal/compiler_is.h +enc/big5.$(OBJEXT): internal/compiler_is/apple.h +enc/big5.$(OBJEXT): internal/compiler_is/clang.h +enc/big5.$(OBJEXT): internal/compiler_is/gcc.h +enc/big5.$(OBJEXT): internal/compiler_is/intel.h +enc/big5.$(OBJEXT): internal/compiler_is/msvc.h +enc/big5.$(OBJEXT): internal/compiler_is/sunpro.h +enc/big5.$(OBJEXT): internal/compiler_since.h +enc/big5.$(OBJEXT): internal/config.h +enc/big5.$(OBJEXT): internal/dllexport.h +enc/big5.$(OBJEXT): internal/dosish.h +enc/big5.$(OBJEXT): internal/has/attribute.h +enc/big5.$(OBJEXT): internal/has/builtin.h +enc/big5.$(OBJEXT): internal/has/c_attribute.h +enc/big5.$(OBJEXT): internal/has/cpp_attribute.h +enc/big5.$(OBJEXT): internal/has/declspec_attribute.h +enc/big5.$(OBJEXT): internal/has/extension.h +enc/big5.$(OBJEXT): internal/has/feature.h +enc/big5.$(OBJEXT): internal/has/warning.h +enc/big5.$(OBJEXT): internal/stdalign.h +enc/big5.$(OBJEXT): internal/stdbool.h +enc/big5.$(OBJEXT): internal/warning_push.h +enc/big5.$(OBJEXT): internal/xmalloc.h enc/big5.$(OBJEXT): missing.h enc/big5.$(OBJEXT): onigmo.h +enc/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/cesu_8.$(OBJEXT): $(top_srcdir)/encindex.h enc/cesu_8.$(OBJEXT): $(top_srcdir)/regenc.h +enc/cesu_8.$(OBJEXT): assert.h +enc/cesu_8.$(OBJEXT): backward.h +enc/cesu_8.$(OBJEXT): backward/2/assume.h +enc/cesu_8.$(OBJEXT): backward/2/attributes.h +enc/cesu_8.$(OBJEXT): backward/2/bool.h +enc/cesu_8.$(OBJEXT): backward/2/inttypes.h +enc/cesu_8.$(OBJEXT): backward/2/limits.h +enc/cesu_8.$(OBJEXT): backward/2/long_long.h +enc/cesu_8.$(OBJEXT): backward/2/stdalign.h +enc/cesu_8.$(OBJEXT): backward/2/stdarg.h enc/cesu_8.$(OBJEXT): config.h enc/cesu_8.$(OBJEXT): defines.h enc/cesu_8.$(OBJEXT): enc/cesu_8.c +enc/cesu_8.$(OBJEXT): encoding.h +enc/cesu_8.$(OBJEXT): intern.h +enc/cesu_8.$(OBJEXT): internal/anyargs.h +enc/cesu_8.$(OBJEXT): internal/arithmetic.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/char.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/double.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/fixnum.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/gid_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/int.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/long.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/long_long.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/mode_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/off_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/pid_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/short.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/size_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/cesu_8.$(OBJEXT): internal/arithmetic/uid_t.h +enc/cesu_8.$(OBJEXT): internal/assume.h +enc/cesu_8.$(OBJEXT): internal/attr/alloc_size.h +enc/cesu_8.$(OBJEXT): internal/attr/artificial.h +enc/cesu_8.$(OBJEXT): internal/attr/cold.h +enc/cesu_8.$(OBJEXT): internal/attr/const.h +enc/cesu_8.$(OBJEXT): internal/attr/constexpr.h +enc/cesu_8.$(OBJEXT): internal/attr/deprecated.h +enc/cesu_8.$(OBJEXT): internal/attr/diagnose_if.h +enc/cesu_8.$(OBJEXT): internal/attr/enum_extensibility.h +enc/cesu_8.$(OBJEXT): internal/attr/error.h +enc/cesu_8.$(OBJEXT): internal/attr/flag_enum.h +enc/cesu_8.$(OBJEXT): internal/attr/forceinline.h +enc/cesu_8.$(OBJEXT): internal/attr/format.h +enc/cesu_8.$(OBJEXT): internal/attr/maybe_unused.h +enc/cesu_8.$(OBJEXT): internal/attr/noalias.h +enc/cesu_8.$(OBJEXT): internal/attr/nodiscard.h +enc/cesu_8.$(OBJEXT): internal/attr/noexcept.h +enc/cesu_8.$(OBJEXT): internal/attr/noinline.h +enc/cesu_8.$(OBJEXT): internal/attr/nonnull.h +enc/cesu_8.$(OBJEXT): internal/attr/noreturn.h +enc/cesu_8.$(OBJEXT): internal/attr/pure.h +enc/cesu_8.$(OBJEXT): internal/attr/restrict.h +enc/cesu_8.$(OBJEXT): internal/attr/returns_nonnull.h +enc/cesu_8.$(OBJEXT): internal/attr/warning.h +enc/cesu_8.$(OBJEXT): internal/attr/weakref.h +enc/cesu_8.$(OBJEXT): internal/cast.h +enc/cesu_8.$(OBJEXT): internal/compiler_is.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/apple.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/clang.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/gcc.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/intel.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/msvc.h +enc/cesu_8.$(OBJEXT): internal/compiler_is/sunpro.h +enc/cesu_8.$(OBJEXT): internal/compiler_since.h +enc/cesu_8.$(OBJEXT): internal/config.h +enc/cesu_8.$(OBJEXT): internal/constant_p.h +enc/cesu_8.$(OBJEXT): internal/core.h +enc/cesu_8.$(OBJEXT): internal/core/rarray.h +enc/cesu_8.$(OBJEXT): internal/core/rbasic.h +enc/cesu_8.$(OBJEXT): internal/core/rbignum.h +enc/cesu_8.$(OBJEXT): internal/core/rclass.h +enc/cesu_8.$(OBJEXT): internal/core/rdata.h +enc/cesu_8.$(OBJEXT): internal/core/rfile.h +enc/cesu_8.$(OBJEXT): internal/core/rhash.h +enc/cesu_8.$(OBJEXT): internal/core/robject.h +enc/cesu_8.$(OBJEXT): internal/core/rregexp.h +enc/cesu_8.$(OBJEXT): internal/core/rstring.h +enc/cesu_8.$(OBJEXT): internal/core/rstruct.h +enc/cesu_8.$(OBJEXT): internal/core/rtypeddata.h +enc/cesu_8.$(OBJEXT): internal/ctype.h +enc/cesu_8.$(OBJEXT): internal/dllexport.h +enc/cesu_8.$(OBJEXT): internal/dosish.h +enc/cesu_8.$(OBJEXT): internal/encoding/coderange.h +enc/cesu_8.$(OBJEXT): internal/encoding/ctype.h +enc/cesu_8.$(OBJEXT): internal/encoding/encoding.h +enc/cesu_8.$(OBJEXT): internal/encoding/pathname.h +enc/cesu_8.$(OBJEXT): internal/encoding/re.h +enc/cesu_8.$(OBJEXT): internal/encoding/sprintf.h +enc/cesu_8.$(OBJEXT): internal/encoding/string.h +enc/cesu_8.$(OBJEXT): internal/encoding/symbol.h +enc/cesu_8.$(OBJEXT): internal/encoding/transcode.h +enc/cesu_8.$(OBJEXT): internal/error.h +enc/cesu_8.$(OBJEXT): internal/eval.h +enc/cesu_8.$(OBJEXT): internal/event.h +enc/cesu_8.$(OBJEXT): internal/fl_type.h +enc/cesu_8.$(OBJEXT): internal/gc.h +enc/cesu_8.$(OBJEXT): internal/glob.h +enc/cesu_8.$(OBJEXT): internal/globals.h +enc/cesu_8.$(OBJEXT): internal/has/attribute.h +enc/cesu_8.$(OBJEXT): internal/has/builtin.h +enc/cesu_8.$(OBJEXT): internal/has/c_attribute.h +enc/cesu_8.$(OBJEXT): internal/has/cpp_attribute.h +enc/cesu_8.$(OBJEXT): internal/has/declspec_attribute.h +enc/cesu_8.$(OBJEXT): internal/has/extension.h +enc/cesu_8.$(OBJEXT): internal/has/feature.h +enc/cesu_8.$(OBJEXT): internal/has/warning.h +enc/cesu_8.$(OBJEXT): internal/intern/array.h +enc/cesu_8.$(OBJEXT): internal/intern/bignum.h +enc/cesu_8.$(OBJEXT): internal/intern/class.h +enc/cesu_8.$(OBJEXT): internal/intern/compar.h +enc/cesu_8.$(OBJEXT): internal/intern/complex.h +enc/cesu_8.$(OBJEXT): internal/intern/cont.h +enc/cesu_8.$(OBJEXT): internal/intern/dir.h +enc/cesu_8.$(OBJEXT): internal/intern/enum.h +enc/cesu_8.$(OBJEXT): internal/intern/enumerator.h +enc/cesu_8.$(OBJEXT): internal/intern/error.h +enc/cesu_8.$(OBJEXT): internal/intern/eval.h +enc/cesu_8.$(OBJEXT): internal/intern/file.h +enc/cesu_8.$(OBJEXT): internal/intern/gc.h +enc/cesu_8.$(OBJEXT): internal/intern/hash.h +enc/cesu_8.$(OBJEXT): internal/intern/io.h +enc/cesu_8.$(OBJEXT): internal/intern/load.h +enc/cesu_8.$(OBJEXT): internal/intern/marshal.h +enc/cesu_8.$(OBJEXT): internal/intern/numeric.h +enc/cesu_8.$(OBJEXT): internal/intern/object.h +enc/cesu_8.$(OBJEXT): internal/intern/parse.h +enc/cesu_8.$(OBJEXT): internal/intern/proc.h +enc/cesu_8.$(OBJEXT): internal/intern/process.h +enc/cesu_8.$(OBJEXT): internal/intern/random.h +enc/cesu_8.$(OBJEXT): internal/intern/range.h +enc/cesu_8.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/cesu_8.$(OBJEXT): internal/intern/sprintf.h +enc/cesu_8.$(OBJEXT): internal/intern/string.h +enc/cesu_8.$(OBJEXT): internal/intern/struct.h +enc/cesu_8.$(OBJEXT): internal/intern/thread.h +enc/cesu_8.$(OBJEXT): internal/intern/time.h +enc/cesu_8.$(OBJEXT): internal/intern/variable.h +enc/cesu_8.$(OBJEXT): internal/intern/vm.h +enc/cesu_8.$(OBJEXT): internal/interpreter.h +enc/cesu_8.$(OBJEXT): internal/iterator.h +enc/cesu_8.$(OBJEXT): internal/memory.h +enc/cesu_8.$(OBJEXT): internal/method.h +enc/cesu_8.$(OBJEXT): internal/module.h +enc/cesu_8.$(OBJEXT): internal/newobj.h +enc/cesu_8.$(OBJEXT): internal/rgengc.h +enc/cesu_8.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/cesu_8.$(OBJEXT): internal/value.h +enc/cesu_8.$(OBJEXT): internal/value_type.h +enc/cesu_8.$(OBJEXT): internal/variable.h +enc/cesu_8.$(OBJEXT): internal/warning_push.h +enc/cesu_8.$(OBJEXT): internal/xmalloc.h enc/cesu_8.$(OBJEXT): missing.h enc/cesu_8.$(OBJEXT): onigmo.h +enc/cesu_8.$(OBJEXT): oniguruma.h +enc/cesu_8.$(OBJEXT): st.h +enc/cesu_8.$(OBJEXT): subst.h enc/cp949.$(OBJEXT): $(top_srcdir)/regenc.h +enc/cp949.$(OBJEXT): assert.h +enc/cp949.$(OBJEXT): backward/2/assume.h +enc/cp949.$(OBJEXT): backward/2/attributes.h +enc/cp949.$(OBJEXT): backward/2/bool.h +enc/cp949.$(OBJEXT): backward/2/long_long.h +enc/cp949.$(OBJEXT): backward/2/stdalign.h +enc/cp949.$(OBJEXT): backward/2/stdarg.h enc/cp949.$(OBJEXT): config.h enc/cp949.$(OBJEXT): defines.h enc/cp949.$(OBJEXT): enc/cp949.c +enc/cp949.$(OBJEXT): internal/assume.h +enc/cp949.$(OBJEXT): internal/attr/alloc_size.h +enc/cp949.$(OBJEXT): internal/attr/cold.h +enc/cp949.$(OBJEXT): internal/attr/const.h +enc/cp949.$(OBJEXT): internal/attr/deprecated.h +enc/cp949.$(OBJEXT): internal/attr/error.h +enc/cp949.$(OBJEXT): internal/attr/forceinline.h +enc/cp949.$(OBJEXT): internal/attr/format.h +enc/cp949.$(OBJEXT): internal/attr/maybe_unused.h +enc/cp949.$(OBJEXT): internal/attr/nodiscard.h +enc/cp949.$(OBJEXT): internal/attr/noexcept.h +enc/cp949.$(OBJEXT): internal/attr/noinline.h +enc/cp949.$(OBJEXT): internal/attr/nonnull.h +enc/cp949.$(OBJEXT): internal/attr/noreturn.h +enc/cp949.$(OBJEXT): internal/attr/pure.h +enc/cp949.$(OBJEXT): internal/attr/restrict.h +enc/cp949.$(OBJEXT): internal/attr/returns_nonnull.h +enc/cp949.$(OBJEXT): internal/attr/warning.h +enc/cp949.$(OBJEXT): internal/cast.h +enc/cp949.$(OBJEXT): internal/compiler_is.h +enc/cp949.$(OBJEXT): internal/compiler_is/apple.h +enc/cp949.$(OBJEXT): internal/compiler_is/clang.h +enc/cp949.$(OBJEXT): internal/compiler_is/gcc.h +enc/cp949.$(OBJEXT): internal/compiler_is/intel.h +enc/cp949.$(OBJEXT): internal/compiler_is/msvc.h +enc/cp949.$(OBJEXT): internal/compiler_is/sunpro.h +enc/cp949.$(OBJEXT): internal/compiler_since.h +enc/cp949.$(OBJEXT): internal/config.h +enc/cp949.$(OBJEXT): internal/dllexport.h +enc/cp949.$(OBJEXT): internal/dosish.h +enc/cp949.$(OBJEXT): internal/has/attribute.h +enc/cp949.$(OBJEXT): internal/has/builtin.h +enc/cp949.$(OBJEXT): internal/has/c_attribute.h +enc/cp949.$(OBJEXT): internal/has/cpp_attribute.h +enc/cp949.$(OBJEXT): internal/has/declspec_attribute.h +enc/cp949.$(OBJEXT): internal/has/extension.h +enc/cp949.$(OBJEXT): internal/has/feature.h +enc/cp949.$(OBJEXT): internal/has/warning.h +enc/cp949.$(OBJEXT): internal/stdalign.h +enc/cp949.$(OBJEXT): internal/stdbool.h +enc/cp949.$(OBJEXT): internal/warning_push.h +enc/cp949.$(OBJEXT): internal/xmalloc.h enc/cp949.$(OBJEXT): missing.h enc/cp949.$(OBJEXT): onigmo.h enc/emacs_mule.$(OBJEXT): $(top_srcdir)/regenc.h +enc/emacs_mule.$(OBJEXT): assert.h +enc/emacs_mule.$(OBJEXT): backward/2/assume.h +enc/emacs_mule.$(OBJEXT): backward/2/attributes.h +enc/emacs_mule.$(OBJEXT): backward/2/bool.h +enc/emacs_mule.$(OBJEXT): backward/2/long_long.h +enc/emacs_mule.$(OBJEXT): backward/2/stdalign.h +enc/emacs_mule.$(OBJEXT): backward/2/stdarg.h enc/emacs_mule.$(OBJEXT): config.h enc/emacs_mule.$(OBJEXT): defines.h enc/emacs_mule.$(OBJEXT): enc/emacs_mule.c +enc/emacs_mule.$(OBJEXT): internal/assume.h +enc/emacs_mule.$(OBJEXT): internal/attr/alloc_size.h +enc/emacs_mule.$(OBJEXT): internal/attr/cold.h +enc/emacs_mule.$(OBJEXT): internal/attr/const.h +enc/emacs_mule.$(OBJEXT): internal/attr/deprecated.h +enc/emacs_mule.$(OBJEXT): internal/attr/error.h +enc/emacs_mule.$(OBJEXT): internal/attr/forceinline.h +enc/emacs_mule.$(OBJEXT): internal/attr/format.h +enc/emacs_mule.$(OBJEXT): internal/attr/maybe_unused.h +enc/emacs_mule.$(OBJEXT): internal/attr/nodiscard.h +enc/emacs_mule.$(OBJEXT): internal/attr/noexcept.h +enc/emacs_mule.$(OBJEXT): internal/attr/noinline.h +enc/emacs_mule.$(OBJEXT): internal/attr/nonnull.h +enc/emacs_mule.$(OBJEXT): internal/attr/noreturn.h +enc/emacs_mule.$(OBJEXT): internal/attr/pure.h +enc/emacs_mule.$(OBJEXT): internal/attr/restrict.h +enc/emacs_mule.$(OBJEXT): internal/attr/returns_nonnull.h +enc/emacs_mule.$(OBJEXT): internal/attr/warning.h +enc/emacs_mule.$(OBJEXT): internal/cast.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/apple.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/clang.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/gcc.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/intel.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/msvc.h +enc/emacs_mule.$(OBJEXT): internal/compiler_is/sunpro.h +enc/emacs_mule.$(OBJEXT): internal/compiler_since.h +enc/emacs_mule.$(OBJEXT): internal/config.h +enc/emacs_mule.$(OBJEXT): internal/dllexport.h +enc/emacs_mule.$(OBJEXT): internal/dosish.h +enc/emacs_mule.$(OBJEXT): internal/has/attribute.h +enc/emacs_mule.$(OBJEXT): internal/has/builtin.h +enc/emacs_mule.$(OBJEXT): internal/has/c_attribute.h +enc/emacs_mule.$(OBJEXT): internal/has/cpp_attribute.h +enc/emacs_mule.$(OBJEXT): internal/has/declspec_attribute.h +enc/emacs_mule.$(OBJEXT): internal/has/extension.h +enc/emacs_mule.$(OBJEXT): internal/has/feature.h +enc/emacs_mule.$(OBJEXT): internal/has/warning.h +enc/emacs_mule.$(OBJEXT): internal/stdalign.h +enc/emacs_mule.$(OBJEXT): internal/stdbool.h +enc/emacs_mule.$(OBJEXT): internal/warning_push.h +enc/emacs_mule.$(OBJEXT): internal/xmalloc.h enc/emacs_mule.$(OBJEXT): missing.h enc/emacs_mule.$(OBJEXT): onigmo.h -enc/encdb.$(OBJEXT): $(hdrdir)/ruby.h enc/encdb.$(OBJEXT): $(hdrdir)/ruby/ruby.h -enc/encdb.$(OBJEXT): $(top_srcdir)/internal.h +enc/encdb.$(OBJEXT): $(top_srcdir)/internal/encoding.h enc/encdb.$(OBJEXT): assert.h enc/encdb.$(OBJEXT): backward.h +enc/encdb.$(OBJEXT): backward/2/assume.h +enc/encdb.$(OBJEXT): backward/2/attributes.h +enc/encdb.$(OBJEXT): backward/2/bool.h +enc/encdb.$(OBJEXT): backward/2/inttypes.h +enc/encdb.$(OBJEXT): backward/2/limits.h +enc/encdb.$(OBJEXT): backward/2/long_long.h +enc/encdb.$(OBJEXT): backward/2/stdalign.h +enc/encdb.$(OBJEXT): backward/2/stdarg.h enc/encdb.$(OBJEXT): config.h enc/encdb.$(OBJEXT): defines.h enc/encdb.$(OBJEXT): enc/encdb.c enc/encdb.$(OBJEXT): encdb.h +enc/encdb.$(OBJEXT): encoding.h enc/encdb.$(OBJEXT): intern.h +enc/encdb.$(OBJEXT): internal/anyargs.h +enc/encdb.$(OBJEXT): internal/arithmetic.h +enc/encdb.$(OBJEXT): internal/arithmetic/char.h +enc/encdb.$(OBJEXT): internal/arithmetic/double.h +enc/encdb.$(OBJEXT): internal/arithmetic/fixnum.h +enc/encdb.$(OBJEXT): internal/arithmetic/gid_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/int.h +enc/encdb.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/long.h +enc/encdb.$(OBJEXT): internal/arithmetic/long_long.h +enc/encdb.$(OBJEXT): internal/arithmetic/mode_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/off_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/pid_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/short.h +enc/encdb.$(OBJEXT): internal/arithmetic/size_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/encdb.$(OBJEXT): internal/arithmetic/uid_t.h +enc/encdb.$(OBJEXT): internal/assume.h +enc/encdb.$(OBJEXT): internal/attr/alloc_size.h +enc/encdb.$(OBJEXT): internal/attr/artificial.h +enc/encdb.$(OBJEXT): internal/attr/cold.h +enc/encdb.$(OBJEXT): internal/attr/const.h +enc/encdb.$(OBJEXT): internal/attr/constexpr.h +enc/encdb.$(OBJEXT): internal/attr/deprecated.h +enc/encdb.$(OBJEXT): internal/attr/diagnose_if.h +enc/encdb.$(OBJEXT): internal/attr/enum_extensibility.h +enc/encdb.$(OBJEXT): internal/attr/error.h +enc/encdb.$(OBJEXT): internal/attr/flag_enum.h +enc/encdb.$(OBJEXT): internal/attr/forceinline.h +enc/encdb.$(OBJEXT): internal/attr/format.h +enc/encdb.$(OBJEXT): internal/attr/maybe_unused.h +enc/encdb.$(OBJEXT): internal/attr/noalias.h +enc/encdb.$(OBJEXT): internal/attr/nodiscard.h +enc/encdb.$(OBJEXT): internal/attr/noexcept.h +enc/encdb.$(OBJEXT): internal/attr/noinline.h +enc/encdb.$(OBJEXT): internal/attr/nonnull.h +enc/encdb.$(OBJEXT): internal/attr/noreturn.h +enc/encdb.$(OBJEXT): internal/attr/pure.h +enc/encdb.$(OBJEXT): internal/attr/restrict.h +enc/encdb.$(OBJEXT): internal/attr/returns_nonnull.h +enc/encdb.$(OBJEXT): internal/attr/warning.h +enc/encdb.$(OBJEXT): internal/attr/weakref.h +enc/encdb.$(OBJEXT): internal/cast.h +enc/encdb.$(OBJEXT): internal/compiler_is.h +enc/encdb.$(OBJEXT): internal/compiler_is/apple.h +enc/encdb.$(OBJEXT): internal/compiler_is/clang.h +enc/encdb.$(OBJEXT): internal/compiler_is/gcc.h +enc/encdb.$(OBJEXT): internal/compiler_is/intel.h +enc/encdb.$(OBJEXT): internal/compiler_is/msvc.h +enc/encdb.$(OBJEXT): internal/compiler_is/sunpro.h +enc/encdb.$(OBJEXT): internal/compiler_since.h +enc/encdb.$(OBJEXT): internal/config.h +enc/encdb.$(OBJEXT): internal/constant_p.h +enc/encdb.$(OBJEXT): internal/core.h +enc/encdb.$(OBJEXT): internal/core/rarray.h +enc/encdb.$(OBJEXT): internal/core/rbasic.h +enc/encdb.$(OBJEXT): internal/core/rbignum.h +enc/encdb.$(OBJEXT): internal/core/rclass.h +enc/encdb.$(OBJEXT): internal/core/rdata.h +enc/encdb.$(OBJEXT): internal/core/rfile.h +enc/encdb.$(OBJEXT): internal/core/rhash.h +enc/encdb.$(OBJEXT): internal/core/robject.h +enc/encdb.$(OBJEXT): internal/core/rregexp.h +enc/encdb.$(OBJEXT): internal/core/rstring.h +enc/encdb.$(OBJEXT): internal/core/rstruct.h +enc/encdb.$(OBJEXT): internal/core/rtypeddata.h +enc/encdb.$(OBJEXT): internal/ctype.h +enc/encdb.$(OBJEXT): internal/dllexport.h +enc/encdb.$(OBJEXT): internal/dosish.h +enc/encdb.$(OBJEXT): internal/encoding/coderange.h +enc/encdb.$(OBJEXT): internal/encoding/ctype.h +enc/encdb.$(OBJEXT): internal/encoding/encoding.h +enc/encdb.$(OBJEXT): internal/encoding/pathname.h +enc/encdb.$(OBJEXT): internal/encoding/re.h +enc/encdb.$(OBJEXT): internal/encoding/sprintf.h +enc/encdb.$(OBJEXT): internal/encoding/string.h +enc/encdb.$(OBJEXT): internal/encoding/symbol.h +enc/encdb.$(OBJEXT): internal/encoding/transcode.h +enc/encdb.$(OBJEXT): internal/error.h +enc/encdb.$(OBJEXT): internal/eval.h +enc/encdb.$(OBJEXT): internal/event.h +enc/encdb.$(OBJEXT): internal/fl_type.h +enc/encdb.$(OBJEXT): internal/gc.h +enc/encdb.$(OBJEXT): internal/glob.h +enc/encdb.$(OBJEXT): internal/globals.h +enc/encdb.$(OBJEXT): internal/has/attribute.h +enc/encdb.$(OBJEXT): internal/has/builtin.h +enc/encdb.$(OBJEXT): internal/has/c_attribute.h +enc/encdb.$(OBJEXT): internal/has/cpp_attribute.h +enc/encdb.$(OBJEXT): internal/has/declspec_attribute.h +enc/encdb.$(OBJEXT): internal/has/extension.h +enc/encdb.$(OBJEXT): internal/has/feature.h +enc/encdb.$(OBJEXT): internal/has/warning.h +enc/encdb.$(OBJEXT): internal/intern/array.h +enc/encdb.$(OBJEXT): internal/intern/bignum.h +enc/encdb.$(OBJEXT): internal/intern/class.h +enc/encdb.$(OBJEXT): internal/intern/compar.h +enc/encdb.$(OBJEXT): internal/intern/complex.h +enc/encdb.$(OBJEXT): internal/intern/cont.h +enc/encdb.$(OBJEXT): internal/intern/dir.h +enc/encdb.$(OBJEXT): internal/intern/enum.h +enc/encdb.$(OBJEXT): internal/intern/enumerator.h +enc/encdb.$(OBJEXT): internal/intern/error.h +enc/encdb.$(OBJEXT): internal/intern/eval.h +enc/encdb.$(OBJEXT): internal/intern/file.h +enc/encdb.$(OBJEXT): internal/intern/gc.h +enc/encdb.$(OBJEXT): internal/intern/hash.h +enc/encdb.$(OBJEXT): internal/intern/io.h +enc/encdb.$(OBJEXT): internal/intern/load.h +enc/encdb.$(OBJEXT): internal/intern/marshal.h +enc/encdb.$(OBJEXT): internal/intern/numeric.h +enc/encdb.$(OBJEXT): internal/intern/object.h +enc/encdb.$(OBJEXT): internal/intern/parse.h +enc/encdb.$(OBJEXT): internal/intern/proc.h +enc/encdb.$(OBJEXT): internal/intern/process.h +enc/encdb.$(OBJEXT): internal/intern/random.h +enc/encdb.$(OBJEXT): internal/intern/range.h +enc/encdb.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/encdb.$(OBJEXT): internal/intern/sprintf.h +enc/encdb.$(OBJEXT): internal/intern/string.h +enc/encdb.$(OBJEXT): internal/intern/struct.h +enc/encdb.$(OBJEXT): internal/intern/thread.h +enc/encdb.$(OBJEXT): internal/intern/time.h +enc/encdb.$(OBJEXT): internal/intern/variable.h +enc/encdb.$(OBJEXT): internal/intern/vm.h +enc/encdb.$(OBJEXT): internal/interpreter.h +enc/encdb.$(OBJEXT): internal/iterator.h +enc/encdb.$(OBJEXT): internal/memory.h +enc/encdb.$(OBJEXT): internal/method.h +enc/encdb.$(OBJEXT): internal/module.h +enc/encdb.$(OBJEXT): internal/newobj.h +enc/encdb.$(OBJEXT): internal/rgengc.h +enc/encdb.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/encdb.$(OBJEXT): internal/value.h +enc/encdb.$(OBJEXT): internal/value_type.h +enc/encdb.$(OBJEXT): internal/variable.h +enc/encdb.$(OBJEXT): internal/warning_push.h +enc/encdb.$(OBJEXT): internal/xmalloc.h enc/encdb.$(OBJEXT): missing.h +enc/encdb.$(OBJEXT): onigmo.h +enc/encdb.$(OBJEXT): oniguruma.h enc/encdb.$(OBJEXT): st.h enc/encdb.$(OBJEXT): subst.h enc/euc_jp.$(OBJEXT): $(top_srcdir)/regenc.h +enc/euc_jp.$(OBJEXT): assert.h +enc/euc_jp.$(OBJEXT): backward/2/assume.h +enc/euc_jp.$(OBJEXT): backward/2/attributes.h +enc/euc_jp.$(OBJEXT): backward/2/bool.h +enc/euc_jp.$(OBJEXT): backward/2/long_long.h +enc/euc_jp.$(OBJEXT): backward/2/stdalign.h +enc/euc_jp.$(OBJEXT): backward/2/stdarg.h enc/euc_jp.$(OBJEXT): config.h enc/euc_jp.$(OBJEXT): defines.h enc/euc_jp.$(OBJEXT): enc/euc_jp.c enc/euc_jp.$(OBJEXT): enc/jis/props.h enc/euc_jp.$(OBJEXT): enc/jis/props.kwd +enc/euc_jp.$(OBJEXT): internal/assume.h +enc/euc_jp.$(OBJEXT): internal/attr/alloc_size.h +enc/euc_jp.$(OBJEXT): internal/attr/cold.h +enc/euc_jp.$(OBJEXT): internal/attr/const.h +enc/euc_jp.$(OBJEXT): internal/attr/deprecated.h +enc/euc_jp.$(OBJEXT): internal/attr/error.h +enc/euc_jp.$(OBJEXT): internal/attr/forceinline.h +enc/euc_jp.$(OBJEXT): internal/attr/format.h +enc/euc_jp.$(OBJEXT): internal/attr/maybe_unused.h +enc/euc_jp.$(OBJEXT): internal/attr/nodiscard.h +enc/euc_jp.$(OBJEXT): internal/attr/noexcept.h +enc/euc_jp.$(OBJEXT): internal/attr/noinline.h +enc/euc_jp.$(OBJEXT): internal/attr/nonnull.h +enc/euc_jp.$(OBJEXT): internal/attr/noreturn.h +enc/euc_jp.$(OBJEXT): internal/attr/pure.h +enc/euc_jp.$(OBJEXT): internal/attr/restrict.h +enc/euc_jp.$(OBJEXT): internal/attr/returns_nonnull.h +enc/euc_jp.$(OBJEXT): internal/attr/warning.h +enc/euc_jp.$(OBJEXT): internal/cast.h +enc/euc_jp.$(OBJEXT): internal/compiler_is.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/apple.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/clang.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/gcc.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/intel.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/msvc.h +enc/euc_jp.$(OBJEXT): internal/compiler_is/sunpro.h +enc/euc_jp.$(OBJEXT): internal/compiler_since.h +enc/euc_jp.$(OBJEXT): internal/config.h +enc/euc_jp.$(OBJEXT): internal/dllexport.h +enc/euc_jp.$(OBJEXT): internal/dosish.h +enc/euc_jp.$(OBJEXT): internal/has/attribute.h +enc/euc_jp.$(OBJEXT): internal/has/builtin.h +enc/euc_jp.$(OBJEXT): internal/has/c_attribute.h +enc/euc_jp.$(OBJEXT): internal/has/cpp_attribute.h +enc/euc_jp.$(OBJEXT): internal/has/declspec_attribute.h +enc/euc_jp.$(OBJEXT): internal/has/extension.h +enc/euc_jp.$(OBJEXT): internal/has/feature.h +enc/euc_jp.$(OBJEXT): internal/has/warning.h +enc/euc_jp.$(OBJEXT): internal/stdalign.h +enc/euc_jp.$(OBJEXT): internal/stdbool.h +enc/euc_jp.$(OBJEXT): internal/warning_push.h +enc/euc_jp.$(OBJEXT): internal/xmalloc.h enc/euc_jp.$(OBJEXT): missing.h enc/euc_jp.$(OBJEXT): onigmo.h enc/euc_kr.$(OBJEXT): $(top_srcdir)/regenc.h +enc/euc_kr.$(OBJEXT): assert.h +enc/euc_kr.$(OBJEXT): backward/2/assume.h +enc/euc_kr.$(OBJEXT): backward/2/attributes.h +enc/euc_kr.$(OBJEXT): backward/2/bool.h +enc/euc_kr.$(OBJEXT): backward/2/long_long.h +enc/euc_kr.$(OBJEXT): backward/2/stdalign.h +enc/euc_kr.$(OBJEXT): backward/2/stdarg.h enc/euc_kr.$(OBJEXT): config.h enc/euc_kr.$(OBJEXT): defines.h enc/euc_kr.$(OBJEXT): enc/euc_kr.c +enc/euc_kr.$(OBJEXT): internal/assume.h +enc/euc_kr.$(OBJEXT): internal/attr/alloc_size.h +enc/euc_kr.$(OBJEXT): internal/attr/cold.h +enc/euc_kr.$(OBJEXT): internal/attr/const.h +enc/euc_kr.$(OBJEXT): internal/attr/deprecated.h +enc/euc_kr.$(OBJEXT): internal/attr/error.h +enc/euc_kr.$(OBJEXT): internal/attr/forceinline.h +enc/euc_kr.$(OBJEXT): internal/attr/format.h +enc/euc_kr.$(OBJEXT): internal/attr/maybe_unused.h +enc/euc_kr.$(OBJEXT): internal/attr/nodiscard.h +enc/euc_kr.$(OBJEXT): internal/attr/noexcept.h +enc/euc_kr.$(OBJEXT): internal/attr/noinline.h +enc/euc_kr.$(OBJEXT): internal/attr/nonnull.h +enc/euc_kr.$(OBJEXT): internal/attr/noreturn.h +enc/euc_kr.$(OBJEXT): internal/attr/pure.h +enc/euc_kr.$(OBJEXT): internal/attr/restrict.h +enc/euc_kr.$(OBJEXT): internal/attr/returns_nonnull.h +enc/euc_kr.$(OBJEXT): internal/attr/warning.h +enc/euc_kr.$(OBJEXT): internal/cast.h +enc/euc_kr.$(OBJEXT): internal/compiler_is.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/apple.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/clang.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/gcc.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/intel.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/msvc.h +enc/euc_kr.$(OBJEXT): internal/compiler_is/sunpro.h +enc/euc_kr.$(OBJEXT): internal/compiler_since.h +enc/euc_kr.$(OBJEXT): internal/config.h +enc/euc_kr.$(OBJEXT): internal/dllexport.h +enc/euc_kr.$(OBJEXT): internal/dosish.h +enc/euc_kr.$(OBJEXT): internal/has/attribute.h +enc/euc_kr.$(OBJEXT): internal/has/builtin.h +enc/euc_kr.$(OBJEXT): internal/has/c_attribute.h +enc/euc_kr.$(OBJEXT): internal/has/cpp_attribute.h +enc/euc_kr.$(OBJEXT): internal/has/declspec_attribute.h +enc/euc_kr.$(OBJEXT): internal/has/extension.h +enc/euc_kr.$(OBJEXT): internal/has/feature.h +enc/euc_kr.$(OBJEXT): internal/has/warning.h +enc/euc_kr.$(OBJEXT): internal/stdalign.h +enc/euc_kr.$(OBJEXT): internal/stdbool.h +enc/euc_kr.$(OBJEXT): internal/warning_push.h +enc/euc_kr.$(OBJEXT): internal/xmalloc.h enc/euc_kr.$(OBJEXT): missing.h enc/euc_kr.$(OBJEXT): onigmo.h enc/euc_tw.$(OBJEXT): $(top_srcdir)/regenc.h +enc/euc_tw.$(OBJEXT): assert.h +enc/euc_tw.$(OBJEXT): backward/2/assume.h +enc/euc_tw.$(OBJEXT): backward/2/attributes.h +enc/euc_tw.$(OBJEXT): backward/2/bool.h +enc/euc_tw.$(OBJEXT): backward/2/long_long.h +enc/euc_tw.$(OBJEXT): backward/2/stdalign.h +enc/euc_tw.$(OBJEXT): backward/2/stdarg.h enc/euc_tw.$(OBJEXT): config.h enc/euc_tw.$(OBJEXT): defines.h enc/euc_tw.$(OBJEXT): enc/euc_tw.c +enc/euc_tw.$(OBJEXT): internal/assume.h +enc/euc_tw.$(OBJEXT): internal/attr/alloc_size.h +enc/euc_tw.$(OBJEXT): internal/attr/cold.h +enc/euc_tw.$(OBJEXT): internal/attr/const.h +enc/euc_tw.$(OBJEXT): internal/attr/deprecated.h +enc/euc_tw.$(OBJEXT): internal/attr/error.h +enc/euc_tw.$(OBJEXT): internal/attr/forceinline.h +enc/euc_tw.$(OBJEXT): internal/attr/format.h +enc/euc_tw.$(OBJEXT): internal/attr/maybe_unused.h +enc/euc_tw.$(OBJEXT): internal/attr/nodiscard.h +enc/euc_tw.$(OBJEXT): internal/attr/noexcept.h +enc/euc_tw.$(OBJEXT): internal/attr/noinline.h +enc/euc_tw.$(OBJEXT): internal/attr/nonnull.h +enc/euc_tw.$(OBJEXT): internal/attr/noreturn.h +enc/euc_tw.$(OBJEXT): internal/attr/pure.h +enc/euc_tw.$(OBJEXT): internal/attr/restrict.h +enc/euc_tw.$(OBJEXT): internal/attr/returns_nonnull.h +enc/euc_tw.$(OBJEXT): internal/attr/warning.h +enc/euc_tw.$(OBJEXT): internal/cast.h +enc/euc_tw.$(OBJEXT): internal/compiler_is.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/apple.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/clang.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/gcc.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/intel.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/msvc.h +enc/euc_tw.$(OBJEXT): internal/compiler_is/sunpro.h +enc/euc_tw.$(OBJEXT): internal/compiler_since.h +enc/euc_tw.$(OBJEXT): internal/config.h +enc/euc_tw.$(OBJEXT): internal/dllexport.h +enc/euc_tw.$(OBJEXT): internal/dosish.h +enc/euc_tw.$(OBJEXT): internal/has/attribute.h +enc/euc_tw.$(OBJEXT): internal/has/builtin.h +enc/euc_tw.$(OBJEXT): internal/has/c_attribute.h +enc/euc_tw.$(OBJEXT): internal/has/cpp_attribute.h +enc/euc_tw.$(OBJEXT): internal/has/declspec_attribute.h +enc/euc_tw.$(OBJEXT): internal/has/extension.h +enc/euc_tw.$(OBJEXT): internal/has/feature.h +enc/euc_tw.$(OBJEXT): internal/has/warning.h +enc/euc_tw.$(OBJEXT): internal/stdalign.h +enc/euc_tw.$(OBJEXT): internal/stdbool.h +enc/euc_tw.$(OBJEXT): internal/warning_push.h +enc/euc_tw.$(OBJEXT): internal/xmalloc.h enc/euc_tw.$(OBJEXT): missing.h enc/euc_tw.$(OBJEXT): onigmo.h enc/gb18030.$(OBJEXT): $(top_srcdir)/regenc.h +enc/gb18030.$(OBJEXT): assert.h +enc/gb18030.$(OBJEXT): backward/2/assume.h +enc/gb18030.$(OBJEXT): backward/2/attributes.h +enc/gb18030.$(OBJEXT): backward/2/bool.h +enc/gb18030.$(OBJEXT): backward/2/long_long.h +enc/gb18030.$(OBJEXT): backward/2/stdalign.h +enc/gb18030.$(OBJEXT): backward/2/stdarg.h enc/gb18030.$(OBJEXT): config.h enc/gb18030.$(OBJEXT): defines.h enc/gb18030.$(OBJEXT): enc/gb18030.c +enc/gb18030.$(OBJEXT): internal/assume.h +enc/gb18030.$(OBJEXT): internal/attr/alloc_size.h +enc/gb18030.$(OBJEXT): internal/attr/cold.h +enc/gb18030.$(OBJEXT): internal/attr/const.h +enc/gb18030.$(OBJEXT): internal/attr/deprecated.h +enc/gb18030.$(OBJEXT): internal/attr/error.h +enc/gb18030.$(OBJEXT): internal/attr/forceinline.h +enc/gb18030.$(OBJEXT): internal/attr/format.h +enc/gb18030.$(OBJEXT): internal/attr/maybe_unused.h +enc/gb18030.$(OBJEXT): internal/attr/nodiscard.h +enc/gb18030.$(OBJEXT): internal/attr/noexcept.h +enc/gb18030.$(OBJEXT): internal/attr/noinline.h +enc/gb18030.$(OBJEXT): internal/attr/nonnull.h +enc/gb18030.$(OBJEXT): internal/attr/noreturn.h +enc/gb18030.$(OBJEXT): internal/attr/pure.h +enc/gb18030.$(OBJEXT): internal/attr/restrict.h +enc/gb18030.$(OBJEXT): internal/attr/returns_nonnull.h +enc/gb18030.$(OBJEXT): internal/attr/warning.h +enc/gb18030.$(OBJEXT): internal/cast.h +enc/gb18030.$(OBJEXT): internal/compiler_is.h +enc/gb18030.$(OBJEXT): internal/compiler_is/apple.h +enc/gb18030.$(OBJEXT): internal/compiler_is/clang.h +enc/gb18030.$(OBJEXT): internal/compiler_is/gcc.h +enc/gb18030.$(OBJEXT): internal/compiler_is/intel.h +enc/gb18030.$(OBJEXT): internal/compiler_is/msvc.h +enc/gb18030.$(OBJEXT): internal/compiler_is/sunpro.h +enc/gb18030.$(OBJEXT): internal/compiler_since.h +enc/gb18030.$(OBJEXT): internal/config.h +enc/gb18030.$(OBJEXT): internal/dllexport.h +enc/gb18030.$(OBJEXT): internal/dosish.h +enc/gb18030.$(OBJEXT): internal/has/attribute.h +enc/gb18030.$(OBJEXT): internal/has/builtin.h +enc/gb18030.$(OBJEXT): internal/has/c_attribute.h +enc/gb18030.$(OBJEXT): internal/has/cpp_attribute.h +enc/gb18030.$(OBJEXT): internal/has/declspec_attribute.h +enc/gb18030.$(OBJEXT): internal/has/extension.h +enc/gb18030.$(OBJEXT): internal/has/feature.h +enc/gb18030.$(OBJEXT): internal/has/warning.h +enc/gb18030.$(OBJEXT): internal/stdalign.h +enc/gb18030.$(OBJEXT): internal/stdbool.h +enc/gb18030.$(OBJEXT): internal/warning_push.h +enc/gb18030.$(OBJEXT): internal/xmalloc.h enc/gb18030.$(OBJEXT): missing.h enc/gb18030.$(OBJEXT): onigmo.h enc/gb2312.$(OBJEXT): $(top_srcdir)/regenc.h +enc/gb2312.$(OBJEXT): assert.h +enc/gb2312.$(OBJEXT): backward/2/assume.h +enc/gb2312.$(OBJEXT): backward/2/attributes.h +enc/gb2312.$(OBJEXT): backward/2/bool.h +enc/gb2312.$(OBJEXT): backward/2/long_long.h +enc/gb2312.$(OBJEXT): backward/2/stdalign.h +enc/gb2312.$(OBJEXT): backward/2/stdarg.h enc/gb2312.$(OBJEXT): config.h enc/gb2312.$(OBJEXT): defines.h enc/gb2312.$(OBJEXT): enc/gb2312.c +enc/gb2312.$(OBJEXT): internal/assume.h +enc/gb2312.$(OBJEXT): internal/attr/alloc_size.h +enc/gb2312.$(OBJEXT): internal/attr/cold.h +enc/gb2312.$(OBJEXT): internal/attr/const.h +enc/gb2312.$(OBJEXT): internal/attr/deprecated.h +enc/gb2312.$(OBJEXT): internal/attr/error.h +enc/gb2312.$(OBJEXT): internal/attr/forceinline.h +enc/gb2312.$(OBJEXT): internal/attr/format.h +enc/gb2312.$(OBJEXT): internal/attr/maybe_unused.h +enc/gb2312.$(OBJEXT): internal/attr/nodiscard.h +enc/gb2312.$(OBJEXT): internal/attr/noexcept.h +enc/gb2312.$(OBJEXT): internal/attr/noinline.h +enc/gb2312.$(OBJEXT): internal/attr/nonnull.h +enc/gb2312.$(OBJEXT): internal/attr/noreturn.h +enc/gb2312.$(OBJEXT): internal/attr/pure.h +enc/gb2312.$(OBJEXT): internal/attr/restrict.h +enc/gb2312.$(OBJEXT): internal/attr/returns_nonnull.h +enc/gb2312.$(OBJEXT): internal/attr/warning.h +enc/gb2312.$(OBJEXT): internal/cast.h +enc/gb2312.$(OBJEXT): internal/compiler_is.h +enc/gb2312.$(OBJEXT): internal/compiler_is/apple.h +enc/gb2312.$(OBJEXT): internal/compiler_is/clang.h +enc/gb2312.$(OBJEXT): internal/compiler_is/gcc.h +enc/gb2312.$(OBJEXT): internal/compiler_is/intel.h +enc/gb2312.$(OBJEXT): internal/compiler_is/msvc.h +enc/gb2312.$(OBJEXT): internal/compiler_is/sunpro.h +enc/gb2312.$(OBJEXT): internal/compiler_since.h +enc/gb2312.$(OBJEXT): internal/config.h +enc/gb2312.$(OBJEXT): internal/dllexport.h +enc/gb2312.$(OBJEXT): internal/dosish.h +enc/gb2312.$(OBJEXT): internal/has/attribute.h +enc/gb2312.$(OBJEXT): internal/has/builtin.h +enc/gb2312.$(OBJEXT): internal/has/c_attribute.h +enc/gb2312.$(OBJEXT): internal/has/cpp_attribute.h +enc/gb2312.$(OBJEXT): internal/has/declspec_attribute.h +enc/gb2312.$(OBJEXT): internal/has/extension.h +enc/gb2312.$(OBJEXT): internal/has/feature.h +enc/gb2312.$(OBJEXT): internal/has/warning.h +enc/gb2312.$(OBJEXT): internal/stdalign.h +enc/gb2312.$(OBJEXT): internal/stdbool.h +enc/gb2312.$(OBJEXT): internal/warning_push.h +enc/gb2312.$(OBJEXT): internal/xmalloc.h enc/gb2312.$(OBJEXT): missing.h enc/gb2312.$(OBJEXT): onigmo.h enc/gbk.$(OBJEXT): $(top_srcdir)/regenc.h +enc/gbk.$(OBJEXT): assert.h +enc/gbk.$(OBJEXT): backward/2/assume.h +enc/gbk.$(OBJEXT): backward/2/attributes.h +enc/gbk.$(OBJEXT): backward/2/bool.h +enc/gbk.$(OBJEXT): backward/2/long_long.h +enc/gbk.$(OBJEXT): backward/2/stdalign.h +enc/gbk.$(OBJEXT): backward/2/stdarg.h enc/gbk.$(OBJEXT): config.h enc/gbk.$(OBJEXT): defines.h enc/gbk.$(OBJEXT): enc/gbk.c +enc/gbk.$(OBJEXT): internal/assume.h +enc/gbk.$(OBJEXT): internal/attr/alloc_size.h +enc/gbk.$(OBJEXT): internal/attr/cold.h +enc/gbk.$(OBJEXT): internal/attr/const.h +enc/gbk.$(OBJEXT): internal/attr/deprecated.h +enc/gbk.$(OBJEXT): internal/attr/error.h +enc/gbk.$(OBJEXT): internal/attr/forceinline.h +enc/gbk.$(OBJEXT): internal/attr/format.h +enc/gbk.$(OBJEXT): internal/attr/maybe_unused.h +enc/gbk.$(OBJEXT): internal/attr/nodiscard.h +enc/gbk.$(OBJEXT): internal/attr/noexcept.h +enc/gbk.$(OBJEXT): internal/attr/noinline.h +enc/gbk.$(OBJEXT): internal/attr/nonnull.h +enc/gbk.$(OBJEXT): internal/attr/noreturn.h +enc/gbk.$(OBJEXT): internal/attr/pure.h +enc/gbk.$(OBJEXT): internal/attr/restrict.h +enc/gbk.$(OBJEXT): internal/attr/returns_nonnull.h +enc/gbk.$(OBJEXT): internal/attr/warning.h +enc/gbk.$(OBJEXT): internal/cast.h +enc/gbk.$(OBJEXT): internal/compiler_is.h +enc/gbk.$(OBJEXT): internal/compiler_is/apple.h +enc/gbk.$(OBJEXT): internal/compiler_is/clang.h +enc/gbk.$(OBJEXT): internal/compiler_is/gcc.h +enc/gbk.$(OBJEXT): internal/compiler_is/intel.h +enc/gbk.$(OBJEXT): internal/compiler_is/msvc.h +enc/gbk.$(OBJEXT): internal/compiler_is/sunpro.h +enc/gbk.$(OBJEXT): internal/compiler_since.h +enc/gbk.$(OBJEXT): internal/config.h +enc/gbk.$(OBJEXT): internal/dllexport.h +enc/gbk.$(OBJEXT): internal/dosish.h +enc/gbk.$(OBJEXT): internal/has/attribute.h +enc/gbk.$(OBJEXT): internal/has/builtin.h +enc/gbk.$(OBJEXT): internal/has/c_attribute.h +enc/gbk.$(OBJEXT): internal/has/cpp_attribute.h +enc/gbk.$(OBJEXT): internal/has/declspec_attribute.h +enc/gbk.$(OBJEXT): internal/has/extension.h +enc/gbk.$(OBJEXT): internal/has/feature.h +enc/gbk.$(OBJEXT): internal/has/warning.h +enc/gbk.$(OBJEXT): internal/stdalign.h +enc/gbk.$(OBJEXT): internal/stdbool.h +enc/gbk.$(OBJEXT): internal/warning_push.h +enc/gbk.$(OBJEXT): internal/xmalloc.h enc/gbk.$(OBJEXT): missing.h enc/gbk.$(OBJEXT): onigmo.h enc/iso_8859_1.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_1.$(OBJEXT): assert.h +enc/iso_8859_1.$(OBJEXT): backward/2/assume.h +enc/iso_8859_1.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_1.$(OBJEXT): backward/2/bool.h +enc/iso_8859_1.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_1.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_1.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_1.$(OBJEXT): config.h enc/iso_8859_1.$(OBJEXT): defines.h enc/iso_8859_1.$(OBJEXT): enc/iso_8859.h enc/iso_8859_1.$(OBJEXT): enc/iso_8859_1.c +enc/iso_8859_1.$(OBJEXT): internal/assume.h +enc/iso_8859_1.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_1.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_1.$(OBJEXT): internal/attr/const.h +enc/iso_8859_1.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_1.$(OBJEXT): internal/attr/error.h +enc/iso_8859_1.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_1.$(OBJEXT): internal/attr/format.h +enc/iso_8859_1.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_1.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_1.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_1.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_1.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_1.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_1.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_1.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_1.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_1.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_1.$(OBJEXT): internal/cast.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_1.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_1.$(OBJEXT): internal/config.h +enc/iso_8859_1.$(OBJEXT): internal/dllexport.h +enc/iso_8859_1.$(OBJEXT): internal/dosish.h +enc/iso_8859_1.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_1.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_1.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_1.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_1.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_1.$(OBJEXT): internal/has/extension.h +enc/iso_8859_1.$(OBJEXT): internal/has/feature.h +enc/iso_8859_1.$(OBJEXT): internal/has/warning.h +enc/iso_8859_1.$(OBJEXT): internal/stdalign.h +enc/iso_8859_1.$(OBJEXT): internal/stdbool.h +enc/iso_8859_1.$(OBJEXT): internal/warning_push.h +enc/iso_8859_1.$(OBJEXT): internal/xmalloc.h enc/iso_8859_1.$(OBJEXT): missing.h enc/iso_8859_1.$(OBJEXT): onigmo.h enc/iso_8859_10.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_10.$(OBJEXT): assert.h +enc/iso_8859_10.$(OBJEXT): backward/2/assume.h +enc/iso_8859_10.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_10.$(OBJEXT): backward/2/bool.h +enc/iso_8859_10.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_10.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_10.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_10.$(OBJEXT): config.h enc/iso_8859_10.$(OBJEXT): defines.h enc/iso_8859_10.$(OBJEXT): enc/iso_8859.h enc/iso_8859_10.$(OBJEXT): enc/iso_8859_10.c +enc/iso_8859_10.$(OBJEXT): internal/assume.h +enc/iso_8859_10.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_10.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_10.$(OBJEXT): internal/attr/const.h +enc/iso_8859_10.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_10.$(OBJEXT): internal/attr/error.h +enc/iso_8859_10.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_10.$(OBJEXT): internal/attr/format.h +enc/iso_8859_10.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_10.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_10.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_10.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_10.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_10.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_10.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_10.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_10.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_10.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_10.$(OBJEXT): internal/cast.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_10.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_10.$(OBJEXT): internal/config.h +enc/iso_8859_10.$(OBJEXT): internal/dllexport.h +enc/iso_8859_10.$(OBJEXT): internal/dosish.h +enc/iso_8859_10.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_10.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_10.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_10.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_10.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_10.$(OBJEXT): internal/has/extension.h +enc/iso_8859_10.$(OBJEXT): internal/has/feature.h +enc/iso_8859_10.$(OBJEXT): internal/has/warning.h +enc/iso_8859_10.$(OBJEXT): internal/stdalign.h +enc/iso_8859_10.$(OBJEXT): internal/stdbool.h +enc/iso_8859_10.$(OBJEXT): internal/warning_push.h +enc/iso_8859_10.$(OBJEXT): internal/xmalloc.h enc/iso_8859_10.$(OBJEXT): missing.h enc/iso_8859_10.$(OBJEXT): onigmo.h enc/iso_8859_11.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_11.$(OBJEXT): assert.h +enc/iso_8859_11.$(OBJEXT): backward/2/assume.h +enc/iso_8859_11.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_11.$(OBJEXT): backward/2/bool.h +enc/iso_8859_11.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_11.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_11.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_11.$(OBJEXT): config.h enc/iso_8859_11.$(OBJEXT): defines.h enc/iso_8859_11.$(OBJEXT): enc/iso_8859_11.c +enc/iso_8859_11.$(OBJEXT): internal/assume.h +enc/iso_8859_11.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_11.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_11.$(OBJEXT): internal/attr/const.h +enc/iso_8859_11.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_11.$(OBJEXT): internal/attr/error.h +enc/iso_8859_11.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_11.$(OBJEXT): internal/attr/format.h +enc/iso_8859_11.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_11.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_11.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_11.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_11.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_11.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_11.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_11.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_11.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_11.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_11.$(OBJEXT): internal/cast.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_11.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_11.$(OBJEXT): internal/config.h +enc/iso_8859_11.$(OBJEXT): internal/dllexport.h +enc/iso_8859_11.$(OBJEXT): internal/dosish.h +enc/iso_8859_11.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_11.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_11.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_11.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_11.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_11.$(OBJEXT): internal/has/extension.h +enc/iso_8859_11.$(OBJEXT): internal/has/feature.h +enc/iso_8859_11.$(OBJEXT): internal/has/warning.h +enc/iso_8859_11.$(OBJEXT): internal/stdalign.h +enc/iso_8859_11.$(OBJEXT): internal/stdbool.h +enc/iso_8859_11.$(OBJEXT): internal/warning_push.h +enc/iso_8859_11.$(OBJEXT): internal/xmalloc.h enc/iso_8859_11.$(OBJEXT): missing.h enc/iso_8859_11.$(OBJEXT): onigmo.h enc/iso_8859_13.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_13.$(OBJEXT): assert.h +enc/iso_8859_13.$(OBJEXT): backward/2/assume.h +enc/iso_8859_13.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_13.$(OBJEXT): backward/2/bool.h +enc/iso_8859_13.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_13.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_13.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_13.$(OBJEXT): config.h enc/iso_8859_13.$(OBJEXT): defines.h enc/iso_8859_13.$(OBJEXT): enc/iso_8859.h enc/iso_8859_13.$(OBJEXT): enc/iso_8859_13.c +enc/iso_8859_13.$(OBJEXT): internal/assume.h +enc/iso_8859_13.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_13.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_13.$(OBJEXT): internal/attr/const.h +enc/iso_8859_13.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_13.$(OBJEXT): internal/attr/error.h +enc/iso_8859_13.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_13.$(OBJEXT): internal/attr/format.h +enc/iso_8859_13.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_13.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_13.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_13.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_13.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_13.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_13.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_13.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_13.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_13.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_13.$(OBJEXT): internal/cast.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_13.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_13.$(OBJEXT): internal/config.h +enc/iso_8859_13.$(OBJEXT): internal/dllexport.h +enc/iso_8859_13.$(OBJEXT): internal/dosish.h +enc/iso_8859_13.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_13.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_13.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_13.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_13.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_13.$(OBJEXT): internal/has/extension.h +enc/iso_8859_13.$(OBJEXT): internal/has/feature.h +enc/iso_8859_13.$(OBJEXT): internal/has/warning.h +enc/iso_8859_13.$(OBJEXT): internal/stdalign.h +enc/iso_8859_13.$(OBJEXT): internal/stdbool.h +enc/iso_8859_13.$(OBJEXT): internal/warning_push.h +enc/iso_8859_13.$(OBJEXT): internal/xmalloc.h enc/iso_8859_13.$(OBJEXT): missing.h enc/iso_8859_13.$(OBJEXT): onigmo.h enc/iso_8859_14.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_14.$(OBJEXT): assert.h +enc/iso_8859_14.$(OBJEXT): backward/2/assume.h +enc/iso_8859_14.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_14.$(OBJEXT): backward/2/bool.h +enc/iso_8859_14.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_14.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_14.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_14.$(OBJEXT): config.h enc/iso_8859_14.$(OBJEXT): defines.h enc/iso_8859_14.$(OBJEXT): enc/iso_8859.h enc/iso_8859_14.$(OBJEXT): enc/iso_8859_14.c +enc/iso_8859_14.$(OBJEXT): internal/assume.h +enc/iso_8859_14.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_14.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_14.$(OBJEXT): internal/attr/const.h +enc/iso_8859_14.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_14.$(OBJEXT): internal/attr/error.h +enc/iso_8859_14.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_14.$(OBJEXT): internal/attr/format.h +enc/iso_8859_14.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_14.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_14.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_14.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_14.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_14.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_14.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_14.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_14.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_14.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_14.$(OBJEXT): internal/cast.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_14.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_14.$(OBJEXT): internal/config.h +enc/iso_8859_14.$(OBJEXT): internal/dllexport.h +enc/iso_8859_14.$(OBJEXT): internal/dosish.h +enc/iso_8859_14.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_14.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_14.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_14.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_14.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_14.$(OBJEXT): internal/has/extension.h +enc/iso_8859_14.$(OBJEXT): internal/has/feature.h +enc/iso_8859_14.$(OBJEXT): internal/has/warning.h +enc/iso_8859_14.$(OBJEXT): internal/stdalign.h +enc/iso_8859_14.$(OBJEXT): internal/stdbool.h +enc/iso_8859_14.$(OBJEXT): internal/warning_push.h +enc/iso_8859_14.$(OBJEXT): internal/xmalloc.h enc/iso_8859_14.$(OBJEXT): missing.h enc/iso_8859_14.$(OBJEXT): onigmo.h enc/iso_8859_15.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_15.$(OBJEXT): assert.h +enc/iso_8859_15.$(OBJEXT): backward/2/assume.h +enc/iso_8859_15.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_15.$(OBJEXT): backward/2/bool.h +enc/iso_8859_15.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_15.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_15.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_15.$(OBJEXT): config.h enc/iso_8859_15.$(OBJEXT): defines.h enc/iso_8859_15.$(OBJEXT): enc/iso_8859.h enc/iso_8859_15.$(OBJEXT): enc/iso_8859_15.c +enc/iso_8859_15.$(OBJEXT): internal/assume.h +enc/iso_8859_15.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_15.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_15.$(OBJEXT): internal/attr/const.h +enc/iso_8859_15.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_15.$(OBJEXT): internal/attr/error.h +enc/iso_8859_15.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_15.$(OBJEXT): internal/attr/format.h +enc/iso_8859_15.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_15.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_15.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_15.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_15.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_15.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_15.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_15.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_15.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_15.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_15.$(OBJEXT): internal/cast.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_15.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_15.$(OBJEXT): internal/config.h +enc/iso_8859_15.$(OBJEXT): internal/dllexport.h +enc/iso_8859_15.$(OBJEXT): internal/dosish.h +enc/iso_8859_15.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_15.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_15.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_15.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_15.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_15.$(OBJEXT): internal/has/extension.h +enc/iso_8859_15.$(OBJEXT): internal/has/feature.h +enc/iso_8859_15.$(OBJEXT): internal/has/warning.h +enc/iso_8859_15.$(OBJEXT): internal/stdalign.h +enc/iso_8859_15.$(OBJEXT): internal/stdbool.h +enc/iso_8859_15.$(OBJEXT): internal/warning_push.h +enc/iso_8859_15.$(OBJEXT): internal/xmalloc.h enc/iso_8859_15.$(OBJEXT): missing.h enc/iso_8859_15.$(OBJEXT): onigmo.h enc/iso_8859_16.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_16.$(OBJEXT): assert.h +enc/iso_8859_16.$(OBJEXT): backward/2/assume.h +enc/iso_8859_16.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_16.$(OBJEXT): backward/2/bool.h +enc/iso_8859_16.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_16.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_16.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_16.$(OBJEXT): config.h enc/iso_8859_16.$(OBJEXT): defines.h enc/iso_8859_16.$(OBJEXT): enc/iso_8859.h enc/iso_8859_16.$(OBJEXT): enc/iso_8859_16.c +enc/iso_8859_16.$(OBJEXT): internal/assume.h +enc/iso_8859_16.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_16.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_16.$(OBJEXT): internal/attr/const.h +enc/iso_8859_16.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_16.$(OBJEXT): internal/attr/error.h +enc/iso_8859_16.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_16.$(OBJEXT): internal/attr/format.h +enc/iso_8859_16.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_16.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_16.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_16.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_16.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_16.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_16.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_16.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_16.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_16.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_16.$(OBJEXT): internal/cast.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_16.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_16.$(OBJEXT): internal/config.h +enc/iso_8859_16.$(OBJEXT): internal/dllexport.h +enc/iso_8859_16.$(OBJEXT): internal/dosish.h +enc/iso_8859_16.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_16.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_16.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_16.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_16.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_16.$(OBJEXT): internal/has/extension.h +enc/iso_8859_16.$(OBJEXT): internal/has/feature.h +enc/iso_8859_16.$(OBJEXT): internal/has/warning.h +enc/iso_8859_16.$(OBJEXT): internal/stdalign.h +enc/iso_8859_16.$(OBJEXT): internal/stdbool.h +enc/iso_8859_16.$(OBJEXT): internal/warning_push.h +enc/iso_8859_16.$(OBJEXT): internal/xmalloc.h enc/iso_8859_16.$(OBJEXT): missing.h enc/iso_8859_16.$(OBJEXT): onigmo.h enc/iso_8859_2.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_2.$(OBJEXT): assert.h +enc/iso_8859_2.$(OBJEXT): backward/2/assume.h +enc/iso_8859_2.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_2.$(OBJEXT): backward/2/bool.h +enc/iso_8859_2.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_2.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_2.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_2.$(OBJEXT): config.h enc/iso_8859_2.$(OBJEXT): defines.h enc/iso_8859_2.$(OBJEXT): enc/iso_8859.h enc/iso_8859_2.$(OBJEXT): enc/iso_8859_2.c +enc/iso_8859_2.$(OBJEXT): internal/assume.h +enc/iso_8859_2.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_2.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_2.$(OBJEXT): internal/attr/const.h +enc/iso_8859_2.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_2.$(OBJEXT): internal/attr/error.h +enc/iso_8859_2.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_2.$(OBJEXT): internal/attr/format.h +enc/iso_8859_2.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_2.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_2.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_2.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_2.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_2.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_2.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_2.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_2.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_2.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_2.$(OBJEXT): internal/cast.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_2.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_2.$(OBJEXT): internal/config.h +enc/iso_8859_2.$(OBJEXT): internal/dllexport.h +enc/iso_8859_2.$(OBJEXT): internal/dosish.h +enc/iso_8859_2.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_2.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_2.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_2.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_2.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_2.$(OBJEXT): internal/has/extension.h +enc/iso_8859_2.$(OBJEXT): internal/has/feature.h +enc/iso_8859_2.$(OBJEXT): internal/has/warning.h +enc/iso_8859_2.$(OBJEXT): internal/stdalign.h +enc/iso_8859_2.$(OBJEXT): internal/stdbool.h +enc/iso_8859_2.$(OBJEXT): internal/warning_push.h +enc/iso_8859_2.$(OBJEXT): internal/xmalloc.h enc/iso_8859_2.$(OBJEXT): missing.h enc/iso_8859_2.$(OBJEXT): onigmo.h enc/iso_8859_3.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_3.$(OBJEXT): assert.h +enc/iso_8859_3.$(OBJEXT): backward/2/assume.h +enc/iso_8859_3.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_3.$(OBJEXT): backward/2/bool.h +enc/iso_8859_3.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_3.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_3.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_3.$(OBJEXT): config.h enc/iso_8859_3.$(OBJEXT): defines.h enc/iso_8859_3.$(OBJEXT): enc/iso_8859.h enc/iso_8859_3.$(OBJEXT): enc/iso_8859_3.c +enc/iso_8859_3.$(OBJEXT): internal/assume.h +enc/iso_8859_3.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_3.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_3.$(OBJEXT): internal/attr/const.h +enc/iso_8859_3.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_3.$(OBJEXT): internal/attr/error.h +enc/iso_8859_3.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_3.$(OBJEXT): internal/attr/format.h +enc/iso_8859_3.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_3.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_3.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_3.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_3.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_3.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_3.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_3.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_3.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_3.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_3.$(OBJEXT): internal/cast.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_3.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_3.$(OBJEXT): internal/config.h +enc/iso_8859_3.$(OBJEXT): internal/dllexport.h +enc/iso_8859_3.$(OBJEXT): internal/dosish.h +enc/iso_8859_3.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_3.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_3.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_3.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_3.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_3.$(OBJEXT): internal/has/extension.h +enc/iso_8859_3.$(OBJEXT): internal/has/feature.h +enc/iso_8859_3.$(OBJEXT): internal/has/warning.h +enc/iso_8859_3.$(OBJEXT): internal/stdalign.h +enc/iso_8859_3.$(OBJEXT): internal/stdbool.h +enc/iso_8859_3.$(OBJEXT): internal/warning_push.h +enc/iso_8859_3.$(OBJEXT): internal/xmalloc.h enc/iso_8859_3.$(OBJEXT): missing.h enc/iso_8859_3.$(OBJEXT): onigmo.h enc/iso_8859_4.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_4.$(OBJEXT): assert.h +enc/iso_8859_4.$(OBJEXT): backward/2/assume.h +enc/iso_8859_4.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_4.$(OBJEXT): backward/2/bool.h +enc/iso_8859_4.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_4.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_4.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_4.$(OBJEXT): config.h enc/iso_8859_4.$(OBJEXT): defines.h enc/iso_8859_4.$(OBJEXT): enc/iso_8859.h enc/iso_8859_4.$(OBJEXT): enc/iso_8859_4.c +enc/iso_8859_4.$(OBJEXT): internal/assume.h +enc/iso_8859_4.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_4.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_4.$(OBJEXT): internal/attr/const.h +enc/iso_8859_4.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_4.$(OBJEXT): internal/attr/error.h +enc/iso_8859_4.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_4.$(OBJEXT): internal/attr/format.h +enc/iso_8859_4.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_4.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_4.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_4.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_4.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_4.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_4.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_4.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_4.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_4.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_4.$(OBJEXT): internal/cast.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_4.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_4.$(OBJEXT): internal/config.h +enc/iso_8859_4.$(OBJEXT): internal/dllexport.h +enc/iso_8859_4.$(OBJEXT): internal/dosish.h +enc/iso_8859_4.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_4.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_4.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_4.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_4.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_4.$(OBJEXT): internal/has/extension.h +enc/iso_8859_4.$(OBJEXT): internal/has/feature.h +enc/iso_8859_4.$(OBJEXT): internal/has/warning.h +enc/iso_8859_4.$(OBJEXT): internal/stdalign.h +enc/iso_8859_4.$(OBJEXT): internal/stdbool.h +enc/iso_8859_4.$(OBJEXT): internal/warning_push.h +enc/iso_8859_4.$(OBJEXT): internal/xmalloc.h enc/iso_8859_4.$(OBJEXT): missing.h enc/iso_8859_4.$(OBJEXT): onigmo.h enc/iso_8859_5.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_5.$(OBJEXT): assert.h +enc/iso_8859_5.$(OBJEXT): backward/2/assume.h +enc/iso_8859_5.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_5.$(OBJEXT): backward/2/bool.h +enc/iso_8859_5.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_5.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_5.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_5.$(OBJEXT): config.h enc/iso_8859_5.$(OBJEXT): defines.h enc/iso_8859_5.$(OBJEXT): enc/iso_8859_5.c +enc/iso_8859_5.$(OBJEXT): internal/assume.h +enc/iso_8859_5.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_5.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_5.$(OBJEXT): internal/attr/const.h +enc/iso_8859_5.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_5.$(OBJEXT): internal/attr/error.h +enc/iso_8859_5.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_5.$(OBJEXT): internal/attr/format.h +enc/iso_8859_5.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_5.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_5.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_5.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_5.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_5.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_5.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_5.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_5.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_5.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_5.$(OBJEXT): internal/cast.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_5.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_5.$(OBJEXT): internal/config.h +enc/iso_8859_5.$(OBJEXT): internal/dllexport.h +enc/iso_8859_5.$(OBJEXT): internal/dosish.h +enc/iso_8859_5.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_5.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_5.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_5.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_5.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_5.$(OBJEXT): internal/has/extension.h +enc/iso_8859_5.$(OBJEXT): internal/has/feature.h +enc/iso_8859_5.$(OBJEXT): internal/has/warning.h +enc/iso_8859_5.$(OBJEXT): internal/stdalign.h +enc/iso_8859_5.$(OBJEXT): internal/stdbool.h +enc/iso_8859_5.$(OBJEXT): internal/warning_push.h +enc/iso_8859_5.$(OBJEXT): internal/xmalloc.h enc/iso_8859_5.$(OBJEXT): missing.h enc/iso_8859_5.$(OBJEXT): onigmo.h enc/iso_8859_6.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_6.$(OBJEXT): assert.h +enc/iso_8859_6.$(OBJEXT): backward/2/assume.h +enc/iso_8859_6.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_6.$(OBJEXT): backward/2/bool.h +enc/iso_8859_6.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_6.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_6.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_6.$(OBJEXT): config.h enc/iso_8859_6.$(OBJEXT): defines.h enc/iso_8859_6.$(OBJEXT): enc/iso_8859_6.c +enc/iso_8859_6.$(OBJEXT): internal/assume.h +enc/iso_8859_6.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_6.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_6.$(OBJEXT): internal/attr/const.h +enc/iso_8859_6.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_6.$(OBJEXT): internal/attr/error.h +enc/iso_8859_6.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_6.$(OBJEXT): internal/attr/format.h +enc/iso_8859_6.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_6.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_6.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_6.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_6.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_6.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_6.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_6.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_6.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_6.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_6.$(OBJEXT): internal/cast.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_6.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_6.$(OBJEXT): internal/config.h +enc/iso_8859_6.$(OBJEXT): internal/dllexport.h +enc/iso_8859_6.$(OBJEXT): internal/dosish.h +enc/iso_8859_6.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_6.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_6.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_6.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_6.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_6.$(OBJEXT): internal/has/extension.h +enc/iso_8859_6.$(OBJEXT): internal/has/feature.h +enc/iso_8859_6.$(OBJEXT): internal/has/warning.h +enc/iso_8859_6.$(OBJEXT): internal/stdalign.h +enc/iso_8859_6.$(OBJEXT): internal/stdbool.h +enc/iso_8859_6.$(OBJEXT): internal/warning_push.h +enc/iso_8859_6.$(OBJEXT): internal/xmalloc.h enc/iso_8859_6.$(OBJEXT): missing.h enc/iso_8859_6.$(OBJEXT): onigmo.h enc/iso_8859_7.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_7.$(OBJEXT): assert.h +enc/iso_8859_7.$(OBJEXT): backward/2/assume.h +enc/iso_8859_7.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_7.$(OBJEXT): backward/2/bool.h +enc/iso_8859_7.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_7.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_7.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_7.$(OBJEXT): config.h enc/iso_8859_7.$(OBJEXT): defines.h enc/iso_8859_7.$(OBJEXT): enc/iso_8859_7.c +enc/iso_8859_7.$(OBJEXT): internal/assume.h +enc/iso_8859_7.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_7.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_7.$(OBJEXT): internal/attr/const.h +enc/iso_8859_7.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_7.$(OBJEXT): internal/attr/error.h +enc/iso_8859_7.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_7.$(OBJEXT): internal/attr/format.h +enc/iso_8859_7.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_7.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_7.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_7.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_7.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_7.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_7.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_7.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_7.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_7.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_7.$(OBJEXT): internal/cast.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_7.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_7.$(OBJEXT): internal/config.h +enc/iso_8859_7.$(OBJEXT): internal/dllexport.h +enc/iso_8859_7.$(OBJEXT): internal/dosish.h +enc/iso_8859_7.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_7.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_7.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_7.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_7.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_7.$(OBJEXT): internal/has/extension.h +enc/iso_8859_7.$(OBJEXT): internal/has/feature.h +enc/iso_8859_7.$(OBJEXT): internal/has/warning.h +enc/iso_8859_7.$(OBJEXT): internal/stdalign.h +enc/iso_8859_7.$(OBJEXT): internal/stdbool.h +enc/iso_8859_7.$(OBJEXT): internal/warning_push.h +enc/iso_8859_7.$(OBJEXT): internal/xmalloc.h enc/iso_8859_7.$(OBJEXT): missing.h enc/iso_8859_7.$(OBJEXT): onigmo.h enc/iso_8859_8.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_8.$(OBJEXT): assert.h +enc/iso_8859_8.$(OBJEXT): backward/2/assume.h +enc/iso_8859_8.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_8.$(OBJEXT): backward/2/bool.h +enc/iso_8859_8.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_8.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_8.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_8.$(OBJEXT): config.h enc/iso_8859_8.$(OBJEXT): defines.h enc/iso_8859_8.$(OBJEXT): enc/iso_8859_8.c +enc/iso_8859_8.$(OBJEXT): internal/assume.h +enc/iso_8859_8.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_8.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_8.$(OBJEXT): internal/attr/const.h +enc/iso_8859_8.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_8.$(OBJEXT): internal/attr/error.h +enc/iso_8859_8.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_8.$(OBJEXT): internal/attr/format.h +enc/iso_8859_8.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_8.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_8.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_8.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_8.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_8.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_8.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_8.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_8.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_8.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_8.$(OBJEXT): internal/cast.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_8.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_8.$(OBJEXT): internal/config.h +enc/iso_8859_8.$(OBJEXT): internal/dllexport.h +enc/iso_8859_8.$(OBJEXT): internal/dosish.h +enc/iso_8859_8.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_8.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_8.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_8.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_8.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_8.$(OBJEXT): internal/has/extension.h +enc/iso_8859_8.$(OBJEXT): internal/has/feature.h +enc/iso_8859_8.$(OBJEXT): internal/has/warning.h +enc/iso_8859_8.$(OBJEXT): internal/stdalign.h +enc/iso_8859_8.$(OBJEXT): internal/stdbool.h +enc/iso_8859_8.$(OBJEXT): internal/warning_push.h +enc/iso_8859_8.$(OBJEXT): internal/xmalloc.h enc/iso_8859_8.$(OBJEXT): missing.h enc/iso_8859_8.$(OBJEXT): onigmo.h enc/iso_8859_9.$(OBJEXT): $(top_srcdir)/regenc.h +enc/iso_8859_9.$(OBJEXT): assert.h +enc/iso_8859_9.$(OBJEXT): backward/2/assume.h +enc/iso_8859_9.$(OBJEXT): backward/2/attributes.h +enc/iso_8859_9.$(OBJEXT): backward/2/bool.h +enc/iso_8859_9.$(OBJEXT): backward/2/long_long.h +enc/iso_8859_9.$(OBJEXT): backward/2/stdalign.h +enc/iso_8859_9.$(OBJEXT): backward/2/stdarg.h enc/iso_8859_9.$(OBJEXT): config.h enc/iso_8859_9.$(OBJEXT): defines.h enc/iso_8859_9.$(OBJEXT): enc/iso_8859.h enc/iso_8859_9.$(OBJEXT): enc/iso_8859_9.c +enc/iso_8859_9.$(OBJEXT): internal/assume.h +enc/iso_8859_9.$(OBJEXT): internal/attr/alloc_size.h +enc/iso_8859_9.$(OBJEXT): internal/attr/cold.h +enc/iso_8859_9.$(OBJEXT): internal/attr/const.h +enc/iso_8859_9.$(OBJEXT): internal/attr/deprecated.h +enc/iso_8859_9.$(OBJEXT): internal/attr/error.h +enc/iso_8859_9.$(OBJEXT): internal/attr/forceinline.h +enc/iso_8859_9.$(OBJEXT): internal/attr/format.h +enc/iso_8859_9.$(OBJEXT): internal/attr/maybe_unused.h +enc/iso_8859_9.$(OBJEXT): internal/attr/nodiscard.h +enc/iso_8859_9.$(OBJEXT): internal/attr/noexcept.h +enc/iso_8859_9.$(OBJEXT): internal/attr/noinline.h +enc/iso_8859_9.$(OBJEXT): internal/attr/nonnull.h +enc/iso_8859_9.$(OBJEXT): internal/attr/noreturn.h +enc/iso_8859_9.$(OBJEXT): internal/attr/pure.h +enc/iso_8859_9.$(OBJEXT): internal/attr/restrict.h +enc/iso_8859_9.$(OBJEXT): internal/attr/returns_nonnull.h +enc/iso_8859_9.$(OBJEXT): internal/attr/warning.h +enc/iso_8859_9.$(OBJEXT): internal/cast.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/apple.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/clang.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/gcc.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/intel.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/msvc.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_is/sunpro.h +enc/iso_8859_9.$(OBJEXT): internal/compiler_since.h +enc/iso_8859_9.$(OBJEXT): internal/config.h +enc/iso_8859_9.$(OBJEXT): internal/dllexport.h +enc/iso_8859_9.$(OBJEXT): internal/dosish.h +enc/iso_8859_9.$(OBJEXT): internal/has/attribute.h +enc/iso_8859_9.$(OBJEXT): internal/has/builtin.h +enc/iso_8859_9.$(OBJEXT): internal/has/c_attribute.h +enc/iso_8859_9.$(OBJEXT): internal/has/cpp_attribute.h +enc/iso_8859_9.$(OBJEXT): internal/has/declspec_attribute.h +enc/iso_8859_9.$(OBJEXT): internal/has/extension.h +enc/iso_8859_9.$(OBJEXT): internal/has/feature.h +enc/iso_8859_9.$(OBJEXT): internal/has/warning.h +enc/iso_8859_9.$(OBJEXT): internal/stdalign.h +enc/iso_8859_9.$(OBJEXT): internal/stdbool.h +enc/iso_8859_9.$(OBJEXT): internal/warning_push.h +enc/iso_8859_9.$(OBJEXT): internal/xmalloc.h enc/iso_8859_9.$(OBJEXT): missing.h enc/iso_8859_9.$(OBJEXT): onigmo.h enc/koi8_r.$(OBJEXT): $(top_srcdir)/regenc.h +enc/koi8_r.$(OBJEXT): assert.h +enc/koi8_r.$(OBJEXT): backward/2/assume.h +enc/koi8_r.$(OBJEXT): backward/2/attributes.h +enc/koi8_r.$(OBJEXT): backward/2/bool.h +enc/koi8_r.$(OBJEXT): backward/2/long_long.h +enc/koi8_r.$(OBJEXT): backward/2/stdalign.h +enc/koi8_r.$(OBJEXT): backward/2/stdarg.h enc/koi8_r.$(OBJEXT): config.h enc/koi8_r.$(OBJEXT): defines.h enc/koi8_r.$(OBJEXT): enc/koi8_r.c +enc/koi8_r.$(OBJEXT): internal/assume.h +enc/koi8_r.$(OBJEXT): internal/attr/alloc_size.h +enc/koi8_r.$(OBJEXT): internal/attr/cold.h +enc/koi8_r.$(OBJEXT): internal/attr/const.h +enc/koi8_r.$(OBJEXT): internal/attr/deprecated.h +enc/koi8_r.$(OBJEXT): internal/attr/error.h +enc/koi8_r.$(OBJEXT): internal/attr/forceinline.h +enc/koi8_r.$(OBJEXT): internal/attr/format.h +enc/koi8_r.$(OBJEXT): internal/attr/maybe_unused.h +enc/koi8_r.$(OBJEXT): internal/attr/nodiscard.h +enc/koi8_r.$(OBJEXT): internal/attr/noexcept.h +enc/koi8_r.$(OBJEXT): internal/attr/noinline.h +enc/koi8_r.$(OBJEXT): internal/attr/nonnull.h +enc/koi8_r.$(OBJEXT): internal/attr/noreturn.h +enc/koi8_r.$(OBJEXT): internal/attr/pure.h +enc/koi8_r.$(OBJEXT): internal/attr/restrict.h +enc/koi8_r.$(OBJEXT): internal/attr/returns_nonnull.h +enc/koi8_r.$(OBJEXT): internal/attr/warning.h +enc/koi8_r.$(OBJEXT): internal/cast.h +enc/koi8_r.$(OBJEXT): internal/compiler_is.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/apple.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/clang.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/gcc.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/intel.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/msvc.h +enc/koi8_r.$(OBJEXT): internal/compiler_is/sunpro.h +enc/koi8_r.$(OBJEXT): internal/compiler_since.h +enc/koi8_r.$(OBJEXT): internal/config.h +enc/koi8_r.$(OBJEXT): internal/dllexport.h +enc/koi8_r.$(OBJEXT): internal/dosish.h +enc/koi8_r.$(OBJEXT): internal/has/attribute.h +enc/koi8_r.$(OBJEXT): internal/has/builtin.h +enc/koi8_r.$(OBJEXT): internal/has/c_attribute.h +enc/koi8_r.$(OBJEXT): internal/has/cpp_attribute.h +enc/koi8_r.$(OBJEXT): internal/has/declspec_attribute.h +enc/koi8_r.$(OBJEXT): internal/has/extension.h +enc/koi8_r.$(OBJEXT): internal/has/feature.h +enc/koi8_r.$(OBJEXT): internal/has/warning.h +enc/koi8_r.$(OBJEXT): internal/stdalign.h +enc/koi8_r.$(OBJEXT): internal/stdbool.h +enc/koi8_r.$(OBJEXT): internal/warning_push.h +enc/koi8_r.$(OBJEXT): internal/xmalloc.h enc/koi8_r.$(OBJEXT): missing.h enc/koi8_r.$(OBJEXT): onigmo.h enc/koi8_u.$(OBJEXT): $(top_srcdir)/regenc.h +enc/koi8_u.$(OBJEXT): assert.h +enc/koi8_u.$(OBJEXT): backward/2/assume.h +enc/koi8_u.$(OBJEXT): backward/2/attributes.h +enc/koi8_u.$(OBJEXT): backward/2/bool.h +enc/koi8_u.$(OBJEXT): backward/2/long_long.h +enc/koi8_u.$(OBJEXT): backward/2/stdalign.h +enc/koi8_u.$(OBJEXT): backward/2/stdarg.h enc/koi8_u.$(OBJEXT): config.h enc/koi8_u.$(OBJEXT): defines.h enc/koi8_u.$(OBJEXT): enc/koi8_u.c +enc/koi8_u.$(OBJEXT): internal/assume.h +enc/koi8_u.$(OBJEXT): internal/attr/alloc_size.h +enc/koi8_u.$(OBJEXT): internal/attr/cold.h +enc/koi8_u.$(OBJEXT): internal/attr/const.h +enc/koi8_u.$(OBJEXT): internal/attr/deprecated.h +enc/koi8_u.$(OBJEXT): internal/attr/error.h +enc/koi8_u.$(OBJEXT): internal/attr/forceinline.h +enc/koi8_u.$(OBJEXT): internal/attr/format.h +enc/koi8_u.$(OBJEXT): internal/attr/maybe_unused.h +enc/koi8_u.$(OBJEXT): internal/attr/nodiscard.h +enc/koi8_u.$(OBJEXT): internal/attr/noexcept.h +enc/koi8_u.$(OBJEXT): internal/attr/noinline.h +enc/koi8_u.$(OBJEXT): internal/attr/nonnull.h +enc/koi8_u.$(OBJEXT): internal/attr/noreturn.h +enc/koi8_u.$(OBJEXT): internal/attr/pure.h +enc/koi8_u.$(OBJEXT): internal/attr/restrict.h +enc/koi8_u.$(OBJEXT): internal/attr/returns_nonnull.h +enc/koi8_u.$(OBJEXT): internal/attr/warning.h +enc/koi8_u.$(OBJEXT): internal/cast.h +enc/koi8_u.$(OBJEXT): internal/compiler_is.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/apple.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/clang.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/gcc.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/intel.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/msvc.h +enc/koi8_u.$(OBJEXT): internal/compiler_is/sunpro.h +enc/koi8_u.$(OBJEXT): internal/compiler_since.h +enc/koi8_u.$(OBJEXT): internal/config.h +enc/koi8_u.$(OBJEXT): internal/dllexport.h +enc/koi8_u.$(OBJEXT): internal/dosish.h +enc/koi8_u.$(OBJEXT): internal/has/attribute.h +enc/koi8_u.$(OBJEXT): internal/has/builtin.h +enc/koi8_u.$(OBJEXT): internal/has/c_attribute.h +enc/koi8_u.$(OBJEXT): internal/has/cpp_attribute.h +enc/koi8_u.$(OBJEXT): internal/has/declspec_attribute.h +enc/koi8_u.$(OBJEXT): internal/has/extension.h +enc/koi8_u.$(OBJEXT): internal/has/feature.h +enc/koi8_u.$(OBJEXT): internal/has/warning.h +enc/koi8_u.$(OBJEXT): internal/stdalign.h +enc/koi8_u.$(OBJEXT): internal/stdbool.h +enc/koi8_u.$(OBJEXT): internal/warning_push.h +enc/koi8_u.$(OBJEXT): internal/xmalloc.h enc/koi8_u.$(OBJEXT): missing.h enc/koi8_u.$(OBJEXT): onigmo.h enc/shift_jis.$(OBJEXT): $(top_srcdir)/regenc.h +enc/shift_jis.$(OBJEXT): assert.h +enc/shift_jis.$(OBJEXT): backward/2/assume.h +enc/shift_jis.$(OBJEXT): backward/2/attributes.h +enc/shift_jis.$(OBJEXT): backward/2/bool.h +enc/shift_jis.$(OBJEXT): backward/2/long_long.h +enc/shift_jis.$(OBJEXT): backward/2/stdalign.h +enc/shift_jis.$(OBJEXT): backward/2/stdarg.h enc/shift_jis.$(OBJEXT): config.h enc/shift_jis.$(OBJEXT): defines.h enc/shift_jis.$(OBJEXT): enc/jis/props.h enc/shift_jis.$(OBJEXT): enc/jis/props.kwd enc/shift_jis.$(OBJEXT): enc/shift_jis.c enc/shift_jis.$(OBJEXT): enc/shift_jis.h +enc/shift_jis.$(OBJEXT): internal/assume.h +enc/shift_jis.$(OBJEXT): internal/attr/alloc_size.h +enc/shift_jis.$(OBJEXT): internal/attr/cold.h +enc/shift_jis.$(OBJEXT): internal/attr/const.h +enc/shift_jis.$(OBJEXT): internal/attr/deprecated.h +enc/shift_jis.$(OBJEXT): internal/attr/error.h +enc/shift_jis.$(OBJEXT): internal/attr/forceinline.h +enc/shift_jis.$(OBJEXT): internal/attr/format.h +enc/shift_jis.$(OBJEXT): internal/attr/maybe_unused.h +enc/shift_jis.$(OBJEXT): internal/attr/nodiscard.h +enc/shift_jis.$(OBJEXT): internal/attr/noexcept.h +enc/shift_jis.$(OBJEXT): internal/attr/noinline.h +enc/shift_jis.$(OBJEXT): internal/attr/nonnull.h +enc/shift_jis.$(OBJEXT): internal/attr/noreturn.h +enc/shift_jis.$(OBJEXT): internal/attr/pure.h +enc/shift_jis.$(OBJEXT): internal/attr/restrict.h +enc/shift_jis.$(OBJEXT): internal/attr/returns_nonnull.h +enc/shift_jis.$(OBJEXT): internal/attr/warning.h +enc/shift_jis.$(OBJEXT): internal/cast.h +enc/shift_jis.$(OBJEXT): internal/compiler_is.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/apple.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/clang.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/gcc.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/intel.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/msvc.h +enc/shift_jis.$(OBJEXT): internal/compiler_is/sunpro.h +enc/shift_jis.$(OBJEXT): internal/compiler_since.h +enc/shift_jis.$(OBJEXT): internal/config.h +enc/shift_jis.$(OBJEXT): internal/dllexport.h +enc/shift_jis.$(OBJEXT): internal/dosish.h +enc/shift_jis.$(OBJEXT): internal/has/attribute.h +enc/shift_jis.$(OBJEXT): internal/has/builtin.h +enc/shift_jis.$(OBJEXT): internal/has/c_attribute.h +enc/shift_jis.$(OBJEXT): internal/has/cpp_attribute.h +enc/shift_jis.$(OBJEXT): internal/has/declspec_attribute.h +enc/shift_jis.$(OBJEXT): internal/has/extension.h +enc/shift_jis.$(OBJEXT): internal/has/feature.h +enc/shift_jis.$(OBJEXT): internal/has/warning.h +enc/shift_jis.$(OBJEXT): internal/stdalign.h +enc/shift_jis.$(OBJEXT): internal/stdbool.h +enc/shift_jis.$(OBJEXT): internal/warning_push.h +enc/shift_jis.$(OBJEXT): internal/xmalloc.h enc/shift_jis.$(OBJEXT): missing.h enc/shift_jis.$(OBJEXT): onigmo.h enc/trans/big5.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/big5.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/big5.$(OBJEXT): assert.h enc/trans/big5.$(OBJEXT): backward.h +enc/trans/big5.$(OBJEXT): backward/2/assume.h +enc/trans/big5.$(OBJEXT): backward/2/attributes.h +enc/trans/big5.$(OBJEXT): backward/2/bool.h +enc/trans/big5.$(OBJEXT): backward/2/inttypes.h +enc/trans/big5.$(OBJEXT): backward/2/limits.h +enc/trans/big5.$(OBJEXT): backward/2/long_long.h +enc/trans/big5.$(OBJEXT): backward/2/stdalign.h +enc/trans/big5.$(OBJEXT): backward/2/stdarg.h enc/trans/big5.$(OBJEXT): config.h enc/trans/big5.$(OBJEXT): defines.h enc/trans/big5.$(OBJEXT): enc/trans/big5.c enc/trans/big5.$(OBJEXT): intern.h +enc/trans/big5.$(OBJEXT): internal/anyargs.h +enc/trans/big5.$(OBJEXT): internal/arithmetic.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/char.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/double.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/int.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/long.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/short.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/big5.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/big5.$(OBJEXT): internal/assume.h +enc/trans/big5.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/big5.$(OBJEXT): internal/attr/artificial.h +enc/trans/big5.$(OBJEXT): internal/attr/cold.h +enc/trans/big5.$(OBJEXT): internal/attr/const.h +enc/trans/big5.$(OBJEXT): internal/attr/constexpr.h +enc/trans/big5.$(OBJEXT): internal/attr/deprecated.h +enc/trans/big5.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/big5.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/big5.$(OBJEXT): internal/attr/error.h +enc/trans/big5.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/big5.$(OBJEXT): internal/attr/forceinline.h +enc/trans/big5.$(OBJEXT): internal/attr/format.h +enc/trans/big5.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/big5.$(OBJEXT): internal/attr/noalias.h +enc/trans/big5.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/big5.$(OBJEXT): internal/attr/noexcept.h +enc/trans/big5.$(OBJEXT): internal/attr/noinline.h +enc/trans/big5.$(OBJEXT): internal/attr/nonnull.h +enc/trans/big5.$(OBJEXT): internal/attr/noreturn.h +enc/trans/big5.$(OBJEXT): internal/attr/pure.h +enc/trans/big5.$(OBJEXT): internal/attr/restrict.h +enc/trans/big5.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/big5.$(OBJEXT): internal/attr/warning.h +enc/trans/big5.$(OBJEXT): internal/attr/weakref.h +enc/trans/big5.$(OBJEXT): internal/cast.h +enc/trans/big5.$(OBJEXT): internal/compiler_is.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/big5.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/big5.$(OBJEXT): internal/compiler_since.h +enc/trans/big5.$(OBJEXT): internal/config.h +enc/trans/big5.$(OBJEXT): internal/constant_p.h +enc/trans/big5.$(OBJEXT): internal/core.h +enc/trans/big5.$(OBJEXT): internal/core/rarray.h +enc/trans/big5.$(OBJEXT): internal/core/rbasic.h +enc/trans/big5.$(OBJEXT): internal/core/rbignum.h +enc/trans/big5.$(OBJEXT): internal/core/rclass.h +enc/trans/big5.$(OBJEXT): internal/core/rdata.h +enc/trans/big5.$(OBJEXT): internal/core/rfile.h +enc/trans/big5.$(OBJEXT): internal/core/rhash.h +enc/trans/big5.$(OBJEXT): internal/core/robject.h +enc/trans/big5.$(OBJEXT): internal/core/rregexp.h +enc/trans/big5.$(OBJEXT): internal/core/rstring.h +enc/trans/big5.$(OBJEXT): internal/core/rstruct.h +enc/trans/big5.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/big5.$(OBJEXT): internal/ctype.h +enc/trans/big5.$(OBJEXT): internal/dllexport.h +enc/trans/big5.$(OBJEXT): internal/dosish.h +enc/trans/big5.$(OBJEXT): internal/error.h +enc/trans/big5.$(OBJEXT): internal/eval.h +enc/trans/big5.$(OBJEXT): internal/event.h +enc/trans/big5.$(OBJEXT): internal/fl_type.h +enc/trans/big5.$(OBJEXT): internal/gc.h +enc/trans/big5.$(OBJEXT): internal/glob.h +enc/trans/big5.$(OBJEXT): internal/globals.h +enc/trans/big5.$(OBJEXT): internal/has/attribute.h +enc/trans/big5.$(OBJEXT): internal/has/builtin.h +enc/trans/big5.$(OBJEXT): internal/has/c_attribute.h +enc/trans/big5.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/big5.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/big5.$(OBJEXT): internal/has/extension.h +enc/trans/big5.$(OBJEXT): internal/has/feature.h +enc/trans/big5.$(OBJEXT): internal/has/warning.h +enc/trans/big5.$(OBJEXT): internal/intern/array.h +enc/trans/big5.$(OBJEXT): internal/intern/bignum.h +enc/trans/big5.$(OBJEXT): internal/intern/class.h +enc/trans/big5.$(OBJEXT): internal/intern/compar.h +enc/trans/big5.$(OBJEXT): internal/intern/complex.h +enc/trans/big5.$(OBJEXT): internal/intern/cont.h +enc/trans/big5.$(OBJEXT): internal/intern/dir.h +enc/trans/big5.$(OBJEXT): internal/intern/enum.h +enc/trans/big5.$(OBJEXT): internal/intern/enumerator.h +enc/trans/big5.$(OBJEXT): internal/intern/error.h +enc/trans/big5.$(OBJEXT): internal/intern/eval.h +enc/trans/big5.$(OBJEXT): internal/intern/file.h +enc/trans/big5.$(OBJEXT): internal/intern/gc.h +enc/trans/big5.$(OBJEXT): internal/intern/hash.h +enc/trans/big5.$(OBJEXT): internal/intern/io.h +enc/trans/big5.$(OBJEXT): internal/intern/load.h +enc/trans/big5.$(OBJEXT): internal/intern/marshal.h +enc/trans/big5.$(OBJEXT): internal/intern/numeric.h +enc/trans/big5.$(OBJEXT): internal/intern/object.h +enc/trans/big5.$(OBJEXT): internal/intern/parse.h +enc/trans/big5.$(OBJEXT): internal/intern/proc.h +enc/trans/big5.$(OBJEXT): internal/intern/process.h +enc/trans/big5.$(OBJEXT): internal/intern/random.h +enc/trans/big5.$(OBJEXT): internal/intern/range.h +enc/trans/big5.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/big5.$(OBJEXT): internal/intern/sprintf.h +enc/trans/big5.$(OBJEXT): internal/intern/string.h +enc/trans/big5.$(OBJEXT): internal/intern/struct.h +enc/trans/big5.$(OBJEXT): internal/intern/thread.h +enc/trans/big5.$(OBJEXT): internal/intern/time.h +enc/trans/big5.$(OBJEXT): internal/intern/variable.h +enc/trans/big5.$(OBJEXT): internal/intern/vm.h +enc/trans/big5.$(OBJEXT): internal/interpreter.h +enc/trans/big5.$(OBJEXT): internal/iterator.h +enc/trans/big5.$(OBJEXT): internal/memory.h +enc/trans/big5.$(OBJEXT): internal/method.h +enc/trans/big5.$(OBJEXT): internal/module.h +enc/trans/big5.$(OBJEXT): internal/newobj.h +enc/trans/big5.$(OBJEXT): internal/rgengc.h +enc/trans/big5.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/big5.$(OBJEXT): internal/value.h +enc/trans/big5.$(OBJEXT): internal/value_type.h +enc/trans/big5.$(OBJEXT): internal/variable.h +enc/trans/big5.$(OBJEXT): internal/warning_push.h +enc/trans/big5.$(OBJEXT): internal/xmalloc.h enc/trans/big5.$(OBJEXT): missing.h enc/trans/big5.$(OBJEXT): st.h enc/trans/big5.$(OBJEXT): subst.h @@ -397,10 +2352,157 @@ enc/trans/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/cesu_8.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/cesu_8.$(OBJEXT): assert.h enc/trans/cesu_8.$(OBJEXT): backward.h +enc/trans/cesu_8.$(OBJEXT): backward/2/assume.h +enc/trans/cesu_8.$(OBJEXT): backward/2/attributes.h +enc/trans/cesu_8.$(OBJEXT): backward/2/bool.h +enc/trans/cesu_8.$(OBJEXT): backward/2/inttypes.h +enc/trans/cesu_8.$(OBJEXT): backward/2/limits.h +enc/trans/cesu_8.$(OBJEXT): backward/2/long_long.h +enc/trans/cesu_8.$(OBJEXT): backward/2/stdalign.h +enc/trans/cesu_8.$(OBJEXT): backward/2/stdarg.h enc/trans/cesu_8.$(OBJEXT): config.h enc/trans/cesu_8.$(OBJEXT): defines.h enc/trans/cesu_8.$(OBJEXT): enc/trans/cesu_8.c enc/trans/cesu_8.$(OBJEXT): intern.h +enc/trans/cesu_8.$(OBJEXT): internal/anyargs.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/char.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/double.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/int.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/long.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/short.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/cesu_8.$(OBJEXT): internal/assume.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/artificial.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/cold.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/const.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/constexpr.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/deprecated.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/error.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/forceinline.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/format.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/noalias.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/noexcept.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/noinline.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/nonnull.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/noreturn.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/pure.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/restrict.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/warning.h +enc/trans/cesu_8.$(OBJEXT): internal/attr/weakref.h +enc/trans/cesu_8.$(OBJEXT): internal/cast.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/cesu_8.$(OBJEXT): internal/compiler_since.h +enc/trans/cesu_8.$(OBJEXT): internal/config.h +enc/trans/cesu_8.$(OBJEXT): internal/constant_p.h +enc/trans/cesu_8.$(OBJEXT): internal/core.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rarray.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rbasic.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rbignum.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rclass.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rdata.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rfile.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rhash.h +enc/trans/cesu_8.$(OBJEXT): internal/core/robject.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rregexp.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rstring.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rstruct.h +enc/trans/cesu_8.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/cesu_8.$(OBJEXT): internal/ctype.h +enc/trans/cesu_8.$(OBJEXT): internal/dllexport.h +enc/trans/cesu_8.$(OBJEXT): internal/dosish.h +enc/trans/cesu_8.$(OBJEXT): internal/error.h +enc/trans/cesu_8.$(OBJEXT): internal/eval.h +enc/trans/cesu_8.$(OBJEXT): internal/event.h +enc/trans/cesu_8.$(OBJEXT): internal/fl_type.h +enc/trans/cesu_8.$(OBJEXT): internal/gc.h +enc/trans/cesu_8.$(OBJEXT): internal/glob.h +enc/trans/cesu_8.$(OBJEXT): internal/globals.h +enc/trans/cesu_8.$(OBJEXT): internal/has/attribute.h +enc/trans/cesu_8.$(OBJEXT): internal/has/builtin.h +enc/trans/cesu_8.$(OBJEXT): internal/has/c_attribute.h +enc/trans/cesu_8.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/cesu_8.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/cesu_8.$(OBJEXT): internal/has/extension.h +enc/trans/cesu_8.$(OBJEXT): internal/has/feature.h +enc/trans/cesu_8.$(OBJEXT): internal/has/warning.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/array.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/bignum.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/class.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/compar.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/complex.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/cont.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/dir.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/enum.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/enumerator.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/error.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/eval.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/file.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/gc.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/hash.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/io.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/load.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/marshal.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/numeric.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/object.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/parse.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/proc.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/process.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/random.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/range.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/sprintf.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/string.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/struct.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/thread.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/time.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/variable.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/vm.h +enc/trans/cesu_8.$(OBJEXT): internal/interpreter.h +enc/trans/cesu_8.$(OBJEXT): internal/iterator.h +enc/trans/cesu_8.$(OBJEXT): internal/memory.h +enc/trans/cesu_8.$(OBJEXT): internal/method.h +enc/trans/cesu_8.$(OBJEXT): internal/module.h +enc/trans/cesu_8.$(OBJEXT): internal/newobj.h +enc/trans/cesu_8.$(OBJEXT): internal/rgengc.h +enc/trans/cesu_8.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/cesu_8.$(OBJEXT): internal/value.h +enc/trans/cesu_8.$(OBJEXT): internal/value_type.h +enc/trans/cesu_8.$(OBJEXT): internal/variable.h +enc/trans/cesu_8.$(OBJEXT): internal/warning_push.h +enc/trans/cesu_8.$(OBJEXT): internal/xmalloc.h enc/trans/cesu_8.$(OBJEXT): missing.h enc/trans/cesu_8.$(OBJEXT): st.h enc/trans/cesu_8.$(OBJEXT): subst.h @@ -408,10 +2510,157 @@ enc/trans/chinese.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/chinese.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/chinese.$(OBJEXT): assert.h enc/trans/chinese.$(OBJEXT): backward.h +enc/trans/chinese.$(OBJEXT): backward/2/assume.h +enc/trans/chinese.$(OBJEXT): backward/2/attributes.h +enc/trans/chinese.$(OBJEXT): backward/2/bool.h +enc/trans/chinese.$(OBJEXT): backward/2/inttypes.h +enc/trans/chinese.$(OBJEXT): backward/2/limits.h +enc/trans/chinese.$(OBJEXT): backward/2/long_long.h +enc/trans/chinese.$(OBJEXT): backward/2/stdalign.h +enc/trans/chinese.$(OBJEXT): backward/2/stdarg.h enc/trans/chinese.$(OBJEXT): config.h enc/trans/chinese.$(OBJEXT): defines.h enc/trans/chinese.$(OBJEXT): enc/trans/chinese.c enc/trans/chinese.$(OBJEXT): intern.h +enc/trans/chinese.$(OBJEXT): internal/anyargs.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/char.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/double.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/int.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/long.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/short.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/chinese.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/chinese.$(OBJEXT): internal/assume.h +enc/trans/chinese.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/chinese.$(OBJEXT): internal/attr/artificial.h +enc/trans/chinese.$(OBJEXT): internal/attr/cold.h +enc/trans/chinese.$(OBJEXT): internal/attr/const.h +enc/trans/chinese.$(OBJEXT): internal/attr/constexpr.h +enc/trans/chinese.$(OBJEXT): internal/attr/deprecated.h +enc/trans/chinese.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/chinese.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/chinese.$(OBJEXT): internal/attr/error.h +enc/trans/chinese.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/chinese.$(OBJEXT): internal/attr/forceinline.h +enc/trans/chinese.$(OBJEXT): internal/attr/format.h +enc/trans/chinese.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/chinese.$(OBJEXT): internal/attr/noalias.h +enc/trans/chinese.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/chinese.$(OBJEXT): internal/attr/noexcept.h +enc/trans/chinese.$(OBJEXT): internal/attr/noinline.h +enc/trans/chinese.$(OBJEXT): internal/attr/nonnull.h +enc/trans/chinese.$(OBJEXT): internal/attr/noreturn.h +enc/trans/chinese.$(OBJEXT): internal/attr/pure.h +enc/trans/chinese.$(OBJEXT): internal/attr/restrict.h +enc/trans/chinese.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/chinese.$(OBJEXT): internal/attr/warning.h +enc/trans/chinese.$(OBJEXT): internal/attr/weakref.h +enc/trans/chinese.$(OBJEXT): internal/cast.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/chinese.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/chinese.$(OBJEXT): internal/compiler_since.h +enc/trans/chinese.$(OBJEXT): internal/config.h +enc/trans/chinese.$(OBJEXT): internal/constant_p.h +enc/trans/chinese.$(OBJEXT): internal/core.h +enc/trans/chinese.$(OBJEXT): internal/core/rarray.h +enc/trans/chinese.$(OBJEXT): internal/core/rbasic.h +enc/trans/chinese.$(OBJEXT): internal/core/rbignum.h +enc/trans/chinese.$(OBJEXT): internal/core/rclass.h +enc/trans/chinese.$(OBJEXT): internal/core/rdata.h +enc/trans/chinese.$(OBJEXT): internal/core/rfile.h +enc/trans/chinese.$(OBJEXT): internal/core/rhash.h +enc/trans/chinese.$(OBJEXT): internal/core/robject.h +enc/trans/chinese.$(OBJEXT): internal/core/rregexp.h +enc/trans/chinese.$(OBJEXT): internal/core/rstring.h +enc/trans/chinese.$(OBJEXT): internal/core/rstruct.h +enc/trans/chinese.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/chinese.$(OBJEXT): internal/ctype.h +enc/trans/chinese.$(OBJEXT): internal/dllexport.h +enc/trans/chinese.$(OBJEXT): internal/dosish.h +enc/trans/chinese.$(OBJEXT): internal/error.h +enc/trans/chinese.$(OBJEXT): internal/eval.h +enc/trans/chinese.$(OBJEXT): internal/event.h +enc/trans/chinese.$(OBJEXT): internal/fl_type.h +enc/trans/chinese.$(OBJEXT): internal/gc.h +enc/trans/chinese.$(OBJEXT): internal/glob.h +enc/trans/chinese.$(OBJEXT): internal/globals.h +enc/trans/chinese.$(OBJEXT): internal/has/attribute.h +enc/trans/chinese.$(OBJEXT): internal/has/builtin.h +enc/trans/chinese.$(OBJEXT): internal/has/c_attribute.h +enc/trans/chinese.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/chinese.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/chinese.$(OBJEXT): internal/has/extension.h +enc/trans/chinese.$(OBJEXT): internal/has/feature.h +enc/trans/chinese.$(OBJEXT): internal/has/warning.h +enc/trans/chinese.$(OBJEXT): internal/intern/array.h +enc/trans/chinese.$(OBJEXT): internal/intern/bignum.h +enc/trans/chinese.$(OBJEXT): internal/intern/class.h +enc/trans/chinese.$(OBJEXT): internal/intern/compar.h +enc/trans/chinese.$(OBJEXT): internal/intern/complex.h +enc/trans/chinese.$(OBJEXT): internal/intern/cont.h +enc/trans/chinese.$(OBJEXT): internal/intern/dir.h +enc/trans/chinese.$(OBJEXT): internal/intern/enum.h +enc/trans/chinese.$(OBJEXT): internal/intern/enumerator.h +enc/trans/chinese.$(OBJEXT): internal/intern/error.h +enc/trans/chinese.$(OBJEXT): internal/intern/eval.h +enc/trans/chinese.$(OBJEXT): internal/intern/file.h +enc/trans/chinese.$(OBJEXT): internal/intern/gc.h +enc/trans/chinese.$(OBJEXT): internal/intern/hash.h +enc/trans/chinese.$(OBJEXT): internal/intern/io.h +enc/trans/chinese.$(OBJEXT): internal/intern/load.h +enc/trans/chinese.$(OBJEXT): internal/intern/marshal.h +enc/trans/chinese.$(OBJEXT): internal/intern/numeric.h +enc/trans/chinese.$(OBJEXT): internal/intern/object.h +enc/trans/chinese.$(OBJEXT): internal/intern/parse.h +enc/trans/chinese.$(OBJEXT): internal/intern/proc.h +enc/trans/chinese.$(OBJEXT): internal/intern/process.h +enc/trans/chinese.$(OBJEXT): internal/intern/random.h +enc/trans/chinese.$(OBJEXT): internal/intern/range.h +enc/trans/chinese.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/chinese.$(OBJEXT): internal/intern/sprintf.h +enc/trans/chinese.$(OBJEXT): internal/intern/string.h +enc/trans/chinese.$(OBJEXT): internal/intern/struct.h +enc/trans/chinese.$(OBJEXT): internal/intern/thread.h +enc/trans/chinese.$(OBJEXT): internal/intern/time.h +enc/trans/chinese.$(OBJEXT): internal/intern/variable.h +enc/trans/chinese.$(OBJEXT): internal/intern/vm.h +enc/trans/chinese.$(OBJEXT): internal/interpreter.h +enc/trans/chinese.$(OBJEXT): internal/iterator.h +enc/trans/chinese.$(OBJEXT): internal/memory.h +enc/trans/chinese.$(OBJEXT): internal/method.h +enc/trans/chinese.$(OBJEXT): internal/module.h +enc/trans/chinese.$(OBJEXT): internal/newobj.h +enc/trans/chinese.$(OBJEXT): internal/rgengc.h +enc/trans/chinese.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/chinese.$(OBJEXT): internal/value.h +enc/trans/chinese.$(OBJEXT): internal/value_type.h +enc/trans/chinese.$(OBJEXT): internal/variable.h +enc/trans/chinese.$(OBJEXT): internal/warning_push.h +enc/trans/chinese.$(OBJEXT): internal/xmalloc.h enc/trans/chinese.$(OBJEXT): missing.h enc/trans/chinese.$(OBJEXT): st.h enc/trans/chinese.$(OBJEXT): subst.h @@ -419,10 +2668,157 @@ enc/trans/ebcdic.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/ebcdic.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/ebcdic.$(OBJEXT): assert.h enc/trans/ebcdic.$(OBJEXT): backward.h +enc/trans/ebcdic.$(OBJEXT): backward/2/assume.h +enc/trans/ebcdic.$(OBJEXT): backward/2/attributes.h +enc/trans/ebcdic.$(OBJEXT): backward/2/bool.h +enc/trans/ebcdic.$(OBJEXT): backward/2/inttypes.h +enc/trans/ebcdic.$(OBJEXT): backward/2/limits.h +enc/trans/ebcdic.$(OBJEXT): backward/2/long_long.h +enc/trans/ebcdic.$(OBJEXT): backward/2/stdalign.h +enc/trans/ebcdic.$(OBJEXT): backward/2/stdarg.h enc/trans/ebcdic.$(OBJEXT): config.h enc/trans/ebcdic.$(OBJEXT): defines.h enc/trans/ebcdic.$(OBJEXT): enc/trans/ebcdic.c enc/trans/ebcdic.$(OBJEXT): intern.h +enc/trans/ebcdic.$(OBJEXT): internal/anyargs.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/char.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/double.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/int.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/long.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/short.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/ebcdic.$(OBJEXT): internal/assume.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/artificial.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/cold.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/const.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/constexpr.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/deprecated.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/error.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/forceinline.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/format.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/noalias.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/noexcept.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/noinline.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/nonnull.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/noreturn.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/pure.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/restrict.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/warning.h +enc/trans/ebcdic.$(OBJEXT): internal/attr/weakref.h +enc/trans/ebcdic.$(OBJEXT): internal/cast.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/ebcdic.$(OBJEXT): internal/compiler_since.h +enc/trans/ebcdic.$(OBJEXT): internal/config.h +enc/trans/ebcdic.$(OBJEXT): internal/constant_p.h +enc/trans/ebcdic.$(OBJEXT): internal/core.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rarray.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rbasic.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rbignum.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rclass.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rdata.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rfile.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rhash.h +enc/trans/ebcdic.$(OBJEXT): internal/core/robject.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rregexp.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rstring.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rstruct.h +enc/trans/ebcdic.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/ebcdic.$(OBJEXT): internal/ctype.h +enc/trans/ebcdic.$(OBJEXT): internal/dllexport.h +enc/trans/ebcdic.$(OBJEXT): internal/dosish.h +enc/trans/ebcdic.$(OBJEXT): internal/error.h +enc/trans/ebcdic.$(OBJEXT): internal/eval.h +enc/trans/ebcdic.$(OBJEXT): internal/event.h +enc/trans/ebcdic.$(OBJEXT): internal/fl_type.h +enc/trans/ebcdic.$(OBJEXT): internal/gc.h +enc/trans/ebcdic.$(OBJEXT): internal/glob.h +enc/trans/ebcdic.$(OBJEXT): internal/globals.h +enc/trans/ebcdic.$(OBJEXT): internal/has/attribute.h +enc/trans/ebcdic.$(OBJEXT): internal/has/builtin.h +enc/trans/ebcdic.$(OBJEXT): internal/has/c_attribute.h +enc/trans/ebcdic.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/ebcdic.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/ebcdic.$(OBJEXT): internal/has/extension.h +enc/trans/ebcdic.$(OBJEXT): internal/has/feature.h +enc/trans/ebcdic.$(OBJEXT): internal/has/warning.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/array.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/bignum.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/class.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/compar.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/complex.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/cont.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/dir.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/enum.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/enumerator.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/error.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/eval.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/file.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/gc.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/hash.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/io.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/load.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/marshal.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/numeric.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/object.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/parse.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/proc.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/process.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/random.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/range.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/sprintf.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/string.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/struct.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/thread.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/time.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/variable.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/vm.h +enc/trans/ebcdic.$(OBJEXT): internal/interpreter.h +enc/trans/ebcdic.$(OBJEXT): internal/iterator.h +enc/trans/ebcdic.$(OBJEXT): internal/memory.h +enc/trans/ebcdic.$(OBJEXT): internal/method.h +enc/trans/ebcdic.$(OBJEXT): internal/module.h +enc/trans/ebcdic.$(OBJEXT): internal/newobj.h +enc/trans/ebcdic.$(OBJEXT): internal/rgengc.h +enc/trans/ebcdic.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/ebcdic.$(OBJEXT): internal/value.h +enc/trans/ebcdic.$(OBJEXT): internal/value_type.h +enc/trans/ebcdic.$(OBJEXT): internal/variable.h +enc/trans/ebcdic.$(OBJEXT): internal/warning_push.h +enc/trans/ebcdic.$(OBJEXT): internal/xmalloc.h enc/trans/ebcdic.$(OBJEXT): missing.h enc/trans/ebcdic.$(OBJEXT): st.h enc/trans/ebcdic.$(OBJEXT): subst.h @@ -430,10 +2826,157 @@ enc/trans/emoji.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/emoji.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/emoji.$(OBJEXT): assert.h enc/trans/emoji.$(OBJEXT): backward.h +enc/trans/emoji.$(OBJEXT): backward/2/assume.h +enc/trans/emoji.$(OBJEXT): backward/2/attributes.h +enc/trans/emoji.$(OBJEXT): backward/2/bool.h +enc/trans/emoji.$(OBJEXT): backward/2/inttypes.h +enc/trans/emoji.$(OBJEXT): backward/2/limits.h +enc/trans/emoji.$(OBJEXT): backward/2/long_long.h +enc/trans/emoji.$(OBJEXT): backward/2/stdalign.h +enc/trans/emoji.$(OBJEXT): backward/2/stdarg.h enc/trans/emoji.$(OBJEXT): config.h enc/trans/emoji.$(OBJEXT): defines.h enc/trans/emoji.$(OBJEXT): enc/trans/emoji.c enc/trans/emoji.$(OBJEXT): intern.h +enc/trans/emoji.$(OBJEXT): internal/anyargs.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/char.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/double.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/int.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/long.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/short.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/emoji.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/emoji.$(OBJEXT): internal/assume.h +enc/trans/emoji.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/emoji.$(OBJEXT): internal/attr/artificial.h +enc/trans/emoji.$(OBJEXT): internal/attr/cold.h +enc/trans/emoji.$(OBJEXT): internal/attr/const.h +enc/trans/emoji.$(OBJEXT): internal/attr/constexpr.h +enc/trans/emoji.$(OBJEXT): internal/attr/deprecated.h +enc/trans/emoji.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/emoji.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/emoji.$(OBJEXT): internal/attr/error.h +enc/trans/emoji.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/emoji.$(OBJEXT): internal/attr/forceinline.h +enc/trans/emoji.$(OBJEXT): internal/attr/format.h +enc/trans/emoji.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/emoji.$(OBJEXT): internal/attr/noalias.h +enc/trans/emoji.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/emoji.$(OBJEXT): internal/attr/noexcept.h +enc/trans/emoji.$(OBJEXT): internal/attr/noinline.h +enc/trans/emoji.$(OBJEXT): internal/attr/nonnull.h +enc/trans/emoji.$(OBJEXT): internal/attr/noreturn.h +enc/trans/emoji.$(OBJEXT): internal/attr/pure.h +enc/trans/emoji.$(OBJEXT): internal/attr/restrict.h +enc/trans/emoji.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/emoji.$(OBJEXT): internal/attr/warning.h +enc/trans/emoji.$(OBJEXT): internal/attr/weakref.h +enc/trans/emoji.$(OBJEXT): internal/cast.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/emoji.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/emoji.$(OBJEXT): internal/compiler_since.h +enc/trans/emoji.$(OBJEXT): internal/config.h +enc/trans/emoji.$(OBJEXT): internal/constant_p.h +enc/trans/emoji.$(OBJEXT): internal/core.h +enc/trans/emoji.$(OBJEXT): internal/core/rarray.h +enc/trans/emoji.$(OBJEXT): internal/core/rbasic.h +enc/trans/emoji.$(OBJEXT): internal/core/rbignum.h +enc/trans/emoji.$(OBJEXT): internal/core/rclass.h +enc/trans/emoji.$(OBJEXT): internal/core/rdata.h +enc/trans/emoji.$(OBJEXT): internal/core/rfile.h +enc/trans/emoji.$(OBJEXT): internal/core/rhash.h +enc/trans/emoji.$(OBJEXT): internal/core/robject.h +enc/trans/emoji.$(OBJEXT): internal/core/rregexp.h +enc/trans/emoji.$(OBJEXT): internal/core/rstring.h +enc/trans/emoji.$(OBJEXT): internal/core/rstruct.h +enc/trans/emoji.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/emoji.$(OBJEXT): internal/ctype.h +enc/trans/emoji.$(OBJEXT): internal/dllexport.h +enc/trans/emoji.$(OBJEXT): internal/dosish.h +enc/trans/emoji.$(OBJEXT): internal/error.h +enc/trans/emoji.$(OBJEXT): internal/eval.h +enc/trans/emoji.$(OBJEXT): internal/event.h +enc/trans/emoji.$(OBJEXT): internal/fl_type.h +enc/trans/emoji.$(OBJEXT): internal/gc.h +enc/trans/emoji.$(OBJEXT): internal/glob.h +enc/trans/emoji.$(OBJEXT): internal/globals.h +enc/trans/emoji.$(OBJEXT): internal/has/attribute.h +enc/trans/emoji.$(OBJEXT): internal/has/builtin.h +enc/trans/emoji.$(OBJEXT): internal/has/c_attribute.h +enc/trans/emoji.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/emoji.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/emoji.$(OBJEXT): internal/has/extension.h +enc/trans/emoji.$(OBJEXT): internal/has/feature.h +enc/trans/emoji.$(OBJEXT): internal/has/warning.h +enc/trans/emoji.$(OBJEXT): internal/intern/array.h +enc/trans/emoji.$(OBJEXT): internal/intern/bignum.h +enc/trans/emoji.$(OBJEXT): internal/intern/class.h +enc/trans/emoji.$(OBJEXT): internal/intern/compar.h +enc/trans/emoji.$(OBJEXT): internal/intern/complex.h +enc/trans/emoji.$(OBJEXT): internal/intern/cont.h +enc/trans/emoji.$(OBJEXT): internal/intern/dir.h +enc/trans/emoji.$(OBJEXT): internal/intern/enum.h +enc/trans/emoji.$(OBJEXT): internal/intern/enumerator.h +enc/trans/emoji.$(OBJEXT): internal/intern/error.h +enc/trans/emoji.$(OBJEXT): internal/intern/eval.h +enc/trans/emoji.$(OBJEXT): internal/intern/file.h +enc/trans/emoji.$(OBJEXT): internal/intern/gc.h +enc/trans/emoji.$(OBJEXT): internal/intern/hash.h +enc/trans/emoji.$(OBJEXT): internal/intern/io.h +enc/trans/emoji.$(OBJEXT): internal/intern/load.h +enc/trans/emoji.$(OBJEXT): internal/intern/marshal.h +enc/trans/emoji.$(OBJEXT): internal/intern/numeric.h +enc/trans/emoji.$(OBJEXT): internal/intern/object.h +enc/trans/emoji.$(OBJEXT): internal/intern/parse.h +enc/trans/emoji.$(OBJEXT): internal/intern/proc.h +enc/trans/emoji.$(OBJEXT): internal/intern/process.h +enc/trans/emoji.$(OBJEXT): internal/intern/random.h +enc/trans/emoji.$(OBJEXT): internal/intern/range.h +enc/trans/emoji.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/emoji.$(OBJEXT): internal/intern/sprintf.h +enc/trans/emoji.$(OBJEXT): internal/intern/string.h +enc/trans/emoji.$(OBJEXT): internal/intern/struct.h +enc/trans/emoji.$(OBJEXT): internal/intern/thread.h +enc/trans/emoji.$(OBJEXT): internal/intern/time.h +enc/trans/emoji.$(OBJEXT): internal/intern/variable.h +enc/trans/emoji.$(OBJEXT): internal/intern/vm.h +enc/trans/emoji.$(OBJEXT): internal/interpreter.h +enc/trans/emoji.$(OBJEXT): internal/iterator.h +enc/trans/emoji.$(OBJEXT): internal/memory.h +enc/trans/emoji.$(OBJEXT): internal/method.h +enc/trans/emoji.$(OBJEXT): internal/module.h +enc/trans/emoji.$(OBJEXT): internal/newobj.h +enc/trans/emoji.$(OBJEXT): internal/rgengc.h +enc/trans/emoji.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/emoji.$(OBJEXT): internal/value.h +enc/trans/emoji.$(OBJEXT): internal/value_type.h +enc/trans/emoji.$(OBJEXT): internal/variable.h +enc/trans/emoji.$(OBJEXT): internal/warning_push.h +enc/trans/emoji.$(OBJEXT): internal/xmalloc.h enc/trans/emoji.$(OBJEXT): missing.h enc/trans/emoji.$(OBJEXT): st.h enc/trans/emoji.$(OBJEXT): subst.h @@ -441,10 +2984,157 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): assert.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/assume.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/attributes.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/bool.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/inttypes.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/limits.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/long_long.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdalign.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdarg.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): config.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): defines.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): enc/trans/emoji_iso2022_kddi.c enc/trans/emoji_iso2022_kddi.$(OBJEXT): intern.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/anyargs.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/char.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/double.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/int.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/long.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/short.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/assume.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/artificial.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/cold.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/const.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/constexpr.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/deprecated.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/error.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/forceinline.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/format.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noalias.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noexcept.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noinline.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/nonnull.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noreturn.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/pure.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/restrict.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/warning.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/weakref.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/cast.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_since.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/config.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/constant_p.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rarray.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rbasic.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rbignum.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rclass.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rdata.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rfile.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rhash.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/robject.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rregexp.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rstring.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rstruct.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/ctype.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/dllexport.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/dosish.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/error.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/eval.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/event.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/fl_type.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/gc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/glob.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/globals.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/attribute.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/builtin.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/c_attribute.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/extension.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/feature.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/warning.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/array.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/bignum.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/class.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/compar.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/complex.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/cont.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/dir.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/enum.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/enumerator.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/error.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/eval.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/file.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/gc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/hash.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/io.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/load.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/marshal.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/numeric.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/object.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/parse.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/proc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/process.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/random.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/range.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/sprintf.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/string.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/struct.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/thread.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/time.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/variable.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/vm.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/interpreter.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/iterator.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/memory.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/method.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/module.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/newobj.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/rgengc.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value_type.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/variable.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/warning_push.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): missing.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): st.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): subst.h @@ -452,10 +3142,157 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/emoji_sjis_docomo.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/emoji_sjis_docomo.$(OBJEXT): assert.h enc/trans/emoji_sjis_docomo.$(OBJEXT): backward.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/assume.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/attributes.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/bool.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/inttypes.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/limits.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/long_long.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdalign.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdarg.h enc/trans/emoji_sjis_docomo.$(OBJEXT): config.h enc/trans/emoji_sjis_docomo.$(OBJEXT): defines.h enc/trans/emoji_sjis_docomo.$(OBJEXT): enc/trans/emoji_sjis_docomo.c enc/trans/emoji_sjis_docomo.$(OBJEXT): intern.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/anyargs.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/char.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/double.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/int.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/long.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/short.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/assume.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/artificial.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/cold.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/const.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/constexpr.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/deprecated.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/error.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/forceinline.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/format.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noalias.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noexcept.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noinline.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/nonnull.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noreturn.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/pure.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/restrict.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/warning.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/weakref.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/cast.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_since.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/config.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/constant_p.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rarray.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rbasic.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rbignum.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rclass.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rdata.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rfile.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rhash.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/robject.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rregexp.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rstring.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rstruct.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/ctype.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/dllexport.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/dosish.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/error.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/eval.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/event.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/fl_type.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/gc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/glob.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/globals.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/attribute.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/builtin.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/c_attribute.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/extension.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/feature.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/warning.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/array.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/bignum.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/class.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/compar.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/complex.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/cont.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/dir.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/enum.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/enumerator.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/error.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/eval.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/file.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/gc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/hash.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/io.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/load.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/marshal.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/numeric.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/object.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/parse.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/proc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/process.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/random.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/range.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/sprintf.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/string.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/struct.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/thread.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/time.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/variable.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/vm.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/interpreter.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/iterator.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/memory.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/method.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/module.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/newobj.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/rgengc.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value_type.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/variable.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/warning_push.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_docomo.$(OBJEXT): missing.h enc/trans/emoji_sjis_docomo.$(OBJEXT): st.h enc/trans/emoji_sjis_docomo.$(OBJEXT): subst.h @@ -463,10 +3300,157 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/emoji_sjis_kddi.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/emoji_sjis_kddi.$(OBJEXT): assert.h enc/trans/emoji_sjis_kddi.$(OBJEXT): backward.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/assume.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/attributes.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/bool.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/inttypes.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/limits.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/long_long.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdalign.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdarg.h enc/trans/emoji_sjis_kddi.$(OBJEXT): config.h enc/trans/emoji_sjis_kddi.$(OBJEXT): defines.h enc/trans/emoji_sjis_kddi.$(OBJEXT): enc/trans/emoji_sjis_kddi.c enc/trans/emoji_sjis_kddi.$(OBJEXT): intern.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/anyargs.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/char.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/double.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/int.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/long.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/short.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/assume.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/artificial.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/cold.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/const.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/constexpr.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/deprecated.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/error.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/forceinline.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/format.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noalias.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noexcept.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noinline.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/nonnull.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noreturn.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/pure.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/restrict.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/warning.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/weakref.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/cast.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_since.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/config.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/constant_p.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rarray.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rbasic.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rbignum.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rclass.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rdata.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rfile.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rhash.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/robject.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rregexp.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rstring.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rstruct.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/ctype.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/dllexport.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/dosish.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/error.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/eval.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/event.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/fl_type.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/gc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/glob.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/globals.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/attribute.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/builtin.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/c_attribute.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/extension.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/feature.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/warning.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/array.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/bignum.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/class.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/compar.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/complex.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/cont.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/dir.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/enum.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/enumerator.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/error.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/eval.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/file.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/gc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/hash.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/io.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/load.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/marshal.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/numeric.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/object.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/parse.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/proc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/process.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/random.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/range.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/sprintf.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/string.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/struct.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/thread.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/time.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/variable.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/vm.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/interpreter.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/iterator.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/memory.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/method.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/module.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/newobj.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/rgengc.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value_type.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/variable.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/warning_push.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_kddi.$(OBJEXT): missing.h enc/trans/emoji_sjis_kddi.$(OBJEXT): st.h enc/trans/emoji_sjis_kddi.$(OBJEXT): subst.h @@ -474,10 +3458,157 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/emoji_sjis_softbank.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/emoji_sjis_softbank.$(OBJEXT): assert.h enc/trans/emoji_sjis_softbank.$(OBJEXT): backward.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/assume.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/attributes.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/bool.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/inttypes.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/limits.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/long_long.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdalign.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdarg.h enc/trans/emoji_sjis_softbank.$(OBJEXT): config.h enc/trans/emoji_sjis_softbank.$(OBJEXT): defines.h enc/trans/emoji_sjis_softbank.$(OBJEXT): enc/trans/emoji_sjis_softbank.c enc/trans/emoji_sjis_softbank.$(OBJEXT): intern.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/anyargs.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/char.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/double.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/int.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/long.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/short.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/assume.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/artificial.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/cold.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/const.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/constexpr.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/deprecated.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/error.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/forceinline.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/format.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noalias.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noexcept.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noinline.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/nonnull.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noreturn.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/pure.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/restrict.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/warning.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/weakref.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/cast.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_since.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/config.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/constant_p.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rarray.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rbasic.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rbignum.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rclass.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rdata.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rfile.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rhash.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/robject.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rregexp.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rstring.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rstruct.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/ctype.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/dllexport.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/dosish.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/error.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/eval.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/event.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/fl_type.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/gc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/glob.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/globals.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/attribute.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/builtin.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/c_attribute.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/extension.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/feature.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/warning.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/array.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/bignum.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/class.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/compar.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/complex.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/cont.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/dir.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/enum.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/enumerator.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/error.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/eval.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/file.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/gc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/hash.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/io.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/load.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/marshal.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/numeric.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/object.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/parse.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/proc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/process.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/random.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/range.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/sprintf.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/string.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/struct.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/thread.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/time.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/variable.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/vm.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/interpreter.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/iterator.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/memory.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/method.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/module.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/newobj.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/rgengc.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value_type.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/variable.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/warning_push.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_softbank.$(OBJEXT): missing.h enc/trans/emoji_sjis_softbank.$(OBJEXT): st.h enc/trans/emoji_sjis_softbank.$(OBJEXT): subst.h @@ -485,10 +3616,157 @@ enc/trans/escape.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/escape.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/escape.$(OBJEXT): assert.h enc/trans/escape.$(OBJEXT): backward.h +enc/trans/escape.$(OBJEXT): backward/2/assume.h +enc/trans/escape.$(OBJEXT): backward/2/attributes.h +enc/trans/escape.$(OBJEXT): backward/2/bool.h +enc/trans/escape.$(OBJEXT): backward/2/inttypes.h +enc/trans/escape.$(OBJEXT): backward/2/limits.h +enc/trans/escape.$(OBJEXT): backward/2/long_long.h +enc/trans/escape.$(OBJEXT): backward/2/stdalign.h +enc/trans/escape.$(OBJEXT): backward/2/stdarg.h enc/trans/escape.$(OBJEXT): config.h enc/trans/escape.$(OBJEXT): defines.h enc/trans/escape.$(OBJEXT): enc/trans/escape.c enc/trans/escape.$(OBJEXT): intern.h +enc/trans/escape.$(OBJEXT): internal/anyargs.h +enc/trans/escape.$(OBJEXT): internal/arithmetic.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/char.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/double.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/int.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/long.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/short.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/escape.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/escape.$(OBJEXT): internal/assume.h +enc/trans/escape.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/escape.$(OBJEXT): internal/attr/artificial.h +enc/trans/escape.$(OBJEXT): internal/attr/cold.h +enc/trans/escape.$(OBJEXT): internal/attr/const.h +enc/trans/escape.$(OBJEXT): internal/attr/constexpr.h +enc/trans/escape.$(OBJEXT): internal/attr/deprecated.h +enc/trans/escape.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/escape.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/escape.$(OBJEXT): internal/attr/error.h +enc/trans/escape.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/escape.$(OBJEXT): internal/attr/forceinline.h +enc/trans/escape.$(OBJEXT): internal/attr/format.h +enc/trans/escape.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/escape.$(OBJEXT): internal/attr/noalias.h +enc/trans/escape.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/escape.$(OBJEXT): internal/attr/noexcept.h +enc/trans/escape.$(OBJEXT): internal/attr/noinline.h +enc/trans/escape.$(OBJEXT): internal/attr/nonnull.h +enc/trans/escape.$(OBJEXT): internal/attr/noreturn.h +enc/trans/escape.$(OBJEXT): internal/attr/pure.h +enc/trans/escape.$(OBJEXT): internal/attr/restrict.h +enc/trans/escape.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/escape.$(OBJEXT): internal/attr/warning.h +enc/trans/escape.$(OBJEXT): internal/attr/weakref.h +enc/trans/escape.$(OBJEXT): internal/cast.h +enc/trans/escape.$(OBJEXT): internal/compiler_is.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/escape.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/escape.$(OBJEXT): internal/compiler_since.h +enc/trans/escape.$(OBJEXT): internal/config.h +enc/trans/escape.$(OBJEXT): internal/constant_p.h +enc/trans/escape.$(OBJEXT): internal/core.h +enc/trans/escape.$(OBJEXT): internal/core/rarray.h +enc/trans/escape.$(OBJEXT): internal/core/rbasic.h +enc/trans/escape.$(OBJEXT): internal/core/rbignum.h +enc/trans/escape.$(OBJEXT): internal/core/rclass.h +enc/trans/escape.$(OBJEXT): internal/core/rdata.h +enc/trans/escape.$(OBJEXT): internal/core/rfile.h +enc/trans/escape.$(OBJEXT): internal/core/rhash.h +enc/trans/escape.$(OBJEXT): internal/core/robject.h +enc/trans/escape.$(OBJEXT): internal/core/rregexp.h +enc/trans/escape.$(OBJEXT): internal/core/rstring.h +enc/trans/escape.$(OBJEXT): internal/core/rstruct.h +enc/trans/escape.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/escape.$(OBJEXT): internal/ctype.h +enc/trans/escape.$(OBJEXT): internal/dllexport.h +enc/trans/escape.$(OBJEXT): internal/dosish.h +enc/trans/escape.$(OBJEXT): internal/error.h +enc/trans/escape.$(OBJEXT): internal/eval.h +enc/trans/escape.$(OBJEXT): internal/event.h +enc/trans/escape.$(OBJEXT): internal/fl_type.h +enc/trans/escape.$(OBJEXT): internal/gc.h +enc/trans/escape.$(OBJEXT): internal/glob.h +enc/trans/escape.$(OBJEXT): internal/globals.h +enc/trans/escape.$(OBJEXT): internal/has/attribute.h +enc/trans/escape.$(OBJEXT): internal/has/builtin.h +enc/trans/escape.$(OBJEXT): internal/has/c_attribute.h +enc/trans/escape.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/escape.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/escape.$(OBJEXT): internal/has/extension.h +enc/trans/escape.$(OBJEXT): internal/has/feature.h +enc/trans/escape.$(OBJEXT): internal/has/warning.h +enc/trans/escape.$(OBJEXT): internal/intern/array.h +enc/trans/escape.$(OBJEXT): internal/intern/bignum.h +enc/trans/escape.$(OBJEXT): internal/intern/class.h +enc/trans/escape.$(OBJEXT): internal/intern/compar.h +enc/trans/escape.$(OBJEXT): internal/intern/complex.h +enc/trans/escape.$(OBJEXT): internal/intern/cont.h +enc/trans/escape.$(OBJEXT): internal/intern/dir.h +enc/trans/escape.$(OBJEXT): internal/intern/enum.h +enc/trans/escape.$(OBJEXT): internal/intern/enumerator.h +enc/trans/escape.$(OBJEXT): internal/intern/error.h +enc/trans/escape.$(OBJEXT): internal/intern/eval.h +enc/trans/escape.$(OBJEXT): internal/intern/file.h +enc/trans/escape.$(OBJEXT): internal/intern/gc.h +enc/trans/escape.$(OBJEXT): internal/intern/hash.h +enc/trans/escape.$(OBJEXT): internal/intern/io.h +enc/trans/escape.$(OBJEXT): internal/intern/load.h +enc/trans/escape.$(OBJEXT): internal/intern/marshal.h +enc/trans/escape.$(OBJEXT): internal/intern/numeric.h +enc/trans/escape.$(OBJEXT): internal/intern/object.h +enc/trans/escape.$(OBJEXT): internal/intern/parse.h +enc/trans/escape.$(OBJEXT): internal/intern/proc.h +enc/trans/escape.$(OBJEXT): internal/intern/process.h +enc/trans/escape.$(OBJEXT): internal/intern/random.h +enc/trans/escape.$(OBJEXT): internal/intern/range.h +enc/trans/escape.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/escape.$(OBJEXT): internal/intern/sprintf.h +enc/trans/escape.$(OBJEXT): internal/intern/string.h +enc/trans/escape.$(OBJEXT): internal/intern/struct.h +enc/trans/escape.$(OBJEXT): internal/intern/thread.h +enc/trans/escape.$(OBJEXT): internal/intern/time.h +enc/trans/escape.$(OBJEXT): internal/intern/variable.h +enc/trans/escape.$(OBJEXT): internal/intern/vm.h +enc/trans/escape.$(OBJEXT): internal/interpreter.h +enc/trans/escape.$(OBJEXT): internal/iterator.h +enc/trans/escape.$(OBJEXT): internal/memory.h +enc/trans/escape.$(OBJEXT): internal/method.h +enc/trans/escape.$(OBJEXT): internal/module.h +enc/trans/escape.$(OBJEXT): internal/newobj.h +enc/trans/escape.$(OBJEXT): internal/rgengc.h +enc/trans/escape.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/escape.$(OBJEXT): internal/value.h +enc/trans/escape.$(OBJEXT): internal/value_type.h +enc/trans/escape.$(OBJEXT): internal/variable.h +enc/trans/escape.$(OBJEXT): internal/warning_push.h +enc/trans/escape.$(OBJEXT): internal/xmalloc.h enc/trans/escape.$(OBJEXT): missing.h enc/trans/escape.$(OBJEXT): st.h enc/trans/escape.$(OBJEXT): subst.h @@ -496,10 +3774,157 @@ enc/trans/gb18030.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/gb18030.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/gb18030.$(OBJEXT): assert.h enc/trans/gb18030.$(OBJEXT): backward.h +enc/trans/gb18030.$(OBJEXT): backward/2/assume.h +enc/trans/gb18030.$(OBJEXT): backward/2/attributes.h +enc/trans/gb18030.$(OBJEXT): backward/2/bool.h +enc/trans/gb18030.$(OBJEXT): backward/2/inttypes.h +enc/trans/gb18030.$(OBJEXT): backward/2/limits.h +enc/trans/gb18030.$(OBJEXT): backward/2/long_long.h +enc/trans/gb18030.$(OBJEXT): backward/2/stdalign.h +enc/trans/gb18030.$(OBJEXT): backward/2/stdarg.h enc/trans/gb18030.$(OBJEXT): config.h enc/trans/gb18030.$(OBJEXT): defines.h enc/trans/gb18030.$(OBJEXT): enc/trans/gb18030.c enc/trans/gb18030.$(OBJEXT): intern.h +enc/trans/gb18030.$(OBJEXT): internal/anyargs.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/char.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/double.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/int.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/long.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/short.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/gb18030.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/gb18030.$(OBJEXT): internal/assume.h +enc/trans/gb18030.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/gb18030.$(OBJEXT): internal/attr/artificial.h +enc/trans/gb18030.$(OBJEXT): internal/attr/cold.h +enc/trans/gb18030.$(OBJEXT): internal/attr/const.h +enc/trans/gb18030.$(OBJEXT): internal/attr/constexpr.h +enc/trans/gb18030.$(OBJEXT): internal/attr/deprecated.h +enc/trans/gb18030.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/gb18030.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/gb18030.$(OBJEXT): internal/attr/error.h +enc/trans/gb18030.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/gb18030.$(OBJEXT): internal/attr/forceinline.h +enc/trans/gb18030.$(OBJEXT): internal/attr/format.h +enc/trans/gb18030.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/gb18030.$(OBJEXT): internal/attr/noalias.h +enc/trans/gb18030.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/gb18030.$(OBJEXT): internal/attr/noexcept.h +enc/trans/gb18030.$(OBJEXT): internal/attr/noinline.h +enc/trans/gb18030.$(OBJEXT): internal/attr/nonnull.h +enc/trans/gb18030.$(OBJEXT): internal/attr/noreturn.h +enc/trans/gb18030.$(OBJEXT): internal/attr/pure.h +enc/trans/gb18030.$(OBJEXT): internal/attr/restrict.h +enc/trans/gb18030.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/gb18030.$(OBJEXT): internal/attr/warning.h +enc/trans/gb18030.$(OBJEXT): internal/attr/weakref.h +enc/trans/gb18030.$(OBJEXT): internal/cast.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/gb18030.$(OBJEXT): internal/compiler_since.h +enc/trans/gb18030.$(OBJEXT): internal/config.h +enc/trans/gb18030.$(OBJEXT): internal/constant_p.h +enc/trans/gb18030.$(OBJEXT): internal/core.h +enc/trans/gb18030.$(OBJEXT): internal/core/rarray.h +enc/trans/gb18030.$(OBJEXT): internal/core/rbasic.h +enc/trans/gb18030.$(OBJEXT): internal/core/rbignum.h +enc/trans/gb18030.$(OBJEXT): internal/core/rclass.h +enc/trans/gb18030.$(OBJEXT): internal/core/rdata.h +enc/trans/gb18030.$(OBJEXT): internal/core/rfile.h +enc/trans/gb18030.$(OBJEXT): internal/core/rhash.h +enc/trans/gb18030.$(OBJEXT): internal/core/robject.h +enc/trans/gb18030.$(OBJEXT): internal/core/rregexp.h +enc/trans/gb18030.$(OBJEXT): internal/core/rstring.h +enc/trans/gb18030.$(OBJEXT): internal/core/rstruct.h +enc/trans/gb18030.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/gb18030.$(OBJEXT): internal/ctype.h +enc/trans/gb18030.$(OBJEXT): internal/dllexport.h +enc/trans/gb18030.$(OBJEXT): internal/dosish.h +enc/trans/gb18030.$(OBJEXT): internal/error.h +enc/trans/gb18030.$(OBJEXT): internal/eval.h +enc/trans/gb18030.$(OBJEXT): internal/event.h +enc/trans/gb18030.$(OBJEXT): internal/fl_type.h +enc/trans/gb18030.$(OBJEXT): internal/gc.h +enc/trans/gb18030.$(OBJEXT): internal/glob.h +enc/trans/gb18030.$(OBJEXT): internal/globals.h +enc/trans/gb18030.$(OBJEXT): internal/has/attribute.h +enc/trans/gb18030.$(OBJEXT): internal/has/builtin.h +enc/trans/gb18030.$(OBJEXT): internal/has/c_attribute.h +enc/trans/gb18030.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/gb18030.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/gb18030.$(OBJEXT): internal/has/extension.h +enc/trans/gb18030.$(OBJEXT): internal/has/feature.h +enc/trans/gb18030.$(OBJEXT): internal/has/warning.h +enc/trans/gb18030.$(OBJEXT): internal/intern/array.h +enc/trans/gb18030.$(OBJEXT): internal/intern/bignum.h +enc/trans/gb18030.$(OBJEXT): internal/intern/class.h +enc/trans/gb18030.$(OBJEXT): internal/intern/compar.h +enc/trans/gb18030.$(OBJEXT): internal/intern/complex.h +enc/trans/gb18030.$(OBJEXT): internal/intern/cont.h +enc/trans/gb18030.$(OBJEXT): internal/intern/dir.h +enc/trans/gb18030.$(OBJEXT): internal/intern/enum.h +enc/trans/gb18030.$(OBJEXT): internal/intern/enumerator.h +enc/trans/gb18030.$(OBJEXT): internal/intern/error.h +enc/trans/gb18030.$(OBJEXT): internal/intern/eval.h +enc/trans/gb18030.$(OBJEXT): internal/intern/file.h +enc/trans/gb18030.$(OBJEXT): internal/intern/gc.h +enc/trans/gb18030.$(OBJEXT): internal/intern/hash.h +enc/trans/gb18030.$(OBJEXT): internal/intern/io.h +enc/trans/gb18030.$(OBJEXT): internal/intern/load.h +enc/trans/gb18030.$(OBJEXT): internal/intern/marshal.h +enc/trans/gb18030.$(OBJEXT): internal/intern/numeric.h +enc/trans/gb18030.$(OBJEXT): internal/intern/object.h +enc/trans/gb18030.$(OBJEXT): internal/intern/parse.h +enc/trans/gb18030.$(OBJEXT): internal/intern/proc.h +enc/trans/gb18030.$(OBJEXT): internal/intern/process.h +enc/trans/gb18030.$(OBJEXT): internal/intern/random.h +enc/trans/gb18030.$(OBJEXT): internal/intern/range.h +enc/trans/gb18030.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/gb18030.$(OBJEXT): internal/intern/sprintf.h +enc/trans/gb18030.$(OBJEXT): internal/intern/string.h +enc/trans/gb18030.$(OBJEXT): internal/intern/struct.h +enc/trans/gb18030.$(OBJEXT): internal/intern/thread.h +enc/trans/gb18030.$(OBJEXT): internal/intern/time.h +enc/trans/gb18030.$(OBJEXT): internal/intern/variable.h +enc/trans/gb18030.$(OBJEXT): internal/intern/vm.h +enc/trans/gb18030.$(OBJEXT): internal/interpreter.h +enc/trans/gb18030.$(OBJEXT): internal/iterator.h +enc/trans/gb18030.$(OBJEXT): internal/memory.h +enc/trans/gb18030.$(OBJEXT): internal/method.h +enc/trans/gb18030.$(OBJEXT): internal/module.h +enc/trans/gb18030.$(OBJEXT): internal/newobj.h +enc/trans/gb18030.$(OBJEXT): internal/rgengc.h +enc/trans/gb18030.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/gb18030.$(OBJEXT): internal/value.h +enc/trans/gb18030.$(OBJEXT): internal/value_type.h +enc/trans/gb18030.$(OBJEXT): internal/variable.h +enc/trans/gb18030.$(OBJEXT): internal/warning_push.h +enc/trans/gb18030.$(OBJEXT): internal/xmalloc.h enc/trans/gb18030.$(OBJEXT): missing.h enc/trans/gb18030.$(OBJEXT): st.h enc/trans/gb18030.$(OBJEXT): subst.h @@ -507,10 +3932,157 @@ enc/trans/gbk.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/gbk.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/gbk.$(OBJEXT): assert.h enc/trans/gbk.$(OBJEXT): backward.h +enc/trans/gbk.$(OBJEXT): backward/2/assume.h +enc/trans/gbk.$(OBJEXT): backward/2/attributes.h +enc/trans/gbk.$(OBJEXT): backward/2/bool.h +enc/trans/gbk.$(OBJEXT): backward/2/inttypes.h +enc/trans/gbk.$(OBJEXT): backward/2/limits.h +enc/trans/gbk.$(OBJEXT): backward/2/long_long.h +enc/trans/gbk.$(OBJEXT): backward/2/stdalign.h +enc/trans/gbk.$(OBJEXT): backward/2/stdarg.h enc/trans/gbk.$(OBJEXT): config.h enc/trans/gbk.$(OBJEXT): defines.h enc/trans/gbk.$(OBJEXT): enc/trans/gbk.c enc/trans/gbk.$(OBJEXT): intern.h +enc/trans/gbk.$(OBJEXT): internal/anyargs.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/char.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/double.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/int.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/long.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/short.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/gbk.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/gbk.$(OBJEXT): internal/assume.h +enc/trans/gbk.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/gbk.$(OBJEXT): internal/attr/artificial.h +enc/trans/gbk.$(OBJEXT): internal/attr/cold.h +enc/trans/gbk.$(OBJEXT): internal/attr/const.h +enc/trans/gbk.$(OBJEXT): internal/attr/constexpr.h +enc/trans/gbk.$(OBJEXT): internal/attr/deprecated.h +enc/trans/gbk.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/gbk.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/gbk.$(OBJEXT): internal/attr/error.h +enc/trans/gbk.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/gbk.$(OBJEXT): internal/attr/forceinline.h +enc/trans/gbk.$(OBJEXT): internal/attr/format.h +enc/trans/gbk.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/gbk.$(OBJEXT): internal/attr/noalias.h +enc/trans/gbk.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/gbk.$(OBJEXT): internal/attr/noexcept.h +enc/trans/gbk.$(OBJEXT): internal/attr/noinline.h +enc/trans/gbk.$(OBJEXT): internal/attr/nonnull.h +enc/trans/gbk.$(OBJEXT): internal/attr/noreturn.h +enc/trans/gbk.$(OBJEXT): internal/attr/pure.h +enc/trans/gbk.$(OBJEXT): internal/attr/restrict.h +enc/trans/gbk.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/gbk.$(OBJEXT): internal/attr/warning.h +enc/trans/gbk.$(OBJEXT): internal/attr/weakref.h +enc/trans/gbk.$(OBJEXT): internal/cast.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/gbk.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/gbk.$(OBJEXT): internal/compiler_since.h +enc/trans/gbk.$(OBJEXT): internal/config.h +enc/trans/gbk.$(OBJEXT): internal/constant_p.h +enc/trans/gbk.$(OBJEXT): internal/core.h +enc/trans/gbk.$(OBJEXT): internal/core/rarray.h +enc/trans/gbk.$(OBJEXT): internal/core/rbasic.h +enc/trans/gbk.$(OBJEXT): internal/core/rbignum.h +enc/trans/gbk.$(OBJEXT): internal/core/rclass.h +enc/trans/gbk.$(OBJEXT): internal/core/rdata.h +enc/trans/gbk.$(OBJEXT): internal/core/rfile.h +enc/trans/gbk.$(OBJEXT): internal/core/rhash.h +enc/trans/gbk.$(OBJEXT): internal/core/robject.h +enc/trans/gbk.$(OBJEXT): internal/core/rregexp.h +enc/trans/gbk.$(OBJEXT): internal/core/rstring.h +enc/trans/gbk.$(OBJEXT): internal/core/rstruct.h +enc/trans/gbk.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/gbk.$(OBJEXT): internal/ctype.h +enc/trans/gbk.$(OBJEXT): internal/dllexport.h +enc/trans/gbk.$(OBJEXT): internal/dosish.h +enc/trans/gbk.$(OBJEXT): internal/error.h +enc/trans/gbk.$(OBJEXT): internal/eval.h +enc/trans/gbk.$(OBJEXT): internal/event.h +enc/trans/gbk.$(OBJEXT): internal/fl_type.h +enc/trans/gbk.$(OBJEXT): internal/gc.h +enc/trans/gbk.$(OBJEXT): internal/glob.h +enc/trans/gbk.$(OBJEXT): internal/globals.h +enc/trans/gbk.$(OBJEXT): internal/has/attribute.h +enc/trans/gbk.$(OBJEXT): internal/has/builtin.h +enc/trans/gbk.$(OBJEXT): internal/has/c_attribute.h +enc/trans/gbk.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/gbk.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/gbk.$(OBJEXT): internal/has/extension.h +enc/trans/gbk.$(OBJEXT): internal/has/feature.h +enc/trans/gbk.$(OBJEXT): internal/has/warning.h +enc/trans/gbk.$(OBJEXT): internal/intern/array.h +enc/trans/gbk.$(OBJEXT): internal/intern/bignum.h +enc/trans/gbk.$(OBJEXT): internal/intern/class.h +enc/trans/gbk.$(OBJEXT): internal/intern/compar.h +enc/trans/gbk.$(OBJEXT): internal/intern/complex.h +enc/trans/gbk.$(OBJEXT): internal/intern/cont.h +enc/trans/gbk.$(OBJEXT): internal/intern/dir.h +enc/trans/gbk.$(OBJEXT): internal/intern/enum.h +enc/trans/gbk.$(OBJEXT): internal/intern/enumerator.h +enc/trans/gbk.$(OBJEXT): internal/intern/error.h +enc/trans/gbk.$(OBJEXT): internal/intern/eval.h +enc/trans/gbk.$(OBJEXT): internal/intern/file.h +enc/trans/gbk.$(OBJEXT): internal/intern/gc.h +enc/trans/gbk.$(OBJEXT): internal/intern/hash.h +enc/trans/gbk.$(OBJEXT): internal/intern/io.h +enc/trans/gbk.$(OBJEXT): internal/intern/load.h +enc/trans/gbk.$(OBJEXT): internal/intern/marshal.h +enc/trans/gbk.$(OBJEXT): internal/intern/numeric.h +enc/trans/gbk.$(OBJEXT): internal/intern/object.h +enc/trans/gbk.$(OBJEXT): internal/intern/parse.h +enc/trans/gbk.$(OBJEXT): internal/intern/proc.h +enc/trans/gbk.$(OBJEXT): internal/intern/process.h +enc/trans/gbk.$(OBJEXT): internal/intern/random.h +enc/trans/gbk.$(OBJEXT): internal/intern/range.h +enc/trans/gbk.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/gbk.$(OBJEXT): internal/intern/sprintf.h +enc/trans/gbk.$(OBJEXT): internal/intern/string.h +enc/trans/gbk.$(OBJEXT): internal/intern/struct.h +enc/trans/gbk.$(OBJEXT): internal/intern/thread.h +enc/trans/gbk.$(OBJEXT): internal/intern/time.h +enc/trans/gbk.$(OBJEXT): internal/intern/variable.h +enc/trans/gbk.$(OBJEXT): internal/intern/vm.h +enc/trans/gbk.$(OBJEXT): internal/interpreter.h +enc/trans/gbk.$(OBJEXT): internal/iterator.h +enc/trans/gbk.$(OBJEXT): internal/memory.h +enc/trans/gbk.$(OBJEXT): internal/method.h +enc/trans/gbk.$(OBJEXT): internal/module.h +enc/trans/gbk.$(OBJEXT): internal/newobj.h +enc/trans/gbk.$(OBJEXT): internal/rgengc.h +enc/trans/gbk.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/gbk.$(OBJEXT): internal/value.h +enc/trans/gbk.$(OBJEXT): internal/value_type.h +enc/trans/gbk.$(OBJEXT): internal/variable.h +enc/trans/gbk.$(OBJEXT): internal/warning_push.h +enc/trans/gbk.$(OBJEXT): internal/xmalloc.h enc/trans/gbk.$(OBJEXT): missing.h enc/trans/gbk.$(OBJEXT): st.h enc/trans/gbk.$(OBJEXT): subst.h @@ -518,10 +4090,157 @@ enc/trans/iso2022.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/iso2022.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/iso2022.$(OBJEXT): assert.h enc/trans/iso2022.$(OBJEXT): backward.h +enc/trans/iso2022.$(OBJEXT): backward/2/assume.h +enc/trans/iso2022.$(OBJEXT): backward/2/attributes.h +enc/trans/iso2022.$(OBJEXT): backward/2/bool.h +enc/trans/iso2022.$(OBJEXT): backward/2/inttypes.h +enc/trans/iso2022.$(OBJEXT): backward/2/limits.h +enc/trans/iso2022.$(OBJEXT): backward/2/long_long.h +enc/trans/iso2022.$(OBJEXT): backward/2/stdalign.h +enc/trans/iso2022.$(OBJEXT): backward/2/stdarg.h enc/trans/iso2022.$(OBJEXT): config.h enc/trans/iso2022.$(OBJEXT): defines.h enc/trans/iso2022.$(OBJEXT): enc/trans/iso2022.c enc/trans/iso2022.$(OBJEXT): intern.h +enc/trans/iso2022.$(OBJEXT): internal/anyargs.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/char.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/double.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/int.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/long.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/short.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/iso2022.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/iso2022.$(OBJEXT): internal/assume.h +enc/trans/iso2022.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/iso2022.$(OBJEXT): internal/attr/artificial.h +enc/trans/iso2022.$(OBJEXT): internal/attr/cold.h +enc/trans/iso2022.$(OBJEXT): internal/attr/const.h +enc/trans/iso2022.$(OBJEXT): internal/attr/constexpr.h +enc/trans/iso2022.$(OBJEXT): internal/attr/deprecated.h +enc/trans/iso2022.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/iso2022.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/iso2022.$(OBJEXT): internal/attr/error.h +enc/trans/iso2022.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/iso2022.$(OBJEXT): internal/attr/forceinline.h +enc/trans/iso2022.$(OBJEXT): internal/attr/format.h +enc/trans/iso2022.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/iso2022.$(OBJEXT): internal/attr/noalias.h +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/noreturn.h +enc/trans/iso2022.$(OBJEXT): internal/attr/pure.h +enc/trans/iso2022.$(OBJEXT): internal/attr/restrict.h +enc/trans/iso2022.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/iso2022.$(OBJEXT): internal/attr/warning.h +enc/trans/iso2022.$(OBJEXT): internal/attr/weakref.h +enc/trans/iso2022.$(OBJEXT): internal/cast.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/iso2022.$(OBJEXT): internal/compiler_since.h +enc/trans/iso2022.$(OBJEXT): internal/config.h +enc/trans/iso2022.$(OBJEXT): internal/constant_p.h +enc/trans/iso2022.$(OBJEXT): internal/core.h +enc/trans/iso2022.$(OBJEXT): internal/core/rarray.h +enc/trans/iso2022.$(OBJEXT): internal/core/rbasic.h +enc/trans/iso2022.$(OBJEXT): internal/core/rbignum.h +enc/trans/iso2022.$(OBJEXT): internal/core/rclass.h +enc/trans/iso2022.$(OBJEXT): internal/core/rdata.h +enc/trans/iso2022.$(OBJEXT): internal/core/rfile.h +enc/trans/iso2022.$(OBJEXT): internal/core/rhash.h +enc/trans/iso2022.$(OBJEXT): internal/core/robject.h +enc/trans/iso2022.$(OBJEXT): internal/core/rregexp.h +enc/trans/iso2022.$(OBJEXT): internal/core/rstring.h +enc/trans/iso2022.$(OBJEXT): internal/core/rstruct.h +enc/trans/iso2022.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/iso2022.$(OBJEXT): internal/ctype.h +enc/trans/iso2022.$(OBJEXT): internal/dllexport.h +enc/trans/iso2022.$(OBJEXT): internal/dosish.h +enc/trans/iso2022.$(OBJEXT): internal/error.h +enc/trans/iso2022.$(OBJEXT): internal/eval.h +enc/trans/iso2022.$(OBJEXT): internal/event.h +enc/trans/iso2022.$(OBJEXT): internal/fl_type.h +enc/trans/iso2022.$(OBJEXT): internal/gc.h +enc/trans/iso2022.$(OBJEXT): internal/glob.h +enc/trans/iso2022.$(OBJEXT): internal/globals.h +enc/trans/iso2022.$(OBJEXT): internal/has/attribute.h +enc/trans/iso2022.$(OBJEXT): internal/has/builtin.h +enc/trans/iso2022.$(OBJEXT): internal/has/c_attribute.h +enc/trans/iso2022.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/iso2022.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/iso2022.$(OBJEXT): internal/has/extension.h +enc/trans/iso2022.$(OBJEXT): internal/has/feature.h +enc/trans/iso2022.$(OBJEXT): internal/has/warning.h +enc/trans/iso2022.$(OBJEXT): internal/intern/array.h +enc/trans/iso2022.$(OBJEXT): internal/intern/bignum.h +enc/trans/iso2022.$(OBJEXT): internal/intern/class.h +enc/trans/iso2022.$(OBJEXT): internal/intern/compar.h +enc/trans/iso2022.$(OBJEXT): internal/intern/complex.h +enc/trans/iso2022.$(OBJEXT): internal/intern/cont.h +enc/trans/iso2022.$(OBJEXT): internal/intern/dir.h +enc/trans/iso2022.$(OBJEXT): internal/intern/enum.h +enc/trans/iso2022.$(OBJEXT): internal/intern/enumerator.h +enc/trans/iso2022.$(OBJEXT): internal/intern/error.h +enc/trans/iso2022.$(OBJEXT): internal/intern/eval.h +enc/trans/iso2022.$(OBJEXT): internal/intern/file.h +enc/trans/iso2022.$(OBJEXT): internal/intern/gc.h +enc/trans/iso2022.$(OBJEXT): internal/intern/hash.h +enc/trans/iso2022.$(OBJEXT): internal/intern/io.h +enc/trans/iso2022.$(OBJEXT): internal/intern/load.h +enc/trans/iso2022.$(OBJEXT): internal/intern/marshal.h +enc/trans/iso2022.$(OBJEXT): internal/intern/numeric.h +enc/trans/iso2022.$(OBJEXT): internal/intern/object.h +enc/trans/iso2022.$(OBJEXT): internal/intern/parse.h +enc/trans/iso2022.$(OBJEXT): internal/intern/proc.h +enc/trans/iso2022.$(OBJEXT): internal/intern/process.h +enc/trans/iso2022.$(OBJEXT): internal/intern/random.h +enc/trans/iso2022.$(OBJEXT): internal/intern/range.h +enc/trans/iso2022.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/iso2022.$(OBJEXT): internal/intern/sprintf.h +enc/trans/iso2022.$(OBJEXT): internal/intern/string.h +enc/trans/iso2022.$(OBJEXT): internal/intern/struct.h +enc/trans/iso2022.$(OBJEXT): internal/intern/thread.h +enc/trans/iso2022.$(OBJEXT): internal/intern/time.h +enc/trans/iso2022.$(OBJEXT): internal/intern/variable.h +enc/trans/iso2022.$(OBJEXT): internal/intern/vm.h +enc/trans/iso2022.$(OBJEXT): internal/interpreter.h +enc/trans/iso2022.$(OBJEXT): internal/iterator.h +enc/trans/iso2022.$(OBJEXT): internal/memory.h +enc/trans/iso2022.$(OBJEXT): internal/method.h +enc/trans/iso2022.$(OBJEXT): internal/module.h +enc/trans/iso2022.$(OBJEXT): internal/newobj.h +enc/trans/iso2022.$(OBJEXT): internal/rgengc.h +enc/trans/iso2022.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/iso2022.$(OBJEXT): internal/value.h +enc/trans/iso2022.$(OBJEXT): internal/value_type.h +enc/trans/iso2022.$(OBJEXT): internal/variable.h +enc/trans/iso2022.$(OBJEXT): internal/warning_push.h +enc/trans/iso2022.$(OBJEXT): internal/xmalloc.h enc/trans/iso2022.$(OBJEXT): missing.h enc/trans/iso2022.$(OBJEXT): st.h enc/trans/iso2022.$(OBJEXT): subst.h @@ -529,10 +4248,157 @@ enc/trans/japanese.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/japanese.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/japanese.$(OBJEXT): assert.h enc/trans/japanese.$(OBJEXT): backward.h +enc/trans/japanese.$(OBJEXT): backward/2/assume.h +enc/trans/japanese.$(OBJEXT): backward/2/attributes.h +enc/trans/japanese.$(OBJEXT): backward/2/bool.h +enc/trans/japanese.$(OBJEXT): backward/2/inttypes.h +enc/trans/japanese.$(OBJEXT): backward/2/limits.h +enc/trans/japanese.$(OBJEXT): backward/2/long_long.h +enc/trans/japanese.$(OBJEXT): backward/2/stdalign.h +enc/trans/japanese.$(OBJEXT): backward/2/stdarg.h enc/trans/japanese.$(OBJEXT): config.h enc/trans/japanese.$(OBJEXT): defines.h enc/trans/japanese.$(OBJEXT): enc/trans/japanese.c enc/trans/japanese.$(OBJEXT): intern.h +enc/trans/japanese.$(OBJEXT): internal/anyargs.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/char.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/double.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/int.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/long.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/short.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/japanese.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/japanese.$(OBJEXT): internal/assume.h +enc/trans/japanese.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/japanese.$(OBJEXT): internal/attr/artificial.h +enc/trans/japanese.$(OBJEXT): internal/attr/cold.h +enc/trans/japanese.$(OBJEXT): internal/attr/const.h +enc/trans/japanese.$(OBJEXT): internal/attr/constexpr.h +enc/trans/japanese.$(OBJEXT): internal/attr/deprecated.h +enc/trans/japanese.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/japanese.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/japanese.$(OBJEXT): internal/attr/error.h +enc/trans/japanese.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/japanese.$(OBJEXT): internal/attr/forceinline.h +enc/trans/japanese.$(OBJEXT): internal/attr/format.h +enc/trans/japanese.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/japanese.$(OBJEXT): internal/attr/noalias.h +enc/trans/japanese.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/japanese.$(OBJEXT): internal/attr/noexcept.h +enc/trans/japanese.$(OBJEXT): internal/attr/noinline.h +enc/trans/japanese.$(OBJEXT): internal/attr/nonnull.h +enc/trans/japanese.$(OBJEXT): internal/attr/noreturn.h +enc/trans/japanese.$(OBJEXT): internal/attr/pure.h +enc/trans/japanese.$(OBJEXT): internal/attr/restrict.h +enc/trans/japanese.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/japanese.$(OBJEXT): internal/attr/warning.h +enc/trans/japanese.$(OBJEXT): internal/attr/weakref.h +enc/trans/japanese.$(OBJEXT): internal/cast.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/japanese.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/japanese.$(OBJEXT): internal/compiler_since.h +enc/trans/japanese.$(OBJEXT): internal/config.h +enc/trans/japanese.$(OBJEXT): internal/constant_p.h +enc/trans/japanese.$(OBJEXT): internal/core.h +enc/trans/japanese.$(OBJEXT): internal/core/rarray.h +enc/trans/japanese.$(OBJEXT): internal/core/rbasic.h +enc/trans/japanese.$(OBJEXT): internal/core/rbignum.h +enc/trans/japanese.$(OBJEXT): internal/core/rclass.h +enc/trans/japanese.$(OBJEXT): internal/core/rdata.h +enc/trans/japanese.$(OBJEXT): internal/core/rfile.h +enc/trans/japanese.$(OBJEXT): internal/core/rhash.h +enc/trans/japanese.$(OBJEXT): internal/core/robject.h +enc/trans/japanese.$(OBJEXT): internal/core/rregexp.h +enc/trans/japanese.$(OBJEXT): internal/core/rstring.h +enc/trans/japanese.$(OBJEXT): internal/core/rstruct.h +enc/trans/japanese.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/japanese.$(OBJEXT): internal/ctype.h +enc/trans/japanese.$(OBJEXT): internal/dllexport.h +enc/trans/japanese.$(OBJEXT): internal/dosish.h +enc/trans/japanese.$(OBJEXT): internal/error.h +enc/trans/japanese.$(OBJEXT): internal/eval.h +enc/trans/japanese.$(OBJEXT): internal/event.h +enc/trans/japanese.$(OBJEXT): internal/fl_type.h +enc/trans/japanese.$(OBJEXT): internal/gc.h +enc/trans/japanese.$(OBJEXT): internal/glob.h +enc/trans/japanese.$(OBJEXT): internal/globals.h +enc/trans/japanese.$(OBJEXT): internal/has/attribute.h +enc/trans/japanese.$(OBJEXT): internal/has/builtin.h +enc/trans/japanese.$(OBJEXT): internal/has/c_attribute.h +enc/trans/japanese.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/japanese.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/japanese.$(OBJEXT): internal/has/extension.h +enc/trans/japanese.$(OBJEXT): internal/has/feature.h +enc/trans/japanese.$(OBJEXT): internal/has/warning.h +enc/trans/japanese.$(OBJEXT): internal/intern/array.h +enc/trans/japanese.$(OBJEXT): internal/intern/bignum.h +enc/trans/japanese.$(OBJEXT): internal/intern/class.h +enc/trans/japanese.$(OBJEXT): internal/intern/compar.h +enc/trans/japanese.$(OBJEXT): internal/intern/complex.h +enc/trans/japanese.$(OBJEXT): internal/intern/cont.h +enc/trans/japanese.$(OBJEXT): internal/intern/dir.h +enc/trans/japanese.$(OBJEXT): internal/intern/enum.h +enc/trans/japanese.$(OBJEXT): internal/intern/enumerator.h +enc/trans/japanese.$(OBJEXT): internal/intern/error.h +enc/trans/japanese.$(OBJEXT): internal/intern/eval.h +enc/trans/japanese.$(OBJEXT): internal/intern/file.h +enc/trans/japanese.$(OBJEXT): internal/intern/gc.h +enc/trans/japanese.$(OBJEXT): internal/intern/hash.h +enc/trans/japanese.$(OBJEXT): internal/intern/io.h +enc/trans/japanese.$(OBJEXT): internal/intern/load.h +enc/trans/japanese.$(OBJEXT): internal/intern/marshal.h +enc/trans/japanese.$(OBJEXT): internal/intern/numeric.h +enc/trans/japanese.$(OBJEXT): internal/intern/object.h +enc/trans/japanese.$(OBJEXT): internal/intern/parse.h +enc/trans/japanese.$(OBJEXT): internal/intern/proc.h +enc/trans/japanese.$(OBJEXT): internal/intern/process.h +enc/trans/japanese.$(OBJEXT): internal/intern/random.h +enc/trans/japanese.$(OBJEXT): internal/intern/range.h +enc/trans/japanese.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/japanese.$(OBJEXT): internal/intern/sprintf.h +enc/trans/japanese.$(OBJEXT): internal/intern/string.h +enc/trans/japanese.$(OBJEXT): internal/intern/struct.h +enc/trans/japanese.$(OBJEXT): internal/intern/thread.h +enc/trans/japanese.$(OBJEXT): internal/intern/time.h +enc/trans/japanese.$(OBJEXT): internal/intern/variable.h +enc/trans/japanese.$(OBJEXT): internal/intern/vm.h +enc/trans/japanese.$(OBJEXT): internal/interpreter.h +enc/trans/japanese.$(OBJEXT): internal/iterator.h +enc/trans/japanese.$(OBJEXT): internal/memory.h +enc/trans/japanese.$(OBJEXT): internal/method.h +enc/trans/japanese.$(OBJEXT): internal/module.h +enc/trans/japanese.$(OBJEXT): internal/newobj.h +enc/trans/japanese.$(OBJEXT): internal/rgengc.h +enc/trans/japanese.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/japanese.$(OBJEXT): internal/value.h +enc/trans/japanese.$(OBJEXT): internal/value_type.h +enc/trans/japanese.$(OBJEXT): internal/variable.h +enc/trans/japanese.$(OBJEXT): internal/warning_push.h +enc/trans/japanese.$(OBJEXT): internal/xmalloc.h enc/trans/japanese.$(OBJEXT): missing.h enc/trans/japanese.$(OBJEXT): st.h enc/trans/japanese.$(OBJEXT): subst.h @@ -540,10 +4406,157 @@ enc/trans/japanese_euc.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/japanese_euc.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/japanese_euc.$(OBJEXT): assert.h enc/trans/japanese_euc.$(OBJEXT): backward.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/assume.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/attributes.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/bool.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/inttypes.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/limits.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/long_long.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/stdalign.h +enc/trans/japanese_euc.$(OBJEXT): backward/2/stdarg.h enc/trans/japanese_euc.$(OBJEXT): config.h enc/trans/japanese_euc.$(OBJEXT): defines.h enc/trans/japanese_euc.$(OBJEXT): enc/trans/japanese_euc.c enc/trans/japanese_euc.$(OBJEXT): intern.h +enc/trans/japanese_euc.$(OBJEXT): internal/anyargs.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/char.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/double.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/int.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/long.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/short.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/japanese_euc.$(OBJEXT): internal/assume.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/artificial.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/cold.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/const.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/constexpr.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/deprecated.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/error.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/forceinline.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/format.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/noalias.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/noexcept.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/noinline.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/nonnull.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/noreturn.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/pure.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/restrict.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/warning.h +enc/trans/japanese_euc.$(OBJEXT): internal/attr/weakref.h +enc/trans/japanese_euc.$(OBJEXT): internal/cast.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/japanese_euc.$(OBJEXT): internal/compiler_since.h +enc/trans/japanese_euc.$(OBJEXT): internal/config.h +enc/trans/japanese_euc.$(OBJEXT): internal/constant_p.h +enc/trans/japanese_euc.$(OBJEXT): internal/core.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rarray.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rbasic.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rbignum.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rclass.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rdata.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rfile.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rhash.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/robject.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rregexp.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rstring.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rstruct.h +enc/trans/japanese_euc.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/japanese_euc.$(OBJEXT): internal/ctype.h +enc/trans/japanese_euc.$(OBJEXT): internal/dllexport.h +enc/trans/japanese_euc.$(OBJEXT): internal/dosish.h +enc/trans/japanese_euc.$(OBJEXT): internal/error.h +enc/trans/japanese_euc.$(OBJEXT): internal/eval.h +enc/trans/japanese_euc.$(OBJEXT): internal/event.h +enc/trans/japanese_euc.$(OBJEXT): internal/fl_type.h +enc/trans/japanese_euc.$(OBJEXT): internal/gc.h +enc/trans/japanese_euc.$(OBJEXT): internal/glob.h +enc/trans/japanese_euc.$(OBJEXT): internal/globals.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/attribute.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/builtin.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/c_attribute.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/extension.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/feature.h +enc/trans/japanese_euc.$(OBJEXT): internal/has/warning.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/array.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/bignum.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/class.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/compar.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/complex.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/cont.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/dir.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/enum.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/enumerator.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/error.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/eval.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/file.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/gc.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/hash.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/io.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/load.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/marshal.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/numeric.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/object.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/parse.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/proc.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/process.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/random.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/range.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/sprintf.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/string.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/struct.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/thread.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/time.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/variable.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/vm.h +enc/trans/japanese_euc.$(OBJEXT): internal/interpreter.h +enc/trans/japanese_euc.$(OBJEXT): internal/iterator.h +enc/trans/japanese_euc.$(OBJEXT): internal/memory.h +enc/trans/japanese_euc.$(OBJEXT): internal/method.h +enc/trans/japanese_euc.$(OBJEXT): internal/module.h +enc/trans/japanese_euc.$(OBJEXT): internal/newobj.h +enc/trans/japanese_euc.$(OBJEXT): internal/rgengc.h +enc/trans/japanese_euc.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/japanese_euc.$(OBJEXT): internal/value.h +enc/trans/japanese_euc.$(OBJEXT): internal/value_type.h +enc/trans/japanese_euc.$(OBJEXT): internal/variable.h +enc/trans/japanese_euc.$(OBJEXT): internal/warning_push.h +enc/trans/japanese_euc.$(OBJEXT): internal/xmalloc.h enc/trans/japanese_euc.$(OBJEXT): missing.h enc/trans/japanese_euc.$(OBJEXT): st.h enc/trans/japanese_euc.$(OBJEXT): subst.h @@ -551,10 +4564,157 @@ enc/trans/japanese_sjis.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/japanese_sjis.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/japanese_sjis.$(OBJEXT): assert.h enc/trans/japanese_sjis.$(OBJEXT): backward.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/assume.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/attributes.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/bool.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/inttypes.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/limits.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/long_long.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdalign.h +enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdarg.h enc/trans/japanese_sjis.$(OBJEXT): config.h enc/trans/japanese_sjis.$(OBJEXT): defines.h enc/trans/japanese_sjis.$(OBJEXT): enc/trans/japanese_sjis.c enc/trans/japanese_sjis.$(OBJEXT): intern.h +enc/trans/japanese_sjis.$(OBJEXT): internal/anyargs.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/char.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/double.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/int.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/long.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/short.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/japanese_sjis.$(OBJEXT): internal/assume.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/artificial.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/cold.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/const.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/constexpr.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/deprecated.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/error.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/forceinline.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/format.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noalias.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noexcept.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noinline.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/nonnull.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noreturn.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/pure.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/restrict.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/warning.h +enc/trans/japanese_sjis.$(OBJEXT): internal/attr/weakref.h +enc/trans/japanese_sjis.$(OBJEXT): internal/cast.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_since.h +enc/trans/japanese_sjis.$(OBJEXT): internal/config.h +enc/trans/japanese_sjis.$(OBJEXT): internal/constant_p.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rarray.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rbasic.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rbignum.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rclass.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rdata.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rfile.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rhash.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/robject.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rregexp.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rstring.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rstruct.h +enc/trans/japanese_sjis.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/japanese_sjis.$(OBJEXT): internal/ctype.h +enc/trans/japanese_sjis.$(OBJEXT): internal/dllexport.h +enc/trans/japanese_sjis.$(OBJEXT): internal/dosish.h +enc/trans/japanese_sjis.$(OBJEXT): internal/error.h +enc/trans/japanese_sjis.$(OBJEXT): internal/eval.h +enc/trans/japanese_sjis.$(OBJEXT): internal/event.h +enc/trans/japanese_sjis.$(OBJEXT): internal/fl_type.h +enc/trans/japanese_sjis.$(OBJEXT): internal/gc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/glob.h +enc/trans/japanese_sjis.$(OBJEXT): internal/globals.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/attribute.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/builtin.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/c_attribute.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/extension.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/feature.h +enc/trans/japanese_sjis.$(OBJEXT): internal/has/warning.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/array.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/bignum.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/class.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/compar.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/complex.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/cont.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/dir.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/enum.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/enumerator.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/error.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/eval.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/file.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/gc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/hash.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/io.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/load.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/marshal.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/numeric.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/object.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/parse.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/proc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/process.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/random.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/range.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/sprintf.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/string.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/struct.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/thread.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/time.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/variable.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/vm.h +enc/trans/japanese_sjis.$(OBJEXT): internal/interpreter.h +enc/trans/japanese_sjis.$(OBJEXT): internal/iterator.h +enc/trans/japanese_sjis.$(OBJEXT): internal/memory.h +enc/trans/japanese_sjis.$(OBJEXT): internal/method.h +enc/trans/japanese_sjis.$(OBJEXT): internal/module.h +enc/trans/japanese_sjis.$(OBJEXT): internal/newobj.h +enc/trans/japanese_sjis.$(OBJEXT): internal/rgengc.h +enc/trans/japanese_sjis.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/japanese_sjis.$(OBJEXT): internal/value.h +enc/trans/japanese_sjis.$(OBJEXT): internal/value_type.h +enc/trans/japanese_sjis.$(OBJEXT): internal/variable.h +enc/trans/japanese_sjis.$(OBJEXT): internal/warning_push.h +enc/trans/japanese_sjis.$(OBJEXT): internal/xmalloc.h enc/trans/japanese_sjis.$(OBJEXT): missing.h enc/trans/japanese_sjis.$(OBJEXT): st.h enc/trans/japanese_sjis.$(OBJEXT): subst.h @@ -562,20 +4722,314 @@ enc/trans/korean.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/korean.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/korean.$(OBJEXT): assert.h enc/trans/korean.$(OBJEXT): backward.h +enc/trans/korean.$(OBJEXT): backward/2/assume.h +enc/trans/korean.$(OBJEXT): backward/2/attributes.h +enc/trans/korean.$(OBJEXT): backward/2/bool.h +enc/trans/korean.$(OBJEXT): backward/2/inttypes.h +enc/trans/korean.$(OBJEXT): backward/2/limits.h +enc/trans/korean.$(OBJEXT): backward/2/long_long.h +enc/trans/korean.$(OBJEXT): backward/2/stdalign.h +enc/trans/korean.$(OBJEXT): backward/2/stdarg.h enc/trans/korean.$(OBJEXT): config.h enc/trans/korean.$(OBJEXT): defines.h enc/trans/korean.$(OBJEXT): enc/trans/korean.c enc/trans/korean.$(OBJEXT): intern.h +enc/trans/korean.$(OBJEXT): internal/anyargs.h +enc/trans/korean.$(OBJEXT): internal/arithmetic.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/char.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/double.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/int.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/long.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/short.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/korean.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/korean.$(OBJEXT): internal/assume.h +enc/trans/korean.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/korean.$(OBJEXT): internal/attr/artificial.h +enc/trans/korean.$(OBJEXT): internal/attr/cold.h +enc/trans/korean.$(OBJEXT): internal/attr/const.h +enc/trans/korean.$(OBJEXT): internal/attr/constexpr.h +enc/trans/korean.$(OBJEXT): internal/attr/deprecated.h +enc/trans/korean.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/korean.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/korean.$(OBJEXT): internal/attr/error.h +enc/trans/korean.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/korean.$(OBJEXT): internal/attr/forceinline.h +enc/trans/korean.$(OBJEXT): internal/attr/format.h +enc/trans/korean.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/korean.$(OBJEXT): internal/attr/noalias.h +enc/trans/korean.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/korean.$(OBJEXT): internal/attr/noexcept.h +enc/trans/korean.$(OBJEXT): internal/attr/noinline.h +enc/trans/korean.$(OBJEXT): internal/attr/nonnull.h +enc/trans/korean.$(OBJEXT): internal/attr/noreturn.h +enc/trans/korean.$(OBJEXT): internal/attr/pure.h +enc/trans/korean.$(OBJEXT): internal/attr/restrict.h +enc/trans/korean.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/korean.$(OBJEXT): internal/attr/warning.h +enc/trans/korean.$(OBJEXT): internal/attr/weakref.h +enc/trans/korean.$(OBJEXT): internal/cast.h +enc/trans/korean.$(OBJEXT): internal/compiler_is.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/korean.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/korean.$(OBJEXT): internal/compiler_since.h +enc/trans/korean.$(OBJEXT): internal/config.h +enc/trans/korean.$(OBJEXT): internal/constant_p.h +enc/trans/korean.$(OBJEXT): internal/core.h +enc/trans/korean.$(OBJEXT): internal/core/rarray.h +enc/trans/korean.$(OBJEXT): internal/core/rbasic.h +enc/trans/korean.$(OBJEXT): internal/core/rbignum.h +enc/trans/korean.$(OBJEXT): internal/core/rclass.h +enc/trans/korean.$(OBJEXT): internal/core/rdata.h +enc/trans/korean.$(OBJEXT): internal/core/rfile.h +enc/trans/korean.$(OBJEXT): internal/core/rhash.h +enc/trans/korean.$(OBJEXT): internal/core/robject.h +enc/trans/korean.$(OBJEXT): internal/core/rregexp.h +enc/trans/korean.$(OBJEXT): internal/core/rstring.h +enc/trans/korean.$(OBJEXT): internal/core/rstruct.h +enc/trans/korean.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/korean.$(OBJEXT): internal/ctype.h +enc/trans/korean.$(OBJEXT): internal/dllexport.h +enc/trans/korean.$(OBJEXT): internal/dosish.h +enc/trans/korean.$(OBJEXT): internal/error.h +enc/trans/korean.$(OBJEXT): internal/eval.h +enc/trans/korean.$(OBJEXT): internal/event.h +enc/trans/korean.$(OBJEXT): internal/fl_type.h +enc/trans/korean.$(OBJEXT): internal/gc.h +enc/trans/korean.$(OBJEXT): internal/glob.h +enc/trans/korean.$(OBJEXT): internal/globals.h +enc/trans/korean.$(OBJEXT): internal/has/attribute.h +enc/trans/korean.$(OBJEXT): internal/has/builtin.h +enc/trans/korean.$(OBJEXT): internal/has/c_attribute.h +enc/trans/korean.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/korean.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/korean.$(OBJEXT): internal/has/extension.h +enc/trans/korean.$(OBJEXT): internal/has/feature.h +enc/trans/korean.$(OBJEXT): internal/has/warning.h +enc/trans/korean.$(OBJEXT): internal/intern/array.h +enc/trans/korean.$(OBJEXT): internal/intern/bignum.h +enc/trans/korean.$(OBJEXT): internal/intern/class.h +enc/trans/korean.$(OBJEXT): internal/intern/compar.h +enc/trans/korean.$(OBJEXT): internal/intern/complex.h +enc/trans/korean.$(OBJEXT): internal/intern/cont.h +enc/trans/korean.$(OBJEXT): internal/intern/dir.h +enc/trans/korean.$(OBJEXT): internal/intern/enum.h +enc/trans/korean.$(OBJEXT): internal/intern/enumerator.h +enc/trans/korean.$(OBJEXT): internal/intern/error.h +enc/trans/korean.$(OBJEXT): internal/intern/eval.h +enc/trans/korean.$(OBJEXT): internal/intern/file.h +enc/trans/korean.$(OBJEXT): internal/intern/gc.h +enc/trans/korean.$(OBJEXT): internal/intern/hash.h +enc/trans/korean.$(OBJEXT): internal/intern/io.h +enc/trans/korean.$(OBJEXT): internal/intern/load.h +enc/trans/korean.$(OBJEXT): internal/intern/marshal.h +enc/trans/korean.$(OBJEXT): internal/intern/numeric.h +enc/trans/korean.$(OBJEXT): internal/intern/object.h +enc/trans/korean.$(OBJEXT): internal/intern/parse.h +enc/trans/korean.$(OBJEXT): internal/intern/proc.h +enc/trans/korean.$(OBJEXT): internal/intern/process.h +enc/trans/korean.$(OBJEXT): internal/intern/random.h +enc/trans/korean.$(OBJEXT): internal/intern/range.h +enc/trans/korean.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/korean.$(OBJEXT): internal/intern/sprintf.h +enc/trans/korean.$(OBJEXT): internal/intern/string.h +enc/trans/korean.$(OBJEXT): internal/intern/struct.h +enc/trans/korean.$(OBJEXT): internal/intern/thread.h +enc/trans/korean.$(OBJEXT): internal/intern/time.h +enc/trans/korean.$(OBJEXT): internal/intern/variable.h +enc/trans/korean.$(OBJEXT): internal/intern/vm.h +enc/trans/korean.$(OBJEXT): internal/interpreter.h +enc/trans/korean.$(OBJEXT): internal/iterator.h +enc/trans/korean.$(OBJEXT): internal/memory.h +enc/trans/korean.$(OBJEXT): internal/method.h +enc/trans/korean.$(OBJEXT): internal/module.h +enc/trans/korean.$(OBJEXT): internal/newobj.h +enc/trans/korean.$(OBJEXT): internal/rgengc.h +enc/trans/korean.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/korean.$(OBJEXT): internal/value.h +enc/trans/korean.$(OBJEXT): internal/value_type.h +enc/trans/korean.$(OBJEXT): internal/variable.h +enc/trans/korean.$(OBJEXT): internal/warning_push.h +enc/trans/korean.$(OBJEXT): internal/xmalloc.h enc/trans/korean.$(OBJEXT): missing.h enc/trans/korean.$(OBJEXT): st.h enc/trans/korean.$(OBJEXT): subst.h enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/newline.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/newline.$(OBJEXT): assert.h +enc/trans/newline.$(OBJEXT): backward/2/assume.h +enc/trans/newline.$(OBJEXT): backward/2/attributes.h +enc/trans/newline.$(OBJEXT): backward/2/bool.h +enc/trans/newline.$(OBJEXT): backward/2/inttypes.h +enc/trans/newline.$(OBJEXT): backward/2/limits.h +enc/trans/newline.$(OBJEXT): backward/2/long_long.h +enc/trans/newline.$(OBJEXT): backward/2/stdalign.h +enc/trans/newline.$(OBJEXT): backward/2/stdarg.h enc/trans/newline.$(OBJEXT): config.h enc/trans/newline.$(OBJEXT): defines.h enc/trans/newline.$(OBJEXT): enc/trans/newline.c enc/trans/newline.$(OBJEXT): intern.h +enc/trans/newline.$(OBJEXT): internal/anyargs.h +enc/trans/newline.$(OBJEXT): internal/arithmetic.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/char.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/double.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/int.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/long.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/short.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/newline.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/newline.$(OBJEXT): internal/assume.h +enc/trans/newline.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/newline.$(OBJEXT): internal/attr/artificial.h +enc/trans/newline.$(OBJEXT): internal/attr/cold.h +enc/trans/newline.$(OBJEXT): internal/attr/const.h +enc/trans/newline.$(OBJEXT): internal/attr/constexpr.h +enc/trans/newline.$(OBJEXT): internal/attr/deprecated.h +enc/trans/newline.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/newline.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/newline.$(OBJEXT): internal/attr/error.h +enc/trans/newline.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/newline.$(OBJEXT): internal/attr/forceinline.h +enc/trans/newline.$(OBJEXT): internal/attr/format.h +enc/trans/newline.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/newline.$(OBJEXT): internal/attr/noalias.h +enc/trans/newline.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/newline.$(OBJEXT): internal/attr/noexcept.h +enc/trans/newline.$(OBJEXT): internal/attr/noinline.h +enc/trans/newline.$(OBJEXT): internal/attr/nonnull.h +enc/trans/newline.$(OBJEXT): internal/attr/noreturn.h +enc/trans/newline.$(OBJEXT): internal/attr/pure.h +enc/trans/newline.$(OBJEXT): internal/attr/restrict.h +enc/trans/newline.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/newline.$(OBJEXT): internal/attr/warning.h +enc/trans/newline.$(OBJEXT): internal/attr/weakref.h +enc/trans/newline.$(OBJEXT): internal/cast.h +enc/trans/newline.$(OBJEXT): internal/compiler_is.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/newline.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/newline.$(OBJEXT): internal/compiler_since.h +enc/trans/newline.$(OBJEXT): internal/config.h +enc/trans/newline.$(OBJEXT): internal/constant_p.h +enc/trans/newline.$(OBJEXT): internal/core.h +enc/trans/newline.$(OBJEXT): internal/core/rarray.h +enc/trans/newline.$(OBJEXT): internal/core/rbasic.h +enc/trans/newline.$(OBJEXT): internal/core/rbignum.h +enc/trans/newline.$(OBJEXT): internal/core/rclass.h +enc/trans/newline.$(OBJEXT): internal/core/rdata.h +enc/trans/newline.$(OBJEXT): internal/core/rfile.h +enc/trans/newline.$(OBJEXT): internal/core/rhash.h +enc/trans/newline.$(OBJEXT): internal/core/robject.h +enc/trans/newline.$(OBJEXT): internal/core/rregexp.h +enc/trans/newline.$(OBJEXT): internal/core/rstring.h +enc/trans/newline.$(OBJEXT): internal/core/rstruct.h +enc/trans/newline.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/newline.$(OBJEXT): internal/ctype.h +enc/trans/newline.$(OBJEXT): internal/dllexport.h +enc/trans/newline.$(OBJEXT): internal/dosish.h +enc/trans/newline.$(OBJEXT): internal/error.h +enc/trans/newline.$(OBJEXT): internal/eval.h +enc/trans/newline.$(OBJEXT): internal/event.h +enc/trans/newline.$(OBJEXT): internal/fl_type.h +enc/trans/newline.$(OBJEXT): internal/gc.h +enc/trans/newline.$(OBJEXT): internal/glob.h +enc/trans/newline.$(OBJEXT): internal/globals.h +enc/trans/newline.$(OBJEXT): internal/has/attribute.h +enc/trans/newline.$(OBJEXT): internal/has/builtin.h +enc/trans/newline.$(OBJEXT): internal/has/c_attribute.h +enc/trans/newline.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/newline.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/newline.$(OBJEXT): internal/has/extension.h +enc/trans/newline.$(OBJEXT): internal/has/feature.h +enc/trans/newline.$(OBJEXT): internal/has/warning.h +enc/trans/newline.$(OBJEXT): internal/intern/array.h +enc/trans/newline.$(OBJEXT): internal/intern/bignum.h +enc/trans/newline.$(OBJEXT): internal/intern/class.h +enc/trans/newline.$(OBJEXT): internal/intern/compar.h +enc/trans/newline.$(OBJEXT): internal/intern/complex.h +enc/trans/newline.$(OBJEXT): internal/intern/cont.h +enc/trans/newline.$(OBJEXT): internal/intern/dir.h +enc/trans/newline.$(OBJEXT): internal/intern/enum.h +enc/trans/newline.$(OBJEXT): internal/intern/enumerator.h +enc/trans/newline.$(OBJEXT): internal/intern/error.h +enc/trans/newline.$(OBJEXT): internal/intern/eval.h +enc/trans/newline.$(OBJEXT): internal/intern/file.h +enc/trans/newline.$(OBJEXT): internal/intern/gc.h +enc/trans/newline.$(OBJEXT): internal/intern/hash.h +enc/trans/newline.$(OBJEXT): internal/intern/io.h +enc/trans/newline.$(OBJEXT): internal/intern/load.h +enc/trans/newline.$(OBJEXT): internal/intern/marshal.h +enc/trans/newline.$(OBJEXT): internal/intern/numeric.h +enc/trans/newline.$(OBJEXT): internal/intern/object.h +enc/trans/newline.$(OBJEXT): internal/intern/parse.h +enc/trans/newline.$(OBJEXT): internal/intern/proc.h +enc/trans/newline.$(OBJEXT): internal/intern/process.h +enc/trans/newline.$(OBJEXT): internal/intern/random.h +enc/trans/newline.$(OBJEXT): internal/intern/range.h +enc/trans/newline.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/newline.$(OBJEXT): internal/intern/sprintf.h +enc/trans/newline.$(OBJEXT): internal/intern/string.h +enc/trans/newline.$(OBJEXT): internal/intern/struct.h +enc/trans/newline.$(OBJEXT): internal/intern/thread.h +enc/trans/newline.$(OBJEXT): internal/intern/time.h +enc/trans/newline.$(OBJEXT): internal/intern/variable.h +enc/trans/newline.$(OBJEXT): internal/intern/vm.h +enc/trans/newline.$(OBJEXT): internal/interpreter.h +enc/trans/newline.$(OBJEXT): internal/iterator.h +enc/trans/newline.$(OBJEXT): internal/memory.h +enc/trans/newline.$(OBJEXT): internal/method.h +enc/trans/newline.$(OBJEXT): internal/module.h +enc/trans/newline.$(OBJEXT): internal/newobj.h +enc/trans/newline.$(OBJEXT): internal/rgengc.h +enc/trans/newline.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/newline.$(OBJEXT): internal/value.h +enc/trans/newline.$(OBJEXT): internal/value_type.h +enc/trans/newline.$(OBJEXT): internal/variable.h +enc/trans/newline.$(OBJEXT): internal/warning_push.h +enc/trans/newline.$(OBJEXT): internal/xmalloc.h enc/trans/newline.$(OBJEXT): missing.h enc/trans/newline.$(OBJEXT): st.h enc/trans/newline.$(OBJEXT): subst.h @@ -583,10 +5037,157 @@ enc/trans/single_byte.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/single_byte.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/single_byte.$(OBJEXT): assert.h enc/trans/single_byte.$(OBJEXT): backward.h +enc/trans/single_byte.$(OBJEXT): backward/2/assume.h +enc/trans/single_byte.$(OBJEXT): backward/2/attributes.h +enc/trans/single_byte.$(OBJEXT): backward/2/bool.h +enc/trans/single_byte.$(OBJEXT): backward/2/inttypes.h +enc/trans/single_byte.$(OBJEXT): backward/2/limits.h +enc/trans/single_byte.$(OBJEXT): backward/2/long_long.h +enc/trans/single_byte.$(OBJEXT): backward/2/stdalign.h +enc/trans/single_byte.$(OBJEXT): backward/2/stdarg.h enc/trans/single_byte.$(OBJEXT): config.h enc/trans/single_byte.$(OBJEXT): defines.h enc/trans/single_byte.$(OBJEXT): enc/trans/single_byte.c enc/trans/single_byte.$(OBJEXT): intern.h +enc/trans/single_byte.$(OBJEXT): internal/anyargs.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/char.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/double.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/int.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/long.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/short.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/single_byte.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/single_byte.$(OBJEXT): internal/assume.h +enc/trans/single_byte.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/single_byte.$(OBJEXT): internal/attr/artificial.h +enc/trans/single_byte.$(OBJEXT): internal/attr/cold.h +enc/trans/single_byte.$(OBJEXT): internal/attr/const.h +enc/trans/single_byte.$(OBJEXT): internal/attr/constexpr.h +enc/trans/single_byte.$(OBJEXT): internal/attr/deprecated.h +enc/trans/single_byte.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/single_byte.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/single_byte.$(OBJEXT): internal/attr/error.h +enc/trans/single_byte.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/single_byte.$(OBJEXT): internal/attr/forceinline.h +enc/trans/single_byte.$(OBJEXT): internal/attr/format.h +enc/trans/single_byte.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/single_byte.$(OBJEXT): internal/attr/noalias.h +enc/trans/single_byte.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/single_byte.$(OBJEXT): internal/attr/noexcept.h +enc/trans/single_byte.$(OBJEXT): internal/attr/noinline.h +enc/trans/single_byte.$(OBJEXT): internal/attr/nonnull.h +enc/trans/single_byte.$(OBJEXT): internal/attr/noreturn.h +enc/trans/single_byte.$(OBJEXT): internal/attr/pure.h +enc/trans/single_byte.$(OBJEXT): internal/attr/restrict.h +enc/trans/single_byte.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/single_byte.$(OBJEXT): internal/attr/warning.h +enc/trans/single_byte.$(OBJEXT): internal/attr/weakref.h +enc/trans/single_byte.$(OBJEXT): internal/cast.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/single_byte.$(OBJEXT): internal/compiler_since.h +enc/trans/single_byte.$(OBJEXT): internal/config.h +enc/trans/single_byte.$(OBJEXT): internal/constant_p.h +enc/trans/single_byte.$(OBJEXT): internal/core.h +enc/trans/single_byte.$(OBJEXT): internal/core/rarray.h +enc/trans/single_byte.$(OBJEXT): internal/core/rbasic.h +enc/trans/single_byte.$(OBJEXT): internal/core/rbignum.h +enc/trans/single_byte.$(OBJEXT): internal/core/rclass.h +enc/trans/single_byte.$(OBJEXT): internal/core/rdata.h +enc/trans/single_byte.$(OBJEXT): internal/core/rfile.h +enc/trans/single_byte.$(OBJEXT): internal/core/rhash.h +enc/trans/single_byte.$(OBJEXT): internal/core/robject.h +enc/trans/single_byte.$(OBJEXT): internal/core/rregexp.h +enc/trans/single_byte.$(OBJEXT): internal/core/rstring.h +enc/trans/single_byte.$(OBJEXT): internal/core/rstruct.h +enc/trans/single_byte.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/single_byte.$(OBJEXT): internal/ctype.h +enc/trans/single_byte.$(OBJEXT): internal/dllexport.h +enc/trans/single_byte.$(OBJEXT): internal/dosish.h +enc/trans/single_byte.$(OBJEXT): internal/error.h +enc/trans/single_byte.$(OBJEXT): internal/eval.h +enc/trans/single_byte.$(OBJEXT): internal/event.h +enc/trans/single_byte.$(OBJEXT): internal/fl_type.h +enc/trans/single_byte.$(OBJEXT): internal/gc.h +enc/trans/single_byte.$(OBJEXT): internal/glob.h +enc/trans/single_byte.$(OBJEXT): internal/globals.h +enc/trans/single_byte.$(OBJEXT): internal/has/attribute.h +enc/trans/single_byte.$(OBJEXT): internal/has/builtin.h +enc/trans/single_byte.$(OBJEXT): internal/has/c_attribute.h +enc/trans/single_byte.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/single_byte.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/single_byte.$(OBJEXT): internal/has/extension.h +enc/trans/single_byte.$(OBJEXT): internal/has/feature.h +enc/trans/single_byte.$(OBJEXT): internal/has/warning.h +enc/trans/single_byte.$(OBJEXT): internal/intern/array.h +enc/trans/single_byte.$(OBJEXT): internal/intern/bignum.h +enc/trans/single_byte.$(OBJEXT): internal/intern/class.h +enc/trans/single_byte.$(OBJEXT): internal/intern/compar.h +enc/trans/single_byte.$(OBJEXT): internal/intern/complex.h +enc/trans/single_byte.$(OBJEXT): internal/intern/cont.h +enc/trans/single_byte.$(OBJEXT): internal/intern/dir.h +enc/trans/single_byte.$(OBJEXT): internal/intern/enum.h +enc/trans/single_byte.$(OBJEXT): internal/intern/enumerator.h +enc/trans/single_byte.$(OBJEXT): internal/intern/error.h +enc/trans/single_byte.$(OBJEXT): internal/intern/eval.h +enc/trans/single_byte.$(OBJEXT): internal/intern/file.h +enc/trans/single_byte.$(OBJEXT): internal/intern/gc.h +enc/trans/single_byte.$(OBJEXT): internal/intern/hash.h +enc/trans/single_byte.$(OBJEXT): internal/intern/io.h +enc/trans/single_byte.$(OBJEXT): internal/intern/load.h +enc/trans/single_byte.$(OBJEXT): internal/intern/marshal.h +enc/trans/single_byte.$(OBJEXT): internal/intern/numeric.h +enc/trans/single_byte.$(OBJEXT): internal/intern/object.h +enc/trans/single_byte.$(OBJEXT): internal/intern/parse.h +enc/trans/single_byte.$(OBJEXT): internal/intern/proc.h +enc/trans/single_byte.$(OBJEXT): internal/intern/process.h +enc/trans/single_byte.$(OBJEXT): internal/intern/random.h +enc/trans/single_byte.$(OBJEXT): internal/intern/range.h +enc/trans/single_byte.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/single_byte.$(OBJEXT): internal/intern/sprintf.h +enc/trans/single_byte.$(OBJEXT): internal/intern/string.h +enc/trans/single_byte.$(OBJEXT): internal/intern/struct.h +enc/trans/single_byte.$(OBJEXT): internal/intern/thread.h +enc/trans/single_byte.$(OBJEXT): internal/intern/time.h +enc/trans/single_byte.$(OBJEXT): internal/intern/variable.h +enc/trans/single_byte.$(OBJEXT): internal/intern/vm.h +enc/trans/single_byte.$(OBJEXT): internal/interpreter.h +enc/trans/single_byte.$(OBJEXT): internal/iterator.h +enc/trans/single_byte.$(OBJEXT): internal/memory.h +enc/trans/single_byte.$(OBJEXT): internal/method.h +enc/trans/single_byte.$(OBJEXT): internal/module.h +enc/trans/single_byte.$(OBJEXT): internal/newobj.h +enc/trans/single_byte.$(OBJEXT): internal/rgengc.h +enc/trans/single_byte.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/single_byte.$(OBJEXT): internal/value.h +enc/trans/single_byte.$(OBJEXT): internal/value_type.h +enc/trans/single_byte.$(OBJEXT): internal/variable.h +enc/trans/single_byte.$(OBJEXT): internal/warning_push.h +enc/trans/single_byte.$(OBJEXT): internal/xmalloc.h enc/trans/single_byte.$(OBJEXT): missing.h enc/trans/single_byte.$(OBJEXT): st.h enc/trans/single_byte.$(OBJEXT): subst.h @@ -596,10 +5197,157 @@ enc/trans/utf8_mac.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/utf8_mac.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/utf8_mac.$(OBJEXT): assert.h enc/trans/utf8_mac.$(OBJEXT): backward.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/assume.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/attributes.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/bool.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/inttypes.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/limits.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/long_long.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/stdalign.h +enc/trans/utf8_mac.$(OBJEXT): backward/2/stdarg.h enc/trans/utf8_mac.$(OBJEXT): config.h enc/trans/utf8_mac.$(OBJEXT): defines.h enc/trans/utf8_mac.$(OBJEXT): enc/trans/utf8_mac.c enc/trans/utf8_mac.$(OBJEXT): intern.h +enc/trans/utf8_mac.$(OBJEXT): internal/anyargs.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/char.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/double.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/int.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/long.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/short.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/utf8_mac.$(OBJEXT): internal/assume.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/artificial.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/cold.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/const.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/constexpr.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/deprecated.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/error.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/forceinline.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/format.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/noalias.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/noexcept.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/noinline.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/nonnull.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/noreturn.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/pure.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/restrict.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/warning.h +enc/trans/utf8_mac.$(OBJEXT): internal/attr/weakref.h +enc/trans/utf8_mac.$(OBJEXT): internal/cast.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/utf8_mac.$(OBJEXT): internal/compiler_since.h +enc/trans/utf8_mac.$(OBJEXT): internal/config.h +enc/trans/utf8_mac.$(OBJEXT): internal/constant_p.h +enc/trans/utf8_mac.$(OBJEXT): internal/core.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rarray.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rbasic.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rbignum.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rclass.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rdata.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rfile.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rhash.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/robject.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rregexp.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rstring.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rstruct.h +enc/trans/utf8_mac.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/utf8_mac.$(OBJEXT): internal/ctype.h +enc/trans/utf8_mac.$(OBJEXT): internal/dllexport.h +enc/trans/utf8_mac.$(OBJEXT): internal/dosish.h +enc/trans/utf8_mac.$(OBJEXT): internal/error.h +enc/trans/utf8_mac.$(OBJEXT): internal/eval.h +enc/trans/utf8_mac.$(OBJEXT): internal/event.h +enc/trans/utf8_mac.$(OBJEXT): internal/fl_type.h +enc/trans/utf8_mac.$(OBJEXT): internal/gc.h +enc/trans/utf8_mac.$(OBJEXT): internal/glob.h +enc/trans/utf8_mac.$(OBJEXT): internal/globals.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/attribute.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/builtin.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/c_attribute.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/extension.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/feature.h +enc/trans/utf8_mac.$(OBJEXT): internal/has/warning.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/array.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/bignum.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/class.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/compar.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/complex.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/cont.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/dir.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/enum.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/enumerator.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/error.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/eval.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/file.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/gc.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/hash.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/io.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/load.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/marshal.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/numeric.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/object.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/parse.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/proc.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/process.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/random.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/range.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/sprintf.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/string.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/struct.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/thread.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/time.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/variable.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/vm.h +enc/trans/utf8_mac.$(OBJEXT): internal/interpreter.h +enc/trans/utf8_mac.$(OBJEXT): internal/iterator.h +enc/trans/utf8_mac.$(OBJEXT): internal/memory.h +enc/trans/utf8_mac.$(OBJEXT): internal/method.h +enc/trans/utf8_mac.$(OBJEXT): internal/module.h +enc/trans/utf8_mac.$(OBJEXT): internal/newobj.h +enc/trans/utf8_mac.$(OBJEXT): internal/rgengc.h +enc/trans/utf8_mac.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/utf8_mac.$(OBJEXT): internal/value.h +enc/trans/utf8_mac.$(OBJEXT): internal/value_type.h +enc/trans/utf8_mac.$(OBJEXT): internal/variable.h +enc/trans/utf8_mac.$(OBJEXT): internal/warning_push.h +enc/trans/utf8_mac.$(OBJEXT): internal/xmalloc.h enc/trans/utf8_mac.$(OBJEXT): missing.h enc/trans/utf8_mac.$(OBJEXT): st.h enc/trans/utf8_mac.$(OBJEXT): subst.h @@ -607,10 +5355,157 @@ enc/trans/utf_16_32.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/trans/utf_16_32.$(OBJEXT): $(top_srcdir)/transcode_data.h enc/trans/utf_16_32.$(OBJEXT): assert.h enc/trans/utf_16_32.$(OBJEXT): backward.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/assume.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/attributes.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/bool.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/inttypes.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/limits.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/long_long.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/stdalign.h +enc/trans/utf_16_32.$(OBJEXT): backward/2/stdarg.h enc/trans/utf_16_32.$(OBJEXT): config.h enc/trans/utf_16_32.$(OBJEXT): defines.h enc/trans/utf_16_32.$(OBJEXT): enc/trans/utf_16_32.c enc/trans/utf_16_32.$(OBJEXT): intern.h +enc/trans/utf_16_32.$(OBJEXT): internal/anyargs.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/char.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/double.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/fixnum.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/gid_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/int.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/long.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/long_long.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/mode_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/off_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/pid_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/short.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/size_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/uid_t.h +enc/trans/utf_16_32.$(OBJEXT): internal/assume.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/alloc_size.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/artificial.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/cold.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/const.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/constexpr.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/deprecated.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/diagnose_if.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/enum_extensibility.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/error.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/flag_enum.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/forceinline.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/format.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/maybe_unused.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/noalias.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/nodiscard.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/noexcept.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/noinline.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/nonnull.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/noreturn.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/pure.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/restrict.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/returns_nonnull.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/warning.h +enc/trans/utf_16_32.$(OBJEXT): internal/attr/weakref.h +enc/trans/utf_16_32.$(OBJEXT): internal/cast.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/apple.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/clang.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/gcc.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/intel.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/msvc.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/sunpro.h +enc/trans/utf_16_32.$(OBJEXT): internal/compiler_since.h +enc/trans/utf_16_32.$(OBJEXT): internal/config.h +enc/trans/utf_16_32.$(OBJEXT): internal/constant_p.h +enc/trans/utf_16_32.$(OBJEXT): internal/core.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rarray.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rbasic.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rbignum.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rclass.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rdata.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rfile.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rhash.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/robject.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rregexp.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rstring.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rstruct.h +enc/trans/utf_16_32.$(OBJEXT): internal/core/rtypeddata.h +enc/trans/utf_16_32.$(OBJEXT): internal/ctype.h +enc/trans/utf_16_32.$(OBJEXT): internal/dllexport.h +enc/trans/utf_16_32.$(OBJEXT): internal/dosish.h +enc/trans/utf_16_32.$(OBJEXT): internal/error.h +enc/trans/utf_16_32.$(OBJEXT): internal/eval.h +enc/trans/utf_16_32.$(OBJEXT): internal/event.h +enc/trans/utf_16_32.$(OBJEXT): internal/fl_type.h +enc/trans/utf_16_32.$(OBJEXT): internal/gc.h +enc/trans/utf_16_32.$(OBJEXT): internal/glob.h +enc/trans/utf_16_32.$(OBJEXT): internal/globals.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/attribute.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/builtin.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/c_attribute.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/cpp_attribute.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/declspec_attribute.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/extension.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/feature.h +enc/trans/utf_16_32.$(OBJEXT): internal/has/warning.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/array.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/bignum.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/class.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/compar.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/complex.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/cont.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/dir.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/enum.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/enumerator.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/error.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/eval.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/file.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/gc.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/hash.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/io.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/load.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/marshal.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/numeric.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/object.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/parse.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/proc.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/process.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/random.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/range.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/sprintf.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/string.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/struct.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/thread.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/time.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/variable.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/vm.h +enc/trans/utf_16_32.$(OBJEXT): internal/interpreter.h +enc/trans/utf_16_32.$(OBJEXT): internal/iterator.h +enc/trans/utf_16_32.$(OBJEXT): internal/memory.h +enc/trans/utf_16_32.$(OBJEXT): internal/method.h +enc/trans/utf_16_32.$(OBJEXT): internal/module.h +enc/trans/utf_16_32.$(OBJEXT): internal/newobj.h +enc/trans/utf_16_32.$(OBJEXT): internal/rgengc.h +enc/trans/utf_16_32.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/trans/utf_16_32.$(OBJEXT): internal/value.h +enc/trans/utf_16_32.$(OBJEXT): internal/value_type.h +enc/trans/utf_16_32.$(OBJEXT): internal/variable.h +enc/trans/utf_16_32.$(OBJEXT): internal/warning_push.h +enc/trans/utf_16_32.$(OBJEXT): internal/xmalloc.h enc/trans/utf_16_32.$(OBJEXT): missing.h enc/trans/utf_16_32.$(OBJEXT): st.h enc/trans/utf_16_32.$(OBJEXT): subst.h @@ -620,103 +5515,1115 @@ enc/unicode.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/unicode.$(OBJEXT): $(top_srcdir)/regenc.h enc/unicode.$(OBJEXT): $(top_srcdir)/regint.h enc/unicode.$(OBJEXT): assert.h +enc/unicode.$(OBJEXT): backward/2/assume.h +enc/unicode.$(OBJEXT): backward/2/attributes.h +enc/unicode.$(OBJEXT): backward/2/bool.h +enc/unicode.$(OBJEXT): backward/2/inttypes.h +enc/unicode.$(OBJEXT): backward/2/limits.h +enc/unicode.$(OBJEXT): backward/2/long_long.h +enc/unicode.$(OBJEXT): backward/2/stdalign.h +enc/unicode.$(OBJEXT): backward/2/stdarg.h enc/unicode.$(OBJEXT): config.h enc/unicode.$(OBJEXT): defines.h enc/unicode.$(OBJEXT): enc/unicode.c enc/unicode.$(OBJEXT): intern.h +enc/unicode.$(OBJEXT): internal/anyargs.h +enc/unicode.$(OBJEXT): internal/arithmetic.h +enc/unicode.$(OBJEXT): internal/arithmetic/char.h +enc/unicode.$(OBJEXT): internal/arithmetic/double.h +enc/unicode.$(OBJEXT): internal/arithmetic/fixnum.h +enc/unicode.$(OBJEXT): internal/arithmetic/gid_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/int.h +enc/unicode.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/long.h +enc/unicode.$(OBJEXT): internal/arithmetic/long_long.h +enc/unicode.$(OBJEXT): internal/arithmetic/mode_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/off_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/pid_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/short.h +enc/unicode.$(OBJEXT): internal/arithmetic/size_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/unicode.$(OBJEXT): internal/arithmetic/uid_t.h +enc/unicode.$(OBJEXT): internal/assume.h +enc/unicode.$(OBJEXT): internal/attr/alloc_size.h +enc/unicode.$(OBJEXT): internal/attr/artificial.h +enc/unicode.$(OBJEXT): internal/attr/cold.h +enc/unicode.$(OBJEXT): internal/attr/const.h +enc/unicode.$(OBJEXT): internal/attr/constexpr.h +enc/unicode.$(OBJEXT): internal/attr/deprecated.h +enc/unicode.$(OBJEXT): internal/attr/diagnose_if.h +enc/unicode.$(OBJEXT): internal/attr/enum_extensibility.h +enc/unicode.$(OBJEXT): internal/attr/error.h +enc/unicode.$(OBJEXT): internal/attr/flag_enum.h +enc/unicode.$(OBJEXT): internal/attr/forceinline.h +enc/unicode.$(OBJEXT): internal/attr/format.h +enc/unicode.$(OBJEXT): internal/attr/maybe_unused.h +enc/unicode.$(OBJEXT): internal/attr/noalias.h +enc/unicode.$(OBJEXT): internal/attr/nodiscard.h +enc/unicode.$(OBJEXT): internal/attr/noexcept.h +enc/unicode.$(OBJEXT): internal/attr/noinline.h +enc/unicode.$(OBJEXT): internal/attr/nonnull.h +enc/unicode.$(OBJEXT): internal/attr/noreturn.h +enc/unicode.$(OBJEXT): internal/attr/pure.h +enc/unicode.$(OBJEXT): internal/attr/restrict.h +enc/unicode.$(OBJEXT): internal/attr/returns_nonnull.h +enc/unicode.$(OBJEXT): internal/attr/warning.h +enc/unicode.$(OBJEXT): internal/attr/weakref.h +enc/unicode.$(OBJEXT): internal/cast.h +enc/unicode.$(OBJEXT): internal/compiler_is.h +enc/unicode.$(OBJEXT): internal/compiler_is/apple.h +enc/unicode.$(OBJEXT): internal/compiler_is/clang.h +enc/unicode.$(OBJEXT): internal/compiler_is/gcc.h +enc/unicode.$(OBJEXT): internal/compiler_is/intel.h +enc/unicode.$(OBJEXT): internal/compiler_is/msvc.h +enc/unicode.$(OBJEXT): internal/compiler_is/sunpro.h +enc/unicode.$(OBJEXT): internal/compiler_since.h +enc/unicode.$(OBJEXT): internal/config.h +enc/unicode.$(OBJEXT): internal/constant_p.h +enc/unicode.$(OBJEXT): internal/core.h +enc/unicode.$(OBJEXT): internal/core/rarray.h +enc/unicode.$(OBJEXT): internal/core/rbasic.h +enc/unicode.$(OBJEXT): internal/core/rbignum.h +enc/unicode.$(OBJEXT): internal/core/rclass.h +enc/unicode.$(OBJEXT): internal/core/rdata.h +enc/unicode.$(OBJEXT): internal/core/rfile.h +enc/unicode.$(OBJEXT): internal/core/rhash.h +enc/unicode.$(OBJEXT): internal/core/robject.h +enc/unicode.$(OBJEXT): internal/core/rregexp.h +enc/unicode.$(OBJEXT): internal/core/rstring.h +enc/unicode.$(OBJEXT): internal/core/rstruct.h +enc/unicode.$(OBJEXT): internal/core/rtypeddata.h +enc/unicode.$(OBJEXT): internal/ctype.h +enc/unicode.$(OBJEXT): internal/dllexport.h +enc/unicode.$(OBJEXT): internal/dosish.h +enc/unicode.$(OBJEXT): internal/error.h +enc/unicode.$(OBJEXT): internal/eval.h +enc/unicode.$(OBJEXT): internal/event.h +enc/unicode.$(OBJEXT): internal/fl_type.h +enc/unicode.$(OBJEXT): internal/gc.h +enc/unicode.$(OBJEXT): internal/glob.h +enc/unicode.$(OBJEXT): internal/globals.h +enc/unicode.$(OBJEXT): internal/has/attribute.h +enc/unicode.$(OBJEXT): internal/has/builtin.h +enc/unicode.$(OBJEXT): internal/has/c_attribute.h +enc/unicode.$(OBJEXT): internal/has/cpp_attribute.h +enc/unicode.$(OBJEXT): internal/has/declspec_attribute.h +enc/unicode.$(OBJEXT): internal/has/extension.h +enc/unicode.$(OBJEXT): internal/has/feature.h +enc/unicode.$(OBJEXT): internal/has/warning.h +enc/unicode.$(OBJEXT): internal/intern/array.h +enc/unicode.$(OBJEXT): internal/intern/bignum.h +enc/unicode.$(OBJEXT): internal/intern/class.h +enc/unicode.$(OBJEXT): internal/intern/compar.h +enc/unicode.$(OBJEXT): internal/intern/complex.h +enc/unicode.$(OBJEXT): internal/intern/cont.h +enc/unicode.$(OBJEXT): internal/intern/dir.h +enc/unicode.$(OBJEXT): internal/intern/enum.h +enc/unicode.$(OBJEXT): internal/intern/enumerator.h +enc/unicode.$(OBJEXT): internal/intern/error.h +enc/unicode.$(OBJEXT): internal/intern/eval.h +enc/unicode.$(OBJEXT): internal/intern/file.h +enc/unicode.$(OBJEXT): internal/intern/gc.h +enc/unicode.$(OBJEXT): internal/intern/hash.h +enc/unicode.$(OBJEXT): internal/intern/io.h +enc/unicode.$(OBJEXT): internal/intern/load.h +enc/unicode.$(OBJEXT): internal/intern/marshal.h +enc/unicode.$(OBJEXT): internal/intern/numeric.h +enc/unicode.$(OBJEXT): internal/intern/object.h +enc/unicode.$(OBJEXT): internal/intern/parse.h +enc/unicode.$(OBJEXT): internal/intern/proc.h +enc/unicode.$(OBJEXT): internal/intern/process.h +enc/unicode.$(OBJEXT): internal/intern/random.h +enc/unicode.$(OBJEXT): internal/intern/range.h +enc/unicode.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/unicode.$(OBJEXT): internal/intern/sprintf.h +enc/unicode.$(OBJEXT): internal/intern/string.h +enc/unicode.$(OBJEXT): internal/intern/struct.h +enc/unicode.$(OBJEXT): internal/intern/thread.h +enc/unicode.$(OBJEXT): internal/intern/time.h +enc/unicode.$(OBJEXT): internal/intern/variable.h +enc/unicode.$(OBJEXT): internal/intern/vm.h +enc/unicode.$(OBJEXT): internal/interpreter.h +enc/unicode.$(OBJEXT): internal/iterator.h +enc/unicode.$(OBJEXT): internal/memory.h +enc/unicode.$(OBJEXT): internal/method.h +enc/unicode.$(OBJEXT): internal/module.h +enc/unicode.$(OBJEXT): internal/newobj.h +enc/unicode.$(OBJEXT): internal/rgengc.h +enc/unicode.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/unicode.$(OBJEXT): internal/value.h +enc/unicode.$(OBJEXT): internal/value_type.h +enc/unicode.$(OBJEXT): internal/variable.h +enc/unicode.$(OBJEXT): internal/warning_push.h +enc/unicode.$(OBJEXT): internal/xmalloc.h enc/unicode.$(OBJEXT): missing.h enc/unicode.$(OBJEXT): onigmo.h enc/unicode.$(OBJEXT): st.h enc/unicode.$(OBJEXT): subst.h +enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/us_ascii.$(OBJEXT): $(top_srcdir)/encindex.h enc/us_ascii.$(OBJEXT): $(top_srcdir)/regenc.h +enc/us_ascii.$(OBJEXT): assert.h +enc/us_ascii.$(OBJEXT): backward/2/assume.h +enc/us_ascii.$(OBJEXT): backward/2/attributes.h +enc/us_ascii.$(OBJEXT): backward/2/bool.h +enc/us_ascii.$(OBJEXT): backward/2/inttypes.h +enc/us_ascii.$(OBJEXT): backward/2/limits.h +enc/us_ascii.$(OBJEXT): backward/2/long_long.h +enc/us_ascii.$(OBJEXT): backward/2/stdalign.h +enc/us_ascii.$(OBJEXT): backward/2/stdarg.h enc/us_ascii.$(OBJEXT): config.h enc/us_ascii.$(OBJEXT): defines.h enc/us_ascii.$(OBJEXT): enc/us_ascii.c +enc/us_ascii.$(OBJEXT): encoding.h +enc/us_ascii.$(OBJEXT): intern.h +enc/us_ascii.$(OBJEXT): internal/anyargs.h +enc/us_ascii.$(OBJEXT): internal/arithmetic.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/char.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/double.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/fixnum.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/gid_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/int.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/long.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/long_long.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/mode_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/off_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/pid_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/short.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/size_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/us_ascii.$(OBJEXT): internal/arithmetic/uid_t.h +enc/us_ascii.$(OBJEXT): internal/assume.h +enc/us_ascii.$(OBJEXT): internal/attr/alloc_size.h +enc/us_ascii.$(OBJEXT): internal/attr/artificial.h +enc/us_ascii.$(OBJEXT): internal/attr/cold.h +enc/us_ascii.$(OBJEXT): internal/attr/const.h +enc/us_ascii.$(OBJEXT): internal/attr/constexpr.h +enc/us_ascii.$(OBJEXT): internal/attr/deprecated.h +enc/us_ascii.$(OBJEXT): internal/attr/diagnose_if.h +enc/us_ascii.$(OBJEXT): internal/attr/enum_extensibility.h +enc/us_ascii.$(OBJEXT): internal/attr/error.h +enc/us_ascii.$(OBJEXT): internal/attr/flag_enum.h +enc/us_ascii.$(OBJEXT): internal/attr/forceinline.h +enc/us_ascii.$(OBJEXT): internal/attr/format.h +enc/us_ascii.$(OBJEXT): internal/attr/maybe_unused.h +enc/us_ascii.$(OBJEXT): internal/attr/noalias.h +enc/us_ascii.$(OBJEXT): internal/attr/nodiscard.h +enc/us_ascii.$(OBJEXT): internal/attr/noexcept.h +enc/us_ascii.$(OBJEXT): internal/attr/noinline.h +enc/us_ascii.$(OBJEXT): internal/attr/nonnull.h +enc/us_ascii.$(OBJEXT): internal/attr/noreturn.h +enc/us_ascii.$(OBJEXT): internal/attr/pure.h +enc/us_ascii.$(OBJEXT): internal/attr/restrict.h +enc/us_ascii.$(OBJEXT): internal/attr/returns_nonnull.h +enc/us_ascii.$(OBJEXT): internal/attr/warning.h +enc/us_ascii.$(OBJEXT): internal/attr/weakref.h +enc/us_ascii.$(OBJEXT): internal/cast.h +enc/us_ascii.$(OBJEXT): internal/compiler_is.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/apple.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/clang.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/gcc.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/intel.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/msvc.h +enc/us_ascii.$(OBJEXT): internal/compiler_is/sunpro.h +enc/us_ascii.$(OBJEXT): internal/compiler_since.h +enc/us_ascii.$(OBJEXT): internal/config.h +enc/us_ascii.$(OBJEXT): internal/constant_p.h +enc/us_ascii.$(OBJEXT): internal/core.h +enc/us_ascii.$(OBJEXT): internal/core/rarray.h +enc/us_ascii.$(OBJEXT): internal/core/rbasic.h +enc/us_ascii.$(OBJEXT): internal/core/rbignum.h +enc/us_ascii.$(OBJEXT): internal/core/rclass.h +enc/us_ascii.$(OBJEXT): internal/core/rdata.h +enc/us_ascii.$(OBJEXT): internal/core/rfile.h +enc/us_ascii.$(OBJEXT): internal/core/rhash.h +enc/us_ascii.$(OBJEXT): internal/core/robject.h +enc/us_ascii.$(OBJEXT): internal/core/rregexp.h +enc/us_ascii.$(OBJEXT): internal/core/rstring.h +enc/us_ascii.$(OBJEXT): internal/core/rstruct.h +enc/us_ascii.$(OBJEXT): internal/core/rtypeddata.h +enc/us_ascii.$(OBJEXT): internal/ctype.h +enc/us_ascii.$(OBJEXT): internal/dllexport.h +enc/us_ascii.$(OBJEXT): internal/dosish.h +enc/us_ascii.$(OBJEXT): internal/encoding/coderange.h +enc/us_ascii.$(OBJEXT): internal/encoding/ctype.h +enc/us_ascii.$(OBJEXT): internal/encoding/encoding.h +enc/us_ascii.$(OBJEXT): internal/encoding/pathname.h +enc/us_ascii.$(OBJEXT): internal/encoding/re.h +enc/us_ascii.$(OBJEXT): internal/encoding/sprintf.h +enc/us_ascii.$(OBJEXT): internal/encoding/string.h +enc/us_ascii.$(OBJEXT): internal/encoding/symbol.h +enc/us_ascii.$(OBJEXT): internal/encoding/transcode.h +enc/us_ascii.$(OBJEXT): internal/error.h +enc/us_ascii.$(OBJEXT): internal/eval.h +enc/us_ascii.$(OBJEXT): internal/event.h +enc/us_ascii.$(OBJEXT): internal/fl_type.h +enc/us_ascii.$(OBJEXT): internal/gc.h +enc/us_ascii.$(OBJEXT): internal/glob.h +enc/us_ascii.$(OBJEXT): internal/globals.h +enc/us_ascii.$(OBJEXT): internal/has/attribute.h +enc/us_ascii.$(OBJEXT): internal/has/builtin.h +enc/us_ascii.$(OBJEXT): internal/has/c_attribute.h +enc/us_ascii.$(OBJEXT): internal/has/cpp_attribute.h +enc/us_ascii.$(OBJEXT): internal/has/declspec_attribute.h +enc/us_ascii.$(OBJEXT): internal/has/extension.h +enc/us_ascii.$(OBJEXT): internal/has/feature.h +enc/us_ascii.$(OBJEXT): internal/has/warning.h +enc/us_ascii.$(OBJEXT): internal/intern/array.h +enc/us_ascii.$(OBJEXT): internal/intern/bignum.h +enc/us_ascii.$(OBJEXT): internal/intern/class.h +enc/us_ascii.$(OBJEXT): internal/intern/compar.h +enc/us_ascii.$(OBJEXT): internal/intern/complex.h +enc/us_ascii.$(OBJEXT): internal/intern/cont.h +enc/us_ascii.$(OBJEXT): internal/intern/dir.h +enc/us_ascii.$(OBJEXT): internal/intern/enum.h +enc/us_ascii.$(OBJEXT): internal/intern/enumerator.h +enc/us_ascii.$(OBJEXT): internal/intern/error.h +enc/us_ascii.$(OBJEXT): internal/intern/eval.h +enc/us_ascii.$(OBJEXT): internal/intern/file.h +enc/us_ascii.$(OBJEXT): internal/intern/gc.h +enc/us_ascii.$(OBJEXT): internal/intern/hash.h +enc/us_ascii.$(OBJEXT): internal/intern/io.h +enc/us_ascii.$(OBJEXT): internal/intern/load.h +enc/us_ascii.$(OBJEXT): internal/intern/marshal.h +enc/us_ascii.$(OBJEXT): internal/intern/numeric.h +enc/us_ascii.$(OBJEXT): internal/intern/object.h +enc/us_ascii.$(OBJEXT): internal/intern/parse.h +enc/us_ascii.$(OBJEXT): internal/intern/proc.h +enc/us_ascii.$(OBJEXT): internal/intern/process.h +enc/us_ascii.$(OBJEXT): internal/intern/random.h +enc/us_ascii.$(OBJEXT): internal/intern/range.h +enc/us_ascii.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/us_ascii.$(OBJEXT): internal/intern/sprintf.h +enc/us_ascii.$(OBJEXT): internal/intern/string.h +enc/us_ascii.$(OBJEXT): internal/intern/struct.h +enc/us_ascii.$(OBJEXT): internal/intern/thread.h +enc/us_ascii.$(OBJEXT): internal/intern/time.h +enc/us_ascii.$(OBJEXT): internal/intern/variable.h +enc/us_ascii.$(OBJEXT): internal/intern/vm.h +enc/us_ascii.$(OBJEXT): internal/interpreter.h +enc/us_ascii.$(OBJEXT): internal/iterator.h +enc/us_ascii.$(OBJEXT): internal/memory.h +enc/us_ascii.$(OBJEXT): internal/method.h +enc/us_ascii.$(OBJEXT): internal/module.h +enc/us_ascii.$(OBJEXT): internal/newobj.h +enc/us_ascii.$(OBJEXT): internal/rgengc.h +enc/us_ascii.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/us_ascii.$(OBJEXT): internal/value.h +enc/us_ascii.$(OBJEXT): internal/value_type.h +enc/us_ascii.$(OBJEXT): internal/variable.h +enc/us_ascii.$(OBJEXT): internal/warning_push.h +enc/us_ascii.$(OBJEXT): internal/xmalloc.h enc/us_ascii.$(OBJEXT): missing.h enc/us_ascii.$(OBJEXT): onigmo.h +enc/us_ascii.$(OBJEXT): oniguruma.h +enc/us_ascii.$(OBJEXT): st.h +enc/us_ascii.$(OBJEXT): subst.h enc/utf_16be.$(OBJEXT): $(top_srcdir)/regenc.h +enc/utf_16be.$(OBJEXT): assert.h +enc/utf_16be.$(OBJEXT): backward/2/assume.h +enc/utf_16be.$(OBJEXT): backward/2/attributes.h +enc/utf_16be.$(OBJEXT): backward/2/bool.h +enc/utf_16be.$(OBJEXT): backward/2/long_long.h +enc/utf_16be.$(OBJEXT): backward/2/stdalign.h +enc/utf_16be.$(OBJEXT): backward/2/stdarg.h enc/utf_16be.$(OBJEXT): config.h enc/utf_16be.$(OBJEXT): defines.h enc/utf_16be.$(OBJEXT): enc/iso_8859.h enc/utf_16be.$(OBJEXT): enc/utf_16be.c +enc/utf_16be.$(OBJEXT): internal/assume.h +enc/utf_16be.$(OBJEXT): internal/attr/alloc_size.h +enc/utf_16be.$(OBJEXT): internal/attr/cold.h +enc/utf_16be.$(OBJEXT): internal/attr/const.h +enc/utf_16be.$(OBJEXT): internal/attr/deprecated.h +enc/utf_16be.$(OBJEXT): internal/attr/error.h +enc/utf_16be.$(OBJEXT): internal/attr/forceinline.h +enc/utf_16be.$(OBJEXT): internal/attr/format.h +enc/utf_16be.$(OBJEXT): internal/attr/maybe_unused.h +enc/utf_16be.$(OBJEXT): internal/attr/nodiscard.h +enc/utf_16be.$(OBJEXT): internal/attr/noexcept.h +enc/utf_16be.$(OBJEXT): internal/attr/noinline.h +enc/utf_16be.$(OBJEXT): internal/attr/nonnull.h +enc/utf_16be.$(OBJEXT): internal/attr/noreturn.h +enc/utf_16be.$(OBJEXT): internal/attr/pure.h +enc/utf_16be.$(OBJEXT): internal/attr/restrict.h +enc/utf_16be.$(OBJEXT): internal/attr/returns_nonnull.h +enc/utf_16be.$(OBJEXT): internal/attr/warning.h +enc/utf_16be.$(OBJEXT): internal/cast.h +enc/utf_16be.$(OBJEXT): internal/compiler_is.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/apple.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/clang.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/gcc.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/intel.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/msvc.h +enc/utf_16be.$(OBJEXT): internal/compiler_is/sunpro.h +enc/utf_16be.$(OBJEXT): internal/compiler_since.h +enc/utf_16be.$(OBJEXT): internal/config.h +enc/utf_16be.$(OBJEXT): internal/dllexport.h +enc/utf_16be.$(OBJEXT): internal/dosish.h +enc/utf_16be.$(OBJEXT): internal/has/attribute.h +enc/utf_16be.$(OBJEXT): internal/has/builtin.h +enc/utf_16be.$(OBJEXT): internal/has/c_attribute.h +enc/utf_16be.$(OBJEXT): internal/has/cpp_attribute.h +enc/utf_16be.$(OBJEXT): internal/has/declspec_attribute.h +enc/utf_16be.$(OBJEXT): internal/has/extension.h +enc/utf_16be.$(OBJEXT): internal/has/feature.h +enc/utf_16be.$(OBJEXT): internal/has/warning.h +enc/utf_16be.$(OBJEXT): internal/stdalign.h +enc/utf_16be.$(OBJEXT): internal/stdbool.h +enc/utf_16be.$(OBJEXT): internal/warning_push.h +enc/utf_16be.$(OBJEXT): internal/xmalloc.h enc/utf_16be.$(OBJEXT): missing.h enc/utf_16be.$(OBJEXT): onigmo.h enc/utf_16le.$(OBJEXT): $(top_srcdir)/regenc.h +enc/utf_16le.$(OBJEXT): assert.h +enc/utf_16le.$(OBJEXT): backward/2/assume.h +enc/utf_16le.$(OBJEXT): backward/2/attributes.h +enc/utf_16le.$(OBJEXT): backward/2/bool.h +enc/utf_16le.$(OBJEXT): backward/2/long_long.h +enc/utf_16le.$(OBJEXT): backward/2/stdalign.h +enc/utf_16le.$(OBJEXT): backward/2/stdarg.h enc/utf_16le.$(OBJEXT): config.h enc/utf_16le.$(OBJEXT): defines.h enc/utf_16le.$(OBJEXT): enc/iso_8859.h enc/utf_16le.$(OBJEXT): enc/utf_16le.c +enc/utf_16le.$(OBJEXT): internal/assume.h +enc/utf_16le.$(OBJEXT): internal/attr/alloc_size.h +enc/utf_16le.$(OBJEXT): internal/attr/cold.h +enc/utf_16le.$(OBJEXT): internal/attr/const.h +enc/utf_16le.$(OBJEXT): internal/attr/deprecated.h +enc/utf_16le.$(OBJEXT): internal/attr/error.h +enc/utf_16le.$(OBJEXT): internal/attr/forceinline.h +enc/utf_16le.$(OBJEXT): internal/attr/format.h +enc/utf_16le.$(OBJEXT): internal/attr/maybe_unused.h +enc/utf_16le.$(OBJEXT): internal/attr/nodiscard.h +enc/utf_16le.$(OBJEXT): internal/attr/noexcept.h +enc/utf_16le.$(OBJEXT): internal/attr/noinline.h +enc/utf_16le.$(OBJEXT): internal/attr/nonnull.h +enc/utf_16le.$(OBJEXT): internal/attr/noreturn.h +enc/utf_16le.$(OBJEXT): internal/attr/pure.h +enc/utf_16le.$(OBJEXT): internal/attr/restrict.h +enc/utf_16le.$(OBJEXT): internal/attr/returns_nonnull.h +enc/utf_16le.$(OBJEXT): internal/attr/warning.h +enc/utf_16le.$(OBJEXT): internal/cast.h +enc/utf_16le.$(OBJEXT): internal/compiler_is.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/apple.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/clang.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/gcc.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/intel.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/msvc.h +enc/utf_16le.$(OBJEXT): internal/compiler_is/sunpro.h +enc/utf_16le.$(OBJEXT): internal/compiler_since.h +enc/utf_16le.$(OBJEXT): internal/config.h +enc/utf_16le.$(OBJEXT): internal/dllexport.h +enc/utf_16le.$(OBJEXT): internal/dosish.h +enc/utf_16le.$(OBJEXT): internal/has/attribute.h +enc/utf_16le.$(OBJEXT): internal/has/builtin.h +enc/utf_16le.$(OBJEXT): internal/has/c_attribute.h +enc/utf_16le.$(OBJEXT): internal/has/cpp_attribute.h +enc/utf_16le.$(OBJEXT): internal/has/declspec_attribute.h +enc/utf_16le.$(OBJEXT): internal/has/extension.h +enc/utf_16le.$(OBJEXT): internal/has/feature.h +enc/utf_16le.$(OBJEXT): internal/has/warning.h +enc/utf_16le.$(OBJEXT): internal/stdalign.h +enc/utf_16le.$(OBJEXT): internal/stdbool.h +enc/utf_16le.$(OBJEXT): internal/warning_push.h +enc/utf_16le.$(OBJEXT): internal/xmalloc.h enc/utf_16le.$(OBJEXT): missing.h enc/utf_16le.$(OBJEXT): onigmo.h enc/utf_32be.$(OBJEXT): $(top_srcdir)/regenc.h +enc/utf_32be.$(OBJEXT): assert.h +enc/utf_32be.$(OBJEXT): backward/2/assume.h +enc/utf_32be.$(OBJEXT): backward/2/attributes.h +enc/utf_32be.$(OBJEXT): backward/2/bool.h +enc/utf_32be.$(OBJEXT): backward/2/long_long.h +enc/utf_32be.$(OBJEXT): backward/2/stdalign.h +enc/utf_32be.$(OBJEXT): backward/2/stdarg.h enc/utf_32be.$(OBJEXT): config.h enc/utf_32be.$(OBJEXT): defines.h enc/utf_32be.$(OBJEXT): enc/iso_8859.h enc/utf_32be.$(OBJEXT): enc/utf_32be.c +enc/utf_32be.$(OBJEXT): internal/assume.h +enc/utf_32be.$(OBJEXT): internal/attr/alloc_size.h +enc/utf_32be.$(OBJEXT): internal/attr/cold.h +enc/utf_32be.$(OBJEXT): internal/attr/const.h +enc/utf_32be.$(OBJEXT): internal/attr/deprecated.h +enc/utf_32be.$(OBJEXT): internal/attr/error.h +enc/utf_32be.$(OBJEXT): internal/attr/forceinline.h +enc/utf_32be.$(OBJEXT): internal/attr/format.h +enc/utf_32be.$(OBJEXT): internal/attr/maybe_unused.h +enc/utf_32be.$(OBJEXT): internal/attr/nodiscard.h +enc/utf_32be.$(OBJEXT): internal/attr/noexcept.h +enc/utf_32be.$(OBJEXT): internal/attr/noinline.h +enc/utf_32be.$(OBJEXT): internal/attr/nonnull.h +enc/utf_32be.$(OBJEXT): internal/attr/noreturn.h +enc/utf_32be.$(OBJEXT): internal/attr/pure.h +enc/utf_32be.$(OBJEXT): internal/attr/restrict.h +enc/utf_32be.$(OBJEXT): internal/attr/returns_nonnull.h +enc/utf_32be.$(OBJEXT): internal/attr/warning.h +enc/utf_32be.$(OBJEXT): internal/cast.h +enc/utf_32be.$(OBJEXT): internal/compiler_is.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/apple.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/clang.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/gcc.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/intel.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/msvc.h +enc/utf_32be.$(OBJEXT): internal/compiler_is/sunpro.h +enc/utf_32be.$(OBJEXT): internal/compiler_since.h +enc/utf_32be.$(OBJEXT): internal/config.h +enc/utf_32be.$(OBJEXT): internal/dllexport.h +enc/utf_32be.$(OBJEXT): internal/dosish.h +enc/utf_32be.$(OBJEXT): internal/has/attribute.h +enc/utf_32be.$(OBJEXT): internal/has/builtin.h +enc/utf_32be.$(OBJEXT): internal/has/c_attribute.h +enc/utf_32be.$(OBJEXT): internal/has/cpp_attribute.h +enc/utf_32be.$(OBJEXT): internal/has/declspec_attribute.h +enc/utf_32be.$(OBJEXT): internal/has/extension.h +enc/utf_32be.$(OBJEXT): internal/has/feature.h +enc/utf_32be.$(OBJEXT): internal/has/warning.h +enc/utf_32be.$(OBJEXT): internal/stdalign.h +enc/utf_32be.$(OBJEXT): internal/stdbool.h +enc/utf_32be.$(OBJEXT): internal/warning_push.h +enc/utf_32be.$(OBJEXT): internal/xmalloc.h enc/utf_32be.$(OBJEXT): missing.h enc/utf_32be.$(OBJEXT): onigmo.h enc/utf_32le.$(OBJEXT): $(top_srcdir)/regenc.h +enc/utf_32le.$(OBJEXT): assert.h +enc/utf_32le.$(OBJEXT): backward/2/assume.h +enc/utf_32le.$(OBJEXT): backward/2/attributes.h +enc/utf_32le.$(OBJEXT): backward/2/bool.h +enc/utf_32le.$(OBJEXT): backward/2/long_long.h +enc/utf_32le.$(OBJEXT): backward/2/stdalign.h +enc/utf_32le.$(OBJEXT): backward/2/stdarg.h enc/utf_32le.$(OBJEXT): config.h enc/utf_32le.$(OBJEXT): defines.h enc/utf_32le.$(OBJEXT): enc/iso_8859.h enc/utf_32le.$(OBJEXT): enc/utf_32le.c +enc/utf_32le.$(OBJEXT): internal/assume.h +enc/utf_32le.$(OBJEXT): internal/attr/alloc_size.h +enc/utf_32le.$(OBJEXT): internal/attr/cold.h +enc/utf_32le.$(OBJEXT): internal/attr/const.h +enc/utf_32le.$(OBJEXT): internal/attr/deprecated.h +enc/utf_32le.$(OBJEXT): internal/attr/error.h +enc/utf_32le.$(OBJEXT): internal/attr/forceinline.h +enc/utf_32le.$(OBJEXT): internal/attr/format.h +enc/utf_32le.$(OBJEXT): internal/attr/maybe_unused.h +enc/utf_32le.$(OBJEXT): internal/attr/nodiscard.h +enc/utf_32le.$(OBJEXT): internal/attr/noexcept.h +enc/utf_32le.$(OBJEXT): internal/attr/noinline.h +enc/utf_32le.$(OBJEXT): internal/attr/nonnull.h +enc/utf_32le.$(OBJEXT): internal/attr/noreturn.h +enc/utf_32le.$(OBJEXT): internal/attr/pure.h +enc/utf_32le.$(OBJEXT): internal/attr/restrict.h +enc/utf_32le.$(OBJEXT): internal/attr/returns_nonnull.h +enc/utf_32le.$(OBJEXT): internal/attr/warning.h +enc/utf_32le.$(OBJEXT): internal/cast.h +enc/utf_32le.$(OBJEXT): internal/compiler_is.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/apple.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/clang.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/gcc.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/intel.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/msvc.h +enc/utf_32le.$(OBJEXT): internal/compiler_is/sunpro.h +enc/utf_32le.$(OBJEXT): internal/compiler_since.h +enc/utf_32le.$(OBJEXT): internal/config.h +enc/utf_32le.$(OBJEXT): internal/dllexport.h +enc/utf_32le.$(OBJEXT): internal/dosish.h +enc/utf_32le.$(OBJEXT): internal/has/attribute.h +enc/utf_32le.$(OBJEXT): internal/has/builtin.h +enc/utf_32le.$(OBJEXT): internal/has/c_attribute.h +enc/utf_32le.$(OBJEXT): internal/has/cpp_attribute.h +enc/utf_32le.$(OBJEXT): internal/has/declspec_attribute.h +enc/utf_32le.$(OBJEXT): internal/has/extension.h +enc/utf_32le.$(OBJEXT): internal/has/feature.h +enc/utf_32le.$(OBJEXT): internal/has/warning.h +enc/utf_32le.$(OBJEXT): internal/stdalign.h +enc/utf_32le.$(OBJEXT): internal/stdbool.h +enc/utf_32le.$(OBJEXT): internal/warning_push.h +enc/utf_32le.$(OBJEXT): internal/xmalloc.h enc/utf_32le.$(OBJEXT): missing.h enc/utf_32le.$(OBJEXT): onigmo.h +enc/utf_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h enc/utf_8.$(OBJEXT): $(top_srcdir)/encindex.h enc/utf_8.$(OBJEXT): $(top_srcdir)/regenc.h +enc/utf_8.$(OBJEXT): assert.h +enc/utf_8.$(OBJEXT): backward/2/assume.h +enc/utf_8.$(OBJEXT): backward/2/attributes.h +enc/utf_8.$(OBJEXT): backward/2/bool.h +enc/utf_8.$(OBJEXT): backward/2/inttypes.h +enc/utf_8.$(OBJEXT): backward/2/limits.h +enc/utf_8.$(OBJEXT): backward/2/long_long.h +enc/utf_8.$(OBJEXT): backward/2/stdalign.h +enc/utf_8.$(OBJEXT): backward/2/stdarg.h enc/utf_8.$(OBJEXT): config.h enc/utf_8.$(OBJEXT): defines.h enc/utf_8.$(OBJEXT): enc/utf_8.c +enc/utf_8.$(OBJEXT): encoding.h +enc/utf_8.$(OBJEXT): intern.h +enc/utf_8.$(OBJEXT): internal/anyargs.h +enc/utf_8.$(OBJEXT): internal/arithmetic.h +enc/utf_8.$(OBJEXT): internal/arithmetic/char.h +enc/utf_8.$(OBJEXT): internal/arithmetic/double.h +enc/utf_8.$(OBJEXT): internal/arithmetic/fixnum.h +enc/utf_8.$(OBJEXT): internal/arithmetic/gid_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/int.h +enc/utf_8.$(OBJEXT): internal/arithmetic/intptr_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/long.h +enc/utf_8.$(OBJEXT): internal/arithmetic/long_long.h +enc/utf_8.$(OBJEXT): internal/arithmetic/mode_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/off_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/pid_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/short.h +enc/utf_8.$(OBJEXT): internal/arithmetic/size_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/st_data_t.h +enc/utf_8.$(OBJEXT): internal/arithmetic/uid_t.h +enc/utf_8.$(OBJEXT): internal/assume.h +enc/utf_8.$(OBJEXT): internal/attr/alloc_size.h +enc/utf_8.$(OBJEXT): internal/attr/artificial.h +enc/utf_8.$(OBJEXT): internal/attr/cold.h +enc/utf_8.$(OBJEXT): internal/attr/const.h +enc/utf_8.$(OBJEXT): internal/attr/constexpr.h +enc/utf_8.$(OBJEXT): internal/attr/deprecated.h +enc/utf_8.$(OBJEXT): internal/attr/diagnose_if.h +enc/utf_8.$(OBJEXT): internal/attr/enum_extensibility.h +enc/utf_8.$(OBJEXT): internal/attr/error.h +enc/utf_8.$(OBJEXT): internal/attr/flag_enum.h +enc/utf_8.$(OBJEXT): internal/attr/forceinline.h +enc/utf_8.$(OBJEXT): internal/attr/format.h +enc/utf_8.$(OBJEXT): internal/attr/maybe_unused.h +enc/utf_8.$(OBJEXT): internal/attr/noalias.h +enc/utf_8.$(OBJEXT): internal/attr/nodiscard.h +enc/utf_8.$(OBJEXT): internal/attr/noexcept.h +enc/utf_8.$(OBJEXT): internal/attr/noinline.h +enc/utf_8.$(OBJEXT): internal/attr/nonnull.h +enc/utf_8.$(OBJEXT): internal/attr/noreturn.h +enc/utf_8.$(OBJEXT): internal/attr/pure.h +enc/utf_8.$(OBJEXT): internal/attr/restrict.h +enc/utf_8.$(OBJEXT): internal/attr/returns_nonnull.h +enc/utf_8.$(OBJEXT): internal/attr/warning.h +enc/utf_8.$(OBJEXT): internal/attr/weakref.h +enc/utf_8.$(OBJEXT): internal/cast.h +enc/utf_8.$(OBJEXT): internal/compiler_is.h +enc/utf_8.$(OBJEXT): internal/compiler_is/apple.h +enc/utf_8.$(OBJEXT): internal/compiler_is/clang.h +enc/utf_8.$(OBJEXT): internal/compiler_is/gcc.h +enc/utf_8.$(OBJEXT): internal/compiler_is/intel.h +enc/utf_8.$(OBJEXT): internal/compiler_is/msvc.h +enc/utf_8.$(OBJEXT): internal/compiler_is/sunpro.h +enc/utf_8.$(OBJEXT): internal/compiler_since.h +enc/utf_8.$(OBJEXT): internal/config.h +enc/utf_8.$(OBJEXT): internal/constant_p.h +enc/utf_8.$(OBJEXT): internal/core.h +enc/utf_8.$(OBJEXT): internal/core/rarray.h +enc/utf_8.$(OBJEXT): internal/core/rbasic.h +enc/utf_8.$(OBJEXT): internal/core/rbignum.h +enc/utf_8.$(OBJEXT): internal/core/rclass.h +enc/utf_8.$(OBJEXT): internal/core/rdata.h +enc/utf_8.$(OBJEXT): internal/core/rfile.h +enc/utf_8.$(OBJEXT): internal/core/rhash.h +enc/utf_8.$(OBJEXT): internal/core/robject.h +enc/utf_8.$(OBJEXT): internal/core/rregexp.h +enc/utf_8.$(OBJEXT): internal/core/rstring.h +enc/utf_8.$(OBJEXT): internal/core/rstruct.h +enc/utf_8.$(OBJEXT): internal/core/rtypeddata.h +enc/utf_8.$(OBJEXT): internal/ctype.h +enc/utf_8.$(OBJEXT): internal/dllexport.h +enc/utf_8.$(OBJEXT): internal/dosish.h +enc/utf_8.$(OBJEXT): internal/encoding/coderange.h +enc/utf_8.$(OBJEXT): internal/encoding/ctype.h +enc/utf_8.$(OBJEXT): internal/encoding/encoding.h +enc/utf_8.$(OBJEXT): internal/encoding/pathname.h +enc/utf_8.$(OBJEXT): internal/encoding/re.h +enc/utf_8.$(OBJEXT): internal/encoding/sprintf.h +enc/utf_8.$(OBJEXT): internal/encoding/string.h +enc/utf_8.$(OBJEXT): internal/encoding/symbol.h +enc/utf_8.$(OBJEXT): internal/encoding/transcode.h +enc/utf_8.$(OBJEXT): internal/error.h +enc/utf_8.$(OBJEXT): internal/eval.h +enc/utf_8.$(OBJEXT): internal/event.h +enc/utf_8.$(OBJEXT): internal/fl_type.h +enc/utf_8.$(OBJEXT): internal/gc.h +enc/utf_8.$(OBJEXT): internal/glob.h +enc/utf_8.$(OBJEXT): internal/globals.h +enc/utf_8.$(OBJEXT): internal/has/attribute.h +enc/utf_8.$(OBJEXT): internal/has/builtin.h +enc/utf_8.$(OBJEXT): internal/has/c_attribute.h +enc/utf_8.$(OBJEXT): internal/has/cpp_attribute.h +enc/utf_8.$(OBJEXT): internal/has/declspec_attribute.h +enc/utf_8.$(OBJEXT): internal/has/extension.h +enc/utf_8.$(OBJEXT): internal/has/feature.h +enc/utf_8.$(OBJEXT): internal/has/warning.h +enc/utf_8.$(OBJEXT): internal/intern/array.h +enc/utf_8.$(OBJEXT): internal/intern/bignum.h +enc/utf_8.$(OBJEXT): internal/intern/class.h +enc/utf_8.$(OBJEXT): internal/intern/compar.h +enc/utf_8.$(OBJEXT): internal/intern/complex.h +enc/utf_8.$(OBJEXT): internal/intern/cont.h +enc/utf_8.$(OBJEXT): internal/intern/dir.h +enc/utf_8.$(OBJEXT): internal/intern/enum.h +enc/utf_8.$(OBJEXT): internal/intern/enumerator.h +enc/utf_8.$(OBJEXT): internal/intern/error.h +enc/utf_8.$(OBJEXT): internal/intern/eval.h +enc/utf_8.$(OBJEXT): internal/intern/file.h +enc/utf_8.$(OBJEXT): internal/intern/gc.h +enc/utf_8.$(OBJEXT): internal/intern/hash.h +enc/utf_8.$(OBJEXT): internal/intern/io.h +enc/utf_8.$(OBJEXT): internal/intern/load.h +enc/utf_8.$(OBJEXT): internal/intern/marshal.h +enc/utf_8.$(OBJEXT): internal/intern/numeric.h +enc/utf_8.$(OBJEXT): internal/intern/object.h +enc/utf_8.$(OBJEXT): internal/intern/parse.h +enc/utf_8.$(OBJEXT): internal/intern/proc.h +enc/utf_8.$(OBJEXT): internal/intern/process.h +enc/utf_8.$(OBJEXT): internal/intern/random.h +enc/utf_8.$(OBJEXT): internal/intern/range.h +enc/utf_8.$(OBJEXT): internal/intern/rational.h +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/signal.h +enc/utf_8.$(OBJEXT): internal/intern/sprintf.h +enc/utf_8.$(OBJEXT): internal/intern/string.h +enc/utf_8.$(OBJEXT): internal/intern/struct.h +enc/utf_8.$(OBJEXT): internal/intern/thread.h +enc/utf_8.$(OBJEXT): internal/intern/time.h +enc/utf_8.$(OBJEXT): internal/intern/variable.h +enc/utf_8.$(OBJEXT): internal/intern/vm.h +enc/utf_8.$(OBJEXT): internal/interpreter.h +enc/utf_8.$(OBJEXT): internal/iterator.h +enc/utf_8.$(OBJEXT): internal/memory.h +enc/utf_8.$(OBJEXT): internal/method.h +enc/utf_8.$(OBJEXT): internal/module.h +enc/utf_8.$(OBJEXT): internal/newobj.h +enc/utf_8.$(OBJEXT): internal/rgengc.h +enc/utf_8.$(OBJEXT): internal/scan_args.h +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/symbol.h +enc/utf_8.$(OBJEXT): internal/value.h +enc/utf_8.$(OBJEXT): internal/value_type.h +enc/utf_8.$(OBJEXT): internal/variable.h +enc/utf_8.$(OBJEXT): internal/warning_push.h +enc/utf_8.$(OBJEXT): internal/xmalloc.h enc/utf_8.$(OBJEXT): missing.h enc/utf_8.$(OBJEXT): onigmo.h +enc/utf_8.$(OBJEXT): oniguruma.h +enc/utf_8.$(OBJEXT): st.h +enc/utf_8.$(OBJEXT): subst.h enc/windows_1250.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1250.$(OBJEXT): assert.h +enc/windows_1250.$(OBJEXT): backward/2/assume.h +enc/windows_1250.$(OBJEXT): backward/2/attributes.h +enc/windows_1250.$(OBJEXT): backward/2/bool.h +enc/windows_1250.$(OBJEXT): backward/2/long_long.h +enc/windows_1250.$(OBJEXT): backward/2/stdalign.h +enc/windows_1250.$(OBJEXT): backward/2/stdarg.h enc/windows_1250.$(OBJEXT): config.h enc/windows_1250.$(OBJEXT): defines.h enc/windows_1250.$(OBJEXT): enc/iso_8859.h enc/windows_1250.$(OBJEXT): enc/windows_1250.c +enc/windows_1250.$(OBJEXT): internal/assume.h +enc/windows_1250.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1250.$(OBJEXT): internal/attr/cold.h +enc/windows_1250.$(OBJEXT): internal/attr/const.h +enc/windows_1250.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1250.$(OBJEXT): internal/attr/error.h +enc/windows_1250.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1250.$(OBJEXT): internal/attr/format.h +enc/windows_1250.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1250.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1250.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1250.$(OBJEXT): internal/attr/noinline.h +enc/windows_1250.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1250.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1250.$(OBJEXT): internal/attr/pure.h +enc/windows_1250.$(OBJEXT): internal/attr/restrict.h +enc/windows_1250.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1250.$(OBJEXT): internal/attr/warning.h +enc/windows_1250.$(OBJEXT): internal/cast.h +enc/windows_1250.$(OBJEXT): internal/compiler_is.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1250.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1250.$(OBJEXT): internal/compiler_since.h +enc/windows_1250.$(OBJEXT): internal/config.h +enc/windows_1250.$(OBJEXT): internal/dllexport.h +enc/windows_1250.$(OBJEXT): internal/dosish.h +enc/windows_1250.$(OBJEXT): internal/has/attribute.h +enc/windows_1250.$(OBJEXT): internal/has/builtin.h +enc/windows_1250.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1250.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1250.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1250.$(OBJEXT): internal/has/extension.h +enc/windows_1250.$(OBJEXT): internal/has/feature.h +enc/windows_1250.$(OBJEXT): internal/has/warning.h +enc/windows_1250.$(OBJEXT): internal/stdalign.h +enc/windows_1250.$(OBJEXT): internal/stdbool.h +enc/windows_1250.$(OBJEXT): internal/warning_push.h +enc/windows_1250.$(OBJEXT): internal/xmalloc.h enc/windows_1250.$(OBJEXT): missing.h enc/windows_1250.$(OBJEXT): onigmo.h enc/windows_1251.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1251.$(OBJEXT): assert.h +enc/windows_1251.$(OBJEXT): backward/2/assume.h +enc/windows_1251.$(OBJEXT): backward/2/attributes.h +enc/windows_1251.$(OBJEXT): backward/2/bool.h +enc/windows_1251.$(OBJEXT): backward/2/long_long.h +enc/windows_1251.$(OBJEXT): backward/2/stdalign.h +enc/windows_1251.$(OBJEXT): backward/2/stdarg.h enc/windows_1251.$(OBJEXT): config.h enc/windows_1251.$(OBJEXT): defines.h enc/windows_1251.$(OBJEXT): enc/windows_1251.c +enc/windows_1251.$(OBJEXT): internal/assume.h +enc/windows_1251.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1251.$(OBJEXT): internal/attr/cold.h +enc/windows_1251.$(OBJEXT): internal/attr/const.h +enc/windows_1251.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1251.$(OBJEXT): internal/attr/error.h +enc/windows_1251.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1251.$(OBJEXT): internal/attr/format.h +enc/windows_1251.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1251.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1251.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1251.$(OBJEXT): internal/attr/noinline.h +enc/windows_1251.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1251.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1251.$(OBJEXT): internal/attr/pure.h +enc/windows_1251.$(OBJEXT): internal/attr/restrict.h +enc/windows_1251.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1251.$(OBJEXT): internal/attr/warning.h +enc/windows_1251.$(OBJEXT): internal/cast.h +enc/windows_1251.$(OBJEXT): internal/compiler_is.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1251.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1251.$(OBJEXT): internal/compiler_since.h +enc/windows_1251.$(OBJEXT): internal/config.h +enc/windows_1251.$(OBJEXT): internal/dllexport.h +enc/windows_1251.$(OBJEXT): internal/dosish.h +enc/windows_1251.$(OBJEXT): internal/has/attribute.h +enc/windows_1251.$(OBJEXT): internal/has/builtin.h +enc/windows_1251.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1251.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1251.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1251.$(OBJEXT): internal/has/extension.h +enc/windows_1251.$(OBJEXT): internal/has/feature.h +enc/windows_1251.$(OBJEXT): internal/has/warning.h +enc/windows_1251.$(OBJEXT): internal/stdalign.h +enc/windows_1251.$(OBJEXT): internal/stdbool.h +enc/windows_1251.$(OBJEXT): internal/warning_push.h +enc/windows_1251.$(OBJEXT): internal/xmalloc.h enc/windows_1251.$(OBJEXT): missing.h enc/windows_1251.$(OBJEXT): onigmo.h enc/windows_1252.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1252.$(OBJEXT): assert.h +enc/windows_1252.$(OBJEXT): backward/2/assume.h +enc/windows_1252.$(OBJEXT): backward/2/attributes.h +enc/windows_1252.$(OBJEXT): backward/2/bool.h +enc/windows_1252.$(OBJEXT): backward/2/long_long.h +enc/windows_1252.$(OBJEXT): backward/2/stdalign.h +enc/windows_1252.$(OBJEXT): backward/2/stdarg.h enc/windows_1252.$(OBJEXT): config.h enc/windows_1252.$(OBJEXT): defines.h enc/windows_1252.$(OBJEXT): enc/iso_8859.h enc/windows_1252.$(OBJEXT): enc/windows_1252.c +enc/windows_1252.$(OBJEXT): internal/assume.h +enc/windows_1252.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1252.$(OBJEXT): internal/attr/cold.h +enc/windows_1252.$(OBJEXT): internal/attr/const.h +enc/windows_1252.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1252.$(OBJEXT): internal/attr/error.h +enc/windows_1252.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1252.$(OBJEXT): internal/attr/format.h +enc/windows_1252.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1252.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1252.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1252.$(OBJEXT): internal/attr/noinline.h +enc/windows_1252.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1252.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1252.$(OBJEXT): internal/attr/pure.h +enc/windows_1252.$(OBJEXT): internal/attr/restrict.h +enc/windows_1252.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1252.$(OBJEXT): internal/attr/warning.h +enc/windows_1252.$(OBJEXT): internal/cast.h +enc/windows_1252.$(OBJEXT): internal/compiler_is.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1252.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1252.$(OBJEXT): internal/compiler_since.h +enc/windows_1252.$(OBJEXT): internal/config.h +enc/windows_1252.$(OBJEXT): internal/dllexport.h +enc/windows_1252.$(OBJEXT): internal/dosish.h +enc/windows_1252.$(OBJEXT): internal/has/attribute.h +enc/windows_1252.$(OBJEXT): internal/has/builtin.h +enc/windows_1252.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1252.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1252.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1252.$(OBJEXT): internal/has/extension.h +enc/windows_1252.$(OBJEXT): internal/has/feature.h +enc/windows_1252.$(OBJEXT): internal/has/warning.h +enc/windows_1252.$(OBJEXT): internal/stdalign.h +enc/windows_1252.$(OBJEXT): internal/stdbool.h +enc/windows_1252.$(OBJEXT): internal/warning_push.h +enc/windows_1252.$(OBJEXT): internal/xmalloc.h enc/windows_1252.$(OBJEXT): missing.h enc/windows_1252.$(OBJEXT): onigmo.h enc/windows_1253.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1253.$(OBJEXT): assert.h +enc/windows_1253.$(OBJEXT): backward/2/assume.h +enc/windows_1253.$(OBJEXT): backward/2/attributes.h +enc/windows_1253.$(OBJEXT): backward/2/bool.h +enc/windows_1253.$(OBJEXT): backward/2/long_long.h +enc/windows_1253.$(OBJEXT): backward/2/stdalign.h +enc/windows_1253.$(OBJEXT): backward/2/stdarg.h enc/windows_1253.$(OBJEXT): config.h enc/windows_1253.$(OBJEXT): defines.h enc/windows_1253.$(OBJEXT): enc/windows_1253.c +enc/windows_1253.$(OBJEXT): internal/assume.h +enc/windows_1253.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1253.$(OBJEXT): internal/attr/cold.h +enc/windows_1253.$(OBJEXT): internal/attr/const.h +enc/windows_1253.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1253.$(OBJEXT): internal/attr/error.h +enc/windows_1253.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1253.$(OBJEXT): internal/attr/format.h +enc/windows_1253.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1253.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1253.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1253.$(OBJEXT): internal/attr/noinline.h +enc/windows_1253.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1253.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1253.$(OBJEXT): internal/attr/pure.h +enc/windows_1253.$(OBJEXT): internal/attr/restrict.h +enc/windows_1253.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1253.$(OBJEXT): internal/attr/warning.h +enc/windows_1253.$(OBJEXT): internal/cast.h +enc/windows_1253.$(OBJEXT): internal/compiler_is.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1253.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1253.$(OBJEXT): internal/compiler_since.h +enc/windows_1253.$(OBJEXT): internal/config.h +enc/windows_1253.$(OBJEXT): internal/dllexport.h +enc/windows_1253.$(OBJEXT): internal/dosish.h +enc/windows_1253.$(OBJEXT): internal/has/attribute.h +enc/windows_1253.$(OBJEXT): internal/has/builtin.h +enc/windows_1253.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1253.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1253.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1253.$(OBJEXT): internal/has/extension.h +enc/windows_1253.$(OBJEXT): internal/has/feature.h +enc/windows_1253.$(OBJEXT): internal/has/warning.h +enc/windows_1253.$(OBJEXT): internal/stdalign.h +enc/windows_1253.$(OBJEXT): internal/stdbool.h +enc/windows_1253.$(OBJEXT): internal/warning_push.h +enc/windows_1253.$(OBJEXT): internal/xmalloc.h enc/windows_1253.$(OBJEXT): missing.h enc/windows_1253.$(OBJEXT): onigmo.h enc/windows_1254.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1254.$(OBJEXT): assert.h +enc/windows_1254.$(OBJEXT): backward/2/assume.h +enc/windows_1254.$(OBJEXT): backward/2/attributes.h +enc/windows_1254.$(OBJEXT): backward/2/bool.h +enc/windows_1254.$(OBJEXT): backward/2/long_long.h +enc/windows_1254.$(OBJEXT): backward/2/stdalign.h +enc/windows_1254.$(OBJEXT): backward/2/stdarg.h enc/windows_1254.$(OBJEXT): config.h enc/windows_1254.$(OBJEXT): defines.h enc/windows_1254.$(OBJEXT): enc/iso_8859.h enc/windows_1254.$(OBJEXT): enc/windows_1254.c +enc/windows_1254.$(OBJEXT): internal/assume.h +enc/windows_1254.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1254.$(OBJEXT): internal/attr/cold.h +enc/windows_1254.$(OBJEXT): internal/attr/const.h +enc/windows_1254.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1254.$(OBJEXT): internal/attr/error.h +enc/windows_1254.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1254.$(OBJEXT): internal/attr/format.h +enc/windows_1254.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1254.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1254.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1254.$(OBJEXT): internal/attr/noinline.h +enc/windows_1254.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1254.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1254.$(OBJEXT): internal/attr/pure.h +enc/windows_1254.$(OBJEXT): internal/attr/restrict.h +enc/windows_1254.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1254.$(OBJEXT): internal/attr/warning.h +enc/windows_1254.$(OBJEXT): internal/cast.h +enc/windows_1254.$(OBJEXT): internal/compiler_is.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1254.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1254.$(OBJEXT): internal/compiler_since.h +enc/windows_1254.$(OBJEXT): internal/config.h +enc/windows_1254.$(OBJEXT): internal/dllexport.h +enc/windows_1254.$(OBJEXT): internal/dosish.h +enc/windows_1254.$(OBJEXT): internal/has/attribute.h +enc/windows_1254.$(OBJEXT): internal/has/builtin.h +enc/windows_1254.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1254.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1254.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1254.$(OBJEXT): internal/has/extension.h +enc/windows_1254.$(OBJEXT): internal/has/feature.h +enc/windows_1254.$(OBJEXT): internal/has/warning.h +enc/windows_1254.$(OBJEXT): internal/stdalign.h +enc/windows_1254.$(OBJEXT): internal/stdbool.h +enc/windows_1254.$(OBJEXT): internal/warning_push.h +enc/windows_1254.$(OBJEXT): internal/xmalloc.h enc/windows_1254.$(OBJEXT): missing.h enc/windows_1254.$(OBJEXT): onigmo.h enc/windows_1257.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_1257.$(OBJEXT): assert.h +enc/windows_1257.$(OBJEXT): backward/2/assume.h +enc/windows_1257.$(OBJEXT): backward/2/attributes.h +enc/windows_1257.$(OBJEXT): backward/2/bool.h +enc/windows_1257.$(OBJEXT): backward/2/long_long.h +enc/windows_1257.$(OBJEXT): backward/2/stdalign.h +enc/windows_1257.$(OBJEXT): backward/2/stdarg.h enc/windows_1257.$(OBJEXT): config.h enc/windows_1257.$(OBJEXT): defines.h enc/windows_1257.$(OBJEXT): enc/iso_8859.h enc/windows_1257.$(OBJEXT): enc/windows_1257.c +enc/windows_1257.$(OBJEXT): internal/assume.h +enc/windows_1257.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_1257.$(OBJEXT): internal/attr/cold.h +enc/windows_1257.$(OBJEXT): internal/attr/const.h +enc/windows_1257.$(OBJEXT): internal/attr/deprecated.h +enc/windows_1257.$(OBJEXT): internal/attr/error.h +enc/windows_1257.$(OBJEXT): internal/attr/forceinline.h +enc/windows_1257.$(OBJEXT): internal/attr/format.h +enc/windows_1257.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_1257.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_1257.$(OBJEXT): internal/attr/noexcept.h +enc/windows_1257.$(OBJEXT): internal/attr/noinline.h +enc/windows_1257.$(OBJEXT): internal/attr/nonnull.h +enc/windows_1257.$(OBJEXT): internal/attr/noreturn.h +enc/windows_1257.$(OBJEXT): internal/attr/pure.h +enc/windows_1257.$(OBJEXT): internal/attr/restrict.h +enc/windows_1257.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_1257.$(OBJEXT): internal/attr/warning.h +enc/windows_1257.$(OBJEXT): internal/cast.h +enc/windows_1257.$(OBJEXT): internal/compiler_is.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_1257.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_1257.$(OBJEXT): internal/compiler_since.h +enc/windows_1257.$(OBJEXT): internal/config.h +enc/windows_1257.$(OBJEXT): internal/dllexport.h +enc/windows_1257.$(OBJEXT): internal/dosish.h +enc/windows_1257.$(OBJEXT): internal/has/attribute.h +enc/windows_1257.$(OBJEXT): internal/has/builtin.h +enc/windows_1257.$(OBJEXT): internal/has/c_attribute.h +enc/windows_1257.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_1257.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_1257.$(OBJEXT): internal/has/extension.h +enc/windows_1257.$(OBJEXT): internal/has/feature.h +enc/windows_1257.$(OBJEXT): internal/has/warning.h +enc/windows_1257.$(OBJEXT): internal/stdalign.h +enc/windows_1257.$(OBJEXT): internal/stdbool.h +enc/windows_1257.$(OBJEXT): internal/warning_push.h +enc/windows_1257.$(OBJEXT): internal/xmalloc.h enc/windows_1257.$(OBJEXT): missing.h enc/windows_1257.$(OBJEXT): onigmo.h enc/windows_31j.$(OBJEXT): $(top_srcdir)/regenc.h +enc/windows_31j.$(OBJEXT): assert.h +enc/windows_31j.$(OBJEXT): backward/2/assume.h +enc/windows_31j.$(OBJEXT): backward/2/attributes.h +enc/windows_31j.$(OBJEXT): backward/2/bool.h +enc/windows_31j.$(OBJEXT): backward/2/long_long.h +enc/windows_31j.$(OBJEXT): backward/2/stdalign.h +enc/windows_31j.$(OBJEXT): backward/2/stdarg.h enc/windows_31j.$(OBJEXT): config.h enc/windows_31j.$(OBJEXT): defines.h enc/windows_31j.$(OBJEXT): enc/jis/props.h enc/windows_31j.$(OBJEXT): enc/jis/props.kwd enc/windows_31j.$(OBJEXT): enc/shift_jis.h enc/windows_31j.$(OBJEXT): enc/windows_31j.c +enc/windows_31j.$(OBJEXT): internal/assume.h +enc/windows_31j.$(OBJEXT): internal/attr/alloc_size.h +enc/windows_31j.$(OBJEXT): internal/attr/cold.h +enc/windows_31j.$(OBJEXT): internal/attr/const.h +enc/windows_31j.$(OBJEXT): internal/attr/deprecated.h +enc/windows_31j.$(OBJEXT): internal/attr/error.h +enc/windows_31j.$(OBJEXT): internal/attr/forceinline.h +enc/windows_31j.$(OBJEXT): internal/attr/format.h +enc/windows_31j.$(OBJEXT): internal/attr/maybe_unused.h +enc/windows_31j.$(OBJEXT): internal/attr/nodiscard.h +enc/windows_31j.$(OBJEXT): internal/attr/noexcept.h +enc/windows_31j.$(OBJEXT): internal/attr/noinline.h +enc/windows_31j.$(OBJEXT): internal/attr/nonnull.h +enc/windows_31j.$(OBJEXT): internal/attr/noreturn.h +enc/windows_31j.$(OBJEXT): internal/attr/pure.h +enc/windows_31j.$(OBJEXT): internal/attr/restrict.h +enc/windows_31j.$(OBJEXT): internal/attr/returns_nonnull.h +enc/windows_31j.$(OBJEXT): internal/attr/warning.h +enc/windows_31j.$(OBJEXT): internal/cast.h +enc/windows_31j.$(OBJEXT): internal/compiler_is.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/apple.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/clang.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/gcc.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/intel.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/msvc.h +enc/windows_31j.$(OBJEXT): internal/compiler_is/sunpro.h +enc/windows_31j.$(OBJEXT): internal/compiler_since.h +enc/windows_31j.$(OBJEXT): internal/config.h +enc/windows_31j.$(OBJEXT): internal/dllexport.h +enc/windows_31j.$(OBJEXT): internal/dosish.h +enc/windows_31j.$(OBJEXT): internal/has/attribute.h +enc/windows_31j.$(OBJEXT): internal/has/builtin.h +enc/windows_31j.$(OBJEXT): internal/has/c_attribute.h +enc/windows_31j.$(OBJEXT): internal/has/cpp_attribute.h +enc/windows_31j.$(OBJEXT): internal/has/declspec_attribute.h +enc/windows_31j.$(OBJEXT): internal/has/extension.h +enc/windows_31j.$(OBJEXT): internal/has/feature.h +enc/windows_31j.$(OBJEXT): internal/has/warning.h +enc/windows_31j.$(OBJEXT): internal/stdalign.h +enc/windows_31j.$(OBJEXT): internal/stdbool.h +enc/windows_31j.$(OBJEXT): internal/warning_push.h +enc/windows_31j.$(OBJEXT): internal/xmalloc.h enc/windows_31j.$(OBJEXT): missing.h enc/windows_31j.$(OBJEXT): onigmo.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/enc/encdb.c b/ruby/enc/encdb.c index a41e4edc6..a1936df80 100644 --- a/ruby/enc/encdb.c +++ b/ruby/enc/encdb.c @@ -9,7 +9,7 @@ **********************************************************************/ -#include "internal.h" +#include "internal/encoding.h" #define ENC_REPLICATE(name, orig) rb_encdb_replicate((name), (orig)) #define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig)) diff --git a/ruby/enc/euc_jp.c b/ruby/enc/euc_jp.c index ded051af6..d283bf4eb 100644 --- a/ruby/enc/euc_jp.c +++ b/ruby/enc/euc_jp.c @@ -593,7 +593,7 @@ ENC_ALIAS("eucJP", "EUC-JP") /* UI-OSF Application Platform Profile for Japanese * Name: eucJP-ms * Link: http://home.m05.itscom.net/numa/cde/ucs-conv/ucs-conv.html * Link: http://www2d.biglobe.ne.jp/~msyk/charcode/cp932/eucJP-ms.html - * Link: http://ja.wikipedia.org/wiki/EUC-JP + * Link: https://ja.wikipedia.org/wiki/EUC-JP */ ENC_REPLICATE("eucJP-ms", "EUC-JP") /* TOG/JVC CDE/Motif Technical WG */ ENC_ALIAS("euc-jp-ms", "eucJP-ms") @@ -610,7 +610,7 @@ ENC_REPLICATE("CP51932", "EUC-JP") /* * Name: EUC-JIS-2004 - * Link: http://ja.wikipedia.org/wiki/EUC-JIS-2004 + * Link: https://ja.wikipedia.org/wiki/EUC-JIS-2004 */ ENC_REPLICATE("EUC-JIS-2004", "EUC-JP") /* defined at JIS X 0213:2004 */ ENC_ALIAS("EUC-JISX0213", "EUC-JIS-2004") /* defined at JIS X 0213:2000, and obsolete at JIS X 0213:2004 */ diff --git a/ruby/enc/iso_8859_11.c b/ruby/enc/iso_8859_11.c index 85e8f2cdb..b9c6119fd 100644 --- a/ruby/enc/iso_8859_11.c +++ b/ruby/enc/iso_8859_11.c @@ -102,7 +102,7 @@ ENC_ALIAS("ISO8859-11", "ISO-8859-11") /* * Name: TIS-620 * MIBenum: 2259 - * Link: http://en.wikipedia.org/wiki/Thai_Industrial_Standard_620-2533 + * Link: https://en.wikipedia.org/wiki/Thai_Industrial_Standard_620-2533 */ ENC_REPLICATE("TIS-620", "ISO-8859-11") diff --git a/ruby/enc/iso_8859_6.c b/ruby/enc/iso_8859_6.c index 6d852ac8c..cdb74054d 100644 --- a/ruby/enc/iso_8859_6.c +++ b/ruby/enc/iso_8859_6.c @@ -104,7 +104,7 @@ ENC_ALIAS("ISO8859-6", "ISO-8859-6") * MIBenum: 2256 * Link: http://www.iana.org/assignments/character-sets * Link: http://www.microsoft.com/globaldev/reference/sbcs/1256.mspx - * Link: http://en.wikipedia.org/wiki/Windows-1256 + * Link: https://en.wikipedia.org/wiki/Windows-1256 */ ENC_REPLICATE("Windows-1256", "ISO-8859-6") ENC_ALIAS("CP1256", "Windows-1256") diff --git a/ruby/enc/iso_8859_8.c b/ruby/enc/iso_8859_8.c index 0a7a29e82..e256855f2 100644 --- a/ruby/enc/iso_8859_8.c +++ b/ruby/enc/iso_8859_8.c @@ -104,7 +104,7 @@ ENC_ALIAS("ISO8859-8", "ISO-8859-8") * MIBenum: 2255 * Link: http://www.iana.org/assignments/character-sets * Link: http://www.microsoft.com/globaldev/reference/sbcs/1255.mspx - * Link: http://en.wikipedia.org/wiki/Windows-1255 + * Link: https://en.wikipedia.org/wiki/Windows-1255 */ ENC_REPLICATE("Windows-1255", "ISO-8859-8") ENC_ALIAS("CP1255", "Windows-1255") diff --git a/ruby/enc/shift_jis.c b/ruby/enc/shift_jis.c index 65fd5102d..f1355d2d9 100644 --- a/ruby/enc/shift_jis.c +++ b/ruby/enc/shift_jis.c @@ -55,13 +55,13 @@ OnigEncodingDefine(shift_jis, Shift_JIS) = { * Name: Shift_JIS * MIBenum: 17 * Link: http://www.iana.org/assignments/character-sets - * Link: http://ja.wikipedia.org/wiki/Shift_JIS + * Link: https://ja.wikipedia.org/wiki/Shift_JIS */ /* * Name: MacJapanese * Link: http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/JAPANESE.TXT - * Link: http://ja.wikipedia.org/wiki/MacJapanese + * Link: https://ja.wikipedia.org/wiki/MacJapanese */ ENC_REPLICATE("MacJapanese", "Shift_JIS") ENC_ALIAS("MacJapan", "MacJapanese") diff --git a/ruby/enc/trans/escape.trans b/ruby/enc/trans/escape.trans index c76ffa0e0..36d9dd0f1 100644 --- a/ruby/enc/trans/escape.trans +++ b/ruby/enc/trans/escape.trans @@ -18,9 +18,10 @@ ], nil) transcode_tblgen("", "xml_attr_content_escape", [ - ["{00-21,23-25,27-3B,3D,3F-FF}", :nomap], + ["{00-21,23-25,28-3B,3D,3F-FF}", :nomap], ["22", hexstr(""")], ["26", hexstr("&")], + ["27", hexstr("'")], ["3C", hexstr("<")], ["3E", hexstr(">")] ], nil) diff --git a/ruby/enc/trans/ibm720-tbl.rb b/ruby/enc/trans/ibm720-tbl.rb new file mode 100644 index 000000000..558684d64 --- /dev/null +++ b/ruby/enc/trans/ibm720-tbl.rb @@ -0,0 +1,122 @@ +IBM720_TO_UCS_TBL = [ + ["FF",0xA0], + ["9C",0xA3], + ["94",0xA4], + ["AE",0xAB], + ["F8",0xB0], + ["FD",0xB2], + ["E6",0xB5], + ["FA",0xB7], + ["AF",0xBB], + ["85",0xE0], + ["83",0xE2], + ["87",0xE7], + ["8A",0xE8], + ["82",0xE9], + ["88",0xEA], + ["89",0xEB], + ["8C",0xEE], + ["8B",0xEF], + ["93",0xF4], + ["97",0xF9], + ["96",0xFB], + ["98",0x621], + ["99",0x622], + ["9A",0x623], + ["9B",0x624], + ["9D",0x625], + ["9E",0x626], + ["9F",0x627], + ["A0",0x628], + ["A1",0x629], + ["A2",0x62A], + ["A3",0x62B], + ["A4",0x62C], + ["A5",0x62D], + ["A6",0x62E], + ["A7",0x62F], + ["A8",0x630], + ["A9",0x631], + ["AA",0x632], + ["AB",0x633], + ["AC",0x634], + ["AD",0x635], + ["E0",0x636], + ["E1",0x637], + ["E2",0x638], + ["E3",0x639], + ["E4",0x63A], + ["95",0x640], + ["E5",0x641], + ["E7",0x642], + ["E8",0x643], + ["E9",0x644], + ["EA",0x645], + ["EB",0x646], + ["EC",0x647], + ["ED",0x648], + ["EE",0x649], + ["EF",0x64A], + ["F1",0x64B], + ["F2",0x64C], + ["F3",0x64D], + ["F4",0x64E], + ["F5",0x64F], + ["F6",0x650], + ["91",0x651], + ["92",0x652], + ["FC",0x207F], + ["F9",0x2219], + ["FB",0x221A], + ["F7",0x2248], + ["F0",0x2261], + ["C4",0x2500], + ["B3",0x2502], + ["DA",0x250C], + ["BF",0x2510], + ["C0",0x2514], + ["D9",0x2518], + ["C3",0x251C], + ["B4",0x2524], + ["C2",0x252C], + ["C1",0x2534], + ["C5",0x253C], + ["CD",0x2550], + ["BA",0x2551], + ["D5",0x2552], + ["D6",0x2553], + ["C9",0x2554], + ["B8",0x2555], + ["B7",0x2556], + ["BB",0x2557], + ["D4",0x2558], + ["D3",0x2559], + ["C8",0x255A], + ["BE",0x255B], + ["BD",0x255C], + ["BC",0x255D], + ["C6",0x255E], + ["C7",0x255F], + ["CC",0x2560], + ["B5",0x2561], + ["B6",0x2562], + ["B9",0x2563], + ["D1",0x2564], + ["D2",0x2565], + ["CB",0x2566], + ["CF",0x2567], + ["D0",0x2568], + ["CA",0x2569], + ["D8",0x256A], + ["D7",0x256B], + ["CE",0x256C], + ["DF",0x2580], + ["DC",0x2584], + ["DB",0x2588], + ["DD",0x258C], + ["DE",0x2590], + ["B0",0x2591], + ["B1",0x2592], + ["B2",0x2593], + ["FE",0x25A0], +] diff --git a/ruby/enc/trans/newline.trans b/ruby/enc/trans/newline.trans index a200ec00a..9e763407f 100644 --- a/ruby/enc/trans/newline.trans +++ b/ruby/enc/trans/newline.trans @@ -98,7 +98,7 @@ rb_universal_newline = { 2, /* max_output */ asciicompat_converter, /* asciicompat_type */ 2, universal_newline_init, universal_newline_init, /* state_size, state_init, state_fini */ - NULL, NULL, NULL, fun_so_universal_newline, + 0, 0, 0, fun_so_universal_newline, universal_newline_finish }; @@ -110,8 +110,8 @@ rb_crlf_newline = { 1, /* max_input */ 2, /* max_output */ asciicompat_converter, /* asciicompat_type */ - 0, NULL, NULL, /* state_size, state_init, state_fini */ - NULL, NULL, NULL, NULL + 0, 0, 0, /* state_size, state_init, state_fini */ + 0, 0, 0, 0 }; static const rb_transcoder @@ -122,8 +122,8 @@ rb_cr_newline = { 1, /* max_input */ 1, /* max_output */ asciicompat_converter, /* asciicompat_type */ - 0, NULL, NULL, /* state_size, state_init, state_fini */ - NULL, NULL, NULL, NULL + 0, 0, 0, /* state_size, state_init, state_fini */ + 0, 0, 0, 0 }; void diff --git a/ruby/enc/trans/single_byte.trans b/ruby/enc/trans/single_byte.trans index cf521bed3..0d5407b91 100644 --- a/ruby/enc/trans/single_byte.trans +++ b/ruby/enc/trans/single_byte.trans @@ -51,8 +51,9 @@ transcode_tblgen_singlebyte "WINDOWS-1256" transcode_tblgen_singlebyte "WINDOWS-1257" transcode_tblgen_singlebyte "IBM437" - transcode_tblgen_singlebyte "IBM775" + transcode_tblgen_singlebyte "IBM720" transcode_tblgen_singlebyte "IBM737" + transcode_tblgen_singlebyte "IBM775" transcode_tblgen_singlebyte "IBM852" transcode_tblgen_singlebyte "IBM855" transcode_tblgen_singlebyte "IBM857" diff --git a/ruby/enc/unicode.c b/ruby/enc/unicode.c index 6e8c3d881..18fba0247 100644 --- a/ruby/enc/unicode.c +++ b/ruby/enc/unicode.c @@ -493,6 +493,10 @@ onigenc_unicode_get_case_fold_codes_by_str(OnigEncoding enc, #endif if ((to = onigenc_unicode_fold_lookup(code)) != 0) { + if (OnigCodePointCount(to->n) == 0) { + /* any codepoint should not be empty */ + UNREACHABLE_RETURN(0); + } if (OnigCodePointCount(to->n) == 1) { OnigCodePoint orig_code = code; diff --git a/ruby/enc/unicode/12.1.0/casefold.h b/ruby/enc/unicode/13.0.0/casefold.h similarity index 90% rename from ruby/enc/unicode/12.1.0/casefold.h rename to ruby/enc/unicode/13.0.0/casefold.h index 4c62f0fae..39f22604c 100644 --- a/ruby/enc/unicode/12.1.0/casefold.h +++ b/ruby/enc/unicode/13.0.0/casefold.h @@ -2,19 +2,19 @@ /* Generated by enc/unicode/case-folding.rb */ #if defined ONIG_UNICODE_VERSION_STRING && !( \ - ONIG_UNICODE_VERSION_MAJOR == 12 && \ - ONIG_UNICODE_VERSION_MINOR == 1 && \ + ONIG_UNICODE_VERSION_MAJOR == 13 && \ + ONIG_UNICODE_VERSION_MINOR == 0 && \ ONIG_UNICODE_VERSION_TEENY == 0 && \ 1) # error ONIG_UNICODE_VERSION_STRING mismatch #endif -#define ONIG_UNICODE_VERSION_STRING "12.1.0" -#define ONIG_UNICODE_VERSION_MAJOR 12 -#define ONIG_UNICODE_VERSION_MINOR 1 +#define ONIG_UNICODE_VERSION_STRING "13.0.0" +#define ONIG_UNICODE_VERSION_MAJOR 13 +#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 (*)[1485])(CaseFold_11_Table+0)) +#define CaseFold (*(CaseFold_11_Type (*)[1488])(CaseFold_11_Table+0)) {0x0041, {1|F|D, {0x0061}}}, {0x0042, {1|F|D, {0x0062}}}, {0x0043, {1|F|D, {0x0063}}}, @@ -1157,6 +1157,9 @@ static const CaseFold_11_Type CaseFold_11_Table[] = { {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}}}, + {0xa7f5, {1|F|D, {0xa7f6}}}, {0xab70, {1|F|U, {0x13a0}}}, {0xab71, {1|F|U, {0x13a1}}}, {0xab72, {1|F|U, {0x13a2}}}, @@ -1500,7 +1503,7 @@ static const CaseFold_11_Type CaseFold_11_Table[] = { {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+1485)) +#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1488)) {0x0049, {1|F|D, {0x0069}}}, {0x0130, {2|F|D, {0x0069, 0x0307}}}, }; @@ -1508,7 +1511,7 @@ static const CaseFold_11_Type CaseFold_11_Table[] = { /* 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 = 3500, duplicates = 0 */ +/* maximum key range = 3677, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -1523,29 +1526,29 @@ onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code) { static const unsigned short asso_values[] = { - 5, 273, 4, 8, 3, 1, 86, 9, 2, 289, - 290, 3, 3510, 3510, 3510, 3510, 3510, 3510, 3510, 3510, - 3510, 3510, 3510, 3510, 3510, 50, 3510, 3510, 3510, 3510, - 3510, 3510, 3510, 225, 3510, 3510, 3510, 3510, 3510, 28, - 3510, 3510, 3510, 3510, 3510, 3510, 3510, 3510, 3510, 394, - 3510, 3510, 3510, 3510, 3510, 3510, 3510, 47, 3510, 3510, - 255, 40, 286, 1, 3510, 3510, 599, 8, 3510, 3510, - 3510, 3510, 3510, 282, 3510, 3510, 267, 667, 473, 39, - 2019, 189, 47, 175, 2001, 107, 1626, 6, 12, 25, - 1961, 678, 1128, 526, 1945, 148, 1923, 371, 1720, 134, - 1857, 80, 1375, 66, 1705, 300, 1635, 445, 1611, 472, - 1795, 216, 1303, 499, 1552, 270, 1511, 243, 121, 619, - 1284, 540, 875, 592, 1484, 567, 412, 703, 1692, 387, - 1782, 781, 1767, 664, 1718, 648, 1316, 608, 1647, 715, - 1592, 771, 1544, 1029, 1563, 887, 1296, 861, 1194, 978, - 95, 899, 1257, 835, 1335, 765, 1529, 984, 862, 938, - 1460, 759, 329, 1079, 1159, 940, 234, 1101, 1204, 990, - 949, 1493, 92, 1438, 77, 1391, 7, 1073, 44, 1377, - 2, 1435, 4, 1321, 428, 1274, 332, 1206, 11, 1426, - 46, 478, 200, 1502, 31, 1400, 153, 1663, 352, 1820, - 229, 1733, 265, 1405, 315, 1879, 198 + 1, 3681, 2, 7, 3, 416, 200, 59, 83, 50, + 2, 288, 142, 5, 3681, 3681, 3681, 3681, 3681, 3681, + 3681, 3681, 3681, 3681, 3681, 3681, 3681, 30, 3681, 3681, + 3681, 3681, 3681, 3681, 3681, 127, 3681, 3681, 3681, 3681, + 3681, 19, 3681, 3681, 3681, 3681, 3681, 3681, 3681, 3681, + 3681, 459, 3681, 3681, 3681, 3681, 3681, 3681, 3681, 190, + 3681, 3681, 14, 13, 297, 1, 3681, 3681, 300, 5, + 3681, 3681, 3681, 3681, 3681, 179, 3681, 3681, 205, 792, + 431, 28, 1935, 486, 235, 442, 2030, 113, 1663, 5, + 11, 22, 1884, 649, 743, 397, 1558, 96, 1958, 130, + 1745, 279, 1900, 79, 1345, 45, 1785, 62, 1708, 342, + 1679, 262, 1857, 147, 1364, 532, 1639, 197, 1612, 180, + 519, 587, 1332, 380, 1044, 546, 1578, 464, 431, 698, + 1701, 573, 1593, 768, 1893, 737, 1735, 643, 1552, 669, + 1807, 794, 1633, 704, 1821, 1313, 1630, 1064, 1283, 1001, + 1321, 1119, 1307, 1040, 948, 864, 1697, 1015, 1338, 1174, + 1945, 1153, 1002, 1109, 1280, 1245, 812, 1095, 286, 1261, + 512, 1210, 372, 1496, 98, 1494, 31, 1526, 14, 1136, + 77, 1476, 5, 1511, 68, 1425, 9, 1418, 205, 1387, + 209, 1358, 60, 1834, 12, 1564, 39, 2015, 128, 916, + 88, 1275, 2, 1019, 333, 665, 346, 1365, 174 }; - return asso_values[bits_of(code, 2)+79] + asso_values[bits_of(code, 1)] + asso_values[bits_of(code, 0)]; + return asso_values[bits_of(code, 2)+81] + asso_values[bits_of(code, 1)+2] + asso_values[bits_of(code, 0)]; } static const CodePointList3 * @@ -1555,1958 +1558,2042 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) { MIN_CODE_VALUE = 0x41, MAX_CODE_VALUE = 0x1e921, - TOTAL_KEYWORDS = 1487, + TOTAL_KEYWORDS = 1490, MIN_WORD_LENGTH = 3, MAX_WORD_LENGTH = 3, - MIN_HASH_VALUE = 10, - MAX_HASH_VALUE = 3509 + MIN_HASH_VALUE = 4, + MAX_HASH_VALUE = 3680 }; static const short wordlist[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0x1fe7*/ 848, - /*0x10408*/ 1268, + /*0x1ff9*/ 860, + -1, + /*0x0179*/ 117, /*0x1f88*/ 775, /*0x0408*/ 305, - /*0x0208*/ 194, /*0x0108*/ 61, - /*0xab88*/ 1166, - /*0x10409*/ 1269, + /*0x10408*/ 1271, + /*0x1fe9*/ 850, + /*0xab88*/ 1169, /*0x1f89*/ 776, /*0x0409*/ 306, - /*0x0388*/ 235, - /*0x2c67*/ 962, - /*0xab89*/ 1167, - /*0x2c08*/ 919, - -1, - /*0x0189*/ 126, - /*0x0389*/ 236, -1, - /*0x2c6d*/ 965, + /*0x10409*/ 1272, + /*0x2c08*/ 919, + /*0xab89*/ 1170, + /*0x1e88*/ 653, + /*0x1e08*/ 589, + /*0x2c69*/ 963, + /*0x13f9*/ 525, /*0x2c09*/ 920, - /*0x1040a*/ 1270, /*0x1f8a*/ 777, /*0x040a*/ 307, - /*0x020a*/ 195, /*0x010a*/ 62, - /*0xab8a*/ 1168, + /*0x1040a*/ 1273, /*0x2c88*/ 977, - /*0x1ff3*/ 855, - /*0x018a*/ 127, - /*0x038a*/ 237, - -1, - /*0x2ced*/ 1024, - /*0x2c0a*/ 921, - -1, - /*0x10400*/ 1260, + /*0xab8a*/ 1171, /*0x1f80*/ 767, /*0x0400*/ 297, - /*0x0200*/ 190, /*0x0100*/ 57, - /*0xab80*/ 1158, - /*0x1fe3*/ 845, - /*0x1e88*/ 653, - /*0x10403*/ 1263, - /*0x1f83*/ 770, - /*0x0403*/ 300, - /*0x2c8a*/ 978, - /*0x2c00*/ 911, - /*0xab83*/ 1161, - /*0x1c88*/ 538, - /*0x10c88*/ 1344, - /*0x2183*/ 884, - /*0x2c63*/ 960, - /*0x1e908*/ 1459, - /*0x2c6f*/ 967, - /*0x2c03*/ 914, - /*0x10c89*/ 1345, - -1, -1, - /*0x1e909*/ 1460, - /*0x2c80*/ 973, + /*0x10400*/ 1263, + /*0x2c0a*/ 921, + /*0xab80*/ 1161, /*0x1e8a*/ 654, - /*0x10418*/ 1284, + /*0x1e0a*/ 590, + /*0x10c88*/ 1347, + /*0x00df*/ 56, + /*0x2c00*/ 911, + /*0x1ff3*/ 855, + /*0x1e80*/ 649, + /*0x1e00*/ 585, + /*0x10c89*/ 1348, + /*0x2c8a*/ 978, + -1, /*0x1f98*/ 791, /*0x0418*/ 321, - /*0x0218*/ 202, /*0x0118*/ 69, - /*0xab98*/ 1182, + /*0x10418*/ 1287, + /*0x2c80*/ 973, + /*0xab98*/ 1185, + /*0x03f9*/ 292, -1, - /*0x10c8a*/ 1346, - /*0x0198*/ 137, - /*0x0398*/ 249, - /*0x1e90a*/ 1461, - /*0xa780*/ 1105, + /*0x10c8a*/ 1349, + /*0x0388*/ 235, /*0x2c18*/ 935, - /*0x1e80*/ 649, - /*0x10416*/ 1282, + /*0xa780*/ 1105, + /*0x1e98*/ 662, + /*0x1e18*/ 597, + /*0x10c80*/ 1339, + /*0x0389*/ 236, + /*0x03f1*/ 288, + /*0x1f9a*/ 793, + /*0x041a*/ 323, + /*0x011a*/ 70, + /*0x1041a*/ 1289, + /*0x2c98*/ 985, + /*0xab9a*/ 1187, + /*0x1fe7*/ 848, + -1, + /*0x2c6f*/ 967, + /*0x038a*/ 237, + /*0x2c1a*/ 937, + /*0xa798*/ 1114, + /*0x1e9a*/ 664, + /*0x1e1a*/ 598, + /*0x10c98*/ 1363, + /*0x1fe3*/ 845, + /*0x2c67*/ 962, /*0x1f96*/ 789, /*0x0416*/ 319, - /*0x0216*/ 201, /*0x0116*/ 68, - /*0xab96*/ 1180, - /*0x1c80*/ 530, - /*0x10c80*/ 1336, - /*0x0196*/ 135, - /*0x0396*/ 247, - /*0x1e900*/ 1451, - /*0x2c98*/ 985, - /*0x2c16*/ 933, - -1, - /*0x1c83*/ 533, - /*0x10c83*/ 1339, - /*0x1fc7*/ 830, - -1, - /*0x1e903*/ 1454, - /*0x0147*/ 91, - /*0x0047*/ 6, + /*0x10416*/ 1285, + /*0x2c9a*/ 986, + /*0xab96*/ 1183, -1, -1, - /*0x01c7*/ 159, - /*0xa798*/ 1114, - /*0x2c96*/ 984, - /*0x1e98*/ 662, - /*0x10406*/ 1266, - /*0x1f86*/ 773, - /*0x0406*/ 303, - /*0x0206*/ 193, - /*0x0106*/ 60, - /*0xab86*/ 1164, - /*0x1c98*/ 547, - /*0x10c98*/ 1360, - /*0x0186*/ 124, - /*0x0386*/ 234, - /*0x1e918*/ 1475, - /*0xa796*/ 1113, - /*0x2c06*/ 917, + /*0x2c63*/ 960, + /*0x1ff7*/ 858, + /*0x2c16*/ 933, + /*0xa79a*/ 1115, /*0x1e96*/ 660, - /*0x10427*/ 1299, - /*0x1fa7*/ 806, - /*0x0427*/ 336, - -1, -1, - /*0xaba7*/ 1197, - /*0x1c96*/ 545, - /*0x10c96*/ 1358, - /*0x01a7*/ 145, - /*0x03a7*/ 263, - /*0x1e916*/ 1473, - /*0x2c86*/ 976, - /*0x2c27*/ 950, - /*0x10414*/ 1280, - /*0x1f94*/ 787, - /*0x0414*/ 317, - /*0x0214*/ 200, - /*0x0114*/ 67, - /*0xab94*/ 1178, - -1, -1, - /*0x0194*/ 134, - /*0x0394*/ 245, + /*0x1e16*/ 596, + /*0x10c9a*/ 1365, + /*0x0398*/ 249, -1, - /*0xa786*/ 1108, - /*0x2c14*/ 931, - /*0x1e86*/ 652, - /*0x10410*/ 1276, /*0x1f90*/ 783, /*0x0410*/ 313, - /*0x0210*/ 198, /*0x0110*/ 65, - /*0xab90*/ 1174, - /*0x1c86*/ 536, - /*0x10c86*/ 1342, - /*0x0190*/ 131, - /*0x0390*/ 241, - /*0x1e906*/ 1457, - /*0x2c94*/ 983, - /*0x2c10*/ 927, - -1, - /*0x03f5*/ 290, - /*0xfb00*/ 1222, - -1, - /*0x2c75*/ 970, + /*0x10410*/ 1279, + /*0x2c96*/ 984, + /*0xab90*/ 1177, -1, -1, - /*0x1ca7*/ 562, - /*0x10ca7*/ 1375, + /*0x00dd*/ 54, -1, - /*0xfb03*/ 1225, + /*0x2c10*/ 927, + /*0xa796*/ 1113, + /*0x1e90*/ 657, + /*0x1e10*/ 593, + /*0x10c96*/ 1361, + /*0x039a*/ 251, -1, + /*0x1f86*/ 773, + /*0x0406*/ 303, + /*0x0106*/ 60, + /*0x10406*/ 1269, /*0x2c90*/ 981, - /*0x1e94*/ 659, - /*0x10404*/ 1264, - /*0x1f84*/ 771, - /*0x0404*/ 301, - /*0x0204*/ 192, - /*0x0104*/ 59, - /*0xab84*/ 1162, - /*0x1c94*/ 543, - /*0x10c94*/ 1356, - /*0x0184*/ 123, - -1, - /*0x1e914*/ 1471, + /*0xab86*/ 1167, + -1, -1, -1, -1, + /*0x2c06*/ 917, /*0xa790*/ 1111, - /*0x2c04*/ 915, - /*0x1e90*/ 657, - /*0x10402*/ 1262, - /*0x1f82*/ 769, - /*0x0402*/ 299, - /*0x0202*/ 191, - /*0x0102*/ 58, - /*0xab82*/ 1160, - /*0x1c90*/ 539, - /*0x10c90*/ 1352, - /*0x0182*/ 122, + /*0x1e86*/ 652, + /*0x1e06*/ 588, + /*0x10c90*/ 1355, + /*0x0396*/ 247, -1, - /*0x1e910*/ 1467, - /*0x2c84*/ 975, - /*0x2c02*/ 913, - /*0x017f*/ 120, + /*0x1f92*/ 785, + /*0x0412*/ 315, + /*0x0112*/ 66, + /*0x10412*/ 1281, + /*0x2c86*/ 976, + /*0xab92*/ 1179, -1, - /*0xfb16*/ 1232, - -1, -1, - /*0x03ff*/ 296, - /*0x01f1*/ 181, - /*0x03f1*/ 288, - /*0x2c7f*/ 972, - -1, -1, - /*0xa784*/ 1107, - /*0x2c82*/ 974, - /*0x1e84*/ 651, - /*0x10420*/ 1292, + /*0x03f7*/ 291, + /*0x2c75*/ 970, + -1, + /*0x2c12*/ 929, + /*0xa786*/ 1108, + /*0x1e92*/ 658, + /*0x1e12*/ 594, + /*0x10c86*/ 1345, + /*0x0390*/ 241, + /*0x0508*/ 425, /*0x1fa0*/ 799, /*0x0420*/ 329, - /*0x0220*/ 206, /*0x0120*/ 73, - /*0xaba0*/ 1190, - /*0x1c84*/ 534, - /*0x10c84*/ 1340, - /*0x01a0*/ 141, - /*0x03a0*/ 257, - /*0x1e904*/ 1455, - /*0xa782*/ 1106, + /*0x10420*/ 1295, + /*0x2c92*/ 982, + /*0xaba0*/ 1193, + -1, -1, -1, + /*0xa7f5*/ 1144, /*0x2c20*/ 943, - /*0x1e82*/ 650, - /*0x1ff9*/ 860, - /*0xfb06*/ 1228, - -1, - /*0x0179*/ 117, - -1, - /*0x1fd7*/ 839, - /*0x1c82*/ 532, - /*0x10c82*/ 1338, - /*0x03f9*/ 292, - /*0x0057*/ 21, - /*0x1e902*/ 1453, + /*0xa792*/ 1112, + /*0x1ea0*/ 667, + /*0x1e20*/ 601, + /*0x10c92*/ 1357, + /*0x0386*/ 234, + /*0x050a*/ 426, + -1, -1, -1, -1, /*0x2ca0*/ 989, - /*0x01d7*/ 168, - /*0x10426*/ 1298, + /*0x0500*/ 421, + -1, -1, -1, -1, -1, + /*0xa7a0*/ 1118, + /*0x017f*/ 120, + /*0x03f5*/ 290, + /*0x10ca0*/ 1371, + /*0x0392*/ 243, /*0x1fa6*/ 805, /*0x0426*/ 335, - /*0x0226*/ 209, /*0x0126*/ 76, - /*0xaba6*/ 1196, - -1, -1, - /*0x01a6*/ 144, - /*0x03a6*/ 262, - -1, - /*0xa7a0*/ 1118, + /*0x10426*/ 1301, + /*0x2c7f*/ 972, + /*0xaba6*/ 1199, + /*0x0518*/ 433, + -1, -1, -1, /*0x2c26*/ 949, - /*0x1ea0*/ 667, - /*0x13f9*/ 525, - /*0xfb14*/ 1230, - -1, -1, - /*0x1e08*/ 589, -1, - /*0x1ca0*/ 555, - /*0x10ca0*/ 1368, + /*0x1ea6*/ 670, + /*0x1e26*/ 604, + /*0x1c88*/ 538, -1, - /*0x1ffb*/ 862, - /*0x1e920*/ 1483, - /*0x2ca6*/ 992, - /*0x017b*/ 118, - /*0x10424*/ 1296, + /*0x03a0*/ 257, /*0x1fa4*/ 803, /*0x0424*/ 333, - /*0x0224*/ 208, /*0x0124*/ 75, - /*0xaba4*/ 1194, - -1, -1, - /*0x01a4*/ 143, - /*0x03a4*/ 260, - /*0x1e0a*/ 590, - /*0xa7a6*/ 1121, + /*0x10424*/ 1299, + /*0x2ca6*/ 992, + /*0xaba4*/ 1197, + /*0x051a*/ 434, + /*0x0208*/ 194, + /*0x1feb*/ 852, + -1, /*0x2c24*/ 947, - /*0x1ea6*/ 670, + /*0xa7a6*/ 1121, + /*0x1ea4*/ 669, + /*0x1e24*/ 603, + /*0x10ca6*/ 1377, + -1, -1, -1, + /*0x2c6b*/ 964, + -1, + /*0x1c80*/ 530, + /*0x2ca4*/ 991, + /*0x2c6d*/ 965, + /*0x0516*/ 432, + /*0x020a*/ 195, + -1, + /*0x03ff*/ 296, + -1, + /*0xa7a4*/ 1120, + /*0x2ceb*/ 1023, + /*0x0200*/ 190, + /*0x10ca4*/ 1375, + /*0x03a6*/ 262, + /*0x2ced*/ 1024, + -1, -1, -1, + /*0x1c98*/ 547, + /*0x1f83*/ 770, + /*0x0403*/ 300, + /*0x0510*/ 429, + /*0x10403*/ 1266, + /*0x2183*/ 884, + /*0xab83*/ 1164, + -1, -1, -1, + /*0x0218*/ 202, + /*0x2c03*/ 914, + /*0x03a4*/ 260, + -1, -1, -1, -1, + /*0x1c9a*/ 549, + -1, -1, + /*0x0506*/ 424, + -1, /*0x037f*/ 233, - -1, -1, -1, -1, -1, - /*0x1ca6*/ 561, - /*0x10ca6*/ 1374, + -1, -1, -1, -1, + /*0x021a*/ 203, + /*0x1f9e*/ 797, + /*0x041e*/ 327, + /*0x011e*/ 72, + /*0x1041e*/ 1293, + /*0x10c83*/ 1342, + /*0xab9e*/ 1191, + /*0x1c96*/ 545, + -1, -1, + /*0x0512*/ 430, + /*0x2c1e*/ 941, + /*0x10a0*/ 484, + /*0x1e9e*/ 666, + /*0x1e1e*/ 600, + -1, -1, + /*0x0216*/ 201, + /*0x1f94*/ 787, + /*0x0414*/ 317, + /*0x0114*/ 67, + /*0x10414*/ 1283, + /*0x2c9e*/ 988, + /*0xab94*/ 1181, + /*0x1c90*/ 539, + /*0x1fd7*/ 839, + /*0x0057*/ 21, + /*0x0520*/ 437, + /*0x2c14*/ 931, + /*0xa79e*/ 1117, + /*0x1e94*/ 659, + /*0x1e14*/ 595, + /*0x10c9e*/ 1369, + -1, + /*0x0210*/ 198, + -1, + /*0x1e908*/ 1462, + -1, -1, + /*0x2c94*/ 983, /*0x1f08*/ 715, - /*0x13fb*/ 527, - /*0x1e00*/ 585, - /*0x2ca4*/ 991, - /*0x0508*/ 425, - /*0x1f6d*/ 764, + /*0x1c86*/ 536, + /*0x1e909*/ 1463, + /*0x2165*/ 873, + /*0x1f69*/ 760, + /*0x10a6*/ 490, /*0x1f09*/ 716, - /*0xfb04*/ 1226, - /*0x1041a*/ 1286, - /*0x1f9a*/ 793, - /*0x041a*/ 323, - /*0x021a*/ 203, - /*0x011a*/ 70, - /*0xab9a*/ 1184, + /*0x2169*/ 877, + /*0x048a*/ 362, + /*0x10c94*/ 1359, + /*0x039e*/ 255, + /*0x0206*/ 193, + /*0x2161*/ 869, + /*0x1e90a*/ 1464, + /*0x0480*/ 361, -1, -1, - /*0xa7a4*/ 1120, - /*0x039a*/ 251, - /*0x1ea4*/ 669, /*0x1f0a*/ 717, - /*0x2c1a*/ 937, - /*0xfb02*/ 1224, - /*0x048a*/ 362, - /*0x050a*/ 426, + /*0x1c92*/ 541, + /*0x1e900*/ 1454, + /*0x0526*/ 440, -1, - /*0x1ca4*/ 559, - /*0x10ca4*/ 1372, - /*0x017d*/ 119, - /*0x10c7*/ 522, - /*0x1e18*/ 597, + /*0x10a4*/ 488, + -1, -1, -1, + /*0x1f5f*/ 758, + /*0x0394*/ 245, + /*0x0212*/ 199, -1, -1, - /*0x03fd*/ 294, - /*0x2c9a*/ 986, + /*0x0498*/ 369, + /*0x1ffb*/ 862, + -1, + /*0x017b*/ 118, + /*0x1ca0*/ 555, + /*0x1e918*/ 1478, + /*0x0524*/ 439, -1, -1, - /*0x0480*/ 361, - /*0x0500*/ 421, - /*0x1fd3*/ 837, + /*0x1f18*/ 723, + /*0x1f9c*/ 795, + /*0x041c*/ 325, + /*0x011c*/ 71, + /*0x1041c*/ 1291, + /*0x0220*/ 206, + /*0xab9c*/ 1189, + /*0x017d*/ 119, + /*0x049a*/ 370, + -1, + /*0x13fb*/ 527, + /*0x2c1c*/ 939, -1, + /*0x1e91a*/ 1480, + /*0x1e1c*/ 599, /*0x1f6f*/ 766, - /*0x1feb*/ 852, - /*0x0053*/ 17, - /*0x1e16*/ 596, -1, - /*0x01d3*/ 166, - /*0xa79a*/ 1115, + /*0x1f1a*/ 725, + /*0x216f*/ 883, + -1, -1, -1, + /*0x2c9c*/ 987, + /*0x13fd*/ 529, -1, - /*0x1e9a*/ 664, + /*0x0496*/ 368, + /*0x2167*/ 875, + -1, + /*0x1ca6*/ 561, + /*0xa79c*/ 1116, + /*0x1e916*/ 1476, + /*0x1fdb*/ 843, + /*0x10c9c*/ 1367, -1, -1, - /*0x13fd*/ 529, - /*0x2c6b*/ 964, + /*0x2163*/ 871, -1, - /*0x10a7*/ 491, - /*0x1c9a*/ 549, - /*0x10c9a*/ 1362, + /*0x00db*/ 52, + /*0x0226*/ 209, + /*0x1faa*/ 809, + /*0x042a*/ 339, + /*0x012a*/ 78, + /*0x0490*/ 365, -1, - /*0x00df*/ 56, - /*0x1e91a*/ 1477, - /*0x1f18*/ 723, - /*0x1ff7*/ 858, + /*0xabaa*/ 1203, + /*0x1ca4*/ 559, -1, - /*0x0498*/ 369, - /*0x0518*/ 433, - /*0x2ceb*/ 1023, + /*0x1e910*/ 1470, + -1, + /*0x2c2a*/ 953, + /*0x039c*/ 253, + /*0x1eaa*/ 672, + /*0x1e2a*/ 606, + /*0x1f5d*/ 757, + /*0x03fd*/ 294, + /*0x0224*/ 208, + /*0x1f8e*/ 781, + /*0x040e*/ 311, + /*0x010e*/ 64, + /*0x1040e*/ 1277, + /*0x2caa*/ 994, + /*0xab8e*/ 1175, + /*0x051e*/ 436, + -1, + /*0x1e906*/ 1460, + -1, + /*0x2c0e*/ 925, + /*0xa7aa*/ 1123, + /*0x1e8e*/ 656, + /*0x1e0e*/ 592, + /*0x10caa*/ 1381, + -1, -1, -1, -1, -1, + /*0x0492*/ 366, + /*0x2c8e*/ 980, + -1, + /*0x0514*/ 431, + -1, + /*0x1e912*/ 1472, + -1, + /*0x1c83*/ 533, + -1, + /*0x0189*/ 126, + /*0x01f1*/ 181, + /*0x10c8e*/ 1353, + /*0x03aa*/ 266, + -1, + /*0x1faf*/ 814, + /*0x042f*/ 344, + /*0xa779*/ 1101, + /*0x04a0*/ 373, + -1, + /*0xabaf*/ 1208, + /*0x018a*/ 127, + -1, + /*0x1e920*/ 1486, + -1, -1, + /*0x1f84*/ 771, + /*0x0404*/ 301, + /*0x0104*/ 59, + /*0x10404*/ 1267, + /*0x038e*/ 239, + /*0xab84*/ 1165, + -1, -1, -1, + /*0x1c9e*/ 553, + /*0x2c04*/ 915, + -1, + /*0x1e84*/ 651, + /*0x1e04*/ 587, + -1, -1, -1, -1, + /*0x0198*/ 137, + /*0x021e*/ 205, + /*0x10caf*/ 1386, + /*0x2c84*/ 975, + /*0x1fae*/ 813, + /*0x042e*/ 343, + /*0x012e*/ 80, + /*0x04a6*/ 376, + /*0x1c94*/ 543, + /*0xabae*/ 1207, + /*0xa784*/ 1107, -1, -1, + /*0x10c84*/ 1343, + /*0x2c2e*/ 957, + -1, + /*0x1eae*/ 674, + /*0x1e2e*/ 608, + /*0x0214*/ 200, + /*0x2126*/ 864, + -1, -1, -1, + /*0x051c*/ 435, + /*0x04a4*/ 375, + /*0x2cae*/ 996, + /*0x1f82*/ 769, + /*0x0402*/ 299, + /*0x0102*/ 58, + /*0x10402*/ 1265, + -1, + /*0xab82*/ 1163, + /*0xa7ae*/ 1127, + -1, + /*0x0196*/ 135, + /*0x10cae*/ 1385, + /*0x2c02*/ 913, + -1, + /*0x1e82*/ 650, + /*0x1e02*/ 586, + -1, + /*0x1f6b*/ 762, + -1, /*0x01f7*/ 185, - /*0x03f7*/ 291, - /*0x1e06*/ 588, - /*0x1f5f*/ 758, + /*0x216b*/ 879, + /*0x1f6d*/ 764, + /*0x10aa*/ 494, + /*0x2c82*/ 974, + /*0x216d*/ 881, + -1, -1, + /*0x0190*/ 131, + /*0x1fd9*/ 841, + /*0x0059*/ 23, + /*0xa782*/ 1106, + -1, -1, + /*0x10c82*/ 1341, + /*0x00d9*/ 50, + /*0x1fa7*/ 806, + /*0x0427*/ 336, + /*0x052a*/ 442, + /*0x10427*/ 1302, -1, - /*0x00dd*/ 54, + /*0xaba7*/ 1200, -1, -1, - /*0x00c7*/ 33, - /*0x0496*/ 368, - /*0x0516*/ 432, - /*0x10412*/ 1278, - /*0x1f92*/ 785, - /*0x0412*/ 315, - /*0x0212*/ 199, - /*0x0112*/ 66, - /*0xab92*/ 1176, - /*0x24c7*/ 902, - /*0x1f5d*/ 757, + /*0x1e903*/ 1457, + /*0x0186*/ 124, + /*0x2c27*/ 950, + -1, + /*0x1c9c*/ 551, + /*0x1fa2*/ 801, + /*0x0422*/ 331, + /*0x0122*/ 74, + /*0x10422*/ 1297, + -1, + /*0xaba2*/ 1195, + /*0x050e*/ 428, + -1, -1, + /*0x021c*/ 204, + /*0x2c22*/ 945, + -1, + /*0x1ea2*/ 668, + /*0x1e22*/ 602, + /*0x1fac*/ 811, + /*0x042c*/ 341, + /*0x012c*/ 79, + /*0x049e*/ 372, + /*0x10ca7*/ 1378, + /*0xabac*/ 1205, + /*0xfb00*/ 1225, + /*0x2ca2*/ 990, + /*0x1e91e*/ 1484, + -1, + /*0x2c2c*/ 955, + /*0x10af*/ 499, + /*0x1eac*/ 673, + /*0x1e2c*/ 607, + /*0xa7a2*/ 1119, + -1, + /*0x01a0*/ 141, + /*0x10ca2*/ 1373, + -1, -1, + /*0x0494*/ 367, + /*0x2cac*/ 995, + /*0x03a7*/ 263, + /*0x1caa*/ 565, -1, - /*0x0392*/ 243, + /*0x1e914*/ 1474, -1, - /*0x104c7*/ 1323, - /*0x2c12*/ 929, - /*0x04c7*/ 393, - /*0x0547*/ 467, - -1, -1, /*0x1fb2*/ 815, - /*0x1e14*/ 595, - /*0x0232*/ 215, + /*0xa7ac*/ 1125, /*0x0132*/ 81, - /*0xabb2*/ 1208, - -1, -1, - /*0x01b2*/ 151, - /*0x2c92*/ 982, - /*0x0506*/ 424, - -1, -1, -1, -1, -1, - /*0x1e10*/ 593, - -1, -1, -1, -1, -1, - /*0xa792*/ 1112, - -1, - /*0x1e92*/ 658, - /*0x2cb2*/ 998, - /*0x1faf*/ 814, - /*0x042f*/ 344, - -1, -1, - /*0xabaf*/ 1205, - /*0x1c92*/ 541, - /*0x10c92*/ 1354, - /*0x01af*/ 149, -1, - /*0x1e912*/ 1469, - /*0x0494*/ 367, - /*0x0514*/ 431, - /*0xa7b2*/ 1130, + /*0x10cac*/ 1383, + /*0xabb2*/ 1211, + /*0x022a*/ 211, + -1, -1, -1, + /*0x0504*/ 423, -1, /*0x1eb2*/ 676, + /*0x1e32*/ 610, + /*0x1fa8*/ 807, + /*0x0428*/ 337, + /*0x0128*/ 77, + /*0x10ae*/ 498, -1, - /*0x1fe9*/ 850, - /*0x1e04*/ 587, - -1, -1, -1, - /*0x1cb2*/ 573, - /*0x10cb2*/ 1386, + /*0xaba8*/ 1201, -1, - /*0x0490*/ 365, - /*0x0510*/ 429, + /*0x2cb2*/ 998, + /*0x01a6*/ 144, + /*0x020e*/ 197, + /*0x2c28*/ 951, -1, - /*0x2c69*/ 963, - /*0x10a0*/ 484, - -1, -1, - /*0x1e02*/ 586, - /*0x1041c*/ 1288, - /*0x1f9c*/ 795, - /*0x041c*/ 325, - /*0x021c*/ 204, - /*0x011c*/ 71, - /*0xab9c*/ 1186, + /*0x1ea8*/ 671, + /*0x1e28*/ 605, + /*0xa7b2*/ 1130, + -1, + /*0xfb16*/ 1235, + /*0x10cb2*/ 1389, + /*0x052e*/ 444, + -1, + /*0x118a0*/ 1390, + /*0x2ca8*/ 993, -1, -1, - /*0x019c*/ 138, - /*0x039c*/ 253, + /*0xa726*/ 1065, + /*0x01a4*/ 143, -1, -1, - /*0x2c1c*/ 939, + /*0xa7a8*/ 1122, + /*0xff26*/ 1242, + -1, + /*0x10ca8*/ 1379, -1, /*0x1caf*/ 570, - /*0x10caf*/ 1383, - -1, -1, -1, -1, - /*0x0504*/ 423, - -1, -1, - /*0x10a6*/ 490, + -1, -1, -1, -1, -1, -1, + /*0x0502*/ 422, + /*0xa724*/ 1064, + /*0x049c*/ 371, -1, - /*0x2c9c*/ 987, - /*0x1e20*/ 601, - /*0x1041e*/ 1290, - /*0x1f9e*/ 797, - /*0x041e*/ 327, - /*0x021e*/ 205, - /*0x011e*/ 72, - /*0xab9e*/ 1188, + /*0x1c84*/ 534, -1, - /*0x0502*/ 422, - /*0x0470*/ 353, - /*0x039e*/ 255, - /*0x0170*/ 112, - /*0xa79c*/ 1116, - /*0x2c1e*/ 941, + /*0xff24*/ 1240, + /*0x1e91c*/ 1482, -1, - /*0x01f0*/ 180, - /*0x03f0*/ 287, - -1, -1, - /*0x2c70*/ 968, + /*0x03a8*/ 264, + /*0xfb06*/ 1231, + /*0x1f1c*/ 727, -1, - /*0x1c9c*/ 551, - /*0x10c9c*/ 1364, + /*0x118a6*/ 1396, + /*0x0204*/ 192, -1, - /*0x10a4*/ 488, - /*0x1e91c*/ 1479, - /*0x2c9e*/ 988, - /*0x1e26*/ 604, - /*0x10422*/ 1294, - /*0x1fa2*/ 801, - /*0x0422*/ 331, - /*0x0222*/ 207, - /*0x0122*/ 74, - /*0xaba2*/ 1192, - /*0x04a0*/ 373, - /*0x0520*/ 437, - /*0x01a2*/ 142, - -1, -1, - /*0xa79e*/ 1117, - /*0x2c22*/ 945, - /*0x1e9e*/ 666, - /*0x118a7*/ 1394, - -1, -1, -1, -1, - /*0x1ef0*/ 707, - /*0x1c9e*/ 553, - /*0x10c9e*/ 1366, + /*0x1fb8*/ 820, + -1, + /*0x10a7*/ 491, -1, -1, - /*0x1e91e*/ 1481, - /*0x2ca2*/ 990, - /*0x1e24*/ 603, - /*0x1040e*/ 1274, - /*0x1f8e*/ 781, - /*0x040e*/ 311, - /*0x020e*/ 197, - /*0x010e*/ 64, - /*0xab8e*/ 1172, - /*0x04a6*/ 376, - /*0x0526*/ 440, - /*0x018e*/ 129, - /*0x038e*/ 239, - /*0xff27*/ 1240, - /*0xa7a2*/ 1119, - /*0x2c0e*/ 925, - /*0x1ea2*/ 668, + /*0xabb8*/ 1217, + /*0x1f8c*/ 779, + /*0x040c*/ 309, + /*0x010c*/ 63, + /*0x1040c*/ 1275, + /*0x1cae*/ 569, + /*0xab8c*/ 1173, + /*0x1eb8*/ 679, + /*0x1e38*/ 613, + /*0x118a4*/ 1394, + /*0x10a2*/ 486, + /*0x2c0c*/ 923, -1, - /*0x1faa*/ 809, - /*0x042a*/ 339, - /*0x022a*/ 211, - /*0x012a*/ 78, - /*0xabaa*/ 1200, - /*0x1ca2*/ 557, - /*0x10ca2*/ 1370, + /*0x1e8c*/ 655, + /*0x1e0c*/ 591, + /*0x022e*/ 213, + /*0x2cb8*/ 1001, + /*0x1ffc*/ 863, + /*0x047c*/ 359, + /*0x04aa*/ 378, + /*0x1f5b*/ 756, + /*0x1fba*/ 822, + /*0x2c8c*/ 979, + /*0xa7b8*/ 1134, + /*0x10ac*/ 496, + /*0x0522*/ 438, + /*0xabba*/ 1219, + /*0x1c82*/ 532, + /*0x1f2a*/ 731, + /*0x1efc*/ 713, + /*0x1e7c*/ 647, + /*0x212a*/ 865, + /*0x10c8c*/ 1351, + /*0x1eba*/ 680, + /*0x1e3a*/ 614, + /*0x13fc*/ 528, + /*0x048e*/ 364, + /*0x0202*/ 191, -1, - /*0x03aa*/ 266, + /*0x052c*/ 443, -1, - /*0x2c8e*/ 980, - /*0x2c2a*/ 953, + /*0x1e90e*/ 1468, + /*0x2cba*/ 1002, -1, -1, - /*0x1e1a*/ 598, + /*0x1f0e*/ 721, + /*0x0194*/ 134, + -1, -1, + /*0xa7ba*/ 1135, + /*0x038c*/ 238, + /*0x10b2*/ 502, + /*0x0130*/ 1489, + /*0x01d7*/ 168, + -1, + /*0xabb0*/ 1209, + /*0x1fbe*/ 825, -1, -1, -1, - /*0x04a4*/ 375, - /*0x0524*/ 439, + /*0x1ca7*/ 562, + /*0xabbe*/ 1223, + /*0x1eb0*/ 675, + /*0x1e30*/ 609, + -1, + /*0x10a8*/ 492, + /*0x0532*/ 446, + -1, + /*0x1ebe*/ 682, + /*0x1e3e*/ 616, + -1, + /*0x2cb0*/ 997, + -1, + /*0x1ca2*/ 557, -1, -1, -1, - /*0x0370*/ 230, - /*0x2caa*/ 994, - /*0x1e8e*/ 656, + /*0x2cbe*/ 1004, + /*0xa7b0*/ 1128, + /*0x1f2f*/ 736, + /*0x0528*/ 441, + /*0x10cb0*/ 1387, -1, - /*0x1fae*/ 813, - /*0x042e*/ 343, - /*0x022e*/ 213, - /*0x012e*/ 80, - /*0xabae*/ 1204, + /*0x0222*/ 207, + /*0xa7be*/ 1137, -1, - /*0x10c8e*/ 1350, - /*0x01ae*/ 148, + /*0x1e904*/ 1458, + /*0x1cac*/ 567, -1, - /*0x1e90e*/ 1465, - /*0xa7aa*/ 1123, - /*0x2c2e*/ 957, - /*0x1eaa*/ 672, - -1, -1, -1, -1, -1, - /*0x1f1a*/ 725, - /*0x1caa*/ 565, - /*0x10caa*/ 1378, - /*0x049a*/ 370, - /*0x051a*/ 434, + /*0x1fb6*/ 818, -1, - /*0x2cae*/ 996, - /*0x1fac*/ 811, - /*0x042c*/ 341, - /*0x022c*/ 212, - /*0x012c*/ 79, - /*0xabac*/ 1202, + /*0x0136*/ 83, -1, -1, - /*0x01ac*/ 147, - /*0x2165*/ 873, - /*0x00d3*/ 45, - /*0x2167*/ 875, - /*0x2c2c*/ 955, - /*0xa7ae*/ 1127, - /*0x2161*/ 869, - /*0x1eae*/ 674, - /*0x118a0*/ 1387, - /*0x1fba*/ 822, - /*0x216d*/ 881, - /*0x023a*/ 216, - /*0x10b2*/ 502, - /*0xabba*/ 1216, - /*0x1cae*/ 569, - /*0x10cae*/ 1382, - /*0x104d3*/ 1335, - /*0x2cac*/ 995, - /*0x1f6b*/ 762, - /*0x0553*/ 479, - /*0x1fa8*/ 807, - /*0x0428*/ 337, - /*0x0228*/ 210, - /*0x0128*/ 77, - /*0xaba8*/ 1198, - -1, - /*0x1e12*/ 594, + /*0xabb6*/ 1215, + /*0x1f8d*/ 780, + /*0x040d*/ 310, + /*0x022c*/ 212, + /*0x1040d*/ 1276, + /*0x03b0*/ 268, + /*0xab8d*/ 1174, + /*0x1eb6*/ 678, + /*0x1e36*/ 612, + /*0x04ae*/ 380, -1, - /*0x03a8*/ 264, + /*0x2c0d*/ 924, + -1, -1, -1, + /*0x019c*/ 138, + /*0x2cb6*/ 1000, + /*0xfb03*/ 1228, + /*0x1f2e*/ 735, -1, - /*0xa7ac*/ 1125, - /*0x2c28*/ 951, - /*0x1eac*/ 673, - /*0x2cba*/ 1002, + /*0x1cb2*/ 573, -1, - /*0x118a6*/ 1393, + /*0xa77b*/ 1102, + /*0xa7b6*/ 1133, + -1, -1, + /*0x1fb4*/ 817, + /*0x10b8*/ 508, + /*0x0134*/ 82, + /*0xa78d*/ 1110, + /*0x0232*/ 215, + /*0xabb4*/ 1213, + /*0x10c8d*/ 1352, -1, - /*0x10af*/ 499, + /*0x1ca8*/ 563, + /*0xa77d*/ 1103, + /*0x1e902*/ 1456, -1, - /*0x1cac*/ 567, - /*0x10cac*/ 1380, + /*0x1eb4*/ 677, + /*0x1e34*/ 611, + -1, -1, + /*0x0538*/ 452, -1, - /*0x1e32*/ 610, - /*0x2163*/ 871, - /*0x2ca8*/ 993, - /*0x216f*/ 883, - /*0xa7ba*/ 1135, + /*0x0228*/ 210, + /*0x01db*/ 170, -1, - /*0x1eba*/ 680, - /*0x1fb8*/ 820, + /*0x2cb4*/ 999, + /*0x050c*/ 427, -1, -1, -1, - /*0xabb8*/ 1214, - -1, - /*0x1cba*/ 581, - /*0x01b8*/ 155, - /*0xa7a8*/ 1122, - /*0xff26*/ 1239, - /*0x1ea8*/ 671, - /*0x0492*/ 366, - /*0x0512*/ 430, - /*0x118a4*/ 1391, - -1, -1, - /*0x1fb6*/ 818, - /*0x1ca8*/ 563, - /*0x10ca8*/ 1376, - /*0x0136*/ 83, - /*0xabb6*/ 1212, - -1, -1, + /*0x1fbc*/ 824, + /*0x10ba*/ 510, + /*0xa7b4*/ 1132, /*0xa688*/ 1053, - /*0x2cb8*/ 1001, - /*0x104b2*/ 1302, -1, - /*0x04b2*/ 382, - /*0x0532*/ 446, - /*0x1040c*/ 1272, - /*0x1f8c*/ 779, - /*0x040c*/ 309, - /*0x020c*/ 196, - /*0x010c*/ 63, - /*0xab8c*/ 1170, + /*0xabbc*/ 1221, + -1, -1, -1, + /*0xfb14*/ 1233, + -1, -1, + /*0x1ebc*/ 681, + /*0x1e3c*/ 615, + /*0x1f59*/ 755, -1, - /*0xff24*/ 1237, - /*0xa7b8*/ 1134, - /*0x038c*/ 238, - /*0x1eb8*/ 679, - /*0x2cb6*/ 1000, - /*0x2c0c*/ 923, + /*0x053a*/ 454, + /*0xa72a*/ 1067, + /*0x018e*/ 129, + /*0x0055*/ 19, /*0xa68a*/ 1054, - -1, -1, -1, + /*0x2cbc*/ 1003, + /*0xff2a*/ 1246, + -1, + /*0x00d5*/ 47, + /*0x04a2*/ 374, + /*0xa680*/ 1049, + /*0x24b8*/ 887, + /*0xa7bc*/ 1136, + -1, + /*0x10b0*/ 500, + -1, -1, -1, -1, -1, + /*0x10be*/ 514, + -1, /*0x1cb8*/ 579, + /*0x04ac*/ 379, + -1, -1, -1, + /*0xa698*/ 1061, -1, -1, - /*0x1f2f*/ 736, + /*0x118aa*/ 1400, -1, - /*0x1e1c*/ 599, - /*0xa779*/ 1101, - /*0xa7b6*/ 1133, - /*0x2c8c*/ 979, - /*0x1eb6*/ 678, - /*0xa680*/ 1049, - /*0x0230*/ 214, - /*0x0130*/ 1486, - /*0xabb0*/ 1206, + /*0x1f2c*/ 733, -1, -1, - /*0x1cb6*/ 577, - /*0x03b0*/ 268, + /*0x053e*/ 458, + /*0x01af*/ 149, + /*0x24ba*/ 889, + /*0x020c*/ 196, + -1, -1, -1, -1, -1, + /*0xa69a*/ 1062, + -1, -1, + /*0x0184*/ 123, + /*0x1cba*/ 581, -1, - /*0x1f69*/ 760, - /*0xa726*/ 1065, - /*0x1fbc*/ 824, + /*0x04b2*/ 382, + /*0x03d5*/ 273, + /*0x104b2*/ 1305, + /*0x10b6*/ 506, + /*0x1fca*/ 833, + /*0x004a*/ 8, + /*0x014a*/ 93, + /*0xff2f*/ 1251, + /*0x023a*/ 216, -1, - /*0x1e8c*/ 655, + /*0x00ca*/ 36, + /*0xa696*/ 1060, + /*0x2132*/ 867, -1, - /*0xabbc*/ 1218, - -1, -1, - /*0x01bc*/ 156, - /*0x10a2*/ 486, + /*0x04a8*/ 377, -1, - /*0x10c8c*/ 1348, - /*0x1e1e*/ 600, - /*0x2cb0*/ 997, - /*0x1e90c*/ 1463, + /*0x1eca*/ 688, + /*0x1e4a*/ 622, + /*0x0536*/ 450, + /*0x01ae*/ 148, + -1, -1, + /*0x24be*/ 893, + /*0x1f28*/ 729, -1, - /*0x1f1c*/ 727, - /*0xa698*/ 1061, - /*0x1e70*/ 641, - /*0x049c*/ 371, - /*0x051c*/ 435, + /*0x2cca*/ 1010, -1, - /*0xa77b*/ 1102, + /*0x1cb0*/ 571, + /*0xa690*/ 1057, -1, -1, - /*0x2cbc*/ 1003, - /*0xa7b0*/ 1128, - /*0xa724*/ 1064, - /*0x1eb0*/ 675, + /*0x118af*/ 1405, + -1, + /*0x1cbe*/ 583, + /*0x10b4*/ 504, + /*0xa72e*/ 1069, + -1, + /*0x0230*/ 214, -1, -1, - /*0xa696*/ 1060, - -1, -1, -1, - /*0x1cb0*/ 571, - /*0x10cb0*/ 1384, + /*0xff2e*/ 1250, + /*0x0182*/ 122, -1, - /*0xa7bc*/ 1136, - /*0x1e22*/ 602, - /*0x1ebc*/ 681, - -1, -1, -1, -1, - /*0x1fd2*/ 836, - /*0x049e*/ 372, - /*0x051e*/ 436, - /*0x0152*/ 97, - /*0x0052*/ 16, - /*0x10aa*/ 494, - /*0x1fcc*/ 835, - /*0x04f0*/ 413, - /*0x024c*/ 227, - /*0x014c*/ 94, - /*0x004c*/ 10, + /*0x023e*/ 219, -1, - /*0x1fbe*/ 825, /*0xa686*/ 1052, - /*0x023e*/ 219, + -1, -1, -1, + /*0x0534*/ 448, + -1, -1, -1, -1, -1, + /*0x24b6*/ 885, + /*0x1ff6*/ 857, + /*0x0476*/ 356, + /*0x0176*/ 115, -1, - /*0xabbe*/ 1220, - -1, -1, - /*0x118b2*/ 1405, + /*0x10bc*/ 512, -1, - /*0x1e0e*/ 592, - /*0x1fb4*/ 817, + /*0xa692*/ 1058, -1, - /*0x2cd2*/ 1014, - /*0x0134*/ 82, - /*0xabb4*/ 1210, - /*0xa77d*/ 1103, - /*0x04a2*/ 374, - /*0x0522*/ 438, - /*0x2ccc*/ 1011, + /*0x118ae*/ 1404, -1, - /*0x10ae*/ 498, - -1, -1, - /*0x1e2a*/ 606, - /*0x2cbe*/ 1004, - -1, -1, - /*0x1ed2*/ 692, - /*0xa694*/ 1059, + /*0x1cb6*/ 577, + /*0x01d9*/ 169, + /*0x1ef6*/ 710, + /*0x1e76*/ 644, + /*0x04b8*/ 385, -1, - /*0xff32*/ 1251, + /*0x104b8*/ 1311, -1, - /*0x118af*/ 1402, - /*0x1ecc*/ 689, - /*0x2cb4*/ 999, + /*0x01a7*/ 145, + /*0x053c*/ 456, + /*0x048c*/ 363, -1, -1, - /*0xa7be*/ 1137, + /*0x1f38*/ 737, -1, - /*0x1ebe*/ 682, - /*0x1f0e*/ 721, + /*0x1e90c*/ 1466, + -1, -1, -1, + /*0x1f0c*/ 719, -1, - /*0xa690*/ 1057, - /*0x048e*/ 364, - /*0x050e*/ 428, - /*0x10ac*/ 496, - /*0x1cbe*/ 583, - /*0xa7b4*/ 1132, + /*0x01a2*/ 142, + /*0x1fc9*/ 832, + /*0x0049*/ 1488, + /*0x0149*/ 92, -1, - /*0x1eb4*/ 677, - /*0x1e2e*/ 608, - -1, -1, -1, - /*0x1f2a*/ 731, - /*0xff2f*/ 1248, + /*0x04fc*/ 419, + /*0x0555*/ 481, + /*0x00c9*/ 35, + /*0xff27*/ 1243, + /*0x04ba*/ 386, /*0x1cb4*/ 575, - /*0x04aa*/ 378, - /*0x052a*/ 442, - -1, -1, - /*0x10ba*/ 510, + /*0x104ba*/ 1313, -1, -1, - /*0x1fca*/ 833, + /*0x01ac*/ 147, -1, - /*0x024a*/ 226, - /*0x014a*/ 93, - /*0x004a*/ 8, - /*0xa684*/ 1051, - /*0x2126*/ 864, - /*0x01ca*/ 161, - /*0x10a8*/ 492, + /*0xa722*/ 1063, + -1, + /*0x1f3a*/ 739, + /*0xfb04*/ 1229, + -1, + /*0xff22*/ 1238, + -1, -1, -1, + /*0x24bc*/ 891, + -1, -1, -1, + /*0xa7c9*/ 1143, + /*0xa72c*/ 1068, + -1, + /*0x118a7*/ 1397, -1, -1, - /*0x1e2c*/ 607, - -1, -1, -1, -1, -1, - /*0x1f2e*/ 735, + /*0xff2c*/ 1248, + -1, -1, + /*0x04b0*/ 381, -1, - /*0xa682*/ 1050, - /*0x04ae*/ 380, - /*0x052e*/ 444, + /*0x104b0*/ 1303, + /*0x01b2*/ 151, + -1, -1, + /*0x04be*/ 388, + /*0x118a2*/ 1392, + /*0x104be*/ 1317, + -1, -1, -1, -1, + /*0x0376*/ 232, -1, + /*0x1f3e*/ 743, + /*0x1fc4*/ 828, + /*0x0044*/ 3, + /*0x0051*/ 15, /*0xa732*/ 1070, - /*0x2cca*/ 1010, + /*0x054a*/ 470, + /*0x118ac*/ 1402, + /*0x00c4*/ 30, + /*0x00d1*/ 43, + /*0xff32*/ 1254, + /*0xfb02*/ 1227, + -1, -1, + /*0x1ec4*/ 685, + /*0x1e44*/ 619, + /*0x1fcc*/ 835, + /*0x004c*/ 10, + /*0x014c*/ 94, + /*0xa728*/ 1066, + /*0x1ffa*/ 861, + /*0x047a*/ 358, + /*0x00cc*/ 38, + /*0x2cc4*/ 1007, + /*0xff28*/ 1244, + /*0x04b6*/ 384, -1, - /*0x1fc4*/ 828, - /*0x1e3a*/ 614, - /*0x0244*/ 222, + /*0x104b6*/ 1309, + /*0x1ecc*/ 689, + /*0x1e4c*/ 623, + /*0xa7c4*/ 1139, -1, - /*0x0044*/ 3, - /*0x004f*/ 13, + /*0x1efa*/ 712, + /*0x1e7a*/ 646, + /*0x118b2*/ 1408, -1, - /*0x01c4*/ 157, - /*0x01cf*/ 164, - /*0x03cf*/ 270, + /*0x1e90d*/ 1467, + /*0x2ccc*/ 1011, + /*0x13fa*/ 526, + -1, + /*0x1f0d*/ 720, + /*0x1fc8*/ 831, + /*0x0048*/ 7, + /*0x24ca*/ 905, -1, - /*0x10b8*/ 508, - /*0x1e28*/ 605, - /*0x1eca*/ 688, /*0x1fab*/ 810, /*0x042b*/ 340, - /*0x1f2c*/ 733, - -1, - /*0xabab*/ 1201, - /*0x04ac*/ 379, - /*0x052c*/ 443, + /*0x00c8*/ 34, + /*0x118a8*/ 1398, -1, - /*0x03ab*/ 267, + /*0xabab*/ 1204, -1, - /*0x2cc4*/ 1007, + /*0x03d1*/ 272, + /*0x1ec8*/ 687, + /*0x1e48*/ 621, /*0x2c2b*/ 954, - /*0x1fc2*/ 826, - /*0x10b6*/ 506, - /*0x24ba*/ 889, - /*0x118a2*/ 1389, - /*0x0042*/ 1, + /*0x04b4*/ 383, -1, - /*0x1f3a*/ 739, - /*0x104ba*/ 1310, - /*0x03c2*/ 269, - /*0x04ba*/ 386, - /*0x053a*/ 454, - /*0xa7c4*/ 1139, - /*0x1fc8*/ 831, - /*0x1ec4*/ 685, - /*0x0248*/ 225, - /*0x1e38*/ 613, - /*0x0048*/ 7, - /*0x1f28*/ 729, + /*0x104b4*/ 1307, + /*0x01b8*/ 155, + -1, -1, + /*0x2cc8*/ 1009, -1, - /*0x01c8*/ 160, - /*0x04a8*/ 377, - /*0x0528*/ 441, + /*0x024a*/ 226, + /*0x1fc2*/ 826, + /*0x0042*/ 1, -1, -1, - /*0x2cc2*/ 1006, + /*0x03fa*/ 293, + /*0xa64a*/ 1031, + /*0x00c2*/ 28, + /*0xa694*/ 1059, /*0xa7ab*/ 1124, - /*0xff22*/ 1235, - -1, -1, -1, -1, - /*0x1e36*/ 612, - -1, -1, - /*0x1cab*/ 566, - /*0x10cab*/ 1379, - /*0x2cc8*/ 1009, - /*0xa7c2*/ 1138, -1, + /*0xa738*/ 1073, + /*0x10cab*/ 1382, /*0x1ec2*/ 684, - /*0x10b0*/ 500, - -1, - /*0x24b8*/ 887, - /*0x216b*/ 879, - /*0x118aa*/ 1397, - /*0x1e0c*/ 591, - /*0x1f38*/ 737, - /*0x104b8*/ 1308, - -1, - /*0x04b8*/ 385, - /*0x0538*/ 452, - /*0x1ec8*/ 687, - /*0x10bc*/ 512, - /*0x1fd6*/ 838, - /*0x0150*/ 96, - /*0x0050*/ 14, - /*0x0156*/ 99, - /*0x0056*/ 20, - /*0x24b6*/ 885, - /*0x03d0*/ 271, + /*0x1e42*/ 618, -1, - /*0x03d6*/ 274, - /*0x1fdb*/ 843, - /*0x104b6*/ 1306, + /*0xff38*/ 1260, + /*0x01fc*/ 188, + /*0x04bc*/ 387, -1, - /*0x04b6*/ 384, - /*0x0536*/ 450, - /*0xff2a*/ 1243, + /*0x104bc*/ 1315, -1, - /*0x01db*/ 170, - /*0x1e30*/ 609, - /*0x118ae*/ 1401, + /*0x2cc2*/ 1006, -1, -1, -1, - /*0x2cd0*/ 1013, - /*0x1f0c*/ 719, - /*0x2cd6*/ 1016, - /*0xa69a*/ 1062, - /*0x048c*/ 363, - /*0x050c*/ 427, - -1, - /*0x1e3c*/ 615, - /*0xa722*/ 1063, - -1, -1, -1, -1, -1, -1, - /*0x1ed0*/ 691, - /*0x1fc6*/ 829, - /*0x1ed6*/ 694, - /*0x0246*/ 224, - /*0xff2e*/ 1247, - /*0x0046*/ 5, - /*0x118ac*/ 1399, - -1, - /*0x2132*/ 867, - /*0x024e*/ 228, - /*0x014e*/ 95, - /*0x004e*/ 12, - /*0x104b0*/ 1300, - /*0x1fda*/ 842, - /*0x04b0*/ 381, + /*0x0549*/ 469, + /*0x1f3c*/ 741, -1, - /*0x015a*/ 101, - /*0x005a*/ 24, - /*0x10be*/ 514, - /*0x24bc*/ 891, + /*0xa7c2*/ 1138, + /*0x03ab*/ 267, -1, - /*0x03da*/ 276, - /*0x118ba*/ 1413, - /*0x1f3c*/ 741, - /*0x104bc*/ 1312, - /*0x2cc6*/ 1008, - /*0x04bc*/ 387, - /*0x053c*/ 456, - /*0x10b4*/ 504, - /*0xff2c*/ 1245, + /*0x1fd6*/ 838, + /*0x0056*/ 20, + /*0x0156*/ 99, + -1, -1, + /*0xa73a*/ 1074, + /*0x00d6*/ 48, -1, - /*0x2cce*/ 1012, + /*0x118b8*/ 1414, -1, - /*0x118a8*/ 1395, - /*0xa72a*/ 1067, + /*0xff3a*/ 1262, -1, - /*0x1e52*/ 626, - /*0x2cda*/ 1018, - /*0xa7c6*/ 1141, + /*0x1ed6*/ 694, + /*0x1e56*/ 628, + /*0x1fd2*/ 836, + /*0x0052*/ 16, + /*0x0152*/ 97, -1, - /*0x1ec6*/ 686, + /*0x03c2*/ 269, -1, - /*0x1e4c*/ 623, + /*0x00d2*/ 44, + /*0x2cd6*/ 1016, -1, -1, - /*0xff3a*/ 1259, - /*0x1ece*/ 690, - /*0xa652*/ 1035, - /*0x1e3e*/ 616, - /*0x2169*/ 877, + /*0x1fc6*/ 829, + /*0x0046*/ 5, + /*0x1ed2*/ 692, + /*0x1e52*/ 626, -1, -1, - /*0x1eda*/ 696, - /*0xa64c*/ 1032, - /*0x00d2*/ 44, - -1, - /*0xff28*/ 1241, - -1, - /*0x1e34*/ 611, - /*0xa692*/ 1058, - /*0x00cc*/ 38, - /*0xa72e*/ 1069, - /*0x118b8*/ 1411, - -1, -1, -1, -1, - /*0x1f52*/ 752, - /*0x104d2*/ 1334, - /*0x24cc*/ 907, - /*0x04d2*/ 398, - /*0x0552*/ 478, - -1, - /*0x1f4c*/ 749, - /*0x104cc*/ 1328, - /*0x24be*/ 893, - /*0x2cc0*/ 1005, - /*0x054c*/ 472, - /*0x118b6*/ 1409, - /*0x1f3e*/ 743, - /*0x104be*/ 1314, + /*0x00c6*/ 32, + /*0x24c9*/ 904, + /*0x10c4*/ 520, -1, - /*0x04be*/ 388, - /*0x053e*/ 458, + /*0x118ba*/ 1416, + /*0x2cd2*/ 1014, + /*0x1ec6*/ 686, + /*0x1e46*/ 620, -1, - /*0xff38*/ 1257, - /*0xa72c*/ 1068, - -1, -1, -1, - /*0x104b4*/ 1304, - /*0x1ec0*/ 683, - /*0x04b4*/ 383, - /*0x0534*/ 448, - -1, -1, + /*0xff30*/ 1252, + /*0xa73e*/ 1076, /*0x1fe2*/ 844, /*0x0462*/ 346, - -1, /*0x0162*/ 105, -1, - /*0xff36*/ 1255, - /*0xa73a*/ 1074, - /*0x01e2*/ 173, - /*0x03e2*/ 280, - /*0x0154*/ 98, - /*0x0054*/ 18, - /*0x2c62*/ 959, - /*0x10c4*/ 520, - -1, -1, -1, - /*0x1e4a*/ 622, - /*0xa728*/ 1066, - -1, -1, -1, - /*0x118b0*/ 1403, - -1, -1, - /*0x2ce2*/ 1022, - -1, - /*0x10ab*/ 495, - /*0xa64a*/ 1031, - /*0x1fd8*/ 840, - -1, - /*0x2cd4*/ 1015, - /*0x0158*/ 100, - /*0x0058*/ 22, - /*0x118bc*/ 1415, - /*0x00ca*/ 36, - -1, - /*0x03d8*/ 275, + /*0x2cc6*/ 1008, -1, - /*0x10c2*/ 518, + /*0x0544*/ 464, + /*0x0551*/ 477, + /*0x03d6*/ 274, + -1, + /*0x2c62*/ 959, + /*0xa7c6*/ 1141, /*0x1ee2*/ 700, - -1, -1, - /*0x1e44*/ 619, - /*0x24ca*/ 905, - /*0xff30*/ 1249, - /*0x1ed4*/ 693, - /*0xa738*/ 1073, + /*0x1e62*/ 634, + -1, -1, -1, + /*0x104ca*/ 1329, + /*0x0050*/ 14, + /*0x0150*/ 96, + /*0x054c*/ 472, + /*0x2ce2*/ 1022, + /*0x118b0*/ 1406, + /*0x00d0*/ 42, /*0x1f4a*/ 747, - /*0x104ca*/ 1326, - -1, -1, - /*0x054a*/ 470, - /*0x2cd8*/ 1017, - /*0xa644*/ 1028, - /*0x1040d*/ 1273, - /*0x1f8d*/ 780, - /*0x040d*/ 310, - -1, -1, - /*0xab8d*/ 1171, - /*0x00c4*/ 30, - /*0x00cf*/ 41, + -1, -1, -1, + /*0x118be*/ 1420, + /*0x1ed0*/ 691, + /*0x1e50*/ 625, + -1, /*0xa736*/ 1072, + -1, + /*0x10ab*/ 495, + -1, -1, + /*0xff36*/ 1258, + /*0x2cd0*/ 1013, + /*0x004e*/ 12, + /*0x014e*/ 95, -1, -1, - /*0x212a*/ 865, - /*0x2c0d*/ 924, - /*0x1ed8*/ 695, - /*0x1e42*/ 618, /*0x24c4*/ 899, - /*0x24cf*/ 910, + /*0x00ce*/ 40, + /*0x0548*/ 468, -1, -1, -1, - /*0x104c4*/ 1320, - /*0x104cf*/ 1331, + /*0x03e2*/ 280, + /*0x1ece*/ 690, + /*0x1e4e*/ 624, + /*0x16e5f*/ 1453, + /*0xa68e*/ 1056, + /*0x10c2*/ 518, + -1, -1, + /*0x24cc*/ 907, -1, - /*0x0544*/ 464, - /*0x054f*/ 475, - /*0xa642*/ 1027, - /*0x1e48*/ 621, - -1, -1, -1, -1, -1, - /*0x00c2*/ 28, - /*0x1f2b*/ 732, + /*0x2cce*/ 1012, -1, - /*0x118be*/ 1417, - /*0x0055*/ 19, - /*0xa648*/ 1030, - /*0xa78d*/ 1110, - /*0x01d5*/ 167, - /*0x03d5*/ 273, - /*0x24c2*/ 897, - -1, -1, - /*0x00c8*/ 34, - /*0x118b4*/ 1407, - /*0x104c2*/ 1318, + /*0x118b6*/ 1412, + -1, + /*0xa734*/ 1071, + /*0x0244*/ 222, -1, - /*0x10c8d*/ 1349, + /*0x03d0*/ 271, + /*0x04f6*/ 416, + /*0xff34*/ 1256, /*0x0542*/ 462, + /*0xa644*/ 1028, + -1, -1, + /*0x01bc*/ 156, + /*0x1fda*/ 842, + /*0x005a*/ 24, + /*0x015a*/ 101, + -1, + /*0x024c*/ 227, -1, - /*0x1e90d*/ 1464, + /*0x00da*/ 51, -1, /*0x24c8*/ 903, - -1, -1, -1, - /*0x1f48*/ 745, - /*0x104c8*/ 1324, - /*0xa73c*/ 1075, -1, - /*0x0548*/ 468, - -1, -1, - /*0xa68e*/ 1056, - /*0x1e50*/ 625, + /*0xa64c*/ 1032, -1, - /*0x1e56*/ 628, - /*0xff34*/ 1253, - /*0x0245*/ 223, - /*0x0145*/ 90, - /*0x0045*/ 4, + /*0x1eda*/ 696, + /*0x1e5a*/ 630, -1, - /*0x16e5f*/ 1450, - /*0x01c5*/ 158, + /*0xa73c*/ 1075, -1, - /*0xa650*/ 1034, - /*0x1fd9*/ 841, - /*0xa656*/ 1037, - /*0x1fec*/ 853, - /*0x046c*/ 351, - /*0x0059*/ 23, - /*0x016c*/ 110, - /*0x00d0*/ 42, - /*0x01d9*/ 169, - /*0x00d6*/ 48, - /*0x01ec*/ 178, - /*0x03ec*/ 285, - /*0x16e5d*/ 1448, - -1, -1, - /*0x16e47*/ 1426, + /*0x01d5*/ 167, + /*0x118b4*/ 1410, -1, -1, - /*0x00db*/ 52, + /*0x2cda*/ 1018, -1, - /*0x1f50*/ 751, - /*0x104d0*/ 1332, - /*0x1f56*/ 754, - /*0x04d0*/ 397, - /*0x0550*/ 476, - /*0x04d6*/ 400, + /*0x1cab*/ 566, + /*0xa684*/ 1051, + /*0x04c9*/ 394, /*0x0556*/ 482, - /*0xa752*/ 1086, - /*0xa7c5*/ 1140, - /*0x1e46*/ 620, + /*0x104c9*/ 1328, -1, - /*0x1f5b*/ 756, + /*0x0248*/ 225, + -1, -1, + /*0x24c2*/ 897, -1, - /*0xa74c*/ 1083, + /*0x1f49*/ 746, + /*0xa648*/ 1030, + /*0x0054*/ 18, + /*0x0154*/ 98, + -1, -1, + /*0x0552*/ 478, + /*0x00d4*/ 46, + -1, -1, + /*0x118bc*/ 1418, + /*0x16e5d*/ 1451, -1, - /*0x1e4e*/ 624, - -1, -1, -1, - /*0xa73e*/ 1076, - /*0xa646*/ 1029, - /*0x1e5a*/ 630, - /*0x1eec*/ 705, - -1, -1, -1, - /*0xa64e*/ 1033, - /*0x00c6*/ 32, + /*0x1ed4*/ 693, + /*0x1e54*/ 627, + /*0x03da*/ 276, + /*0x0546*/ 466, + /*0x1fd8*/ 840, + /*0x0058*/ 22, + /*0x0158*/ 100, + -1, -1, + /*0x2cd4*/ 1015, + /*0x00d8*/ 49, -1, - /*0xa734*/ 1071, - /*0x10c0*/ 516, + /*0xa642*/ 1027, + -1, -1, -1, + /*0x1ed8*/ 695, + /*0x1e58*/ 629, + /*0x1ff8*/ 859, + /*0x0478*/ 357, + /*0x0178*/ 116, + /*0xa682*/ 1050, + /*0x01ca*/ 161, + /*0x1fd3*/ 837, + /*0x0053*/ 17, + /*0x2cd8*/ 1017, + /*0x1fc3*/ 827, + /*0x0043*/ 2, + /*0x0143*/ 89, + /*0x00d3*/ 45, + /*0x1ef8*/ 711, + /*0x1e78*/ 645, + /*0x00c3*/ 29, + /*0x104c4*/ 1323, + /*0x104d1*/ 1336, -1, - /*0xa65a*/ 1039, - /*0x00ce*/ 40, - /*0x1fc9*/ 832, + /*0x13f8*/ 524, + /*0x0550*/ 476, + /*0xa74a*/ 1082, -1, /*0x24c6*/ 901, - /*0x0149*/ 92, - /*0x0049*/ 1485, - /*0x00da*/ 51, + -1, -1, + /*0xa656*/ 1037, + -1, -1, -1, + /*0x104cc*/ 1331, -1, - /*0x104c6*/ 1322, - /*0x24ce*/ 909, - /*0x118ab*/ 1398, - /*0x0546*/ 466, + /*0x04fa*/ 418, + /*0x1fc7*/ 830, + /*0x0047*/ 6, + /*0x0147*/ 91, + /*0x03d8*/ 275, + /*0x1f4c*/ 749, + -1, + /*0x00c7*/ 33, + /*0xa652*/ 1035, + /*0x054e*/ 474, -1, -1, - /*0x104ce*/ 1330, + /*0x0246*/ 224, + /*0x00c0*/ 26, -1, -1, - /*0x054e*/ 474, - /*0x1fea*/ 851, - /*0x046a*/ 350, + /*0x0045*/ 4, + /*0x0145*/ 90, + /*0xa646*/ 1029, + /*0x1ec0*/ 683, + /*0x1e40*/ 617, + /*0x00c5*/ 31, -1, - /*0x016a*/ 109, - /*0x04da*/ 402, - /*0x0345*/ 229, + /*0x104c8*/ 1327, -1, - /*0x01ea*/ 177, - /*0x03ea*/ 284, - /*0x1e40*/ 617, + /*0x01f6*/ 184, /*0x1fa9*/ 808, /*0x0429*/ 338, + /*0x2cc0*/ 1005, + /*0xa7c7*/ 1142, + /*0x1f48*/ 745, + /*0xaba9*/ 1202, + -1, + /*0x004d*/ 11, + /*0x1f2b*/ 732, + /*0xa662*/ 1043, + /*0x2c29*/ 952, + /*0x212b*/ 866, + /*0x00cd*/ 39, + /*0x1f97*/ 790, + /*0x0417*/ 320, + -1, + /*0x10417*/ 1286, + /*0xa7c5*/ 1140, + /*0xab97*/ 1184, + -1, + /*0x24ce*/ 909, + /*0x104c2*/ 1321, + -1, + /*0x2c17*/ 934, + -1, + /*0x1e97*/ 661, + /*0xa650*/ 1034, + /*0x046e*/ 352, + /*0x016e*/ 111, -1, -1, - /*0xaba9*/ 1199, - /*0xff2b*/ 1244, + /*0x10ca9*/ 1380, + /*0x1fa1*/ 800, + /*0x0421*/ 330, + /*0x047e*/ 360, + /*0x10421*/ 1296, + /*0x2c6e*/ 966, + /*0xaba1*/ 1194, + /*0x1eee*/ 706, + /*0x1e6e*/ 640, + -1, + /*0x024e*/ 228, + /*0x2c21*/ 944, + /*0x2c7e*/ 971, + /*0x10c97*/ 1362, + /*0x1efe*/ 714, + /*0x1e7e*/ 648, + /*0xa64e*/ 1033, -1, - /*0x01a9*/ 146, /*0x03a9*/ 265, + /*0x04d6*/ 400, + -1, -1, -1, + /*0x0554*/ 480, + /*0x1fec*/ 853, + /*0x046c*/ 351, + /*0x016c*/ 110, -1, - /*0xa640*/ 1026, - /*0x2c29*/ 952, - /*0x1fc3*/ 827, - -1, - /*0x0243*/ 221, - /*0x0143*/ 89, - /*0x0043*/ 2, - /*0x00c0*/ 26, - /*0x10421*/ 1293, - /*0x1fa1*/ 800, - /*0x0421*/ 330, + /*0x1f56*/ 754, + -1, -1, + /*0x0397*/ 248, + /*0x10ca1*/ 1372, + /*0x04d2*/ 398, -1, - /*0xa74a*/ 1082, - /*0xaba1*/ 1191, + /*0x104d2*/ 1337, + /*0x1eec*/ 705, + /*0x1e6c*/ 639, -1, -1, - /*0x24c0*/ 895, + /*0x0345*/ 229, + -1, + /*0x1f52*/ 752, + -1, + /*0x03ee*/ 286, + /*0x104c6*/ 1325, + /*0x10c3*/ 519, + -1, -1, -1, /*0x03a1*/ 258, + /*0x03fe*/ 295, + /*0xa65a*/ 1039, + /*0x01c4*/ 157, + /*0x01d1*/ 165, + /*0x1fea*/ 851, + /*0x046a*/ 350, + /*0x016a*/ 109, + /*0x0553*/ 479, -1, - /*0x1eea*/ 704, - /*0x2c21*/ 944, - /*0x104c0*/ 1316, - /*0x1fb9*/ 821, - /*0x04c0*/ 389, - /*0x0540*/ 460, - /*0x0139*/ 84, - /*0xabb9*/ 1215, + /*0x04e2*/ 406, + /*0x0543*/ 463, /*0x1fe8*/ 849, /*0x0468*/ 349, - -1, /*0x0168*/ 108, -1, -1, - /*0x1e62*/ 634, - /*0x01e8*/ 176, - /*0x03e8*/ 283, - /*0x1ca9*/ 564, - /*0x10ca9*/ 1377, + /*0x1eea*/ 704, + /*0x1e6a*/ 638, /*0xa744*/ 1079, - /*0x1e54*/ 627, - -1, - /*0x1fcb*/ 834, - -1, -1, - /*0xa662*/ 1043, - /*0x004b*/ 9, - -1, -1, - /*0x01cb*/ 162, + /*0x10c7*/ 522, + /*0x01fa*/ 187, + /*0x2162*/ 870, + /*0x03ec*/ 285, + /*0x1ee8*/ 703, + /*0x1e68*/ 637, + /*0x10c0*/ 516, + /*0x04d0*/ 397, /*0xa68c*/ 1055, + /*0x104d0*/ 1335, + /*0x16e57*/ 1445, + -1, -1, + /*0xa74c*/ 1083, + /*0x10c5*/ 521, + /*0x0547*/ 467, + /*0x1f50*/ 751, /*0xa654*/ 1036, - -1, -1, -1, -1, - /*0x1ca1*/ 556, - /*0x10ca1*/ 1369, - /*0x00d4*/ 46, - -1, - /*0x1e921*/ 1484, - -1, - /*0x1e58*/ 629, - -1, - /*0x16e57*/ 1442, - /*0xa742*/ 1078, - -1, - /*0x1ee8*/ 703, - /*0x04e2*/ 406, - /*0x1cb9*/ 580, - -1, - /*0x1f54*/ 753, + -1, -1, -1, + /*0x0540*/ 460, + /*0x01c8*/ 160, + -1, -1, + /*0x10a9*/ 493, + -1, -1, + /*0x24c3*/ 898, + /*0x0545*/ 465, + /*0x104ce*/ 1333, + /*0x10cd*/ 523, -1, /*0xa658*/ 1038, - /*0x04d4*/ 399, - /*0x0554*/ 480, - -1, + /*0x03ea*/ 284, + -1, -1, -1, /*0xa748*/ 1081, -1, -1, - /*0x00d8*/ 49, - /*0x10417*/ 1283, - /*0x1f97*/ 790, - /*0x0417*/ 320, + /*0x03e8*/ 283, + -1, /*0x1fe4*/ 846, /*0x0464*/ 347, - /*0xab97*/ 1181, /*0x0164*/ 106, + /*0x054d*/ 473, + /*0xff2b*/ 1247, -1, - /*0x0197*/ 136, - /*0x0397*/ 248, - /*0x01e4*/ 174, - /*0x03e4*/ 281, - /*0x2c17*/ 934, - -1, - /*0x2c64*/ 961, - /*0x04d8*/ 401, + /*0x0243*/ 221, -1, -1, - /*0x0460*/ 345, + /*0x24c7*/ 902, + /*0x2c64*/ 961, -1, - /*0x0160*/ 104, + /*0x1ee4*/ 701, + /*0x1e64*/ 635, + /*0x10a1*/ 485, + /*0x24c0*/ 895, -1, -1, -1, - /*0x01e0*/ 172, - /*0x03e0*/ 279, - /*0x1ff4*/ 856, - /*0x0474*/ 355, - /*0x2c60*/ 958, - /*0x0174*/ 114, + /*0xa742*/ 1078, + /*0x015e*/ 103, + /*0x04da*/ 402, + /*0x015c*/ 102, + /*0x24c5*/ 900, + /*0x00de*/ 55, -1, - /*0x1ffc*/ 863, - /*0x047c*/ 359, - /*0x01f4*/ 183, - /*0x03f4*/ 289, - /*0xa750*/ 1085, + /*0x00dc*/ 53, -1, - /*0xa756*/ 1088, - /*0x01fc*/ 188, - /*0x1f0d*/ 720, - /*0x1e97*/ 661, - /*0x2ce0*/ 1021, - /*0x1ee4*/ 701, + /*0x118ab*/ 1401, -1, - /*0x10c5*/ 521, + /*0x1ede*/ 698, + /*0x1e5e*/ 632, + /*0x1edc*/ 697, + /*0x1e5c*/ 631, + -1, + /*0x1fe6*/ 847, + /*0x0466*/ 348, + /*0x0166*/ 107, + -1, + /*0x2cde*/ 1020, + /*0x24cd*/ 908, + /*0x2cdc*/ 1019, + /*0xa640*/ 1026, + -1, + /*0x0245*/ 223, + /*0x1ca9*/ 564, + -1, + /*0x1ee6*/ 702, + /*0x1e66*/ 636, + /*0x03e4*/ 281, + /*0xa756*/ 1088, + /*0x0460*/ 345, + /*0x0160*/ 104, + /*0x16e5b*/ 1449, -1, -1, + /*0x04d4*/ 399, + -1, /*0x1c97*/ 546, - /*0x10c97*/ 1359, - -1, -1, - /*0x1e917*/ 1474, -1, - /*0x046e*/ 352, + /*0x2c60*/ 958, -1, - /*0x016e*/ 111, /*0x1ee0*/ 699, - /*0x00d5*/ 47, - /*0x13fc*/ 528, - /*0x01ee*/ 179, - /*0x03ee*/ 286, - /*0x1fe6*/ 847, - /*0x0466*/ 348, - /*0x2c6e*/ 966, - /*0x0166*/ 107, - /*0x1ef4*/ 709, + /*0x1e60*/ 633, + /*0xa752*/ 1086, + /*0x1f54*/ 753, -1, - /*0x015e*/ 103, - /*0x01e6*/ 175, - /*0x03e6*/ 282, - /*0x1efc*/ 713, - /*0x01de*/ 171, /*0x03de*/ 278, -1, - /*0x0555*/ 481, - /*0xa746*/ 1080, - -1, -1, - /*0x16e53*/ 1438, - -1, -1, - /*0xa74e*/ 1084, - -1, -1, -1, -1, - /*0x1e6c*/ 639, - /*0xa75a*/ 1090, - /*0x2cde*/ 1020, + /*0x03dc*/ 277, -1, - /*0x0051*/ 15, - /*0x1eee*/ 706, - /*0x00c5*/ 31, - /*0x01d1*/ 165, - /*0x03d1*/ 272, - -1, -1, - /*0xa66c*/ 1048, + /*0x2ce0*/ 1021, + /*0x04d8*/ 401, -1, - /*0x212b*/ 866, - /*0x1ee6*/ 702, - /*0x24c5*/ 900, - /*0x00d9*/ 50, - /*0x1ede*/ 698, + /*0xa746*/ 1080, + /*0x01e2*/ 173, + /*0x1fb9*/ 821, + /*0x1ca1*/ 556, + /*0x0139*/ 84, -1, -1, - /*0x104c5*/ 1321, + /*0xabb9*/ 1218, + /*0x1f8f*/ 782, + /*0x040f*/ 312, + /*0x03e6*/ 282, + /*0x1040f*/ 1278, + /*0x04f8*/ 417, + /*0xab8f*/ 1176, + /*0x1ff2*/ 854, + /*0x0472*/ 354, + /*0x0172*/ 113, + /*0xa762*/ 1094, + /*0x2c0f*/ 926, + /*0x104d3*/ 1338, + /*0x04c3*/ 391, -1, - /*0x04c5*/ 392, - /*0x0545*/ 465, + /*0x104c3*/ 1322, + -1, + /*0x2c72*/ 969, + /*0x03e0*/ 279, + /*0x1ef2*/ 708, + /*0x1e72*/ 642, /*0x1fad*/ 812, /*0x042d*/ 342, + -1, -1, -1, + /*0xabad*/ 1206, + /*0xa750*/ 1085, + /*0x2cf2*/ 1025, -1, -1, - /*0xabad*/ 1203, - /*0x1f59*/ 755, - -1, - /*0x1f6c*/ 763, - -1, -1, - /*0x04ec*/ 411, /*0x2c2d*/ 956, - /*0x015c*/ 102, + /*0x10c8f*/ 1354, + -1, -1, + /*0xa66c*/ 1048, + /*0x1fb3*/ 816, + /*0x04c7*/ 393, -1, - /*0xfb17*/ 1233, + /*0x104c7*/ 1326, -1, - /*0xa740*/ 1077, - /*0x03dc*/ 277, - /*0x1ff2*/ 854, - /*0x0472*/ 354, + /*0xabb3*/ 1212, -1, - /*0x0172*/ 113, + /*0x04c0*/ 389, + -1, + /*0x104c0*/ 1319, -1, -1, - /*0x10a9*/ 493, - /*0x01f2*/ 182, - /*0x10425*/ 1297, + /*0xa74e*/ 1084, + /*0xa7ad*/ 1126, + /*0x038f*/ 240, + /*0x04c5*/ 392, + /*0x10cad*/ 1384, + /*0x104c5*/ 1324, + -1, /*0x1fa5*/ 804, /*0x0425*/ 334, - /*0x2c72*/ 969, -1, - /*0xaba5*/ 1195, + /*0x10425*/ 1300, -1, - /*0x2cdc*/ 1019, - -1, - /*0x03a5*/ 261, - /*0x10c3*/ 519, - /*0xa7ad*/ 1126, - /*0x2c25*/ 948, + /*0xaba5*/ 1198, -1, -1, -1, - /*0x2cf2*/ 1025, - /*0x10a1*/ 485, - /*0x1e6a*/ 638, - /*0x00c9*/ 35, - /*0x1cad*/ 568, - /*0x10cad*/ 1381, - /*0x1edc*/ 697, - /*0x004d*/ 11, - -1, -1, - /*0x01cd*/ 163, - -1, - /*0x24c9*/ 904, + /*0xa7b3*/ 1131, + /*0x2c25*/ 948, /*0xa66a*/ 1047, - /*0x10b9*/ 509, - /*0x1ef2*/ 708, - /*0x1f49*/ 746, - /*0x104c9*/ 1325, - /*0xa762*/ 1094, - /*0x04c9*/ 394, - /*0x0549*/ 469, - /*0x013f*/ 87, - /*0xabbf*/ 1221, -1, - /*0xa754*/ 1087, - /*0x10423*/ 1295, - /*0x1fa3*/ 802, - /*0x0423*/ 332, - -1, -1, - /*0xaba3*/ 1193, - /*0x1ca5*/ 560, - /*0x10ca5*/ 1373, - /*0x1f6a*/ 761, - /*0x03a3*/ 259, + /*0x04cd*/ 396, -1, - /*0x04ea*/ 410, - /*0x2c23*/ 946, + /*0x104cd*/ 1332, + /*0x1f29*/ 730, -1, - /*0x0241*/ 220, - /*0x0141*/ 88, + /*0xa668*/ 1046, /*0x0041*/ 0, - /*0x00c3*/ 29, - /*0x1f29*/ 730, + /*0x0141*/ 88, + -1, + /*0x1f4d*/ 750, + /*0x013d*/ 86, + /*0x00c1*/ 27, + /*0x1e917*/ 1477, + /*0xabbd*/ 1222, + /*0x1fa3*/ 802, + /*0x0423*/ 332, + /*0xa75a*/ 1090, + /*0x10423*/ 1298, + /*0x10ca5*/ 1376, + /*0xaba3*/ 1196, + /*0x04ee*/ 412, + /*0x0372*/ 231, -1, -1, - /*0xa758*/ 1089, + /*0x2c23*/ 946, -1, -1, - /*0x1e68*/ 637, + /*0x04fe*/ 420, -1, - /*0x24c3*/ 898, - -1, -1, -1, -1, - /*0x104c3*/ 1319, + /*0x1f6e*/ 765, -1, - /*0x04c3*/ 391, - /*0x0543*/ 463, - /*0xa668*/ 1046, - /*0x0372*/ 231, - -1, -1, - /*0x1cbf*/ 584, + /*0x1e921*/ 1487, + /*0x216e*/ 882, -1, -1, -1, - /*0x023d*/ 218, - /*0x013d*/ 86, - /*0xabbd*/ 1219, - /*0x24b9*/ 888, - /*0x1ca3*/ 558, - /*0x10ca3*/ 1371, + /*0x03a5*/ 261, -1, - /*0x1f39*/ 738, - /*0x104b9*/ 1309, + /*0x1f87*/ 774, + /*0x0407*/ 304, + /*0xab79*/ 1154, + /*0x10407*/ 1270, + /*0x0587*/ 483, + /*0xab87*/ 1168, + /*0x16e59*/ 1447, + /*0x10ca3*/ 1374, -1, -1, - /*0x0539*/ 453, - /*0x1f68*/ 759, - /*0x00cb*/ 37, + /*0x2c07*/ 918, + /*0x04ec*/ 411, + /*0xab71*/ 1146, + /*0xa754*/ 1087, -1, - /*0x04e8*/ 409, - /*0x1041d*/ 1289, + /*0x10b9*/ 509, /*0x1f9d*/ 796, /*0x041d*/ 326, - -1, -1, - /*0xab9d*/ 1187, - /*0x24cb*/ 906, + /*0xa664*/ 1044, + /*0x1041d*/ 1292, + /*0x1f6c*/ 763, + /*0xab9d*/ 1190, -1, - /*0x019d*/ 139, - /*0x039d*/ 254, - /*0x1f4b*/ 748, - /*0x104cb*/ 1327, + /*0x216c*/ 880, + -1, + /*0x03a3*/ 259, /*0x2c1d*/ 940, - /*0x04cb*/ 395, - /*0x054b*/ 471, - /*0x10407*/ 1267, - /*0x1f87*/ 774, - /*0x0407*/ 304, - /*0x0587*/ 483, + /*0x01f8*/ 186, -1, - /*0xab87*/ 1165, - /*0x1e64*/ 635, + /*0xa758*/ 1089, + /*0x0539*/ 453, + /*0x10c87*/ 1346, + /*0x01d3*/ 166, + -1, + /*0x1fcb*/ 834, + /*0x004b*/ 9, + /*0xa65e*/ 1041, + -1, + /*0xa65c*/ 1040, + /*0xab73*/ 1148, + /*0x00cb*/ 37, + /*0x10ad*/ 497, + /*0x04ea*/ 410, + /*0xabb1*/ 1210, -1, - /*0x0187*/ 125, - /*0x1041b*/ 1287, /*0x1f9b*/ 794, /*0x041b*/ 324, - /*0x2c07*/ 918, - /*0x1cbd*/ 582, - /*0xab9b*/ 1185, - -1, -1, - /*0xa664*/ 1044, - /*0x039b*/ 252, + /*0x10c9d*/ 1368, + /*0x1041b*/ 1290, + /*0x04e8*/ 409, + /*0xab9b*/ 1188, + /*0x1f6a*/ 761, -1, - /*0x1e60*/ 633, + /*0xa666*/ 1045, + /*0x216a*/ 878, /*0x2c1b*/ 938, - /*0x1fbb*/ 823, + /*0x10b3*/ 503, + /*0x1e9b*/ 665, + /*0x1f68*/ 759, + /*0x01c7*/ 159, -1, - /*0x023b*/ 217, - /*0x013b*/ 85, - /*0xabbb*/ 1217, - -1, -1, - /*0x1e74*/ 643, - /*0xab73*/ 1145, + /*0x2168*/ 876, + -1, -1, -1, + /*0x039d*/ 254, + /*0xa7b1*/ 1129, + /*0x24b9*/ 888, /*0xa660*/ 1042, - /*0x1c9d*/ 552, - /*0x10c9d*/ 1365, - /*0x1e7c*/ 647, - -1, - /*0x1e91d*/ 1480, + /*0x10cb1*/ 1388, -1, - /*0x1ff6*/ 857, - /*0x0476*/ 356, - /*0x04e4*/ 407, - /*0x0176*/ 115, - -1, -1, -1, - /*0x01f6*/ 184, - /*0x2162*/ 870, - /*0x1c87*/ 537, - /*0x10c87*/ 1343, - /*0x1e9b*/ 665, - /*0x118a9*/ 1396, - /*0x1e907*/ 1458, - /*0xa76c*/ 1099, + /*0x0533*/ 447, + /*0x1fb7*/ 819, + /*0x01c5*/ 158, -1, - /*0x04e0*/ 405, - /*0x1e6e*/ 640, - /*0x1c9b*/ 550, - /*0x10c9b*/ 1363, - -1, -1, - /*0x1e91b*/ 1478, + /*0x10a5*/ 489, + /*0x10c9b*/ 1366, + /*0xabb7*/ 1216, + /*0x1cb9*/ 580, -1, -1, - /*0x04f4*/ 415, - /*0x1e66*/ 636, + /*0xa740*/ 1077, + /*0x1f93*/ 786, + /*0x0413*/ 316, + /*0x01a9*/ 146, + /*0x10413*/ 1282, + -1, + /*0xab93*/ 1180, + /*0xab77*/ 1152, + -1, + /*0x01cd*/ 163, + -1, + /*0x2c13*/ 930, + /*0x10c1*/ 517, + /*0x039b*/ 252, + -1, + /*0x10bd*/ 513, + /*0x0197*/ 136, -1, -1, - /*0x1e5e*/ 632, - /*0x04fc*/ 419, - /*0x118a1*/ 1388, + /*0x04e4*/ 407, -1, - /*0xabb1*/ 1207, + /*0x10a3*/ 487, -1, - /*0xff29*/ 1242, - /*0x01b1*/ 150, - /*0xa666*/ 1045, + /*0x1cad*/ 568, + /*0xff29*/ 1245, + -1, -1, + /*0x0541*/ 461, + -1, + /*0x01ee*/ 179, + /*0x053d*/ 457, + /*0x2164*/ 872, + /*0x10c93*/ 1358, + -1, -1, -1, + /*0x01fe*/ 189, + /*0x04de*/ 404, + /*0x1cb3*/ 574, + /*0x04dc*/ 403, -1, - /*0x1ef6*/ 710, - /*0xa65e*/ 1041, - /*0x10419*/ 1285, /*0x1f99*/ 792, /*0x0419*/ 322, - /*0x118b9*/ 1412, - /*0x10ad*/ 497, - /*0xab99*/ 1183, - /*0x00de*/ 55, - /*0x1f6e*/ 765, -1, - /*0x0399*/ 250, - /*0x04ee*/ 412, + /*0x10419*/ 1288, + /*0xa76e*/ 1100, + /*0xab99*/ 1186, + /*0xab75*/ 1150, + /*0x118a9*/ 1399, -1, - /*0x2c19*/ 936, - /*0xff21*/ 1234, - /*0x1fb7*/ 819, - /*0x10413*/ 1279, - /*0x1f93*/ 786, - /*0x0413*/ 316, - /*0xabb7*/ 1213, - /*0x04e6*/ 408, - /*0xab93*/ 1177, - /*0x01b7*/ 154, - /*0x04de*/ 404, - /*0x0193*/ 133, /*0x0393*/ 244, - /*0xa7b1*/ 1129, - /*0xff39*/ 1258, - /*0x2c13*/ 930, - /*0x00d1*/ 43, - /*0x1ffa*/ 861, - /*0x047a*/ 358, - /*0x10a5*/ 489, - -1, -1, - /*0x1cb1*/ 572, - /*0x10cb1*/ 1385, - /*0x01fa*/ 187, - /*0x03fa*/ 293, - -1, -1, + /*0x2c19*/ 936, + /*0xa77e*/ 1104, /*0x1e99*/ 663, - /*0xa76a*/ 1098, - /*0x104d1*/ 1333, - /*0x1e5c*/ 631, - /*0x0376*/ 232, - /*0x0551*/ 477, - -1, - /*0x1c99*/ 548, - /*0x10c99*/ 1361, - /*0x10cd*/ 523, - -1, - /*0x1e919*/ 1476, - /*0x1e72*/ 642, + /*0x04e6*/ 408, -1, - /*0xa65c*/ 1040, + /*0xff21*/ 1237, + /*0x1ca5*/ 560, + /*0x01ec*/ 178, + -1, -1, -1, -1, + /*0x1fbb*/ 823, + /*0x24c1*/ 896, + /*0x013b*/ 85, + /*0x2166*/ 874, + /*0x24bd*/ 892, + /*0xabbb*/ 1220, + /*0x04e0*/ 405, + -1, -1, + /*0x10c99*/ 1364, -1, - /*0x13fa*/ 526, + /*0xa76c*/ 1099, -1, -1, -1, - /*0x1cb7*/ 578, - /*0x00dc*/ 53, - /*0x1c93*/ 542, - /*0x10c93*/ 1355, - /*0x10bf*/ 515, - /*0x1f2d*/ 734, - /*0x1e913*/ 1470, - /*0xabb5*/ 1211, - /*0x1efa*/ 712, + /*0x1cbd*/ 582, + /*0x013f*/ 87, + /*0x118a1*/ 1391, + /*0x2160*/ 868, + /*0xabbf*/ 1224, + /*0x10b1*/ 501, + /*0x1ca3*/ 558, + /*0x0241*/ 220, + -1, -1, + /*0x023d*/ 218, + /*0x01ea*/ 177, + /*0x0399*/ 250, + /*0x0470*/ 353, + /*0x0170*/ 112, + /*0xab7f*/ 1160, + /*0x054b*/ 471, -1, - /*0x01b5*/ 153, + /*0x01e8*/ 176, + /*0x104b9*/ 1312, + /*0x0531*/ 445, -1, - /*0x10a3*/ 487, - /*0xab75*/ 1147, - -1, -1, -1, - /*0x04dc*/ 403, - /*0x1fb3*/ 816, - -1, -1, -1, - /*0xabb3*/ 1209, - /*0x10c1*/ 517, + /*0x2c70*/ 968, -1, - /*0x01b3*/ 152, + /*0x1ef0*/ 707, + /*0x1e70*/ 641, + /*0x1f39*/ 738, + /*0xa76a*/ 1098, + /*0x1e90f*/ 1469, /*0x04f2*/ 414, + /*0x1c87*/ 537, -1, - /*0xa768*/ 1097, + /*0x1f0f*/ 722, -1, - /*0x1041f*/ 1291, + /*0xa768*/ 1097, /*0x1f9f*/ 798, /*0x041f*/ 328, - -1, -1, - /*0xab9f*/ 1189, - -1, - /*0x00cd*/ 39, - /*0x019f*/ 140, - /*0x039f*/ 256, - /*0x216c*/ 880, -1, + /*0x1041f*/ 1294, + /*0x10b7*/ 507, + /*0xab9f*/ 1192, + -1, -1, -1, -1, /*0x2c1f*/ 942, - -1, -1, -1, - /*0x24cd*/ 908, - -1, -1, - /*0x1cb5*/ 576, - /*0x1f4d*/ 750, - /*0x104cd*/ 1329, - /*0x10bd*/ 513, - /*0x04cd*/ 396, - /*0x054d*/ 473, - /*0xa7b3*/ 1131, - /*0x1ff8*/ 859, - /*0x0478*/ 357, - /*0xab7f*/ 1157, - /*0x0178*/ 116, - /*0xab71*/ 1143, - /*0x24bf*/ 894, + /*0x1c9d*/ 552, + /*0xfb17*/ 1236, + -1, -1, -1, -1, + /*0x1f2d*/ 734, + /*0x24cb*/ 906, + /*0x0537*/ 451, + -1, -1, -1, -1, -1, + /*0x104b3*/ 1306, + /*0x03f0*/ 287, + /*0x1f8b*/ 778, + /*0x040b*/ 308, -1, - /*0x01f8*/ 186, - /*0x1cb3*/ 574, - /*0x1f3f*/ 744, - /*0x104bf*/ 1315, + /*0x1040b*/ 1274, + /*0x10c9f*/ 1370, + /*0xab8b*/ 1172, + /*0x1cb1*/ 572, + /*0x01e4*/ 174, -1, -1, - /*0x053f*/ 459, + /*0x2c0b*/ 922, + -1, -1, + /*0x1c9b*/ 550, + /*0xabb5*/ 1214, + /*0x00b5*/ 25, + /*0x1f95*/ 788, + /*0x0415*/ 318, -1, - /*0x00c1*/ 27, - -1, -1, -1, -1, -1, - /*0x1c9f*/ 554, - /*0x10c9f*/ 1367, - /*0xfb13*/ 1229, - /*0x24c1*/ 896, - /*0x1e91f*/ 1482, + /*0x10415*/ 1284, -1, - /*0x13f8*/ 524, + /*0xab95*/ 1182, + /*0x039f*/ 256, /*0xa764*/ 1095, - /*0x104c1*/ 1317, -1, + /*0x01de*/ 171, + /*0x2c15*/ 932, + -1, + /*0xa78b*/ 1109, + /*0x24b7*/ 886, + -1, + /*0x10c8b*/ 1350, + /*0x0370*/ 230, /*0x04c1*/ 390, - /*0x0541*/ 461, - /*0xab79*/ 1151, - -1, -1, - /*0x10415*/ 1281, - /*0x1f95*/ 788, - /*0x0415*/ 318, - /*0x1ef8*/ 711, -1, - /*0xab95*/ 1179, - /*0xa760*/ 1093, + /*0x104c1*/ 1320, -1, -1, - /*0x0395*/ 246, - -1, -1, - /*0x2c15*/ 932, - -1, -1, - /*0x10bb*/ 511, - /*0x216a*/ 878, - /*0x24bd*/ 892, + /*0x104bd*/ 1316, -1, - /*0x118ad*/ 1400, + /*0x1cb7*/ 578, + /*0xa75e*/ 1092, + /*0x01e6*/ 175, + /*0xa75c*/ 1091, -1, /*0x1f3d*/ 742, - /*0x104bd*/ 1313, -1, - /*0x047e*/ 360, - /*0x053d*/ 457, - /*0x16e52*/ 1437, - -1, -1, -1, - /*0x01fe*/ 189, - /*0x03fe*/ 295, - /*0x16e4c*/ 1431, - /*0xab7b*/ 1153, - /*0x2c7e*/ 971, - -1, -1, -1, -1, -1, - /*0x1f1d*/ 728, - /*0xa76e*/ 1100, - /*0xff2d*/ 1246, - -1, -1, -1, - /*0x118a5*/ 1392, - /*0x1c95*/ 544, - /*0x10c95*/ 1357, + /*0x10c95*/ 1360, + -1, + /*0x10bb*/ 511, + /*0x1c93*/ 542, + /*0x1f81*/ 768, + /*0x0401*/ 298, + -1, + /*0x10401*/ 1264, -1, + /*0xab81*/ 1162, + /*0x01e0*/ 172, /*0xa766*/ 1096, - /*0x1e915*/ 1472, + -1, -1, + /*0x2c01*/ 912, + /*0x004f*/ 13, + /*0x10bf*/ 515, + /*0x053b*/ 455, + /*0x0395*/ 246, -1, - /*0xa75e*/ 1092, - -1, -1, -1, -1, -1, -1, - /*0x10b1*/ 501, - /*0x1e76*/ 644, - /*0x1efe*/ 714, - /*0x2168*/ 876, - /*0x1f1b*/ 726, + /*0x00cf*/ 41, + -1, -1, -1, + /*0x1e907*/ 1461, -1, - /*0x10411*/ 1277, + /*0xa760*/ 1093, /*0x1f91*/ 784, /*0x0411*/ 314, - /*0xff25*/ 1238, - -1, - /*0xab91*/ 1175, - /*0x24bb*/ 890, - -1, - /*0x0191*/ 132, - /*0x0391*/ 242, - /*0x1f3b*/ 740, - /*0x104bb*/ 1311, - /*0x2c11*/ 928, - /*0x118bf*/ 1418, - /*0x053b*/ 455, - -1, -1, - /*0xab7d*/ 1155, - -1, -1, - /*0x10b7*/ 507, - /*0x118a3*/ 1390, - /*0x1040f*/ 1275, - /*0x1f8f*/ 782, - /*0x040f*/ 312, - -1, -1, - /*0xab8f*/ 1173, -1, - /*0x04f6*/ 416, - /*0x018f*/ 130, - /*0x038f*/ 240, + /*0x10411*/ 1280, + /*0x053f*/ 459, + /*0xab91*/ 1178, -1, -1, - /*0x2c0f*/ 926, + /*0x10c81*/ 1340, -1, - /*0x16e4a*/ 1429, - -1, - /*0x1040b*/ 1271, - /*0x1f8b*/ 778, - /*0x040b*/ 308, - -1, - /*0xa75c*/ 1091, - /*0xab8b*/ 1169, - /*0xff23*/ 1236, + /*0x2c11*/ 928, + /*0x16e55*/ 1443, -1, - /*0x018b*/ 128, - /*0x1c91*/ 540, - /*0x10c91*/ 1353, + /*0x1e91d*/ 1483, -1, - /*0x2c0b*/ 922, - /*0x1e911*/ 1468, + /*0x018f*/ 130, + /*0x1c99*/ 548, + /*0x1f1d*/ 728, + -1, -1, -1, + /*0x01f2*/ 182, + -1, -1, -1, -1, + /*0x04cb*/ 395, + /*0x24bb*/ 890, + /*0x104cb*/ 1330, -1, - /*0x2164*/ 872, - /*0xab77*/ 1149, + /*0xff39*/ 1261, + /*0x10c91*/ 1356, + /*0x104b1*/ 1304, + -1, -1, + /*0x1f4b*/ 748, + /*0x03cf*/ 270, -1, - /*0x104b1*/ 1301, + /*0xab7b*/ 1156, + -1, -1, + /*0x24bf*/ 894, + /*0x1e91b*/ 1481, + -1, -1, -1, + /*0x1f1b*/ 726, -1, - /*0xfb15*/ 1231, - /*0x0531*/ 445, + /*0x023b*/ 217, + /*0x0391*/ 242, + /*0x01b3*/ 152, + /*0xab7d*/ 1158, + /*0x1cbf*/ 584, -1, - /*0x118bd*/ 1416, - /*0x16e44*/ 1423, - /*0x16e4f*/ 1434, + /*0x118b9*/ 1415, -1, - /*0x1e7a*/ 646, + /*0xff2d*/ 1249, + /*0x1ff4*/ 856, + /*0x0474*/ 355, + /*0x0174*/ 114, -1, - /*0x2160*/ 868, - /*0x1f19*/ 724, /*0x10b5*/ 505, - /*0x10c8f*/ 1351, + -1, + /*0x16e4a*/ 1432, -1, -1, - /*0x1e90f*/ 1466, + /*0x104b7*/ 1310, -1, -1, - /*0xa78b*/ 1109, - /*0x24b7*/ 886, - /*0x10405*/ 1265, + /*0x1ef4*/ 709, + /*0x1e74*/ 643, + /*0xff33*/ 1255, /*0x1f85*/ 772, /*0x0405*/ 302, -1, - /*0x104b7*/ 1307, - /*0xab85*/ 1163, - /*0x10b3*/ 503, - /*0x0537*/ 451, - /*0x10c8b*/ 1347, + /*0x10405*/ 1268, + /*0x0535*/ 449, + /*0xab85*/ 1166, + -1, + /*0x1e913*/ 1473, + /*0x118ad*/ 1403, -1, - /*0x16e42*/ 1421, - /*0x1e90b*/ 1462, /*0x2c05*/ 916, -1, -1, -1, -1, -1, - /*0x10401*/ 1261, - /*0x1f81*/ 768, - /*0x0401*/ 298, - /*0x04fa*/ 418, - /*0x16e48*/ 1427, - /*0xab81*/ 1159, - /*0x216e*/ 882, + /*0x1c9f*/ 554, -1, - /*0x0181*/ 121, - -1, -1, -1, - /*0x2c01*/ 912, - -1, -1, - /*0x2166*/ 874, + /*0xff25*/ 1241, -1, -1, -1, -1, - /*0x118bb*/ 1414, - /*0x00b5*/ 25, + /*0x118b3*/ 1409, -1, -1, -1, -1, -1, -1, -1, - /*0x1c85*/ 535, - /*0x10c85*/ 1341, + /*0x10c85*/ 1344, -1, -1, - /*0x1e905*/ 1456, + /*0x03f4*/ 289, + -1, -1, -1, -1, -1, -1, -1, - /*0x104b5*/ 1305, + /*0x118a5*/ 1395, -1, -1, - /*0x0535*/ 449, + /*0xff23*/ 1239, + -1, + /*0x1e919*/ 1479, + /*0x0187*/ 125, + -1, -1, + /*0x1f19*/ 724, + /*0x1cb5*/ 576, + -1, -1, -1, + /*0x054f*/ 475, + -1, -1, + /*0x1c95*/ 544, + -1, -1, -1, + /*0x118bd*/ 1419, + /*0x019d*/ 139, + -1, + /*0x104bb*/ 1314, + -1, -1, + /*0x118a3*/ 1393, + -1, -1, -1, + /*0x1f3b*/ 740, + -1, + /*0x16e49*/ 1431, -1, -1, -1, -1, - /*0x16e50*/ 1435, + /*0x104bf*/ 1318, -1, - /*0x16e56*/ 1441, + /*0x01cb*/ 162, + -1, -1, -1, + /*0x01b1*/ 150, + /*0x1f3f*/ 744, + -1, -1, -1, + /*0x04f0*/ 413, -1, + /*0x24cf*/ 910, /*0x1c81*/ 531, - /*0x10c81*/ 1337, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xff31*/ 1253, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x1c91*/ 540, -1, - /*0x104b3*/ 1303, - /*0x1e901*/ 1452, + /*0x1e91f*/ 1485, + /*0x01b7*/ 154, + -1, -1, -1, -1, -1, -1, -1, - /*0x0533*/ 447, - /*0x16e5b*/ 1446, + /*0x16e44*/ 1426, + /*0x16e51*/ 1439, + /*0x0193*/ 133, + /*0x118b1*/ 1407, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0xff37*/ 1259, + /*0x16e4c*/ 1434, + -1, -1, -1, + /*0x1e90b*/ 1465, + -1, -1, -1, + /*0x1f0b*/ 718, -1, - /*0x1e78*/ 645, + /*0x104b5*/ 1308, -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x1e915*/ 1475, -1, -1, - /*0x118b1*/ 1404, + /*0x118b7*/ 1413, + -1, + /*0x16e48*/ 1430, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x16e46*/ 1425, - /*0xab70*/ 1142, - -1, -1, -1, - /*0xff31*/ 1250, - /*0x16e4e*/ 1433, - /*0x04f8*/ 417, - /*0x118b7*/ 1410, -1, -1, -1, - /*0x16e5a*/ 1445, + /*0x1c85*/ 535, + -1, + /*0x16e42*/ 1424, + -1, -1, -1, -1, -1, + /*0x1e901*/ 1455, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xfb05*/ 1227, + /*0x104cf*/ 1334, -1, -1, -1, -1, -1, -1, - -1, - /*0xff37*/ 1256, - /*0x1e7e*/ 648, -1, -1, -1, -1, -1, -1, -1, -1, - /*0xfb01*/ 1223, + /*0x01f0*/ 180, + /*0x1e911*/ 1471, + -1, + /*0x16e56*/ 1444, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0x16e52*/ 1440, + /*0x118bb*/ 1417, + -1, + /*0xfb13*/ 1232, + -1, -1, + /*0x019f*/ 140, -1, -1, -1, - /*0x16e40*/ 1419, - -1, -1, -1, -1, -1, - /*0x118b5*/ 1408, + /*0x16e46*/ 1428, + -1, -1, -1, -1, + /*0x118bf*/ 1421, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x018b*/ 128, -1, -1, - /*0x04fe*/ 420, + /*0x04f4*/ 415, -1, -1, -1, -1, -1, - /*0x118b3*/ 1406, + /*0x01b5*/ 153, + -1, + /*0x16e50*/ 1438, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x1e905*/ 1459, + -1, -1, -1, -1, -1, + /*0xab7c*/ 1157, + /*0xff35*/ 1257, -1, - /*0xff35*/ 1254, + /*0x16e4e*/ 1436, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xff33*/ 1252, - -1, -1, -1, -1, -1, - /*0x16e54*/ 1439, -1, -1, -1, -1, -1, -1, + /*0x0181*/ 121, + -1, -1, + /*0x118b5*/ 1411, -1, -1, -1, -1, -1, -1, + /*0x01cf*/ 164, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x16e58*/ 1443, + /*0x16e5a*/ 1448, -1, -1, -1, -1, -1, - /*0x1f0f*/ 722, - -1, -1, -1, -1, -1, -1, + /*0x0191*/ 132, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x1f0b*/ 718, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x16e54*/ 1442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x16e58*/ 1446, + -1, -1, -1, -1, -1, + /*0xfb15*/ 1234, -1, -1, -1, -1, -1, - /*0x16e55*/ 1440, + /*0x01f4*/ 183, + -1, -1, -1, -1, -1, -1, + /*0x16e53*/ 1441, + -1, -1, + /*0x16e43*/ 1425, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /*0xfb01*/ 1226, + -1, -1, -1, -1, + /*0x16e47*/ 1429, + -1, -1, -1, -1, -1, + /*0x16e40*/ 1422, -1, -1, -1, -1, -1, -1, + -1, + /*0x16e45*/ 1427, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0x16e45*/ 1424, + /*0x16e4d*/ 1435, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x16e59*/ 1444, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xa77e*/ 1104, -1, -1, -1, -1, -1, -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*/ 1428, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xfb05*/ 1230, -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*/ 1151, -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x16e43*/ 1422, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1430, -1, -1, -1, -1, -1, -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*/ 1452, + -1, + /*0x16e5c*/ 1450, -1, -1, -1, -1, -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*/ 1155, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3516,34 +3603,28 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0x16e5e*/ 1449, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x16e51*/ 1436, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1447, + /*0x16e41*/ 1423, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1432, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1420, -1, -1, -1, -1, -1, -1, + /*0x16e4b*/ 1433, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3557,6 +3638,9 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xab78*/ 1153, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3570,6 +3654,8 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xab7e*/ 1159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3582,6 +3668,8 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + /*0x16e4f*/ 1437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3599,13 +3687,11 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, - /*0xab74*/ 1146, - -1, -1, -1, -1, - /*0xab7c*/ 1154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xab72*/ 1147, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3619,7 +3705,6 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0xab72*/ 1144, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3646,21 +3731,19 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xab76*/ 1148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1145, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3675,8 +3758,6 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xab78*/ 1150, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3686,8 +3767,8 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xab7e*/ 1156 + -1, -1, -1, -1, -1, -1, + /*0xab74*/ 1149 }; if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) @@ -3706,7 +3787,7 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) } static const CaseUnfold_11_Type CaseUnfold_11_Table[] = { -#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1352])(CaseUnfold_11_Table+0)) +#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1355])(CaseUnfold_11_Table+0)) {0x0061, {1|U, {0x0041}}}, {0x0062, {1|U, {0x0042}}}, {0x0063, {1|U, {0x0043}}}, @@ -4807,6 +4888,9 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = { {0xa7bd, {1|U, {0xa7bc}}}, {0xa7bf, {1|U, {0xa7be}}}, {0xa7c3, {1|U, {0xa7c2}}}, + {0xa7c8, {1|U, {0xa7c7}}}, + {0xa7ca, {1|U, {0xa7c9}}}, + {0xa7f6, {1|U, {0xa7f5}}}, {0xab53, {1|U, {0xa7b3}}}, {0xff41, {1|U, {0xff21}}}, {0xff42, {1|U, {0xff22}}}, @@ -5059,14 +5143,14 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = { {0x1e941, {1|U, {0x1e91f}}}, {0x1e942, {1|U, {0x1e920}}}, {0x1e943, {1|U, {0x1e921}}}, -#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1352)) +#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1355)) {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 = 2507, duplicates = 0 */ +/* maximum key range = 2461, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -5081,26 +5165,26 @@ onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code) { static const unsigned short asso_values[] = { - 1, 2510, 2, 7, 4, 582, 9, 308, 197, 674, - 297, 20, 2, 3, 303, 351, 2510, 2510, 2510, 2510, - 2510, 2510, 2510, 2510, 2510, 2510, 2510, 2510, 2510, 112, - 2510, 2510, 2510, 2510, 2510, 2510, 2510, 120, 2510, 2510, - 2510, 2510, 2510, 1, 2510, 2510, 2510, 2510, 2510, 2510, - 2510, 2510, 2510, 278, 2510, 2510, 2510, 2510, 2510, 2510, - 2510, 2510, 12, 1, 7, 8, 218, 878, 222, 1178, - 480, 1102, 54, 1340, 151, 1615, 8, 15, 106, 1607, - 225, 854, 87, 490, 44, 1351, 5, 1281, 3, 1470, - 11, 1215, 377, 10, 441, 599, 152, 1642, 127, 1334, - 702, 841, 594, 827, 123, 916, 146, 1118, 117, 1363, - 254, 812, 249, 1096, 1630, 945, 437, 745, 1600, 718, - 1593, 704, 152, 1005, 383, 1064, 1493, 975, 236, 676, - 761, 579, 1017, 557, 1241, 628, 1195, 614, 1506, 464, - 1576, 535, 1432, 513, 1159, 423, 1026, 276, 1460, 291, - 1453, 392, 1263, 201, 1442, 85, 1412, 70, 1430, 100, - 1632, 129, 1410, 1, 1386, 25, 1373, 35, 656, 55, - 1188, 45, 1308, 160, 687, 227, 355, 175, 1201, 328, - 1030, 367, 1483, 414, 1479, 1166, 1418, 783, 994, 937, - 1083, 959, 1463, 967 + 1, 2464, 2, 7, 4, 582, 9, 308, 197, 674, + 456, 20, 2, 3, 303, 351, 2464, 2464, 2464, 2464, + 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 112, + 2464, 2464, 2464, 2464, 2464, 2464, 2464, 120, 2464, 2464, + 2464, 2464, 2464, 1, 2464, 2464, 2464, 2464, 2464, 2464, + 2464, 2464, 2464, 278, 2464, 2464, 2464, 2464, 2464, 2464, + 2464, 2464, 12, 1, 7, 8, 218, 878, 222, 1178, + 480, 1102, 54, 1282, 153, 1579, 8, 15, 151, 1607, + 225, 854, 87, 490, 106, 1416, 5, 1351, 3, 1502, + 11, 1215, 377, 10, 441, 599, 152, 1722, 127, 1334, + 717, 841, 594, 827, 123, 916, 146, 1118, 117, 1363, + 254, 812, 249, 1096, 1512, 945, 437, 745, 1682, 718, + 1676, 704, 152, 1005, 383, 1064, 1561, 975, 236, 676, + 761, 579, 1017, 557, 1241, 628, 1276, 614, 1195, 464, + 1659, 535, 1627, 513, 1159, 423, 1026, 276, 1506, 291, + 1460, 392, 1453, 201, 1483, 85, 1412, 70, 1430, 100, + 1552, 129, 1427, 1, 1386, 25, 1382, 35, 656, 55, + 1188, 45, 1201, 160, 687, 227, 355, 175, 1373, 328, + 1030, 367, 1405, 414, 1230, 1166, 1531, 783, 994, 937, + 1217, 959, 1023, 967 }; return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)]; } @@ -5112,11 +5196,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) { MIN_CODE_VALUE = 0x61, MAX_CODE_VALUE = 0x1e943, - TOTAL_KEYWORDS = 1353, + TOTAL_KEYWORDS = 1356, MIN_WORD_LENGTH = 3, MAX_WORD_LENGTH = 3, MIN_HASH_VALUE = 3, - MAX_HASH_VALUE = 2509 + MAX_HASH_VALUE = 2463 }; static const short wordlist[] = @@ -5127,7 +5211,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04e1*/ 400, /*0x0061*/ 0, -1, - /*0x104e1*/ 1176, + /*0x104e1*/ 1179, /*0x1e61*/ 661, /*0x1ee1*/ 720, /*0x0161*/ 102, @@ -5150,7 +5234,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04e3*/ 401, /*0x0063*/ 2, -1, - /*0x104e3*/ 1178, + /*0x104e3*/ 1181, /*0x1e63*/ 662, /*0x1ee3*/ 721, /*0x0163*/ 103, @@ -5160,7 +5244,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04e5*/ 402, /*0x0065*/ 4, /*0x24e3*/ 842, - /*0x104e5*/ 1180, + /*0x104e5*/ 1183, /*0x1e65*/ 663, /*0x1ee5*/ 722, /*0x0165*/ 104, @@ -5168,9 +5252,9 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x13e9*/ 597, /*0x0469*/ 344, /*0x04e9*/ 404, - /*0x0069*/ 1352, + /*0x0069*/ 1355, /*0x24e5*/ 844, - /*0x104e9*/ 1184, + /*0x104e9*/ 1187, /*0x1e69*/ 665, /*0x1ee9*/ 724, /*0x0169*/ 106, @@ -5180,7 +5264,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04e7*/ 403, /*0x0067*/ 6, /*0x24e9*/ 848, - /*0x104e7*/ 1182, + /*0x104e7*/ 1185, /*0x1e67*/ 664, /*0x1ee7*/ 723, /*0x0167*/ 105, @@ -5192,7 +5276,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04db*/ 397, -1, /*0x03e7*/ 283, - /*0x104db*/ 1170, + /*0x104db*/ 1173, /*0x1e5b*/ 658, /*0x1edb*/ 717, /*0x015b*/ 99, @@ -5204,7 +5288,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04d9*/ 396, /*0xa761*/ 1064, /*0x03db*/ 277, - /*0x104d9*/ 1168, + /*0x104d9*/ 1171, /*0x1e59*/ 657, /*0x1ed9*/ 716, /*0x0159*/ 98, @@ -5216,7 +5300,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04dd*/ 398, -1, /*0x03d9*/ 276, - /*0x104dd*/ 1172, + /*0x104dd*/ 1175, /*0x1e5d*/ 659, /*0x1edd*/ 718, /*0x015d*/ 100, @@ -5225,13 +5309,13 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0xa763*/ 1065, -1, /*0x24dd*/ 836, - /*0x10ce1*/ 1236, + /*0x10ce1*/ 1239, -1, /*0x13aa*/ 534, -1, /*0x03dd*/ 278, /*0x10e1*/ 495, - /*0x1042a*/ 1129, + /*0x1042a*/ 1132, /*0xa765*/ 1066, /*0x13a6*/ 530, -1, -1, -1, @@ -5242,12 +5326,12 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04df*/ 399, /*0xa769*/ 1068, -1, - /*0x104df*/ 1174, + /*0x104df*/ 1177, /*0x1e5f*/ 660, /*0x1edf*/ 719, /*0x015f*/ 101, /*0x2cdf*/ 951, - /*0x10ce3*/ 1238, + /*0x10ce3*/ 1241, -1, -1, /*0xa767*/ 1067, /*0x24df*/ 838, @@ -5256,27 +5340,27 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x13a8*/ 532, -1, /*0x03df*/ 279, - /*0x10ce5*/ 1240, - /*0x10428*/ 1127, + /*0x10ce5*/ 1243, + /*0x10428*/ 1130, -1, /*0x13b8*/ 548, /*0x0438*/ 300, /*0x10e5*/ 499, -1, - /*0x10438*/ 1143, + /*0x10438*/ 1146, /*0xa75b*/ 1061, -1, - /*0x10ce9*/ 1244, + /*0x10ce9*/ 1247, /*0x13eb*/ 599, /*0x046b*/ 345, /*0x04eb*/ 405, /*0x006b*/ 9, /*0x10e9*/ 503, - /*0x104eb*/ 1186, + /*0x104eb*/ 1189, /*0x1e6b*/ 666, /*0x1eeb*/ 725, /*0x016b*/ 107, - /*0x10ce7*/ 1242, + /*0x10ce7*/ 1245, -1, /*0x03b8*/ 253, /*0xa759*/ 1060, @@ -5287,11 +5371,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04ef*/ 407, /*0x006f*/ 13, /*0x03eb*/ 285, - /*0x104ef*/ 1190, + /*0x104ef*/ 1193, /*0x1e6f*/ 668, /*0x1eef*/ 727, /*0x016f*/ 109, - /*0x10cdb*/ 1230, + /*0x10cdb*/ 1233, -1, -1, /*0xa75d*/ 1062, -1, @@ -5301,7 +5385,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, -1, /*0x0261*/ 210, -1, - /*0x10cd9*/ 1228, + /*0x10cd9*/ 1231, -1, /*0x13d7*/ 579, /*0x0457*/ 331, @@ -5315,7 +5399,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2cd7*/ 947, /*0x020b*/ 170, -1, -1, - /*0x10cdd*/ 1232, + /*0x10cdd*/ 1235, /*0x24d7*/ 830, /*0xa75f*/ 1063, -1, @@ -5332,17 +5416,17 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04ed*/ 406, /*0x006d*/ 11, /*0x0265*/ 212, - /*0x104ed*/ 1188, + /*0x104ed*/ 1191, /*0x1e6d*/ 667, /*0x1eed*/ 726, /*0x016d*/ 108, /*0x13be*/ 554, /*0x043e*/ 306, -1, -1, - /*0x1043e*/ 1149, + /*0x1043e*/ 1152, /*0x0269*/ 215, /*0x1f63*/ 779, - /*0x10cdf*/ 1234, + /*0x10cdf*/ 1237, /*0x013e*/ 85, -1, /*0x03ed*/ 286, @@ -5352,14 +5436,14 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0xa663*/ 1014, -1, /*0x1f65*/ 781, - /*0x1042e*/ 1133, + /*0x1042e*/ 1136, /*0x13ac*/ 536, /*0x03be*/ 259, -1, -1, - /*0x1042c*/ 1131, + /*0x1042c*/ 1134, -1, /*0xa665*/ 1015, - /*0x1f12*/ 746, + -1, /*0xa76f*/ 1071, -1, -1, -1, /*0x025b*/ 207, @@ -5370,7 +5454,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x1f06*/ 742, /*0x1f67*/ 783, /*0x03ac*/ 242, - /*0x10ceb*/ 1246, + /*0x10ceb*/ 1249, -1, /*0x13d1*/ 573, /*0x0451*/ 325, @@ -5384,7 +5468,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2cd1*/ 944, -1, -1, /*0xa757*/ 1059, - /*0x10cef*/ 1250, + /*0x10cef*/ 1253, /*0x24d1*/ 824, /*0x13d3*/ 575, /*0x0453*/ 327, @@ -5397,7 +5481,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0153*/ 95, /*0x2cd3*/ 945, -1, - /*0xab53*/ 1100, + /*0xab53*/ 1103, /*0x0561*/ 440, /*0x1f10*/ 744, /*0x24d3*/ 826, @@ -5409,12 +5493,14 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x051b*/ 429, -1, /*0xa76d*/ 1070, - /*0x10cd7*/ 1226, + /*0x10cd7*/ 1229, -1, /*0x050b*/ 421, -1, -1, /*0x10d7*/ 485, - -1, -1, -1, -1, + -1, -1, + /*0x1f12*/ 746, + -1, /*0xa65d*/ 1011, -1, /*0x0563*/ 442, @@ -5423,14 +5509,14 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04f1*/ 408, /*0x0071*/ 15, /*0x01e3*/ 152, - /*0x104f1*/ 1192, + /*0x104f1*/ 1195, /*0x1e71*/ 669, /*0x1ef1*/ 728, /*0x0171*/ 110, /*0x0565*/ 444, -1, -1, /*0x1f26*/ 756, - /*0x10ced*/ 1248, + /*0x10ced*/ 1251, /*0x01e5*/ 153, -1, /*0x1f20*/ 750, @@ -5438,8 +5524,8 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x10ed*/ 507, /*0x0569*/ 448, -1, -1, - /*0x118db*/ 1281, - /*0x0192*/ 122, + /*0x118db*/ 1284, + -1, /*0x01e9*/ 155, -1, /*0xa65f*/ 1012, @@ -5448,19 +5534,19 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0567*/ 446, /*0x006e*/ 12, -1, - /*0x104ee*/ 1189, + /*0x104ee*/ 1192, -1, /*0x01e7*/ 154, /*0xa751*/ 1056, /*0x2cee*/ 955, - /*0x118d9*/ 1279, + /*0x118d9*/ 1282, -1, /*0x13f3*/ 607, /*0x0473*/ 349, /*0x04f3*/ 409, /*0x0073*/ 17, /*0x026f*/ 219, - /*0x104f3*/ 1194, + /*0x104f3*/ 1197, /*0x1e73*/ 670, /*0x1ef3*/ 729, /*0x0173*/ 111, @@ -5468,15 +5554,15 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2c61*/ 896, /*0xa753*/ 1057, -1, - /*0x118dd*/ 1283, + /*0x118dd*/ 1286, -1, -1, /*0x13ba*/ 550, /*0x043a*/ 302, /*0xa66b*/ 1018, /*0x03f3*/ 289, - /*0x1043a*/ 1145, + /*0x1043a*/ 1148, -1, -1, - /*0x10cd1*/ 1220, + /*0x10cd1*/ 1223, /*0x013a*/ 83, /*0x13d5*/ 577, /*0x0455*/ 329, @@ -5491,21 +5577,21 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x03ba*/ 255, -1, /*0x0586*/ 477, - /*0x10cd3*/ 1222, + /*0x10cd3*/ 1225, /*0x24d5*/ 828, /*0x01dd*/ 149, -1, - /*0x118df*/ 1285, + /*0x118df*/ 1288, /*0x10d3*/ 481, /*0x2c65*/ 897, -1, - /*0x018c*/ 121, + /*0x0192*/ 122, /*0x13f5*/ 609, /*0x0475*/ 350, /*0x04f5*/ 410, /*0x0075*/ 19, /*0x1f57*/ 775, - /*0x104f5*/ 1196, + /*0x104f5*/ 1199, /*0x1e75*/ 671, /*0x1ef5*/ 730, /*0x0175*/ 112, @@ -5513,22 +5599,22 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x044f*/ 323, /*0x04cf*/ 391, /*0xa657*/ 1008, - /*0x1044f*/ 1166, - /*0x1e92a*/ 1326, + /*0x1044f*/ 1169, + /*0x1e92a*/ 1329, /*0x1e4f*/ 652, /*0x1ecf*/ 711, /*0x014f*/ 93, /*0x2ccf*/ 943, -1, - /*0x1e926*/ 1322, + /*0x1e926*/ 1325, /*0x1f00*/ 736, /*0x01df*/ 150, /*0x13b2*/ 542, /*0x0432*/ 294, /*0x1f02*/ 738, -1, - /*0x10432*/ 1137, - /*0x10cf1*/ 1252, + /*0x10432*/ 1140, + /*0x10cf1*/ 1255, /*0x2d16*/ 979, -1, /*0x2d14*/ 977, @@ -5543,19 +5629,19 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0x2d0b*/ 968, /*0x03b2*/ 247, - /*0x1e928*/ 1324, - /*0x0188*/ 120, + /*0x1e928*/ 1327, + /*0x018c*/ 121, /*0x019e*/ 126, - -1, + /*0x0188*/ 120, /*0x2c59*/ 890, /*0x056b*/ 450, - /*0x1e938*/ 1340, + /*0x1e938*/ 1343, /*0x13c9*/ 565, /*0x0449*/ 317, -1, /*0x01eb*/ 156, - /*0x10449*/ 1160, - /*0x10cee*/ 1249, + /*0x10449*/ 1163, + /*0x10cee*/ 1252, /*0x1e49*/ 649, /*0x1ec9*/ 708, /*0x0251*/ 200, @@ -5567,11 +5653,10 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0xa755*/ 1058, -1, - /*0x118d7*/ 1277, + /*0x118d7*/ 1280, /*0x01ef*/ 158, /*0x03c9*/ 269, - /*0x2d12*/ 975, - -1, + -1, -1, /*0x10f3*/ 513, /*0x0253*/ 202, -1, -1, -1, -1, @@ -5586,7 +5671,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0xa79b*/ 1085, /*0xa651*/ 1005, -1, -1, -1, -1, - /*0x10cd5*/ 1224, + /*0x10cd5*/ 1227, -1, /*0x1f53*/ 773, -1, @@ -5597,7 +5682,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x044d*/ 321, -1, /*0xa653*/ 1006, - /*0x1044d*/ 1164, + /*0x1044d*/ 1167, -1, /*0x1e4d*/ 651, /*0x1ecd*/ 710, @@ -5616,60 +5701,58 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x01ed*/ 157, /*0x13cb*/ 567, /*0x044b*/ 319, - /*0x10ccf*/ 1218, + /*0x10ccf*/ 1221, -1, - /*0x1044b*/ 1162, + /*0x1044b*/ 1165, -1, /*0x1e4b*/ 650, /*0x1ecb*/ 709, /*0x014b*/ 91, /*0x2ccb*/ 941, /*0x1f71*/ 785, - /*0x2d0c*/ 969, - /*0x1e93e*/ 1346, + /*0x2d12*/ 975, + /*0x1e93e*/ 1349, -1, -1, -1, /*0xa749*/ 1052, -1, -1, /*0x03cb*/ 271, -1, - /*0x118d1*/ 1271, + /*0x118d1*/ 1274, /*0x13c3*/ 559, /*0x0443*/ 311, -1, - /*0x1e92e*/ 1330, - /*0x10443*/ 1154, + /*0x1e92e*/ 1333, + /*0x10443*/ 1157, -1, /*0x1e43*/ 646, /*0x1ec3*/ 705, - /*0x1e92c*/ 1328, + /*0x1e92c*/ 1331, /*0x2cc3*/ 937, /*0x2d20*/ 989, /*0x0580*/ 471, -1, -1, - /*0x118d3*/ 1273, + /*0x118d3*/ 1276, /*0x0582*/ 473, -1, -1, -1, /*0x03c3*/ 263, /*0x2c57*/ 888, - /*0x10cc9*/ 1212, + /*0x10cc9*/ 1215, /*0x13c1*/ 557, /*0x0441*/ 309, -1, /*0x00e1*/ 26, - /*0x10441*/ 1152, + /*0x10441*/ 1155, /*0x1f73*/ 787, /*0x1e41*/ 645, /*0x1ec1*/ 704, -1, /*0x2cc1*/ 936, -1, -1, - /*0x2d08*/ 965, + /*0x2d0c*/ 969, /*0x2d1e*/ 987, - -1, + /*0x2d08*/ 965, /*0x13a4*/ 528, - -1, - /*0xa78c*/ 1079, - -1, + -1, -1, -1, /*0x03c1*/ 262, -1, /*0xa74d*/ 1054, @@ -5688,32 +5771,33 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0447*/ 315, /*0x00e5*/ 30, /*0xa655*/ 1007, - /*0x10447*/ 1158, + /*0x10447*/ 1161, /*0x024f*/ 198, /*0x1e47*/ 648, /*0x1ec7*/ 707, /*0xa74b*/ 1053, /*0x2cc7*/ 939, - /*0x0371*/ 236, - -1, + -1, -1, /*0x00e9*/ 34, - /*0x10ccd*/ 1216, + /*0x10ccd*/ 1219, /*0x13c5*/ 561, /*0x0445*/ 313, /*0x0571*/ 456, /*0x1f75*/ 789, - /*0x10445*/ 1156, + /*0x10445*/ 1159, /*0x03c7*/ 267, /*0x1e45*/ 647, /*0x1ec5*/ 706, /*0x00e7*/ 32, /*0x2cc5*/ 938, - -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0xa78c*/ 1079, + -1, -1, /*0xa743*/ 1049, -1, -1, /*0x03c5*/ 265, /*0xa64f*/ 1004, - /*0x10ccb*/ 1214, + /*0x10ccb*/ 1217, -1, -1, /*0x2c51*/ 882, -1, @@ -5724,18 +5808,17 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2d00*/ 957, /*0x0066*/ 5, /*0x0249*/ 195, - /*0x104e6*/ 1181, + /*0x104e6*/ 1184, /*0x2d02*/ 959, - /*0x0373*/ 237, - -1, + -1, -1, /*0x2d0e*/ 971, /*0xa741*/ 1048, /*0x2c53*/ 884, -1, /*0x0573*/ 458, /*0x24e6*/ 845, - /*0x10cc3*/ 1206, - /*0x118d5*/ 1275, + /*0x10cc3*/ 1209, + /*0x118d5*/ 1278, -1, /*0x01f3*/ 159, -1, @@ -5743,7 +5826,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x043f*/ 307, /*0x04bf*/ 383, -1, - /*0x1043f*/ 1150, + /*0x1043f*/ 1153, /*0x028a*/ 230, /*0x1e3f*/ 644, /*0x1ebf*/ 703, @@ -5755,21 +5838,21 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0xa649*/ 1001, /*0x006c*/ 10, -1, - /*0x104ec*/ 1187, - /*0x10cc1*/ 1204, - /*0x1e93a*/ 1342, + /*0x104ec*/ 1190, + /*0x10cc1*/ 1207, + /*0x1e93a*/ 1345, /*0x03bf*/ 260, /*0x2cec*/ 954, /*0x1f04*/ 740, -1, -1, -1, /*0xa747*/ 1051, - /*0x13a2*/ 526, - /*0x118cf*/ 1269, + -1, + /*0x118cf*/ 1272, /*0x13b7*/ 547, /*0x0437*/ 299, /*0x04b7*/ 379, /*0x1f11*/ 745, - /*0x10437*/ 1142, + /*0x10437*/ 1145, /*0x024d*/ 197, /*0x1e37*/ 640, /*0x1eb7*/ 699, @@ -5778,35 +5861,35 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0xa745*/ 1050, /*0x0575*/ 460, - /*0x0292*/ 233, + /*0x13a2*/ 526, /*0x13b5*/ 545, /*0x0435*/ 297, /*0x04b5*/ 378, /*0x01f5*/ 160, - /*0x10435*/ 1140, + /*0x10435*/ 1143, /*0x03b7*/ 252, /*0x1e35*/ 639, /*0x1eb5*/ 698, /*0x0135*/ 81, /*0x2cb5*/ 930, - /*0x10cc7*/ 1210, + /*0x10cc7*/ 1213, -1, -1, /*0x024b*/ 196, -1, - /*0x16e61*/ 1287, + /*0x16e61*/ 1290, -1, -1, -1, /*0x03b5*/ 250, /*0xa64d*/ 1003, -1, -1, /*0x00eb*/ 36, - /*0x10cc5*/ 1208, + /*0x10cc5*/ 1211, /*0x2c73*/ 902, - /*0x118c9*/ 1263, + /*0x118c9*/ 1266, /*0x13b3*/ 543, /*0x0433*/ 295, /*0x04b3*/ 377, - /*0x1e932*/ 1334, - /*0x10433*/ 1138, + /*0x1e932*/ 1337, + /*0x10433*/ 1141, -1, /*0x1e33*/ 638, /*0x1eb3*/ 697, @@ -5814,7 +5897,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2cb3*/ 929, -1, /*0x00ef*/ 40, - /*0x16e63*/ 1289, + /*0x16e63*/ 1292, -1, /*0x2c3a*/ 859, /*0xa64b*/ 1002, @@ -5822,41 +5905,41 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0440*/ 308, /*0xa73f*/ 1047, /*0x03b3*/ 248, - /*0x10440*/ 1151, + /*0x10440*/ 1154, -1, - /*0x16e65*/ 1291, + /*0x16e65*/ 1294, /*0x2c55*/ 886, /*0x0140*/ 86, - /*0x10ce6*/ 1241, + /*0x10ce6*/ 1244, /*0x01c9*/ 139, -1, -1, /*0x1f43*/ 769, /*0x10e6*/ 500, -1, - /*0x16e69*/ 1295, + /*0x16e69*/ 1298, -1, - /*0x028c*/ 232, + /*0x0292*/ 233, /*0x03c0*/ 261, -1, /*0xa643*/ 998, - -1, + /*0x0371*/ 236, /*0x0479*/ 352, /*0x04f9*/ 412, /*0x0079*/ 23, - /*0x16e67*/ 1293, - /*0x104f9*/ 1200, + /*0x16e67*/ 1296, + /*0x104f9*/ 1203, /*0x1e79*/ 673, /*0x1ef9*/ 732, /*0xa737*/ 1043, /*0x0511*/ 424, - /*0x118cd*/ 1267, + /*0x118cd*/ 1270, /*0x1d79*/ 610, /*0x021d*/ 179, /*0x1f41*/ 767, -1, -1, /*0x2c4f*/ 880, -1, - /*0x10cec*/ 1247, + /*0x10cec*/ 1250, -1, -1, /*0xa641*/ 997, /*0xa735*/ 1042, @@ -5869,17 +5952,18 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x13ad*/ 537, /*0x2c32*/ 851, /*0x04ad*/ 374, - /*0x118cb*/ 1265, - /*0x1042d*/ 1132, + /*0x118cb*/ 1268, + /*0x1042d*/ 1135, /*0x2d1a*/ 983, /*0x1e2d*/ 635, /*0x1ead*/ 694, /*0x012d*/ 78, /*0x2cad*/ 926, - -1, -1, - /*0x0288*/ 228, - /*0x029e*/ 235, + /*0x0373*/ 237, -1, + /*0x028c*/ 232, + /*0x029e*/ 235, + /*0x0288*/ 228, /*0x13a5*/ 529, -1, /*0x04a5*/ 370, @@ -5890,7 +5974,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x1ea5*/ 690, /*0x0125*/ 74, /*0x2ca5*/ 922, - /*0x118c3*/ 1257, + /*0x118c3*/ 1260, -1, /*0xa647*/ 1000, /*0x2c49*/ 874, @@ -5904,26 +5988,26 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x1ea3*/ 689, /*0x0123*/ 73, /*0x2ca3*/ 921, - /*0xff59*/ 1125, + /*0xff59*/ 1128, /*0x0266*/ 213, /*0xa645*/ 999, -1, -1, /*0x048f*/ 359, -1, -1, - /*0x118c1*/ 1255, + /*0x118c1*/ 1258, /*0x1e0f*/ 620, /*0x1e8f*/ 684, /*0x010f*/ 63, /*0x2c8f*/ 911, /*0xa69b*/ 1033, -1, -1, -1, - /*0x1e943*/ 1351, + /*0x1e943*/ 1354, /*0xa68b*/ 1025, -1, -1, /*0x023f*/ 191, /*0x1f66*/ 782, -1, - /*0x10cc0*/ 1203, + /*0x10cc0*/ 1206, -1, -1, /*0x1fe1*/ 803, -1, @@ -5937,11 +6021,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2c81*/ 904, -1, /*0x2c4d*/ 878, - /*0x1e941*/ 1349, + /*0x1e941*/ 1352, /*0x0280*/ 224, - /*0x16e6b*/ 1297, + /*0x16e6b*/ 1300, /*0x2175*/ 811, - /*0x118c7*/ 1261, + /*0x118c7*/ 1264, /*0x0282*/ 225, -1, -1, -1, /*0xa72d*/ 1039, @@ -5949,10 +6033,10 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x051d*/ 430, /*0x10f9*/ 519, -1, -1, - /*0x1e924*/ 1320, + /*0x1e924*/ 1323, -1, - /*0x16e6f*/ 1301, - /*0x118c5*/ 1259, + /*0x16e6f*/ 1304, + /*0x118c5*/ 1262, /*0x00f1*/ 42, -1, /*0x2c4b*/ 876, @@ -5963,7 +6047,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x13a7*/ 531, -1, /*0x04a7*/ 371, - /*0x1f22*/ 752, + -1, /*0x2d04*/ 961, /*0x1f37*/ 765, /*0x1e27*/ 632, @@ -5976,7 +6060,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2d11*/ 974, -1, -1, /*0x2c43*/ 868, - -1, + /*0x1f22*/ 752, /*0x1f35*/ 763, /*0x00ee*/ 39, -1, @@ -5984,14 +6068,14 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x04fb*/ 413, -1, /*0x0233*/ 189, - /*0x104fb*/ 1202, + /*0x104fb*/ 1205, /*0x1e7b*/ 674, /*0x1efb*/ 733, /*0x13b1*/ 541, /*0x0431*/ 293, /*0x04b1*/ 376, /*0x00f3*/ 44, - /*0x10431*/ 1136, + /*0x10431*/ 1139, -1, /*0x1e31*/ 637, /*0x1eb1*/ 696, @@ -6001,7 +6085,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x03fb*/ 291, /*0x0240*/ 192, /*0x0566*/ 445, - /*0x16e6d*/ 1299, + /*0x16e6d*/ 1302, /*0x047d*/ 354, /*0x04fd*/ 414, /*0x1f33*/ 761, @@ -6009,7 +6093,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x03b1*/ 246, /*0x1e7d*/ 675, /*0x1efd*/ 734, - /*0xff57*/ 1123, + /*0xff57*/ 1126, /*0x047f*/ 355, /*0x04ff*/ 415, /*0x1d7d*/ 611, @@ -6020,14 +6104,14 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x043d*/ 305, /*0x04bd*/ 382, /*0x1f40*/ 766, - /*0x1043d*/ 1148, + /*0x1043d*/ 1151, /*0xa791*/ 1080, /*0x1e3d*/ 643, /*0x1ebd*/ 702, /*0x01bf*/ 137, /*0x2cbd*/ 934, -1, -1, - /*0x1e93f*/ 1347, + /*0x1e93f*/ 1350, -1, /*0x056c*/ 451, /*0x2c47*/ 872, @@ -6037,7 +6121,7 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0x007a*/ 24, -1, - /*0x104fa*/ 1201, + /*0x104fa*/ 1204, /*0x1f79*/ 793, -1, /*0x017a*/ 114, @@ -6047,40 +6131,40 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0439*/ 301, /*0x04b9*/ 380, /*0x022d*/ 186, - /*0x10439*/ 1144, + /*0x10439*/ 1147, -1, /*0x1e39*/ 641, /*0x1eb9*/ 700, - /*0x1e922*/ 1318, + -1, /*0x2cb9*/ 932, - /*0x1e937*/ 1339, + /*0x1e937*/ 1342, -1, /*0x13c2*/ 558, /*0x0442*/ 310, /*0x04c2*/ 384, -1, - /*0x10442*/ 1153, + /*0x10442*/ 1156, -1, /*0x0225*/ 182, /*0x03b9*/ 254, /*0x0142*/ 87, /*0x13d0*/ 572, /*0x0450*/ 324, - -1, - /*0x1e935*/ 1337, + /*0x1e922*/ 1321, + /*0x1e935*/ 1340, /*0x13f2*/ 606, - -1, + /*0x017e*/ 116, /*0x2c66*/ 898, /*0x0072*/ 16, /*0x2d24*/ 993, - /*0x104f2*/ 1193, + /*0x104f2*/ 1196, -1, /*0x0223*/ 181, -1, /*0x2d1d*/ 986, /*0x24d0*/ 823, - /*0x118c0*/ 1254, - /*0xff51*/ 1117, + /*0x118c0*/ 1257, + /*0xff51*/ 1120, -1, /*0x1f25*/ 755, -1, -1, @@ -6093,11 +6177,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0xa77f*/ 1074, -1, - /*0x1e933*/ 1335, - /*0xff53*/ 1119, + /*0x1e933*/ 1338, + /*0xff53*/ 1122, /*0x1f23*/ 753, -1, - /*0x16e71*/ 1303, + /*0x16e71*/ 1306, -1, /*0xa73d*/ 1046, /*0x2c6c*/ 901, @@ -6105,11 +6189,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x043b*/ 303, /*0x04bb*/ 381, -1, - /*0x1043b*/ 1146, + /*0x1043b*/ 1149, -1, /*0x1e3b*/ 642, /*0x1ebb*/ 701, - /*0x1e940*/ 1348, + /*0x1e940*/ 1351, /*0x2cbb*/ 933, /*0x0201*/ 165, -1, -1, -1, @@ -6122,11 +6206,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0x0579*/ 464, /*0x10ff*/ 523, - /*0x16e6e*/ 1300, + /*0x16e6e*/ 1303, -1, /*0xa79d*/ 1086, /*0x01f9*/ 161, - /*0x017c*/ 115, + -1, /*0xa739*/ 1044, -1, /*0x2c35*/ 854, @@ -6134,8 +6218,8 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x13af*/ 539, -1, /*0x04af*/ 375, - /*0x16e73*/ 1305, - /*0x1042f*/ 1134, + /*0x16e73*/ 1308, + /*0x1042f*/ 1137, -1, /*0x1e2f*/ 636, /*0x1eaf*/ 695, @@ -6155,8 +6239,8 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x01ad*/ 131, /*0x04a9*/ 372, /*0x2c33*/ 852, - /*0x10429*/ 1128, - /*0x1e92d*/ 1329, + /*0x10429*/ 1131, + /*0x1e92d*/ 1332, /*0x1e29*/ 633, /*0x1ea9*/ 692, /*0x0129*/ 76, @@ -6164,45 +6248,45 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, /*0x0525*/ 434, -1, - /*0x10cc2*/ 1205, + /*0x10cc2*/ 1208, -1, /*0x1f27*/ 757, /*0x01a5*/ 129, -1, -1, /*0x2c40*/ 865, - /*0x1e925*/ 1321, + /*0x1e925*/ 1324, -1, - /*0x10cd0*/ 1219, + /*0x10cd0*/ 1222, /*0x0231*/ 188, - /*0x2d22*/ 991, + /*0x10fe*/ 522, /*0x0523*/ 433, - /*0x10cf2*/ 1253, + /*0x10cf2*/ 1256, /*0x10d0*/ 478, - /*0x16e75*/ 1307, + /*0x16e75*/ 1310, -1, /*0x01a3*/ 128, /*0x10f2*/ 512, -1, /*0xa73b*/ 1045, - /*0x1e923*/ 1319, + /*0x1e923*/ 1322, /*0x1fd1*/ 801, /*0x1f7b*/ 795, /*0x027d*/ 223, /*0x050f*/ 423, - -1, - /*0xff55*/ 1121, + /*0x2d22*/ 991, + /*0xff55*/ 1124, /*0x13ce*/ 570, /*0x044e*/ 322, /*0x04ce*/ 390, /*0x1f31*/ 759, - /*0x1044e*/ 1165, + /*0x1044e*/ 1168, -1, -1, /*0xa7bf*/ 1098, /*0x0477*/ 351, /*0x04f7*/ 411, /*0x0077*/ 21, - /*0xa77c*/ 1073, - /*0x104f7*/ 1198, + -1, + /*0x104f7*/ 1201, /*0x1e77*/ 672, /*0x1ef7*/ 731, /*0x0177*/ 113, @@ -6219,31 +6303,31 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0103*/ 57, /*0x2c83*/ 905, /*0x13e8*/ 596, - /*0xff4f*/ 1115, + /*0xff4f*/ 1118, -1, /*0x0068*/ 7, -1, - /*0x104e8*/ 1183, + /*0x104e8*/ 1186, /*0xa7b7*/ 1094, - /*0x13c6*/ 562, - /*0x0446*/ 314, - /*0x04c6*/ 386, + /*0x13c8*/ 564, + /*0x0448*/ 316, + /*0x04c8*/ 387, -1, - /*0x10446*/ 1157, + /*0x10448*/ 1162, -1, - /*0x13f0*/ 604, + /*0x13ea*/ 598, /*0x24e8*/ 847, - /*0x0146*/ 89, - /*0x0070*/ 14, + /*0x0148*/ 90, + /*0x006a*/ 8, /*0xa729*/ 1037, - /*0x104f0*/ 1191, + /*0x104ea*/ 1188, -1, /*0xa7b5*/ 1093, -1, -1, /*0x1f7a*/ 794, -1, /*0x0242*/ 193, - /*0x03c6*/ 266, + /*0x03c8*/ 268, -1, -1, /*0x0499*/ 364, /*0x0527*/ 435, @@ -6252,16 +6336,17 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0250*/ 199, /*0x0119*/ 68, /*0x2c99*/ 916, - -1, + /*0x017c*/ 115, /*0x0272*/ 221, - /*0x1e927*/ 1323, + /*0x1e927*/ 1326, /*0x0581*/ 472, -1, - /*0xff49*/ 1109, + /*0xff49*/ 1112, -1, -1, - /*0x037b*/ 239, + /*0x0076*/ 20, /*0x1f42*/ 768, - -1, -1, + /*0x104f6*/ 1200, + -1, /*0x00e6*/ 31, -1, /*0x057b*/ 466, @@ -6270,79 +6355,79 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0444*/ 312, /*0x04c4*/ 385, /*0x01fb*/ 162, - /*0x10444*/ 1155, + /*0x10444*/ 1158, -1, /*0x1f72*/ 786, -1, /*0x0144*/ 88, -1, -1, /*0x2d2d*/ 996, - -1, -1, - /*0x037d*/ 241, - /*0x1e931*/ 1333, + -1, -1, -1, + /*0x1e931*/ 1336, -1, -1, -1, /*0x03c4*/ 264, /*0x057d*/ 468, /*0x2179*/ 815, - /*0x13d6*/ 578, - /*0x0456*/ 330, - -1, + -1, -1, -1, /*0x01fd*/ 163, /*0x2d25*/ 994, /*0x00ec*/ 37, /*0x057f*/ 470, -1, -1, /*0x029d*/ 234, - /*0x10cce*/ 1217, + /*0x10cce*/ 1220, /*0x01ff*/ 164, - -1, -1, - /*0x24d6*/ 829, - -1, - /*0xff4d*/ 1113, -1, + /*0x13c6*/ 562, + /*0x0446*/ 314, + /*0x04c6*/ 386, + /*0xff4d*/ 1116, + /*0x10446*/ 1160, /*0x2d23*/ 992, /*0x01bd*/ 136, - /*0x0495*/ 362, -1, + /*0x0146*/ 89, /*0x10f7*/ 517, - /*0x1e93d*/ 1345, - /*0x1e15*/ 623, - /*0x1e95*/ 687, - /*0x0115*/ 66, - /*0x2c95*/ 914, + /*0x1e93d*/ 1348, -1, + /*0x1e07*/ 616, + /*0x1e87*/ 680, + /*0x0107*/ 59, + /*0x2c87*/ 907, /*0x022f*/ 187, -1, /*0x2d0f*/ 972, - -1, + /*0x03c6*/ 266, /*0x057a*/ 465, - /*0x118c2*/ 1256, + /*0x118c2*/ 1259, /*0x0205*/ 167, + -1, -1, + /*0xff4b*/ 1114, + /*0x10ce8*/ 1246, -1, - /*0x1f7c*/ 796, - /*0xff4b*/ 1111, - /*0x10ce8*/ 1243, - -1, -1, -1, - /*0x118d0*/ 1270, + /*0xa77c*/ 1073, + -1, + /*0x118d0*/ 1273, /*0x10e8*/ 502, - /*0x13ea*/ 598, - /*0x10cc6*/ 1209, -1, - /*0x006a*/ 8, + /*0x10cc8*/ 1214, + -1, -1, /*0x01b9*/ 135, - /*0x104ea*/ 1185, + -1, /*0x0229*/ 184, - /*0x10cf0*/ 1251, - /*0x1e939*/ 1341, + /*0x10cea*/ 1248, + /*0x1e939*/ 1344, /*0xa7a5*/ 1090, /*0x2d01*/ 958, /*0x1f05*/ 741, - /*0x10f0*/ 510, + /*0x10ea*/ 504, /*0x2c31*/ 850, -1, - /*0xff43*/ 1103, - -1, -1, -1, -1, - /*0x1e942*/ 1350, + /*0xff43*/ 1106, + -1, + /*0x057e*/ 469, + -1, -1, + /*0x1e942*/ 1353, -1, -1, /*0xa7a3*/ 1089, /*0x0572*/ 457, @@ -6356,57 +6441,56 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x0121*/ 72, /*0x2ca1*/ 920, /*0xa691*/ 1028, - /*0xff41*/ 1101, - /*0x1e07*/ 616, - /*0x1e87*/ 680, - /*0x0107*/ 59, - /*0x2c87*/ 907, + /*0xff41*/ 1104, + -1, -1, -1, + /*0x10f6*/ 516, -1, /*0x2c3d*/ 862, -1, - /*0x0493*/ 361, + /*0x0495*/ 362, -1, - /*0x10cc4*/ 1207, + /*0x10cc4*/ 1210, /*0x2d27*/ 995, - /*0x1e13*/ 622, - /*0x1e93*/ 686, - /*0x0113*/ 65, - /*0x2c93*/ 913, + /*0x1e15*/ 623, + /*0x1e95*/ 687, + /*0x0115*/ 66, + /*0x2c95*/ 914, -1, -1, /*0x13ab*/ 535, /*0x00f9*/ 49, /*0x04ab*/ 373, -1, - /*0x1042b*/ 1130, + /*0x1042b*/ 1133, /*0xa781*/ 1075, /*0x1e2b*/ 634, /*0x1eab*/ 693, /*0x012b*/ 77, /*0x2cab*/ 925, - /*0x13e4*/ 592, + /*0x13f0*/ 604, /*0x0203*/ 166, - /*0x1e93b*/ 1343, - /*0x0064*/ 3, - /*0x10cd6*/ 1225, - /*0x104e4*/ 1179, - /*0x037c*/ 240, - /*0xff47*/ 1107, + /*0x1e93b*/ 1346, + /*0x0070*/ 14, + -1, + /*0x104f0*/ 1194, + -1, + /*0xff47*/ 1110, /*0x2c39*/ 858, - /*0x10d6*/ 484, + /*0x13e4*/ 592, /*0x1f77*/ 791, /*0x0268*/ 214, - /*0x057c*/ 467, + /*0x0064*/ 3, /*0x13e2*/ 590, - /*0x24e4*/ 843, - /*0x16e66*/ 1292, + /*0x104e4*/ 1182, + /*0x16e66*/ 1295, /*0x0062*/ 1, - -1, - /*0x104e2*/ 1177, - -1, + /*0x10cc6*/ 1212, + /*0x104e2*/ 1180, + /*0x037b*/ 239, /*0x2c42*/ 867, - /*0xff45*/ 1105, + /*0xff45*/ 1108, /*0x1f03*/ 739, - -1, -1, + /*0x24e4*/ 843, + /*0x026a*/ 216, /*0x052f*/ 439, -1, /*0x24e2*/ 841, @@ -6414,531 +6498,529 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) /*0x2c50*/ 881, -1, /*0x0505*/ 418, - -1, + /*0x13f4*/ 608, /*0xa7a7*/ 1091, - /*0x1e92f*/ 1331, - -1, + /*0x1e92f*/ 1334, + /*0x0074*/ 18, /*0x0185*/ 119, - /*0x13e0*/ 588, + /*0x104f4*/ 1198, /*0x0219*/ 177, /*0x13da*/ 582, /*0x045a*/ 334, + /*0x037d*/ 241, -1, - /*0x104e0*/ 1175, /*0x217b*/ 817, - /*0x104da*/ 1169, - /*0x1f70*/ 784, - /*0x16e6c*/ 1298, + /*0x104da*/ 1172, + /*0x0493*/ 361, + /*0x16e6c*/ 1301, /*0x0529*/ 436, - /*0x0078*/ 22, - /*0x10cea*/ 1245, - /*0x104f8*/ 1199, - /*0x24e0*/ 839, -1, + /*0x1e13*/ 622, + /*0x1e93*/ 686, + /*0x0113*/ 65, + /*0x2c93*/ 913, /*0x24da*/ 833, - /*0x10ea*/ 504, + /*0x13e0*/ 588, -1, - /*0x1e929*/ 1325, + /*0x1e929*/ 1328, /*0x13dc*/ 584, /*0x045c*/ 336, - /*0x13cc*/ 568, - /*0x044c*/ 320, - /*0x04cc*/ 389, - /*0x104dc*/ 1171, - /*0x1044c*/ 1163, - /*0x03f8*/ 290, + /*0x104e0*/ 1178, + -1, + /*0x1f7c*/ 796, + /*0x104dc*/ 1174, + -1, -1, /*0x217d*/ 819, - /*0x118ce*/ 1268, + /*0x118ce*/ 1271, /*0x2c3b*/ 860, - -1, - /*0x13d8*/ 580, - /*0x0458*/ 332, + /*0x24e0*/ 839, + -1, -1, /*0x24dc*/ 835, -1, /*0x217f*/ 821, - /*0x104d8*/ 1167, + /*0x1f76*/ 790, -1, -1, /*0xa72b*/ 1038, - /*0x03cc*/ 272, + -1, /*0x0585*/ 476, + /*0x13d6*/ 578, + /*0x0456*/ 330, + -1, -1, -1, + /*0x1f44*/ 770, + -1, /*0x13d4*/ 576, /*0x0454*/ 328, - -1, - /*0x24d8*/ 831, - -1, - /*0x1f44*/ 770, - /*0x0256*/ 204, - /*0x13d2*/ 574, - /*0x0452*/ 326, - /*0x0377*/ 238, - -1, -1, + -1, -1, -1, /*0xa7bd*/ 1097, /*0x01ce*/ 141, - /*0x24d4*/ 827, + /*0x24d6*/ 829, /*0x0577*/ 462, - -1, -1, - /*0x017e*/ 116, - /*0x0497*/ 363, + -1, -1, -1, -1, /*0x217a*/ 816, - /*0x24d2*/ 825, - /*0x118c6*/ 1260, - /*0x1e17*/ 624, - /*0x0215*/ 175, - /*0x0117*/ 67, - /*0x2c97*/ 915, - /*0x0503*/ 417, + /*0x24d4*/ 827, + /*0x118c8*/ 1265, + -1, -1, + /*0x0207*/ 168, -1, - /*0x0076*/ 20, - /*0x13f4*/ 608, - /*0x104f6*/ 1197, + /*0x0503*/ 417, + -1, -1, + /*0x13d8*/ 580, + /*0x0458*/ 332, /*0x0183*/ 118, - /*0x0074*/ 18, - /*0x10ce4*/ 1239, - /*0x104f4*/ 1195, + -1, + /*0x10cf0*/ 1254, + /*0x104d8*/ 1170, -1, /*0x0568*/ 447, -1, - /*0x10e4*/ 498, - /*0x13bc*/ 552, - /*0x043c*/ 304, + /*0x10f0*/ 510, + -1, -1, /*0xa7b9*/ 1095, + /*0x10ce4*/ 1242, + /*0x24d8*/ 831, -1, - /*0x1043c*/ 1147, - /*0x1f15*/ 749, - -1, - /*0x10ce2*/ 1237, - /*0x013c*/ 84, - /*0x01c6*/ 138, - /*0x0570*/ 455, - /*0x026a*/ 216, + /*0x1f07*/ 743, + /*0x10ce2*/ 1240, + /*0x10e4*/ 498, + /*0x217e*/ 820, + /*0x056a*/ 449, + /*0x0497*/ 363, /*0x10e2*/ 496, - /*0x13c8*/ 564, - /*0x0448*/ 316, - /*0x04c8*/ 387, + /*0x13d2*/ 574, + /*0x0452*/ 326, + /*0x1e17*/ 624, /*0x2172*/ 808, - /*0x10448*/ 1159, - -1, - /*0x03bc*/ 257, - -1, - /*0x0148*/ 90, - /*0x16e79*/ 1311, + /*0x0117*/ 67, + /*0x2c97*/ 915, + /*0x13b0*/ 540, + /*0x0430*/ 292, -1, + /*0x16e79*/ 1314, + /*0x10430*/ 1138, /*0x0519*/ 428, /*0x00fb*/ 51, - -1, -1, - /*0x118c4*/ 1258, + /*0x057c*/ 467, + /*0x24d2*/ 825, + /*0x118c4*/ 1261, /*0x0199*/ 124, -1, - /*0x10ce0*/ 1235, - /*0x03c8*/ 268, - /*0x10cda*/ 1229, + /*0x10f4*/ 514, -1, - /*0x0583*/ 474, - /*0x10e0*/ 494, + /*0x10cda*/ 1232, -1, + /*0x0583*/ 474, + -1, -1, /*0x10da*/ 488, - -1, -1, -1, + /*0x0576*/ 461, + -1, + /*0x0078*/ 22, /*0x2c4e*/ 879, - /*0x0207*/ 168, - /*0x10f8*/ 518, - -1, -1, + /*0x104f8*/ 1202, + -1, -1, -1, /*0x00fd*/ 53, - -1, + /*0x10ce0*/ 1238, /*0x2d05*/ 962, - /*0x118d6*/ 1276, - /*0x10cdc*/ 1231, -1, - /*0x10ccc*/ 1215, - /*0x0213*/ 174, + /*0x10cdc*/ 1234, + -1, + /*0x10e0*/ 494, + /*0x0215*/ 175, /*0x00ff*/ 55, /*0x10dc*/ 490, - -1, + /*0x03f8*/ 290, /*0x1f21*/ 751, - -1, -1, + /*0x13de*/ 586, + /*0x045e*/ 338, /*0xa7bb*/ 1096, -1, - /*0x10cd8*/ 1227, - /*0x1f07*/ 743, + /*0x118c6*/ 1263, + /*0x104de*/ 1176, -1, /*0x022b*/ 185, -1, - /*0x10d8*/ 486, - /*0x217c*/ 818, + /*0x13bc*/ 552, + /*0x043c*/ 304, -1, /*0x2c68*/ 899, - -1, -1, - /*0x10cd4*/ 1223, - /*0x1f13*/ 747, + /*0x1043c*/ 1150, + /*0x24de*/ 837, + /*0x10cd6*/ 1228, + /*0x1f15*/ 749, + /*0x013c*/ 84, -1, - /*0x01d6*/ 145, - /*0x2c46*/ 871, - /*0x10d4*/ 482, + /*0x2c48*/ 873, + /*0x10d6*/ 484, -1, - /*0x10cd2*/ 1221, + /*0x10cd4*/ 1226, /*0x00fa*/ 50, - /*0x13ca*/ 566, - /*0x044a*/ 318, - /*0x04ca*/ 388, - /*0x10d2*/ 480, - /*0x1044a*/ 1161, + -1, + /*0x2c6a*/ 900, + -1, + /*0x10d4*/ 482, + /*0x03bc*/ 257, /*0x2184*/ 822, - /*0x10fe*/ 522, - /*0x0515*/ 426, - -1, -1, -1, -1, - /*0x0195*/ 123, -1, - /*0x1f64*/ 780, + /*0x01c6*/ 138, + /*0x0507*/ 419, + /*0x1e09*/ 617, + /*0x1e89*/ 681, + /*0x0109*/ 60, + /*0x2c89*/ 908, -1, - /*0xa785*/ 1077, - /*0x13b6*/ 546, - /*0x0436*/ 298, - /*0x03ca*/ 270, + /*0x1f70*/ 784, -1, - /*0x10436*/ 1141, - /*0x10f6*/ 516, + /*0xa785*/ 1077, + -1, -1, -1, -1, + /*0x10cd8*/ 1230, -1, - /*0x13b4*/ 544, - /*0x0434*/ 296, - /*0x10f4*/ 514, + /*0x1f64*/ 780, + -1, -1, + /*0x10d8*/ 486, /*0x1f62*/ 778, - /*0x10434*/ 1139, + /*0x00fe*/ 54, -1, - /*0x0260*/ 209, + /*0x2c76*/ 903, -1, /*0xa7a9*/ 1092, /*0x048d*/ 358, - /*0x056a*/ 449, + -1, /*0x00f2*/ 43, - /*0x03b6*/ 251, + /*0x0213*/ 174, /*0x1e0d*/ 619, /*0x1e8d*/ 683, /*0x010d*/ 62, /*0x2c8d*/ 910, /*0x2c44*/ 869, /*0x2d03*/ 960, - /*0x03b4*/ 249, - /*0x10cc8*/ 1211, - /*0x1e09*/ 617, - /*0x1e89*/ 681, - /*0x0109*/ 60, - /*0x2c89*/ 908, -1, + /*0x10cd2*/ 1224, + /*0x0377*/ 238, + /*0x1f74*/ 788, + /*0x0260*/ 209, + -1, + /*0x10d2*/ 480, /*0x025c*/ 208, - /*0x1f60*/ 776, + /*0x13cc*/ 568, + /*0x044c*/ 320, + /*0x04cc*/ 389, + -1, + /*0x1044c*/ 1166, + -1, + /*0x1f13*/ 747, -1, -1, - /*0x13b0*/ 540, - /*0x0430*/ 292, - /*0x13de*/ 586, - /*0x045e*/ 338, - /*0x10430*/ 1135, - /*0x1f78*/ 792, /*0x0521*/ 432, - /*0x104de*/ 1173, - /*0x214e*/ 805, - /*0x2c56*/ 887, -1, + /*0x214e*/ 805, + -1, -1, /*0x01a1*/ 127, - /*0x0507*/ 419, - -1, - /*0x049f*/ 367, + -1, -1, + /*0x1f60*/ 776, /*0x2177*/ 813, - /*0x24de*/ 837, + /*0x03cc*/ 272, + -1, -1, + /*0x0256*/ 204, + /*0x10f8*/ 518, -1, - /*0x1e1f*/ 628, + /*0x2c46*/ 871, + /*0x0515*/ 426, + -1, + /*0x2d19*/ 982, /*0x0254*/ 203, - /*0x011f*/ 71, - /*0x2c9f*/ 919, -1, - /*0x0513*/ 425, + /*0x0195*/ 123, + /*0x13ca*/ 566, + /*0x044a*/ 318, + /*0x04ca*/ 388, -1, - /*0x2d19*/ 982, - /*0x0252*/ 201, - -1, -1, -1, -1, -1, -1, + /*0x1044a*/ 1164, -1, - /*0x00fc*/ 52, /*0x052b*/ 437, - /*0x0217*/ 176, + /*0x10cde*/ 1236, -1, /*0xa783*/ 1076, - /*0x16e7b*/ 1313, - -1, -1, -1, -1, - /*0x1e92b*/ 1327, + /*0x16e7b*/ 1316, + -1, + /*0x10de*/ 492, + /*0x037c*/ 240, + -1, + /*0x1e92b*/ 1330, + /*0x0570*/ 455, + /*0x13b6*/ 546, + /*0x0436*/ 298, + /*0x03ca*/ 270, + -1, + /*0x10436*/ 1144, + -1, + /*0x13b4*/ 544, + /*0x0434*/ 296, /*0x0564*/ 443, - -1, -1, -1, -1, - /*0x2170*/ 806, - -1, -1, -1, - /*0x2c6a*/ 900, - -1, -1, -1, - /*0x0562*/ 441, - /*0x023c*/ 190, - /*0x10cca*/ 1213, - /*0x16e7d*/ 1315, - /*0x118da*/ 1280, - -1, -1, -1, - /*0x1f76*/ 790, - -1, -1, - /*0x16e7f*/ 1317, - /*0x1f74*/ 788, - -1, -1, -1, -1, - /*0xa799*/ 1084, + /*0xa7c8*/ 1100, + /*0x10434*/ 1142, + -1, + /*0x0562*/ 441, -1, -1, - /*0xa68f*/ 1027, + /*0x16e7d*/ 1318, + /*0x118da*/ 1283, + -1, -1, + /*0x03b6*/ 251, + /*0x217c*/ 818, + -1, + /*0x0217*/ 176, + /*0x16e7f*/ 1320, -1, - /*0x118dc*/ 1282, + /*0x03b4*/ 249, + /*0x0252*/ 201, + -1, -1, + /*0xa799*/ 1084, -1, - /*0x118cc*/ 1266, + /*0x0574*/ 459, + /*0xa68f*/ 1027, + /*0x2176*/ 812, + /*0x118dc*/ 1285, -1, -1, -1, -1, -1, -1, + -1, + /*0x0513*/ 425, /*0x01da*/ 147, - /*0x0578*/ 463, - /*0x2d15*/ 978, - /*0x118d8*/ 1278, - -1, -1, -1, - /*0x16e7a*/ 1312, - -1, -1, -1, -1, -1, + /*0xa7f6*/ 1102, + -1, + /*0x2d07*/ 964, + -1, + /*0x049f*/ 367, + -1, + /*0x16e7a*/ 1315, + -1, + /*0x1e1f*/ 628, + /*0x1f30*/ 758, + /*0x011f*/ 71, + /*0x2c9f*/ 919, /*0xa681*/ 1020, - /*0x118d4*/ 1274, + /*0x118d6*/ 1279, -1, -1, -1, /*0x01dc*/ 148, - -1, - /*0x01cc*/ 140, - /*0x118d2*/ 1272, - -1, -1, -1, -1, -1, - /*0x10cde*/ 1233, -1, -1, - /*0x01d8*/ 146, - -1, - /*0x10de*/ 492, + /*0x118d4*/ 1277, + /*0x10ccc*/ 1218, -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x01d4*/ 144, + /*0x1f78*/ 792, + -1, -1, -1, -1, -1, -1, + /*0x16e7e*/ 1319, -1, - /*0x16e72*/ 1304, + /*0x023c*/ 190, -1, -1, - /*0x057e*/ 469, + /*0x01d6*/ 145, -1, - /*0x01d2*/ 143, + /*0x16e72*/ 1307, + /*0x118d8*/ 1281, + -1, -1, -1, + /*0x01d4*/ 144, -1, /*0x00e8*/ 33, -1, -1, - /*0x0517*/ 427, - -1, + /*0xa787*/ 1078, + /*0x10cca*/ 1216, /*0x2d21*/ 990, - -1, -1, -1, -1, -1, - /*0x2d07*/ 964, - /*0x0576*/ 461, - /*0x00f0*/ 41, - /*0xff42*/ 1102, - -1, - /*0x0574*/ 459, - /*0x118c8*/ 1262, + /*0x0209*/ 169, + -1, -1, -1, -1, -1, -1, + /*0x00ea*/ 35, + /*0xff42*/ 1105, + -1, -1, + /*0x118d2*/ 1275, -1, /*0x2c5a*/ 891, - -1, -1, - /*0x2d13*/ 976, - /*0xff50*/ 1116, - -1, -1, -1, -1, -1, -1, + -1, + /*0x01d8*/ 146, + /*0x2d15*/ 978, + /*0xff50*/ 1119, + -1, -1, -1, -1, -1, + /*0x00fc*/ 52, -1, -1, -1, -1, /*0x020d*/ 171, - /*0x1e93c*/ 1344, + /*0x0517*/ 427, -1, /*0x2c5c*/ 893, + -1, -1, -1, -1, + /*0x00f6*/ 47, -1, - /*0x2c4c*/ 877, - -1, - /*0x1f36*/ 764, - /*0x0209*/ 169, - -1, -1, -1, - /*0x16e7c*/ 1314, - -1, - /*0x1f34*/ 762, - /*0x2c58*/ 889, - -1, -1, -1, + /*0x01d2*/ 143, + -1, -1, -1, -1, -1, + /*0x01b0*/ 132, + -1, -1, /*0x1fb1*/ 799, - -1, + /*0x1e930*/ 1335, /*0xa7a1*/ 1088, -1, -1, -1, -1, + /*0x2c56*/ 887, + -1, -1, + /*0x118de*/ 1287, + /*0x0578*/ 463, + -1, -1, /*0x2c54*/ 885, - /*0xa787*/ 1078, - -1, -1, -1, -1, -1, - /*0x2c52*/ 883, - -1, - /*0x021f*/ 180, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, - /*0xa793*/ 1081, - -1, -1, -1, -1, -1, - /*0x1f30*/ 758, - -1, -1, -1, /*0x0283*/ 226, + /*0x2170*/ 806, -1, -1, -1, - /*0x2c76*/ 903, - /*0x118ca*/ 1264, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x2c3c*/ 861, - -1, -1, -1, -1, -1, -1, + /*0x2d13*/ 976, + -1, -1, + /*0x2c58*/ 889, -1, -1, -1, -1, -1, -1, - /*0x2c48*/ 873, -1, -1, -1, -1, -1, -1, - /*0x00ea*/ 35, + /*0x1e93c*/ 1347, -1, -1, -1, -1, -1, -1, - -1, - /*0x2178*/ 814, - /*0x16e77*/ 1309, - -1, - /*0x01b6*/ 134, - -1, -1, - /*0x1fd0*/ 800, - /*0x1e936*/ 1338, -1, -1, - /*0x01b4*/ 133, - -1, - /*0x050d*/ 422, - /*0x2d17*/ 980, - /*0x1e934*/ 1336, - /*0x118de*/ 1284, - -1, -1, -1, -1, /*0x0509*/ 420, - -1, -1, - /*0x16e68*/ 1294, - -1, -1, -1, -1, - /*0xff4e*/ 1114, - -1, -1, -1, -1, -1, -1, + /*0x2c52*/ 883, -1, - /*0x16e70*/ 1302, + /*0x2174*/ 810, -1, -1, -1, - /*0x01b0*/ 132, + /*0x2c30*/ 849, + -1, -1, -1, -1, + /*0x1f36*/ 764, + -1, -1, -1, -1, + /*0x16e77*/ 1312, + /*0x1f34*/ 762, -1, -1, -1, - /*0x1e930*/ 1332, - /*0x217e*/ 820, + /*0x1fd0*/ 800, + -1, -1, + /*0xa793*/ 1081, + /*0x118cc*/ 1269, -1, - /*0x051f*/ 431, + /*0x050d*/ 422, -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x021f*/ 180, -1, - /*0x2c4a*/ 875, - -1, - /*0x00e4*/ 29, - -1, - /*0xa685*/ 1022, - -1, - /*0x2176*/ 812, - -1, - /*0xa797*/ 1083, - /*0xff46*/ 1106, - /*0x2174*/ 810, + /*0x16e68*/ 1297, -1, -1, -1, -1, - /*0x00e2*/ 27, - -1, - /*0x2c36*/ 855, - -1, -1, -1, -1, -1, -1, - /*0x2c34*/ 853, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, + /*0xff4e*/ 1117, -1, -1, - /*0x00e0*/ 25, - -1, -1, -1, -1, -1, -1, + /*0x2c5e*/ 895, + -1, -1, -1, -1, + /*0x16e6a*/ 1299, + /*0x01cc*/ 140, + -1, -1, + /*0x2c3c*/ 861, -1, - /*0x00f8*/ 48, + /*0x118ca*/ 1267, + -1, -1, + /*0x2d17*/ 980, -1, -1, -1, -1, -1, -1, - /*0x2c30*/ 849, - /*0xff44*/ 1104, - /*0x2c5e*/ 895, + /*0x16e7c*/ 1317, -1, -1, -1, -1, + /*0x00f0*/ 41, /*0x0287*/ 227, + /*0xa685*/ 1022, + -1, -1, -1, -1, + /*0xff48*/ 1111, + /*0x16e76*/ 1311, + /*0x00e4*/ 29, + -1, -1, -1, + /*0x00e2*/ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0xff56*/ 1122, + /*0x01b6*/ 134, -1, -1, - /*0xa683*/ 1021, - -1, -1, -1, -1, -1, -1, + /*0x00f4*/ 45, + /*0x1e936*/ 1341, -1, - /*0x16e6a*/ 1296, - -1, -1, -1, - /*0x00fe*/ 54, + /*0x01b4*/ 133, -1, -1, - /*0x2d0d*/ 970, + /*0xa797*/ 1083, + /*0x1e934*/ 1339, -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x2c4c*/ 877, + -1, -1, -1, + /*0xff44*/ 1107, + /*0x00e0*/ 25, -1, + /*0x2178*/ 814, + -1, -1, -1, -1, -1, -1, + -1, -1, /*0x2d09*/ 966, -1, -1, -1, -1, - /*0x00f6*/ 47, - -1, -1, -1, - /*0x00f4*/ 45, - -1, -1, -1, -1, - /*0xa699*/ 1032, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x2d1f*/ 988, + /*0x051f*/ 431, -1, -1, -1, -1, -1, -1, + -1, + /*0xa683*/ 1021, + -1, -1, + /*0x2c4a*/ 875, -1, -1, -1, -1, -1, -1, + /*0xff46*/ 1109, + -1, -1, -1, -1, + /*0x2d0d*/ 970, + -1, -1, -1, -1, + /*0x2c36*/ 855, + -1, -1, -1, -1, -1, + /*0x2c34*/ 853, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0x16e64*/ 1290, + /*0xa699*/ 1032, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0x16e62*/ 1288, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, - /*0xa79f*/ 1087, - -1, -1, - /*0xa695*/ 1030, -1, -1, -1, -1, -1, -1, - /*0x16e60*/ 1286, + -1, -1, -1, -1, -1, + /*0x16e70*/ 1305, -1, -1, -1, -1, -1, -1, + /*0x00f8*/ 48, -1, - /*0x16e78*/ 1310, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, + /*0x16e64*/ 1293, + -1, -1, -1, + /*0x16e62*/ 1291, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xff5a*/ 1126, + -1, -1, -1, -1, -1, + /*0xa687*/ 1023, + /*0x16e74*/ 1309, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xa7ca*/ 1101, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0xa687*/ 1023, - /*0x16e7e*/ 1316, + /*0x16e60*/ 1289, -1, -1, - /*0xff4c*/ 1112, + /*0x2d1f*/ 988, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /*0xa693*/ 1029, - -1, -1, - /*0xff58*/ 1124, - -1, -1, - /*0x16e76*/ 1308, - -1, -1, -1, - /*0x16e74*/ 1306, -1, -1, -1, - /*0xff54*/ 1120, + /*0xff5a*/ 1129, -1, -1, -1, -1, -1, -1, - /*0xff52*/ 1118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + /*0xa695*/ 1030, -1, -1, -1, -1, -1, -1, + /*0xa79f*/ 1087, -1, -1, -1, -1, -1, -1, + /*0xff56*/ 1125, -1, -1, -1, -1, -1, -1, + /*0xff54*/ 1123, -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xff48*/ 1108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xff58*/ 1127, -1, -1, - /*0x1fe0*/ 802, /*0x0289*/ 229, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x16e78*/ 1313, -1, -1, -1, -1, -1, -1, + /*0xa693*/ 1029, + -1, + /*0xff52*/ 1121, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0xa697*/ 1031, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0xff4a*/ 1110, -1, -1, -1, -1, -1, -1, + -1, + /*0x1fe0*/ 802, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -6947,18 +7029,24 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0xa697*/ 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, + /*0x1fb0*/ 798, + -1, -1, -1, + /*0xff4c*/ 1115, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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*/ 1026, + -1, + /*0xff4a*/ 1113, -1, -1, -1, -1, -1, -1, -1, /*0xa689*/ 1024, @@ -6966,10 +7054,8 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -1, -1, -1, -1, -1, -1, -1, -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, + /*0xa68d*/ 1026 }; if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) diff --git a/ruby/enc/unicode/12.1.0/name2ctype.h b/ruby/enc/unicode/13.0.0/name2ctype.h similarity index 90% rename from ruby/enc/unicode/12.1.0/name2ctype.h rename to ruby/enc/unicode/13.0.0/name2ctype.h index b2270d5ca..e8997c7d2 100644 --- a/ruby/enc/unicode/12.1.0/name2ctype.h +++ b/ruby/enc/unicode/13.0.0/name2ctype.h @@ -43,7 +43,7 @@ static const OnigCodePoint CR_NEWLINE[] = { /* 'Alpha': [[:Alpha:]] */ static const OnigCodePoint CR_Alpha[] = { - 679, + 695, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -97,7 +97,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d4, 0x08df, 0x08e3, 0x08e9, 0x08f0, 0x093b, @@ -201,8 +201,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, @@ -212,7 +211,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x0d54, 0x0d57, 0x0d5f, 0x0d63, 0x0d7a, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -300,6 +299,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x1a20, 0x1a5e, 0x1a61, 0x1a74, 0x1aa7, 0x1aa7, + 0x1abf, 0x1ac0, 0x1b00, 0x1b33, 0x1b35, 0x1b43, 0x1b45, 0x1b4b, @@ -387,10 +387,10 @@ static const OnigCodePoint CR_Alpha[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -402,8 +402,8 @@ static const OnigCodePoint CR_Alpha[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa805, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa805, 0xa807, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c3, @@ -434,7 +434,7 @@ static const OnigCodePoint CR_Alpha[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabea, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -519,19 +519,24 @@ static const OnigCodePoint CR_Alpha[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, + 0x10e80, 0x10ea9, + 0x10eab, 0x10eac, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11045, 0x11082, 0x110b8, 0x110d0, 0x110e8, 0x11100, 0x11132, - 0x11144, 0x11146, + 0x11144, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11180, 0x111bf, 0x111c1, 0x111c4, + 0x111ce, 0x111cf, 0x111da, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, @@ -560,7 +565,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x11400, 0x11441, 0x11443, 0x11445, 0x11447, 0x1144a, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114c1, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -576,7 +581,14 @@ static const OnigCodePoint CR_Alpha[] = { 0x1171d, 0x1172a, 0x11800, 0x11838, 0x118a0, 0x118df, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x1193c, + 0x1193f, 0x11942, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119df, @@ -609,6 +621,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x11d93, 0x11d96, 0x11d98, 0x11d98, 0x11ee0, 0x11ef6, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -627,8 +640,10 @@ static const OnigCodePoint CR_Alpha[] = { 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -717,12 +732,13 @@ static const OnigCodePoint CR_Alpha[] = { 0x1f130, 0x1f149, 0x1f150, 0x1f169, 0x1f170, 0x1f189, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Alpha */ /* 'Blank': [[:Blank:]] */ @@ -747,7 +763,7 @@ static const OnigCodePoint CR_Cntrl[] = { /* 'Digit': [[:Digit:]] */ static const OnigCodePoint CR_Digit[] = { - 59, + 61, 0x0030, 0x0039, 0x0660, 0x0669, 0x06f0, 0x06f9, @@ -798,6 +814,7 @@ static const OnigCodePoint CR_Digit[] = { 0x116c0, 0x116c9, 0x11730, 0x11739, 0x118e0, 0x118e9, + 0x11950, 0x11959, 0x11c50, 0x11c59, 0x11d50, 0x11d59, 0x11da0, 0x11da9, @@ -807,11 +824,12 @@ static const OnigCodePoint CR_Digit[] = { 0x1e140, 0x1e149, 0x1e2f0, 0x1e2f9, 0x1e950, 0x1e959, + 0x1fbf0, 0x1fbf9, }; /* CR_Digit */ /* 'Graph': [[:Graph:]] */ static const OnigCodePoint CR_Graph[] = { - 671, + 682, 0x0021, 0x007e, 0x00a1, 0x0377, 0x037a, 0x037f, @@ -836,7 +854,7 @@ static const OnigCodePoint CR_Graph[] = { 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -891,7 +909,7 @@ static const OnigCodePoint CR_Graph[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -935,15 +953,14 @@ static const OnigCodePoint CR_Graph[] = { 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, @@ -1030,7 +1047,7 @@ static const OnigCodePoint CR_Graph[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -1071,7 +1088,7 @@ static const OnigCodePoint CR_Graph[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, + 0x2b97, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -1088,7 +1105,7 @@ static const OnigCodePoint CR_Graph[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4f, + 0x2de0, 0x2e52, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -1098,18 +1115,16 @@ static const OnigCodePoint CR_Graph[] = { 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 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, @@ -1129,7 +1144,7 @@ static const OnigCodePoint CR_Graph[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -1174,7 +1189,7 @@ static const OnigCodePoint CR_Graph[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, @@ -1234,8 +1249,12 @@ static const OnigCodePoint CR_Graph[] = { 0x10cfa, 0x10d27, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, @@ -1244,10 +1263,9 @@ static const OnigCodePoint CR_Graph[] = { 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11176, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1123e, @@ -1273,9 +1291,8 @@ static const OnigCodePoint CR_Graph[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 0x11400, 0x1145b, + 0x1145d, 0x11461, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -1290,7 +1307,14 @@ static const OnigCodePoint CR_Graph[] = { 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, @@ -1318,6 +1342,7 @@ static const OnigCodePoint CR_Graph[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, @@ -1341,9 +1366,11 @@ static const OnigCodePoint CR_Graph[] = { 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, @@ -1441,17 +1468,15 @@ static const OnigCodePoint CR_Graph[] = { 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, @@ -1460,24 +1485,28 @@ static const OnigCodePoint CR_Graph[] = { 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, - 0x20000, 0x2a6d6, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, @@ -1487,7 +1516,7 @@ static const OnigCodePoint CR_Graph[] = { /* 'Lower': [[:Lower:]] */ static const OnigCodePoint CR_Lower[] = { - 649, + 652, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, @@ -2096,9 +2125,12 @@ static const OnigCodePoint CR_Lower[] = { 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, 0xa7c3, 0xa7c3, + 0xa7c8, 0xa7c8, + 0xa7ca, 0xa7ca, + 0xa7f6, 0xa7f6, 0xa7f8, 0xa7fa, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab68, 0xab70, 0xabbf, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -2141,7 +2173,7 @@ static const OnigCodePoint CR_Lower[] = { /* 'Print': [[:Print:]] */ static const OnigCodePoint CR_Print[] = { - 668, + 679, 0x0020, 0x007e, 0x00a0, 0x0377, 0x037a, 0x037f, @@ -2166,7 +2198,7 @@ static const OnigCodePoint CR_Print[] = { 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -2221,7 +2253,7 @@ static const OnigCodePoint CR_Print[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -2265,15 +2297,14 @@ static const OnigCodePoint CR_Print[] = { 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, @@ -2359,7 +2390,7 @@ static const OnigCodePoint CR_Print[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -2398,7 +2429,7 @@ static const OnigCodePoint CR_Print[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, + 0x2b97, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -2415,7 +2446,7 @@ static const OnigCodePoint CR_Print[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4f, + 0x2de0, 0x2e52, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -2425,18 +2456,16 @@ static const OnigCodePoint CR_Print[] = { 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 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, @@ -2456,7 +2485,7 @@ static const OnigCodePoint CR_Print[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -2501,7 +2530,7 @@ static const OnigCodePoint CR_Print[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, @@ -2561,8 +2590,12 @@ static const OnigCodePoint CR_Print[] = { 0x10cfa, 0x10d27, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, @@ -2571,10 +2604,9 @@ static const OnigCodePoint CR_Print[] = { 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11176, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1123e, @@ -2600,9 +2632,8 @@ static const OnigCodePoint CR_Print[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 0x11400, 0x1145b, + 0x1145d, 0x11461, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -2617,7 +2648,14 @@ static const OnigCodePoint CR_Print[] = { 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, @@ -2645,6 +2683,7 @@ static const OnigCodePoint CR_Print[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, @@ -2668,9 +2707,11 @@ static const OnigCodePoint CR_Print[] = { 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, @@ -2768,17 +2809,15 @@ static const OnigCodePoint CR_Print[] = { 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, @@ -2787,24 +2826,28 @@ static const OnigCodePoint CR_Print[] = { 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, - 0x20000, 0x2a6d6, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, @@ -2814,7 +2857,7 @@ static const OnigCodePoint CR_Print[] = { /* 'XPosixPunct': [[:Punct:]] */ static const OnigCodePoint CR_XPosixPunct[] = { - 177, + 180, 0x0021, 0x002f, 0x003a, 0x0040, 0x005b, 0x0060, @@ -2900,6 +2943,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x2d70, 0x2d70, 0x2e00, 0x2e2e, 0x2e30, 0x2e4f, + 0x2e52, 0x2e52, 0x3001, 0x3003, 0x3008, 0x3011, 0x3014, 0x301f, @@ -2953,6 +2997,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x10af0, 0x10af6, 0x10b39, 0x10b3f, 0x10b99, 0x10b9c, + 0x10ead, 0x10ead, 0x10f55, 0x10f59, 0x11047, 0x1104d, 0x110bb, 0x110bc, @@ -2966,7 +3011,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x11238, 0x1123d, 0x112a9, 0x112a9, 0x1144b, 0x1144f, - 0x1145b, 0x1145b, + 0x1145a, 0x1145b, 0x1145d, 0x1145d, 0x114c6, 0x114c6, 0x115c1, 0x115d7, @@ -2974,6 +3019,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x11660, 0x1166c, 0x1173c, 0x1173e, 0x1183b, 0x1183b, + 0x11944, 0x11946, 0x119e2, 0x119e2, 0x11a3f, 0x11a46, 0x11a9a, 0x11a9c, @@ -3011,7 +3057,7 @@ static const OnigCodePoint CR_Space[] = { /* 'Upper': [[:Upper:]] */ static const OnigCodePoint CR_Upper[] = { - 641, + 643, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -3611,7 +3657,9 @@ static const OnigCodePoint CR_Upper[] = { 0xa7bc, 0xa7bc, 0xa7be, 0xa7be, 0xa7c2, 0xa7c2, - 0xa7c4, 0xa7c6, + 0xa7c4, 0xa7c7, + 0xa7c9, 0xa7c9, + 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, 0x104b0, 0x104d3, @@ -3665,7 +3713,7 @@ static const OnigCodePoint CR_XDigit[] = { /* 'Word': [[:Word:]] */ static const OnigCodePoint CR_Word[] = { - 716, + 732, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -3717,7 +3765,7 @@ static const OnigCodePoint CR_Word[] = { 0x0840, 0x085b, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, @@ -3777,7 +3825,7 @@ static const OnigCodePoint CR_Word[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, @@ -3823,8 +3871,7 @@ static const OnigCodePoint CR_Word[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, @@ -3833,7 +3880,7 @@ static const OnigCodePoint CR_Word[] = { 0x0d5f, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -3932,7 +3979,7 @@ static const OnigCodePoint CR_Word[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, @@ -4017,10 +4064,10 @@ static const OnigCodePoint CR_Word[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -4031,8 +4078,9 @@ static const OnigCodePoint CR_Word[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa827, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa827, + 0xa82c, 0xa82c, 0xa840, 0xa873, 0xa880, 0xa8c5, 0xa8d0, 0xa8d9, @@ -4058,7 +4106,7 @@ static const OnigCodePoint CR_Word[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, @@ -4157,9 +4205,13 @@ static const OnigCodePoint CR_Word[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10e80, 0x10ea9, + 0x10eab, 0x10eac, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11046, 0x11066, 0x1106f, @@ -4168,12 +4220,12 @@ static const OnigCodePoint CR_Word[] = { 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, - 0x11144, 0x11146, + 0x11144, 0x11147, 0x11150, 0x11173, 0x11176, 0x11176, 0x11180, 0x111c4, 0x111c9, 0x111cc, - 0x111d0, 0x111da, + 0x111ce, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x11237, @@ -4202,7 +4254,7 @@ static const OnigCodePoint CR_Word[] = { 0x11370, 0x11374, 0x11400, 0x1144a, 0x11450, 0x11459, - 0x1145e, 0x1145f, + 0x1145e, 0x11461, 0x11480, 0x114c5, 0x114c7, 0x114c7, 0x114d0, 0x114d9, @@ -4219,7 +4271,14 @@ static const OnigCodePoint CR_Word[] = { 0x11730, 0x11739, 0x11800, 0x1183a, 0x118a0, 0x118e9, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11943, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e1, @@ -4250,6 +4309,7 @@ static const OnigCodePoint CR_Word[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef6, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -4270,9 +4330,11 @@ static const OnigCodePoint CR_Word[] = { 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, - 0x16fe3, 0x16fe3, + 0x16fe3, 0x16fe4, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -4375,18 +4437,20 @@ static const OnigCodePoint CR_Word[] = { 0x1f130, 0x1f149, 0x1f150, 0x1f169, 0x1f170, 0x1f189, - 0x20000, 0x2a6d6, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0100, 0xe01ef, }; /* CR_Word */ /* 'Alnum': [[:Alnum:]] */ static const OnigCodePoint CR_Alnum[] = { - 715, + 732, 0x0030, 0x0039, 0x0041, 0x005a, 0x0061, 0x007a, @@ -4440,7 +4504,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d4, 0x08df, 0x08e3, 0x08e9, 0x08f0, 0x093b, @@ -4550,8 +4614,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, @@ -4562,7 +4625,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x0d5f, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -4658,6 +4721,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x1a80, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, + 0x1abf, 0x1ac0, 0x1b00, 0x1b33, 0x1b35, 0x1b43, 0x1b45, 0x1b4b, @@ -4745,10 +4809,10 @@ static const OnigCodePoint CR_Alnum[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -4759,8 +4823,8 @@ static const OnigCodePoint CR_Alnum[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa805, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa805, 0xa807, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c3, @@ -4791,7 +4855,7 @@ static const OnigCodePoint CR_Alnum[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabea, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -4880,9 +4944,13 @@ static const OnigCodePoint CR_Alnum[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10e80, 0x10ea9, + 0x10eab, 0x10eac, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11045, 0x11066, 0x1106f, @@ -4891,12 +4959,12 @@ static const OnigCodePoint CR_Alnum[] = { 0x110f0, 0x110f9, 0x11100, 0x11132, 0x11136, 0x1113f, - 0x11144, 0x11146, + 0x11144, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11180, 0x111bf, 0x111c1, 0x111c4, - 0x111d0, 0x111da, + 0x111ce, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x11234, @@ -4926,7 +4994,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x11443, 0x11445, 0x11447, 0x1144a, 0x11450, 0x11459, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114c1, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -4946,7 +5014,15 @@ static const OnigCodePoint CR_Alnum[] = { 0x11730, 0x11739, 0x11800, 0x11838, 0x118a0, 0x118e9, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x1193c, + 0x1193f, 0x11942, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119df, @@ -4982,6 +5058,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x11d98, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef6, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -5002,8 +5079,10 @@ static const OnigCodePoint CR_Alnum[] = { 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -5096,12 +5175,14 @@ static const OnigCodePoint CR_Alnum[] = { 0x1f130, 0x1f149, 0x1f150, 0x1f169, 0x1f170, 0x1f189, - 0x20000, 0x2a6d6, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Alnum */ /* 'ASCII': [[:ASCII:]] */ @@ -5112,7 +5193,7 @@ static const OnigCodePoint CR_ASCII[] = { /* 'Punct' */ static const OnigCodePoint CR_Punct[] = { - 182, + 185, 0x0021, 0x0023, 0x0025, 0x002a, 0x002c, 0x002f, @@ -5203,6 +5284,7 @@ static const OnigCodePoint CR_Punct[] = { 0x2d70, 0x2d70, 0x2e00, 0x2e2e, 0x2e30, 0x2e4f, + 0x2e52, 0x2e52, 0x3001, 0x3003, 0x3008, 0x3011, 0x3014, 0x301f, @@ -5256,6 +5338,7 @@ static const OnigCodePoint CR_Punct[] = { 0x10af0, 0x10af6, 0x10b39, 0x10b3f, 0x10b99, 0x10b9c, + 0x10ead, 0x10ead, 0x10f55, 0x10f59, 0x11047, 0x1104d, 0x110bb, 0x110bc, @@ -5269,7 +5352,7 @@ static const OnigCodePoint CR_Punct[] = { 0x11238, 0x1123d, 0x112a9, 0x112a9, 0x1144b, 0x1144f, - 0x1145b, 0x1145b, + 0x1145a, 0x1145b, 0x1145d, 0x1145d, 0x114c6, 0x114c6, 0x115c1, 0x115d7, @@ -5277,6 +5360,7 @@ static const OnigCodePoint CR_Punct[] = { 0x11660, 0x1166c, 0x1173c, 0x1173e, 0x1183b, 0x1183b, + 0x11944, 0x11946, 0x119e2, 0x119e2, 0x11a3f, 0x11a46, 0x11a9a, 0x11a9c, @@ -5306,7 +5390,7 @@ static const OnigCodePoint CR_Any[] = { /* 'Assigned': - */ static const OnigCodePoint CR_Assigned[] = { - 666, + 677, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -5330,7 +5414,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -5385,7 +5469,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -5429,15 +5513,14 @@ static const OnigCodePoint CR_Assigned[] = { 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, @@ -5523,7 +5606,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -5561,7 +5644,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, + 0x2b97, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -5578,7 +5661,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4f, + 0x2de0, 0x2e52, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -5588,18 +5671,16 @@ static const OnigCodePoint CR_Assigned[] = { 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 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, @@ -5619,7 +5700,7 @@ static const OnigCodePoint CR_Assigned[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -5664,7 +5745,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, @@ -5724,8 +5805,12 @@ static const OnigCodePoint CR_Assigned[] = { 0x10cfa, 0x10d27, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, @@ -5734,10 +5819,9 @@ static const OnigCodePoint CR_Assigned[] = { 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11176, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1123e, @@ -5763,9 +5847,8 @@ static const OnigCodePoint CR_Assigned[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 0x11400, 0x1145b, + 0x1145d, 0x11461, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -5780,7 +5863,14 @@ static const OnigCodePoint CR_Assigned[] = { 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, @@ -5808,6 +5898,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, @@ -5831,9 +5922,11 @@ static const OnigCodePoint CR_Assigned[] = { 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, @@ -5931,17 +6024,15 @@ static const OnigCodePoint CR_Assigned[] = { 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, @@ -5950,24 +6041,28 @@ static const OnigCodePoint CR_Assigned[] = { 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, - 0x20000, 0x2a6d6, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, @@ -5977,7 +6072,7 @@ static const OnigCodePoint CR_Assigned[] = { /* 'C': Major Category */ static const OnigCodePoint CR_C[] = { - 668, + 679, 0x0000, 0x001f, 0x007f, 0x009f, 0x00ad, 0x00ad, @@ -6005,7 +6100,7 @@ static const OnigCodePoint CR_C[] = { 0x085f, 0x085f, 0x086b, 0x089f, 0x08b5, 0x08b5, - 0x08be, 0x08d2, + 0x08c8, 0x08d2, 0x08e2, 0x08e2, 0x0984, 0x0984, 0x098d, 0x098e, @@ -6060,7 +6155,7 @@ static const OnigCodePoint CR_C[] = { 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, - 0x0b4e, 0x0b55, + 0x0b4e, 0x0b54, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, @@ -6105,14 +6200,13 @@ static const OnigCodePoint CR_C[] = { 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0cff, - 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d50, 0x0d53, 0x0d64, 0x0d65, - 0x0d80, 0x0d81, + 0x0d80, 0x0d80, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, @@ -6199,7 +6293,7 @@ static const OnigCodePoint CR_C[] = { 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, - 0x1abf, 0x1aff, + 0x1ac1, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, @@ -6238,7 +6332,7 @@ static const OnigCodePoint CR_C[] = { 0x2427, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, - 0x2b96, 0x2b97, + 0x2b96, 0x2b96, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, @@ -6256,7 +6350,7 @@ static const OnigCodePoint CR_C[] = { 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, - 0x2e50, 0x2e7f, + 0x2e53, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, @@ -6266,18 +6360,16 @@ static const OnigCodePoint CR_C[] = { 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, - 0x4db6, 0x4dbf, - 0x9ff0, 0x9fff, + 0x9ffd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, 0xa7c0, 0xa7c1, - 0xa7c7, 0xa7f6, - 0xa82c, 0xa82f, + 0xa7cb, 0xa7f4, + 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c6, 0xa8cd, @@ -6297,7 +6389,7 @@ static const OnigCodePoint CR_C[] = { 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xab2f, - 0xab68, 0xab6f, + 0xab6c, 0xab6f, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, @@ -6341,7 +6433,7 @@ static const OnigCodePoint CR_C[] = { 0x10103, 0x10106, 0x10134, 0x10136, 0x1018f, 0x1018f, - 0x1019c, 0x1019f, + 0x1019d, 0x1019f, 0x101a1, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, @@ -6400,9 +6492,13 @@ static const OnigCodePoint CR_C[] = { 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, 0x10d3a, 0x10e5f, - 0x10e7f, 0x10eff, + 0x10e7f, 0x10e7f, + 0x10eaa, 0x10eaa, + 0x10eae, 0x10eaf, + 0x10eb2, 0x10eff, 0x10f28, 0x10f2f, - 0x10f5a, 0x10fdf, + 0x10f5a, 0x10faf, + 0x10fcc, 0x10fdf, 0x10ff7, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107e, @@ -6411,9 +6507,8 @@ static const OnigCodePoint CR_C[] = { 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, - 0x11147, 0x1114f, + 0x11148, 0x1114f, 0x11177, 0x1117f, - 0x111ce, 0x111cf, 0x111e0, 0x111e0, 0x111f5, 0x111ff, 0x11212, 0x11212, @@ -6440,9 +6535,8 @@ static const OnigCodePoint CR_C[] = { 0x11364, 0x11365, 0x1136d, 0x1136f, 0x11375, 0x113ff, - 0x1145a, 0x1145a, 0x1145c, 0x1145c, - 0x11460, 0x1147f, + 0x11462, 0x1147f, 0x114c8, 0x114cf, 0x114da, 0x1157f, 0x115b6, 0x115b7, @@ -6457,7 +6551,14 @@ static const OnigCodePoint CR_C[] = { 0x11740, 0x117ff, 0x1183c, 0x1189f, 0x118f3, 0x118fe, - 0x11900, 0x1199f, + 0x11907, 0x11908, + 0x1190a, 0x1190b, + 0x11914, 0x11914, + 0x11917, 0x11917, + 0x11936, 0x11936, + 0x11939, 0x1193a, + 0x11947, 0x1194f, + 0x1195a, 0x1199f, 0x119a8, 0x119a9, 0x119d8, 0x119d9, 0x119e5, 0x119ff, @@ -6484,7 +6585,8 @@ static const OnigCodePoint CR_C[] = { 0x11d92, 0x11d92, 0x11d99, 0x11d9f, 0x11daa, 0x11edf, - 0x11ef9, 0x11fbf, + 0x11ef9, 0x11faf, + 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, 0x1246f, 0x1246f, @@ -6507,9 +6609,11 @@ static const OnigCodePoint CR_C[] = { 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, 0x16fa0, 0x16fdf, - 0x16fe4, 0x16fff, + 0x16fe5, 0x16fef, + 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18af3, 0x1afff, + 0x18cd6, 0x18cff, + 0x18d09, 0x1afff, 0x1b11f, 0x1b14f, 0x1b153, 0x1b163, 0x1b168, 0x1b16f, @@ -6608,17 +6712,15 @@ static const OnigCodePoint CR_C[] = { 0x1f0c0, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0f6, 0x1f0ff, - 0x1f10d, 0x1f10f, - 0x1f16d, 0x1f16f, - 0x1f1ad, 0x1f1e5, + 0x1f1ae, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23c, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f25f, 0x1f266, 0x1f2ff, - 0x1f6d6, 0x1f6df, + 0x1f6d8, 0x1f6df, 0x1f6ed, 0x1f6ef, - 0x1f6fb, 0x1f6ff, + 0x1f6fd, 0x1f6ff, 0x1f774, 0x1f77f, 0x1f7d9, 0x1f7df, 0x1f7ec, 0x1f7ff, @@ -6626,25 +6728,29 @@ static const OnigCodePoint CR_C[] = { 0x1f848, 0x1f84f, 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, - 0x1f8ae, 0x1f8ff, - 0x1f90c, 0x1f90c, - 0x1f972, 0x1f972, - 0x1f977, 0x1f979, - 0x1f9a3, 0x1f9a4, - 0x1f9ab, 0x1f9ad, - 0x1f9cb, 0x1f9cc, + 0x1f8ae, 0x1f8af, + 0x1f8b2, 0x1f8ff, + 0x1f979, 0x1f979, + 0x1f9cc, 0x1f9cc, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, - 0x1fa74, 0x1fa77, + 0x1fa75, 0x1fa77, 0x1fa7b, 0x1fa7f, - 0x1fa83, 0x1fa8f, - 0x1fa96, 0x1ffff, - 0x2a6d7, 0x2a6ff, + 0x1fa87, 0x1fa8f, + 0x1faa9, 0x1faaf, + 0x1fab7, 0x1fabf, + 0x1fac3, 0x1facf, + 0x1fad7, 0x1faff, + 0x1fb93, 0x1fb93, + 0x1fbcb, 0x1fbef, + 0x1fbfa, 0x1ffff, + 0x2a6de, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, 0x2ebe1, 0x2f7ff, - 0x2fa1e, 0xe00ff, + 0x2fa1e, 0x2ffff, + 0x3134b, 0xe00ff, 0xe01f0, 0x10ffff, }; /* CR_C */ @@ -6678,7 +6784,7 @@ static const OnigCodePoint CR_Cf[] = { /* 'Cn': General Category */ static const OnigCodePoint CR_Cn[] = { - 666, + 677, 0x0378, 0x0379, 0x0380, 0x0383, 0x038b, 0x038b, @@ -6702,7 +6808,7 @@ static const OnigCodePoint CR_Cn[] = { 0x085f, 0x085f, 0x086b, 0x089f, 0x08b5, 0x08b5, - 0x08be, 0x08d2, + 0x08c8, 0x08d2, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, @@ -6756,7 +6862,7 @@ static const OnigCodePoint CR_Cn[] = { 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, - 0x0b4e, 0x0b55, + 0x0b4e, 0x0b54, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, @@ -6801,14 +6907,13 @@ static const OnigCodePoint CR_Cn[] = { 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0cff, - 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d50, 0x0d53, 0x0d64, 0x0d65, - 0x0d80, 0x0d81, + 0x0d80, 0x0d80, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, @@ -6895,7 +7000,7 @@ static const OnigCodePoint CR_Cn[] = { 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, - 0x1abf, 0x1aff, + 0x1ac1, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, @@ -6932,7 +7037,7 @@ static const OnigCodePoint CR_Cn[] = { 0x2427, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, - 0x2b96, 0x2b97, + 0x2b96, 0x2b96, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, @@ -6950,7 +7055,7 @@ static const OnigCodePoint CR_Cn[] = { 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, - 0x2e50, 0x2e7f, + 0x2e53, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, @@ -6960,18 +7065,16 @@ static const OnigCodePoint CR_Cn[] = { 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, - 0x4db6, 0x4dbf, - 0x9ff0, 0x9fff, + 0x9ffd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, 0xa7c0, 0xa7c1, - 0xa7c7, 0xa7f6, - 0xa82c, 0xa82f, + 0xa7cb, 0xa7f4, + 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c6, 0xa8cd, @@ -6991,7 +7094,7 @@ static const OnigCodePoint CR_Cn[] = { 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xab2f, - 0xab68, 0xab6f, + 0xab6c, 0xab6f, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, @@ -7036,7 +7139,7 @@ static const OnigCodePoint CR_Cn[] = { 0x10103, 0x10106, 0x10134, 0x10136, 0x1018f, 0x1018f, - 0x1019c, 0x1019f, + 0x1019d, 0x1019f, 0x101a1, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, @@ -7095,9 +7198,13 @@ static const OnigCodePoint CR_Cn[] = { 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, 0x10d3a, 0x10e5f, - 0x10e7f, 0x10eff, + 0x10e7f, 0x10e7f, + 0x10eaa, 0x10eaa, + 0x10eae, 0x10eaf, + 0x10eb2, 0x10eff, 0x10f28, 0x10f2f, - 0x10f5a, 0x10fdf, + 0x10f5a, 0x10faf, + 0x10fcc, 0x10fdf, 0x10ff7, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107e, @@ -7106,9 +7213,8 @@ static const OnigCodePoint CR_Cn[] = { 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, - 0x11147, 0x1114f, + 0x11148, 0x1114f, 0x11177, 0x1117f, - 0x111ce, 0x111cf, 0x111e0, 0x111e0, 0x111f5, 0x111ff, 0x11212, 0x11212, @@ -7135,9 +7241,8 @@ static const OnigCodePoint CR_Cn[] = { 0x11364, 0x11365, 0x1136d, 0x1136f, 0x11375, 0x113ff, - 0x1145a, 0x1145a, 0x1145c, 0x1145c, - 0x11460, 0x1147f, + 0x11462, 0x1147f, 0x114c8, 0x114cf, 0x114da, 0x1157f, 0x115b6, 0x115b7, @@ -7152,7 +7257,14 @@ static const OnigCodePoint CR_Cn[] = { 0x11740, 0x117ff, 0x1183c, 0x1189f, 0x118f3, 0x118fe, - 0x11900, 0x1199f, + 0x11907, 0x11908, + 0x1190a, 0x1190b, + 0x11914, 0x11914, + 0x11917, 0x11917, + 0x11936, 0x11936, + 0x11939, 0x1193a, + 0x11947, 0x1194f, + 0x1195a, 0x1199f, 0x119a8, 0x119a9, 0x119d8, 0x119d9, 0x119e5, 0x119ff, @@ -7179,7 +7291,8 @@ static const OnigCodePoint CR_Cn[] = { 0x11d92, 0x11d92, 0x11d99, 0x11d9f, 0x11daa, 0x11edf, - 0x11ef9, 0x11fbf, + 0x11ef9, 0x11faf, + 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, 0x1246f, 0x1246f, @@ -7203,9 +7316,11 @@ static const OnigCodePoint CR_Cn[] = { 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, 0x16fa0, 0x16fdf, - 0x16fe4, 0x16fff, + 0x16fe5, 0x16fef, + 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18af3, 0x1afff, + 0x18cd6, 0x18cff, + 0x18d09, 0x1afff, 0x1b11f, 0x1b14f, 0x1b153, 0x1b163, 0x1b168, 0x1b16f, @@ -7303,17 +7418,15 @@ static const OnigCodePoint CR_Cn[] = { 0x1f0c0, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0f6, 0x1f0ff, - 0x1f10d, 0x1f10f, - 0x1f16d, 0x1f16f, - 0x1f1ad, 0x1f1e5, + 0x1f1ae, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23c, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f25f, 0x1f266, 0x1f2ff, - 0x1f6d6, 0x1f6df, + 0x1f6d8, 0x1f6df, 0x1f6ed, 0x1f6ef, - 0x1f6fb, 0x1f6ff, + 0x1f6fd, 0x1f6ff, 0x1f774, 0x1f77f, 0x1f7d9, 0x1f7df, 0x1f7ec, 0x1f7ff, @@ -7321,25 +7434,29 @@ static const OnigCodePoint CR_Cn[] = { 0x1f848, 0x1f84f, 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, - 0x1f8ae, 0x1f8ff, - 0x1f90c, 0x1f90c, - 0x1f972, 0x1f972, - 0x1f977, 0x1f979, - 0x1f9a3, 0x1f9a4, - 0x1f9ab, 0x1f9ad, - 0x1f9cb, 0x1f9cc, + 0x1f8ae, 0x1f8af, + 0x1f8b2, 0x1f8ff, + 0x1f979, 0x1f979, + 0x1f9cc, 0x1f9cc, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, - 0x1fa74, 0x1fa77, + 0x1fa75, 0x1fa77, 0x1fa7b, 0x1fa7f, - 0x1fa83, 0x1fa8f, - 0x1fa96, 0x1ffff, - 0x2a6d7, 0x2a6ff, + 0x1fa87, 0x1fa8f, + 0x1faa9, 0x1faaf, + 0x1fab7, 0x1fabf, + 0x1fac3, 0x1facf, + 0x1fad7, 0x1faff, + 0x1fb93, 0x1fb93, + 0x1fbcb, 0x1fbef, + 0x1fbfa, 0x1ffff, + 0x2a6de, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, 0x2ebe1, 0x2f7ff, - 0x2fa1e, 0xe0000, + 0x2fa1e, 0x2ffff, + 0x3134b, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xe00ff, 0xe01f0, 0xeffff, @@ -7363,7 +7480,7 @@ static const OnigCodePoint CR_Cs[] = { /* 'L': Major Category */ static const OnigCodePoint CR_L[] = { - 609, + 622, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -7414,7 +7531,7 @@ static const OnigCodePoint CR_L[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, @@ -7490,7 +7607,7 @@ static const OnigCodePoint CR_L[] = { 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, - 0x0d05, 0x0d0c, + 0x0d04, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, @@ -7661,10 +7778,10 @@ static const OnigCodePoint CR_L[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -7676,8 +7793,8 @@ static const OnigCodePoint CR_L[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa801, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, @@ -7714,7 +7831,7 @@ static const OnigCodePoint CR_L[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -7798,15 +7915,19 @@ static const OnigCodePoint CR_L[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10e80, 0x10ea9, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11144, 0x11144, + 0x11147, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11183, 0x111b2, @@ -7832,7 +7953,7 @@ static const OnigCodePoint CR_L[] = { 0x1135d, 0x11361, 0x11400, 0x11434, 0x11447, 0x1144a, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114af, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -7845,7 +7966,13 @@ static const OnigCodePoint CR_L[] = { 0x11700, 0x1171a, 0x11800, 0x1182b, 0x118a0, 0x118df, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192f, + 0x1193f, 0x1193f, + 0x11941, 0x11941, 0x119a0, 0x119a7, 0x119aa, 0x119d0, 0x119e1, 0x119e1, @@ -7870,6 +7997,7 @@ static const OnigCodePoint CR_L[] = { 0x11d6a, 0x11d89, 0x11d98, 0x11d98, 0x11ee0, 0x11ef2, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12480, 0x12543, 0x13000, 0x1342e, @@ -7888,7 +8016,8 @@ static const OnigCodePoint CR_L[] = { 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -7967,17 +8096,18 @@ static const OnigCodePoint CR_L[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_L */ /* 'LC': General Category */ static const OnigCodePoint CR_LC[] = { - 131, + 132, 0x0041, 0x005a, 0x0061, 0x007a, 0x00b5, 0x00b5, @@ -8062,10 +8192,11 @@ static const OnigCodePoint CR_LC[] = { 0xa771, 0xa787, 0xa78b, 0xa78e, 0xa790, 0xa7bf, - 0xa7c2, 0xa7c6, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa7f6, 0xa7fa, 0xa7fa, 0xab30, 0xab5a, - 0xab60, 0xab67, + 0xab60, 0xab68, 0xab70, 0xabbf, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -8113,7 +8244,7 @@ static const OnigCodePoint CR_LC[] = { /* 'Ll': General Category */ static const OnigCodePoint CR_Ll[] = { - 642, + 645, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -8715,9 +8846,12 @@ static const OnigCodePoint CR_Ll[] = { 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, 0xa7c3, 0xa7c3, + 0xa7c8, 0xa7c8, + 0xa7ca, 0xa7ca, + 0xa7f6, 0xa7f6, 0xa7fa, 0xa7fa, 0xab30, 0xab5a, - 0xab60, 0xab67, + 0xab60, 0xab68, 0xab70, 0xabbf, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -8760,7 +8894,7 @@ static const OnigCodePoint CR_Ll[] = { /* 'Lm': General Category */ static const OnigCodePoint CR_Lm[] = { - 60, + 61, 0x02b0, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, @@ -8813,6 +8947,7 @@ static const OnigCodePoint CR_Lm[] = { 0xaadd, 0xaadd, 0xaaf3, 0xaaf4, 0xab5c, 0xab5f, + 0xab69, 0xab69, 0xff70, 0xff70, 0xff9e, 0xff9f, 0x16b40, 0x16b43, @@ -8825,7 +8960,7 @@ static const OnigCodePoint CR_Lm[] = { /* 'Lo': General Category */ static const OnigCodePoint CR_Lo[] = { - 476, + 489, 0x00aa, 0x00aa, 0x00ba, 0x00ba, 0x01bb, 0x01bb, @@ -8850,7 +8985,7 @@ static const OnigCodePoint CR_Lo[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, @@ -8926,7 +9061,7 @@ static const OnigCodePoint CR_Lo[] = { 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, - 0x0d05, 0x0d0c, + 0x0d04, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, @@ -9039,10 +9174,10 @@ static const OnigCodePoint CR_Lo[] = { 0x30ff, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa014, 0xa016, 0xa48c, 0xa4d0, 0xa4f7, @@ -9166,15 +9301,19 @@ static const OnigCodePoint CR_Lo[] = { 0x10b80, 0x10b91, 0x10c00, 0x10c48, 0x10d00, 0x10d23, + 0x10e80, 0x10ea9, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11144, 0x11144, + 0x11147, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11183, 0x111b2, @@ -9200,7 +9339,7 @@ static const OnigCodePoint CR_Lo[] = { 0x1135d, 0x11361, 0x11400, 0x11434, 0x11447, 0x1144a, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114af, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -9212,7 +9351,13 @@ static const OnigCodePoint CR_Lo[] = { 0x116b8, 0x116b8, 0x11700, 0x1171a, 0x11800, 0x1182b, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192f, + 0x1193f, 0x1193f, + 0x11941, 0x11941, 0x119a0, 0x119a7, 0x119aa, 0x119d0, 0x119e1, 0x119e1, @@ -9237,6 +9382,7 @@ static const OnigCodePoint CR_Lo[] = { 0x11d6a, 0x11d89, 0x11d98, 0x11d98, 0x11ee0, 0x11ef2, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12480, 0x12543, 0x13000, 0x1342e, @@ -9250,7 +9396,8 @@ static const OnigCodePoint CR_Lo[] = { 0x16f00, 0x16f4a, 0x16f50, 0x16f50, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -9296,12 +9443,13 @@ static const OnigCodePoint CR_Lo[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Lo */ /* 'Lt': General Category */ @@ -9321,7 +9469,7 @@ static const OnigCodePoint CR_Lt[] = { /* 'Lu': General Category */ static const OnigCodePoint CR_Lu[] = { - 636, + 638, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -9919,7 +10067,9 @@ static const OnigCodePoint CR_Lu[] = { 0xa7bc, 0xa7bc, 0xa7be, 0xa7be, 0xa7c2, 0xa7c2, - 0xa7c4, 0xa7c6, + 0xa7c4, 0xa7c7, + 0xa7c9, 0xa7c9, + 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, 0x104b0, 0x104d3, @@ -9962,7 +10112,7 @@ static const OnigCodePoint CR_Lu[] = { /* 'M': Major Category */ static const OnigCodePoint CR_M[] = { - 280, + 290, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, @@ -10021,7 +10171,7 @@ static const OnigCodePoint CR_M[] = { 0x0b3e, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bbe, 0x0bc2, @@ -10048,7 +10198,7 @@ static const OnigCodePoint CR_M[] = { 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d62, 0x0d63, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, @@ -10095,7 +10245,7 @@ static const OnigCodePoint CR_M[] = { 0x1a55, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a7f, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b04, 0x1b34, 0x1b44, 0x1b6b, 0x1b73, @@ -10124,6 +10274,7 @@ static const OnigCodePoint CR_M[] = { 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa823, 0xa827, + 0xa82c, 0xa82c, 0xa880, 0xa881, 0xa8b4, 0xa8c5, 0xa8e0, 0xa8f1, @@ -10159,6 +10310,7 @@ static const OnigCodePoint CR_M[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x10f46, 0x10f50, 0x11000, 0x11002, 0x11038, 0x11046, @@ -10171,6 +10323,7 @@ static const OnigCodePoint CR_M[] = { 0x11180, 0x11182, 0x111b3, 0x111c0, 0x111c9, 0x111cc, + 0x111ce, 0x111cf, 0x1122c, 0x11237, 0x1123e, 0x1123e, 0x112df, 0x112ea, @@ -10193,6 +10346,11 @@ static const OnigCodePoint CR_M[] = { 0x116ab, 0x116b7, 0x1171d, 0x1172b, 0x1182c, 0x1183a, + 0x11930, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x1193e, + 0x11940, 0x11940, + 0x11942, 0x11943, 0x119d1, 0x119d7, 0x119da, 0x119e0, 0x119e4, 0x119e4, @@ -10220,6 +10378,8 @@ static const OnigCodePoint CR_M[] = { 0x16f4f, 0x16f4f, 0x16f51, 0x16f87, 0x16f8f, 0x16f92, + 0x16fe4, 0x16fe4, + 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, @@ -10247,7 +10407,7 @@ static const OnigCodePoint CR_M[] = { /* 'Mc': General Category */ static const OnigCodePoint CR_Mc[] = { - 168, + 175, 0x0903, 0x0903, 0x093b, 0x093b, 0x093e, 0x0940, @@ -10367,6 +10527,7 @@ static const OnigCodePoint CR_Mc[] = { 0x11182, 0x11182, 0x111b3, 0x111b5, 0x111bf, 0x111c0, + 0x111ce, 0x111ce, 0x1122c, 0x1122e, 0x11232, 0x11233, 0x11235, 0x11235, @@ -10398,6 +10559,11 @@ static const OnigCodePoint CR_Mc[] = { 0x11726, 0x11726, 0x1182c, 0x1182e, 0x11838, 0x11838, + 0x11930, 0x11935, + 0x11937, 0x11938, + 0x1193d, 0x1193d, + 0x11940, 0x11940, + 0x11942, 0x11942, 0x119d1, 0x119d3, 0x119dc, 0x119df, 0x119e4, 0x119e4, @@ -10414,6 +10580,7 @@ static const OnigCodePoint CR_Mc[] = { 0x11d96, 0x11d96, 0x11ef5, 0x11ef6, 0x16f51, 0x16f87, + 0x16ff0, 0x16ff1, 0x1d165, 0x1d166, 0x1d16d, 0x1d172, }; /* CR_Mc */ @@ -10430,7 +10597,7 @@ static const OnigCodePoint CR_Me[] = { /* 'Mn': General Category */ static const OnigCodePoint CR_Mn[] = { - 318, + 327, 0x0300, 0x036f, 0x0483, 0x0487, 0x0591, 0x05bd, @@ -10489,7 +10656,7 @@ static const OnigCodePoint CR_Mn[] = { 0x0b3f, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, - 0x0b56, 0x0b56, + 0x0b55, 0x0b56, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bc0, 0x0bc0, @@ -10512,6 +10679,7 @@ static const OnigCodePoint CR_Mn[] = { 0x0d41, 0x0d44, 0x0d4d, 0x0d4d, 0x0d62, 0x0d63, + 0x0d81, 0x0d81, 0x0dca, 0x0dca, 0x0dd2, 0x0dd4, 0x0dd6, 0x0dd6, @@ -10569,6 +10737,7 @@ static const OnigCodePoint CR_Mn[] = { 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, 0x1ab0, 0x1abd, + 0x1abf, 0x1ac0, 0x1b00, 0x1b03, 0x1b34, 0x1b34, 0x1b36, 0x1b3a, @@ -10609,6 +10778,7 @@ static const OnigCodePoint CR_Mn[] = { 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c5, 0xa8e0, 0xa8f1, 0xa8ff, 0xa8ff, @@ -10648,6 +10818,7 @@ static const OnigCodePoint CR_Mn[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x10f46, 0x10f50, 0x11001, 0x11001, 0x11038, 0x11046, @@ -10661,6 +10832,7 @@ static const OnigCodePoint CR_Mn[] = { 0x11180, 0x11181, 0x111b6, 0x111be, 0x111c9, 0x111cc, + 0x111cf, 0x111cf, 0x1122f, 0x11231, 0x11234, 0x11234, 0x11236, 0x11237, @@ -10696,6 +10868,9 @@ static const OnigCodePoint CR_Mn[] = { 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, + 0x1193b, 0x1193c, + 0x1193e, 0x1193e, + 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, 0x119e0, 0x119e0, @@ -10727,6 +10902,7 @@ static const OnigCodePoint CR_Mn[] = { 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f92, + 0x16fe4, 0x16fe4, 0x1bc9d, 0x1bc9e, 0x1d167, 0x1d169, 0x1d17b, 0x1d182, @@ -10753,7 +10929,7 @@ static const OnigCodePoint CR_Mn[] = { /* 'N': Major Category */ static const OnigCodePoint CR_N[] = { - 130, + 133, 0x0030, 0x0039, 0x00b2, 0x00b3, 0x00b9, 0x00b9, @@ -10850,6 +11026,7 @@ static const OnigCodePoint CR_N[] = { 0x10e60, 0x10e7e, 0x10f1d, 0x10f26, 0x10f51, 0x10f54, + 0x10fc5, 0x10fcb, 0x11052, 0x1106f, 0x110f0, 0x110f9, 0x11136, 0x1113f, @@ -10862,6 +11039,7 @@ static const OnigCodePoint CR_N[] = { 0x116c0, 0x116c9, 0x11730, 0x1173b, 0x118e0, 0x118f2, + 0x11950, 0x11959, 0x11c50, 0x11c6c, 0x11d50, 0x11d59, 0x11da0, 0x11da9, @@ -10884,6 +11062,7 @@ static const OnigCodePoint CR_N[] = { 0x1ed01, 0x1ed2d, 0x1ed2f, 0x1ed3d, 0x1f100, 0x1f10c, + 0x1fbf0, 0x1fbf9, }; /* CR_N */ /* 'Nd': General Category */ @@ -10908,7 +11087,7 @@ static const OnigCodePoint CR_Nl[] = { /* 'No': General Category */ static const OnigCodePoint CR_No[] = { - 70, + 71, 0x00b2, 0x00b3, 0x00b9, 0x00b9, 0x00bc, 0x00be, @@ -10962,6 +11141,7 @@ static const OnigCodePoint CR_No[] = { 0x10e60, 0x10e7e, 0x10f1d, 0x10f26, 0x10f51, 0x10f54, + 0x10fc5, 0x10fcb, 0x11052, 0x11065, 0x111e1, 0x111f4, 0x1173a, 0x1173b, @@ -10997,7 +11177,7 @@ static const OnigCodePoint CR_Pc[] = { /* 'Pd': General Category */ static const OnigCodePoint CR_Pd[] = { - 17, + 18, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, @@ -11015,6 +11195,7 @@ static const OnigCodePoint CR_Pd[] = { 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, + 0x10ead, 0x10ead, }; /* CR_Pd */ /* 'Pe': General Category */ @@ -11127,7 +11308,7 @@ static const OnigCodePoint CR_Pi[] = { /* 'Po': General Category */ static const OnigCodePoint CR_Po[] = { - 179, + 181, 0x0021, 0x0023, 0x0025, 0x0027, 0x002a, 0x002a, @@ -11216,6 +11397,7 @@ static const OnigCodePoint CR_Po[] = { 0x2e3c, 0x2e3f, 0x2e41, 0x2e41, 0x2e43, 0x2e4f, + 0x2e52, 0x2e52, 0x3001, 0x3003, 0x303d, 0x303d, 0x30fb, 0x30fb, @@ -11281,7 +11463,7 @@ static const OnigCodePoint CR_Po[] = { 0x11238, 0x1123d, 0x112a9, 0x112a9, 0x1144b, 0x1144f, - 0x1145b, 0x1145b, + 0x1145a, 0x1145b, 0x1145d, 0x1145d, 0x114c6, 0x114c6, 0x115c1, 0x115d7, @@ -11289,6 +11471,7 @@ static const OnigCodePoint CR_Po[] = { 0x11660, 0x1166c, 0x1173c, 0x1173e, 0x1183b, 0x1183b, + 0x11944, 0x11946, 0x119e2, 0x119e2, 0x11a3f, 0x11a46, 0x11a9a, 0x11a9c, @@ -11391,7 +11574,7 @@ static const OnigCodePoint CR_Ps[] = { /* 'S': Major Category */ static const OnigCodePoint CR_S[] = { - 226, + 229, 0x0024, 0x0024, 0x002b, 0x002b, 0x003c, 0x003e, @@ -11492,8 +11675,9 @@ static const OnigCodePoint CR_S[] = { 0x29dc, 0x29fb, 0x29fe, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bff, + 0x2b97, 0x2bff, 0x2ce5, 0x2cea, + 0x2e50, 0x2e51, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -11522,6 +11706,7 @@ static const OnigCodePoint CR_S[] = { 0xa836, 0xa839, 0xaa77, 0xaa79, 0xab5b, 0xab5b, + 0xab6a, 0xab6b, 0xfb29, 0xfb29, 0xfbb2, 0xfbc1, 0xfdfc, 0xfdfd, @@ -11541,7 +11726,7 @@ static const OnigCodePoint CR_S[] = { 0x10137, 0x1013f, 0x10179, 0x10189, 0x1018c, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fc, 0x10877, 0x10878, @@ -11588,16 +11773,15 @@ static const OnigCodePoint CR_S[] = { 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, - 0x1f110, 0x1f16c, - 0x1f170, 0x1f1ac, + 0x1f10d, 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, @@ -11606,18 +11790,20 @@ static const OnigCodePoint CR_S[] = { 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, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, }; /* CR_S */ /* 'Sc': General Category */ @@ -11648,7 +11834,7 @@ static const OnigCodePoint CR_Sc[] = { /* 'Sk': General Category */ static const OnigCodePoint CR_Sk[] = { - 29, + 30, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, @@ -11673,6 +11859,7 @@ static const OnigCodePoint CR_Sk[] = { 0xa720, 0xa721, 0xa789, 0xa78a, 0xab5b, 0xab5b, + 0xab6a, 0xab6b, 0xfbb2, 0xfbc1, 0xff3e, 0xff3e, 0xff40, 0xff40, @@ -11751,7 +11938,7 @@ static const OnigCodePoint CR_Sm[] = { /* 'So': General Category */ static const OnigCodePoint CR_So[] = { - 180, + 182, 0x00a6, 0x00a6, 0x00a9, 0x00a9, 0x00ae, 0x00ae, @@ -11832,8 +12019,9 @@ static const OnigCodePoint CR_So[] = { 0x2b45, 0x2b46, 0x2b4d, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bff, + 0x2b97, 0x2bff, 0x2ce5, 0x2cea, + 0x2e50, 0x2e51, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -11866,7 +12054,7 @@ static const OnigCodePoint CR_So[] = { 0x10137, 0x1013f, 0x10179, 0x10189, 0x1018c, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fc, 0x10877, 0x10878, @@ -11901,17 +12089,16 @@ static const OnigCodePoint CR_So[] = { 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, - 0x1f110, 0x1f16c, - 0x1f170, 0x1f1ac, + 0x1f10d, 0x1f1ad, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f260, 0x1f265, 0x1f300, 0x1f3fa, - 0x1f400, 0x1f6d5, + 0x1f400, 0x1f6d7, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6fa, + 0x1f6f0, 0x1f6fc, 0x1f700, 0x1f773, 0x1f780, 0x1f7d8, 0x1f7e0, 0x1f7eb, @@ -11920,18 +12107,20 @@ static const OnigCodePoint CR_So[] = { 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, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, }; /* CR_So */ /* 'Z': Major Category */ @@ -12125,7 +12314,7 @@ static const OnigCodePoint CR_Math[] = { /* 'Cased': Derived Property */ static const OnigCodePoint CR_Cased[] = { - 140, + 141, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -12216,10 +12405,11 @@ static const OnigCodePoint CR_Cased[] = { 0xa722, 0xa787, 0xa78b, 0xa78e, 0xa790, 0xa7bf, - 0xa7c2, 0xa7c6, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa7f6, 0xa7f8, 0xa7fa, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab68, 0xab70, 0xabbf, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -12270,7 +12460,7 @@ static const OnigCodePoint CR_Cased[] = { /* 'Case_Ignorable': Derived Property */ static const OnigCodePoint CR_Case_Ignorable[] = { - 401, + 410, 0x0027, 0x0027, 0x002e, 0x002e, 0x003a, 0x003a, @@ -12288,6 +12478,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x0387, 0x0387, 0x0483, 0x0489, 0x0559, 0x0559, + 0x055f, 0x055f, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, @@ -12346,7 +12537,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x0b3f, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, - 0x0b56, 0x0b56, + 0x0b55, 0x0b56, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bc0, 0x0bc0, @@ -12369,6 +12560,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x0d41, 0x0d44, 0x0d4d, 0x0d4d, 0x0d62, 0x0d63, + 0x0d81, 0x0d81, 0x0dca, 0x0dca, 0x0dd2, 0x0dd4, 0x0dd6, 0x0dd6, @@ -12430,7 +12622,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, 0x1aa7, 0x1aa7, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b03, 0x1b34, 0x1b34, 0x1b36, 0x1b3a, @@ -12503,6 +12695,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c5, 0xa8e0, 0xa8f1, 0xa8ff, 0xa8ff, @@ -12531,6 +12724,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0xaaf3, 0xaaf4, 0xaaf6, 0xaaf6, 0xab5b, 0xab5f, + 0xab69, 0xab6b, 0xabe5, 0xabe5, 0xabe8, 0xabe8, 0xabed, 0xabed, @@ -12561,6 +12755,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x10f46, 0x10f50, 0x11001, 0x11001, 0x11038, 0x11046, @@ -12576,6 +12771,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x11180, 0x11181, 0x111b6, 0x111be, 0x111c9, 0x111cc, + 0x111cf, 0x111cf, 0x1122f, 0x11231, 0x11234, 0x11234, 0x11236, 0x11237, @@ -12611,6 +12807,9 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, + 0x1193b, 0x1193c, + 0x1193e, 0x1193e, + 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, 0x119e0, 0x119e0, @@ -12645,7 +12844,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x16f4f, 0x16f4f, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, - 0x16fe3, 0x16fe3, + 0x16fe3, 0x16fe4, 0x1bc9d, 0x1bc9e, 0x1bca0, 0x1bca3, 0x1d167, 0x1d169, @@ -12676,7 +12875,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { /* 'Changes_When_Lowercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Lowercased[] = { - 599, + 601, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -13268,7 +13467,9 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { 0xa7bc, 0xa7bc, 0xa7be, 0xa7be, 0xa7c2, 0xa7c2, - 0xa7c4, 0xa7c6, + 0xa7c4, 0xa7c7, + 0xa7c9, 0xa7c9, + 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, 0x104b0, 0x104d3, @@ -13280,7 +13481,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { /* 'Changes_When_Uppercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Uppercased[] = { - 616, + 619, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -13886,6 +14087,9 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, 0xa7c3, 0xa7c3, + 0xa7c8, 0xa7c8, + 0xa7ca, 0xa7ca, + 0xa7f6, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, 0xfb00, 0xfb06, @@ -13901,7 +14105,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { /* 'Changes_When_Titlecased': Derived Property */ static const OnigCodePoint CR_Changes_When_Titlecased[] = { - 615, + 618, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -14506,6 +14710,9 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, 0xa7c3, 0xa7c3, + 0xa7c8, 0xa7c8, + 0xa7ca, 0xa7ca, + 0xa7f6, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, 0xfb00, 0xfb06, @@ -14521,7 +14728,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { /* 'Changes_When_Casefolded': Derived Property */ static const OnigCodePoint CR_Changes_When_Casefolded[] = { - 612, + 614, 0x0041, 0x005a, 0x00b5, 0x00b5, 0x00c0, 0x00d6, @@ -15123,7 +15330,9 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = { 0xa7bc, 0xa7bc, 0xa7be, 0xa7be, 0xa7c2, 0xa7c2, - 0xa7c4, 0xa7c6, + 0xa7c4, 0xa7c7, + 0xa7c9, 0xa7c9, + 0xa7f5, 0xa7f5, 0xab70, 0xabbf, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -15138,7 +15347,7 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = { /* 'Changes_When_Casemapped': Derived Property */ static const OnigCodePoint CR_Changes_When_Casemapped[] = { - 123, + 124, 0x0041, 0x005a, 0x0061, 0x007a, 0x00b5, 0x00b5, @@ -15247,7 +15456,8 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0xa790, 0xa794, 0xa796, 0xa7ae, 0xa7b0, 0xa7bf, - 0xa7c2, 0xa7c6, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, 0xfb00, 0xfb06, @@ -15266,7 +15476,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { /* 'ID_Start': Derived Property */ static const OnigCodePoint CR_ID_Start[] = { - 609, + 622, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -15317,7 +15527,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, @@ -15393,7 +15603,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, - 0x0d05, 0x0d0c, + 0x0d04, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, @@ -15562,10 +15772,10 @@ static const OnigCodePoint CR_ID_Start[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -15577,8 +15787,8 @@ static const OnigCodePoint CR_ID_Start[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa801, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, @@ -15615,7 +15825,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -15700,15 +15910,19 @@ static const OnigCodePoint CR_ID_Start[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10e80, 0x10ea9, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11144, 0x11144, + 0x11147, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11183, 0x111b2, @@ -15734,7 +15948,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x1135d, 0x11361, 0x11400, 0x11434, 0x11447, 0x1144a, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114af, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -15747,7 +15961,13 @@ static const OnigCodePoint CR_ID_Start[] = { 0x11700, 0x1171a, 0x11800, 0x1182b, 0x118a0, 0x118df, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192f, + 0x1193f, 0x1193f, + 0x11941, 0x11941, 0x119a0, 0x119a7, 0x119aa, 0x119d0, 0x119e1, 0x119e1, @@ -15772,6 +15992,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x11d6a, 0x11d89, 0x11d98, 0x11d98, 0x11ee0, 0x11ef2, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -15791,7 +16012,8 @@ static const OnigCodePoint CR_ID_Start[] = { 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -15870,17 +16092,18 @@ static const OnigCodePoint CR_ID_Start[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_ID_Start */ /* 'ID_Continue': Derived Property */ static const OnigCodePoint CR_ID_Continue[] = { - 713, + 730, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -15933,7 +16156,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x0840, 0x085b, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, @@ -15993,7 +16216,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, @@ -16039,8 +16262,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, @@ -16049,7 +16271,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x0d5f, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -16150,6 +16372,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1ab0, 0x1abd, + 0x1abf, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, @@ -16232,10 +16455,10 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -16246,8 +16469,9 @@ static const OnigCodePoint CR_ID_Continue[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa827, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa827, + 0xa82c, 0xa82c, 0xa840, 0xa873, 0xa880, 0xa8c5, 0xa8d0, 0xa8d9, @@ -16273,7 +16497,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, @@ -16372,9 +16596,13 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10e80, 0x10ea9, + 0x10eab, 0x10eac, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11046, 0x11066, 0x1106f, @@ -16383,12 +16611,12 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, - 0x11144, 0x11146, + 0x11144, 0x11147, 0x11150, 0x11173, 0x11176, 0x11176, 0x11180, 0x111c4, 0x111c9, 0x111cc, - 0x111d0, 0x111da, + 0x111ce, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x11237, @@ -16417,7 +16645,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11370, 0x11374, 0x11400, 0x1144a, 0x11450, 0x11459, - 0x1145e, 0x1145f, + 0x1145e, 0x11461, 0x11480, 0x114c5, 0x114c7, 0x114c7, 0x114d0, 0x114d9, @@ -16434,7 +16662,14 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11730, 0x11739, 0x11800, 0x1183a, 0x118a0, 0x118e9, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11943, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e1, @@ -16465,6 +16700,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef6, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -16485,9 +16721,11 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, - 0x16fe3, 0x16fe3, + 0x16fe3, 0x16fe4, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -16587,18 +16825,20 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0100, 0xe01ef, }; /* CR_ID_Continue */ /* 'XID_Start': Derived Property */ static const OnigCodePoint CR_XID_Start[] = { - 616, + 629, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -16649,7 +16889,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x0840, 0x0858, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, @@ -16725,7 +16965,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, - 0x0d05, 0x0d0c, + 0x0d04, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, @@ -16894,10 +17134,10 @@ static const OnigCodePoint CR_XID_Start[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -16909,8 +17149,8 @@ static const OnigCodePoint CR_XID_Start[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa801, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, @@ -16947,7 +17187,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -17039,15 +17279,19 @@ static const OnigCodePoint CR_XID_Start[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10e80, 0x10ea9, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11144, 0x11144, + 0x11147, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11183, 0x111b2, @@ -17073,7 +17317,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x1135d, 0x11361, 0x11400, 0x11434, 0x11447, 0x1144a, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114af, 0x114c4, 0x114c5, 0x114c7, 0x114c7, @@ -17086,7 +17330,13 @@ static const OnigCodePoint CR_XID_Start[] = { 0x11700, 0x1171a, 0x11800, 0x1182b, 0x118a0, 0x118df, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192f, + 0x1193f, 0x1193f, + 0x11941, 0x11941, 0x119a0, 0x119a7, 0x119aa, 0x119d0, 0x119e1, 0x119e1, @@ -17111,6 +17361,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x11d6a, 0x11d89, 0x11d98, 0x11d98, 0x11ee0, 0x11ef2, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -17130,7 +17381,8 @@ static const OnigCodePoint CR_XID_Start[] = { 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -17209,17 +17461,18 @@ static const OnigCodePoint CR_XID_Start[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_XID_Start */ /* 'XID_Continue': Derived Property */ static const OnigCodePoint CR_XID_Continue[] = { - 720, + 737, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -17272,7 +17525,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x0840, 0x085b, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, @@ -17332,7 +17585,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, @@ -17378,8 +17631,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, @@ -17388,7 +17640,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x0d5f, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -17489,6 +17741,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1ab0, 0x1abd, + 0x1abf, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, @@ -17572,10 +17825,10 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, 0x31f0, 0x31ff, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, @@ -17586,8 +17839,9 @@ static const OnigCodePoint CR_XID_Continue[] = { 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa827, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa827, + 0xa82c, 0xa82c, 0xa840, 0xa873, 0xa880, 0xa8c5, 0xa8d0, 0xa8d9, @@ -17613,7 +17867,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, - 0xab5c, 0xab67, + 0xab5c, 0xab69, 0xab70, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, @@ -17718,9 +17972,13 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10e80, 0x10ea9, + 0x10eab, 0x10eac, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, + 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11046, 0x11066, 0x1106f, @@ -17729,12 +17987,12 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, - 0x11144, 0x11146, + 0x11144, 0x11147, 0x11150, 0x11173, 0x11176, 0x11176, 0x11180, 0x111c4, 0x111c9, 0x111cc, - 0x111d0, 0x111da, + 0x111ce, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x11237, @@ -17763,7 +18021,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11370, 0x11374, 0x11400, 0x1144a, 0x11450, 0x11459, - 0x1145e, 0x1145f, + 0x1145e, 0x11461, 0x11480, 0x114c5, 0x114c7, 0x114c7, 0x114d0, 0x114d9, @@ -17780,7 +18038,14 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11730, 0x11739, 0x11800, 0x1183a, 0x118a0, 0x118e9, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11943, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e1, @@ -17811,6 +18076,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef6, + 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, @@ -17831,9 +18097,11 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, - 0x16fe3, 0x16fe3, + 0x16fe3, 0x16fe4, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -17933,12 +18201,14 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, - 0x20000, 0x2a6d6, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, 0xe0100, 0xe01ef, }; /* CR_XID_Continue */ @@ -17966,7 +18236,7 @@ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = { /* 'Grapheme_Extend': Derived Property */ static const OnigCodePoint CR_Grapheme_Extend[] = { - 335, + 344, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, @@ -18027,7 +18297,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x0b3e, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bbe, 0x0bbe, @@ -18056,6 +18326,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x0d4d, 0x0d4d, 0x0d57, 0x0d57, 0x0d62, 0x0d63, + 0x0d81, 0x0d81, 0x0dca, 0x0dca, 0x0dcf, 0x0dcf, 0x0dd2, 0x0dd4, @@ -18114,7 +18385,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x1a65, 0x1a6c, 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b03, 0x1b34, 0x1b3a, 0x1b3c, 0x1b3c, @@ -18153,6 +18424,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c5, 0xa8e0, 0xa8f1, 0xa8ff, 0xa8ff, @@ -18193,6 +18465,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x10f46, 0x10f50, 0x11001, 0x11001, 0x11038, 0x11046, @@ -18206,6 +18479,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x11180, 0x11181, 0x111b6, 0x111be, 0x111c9, 0x111cc, + 0x111cf, 0x111cf, 0x1122f, 0x11231, 0x11234, 0x11234, 0x11236, 0x11237, @@ -18246,6 +18520,10 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, + 0x11930, 0x11930, + 0x1193b, 0x1193c, + 0x1193e, 0x1193e, + 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, 0x119e0, 0x119e0, @@ -18277,6 +18555,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f92, + 0x16fe4, 0x16fe4, 0x1bc9d, 0x1bc9e, 0x1d165, 0x1d165, 0x1d167, 0x1d169, @@ -18306,7 +18585,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { /* 'Grapheme_Base': Derived Property */ static const OnigCodePoint CR_Grapheme_Base[] = { - 819, + 834, 0x0020, 0x007e, 0x00a0, 0x00ac, 0x00ae, 0x02ff, @@ -18350,7 +18629,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x0903, 0x0939, 0x093b, 0x093b, 0x093d, 0x0940, @@ -18456,8 +18735,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d02, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d02, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, @@ -18639,7 +18917,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, + 0x2b97, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cee, 0x2cf2, 0x2cf3, @@ -18657,7 +18935,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2e00, 0x2e4f, + 0x2e00, 0x2e52, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -18668,11 +18946,9 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x309b, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x4db5, - 0x4dc0, 0x9fef, + 0x3220, 0x9ffc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, @@ -18682,8 +18958,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0xa6a0, 0xa6ef, 0xa6f2, 0xa6f7, 0xa700, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa801, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa824, @@ -18725,7 +19001,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabe4, 0xabe6, 0xabe7, 0xabe9, 0xabec, @@ -18773,7 +19049,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fc, 0x10280, 0x1029c, @@ -18831,9 +19107,13 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x10cfa, 0x10d23, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10ead, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f45, 0x10f51, 0x10f59, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x11000, 0x11002, 0x11037, @@ -18847,12 +19127,12 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x110f0, 0x110f9, 0x11103, 0x11126, 0x1112c, 0x1112c, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11172, 0x11174, 0x11176, 0x11182, 0x111b5, 0x111bf, 0x111c8, - 0x111cd, 0x111cd, + 0x111cd, 0x111ce, 0x111d0, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, @@ -18885,10 +19165,9 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11400, 0x11437, 0x11440, 0x11441, 0x11445, 0x11445, - 0x11447, 0x11459, - 0x1145b, 0x1145b, + 0x11447, 0x1145b, 0x1145d, 0x1145d, - 0x1145f, 0x1145f, + 0x1145f, 0x11461, 0x11480, 0x114af, 0x114b1, 0x114b2, 0x114b9, 0x114b9, @@ -18922,7 +19201,17 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11838, 0x11838, 0x1183b, 0x1183b, 0x118a0, 0x118f2, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192f, + 0x11931, 0x11935, + 0x11937, 0x11938, + 0x1193d, 0x1193d, + 0x1193f, 0x11942, + 0x11944, 0x11946, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d3, 0x119dc, 0x119df, @@ -18960,6 +19249,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11da0, 0x11da9, 0x11ee0, 0x11ef2, 0x11ef5, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, @@ -18984,8 +19274,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x16f50, 0x16f87, 0x16f93, 0x16f9f, 0x16fe0, 0x16fe3, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -19089,17 +19381,15 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 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, @@ -19108,29 +19398,33 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 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, - 0x20000, 0x2a6d6, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Grapheme_Base */ /* 'Grapheme_Link': Derived Property */ static const OnigCodePoint CR_Grapheme_Link[] = { - 52, + 54, 0x094d, 0x094d, 0x09cd, 0x09cd, 0x0a4d, 0x0a4d, @@ -19155,6 +19449,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = { 0x1bf2, 0x1bf3, 0x2d7f, 0x2d7f, 0xa806, 0xa806, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c4, 0xa953, 0xa953, 0xa9c0, 0xa9c0, @@ -19176,6 +19471,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = { 0x116b6, 0x116b6, 0x1172b, 0x1172b, 0x11839, 0x11839, + 0x1193d, 0x1193e, 0x119e0, 0x119e0, 0x11a34, 0x11a34, 0x11a47, 0x11a47, @@ -19187,7 +19483,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = { /* 'Common': Script */ static const OnigCodePoint CR_Common[] = { - 172, + 173, 0x0000, 0x0040, 0x005b, 0x0060, 0x007b, 0x00a9, @@ -19202,7 +19498,6 @@ static const OnigCodePoint CR_Common[] = { 0x037e, 0x037e, 0x0385, 0x0385, 0x0387, 0x0387, - 0x0589, 0x0589, 0x0605, 0x0605, 0x060c, 0x060c, 0x061b, 0x061b, @@ -19241,8 +19536,8 @@ static const OnigCodePoint CR_Common[] = { 0x2460, 0x27ff, 0x2900, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bff, - 0x2e00, 0x2e4f, + 0x2b97, 0x2bff, + 0x2e00, 0x2e52, 0x2ff0, 0x2ffb, 0x3000, 0x3004, 0x3006, 0x3006, @@ -19265,6 +19560,7 @@ static const OnigCodePoint CR_Common[] = { 0xa92e, 0xa92e, 0xa9cf, 0xa9cf, 0xab5b, 0xab5b, + 0xab6a, 0xab6b, 0xfd3e, 0xfd3f, 0xfe10, 0xfe19, 0xfe30, 0xfe52, @@ -19282,7 +19578,7 @@ static const OnigCodePoint CR_Common[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1013f, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101d0, 0x101fc, 0x102e1, 0x102fb, 0x16fe2, 0x16fe3, @@ -19326,18 +19622,16 @@ static const OnigCodePoint CR_Common[] = { 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, - 0x1f100, 0x1f10c, - 0x1f110, 0x1f16c, - 0x1f170, 0x1f1ac, + 0x1f100, 0x1f1ad, 0x1f1e6, 0x1f1ff, 0x1f201, 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, @@ -19346,18 +19640,21 @@ static const OnigCodePoint CR_Common[] = { 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, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, 0xe0001, 0xe0001, 0xe0020, 0xe007f, }; /* CR_Common */ @@ -19389,11 +19686,11 @@ static const OnigCodePoint CR_Latin[] = { 0x2c60, 0x2c7f, 0xa722, 0xa787, 0xa78b, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa7ff, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa7ff, 0xab30, 0xab5a, 0xab5c, 0xab64, - 0xab66, 0xab67, + 0xab66, 0xab69, 0xfb00, 0xfb06, 0xff21, 0xff3a, 0xff41, 0xff5a, @@ -19455,10 +19752,9 @@ static const OnigCodePoint CR_Cyrillic[] = { /* 'Armenian': Script */ static const OnigCodePoint CR_Armenian[] = { - 5, + 4, 0x0531, 0x0556, - 0x0559, 0x0588, - 0x058a, 0x058a, + 0x0559, 0x058a, 0x058d, 0x058f, 0xfb13, 0xfb17, }; /* CR_Armenian */ @@ -19492,7 +19788,7 @@ static const OnigCodePoint CR_Arabic[] = { 0x06de, 0x06ff, 0x0750, 0x077f, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x08e1, 0x08e3, 0x08ff, 0xfb50, 0xfbc1, @@ -19635,7 +19931,7 @@ static const OnigCodePoint CR_Oriya[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -19701,9 +19997,8 @@ static const OnigCodePoint CR_Kannada[] = { /* 'Malayalam': Script */ static const OnigCodePoint CR_Malayalam[] = { - 8, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 7, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, @@ -19715,7 +20010,7 @@ static const OnigCodePoint CR_Malayalam[] = { /* 'Sinhala': Script */ static const OnigCodePoint CR_Sinhala[] = { 13, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -19922,12 +20217,12 @@ static const OnigCodePoint CR_Bopomofo[] = { 3, 0x02ea, 0x02eb, 0x3105, 0x312f, - 0x31a0, 0x31ba, + 0x31a0, 0x31bf, }; /* CR_Bopomofo */ /* 'Han': Script */ static const OnigCodePoint CR_Han[] = { - 17, + 19, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -19935,16 +20230,18 @@ static const OnigCodePoint CR_Han[] = { 0x3007, 0x3007, 0x3021, 0x3029, 0x3038, 0x303b, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xf900, 0xfa6d, 0xfa70, 0xfad9, - 0x20000, 0x2a6d6, + 0x16ff0, 0x16ff1, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Han */ /* 'Yi': Script */ @@ -19981,7 +20278,7 @@ static const OnigCodePoint CR_Inherited[] = { 0x064b, 0x0655, 0x0670, 0x0670, 0x0951, 0x0954, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce0, 0x1ce2, 0x1ce8, @@ -20146,7 +20443,7 @@ static const OnigCodePoint CR_Tifinagh[] = { /* 'Syloti_Nagri': Script */ static const OnigCodePoint CR_Syloti_Nagri[] = { 1, - 0xa800, 0xa82b, + 0xa800, 0xa82c, }; /* CR_Syloti_Nagri */ /* 'Old_Persian': Script */ @@ -20321,8 +20618,9 @@ static const OnigCodePoint CR_Samaritan[] = { /* 'Lisu': Script */ static const OnigCodePoint CR_Lisu[] = { - 1, + 2, 0xa4d0, 0xa4ff, + 0x11fb0, 0x11fb0, }; /* CR_Lisu */ /* 'Bamum': Script */ @@ -20414,7 +20712,7 @@ static const OnigCodePoint CR_Mandaic[] = { static const OnigCodePoint CR_Chakma[] = { 2, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, }; /* CR_Chakma */ /* 'Meroitic_Cursive': Script */ @@ -20441,9 +20739,8 @@ static const OnigCodePoint CR_Miao[] = { /* 'Sharada': Script */ static const OnigCodePoint CR_Sharada[] = { - 2, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 1, + 0x11180, 0x111df, }; /* CR_Sharada */ /* 'Sora_Sompeng': Script */ @@ -20712,10 +21009,9 @@ static const OnigCodePoint CR_Marchen[] = { /* 'Newa': Script */ static const OnigCodePoint CR_Newa[] = { - 3, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 2, + 0x11400, 0x1145b, + 0x1145d, 0x11461, }; /* CR_Newa */ /* 'Osage': Script */ @@ -20727,10 +21023,11 @@ static const OnigCodePoint CR_Osage[] = { /* 'Tangut': Script */ static const OnigCodePoint CR_Tangut[] = { - 3, + 4, 0x16fe0, 0x16fe0, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18aff, + 0x18d00, 0x18d08, }; /* CR_Tangut */ /* 'Masaram_Gondi': Script */ @@ -20842,6 +21139,40 @@ static const OnigCodePoint CR_Wancho[] = { 0x1e2ff, 0x1e2ff, }; /* CR_Wancho */ +/* 'Chorasmian': Script */ +static const OnigCodePoint CR_Chorasmian[] = { + 1, + 0x10fb0, 0x10fcb, +}; /* CR_Chorasmian */ + +/* 'Dives_Akuru': Script */ +static const OnigCodePoint CR_Dives_Akuru[] = { + 8, + 0x11900, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11946, + 0x11950, 0x11959, +}; /* CR_Dives_Akuru */ + +/* 'Khitan_Small_Script': Script */ +static const OnigCodePoint CR_Khitan_Small_Script[] = { + 2, + 0x16fe4, 0x16fe4, + 0x18b00, 0x18cd5, +}; /* CR_Khitan_Small_Script */ + +/* 'Yezidi': Script */ +static const OnigCodePoint CR_Yezidi[] = { + 3, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, +}; /* CR_Yezidi */ + /* 'White_Space': Binary Property */ #define CR_White_Space CR_Space @@ -20862,7 +21193,7 @@ static const OnigCodePoint CR_Join_Control[] = { /* 'Dash': Binary Property */ static const OnigCodePoint CR_Dash[] = { - 21, + 22, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, @@ -20884,6 +21215,7 @@ static const OnigCodePoint CR_Dash[] = { 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, + 0x10ead, 0x10ead, }; /* CR_Dash */ /* 'Hyphen': Binary Property */ @@ -20921,7 +21253,7 @@ static const OnigCodePoint CR_Quotation_Mark[] = { /* 'Terminal_Punctuation': Binary Property */ static const OnigCodePoint CR_Terminal_Punctuation[] = { - 102, + 104, 0x0021, 0x0021, 0x002c, 0x002c, 0x002e, 0x002e, @@ -21005,11 +21337,13 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0x11238, 0x1123c, 0x112a9, 0x112a9, 0x1144b, 0x1144d, - 0x1145b, 0x1145b, + 0x1145a, 0x1145b, 0x115c2, 0x115c5, 0x115c9, 0x115d7, 0x11641, 0x11642, 0x1173c, 0x1173e, + 0x11944, 0x11944, + 0x11946, 0x11946, 0x11a42, 0x11a43, 0x11a9b, 0x11a9c, 0x11aa1, 0x11aa2, @@ -21181,7 +21515,7 @@ static const OnigCodePoint CR_Hex_Digit[] = { /* 'Other_Alphabetic': Binary Property */ static const OnigCodePoint CR_Other_Alphabetic[] = { - 221, + 230, 0x0345, 0x0345, 0x05b0, 0x05bd, 0x05bf, 0x05bf, @@ -21259,7 +21593,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x0d4a, 0x0d4c, 0x0d57, 0x0d57, 0x0d62, 0x0d63, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, @@ -21297,6 +21631,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x1a17, 0x1a1b, 0x1a55, 0x1a5e, 0x1a61, 0x1a74, + 0x1abf, 0x1ac0, 0x1b00, 0x1b04, 0x1b35, 0x1b43, 0x1b80, 0x1b82, @@ -21338,6 +21673,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x11000, 0x11002, 0x11038, 0x11045, 0x11082, 0x11082, @@ -21347,6 +21683,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x11145, 0x11146, 0x11180, 0x11182, 0x111b3, 0x111bf, + 0x111ce, 0x111cf, 0x1122c, 0x11234, 0x11237, 0x11237, 0x1123e, 0x1123e, @@ -21368,6 +21705,11 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x116ab, 0x116b5, 0x1171d, 0x1172a, 0x1182c, 0x11838, + 0x11930, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x1193c, + 0x11940, 0x11940, + 0x11942, 0x11942, 0x119d1, 0x119d7, 0x119da, 0x119df, 0x119e4, 0x119e4, @@ -21393,6 +21735,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x16f4f, 0x16f4f, 0x16f51, 0x16f87, 0x16f8f, 0x16f92, + 0x16ff0, 0x16ff1, 0x1bc9e, 0x1bc9e, 0x1e000, 0x1e006, 0x1e008, 0x1e018, @@ -21407,28 +21750,31 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { /* 'Ideographic': Binary Property */ static const OnigCodePoint CR_Ideographic[] = { - 16, + 19, 0x3006, 0x3007, 0x3021, 0x3029, 0x3038, 0x303a, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xf900, 0xfa6d, 0xfa70, 0xfad9, + 0x16fe4, 0x16fe4, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b170, 0x1b2fb, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, + 0x30000, 0x3134a, }; /* CR_Ideographic */ /* 'Diacritic': Binary Property */ static const OnigCodePoint CR_Diacritic[] = { - 171, + 176, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, @@ -21471,6 +21817,7 @@ static const OnigCodePoint CR_Diacritic[] = { 0x0afd, 0x0aff, 0x0b3c, 0x0b3c, 0x0b4d, 0x0b4d, + 0x0b55, 0x0b55, 0x0bcd, 0x0bcd, 0x0c4d, 0x0c4d, 0x0cbc, 0x0cbc, @@ -21548,6 +21895,7 @@ static const OnigCodePoint CR_Diacritic[] = { 0xaabf, 0xaac2, 0xaaf6, 0xaaf6, 0xab5b, 0xab5f, + 0xab69, 0xab6b, 0xabec, 0xabed, 0xfb1e, 0xfb1e, 0xfe20, 0xfe2f, @@ -21579,6 +21927,8 @@ static const OnigCodePoint CR_Diacritic[] = { 0x116b6, 0x116b7, 0x1172b, 0x1172b, 0x11839, 0x1183a, + 0x1193d, 0x1193e, + 0x11943, 0x11943, 0x119e0, 0x119e0, 0x11a34, 0x11a34, 0x11a47, 0x11a47, @@ -21590,6 +21940,7 @@ static const OnigCodePoint CR_Diacritic[] = { 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16f8f, 0x16f9f, + 0x16ff0, 0x16ff1, 0x1d167, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, @@ -21604,11 +21955,12 @@ static const OnigCodePoint CR_Diacritic[] = { /* 'Extender': Binary Property */ static const OnigCodePoint CR_Extender[] = { - 31, + 32, 0x00b7, 0x00b7, 0x02d0, 0x02d1, 0x0640, 0x0640, 0x07fa, 0x07fa, + 0x0b55, 0x0b55, 0x0e46, 0x0e46, 0x0ec6, 0x0ec6, 0x180a, 0x180a, @@ -21698,7 +22050,7 @@ static const OnigCodePoint CR_Noncharacter_Code_Point[] = { /* 'Other_Grapheme_Extend': Binary Property */ static const OnigCodePoint CR_Other_Grapheme_Extend[] = { - 24, + 25, 0x09be, 0x09be, 0x09d7, 0x09d7, 0x0b3e, 0x0b3e, @@ -21720,6 +22072,7 @@ static const OnigCodePoint CR_Other_Grapheme_Extend[] = { 0x114b0, 0x114b0, 0x114bd, 0x114bd, 0x115af, 0x115af, + 0x11930, 0x11930, 0x1d165, 0x1d165, 0x1d16e, 0x1d172, 0xe0020, 0xe007f, @@ -21748,9 +22101,9 @@ static const OnigCodePoint CR_Radical[] = { /* 'Unified_Ideograph': Binary Property */ static const OnigCodePoint CR_Unified_Ideograph[] = { - 14, - 0x3400, 0x4db5, - 0x4e00, 0x9fef, + 15, + 0x3400, 0x4dbf, + 0x4e00, 0x9ffc, 0xfa0e, 0xfa0f, 0xfa11, 0xfa11, 0xfa13, 0xfa14, @@ -21758,11 +22111,12 @@ static const OnigCodePoint CR_Unified_Ideograph[] = { 0xfa21, 0xfa21, 0xfa23, 0xfa24, 0xfa27, 0xfa29, - 0x20000, 0x2a6d6, + 0x20000, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x30000, 0x3134a, }; /* CR_Unified_Ideograph */ /* 'Other_Default_Ignorable_Code_Point': Binary Property */ @@ -21862,7 +22216,7 @@ static const OnigCodePoint CR_Other_ID_Continue[] = { /* 'Sentence_Terminal': Binary Property */ static const OnigCodePoint CR_Sentence_Terminal[] = { - 74, + 76, 0x0021, 0x0021, 0x002e, 0x002e, 0x003f, 0x003f, @@ -21926,6 +22280,8 @@ static const OnigCodePoint CR_Sentence_Terminal[] = { 0x115c9, 0x115d7, 0x11641, 0x11642, 0x1173c, 0x1173e, + 0x11944, 0x11944, + 0x11946, 0x11946, 0x11a42, 0x11a43, 0x11a9b, 0x11a9c, 0x11c41, 0x11c42, @@ -22009,7 +22365,7 @@ static const OnigCodePoint CR_Regional_Indicator[] = { /* 'Emoji': Emoji */ static const OnigCodePoint CR_Emoji[] = { - 151, + 152, 0x0023, 0x0023, 0x002a, 0x002a, 0x0030, 0x0039, @@ -22056,6 +22412,7 @@ static const OnigCodePoint CR_Emoji[] = { 0x2699, 0x2699, 0x269b, 0x269c, 0x26a0, 0x26a1, + 0x26a7, 0x26a7, 0x26aa, 0x26ab, 0x26b0, 0x26b1, 0x26bd, 0x26be, @@ -22142,25 +22499,25 @@ static const OnigCodePoint CR_Emoji[] = { 0x1f5fa, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f6cb, 0x1f6d2, - 0x1f6d5, 0x1f6d5, + 0x1f6d5, 0x1f6d7, 0x1f6e0, 0x1f6e5, 0x1f6e9, 0x1f6e9, 0x1f6eb, 0x1f6ec, 0x1f6f0, 0x1f6f0, - 0x1f6f3, 0x1f6fa, + 0x1f6f3, 0x1f6fc, 0x1f7e0, 0x1f7eb, - 0x1f90d, 0x1f93a, + 0x1f90c, 0x1f93a, 0x1f93c, 0x1f945, - 0x1f947, 0x1f971, - 0x1f973, 0x1f976, - 0x1f97a, 0x1f9a2, - 0x1f9a5, 0x1f9aa, - 0x1f9ae, 0x1f9ca, + 0x1f947, 0x1f978, + 0x1f97a, 0x1f9cb, 0x1f9cd, 0x1f9ff, - 0x1fa70, 0x1fa73, + 0x1fa70, 0x1fa74, 0x1fa78, 0x1fa7a, - 0x1fa80, 0x1fa82, - 0x1fa90, 0x1fa95, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, }; /* CR_Emoji */ /* 'Emoji_Presentation': Emoji */ @@ -22231,22 +22588,22 @@ static const OnigCodePoint CR_Emoji_Presentation[] = { 0x1f680, 0x1f6c5, 0x1f6cc, 0x1f6cc, 0x1f6d0, 0x1f6d2, - 0x1f6d5, 0x1f6d5, + 0x1f6d5, 0x1f6d7, 0x1f6eb, 0x1f6ec, - 0x1f6f4, 0x1f6fa, + 0x1f6f4, 0x1f6fc, 0x1f7e0, 0x1f7eb, - 0x1f90d, 0x1f93a, + 0x1f90c, 0x1f93a, 0x1f93c, 0x1f945, - 0x1f947, 0x1f971, - 0x1f973, 0x1f976, - 0x1f97a, 0x1f9a2, - 0x1f9a5, 0x1f9aa, - 0x1f9ae, 0x1f9ca, + 0x1f947, 0x1f978, + 0x1f97a, 0x1f9cb, 0x1f9cd, 0x1f9ff, - 0x1fa70, 0x1fa73, + 0x1fa70, 0x1fa74, 0x1fa78, 0x1fa7a, - 0x1fa80, 0x1fa82, - 0x1fa90, 0x1fa95, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, }; /* CR_Emoji_Presentation */ /* 'Emoji_Modifier': Emoji */ @@ -22257,7 +22614,7 @@ static const OnigCodePoint CR_Emoji_Modifier[] = { /* 'Emoji_Modifier_Base': Emoji */ static const OnigCodePoint CR_Emoji_Modifier_Base[] = { - 36, + 38, 0x261d, 0x261d, 0x26f9, 0x26f9, 0x270a, 0x270d, @@ -22284,11 +22641,13 @@ static const OnigCodePoint CR_Emoji_Modifier_Base[] = { 0x1f6b4, 0x1f6b6, 0x1f6c0, 0x1f6c0, 0x1f6cc, 0x1f6cc, + 0x1f90c, 0x1f90c, 0x1f90f, 0x1f90f, 0x1f918, 0x1f91f, 0x1f926, 0x1f926, 0x1f930, 0x1f939, 0x1f93c, 0x1f93e, + 0x1f977, 0x1f977, 0x1f9b5, 0x1f9b6, 0x1f9b8, 0x1f9b9, 0x1f9bb, 0x1f9bb, @@ -22313,7 +22672,7 @@ static const OnigCodePoint CR_Emoji_Component[] = { /* 'Extended_Pictographic': Emoji */ static const OnigCodePoint CR_Extended_Pictographic[] = { - 77, + 78, 0x00a9, 0x00a9, 0x00ae, 0x00ae, 0x203c, 0x203c, @@ -22390,12 +22749,13 @@ static const OnigCodePoint CR_Extended_Pictographic[] = { 0x1f8ae, 0x1f8ff, 0x1f90c, 0x1f93a, 0x1f93c, 0x1f945, - 0x1f947, 0x1fffd, + 0x1f947, 0x1faff, + 0x1fc00, 0x1fffd, }; /* CR_Extended_Pictographic */ /* 'Unknown': Script */ static const OnigCodePoint CR_Unknown[] = { - 664, + 675, 0x0378, 0x0379, 0x0380, 0x0383, 0x038b, 0x038b, @@ -22419,7 +22779,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x085f, 0x085f, 0x086b, 0x089f, 0x08b5, 0x08b5, - 0x08be, 0x08d2, + 0x08c8, 0x08d2, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, @@ -22473,7 +22833,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, - 0x0b4e, 0x0b55, + 0x0b4e, 0x0b54, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, @@ -22518,14 +22878,13 @@ static const OnigCodePoint CR_Unknown[] = { 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0cff, - 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d50, 0x0d53, 0x0d64, 0x0d65, - 0x0d80, 0x0d81, + 0x0d80, 0x0d80, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, @@ -22612,7 +22971,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, - 0x1abf, 0x1aff, + 0x1ac1, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, @@ -22649,7 +23008,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x2427, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, - 0x2b96, 0x2b97, + 0x2b96, 0x2b96, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, @@ -22667,7 +23026,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, - 0x2e50, 0x2e7f, + 0x2e53, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, @@ -22677,18 +23036,16 @@ static const OnigCodePoint CR_Unknown[] = { 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, - 0x4db6, 0x4dbf, - 0x9ff0, 0x9fff, + 0x9ffd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, 0xa7c0, 0xa7c1, - 0xa7c7, 0xa7f6, - 0xa82c, 0xa82f, + 0xa7cb, 0xa7f4, + 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c6, 0xa8cd, @@ -22708,7 +23065,7 @@ static const OnigCodePoint CR_Unknown[] = { 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xab2f, - 0xab68, 0xab6f, + 0xab6c, 0xab6f, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, @@ -22753,7 +23110,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x10103, 0x10106, 0x10134, 0x10136, 0x1018f, 0x1018f, - 0x1019c, 0x1019f, + 0x1019d, 0x1019f, 0x101a1, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, @@ -22812,9 +23169,13 @@ static const OnigCodePoint CR_Unknown[] = { 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, 0x10d3a, 0x10e5f, - 0x10e7f, 0x10eff, + 0x10e7f, 0x10e7f, + 0x10eaa, 0x10eaa, + 0x10eae, 0x10eaf, + 0x10eb2, 0x10eff, 0x10f28, 0x10f2f, - 0x10f5a, 0x10fdf, + 0x10f5a, 0x10faf, + 0x10fcc, 0x10fdf, 0x10ff7, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107e, @@ -22823,9 +23184,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, - 0x11147, 0x1114f, + 0x11148, 0x1114f, 0x11177, 0x1117f, - 0x111ce, 0x111cf, 0x111e0, 0x111e0, 0x111f5, 0x111ff, 0x11212, 0x11212, @@ -22852,9 +23212,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x11364, 0x11365, 0x1136d, 0x1136f, 0x11375, 0x113ff, - 0x1145a, 0x1145a, 0x1145c, 0x1145c, - 0x11460, 0x1147f, + 0x11462, 0x1147f, 0x114c8, 0x114cf, 0x114da, 0x1157f, 0x115b6, 0x115b7, @@ -22869,7 +23228,14 @@ static const OnigCodePoint CR_Unknown[] = { 0x11740, 0x117ff, 0x1183c, 0x1189f, 0x118f3, 0x118fe, - 0x11900, 0x1199f, + 0x11907, 0x11908, + 0x1190a, 0x1190b, + 0x11914, 0x11914, + 0x11917, 0x11917, + 0x11936, 0x11936, + 0x11939, 0x1193a, + 0x11947, 0x1194f, + 0x1195a, 0x1199f, 0x119a8, 0x119a9, 0x119d8, 0x119d9, 0x119e5, 0x119ff, @@ -22896,7 +23262,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x11d92, 0x11d92, 0x11d99, 0x11d9f, 0x11daa, 0x11edf, - 0x11ef9, 0x11fbf, + 0x11ef9, 0x11faf, + 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, 0x1246f, 0x1246f, @@ -22920,9 +23287,11 @@ static const OnigCodePoint CR_Unknown[] = { 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, 0x16fa0, 0x16fdf, - 0x16fe4, 0x16fff, + 0x16fe5, 0x16fef, + 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18af3, 0x1afff, + 0x18cd6, 0x18cff, + 0x18d09, 0x1afff, 0x1b11f, 0x1b14f, 0x1b153, 0x1b163, 0x1b168, 0x1b16f, @@ -23020,17 +23389,15 @@ static const OnigCodePoint CR_Unknown[] = { 0x1f0c0, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0f6, 0x1f0ff, - 0x1f10d, 0x1f10f, - 0x1f16d, 0x1f16f, - 0x1f1ad, 0x1f1e5, + 0x1f1ae, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23c, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f25f, 0x1f266, 0x1f2ff, - 0x1f6d6, 0x1f6df, + 0x1f6d8, 0x1f6df, 0x1f6ed, 0x1f6ef, - 0x1f6fb, 0x1f6ff, + 0x1f6fd, 0x1f6ff, 0x1f774, 0x1f77f, 0x1f7d9, 0x1f7df, 0x1f7ec, 0x1f7ff, @@ -23038,25 +23405,29 @@ static const OnigCodePoint CR_Unknown[] = { 0x1f848, 0x1f84f, 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, - 0x1f8ae, 0x1f8ff, - 0x1f90c, 0x1f90c, - 0x1f972, 0x1f972, - 0x1f977, 0x1f979, - 0x1f9a3, 0x1f9a4, - 0x1f9ab, 0x1f9ad, - 0x1f9cb, 0x1f9cc, + 0x1f8ae, 0x1f8af, + 0x1f8b2, 0x1f8ff, + 0x1f979, 0x1f979, + 0x1f9cc, 0x1f9cc, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, - 0x1fa74, 0x1fa77, + 0x1fa75, 0x1fa77, 0x1fa7b, 0x1fa7f, - 0x1fa83, 0x1fa8f, - 0x1fa96, 0x1ffff, - 0x2a6d7, 0x2a6ff, + 0x1fa87, 0x1fa8f, + 0x1faa9, 0x1faaf, + 0x1fab7, 0x1fabf, + 0x1fac3, 0x1facf, + 0x1fad7, 0x1faff, + 0x1fb93, 0x1fb93, + 0x1fbcb, 0x1fbef, + 0x1fbfa, 0x1ffff, + 0x2a6de, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, 0x2ebe1, 0x2f7ff, - 0x2fa1e, 0xe0000, + 0x2fa1e, 0x2ffff, + 0x3134b, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xe00ff, 0xe01f0, 0x10ffff, @@ -34204,216 +34575,910 @@ static const OnigCodePoint CR_Age_12_1[] = { 0xefffe, 0x10ffff, }; /* CR_Age_12_1 */ -#endif /* USE_UNICODE_AGE_PROPERTIES */ -/* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */ -static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = { - 11, - 0x0600, 0x0605, - 0x06dd, 0x06dd, - 0x070f, 0x070f, - 0x08e2, 0x08e2, - 0x0d4e, 0x0d4e, - 0x110bd, 0x110bd, - 0x110cd, 0x110cd, - 0x111c2, 0x111c3, - 0x11a3a, 0x11a3a, - 0x11a84, 0x11a89, - 0x11d46, 0x11d46, -}; /* CR_Grapheme_Cluster_Break_Prepend */ - -/* 'Grapheme_Cluster_Break_CR': Grapheme_Cluster_Break=CR */ -static const OnigCodePoint CR_Grapheme_Cluster_Break_CR[] = { - 1, - 0x000d, 0x000d, -}; /* CR_Grapheme_Cluster_Break_CR */ - -/* 'Grapheme_Cluster_Break_LF': Grapheme_Cluster_Break=LF */ -#define CR_Grapheme_Cluster_Break_LF CR_NEWLINE - -/* 'Grapheme_Cluster_Break_Control': Grapheme_Cluster_Break=Control */ -static const OnigCodePoint CR_Grapheme_Cluster_Break_Control[] = { - 19, - 0x0000, 0x0009, - 0x000b, 0x000c, - 0x000e, 0x001f, - 0x007f, 0x009f, - 0x00ad, 0x00ad, - 0x061c, 0x061c, - 0x180e, 0x180e, - 0x200b, 0x200b, - 0x200e, 0x200f, - 0x2028, 0x202e, - 0x2060, 0x206f, - 0xfeff, 0xfeff, - 0xfff0, 0xfffb, - 0x13430, 0x13438, - 0x1bca0, 0x1bca3, - 0x1d173, 0x1d17a, - 0xe0000, 0xe001f, - 0xe0080, 0xe00ff, - 0xe01f0, 0xe0fff, -}; /* CR_Grapheme_Cluster_Break_Control */ - -/* 'Grapheme_Cluster_Break_Extend': Grapheme_Cluster_Break=Extend */ -static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { - 336, - 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, - 0x08d3, 0x08e1, - 0x08e3, 0x0902, - 0x093a, 0x093a, - 0x093c, 0x093c, - 0x0941, 0x0948, - 0x094d, 0x094d, - 0x0951, 0x0957, - 0x0962, 0x0963, - 0x0981, 0x0981, - 0x09bc, 0x09bc, - 0x09be, 0x09be, - 0x09c1, 0x09c4, - 0x09cd, 0x09cd, +/* 'Age_13_0': Derived Age 13.0 */ +static const OnigCodePoint CR_Age_13_0[] = { + 686, + 0x0000, 0x0377, + 0x037a, 0x037f, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x052f, + 0x0531, 0x0556, + 0x0559, 0x058a, + 0x058d, 0x058f, + 0x0591, 0x05c7, + 0x05d0, 0x05ea, + 0x05ef, 0x05f4, + 0x0600, 0x061c, + 0x061e, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x07b1, + 0x07c0, 0x07fa, + 0x07fd, 0x082d, + 0x0830, 0x083e, + 0x0840, 0x085b, + 0x085e, 0x085e, + 0x0860, 0x086a, + 0x08a0, 0x08b4, + 0x08b6, 0x08c7, + 0x08d3, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09ce, 0x09d7, 0x09d7, - 0x09e2, 0x09e3, - 0x09fe, 0x09fe, - 0x0a01, 0x0a02, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fe, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, - 0x0a41, 0x0a42, + 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, - 0x0a70, 0x0a71, - 0x0a75, 0x0a75, - 0x0a81, 0x0a82, - 0x0abc, 0x0abc, - 0x0ac1, 0x0ac5, - 0x0ac7, 0x0ac8, - 0x0acd, 0x0acd, - 0x0ae2, 0x0ae3, - 0x0afa, 0x0aff, - 0x0b01, 0x0b01, - 0x0b3c, 0x0b3c, - 0x0b3e, 0x0b3f, - 0x0b41, 0x0b44, - 0x0b4d, 0x0b4d, - 0x0b56, 0x0b57, - 0x0b62, 0x0b63, - 0x0b82, 0x0b82, - 0x0bbe, 0x0bbe, - 0x0bc0, 0x0bc0, - 0x0bcd, 0x0bcd, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a76, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0af1, + 0x0af9, 0x0aff, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b44, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b55, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b63, + 0x0b66, 0x0b77, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, - 0x0c00, 0x0c00, - 0x0c04, 0x0c04, - 0x0c3e, 0x0c40, + 0x0be6, 0x0bfa, + 0x0c00, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c39, + 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, - 0x0c62, 0x0c63, - 0x0c81, 0x0c81, - 0x0cbc, 0x0cbc, - 0x0cbf, 0x0cbf, - 0x0cc2, 0x0cc2, - 0x0cc6, 0x0cc6, - 0x0ccc, 0x0ccd, + 0x0c58, 0x0c5a, + 0x0c60, 0x0c63, + 0x0c66, 0x0c6f, + 0x0c77, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, - 0x0ce2, 0x0ce3, - 0x0d00, 0x0d01, - 0x0d3b, 0x0d3c, - 0x0d3e, 0x0d3e, - 0x0d41, 0x0d44, - 0x0d4d, 0x0d4d, - 0x0d57, 0x0d57, - 0x0d62, 0x0d63, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce3, + 0x0ce6, 0x0cef, + 0x0cf1, 0x0cf2, + 0x0d00, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d44, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4f, + 0x0d54, 0x0d63, + 0x0d66, 0x0d7f, + 0x0d81, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, - 0x0dcf, 0x0dcf, - 0x0dd2, 0x0dd4, + 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, - 0x0ddf, 0x0ddf, - 0x0e31, 0x0e31, - 0x0e34, 0x0e3a, - 0x0e47, 0x0e4e, - 0x0eb1, 0x0eb1, - 0x0eb4, 0x0ebc, + 0x0dd8, 0x0ddf, + 0x0de6, 0x0def, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e86, 0x0e8a, + 0x0e8c, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, - 0x0f18, 0x0f19, - 0x0f35, 0x0f35, - 0x0f37, 0x0f37, - 0x0f39, 0x0f39, - 0x0f71, 0x0f7e, - 0x0f80, 0x0f84, - 0x0f86, 0x0f87, - 0x0f8d, 0x0f97, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edf, + 0x0f00, 0x0f47, + 0x0f49, 0x0f6c, + 0x0f71, 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, 0x1714, - 0x1732, 0x1734, - 0x1752, 0x1753, + 0x0fbe, 0x0fcc, + 0x0fce, 0x0fda, + 0x1000, 0x10c5, + 0x10c7, 0x10c7, + 0x10cd, 0x10cd, + 0x10d0, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12d6, + 0x12d8, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x135a, + 0x135d, 0x137c, + 0x1380, 0x1399, + 0x13a0, 0x13f5, + 0x13f8, 0x13fd, + 0x1400, 0x169c, + 0x16a0, 0x16f8, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, 0x1772, 0x1773, - 0x17b4, 0x17b5, - 0x17b7, 0x17bd, - 0x17c6, 0x17c6, - 0x17c9, 0x17d3, - 0x17dd, 0x17dd, - 0x180b, 0x180d, - 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, 0x1abe, - 0x1b00, 0x1b03, - 0x1b34, 0x1b3a, - 0x1b3c, 0x1b3c, - 0x1b42, 0x1b42, - 0x1b6b, 0x1b73, - 0x1b80, 0x1b81, - 0x1ba2, 0x1ba5, - 0x1ba8, 0x1ba9, - 0x1bab, 0x1bad, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x180e, + 0x1810, 0x1819, + 0x1820, 0x1878, + 0x1880, 0x18aa, + 0x18b0, 0x18f5, + 0x1900, 0x191e, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x1980, 0x19ab, + 0x19b0, 0x19c9, + 0x19d0, 0x19da, + 0x19de, 0x1a1b, + 0x1a1e, 0x1a5e, + 0x1a60, 0x1a7c, + 0x1a7f, 0x1a89, + 0x1a90, 0x1a99, + 0x1aa0, 0x1aad, + 0x1ab0, 0x1ac0, + 0x1b00, 0x1b4b, + 0x1b50, 0x1b7c, + 0x1b80, 0x1bf3, + 0x1bfc, 0x1c37, + 0x1c3b, 0x1c49, + 0x1c4d, 0x1c88, + 0x1c90, 0x1cba, + 0x1cbd, 0x1cc7, + 0x1cd0, 0x1cfa, + 0x1d00, 0x1df9, + 0x1dfb, 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, 0x2064, + 0x2066, 0x2071, + 0x2074, 0x208e, + 0x2090, 0x209c, + 0x20a0, 0x20bf, + 0x20d0, 0x20f0, + 0x2100, 0x218b, + 0x2190, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2b73, + 0x2b76, 0x2b95, + 0x2b97, 0x2c2e, + 0x2c30, 0x2c5e, + 0x2c60, 0x2cf3, + 0x2cf9, 0x2d25, + 0x2d27, 0x2d27, + 0x2d2d, 0x2d2d, + 0x2d30, 0x2d67, + 0x2d6f, 0x2d70, + 0x2d7f, 0x2d96, + 0x2da0, 0x2da6, + 0x2da8, 0x2dae, + 0x2db0, 0x2db6, + 0x2db8, 0x2dbe, + 0x2dc0, 0x2dc6, + 0x2dc8, 0x2dce, + 0x2dd0, 0x2dd6, + 0x2dd8, 0x2dde, + 0x2de0, 0x2e52, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3000, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x312f, + 0x3131, 0x318e, + 0x3190, 0x31e3, + 0x31f0, 0x321e, + 0x3220, 0x9ffc, + 0xa000, 0xa48c, + 0xa490, 0xa4c6, + 0xa4d0, 0xa62b, + 0xa640, 0xa6f7, + 0xa700, 0xa7bf, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa82c, + 0xa830, 0xa839, + 0xa840, 0xa877, + 0xa880, 0xa8c5, + 0xa8ce, 0xa8d9, + 0xa8e0, 0xa953, + 0xa95f, 0xa97c, + 0xa980, 0xa9cd, + 0xa9cf, 0xa9d9, + 0xa9de, 0xa9fe, + 0xaa00, 0xaa36, + 0xaa40, 0xaa4d, + 0xaa50, 0xaa59, + 0xaa5c, 0xaac2, + 0xaadb, 0xaaf6, + 0xab01, 0xab06, + 0xab09, 0xab0e, + 0xab11, 0xab16, + 0xab20, 0xab26, + 0xab28, 0xab2e, + 0xab30, 0xab6b, + 0xab70, 0xabed, + 0xabf0, 0xabf9, + 0xac00, 0xd7a3, + 0xd7b0, 0xd7c6, + 0xd7cb, 0xd7fb, + 0xd800, 0xfa6d, + 0xfa70, 0xfad9, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbc1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdd0, 0xfdfd, + 0xfe00, 0xfe19, + 0xfe20, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1018e, + 0x10190, 0x1019c, + 0x101a0, 0x101a0, + 0x101d0, 0x101fd, + 0x10280, 0x1029c, + 0x102a0, 0x102d0, + 0x102e0, 0x102fb, + 0x10300, 0x10323, + 0x1032d, 0x1034a, + 0x10350, 0x1037a, + 0x10380, 0x1039d, + 0x1039f, 0x103c3, + 0x103c8, 0x103d5, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x104b0, 0x104d3, + 0x104d8, 0x104fb, + 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, 0x1089e, + 0x108a7, 0x108af, + 0x108e0, 0x108f2, + 0x108f4, 0x108f5, + 0x108fb, 0x1091b, + 0x1091f, 0x10939, + 0x1093f, 0x1093f, + 0x10980, 0x109b7, + 0x109bc, 0x109cf, + 0x109d2, 0x10a03, + 0x10a05, 0x10a06, + 0x10a0c, 0x10a13, + 0x10a15, 0x10a17, + 0x10a19, 0x10a35, + 0x10a38, 0x10a3a, + 0x10a3f, 0x10a48, + 0x10a50, 0x10a58, + 0x10a60, 0x10a9f, + 0x10ac0, 0x10ae6, + 0x10aeb, 0x10af6, + 0x10b00, 0x10b35, + 0x10b39, 0x10b55, + 0x10b58, 0x10b72, + 0x10b78, 0x10b91, + 0x10b99, 0x10b9c, + 0x10ba9, 0x10baf, + 0x10c00, 0x10c48, + 0x10c80, 0x10cb2, + 0x10cc0, 0x10cf2, + 0x10cfa, 0x10d27, + 0x10d30, 0x10d39, + 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, + 0x10f00, 0x10f27, + 0x10f30, 0x10f59, + 0x10fb0, 0x10fcb, + 0x10fe0, 0x10ff6, + 0x11000, 0x1104d, + 0x11052, 0x1106f, + 0x1107f, 0x110c1, + 0x110cd, 0x110cd, + 0x110d0, 0x110e8, + 0x110f0, 0x110f9, + 0x11100, 0x11134, + 0x11136, 0x11147, + 0x11150, 0x11176, + 0x11180, 0x111df, + 0x111e1, 0x111f4, + 0x11200, 0x11211, + 0x11213, 0x1123e, + 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, + 0x1133b, 0x11344, + 0x11347, 0x11348, + 0x1134b, 0x1134d, + 0x11350, 0x11350, + 0x11357, 0x11357, + 0x1135d, 0x11363, + 0x11366, 0x1136c, + 0x11370, 0x11374, + 0x11400, 0x1145b, + 0x1145d, 0x11461, + 0x11480, 0x114c7, + 0x114d0, 0x114d9, + 0x11580, 0x115b5, + 0x115b8, 0x115dd, + 0x11600, 0x11644, + 0x11650, 0x11659, + 0x11660, 0x1166c, + 0x11680, 0x116b8, + 0x116c0, 0x116c9, + 0x11700, 0x1171a, + 0x1171d, 0x1172b, + 0x11730, 0x1173f, + 0x11800, 0x1183b, + 0x118a0, 0x118f2, + 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, + 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, + 0x11d60, 0x11d65, + 0x11d67, 0x11d68, + 0x11d6a, 0x11d8e, + 0x11d90, 0x11d91, + 0x11d93, 0x11d98, + 0x11da0, 0x11da9, + 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, + 0x11fc0, 0x11ff1, + 0x11fff, 0x12399, + 0x12400, 0x1246e, + 0x12470, 0x12474, + 0x12480, 0x12543, + 0x13000, 0x1342e, + 0x13430, 0x13438, + 0x14400, 0x14646, + 0x16800, 0x16a38, + 0x16a40, 0x16a5e, + 0x16a60, 0x16a69, + 0x16a6e, 0x16a6f, + 0x16ad0, 0x16aed, + 0x16af0, 0x16af5, + 0x16b00, 0x16b45, + 0x16b50, 0x16b59, + 0x16b5b, 0x16b61, + 0x16b63, 0x16b77, + 0x16b7d, 0x16b8f, + 0x16e40, 0x16e9a, + 0x16f00, 0x16f4a, + 0x16f4f, 0x16f87, + 0x16f8f, 0x16f9f, + 0x16fe0, 0x16fe4, + 0x16ff0, 0x16ff1, + 0x17000, 0x187f7, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, + 0x1b000, 0x1b11e, + 0x1b150, 0x1b152, + 0x1b164, 0x1b167, + 0x1b170, 0x1b2fb, + 0x1bc00, 0x1bc6a, + 0x1bc70, 0x1bc7c, + 0x1bc80, 0x1bc88, + 0x1bc90, 0x1bc99, + 0x1bc9c, 0x1bca3, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d129, 0x1d1e8, + 0x1d200, 0x1d245, + 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, 0x1da8b, + 0x1da9b, 0x1da9f, + 0x1daa1, 0x1daaf, + 0x1e000, 0x1e006, + 0x1e008, 0x1e018, + 0x1e01b, 0x1e021, + 0x1e023, 0x1e024, + 0x1e026, 0x1e02a, + 0x1e100, 0x1e12c, + 0x1e130, 0x1e13d, + 0x1e140, 0x1e149, + 0x1e14e, 0x1e14f, + 0x1e2c0, 0x1e2f9, + 0x1e2ff, 0x1e2ff, + 0x1e800, 0x1e8c4, + 0x1e8c7, 0x1e8d6, + 0x1e900, 0x1e94b, + 0x1e950, 0x1e959, + 0x1e95e, 0x1e95f, + 0x1ec71, 0x1ecb4, + 0x1ed01, 0x1ed3d, + 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, 0x1f0bf, + 0x1f0c1, 0x1f0cf, + 0x1f0d1, 0x1f0f5, + 0x1f100, 0x1f1ad, + 0x1f1e6, 0x1f202, + 0x1f210, 0x1f23b, + 0x1f240, 0x1f248, + 0x1f250, 0x1f251, + 0x1f260, 0x1f265, + 0x1f300, 0x1f6d7, + 0x1f6e0, 0x1f6ec, + 0x1f6f0, 0x1f6fc, + 0x1f700, 0x1f773, + 0x1f780, 0x1f7d8, + 0x1f7e0, 0x1f7eb, + 0x1f800, 0x1f80b, + 0x1f810, 0x1f847, + 0x1f850, 0x1f859, + 0x1f860, 0x1f887, + 0x1f890, 0x1f8ad, + 0x1f8b0, 0x1f8b1, + 0x1f900, 0x1f978, + 0x1f97a, 0x1f9cb, + 0x1f9cd, 0x1fa53, + 0x1fa60, 0x1fa6d, + 0x1fa70, 0x1fa74, + 0x1fa78, 0x1fa7a, + 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, 0x3134a, + 0x3fffe, 0x3ffff, + 0x4fffe, 0x4ffff, + 0x5fffe, 0x5ffff, + 0x6fffe, 0x6ffff, + 0x7fffe, 0x7ffff, + 0x8fffe, 0x8ffff, + 0x9fffe, 0x9ffff, + 0xafffe, 0xaffff, + 0xbfffe, 0xbffff, + 0xcfffe, 0xcffff, + 0xdfffe, 0xdffff, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, + 0xefffe, 0x10ffff, +}; /* CR_Age_13_0 */ + +#endif /* USE_UNICODE_AGE_PROPERTIES */ +/* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */ +static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = { + 13, + 0x0600, 0x0605, + 0x06dd, 0x06dd, + 0x070f, 0x070f, + 0x08e2, 0x08e2, + 0x0d4e, 0x0d4e, + 0x110bd, 0x110bd, + 0x110cd, 0x110cd, + 0x111c2, 0x111c3, + 0x1193f, 0x1193f, + 0x11941, 0x11941, + 0x11a3a, 0x11a3a, + 0x11a84, 0x11a89, + 0x11d46, 0x11d46, +}; /* CR_Grapheme_Cluster_Break_Prepend */ + +/* 'Grapheme_Cluster_Break_CR': Grapheme_Cluster_Break=CR */ +static const OnigCodePoint CR_Grapheme_Cluster_Break_CR[] = { + 1, + 0x000d, 0x000d, +}; /* CR_Grapheme_Cluster_Break_CR */ + +/* 'Grapheme_Cluster_Break_LF': Grapheme_Cluster_Break=LF */ +#define CR_Grapheme_Cluster_Break_LF CR_NEWLINE + +/* 'Grapheme_Cluster_Break_Control': Grapheme_Cluster_Break=Control */ +static const OnigCodePoint CR_Grapheme_Cluster_Break_Control[] = { + 19, + 0x0000, 0x0009, + 0x000b, 0x000c, + 0x000e, 0x001f, + 0x007f, 0x009f, + 0x00ad, 0x00ad, + 0x061c, 0x061c, + 0x180e, 0x180e, + 0x200b, 0x200b, + 0x200e, 0x200f, + 0x2028, 0x202e, + 0x2060, 0x206f, + 0xfeff, 0xfeff, + 0xfff0, 0xfffb, + 0x13430, 0x13438, + 0x1bca0, 0x1bca3, + 0x1d173, 0x1d17a, + 0xe0000, 0xe001f, + 0xe0080, 0xe00ff, + 0xe01f0, 0xe0fff, +}; /* CR_Grapheme_Cluster_Break_Control */ + +/* 'Grapheme_Cluster_Break_Extend': Grapheme_Cluster_Break=Extend */ +static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { + 345, + 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, + 0x08d3, 0x08e1, + 0x08e3, 0x0902, + 0x093a, 0x093a, + 0x093c, 0x093c, + 0x0941, 0x0948, + 0x094d, 0x094d, + 0x0951, 0x0957, + 0x0962, 0x0963, + 0x0981, 0x0981, + 0x09bc, 0x09bc, + 0x09be, 0x09be, + 0x09c1, 0x09c4, + 0x09cd, 0x09cd, + 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, + 0x0acd, 0x0acd, + 0x0ae2, 0x0ae3, + 0x0afa, 0x0aff, + 0x0b01, 0x0b01, + 0x0b3c, 0x0b3c, + 0x0b3e, 0x0b3f, + 0x0b41, 0x0b44, + 0x0b4d, 0x0b4d, + 0x0b55, 0x0b57, + 0x0b62, 0x0b63, + 0x0b82, 0x0b82, + 0x0bbe, 0x0bbe, + 0x0bc0, 0x0bc0, + 0x0bcd, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0c00, 0x0c00, + 0x0c04, 0x0c04, + 0x0c3e, 0x0c40, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c62, 0x0c63, + 0x0c81, 0x0c81, + 0x0cbc, 0x0cbc, + 0x0cbf, 0x0cbf, + 0x0cc2, 0x0cc2, + 0x0cc6, 0x0cc6, + 0x0ccc, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0ce2, 0x0ce3, + 0x0d00, 0x0d01, + 0x0d3b, 0x0d3c, + 0x0d3e, 0x0d3e, + 0x0d41, 0x0d44, + 0x0d4d, 0x0d4d, + 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, 0x0ecd, + 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, 0x1714, + 0x1732, 0x1734, + 0x1752, 0x1753, + 0x1772, 0x1773, + 0x17b4, 0x17b5, + 0x17b7, 0x17bd, + 0x17c6, 0x17c6, + 0x17c9, 0x17d3, + 0x17dd, 0x17dd, + 0x180b, 0x180d, + 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, 0x1ac0, + 0x1b00, 0x1b03, + 0x1b34, 0x1b3a, + 0x1b3c, 0x1b3c, + 0x1b42, 0x1b42, + 0x1b6b, 0x1b73, + 0x1b80, 0x1b81, + 0x1ba2, 0x1ba5, + 0x1ba8, 0x1ba9, + 0x1bab, 0x1bad, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, @@ -34443,6 +35508,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c5, 0xa8e0, 0xa8f1, 0xa8ff, 0xa8ff, @@ -34483,6 +35549,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10eab, 0x10eac, 0x10f46, 0x10f50, 0x11001, 0x11001, 0x11038, 0x11046, @@ -34496,6 +35563,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x11180, 0x11181, 0x111b6, 0x111be, 0x111c9, 0x111cc, + 0x111cf, 0x111cf, 0x1122f, 0x11231, 0x11234, 0x11234, 0x11236, 0x11237, @@ -34536,6 +35604,10 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, + 0x11930, 0x11930, + 0x1193b, 0x1193c, + 0x1193e, 0x1193e, + 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, 0x119e0, 0x119e0, @@ -34567,6 +35639,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f92, + 0x16fe4, 0x16fe4, 0x1bc9d, 0x1bc9e, 0x1d165, 0x1d165, 0x1d167, 0x1d169, @@ -34600,7 +35673,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[] = { - 152, + 159, 0x0903, 0x0903, 0x093b, 0x093b, 0x093e, 0x0940, @@ -34704,6 +35777,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x11182, 0x11182, 0x111b3, 0x111b5, 0x111bf, 0x111c0, + 0x111ce, 0x111ce, 0x1122c, 0x1122e, 0x11232, 0x11233, 0x11235, 0x11235, @@ -34735,6 +35809,11 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x11726, 0x11726, 0x1182c, 0x1182e, 0x11838, 0x11838, + 0x11931, 0x11935, + 0x11937, 0x11938, + 0x1193d, 0x1193d, + 0x11940, 0x11940, + 0x11942, 0x11942, 0x119d1, 0x119d3, 0x119dc, 0x119df, 0x119e4, 0x119e4, @@ -34751,6 +35830,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x11d96, 0x11d96, 0x11ef5, 0x11ef6, 0x16f51, 0x16f87, + 0x16ff0, 0x16ff1, 0x1d166, 0x1d166, 0x1d16d, 0x1d16d, }; /* CR_Grapheme_Cluster_Break_SpacingMark */ @@ -36314,7 +37394,10 @@ static const OnigCodePoint CR_In_Yi_Radicals[] = { }; /* CR_In_Yi_Radicals */ /* 'In_Lisu': Block */ -#define CR_In_Lisu CR_Lisu +static const OnigCodePoint CR_In_Lisu[] = { + 1, + 0xa4d0, 0xa4ff, +}; /* CR_In_Lisu */ /* 'In_Vai': Block */ static const OnigCodePoint CR_In_Vai[] = { @@ -36790,6 +37873,12 @@ static const OnigCodePoint CR_In_Rumi_Numeral_Symbols[] = { 0x10e60, 0x10e7f, }; /* CR_In_Rumi_Numeral_Symbols */ +/* 'In_Yezidi': Block */ +static const OnigCodePoint CR_In_Yezidi[] = { + 1, + 0x10e80, 0x10ebf, +}; /* CR_In_Yezidi */ + /* 'In_Old_Sogdian': Block */ static const OnigCodePoint CR_In_Old_Sogdian[] = { 1, @@ -36802,6 +37891,12 @@ static const OnigCodePoint CR_In_Sogdian[] = { 0x10f30, 0x10f6f, }; /* CR_In_Sogdian */ +/* 'In_Chorasmian': Block */ +static const OnigCodePoint CR_In_Chorasmian[] = { + 1, + 0x10fb0, 0x10fdf, +}; /* CR_In_Chorasmian */ + /* 'In_Elymaic': Block */ static const OnigCodePoint CR_In_Elymaic[] = { 1, @@ -36839,10 +37934,7 @@ static const OnigCodePoint CR_In_Mahajani[] = { }; /* CR_In_Mahajani */ /* 'In_Sharada': Block */ -static const OnigCodePoint CR_In_Sharada[] = { - 1, - 0x11180, 0x111df, -}; /* CR_In_Sharada */ +#define CR_In_Sharada CR_Sharada /* 'In_Sinhala_Archaic_Numbers': Block */ static const OnigCodePoint CR_In_Sinhala_Archaic_Numbers[] = { @@ -36928,6 +38020,12 @@ static const OnigCodePoint CR_In_Warang_Citi[] = { 0x118a0, 0x118ff, }; /* CR_In_Warang_Citi */ +/* 'In_Dives_Akuru': Block */ +static const OnigCodePoint CR_In_Dives_Akuru[] = { + 1, + 0x11900, 0x1195f, +}; /* CR_In_Dives_Akuru */ + /* 'In_Nandinagari': Block */ static const OnigCodePoint CR_In_Nandinagari[] = { 1, @@ -36982,6 +38080,12 @@ static const OnigCodePoint CR_In_Makasar[] = { 0x11ee0, 0x11eff, }; /* CR_In_Makasar */ +/* 'In_Lisu_Supplement': Block */ +static const OnigCodePoint CR_In_Lisu_Supplement[] = { + 1, + 0x11fb0, 0x11fbf, +}; /* CR_In_Lisu_Supplement */ + /* 'In_Tamil_Supplement': Block */ static const OnigCodePoint CR_In_Tamil_Supplement[] = { 1, @@ -37078,6 +38182,18 @@ static const OnigCodePoint CR_In_Tangut_Components[] = { 0x18800, 0x18aff, }; /* CR_In_Tangut_Components */ +/* 'In_Khitan_Small_Script': Block */ +static const OnigCodePoint CR_In_Khitan_Small_Script[] = { + 1, + 0x18b00, 0x18cff, +}; /* CR_In_Khitan_Small_Script */ + +/* 'In_Tangut_Supplement': Block */ +static const OnigCodePoint CR_In_Tangut_Supplement[] = { + 1, + 0x18d00, 0x18d8f, +}; /* CR_In_Tangut_Supplement */ + /* 'In_Kana_Supplement': Block */ static const OnigCodePoint CR_In_Kana_Supplement[] = { 1, @@ -37300,6 +38416,12 @@ static const OnigCodePoint CR_In_Symbols_and_Pictographs_Extended_A[] = { 0x1fa70, 0x1faff, }; /* CR_In_Symbols_and_Pictographs_Extended_A */ +/* 'In_Symbols_for_Legacy_Computing': Block */ +static const OnigCodePoint CR_In_Symbols_for_Legacy_Computing[] = { + 1, + 0x1fb00, 0x1fbff, +}; /* CR_In_Symbols_for_Legacy_Computing */ + /* 'In_CJK_Unified_Ideographs_Extension_B': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_B[] = { 1, @@ -37336,6 +38458,12 @@ static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs_Supplement[] = { 0x2f800, 0x2fa1f, }; /* CR_In_CJK_Compatibility_Ideographs_Supplement */ +/* 'In_CJK_Unified_Ideographs_Extension_G': Block */ +static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_G[] = { + 1, + 0x30000, 0x3134f, +}; /* CR_In_CJK_Unified_Ideographs_Extension_G */ + /* 'In_Tags': Block */ static const OnigCodePoint CR_In_Tags[] = { 1, @@ -37362,7 +38490,7 @@ static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_B[] = { /* 'In_No_Block': Block */ static const OnigCodePoint CR_In_No_Block[] = { - 53, + 54, 0x0870, 0x089f, 0x2fe0, 0x2fef, 0x10200, 0x1027f, @@ -37375,20 +38503,20 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x10bb0, 0x10bff, 0x10c50, 0x10c7f, 0x10d40, 0x10e5f, - 0x10e80, 0x10eff, - 0x10f70, 0x10fdf, + 0x10ec0, 0x10eff, + 0x10f70, 0x10faf, 0x11250, 0x1127f, 0x11380, 0x113ff, 0x114e0, 0x1157f, 0x116d0, 0x116ff, 0x11740, 0x117ff, 0x11850, 0x1189f, - 0x11900, 0x1199f, + 0x11960, 0x1199f, 0x11ab0, 0x11abf, 0x11b00, 0x11bff, 0x11cc0, 0x11cff, 0x11db0, 0x11edf, - 0x11f00, 0x11fbf, + 0x11f00, 0x11faf, 0x12550, 0x12fff, 0x13440, 0x143ff, 0x14680, 0x167ff, @@ -37396,7 +38524,7 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x16b90, 0x16e3f, 0x16ea0, 0x16eff, 0x16fa0, 0x16fdf, - 0x18b00, 0x1afff, + 0x18d90, 0x1afff, 0x1b300, 0x1bbff, 0x1bcb0, 0x1cfff, 0x1d250, 0x1d2df, @@ -37410,10 +38538,11 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x1ecc0, 0x1ecff, 0x1ed50, 0x1edff, 0x1ef00, 0x1efff, - 0x1fb00, 0x1ffff, + 0x1fc00, 0x1ffff, 0x2a6e0, 0x2a6ff, 0x2ebf0, 0x2f7ff, - 0x2fa20, 0xdffff, + 0x2fa20, 0x2ffff, + 0x31350, 0xdffff, 0xe0080, 0xe00ff, 0xe01f0, 0xeffff, }; /* CR_In_No_Block */ @@ -37648,6 +38777,10 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Nandinagari, CR_Nyiakeng_Puachue_Hmong, CR_Wancho, + CR_Chorasmian, + CR_Dives_Akuru, + CR_Khitan_Small_Script, + CR_Yezidi, CR_White_Space, CR_Bidi_Control, CR_Join_Control, @@ -37712,6 +38845,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Age_11_0, CR_Age_12_0, CR_Age_12_1, + CR_Age_13_0, #endif /* USE_UNICODE_AGE_PROPERTIES */ CR_Grapheme_Cluster_Break_Prepend, CR_Grapheme_Cluster_Break_CR, @@ -37931,8 +39065,10 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Old_Hungarian, CR_In_Hanifi_Rohingya, CR_In_Rumi_Numeral_Symbols, + CR_In_Yezidi, CR_In_Old_Sogdian, CR_In_Sogdian, + CR_In_Chorasmian, CR_In_Elymaic, CR_In_Brahmi, CR_In_Kaithi, @@ -37954,6 +39090,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Ahom, CR_In_Dogra, CR_In_Warang_Citi, + CR_In_Dives_Akuru, CR_In_Nandinagari, CR_In_Zanabazar_Square, CR_In_Soyombo, @@ -37963,6 +39100,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Masaram_Gondi, CR_In_Gunjala_Gondi, CR_In_Makasar, + CR_In_Lisu_Supplement, CR_In_Tamil_Supplement, CR_In_Cuneiform, CR_In_Cuneiform_Numbers_and_Punctuation, @@ -37979,6 +39117,8 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Ideographic_Symbols_and_Punctuation, CR_In_Tangut, CR_In_Tangut_Components, + CR_In_Khitan_Small_Script, + CR_In_Tangut_Supplement, CR_In_Kana_Supplement, CR_In_Kana_Extended_A, CR_In_Small_Kana_Extension, @@ -38016,12 +39156,14 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Supplemental_Symbols_and_Pictographs, CR_In_Chess_Symbols, CR_In_Symbols_and_Pictographs_Extended_A, + CR_In_Symbols_for_Legacy_Computing, CR_In_CJK_Unified_Ideographs_Extension_B, CR_In_CJK_Unified_Ideographs_Extension_C, CR_In_CJK_Unified_Ideographs_Extension_D, CR_In_CJK_Unified_Ideographs_Extension_E, CR_In_CJK_Unified_Ideographs_Extension_F, CR_In_CJK_Compatibility_Ideographs_Supplement, + CR_In_CJK_Unified_Ideographs_Extension_G, CR_In_Tags, CR_In_Variation_Selectors_Supplement, CR_In_Supplementary_Private_Use_Area_A, @@ -38045,20 +39187,22 @@ static const struct uniname2ctype_struct *uniname2ctype_p( #define TOTAL_KEYWORDS 15 #define MIN_WORD_LENGTH 4 #define MAX_WORD_LENGTH 11 -#define MIN_HASH_VALUE 6 -#define MAX_HASH_VALUE 20 -/* maximum key range = 15, duplicates = 0 */ #else /* USE_UNICODE_PROPERTIES */ #ifndef USE_UNICODE_AGE_PROPERTIES -#define TOTAL_KEYWORDS 814 +#define TOTAL_KEYWORDS 835 #else /* USE_UNICODE_AGE_PROPERTIES */ -#define TOTAL_KEYWORDS 836 +#define TOTAL_KEYWORDS 858 #endif /* USE_UNICODE_AGE_PROPERTIES */ #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 44 -#define MIN_HASH_VALUE 11 +#endif /* USE_UNICODE_PROPERTIES */ +#define MIN_HASH_VALUE 6 +#ifndef USE_UNICODE_PROPERTIES +#define MAX_HASH_VALUE 20 +/* maximum key range = 15, duplicates = 0 */ +#else /* USE_UNICODE_PROPERTIES */ #define MAX_HASH_VALUE 6098 -/* maximum key range = 6088, duplicates = 0 */ +/* maximum key range = 6093, duplicates = 0 */ #endif /* USE_UNICODE_PROPERTIES */ #ifdef __GNUC__ @@ -38100,16 +39244,16 @@ uniname2ctype_hash (register const char *str, register size_t len) 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, #else /* USE_UNICODE_AGE_PROPERTIES */ - 6099, 6099, 6099, 6099, 6099, 6099, 17, 6099, 3, 1, - 4, 13, 3, 22, 9, 16, 12, 5, 6099, 6099, + 6099, 6099, 6099, 6099, 6099, 6099, 20, 6099, 3, 1, + 4, 7, 20, 16, 11, 10, 6, 1, 6099, 6099, #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, 1023, 1071, 1051, 4, 1492, 9, 500, 88, - 8, 18, 1371, 797, 54, 203, 310, 619, 1608, 603, - 364, 1438, 20, 1, 3, 6099, 6099, 6099, 6099, 6099 + 437, 37, 117, 1071, 1051, 4, 1488, 9, 500, 88, + 8, 18, 1371, 1287, 54, 203, 310, 619, 1635, 649, + 161, 1624, 4, 2, 1, 6099, 6099, 6099, 6099, 6099 #endif /* USE_UNICODE_PROPERTIES */ }; #ifndef USE_UNICODE_PROPERTIES @@ -38173,10 +39317,11 @@ 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_str6[sizeof("z")]; + char uniname2ctype_pool_str12[sizeof("yi")]; + char uniname2ctype_pool_str17[sizeof("zzzz")]; + char uniname2ctype_pool_str18[sizeof("yiii")]; char uniname2ctype_pool_str22[sizeof("lana")]; - char uniname2ctype_pool_str24[sizeof("z")]; char uniname2ctype_pool_str25[sizeof("lina")]; char uniname2ctype_pool_str33[sizeof("maka")]; char uniname2ctype_pool_str35[sizeof("mani")]; @@ -38186,11 +39331,11 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str47[sizeof("ci")]; char uniname2ctype_pool_str48[sizeof("lao")]; char uniname2ctype_pool_str49[sizeof("laoo")]; + char uniname2ctype_pool_str51[sizeof("yezi")]; 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("zzzz")]; char uniname2ctype_pool_str71[sizeof("gran")]; char uniname2ctype_pool_str75[sizeof("co")]; char uniname2ctype_pool_str83[sizeof("lineara")]; @@ -38209,10 +39354,13 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str117[sizeof("geor")]; char uniname2ctype_pool_str118[sizeof("greek")]; char uniname2ctype_pool_str122[sizeof("gonm")]; + char uniname2ctype_pool_str126[sizeof("dia")]; + char uniname2ctype_pool_str127[sizeof("di")]; 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_str135[sizeof("diak")]; char uniname2ctype_pool_str139[sizeof("cakm")]; char uniname2ctype_pool_str145[sizeof("inmanichaean")]; char uniname2ctype_pool_str146[sizeof("inmro")]; @@ -38222,6 +39370,8 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str152[sizeof("mandaic")]; char uniname2ctype_pool_str153[sizeof("meeteimayek")]; char uniname2ctype_pool_str161[sizeof("inarmenian")]; + char uniname2ctype_pool_str173[sizeof("vai")]; + char uniname2ctype_pool_str174[sizeof("vaii")]; char uniname2ctype_pool_str177[sizeof("inmyanmar")]; char uniname2ctype_pool_str178[sizeof("inmakasar")]; char uniname2ctype_pool_str183[sizeof("common")]; @@ -38234,6 +39384,7 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str213[sizeof("qaai")]; 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")]; @@ -38246,6 +39397,7 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str267[sizeof("armn")]; char uniname2ctype_pool_str268[sizeof("incherokee")]; char uniname2ctype_pool_str270[sizeof("prependedconcatenationmark")]; + char uniname2ctype_pool_str273[sizeof("cf")]; char uniname2ctype_pool_str274[sizeof("incuneiform")]; char uniname2ctype_pool_str275[sizeof("inavestan")]; char uniname2ctype_pool_str281[sizeof("inipaextensions")]; @@ -38253,9 +39405,11 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str283[sizeof("armenian")]; char uniname2ctype_pool_str285[sizeof("insharada")]; char uniname2ctype_pool_str289[sizeof("inmarchen")]; + char uniname2ctype_pool_str290[sizeof("pf")]; char uniname2ctype_pool_str293[sizeof("makasar")]; char uniname2ctype_pool_str297[sizeof("masaramgondi")]; char uniname2ctype_pool_str301[sizeof("inarrows")]; + char uniname2ctype_pool_str302[sizeof("diacritic")]; char uniname2ctype_pool_str311[sizeof("incyrillic")]; char uniname2ctype_pool_str313[sizeof("incham")]; char uniname2ctype_pool_str315[sizeof("qmark")]; @@ -38266,26 +39420,25 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str335[sizeof("inmasaramgondi")]; char uniname2ctype_pool_str338[sizeof("inthaana")]; char uniname2ctype_pool_str340[sizeof("latin")]; + char uniname2ctype_pool_str341[sizeof("inzanabazarsquare")]; 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_str357[sizeof("inzanabazarsquare")]; char uniname2ctype_pool_str362[sizeof("inscriptionalparthian")]; char uniname2ctype_pool_str366[sizeof("initialpunctuation")]; char uniname2ctype_pool_str373[sizeof("mtei")]; - char uniname2ctype_pool_str376[sizeof("vai")]; - char uniname2ctype_pool_str377[sizeof("vaii")]; 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_str411[sizeof("zs")]; + char uniname2ctype_pool_str409[sizeof("zs")]; char uniname2ctype_pool_str418[sizeof("katakana")]; char uniname2ctype_pool_str426[sizeof("prti")]; char uniname2ctype_pool_str442[sizeof("ascii")]; char uniname2ctype_pool_str445[sizeof("cs")]; + char uniname2ctype_pool_str460[sizeof("decimalnumber")]; char uniname2ctype_pool_str462[sizeof("ps")]; char uniname2ctype_pool_str468[sizeof("mand")]; char uniname2ctype_pool_str470[sizeof("privateuse")]; @@ -38295,26 +39448,28 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str486[sizeof("incjkcompatibilityforms")]; char uniname2ctype_pool_str488[sizeof("inkanaextendeda")]; char uniname2ctype_pool_str491[sizeof("incjkcompatibilityideographs")]; + char uniname2ctype_pool_str494[sizeof("yezidi")]; 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_str519[sizeof("xidcontinue")]; char uniname2ctype_pool_str520[sizeof("inideographicdescriptioncharacters")]; - char uniname2ctype_pool_str535[sizeof("xidcontinue")]; 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_str560[sizeof("inoldnortharabian")]; + char uniname2ctype_pool_str562[sizeof("xidc")]; char uniname2ctype_pool_str565[sizeof("intransportandmapsymbols")]; char uniname2ctype_pool_str566[sizeof("letternumber")]; char uniname2ctype_pool_str568[sizeof("gothic")]; + char uniname2ctype_pool_str569[sizeof("vs")]; char uniname2ctype_pool_str572[sizeof("inlineara")]; char uniname2ctype_pool_str577[sizeof("inmendekikakui")]; - char uniname2ctype_pool_str578[sizeof("xidc")]; char uniname2ctype_pool_str579[sizeof("mongolian")]; char uniname2ctype_pool_str582[sizeof("inmiscellaneousmathematicalsymbolsa")]; char uniname2ctype_pool_str583[sizeof("inspecials")]; @@ -38326,23 +39481,28 @@ struct uniname2ctype_pool_t 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_str613[sizeof("medf")]; char uniname2ctype_pool_str614[sizeof("inadlam")]; char uniname2ctype_pool_str624[sizeof("psalterpahlavi")]; char uniname2ctype_pool_str625[sizeof("incommonindicnumberforms")]; + char uniname2ctype_pool_str629[sizeof("medefaidrin")]; char uniname2ctype_pool_str630[sizeof("lt")]; - char uniname2ctype_pool_str636[sizeof("innewa")]; + char uniname2ctype_pool_str631[sizeof("patternsyntax")]; + char uniname2ctype_pool_str638[sizeof("inshorthandformatcontrols")]; char uniname2ctype_pool_str639[sizeof("sk")]; char uniname2ctype_pool_str642[sizeof("control")]; char uniname2ctype_pool_str645[sizeof("inancientsymbols")]; char uniname2ctype_pool_str647[sizeof("palm")]; char uniname2ctype_pool_str650[sizeof("inlycian")]; + char uniname2ctype_pool_str652[sizeof("xids")]; char uniname2ctype_pool_str657[sizeof("so")]; char uniname2ctype_pool_str660[sizeof("patternwhitespace")]; - char uniname2ctype_pool_str668[sizeof("xids")]; char uniname2ctype_pool_str672[sizeof("inmandaic")]; char uniname2ctype_pool_str675[sizeof("idc")]; char uniname2ctype_pool_str678[sizeof("meroiticcursive")]; - char uniname2ctype_pool_str695[sizeof("inwarangciti")]; + char uniname2ctype_pool_str682[sizeof("innewa")]; + char uniname2ctype_pool_str688[sizeof("dsrt")]; char uniname2ctype_pool_str696[sizeof("sora")]; char uniname2ctype_pool_str697[sizeof("inopticalcharacterrecognition")]; char uniname2ctype_pool_str703[sizeof("inoldsogdian")]; @@ -38353,24 +39513,27 @@ struct uniname2ctype_pool_t 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_str741[sizeof("inwarangciti")]; 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_str765[sizeof("deseret")]; char uniname2ctype_pool_str766[sizeof("samr")]; - char uniname2ctype_pool_str767[sizeof("inwancho")]; char uniname2ctype_pool_str771[sizeof("batak")]; - char uniname2ctype_pool_str772[sizeof("vs")]; char uniname2ctype_pool_str776[sizeof("patws")]; char uniname2ctype_pool_str783[sizeof("samaritan")]; char uniname2ctype_pool_str787[sizeof("idsbinaryoperator")]; + char uniname2ctype_pool_str788[sizeof("lower")]; 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_str806[sizeof("incyrillicextendeda")]; char uniname2ctype_pool_str809[sizeof("insylotinagri")]; + char uniname2ctype_pool_str811[sizeof("intaixuanjingsymbols")]; + char uniname2ctype_pool_str813[sizeof("inwancho")]; char uniname2ctype_pool_str814[sizeof("inugaritic")]; char uniname2ctype_pool_str818[sizeof("incontrolpictures")]; char uniname2ctype_pool_str821[sizeof("inlinearbideograms")]; @@ -38379,22 +39542,23 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str824[sizeof("ital")]; char uniname2ctype_pool_str825[sizeof("inmodifiertoneletters")]; char uniname2ctype_pool_str828[sizeof("inancientgreekmusicalnotation")]; - char uniname2ctype_pool_str834[sizeof("patternsyntax")]; 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_str862[sizeof("oriya")]; char uniname2ctype_pool_str875[sizeof("intaile")]; + char uniname2ctype_pool_str882[sizeof("cuneiform")]; char uniname2ctype_pool_str886[sizeof("inmiscellaneoussymbols")]; + char uniname2ctype_pool_str888[sizeof("lowercase")]; + char uniname2ctype_pool_str891[sizeof("cwcm")]; 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_str918[sizeof("incyrillicextendedc")]; + char uniname2ctype_pool_str920[sizeof("cwcf")]; char uniname2ctype_pool_str924[sizeof("idcontinue")]; char uniname2ctype_pool_str926[sizeof("intamil")]; char uniname2ctype_pool_str928[sizeof("inmultani")]; @@ -38403,42 +39567,39 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str946[sizeof("bali")]; char uniname2ctype_pool_str961[sizeof("blank")]; char uniname2ctype_pool_str963[sizeof("idst")]; + char uniname2ctype_pool_str972[sizeof("modifierletter")]; char uniname2ctype_pool_str974[sizeof("inlydian")]; - char uniname2ctype_pool_str986[sizeof("innewtailue")]; + char uniname2ctype_pool_str991[sizeof("xsux")]; char uniname2ctype_pool_str994[sizeof("bengali")]; char uniname2ctype_pool_str995[sizeof("runr")]; - char uniname2ctype_pool_str1005[sizeof("zl")]; - char uniname2ctype_pool_str1009[sizeof("incyrillicextendeda")]; + char uniname2ctype_pool_str1003[sizeof("zl")]; + char uniname2ctype_pool_str1005[sizeof("inunifiedcanadianaboriginalsyllabics")]; char uniname2ctype_pool_str1010[sizeof("ll")]; char uniname2ctype_pool_str1013[sizeof("indeseret")]; - char uniname2ctype_pool_str1014[sizeof("intaixuanjingsymbols")]; char uniname2ctype_pool_str1015[sizeof("inancientgreeknumbers")]; char uniname2ctype_pool_str1021[sizeof("idstart")]; char uniname2ctype_pool_str1025[sizeof("inmeeteimayekextensions")]; char uniname2ctype_pool_str1028[sizeof("balinese")]; - char uniname2ctype_pool_str1032[sizeof("dia")]; - char uniname2ctype_pool_str1033[sizeof("di")]; + char uniname2ctype_pool_str1032[sizeof("innewtailue")]; 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_str1070[sizeof("zinh")]; + char uniname2ctype_pool_str1068[sizeof("zinh")]; char uniname2ctype_pool_str1072[sizeof("sind")]; - char uniname2ctype_pool_str1080[sizeof("osage")]; + char uniname2ctype_pool_str1074[sizeof("xidstart")]; + char uniname2ctype_pool_str1075[sizeof("xdigit")]; char uniname2ctype_pool_str1081[sizeof("inlatinextendedc")]; - char uniname2ctype_pool_str1085[sizeof("uideo")]; char uniname2ctype_pool_str1087[sizeof("incountingrodnumerals")]; - char uniname2ctype_pool_str1090[sizeof("xidstart")]; - char uniname2ctype_pool_str1091[sizeof("xdigit")]; - char uniname2ctype_pool_str1093[sizeof("osma")]; char uniname2ctype_pool_str1097[sizeof("inkhudawadi")]; char uniname2ctype_pool_str1102[sizeof("inhanifirohingya")]; char uniname2ctype_pool_str1105[sizeof("gong")]; char uniname2ctype_pool_str1107[sizeof("ingrantha")]; char uniname2ctype_pool_str1109[sizeof("bidic")]; + char uniname2ctype_pool_str1116[sizeof("variationselector")]; char uniname2ctype_pool_str1119[sizeof("mong")]; char uniname2ctype_pool_str1120[sizeof("cased")]; - char uniname2ctype_pool_str1121[sizeof("incyrillicextendedc")]; + char uniname2ctype_pool_str1131[sizeof("uideo")]; char uniname2ctype_pool_str1134[sizeof("inhiragana")]; char uniname2ctype_pool_str1140[sizeof("sinhala")]; char uniname2ctype_pool_str1142[sizeof("adlm")]; @@ -38456,7 +39617,6 @@ struct uniname2ctype_pool_t 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")]; @@ -38471,10 +39631,11 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str1198[sizeof("khar")]; char uniname2ctype_pool_str1203[sizeof("inmongolian")]; char uniname2ctype_pool_str1207[sizeof("incherokeesupplement")]; - char uniname2ctype_pool_str1208[sizeof("diacritic")]; char uniname2ctype_pool_str1209[sizeof("manichaean")]; - char uniname2ctype_pool_str1210[sizeof("xsux")]; char uniname2ctype_pool_str1212[sizeof("inolchiki")]; + char uniname2ctype_pool_str1213[sizeof("dogra")]; + char uniname2ctype_pool_str1221[sizeof("lowercaseletter")]; + char uniname2ctype_pool_str1223[sizeof("inkhitansmallscript")]; char uniname2ctype_pool_str1227[sizeof("quotationmark")]; char uniname2ctype_pool_str1231[sizeof("adlam")]; char uniname2ctype_pool_str1232[sizeof("inethiopic")]; @@ -38484,47 +39645,41 @@ struct uniname2ctype_pool_t 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_str1240[sizeof("age=13.0")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ char uniname2ctype_pool_str1243[sizeof("casedletter")]; char uniname2ctype_pool_str1244[sizeof("ingurmukhi")]; - char uniname2ctype_pool_str1245[sizeof("odi")]; char uniname2ctype_pool_str1246[sizeof("incjkunifiedideographsextensiona")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1247[sizeof("age=1.1")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ + char uniname2ctype_pool_str1247[sizeof("inunifiedcanadianaboriginalsyllabicsextended")]; char uniname2ctype_pool_str1248[sizeof("lu")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1249[sizeof("age=4.1")]; - char uniname2ctype_pool_str1250[sizeof("age=2.1")]; - char uniname2ctype_pool_str1251[sizeof("age=4.0")]; - char uniname2ctype_pool_str1252[sizeof("age=2.0")]; - char uniname2ctype_pool_str1253[sizeof("age=9.0")]; + char uniname2ctype_pool_str1250[sizeof("age=1.1")]; + char uniname2ctype_pool_str1252[sizeof("age=9.0")]; + char uniname2ctype_pool_str1253[sizeof("age=2.1")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ char uniname2ctype_pool_str1254[sizeof("intamilsupplement")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1255[sizeof("age=6.1")]; + char uniname2ctype_pool_str1255[sizeof("age=2.0")]; + char uniname2ctype_pool_str1256[sizeof("age=3.1")]; + char uniname2ctype_pool_str1257[sizeof("age=8.0")]; + char uniname2ctype_pool_str1258[sizeof("age=3.0")]; + char uniname2ctype_pool_str1259[sizeof("age=3.2")]; + char uniname2ctype_pool_str1260[sizeof("age=6.1")]; + char uniname2ctype_pool_str1261[sizeof("age=7.0")]; + char uniname2ctype_pool_str1262[sizeof("age=6.0")]; + char uniname2ctype_pool_str1263[sizeof("age=6.2")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1256[sizeof("unknown")]; + char uniname2ctype_pool_str1264[sizeof("dogr")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1257[sizeof("age=6.0")]; - char uniname2ctype_pool_str1258[sizeof("age=6.2")]; - char uniname2ctype_pool_str1259[sizeof("age=3.1")]; - char uniname2ctype_pool_str1260[sizeof("age=8.0")]; - char uniname2ctype_pool_str1261[sizeof("age=3.0")]; - char uniname2ctype_pool_str1262[sizeof("age=3.2")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1263[sizeof("cwt")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1264[sizeof("age=7.0")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1266[sizeof("unassigned")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1267[sizeof("age=6.3")]; - char uniname2ctype_pool_str1268[sizeof("age=5.1")]; - char uniname2ctype_pool_str1270[sizeof("age=5.0")]; - char uniname2ctype_pool_str1271[sizeof("age=5.2")]; + char uniname2ctype_pool_str1265[sizeof("age=5.1")]; + char uniname2ctype_pool_str1266[sizeof("age=6.3")]; + char uniname2ctype_pool_str1267[sizeof("age=5.0")]; + char uniname2ctype_pool_str1268[sizeof("age=5.2")]; + char uniname2ctype_pool_str1269[sizeof("age=4.1")]; + char uniname2ctype_pool_str1271[sizeof("age=4.0")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ char uniname2ctype_pool_str1274[sizeof("ahom")]; + char uniname2ctype_pool_str1278[sizeof("phnx")]; char uniname2ctype_pool_str1282[sizeof("incjkunifiedideographsextensione")]; char uniname2ctype_pool_str1285[sizeof("khmr")]; char uniname2ctype_pool_str1289[sizeof("insinhala")]; @@ -38533,22 +39688,28 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str1300[sizeof("guru")]; char uniname2ctype_pool_str1301[sizeof("sundanese")]; char uniname2ctype_pool_str1306[sizeof("punct")]; + char uniname2ctype_pool_str1309[sizeof("cwt")]; + char uniname2ctype_pool_str1312[sizeof("unassigned")]; char uniname2ctype_pool_str1314[sizeof("paucinhau")]; char uniname2ctype_pool_str1317[sizeof("gurmukhi")]; - char uniname2ctype_pool_str1319[sizeof("variationselector")]; + 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_str1348[sizeof("unknown")]; + char uniname2ctype_pool_str1349[sizeof("chrs")]; + char uniname2ctype_pool_str1352[sizeof("oriya")]; char uniname2ctype_pool_str1354[sizeof("inscriptionalpahlavi")]; - char uniname2ctype_pool_str1355[sizeof("oidc")]; char uniname2ctype_pool_str1358[sizeof("incjkunifiedideographsextensionc")]; char uniname2ctype_pool_str1360[sizeof("cntrl")]; + char uniname2ctype_pool_str1362[sizeof("incjkunifiedideographsextensionf")]; char uniname2ctype_pool_str1365[sizeof("inlatinextendedadditional")]; - char uniname2ctype_pool_str1366[sizeof("decimalnumber")]; + char uniname2ctype_pool_str1366[sizeof("ahex")]; 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_str1376[sizeof("dash")]; char uniname2ctype_pool_str1380[sizeof("n")]; char uniname2ctype_pool_str1384[sizeof("math")]; char uniname2ctype_pool_str1387[sizeof("goth")]; @@ -38559,469 +39720,468 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str1419[sizeof("nko")]; char uniname2ctype_pool_str1420[sizeof("nkoo")]; char uniname2ctype_pool_str1422[sizeof("ingreekandcoptic")]; - char uniname2ctype_pool_str1423[sizeof("olck")]; char uniname2ctype_pool_str1426[sizeof("p")]; char uniname2ctype_pool_str1428[sizeof("grantha")]; - char uniname2ctype_pool_str1434[sizeof("olchiki")]; + char uniname2ctype_pool_str1434[sizeof("xpeo")]; char uniname2ctype_pool_str1438[sizeof("incjkunifiedideographs")]; - char uniname2ctype_pool_str1441[sizeof("zanb")]; + char uniname2ctype_pool_str1439[sizeof("zanb")]; char uniname2ctype_pool_str1442[sizeof("intirhuta")]; - char uniname2ctype_pool_str1445[sizeof("oids")]; char uniname2ctype_pool_str1448[sizeof("inhatran")]; char uniname2ctype_pool_str1449[sizeof("linb")]; - char uniname2ctype_pool_str1450[sizeof("xpeo")]; char uniname2ctype_pool_str1451[sizeof("mult")]; char uniname2ctype_pool_str1454[sizeof("saurashtra")]; char uniname2ctype_pool_str1457[sizeof("kthi")]; char uniname2ctype_pool_str1462[sizeof("inbhaiksuki")]; - char uniname2ctype_pool_str1466[sizeof("olower")]; char uniname2ctype_pool_str1470[sizeof("innabataean")]; char uniname2ctype_pool_str1471[sizeof("inphoenician")]; char uniname2ctype_pool_str1475[sizeof("inkanbun")]; char uniname2ctype_pool_str1476[sizeof("inmeroitichieroglyphs")]; - char uniname2ctype_pool_str1478[sizeof("inkayahli")]; - char uniname2ctype_pool_str1481[sizeof("phnx")]; - char uniname2ctype_pool_str1485[sizeof("inoriya")]; char uniname2ctype_pool_str1489[sizeof("enclosingmark")]; char uniname2ctype_pool_str1495[sizeof("sd")]; char uniname2ctype_pool_str1497[sizeof("inelbasan")]; - char uniname2ctype_pool_str1498[sizeof("wara")]; char uniname2ctype_pool_str1499[sizeof("inenclosedideographicsupplement")]; char uniname2ctype_pool_str1501[sizeof("sidd")]; + char uniname2ctype_pool_str1505[sizeof("hani")]; char uniname2ctype_pool_str1507[sizeof("linearb")]; - char uniname2ctype_pool_str1509[sizeof("hani")]; - char uniname2ctype_pool_str1512[sizeof("han")]; + char uniname2ctype_pool_str1508[sizeof("han")]; + char uniname2ctype_pool_str1509[sizeof("intifinagh")]; char uniname2ctype_pool_str1517[sizeof("inenclosedalphanumericsupplement")]; - char uniname2ctype_pool_str1519[sizeof("medf")]; + char uniname2ctype_pool_str1519[sizeof("hano")]; char uniname2ctype_pool_str1520[sizeof("bidicontrol")]; - char uniname2ctype_pool_str1523[sizeof("hano")]; 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_str1535[sizeof("medefaidrin")]; char uniname2ctype_pool_str1536[sizeof("braille")]; char uniname2ctype_pool_str1537[sizeof("regionalindicator")]; - char uniname2ctype_pool_str1542[sizeof("inlowsurrogates")]; - char uniname2ctype_pool_str1544[sizeof("inshorthandformatcontrols")]; + char uniname2ctype_pool_str1544[sizeof("inkhojki")]; char uniname2ctype_pool_str1547[sizeof("brah")]; - char uniname2ctype_pool_str1548[sizeof("inkhojki")]; + char uniname2ctype_pool_str1548[sizeof("hanunoo")]; char uniname2ctype_pool_str1549[sizeof("inoldhungarian")]; - char uniname2ctype_pool_str1552[sizeof("hanunoo")]; - char uniname2ctype_pool_str1555[sizeof("hira")]; + char uniname2ctype_pool_str1551[sizeof("hira")]; char uniname2ctype_pool_str1557[sizeof("beng")]; char uniname2ctype_pool_str1563[sizeof("emojimodifierbase")]; char uniname2ctype_pool_str1565[sizeof("inarabic")]; - char uniname2ctype_pool_str1567[sizeof("lyci")]; - char uniname2ctype_pool_str1569[sizeof("ahex")]; + char uniname2ctype_pool_str1570[sizeof("osage")]; char uniname2ctype_pool_str1572[sizeof("inherited")]; char uniname2ctype_pool_str1580[sizeof("glag")]; - char uniname2ctype_pool_str1582[sizeof("lycian")]; + char uniname2ctype_pool_str1583[sizeof("osma")]; char uniname2ctype_pool_str1587[sizeof("indogra")]; - char uniname2ctype_pool_str1594[sizeof("dsrt")]; + char uniname2ctype_pool_str1588[sizeof("inlowsurrogates")]; char uniname2ctype_pool_str1597[sizeof("arab")]; - char uniname2ctype_pool_str1602[sizeof("mymr")]; - char uniname2ctype_pool_str1607[sizeof("myanmar")]; 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_str1631[sizeof("takri")]; char uniname2ctype_pool_str1635[sizeof("graphemeextend")]; - char uniname2ctype_pool_str1638[sizeof("invai")]; - char uniname2ctype_pool_str1643[sizeof("cwl")]; char uniname2ctype_pool_str1654[sizeof("ingeometricshapes")]; char uniname2ctype_pool_str1655[sizeof("emojicomponent")]; + char uniname2ctype_pool_str1656[sizeof("softdotted")]; + char uniname2ctype_pool_str1658[sizeof("takri")]; + char uniname2ctype_pool_str1661[sizeof("inyezidi")]; char uniname2ctype_pool_str1662[sizeof("coptic")]; - char uniname2ctype_pool_str1671[sizeof("deseret")]; + char uniname2ctype_pool_str1664[sizeof("inkayahli")]; + char uniname2ctype_pool_str1665[sizeof("invai")]; + char uniname2ctype_pool_str1671[sizeof("inoriya")]; char uniname2ctype_pool_str1675[sizeof("inarabicpresentationformsa")]; - char uniname2ctype_pool_str1676[sizeof("takr")]; 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_str1689[sizeof("cwl")]; char uniname2ctype_pool_str1691[sizeof("shavian")]; - char uniname2ctype_pool_str1692[sizeof("taile")]; char uniname2ctype_pool_str1699[sizeof("insundanesesupplement")]; - char uniname2ctype_pool_str1702[sizeof("inelymaic")]; - char uniname2ctype_pool_str1703[sizeof("insoyombo")]; + char uniname2ctype_pool_str1703[sizeof("takr")]; char uniname2ctype_pool_str1704[sizeof("bhks")]; char uniname2ctype_pool_str1714[sizeof("bhaiksuki")]; - char uniname2ctype_pool_str1716[sizeof("incjkcompatibility")]; + char uniname2ctype_pool_str1719[sizeof("taile")]; char uniname2ctype_pool_str1722[sizeof("inhanunoo")]; char uniname2ctype_pool_str1724[sizeof("intangut")]; + char uniname2ctype_pool_str1727[sizeof("inethiopicextendeda")]; 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_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_str1780[sizeof("cwcf")]; - char uniname2ctype_pool_str1788[sizeof("cuneiform")]; - char uniname2ctype_pool_str1791[sizeof("term")]; + char uniname2ctype_pool_str1779[sizeof("ugar")]; + char uniname2ctype_pool_str1788[sizeof("mymr")]; + char uniname2ctype_pool_str1793[sizeof("myanmar")]; + char uniname2ctype_pool_str1794[sizeof("deva")]; char uniname2ctype_pool_str1806[sizeof("intibetan")]; char uniname2ctype_pool_str1810[sizeof("intags")]; char uniname2ctype_pool_str1811[sizeof("asciihexdigit")]; + char uniname2ctype_pool_str1812[sizeof("devanagari")]; char uniname2ctype_pool_str1813[sizeof("sentenceterminal")]; - char uniname2ctype_pool_str1816[sizeof("inmayannumerals")]; + char uniname2ctype_pool_str1816[sizeof("defaultignorablecodepoint")]; + char uniname2ctype_pool_str1817[sizeof("digit")]; + char uniname2ctype_pool_str1818[sizeof("term")]; char uniname2ctype_pool_str1821[sizeof("nand")]; - char uniname2ctype_pool_str1825[sizeof("patsyn")]; - char uniname2ctype_pool_str1826[sizeof("hatran")]; + char uniname2ctype_pool_str1822[sizeof("hatran")]; char uniname2ctype_pool_str1828[sizeof("inblockelements")]; char uniname2ctype_pool_str1838[sizeof("inornamentaldingbats")]; char uniname2ctype_pool_str1842[sizeof("innumberforms")]; - char uniname2ctype_pool_str1843[sizeof("oldpersian")]; - char uniname2ctype_pool_str1846[sizeof("inshavian")]; + char uniname2ctype_pool_str1845[sizeof("oidc")]; char uniname2ctype_pool_str1848[sizeof("bopo")]; - char uniname2ctype_pool_str1861[sizeof("hatr")]; + char uniname2ctype_pool_str1850[sizeof("hex")]; + char uniname2ctype_pool_str1855[sizeof("ext")]; + char uniname2ctype_pool_str1857[sizeof("hatr")]; char uniname2ctype_pool_str1866[sizeof("caseignorable")]; char uniname2ctype_pool_str1871[sizeof("inoldpersian")]; - char uniname2ctype_pool_str1878[sizeof("modifierletter")]; - char uniname2ctype_pool_str1881[sizeof("cwu")]; - char uniname2ctype_pool_str1891[sizeof("lydi")]; - char uniname2ctype_pool_str1892[sizeof("inbyzantinemusicalsymbols")]; + char uniname2ctype_pool_str1873[sizeof("inshavian")]; + char uniname2ctype_pool_str1876[sizeof("inbyzantinemusicalsymbols")]; + char uniname2ctype_pool_str1879[sizeof("xposixpunct")]; + 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_str1906[sizeof("lydian")]; - char uniname2ctype_pool_str1911[sizeof("inunifiedcanadianaboriginalsyllabics")]; - char uniname2ctype_pool_str1915[sizeof("orkh")]; - char uniname2ctype_pool_str1928[sizeof("inyiradicals")]; + char uniname2ctype_pool_str1913[sizeof("olck")]; + char uniname2ctype_pool_str1924[sizeof("olchiki")]; + char uniname2ctype_pool_str1927[sizeof("cwu")]; char uniname2ctype_pool_str1929[sizeof("inkatakanaphoneticextensions")]; - char uniname2ctype_pool_str1930[sizeof("inethiopicextendeda")]; char uniname2ctype_pool_str1932[sizeof("incoptic")]; + char uniname2ctype_pool_str1935[sizeof("oids")]; char uniname2ctype_pool_str1936[sizeof("inarabicextendeda")]; - char uniname2ctype_pool_str1947[sizeof("oldpermic")]; char uniname2ctype_pool_str1950[sizeof("incjksymbolsandpunctuation")]; - char uniname2ctype_pool_str1951[sizeof("word")]; + char uniname2ctype_pool_str1956[sizeof("olower")]; char uniname2ctype_pool_str1958[sizeof("bopomofo")]; - char uniname2ctype_pool_str1961[sizeof("ogam")]; char uniname2ctype_pool_str1964[sizeof("inlisu")]; char uniname2ctype_pool_str1967[sizeof("inoldpermic")]; char uniname2ctype_pool_str1968[sizeof("innoblock")]; - char uniname2ctype_pool_str1971[sizeof("taiviet")]; + char uniname2ctype_pool_str1976[sizeof("extpict")]; char uniname2ctype_pool_str1985[sizeof("inbraillepatterns")]; 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_str1998[sizeof("taiviet")]; + char uniname2ctype_pool_str2001[sizeof("inphoneticextensions")]; + char uniname2ctype_pool_str2002[sizeof("inmayannumerals")]; 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_str2016[sizeof("newa")]; char uniname2ctype_pool_str2023[sizeof("spacingmark")]; char uniname2ctype_pool_str2024[sizeof("inpalmyrene")]; - char uniname2ctype_pool_str2033[sizeof("cyrl")]; char uniname2ctype_pool_str2043[sizeof("assigned")]; - char uniname2ctype_pool_str2048[sizeof("mlym")]; - char uniname2ctype_pool_str2055[sizeof("malayalam")]; - char uniname2ctype_pool_str2058[sizeof("ext")]; - char uniname2ctype_pool_str2062[sizeof("newtailue")]; + char uniname2ctype_pool_str2049[sizeof("extender")]; + char uniname2ctype_pool_str2062[sizeof("newa")]; 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_str2083[sizeof("indevanagari")]; - char uniname2ctype_pool_str2084[sizeof("avestan")]; - char uniname2ctype_pool_str2085[sizeof("cf")]; - char uniname2ctype_pool_str2093[sizeof("palmyrene")]; + char uniname2ctype_pool_str2092[sizeof("lydian")]; char uniname2ctype_pool_str2095[sizeof("inethiopicsupplement")]; - char uniname2ctype_pool_str2097[sizeof("soyo")]; - char uniname2ctype_pool_str2098[sizeof("xposixpunct")]; - char uniname2ctype_pool_str2102[sizeof("pf")]; char uniname2ctype_pool_str2103[sizeof("sarb")]; - char uniname2ctype_pool_str2109[sizeof("zanabazarsquare")]; - char uniname2ctype_pool_str2110[sizeof("ugaritic")]; - char uniname2ctype_pool_str2112[sizeof("osge")]; - char uniname2ctype_pool_str2114[sizeof("java")]; + char uniname2ctype_pool_str2107[sizeof("zanabazarsquare")]; + char uniname2ctype_pool_str2108[sizeof("newtailue")]; + char uniname2ctype_pool_str2110[sizeof("indevanagari")]; + char uniname2ctype_pool_str2111[sizeof("avestan")]; + char uniname2ctype_pool_str2114[sizeof("inyiradicals")]; char uniname2ctype_pool_str2117[sizeof("sharada")]; - char uniname2ctype_pool_str2119[sizeof("dogra")]; + char uniname2ctype_pool_str2118[sizeof("inphoneticextensionssupplement")]; + char uniname2ctype_pool_str2122[sizeof("deprecated")]; char uniname2ctype_pool_str2135[sizeof("bugi")]; - char uniname2ctype_pool_str2137[sizeof("meroitichieroglyphs")]; + char uniname2ctype_pool_str2137[sizeof("word")]; + char uniname2ctype_pool_str2141[sizeof("java")]; char uniname2ctype_pool_str2145[sizeof("separator")]; char uniname2ctype_pool_str2146[sizeof("ingeorgiansupplement")]; char uniname2ctype_pool_str2149[sizeof("sogd")]; - char uniname2ctype_pool_str2150[sizeof("tale")]; - char uniname2ctype_pool_str2153[sizeof("inunifiedcanadianaboriginalsyllabicsextended")]; - char uniname2ctype_pool_str2161[sizeof("terminalpunctuation")]; + char uniname2ctype_pool_str2156[sizeof("ugaritic")]; + char uniname2ctype_pool_str2162[sizeof("inethiopicextended")]; char uniname2ctype_pool_str2165[sizeof("shrd")]; char uniname2ctype_pool_str2166[sizeof("graph")]; - char uniname2ctype_pool_str2167[sizeof("olditalic")]; - char uniname2ctype_pool_str2170[sizeof("dogr")]; - char uniname2ctype_pool_str2173[sizeof("gujr")]; + char uniname2ctype_pool_str2169[sizeof("gujr")]; + char uniname2ctype_pool_str2177[sizeof("tale")]; + char uniname2ctype_pool_str2178[sizeof("gujarati")]; char uniname2ctype_pool_str2181[sizeof("phag")]; - char uniname2ctype_pool_str2182[sizeof("gujarati")]; + char uniname2ctype_pool_str2188[sizeof("terminalpunctuation")]; char uniname2ctype_pool_str2195[sizeof("inhanguljamo")]; - char uniname2ctype_pool_str2199[sizeof("javanese")]; - char uniname2ctype_pool_str2201[sizeof("taml")]; - char uniname2ctype_pool_str2204[sizeof("inphoneticextensions")]; char uniname2ctype_pool_str2207[sizeof("siddham")]; + char uniname2ctype_pool_str2213[sizeof("ingeorgianextended")]; char uniname2ctype_pool_str2217[sizeof("buginese")]; char uniname2ctype_pool_str2218[sizeof("inmongoliansupplement")]; - char uniname2ctype_pool_str2222[sizeof("invariationselectors")]; + char uniname2ctype_pool_str2219[sizeof("cyrl")]; char uniname2ctype_pool_str2224[sizeof("inhanguljamoextendeda")]; - char uniname2ctype_pool_str2225[sizeof("inverticalforms")]; - char uniname2ctype_pool_str2228[sizeof("syrc")]; + char uniname2ctype_pool_str2226[sizeof("javanese")]; + char uniname2ctype_pool_str2228[sizeof("taml")]; char uniname2ctype_pool_str2229[sizeof("number")]; + char uniname2ctype_pool_str2230[sizeof("incyrillicextendedb")]; + char uniname2ctype_pool_str2234[sizeof("mlym")]; char uniname2ctype_pool_str2235[sizeof("incopticepactnumbers")]; - char uniname2ctype_pool_str2238[sizeof("avst")]; + 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_str2252[sizeof("extender")]; - char uniname2ctype_pool_str2258[sizeof("intaiviet")]; - char uniname2ctype_pool_str2260[sizeof("hex")]; - char uniname2ctype_pool_str2268[sizeof("incjkunifiedideographsextensionf")]; - char uniname2ctype_pool_str2271[sizeof("other")]; - char uniname2ctype_pool_str2272[sizeof("otheridcontinue")]; - char uniname2ctype_pool_str2278[sizeof("shaw")]; - char uniname2ctype_pool_str2282[sizeof("dash")]; - char uniname2ctype_pool_str2285[sizeof("othernumber")]; - char uniname2ctype_pool_str2294[sizeof("orya")]; - char uniname2ctype_pool_str2302[sizeof("invedicextensions")]; - char uniname2ctype_pool_str2305[sizeof("sgnw")]; + char uniname2ctype_pool_str2249[sizeof("invariationselectors")]; + char uniname2ctype_pool_str2252[sizeof("inverticalforms")]; + char uniname2ctype_pool_str2265[sizeof("avst")]; + char uniname2ctype_pool_str2279[sizeof("palmyrene")]; + char uniname2ctype_pool_str2283[sizeof("soyo")]; + char uniname2ctype_pool_str2285[sizeof("intaiviet")]; char uniname2ctype_pool_str2312[sizeof("caucasianalbanian")]; char uniname2ctype_pool_str2315[sizeof("inmathematicalalphanumericsymbols")]; - char uniname2ctype_pool_str2321[sizeof("inphoneticextensionssupplement")]; - char uniname2ctype_pool_str2339[sizeof("invariationselectorssupplement")]; + char uniname2ctype_pool_str2316[sizeof("incjkunifiedideographsextensiong")]; + char uniname2ctype_pool_str2323[sizeof("meroitichieroglyphs")]; + char uniname2ctype_pool_str2324[sizeof("shaw")]; + char uniname2ctype_pool_str2329[sizeof("invedicextensions")]; + char uniname2ctype_pool_str2333[sizeof("oldpersian")]; char uniname2ctype_pool_str2343[sizeof("induployan")]; - char uniname2ctype_pool_str2344[sizeof("syriac")]; - char uniname2ctype_pool_str2357[sizeof("oalpha")]; + char uniname2ctype_pool_str2351[sizeof("sgnw")]; char uniname2ctype_pool_str2361[sizeof("innyiakengpuachuehmong")]; char uniname2ctype_pool_str2364[sizeof("incombiningdiacriticalmarks")]; - char uniname2ctype_pool_str2365[sizeof("inethiopicextended")]; + char uniname2ctype_pool_str2366[sizeof("invariationselectorssupplement")]; char uniname2ctype_pool_str2373[sizeof("nl")]; char uniname2ctype_pool_str2374[sizeof("incombiningdiacriticalmarksforsymbols")]; - char uniname2ctype_pool_str2375[sizeof("khudawadi")]; - char uniname2ctype_pool_str2378[sizeof("otheralphabetic")]; - char uniname2ctype_pool_str2389[sizeof("oldhungarian")]; - char uniname2ctype_pool_str2396[sizeof("incurrencysymbols")]; char uniname2ctype_pool_str2397[sizeof("incjkradicalssupplement")]; char uniname2ctype_pool_str2398[sizeof("inglagolitic")]; - char uniname2ctype_pool_str2415[sizeof("intifinagh")]; - char uniname2ctype_pool_str2416[sizeof("ingeorgianextended")]; + char uniname2ctype_pool_str2405[sizeof("orkh")]; + char uniname2ctype_pool_str2414[sizeof("syrc")]; + char uniname2ctype_pool_str2421[sizeof("khudawadi")]; char uniname2ctype_pool_str2427[sizeof("surrogate")]; - char uniname2ctype_pool_str2433[sizeof("incyrillicextendedb")]; + char uniname2ctype_pool_str2431[sizeof("extendedpictographic")]; + char uniname2ctype_pool_str2437[sizeof("oldpermic")]; char uniname2ctype_pool_str2440[sizeof("ethi")]; - char uniname2ctype_pool_str2451[sizeof("titlecaseletter")]; + char uniname2ctype_pool_str2451[sizeof("ogam")]; char uniname2ctype_pool_str2454[sizeof("rohg")]; - char uniname2ctype_pool_str2458[sizeof("inmeroiticcursive")]; char uniname2ctype_pool_str2460[sizeof("idstrinaryoperator")]; char uniname2ctype_pool_str2470[sizeof("inphagspa")]; char uniname2ctype_pool_str2475[sizeof("lepcha")]; + char uniname2ctype_pool_str2478[sizeof("titlecaseletter")]; char uniname2ctype_pool_str2479[sizeof("intagalog")]; - char uniname2ctype_pool_str2480[sizeof("mathsymbol")]; char uniname2ctype_pool_str2481[sizeof("incombiningdiacriticalmarkssupplement")]; + char uniname2ctype_pool_str2485[sizeof("inmeroiticcursive")]; char uniname2ctype_pool_str2506[sizeof("inbrahmi")]; char uniname2ctype_pool_str2513[sizeof("insymbolsandpictographsextendeda")]; - char uniname2ctype_pool_str2519[sizeof("inlinearbsyllabary")]; - char uniname2ctype_pool_str2529[sizeof("oldturkic")]; + char uniname2ctype_pool_str2530[sizeof("syriac")]; + char uniname2ctype_pool_str2533[sizeof("modifiersymbol")]; char uniname2ctype_pool_str2534[sizeof("inbengali")]; - char uniname2ctype_pool_str2540[sizeof("wancho")]; - char uniname2ctype_pool_str2542[sizeof("osmanya")]; + char uniname2ctype_pool_str2536[sizeof("inhalfwidthandfullwidthforms")]; char uniname2ctype_pool_str2548[sizeof("buhd")]; - char uniname2ctype_pool_str2552[sizeof("insmallformvariants")]; - char uniname2ctype_pool_str2561[sizeof("indevanagariextended")]; - char uniname2ctype_pool_str2562[sizeof("softdotted")]; + char uniname2ctype_pool_str2562[sizeof("mahj")]; char uniname2ctype_pool_str2564[sizeof("inbuginese")]; - char uniname2ctype_pool_str2566[sizeof("mahj")]; char uniname2ctype_pool_str2567[sizeof("inlatin1supplement")]; char uniname2ctype_pool_str2570[sizeof("ingothic")]; - char uniname2ctype_pool_str2575[sizeof("mahajani")]; - char uniname2ctype_pool_str2576[sizeof("hang")]; - char uniname2ctype_pool_str2579[sizeof("sylo")]; - char uniname2ctype_pool_str2586[sizeof("warangciti")]; - char uniname2ctype_pool_str2595[sizeof("ingujarati")]; - char uniname2ctype_pool_str2603[sizeof("tirhuta")]; + char uniname2ctype_pool_str2571[sizeof("mahajani")]; + char uniname2ctype_pool_str2572[sizeof("hang")]; + char uniname2ctype_pool_str2576[sizeof("ebase")]; + char uniname2ctype_pool_str2579[sizeof("insmallformvariants")]; + char uniname2ctype_pool_str2582[sizeof("incurrencysymbols")]; + char uniname2ctype_pool_str2588[sizeof("indevanagariextended")]; + char uniname2ctype_pool_str2589[sizeof("divesakuru")]; + char uniname2ctype_pool_str2591[sizeof("ingujarati")]; + char uniname2ctype_pool_str2602[sizeof("osge")]; char uniname2ctype_pool_str2606[sizeof("incombiningdiacriticalmarksextended")]; char uniname2ctype_pool_str2609[sizeof("spaceseparator")]; - char uniname2ctype_pool_str2614[sizeof("ingunjalagondi")]; - char uniname2ctype_pool_str2624[sizeof("wcho")]; - char uniname2ctype_pool_str2631[sizeof("hiragana")]; - char uniname2ctype_pool_str2634[sizeof("extendedpictographic")]; - char uniname2ctype_pool_str2643[sizeof("inrejang")]; - char uniname2ctype_pool_str2644[sizeof("inottomansiyaqnumbers")]; + char uniname2ctype_pool_str2610[sizeof("ingunjalagondi")]; + char uniname2ctype_pool_str2611[sizeof("dupl")]; + char uniname2ctype_pool_str2627[sizeof("hiragana")]; + char uniname2ctype_pool_str2630[sizeof("tirhuta")]; + char uniname2ctype_pool_str2639[sizeof("inrejang")]; + char uniname2ctype_pool_str2644[sizeof("dashpunctuation")]; char uniname2ctype_pool_str2648[sizeof("nchar")]; - char uniname2ctype_pool_str2650[sizeof("cyrillic")]; - char uniname2ctype_pool_str2653[sizeof("khoj")]; + char uniname2ctype_pool_str2649[sizeof("khoj")]; char uniname2ctype_pool_str2656[sizeof("inlimbu")]; - char uniname2ctype_pool_str2663[sizeof("hmng")]; - char uniname2ctype_pool_str2665[sizeof("thaa")]; - char uniname2ctype_pool_str2668[sizeof("thai")]; + char uniname2ctype_pool_str2657[sizeof("olditalic")]; + char uniname2ctype_pool_str2659[sizeof("hmng")]; + char uniname2ctype_pool_str2666[sizeof("mathsymbol")]; char uniname2ctype_pool_str2670[sizeof("incjkunifiedideographsextensionb")]; - char uniname2ctype_pool_str2673[sizeof("deva")]; - char uniname2ctype_pool_str2676[sizeof("thaana")]; char uniname2ctype_pool_str2688[sizeof("phagspa")]; - char uniname2ctype_pool_str2691[sizeof("devanagari")]; - char uniname2ctype_pool_str2692[sizeof("tang")]; + char uniname2ctype_pool_str2692[sizeof("thaa")]; char uniname2ctype_pool_str2694[sizeof("currencysymbol")]; - char uniname2ctype_pool_str2698[sizeof("tagbanwa")]; - char uniname2ctype_pool_str2701[sizeof("inenclosedcjklettersandmonths")]; - char uniname2ctype_pool_str2702[sizeof("tamil")]; - char uniname2ctype_pool_str2721[sizeof("tirh")]; - char uniname2ctype_pool_str2723[sizeof("digit")]; - char uniname2ctype_pool_str2732[sizeof("talu")]; - char uniname2ctype_pool_str2747[sizeof("zp")]; + char uniname2ctype_pool_str2695[sizeof("thai")]; + char uniname2ctype_pool_str2697[sizeof("inenclosedcjklettersandmonths")]; + char uniname2ctype_pool_str2703[sizeof("thaana")]; + char uniname2ctype_pool_str2704[sizeof("hanifirohingya")]; + char uniname2ctype_pool_str2705[sizeof("inlinearbsyllabary")]; + char uniname2ctype_pool_str2719[sizeof("tang")]; + char uniname2ctype_pool_str2725[sizeof("tagbanwa")]; + char uniname2ctype_pool_str2726[sizeof("wancho")]; + char uniname2ctype_pool_str2729[sizeof("tamil")]; + char uniname2ctype_pool_str2745[sizeof("zp")]; + char uniname2ctype_pool_str2748[sizeof("tirh")]; char uniname2ctype_pool_str2750[sizeof("inpaucinhau")]; - char uniname2ctype_pool_str2760[sizeof("taitham")]; - char uniname2ctype_pool_str2764[sizeof("otherlowercase")]; - char uniname2ctype_pool_str2768[sizeof("telu")]; + char uniname2ctype_pool_str2759[sizeof("talu")]; + char uniname2ctype_pool_str2761[sizeof("other")]; + char uniname2ctype_pool_str2762[sizeof("otheridcontinue")]; + char uniname2ctype_pool_str2765[sizeof("sylo")]; char uniname2ctype_pool_str2769[sizeof("inaegeannumbers")]; - char uniname2ctype_pool_str2777[sizeof("otherletter")]; - char uniname2ctype_pool_str2780[sizeof("whitespace")]; + char uniname2ctype_pool_str2772[sizeof("warangciti")]; + char uniname2ctype_pool_str2775[sizeof("othernumber")]; + char uniname2ctype_pool_str2787[sizeof("taitham")]; char uniname2ctype_pool_str2793[sizeof("nonspacingmark")]; + char uniname2ctype_pool_str2795[sizeof("telu")]; + char uniname2ctype_pool_str2810[sizeof("wcho")]; char uniname2ctype_pool_str2816[sizeof("graphemeclusterbreak=spacingmark")]; char uniname2ctype_pool_str2821[sizeof("inletterlikesymbols")]; + char uniname2ctype_pool_str2824[sizeof("tifinagh")]; + char uniname2ctype_pool_str2830[sizeof("inottomansiyaqnumbers")]; char uniname2ctype_pool_str2834[sizeof("intagbanwa")]; - char uniname2ctype_pool_str2841[sizeof("oldsogdian")]; - char uniname2ctype_pool_str2848[sizeof("otheridstart")]; + char uniname2ctype_pool_str2835[sizeof("tfng")]; + 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_str2862[sizeof("tangut")]; char uniname2ctype_pool_str2867[sizeof("graphemeclusterbreak=regionalindicator")]; + char uniname2ctype_pool_str2868[sizeof("otheralphabetic")]; char uniname2ctype_pool_str2871[sizeof("noncharactercodepoint")]; - char uniname2ctype_pool_str2883[sizeof("otheruppercase")]; - char uniname2ctype_pool_str2885[sizeof("rjng")]; - char uniname2ctype_pool_str2886[sizeof("sylotinagri")]; + char uniname2ctype_pool_str2879[sizeof("oldhungarian")]; + char uniname2ctype_pool_str2881[sizeof("rjng")]; + char uniname2ctype_pool_str2885[sizeof("changeswhencasefolded")]; + char uniname2ctype_pool_str2886[sizeof("insymbolsforlegacycomputing")]; + char uniname2ctype_pool_str2889[sizeof("tangut")]; + char uniname2ctype_pool_str2899[sizeof("dep")]; char uniname2ctype_pool_str2904[sizeof("inhangulsyllables")]; char uniname2ctype_pool_str2905[sizeof("emojipresentation")]; - char uniname2ctype_pool_str2906[sizeof("inindicsiyaqnumbers")]; + char uniname2ctype_pool_str2907[sizeof("epres")]; char uniname2ctype_pool_str2909[sizeof("inbassavah")]; - char uniname2ctype_pool_str2912[sizeof("ogrext")]; - char uniname2ctype_pool_str2926[sizeof("othersymbol")]; - char uniname2ctype_pool_str2938[sizeof("oupper")]; + char uniname2ctype_pool_str2915[sizeof("graphemeclusterbreak=lf")]; char uniname2ctype_pool_str2941[sizeof("inbuhid")]; - char uniname2ctype_pool_str2963[sizeof("hmnp")]; + char uniname2ctype_pool_str2959[sizeof("hmnp")]; 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_str2993[sizeof("omath")]; - char uniname2ctype_pool_str3000[sizeof("any")]; 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_str3012[sizeof("hebr")]; - char uniname2ctype_pool_str3028[sizeof("deprecated")]; + char uniname2ctype_pool_str3008[sizeof("hebr")]; + char uniname2ctype_pool_str3019[sizeof("oldturkic")]; char uniname2ctype_pool_str3045[sizeof("inarabicmathematicalalphabeticsymbols")]; - char uniname2ctype_pool_str3055[sizeof("inprivateusearea")]; - char uniname2ctype_pool_str3089[sizeof("kayahli")]; - char uniname2ctype_pool_str3098[sizeof("inplayingcards")]; + char uniname2ctype_pool_str3053[sizeof("khitansmallscript")]; + char uniname2ctype_pool_str3072[sizeof("sylotinagri")]; + char uniname2ctype_pool_str3079[sizeof("hexdigit")]; + char uniname2ctype_pool_str3082[sizeof("inprivateusearea")]; char uniname2ctype_pool_str3099[sizeof("inarabicpresentationformsb")]; - char uniname2ctype_pool_str3100[sizeof("ogham")]; - char uniname2ctype_pool_str3101[sizeof("elym")]; char uniname2ctype_pool_str3107[sizeof("graphemeclusterbreak=t")]; char uniname2ctype_pool_str3109[sizeof("graphemeclusterbreak=lvt")]; char uniname2ctype_pool_str3111[sizeof("nbat")]; + char uniname2ctype_pool_str3122[sizeof("hangul")]; char uniname2ctype_pool_str3125[sizeof("nabataean")]; - char uniname2ctype_pool_str3126[sizeof("hangul")]; - char uniname2ctype_pool_str3134[sizeof("elymaic")]; - char uniname2ctype_pool_str3158[sizeof("inhebrew")]; - char uniname2ctype_pool_str3165[sizeof("injavanese")]; - char uniname2ctype_pool_str3169[sizeof("symbol")]; + char uniname2ctype_pool_str3142[sizeof("intangutsupplement")]; char uniname2ctype_pool_str3176[sizeof("inmathematicaloperators")]; char uniname2ctype_pool_str3180[sizeof("inarabicsupplement")]; - char uniname2ctype_pool_str3185[sizeof("cypriot")]; - char uniname2ctype_pool_str3194[sizeof("hung")]; - char uniname2ctype_pool_str3205[sizeof("wspace")]; + char uniname2ctype_pool_str3188[sizeof("injavanese")]; + char uniname2ctype_pool_str3190[sizeof("hung")]; + char uniname2ctype_pool_str3199[sizeof("ogrext")]; + char uniname2ctype_pool_str3204[sizeof("inhebrew")]; char uniname2ctype_pool_str3209[sizeof("changeswhenlowercased")]; char uniname2ctype_pool_str3215[sizeof("elbasan")]; - char uniname2ctype_pool_str3218[sizeof("hluw")]; + 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("oldnortharabian")]; - char uniname2ctype_pool_str3266[sizeof("inyijinghexagramsymbols")]; - char uniname2ctype_pool_str3286[sizeof("hexdigit")]; + char uniname2ctype_pool_str3254[sizeof("otherlowercase")]; + char uniname2ctype_pool_str3260[sizeof("hluw")]; + 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_str3309[sizeof("bassavah")]; - char uniname2ctype_pool_str3317[sizeof("otherdefaultignorablecodepoint")]; + 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_str3336[sizeof("bassavah")]; + char uniname2ctype_pool_str3338[sizeof("otheridstart")]; char uniname2ctype_pool_str3348[sizeof("insupplementalarrowsa")]; - char uniname2ctype_pool_str3349[sizeof("inyisyllables")]; - char uniname2ctype_pool_str3351[sizeof("tibt")]; - char uniname2ctype_pool_str3360[sizeof("othermath")]; - char uniname2ctype_pool_str3363[sizeof("tibetan")]; - char uniname2ctype_pool_str3365[sizeof("inmahjongtiles")]; - char uniname2ctype_pool_str3433[sizeof("signwriting")]; + char uniname2ctype_pool_str3355[sizeof("symbol")]; + char uniname2ctype_pool_str3361[sizeof("inmahjongtiles")]; + char uniname2ctype_pool_str3371[sizeof("cypriot")]; + char uniname2ctype_pool_str3372[sizeof("any")]; + char uniname2ctype_pool_str3373[sizeof("otheruppercase")]; + char uniname2ctype_pool_str3376[sizeof("indivesakuru")]; + char uniname2ctype_pool_str3378[sizeof("tibt")]; + char uniname2ctype_pool_str3390[sizeof("tibetan")]; + char uniname2ctype_pool_str3391[sizeof("wspace")]; + char uniname2ctype_pool_str3396[sizeof("inindicsiyaqnumbers")]; + char uniname2ctype_pool_str3416[sizeof("othersymbol")]; + char uniname2ctype_pool_str3428[sizeof("oupper")]; char uniname2ctype_pool_str3436[sizeof("nushu")]; - char uniname2ctype_pool_str3439[sizeof("modifiersymbol")]; - char uniname2ctype_pool_str3442[sizeof("inhalfwidthandfullwidthforms")]; - char uniname2ctype_pool_str3458[sizeof("upper")]; + char uniname2ctype_pool_str3448[sizeof("inyijinghexagramsymbols")]; char uniname2ctype_pool_str3460[sizeof("insupplementalarrowsc")]; + char uniname2ctype_pool_str3479[sizeof("signwriting")]; + char uniname2ctype_pool_str3483[sizeof("omath")]; + char uniname2ctype_pool_str3504[sizeof("upper")]; char uniname2ctype_pool_str3511[sizeof("insupplementalmathematicaloperators")]; - char uniname2ctype_pool_str3512[sizeof("incypriotsyllabary")]; - char uniname2ctype_pool_str3517[sizeof("dupl")]; - char uniname2ctype_pool_str3531[sizeof("tavt")]; char uniname2ctype_pool_str3532[sizeof("inpahawhhmong")]; char uniname2ctype_pool_str3533[sizeof("alphabetic")]; - char uniname2ctype_pool_str3550[sizeof("dashpunctuation")]; - char uniname2ctype_pool_str3558[sizeof("uppercase")]; - char uniname2ctype_pool_str3613[sizeof("soyombo")]; - char uniname2ctype_pool_str3614[sizeof("hanifirohingya")]; - char uniname2ctype_pool_str3616[sizeof("otherpunctuation")]; - char uniname2ctype_pool_str3628[sizeof("defaultignorablecodepoint")]; + char uniname2ctype_pool_str3585[sizeof("tavt")]; + char uniname2ctype_pool_str3590[sizeof("ogham")]; + char uniname2ctype_pool_str3604[sizeof("uppercase")]; char uniname2ctype_pool_str3648[sizeof("inhanguljamoextendedb")]; char uniname2ctype_pool_str3664[sizeof("aghb")]; - char uniname2ctype_pool_str3703[sizeof("tifinagh")]; + char uniname2ctype_pool_str3698[sizeof("incypriotsyllabary")]; char uniname2ctype_pool_str3705[sizeof("inlatinextendedb")]; - char uniname2ctype_pool_str3714[sizeof("tfng")]; + char uniname2ctype_pool_str3721[sizeof("inyisyllables")]; + char uniname2ctype_pool_str3744[sizeof("oldnortharabian")]; + char uniname2ctype_pool_str3765[sizeof("duployan")]; char uniname2ctype_pool_str3766[sizeof("inhighprivateusesurrogates")]; - char uniname2ctype_pool_str3791[sizeof("changeswhencasefolded")]; - char uniname2ctype_pool_str3805[sizeof("dep")]; - char uniname2ctype_pool_str3819[sizeof("oldsoutharabian")]; - char uniname2ctype_pool_str3821[sizeof("graphemeclusterbreak=lf")]; - char uniname2ctype_pool_str3842[sizeof("pahawhhmong")]; - char uniname2ctype_pool_str3845[sizeof("unifiedideograph")]; - char uniname2ctype_pool_str3891[sizeof("uppercaseletter")]; + char uniname2ctype_pool_str3799[sizeof("soyombo")]; + char uniname2ctype_pool_str3807[sizeof("otherdefaultignorablecodepoint")]; + char uniname2ctype_pool_str3850[sizeof("othermath")]; + char uniname2ctype_pool_str3884[sizeof("inbopomofoextended")]; + char uniname2ctype_pool_str3888[sizeof("pahawhhmong")]; + char uniname2ctype_pool_str3891[sizeof("unifiedideograph")]; char uniname2ctype_pool_str3924[sizeof("insupplementalpunctuation")]; + char uniname2ctype_pool_str3937[sizeof("uppercaseletter")]; char uniname2ctype_pool_str3942[sizeof("ethiopic")]; + char uniname2ctype_pool_str3949[sizeof("ecomp")]; char uniname2ctype_pool_str3976[sizeof("inglagoliticsupplement")]; - char uniname2ctype_pool_str3995[sizeof("rejang")]; - char uniname2ctype_pool_str4087[sizeof("inbopomofoextended")]; - char uniname2ctype_pool_str4109[sizeof("tagb")]; - char uniname2ctype_pool_str4137[sizeof("othergraphemeextend")]; - char uniname2ctype_pool_str4162[sizeof("inegyptianhieroglyphs")]; - char uniname2ctype_pool_str4175[sizeof("inegyptianhieroglyphformatcontrols")]; - char uniname2ctype_pool_str4203[sizeof("hebrew")]; - char uniname2ctype_pool_str4254[sizeof("tglg")]; - char uniname2ctype_pool_str4276[sizeof("tagalog")]; - char uniname2ctype_pool_str4291[sizeof("graphemeclusterbreak=zwj")]; - char uniname2ctype_pool_str4321[sizeof("zyyy")]; - char uniname2ctype_pool_str4360[sizeof("hyphen")]; - char uniname2ctype_pool_str4397[sizeof("inboxdrawing")]; - char uniname2ctype_pool_str4405[sizeof("graphemeclusterbreak=v")]; - char uniname2ctype_pool_str4406[sizeof("graphemeclusterbreak=lv")]; - char uniname2ctype_pool_str4460[sizeof("telugu")]; - char uniname2ctype_pool_str4485[sizeof("duployan")]; - char uniname2ctype_pool_str4528[sizeof("openpunctuation")]; + char uniname2ctype_pool_str3991[sizeof("rejang")]; + char uniname2ctype_pool_str4106[sizeof("otherpunctuation")]; + char uniname2ctype_pool_str4136[sizeof("tagb")]; + char uniname2ctype_pool_str4194[sizeof("inboxdrawing")]; + char uniname2ctype_pool_str4281[sizeof("tglg")]; + char uniname2ctype_pool_str4287[sizeof("graphemeclusterbreak=zwj")]; + char uniname2ctype_pool_str4291[sizeof("hebrew")]; + char uniname2ctype_pool_str4303[sizeof("tagalog")]; + char uniname2ctype_pool_str4309[sizeof("oldsoutharabian")]; + char uniname2ctype_pool_str4348[sizeof("inegyptianhieroglyphs")]; + char uniname2ctype_pool_str4361[sizeof("inegyptianhieroglyphformatcontrols")]; + char uniname2ctype_pool_str4432[sizeof("graphemeclusterbreak=v")]; + char uniname2ctype_pool_str4433[sizeof("graphemeclusterbreak=lv")]; + char uniname2ctype_pool_str4487[sizeof("telugu")]; + char uniname2ctype_pool_str4542[sizeof("hyphen")]; + char uniname2ctype_pool_str4627[sizeof("othergraphemeextend")]; char uniname2ctype_pool_str4674[sizeof("insupplementaryprivateuseareaa")]; char uniname2ctype_pool_str4683[sizeof("inhighsurrogates")]; char uniname2ctype_pool_str4772[sizeof("insupplementalarrowsb")]; - char uniname2ctype_pool_str4948[sizeof("insupplementalsymbolsandpictographs")]; - char uniname2ctype_pool_str4955[sizeof("egyp")]; + char uniname2ctype_pool_str4877[sizeof("zyyy")]; char uniname2ctype_pool_str4986[sizeof("inhangulcompatibilityjamo")]; - char uniname2ctype_pool_str5114[sizeof("nyiakengpuachuehmong")]; - char uniname2ctype_pool_str5608[sizeof("egyptianhieroglyphs")]; + char uniname2ctype_pool_str5018[sizeof("openpunctuation")]; + 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")]; #endif /* USE_UNICODE_PROPERTIES */ }; @@ -39030,10 +40190,11 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = #ifndef USE_UNICODE_PROPERTIES "word", #else /* USE_UNICODE_PROPERTIES */ + "z", "yi", + "zzzz", "yiii", "lana", - "z", "lina", "maka", "mani", @@ -39043,11 +40204,11 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "ci", "lao", "laoo", + "yezi", "inkannada", "cn", "pi", "innko", - "zzzz", "gran", "co", "lineara", @@ -39066,10 +40227,13 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "geor", "greek", "gonm", + "dia", + "di", "mendekikakui", "pe", "mero", "inosmanya", + "diak", "cakm", "inmanichaean", "inmro", @@ -39079,6 +40243,8 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "mandaic", "meeteimayek", "inarmenian", + "vai", + "vaii", "inmyanmar", "inmakasar", "common", @@ -39091,6 +40257,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "qaai", "inahom", "merc", + "inchorasmian", "combiningmark", "lc", "perm", @@ -39103,6 +40270,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "armn", "incherokee", "prependedconcatenationmark", + "cf", "incuneiform", "inavestan", "inipaextensions", @@ -39110,9 +40278,11 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "armenian", "insharada", "inmarchen", + "pf", "makasar", "masaramgondi", "inarrows", + "diacritic", "incyrillic", "incham", "qmark", @@ -39123,17 +40293,15 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "inmasaramgondi", "inthaana", "latin", + "inzanabazarsquare", "inthai", "lineseparator", "pcm", "inkatakana", "inkaithi", - "inzanabazarsquare", "inscriptionalparthian", "initialpunctuation", "mtei", - "vai", - "vaii", "inkhmersymbols", "insyriac", "intakri", @@ -39143,6 +40311,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "prti", "ascii", "cs", + "decimalnumber", "ps", "mand", "privateuse", @@ -39152,26 +40321,28 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "incjkcompatibilityforms", "inkanaextendeda", "incjkcompatibilityideographs", + "yezidi", "brai", "mend", "ideo", "letter", "l", "inmeeteimayek", - "inideographicdescriptioncharacters", "xidcontinue", + "inideographicdescriptioncharacters", "knda", "innandinagari", "kannada", "inmodi", "inlao", "inoldnortharabian", + "xidc", "intransportandmapsymbols", "letternumber", "gothic", + "vs", "inlineara", "inmendekikakui", - "xidc", "mongolian", "inmiscellaneousmathematicalsymbolsa", "inspecials", @@ -39183,23 +40354,28 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "inmedefaidrin", "inchesssymbols", "incjkcompatibilityideographssupplement", + "kits", + "medf", "inadlam", "psalterpahlavi", "incommonindicnumberforms", + "medefaidrin", "lt", - "innewa", + "patternsyntax", + "inshorthandformatcontrols", "sk", "control", "inancientsymbols", "palm", "inlycian", + "xids", "so", "patternwhitespace", - "xids", "inmandaic", "idc", "meroiticcursive", - "inwarangciti", + "innewa", + "dsrt", "sora", "inopticalcharacterrecognition", "inoldsogdian", @@ -39215,18 +40391,18 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "alpha", #else /* USE_UNICODE_PROPERTIES */ "intaitham", - "lower", + "inwarangciti", "joinc", "inoldsoutharabian", "incjkstrokes", "batk", + "deseret", "samr", - "inwancho", "batak", - "vs", "patws", "samaritan", "idsbinaryoperator", + "lower", "pauc", "insmallkanaextension", "sm", @@ -39234,7 +40410,10 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = #endif /* USE_UNICODE_PROPERTIES */ "alnum", #ifdef USE_UNICODE_PROPERTIES + "incyrillicextendeda", "insylotinagri", + "intaixuanjingsymbols", + "inwancho", "inugaritic", "incontrolpictures", "inlinearbideograms", @@ -39243,22 +40422,23 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "ital", "inmodifiertoneletters", "inancientgreekmusicalnotation", - "patternsyntax", "lisu", - "lowercase", - "cwcm", "sc", "bass", "ids", "inlatinextendeda", - "oriya", "intaile", + "cuneiform", "inmiscellaneoussymbols", + "lowercase", + "cwcm", "inmiscellaneoussymbolsandarrows", "incaucasianalbanian", "inmiscellaneoussymbolsandpictographs", "inoldturkic", "insaurashtra", + "incyrillicextendedc", + "cwcf", "idcontinue", "intamil", "inmultani", @@ -39267,31 +40447,26 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "bali", "blank", "idst", + "modifierletter", "inlydian", - "innewtailue", + "xsux", "bengali", "runr", "zl", - "incyrillicextendeda", + "inunifiedcanadianaboriginalsyllabics", "ll", "indeseret", - "intaixuanjingsymbols", "inancientgreeknumbers", "idstart", "inmeeteimayekextensions", "balinese", - "dia", - "di", + "innewtailue", "inspacingmodifierletters", "inearlydynasticcuneiform", "plrd", "canadianaboriginal", "zinh", "sind", - "osage", - "inlatinextendedc", - "uideo", - "incountingrodnumerals", "xidstart", #endif /* USE_UNICODE_PROPERTIES */ "xdigit", @@ -39299,15 +40474,17 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "upper", "ascii", #else /* USE_UNICODE_PROPERTIES */ - "osma", + "inlatinextendedc", + "incountingrodnumerals", "inkhudawadi", "inhanifirohingya", "gong", "ingrantha", "bidic", + "variationselector", "mong", "cased", - "incyrillicextendedc", + "uideo", "inhiragana", "sinhala", "adlm", @@ -39325,7 +40502,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "ingeneralpunctuation", "inmahajani", "incyrillicsupplement", - "lowercaseletter", "marchen", "graphemelink", "ingeorgian", @@ -39340,10 +40516,11 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "khar", "inmongolian", "incherokeesupplement", - "diacritic", "manichaean", - "xsux", "inolchiki", + "dogra", + "lowercaseletter", + "inkhitansmallscript", "quotationmark", "adlam", "inethiopic", @@ -39353,47 +40530,41 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "age=12.1", "age=10.0", "age=12.0", + "age=13.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ "casedletter", "ingurmukhi", - "odi", "incjkunifiedideographsextensiona", -#ifdef USE_UNICODE_AGE_PROPERTIES - "age=1.1", -#endif /* USE_UNICODE_AGE_PROPERTIES */ + "inunifiedcanadianaboriginalsyllabicsextended", "lu", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=4.1", - "age=2.1", - "age=4.0", - "age=2.0", + "age=1.1", "age=9.0", + "age=2.1", #endif /* USE_UNICODE_AGE_PROPERTIES */ "intamilsupplement", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=6.1", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "unknown", -#ifdef USE_UNICODE_AGE_PROPERTIES - "age=6.0", - "age=6.2", + "age=2.0", "age=3.1", "age=8.0", "age=3.0", "age=3.2", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "cwt", -#ifdef USE_UNICODE_AGE_PROPERTIES + "age=6.1", "age=7.0", + "age=6.0", + "age=6.2", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "unassigned", + "dogr", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=6.3", "age=5.1", + "age=6.3", "age=5.0", "age=5.2", + "age=4.1", + "age=4.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ "ahom", + "phnx", "incjkunifiedideographsextensione", "khmr", "insinhala", @@ -39402,24 +40573,32 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "guru", "sundanese", "punct", + "cwt", + "unassigned", "paucinhau", "gurmukhi", - "variationselector", + "chorasmian", "logicalorderexception", "khmer", "limbu", + "unknown", + "chrs", + "oriya", "inscriptionalpahlavi", - "oidc", "incjkunifiedideographsextensionc", #endif /* USE_UNICODE_PROPERTIES */ "cntrl", -#ifdef USE_UNICODE_PROPERTIES +#ifndef USE_UNICODE_PROPERTIES + "space", +#else /* USE_UNICODE_PROPERTIES */ + "incjkunifiedideographsextensionf", "inlatinextendedadditional", - "decimalnumber", + "ahex", "insorasompeng", "radical", "emojimodifier", "kharoshthi", + "dash", "n", "math", "goth", @@ -39430,479 +40609,475 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = "nko", "nkoo", "ingreekandcoptic", - "olck", "p", "grantha", - "olchiki", + "xpeo", "incjkunifiedideographs", "zanb", "intirhuta", - "oids", "inhatran", "linb", - "xpeo", "mult", "saurashtra", "kthi", "inbhaiksuki", - "olower", "innabataean", "inphoenician", "inkanbun", "inmeroitichieroglyphs", - "inkayahli", - "phnx", - "inoriya", "enclosingmark", "sd", "inelbasan", - "wara", "inenclosedideographicsupplement", "sidd", - "linearb", "hani", + "linearb", "han", + "intifinagh", "inenclosedalphanumericsupplement", - "medf", - "bidicontrol", "hano", + "bidicontrol", "inphaistosdisc", "limb", "inkangxiradicals", "lepc", - "medefaidrin", "braille", "regionalindicator", - "inlowsurrogates", - "inshorthandformatcontrols", - "brah", "inkhojki", - "inoldhungarian", + "brah", "hanunoo", + "inoldhungarian", "hira", "beng", "emojimodifierbase", "inarabic", - "lyci", - "ahex", + "osage", "inherited", "glag", - "lycian", + "osma", "indogra", - "dsrt", + "inlowsurrogates", "arab", - "mymr", - "myanmar", "phli", "inimperialaramaic", + "emod", "ingreekextended", "inanatolianhieroglyphs", "punctuation", - "takri", "graphemeextend", - "invai", - "cwl", "ingeometricshapes", "emojicomponent", + "softdotted", + "takri", + "inyezidi", "coptic", - "deseret", + "inkayahli", + "invai", + "inoriya", "inarabicpresentationformsa", - "takr", "inbasiclatin", "incjkunifiedideographsextensiond", + "wara", "sinh", "sund", + "cwl", "shavian", - "taile", "insundanesesupplement", - "inelymaic", - "insoyombo", + "takr", "bhks", "bhaiksuki", - "incjkcompatibility", + "taile", "inhanunoo", "intangut", + "inethiopicextendeda", "sogdian", "inlatinextendedd", "sogo", "insinhalaarchaicnumbers", "ideographic", - "ugar", + "odi", "copt", "imperialaramaic", "insogdian", "indingbats", "format", "ininscriptionalpahlavi", + "lyci", "ininscriptionalparthian", "grbase", + "lycian", "inbatak", "cprt", - "cwcf", - "cuneiform", - "term", + "ugar", + "mymr", + "myanmar", + "deva", "intibetan", "intags", "asciihexdigit", + "devanagari", "sentenceterminal", - "inmayannumerals", + "defaultignorablecodepoint", + "digit", + "term", "nand", - "patsyn", "hatran", "inblockelements", "inornamentaldingbats", "innumberforms", - "oldpersian", - "inshavian", + "oidc", "bopo", + "hex", + "ext", "hatr", "caseignorable", "inoldpersian", - "modifierletter", - "cwu", - "lydi", + "inshavian", "inbyzantinemusicalsymbols", +#endif /* USE_UNICODE_PROPERTIES */ + "xposixpunct", +#ifndef USE_UNICODE_PROPERTIES + "lower", +#else /* USE_UNICODE_PROPERTIES */ + "inelymaic", + "insoyombo", "ingeometricshapesextended", + "incjkcompatibility", "inmyanmarextendedb", "innushu", - "lydian", - "inunifiedcanadianaboriginalsyllabics", - "orkh", - "inyiradicals", + "olck", + "olchiki", + "cwu", "inkatakanaphoneticextensions", - "inethiopicextendeda", "incoptic", + "oids", "inarabicextendeda", - "oldpermic", "incjksymbolsandpunctuation", - "word", + "olower", "bopomofo", - "ogam", "inlisu", "inoldpermic", "innoblock", - "taiviet", + "extpict", "inbraillepatterns", "alpha", "inbalinese", "sorasompeng", "closepunctuation", + "taiviet", + "inphoneticextensions", + "inmayannumerals", "inmiscellaneousmathematicalsymbolsb", "inlepcha", + "patsyn", + "inlisusupplement", "insyriacsupplement", - "newa", "spacingmark", "inpalmyrene", - "cyrl", "assigned", - "mlym", - "malayalam", - "ext", - "newtailue", -#endif /* USE_UNICODE_PROPERTIES */ + "extender", + "newa", "space", -#ifdef USE_UNICODE_PROPERTIES "intelugu", + "lydi", "idsb", - "indevanagari", - "avestan", - "cf", - "palmyrene", + "lydian", "inethiopicsupplement", - "soyo", -#endif /* USE_UNICODE_PROPERTIES */ - "xposixpunct", -#ifndef USE_UNICODE_PROPERTIES - "lower", -#else /* USE_UNICODE_PROPERTIES */ - "pf", "sarb", "zanabazarsquare", - "ugaritic", - "osge", - "java", + "newtailue", + "indevanagari", + "avestan", + "inyiradicals", "sharada", - "dogra", + "inphoneticextensionssupplement", + "deprecated", "bugi", - "meroitichieroglyphs", + "word", + "java", "separator", "ingeorgiansupplement", "sogd", - "tale", - "inunifiedcanadianaboriginalsyllabicsextended", - "terminalpunctuation", + "ugaritic", + "inethiopicextended", "shrd", #endif /* USE_UNICODE_PROPERTIES */ "graph", -#ifdef USE_UNICODE_PROPERTIES - "olditalic", - "dogr", +#ifndef USE_UNICODE_PROPERTIES + "digit", + "blank" +#else /* USE_UNICODE_PROPERTIES */ "gujr", - "phag", + "tale", "gujarati", + "phag", + "terminalpunctuation", "inhanguljamo", - "javanese", - "taml", - "inphoneticextensions", "siddham", + "ingeorgianextended", "buginese", "inmongoliansupplement", - "invariationselectors", + "cyrl", "inhanguljamoextendeda", - "inverticalforms", - "syrc", + "javanese", + "taml", "number", + "incyrillicextendedb", + "mlym", "incopticepactnumbers", - "avst", + "malayalam", "inbamum", "nd", "insuttonsignwriting", - "extender", + "invariationselectors", + "inverticalforms", + "avst", + "palmyrene", + "soyo", "intaiviet", - "hex", - "incjkunifiedideographsextensionf", - "other", - "otheridcontinue", - "shaw", - "dash", - "othernumber", - "orya", - "invedicextensions", - "sgnw", "caucasianalbanian", "inmathematicalalphanumericsymbols", - "inphoneticextensionssupplement", - "invariationselectorssupplement", + "incjkunifiedideographsextensiong", + "meroitichieroglyphs", + "shaw", + "invedicextensions", + "oldpersian", "induployan", - "syriac", - "oalpha", + "sgnw", "innyiakengpuachuehmong", "incombiningdiacriticalmarks", - "inethiopicextended", + "invariationselectorssupplement", "nl", "incombiningdiacriticalmarksforsymbols", - "khudawadi", - "otheralphabetic", - "oldhungarian", - "incurrencysymbols", "incjkradicalssupplement", "inglagolitic", - "intifinagh", - "ingeorgianextended", + "orkh", + "syrc", + "khudawadi", "surrogate", - "incyrillicextendedb", + "extendedpictographic", + "oldpermic", "ethi", - "titlecaseletter", + "ogam", "rohg", - "inmeroiticcursive", "idstrinaryoperator", "inphagspa", "lepcha", + "titlecaseletter", "intagalog", - "mathsymbol", "incombiningdiacriticalmarkssupplement", + "inmeroiticcursive", "inbrahmi", "insymbolsandpictographsextendeda", - "inlinearbsyllabary", - "oldturkic", + "syriac", + "modifiersymbol", "inbengali", - "wancho", - "osmanya", + "inhalfwidthandfullwidthforms", "buhd", - "insmallformvariants", - "indevanagariextended", - "softdotted", - "inbuginese", "mahj", + "inbuginese", "inlatin1supplement", "ingothic", "mahajani", "hang", - "sylo", - "warangciti", + "ebase", + "insmallformvariants", + "incurrencysymbols", + "indevanagariextended", + "divesakuru", "ingujarati", - "tirhuta", + "osge", "incombiningdiacriticalmarksextended", "spaceseparator", "ingunjalagondi", - "wcho", + "dupl", "hiragana", - "extendedpictographic", + "tirhuta", "inrejang", - "inottomansiyaqnumbers", + "dashpunctuation", "nchar", - "cyrillic", "khoj", "inlimbu", + "olditalic", "hmng", + "mathsymbol", + "incjkunifiedideographsextensionb", + "phagspa", "thaa", + "currencysymbol", "thai", - "incjkunifiedideographsextensionb", - "deva", + "inenclosedcjklettersandmonths", "thaana", - "phagspa", - "devanagari", + "hanifirohingya", + "inlinearbsyllabary", "tang", - "currencysymbol", "tagbanwa", - "inenclosedcjklettersandmonths", + "wancho", "tamil", - "tirh", -#endif /* USE_UNICODE_PROPERTIES */ - "digit", -#ifndef USE_UNICODE_PROPERTIES - "blank" -#else /* USE_UNICODE_PROPERTIES */ - "talu", "zp", + "tirh", "inpaucinhau", - "taitham", - "otherlowercase", - "telu", + "talu", + "other", + "otheridcontinue", + "sylo", "inaegeannumbers", - "otherletter", - "whitespace", + "warangciti", + "othernumber", + "taitham", "nonspacingmark", + "telu", + "wcho", "graphemeclusterbreak=spacingmark", "inletterlikesymbols", + "tifinagh", + "inottomansiyaqnumbers", "intagbanwa", - "oldsogdian", - "otheridstart", + "tfng", + "cyrillic", + "oalpha", "graphemeclusterbreak=cr", "narb", "changeswhencasemapped", "inbopomofo", - "tangut", "graphemeclusterbreak=regionalindicator", + "otheralphabetic", "noncharactercodepoint", - "otheruppercase", + "oldhungarian", "rjng", - "sylotinagri", + "changeswhencasefolded", + "insymbolsforlegacycomputing", + "tangut", + "dep", "inhangulsyllables", "emojipresentation", - "inindicsiyaqnumbers", + "epres", "inbassavah", - "ogrext", - "othersymbol", - "oupper", + "graphemeclusterbreak=lf", "inbuhid", "hmnp", "inpsalterpahlavi", + "whitespace", "finalpunctuation", + "orya", "phlp", "inbamumsupplement", "buhid", "paragraphseparator", "inalphabeticpresentationforms", - "omath", - "any", "elba", "changeswhentitlecased", "incombininghalfmarks", "intangutcomponents", "hebr", - "deprecated", + "oldturkic", "inarabicmathematicalalphabeticsymbols", + "khitansmallscript", + "sylotinagri", + "hexdigit", "inprivateusearea", - "kayahli", - "inplayingcards", "inarabicpresentationformsb", - "ogham", - "elym", "graphemeclusterbreak=t", "graphemeclusterbreak=lvt", "nbat", - "nabataean", "hangul", - "elymaic", - "inhebrew", - "injavanese", - "symbol", + "nabataean", + "intangutsupplement", "inmathematicaloperators", "inarabicsupplement", - "cypriot", + "injavanese", "hung", - "wspace", + "ogrext", + "inhebrew", "changeswhenlowercased", "elbasan", - "hluw", + "osmanya", "insuperscriptsandsubscripts", "graphemeclusterbreak=extend", "graphemeclusterbreak=prepend", "nshu", - "oldnortharabian", - "inyijinghexagramsymbols", - "hexdigit", + "otherlowercase", + "hluw", + "otherletter", + "kayahli", + "inplayingcards", + "elym", "graphemeclusterbreak=l", "graphemeclusterbreak=control", - "bassavah", - "otherdefaultignorablecodepoint", + "elymaic", "changeswhenuppercased", "inalchemicalsymbols", + "oldsogdian", + "bassavah", + "otheridstart", "insupplementalarrowsa", - "inyisyllables", + "symbol", + "inmahjongtiles", + "cypriot", + "any", + "otheruppercase", + "indivesakuru", "tibt", - "othermath", "tibetan", - "inmahjongtiles", - "signwriting", + "wspace", + "inindicsiyaqnumbers", + "othersymbol", + "oupper", "nushu", - "modifiersymbol", - "inhalfwidthandfullwidthforms", - "upper", + "inyijinghexagramsymbols", "insupplementalarrowsc", + "signwriting", + "omath", + "upper", "insupplementalmathematicaloperators", - "incypriotsyllabary", - "dupl", - "tavt", "inpahawhhmong", "alphabetic", - "dashpunctuation", + "tavt", + "ogham", "uppercase", - "soyombo", - "hanifirohingya", - "otherpunctuation", - "defaultignorablecodepoint", "inhanguljamoextendedb", "aghb", - "tifinagh", + "incypriotsyllabary", "inlatinextendedb", - "tfng", + "inyisyllables", + "oldnortharabian", + "duployan", "inhighprivateusesurrogates", - "changeswhencasefolded", - "dep", - "oldsoutharabian", - "graphemeclusterbreak=lf", + "soyombo", + "otherdefaultignorablecodepoint", + "othermath", + "inbopomofoextended", "pahawhhmong", "unifiedideograph", - "uppercaseletter", "insupplementalpunctuation", + "uppercaseletter", "ethiopic", + "ecomp", "inglagoliticsupplement", "rejang", - "inbopomofoextended", + "otherpunctuation", "tagb", - "othergraphemeextend", - "inegyptianhieroglyphs", - "inegyptianhieroglyphformatcontrols", - "hebrew", + "inboxdrawing", "tglg", - "tagalog", "graphemeclusterbreak=zwj", - "zyyy", - "hyphen", - "inboxdrawing", + "hebrew", + "tagalog", + "oldsoutharabian", + "inegyptianhieroglyphs", + "inegyptianhieroglyphformatcontrols", "graphemeclusterbreak=v", "graphemeclusterbreak=lv", "telugu", - "duployan", - "openpunctuation", + "hyphen", + "othergraphemeextend", "insupplementaryprivateuseareaa", "inhighsurrogates", "insupplementalarrowsb", + "zyyy", + "inhangulcompatibilityjamo", + "openpunctuation", "insupplementalsymbolsandpictographs", "egyp", - "inhangulcompatibilityjamo", "nyiakengpuachuehmong", "egyptianhieroglyphs", "insupplementaryprivateuseareab" @@ -39914,16 +41089,33 @@ uniname2ctype_p (register const char *str, register size_t len) { static const struct uniname2ctype_struct wordlist[] = { -#ifdef USE_UNICODE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str11), 111}, + {-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(str6), 52}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str17), 111}, + {uniname2ctype_offset(str12), 111}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str17), 271}, + {uniname2ctype_offset(str18), 111}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str22), 152}, - {-1}, - {uniname2ctype_offset(str24), 52}, + {-1}, {-1}, {uniname2ctype_offset(str25), 184}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str33), 218}, @@ -39936,16 +41128,16 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str47), 61}, {uniname2ctype_offset(str48), 95}, {uniname2ctype_offset(str49), 95}, - {-1}, {-1}, - {uniname2ctype_offset(str52), 331}, + {-1}, + {uniname2ctype_offset(str51), 230}, + {uniname2ctype_offset(str52), 336}, {-1}, {-1}, {uniname2ctype_offset(str55), 21}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str64), 44}, {-1}, - {uniname2ctype_offset(str66), 319}, - {uniname2ctype_offset(str67), 267}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str66), 324}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str71), 181}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str75), 22}, @@ -39959,9 +41151,9 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str94), 33}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str100), 149}, - {uniname2ctype_offset(str101), 496}, + {uniname2ctype_offset(str101), 501}, {uniname2ctype_offset(str102), 108}, - {uniname2ctype_offset(str103), 252}, + {uniname2ctype_offset(str103), 256}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str107), 31}, {uniname2ctype_offset(str108), 77}, @@ -39975,30 +41167,37 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str118), 77}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str122), 212}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str126), 243}, + {uniname2ctype_offset(str127), 71}, + {-1}, {uniname2ctype_offset(str129), 187}, {uniname2ctype_offset(str130), 42}, {uniname2ctype_offset(str131), 172}, {-1}, {-1}, - {uniname2ctype_offset(str134), 482}, - {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str134), 487}, + {uniname2ctype_offset(str135), 228}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str139), 170}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str145), 499}, - {uniname2ctype_offset(str146), 548}, + {uniname2ctype_offset(str145), 504}, + {uniname2ctype_offset(str146), 557}, {-1}, - {uniname2ctype_offset(str148), 552}, - {uniname2ctype_offset(str149), 514}, + {uniname2ctype_offset(str148), 561}, + {uniname2ctype_offset(str149), 521}, {-1}, {uniname2ctype_offset(str151), 18}, {uniname2ctype_offset(str152), 169}, {uniname2ctype_offset(str153), 160}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str161), 313}, + {uniname2ctype_offset(str161), 318}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str177), 337}, - {uniname2ctype_offset(str178), 539}, + {-1}, {-1}, + {uniname2ctype_offset(str173), 144}, + {uniname2ctype_offset(str174), 144}, + {-1}, {-1}, + {uniname2ctype_offset(str177), 342}, + {uniname2ctype_offset(str178), 547}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str183), 75}, {-1}, {-1}, @@ -40007,18 +41206,19 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str190), 208}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str203), 345}, - {uniname2ctype_offset(str204), 473}, + {uniname2ctype_offset(str203), 350}, + {uniname2ctype_offset(str204), 478}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str210), 553}, + {uniname2ctype_offset(str210), 562}, {-1}, - {uniname2ctype_offset(str212), 350}, + {uniname2ctype_offset(str212), 355}, {uniname2ctype_offset(str213), 115}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str218), 528}, + {uniname2ctype_offset(str218), 535}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str226), 171}, - {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str230), 516}, {uniname2ctype_offset(str231), 31}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str236), 25}, @@ -40030,85 +41230,84 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {uniname2ctype_offset(str253), 102}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str260), 542}, + {uniname2ctype_offset(str260), 551}, {-1}, {-1}, {uniname2ctype_offset(str263), 161}, {-1}, {uniname2ctype_offset(str265), 19}, {-1}, {uniname2ctype_offset(str267), 79}, - {uniname2ctype_offset(str268), 342}, + {uniname2ctype_offset(str268), 347}, {-1}, - {uniname2ctype_offset(str270), 259}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str274), 541}, - {uniname2ctype_offset(str275), 500}, + {uniname2ctype_offset(str270), 263}, + {-1}, {-1}, + {uniname2ctype_offset(str273), 20}, + {uniname2ctype_offset(str274), 550}, + {uniname2ctype_offset(str275), 505}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str281), 307}, + {uniname2ctype_offset(str281), 312}, {uniname2ctype_offset(str282), 40}, {uniname2ctype_offset(str283), 79}, {-1}, - {uniname2ctype_offset(str285), 516}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str289), 536}, + {uniname2ctype_offset(str285), 523}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str289), 544}, + {uniname2ctype_offset(str290), 43}, + {-1}, {-1}, {uniname2ctype_offset(str293), 218}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str297), 212}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str301), 380}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str311), 311}, + {uniname2ctype_offset(str301), 385}, + {uniname2ctype_offset(str302), 243}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str311), 316}, {-1}, - {uniname2ctype_offset(str313), 441}, + {uniname2ctype_offset(str313), 446}, {-1}, - {uniname2ctype_offset(str315), 232}, + {uniname2ctype_offset(str315), 236}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str320), 260}, + {uniname2ctype_offset(str320), 264}, {-1}, {uniname2ctype_offset(str322), 129}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str328), 320}, + {uniname2ctype_offset(str328), 325}, {-1}, {-1}, {uniname2ctype_offset(str331), 76}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str335), 537}, + {uniname2ctype_offset(str335), 545}, {-1}, {-1}, - {uniname2ctype_offset(str338), 318}, + {uniname2ctype_offset(str338), 323}, {-1}, {uniname2ctype_offset(str340), 76}, - {-1}, - {uniname2ctype_offset(str342), 334}, + {uniname2ctype_offset(str341), 540}, + {uniname2ctype_offset(str342), 339}, {-1}, {-1}, {uniname2ctype_offset(str345), 53}, - {uniname2ctype_offset(str346), 259}, + {uniname2ctype_offset(str346), 263}, {-1}, - {uniname2ctype_offset(str348), 411}, + {uniname2ctype_offset(str348), 416}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str352), 512}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str357), 532}, - {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str352), 519}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str362), 163}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str366), 44}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str373), 160}, - {-1}, {-1}, - {uniname2ctype_offset(str376), 144}, - {uniname2ctype_offset(str377), 144}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str386), 356}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str399), 316}, + {uniname2ctype_offset(str386), 361}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str399), 321}, {-1}, - {uniname2ctype_offset(str401), 527}, + {uniname2ctype_offset(str401), 534}, {-1}, {-1}, {uniname2ctype_offset(str404), 81}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str411), 55}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str409), 55}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str418), 108}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str426), 163}, @@ -40118,216 +41317,234 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {uniname2ctype_offset(str445), 23}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str460), 36}, + {-1}, {uniname2ctype_offset(str462), 46}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str468), 169}, {-1}, {uniname2ctype_offset(str470), 22}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str475), 507}, + {uniname2ctype_offset(str475), 512}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str480), 442}, + {uniname2ctype_offset(str480), 447}, {uniname2ctype_offset(str481), 188}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str486), 461}, + {uniname2ctype_offset(str486), 466}, {-1}, - {uniname2ctype_offset(str488), 557}, + {uniname2ctype_offset(str488), 568}, {-1}, {-1}, - {uniname2ctype_offset(str491), 455}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str491), 460}, + {-1}, {-1}, + {uniname2ctype_offset(str494), 230}, + {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str500), 127}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str504), 187}, - {uniname2ctype_offset(str505), 238}, + {uniname2ctype_offset(str505), 242}, {uniname2ctype_offset(str506), 24}, {-1}, {-1}, {uniname2ctype_offset(str509), 24}, {-1}, - {uniname2ctype_offset(str511), 448}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str520), 408}, + {uniname2ctype_offset(str511), 453}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str519), 70}, + {uniname2ctype_offset(str520), 413}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str535), 70}, - {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str538), 91}, {-1}, {-1}, - {uniname2ctype_offset(str541), 531}, + {uniname2ctype_offset(str541), 539}, {-1}, {uniname2ctype_offset(str543), 91}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str556), 525}, + {uniname2ctype_offset(str556), 532}, {-1}, - {uniname2ctype_offset(str558), 335}, + {uniname2ctype_offset(str558), 340}, {-1}, - {uniname2ctype_offset(str560), 498}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str565), 586}, + {uniname2ctype_offset(str560), 503}, + {-1}, + {uniname2ctype_offset(str562), 70}, + {-1}, {-1}, + {uniname2ctype_offset(str565), 597}, {uniname2ctype_offset(str566), 37}, {-1}, {uniname2ctype_offset(str568), 113}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str572), 486}, + {uniname2ctype_offset(str569), 260}, + {-1}, {-1}, + {uniname2ctype_offset(str572), 491}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str577), 573}, - {uniname2ctype_offset(str578), 70}, + {uniname2ctype_offset(str577), 584}, + {-1}, {uniname2ctype_offset(str579), 106}, {-1}, {-1}, - {uniname2ctype_offset(str582), 391}, - {uniname2ctype_offset(str583), 465}, + {uniname2ctype_offset(str582), 396}, + {uniname2ctype_offset(str583), 470}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str590), 74}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str594), 168}, {-1}, - {uniname2ctype_offset(str596), 584}, + {uniname2ctype_offset(str596), 595}, {uniname2ctype_offset(str597), 146}, {-1}, {-1}, - {uniname2ctype_offset(str600), 475}, + {uniname2ctype_offset(str600), 480}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str604), 551}, - {uniname2ctype_offset(str605), 591}, + {uniname2ctype_offset(str604), 560}, + {uniname2ctype_offset(str605), 602}, {-1}, {-1}, - {uniname2ctype_offset(str608), 598}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str614), 574}, + {uniname2ctype_offset(str608), 610}, + {uniname2ctype_offset(str609), 229}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str613), 219}, + {uniname2ctype_offset(str614), 585}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str624), 195}, - {uniname2ctype_offset(str625), 432}, - {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str625), 437}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str629), 219}, {uniname2ctype_offset(str630), 29}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str636), 522}, - {-1}, {-1}, + {uniname2ctype_offset(str631), 262}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str638), 572}, {uniname2ctype_offset(str639), 49}, {-1}, {-1}, {uniname2ctype_offset(str642), 19}, {-1}, {-1}, - {uniname2ctype_offset(str645), 470}, + {uniname2ctype_offset(str645), 475}, {-1}, {uniname2ctype_offset(str647), 192}, {-1}, {-1}, - {uniname2ctype_offset(str650), 472}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str650), 477}, + {-1}, + {uniname2ctype_offset(str652), 69}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str657), 51}, {-1}, {-1}, - {uniname2ctype_offset(str660), 257}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str668), 69}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str672), 321}, + {uniname2ctype_offset(str660), 261}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str672), 326}, {-1}, {-1}, {uniname2ctype_offset(str675), 68}, {-1}, {-1}, {uniname2ctype_offset(str678), 171}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str682), 529}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str688), 114}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str695), 530}, {uniname2ctype_offset(str696), 175}, - {uniname2ctype_offset(str697), 384}, + {uniname2ctype_offset(str697), 389}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str703), 508}, + {uniname2ctype_offset(str703), 514}, {-1}, - {uniname2ctype_offset(str705), 332}, + {uniname2ctype_offset(str705), 337}, {-1}, {uniname2ctype_offset(str707), 158}, - {uniname2ctype_offset(str708), 556}, + {uniname2ctype_offset(str708), 567}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str713), 361}, + {uniname2ctype_offset(str713), 366}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str720), 72}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str737), 7}, - {uniname2ctype_offset(str738), 358}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str742), 6}, + {uniname2ctype_offset(str738), 363}, + {-1}, {-1}, + {uniname2ctype_offset(str741), 537}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str753), 233}, {-1}, - {uniname2ctype_offset(str753), 229}, - {-1}, - {uniname2ctype_offset(str755), 497}, + {uniname2ctype_offset(str755), 502}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str760), 416}, + {uniname2ctype_offset(str760), 421}, {uniname2ctype_offset(str761), 167}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str766), 156}, - {uniname2ctype_offset(str767), 572}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str765), 114}, + {uniname2ctype_offset(str766), 156}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str771), 167}, - {uniname2ctype_offset(str772), 256}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str776), 257}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str776), 261}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str783), 156}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str787), 245}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str787), 249}, + {uniname2ctype_offset(str788), 6}, + {-1}, {-1}, {uniname2ctype_offset(str791), 193}, {-1}, {-1}, - {uniname2ctype_offset(str794), 558}, + {uniname2ctype_offset(str794), 569}, {-1}, {-1}, {uniname2ctype_offset(str797), 50}, {-1}, - {uniname2ctype_offset(str799), 579}, + {uniname2ctype_offset(str799), 590}, {-1}, {-1}, {uniname2ctype_offset(str802), 13}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str809), 431}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str814), 478}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str818), 383}, + {uniname2ctype_offset(str806), 409}, {-1}, {-1}, - {uniname2ctype_offset(str821), 467}, - {uniname2ctype_offset(str822), 563}, + {uniname2ctype_offset(str809), 436}, + {-1}, + {uniname2ctype_offset(str811), 577}, + {-1}, + {uniname2ctype_offset(str813), 583}, + {uniname2ctype_offset(str814), 483}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str818), 388}, + {-1}, {-1}, + {uniname2ctype_offset(str821), 472}, + {uniname2ctype_offset(str822), 574}, {uniname2ctype_offset(str823), 47}, {uniname2ctype_offset(str824), 112}, - {uniname2ctype_offset(str825), 429}, + {uniname2ctype_offset(str825), 434}, {-1}, {-1}, - {uniname2ctype_offset(str828), 564}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str834), 258}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str828), 575}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str838), 157}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str842), 58}, - {-1}, {-1}, - {uniname2ctype_offset(str845), 66}, - {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str847), 48}, {uniname2ctype_offset(str848), 178}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str855), 67}, {-1}, - {uniname2ctype_offset(str857), 305}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str862), 88}, + {uniname2ctype_offset(str857), 310}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str875), 359}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str882), 137}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str875), 354}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str886), 394}, {-1}, - {uniname2ctype_offset(str886), 389}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str895), 397}, + {uniname2ctype_offset(str888), 58}, {-1}, {-1}, - {uniname2ctype_offset(str898), 485}, + {uniname2ctype_offset(str891), 66}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str895), 402}, + {-1}, {-1}, + {uniname2ctype_offset(str898), 490}, {-1}, - {uniname2ctype_offset(str900), 583}, + {uniname2ctype_offset(str900), 594}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str906), 504}, - {uniname2ctype_offset(str907), 434}, + {uniname2ctype_offset(str906), 509}, + {uniname2ctype_offset(str907), 439}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str918), 370}, + {-1}, + {uniname2ctype_offset(str920), 65}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str924), 68}, {-1}, - {uniname2ctype_offset(str926), 329}, + {uniname2ctype_offset(str926), 334}, {-1}, - {uniname2ctype_offset(str928), 519}, - {uniname2ctype_offset(str929), 446}, + {uniname2ctype_offset(str928), 526}, + {uniname2ctype_offset(str929), 451}, {uniname2ctype_offset(str930), 41}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -40336,206 +41553,199 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str961), 2}, {-1}, - {uniname2ctype_offset(str963), 246}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str963), 250}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str972), 27}, {-1}, - {uniname2ctype_offset(str974), 493}, + {uniname2ctype_offset(str974), 498}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str986), 355}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str991), 137}, + {-1}, {-1}, {uniname2ctype_offset(str994), 85}, {uniname2ctype_offset(str995), 104}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1005), 53}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1009), 404}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1003), 53}, + {-1}, + {uniname2ctype_offset(str1005), 348}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1010), 26}, {-1}, {-1}, - {uniname2ctype_offset(str1013), 480}, - {uniname2ctype_offset(str1014), 566}, - {uniname2ctype_offset(str1015), 469}, + {uniname2ctype_offset(str1013), 485}, + {-1}, + {uniname2ctype_offset(str1015), 474}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1021), 67}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1025), 444}, + {uniname2ctype_offset(str1025), 449}, {-1}, {-1}, {uniname2ctype_offset(str1028), 136}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1032), 239}, - {uniname2ctype_offset(str1033), 71}, - {-1}, - {uniname2ctype_offset(str1035), 308}, - {uniname2ctype_offset(str1036), 543}, + {uniname2ctype_offset(str1032), 360}, + {-1}, {-1}, + {uniname2ctype_offset(str1035), 313}, + {uniname2ctype_offset(str1036), 552}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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}, - {uniname2ctype_offset(str1070), 115}, - {-1}, - {uniname2ctype_offset(str1072), 197}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1080), 210}, - {uniname2ctype_offset(str1081), 399}, + {uniname2ctype_offset(str1068), 115}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1085), 248}, - {-1}, - {uniname2ctype_offset(str1087), 567}, - {-1}, {-1}, - {uniname2ctype_offset(str1090), 69}, - {uniname2ctype_offset(str1091), 11}, + {uniname2ctype_offset(str1072), 197}, {-1}, - {uniname2ctype_offset(str1093), 125}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1097), 520}, + {uniname2ctype_offset(str1074), 69}, + {uniname2ctype_offset(str1075), 11}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1081), 404}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1087), 578}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1097), 527}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1102), 506}, + {uniname2ctype_offset(str1102), 511}, {-1}, {-1}, {uniname2ctype_offset(str1105), 217}, {-1}, - {uniname2ctype_offset(str1107), 521}, + {uniname2ctype_offset(str1107), 528}, {-1}, - {uniname2ctype_offset(str1109), 228}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1109), 232}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1116), 260}, + {-1}, {-1}, {uniname2ctype_offset(str1119), 106}, {uniname2ctype_offset(str1120), 60}, - {uniname2ctype_offset(str1121), 365}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1134), 410}, + {-1}, + {uniname2ctype_offset(str1131), 252}, + {-1}, {-1}, + {uniname2ctype_offset(str1134), 415}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1140), 93}, {-1}, {uniname2ctype_offset(str1142), 206}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1146), 131}, - {uniname2ctype_offset(str1147), 255}, + {uniname2ctype_offset(str1147), 259}, {-1}, {uniname2ctype_offset(str1149), 158}, {uniname2ctype_offset(str1150), 98}, - {uniname2ctype_offset(str1151), 483}, + {uniname2ctype_offset(str1151), 488}, {uniname2ctype_offset(str1152), 217}, {uniname2ctype_offset(str1153), 138}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1157), 203}, {uniname2ctype_offset(str1158), 166}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1164), 229}, + {uniname2ctype_offset(str1164), 233}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1168), 104}, {-1}, - {uniname2ctype_offset(str1170), 374}, - {uniname2ctype_offset(str1171), 515}, + {uniname2ctype_offset(str1170), 379}, + {uniname2ctype_offset(str1171), 522}, {-1}, {-1}, - {uniname2ctype_offset(str1174), 312}, - {uniname2ctype_offset(str1175), 26}, + {uniname2ctype_offset(str1174), 317}, + {-1}, {uniname2ctype_offset(str1176), 208}, {uniname2ctype_offset(str1177), 74}, - {uniname2ctype_offset(str1178), 338}, + {uniname2ctype_offset(str1178), 343}, {-1}, {uniname2ctype_offset(str1180), 183}, {uniname2ctype_offset(str1181), 151}, - {uniname2ctype_offset(str1182), 344}, + {uniname2ctype_offset(str1182), 349}, {uniname2ctype_offset(str1183), 101}, {-1}, {uniname2ctype_offset(str1185), 170}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1190), 261}, - {uniname2ctype_offset(str1191), 524}, + {uniname2ctype_offset(str1190), 265}, + {uniname2ctype_offset(str1191), 531}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1197), 101}, {uniname2ctype_offset(str1198), 135}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1203), 351}, + {uniname2ctype_offset(str1203), 356}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1207), 447}, - {uniname2ctype_offset(str1208), 239}, + {uniname2ctype_offset(str1207), 452}, + {-1}, {uniname2ctype_offset(str1209), 186}, - {uniname2ctype_offset(str1210), 137}, + {-1}, {-1}, + {uniname2ctype_offset(str1212), 369}, + {uniname2ctype_offset(str1213), 216}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1221), 26}, {-1}, - {uniname2ctype_offset(str1212), 364}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1227), 232}, + {uniname2ctype_offset(str1223), 565}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1227), 236}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1231), 206}, - {uniname2ctype_offset(str1232), 340}, + {uniname2ctype_offset(str1232), 345}, {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), 287}, - {uniname2ctype_offset(str1235), 289}, - {uniname2ctype_offset(str1236), 286}, - {uniname2ctype_offset(str1237), 288}, - {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1234), 291}, + {uniname2ctype_offset(str1235), 293}, + {uniname2ctype_offset(str1236), 290}, + {uniname2ctype_offset(str1237), 292}, + {-1}, {-1}, + {uniname2ctype_offset(str1240), 294}, + {-1}, {-1}, #endif /* USE_UNICODE_AGE_PROPERTIES */ {uniname2ctype_offset(str1243), 25}, - {uniname2ctype_offset(str1244), 326}, - {uniname2ctype_offset(str1245), 249}, - {uniname2ctype_offset(str1246), 420}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1244), 331}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1247), 268}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1246), 425}, + {uniname2ctype_offset(str1247), 357}, {uniname2ctype_offset(str1248), 30}, #ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1249), 275}, - {uniname2ctype_offset(str1250), 270}, - {uniname2ctype_offset(str1251), 274}, - {uniname2ctype_offset(str1252), 269}, - {uniname2ctype_offset(str1253), 285}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1254), 540}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1255), 280}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1256), 267}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, #else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1257), 279}, - {uniname2ctype_offset(str1258), 281}, - {uniname2ctype_offset(str1259), 272}, - {uniname2ctype_offset(str1260), 284}, - {uniname2ctype_offset(str1261), 271}, - {uniname2ctype_offset(str1262), 273}, + {-1}, + {uniname2ctype_offset(str1250), 272}, + {-1}, + {uniname2ctype_offset(str1252), 289}, + {uniname2ctype_offset(str1253), 274}, #endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1263), 64}, + {uniname2ctype_offset(str1254), 549}, #ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1264), 283}, - {-1}, + {uniname2ctype_offset(str1255), 273}, + {uniname2ctype_offset(str1256), 276}, + {uniname2ctype_offset(str1257), 288}, + {uniname2ctype_offset(str1258), 275}, + {uniname2ctype_offset(str1259), 277}, + {uniname2ctype_offset(str1260), 284}, + {uniname2ctype_offset(str1261), 287}, + {uniname2ctype_offset(str1262), 283}, + {uniname2ctype_offset(str1263), 285}, #endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1266), 21}, + {uniname2ctype_offset(str1264), 216}, #ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1267), 282}, - {uniname2ctype_offset(str1268), 277}, + {uniname2ctype_offset(str1265), 281}, + {uniname2ctype_offset(str1266), 286}, + {uniname2ctype_offset(str1267), 280}, + {uniname2ctype_offset(str1268), 282}, + {uniname2ctype_offset(str1269), 279}, {-1}, - {uniname2ctype_offset(str1270), 276}, {uniname2ctype_offset(str1271), 278}, {-1}, {-1}, #endif /* USE_UNICODE_AGE_PROPERTIES */ {uniname2ctype_offset(str1274), 200}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1282), 596}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1278), 138}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1282), 608}, {-1}, {-1}, {uniname2ctype_offset(str1285), 105}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1289), 333}, + {uniname2ctype_offset(str1289), 338}, {-1}, {-1}, - {uniname2ctype_offset(str1292), 382}, + {uniname2ctype_offset(str1292), 387}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1297), 145}, {-1}, {-1}, @@ -40543,38 +41753,48 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str1301), 141}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1306), 15}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str1309), 64}, + {-1}, {-1}, + {uniname2ctype_offset(str1312), 21}, + {-1}, {uniname2ctype_offset(str1314), 193}, {-1}, {-1}, {uniname2ctype_offset(str1317), 86}, - {-1}, - {uniname2ctype_offset(str1319), 256}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str1328), 227}, {-1}, {-1}, - {uniname2ctype_offset(str1331), 252}, + {uniname2ctype_offset(str1331), 256}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1340), 105}, {-1}, {-1}, {uniname2ctype_offset(str1343), 120}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1348), 271}, + {uniname2ctype_offset(str1349), 227}, + {-1}, {-1}, + {uniname2ctype_offset(str1352), 88}, {-1}, {uniname2ctype_offset(str1354), 164}, - {uniname2ctype_offset(str1355), 254}, - {-1}, {-1}, - {uniname2ctype_offset(str1358), 594}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1358), 606}, {-1}, {uniname2ctype_offset(str1360), 3}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1365), 372}, - {uniname2ctype_offset(str1366), 36}, - {uniname2ctype_offset(str1367), 513}, {-1}, - {uniname2ctype_offset(str1369), 247}, + {uniname2ctype_offset(str1362), 609}, + {-1}, {-1}, + {uniname2ctype_offset(str1365), 377}, + {uniname2ctype_offset(str1366), 240}, + {uniname2ctype_offset(str1367), 520}, + {-1}, + {uniname2ctype_offset(str1369), 251}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1373), 263}, + {uniname2ctype_offset(str1373), 267}, {-1}, {uniname2ctype_offset(str1375), 135}, - {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1376), 234}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str1380), 35}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1384), 56}, @@ -40583,7 +41803,7 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1400), 201}, - {uniname2ctype_offset(str1401), 385}, + {uniname2ctype_offset(str1401), 390}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1407), 224}, {-1}, @@ -40592,887 +41812,884 @@ uniname2ctype_p (register const char *str, register size_t len) {uniname2ctype_offset(str1419), 140}, {uniname2ctype_offset(str1420), 140}, {-1}, - {uniname2ctype_offset(str1422), 310}, - {uniname2ctype_offset(str1423), 143}, - {-1}, {-1}, + {uniname2ctype_offset(str1422), 315}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str1426), 39}, {-1}, {uniname2ctype_offset(str1428), 181}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1434), 143}, + {uniname2ctype_offset(str1434), 134}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1438), 422}, + {uniname2ctype_offset(str1438), 427}, + {uniname2ctype_offset(str1439), 215}, {-1}, {-1}, - {uniname2ctype_offset(str1441), 215}, - {uniname2ctype_offset(str1442), 523}, - {-1}, {-1}, - {uniname2ctype_offset(str1445), 253}, - {-1}, {-1}, - {uniname2ctype_offset(str1448), 491}, + {uniname2ctype_offset(str1442), 530}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1448), 496}, {uniname2ctype_offset(str1449), 122}, - {uniname2ctype_offset(str1450), 134}, + {-1}, {uniname2ctype_offset(str1451), 203}, {-1}, {-1}, {uniname2ctype_offset(str1454), 145}, {-1}, {-1}, {uniname2ctype_offset(str1457), 166}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1462), 535}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1466), 241}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1470), 490}, - {uniname2ctype_offset(str1471), 492}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1475), 414}, - {uniname2ctype_offset(str1476), 494}, - {-1}, - {uniname2ctype_offset(str1478), 436}, - {-1}, {-1}, - {uniname2ctype_offset(str1481), 138}, + {uniname2ctype_offset(str1462), 543}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1470), 495}, + {uniname2ctype_offset(str1471), 497}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1485), 328}, + {uniname2ctype_offset(str1475), 419}, + {uniname2ctype_offset(str1476), 499}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1489), 33}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1495), 251}, + {uniname2ctype_offset(str1495), 255}, + {-1}, + {uniname2ctype_offset(str1497), 489}, {-1}, - {uniname2ctype_offset(str1497), 484}, - {uniname2ctype_offset(str1498), 199}, - {uniname2ctype_offset(str1499), 582}, + {uniname2ctype_offset(str1499), 593}, {-1}, {uniname2ctype_offset(str1501), 196}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1507), 122}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1505), 110}, {-1}, - {uniname2ctype_offset(str1509), 110}, - {-1}, {-1}, - {uniname2ctype_offset(str1512), 110}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1517), 581}, + {uniname2ctype_offset(str1507), 122}, + {uniname2ctype_offset(str1508), 110}, + {uniname2ctype_offset(str1509), 407}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1517), 592}, {-1}, - {uniname2ctype_offset(str1519), 219}, - {uniname2ctype_offset(str1520), 228}, - {-1}, {-1}, - {uniname2ctype_offset(str1523), 117}, - {uniname2ctype_offset(str1524), 471}, + {uniname2ctype_offset(str1519), 117}, + {uniname2ctype_offset(str1520), 232}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1524), 476}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1529), 120}, {-1}, - {uniname2ctype_offset(str1531), 407}, + {uniname2ctype_offset(str1531), 412}, {-1}, {uniname2ctype_offset(str1533), 142}, - {-1}, - {uniname2ctype_offset(str1535), 219}, + {-1}, {-1}, {uniname2ctype_offset(str1536), 127}, - {uniname2ctype_offset(str1537), 260}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1542), 453}, - {-1}, - {uniname2ctype_offset(str1544), 561}, + {uniname2ctype_offset(str1537), 264}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1544), 525}, {-1}, {-1}, {uniname2ctype_offset(str1547), 168}, - {uniname2ctype_offset(str1548), 518}, - {uniname2ctype_offset(str1549), 505}, - {-1}, {-1}, - {uniname2ctype_offset(str1552), 117}, - {-1}, {-1}, - {uniname2ctype_offset(str1555), 107}, + {uniname2ctype_offset(str1548), 117}, + {uniname2ctype_offset(str1549), 510}, {-1}, + {uniname2ctype_offset(str1551), 107}, + {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1557), 85}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1563), 264}, - {-1}, - {uniname2ctype_offset(str1565), 315}, + {uniname2ctype_offset(str1563), 268}, {-1}, - {uniname2ctype_offset(str1567), 148}, + {uniname2ctype_offset(str1565), 320}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1570), 210}, {-1}, - {uniname2ctype_offset(str1569), 236}, - {-1}, {-1}, {uniname2ctype_offset(str1572), 115}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1580), 131}, - {-1}, - {uniname2ctype_offset(str1582), 148}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1587), 529}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1594), 114}, {-1}, {-1}, + {uniname2ctype_offset(str1583), 125}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1587), 536}, + {uniname2ctype_offset(str1588), 458}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1597), 81}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1602), 97}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1607), 97}, - {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1613), 164}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1617), 488}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1622), 373}, - {uniname2ctype_offset(str1623), 546}, + {uniname2ctype_offset(str1617), 493}, + {uniname2ctype_offset(str1618), 267}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1622), 378}, + {uniname2ctype_offset(str1623), 555}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1629), 39}, - {-1}, - {uniname2ctype_offset(str1631), 176}, - {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1635), 72}, - {-1}, {-1}, - {uniname2ctype_offset(str1638), 426}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1643), 62}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1654), 393}, + {uniname2ctype_offset(str1655), 269}, + {uniname2ctype_offset(str1656), 255}, {-1}, - {uniname2ctype_offset(str1654), 388}, - {uniname2ctype_offset(str1655), 265}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1658), 176}, + {-1}, {-1}, + {uniname2ctype_offset(str1661), 513}, {uniname2ctype_offset(str1662), 129}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1671), 114}, + {-1}, + {uniname2ctype_offset(str1664), 441}, + {uniname2ctype_offset(str1665), 431}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1671), 333}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1675), 457}, - {uniname2ctype_offset(str1676), 176}, - {uniname2ctype_offset(str1677), 303}, + {uniname2ctype_offset(str1675), 462}, + {-1}, + {uniname2ctype_offset(str1677), 308}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1682), 595}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1682), 607}, + {-1}, + {uniname2ctype_offset(str1684), 199}, + {-1}, {uniname2ctype_offset(str1686), 93}, {uniname2ctype_offset(str1687), 141}, - {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str1689), 62}, + {-1}, {uniname2ctype_offset(str1691), 124}, - {uniname2ctype_offset(str1692), 121}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1699), 367}, - {-1}, {-1}, - {uniname2ctype_offset(str1702), 510}, - {uniname2ctype_offset(str1703), 533}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1699), 372}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1703), 176}, {uniname2ctype_offset(str1704), 207}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1714), 207}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1719), 121}, + {-1}, {-1}, + {uniname2ctype_offset(str1722), 352}, {-1}, - {uniname2ctype_offset(str1716), 419}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1722), 347}, - {-1}, - {uniname2ctype_offset(str1724), 554}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1724), 563}, + {-1}, {-1}, + {uniname2ctype_offset(str1727), 450}, {uniname2ctype_offset(str1728), 221}, - {uniname2ctype_offset(str1729), 430}, + {uniname2ctype_offset(str1729), 435}, {uniname2ctype_offset(str1730), 222}, - {uniname2ctype_offset(str1731), 517}, - {uniname2ctype_offset(str1732), 238}, - {uniname2ctype_offset(str1733), 123}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1731), 524}, + {uniname2ctype_offset(str1732), 242}, + {-1}, {-1}, + {uniname2ctype_offset(str1735), 253}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1740), 129}, {-1}, {uniname2ctype_offset(str1742), 161}, {-1}, {-1}, - {uniname2ctype_offset(str1745), 509}, - {uniname2ctype_offset(str1746), 390}, + {uniname2ctype_offset(str1745), 515}, + {uniname2ctype_offset(str1746), 395}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1750), 20}, {-1}, - {uniname2ctype_offset(str1752), 502}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1757), 501}, + {uniname2ctype_offset(str1752), 507}, + {uniname2ctype_offset(str1753), 148}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1757), 506}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1766), 73}, - {-1}, {-1}, - {uniname2ctype_offset(str1769), 362}, + {-1}, + {uniname2ctype_offset(str1768), 148}, + {uniname2ctype_offset(str1769), 367}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1776), 126}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1780), 65}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1788), 137}, {-1}, {-1}, - {uniname2ctype_offset(str1791), 233}, + {uniname2ctype_offset(str1779), 123}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1788), 97}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1793), 97}, + {uniname2ctype_offset(str1794), 84}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1806), 336}, + {-1}, {-1}, + {uniname2ctype_offset(str1806), 341}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1810), 599}, - {uniname2ctype_offset(str1811), 236}, - {-1}, - {uniname2ctype_offset(str1813), 255}, + {uniname2ctype_offset(str1810), 612}, + {uniname2ctype_offset(str1811), 240}, + {uniname2ctype_offset(str1812), 84}, + {uniname2ctype_offset(str1813), 259}, + {-1}, {-1}, + {uniname2ctype_offset(str1816), 71}, + {uniname2ctype_offset(str1817), 4}, + {uniname2ctype_offset(str1818), 237}, {-1}, {-1}, - {uniname2ctype_offset(str1816), 565}, - {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1821), 224}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1825), 258}, - {uniname2ctype_offset(str1826), 202}, - {-1}, - {uniname2ctype_offset(str1828), 387}, + {uniname2ctype_offset(str1822), 202}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1828), 392}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1838), 585}, + {uniname2ctype_offset(str1838), 596}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1842), 379}, - {uniname2ctype_offset(str1843), 134}, + {uniname2ctype_offset(str1842), 384}, + {-1}, {-1}, + {uniname2ctype_offset(str1845), 258}, {-1}, {-1}, - {uniname2ctype_offset(str1846), 481}, - {-1}, {uniname2ctype_offset(str1848), 109}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1861), 202}, + {-1}, + {uniname2ctype_offset(str1850), 239}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1855), 244}, + {-1}, + {uniname2ctype_offset(str1857), 202}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1866), 61}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1871), 479}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1878), 27}, + {uniname2ctype_offset(str1871), 484}, + {-1}, + {uniname2ctype_offset(str1873), 486}, {-1}, {-1}, - {uniname2ctype_offset(str1881), 63}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1891), 150}, - {uniname2ctype_offset(str1892), 562}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1896), 588}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1904), 440}, - {uniname2ctype_offset(str1905), 559}, - {uniname2ctype_offset(str1906), 150}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1911), 343}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1915), 165}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1928), 424}, - {uniname2ctype_offset(str1929), 417}, - {uniname2ctype_offset(str1930), 445}, + {uniname2ctype_offset(str1876), 573}, + {-1}, {-1}, + {uniname2ctype_offset(str1879), 8}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1888), 517}, + {uniname2ctype_offset(str1889), 541}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1896), 599}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1902), 424}, {-1}, - {uniname2ctype_offset(str1932), 400}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1936), 323}, + {uniname2ctype_offset(str1904), 445}, + {uniname2ctype_offset(str1905), 570}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1913), 143}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1947), 194}, - {-1}, {-1}, - {uniname2ctype_offset(str1950), 409}, - {uniname2ctype_offset(str1951), 12}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1958), 109}, + {uniname2ctype_offset(str1924), 143}, {-1}, {-1}, - {uniname2ctype_offset(str1961), 103}, - {-1}, {-1}, - {uniname2ctype_offset(str1964), 425}, + {uniname2ctype_offset(str1927), 63}, + {-1}, + {uniname2ctype_offset(str1929), 422}, {-1}, {-1}, - {uniname2ctype_offset(str1967), 477}, - {uniname2ctype_offset(str1968), 603}, + {uniname2ctype_offset(str1932), 405}, {-1}, {-1}, - {uniname2ctype_offset(str1971), 153}, + {uniname2ctype_offset(str1935), 257}, + {uniname2ctype_offset(str1936), 328}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1985), 393}, + {uniname2ctype_offset(str1950), 414}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1956), 245}, + {-1}, + {uniname2ctype_offset(str1958), 109}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1964), 430}, + {-1}, {-1}, + {uniname2ctype_offset(str1967), 482}, + {uniname2ctype_offset(str1968), 616}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1976), 270}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1985), 398}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str1991), 1}, {-1}, - {uniname2ctype_offset(str1993), 360}, + {uniname2ctype_offset(str1993), 365}, {uniname2ctype_offset(str1994), 175}, {-1}, {uniname2ctype_offset(str1996), 42}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2006), 395}, + {-1}, + {uniname2ctype_offset(str1998), 153}, + {-1}, {-1}, + {uniname2ctype_offset(str2001), 374}, + {uniname2ctype_offset(str2002), 576}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2010), 363}, + {uniname2ctype_offset(str2006), 400}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2014), 322}, + {uniname2ctype_offset(str2010), 368}, + {uniname2ctype_offset(str2011), 262}, + {uniname2ctype_offset(str2012), 548}, {-1}, - {uniname2ctype_offset(str2016), 209}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2023), 32}, - {uniname2ctype_offset(str2024), 489}, + {uniname2ctype_offset(str2014), 327}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2033), 78}, + {uniname2ctype_offset(str2023), 32}, + {uniname2ctype_offset(str2024), 494}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2043), 17}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2048), 92}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2055), 92}, - {-1}, {-1}, - {uniname2ctype_offset(str2058), 240}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2049), 244}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2062), 130}, + {uniname2ctype_offset(str2062), 209}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2070), 9}, {-1}, {-1}, - {uniname2ctype_offset(str2073), 330}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2078), 245}, + {uniname2ctype_offset(str2073), 335}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2077), 150}, + {uniname2ctype_offset(str2078), 249}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2083), 324}, - {uniname2ctype_offset(str2084), 154}, - {uniname2ctype_offset(str2085), 20}, + {uniname2ctype_offset(str2092), 150}, + {-1}, {-1}, + {uniname2ctype_offset(str2095), 346}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2093), 192}, - {-1}, - {uniname2ctype_offset(str2095), 341}, - {-1}, - {uniname2ctype_offset(str2097), 214}, - {uniname2ctype_offset(str2098), 8}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2102), 43}, {uniname2ctype_offset(str2103), 162}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2109), 215}, - {uniname2ctype_offset(str2110), 123}, - {-1}, - {uniname2ctype_offset(str2112), 210}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2107), 215}, + {uniname2ctype_offset(str2108), 130}, {-1}, - {uniname2ctype_offset(str2114), 159}, + {uniname2ctype_offset(str2110), 329}, + {uniname2ctype_offset(str2111), 154}, + {-1}, {-1}, + {uniname2ctype_offset(str2114), 429}, {-1}, {-1}, {uniname2ctype_offset(str2117), 174}, - {-1}, - {uniname2ctype_offset(str2119), 216}, + {uniname2ctype_offset(str2118), 375}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2122), 254}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str2135), 128}, {-1}, - {uniname2ctype_offset(str2137), 172}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2137), 12}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2141), 159}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str2145), 52}, - {uniname2ctype_offset(str2146), 401}, + {uniname2ctype_offset(str2146), 406}, {-1}, {-1}, {uniname2ctype_offset(str2149), 221}, - {uniname2ctype_offset(str2150), 121}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2156), 123}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2162), 408}, {-1}, {-1}, - {uniname2ctype_offset(str2153), 352}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2161), 233}, - {-1}, {-1}, {-1}, {uniname2ctype_offset(str2165), 174}, {uniname2ctype_offset(str2166), 5}, - {uniname2ctype_offset(str2167), 112}, - {-1}, {-1}, - {uniname2ctype_offset(str2170), 216}, {-1}, {-1}, - {uniname2ctype_offset(str2173), 87}, + {uniname2ctype_offset(str2169), 87}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2177), 121}, + {uniname2ctype_offset(str2178), 87}, + {-1}, {-1}, {uniname2ctype_offset(str2181), 139}, - {uniname2ctype_offset(str2182), 87}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2188), 237}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2195), 344}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2195), 339}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2199), 159}, - {-1}, - {uniname2ctype_offset(str2201), 89}, - {-1}, {-1}, - {uniname2ctype_offset(str2204), 369}, {-1}, {-1}, {uniname2ctype_offset(str2207), 196}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2217), 128}, - {uniname2ctype_offset(str2218), 526}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2213), 371}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2222), 458}, + {uniname2ctype_offset(str2217), 128}, + {uniname2ctype_offset(str2218), 533}, + {uniname2ctype_offset(str2219), 78}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2224), 443}, {-1}, - {uniname2ctype_offset(str2224), 438}, - {uniname2ctype_offset(str2225), 459}, - {-1}, {-1}, - {uniname2ctype_offset(str2228), 82}, + {uniname2ctype_offset(str2226), 159}, + {-1}, + {uniname2ctype_offset(str2228), 89}, {uniname2ctype_offset(str2229), 35}, + {uniname2ctype_offset(str2230), 432}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2234), 92}, + {uniname2ctype_offset(str2235), 479}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2235), 474}, + {uniname2ctype_offset(str2241), 92}, {-1}, {-1}, - {uniname2ctype_offset(str2238), 154}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2244), 428}, + {uniname2ctype_offset(str2244), 433}, {-1}, {-1}, {uniname2ctype_offset(str2247), 36}, - {uniname2ctype_offset(str2248), 569}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2252), 240}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2258), 443}, - {-1}, - {uniname2ctype_offset(str2260), 235}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2268), 597}, + {uniname2ctype_offset(str2248), 580}, + {uniname2ctype_offset(str2249), 463}, {-1}, {-1}, - {uniname2ctype_offset(str2271), 18}, - {uniname2ctype_offset(str2272), 254}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2278), 124}, + {uniname2ctype_offset(str2252), 464}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2282), 230}, - {-1}, {-1}, - {uniname2ctype_offset(str2285), 38}, + {uniname2ctype_offset(str2265), 154}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2279), 192}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2283), 214}, + {-1}, + {uniname2ctype_offset(str2285), 448}, + {-1}, {-1}, {-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(str2294), 88}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2302), 368}, - {-1}, {-1}, - {uniname2ctype_offset(str2305), 205}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2312), 177}, {-1}, {-1}, - {uniname2ctype_offset(str2315), 568}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2321), 370}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2339), 600}, + {uniname2ctype_offset(str2315), 579}, + {uniname2ctype_offset(str2316), 611}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2323), 172}, + {uniname2ctype_offset(str2324), 124}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2329), 373}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2343), 560}, - {uniname2ctype_offset(str2344), 82}, + {uniname2ctype_offset(str2333), 134}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2357), 237}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2361), 571}, - {-1}, {-1}, - {uniname2ctype_offset(str2364), 309}, - {uniname2ctype_offset(str2365), 403}, + {uniname2ctype_offset(str2343), 571}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2373), 37}, - {uniname2ctype_offset(str2374), 377}, - {uniname2ctype_offset(str2375), 197}, - {-1}, {-1}, - {uniname2ctype_offset(str2378), 237}, + {uniname2ctype_offset(str2351), 205}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2361), 582}, + {-1}, {-1}, + {uniname2ctype_offset(str2364), 314}, {-1}, - {uniname2ctype_offset(str2389), 204}, + {uniname2ctype_offset(str2366), 613}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2396), 376}, - {uniname2ctype_offset(str2397), 406}, - {uniname2ctype_offset(str2398), 398}, + {uniname2ctype_offset(str2373), 37}, + {uniname2ctype_offset(str2374), 382}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2415), 402}, - {uniname2ctype_offset(str2416), 366}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2397), 411}, + {uniname2ctype_offset(str2398), 403}, + {-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}, {-1}, {-1}, + {uniname2ctype_offset(str2421), 197}, + {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2427), 23}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2431), 270}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2433), 427}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2437), 194}, + {-1}, {-1}, {uniname2ctype_offset(str2440), 100}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2451), 29}, + {uniname2ctype_offset(str2451), 103}, {-1}, {-1}, {uniname2ctype_offset(str2454), 220}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2458), 495}, - {-1}, - {uniname2ctype_offset(str2460), 246}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2460), 250}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2470), 433}, + {uniname2ctype_offset(str2470), 438}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2475), 142}, + {-1}, {-1}, + {uniname2ctype_offset(str2478), 29}, + {uniname2ctype_offset(str2479), 351}, + {-1}, + {uniname2ctype_offset(str2481), 376}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2479), 346}, - {uniname2ctype_offset(str2480), 50}, - {uniname2ctype_offset(str2481), 371}, + {uniname2ctype_offset(str2485), 500}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str2506), 518}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2506), 511}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2513), 592}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2519), 466}, + {uniname2ctype_offset(str2513), 603}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2529), 165}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2534), 325}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2540), 226}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2530), 82}, + {-1}, {-1}, + {uniname2ctype_offset(str2533), 49}, + {uniname2ctype_offset(str2534), 330}, {-1}, - {uniname2ctype_offset(str2542), 125}, - {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2536), 469}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {uniname2ctype_offset(str2548), 118}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2552), 462}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2561), 435}, - {uniname2ctype_offset(str2562), 251}, - {-1}, - {uniname2ctype_offset(str2564), 357}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2562), 185}, {-1}, - {uniname2ctype_offset(str2566), 185}, - {uniname2ctype_offset(str2567), 304}, + {uniname2ctype_offset(str2564), 362}, {-1}, {-1}, - {uniname2ctype_offset(str2570), 476}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2575), 185}, - {uniname2ctype_offset(str2576), 99}, + {uniname2ctype_offset(str2567), 309}, {-1}, {-1}, - {uniname2ctype_offset(str2579), 133}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2586), 199}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2595), 327}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2603), 198}, + {uniname2ctype_offset(str2570), 481}, + {uniname2ctype_offset(str2571), 185}, + {uniname2ctype_offset(str2572), 99}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2576), 268}, + {-1}, {-1}, + {uniname2ctype_offset(str2579), 467}, {-1}, {-1}, - {uniname2ctype_offset(str2606), 359}, + {uniname2ctype_offset(str2582), 381}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2588), 440}, + {uniname2ctype_offset(str2589), 228}, + {-1}, + {uniname2ctype_offset(str2591), 332}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str2602), 210}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2606), 364}, {-1}, {-1}, {uniname2ctype_offset(str2609), 55}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2614), 538}, + {uniname2ctype_offset(str2610), 546}, + {uniname2ctype_offset(str2611), 179}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2624), 226}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2631), 107}, + {uniname2ctype_offset(str2627), 107}, {-1}, {-1}, - {uniname2ctype_offset(str2634), 266}, + {uniname2ctype_offset(str2630), 198}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2643), 437}, - {uniname2ctype_offset(str2644), 576}, + {uniname2ctype_offset(str2639), 442}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2644), 41}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2648), 243}, - {-1}, - {uniname2ctype_offset(str2650), 78}, - {-1}, {-1}, - {uniname2ctype_offset(str2653), 183}, - {-1}, {-1}, - {uniname2ctype_offset(str2656), 353}, + {uniname2ctype_offset(str2648), 247}, + {uniname2ctype_offset(str2649), 183}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2663), 182}, - {-1}, - {uniname2ctype_offset(str2665), 83}, - {-1}, {-1}, - {uniname2ctype_offset(str2668), 94}, + {uniname2ctype_offset(str2656), 358}, + {uniname2ctype_offset(str2657), 112}, {-1}, - {uniname2ctype_offset(str2670), 593}, - {-1}, {-1}, - {uniname2ctype_offset(str2673), 84}, - {-1}, {-1}, - {uniname2ctype_offset(str2676), 83}, + {uniname2ctype_offset(str2659), 182}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2666), 50}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2670), 605}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2688), 139}, - {-1}, {-1}, - {uniname2ctype_offset(str2691), 84}, - {uniname2ctype_offset(str2692), 211}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2692), 83}, {-1}, {uniname2ctype_offset(str2694), 48}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2698), 119}, - {-1}, {-1}, - {uniname2ctype_offset(str2701), 418}, - {uniname2ctype_offset(str2702), 89}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2721), 198}, + {uniname2ctype_offset(str2695), 94}, {-1}, - {uniname2ctype_offset(str2723), 4}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2732), 130}, + {uniname2ctype_offset(str2697), 423}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2703), 83}, + {uniname2ctype_offset(str2704), 220}, + {uniname2ctype_offset(str2705), 471}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2719), 211}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2747), 54}, + {uniname2ctype_offset(str2725), 119}, + {uniname2ctype_offset(str2726), 226}, {-1}, {-1}, - {uniname2ctype_offset(str2750), 534}, + {uniname2ctype_offset(str2729), 89}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2760), 152}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2764), 241}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2745), 54}, + {-1}, {-1}, + {uniname2ctype_offset(str2748), 198}, + {-1}, + {uniname2ctype_offset(str2750), 542}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2759), 130}, + {-1}, + {uniname2ctype_offset(str2761), 18}, + {uniname2ctype_offset(str2762), 258}, + {-1}, {-1}, + {uniname2ctype_offset(str2765), 133}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2768), 90}, - {uniname2ctype_offset(str2769), 468}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2777), 28}, + {uniname2ctype_offset(str2769), 473}, + {-1}, {-1}, + {uniname2ctype_offset(str2772), 199}, {-1}, {-1}, - {uniname2ctype_offset(str2780), 227}, + {uniname2ctype_offset(str2775), 38}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str2787), 152}, + {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str2793), 34}, + {-1}, + {uniname2ctype_offset(str2795), 90}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2816), 296}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2810), 226}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2816), 301}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2821), 378}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2834), 349}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2841), 222}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2848), 253}, + {uniname2ctype_offset(str2821), 383}, + {-1}, {-1}, + {uniname2ctype_offset(str2824), 132}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2830), 587}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2852), 291}, + {uniname2ctype_offset(str2834), 354}, + {uniname2ctype_offset(str2835), 132}, + {uniname2ctype_offset(str2836), 78}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str2847), 241}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2852), 296}, {-1}, {-1}, {uniname2ctype_offset(str2855), 190}, {uniname2ctype_offset(str2856), 66}, {-1}, {-1}, - {uniname2ctype_offset(str2859), 412}, - {-1}, {-1}, - {uniname2ctype_offset(str2862), 211}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2867), 295}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2871), 243}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2859), 417}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2867), 300}, + {uniname2ctype_offset(str2868), 241}, {-1}, {-1}, - {uniname2ctype_offset(str2883), 242}, + {uniname2ctype_offset(str2871), 247}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2879), 204}, {-1}, - {uniname2ctype_offset(str2885), 147}, - {uniname2ctype_offset(str2886), 133}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2904), 449}, - {uniname2ctype_offset(str2905), 262}, - {uniname2ctype_offset(str2906), 575}, - {-1}, {-1}, - {uniname2ctype_offset(str2909), 549}, + {uniname2ctype_offset(str2881), 147}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2885), 65}, + {uniname2ctype_offset(str2886), 604}, {-1}, {-1}, - {uniname2ctype_offset(str2912), 244}, + {uniname2ctype_offset(str2889), 211}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2899), 254}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2926), 51}, + {uniname2ctype_offset(str2904), 454}, + {uniname2ctype_offset(str2905), 266}, + {-1}, + {uniname2ctype_offset(str2907), 266}, + {-1}, + {uniname2ctype_offset(str2909), 558}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2915), 297}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str2938), 242}, - {-1}, {-1}, - {uniname2ctype_offset(str2941), 348}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2941), 353}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2963), 225}, - {uniname2ctype_offset(str2964), 503}, - {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2959), 225}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2964), 508}, + {-1}, + {uniname2ctype_offset(str2966), 231}, {uniname2ctype_offset(str2967), 43}, + {-1}, {-1}, + {uniname2ctype_offset(str2970), 88}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {uniname2ctype_offset(str2980), 195}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2984), 547}, + {uniname2ctype_offset(str2984), 556}, {-1}, {uniname2ctype_offset(str2986), 118}, {uniname2ctype_offset(str2987), 54}, - {uniname2ctype_offset(str2988), 456}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2993), 234}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3000), 16}, + {uniname2ctype_offset(str2988), 461}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {uniname2ctype_offset(str3001), 180}, {uniname2ctype_offset(str3002), 64}, {-1}, {-1}, - {uniname2ctype_offset(str3005), 460}, - {uniname2ctype_offset(str3006), 555}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3012), 80}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3028), 250}, + {uniname2ctype_offset(str3005), 465}, + {uniname2ctype_offset(str3006), 564}, + {-1}, + {uniname2ctype_offset(str3008), 80}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3045), 577}, + {-1}, + {uniname2ctype_offset(str3019), 165}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3055), 454}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3045), 588}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3053), 229}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3072), 133}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3089), 146}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3098), 580}, - {uniname2ctype_offset(str3099), 463}, - {uniname2ctype_offset(str3100), 103}, - {uniname2ctype_offset(str3101), 223}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3107), 299}, + {uniname2ctype_offset(str3079), 239}, + {-1}, {-1}, + {uniname2ctype_offset(str3082), 459}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3099), 468}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3107), 304}, {-1}, - {uniname2ctype_offset(str3109), 301}, + {uniname2ctype_offset(str3109), 306}, {-1}, {uniname2ctype_offset(str3111), 191}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str3122), 99}, + {-1}, {-1}, {uniname2ctype_offset(str3125), 191}, - {uniname2ctype_offset(str3126), 99}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3134), 223}, + {uniname2ctype_offset(str3142), 566}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3158), 314}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3165), 439}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3169), 47}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3176), 381}, + {uniname2ctype_offset(str3176), 386}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3180), 317}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3185), 126}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3194), 204}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3180), 322}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3188), 444}, {-1}, - {uniname2ctype_offset(str3205), 227}, - {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3190), 204}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3199), 248}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3204), 319}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3209), 62}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3215), 180}, {-1}, {-1}, - {uniname2ctype_offset(str3218), 201}, + {uniname2ctype_offset(str3218), 125}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3237), 375}, + {uniname2ctype_offset(str3237), 380}, {-1}, - {uniname2ctype_offset(str3239), 294}, - {uniname2ctype_offset(str3240), 290}, + {uniname2ctype_offset(str3239), 299}, + {uniname2ctype_offset(str3240), 295}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3248), 213}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3254), 190}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3254), 245}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3260), 201}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3267), 28}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3275), 146}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3284), 591}, {-1}, {-1}, - {uniname2ctype_offset(str3266), 421}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3287), 223}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3286), 235}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3297), 297}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3303), 293}, + {uniname2ctype_offset(str3297), 302}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3309), 178}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3317), 249}, + {uniname2ctype_offset(str3303), 298}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3320), 223}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3328), 63}, - {uniname2ctype_offset(str3329), 587}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3348), 392}, - {uniname2ctype_offset(str3349), 423}, + {uniname2ctype_offset(str3329), 598}, {-1}, - {uniname2ctype_offset(str3351), 96}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3360), 234}, - {-1}, {-1}, - {uniname2ctype_offset(str3363), 96}, + {uniname2ctype_offset(str3331), 222}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3336), 178}, {-1}, - {uniname2ctype_offset(str3365), 578}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3338), 257}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3348), 397}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3355), 47}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3361), 589}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3371), 126}, + {uniname2ctype_offset(str3372), 16}, + {uniname2ctype_offset(str3373), 246}, + {-1}, {-1}, + {uniname2ctype_offset(str3376), 538}, + {-1}, + {uniname2ctype_offset(str3378), 96}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str3390), 96}, + {uniname2ctype_offset(str3391), 231}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3396), 586}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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}, {-1}, {-1}, - {uniname2ctype_offset(str3433), 205}, {-1}, {-1}, + {uniname2ctype_offset(str3428), 246}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3436), 213}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3439), 49}, - {-1}, {-1}, - {uniname2ctype_offset(str3442), 464}, + {uniname2ctype_offset(str3448), 426}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3458), 10}, - {-1}, - {uniname2ctype_offset(str3460), 589}, + {-1}, {-1}, + {uniname2ctype_offset(str3460), 600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3479), 205}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3483), 238}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str3504), 10}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3511), 401}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3511), 396}, - {uniname2ctype_offset(str3512), 487}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3517), 179}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3531), 153}, - {uniname2ctype_offset(str3532), 550}, + {-1}, {-1}, + {uniname2ctype_offset(str3532), 559}, {uniname2ctype_offset(str3533), 57}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3550), 41}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3558), 59}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3585), 153}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3590), 103}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3604), 59}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3613), 214}, - {uniname2ctype_offset(str3614), 220}, - {-1}, - {uniname2ctype_offset(str3616), 45}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str3628), 71}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3648), 450}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3648), 455}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3664), 177}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3698), 492}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3705), 311}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str3703), 132}, - {-1}, - {uniname2ctype_offset(str3705), 306}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3714), 132}, - {-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(str3721), 428}, {-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}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3766), 452}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str3765), 179}, + {uniname2ctype_offset(str3766), 457}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3791), 65}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3805), 250}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3819), 162}, - {-1}, - {uniname2ctype_offset(str3821), 292}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3799), 214}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3807), 253}, {-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), 248}, {-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(str3850), 238}, {-1}, {-1}, {-1}, {-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(str3891), 30}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3884), 420}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3888), 182}, + {-1}, {-1}, + {uniname2ctype_offset(str3891), 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(str3924), 405}, + {uniname2ctype_offset(str3924), 410}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3937), 30}, + {-1}, {-1}, {-1}, {-1}, {uniname2ctype_offset(str3942), 100}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3949), 269}, {-1}, {-1}, {-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(str3976), 581}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3976), 570}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3991), 147}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3995), 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}, @@ -41483,79 +42700,74 @@ 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}, - {uniname2ctype_offset(str4087), 415}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4106), 45}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4109), 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str4136), 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4137), 244}, {-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(str4162), 544}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4175), 545}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4194), 391}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4203), 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}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4254), 116}, {-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(str4281), 116}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4287), 307}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4276), 116}, + {uniname2ctype_offset(str4291), 80}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str4303), 116}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4291), 302}, + {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}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4321), 75}, + {uniname2ctype_offset(str4348), 553}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4361), 554}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4360), 231}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4397), 386}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4405), 298}, - {uniname2ctype_offset(str4406), 300}, + {uniname2ctype_offset(str4432), 303}, + {uniname2ctype_offset(str4433), 305}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4460), 90}, + {uniname2ctype_offset(str4487), 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}, - {uniname2ctype_offset(str4485), 179}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4528), 46}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4542), 235}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -41565,15 +42777,17 @@ 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(str4627), 248}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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), 601}, + {uniname2ctype_offset(str4674), 614}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4683), 451}, + {uniname2ctype_offset(str4683), 456}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -41584,8 +42798,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}, - {uniname2ctype_offset(str4772), 394}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4772), 399}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -41597,6 +42810,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}, {-1}, {-1}, + {uniname2ctype_offset(str4877), 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}, @@ -41604,38 +42819,17 @@ 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(str4948), 590}, -#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(str4955), 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}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4986), 413}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4986), 418}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -41645,11 +42839,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}, - {uniname2ctype_offset(str5114), 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}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5134), 601}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {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}, @@ -41667,6 +42863,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}, {-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}, @@ -41701,8 +42899,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}, {-1}, {-1}, - {uniname2ctype_offset(str5608), 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}, @@ -41744,6 +42940,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}, {-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}, @@ -41757,8 +42955,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}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str6098), 602} + {uniname2ctype_offset(str6098), 615} #endif /* USE_UNICODE_PROPERTIES */ }; @@ -41789,22 +42986,22 @@ uniname2ctype(const UChar *name, unsigned int len) return -1; } #if defined ONIG_UNICODE_VERSION_STRING && !( \ - ONIG_UNICODE_VERSION_MAJOR == 12 && \ - ONIG_UNICODE_VERSION_MINOR == 1 && \ + ONIG_UNICODE_VERSION_MAJOR == 13 && \ + ONIG_UNICODE_VERSION_MINOR == 0 && \ ONIG_UNICODE_VERSION_TEENY == 0 && \ 1) # error ONIG_UNICODE_VERSION_STRING mismatch #endif -#define ONIG_UNICODE_VERSION_STRING "12.1.0" -#define ONIG_UNICODE_VERSION_MAJOR 12 -#define ONIG_UNICODE_VERSION_MINOR 1 +#define ONIG_UNICODE_VERSION_STRING "13.0.0" +#define ONIG_UNICODE_VERSION_MAJOR 13 +#define ONIG_UNICODE_VERSION_MINOR 0 #define ONIG_UNICODE_VERSION_TEENY 0 #if defined ONIG_UNICODE_EMOJI_VERSION_STRING && !( \ - ONIG_UNICODE_EMOJI_VERSION_MAJOR == 12 && \ + ONIG_UNICODE_EMOJI_VERSION_MAJOR == 13 && \ ONIG_UNICODE_EMOJI_VERSION_MINOR == 0 && \ 1) # error ONIG_UNICODE_EMOJI_VERSION_STRING mismatch #endif -#define ONIG_UNICODE_EMOJI_VERSION_STRING "12.0" -#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 12 +#define ONIG_UNICODE_EMOJI_VERSION_STRING "13.0" +#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 13 #define ONIG_UNICODE_EMOJI_VERSION_MINOR 0 diff --git a/ruby/enc/unicode/case-folding.rb b/ruby/enc/unicode/case-folding.rb old mode 100755 new mode 100644 index 362d6ebfd..4a29fdebf --- a/ruby/enc/unicode/case-folding.rb +++ b/ruby/enc/unicode/case-folding.rb @@ -232,7 +232,7 @@ def initialize(mapping_directory) @version = nil IO.foreach(File.join(mapping_directory, 'UnicodeData.txt'), mode: "rb") do |line| next if line =~ /^ - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef ENCLOSE_IO_H_999BC1DA -#define ENCLOSE_IO_H_999BC1DA - -#include "enclose_io_prelude.h" -#include "enclose_io_common.h" -#include "enclose_io_win32.h" -#include "enclose_io_unix.h" - -#endif diff --git a/ruby/enclose_io_common.h b/ruby/enclose_io_common.h deleted file mode 100644 index 5bab74232..000000000 --- a/ruby/enclose_io_common.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef ENCLOSE_IO_COMMON_H_39323079 -#define ENCLOSE_IO_COMMON_H_39323079 - -#include "squash.h" - -#ifndef __USE_XOPEN_EXTENDED -#define __USE_XOPEN_EXTENDED -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* PATH_MAX */ - -#ifdef __linux__ -#include /* PATH_MAX */ -#endif - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -extern sqfs *enclose_io_fs; -extern sqfs_path enclose_io_cwd; - -#define ENCLOSE_IO_PP_NARG(...) \ - ENCLOSE_IO_PP_NARG_(__VA_ARGS__,ENCLOSE_IO_PP_RSEQ_N()) -#define ENCLOSE_IO_PP_NARG_(...) \ - ENCLOSE_IO_PP_ARG_N(__VA_ARGS__) -#define ENCLOSE_IO_PP_ARG_N( \ - _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, N, ...) N -#define ENCLOSE_IO_PP_RSEQ_N() \ - 63,62,61,60, \ - 59,58,57,56,55,54,53,52,51,50, \ - 49,48,47,46,45,44,43,42,41,40, \ - 39,38,37,36,35,34,33,32,31,30, \ - 29,28,27,26,25,24,23,22,21,20, \ - 19,18,17,16,15,14,13,12,11,10, \ - 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 - -short enclose_io_is_path(char *pathname); -short enclose_io_is_path_w(wchar_t *pathname); -short enclose_io_is_relative_w(wchar_t *pathname); - -#define ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN(PATH, RETURN1, RETURN2) \ - if (mkdir_workdir) { \ - sqfs_path mkdir_workdir_expanded; \ - char *mkdir_workdir_expanded_head; \ - size_t mkdir_workdir_len; \ - size_t memcpy_len; \ - struct stat mkdir_workdir_buf; \ - mkdir_workdir_len = strlen(mkdir_workdir); \ - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); \ - memcpy_len = strlen(PATH); \ - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { \ - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; \ - } \ - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], (PATH), memcpy_len); \ - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; \ - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); \ - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { \ - memmove(mkdir_workdir_expanded_head, mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1); \ - if (0 == stat(mkdir_workdir_expanded, &mkdir_workdir_buf)) { \ - return(RETURN2); \ - } \ - } \ - } \ - return(RETURN1) - -#define ENCLOSE_IO_GEN_EXPANDED_NAME(path) \ - enclose_io_cwd_len = strlen(enclose_io_cwd); \ - memcpy(enclose_io_expanded, enclose_io_cwd, enclose_io_cwd_len); \ - memcpy_len = strlen(path); \ - if (SQUASHFS_PATH_LEN - enclose_io_cwd_len < memcpy_len) { memcpy_len = SQUASHFS_PATH_LEN - enclose_io_cwd_len; } \ - memcpy(&enclose_io_expanded[enclose_io_cwd_len], (path), memcpy_len); \ - enclose_io_expanded[enclose_io_cwd_len + memcpy_len] = '\0' - -//TODO maybe use WideCharToMultiByte -#define W_ENCLOSE_IO_PATH_CONVERT(path) \ - enclose_io_converted = (char *)enclose_io_converted_storage; \ - enclose_io_converted_length = wcstombs(enclose_io_converted_storage, (path), SQUASHFS_PATH_LEN); \ - if ((size_t)-1 == enclose_io_converted_length) { enclose_io_converted_length = 0; } \ - enclose_io_converted[enclose_io_converted_length] = '\0'; \ - if (strnlen(enclose_io_converted_storage, 4) >= 4 && (0 == strncmp(enclose_io_converted_storage, "\\\\?\\", 4) || 0 == strncmp(enclose_io_converted_storage, "//?/", 4))) { \ - if (strnlen(enclose_io_converted_storage, 6) >= 6 && ':' == enclose_io_converted_storage[5]) { \ - enclose_io_converted += 6; \ - } else { \ - enclose_io_converted += 4; \ - } \ - } else if (strnlen(enclose_io_converted_storage, 3) >= 3 && (0 == strncmp(enclose_io_converted_storage + 1, ":\\", 2) || 0 == strncmp(enclose_io_converted_storage + 1, ":/", 2))) { \ - enclose_io_converted += 2; \ - } \ - for (enclose_io_i = enclose_io_converted; *enclose_io_i; enclose_io_i++) { \ - if ('\\' == *enclose_io_i) { *enclose_io_i = '/'; } \ - } - -#define ENCLOSE_IO_SET_LAST_ERROR do { \ - if (ENOMEM == errno) { \ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); \ - _doserrno = ERROR_NOT_ENOUGH_MEMORY; \ - } else if (ENOENT == errno) { \ - SetLastError(ERROR_FILE_NOT_FOUND); \ - _doserrno = ERROR_FILE_NOT_FOUND; \ - } else if (EBADF == errno) { \ - SetLastError(ERROR_INVALID_HANDLE); \ - _doserrno = ERROR_INVALID_HANDLE; \ - } else if (ENAMETOOLONG == errno) { \ - SetLastError(ERROR_BUFFER_OVERFLOW); \ - _doserrno = ERROR_BUFFER_OVERFLOW; \ - } else { \ - SetLastError(ERROR_INVALID_FUNCTION); \ - _doserrno = ERROR_INVALID_FUNCTION; \ - } \ - } while (0) - -int enclose_io_exepath(char* buffer, size_t* size); -int enclose_io_dos_return(int statement); -short enclose_io_if(const char* path); -SQUASH_OS_PATH enclose_io_ifextract(const char* path, const char* ext_name); -void enclose_io_chdir_helper(const char *path); -int enclose_io_chdir(const char *path); -char *enclose_io_getcwd(char *buf, size_t size); -char *enclose_io_getwd(char *buf); -int enclose_io_stat(const char *path, struct stat *buf); -int enclose_io_fstat(int fildes, struct stat *buf); -int enclose_io_open(int nargs, const char *pathname, int flags, ...); -int enclose_io_openat(int fd, int nargs, const char *pathname, int flags, ...); -int enclose_io_close(int fildes); -ssize_t enclose_io_read(int fildes, void *buf, size_t nbyte); -off_t enclose_io_lseek(int fildes, off_t offset, int whence); - -#ifdef _WIN32 - -#include "enclose_io_winapi.h" - -short enclose_io_if_w(const wchar_t* path); -int enclose_io__open(const char *pathname, int flags); -int enclose_io__wopen(const wchar_t *pathname, int flags, int mode); -int enclose_io__wmkdir(wchar_t* pathname); -int enclose_io_open_osfhandle(intptr_t osfhandle, int flags); -intptr_t enclose_io_get_osfhandle(int fd); -int enclose_io_wchdir(const wchar_t *path); -wchar_t *enclose_io_wgetcwd(wchar_t *buf, size_t size); -int enclose_io_fstati64(int fildes, struct _stati64 *buf); -__int64 enclose_io_lseeki64(int fildes, __int64 offset, int whence); - -HANDLE -EncloseIOCreateFileW( - LPCWSTR lpFileName, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile -); - -NTSTATUS -EncloseIOpNtQueryDirectoryFile( - HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass, - BOOLEAN ReturnSingleEntry, - PUNICODE_STRING FileName, - BOOLEAN RestartScan -); - -BOOL -EncloseIOCloseHandle( - HANDLE hObject -); - -DWORD -EncloseIOGetFileAttributesW( - LPCWSTR lpFileName -); - -BOOL -EncloseIOGetFileAttributesExW( - LPCWSTR lpFileName, - GET_FILEEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFileInformation -); - -NTSTATUS -EncloseIOpNtQueryInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -NTSTATUS -EncloseIOpNtQueryVolumeInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FsInformation, - ULONG Length, - FS_INFORMATION_CLASS FsInformationClass); - -BOOL -EncloseIOReadFile( - HANDLE hFile, - LPVOID lpBuffer, - DWORD nNumberOfBytesToRead, - LPDWORD lpNumberOfBytesRead, - LPOVERLAPPED lpOverlapped -); - -BOOL -EncloseIOGetHandleInformation( - HANDLE hObject, - LPDWORD lpdwFlags -); - -DWORD -EncloseIOGetFileType( - HANDLE hFile -); - -HANDLE -EncloseIOFindFirstFileW( - LPCWSTR lpFileName, - LPWIN32_FIND_DATAW lpFindFileData -); - -BOOL -EncloseIOFindNextFileW( - HANDLE hFindFile, - LPWIN32_FIND_DATAW lpFindFileData -); - -BOOL -EncloseIOFindClose( - HANDLE hFindFile -); - -BOOL -EncloseIODeviceIoControl( - HANDLE hDevice, - DWORD dwIoControlCode, - LPVOID lpInBuffer, - DWORD nInBufferSize, - LPVOID lpOutBuffer, - DWORD nOutBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped -); - -HANDLE -EncloseIOCreateIoCompletionPort( - HANDLE FileHandle, - HANDLE ExistingCompletionPort, - ULONG_PTR CompletionKey, - DWORD NumberOfConcurrentThreads -); - -BOOL -EncloseIOReadDirectoryChangesW( - HANDLE hDirectory, - LPVOID lpBuffer, - DWORD nBufferLength, - BOOL bWatchSubtree, - DWORD dwNotifyFilter, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped, - LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine -); - -HMODULE -EncloseIOLoadLibraryExW( - LPCWSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags -); - -BOOL -EncloseIOCreateProcessW( - LPCWSTR lpApplicationName, - LPWSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCWSTR lpCurrentDirectory, - LPSTARTUPINFOW lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation -); - -BOOL -EncloseIOSetCurrentDirectoryW( - LPCWSTR lpPathName -); - -DWORD -EncloseIOGetCurrentDirectoryW( - DWORD nBufferLength, - LPWSTR lpBuffer -); - -DWORD -EncloseIOGetFullPathNameW( - LPCWSTR lpFileName, - DWORD nBufferLength, - LPWSTR lpBuffer, - LPWSTR* lpFilePart -); - -BOOL -EncloseIOGetFileInformationByHandle( - HANDLE hFile, - LPBY_HANDLE_FILE_INFORMATION lpFileInformation -); - -#else // ifdef _WIN32 -int enclose_io_lstat(const char *path, struct stat *buf); -ssize_t enclose_io_readlink(const char *path, char *buf, size_t bufsize); -DIR * enclose_io_opendir(const char *filename); -DIR * enclose_io_fdopendir(int fd); -int enclose_io_closedir(DIR *dirp); -struct SQUASH_DIRENT * enclose_io_readdir(DIR *dirp); -long enclose_io_telldir(DIR *dirp); -void enclose_io_seekdir(DIR *dirp, long loc); -void enclose_io_rewinddir(DIR *dirp); -int enclose_io_dirfd(DIR *dirp); -int enclose_io_scandir(const char *dirname, struct SQUASH_DIRENT ***namelist, - int(*select)(const struct SQUASH_DIRENT *), - int(*compar)(const struct SQUASH_DIRENT **, const struct SQUASH_DIRENT **)); -ssize_t enclose_io_pread(int d, void *buf, size_t nbyte, off_t offset); -ssize_t enclose_io_readv(int d, const struct iovec *iov, int iovcnt); -void* enclose_io_dlopen(const char* path, int mode); -int enclose_io_access(const char *path, int mode); -int enclose_io_mkdir(const char *path, mode_t mode); -int enclose_io_execv(const char *path, char *const argv[]); - -#endif // ifdef _WIN32 - -#endif diff --git a/ruby/enclose_io_prelude.h b/ruby/enclose_io_prelude.h deleted file mode 100644 index ac877cc64..000000000 --- a/ruby/enclose_io_prelude.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef ENCLOSE_IO_PRELUDE_H_E46A560C -#define ENCLOSE_IO_PRELUDE_H_E46A560C - -#ifdef _WIN32 -#define WINDOWS_H_A80B5674 -typedef unsigned short sqfs_mode_t; -typedef uint32_t sqfs_id_t; -typedef DWORD64 sqfs_off_t; -#endif // _WIN32 - -#endif /* end of include guard: ENCLOSE_IO_PRELUDE_H_E46A560C */ diff --git a/ruby/enclose_io_unix.c b/ruby/enclose_io_unix.c deleted file mode 100644 index 7ee07b77b..000000000 --- a/ruby/enclose_io_unix.c +++ /dev/null @@ -1,1435 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "enclose_io_common.h" - -#ifdef _WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#define MAXPATHLEN 4096 -#define mode_t unsigned int -#endif - -#ifdef __linux__ -#include -#endif - -#ifdef __APPLE__ -#include -#include -#include -#include -#include // PATH_MAX -#endif - -sqfs *enclose_io_fs; -sqfs_path enclose_io_cwd; /* must end with a slash */ -SQUASH_OS_PATH generic_mkdir_workdir = NULL; -char *mkdir_workdir = NULL; /* must NOT end with a slash */ -char *enclose_io_mkdir_scope = "/__enclose_io_memfs__"; /* must NOT end with a slash */ - -#ifdef _WIN32 -#include -static void mkdir_workdir_halt_rm(const wchar_t *sPath) -{ - SHFILEOPSTRUCTW fileop; - size_t len = wcslen(sPath); - wchar_t pFrom[MAX_PATH * 2]; - - if (len > MAX_PATH) { - return; - } - wcscpy(pFrom, sPath); - pFrom[len] = 0; - pFrom[len + 1] = 0; - - fileop.hwnd = NULL; - fileop.wFunc = FO_DELETE; - fileop.pFrom = pFrom; - fileop.pTo = NULL; - fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; - fileop.fAnyOperationsAborted = FALSE; - fileop.lpszProgressTitle = NULL; - fileop.hNameMappings = NULL; - - SHFileOperationW(&fileop); -} -#else -static int mkdir_workdir_halt_rm(const char *arg1, const struct stat *ptr, int flag, struct FTW *ftwarg) -{ - if (FTW_D == flag || FTW_DNR == flag || FTW_DP == flag) { - rmdir(arg1); - } else { - unlink(arg1); - } -} -#endif - -static void mkdir_workdir_halt() -{ -#ifdef _WIN32 - mkdir_workdir_halt_rm(generic_mkdir_workdir); -#else - nftw(mkdir_workdir, mkdir_workdir_halt_rm, 20, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); -#endif -} - -static char * enclose_io_mkdir_workdir() -{ - if (NULL == mkdir_workdir) { - MUTEX_LOCK(&squash_global_mutex); - if (NULL == mkdir_workdir) { - generic_mkdir_workdir = squash_tmpf(squash_tmpdir(), NULL); - if (NULL == generic_mkdir_workdir) { - mkdir_workdir = NULL; - return NULL; - } -#ifdef _WIN32 - mkdir_workdir = malloc(MAX_PATH * 3); - if (NULL == mkdir_workdir) { - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } - if ((size_t)-1 == wcstombs(mkdir_workdir, generic_mkdir_workdir, MAX_PATH)) { - free(mkdir_workdir); - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } - if (mkdir(mkdir_workdir)) { - free(mkdir_workdir); - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } - if (atexit(mkdir_workdir_halt)) { - free(mkdir_workdir); - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } -#else - mkdir_workdir = generic_mkdir_workdir; - if (mkdir(mkdir_workdir, S_IRWXU)) { - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } - if (atexit(mkdir_workdir_halt)) { - mkdir_workdir = NULL; - free(generic_mkdir_workdir); - generic_mkdir_workdir = NULL; - return NULL; - } -#endif - } - MUTEX_UNLOCK(&squash_global_mutex); - } - return mkdir_workdir; -} - -static int enclose_io_mkdir_consult(char *path, mode_t mode) { - int ret; - char *head = NULL; - char *p = NULL; - char *p_left = NULL; - struct stat buf; - char *path2; - - while (strlen(path) - 1 >= 0 && '/' == path[strlen(path) - 1]) { - path[strlen(path) - 1] = 0; - } - - head = strstr(path, enclose_io_mkdir_scope); - if (NULL == head || '/' != head[strlen(enclose_io_mkdir_scope)]) { - errno = ENOENT; - return -1; - } - - for (p = head + strlen(enclose_io_mkdir_scope) + 1; *p; p++) { - if (*p == '/') { - *p = 0; - if (0 == squash_stat(enclose_io_fs, head, &buf) && S_ISDIR(buf.st_mode)) { - path2 = strdup(path); - if (NULL == path2) { - return -1; - } else { - memmove( - path2 + (head-path), - path2 + (head-path) + strlen(enclose_io_mkdir_scope), - strlen(path2 + (head-path) + strlen(enclose_io_mkdir_scope)) + 1 - ); -#ifdef _WIN32 - mkdir(path2); -#else - mkdir(path2, mode); -#endif - free(path2); - } - *p = '/'; - } else { - *p = '/'; - break; - } - } - } - memmove( - head, - head + strlen(enclose_io_mkdir_scope), - strlen(head + strlen(enclose_io_mkdir_scope)) + 1 - ); -#ifdef _WIN32 - return mkdir(path); -#else - return mkdir(path, mode); -#endif -} - -int enclose_io_mkdir(const char *path, mode_t mode) -{ - if (enclose_io_cwd[0] && '/' != *path) { - struct stat buf; - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - int ret; - int ret_inner; - const char* workdir; - const char* workdir_path; - - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - ret = squash_stat(enclose_io_fs, enclose_io_expanded, &buf); - workdir = enclose_io_mkdir_workdir(); - if (NULL == workdir) { - errno = ENOENT; - return -1; - } - workdir_path = malloc(strlen(workdir) + strlen(enclose_io_expanded) + 1); - if (NULL == workdir_path) { - errno = ENOMEM; - return -1; - } - strcpy(workdir_path, workdir); - strcat(workdir_path, enclose_io_expanded); - ret_inner = enclose_io_mkdir_consult(workdir_path, mode); - free(workdir_path); - if (0 == ret) { - errno = EEXIST; - return -1; - } else { - return ret_inner; - } - } else if (enclose_io_is_path(path)) { - struct stat buf; - int ret; - int ret_inner; - const char* workdir; - const char* workdir_path; - - ret = squash_stat(enclose_io_fs, path, &buf); - workdir = enclose_io_mkdir_workdir(); - if (NULL == workdir) { - errno = ENOENT; - return -1; - } - workdir_path = malloc(strlen(workdir) + strlen(path) + 1); - if (NULL == workdir_path) { - errno = ENOMEM; - return -1; - } - strcpy(workdir_path, workdir); - strcat(workdir_path, path); - ret_inner = enclose_io_mkdir_consult(workdir_path, mode); - free(workdir_path); - if (0 == ret) { - errno = EEXIST; - return -1; - } else { - return ret_inner; - } - } else { - return mkdir(path, mode); - } -} - -#ifdef _WIN32 -int enclose_io__wmkdir(wchar_t* pathname) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(pathname)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(pathname); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - return enclose_io_dos_return(enclose_io_mkdir(enclose_io_expanded, 0777)); - } else if (enclose_io_is_path_w(pathname)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(pathname); - return enclose_io_dos_return(enclose_io_mkdir(enclose_io_converted, 0777)); - } else { - return _wmkdir(pathname); - } -} -#else -int enclose_io__exec(const char *path, char *const argv[]) -{ - int i, ret, argc; - char **new_argv, **argv_memory = NULL; - size_t exec_path_len = 2 * PATH_MAX; - char* exec_path = (char*)(malloc(exec_path_len)); - - ret = enclose_io_exepath(exec_path, &exec_path_len); - assert(0 == ret); - - ret = setenv("ENCLOSE_IO_USE_ORIGINAL_RUBY", "true", 1); - ret = setenv("ENCLOSE_IO_USE_ORIGINAL_NODE", "true", 1); - assert(0 == ret); - - argc = 1; - while (argv[argc]) { ++argc; } - new_argv = (char **)malloc( (2 + argc) * sizeof(char *)); - assert(new_argv); - new_argv[0] = argv[0]; - new_argv[1] = path; - for (i = 1; i < argc; ++i) { - new_argv[2 + i - 1] = argv[i]; - } - new_argv[2 + argc - 1] = NULL; - - ret = execv(exec_path, new_argv); - - free(exec_path); - free(new_argv); - return ret; -} - -int enclose_io_execv(const char *path, char *const argv[]) -{ - const char* squash_extracted_path = NULL; - - if (enclose_io_cwd[0] && '/' != *path) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - return enclose_io__exec(enclose_io_expanded, argv); - } else if (enclose_io_is_path(path)) { - return enclose_io__exec(path, argv); - } else { - return execv(path, argv); - } -} - -int enclose_io_lstat(const char *path, struct stat *buf) -{ - if (enclose_io_cwd[0] && '/' != *path) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - squash_lstat(enclose_io_fs, enclose_io_expanded, buf), - lstat(mkdir_workdir_expanded, buf) - ); - } else if (enclose_io_is_path(path)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - path, - squash_lstat(enclose_io_fs, path, buf), - lstat(mkdir_workdir_expanded, buf) - ); - } else { - return lstat(path, buf); - } -} - -ssize_t enclose_io_readlink(const char *path, char *buf, size_t bufsize) -{ - if (enclose_io_cwd[0] && '/' != *path) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - squash_readlink(enclose_io_fs, enclose_io_expanded, buf, bufsize), - readlink(mkdir_workdir_expanded, buf, bufsize) - ); - } - else if (enclose_io_is_path(path)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - path, - squash_readlink(enclose_io_fs, path, buf, bufsize), - readlink(mkdir_workdir_expanded, buf, bufsize) - ); - } - else { - return readlink(path, buf, bufsize); - } -} - -DIR * enclose_io_opendir(const char *filename) -{ - if (enclose_io_cwd[0] && '/' != *filename) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(filename); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - (DIR *)squash_opendir(enclose_io_fs, enclose_io_expanded), - opendir(mkdir_workdir_expanded) - ); - } - else if (enclose_io_is_path(filename)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - filename, - (DIR *)squash_opendir(enclose_io_fs, filename), - opendir(mkdir_workdir_expanded) - ); - } - else { - return opendir(filename); - } -} - -DIR * enclose_io_fdopendir(int fd) -{ - sqfs_err error; - short found; - SQUASH_DIR *dir; - int *handle; - struct squash_file *file; - sqfs *fs; - - if (!SQUASH_VALID_VFD(fd)) - { - return fdopendir(fd); - } - - file = squash_global_fdtable.fds[fd]; - - dir = calloc(1, sizeof(SQUASH_DIR)); - - if (NULL == dir) - { - errno = ENOMEM; - return NULL; - } - - fs = file->fs; - - dir->fs = fs; - dir->entries = NULL; - dir->nr = 0; - dir->filename = strdup(file->filename); - dir->fd = fd; - dir->actual_nr = 0; - dir->loc = 0; - - error = sqfs_inode_get(fs, &dir->node, sqfs_inode_root(fs)); - if (SQFS_OK != error) - { - goto failure; - } - error = sqfs_lookup_path_inner(fs, &dir->node, dir->filename, &found, 1); - if (SQFS_OK != error) - { - goto failure; - } - if (!found) - { - errno = ENOENT; - goto failure; - } - error = sqfs_dir_open(fs, &dir->node, &dir->dir, 0); - if (SQFS_OK != error) - { - goto failure; - } - - handle = (int *)(squash_global_fdtable.fds[dir->fd]->payload); - - MUTEX_LOCK(&squash_global_mutex); - free(handle); - squash_global_fdtable.fds[dir->fd]->payload = (void *)dir; - MUTEX_UNLOCK(&squash_global_mutex); - - return dir; -failure: - if (!errno) { - errno = ENOENT; - } - free(dir); - return NULL; -} - -int enclose_io_closedir(DIR *dirp) -{ - if (squash_find_entry(dirp)) { - return squash_closedir((SQUASH_DIR *)dirp); - } - else { - return closedir(dirp); - } -} - -struct SQUASH_DIRENT * enclose_io_readdir(DIR *dirp) -{ - if (squash_find_entry(dirp)) { - return squash_readdir((SQUASH_DIR *)dirp); - } - else { - return readdir(dirp); - } -} - -long enclose_io_telldir(DIR *dirp) -{ - if (squash_find_entry(dirp)) { - return squash_telldir((SQUASH_DIR *)dirp); - } - else { - return telldir(dirp); - } -} - -void enclose_io_seekdir(DIR *dirp, long loc) -{ - if (squash_find_entry(dirp)) { - return squash_seekdir((SQUASH_DIR *)dirp, loc); - } - else { - return seekdir(dirp, loc); - } -} - -void enclose_io_rewinddir(DIR *dirp) -{ - if (squash_find_entry(dirp)) { - return squash_rewinddir((SQUASH_DIR *)dirp); - } - else { - return rewinddir(dirp); - } -} - -int enclose_io_dirfd(DIR *dirp) -{ - if (squash_find_entry(dirp)) { - return squash_dirfd((SQUASH_DIR *)dirp); - } - else { - return dirfd(dirp); - } -} - -int enclose_io_scandir(const char *dirname, struct SQUASH_DIRENT ***namelist, - int(*select)(const struct SQUASH_DIRENT *), - int(*compar)(const struct SQUASH_DIRENT **, const struct SQUASH_DIRENT **)) -{ - if (enclose_io_cwd[0] && '/' != *dirname) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(dirname); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - squash_scandir(enclose_io_fs, enclose_io_expanded, namelist, select, compar), - scandir(mkdir_workdir_expanded, namelist, select, compar) - ); - } - else if (enclose_io_is_path(dirname)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - dirname, - squash_scandir(enclose_io_fs, dirname, namelist, select, compar), - scandir(mkdir_workdir_expanded, namelist, select, compar) - ); - } - else { - return scandir(dirname, namelist, select, compar); - } -} - -ssize_t enclose_io_pread(int d, void *buf, size_t nbyte, off_t offset) -{ - if (SQUASH_VALID_VFD(d)) { - off_t lseek_off, backup_off; - ssize_t read_ssize; - backup_off = squash_lseek(d, 0, SQUASH_SEEK_CUR); - if (-1 == backup_off) { - return -1; - } - lseek_off = squash_lseek(d, offset, SQUASH_SEEK_SET); - if (-1 == lseek_off) { - return -1; - } - read_ssize = squash_read(d, buf, nbyte); - if (-1 == read_ssize) { - return -1; - } - lseek_off = squash_lseek(d, backup_off, SQUASH_SEEK_SET); - assert(backup_off == lseek_off); - return read_ssize; - } else { - return pread(d, buf, nbyte, offset); - } -} - -ssize_t enclose_io_readv(int d, const struct iovec *iov, int iovcnt) -{ - if (SQUASH_VALID_VFD(d)) { - int i; - ssize_t i_ssize; - ssize_t ret = 0; - for (i = 0; i < iovcnt; ++i) { - i_ssize = squash_read(d, iov[i].iov_base, iov[i].iov_len); - if (-1 == i_ssize) { - return -1; - } else if (0 == i_ssize) { - break; - } else { - ret += i_ssize; - } - } - return ret; - } else { - return readv(d, iov, iovcnt); - } -} - -void* enclose_io_dlopen(const char* path, int mode) -{ - return dlopen(enclose_io_ifextract(path, NULL), mode); -} - -int enclose_io_access(const char *path, int mode) -{ - if (enclose_io_cwd[0] && '/' != *path) { - struct stat buf; - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - squash_stat(enclose_io_fs, enclose_io_expanded, &buf), - access(mkdir_workdir_expanded, &buf) - ); - } else if (enclose_io_is_path(path)) { - struct stat buf; - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - path, - squash_stat(enclose_io_fs, path, &buf), - access(mkdir_workdir_expanded, &buf) - ); - } else { - return access(path, mode); - } -} - -#endif // !_WIN32 - -int enclose_io_dos_return(int statement) { -#ifdef _WIN32 - int ret = (statement); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return ret; - } else { - return ret; - } -#else - return (statement); -#endif // _WIN32 -} - -short enclose_io_if(const char* path) -{ - if (enclose_io_cwd[0] && '/' != *path) { - return 1; - } else if (enclose_io_is_path(path)) { - return 1; - } else { - return 0; - } -} - -SQUASH_OS_PATH enclose_io_ifextract(const char* path, const char* ext_name) -{ - if (enclose_io_cwd[0] && '/' != *path) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - return squash_extract(enclose_io_fs, enclose_io_expanded, ext_name); - } - else if (enclose_io_is_path(path)) { - return squash_extract(enclose_io_fs, path, ext_name); - } - else { - return path; - } -} - -void enclose_io_chdir_helper(const char *path) -{ - size_t memcpy_len = strlen(path); - if (SQUASHFS_PATH_LEN - 1 < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - 1; - } - memcpy(enclose_io_cwd, path, memcpy_len); - while ('/' == enclose_io_cwd[memcpy_len - 1]) { - memcpy_len--; - } - enclose_io_cwd[memcpy_len] = '/'; - enclose_io_cwd[memcpy_len + 1] = '\0'; -} - -int enclose_io_chdir(const char *path) -{ - if (enclose_io_is_path(path)) { - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(path); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], (path), memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - if (0 == stat(mkdir_workdir_expanded, &mkdir_workdir_buf)) { - int ret = chdir(mkdir_workdir_expanded); - if (0 == ret) { - enclose_io_chdir_helper(path); - } - return ret; - } - } - } - - struct stat st; - int ret; - - ret = squash_stat(enclose_io_fs, path, &st); - if (-1 == ret) { - #ifdef _WIN32 - ENCLOSE_IO_SET_LAST_ERROR; - #endif - return -1; - } - if (S_ISDIR(st.st_mode)) { - enclose_io_chdir_helper(path); - return 0; - } else { - errno = ENOENT; - #ifdef _WIN32 - ENCLOSE_IO_SET_LAST_ERROR; - #endif - return -1; - } - } else { - int ret; - - ret = chdir(path); - if (0 == ret) { - enclose_io_cwd[0] = '\0'; - } - return ret; - } -} - -char *enclose_io_getcwd(char *buf, size_t size) -{ - if (enclose_io_cwd[0]) { - size_t memcpy_len = strlen(enclose_io_cwd); - if (NULL == buf) { - buf = malloc((memcpy_len + 1) * sizeof(char)); - if (NULL == buf) { - errno = ENOMEM; - #ifdef _WIN32 - ENCLOSE_IO_SET_LAST_ERROR; - #endif - return NULL; - } - } else { - if (size - 1 < memcpy_len) { - memcpy_len = size - 1; - } - } - memcpy(buf, enclose_io_cwd, memcpy_len); - assert(memcpy_len - 1 >= 0); - buf[memcpy_len - 1] = '\0'; - return buf; - } else { - return getcwd(buf, size); - } -} - -char *enclose_io_getwd(char *buf) -{ - return enclose_io_getcwd(buf, MAXPATHLEN); -} - -#ifdef _WIN32 -short enclose_io_if_w(const wchar_t* path) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(path)) { - return 1; - } else if (enclose_io_is_path_w(path)) { - return 1; - } else { - return 0; - } -} - -BOOL -EncloseIOSetCurrentDirectoryW( - LPCWSTR lpPathName -) -{ - if (enclose_io_is_path_w(lpPathName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - int ret; - - W_ENCLOSE_IO_PATH_CONVERT(lpPathName); - - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(enclose_io_converted); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], (enclose_io_converted), memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - if (0 == stat(mkdir_workdir_expanded, &mkdir_workdir_buf)) { - BOOL ret = SetCurrentDirectory(mkdir_workdir_expanded); - if (ret) { - enclose_io_chdir_helper(enclose_io_converted); - } - return ret; - } - } - } - - ret = enclose_io_chdir(enclose_io_converted); - if (0 == ret) { - return 1; - } else { - return 0; - } - } else { - BOOL ret = SetCurrentDirectoryW(lpPathName); - // If the function succeeds, the return value is nonzero. - if (ret) { - enclose_io_cwd[0] = '\0'; - } - return ret; - } -} - -DWORD -EncloseIOGetCurrentDirectoryW( - DWORD nBufferLength, - LPWSTR lpBuffer -) -{ - if (enclose_io_cwd[0]) { - size_t x; - char *ret = enclose_io_getcwd(NULL, 0); - if (NULL == ret) { - return 0; - } - x = mbstowcs(lpBuffer, ret, nBufferLength - 1); - free(ret); - if (NULL == lpBuffer) { - return x + 1; - } else { - return x; - } - } else { - return GetCurrentDirectoryW( - nBufferLength, - lpBuffer - ); - } -} - -DWORD -EncloseIOGetFullPathNameW( - LPCWSTR lpFileName, - DWORD nBufferLength, - LPWSTR lpBuffer, - LPWSTR* lpFilePart -) -{ - DWORD retval = 0; - - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - wchar_t enclose_io_expanded_w[SQUASHFS_PATH_LEN + 1]; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - - mbstowcs(enclose_io_expanded_w, enclose_io_expanded, SQUASHFS_PATH_LEN); - enclose_io_expanded_w[SQUASHFS_PATH_LEN] = 0; - - retval = GetFullPathNameW( - enclose_io_expanded_w, - nBufferLength, - lpBuffer, - lpFilePart - ); - } else { - retval = GetFullPathNameW( - lpFileName, - nBufferLength, - lpBuffer, - lpFilePart - ); - } - - if (0 == retval || retval > nBufferLength) { - return retval; - } - - if (0 == wcsncmp(lpBuffer + 1, L":\\__enclose_io_memfs__", 22)) { - assert(NULL == lpFilePart); // TODO - memmove(lpBuffer, lpBuffer + 2, (retval - 2) * sizeof(wchar_t)); - return retval - 2; - } - - return retval; -} - -#endif // _WIN32 - -int enclose_io_stat(const char *path, struct stat *buf) -{ - if (enclose_io_cwd[0] && '/' != *path) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(path); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - enclose_io_dos_return(squash_stat(enclose_io_fs, enclose_io_expanded, buf)), - stat(mkdir_workdir_expanded, buf) - ); - } else if (enclose_io_is_path(path)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - path, - enclose_io_dos_return(squash_stat(enclose_io_fs, path, buf)), - stat(mkdir_workdir_expanded, buf) - ); - } else { - return stat(path, buf); - } -} - -int enclose_io_fstat(int fildes, struct stat *buf) -{ - if (SQUASH_VALID_VFD(fildes)) { - return enclose_io_dos_return(squash_fstat(fildes, buf)); - } else { - return fstat(fildes, buf); - } -} - -int enclose_io_open(int nargs, const char *pathname, int flags, ...) -{ - if (enclose_io_cwd[0] && '/' != *pathname) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(pathname); - if (!(O_CREAT & flags)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - enclose_io_dos_return(squash_open(enclose_io_fs, enclose_io_expanded)), - open(mkdir_workdir_expanded, flags) - ); - } else { - va_list args; - mode_t mode; - assert(3 == nargs); - va_start(args, flags); - mode = va_arg(args, mode_t); - va_end(args); - char *dir_thereof_ptr = strrchr(enclose_io_expanded, '/'); - if (dir_thereof_ptr) { - *dir_thereof_ptr = 0; - enclose_io_mkdir(enclose_io_expanded, 0777); - *dir_thereof_ptr = '/'; - } - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(enclose_io_expanded); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], enclose_io_expanded, memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - return enclose_io_dos_return(open(mkdir_workdir_expanded, flags, mode)); - } else { - errno = ENOENT; - return enclose_io_dos_return(-1); - } - } else { - errno = ENOENT; - return enclose_io_dos_return(-1); - } - } - } else if (enclose_io_is_path(pathname)) { - if (!(O_CREAT & flags)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - pathname, - enclose_io_dos_return(squash_open(enclose_io_fs, pathname)), - open(mkdir_workdir_expanded, flags) - ); - } else { - va_list args; - mode_t mode; - assert(3 == nargs); - va_start(args, flags); - mode = va_arg(args, mode_t); - va_end(args); - char *dir_thereof_ptr = strrchr(pathname, '/'); - if (dir_thereof_ptr) { - *dir_thereof_ptr = 0; - enclose_io_mkdir(pathname, 0777); - *dir_thereof_ptr = '/'; - } - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(pathname); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], pathname, memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - return enclose_io_dos_return(open(mkdir_workdir_expanded, flags, mode)); - } else { - errno = ENOENT; - return enclose_io_dos_return(-1); - } - } else { - errno = ENOENT; - return enclose_io_dos_return(-1); - } - } - } else { - if (2 == nargs) { - return open(pathname, flags); - } else { - va_list args; - mode_t mode; - va_start(args, flags); - mode = va_arg(args, mode_t); - va_end(args); - return open(pathname, flags, mode); - } - } -} - -int enclose_io_close(int fildes) -{ - if (SQUASH_VALID_VFD(fildes)) { - return enclose_io_dos_return(squash_close(fildes)); - } else { - return close(fildes); - } -} - -ssize_t enclose_io_read(int fildes, void *buf, size_t nbyte) -{ - if (SQUASH_VALID_VFD(fildes)) { - return enclose_io_dos_return(squash_read(fildes, buf, nbyte)); - } else { - return read(fildes, buf, nbyte); - } -} - -off_t enclose_io_lseek(int fildes, off_t offset, int whence) -{ - if (SQUASH_VALID_VFD(fildes)) { - return enclose_io_dos_return(squash_lseek(fildes, offset, whence)); - } else { - return lseek(fildes, offset, whence); - } -} - -short enclose_io_is_path(char *pathname) -{ - if (strnlen((pathname), 21) >= 21) { - if (0 == strncmp((pathname), "/__enclose_io_memfs__", 21) -#ifdef _WIN32 - || 0 == strncmp((pathname), "\\__enclose_io_memfs__", 21) -#endif - ) { - return 1; - } - } -#ifdef _WIN32 - if (strnlen((pathname), 23) >= 23) { - if (0 == strncmp((pathname) + 1, ":/__enclose_io_memfs__", 22) - || 0 == strncmp((pathname) + 1, ":\\__enclose_io_memfs__", 22) - ) { - return 1; - } - } - if (strnlen((pathname), 24) >= 24) { - if (0 == strncmp((pathname), "\\\\?\\__enclose_io_memfs__", 24) || - 0 == strncmp((pathname), "//?/__enclose_io_memfs__", 24)) { - return 1; - } - } - if (strnlen((pathname), 27) >= 27) { - if (0 == strncmp((pathname), "\\\\?\\", 4) || - 0 == strncmp((pathname), "//?/", 4)) { - if (0 == strncmp((pathname) + 5, ":\\__enclose_io_memfs__", 22) || - 0 == strncmp((pathname) + 5, ":/__enclose_io_memfs__", 22)) { - return 1; - } - } - } -#endif - return 0; -} - -#ifdef _WIN32 -short enclose_io_is_path_w(wchar_t *pathname) -{ - if (wcsnlen((pathname), 21) >= 21) { - if (0 == wcsncmp((pathname), L"/__enclose_io_memfs__", 21) - || 0 == wcsncmp((pathname), L"\\__enclose_io_memfs__", 21) - ) { - return 1; - } - } - if (wcsnlen((pathname), 23) >= 23) { - if (0 == wcsncmp((pathname) + 1, L":/__enclose_io_memfs__", 22) - || 0 == wcsncmp((pathname) + 1, L":\\__enclose_io_memfs__", 22) - ) { - return 1; - } - } - if (wcsnlen((pathname), 24) >= 24) { - if (0 == wcsncmp((pathname), L"\\\\?\\__enclose_io_memfs__", 24) || - 0 == wcsncmp((pathname), L"//?/__enclose_io_memfs__", 24)) { - return 1; - } - } - if (wcsnlen((pathname), 27) >= 27) { - if (0 == wcsncmp((pathname), L"\\\\?\\", 4) || - 0 == wcsncmp((pathname), L"//?/", 4)) { - if (0 == wcsncmp((pathname) + 5, L":\\__enclose_io_memfs__", 22) || - 0 == wcsncmp((pathname) + 5, L":/__enclose_io_memfs__", 22)) { - return 1; - } - } - } - return 0; -} - -short enclose_io_is_relative_w(wchar_t *pathname) -{ - if (L'N' == pathname[0] && L'U' == pathname[1] && L'L' == pathname[2] && 0 == pathname[3]) { - return 0; - } - if (L'\\' == (pathname)[0] || - L'/' == (pathname)[0]) { - return 0; - } - if (wcsnlen(pathname, 3) >= 3) { - if (0 == wcsncmp((pathname) + 1, L":\\", 2) || - 0 == wcsncmp((pathname) + 1, L":/", 2)) { - return 0; - } - } - if (wcsnlen(pathname, 4) >= 4) { - if (0 == wcsncmp((pathname), L"\\\\?\\", 4) || - 0 == wcsncmp((pathname), L"//?/", 4)) { - return 0; - } - } - if (wcsnlen(pathname, 7) >= 7) { - if (0 == wcsncmp((pathname), L"\\\\?\\", 4) && 0 == wcsncmp((pathname) + 5, L":\\", 2) ) { - return 0; - } - if (0 == wcsncmp((pathname), L"//?/", 4) && 0 == wcsncmp((pathname) + 5, L":/", 2) ) { - return 0; - } - } - return 1; -} -#endif - -#ifndef _WIN32 -int enclose_io_openat(int nargs, int dirfd, const char* pathname, int flags, ...) -{ - if (3 == nargs) { - // If pathname is absolute, then dirfd is ignored. - if (enclose_io_is_path(pathname)) { - return enclose_io_open(nargs, pathname, flags); - } - - // If the pathname given in pathname is relative, - // then it is interpreted relative to the directory referred to by the file descriptor dirfd - // (rather than relative to the current working directory of the calling process, as is done by open(2) for a relative pathname). - // TODO: at dirfd - if (dirfd == AT_FDCWD && enclose_io_cwd[0] && '/' != *pathname) { - return enclose_io_open(nargs, pathname, flags); - } - - return openat(dirfd, pathname, flags); - } - else { - va_list args; - mode_t mode; - assert(4 == nargs); - va_start(args, flags); - mode = va_arg(args, mode_t); - va_end(args); - - // If pathname is absolute, then dirfd is ignored. - if (enclose_io_is_path(pathname)) { - return enclose_io_open(nargs, pathname, flags, mode); - } - - // If the pathname given in pathname is relative, - // then it is interpreted relative to the directory referred to by the file descriptor dirfd - // (rather than relative to the current working directory of the calling process, as is done by open(2) for a relative pathname). - // TODO: at dirfd - if (dirfd == AT_FDCWD && enclose_io_cwd[0] && '/' != *pathname) { - return enclose_io_open(nargs, pathname, flags, mode); - } - - return openat(dirfd, pathname, flags, mode); - } -} -#endif - -/* - * enclose_io_exepath is derived from uv_exepath of libuv. - * libuv is licensed for use as follows: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifdef _WIN32 -int enclose_io_exepath(char* buffer, size_t* size_ptr) { - int utf8_len, utf16_buffer_len, utf16_len; - WCHAR* utf16_buffer; - int err; - - if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) { - return -1; - } - - if (*size_ptr > 32768) { - /* Windows paths can never be longer than this. */ - utf16_buffer_len = 32768; - } else { - utf16_buffer_len = (int) *size_ptr; - } - - utf16_buffer = (WCHAR*) malloc(sizeof(WCHAR) * utf16_buffer_len); - if (!utf16_buffer) { - return -1; - } - - /* Get the path as UTF-16. */ - utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); - if (utf16_len <= 0) { - err = GetLastError(); - goto error; - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* Convert to UTF-8 */ - utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - (int) *size_ptr, - NULL, - NULL); - if (utf8_len == 0) { - err = GetLastError(); - goto error; - } - - free(utf16_buffer); - - /* utf8_len *does* include the terminating null at this point, but the */ - /* returned size shouldn't. */ - *size_ptr = utf8_len - 1; - return 0; - - error: - free(utf16_buffer); - return -1; -} - -#endif - -#ifdef __linux__ -int enclose_io_exepath(char* buffer, size_t* size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return -1; - - buffer[n] = '\0'; - *size = n; - - return 0; -} -#endif - -#ifdef __APPLE__ -int enclose_io_exepath(char* buffer, size_t* size) { - /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ - char abspath[PATH_MAX * 2 + 1]; - char exepath[PATH_MAX + 1]; - uint32_t exepath_size; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - exepath_size = sizeof(exepath); - if (_NSGetExecutablePath(exepath, &exepath_size)) - return -1; - - if (realpath(exepath, abspath) != abspath) - return -1; - - abspath_size = strlen(abspath); - if (abspath_size == 0) - return -1; - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} -#endif diff --git a/ruby/enclose_io_unix.h b/ruby/enclose_io_unix.h deleted file mode 100644 index 291f5277e..000000000 --- a/ruby/enclose_io_unix.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef ENCLOSE_IO_UNIX_H_E0229A03 -#define ENCLOSE_IO_UNIX_H_E0229A03 -#ifndef __cplusplus -#ifndef _WIN32 - - #ifdef dirfd - #undef dirfd - #endif - - #define getcwd(...) enclose_io_getcwd(__VA_ARGS__) - #define getwd(...) enclose_io_getwd(__VA_ARGS__) - #define chdir(...) enclose_io_chdir(__VA_ARGS__) - #define stat(...) enclose_io_stat(__VA_ARGS__) - #define fstat(...) enclose_io_fstat(__VA_ARGS__) - #define lstat(...) enclose_io_lstat(__VA_ARGS__) - #define open(...) enclose_io_open(ENCLOSE_IO_PP_NARG(__VA_ARGS__), __VA_ARGS__) - #define openat(...) enclose_io_openat(ENCLOSE_IO_PP_NARG(__VA_ARGS__), __VA_ARGS__) - #define close(...) enclose_io_close(__VA_ARGS__) - #define read(...) enclose_io_read(__VA_ARGS__) - #define lseek(...) enclose_io_lseek(__VA_ARGS__) - #define readlink(...) enclose_io_readlink(__VA_ARGS__) - #define opendir(...) enclose_io_opendir(__VA_ARGS__) - #define fdopendir(...) enclose_io_fdopendir(__VA_ARGS__) - #define closedir(...) enclose_io_closedir(__VA_ARGS__) - #define readdir(...) enclose_io_readdir(__VA_ARGS__) - #define telldir(...) enclose_io_telldir(__VA_ARGS__) - #define seekdir(...) enclose_io_seekdir(__VA_ARGS__) - #define rewinddir(...) enclose_io_rewinddir(__VA_ARGS__) - #define dirfd(...) enclose_io_dirfd(__VA_ARGS__) - #define scandir(...) enclose_io_scandir(__VA_ARGS__) - #define pread(...) enclose_io_pread(__VA_ARGS__) - #define readv(...) enclose_io_readv(__VA_ARGS__) - #define dlopen(...) enclose_io_dlopen(__VA_ARGS__) - #define access(...) enclose_io_access(__VA_ARGS__) - #define mkdir(...) enclose_io_mkdir(__VA_ARGS__) - #define execv(...) enclose_io_execv(__VA_ARGS__) - -#endif // !_WIN32 -#endif //!__cplusplus -#endif diff --git a/ruby/enclose_io_win32.c b/ruby/enclose_io_win32.c deleted file mode 100644 index 85528ddd3..000000000 --- a/ruby/enclose_io_win32.c +++ /dev/null @@ -1,1325 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "enclose_io_common.h" - -#ifdef _WIN32 - -extern char *mkdir_workdir; -extern char *enclose_io_mkdir_scope; - -int enclose_io__open(const char *pathname, int flags) -{ - if (enclose_io_cwd[0] && '/' != *pathname) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - ENCLOSE_IO_GEN_EXPANDED_NAME(pathname); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - enclose_io_dos_return(squash_open(enclose_io_fs, enclose_io_expanded)), - _open(mkdir_workdir_expanded, flags) - ); - } else if (enclose_io_is_path(pathname)) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - pathname, - enclose_io_dos_return(squash_open(enclose_io_fs, pathname)), - _open(mkdir_workdir_expanded, flags) - ); - } else { - return _open(pathname, flags); - } -} - -int enclose_io__wopen(const wchar_t *pathname, int flags, int mode) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(pathname)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(pathname); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - enclose_io_dos_return(squash_open(enclose_io_fs, enclose_io_expanded)), - _open(mkdir_workdir_expanded, flags, mode) - ); - } else if (enclose_io_is_path_w(pathname)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(pathname); - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - enclose_io_dos_return(squash_open(enclose_io_fs, enclose_io_converted)), - _open(mkdir_workdir_expanded, flags, mode) - ); - } else { - return _wopen(pathname, flags, mode); - } -} - -int enclose_io_open_osfhandle(intptr_t osfhandle, int flags) -{ - struct squash_file *entry = squash_find_entry((void *)osfhandle); - if (entry) { - return entry->fd; - } else { - return _open_osfhandle(osfhandle, flags); - } -} - -intptr_t enclose_io_get_osfhandle(int fd) -{ - if (SQUASH_VALID_VFD(fd)) { - assert(!(S_ISDIR(squash_global_fdtable.fds[fd]->st.st_mode))); - return (intptr_t)(squash_global_fdtable.fds[fd]->payload); - } - else { - return _get_osfhandle(fd); - } -} - -int enclose_io_wchdir(const wchar_t *path) -{ - if (enclose_io_is_path_w(path)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - struct stat st; - int ret; - - W_ENCLOSE_IO_PATH_CONVERT(path); - - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(enclose_io_converted); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], (enclose_io_converted), memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - if (0 == stat(mkdir_workdir_expanded, &mkdir_workdir_buf)) { - int ret = _chdir(mkdir_workdir_expanded); - if (0 == ret) { - enclose_io_chdir_helper(enclose_io_converted); - } - return ret; - } - } - } - - ret = squash_stat(enclose_io_fs, enclose_io_converted, &st); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return -1; - } - if (S_ISDIR(st.st_mode)) { - enclose_io_chdir_helper(enclose_io_converted); - return 0; - } else { - errno = ENOENT; - ENCLOSE_IO_SET_LAST_ERROR; - return -1; - } - } else { - int ret = _wchdir(path); - if (0 == ret) { - enclose_io_cwd[0] = '\0'; - } - return ret; - } -} - -wchar_t *enclose_io_wgetcwd(wchar_t *buf, size_t size) -{ - wchar_t tempbuf[SQUASHFS_PATH_LEN + 1]; - size_t retlen; - if (enclose_io_cwd[0]) { - retlen = mbstowcs(tempbuf, enclose_io_cwd, SQUASHFS_PATH_LEN); - if ((size_t)-1 == retlen) { - errno = ERANGE; - ENCLOSE_IO_SET_LAST_ERROR; - return NULL; - } - tempbuf[retlen] = L'\0'; - if (NULL == buf) { - buf = malloc((retlen + 1) * sizeof(wchar_t)); - if (NULL == buf) { - errno = ENOMEM; - return NULL; - } - } else { - if (size - 1 < retlen) { - retlen = size - 1; - } - } - memcpy(buf, tempbuf, retlen * sizeof(wchar_t)); - buf[retlen] = L'\0'; - return buf; - } else { - return _wgetcwd(buf, size); - } -} - -int enclose_io_fstati64(int fildes, struct _stati64 *buf) -{ - struct stat st; - if (SQUASH_VALID_VFD(fildes)) { - if (NULL == buf) { - errno = EINVAL; - ENCLOSE_IO_SET_LAST_ERROR; - return -1; - } - st = SQUASH_VFD_FILE(fildes)->st; - buf->st_dev = st.st_dev; - buf->st_ino = st.st_ino; - buf->st_mode = st.st_mode; - buf->st_nlink = st.st_nlink; - buf->st_uid = st.st_uid; - buf->st_gid = st.st_gid; - buf->st_rdev = st.st_rdev; - buf->st_size = st.st_size; - buf->st_atime = st.st_atime; - buf->st_mtime = st.st_mtime; - buf->st_ctime = st.st_ctime; - return 0; - } else { - return _fstati64(fildes, buf); - } -} - -__int64 enclose_io_lseeki64(int fildes, __int64 offset, int whence) -{ - if (SQUASH_VALID_VFD(fildes)) { - return enclose_io_dos_return(squash_lseek(fildes, offset, whence)); - } else { - return _lseeki64(fildes, offset, whence); - } -} - -static HANDLE EncloseIOCreateFileWHelper( - char * incoming, - DWORD dwFlagsAndAttributes) -{ - int ret; - struct stat buf; - SQUASH_DIR *dirp; - int follow_link; - - if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) { - ret = squash_lstat(enclose_io_fs, incoming, &buf); - follow_link = 0; - } else { - ret = squash_stat(enclose_io_fs, incoming, &buf); - follow_link = 1; - } - - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - if (S_ISDIR(buf.st_mode)) { - dirp = squash_opendir_inner(enclose_io_fs, incoming, follow_link); - if (NULL != dirp) { - return (HANDLE)(dirp); - } else { - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } else { - ret = squash_open_inner(enclose_io_fs, incoming, follow_link); - if (ret >= 0) { - return (HANDLE)(squash_global_fdtable.fds[ret]->payload); - } else { - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } -} - -HANDLE -EncloseIOCreateFileW( - LPCWSTR lpFileName, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile -) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - if (OPEN_EXISTING == dwCreationDisposition) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - EncloseIOCreateFileWHelper( - enclose_io_expanded, - dwFlagsAndAttributes - ), - CreateFile( - mkdir_workdir_expanded, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile - ) - ); - } else { - char *dir_thereof_ptr = strrchr(enclose_io_expanded, '/'); - if (dir_thereof_ptr) { - *dir_thereof_ptr = 0; - enclose_io_mkdir(enclose_io_expanded, 0777); - *dir_thereof_ptr = '/'; - } - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(enclose_io_expanded); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], enclose_io_expanded, memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - return CreateFile( - mkdir_workdir_expanded, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile - ); - } else { - errno = ENOENT; - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } else { - errno = ENOENT; - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } - } else if (enclose_io_is_path_w(lpFileName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - - if (OPEN_EXISTING == dwCreationDisposition) { - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - EncloseIOCreateFileWHelper( - enclose_io_converted, - dwFlagsAndAttributes - ), - CreateFile( - mkdir_workdir_expanded, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile - ) - ); - } else { - char *dir_thereof_ptr = strrchr(enclose_io_converted, '/'); - if (dir_thereof_ptr) { - *dir_thereof_ptr = 0; - enclose_io_mkdir(enclose_io_converted, 0777); - *dir_thereof_ptr = '/'; - } - if (mkdir_workdir) { - sqfs_path mkdir_workdir_expanded; - char *mkdir_workdir_expanded_head; - size_t mkdir_workdir_len; - size_t memcpy_len; - struct stat mkdir_workdir_buf; - mkdir_workdir_len = strlen(mkdir_workdir); - memcpy(mkdir_workdir_expanded, mkdir_workdir, mkdir_workdir_len); - memcpy_len = strlen(enclose_io_converted); - if (SQUASHFS_PATH_LEN - mkdir_workdir_len < memcpy_len) { - memcpy_len = SQUASHFS_PATH_LEN - mkdir_workdir_len; - } - memcpy(&mkdir_workdir_expanded[mkdir_workdir_len], enclose_io_converted, memcpy_len); - mkdir_workdir_expanded[mkdir_workdir_len + memcpy_len] = '\0'; - mkdir_workdir_expanded_head = strstr(mkdir_workdir_expanded, enclose_io_mkdir_scope); - if (mkdir_workdir_expanded_head && '/' == mkdir_workdir_expanded_head[strlen(enclose_io_mkdir_scope)]) { - memmove( - mkdir_workdir_expanded_head, - mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope), - strlen(mkdir_workdir_expanded_head + strlen(enclose_io_mkdir_scope)) + 1 - ); - return CreateFile( - mkdir_workdir_expanded, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile - ); - } else { - errno = ENOENT; - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } else { - errno = ENOENT; - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - } - } else { - return CreateFileW( - lpFileName, - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile - ); - } -} - -BOOL -EncloseIOCloseHandle( - HANDLE hObject -) -{ - struct squash_file *sqf = squash_find_entry((void *)hObject); - if (sqf) { - int ret; - if (S_ISDIR(sqf->st.st_mode)) { - ret = squash_closedir((SQUASH_DIR *)hObject); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - return TRUE; - } else { - ret = squash_close(*((int *)hObject)); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - return TRUE; - } - } else { - return CloseHandle( - hObject - ); - } -} - -BOOL -EncloseIOReadFile( - HANDLE hFile, - LPVOID lpBuffer, - DWORD nNumberOfBytesToRead, - LPDWORD lpNumberOfBytesRead, - LPOVERLAPPED lpOverlapped -) -{ - struct squash_file *sqf = squash_find_entry((void *)hFile); - int ret; - - if (sqf) { - if (NULL != lpOverlapped) { - squash_lseek(sqf->fd, lpOverlapped->Offset, SQUASH_SEEK_SET); - assert(0 == lpOverlapped->OffsetHigh); // TODO support OffsetHigh - } - ret = squash_read(sqf->fd, lpBuffer, nNumberOfBytesToRead); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - *lpNumberOfBytesRead = ret; - return TRUE; - } else { - return ReadFile( - hFile, - lpBuffer, - nNumberOfBytesToRead, - lpNumberOfBytesRead, - lpOverlapped - ); - } -} - -static DWORD EncloseIOGetFileAttributesHelper(struct stat *st) -{ - DWORD fa = 0; //FILE_ATTRIBUTE_READONLY; - if (S_ISCHR(st->st_mode)) { - fa |= FILE_ATTRIBUTE_DEVICE; - } else if (S_ISLNK(st->st_mode)) { - fa |= FILE_ATTRIBUTE_REPARSE_POINT; - } else if (S_ISDIR(st->st_mode)) { - fa |= FILE_ATTRIBUTE_DIRECTORY; - } else { - fa |= FILE_ATTRIBUTE_NORMAL; - } - return fa; -} - -DWORD -EncloseIOGetFileAttributesWHelper( - const char *path -) -{ - int ret; - struct stat buf; - ret = squash_stat(enclose_io_fs, path, &buf); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_FILE_ATTRIBUTES; - } - return EncloseIOGetFileAttributesHelper(&buf); -} - -DWORD -EncloseIOGetFileAttributesW( - LPCWSTR lpFileName -) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - EncloseIOGetFileAttributesWHelper(enclose_io_expanded), - GetFileAttributes( - mkdir_workdir_expanded - ) - ); - } else if (enclose_io_is_path_w(lpFileName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - EncloseIOGetFileAttributesWHelper(enclose_io_converted), - GetFileAttributes( - mkdir_workdir_expanded - ) - ); - } else { - return GetFileAttributesW( - lpFileName - ); - } -} - -static void EncloseIOUnixtimeToFiletime(time_t time, FILETIME *ft) -{ - ULARGE_INTEGER tmp; - tmp.QuadPart = ((long long)time + (long long)((1970-1601)*365.2425) * 24 * 60 * 60) * 10 * 1000 * 1000; - ft->dwLowDateTime = tmp.LowPart; - ft->dwHighDateTime = tmp.HighPart; -} - -static void EncloseIOFillWin32FileAttributeDataHelper(WIN32_FILE_ATTRIBUTE_DATA *fa, struct stat *st) -{ - fa->dwFileAttributes = EncloseIOGetFileAttributesHelper(st); - EncloseIOUnixtimeToFiletime(st->st_atime, &fa->ftLastAccessTime); - EncloseIOUnixtimeToFiletime(st->st_mtime, &fa->ftLastWriteTime); - EncloseIOUnixtimeToFiletime(st->st_ctime, &fa->ftCreationTime); - // TODO somehow support large files? - fa->nFileSizeHigh = 0; - fa->nFileSizeLow = st->st_size; -} - -BOOL -EncloseIOGetFileAttributesExWHelper( - const char *path, - LPVOID lpFileInformation -) -{ - int ret; - struct stat buf; - WIN32_FILE_ATTRIBUTE_DATA *fa; - - ret = squash_stat(enclose_io_fs, path, &buf); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return 0; - } - fa = (WIN32_FILE_ATTRIBUTE_DATA *)lpFileInformation; - EncloseIOFillWin32FileAttributeDataHelper(fa, &buf); - return 1; -} - -BOOL -EncloseIOGetFileAttributesExW( - LPCWSTR lpFileName, - GET_FILEEX_INFO_LEVELS fInfoLevelId, - LPVOID lpFileInformation -) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - assert(GetFileExInfoStandard == fInfoLevelId); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - EncloseIOGetFileAttributesExWHelper(enclose_io_expanded, lpFileInformation), - GetFileAttributesEx( - mkdir_workdir_expanded, - fInfoLevelId, - lpFileInformation - ), - ); - } else if (enclose_io_is_path_w(lpFileName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - assert(GetFileExInfoStandard == fInfoLevelId); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - EncloseIOGetFileAttributesExWHelper(enclose_io_converted, lpFileInformation), - GetFileAttributesEx( - mkdir_workdir_expanded, - fInfoLevelId, - lpFileInformation - ) - ); - } else { - return GetFileAttributesExW( - lpFileName, - fInfoLevelId, - lpFileInformation - ); - } -} - -BOOL -EncloseIOGetHandleInformation( - HANDLE hObject, - LPDWORD lpdwFlags -) -{ - struct squash_file *sqf = squash_find_entry((void *)hObject); - if (sqf) { - *lpdwFlags = 0; - return 1; - } else { - return GetHandleInformation( - hObject, - lpdwFlags - ); - } -} - -DWORD -EncloseIOGetFileType( - HANDLE hFile -) -{ - struct squash_file *sqf = squash_find_entry((void *)hFile); - if (sqf) { - struct stat st; - st = sqf->st; - if (S_ISCHR(st.st_mode)) { - return FILE_TYPE_CHAR; - } else if (S_ISREG(st.st_mode)) { - return FILE_TYPE_DISK; - } else if (S_ISFIFO(st.st_mode)) { - return FILE_TYPE_PIPE; - } else { - return FILE_TYPE_UNKNOWN; - } - } else { - return GetFileType( - hFile - ); - } -} - -DWORD EncloseIODType2FileAttributes(int d_type) -{ - DWORD x = 0; //FILE_ATTRIBUTE_READONLY; - if (DT_CHR == d_type) { - x |= FILE_ATTRIBUTE_DEVICE; - } else if (DT_LNK == d_type) { - x |= FILE_ATTRIBUTE_REPARSE_POINT; - } else if (DT_DIR == d_type) { - x |= FILE_ATTRIBUTE_DIRECTORY; - } else { - x |= FILE_ATTRIBUTE_NORMAL; - } - return x; -} - -HANDLE -EncloseIOFindFirstFileHelper( - char *incoming, - LPWIN32_FIND_DATAW lpFindFileData -) -{ - char *dup_incoming = strdup(incoming); - char *parent = incoming + strlen(incoming); - SQUASH_DIR *dirp; - struct SQUASH_DIRENT *mydirent; - struct SQUASH_DIRENT dummy_dirent; - char *current_path_tail; - char *current_path; - size_t mbstowcs_size; - - while (parent >= incoming) { - if ('/' == *parent) { - break; - } - parent -= 1; - } - *parent = '\0'; - dirp = squash_opendir(enclose_io_fs, incoming); - if (NULL == dirp) { - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - dirp->payload = dup_incoming; - current_path = (char *)malloc(strlen(dup_incoming) + SQUASHFS_PATH_LEN + 1); - if (NULL == current_path) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return INVALID_HANDLE_VALUE; - } - memcpy(current_path, incoming, strlen(incoming) + 1); - strcat(current_path, "/"); - current_path_tail = current_path + strlen(current_path); - do { - mydirent = squash_readdir(dirp); - if (NULL == mydirent) { - // try to determine - // either this dir is empty - // or the dir is not empty and we run out of possible matches - if (dirp->actual_nr == 0) { - // this dir is empty - // so just return a "." to match the original Windows behavior - current_path_tail[0] = '.'; - current_path_tail[1] = 0; // we are sure that this will make true==PathMatchSpecA(current_path, dup_incoming) - dummy_dirent.d_namlen = 1; - dummy_dirent.d_ino = dirp->node.base.inode_number; - dummy_dirent.d_name[0] = '.'; - dummy_dirent.d_name[1] = 0; - dummy_dirent.d_type = DT_DIR; - mydirent = &dummy_dirent; - } - break; - } - memcpy(current_path_tail, mydirent->d_name, strlen(mydirent->d_name) + 1); - } while (!PathMatchSpecA(current_path, dup_incoming)); - free(current_path); - if (NULL == mydirent) { - int ret = squash_closedir(dirp); - assert(0 == ret); - ENCLOSE_IO_SET_LAST_ERROR; - return INVALID_HANDLE_VALUE; - } - mbstowcs_size = mbstowcs(lpFindFileData->cFileName, mydirent->d_name, sizeof(lpFindFileData->cFileName) / sizeof(lpFindFileData->cFileName[0]) - 1); - if ((size_t)-1 == mbstowcs_size) { - errno = EIO; - ENCLOSE_IO_SET_LAST_ERROR; - return 0; - } - lpFindFileData->cFileName[mbstowcs_size] = 0; - lpFindFileData->cAlternateFileName[0] = 0; - lpFindFileData->dwFileAttributes = EncloseIODType2FileAttributes(mydirent->d_type); - return (HANDLE)(dirp); -} - -HANDLE -EncloseIOFindFirstFileW( - LPCWSTR lpFileName, - LPWIN32_FIND_DATAW lpFindFileData -) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - EncloseIOFindFirstFileHelper(enclose_io_expanded, lpFindFileData), - FindFirstFile( - mkdir_workdir_expanded, - lpFindFileData - ) - ); - } else if (enclose_io_is_path_w(lpFileName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpFileName); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - EncloseIOFindFirstFileHelper(enclose_io_converted, lpFindFileData), - FindFirstFile( - mkdir_workdir_expanded, - lpFindFileData - ) - ); - } else { - return FindFirstFileW( - lpFileName, - lpFindFileData - ); - } -} - -BOOL -EncloseIOFindNextFileW( - HANDLE hFindFile, - LPWIN32_FIND_DATAW lpFindFileData -) -{ - struct squash_file *sqf = squash_find_entry((void *)hFindFile); - - if (sqf) { - SQUASH_DIR *dirp; - struct SQUASH_DIRENT *mydirent; - char *current_path; - char *current_path_tail; - size_t mbstowcs_size; - - dirp = (SQUASH_DIR*)hFindFile; - current_path = (char *)malloc(strlen((char *)(dirp->payload)) + SQUASHFS_PATH_LEN + 1); - if (NULL == current_path) { - errno = ENOMEM; - ENCLOSE_IO_SET_LAST_ERROR; - return 0; - } - memcpy(current_path, dirp->filename, strlen(dirp->filename) + 1); - strcat(current_path, "/"); - current_path_tail = current_path + strlen(current_path); - do { - mydirent = squash_readdir(dirp); - if (NULL == mydirent) { - break; - } - memcpy(current_path_tail, mydirent->d_name, strlen(mydirent->d_name) + 1); - } while (!PathMatchSpecA(current_path, (char *)(dirp->payload))); - free(current_path); - if (NULL == mydirent) { - errno = ENOENT; - SetLastError(ERROR_NO_MORE_FILES); - _doserrno = ERROR_NO_MORE_FILES; - return 0; - } - mbstowcs_size = mbstowcs(lpFindFileData->cFileName, mydirent->d_name, sizeof(lpFindFileData->cFileName) / sizeof(lpFindFileData->cFileName[0]) - 1); - if ((size_t)-1 == mbstowcs_size) { - errno = EIO; - ENCLOSE_IO_SET_LAST_ERROR; - return 0; - } - lpFindFileData->cFileName[mbstowcs_size] = 0; - lpFindFileData->cAlternateFileName[0] = 0; - lpFindFileData->dwFileAttributes = EncloseIODType2FileAttributes(mydirent->d_type); - return 1; - } else { - return FindNextFileW( - hFindFile, - lpFindFileData - ); - } -} - -BOOL -EncloseIOFindClose( - HANDLE hFindFile -) -{ - struct squash_file *sqf = squash_find_entry((void *)hFindFile); - int ret; - - if (sqf) { - ret = squash_closedir((SQUASH_DIR *)hFindFile); - if (0 == ret) { - return 1; - } else { - ENCLOSE_IO_SET_LAST_ERROR; - return 0; - } - } else { - return FindClose( - hFindFile - ); - } -} - -BOOL -EncloseIODeviceIoControl( - HANDLE hDevice, - DWORD dwIoControlCode, - LPVOID lpInBuffer, - DWORD nInBufferSize, - LPVOID lpOutBuffer, - DWORD nOutBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped -) -{ - struct squash_file *sqf = squash_find_entry((void *)hDevice); - int ret; - - if (sqf) { - char the_path[SQUASHFS_PATH_LEN + 1]; - wchar_t the_wpath[SQUASHFS_PATH_LEN + 1]; - struct stat st; - size_t retlen; - REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*)lpOutBuffer; - - // TODO handle the overlapped - assert(NULL == lpOverlapped); - - // TODO support more than FSCTL_GET_REPARSE_POINT - assert(0 == nInBufferSize); - - // FSCTL_GET_REPARSE_POINT - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364571(v=vs.85).aspx - assert(dwIoControlCode == FSCTL_GET_REPARSE_POINT); - assert(NULL == lpInBuffer); - st = sqf->st; - if (!S_ISLNK(st.st_mode)) { - errno = EINVAL; - SetLastError(ERROR_NOT_A_REPARSE_POINT); - _doserrno = ERROR_NOT_A_REPARSE_POINT; - return FALSE; - } - ret = squash_readlink_inode( - enclose_io_fs, - &sqf->node, - the_path, - SQUASHFS_PATH_LEN - ); - if (-1 == ret) { - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - - retlen = mbstowcs(the_wpath, the_path, SQUASHFS_PATH_LEN); - if ((size_t)-1 == retlen) { - errno = ENAMETOOLONG; - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - the_wpath[retlen] = L'\0'; - *lpBytesReturned = sizeof(REPARSE_DATA_BUFFER) + retlen * sizeof(wchar_t); - if (*lpBytesReturned > nOutBufferSize) { - *lpBytesReturned = 0; - errno = ENAMETOOLONG; - ENCLOSE_IO_SET_LAST_ERROR; - return FALSE; - } - reparse_data->ReparseTag = IO_REPARSE_TAG_SYMLINK; - memcpy(reparse_data->SymbolicLinkReparseBuffer.PathBuffer, the_wpath, (retlen + 1) * sizeof(wchar_t)); - reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength = retlen * sizeof(wchar_t); - reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; - return TRUE; - } else { - return DeviceIoControl( - hDevice, - dwIoControlCode, - lpInBuffer, - nInBufferSize, - lpOutBuffer, - nOutBufferSize, - lpBytesReturned, - lpOverlapped - ); - } -} - -HANDLE -EncloseIOCreateIoCompletionPort( - HANDLE FileHandle, - HANDLE ExistingCompletionPort, - ULONG_PTR CompletionKey, - DWORD NumberOfConcurrentThreads -) -{ - struct squash_file *sqf = squash_find_entry((void *)FileHandle); - - if (sqf) { - // do nothing - assert(NULL != ExistingCompletionPort); - return ExistingCompletionPort; - } else { - return CreateIoCompletionPort( - FileHandle, - ExistingCompletionPort, - CompletionKey, - NumberOfConcurrentThreads - ); - } -} - -BOOL -EncloseIOReadDirectoryChangesW( - HANDLE hDirectory, - LPVOID lpBuffer, - DWORD nBufferLength, - BOOL bWatchSubtree, - DWORD dwNotifyFilter, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped, - LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine -) -{ - struct squash_file *sqf = squash_find_entry((void *)hDirectory); - - if (sqf) { - // do nothing - assert(lpOverlapped); - return TRUE; - } else { - return ReadDirectoryChangesW( - hDirectory, - lpBuffer, - nBufferLength, - bWatchSubtree, - dwNotifyFilter, - lpBytesReturned, - lpOverlapped, - lpCompletionRoutine - ); - } -} - -HMODULE -EncloseIOLoadLibraryExW( - LPCWSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags -) -{ - if (enclose_io_cwd[0] && enclose_io_is_relative_w(lpLibFileName)) { - sqfs_path enclose_io_expanded; - size_t enclose_io_cwd_len; - size_t memcpy_len; - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpLibFileName); - ENCLOSE_IO_GEN_EXPANDED_NAME(enclose_io_converted); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_expanded, - LoadLibraryExW( - squash_extract(enclose_io_fs, enclose_io_expanded, "dll"), - hFile, - dwFlags - ), - LoadLibraryEx( - mkdir_workdir_expanded, - hFile, - dwFlags - ) - ); - } - else if (enclose_io_is_path_w(lpLibFileName)) { - sqfs_path enclose_io_converted_storage; - char *enclose_io_converted; - char *enclose_io_i; - size_t enclose_io_converted_length; - - W_ENCLOSE_IO_PATH_CONVERT(lpLibFileName); - - ENCLOSE_IO_CONSIDER_MKDIR_WORKDIR_RETURN( - enclose_io_converted, - LoadLibraryExW( - squash_extract(enclose_io_fs, enclose_io_converted, "dll"), - hFile, - dwFlags - ), - LoadLibraryEx( - mkdir_workdir_expanded, - hFile, - dwFlags - ) - ); - } - else { - return LoadLibraryExW( - lpLibFileName, - hFile, - dwFlags - ); - } -} - -BOOL -EncloseIOCreateProcessW( - LPCWSTR lpApplicationName, - LPWSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCWSTR lpCurrentDirectory, - LPSTARTUPINFOW lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation -) -{ - if (NULL != lpCurrentDirectory && enclose_io_is_path_w(lpCurrentDirectory)) { - lpCurrentDirectory = NULL; - } - return CreateProcessW( - lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation - ); -} - -BOOL -EncloseIOGetFileInformationByHandle( - HANDLE hFile, - LPBY_HANDLE_FILE_INFORMATION lpFileInformation -) -{ - struct squash_file *sqf = squash_find_entry((void *)hFile); - struct stat st; - if (sqf) { - st = sqf->st; - lpFileInformation->dwFileAttributes = EncloseIOGetFileAttributesHelper(&st); - EncloseIOUnixtimeToFiletime(st.st_ctime, &lpFileInformation->ftCreationTime); - EncloseIOUnixtimeToFiletime(st.st_atime, &lpFileInformation->ftLastAccessTime); - EncloseIOUnixtimeToFiletime(st.st_mtime, &lpFileInformation->ftLastWriteTime); - lpFileInformation->dwVolumeSerialNumber = 0; // TODO - lpFileInformation->nFileSizeHigh = 0; - lpFileInformation->nFileSizeLow = st.st_size; - lpFileInformation->nNumberOfLinks = st.st_nlink; - lpFileInformation->nFileIndexHigh = 0; - lpFileInformation->nFileIndexLow = st.st_ino; - return 1; - } else { - return GetFileInformationByHandle( - hFile, - lpFileInformation - ); - } -} - -#ifndef RUBY_EXPORT -NTSTATUS -EncloseIOpNtQueryInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass) -{ - struct squash_file *sqf = squash_find_entry((void *)FileHandle); - struct stat st; - if (sqf) { - st = sqf->st; - IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED; - FILE_ALL_INFORMATION *file_info = (FILE_ALL_INFORMATION *)FileInformation; - file_info->BasicInformation.FileAttributes = EncloseIOGetFileAttributesHelper(&st); - file_info->StandardInformation.EndOfFile.QuadPart = st.st_size; - - file_info->BasicInformation.LastAccessTime.QuadPart = st.st_atime * 10000000ULL + 116444736000000000ULL; - file_info->BasicInformation.ChangeTime.QuadPart = st.st_mtime * 10000000ULL + 116444736000000000ULL; - file_info->BasicInformation.LastWriteTime.QuadPart = st.st_mtime * 10000000ULL + 116444736000000000ULL; - file_info->BasicInformation.CreationTime.QuadPart = st.st_ctime * 10000000ULL + 116444736000000000ULL; - file_info->InternalInformation.IndexNumber.QuadPart = st.st_ino; - file_info->StandardInformation.AllocationSize.QuadPart = st.st_size; - file_info->StandardInformation.NumberOfLinks = st.st_nlink; - - return STATUS_SUCCESS; - } else { - return pNtQueryInformationFile( - FileHandle, - IoStatusBlock, - FileInformation, - Length, - FileInformationClass - ); - } -} - -NTSTATUS -EncloseIOpNtQueryVolumeInformationFile( - HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FsInformation, - ULONG Length, - FS_INFORMATION_CLASS FsInformationClass) -{ - if (squash_find_entry((void *)FileHandle)) { - IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED; - return STATUS_SUCCESS; - } else { - return pNtQueryVolumeInformationFile( - FileHandle, - IoStatusBlock, - FsInformation, - Length, - FsInformationClass); - } -} - -NTSTATUS -EncloseIOpNtQueryDirectoryFile( - HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass, - BOOLEAN ReturnSingleEntry, - PUNICODE_STRING FileName, - BOOLEAN RestartScan -) -{ - SQUASH_DIR *handle; - struct SQUASH_DIRENT *mydirent; - size_t retlen; - - if (squash_find_entry((void *)FileHandle)) { - handle = (SQUASH_DIR *)FileHandle; - mydirent = squash_readdir(handle); - if (NULL == mydirent) { - return STATUS_NO_MORE_FILES; - } else { - /* FileInformation points to a buffer to hold directory entries. - * It's important that this buffer can hold at least one entry, regardless - * of the length of the file names present in the enumerated directory. - * A file name is at most 256 WCHARs long. - * According to MSDN, the buffer must be aligned at an 8-byte boundary. - */ - assert(Length > 256 * sizeof(wchar_t)); - FILE_DIRECTORY_INFORMATION *ret = (FILE_DIRECTORY_INFORMATION *)FileInformation; - ret->NextEntryOffset = 0; - retlen = mbstowcs(ret->FileName, mydirent->d_name, 255); - if ((size_t)-1 == retlen) { - return -1; - } - ret->FileName[retlen] = 0; - ret->FileNameLength = sizeof(ret->FileName[0]) * retlen; - ret->FileAttributes = EncloseIODType2FileAttributes(mydirent->d_type); - IoStatusBlock->Information = (char*)(&ret->FileName[retlen]) - (char*)FileInformation + 1; - return STATUS_SUCCESS; - } - } else { - return pNtQueryDirectoryFile( - FileHandle, - Event, - ApcRoutine, - ApcContext, - IoStatusBlock, - FileInformation, - Length, - FileInformationClass, - ReturnSingleEntry, - FileName, - RestartScan - ); - } -} - -#endif // !RUBY_EXPORT -#endif diff --git a/ruby/enclose_io_win32.h b/ruby/enclose_io_win32.h deleted file mode 100644 index 69e46754f..000000000 --- a/ruby/enclose_io_win32.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef ENCLOSE_IO_WIN32_H_9A3D18C6 -#define ENCLOSE_IO_WIN32_H_9A3D18C6 -#ifndef __cplusplus -#ifdef _WIN32 - -#ifdef _fstati64 -#undef _fstati64 -#endif - -#define chdir(...) enclose_io_chdir(__VA_ARGS__) - -#ifndef RUBY_EXPORT - // Ruby has defined the following symbols to - // something like rb_w32_uopen - #define getcwd(...) enclose_io_getcwd(__VA_ARGS__) - #define stat(...) enclose_io_stat(__VA_ARGS__) - #define fstat(...) enclose_io_fstat(__VA_ARGS__) - #define open(...) enclose_io_open(ENCLOSE_IO_PP_NARG(__VA_ARGS__), __VA_ARGS__) - #define close(...) enclose_io_close(__VA_ARGS__) - #define read(...) enclose_io_read(__VA_ARGS__) - #define lseek(...) enclose_io_lseek(__VA_ARGS__) - - // Ruby does not use those things - #define pNtQueryDirectoryFile(...) EncloseIOpNtQueryDirectoryFile(__VA_ARGS__) - #define pNtQueryInformationFile(...) EncloseIOpNtQueryInformationFile(__VA_ARGS__) - #define pNtQueryVolumeInformationFile(...) EncloseIOpNtQueryVolumeInformationFile(__VA_ARGS__) -#endif // !RUBY_EXPORT - -#define _chdir(...) enclose_io_chdir(__VA_ARGS__) -#define _wchdir(...) enclose_io_wchdir(__VA_ARGS__) -#define _getwd(...) enclose_io_getwd(__VA_ARGS__) -#define _wgetwd(...) enclose_io_wgetwd(__VA_ARGS__) -#define _fstati64(...) enclose_io_fstati64(__VA_ARGS__) -#define _open(...) enclose_io__open(__VA_ARGS__) -#define _wopen(...) enclose_io__wopen(__VA_ARGS__) -#define _wmkdir(...) enclose_io__wmkdir(__VA_ARGS__) -#define _close(...) enclose_io_close(__VA_ARGS__) -#define _open_osfhandle(...) enclose_io_open_osfhandle(__VA_ARGS__) -#define _get_osfhandle(...) enclose_io_get_osfhandle(__VA_ARGS__) -#define _read(...) enclose_io_read(__VA_ARGS__) -#define _lseeki64(...) enclose_io_lseeki64(__VA_ARGS__) - -#define CreateFileW(...) EncloseIOCreateFileW(__VA_ARGS__) -#define CloseHandle(...) EncloseIOCloseHandle(__VA_ARGS__) -#define ReadFile(...) EncloseIOReadFile(__VA_ARGS__) - -#define GetFileAttributesW(...) EncloseIOGetFileAttributesW(__VA_ARGS__) -#define GetFileAttributesExW(...) EncloseIOGetFileAttributesExW(__VA_ARGS__) -#define GetHandleInformation(...) EncloseIOGetHandleInformation(__VA_ARGS__) -#define GetFileType(...) EncloseIOGetFileType(__VA_ARGS__) -#define FindFirstFileW(...) EncloseIOFindFirstFileW(__VA_ARGS__) -#define FindNextFileW(...) EncloseIOFindNextFileW(__VA_ARGS__) -#define FindClose(...) EncloseIOFindClose(__VA_ARGS__) -#define DeviceIoControl(...) EncloseIODeviceIoControl(__VA_ARGS__) -#define CreateIoCompletionPort(...) EncloseIOCreateIoCompletionPort(__VA_ARGS__) -#define ReadDirectoryChangesW(...) EncloseIOReadDirectoryChangesW(__VA_ARGS__) -#define LoadLibraryExW(...) EncloseIOLoadLibraryExW(__VA_ARGS__) -#define CreateProcessW(...) EncloseIOCreateProcessW(__VA_ARGS__) -#define SetCurrentDirectoryW(...) EncloseIOSetCurrentDirectoryW(__VA_ARGS__) -#define GetCurrentDirectoryW(...) EncloseIOGetCurrentDirectoryW(__VA_ARGS__) -#define GetFullPathNameW(...) EncloseIOGetFullPathNameW(__VA_ARGS__) -#define GetFileInformationByHandle(...) EncloseIOGetFileInformationByHandle(__VA_ARGS__) - -#endif //_WIN32 -#endif //!__cplusplus -#endif diff --git a/ruby/enclose_io_winapi.h b/ruby/enclose_io_winapi.h deleted file mode 100644 index 162ce0252..000000000 --- a/ruby/enclose_io_winapi.h +++ /dev/null @@ -1,246 +0,0 @@ -/* -* Copyright (c) 2017 - 2020 Minqi Pan -* Shengyuan Liu -* -* This file is part of libsquash, distributed under the MIT License -* For full terms see the included LICENSE file -*/ - -#ifndef ENCLOSE_IO_WINAPI_H_VD6Y96RT -#define ENCLOSE_IO_WINAPI_H_VD6Y96RT - -#ifndef STATUS_NO_MORE_FILES -# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L) -#endif - -#ifndef STATUS_NOT_IMPLEMENTED -# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L) -#endif - -#ifndef STATUS_SUCCESS -# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) -#endif - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - }; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -typedef VOID (NTAPI *PIO_APC_ROUTINE) - (PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved); - -typedef enum _FILE_INFORMATION_CLASS { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileObjectIdInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileQuotaInformation, - FileReparsePointInformation, - FileNetworkOpenInformation, - FileAttributeTagInformation, - FileTrackingInformation, - FileIdBothDirectoryInformation, - FileIdFullDirectoryInformation, - FileValidDataLengthInformation, - FileShortNameInformation, - FileIoCompletionNotificationInformation, - FileIoStatusBlockRangeInformation, - FileIoPriorityHintInformation, - FileSfioReserveInformation, - FileSfioVolumeInformation, - FileHardLinkInformation, - FileProcessIdsUsingFileInformation, - FileNormalizedNameInformation, - FileNetworkPhysicalNameInformation, - FileIdGlobalTxDirectoryInformation, - FileIsRemoteDeviceInformation, - FileAttributeCacheInformation, - FileNumaNodeInformation, - FileStandardLinkInformation, - FileRemoteProtocolInformation, - FileMaximumInformation -} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; - -/* from winternl.h */ -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING, *PUNICODE_STRING; - -typedef NTSTATUS(NTAPI *sNtQueryDirectoryFile) -(HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass, - BOOLEAN ReturnSingleEntry, - PUNICODE_STRING FileName, - BOOLEAN RestartScan - ); - -typedef struct _FILE_DIRECTORY_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; - -typedef NTSTATUS(NTAPI *sNtQueryInformationFile) -(HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -typedef enum _FS_INFORMATION_CLASS { - FileFsVolumeInformation = 1, - FileFsLabelInformation = 2, - FileFsSizeInformation = 3, - FileFsDeviceInformation = 4, - FileFsAttributeInformation = 5, - FileFsControlInformation = 6, - FileFsFullSizeInformation = 7, - FileFsObjectIdInformation = 8, - FileFsDriverPathInformation = 9, - FileFsVolumeFlagsInformation = 10, - FileFsSectorSizeInformation = 11 -} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; - -typedef NTSTATUS(NTAPI *sNtQueryVolumeInformationFile) -(HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FsInformation, - ULONG Length, - FS_INFORMATION_CLASS FsInformationClass); - -typedef struct _FILE_BASIC_INFORMATION { - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - DWORD FileAttributes; -} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; - -typedef struct _FILE_STANDARD_INFORMATION { - LARGE_INTEGER AllocationSize; - LARGE_INTEGER EndOfFile; - ULONG NumberOfLinks; - BOOLEAN DeletePending; - BOOLEAN Directory; -} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; - -typedef struct _FILE_INTERNAL_INFORMATION { - LARGE_INTEGER IndexNumber; -} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; - -typedef struct _FILE_EA_INFORMATION { - ULONG EaSize; -} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; - -typedef struct _FILE_ACCESS_INFORMATION { - ACCESS_MASK AccessFlags; -} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; - -typedef struct _FILE_POSITION_INFORMATION { - LARGE_INTEGER CurrentByteOffset; -} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; - -typedef struct _FILE_MODE_INFORMATION { - ULONG Mode; -} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; - -typedef struct _FILE_ALIGNMENT_INFORMATION { - ULONG AlignmentRequirement; -} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; - -typedef struct _FILE_NAME_INFORMATION { - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; - -typedef struct _FILE_ALL_INFORMATION { - FILE_BASIC_INFORMATION BasicInformation; - FILE_STANDARD_INFORMATION StandardInformation; - FILE_INTERNAL_INFORMATION InternalInformation; - FILE_EA_INFORMATION EaInformation; - FILE_ACCESS_INFORMATION AccessInformation; - FILE_POSITION_INFORMATION PositionInformation; - FILE_MODE_INFORMATION ModeInformation; - FILE_ALIGNMENT_INFORMATION AlignmentInformation; - FILE_NAME_INFORMATION NameInformation; -} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; - -extern sNtQueryDirectoryFile pNtQueryDirectoryFile; -extern sNtQueryInformationFile pNtQueryInformationFile; -extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; - -typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; - -#endif diff --git a/ruby/encoding.c b/ruby/encoding.c index 69015cc8f..273710837 100644 --- a/ruby/encoding.c +++ b/ruby/encoding.c @@ -9,14 +9,25 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "internal.h" +#include "ruby/internal/config.h" + +#include + #include "encindex.h" +#include "internal.h" +#include "internal/enc.h" +#include "internal/encoding.h" +#include "internal/inits.h" +#include "internal/load.h" +#include "internal/object.h" +#include "internal/string.h" +#include "internal/vm.h" #include "regenc.h" -#include +#include "ruby/encoding.h" #include "ruby/util.h" - #include "ruby_assert.h" +#include "vm_sync.h" + #ifndef ENC_DEBUG #define ENC_DEBUG 0 #endif @@ -44,7 +55,10 @@ void rb_encdb_set_unicode(int index); static ID id_encoding; VALUE rb_cEncoding; -static VALUE rb_encoding_list; + +#define DEFAULT_ENCODING_LIST_CAPA 128 +static VALUE rb_default_encoding_list; +static VALUE rb_additional_encoding_list; struct rb_encoding_entry { const char *name; @@ -52,12 +66,27 @@ struct rb_encoding_entry { rb_encoding *base; }; -static struct { +static struct enc_table { struct rb_encoding_entry *list; int count; int size; st_table *names; -} enc_table; +} global_enc_table; + +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 ENC_DUMMY_FLAG (1<<24) #define ENC_INDEX_MASK (~(~0U<<24)) @@ -72,10 +101,6 @@ static struct { #define ENCODING_NAMELEN_MAX 63 #define valid_encoding_name_p(name) ((name) && strlen(name) <= ENCODING_NAMELEN_MAX) -#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc)) - -static int load_encoding(const char *name); - static const rb_data_type_t encoding_data_type = { "encoding", {0, 0, 0,}, @@ -94,22 +119,69 @@ rb_data_is_encoding(VALUE obj) static VALUE enc_new(rb_encoding *encoding) { - return TypedData_Wrap_Struct(rb_cEncoding, &encoding_data_type, (void *)encoding); + VALUE enc = TypedData_Wrap_Struct(rb_cEncoding, &encoding_data_type, (void *)encoding); + rb_obj_freeze(enc); + FL_SET_RAW(enc, RUBY_FL_SHAREABLE); + return enc; +} + +static void +enc_list_update(int index, rb_raw_encoding *encoding) +{ + if (index < DEFAULT_ENCODING_LIST_CAPA) { + VALUE list = rb_default_encoding_list; + if (list && NIL_P(rb_ary_entry(list, index))) { + /* initialize encoding data */ + rb_ary_store(list, index, enc_new(encoding)); + } + } + else { + RB_VM_LOCK_ENTER(); + { + VALUE list = rb_additional_encoding_list; + if (list && NIL_P(rb_ary_entry(list, index))) { + /* initialize encoding data */ + rb_ary_store(list, index - DEFAULT_ENCODING_LIST_CAPA, enc_new(encoding)); + } + } + RB_VM_LOCK_LEAVE(); + } } static VALUE -rb_enc_from_encoding_index(int idx) +enc_list_lookup(int idx) { VALUE list, enc; - if (!(list = rb_encoding_list)) { - rb_bug("rb_enc_from_encoding_index(%d): no rb_encoding_list", idx); + if (idx < DEFAULT_ENCODING_LIST_CAPA) { + if (!(list = rb_default_encoding_list)) { + rb_bug("rb_enc_from_encoding_index(%d): no rb_default_encoding_list", idx); + } + enc = rb_ary_entry(list, idx); } - enc = rb_ary_entry(list, idx); + else { + RB_VM_LOCK_ENTER(); + { + if (!(list = rb_additional_encoding_list)) { + rb_bug("rb_enc_from_encoding_index(%d): no rb_additional_encoding_list", idx); + } + enc = rb_ary_entry(list, idx - DEFAULT_ENCODING_LIST_CAPA); + } + RB_VM_LOCK_LEAVE(); + } + if (NIL_P(enc)) { - rb_bug("rb_enc_from_encoding_index(%d): not created yet", idx); + rb_bug("rb_enc_from_encoding_index(%d): not created yet", idx); + } + else { + return enc; } - return enc; +} + +static VALUE +rb_enc_from_encoding_index(int idx) +{ + return enc_list_lookup(idx); } VALUE @@ -133,16 +205,14 @@ rb_enc_dummy_p(rb_encoding *enc) return ENC_DUMMY_P(enc) != 0; } -static int enc_autoload(rb_encoding *); - static int check_encoding(rb_encoding *enc) { int index = rb_enc_to_index(enc); if (rb_enc_from_index(index) != enc) return -1; - if (enc_autoload_p(enc)) { - index = enc_autoload(enc); + if (rb_enc_autoload_p(enc)) { + index = rb_enc_autoload(enc); } return index; } @@ -186,7 +256,7 @@ must_encindex(int index) rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)", index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc)); } - if (enc_autoload_p(enc) && enc_autoload(enc) == -1) { + if (rb_enc_autoload_p(enc) && rb_enc_autoload(enc) == -1) { rb_loaderror("failed to load encoding (%s)", rb_enc_name(enc)); } @@ -197,6 +267,7 @@ int rb_to_encoding_index(VALUE enc) { int idx; + const char *name; idx = enc_check_encoding(enc); if (idx >= 0) { @@ -208,20 +279,33 @@ rb_to_encoding_index(VALUE enc) if (!rb_enc_asciicompat(rb_enc_get(enc))) { return -1; } - return rb_enc_find_index(StringValueCStr(enc)); + if (!(name = rb_str_to_cstr(enc))) { + return -1; + } + return rb_enc_find_index(name); +} + +static const char * +name_for_encoding(volatile VALUE *enc) +{ + VALUE name = StringValue(*enc); + const char *n; + + if (!rb_enc_asciicompat(rb_enc_get(name))) { + rb_raise(rb_eArgError, "invalid encoding name (non ASCII)"); + } + if (!(n = rb_str_to_cstr(name))) { + rb_raise(rb_eArgError, "invalid encoding name (NUL byte)"); + } + return n; } /* Returns encoding index or UNSPECIFIED_ENCODING */ static int str_find_encindex(VALUE enc) { - int idx; - - StringValue(enc); - if (!rb_enc_asciicompat(rb_enc_get(enc))) { - rb_raise(rb_eArgError, "invalid name encoding (non ASCII)"); - } - idx = rb_enc_find_index(StringValueCStr(enc)); + int idx = rb_enc_find_index(name_for_encoding(&enc)); + RB_GC_GUARD(enc); return idx; } @@ -259,26 +343,25 @@ rb_find_encoding(VALUE enc) } static int -enc_table_expand(int newsize) +enc_table_expand(struct enc_table *enc_table, int newsize) { struct rb_encoding_entry *ent; int count = newsize; - if (enc_table.size >= newsize) return newsize; + if (enc_table->size >= newsize) return newsize; newsize = (newsize + 7) / 8 * 8; - ent = REALLOC_N(enc_table.list, struct rb_encoding_entry, newsize); - memset(ent + enc_table.size, 0, sizeof(*ent)*(newsize - enc_table.size)); - enc_table.list = ent; - enc_table.size = newsize; + ent = REALLOC_N(enc_table->list, struct rb_encoding_entry, newsize); + memset(ent + enc_table->size, 0, sizeof(*ent)*(newsize - enc_table->size)); + enc_table->list = ent; + enc_table->size = newsize; return count; } static int -enc_register_at(int index, const char *name, rb_encoding *base_encoding) +enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_encoding *base_encoding) { - struct rb_encoding_entry *ent = &enc_table.list[index]; + struct rb_encoding_entry *ent = &enc_table->list[index]; rb_raw_encoding *encoding; - VALUE list; if (!valid_encoding_name_p(name)) return -1; if (!ent->name) { @@ -300,76 +383,121 @@ enc_register_at(int index, const char *name, rb_encoding *base_encoding) encoding->name = name; encoding->ruby_encoding_index = index; ent->enc = encoding; - st_insert(enc_table.names, (st_data_t)name, (st_data_t)index); - list = rb_encoding_list; - if (list && NIL_P(rb_ary_entry(list, index))) { - /* initialize encoding data */ - rb_ary_store(list, index, enc_new(encoding)); - } + st_insert(enc_table->names, (st_data_t)name, (st_data_t)index); + + enc_list_update(index, encoding); return index; } static int -enc_register(const char *name, rb_encoding *encoding) +enc_register(struct enc_table *enc_table, const char *name, rb_encoding *encoding) { - int index = enc_table.count; + int index = enc_table->count; - if ((index = enc_table_expand(index + 1)) < 0) return -1; - enc_table.count = index; - return enc_register_at(index - 1, name, encoding); + enc_table->count = enc_table_expand(enc_table, index + 1); + return enc_register_at(enc_table, index, name, encoding); } static void set_encoding_const(const char *, rb_encoding *); -int rb_enc_registered(const char *name); +static int enc_registered(struct enc_table *enc_table, const char *name); + +static rb_encoding * +enc_from_index(struct enc_table *enc_table, int index) +{ + if (UNLIKELY(index < 0 || enc_table->count <= (index &= ENC_INDEX_MASK))) { + return 0; + } + return enc_table->list[index].enc; +} + +rb_encoding * +rb_enc_from_index(int index) +{ + rb_encoding *enc; + + switch (index) { + case ENCINDEX_ASCII: return global_enc_ascii; + case ENCINDEX_UTF_8: return global_enc_utf_8; + case ENCINDEX_US_ASCII: return global_enc_us_ascii; + default: + GLOBAL_ENC_TABLE_EVAL(enc_table, + enc = enc_from_index(enc_table, index)); + return enc; + } +} int rb_enc_register(const char *name, rb_encoding *encoding) { - int index = rb_enc_registered(name); + int index; + + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + index = enc_registered(enc_table, name); + + if (index >= 0) { + rb_encoding *oldenc = enc_from_index(enc_table, index); + if (STRCASECMP(name, rb_enc_name(oldenc))) { + index = enc_register(enc_table, name, encoding); + } + else if (rb_enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) { + enc_register_at(enc_table, index, name, encoding); + } + else { + rb_raise(rb_eArgError, "encoding %s is already registered", name); + } + } + else { + index = enc_register(enc_table, name, encoding); + set_encoding_const(name, rb_enc_from_index(index)); + } + } + GLOBAL_ENC_TABLE_LEAVE(); + return index; +} - if (index >= 0) { - rb_encoding *oldenc = rb_enc_from_index(index); - if (STRCASECMP(name, rb_enc_name(oldenc))) { - index = enc_register(name, encoding); - } - else if (enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) { - enc_register_at(index, name, encoding); - } - else { - rb_raise(rb_eArgError, "encoding %s is already registered", name); - } - } - else { - index = enc_register(name, encoding); - set_encoding_const(name, rb_enc_from_index(index)); +int +enc_registered(struct enc_table *enc_table, const char *name) +{ + st_data_t idx = 0; + + if (!name) return -1; + if (!enc_table->list) return -1; + if (st_lookup(enc_table->names, (st_data_t)name, &idx)) { + return (int)idx; } - return index; + return -1; } void rb_encdb_declare(const char *name) { - int idx = rb_enc_registered(name); - if (idx < 0) { - idx = enc_register(name, 0); + GLOBAL_ENC_TABLE_ENTER(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)); } - set_encoding_const(name, rb_enc_from_index(idx)); + GLOBAL_ENC_TABLE_LEAVE(); } static void -enc_check_duplication(const char *name) +enc_check_duplication(struct enc_table *enc_table, const char *name) { - if (rb_enc_registered(name) >= 0) { + if (enc_registered(enc_table, name) >= 0) { rb_raise(rb_eArgError, "encoding %s is already registered", name); } } static rb_encoding* -set_base_encoding(int index, rb_encoding *base) +set_base_encoding(struct enc_table *enc_table, int index, rb_encoding *base) { - rb_encoding *enc = enc_table.list[index].enc; + rb_encoding *enc = enc_table->list[index].enc; - enc_table.list[index].base = base; + ASSUME(enc); + enc_table->list[index].base = base; if (ENC_DUMMY_P(base)) ENC_SET_DUMMY((rb_raw_encoding *)enc); return enc; } @@ -381,9 +509,13 @@ set_base_encoding(int index, rb_encoding *base) void rb_enc_set_base(const char *name, const char *orig) { - int idx = rb_enc_registered(name); - int origidx = rb_enc_registered(orig); - set_base_encoding(idx, rb_enc_from_index(origidx)); + GLOBAL_ENC_TABLE_ENTER(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 @@ -392,24 +524,39 @@ rb_enc_set_base(const char *name, const char *orig) int rb_enc_set_dummy(int index) { - rb_encoding *enc = enc_table.list[index].enc; + rb_encoding *enc; + + GLOBAL_ENC_TABLE_EVAL(enc_table, + enc = enc_table->list[index].enc); ENC_SET_DUMMY((rb_raw_encoding *)enc); return index; } -int -rb_enc_replicate(const char *name, rb_encoding *encoding) +static int +enc_replicate(struct enc_table *enc_table, const char *name, rb_encoding *encoding) { int idx; - enc_check_duplication(name); - idx = enc_register(name, encoding); - set_base_encoding(idx, encoding); + enc_check_duplication(enc_table, name); + idx = enc_register(enc_table, name, encoding); + if (idx < 0) rb_raise(rb_eArgError, "invalid encoding name: %s", name); + set_base_encoding(enc_table, idx, encoding); set_encoding_const(name, rb_enc_from_index(idx)); return idx; } +int +rb_enc_replicate(const char *name, rb_encoding *encoding) +{ + int r; + + GLOBAL_ENC_TABLE_EVAL(enc_table, + r = enc_replicate(enc_table, name, encoding)); + + return r; +} + /* * call-seq: * enc.replicate(name) -> encoding @@ -420,24 +567,24 @@ rb_enc_replicate(const char *name, rb_encoding *encoding) * */ static VALUE -enc_replicate(VALUE encoding, VALUE name) +enc_replicate_m(VALUE encoding, VALUE name) { - return rb_enc_from_encoding_index( - rb_enc_replicate(StringValueCStr(name), - rb_to_encoding(encoding))); + int idx = rb_enc_replicate(name_for_encoding(&name), rb_to_encoding(encoding)); + RB_GC_GUARD(name); + return rb_enc_from_encoding_index(idx); } static int -enc_replicate_with_index(const char *name, rb_encoding *origenc, int idx) +enc_replicate_with_index(struct enc_table *enc_table, const char *name, rb_encoding *origenc, int idx) { if (idx < 0) { - idx = enc_register(name, origenc); + idx = enc_register(enc_table, name, origenc); } else { - idx = enc_register_at(idx, name, origenc); + idx = enc_register_at(enc_table, idx, name, origenc); } if (idx >= 0) { - set_base_encoding(idx, origenc); + set_base_encoding(enc_table, idx, origenc); set_encoding_const(name, rb_enc_from_index(idx)); } else { @@ -449,33 +596,54 @@ enc_replicate_with_index(const char *name, rb_encoding *origenc, int idx) int rb_encdb_replicate(const char *name, const char *orig) { - int origidx = rb_enc_registered(orig); - int idx = rb_enc_registered(name); + int r; + + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + int origidx = enc_registered(enc_table, orig); + int idx = enc_registered(enc_table, name); - if (origidx < 0) { - origidx = enc_register(orig, 0); + if (origidx < 0) { + origidx = enc_register(enc_table, orig, 0); + } + r = enc_replicate_with_index(enc_table, name, rb_enc_from_index(origidx), idx); } - return enc_replicate_with_index(name, rb_enc_from_index(origidx), idx); + GLOBAL_ENC_TABLE_LEAVE(); + + return r; } int rb_define_dummy_encoding(const char *name) { - int index = rb_enc_replicate(name, rb_ascii8bit_encoding()); - rb_encoding *enc = enc_table.list[index].enc; + int index; + + GLOBAL_ENC_TABLE_ENTER(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(); - ENC_SET_DUMMY((rb_raw_encoding *)enc); return index; } int rb_encdb_dummy(const char *name) { - int index = enc_replicate_with_index(name, rb_ascii8bit_encoding(), - rb_enc_registered(name)); - rb_encoding *enc = enc_table.list[index].enc; + int index; + + GLOBAL_ENC_TABLE_ENTER(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(); - ENC_SET_DUMMY((rb_raw_encoding *)enc); return index; } @@ -495,7 +663,7 @@ rb_encdb_dummy(const char *name) static VALUE enc_dummy_p(VALUE enc) { - return ENC_DUMMY_P(must_encoding(enc)) ? Qtrue : Qfalse; + return RBOOL(ENC_DUMMY_P(must_encoding(enc))); } /* @@ -511,7 +679,7 @@ enc_dummy_p(VALUE enc) static VALUE enc_ascii_compatible_p(VALUE enc) { - return rb_enc_asciicompat(must_encoding(enc)) ? Qtrue : Qfalse; + return RBOOL(rb_enc_asciicompat(must_encoding(enc))); } /* @@ -534,63 +702,84 @@ enc_dup_name(st_data_t name) * else returns NULL. */ static int -enc_alias_internal(const char *alias, int idx) +enc_alias_internal(struct enc_table *enc_table, const char *alias, int idx) { - return st_insert2(enc_table.names, (st_data_t)alias, (st_data_t)idx, + return st_insert2(enc_table->names, (st_data_t)alias, (st_data_t)idx, enc_dup_name); } static int -enc_alias(const char *alias, int idx) +enc_alias(struct enc_table *enc_table, const char *alias, int idx) { if (!valid_encoding_name_p(alias)) return -1; - if (!enc_alias_internal(alias, idx)) - set_encoding_const(alias, rb_enc_from_index(idx)); + if (!enc_alias_internal(enc_table, alias, idx)) + set_encoding_const(alias, enc_from_index(enc_table, idx)); return idx; } int rb_enc_alias(const char *alias, const char *orig) { - int idx; + int idx, r; - enc_check_duplication(alias); - if ((idx = rb_enc_find_index(orig)) < 0) { - return -1; + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + enc_check_duplication(enc_table, alias); + if ((idx = rb_enc_find_index(orig)) < 0) { + r = -1; + } + else { + r = enc_alias(enc_table, alias, idx); + } } - return enc_alias(alias, idx); + GLOBAL_ENC_TABLE_LEAVE(); + + return r; } int rb_encdb_alias(const char *alias, const char *orig) { - int idx = rb_enc_registered(orig); + int r; - if (idx < 0) { - idx = enc_register(orig, 0); + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + int idx = enc_registered(enc_table, orig); + + if (idx < 0) { + idx = enc_register(enc_table, orig, 0); + } + r = enc_alias(enc_table, alias, idx); } - return enc_alias(alias, idx); + GLOBAL_ENC_TABLE_LEAVE(); + + return r; } void rb_encdb_set_unicode(int index) { - ((rb_raw_encoding *)rb_enc_from_index(index))->flags |= ONIGENC_FLAG_UNICODE; + rb_raw_encoding *enc = (rb_raw_encoding *)rb_enc_from_index(index); + ASSUME(enc); + enc->flags |= ONIGENC_FLAG_UNICODE; } -void -rb_enc_init(void) +static void +rb_enc_init(struct enc_table *enc_table) { - enc_table_expand(ENCODING_COUNT + 1); - if (!enc_table.names) { - enc_table.names = st_init_strcasetable(); + enc_table_expand(enc_table, ENCODING_COUNT + 1); + if (!enc_table->names) { + enc_table->names = st_init_strcasetable(); } -#define ENC_REGISTER(enc) enc_register_at(ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc) +#define ENC_REGISTER(enc) enc_register_at(enc_table, ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc) ENC_REGISTER(ASCII); ENC_REGISTER(UTF_8); ENC_REGISTER(US_ASCII); + global_enc_ascii = enc_table->list[ENCINDEX_ASCII].enc; + global_enc_utf_8 = enc_table->list[ENCINDEX_UTF_8].enc; + global_enc_us_ascii = enc_table->list[ENCINDEX_US_ASCII].enc; #undef ENC_REGISTER -#define ENCDB_REGISTER(name, enc) enc_register_at(ENCINDEX_##enc, name, NULL) +#define ENCDB_REGISTER(name, enc) enc_register_at(enc_table, ENCINDEX_##enc, name, NULL) ENCDB_REGISTER("UTF-16BE", UTF_16BE); ENCDB_REGISTER("UTF-16LE", UTF_16LE); ENCDB_REGISTER("UTF-32BE", UTF_32BE); @@ -602,16 +791,7 @@ rb_enc_init(void) ENCDB_REGISTER("EUC-JP", EUC_JP); ENCDB_REGISTER("Windows-31J", Windows_31J); #undef ENCDB_REGISTER - enc_table.count = ENCINDEX_BUILTIN_MAX; -} - -rb_encoding * -rb_enc_from_index(int index) -{ - if (UNLIKELY(index < 0 || enc_table.count <= (index &= ENC_INDEX_MASK))) { - return 0; - } - return enc_table.list[index].enc; + enc_table->count = ENCINDEX_BUILTIN_MAX; } rb_encoding * @@ -620,24 +800,12 @@ rb_enc_get_from_index(int index) return must_encindex(index); } -int -rb_enc_registered(const char *name) -{ - st_data_t idx = 0; - - if (!name) return -1; - if (!enc_table.list) return -1; - if (st_lookup(enc_table.names, (st_data_t)name, &idx)) { - return (int)idx; - } - return -1; -} +int rb_require_internal_silent(VALUE fname); static int load_encoding(const char *name) { VALUE enclib = rb_sprintf("enc/%s.so", name); - VALUE verbose = ruby_verbose; VALUE debug = ruby_debug; VALUE errinfo; char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3; @@ -650,40 +818,60 @@ load_encoding(const char *name) ++s; } enclib = rb_fstring(enclib); - ruby_verbose = Qfalse; ruby_debug = Qfalse; errinfo = rb_errinfo(); - loaded = rb_require_internal(enclib); - ruby_verbose = verbose; + loaded = rb_require_internal_silent(enclib); ruby_debug = debug; rb_set_errinfo(errinfo); - if (loaded < 0 || 1 < loaded) return -1; - if ((idx = rb_enc_registered(name)) < 0) return -1; - if (enc_autoload_p(enc_table.list[idx].enc)) return -1; + + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + if (loaded < 0 || 1 < loaded) { + idx = -1; + } + else if ((idx = enc_registered(enc_table, name)) < 0) { + idx = -1; + } + else if (rb_enc_autoload_p(enc_table->list[idx].enc)) { + idx = -1; + } + } + GLOBAL_ENC_TABLE_LEAVE(); + return idx; } static int -enc_autoload(rb_encoding *enc) +enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc) { - int i; - rb_encoding *base = enc_table.list[ENC_TO_ENCINDEX(enc)].base; + rb_encoding *base = enc_table->list[ENC_TO_ENCINDEX(enc)].base; if (base) { - i = 0; + int i = 0; do { - if (i >= enc_table.count) return -1; - } while (enc_table.list[i].enc != base && (++i, 1)); - if (enc_autoload_p(base)) { - if (enc_autoload(base) < 0) return -1; + 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(i & ENC_INDEX_MASK, rb_enc_name(enc), base); - ((rb_raw_encoding *)enc)->ruby_encoding_index = i; + 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 { - i = load_encoding(rb_enc_name(enc)); + return -2; + } +} + +int +rb_enc_autoload(rb_encoding *enc) +{ + int i; + GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_autoload_body(enc_table, enc)); + if (i == -2) { + i = load_encoding(rb_enc_name(enc)); } return i; } @@ -692,9 +880,11 @@ enc_autoload(rb_encoding *enc) int rb_enc_find_index(const char *name) { - int i = rb_enc_registered(name); + int i; rb_encoding *enc; + GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_registered(enc_table, name)); + if (i < 0) { i = load_encoding(name); } @@ -703,8 +893,8 @@ rb_enc_find_index(const char *name) rb_raise(rb_eArgError, "encoding %s is not registered", name); } } - else if (enc_autoload_p(enc)) { - if (enc_autoload(enc) < 0) { + else if (rb_enc_autoload_p(enc)) { + if (rb_enc_autoload(enc) < 0) { rb_warn("failed to load encoding (%s); use ASCII-8BIT instead", name); return 0; @@ -769,8 +959,18 @@ enc_get_index_str(VALUE str) if (i == ENCODING_INLINE_MAX) { VALUE iv; +#if 0 iv = rb_ivar_get(str, rb_id_encoding()); i = NUM2INT(iv); +#else + /* + * Tentatively, assume ASCII-8BIT, if encoding index instance + * variable is not found. This can happen when freeing after + * all instance variables are removed in `obj_free`. + */ + iv = rb_attr_get(str, rb_id_encoding()); + i = NIL_P(iv) ? ENCINDEX_ASCII : NUM2INT(iv); +#endif } return i; } @@ -874,12 +1074,9 @@ rb_enc_get(VALUE obj) return rb_enc_from_index(rb_enc_get_index(obj)); } -static rb_encoding* enc_compatible_str(VALUE str1, VALUE str2); - -rb_encoding* -rb_enc_check_str(VALUE str1, VALUE str2) +static rb_encoding* +rb_encoding_check(rb_encoding* enc, VALUE str1, VALUE str2) { - rb_encoding *enc = enc_compatible_str(MUST_STRING(str1), MUST_STRING(str2)); if (!enc) rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", rb_enc_name(rb_enc_get(str1)), @@ -887,15 +1084,20 @@ rb_enc_check_str(VALUE str1, VALUE str2) return enc; } +static rb_encoding* enc_compatible_str(VALUE str1, VALUE str2); + +rb_encoding* +rb_enc_check_str(VALUE str1, VALUE str2) +{ + rb_encoding *enc = enc_compatible_str(MUST_STRING(str1), MUST_STRING(str2)); + return rb_encoding_check(enc, str1, str2); +} + rb_encoding* rb_enc_check(VALUE str1, VALUE str2) { rb_encoding *enc = rb_enc_compatible(str1, 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))); - return enc; + return rb_encoding_check(enc, str1, str2); } static rb_encoding* @@ -909,7 +1111,7 @@ enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2) if (isstr2 && RSTRING_LEN(str2) == 0) return enc1; isstr1 = RB_TYPE_P(str1, T_STRING); - if (isstr1 && RSTRING_LEN(str1) == 0) + if (isstr1 && isstr2 && RSTRING_LEN(str1) == 0) return (rb_enc_asciicompat(enc1) && rb_enc_str_asciionly_p(str2)) ? enc1 : enc2; if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) { return 0; @@ -1078,13 +1280,6 @@ rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc) return rb_enc_mbc_to_codepoint(p, e, enc); } -#undef rb_enc_codepoint -unsigned int -rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc) -{ - return rb_enc_codepoint_len(p, e, 0, enc); -} - int rb_enc_codelen(int c, rb_encoding *enc) { @@ -1095,13 +1290,6 @@ rb_enc_codelen(int c, rb_encoding *enc) return n; } -#undef rb_enc_code_to_mbclen -int -rb_enc_code_to_mbclen(int code, rb_encoding *enc) -{ - return ONIGENC_CODE_TO_MBCLEN(enc, code); -} - int rb_enc_toupper(int c, rb_encoding *enc) { @@ -1138,7 +1326,7 @@ enc_inspect(VALUE self) "#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self), rb_enc_name(enc), (ENC_DUMMY_P(enc) ? " (dummy)" : ""), - enc_autoload_p(enc) ? " (autoload)" : ""); + rb_enc_autoload_p(enc) ? " (autoload)" : ""); } /* @@ -1183,7 +1371,10 @@ enc_names(VALUE self) args[0] = (VALUE)rb_to_encoding_index(self); args[1] = rb_ary_new2(0); - st_foreach(enc_table.names, enc_names_i, (st_data_t)args); + + GLOBAL_ENC_TABLE_EVAL(enc_table, + st_foreach(enc_table->names, enc_names_i, (st_data_t)args)); + return args[1]; } @@ -1209,7 +1400,14 @@ static VALUE enc_list(VALUE klass) { VALUE ary = rb_ary_new2(0); - rb_ary_replace(ary, rb_encoding_list); + + RB_VM_LOCK_ENTER(); + { + rb_ary_replace(ary, rb_default_encoding_list); + rb_ary_concat(ary, rb_additional_encoding_list); + } + RB_VM_LOCK_LEAVE(); + return ary; } @@ -1282,12 +1480,13 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2) return rb_enc_from_encoding(enc); } +NORETURN(static VALUE enc_s_alloc(VALUE klass)); /* :nodoc: */ static VALUE enc_s_alloc(VALUE klass) { rb_undefined_alloc(klass); - return Qnil; + UNREACHABLE_RETURN(Qnil); } /* :nodoc: */ @@ -1315,7 +1514,7 @@ enc_m_loader(VALUE klass, VALUE str) rb_encoding * rb_ascii8bit_encoding(void) { - return enc_table.list[ENCINDEX_ASCII].enc; + return global_enc_ascii; } int @@ -1327,7 +1526,7 @@ rb_ascii8bit_encindex(void) rb_encoding * rb_utf8_encoding(void) { - return enc_table.list[ENCINDEX_UTF_8].enc; + return global_enc_utf_8; } int @@ -1339,7 +1538,7 @@ rb_utf8_encindex(void) rb_encoding * rb_usascii_encoding(void) { - return enc_table.list[ENCINDEX_US_ASCII].enc; + return global_enc_us_ascii; } int @@ -1355,15 +1554,17 @@ rb_locale_encindex(void) { int idx = rb_locale_charmap_index(); - if (idx < 0) idx = ENCINDEX_ASCII; + if (idx < 0) idx = ENCINDEX_UTF_8; - if (rb_enc_registered("locale") < 0) { + GLOBAL_ENC_TABLE_ENTER(enc_table); + if (enc_registered(enc_table, "locale") < 0) { # if defined _WIN32 void Init_w32_codepage(void); Init_w32_codepage(); # endif - enc_alias_internal("locale", idx); + enc_alias_internal(enc_table, "locale", idx); } + GLOBAL_ENC_TABLE_LEAVE(); return idx; } @@ -1377,7 +1578,11 @@ rb_locale_encoding(void) int rb_filesystem_encindex(void) { - int idx = rb_enc_registered("filesystem"); + int idx; + + GLOBAL_ENC_TABLE_EVAL(enc_table, + idx = enc_registered(enc_table, "filesystem")); + if (idx < 0) idx = ENCINDEX_ASCII; return idx; @@ -1405,20 +1610,25 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha /* Already set */ overridden = TRUE; - if (NIL_P(encoding)) { - def->index = -1; - def->enc = 0; - st_insert(enc_table.names, (st_data_t)strdup(name), - (st_data_t)UNSPECIFIED_ENCODING); - } - else { - def->index = rb_enc_to_index(rb_to_encoding(encoding)); - def->enc = 0; - enc_alias_internal(name, def->index); - } - - if (def == &default_external) - enc_alias_internal("filesystem", Init_enc_set_filesystem_encoding()); + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + if (NIL_P(encoding)) { + def->index = -1; + def->enc = 0; + st_insert(enc_table->names, (st_data_t)strdup(name), + (st_data_t)UNSPECIFIED_ENCODING); + } + else { + def->index = rb_enc_to_index(rb_to_encoding(encoding)); + def->enc = 0; + enc_alias_internal(enc_table, name, def->index); + } + + if (def == &default_external) { + enc_alias_internal(enc_table, "filesystem", Init_enc_set_filesystem_encoding()); + } + } + GLOBAL_ENC_TABLE_LEAVE(); return overridden; } @@ -1465,9 +1675,11 @@ rb_enc_default_external(void) * encoding may not be valid. Be sure to check String#valid_encoding?. * * File data written to disk will be transcoded to the default external - * encoding when written. + * encoding when written, if default_internal is not nil. * - * The default external encoding is initialized by the locale or -E option. + * The default external encoding is initialized by the -E option. + * If -E isn't set, it is initialized to UTF-8 on Windows and the locale on + * other operating systems. */ static VALUE get_default_external(VALUE klass) @@ -1550,8 +1762,7 @@ rb_enc_default_internal(void) * The script encoding (__ENCODING__), not default_internal, is used as the * encoding of created strings. * - * Encoding::default_internal is initialized by the source file's - * internal_encoding or -E option. + * Encoding::default_internal is initialized with -E option or nil otherwise. */ static VALUE get_default_internal(VALUE klass) @@ -1664,8 +1875,15 @@ rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg) static VALUE rb_enc_name_list(VALUE klass) { - VALUE ary = rb_ary_new2(enc_table.names->num_entries); - st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary); + VALUE ary; + + GLOBAL_ENC_TABLE_ENTER(enc_table); + { + ary = rb_ary_new2(enc_table->names->num_entries); + st_foreach(enc_table->names, rb_enc_name_list_i, (st_data_t)ary); + } + GLOBAL_ENC_TABLE_LEAVE(); + return ary; } @@ -1710,7 +1928,10 @@ rb_enc_aliases(VALUE klass) VALUE aliases[2]; aliases[0] = rb_hash_new(); aliases[1] = rb_ary_new(); - st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases); + + GLOBAL_ENC_TABLE_EVAL(enc_table, + st_foreach(enc_table->names, rb_enc_aliases_enc_i, (st_data_t)aliases)); + return aliases[0]; } @@ -1918,8 +2139,6 @@ rb_enc_aliases(VALUE klass) void Init_Encoding(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) VALUE list; int i; @@ -1932,7 +2151,7 @@ Init_Encoding(void) rb_define_method(rb_cEncoding, "names", enc_names, 0); rb_define_method(rb_cEncoding, "dummy?", enc_dummy_p, 0); rb_define_method(rb_cEncoding, "ascii_compatible?", enc_ascii_compatible_p, 0); - rb_define_method(rb_cEncoding, "replicate", enc_replicate, 1); + rb_define_method(rb_cEncoding, "replicate", enc_replicate_m, 1); rb_define_singleton_method(rb_cEncoding, "list", enc_list, 0); rb_define_singleton_method(rb_cEncoding, "name_list", rb_enc_name_list, 0); rb_define_singleton_method(rb_cEncoding, "aliases", rb_enc_aliases, 0); @@ -1948,22 +2167,29 @@ Init_Encoding(void) rb_define_singleton_method(rb_cEncoding, "default_internal=", set_default_internal, 1); rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0); /* in localeinit.c */ - list = rb_ary_new2(enc_table.count); + struct enc_table *enc_table = &global_enc_table; + + if (DEFAULT_ENCODING_LIST_CAPA < enc_table->count) rb_bug("DEFAULT_ENCODING_LIST_CAPA is too small"); + + list = rb_additional_encoding_list = rb_ary_new(); + RBASIC_CLEAR_CLASS(list); + rb_gc_register_mark_object(list); + + list = rb_default_encoding_list = rb_ary_new2(DEFAULT_ENCODING_LIST_CAPA); RBASIC_CLEAR_CLASS(list); - rb_encoding_list = list; rb_gc_register_mark_object(list); - for (i = 0; i < enc_table.count; ++i) { - rb_ary_push(list, enc_new(enc_table.list[i].enc)); + for (i = 0; i < enc_table->count; ++i) { + rb_ary_push(list, enc_new(enc_table->list[i].enc)); } - rb_marshal_define_compat(rb_cEncoding, Qnil, NULL, enc_m_loader); + rb_marshal_define_compat(rb_cEncoding, Qnil, 0, enc_m_loader); } void Init_encodings(void) { - rb_enc_init(); + rb_enc_init(&global_enc_table); } /* locale insensitive ctype functions */ @@ -1971,5 +2197,5 @@ Init_encodings(void) void rb_enc_foreach_name(int (*func)(st_data_t name, st_data_t idx, st_data_t arg), st_data_t arg) { - st_foreach(enc_table.names, func, arg); + GLOBAL_ENC_TABLE_EVAL(enc_table, st_foreach(enc_table->names, func, arg)); } diff --git a/ruby/enum.c b/ruby/enum.c index cc77964ff..f8e327ff7 100644 --- a/ruby/enum.c +++ b/ruby/enum.c @@ -9,17 +9,37 @@ **********************************************************************/ -#include "ruby/encoding.h" +#include "id.h" #include "internal.h" +#include "internal/compar.h" +#include "internal/enum.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/rational.h" +#include "internal/re.h" #include "ruby/util.h" -#include "id.h" +#include "ruby_assert.h" #include "symbol.h" -#include - VALUE rb_mEnumerable; static ID id_next; +static ID id__alone; +static ID id__separator; +static ID id_chunk_categorize; +static ID id_chunk_enumerable; +static ID id_sliceafter_enum; +static ID id_sliceafter_pat; +static ID id_sliceafter_pred; +static ID id_slicebefore_enumerable; +static ID id_slicebefore_sep_pat; +static ID id_slicebefore_sep_pred; +static ID id_slicewhen_enum; +static ID id_slicewhen_inverted; +static ID id_slicewhen_pred; #define id_div idDiv #define id_each idEach @@ -75,6 +95,22 @@ grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) return Qnil; } +static VALUE +grep_regexp_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) +{ + struct MEMO *memo = MEMO_CAST(args); + VALUE converted_element, match; + ENUM_WANT_SVALUE(); + + /* In case element can't be converted to a Symbol or String: not a match (don't raise) */ + converted_element = SYMBOL_P(i) ? i : rb_check_string_type(i); + match = NIL_P(converted_element) ? Qfalse : rb_reg_match_p(memo->v1, i, 0); + if (match == memo->u3.value) { + rb_ary_push(memo->v2, i); + } + return Qnil; +} + static VALUE grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) { @@ -87,59 +123,88 @@ grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) return Qnil; } +static VALUE +enum_grep0(VALUE obj, VALUE pat, VALUE test) +{ + VALUE ary = rb_ary_new(); + struct MEMO *memo = MEMO_NEW(pat, ary, test); + rb_block_call_func_t fn; + if (rb_block_given_p()) { + fn = grep_iter_i; + } + else if (RB_TYPE_P(pat, T_REGEXP) && + LIKELY(rb_method_basic_definition_p(CLASS_OF(pat), idEqq))) { + fn = grep_regexp_i; + } + else { + fn = grep_i; + } + rb_block_call(obj, id_each, 0, 0, fn, (VALUE)memo); + + return ary; +} + /* - * call-seq: - * enum.grep(pattern) -> array - * enum.grep(pattern) { |obj| block } -> array + * call-seq: + * grep(pattern) -> array + * grep(pattern) {|element| ... } -> array + * + * Returns an array of objects based elements of +self+ that match the given pattern. + * + * With no block given, returns an array containing each element + * for which pattern === element is +true+: * - * Returns an array of every element in enum for which - * Pattern === element. If the optional block is - * supplied, each matching element is passed to it, and the block's - * result is stored in the output array. + * a = ['foo', 'bar', 'car', 'moo'] + * a.grep(/ar/) # => ["bar", "car"] + * (1..10).grep(3..8) # => [3, 4, 5, 6, 7, 8] + * ['a', 'b', 0, 1].grep(Integer) # => [0, 1] * - * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44] - * c = IO.constants - * c.grep(/SEEK/) #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END] - * res = c.grep(/SEEK/) { |v| IO.const_get(v) } - * res #=> [0, 1, 2] + * With a block given, + * calls the block with each matching element and returns an array containing each + * object returned by the block: * + * a = ['foo', 'bar', 'car', 'moo'] + * a.grep(/ar/) {|element| element.upcase } # => ["BAR", "CAR"] + * + * Related: #grep_v. */ static VALUE enum_grep(VALUE obj, VALUE pat) { - VALUE ary = rb_ary_new(); - struct MEMO *memo = MEMO_NEW(pat, ary, Qtrue); - - rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo); - - return ary; + return enum_grep0(obj, pat, Qtrue); } /* - * call-seq: - * enum.grep_v(pattern) -> array - * enum.grep_v(pattern) { |obj| block } -> array + * call-seq: + * grep_v(pattern) -> array + * grep_v(pattern) {|element| ... } -> array + * + * Returns an array of objects based on elements of +self+ + * that don't match the given pattern. + * + * With no block given, returns an array containing each element + * for which pattern === element is +false+: * - * Inverted version of Enumerable#grep. - * Returns an array of every element in enum for which - * not Pattern === element. + * a = ['foo', 'bar', 'car', 'moo'] + * a.grep_v(/ar/) # => ["foo", "moo"] + * (1..10).grep_v(3..8) # => [1, 2, 9, 10] + * ['a', 'b', 0, 1].grep_v(Integer) # => ["a", "b"] * - * (1..10).grep_v 2..5 #=> [1, 6, 7, 8, 9, 10] - * res =(1..10).grep_v(2..5) { |v| v * 2 } - * res #=> [2, 12, 14, 16, 18, 20] + * With a block given, + * calls the block with each non-matching element and returns an array containing each + * object returned by the block: * + * a = ['foo', 'bar', 'car', 'moo'] + * a.grep_v(/ar/) {|element| element.upcase } # => ["FOO", "MOO"] + * + * Related: #grep. */ static VALUE enum_grep_v(VALUE obj, VALUE pat) { - VALUE ary = rb_ary_new(); - struct MEMO *memo = MEMO_NEW(pat, ary, Qfalse); - - rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo); - - return ary; + return enum_grep0(obj, pat, Qfalse); } #define COUNT_BIGNUM IMEMO_FL_USER0 @@ -204,20 +269,28 @@ count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) } /* - * call-seq: - * enum.count -> int - * enum.count(item) -> int - * enum.count { |obj| block } -> int + * call-seq: + * count -> integer + * count(object) -> integer + * count {|element| ... } -> integer + * + * Returns the count of elements, based on an argument or block criterion, if given. + * + * With no argument and no block given, returns the number of elements: + * + * [0, 1, 2].count # => 3 + * {foo: 0, bar: 1, baz: 2}.count # => 3 + * + * With argument +object+ given, + * returns the number of elements that are == to +object+: + * + * [0, 1, 2, 1].count(1) # => 2 * - * Returns the number of items in +enum+ through enumeration. - * If an argument is given, the number of items in +enum+ that - * are equal to +item+ are counted. If a block is given, it - * counts the number of elements yielding a true value. + * With a block given, calls the block with each element + * and returns the number of elements for which the block returns a truthy value: * - * ary = [1, 2, 4, 2] - * ary.count #=> 4 - * ary.count(2) #=> 2 - * ary.count{ |x| x%2==0 } #=> 3 + * [0, 1, 2, 3].count {|element| element < 2} # => 2 + * {foo: 0, bar: 1, baz: 2}.count {|key, value| value < 2} # => 2 * */ @@ -264,31 +337,26 @@ find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) } /* - * call-seq: - * enum.detect(ifnone = nil) { |obj| block } -> obj or nil - * enum.find(ifnone = nil) { |obj| block } -> obj or nil - * enum.detect(ifnone = nil) -> an_enumerator - * enum.find(ifnone = nil) -> an_enumerator + * call-seq: + * find(if_none_proc = nil) {|element| ... } -> object or nil + * find(if_none_proc = nil) -> enumerator + * + * Returns the first element for which the block returns a truthy value. + * + * With a block given, calls the block with successive elements of the collection; + * returns the first element for which the block returns a truthy value: * - * Passes each entry in enum to block. Returns the - * first for which block is not false. If no - * object matches, calls ifnone and returns its result when it - * is specified, or returns nil otherwise. + * (0..9).find {|element| element > 2} # => 3 * - * If no block is given, an enumerator is returned instead. + * If no such element is found, calls +if_none_proc+ and returns its return value. * - * (1..100).detect #=> # - * (1..100).find #=> # + * (0..9).find(proc {false}) {|element| element > 12} # => false + * {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') } # => [:bar, 1] + * {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => [] * - * (1..10).detect { |i| i % 5 == 0 && i % 7 == 0 } #=> nil - * (1..10).find { |i| i % 5 == 0 && i % 7 == 0 } #=> nil - * (1..10).detect(-> {0}) { |i| i % 5 == 0 && i % 7 == 0 } #=> 0 - * (1..10).find(-> {0}) { |i| i % 5 == 0 && i % 7 == 0 } #=> 0 - * (1..100).detect { |i| i % 5 == 0 && i % 7 == 0 } #=> 35 - * (1..100).find { |i| i % 5 == 0 && i % 7 == 0 } #=> 35 + * With no block given, returns an \Enumerator. * */ - static VALUE enum_find(int argc, VALUE *argv, VALUE obj) { @@ -337,21 +405,26 @@ find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) } /* - * call-seq: - * enum.find_index(value) -> int or nil - * enum.find_index { |obj| block } -> int or nil - * enum.find_index -> an_enumerator + * call-seq: + * find_index(object) -> integer or nil + * find_index {|element| ... } -> integer or nil + * find_index -> enumerator * - * Compares each entry in enum with value or passes - * to block. Returns the index for the first for which the - * evaluated value is non-false. If no object matches, returns - * nil + * Returns the index of the first element that meets a specified criterion, + * or +nil+ if no such element is found. * - * If neither block nor argument is given, an enumerator is returned instead. + * With argument +object+ given, + * returns the index of the first element that is == +object+: * - * (1..10).find_index { |i| i % 5 == 0 && i % 7 == 0 } #=> nil - * (1..100).find_index { |i| i % 5 == 0 && i % 7 == 0 } #=> 34 - * (1..100).find_index(50) #=> 49 + * ['a', 'b', 'c', 'b'].find_index('b') # => 1 + * + * With a block given, calls the block with successive elements; + * returns the first element for which the block returns a truthy value: + * + * ['a', 'b', 'c', 'b'].find_index {|element| element.start_with?('b') } # => 1 + * {foo: 0, bar: 1, baz: 2}.find_index {|key, value| value > 1 } # => 2 + * + * With no argument and no block given, returns an \Enumerator. * */ @@ -415,32 +488,23 @@ enum_size_over_p(VALUE obj, long n) } /* - * call-seq: - * enum.find_all { |obj| block } -> array - * enum.select { |obj| block } -> array - * enum.filter { |obj| block } -> array - * enum.find_all -> an_enumerator - * enum.select -> an_enumerator - * enum.filter -> an_enumerator - * - * Returns an array containing all elements of +enum+ - * for which the given +block+ returns a true value. - * - * The find_all and select methods are aliases. - * There is no performance benefit to either. - * - * If no block is given, an Enumerator is returned instead. + * call-seq: + * select {|element| ... } -> array + * select -> enumerator * + * Returns an array containing elements selected by the block. * - * (1..10).find_all { |i| i % 3 == 0 } #=> [3, 6, 9] + * With a block given, calls the block with successive elements; + * returns an array of those elements for which the block returns a truthy value: * - * [1,2,3,4,5].select { |num| num.even? } #=> [2, 4] + * (0..9).select {|element| element % 3 == 0 } # => [0, 3, 6, 9] + * a = {foo: 0, bar: 1, baz: 2}.select {|key, value| key.start_with?('b') } + * a # => {:bar=>1, :baz=>2} * - * [:foo, :bar].filter { |x| x == :foo } #=> [:foo] + * With no block given, returns an \Enumerator. * - * See also Enumerable#reject, Enumerable#grep. + * Related: #reject. */ - static VALUE enum_find_all(VALUE obj) { @@ -467,17 +531,19 @@ filter_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) } /* - * call-seq: - * enum.filter_map { |obj| block } -> array - * enum.filter_map -> an_enumerator + * call-seq: + * filter_map {|element| ... } -> array + * filter_map -> enumerator * - * Returns a new array containing the truthy results (everything except - * +false+ or +nil+) of running the +block+ for every element in +enum+. + * Returns an array containing truthy elements returned by the block. * - * If no block is given, an Enumerator is returned instead. + * With a block given, calls the block with successive elements; + * returns an array containing each truthy value returned by the block: * + * (0..9).filter_map {|i| i * 2 if i.even? } # => [0, 4, 8, 12, 16] + * {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz] * - * (1..10).filter_map { |i| i * 2 if i.even? } #=> [4, 8, 12, 16, 20] + * When no block given, returns an \Enumerator. * */ static VALUE @@ -506,20 +572,21 @@ reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) } /* - * call-seq: - * enum.reject { |obj| block } -> array - * enum.reject -> an_enumerator + * call-seq: + * reject {|element| ... } -> array + * reject -> enumerator * - * Returns an array for all elements of +enum+ for which the given - * +block+ returns false. + * Returns an array of objects rejected by the block. * - * If no block is given, an Enumerator is returned instead. + * With a block given, calls the block with successive elements; + * returns an array of those elements for which the block returns +nil+ or +false+: * - * (1..10).reject { |i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10] + * (0..9).reject {|i| i * 2 if i.even? } # => [1, 3, 5, 7, 9] + * {foo: 0, bar: 1, baz: 2}.reject {|key, value| key if value.odd? } # => {:foo=>0, :baz=>2} * - * [1, 2, 3, 4, 5].reject { |num| num.even? } #=> [1, 3, 5] + * When no block given, returns an \Enumerator. * - * See also Enumerable#find_all. + * Related: #select. */ static VALUE @@ -552,22 +619,21 @@ collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) } /* - * call-seq: - * enum.collect { |obj| block } -> array - * enum.map { |obj| block } -> array - * enum.collect -> an_enumerator - * enum.map -> an_enumerator + * call-seq: + * map {|element| ... } -> array + * map -> enumerator * - * Returns a new array with the results of running block once - * for every element in enum. + * Returns an array of objects returned by the block. * - * If no block is given, an enumerator is returned instead. + * With a block given, calls the block with successive elements; + * returns an array of the objects returned by the block: * - * (1..4).map { |i| i*i } #=> [1, 4, 9, 16] - * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"] + * (0..4).map {|i| i*i } # => [0, 1, 4, 9, 16] + * {foo: 0, bar: 1, baz: 2}.map {|key, value| value*2} # => [0, 2, 4] + * + * With no block given, returns an \Enumerator. * */ - static VALUE enum_collect(VALUE obj) { @@ -601,22 +667,24 @@ flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) } /* - * call-seq: - * enum.flat_map { |obj| block } -> array - * enum.collect_concat { |obj| block } -> array - * enum.flat_map -> an_enumerator - * enum.collect_concat -> an_enumerator + * call-seq: + * flat_map {|element| ... } -> array + * flat_map -> enumerator + * + * Returns an array of flattened objects returned by the block. * - * Returns a new array with the concatenated results of running - * block once for every element in enum. + * With a block given, calls the block with successive elements; + * returns a flattened array of objects returned by the block: * - * If no block is given, an enumerator is returned instead. + * [0, 1, 2, 3].flat_map {|element| -element } # => [0, -1, -2, -3] + * [0, 1, 2, 3].flat_map {|element| [element, -element] } # => [0, 0, 1, -1, 2, -2, 3, -3] + * [[0, 1], [2, 3]].flat_map {|e| e + [100] } # => [0, 1, 100, 2, 3, 100] + * {foo: 0, bar: 1, baz: 2}.flat_map {|key, value| [key, value] } # => [:foo, 0, :bar, 1, :baz, 2] * - * [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4] - * [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100] + * With no block given, returns an \Enumerator. * + * Alias: #collect_concat. */ - static VALUE enum_flat_map(VALUE obj) { @@ -632,35 +700,37 @@ enum_flat_map(VALUE obj) /* * call-seq: - * enum.to_a(*args) -> array - * enum.entries(*args) -> array + * to_a -> array * - * Returns an array containing the items in enum. + * Returns an array containing the items in +self+: * - * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7] - * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]] + * (0..4).to_a # => [0, 1, 2, 3, 4] * - * require 'prime' - * Prime.entries 10 #=> [2, 3, 5, 7] + * Enumerable#entries is an alias for Enumerable#to_a. */ static VALUE enum_to_a(int argc, VALUE *argv, VALUE obj) { VALUE ary = rb_ary_new(); - rb_block_call(obj, id_each, argc, argv, collect_all, ary); + rb_block_call_kw(obj, id_each, argc, argv, collect_all, ary, RB_PASS_CALLED_KEYWORDS); return ary; } static VALUE -enum_hashify(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter) +enum_hashify_into(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter, VALUE hash) { - VALUE hash = rb_hash_new(); rb_block_call(obj, id_each, argc, argv, iter, hash); return hash; } +static VALUE +enum_hashify(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter) +{ + return enum_hashify_into(obj, argc, argv, iter, rb_hash_new()); +} + static VALUE enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) { @@ -676,20 +746,23 @@ enum_to_h_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) /* * call-seq: - * enum.to_h(*args) -> hash - * enum.to_h(*args) {...} -> hash + * to_h -> hash + * to_h {|element| ... } -> hash * - * Returns the result of interpreting enum as a list of - * [key, value] pairs. + * When +self+ consists of 2-element arrays, + * returns a hash each of whose entries is the key-value pair + * formed from one of those arrays: * - * %i[hello world].each_with_index.to_h - * # => {:hello => 0, :world => 1} + * [[:foo, 0], [:bar, 1], [:baz, 2]].to_h # => {:foo=>0, :bar=>1, :baz=>2} * - * If a block is given, the results of the block on each element of - * the enum will be used as pairs. + * When a block is given, the block is called with each element of +self+; + * the block should return a 2-element array which becomes a key-value pair + * in the returned hash: * - * (1..5).to_h {|x| [x, x ** 2]} - * #=> {1=>1, 2=>4, 3=>9, 4=>16, 5=>25} + * (0..3).to_h {|i| [i, i ** 2]} # => {0=>0, 1=>1, 2=>4, 3=>9} + * + * Raises an exception if an element of +self+ is not a 2-element array, + * and a block is not passed. */ static VALUE @@ -728,7 +801,7 @@ inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p)) } else if (SYMBOL_P(name = memo->u3.value)) { const ID mid = SYM2ID(name); - MEMO_V1_SET(memo, rb_funcallv(memo->v1, mid, 1, &i)); + MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i)); } else { VALUE args[2]; @@ -771,11 +844,11 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op) if (FIXNUM_P(e)) { n += FIX2LONG(e); /* should not overflow long type */ if (!FIXABLE(n)) { - v = rb_big_plus(ULONG2NUM(n), v); + v = rb_big_plus(LONG2NUM(n), v); n = 0; } } - else if (RB_TYPE_P(e, T_BIGNUM)) + else if (RB_BIGNUM_TYPE_P(e)) v = rb_big_plus(e, v); else goto not_integer; @@ -798,48 +871,136 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op) /* * call-seq: - * enum.inject(initial, sym) -> obj - * enum.inject(sym) -> obj - * enum.inject(initial) { |memo, obj| block } -> obj - * enum.inject { |memo, obj| block } -> obj - * enum.reduce(initial, sym) -> obj - * enum.reduce(sym) -> obj - * enum.reduce(initial) { |memo, obj| block } -> obj - * enum.reduce { |memo, obj| block } -> obj - * - * Combines all elements of enum by applying a binary - * operation, specified by a block or a symbol that names a - * method or operator. - * - * The inject and reduce methods are aliases. There - * is no performance benefit to either. - * - * If you specify a block, then for each element in enum - * the block is passed an accumulator value (memo) and the element. - * If you specify a symbol instead, then each element in the collection - * will be passed to the named method of memo. - * In either case, the result becomes the new value for memo. - * At the end of the iteration, the final value of memo is the - * return value for the method. - * - * If you do not explicitly specify an initial value for memo, - * then the first element of collection is used as the initial value - * of memo. - * - * - * # Sum some numbers - * (5..10).reduce(:+) #=> 45 - * # Same using a block and inject - * (5..10).inject { |sum, n| sum + n } #=> 45 - * # Multiply some numbers - * (5..10).reduce(1, :*) #=> 151200 - * # Same using a block - * (5..10).inject(1) { |product, n| product * n } #=> 151200 - * # find the longest word - * longest = %w{ cat sheep bear }.inject do |memo, word| - * memo.length > word.length ? memo : word - * end - * longest #=> "sheep" + * 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: + * + * - 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 + * + * 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 + * + * Operands + * + * If argument +initial_operand+ is not given, + * the operands for +inject+ are simply the elements of +self+. + * Example calls and their operands: + * + * - (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']. + * + * Examples with first operand (which is self.first) of various types: + * + * # 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) + * + * If argument +initial_operand+ is given, + * the operands for +inject+ are that value plus the elements of +self+. + * Example calls their operands: + * + * - (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']. + * + * Examples with +initial_operand+ of various types: + * + * # 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) + * + * Combination by Given \Method + * + * If the method-name argument +symbol+ is given, + * the operands are combined by that method: + * + * - 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. + * + * The return value from +inject+ is the result of the last combination. + * + * This call to +inject+ computes the sum of the operands: + * + * (1..4).inject(:+) # => 10 + * + * Examples with various methods: + * + * # 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]] + * + * Combination by Given Block + * + * If a block is given, the operands are passed to the block: + * + * - 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. + * + * 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..4).inject do |memo, element| + * p "Memo: #{memo}; element: #{element}" + * memo + element + * end # => 10 + * + * Output: + * + * "Memo: 1; element: 2" + * "Memo: 3; element: 3" + * "Memo: 6; element: 4" + * + * Enumerable#reduce is an alias for Enumerable#inject. * */ static VALUE @@ -905,16 +1066,29 @@ partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys)) /* * call-seq: - * enum.partition { |obj| block } -> [ true_array, false_array ] - * enum.partition -> an_enumerator + * partition {|element| ... } -> [true_array, false_array] + * partition -> enumerator + * + * With a block given, returns an array of two arrays: * - * Returns two arrays, the first containing the elements of - * enum for which the block evaluates to true, the second - * containing the rest. + * - The first having those elements for which the block returns a truthy value. + * - The other having all other elements. * - * If no block is given, an enumerator is returned instead. + * Examples: * - * (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]] + * p = (1..4).partition {|i| i.even? } + * p # => [[2, 4], [1, 3]] + * p = ('a'..'d').partition {|c| c < 'c' } + * p # => [["a", "b"], ["c", "d"]] + * h = {foo: 0, bar: 1, baz: 2, bat: 3} + * p = h.partition {|key, value| key.start_with?('b') } + * p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]] + * p = h.partition {|key, value| value < 2 } + * p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]] + * + * With no block given, returns an Enumerator. + * + * Related: Enumerable#group_by. * */ @@ -953,16 +1127,23 @@ group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) /* * call-seq: - * enum.group_by { |obj| block } -> a_hash - * enum.group_by -> an_enumerator + * group_by {|element| ... } -> hash + * group_by -> enumerator + * + * With a block given returns a hash: * - * Groups the collection by result of the block. Returns a hash where the - * keys are the evaluated result from the block and the values are - * arrays of elements in the collection that correspond to the key. + * - Each key is a return value from the block. + * - Each value is an array of those elements for which the block returned that key. * - * If no block is given an enumerator is returned. + * Examples: * - * (1..6).group_by { |i| i%3 } #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} + * g = (1..6).group_by {|i| i%3 } + * g # => {1=>[1, 4], 2=>[2, 5], 0=>[3, 6]} + * h = {foo: 0, bar: 1, baz: 0, bat: 1} + * g = h.group_by {|key, value| value } + * g # => {0=>[[:foo, 0], [:baz, 0]], 1=>[[:bar, 1], [:bat, 1]]} + * + * With no block given, returns an Enumerator. * */ @@ -974,47 +1155,86 @@ enum_group_by(VALUE obj) return enum_hashify(obj, 0, 0, group_by_i); } -static void -tally_up(VALUE hash, VALUE group) +static int +tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing) { - VALUE tally = rb_hash_aref(hash, group); - if (NIL_P(tally)) { + VALUE tally = (VALUE)*value; + VALUE hash = (VALUE)arg; + if (!existing) { tally = INT2FIX(1); } else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) { tally += INT2FIX(1) & ~FIXNUM_FLAG; } else { + Check_Type(tally, T_BIGNUM); tally = rb_big_plus(tally, INT2FIX(1)); + RB_OBJ_WRITTEN(hash, Qundef, tally); } - rb_hash_aset(hash, group, 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); + return hash; } static VALUE tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) { ENUM_WANT_SVALUE(); - tally_up(hash, i); + rb_enum_tally_up(hash, i); return Qnil; } /* * call-seq: - * enum.tally -> a_hash + * tally -> new_hash + * tally(hash) -> hash + * + * Returns a hash containing the counts of equal elements: + * + * - Each key is an element of +self+. + * - Each value is the number elements equal to that key. + * + * With no argument: * - * Tallies the collection, i.e., counts the occurrences of each element. - * Returns a hash with the elements of the collection as keys and the - * corresponding counts as values. + * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3} + * + * 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: + * + * 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} * - * ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1} */ static VALUE -enum_tally(VALUE obj) +enum_tally(int argc, VALUE *argv, VALUE obj) { - return enum_hashify(obj, 0, 0, tally_i); + VALUE hash; + if (rb_check_arity(argc, 0, 1)) { + hash = rb_convert_type(argv[0], T_HASH, "Hash", "to_hash"); + rb_check_frozen(hash); + } + else { + hash = rb_hash_new(); + } + + return enum_hashify_into(obj, 0, 0, tally_i, hash); } +NORETURN(static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))); static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params)) { @@ -1031,18 +1251,26 @@ static VALUE enum_take(VALUE obj, VALUE n); /* * call-seq: - * enum.first -> obj or nil - * enum.first(n) -> an_array + * first -> element or nil + * first(n) -> array * - * Returns the first element, or the first +n+ elements, of the enumerable. - * If the enumerable is empty, the first form returns nil, and the - * second form returns an empty array. + * Returns the first element or elements. * - * %w[foo bar baz].first #=> "foo" - * %w[foo bar baz].first(2) #=> ["foo", "bar"] - * %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"] - * [].first #=> nil - * [].first(10) #=> [] + * With no argument, returns the first element, or +nil+ if there is none: + * + * (1..4).first # => 1 + * %w[a b c].first # => "a" + * {foo: 1, bar: 1, baz: 2}.first # => [:foo, 1] + * [].first # => nil + * + * With integer argument +n+, returns an array + * containing the first +n+ elements that exist: + * + * (1..4).first(2) # => [1, 2] + * %w[a b c d].first(3) # => ["a", "b", "c"] + * %w[a b c d].first(50) # => ["a", "b", "c", "d"] + * {foo: 1, bar: 1, baz: 2}.first(2) # => [[:foo, 1], [:bar, 1]] + * [].first(2) # => [] * */ @@ -1061,28 +1289,35 @@ enum_first(int argc, VALUE *argv, VALUE obj) } } - /* * call-seq: - * enum.sort -> array - * enum.sort { |a, b| block } -> array + * sort -> array + * sort {|a, b| ... } -> array + * + * Returns an array containing the sorted elements of +self+. + * The ordering of equal elements is indeterminate and may be unstable. + * + * With no block given, the sort compares + * using the elements' own method <=>: * - * Returns an array containing the items in enum sorted. + * %w[b c a d].sort # => ["a", "b", "c", "d"] + * {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]] * - * Comparisons for the sort will be done using the items' own - * <=> operator or using an optional code block. + * With a block given, comparisons in the block determine the ordering. + * The block is called with two elements +a+ and +b+, and must return: * - * The block must implement a comparison between +a+ and +b+ and return - * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+ - * are equivalent, or an integer greater than 0 when +a+ follows +b+. + * - A negative integer if a < b. + * - Zero if a == b. + * - A positive integer if a > b. * - * The result is not guaranteed to be stable. When the comparison of two - * elements returns +0+, the order of the elements is unpredictable. + * Examples: * - * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"] - * (1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] + * a = %w[b c a d] + * a.sort {|a, b| b <=> a } # => ["d", "c", "b", "a"] + * h = {foo: 0, bar: 1, baz: 2} + * h.sort {|a, b| b <=> a } # => [[:foo, 0], [:baz, 2], [:bar, 1]] * - * See also Enumerable#sort_by. It implements a Schwartzian transform + * See also #sort_by. It implements a Schwartzian transform * which is useful when key computation or comparison is expensive. */ @@ -1147,19 +1382,23 @@ sort_by_cmp(const void *ap, const void *bp, void *data) /* * call-seq: - * enum.sort_by { |obj| block } -> array - * enum.sort_by -> an_enumerator + * sort_by {|element| ... } -> array + * sort_by -> enumerator * - * Sorts enum using a set of keys generated by mapping the - * values in enum through the given block. + * With a block given, returns an array of elements of +self+, + * sorted according to the value returned by the block for each element. + * The ordering of equal elements is indeterminate and may be unstable. * - * The result is not guaranteed to be stable. When two keys are equal, - * the order of the corresponding elements is unpredictable. + * Examples: * - * If no block is given, an enumerator is returned instead. + * a = %w[xx xxx x xxxx] + * a.sort_by {|s| s.size } # => ["x", "xx", "xxx", "xxxx"] + * a.sort_by {|s| -s.size } # => ["xxxx", "xxx", "xx", "x"] + * h = {foo: 2, bar: 1, baz: 0} + * h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]] + * h.sort_by{|key, value| key } # => [[:bar, 1], [:baz, 0], [:foo, 2]] * - * %w{apple pear fig}.sort_by { |word| word.length } - * #=> ["fig", "pear", "apple"] + * With no block given, returns an Enumerator. * * The current implementation of #sort_by generates an array of * tuples containing the original collection element and the mapped @@ -1317,25 +1556,44 @@ DEFINE_ENUMFUNCS(all) /* * call-seq: - * enum.all? [{ |obj| block } ] -> true or false - * enum.all?(pattern) -> true or false - * - * Passes each element of the collection to the given block. The method - * returns true if the block never returns - * false or nil. If the block is not given, - * Ruby adds an implicit block of { |obj| obj } which will - * cause #all? to return +true+ when none of the collection members are - * +false+ or +nil+. - * - * If instead a pattern is supplied, the method returns whether - * pattern === element for every collection member. - * - * %w[ant bear cat].all? { |word| word.length >= 3 } #=> true - * %w[ant bear cat].all? { |word| word.length >= 4 } #=> false - * %w[ant bear cat].all?(/t/) #=> false - * [1, 2i, 3.14].all?(Numeric) #=> true - * [nil, true, 99].all? #=> false - * [].all? #=> true + * all? -> true or false + * all?(pattern) -> true or false + * all? {|element| ... } -> true or false + * + * Returns whether every element meets a given criterion. + * + * With no argument and no block, + * returns whether every element is truthy: + * + * (1..4).all? # => true + * %w[a b c d].all? # => true + * [1, 2, nil].all? # => false + * ['a','b', false].all? # => false + * [].all? # => true + * + * With argument +pattern+ and no block, + * returns whether for each element +element+, + * pattern === element: + * + * (1..4).all?(Integer) # => true + * (1..4).all?(Numeric) # => true + * (1..4).all?(Float) # => false + * %w[bar baz bat bam].all?(/ba/) # => true + * %w[bar baz bat bam].all?(/bar/) # => false + * %w[bar baz bat bam].all?('ba') # => false + * {foo: 0, bar: 1, baz: 2}.all?(Array) # => true + * {foo: 0, bar: 1, baz: 2}.all?(Hash) # => false + * [].all?(Integer) # => true + * + * With a block given, returns whether the block returns a truthy value + * for every element: + * + * (1..4).all? {|element| element < 5 } # => true + * (1..4).all? {|element| element < 4 } # => false + * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 3 } # => true + * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 2 } # => false + * + * Related: #any?, #none? #one?. * */ @@ -1359,26 +1617,44 @@ DEFINE_ENUMFUNCS(any) /* * call-seq: - * enum.any? [{ |obj| block }] -> true or false - * enum.any?(pattern) -> true or false - * - * Passes each element of the collection to the given block. The method - * returns true if the block ever returns a value other - * than false or nil. If the block is not - * given, Ruby adds an implicit block of { |obj| obj } that - * will cause #any? to return +true+ if at least one of the collection - * members is not +false+ or +nil+. - * - * If instead a pattern is supplied, the method returns whether - * pattern === element for any collection member. - * - * %w[ant bear cat].any? { |word| word.length >= 3 } #=> true - * %w[ant bear cat].any? { |word| word.length >= 4 } #=> true - * %w[ant bear cat].any?(/d/) #=> false - * [nil, true, 99].any?(Integer) #=> true - * [nil, true, 99].any? #=> true - * [].any? #=> false + * any? -> true or false + * any?(pattern) -> true or false + * any? {|element| ... } -> true or false + * + * Returns whether any element meets a given criterion. + * + * With no argument and no block, + * returns whether any element is truthy: + * + * (1..4).any? # => true + * %w[a b c d].any? # => true + * [1, false, nil].any? # => true + * [].any? # => false + * + * With argument +pattern+ and no block, + * returns whether for any element +element+, + * pattern === element: + * + * [nil, false, 0].any?(Integer) # => true + * [nil, false, 0].any?(Numeric) # => true + * [nil, false, 0].any?(Float) # => false + * %w[bar baz bat bam].any?(/m/) # => true + * %w[bar baz bat bam].any?(/foo/) # => false + * %w[bar baz bat bam].any?('ba') # => false + * {foo: 0, bar: 1, baz: 2}.any?(Array) # => true + * {foo: 0, bar: 1, baz: 2}.any?(Hash) # => false + * [].any?(Integer) # => false * + * With a block given, returns whether the block returns a truthy value + * for any element: + * + * (1..4).any? {|element| element < 2 } # => true + * (1..4).any? {|element| element < 1 } # => false + * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 1 } # => true + * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 0 } # => false + * + * + * Related: #all?, #none?, #one?. */ static VALUE @@ -1628,26 +1904,45 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary) /* * call-seq: - * enum.one? [{ |obj| block }] -> true or false - * enum.one?(pattern) -> true or false - * - * Passes each element of the collection to the given block. The method - * returns true if the block returns true - * exactly once. If the block is not given, one? will return - * true only if exactly one of the collection members is - * true. - * - * If instead a pattern is supplied, the method returns whether - * pattern === element for exactly one collection member. - * - * %w{ant bear cat}.one? { |word| word.length == 4 } #=> true - * %w{ant bear cat}.one? { |word| word.length > 4 } #=> false - * %w{ant bear cat}.one? { |word| word.length < 4 } #=> false - * %w{ant bear cat}.one?(/t/) #=> false - * [ nil, true, 99 ].one? #=> false - * [ nil, true, false ].one? #=> true - * [ nil, true, 99 ].one?(Integer) #=> true - * [].one? #=> false + * one? -> true or false + * one?(pattern) -> true or false + * one? {|element| ... } -> true or false + * + * Returns whether exactly one element meets a given criterion. + * + * With no argument and no block, + * returns whether exactly one element is truthy: + * + * (1..1).one? # => true + * [1, nil, false].one? # => true + * (1..4).one? # => false + * {foo: 0}.one? # => true + * {foo: 0, bar: 1}.one? # => false + * [].one? # => false + * + * With argument +pattern+ and no block, + * returns whether for exactly one element +element+, + * pattern === element: + * + * [nil, false, 0].one?(Integer) # => true + * [nil, false, 0].one?(Numeric) # => true + * [nil, false, 0].one?(Float) # => false + * %w[bar baz bat bam].one?(/m/) # => true + * %w[bar baz bat bam].one?(/foo/) # => false + * %w[bar baz bat bam].one?('ba') # => false + * {foo: 0, bar: 1, baz: 2}.one?(Array) # => false + * {foo: 0}.one?(Array) # => true + * [].one?(Integer) # => false + * + * With a block given, returns whether the block returns a truthy value + * for exactly one element: + * + * (1..4).one? {|element| element < 2 } # => true + * (1..4).one? {|element| element < 1 } # => false + * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 1 } # => true + * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 2 } # => false + * + * Related: #none?, #all?, #any?. * */ static VALUE @@ -1674,25 +1969,43 @@ DEFINE_ENUMFUNCS(none) /* * call-seq: - * enum.none? [{ |obj| block }] -> true or false - * enum.none?(pattern) -> true or false - * - * Passes each element of the collection to the given block. The method - * returns true if the block never returns true - * for all elements. If the block is not given, none? will return - * true only if none of the collection members is true. - * - * If instead a pattern is supplied, the method returns whether - * pattern === element for none of the collection members. - * - * %w{ant bear cat}.none? { |word| word.length == 5 } #=> true - * %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false - * %w{ant bear cat}.none?(/d/) #=> true - * [1, 3.14, 42].none?(Float) #=> false - * [].none? #=> true - * [nil].none? #=> true - * [nil, false].none? #=> true - * [nil, false, true].none? #=> false + * none? -> true or false + * none?(pattern) -> true or false + * none? {|element| ... } -> true or false + * + * Returns whether no element meets a given criterion. + * + * With no argument and no block, + * returns whether no element is truthy: + * + * (1..4).none? # => false + * [nil, false].none? # => true + * {foo: 0}.none? # => false + * {foo: 0, bar: 1}.none? # => false + * [].none? # => true + * + * With argument +pattern+ and no block, + * returns whether for no element +element+, + * pattern === element: + * + * [nil, false, 1.1].none?(Integer) # => true + * %w[bar baz bat bam].none?(/m/) # => false + * %w[bar baz bat bam].none?(/foo/) # => true + * %w[bar baz bat bam].none?('ba') # => true + * {foo: 0, bar: 1, baz: 2}.none?(Hash) # => true + * {foo: 0}.none?(Array) # => false + * [].none?(Integer) # => true + * + * With a block given, returns whether the block returns a truthy value + * for no element: + * + * (1..4).none? {|element| element < 1 } # => true + * (1..4).none? {|element| element < 2 } # => false + * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 0 } # => true + * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 1 } # => false + * + * Related: #one?, #all?, #any?. + * */ static VALUE enum_none(int argc, VALUE *argv, VALUE obj) @@ -1750,26 +2063,59 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.min -> obj - * enum.min { |a, b| block } -> obj - * enum.min(n) -> array - * enum.min(n) { |a, b| block } -> array - * - * Returns the object in _enum_ with the minimum value. The - * first form assumes all objects implement Comparable; - * the second uses the block to return a <=> b. - * - * a = %w(albatross dog horse) - * a.min #=> "albatross" - * a.min { |a, b| a.length <=> b.length } #=> "dog" - * - * If the +n+ argument is given, minimum +n+ elements are returned - * as a sorted array. - * - * a = %w[albatross dog horse] - * a.min(2) #=> ["albatross", "dog"] - * a.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"] - * [5, 1, 3, 4, 2].min(3) #=> [1, 2, 3] + * min -> element + * min(n) -> array + * min {|a, b| ... } -> element + * min(n) {|a, b| ... } -> array + * + * Returns the element with the minimum element according to a given criterion. + * 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: + * + * (1..4).min # => 1 + * (-4..-1).min # => -4 + * %w[d c b a].min # => "a" + * {foo: 0, bar: 1, baz: 2}.min # => [:bar, 1] + * [].min # => nil + * + * With positive integer argument +n+ given, and no block, + * returns an array containing the first +n+ minimum elements that exist: + * + * (1..4).min(2) # => [1, 2] + * (-4..-1).min(2) # => [-4, -3] + * %w[d c b a].min(2) # => ["a", "b"] + * {foo: 0, bar: 1, baz: 2}.min(2) # => [[:bar, 1], [:baz, 2]] + * [].min(2) # => [] + * + * With a block given, the block determines the minimum elements. + * The block is called with two elements +a+ and +b+, and must return: + * + * - A negative integer if a < b. + * - Zero if a == b. + * - A positive integer if a > b. + * + * With a block given and no argument, + * returns the minimum element as determined by the block: + * + * %w[xxx x xxxx xx].min {|a, b| a.size <=> b.size } # => "x" + * h = {foo: 0, bar: 1, baz: 2} + * h.min {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:foo, 0] + * [].min {|a, b| a <=> b } # => nil + * + * With a block given and positive integer argument +n+ given, + * returns an array containing the first +n+ minimum elements that exist, + * as determined by the block. + * + * %w[xxx x xxxx xx].min(2) {|a, b| a.size <=> b.size } # => ["x", "xx"] + * h = {foo: 0, bar: 1, baz: 2} + * h.min(2) {|pair1, pair2| pair1[1] <=> pair2[1] } + * # => [[:foo, 0], [:bar, 1]] + * [].min(2) {|a, b| a <=> b } # => [] + * + * Related: #min_by, #minmax, #max. + * */ static VALUE @@ -1842,26 +2188,59 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.max -> obj - * enum.max { |a, b| block } -> obj - * enum.max(n) -> array - * enum.max(n) { |a, b| block } -> array - * - * Returns the object in _enum_ with the maximum value. The - * first form assumes all objects implement Comparable; - * the second uses the block to return a <=> b. - * - * a = %w(albatross dog horse) - * a.max #=> "horse" - * a.max { |a, b| a.length <=> b.length } #=> "albatross" - * - * If the +n+ argument is given, maximum +n+ elements are returned - * as an array, sorted in descending order. - * - * a = %w[albatross dog horse] - * a.max(2) #=> ["horse", "dog"] - * a.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"] - * [5, 1, 3, 4, 2].max(3) #=> [5, 4, 3] + * max -> element + * max(n) -> array + * max {|a, b| ... } -> element + * max(n) {|a, b| ... } -> array + * + * Returns the element with the maximum element according to a given criterion. + * 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: + * + * (1..4).max # => 4 + * (-4..-1).max # => -1 + * %w[d c b a].max # => "d" + * {foo: 0, bar: 1, baz: 2}.max # => [:foo, 0] + * [].max # => nil + * + * With positive integer argument +n+ given, and no block, + * returns an array containing the first +n+ maximum elements that exist: + * + * (1..4).max(2) # => [4, 3] + * (-4..-1).max(2) # => [-1, -2] + * %w[d c b a].max(2) # => ["d", "c"] + * {foo: 0, bar: 1, baz: 2}.max(2) # => [[:foo, 0], [:baz, 2]] + * [].max(2) # => [] + * + * With a block given, the block determines the maximum elements. + * The block is called with two elements +a+ and +b+, and must return: + * + * - A negative integer if a < b. + * - Zero if a == b. + * - A positive integer if a > b. + * + * With a block given and no argument, + * returns the maximum element as determined by the block: + * + * %w[xxx x xxxx xx].max {|a, b| a.size <=> b.size } # => "xxxx" + * h = {foo: 0, bar: 1, baz: 2} + * h.max {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:baz, 2] + * [].max {|a, b| a <=> b } # => nil + * + * With a block given and positive integer argument +n+ given, + * returns an array containing the first +n+ maximum elements that exist, + * as determined by the block. + * + * %w[xxx x xxxx xx].max(2) {|a, b| a.size <=> b.size } # => ["xxxx", "xxx"] + * h = {foo: 0, bar: 1, baz: 2} + * h.max(2) {|pair1, pair2| pair1[1] <=> pair2[1] } + * # => [[:baz, 2], [:bar, 1]] + * [].max(2) {|a, b| a <=> b } # => [] + * + * Related: #min, #minmax, #max_by. + * */ static VALUE @@ -2002,17 +2381,33 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo)) /* * call-seq: - * enum.minmax -> [min, max] - * enum.minmax { |a, b| block } -> [min, max] + * minmax -> [minimum, maximum] + * minmax {|a, b| ... } -> [minimum, maximum] + * + * Returns a 2-element array containing the minimum and maximum elements + * according to a given criterion. + * 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: + * + * (1..4).minmax # => [1, 4] + * (-4..-1).minmax # => [-4, -1] + * %w[d c b a].minmax # => ["a", "d"] + * {foo: 0, bar: 1, baz: 2}.minmax # => [[:bar, 1], [:foo, 0]] + * [].minmax # => [nil, nil] + * + * With a block given, returns the minimum and maximum elements + * as determined by the block: * - * Returns a two element array which contains the minimum and the - * maximum value in the enumerable. The first form assumes all - * objects implement Comparable; the second uses the - * block to return a <=> b. + * %w[xxx x xxxx xx].minmax {|a, b| a.size <=> b.size } # => ["x", "xxxx"] + * h = {foo: 0, bar: 1, baz: 2} + * h.minmax {|pair1, pair2| pair1[1] <=> pair2[1] } + * # => [[:foo, 0], [:baz, 2]] + * [].minmax {|a, b| a <=> b } # => [nil, nil] + * + * Related: #min, #max, #minmax_by. * - * a = %w(albatross dog horse) - * a.minmax #=> ["albatross", "horse"] - * a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"] */ static VALUE @@ -2064,25 +2459,38 @@ min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.min_by {|obj| block } -> obj - * enum.min_by -> an_enumerator - * enum.min_by(n) {|obj| block } -> array - * enum.min_by(n) -> an_enumerator + * min_by {|element| ... } -> element + * min_by(n) {|element| ... } -> array + * min_by -> enumerator + * min_by(n) -> enumerator + * + * Returns the elements for which the block returns the minimum values. + * + * With a block given and no argument, + * returns the element for which the block returns the minimum value: + * + * (1..4).min_by {|element| -element } # => 4 + * %w[a b c d].min_by {|element| -element.ord } # => "d" + * {foo: 0, bar: 1, baz: 2}.min_by {|key, value| -value } # => [:baz, 2] + * [].min_by {|element| -element } # => nil * - * Returns the object in enum that gives the minimum - * value from the given block. + * With a block given and positive integer argument +n+ given, + * returns an array containing the +n+ elements + * for which the block returns minimum values: * - * If no block is given, an enumerator is returned instead. + * (1..4).min_by(2) {|element| -element } + * # => [4, 3] + * %w[a b c d].min_by(2) {|element| -element.ord } + * # => ["d", "c"] + * {foo: 0, bar: 1, baz: 2}.min_by(2) {|key, value| -value } + * # => [[:baz, 2], [:bar, 1]] + * [].min_by(2) {|element| -element } + * # => [] * - * a = %w(albatross dog horse) - * a.min_by { |x| x.length } #=> "dog" + * Returns an Enumerator if no block is given. * - * If the +n+ argument is given, minimum +n+ elements are returned - * as an array. These +n+ elements are sorted by the value from the - * given block. + * Related: #min, #minmax, #max_by. * - * a = %w[albatross dog horse] - * p a.min_by(2) {|x| x.length } #=> ["dog", "horse"] */ static VALUE @@ -2126,69 +2534,37 @@ max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.max_by {|obj| block } -> obj - * enum.max_by -> an_enumerator - * enum.max_by(n) {|obj| block } -> obj - * enum.max_by(n) -> an_enumerator - * - * Returns the object in enum that gives the maximum - * value from the given block. - * - * If no block is given, an enumerator is returned instead. - * - * a = %w(albatross dog horse) - * a.max_by { |x| x.length } #=> "albatross" - * - * If the +n+ argument is given, maximum +n+ elements are returned - * as an array. These +n+ elements are sorted by the value from the - * given block, in descending order. - * - * a = %w[albatross dog horse] - * a.max_by(2) {|x| x.length } #=> ["albatross", "horse"] - * - * enum.max_by(n) can be used to implement weighted random sampling. - * Following example implements and use Enumerable#wsample. - * - * module Enumerable - * # weighted random sampling. - * # - * # Pavlos S. Efraimidis, Paul G. Spirakis - * # Weighted random sampling with a reservoir - * # Information Processing Letters - * # Volume 97, Issue 5 (16 March 2006) - * def wsample(n) - * self.max_by(n) {|v| rand ** (1.0/yield(v)) } - * end - * end - * e = (-20..20).to_a*10000 - * a = e.wsample(20000) {|x| - * Math.exp(-(x/5.0)**2) # normal distribution - * } - * # a is 20000 samples from e. - * p a.length #=> 20000 - * h = a.group_by {|x| x } - * -10.upto(10) {|x| puts "*" * (h[x].length/30.0).to_i if h[x] } - * #=> * - * # *** - * # ****** - * # *********** - * # ****************** - * # ***************************** - * # ***************************************** - * # **************************************************** - * # *************************************************************** - * # ******************************************************************** - * # *********************************************************************** - * # *********************************************************************** - * # ************************************************************** - * # **************************************************** - * # *************************************** - * # *************************** - * # ****************** - * # *********** - * # ******* - * # *** - * # * + * max_by {|element| ... } -> element + * max_by(n) {|element| ... } -> array + * max_by -> enumerator + * max_by(n) -> enumerator + * + * Returns the elements for which the block returns the maximum values. + * + * With a block given and no argument, + * returns the element for which the block returns the maximum value: + * + * (1..4).max_by {|element| -element } # => 1 + * %w[a b c d].max_by {|element| -element.ord } # => "a" + * {foo: 0, bar: 1, baz: 2}.max_by {|key, value| -value } # => [:foo, 0] + * [].max_by {|element| -element } # => nil + * + * With a block given and positive integer argument +n+ given, + * returns an array containing the +n+ elements + * for which the block returns maximum values: + * + * (1..4).max_by(2) {|element| -element } + * # => [1, 2] + * %w[a b c d].max_by(2) {|element| -element.ord } + * # => ["a", "b"] + * {foo: 0, bar: 1, baz: 2}.max_by(2) {|key, value| -value } + * # => [[:foo, 0], [:bar, 1]] + * [].max_by(2) {|element| -element } + * # => [] + * + * Returns an Enumerator if no block is given. + * + * Related: #max, #minmax, #min_by. * */ @@ -2285,17 +2661,25 @@ minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo)) /* * call-seq: - * enum.minmax_by { |obj| block } -> [min, max] - * enum.minmax_by -> an_enumerator + * minmax_by {|element| ... } -> [minimum, maximum] + * minmax_by -> enumerator * - * Returns a two element array containing the objects in - * enum that correspond to the minimum and maximum values respectively - * from the given block. + * Returns a 2-element array containing the elements + * for which the block returns minimum and maximum values: * - * If no block is given, an enumerator is returned instead. + * (1..4).minmax_by {|element| -element } + * # => [4, 1] + * %w[a b c d].minmax_by {|element| -element.ord } + * # => ["d", "a"] + * {foo: 0, bar: 1, baz: 2}.minmax_by {|key, value| -value } + * # => [[:baz, 2], [:foo, 0]] + * [].minmax_by {|element| -element } + * # => [nil, nil] + * + * Returns an Enumerator if no block is given. + * + * Related: #max_by, #minmax, #min_by. * - * a = %w(albatross dog horse) - * a.minmax_by { |x| x.length } #=> ["dog", "albatross"] */ static VALUE @@ -2333,16 +2717,20 @@ member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args)) /* * call-seq: - * enum.include?(obj) -> true or false - * enum.member?(obj) -> true or false + * include?(object) -> true or false + * + * Returns whether for any element object == element: * - * Returns true if any member of enum equals - * obj. Equality is tested using ==. + * (1..4).include?(2) # => true + * (1..4).include?(5) # => false + * (1..4).include?('2') # => false + * %w[a b c d].include?('b') # => true + * %w[a b c d].include?('2') # => false + * {foo: 0, bar: 1, baz: 2}.include?(:foo) # => true + * {foo: 0, bar: 1, baz: 2}.include?('foo') # => false + * {foo: 0, bar: 1, baz: 2}.include?(0) # => false * - * (1..10).include? 5 #=> true - * (1..10).include? 15 #=> false - * (1..10).member? 5 #=> true - * (1..10).member? 15 #=> false + * Enumerable#member? is an alias for Enumerable#include?. * */ @@ -2367,20 +2755,28 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) /* * call-seq: - * enum.each_with_index(*args) { |obj, i| block } -> enum - * enum.each_with_index(*args) -> an_enumerator + * each_with_index(*args) {|element, i| ..... } -> self + * each_with_index(*args) -> enumerator * - * Calls block with two arguments, the item and its index, - * for each item in enum. Given arguments are passed through - * to #each(). + * With a block given, calls the block with each element and its index; + * returns +self+: * - * If no block is given, an enumerator is returned instead. + * h = {} + * (1..4).each_with_index {|element, i| h[element] = i } # => 1..4 + * h # => {1=>0, 2=>1, 3=>2, 4=>3} * - * hash = Hash.new - * %w(cat dog wombat).each_with_index { |item, index| - * hash[item] = index - * } - * hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2} + * h = {} + * %w[a b c d].each_with_index {|element, i| h[element] = i } + * # => ["a", "b", "c", "d"] + * h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3} + * + * a = [] + * h = {foo: 0, bar: 1, baz: 2} + * h.each_with_index {|element, i| a.push([i, element]) } + * # => {:foo=>0, :bar=>1, :baz=>2} + * a # => [[0, [:foo, 0]], [1, [:bar, 1]], [2, [:baz, 2]]] + * + * With no block given, returns an Enumerator. * */ @@ -2399,20 +2795,28 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj) /* * call-seq: - * enum.reverse_each(*args) { |item| block } -> enum - * enum.reverse_each(*args) -> an_enumerator + * reverse_each(*args) {|element| ... } -> self + * reverse_each(*args) -> enumerator * - * Builds a temporary array and traverses that array in reverse order. + * With a block given, calls the block with each element, + * but in reverse order; returns +self+: * - * If no block is given, an enumerator is returned instead. + * a = [] + * (1..4).reverse_each {|element| a.push(-element) } # => 1..4 + * a # => [-4, -3, -2, -1] * - * (1..3).reverse_each { |v| p v } + * a = [] + * %w[a b c d].reverse_each {|element| a.push(element) } + * # => ["a", "b", "c", "d"] + * a # => ["d", "c", "b", "a"] * - * produces: + * a = [] + * h.reverse_each {|element| a.push(element) } + * # => {:foo=>0, :bar=>1, :baz=>2} + * a # => [[:baz, 2], [:bar, 1], [:foo, 0]] + * + * With no block given, returns an Enumerator. * - * 3 - * 2 - * 1 */ static VALUE @@ -2449,30 +2853,39 @@ each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p)) /* * call-seq: - * enum.each_entry { |obj| block } -> enum - * enum.each_entry -> an_enumerator - * - * Calls block once for each element in +self+, passing that - * element as a parameter, converting multiple values from yield to an - * array. - * - * If no block is given, an enumerator is returned instead. - * - * class Foo - * include Enumerable - * def each - * yield 1 - * yield 1, 2 - * yield - * end - * end - * Foo.new.each_entry{ |o| p o } + * each_entry(*args) {|element| ... } -> self + * each_entry(*args) -> enumerator + * + * Calls the given block with each element, + * converting multiple values from yield to an array; returns +self+: + * + * a = [] + * (1..4).each_entry {|element| a.push(element) } # => 1..4 + * a # => [1, 2, 3, 4] + * + * a = [] + * h = {foo: 0, bar: 1, baz:2} + * h.each_entry {|element| a.push(element) } + * # => {:foo=>0, :bar=>1, :baz=>2} + * a # => [[:foo, 0], [:bar, 1], [:baz, 2]] + * + * class Foo + * include Enumerable + * def each + * yield 1 + * yield 1, 2 + * yield + * end + * end + * Foo.new.each_entry {|yielded| p yielded } * - * produces: + * Output: * - * 1 - * [1, 2] - * nil + * 1 + * [1, 2] + * nil + * + * With no block given, returns an Enumerator. * */ @@ -2537,7 +2950,7 @@ enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj) if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size"); size = enum_size(obj, 0, 0); - if (size == Qnil) return Qnil; + if (NIL_P(size)) return Qnil; if (RB_FLOAT_TYPE_P(size) && RTEST(rb_funcall(size, infinite_p, 0))) { return size; } @@ -2548,18 +2961,22 @@ enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj) /* * call-seq: - * enum.each_slice(n) { ... } -> nil - * enum.each_slice(n) -> an_enumerator + * each_slice(n) { ... } -> self + * each_slice(n) -> enumerator + * + * Calls the block with each successive disjoint +n+-tuple of elements; + * returns +self+: + * + * a = [] + * (1..10).each_slice(3) {|tuple| a.push(tuple) } + * a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] * - * Iterates the given block for each slice of elements. If no - * block is given, returns an enumerator. + * a = [] + * h = {foo: 0, bar: 1, baz: 2, bat: 3, bam: 4} + * h.each_slice(2) {|tuple| a.push(tuple) } + * a # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]], [[:bam, 4]]] * - * (1..10).each_slice(3) { |a| p a } - * # outputs below - * [1, 2, 3] - * [4, 5, 6] - * [7, 8, 9] - * [10] + * With no block given, returns an Enumerator. * */ static VALUE @@ -2580,7 +2997,7 @@ enum_each_slice(VALUE obj, VALUE n) ary = memo->v1; if (RARRAY_LEN(ary) > 0) rb_yield(ary); - return Qnil; + return obj; } static VALUE @@ -2615,7 +3032,7 @@ enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj) if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size"); size = enum_size(obj, 0, 0); - if (size == Qnil) return Qnil; + if (NIL_P(size)) return Qnil; n = add_int(size, 1 - cons_size); return (OPTIMIZED_CMP(n, zero, cmp_opt) == -1) ? zero : n; @@ -2623,23 +3040,22 @@ enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj) /* * call-seq: - * enum.each_cons(n) { ... } -> nil - * enum.each_cons(n) -> an_enumerator - * - * Iterates the given block for each array of consecutive - * elements. If no block is given, returns an enumerator. - * - * e.g.: - * (1..10).each_cons(3) { |a| p a } - * # outputs below - * [1, 2, 3] - * [2, 3, 4] - * [3, 4, 5] - * [4, 5, 6] - * [5, 6, 7] - * [6, 7, 8] - * [7, 8, 9] - * [8, 9, 10] + * each_cons(n) { ... } -> self + * each_cons(n) -> enumerator + * + * Calls the block with each successive overlapped +n+-tuple of elements; + * returns +self+: + * + * a = [] + * (1..5).each_cons(3) {|element| a.push(element) } + * a # => [[1, 2, 3], [2, 3, 4], [3, 4, 5]] + * + * a = [] + * h = {foo: 0, bar: 1, baz: 2, bam: 3} + * h.each_cons(2) {|element| a.push(element) } + * a # => [[[:foo, 0], [:bar, 1]], [[:bar, 1], [:baz, 2]], [[:baz, 2], [:bam, 3]]] + * + * With no block given, returns an Enumerator. * */ static VALUE @@ -2652,11 +3068,11 @@ enum_each_cons(VALUE obj, VALUE n) if (size <= 0) rb_raise(rb_eArgError, "invalid size"); RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size); arity = rb_block_arity(); - if (enum_size_over_p(obj, size)) return Qnil; + if (enum_size_over_p(obj, size)) return obj; memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size); rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo); - return Qnil; + return obj; } static VALUE @@ -2668,16 +3084,17 @@ each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) /* * call-seq: - * enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj - * enum.each_with_object(obj) -> an_enumerator + * each_with_object(object) { |(*args), memo_object| ... } -> object + * each_with_object(object) -> enumerator * - * Iterates the given block for each element with an arbitrary - * object given, and returns the initially given object. + * Calls the block once for each element, passing both the element + * and the given object: * - * If no block is given, returns an enumerator. + * (1..4).each_with_object([]) {|i, a| a.push(i**2) } # => [1, 4, 9, 16] + * h.each_with_object({}) {|element, h| k, v = *element; h[v] = k } + * # => {0=>:foo, 1=>:bar, 2=>:baz} * - * evens = (1..10).each_with_object([]) { |i, a| a << i*2 } - * #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + * With no block given, returns an Enumerator. * */ static VALUE @@ -2779,29 +3196,68 @@ zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval)) /* * call-seq: - * enum.zip(arg, ...) -> an_array_of_array - * enum.zip(arg, ...) { |arr| block } -> nil - * - * Takes one element from enum and merges corresponding - * elements from each args. This generates a sequence of - * n-element arrays, where n is one more than the - * count of arguments. The length of the resulting sequence will be - * enum#size. If the size of any argument is less than - * enum#size, nil values are supplied. If - * a block is given, it is invoked for each output array, otherwise - * an array of arrays is returned. - * - * a = [ 4, 5, 6 ] - * b = [ 7, 8, 9 ] - * - * a.zip(b) #=> [[4, 7], [5, 8], [6, 9]] - * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]] - * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]] - * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]] - * - * c = [] - * a.zip(b) { |x, y| c << x + y } #=> nil - * c #=> [11, 13, 15] + * zip(*other_enums) -> array + * zip(*other_enums) {|array| ... } -> nil + * + * With no block given, returns a new array +new_array+ of size self.size + * whose elements are arrays. + * Each nested array new_array[n] + * is of size other_enums.size+1, and contains: + * + * - The +n+-th element of self. + * - The +n+-th element of each of the +other_enums+. + * + * If all +other_enums+ and self are the same size, + * all elements are included in the result, and there is no +nil+-filling: + * + * 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]] + * + * f = {foo: 0, bar: 1, baz: 2} + * g = {goo: 3, gar: 4, gaz: 5} + * h = {hoo: 6, har: 7, haz: 8} + * d = f.zip(g, h) + * d # => [ + * # [[:foo, 0], [:goo, 3], [:hoo, 6]], + * # [[:bar, 1], [:gar, 4], [:har, 7]], + * # [[:baz, 2], [:gaz, 5], [:haz, 8]] + * # ] + * + * If any enumerable in other_enums is smaller than self, + * fills to self.size with +nil+: + * + * 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]] + * + * If any enumerable in other_enums is larger than self, + * its trailing elements are ignored: + * + * 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]] + * + * When a block is given, calls the block with each of the sub-arrays + * (formed as above); returns nil: + * + * 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] * */ @@ -2857,13 +3313,16 @@ take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.take(n) -> array + * take(n) -> array + * + * For non-negative integer +n+, returns the first +n+ elements: * - * Returns first n elements from enum. + * r = (1..4) + * r.take(2) # => [1, 2] + * r.take(0) # => [] * - * a = [1, 2, 3, 4, 5, 0] - * a.take(3) #=> [1, 2, 3] - * a.take(30) #=> [1, 2, 3, 4, 5, 0] + * h = {foo: 0, bar: 1, baz: 2, bat: 3} + * h.take(2) # => [[:foo, 0], [:bar, 1]] * */ @@ -2896,16 +3355,20 @@ take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) /* * call-seq: - * enum.take_while { |obj| block } -> array - * enum.take_while -> an_enumerator + * take_while {|element| ... } -> array + * take_while -> enumerator * - * Passes elements to the block until the block returns +nil+ or +false+, - * then stops iterating and returns an array of all prior elements. + * Calls the block with successive elements as long as the block + * returns a truthy value; + * returns an array of all elements up to that point: * - * If no block is given, an enumerator is returned instead. * - * a = [1, 2, 3, 4, 5, 0] - * a.take_while { |i| i < 3 } #=> [1, 2] + * (1..4).take_while{|i| i < 3 } # => [1, 2] + * h = {foo: 0, bar: 1, baz: 2} + * h.take_while{|element| key, value = *element; value < 2 } + * # => [[:foo, 0], [:bar, 1]] + * + * With no block given, returns an Enumerator. * */ @@ -2935,13 +3398,20 @@ drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.drop(n) -> array + * drop(n) -> array + * + * For positive integer +n+, returns an array containing + * all but the first +n+ elements: * - * Drops first n elements from enum, and returns rest elements - * in an array. + * r = (1..4) + * r.drop(3) # => [4] + * r.drop(2) # => [3, 4] + * r.drop(1) # => [2, 3, 4] + * r.drop(0) # => [1, 2, 3, 4] + * r.drop(50) # => [] * - * a = [1, 2, 3, 4, 5, 0] - * a.drop(3) #=> [4, 5, 0] + * h = {foo: 0, bar: 1, baz: 2, bat: 3} + * h.drop(2) # => [[:baz, 2], [:bat, 3]] * */ @@ -2980,17 +3450,20 @@ drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) /* * call-seq: - * enum.drop_while { |obj| block } -> array - * enum.drop_while -> an_enumerator + * drop_while {|element| ... } -> array + * drop_while -> enumerator + * + * Calls the block with successive elements as long as the block + * returns a truthy value; + * returns an array of all elements after that point: * - * Drops elements up to, but not including, the first element for - * which the block returns +nil+ or +false+ and returns an array - * containing the remaining elements. * - * If no block is given, an enumerator is returned instead. + * (1..4).drop_while{|i| i < 3 } # => [3, 4] + * h = {foo: 0, bar: 1, baz: 2} + * a = h.drop_while{|element| key, value = *element; value < 2 } + * a # => [[:baz, 2]] * - * a = [1, 2, 3, 4, 5, 0] - * a.drop_while { |i| i < 3 } #=> [3, 4, 5, 0] + * With no block given, returns an Enumerator. * */ @@ -3040,22 +3513,28 @@ enum_cycle_size(VALUE self, VALUE args, VALUE eobj) /* * call-seq: - * enum.cycle(n=nil) { |obj| block } -> nil - * enum.cycle(n=nil) -> an_enumerator + * cycle(n = nil) {|element| ...} -> nil + * cycle(n = nil) -> enumerator * - * Calls block for each element of enum repeatedly _n_ - * times or forever if none or +nil+ is given. If a non-positive - * number is given or the collection is empty, does nothing. Returns - * +nil+ if the loop has finished without getting interrupted. + * When called with positive integer argument +n+ and a block, + * calls the block with each element, then does so again, + * until it has done so +n+ times; returns +nil+: * - * Enumerable#cycle saves elements in an internal array so changes - * to enum after the first pass have no effect. + * a = [] + * (1..4).cycle(3) {|element| a.push(element) } # => nil + * a # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4] + * a = [] + * ('a'..'d').cycle(2) {|element| a.push(element) } + * a # => ["a", "b", "c", "d", "a", "b", "c", "d"] + * a = [] + * {foo: 0, bar: 1, baz: 2}.cycle(2) {|element| a.push(element) } + * a # => [[:foo, 0], [:bar, 1], [:baz, 2], [:foo, 0], [:bar, 1], [:baz, 2]] * - * If no block is given, an enumerator is returned instead. + * If count is zero or negative, does not call the block. * - * a = ["a", "b", "c"] - * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever. - * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c. + * When called with a block and +n+ is +nil+, cycles forever. + * + * When no block is given, returns an Enumerator. * */ @@ -3101,8 +3580,8 @@ chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp)) { struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp); VALUE v, s; - VALUE alone = ID2SYM(rb_intern("_alone")); - VALUE separator = ID2SYM(rb_intern("_separator")); + VALUE alone = ID2SYM(id__alone); + VALUE separator = ID2SYM(id__separator); ENUM_WANT_SVALUE(); @@ -3154,8 +3633,8 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) VALUE arg; struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg); - enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable")); - memo->categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize")); + enumerable = rb_ivar_get(enumerator, id_chunk_enumerable); + memo->categorize = rb_ivar_get(enumerator, id_chunk_categorize); memo->prev_value = Qnil; memo->prev_elts = Qnil; memo->yielder = yielder; @@ -3171,50 +3650,78 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) /* * call-seq: - * enum.chunk { |elt| ... } -> an_enumerator + * chunk {|array| ... } -> enumerator * - * Enumerates over the items, chunking them together based on the return - * value of the block. + * Each element in the returned enumerator is a 2-element array consisting of: * - * Consecutive elements which return the same block value are chunked together. + * - A value returned by the block. + * - An array ("chunk") containing the element for which that value was returned, + * and all following elements for which the block returned the same value: * - * For example, consecutive even numbers and odd numbers can be - * chunked as follows. + * So that: * - * [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n| - * n.even? - * }.each { |even, ary| - * p [even, ary] - * } - * #=> [false, [3, 1]] - * # [true, [4]] - * # [false, [1, 5, 9]] - * # [true, [2, 6]] - * # [false, [5, 3, 5]] + * - Each block return value that is different from its predecessor + * begins a new chunk. + * - Each block return value that is the same as its predecessor + * continues the same chunk. + * + * Example: + * + * e = (0..10).chunk {|i| (i / 3).floor } # => # + * # The enumerator elements. + * e.next # => [0, [0, 1, 2]] + * e.next # => [1, [3, 4, 5]] + * e.next # => [2, [6, 7, 8]] + * e.next # => [3, [9, 10]] + * + * \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. + * url = 'https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt' + * words = URI::open(url).readlines + * # Make chunks, one for each letter. + * e = words.chunk {|word| word.upcase[0] } # => # + * # Display 'A' through 'F'. + * e.each {|c, words| p [c, words.length]; break if c == 'F' } * - * This method is especially useful for sorted series of elements. - * The following example counts words for each initial letter. + * Output: * - * open("/usr/share/dict/words", "r:iso-8859-1") { |f| - * f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] } + * ["A", 17096] + * ["B", 11070] + * ["C", 19901] + * ["D", 10896] + * ["E", 8736] + * ["F", 6860] + * + * You can use the special symbol :_alone to force an element + * into its own separate chuck: + * + * a = [0, 0, 1, 1] + * e = a.chunk{|i| i.even? ? :_alone : true } + * e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]] + * + * For example, you can put each line that contains a URL into its own chunk: + * + * pattern = /http/ + * open(filename) { |f| + * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines| + * pp lines + * } * } - * #=> ["\n", 1] - * # ["A", 1327] - * # ["B", 1372] - * # ["C", 1507] - * # ["D", 791] - * # ... * - * The following key values have special meaning: - * - +nil+ and +:_separator+ specifies that the elements should be dropped. - * - +:_alone+ specifies that the element should be chunked by itself. + * You can use the special symbol :_separator or +nil+ + * to force an element to be ignored (not included in any chunk): * - * Any other symbols that begin with an underscore will raise an error: + * a = [0, 0, -1, 1, 1] + * e = a.chunk{|i| i < 0 ? :_separator : true } + * e.to_a # => [[true, [0, 0]], [true, [1, 1]]] * - * items.chunk { |item| :_underscore } - * #=> RuntimeError: symbols beginning with an underscore are reserved + * Note that the separator does end the chunk: * - * +nil+ and +:_separator+ can be used to ignore some elements. + * a = [0, 0, -1, 1, -1, 1] + * e = a.chunk{|i| i < 0 ? :_separator : true } + * e.to_a # => [[true, [0, 0]], [true, [1]], [true, [1]]] * * For example, the sequence of hyphens in svn log can be eliminated as follows: * @@ -3244,18 +3751,6 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) * pp lines * } * - * +:_alone+ can be used to force items into their own chunk. - * For example, you can put lines that contain a URL by themselves, - * and chunk the rest of the lines together, like this: - * - * pattern = /http/ - * open(filename) { |f| - * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines| - * pp lines - * } - * } - * - * If no block is given, an enumerator to `chunk` is returned instead. */ static VALUE enum_chunk(VALUE enumerable) @@ -3265,8 +3760,8 @@ enum_chunk(VALUE enumerable) RETURN_SIZED_ENUMERATOR(enumerable, 0, 0, enum_size); enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable); - rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc()); + rb_ivar_set(enumerator, id_chunk_enumerable, enumerable); + rb_ivar_set(enumerator, id_chunk_categorize, rb_block_proc()); rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator); return enumerator; } @@ -3313,9 +3808,9 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) VALUE arg; struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg); - enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable")); - memo->sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred")); - memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil; + enumerable = rb_ivar_get(enumerator, id_slicebefore_enumerable); + memo->sep_pred = rb_attr_get(enumerator, id_slicebefore_sep_pred); + memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, id_slicebefore_sep_pat) : Qnil; memo->prev_elts = Qnil; memo->yielder = yielder; @@ -3328,24 +3823,41 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) /* * call-seq: - * enum.slice_before(pattern) -> an_enumerator - * enum.slice_before { |elt| bool } -> an_enumerator + * slice_before(pattern) -> enumerator + * slice_before {|array| ... } -> enumerator * - * Creates an enumerator for each chunked elements. - * The beginnings of chunks are defined by _pattern_ and the block. - - * If _pattern_ === _elt_ returns true or the block - * returns true for the element, the element is beginning of a - * chunk. - - * The === and _block_ is called from the first element to the last - * element of _enum_. The result for the first element is ignored. - - * The result enumerator yields the chunked elements as an array. - * So +each+ method can be called as follows: + * With argument +pattern+, returns an enumerator that uses the pattern + * to partition elements into arrays ("slices"). + * An element begins a new slice if element === pattern + * (or if it is the first element). + * + * a = %w[foo bar fop for baz fob fog bam foy] + * e = a.slice_before(/ba/) # => # + * e.each {|array| p array } + * + * Output: + * + * ["foo"] + * ["bar", "fop", "for"] + * ["baz", "fob", "fog"] + * ["bam", "foy"] + * + * With a block, returns an enumerator that uses the block + * to partition elements into arrays. + * An element begins a new slice if its block return is a truthy value + * (or if it is the first element): * - * enum.slice_before(pattern).each { |ary| ... } - * enum.slice_before { |elt| bool }.each { |ary| ... } + * e = (1..20).slice_before {|i| i % 4 == 2 } # => # + * e.each {|array| p array } + * + * Output: + * + * [1] + * [2, 3, 4, 5] + * [6, 7, 8, 9] + * [10, 11, 12, 13] + * [14, 15, 16, 17] + * [18, 19, 20] * * Other methods of the Enumerator class and Enumerable module, * such as +to_a+, +map+, etc., are also usable. @@ -3363,7 +3875,6 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e } * } * - * * "svn proplist -R" produces multiline output for each file. * They can be chunked as follows: * @@ -3479,15 +3990,15 @@ enum_slice_before(int argc, VALUE *argv, VALUE enumerable) if (argc != 0) rb_error_arity(argc, 0, 0); enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc()); + rb_ivar_set(enumerator, id_slicebefore_sep_pred, rb_block_proc()); } else { VALUE sep_pat; rb_scan_args(argc, argv, "1", &sep_pat); enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat); + rb_ivar_set(enumerator, id_slicebefore_sep_pat, sep_pat); } - rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable); + rb_ivar_set(enumerator, id_slicebefore_enumerable, enumerable); rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator); return enumerator; } @@ -3543,9 +4054,9 @@ sliceafter_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) VALUE arg; struct sliceafter_arg *memo = NEW_MEMO_FOR(struct sliceafter_arg, arg); - enumerable = rb_ivar_get(enumerator, rb_intern("sliceafter_enum")); - memo->pat = rb_ivar_get(enumerator, rb_intern("sliceafter_pat")); - memo->pred = rb_attr_get(enumerator, rb_intern("sliceafter_pred")); + enumerable = rb_ivar_get(enumerator, id_sliceafter_enum); + memo->pat = rb_ivar_get(enumerator, id_sliceafter_pat); + memo->pred = rb_attr_get(enumerator, id_sliceafter_pred); memo->prev_elts = Qnil; memo->yielder = yielder; @@ -3558,24 +4069,39 @@ sliceafter_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) /* * call-seq: - * enum.slice_after(pattern) -> an_enumerator - * enum.slice_after { |elt| bool } -> an_enumerator + * slice_after(pattern) -> enumerator + * slice_after {|array| ... } -> enumerator + * + * With argument +pattern+, returns an enumerator that uses the pattern + * to partition elements into arrays ("slices"). + * An element ends the current slice if element === pattern: + * + * a = %w[foo bar fop for baz fob fog bam foy] + * e = a.slice_after(/ba/) # => # + * e.each {|array| p array } + * + * Output: * - * Creates an enumerator for each chunked elements. - * The ends of chunks are defined by _pattern_ and the block. + * ["foo", "bar"] + * ["fop", "for", "baz"] + * ["fob", "fog", "bam"] + * ["foy"] * - * If _pattern_ === _elt_ returns true or the block - * returns true for the element, the element is end of a - * chunk. + * With a block, returns an enumerator that uses the block + * to partition elements into arrays. + * An element ends the current slice if its block return is a truthy value: * - * The === and _block_ is called from the first element to the last - * element of _enum_. + * e = (1..20).slice_after {|i| i % 4 == 2 } # => # + * e.each {|array| p array } * - * The result enumerator yields the chunked elements as an array. - * So +each+ method can be called as follows: + * Output: * - * enum.slice_after(pattern).each { |ary| ... } - * enum.slice_after { |elt| bool }.each { |ary| ... } + * [1, 2] + * [3, 4, 5, 6] + * [7, 8, 9, 10] + * [11, 12, 13, 14] + * [15, 16, 17, 18] + * [19, 20] * * Other methods of the Enumerator class and Enumerable module, * such as +map+, etc., are also usable. @@ -3608,9 +4134,9 @@ enum_slice_after(int argc, VALUE *argv, VALUE enumerable) } enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("sliceafter_enum"), enumerable); - rb_ivar_set(enumerator, rb_intern("sliceafter_pat"), pat); - rb_ivar_set(enumerator, rb_intern("sliceafter_pred"), pred); + rb_ivar_set(enumerator, id_sliceafter_enum, enumerable); + rb_ivar_set(enumerator, id_sliceafter_pat, pat); + rb_ivar_set(enumerator, id_sliceafter_pred, pred); rb_block_call(enumerator, idInitialize, 0, 0, sliceafter_i, enumerator); return enumerator; @@ -3673,12 +4199,12 @@ slicewhen_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) struct slicewhen_arg *memo = NEW_PARTIAL_MEMO_FOR(struct slicewhen_arg, arg, inverted); - enumerable = rb_ivar_get(enumerator, rb_intern("slicewhen_enum")); - memo->pred = rb_attr_get(enumerator, rb_intern("slicewhen_pred")); + enumerable = rb_ivar_get(enumerator, id_slicewhen_enum); + memo->pred = rb_attr_get(enumerator, id_slicewhen_pred); memo->prev_elt = Qundef; memo->prev_elts = Qnil; memo->yielder = yielder; - memo->inverted = RTEST(rb_attr_get(enumerator, rb_intern("slicewhen_inverted"))); + memo->inverted = RTEST(rb_attr_get(enumerator, id_slicewhen_inverted)); rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg); memo = MEMO_FOR(struct slicewhen_arg, arg); @@ -3689,65 +4215,23 @@ slicewhen_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) /* * call-seq: - * enum.slice_when {|elt_before, elt_after| bool } -> an_enumerator + * slice_when {|element, next_element| ... } -> enumerator * - * Creates an enumerator for each chunked elements. - * The beginnings of chunks are defined by the block. + * The returned enumerator uses the block + * to partition elements into arrays ("slices"); + * it calls the block with each element and its successor; + * begins a new slice if and only if the block returns a truthy value: * - * This method split each chunk using adjacent elements, - * _elt_before_ and _elt_after_, - * in the receiver enumerator. - * This method split chunks between _elt_before_ and _elt_after_ where - * the block returns true. + * a = [0, 1, 2, 4, 5, 6, 8, 9] + * e = a.slice_when {|i, j| j != i + 1 } + * e.each {|array| p array } * - * The block is called the length of the receiver enumerator minus one. + * Output: * - * The result enumerator yields the chunked elements as an array. - * So +each+ method can be called as follows: + * [0, 1, 2] + * [4, 5, 6] + * [8, 9] * - * enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... } - * - * Other methods of the Enumerator class and Enumerable module, - * such as +to_a+, +map+, etc., are also usable. - * - * For example, one-by-one increasing subsequence can be chunked as follows: - * - * a = [1,2,4,9,10,11,12,15,16,19,20,21] - * b = a.slice_when {|i, j| i+1 != j } - * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]] - * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" } - * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"] - * d = c.join(",") - * p d #=> "1,2,4,9-12,15,16,19-21" - * - * Near elements (threshold: 6) in sorted array can be chunked as follows: - * - * a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57] - * p a.slice_when {|i, j| 6 < j - i }.to_a - * #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]] - * - * Increasing (non-decreasing) subsequence can be chunked as follows: - * - * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5] - * p a.slice_when {|i, j| i > j }.to_a - * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]] - * - * Adjacent evens and odds can be chunked as follows: - * (Enumerable#chunk is another way to do it.) - * - * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0] - * p a.slice_when {|i, j| i.even? != j.even? }.to_a - * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]] - * - * Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows: - * (See Enumerable#chunk to ignore empty lines.) - * - * lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"] - * p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a - * #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]] - * - * Enumerable#chunk_while does the same, except splitting when the block - * returns false instead of true. */ static VALUE enum_slice_when(VALUE enumerable) @@ -3758,9 +4242,9 @@ enum_slice_when(VALUE enumerable) pred = rb_block_proc(); enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("slicewhen_enum"), enumerable); - rb_ivar_set(enumerator, rb_intern("slicewhen_pred"), pred); - rb_ivar_set(enumerator, rb_intern("slicewhen_inverted"), Qfalse); + rb_ivar_set(enumerator, id_slicewhen_enum, enumerable); + rb_ivar_set(enumerator, id_slicewhen_pred, pred); + rb_ivar_set(enumerator, id_slicewhen_inverted, Qfalse); rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator); return enumerator; @@ -3768,52 +4252,27 @@ enum_slice_when(VALUE enumerable) /* * call-seq: - * enum.chunk_while {|elt_before, elt_after| bool } -> an_enumerator - * - * Creates an enumerator for each chunked elements. - * The beginnings of chunks are defined by the block. - * - * This method split each chunk using adjacent elements, - * _elt_before_ and _elt_after_, - * in the receiver enumerator. - * This method split chunks between _elt_before_ and _elt_after_ where - * the block returns false. - * - * The block is called the length of the receiver enumerator minus one. - * - * The result enumerator yields the chunked elements as an array. - * So +each+ method can be called as follows: + * chunk_while {|element, next_element| ... } -> enumerator * - * enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... } + * The returned Enumerator uses the block to partition elements + * into arrays ("chunks"); + * it calls the block with each element and its successor; + * begins a new chunk if and only if the block returns a truthy value: * - * Other methods of the Enumerator class and Enumerable module, - * such as +to_a+, +map+, etc., are also usable. - * - * For example, one-by-one increasing subsequence can be chunked as follows: + * Example: * - * a = [1,2,4,9,10,11,12,15,16,19,20,21] - * b = a.chunk_while {|i, j| i+1 == j } - * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]] - * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" } - * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"] - * d = c.join(",") - * p d #=> "1,2,4,9-12,15,16,19-21" + * a = [1, 2, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21] + * e = a.chunk_while {|i, j| j == i + 1 } + * e.each {|array| p array } * - * Increasing (non-decreasing) subsequence can be chunked as follows: + * Output: * - * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5] - * p a.chunk_while {|i, j| i <= j }.to_a - * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]] + * [1, 2] + * [4] + * [9, 10, 11, 12] + * [15, 16] + * [19, 20, 21] * - * Adjacent evens and odds can be chunked as follows: - * (Enumerable#chunk is another way to do it.) - * - * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0] - * p a.chunk_while {|i, j| i.even? == j.even? }.to_a - * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]] - * - * Enumerable#slice_when does the same, except splitting when the block - * returns true instead of false. */ static VALUE enum_chunk_while(VALUE enumerable) @@ -3824,9 +4283,9 @@ enum_chunk_while(VALUE enumerable) pred = rb_block_proc(); enumerator = rb_obj_alloc(rb_cEnumerator); - rb_ivar_set(enumerator, rb_intern("slicewhen_enum"), enumerable); - rb_ivar_set(enumerator, rb_intern("slicewhen_pred"), pred); - rb_ivar_set(enumerator, rb_intern("slicewhen_inverted"), Qtrue); + rb_ivar_set(enumerator, id_slicewhen_enum, enumerable); + rb_ivar_set(enumerator, id_slicewhen_pred, pred); + rb_ivar_set(enumerator, id_slicewhen_inverted, Qtrue); rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator); return enumerator; @@ -3841,122 +4300,141 @@ struct enum_sum_memo { }; static void -sum_iter(VALUE i, struct enum_sum_memo *memo) +sum_iter_normalize_memo(struct enum_sum_memo *memo) { - const int unused = (assert(memo != NULL), 0); + assert(FIXABLE(memo->n)); + memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v); + memo->n = 0; - long n = memo->n; - VALUE v = memo->v; - VALUE r = memo->r; - double f = memo->f; - double c = memo->c; + switch (TYPE(memo->r)) { + case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v); break; + case T_UNDEF: break; + default: UNREACHABLE; /* or ...? */ + } + memo->r = Qundef; +} - if (memo->block_given) - i = rb_yield(i); +static void +sum_iter_fixnum(VALUE i, struct enum_sum_memo *memo) +{ + memo->n += FIX2LONG(i); /* should not overflow long type */ + if (! FIXABLE(memo->n)) { + memo->v = rb_big_plus(LONG2NUM(memo->n), memo->v); + memo->n = 0; + } +} - if (memo->float_value) - goto float_value; +static void +sum_iter_bignum(VALUE i, struct enum_sum_memo *memo) +{ + memo->v = rb_big_plus(i, memo->v); +} - if (FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || RB_TYPE_P(v, T_RATIONAL)) { - if (FIXNUM_P(i)) { - n += FIX2LONG(i); /* should not overflow long type */ - if (!FIXABLE(n)) { - v = rb_big_plus(LONG2NUM(n), v); - n = 0; - } - } - else if (RB_TYPE_P(i, T_BIGNUM)) - v = rb_big_plus(i, v); - else if (RB_TYPE_P(i, T_RATIONAL)) { - if (r == Qundef) - r = i; - else - r = rb_rational_plus(r, i); - } - else { - if (n != 0) { - v = rb_fix_plus(LONG2FIX(n), v); - n = 0; - } - if (r != Qundef) { - /* r can be an Integer when mathn is loaded */ - if (FIXNUM_P(r)) - v = rb_fix_plus(r, v); - else if (RB_TYPE_P(r, T_BIGNUM)) - v = rb_big_plus(r, v); - else - v = rb_rational_plus(r, v); - r = Qundef; - } - if (RB_FLOAT_TYPE_P(i)) { - f = NUM2DBL(v); - c = 0.0; - memo->float_value = 1; - goto float_value; - } - else - goto some_value; - } +static void +sum_iter_rational(VALUE i, struct enum_sum_memo *memo) +{ + if (memo->r == Qundef) { + memo->r = i; } - else if (RB_FLOAT_TYPE_P(v)) { - /* - * Kahan-Babuska balancing compensated summation algorithm - * See http://link.springer.com/article/10.1007/s00607-005-0139-x - */ - double x, t; - - float_value: - if (RB_FLOAT_TYPE_P(i)) - x = RFLOAT_VALUE(i); - else if (FIXNUM_P(i)) - x = FIX2LONG(i); - else if (RB_TYPE_P(i, T_BIGNUM)) - x = rb_big2dbl(i); - else if (RB_TYPE_P(i, T_RATIONAL)) - x = rb_num2dbl(i); - else { - v = DBL2NUM(f); - memo->float_value = 0; - goto some_value; - } + else { + memo->r = rb_rational_plus(memo->r, i); + } +} - if (isnan(f)) return; - if (isnan(x)) { - memo->v = i; - memo->f = x; - return; - } - if (isinf(x)) { - if (isinf(f) && signbit(x) != signbit(f)) { - memo->f = NAN; - memo->v = DBL2NUM(f); - } - else { - memo->f = x; - memo->v = i; - } - return; +static void +sum_iter_some_value(VALUE i, struct enum_sum_memo *memo) +{ + memo->v = rb_funcallv(memo->v, idPLUS, 1, &i); +} + +static void +sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo) +{ + /* + * Kahan-Babuska balancing compensated summation algorithm + * See https://link.springer.com/article/10.1007/s00607-005-0139-x + */ + double x; + + switch (TYPE(i)) { + case T_FLOAT: x = RFLOAT_VALUE(i); break; + case T_FIXNUM: x = FIX2LONG(i); break; + case T_BIGNUM: x = rb_big2dbl(i); break; + case T_RATIONAL: x = rb_num2dbl(i); break; + default: + memo->v = DBL2NUM(memo->f); + memo->float_value = 0; + sum_iter_some_value(i, memo); + return; + } + + double f = memo->f; + + if (isnan(f)) { + return; + } + else if (! isfinite(x)) { + if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) { + i = DBL2NUM(f); + x = nan(""); } - if (isinf(f)) return; + memo->v = i; + memo->f = x; + return; + } + else if (isinf(f)) { + return; + } - t = f + x; - if (fabs(f) >= fabs(x)) - c += ((f - t) + x); - else - c += ((x - t) + f); - f = t; + double c = memo->c; + double t = f + x; + + if (fabs(f) >= fabs(x)) { + c += ((f - t) + x); } else { - some_value: - v = rb_funcallv(v, idPLUS, 1, &i); + c += ((x - t) + f); } + f = t; - memo->v = v; - memo->n = n; - memo->r = r; memo->f = f; memo->c = c; - (void)unused; +} + +static void +sum_iter(VALUE i, struct enum_sum_memo *memo) +{ + assert(memo != NULL); + if (memo->block_given) { + i = rb_yield(i); + } + + if (memo->float_value) { + sum_iter_Kahan_Babuska(i, 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_FIXNUM: + case T_BIGNUM: + case T_RATIONAL: + switch (TYPE(i)) { + case T_FIXNUM: sum_iter_fixnum(i, memo); return; + case T_BIGNUM: sum_iter_bignum(i, memo); return; + case T_RATIONAL: sum_iter_rational(i, memo); return; + case T_FLOAT: + sum_iter_normalize_memo(memo); + memo->f = NUM2DBL(memo->v); + memo->c = 0.0; + memo->float_value = 1; + sum_iter_Kahan_Babuska(i, memo); + return; + default: + sum_iter_normalize_memo(memo); + sum_iter_some_value(i, memo); + return; + } + } } static VALUE @@ -4005,36 +4483,35 @@ int_range_sum(VALUE beg, VALUE end, int excl, VALUE init) } /* - * call-seq: - * enum.sum(init=0) -> number - * enum.sum(init=0) {|e| expr } -> number - * - * Returns the sum of elements in an Enumerable. + * call-seq: + * sum(initial_value = 0) -> number + * sum(initial_value = 0) {|element| ... } -> object * - * If a block is given, the block is applied to each element - * before addition. + * With no block given, + * returns the sum of +initial_value+ and the elements: * - * If enum is empty, it returns init. + * (1..100).sum # => 5050 + * (1..100).sum(1) # => 5051 + * ('a'..'d').sum('foo') # => "fooabcd" * - * For example: + * Generally, the sum is computed using methods + and +each+; + * for performance optimizations, those methods may not be used, + * and so any redefinition of those methods may not have effect here. * - * { 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50 - * (1..10).sum #=> 55 - * (1..10).sum {|v| v * 2 } #=> 110 - * ('a'..'z').sum #=> TypeError + * One such optimization: When possible, computes using Gauss's summation + * formula n(n+1)/2: * - * This method can be used for non-numeric objects by - * explicit init argument. + * 100 * (100 + 1) / 2 # => 5050 * - * { 1 => 10, 2 => 20 }.sum([]) #=> [1, 10, 2, 20] - * "a\nb\nc".each_line.lazy.map(&:chomp).sum("") #=> "abc" + * With a block given, calls the block with each element; + * returns the sum of +initial_value+ and the block return values: * - * If the method is applied to an Integer range without a block, - * the sum is not done by iteration, but instead using Gauss's summation - * formula. + * (1..4).sum {|i| i*i } # => 30 + * (1..4).sum(100) {|i| i*i } # => 130 + * h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5} + * h.sum {|key, value| value.odd? ? value : 0 } # => 9 + * ('a'..'f').sum('x') {|c| c < 'd' ? c : '' } # => "xabc" * - * Enumerable#sum method may not respect method redefinition of "+" - * methods such as Integer#+, or "each" methods such as Range#each. */ static VALUE enum_sum(int argc, VALUE* argv, VALUE obj) @@ -4059,8 +4536,8 @@ enum_sum(int argc, VALUE* argv, VALUE obj) if (RTEST(rb_range_values(obj, &beg, &end, &excl))) { if (!memo.block_given && !memo.float_value && - (FIXNUM_P(beg) || RB_TYPE_P(beg, T_BIGNUM)) && - (FIXNUM_P(end) || RB_TYPE_P(end, T_BIGNUM))) { + (FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) && + (FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) { return int_range_sum(beg, end, excl, memo.v); } } @@ -4078,13 +4555,7 @@ enum_sum(int argc, VALUE* argv, VALUE obj) if (memo.n != 0) memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v); if (memo.r != Qundef) { - /* r can be an Integer when mathn is loaded */ - if (FIXNUM_P(memo.r)) - memo.v = rb_fix_plus(memo.r, memo.v); - else if (RB_TYPE_P(memo.r, T_BIGNUM)) - memo.v = rb_big_plus(memo.r, memo.v); - else - memo.v = rb_rational_plus(memo.r, memo.v); + memo.v = rb_rational_plus(memo.r, memo.v); } return memo.v; } @@ -4108,12 +4579,23 @@ uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) /* * call-seq: - * enum.uniq -> new_ary - * enum.uniq { |item| ... } -> new_ary + * uniq -> array + * uniq {|element| ... } -> array + * + * With no block, returns a new array containing only unique elements; + * the array has no two elements +e0+ and +e1+ such that e0.eql?(e1): + * + * %w[a b c c b a a b c].uniq # => ["a", "b", "c"] + * [0, 1, 2, 2, 1, 0, 0, 1, 2].uniq # => [0, 1, 2] * - * Returns a new array by removing duplicate values in +self+. + * With a block, returns a new array containing only for which the block + * returns a unique value: + * + * a = [0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1] + * a.uniq {|i| i.even? ? i : 0 } # => [0, 2, 4] + * a = %w[a b c d e e d c b a a b c d e] + a.uniq {|c| c < 'c' } # => ["a", "c"] * - * See also Array#uniq. */ static VALUE @@ -4130,22 +4612,196 @@ enum_uniq(VALUE obj) return ret; } +static VALUE +compact_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) +{ + ENUM_WANT_SVALUE(); + + if (!NIL_P(i)) { + rb_ary_push(ary, i); + } + return Qnil; +} + +/* + * call-seq: + * compact -> array + * + * Returns an array of all non-+nil+ elements: + * + * a = [nil, 0, nil, 'a', false, nil, false, nil, 'a', nil, 0, nil] + * a.compact # => [0, "a", false, false, "a", 0] + * + */ + +static VALUE +enum_compact(VALUE obj) +{ + VALUE ary; + + ary = rb_ary_new(); + rb_block_call(obj, id_each, 0, 0, compact_i, ary); + + return ary; +} + + /* - * The Enumerable mixin provides collection classes with several - * traversal and searching methods, and with the ability to sort. The - * class must provide a method #each, which yields - * successive members of the collection. If Enumerable#max, #min, or - * #sort is used, the objects in the collection must also implement a - * meaningful <=> operator, as these methods rely on an - * ordering between members of the collection. + * == What's Here + * + * \Module \Enumerable provides methods that are useful to a collection class for: + * - {Querying}[#module-Enumerable-label-Methods+for+Querying] + * - {Fetching}[#module-Enumerable-label-Methods+for+Fetching] + * - {Searching}[#module-Enumerable-label-Methods+for+Searching] + * - {Sorting}[#module-Enumerable-label-Methods+for+Sorting] + * - {Iterating}[#module-Enumerable-label-Methods+for+Iterating] + * - {And more....}[#module-Enumerable-label-Other+Methods] + * + * === Methods for Querying + * + * These methods return information about the \Enumerable other than the elements themselves: + * + * #include?, #member?:: 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. + * #one?:: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise. + * #count:: Returns the count of elements, + * based on an argument or block criterion, if given. + * #tally:: Returns a new \Hash containing the counts of occurrences of each element. + * + * === Methods for Fetching + * + * These methods return entries from the \Enumerable, without modifying it: + * + * Leading, trailing, or all elements: + * #entries, #to_a:: 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. + * #take_while:: Returns leading elements as specified by the given block. + * #drop_while:: Returns trailing elements as specified by the given block. + * + * Minimum and maximum value elements: + * #min:: Returns the elements whose values are smallest among the elements, + * 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. + * #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. + * #minmax_by:: Returns the smallest and largest elements, as determined by the given block. + * + * Groups, slices, and partitions: + * #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. + * #slice_before:: Returns a new \Enumerator whose entries are a partition of +self+, + 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. + * #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. + * + * === Methods for Searching and Filtering + * + * 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_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. + * + * === Methods for Sorting + * + * These methods return elements in sorted order. + * + * #sort:: Returns the elements, sorted by <=> or the given block. + * #sort_by:: Returns the elements, sorted by the given block. + * + * === Methods for Iterating + * + * #each_entry:: Calls the block with each successive element + * (slightly different from #each). + * #each_with_index:: Calls the block with each successive element and its index. + * #each_with_object:: Calls the block with each successive element and a given object. + * #each_slice:: Calls the block with successive non-overlapping slices. + * #each_cons:: Calls the block with successive overlapping slices. + * (different from #each_slice). + * #reverse_each:: Calls the block with each successive element, in reverse order. + * + * === Other Methods + * + * #map, #collect:: 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. + * #grep:: Returns elements selected by a given object + * or objects returned by a given block. + * #grep_v:: Returns elements selected by a given object + * or objects returned by a given block. + * #reduce, #inject:: 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. + * #cycle:: Calls the block with each element, cycling repeatedly. + * + * == Usage + * + * To use module \Enumerable in a collection class: + * + * - Include it: + * + * include Enumerable + * + * - Implement method #each + * which must yield successive elements of the collection. + * The method will be called by almost any \Enumerable method. + * + * Example: + * + * class Foo + * include Enumerable + * def each + * yield 1 + * yield 1, 2 + * yield + * end + * end + * Foo.new.each_entry{ |element| p element } + * + * Output: + * + * 1 + * [1, 2] + * nil + * + * == \Enumerable in Ruby Core Classes + * Some Ruby classes include \Enumerable: + * - Array + * - Dir + * - Hash + * - IO + * - Range + * - Set + * - Struct + * Virtually all methods in \Enumerable call method +#each+ in the including class: + * - Hash#each yields the next key-value pair as a 2-element \Array. + * - Struct#each yields the next name-value pair as a 2-element \Array. + * - For the other classes above, +#each+ yields the next object from the collection. + * + * == About the Examples + * The example code snippets for the \Enumerable methods: + * - Always show the use of one or more \Array-like classes (often \Array itself). + * - Sometimes show the use of a \Hash-like class. + * 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. */ void Init_Enumerable(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - rb_mEnumerable = rb_define_module("Enumerable"); rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1); @@ -4173,7 +4829,7 @@ Init_Enumerable(void) rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1); rb_define_method(rb_mEnumerable, "partition", enum_partition, 0); rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0); - rb_define_method(rb_mEnumerable, "tally", enum_tally, 0); + rb_define_method(rb_mEnumerable, "tally", enum_tally, -1); rb_define_method(rb_mEnumerable, "first", enum_first, -1); rb_define_method(rb_mEnumerable, "all?", enum_all, -1); rb_define_method(rb_mEnumerable, "any?", enum_any, -1); @@ -4206,6 +4862,20 @@ Init_Enumerable(void) rb_define_method(rb_mEnumerable, "chunk_while", enum_chunk_while, 0); rb_define_method(rb_mEnumerable, "sum", enum_sum, -1); rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0); - - id_next = rb_intern("next"); + rb_define_method(rb_mEnumerable, "compact", enum_compact, 0); + + id__alone = rb_intern_const("_alone"); + id__separator = rb_intern_const("_separator"); + id_chunk_categorize = rb_intern_const("chunk_categorize"); + id_chunk_enumerable = rb_intern_const("chunk_enumerable"); + id_next = rb_intern_const("next"); + id_sliceafter_enum = rb_intern_const("sliceafter_enum"); + id_sliceafter_pat = rb_intern_const("sliceafter_pat"); + id_sliceafter_pred = rb_intern_const("sliceafter_pred"); + id_slicebefore_enumerable = rb_intern_const("slicebefore_enumerable"); + id_slicebefore_sep_pat = rb_intern_const("slicebefore_sep_pat"); + id_slicebefore_sep_pred = rb_intern_const("slicebefore_sep_pred"); + id_slicewhen_enum = rb_intern_const("slicewhen_enum"); + id_slicewhen_inverted = rb_intern_const("slicewhen_inverted"); + id_slicewhen_pred = rb_intern_const("slicewhen_pred"); } diff --git a/ruby/enumerator.c b/ruby/enumerator.c index 9d0547da0..be469ee38 100644 --- a/ruby/enumerator.c +++ b/ruby/enumerator.c @@ -12,14 +12,23 @@ ************************************************/ -#include "ruby/ruby.h" -#include "internal.h" -#include "id.h" +#include "ruby/internal/config.h" #ifdef HAVE_FLOAT_H #include #endif +#include "id.h" +#include "internal.h" +#include "internal/enumerator.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/numeric.h" +#include "internal/range.h" +#include "internal/rational.h" +#include "ruby/ruby.h" + /* * Document-class: Enumerator * @@ -73,6 +82,14 @@ * puts e.next # => 3 * puts e.next # raises StopIteration * + * Note that enumeration sequence by +next+, +next_values+, +peek+ and + * +peek_values+ do not affect other non-external + * enumeration methods, unless the underlying iteration method itself has + * side-effect, e.g. IO#each_line. + * + * Moreover, implementation typically uses fibers so performance could be + * slower and exception stacktraces different than expected. + * * You can use this to implement an internal iterator as follows: * * def ext_each(e) @@ -376,8 +393,6 @@ enumerator_allocate(VALUE klass) return enum_obj; } -#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p()) - static VALUE enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat) { @@ -405,15 +420,31 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar return enum_obj; } +static VALUE +convert_to_feasible_size_value(VALUE obj) +{ + if (NIL_P(obj)) { + return obj; + } + else if (rb_respond_to(obj, id_call)) { + return obj; + } + else if (RB_FLOAT_TYPE_P(obj) && RFLOAT_VALUE(obj) == HUGE_VAL) { + return obj; + } + else { + return rb_to_int(obj); + } +} + /* * call-seq: * Enumerator.new(size = nil) { |yielder| ... } - * Enumerator.new(obj, method = :each, *args) * * Creates a new Enumerator object, which can be used as an * Enumerable. * - * In the first form, iteration is defined by the given block, in + * Iteration is defined by the given block, in * which a "yielder" object, given as block parameter, can be used to * yield a value by calling the +yield+ method (aliased as <<): * @@ -430,52 +461,16 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar * The optional parameter can be used to specify how to calculate the size * in a lazy fashion (see Enumerator#size). It can either be a value or * a callable object. - * - * In the deprecated second form, a generated Enumerator iterates over the - * given object using the given method with the given arguments passed. - * - * Use of this form is discouraged. Use Object#enum_for or Object#to_enum - * instead. - * - * e = Enumerator.new(ObjectSpace, :each_object) - * #-> ObjectSpace.enum_for(:each_object) - * - * e.select { |obj| obj.is_a?(Class) } # => array of all classes - * */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { - VALUE recv, meth = sym_each; - VALUE size = Qnil; - int kw_splat = 0; - - if (rb_block_given_p()) { - rb_check_arity(argc, 0, 1); - recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); - if (argc) { - if (NIL_P(argv[0]) || rb_respond_to(argv[0], id_call) || - (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == HUGE_VAL)) { - size = argv[0]; - } - else { - size = rb_to_int(argv[0]); - } - argc = 0; - } - } - else { - rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); - rb_warn_deprecated("Enumerator.new without a block", "Object#to_enum"); - recv = *argv++; - if (--argc) { - meth = *argv++; - --argc; - } - kw_splat = PASS_KW_SPLAT; - } + VALUE iter = rb_block_proc(); + VALUE recv = generator_init(generator_allocate(rb_cGenerator), iter); + VALUE arg0 = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil; + VALUE size = convert_to_feasible_size_value(arg0); - return enumerator_init(obj, recv, meth, argc, argv, 0, size, kw_splat); + return enumerator_init(obj, recv, sym_each, 0, 0, 0, size, false); } /* :nodoc: */ @@ -522,27 +517,25 @@ static VALUE lazy_to_enum_i(VALUE self, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat); VALUE -rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn) +rb_enumeratorize_with_size_kw(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat) { - /* Similar effect as calling obj.to_enum, i.e. dispatching to either - Kernel#to_enum vs Lazy#to_enum */ - if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) - return lazy_to_enum_i(obj, meth, argc, argv, size_fn, PASS_KW_SPLAT); - else - return enumerator_init(enumerator_allocate(rb_cEnumerator), - obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT); + VALUE base_class = rb_cEnumerator; + + if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) { + base_class = rb_cLazy; + } + else if (RTEST(rb_obj_is_kind_of(obj, rb_cEnumChain))) { + obj = enumerator_init(enumerator_allocate(rb_cEnumerator), obj, sym_each, 0, 0, 0, Qnil, false); + } + + return enumerator_init(enumerator_allocate(base_class), + obj, meth, argc, argv, size_fn, Qnil, kw_splat); } VALUE -rb_enumeratorize_with_size_kw(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat) +rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn) { - /* Similar effect as calling obj.to_enum, i.e. dispatching to either - Kernel#to_enum vs Lazy#to_enum */ - if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) - return lazy_to_enum_i(obj, meth, argc, argv, size_fn, kw_splat); - else - return enumerator_init(enumerator_allocate(rb_cEnumerator), - obj, meth, argc, argv, size_fn, Qnil, kw_splat); + return rb_enumeratorize_with_size_kw(obj, meth, argc, argv, size_fn, rb_keyword_given_p()); } static VALUE @@ -716,9 +709,9 @@ enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo)) * puts "#{string}: #{x}" * end * - * # => foo:0 - * # => foo:1 - * # => foo:2 + * # => foo: 0 + * # => foo: 1 + * # => foo: 2 */ static VALUE enumerator_with_object(VALUE obj, VALUE memo) @@ -798,6 +791,8 @@ get_next_values(VALUE obj, struct enumerator *e) * internal position forward. When the position reached at the end, * StopIteration is raised. * + * See class-level notes about external iterators. + * * This method can be used to distinguish yield and yield * nil. * @@ -831,10 +826,6 @@ get_next_values(VALUE obj, struct enumerator *e) * # yield nil [nil] nil * # yield [1, 2] [[1, 2]] [1, 2] * - * Note that +next_values+ does not affect other non-external enumeration - * methods unless underlying iteration method itself has side-effect, e.g. - * IO#each_line. - * */ static VALUE @@ -888,9 +879,7 @@ ary2sv(VALUE args, int dup) * p e.next #=> 3 * p e.next #raises StopIteration * - * Note that enumeration sequence by +next+ does not affect other non-external - * enumeration methods, unless the underlying iteration methods itself has - * side-effect, e.g. IO#each_line. + * See class-level notes about external iterators. * */ @@ -920,6 +909,8 @@ enumerator_peek_values(VALUE obj) * doesn't move the internal position forward. If the position is already at * the end, StopIteration is raised. * + * See class-level notes about external iterators. + * * === Example * * o = Object.new @@ -954,6 +945,8 @@ enumerator_peek_values_m(VALUE obj) * position forward. If the position is already at the end, StopIteration * is raised. * + * See class-level notes about external iterators. + * * === Example * * a = [1,2,3] @@ -1351,7 +1344,7 @@ yielder_yield_push(VALUE obj, VALUE arg) } /* - * Returns a Proc object that takes an argument and yields it. + * Returns a Proc object that takes arguments and yields them. * * This method is implemented so that a Yielder object can be directly * passed to another method as a block argument. @@ -1539,17 +1532,7 @@ lazyenum_size(VALUE self, VALUE args, VALUE eobj) return enum_size(self); } -static VALUE -lazy_size(VALUE self) -{ - return enum_size(rb_ivar_get(self, id_receiver)); -} - -static VALUE -lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy) -{ - return lazy_size(lazy); -} +#define lazy_receiver_size lazy_map_size static VALUE lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m)) @@ -1591,24 +1574,47 @@ lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m)) #define LAZY_MEMO_BREAK_P(memo) ((memo)->memo_flags & LAZY_MEMO_BREAK) #define LAZY_MEMO_PACKED_P(memo) ((memo)->memo_flags & LAZY_MEMO_PACKED) #define LAZY_MEMO_SET_BREAK(memo) ((memo)->memo_flags |= LAZY_MEMO_BREAK) +#define LAZY_MEMO_RESET_BREAK(memo) ((memo)->memo_flags &= ~LAZY_MEMO_BREAK) #define LAZY_MEMO_SET_VALUE(memo, value) MEMO_V2_SET(memo, value) #define LAZY_MEMO_SET_PACKED(memo) ((memo)->memo_flags |= LAZY_MEMO_PACKED) #define LAZY_MEMO_RESET_PACKED(memo) ((memo)->memo_flags &= ~LAZY_MEMO_PACKED) +static VALUE lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i); + static VALUE lazy_init_yielder(RB_BLOCK_CALL_FUNC_ARGLIST(_, m)) { VALUE yielder = RARRAY_AREF(m, 0); VALUE procs_array = RARRAY_AREF(m, 1); VALUE memos = rb_attr_get(yielder, id_memo); - long i = 0; struct MEMO *result; - int cont = 1; - result = MEMO_NEW(Qnil, rb_enum_values_pack(argc, argv), + result = MEMO_NEW(m, rb_enum_values_pack(argc, argv), argc > 1 ? LAZY_MEMO_PACKED : 0); + return lazy_yielder_result(result, yielder, procs_array, memos, 0); +} + +static VALUE +lazy_yielder_yield(struct MEMO *result, long memo_index, int argc, const VALUE *argv) +{ + VALUE m = result->v1; + VALUE yielder = RARRAY_AREF(m, 0); + VALUE procs_array = RARRAY_AREF(m, 1); + VALUE memos = rb_attr_get(yielder, id_memo); + LAZY_MEMO_SET_VALUE(result, rb_enum_values_pack(argc, argv)); + if (argc > 1) + LAZY_MEMO_SET_PACKED(result); + else + LAZY_MEMO_RESET_PACKED(result); + return lazy_yielder_result(result, yielder, procs_array, memos, memo_index); +} + +static VALUE +lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i) +{ + int cont = 1; - for (i = 0; i < RARRAY_LEN(procs_array); i++) { + for (; i < RARRAY_LEN(procs_array); i++) { VALUE proc = RARRAY_AREF(procs_array, i); struct proc_entry *entry = proc_entry_ptr(proc); if (!(*entry->fn->proc)(proc, result, memos, i)) { @@ -1703,13 +1709,13 @@ lazy_generator_init(VALUE enumerator, VALUE procs) * * # This will fetch all URLs before selecting * # necessary data - * URLS.map { |u| JSON.parse(open(u).read) } + * URLS.map { |u| JSON.parse(URI.open(u).read) } * .select { |data| data.key?('stats') } * .first(5) * * # This will fetch URLs one-by-one, only till * # there is enough data to satisfy the condition - * URLS.lazy.map { |u| JSON.parse(open(u).read) } + * URLS.lazy.map { |u| JSON.parse(URI.open(u).read) } * .select { |data| data.key?('stats') } * .first(5) * @@ -1803,6 +1809,7 @@ lazy_set_args(VALUE lazy, VALUE args) } } +#if 0 static VALUE lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn) { @@ -1811,6 +1818,7 @@ lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn) e->size_fn = size_fn; return lazy; } +#endif static VALUE lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo, @@ -1884,7 +1892,7 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo, static VALUE enumerable_lazy(VALUE obj) { - VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, PASS_KW_SPLAT); + VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, rb_keyword_given_p()); /* Qfalse indicates that the Enumerator::Lazy has no method name */ rb_ivar_set(result, id_method, Qfalse); return result; @@ -1932,7 +1940,7 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self) if (RTEST((super_meth = rb_hash_aref(lazy_use_super_method, meth)))) { meth = super_meth; } - lazy = lazy_to_enum_i(self, meth, argc, argv, 0, PASS_KW_SPLAT); + 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(); } @@ -2022,58 +2030,58 @@ lazy_map(VALUE obj) return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs); } +struct flat_map_i_arg { + struct MEMO *result; + long index; +}; + static VALUE -lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, yielder)) +lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, y)) { - VALUE arg = rb_enum_values_pack(argc, argv); + struct flat_map_i_arg *arg = (struct flat_map_i_arg *)y; - return rb_funcallv(yielder, idLTLT, 1, &arg); + return lazy_yielder_yield(arg->result, arg->index, argc, argv); } -static VALUE -lazy_flat_map_each(VALUE obj, VALUE yielder) +static struct MEMO * +lazy_flat_map_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index) { - rb_block_call(obj, id_each, 0, 0, lazy_flat_map_i, yielder); - return Qnil; -} + VALUE value = lazyenum_yield_values(proc_entry, result); + VALUE ary = 0; + const long proc_index = memo_index + 1; + int break_p = LAZY_MEMO_BREAK_P(result); -static VALUE -lazy_flat_map_to_ary(VALUE obj, VALUE yielder) -{ - VALUE ary = rb_check_array_type(obj); - if (NIL_P(ary)) { - rb_funcall(yielder, idLTLT, 1, obj); + if (RB_TYPE_P(value, T_ARRAY)) { + ary = value; } - else { - long i; - for (i = 0; i < RARRAY_LEN(ary); i++) { - rb_funcall(yielder, idLTLT, 1, RARRAY_AREF(ary, i)); - } + else if (rb_respond_to(value, id_force) && rb_respond_to(value, id_each)) { + struct flat_map_i_arg arg = {.result = result, .index = proc_index}; + LAZY_MEMO_RESET_BREAK(result); + rb_block_call(value, id_each, 0, 0, lazy_flat_map_i, (VALUE)&arg); + if (break_p) LAZY_MEMO_SET_BREAK(result); + return 0; } - return Qnil; -} -static VALUE -lazy_flat_map_proc(RB_BLOCK_CALL_FUNC_ARGLIST(val, m)) -{ - VALUE result = rb_yield_values2(argc - 1, &argv[1]); - if (RB_TYPE_P(result, T_ARRAY)) { - long i; - for (i = 0; i < RARRAY_LEN(result); i++) { - rb_funcall(argv[0], idLTLT, 1, RARRAY_AREF(result, i)); - } - } - else { - if (rb_respond_to(result, id_force) && rb_respond_to(result, id_each)) { - lazy_flat_map_each(result, argv[0]); - } - else { - lazy_flat_map_to_ary(result, argv[0]); - } + if (ary || !NIL_P(ary = rb_check_array_type(value))) { + long i; + LAZY_MEMO_RESET_BREAK(result); + for (i = 0; i + 1 < RARRAY_LEN(ary); i++) { + const VALUE argv = RARRAY_AREF(ary, i); + lazy_yielder_yield(result, proc_index, 1, &argv); + } + if (break_p) LAZY_MEMO_SET_BREAK(result); + if (i >= RARRAY_LEN(ary)) return 0; + value = RARRAY_AREF(ary, i); } - return Qnil; + LAZY_MEMO_SET_VALUE(result, value); + LAZY_MEMO_RESET_PACKED(result); + return result; } +static const lazyenum_funcs lazy_flat_map_funcs = { + lazy_flat_map_proc, 0, +}; + /* * call-seq: * lazy.collect_concat { |obj| block } -> a_lazy_enumerator @@ -2104,9 +2112,7 @@ lazy_flat_map(VALUE obj) rb_raise(rb_eArgError, "tried to call lazy flat_map without a block"); } - return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, - lazy_flat_map_proc, 0), - Qnil, 0); + return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs); } static struct MEMO * @@ -2308,58 +2314,59 @@ next_stopped(VALUE obj, VALUE _) return Qnil; } -static VALUE -lazy_zip_arrays_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, arrays)) +static struct MEMO * +lazy_zip_arrays_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index) { - VALUE yielder, ary, memo; - long i, count; - - yielder = argv[0]; - memo = rb_attr_get(yielder, id_memo); - count = NIL_P(memo) ? 0 : NUM2LONG(memo); + struct proc_entry *entry = proc_entry_ptr(proc_entry); + VALUE ary, arrays = entry->memo; + VALUE memo = rb_ary_entry(memos, memo_index); + long i, count = NIL_P(memo) ? 0 : NUM2LONG(memo); ary = rb_ary_new2(RARRAY_LEN(arrays) + 1); - rb_ary_push(ary, argv[1]); + rb_ary_push(ary, result->memo_value); for (i = 0; i < RARRAY_LEN(arrays); i++) { rb_ary_push(ary, rb_ary_entry(RARRAY_AREF(arrays, i), count)); } - rb_funcall(yielder, idLTLT, 1, ary); - rb_ivar_set(yielder, id_memo, LONG2NUM(++count)); - return Qnil; + LAZY_MEMO_SET_VALUE(result, ary); + LAZY_MEMO_SET_PACKED(result); + rb_ary_store(memos, memo_index, LONG2NUM(++count)); + return result; } -static VALUE -lazy_zip_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, zip_args)) +static struct MEMO * +lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index) { - VALUE yielder, ary, arg, v; + struct proc_entry *entry = proc_entry_ptr(proc_entry); + VALUE arg = rb_ary_entry(memos, memo_index); + VALUE zip_args = entry->memo; + VALUE ary, v; long i; - yielder = argv[0]; - arg = rb_attr_get(yielder, id_memo); if (NIL_P(arg)) { arg = rb_ary_new2(RARRAY_LEN(zip_args)); for (i = 0; i < RARRAY_LEN(zip_args); i++) { rb_ary_push(arg, rb_funcall(RARRAY_AREF(zip_args, i), id_to_enum, 0)); } - rb_ivar_set(yielder, id_memo, arg); + rb_ary_store(memos, memo_index, arg); } ary = rb_ary_new2(RARRAY_LEN(arg) + 1); - v = Qnil; - if (--argc > 0) { - ++argv; - v = argc > 1 ? rb_ary_new_from_values(argc, argv) : *argv; - } - rb_ary_push(ary, v); + rb_ary_push(ary, result->memo_value); for (i = 0; i < RARRAY_LEN(arg); i++) { v = rb_rescue2(call_next, RARRAY_AREF(arg, i), next_stopped, 0, rb_eStopIteration, (VALUE)0); rb_ary_push(ary, v); } - rb_funcall(yielder, idLTLT, 1, ary); - return Qnil; + LAZY_MEMO_SET_VALUE(result, ary); + LAZY_MEMO_SET_PACKED(result); + return result; } +static const lazyenum_funcs lazy_zip_funcs[] = { + {lazy_zip_func, lazy_receiver_size,}, + {lazy_zip_arrays_func, lazy_receiver_size,}, +}; + /* * call-seq: * lazy.zip(arg, ...) -> lazy_enumerator @@ -2373,7 +2380,7 @@ lazy_zip(int argc, VALUE *argv, VALUE obj) { VALUE ary, v; long i; - rb_block_call_func *func = lazy_zip_arrays_func; + const lazyenum_funcs *funcs = &lazy_zip_funcs[1]; if (rb_block_given_p()) { return rb_call_super(argc, argv); @@ -2390,15 +2397,13 @@ lazy_zip(int argc, VALUE *argv, VALUE obj) } } ary = rb_ary_new4(argc, argv); - func = lazy_zip_func; + funcs = &lazy_zip_funcs[0]; break; } rb_ary_push(ary, v); } - return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, - func, ary), - ary, lazy_receiver_size); + return lazy_add_method(obj, 0, 0, ary, ary, funcs); } static struct MEMO * @@ -2646,6 +2651,30 @@ lazy_uniq(VALUE obj) return lazy_add_method(obj, 0, 0, Qnil, Qnil, funcs); } +static struct MEMO * +lazy_compact_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index) +{ + if (NIL_P(result->memo_value)) return 0; + return result; +} + +static const lazyenum_funcs lazy_compact_funcs = { + lazy_compact_proc, 0, +}; + +/* + * call-seq: + * lazy.compact -> lazy_enumerator + * + * Like Enumerable#compact, but chains operation to be lazy-evaluated. + */ + +static VALUE +lazy_compact(VALUE obj) +{ + return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_compact_funcs); +} + static struct MEMO * lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long memo_index) { @@ -2662,7 +2691,8 @@ lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long me if (entry->proc) { rb_proc_call_with_block(entry->proc, 2, argv, Qnil); LAZY_MEMO_RESET_PACKED(result); - } else { + } + else { LAZY_MEMO_SET_VALUE(result, rb_ary_new_from_values(2, argv)); LAZY_MEMO_SET_PACKED(result); } @@ -2670,8 +2700,14 @@ lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long me return result; } +static VALUE +lazy_with_index_size(VALUE proc, VALUE receiver) +{ + return receiver; +} + static const lazyenum_funcs lazy_with_index_funcs = { - lazy_with_index_proc, 0, + lazy_with_index_proc, lazy_with_index_size, }; /* @@ -2679,7 +2715,8 @@ static const lazyenum_funcs lazy_with_index_funcs = { * lazy.with_index(offset = 0) {|(*args), idx| block } * lazy.with_index(offset = 0) * - * If a block is given, iterates the given block for each element + * If a block is given, returns a lazy enumerator that will + * iterate over the given block for each element * with an index, which starts from +offset+, and returns a * lazy enumerator that yields the same values (without the index). * @@ -2917,6 +2954,8 @@ producer_each_stop(VALUE dummy, VALUE exc) return rb_attr_get(exc, id_result); } +NORETURN(static VALUE producer_each_i(VALUE obj)); + static VALUE producer_each_i(VALUE obj) { @@ -2929,7 +2968,8 @@ producer_each_i(VALUE obj) if (init == Qundef) { curr = Qnil; - } else { + } + else { rb_yield(init); curr = init; } @@ -2939,7 +2979,7 @@ producer_each_i(VALUE obj) rb_yield(curr); } - return Qnil; + UNREACHABLE_RETURN(Qnil); } /* :nodoc: */ @@ -2978,7 +3018,7 @@ producer_size(VALUE obj, VALUE args, VALUE eobj) * enclosing_section = ancestors.find { |n| n.type == :section } * * Using ::produce together with Enumerable methods like Enumerable#detect, - * Enumerable#slice, Enumerable#take_while can provide Enumerator-based alternatives + * Enumerable#slice_after, Enumerable#take_while can provide Enumerator-based alternatives * for +while+ and +until+ cycles: * * # Find next Tuesday @@ -3104,6 +3144,21 @@ enum_chain_initialize(VALUE obj, VALUE enums) return obj; } +static VALUE +new_enum_chain(VALUE enums) +{ + long i; + VALUE obj = enum_chain_initialize(enum_chain_allocate(rb_cEnumChain), enums); + + for (i = 0; i < RARRAY_LEN(enums); i++) { + if (RTEST(rb_obj_is_kind_of(RARRAY_AREF(enums, i), rb_cLazy))) { + return enumerable_lazy(obj); + } + } + + return obj; +} + /* :nodoc: */ static VALUE enum_chain_init_copy(VALUE obj, VALUE orig) @@ -3132,7 +3187,7 @@ enum_chain_total_size(VALUE enums) for (i = 0; i < RARRAY_LEN(enums); i++) { VALUE size = enum_size(RARRAY_AREF(enums, i)); - if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) { + if (NIL_P(size) || (RB_FLOAT_TYPE_P(size) && isinf(NUM2DBL(size)))) { return size; } if (!RB_INTEGER_TYPE_P(size)) { @@ -3273,8 +3328,7 @@ enum_chain(int argc, VALUE *argv, VALUE obj) { VALUE enums = rb_ary_new_from_values(1, &obj); rb_ary_cat(enums, argv, argc); - - return enum_chain_initialize(enum_chain_allocate(rb_cEnumChain), enums); + return new_enum_chain(enums); } /* @@ -3290,9 +3344,7 @@ enum_chain(int argc, VALUE *argv, VALUE obj) static VALUE enumerator_plus(VALUE obj, VALUE eobj) { - VALUE enums = rb_ary_new_from_args(2, obj, eobj); - - return enum_chain_initialize(enum_chain_allocate(rb_cEnumChain), enums); + return new_enum_chain(rb_ary_new_from_args(2, obj, eobj)); } /* @@ -3302,6 +3354,9 @@ enumerator_plus(VALUE obj, VALUE eobj) * that is a representation of sequences of numbers with common difference. * Instances of this class can be generated by the Range#step and Numeric#step * methods. + * + * The class can be used for slicing Array (see Array#slice) or custom + * collections. */ VALUE @@ -3310,11 +3365,11 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, VALUE beg, VALUE end, VALUE step, int excl) { VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq), - obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT); + 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, excl ? Qtrue : Qfalse); + rb_ivar_set(aseq, id_exclude_end, RBOOL(excl)); return aseq; } @@ -3380,17 +3435,53 @@ rb_arithmetic_sequence_extract(VALUE obj, rb_arithmetic_sequence_components_t *c component->exclude_end = arith_seq_exclude_end_p(obj); return 1; } - else if (rb_obj_is_kind_of(obj, rb_cRange)) { - component->begin = RANGE_BEG(obj); - component->end = RANGE_END(obj); + else if (rb_range_values(obj, &component->begin, &component->end, &component->exclude_end)) { component->step = INT2FIX(1); - component->exclude_end = RTEST(RANGE_EXCL(obj)); return 1; } return 0; } +VALUE +rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *stepp, long len, int err) +{ + RBIMPL_NONNULL_ARG(begp); + RBIMPL_NONNULL_ARG(lenp); + RBIMPL_NONNULL_ARG(stepp); + + rb_arithmetic_sequence_components_t aseq; + if (!rb_arithmetic_sequence_extract(obj, &aseq)) { + return Qfalse; + } + + long step = NIL_P(aseq.step) ? 1 : NUM2LONG(aseq.step); + *stepp = step; + + if (step < 0) { + VALUE tmp = aseq.begin; + aseq.begin = aseq.end; + aseq.end = tmp; + } + + if (err == 0 && (step < -1 || step > 1)) { + if (rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, 1) == Qtrue) { + if (*begp > len) + goto out_of_range; + if (*lenp > len) + goto out_of_range; + return Qtrue; + } + } + else { + return rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, err); + } + + out_of_range: + rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", obj); + return Qnil; +} + /* * call-seq: * aseq.first -> num or nil @@ -3535,6 +3626,88 @@ arith_seq_first(int argc, VALUE *argv, VALUE self) return rb_call_super(argc, argv); } +static inline VALUE +num_plus(VALUE a, VALUE b) +{ + if (RB_INTEGER_TYPE_P(a)) { + return rb_int_plus(a, b); + } + else if (RB_FLOAT_TYPE_P(a)) { + return rb_float_plus(a, b); + } + else if (RB_TYPE_P(a, T_RATIONAL)) { + return rb_rational_plus(a, b); + } + else { + return rb_funcallv(a, '+', 1, &b); + } +} + +static inline VALUE +num_minus(VALUE a, VALUE b) +{ + if (RB_INTEGER_TYPE_P(a)) { + return rb_int_minus(a, b); + } + else if (RB_FLOAT_TYPE_P(a)) { + return rb_float_minus(a, b); + } + else if (RB_TYPE_P(a, T_RATIONAL)) { + return rb_rational_minus(a, b); + } + else { + return rb_funcallv(a, '-', 1, &b); + } +} + +static inline VALUE +num_mul(VALUE a, VALUE b) +{ + if (RB_INTEGER_TYPE_P(a)) { + return rb_int_mul(a, b); + } + else if (RB_FLOAT_TYPE_P(a)) { + return rb_float_mul(a, b); + } + else if (RB_TYPE_P(a, T_RATIONAL)) { + return rb_rational_mul(a, b); + } + else { + return rb_funcallv(a, '*', 1, &b); + } +} + +static inline VALUE +num_idiv(VALUE a, VALUE b) +{ + VALUE q; + if (RB_INTEGER_TYPE_P(a)) { + q = rb_int_idiv(a, b); + } + else if (RB_FLOAT_TYPE_P(a)) { + q = rb_float_div(a, b); + } + else if (RB_TYPE_P(a, T_RATIONAL)) { + q = rb_rational_div(a, b); + } + else { + q = rb_funcallv(a, idDiv, 1, &b); + } + + if (RB_INTEGER_TYPE_P(q)) { + return q; + } + else if (RB_FLOAT_TYPE_P(q)) { + return rb_float_floor(q, 0); + } + else if (RB_TYPE_P(q, T_RATIONAL)) { + return rb_rational_floor(q, 0); + } + else { + return rb_funcall(q, rb_intern("floor"), 0); + } +} + /* * call-seq: * aseq.last -> num or nil @@ -3559,7 +3732,7 @@ arith_seq_last(int argc, VALUE *argv, VALUE self) b = arith_seq_begin(self); s = arith_seq_step(self); - len_1 = rb_int_idiv(rb_int_minus(e, b), s); + len_1 = num_idiv(num_minus(e, b), s); if (rb_num_negative_int_p(len_1)) { if (argc == 0) { return Qnil; @@ -3567,9 +3740,9 @@ arith_seq_last(int argc, VALUE *argv, VALUE self) return rb_ary_new_capa(0); } - last = rb_int_plus(b, rb_int_mul(s, len_1)); + last = num_plus(b, num_mul(s, len_1)); if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) { - last = rb_int_minus(last, s); + last = num_minus(last, s); } if (argc == 0) { @@ -3778,57 +3951,28 @@ arith_seq_each(VALUE self) return self; } - len_1 = rb_int_idiv(rb_int_minus(e, c), s); - last = rb_int_plus(c, rb_int_mul(s, len_1)); + len_1 = num_idiv(num_minus(e, c), s); + last = num_plus(c, num_mul(s, len_1)); if (x && rb_equal(last, e)) { - last = rb_int_minus(last, s); + last = num_minus(last, s); } if (rb_num_negative_int_p(s)) { while (NUM_GE(c, last)) { rb_yield(c); - c = rb_int_plus(c, s); + c = num_plus(c, s); } } else { while (NUM_GE(last, c)) { rb_yield(c); - c = rb_int_plus(c, s); + c = num_plus(c, s); } } return self; } -static double -arith_seq_float_step_size(double beg, double end, double step, int excl) -{ - double const epsilon = DBL_EPSILON; - double n, err; - - if (step == 0) { - return HUGE_VAL; - } - n = (end - beg) / step; - err = (fabs(beg) + fabs(end) + fabs(end - beg)) / fabs(step) * epsilon; - if (isinf(step)) { - return step > 0 ? beg <= end : beg >= end; - } - if (err > 0.5) err = 0.5; - if (excl) { - if (n <= 0) return 0; - if (n < 1) - n = 0; - else - n = floor(n - err); - } - else { - if (n < 0) return 0; - n = floor(n + err); - } - return n + 1; -} - /* * call-seq: * aseq.size -> num or nil @@ -3862,9 +4006,9 @@ arith_seq_size(VALUE self) ee = NUM2DBL(e); } - n = arith_seq_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x); + n = ruby_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x); if (isinf(n)) return DBL2NUM(n); - if (POSFIXABLE(n)) return LONG2FIX(n); + if (POSFIXABLE(n)) return LONG2FIX((long)n); return rb_dbl2big(n); } @@ -3896,10 +4040,11 @@ arith_seq_size(VALUE self) return len; } +#define sym(name) ID2SYM(rb_intern_const(name)) void InitVM_Enumerator(void) { - ID id_private = rb_intern("private"); + ID id_private = rb_intern_const("private"); rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1); rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1); @@ -3949,23 +4094,23 @@ InitVM_Enumerator(void) rb_define_alias(rb_cLazy, "_enumerable_uniq", "uniq"); rb_define_private_method(rb_cLazy, "_enumerable_with_index", enumerator_with_index, -1); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_map"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_collect"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_flat_map"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_collect_concat"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_select"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_find_all"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_filter"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_filter_map"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_reject"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_grep"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_grep_v"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_zip"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_take"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_take_while"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_drop"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_drop_while"))); - rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_uniq"))); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_map")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_flat_map")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect_concat")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_select")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_find_all")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter_map")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_reject")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep_v")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_zip")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take_while")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop_while")); + rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_uniq")); rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1); rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1); @@ -3994,27 +4139,28 @@ InitVM_Enumerator(void) rb_define_method(rb_cLazy, "slice_when", lazy_super, -1); rb_define_method(rb_cLazy, "chunk_while", lazy_super, -1); rb_define_method(rb_cLazy, "uniq", lazy_uniq, 0); + rb_define_method(rb_cLazy, "compact", lazy_compact, 0); rb_define_method(rb_cLazy, "with_index", lazy_with_index, -1); lazy_use_super_method = rb_hash_new_with_size(18); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("map")), ID2SYM(rb_intern("_enumerable_map"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("collect")), ID2SYM(rb_intern("_enumerable_collect"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("flat_map")), ID2SYM(rb_intern("_enumerable_flat_map"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("collect_concat")), ID2SYM(rb_intern("_enumerable_collect_concat"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("select")), ID2SYM(rb_intern("_enumerable_select"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("find_all")), ID2SYM(rb_intern("_enumerable_find_all"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("filter")), ID2SYM(rb_intern("_enumerable_filter"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("filter_map")), ID2SYM(rb_intern("_enumerable_filter_map"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("reject")), ID2SYM(rb_intern("_enumerable_reject"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("grep")), ID2SYM(rb_intern("_enumerable_grep"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("grep_v")), ID2SYM(rb_intern("_enumerable_grep_v"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("zip")), ID2SYM(rb_intern("_enumerable_zip"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("take")), ID2SYM(rb_intern("_enumerable_take"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("take_while")), ID2SYM(rb_intern("_enumerable_take_while"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("drop")), ID2SYM(rb_intern("_enumerable_drop"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("drop_while")), ID2SYM(rb_intern("_enumerable_drop_while"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("uniq")), ID2SYM(rb_intern("_enumerable_uniq"))); - rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("with_index")), ID2SYM(rb_intern("_enumerable_with_index"))); + rb_hash_aset(lazy_use_super_method, sym("map"), sym("_enumerable_map")); + rb_hash_aset(lazy_use_super_method, sym("collect"), sym("_enumerable_collect")); + rb_hash_aset(lazy_use_super_method, sym("flat_map"), sym("_enumerable_flat_map")); + rb_hash_aset(lazy_use_super_method, sym("collect_concat"), sym("_enumerable_collect_concat")); + rb_hash_aset(lazy_use_super_method, sym("select"), sym("_enumerable_select")); + rb_hash_aset(lazy_use_super_method, sym("find_all"), sym("_enumerable_find_all")); + rb_hash_aset(lazy_use_super_method, sym("filter"), sym("_enumerable_filter")); + rb_hash_aset(lazy_use_super_method, sym("filter_map"), sym("_enumerable_filter_map")); + rb_hash_aset(lazy_use_super_method, sym("reject"), sym("_enumerable_reject")); + rb_hash_aset(lazy_use_super_method, sym("grep"), sym("_enumerable_grep")); + rb_hash_aset(lazy_use_super_method, sym("grep_v"), sym("_enumerable_grep_v")); + rb_hash_aset(lazy_use_super_method, sym("zip"), sym("_enumerable_zip")); + rb_hash_aset(lazy_use_super_method, sym("take"), sym("_enumerable_take")); + rb_hash_aset(lazy_use_super_method, sym("take_while"), sym("_enumerable_take_while")); + rb_hash_aset(lazy_use_super_method, sym("drop"), sym("_enumerable_drop")); + rb_hash_aset(lazy_use_super_method, sym("drop_while"), sym("_enumerable_drop_while")); + 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); @@ -4062,6 +4208,11 @@ InitVM_Enumerator(void) rb_define_method(rb_cEnumChain, "size", enum_chain_size, 0); rb_define_method(rb_cEnumChain, "rewind", enum_chain_rewind, 0); rb_define_method(rb_cEnumChain, "inspect", enum_chain_inspect, 0); + rb_undef_method(rb_cEnumChain, "feed"); + rb_undef_method(rb_cEnumChain, "next"); + rb_undef_method(rb_cEnumChain, "next_values"); + rb_undef_method(rb_cEnumChain, "peek"); + rb_undef_method(rb_cEnumChain, "peek_values"); /* ArithmeticSequence */ rb_cArithSeq = rb_define_class_under(rb_cEnumerator, "ArithmeticSequence", rb_cEnumerator); @@ -4083,28 +4234,28 @@ InitVM_Enumerator(void) rb_provide("enumerator.so"); /* for backward compatibility */ } +#undef sym -#undef rb_intern void Init_Enumerator(void) { - id_rewind = rb_intern("rewind"); - id_new = rb_intern("new"); - id_next = rb_intern("next"); - id_result = rb_intern("result"); - id_receiver = rb_intern("receiver"); - id_arguments = rb_intern("arguments"); - id_memo = rb_intern("memo"); - id_method = rb_intern("method"); - id_force = rb_intern("force"); - id_to_enum = rb_intern("to_enum"); - id_begin = rb_intern("begin"); - id_end = rb_intern("end"); - id_step = rb_intern("step"); - id_exclude_end = rb_intern("exclude_end"); + 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"); + id_arguments = rb_intern_const("arguments"); + id_memo = rb_intern_const("memo"); + id_method = rb_intern_const("method"); + id_force = rb_intern_const("force"); + id_to_enum = rb_intern_const("to_enum"); + 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("cycle")); - sym_yield = ID2SYM(rb_intern("yield")); + sym_cycle = ID2SYM(rb_intern_const("cycle")); + sym_yield = ID2SYM(rb_intern_const("yield")); InitVM(Enumerator); } diff --git a/ruby/error.c b/ruby/error.c index 9557d8552..a870d0200 100644 --- a/ruby/error.c +++ b/ruby/error.c @@ -9,29 +9,43 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/st.h" -#include "internal.h" -#include "ruby_assert.h" -#include "vm_core.h" -#include "builtin.h" +#include "ruby/internal/config.h" -#include +#include #include +#include + #ifdef HAVE_STDLIB_H -#include +# include #endif -#include + #ifdef HAVE_UNISTD_H -#include +# include #endif #if defined __APPLE__ # include #endif +#include "internal.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/symbol.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "ruby/encoding.h" +#include "ruby/st.h" +#include "ruby_assert.h" +#include "vm_core.h" + +#include "builtin.h" + /*! - * \defgroup exception Exception handlings + * \addtogroup exception * \{ */ @@ -51,6 +65,7 @@ VALUE rb_iseqw_local_variables(VALUE iseqval); VALUE rb_iseqw_new(const rb_iseq_t *); int rb_str_end_with_asciichar(VALUE str, int c); +long rb_backtrace_length_limit = -1; VALUE rb_eEAGAIN; VALUE rb_eEWOULDBLOCK; VALUE rb_eEINPROGRESS; @@ -58,6 +73,13 @@ static VALUE rb_mWarning; static VALUE rb_cWarningBuffer; static ID id_warn; +static ID id_category; +static ID id_deprecated; +static ID id_experimental; +static VALUE sym_category; +static struct { + st_table *id2enum, *enum2id; +} warning_categories; extern const char ruby_description[]; @@ -86,6 +108,7 @@ err_position_0(char *buf, long len, const char *file, int line) } } +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 0) static VALUE err_vcatf(VALUE str, const char *pre, const char *file, int line, const char *fmt, va_list args) @@ -128,7 +151,9 @@ rb_syntax_error_append(VALUE exc, VALUE file, int line, int column, return exc; } -static unsigned int warning_disabled_categories; +static unsigned int warning_disabled_categories = ( + 1U << RB_WARN_CATEGORY_DEPRECATED | + 0); static unsigned int rb_warning_category_mask(VALUE category) @@ -139,18 +164,24 @@ rb_warning_category_mask(VALUE category) rb_warning_category_t rb_warning_category_from_name(VALUE category) { - rb_warning_category_t cat = RB_WARN_CATEGORY_NONE; + st_data_t cat_value; + ID cat_id; Check_Type(category, T_SYMBOL); - if (category == ID2SYM(rb_intern("deprecated"))) { - cat = RB_WARN_CATEGORY_DEPRECATED; - } - else if (category == ID2SYM(rb_intern("experimental"))) { - cat = RB_WARN_CATEGORY_EXPERIMENTAL; - } - else { + if (!(cat_id = rb_check_id(&category)) || + !st_lookup(warning_categories.id2enum, cat_id, &cat_value)) { rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category); } - return cat; + return (rb_warning_category_t)cat_value; +} + +static VALUE +rb_warning_category_to_name(rb_warning_category_t category) +{ + st_data_t id; + if (!st_lookup(warning_categories.enum2id, category, &id)) { + rb_raise(rb_eArgError, "invalid category: %d", (int)category); + } + return id ? ID2SYM(id) : Qnil; } void @@ -167,7 +198,7 @@ rb_warning_category_enabled_p(rb_warning_category_t category) } /* - * call-seq + * call-seq: * Warning[category] -> true or false * * Returns the flag to show the warning messages for +category+. @@ -187,13 +218,11 @@ static VALUE rb_warning_s_aref(VALUE mod, VALUE category) { rb_warning_category_t cat = rb_warning_category_from_name(category); - if (rb_warning_category_enabled_p(cat)) - return Qtrue; - return Qfalse; + return RBOOL(rb_warning_category_enabled_p(cat)); } /* - * call-seq + * call-seq: * Warning[category] = flag -> flag * * Sets the warning flags for +category+. @@ -215,17 +244,31 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag) /* * call-seq: - * warn(msg) -> nil + * warn(msg, category: nil) -> nil * * Writes warning message +msg+ to $stderr. This method is called by - * Ruby for all emitted warnings. + * Ruby for all emitted warnings. A +category+ may be included with + * the warning. + * + * See the documentation of the Warning module for how to customize this. */ static VALUE -rb_warning_s_warn(VALUE mod, VALUE str) +rb_warning_s_warn(int argc, VALUE *argv, VALUE mod) { + VALUE str; + VALUE opt; + VALUE category = Qnil; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(opt)) rb_get_kwargs(opt, &id_category, 0, 1, &category); + Check_Type(str, T_STRING); rb_must_asciicompat(str); + if (!NIL_P(category)) { + rb_warning_category_t cat = rb_warning_category_from_name(category); + if (!rb_warning_category_enabled_p(cat)) return Qnil; + } rb_write_error_str(str); return Qnil; } @@ -238,11 +281,30 @@ rb_warning_s_warn(VALUE mod, VALUE str) * Warning.warn is called for all warnings issued by Ruby. * By default, warnings are printed to $stderr. * - * By overriding Warning.warn, you can change how warnings are - * handled by Ruby, either filtering some warnings, and/or outputting - * warnings somewhere other than $stderr. When Warning.warn is - * overridden, super can be called to get the default behavior of - * printing the warning to $stderr. + * 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. + * + * 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. + * + * Example: + * module MyWarningFilter + * def warn(message, category: nil, **kwargs) + * if /some warning I want to ignore/.match?(message) + * # ignore + * else + * super + * end + * end + * end + * Warning.extend MyWarningFilter + * + * 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. */ static VALUE @@ -251,12 +313,40 @@ rb_warning_warn(VALUE mod, VALUE str) return rb_funcallv(mod, id_warn, 1, &str); } + +static int +rb_warning_warn_arity(void) +{ + const rb_method_entry_t *me = rb_method_entry(rb_singleton_class(rb_mWarning), id_warn); + return me ? rb_method_entry_arity(me) : 1; +} + +static VALUE +rb_warn_category(VALUE str, VALUE category) +{ + if (RUBY_DEBUG && !NIL_P(category)) { + rb_warning_category_from_name(category); + } + + if (rb_warning_warn_arity() == 1) { + return rb_warning_warn(rb_mWarning, str); + } + else { + VALUE args[2]; + args[0] = str; + args[1] = rb_hash_new(); + rb_hash_aset(args[1], sym_category, category); + return rb_funcallv_kw(rb_mWarning, id_warn, 2, args, RB_PASS_KEYWORDS); + } +} + static void rb_write_warning_str(VALUE str) { rb_warning_warn(rb_mWarning, str); } +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 0) static VALUE warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args) { @@ -295,6 +385,21 @@ rb_compile_warning(const char *file, int line, const char *fmt, ...) rb_write_warning_str(str); } +void +rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...) +{ + VALUE str; + va_list args; + + if (NIL_P(ruby_verbose)) return; + + va_start(args, fmt); + str = warn_vsprintf(NULL, file, line, fmt, args); + va_end(args); + rb_warn_category(str, rb_warning_category_to_name(category)); +} + +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) static VALUE warning_string(rb_encoding *enc, const char *fmt, va_list args) { @@ -319,6 +424,16 @@ rb_warn(const char *fmt, ...) } } +void +rb_category_warn(rb_warning_category_t category, const char *fmt, ...) +{ + if (!NIL_P(ruby_verbose)) { + with_warning_string(mesg, 0, fmt) { + rb_warn_category(mesg, rb_warning_category_to_name(category)); + } + } +} + void rb_enc_warn(rb_encoding *enc, const char *fmt, ...) { @@ -340,6 +455,17 @@ rb_warning(const char *fmt, ...) } } +/* rb_category_warning() reports only in verbose mode */ +void +rb_category_warning(rb_warning_category_t category, const char *fmt, ...) +{ + if (RTEST(ruby_verbose)) { + with_warning_string(mesg, 0, fmt) { + rb_warn_category(mesg, rb_warning_category_to_name(category)); + } + } +} + VALUE rb_warning_string(const char *fmt, ...) { @@ -360,20 +486,51 @@ rb_enc_warning(rb_encoding *enc, const char *fmt, ...) } #endif +static bool +deprecation_warning_enabled(void) +{ + if (NIL_P(ruby_verbose)) return false; + if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return false; + return true; +} + +static void +warn_deprecated(VALUE mesg, const char *removal, const char *suggest) +{ + rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1); + rb_str_cat_cstr(mesg, " is deprecated"); + if (removal) { + rb_str_catf(mesg, " and will be removed in Ruby %s", removal); + } + if (suggest) rb_str_catf(mesg, "; use %s instead", suggest); + rb_str_cat_cstr(mesg, "\n"); + rb_warn_category(mesg, ID2SYM(id_deprecated)); +} + void rb_warn_deprecated(const char *fmt, const char *suggest, ...) { - if (NIL_P(ruby_verbose)) return; - if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return; + if (!deprecation_warning_enabled()) return; + va_list args; va_start(args, suggest); VALUE mesg = warning_string(0, fmt, args); va_end(args); - rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1); - rb_str_cat_cstr(mesg, " is deprecated"); - if (suggest) rb_str_catf(mesg, "; use %s instead", suggest); - rb_str_cat_cstr(mesg, "\n"); - rb_write_warning_str(mesg); + + warn_deprecated(mesg, NULL, suggest); +} + +void +rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...) +{ + if (!deprecation_warning_enabled()) return; + + va_list args; + va_start(args, suggest); + VALUE mesg = warning_string(0, fmt, args); + va_end(args); + + warn_deprecated(mesg, removal, suggest); } static inline int @@ -393,9 +550,10 @@ warning_write(int argc, VALUE *argv, VALUE buf) return buf; } -VALUE rb_ec_backtrace_location_ary(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); + static VALUE -rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel) +rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category) { VALUE location = Qnil; int argc = RARRAY_LENINT(msgs); @@ -408,7 +566,7 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel) if (lev < 0) { rb_raise(rb_eArgError, "negative level (%ld)", lev); } - location = rb_ec_backtrace_location_ary(ec, lev + 1, 1); + location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE); if (!NIL_P(location)) { location = rb_ary_entry(location, 0); } @@ -431,12 +589,18 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel) rb_io_puts(argc, argv, str); RBASIC_SET_CLASS(str, rb_cString); } + + if (!NIL_P(category)) { + category = rb_to_symbol_type(category); + rb_warning_category_from_name(category); + } + if (exc == rb_mWarning) { rb_must_asciicompat(str); rb_write_error_str(str); } else { - rb_write_warning_str(str); + rb_warn_category(str, category); } } return Qnil; @@ -516,7 +680,7 @@ preface_dump(FILE *out) static const char msg[] = "" "-- Crash Report log information " "--------------------------------------------\n" - " See Crash Report log file under the one of following:\n" + " See Crash Report log file in one of the following locations:\n" # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 " * ~/Library/Logs/CrashReporter\n" " * /Library/Logs/CrashReporter\n" @@ -556,6 +720,7 @@ postscript_dump(FILE *out) bug_important_message(out, msg, msglen); } +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) static void bug_report_begin_valist(FILE *out, const char *fmt, va_list args) { @@ -567,17 +732,6 @@ bug_report_begin_valist(FILE *out, const char *fmt, va_list args) snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description); fputs(buf, out); preface_dump(out); - -#if RUBY_DEVEL - const char *cmd = getenv("RUBY_ON_BUG"); - if (cmd) { - snprintf(buf, sizeof(buf), "%s %"PRI_PIDT_PREFIX"d", cmd, getpid()); - int r = system(buf); - if (r == -1) { - snprintf(buf, sizeof(buf), "Launching RUBY_ON_BUG command failed."); - } - } -#endif } #define bug_report_begin(out, fmt) do { \ @@ -630,18 +784,27 @@ die(void) abort(); } +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0) void -rb_bug(const char *fmt, ...) +rb_bug_without_die(const char *fmt, va_list args) { const char *file = NULL; int line = 0; if (GET_EC()) { - file = rb_source_location_cstr(&line); + file = rb_source_location_cstr(&line); } - report_bug(file, line, fmt, NULL); + report_bug_valist(file, line, fmt, NULL, args); +} +void +rb_bug(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + rb_bug_without_die(fmt, args); + va_end(args); die(); } @@ -736,7 +899,7 @@ static const char builtin_types[][10] = { "Array", "Hash", "Struct", - "Bignum", + "Integer", "File", "Data", /* internal use: wrapped C pointers */ "MatchData", /* data of $~ */ @@ -747,14 +910,14 @@ static const char builtin_types[][10] = { "true", "false", "Symbol", /* :symbol */ - "Fixnum", + "Integer", "undef", /* internal use: #undef; should not happen */ "", /* 0x17 */ "", /* 0x18 */ "", /* 0x19 */ - "Memo", /* internal use: general memo */ - "Node", /* internal use: syntax tree node */ - "iClass", /* internal use: mixed-in module holder */ + "", /* internal use: general memo */ + "", /* internal use: syntax tree node */ + "", /* internal use: mixed-in module holder */ }; const char * @@ -767,6 +930,17 @@ rb_builtin_type_name(int t) return 0; } +static VALUE +displaying_class_of(VALUE x) +{ + switch (x) { + case Qfalse: return rb_fstring_cstr("false"); + case Qnil: return rb_fstring_cstr("nil"); + case Qtrue: return rb_fstring_cstr("true"); + default: return rb_obj_class(x); + } +} + static const char * builtin_class_name(VALUE x) { @@ -804,7 +978,7 @@ rb_builtin_class_name(VALUE x) return etype; } -NORETURN(static void unexpected_type(VALUE, int, int)); +COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int)); #define UNDEF_LEAKED "undef leaked to the Ruby space" static void @@ -814,13 +988,8 @@ unexpected_type(VALUE x, int xt, int t) VALUE mesg, exc = rb_eFatal; if (tname) { - const char *cname = builtin_class_name(x); - if (cname) - mesg = rb_sprintf("wrong argument type %s (expected %s)", - cname, tname); - else - mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)", - rb_obj_class(x), tname); + mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)", + displaying_class_of(x), tname); exc = rb_eTypeError; } else if (xt > T_MASK && xt <= 0x3f) { @@ -838,12 +1007,20 @@ rb_check_type(VALUE x, int t) { int xt; - if (x == Qundef) { + if (RB_UNLIKELY(x == Qundef)) { rb_bug(UNDEF_LEAKED); } xt = TYPE(x); - if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) { + if (xt != t || (xt == T_DATA && rbimpl_rtypeddata_p(x))) { + /* + * Typed data is not simple `T_DATA`, but in a sense an + * extension of `struct RVALUE`, which are incompatible with + * each other except when inherited. + * + * So it is not enough to just check `T_DATA`, it must be + * identified by its `type` using `Check_TypedStruct` instead. + */ unexpected_type(x, xt, t); } } @@ -851,7 +1028,7 @@ rb_check_type(VALUE x, int t) void rb_unexpected_type(VALUE x, int t) { - if (x == Qundef) { + if (RB_UNLIKELY(x == Qundef)) { rb_bug(UNDEF_LEAKED); } @@ -888,26 +1065,26 @@ rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type) void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type) { - const char *etype; + VALUE actual; if (!RB_TYPE_P(obj, T_DATA)) { - wrong_type: - etype = builtin_class_name(obj); - if (!etype) - rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)", - rb_obj_class(obj), data_type->wrap_struct_name); - wrong_datatype: - rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", - etype, data_type->wrap_struct_name); - } - if (!RTYPEDDATA_P(obj)) { - goto wrong_type; + actual = displaying_class_of(obj); + } + else if (!RTYPEDDATA_P(obj)) { + actual = displaying_class_of(obj); } else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) { - etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name; - goto wrong_datatype; + const char *name = RTYPEDDATA_TYPE(obj)->wrap_struct_name; + actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */ + } + else { + return DATA_PTR(obj); } - return DATA_PTR(obj); + + const char *expected = data_type->wrap_struct_name; + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)", + actual, expected); + UNREACHABLE_RETURN(NULL); } /* exception classes */ @@ -933,6 +1110,7 @@ VALUE rb_eNotImpError; VALUE rb_eNoMemError; VALUE rb_cNameErrorMesg; VALUE rb_eNoMatchingPatternError; +VALUE rb_eNoMatchingPatternKeyError; VALUE rb_eScriptError; VALUE rb_eSyntaxError; @@ -945,7 +1123,7 @@ static VALUE rb_eNOERROR; ID ruby_static_id_cause; #define id_cause ruby_static_id_cause static ID id_message, id_backtrace; -static ID id_key, id_args, id_Errno, id_errno, id_i_path; +static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path; static ID id_receiver, id_recv, id_iseq, id_local_variables; static ID id_private_call_p, id_top, id_bottom; #define id_bt idBt @@ -986,7 +1164,8 @@ exc_init(VALUE exc, VALUE mesg) /* * call-seq: - * Exception.new(msg = nil) -> exception + * Exception.new(msg = nil) -> exception + * Exception.exception(msg = nil) -> exception * * Construct a new Exception object, optionally passing in * a message. @@ -1005,7 +1184,7 @@ exc_initialize(int argc, VALUE *argv, VALUE exc) * Document-method: exception * * call-seq: - * exc.exception(string) -> an_exception or exc + * exc.exception([string]) -> an_exception or exc * * With no argument, or if the argument is the same as the receiver, * return the receiver. Otherwise, create a new @@ -1065,7 +1244,7 @@ rb_get_message(VALUE exc) static VALUE exc_s_to_tty_p(VALUE self) { - return rb_stderr_tty_p() ? Qtrue : Qfalse; + return RBOOL(rb_stderr_tty_p()); } /* @@ -1105,8 +1284,8 @@ exc_full_message(int argc, VALUE *argv, VALUE exc) rb_get_kwargs(opt, kw, 0, kw_max_, args); switch (args[kw_highlight]) { default: - rb_raise(rb_eArgError, "expected true or false as " - "highlight: %+"PRIsVALUE, args[kw_highlight]); + rb_bool_expected(args[kw_highlight], "highlight"); + UNREACHABLE; case Qundef: args[kw_highlight] = Qnil; break; case Qtrue: case Qfalse: case Qnil: break; } @@ -1370,9 +1549,7 @@ exc_equal(VALUE exc, VALUE obj) if (!rb_equal(rb_attr_get(exc, id_mesg), mesg)) return Qfalse; - if (!rb_equal(exc_backtrace(exc), backtrace)) - return Qfalse; - return Qtrue; + return rb_equal(exc_backtrace(exc), backtrace); } /* @@ -1460,10 +1637,7 @@ exit_success_p(VALUE exc) if (NIL_P(status_val)) return Qtrue; status = NUM2INT(status_val); - if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) - return Qtrue; - - return Qfalse; + return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS); } static VALUE @@ -1636,7 +1810,7 @@ static VALUE nometh_err_init_attr(VALUE exc, VALUE args, int priv) { rb_ivar_set(exc, id_args, args); - rb_ivar_set(exc, id_private_call_p, priv ? Qtrue : Qfalse); + rb_ivar_set(exc, id_private_call_p, RBOOL(priv)); return exc; } @@ -1712,9 +1886,9 @@ static const rb_data_type_t name_err_mesg_data_type = { /* :nodoc: */ static VALUE -rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method) +rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE method) { - VALUE result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, 0); + 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; @@ -1724,6 +1898,35 @@ rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method) return result; } +/* :nodoc: */ +static VALUE +rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method) +{ + return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method); +} + +/* :nodoc: */ +static VALUE +name_err_mesg_alloc(VALUE klass) +{ + return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil); +} + +/* :nodoc: */ +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); + return obj1; +} + /* :nodoc: */ static VALUE name_err_mesg_equal(VALUE obj1, VALUE obj2) @@ -1744,6 +1947,17 @@ name_err_mesg_equal(VALUE obj1, VALUE obj2) return Qtrue; } +/* :nodoc: */ +static VALUE +name_err_mesg_receiver_name(VALUE obj) +{ + if (RB_SPECIAL_CONST_P(obj)) return Qundef; + if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) { + return rb_check_funcall(obj, rb_intern("name"), 0, 0); + } + return Qundef; +} + /* :nodoc: */ static VALUE name_err_mesg_to_str(VALUE obj) @@ -1772,10 +1986,14 @@ name_err_mesg_to_str(VALUE obj) d = FAKE_CSTR(&d_str, "false"); break; default: - d = rb_protect(rb_inspect, obj, &state); - if (state) + d = rb_protect(name_err_mesg_receiver_name, obj, &state); + if (state || d == Qundef || NIL_P(d)) + d = rb_protect(rb_inspect, obj, &state); + if (state) { rb_set_errinfo(Qnil); - if (NIL_P(d) || RSTRING_LEN(d) > 65) { + } + d = rb_check_string_type(d); + if (NIL_P(d)) { d = rb_any_to_s(obj); } singleton = (RSTRING_LEN(d) > 0 && RSTRING_PTR(d)[0] == '#'); @@ -1946,6 +2164,73 @@ key_err_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* + * call-seq: + * no_matching_pattern_key_error.matchee -> object + * + * Return the matchee associated with this NoMatchingPatternKeyError exception. + */ + +static VALUE +no_matching_pattern_key_err_matchee(VALUE self) +{ + VALUE matchee; + + matchee = rb_ivar_lookup(self, id_matchee, Qundef); + if (matchee != Qundef) return matchee; + rb_raise(rb_eArgError, "no matchee is available"); +} + +/* + * call-seq: + * no_matching_pattern_key_error.key -> object + * + * Return the key caused this NoMatchingPatternKeyError exception. + */ + +static VALUE +no_matching_pattern_key_err_key(VALUE self) +{ + VALUE key; + + key = rb_ivar_lookup(self, id_key, Qundef); + if (key != Qundef) return key; + rb_raise(rb_eArgError, "no key is available"); +} + +/* + * call-seq: + * NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error + * + * Construct a new +NoMatchingPatternKeyError+ exception with the given message, + * matchee and key. + */ + +static VALUE +no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE options; + + rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv); + + if (!NIL_P(options)) { + ID keywords[2]; + VALUE values[numberof(keywords)]; + int i; + keywords[0] = id_matchee; + keywords[1] = id_key; + rb_get_kwargs(options, keywords, 0, numberof(values), values); + for (i = 0; i < numberof(values); ++i) { + if (values[i] != Qundef) { + rb_ivar_set(self, keywords[i], values[i]); + } + } + } + + return self; +} + + /* * call-seq: * SyntaxError.new([msg]) -> syntax_error @@ -2137,9 +2422,7 @@ syserr_eqq(VALUE self, VALUE exc) num = rb_funcallv(exc, id_errno, 0, 0); } e = rb_const_get(self, id_Errno); - if (FIXNUM_P(num) ? num == e : rb_equal(num, e)) - return Qtrue; - return Qfalse; + return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e)); } @@ -2444,6 +2727,8 @@ 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. * @@ -2538,10 +2823,56 @@ syserr_eqq(VALUE self, VALUE exc) * * fatal */ +static VALUE +exception_alloc(VALUE klass) +{ + return rb_class_allocate_instance(klass); +} + +static VALUE +exception_dumper(VALUE exc) +{ + // TODO: Currently, the instance variables "bt" and "bt_locations" + // refers to the same object (Array of String). But "bt_locations" + // should have an Array of Thread::Backtrace::Locations. + + return exc; +} + +static int +ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc) +{ + rb_ivar_set((VALUE) exc, (ID) key, (VALUE) val); + return ST_CONTINUE; +} + +static VALUE +exception_loader(VALUE exc, VALUE obj) +{ + // The loader function of rb_marshal_define_compat seems to be called for two events: + // one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF. + // In the former case, the first argument is an instance of Exception (because + // we pass rb_eException to rb_marshal_define_compat). In the latter case, the first + // argument is a class object (see TYPE_USERDEF case in r_object0). + // We want to copy all instance variables (but "bt_locations") from obj to exc. + // But we do not want to do so in the second case, so the following branch is for that. + if (RB_TYPE_P(exc, T_CLASS)) return obj; // maybe called from Marshal's TYPE_USERDEF + + rb_ivar_foreach(obj, ivar_copy_i, exc); + + if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) { + rb_ivar_set(exc, id_bt_locations, Qnil); + } + + return exc; +} + void Init_Exception(void) { rb_eException = rb_define_class("Exception", rb_cObject); + rb_define_alloc_func(rb_eException, exception_alloc); + rb_marshal_define_compat(rb_eException, rb_eException, exception_dumper, exception_loader); rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1); rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0); rb_define_method(rb_eException, "exception", exc_exception, -1); @@ -2590,7 +2921,9 @@ Init_Exception(void) rb_define_method(rb_eNameError, "name", name_err_name, 0); rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0); rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0); - rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData); + rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cObject); + rb_define_alloc_func(rb_cNameErrorMesg, name_err_mesg_alloc); + rb_define_method(rb_cNameErrorMesg, "initialize_copy", name_err_mesg_init_copy, 1); rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1); rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0); rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1); @@ -2608,7 +2941,11 @@ Init_Exception(void) rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException); rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError); rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError); - rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eRuntimeError); + rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eStandardError); + rb_eNoMatchingPatternKeyError = rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError); + rb_define_method(rb_eNoMatchingPatternKeyError, "initialize", no_matching_pattern_key_err_initialize, -1); + rb_define_method(rb_eNoMatchingPatternKeyError, "matchee", no_matching_pattern_key_err_matchee, 0); + rb_define_method(rb_eNoMatchingPatternKeyError, "key", no_matching_pattern_key_err_key, 0); syserr_tbl = st_init_numtable(); rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError); @@ -2621,7 +2958,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_method(rb_mWarning, "warn", rb_warning_s_warn, 1); + rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1); rb_extend_object(rb_mWarning, rb_mWarning); /* :nodoc: */ @@ -2632,6 +2969,7 @@ Init_Exception(void) id_message = rb_intern_const("message"); id_backtrace = rb_intern_const("backtrace"); id_key = rb_intern_const("key"); + id_matchee = rb_intern_const("matchee"); id_args = rb_intern_const("args"); id_receiver = rb_intern_const("receiver"); id_private_call_p = rb_intern_const("private_call?"); @@ -2640,10 +2978,24 @@ Init_Exception(void) id_errno = rb_intern_const("errno"); id_i_path = rb_intern_const("@path"); id_warn = rb_intern_const("warn"); + id_category = rb_intern_const("category"); + id_deprecated = rb_intern_const("deprecated"); + id_experimental = rb_intern_const("experimental"); id_top = rb_intern_const("top"); id_bottom = rb_intern_const("bottom"); id_iseq = rb_make_internal_id(); id_recv = rb_make_internal_id(); + + sym_category = ID2SYM(id_category); + + warning_categories.id2enum = rb_init_identtable(); + st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED); + st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL); + + 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); } void @@ -2813,6 +3165,12 @@ rb_sys_fail_path_in(const char *func_name, VALUE path) void rb_syserr_fail_path_in(const char *func_name, int n, VALUE path) +{ + rb_exc_raise(rb_syserr_new_path_in(func_name, n, path)); +} + +VALUE +rb_syserr_new_path_in(const char *func_name, int n, VALUE path) { VALUE args[2]; @@ -2825,40 +3183,45 @@ rb_syserr_fail_path_in(const char *func_name, int n, VALUE path) } args[0] = path; args[1] = rb_str_new_cstr(func_name); - rb_exc_raise(rb_class_new_instance(2, args, get_syserr(n))); + return rb_class_new_instance(2, args, get_syserr(n)); } #endif +NORETURN(static void rb_mod_exc_raise(VALUE exc, VALUE mod)); + +static void +rb_mod_exc_raise(VALUE exc, VALUE mod) +{ + rb_extend_object(exc, mod); + rb_exc_raise(exc); +} + void rb_mod_sys_fail(VALUE mod, const char *mesg) { VALUE exc = make_errno_exc(mesg); - rb_extend_object(exc, mod); - rb_exc_raise(exc); + rb_mod_exc_raise(exc, mod); } void rb_mod_sys_fail_str(VALUE mod, VALUE mesg) { VALUE exc = make_errno_exc_str(mesg); - rb_extend_object(exc, mod); - rb_exc_raise(exc); + rb_mod_exc_raise(exc, mod); } void rb_mod_syserr_fail(VALUE mod, int e, const char *mesg) { VALUE exc = rb_syserr_new(e, mesg); - rb_extend_object(exc, mod); - rb_exc_raise(exc); + rb_mod_exc_raise(exc, mod); } void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg) { VALUE exc = rb_syserr_new_str(e, mesg); - rb_extend_object(exc, mod); - rb_exc_raise(exc); + rb_mod_exc_raise(exc, mod); } static void @@ -3033,14 +3396,14 @@ rb_check_frozen(VALUE obj) void rb_error_untrusted(VALUE obj) { - rb_warning("rb_error_untrusted is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_error_untrusted", NULL); } #undef rb_check_trusted void rb_check_trusted(VALUE obj) { - rb_warning("rb_check_trusted is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_check_trusted", NULL); } void @@ -3064,12 +3427,6 @@ Init_syserr(void) #include "warning.rbinc" -void -Init_warning(void) -{ - load_warning(); -} - /*! * \} */ diff --git a/ruby/eval.c b/ruby/eval.c index 08f7ba97d..0de3105ac 100644 --- a/ruby/eval.c +++ b/ruby/eval.c @@ -11,24 +11,38 @@ **********************************************************************/ -#include "internal.h" +#include "ruby/internal/config.h" + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + #include "eval_intern.h" -#include "iseq.h" #include "gc.h" -#include "ruby/vm.h" -#include "vm_core.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/hash.h" +#include "internal/inits.h" +#include "internal/io.h" +#include "internal/object.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "ruby/fiber/scheduler.h" +#include "iseq.h" #include "mjit.h" #include "probes.h" #include "probes_helper.h" -#ifdef HAVE_SYS_PRCTL_H -#include -#endif +#include "ruby/vm.h" +#include "vm_core.h" +#include "ractor_core.h" -NORETURN(void rb_raise_jump(VALUE, VALUE)); +NORETURN(static void rb_raise_jump(VALUE, VALUE)); void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec); void rb_ec_clear_all_trace_func(const rb_execution_context_t *ec); -static int rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex); +static int rb_ec_cleanup(rb_execution_context_t *ec, int ex); static int rb_ec_exec_node(rb_execution_context_t *ec, void *n); VALUE rb_eLocalJumpError; @@ -47,11 +61,6 @@ extern ID ruby_static_id_cause; (!SPECIAL_CONST_P(obj) && \ (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE)) -/*! - * Initializes the VM and builtin libraries. - * @retval 0 if succeeded. - * @retval non-zero an error occurred. - */ int ruby_setup(void) { @@ -85,11 +94,6 @@ ruby_setup(void) return state; } -/*! - * Calls ruby_setup() and check error. - * - * Prints errors and calls exit(3) if an error occurred. - */ void ruby_init(void) { @@ -101,16 +105,6 @@ ruby_init(void) } } -/*! Processes command line arguments and compiles the Ruby source to execute. - * - * This function does: - * \li Processes the given command line flags and arguments for ruby(1) - * \li compiles the source code from the given argument, -e or stdin, and - * \li returns the compiled source as an opaque pointer to an internal data structure - * - * @return an opaque pointer to the compiled source or an internal special value. - * @sa ruby_executable_node(). - */ void * ruby_options(int argc, char **argv) { @@ -132,9 +126,27 @@ ruby_options(int argc, char **argv) return iseq; } +static void +rb_ec_fiber_scheduler_finalize(rb_execution_context_t *ec) +{ + enum ruby_tag_type state; + + EC_PUSH_TAG(ec); + if ((state = EC_EXEC_TAG()) == TAG_NONE) { + rb_fiber_scheduler_set(Qnil); + } + else { + state = error_handle(ec, state); + } + EC_POP_TAG(); +} + static void rb_ec_teardown(rb_execution_context_t *ec) { + // If the user code defined a scheduler for the top level thread, run it: + rb_ec_fiber_scheduler_finalize(ec); + EC_PUSH_TAG(ec); if (EC_EXEC_TAG() == TAG_NONE) { rb_vm_trap_exit(rb_ec_vm_ptr(ec)); @@ -152,13 +164,6 @@ rb_ec_finalize(rb_execution_context_t *ec) rb_objspace_call_finalizer(rb_ec_vm_ptr(ec)->objspace); } -/** Runs the VM finalization processes. - * - * END{} and procs registered by Kernel.#at_exit are - * executed here. See the Ruby language spec for more details. - * - * @note This function is allowed to raise an exception if an error occurred. - */ void ruby_finalize(void) { @@ -167,24 +172,14 @@ ruby_finalize(void) rb_ec_finalize(ec); } -/** Destructs the VM. - * - * Runs the VM finalization processes as well as ruby_finalize(), and frees - * resources used by the VM. - * - * @param ex Default value to the return value. - * @return If an error occurred returns a non-zero. If otherwise, returns the - * given ex. - * @note This function does not raise any exception. - */ int -ruby_cleanup(volatile int ex) +ruby_cleanup(int ex) { return rb_ec_cleanup(GET_EC(), ex); } static int -rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex) +rb_ec_cleanup(rb_execution_context_t *ec, int ex0) { int state; volatile VALUE errs[2] = { Qundef, Qundef }; @@ -193,16 +188,16 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex) rb_thread_t *const volatile th0 = th; volatile int sysex = EXIT_SUCCESS; volatile int step = 0; + volatile int ex = ex0; rb_threadptr_interrupt(th); rb_threadptr_check_signal(th); + EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - th = th0; SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(ec); }); step_0: step++; - th = th0; errs[1] = ec->errinfo; if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil; ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]); @@ -210,27 +205,27 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex) SAVE_ROOT_JMPBUF(th, rb_ec_teardown(ec)); step_1: step++; - th = th0; /* protect from Thread#raise */ th->status = THREAD_KILLED; errs[0] = ec->errinfo; - SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all()); + SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all()); } else { + th = th0; switch (step) { case 0: goto step_0; case 1: goto step_1; } if (ex == 0) ex = state; } - th = th0; ec->errinfo = errs[1]; sysex = error_handle(ec, ex); state = 0; for (nerr = 0; nerr < numberof(errs); ++nerr) { VALUE err = ATOMIC_VALUE_EXCHANGE(errs[nerr], Qnil); + VALUE sig; if (!RTEST(err)) continue; @@ -246,6 +241,11 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex) state = NUM2INT(sig); break; } + else if (rb_obj_is_kind_of(err, rb_eSystemCallError) && + FIXNUM_P(sig = rb_attr_get(err, id_signo))) { + state = NUM2INT(sig); + break; + } else if (sysex == EXIT_SUCCESS) { sysex = EXIT_FAILURE; } @@ -257,7 +257,9 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex) /* unlock again if finalizer took mutexes. */ rb_threadptr_unlock_all_locking_mutexes(th); + th = th0; EC_POP_TAG(); + th = th0; rb_thread_stop_timer_thread(); ruby_vm_destruct(th->vm); if (state) ruby_default_signal(state); @@ -283,25 +285,12 @@ rb_ec_exec_node(rb_execution_context_t *ec, void *n) return state; } -/*! Calls ruby_cleanup() and exits the process */ void ruby_stop(int ex) { exit(ruby_cleanup(ex)); } -/*! Checks the return value of ruby_options(). - * @param n return value of ruby_options(). - * @param status pointer to the exit status of this process. - * - * ruby_options() sometimes returns a special value to indicate this process - * should immediately exit. This function checks if the case. Also stores the - * exit status that the caller have to pass to exit(3) into - * *status. - * - * @retval non-zero if the given opaque pointer is actually a compiled source. - * @retval 0 if the given value is such a special value. - */ int ruby_executable_node(void *n, int *status) { @@ -319,10 +308,6 @@ ruby_executable_node(void *n, int *status) return FALSE; } -/*! Runs the given compiled source and exits this process. - * @retval 0 if successfully run the source - * @retval non-zero if an error occurred. -*/ int ruby_run_node(void *n) { @@ -336,7 +321,6 @@ ruby_run_node(void *n) return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n)); } -/*! Runs the given compiled source */ int ruby_exec_node(void *n) { @@ -438,9 +422,11 @@ void rb_class_modify_check(VALUE klass) { if (SPECIAL_CONST_P(klass)) { - noclass: Check_Type(klass, T_CLASS); } + if (RB_TYPE_P(klass, T_MODULE)) { + rb_module_set_initialized(klass); + } if (OBJ_FROZEN(klass)) { const char *desc; @@ -456,6 +442,8 @@ rb_class_modify_check(VALUE klass) case T_CLASS: desc = "Class"; break; + default: + break; } } } @@ -469,7 +457,8 @@ rb_class_modify_check(VALUE klass) desc = "class"; break; default: - goto noclass; + Check_Type(klass, T_CLASS); + UNREACHABLE; } } rb_frozen_error_raise(klass, "can't modify frozen %s: %"PRIsVALUE, desc, klass); @@ -622,16 +611,19 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE } if (rb_ec_set_raised(ec)) { - fatal: - ec->errinfo = exception_error; - rb_ec_reset_raised(ec); - EC_JUMP_TAG(ec, TAG_FATAL); + goto fatal; } if (tag != TAG_FATAL) { RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(ec->errinfo)); EXEC_EVENT_HOOK(ec, RUBY_EVENT_RAISE, ec->cfp->self, 0, 0, 0, mesg); } + return; + + fatal: + ec->errinfo = exception_error; + rb_ec_reset_raised(ec); + EC_JUMP_TAG(ec, TAG_FATAL); } /*! \private */ @@ -657,6 +649,17 @@ 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)); + +static void +rb_exc_exception(VALUE mesg, int tag, VALUE cause) +{ + if (!NIL_P(mesg)) { + mesg = make_exception(1, &mesg, FALSE); + } + 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. @@ -667,10 +670,7 @@ static VALUE make_exception(int argc, const VALUE *argv, int isstr); void rb_exc_raise(VALUE mesg) { - if (!NIL_P(mesg)) { - mesg = make_exception(1, &mesg, FALSE); - } - rb_longjmp(GET_EC(), TAG_RAISE, mesg, Qundef); + rb_exc_exception(mesg, TAG_RAISE, Qundef); } /*! @@ -683,16 +683,9 @@ rb_exc_raise(VALUE mesg) void rb_exc_fatal(VALUE mesg) { - if (!NIL_P(mesg)) { - mesg = make_exception(1, &mesg, FALSE); - } - rb_longjmp(GET_EC(), TAG_FATAL, mesg, Qnil); + rb_exc_exception(mesg, TAG_FATAL, Qnil); } -/*! - * Raises an \c Interrupt exception. - * \ingroup exception - */ void rb_interrupt(void) { @@ -784,69 +777,42 @@ static VALUE make_exception(int argc, const VALUE *argv, int isstr) { VALUE mesg, exc; - int n; mesg = Qnil; switch (argc) { case 0: - break; + return Qnil; case 1: exc = argv[0]; - if (NIL_P(exc)) - break; - if (isstr) { + if (isstr &&! NIL_P(exc)) { mesg = rb_check_string_type(exc); if (!NIL_P(mesg)) { - mesg = rb_exc_new3(rb_eRuntimeError, mesg); - break; + return rb_exc_new3(rb_eRuntimeError, mesg); } } - n = 0; - goto exception_call; case 2: case 3: - exc = argv[0]; - n = 1; - exception_call: - mesg = rb_check_funcall(exc, idException, n, argv+1); - if (mesg == Qundef) { - rb_raise(rb_eTypeError, "exception class/object expected"); - } break; default: rb_error_arity(argc, 0, 3); } - if (argc > 0) { - if (!rb_obj_is_kind_of(mesg, rb_eException)) - rb_raise(rb_eTypeError, "exception object expected"); - if (argc > 2) - set_backtrace(mesg, argv[2]); + if (NIL_P(mesg)) { + mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]); + } + if (mesg == Qundef) { + rb_raise(rb_eTypeError, "exception class/object expected"); + } + if (!rb_obj_is_kind_of(mesg, rb_eException)) { + rb_raise(rb_eTypeError, "exception object expected"); + } + if (argc == 3) { + set_backtrace(mesg, argv[2]); } return mesg; } -/*! - * Make an \c Exception object from the list of arguments in a manner - * similar to \c Kernel\#raise. - * - * \param[in] argc the number of arguments - * \param[in] argv a pointer to the array of arguments. - * - * The first form of this function takes a \c String argument. Then - * it returns a \c RuntimeError whose error message is the given value. - * - * The second from of this function takes an \c Exception object. Then - * it just returns the given value. - * - * The last form takes an exception class, an optional error message and - * an optional array of backtrace. Then it passes the optional arguments - * to \c #exception method of the exception class. - * - * \return the exception object, or \c Qnil if \c argc is 0. - * \ingroup exception - */ VALUE rb_make_exception(int argc, const VALUE *argv) { @@ -854,9 +820,8 @@ rb_make_exception(int argc, const VALUE *argv) } /*! \private - * \todo can be static? */ -void +static void rb_raise_jump(VALUE mesg, VALUE cause) { rb_execution_context_t *ec = GET_EC(); @@ -872,14 +837,6 @@ rb_raise_jump(VALUE mesg, VALUE cause) rb_longjmp(ec, TAG_RAISE, mesg, cause); } -/*! - * Continues the exception caught by rb_protect() and rb_eval_string_protect(). - * - * This function never return to the caller. - * \param[in] the value of \c *state which the protect function has set to the - * their last parameter. - * \ingroup exception - */ void rb_jump_tag(int tag) { @@ -889,11 +846,6 @@ rb_jump_tag(int tag) EC_JUMP_TAG(GET_EC(), tag); } -/*! Determines if the current method is given a block. - * \retval zero if not given - * \retval non-zero if given - * \ingroup defmethod - */ int rb_block_given_p(void) { @@ -913,21 +865,8 @@ rb_keyword_given_p(void) return rb_vm_cframe_keyword_p(GET_EC()->cfp); } -/* -- Remove In 3.0 -- */ -int rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp); -int -rb_empty_keyword_given_p(void) -{ - return rb_vm_cframe_empty_keyword_p(GET_EC()->cfp); -} - VALUE rb_eThreadError; -/*! Declares that the current method needs a block. - * - * Raises a \c LocalJumpError if not given a block. - * \ingroup defmethod - */ void rb_need_block(void) { @@ -936,28 +875,6 @@ rb_need_block(void) } } -/*! An equivalent of \c rescue clause. - * - * Equivalent to begin .. rescue err_type .. end - * - * \param[in] b_proc a function which potentially raises an exception. - * \param[in] data1 the argument of \a b_proc - * \param[in] r_proc a function which rescues an exception in \a b_proc. - * \param[in] data2 the first argument of \a r_proc - * \param[in] ... 1 or more exception classes. Must be terminated by \c (VALUE)0. - * - * First it calls the function \a b_proc, with \a data1 as the argument. - * When \a b_proc raises an exception, it calls \a r_proc with \a data2 and - * the exception object if the exception is a kind of one of the given - * exception classes. - * - * \return the return value of \a b_proc if no exception occurs, - * or the return value of \a r_proc if otherwise. - * \sa rb_rescue - * \sa rb_ensure - * \sa rb_protect - * \ingroup exception - */ VALUE rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1, VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...) @@ -969,10 +886,6 @@ rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1, return ret; } -/*! - * \copydoc rb_rescue2 - * \param[in] args exception classes, terminated by 0. - */ VALUE rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1, VALUE (* r_proc) (VALUE, VALUE), VALUE data2, @@ -992,7 +905,7 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1, else if (result) { /* escape from r_proc */ if (state == TAG_RETRY) { - state = 0; + state = TAG_NONE; ec->errinfo = Qnil; result = Qfalse; goto retry_entry; @@ -1004,17 +917,21 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1, if (state == TAG_RAISE) { int handle = FALSE; VALUE eclass; + va_list ap; - while ((eclass = va_arg(args, VALUE)) != 0) { + result = Qnil; + /* reuses args when raised again after retrying in r_proc */ + va_copy(ap, args); + while ((eclass = va_arg(ap, VALUE)) != 0) { if (rb_obj_is_kind_of(ec->errinfo, eclass)) { handle = TRUE; break; } } + va_end(ap); if (handle) { - result = Qnil; - state = 0; + state = TAG_NONE; if (r_proc) { result = (*r_proc) (data2, ec->errinfo); } @@ -1029,20 +946,6 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1, return result; } -/*! An equivalent of \c rescue clause. - * - * Equivalent to begin .. rescue .. end. - * - * It is same as - * \code{cpp} - * rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0); - * \endcode - * - * \sa rb_rescue2 - * \sa rb_ensure - * \sa rb_protect - * \ingroup exception - */ VALUE rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1, VALUE (* r_proc)(VALUE, VALUE), VALUE data2) @@ -1051,23 +954,6 @@ rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1, (VALUE)0); } -/*! Protects a function call from potential global escapes from the function. - * - * Such global escapes include exceptions, \c Kernel\#throw, \c break in - * an iterator, for example. - * It first calls the function func with arg as the argument. - * If no exception occurred during func, it returns the result of func and - * *state is zero. - * Otherwise, it returns Qnil and sets *state to nonzero. - * If state is NULL, it is not set in both cases. - * - * You have to clear the error info with rb_set_errinfo(Qnil) when - * ignoring the caught exception. - * \ingroup exception - * \sa rb_rescue - * \sa rb_rescue2 - * \sa rb_ensure - */ VALUE rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) { @@ -1075,42 +961,20 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) volatile enum ruby_tag_type state; rb_execution_context_t * volatile ec = GET_EC(); rb_control_frame_t *volatile cfp = ec->cfp; - struct rb_vm_protect_tag protect_tag; - rb_jmpbuf_t org_jmpbuf; - - protect_tag.prev = ec->protect_tag; EC_PUSH_TAG(ec); - ec->protect_tag = &protect_tag; - MEMCPY(&org_jmpbuf, &rb_ec_thread_ptr(ec)->root_jmpbuf, rb_jmpbuf_t, 1); if ((state = EC_EXEC_TAG()) == TAG_NONE) { SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data)); } else { rb_vm_rewind_cfp(ec, cfp); } - MEMCPY(&rb_ec_thread_ptr(ec)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1); - ec->protect_tag = protect_tag.prev; EC_POP_TAG(); if (pstate != NULL) *pstate = state; return result; } -/*! - * An equivalent to \c ensure clause. - * - * Equivalent to begin .. ensure .. end. - * - * Calls the function \a b_proc with \a data1 as the argument, - * then calls \a e_proc with \a data2 when execution terminated. - * \return The return value of \a b_proc if no exception occurred, - * or \c Qnil if otherwise. - * \sa rb_rescue - * \sa rb_rescue2 - * \sa rb_protect - * \ingroup exception - */ VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2) { @@ -1167,35 +1031,12 @@ frame_called_id(rb_control_frame_t *cfp) } } -/*! - * The original name of the current method. - * - * The function returns the original name of the method even if - * an alias of the method is called. - * The function can also return 0 if it is not in a method. This - * case can happen in a toplevel of a source file, for example. - * - * \returns the ID of the name or 0 - * \sa rb_frame_callee - * \ingroup defmethod - */ ID rb_frame_this_func(void) { return frame_func_id(GET_EC()->cfp); } -/*! - * The name of the current method. - * - * The function returns the alias if an alias of the method is called. - * The function can also return 0 if it is not in a method. This - * case can happen in a toplevel of a source file, for example. - * - * \returns the ID of the name or 0. - * \sa rb_frame_this_func - * \ingroup defmethod - */ ID rb_frame_callee(void) { @@ -1287,6 +1128,10 @@ rb_mod_include(int argc, VALUE *argv, VALUE module) CONST_ID(id_append_features, "append_features"); CONST_ID(id_included, "included"); + if (FL_TEST(module, RMODULE_IS_REFINEMENT)) { + rb_warn_deprecated_to_remove_at(3.2, "Refinement#include", NULL); + } + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); for (i = 0; i < argc; i++) Check_Type(argv[i], T_MODULE); @@ -1333,6 +1178,10 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module) int i; ID id_prepend_features, id_prepended; + if (FL_TEST(module, RMODULE_IS_REFINEMENT)) { + rb_warn_deprecated_to_remove_at(3.2, "Refinement#prepend", NULL); + } + CONST_ID(id_prepend_features, "prepend_features"); CONST_ID(id_prepended, "prepended"); @@ -1370,7 +1219,7 @@ refinement_superclass(VALUE superclass) { if (RB_TYPE_P(superclass, T_MODULE)) { /* FIXME: Should ancestors of superclass be used here? */ - return rb_include_class_new(superclass, rb_cBasicObject); + return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject); } else { return superclass; @@ -1379,9 +1228,8 @@ refinement_superclass(VALUE superclass) /*! * \private - * \todo can be static? */ -void +static void rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module) { VALUE iclass, c, superclass = klass; @@ -1412,8 +1260,7 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module) c = iclass = rb_include_class_new(module, superclass); RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); - RCLASS_M_TBL(OBJ_WB_UNPROTECT(c)) = - RCLASS_M_TBL(OBJ_WB_UNPROTECT(module)); /* TODO: check unprotecting */ + RCLASS_M_TBL(c) = RCLASS_M_TBL(module); module = RCLASS_SUPER(module); while (module && module != klass) { @@ -1466,14 +1313,13 @@ using_module_recursive(const rb_cref_t *cref, VALUE klass) /*! * \private - * \todo can be static? */ -void +static void rb_using_module(const rb_cref_t *cref, VALUE module) { Check_Type(module, T_MODULE); using_module_recursive(cref, module); - rb_clear_method_cache_by_class(rb_cObject); + rb_clear_method_cache_all(); } /*! \private */ @@ -1543,9 +1389,6 @@ rb_mod_refine(VALUE module, VALUE klass) } ensure_class_or_module(klass); - if (RB_TYPE_P(klass, T_MODULE)) { - FL_SET(klass, RCLASS_REFINED_BY_ANY); - } CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) { @@ -1562,7 +1405,7 @@ rb_mod_refine(VALUE module, VALUE klass) refinement = rb_hash_lookup(refinements, klass); if (NIL_P(refinement)) { VALUE superclass = refinement_superclass(klass); - refinement = rb_module_new(); + refinement = rb_refinement_new(); RCLASS_SET_SUPER(refinement, superclass); FL_SET(refinement, RMODULE_IS_REFINEMENT); CONST_ID(id_refined_class, "__refined_class__"); @@ -1667,21 +1510,62 @@ rb_mod_s_used_modules(VALUE _) return rb_funcall(ary, rb_intern("uniq"), 0); } -/*! - * Calls \c #initialize method of \a obj with the given arguments. - * - * It also forwards the given block to \c #initialize if given. - * - * \param[in] obj the receiver object - * \param[in] argc the number of arguments - * \param[in] argv a pointer to the array of arguments - * \ingroup object +struct refinement_import_methods_arg { + rb_cref_t *cref; + VALUE refinement; + VALUE module; +}; + +/* vm.c */ +rb_cref_t *rb_vm_cref_dup_without_refinements(const rb_cref_t *cref); + +static enum rb_id_table_iterator_result +refinement_import_methods_i(ID key, VALUE value, void *data) +{ + const rb_method_entry_t *me = (const rb_method_entry_t *)value; + struct refinement_import_methods_arg *arg = (struct refinement_import_methods_arg *)data; + + if (me->def->type != VM_METHOD_TYPE_ISEQ) { + rb_raise(rb_eArgError, "Can't import method which is not defined with Ruby code: %"PRIsVALUE"#%"PRIsVALUE, rb_class_path(arg->module), rb_id2str(key)); + } + rb_cref_t *new_cref = rb_vm_cref_dup_without_refinements(me->def->body.iseq.cref); + CREF_REFINEMENTS_SET(new_cref, CREF_REFINEMENTS(arg->cref)); + rb_add_method_iseq(arg->refinement, key, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me)); + return ID_TABLE_CONTINUE; +} + +/* + * Note: docs for the method are in class.c */ + +static VALUE +refinement_import_methods(int argc, VALUE *argv, VALUE refinement) +{ + int i; + struct refinement_import_methods_arg arg; + + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); + for (i = 0; i < argc; i++) { + Check_Type(argv[i], T_MODULE); + if (RCLASS_SUPER(argv[i])) { + rb_warn("%"PRIsVALUE" has ancestors, but Refinement#import_methods doesn't import their methods", rb_class_path(argv[i])); + } + } + arg.cref = rb_vm_cref_replace_with_duplicated_cref(); + arg.refinement = refinement; + for (i = 0; i < argc; i++) { + arg.module = argv[i]; + struct rb_id_table *m_tbl = RCLASS_M_TBL(argv[i]); + if (!m_tbl) continue; + rb_id_table_foreach(m_tbl, refinement_import_methods_i, &arg); + } + return refinement; +} + void rb_obj_call_init(VALUE obj, int argc, const VALUE *argv) { - PASS_PASSED_BLOCK_HANDLER(); - rb_funcallv_kw(obj, idInitialize, argc, argv, RB_NO_KEYWORDS); + rb_obj_call_init_kw(obj, argc, argv, RB_NO_KEYWORDS); } void @@ -1691,12 +1575,6 @@ rb_obj_call_init_kw(VALUE obj, int argc, const VALUE *argv, int kw_splat) rb_funcallv_kw(obj, idInitialize, argc, argv, kw_splat); } -/*! - * Extend the object with the module. - * - * Same as \c Module\#extend_object. - * \ingroup class - */ void rb_extend_object(VALUE obj, VALUE module) { @@ -1872,26 +1750,12 @@ errinfo_getter(ID id, VALUE *_) return get_errinfo(); } -/*! The current exception in the current thread. - * - * Same as \c $! in Ruby. - * \return the current exception or \c Qnil - * \ingroup exception - */ VALUE rb_errinfo(void) { return GET_EC()->errinfo; } -/*! Sets the current exception (\c $!) to the given value - * - * \param[in] err an \c Exception object or \c Qnil. - * \exception TypeError if \a err is neither an exception nor \c nil. - * \note this function does not raise the exception. - * Use \c rb_raise() when you want to raise. - * \ingroup exception - */ void rb_set_errinfo(VALUE err) { @@ -1993,7 +1857,10 @@ f_current_dirname(VALUE _) * call-seq: * global_variables -> array * - * Returns an array of the names of global variables. + * Returns an array of the names of global variables. This includes + * special regexp global variables such as $~ and $+, + * but does not include the numbered regexp global variables ($1, + * $2, etc.). * * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr] */ @@ -2055,6 +1922,9 @@ Init_eval(void) rb_define_virtual_variable("$@", errat_getter, errat_setter); rb_define_virtual_variable("$!", errinfo_getter, 0); + rb_gvar_ractor_local("$@"); + rb_gvar_ractor_local("$!"); + rb_define_global_function("raise", f_raise, -1); rb_define_global_function("fail", f_raise, -1); @@ -2075,6 +1945,7 @@ Init_eval(void) rb_define_singleton_method(rb_cModule, "used_modules", rb_mod_s_used_modules, 0); rb_undef_method(rb_cClass, "refine"); + rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1); rb_undef_method(rb_cClass, "module_function"); diff --git a/ruby/eval_error.c b/ruby/eval_error.c index 847072ab9..9b453eede 100644 --- a/ruby/eval_error.c +++ b/ruby/eval_error.c @@ -228,34 +228,48 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VA } static void -print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reverse) +print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reverse, long backtrace_limit) { if (!NIL_P(errat)) { long i; long len = RARRAY_LEN(errat); - int skip = eclass == rb_eSysStackError; const int threshold = 1000000000; int width = (len <= 1) ? INT_MIN : ((int)log10((double)(len > threshold ? ((len - 1) / threshold) : len - 1)) + (len < threshold ? 0 : 9) + 1); -#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) -#define TRACE_HEAD 8 -#define TRACE_TAIL 5 + long skip_start = -1, skip_len = 0; + + // skip for stackoverflow + if (eclass == rb_eSysStackError) { + long trace_head = 9; + long trace_tail = 4; + long trace_max = trace_head + trace_tail + 5; + if (len > trace_max) { + skip_start = trace_head; + skip_len = len - trace_max + 5; + } + } + + // skip for explicit limit + if (backtrace_limit >= 0 && len > backtrace_limit + 2) { + skip_start = backtrace_limit + 1; + skip_len = len - skip_start; + } for (i = 1; i < len; i++) { + if (i == skip_start) { + write_warn_str(str, rb_sprintf("\t ... %ld levels...\n", skip_len)); + i += skip_len; + if (i >= len) break; + } VALUE line = RARRAY_AREF(errat, reverse ? len - i : i); if (RB_TYPE_P(line, T_STRING)) { VALUE bt = rb_str_new_cstr("\t"); if (reverse) rb_str_catf(bt, "%*ld: ", width, len - i); write_warn_str(str, rb_str_catf(bt, "from %"PRIsVALUE"\n", line)); } - if (skip && i == TRACE_HEAD && len > TRACE_MAX) { - write_warn_str(str, rb_sprintf("\t ... %ld levels...\n", - len - TRACE_HEAD - TRACE_TAIL)); - i = len - TRACE_TAIL; - } } } } @@ -275,7 +289,7 @@ shown_cause_p(VALUE cause, VALUE *shown_causes) } static void -show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, VALUE *shown_causes) +show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, long backtrace_limit, VALUE *shown_causes) { VALUE cause = rb_attr_get(errinfo, id_cause); if (!NIL_P(cause) && rb_obj_is_kind_of(cause, rb_eException) && @@ -284,14 +298,14 @@ show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, VALUE *show VALUE errat = rb_get_backtrace(cause); VALUE emesg = rb_get_message(cause); if (reverse) { - show_cause(cause, str, highlight, reverse, shown_causes); - print_backtrace(eclass, errat, str, TRUE); + show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes); + print_backtrace(eclass, errat, str, TRUE, backtrace_limit); print_errinfo(eclass, errat, emesg, str, highlight!=0); } else { print_errinfo(eclass, errat, emesg, str, highlight!=0); - print_backtrace(eclass, errat, str, FALSE); - show_cause(cause, str, highlight, reverse, shown_causes); + print_backtrace(eclass, errat, str, FALSE, backtrace_limit); + show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes); } } } @@ -301,6 +315,7 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig { volatile VALUE eclass; VALUE shown_causes = 0; + long backtrace_limit = rb_backtrace_length_limit; if (NIL_P(errinfo)) return; @@ -309,9 +324,9 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig errat = Qnil; } eclass = CLASS_OF(errinfo); - if (NIL_P(reverse) || NIL_P(highlight)) { + if (NIL_P(reverse)) reverse = Qfalse; + if (NIL_P(highlight)) { VALUE tty = (VALUE)rb_stderr_tty_p(); - if (NIL_P(reverse)) reverse = tty; if (NIL_P(highlight)) highlight = tty; } if (reverse) { @@ -331,14 +346,14 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig len = p - (msg = buff); } write_warn2(str, msg, len); - show_cause(errinfo, str, highlight, reverse, &shown_causes); - print_backtrace(eclass, errat, str, TRUE); + show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes); + print_backtrace(eclass, errat, str, TRUE, backtrace_limit); print_errinfo(eclass, errat, emesg, str, highlight!=0); } else { print_errinfo(eclass, errat, emesg, str, highlight!=0); - print_backtrace(eclass, errat, str, FALSE); - show_cause(errinfo, str, highlight, reverse, &shown_causes); + print_backtrace(eclass, errat, str, FALSE, backtrace_limit); + show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes); } } @@ -348,6 +363,7 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) volatile uint8_t raised_flag = ec->raised_flag; volatile VALUE errat = Qundef; volatile VALUE emesg = Qundef; + volatile bool written = false; if (NIL_P(errinfo)) return; @@ -362,7 +378,10 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) emesg = rb_get_message(errinfo); } - rb_error_write(errinfo, emesg, errat, Qnil, Qnil, Qnil); + if (!written) { + written = true; + rb_error_write(errinfo, emesg, errat, Qnil, Qnil, Qfalse); + } EC_POP_TAG(); ec->errinfo = errinfo; @@ -411,8 +430,8 @@ rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi) switch (visi & METHOD_VISI_MASK) { case METHOD_VISI_UNDEF: case METHOD_VISI_PUBLIC: mesg = inaccessible_mesg(""); break; - case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg(" private"); break; - case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg(" protected"); break; + case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg("private"); break; + case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg("protected"); break; default: UNREACHABLE; } rb_name_err_raise_str(mesg, klass, ID2SYM(id)); @@ -474,6 +493,10 @@ error_handle(rb_execution_context_t *ec, int ex) rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) { /* no message when exiting by signal */ } + else if (rb_obj_is_kind_of(errinfo, rb_eSystemCallError) && + FIXNUM_P(rb_attr_get(errinfo, id_signo))) { + /* no message when exiting by error to be mapped to signal */ + } else { rb_ec_error_print(ec, errinfo); } diff --git a/ruby/eval_intern.h b/ruby/eval_intern.h index aa07ce30e..78feb241a 100644 --- a/ruby/eval_intern.h +++ b/ruby/eval_intern.h @@ -91,40 +91,12 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval #include -#ifdef _MSC_VER -#define SAVE_ROOT_JMPBUF_BEFORE_STMT \ - __try { -#define SAVE_ROOT_JMPBUF_AFTER_STMT \ - } \ - __except (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW ? \ - (rb_ec_raised_set(GET_EC(), RAISED_STACKOVERFLOW), \ - raise(SIGSEGV), \ - EXCEPTION_EXECUTE_HANDLER) : \ - EXCEPTION_CONTINUE_SEARCH) { \ - /* never reaches here */ \ - } -#elif defined(__MINGW32__) -LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); -#define SAVE_ROOT_JMPBUF_BEFORE_STMT \ - do { \ - PVOID _handler = AddVectoredExceptionHandler(1, rb_w32_stack_overflow_handler); - -#define SAVE_ROOT_JMPBUF_AFTER_STMT \ - RemoveVectoredExceptionHandler(_handler); \ - } while (0); -#else -#define SAVE_ROOT_JMPBUF_BEFORE_STMT -#define SAVE_ROOT_JMPBUF_AFTER_STMT -#endif #define SAVE_ROOT_JMPBUF(th, stmt) do \ - if (ruby_setjmp((th)->root_jmpbuf) == 0) { \ - SAVE_ROOT_JMPBUF_BEFORE_STMT \ + if (true) { \ stmt; \ - SAVE_ROOT_JMPBUF_AFTER_STMT \ } \ - else { \ - rb_fiber_start(); \ + else if (th) { /* suppress unused-variable warning */ \ } while (0) #define EC_PUSH_TAG(ec) do { \ @@ -132,7 +104,8 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); struct rb_vm_tag _tag; \ _tag.state = TAG_NONE; \ _tag.tag = Qundef; \ - _tag.prev = _ec->tag; + _tag.prev = _ec->tag; \ + _tag.lock_rec = rb_ec_vm_lock_rec(_ec); \ #define EC_POP_TAG() \ _ec->tag = _tag.prev; \ @@ -143,7 +116,7 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); #define EC_REPUSH_TAG() (void)(_ec->tag = &_tag) -#if defined __GNUC__ && __GNUC__ == 4 && (__GNUC_MINOR__ >= 6 && __GNUC_MINOR__ <= 8) || __clang__ +#if defined __GNUC__ && __GNUC__ == 4 && (__GNUC_MINOR__ >= 6 && __GNUC_MINOR__ <= 8) || defined __clang__ /* This macro prevents GCC 4.6--4.8 from emitting maybe-uninitialized warnings. * This macro also prevents Clang from dumping core in EC_EXEC_TAG(). * (I confirmed Clang 4.0.1 and 5.0.0.) @@ -157,12 +130,23 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); # define VAR_NOCLOBBERED(var) var #endif +static inline void +rb_ec_vm_lock_rec_check(const rb_execution_context_t *ec, unsigned int recorded_lock_rec) +{ + unsigned int current_lock_rec = rb_ec_vm_lock_rec(ec); + if (current_lock_rec != recorded_lock_rec) { + rb_ec_vm_lock_rec_release(ec, recorded_lock_rec, current_lock_rec); + } +} + /* clear ec->tag->state, and return the value */ static inline int rb_ec_tag_state(const rb_execution_context_t *ec) { - enum ruby_tag_type state = ec->tag->state; - ec->tag->state = TAG_NONE; + struct rb_vm_tag *tag = ec->tag; + enum ruby_tag_type state = tag->state; + tag->state = TAG_NONE; + rb_ec_vm_lock_rec_check(ec, tag->lock_rec); return state; } @@ -189,11 +173,30 @@ rb_ec_tag_jump(const rb_execution_context_t *ec, enum ruby_tag_type st) #define CREF_FL_PUSHED_BY_EVAL IMEMO_FL_USER1 #define CREF_FL_OMOD_SHARED IMEMO_FL_USER2 +#define CREF_FL_SINGLETON IMEMO_FL_USER3 + +static inline int CREF_SINGLETON(const rb_cref_t *cref); static inline VALUE CREF_CLASS(const rb_cref_t *cref) { - return cref->klass; + if (CREF_SINGLETON(cref)) { + return CLASS_OF(cref->klass_or_self); + } + else { + return cref->klass_or_self; + } +} + +static inline VALUE +CREF_CLASS_FOR_DEFINITION(const rb_cref_t *cref) +{ + if (CREF_SINGLETON(cref)) { + return rb_singleton_class(cref->klass_or_self); + } + else { + return cref->klass_or_self; + } } static inline rb_cref_t * @@ -232,6 +235,18 @@ CREF_PUSHED_BY_EVAL_SET(rb_cref_t *cref) cref->flags |= CREF_FL_PUSHED_BY_EVAL; } +static inline int +CREF_SINGLETON(const rb_cref_t *cref) +{ + return cref->flags & CREF_FL_SINGLETON; +} + +static inline void +CREF_SINGLETON_SET(rb_cref_t *cref) +{ + cref->flags |= CREF_FL_SINGLETON; +} + static inline int CREF_OMOD_SHARED(const rb_cref_t *cref) { @@ -268,7 +283,7 @@ VALUE rb_make_exception(int argc, const VALUE *argv); NORETURN(void rb_method_name_error(VALUE, VALUE)); -NORETURN(void rb_fiber_start(void)); +NORETURN(void rb_fiber_start(rb_fiber_t*)); NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t)); NORETURN(void rb_print_undef_str(VALUE, VALUE)); @@ -281,17 +296,25 @@ 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); void rb_vm_set_progname(VALUE filename); -void rb_thread_terminate_all(void); VALUE rb_vm_cbase(void); /* vm_backtrace.c */ 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); +VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal); #ifndef CharNext /* defined as CharNext[AW] on Windows. */ # ifdef HAVE_MBLEN -# define CharNext(p) ((p) + mblen((p), RUBY_MBCHAR_MAXSIZE)) +# define CharNext(p) rb_char_next(p) +static inline char * +rb_char_next(const char *p) +{ + if (p) { + int len = mblen(p, RUBY_MBCHAR_MAXSIZE); + p += len > 0 ? len : 1; + } + return (char *)p; +} # else # define CharNext(p) ((p) + 1) # endif diff --git a/ruby/eval_jump.c b/ruby/eval_jump.c index 75d4ad020..2ea73b0da 100644 --- a/ruby/eval_jump.c +++ b/ruby/eval_jump.c @@ -48,7 +48,7 @@ rb_f_at_exit(VALUE _) } struct end_proc_data { - void (*func) (); + void (*func) (VALUE); VALUE data; struct end_proc_data *next; }; diff --git a/ruby/ext/-test-/RUBY_ALIGNOF/c.c b/ruby/ext/-test-/RUBY_ALIGNOF/c.c new file mode 100644 index 000000000..7a9f7cb49 --- /dev/null +++ b/ruby/ext/-test-/RUBY_ALIGNOF/c.c @@ -0,0 +1,15 @@ +#include "ruby.h" +#include + +struct T { + char _; + double t; +}; + +RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(struct T, t)); + +void +Init_RUBY_ALIGNOF(void) +{ + // Windows linker mandates this symbol to exist. +} diff --git a/ruby/ext/-test-/RUBY_ALIGNOF/cpp.cpp b/ruby/ext/-test-/RUBY_ALIGNOF/cpp.cpp new file mode 100644 index 000000000..ed76d49b9 --- /dev/null +++ b/ruby/ext/-test-/RUBY_ALIGNOF/cpp.cpp @@ -0,0 +1,9 @@ +#include "ruby.h" +#include + +struct T { + char _; + double t; +}; + +RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(T, t)); diff --git a/ruby/ext/-test-/RUBY_ALIGNOF/depend b/ruby/ext/-test-/RUBY_ALIGNOF/depend new file mode 100644 index 000000000..f12fdf59c --- /dev/null +++ b/ruby/ext/-test-/RUBY_ALIGNOF/depend @@ -0,0 +1,161 @@ +# AUTOGENERATED DEPENDENCIES START +c.o: $(RUBY_EXTCONF_H) +c.o: $(arch_hdrdir)/ruby/config.h +c.o: $(hdrdir)/ruby.h +c.o: $(hdrdir)/ruby/assert.h +c.o: $(hdrdir)/ruby/backward.h +c.o: $(hdrdir)/ruby/backward/2/assume.h +c.o: $(hdrdir)/ruby/backward/2/attributes.h +c.o: $(hdrdir)/ruby/backward/2/bool.h +c.o: $(hdrdir)/ruby/backward/2/inttypes.h +c.o: $(hdrdir)/ruby/backward/2/limits.h +c.o: $(hdrdir)/ruby/backward/2/long_long.h +c.o: $(hdrdir)/ruby/backward/2/stdalign.h +c.o: $(hdrdir)/ruby/backward/2/stdarg.h +c.o: $(hdrdir)/ruby/defines.h +c.o: $(hdrdir)/ruby/intern.h +c.o: $(hdrdir)/ruby/internal/anyargs.h +c.o: $(hdrdir)/ruby/internal/arithmetic.h +c.o: $(hdrdir)/ruby/internal/arithmetic/char.h +c.o: $(hdrdir)/ruby/internal/arithmetic/double.h +c.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +c.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/int.h +c.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/long.h +c.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +c.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/short.h +c.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +c.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +c.o: $(hdrdir)/ruby/internal/assume.h +c.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +c.o: $(hdrdir)/ruby/internal/attr/artificial.h +c.o: $(hdrdir)/ruby/internal/attr/cold.h +c.o: $(hdrdir)/ruby/internal/attr/const.h +c.o: $(hdrdir)/ruby/internal/attr/constexpr.h +c.o: $(hdrdir)/ruby/internal/attr/deprecated.h +c.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +c.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +c.o: $(hdrdir)/ruby/internal/attr/error.h +c.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +c.o: $(hdrdir)/ruby/internal/attr/forceinline.h +c.o: $(hdrdir)/ruby/internal/attr/format.h +c.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +c.o: $(hdrdir)/ruby/internal/attr/noalias.h +c.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +c.o: $(hdrdir)/ruby/internal/attr/noexcept.h +c.o: $(hdrdir)/ruby/internal/attr/noinline.h +c.o: $(hdrdir)/ruby/internal/attr/nonnull.h +c.o: $(hdrdir)/ruby/internal/attr/noreturn.h +c.o: $(hdrdir)/ruby/internal/attr/pure.h +c.o: $(hdrdir)/ruby/internal/attr/restrict.h +c.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +c.o: $(hdrdir)/ruby/internal/attr/warning.h +c.o: $(hdrdir)/ruby/internal/attr/weakref.h +c.o: $(hdrdir)/ruby/internal/cast.h +c.o: $(hdrdir)/ruby/internal/compiler_is.h +c.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +c.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +c.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +c.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +c.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +c.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +c.o: $(hdrdir)/ruby/internal/compiler_since.h +c.o: $(hdrdir)/ruby/internal/config.h +c.o: $(hdrdir)/ruby/internal/constant_p.h +c.o: $(hdrdir)/ruby/internal/core.h +c.o: $(hdrdir)/ruby/internal/core/rarray.h +c.o: $(hdrdir)/ruby/internal/core/rbasic.h +c.o: $(hdrdir)/ruby/internal/core/rbignum.h +c.o: $(hdrdir)/ruby/internal/core/rclass.h +c.o: $(hdrdir)/ruby/internal/core/rdata.h +c.o: $(hdrdir)/ruby/internal/core/rfile.h +c.o: $(hdrdir)/ruby/internal/core/rhash.h +c.o: $(hdrdir)/ruby/internal/core/robject.h +c.o: $(hdrdir)/ruby/internal/core/rregexp.h +c.o: $(hdrdir)/ruby/internal/core/rstring.h +c.o: $(hdrdir)/ruby/internal/core/rstruct.h +c.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +c.o: $(hdrdir)/ruby/internal/ctype.h +c.o: $(hdrdir)/ruby/internal/dllexport.h +c.o: $(hdrdir)/ruby/internal/dosish.h +c.o: $(hdrdir)/ruby/internal/error.h +c.o: $(hdrdir)/ruby/internal/eval.h +c.o: $(hdrdir)/ruby/internal/event.h +c.o: $(hdrdir)/ruby/internal/fl_type.h +c.o: $(hdrdir)/ruby/internal/gc.h +c.o: $(hdrdir)/ruby/internal/glob.h +c.o: $(hdrdir)/ruby/internal/globals.h +c.o: $(hdrdir)/ruby/internal/has/attribute.h +c.o: $(hdrdir)/ruby/internal/has/builtin.h +c.o: $(hdrdir)/ruby/internal/has/c_attribute.h +c.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +c.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +c.o: $(hdrdir)/ruby/internal/has/extension.h +c.o: $(hdrdir)/ruby/internal/has/feature.h +c.o: $(hdrdir)/ruby/internal/has/warning.h +c.o: $(hdrdir)/ruby/internal/intern/array.h +c.o: $(hdrdir)/ruby/internal/intern/bignum.h +c.o: $(hdrdir)/ruby/internal/intern/class.h +c.o: $(hdrdir)/ruby/internal/intern/compar.h +c.o: $(hdrdir)/ruby/internal/intern/complex.h +c.o: $(hdrdir)/ruby/internal/intern/cont.h +c.o: $(hdrdir)/ruby/internal/intern/dir.h +c.o: $(hdrdir)/ruby/internal/intern/enum.h +c.o: $(hdrdir)/ruby/internal/intern/enumerator.h +c.o: $(hdrdir)/ruby/internal/intern/error.h +c.o: $(hdrdir)/ruby/internal/intern/eval.h +c.o: $(hdrdir)/ruby/internal/intern/file.h +c.o: $(hdrdir)/ruby/internal/intern/gc.h +c.o: $(hdrdir)/ruby/internal/intern/hash.h +c.o: $(hdrdir)/ruby/internal/intern/io.h +c.o: $(hdrdir)/ruby/internal/intern/load.h +c.o: $(hdrdir)/ruby/internal/intern/marshal.h +c.o: $(hdrdir)/ruby/internal/intern/numeric.h +c.o: $(hdrdir)/ruby/internal/intern/object.h +c.o: $(hdrdir)/ruby/internal/intern/parse.h +c.o: $(hdrdir)/ruby/internal/intern/proc.h +c.o: $(hdrdir)/ruby/internal/intern/process.h +c.o: $(hdrdir)/ruby/internal/intern/random.h +c.o: $(hdrdir)/ruby/internal/intern/range.h +c.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +c.o: $(hdrdir)/ruby/internal/intern/sprintf.h +c.o: $(hdrdir)/ruby/internal/intern/string.h +c.o: $(hdrdir)/ruby/internal/intern/struct.h +c.o: $(hdrdir)/ruby/internal/intern/thread.h +c.o: $(hdrdir)/ruby/internal/intern/time.h +c.o: $(hdrdir)/ruby/internal/intern/variable.h +c.o: $(hdrdir)/ruby/internal/intern/vm.h +c.o: $(hdrdir)/ruby/internal/interpreter.h +c.o: $(hdrdir)/ruby/internal/iterator.h +c.o: $(hdrdir)/ruby/internal/memory.h +c.o: $(hdrdir)/ruby/internal/method.h +c.o: $(hdrdir)/ruby/internal/module.h +c.o: $(hdrdir)/ruby/internal/newobj.h +c.o: $(hdrdir)/ruby/internal/rgengc.h +c.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +c.o: $(hdrdir)/ruby/internal/value.h +c.o: $(hdrdir)/ruby/internal/value_type.h +c.o: $(hdrdir)/ruby/internal/variable.h +c.o: $(hdrdir)/ruby/internal/warning_push.h +c.o: $(hdrdir)/ruby/internal/xmalloc.h +c.o: $(hdrdir)/ruby/missing.h +c.o: $(hdrdir)/ruby/ruby.h +c.o: $(hdrdir)/ruby/st.h +c.o: $(hdrdir)/ruby/subst.h +c.o: c.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/RUBY_ALIGNOF/extconf.rb b/ruby/ext/-test-/RUBY_ALIGNOF/extconf.rb new file mode 100644 index 000000000..98a370e98 --- /dev/null +++ b/ruby/ext/-test-/RUBY_ALIGNOF/extconf.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: false +$objs = %W"c.#$OBJEXT" + +$objs << "cpp.#$OBJEXT" if MakeMakefile['C++'].have_devel? + +create_makefile("-test-/RUBY_ALIGNOF") diff --git a/ruby/ext/-test-/arith_seq/extract/depend b/ruby/ext/-test-/arith_seq/extract/depend index bb0719941..ac7782527 100644 --- a/ruby/ext/-test-/arith_seq/extract/depend +++ b/ruby/ext/-test-/arith_seq/extract/depend @@ -3,8 +3,155 @@ extract.o: $(RUBY_EXTCONF_H) extract.o: $(arch_hdrdir)/ruby/config.h extract.o: $(hdrdir)/ruby/assert.h extract.o: $(hdrdir)/ruby/backward.h +extract.o: $(hdrdir)/ruby/backward/2/assume.h +extract.o: $(hdrdir)/ruby/backward/2/attributes.h +extract.o: $(hdrdir)/ruby/backward/2/bool.h +extract.o: $(hdrdir)/ruby/backward/2/inttypes.h +extract.o: $(hdrdir)/ruby/backward/2/limits.h +extract.o: $(hdrdir)/ruby/backward/2/long_long.h +extract.o: $(hdrdir)/ruby/backward/2/stdalign.h +extract.o: $(hdrdir)/ruby/backward/2/stdarg.h extract.o: $(hdrdir)/ruby/defines.h extract.o: $(hdrdir)/ruby/intern.h +extract.o: $(hdrdir)/ruby/internal/anyargs.h +extract.o: $(hdrdir)/ruby/internal/arithmetic.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/char.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/double.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/int.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/long.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/short.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +extract.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +extract.o: $(hdrdir)/ruby/internal/assume.h +extract.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +extract.o: $(hdrdir)/ruby/internal/attr/artificial.h +extract.o: $(hdrdir)/ruby/internal/attr/cold.h +extract.o: $(hdrdir)/ruby/internal/attr/const.h +extract.o: $(hdrdir)/ruby/internal/attr/constexpr.h +extract.o: $(hdrdir)/ruby/internal/attr/deprecated.h +extract.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +extract.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +extract.o: $(hdrdir)/ruby/internal/attr/error.h +extract.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +extract.o: $(hdrdir)/ruby/internal/attr/forceinline.h +extract.o: $(hdrdir)/ruby/internal/attr/format.h +extract.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +extract.o: $(hdrdir)/ruby/internal/attr/noalias.h +extract.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +extract.o: $(hdrdir)/ruby/internal/attr/noexcept.h +extract.o: $(hdrdir)/ruby/internal/attr/noinline.h +extract.o: $(hdrdir)/ruby/internal/attr/nonnull.h +extract.o: $(hdrdir)/ruby/internal/attr/noreturn.h +extract.o: $(hdrdir)/ruby/internal/attr/pure.h +extract.o: $(hdrdir)/ruby/internal/attr/restrict.h +extract.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +extract.o: $(hdrdir)/ruby/internal/attr/warning.h +extract.o: $(hdrdir)/ruby/internal/attr/weakref.h +extract.o: $(hdrdir)/ruby/internal/cast.h +extract.o: $(hdrdir)/ruby/internal/compiler_is.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +extract.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +extract.o: $(hdrdir)/ruby/internal/compiler_since.h +extract.o: $(hdrdir)/ruby/internal/config.h +extract.o: $(hdrdir)/ruby/internal/constant_p.h +extract.o: $(hdrdir)/ruby/internal/core.h +extract.o: $(hdrdir)/ruby/internal/core/rarray.h +extract.o: $(hdrdir)/ruby/internal/core/rbasic.h +extract.o: $(hdrdir)/ruby/internal/core/rbignum.h +extract.o: $(hdrdir)/ruby/internal/core/rclass.h +extract.o: $(hdrdir)/ruby/internal/core/rdata.h +extract.o: $(hdrdir)/ruby/internal/core/rfile.h +extract.o: $(hdrdir)/ruby/internal/core/rhash.h +extract.o: $(hdrdir)/ruby/internal/core/robject.h +extract.o: $(hdrdir)/ruby/internal/core/rregexp.h +extract.o: $(hdrdir)/ruby/internal/core/rstring.h +extract.o: $(hdrdir)/ruby/internal/core/rstruct.h +extract.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +extract.o: $(hdrdir)/ruby/internal/ctype.h +extract.o: $(hdrdir)/ruby/internal/dllexport.h +extract.o: $(hdrdir)/ruby/internal/dosish.h +extract.o: $(hdrdir)/ruby/internal/error.h +extract.o: $(hdrdir)/ruby/internal/eval.h +extract.o: $(hdrdir)/ruby/internal/event.h +extract.o: $(hdrdir)/ruby/internal/fl_type.h +extract.o: $(hdrdir)/ruby/internal/gc.h +extract.o: $(hdrdir)/ruby/internal/glob.h +extract.o: $(hdrdir)/ruby/internal/globals.h +extract.o: $(hdrdir)/ruby/internal/has/attribute.h +extract.o: $(hdrdir)/ruby/internal/has/builtin.h +extract.o: $(hdrdir)/ruby/internal/has/c_attribute.h +extract.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +extract.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +extract.o: $(hdrdir)/ruby/internal/has/extension.h +extract.o: $(hdrdir)/ruby/internal/has/feature.h +extract.o: $(hdrdir)/ruby/internal/has/warning.h +extract.o: $(hdrdir)/ruby/internal/intern/array.h +extract.o: $(hdrdir)/ruby/internal/intern/bignum.h +extract.o: $(hdrdir)/ruby/internal/intern/class.h +extract.o: $(hdrdir)/ruby/internal/intern/compar.h +extract.o: $(hdrdir)/ruby/internal/intern/complex.h +extract.o: $(hdrdir)/ruby/internal/intern/cont.h +extract.o: $(hdrdir)/ruby/internal/intern/dir.h +extract.o: $(hdrdir)/ruby/internal/intern/enum.h +extract.o: $(hdrdir)/ruby/internal/intern/enumerator.h +extract.o: $(hdrdir)/ruby/internal/intern/error.h +extract.o: $(hdrdir)/ruby/internal/intern/eval.h +extract.o: $(hdrdir)/ruby/internal/intern/file.h +extract.o: $(hdrdir)/ruby/internal/intern/gc.h +extract.o: $(hdrdir)/ruby/internal/intern/hash.h +extract.o: $(hdrdir)/ruby/internal/intern/io.h +extract.o: $(hdrdir)/ruby/internal/intern/load.h +extract.o: $(hdrdir)/ruby/internal/intern/marshal.h +extract.o: $(hdrdir)/ruby/internal/intern/numeric.h +extract.o: $(hdrdir)/ruby/internal/intern/object.h +extract.o: $(hdrdir)/ruby/internal/intern/parse.h +extract.o: $(hdrdir)/ruby/internal/intern/proc.h +extract.o: $(hdrdir)/ruby/internal/intern/process.h +extract.o: $(hdrdir)/ruby/internal/intern/random.h +extract.o: $(hdrdir)/ruby/internal/intern/range.h +extract.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +extract.o: $(hdrdir)/ruby/internal/intern/sprintf.h +extract.o: $(hdrdir)/ruby/internal/intern/string.h +extract.o: $(hdrdir)/ruby/internal/intern/struct.h +extract.o: $(hdrdir)/ruby/internal/intern/thread.h +extract.o: $(hdrdir)/ruby/internal/intern/time.h +extract.o: $(hdrdir)/ruby/internal/intern/variable.h +extract.o: $(hdrdir)/ruby/internal/intern/vm.h +extract.o: $(hdrdir)/ruby/internal/interpreter.h +extract.o: $(hdrdir)/ruby/internal/iterator.h +extract.o: $(hdrdir)/ruby/internal/memory.h +extract.o: $(hdrdir)/ruby/internal/method.h +extract.o: $(hdrdir)/ruby/internal/module.h +extract.o: $(hdrdir)/ruby/internal/newobj.h +extract.o: $(hdrdir)/ruby/internal/rgengc.h +extract.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +extract.o: $(hdrdir)/ruby/internal/value.h +extract.o: $(hdrdir)/ruby/internal/value_type.h +extract.o: $(hdrdir)/ruby/internal/variable.h +extract.o: $(hdrdir)/ruby/internal/warning_push.h +extract.o: $(hdrdir)/ruby/internal/xmalloc.h extract.o: $(hdrdir)/ruby/missing.h extract.o: $(hdrdir)/ruby/ruby.h extract.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/array/concat/depend b/ruby/ext/-test-/array/concat/depend new file mode 100644 index 000000000..e1d49bc64 --- /dev/null +++ b/ruby/ext/-test-/array/concat/depend @@ -0,0 +1,161 @@ +# AUTOGENERATED DEPENDENCIES START +to_ary_concat.o: $(RUBY_EXTCONF_H) +to_ary_concat.o: $(arch_hdrdir)/ruby/config.h +to_ary_concat.o: $(hdrdir)/ruby.h +to_ary_concat.o: $(hdrdir)/ruby/assert.h +to_ary_concat.o: $(hdrdir)/ruby/backward.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/assume.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/attributes.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/bool.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/inttypes.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/limits.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/long_long.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdalign.h +to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdarg.h +to_ary_concat.o: $(hdrdir)/ruby/defines.h +to_ary_concat.o: $(hdrdir)/ruby/intern.h +to_ary_concat.o: $(hdrdir)/ruby/internal/anyargs.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/char.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/double.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/int.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/short.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +to_ary_concat.o: $(hdrdir)/ruby/internal/assume.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/artificial.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/cold.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/const.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/constexpr.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/deprecated.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/error.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/forceinline.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/format.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noalias.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noexcept.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noinline.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nonnull.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noreturn.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/pure.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/restrict.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/warning.h +to_ary_concat.o: $(hdrdir)/ruby/internal/attr/weakref.h +to_ary_concat.o: $(hdrdir)/ruby/internal/cast.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_since.h +to_ary_concat.o: $(hdrdir)/ruby/internal/config.h +to_ary_concat.o: $(hdrdir)/ruby/internal/constant_p.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rarray.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbasic.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbignum.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rclass.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rdata.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rfile.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rhash.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/robject.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rregexp.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstring.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstruct.h +to_ary_concat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +to_ary_concat.o: $(hdrdir)/ruby/internal/ctype.h +to_ary_concat.o: $(hdrdir)/ruby/internal/dllexport.h +to_ary_concat.o: $(hdrdir)/ruby/internal/dosish.h +to_ary_concat.o: $(hdrdir)/ruby/internal/error.h +to_ary_concat.o: $(hdrdir)/ruby/internal/eval.h +to_ary_concat.o: $(hdrdir)/ruby/internal/event.h +to_ary_concat.o: $(hdrdir)/ruby/internal/fl_type.h +to_ary_concat.o: $(hdrdir)/ruby/internal/gc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/glob.h +to_ary_concat.o: $(hdrdir)/ruby/internal/globals.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/attribute.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/builtin.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/c_attribute.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/extension.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/feature.h +to_ary_concat.o: $(hdrdir)/ruby/internal/has/warning.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/array.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/bignum.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/class.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/compar.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/complex.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/cont.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/dir.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enum.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enumerator.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/error.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/eval.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/file.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/gc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/hash.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/io.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/load.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/marshal.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/numeric.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/object.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/parse.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/proc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/process.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/random.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/range.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/sprintf.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/string.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/struct.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/thread.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/time.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/variable.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/vm.h +to_ary_concat.o: $(hdrdir)/ruby/internal/interpreter.h +to_ary_concat.o: $(hdrdir)/ruby/internal/iterator.h +to_ary_concat.o: $(hdrdir)/ruby/internal/memory.h +to_ary_concat.o: $(hdrdir)/ruby/internal/method.h +to_ary_concat.o: $(hdrdir)/ruby/internal/module.h +to_ary_concat.o: $(hdrdir)/ruby/internal/newobj.h +to_ary_concat.o: $(hdrdir)/ruby/internal/rgengc.h +to_ary_concat.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +to_ary_concat.o: $(hdrdir)/ruby/internal/value.h +to_ary_concat.o: $(hdrdir)/ruby/internal/value_type.h +to_ary_concat.o: $(hdrdir)/ruby/internal/variable.h +to_ary_concat.o: $(hdrdir)/ruby/internal/warning_push.h +to_ary_concat.o: $(hdrdir)/ruby/internal/xmalloc.h +to_ary_concat.o: $(hdrdir)/ruby/missing.h +to_ary_concat.o: $(hdrdir)/ruby/ruby.h +to_ary_concat.o: $(hdrdir)/ruby/st.h +to_ary_concat.o: $(hdrdir)/ruby/subst.h +to_ary_concat.o: to_ary_concat.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/array/concat/extconf.rb b/ruby/ext/-test-/array/concat/extconf.rb new file mode 100644 index 000000000..cdd79126c --- /dev/null +++ b/ruby/ext/-test-/array/concat/extconf.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: false +create_makefile("-test-/array/to_ary_concat") diff --git a/ruby/ext/-test-/array/concat/to_ary_concat.c b/ruby/ext/-test-/array/concat/to_ary_concat.c new file mode 100644 index 000000000..07a96d390 --- /dev/null +++ b/ruby/ext/-test-/array/concat/to_ary_concat.c @@ -0,0 +1,38 @@ +#include "ruby.h" + +// Bar + +typedef struct { + int dummy; +} Bar; + +static rb_data_type_t Bar_type = { + "Bar", + {NULL, RUBY_TYPED_DEFAULT_FREE, NULL }, +}; + +static VALUE +Bar_alloc(VALUE klass) +{ + return TypedData_Wrap_Struct(klass, &Bar_type, NULL); +} + +static VALUE +Bar_to_ary(VALUE _self) +{ + VALUE ary = rb_ary_new2(2); + VALUE foo = rb_ary_new2(0); + rb_ary_push(ary, foo); + rb_ary_push(ary, foo); + rb_ary_push(ary, foo); + return ary; +} + +void +Init_to_ary_concat(void) +{ + VALUE mBug = rb_define_module("Bug"); + VALUE bar = rb_define_class_under(mBug, "Bar", rb_cObject); + rb_define_alloc_func(bar, Bar_alloc); + rb_define_method(bar, "to_ary", Bar_to_ary, 0); +} diff --git a/ruby/ext/-test-/array/resize/depend b/ruby/ext/-test-/array/resize/depend index a03cc47d5..bd0b1bf28 100644 --- a/ruby/ext/-test-/array/resize/depend +++ b/ruby/ext/-test-/array/resize/depend @@ -3,8 +3,155 @@ resize.o: $(RUBY_EXTCONF_H) resize.o: $(arch_hdrdir)/ruby/config.h resize.o: $(hdrdir)/ruby/assert.h resize.o: $(hdrdir)/ruby/backward.h +resize.o: $(hdrdir)/ruby/backward/2/assume.h +resize.o: $(hdrdir)/ruby/backward/2/attributes.h +resize.o: $(hdrdir)/ruby/backward/2/bool.h +resize.o: $(hdrdir)/ruby/backward/2/inttypes.h +resize.o: $(hdrdir)/ruby/backward/2/limits.h +resize.o: $(hdrdir)/ruby/backward/2/long_long.h +resize.o: $(hdrdir)/ruby/backward/2/stdalign.h +resize.o: $(hdrdir)/ruby/backward/2/stdarg.h resize.o: $(hdrdir)/ruby/defines.h resize.o: $(hdrdir)/ruby/intern.h +resize.o: $(hdrdir)/ruby/internal/anyargs.h +resize.o: $(hdrdir)/ruby/internal/arithmetic.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/char.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/double.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/int.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/long.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/short.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +resize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +resize.o: $(hdrdir)/ruby/internal/assume.h +resize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +resize.o: $(hdrdir)/ruby/internal/attr/artificial.h +resize.o: $(hdrdir)/ruby/internal/attr/cold.h +resize.o: $(hdrdir)/ruby/internal/attr/const.h +resize.o: $(hdrdir)/ruby/internal/attr/constexpr.h +resize.o: $(hdrdir)/ruby/internal/attr/deprecated.h +resize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +resize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +resize.o: $(hdrdir)/ruby/internal/attr/error.h +resize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +resize.o: $(hdrdir)/ruby/internal/attr/forceinline.h +resize.o: $(hdrdir)/ruby/internal/attr/format.h +resize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +resize.o: $(hdrdir)/ruby/internal/attr/noalias.h +resize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +resize.o: $(hdrdir)/ruby/internal/attr/noexcept.h +resize.o: $(hdrdir)/ruby/internal/attr/noinline.h +resize.o: $(hdrdir)/ruby/internal/attr/nonnull.h +resize.o: $(hdrdir)/ruby/internal/attr/noreturn.h +resize.o: $(hdrdir)/ruby/internal/attr/pure.h +resize.o: $(hdrdir)/ruby/internal/attr/restrict.h +resize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +resize.o: $(hdrdir)/ruby/internal/attr/warning.h +resize.o: $(hdrdir)/ruby/internal/attr/weakref.h +resize.o: $(hdrdir)/ruby/internal/cast.h +resize.o: $(hdrdir)/ruby/internal/compiler_is.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +resize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +resize.o: $(hdrdir)/ruby/internal/compiler_since.h +resize.o: $(hdrdir)/ruby/internal/config.h +resize.o: $(hdrdir)/ruby/internal/constant_p.h +resize.o: $(hdrdir)/ruby/internal/core.h +resize.o: $(hdrdir)/ruby/internal/core/rarray.h +resize.o: $(hdrdir)/ruby/internal/core/rbasic.h +resize.o: $(hdrdir)/ruby/internal/core/rbignum.h +resize.o: $(hdrdir)/ruby/internal/core/rclass.h +resize.o: $(hdrdir)/ruby/internal/core/rdata.h +resize.o: $(hdrdir)/ruby/internal/core/rfile.h +resize.o: $(hdrdir)/ruby/internal/core/rhash.h +resize.o: $(hdrdir)/ruby/internal/core/robject.h +resize.o: $(hdrdir)/ruby/internal/core/rregexp.h +resize.o: $(hdrdir)/ruby/internal/core/rstring.h +resize.o: $(hdrdir)/ruby/internal/core/rstruct.h +resize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +resize.o: $(hdrdir)/ruby/internal/ctype.h +resize.o: $(hdrdir)/ruby/internal/dllexport.h +resize.o: $(hdrdir)/ruby/internal/dosish.h +resize.o: $(hdrdir)/ruby/internal/error.h +resize.o: $(hdrdir)/ruby/internal/eval.h +resize.o: $(hdrdir)/ruby/internal/event.h +resize.o: $(hdrdir)/ruby/internal/fl_type.h +resize.o: $(hdrdir)/ruby/internal/gc.h +resize.o: $(hdrdir)/ruby/internal/glob.h +resize.o: $(hdrdir)/ruby/internal/globals.h +resize.o: $(hdrdir)/ruby/internal/has/attribute.h +resize.o: $(hdrdir)/ruby/internal/has/builtin.h +resize.o: $(hdrdir)/ruby/internal/has/c_attribute.h +resize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +resize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +resize.o: $(hdrdir)/ruby/internal/has/extension.h +resize.o: $(hdrdir)/ruby/internal/has/feature.h +resize.o: $(hdrdir)/ruby/internal/has/warning.h +resize.o: $(hdrdir)/ruby/internal/intern/array.h +resize.o: $(hdrdir)/ruby/internal/intern/bignum.h +resize.o: $(hdrdir)/ruby/internal/intern/class.h +resize.o: $(hdrdir)/ruby/internal/intern/compar.h +resize.o: $(hdrdir)/ruby/internal/intern/complex.h +resize.o: $(hdrdir)/ruby/internal/intern/cont.h +resize.o: $(hdrdir)/ruby/internal/intern/dir.h +resize.o: $(hdrdir)/ruby/internal/intern/enum.h +resize.o: $(hdrdir)/ruby/internal/intern/enumerator.h +resize.o: $(hdrdir)/ruby/internal/intern/error.h +resize.o: $(hdrdir)/ruby/internal/intern/eval.h +resize.o: $(hdrdir)/ruby/internal/intern/file.h +resize.o: $(hdrdir)/ruby/internal/intern/gc.h +resize.o: $(hdrdir)/ruby/internal/intern/hash.h +resize.o: $(hdrdir)/ruby/internal/intern/io.h +resize.o: $(hdrdir)/ruby/internal/intern/load.h +resize.o: $(hdrdir)/ruby/internal/intern/marshal.h +resize.o: $(hdrdir)/ruby/internal/intern/numeric.h +resize.o: $(hdrdir)/ruby/internal/intern/object.h +resize.o: $(hdrdir)/ruby/internal/intern/parse.h +resize.o: $(hdrdir)/ruby/internal/intern/proc.h +resize.o: $(hdrdir)/ruby/internal/intern/process.h +resize.o: $(hdrdir)/ruby/internal/intern/random.h +resize.o: $(hdrdir)/ruby/internal/intern/range.h +resize.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h +resize.o: $(hdrdir)/ruby/internal/intern/string.h +resize.o: $(hdrdir)/ruby/internal/intern/struct.h +resize.o: $(hdrdir)/ruby/internal/intern/thread.h +resize.o: $(hdrdir)/ruby/internal/intern/time.h +resize.o: $(hdrdir)/ruby/internal/intern/variable.h +resize.o: $(hdrdir)/ruby/internal/intern/vm.h +resize.o: $(hdrdir)/ruby/internal/interpreter.h +resize.o: $(hdrdir)/ruby/internal/iterator.h +resize.o: $(hdrdir)/ruby/internal/memory.h +resize.o: $(hdrdir)/ruby/internal/method.h +resize.o: $(hdrdir)/ruby/internal/module.h +resize.o: $(hdrdir)/ruby/internal/newobj.h +resize.o: $(hdrdir)/ruby/internal/rgengc.h +resize.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +resize.o: $(hdrdir)/ruby/internal/value.h +resize.o: $(hdrdir)/ruby/internal/value_type.h +resize.o: $(hdrdir)/ruby/internal/variable.h +resize.o: $(hdrdir)/ruby/internal/warning_push.h +resize.o: $(hdrdir)/ruby/internal/xmalloc.h resize.o: $(hdrdir)/ruby/missing.h resize.o: $(hdrdir)/ruby/ruby.h resize.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/array/resize/resize.c b/ruby/ext/-test-/array/resize/resize.c index 08bcee3e7..cfe910ebe 100644 --- a/ruby/ext/-test-/array/resize/resize.c +++ b/ruby/ext/-test-/array/resize/resize.c @@ -1,7 +1,7 @@ #include "ruby/ruby.h" static VALUE -ary_resize(VALUE ary, VALUE len) +ary_resize(VALUE klass, VALUE ary, VALUE len) { rb_ary_resize(ary, NUM2LONG(len)); return ary; @@ -10,5 +10,7 @@ ary_resize(VALUE ary, VALUE len) void Init_resize(void) { - rb_define_method(rb_cArray, "__resize__", ary_resize, 1); + VALUE mBug = rb_define_module("Bug"); + VALUE klass = rb_define_class_under(mBug, "Array", rb_cObject); + rb_define_singleton_method(klass, "__resize__", ary_resize, 2); } diff --git a/ruby/ext/-test-/auto_ext.rb b/ruby/ext/-test-/auto_ext.rb index 71606a9dd..58c49c177 100644 --- a/ruby/ext/-test-/auto_ext.rb +++ b/ruby/ext/-test-/auto_ext.rb @@ -6,5 +6,6 @@ def auto_ext(feat = $0[%r[/ext/(-test-/.*)/extconf.rb\z], 1], inc: false) inits.delete("init") inits.map! {|s|"X(#{s})"} $defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\"" + create_header create_makefile(feat) end diff --git a/ruby/ext/-test-/bignum/big2str.c b/ruby/ext/-test-/bignum/big2str.c index ec4bde291..255e8ad72 100644 --- a/ruby/ext/-test-/bignum/big2str.c +++ b/ruby/ext/-test-/bignum/big2str.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE big(VALUE x) @@ -12,7 +12,7 @@ big(VALUE x) } static VALUE -big2str_generic(VALUE x, VALUE vbase) +big2str_generic(VALUE klass, VALUE x, VALUE vbase) { int base = NUM2INT(vbase); if (base < 2 || 36 < base) @@ -23,7 +23,7 @@ big2str_generic(VALUE x, VALUE vbase) #define POW2_P(x) (((x)&((x)-1))==0) static VALUE -big2str_poweroftwo(VALUE x, VALUE vbase) +big2str_poweroftwo(VALUE klass, VALUE x, VALUE vbase) { int base = NUM2INT(vbase); if (base < 2 || 36 < base || !POW2_P(base)) @@ -33,7 +33,7 @@ big2str_poweroftwo(VALUE x, VALUE vbase) #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE -big2str_gmp(VALUE x, VALUE vbase) +big2str_gmp(VALUE klass, VALUE x, VALUE vbase) { int base = NUM2INT(vbase); if (base < 2 || 36 < base) @@ -47,7 +47,7 @@ big2str_gmp(VALUE x, VALUE vbase) void Init_big2str(VALUE klass) { - rb_define_method(rb_cInteger, "big2str_generic", big2str_generic, 1); - rb_define_method(rb_cInteger, "big2str_poweroftwo", big2str_poweroftwo, 1); - rb_define_method(rb_cInteger, "big2str_gmp", big2str_gmp, 1); + rb_define_singleton_method(klass, "big2str_generic", big2str_generic, 2); + rb_define_singleton_method(klass, "big2str_poweroftwo", big2str_poweroftwo, 2); + rb_define_singleton_method(klass, "big2str_gmp", big2str_gmp, 2); } diff --git a/ruby/ext/-test-/bignum/bigzero.c b/ruby/ext/-test-/bignum/bigzero.c index 35117db7a..e2bfebcd3 100644 --- a/ruby/ext/-test-/bignum/bigzero.c +++ b/ruby/ext/-test-/bignum/bigzero.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE bug_big_zero(VALUE self, VALUE length) diff --git a/ruby/ext/-test-/bignum/depend b/ruby/ext/-test-/bignum/depend index 38c9f6114..28edc15f2 100644 --- a/ruby/ext/-test-/bignum/depend +++ b/ruby/ext/-test-/bignum/depend @@ -1,50 +1,635 @@ # AUTOGENERATED DEPENDENCIES START big2str.o: $(RUBY_EXTCONF_H) big2str.o: $(arch_hdrdir)/ruby/config.h -big2str.o: $(hdrdir)/ruby.h big2str.o: $(hdrdir)/ruby/assert.h big2str.o: $(hdrdir)/ruby/backward.h +big2str.o: $(hdrdir)/ruby/backward/2/assume.h +big2str.o: $(hdrdir)/ruby/backward/2/attributes.h +big2str.o: $(hdrdir)/ruby/backward/2/bool.h +big2str.o: $(hdrdir)/ruby/backward/2/inttypes.h +big2str.o: $(hdrdir)/ruby/backward/2/limits.h +big2str.o: $(hdrdir)/ruby/backward/2/long_long.h +big2str.o: $(hdrdir)/ruby/backward/2/stdalign.h +big2str.o: $(hdrdir)/ruby/backward/2/stdarg.h big2str.o: $(hdrdir)/ruby/defines.h big2str.o: $(hdrdir)/ruby/intern.h +big2str.o: $(hdrdir)/ruby/internal/anyargs.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/char.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/double.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/int.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/long.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/short.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +big2str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +big2str.o: $(hdrdir)/ruby/internal/assume.h +big2str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +big2str.o: $(hdrdir)/ruby/internal/attr/artificial.h +big2str.o: $(hdrdir)/ruby/internal/attr/cold.h +big2str.o: $(hdrdir)/ruby/internal/attr/const.h +big2str.o: $(hdrdir)/ruby/internal/attr/constexpr.h +big2str.o: $(hdrdir)/ruby/internal/attr/deprecated.h +big2str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +big2str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +big2str.o: $(hdrdir)/ruby/internal/attr/error.h +big2str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +big2str.o: $(hdrdir)/ruby/internal/attr/forceinline.h +big2str.o: $(hdrdir)/ruby/internal/attr/format.h +big2str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +big2str.o: $(hdrdir)/ruby/internal/attr/noalias.h +big2str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +big2str.o: $(hdrdir)/ruby/internal/attr/noexcept.h +big2str.o: $(hdrdir)/ruby/internal/attr/noinline.h +big2str.o: $(hdrdir)/ruby/internal/attr/nonnull.h +big2str.o: $(hdrdir)/ruby/internal/attr/noreturn.h +big2str.o: $(hdrdir)/ruby/internal/attr/pure.h +big2str.o: $(hdrdir)/ruby/internal/attr/restrict.h +big2str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +big2str.o: $(hdrdir)/ruby/internal/attr/warning.h +big2str.o: $(hdrdir)/ruby/internal/attr/weakref.h +big2str.o: $(hdrdir)/ruby/internal/cast.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +big2str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +big2str.o: $(hdrdir)/ruby/internal/compiler_since.h +big2str.o: $(hdrdir)/ruby/internal/config.h +big2str.o: $(hdrdir)/ruby/internal/constant_p.h +big2str.o: $(hdrdir)/ruby/internal/core.h +big2str.o: $(hdrdir)/ruby/internal/core/rarray.h +big2str.o: $(hdrdir)/ruby/internal/core/rbasic.h +big2str.o: $(hdrdir)/ruby/internal/core/rbignum.h +big2str.o: $(hdrdir)/ruby/internal/core/rclass.h +big2str.o: $(hdrdir)/ruby/internal/core/rdata.h +big2str.o: $(hdrdir)/ruby/internal/core/rfile.h +big2str.o: $(hdrdir)/ruby/internal/core/rhash.h +big2str.o: $(hdrdir)/ruby/internal/core/robject.h +big2str.o: $(hdrdir)/ruby/internal/core/rregexp.h +big2str.o: $(hdrdir)/ruby/internal/core/rstring.h +big2str.o: $(hdrdir)/ruby/internal/core/rstruct.h +big2str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +big2str.o: $(hdrdir)/ruby/internal/ctype.h +big2str.o: $(hdrdir)/ruby/internal/dllexport.h +big2str.o: $(hdrdir)/ruby/internal/dosish.h +big2str.o: $(hdrdir)/ruby/internal/error.h +big2str.o: $(hdrdir)/ruby/internal/eval.h +big2str.o: $(hdrdir)/ruby/internal/event.h +big2str.o: $(hdrdir)/ruby/internal/fl_type.h +big2str.o: $(hdrdir)/ruby/internal/gc.h +big2str.o: $(hdrdir)/ruby/internal/glob.h +big2str.o: $(hdrdir)/ruby/internal/globals.h +big2str.o: $(hdrdir)/ruby/internal/has/attribute.h +big2str.o: $(hdrdir)/ruby/internal/has/builtin.h +big2str.o: $(hdrdir)/ruby/internal/has/c_attribute.h +big2str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +big2str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +big2str.o: $(hdrdir)/ruby/internal/has/extension.h +big2str.o: $(hdrdir)/ruby/internal/has/feature.h +big2str.o: $(hdrdir)/ruby/internal/has/warning.h +big2str.o: $(hdrdir)/ruby/internal/intern/array.h +big2str.o: $(hdrdir)/ruby/internal/intern/bignum.h +big2str.o: $(hdrdir)/ruby/internal/intern/class.h +big2str.o: $(hdrdir)/ruby/internal/intern/compar.h +big2str.o: $(hdrdir)/ruby/internal/intern/complex.h +big2str.o: $(hdrdir)/ruby/internal/intern/cont.h +big2str.o: $(hdrdir)/ruby/internal/intern/dir.h +big2str.o: $(hdrdir)/ruby/internal/intern/enum.h +big2str.o: $(hdrdir)/ruby/internal/intern/enumerator.h +big2str.o: $(hdrdir)/ruby/internal/intern/error.h +big2str.o: $(hdrdir)/ruby/internal/intern/eval.h +big2str.o: $(hdrdir)/ruby/internal/intern/file.h +big2str.o: $(hdrdir)/ruby/internal/intern/gc.h +big2str.o: $(hdrdir)/ruby/internal/intern/hash.h +big2str.o: $(hdrdir)/ruby/internal/intern/io.h +big2str.o: $(hdrdir)/ruby/internal/intern/load.h +big2str.o: $(hdrdir)/ruby/internal/intern/marshal.h +big2str.o: $(hdrdir)/ruby/internal/intern/numeric.h +big2str.o: $(hdrdir)/ruby/internal/intern/object.h +big2str.o: $(hdrdir)/ruby/internal/intern/parse.h +big2str.o: $(hdrdir)/ruby/internal/intern/proc.h +big2str.o: $(hdrdir)/ruby/internal/intern/process.h +big2str.o: $(hdrdir)/ruby/internal/intern/random.h +big2str.o: $(hdrdir)/ruby/internal/intern/range.h +big2str.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +big2str.o: $(hdrdir)/ruby/internal/intern/sprintf.h +big2str.o: $(hdrdir)/ruby/internal/intern/string.h +big2str.o: $(hdrdir)/ruby/internal/intern/struct.h +big2str.o: $(hdrdir)/ruby/internal/intern/thread.h +big2str.o: $(hdrdir)/ruby/internal/intern/time.h +big2str.o: $(hdrdir)/ruby/internal/intern/variable.h +big2str.o: $(hdrdir)/ruby/internal/intern/vm.h +big2str.o: $(hdrdir)/ruby/internal/interpreter.h +big2str.o: $(hdrdir)/ruby/internal/iterator.h +big2str.o: $(hdrdir)/ruby/internal/memory.h +big2str.o: $(hdrdir)/ruby/internal/method.h +big2str.o: $(hdrdir)/ruby/internal/module.h +big2str.o: $(hdrdir)/ruby/internal/newobj.h +big2str.o: $(hdrdir)/ruby/internal/rgengc.h +big2str.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +big2str.o: $(hdrdir)/ruby/internal/value.h +big2str.o: $(hdrdir)/ruby/internal/value_type.h +big2str.o: $(hdrdir)/ruby/internal/variable.h +big2str.o: $(hdrdir)/ruby/internal/warning_push.h +big2str.o: $(hdrdir)/ruby/internal/xmalloc.h big2str.o: $(hdrdir)/ruby/missing.h big2str.o: $(hdrdir)/ruby/ruby.h big2str.o: $(hdrdir)/ruby/st.h big2str.o: $(hdrdir)/ruby/subst.h -big2str.o: $(top_srcdir)/internal.h +big2str.o: $(top_srcdir)/internal/bignum.h big2str.o: big2str.c bigzero.o: $(RUBY_EXTCONF_H) bigzero.o: $(arch_hdrdir)/ruby/config.h -bigzero.o: $(hdrdir)/ruby.h bigzero.o: $(hdrdir)/ruby/assert.h bigzero.o: $(hdrdir)/ruby/backward.h +bigzero.o: $(hdrdir)/ruby/backward/2/assume.h +bigzero.o: $(hdrdir)/ruby/backward/2/attributes.h +bigzero.o: $(hdrdir)/ruby/backward/2/bool.h +bigzero.o: $(hdrdir)/ruby/backward/2/inttypes.h +bigzero.o: $(hdrdir)/ruby/backward/2/limits.h +bigzero.o: $(hdrdir)/ruby/backward/2/long_long.h +bigzero.o: $(hdrdir)/ruby/backward/2/stdalign.h +bigzero.o: $(hdrdir)/ruby/backward/2/stdarg.h bigzero.o: $(hdrdir)/ruby/defines.h bigzero.o: $(hdrdir)/ruby/intern.h +bigzero.o: $(hdrdir)/ruby/internal/anyargs.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bigzero.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bigzero.o: $(hdrdir)/ruby/internal/assume.h +bigzero.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bigzero.o: $(hdrdir)/ruby/internal/attr/artificial.h +bigzero.o: $(hdrdir)/ruby/internal/attr/cold.h +bigzero.o: $(hdrdir)/ruby/internal/attr/const.h +bigzero.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bigzero.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bigzero.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bigzero.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bigzero.o: $(hdrdir)/ruby/internal/attr/error.h +bigzero.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bigzero.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bigzero.o: $(hdrdir)/ruby/internal/attr/format.h +bigzero.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bigzero.o: $(hdrdir)/ruby/internal/attr/noalias.h +bigzero.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bigzero.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bigzero.o: $(hdrdir)/ruby/internal/attr/noinline.h +bigzero.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bigzero.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bigzero.o: $(hdrdir)/ruby/internal/attr/pure.h +bigzero.o: $(hdrdir)/ruby/internal/attr/restrict.h +bigzero.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bigzero.o: $(hdrdir)/ruby/internal/attr/warning.h +bigzero.o: $(hdrdir)/ruby/internal/attr/weakref.h +bigzero.o: $(hdrdir)/ruby/internal/cast.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bigzero.o: $(hdrdir)/ruby/internal/compiler_since.h +bigzero.o: $(hdrdir)/ruby/internal/config.h +bigzero.o: $(hdrdir)/ruby/internal/constant_p.h +bigzero.o: $(hdrdir)/ruby/internal/core.h +bigzero.o: $(hdrdir)/ruby/internal/core/rarray.h +bigzero.o: $(hdrdir)/ruby/internal/core/rbasic.h +bigzero.o: $(hdrdir)/ruby/internal/core/rbignum.h +bigzero.o: $(hdrdir)/ruby/internal/core/rclass.h +bigzero.o: $(hdrdir)/ruby/internal/core/rdata.h +bigzero.o: $(hdrdir)/ruby/internal/core/rfile.h +bigzero.o: $(hdrdir)/ruby/internal/core/rhash.h +bigzero.o: $(hdrdir)/ruby/internal/core/robject.h +bigzero.o: $(hdrdir)/ruby/internal/core/rregexp.h +bigzero.o: $(hdrdir)/ruby/internal/core/rstring.h +bigzero.o: $(hdrdir)/ruby/internal/core/rstruct.h +bigzero.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bigzero.o: $(hdrdir)/ruby/internal/ctype.h +bigzero.o: $(hdrdir)/ruby/internal/dllexport.h +bigzero.o: $(hdrdir)/ruby/internal/dosish.h +bigzero.o: $(hdrdir)/ruby/internal/error.h +bigzero.o: $(hdrdir)/ruby/internal/eval.h +bigzero.o: $(hdrdir)/ruby/internal/event.h +bigzero.o: $(hdrdir)/ruby/internal/fl_type.h +bigzero.o: $(hdrdir)/ruby/internal/gc.h +bigzero.o: $(hdrdir)/ruby/internal/glob.h +bigzero.o: $(hdrdir)/ruby/internal/globals.h +bigzero.o: $(hdrdir)/ruby/internal/has/attribute.h +bigzero.o: $(hdrdir)/ruby/internal/has/builtin.h +bigzero.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bigzero.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bigzero.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bigzero.o: $(hdrdir)/ruby/internal/has/extension.h +bigzero.o: $(hdrdir)/ruby/internal/has/feature.h +bigzero.o: $(hdrdir)/ruby/internal/has/warning.h +bigzero.o: $(hdrdir)/ruby/internal/intern/array.h +bigzero.o: $(hdrdir)/ruby/internal/intern/bignum.h +bigzero.o: $(hdrdir)/ruby/internal/intern/class.h +bigzero.o: $(hdrdir)/ruby/internal/intern/compar.h +bigzero.o: $(hdrdir)/ruby/internal/intern/complex.h +bigzero.o: $(hdrdir)/ruby/internal/intern/cont.h +bigzero.o: $(hdrdir)/ruby/internal/intern/dir.h +bigzero.o: $(hdrdir)/ruby/internal/intern/enum.h +bigzero.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bigzero.o: $(hdrdir)/ruby/internal/intern/error.h +bigzero.o: $(hdrdir)/ruby/internal/intern/eval.h +bigzero.o: $(hdrdir)/ruby/internal/intern/file.h +bigzero.o: $(hdrdir)/ruby/internal/intern/gc.h +bigzero.o: $(hdrdir)/ruby/internal/intern/hash.h +bigzero.o: $(hdrdir)/ruby/internal/intern/io.h +bigzero.o: $(hdrdir)/ruby/internal/intern/load.h +bigzero.o: $(hdrdir)/ruby/internal/intern/marshal.h +bigzero.o: $(hdrdir)/ruby/internal/intern/numeric.h +bigzero.o: $(hdrdir)/ruby/internal/intern/object.h +bigzero.o: $(hdrdir)/ruby/internal/intern/parse.h +bigzero.o: $(hdrdir)/ruby/internal/intern/proc.h +bigzero.o: $(hdrdir)/ruby/internal/intern/process.h +bigzero.o: $(hdrdir)/ruby/internal/intern/random.h +bigzero.o: $(hdrdir)/ruby/internal/intern/range.h +bigzero.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bigzero.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bigzero.o: $(hdrdir)/ruby/internal/intern/string.h +bigzero.o: $(hdrdir)/ruby/internal/intern/struct.h +bigzero.o: $(hdrdir)/ruby/internal/intern/thread.h +bigzero.o: $(hdrdir)/ruby/internal/intern/time.h +bigzero.o: $(hdrdir)/ruby/internal/intern/variable.h +bigzero.o: $(hdrdir)/ruby/internal/intern/vm.h +bigzero.o: $(hdrdir)/ruby/internal/interpreter.h +bigzero.o: $(hdrdir)/ruby/internal/iterator.h +bigzero.o: $(hdrdir)/ruby/internal/memory.h +bigzero.o: $(hdrdir)/ruby/internal/method.h +bigzero.o: $(hdrdir)/ruby/internal/module.h +bigzero.o: $(hdrdir)/ruby/internal/newobj.h +bigzero.o: $(hdrdir)/ruby/internal/rgengc.h +bigzero.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bigzero.o: $(hdrdir)/ruby/internal/value.h +bigzero.o: $(hdrdir)/ruby/internal/value_type.h +bigzero.o: $(hdrdir)/ruby/internal/variable.h +bigzero.o: $(hdrdir)/ruby/internal/warning_push.h +bigzero.o: $(hdrdir)/ruby/internal/xmalloc.h bigzero.o: $(hdrdir)/ruby/missing.h bigzero.o: $(hdrdir)/ruby/ruby.h bigzero.o: $(hdrdir)/ruby/st.h bigzero.o: $(hdrdir)/ruby/subst.h -bigzero.o: $(top_srcdir)/internal.h +bigzero.o: $(top_srcdir)/internal/bignum.h bigzero.o: bigzero.c div.o: $(RUBY_EXTCONF_H) div.o: $(arch_hdrdir)/ruby/config.h -div.o: $(hdrdir)/ruby.h div.o: $(hdrdir)/ruby/assert.h div.o: $(hdrdir)/ruby/backward.h +div.o: $(hdrdir)/ruby/backward/2/assume.h +div.o: $(hdrdir)/ruby/backward/2/attributes.h +div.o: $(hdrdir)/ruby/backward/2/bool.h +div.o: $(hdrdir)/ruby/backward/2/inttypes.h +div.o: $(hdrdir)/ruby/backward/2/limits.h +div.o: $(hdrdir)/ruby/backward/2/long_long.h +div.o: $(hdrdir)/ruby/backward/2/stdalign.h +div.o: $(hdrdir)/ruby/backward/2/stdarg.h div.o: $(hdrdir)/ruby/defines.h div.o: $(hdrdir)/ruby/intern.h +div.o: $(hdrdir)/ruby/internal/anyargs.h +div.o: $(hdrdir)/ruby/internal/arithmetic.h +div.o: $(hdrdir)/ruby/internal/arithmetic/char.h +div.o: $(hdrdir)/ruby/internal/arithmetic/double.h +div.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +div.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/int.h +div.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/long.h +div.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +div.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/short.h +div.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +div.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +div.o: $(hdrdir)/ruby/internal/assume.h +div.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +div.o: $(hdrdir)/ruby/internal/attr/artificial.h +div.o: $(hdrdir)/ruby/internal/attr/cold.h +div.o: $(hdrdir)/ruby/internal/attr/const.h +div.o: $(hdrdir)/ruby/internal/attr/constexpr.h +div.o: $(hdrdir)/ruby/internal/attr/deprecated.h +div.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +div.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +div.o: $(hdrdir)/ruby/internal/attr/error.h +div.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +div.o: $(hdrdir)/ruby/internal/attr/forceinline.h +div.o: $(hdrdir)/ruby/internal/attr/format.h +div.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +div.o: $(hdrdir)/ruby/internal/attr/noalias.h +div.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +div.o: $(hdrdir)/ruby/internal/attr/noexcept.h +div.o: $(hdrdir)/ruby/internal/attr/noinline.h +div.o: $(hdrdir)/ruby/internal/attr/nonnull.h +div.o: $(hdrdir)/ruby/internal/attr/noreturn.h +div.o: $(hdrdir)/ruby/internal/attr/pure.h +div.o: $(hdrdir)/ruby/internal/attr/restrict.h +div.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +div.o: $(hdrdir)/ruby/internal/attr/warning.h +div.o: $(hdrdir)/ruby/internal/attr/weakref.h +div.o: $(hdrdir)/ruby/internal/cast.h +div.o: $(hdrdir)/ruby/internal/compiler_is.h +div.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +div.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +div.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +div.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +div.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +div.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +div.o: $(hdrdir)/ruby/internal/compiler_since.h +div.o: $(hdrdir)/ruby/internal/config.h +div.o: $(hdrdir)/ruby/internal/constant_p.h +div.o: $(hdrdir)/ruby/internal/core.h +div.o: $(hdrdir)/ruby/internal/core/rarray.h +div.o: $(hdrdir)/ruby/internal/core/rbasic.h +div.o: $(hdrdir)/ruby/internal/core/rbignum.h +div.o: $(hdrdir)/ruby/internal/core/rclass.h +div.o: $(hdrdir)/ruby/internal/core/rdata.h +div.o: $(hdrdir)/ruby/internal/core/rfile.h +div.o: $(hdrdir)/ruby/internal/core/rhash.h +div.o: $(hdrdir)/ruby/internal/core/robject.h +div.o: $(hdrdir)/ruby/internal/core/rregexp.h +div.o: $(hdrdir)/ruby/internal/core/rstring.h +div.o: $(hdrdir)/ruby/internal/core/rstruct.h +div.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +div.o: $(hdrdir)/ruby/internal/ctype.h +div.o: $(hdrdir)/ruby/internal/dllexport.h +div.o: $(hdrdir)/ruby/internal/dosish.h +div.o: $(hdrdir)/ruby/internal/error.h +div.o: $(hdrdir)/ruby/internal/eval.h +div.o: $(hdrdir)/ruby/internal/event.h +div.o: $(hdrdir)/ruby/internal/fl_type.h +div.o: $(hdrdir)/ruby/internal/gc.h +div.o: $(hdrdir)/ruby/internal/glob.h +div.o: $(hdrdir)/ruby/internal/globals.h +div.o: $(hdrdir)/ruby/internal/has/attribute.h +div.o: $(hdrdir)/ruby/internal/has/builtin.h +div.o: $(hdrdir)/ruby/internal/has/c_attribute.h +div.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +div.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +div.o: $(hdrdir)/ruby/internal/has/extension.h +div.o: $(hdrdir)/ruby/internal/has/feature.h +div.o: $(hdrdir)/ruby/internal/has/warning.h +div.o: $(hdrdir)/ruby/internal/intern/array.h +div.o: $(hdrdir)/ruby/internal/intern/bignum.h +div.o: $(hdrdir)/ruby/internal/intern/class.h +div.o: $(hdrdir)/ruby/internal/intern/compar.h +div.o: $(hdrdir)/ruby/internal/intern/complex.h +div.o: $(hdrdir)/ruby/internal/intern/cont.h +div.o: $(hdrdir)/ruby/internal/intern/dir.h +div.o: $(hdrdir)/ruby/internal/intern/enum.h +div.o: $(hdrdir)/ruby/internal/intern/enumerator.h +div.o: $(hdrdir)/ruby/internal/intern/error.h +div.o: $(hdrdir)/ruby/internal/intern/eval.h +div.o: $(hdrdir)/ruby/internal/intern/file.h +div.o: $(hdrdir)/ruby/internal/intern/gc.h +div.o: $(hdrdir)/ruby/internal/intern/hash.h +div.o: $(hdrdir)/ruby/internal/intern/io.h +div.o: $(hdrdir)/ruby/internal/intern/load.h +div.o: $(hdrdir)/ruby/internal/intern/marshal.h +div.o: $(hdrdir)/ruby/internal/intern/numeric.h +div.o: $(hdrdir)/ruby/internal/intern/object.h +div.o: $(hdrdir)/ruby/internal/intern/parse.h +div.o: $(hdrdir)/ruby/internal/intern/proc.h +div.o: $(hdrdir)/ruby/internal/intern/process.h +div.o: $(hdrdir)/ruby/internal/intern/random.h +div.o: $(hdrdir)/ruby/internal/intern/range.h +div.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +div.o: $(hdrdir)/ruby/internal/intern/sprintf.h +div.o: $(hdrdir)/ruby/internal/intern/string.h +div.o: $(hdrdir)/ruby/internal/intern/struct.h +div.o: $(hdrdir)/ruby/internal/intern/thread.h +div.o: $(hdrdir)/ruby/internal/intern/time.h +div.o: $(hdrdir)/ruby/internal/intern/variable.h +div.o: $(hdrdir)/ruby/internal/intern/vm.h +div.o: $(hdrdir)/ruby/internal/interpreter.h +div.o: $(hdrdir)/ruby/internal/iterator.h +div.o: $(hdrdir)/ruby/internal/memory.h +div.o: $(hdrdir)/ruby/internal/method.h +div.o: $(hdrdir)/ruby/internal/module.h +div.o: $(hdrdir)/ruby/internal/newobj.h +div.o: $(hdrdir)/ruby/internal/rgengc.h +div.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +div.o: $(hdrdir)/ruby/internal/value.h +div.o: $(hdrdir)/ruby/internal/value_type.h +div.o: $(hdrdir)/ruby/internal/variable.h +div.o: $(hdrdir)/ruby/internal/warning_push.h +div.o: $(hdrdir)/ruby/internal/xmalloc.h div.o: $(hdrdir)/ruby/missing.h div.o: $(hdrdir)/ruby/ruby.h div.o: $(hdrdir)/ruby/st.h div.o: $(hdrdir)/ruby/subst.h -div.o: $(top_srcdir)/internal.h +div.o: $(top_srcdir)/internal/bignum.h div.o: div.c 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/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/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/gc.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/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/rgengc.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/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 @@ -52,41 +637,479 @@ init.o: $(hdrdir)/ruby/subst.h init.o: init.c intpack.o: $(RUBY_EXTCONF_H) intpack.o: $(arch_hdrdir)/ruby/config.h -intpack.o: $(hdrdir)/ruby.h intpack.o: $(hdrdir)/ruby/assert.h intpack.o: $(hdrdir)/ruby/backward.h +intpack.o: $(hdrdir)/ruby/backward/2/assume.h +intpack.o: $(hdrdir)/ruby/backward/2/attributes.h +intpack.o: $(hdrdir)/ruby/backward/2/bool.h +intpack.o: $(hdrdir)/ruby/backward/2/inttypes.h +intpack.o: $(hdrdir)/ruby/backward/2/limits.h +intpack.o: $(hdrdir)/ruby/backward/2/long_long.h +intpack.o: $(hdrdir)/ruby/backward/2/stdalign.h +intpack.o: $(hdrdir)/ruby/backward/2/stdarg.h intpack.o: $(hdrdir)/ruby/defines.h intpack.o: $(hdrdir)/ruby/intern.h +intpack.o: $(hdrdir)/ruby/internal/anyargs.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/char.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/double.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/int.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/long.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/short.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +intpack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +intpack.o: $(hdrdir)/ruby/internal/assume.h +intpack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +intpack.o: $(hdrdir)/ruby/internal/attr/artificial.h +intpack.o: $(hdrdir)/ruby/internal/attr/cold.h +intpack.o: $(hdrdir)/ruby/internal/attr/const.h +intpack.o: $(hdrdir)/ruby/internal/attr/constexpr.h +intpack.o: $(hdrdir)/ruby/internal/attr/deprecated.h +intpack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +intpack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +intpack.o: $(hdrdir)/ruby/internal/attr/error.h +intpack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +intpack.o: $(hdrdir)/ruby/internal/attr/forceinline.h +intpack.o: $(hdrdir)/ruby/internal/attr/format.h +intpack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +intpack.o: $(hdrdir)/ruby/internal/attr/noalias.h +intpack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +intpack.o: $(hdrdir)/ruby/internal/attr/noexcept.h +intpack.o: $(hdrdir)/ruby/internal/attr/noinline.h +intpack.o: $(hdrdir)/ruby/internal/attr/nonnull.h +intpack.o: $(hdrdir)/ruby/internal/attr/noreturn.h +intpack.o: $(hdrdir)/ruby/internal/attr/pure.h +intpack.o: $(hdrdir)/ruby/internal/attr/restrict.h +intpack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +intpack.o: $(hdrdir)/ruby/internal/attr/warning.h +intpack.o: $(hdrdir)/ruby/internal/attr/weakref.h +intpack.o: $(hdrdir)/ruby/internal/cast.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +intpack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +intpack.o: $(hdrdir)/ruby/internal/compiler_since.h +intpack.o: $(hdrdir)/ruby/internal/config.h +intpack.o: $(hdrdir)/ruby/internal/constant_p.h +intpack.o: $(hdrdir)/ruby/internal/core.h +intpack.o: $(hdrdir)/ruby/internal/core/rarray.h +intpack.o: $(hdrdir)/ruby/internal/core/rbasic.h +intpack.o: $(hdrdir)/ruby/internal/core/rbignum.h +intpack.o: $(hdrdir)/ruby/internal/core/rclass.h +intpack.o: $(hdrdir)/ruby/internal/core/rdata.h +intpack.o: $(hdrdir)/ruby/internal/core/rfile.h +intpack.o: $(hdrdir)/ruby/internal/core/rhash.h +intpack.o: $(hdrdir)/ruby/internal/core/robject.h +intpack.o: $(hdrdir)/ruby/internal/core/rregexp.h +intpack.o: $(hdrdir)/ruby/internal/core/rstring.h +intpack.o: $(hdrdir)/ruby/internal/core/rstruct.h +intpack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +intpack.o: $(hdrdir)/ruby/internal/ctype.h +intpack.o: $(hdrdir)/ruby/internal/dllexport.h +intpack.o: $(hdrdir)/ruby/internal/dosish.h +intpack.o: $(hdrdir)/ruby/internal/error.h +intpack.o: $(hdrdir)/ruby/internal/eval.h +intpack.o: $(hdrdir)/ruby/internal/event.h +intpack.o: $(hdrdir)/ruby/internal/fl_type.h +intpack.o: $(hdrdir)/ruby/internal/gc.h +intpack.o: $(hdrdir)/ruby/internal/glob.h +intpack.o: $(hdrdir)/ruby/internal/globals.h +intpack.o: $(hdrdir)/ruby/internal/has/attribute.h +intpack.o: $(hdrdir)/ruby/internal/has/builtin.h +intpack.o: $(hdrdir)/ruby/internal/has/c_attribute.h +intpack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +intpack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +intpack.o: $(hdrdir)/ruby/internal/has/extension.h +intpack.o: $(hdrdir)/ruby/internal/has/feature.h +intpack.o: $(hdrdir)/ruby/internal/has/warning.h +intpack.o: $(hdrdir)/ruby/internal/intern/array.h +intpack.o: $(hdrdir)/ruby/internal/intern/bignum.h +intpack.o: $(hdrdir)/ruby/internal/intern/class.h +intpack.o: $(hdrdir)/ruby/internal/intern/compar.h +intpack.o: $(hdrdir)/ruby/internal/intern/complex.h +intpack.o: $(hdrdir)/ruby/internal/intern/cont.h +intpack.o: $(hdrdir)/ruby/internal/intern/dir.h +intpack.o: $(hdrdir)/ruby/internal/intern/enum.h +intpack.o: $(hdrdir)/ruby/internal/intern/enumerator.h +intpack.o: $(hdrdir)/ruby/internal/intern/error.h +intpack.o: $(hdrdir)/ruby/internal/intern/eval.h +intpack.o: $(hdrdir)/ruby/internal/intern/file.h +intpack.o: $(hdrdir)/ruby/internal/intern/gc.h +intpack.o: $(hdrdir)/ruby/internal/intern/hash.h +intpack.o: $(hdrdir)/ruby/internal/intern/io.h +intpack.o: $(hdrdir)/ruby/internal/intern/load.h +intpack.o: $(hdrdir)/ruby/internal/intern/marshal.h +intpack.o: $(hdrdir)/ruby/internal/intern/numeric.h +intpack.o: $(hdrdir)/ruby/internal/intern/object.h +intpack.o: $(hdrdir)/ruby/internal/intern/parse.h +intpack.o: $(hdrdir)/ruby/internal/intern/proc.h +intpack.o: $(hdrdir)/ruby/internal/intern/process.h +intpack.o: $(hdrdir)/ruby/internal/intern/random.h +intpack.o: $(hdrdir)/ruby/internal/intern/range.h +intpack.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +intpack.o: $(hdrdir)/ruby/internal/intern/sprintf.h +intpack.o: $(hdrdir)/ruby/internal/intern/string.h +intpack.o: $(hdrdir)/ruby/internal/intern/struct.h +intpack.o: $(hdrdir)/ruby/internal/intern/thread.h +intpack.o: $(hdrdir)/ruby/internal/intern/time.h +intpack.o: $(hdrdir)/ruby/internal/intern/variable.h +intpack.o: $(hdrdir)/ruby/internal/intern/vm.h +intpack.o: $(hdrdir)/ruby/internal/interpreter.h +intpack.o: $(hdrdir)/ruby/internal/iterator.h +intpack.o: $(hdrdir)/ruby/internal/memory.h +intpack.o: $(hdrdir)/ruby/internal/method.h +intpack.o: $(hdrdir)/ruby/internal/module.h +intpack.o: $(hdrdir)/ruby/internal/newobj.h +intpack.o: $(hdrdir)/ruby/internal/rgengc.h +intpack.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +intpack.o: $(hdrdir)/ruby/internal/value.h +intpack.o: $(hdrdir)/ruby/internal/value_type.h +intpack.o: $(hdrdir)/ruby/internal/variable.h +intpack.o: $(hdrdir)/ruby/internal/warning_push.h +intpack.o: $(hdrdir)/ruby/internal/xmalloc.h intpack.o: $(hdrdir)/ruby/missing.h intpack.o: $(hdrdir)/ruby/ruby.h intpack.o: $(hdrdir)/ruby/st.h intpack.o: $(hdrdir)/ruby/subst.h -intpack.o: $(top_srcdir)/internal.h +intpack.o: $(top_srcdir)/internal/bignum.h intpack.o: intpack.c mul.o: $(RUBY_EXTCONF_H) mul.o: $(arch_hdrdir)/ruby/config.h -mul.o: $(hdrdir)/ruby.h mul.o: $(hdrdir)/ruby/assert.h mul.o: $(hdrdir)/ruby/backward.h +mul.o: $(hdrdir)/ruby/backward/2/assume.h +mul.o: $(hdrdir)/ruby/backward/2/attributes.h +mul.o: $(hdrdir)/ruby/backward/2/bool.h +mul.o: $(hdrdir)/ruby/backward/2/inttypes.h +mul.o: $(hdrdir)/ruby/backward/2/limits.h +mul.o: $(hdrdir)/ruby/backward/2/long_long.h +mul.o: $(hdrdir)/ruby/backward/2/stdalign.h +mul.o: $(hdrdir)/ruby/backward/2/stdarg.h mul.o: $(hdrdir)/ruby/defines.h mul.o: $(hdrdir)/ruby/intern.h +mul.o: $(hdrdir)/ruby/internal/anyargs.h +mul.o: $(hdrdir)/ruby/internal/arithmetic.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/char.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/double.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/int.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/long.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/short.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +mul.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +mul.o: $(hdrdir)/ruby/internal/assume.h +mul.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +mul.o: $(hdrdir)/ruby/internal/attr/artificial.h +mul.o: $(hdrdir)/ruby/internal/attr/cold.h +mul.o: $(hdrdir)/ruby/internal/attr/const.h +mul.o: $(hdrdir)/ruby/internal/attr/constexpr.h +mul.o: $(hdrdir)/ruby/internal/attr/deprecated.h +mul.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +mul.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +mul.o: $(hdrdir)/ruby/internal/attr/error.h +mul.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +mul.o: $(hdrdir)/ruby/internal/attr/forceinline.h +mul.o: $(hdrdir)/ruby/internal/attr/format.h +mul.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +mul.o: $(hdrdir)/ruby/internal/attr/noalias.h +mul.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +mul.o: $(hdrdir)/ruby/internal/attr/noexcept.h +mul.o: $(hdrdir)/ruby/internal/attr/noinline.h +mul.o: $(hdrdir)/ruby/internal/attr/nonnull.h +mul.o: $(hdrdir)/ruby/internal/attr/noreturn.h +mul.o: $(hdrdir)/ruby/internal/attr/pure.h +mul.o: $(hdrdir)/ruby/internal/attr/restrict.h +mul.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +mul.o: $(hdrdir)/ruby/internal/attr/warning.h +mul.o: $(hdrdir)/ruby/internal/attr/weakref.h +mul.o: $(hdrdir)/ruby/internal/cast.h +mul.o: $(hdrdir)/ruby/internal/compiler_is.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +mul.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +mul.o: $(hdrdir)/ruby/internal/compiler_since.h +mul.o: $(hdrdir)/ruby/internal/config.h +mul.o: $(hdrdir)/ruby/internal/constant_p.h +mul.o: $(hdrdir)/ruby/internal/core.h +mul.o: $(hdrdir)/ruby/internal/core/rarray.h +mul.o: $(hdrdir)/ruby/internal/core/rbasic.h +mul.o: $(hdrdir)/ruby/internal/core/rbignum.h +mul.o: $(hdrdir)/ruby/internal/core/rclass.h +mul.o: $(hdrdir)/ruby/internal/core/rdata.h +mul.o: $(hdrdir)/ruby/internal/core/rfile.h +mul.o: $(hdrdir)/ruby/internal/core/rhash.h +mul.o: $(hdrdir)/ruby/internal/core/robject.h +mul.o: $(hdrdir)/ruby/internal/core/rregexp.h +mul.o: $(hdrdir)/ruby/internal/core/rstring.h +mul.o: $(hdrdir)/ruby/internal/core/rstruct.h +mul.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +mul.o: $(hdrdir)/ruby/internal/ctype.h +mul.o: $(hdrdir)/ruby/internal/dllexport.h +mul.o: $(hdrdir)/ruby/internal/dosish.h +mul.o: $(hdrdir)/ruby/internal/error.h +mul.o: $(hdrdir)/ruby/internal/eval.h +mul.o: $(hdrdir)/ruby/internal/event.h +mul.o: $(hdrdir)/ruby/internal/fl_type.h +mul.o: $(hdrdir)/ruby/internal/gc.h +mul.o: $(hdrdir)/ruby/internal/glob.h +mul.o: $(hdrdir)/ruby/internal/globals.h +mul.o: $(hdrdir)/ruby/internal/has/attribute.h +mul.o: $(hdrdir)/ruby/internal/has/builtin.h +mul.o: $(hdrdir)/ruby/internal/has/c_attribute.h +mul.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +mul.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +mul.o: $(hdrdir)/ruby/internal/has/extension.h +mul.o: $(hdrdir)/ruby/internal/has/feature.h +mul.o: $(hdrdir)/ruby/internal/has/warning.h +mul.o: $(hdrdir)/ruby/internal/intern/array.h +mul.o: $(hdrdir)/ruby/internal/intern/bignum.h +mul.o: $(hdrdir)/ruby/internal/intern/class.h +mul.o: $(hdrdir)/ruby/internal/intern/compar.h +mul.o: $(hdrdir)/ruby/internal/intern/complex.h +mul.o: $(hdrdir)/ruby/internal/intern/cont.h +mul.o: $(hdrdir)/ruby/internal/intern/dir.h +mul.o: $(hdrdir)/ruby/internal/intern/enum.h +mul.o: $(hdrdir)/ruby/internal/intern/enumerator.h +mul.o: $(hdrdir)/ruby/internal/intern/error.h +mul.o: $(hdrdir)/ruby/internal/intern/eval.h +mul.o: $(hdrdir)/ruby/internal/intern/file.h +mul.o: $(hdrdir)/ruby/internal/intern/gc.h +mul.o: $(hdrdir)/ruby/internal/intern/hash.h +mul.o: $(hdrdir)/ruby/internal/intern/io.h +mul.o: $(hdrdir)/ruby/internal/intern/load.h +mul.o: $(hdrdir)/ruby/internal/intern/marshal.h +mul.o: $(hdrdir)/ruby/internal/intern/numeric.h +mul.o: $(hdrdir)/ruby/internal/intern/object.h +mul.o: $(hdrdir)/ruby/internal/intern/parse.h +mul.o: $(hdrdir)/ruby/internal/intern/proc.h +mul.o: $(hdrdir)/ruby/internal/intern/process.h +mul.o: $(hdrdir)/ruby/internal/intern/random.h +mul.o: $(hdrdir)/ruby/internal/intern/range.h +mul.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +mul.o: $(hdrdir)/ruby/internal/intern/sprintf.h +mul.o: $(hdrdir)/ruby/internal/intern/string.h +mul.o: $(hdrdir)/ruby/internal/intern/struct.h +mul.o: $(hdrdir)/ruby/internal/intern/thread.h +mul.o: $(hdrdir)/ruby/internal/intern/time.h +mul.o: $(hdrdir)/ruby/internal/intern/variable.h +mul.o: $(hdrdir)/ruby/internal/intern/vm.h +mul.o: $(hdrdir)/ruby/internal/interpreter.h +mul.o: $(hdrdir)/ruby/internal/iterator.h +mul.o: $(hdrdir)/ruby/internal/memory.h +mul.o: $(hdrdir)/ruby/internal/method.h +mul.o: $(hdrdir)/ruby/internal/module.h +mul.o: $(hdrdir)/ruby/internal/newobj.h +mul.o: $(hdrdir)/ruby/internal/rgengc.h +mul.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +mul.o: $(hdrdir)/ruby/internal/value.h +mul.o: $(hdrdir)/ruby/internal/value_type.h +mul.o: $(hdrdir)/ruby/internal/variable.h +mul.o: $(hdrdir)/ruby/internal/warning_push.h +mul.o: $(hdrdir)/ruby/internal/xmalloc.h mul.o: $(hdrdir)/ruby/missing.h mul.o: $(hdrdir)/ruby/ruby.h mul.o: $(hdrdir)/ruby/st.h mul.o: $(hdrdir)/ruby/subst.h -mul.o: $(top_srcdir)/internal.h +mul.o: $(top_srcdir)/internal/bignum.h mul.o: mul.c str2big.o: $(RUBY_EXTCONF_H) str2big.o: $(arch_hdrdir)/ruby/config.h -str2big.o: $(hdrdir)/ruby.h str2big.o: $(hdrdir)/ruby/assert.h str2big.o: $(hdrdir)/ruby/backward.h +str2big.o: $(hdrdir)/ruby/backward/2/assume.h +str2big.o: $(hdrdir)/ruby/backward/2/attributes.h +str2big.o: $(hdrdir)/ruby/backward/2/bool.h +str2big.o: $(hdrdir)/ruby/backward/2/inttypes.h +str2big.o: $(hdrdir)/ruby/backward/2/limits.h +str2big.o: $(hdrdir)/ruby/backward/2/long_long.h +str2big.o: $(hdrdir)/ruby/backward/2/stdalign.h +str2big.o: $(hdrdir)/ruby/backward/2/stdarg.h str2big.o: $(hdrdir)/ruby/defines.h str2big.o: $(hdrdir)/ruby/intern.h +str2big.o: $(hdrdir)/ruby/internal/anyargs.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/char.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/double.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/int.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/long.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/short.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +str2big.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +str2big.o: $(hdrdir)/ruby/internal/assume.h +str2big.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +str2big.o: $(hdrdir)/ruby/internal/attr/artificial.h +str2big.o: $(hdrdir)/ruby/internal/attr/cold.h +str2big.o: $(hdrdir)/ruby/internal/attr/const.h +str2big.o: $(hdrdir)/ruby/internal/attr/constexpr.h +str2big.o: $(hdrdir)/ruby/internal/attr/deprecated.h +str2big.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +str2big.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +str2big.o: $(hdrdir)/ruby/internal/attr/error.h +str2big.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +str2big.o: $(hdrdir)/ruby/internal/attr/forceinline.h +str2big.o: $(hdrdir)/ruby/internal/attr/format.h +str2big.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +str2big.o: $(hdrdir)/ruby/internal/attr/noalias.h +str2big.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +str2big.o: $(hdrdir)/ruby/internal/attr/noexcept.h +str2big.o: $(hdrdir)/ruby/internal/attr/noinline.h +str2big.o: $(hdrdir)/ruby/internal/attr/nonnull.h +str2big.o: $(hdrdir)/ruby/internal/attr/noreturn.h +str2big.o: $(hdrdir)/ruby/internal/attr/pure.h +str2big.o: $(hdrdir)/ruby/internal/attr/restrict.h +str2big.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +str2big.o: $(hdrdir)/ruby/internal/attr/warning.h +str2big.o: $(hdrdir)/ruby/internal/attr/weakref.h +str2big.o: $(hdrdir)/ruby/internal/cast.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +str2big.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +str2big.o: $(hdrdir)/ruby/internal/compiler_since.h +str2big.o: $(hdrdir)/ruby/internal/config.h +str2big.o: $(hdrdir)/ruby/internal/constant_p.h +str2big.o: $(hdrdir)/ruby/internal/core.h +str2big.o: $(hdrdir)/ruby/internal/core/rarray.h +str2big.o: $(hdrdir)/ruby/internal/core/rbasic.h +str2big.o: $(hdrdir)/ruby/internal/core/rbignum.h +str2big.o: $(hdrdir)/ruby/internal/core/rclass.h +str2big.o: $(hdrdir)/ruby/internal/core/rdata.h +str2big.o: $(hdrdir)/ruby/internal/core/rfile.h +str2big.o: $(hdrdir)/ruby/internal/core/rhash.h +str2big.o: $(hdrdir)/ruby/internal/core/robject.h +str2big.o: $(hdrdir)/ruby/internal/core/rregexp.h +str2big.o: $(hdrdir)/ruby/internal/core/rstring.h +str2big.o: $(hdrdir)/ruby/internal/core/rstruct.h +str2big.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +str2big.o: $(hdrdir)/ruby/internal/ctype.h +str2big.o: $(hdrdir)/ruby/internal/dllexport.h +str2big.o: $(hdrdir)/ruby/internal/dosish.h +str2big.o: $(hdrdir)/ruby/internal/error.h +str2big.o: $(hdrdir)/ruby/internal/eval.h +str2big.o: $(hdrdir)/ruby/internal/event.h +str2big.o: $(hdrdir)/ruby/internal/fl_type.h +str2big.o: $(hdrdir)/ruby/internal/gc.h +str2big.o: $(hdrdir)/ruby/internal/glob.h +str2big.o: $(hdrdir)/ruby/internal/globals.h +str2big.o: $(hdrdir)/ruby/internal/has/attribute.h +str2big.o: $(hdrdir)/ruby/internal/has/builtin.h +str2big.o: $(hdrdir)/ruby/internal/has/c_attribute.h +str2big.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +str2big.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +str2big.o: $(hdrdir)/ruby/internal/has/extension.h +str2big.o: $(hdrdir)/ruby/internal/has/feature.h +str2big.o: $(hdrdir)/ruby/internal/has/warning.h +str2big.o: $(hdrdir)/ruby/internal/intern/array.h +str2big.o: $(hdrdir)/ruby/internal/intern/bignum.h +str2big.o: $(hdrdir)/ruby/internal/intern/class.h +str2big.o: $(hdrdir)/ruby/internal/intern/compar.h +str2big.o: $(hdrdir)/ruby/internal/intern/complex.h +str2big.o: $(hdrdir)/ruby/internal/intern/cont.h +str2big.o: $(hdrdir)/ruby/internal/intern/dir.h +str2big.o: $(hdrdir)/ruby/internal/intern/enum.h +str2big.o: $(hdrdir)/ruby/internal/intern/enumerator.h +str2big.o: $(hdrdir)/ruby/internal/intern/error.h +str2big.o: $(hdrdir)/ruby/internal/intern/eval.h +str2big.o: $(hdrdir)/ruby/internal/intern/file.h +str2big.o: $(hdrdir)/ruby/internal/intern/gc.h +str2big.o: $(hdrdir)/ruby/internal/intern/hash.h +str2big.o: $(hdrdir)/ruby/internal/intern/io.h +str2big.o: $(hdrdir)/ruby/internal/intern/load.h +str2big.o: $(hdrdir)/ruby/internal/intern/marshal.h +str2big.o: $(hdrdir)/ruby/internal/intern/numeric.h +str2big.o: $(hdrdir)/ruby/internal/intern/object.h +str2big.o: $(hdrdir)/ruby/internal/intern/parse.h +str2big.o: $(hdrdir)/ruby/internal/intern/proc.h +str2big.o: $(hdrdir)/ruby/internal/intern/process.h +str2big.o: $(hdrdir)/ruby/internal/intern/random.h +str2big.o: $(hdrdir)/ruby/internal/intern/range.h +str2big.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +str2big.o: $(hdrdir)/ruby/internal/intern/sprintf.h +str2big.o: $(hdrdir)/ruby/internal/intern/string.h +str2big.o: $(hdrdir)/ruby/internal/intern/struct.h +str2big.o: $(hdrdir)/ruby/internal/intern/thread.h +str2big.o: $(hdrdir)/ruby/internal/intern/time.h +str2big.o: $(hdrdir)/ruby/internal/intern/variable.h +str2big.o: $(hdrdir)/ruby/internal/intern/vm.h +str2big.o: $(hdrdir)/ruby/internal/interpreter.h +str2big.o: $(hdrdir)/ruby/internal/iterator.h +str2big.o: $(hdrdir)/ruby/internal/memory.h +str2big.o: $(hdrdir)/ruby/internal/method.h +str2big.o: $(hdrdir)/ruby/internal/module.h +str2big.o: $(hdrdir)/ruby/internal/newobj.h +str2big.o: $(hdrdir)/ruby/internal/rgengc.h +str2big.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +str2big.o: $(hdrdir)/ruby/internal/value.h +str2big.o: $(hdrdir)/ruby/internal/value_type.h +str2big.o: $(hdrdir)/ruby/internal/variable.h +str2big.o: $(hdrdir)/ruby/internal/warning_push.h +str2big.o: $(hdrdir)/ruby/internal/xmalloc.h str2big.o: $(hdrdir)/ruby/missing.h str2big.o: $(hdrdir)/ruby/ruby.h str2big.o: $(hdrdir)/ruby/st.h str2big.o: $(hdrdir)/ruby/subst.h -str2big.o: $(top_srcdir)/internal.h +str2big.o: $(top_srcdir)/internal/bignum.h str2big.o: str2big.c # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/bignum/div.c b/ruby/ext/-test-/bignum/div.c index a1db21dc3..85ee0677f 100644 --- a/ruby/ext/-test-/bignum/div.c +++ b/ruby/ext/-test-/bignum/div.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE big(VALUE x) @@ -12,14 +12,14 @@ big(VALUE x) } static VALUE -divrem_normal(VALUE x, VALUE y) +divrem_normal(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_divrem_normal(big(x), big(y))); } #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE -divrem_gmp(VALUE x, VALUE y) +divrem_gmp(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_divrem_gmp(big(x), big(y))); } @@ -30,6 +30,6 @@ divrem_gmp(VALUE x, VALUE y) void Init_div(VALUE klass) { - rb_define_method(rb_cInteger, "big_divrem_normal", divrem_normal, 1); - rb_define_method(rb_cInteger, "big_divrem_gmp", divrem_gmp, 1); + rb_define_singleton_method(klass, "big_divrem_normal", divrem_normal, 2); + rb_define_singleton_method(klass, "big_divrem_gmp", divrem_gmp, 2); } diff --git a/ruby/ext/-test-/bignum/intpack.c b/ruby/ext/-test-/bignum/intpack.c index 2d19442cf..d5591505e 100644 --- a/ruby/ext/-test-/bignum/intpack.c +++ b/ruby/ext/-test-/bignum/intpack.c @@ -1,7 +1,7 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE -rb_integer_pack_raw_m(VALUE val, VALUE buf, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags) +rb_integer_pack_raw_m(VALUE klass, VALUE val, VALUE buf, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags) { int sign; size_t numwords = 0; @@ -17,7 +17,7 @@ rb_integer_pack_raw_m(VALUE val, VALUE buf, VALUE numwords_arg, VALUE wordsize_a } static VALUE -rb_integer_pack_m(VALUE val, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags) +rb_integer_pack_m(VALUE klass, VALUE val, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags) { int sign; size_t numwords = NUM2SIZET(numwords_arg); @@ -45,7 +45,7 @@ rb_integer_unpack_m(VALUE klass, VALUE buf, VALUE numwords, VALUE wordsize, VALU } static VALUE -rb_integer_test_numbits_2comp_without_sign(VALUE val) +rb_integer_test_numbits_2comp_without_sign(VALUE klass, VALUE val) { size_t size; int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); @@ -54,7 +54,7 @@ rb_integer_test_numbits_2comp_without_sign(VALUE val) } static VALUE -rb_integer_test_numbytes_2comp_with_sign(VALUE val) +rb_integer_test_numbytes_2comp_with_sign(VALUE klass, VALUE val) { int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); int nlz_bits; @@ -67,21 +67,21 @@ rb_integer_test_numbytes_2comp_with_sign(VALUE val) void Init_intpack(VALUE klass) { - rb_define_method(rb_cInteger, "test_pack_raw", rb_integer_pack_raw_m, 5); - rb_define_method(rb_cInteger, "test_pack", rb_integer_pack_m, 4); - rb_define_singleton_method(rb_cInteger, "test_unpack", rb_integer_unpack_m, 5); - rb_define_const(rb_cInteger, "INTEGER_PACK_MSWORD_FIRST", INT2NUM(INTEGER_PACK_MSWORD_FIRST)); - rb_define_const(rb_cInteger, "INTEGER_PACK_LSWORD_FIRST", INT2NUM(INTEGER_PACK_LSWORD_FIRST)); - rb_define_const(rb_cInteger, "INTEGER_PACK_MSBYTE_FIRST", INT2NUM(INTEGER_PACK_MSBYTE_FIRST)); - rb_define_const(rb_cInteger, "INTEGER_PACK_LSBYTE_FIRST", INT2NUM(INTEGER_PACK_LSBYTE_FIRST)); - rb_define_const(rb_cInteger, "INTEGER_PACK_NATIVE_BYTE_ORDER", INT2NUM(INTEGER_PACK_NATIVE_BYTE_ORDER)); - rb_define_const(rb_cInteger, "INTEGER_PACK_2COMP", INT2NUM(INTEGER_PACK_2COMP)); - rb_define_const(rb_cInteger, "INTEGER_PACK_LITTLE_ENDIAN", INT2NUM(INTEGER_PACK_LITTLE_ENDIAN)); - rb_define_const(rb_cInteger, "INTEGER_PACK_BIG_ENDIAN", INT2NUM(INTEGER_PACK_BIG_ENDIAN)); - rb_define_const(rb_cInteger, "INTEGER_PACK_FORCE_BIGNUM", INT2NUM(INTEGER_PACK_FORCE_BIGNUM)); - rb_define_const(rb_cInteger, "INTEGER_PACK_NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE)); - rb_define_const(rb_cInteger, "INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION", INT2NUM(INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)); + rb_define_singleton_method(klass, "test_pack_raw", rb_integer_pack_raw_m, 6); + rb_define_singleton_method(klass, "test_pack", rb_integer_pack_m, 5); + rb_define_singleton_method(klass, "test_unpack", rb_integer_unpack_m, 5); + rb_define_const(klass, "INTEGER_PACK_MSWORD_FIRST", INT2NUM(INTEGER_PACK_MSWORD_FIRST)); + rb_define_const(klass, "INTEGER_PACK_LSWORD_FIRST", INT2NUM(INTEGER_PACK_LSWORD_FIRST)); + rb_define_const(klass, "INTEGER_PACK_MSBYTE_FIRST", INT2NUM(INTEGER_PACK_MSBYTE_FIRST)); + rb_define_const(klass, "INTEGER_PACK_LSBYTE_FIRST", INT2NUM(INTEGER_PACK_LSBYTE_FIRST)); + rb_define_const(klass, "INTEGER_PACK_NATIVE_BYTE_ORDER", INT2NUM(INTEGER_PACK_NATIVE_BYTE_ORDER)); + rb_define_const(klass, "INTEGER_PACK_2COMP", INT2NUM(INTEGER_PACK_2COMP)); + rb_define_const(klass, "INTEGER_PACK_LITTLE_ENDIAN", INT2NUM(INTEGER_PACK_LITTLE_ENDIAN)); + rb_define_const(klass, "INTEGER_PACK_BIG_ENDIAN", INT2NUM(INTEGER_PACK_BIG_ENDIAN)); + rb_define_const(klass, "INTEGER_PACK_FORCE_BIGNUM", INT2NUM(INTEGER_PACK_FORCE_BIGNUM)); + rb_define_const(klass, "INTEGER_PACK_NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE)); + rb_define_const(klass, "INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION", INT2NUM(INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)); - rb_define_method(rb_cInteger, "test_numbits_2comp_without_sign", rb_integer_test_numbits_2comp_without_sign, 0); - rb_define_method(rb_cInteger, "test_numbytes_2comp_with_sign", rb_integer_test_numbytes_2comp_with_sign, 0); + rb_define_singleton_method(klass, "test_numbits_2comp_without_sign", rb_integer_test_numbits_2comp_without_sign, 1); + rb_define_singleton_method(klass, "test_numbytes_2comp_with_sign", rb_integer_test_numbytes_2comp_with_sign, 1); } diff --git a/ruby/ext/-test-/bignum/mul.c b/ruby/ext/-test-/bignum/mul.c index b922f3443..05ba103c4 100644 --- a/ruby/ext/-test-/bignum/mul.c +++ b/ruby/ext/-test-/bignum/mul.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE big(VALUE x) @@ -12,38 +12,38 @@ big(VALUE x) } static VALUE -mul_normal(VALUE x, VALUE y) +mul_normal(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_mul_normal(big(x), big(y))); } static VALUE -sq_fast(VALUE x) +sq_fast(VALUE klass, VALUE x) { return rb_big_norm(rb_big_sq_fast(big(x))); } static VALUE -mul_balance(VALUE x, VALUE y) +mul_balance(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_mul_balance(big(x), big(y))); } static VALUE -mul_karatsuba(VALUE x, VALUE y) +mul_karatsuba(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_mul_karatsuba(big(x), big(y))); } static VALUE -mul_toom3(VALUE x, VALUE y) +mul_toom3(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_mul_toom3(big(x), big(y))); } #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE -mul_gmp(VALUE x, VALUE y) +mul_gmp(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_big_mul_gmp(big(x), big(y))); } @@ -54,12 +54,12 @@ mul_gmp(VALUE x, VALUE y) void Init_mul(VALUE klass) { - rb_define_const(rb_cInteger, "SIZEOF_BDIGIT", INT2NUM(SIZEOF_BDIGIT)); - rb_define_const(rb_cInteger, "BITSPERDIG", INT2NUM(SIZEOF_BDIGIT * CHAR_BIT)); - rb_define_method(rb_cInteger, "big_mul_normal", mul_normal, 1); - rb_define_method(rb_cInteger, "big_sq_fast", sq_fast, 0); - rb_define_method(rb_cInteger, "big_mul_balance", mul_balance, 1); - rb_define_method(rb_cInteger, "big_mul_karatsuba", mul_karatsuba, 1); - rb_define_method(rb_cInteger, "big_mul_toom3", mul_toom3, 1); - rb_define_method(rb_cInteger, "big_mul_gmp", mul_gmp, 1); + rb_define_const(klass, "SIZEOF_BDIGIT", INT2NUM(SIZEOF_BDIGIT)); + rb_define_const(klass, "BITSPERDIG", INT2NUM(SIZEOF_BDIGIT * CHAR_BIT)); + rb_define_singleton_method(klass, "big_mul_normal", mul_normal, 2); + rb_define_singleton_method(klass, "big_sq_fast", sq_fast, 1); + rb_define_singleton_method(klass, "big_mul_balance", mul_balance, 2); + rb_define_singleton_method(klass, "big_mul_karatsuba", mul_karatsuba, 2); + rb_define_singleton_method(klass, "big_mul_toom3", mul_toom3, 2); + rb_define_singleton_method(klass, "big_mul_gmp", mul_gmp, 2); } diff --git a/ruby/ext/-test-/bignum/str2big.c b/ruby/ext/-test-/bignum/str2big.c index bc79ef032..337cf8fb6 100644 --- a/ruby/ext/-test-/bignum/str2big.c +++ b/ruby/ext/-test-/bignum/str2big.c @@ -1,26 +1,26 @@ -#include "internal.h" +#include "internal/bignum.h" static VALUE -str2big_poweroftwo(VALUE str, VALUE vbase, VALUE badcheck) +str2big_poweroftwo(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck) { return rb_str2big_poweroftwo(str, NUM2INT(vbase), RTEST(badcheck)); } static VALUE -str2big_normal(VALUE str, VALUE vbase, VALUE badcheck) +str2big_normal(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck) { return rb_str2big_normal(str, NUM2INT(vbase), RTEST(badcheck)); } static VALUE -str2big_karatsuba(VALUE str, VALUE vbase, VALUE badcheck) +str2big_karatsuba(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck) { return rb_str2big_karatsuba(str, NUM2INT(vbase), RTEST(badcheck)); } #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE -str2big_gmp(VALUE str, VALUE vbase, VALUE badcheck) +str2big_gmp(VALUE klass, VALUE str, VALUE vbase, VALUE badcheck) { return rb_str2big_gmp(str, NUM2INT(vbase), RTEST(badcheck)); } @@ -31,8 +31,8 @@ str2big_gmp(VALUE str, VALUE vbase, VALUE badcheck) void Init_str2big(VALUE klass) { - rb_define_method(rb_cString, "str2big_poweroftwo", str2big_poweroftwo, 2); - rb_define_method(rb_cString, "str2big_normal", str2big_normal, 2); - rb_define_method(rb_cString, "str2big_karatsuba", str2big_karatsuba, 2); - rb_define_method(rb_cString, "str2big_gmp", str2big_gmp, 2); + rb_define_singleton_method(klass, "str2big_poweroftwo", str2big_poweroftwo, 3); + rb_define_singleton_method(klass, "str2big_normal", str2big_normal, 3); + rb_define_singleton_method(klass, "str2big_karatsuba", str2big_karatsuba, 3); + rb_define_singleton_method(klass, "str2big_gmp", str2big_gmp, 3); } diff --git a/ruby/ext/-test-/bug-14834/depend b/ruby/ext/-test-/bug-14834/depend index 5206f995b..086713990 100644 --- a/ruby/ext/-test-/bug-14834/depend +++ b/ruby/ext/-test-/bug-14834/depend @@ -3,9 +3,156 @@ 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/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/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/gc.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/rgengc.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 diff --git a/ruby/ext/-test-/bug-3571/depend b/ruby/ext/-test-/bug-3571/depend index 74911f0af..73d1fec43 100644 --- a/ruby/ext/-test-/bug-3571/depend +++ b/ruby/ext/-test-/bug-3571/depend @@ -4,8 +4,155 @@ bug.o: $(arch_hdrdir)/ruby/config.h bug.o: $(hdrdir)/ruby.h bug.o: $(hdrdir)/ruby/assert.h bug.o: $(hdrdir)/ruby/backward.h +bug.o: $(hdrdir)/ruby/backward/2/assume.h +bug.o: $(hdrdir)/ruby/backward/2/attributes.h +bug.o: $(hdrdir)/ruby/backward/2/bool.h +bug.o: $(hdrdir)/ruby/backward/2/inttypes.h +bug.o: $(hdrdir)/ruby/backward/2/limits.h +bug.o: $(hdrdir)/ruby/backward/2/long_long.h +bug.o: $(hdrdir)/ruby/backward/2/stdalign.h +bug.o: $(hdrdir)/ruby/backward/2/stdarg.h bug.o: $(hdrdir)/ruby/defines.h bug.o: $(hdrdir)/ruby/intern.h +bug.o: $(hdrdir)/ruby/internal/anyargs.h +bug.o: $(hdrdir)/ruby/internal/arithmetic.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bug.o: $(hdrdir)/ruby/internal/assume.h +bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bug.o: $(hdrdir)/ruby/internal/attr/artificial.h +bug.o: $(hdrdir)/ruby/internal/attr/cold.h +bug.o: $(hdrdir)/ruby/internal/attr/const.h +bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bug.o: $(hdrdir)/ruby/internal/attr/error.h +bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bug.o: $(hdrdir)/ruby/internal/attr/format.h +bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bug.o: $(hdrdir)/ruby/internal/attr/noalias.h +bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bug.o: $(hdrdir)/ruby/internal/attr/noinline.h +bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bug.o: $(hdrdir)/ruby/internal/attr/pure.h +bug.o: $(hdrdir)/ruby/internal/attr/restrict.h +bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/warning.h +bug.o: $(hdrdir)/ruby/internal/attr/weakref.h +bug.o: $(hdrdir)/ruby/internal/cast.h +bug.o: $(hdrdir)/ruby/internal/compiler_is.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bug.o: $(hdrdir)/ruby/internal/compiler_since.h +bug.o: $(hdrdir)/ruby/internal/config.h +bug.o: $(hdrdir)/ruby/internal/constant_p.h +bug.o: $(hdrdir)/ruby/internal/core.h +bug.o: $(hdrdir)/ruby/internal/core/rarray.h +bug.o: $(hdrdir)/ruby/internal/core/rbasic.h +bug.o: $(hdrdir)/ruby/internal/core/rbignum.h +bug.o: $(hdrdir)/ruby/internal/core/rclass.h +bug.o: $(hdrdir)/ruby/internal/core/rdata.h +bug.o: $(hdrdir)/ruby/internal/core/rfile.h +bug.o: $(hdrdir)/ruby/internal/core/rhash.h +bug.o: $(hdrdir)/ruby/internal/core/robject.h +bug.o: $(hdrdir)/ruby/internal/core/rregexp.h +bug.o: $(hdrdir)/ruby/internal/core/rstring.h +bug.o: $(hdrdir)/ruby/internal/core/rstruct.h +bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bug.o: $(hdrdir)/ruby/internal/ctype.h +bug.o: $(hdrdir)/ruby/internal/dllexport.h +bug.o: $(hdrdir)/ruby/internal/dosish.h +bug.o: $(hdrdir)/ruby/internal/error.h +bug.o: $(hdrdir)/ruby/internal/eval.h +bug.o: $(hdrdir)/ruby/internal/event.h +bug.o: $(hdrdir)/ruby/internal/fl_type.h +bug.o: $(hdrdir)/ruby/internal/gc.h +bug.o: $(hdrdir)/ruby/internal/glob.h +bug.o: $(hdrdir)/ruby/internal/globals.h +bug.o: $(hdrdir)/ruby/internal/has/attribute.h +bug.o: $(hdrdir)/ruby/internal/has/builtin.h +bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/extension.h +bug.o: $(hdrdir)/ruby/internal/has/feature.h +bug.o: $(hdrdir)/ruby/internal/has/warning.h +bug.o: $(hdrdir)/ruby/internal/intern/array.h +bug.o: $(hdrdir)/ruby/internal/intern/bignum.h +bug.o: $(hdrdir)/ruby/internal/intern/class.h +bug.o: $(hdrdir)/ruby/internal/intern/compar.h +bug.o: $(hdrdir)/ruby/internal/intern/complex.h +bug.o: $(hdrdir)/ruby/internal/intern/cont.h +bug.o: $(hdrdir)/ruby/internal/intern/dir.h +bug.o: $(hdrdir)/ruby/internal/intern/enum.h +bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bug.o: $(hdrdir)/ruby/internal/intern/error.h +bug.o: $(hdrdir)/ruby/internal/intern/eval.h +bug.o: $(hdrdir)/ruby/internal/intern/file.h +bug.o: $(hdrdir)/ruby/internal/intern/gc.h +bug.o: $(hdrdir)/ruby/internal/intern/hash.h +bug.o: $(hdrdir)/ruby/internal/intern/io.h +bug.o: $(hdrdir)/ruby/internal/intern/load.h +bug.o: $(hdrdir)/ruby/internal/intern/marshal.h +bug.o: $(hdrdir)/ruby/internal/intern/numeric.h +bug.o: $(hdrdir)/ruby/internal/intern/object.h +bug.o: $(hdrdir)/ruby/internal/intern/parse.h +bug.o: $(hdrdir)/ruby/internal/intern/proc.h +bug.o: $(hdrdir)/ruby/internal/intern/process.h +bug.o: $(hdrdir)/ruby/internal/intern/random.h +bug.o: $(hdrdir)/ruby/internal/intern/range.h +bug.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bug.o: $(hdrdir)/ruby/internal/intern/string.h +bug.o: $(hdrdir)/ruby/internal/intern/struct.h +bug.o: $(hdrdir)/ruby/internal/intern/thread.h +bug.o: $(hdrdir)/ruby/internal/intern/time.h +bug.o: $(hdrdir)/ruby/internal/intern/variable.h +bug.o: $(hdrdir)/ruby/internal/intern/vm.h +bug.o: $(hdrdir)/ruby/internal/interpreter.h +bug.o: $(hdrdir)/ruby/internal/iterator.h +bug.o: $(hdrdir)/ruby/internal/memory.h +bug.o: $(hdrdir)/ruby/internal/method.h +bug.o: $(hdrdir)/ruby/internal/module.h +bug.o: $(hdrdir)/ruby/internal/newobj.h +bug.o: $(hdrdir)/ruby/internal/rgengc.h +bug.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bug.o: $(hdrdir)/ruby/internal/value.h +bug.o: $(hdrdir)/ruby/internal/value_type.h +bug.o: $(hdrdir)/ruby/internal/variable.h +bug.o: $(hdrdir)/ruby/internal/warning_push.h +bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/bug-5832/depend b/ruby/ext/-test-/bug-5832/depend index 74911f0af..73d1fec43 100644 --- a/ruby/ext/-test-/bug-5832/depend +++ b/ruby/ext/-test-/bug-5832/depend @@ -4,8 +4,155 @@ bug.o: $(arch_hdrdir)/ruby/config.h bug.o: $(hdrdir)/ruby.h bug.o: $(hdrdir)/ruby/assert.h bug.o: $(hdrdir)/ruby/backward.h +bug.o: $(hdrdir)/ruby/backward/2/assume.h +bug.o: $(hdrdir)/ruby/backward/2/attributes.h +bug.o: $(hdrdir)/ruby/backward/2/bool.h +bug.o: $(hdrdir)/ruby/backward/2/inttypes.h +bug.o: $(hdrdir)/ruby/backward/2/limits.h +bug.o: $(hdrdir)/ruby/backward/2/long_long.h +bug.o: $(hdrdir)/ruby/backward/2/stdalign.h +bug.o: $(hdrdir)/ruby/backward/2/stdarg.h bug.o: $(hdrdir)/ruby/defines.h bug.o: $(hdrdir)/ruby/intern.h +bug.o: $(hdrdir)/ruby/internal/anyargs.h +bug.o: $(hdrdir)/ruby/internal/arithmetic.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bug.o: $(hdrdir)/ruby/internal/assume.h +bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bug.o: $(hdrdir)/ruby/internal/attr/artificial.h +bug.o: $(hdrdir)/ruby/internal/attr/cold.h +bug.o: $(hdrdir)/ruby/internal/attr/const.h +bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bug.o: $(hdrdir)/ruby/internal/attr/error.h +bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bug.o: $(hdrdir)/ruby/internal/attr/format.h +bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bug.o: $(hdrdir)/ruby/internal/attr/noalias.h +bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bug.o: $(hdrdir)/ruby/internal/attr/noinline.h +bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bug.o: $(hdrdir)/ruby/internal/attr/pure.h +bug.o: $(hdrdir)/ruby/internal/attr/restrict.h +bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/warning.h +bug.o: $(hdrdir)/ruby/internal/attr/weakref.h +bug.o: $(hdrdir)/ruby/internal/cast.h +bug.o: $(hdrdir)/ruby/internal/compiler_is.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bug.o: $(hdrdir)/ruby/internal/compiler_since.h +bug.o: $(hdrdir)/ruby/internal/config.h +bug.o: $(hdrdir)/ruby/internal/constant_p.h +bug.o: $(hdrdir)/ruby/internal/core.h +bug.o: $(hdrdir)/ruby/internal/core/rarray.h +bug.o: $(hdrdir)/ruby/internal/core/rbasic.h +bug.o: $(hdrdir)/ruby/internal/core/rbignum.h +bug.o: $(hdrdir)/ruby/internal/core/rclass.h +bug.o: $(hdrdir)/ruby/internal/core/rdata.h +bug.o: $(hdrdir)/ruby/internal/core/rfile.h +bug.o: $(hdrdir)/ruby/internal/core/rhash.h +bug.o: $(hdrdir)/ruby/internal/core/robject.h +bug.o: $(hdrdir)/ruby/internal/core/rregexp.h +bug.o: $(hdrdir)/ruby/internal/core/rstring.h +bug.o: $(hdrdir)/ruby/internal/core/rstruct.h +bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bug.o: $(hdrdir)/ruby/internal/ctype.h +bug.o: $(hdrdir)/ruby/internal/dllexport.h +bug.o: $(hdrdir)/ruby/internal/dosish.h +bug.o: $(hdrdir)/ruby/internal/error.h +bug.o: $(hdrdir)/ruby/internal/eval.h +bug.o: $(hdrdir)/ruby/internal/event.h +bug.o: $(hdrdir)/ruby/internal/fl_type.h +bug.o: $(hdrdir)/ruby/internal/gc.h +bug.o: $(hdrdir)/ruby/internal/glob.h +bug.o: $(hdrdir)/ruby/internal/globals.h +bug.o: $(hdrdir)/ruby/internal/has/attribute.h +bug.o: $(hdrdir)/ruby/internal/has/builtin.h +bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/extension.h +bug.o: $(hdrdir)/ruby/internal/has/feature.h +bug.o: $(hdrdir)/ruby/internal/has/warning.h +bug.o: $(hdrdir)/ruby/internal/intern/array.h +bug.o: $(hdrdir)/ruby/internal/intern/bignum.h +bug.o: $(hdrdir)/ruby/internal/intern/class.h +bug.o: $(hdrdir)/ruby/internal/intern/compar.h +bug.o: $(hdrdir)/ruby/internal/intern/complex.h +bug.o: $(hdrdir)/ruby/internal/intern/cont.h +bug.o: $(hdrdir)/ruby/internal/intern/dir.h +bug.o: $(hdrdir)/ruby/internal/intern/enum.h +bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bug.o: $(hdrdir)/ruby/internal/intern/error.h +bug.o: $(hdrdir)/ruby/internal/intern/eval.h +bug.o: $(hdrdir)/ruby/internal/intern/file.h +bug.o: $(hdrdir)/ruby/internal/intern/gc.h +bug.o: $(hdrdir)/ruby/internal/intern/hash.h +bug.o: $(hdrdir)/ruby/internal/intern/io.h +bug.o: $(hdrdir)/ruby/internal/intern/load.h +bug.o: $(hdrdir)/ruby/internal/intern/marshal.h +bug.o: $(hdrdir)/ruby/internal/intern/numeric.h +bug.o: $(hdrdir)/ruby/internal/intern/object.h +bug.o: $(hdrdir)/ruby/internal/intern/parse.h +bug.o: $(hdrdir)/ruby/internal/intern/proc.h +bug.o: $(hdrdir)/ruby/internal/intern/process.h +bug.o: $(hdrdir)/ruby/internal/intern/random.h +bug.o: $(hdrdir)/ruby/internal/intern/range.h +bug.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bug.o: $(hdrdir)/ruby/internal/intern/string.h +bug.o: $(hdrdir)/ruby/internal/intern/struct.h +bug.o: $(hdrdir)/ruby/internal/intern/thread.h +bug.o: $(hdrdir)/ruby/internal/intern/time.h +bug.o: $(hdrdir)/ruby/internal/intern/variable.h +bug.o: $(hdrdir)/ruby/internal/intern/vm.h +bug.o: $(hdrdir)/ruby/internal/interpreter.h +bug.o: $(hdrdir)/ruby/internal/iterator.h +bug.o: $(hdrdir)/ruby/internal/memory.h +bug.o: $(hdrdir)/ruby/internal/method.h +bug.o: $(hdrdir)/ruby/internal/module.h +bug.o: $(hdrdir)/ruby/internal/newobj.h +bug.o: $(hdrdir)/ruby/internal/rgengc.h +bug.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bug.o: $(hdrdir)/ruby/internal/value.h +bug.o: $(hdrdir)/ruby/internal/value_type.h +bug.o: $(hdrdir)/ruby/internal/variable.h +bug.o: $(hdrdir)/ruby/internal/warning_push.h +bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/bug_reporter/depend b/ruby/ext/-test-/bug_reporter/depend index 62bac0356..d36d0fb6c 100644 --- a/ruby/ext/-test-/bug_reporter/depend +++ b/ruby/ext/-test-/bug_reporter/depend @@ -4,8 +4,155 @@ bug_reporter.o: $(arch_hdrdir)/ruby/config.h bug_reporter.o: $(hdrdir)/ruby.h bug_reporter.o: $(hdrdir)/ruby/assert.h bug_reporter.o: $(hdrdir)/ruby/backward.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/assume.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/attributes.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/bool.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/inttypes.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/limits.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/long_long.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/stdalign.h +bug_reporter.o: $(hdrdir)/ruby/backward/2/stdarg.h bug_reporter.o: $(hdrdir)/ruby/defines.h bug_reporter.o: $(hdrdir)/ruby/intern.h +bug_reporter.o: $(hdrdir)/ruby/internal/anyargs.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bug_reporter.o: $(hdrdir)/ruby/internal/assume.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/artificial.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/cold.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/const.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/error.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/format.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/noalias.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/noinline.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/pure.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/restrict.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/warning.h +bug_reporter.o: $(hdrdir)/ruby/internal/attr/weakref.h +bug_reporter.o: $(hdrdir)/ruby/internal/cast.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bug_reporter.o: $(hdrdir)/ruby/internal/compiler_since.h +bug_reporter.o: $(hdrdir)/ruby/internal/config.h +bug_reporter.o: $(hdrdir)/ruby/internal/constant_p.h +bug_reporter.o: $(hdrdir)/ruby/internal/core.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rarray.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rbasic.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rbignum.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rclass.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rdata.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rfile.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rhash.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/robject.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rregexp.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rstring.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rstruct.h +bug_reporter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bug_reporter.o: $(hdrdir)/ruby/internal/ctype.h +bug_reporter.o: $(hdrdir)/ruby/internal/dllexport.h +bug_reporter.o: $(hdrdir)/ruby/internal/dosish.h +bug_reporter.o: $(hdrdir)/ruby/internal/error.h +bug_reporter.o: $(hdrdir)/ruby/internal/eval.h +bug_reporter.o: $(hdrdir)/ruby/internal/event.h +bug_reporter.o: $(hdrdir)/ruby/internal/fl_type.h +bug_reporter.o: $(hdrdir)/ruby/internal/gc.h +bug_reporter.o: $(hdrdir)/ruby/internal/glob.h +bug_reporter.o: $(hdrdir)/ruby/internal/globals.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/attribute.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/builtin.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/extension.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/feature.h +bug_reporter.o: $(hdrdir)/ruby/internal/has/warning.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/array.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/bignum.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/class.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/compar.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/complex.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/cont.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/dir.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/enum.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/error.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/eval.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/file.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/gc.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/hash.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/io.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/load.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/marshal.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/numeric.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/object.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/parse.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/proc.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/process.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/random.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/range.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/string.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/struct.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/thread.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/time.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/variable.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/vm.h +bug_reporter.o: $(hdrdir)/ruby/internal/interpreter.h +bug_reporter.o: $(hdrdir)/ruby/internal/iterator.h +bug_reporter.o: $(hdrdir)/ruby/internal/memory.h +bug_reporter.o: $(hdrdir)/ruby/internal/method.h +bug_reporter.o: $(hdrdir)/ruby/internal/module.h +bug_reporter.o: $(hdrdir)/ruby/internal/newobj.h +bug_reporter.o: $(hdrdir)/ruby/internal/rgengc.h +bug_reporter.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bug_reporter.o: $(hdrdir)/ruby/internal/value.h +bug_reporter.o: $(hdrdir)/ruby/internal/value_type.h +bug_reporter.o: $(hdrdir)/ruby/internal/variable.h +bug_reporter.o: $(hdrdir)/ruby/internal/warning_push.h +bug_reporter.o: $(hdrdir)/ruby/internal/xmalloc.h bug_reporter.o: $(hdrdir)/ruby/missing.h bug_reporter.o: $(hdrdir)/ruby/ruby.h bug_reporter.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/class/depend b/ruby/ext/-test-/class/depend index 451256cc7..bb74e1f24 100644 --- a/ruby/ext/-test-/class/depend +++ b/ruby/ext/-test-/class/depend @@ -3,8 +3,155 @@ class2name.o: $(RUBY_EXTCONF_H) class2name.o: $(arch_hdrdir)/ruby/config.h class2name.o: $(hdrdir)/ruby/assert.h class2name.o: $(hdrdir)/ruby/backward.h +class2name.o: $(hdrdir)/ruby/backward/2/assume.h +class2name.o: $(hdrdir)/ruby/backward/2/attributes.h +class2name.o: $(hdrdir)/ruby/backward/2/bool.h +class2name.o: $(hdrdir)/ruby/backward/2/inttypes.h +class2name.o: $(hdrdir)/ruby/backward/2/limits.h +class2name.o: $(hdrdir)/ruby/backward/2/long_long.h +class2name.o: $(hdrdir)/ruby/backward/2/stdalign.h +class2name.o: $(hdrdir)/ruby/backward/2/stdarg.h class2name.o: $(hdrdir)/ruby/defines.h class2name.o: $(hdrdir)/ruby/intern.h +class2name.o: $(hdrdir)/ruby/internal/anyargs.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/char.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/double.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/int.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/long.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/short.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +class2name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +class2name.o: $(hdrdir)/ruby/internal/assume.h +class2name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +class2name.o: $(hdrdir)/ruby/internal/attr/artificial.h +class2name.o: $(hdrdir)/ruby/internal/attr/cold.h +class2name.o: $(hdrdir)/ruby/internal/attr/const.h +class2name.o: $(hdrdir)/ruby/internal/attr/constexpr.h +class2name.o: $(hdrdir)/ruby/internal/attr/deprecated.h +class2name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +class2name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +class2name.o: $(hdrdir)/ruby/internal/attr/error.h +class2name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +class2name.o: $(hdrdir)/ruby/internal/attr/forceinline.h +class2name.o: $(hdrdir)/ruby/internal/attr/format.h +class2name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +class2name.o: $(hdrdir)/ruby/internal/attr/noalias.h +class2name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +class2name.o: $(hdrdir)/ruby/internal/attr/noexcept.h +class2name.o: $(hdrdir)/ruby/internal/attr/noinline.h +class2name.o: $(hdrdir)/ruby/internal/attr/nonnull.h +class2name.o: $(hdrdir)/ruby/internal/attr/noreturn.h +class2name.o: $(hdrdir)/ruby/internal/attr/pure.h +class2name.o: $(hdrdir)/ruby/internal/attr/restrict.h +class2name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +class2name.o: $(hdrdir)/ruby/internal/attr/warning.h +class2name.o: $(hdrdir)/ruby/internal/attr/weakref.h +class2name.o: $(hdrdir)/ruby/internal/cast.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +class2name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +class2name.o: $(hdrdir)/ruby/internal/compiler_since.h +class2name.o: $(hdrdir)/ruby/internal/config.h +class2name.o: $(hdrdir)/ruby/internal/constant_p.h +class2name.o: $(hdrdir)/ruby/internal/core.h +class2name.o: $(hdrdir)/ruby/internal/core/rarray.h +class2name.o: $(hdrdir)/ruby/internal/core/rbasic.h +class2name.o: $(hdrdir)/ruby/internal/core/rbignum.h +class2name.o: $(hdrdir)/ruby/internal/core/rclass.h +class2name.o: $(hdrdir)/ruby/internal/core/rdata.h +class2name.o: $(hdrdir)/ruby/internal/core/rfile.h +class2name.o: $(hdrdir)/ruby/internal/core/rhash.h +class2name.o: $(hdrdir)/ruby/internal/core/robject.h +class2name.o: $(hdrdir)/ruby/internal/core/rregexp.h +class2name.o: $(hdrdir)/ruby/internal/core/rstring.h +class2name.o: $(hdrdir)/ruby/internal/core/rstruct.h +class2name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +class2name.o: $(hdrdir)/ruby/internal/ctype.h +class2name.o: $(hdrdir)/ruby/internal/dllexport.h +class2name.o: $(hdrdir)/ruby/internal/dosish.h +class2name.o: $(hdrdir)/ruby/internal/error.h +class2name.o: $(hdrdir)/ruby/internal/eval.h +class2name.o: $(hdrdir)/ruby/internal/event.h +class2name.o: $(hdrdir)/ruby/internal/fl_type.h +class2name.o: $(hdrdir)/ruby/internal/gc.h +class2name.o: $(hdrdir)/ruby/internal/glob.h +class2name.o: $(hdrdir)/ruby/internal/globals.h +class2name.o: $(hdrdir)/ruby/internal/has/attribute.h +class2name.o: $(hdrdir)/ruby/internal/has/builtin.h +class2name.o: $(hdrdir)/ruby/internal/has/c_attribute.h +class2name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +class2name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +class2name.o: $(hdrdir)/ruby/internal/has/extension.h +class2name.o: $(hdrdir)/ruby/internal/has/feature.h +class2name.o: $(hdrdir)/ruby/internal/has/warning.h +class2name.o: $(hdrdir)/ruby/internal/intern/array.h +class2name.o: $(hdrdir)/ruby/internal/intern/bignum.h +class2name.o: $(hdrdir)/ruby/internal/intern/class.h +class2name.o: $(hdrdir)/ruby/internal/intern/compar.h +class2name.o: $(hdrdir)/ruby/internal/intern/complex.h +class2name.o: $(hdrdir)/ruby/internal/intern/cont.h +class2name.o: $(hdrdir)/ruby/internal/intern/dir.h +class2name.o: $(hdrdir)/ruby/internal/intern/enum.h +class2name.o: $(hdrdir)/ruby/internal/intern/enumerator.h +class2name.o: $(hdrdir)/ruby/internal/intern/error.h +class2name.o: $(hdrdir)/ruby/internal/intern/eval.h +class2name.o: $(hdrdir)/ruby/internal/intern/file.h +class2name.o: $(hdrdir)/ruby/internal/intern/gc.h +class2name.o: $(hdrdir)/ruby/internal/intern/hash.h +class2name.o: $(hdrdir)/ruby/internal/intern/io.h +class2name.o: $(hdrdir)/ruby/internal/intern/load.h +class2name.o: $(hdrdir)/ruby/internal/intern/marshal.h +class2name.o: $(hdrdir)/ruby/internal/intern/numeric.h +class2name.o: $(hdrdir)/ruby/internal/intern/object.h +class2name.o: $(hdrdir)/ruby/internal/intern/parse.h +class2name.o: $(hdrdir)/ruby/internal/intern/proc.h +class2name.o: $(hdrdir)/ruby/internal/intern/process.h +class2name.o: $(hdrdir)/ruby/internal/intern/random.h +class2name.o: $(hdrdir)/ruby/internal/intern/range.h +class2name.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +class2name.o: $(hdrdir)/ruby/internal/intern/sprintf.h +class2name.o: $(hdrdir)/ruby/internal/intern/string.h +class2name.o: $(hdrdir)/ruby/internal/intern/struct.h +class2name.o: $(hdrdir)/ruby/internal/intern/thread.h +class2name.o: $(hdrdir)/ruby/internal/intern/time.h +class2name.o: $(hdrdir)/ruby/internal/intern/variable.h +class2name.o: $(hdrdir)/ruby/internal/intern/vm.h +class2name.o: $(hdrdir)/ruby/internal/interpreter.h +class2name.o: $(hdrdir)/ruby/internal/iterator.h +class2name.o: $(hdrdir)/ruby/internal/memory.h +class2name.o: $(hdrdir)/ruby/internal/method.h +class2name.o: $(hdrdir)/ruby/internal/module.h +class2name.o: $(hdrdir)/ruby/internal/newobj.h +class2name.o: $(hdrdir)/ruby/internal/rgengc.h +class2name.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +class2name.o: $(hdrdir)/ruby/internal/value.h +class2name.o: $(hdrdir)/ruby/internal/value_type.h +class2name.o: $(hdrdir)/ruby/internal/variable.h +class2name.o: $(hdrdir)/ruby/internal/warning_push.h +class2name.o: $(hdrdir)/ruby/internal/xmalloc.h class2name.o: $(hdrdir)/ruby/missing.h class2name.o: $(hdrdir)/ruby/ruby.h class2name.o: $(hdrdir)/ruby/st.h @@ -15,8 +162,155 @@ 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/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/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/gc.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/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/rgengc.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/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 diff --git a/ruby/ext/-test-/cxxanyargs/cxxanyargs.cpp b/ruby/ext/-test-/cxxanyargs/cxxanyargs.cpp index efe35fa35..eded13e2e 100644 --- a/ruby/ext/-test-/cxxanyargs/cxxanyargs.cpp +++ b/ruby/ext/-test-/cxxanyargs/cxxanyargs.cpp @@ -5,12 +5,18 @@ #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. @@ -36,6 +42,18 @@ namespace test_rb_define_virtual_variable { RUBY_METHOD_FUNC(getter), reinterpret_cast(setter)); // old rb_define_virtual_variable("test", getter, setter); // new + +#ifdef HAVE_NULLPTR + rb_define_virtual_variable("test", nullptr, reinterpret_cast(setter)); + rb_define_virtual_variable("test", nullptr, setter); + + rb_define_virtual_variable("test", RUBY_METHOD_FUNC(getter), nullptr); + rb_define_virtual_variable("test", getter, nullptr); + + // It doesn't make any sense for both function pointers be nullptr at + // the same time. +#endif + return self; } } @@ -62,6 +80,18 @@ struct test_rb_define_hooked_variable { RUBY_METHOD_FUNC(getter), reinterpret_cast(setter)); // old rb_define_hooked_variable("test", &v, getter, setter); // new + +#ifdef HAVE_NULLPTR + rb_define_hooked_variable("test", &v, nullptr, reinterpret_cast(setter)); + rb_define_hooked_variable("test", &v, nullptr, setter); + + rb_define_hooked_variable("test", &v, RUBY_METHOD_FUNC(getter), nullptr); + rb_define_hooked_variable("test", &v, getter, nullptr); + + // It doesn't make any sense for both function pointers be nullptr at + // the same time. +#endif + return self; } }; @@ -83,6 +113,10 @@ namespace test_rb_iterate { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + rb_iterate(iter, self, nullptr, self); +#endif + rb_iterate(iter, self, RUBY_METHOD_FUNC(block), self); // old return rb_iterate(iter, self, block, self); // new } @@ -100,6 +134,11 @@ namespace test_rb_block_call { { const ID mid = rb_intern("each"); const VALUE argv[] = { Qundef }; + +#ifdef HAVE_NULLPTR + rb_block_call(self, mid, 0, argv, nullptr, self); +#endif + rb_block_call(self, mid, 0, argv, RUBY_METHOD_FUNC(block), self); // old return rb_block_call(self, mid, 0, argv, block, self); // new } @@ -121,6 +160,11 @@ namespace test_rb_rescue { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + rb_rescue(RUBY_METHOD_FUNC(begin), self, nullptr, self); + rb_rescue(begin, self, nullptr, self); +#endif + rb_rescue(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self); // old return rb_rescue(begin, self, rescue, self); // new } @@ -142,9 +186,14 @@ namespace test_rb_rescue2 { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + rb_rescue2(RUBY_METHOD_FUNC(begin), self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0); + rb_rescue2(begin, self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0); +#endif + rb_rescue2(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self, - rb_eStandardError, rb_eFatal, 0); // old - return rb_rescue2(begin, self, rescue, self, rb_eStandardError, rb_eFatal, 0); // new + rb_eStandardError, rb_eFatal, (VALUE)0); // old + return rb_rescue2(begin, self, rescue, self, rb_eStandardError, rb_eFatal, (VALUE)0); // new } } @@ -164,6 +213,11 @@ namespace test_rb_ensure { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + rb_ensure(RUBY_METHOD_FUNC(begin), self, nullptr, self); + rb_ensure(begin, self, nullptr, self); +#endif + rb_ensure(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(ensure), self); // old return rb_ensure(begin, self, ensure, self); // new } @@ -180,6 +234,11 @@ namespace test_rb_catch { test(VALUE self) { static const char *zero = 0; + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a catcher. +#endif + rb_catch(zero, RUBY_METHOD_FUNC(catcher), self); // old return rb_catch(zero, catcher, self); // new } @@ -195,6 +254,10 @@ namespace test_rb_catch_obj { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a catcher. +#endif + rb_catch_obj(self, RUBY_METHOD_FUNC(catcher), self); // old return rb_catch_obj(self, catcher, self); // new } @@ -210,6 +273,10 @@ namespace test_rb_fiber_new { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a fiber. +#endif + rb_fiber_new(RUBY_METHOD_FUNC(fiber), self); // old return rb_fiber_new(fiber, self); // new } @@ -225,6 +292,10 @@ namespace test_rb_proc_new { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a proc. +#endif + rb_fiber_new(RUBY_METHOD_FUNC(proc), self); // old return rb_fiber_new(proc, self); // new } @@ -244,6 +315,11 @@ struct test_rb_thread_create { test(VALUE self) { v = self; + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a thread. +#endif + rb_thread_create(RUBY_METHOD_FUNC(thread), &v); // old return rb_thread_create(thread, &v); // new } @@ -262,6 +338,11 @@ namespace test_st_foreach { { st_data_t data = 0; st_table *st = st_init_numtable(); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as an iterator. +#endif + st_foreach(st, reinterpret_cast(iter), data); // old st_foreach(st, iter, data); // new return self; @@ -280,6 +361,11 @@ namespace test_st_foreach_check { { st_data_t data = 0; st_table *st = st_init_numtable(); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as an iterator. +#endif + st_foreach_check(st, reinterpret_cast(iter), data, data); // old st_foreach_check(st, iter, data, data); // new return self; @@ -298,6 +384,11 @@ namespace test_st_foreach_safe { { st_data_t data = 0; st_table *st = st_init_numtable(); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as an iterator. +#endif + st_foreach_safe(st, reinterpret_cast(iter), data); // old st_foreach_safe(st, iter, data); // new return self; @@ -315,6 +406,11 @@ namespace test_rb_hash_foreach { test(VALUE self) { VALUE h = rb_hash_new(); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as an iterator. +#endif + rb_hash_foreach(h, reinterpret_cast(iter), self); // old rb_hash_foreach(h, iter, self); // new return self; @@ -331,6 +427,10 @@ namespace test_rb_ivar_foreach { VALUE test(VALUE self) { +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as an iterator. +#endif + rb_ivar_foreach(self, reinterpret_cast(iter), self); // old rb_ivar_foreach(self, iter, self); // new return self; @@ -362,6 +462,12 @@ namespace test_rb_define_method { return Qnil; } + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + VALUE test(VALUE self) { @@ -370,18 +476,102 @@ namespace test_rb_define_method { rb_define_method(self, "m2", m2, 2); rb_define_method(self, "ma", ma, -2); rb_define_method(self, "mv", mv, -1); + rb_define_method(self, "mc", mc, -1); // Cast by RUBY_METHOD_FUNC rb_define_method(self, "m1", RUBY_METHOD_FUNC(m1), 1); rb_define_method(self, "m2", RUBY_METHOD_FUNC(m2), 2); rb_define_method(self, "ma", RUBY_METHOD_FUNC(ma), -2); rb_define_method(self, "mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_method(self, "mc", RUBY_METHOD_FUNC(mc), -1); // Explicit cast instead of RUBY_METHOD_FUNC rb_define_method(self, "m1", (VALUE (*)(...))(m1), 1); rb_define_method(self, "m2", (VALUE (*)(...))(m2), 2); rb_define_method(self, "ma", (VALUE (*)(...))(ma), -2); rb_define_method(self, "mv", (VALUE (*)(...))(mv), -1); + rb_define_method(self, "mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_method(self, "m1", rb_f_notimplement, 1); + rb_define_method(self, "m2", rb_f_notimplement, 2); + rb_define_method(self, "ma", rb_f_notimplement, -2); + rb_define_method(self, "mv", rb_f_notimplement, -1); + rb_define_method(self, "mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif + + return self; + } +} + +namespace test_rb_define_method_id { + static VALUE + m1(VALUE, VALUE) + { + return Qnil; + } + + static VALUE + m2(VALUE, VALUE, VALUE) + { + return Qnil; + } + + static VALUE + ma(VALUE, VALUE) + { + return Qnil; + } + + static VALUE + mv(int, VALUE*, VALUE) + { + return Qnil; + } + + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + + VALUE + test(VALUE self) + { + // No cast + rb_define_method_id(self, rb_intern("m1"), m1, 1); + rb_define_method_id(self, rb_intern("m2"), m2, 2); + rb_define_method_id(self, rb_intern("ma"), ma, -2); + rb_define_method_id(self, rb_intern("mv"), mv, -1); + rb_define_method_id(self, rb_intern("mc"), mc, -1); + + // Cast by RUBY_METHOD_FUNC + rb_define_method_id(self, rb_intern("m1"), RUBY_METHOD_FUNC(m1), 1); + rb_define_method_id(self, rb_intern("m2"), RUBY_METHOD_FUNC(m2), 2); + rb_define_method_id(self, rb_intern("ma"), RUBY_METHOD_FUNC(ma), -2); + rb_define_method_id(self, rb_intern("mv"), RUBY_METHOD_FUNC(mv), -1); + rb_define_method_id(self, rb_intern("mc"), RUBY_METHOD_FUNC(mc), -1); + + // Explicit cast instead of RUBY_METHOD_FUNC + rb_define_method_id(self, rb_intern("m1"), (VALUE (*)(...))(m1), 1); + rb_define_method_id(self, rb_intern("m2"), (VALUE (*)(...))(m2), 2); + rb_define_method_id(self, rb_intern("ma"), (VALUE (*)(...))(ma), -2); + rb_define_method_id(self, rb_intern("mv"), (VALUE (*)(...))(mv), -1); + rb_define_method_id(self, rb_intern("mc"), (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_method_id(self, rb_intern("m1"), rb_f_notimplement, 1); + rb_define_method_id(self, rb_intern("m2"), rb_f_notimplement, 2); + rb_define_method_id(self, rb_intern("ma"), rb_f_notimplement, -2); + rb_define_method_id(self, rb_intern("mv"), rb_f_notimplement, -1); + rb_define_method_id(self, rb_intern("mc"), rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif return self; } @@ -412,6 +602,12 @@ namespace test_rb_define_module_function { return Qnil; } + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + VALUE test(VALUE self) { @@ -420,18 +616,32 @@ namespace test_rb_define_module_function { rb_define_module_function(self, "m2", m2, 2); rb_define_module_function(self, "ma", ma, -2); rb_define_module_function(self, "mv", mv, -1); + rb_define_module_function(self, "mc", mc, -1); // Cast by RUBY_METHOD_FUNC rb_define_module_function(self, "m1", RUBY_METHOD_FUNC(m1), 1); rb_define_module_function(self, "m2", RUBY_METHOD_FUNC(m2), 2); rb_define_module_function(self, "ma", RUBY_METHOD_FUNC(ma), -2); rb_define_module_function(self, "mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_module_function(self, "mc", RUBY_METHOD_FUNC(mc), -1); // Explicit cast instead of RUBY_METHOD_FUNC rb_define_module_function(self, "m1", (VALUE (*)(...))(m1), 1); rb_define_module_function(self, "m2", (VALUE (*)(...))(m2), 2); rb_define_module_function(self, "ma", (VALUE (*)(...))(ma), -2); rb_define_module_function(self, "mv", (VALUE (*)(...))(mv), -1); + rb_define_module_function(self, "mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_module_function(self, "m1", rb_f_notimplement, 1); + rb_define_module_function(self, "m2", rb_f_notimplement, 2); + rb_define_module_function(self, "ma", rb_f_notimplement, -2); + rb_define_module_function(self, "mv", rb_f_notimplement, -1); + rb_define_module_function(self, "mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif return self; } @@ -462,6 +672,12 @@ namespace test_rb_define_singleton_method { return Qnil; } + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + VALUE test(VALUE self) { @@ -470,18 +686,32 @@ namespace test_rb_define_singleton_method { rb_define_singleton_method(self, "m2", m2, 2); rb_define_singleton_method(self, "ma", ma, -2); rb_define_singleton_method(self, "mv", mv, -1); + rb_define_singleton_method(self, "mc", mc, -1); // Cast by RUBY_METHOD_FUNC rb_define_singleton_method(self, "m1", RUBY_METHOD_FUNC(m1), 1); rb_define_singleton_method(self, "m2", RUBY_METHOD_FUNC(m2), 2); rb_define_singleton_method(self, "ma", RUBY_METHOD_FUNC(ma), -2); rb_define_singleton_method(self, "mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_singleton_method(self, "mc", RUBY_METHOD_FUNC(mc), -1); // Explicit cast instead of RUBY_METHOD_FUNC rb_define_singleton_method(self, "m1", (VALUE (*)(...))(m1), 1); rb_define_singleton_method(self, "m2", (VALUE (*)(...))(m2), 2); rb_define_singleton_method(self, "ma", (VALUE (*)(...))(ma), -2); rb_define_singleton_method(self, "mv", (VALUE (*)(...))(mv), -1); + rb_define_singleton_method(self, "mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_singleton_method(self, "m1", rb_f_notimplement, 1); + rb_define_singleton_method(self, "m2", rb_f_notimplement, 2); + rb_define_singleton_method(self, "ma", rb_f_notimplement, -2); + rb_define_singleton_method(self, "mv", rb_f_notimplement, -1); + rb_define_singleton_method(self, "mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif return self; } @@ -512,6 +742,12 @@ namespace test_rb_define_protected_method { return Qnil; } + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + VALUE test(VALUE self) { @@ -520,18 +756,32 @@ namespace test_rb_define_protected_method { rb_define_protected_method(self, "m2", m2, 2); rb_define_protected_method(self, "ma", ma, -2); rb_define_protected_method(self, "mv", mv, -1); + rb_define_protected_method(self, "mc", mc, -1); // Cast by RUBY_METHOD_FUNC rb_define_protected_method(self, "m1", RUBY_METHOD_FUNC(m1), 1); rb_define_protected_method(self, "m2", RUBY_METHOD_FUNC(m2), 2); rb_define_protected_method(self, "ma", RUBY_METHOD_FUNC(ma), -2); rb_define_protected_method(self, "mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_protected_method(self, "mc", RUBY_METHOD_FUNC(mc), -1); // Explicit cast instead of RUBY_METHOD_FUNC rb_define_protected_method(self, "m1", (VALUE (*)(...))(m1), 1); rb_define_protected_method(self, "m2", (VALUE (*)(...))(m2), 2); rb_define_protected_method(self, "ma", (VALUE (*)(...))(ma), -2); rb_define_protected_method(self, "mv", (VALUE (*)(...))(mv), -1); + rb_define_protected_method(self, "mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_protected_method(self, "m1", rb_f_notimplement, 1); + rb_define_protected_method(self, "m2", rb_f_notimplement, 2); + rb_define_protected_method(self, "ma", rb_f_notimplement, -2); + rb_define_protected_method(self, "mv", rb_f_notimplement, -1); + rb_define_protected_method(self, "mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif return self; } @@ -562,6 +812,12 @@ namespace test_rb_define_private_method { return Qnil; } + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + VALUE test(VALUE self) { @@ -570,18 +826,102 @@ namespace test_rb_define_private_method { rb_define_private_method(self, "m2", m2, 2); rb_define_private_method(self, "ma", ma, -2); rb_define_private_method(self, "mv", mv, -1); + rb_define_private_method(self, "mc", mc, -1); // Cast by RUBY_METHOD_FUNC rb_define_private_method(self, "m1", RUBY_METHOD_FUNC(m1), 1); rb_define_private_method(self, "m2", RUBY_METHOD_FUNC(m2), 2); rb_define_private_method(self, "ma", RUBY_METHOD_FUNC(ma), -2); rb_define_private_method(self, "mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_private_method(self, "mc", RUBY_METHOD_FUNC(mc), -1); // Explicit cast instead of RUBY_METHOD_FUNC rb_define_private_method(self, "m1", (VALUE (*)(...))(m1), 1); rb_define_private_method(self, "m2", (VALUE (*)(...))(m2), 2); rb_define_private_method(self, "ma", (VALUE (*)(...))(ma), -2); rb_define_private_method(self, "mv", (VALUE (*)(...))(mv), -1); + rb_define_private_method(self, "mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_private_method(self, "m1", rb_f_notimplement, 1); + rb_define_private_method(self, "m2", rb_f_notimplement, 2); + rb_define_private_method(self, "ma", rb_f_notimplement, -2); + rb_define_private_method(self, "mv", rb_f_notimplement, -1); + rb_define_private_method(self, "mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif + + return self; + } +} + +namespace test_rb_define_global_function { + static VALUE + m1(VALUE, VALUE) + { + return Qnil; + } + + static VALUE + m2(VALUE, VALUE, VALUE) + { + return Qnil; + } + + static VALUE + ma(VALUE, VALUE) + { + return Qnil; + } + + static VALUE + mv(int, VALUE*, VALUE) + { + return Qnil; + } + + static VALUE + mc(int, const VALUE*, VALUE) + { + return Qnil; + } + + VALUE + test(VALUE self) + { + // No cast + rb_define_global_function("m1", m1, 1); + rb_define_global_function("m2", m2, 2); + rb_define_global_function("ma", ma, -2); + rb_define_global_function("mv", mv, -1); + rb_define_global_function("mc", mc, -1); + + // Cast by RUBY_METHOD_FUNC + rb_define_global_function("m1", RUBY_METHOD_FUNC(m1), 1); + rb_define_global_function("m2", RUBY_METHOD_FUNC(m2), 2); + rb_define_global_function("ma", RUBY_METHOD_FUNC(ma), -2); + rb_define_global_function("mv", RUBY_METHOD_FUNC(mv), -1); + rb_define_global_function("mc", RUBY_METHOD_FUNC(mc), -1); + + // Explicit cast instead of RUBY_METHOD_FUNC + rb_define_global_function("m1", (VALUE (*)(...))(m1), 1); + rb_define_global_function("m2", (VALUE (*)(...))(m2), 2); + rb_define_global_function("ma", (VALUE (*)(...))(ma), -2); + rb_define_global_function("mv", (VALUE (*)(...))(mv), -1); + rb_define_global_function("mc", (VALUE (*)(...))(mc), -1); + + // rb_f_notimplement + rb_define_global_function("m1", rb_f_notimplement, 1); + rb_define_global_function("m2", rb_f_notimplement, 2); + rb_define_global_function("ma", rb_f_notimplement, -2); + rb_define_global_function("mv", rb_f_notimplement, -1); + rb_define_global_function("mc", rb_f_notimplement, -1); + +#ifdef HAVE_NULLPTR + // It doesn't make any sense at all to pass nullptr as a method. +#endif return self; } @@ -612,8 +952,10 @@ Init_cxxanyargs(void) test(rb_hash_foreach); test(rb_ivar_foreach); test(rb_define_method); + test(rb_define_method_id); test(rb_define_module_function); test(rb_define_singleton_method); test(rb_define_protected_method); test(rb_define_private_method); + test(rb_define_global_function); } diff --git a/ruby/ext/-test-/cxxanyargs/depend b/ruby/ext/-test-/cxxanyargs/depend index 02113b6c2..fc3d8e45d 100644 --- a/ruby/ext/-test-/cxxanyargs/depend +++ b/ruby/ext/-test-/cxxanyargs/depend @@ -6,20 +6,8 @@ $(TARGET_SO) $(STATIC_LIB): $(FAILURES:.cpp=.failed) $(Q)$(RUBY) -rfileutils \ -e "t = ARGV.shift" \ -e "err = IO.popen(ARGV, err:[:child, :out], &:read)" \ - -e "abort err unless /rb_define_method/ =~ err" \ + -e "abort err unless /rb_define_method/ =~ err.b" \ -e "File.write(t, err)" $@ $(MAKE) $(*F).o # AUTOGENERATED DEPENDENCIES START -cxxanyargs.o: $(RUBY_EXTCONF_H) -cxxanyargs.o: $(arch_hdrdir)/ruby/config.h -cxxanyargs.o: $(hdrdir)/ruby/assert.h -cxxanyargs.o: $(hdrdir)/ruby/backward.h -cxxanyargs.o: $(hdrdir)/ruby/backward/cxxanyargs.hpp -cxxanyargs.o: $(hdrdir)/ruby/defines.h -cxxanyargs.o: $(hdrdir)/ruby/intern.h -cxxanyargs.o: $(hdrdir)/ruby/missing.h -cxxanyargs.o: $(hdrdir)/ruby/ruby.h -cxxanyargs.o: $(hdrdir)/ruby/st.h -cxxanyargs.o: $(hdrdir)/ruby/subst.h -cxxanyargs.o: cxxanyargs.cpp # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/cxxanyargs/extconf.rb b/ruby/ext/-test-/cxxanyargs/extconf.rb index 08d8c8301..9749f4206 100644 --- a/ruby/ext/-test-/cxxanyargs/extconf.rb +++ b/ruby/ext/-test-/cxxanyargs/extconf.rb @@ -2,12 +2,23 @@ cxx = MakeMakefile["C++"] -ok = cxx.try_compile(<<~'begin', "") do |x| +# #### have_devel hack #### +# cxx.try_compile tries to detect compilers, but the try_compile below is +# trying to detect a compiler in a different way. We need to prevent the +# default detection routine. + +cxx.instance_variable_set(:'@have_devel', true) + +ok = cxx.try_link(<<~'begin', "") do |x| #include "ruby/config.h" + #ifdef RUBY_ALTERNATIVE_MALLOC_HEADER + # include RUBY_ALTERNATIVE_MALLOC_HEADER + #endif + namespace { - typedef int conftest[SIZEOF_LONG == sizeof(long) ? 1 : -1]; - typedef int conftest[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1]; + typedef int conftest1[SIZEOF_LONG == sizeof(long) ? 1 : -1]; + typedef int conftest2[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1]; } int @@ -21,6 +32,8 @@ x.sub! %<#include "ruby.h">, '' end +cxx.instance_variable_set(:'@have_devel', ok) + if ok $srcs = %w[cxxanyargs.cpp] failures = Dir.glob($srcdir + "/failure*.cpp").map {|n| File.basename(n)} diff --git a/ruby/ext/-test-/debug/depend b/ruby/ext/-test-/debug/depend index 662ed8751..20f7be675 100644 --- a/ruby/ext/-test-/debug/depend +++ b/ruby/ext/-test-/debug/depend @@ -4,8 +4,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -15,9 +162,156 @@ inspector.o: $(RUBY_EXTCONF_H) inspector.o: $(arch_hdrdir)/ruby/config.h inspector.o: $(hdrdir)/ruby/assert.h inspector.o: $(hdrdir)/ruby/backward.h +inspector.o: $(hdrdir)/ruby/backward/2/assume.h +inspector.o: $(hdrdir)/ruby/backward/2/attributes.h +inspector.o: $(hdrdir)/ruby/backward/2/bool.h +inspector.o: $(hdrdir)/ruby/backward/2/inttypes.h +inspector.o: $(hdrdir)/ruby/backward/2/limits.h +inspector.o: $(hdrdir)/ruby/backward/2/long_long.h +inspector.o: $(hdrdir)/ruby/backward/2/stdalign.h +inspector.o: $(hdrdir)/ruby/backward/2/stdarg.h inspector.o: $(hdrdir)/ruby/debug.h inspector.o: $(hdrdir)/ruby/defines.h inspector.o: $(hdrdir)/ruby/intern.h +inspector.o: $(hdrdir)/ruby/internal/anyargs.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/char.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/double.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/int.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/long.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/short.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +inspector.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +inspector.o: $(hdrdir)/ruby/internal/assume.h +inspector.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +inspector.o: $(hdrdir)/ruby/internal/attr/artificial.h +inspector.o: $(hdrdir)/ruby/internal/attr/cold.h +inspector.o: $(hdrdir)/ruby/internal/attr/const.h +inspector.o: $(hdrdir)/ruby/internal/attr/constexpr.h +inspector.o: $(hdrdir)/ruby/internal/attr/deprecated.h +inspector.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +inspector.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +inspector.o: $(hdrdir)/ruby/internal/attr/error.h +inspector.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +inspector.o: $(hdrdir)/ruby/internal/attr/forceinline.h +inspector.o: $(hdrdir)/ruby/internal/attr/format.h +inspector.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +inspector.o: $(hdrdir)/ruby/internal/attr/noalias.h +inspector.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +inspector.o: $(hdrdir)/ruby/internal/attr/noexcept.h +inspector.o: $(hdrdir)/ruby/internal/attr/noinline.h +inspector.o: $(hdrdir)/ruby/internal/attr/nonnull.h +inspector.o: $(hdrdir)/ruby/internal/attr/noreturn.h +inspector.o: $(hdrdir)/ruby/internal/attr/pure.h +inspector.o: $(hdrdir)/ruby/internal/attr/restrict.h +inspector.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +inspector.o: $(hdrdir)/ruby/internal/attr/warning.h +inspector.o: $(hdrdir)/ruby/internal/attr/weakref.h +inspector.o: $(hdrdir)/ruby/internal/cast.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +inspector.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +inspector.o: $(hdrdir)/ruby/internal/compiler_since.h +inspector.o: $(hdrdir)/ruby/internal/config.h +inspector.o: $(hdrdir)/ruby/internal/constant_p.h +inspector.o: $(hdrdir)/ruby/internal/core.h +inspector.o: $(hdrdir)/ruby/internal/core/rarray.h +inspector.o: $(hdrdir)/ruby/internal/core/rbasic.h +inspector.o: $(hdrdir)/ruby/internal/core/rbignum.h +inspector.o: $(hdrdir)/ruby/internal/core/rclass.h +inspector.o: $(hdrdir)/ruby/internal/core/rdata.h +inspector.o: $(hdrdir)/ruby/internal/core/rfile.h +inspector.o: $(hdrdir)/ruby/internal/core/rhash.h +inspector.o: $(hdrdir)/ruby/internal/core/robject.h +inspector.o: $(hdrdir)/ruby/internal/core/rregexp.h +inspector.o: $(hdrdir)/ruby/internal/core/rstring.h +inspector.o: $(hdrdir)/ruby/internal/core/rstruct.h +inspector.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +inspector.o: $(hdrdir)/ruby/internal/ctype.h +inspector.o: $(hdrdir)/ruby/internal/dllexport.h +inspector.o: $(hdrdir)/ruby/internal/dosish.h +inspector.o: $(hdrdir)/ruby/internal/error.h +inspector.o: $(hdrdir)/ruby/internal/eval.h +inspector.o: $(hdrdir)/ruby/internal/event.h +inspector.o: $(hdrdir)/ruby/internal/fl_type.h +inspector.o: $(hdrdir)/ruby/internal/gc.h +inspector.o: $(hdrdir)/ruby/internal/glob.h +inspector.o: $(hdrdir)/ruby/internal/globals.h +inspector.o: $(hdrdir)/ruby/internal/has/attribute.h +inspector.o: $(hdrdir)/ruby/internal/has/builtin.h +inspector.o: $(hdrdir)/ruby/internal/has/c_attribute.h +inspector.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +inspector.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +inspector.o: $(hdrdir)/ruby/internal/has/extension.h +inspector.o: $(hdrdir)/ruby/internal/has/feature.h +inspector.o: $(hdrdir)/ruby/internal/has/warning.h +inspector.o: $(hdrdir)/ruby/internal/intern/array.h +inspector.o: $(hdrdir)/ruby/internal/intern/bignum.h +inspector.o: $(hdrdir)/ruby/internal/intern/class.h +inspector.o: $(hdrdir)/ruby/internal/intern/compar.h +inspector.o: $(hdrdir)/ruby/internal/intern/complex.h +inspector.o: $(hdrdir)/ruby/internal/intern/cont.h +inspector.o: $(hdrdir)/ruby/internal/intern/dir.h +inspector.o: $(hdrdir)/ruby/internal/intern/enum.h +inspector.o: $(hdrdir)/ruby/internal/intern/enumerator.h +inspector.o: $(hdrdir)/ruby/internal/intern/error.h +inspector.o: $(hdrdir)/ruby/internal/intern/eval.h +inspector.o: $(hdrdir)/ruby/internal/intern/file.h +inspector.o: $(hdrdir)/ruby/internal/intern/gc.h +inspector.o: $(hdrdir)/ruby/internal/intern/hash.h +inspector.o: $(hdrdir)/ruby/internal/intern/io.h +inspector.o: $(hdrdir)/ruby/internal/intern/load.h +inspector.o: $(hdrdir)/ruby/internal/intern/marshal.h +inspector.o: $(hdrdir)/ruby/internal/intern/numeric.h +inspector.o: $(hdrdir)/ruby/internal/intern/object.h +inspector.o: $(hdrdir)/ruby/internal/intern/parse.h +inspector.o: $(hdrdir)/ruby/internal/intern/proc.h +inspector.o: $(hdrdir)/ruby/internal/intern/process.h +inspector.o: $(hdrdir)/ruby/internal/intern/random.h +inspector.o: $(hdrdir)/ruby/internal/intern/range.h +inspector.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +inspector.o: $(hdrdir)/ruby/internal/intern/sprintf.h +inspector.o: $(hdrdir)/ruby/internal/intern/string.h +inspector.o: $(hdrdir)/ruby/internal/intern/struct.h +inspector.o: $(hdrdir)/ruby/internal/intern/thread.h +inspector.o: $(hdrdir)/ruby/internal/intern/time.h +inspector.o: $(hdrdir)/ruby/internal/intern/variable.h +inspector.o: $(hdrdir)/ruby/internal/intern/vm.h +inspector.o: $(hdrdir)/ruby/internal/interpreter.h +inspector.o: $(hdrdir)/ruby/internal/iterator.h +inspector.o: $(hdrdir)/ruby/internal/memory.h +inspector.o: $(hdrdir)/ruby/internal/method.h +inspector.o: $(hdrdir)/ruby/internal/module.h +inspector.o: $(hdrdir)/ruby/internal/newobj.h +inspector.o: $(hdrdir)/ruby/internal/rgengc.h +inspector.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +inspector.o: $(hdrdir)/ruby/internal/value.h +inspector.o: $(hdrdir)/ruby/internal/value_type.h +inspector.o: $(hdrdir)/ruby/internal/variable.h +inspector.o: $(hdrdir)/ruby/internal/warning_push.h +inspector.o: $(hdrdir)/ruby/internal/xmalloc.h inspector.o: $(hdrdir)/ruby/missing.h inspector.o: $(hdrdir)/ruby/ruby.h inspector.o: $(hdrdir)/ruby/st.h @@ -27,9 +321,156 @@ profile_frames.o: $(RUBY_EXTCONF_H) profile_frames.o: $(arch_hdrdir)/ruby/config.h profile_frames.o: $(hdrdir)/ruby/assert.h profile_frames.o: $(hdrdir)/ruby/backward.h +profile_frames.o: $(hdrdir)/ruby/backward/2/assume.h +profile_frames.o: $(hdrdir)/ruby/backward/2/attributes.h +profile_frames.o: $(hdrdir)/ruby/backward/2/bool.h +profile_frames.o: $(hdrdir)/ruby/backward/2/inttypes.h +profile_frames.o: $(hdrdir)/ruby/backward/2/limits.h +profile_frames.o: $(hdrdir)/ruby/backward/2/long_long.h +profile_frames.o: $(hdrdir)/ruby/backward/2/stdalign.h +profile_frames.o: $(hdrdir)/ruby/backward/2/stdarg.h profile_frames.o: $(hdrdir)/ruby/debug.h profile_frames.o: $(hdrdir)/ruby/defines.h profile_frames.o: $(hdrdir)/ruby/intern.h +profile_frames.o: $(hdrdir)/ruby/internal/anyargs.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/char.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/double.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/int.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/short.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +profile_frames.o: $(hdrdir)/ruby/internal/assume.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/artificial.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/cold.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/const.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/constexpr.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/deprecated.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/error.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/forceinline.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/format.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/noalias.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/noexcept.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/noinline.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/nonnull.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/noreturn.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/pure.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/restrict.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/warning.h +profile_frames.o: $(hdrdir)/ruby/internal/attr/weakref.h +profile_frames.o: $(hdrdir)/ruby/internal/cast.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +profile_frames.o: $(hdrdir)/ruby/internal/compiler_since.h +profile_frames.o: $(hdrdir)/ruby/internal/config.h +profile_frames.o: $(hdrdir)/ruby/internal/constant_p.h +profile_frames.o: $(hdrdir)/ruby/internal/core.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rarray.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rbasic.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rbignum.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rclass.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rdata.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rfile.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rhash.h +profile_frames.o: $(hdrdir)/ruby/internal/core/robject.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rregexp.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rstring.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rstruct.h +profile_frames.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +profile_frames.o: $(hdrdir)/ruby/internal/ctype.h +profile_frames.o: $(hdrdir)/ruby/internal/dllexport.h +profile_frames.o: $(hdrdir)/ruby/internal/dosish.h +profile_frames.o: $(hdrdir)/ruby/internal/error.h +profile_frames.o: $(hdrdir)/ruby/internal/eval.h +profile_frames.o: $(hdrdir)/ruby/internal/event.h +profile_frames.o: $(hdrdir)/ruby/internal/fl_type.h +profile_frames.o: $(hdrdir)/ruby/internal/gc.h +profile_frames.o: $(hdrdir)/ruby/internal/glob.h +profile_frames.o: $(hdrdir)/ruby/internal/globals.h +profile_frames.o: $(hdrdir)/ruby/internal/has/attribute.h +profile_frames.o: $(hdrdir)/ruby/internal/has/builtin.h +profile_frames.o: $(hdrdir)/ruby/internal/has/c_attribute.h +profile_frames.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +profile_frames.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +profile_frames.o: $(hdrdir)/ruby/internal/has/extension.h +profile_frames.o: $(hdrdir)/ruby/internal/has/feature.h +profile_frames.o: $(hdrdir)/ruby/internal/has/warning.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/array.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/bignum.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/class.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/compar.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/complex.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/cont.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/dir.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/enum.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/enumerator.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/error.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/eval.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/file.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/gc.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/hash.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/io.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/load.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/marshal.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/numeric.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/object.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/parse.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/proc.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/process.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/random.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/range.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/sprintf.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/string.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/struct.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/thread.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/time.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/variable.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/vm.h +profile_frames.o: $(hdrdir)/ruby/internal/interpreter.h +profile_frames.o: $(hdrdir)/ruby/internal/iterator.h +profile_frames.o: $(hdrdir)/ruby/internal/memory.h +profile_frames.o: $(hdrdir)/ruby/internal/method.h +profile_frames.o: $(hdrdir)/ruby/internal/module.h +profile_frames.o: $(hdrdir)/ruby/internal/newobj.h +profile_frames.o: $(hdrdir)/ruby/internal/rgengc.h +profile_frames.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +profile_frames.o: $(hdrdir)/ruby/internal/value.h +profile_frames.o: $(hdrdir)/ruby/internal/value_type.h +profile_frames.o: $(hdrdir)/ruby/internal/variable.h +profile_frames.o: $(hdrdir)/ruby/internal/warning_push.h +profile_frames.o: $(hdrdir)/ruby/internal/xmalloc.h profile_frames.o: $(hdrdir)/ruby/missing.h profile_frames.o: $(hdrdir)/ruby/ruby.h profile_frames.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/enumerator_kw/depend b/ruby/ext/-test-/enumerator_kw/depend index b7489eaf7..4347538d3 100644 --- a/ruby/ext/-test-/enumerator_kw/depend +++ b/ruby/ext/-test-/enumerator_kw/depend @@ -4,8 +4,155 @@ enumerator_kw.o: $(arch_hdrdir)/ruby/config.h enumerator_kw.o: $(hdrdir)/ruby.h enumerator_kw.o: $(hdrdir)/ruby/assert.h enumerator_kw.o: $(hdrdir)/ruby/backward.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/assume.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/attributes.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/bool.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/limits.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/long_long.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h +enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h enumerator_kw.o: $(hdrdir)/ruby/defines.h enumerator_kw.o: $(hdrdir)/ruby/intern.h +enumerator_kw.o: $(hdrdir)/ruby/internal/anyargs.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +enumerator_kw.o: $(hdrdir)/ruby/internal/assume.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/cold.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/const.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/error.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/format.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/pure.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/warning.h +enumerator_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h +enumerator_kw.o: $(hdrdir)/ruby/internal/cast.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_since.h +enumerator_kw.o: $(hdrdir)/ruby/internal/config.h +enumerator_kw.o: $(hdrdir)/ruby/internal/constant_p.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rarray.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rclass.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rdata.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rfile.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rhash.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/robject.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstring.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h +enumerator_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +enumerator_kw.o: $(hdrdir)/ruby/internal/ctype.h +enumerator_kw.o: $(hdrdir)/ruby/internal/dllexport.h +enumerator_kw.o: $(hdrdir)/ruby/internal/dosish.h +enumerator_kw.o: $(hdrdir)/ruby/internal/error.h +enumerator_kw.o: $(hdrdir)/ruby/internal/eval.h +enumerator_kw.o: $(hdrdir)/ruby/internal/event.h +enumerator_kw.o: $(hdrdir)/ruby/internal/fl_type.h +enumerator_kw.o: $(hdrdir)/ruby/internal/gc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/glob.h +enumerator_kw.o: $(hdrdir)/ruby/internal/globals.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/attribute.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/builtin.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/extension.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/feature.h +enumerator_kw.o: $(hdrdir)/ruby/internal/has/warning.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/array.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/class.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/compar.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/complex.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/cont.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/dir.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enum.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/error.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/eval.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/file.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/gc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/hash.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/io.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/load.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/object.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/parse.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/proc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/process.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/random.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/range.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/string.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/struct.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/thread.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/time.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/variable.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/vm.h +enumerator_kw.o: $(hdrdir)/ruby/internal/interpreter.h +enumerator_kw.o: $(hdrdir)/ruby/internal/iterator.h +enumerator_kw.o: $(hdrdir)/ruby/internal/memory.h +enumerator_kw.o: $(hdrdir)/ruby/internal/method.h +enumerator_kw.o: $(hdrdir)/ruby/internal/module.h +enumerator_kw.o: $(hdrdir)/ruby/internal/newobj.h +enumerator_kw.o: $(hdrdir)/ruby/internal/rgengc.h +enumerator_kw.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +enumerator_kw.o: $(hdrdir)/ruby/internal/value.h +enumerator_kw.o: $(hdrdir)/ruby/internal/value_type.h +enumerator_kw.o: $(hdrdir)/ruby/internal/variable.h +enumerator_kw.o: $(hdrdir)/ruby/internal/warning_push.h +enumerator_kw.o: $(hdrdir)/ruby/internal/xmalloc.h enumerator_kw.o: $(hdrdir)/ruby/missing.h enumerator_kw.o: $(hdrdir)/ruby/ruby.h enumerator_kw.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/exception/depend b/ruby/ext/-test-/exception/depend index d0958de9b..05f6ff655 100644 --- a/ruby/ext/-test-/exception/depend +++ b/ruby/ext/-test-/exception/depend @@ -3,8 +3,155 @@ dataerror.o: $(RUBY_EXTCONF_H) dataerror.o: $(arch_hdrdir)/ruby/config.h dataerror.o: $(hdrdir)/ruby/assert.h dataerror.o: $(hdrdir)/ruby/backward.h +dataerror.o: $(hdrdir)/ruby/backward/2/assume.h +dataerror.o: $(hdrdir)/ruby/backward/2/attributes.h +dataerror.o: $(hdrdir)/ruby/backward/2/bool.h +dataerror.o: $(hdrdir)/ruby/backward/2/inttypes.h +dataerror.o: $(hdrdir)/ruby/backward/2/limits.h +dataerror.o: $(hdrdir)/ruby/backward/2/long_long.h +dataerror.o: $(hdrdir)/ruby/backward/2/stdalign.h +dataerror.o: $(hdrdir)/ruby/backward/2/stdarg.h dataerror.o: $(hdrdir)/ruby/defines.h dataerror.o: $(hdrdir)/ruby/intern.h +dataerror.o: $(hdrdir)/ruby/internal/anyargs.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/char.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/double.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/int.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/short.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +dataerror.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +dataerror.o: $(hdrdir)/ruby/internal/assume.h +dataerror.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +dataerror.o: $(hdrdir)/ruby/internal/attr/artificial.h +dataerror.o: $(hdrdir)/ruby/internal/attr/cold.h +dataerror.o: $(hdrdir)/ruby/internal/attr/const.h +dataerror.o: $(hdrdir)/ruby/internal/attr/constexpr.h +dataerror.o: $(hdrdir)/ruby/internal/attr/deprecated.h +dataerror.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +dataerror.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +dataerror.o: $(hdrdir)/ruby/internal/attr/error.h +dataerror.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +dataerror.o: $(hdrdir)/ruby/internal/attr/forceinline.h +dataerror.o: $(hdrdir)/ruby/internal/attr/format.h +dataerror.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +dataerror.o: $(hdrdir)/ruby/internal/attr/noalias.h +dataerror.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +dataerror.o: $(hdrdir)/ruby/internal/attr/noexcept.h +dataerror.o: $(hdrdir)/ruby/internal/attr/noinline.h +dataerror.o: $(hdrdir)/ruby/internal/attr/nonnull.h +dataerror.o: $(hdrdir)/ruby/internal/attr/noreturn.h +dataerror.o: $(hdrdir)/ruby/internal/attr/pure.h +dataerror.o: $(hdrdir)/ruby/internal/attr/restrict.h +dataerror.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +dataerror.o: $(hdrdir)/ruby/internal/attr/warning.h +dataerror.o: $(hdrdir)/ruby/internal/attr/weakref.h +dataerror.o: $(hdrdir)/ruby/internal/cast.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +dataerror.o: $(hdrdir)/ruby/internal/compiler_since.h +dataerror.o: $(hdrdir)/ruby/internal/config.h +dataerror.o: $(hdrdir)/ruby/internal/constant_p.h +dataerror.o: $(hdrdir)/ruby/internal/core.h +dataerror.o: $(hdrdir)/ruby/internal/core/rarray.h +dataerror.o: $(hdrdir)/ruby/internal/core/rbasic.h +dataerror.o: $(hdrdir)/ruby/internal/core/rbignum.h +dataerror.o: $(hdrdir)/ruby/internal/core/rclass.h +dataerror.o: $(hdrdir)/ruby/internal/core/rdata.h +dataerror.o: $(hdrdir)/ruby/internal/core/rfile.h +dataerror.o: $(hdrdir)/ruby/internal/core/rhash.h +dataerror.o: $(hdrdir)/ruby/internal/core/robject.h +dataerror.o: $(hdrdir)/ruby/internal/core/rregexp.h +dataerror.o: $(hdrdir)/ruby/internal/core/rstring.h +dataerror.o: $(hdrdir)/ruby/internal/core/rstruct.h +dataerror.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +dataerror.o: $(hdrdir)/ruby/internal/ctype.h +dataerror.o: $(hdrdir)/ruby/internal/dllexport.h +dataerror.o: $(hdrdir)/ruby/internal/dosish.h +dataerror.o: $(hdrdir)/ruby/internal/error.h +dataerror.o: $(hdrdir)/ruby/internal/eval.h +dataerror.o: $(hdrdir)/ruby/internal/event.h +dataerror.o: $(hdrdir)/ruby/internal/fl_type.h +dataerror.o: $(hdrdir)/ruby/internal/gc.h +dataerror.o: $(hdrdir)/ruby/internal/glob.h +dataerror.o: $(hdrdir)/ruby/internal/globals.h +dataerror.o: $(hdrdir)/ruby/internal/has/attribute.h +dataerror.o: $(hdrdir)/ruby/internal/has/builtin.h +dataerror.o: $(hdrdir)/ruby/internal/has/c_attribute.h +dataerror.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +dataerror.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +dataerror.o: $(hdrdir)/ruby/internal/has/extension.h +dataerror.o: $(hdrdir)/ruby/internal/has/feature.h +dataerror.o: $(hdrdir)/ruby/internal/has/warning.h +dataerror.o: $(hdrdir)/ruby/internal/intern/array.h +dataerror.o: $(hdrdir)/ruby/internal/intern/bignum.h +dataerror.o: $(hdrdir)/ruby/internal/intern/class.h +dataerror.o: $(hdrdir)/ruby/internal/intern/compar.h +dataerror.o: $(hdrdir)/ruby/internal/intern/complex.h +dataerror.o: $(hdrdir)/ruby/internal/intern/cont.h +dataerror.o: $(hdrdir)/ruby/internal/intern/dir.h +dataerror.o: $(hdrdir)/ruby/internal/intern/enum.h +dataerror.o: $(hdrdir)/ruby/internal/intern/enumerator.h +dataerror.o: $(hdrdir)/ruby/internal/intern/error.h +dataerror.o: $(hdrdir)/ruby/internal/intern/eval.h +dataerror.o: $(hdrdir)/ruby/internal/intern/file.h +dataerror.o: $(hdrdir)/ruby/internal/intern/gc.h +dataerror.o: $(hdrdir)/ruby/internal/intern/hash.h +dataerror.o: $(hdrdir)/ruby/internal/intern/io.h +dataerror.o: $(hdrdir)/ruby/internal/intern/load.h +dataerror.o: $(hdrdir)/ruby/internal/intern/marshal.h +dataerror.o: $(hdrdir)/ruby/internal/intern/numeric.h +dataerror.o: $(hdrdir)/ruby/internal/intern/object.h +dataerror.o: $(hdrdir)/ruby/internal/intern/parse.h +dataerror.o: $(hdrdir)/ruby/internal/intern/proc.h +dataerror.o: $(hdrdir)/ruby/internal/intern/process.h +dataerror.o: $(hdrdir)/ruby/internal/intern/random.h +dataerror.o: $(hdrdir)/ruby/internal/intern/range.h +dataerror.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +dataerror.o: $(hdrdir)/ruby/internal/intern/sprintf.h +dataerror.o: $(hdrdir)/ruby/internal/intern/string.h +dataerror.o: $(hdrdir)/ruby/internal/intern/struct.h +dataerror.o: $(hdrdir)/ruby/internal/intern/thread.h +dataerror.o: $(hdrdir)/ruby/internal/intern/time.h +dataerror.o: $(hdrdir)/ruby/internal/intern/variable.h +dataerror.o: $(hdrdir)/ruby/internal/intern/vm.h +dataerror.o: $(hdrdir)/ruby/internal/interpreter.h +dataerror.o: $(hdrdir)/ruby/internal/iterator.h +dataerror.o: $(hdrdir)/ruby/internal/memory.h +dataerror.o: $(hdrdir)/ruby/internal/method.h +dataerror.o: $(hdrdir)/ruby/internal/module.h +dataerror.o: $(hdrdir)/ruby/internal/newobj.h +dataerror.o: $(hdrdir)/ruby/internal/rgengc.h +dataerror.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +dataerror.o: $(hdrdir)/ruby/internal/value.h +dataerror.o: $(hdrdir)/ruby/internal/value_type.h +dataerror.o: $(hdrdir)/ruby/internal/variable.h +dataerror.o: $(hdrdir)/ruby/internal/warning_push.h +dataerror.o: $(hdrdir)/ruby/internal/xmalloc.h dataerror.o: $(hdrdir)/ruby/missing.h dataerror.o: $(hdrdir)/ruby/ruby.h dataerror.o: $(hdrdir)/ruby/st.h @@ -15,9 +162,165 @@ enc_raise.o: $(arch_hdrdir)/ruby/config.h enc_raise.o: $(hdrdir)/ruby.h enc_raise.o: $(hdrdir)/ruby/assert.h enc_raise.o: $(hdrdir)/ruby/backward.h +enc_raise.o: $(hdrdir)/ruby/backward/2/assume.h +enc_raise.o: $(hdrdir)/ruby/backward/2/attributes.h +enc_raise.o: $(hdrdir)/ruby/backward/2/bool.h +enc_raise.o: $(hdrdir)/ruby/backward/2/inttypes.h +enc_raise.o: $(hdrdir)/ruby/backward/2/limits.h +enc_raise.o: $(hdrdir)/ruby/backward/2/long_long.h +enc_raise.o: $(hdrdir)/ruby/backward/2/stdalign.h +enc_raise.o: $(hdrdir)/ruby/backward/2/stdarg.h enc_raise.o: $(hdrdir)/ruby/defines.h enc_raise.o: $(hdrdir)/ruby/encoding.h enc_raise.o: $(hdrdir)/ruby/intern.h +enc_raise.o: $(hdrdir)/ruby/internal/anyargs.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/char.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/double.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/int.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/short.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +enc_raise.o: $(hdrdir)/ruby/internal/assume.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/artificial.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/cold.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/const.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/constexpr.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/deprecated.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/error.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/forceinline.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/format.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/noalias.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/noexcept.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/noinline.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/nonnull.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/noreturn.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/pure.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/restrict.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/warning.h +enc_raise.o: $(hdrdir)/ruby/internal/attr/weakref.h +enc_raise.o: $(hdrdir)/ruby/internal/cast.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +enc_raise.o: $(hdrdir)/ruby/internal/compiler_since.h +enc_raise.o: $(hdrdir)/ruby/internal/config.h +enc_raise.o: $(hdrdir)/ruby/internal/constant_p.h +enc_raise.o: $(hdrdir)/ruby/internal/core.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rarray.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rbasic.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rbignum.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rclass.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rdata.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rfile.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rhash.h +enc_raise.o: $(hdrdir)/ruby/internal/core/robject.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rregexp.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rstring.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rstruct.h +enc_raise.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +enc_raise.o: $(hdrdir)/ruby/internal/ctype.h +enc_raise.o: $(hdrdir)/ruby/internal/dllexport.h +enc_raise.o: $(hdrdir)/ruby/internal/dosish.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/coderange.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/ctype.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/encoding.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/pathname.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/re.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/string.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/symbol.h +enc_raise.o: $(hdrdir)/ruby/internal/encoding/transcode.h +enc_raise.o: $(hdrdir)/ruby/internal/error.h +enc_raise.o: $(hdrdir)/ruby/internal/eval.h +enc_raise.o: $(hdrdir)/ruby/internal/event.h +enc_raise.o: $(hdrdir)/ruby/internal/fl_type.h +enc_raise.o: $(hdrdir)/ruby/internal/gc.h +enc_raise.o: $(hdrdir)/ruby/internal/glob.h +enc_raise.o: $(hdrdir)/ruby/internal/globals.h +enc_raise.o: $(hdrdir)/ruby/internal/has/attribute.h +enc_raise.o: $(hdrdir)/ruby/internal/has/builtin.h +enc_raise.o: $(hdrdir)/ruby/internal/has/c_attribute.h +enc_raise.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +enc_raise.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +enc_raise.o: $(hdrdir)/ruby/internal/has/extension.h +enc_raise.o: $(hdrdir)/ruby/internal/has/feature.h +enc_raise.o: $(hdrdir)/ruby/internal/has/warning.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/array.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/bignum.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/class.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/compar.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/complex.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/cont.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/dir.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/enum.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/enumerator.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/error.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/eval.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/file.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/gc.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/hash.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/io.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/load.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/marshal.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/numeric.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/object.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/parse.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/proc.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/process.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/random.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/range.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/sprintf.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/string.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/struct.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/thread.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/time.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/variable.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/vm.h +enc_raise.o: $(hdrdir)/ruby/internal/interpreter.h +enc_raise.o: $(hdrdir)/ruby/internal/iterator.h +enc_raise.o: $(hdrdir)/ruby/internal/memory.h +enc_raise.o: $(hdrdir)/ruby/internal/method.h +enc_raise.o: $(hdrdir)/ruby/internal/module.h +enc_raise.o: $(hdrdir)/ruby/internal/newobj.h +enc_raise.o: $(hdrdir)/ruby/internal/rgengc.h +enc_raise.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +enc_raise.o: $(hdrdir)/ruby/internal/value.h +enc_raise.o: $(hdrdir)/ruby/internal/value_type.h +enc_raise.o: $(hdrdir)/ruby/internal/variable.h +enc_raise.o: $(hdrdir)/ruby/internal/warning_push.h +enc_raise.o: $(hdrdir)/ruby/internal/xmalloc.h enc_raise.o: $(hdrdir)/ruby/missing.h enc_raise.o: $(hdrdir)/ruby/onigmo.h enc_raise.o: $(hdrdir)/ruby/oniguruma.h @@ -30,8 +333,155 @@ ensured.o: $(arch_hdrdir)/ruby/config.h ensured.o: $(hdrdir)/ruby.h ensured.o: $(hdrdir)/ruby/assert.h ensured.o: $(hdrdir)/ruby/backward.h +ensured.o: $(hdrdir)/ruby/backward/2/assume.h +ensured.o: $(hdrdir)/ruby/backward/2/attributes.h +ensured.o: $(hdrdir)/ruby/backward/2/bool.h +ensured.o: $(hdrdir)/ruby/backward/2/inttypes.h +ensured.o: $(hdrdir)/ruby/backward/2/limits.h +ensured.o: $(hdrdir)/ruby/backward/2/long_long.h +ensured.o: $(hdrdir)/ruby/backward/2/stdalign.h +ensured.o: $(hdrdir)/ruby/backward/2/stdarg.h ensured.o: $(hdrdir)/ruby/defines.h ensured.o: $(hdrdir)/ruby/intern.h +ensured.o: $(hdrdir)/ruby/internal/anyargs.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ensured.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ensured.o: $(hdrdir)/ruby/internal/assume.h +ensured.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ensured.o: $(hdrdir)/ruby/internal/attr/artificial.h +ensured.o: $(hdrdir)/ruby/internal/attr/cold.h +ensured.o: $(hdrdir)/ruby/internal/attr/const.h +ensured.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ensured.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ensured.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ensured.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ensured.o: $(hdrdir)/ruby/internal/attr/error.h +ensured.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ensured.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ensured.o: $(hdrdir)/ruby/internal/attr/format.h +ensured.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ensured.o: $(hdrdir)/ruby/internal/attr/noalias.h +ensured.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ensured.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ensured.o: $(hdrdir)/ruby/internal/attr/noinline.h +ensured.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ensured.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ensured.o: $(hdrdir)/ruby/internal/attr/pure.h +ensured.o: $(hdrdir)/ruby/internal/attr/restrict.h +ensured.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ensured.o: $(hdrdir)/ruby/internal/attr/warning.h +ensured.o: $(hdrdir)/ruby/internal/attr/weakref.h +ensured.o: $(hdrdir)/ruby/internal/cast.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ensured.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ensured.o: $(hdrdir)/ruby/internal/compiler_since.h +ensured.o: $(hdrdir)/ruby/internal/config.h +ensured.o: $(hdrdir)/ruby/internal/constant_p.h +ensured.o: $(hdrdir)/ruby/internal/core.h +ensured.o: $(hdrdir)/ruby/internal/core/rarray.h +ensured.o: $(hdrdir)/ruby/internal/core/rbasic.h +ensured.o: $(hdrdir)/ruby/internal/core/rbignum.h +ensured.o: $(hdrdir)/ruby/internal/core/rclass.h +ensured.o: $(hdrdir)/ruby/internal/core/rdata.h +ensured.o: $(hdrdir)/ruby/internal/core/rfile.h +ensured.o: $(hdrdir)/ruby/internal/core/rhash.h +ensured.o: $(hdrdir)/ruby/internal/core/robject.h +ensured.o: $(hdrdir)/ruby/internal/core/rregexp.h +ensured.o: $(hdrdir)/ruby/internal/core/rstring.h +ensured.o: $(hdrdir)/ruby/internal/core/rstruct.h +ensured.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ensured.o: $(hdrdir)/ruby/internal/ctype.h +ensured.o: $(hdrdir)/ruby/internal/dllexport.h +ensured.o: $(hdrdir)/ruby/internal/dosish.h +ensured.o: $(hdrdir)/ruby/internal/error.h +ensured.o: $(hdrdir)/ruby/internal/eval.h +ensured.o: $(hdrdir)/ruby/internal/event.h +ensured.o: $(hdrdir)/ruby/internal/fl_type.h +ensured.o: $(hdrdir)/ruby/internal/gc.h +ensured.o: $(hdrdir)/ruby/internal/glob.h +ensured.o: $(hdrdir)/ruby/internal/globals.h +ensured.o: $(hdrdir)/ruby/internal/has/attribute.h +ensured.o: $(hdrdir)/ruby/internal/has/builtin.h +ensured.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ensured.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ensured.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ensured.o: $(hdrdir)/ruby/internal/has/extension.h +ensured.o: $(hdrdir)/ruby/internal/has/feature.h +ensured.o: $(hdrdir)/ruby/internal/has/warning.h +ensured.o: $(hdrdir)/ruby/internal/intern/array.h +ensured.o: $(hdrdir)/ruby/internal/intern/bignum.h +ensured.o: $(hdrdir)/ruby/internal/intern/class.h +ensured.o: $(hdrdir)/ruby/internal/intern/compar.h +ensured.o: $(hdrdir)/ruby/internal/intern/complex.h +ensured.o: $(hdrdir)/ruby/internal/intern/cont.h +ensured.o: $(hdrdir)/ruby/internal/intern/dir.h +ensured.o: $(hdrdir)/ruby/internal/intern/enum.h +ensured.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ensured.o: $(hdrdir)/ruby/internal/intern/error.h +ensured.o: $(hdrdir)/ruby/internal/intern/eval.h +ensured.o: $(hdrdir)/ruby/internal/intern/file.h +ensured.o: $(hdrdir)/ruby/internal/intern/gc.h +ensured.o: $(hdrdir)/ruby/internal/intern/hash.h +ensured.o: $(hdrdir)/ruby/internal/intern/io.h +ensured.o: $(hdrdir)/ruby/internal/intern/load.h +ensured.o: $(hdrdir)/ruby/internal/intern/marshal.h +ensured.o: $(hdrdir)/ruby/internal/intern/numeric.h +ensured.o: $(hdrdir)/ruby/internal/intern/object.h +ensured.o: $(hdrdir)/ruby/internal/intern/parse.h +ensured.o: $(hdrdir)/ruby/internal/intern/proc.h +ensured.o: $(hdrdir)/ruby/internal/intern/process.h +ensured.o: $(hdrdir)/ruby/internal/intern/random.h +ensured.o: $(hdrdir)/ruby/internal/intern/range.h +ensured.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ensured.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ensured.o: $(hdrdir)/ruby/internal/intern/string.h +ensured.o: $(hdrdir)/ruby/internal/intern/struct.h +ensured.o: $(hdrdir)/ruby/internal/intern/thread.h +ensured.o: $(hdrdir)/ruby/internal/intern/time.h +ensured.o: $(hdrdir)/ruby/internal/intern/variable.h +ensured.o: $(hdrdir)/ruby/internal/intern/vm.h +ensured.o: $(hdrdir)/ruby/internal/interpreter.h +ensured.o: $(hdrdir)/ruby/internal/iterator.h +ensured.o: $(hdrdir)/ruby/internal/memory.h +ensured.o: $(hdrdir)/ruby/internal/method.h +ensured.o: $(hdrdir)/ruby/internal/module.h +ensured.o: $(hdrdir)/ruby/internal/newobj.h +ensured.o: $(hdrdir)/ruby/internal/rgengc.h +ensured.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ensured.o: $(hdrdir)/ruby/internal/value.h +ensured.o: $(hdrdir)/ruby/internal/value_type.h +ensured.o: $(hdrdir)/ruby/internal/variable.h +ensured.o: $(hdrdir)/ruby/internal/warning_push.h +ensured.o: $(hdrdir)/ruby/internal/xmalloc.h ensured.o: $(hdrdir)/ruby/missing.h ensured.o: $(hdrdir)/ruby/ruby.h ensured.o: $(hdrdir)/ruby/st.h @@ -42,8 +492,155 @@ 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/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/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/gc.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/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/rgengc.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/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 diff --git a/ruby/ext/-test-/fatal/depend b/ruby/ext/-test-/fatal/depend index c74360fdf..ccb274e8f 100644 --- a/ruby/ext/-test-/fatal/depend +++ b/ruby/ext/-test-/fatal/depend @@ -4,8 +4,155 @@ rb_fatal.o: $(arch_hdrdir)/ruby/config.h rb_fatal.o: $(hdrdir)/ruby.h rb_fatal.o: $(hdrdir)/ruby/assert.h rb_fatal.o: $(hdrdir)/ruby/backward.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/assume.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/attributes.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/bool.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/inttypes.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/limits.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/long_long.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/stdalign.h +rb_fatal.o: $(hdrdir)/ruby/backward/2/stdarg.h rb_fatal.o: $(hdrdir)/ruby/defines.h rb_fatal.o: $(hdrdir)/ruby/intern.h +rb_fatal.o: $(hdrdir)/ruby/internal/anyargs.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rb_fatal.o: $(hdrdir)/ruby/internal/assume.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/artificial.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/cold.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/const.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/error.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/format.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/noalias.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/noinline.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/pure.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/restrict.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/warning.h +rb_fatal.o: $(hdrdir)/ruby/internal/attr/weakref.h +rb_fatal.o: $(hdrdir)/ruby/internal/cast.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rb_fatal.o: $(hdrdir)/ruby/internal/compiler_since.h +rb_fatal.o: $(hdrdir)/ruby/internal/config.h +rb_fatal.o: $(hdrdir)/ruby/internal/constant_p.h +rb_fatal.o: $(hdrdir)/ruby/internal/core.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rarray.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rbasic.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rbignum.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rclass.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rdata.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rfile.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rhash.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/robject.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rregexp.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rstring.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rstruct.h +rb_fatal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rb_fatal.o: $(hdrdir)/ruby/internal/ctype.h +rb_fatal.o: $(hdrdir)/ruby/internal/dllexport.h +rb_fatal.o: $(hdrdir)/ruby/internal/dosish.h +rb_fatal.o: $(hdrdir)/ruby/internal/error.h +rb_fatal.o: $(hdrdir)/ruby/internal/eval.h +rb_fatal.o: $(hdrdir)/ruby/internal/event.h +rb_fatal.o: $(hdrdir)/ruby/internal/fl_type.h +rb_fatal.o: $(hdrdir)/ruby/internal/gc.h +rb_fatal.o: $(hdrdir)/ruby/internal/glob.h +rb_fatal.o: $(hdrdir)/ruby/internal/globals.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/attribute.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/builtin.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/extension.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/feature.h +rb_fatal.o: $(hdrdir)/ruby/internal/has/warning.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/array.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/bignum.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/class.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/compar.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/complex.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/cont.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/dir.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/enum.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/error.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/eval.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/file.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/gc.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/hash.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/io.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/load.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/marshal.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/numeric.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/object.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/parse.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/proc.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/process.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/random.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/range.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/string.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/struct.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/thread.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/time.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/variable.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/vm.h +rb_fatal.o: $(hdrdir)/ruby/internal/interpreter.h +rb_fatal.o: $(hdrdir)/ruby/internal/iterator.h +rb_fatal.o: $(hdrdir)/ruby/internal/memory.h +rb_fatal.o: $(hdrdir)/ruby/internal/method.h +rb_fatal.o: $(hdrdir)/ruby/internal/module.h +rb_fatal.o: $(hdrdir)/ruby/internal/newobj.h +rb_fatal.o: $(hdrdir)/ruby/internal/rgengc.h +rb_fatal.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rb_fatal.o: $(hdrdir)/ruby/internal/value.h +rb_fatal.o: $(hdrdir)/ruby/internal/value_type.h +rb_fatal.o: $(hdrdir)/ruby/internal/variable.h +rb_fatal.o: $(hdrdir)/ruby/internal/warning_push.h +rb_fatal.o: $(hdrdir)/ruby/internal/xmalloc.h rb_fatal.o: $(hdrdir)/ruby/missing.h rb_fatal.o: $(hdrdir)/ruby/ruby.h rb_fatal.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/fatal/rb_fatal.c b/ruby/ext/-test-/fatal/rb_fatal.c index 71aef4658..eedbc51f8 100644 --- a/ruby/ext/-test-/fatal/rb_fatal.c +++ b/ruby/ext/-test-/fatal/rb_fatal.c @@ -15,5 +15,6 @@ ruby_fatal(VALUE obj, VALUE msg) void Init_rb_fatal(void) { - rb_define_method(rb_mKernel, "rb_fatal", ruby_fatal, 1); + VALUE mBug = rb_define_module("Bug"); + rb_define_singleton_method(mBug, "rb_fatal", ruby_fatal, 1); } diff --git a/ruby/ext/-test-/file/depend b/ruby/ext/-test-/file/depend index afdf116a9..a6ac8bb55 100644 --- a/ruby/ext/-test-/file/depend +++ b/ruby/ext/-test-/file/depend @@ -3,9 +3,165 @@ fs.o: $(RUBY_EXTCONF_H) fs.o: $(arch_hdrdir)/ruby/config.h fs.o: $(hdrdir)/ruby/assert.h fs.o: $(hdrdir)/ruby/backward.h +fs.o: $(hdrdir)/ruby/backward/2/assume.h +fs.o: $(hdrdir)/ruby/backward/2/attributes.h +fs.o: $(hdrdir)/ruby/backward/2/bool.h +fs.o: $(hdrdir)/ruby/backward/2/inttypes.h +fs.o: $(hdrdir)/ruby/backward/2/limits.h +fs.o: $(hdrdir)/ruby/backward/2/long_long.h +fs.o: $(hdrdir)/ruby/backward/2/stdalign.h +fs.o: $(hdrdir)/ruby/backward/2/stdarg.h fs.o: $(hdrdir)/ruby/defines.h fs.o: $(hdrdir)/ruby/encoding.h fs.o: $(hdrdir)/ruby/intern.h +fs.o: $(hdrdir)/ruby/internal/anyargs.h +fs.o: $(hdrdir)/ruby/internal/arithmetic.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/char.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/double.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/int.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/long.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/short.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +fs.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +fs.o: $(hdrdir)/ruby/internal/assume.h +fs.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +fs.o: $(hdrdir)/ruby/internal/attr/artificial.h +fs.o: $(hdrdir)/ruby/internal/attr/cold.h +fs.o: $(hdrdir)/ruby/internal/attr/const.h +fs.o: $(hdrdir)/ruby/internal/attr/constexpr.h +fs.o: $(hdrdir)/ruby/internal/attr/deprecated.h +fs.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +fs.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +fs.o: $(hdrdir)/ruby/internal/attr/error.h +fs.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +fs.o: $(hdrdir)/ruby/internal/attr/forceinline.h +fs.o: $(hdrdir)/ruby/internal/attr/format.h +fs.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +fs.o: $(hdrdir)/ruby/internal/attr/noalias.h +fs.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +fs.o: $(hdrdir)/ruby/internal/attr/noexcept.h +fs.o: $(hdrdir)/ruby/internal/attr/noinline.h +fs.o: $(hdrdir)/ruby/internal/attr/nonnull.h +fs.o: $(hdrdir)/ruby/internal/attr/noreturn.h +fs.o: $(hdrdir)/ruby/internal/attr/pure.h +fs.o: $(hdrdir)/ruby/internal/attr/restrict.h +fs.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +fs.o: $(hdrdir)/ruby/internal/attr/warning.h +fs.o: $(hdrdir)/ruby/internal/attr/weakref.h +fs.o: $(hdrdir)/ruby/internal/cast.h +fs.o: $(hdrdir)/ruby/internal/compiler_is.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +fs.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +fs.o: $(hdrdir)/ruby/internal/compiler_since.h +fs.o: $(hdrdir)/ruby/internal/config.h +fs.o: $(hdrdir)/ruby/internal/constant_p.h +fs.o: $(hdrdir)/ruby/internal/core.h +fs.o: $(hdrdir)/ruby/internal/core/rarray.h +fs.o: $(hdrdir)/ruby/internal/core/rbasic.h +fs.o: $(hdrdir)/ruby/internal/core/rbignum.h +fs.o: $(hdrdir)/ruby/internal/core/rclass.h +fs.o: $(hdrdir)/ruby/internal/core/rdata.h +fs.o: $(hdrdir)/ruby/internal/core/rfile.h +fs.o: $(hdrdir)/ruby/internal/core/rhash.h +fs.o: $(hdrdir)/ruby/internal/core/robject.h +fs.o: $(hdrdir)/ruby/internal/core/rregexp.h +fs.o: $(hdrdir)/ruby/internal/core/rstring.h +fs.o: $(hdrdir)/ruby/internal/core/rstruct.h +fs.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +fs.o: $(hdrdir)/ruby/internal/ctype.h +fs.o: $(hdrdir)/ruby/internal/dllexport.h +fs.o: $(hdrdir)/ruby/internal/dosish.h +fs.o: $(hdrdir)/ruby/internal/encoding/coderange.h +fs.o: $(hdrdir)/ruby/internal/encoding/ctype.h +fs.o: $(hdrdir)/ruby/internal/encoding/encoding.h +fs.o: $(hdrdir)/ruby/internal/encoding/pathname.h +fs.o: $(hdrdir)/ruby/internal/encoding/re.h +fs.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +fs.o: $(hdrdir)/ruby/internal/encoding/string.h +fs.o: $(hdrdir)/ruby/internal/encoding/symbol.h +fs.o: $(hdrdir)/ruby/internal/encoding/transcode.h +fs.o: $(hdrdir)/ruby/internal/error.h +fs.o: $(hdrdir)/ruby/internal/eval.h +fs.o: $(hdrdir)/ruby/internal/event.h +fs.o: $(hdrdir)/ruby/internal/fl_type.h +fs.o: $(hdrdir)/ruby/internal/gc.h +fs.o: $(hdrdir)/ruby/internal/glob.h +fs.o: $(hdrdir)/ruby/internal/globals.h +fs.o: $(hdrdir)/ruby/internal/has/attribute.h +fs.o: $(hdrdir)/ruby/internal/has/builtin.h +fs.o: $(hdrdir)/ruby/internal/has/c_attribute.h +fs.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +fs.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +fs.o: $(hdrdir)/ruby/internal/has/extension.h +fs.o: $(hdrdir)/ruby/internal/has/feature.h +fs.o: $(hdrdir)/ruby/internal/has/warning.h +fs.o: $(hdrdir)/ruby/internal/intern/array.h +fs.o: $(hdrdir)/ruby/internal/intern/bignum.h +fs.o: $(hdrdir)/ruby/internal/intern/class.h +fs.o: $(hdrdir)/ruby/internal/intern/compar.h +fs.o: $(hdrdir)/ruby/internal/intern/complex.h +fs.o: $(hdrdir)/ruby/internal/intern/cont.h +fs.o: $(hdrdir)/ruby/internal/intern/dir.h +fs.o: $(hdrdir)/ruby/internal/intern/enum.h +fs.o: $(hdrdir)/ruby/internal/intern/enumerator.h +fs.o: $(hdrdir)/ruby/internal/intern/error.h +fs.o: $(hdrdir)/ruby/internal/intern/eval.h +fs.o: $(hdrdir)/ruby/internal/intern/file.h +fs.o: $(hdrdir)/ruby/internal/intern/gc.h +fs.o: $(hdrdir)/ruby/internal/intern/hash.h +fs.o: $(hdrdir)/ruby/internal/intern/io.h +fs.o: $(hdrdir)/ruby/internal/intern/load.h +fs.o: $(hdrdir)/ruby/internal/intern/marshal.h +fs.o: $(hdrdir)/ruby/internal/intern/numeric.h +fs.o: $(hdrdir)/ruby/internal/intern/object.h +fs.o: $(hdrdir)/ruby/internal/intern/parse.h +fs.o: $(hdrdir)/ruby/internal/intern/proc.h +fs.o: $(hdrdir)/ruby/internal/intern/process.h +fs.o: $(hdrdir)/ruby/internal/intern/random.h +fs.o: $(hdrdir)/ruby/internal/intern/range.h +fs.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +fs.o: $(hdrdir)/ruby/internal/intern/sprintf.h +fs.o: $(hdrdir)/ruby/internal/intern/string.h +fs.o: $(hdrdir)/ruby/internal/intern/struct.h +fs.o: $(hdrdir)/ruby/internal/intern/thread.h +fs.o: $(hdrdir)/ruby/internal/intern/time.h +fs.o: $(hdrdir)/ruby/internal/intern/variable.h +fs.o: $(hdrdir)/ruby/internal/intern/vm.h +fs.o: $(hdrdir)/ruby/internal/interpreter.h +fs.o: $(hdrdir)/ruby/internal/iterator.h +fs.o: $(hdrdir)/ruby/internal/memory.h +fs.o: $(hdrdir)/ruby/internal/method.h +fs.o: $(hdrdir)/ruby/internal/module.h +fs.o: $(hdrdir)/ruby/internal/newobj.h +fs.o: $(hdrdir)/ruby/internal/rgengc.h +fs.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +fs.o: $(hdrdir)/ruby/internal/value.h +fs.o: $(hdrdir)/ruby/internal/value_type.h +fs.o: $(hdrdir)/ruby/internal/variable.h +fs.o: $(hdrdir)/ruby/internal/warning_push.h +fs.o: $(hdrdir)/ruby/internal/xmalloc.h fs.o: $(hdrdir)/ruby/io.h fs.o: $(hdrdir)/ruby/missing.h fs.o: $(hdrdir)/ruby/onigmo.h @@ -19,8 +175,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -30,9 +333,165 @@ stat.o: $(RUBY_EXTCONF_H) stat.o: $(arch_hdrdir)/ruby/config.h stat.o: $(hdrdir)/ruby/assert.h stat.o: $(hdrdir)/ruby/backward.h +stat.o: $(hdrdir)/ruby/backward/2/assume.h +stat.o: $(hdrdir)/ruby/backward/2/attributes.h +stat.o: $(hdrdir)/ruby/backward/2/bool.h +stat.o: $(hdrdir)/ruby/backward/2/inttypes.h +stat.o: $(hdrdir)/ruby/backward/2/limits.h +stat.o: $(hdrdir)/ruby/backward/2/long_long.h +stat.o: $(hdrdir)/ruby/backward/2/stdalign.h +stat.o: $(hdrdir)/ruby/backward/2/stdarg.h stat.o: $(hdrdir)/ruby/defines.h stat.o: $(hdrdir)/ruby/encoding.h stat.o: $(hdrdir)/ruby/intern.h +stat.o: $(hdrdir)/ruby/internal/anyargs.h +stat.o: $(hdrdir)/ruby/internal/arithmetic.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/char.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/double.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/int.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/long.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/short.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +stat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +stat.o: $(hdrdir)/ruby/internal/assume.h +stat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +stat.o: $(hdrdir)/ruby/internal/attr/artificial.h +stat.o: $(hdrdir)/ruby/internal/attr/cold.h +stat.o: $(hdrdir)/ruby/internal/attr/const.h +stat.o: $(hdrdir)/ruby/internal/attr/constexpr.h +stat.o: $(hdrdir)/ruby/internal/attr/deprecated.h +stat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +stat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +stat.o: $(hdrdir)/ruby/internal/attr/error.h +stat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +stat.o: $(hdrdir)/ruby/internal/attr/forceinline.h +stat.o: $(hdrdir)/ruby/internal/attr/format.h +stat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +stat.o: $(hdrdir)/ruby/internal/attr/noalias.h +stat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +stat.o: $(hdrdir)/ruby/internal/attr/noexcept.h +stat.o: $(hdrdir)/ruby/internal/attr/noinline.h +stat.o: $(hdrdir)/ruby/internal/attr/nonnull.h +stat.o: $(hdrdir)/ruby/internal/attr/noreturn.h +stat.o: $(hdrdir)/ruby/internal/attr/pure.h +stat.o: $(hdrdir)/ruby/internal/attr/restrict.h +stat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +stat.o: $(hdrdir)/ruby/internal/attr/warning.h +stat.o: $(hdrdir)/ruby/internal/attr/weakref.h +stat.o: $(hdrdir)/ruby/internal/cast.h +stat.o: $(hdrdir)/ruby/internal/compiler_is.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +stat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +stat.o: $(hdrdir)/ruby/internal/compiler_since.h +stat.o: $(hdrdir)/ruby/internal/config.h +stat.o: $(hdrdir)/ruby/internal/constant_p.h +stat.o: $(hdrdir)/ruby/internal/core.h +stat.o: $(hdrdir)/ruby/internal/core/rarray.h +stat.o: $(hdrdir)/ruby/internal/core/rbasic.h +stat.o: $(hdrdir)/ruby/internal/core/rbignum.h +stat.o: $(hdrdir)/ruby/internal/core/rclass.h +stat.o: $(hdrdir)/ruby/internal/core/rdata.h +stat.o: $(hdrdir)/ruby/internal/core/rfile.h +stat.o: $(hdrdir)/ruby/internal/core/rhash.h +stat.o: $(hdrdir)/ruby/internal/core/robject.h +stat.o: $(hdrdir)/ruby/internal/core/rregexp.h +stat.o: $(hdrdir)/ruby/internal/core/rstring.h +stat.o: $(hdrdir)/ruby/internal/core/rstruct.h +stat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +stat.o: $(hdrdir)/ruby/internal/ctype.h +stat.o: $(hdrdir)/ruby/internal/dllexport.h +stat.o: $(hdrdir)/ruby/internal/dosish.h +stat.o: $(hdrdir)/ruby/internal/encoding/coderange.h +stat.o: $(hdrdir)/ruby/internal/encoding/ctype.h +stat.o: $(hdrdir)/ruby/internal/encoding/encoding.h +stat.o: $(hdrdir)/ruby/internal/encoding/pathname.h +stat.o: $(hdrdir)/ruby/internal/encoding/re.h +stat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +stat.o: $(hdrdir)/ruby/internal/encoding/string.h +stat.o: $(hdrdir)/ruby/internal/encoding/symbol.h +stat.o: $(hdrdir)/ruby/internal/encoding/transcode.h +stat.o: $(hdrdir)/ruby/internal/error.h +stat.o: $(hdrdir)/ruby/internal/eval.h +stat.o: $(hdrdir)/ruby/internal/event.h +stat.o: $(hdrdir)/ruby/internal/fl_type.h +stat.o: $(hdrdir)/ruby/internal/gc.h +stat.o: $(hdrdir)/ruby/internal/glob.h +stat.o: $(hdrdir)/ruby/internal/globals.h +stat.o: $(hdrdir)/ruby/internal/has/attribute.h +stat.o: $(hdrdir)/ruby/internal/has/builtin.h +stat.o: $(hdrdir)/ruby/internal/has/c_attribute.h +stat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +stat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +stat.o: $(hdrdir)/ruby/internal/has/extension.h +stat.o: $(hdrdir)/ruby/internal/has/feature.h +stat.o: $(hdrdir)/ruby/internal/has/warning.h +stat.o: $(hdrdir)/ruby/internal/intern/array.h +stat.o: $(hdrdir)/ruby/internal/intern/bignum.h +stat.o: $(hdrdir)/ruby/internal/intern/class.h +stat.o: $(hdrdir)/ruby/internal/intern/compar.h +stat.o: $(hdrdir)/ruby/internal/intern/complex.h +stat.o: $(hdrdir)/ruby/internal/intern/cont.h +stat.o: $(hdrdir)/ruby/internal/intern/dir.h +stat.o: $(hdrdir)/ruby/internal/intern/enum.h +stat.o: $(hdrdir)/ruby/internal/intern/enumerator.h +stat.o: $(hdrdir)/ruby/internal/intern/error.h +stat.o: $(hdrdir)/ruby/internal/intern/eval.h +stat.o: $(hdrdir)/ruby/internal/intern/file.h +stat.o: $(hdrdir)/ruby/internal/intern/gc.h +stat.o: $(hdrdir)/ruby/internal/intern/hash.h +stat.o: $(hdrdir)/ruby/internal/intern/io.h +stat.o: $(hdrdir)/ruby/internal/intern/load.h +stat.o: $(hdrdir)/ruby/internal/intern/marshal.h +stat.o: $(hdrdir)/ruby/internal/intern/numeric.h +stat.o: $(hdrdir)/ruby/internal/intern/object.h +stat.o: $(hdrdir)/ruby/internal/intern/parse.h +stat.o: $(hdrdir)/ruby/internal/intern/proc.h +stat.o: $(hdrdir)/ruby/internal/intern/process.h +stat.o: $(hdrdir)/ruby/internal/intern/random.h +stat.o: $(hdrdir)/ruby/internal/intern/range.h +stat.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +stat.o: $(hdrdir)/ruby/internal/intern/sprintf.h +stat.o: $(hdrdir)/ruby/internal/intern/string.h +stat.o: $(hdrdir)/ruby/internal/intern/struct.h +stat.o: $(hdrdir)/ruby/internal/intern/thread.h +stat.o: $(hdrdir)/ruby/internal/intern/time.h +stat.o: $(hdrdir)/ruby/internal/intern/variable.h +stat.o: $(hdrdir)/ruby/internal/intern/vm.h +stat.o: $(hdrdir)/ruby/internal/interpreter.h +stat.o: $(hdrdir)/ruby/internal/iterator.h +stat.o: $(hdrdir)/ruby/internal/memory.h +stat.o: $(hdrdir)/ruby/internal/method.h +stat.o: $(hdrdir)/ruby/internal/module.h +stat.o: $(hdrdir)/ruby/internal/newobj.h +stat.o: $(hdrdir)/ruby/internal/rgengc.h +stat.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +stat.o: $(hdrdir)/ruby/internal/value.h +stat.o: $(hdrdir)/ruby/internal/value_type.h +stat.o: $(hdrdir)/ruby/internal/variable.h +stat.o: $(hdrdir)/ruby/internal/warning_push.h +stat.o: $(hdrdir)/ruby/internal/xmalloc.h stat.o: $(hdrdir)/ruby/io.h stat.o: $(hdrdir)/ruby/missing.h stat.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/-test-/float/depend b/ruby/ext/-test-/float/depend index 6007bd3c0..661f4876d 100644 --- a/ruby/ext/-test-/float/depend +++ b/ruby/ext/-test-/float/depend @@ -7,8 +7,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -19,8 +166,155 @@ nextafter.o: $(arch_hdrdir)/ruby/config.h nextafter.o: $(hdrdir)/ruby.h nextafter.o: $(hdrdir)/ruby/assert.h nextafter.o: $(hdrdir)/ruby/backward.h +nextafter.o: $(hdrdir)/ruby/backward/2/assume.h +nextafter.o: $(hdrdir)/ruby/backward/2/attributes.h +nextafter.o: $(hdrdir)/ruby/backward/2/bool.h +nextafter.o: $(hdrdir)/ruby/backward/2/inttypes.h +nextafter.o: $(hdrdir)/ruby/backward/2/limits.h +nextafter.o: $(hdrdir)/ruby/backward/2/long_long.h +nextafter.o: $(hdrdir)/ruby/backward/2/stdalign.h +nextafter.o: $(hdrdir)/ruby/backward/2/stdarg.h nextafter.o: $(hdrdir)/ruby/defines.h nextafter.o: $(hdrdir)/ruby/intern.h +nextafter.o: $(hdrdir)/ruby/internal/anyargs.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/char.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/double.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/int.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/short.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +nextafter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +nextafter.o: $(hdrdir)/ruby/internal/assume.h +nextafter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +nextafter.o: $(hdrdir)/ruby/internal/attr/artificial.h +nextafter.o: $(hdrdir)/ruby/internal/attr/cold.h +nextafter.o: $(hdrdir)/ruby/internal/attr/const.h +nextafter.o: $(hdrdir)/ruby/internal/attr/constexpr.h +nextafter.o: $(hdrdir)/ruby/internal/attr/deprecated.h +nextafter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +nextafter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +nextafter.o: $(hdrdir)/ruby/internal/attr/error.h +nextafter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +nextafter.o: $(hdrdir)/ruby/internal/attr/forceinline.h +nextafter.o: $(hdrdir)/ruby/internal/attr/format.h +nextafter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +nextafter.o: $(hdrdir)/ruby/internal/attr/noalias.h +nextafter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +nextafter.o: $(hdrdir)/ruby/internal/attr/noexcept.h +nextafter.o: $(hdrdir)/ruby/internal/attr/noinline.h +nextafter.o: $(hdrdir)/ruby/internal/attr/nonnull.h +nextafter.o: $(hdrdir)/ruby/internal/attr/noreturn.h +nextafter.o: $(hdrdir)/ruby/internal/attr/pure.h +nextafter.o: $(hdrdir)/ruby/internal/attr/restrict.h +nextafter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +nextafter.o: $(hdrdir)/ruby/internal/attr/warning.h +nextafter.o: $(hdrdir)/ruby/internal/attr/weakref.h +nextafter.o: $(hdrdir)/ruby/internal/cast.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +nextafter.o: $(hdrdir)/ruby/internal/compiler_since.h +nextafter.o: $(hdrdir)/ruby/internal/config.h +nextafter.o: $(hdrdir)/ruby/internal/constant_p.h +nextafter.o: $(hdrdir)/ruby/internal/core.h +nextafter.o: $(hdrdir)/ruby/internal/core/rarray.h +nextafter.o: $(hdrdir)/ruby/internal/core/rbasic.h +nextafter.o: $(hdrdir)/ruby/internal/core/rbignum.h +nextafter.o: $(hdrdir)/ruby/internal/core/rclass.h +nextafter.o: $(hdrdir)/ruby/internal/core/rdata.h +nextafter.o: $(hdrdir)/ruby/internal/core/rfile.h +nextafter.o: $(hdrdir)/ruby/internal/core/rhash.h +nextafter.o: $(hdrdir)/ruby/internal/core/robject.h +nextafter.o: $(hdrdir)/ruby/internal/core/rregexp.h +nextafter.o: $(hdrdir)/ruby/internal/core/rstring.h +nextafter.o: $(hdrdir)/ruby/internal/core/rstruct.h +nextafter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +nextafter.o: $(hdrdir)/ruby/internal/ctype.h +nextafter.o: $(hdrdir)/ruby/internal/dllexport.h +nextafter.o: $(hdrdir)/ruby/internal/dosish.h +nextafter.o: $(hdrdir)/ruby/internal/error.h +nextafter.o: $(hdrdir)/ruby/internal/eval.h +nextafter.o: $(hdrdir)/ruby/internal/event.h +nextafter.o: $(hdrdir)/ruby/internal/fl_type.h +nextafter.o: $(hdrdir)/ruby/internal/gc.h +nextafter.o: $(hdrdir)/ruby/internal/glob.h +nextafter.o: $(hdrdir)/ruby/internal/globals.h +nextafter.o: $(hdrdir)/ruby/internal/has/attribute.h +nextafter.o: $(hdrdir)/ruby/internal/has/builtin.h +nextafter.o: $(hdrdir)/ruby/internal/has/c_attribute.h +nextafter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +nextafter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +nextafter.o: $(hdrdir)/ruby/internal/has/extension.h +nextafter.o: $(hdrdir)/ruby/internal/has/feature.h +nextafter.o: $(hdrdir)/ruby/internal/has/warning.h +nextafter.o: $(hdrdir)/ruby/internal/intern/array.h +nextafter.o: $(hdrdir)/ruby/internal/intern/bignum.h +nextafter.o: $(hdrdir)/ruby/internal/intern/class.h +nextafter.o: $(hdrdir)/ruby/internal/intern/compar.h +nextafter.o: $(hdrdir)/ruby/internal/intern/complex.h +nextafter.o: $(hdrdir)/ruby/internal/intern/cont.h +nextafter.o: $(hdrdir)/ruby/internal/intern/dir.h +nextafter.o: $(hdrdir)/ruby/internal/intern/enum.h +nextafter.o: $(hdrdir)/ruby/internal/intern/enumerator.h +nextafter.o: $(hdrdir)/ruby/internal/intern/error.h +nextafter.o: $(hdrdir)/ruby/internal/intern/eval.h +nextafter.o: $(hdrdir)/ruby/internal/intern/file.h +nextafter.o: $(hdrdir)/ruby/internal/intern/gc.h +nextafter.o: $(hdrdir)/ruby/internal/intern/hash.h +nextafter.o: $(hdrdir)/ruby/internal/intern/io.h +nextafter.o: $(hdrdir)/ruby/internal/intern/load.h +nextafter.o: $(hdrdir)/ruby/internal/intern/marshal.h +nextafter.o: $(hdrdir)/ruby/internal/intern/numeric.h +nextafter.o: $(hdrdir)/ruby/internal/intern/object.h +nextafter.o: $(hdrdir)/ruby/internal/intern/parse.h +nextafter.o: $(hdrdir)/ruby/internal/intern/proc.h +nextafter.o: $(hdrdir)/ruby/internal/intern/process.h +nextafter.o: $(hdrdir)/ruby/internal/intern/random.h +nextafter.o: $(hdrdir)/ruby/internal/intern/range.h +nextafter.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +nextafter.o: $(hdrdir)/ruby/internal/intern/sprintf.h +nextafter.o: $(hdrdir)/ruby/internal/intern/string.h +nextafter.o: $(hdrdir)/ruby/internal/intern/struct.h +nextafter.o: $(hdrdir)/ruby/internal/intern/thread.h +nextafter.o: $(hdrdir)/ruby/internal/intern/time.h +nextafter.o: $(hdrdir)/ruby/internal/intern/variable.h +nextafter.o: $(hdrdir)/ruby/internal/intern/vm.h +nextafter.o: $(hdrdir)/ruby/internal/interpreter.h +nextafter.o: $(hdrdir)/ruby/internal/iterator.h +nextafter.o: $(hdrdir)/ruby/internal/memory.h +nextafter.o: $(hdrdir)/ruby/internal/method.h +nextafter.o: $(hdrdir)/ruby/internal/module.h +nextafter.o: $(hdrdir)/ruby/internal/newobj.h +nextafter.o: $(hdrdir)/ruby/internal/rgengc.h +nextafter.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +nextafter.o: $(hdrdir)/ruby/internal/value.h +nextafter.o: $(hdrdir)/ruby/internal/value_type.h +nextafter.o: $(hdrdir)/ruby/internal/variable.h +nextafter.o: $(hdrdir)/ruby/internal/warning_push.h +nextafter.o: $(hdrdir)/ruby/internal/xmalloc.h nextafter.o: $(hdrdir)/ruby/missing.h nextafter.o: $(hdrdir)/ruby/ruby.h nextafter.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/funcall/depend b/ruby/ext/-test-/funcall/depend index a5f43a804..adec76f14 100644 --- a/ruby/ext/-test-/funcall/depend +++ b/ruby/ext/-test-/funcall/depend @@ -4,8 +4,155 @@ funcall.o: $(arch_hdrdir)/ruby/config.h funcall.o: $(hdrdir)/ruby.h funcall.o: $(hdrdir)/ruby/assert.h funcall.o: $(hdrdir)/ruby/backward.h +funcall.o: $(hdrdir)/ruby/backward/2/assume.h +funcall.o: $(hdrdir)/ruby/backward/2/attributes.h +funcall.o: $(hdrdir)/ruby/backward/2/bool.h +funcall.o: $(hdrdir)/ruby/backward/2/inttypes.h +funcall.o: $(hdrdir)/ruby/backward/2/limits.h +funcall.o: $(hdrdir)/ruby/backward/2/long_long.h +funcall.o: $(hdrdir)/ruby/backward/2/stdalign.h +funcall.o: $(hdrdir)/ruby/backward/2/stdarg.h funcall.o: $(hdrdir)/ruby/defines.h funcall.o: $(hdrdir)/ruby/intern.h +funcall.o: $(hdrdir)/ruby/internal/anyargs.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/char.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/double.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/int.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/long.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/short.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +funcall.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +funcall.o: $(hdrdir)/ruby/internal/assume.h +funcall.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +funcall.o: $(hdrdir)/ruby/internal/attr/artificial.h +funcall.o: $(hdrdir)/ruby/internal/attr/cold.h +funcall.o: $(hdrdir)/ruby/internal/attr/const.h +funcall.o: $(hdrdir)/ruby/internal/attr/constexpr.h +funcall.o: $(hdrdir)/ruby/internal/attr/deprecated.h +funcall.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +funcall.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +funcall.o: $(hdrdir)/ruby/internal/attr/error.h +funcall.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +funcall.o: $(hdrdir)/ruby/internal/attr/forceinline.h +funcall.o: $(hdrdir)/ruby/internal/attr/format.h +funcall.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +funcall.o: $(hdrdir)/ruby/internal/attr/noalias.h +funcall.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +funcall.o: $(hdrdir)/ruby/internal/attr/noexcept.h +funcall.o: $(hdrdir)/ruby/internal/attr/noinline.h +funcall.o: $(hdrdir)/ruby/internal/attr/nonnull.h +funcall.o: $(hdrdir)/ruby/internal/attr/noreturn.h +funcall.o: $(hdrdir)/ruby/internal/attr/pure.h +funcall.o: $(hdrdir)/ruby/internal/attr/restrict.h +funcall.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +funcall.o: $(hdrdir)/ruby/internal/attr/warning.h +funcall.o: $(hdrdir)/ruby/internal/attr/weakref.h +funcall.o: $(hdrdir)/ruby/internal/cast.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +funcall.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +funcall.o: $(hdrdir)/ruby/internal/compiler_since.h +funcall.o: $(hdrdir)/ruby/internal/config.h +funcall.o: $(hdrdir)/ruby/internal/constant_p.h +funcall.o: $(hdrdir)/ruby/internal/core.h +funcall.o: $(hdrdir)/ruby/internal/core/rarray.h +funcall.o: $(hdrdir)/ruby/internal/core/rbasic.h +funcall.o: $(hdrdir)/ruby/internal/core/rbignum.h +funcall.o: $(hdrdir)/ruby/internal/core/rclass.h +funcall.o: $(hdrdir)/ruby/internal/core/rdata.h +funcall.o: $(hdrdir)/ruby/internal/core/rfile.h +funcall.o: $(hdrdir)/ruby/internal/core/rhash.h +funcall.o: $(hdrdir)/ruby/internal/core/robject.h +funcall.o: $(hdrdir)/ruby/internal/core/rregexp.h +funcall.o: $(hdrdir)/ruby/internal/core/rstring.h +funcall.o: $(hdrdir)/ruby/internal/core/rstruct.h +funcall.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +funcall.o: $(hdrdir)/ruby/internal/ctype.h +funcall.o: $(hdrdir)/ruby/internal/dllexport.h +funcall.o: $(hdrdir)/ruby/internal/dosish.h +funcall.o: $(hdrdir)/ruby/internal/error.h +funcall.o: $(hdrdir)/ruby/internal/eval.h +funcall.o: $(hdrdir)/ruby/internal/event.h +funcall.o: $(hdrdir)/ruby/internal/fl_type.h +funcall.o: $(hdrdir)/ruby/internal/gc.h +funcall.o: $(hdrdir)/ruby/internal/glob.h +funcall.o: $(hdrdir)/ruby/internal/globals.h +funcall.o: $(hdrdir)/ruby/internal/has/attribute.h +funcall.o: $(hdrdir)/ruby/internal/has/builtin.h +funcall.o: $(hdrdir)/ruby/internal/has/c_attribute.h +funcall.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +funcall.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +funcall.o: $(hdrdir)/ruby/internal/has/extension.h +funcall.o: $(hdrdir)/ruby/internal/has/feature.h +funcall.o: $(hdrdir)/ruby/internal/has/warning.h +funcall.o: $(hdrdir)/ruby/internal/intern/array.h +funcall.o: $(hdrdir)/ruby/internal/intern/bignum.h +funcall.o: $(hdrdir)/ruby/internal/intern/class.h +funcall.o: $(hdrdir)/ruby/internal/intern/compar.h +funcall.o: $(hdrdir)/ruby/internal/intern/complex.h +funcall.o: $(hdrdir)/ruby/internal/intern/cont.h +funcall.o: $(hdrdir)/ruby/internal/intern/dir.h +funcall.o: $(hdrdir)/ruby/internal/intern/enum.h +funcall.o: $(hdrdir)/ruby/internal/intern/enumerator.h +funcall.o: $(hdrdir)/ruby/internal/intern/error.h +funcall.o: $(hdrdir)/ruby/internal/intern/eval.h +funcall.o: $(hdrdir)/ruby/internal/intern/file.h +funcall.o: $(hdrdir)/ruby/internal/intern/gc.h +funcall.o: $(hdrdir)/ruby/internal/intern/hash.h +funcall.o: $(hdrdir)/ruby/internal/intern/io.h +funcall.o: $(hdrdir)/ruby/internal/intern/load.h +funcall.o: $(hdrdir)/ruby/internal/intern/marshal.h +funcall.o: $(hdrdir)/ruby/internal/intern/numeric.h +funcall.o: $(hdrdir)/ruby/internal/intern/object.h +funcall.o: $(hdrdir)/ruby/internal/intern/parse.h +funcall.o: $(hdrdir)/ruby/internal/intern/proc.h +funcall.o: $(hdrdir)/ruby/internal/intern/process.h +funcall.o: $(hdrdir)/ruby/internal/intern/random.h +funcall.o: $(hdrdir)/ruby/internal/intern/range.h +funcall.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +funcall.o: $(hdrdir)/ruby/internal/intern/sprintf.h +funcall.o: $(hdrdir)/ruby/internal/intern/string.h +funcall.o: $(hdrdir)/ruby/internal/intern/struct.h +funcall.o: $(hdrdir)/ruby/internal/intern/thread.h +funcall.o: $(hdrdir)/ruby/internal/intern/time.h +funcall.o: $(hdrdir)/ruby/internal/intern/variable.h +funcall.o: $(hdrdir)/ruby/internal/intern/vm.h +funcall.o: $(hdrdir)/ruby/internal/interpreter.h +funcall.o: $(hdrdir)/ruby/internal/iterator.h +funcall.o: $(hdrdir)/ruby/internal/memory.h +funcall.o: $(hdrdir)/ruby/internal/method.h +funcall.o: $(hdrdir)/ruby/internal/module.h +funcall.o: $(hdrdir)/ruby/internal/newobj.h +funcall.o: $(hdrdir)/ruby/internal/rgengc.h +funcall.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +funcall.o: $(hdrdir)/ruby/internal/value.h +funcall.o: $(hdrdir)/ruby/internal/value_type.h +funcall.o: $(hdrdir)/ruby/internal/variable.h +funcall.o: $(hdrdir)/ruby/internal/warning_push.h +funcall.o: $(hdrdir)/ruby/internal/xmalloc.h funcall.o: $(hdrdir)/ruby/missing.h funcall.o: $(hdrdir)/ruby/ruby.h funcall.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/gvl/call_without_gvl/call_without_gvl.c b/ruby/ext/-test-/gvl/call_without_gvl/call_without_gvl.c index d77c2f323..233635421 100644 --- a/ruby/ext/-test-/gvl/call_without_gvl/call_without_gvl.c +++ b/ruby/ext/-test-/gvl/call_without_gvl/call_without_gvl.c @@ -24,7 +24,7 @@ thread_runnable_sleep(VALUE thread, VALUE timeout) rb_thread_call_without_gvl(native_sleep_callback, &timeval, RUBY_UBF_IO, NULL); - return thread; + return Qnil; } struct loop_ctl { @@ -65,12 +65,14 @@ thread_ubf_async_safe(VALUE thread, VALUE notify_fd) ctl.stop = 0; rb_nogvl(do_loop, &ctl, stop_set, &ctl, RB_NOGVL_UBF_ASYNC_SAFE); - return thread; + return Qnil; } void Init_call_without_gvl(void) { - rb_define_method(rb_cThread, "__runnable_sleep__", thread_runnable_sleep, 1); - rb_define_method(rb_cThread, "__ubf_async_safe__", thread_ubf_async_safe, 1); + VALUE mBug = rb_define_module("Bug"); + VALUE klass = rb_define_module_under(mBug, "Thread"); + rb_define_singleton_method(klass, "runnable_sleep", thread_runnable_sleep, 1); + rb_define_singleton_method(klass, "ubf_async_safe", thread_ubf_async_safe, 1); } diff --git a/ruby/ext/-test-/gvl/call_without_gvl/depend b/ruby/ext/-test-/gvl/call_without_gvl/depend index 3d4253b97..d74a52522 100644 --- a/ruby/ext/-test-/gvl/call_without_gvl/depend +++ b/ruby/ext/-test-/gvl/call_without_gvl/depend @@ -3,8 +3,155 @@ call_without_gvl.o: $(RUBY_EXTCONF_H) call_without_gvl.o: $(arch_hdrdir)/ruby/config.h call_without_gvl.o: $(hdrdir)/ruby/assert.h call_without_gvl.o: $(hdrdir)/ruby/backward.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/assume.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/attributes.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/bool.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/inttypes.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/limits.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/long_long.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdalign.h +call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdarg.h call_without_gvl.o: $(hdrdir)/ruby/defines.h call_without_gvl.o: $(hdrdir)/ruby/intern.h +call_without_gvl.o: $(hdrdir)/ruby/internal/anyargs.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +call_without_gvl.o: $(hdrdir)/ruby/internal/assume.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/artificial.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/cold.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/const.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/error.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/format.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noalias.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noinline.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/pure.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/restrict.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/warning.h +call_without_gvl.o: $(hdrdir)/ruby/internal/attr/weakref.h +call_without_gvl.o: $(hdrdir)/ruby/internal/cast.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_since.h +call_without_gvl.o: $(hdrdir)/ruby/internal/config.h +call_without_gvl.o: $(hdrdir)/ruby/internal/constant_p.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rarray.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbasic.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbignum.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rclass.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rdata.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rfile.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rhash.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/robject.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rregexp.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstring.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstruct.h +call_without_gvl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +call_without_gvl.o: $(hdrdir)/ruby/internal/ctype.h +call_without_gvl.o: $(hdrdir)/ruby/internal/dllexport.h +call_without_gvl.o: $(hdrdir)/ruby/internal/dosish.h +call_without_gvl.o: $(hdrdir)/ruby/internal/error.h +call_without_gvl.o: $(hdrdir)/ruby/internal/eval.h +call_without_gvl.o: $(hdrdir)/ruby/internal/event.h +call_without_gvl.o: $(hdrdir)/ruby/internal/fl_type.h +call_without_gvl.o: $(hdrdir)/ruby/internal/gc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/glob.h +call_without_gvl.o: $(hdrdir)/ruby/internal/globals.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/attribute.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/builtin.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/extension.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/feature.h +call_without_gvl.o: $(hdrdir)/ruby/internal/has/warning.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/array.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/bignum.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/class.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/compar.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/complex.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/cont.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/dir.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enum.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/error.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/eval.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/file.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/gc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/hash.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/io.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/load.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/marshal.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/numeric.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/object.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/parse.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/proc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/process.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/random.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/range.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/struct.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/thread.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/time.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/variable.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/vm.h +call_without_gvl.o: $(hdrdir)/ruby/internal/interpreter.h +call_without_gvl.o: $(hdrdir)/ruby/internal/iterator.h +call_without_gvl.o: $(hdrdir)/ruby/internal/memory.h +call_without_gvl.o: $(hdrdir)/ruby/internal/method.h +call_without_gvl.o: $(hdrdir)/ruby/internal/module.h +call_without_gvl.o: $(hdrdir)/ruby/internal/newobj.h +call_without_gvl.o: $(hdrdir)/ruby/internal/rgengc.h +call_without_gvl.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +call_without_gvl.o: $(hdrdir)/ruby/internal/value.h +call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h +call_without_gvl.o: $(hdrdir)/ruby/internal/variable.h +call_without_gvl.o: $(hdrdir)/ruby/internal/warning_push.h +call_without_gvl.o: $(hdrdir)/ruby/internal/xmalloc.h call_without_gvl.o: $(hdrdir)/ruby/missing.h call_without_gvl.o: $(hdrdir)/ruby/ruby.h call_without_gvl.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/hash/depend b/ruby/ext/-test-/hash/depend index 5e2b8056c..b8460734c 100644 --- a/ruby/ext/-test-/hash/depend +++ b/ruby/ext/-test-/hash/depend @@ -4,8 +4,155 @@ delete.o: $(arch_hdrdir)/ruby/config.h delete.o: $(hdrdir)/ruby.h delete.o: $(hdrdir)/ruby/assert.h delete.o: $(hdrdir)/ruby/backward.h +delete.o: $(hdrdir)/ruby/backward/2/assume.h +delete.o: $(hdrdir)/ruby/backward/2/attributes.h +delete.o: $(hdrdir)/ruby/backward/2/bool.h +delete.o: $(hdrdir)/ruby/backward/2/inttypes.h +delete.o: $(hdrdir)/ruby/backward/2/limits.h +delete.o: $(hdrdir)/ruby/backward/2/long_long.h +delete.o: $(hdrdir)/ruby/backward/2/stdalign.h +delete.o: $(hdrdir)/ruby/backward/2/stdarg.h delete.o: $(hdrdir)/ruby/defines.h delete.o: $(hdrdir)/ruby/intern.h +delete.o: $(hdrdir)/ruby/internal/anyargs.h +delete.o: $(hdrdir)/ruby/internal/arithmetic.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/char.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/double.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/int.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/long.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/short.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +delete.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +delete.o: $(hdrdir)/ruby/internal/assume.h +delete.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +delete.o: $(hdrdir)/ruby/internal/attr/artificial.h +delete.o: $(hdrdir)/ruby/internal/attr/cold.h +delete.o: $(hdrdir)/ruby/internal/attr/const.h +delete.o: $(hdrdir)/ruby/internal/attr/constexpr.h +delete.o: $(hdrdir)/ruby/internal/attr/deprecated.h +delete.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +delete.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +delete.o: $(hdrdir)/ruby/internal/attr/error.h +delete.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +delete.o: $(hdrdir)/ruby/internal/attr/forceinline.h +delete.o: $(hdrdir)/ruby/internal/attr/format.h +delete.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +delete.o: $(hdrdir)/ruby/internal/attr/noalias.h +delete.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +delete.o: $(hdrdir)/ruby/internal/attr/noexcept.h +delete.o: $(hdrdir)/ruby/internal/attr/noinline.h +delete.o: $(hdrdir)/ruby/internal/attr/nonnull.h +delete.o: $(hdrdir)/ruby/internal/attr/noreturn.h +delete.o: $(hdrdir)/ruby/internal/attr/pure.h +delete.o: $(hdrdir)/ruby/internal/attr/restrict.h +delete.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +delete.o: $(hdrdir)/ruby/internal/attr/warning.h +delete.o: $(hdrdir)/ruby/internal/attr/weakref.h +delete.o: $(hdrdir)/ruby/internal/cast.h +delete.o: $(hdrdir)/ruby/internal/compiler_is.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +delete.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +delete.o: $(hdrdir)/ruby/internal/compiler_since.h +delete.o: $(hdrdir)/ruby/internal/config.h +delete.o: $(hdrdir)/ruby/internal/constant_p.h +delete.o: $(hdrdir)/ruby/internal/core.h +delete.o: $(hdrdir)/ruby/internal/core/rarray.h +delete.o: $(hdrdir)/ruby/internal/core/rbasic.h +delete.o: $(hdrdir)/ruby/internal/core/rbignum.h +delete.o: $(hdrdir)/ruby/internal/core/rclass.h +delete.o: $(hdrdir)/ruby/internal/core/rdata.h +delete.o: $(hdrdir)/ruby/internal/core/rfile.h +delete.o: $(hdrdir)/ruby/internal/core/rhash.h +delete.o: $(hdrdir)/ruby/internal/core/robject.h +delete.o: $(hdrdir)/ruby/internal/core/rregexp.h +delete.o: $(hdrdir)/ruby/internal/core/rstring.h +delete.o: $(hdrdir)/ruby/internal/core/rstruct.h +delete.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +delete.o: $(hdrdir)/ruby/internal/ctype.h +delete.o: $(hdrdir)/ruby/internal/dllexport.h +delete.o: $(hdrdir)/ruby/internal/dosish.h +delete.o: $(hdrdir)/ruby/internal/error.h +delete.o: $(hdrdir)/ruby/internal/eval.h +delete.o: $(hdrdir)/ruby/internal/event.h +delete.o: $(hdrdir)/ruby/internal/fl_type.h +delete.o: $(hdrdir)/ruby/internal/gc.h +delete.o: $(hdrdir)/ruby/internal/glob.h +delete.o: $(hdrdir)/ruby/internal/globals.h +delete.o: $(hdrdir)/ruby/internal/has/attribute.h +delete.o: $(hdrdir)/ruby/internal/has/builtin.h +delete.o: $(hdrdir)/ruby/internal/has/c_attribute.h +delete.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +delete.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +delete.o: $(hdrdir)/ruby/internal/has/extension.h +delete.o: $(hdrdir)/ruby/internal/has/feature.h +delete.o: $(hdrdir)/ruby/internal/has/warning.h +delete.o: $(hdrdir)/ruby/internal/intern/array.h +delete.o: $(hdrdir)/ruby/internal/intern/bignum.h +delete.o: $(hdrdir)/ruby/internal/intern/class.h +delete.o: $(hdrdir)/ruby/internal/intern/compar.h +delete.o: $(hdrdir)/ruby/internal/intern/complex.h +delete.o: $(hdrdir)/ruby/internal/intern/cont.h +delete.o: $(hdrdir)/ruby/internal/intern/dir.h +delete.o: $(hdrdir)/ruby/internal/intern/enum.h +delete.o: $(hdrdir)/ruby/internal/intern/enumerator.h +delete.o: $(hdrdir)/ruby/internal/intern/error.h +delete.o: $(hdrdir)/ruby/internal/intern/eval.h +delete.o: $(hdrdir)/ruby/internal/intern/file.h +delete.o: $(hdrdir)/ruby/internal/intern/gc.h +delete.o: $(hdrdir)/ruby/internal/intern/hash.h +delete.o: $(hdrdir)/ruby/internal/intern/io.h +delete.o: $(hdrdir)/ruby/internal/intern/load.h +delete.o: $(hdrdir)/ruby/internal/intern/marshal.h +delete.o: $(hdrdir)/ruby/internal/intern/numeric.h +delete.o: $(hdrdir)/ruby/internal/intern/object.h +delete.o: $(hdrdir)/ruby/internal/intern/parse.h +delete.o: $(hdrdir)/ruby/internal/intern/proc.h +delete.o: $(hdrdir)/ruby/internal/intern/process.h +delete.o: $(hdrdir)/ruby/internal/intern/random.h +delete.o: $(hdrdir)/ruby/internal/intern/range.h +delete.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +delete.o: $(hdrdir)/ruby/internal/intern/sprintf.h +delete.o: $(hdrdir)/ruby/internal/intern/string.h +delete.o: $(hdrdir)/ruby/internal/intern/struct.h +delete.o: $(hdrdir)/ruby/internal/intern/thread.h +delete.o: $(hdrdir)/ruby/internal/intern/time.h +delete.o: $(hdrdir)/ruby/internal/intern/variable.h +delete.o: $(hdrdir)/ruby/internal/intern/vm.h +delete.o: $(hdrdir)/ruby/internal/interpreter.h +delete.o: $(hdrdir)/ruby/internal/iterator.h +delete.o: $(hdrdir)/ruby/internal/memory.h +delete.o: $(hdrdir)/ruby/internal/method.h +delete.o: $(hdrdir)/ruby/internal/module.h +delete.o: $(hdrdir)/ruby/internal/newobj.h +delete.o: $(hdrdir)/ruby/internal/rgengc.h +delete.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +delete.o: $(hdrdir)/ruby/internal/value.h +delete.o: $(hdrdir)/ruby/internal/value_type.h +delete.o: $(hdrdir)/ruby/internal/variable.h +delete.o: $(hdrdir)/ruby/internal/warning_push.h +delete.o: $(hdrdir)/ruby/internal/xmalloc.h delete.o: $(hdrdir)/ruby/missing.h delete.o: $(hdrdir)/ruby/ruby.h delete.o: $(hdrdir)/ruby/st.h @@ -16,8 +163,155 @@ 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/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/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/gc.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/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/rgengc.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/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 diff --git a/ruby/ext/-test-/integer/core_ext.c b/ruby/ext/-test-/integer/core_ext.c index 510ba4a1e..e364aa4b4 100644 --- a/ruby/ext/-test-/integer/core_ext.c +++ b/ruby/ext/-test-/integer/core_ext.c @@ -1,19 +1,19 @@ -#include "internal.h" +#include "internal/numeric.h" static VALUE -int_bignum_p(VALUE self) +int_bignum_p(VALUE klass, VALUE self) { return RB_TYPE_P(self, T_BIGNUM) ? Qtrue : Qfalse; } static VALUE -int_fixnum_p(VALUE self) +int_fixnum_p(VALUE klass, VALUE self) { return FIXNUM_P(self) ? Qtrue : Qfalse; } static VALUE -rb_int_to_bignum(VALUE x) +rb_int_to_bignum(VALUE klass, VALUE x) { if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x)); @@ -21,7 +21,7 @@ rb_int_to_bignum(VALUE x) } static VALUE -positive_pow(VALUE x, VALUE y) +positive_pow(VALUE klass, VALUE x, VALUE y) { return rb_int_positive_pow(NUM2LONG(x), NUM2ULONG(y)); } @@ -29,8 +29,8 @@ positive_pow(VALUE x, VALUE y) void Init_core_ext(VALUE klass) { - rb_define_method(rb_cInteger, "bignum?", int_bignum_p, 0); - rb_define_method(rb_cInteger, "fixnum?", int_fixnum_p, 0); - rb_define_method(rb_cInteger, "to_bignum", rb_int_to_bignum, 0); - rb_define_method(rb_cInteger, "positive_pow", positive_pow, 1); + rb_define_singleton_method(klass, "bignum?", int_bignum_p, 1); + rb_define_singleton_method(klass, "fixnum?", int_fixnum_p, 1); + rb_define_singleton_method(klass, "to_bignum", rb_int_to_bignum, 1); + rb_define_singleton_method(klass, "positive_pow", positive_pow, 2); } diff --git a/ruby/ext/-test-/integer/depend b/ruby/ext/-test-/integer/depend index 5c9d58138..522f6283a 100644 --- a/ruby/ext/-test-/integer/depend +++ b/ruby/ext/-test-/integer/depend @@ -1,24 +1,325 @@ # AUTOGENERATED DEPENDENCIES START core_ext.o: $(RUBY_EXTCONF_H) core_ext.o: $(arch_hdrdir)/ruby/config.h -core_ext.o: $(hdrdir)/ruby.h core_ext.o: $(hdrdir)/ruby/assert.h core_ext.o: $(hdrdir)/ruby/backward.h +core_ext.o: $(hdrdir)/ruby/backward/2/assume.h +core_ext.o: $(hdrdir)/ruby/backward/2/attributes.h +core_ext.o: $(hdrdir)/ruby/backward/2/bool.h +core_ext.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +core_ext.o: $(hdrdir)/ruby/backward/2/inttypes.h +core_ext.o: $(hdrdir)/ruby/backward/2/limits.h +core_ext.o: $(hdrdir)/ruby/backward/2/long_long.h +core_ext.o: $(hdrdir)/ruby/backward/2/stdalign.h +core_ext.o: $(hdrdir)/ruby/backward/2/stdarg.h core_ext.o: $(hdrdir)/ruby/defines.h core_ext.o: $(hdrdir)/ruby/intern.h +core_ext.o: $(hdrdir)/ruby/internal/anyargs.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +core_ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +core_ext.o: $(hdrdir)/ruby/internal/assume.h +core_ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +core_ext.o: $(hdrdir)/ruby/internal/attr/artificial.h +core_ext.o: $(hdrdir)/ruby/internal/attr/cold.h +core_ext.o: $(hdrdir)/ruby/internal/attr/const.h +core_ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h +core_ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h +core_ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +core_ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +core_ext.o: $(hdrdir)/ruby/internal/attr/error.h +core_ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +core_ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h +core_ext.o: $(hdrdir)/ruby/internal/attr/format.h +core_ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +core_ext.o: $(hdrdir)/ruby/internal/attr/noalias.h +core_ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +core_ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h +core_ext.o: $(hdrdir)/ruby/internal/attr/noinline.h +core_ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h +core_ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h +core_ext.o: $(hdrdir)/ruby/internal/attr/pure.h +core_ext.o: $(hdrdir)/ruby/internal/attr/restrict.h +core_ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +core_ext.o: $(hdrdir)/ruby/internal/attr/warning.h +core_ext.o: $(hdrdir)/ruby/internal/attr/weakref.h +core_ext.o: $(hdrdir)/ruby/internal/cast.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +core_ext.o: $(hdrdir)/ruby/internal/compiler_since.h +core_ext.o: $(hdrdir)/ruby/internal/config.h +core_ext.o: $(hdrdir)/ruby/internal/constant_p.h +core_ext.o: $(hdrdir)/ruby/internal/core.h +core_ext.o: $(hdrdir)/ruby/internal/core/rarray.h +core_ext.o: $(hdrdir)/ruby/internal/core/rbasic.h +core_ext.o: $(hdrdir)/ruby/internal/core/rbignum.h +core_ext.o: $(hdrdir)/ruby/internal/core/rclass.h +core_ext.o: $(hdrdir)/ruby/internal/core/rdata.h +core_ext.o: $(hdrdir)/ruby/internal/core/rfile.h +core_ext.o: $(hdrdir)/ruby/internal/core/rhash.h +core_ext.o: $(hdrdir)/ruby/internal/core/robject.h +core_ext.o: $(hdrdir)/ruby/internal/core/rregexp.h +core_ext.o: $(hdrdir)/ruby/internal/core/rstring.h +core_ext.o: $(hdrdir)/ruby/internal/core/rstruct.h +core_ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +core_ext.o: $(hdrdir)/ruby/internal/ctype.h +core_ext.o: $(hdrdir)/ruby/internal/dllexport.h +core_ext.o: $(hdrdir)/ruby/internal/dosish.h +core_ext.o: $(hdrdir)/ruby/internal/error.h +core_ext.o: $(hdrdir)/ruby/internal/eval.h +core_ext.o: $(hdrdir)/ruby/internal/event.h +core_ext.o: $(hdrdir)/ruby/internal/fl_type.h +core_ext.o: $(hdrdir)/ruby/internal/gc.h +core_ext.o: $(hdrdir)/ruby/internal/glob.h +core_ext.o: $(hdrdir)/ruby/internal/globals.h +core_ext.o: $(hdrdir)/ruby/internal/has/attribute.h +core_ext.o: $(hdrdir)/ruby/internal/has/builtin.h +core_ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h +core_ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +core_ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +core_ext.o: $(hdrdir)/ruby/internal/has/extension.h +core_ext.o: $(hdrdir)/ruby/internal/has/feature.h +core_ext.o: $(hdrdir)/ruby/internal/has/warning.h +core_ext.o: $(hdrdir)/ruby/internal/intern/array.h +core_ext.o: $(hdrdir)/ruby/internal/intern/bignum.h +core_ext.o: $(hdrdir)/ruby/internal/intern/class.h +core_ext.o: $(hdrdir)/ruby/internal/intern/compar.h +core_ext.o: $(hdrdir)/ruby/internal/intern/complex.h +core_ext.o: $(hdrdir)/ruby/internal/intern/cont.h +core_ext.o: $(hdrdir)/ruby/internal/intern/dir.h +core_ext.o: $(hdrdir)/ruby/internal/intern/enum.h +core_ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h +core_ext.o: $(hdrdir)/ruby/internal/intern/error.h +core_ext.o: $(hdrdir)/ruby/internal/intern/eval.h +core_ext.o: $(hdrdir)/ruby/internal/intern/file.h +core_ext.o: $(hdrdir)/ruby/internal/intern/gc.h +core_ext.o: $(hdrdir)/ruby/internal/intern/hash.h +core_ext.o: $(hdrdir)/ruby/internal/intern/io.h +core_ext.o: $(hdrdir)/ruby/internal/intern/load.h +core_ext.o: $(hdrdir)/ruby/internal/intern/marshal.h +core_ext.o: $(hdrdir)/ruby/internal/intern/numeric.h +core_ext.o: $(hdrdir)/ruby/internal/intern/object.h +core_ext.o: $(hdrdir)/ruby/internal/intern/parse.h +core_ext.o: $(hdrdir)/ruby/internal/intern/proc.h +core_ext.o: $(hdrdir)/ruby/internal/intern/process.h +core_ext.o: $(hdrdir)/ruby/internal/intern/random.h +core_ext.o: $(hdrdir)/ruby/internal/intern/range.h +core_ext.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +core_ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h +core_ext.o: $(hdrdir)/ruby/internal/intern/string.h +core_ext.o: $(hdrdir)/ruby/internal/intern/struct.h +core_ext.o: $(hdrdir)/ruby/internal/intern/thread.h +core_ext.o: $(hdrdir)/ruby/internal/intern/time.h +core_ext.o: $(hdrdir)/ruby/internal/intern/variable.h +core_ext.o: $(hdrdir)/ruby/internal/intern/vm.h +core_ext.o: $(hdrdir)/ruby/internal/interpreter.h +core_ext.o: $(hdrdir)/ruby/internal/iterator.h +core_ext.o: $(hdrdir)/ruby/internal/memory.h +core_ext.o: $(hdrdir)/ruby/internal/method.h +core_ext.o: $(hdrdir)/ruby/internal/module.h +core_ext.o: $(hdrdir)/ruby/internal/newobj.h +core_ext.o: $(hdrdir)/ruby/internal/rgengc.h +core_ext.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +core_ext.o: $(hdrdir)/ruby/internal/value.h +core_ext.o: $(hdrdir)/ruby/internal/value_type.h +core_ext.o: $(hdrdir)/ruby/internal/variable.h +core_ext.o: $(hdrdir)/ruby/internal/warning_push.h +core_ext.o: $(hdrdir)/ruby/internal/xmalloc.h core_ext.o: $(hdrdir)/ruby/missing.h core_ext.o: $(hdrdir)/ruby/ruby.h core_ext.o: $(hdrdir)/ruby/st.h core_ext.o: $(hdrdir)/ruby/subst.h -core_ext.o: $(top_srcdir)/internal.h +core_ext.o: $(top_srcdir)/internal/bignum.h +core_ext.o: $(top_srcdir)/internal/bits.h +core_ext.o: $(top_srcdir)/internal/compilers.h +core_ext.o: $(top_srcdir)/internal/fixnum.h +core_ext.o: $(top_srcdir)/internal/numeric.h +core_ext.o: $(top_srcdir)/internal/serial.h +core_ext.o: $(top_srcdir)/internal/static_assert.h +core_ext.o: $(top_srcdir)/internal/vm.h core_ext.o: core_ext.c 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/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/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/gc.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/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/rgengc.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/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 @@ -29,8 +330,155 @@ my_integer.o: $(arch_hdrdir)/ruby/config.h my_integer.o: $(hdrdir)/ruby.h my_integer.o: $(hdrdir)/ruby/assert.h my_integer.o: $(hdrdir)/ruby/backward.h +my_integer.o: $(hdrdir)/ruby/backward/2/assume.h +my_integer.o: $(hdrdir)/ruby/backward/2/attributes.h +my_integer.o: $(hdrdir)/ruby/backward/2/bool.h +my_integer.o: $(hdrdir)/ruby/backward/2/inttypes.h +my_integer.o: $(hdrdir)/ruby/backward/2/limits.h +my_integer.o: $(hdrdir)/ruby/backward/2/long_long.h +my_integer.o: $(hdrdir)/ruby/backward/2/stdalign.h +my_integer.o: $(hdrdir)/ruby/backward/2/stdarg.h my_integer.o: $(hdrdir)/ruby/defines.h my_integer.o: $(hdrdir)/ruby/intern.h +my_integer.o: $(hdrdir)/ruby/internal/anyargs.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/char.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/double.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/int.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/short.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +my_integer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +my_integer.o: $(hdrdir)/ruby/internal/assume.h +my_integer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +my_integer.o: $(hdrdir)/ruby/internal/attr/artificial.h +my_integer.o: $(hdrdir)/ruby/internal/attr/cold.h +my_integer.o: $(hdrdir)/ruby/internal/attr/const.h +my_integer.o: $(hdrdir)/ruby/internal/attr/constexpr.h +my_integer.o: $(hdrdir)/ruby/internal/attr/deprecated.h +my_integer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +my_integer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +my_integer.o: $(hdrdir)/ruby/internal/attr/error.h +my_integer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +my_integer.o: $(hdrdir)/ruby/internal/attr/forceinline.h +my_integer.o: $(hdrdir)/ruby/internal/attr/format.h +my_integer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +my_integer.o: $(hdrdir)/ruby/internal/attr/noalias.h +my_integer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +my_integer.o: $(hdrdir)/ruby/internal/attr/noexcept.h +my_integer.o: $(hdrdir)/ruby/internal/attr/noinline.h +my_integer.o: $(hdrdir)/ruby/internal/attr/nonnull.h +my_integer.o: $(hdrdir)/ruby/internal/attr/noreturn.h +my_integer.o: $(hdrdir)/ruby/internal/attr/pure.h +my_integer.o: $(hdrdir)/ruby/internal/attr/restrict.h +my_integer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +my_integer.o: $(hdrdir)/ruby/internal/attr/warning.h +my_integer.o: $(hdrdir)/ruby/internal/attr/weakref.h +my_integer.o: $(hdrdir)/ruby/internal/cast.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +my_integer.o: $(hdrdir)/ruby/internal/compiler_since.h +my_integer.o: $(hdrdir)/ruby/internal/config.h +my_integer.o: $(hdrdir)/ruby/internal/constant_p.h +my_integer.o: $(hdrdir)/ruby/internal/core.h +my_integer.o: $(hdrdir)/ruby/internal/core/rarray.h +my_integer.o: $(hdrdir)/ruby/internal/core/rbasic.h +my_integer.o: $(hdrdir)/ruby/internal/core/rbignum.h +my_integer.o: $(hdrdir)/ruby/internal/core/rclass.h +my_integer.o: $(hdrdir)/ruby/internal/core/rdata.h +my_integer.o: $(hdrdir)/ruby/internal/core/rfile.h +my_integer.o: $(hdrdir)/ruby/internal/core/rhash.h +my_integer.o: $(hdrdir)/ruby/internal/core/robject.h +my_integer.o: $(hdrdir)/ruby/internal/core/rregexp.h +my_integer.o: $(hdrdir)/ruby/internal/core/rstring.h +my_integer.o: $(hdrdir)/ruby/internal/core/rstruct.h +my_integer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +my_integer.o: $(hdrdir)/ruby/internal/ctype.h +my_integer.o: $(hdrdir)/ruby/internal/dllexport.h +my_integer.o: $(hdrdir)/ruby/internal/dosish.h +my_integer.o: $(hdrdir)/ruby/internal/error.h +my_integer.o: $(hdrdir)/ruby/internal/eval.h +my_integer.o: $(hdrdir)/ruby/internal/event.h +my_integer.o: $(hdrdir)/ruby/internal/fl_type.h +my_integer.o: $(hdrdir)/ruby/internal/gc.h +my_integer.o: $(hdrdir)/ruby/internal/glob.h +my_integer.o: $(hdrdir)/ruby/internal/globals.h +my_integer.o: $(hdrdir)/ruby/internal/has/attribute.h +my_integer.o: $(hdrdir)/ruby/internal/has/builtin.h +my_integer.o: $(hdrdir)/ruby/internal/has/c_attribute.h +my_integer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +my_integer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +my_integer.o: $(hdrdir)/ruby/internal/has/extension.h +my_integer.o: $(hdrdir)/ruby/internal/has/feature.h +my_integer.o: $(hdrdir)/ruby/internal/has/warning.h +my_integer.o: $(hdrdir)/ruby/internal/intern/array.h +my_integer.o: $(hdrdir)/ruby/internal/intern/bignum.h +my_integer.o: $(hdrdir)/ruby/internal/intern/class.h +my_integer.o: $(hdrdir)/ruby/internal/intern/compar.h +my_integer.o: $(hdrdir)/ruby/internal/intern/complex.h +my_integer.o: $(hdrdir)/ruby/internal/intern/cont.h +my_integer.o: $(hdrdir)/ruby/internal/intern/dir.h +my_integer.o: $(hdrdir)/ruby/internal/intern/enum.h +my_integer.o: $(hdrdir)/ruby/internal/intern/enumerator.h +my_integer.o: $(hdrdir)/ruby/internal/intern/error.h +my_integer.o: $(hdrdir)/ruby/internal/intern/eval.h +my_integer.o: $(hdrdir)/ruby/internal/intern/file.h +my_integer.o: $(hdrdir)/ruby/internal/intern/gc.h +my_integer.o: $(hdrdir)/ruby/internal/intern/hash.h +my_integer.o: $(hdrdir)/ruby/internal/intern/io.h +my_integer.o: $(hdrdir)/ruby/internal/intern/load.h +my_integer.o: $(hdrdir)/ruby/internal/intern/marshal.h +my_integer.o: $(hdrdir)/ruby/internal/intern/numeric.h +my_integer.o: $(hdrdir)/ruby/internal/intern/object.h +my_integer.o: $(hdrdir)/ruby/internal/intern/parse.h +my_integer.o: $(hdrdir)/ruby/internal/intern/proc.h +my_integer.o: $(hdrdir)/ruby/internal/intern/process.h +my_integer.o: $(hdrdir)/ruby/internal/intern/random.h +my_integer.o: $(hdrdir)/ruby/internal/intern/range.h +my_integer.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +my_integer.o: $(hdrdir)/ruby/internal/intern/sprintf.h +my_integer.o: $(hdrdir)/ruby/internal/intern/string.h +my_integer.o: $(hdrdir)/ruby/internal/intern/struct.h +my_integer.o: $(hdrdir)/ruby/internal/intern/thread.h +my_integer.o: $(hdrdir)/ruby/internal/intern/time.h +my_integer.o: $(hdrdir)/ruby/internal/intern/variable.h +my_integer.o: $(hdrdir)/ruby/internal/intern/vm.h +my_integer.o: $(hdrdir)/ruby/internal/interpreter.h +my_integer.o: $(hdrdir)/ruby/internal/iterator.h +my_integer.o: $(hdrdir)/ruby/internal/memory.h +my_integer.o: $(hdrdir)/ruby/internal/method.h +my_integer.o: $(hdrdir)/ruby/internal/module.h +my_integer.o: $(hdrdir)/ruby/internal/newobj.h +my_integer.o: $(hdrdir)/ruby/internal/rgengc.h +my_integer.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +my_integer.o: $(hdrdir)/ruby/internal/value.h +my_integer.o: $(hdrdir)/ruby/internal/value_type.h +my_integer.o: $(hdrdir)/ruby/internal/variable.h +my_integer.o: $(hdrdir)/ruby/internal/warning_push.h +my_integer.o: $(hdrdir)/ruby/internal/xmalloc.h my_integer.o: $(hdrdir)/ruby/missing.h my_integer.o: $(hdrdir)/ruby/ruby.h my_integer.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/iseq_load/depend b/ruby/ext/-test-/iseq_load/depend index ac549546e..cffd63138 100644 --- a/ruby/ext/-test-/iseq_load/depend +++ b/ruby/ext/-test-/iseq_load/depend @@ -4,8 +4,155 @@ iseq_load.o: $(arch_hdrdir)/ruby/config.h iseq_load.o: $(hdrdir)/ruby.h iseq_load.o: $(hdrdir)/ruby/assert.h iseq_load.o: $(hdrdir)/ruby/backward.h +iseq_load.o: $(hdrdir)/ruby/backward/2/assume.h +iseq_load.o: $(hdrdir)/ruby/backward/2/attributes.h +iseq_load.o: $(hdrdir)/ruby/backward/2/bool.h +iseq_load.o: $(hdrdir)/ruby/backward/2/inttypes.h +iseq_load.o: $(hdrdir)/ruby/backward/2/limits.h +iseq_load.o: $(hdrdir)/ruby/backward/2/long_long.h +iseq_load.o: $(hdrdir)/ruby/backward/2/stdalign.h +iseq_load.o: $(hdrdir)/ruby/backward/2/stdarg.h iseq_load.o: $(hdrdir)/ruby/defines.h iseq_load.o: $(hdrdir)/ruby/intern.h +iseq_load.o: $(hdrdir)/ruby/internal/anyargs.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/char.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/double.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/int.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/short.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +iseq_load.o: $(hdrdir)/ruby/internal/assume.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/artificial.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/cold.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/const.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/constexpr.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/deprecated.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/error.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/forceinline.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/format.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/noalias.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/noexcept.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/noinline.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/nonnull.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/noreturn.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/pure.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/restrict.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/warning.h +iseq_load.o: $(hdrdir)/ruby/internal/attr/weakref.h +iseq_load.o: $(hdrdir)/ruby/internal/cast.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +iseq_load.o: $(hdrdir)/ruby/internal/compiler_since.h +iseq_load.o: $(hdrdir)/ruby/internal/config.h +iseq_load.o: $(hdrdir)/ruby/internal/constant_p.h +iseq_load.o: $(hdrdir)/ruby/internal/core.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rarray.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rbasic.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rbignum.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rclass.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rdata.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rfile.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rhash.h +iseq_load.o: $(hdrdir)/ruby/internal/core/robject.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rregexp.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rstring.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rstruct.h +iseq_load.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +iseq_load.o: $(hdrdir)/ruby/internal/ctype.h +iseq_load.o: $(hdrdir)/ruby/internal/dllexport.h +iseq_load.o: $(hdrdir)/ruby/internal/dosish.h +iseq_load.o: $(hdrdir)/ruby/internal/error.h +iseq_load.o: $(hdrdir)/ruby/internal/eval.h +iseq_load.o: $(hdrdir)/ruby/internal/event.h +iseq_load.o: $(hdrdir)/ruby/internal/fl_type.h +iseq_load.o: $(hdrdir)/ruby/internal/gc.h +iseq_load.o: $(hdrdir)/ruby/internal/glob.h +iseq_load.o: $(hdrdir)/ruby/internal/globals.h +iseq_load.o: $(hdrdir)/ruby/internal/has/attribute.h +iseq_load.o: $(hdrdir)/ruby/internal/has/builtin.h +iseq_load.o: $(hdrdir)/ruby/internal/has/c_attribute.h +iseq_load.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +iseq_load.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +iseq_load.o: $(hdrdir)/ruby/internal/has/extension.h +iseq_load.o: $(hdrdir)/ruby/internal/has/feature.h +iseq_load.o: $(hdrdir)/ruby/internal/has/warning.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/array.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/bignum.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/class.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/compar.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/complex.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/cont.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/dir.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/enum.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/enumerator.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/error.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/eval.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/file.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/gc.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/hash.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/io.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/load.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/marshal.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/numeric.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/object.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/parse.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/proc.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/process.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/random.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/range.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/sprintf.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/string.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/struct.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/thread.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/time.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/variable.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/vm.h +iseq_load.o: $(hdrdir)/ruby/internal/interpreter.h +iseq_load.o: $(hdrdir)/ruby/internal/iterator.h +iseq_load.o: $(hdrdir)/ruby/internal/memory.h +iseq_load.o: $(hdrdir)/ruby/internal/method.h +iseq_load.o: $(hdrdir)/ruby/internal/module.h +iseq_load.o: $(hdrdir)/ruby/internal/newobj.h +iseq_load.o: $(hdrdir)/ruby/internal/rgengc.h +iseq_load.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +iseq_load.o: $(hdrdir)/ruby/internal/value.h +iseq_load.o: $(hdrdir)/ruby/internal/value_type.h +iseq_load.o: $(hdrdir)/ruby/internal/variable.h +iseq_load.o: $(hdrdir)/ruby/internal/warning_push.h +iseq_load.o: $(hdrdir)/ruby/internal/xmalloc.h iseq_load.o: $(hdrdir)/ruby/missing.h iseq_load.o: $(hdrdir)/ruby/ruby.h iseq_load.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/iter/depend b/ruby/ext/-test-/iter/depend index 5e754950c..5bda724d2 100644 --- a/ruby/ext/-test-/iter/depend +++ b/ruby/ext/-test-/iter/depend @@ -4,8 +4,155 @@ break.o: $(arch_hdrdir)/ruby/config.h break.o: $(hdrdir)/ruby.h break.o: $(hdrdir)/ruby/assert.h break.o: $(hdrdir)/ruby/backward.h +break.o: $(hdrdir)/ruby/backward/2/assume.h +break.o: $(hdrdir)/ruby/backward/2/attributes.h +break.o: $(hdrdir)/ruby/backward/2/bool.h +break.o: $(hdrdir)/ruby/backward/2/inttypes.h +break.o: $(hdrdir)/ruby/backward/2/limits.h +break.o: $(hdrdir)/ruby/backward/2/long_long.h +break.o: $(hdrdir)/ruby/backward/2/stdalign.h +break.o: $(hdrdir)/ruby/backward/2/stdarg.h break.o: $(hdrdir)/ruby/defines.h break.o: $(hdrdir)/ruby/intern.h +break.o: $(hdrdir)/ruby/internal/anyargs.h +break.o: $(hdrdir)/ruby/internal/arithmetic.h +break.o: $(hdrdir)/ruby/internal/arithmetic/char.h +break.o: $(hdrdir)/ruby/internal/arithmetic/double.h +break.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +break.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/int.h +break.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/long.h +break.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +break.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/short.h +break.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +break.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +break.o: $(hdrdir)/ruby/internal/assume.h +break.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +break.o: $(hdrdir)/ruby/internal/attr/artificial.h +break.o: $(hdrdir)/ruby/internal/attr/cold.h +break.o: $(hdrdir)/ruby/internal/attr/const.h +break.o: $(hdrdir)/ruby/internal/attr/constexpr.h +break.o: $(hdrdir)/ruby/internal/attr/deprecated.h +break.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +break.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +break.o: $(hdrdir)/ruby/internal/attr/error.h +break.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +break.o: $(hdrdir)/ruby/internal/attr/forceinline.h +break.o: $(hdrdir)/ruby/internal/attr/format.h +break.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +break.o: $(hdrdir)/ruby/internal/attr/noalias.h +break.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +break.o: $(hdrdir)/ruby/internal/attr/noexcept.h +break.o: $(hdrdir)/ruby/internal/attr/noinline.h +break.o: $(hdrdir)/ruby/internal/attr/nonnull.h +break.o: $(hdrdir)/ruby/internal/attr/noreturn.h +break.o: $(hdrdir)/ruby/internal/attr/pure.h +break.o: $(hdrdir)/ruby/internal/attr/restrict.h +break.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +break.o: $(hdrdir)/ruby/internal/attr/warning.h +break.o: $(hdrdir)/ruby/internal/attr/weakref.h +break.o: $(hdrdir)/ruby/internal/cast.h +break.o: $(hdrdir)/ruby/internal/compiler_is.h +break.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +break.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +break.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +break.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +break.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +break.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +break.o: $(hdrdir)/ruby/internal/compiler_since.h +break.o: $(hdrdir)/ruby/internal/config.h +break.o: $(hdrdir)/ruby/internal/constant_p.h +break.o: $(hdrdir)/ruby/internal/core.h +break.o: $(hdrdir)/ruby/internal/core/rarray.h +break.o: $(hdrdir)/ruby/internal/core/rbasic.h +break.o: $(hdrdir)/ruby/internal/core/rbignum.h +break.o: $(hdrdir)/ruby/internal/core/rclass.h +break.o: $(hdrdir)/ruby/internal/core/rdata.h +break.o: $(hdrdir)/ruby/internal/core/rfile.h +break.o: $(hdrdir)/ruby/internal/core/rhash.h +break.o: $(hdrdir)/ruby/internal/core/robject.h +break.o: $(hdrdir)/ruby/internal/core/rregexp.h +break.o: $(hdrdir)/ruby/internal/core/rstring.h +break.o: $(hdrdir)/ruby/internal/core/rstruct.h +break.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +break.o: $(hdrdir)/ruby/internal/ctype.h +break.o: $(hdrdir)/ruby/internal/dllexport.h +break.o: $(hdrdir)/ruby/internal/dosish.h +break.o: $(hdrdir)/ruby/internal/error.h +break.o: $(hdrdir)/ruby/internal/eval.h +break.o: $(hdrdir)/ruby/internal/event.h +break.o: $(hdrdir)/ruby/internal/fl_type.h +break.o: $(hdrdir)/ruby/internal/gc.h +break.o: $(hdrdir)/ruby/internal/glob.h +break.o: $(hdrdir)/ruby/internal/globals.h +break.o: $(hdrdir)/ruby/internal/has/attribute.h +break.o: $(hdrdir)/ruby/internal/has/builtin.h +break.o: $(hdrdir)/ruby/internal/has/c_attribute.h +break.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +break.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +break.o: $(hdrdir)/ruby/internal/has/extension.h +break.o: $(hdrdir)/ruby/internal/has/feature.h +break.o: $(hdrdir)/ruby/internal/has/warning.h +break.o: $(hdrdir)/ruby/internal/intern/array.h +break.o: $(hdrdir)/ruby/internal/intern/bignum.h +break.o: $(hdrdir)/ruby/internal/intern/class.h +break.o: $(hdrdir)/ruby/internal/intern/compar.h +break.o: $(hdrdir)/ruby/internal/intern/complex.h +break.o: $(hdrdir)/ruby/internal/intern/cont.h +break.o: $(hdrdir)/ruby/internal/intern/dir.h +break.o: $(hdrdir)/ruby/internal/intern/enum.h +break.o: $(hdrdir)/ruby/internal/intern/enumerator.h +break.o: $(hdrdir)/ruby/internal/intern/error.h +break.o: $(hdrdir)/ruby/internal/intern/eval.h +break.o: $(hdrdir)/ruby/internal/intern/file.h +break.o: $(hdrdir)/ruby/internal/intern/gc.h +break.o: $(hdrdir)/ruby/internal/intern/hash.h +break.o: $(hdrdir)/ruby/internal/intern/io.h +break.o: $(hdrdir)/ruby/internal/intern/load.h +break.o: $(hdrdir)/ruby/internal/intern/marshal.h +break.o: $(hdrdir)/ruby/internal/intern/numeric.h +break.o: $(hdrdir)/ruby/internal/intern/object.h +break.o: $(hdrdir)/ruby/internal/intern/parse.h +break.o: $(hdrdir)/ruby/internal/intern/proc.h +break.o: $(hdrdir)/ruby/internal/intern/process.h +break.o: $(hdrdir)/ruby/internal/intern/random.h +break.o: $(hdrdir)/ruby/internal/intern/range.h +break.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +break.o: $(hdrdir)/ruby/internal/intern/sprintf.h +break.o: $(hdrdir)/ruby/internal/intern/string.h +break.o: $(hdrdir)/ruby/internal/intern/struct.h +break.o: $(hdrdir)/ruby/internal/intern/thread.h +break.o: $(hdrdir)/ruby/internal/intern/time.h +break.o: $(hdrdir)/ruby/internal/intern/variable.h +break.o: $(hdrdir)/ruby/internal/intern/vm.h +break.o: $(hdrdir)/ruby/internal/interpreter.h +break.o: $(hdrdir)/ruby/internal/iterator.h +break.o: $(hdrdir)/ruby/internal/memory.h +break.o: $(hdrdir)/ruby/internal/method.h +break.o: $(hdrdir)/ruby/internal/module.h +break.o: $(hdrdir)/ruby/internal/newobj.h +break.o: $(hdrdir)/ruby/internal/rgengc.h +break.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +break.o: $(hdrdir)/ruby/internal/value.h +break.o: $(hdrdir)/ruby/internal/value_type.h +break.o: $(hdrdir)/ruby/internal/variable.h +break.o: $(hdrdir)/ruby/internal/warning_push.h +break.o: $(hdrdir)/ruby/internal/xmalloc.h break.o: $(hdrdir)/ruby/missing.h break.o: $(hdrdir)/ruby/ruby.h break.o: $(hdrdir)/ruby/st.h @@ -16,8 +163,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -28,8 +322,155 @@ yield.o: $(arch_hdrdir)/ruby/config.h yield.o: $(hdrdir)/ruby.h yield.o: $(hdrdir)/ruby/assert.h yield.o: $(hdrdir)/ruby/backward.h +yield.o: $(hdrdir)/ruby/backward/2/assume.h +yield.o: $(hdrdir)/ruby/backward/2/attributes.h +yield.o: $(hdrdir)/ruby/backward/2/bool.h +yield.o: $(hdrdir)/ruby/backward/2/inttypes.h +yield.o: $(hdrdir)/ruby/backward/2/limits.h +yield.o: $(hdrdir)/ruby/backward/2/long_long.h +yield.o: $(hdrdir)/ruby/backward/2/stdalign.h +yield.o: $(hdrdir)/ruby/backward/2/stdarg.h yield.o: $(hdrdir)/ruby/defines.h yield.o: $(hdrdir)/ruby/intern.h +yield.o: $(hdrdir)/ruby/internal/anyargs.h +yield.o: $(hdrdir)/ruby/internal/arithmetic.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/char.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/double.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/int.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/long.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/short.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +yield.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +yield.o: $(hdrdir)/ruby/internal/assume.h +yield.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +yield.o: $(hdrdir)/ruby/internal/attr/artificial.h +yield.o: $(hdrdir)/ruby/internal/attr/cold.h +yield.o: $(hdrdir)/ruby/internal/attr/const.h +yield.o: $(hdrdir)/ruby/internal/attr/constexpr.h +yield.o: $(hdrdir)/ruby/internal/attr/deprecated.h +yield.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +yield.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +yield.o: $(hdrdir)/ruby/internal/attr/error.h +yield.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +yield.o: $(hdrdir)/ruby/internal/attr/forceinline.h +yield.o: $(hdrdir)/ruby/internal/attr/format.h +yield.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +yield.o: $(hdrdir)/ruby/internal/attr/noalias.h +yield.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +yield.o: $(hdrdir)/ruby/internal/attr/noexcept.h +yield.o: $(hdrdir)/ruby/internal/attr/noinline.h +yield.o: $(hdrdir)/ruby/internal/attr/nonnull.h +yield.o: $(hdrdir)/ruby/internal/attr/noreturn.h +yield.o: $(hdrdir)/ruby/internal/attr/pure.h +yield.o: $(hdrdir)/ruby/internal/attr/restrict.h +yield.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +yield.o: $(hdrdir)/ruby/internal/attr/warning.h +yield.o: $(hdrdir)/ruby/internal/attr/weakref.h +yield.o: $(hdrdir)/ruby/internal/cast.h +yield.o: $(hdrdir)/ruby/internal/compiler_is.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +yield.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +yield.o: $(hdrdir)/ruby/internal/compiler_since.h +yield.o: $(hdrdir)/ruby/internal/config.h +yield.o: $(hdrdir)/ruby/internal/constant_p.h +yield.o: $(hdrdir)/ruby/internal/core.h +yield.o: $(hdrdir)/ruby/internal/core/rarray.h +yield.o: $(hdrdir)/ruby/internal/core/rbasic.h +yield.o: $(hdrdir)/ruby/internal/core/rbignum.h +yield.o: $(hdrdir)/ruby/internal/core/rclass.h +yield.o: $(hdrdir)/ruby/internal/core/rdata.h +yield.o: $(hdrdir)/ruby/internal/core/rfile.h +yield.o: $(hdrdir)/ruby/internal/core/rhash.h +yield.o: $(hdrdir)/ruby/internal/core/robject.h +yield.o: $(hdrdir)/ruby/internal/core/rregexp.h +yield.o: $(hdrdir)/ruby/internal/core/rstring.h +yield.o: $(hdrdir)/ruby/internal/core/rstruct.h +yield.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +yield.o: $(hdrdir)/ruby/internal/ctype.h +yield.o: $(hdrdir)/ruby/internal/dllexport.h +yield.o: $(hdrdir)/ruby/internal/dosish.h +yield.o: $(hdrdir)/ruby/internal/error.h +yield.o: $(hdrdir)/ruby/internal/eval.h +yield.o: $(hdrdir)/ruby/internal/event.h +yield.o: $(hdrdir)/ruby/internal/fl_type.h +yield.o: $(hdrdir)/ruby/internal/gc.h +yield.o: $(hdrdir)/ruby/internal/glob.h +yield.o: $(hdrdir)/ruby/internal/globals.h +yield.o: $(hdrdir)/ruby/internal/has/attribute.h +yield.o: $(hdrdir)/ruby/internal/has/builtin.h +yield.o: $(hdrdir)/ruby/internal/has/c_attribute.h +yield.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +yield.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +yield.o: $(hdrdir)/ruby/internal/has/extension.h +yield.o: $(hdrdir)/ruby/internal/has/feature.h +yield.o: $(hdrdir)/ruby/internal/has/warning.h +yield.o: $(hdrdir)/ruby/internal/intern/array.h +yield.o: $(hdrdir)/ruby/internal/intern/bignum.h +yield.o: $(hdrdir)/ruby/internal/intern/class.h +yield.o: $(hdrdir)/ruby/internal/intern/compar.h +yield.o: $(hdrdir)/ruby/internal/intern/complex.h +yield.o: $(hdrdir)/ruby/internal/intern/cont.h +yield.o: $(hdrdir)/ruby/internal/intern/dir.h +yield.o: $(hdrdir)/ruby/internal/intern/enum.h +yield.o: $(hdrdir)/ruby/internal/intern/enumerator.h +yield.o: $(hdrdir)/ruby/internal/intern/error.h +yield.o: $(hdrdir)/ruby/internal/intern/eval.h +yield.o: $(hdrdir)/ruby/internal/intern/file.h +yield.o: $(hdrdir)/ruby/internal/intern/gc.h +yield.o: $(hdrdir)/ruby/internal/intern/hash.h +yield.o: $(hdrdir)/ruby/internal/intern/io.h +yield.o: $(hdrdir)/ruby/internal/intern/load.h +yield.o: $(hdrdir)/ruby/internal/intern/marshal.h +yield.o: $(hdrdir)/ruby/internal/intern/numeric.h +yield.o: $(hdrdir)/ruby/internal/intern/object.h +yield.o: $(hdrdir)/ruby/internal/intern/parse.h +yield.o: $(hdrdir)/ruby/internal/intern/proc.h +yield.o: $(hdrdir)/ruby/internal/intern/process.h +yield.o: $(hdrdir)/ruby/internal/intern/random.h +yield.o: $(hdrdir)/ruby/internal/intern/range.h +yield.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +yield.o: $(hdrdir)/ruby/internal/intern/sprintf.h +yield.o: $(hdrdir)/ruby/internal/intern/string.h +yield.o: $(hdrdir)/ruby/internal/intern/struct.h +yield.o: $(hdrdir)/ruby/internal/intern/thread.h +yield.o: $(hdrdir)/ruby/internal/intern/time.h +yield.o: $(hdrdir)/ruby/internal/intern/variable.h +yield.o: $(hdrdir)/ruby/internal/intern/vm.h +yield.o: $(hdrdir)/ruby/internal/interpreter.h +yield.o: $(hdrdir)/ruby/internal/iterator.h +yield.o: $(hdrdir)/ruby/internal/memory.h +yield.o: $(hdrdir)/ruby/internal/method.h +yield.o: $(hdrdir)/ruby/internal/module.h +yield.o: $(hdrdir)/ruby/internal/newobj.h +yield.o: $(hdrdir)/ruby/internal/rgengc.h +yield.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +yield.o: $(hdrdir)/ruby/internal/value.h +yield.o: $(hdrdir)/ruby/internal/value_type.h +yield.o: $(hdrdir)/ruby/internal/variable.h +yield.o: $(hdrdir)/ruby/internal/warning_push.h +yield.o: $(hdrdir)/ruby/internal/xmalloc.h yield.o: $(hdrdir)/ruby/missing.h yield.o: $(hdrdir)/ruby/ruby.h yield.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/load/protect/depend b/ruby/ext/-test-/load/protect/depend index b62393f1c..43413b4e9 100644 --- a/ruby/ext/-test-/load/protect/depend +++ b/ruby/ext/-test-/load/protect/depend @@ -4,8 +4,155 @@ protect.o: $(arch_hdrdir)/ruby/config.h protect.o: $(hdrdir)/ruby.h protect.o: $(hdrdir)/ruby/assert.h protect.o: $(hdrdir)/ruby/backward.h +protect.o: $(hdrdir)/ruby/backward/2/assume.h +protect.o: $(hdrdir)/ruby/backward/2/attributes.h +protect.o: $(hdrdir)/ruby/backward/2/bool.h +protect.o: $(hdrdir)/ruby/backward/2/inttypes.h +protect.o: $(hdrdir)/ruby/backward/2/limits.h +protect.o: $(hdrdir)/ruby/backward/2/long_long.h +protect.o: $(hdrdir)/ruby/backward/2/stdalign.h +protect.o: $(hdrdir)/ruby/backward/2/stdarg.h protect.o: $(hdrdir)/ruby/defines.h protect.o: $(hdrdir)/ruby/intern.h +protect.o: $(hdrdir)/ruby/internal/anyargs.h +protect.o: $(hdrdir)/ruby/internal/arithmetic.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/char.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/double.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/int.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/long.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/short.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +protect.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +protect.o: $(hdrdir)/ruby/internal/assume.h +protect.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +protect.o: $(hdrdir)/ruby/internal/attr/artificial.h +protect.o: $(hdrdir)/ruby/internal/attr/cold.h +protect.o: $(hdrdir)/ruby/internal/attr/const.h +protect.o: $(hdrdir)/ruby/internal/attr/constexpr.h +protect.o: $(hdrdir)/ruby/internal/attr/deprecated.h +protect.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +protect.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +protect.o: $(hdrdir)/ruby/internal/attr/error.h +protect.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +protect.o: $(hdrdir)/ruby/internal/attr/forceinline.h +protect.o: $(hdrdir)/ruby/internal/attr/format.h +protect.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +protect.o: $(hdrdir)/ruby/internal/attr/noalias.h +protect.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +protect.o: $(hdrdir)/ruby/internal/attr/noexcept.h +protect.o: $(hdrdir)/ruby/internal/attr/noinline.h +protect.o: $(hdrdir)/ruby/internal/attr/nonnull.h +protect.o: $(hdrdir)/ruby/internal/attr/noreturn.h +protect.o: $(hdrdir)/ruby/internal/attr/pure.h +protect.o: $(hdrdir)/ruby/internal/attr/restrict.h +protect.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +protect.o: $(hdrdir)/ruby/internal/attr/warning.h +protect.o: $(hdrdir)/ruby/internal/attr/weakref.h +protect.o: $(hdrdir)/ruby/internal/cast.h +protect.o: $(hdrdir)/ruby/internal/compiler_is.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +protect.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +protect.o: $(hdrdir)/ruby/internal/compiler_since.h +protect.o: $(hdrdir)/ruby/internal/config.h +protect.o: $(hdrdir)/ruby/internal/constant_p.h +protect.o: $(hdrdir)/ruby/internal/core.h +protect.o: $(hdrdir)/ruby/internal/core/rarray.h +protect.o: $(hdrdir)/ruby/internal/core/rbasic.h +protect.o: $(hdrdir)/ruby/internal/core/rbignum.h +protect.o: $(hdrdir)/ruby/internal/core/rclass.h +protect.o: $(hdrdir)/ruby/internal/core/rdata.h +protect.o: $(hdrdir)/ruby/internal/core/rfile.h +protect.o: $(hdrdir)/ruby/internal/core/rhash.h +protect.o: $(hdrdir)/ruby/internal/core/robject.h +protect.o: $(hdrdir)/ruby/internal/core/rregexp.h +protect.o: $(hdrdir)/ruby/internal/core/rstring.h +protect.o: $(hdrdir)/ruby/internal/core/rstruct.h +protect.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +protect.o: $(hdrdir)/ruby/internal/ctype.h +protect.o: $(hdrdir)/ruby/internal/dllexport.h +protect.o: $(hdrdir)/ruby/internal/dosish.h +protect.o: $(hdrdir)/ruby/internal/error.h +protect.o: $(hdrdir)/ruby/internal/eval.h +protect.o: $(hdrdir)/ruby/internal/event.h +protect.o: $(hdrdir)/ruby/internal/fl_type.h +protect.o: $(hdrdir)/ruby/internal/gc.h +protect.o: $(hdrdir)/ruby/internal/glob.h +protect.o: $(hdrdir)/ruby/internal/globals.h +protect.o: $(hdrdir)/ruby/internal/has/attribute.h +protect.o: $(hdrdir)/ruby/internal/has/builtin.h +protect.o: $(hdrdir)/ruby/internal/has/c_attribute.h +protect.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +protect.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +protect.o: $(hdrdir)/ruby/internal/has/extension.h +protect.o: $(hdrdir)/ruby/internal/has/feature.h +protect.o: $(hdrdir)/ruby/internal/has/warning.h +protect.o: $(hdrdir)/ruby/internal/intern/array.h +protect.o: $(hdrdir)/ruby/internal/intern/bignum.h +protect.o: $(hdrdir)/ruby/internal/intern/class.h +protect.o: $(hdrdir)/ruby/internal/intern/compar.h +protect.o: $(hdrdir)/ruby/internal/intern/complex.h +protect.o: $(hdrdir)/ruby/internal/intern/cont.h +protect.o: $(hdrdir)/ruby/internal/intern/dir.h +protect.o: $(hdrdir)/ruby/internal/intern/enum.h +protect.o: $(hdrdir)/ruby/internal/intern/enumerator.h +protect.o: $(hdrdir)/ruby/internal/intern/error.h +protect.o: $(hdrdir)/ruby/internal/intern/eval.h +protect.o: $(hdrdir)/ruby/internal/intern/file.h +protect.o: $(hdrdir)/ruby/internal/intern/gc.h +protect.o: $(hdrdir)/ruby/internal/intern/hash.h +protect.o: $(hdrdir)/ruby/internal/intern/io.h +protect.o: $(hdrdir)/ruby/internal/intern/load.h +protect.o: $(hdrdir)/ruby/internal/intern/marshal.h +protect.o: $(hdrdir)/ruby/internal/intern/numeric.h +protect.o: $(hdrdir)/ruby/internal/intern/object.h +protect.o: $(hdrdir)/ruby/internal/intern/parse.h +protect.o: $(hdrdir)/ruby/internal/intern/proc.h +protect.o: $(hdrdir)/ruby/internal/intern/process.h +protect.o: $(hdrdir)/ruby/internal/intern/random.h +protect.o: $(hdrdir)/ruby/internal/intern/range.h +protect.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +protect.o: $(hdrdir)/ruby/internal/intern/sprintf.h +protect.o: $(hdrdir)/ruby/internal/intern/string.h +protect.o: $(hdrdir)/ruby/internal/intern/struct.h +protect.o: $(hdrdir)/ruby/internal/intern/thread.h +protect.o: $(hdrdir)/ruby/internal/intern/time.h +protect.o: $(hdrdir)/ruby/internal/intern/variable.h +protect.o: $(hdrdir)/ruby/internal/intern/vm.h +protect.o: $(hdrdir)/ruby/internal/interpreter.h +protect.o: $(hdrdir)/ruby/internal/iterator.h +protect.o: $(hdrdir)/ruby/internal/memory.h +protect.o: $(hdrdir)/ruby/internal/method.h +protect.o: $(hdrdir)/ruby/internal/module.h +protect.o: $(hdrdir)/ruby/internal/newobj.h +protect.o: $(hdrdir)/ruby/internal/rgengc.h +protect.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +protect.o: $(hdrdir)/ruby/internal/value.h +protect.o: $(hdrdir)/ruby/internal/value_type.h +protect.o: $(hdrdir)/ruby/internal/variable.h +protect.o: $(hdrdir)/ruby/internal/warning_push.h +protect.o: $(hdrdir)/ruby/internal/xmalloc.h protect.o: $(hdrdir)/ruby/missing.h protect.o: $(hdrdir)/ruby/ruby.h protect.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/marshal/compat/depend b/ruby/ext/-test-/marshal/compat/depend index f15950696..366fb8896 100644 --- a/ruby/ext/-test-/marshal/compat/depend +++ b/ruby/ext/-test-/marshal/compat/depend @@ -4,8 +4,155 @@ usrcompat.o: $(arch_hdrdir)/ruby/config.h usrcompat.o: $(hdrdir)/ruby.h usrcompat.o: $(hdrdir)/ruby/assert.h usrcompat.o: $(hdrdir)/ruby/backward.h +usrcompat.o: $(hdrdir)/ruby/backward/2/assume.h +usrcompat.o: $(hdrdir)/ruby/backward/2/attributes.h +usrcompat.o: $(hdrdir)/ruby/backward/2/bool.h +usrcompat.o: $(hdrdir)/ruby/backward/2/inttypes.h +usrcompat.o: $(hdrdir)/ruby/backward/2/limits.h +usrcompat.o: $(hdrdir)/ruby/backward/2/long_long.h +usrcompat.o: $(hdrdir)/ruby/backward/2/stdalign.h +usrcompat.o: $(hdrdir)/ruby/backward/2/stdarg.h usrcompat.o: $(hdrdir)/ruby/defines.h usrcompat.o: $(hdrdir)/ruby/intern.h +usrcompat.o: $(hdrdir)/ruby/internal/anyargs.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/char.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/double.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/int.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/short.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +usrcompat.o: $(hdrdir)/ruby/internal/assume.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/artificial.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/cold.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/const.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/constexpr.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/deprecated.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/error.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/forceinline.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/format.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/noalias.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/noexcept.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/noinline.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/nonnull.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/noreturn.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/pure.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/restrict.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/warning.h +usrcompat.o: $(hdrdir)/ruby/internal/attr/weakref.h +usrcompat.o: $(hdrdir)/ruby/internal/cast.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +usrcompat.o: $(hdrdir)/ruby/internal/compiler_since.h +usrcompat.o: $(hdrdir)/ruby/internal/config.h +usrcompat.o: $(hdrdir)/ruby/internal/constant_p.h +usrcompat.o: $(hdrdir)/ruby/internal/core.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rarray.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rbasic.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rbignum.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rclass.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rdata.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rfile.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rhash.h +usrcompat.o: $(hdrdir)/ruby/internal/core/robject.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rregexp.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rstring.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rstruct.h +usrcompat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +usrcompat.o: $(hdrdir)/ruby/internal/ctype.h +usrcompat.o: $(hdrdir)/ruby/internal/dllexport.h +usrcompat.o: $(hdrdir)/ruby/internal/dosish.h +usrcompat.o: $(hdrdir)/ruby/internal/error.h +usrcompat.o: $(hdrdir)/ruby/internal/eval.h +usrcompat.o: $(hdrdir)/ruby/internal/event.h +usrcompat.o: $(hdrdir)/ruby/internal/fl_type.h +usrcompat.o: $(hdrdir)/ruby/internal/gc.h +usrcompat.o: $(hdrdir)/ruby/internal/glob.h +usrcompat.o: $(hdrdir)/ruby/internal/globals.h +usrcompat.o: $(hdrdir)/ruby/internal/has/attribute.h +usrcompat.o: $(hdrdir)/ruby/internal/has/builtin.h +usrcompat.o: $(hdrdir)/ruby/internal/has/c_attribute.h +usrcompat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +usrcompat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +usrcompat.o: $(hdrdir)/ruby/internal/has/extension.h +usrcompat.o: $(hdrdir)/ruby/internal/has/feature.h +usrcompat.o: $(hdrdir)/ruby/internal/has/warning.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/array.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/bignum.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/class.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/compar.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/complex.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/cont.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/dir.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/enum.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/enumerator.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/error.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/eval.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/file.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/gc.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/hash.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/io.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/load.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/marshal.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/numeric.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/object.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/parse.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/proc.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/process.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/random.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/range.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/sprintf.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/string.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/struct.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/thread.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/time.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/variable.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/vm.h +usrcompat.o: $(hdrdir)/ruby/internal/interpreter.h +usrcompat.o: $(hdrdir)/ruby/internal/iterator.h +usrcompat.o: $(hdrdir)/ruby/internal/memory.h +usrcompat.o: $(hdrdir)/ruby/internal/method.h +usrcompat.o: $(hdrdir)/ruby/internal/module.h +usrcompat.o: $(hdrdir)/ruby/internal/newobj.h +usrcompat.o: $(hdrdir)/ruby/internal/rgengc.h +usrcompat.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +usrcompat.o: $(hdrdir)/ruby/internal/value.h +usrcompat.o: $(hdrdir)/ruby/internal/value_type.h +usrcompat.o: $(hdrdir)/ruby/internal/variable.h +usrcompat.o: $(hdrdir)/ruby/internal/warning_push.h +usrcompat.o: $(hdrdir)/ruby/internal/xmalloc.h usrcompat.o: $(hdrdir)/ruby/missing.h usrcompat.o: $(hdrdir)/ruby/ruby.h usrcompat.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/marshal/internal_ivar/depend b/ruby/ext/-test-/marshal/internal_ivar/depend index f280347c0..b90f9b257 100644 --- a/ruby/ext/-test-/marshal/internal_ivar/depend +++ b/ruby/ext/-test-/marshal/internal_ivar/depend @@ -4,8 +4,155 @@ internal_ivar.o: $(arch_hdrdir)/ruby/config.h internal_ivar.o: $(hdrdir)/ruby.h internal_ivar.o: $(hdrdir)/ruby/assert.h internal_ivar.o: $(hdrdir)/ruby/backward.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/assume.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/attributes.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/bool.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/inttypes.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/limits.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/long_long.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/stdalign.h +internal_ivar.o: $(hdrdir)/ruby/backward/2/stdarg.h internal_ivar.o: $(hdrdir)/ruby/defines.h internal_ivar.o: $(hdrdir)/ruby/intern.h +internal_ivar.o: $(hdrdir)/ruby/internal/anyargs.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/char.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/double.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/int.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/short.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +internal_ivar.o: $(hdrdir)/ruby/internal/assume.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/artificial.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/cold.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/const.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/constexpr.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/deprecated.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/error.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/forceinline.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/format.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/noalias.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/noexcept.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/noinline.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/nonnull.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/noreturn.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/pure.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/restrict.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/warning.h +internal_ivar.o: $(hdrdir)/ruby/internal/attr/weakref.h +internal_ivar.o: $(hdrdir)/ruby/internal/cast.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +internal_ivar.o: $(hdrdir)/ruby/internal/compiler_since.h +internal_ivar.o: $(hdrdir)/ruby/internal/config.h +internal_ivar.o: $(hdrdir)/ruby/internal/constant_p.h +internal_ivar.o: $(hdrdir)/ruby/internal/core.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rarray.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rbasic.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rbignum.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rclass.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rdata.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rfile.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rhash.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/robject.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rregexp.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rstring.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rstruct.h +internal_ivar.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +internal_ivar.o: $(hdrdir)/ruby/internal/ctype.h +internal_ivar.o: $(hdrdir)/ruby/internal/dllexport.h +internal_ivar.o: $(hdrdir)/ruby/internal/dosish.h +internal_ivar.o: $(hdrdir)/ruby/internal/error.h +internal_ivar.o: $(hdrdir)/ruby/internal/eval.h +internal_ivar.o: $(hdrdir)/ruby/internal/event.h +internal_ivar.o: $(hdrdir)/ruby/internal/fl_type.h +internal_ivar.o: $(hdrdir)/ruby/internal/gc.h +internal_ivar.o: $(hdrdir)/ruby/internal/glob.h +internal_ivar.o: $(hdrdir)/ruby/internal/globals.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/attribute.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/builtin.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/c_attribute.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/extension.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/feature.h +internal_ivar.o: $(hdrdir)/ruby/internal/has/warning.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/array.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/bignum.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/class.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/compar.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/complex.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/cont.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/dir.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/enum.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/enumerator.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/error.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/eval.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/file.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/gc.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/hash.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/io.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/load.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/marshal.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/numeric.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/object.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/parse.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/proc.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/process.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/random.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/range.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/sprintf.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/string.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/struct.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/thread.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/time.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/variable.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/vm.h +internal_ivar.o: $(hdrdir)/ruby/internal/interpreter.h +internal_ivar.o: $(hdrdir)/ruby/internal/iterator.h +internal_ivar.o: $(hdrdir)/ruby/internal/memory.h +internal_ivar.o: $(hdrdir)/ruby/internal/method.h +internal_ivar.o: $(hdrdir)/ruby/internal/module.h +internal_ivar.o: $(hdrdir)/ruby/internal/newobj.h +internal_ivar.o: $(hdrdir)/ruby/internal/rgengc.h +internal_ivar.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +internal_ivar.o: $(hdrdir)/ruby/internal/value.h +internal_ivar.o: $(hdrdir)/ruby/internal/value_type.h +internal_ivar.o: $(hdrdir)/ruby/internal/variable.h +internal_ivar.o: $(hdrdir)/ruby/internal/warning_push.h +internal_ivar.o: $(hdrdir)/ruby/internal/xmalloc.h internal_ivar.o: $(hdrdir)/ruby/missing.h internal_ivar.o: $(hdrdir)/ruby/ruby.h internal_ivar.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/marshal/usr/depend b/ruby/ext/-test-/marshal/usr/depend index 21c0c2d74..4a01f2d5e 100644 --- a/ruby/ext/-test-/marshal/usr/depend +++ b/ruby/ext/-test-/marshal/usr/depend @@ -4,8 +4,155 @@ usrmarshal.o: $(arch_hdrdir)/ruby/config.h usrmarshal.o: $(hdrdir)/ruby.h usrmarshal.o: $(hdrdir)/ruby/assert.h usrmarshal.o: $(hdrdir)/ruby/backward.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/assume.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/attributes.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/bool.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/inttypes.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/limits.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/long_long.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/stdalign.h +usrmarshal.o: $(hdrdir)/ruby/backward/2/stdarg.h usrmarshal.o: $(hdrdir)/ruby/defines.h usrmarshal.o: $(hdrdir)/ruby/intern.h +usrmarshal.o: $(hdrdir)/ruby/internal/anyargs.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/char.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/double.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/int.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/short.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +usrmarshal.o: $(hdrdir)/ruby/internal/assume.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/artificial.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/cold.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/const.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/constexpr.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/deprecated.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/error.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/forceinline.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/format.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/noalias.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/noexcept.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/noinline.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/nonnull.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/noreturn.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/pure.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/restrict.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/warning.h +usrmarshal.o: $(hdrdir)/ruby/internal/attr/weakref.h +usrmarshal.o: $(hdrdir)/ruby/internal/cast.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +usrmarshal.o: $(hdrdir)/ruby/internal/compiler_since.h +usrmarshal.o: $(hdrdir)/ruby/internal/config.h +usrmarshal.o: $(hdrdir)/ruby/internal/constant_p.h +usrmarshal.o: $(hdrdir)/ruby/internal/core.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rarray.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rbasic.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rbignum.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rclass.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rdata.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rfile.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rhash.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/robject.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rregexp.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rstring.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rstruct.h +usrmarshal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +usrmarshal.o: $(hdrdir)/ruby/internal/ctype.h +usrmarshal.o: $(hdrdir)/ruby/internal/dllexport.h +usrmarshal.o: $(hdrdir)/ruby/internal/dosish.h +usrmarshal.o: $(hdrdir)/ruby/internal/error.h +usrmarshal.o: $(hdrdir)/ruby/internal/eval.h +usrmarshal.o: $(hdrdir)/ruby/internal/event.h +usrmarshal.o: $(hdrdir)/ruby/internal/fl_type.h +usrmarshal.o: $(hdrdir)/ruby/internal/gc.h +usrmarshal.o: $(hdrdir)/ruby/internal/glob.h +usrmarshal.o: $(hdrdir)/ruby/internal/globals.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/attribute.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/builtin.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/c_attribute.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/extension.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/feature.h +usrmarshal.o: $(hdrdir)/ruby/internal/has/warning.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/array.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/bignum.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/class.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/compar.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/complex.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/cont.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/dir.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/enum.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/enumerator.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/error.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/eval.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/file.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/gc.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/hash.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/io.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/load.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/marshal.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/numeric.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/object.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/parse.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/proc.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/process.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/random.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/range.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/sprintf.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/string.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/struct.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/thread.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/time.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/variable.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/vm.h +usrmarshal.o: $(hdrdir)/ruby/internal/interpreter.h +usrmarshal.o: $(hdrdir)/ruby/internal/iterator.h +usrmarshal.o: $(hdrdir)/ruby/internal/memory.h +usrmarshal.o: $(hdrdir)/ruby/internal/method.h +usrmarshal.o: $(hdrdir)/ruby/internal/module.h +usrmarshal.o: $(hdrdir)/ruby/internal/newobj.h +usrmarshal.o: $(hdrdir)/ruby/internal/rgengc.h +usrmarshal.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +usrmarshal.o: $(hdrdir)/ruby/internal/value.h +usrmarshal.o: $(hdrdir)/ruby/internal/value_type.h +usrmarshal.o: $(hdrdir)/ruby/internal/variable.h +usrmarshal.o: $(hdrdir)/ruby/internal/warning_push.h +usrmarshal.o: $(hdrdir)/ruby/internal/xmalloc.h usrmarshal.o: $(hdrdir)/ruby/missing.h usrmarshal.o: $(hdrdir)/ruby/ruby.h usrmarshal.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/memory_status/depend b/ruby/ext/-test-/memory_status/depend index 657ef59c3..c9cc903ff 100644 --- a/ruby/ext/-test-/memory_status/depend +++ b/ruby/ext/-test-/memory_status/depend @@ -4,8 +4,155 @@ memory_status.o: $(arch_hdrdir)/ruby/config.h memory_status.o: $(hdrdir)/ruby.h memory_status.o: $(hdrdir)/ruby/assert.h memory_status.o: $(hdrdir)/ruby/backward.h +memory_status.o: $(hdrdir)/ruby/backward/2/assume.h +memory_status.o: $(hdrdir)/ruby/backward/2/attributes.h +memory_status.o: $(hdrdir)/ruby/backward/2/bool.h +memory_status.o: $(hdrdir)/ruby/backward/2/inttypes.h +memory_status.o: $(hdrdir)/ruby/backward/2/limits.h +memory_status.o: $(hdrdir)/ruby/backward/2/long_long.h +memory_status.o: $(hdrdir)/ruby/backward/2/stdalign.h +memory_status.o: $(hdrdir)/ruby/backward/2/stdarg.h memory_status.o: $(hdrdir)/ruby/defines.h memory_status.o: $(hdrdir)/ruby/intern.h +memory_status.o: $(hdrdir)/ruby/internal/anyargs.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/char.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/double.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/int.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/short.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +memory_status.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +memory_status.o: $(hdrdir)/ruby/internal/assume.h +memory_status.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +memory_status.o: $(hdrdir)/ruby/internal/attr/artificial.h +memory_status.o: $(hdrdir)/ruby/internal/attr/cold.h +memory_status.o: $(hdrdir)/ruby/internal/attr/const.h +memory_status.o: $(hdrdir)/ruby/internal/attr/constexpr.h +memory_status.o: $(hdrdir)/ruby/internal/attr/deprecated.h +memory_status.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +memory_status.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +memory_status.o: $(hdrdir)/ruby/internal/attr/error.h +memory_status.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +memory_status.o: $(hdrdir)/ruby/internal/attr/forceinline.h +memory_status.o: $(hdrdir)/ruby/internal/attr/format.h +memory_status.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +memory_status.o: $(hdrdir)/ruby/internal/attr/noalias.h +memory_status.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +memory_status.o: $(hdrdir)/ruby/internal/attr/noexcept.h +memory_status.o: $(hdrdir)/ruby/internal/attr/noinline.h +memory_status.o: $(hdrdir)/ruby/internal/attr/nonnull.h +memory_status.o: $(hdrdir)/ruby/internal/attr/noreturn.h +memory_status.o: $(hdrdir)/ruby/internal/attr/pure.h +memory_status.o: $(hdrdir)/ruby/internal/attr/restrict.h +memory_status.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +memory_status.o: $(hdrdir)/ruby/internal/attr/warning.h +memory_status.o: $(hdrdir)/ruby/internal/attr/weakref.h +memory_status.o: $(hdrdir)/ruby/internal/cast.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +memory_status.o: $(hdrdir)/ruby/internal/compiler_since.h +memory_status.o: $(hdrdir)/ruby/internal/config.h +memory_status.o: $(hdrdir)/ruby/internal/constant_p.h +memory_status.o: $(hdrdir)/ruby/internal/core.h +memory_status.o: $(hdrdir)/ruby/internal/core/rarray.h +memory_status.o: $(hdrdir)/ruby/internal/core/rbasic.h +memory_status.o: $(hdrdir)/ruby/internal/core/rbignum.h +memory_status.o: $(hdrdir)/ruby/internal/core/rclass.h +memory_status.o: $(hdrdir)/ruby/internal/core/rdata.h +memory_status.o: $(hdrdir)/ruby/internal/core/rfile.h +memory_status.o: $(hdrdir)/ruby/internal/core/rhash.h +memory_status.o: $(hdrdir)/ruby/internal/core/robject.h +memory_status.o: $(hdrdir)/ruby/internal/core/rregexp.h +memory_status.o: $(hdrdir)/ruby/internal/core/rstring.h +memory_status.o: $(hdrdir)/ruby/internal/core/rstruct.h +memory_status.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +memory_status.o: $(hdrdir)/ruby/internal/ctype.h +memory_status.o: $(hdrdir)/ruby/internal/dllexport.h +memory_status.o: $(hdrdir)/ruby/internal/dosish.h +memory_status.o: $(hdrdir)/ruby/internal/error.h +memory_status.o: $(hdrdir)/ruby/internal/eval.h +memory_status.o: $(hdrdir)/ruby/internal/event.h +memory_status.o: $(hdrdir)/ruby/internal/fl_type.h +memory_status.o: $(hdrdir)/ruby/internal/gc.h +memory_status.o: $(hdrdir)/ruby/internal/glob.h +memory_status.o: $(hdrdir)/ruby/internal/globals.h +memory_status.o: $(hdrdir)/ruby/internal/has/attribute.h +memory_status.o: $(hdrdir)/ruby/internal/has/builtin.h +memory_status.o: $(hdrdir)/ruby/internal/has/c_attribute.h +memory_status.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +memory_status.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +memory_status.o: $(hdrdir)/ruby/internal/has/extension.h +memory_status.o: $(hdrdir)/ruby/internal/has/feature.h +memory_status.o: $(hdrdir)/ruby/internal/has/warning.h +memory_status.o: $(hdrdir)/ruby/internal/intern/array.h +memory_status.o: $(hdrdir)/ruby/internal/intern/bignum.h +memory_status.o: $(hdrdir)/ruby/internal/intern/class.h +memory_status.o: $(hdrdir)/ruby/internal/intern/compar.h +memory_status.o: $(hdrdir)/ruby/internal/intern/complex.h +memory_status.o: $(hdrdir)/ruby/internal/intern/cont.h +memory_status.o: $(hdrdir)/ruby/internal/intern/dir.h +memory_status.o: $(hdrdir)/ruby/internal/intern/enum.h +memory_status.o: $(hdrdir)/ruby/internal/intern/enumerator.h +memory_status.o: $(hdrdir)/ruby/internal/intern/error.h +memory_status.o: $(hdrdir)/ruby/internal/intern/eval.h +memory_status.o: $(hdrdir)/ruby/internal/intern/file.h +memory_status.o: $(hdrdir)/ruby/internal/intern/gc.h +memory_status.o: $(hdrdir)/ruby/internal/intern/hash.h +memory_status.o: $(hdrdir)/ruby/internal/intern/io.h +memory_status.o: $(hdrdir)/ruby/internal/intern/load.h +memory_status.o: $(hdrdir)/ruby/internal/intern/marshal.h +memory_status.o: $(hdrdir)/ruby/internal/intern/numeric.h +memory_status.o: $(hdrdir)/ruby/internal/intern/object.h +memory_status.o: $(hdrdir)/ruby/internal/intern/parse.h +memory_status.o: $(hdrdir)/ruby/internal/intern/proc.h +memory_status.o: $(hdrdir)/ruby/internal/intern/process.h +memory_status.o: $(hdrdir)/ruby/internal/intern/random.h +memory_status.o: $(hdrdir)/ruby/internal/intern/range.h +memory_status.o: $(hdrdir)/ruby/internal/intern/rational.h +memory_status.o: $(hdrdir)/ruby/internal/intern/re.h +memory_status.o: $(hdrdir)/ruby/internal/intern/ruby.h +memory_status.o: $(hdrdir)/ruby/internal/intern/select.h +memory_status.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +memory_status.o: $(hdrdir)/ruby/internal/intern/signal.h +memory_status.o: $(hdrdir)/ruby/internal/intern/sprintf.h +memory_status.o: $(hdrdir)/ruby/internal/intern/string.h +memory_status.o: $(hdrdir)/ruby/internal/intern/struct.h +memory_status.o: $(hdrdir)/ruby/internal/intern/thread.h +memory_status.o: $(hdrdir)/ruby/internal/intern/time.h +memory_status.o: $(hdrdir)/ruby/internal/intern/variable.h +memory_status.o: $(hdrdir)/ruby/internal/intern/vm.h +memory_status.o: $(hdrdir)/ruby/internal/interpreter.h +memory_status.o: $(hdrdir)/ruby/internal/iterator.h +memory_status.o: $(hdrdir)/ruby/internal/memory.h +memory_status.o: $(hdrdir)/ruby/internal/method.h +memory_status.o: $(hdrdir)/ruby/internal/module.h +memory_status.o: $(hdrdir)/ruby/internal/newobj.h +memory_status.o: $(hdrdir)/ruby/internal/rgengc.h +memory_status.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +memory_status.o: $(hdrdir)/ruby/internal/value.h +memory_status.o: $(hdrdir)/ruby/internal/value_type.h +memory_status.o: $(hdrdir)/ruby/internal/variable.h +memory_status.o: $(hdrdir)/ruby/internal/warning_push.h +memory_status.o: $(hdrdir)/ruby/internal/xmalloc.h memory_status.o: $(hdrdir)/ruby/missing.h memory_status.o: $(hdrdir)/ruby/ruby.h memory_status.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/memory_status/memory_status.c b/ruby/ext/-test-/memory_status/memory_status.c index 5775fa56f..afacbee78 100644 --- a/ruby/ext/-test-/memory_status/memory_status.c +++ b/ruby/ext/-test-/memory_status/memory_status.c @@ -10,11 +10,15 @@ static VALUE cMemoryStatus; +#undef HAVE_RSS +#undef HAVE_PEAK + static VALUE read_status(VALUE self) { VALUE size = INT2FIX(0); #if defined __APPLE__ +# define HAVE_RSS 1 VALUE rss; kern_return_t error; # if defined MACH_TASK_BASIC_INFO @@ -40,14 +44,20 @@ read_status(VALUE self) rss = ULL2NUM(taskinfo.resident_size); rb_struct_aset(self, INT2FIX(1), rss); #elif defined _WIN32 - VALUE peak; +# define HAVE_RSS 1 +# define HAVE_PEAK 1 + VALUE rss, peak; PROCESS_MEMORY_COUNTERS c; c.cb = sizeof(c); if (!GetProcessMemoryInfo(GetCurrentProcess(), &c, c.cb)) return Qnil; size = SIZET2NUM(c.PagefileUsage); + rss = SIZET2NUM(c.WorkingSetSize); peak = SIZET2NUM(c.PeakWorkingSetSize); - rb_struct_aset(self, INT2FIX(1), peak); + rb_struct_aset(self, INT2FIX(2), peak); +#endif +#ifdef HAVE_RSS + rb_struct_aset(self, INT2FIX(1), rss); #endif rb_struct_aset(self, INT2FIX(0), size); return self; @@ -59,9 +69,10 @@ Init_memory_status(void) VALUE mMemory = rb_define_module("Memory"); cMemoryStatus = rb_struct_define_under(mMemory, "Status", "size", -#if defined __APPLE__ +#ifdef HAVE_RSS "rss", -#elif defined _WIN32 +#endif +#ifdef HAVE_PEAK "peak", #endif (char *)NULL); diff --git a/ruby/ext/-test-/memory_view/depend b/ruby/ext/-test-/memory_view/depend new file mode 100644 index 000000000..c42e9f54a --- /dev/null +++ b/ruby/ext/-test-/memory_view/depend @@ -0,0 +1,162 @@ +# AUTOGENERATED DEPENDENCIES START +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/intern.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/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/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/gc.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/rgengc.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/ruby.h +memory_view.o: $(hdrdir)/ruby/st.h +memory_view.o: $(hdrdir)/ruby/subst.h +memory_view.o: memory_view.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/memory_view/extconf.rb b/ruby/ext/-test-/memory_view/extconf.rb new file mode 100644 index 000000000..123b80b8d --- /dev/null +++ b/ruby/ext/-test-/memory_view/extconf.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: false +require "mkmf" + +require_relative "../auto_ext.rb" +auto_ext(inc: true) diff --git a/ruby/ext/-test-/memory_view/memory_view.c b/ruby/ext/-test-/memory_view/memory_view.c new file mode 100644 index 000000000..c1df0353c --- /dev/null +++ b/ruby/ext/-test-/memory_view/memory_view.c @@ -0,0 +1,450 @@ +#include "ruby.h" + +#ifdef HAVE_RUBY_MEMORY_VIEW_H +#include "ruby/memory_view.h" + +#define STRUCT_ALIGNOF(T, result) do { \ + (result) = RUBY_ALIGNOF(T); \ +} while(0) + +static ID id_str; +static VALUE sym_format; +static VALUE sym_native_size_p; +static VALUE sym_offset; +static VALUE sym_size; +static VALUE sym_repeat; +static VALUE sym_obj; +static VALUE sym_byte_size; +static VALUE sym_readonly; +static VALUE sym_format; +static VALUE sym_item_size; +static VALUE sym_ndim; +static VALUE sym_shape; +static VALUE sym_strides; +static VALUE sym_sub_offsets; +static VALUE sym_endianness; +static VALUE sym_little_endian; +static VALUE sym_big_endian; + +static bool +exportable_string_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) +{ + VALUE str = rb_ivar_get(obj, id_str); + rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(str), RSTRING_LEN(str), true); + return true; +} + +static bool +exportable_string_memory_view_available_p(VALUE obj) +{ + VALUE str = rb_ivar_get(obj, id_str); + return !NIL_P(str); +} + +static const rb_memory_view_entry_t exportable_string_memory_view_entry = { + exportable_string_get_memory_view, + NULL, + exportable_string_memory_view_available_p +}; + +static VALUE +memory_view_available_p(VALUE mod, VALUE obj) +{ + return rb_memory_view_available_p(obj) ? Qtrue : Qfalse; +} + +static VALUE +memory_view_register(VALUE mod, VALUE obj) +{ + return rb_memory_view_register(obj, &exportable_string_memory_view_entry) ? Qtrue : Qfalse; +} + +static VALUE +memory_view_item_size_from_format(VALUE mod, VALUE format) +{ + const char *c_str = NULL; + if (!NIL_P(format)) + c_str = StringValueCStr(format); + const char *err = NULL; + ssize_t item_size = rb_memory_view_item_size_from_format(c_str, &err); + if (!err) + return rb_assoc_new(SSIZET2NUM(item_size), Qnil); + else + return rb_assoc_new(SSIZET2NUM(item_size), rb_str_new_cstr(err)); +} + +static VALUE +memory_view_parse_item_format(VALUE mod, VALUE format) +{ + const char *c_str = NULL; + if (!NIL_P(format)) + c_str = StringValueCStr(format); + const char *err = NULL; + + rb_memory_view_item_component_t *members; + size_t n_members; + ssize_t item_size = rb_memory_view_parse_item_format(c_str, &members, &n_members, &err); + + VALUE result = rb_ary_new_capa(3); + rb_ary_push(result, SSIZET2NUM(item_size)); + + if (!err) { + VALUE ary = rb_ary_new_capa((long)n_members); + size_t i; + for (i = 0; i < n_members; ++i) { + VALUE member = rb_hash_new(); + rb_hash_aset(member, sym_format, rb_str_new(&members[i].format, 1)); + rb_hash_aset(member, sym_native_size_p, members[i].native_size_p ? Qtrue : Qfalse); + rb_hash_aset(member, sym_endianness, members[i].little_endian_p ? sym_little_endian : sym_big_endian); + rb_hash_aset(member, sym_offset, SSIZET2NUM(members[i].offset)); + rb_hash_aset(member, sym_size, SSIZET2NUM(members[i].size)); + rb_hash_aset(member, sym_repeat, SSIZET2NUM(members[i].repeat)); + rb_ary_push(ary, member); + } + xfree(members); + rb_ary_push(result, ary); + rb_ary_push(result, Qnil); + } + else { + rb_ary_push(result, Qnil); // members + rb_ary_push(result, rb_str_new_cstr(err)); + } + + return result; +} + +static VALUE +memory_view_get_memory_view_info(VALUE mod, VALUE obj) +{ + rb_memory_view_t view; + + if (!rb_memory_view_get(obj, &view, 0)) { + return Qnil; + } + + VALUE hash = rb_hash_new(); + rb_hash_aset(hash, sym_obj, view.obj); + rb_hash_aset(hash, sym_byte_size, SSIZET2NUM(view.byte_size)); + rb_hash_aset(hash, sym_readonly, view.readonly ? Qtrue : Qfalse); + rb_hash_aset(hash, sym_format, view.format ? rb_str_new_cstr(view.format) : Qnil); + rb_hash_aset(hash, sym_item_size, SSIZET2NUM(view.item_size)); + rb_hash_aset(hash, sym_ndim, SSIZET2NUM(view.ndim)); + + if (view.shape) { + VALUE shape = rb_ary_new_capa(view.ndim); + rb_hash_aset(hash, sym_shape, shape); + } + else { + rb_hash_aset(hash, sym_shape, Qnil); + } + + if (view.strides) { + VALUE strides = rb_ary_new_capa(view.ndim); + rb_hash_aset(hash, sym_strides, strides); + } + else { + rb_hash_aset(hash, sym_strides, Qnil); + } + + if (view.sub_offsets) { + VALUE sub_offsets = rb_ary_new_capa(view.ndim); + rb_hash_aset(hash, sym_sub_offsets, sub_offsets); + } + else { + rb_hash_aset(hash, sym_sub_offsets, Qnil); + } + + rb_memory_view_release(&view); + + return hash; +} + +static VALUE +memory_view_fill_contiguous_strides(VALUE mod, VALUE ndim_v, VALUE item_size_v, VALUE shape_v, VALUE row_major_p) +{ + ssize_t i, ndim = NUM2SSIZET(ndim_v); + + Check_Type(shape_v, T_ARRAY); + ssize_t *shape = ALLOC_N(ssize_t, ndim); + for (i = 0; i < ndim; ++i) { + shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i)); + } + + ssize_t *strides = ALLOC_N(ssize_t, ndim); + rb_memory_view_fill_contiguous_strides(ndim, NUM2SSIZET(item_size_v), shape, RTEST(row_major_p), strides); + + VALUE result = rb_ary_new_capa(ndim); + for (i = 0; i < ndim; ++i) { + rb_ary_push(result, SSIZET2NUM(strides[i])); + } + + xfree(strides); + xfree(shape); + + return result; +} + +static VALUE +memory_view_get_ref_count(VALUE obj) +{ + if (rb_memory_view_exported_object_registry == Qundef) { + return Qnil; + } + + st_table *table; + TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table, + &rb_memory_view_exported_object_registry_data_type, + table); + + st_data_t count; + if (st_lookup(table, (st_data_t)obj, &count)) { + return ULL2NUM(count); + } + + return Qnil; +} + +static VALUE +memory_view_ref_count_while_exporting_i(VALUE obj, long n) +{ + if (n == 0) { + return memory_view_get_ref_count(obj); + } + + rb_memory_view_t view; + if (!rb_memory_view_get(obj, &view, 0)) { + return Qnil; + } + + VALUE ref_count = memory_view_ref_count_while_exporting_i(obj, n-1); + rb_memory_view_release(&view); + + return ref_count; +} + +static VALUE +memory_view_ref_count_while_exporting(VALUE mod, VALUE obj, VALUE n) +{ + Check_Type(n, T_FIXNUM); + return memory_view_ref_count_while_exporting_i(obj, FIX2LONG(n)); +} + +static VALUE +memory_view_extract_item_members(VALUE mod, VALUE str, VALUE format) +{ + StringValue(str); + StringValue(format); + + rb_memory_view_item_component_t *members; + size_t n_members; + const char *err = NULL; + (void)rb_memory_view_parse_item_format(RSTRING_PTR(format), &members, &n_members, &err); + if (err != NULL) { + rb_raise(rb_eArgError, "Unable to parse item format"); + } + + VALUE item = rb_memory_view_extract_item_members(RSTRING_PTR(str), members, n_members); + xfree(members); + + return item; +} + +static VALUE +expstr_initialize(VALUE obj, VALUE s) +{ + if (!NIL_P(s)) { + Check_Type(s, T_STRING); + } + rb_ivar_set(obj, id_str, s); + return Qnil; +} + +static bool +mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) +{ + VALUE buf_v = rb_ivar_get(obj, id_str); + VALUE format_v = rb_ivar_get(obj, SYM2ID(sym_format)); + VALUE shape_v = rb_ivar_get(obj, SYM2ID(sym_shape)); + VALUE strides_v = rb_ivar_get(obj, SYM2ID(sym_strides)); + + const char *err; + const ssize_t item_size = rb_memory_view_item_size_from_format(RSTRING_PTR(format_v), &err); + if (item_size < 0) { + return false; + } + + ssize_t ndim = RARRAY_LEN(shape_v); + if (!NIL_P(strides_v) && RARRAY_LEN(strides_v) != ndim) { + rb_raise(rb_eArgError, "strides has an invalid dimension"); + } + + ssize_t *shape = ALLOC_N(ssize_t, ndim); + ssize_t *strides = ALLOC_N(ssize_t, ndim); + ssize_t i; + if (!NIL_P(strides_v)) { + for (i = 0; i < ndim; ++i) { + shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i)); + strides[i] = NUM2SSIZET(RARRAY_AREF(strides_v, i)); + } + } + else { + for (i = 0; i < ndim; ++i) { + shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i)); + } + + i = ndim - 1; + strides[i] = item_size; + for (; i > 0; --i) { + strides[i-1] = strides[i] * shape[i]; + } + } + + rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(buf_v), RSTRING_LEN(buf_v), true); + view->format = RSTRING_PTR(format_v); + view->item_size = item_size; + view->ndim = ndim; + view->shape = shape; + view->strides = strides; + view->sub_offsets = NULL; + + return true; +} + +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); + + return true; +} + +static bool +mdview_memory_view_available_p(VALUE obj) +{ + return true; +} + +static const rb_memory_view_entry_t mdview_memory_view_entry = { + mdview_get_memory_view, + mdview_release_memory_view, + mdview_memory_view_available_p +}; + +static VALUE +mdview_initialize(VALUE obj, VALUE buf, VALUE format, VALUE shape, VALUE strides) +{ + Check_Type(buf, T_STRING); + StringValue(format); + Check_Type(shape, T_ARRAY); + if (!NIL_P(strides)) Check_Type(strides, T_ARRAY); + + rb_ivar_set(obj, id_str, buf); + rb_ivar_set(obj, SYM2ID(sym_format), format); + rb_ivar_set(obj, SYM2ID(sym_shape), shape); + rb_ivar_set(obj, SYM2ID(sym_strides), strides); + return Qnil; +} + +static VALUE +mdview_aref(VALUE obj, VALUE indices_v) +{ + Check_Type(indices_v, T_ARRAY); + + rb_memory_view_t view; + if (!rb_memory_view_get(obj, &view, 0)) { + rb_raise(rb_eRuntimeError, "rb_memory_view_get: failed"); + } + + if (RARRAY_LEN(indices_v) != view.ndim) { + rb_raise(rb_eKeyError, "Indices has an invalid dimension"); + } + + VALUE buf_indices; + ssize_t *indices = ALLOCV_N(ssize_t, buf_indices, view.ndim); + + ssize_t i; + for (i = 0; i < view.ndim; ++i) { + indices[i] = NUM2SSIZET(RARRAY_AREF(indices_v, i)); + } + + VALUE result = rb_memory_view_get_item(&view, indices); + ALLOCV_END(buf_indices); + rb_memory_view_release(&view); + + return result; +} + +#endif /* HAVE_RUBY_MEMORY_VIEW_H */ + +void +Init_memory_view(void) +{ + rb_ext_ractor_safe(true); +#ifdef HAVE_RUBY_MEMORY_VIEW_H + VALUE mMemoryViewTestUtils = rb_define_module("MemoryViewTestUtils"); + + rb_define_module_function(mMemoryViewTestUtils, "available?", memory_view_available_p, 1); + rb_define_module_function(mMemoryViewTestUtils, "register", memory_view_register, 1); + rb_define_module_function(mMemoryViewTestUtils, "item_size_from_format", memory_view_item_size_from_format, 1); + rb_define_module_function(mMemoryViewTestUtils, "parse_item_format", memory_view_parse_item_format, 1); + rb_define_module_function(mMemoryViewTestUtils, "get_memory_view_info", memory_view_get_memory_view_info, 1); + rb_define_module_function(mMemoryViewTestUtils, "fill_contiguous_strides", memory_view_fill_contiguous_strides, 4); + rb_define_module_function(mMemoryViewTestUtils, "ref_count_while_exporting", memory_view_ref_count_while_exporting, 2); + rb_define_module_function(mMemoryViewTestUtils, "extract_item_members", memory_view_extract_item_members, 2); + + VALUE cExportableString = rb_define_class_under(mMemoryViewTestUtils, "ExportableString", rb_cObject); + rb_define_method(cExportableString, "initialize", expstr_initialize, 1); + rb_memory_view_register(cExportableString, &exportable_string_memory_view_entry); + + VALUE cMDView = rb_define_class_under(mMemoryViewTestUtils, "MultiDimensionalView", rb_cObject); + rb_define_method(cMDView, "initialize", mdview_initialize, 4); + rb_define_method(cMDView, "[]", mdview_aref, 1); + rb_memory_view_register(cMDView, &mdview_memory_view_entry); + + id_str = rb_intern_const("__str__"); + sym_format = ID2SYM(rb_intern_const("format")); + sym_native_size_p = ID2SYM(rb_intern_const("native_size_p")); + sym_offset = ID2SYM(rb_intern_const("offset")); + sym_size = ID2SYM(rb_intern_const("size")); + sym_repeat = ID2SYM(rb_intern_const("repeat")); + sym_obj = ID2SYM(rb_intern_const("obj")); + sym_byte_size = ID2SYM(rb_intern_const("byte_size")); + sym_readonly = ID2SYM(rb_intern_const("readonly")); + sym_format = ID2SYM(rb_intern_const("format")); + sym_item_size = ID2SYM(rb_intern_const("item_size")); + sym_ndim = ID2SYM(rb_intern_const("ndim")); + sym_shape = ID2SYM(rb_intern_const("shape")); + sym_strides = ID2SYM(rb_intern_const("strides")); + sym_sub_offsets = ID2SYM(rb_intern_const("sub_offsets")); + sym_endianness = ID2SYM(rb_intern_const("endianness")); + sym_little_endian = ID2SYM(rb_intern_const("little_endian")); + sym_big_endian = ID2SYM(rb_intern_const("big_endian")); + +#ifdef WORDS_BIGENDIAN + rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_big_endian); +#else + rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_little_endian); +#endif + +#define DEF_ALIGNMENT_CONST(type, TYPE) do { \ + int alignment; \ + STRUCT_ALIGNOF(type, alignment); \ + rb_const_set(mMemoryViewTestUtils, rb_intern_const(#TYPE "_ALIGNMENT"), INT2FIX(alignment)); \ +} while(0) + + DEF_ALIGNMENT_CONST(short, SHORT); + DEF_ALIGNMENT_CONST(int, INT); + DEF_ALIGNMENT_CONST(long, LONG); + DEF_ALIGNMENT_CONST(LONG_LONG, LONG_LONG); + DEF_ALIGNMENT_CONST(int16_t, INT16); + DEF_ALIGNMENT_CONST(int32_t, INT32); + DEF_ALIGNMENT_CONST(int64_t, INT64); + DEF_ALIGNMENT_CONST(intptr_t, INTPTR); + DEF_ALIGNMENT_CONST(float, FLOAT); + DEF_ALIGNMENT_CONST(double, DOUBLE); + +#undef DEF_ALIGNMENT_CONST + +#endif /* HAVE_RUBY_MEMORY_VIEW_H */ +} diff --git a/ruby/ext/-test-/method/depend b/ruby/ext/-test-/method/depend index 028d97e1a..f091d3718 100644 --- a/ruby/ext/-test-/method/depend +++ b/ruby/ext/-test-/method/depend @@ -4,8 +4,155 @@ arity.o: $(arch_hdrdir)/ruby/config.h arity.o: $(hdrdir)/ruby.h arity.o: $(hdrdir)/ruby/assert.h arity.o: $(hdrdir)/ruby/backward.h +arity.o: $(hdrdir)/ruby/backward/2/assume.h +arity.o: $(hdrdir)/ruby/backward/2/attributes.h +arity.o: $(hdrdir)/ruby/backward/2/bool.h +arity.o: $(hdrdir)/ruby/backward/2/inttypes.h +arity.o: $(hdrdir)/ruby/backward/2/limits.h +arity.o: $(hdrdir)/ruby/backward/2/long_long.h +arity.o: $(hdrdir)/ruby/backward/2/stdalign.h +arity.o: $(hdrdir)/ruby/backward/2/stdarg.h arity.o: $(hdrdir)/ruby/defines.h arity.o: $(hdrdir)/ruby/intern.h +arity.o: $(hdrdir)/ruby/internal/anyargs.h +arity.o: $(hdrdir)/ruby/internal/arithmetic.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/char.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/double.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/int.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/long.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/short.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +arity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +arity.o: $(hdrdir)/ruby/internal/assume.h +arity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +arity.o: $(hdrdir)/ruby/internal/attr/artificial.h +arity.o: $(hdrdir)/ruby/internal/attr/cold.h +arity.o: $(hdrdir)/ruby/internal/attr/const.h +arity.o: $(hdrdir)/ruby/internal/attr/constexpr.h +arity.o: $(hdrdir)/ruby/internal/attr/deprecated.h +arity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +arity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +arity.o: $(hdrdir)/ruby/internal/attr/error.h +arity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +arity.o: $(hdrdir)/ruby/internal/attr/forceinline.h +arity.o: $(hdrdir)/ruby/internal/attr/format.h +arity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +arity.o: $(hdrdir)/ruby/internal/attr/noalias.h +arity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +arity.o: $(hdrdir)/ruby/internal/attr/noexcept.h +arity.o: $(hdrdir)/ruby/internal/attr/noinline.h +arity.o: $(hdrdir)/ruby/internal/attr/nonnull.h +arity.o: $(hdrdir)/ruby/internal/attr/noreturn.h +arity.o: $(hdrdir)/ruby/internal/attr/pure.h +arity.o: $(hdrdir)/ruby/internal/attr/restrict.h +arity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +arity.o: $(hdrdir)/ruby/internal/attr/warning.h +arity.o: $(hdrdir)/ruby/internal/attr/weakref.h +arity.o: $(hdrdir)/ruby/internal/cast.h +arity.o: $(hdrdir)/ruby/internal/compiler_is.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +arity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +arity.o: $(hdrdir)/ruby/internal/compiler_since.h +arity.o: $(hdrdir)/ruby/internal/config.h +arity.o: $(hdrdir)/ruby/internal/constant_p.h +arity.o: $(hdrdir)/ruby/internal/core.h +arity.o: $(hdrdir)/ruby/internal/core/rarray.h +arity.o: $(hdrdir)/ruby/internal/core/rbasic.h +arity.o: $(hdrdir)/ruby/internal/core/rbignum.h +arity.o: $(hdrdir)/ruby/internal/core/rclass.h +arity.o: $(hdrdir)/ruby/internal/core/rdata.h +arity.o: $(hdrdir)/ruby/internal/core/rfile.h +arity.o: $(hdrdir)/ruby/internal/core/rhash.h +arity.o: $(hdrdir)/ruby/internal/core/robject.h +arity.o: $(hdrdir)/ruby/internal/core/rregexp.h +arity.o: $(hdrdir)/ruby/internal/core/rstring.h +arity.o: $(hdrdir)/ruby/internal/core/rstruct.h +arity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +arity.o: $(hdrdir)/ruby/internal/ctype.h +arity.o: $(hdrdir)/ruby/internal/dllexport.h +arity.o: $(hdrdir)/ruby/internal/dosish.h +arity.o: $(hdrdir)/ruby/internal/error.h +arity.o: $(hdrdir)/ruby/internal/eval.h +arity.o: $(hdrdir)/ruby/internal/event.h +arity.o: $(hdrdir)/ruby/internal/fl_type.h +arity.o: $(hdrdir)/ruby/internal/gc.h +arity.o: $(hdrdir)/ruby/internal/glob.h +arity.o: $(hdrdir)/ruby/internal/globals.h +arity.o: $(hdrdir)/ruby/internal/has/attribute.h +arity.o: $(hdrdir)/ruby/internal/has/builtin.h +arity.o: $(hdrdir)/ruby/internal/has/c_attribute.h +arity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +arity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +arity.o: $(hdrdir)/ruby/internal/has/extension.h +arity.o: $(hdrdir)/ruby/internal/has/feature.h +arity.o: $(hdrdir)/ruby/internal/has/warning.h +arity.o: $(hdrdir)/ruby/internal/intern/array.h +arity.o: $(hdrdir)/ruby/internal/intern/bignum.h +arity.o: $(hdrdir)/ruby/internal/intern/class.h +arity.o: $(hdrdir)/ruby/internal/intern/compar.h +arity.o: $(hdrdir)/ruby/internal/intern/complex.h +arity.o: $(hdrdir)/ruby/internal/intern/cont.h +arity.o: $(hdrdir)/ruby/internal/intern/dir.h +arity.o: $(hdrdir)/ruby/internal/intern/enum.h +arity.o: $(hdrdir)/ruby/internal/intern/enumerator.h +arity.o: $(hdrdir)/ruby/internal/intern/error.h +arity.o: $(hdrdir)/ruby/internal/intern/eval.h +arity.o: $(hdrdir)/ruby/internal/intern/file.h +arity.o: $(hdrdir)/ruby/internal/intern/gc.h +arity.o: $(hdrdir)/ruby/internal/intern/hash.h +arity.o: $(hdrdir)/ruby/internal/intern/io.h +arity.o: $(hdrdir)/ruby/internal/intern/load.h +arity.o: $(hdrdir)/ruby/internal/intern/marshal.h +arity.o: $(hdrdir)/ruby/internal/intern/numeric.h +arity.o: $(hdrdir)/ruby/internal/intern/object.h +arity.o: $(hdrdir)/ruby/internal/intern/parse.h +arity.o: $(hdrdir)/ruby/internal/intern/proc.h +arity.o: $(hdrdir)/ruby/internal/intern/process.h +arity.o: $(hdrdir)/ruby/internal/intern/random.h +arity.o: $(hdrdir)/ruby/internal/intern/range.h +arity.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +arity.o: $(hdrdir)/ruby/internal/intern/sprintf.h +arity.o: $(hdrdir)/ruby/internal/intern/string.h +arity.o: $(hdrdir)/ruby/internal/intern/struct.h +arity.o: $(hdrdir)/ruby/internal/intern/thread.h +arity.o: $(hdrdir)/ruby/internal/intern/time.h +arity.o: $(hdrdir)/ruby/internal/intern/variable.h +arity.o: $(hdrdir)/ruby/internal/intern/vm.h +arity.o: $(hdrdir)/ruby/internal/interpreter.h +arity.o: $(hdrdir)/ruby/internal/iterator.h +arity.o: $(hdrdir)/ruby/internal/memory.h +arity.o: $(hdrdir)/ruby/internal/method.h +arity.o: $(hdrdir)/ruby/internal/module.h +arity.o: $(hdrdir)/ruby/internal/newobj.h +arity.o: $(hdrdir)/ruby/internal/rgengc.h +arity.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +arity.o: $(hdrdir)/ruby/internal/value.h +arity.o: $(hdrdir)/ruby/internal/value_type.h +arity.o: $(hdrdir)/ruby/internal/variable.h +arity.o: $(hdrdir)/ruby/internal/warning_push.h +arity.o: $(hdrdir)/ruby/internal/xmalloc.h arity.o: $(hdrdir)/ruby/missing.h arity.o: $(hdrdir)/ruby/ruby.h arity.o: $(hdrdir)/ruby/st.h @@ -16,8 +163,155 @@ 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/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/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/gc.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/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/rgengc.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/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 diff --git a/ruby/ext/-test-/notimplement/depend b/ruby/ext/-test-/notimplement/depend index 74911f0af..73d1fec43 100644 --- a/ruby/ext/-test-/notimplement/depend +++ b/ruby/ext/-test-/notimplement/depend @@ -4,8 +4,155 @@ bug.o: $(arch_hdrdir)/ruby/config.h bug.o: $(hdrdir)/ruby.h bug.o: $(hdrdir)/ruby/assert.h bug.o: $(hdrdir)/ruby/backward.h +bug.o: $(hdrdir)/ruby/backward/2/assume.h +bug.o: $(hdrdir)/ruby/backward/2/attributes.h +bug.o: $(hdrdir)/ruby/backward/2/bool.h +bug.o: $(hdrdir)/ruby/backward/2/inttypes.h +bug.o: $(hdrdir)/ruby/backward/2/limits.h +bug.o: $(hdrdir)/ruby/backward/2/long_long.h +bug.o: $(hdrdir)/ruby/backward/2/stdalign.h +bug.o: $(hdrdir)/ruby/backward/2/stdarg.h bug.o: $(hdrdir)/ruby/defines.h bug.o: $(hdrdir)/ruby/intern.h +bug.o: $(hdrdir)/ruby/internal/anyargs.h +bug.o: $(hdrdir)/ruby/internal/arithmetic.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bug.o: $(hdrdir)/ruby/internal/assume.h +bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bug.o: $(hdrdir)/ruby/internal/attr/artificial.h +bug.o: $(hdrdir)/ruby/internal/attr/cold.h +bug.o: $(hdrdir)/ruby/internal/attr/const.h +bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bug.o: $(hdrdir)/ruby/internal/attr/error.h +bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bug.o: $(hdrdir)/ruby/internal/attr/format.h +bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bug.o: $(hdrdir)/ruby/internal/attr/noalias.h +bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bug.o: $(hdrdir)/ruby/internal/attr/noinline.h +bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bug.o: $(hdrdir)/ruby/internal/attr/pure.h +bug.o: $(hdrdir)/ruby/internal/attr/restrict.h +bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bug.o: $(hdrdir)/ruby/internal/attr/warning.h +bug.o: $(hdrdir)/ruby/internal/attr/weakref.h +bug.o: $(hdrdir)/ruby/internal/cast.h +bug.o: $(hdrdir)/ruby/internal/compiler_is.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bug.o: $(hdrdir)/ruby/internal/compiler_since.h +bug.o: $(hdrdir)/ruby/internal/config.h +bug.o: $(hdrdir)/ruby/internal/constant_p.h +bug.o: $(hdrdir)/ruby/internal/core.h +bug.o: $(hdrdir)/ruby/internal/core/rarray.h +bug.o: $(hdrdir)/ruby/internal/core/rbasic.h +bug.o: $(hdrdir)/ruby/internal/core/rbignum.h +bug.o: $(hdrdir)/ruby/internal/core/rclass.h +bug.o: $(hdrdir)/ruby/internal/core/rdata.h +bug.o: $(hdrdir)/ruby/internal/core/rfile.h +bug.o: $(hdrdir)/ruby/internal/core/rhash.h +bug.o: $(hdrdir)/ruby/internal/core/robject.h +bug.o: $(hdrdir)/ruby/internal/core/rregexp.h +bug.o: $(hdrdir)/ruby/internal/core/rstring.h +bug.o: $(hdrdir)/ruby/internal/core/rstruct.h +bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bug.o: $(hdrdir)/ruby/internal/ctype.h +bug.o: $(hdrdir)/ruby/internal/dllexport.h +bug.o: $(hdrdir)/ruby/internal/dosish.h +bug.o: $(hdrdir)/ruby/internal/error.h +bug.o: $(hdrdir)/ruby/internal/eval.h +bug.o: $(hdrdir)/ruby/internal/event.h +bug.o: $(hdrdir)/ruby/internal/fl_type.h +bug.o: $(hdrdir)/ruby/internal/gc.h +bug.o: $(hdrdir)/ruby/internal/glob.h +bug.o: $(hdrdir)/ruby/internal/globals.h +bug.o: $(hdrdir)/ruby/internal/has/attribute.h +bug.o: $(hdrdir)/ruby/internal/has/builtin.h +bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bug.o: $(hdrdir)/ruby/internal/has/extension.h +bug.o: $(hdrdir)/ruby/internal/has/feature.h +bug.o: $(hdrdir)/ruby/internal/has/warning.h +bug.o: $(hdrdir)/ruby/internal/intern/array.h +bug.o: $(hdrdir)/ruby/internal/intern/bignum.h +bug.o: $(hdrdir)/ruby/internal/intern/class.h +bug.o: $(hdrdir)/ruby/internal/intern/compar.h +bug.o: $(hdrdir)/ruby/internal/intern/complex.h +bug.o: $(hdrdir)/ruby/internal/intern/cont.h +bug.o: $(hdrdir)/ruby/internal/intern/dir.h +bug.o: $(hdrdir)/ruby/internal/intern/enum.h +bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bug.o: $(hdrdir)/ruby/internal/intern/error.h +bug.o: $(hdrdir)/ruby/internal/intern/eval.h +bug.o: $(hdrdir)/ruby/internal/intern/file.h +bug.o: $(hdrdir)/ruby/internal/intern/gc.h +bug.o: $(hdrdir)/ruby/internal/intern/hash.h +bug.o: $(hdrdir)/ruby/internal/intern/io.h +bug.o: $(hdrdir)/ruby/internal/intern/load.h +bug.o: $(hdrdir)/ruby/internal/intern/marshal.h +bug.o: $(hdrdir)/ruby/internal/intern/numeric.h +bug.o: $(hdrdir)/ruby/internal/intern/object.h +bug.o: $(hdrdir)/ruby/internal/intern/parse.h +bug.o: $(hdrdir)/ruby/internal/intern/proc.h +bug.o: $(hdrdir)/ruby/internal/intern/process.h +bug.o: $(hdrdir)/ruby/internal/intern/random.h +bug.o: $(hdrdir)/ruby/internal/intern/range.h +bug.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bug.o: $(hdrdir)/ruby/internal/intern/string.h +bug.o: $(hdrdir)/ruby/internal/intern/struct.h +bug.o: $(hdrdir)/ruby/internal/intern/thread.h +bug.o: $(hdrdir)/ruby/internal/intern/time.h +bug.o: $(hdrdir)/ruby/internal/intern/variable.h +bug.o: $(hdrdir)/ruby/internal/intern/vm.h +bug.o: $(hdrdir)/ruby/internal/interpreter.h +bug.o: $(hdrdir)/ruby/internal/iterator.h +bug.o: $(hdrdir)/ruby/internal/memory.h +bug.o: $(hdrdir)/ruby/internal/method.h +bug.o: $(hdrdir)/ruby/internal/module.h +bug.o: $(hdrdir)/ruby/internal/newobj.h +bug.o: $(hdrdir)/ruby/internal/rgengc.h +bug.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bug.o: $(hdrdir)/ruby/internal/value.h +bug.o: $(hdrdir)/ruby/internal/value_type.h +bug.o: $(hdrdir)/ruby/internal/variable.h +bug.o: $(hdrdir)/ruby/internal/warning_push.h +bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/num2int/depend b/ruby/ext/-test-/num2int/depend index 76b69de85..77db0bfb8 100644 --- a/ruby/ext/-test-/num2int/depend +++ b/ruby/ext/-test-/num2int/depend @@ -4,8 +4,155 @@ num2int.o: $(arch_hdrdir)/ruby/config.h num2int.o: $(hdrdir)/ruby.h num2int.o: $(hdrdir)/ruby/assert.h num2int.o: $(hdrdir)/ruby/backward.h +num2int.o: $(hdrdir)/ruby/backward/2/assume.h +num2int.o: $(hdrdir)/ruby/backward/2/attributes.h +num2int.o: $(hdrdir)/ruby/backward/2/bool.h +num2int.o: $(hdrdir)/ruby/backward/2/inttypes.h +num2int.o: $(hdrdir)/ruby/backward/2/limits.h +num2int.o: $(hdrdir)/ruby/backward/2/long_long.h +num2int.o: $(hdrdir)/ruby/backward/2/stdalign.h +num2int.o: $(hdrdir)/ruby/backward/2/stdarg.h num2int.o: $(hdrdir)/ruby/defines.h num2int.o: $(hdrdir)/ruby/intern.h +num2int.o: $(hdrdir)/ruby/internal/anyargs.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/char.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/double.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/int.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/long.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/short.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +num2int.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +num2int.o: $(hdrdir)/ruby/internal/assume.h +num2int.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +num2int.o: $(hdrdir)/ruby/internal/attr/artificial.h +num2int.o: $(hdrdir)/ruby/internal/attr/cold.h +num2int.o: $(hdrdir)/ruby/internal/attr/const.h +num2int.o: $(hdrdir)/ruby/internal/attr/constexpr.h +num2int.o: $(hdrdir)/ruby/internal/attr/deprecated.h +num2int.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +num2int.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +num2int.o: $(hdrdir)/ruby/internal/attr/error.h +num2int.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +num2int.o: $(hdrdir)/ruby/internal/attr/forceinline.h +num2int.o: $(hdrdir)/ruby/internal/attr/format.h +num2int.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +num2int.o: $(hdrdir)/ruby/internal/attr/noalias.h +num2int.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +num2int.o: $(hdrdir)/ruby/internal/attr/noexcept.h +num2int.o: $(hdrdir)/ruby/internal/attr/noinline.h +num2int.o: $(hdrdir)/ruby/internal/attr/nonnull.h +num2int.o: $(hdrdir)/ruby/internal/attr/noreturn.h +num2int.o: $(hdrdir)/ruby/internal/attr/pure.h +num2int.o: $(hdrdir)/ruby/internal/attr/restrict.h +num2int.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +num2int.o: $(hdrdir)/ruby/internal/attr/warning.h +num2int.o: $(hdrdir)/ruby/internal/attr/weakref.h +num2int.o: $(hdrdir)/ruby/internal/cast.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +num2int.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +num2int.o: $(hdrdir)/ruby/internal/compiler_since.h +num2int.o: $(hdrdir)/ruby/internal/config.h +num2int.o: $(hdrdir)/ruby/internal/constant_p.h +num2int.o: $(hdrdir)/ruby/internal/core.h +num2int.o: $(hdrdir)/ruby/internal/core/rarray.h +num2int.o: $(hdrdir)/ruby/internal/core/rbasic.h +num2int.o: $(hdrdir)/ruby/internal/core/rbignum.h +num2int.o: $(hdrdir)/ruby/internal/core/rclass.h +num2int.o: $(hdrdir)/ruby/internal/core/rdata.h +num2int.o: $(hdrdir)/ruby/internal/core/rfile.h +num2int.o: $(hdrdir)/ruby/internal/core/rhash.h +num2int.o: $(hdrdir)/ruby/internal/core/robject.h +num2int.o: $(hdrdir)/ruby/internal/core/rregexp.h +num2int.o: $(hdrdir)/ruby/internal/core/rstring.h +num2int.o: $(hdrdir)/ruby/internal/core/rstruct.h +num2int.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +num2int.o: $(hdrdir)/ruby/internal/ctype.h +num2int.o: $(hdrdir)/ruby/internal/dllexport.h +num2int.o: $(hdrdir)/ruby/internal/dosish.h +num2int.o: $(hdrdir)/ruby/internal/error.h +num2int.o: $(hdrdir)/ruby/internal/eval.h +num2int.o: $(hdrdir)/ruby/internal/event.h +num2int.o: $(hdrdir)/ruby/internal/fl_type.h +num2int.o: $(hdrdir)/ruby/internal/gc.h +num2int.o: $(hdrdir)/ruby/internal/glob.h +num2int.o: $(hdrdir)/ruby/internal/globals.h +num2int.o: $(hdrdir)/ruby/internal/has/attribute.h +num2int.o: $(hdrdir)/ruby/internal/has/builtin.h +num2int.o: $(hdrdir)/ruby/internal/has/c_attribute.h +num2int.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +num2int.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +num2int.o: $(hdrdir)/ruby/internal/has/extension.h +num2int.o: $(hdrdir)/ruby/internal/has/feature.h +num2int.o: $(hdrdir)/ruby/internal/has/warning.h +num2int.o: $(hdrdir)/ruby/internal/intern/array.h +num2int.o: $(hdrdir)/ruby/internal/intern/bignum.h +num2int.o: $(hdrdir)/ruby/internal/intern/class.h +num2int.o: $(hdrdir)/ruby/internal/intern/compar.h +num2int.o: $(hdrdir)/ruby/internal/intern/complex.h +num2int.o: $(hdrdir)/ruby/internal/intern/cont.h +num2int.o: $(hdrdir)/ruby/internal/intern/dir.h +num2int.o: $(hdrdir)/ruby/internal/intern/enum.h +num2int.o: $(hdrdir)/ruby/internal/intern/enumerator.h +num2int.o: $(hdrdir)/ruby/internal/intern/error.h +num2int.o: $(hdrdir)/ruby/internal/intern/eval.h +num2int.o: $(hdrdir)/ruby/internal/intern/file.h +num2int.o: $(hdrdir)/ruby/internal/intern/gc.h +num2int.o: $(hdrdir)/ruby/internal/intern/hash.h +num2int.o: $(hdrdir)/ruby/internal/intern/io.h +num2int.o: $(hdrdir)/ruby/internal/intern/load.h +num2int.o: $(hdrdir)/ruby/internal/intern/marshal.h +num2int.o: $(hdrdir)/ruby/internal/intern/numeric.h +num2int.o: $(hdrdir)/ruby/internal/intern/object.h +num2int.o: $(hdrdir)/ruby/internal/intern/parse.h +num2int.o: $(hdrdir)/ruby/internal/intern/proc.h +num2int.o: $(hdrdir)/ruby/internal/intern/process.h +num2int.o: $(hdrdir)/ruby/internal/intern/random.h +num2int.o: $(hdrdir)/ruby/internal/intern/range.h +num2int.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +num2int.o: $(hdrdir)/ruby/internal/intern/sprintf.h +num2int.o: $(hdrdir)/ruby/internal/intern/string.h +num2int.o: $(hdrdir)/ruby/internal/intern/struct.h +num2int.o: $(hdrdir)/ruby/internal/intern/thread.h +num2int.o: $(hdrdir)/ruby/internal/intern/time.h +num2int.o: $(hdrdir)/ruby/internal/intern/variable.h +num2int.o: $(hdrdir)/ruby/internal/intern/vm.h +num2int.o: $(hdrdir)/ruby/internal/interpreter.h +num2int.o: $(hdrdir)/ruby/internal/iterator.h +num2int.o: $(hdrdir)/ruby/internal/memory.h +num2int.o: $(hdrdir)/ruby/internal/method.h +num2int.o: $(hdrdir)/ruby/internal/module.h +num2int.o: $(hdrdir)/ruby/internal/newobj.h +num2int.o: $(hdrdir)/ruby/internal/rgengc.h +num2int.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +num2int.o: $(hdrdir)/ruby/internal/value.h +num2int.o: $(hdrdir)/ruby/internal/value_type.h +num2int.o: $(hdrdir)/ruby/internal/variable.h +num2int.o: $(hdrdir)/ruby/internal/warning_push.h +num2int.o: $(hdrdir)/ruby/internal/xmalloc.h num2int.o: $(hdrdir)/ruby/missing.h num2int.o: $(hdrdir)/ruby/ruby.h num2int.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/path_to_class/depend b/ruby/ext/-test-/path_to_class/depend index 9a7f7d017..4911b80ad 100644 --- a/ruby/ext/-test-/path_to_class/depend +++ b/ruby/ext/-test-/path_to_class/depend @@ -4,8 +4,155 @@ path_to_class.o: $(arch_hdrdir)/ruby/config.h path_to_class.o: $(hdrdir)/ruby.h path_to_class.o: $(hdrdir)/ruby/assert.h path_to_class.o: $(hdrdir)/ruby/backward.h +path_to_class.o: $(hdrdir)/ruby/backward/2/assume.h +path_to_class.o: $(hdrdir)/ruby/backward/2/attributes.h +path_to_class.o: $(hdrdir)/ruby/backward/2/bool.h +path_to_class.o: $(hdrdir)/ruby/backward/2/inttypes.h +path_to_class.o: $(hdrdir)/ruby/backward/2/limits.h +path_to_class.o: $(hdrdir)/ruby/backward/2/long_long.h +path_to_class.o: $(hdrdir)/ruby/backward/2/stdalign.h +path_to_class.o: $(hdrdir)/ruby/backward/2/stdarg.h path_to_class.o: $(hdrdir)/ruby/defines.h path_to_class.o: $(hdrdir)/ruby/intern.h +path_to_class.o: $(hdrdir)/ruby/internal/anyargs.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/char.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/double.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/int.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/short.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +path_to_class.o: $(hdrdir)/ruby/internal/assume.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/artificial.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/cold.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/const.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/constexpr.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/deprecated.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/error.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/forceinline.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/format.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/noalias.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/noexcept.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/noinline.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/nonnull.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/noreturn.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/pure.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/restrict.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/warning.h +path_to_class.o: $(hdrdir)/ruby/internal/attr/weakref.h +path_to_class.o: $(hdrdir)/ruby/internal/cast.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +path_to_class.o: $(hdrdir)/ruby/internal/compiler_since.h +path_to_class.o: $(hdrdir)/ruby/internal/config.h +path_to_class.o: $(hdrdir)/ruby/internal/constant_p.h +path_to_class.o: $(hdrdir)/ruby/internal/core.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rarray.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rbasic.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rbignum.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rclass.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rdata.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rfile.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rhash.h +path_to_class.o: $(hdrdir)/ruby/internal/core/robject.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rregexp.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rstring.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rstruct.h +path_to_class.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +path_to_class.o: $(hdrdir)/ruby/internal/ctype.h +path_to_class.o: $(hdrdir)/ruby/internal/dllexport.h +path_to_class.o: $(hdrdir)/ruby/internal/dosish.h +path_to_class.o: $(hdrdir)/ruby/internal/error.h +path_to_class.o: $(hdrdir)/ruby/internal/eval.h +path_to_class.o: $(hdrdir)/ruby/internal/event.h +path_to_class.o: $(hdrdir)/ruby/internal/fl_type.h +path_to_class.o: $(hdrdir)/ruby/internal/gc.h +path_to_class.o: $(hdrdir)/ruby/internal/glob.h +path_to_class.o: $(hdrdir)/ruby/internal/globals.h +path_to_class.o: $(hdrdir)/ruby/internal/has/attribute.h +path_to_class.o: $(hdrdir)/ruby/internal/has/builtin.h +path_to_class.o: $(hdrdir)/ruby/internal/has/c_attribute.h +path_to_class.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +path_to_class.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +path_to_class.o: $(hdrdir)/ruby/internal/has/extension.h +path_to_class.o: $(hdrdir)/ruby/internal/has/feature.h +path_to_class.o: $(hdrdir)/ruby/internal/has/warning.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/array.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/bignum.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/class.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/compar.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/complex.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/cont.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/dir.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/enum.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/enumerator.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/error.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/eval.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/file.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/gc.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/hash.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/io.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/load.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/marshal.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/numeric.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/object.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/parse.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/proc.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/process.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/random.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/range.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/sprintf.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/string.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/struct.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/thread.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/time.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/variable.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/vm.h +path_to_class.o: $(hdrdir)/ruby/internal/interpreter.h +path_to_class.o: $(hdrdir)/ruby/internal/iterator.h +path_to_class.o: $(hdrdir)/ruby/internal/memory.h +path_to_class.o: $(hdrdir)/ruby/internal/method.h +path_to_class.o: $(hdrdir)/ruby/internal/module.h +path_to_class.o: $(hdrdir)/ruby/internal/newobj.h +path_to_class.o: $(hdrdir)/ruby/internal/rgengc.h +path_to_class.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +path_to_class.o: $(hdrdir)/ruby/internal/value.h +path_to_class.o: $(hdrdir)/ruby/internal/value_type.h +path_to_class.o: $(hdrdir)/ruby/internal/variable.h +path_to_class.o: $(hdrdir)/ruby/internal/warning_push.h +path_to_class.o: $(hdrdir)/ruby/internal/xmalloc.h path_to_class.o: $(hdrdir)/ruby/missing.h path_to_class.o: $(hdrdir)/ruby/ruby.h path_to_class.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/popen_deadlock/depend b/ruby/ext/-test-/popen_deadlock/depend index 4c3f3853f..e36a6c956 100644 --- a/ruby/ext/-test-/popen_deadlock/depend +++ b/ruby/ext/-test-/popen_deadlock/depend @@ -1,8 +1,156 @@ # AUTOGENERATED DEPENDENCIES START infinite_loop_dlsym.o: $(RUBY_EXTCONF_H) infinite_loop_dlsym.o: $(arch_hdrdir)/ruby/config.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/anyargs.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/char.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/double.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/int.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/short.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/assume.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/artificial.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/cold.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/const.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/constexpr.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/deprecated.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/error.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/forceinline.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/format.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noalias.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noexcept.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noinline.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nonnull.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noreturn.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/pure.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/restrict.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/warning.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/weakref.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/cast.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_since.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/config.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/constant_p.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rarray.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbasic.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbignum.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rclass.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rdata.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rfile.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rhash.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/robject.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rregexp.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstring.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstruct.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/ctype.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dllexport.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dosish.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/error.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/eval.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/event.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/fl_type.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/gc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/glob.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/globals.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/attribute.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/builtin.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/c_attribute.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/extension.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/feature.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/warning.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/array.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/bignum.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/class.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/compar.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/complex.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/cont.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/dir.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enum.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enumerator.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/error.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/eval.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/file.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/gc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/hash.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/io.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/load.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/marshal.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/numeric.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/object.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/parse.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/proc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/process.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/random.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/range.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/sprintf.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/string.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/struct.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/thread.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/time.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/variable.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/vm.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/interpreter.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/iterator.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/memory.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/method.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/module.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/newobj.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/rgengc.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value_type.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/variable.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/warning_push.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/xmalloc.h infinite_loop_dlsym.o: $(hdrdir)/ruby/assert.h infinite_loop_dlsym.o: $(hdrdir)/ruby/backward.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/assume.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/attributes.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/bool.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/inttypes.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/limits.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/long_long.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdalign.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdarg.h infinite_loop_dlsym.o: $(hdrdir)/ruby/defines.h infinite_loop_dlsym.o: $(hdrdir)/ruby/intern.h infinite_loop_dlsym.o: $(hdrdir)/ruby/missing.h diff --git a/ruby/ext/-test-/popen_deadlock/extconf.rb b/ruby/ext/-test-/popen_deadlock/extconf.rb index 24a7d7993..6b6ee7a6b 100644 --- a/ruby/ext/-test-/popen_deadlock/extconf.rb +++ b/ruby/ext/-test-/popen_deadlock/extconf.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false case RUBY_PLATFORM when /solaris/i, /linux/i + $LDFLAGS << " -ldl" create_makefile("-test-/popen_deadlock/infinite_loop_dlsym") end diff --git a/ruby/ext/-test-/postponed_job/depend b/ruby/ext/-test-/postponed_job/depend index 998e2dcc9..36f08b6eb 100644 --- a/ruby/ext/-test-/postponed_job/depend +++ b/ruby/ext/-test-/postponed_job/depend @@ -4,9 +4,156 @@ postponed_job.o: $(arch_hdrdir)/ruby/config.h postponed_job.o: $(hdrdir)/ruby.h postponed_job.o: $(hdrdir)/ruby/assert.h postponed_job.o: $(hdrdir)/ruby/backward.h +postponed_job.o: $(hdrdir)/ruby/backward/2/assume.h +postponed_job.o: $(hdrdir)/ruby/backward/2/attributes.h +postponed_job.o: $(hdrdir)/ruby/backward/2/bool.h +postponed_job.o: $(hdrdir)/ruby/backward/2/inttypes.h +postponed_job.o: $(hdrdir)/ruby/backward/2/limits.h +postponed_job.o: $(hdrdir)/ruby/backward/2/long_long.h +postponed_job.o: $(hdrdir)/ruby/backward/2/stdalign.h +postponed_job.o: $(hdrdir)/ruby/backward/2/stdarg.h postponed_job.o: $(hdrdir)/ruby/debug.h postponed_job.o: $(hdrdir)/ruby/defines.h postponed_job.o: $(hdrdir)/ruby/intern.h +postponed_job.o: $(hdrdir)/ruby/internal/anyargs.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/char.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/double.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/int.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/short.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +postponed_job.o: $(hdrdir)/ruby/internal/assume.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/artificial.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/cold.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/const.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/constexpr.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/deprecated.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/error.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/forceinline.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/format.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/noalias.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/noexcept.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/noinline.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/nonnull.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/noreturn.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/pure.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/restrict.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/warning.h +postponed_job.o: $(hdrdir)/ruby/internal/attr/weakref.h +postponed_job.o: $(hdrdir)/ruby/internal/cast.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +postponed_job.o: $(hdrdir)/ruby/internal/compiler_since.h +postponed_job.o: $(hdrdir)/ruby/internal/config.h +postponed_job.o: $(hdrdir)/ruby/internal/constant_p.h +postponed_job.o: $(hdrdir)/ruby/internal/core.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rarray.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rbasic.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rbignum.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rclass.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rdata.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rfile.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rhash.h +postponed_job.o: $(hdrdir)/ruby/internal/core/robject.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rregexp.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rstring.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rstruct.h +postponed_job.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +postponed_job.o: $(hdrdir)/ruby/internal/ctype.h +postponed_job.o: $(hdrdir)/ruby/internal/dllexport.h +postponed_job.o: $(hdrdir)/ruby/internal/dosish.h +postponed_job.o: $(hdrdir)/ruby/internal/error.h +postponed_job.o: $(hdrdir)/ruby/internal/eval.h +postponed_job.o: $(hdrdir)/ruby/internal/event.h +postponed_job.o: $(hdrdir)/ruby/internal/fl_type.h +postponed_job.o: $(hdrdir)/ruby/internal/gc.h +postponed_job.o: $(hdrdir)/ruby/internal/glob.h +postponed_job.o: $(hdrdir)/ruby/internal/globals.h +postponed_job.o: $(hdrdir)/ruby/internal/has/attribute.h +postponed_job.o: $(hdrdir)/ruby/internal/has/builtin.h +postponed_job.o: $(hdrdir)/ruby/internal/has/c_attribute.h +postponed_job.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +postponed_job.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +postponed_job.o: $(hdrdir)/ruby/internal/has/extension.h +postponed_job.o: $(hdrdir)/ruby/internal/has/feature.h +postponed_job.o: $(hdrdir)/ruby/internal/has/warning.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/array.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/bignum.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/class.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/compar.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/complex.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/cont.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/dir.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/enum.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/enumerator.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/error.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/eval.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/file.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/gc.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/hash.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/io.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/load.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/marshal.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/numeric.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/object.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/parse.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/proc.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/process.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/random.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/range.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/sprintf.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/string.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/struct.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/thread.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/time.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/variable.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/vm.h +postponed_job.o: $(hdrdir)/ruby/internal/interpreter.h +postponed_job.o: $(hdrdir)/ruby/internal/iterator.h +postponed_job.o: $(hdrdir)/ruby/internal/memory.h +postponed_job.o: $(hdrdir)/ruby/internal/method.h +postponed_job.o: $(hdrdir)/ruby/internal/module.h +postponed_job.o: $(hdrdir)/ruby/internal/newobj.h +postponed_job.o: $(hdrdir)/ruby/internal/rgengc.h +postponed_job.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +postponed_job.o: $(hdrdir)/ruby/internal/value.h +postponed_job.o: $(hdrdir)/ruby/internal/value_type.h +postponed_job.o: $(hdrdir)/ruby/internal/variable.h +postponed_job.o: $(hdrdir)/ruby/internal/warning_push.h +postponed_job.o: $(hdrdir)/ruby/internal/xmalloc.h postponed_job.o: $(hdrdir)/ruby/missing.h postponed_job.o: $(hdrdir)/ruby/ruby.h postponed_job.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/postponed_job/postponed_job.c b/ruby/ext/-test-/postponed_job/postponed_job.c index d8684d475..fa57bef6f 100644 --- a/ruby/ext/-test-/postponed_job/postponed_job.c +++ b/ruby/ext/-test-/postponed_job/postponed_job.c @@ -58,6 +58,34 @@ pjob_call_direct(VALUE self, VALUE obj) return self; } +#ifdef HAVE_PTHREAD_H +#include + +static void * +pjob_register_in_c_thread_i(void *obj) +{ + rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj); + rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj); + rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj); + return NULL; +} + +static VALUE +pjob_register_in_c_thread(VALUE self, VALUE obj) +{ + pthread_t thread; + if (pthread_create(&thread, NULL, pjob_register_in_c_thread_i, (void *)obj)) { + return Qfalse; + } + + if (pthread_join(thread, NULL)) { + return Qfalse; + } + + return Qtrue; +} +#endif + void Init_postponed_job(VALUE self) { @@ -65,5 +93,8 @@ 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); +#ifdef HAVE_PTHREAD_H + rb_define_module_function(mBug, "postponed_job_register_in_c_thread", pjob_register_in_c_thread, 1); +#endif } diff --git a/ruby/ext/-test-/printf/depend b/ruby/ext/-test-/printf/depend index 7860797f5..143317c77 100644 --- a/ruby/ext/-test-/printf/depend +++ b/ruby/ext/-test-/printf/depend @@ -4,9 +4,165 @@ printf.o: $(arch_hdrdir)/ruby/config.h printf.o: $(hdrdir)/ruby.h printf.o: $(hdrdir)/ruby/assert.h printf.o: $(hdrdir)/ruby/backward.h +printf.o: $(hdrdir)/ruby/backward/2/assume.h +printf.o: $(hdrdir)/ruby/backward/2/attributes.h +printf.o: $(hdrdir)/ruby/backward/2/bool.h +printf.o: $(hdrdir)/ruby/backward/2/inttypes.h +printf.o: $(hdrdir)/ruby/backward/2/limits.h +printf.o: $(hdrdir)/ruby/backward/2/long_long.h +printf.o: $(hdrdir)/ruby/backward/2/stdalign.h +printf.o: $(hdrdir)/ruby/backward/2/stdarg.h printf.o: $(hdrdir)/ruby/defines.h printf.o: $(hdrdir)/ruby/encoding.h printf.o: $(hdrdir)/ruby/intern.h +printf.o: $(hdrdir)/ruby/internal/anyargs.h +printf.o: $(hdrdir)/ruby/internal/arithmetic.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/char.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/double.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/int.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/long.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/short.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +printf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +printf.o: $(hdrdir)/ruby/internal/assume.h +printf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +printf.o: $(hdrdir)/ruby/internal/attr/artificial.h +printf.o: $(hdrdir)/ruby/internal/attr/cold.h +printf.o: $(hdrdir)/ruby/internal/attr/const.h +printf.o: $(hdrdir)/ruby/internal/attr/constexpr.h +printf.o: $(hdrdir)/ruby/internal/attr/deprecated.h +printf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +printf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +printf.o: $(hdrdir)/ruby/internal/attr/error.h +printf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +printf.o: $(hdrdir)/ruby/internal/attr/forceinline.h +printf.o: $(hdrdir)/ruby/internal/attr/format.h +printf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +printf.o: $(hdrdir)/ruby/internal/attr/noalias.h +printf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +printf.o: $(hdrdir)/ruby/internal/attr/noexcept.h +printf.o: $(hdrdir)/ruby/internal/attr/noinline.h +printf.o: $(hdrdir)/ruby/internal/attr/nonnull.h +printf.o: $(hdrdir)/ruby/internal/attr/noreturn.h +printf.o: $(hdrdir)/ruby/internal/attr/pure.h +printf.o: $(hdrdir)/ruby/internal/attr/restrict.h +printf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +printf.o: $(hdrdir)/ruby/internal/attr/warning.h +printf.o: $(hdrdir)/ruby/internal/attr/weakref.h +printf.o: $(hdrdir)/ruby/internal/cast.h +printf.o: $(hdrdir)/ruby/internal/compiler_is.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +printf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +printf.o: $(hdrdir)/ruby/internal/compiler_since.h +printf.o: $(hdrdir)/ruby/internal/config.h +printf.o: $(hdrdir)/ruby/internal/constant_p.h +printf.o: $(hdrdir)/ruby/internal/core.h +printf.o: $(hdrdir)/ruby/internal/core/rarray.h +printf.o: $(hdrdir)/ruby/internal/core/rbasic.h +printf.o: $(hdrdir)/ruby/internal/core/rbignum.h +printf.o: $(hdrdir)/ruby/internal/core/rclass.h +printf.o: $(hdrdir)/ruby/internal/core/rdata.h +printf.o: $(hdrdir)/ruby/internal/core/rfile.h +printf.o: $(hdrdir)/ruby/internal/core/rhash.h +printf.o: $(hdrdir)/ruby/internal/core/robject.h +printf.o: $(hdrdir)/ruby/internal/core/rregexp.h +printf.o: $(hdrdir)/ruby/internal/core/rstring.h +printf.o: $(hdrdir)/ruby/internal/core/rstruct.h +printf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +printf.o: $(hdrdir)/ruby/internal/ctype.h +printf.o: $(hdrdir)/ruby/internal/dllexport.h +printf.o: $(hdrdir)/ruby/internal/dosish.h +printf.o: $(hdrdir)/ruby/internal/encoding/coderange.h +printf.o: $(hdrdir)/ruby/internal/encoding/ctype.h +printf.o: $(hdrdir)/ruby/internal/encoding/encoding.h +printf.o: $(hdrdir)/ruby/internal/encoding/pathname.h +printf.o: $(hdrdir)/ruby/internal/encoding/re.h +printf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +printf.o: $(hdrdir)/ruby/internal/encoding/string.h +printf.o: $(hdrdir)/ruby/internal/encoding/symbol.h +printf.o: $(hdrdir)/ruby/internal/encoding/transcode.h +printf.o: $(hdrdir)/ruby/internal/error.h +printf.o: $(hdrdir)/ruby/internal/eval.h +printf.o: $(hdrdir)/ruby/internal/event.h +printf.o: $(hdrdir)/ruby/internal/fl_type.h +printf.o: $(hdrdir)/ruby/internal/gc.h +printf.o: $(hdrdir)/ruby/internal/glob.h +printf.o: $(hdrdir)/ruby/internal/globals.h +printf.o: $(hdrdir)/ruby/internal/has/attribute.h +printf.o: $(hdrdir)/ruby/internal/has/builtin.h +printf.o: $(hdrdir)/ruby/internal/has/c_attribute.h +printf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +printf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +printf.o: $(hdrdir)/ruby/internal/has/extension.h +printf.o: $(hdrdir)/ruby/internal/has/feature.h +printf.o: $(hdrdir)/ruby/internal/has/warning.h +printf.o: $(hdrdir)/ruby/internal/intern/array.h +printf.o: $(hdrdir)/ruby/internal/intern/bignum.h +printf.o: $(hdrdir)/ruby/internal/intern/class.h +printf.o: $(hdrdir)/ruby/internal/intern/compar.h +printf.o: $(hdrdir)/ruby/internal/intern/complex.h +printf.o: $(hdrdir)/ruby/internal/intern/cont.h +printf.o: $(hdrdir)/ruby/internal/intern/dir.h +printf.o: $(hdrdir)/ruby/internal/intern/enum.h +printf.o: $(hdrdir)/ruby/internal/intern/enumerator.h +printf.o: $(hdrdir)/ruby/internal/intern/error.h +printf.o: $(hdrdir)/ruby/internal/intern/eval.h +printf.o: $(hdrdir)/ruby/internal/intern/file.h +printf.o: $(hdrdir)/ruby/internal/intern/gc.h +printf.o: $(hdrdir)/ruby/internal/intern/hash.h +printf.o: $(hdrdir)/ruby/internal/intern/io.h +printf.o: $(hdrdir)/ruby/internal/intern/load.h +printf.o: $(hdrdir)/ruby/internal/intern/marshal.h +printf.o: $(hdrdir)/ruby/internal/intern/numeric.h +printf.o: $(hdrdir)/ruby/internal/intern/object.h +printf.o: $(hdrdir)/ruby/internal/intern/parse.h +printf.o: $(hdrdir)/ruby/internal/intern/proc.h +printf.o: $(hdrdir)/ruby/internal/intern/process.h +printf.o: $(hdrdir)/ruby/internal/intern/random.h +printf.o: $(hdrdir)/ruby/internal/intern/range.h +printf.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +printf.o: $(hdrdir)/ruby/internal/intern/sprintf.h +printf.o: $(hdrdir)/ruby/internal/intern/string.h +printf.o: $(hdrdir)/ruby/internal/intern/struct.h +printf.o: $(hdrdir)/ruby/internal/intern/thread.h +printf.o: $(hdrdir)/ruby/internal/intern/time.h +printf.o: $(hdrdir)/ruby/internal/intern/variable.h +printf.o: $(hdrdir)/ruby/internal/intern/vm.h +printf.o: $(hdrdir)/ruby/internal/interpreter.h +printf.o: $(hdrdir)/ruby/internal/iterator.h +printf.o: $(hdrdir)/ruby/internal/memory.h +printf.o: $(hdrdir)/ruby/internal/method.h +printf.o: $(hdrdir)/ruby/internal/module.h +printf.o: $(hdrdir)/ruby/internal/newobj.h +printf.o: $(hdrdir)/ruby/internal/rgengc.h +printf.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +printf.o: $(hdrdir)/ruby/internal/value.h +printf.o: $(hdrdir)/ruby/internal/value_type.h +printf.o: $(hdrdir)/ruby/internal/variable.h +printf.o: $(hdrdir)/ruby/internal/warning_push.h +printf.o: $(hdrdir)/ruby/internal/xmalloc.h printf.o: $(hdrdir)/ruby/missing.h printf.o: $(hdrdir)/ruby/onigmo.h printf.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/-test-/proc/depend b/ruby/ext/-test-/proc/depend index 5946e4ca0..a1ce4cdf4 100644 --- a/ruby/ext/-test-/proc/depend +++ b/ruby/ext/-test-/proc/depend @@ -4,8 +4,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -16,8 +163,155 @@ receiver.o: $(arch_hdrdir)/ruby/config.h receiver.o: $(hdrdir)/ruby.h receiver.o: $(hdrdir)/ruby/assert.h receiver.o: $(hdrdir)/ruby/backward.h +receiver.o: $(hdrdir)/ruby/backward/2/assume.h +receiver.o: $(hdrdir)/ruby/backward/2/attributes.h +receiver.o: $(hdrdir)/ruby/backward/2/bool.h +receiver.o: $(hdrdir)/ruby/backward/2/inttypes.h +receiver.o: $(hdrdir)/ruby/backward/2/limits.h +receiver.o: $(hdrdir)/ruby/backward/2/long_long.h +receiver.o: $(hdrdir)/ruby/backward/2/stdalign.h +receiver.o: $(hdrdir)/ruby/backward/2/stdarg.h receiver.o: $(hdrdir)/ruby/defines.h receiver.o: $(hdrdir)/ruby/intern.h +receiver.o: $(hdrdir)/ruby/internal/anyargs.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +receiver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +receiver.o: $(hdrdir)/ruby/internal/assume.h +receiver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +receiver.o: $(hdrdir)/ruby/internal/attr/artificial.h +receiver.o: $(hdrdir)/ruby/internal/attr/cold.h +receiver.o: $(hdrdir)/ruby/internal/attr/const.h +receiver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +receiver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +receiver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +receiver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +receiver.o: $(hdrdir)/ruby/internal/attr/error.h +receiver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +receiver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +receiver.o: $(hdrdir)/ruby/internal/attr/format.h +receiver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +receiver.o: $(hdrdir)/ruby/internal/attr/noalias.h +receiver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +receiver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +receiver.o: $(hdrdir)/ruby/internal/attr/noinline.h +receiver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +receiver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +receiver.o: $(hdrdir)/ruby/internal/attr/pure.h +receiver.o: $(hdrdir)/ruby/internal/attr/restrict.h +receiver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +receiver.o: $(hdrdir)/ruby/internal/attr/warning.h +receiver.o: $(hdrdir)/ruby/internal/attr/weakref.h +receiver.o: $(hdrdir)/ruby/internal/cast.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +receiver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +receiver.o: $(hdrdir)/ruby/internal/compiler_since.h +receiver.o: $(hdrdir)/ruby/internal/config.h +receiver.o: $(hdrdir)/ruby/internal/constant_p.h +receiver.o: $(hdrdir)/ruby/internal/core.h +receiver.o: $(hdrdir)/ruby/internal/core/rarray.h +receiver.o: $(hdrdir)/ruby/internal/core/rbasic.h +receiver.o: $(hdrdir)/ruby/internal/core/rbignum.h +receiver.o: $(hdrdir)/ruby/internal/core/rclass.h +receiver.o: $(hdrdir)/ruby/internal/core/rdata.h +receiver.o: $(hdrdir)/ruby/internal/core/rfile.h +receiver.o: $(hdrdir)/ruby/internal/core/rhash.h +receiver.o: $(hdrdir)/ruby/internal/core/robject.h +receiver.o: $(hdrdir)/ruby/internal/core/rregexp.h +receiver.o: $(hdrdir)/ruby/internal/core/rstring.h +receiver.o: $(hdrdir)/ruby/internal/core/rstruct.h +receiver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +receiver.o: $(hdrdir)/ruby/internal/ctype.h +receiver.o: $(hdrdir)/ruby/internal/dllexport.h +receiver.o: $(hdrdir)/ruby/internal/dosish.h +receiver.o: $(hdrdir)/ruby/internal/error.h +receiver.o: $(hdrdir)/ruby/internal/eval.h +receiver.o: $(hdrdir)/ruby/internal/event.h +receiver.o: $(hdrdir)/ruby/internal/fl_type.h +receiver.o: $(hdrdir)/ruby/internal/gc.h +receiver.o: $(hdrdir)/ruby/internal/glob.h +receiver.o: $(hdrdir)/ruby/internal/globals.h +receiver.o: $(hdrdir)/ruby/internal/has/attribute.h +receiver.o: $(hdrdir)/ruby/internal/has/builtin.h +receiver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +receiver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +receiver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +receiver.o: $(hdrdir)/ruby/internal/has/extension.h +receiver.o: $(hdrdir)/ruby/internal/has/feature.h +receiver.o: $(hdrdir)/ruby/internal/has/warning.h +receiver.o: $(hdrdir)/ruby/internal/intern/array.h +receiver.o: $(hdrdir)/ruby/internal/intern/bignum.h +receiver.o: $(hdrdir)/ruby/internal/intern/class.h +receiver.o: $(hdrdir)/ruby/internal/intern/compar.h +receiver.o: $(hdrdir)/ruby/internal/intern/complex.h +receiver.o: $(hdrdir)/ruby/internal/intern/cont.h +receiver.o: $(hdrdir)/ruby/internal/intern/dir.h +receiver.o: $(hdrdir)/ruby/internal/intern/enum.h +receiver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +receiver.o: $(hdrdir)/ruby/internal/intern/error.h +receiver.o: $(hdrdir)/ruby/internal/intern/eval.h +receiver.o: $(hdrdir)/ruby/internal/intern/file.h +receiver.o: $(hdrdir)/ruby/internal/intern/gc.h +receiver.o: $(hdrdir)/ruby/internal/intern/hash.h +receiver.o: $(hdrdir)/ruby/internal/intern/io.h +receiver.o: $(hdrdir)/ruby/internal/intern/load.h +receiver.o: $(hdrdir)/ruby/internal/intern/marshal.h +receiver.o: $(hdrdir)/ruby/internal/intern/numeric.h +receiver.o: $(hdrdir)/ruby/internal/intern/object.h +receiver.o: $(hdrdir)/ruby/internal/intern/parse.h +receiver.o: $(hdrdir)/ruby/internal/intern/proc.h +receiver.o: $(hdrdir)/ruby/internal/intern/process.h +receiver.o: $(hdrdir)/ruby/internal/intern/random.h +receiver.o: $(hdrdir)/ruby/internal/intern/range.h +receiver.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +receiver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +receiver.o: $(hdrdir)/ruby/internal/intern/string.h +receiver.o: $(hdrdir)/ruby/internal/intern/struct.h +receiver.o: $(hdrdir)/ruby/internal/intern/thread.h +receiver.o: $(hdrdir)/ruby/internal/intern/time.h +receiver.o: $(hdrdir)/ruby/internal/intern/variable.h +receiver.o: $(hdrdir)/ruby/internal/intern/vm.h +receiver.o: $(hdrdir)/ruby/internal/interpreter.h +receiver.o: $(hdrdir)/ruby/internal/iterator.h +receiver.o: $(hdrdir)/ruby/internal/memory.h +receiver.o: $(hdrdir)/ruby/internal/method.h +receiver.o: $(hdrdir)/ruby/internal/module.h +receiver.o: $(hdrdir)/ruby/internal/newobj.h +receiver.o: $(hdrdir)/ruby/internal/rgengc.h +receiver.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +receiver.o: $(hdrdir)/ruby/internal/value.h +receiver.o: $(hdrdir)/ruby/internal/value_type.h +receiver.o: $(hdrdir)/ruby/internal/variable.h +receiver.o: $(hdrdir)/ruby/internal/warning_push.h +receiver.o: $(hdrdir)/ruby/internal/xmalloc.h receiver.o: $(hdrdir)/ruby/missing.h receiver.o: $(hdrdir)/ruby/ruby.h receiver.o: $(hdrdir)/ruby/st.h @@ -28,8 +322,155 @@ super.o: $(arch_hdrdir)/ruby/config.h super.o: $(hdrdir)/ruby.h super.o: $(hdrdir)/ruby/assert.h super.o: $(hdrdir)/ruby/backward.h +super.o: $(hdrdir)/ruby/backward/2/assume.h +super.o: $(hdrdir)/ruby/backward/2/attributes.h +super.o: $(hdrdir)/ruby/backward/2/bool.h +super.o: $(hdrdir)/ruby/backward/2/inttypes.h +super.o: $(hdrdir)/ruby/backward/2/limits.h +super.o: $(hdrdir)/ruby/backward/2/long_long.h +super.o: $(hdrdir)/ruby/backward/2/stdalign.h +super.o: $(hdrdir)/ruby/backward/2/stdarg.h super.o: $(hdrdir)/ruby/defines.h super.o: $(hdrdir)/ruby/intern.h +super.o: $(hdrdir)/ruby/internal/anyargs.h +super.o: $(hdrdir)/ruby/internal/arithmetic.h +super.o: $(hdrdir)/ruby/internal/arithmetic/char.h +super.o: $(hdrdir)/ruby/internal/arithmetic/double.h +super.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +super.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/int.h +super.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/long.h +super.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +super.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/short.h +super.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +super.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +super.o: $(hdrdir)/ruby/internal/assume.h +super.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +super.o: $(hdrdir)/ruby/internal/attr/artificial.h +super.o: $(hdrdir)/ruby/internal/attr/cold.h +super.o: $(hdrdir)/ruby/internal/attr/const.h +super.o: $(hdrdir)/ruby/internal/attr/constexpr.h +super.o: $(hdrdir)/ruby/internal/attr/deprecated.h +super.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +super.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +super.o: $(hdrdir)/ruby/internal/attr/error.h +super.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +super.o: $(hdrdir)/ruby/internal/attr/forceinline.h +super.o: $(hdrdir)/ruby/internal/attr/format.h +super.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +super.o: $(hdrdir)/ruby/internal/attr/noalias.h +super.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +super.o: $(hdrdir)/ruby/internal/attr/noexcept.h +super.o: $(hdrdir)/ruby/internal/attr/noinline.h +super.o: $(hdrdir)/ruby/internal/attr/nonnull.h +super.o: $(hdrdir)/ruby/internal/attr/noreturn.h +super.o: $(hdrdir)/ruby/internal/attr/pure.h +super.o: $(hdrdir)/ruby/internal/attr/restrict.h +super.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +super.o: $(hdrdir)/ruby/internal/attr/warning.h +super.o: $(hdrdir)/ruby/internal/attr/weakref.h +super.o: $(hdrdir)/ruby/internal/cast.h +super.o: $(hdrdir)/ruby/internal/compiler_is.h +super.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +super.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +super.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +super.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +super.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +super.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +super.o: $(hdrdir)/ruby/internal/compiler_since.h +super.o: $(hdrdir)/ruby/internal/config.h +super.o: $(hdrdir)/ruby/internal/constant_p.h +super.o: $(hdrdir)/ruby/internal/core.h +super.o: $(hdrdir)/ruby/internal/core/rarray.h +super.o: $(hdrdir)/ruby/internal/core/rbasic.h +super.o: $(hdrdir)/ruby/internal/core/rbignum.h +super.o: $(hdrdir)/ruby/internal/core/rclass.h +super.o: $(hdrdir)/ruby/internal/core/rdata.h +super.o: $(hdrdir)/ruby/internal/core/rfile.h +super.o: $(hdrdir)/ruby/internal/core/rhash.h +super.o: $(hdrdir)/ruby/internal/core/robject.h +super.o: $(hdrdir)/ruby/internal/core/rregexp.h +super.o: $(hdrdir)/ruby/internal/core/rstring.h +super.o: $(hdrdir)/ruby/internal/core/rstruct.h +super.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +super.o: $(hdrdir)/ruby/internal/ctype.h +super.o: $(hdrdir)/ruby/internal/dllexport.h +super.o: $(hdrdir)/ruby/internal/dosish.h +super.o: $(hdrdir)/ruby/internal/error.h +super.o: $(hdrdir)/ruby/internal/eval.h +super.o: $(hdrdir)/ruby/internal/event.h +super.o: $(hdrdir)/ruby/internal/fl_type.h +super.o: $(hdrdir)/ruby/internal/gc.h +super.o: $(hdrdir)/ruby/internal/glob.h +super.o: $(hdrdir)/ruby/internal/globals.h +super.o: $(hdrdir)/ruby/internal/has/attribute.h +super.o: $(hdrdir)/ruby/internal/has/builtin.h +super.o: $(hdrdir)/ruby/internal/has/c_attribute.h +super.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +super.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +super.o: $(hdrdir)/ruby/internal/has/extension.h +super.o: $(hdrdir)/ruby/internal/has/feature.h +super.o: $(hdrdir)/ruby/internal/has/warning.h +super.o: $(hdrdir)/ruby/internal/intern/array.h +super.o: $(hdrdir)/ruby/internal/intern/bignum.h +super.o: $(hdrdir)/ruby/internal/intern/class.h +super.o: $(hdrdir)/ruby/internal/intern/compar.h +super.o: $(hdrdir)/ruby/internal/intern/complex.h +super.o: $(hdrdir)/ruby/internal/intern/cont.h +super.o: $(hdrdir)/ruby/internal/intern/dir.h +super.o: $(hdrdir)/ruby/internal/intern/enum.h +super.o: $(hdrdir)/ruby/internal/intern/enumerator.h +super.o: $(hdrdir)/ruby/internal/intern/error.h +super.o: $(hdrdir)/ruby/internal/intern/eval.h +super.o: $(hdrdir)/ruby/internal/intern/file.h +super.o: $(hdrdir)/ruby/internal/intern/gc.h +super.o: $(hdrdir)/ruby/internal/intern/hash.h +super.o: $(hdrdir)/ruby/internal/intern/io.h +super.o: $(hdrdir)/ruby/internal/intern/load.h +super.o: $(hdrdir)/ruby/internal/intern/marshal.h +super.o: $(hdrdir)/ruby/internal/intern/numeric.h +super.o: $(hdrdir)/ruby/internal/intern/object.h +super.o: $(hdrdir)/ruby/internal/intern/parse.h +super.o: $(hdrdir)/ruby/internal/intern/proc.h +super.o: $(hdrdir)/ruby/internal/intern/process.h +super.o: $(hdrdir)/ruby/internal/intern/random.h +super.o: $(hdrdir)/ruby/internal/intern/range.h +super.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +super.o: $(hdrdir)/ruby/internal/intern/sprintf.h +super.o: $(hdrdir)/ruby/internal/intern/string.h +super.o: $(hdrdir)/ruby/internal/intern/struct.h +super.o: $(hdrdir)/ruby/internal/intern/thread.h +super.o: $(hdrdir)/ruby/internal/intern/time.h +super.o: $(hdrdir)/ruby/internal/intern/variable.h +super.o: $(hdrdir)/ruby/internal/intern/vm.h +super.o: $(hdrdir)/ruby/internal/interpreter.h +super.o: $(hdrdir)/ruby/internal/iterator.h +super.o: $(hdrdir)/ruby/internal/memory.h +super.o: $(hdrdir)/ruby/internal/method.h +super.o: $(hdrdir)/ruby/internal/module.h +super.o: $(hdrdir)/ruby/internal/newobj.h +super.o: $(hdrdir)/ruby/internal/rgengc.h +super.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +super.o: $(hdrdir)/ruby/internal/value.h +super.o: $(hdrdir)/ruby/internal/value_type.h +super.o: $(hdrdir)/ruby/internal/variable.h +super.o: $(hdrdir)/ruby/internal/warning_push.h +super.o: $(hdrdir)/ruby/internal/xmalloc.h super.o: $(hdrdir)/ruby/missing.h super.o: $(hdrdir)/ruby/ruby.h super.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/random/depend b/ruby/ext/-test-/random/depend new file mode 100644 index 000000000..7cef34f11 --- /dev/null +++ b/ruby/ext/-test-/random/depend @@ -0,0 +1,320 @@ +# 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/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/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/gc.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/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/rgengc.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/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 +loop.o: $(RUBY_EXTCONF_H) +loop.o: $(arch_hdrdir)/ruby/config.h +loop.o: $(hdrdir)/ruby/assert.h +loop.o: $(hdrdir)/ruby/backward.h +loop.o: $(hdrdir)/ruby/backward/2/assume.h +loop.o: $(hdrdir)/ruby/backward/2/attributes.h +loop.o: $(hdrdir)/ruby/backward/2/bool.h +loop.o: $(hdrdir)/ruby/backward/2/inttypes.h +loop.o: $(hdrdir)/ruby/backward/2/limits.h +loop.o: $(hdrdir)/ruby/backward/2/long_long.h +loop.o: $(hdrdir)/ruby/backward/2/stdalign.h +loop.o: $(hdrdir)/ruby/backward/2/stdarg.h +loop.o: $(hdrdir)/ruby/defines.h +loop.o: $(hdrdir)/ruby/intern.h +loop.o: $(hdrdir)/ruby/internal/anyargs.h +loop.o: $(hdrdir)/ruby/internal/arithmetic.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/char.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/double.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/int.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/long.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/short.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +loop.o: $(hdrdir)/ruby/internal/assume.h +loop.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +loop.o: $(hdrdir)/ruby/internal/attr/artificial.h +loop.o: $(hdrdir)/ruby/internal/attr/cold.h +loop.o: $(hdrdir)/ruby/internal/attr/const.h +loop.o: $(hdrdir)/ruby/internal/attr/constexpr.h +loop.o: $(hdrdir)/ruby/internal/attr/deprecated.h +loop.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +loop.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +loop.o: $(hdrdir)/ruby/internal/attr/error.h +loop.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +loop.o: $(hdrdir)/ruby/internal/attr/forceinline.h +loop.o: $(hdrdir)/ruby/internal/attr/format.h +loop.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +loop.o: $(hdrdir)/ruby/internal/attr/noalias.h +loop.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +loop.o: $(hdrdir)/ruby/internal/attr/noexcept.h +loop.o: $(hdrdir)/ruby/internal/attr/noinline.h +loop.o: $(hdrdir)/ruby/internal/attr/nonnull.h +loop.o: $(hdrdir)/ruby/internal/attr/noreturn.h +loop.o: $(hdrdir)/ruby/internal/attr/pure.h +loop.o: $(hdrdir)/ruby/internal/attr/restrict.h +loop.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +loop.o: $(hdrdir)/ruby/internal/attr/warning.h +loop.o: $(hdrdir)/ruby/internal/attr/weakref.h +loop.o: $(hdrdir)/ruby/internal/cast.h +loop.o: $(hdrdir)/ruby/internal/compiler_is.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +loop.o: $(hdrdir)/ruby/internal/compiler_since.h +loop.o: $(hdrdir)/ruby/internal/config.h +loop.o: $(hdrdir)/ruby/internal/constant_p.h +loop.o: $(hdrdir)/ruby/internal/core.h +loop.o: $(hdrdir)/ruby/internal/core/rarray.h +loop.o: $(hdrdir)/ruby/internal/core/rbasic.h +loop.o: $(hdrdir)/ruby/internal/core/rbignum.h +loop.o: $(hdrdir)/ruby/internal/core/rclass.h +loop.o: $(hdrdir)/ruby/internal/core/rdata.h +loop.o: $(hdrdir)/ruby/internal/core/rfile.h +loop.o: $(hdrdir)/ruby/internal/core/rhash.h +loop.o: $(hdrdir)/ruby/internal/core/robject.h +loop.o: $(hdrdir)/ruby/internal/core/rregexp.h +loop.o: $(hdrdir)/ruby/internal/core/rstring.h +loop.o: $(hdrdir)/ruby/internal/core/rstruct.h +loop.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +loop.o: $(hdrdir)/ruby/internal/ctype.h +loop.o: $(hdrdir)/ruby/internal/dllexport.h +loop.o: $(hdrdir)/ruby/internal/dosish.h +loop.o: $(hdrdir)/ruby/internal/error.h +loop.o: $(hdrdir)/ruby/internal/eval.h +loop.o: $(hdrdir)/ruby/internal/event.h +loop.o: $(hdrdir)/ruby/internal/fl_type.h +loop.o: $(hdrdir)/ruby/internal/gc.h +loop.o: $(hdrdir)/ruby/internal/glob.h +loop.o: $(hdrdir)/ruby/internal/globals.h +loop.o: $(hdrdir)/ruby/internal/has/attribute.h +loop.o: $(hdrdir)/ruby/internal/has/builtin.h +loop.o: $(hdrdir)/ruby/internal/has/c_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/extension.h +loop.o: $(hdrdir)/ruby/internal/has/feature.h +loop.o: $(hdrdir)/ruby/internal/has/warning.h +loop.o: $(hdrdir)/ruby/internal/intern/array.h +loop.o: $(hdrdir)/ruby/internal/intern/bignum.h +loop.o: $(hdrdir)/ruby/internal/intern/class.h +loop.o: $(hdrdir)/ruby/internal/intern/compar.h +loop.o: $(hdrdir)/ruby/internal/intern/complex.h +loop.o: $(hdrdir)/ruby/internal/intern/cont.h +loop.o: $(hdrdir)/ruby/internal/intern/dir.h +loop.o: $(hdrdir)/ruby/internal/intern/enum.h +loop.o: $(hdrdir)/ruby/internal/intern/enumerator.h +loop.o: $(hdrdir)/ruby/internal/intern/error.h +loop.o: $(hdrdir)/ruby/internal/intern/eval.h +loop.o: $(hdrdir)/ruby/internal/intern/file.h +loop.o: $(hdrdir)/ruby/internal/intern/gc.h +loop.o: $(hdrdir)/ruby/internal/intern/hash.h +loop.o: $(hdrdir)/ruby/internal/intern/io.h +loop.o: $(hdrdir)/ruby/internal/intern/load.h +loop.o: $(hdrdir)/ruby/internal/intern/marshal.h +loop.o: $(hdrdir)/ruby/internal/intern/numeric.h +loop.o: $(hdrdir)/ruby/internal/intern/object.h +loop.o: $(hdrdir)/ruby/internal/intern/parse.h +loop.o: $(hdrdir)/ruby/internal/intern/proc.h +loop.o: $(hdrdir)/ruby/internal/intern/process.h +loop.o: $(hdrdir)/ruby/internal/intern/random.h +loop.o: $(hdrdir)/ruby/internal/intern/range.h +loop.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h +loop.o: $(hdrdir)/ruby/internal/intern/string.h +loop.o: $(hdrdir)/ruby/internal/intern/struct.h +loop.o: $(hdrdir)/ruby/internal/intern/thread.h +loop.o: $(hdrdir)/ruby/internal/intern/time.h +loop.o: $(hdrdir)/ruby/internal/intern/variable.h +loop.o: $(hdrdir)/ruby/internal/intern/vm.h +loop.o: $(hdrdir)/ruby/internal/interpreter.h +loop.o: $(hdrdir)/ruby/internal/iterator.h +loop.o: $(hdrdir)/ruby/internal/memory.h +loop.o: $(hdrdir)/ruby/internal/method.h +loop.o: $(hdrdir)/ruby/internal/module.h +loop.o: $(hdrdir)/ruby/internal/newobj.h +loop.o: $(hdrdir)/ruby/internal/rgengc.h +loop.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +loop.o: $(hdrdir)/ruby/internal/value.h +loop.o: $(hdrdir)/ruby/internal/value_type.h +loop.o: $(hdrdir)/ruby/internal/variable.h +loop.o: $(hdrdir)/ruby/internal/warning_push.h +loop.o: $(hdrdir)/ruby/internal/xmalloc.h +loop.o: $(hdrdir)/ruby/missing.h +loop.o: $(hdrdir)/ruby/random.h +loop.o: $(hdrdir)/ruby/ruby.h +loop.o: $(hdrdir)/ruby/st.h +loop.o: $(hdrdir)/ruby/subst.h +loop.o: loop.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/random/extconf.rb b/ruby/ext/-test-/random/extconf.rb new file mode 100644 index 000000000..d786b15db --- /dev/null +++ b/ruby/ext/-test-/random/extconf.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: false +require_relative "../auto_ext.rb" +auto_ext(inc: true) diff --git a/ruby/ext/-test-/random/init.c b/ruby/ext/-test-/random/init.c new file mode 100644 index 000000000..320cba0ad --- /dev/null +++ b/ruby/ext/-test-/random/init.c @@ -0,0 +1,11 @@ +#include "ruby.h" + +#define init(n) {void Init_random_##n(VALUE mod, VALUE base); Init_random_##n(mod, base);} + +void +Init_random(void) +{ + VALUE base = rb_const_get(rb_cRandom, rb_intern_const("Base")); + VALUE mod = rb_define_module_under(rb_define_module("Bug"), "Random"); + TEST_INIT_FUNCS(init); +} diff --git a/ruby/ext/-test-/random/loop.c b/ruby/ext/-test-/random/loop.c new file mode 100644 index 000000000..057209640 --- /dev/null +++ b/ruby/ext/-test-/random/loop.c @@ -0,0 +1,110 @@ +#include "ruby/random.h" + +static const uint32_t max_seeds = 1024; + +typedef struct { + rb_random_t base; + uint32_t num, idx, *buf; +} rand_loop_t; + +RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(loop); +static const rb_random_interface_t random_loop_if = { + 32, + RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop) +}; + +static size_t +random_loop_memsize(const void *ptr) +{ + const rand_loop_t *r = ptr; + return sizeof(*r) + r->num * sizeof(r->buf[0]); +} + +static rb_random_data_type_t random_loop_type = { + "random/loop", + { + rb_random_mark, + RUBY_TYPED_DEFAULT_FREE, + random_loop_memsize, + }, + RB_RANDOM_PARENT, + (void *)&random_loop_if, + RUBY_TYPED_FREE_IMMEDIATELY +}; + + +static VALUE +loop_alloc(VALUE klass) +{ + rand_loop_t *rnd; + VALUE obj = TypedData_Make_Struct(klass, rand_loop_t, &random_loop_type, rnd); + rb_random_base_init(&rnd->base); + return obj; +} + +static void +loop_init(rb_random_t *rnd, const uint32_t *buf, size_t len) +{ + rand_loop_t *r = (rand_loop_t *)rnd; + + if (len > max_seeds) len = max_seeds; + + REALLOC_N(r->buf, uint32_t, len); + MEMCPY(r->buf, buf, uint32_t, (r->num = (uint32_t)len)); +} + +static void +loop_get_bytes(rb_random_t *rnd, void *p, size_t n) +{ + uint8_t *buf = p; + while (n > 0) { + uint32_t x = loop_get_int32(rnd); + switch (n % 4) { + case 0: + *buf++ = (uint8_t)x; + n--; + /* FALLTHROUGH */ + case 3: + *buf++ = (uint8_t)x; + n--; + /* FALLTHROUGH */ + case 2: + *buf++ = (uint8_t)x; + n--; + /* FALLTHROUGH */ + case 1: + *buf++ = (uint8_t)x; + n--; + } + } +} + +static uint32_t +loop_get_int32(rb_random_t *rnd) +{ + rand_loop_t *r = (rand_loop_t *)rnd; + if (r->idx < r->num) { + uint32_t x = r->buf[r->idx++]; + if (r->idx >= r->num) r->idx = 0; + return x; + } + else if (r->num) { + return r->buf[r->idx = 0]; + } + return 0; +} + +static double +loop_get_real(rb_random_t *rnd, int excl) +{ + uint32_t a = loop_get_int32(rnd); + return ldexp(a, -16); +} + +void +Init_random_loop(VALUE mod, VALUE base) +{ + VALUE c = rb_define_class_under(mod, "Loop", base); + rb_define_alloc_func(c, loop_alloc); + RB_RANDOM_DATA_INIT_PARENT(random_loop_type); +} diff --git a/ruby/ext/-test-/rational/depend b/ruby/ext/-test-/rational/depend index 39e65933f..3fbe6e0a0 100644 --- a/ruby/ext/-test-/rational/depend +++ b/ruby/ext/-test-/rational/depend @@ -5,15 +5,173 @@ rat.o: rat.c $(top_srcdir)/internal.h # AUTOGENERATED DEPENDENCIES START rat.o: $(RUBY_EXTCONF_H) rat.o: $(arch_hdrdir)/ruby/config.h -rat.o: $(hdrdir)/ruby.h rat.o: $(hdrdir)/ruby/assert.h rat.o: $(hdrdir)/ruby/backward.h +rat.o: $(hdrdir)/ruby/backward/2/assume.h +rat.o: $(hdrdir)/ruby/backward/2/attributes.h +rat.o: $(hdrdir)/ruby/backward/2/bool.h +rat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +rat.o: $(hdrdir)/ruby/backward/2/inttypes.h +rat.o: $(hdrdir)/ruby/backward/2/limits.h +rat.o: $(hdrdir)/ruby/backward/2/long_long.h +rat.o: $(hdrdir)/ruby/backward/2/stdalign.h +rat.o: $(hdrdir)/ruby/backward/2/stdarg.h rat.o: $(hdrdir)/ruby/defines.h rat.o: $(hdrdir)/ruby/intern.h +rat.o: $(hdrdir)/ruby/internal/anyargs.h +rat.o: $(hdrdir)/ruby/internal/arithmetic.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rat.o: $(hdrdir)/ruby/internal/assume.h +rat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rat.o: $(hdrdir)/ruby/internal/attr/artificial.h +rat.o: $(hdrdir)/ruby/internal/attr/cold.h +rat.o: $(hdrdir)/ruby/internal/attr/const.h +rat.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rat.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rat.o: $(hdrdir)/ruby/internal/attr/error.h +rat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rat.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rat.o: $(hdrdir)/ruby/internal/attr/format.h +rat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rat.o: $(hdrdir)/ruby/internal/attr/noalias.h +rat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rat.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rat.o: $(hdrdir)/ruby/internal/attr/noinline.h +rat.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rat.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rat.o: $(hdrdir)/ruby/internal/attr/pure.h +rat.o: $(hdrdir)/ruby/internal/attr/restrict.h +rat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rat.o: $(hdrdir)/ruby/internal/attr/warning.h +rat.o: $(hdrdir)/ruby/internal/attr/weakref.h +rat.o: $(hdrdir)/ruby/internal/cast.h +rat.o: $(hdrdir)/ruby/internal/compiler_is.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rat.o: $(hdrdir)/ruby/internal/compiler_since.h +rat.o: $(hdrdir)/ruby/internal/config.h +rat.o: $(hdrdir)/ruby/internal/constant_p.h +rat.o: $(hdrdir)/ruby/internal/core.h +rat.o: $(hdrdir)/ruby/internal/core/rarray.h +rat.o: $(hdrdir)/ruby/internal/core/rbasic.h +rat.o: $(hdrdir)/ruby/internal/core/rbignum.h +rat.o: $(hdrdir)/ruby/internal/core/rclass.h +rat.o: $(hdrdir)/ruby/internal/core/rdata.h +rat.o: $(hdrdir)/ruby/internal/core/rfile.h +rat.o: $(hdrdir)/ruby/internal/core/rhash.h +rat.o: $(hdrdir)/ruby/internal/core/robject.h +rat.o: $(hdrdir)/ruby/internal/core/rregexp.h +rat.o: $(hdrdir)/ruby/internal/core/rstring.h +rat.o: $(hdrdir)/ruby/internal/core/rstruct.h +rat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rat.o: $(hdrdir)/ruby/internal/ctype.h +rat.o: $(hdrdir)/ruby/internal/dllexport.h +rat.o: $(hdrdir)/ruby/internal/dosish.h +rat.o: $(hdrdir)/ruby/internal/error.h +rat.o: $(hdrdir)/ruby/internal/eval.h +rat.o: $(hdrdir)/ruby/internal/event.h +rat.o: $(hdrdir)/ruby/internal/fl_type.h +rat.o: $(hdrdir)/ruby/internal/gc.h +rat.o: $(hdrdir)/ruby/internal/glob.h +rat.o: $(hdrdir)/ruby/internal/globals.h +rat.o: $(hdrdir)/ruby/internal/has/attribute.h +rat.o: $(hdrdir)/ruby/internal/has/builtin.h +rat.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rat.o: $(hdrdir)/ruby/internal/has/extension.h +rat.o: $(hdrdir)/ruby/internal/has/feature.h +rat.o: $(hdrdir)/ruby/internal/has/warning.h +rat.o: $(hdrdir)/ruby/internal/intern/array.h +rat.o: $(hdrdir)/ruby/internal/intern/bignum.h +rat.o: $(hdrdir)/ruby/internal/intern/class.h +rat.o: $(hdrdir)/ruby/internal/intern/compar.h +rat.o: $(hdrdir)/ruby/internal/intern/complex.h +rat.o: $(hdrdir)/ruby/internal/intern/cont.h +rat.o: $(hdrdir)/ruby/internal/intern/dir.h +rat.o: $(hdrdir)/ruby/internal/intern/enum.h +rat.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rat.o: $(hdrdir)/ruby/internal/intern/error.h +rat.o: $(hdrdir)/ruby/internal/intern/eval.h +rat.o: $(hdrdir)/ruby/internal/intern/file.h +rat.o: $(hdrdir)/ruby/internal/intern/gc.h +rat.o: $(hdrdir)/ruby/internal/intern/hash.h +rat.o: $(hdrdir)/ruby/internal/intern/io.h +rat.o: $(hdrdir)/ruby/internal/intern/load.h +rat.o: $(hdrdir)/ruby/internal/intern/marshal.h +rat.o: $(hdrdir)/ruby/internal/intern/numeric.h +rat.o: $(hdrdir)/ruby/internal/intern/object.h +rat.o: $(hdrdir)/ruby/internal/intern/parse.h +rat.o: $(hdrdir)/ruby/internal/intern/proc.h +rat.o: $(hdrdir)/ruby/internal/intern/process.h +rat.o: $(hdrdir)/ruby/internal/intern/random.h +rat.o: $(hdrdir)/ruby/internal/intern/range.h +rat.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rat.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rat.o: $(hdrdir)/ruby/internal/intern/string.h +rat.o: $(hdrdir)/ruby/internal/intern/struct.h +rat.o: $(hdrdir)/ruby/internal/intern/thread.h +rat.o: $(hdrdir)/ruby/internal/intern/time.h +rat.o: $(hdrdir)/ruby/internal/intern/variable.h +rat.o: $(hdrdir)/ruby/internal/intern/vm.h +rat.o: $(hdrdir)/ruby/internal/interpreter.h +rat.o: $(hdrdir)/ruby/internal/iterator.h +rat.o: $(hdrdir)/ruby/internal/memory.h +rat.o: $(hdrdir)/ruby/internal/method.h +rat.o: $(hdrdir)/ruby/internal/module.h +rat.o: $(hdrdir)/ruby/internal/newobj.h +rat.o: $(hdrdir)/ruby/internal/rgengc.h +rat.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rat.o: $(hdrdir)/ruby/internal/value.h +rat.o: $(hdrdir)/ruby/internal/value_type.h +rat.o: $(hdrdir)/ruby/internal/variable.h +rat.o: $(hdrdir)/ruby/internal/warning_push.h +rat.o: $(hdrdir)/ruby/internal/xmalloc.h rat.o: $(hdrdir)/ruby/missing.h rat.o: $(hdrdir)/ruby/ruby.h rat.o: $(hdrdir)/ruby/st.h rat.o: $(hdrdir)/ruby/subst.h -rat.o: $(top_srcdir)/internal.h +rat.o: $(top_srcdir)/internal/bignum.h +rat.o: $(top_srcdir)/internal/bits.h +rat.o: $(top_srcdir)/internal/compilers.h +rat.o: $(top_srcdir)/internal/fixnum.h +rat.o: $(top_srcdir)/internal/gc.h +rat.o: $(top_srcdir)/internal/numeric.h +rat.o: $(top_srcdir)/internal/rational.h +rat.o: $(top_srcdir)/internal/serial.h +rat.o: $(top_srcdir)/internal/static_assert.h +rat.o: $(top_srcdir)/internal/vm.h +rat.o: $(top_srcdir)/internal/warnings.h +rat.o: $(top_srcdir)/ruby_assert.h rat.o: rat.c # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/rational/rat.c b/ruby/ext/-test-/rational/rat.c index 772546fca..6489fe3d7 100644 --- a/ruby/ext/-test-/rational/rat.c +++ b/ruby/ext/-test-/rational/rat.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/rational.h" #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE @@ -14,14 +14,14 @@ big(VALUE x) #endif static VALUE -gcd_normal(VALUE x, VALUE y) +gcd_normal(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_gcd_normal(rb_to_int(x), rb_to_int(y))); } #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) static VALUE -gcd_gmp(VALUE x, VALUE y) +gcd_gmp(VALUE klass, VALUE x, VALUE y) { return rb_big_norm(rb_gcd_gmp(big(x), big(y))); } @@ -29,9 +29,20 @@ gcd_gmp(VALUE x, VALUE y) #define gcd_gmp rb_f_notimplement #endif +static VALUE +s_rational_raw(VALUE klass, VALUE x, VALUE y) +{ + return rb_rational_raw(x, y); +} + void -Init_rational(VALUE klass) +Init_rational(void) { - rb_define_method(rb_cInteger, "gcd_normal", gcd_normal, 1); - rb_define_method(rb_cInteger, "gcd_gmp", gcd_gmp, 1); + VALUE mBug = rb_define_module("Bug"); + VALUE klass = rb_define_module_under(mBug, "Rational"); + + rb_define_singleton_method(klass, "gcd_normal", gcd_normal, 2); + rb_define_singleton_method(klass, "gcd_gmp", gcd_gmp, 2); + + rb_define_singleton_method(klass, "raw", s_rational_raw, 2); } diff --git a/ruby/ext/-test-/rb_call_super_kw/depend b/ruby/ext/-test-/rb_call_super_kw/depend index f65dcf969..a8126a9ef 100644 --- a/ruby/ext/-test-/rb_call_super_kw/depend +++ b/ruby/ext/-test-/rb_call_super_kw/depend @@ -4,8 +4,155 @@ rb_call_super_kw.o: $(arch_hdrdir)/ruby/config.h rb_call_super_kw.o: $(hdrdir)/ruby.h rb_call_super_kw.o: $(hdrdir)/ruby/assert.h rb_call_super_kw.o: $(hdrdir)/ruby/backward.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/assume.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/attributes.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/bool.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/limits.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/long_long.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h +rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h rb_call_super_kw.o: $(hdrdir)/ruby/defines.h rb_call_super_kw.o: $(hdrdir)/ruby/intern.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/anyargs.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/assume.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/cold.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/const.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/error.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/format.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/pure.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/warning.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/cast.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_since.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/config.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/constant_p.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rarray.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rclass.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rdata.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rfile.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rhash.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/robject.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstring.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/ctype.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/dllexport.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/dosish.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/error.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/eval.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/event.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/fl_type.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/gc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/glob.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/globals.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/attribute.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/builtin.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/extension.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/feature.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/warning.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/array.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/class.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/compar.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/complex.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/cont.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/dir.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enum.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/error.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/eval.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/file.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/gc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/hash.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/io.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/load.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/object.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/parse.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/proc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/process.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/random.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/range.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/string.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/struct.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/thread.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/time.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/variable.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/vm.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/interpreter.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/iterator.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/memory.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/method.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/module.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/newobj.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/rgengc.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/value.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/value_type.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/variable.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/warning_push.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/xmalloc.h rb_call_super_kw.o: $(hdrdir)/ruby/missing.h rb_call_super_kw.o: $(hdrdir)/ruby/ruby.h rb_call_super_kw.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/recursion/depend b/ruby/ext/-test-/recursion/depend index bf8005724..12d7ae602 100644 --- a/ruby/ext/-test-/recursion/depend +++ b/ruby/ext/-test-/recursion/depend @@ -4,8 +4,155 @@ recursion.o: $(arch_hdrdir)/ruby/config.h recursion.o: $(hdrdir)/ruby.h recursion.o: $(hdrdir)/ruby/assert.h recursion.o: $(hdrdir)/ruby/backward.h +recursion.o: $(hdrdir)/ruby/backward/2/assume.h +recursion.o: $(hdrdir)/ruby/backward/2/attributes.h +recursion.o: $(hdrdir)/ruby/backward/2/bool.h +recursion.o: $(hdrdir)/ruby/backward/2/inttypes.h +recursion.o: $(hdrdir)/ruby/backward/2/limits.h +recursion.o: $(hdrdir)/ruby/backward/2/long_long.h +recursion.o: $(hdrdir)/ruby/backward/2/stdalign.h +recursion.o: $(hdrdir)/ruby/backward/2/stdarg.h recursion.o: $(hdrdir)/ruby/defines.h recursion.o: $(hdrdir)/ruby/intern.h +recursion.o: $(hdrdir)/ruby/internal/anyargs.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/char.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/double.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/int.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/long.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/short.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +recursion.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +recursion.o: $(hdrdir)/ruby/internal/assume.h +recursion.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +recursion.o: $(hdrdir)/ruby/internal/attr/artificial.h +recursion.o: $(hdrdir)/ruby/internal/attr/cold.h +recursion.o: $(hdrdir)/ruby/internal/attr/const.h +recursion.o: $(hdrdir)/ruby/internal/attr/constexpr.h +recursion.o: $(hdrdir)/ruby/internal/attr/deprecated.h +recursion.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +recursion.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +recursion.o: $(hdrdir)/ruby/internal/attr/error.h +recursion.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +recursion.o: $(hdrdir)/ruby/internal/attr/forceinline.h +recursion.o: $(hdrdir)/ruby/internal/attr/format.h +recursion.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +recursion.o: $(hdrdir)/ruby/internal/attr/noalias.h +recursion.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +recursion.o: $(hdrdir)/ruby/internal/attr/noexcept.h +recursion.o: $(hdrdir)/ruby/internal/attr/noinline.h +recursion.o: $(hdrdir)/ruby/internal/attr/nonnull.h +recursion.o: $(hdrdir)/ruby/internal/attr/noreturn.h +recursion.o: $(hdrdir)/ruby/internal/attr/pure.h +recursion.o: $(hdrdir)/ruby/internal/attr/restrict.h +recursion.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +recursion.o: $(hdrdir)/ruby/internal/attr/warning.h +recursion.o: $(hdrdir)/ruby/internal/attr/weakref.h +recursion.o: $(hdrdir)/ruby/internal/cast.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +recursion.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +recursion.o: $(hdrdir)/ruby/internal/compiler_since.h +recursion.o: $(hdrdir)/ruby/internal/config.h +recursion.o: $(hdrdir)/ruby/internal/constant_p.h +recursion.o: $(hdrdir)/ruby/internal/core.h +recursion.o: $(hdrdir)/ruby/internal/core/rarray.h +recursion.o: $(hdrdir)/ruby/internal/core/rbasic.h +recursion.o: $(hdrdir)/ruby/internal/core/rbignum.h +recursion.o: $(hdrdir)/ruby/internal/core/rclass.h +recursion.o: $(hdrdir)/ruby/internal/core/rdata.h +recursion.o: $(hdrdir)/ruby/internal/core/rfile.h +recursion.o: $(hdrdir)/ruby/internal/core/rhash.h +recursion.o: $(hdrdir)/ruby/internal/core/robject.h +recursion.o: $(hdrdir)/ruby/internal/core/rregexp.h +recursion.o: $(hdrdir)/ruby/internal/core/rstring.h +recursion.o: $(hdrdir)/ruby/internal/core/rstruct.h +recursion.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +recursion.o: $(hdrdir)/ruby/internal/ctype.h +recursion.o: $(hdrdir)/ruby/internal/dllexport.h +recursion.o: $(hdrdir)/ruby/internal/dosish.h +recursion.o: $(hdrdir)/ruby/internal/error.h +recursion.o: $(hdrdir)/ruby/internal/eval.h +recursion.o: $(hdrdir)/ruby/internal/event.h +recursion.o: $(hdrdir)/ruby/internal/fl_type.h +recursion.o: $(hdrdir)/ruby/internal/gc.h +recursion.o: $(hdrdir)/ruby/internal/glob.h +recursion.o: $(hdrdir)/ruby/internal/globals.h +recursion.o: $(hdrdir)/ruby/internal/has/attribute.h +recursion.o: $(hdrdir)/ruby/internal/has/builtin.h +recursion.o: $(hdrdir)/ruby/internal/has/c_attribute.h +recursion.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +recursion.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +recursion.o: $(hdrdir)/ruby/internal/has/extension.h +recursion.o: $(hdrdir)/ruby/internal/has/feature.h +recursion.o: $(hdrdir)/ruby/internal/has/warning.h +recursion.o: $(hdrdir)/ruby/internal/intern/array.h +recursion.o: $(hdrdir)/ruby/internal/intern/bignum.h +recursion.o: $(hdrdir)/ruby/internal/intern/class.h +recursion.o: $(hdrdir)/ruby/internal/intern/compar.h +recursion.o: $(hdrdir)/ruby/internal/intern/complex.h +recursion.o: $(hdrdir)/ruby/internal/intern/cont.h +recursion.o: $(hdrdir)/ruby/internal/intern/dir.h +recursion.o: $(hdrdir)/ruby/internal/intern/enum.h +recursion.o: $(hdrdir)/ruby/internal/intern/enumerator.h +recursion.o: $(hdrdir)/ruby/internal/intern/error.h +recursion.o: $(hdrdir)/ruby/internal/intern/eval.h +recursion.o: $(hdrdir)/ruby/internal/intern/file.h +recursion.o: $(hdrdir)/ruby/internal/intern/gc.h +recursion.o: $(hdrdir)/ruby/internal/intern/hash.h +recursion.o: $(hdrdir)/ruby/internal/intern/io.h +recursion.o: $(hdrdir)/ruby/internal/intern/load.h +recursion.o: $(hdrdir)/ruby/internal/intern/marshal.h +recursion.o: $(hdrdir)/ruby/internal/intern/numeric.h +recursion.o: $(hdrdir)/ruby/internal/intern/object.h +recursion.o: $(hdrdir)/ruby/internal/intern/parse.h +recursion.o: $(hdrdir)/ruby/internal/intern/proc.h +recursion.o: $(hdrdir)/ruby/internal/intern/process.h +recursion.o: $(hdrdir)/ruby/internal/intern/random.h +recursion.o: $(hdrdir)/ruby/internal/intern/range.h +recursion.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +recursion.o: $(hdrdir)/ruby/internal/intern/sprintf.h +recursion.o: $(hdrdir)/ruby/internal/intern/string.h +recursion.o: $(hdrdir)/ruby/internal/intern/struct.h +recursion.o: $(hdrdir)/ruby/internal/intern/thread.h +recursion.o: $(hdrdir)/ruby/internal/intern/time.h +recursion.o: $(hdrdir)/ruby/internal/intern/variable.h +recursion.o: $(hdrdir)/ruby/internal/intern/vm.h +recursion.o: $(hdrdir)/ruby/internal/interpreter.h +recursion.o: $(hdrdir)/ruby/internal/iterator.h +recursion.o: $(hdrdir)/ruby/internal/memory.h +recursion.o: $(hdrdir)/ruby/internal/method.h +recursion.o: $(hdrdir)/ruby/internal/module.h +recursion.o: $(hdrdir)/ruby/internal/newobj.h +recursion.o: $(hdrdir)/ruby/internal/rgengc.h +recursion.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +recursion.o: $(hdrdir)/ruby/internal/value.h +recursion.o: $(hdrdir)/ruby/internal/value_type.h +recursion.o: $(hdrdir)/ruby/internal/variable.h +recursion.o: $(hdrdir)/ruby/internal/warning_push.h +recursion.o: $(hdrdir)/ruby/internal/xmalloc.h recursion.o: $(hdrdir)/ruby/missing.h recursion.o: $(hdrdir)/ruby/ruby.h recursion.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/regexp/depend b/ruby/ext/-test-/regexp/depend index 7c88e1235..c46d87624 100644 --- a/ruby/ext/-test-/regexp/depend +++ b/ruby/ext/-test-/regexp/depend @@ -4,8 +4,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -16,8 +163,155 @@ parse_depth_limit.o: $(arch_hdrdir)/ruby/config.h parse_depth_limit.o: $(hdrdir)/ruby.h parse_depth_limit.o: $(hdrdir)/ruby/assert.h parse_depth_limit.o: $(hdrdir)/ruby/backward.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/assume.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/attributes.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/bool.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/inttypes.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/limits.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/long_long.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdalign.h +parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdarg.h parse_depth_limit.o: $(hdrdir)/ruby/defines.h parse_depth_limit.o: $(hdrdir)/ruby/intern.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/anyargs.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/char.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/double.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/int.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/short.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/assume.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/artificial.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/cold.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/const.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/constexpr.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/deprecated.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/error.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/forceinline.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/format.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noalias.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noexcept.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noinline.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nonnull.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noreturn.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/pure.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/restrict.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/warning.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/weakref.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/cast.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_since.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/config.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/constant_p.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rarray.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbasic.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbignum.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rclass.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rdata.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rfile.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rhash.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/robject.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rregexp.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstring.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstruct.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/ctype.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/dllexport.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/dosish.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/error.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/eval.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/event.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/fl_type.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/gc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/glob.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/globals.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/attribute.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/builtin.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/c_attribute.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/extension.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/feature.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/has/warning.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/array.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/bignum.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/class.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/compar.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/complex.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/cont.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/dir.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enum.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enumerator.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/error.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/eval.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/file.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/gc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/hash.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/io.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/load.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/marshal.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/numeric.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/object.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/parse.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/proc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/process.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/random.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/range.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/sprintf.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/string.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/struct.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/thread.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/time.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/variable.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/vm.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/interpreter.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/iterator.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/memory.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/method.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/module.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/newobj.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/rgengc.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/value.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/value_type.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/variable.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/warning_push.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/xmalloc.h parse_depth_limit.o: $(hdrdir)/ruby/missing.h parse_depth_limit.o: $(hdrdir)/ruby/onigmo.h parse_depth_limit.o: $(hdrdir)/ruby/ruby.h diff --git a/ruby/ext/-test-/scan_args/depend b/ruby/ext/-test-/scan_args/depend index c230961ae..99fd82ce3 100644 --- a/ruby/ext/-test-/scan_args/depend +++ b/ruby/ext/-test-/scan_args/depend @@ -4,8 +4,155 @@ scan_args.o: $(arch_hdrdir)/ruby/config.h scan_args.o: $(hdrdir)/ruby.h scan_args.o: $(hdrdir)/ruby/assert.h scan_args.o: $(hdrdir)/ruby/backward.h +scan_args.o: $(hdrdir)/ruby/backward/2/assume.h +scan_args.o: $(hdrdir)/ruby/backward/2/attributes.h +scan_args.o: $(hdrdir)/ruby/backward/2/bool.h +scan_args.o: $(hdrdir)/ruby/backward/2/inttypes.h +scan_args.o: $(hdrdir)/ruby/backward/2/limits.h +scan_args.o: $(hdrdir)/ruby/backward/2/long_long.h +scan_args.o: $(hdrdir)/ruby/backward/2/stdalign.h +scan_args.o: $(hdrdir)/ruby/backward/2/stdarg.h scan_args.o: $(hdrdir)/ruby/defines.h scan_args.o: $(hdrdir)/ruby/intern.h +scan_args.o: $(hdrdir)/ruby/internal/anyargs.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/char.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/double.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/int.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/short.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +scan_args.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +scan_args.o: $(hdrdir)/ruby/internal/assume.h +scan_args.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +scan_args.o: $(hdrdir)/ruby/internal/attr/artificial.h +scan_args.o: $(hdrdir)/ruby/internal/attr/cold.h +scan_args.o: $(hdrdir)/ruby/internal/attr/const.h +scan_args.o: $(hdrdir)/ruby/internal/attr/constexpr.h +scan_args.o: $(hdrdir)/ruby/internal/attr/deprecated.h +scan_args.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +scan_args.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +scan_args.o: $(hdrdir)/ruby/internal/attr/error.h +scan_args.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +scan_args.o: $(hdrdir)/ruby/internal/attr/forceinline.h +scan_args.o: $(hdrdir)/ruby/internal/attr/format.h +scan_args.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +scan_args.o: $(hdrdir)/ruby/internal/attr/noalias.h +scan_args.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +scan_args.o: $(hdrdir)/ruby/internal/attr/noexcept.h +scan_args.o: $(hdrdir)/ruby/internal/attr/noinline.h +scan_args.o: $(hdrdir)/ruby/internal/attr/nonnull.h +scan_args.o: $(hdrdir)/ruby/internal/attr/noreturn.h +scan_args.o: $(hdrdir)/ruby/internal/attr/pure.h +scan_args.o: $(hdrdir)/ruby/internal/attr/restrict.h +scan_args.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +scan_args.o: $(hdrdir)/ruby/internal/attr/warning.h +scan_args.o: $(hdrdir)/ruby/internal/attr/weakref.h +scan_args.o: $(hdrdir)/ruby/internal/cast.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +scan_args.o: $(hdrdir)/ruby/internal/compiler_since.h +scan_args.o: $(hdrdir)/ruby/internal/config.h +scan_args.o: $(hdrdir)/ruby/internal/constant_p.h +scan_args.o: $(hdrdir)/ruby/internal/core.h +scan_args.o: $(hdrdir)/ruby/internal/core/rarray.h +scan_args.o: $(hdrdir)/ruby/internal/core/rbasic.h +scan_args.o: $(hdrdir)/ruby/internal/core/rbignum.h +scan_args.o: $(hdrdir)/ruby/internal/core/rclass.h +scan_args.o: $(hdrdir)/ruby/internal/core/rdata.h +scan_args.o: $(hdrdir)/ruby/internal/core/rfile.h +scan_args.o: $(hdrdir)/ruby/internal/core/rhash.h +scan_args.o: $(hdrdir)/ruby/internal/core/robject.h +scan_args.o: $(hdrdir)/ruby/internal/core/rregexp.h +scan_args.o: $(hdrdir)/ruby/internal/core/rstring.h +scan_args.o: $(hdrdir)/ruby/internal/core/rstruct.h +scan_args.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +scan_args.o: $(hdrdir)/ruby/internal/ctype.h +scan_args.o: $(hdrdir)/ruby/internal/dllexport.h +scan_args.o: $(hdrdir)/ruby/internal/dosish.h +scan_args.o: $(hdrdir)/ruby/internal/error.h +scan_args.o: $(hdrdir)/ruby/internal/eval.h +scan_args.o: $(hdrdir)/ruby/internal/event.h +scan_args.o: $(hdrdir)/ruby/internal/fl_type.h +scan_args.o: $(hdrdir)/ruby/internal/gc.h +scan_args.o: $(hdrdir)/ruby/internal/glob.h +scan_args.o: $(hdrdir)/ruby/internal/globals.h +scan_args.o: $(hdrdir)/ruby/internal/has/attribute.h +scan_args.o: $(hdrdir)/ruby/internal/has/builtin.h +scan_args.o: $(hdrdir)/ruby/internal/has/c_attribute.h +scan_args.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +scan_args.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +scan_args.o: $(hdrdir)/ruby/internal/has/extension.h +scan_args.o: $(hdrdir)/ruby/internal/has/feature.h +scan_args.o: $(hdrdir)/ruby/internal/has/warning.h +scan_args.o: $(hdrdir)/ruby/internal/intern/array.h +scan_args.o: $(hdrdir)/ruby/internal/intern/bignum.h +scan_args.o: $(hdrdir)/ruby/internal/intern/class.h +scan_args.o: $(hdrdir)/ruby/internal/intern/compar.h +scan_args.o: $(hdrdir)/ruby/internal/intern/complex.h +scan_args.o: $(hdrdir)/ruby/internal/intern/cont.h +scan_args.o: $(hdrdir)/ruby/internal/intern/dir.h +scan_args.o: $(hdrdir)/ruby/internal/intern/enum.h +scan_args.o: $(hdrdir)/ruby/internal/intern/enumerator.h +scan_args.o: $(hdrdir)/ruby/internal/intern/error.h +scan_args.o: $(hdrdir)/ruby/internal/intern/eval.h +scan_args.o: $(hdrdir)/ruby/internal/intern/file.h +scan_args.o: $(hdrdir)/ruby/internal/intern/gc.h +scan_args.o: $(hdrdir)/ruby/internal/intern/hash.h +scan_args.o: $(hdrdir)/ruby/internal/intern/io.h +scan_args.o: $(hdrdir)/ruby/internal/intern/load.h +scan_args.o: $(hdrdir)/ruby/internal/intern/marshal.h +scan_args.o: $(hdrdir)/ruby/internal/intern/numeric.h +scan_args.o: $(hdrdir)/ruby/internal/intern/object.h +scan_args.o: $(hdrdir)/ruby/internal/intern/parse.h +scan_args.o: $(hdrdir)/ruby/internal/intern/proc.h +scan_args.o: $(hdrdir)/ruby/internal/intern/process.h +scan_args.o: $(hdrdir)/ruby/internal/intern/random.h +scan_args.o: $(hdrdir)/ruby/internal/intern/range.h +scan_args.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +scan_args.o: $(hdrdir)/ruby/internal/intern/sprintf.h +scan_args.o: $(hdrdir)/ruby/internal/intern/string.h +scan_args.o: $(hdrdir)/ruby/internal/intern/struct.h +scan_args.o: $(hdrdir)/ruby/internal/intern/thread.h +scan_args.o: $(hdrdir)/ruby/internal/intern/time.h +scan_args.o: $(hdrdir)/ruby/internal/intern/variable.h +scan_args.o: $(hdrdir)/ruby/internal/intern/vm.h +scan_args.o: $(hdrdir)/ruby/internal/interpreter.h +scan_args.o: $(hdrdir)/ruby/internal/iterator.h +scan_args.o: $(hdrdir)/ruby/internal/memory.h +scan_args.o: $(hdrdir)/ruby/internal/method.h +scan_args.o: $(hdrdir)/ruby/internal/module.h +scan_args.o: $(hdrdir)/ruby/internal/newobj.h +scan_args.o: $(hdrdir)/ruby/internal/rgengc.h +scan_args.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +scan_args.o: $(hdrdir)/ruby/internal/value.h +scan_args.o: $(hdrdir)/ruby/internal/value_type.h +scan_args.o: $(hdrdir)/ruby/internal/variable.h +scan_args.o: $(hdrdir)/ruby/internal/warning_push.h +scan_args.o: $(hdrdir)/ruby/internal/xmalloc.h scan_args.o: $(hdrdir)/ruby/missing.h scan_args.o: $(hdrdir)/ruby/ruby.h scan_args.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/scan_args/scan_args.c b/ruby/ext/-test-/scan_args/scan_args.c index 9c374da66..8696aad3c 100644 --- a/ruby/ext/-test-/scan_args/scan_args.c +++ b/ruby/ext/-test-/scan_args/scan_args.c @@ -259,15 +259,6 @@ scan_args_k_lead_opt_hash(int argc, VALUE *argv, VALUE self) return rb_ary_new_from_values(numberof(args), args); } -static VALUE -scan_args_e_lead_opt_hash(int argc, VALUE *argv, VALUE self) -{ - VALUE args[4]; - int n = rb_scan_args_kw(RB_SCAN_ARGS_EMPTY_KEYWORDS, argc, argv, "11:", args+1, args+2, args+3); - args[0] = INT2NUM(n); - return rb_ary_new_from_values(numberof(args), args); -} - static VALUE scan_args_n_lead_opt_hash(int argc, VALUE *argv, VALUE self) { @@ -310,6 +301,5 @@ Init_scan_args(void) rb_define_singleton_method(module, "opt_var_trail_hash", scan_args_opt_var_trail_hash, -1); rb_define_singleton_method(module, "lead_opt_var_trail_hash", scan_args_lead_opt_var_trail_hash, -1); rb_define_singleton_method(module, "k_lead_opt_hash", scan_args_k_lead_opt_hash, -1); - rb_define_singleton_method(module, "e_lead_opt_hash", scan_args_e_lead_opt_hash, -1); rb_define_singleton_method(module, "n_lead_opt_hash", scan_args_n_lead_opt_hash, -1); } diff --git a/ruby/ext/-test-/st/foreach/depend b/ruby/ext/-test-/st/foreach/depend index 42d3909f4..612823079 100644 --- a/ruby/ext/-test-/st/foreach/depend +++ b/ruby/ext/-test-/st/foreach/depend @@ -4,8 +4,155 @@ foreach.o: $(arch_hdrdir)/ruby/config.h foreach.o: $(hdrdir)/ruby.h foreach.o: $(hdrdir)/ruby/assert.h foreach.o: $(hdrdir)/ruby/backward.h +foreach.o: $(hdrdir)/ruby/backward/2/assume.h +foreach.o: $(hdrdir)/ruby/backward/2/attributes.h +foreach.o: $(hdrdir)/ruby/backward/2/bool.h +foreach.o: $(hdrdir)/ruby/backward/2/inttypes.h +foreach.o: $(hdrdir)/ruby/backward/2/limits.h +foreach.o: $(hdrdir)/ruby/backward/2/long_long.h +foreach.o: $(hdrdir)/ruby/backward/2/stdalign.h +foreach.o: $(hdrdir)/ruby/backward/2/stdarg.h foreach.o: $(hdrdir)/ruby/defines.h foreach.o: $(hdrdir)/ruby/intern.h +foreach.o: $(hdrdir)/ruby/internal/anyargs.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/char.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/double.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/int.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/long.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/short.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +foreach.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +foreach.o: $(hdrdir)/ruby/internal/assume.h +foreach.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +foreach.o: $(hdrdir)/ruby/internal/attr/artificial.h +foreach.o: $(hdrdir)/ruby/internal/attr/cold.h +foreach.o: $(hdrdir)/ruby/internal/attr/const.h +foreach.o: $(hdrdir)/ruby/internal/attr/constexpr.h +foreach.o: $(hdrdir)/ruby/internal/attr/deprecated.h +foreach.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +foreach.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +foreach.o: $(hdrdir)/ruby/internal/attr/error.h +foreach.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +foreach.o: $(hdrdir)/ruby/internal/attr/forceinline.h +foreach.o: $(hdrdir)/ruby/internal/attr/format.h +foreach.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +foreach.o: $(hdrdir)/ruby/internal/attr/noalias.h +foreach.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +foreach.o: $(hdrdir)/ruby/internal/attr/noexcept.h +foreach.o: $(hdrdir)/ruby/internal/attr/noinline.h +foreach.o: $(hdrdir)/ruby/internal/attr/nonnull.h +foreach.o: $(hdrdir)/ruby/internal/attr/noreturn.h +foreach.o: $(hdrdir)/ruby/internal/attr/pure.h +foreach.o: $(hdrdir)/ruby/internal/attr/restrict.h +foreach.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +foreach.o: $(hdrdir)/ruby/internal/attr/warning.h +foreach.o: $(hdrdir)/ruby/internal/attr/weakref.h +foreach.o: $(hdrdir)/ruby/internal/cast.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +foreach.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +foreach.o: $(hdrdir)/ruby/internal/compiler_since.h +foreach.o: $(hdrdir)/ruby/internal/config.h +foreach.o: $(hdrdir)/ruby/internal/constant_p.h +foreach.o: $(hdrdir)/ruby/internal/core.h +foreach.o: $(hdrdir)/ruby/internal/core/rarray.h +foreach.o: $(hdrdir)/ruby/internal/core/rbasic.h +foreach.o: $(hdrdir)/ruby/internal/core/rbignum.h +foreach.o: $(hdrdir)/ruby/internal/core/rclass.h +foreach.o: $(hdrdir)/ruby/internal/core/rdata.h +foreach.o: $(hdrdir)/ruby/internal/core/rfile.h +foreach.o: $(hdrdir)/ruby/internal/core/rhash.h +foreach.o: $(hdrdir)/ruby/internal/core/robject.h +foreach.o: $(hdrdir)/ruby/internal/core/rregexp.h +foreach.o: $(hdrdir)/ruby/internal/core/rstring.h +foreach.o: $(hdrdir)/ruby/internal/core/rstruct.h +foreach.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +foreach.o: $(hdrdir)/ruby/internal/ctype.h +foreach.o: $(hdrdir)/ruby/internal/dllexport.h +foreach.o: $(hdrdir)/ruby/internal/dosish.h +foreach.o: $(hdrdir)/ruby/internal/error.h +foreach.o: $(hdrdir)/ruby/internal/eval.h +foreach.o: $(hdrdir)/ruby/internal/event.h +foreach.o: $(hdrdir)/ruby/internal/fl_type.h +foreach.o: $(hdrdir)/ruby/internal/gc.h +foreach.o: $(hdrdir)/ruby/internal/glob.h +foreach.o: $(hdrdir)/ruby/internal/globals.h +foreach.o: $(hdrdir)/ruby/internal/has/attribute.h +foreach.o: $(hdrdir)/ruby/internal/has/builtin.h +foreach.o: $(hdrdir)/ruby/internal/has/c_attribute.h +foreach.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +foreach.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +foreach.o: $(hdrdir)/ruby/internal/has/extension.h +foreach.o: $(hdrdir)/ruby/internal/has/feature.h +foreach.o: $(hdrdir)/ruby/internal/has/warning.h +foreach.o: $(hdrdir)/ruby/internal/intern/array.h +foreach.o: $(hdrdir)/ruby/internal/intern/bignum.h +foreach.o: $(hdrdir)/ruby/internal/intern/class.h +foreach.o: $(hdrdir)/ruby/internal/intern/compar.h +foreach.o: $(hdrdir)/ruby/internal/intern/complex.h +foreach.o: $(hdrdir)/ruby/internal/intern/cont.h +foreach.o: $(hdrdir)/ruby/internal/intern/dir.h +foreach.o: $(hdrdir)/ruby/internal/intern/enum.h +foreach.o: $(hdrdir)/ruby/internal/intern/enumerator.h +foreach.o: $(hdrdir)/ruby/internal/intern/error.h +foreach.o: $(hdrdir)/ruby/internal/intern/eval.h +foreach.o: $(hdrdir)/ruby/internal/intern/file.h +foreach.o: $(hdrdir)/ruby/internal/intern/gc.h +foreach.o: $(hdrdir)/ruby/internal/intern/hash.h +foreach.o: $(hdrdir)/ruby/internal/intern/io.h +foreach.o: $(hdrdir)/ruby/internal/intern/load.h +foreach.o: $(hdrdir)/ruby/internal/intern/marshal.h +foreach.o: $(hdrdir)/ruby/internal/intern/numeric.h +foreach.o: $(hdrdir)/ruby/internal/intern/object.h +foreach.o: $(hdrdir)/ruby/internal/intern/parse.h +foreach.o: $(hdrdir)/ruby/internal/intern/proc.h +foreach.o: $(hdrdir)/ruby/internal/intern/process.h +foreach.o: $(hdrdir)/ruby/internal/intern/random.h +foreach.o: $(hdrdir)/ruby/internal/intern/range.h +foreach.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +foreach.o: $(hdrdir)/ruby/internal/intern/sprintf.h +foreach.o: $(hdrdir)/ruby/internal/intern/string.h +foreach.o: $(hdrdir)/ruby/internal/intern/struct.h +foreach.o: $(hdrdir)/ruby/internal/intern/thread.h +foreach.o: $(hdrdir)/ruby/internal/intern/time.h +foreach.o: $(hdrdir)/ruby/internal/intern/variable.h +foreach.o: $(hdrdir)/ruby/internal/intern/vm.h +foreach.o: $(hdrdir)/ruby/internal/interpreter.h +foreach.o: $(hdrdir)/ruby/internal/iterator.h +foreach.o: $(hdrdir)/ruby/internal/memory.h +foreach.o: $(hdrdir)/ruby/internal/method.h +foreach.o: $(hdrdir)/ruby/internal/module.h +foreach.o: $(hdrdir)/ruby/internal/newobj.h +foreach.o: $(hdrdir)/ruby/internal/rgengc.h +foreach.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +foreach.o: $(hdrdir)/ruby/internal/value.h +foreach.o: $(hdrdir)/ruby/internal/value_type.h +foreach.o: $(hdrdir)/ruby/internal/variable.h +foreach.o: $(hdrdir)/ruby/internal/warning_push.h +foreach.o: $(hdrdir)/ruby/internal/xmalloc.h foreach.o: $(hdrdir)/ruby/missing.h foreach.o: $(hdrdir)/ruby/ruby.h foreach.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/st/numhash/depend b/ruby/ext/-test-/st/numhash/depend index 98dcef881..b3475f5fc 100644 --- a/ruby/ext/-test-/st/numhash/depend +++ b/ruby/ext/-test-/st/numhash/depend @@ -4,8 +4,155 @@ numhash.o: $(arch_hdrdir)/ruby/config.h numhash.o: $(hdrdir)/ruby.h numhash.o: $(hdrdir)/ruby/assert.h numhash.o: $(hdrdir)/ruby/backward.h +numhash.o: $(hdrdir)/ruby/backward/2/assume.h +numhash.o: $(hdrdir)/ruby/backward/2/attributes.h +numhash.o: $(hdrdir)/ruby/backward/2/bool.h +numhash.o: $(hdrdir)/ruby/backward/2/inttypes.h +numhash.o: $(hdrdir)/ruby/backward/2/limits.h +numhash.o: $(hdrdir)/ruby/backward/2/long_long.h +numhash.o: $(hdrdir)/ruby/backward/2/stdalign.h +numhash.o: $(hdrdir)/ruby/backward/2/stdarg.h numhash.o: $(hdrdir)/ruby/defines.h numhash.o: $(hdrdir)/ruby/intern.h +numhash.o: $(hdrdir)/ruby/internal/anyargs.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/char.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/double.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/int.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/long.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/short.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +numhash.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +numhash.o: $(hdrdir)/ruby/internal/assume.h +numhash.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +numhash.o: $(hdrdir)/ruby/internal/attr/artificial.h +numhash.o: $(hdrdir)/ruby/internal/attr/cold.h +numhash.o: $(hdrdir)/ruby/internal/attr/const.h +numhash.o: $(hdrdir)/ruby/internal/attr/constexpr.h +numhash.o: $(hdrdir)/ruby/internal/attr/deprecated.h +numhash.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +numhash.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +numhash.o: $(hdrdir)/ruby/internal/attr/error.h +numhash.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +numhash.o: $(hdrdir)/ruby/internal/attr/forceinline.h +numhash.o: $(hdrdir)/ruby/internal/attr/format.h +numhash.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +numhash.o: $(hdrdir)/ruby/internal/attr/noalias.h +numhash.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +numhash.o: $(hdrdir)/ruby/internal/attr/noexcept.h +numhash.o: $(hdrdir)/ruby/internal/attr/noinline.h +numhash.o: $(hdrdir)/ruby/internal/attr/nonnull.h +numhash.o: $(hdrdir)/ruby/internal/attr/noreturn.h +numhash.o: $(hdrdir)/ruby/internal/attr/pure.h +numhash.o: $(hdrdir)/ruby/internal/attr/restrict.h +numhash.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +numhash.o: $(hdrdir)/ruby/internal/attr/warning.h +numhash.o: $(hdrdir)/ruby/internal/attr/weakref.h +numhash.o: $(hdrdir)/ruby/internal/cast.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +numhash.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +numhash.o: $(hdrdir)/ruby/internal/compiler_since.h +numhash.o: $(hdrdir)/ruby/internal/config.h +numhash.o: $(hdrdir)/ruby/internal/constant_p.h +numhash.o: $(hdrdir)/ruby/internal/core.h +numhash.o: $(hdrdir)/ruby/internal/core/rarray.h +numhash.o: $(hdrdir)/ruby/internal/core/rbasic.h +numhash.o: $(hdrdir)/ruby/internal/core/rbignum.h +numhash.o: $(hdrdir)/ruby/internal/core/rclass.h +numhash.o: $(hdrdir)/ruby/internal/core/rdata.h +numhash.o: $(hdrdir)/ruby/internal/core/rfile.h +numhash.o: $(hdrdir)/ruby/internal/core/rhash.h +numhash.o: $(hdrdir)/ruby/internal/core/robject.h +numhash.o: $(hdrdir)/ruby/internal/core/rregexp.h +numhash.o: $(hdrdir)/ruby/internal/core/rstring.h +numhash.o: $(hdrdir)/ruby/internal/core/rstruct.h +numhash.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +numhash.o: $(hdrdir)/ruby/internal/ctype.h +numhash.o: $(hdrdir)/ruby/internal/dllexport.h +numhash.o: $(hdrdir)/ruby/internal/dosish.h +numhash.o: $(hdrdir)/ruby/internal/error.h +numhash.o: $(hdrdir)/ruby/internal/eval.h +numhash.o: $(hdrdir)/ruby/internal/event.h +numhash.o: $(hdrdir)/ruby/internal/fl_type.h +numhash.o: $(hdrdir)/ruby/internal/gc.h +numhash.o: $(hdrdir)/ruby/internal/glob.h +numhash.o: $(hdrdir)/ruby/internal/globals.h +numhash.o: $(hdrdir)/ruby/internal/has/attribute.h +numhash.o: $(hdrdir)/ruby/internal/has/builtin.h +numhash.o: $(hdrdir)/ruby/internal/has/c_attribute.h +numhash.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +numhash.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +numhash.o: $(hdrdir)/ruby/internal/has/extension.h +numhash.o: $(hdrdir)/ruby/internal/has/feature.h +numhash.o: $(hdrdir)/ruby/internal/has/warning.h +numhash.o: $(hdrdir)/ruby/internal/intern/array.h +numhash.o: $(hdrdir)/ruby/internal/intern/bignum.h +numhash.o: $(hdrdir)/ruby/internal/intern/class.h +numhash.o: $(hdrdir)/ruby/internal/intern/compar.h +numhash.o: $(hdrdir)/ruby/internal/intern/complex.h +numhash.o: $(hdrdir)/ruby/internal/intern/cont.h +numhash.o: $(hdrdir)/ruby/internal/intern/dir.h +numhash.o: $(hdrdir)/ruby/internal/intern/enum.h +numhash.o: $(hdrdir)/ruby/internal/intern/enumerator.h +numhash.o: $(hdrdir)/ruby/internal/intern/error.h +numhash.o: $(hdrdir)/ruby/internal/intern/eval.h +numhash.o: $(hdrdir)/ruby/internal/intern/file.h +numhash.o: $(hdrdir)/ruby/internal/intern/gc.h +numhash.o: $(hdrdir)/ruby/internal/intern/hash.h +numhash.o: $(hdrdir)/ruby/internal/intern/io.h +numhash.o: $(hdrdir)/ruby/internal/intern/load.h +numhash.o: $(hdrdir)/ruby/internal/intern/marshal.h +numhash.o: $(hdrdir)/ruby/internal/intern/numeric.h +numhash.o: $(hdrdir)/ruby/internal/intern/object.h +numhash.o: $(hdrdir)/ruby/internal/intern/parse.h +numhash.o: $(hdrdir)/ruby/internal/intern/proc.h +numhash.o: $(hdrdir)/ruby/internal/intern/process.h +numhash.o: $(hdrdir)/ruby/internal/intern/random.h +numhash.o: $(hdrdir)/ruby/internal/intern/range.h +numhash.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +numhash.o: $(hdrdir)/ruby/internal/intern/sprintf.h +numhash.o: $(hdrdir)/ruby/internal/intern/string.h +numhash.o: $(hdrdir)/ruby/internal/intern/struct.h +numhash.o: $(hdrdir)/ruby/internal/intern/thread.h +numhash.o: $(hdrdir)/ruby/internal/intern/time.h +numhash.o: $(hdrdir)/ruby/internal/intern/variable.h +numhash.o: $(hdrdir)/ruby/internal/intern/vm.h +numhash.o: $(hdrdir)/ruby/internal/interpreter.h +numhash.o: $(hdrdir)/ruby/internal/iterator.h +numhash.o: $(hdrdir)/ruby/internal/memory.h +numhash.o: $(hdrdir)/ruby/internal/method.h +numhash.o: $(hdrdir)/ruby/internal/module.h +numhash.o: $(hdrdir)/ruby/internal/newobj.h +numhash.o: $(hdrdir)/ruby/internal/rgengc.h +numhash.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +numhash.o: $(hdrdir)/ruby/internal/value.h +numhash.o: $(hdrdir)/ruby/internal/value_type.h +numhash.o: $(hdrdir)/ruby/internal/variable.h +numhash.o: $(hdrdir)/ruby/internal/warning_push.h +numhash.o: $(hdrdir)/ruby/internal/xmalloc.h numhash.o: $(hdrdir)/ruby/missing.h numhash.o: $(hdrdir)/ruby/ruby.h numhash.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/st/numhash/numhash.c b/ruby/ext/-test-/st/numhash/numhash.c index 71eeed491..aa8015e86 100644 --- a/ruby/ext/-test-/st/numhash/numhash.c +++ b/ruby/ext/-test-/st/numhash/numhash.c @@ -125,7 +125,7 @@ numhash_delete_safe(VALUE self, VALUE key) void Init_numhash(void) { - VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cData); + VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cObject); rb_define_alloc_func(st, numhash_alloc); rb_define_method(st, "initialize", numhash_init, 0); rb_define_method(st, "[]", numhash_aref, 1); diff --git a/ruby/ext/-test-/st/update/depend b/ruby/ext/-test-/st/update/depend index 241e6f9e6..bbf97cbbf 100644 --- a/ruby/ext/-test-/st/update/depend +++ b/ruby/ext/-test-/st/update/depend @@ -4,8 +4,155 @@ update.o: $(arch_hdrdir)/ruby/config.h update.o: $(hdrdir)/ruby.h update.o: $(hdrdir)/ruby/assert.h update.o: $(hdrdir)/ruby/backward.h +update.o: $(hdrdir)/ruby/backward/2/assume.h +update.o: $(hdrdir)/ruby/backward/2/attributes.h +update.o: $(hdrdir)/ruby/backward/2/bool.h +update.o: $(hdrdir)/ruby/backward/2/inttypes.h +update.o: $(hdrdir)/ruby/backward/2/limits.h +update.o: $(hdrdir)/ruby/backward/2/long_long.h +update.o: $(hdrdir)/ruby/backward/2/stdalign.h +update.o: $(hdrdir)/ruby/backward/2/stdarg.h update.o: $(hdrdir)/ruby/defines.h update.o: $(hdrdir)/ruby/intern.h +update.o: $(hdrdir)/ruby/internal/anyargs.h +update.o: $(hdrdir)/ruby/internal/arithmetic.h +update.o: $(hdrdir)/ruby/internal/arithmetic/char.h +update.o: $(hdrdir)/ruby/internal/arithmetic/double.h +update.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +update.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/int.h +update.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/long.h +update.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +update.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/short.h +update.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +update.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +update.o: $(hdrdir)/ruby/internal/assume.h +update.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +update.o: $(hdrdir)/ruby/internal/attr/artificial.h +update.o: $(hdrdir)/ruby/internal/attr/cold.h +update.o: $(hdrdir)/ruby/internal/attr/const.h +update.o: $(hdrdir)/ruby/internal/attr/constexpr.h +update.o: $(hdrdir)/ruby/internal/attr/deprecated.h +update.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +update.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +update.o: $(hdrdir)/ruby/internal/attr/error.h +update.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +update.o: $(hdrdir)/ruby/internal/attr/forceinline.h +update.o: $(hdrdir)/ruby/internal/attr/format.h +update.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +update.o: $(hdrdir)/ruby/internal/attr/noalias.h +update.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +update.o: $(hdrdir)/ruby/internal/attr/noexcept.h +update.o: $(hdrdir)/ruby/internal/attr/noinline.h +update.o: $(hdrdir)/ruby/internal/attr/nonnull.h +update.o: $(hdrdir)/ruby/internal/attr/noreturn.h +update.o: $(hdrdir)/ruby/internal/attr/pure.h +update.o: $(hdrdir)/ruby/internal/attr/restrict.h +update.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +update.o: $(hdrdir)/ruby/internal/attr/warning.h +update.o: $(hdrdir)/ruby/internal/attr/weakref.h +update.o: $(hdrdir)/ruby/internal/cast.h +update.o: $(hdrdir)/ruby/internal/compiler_is.h +update.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +update.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +update.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +update.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +update.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +update.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +update.o: $(hdrdir)/ruby/internal/compiler_since.h +update.o: $(hdrdir)/ruby/internal/config.h +update.o: $(hdrdir)/ruby/internal/constant_p.h +update.o: $(hdrdir)/ruby/internal/core.h +update.o: $(hdrdir)/ruby/internal/core/rarray.h +update.o: $(hdrdir)/ruby/internal/core/rbasic.h +update.o: $(hdrdir)/ruby/internal/core/rbignum.h +update.o: $(hdrdir)/ruby/internal/core/rclass.h +update.o: $(hdrdir)/ruby/internal/core/rdata.h +update.o: $(hdrdir)/ruby/internal/core/rfile.h +update.o: $(hdrdir)/ruby/internal/core/rhash.h +update.o: $(hdrdir)/ruby/internal/core/robject.h +update.o: $(hdrdir)/ruby/internal/core/rregexp.h +update.o: $(hdrdir)/ruby/internal/core/rstring.h +update.o: $(hdrdir)/ruby/internal/core/rstruct.h +update.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +update.o: $(hdrdir)/ruby/internal/ctype.h +update.o: $(hdrdir)/ruby/internal/dllexport.h +update.o: $(hdrdir)/ruby/internal/dosish.h +update.o: $(hdrdir)/ruby/internal/error.h +update.o: $(hdrdir)/ruby/internal/eval.h +update.o: $(hdrdir)/ruby/internal/event.h +update.o: $(hdrdir)/ruby/internal/fl_type.h +update.o: $(hdrdir)/ruby/internal/gc.h +update.o: $(hdrdir)/ruby/internal/glob.h +update.o: $(hdrdir)/ruby/internal/globals.h +update.o: $(hdrdir)/ruby/internal/has/attribute.h +update.o: $(hdrdir)/ruby/internal/has/builtin.h +update.o: $(hdrdir)/ruby/internal/has/c_attribute.h +update.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +update.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +update.o: $(hdrdir)/ruby/internal/has/extension.h +update.o: $(hdrdir)/ruby/internal/has/feature.h +update.o: $(hdrdir)/ruby/internal/has/warning.h +update.o: $(hdrdir)/ruby/internal/intern/array.h +update.o: $(hdrdir)/ruby/internal/intern/bignum.h +update.o: $(hdrdir)/ruby/internal/intern/class.h +update.o: $(hdrdir)/ruby/internal/intern/compar.h +update.o: $(hdrdir)/ruby/internal/intern/complex.h +update.o: $(hdrdir)/ruby/internal/intern/cont.h +update.o: $(hdrdir)/ruby/internal/intern/dir.h +update.o: $(hdrdir)/ruby/internal/intern/enum.h +update.o: $(hdrdir)/ruby/internal/intern/enumerator.h +update.o: $(hdrdir)/ruby/internal/intern/error.h +update.o: $(hdrdir)/ruby/internal/intern/eval.h +update.o: $(hdrdir)/ruby/internal/intern/file.h +update.o: $(hdrdir)/ruby/internal/intern/gc.h +update.o: $(hdrdir)/ruby/internal/intern/hash.h +update.o: $(hdrdir)/ruby/internal/intern/io.h +update.o: $(hdrdir)/ruby/internal/intern/load.h +update.o: $(hdrdir)/ruby/internal/intern/marshal.h +update.o: $(hdrdir)/ruby/internal/intern/numeric.h +update.o: $(hdrdir)/ruby/internal/intern/object.h +update.o: $(hdrdir)/ruby/internal/intern/parse.h +update.o: $(hdrdir)/ruby/internal/intern/proc.h +update.o: $(hdrdir)/ruby/internal/intern/process.h +update.o: $(hdrdir)/ruby/internal/intern/random.h +update.o: $(hdrdir)/ruby/internal/intern/range.h +update.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +update.o: $(hdrdir)/ruby/internal/intern/sprintf.h +update.o: $(hdrdir)/ruby/internal/intern/string.h +update.o: $(hdrdir)/ruby/internal/intern/struct.h +update.o: $(hdrdir)/ruby/internal/intern/thread.h +update.o: $(hdrdir)/ruby/internal/intern/time.h +update.o: $(hdrdir)/ruby/internal/intern/variable.h +update.o: $(hdrdir)/ruby/internal/intern/vm.h +update.o: $(hdrdir)/ruby/internal/interpreter.h +update.o: $(hdrdir)/ruby/internal/iterator.h +update.o: $(hdrdir)/ruby/internal/memory.h +update.o: $(hdrdir)/ruby/internal/method.h +update.o: $(hdrdir)/ruby/internal/module.h +update.o: $(hdrdir)/ruby/internal/newobj.h +update.o: $(hdrdir)/ruby/internal/rgengc.h +update.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +update.o: $(hdrdir)/ruby/internal/value.h +update.o: $(hdrdir)/ruby/internal/value_type.h +update.o: $(hdrdir)/ruby/internal/variable.h +update.o: $(hdrdir)/ruby/internal/warning_push.h +update.o: $(hdrdir)/ruby/internal/xmalloc.h update.o: $(hdrdir)/ruby/missing.h update.o: $(hdrdir)/ruby/ruby.h update.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/string/capacity.c b/ruby/ext/-test-/string/capacity.c index f5277bf4e..33b2023fd 100644 --- a/ruby/ext/-test-/string/capacity.c +++ b/ruby/ext/-test-/string/capacity.c @@ -1,13 +1,14 @@ #include "ruby.h" -#include "internal.h" +#include "internal/string.h" static VALUE bug_str_capacity(VALUE klass, VALUE str) { - return - STR_EMBED_P(str) ? INT2FIX(RSTRING_EMBED_LEN_MAX) : \ - STR_SHARED_P(str) ? INT2FIX(0) : \ - LONG2FIX(RSTRING(str)->as.heap.aux.capa); + if (!STR_EMBED_P(str) && STR_SHARED_P(str)) { + return INT2FIX(0); + } + + return LONG2FIX(rb_str_capacity(str)); } void diff --git a/ruby/ext/-test-/string/coderange.c b/ruby/ext/-test-/string/coderange.c index 1342ce20d..bc998ca37 100644 --- a/ruby/ext/-test-/string/coderange.c +++ b/ruby/ext/-test-/string/coderange.c @@ -38,10 +38,10 @@ str_coderange_scan(VALUE str) void Init_string_coderange(VALUE klass) { - sym_7bit = ID2SYM(rb_intern("7bit")); - sym_valid = ID2SYM(rb_intern("valid")); - sym_unknown = ID2SYM(rb_intern("unknown")); - sym_broken = ID2SYM(rb_intern("broken")); + sym_7bit = ID2SYM(rb_intern_const("7bit")); + sym_valid = ID2SYM(rb_intern_const("valid")); + sym_unknown = ID2SYM(rb_intern_const("unknown")); + sym_broken = ID2SYM(rb_intern_const("broken")); rb_define_method(klass, "coderange", str_coderange, 0); rb_define_method(klass, "coderange_scan", str_coderange_scan, 0); } diff --git a/ruby/ext/-test-/string/cstr.c b/ruby/ext/-test-/string/cstr.c index 71eafdb70..1eadb8b4f 100644 --- a/ruby/ext/-test-/string/cstr.c +++ b/ruby/ext/-test-/string/cstr.c @@ -1,5 +1,6 @@ -#include "ruby/encoding.h" #include "internal.h" +#include "internal/string.h" +#include "ruby/encoding.h" static VALUE bug_str_cstr_term(VALUE str) @@ -61,9 +62,13 @@ bug_str_unterminated_substring(VALUE str, VALUE vbeg, VALUE vlen) if (RSTRING_LEN(str) < beg + len) rb_raise(rb_eIndexError, "end: %ld", beg + len); str = rb_str_new_shared(str); if (STR_EMBED_P(str)) { +#if USE_RVARGC + RSTRING(str)->as.embed.len = (short)len; +#else RSTRING(str)->basic.flags &= ~RSTRING_EMBED_LEN_MASK; RSTRING(str)->basic.flags |= len << RSTRING_EMBED_LEN_SHIFT; - memmove(RSTRING(str)->as.ary, RSTRING(str)->as.ary + beg, len); +#endif + memmove(RSTRING(str)->as.embed.ary, RSTRING(str)->as.embed.ary + beg, len); } else { RSTRING(str)->as.heap.ptr += beg; @@ -111,7 +116,11 @@ bug_str_s_cstr_noembed(VALUE self, VALUE str) Check_Type(str, T_STRING); FL_SET((str2), STR_NOEMBED); memcpy(buf, RSTRING_PTR(str), capacity); +#if USE_RVARGC + RBASIC(str2)->flags &= ~(STR_SHARED | FL_USER5 | FL_USER6); +#else RBASIC(str2)->flags &= ~RSTRING_EMBED_LEN_MASK; +#endif RSTRING(str2)->as.heap.aux.capa = capacity; RSTRING(str2)->as.heap.ptr = buf; RSTRING(str2)->as.heap.len = RSTRING_LEN(str); diff --git a/ruby/ext/-test-/string/depend b/ruby/ext/-test-/string/depend index f6888b5da..1e2e12313 100644 --- a/ruby/ext/-test-/string/depend +++ b/ruby/ext/-test-/string/depend @@ -4,21 +4,338 @@ capacity.o: $(arch_hdrdir)/ruby/config.h capacity.o: $(hdrdir)/ruby.h capacity.o: $(hdrdir)/ruby/assert.h capacity.o: $(hdrdir)/ruby/backward.h +capacity.o: $(hdrdir)/ruby/backward/2/assume.h +capacity.o: $(hdrdir)/ruby/backward/2/attributes.h +capacity.o: $(hdrdir)/ruby/backward/2/bool.h +capacity.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +capacity.o: $(hdrdir)/ruby/backward/2/inttypes.h +capacity.o: $(hdrdir)/ruby/backward/2/limits.h +capacity.o: $(hdrdir)/ruby/backward/2/long_long.h +capacity.o: $(hdrdir)/ruby/backward/2/stdalign.h +capacity.o: $(hdrdir)/ruby/backward/2/stdarg.h capacity.o: $(hdrdir)/ruby/defines.h +capacity.o: $(hdrdir)/ruby/encoding.h capacity.o: $(hdrdir)/ruby/intern.h +capacity.o: $(hdrdir)/ruby/internal/anyargs.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/char.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/double.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/int.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/long.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/short.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +capacity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +capacity.o: $(hdrdir)/ruby/internal/assume.h +capacity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +capacity.o: $(hdrdir)/ruby/internal/attr/artificial.h +capacity.o: $(hdrdir)/ruby/internal/attr/cold.h +capacity.o: $(hdrdir)/ruby/internal/attr/const.h +capacity.o: $(hdrdir)/ruby/internal/attr/constexpr.h +capacity.o: $(hdrdir)/ruby/internal/attr/deprecated.h +capacity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +capacity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +capacity.o: $(hdrdir)/ruby/internal/attr/error.h +capacity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +capacity.o: $(hdrdir)/ruby/internal/attr/forceinline.h +capacity.o: $(hdrdir)/ruby/internal/attr/format.h +capacity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +capacity.o: $(hdrdir)/ruby/internal/attr/noalias.h +capacity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +capacity.o: $(hdrdir)/ruby/internal/attr/noexcept.h +capacity.o: $(hdrdir)/ruby/internal/attr/noinline.h +capacity.o: $(hdrdir)/ruby/internal/attr/nonnull.h +capacity.o: $(hdrdir)/ruby/internal/attr/noreturn.h +capacity.o: $(hdrdir)/ruby/internal/attr/pure.h +capacity.o: $(hdrdir)/ruby/internal/attr/restrict.h +capacity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +capacity.o: $(hdrdir)/ruby/internal/attr/warning.h +capacity.o: $(hdrdir)/ruby/internal/attr/weakref.h +capacity.o: $(hdrdir)/ruby/internal/cast.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +capacity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +capacity.o: $(hdrdir)/ruby/internal/compiler_since.h +capacity.o: $(hdrdir)/ruby/internal/config.h +capacity.o: $(hdrdir)/ruby/internal/constant_p.h +capacity.o: $(hdrdir)/ruby/internal/core.h +capacity.o: $(hdrdir)/ruby/internal/core/rarray.h +capacity.o: $(hdrdir)/ruby/internal/core/rbasic.h +capacity.o: $(hdrdir)/ruby/internal/core/rbignum.h +capacity.o: $(hdrdir)/ruby/internal/core/rclass.h +capacity.o: $(hdrdir)/ruby/internal/core/rdata.h +capacity.o: $(hdrdir)/ruby/internal/core/rfile.h +capacity.o: $(hdrdir)/ruby/internal/core/rhash.h +capacity.o: $(hdrdir)/ruby/internal/core/robject.h +capacity.o: $(hdrdir)/ruby/internal/core/rregexp.h +capacity.o: $(hdrdir)/ruby/internal/core/rstring.h +capacity.o: $(hdrdir)/ruby/internal/core/rstruct.h +capacity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +capacity.o: $(hdrdir)/ruby/internal/ctype.h +capacity.o: $(hdrdir)/ruby/internal/dllexport.h +capacity.o: $(hdrdir)/ruby/internal/dosish.h +capacity.o: $(hdrdir)/ruby/internal/encoding/coderange.h +capacity.o: $(hdrdir)/ruby/internal/encoding/ctype.h +capacity.o: $(hdrdir)/ruby/internal/encoding/encoding.h +capacity.o: $(hdrdir)/ruby/internal/encoding/pathname.h +capacity.o: $(hdrdir)/ruby/internal/encoding/re.h +capacity.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +capacity.o: $(hdrdir)/ruby/internal/encoding/string.h +capacity.o: $(hdrdir)/ruby/internal/encoding/symbol.h +capacity.o: $(hdrdir)/ruby/internal/encoding/transcode.h +capacity.o: $(hdrdir)/ruby/internal/error.h +capacity.o: $(hdrdir)/ruby/internal/eval.h +capacity.o: $(hdrdir)/ruby/internal/event.h +capacity.o: $(hdrdir)/ruby/internal/fl_type.h +capacity.o: $(hdrdir)/ruby/internal/gc.h +capacity.o: $(hdrdir)/ruby/internal/glob.h +capacity.o: $(hdrdir)/ruby/internal/globals.h +capacity.o: $(hdrdir)/ruby/internal/has/attribute.h +capacity.o: $(hdrdir)/ruby/internal/has/builtin.h +capacity.o: $(hdrdir)/ruby/internal/has/c_attribute.h +capacity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +capacity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +capacity.o: $(hdrdir)/ruby/internal/has/extension.h +capacity.o: $(hdrdir)/ruby/internal/has/feature.h +capacity.o: $(hdrdir)/ruby/internal/has/warning.h +capacity.o: $(hdrdir)/ruby/internal/intern/array.h +capacity.o: $(hdrdir)/ruby/internal/intern/bignum.h +capacity.o: $(hdrdir)/ruby/internal/intern/class.h +capacity.o: $(hdrdir)/ruby/internal/intern/compar.h +capacity.o: $(hdrdir)/ruby/internal/intern/complex.h +capacity.o: $(hdrdir)/ruby/internal/intern/cont.h +capacity.o: $(hdrdir)/ruby/internal/intern/dir.h +capacity.o: $(hdrdir)/ruby/internal/intern/enum.h +capacity.o: $(hdrdir)/ruby/internal/intern/enumerator.h +capacity.o: $(hdrdir)/ruby/internal/intern/error.h +capacity.o: $(hdrdir)/ruby/internal/intern/eval.h +capacity.o: $(hdrdir)/ruby/internal/intern/file.h +capacity.o: $(hdrdir)/ruby/internal/intern/gc.h +capacity.o: $(hdrdir)/ruby/internal/intern/hash.h +capacity.o: $(hdrdir)/ruby/internal/intern/io.h +capacity.o: $(hdrdir)/ruby/internal/intern/load.h +capacity.o: $(hdrdir)/ruby/internal/intern/marshal.h +capacity.o: $(hdrdir)/ruby/internal/intern/numeric.h +capacity.o: $(hdrdir)/ruby/internal/intern/object.h +capacity.o: $(hdrdir)/ruby/internal/intern/parse.h +capacity.o: $(hdrdir)/ruby/internal/intern/proc.h +capacity.o: $(hdrdir)/ruby/internal/intern/process.h +capacity.o: $(hdrdir)/ruby/internal/intern/random.h +capacity.o: $(hdrdir)/ruby/internal/intern/range.h +capacity.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +capacity.o: $(hdrdir)/ruby/internal/intern/sprintf.h +capacity.o: $(hdrdir)/ruby/internal/intern/string.h +capacity.o: $(hdrdir)/ruby/internal/intern/struct.h +capacity.o: $(hdrdir)/ruby/internal/intern/thread.h +capacity.o: $(hdrdir)/ruby/internal/intern/time.h +capacity.o: $(hdrdir)/ruby/internal/intern/variable.h +capacity.o: $(hdrdir)/ruby/internal/intern/vm.h +capacity.o: $(hdrdir)/ruby/internal/interpreter.h +capacity.o: $(hdrdir)/ruby/internal/iterator.h +capacity.o: $(hdrdir)/ruby/internal/memory.h +capacity.o: $(hdrdir)/ruby/internal/method.h +capacity.o: $(hdrdir)/ruby/internal/module.h +capacity.o: $(hdrdir)/ruby/internal/newobj.h +capacity.o: $(hdrdir)/ruby/internal/rgengc.h +capacity.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +capacity.o: $(hdrdir)/ruby/internal/value.h +capacity.o: $(hdrdir)/ruby/internal/value_type.h +capacity.o: $(hdrdir)/ruby/internal/variable.h +capacity.o: $(hdrdir)/ruby/internal/warning_push.h +capacity.o: $(hdrdir)/ruby/internal/xmalloc.h capacity.o: $(hdrdir)/ruby/missing.h +capacity.o: $(hdrdir)/ruby/onigmo.h +capacity.o: $(hdrdir)/ruby/oniguruma.h capacity.o: $(hdrdir)/ruby/ruby.h capacity.o: $(hdrdir)/ruby/st.h capacity.o: $(hdrdir)/ruby/subst.h -capacity.o: $(top_srcdir)/internal.h +capacity.o: $(top_srcdir)/internal/compilers.h +capacity.o: $(top_srcdir)/internal/string.h capacity.o: capacity.c coderange.o: $(RUBY_EXTCONF_H) coderange.o: $(arch_hdrdir)/ruby/config.h coderange.o: $(hdrdir)/ruby/assert.h coderange.o: $(hdrdir)/ruby/backward.h +coderange.o: $(hdrdir)/ruby/backward/2/assume.h +coderange.o: $(hdrdir)/ruby/backward/2/attributes.h +coderange.o: $(hdrdir)/ruby/backward/2/bool.h +coderange.o: $(hdrdir)/ruby/backward/2/inttypes.h +coderange.o: $(hdrdir)/ruby/backward/2/limits.h +coderange.o: $(hdrdir)/ruby/backward/2/long_long.h +coderange.o: $(hdrdir)/ruby/backward/2/stdalign.h +coderange.o: $(hdrdir)/ruby/backward/2/stdarg.h coderange.o: $(hdrdir)/ruby/defines.h coderange.o: $(hdrdir)/ruby/encoding.h coderange.o: $(hdrdir)/ruby/intern.h +coderange.o: $(hdrdir)/ruby/internal/anyargs.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/char.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/double.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/int.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/long.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/short.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +coderange.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +coderange.o: $(hdrdir)/ruby/internal/assume.h +coderange.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +coderange.o: $(hdrdir)/ruby/internal/attr/artificial.h +coderange.o: $(hdrdir)/ruby/internal/attr/cold.h +coderange.o: $(hdrdir)/ruby/internal/attr/const.h +coderange.o: $(hdrdir)/ruby/internal/attr/constexpr.h +coderange.o: $(hdrdir)/ruby/internal/attr/deprecated.h +coderange.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +coderange.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +coderange.o: $(hdrdir)/ruby/internal/attr/error.h +coderange.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +coderange.o: $(hdrdir)/ruby/internal/attr/forceinline.h +coderange.o: $(hdrdir)/ruby/internal/attr/format.h +coderange.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +coderange.o: $(hdrdir)/ruby/internal/attr/noalias.h +coderange.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +coderange.o: $(hdrdir)/ruby/internal/attr/noexcept.h +coderange.o: $(hdrdir)/ruby/internal/attr/noinline.h +coderange.o: $(hdrdir)/ruby/internal/attr/nonnull.h +coderange.o: $(hdrdir)/ruby/internal/attr/noreturn.h +coderange.o: $(hdrdir)/ruby/internal/attr/pure.h +coderange.o: $(hdrdir)/ruby/internal/attr/restrict.h +coderange.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +coderange.o: $(hdrdir)/ruby/internal/attr/warning.h +coderange.o: $(hdrdir)/ruby/internal/attr/weakref.h +coderange.o: $(hdrdir)/ruby/internal/cast.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +coderange.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +coderange.o: $(hdrdir)/ruby/internal/compiler_since.h +coderange.o: $(hdrdir)/ruby/internal/config.h +coderange.o: $(hdrdir)/ruby/internal/constant_p.h +coderange.o: $(hdrdir)/ruby/internal/core.h +coderange.o: $(hdrdir)/ruby/internal/core/rarray.h +coderange.o: $(hdrdir)/ruby/internal/core/rbasic.h +coderange.o: $(hdrdir)/ruby/internal/core/rbignum.h +coderange.o: $(hdrdir)/ruby/internal/core/rclass.h +coderange.o: $(hdrdir)/ruby/internal/core/rdata.h +coderange.o: $(hdrdir)/ruby/internal/core/rfile.h +coderange.o: $(hdrdir)/ruby/internal/core/rhash.h +coderange.o: $(hdrdir)/ruby/internal/core/robject.h +coderange.o: $(hdrdir)/ruby/internal/core/rregexp.h +coderange.o: $(hdrdir)/ruby/internal/core/rstring.h +coderange.o: $(hdrdir)/ruby/internal/core/rstruct.h +coderange.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +coderange.o: $(hdrdir)/ruby/internal/ctype.h +coderange.o: $(hdrdir)/ruby/internal/dllexport.h +coderange.o: $(hdrdir)/ruby/internal/dosish.h +coderange.o: $(hdrdir)/ruby/internal/encoding/coderange.h +coderange.o: $(hdrdir)/ruby/internal/encoding/ctype.h +coderange.o: $(hdrdir)/ruby/internal/encoding/encoding.h +coderange.o: $(hdrdir)/ruby/internal/encoding/pathname.h +coderange.o: $(hdrdir)/ruby/internal/encoding/re.h +coderange.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +coderange.o: $(hdrdir)/ruby/internal/encoding/string.h +coderange.o: $(hdrdir)/ruby/internal/encoding/symbol.h +coderange.o: $(hdrdir)/ruby/internal/encoding/transcode.h +coderange.o: $(hdrdir)/ruby/internal/error.h +coderange.o: $(hdrdir)/ruby/internal/eval.h +coderange.o: $(hdrdir)/ruby/internal/event.h +coderange.o: $(hdrdir)/ruby/internal/fl_type.h +coderange.o: $(hdrdir)/ruby/internal/gc.h +coderange.o: $(hdrdir)/ruby/internal/glob.h +coderange.o: $(hdrdir)/ruby/internal/globals.h +coderange.o: $(hdrdir)/ruby/internal/has/attribute.h +coderange.o: $(hdrdir)/ruby/internal/has/builtin.h +coderange.o: $(hdrdir)/ruby/internal/has/c_attribute.h +coderange.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +coderange.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +coderange.o: $(hdrdir)/ruby/internal/has/extension.h +coderange.o: $(hdrdir)/ruby/internal/has/feature.h +coderange.o: $(hdrdir)/ruby/internal/has/warning.h +coderange.o: $(hdrdir)/ruby/internal/intern/array.h +coderange.o: $(hdrdir)/ruby/internal/intern/bignum.h +coderange.o: $(hdrdir)/ruby/internal/intern/class.h +coderange.o: $(hdrdir)/ruby/internal/intern/compar.h +coderange.o: $(hdrdir)/ruby/internal/intern/complex.h +coderange.o: $(hdrdir)/ruby/internal/intern/cont.h +coderange.o: $(hdrdir)/ruby/internal/intern/dir.h +coderange.o: $(hdrdir)/ruby/internal/intern/enum.h +coderange.o: $(hdrdir)/ruby/internal/intern/enumerator.h +coderange.o: $(hdrdir)/ruby/internal/intern/error.h +coderange.o: $(hdrdir)/ruby/internal/intern/eval.h +coderange.o: $(hdrdir)/ruby/internal/intern/file.h +coderange.o: $(hdrdir)/ruby/internal/intern/gc.h +coderange.o: $(hdrdir)/ruby/internal/intern/hash.h +coderange.o: $(hdrdir)/ruby/internal/intern/io.h +coderange.o: $(hdrdir)/ruby/internal/intern/load.h +coderange.o: $(hdrdir)/ruby/internal/intern/marshal.h +coderange.o: $(hdrdir)/ruby/internal/intern/numeric.h +coderange.o: $(hdrdir)/ruby/internal/intern/object.h +coderange.o: $(hdrdir)/ruby/internal/intern/parse.h +coderange.o: $(hdrdir)/ruby/internal/intern/proc.h +coderange.o: $(hdrdir)/ruby/internal/intern/process.h +coderange.o: $(hdrdir)/ruby/internal/intern/random.h +coderange.o: $(hdrdir)/ruby/internal/intern/range.h +coderange.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +coderange.o: $(hdrdir)/ruby/internal/intern/sprintf.h +coderange.o: $(hdrdir)/ruby/internal/intern/string.h +coderange.o: $(hdrdir)/ruby/internal/intern/struct.h +coderange.o: $(hdrdir)/ruby/internal/intern/thread.h +coderange.o: $(hdrdir)/ruby/internal/intern/time.h +coderange.o: $(hdrdir)/ruby/internal/intern/variable.h +coderange.o: $(hdrdir)/ruby/internal/intern/vm.h +coderange.o: $(hdrdir)/ruby/internal/interpreter.h +coderange.o: $(hdrdir)/ruby/internal/iterator.h +coderange.o: $(hdrdir)/ruby/internal/memory.h +coderange.o: $(hdrdir)/ruby/internal/method.h +coderange.o: $(hdrdir)/ruby/internal/module.h +coderange.o: $(hdrdir)/ruby/internal/newobj.h +coderange.o: $(hdrdir)/ruby/internal/rgengc.h +coderange.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +coderange.o: $(hdrdir)/ruby/internal/value.h +coderange.o: $(hdrdir)/ruby/internal/value_type.h +coderange.o: $(hdrdir)/ruby/internal/variable.h +coderange.o: $(hdrdir)/ruby/internal/warning_push.h +coderange.o: $(hdrdir)/ruby/internal/xmalloc.h coderange.o: $(hdrdir)/ruby/missing.h coderange.o: $(hdrdir)/ruby/onigmo.h coderange.o: $(hdrdir)/ruby/oniguruma.h @@ -28,12 +345,168 @@ coderange.o: $(hdrdir)/ruby/subst.h coderange.o: coderange.c cstr.o: $(RUBY_EXTCONF_H) cstr.o: $(arch_hdrdir)/ruby/config.h -cstr.o: $(hdrdir)/ruby.h cstr.o: $(hdrdir)/ruby/assert.h cstr.o: $(hdrdir)/ruby/backward.h +cstr.o: $(hdrdir)/ruby/backward/2/assume.h +cstr.o: $(hdrdir)/ruby/backward/2/attributes.h +cstr.o: $(hdrdir)/ruby/backward/2/bool.h +cstr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +cstr.o: $(hdrdir)/ruby/backward/2/inttypes.h +cstr.o: $(hdrdir)/ruby/backward/2/limits.h +cstr.o: $(hdrdir)/ruby/backward/2/long_long.h +cstr.o: $(hdrdir)/ruby/backward/2/stdalign.h +cstr.o: $(hdrdir)/ruby/backward/2/stdarg.h cstr.o: $(hdrdir)/ruby/defines.h cstr.o: $(hdrdir)/ruby/encoding.h cstr.o: $(hdrdir)/ruby/intern.h +cstr.o: $(hdrdir)/ruby/internal/anyargs.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/char.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/double.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/int.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/long.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/short.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +cstr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +cstr.o: $(hdrdir)/ruby/internal/assume.h +cstr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +cstr.o: $(hdrdir)/ruby/internal/attr/artificial.h +cstr.o: $(hdrdir)/ruby/internal/attr/cold.h +cstr.o: $(hdrdir)/ruby/internal/attr/const.h +cstr.o: $(hdrdir)/ruby/internal/attr/constexpr.h +cstr.o: $(hdrdir)/ruby/internal/attr/deprecated.h +cstr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +cstr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +cstr.o: $(hdrdir)/ruby/internal/attr/error.h +cstr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +cstr.o: $(hdrdir)/ruby/internal/attr/forceinline.h +cstr.o: $(hdrdir)/ruby/internal/attr/format.h +cstr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +cstr.o: $(hdrdir)/ruby/internal/attr/noalias.h +cstr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +cstr.o: $(hdrdir)/ruby/internal/attr/noexcept.h +cstr.o: $(hdrdir)/ruby/internal/attr/noinline.h +cstr.o: $(hdrdir)/ruby/internal/attr/nonnull.h +cstr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +cstr.o: $(hdrdir)/ruby/internal/attr/pure.h +cstr.o: $(hdrdir)/ruby/internal/attr/restrict.h +cstr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +cstr.o: $(hdrdir)/ruby/internal/attr/warning.h +cstr.o: $(hdrdir)/ruby/internal/attr/weakref.h +cstr.o: $(hdrdir)/ruby/internal/cast.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +cstr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +cstr.o: $(hdrdir)/ruby/internal/compiler_since.h +cstr.o: $(hdrdir)/ruby/internal/config.h +cstr.o: $(hdrdir)/ruby/internal/constant_p.h +cstr.o: $(hdrdir)/ruby/internal/core.h +cstr.o: $(hdrdir)/ruby/internal/core/rarray.h +cstr.o: $(hdrdir)/ruby/internal/core/rbasic.h +cstr.o: $(hdrdir)/ruby/internal/core/rbignum.h +cstr.o: $(hdrdir)/ruby/internal/core/rclass.h +cstr.o: $(hdrdir)/ruby/internal/core/rdata.h +cstr.o: $(hdrdir)/ruby/internal/core/rfile.h +cstr.o: $(hdrdir)/ruby/internal/core/rhash.h +cstr.o: $(hdrdir)/ruby/internal/core/robject.h +cstr.o: $(hdrdir)/ruby/internal/core/rregexp.h +cstr.o: $(hdrdir)/ruby/internal/core/rstring.h +cstr.o: $(hdrdir)/ruby/internal/core/rstruct.h +cstr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +cstr.o: $(hdrdir)/ruby/internal/ctype.h +cstr.o: $(hdrdir)/ruby/internal/dllexport.h +cstr.o: $(hdrdir)/ruby/internal/dosish.h +cstr.o: $(hdrdir)/ruby/internal/encoding/coderange.h +cstr.o: $(hdrdir)/ruby/internal/encoding/ctype.h +cstr.o: $(hdrdir)/ruby/internal/encoding/encoding.h +cstr.o: $(hdrdir)/ruby/internal/encoding/pathname.h +cstr.o: $(hdrdir)/ruby/internal/encoding/re.h +cstr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +cstr.o: $(hdrdir)/ruby/internal/encoding/string.h +cstr.o: $(hdrdir)/ruby/internal/encoding/symbol.h +cstr.o: $(hdrdir)/ruby/internal/encoding/transcode.h +cstr.o: $(hdrdir)/ruby/internal/error.h +cstr.o: $(hdrdir)/ruby/internal/eval.h +cstr.o: $(hdrdir)/ruby/internal/event.h +cstr.o: $(hdrdir)/ruby/internal/fl_type.h +cstr.o: $(hdrdir)/ruby/internal/gc.h +cstr.o: $(hdrdir)/ruby/internal/glob.h +cstr.o: $(hdrdir)/ruby/internal/globals.h +cstr.o: $(hdrdir)/ruby/internal/has/attribute.h +cstr.o: $(hdrdir)/ruby/internal/has/builtin.h +cstr.o: $(hdrdir)/ruby/internal/has/c_attribute.h +cstr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +cstr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +cstr.o: $(hdrdir)/ruby/internal/has/extension.h +cstr.o: $(hdrdir)/ruby/internal/has/feature.h +cstr.o: $(hdrdir)/ruby/internal/has/warning.h +cstr.o: $(hdrdir)/ruby/internal/intern/array.h +cstr.o: $(hdrdir)/ruby/internal/intern/bignum.h +cstr.o: $(hdrdir)/ruby/internal/intern/class.h +cstr.o: $(hdrdir)/ruby/internal/intern/compar.h +cstr.o: $(hdrdir)/ruby/internal/intern/complex.h +cstr.o: $(hdrdir)/ruby/internal/intern/cont.h +cstr.o: $(hdrdir)/ruby/internal/intern/dir.h +cstr.o: $(hdrdir)/ruby/internal/intern/enum.h +cstr.o: $(hdrdir)/ruby/internal/intern/enumerator.h +cstr.o: $(hdrdir)/ruby/internal/intern/error.h +cstr.o: $(hdrdir)/ruby/internal/intern/eval.h +cstr.o: $(hdrdir)/ruby/internal/intern/file.h +cstr.o: $(hdrdir)/ruby/internal/intern/gc.h +cstr.o: $(hdrdir)/ruby/internal/intern/hash.h +cstr.o: $(hdrdir)/ruby/internal/intern/io.h +cstr.o: $(hdrdir)/ruby/internal/intern/load.h +cstr.o: $(hdrdir)/ruby/internal/intern/marshal.h +cstr.o: $(hdrdir)/ruby/internal/intern/numeric.h +cstr.o: $(hdrdir)/ruby/internal/intern/object.h +cstr.o: $(hdrdir)/ruby/internal/intern/parse.h +cstr.o: $(hdrdir)/ruby/internal/intern/proc.h +cstr.o: $(hdrdir)/ruby/internal/intern/process.h +cstr.o: $(hdrdir)/ruby/internal/intern/random.h +cstr.o: $(hdrdir)/ruby/internal/intern/range.h +cstr.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +cstr.o: $(hdrdir)/ruby/internal/intern/sprintf.h +cstr.o: $(hdrdir)/ruby/internal/intern/string.h +cstr.o: $(hdrdir)/ruby/internal/intern/struct.h +cstr.o: $(hdrdir)/ruby/internal/intern/thread.h +cstr.o: $(hdrdir)/ruby/internal/intern/time.h +cstr.o: $(hdrdir)/ruby/internal/intern/variable.h +cstr.o: $(hdrdir)/ruby/internal/intern/vm.h +cstr.o: $(hdrdir)/ruby/internal/interpreter.h +cstr.o: $(hdrdir)/ruby/internal/iterator.h +cstr.o: $(hdrdir)/ruby/internal/memory.h +cstr.o: $(hdrdir)/ruby/internal/method.h +cstr.o: $(hdrdir)/ruby/internal/module.h +cstr.o: $(hdrdir)/ruby/internal/newobj.h +cstr.o: $(hdrdir)/ruby/internal/rgengc.h +cstr.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +cstr.o: $(hdrdir)/ruby/internal/value.h +cstr.o: $(hdrdir)/ruby/internal/value_type.h +cstr.o: $(hdrdir)/ruby/internal/variable.h +cstr.o: $(hdrdir)/ruby/internal/warning_push.h +cstr.o: $(hdrdir)/ruby/internal/xmalloc.h cstr.o: $(hdrdir)/ruby/missing.h cstr.o: $(hdrdir)/ruby/onigmo.h cstr.o: $(hdrdir)/ruby/oniguruma.h @@ -41,14 +514,163 @@ cstr.o: $(hdrdir)/ruby/ruby.h cstr.o: $(hdrdir)/ruby/st.h cstr.o: $(hdrdir)/ruby/subst.h cstr.o: $(top_srcdir)/internal.h +cstr.o: $(top_srcdir)/internal/compilers.h +cstr.o: $(top_srcdir)/internal/string.h cstr.o: cstr.c ellipsize.o: $(RUBY_EXTCONF_H) ellipsize.o: $(arch_hdrdir)/ruby/config.h ellipsize.o: $(hdrdir)/ruby.h ellipsize.o: $(hdrdir)/ruby/assert.h ellipsize.o: $(hdrdir)/ruby/backward.h +ellipsize.o: $(hdrdir)/ruby/backward/2/assume.h +ellipsize.o: $(hdrdir)/ruby/backward/2/attributes.h +ellipsize.o: $(hdrdir)/ruby/backward/2/bool.h +ellipsize.o: $(hdrdir)/ruby/backward/2/inttypes.h +ellipsize.o: $(hdrdir)/ruby/backward/2/limits.h +ellipsize.o: $(hdrdir)/ruby/backward/2/long_long.h +ellipsize.o: $(hdrdir)/ruby/backward/2/stdalign.h +ellipsize.o: $(hdrdir)/ruby/backward/2/stdarg.h ellipsize.o: $(hdrdir)/ruby/defines.h ellipsize.o: $(hdrdir)/ruby/intern.h +ellipsize.o: $(hdrdir)/ruby/internal/anyargs.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ellipsize.o: $(hdrdir)/ruby/internal/assume.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/artificial.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/cold.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/const.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/error.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/format.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/noalias.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/noinline.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/pure.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/restrict.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/warning.h +ellipsize.o: $(hdrdir)/ruby/internal/attr/weakref.h +ellipsize.o: $(hdrdir)/ruby/internal/cast.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ellipsize.o: $(hdrdir)/ruby/internal/compiler_since.h +ellipsize.o: $(hdrdir)/ruby/internal/config.h +ellipsize.o: $(hdrdir)/ruby/internal/constant_p.h +ellipsize.o: $(hdrdir)/ruby/internal/core.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rarray.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rbasic.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rbignum.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rclass.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rdata.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rfile.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rhash.h +ellipsize.o: $(hdrdir)/ruby/internal/core/robject.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rregexp.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rstring.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rstruct.h +ellipsize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ellipsize.o: $(hdrdir)/ruby/internal/ctype.h +ellipsize.o: $(hdrdir)/ruby/internal/dllexport.h +ellipsize.o: $(hdrdir)/ruby/internal/dosish.h +ellipsize.o: $(hdrdir)/ruby/internal/error.h +ellipsize.o: $(hdrdir)/ruby/internal/eval.h +ellipsize.o: $(hdrdir)/ruby/internal/event.h +ellipsize.o: $(hdrdir)/ruby/internal/fl_type.h +ellipsize.o: $(hdrdir)/ruby/internal/gc.h +ellipsize.o: $(hdrdir)/ruby/internal/glob.h +ellipsize.o: $(hdrdir)/ruby/internal/globals.h +ellipsize.o: $(hdrdir)/ruby/internal/has/attribute.h +ellipsize.o: $(hdrdir)/ruby/internal/has/builtin.h +ellipsize.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ellipsize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ellipsize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ellipsize.o: $(hdrdir)/ruby/internal/has/extension.h +ellipsize.o: $(hdrdir)/ruby/internal/has/feature.h +ellipsize.o: $(hdrdir)/ruby/internal/has/warning.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/array.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/bignum.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/class.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/compar.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/complex.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/cont.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/dir.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/enum.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/error.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/eval.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/file.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/gc.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/hash.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/io.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/load.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/marshal.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/numeric.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/object.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/parse.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/proc.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/process.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/random.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/range.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/string.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/struct.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/thread.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/time.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/variable.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/vm.h +ellipsize.o: $(hdrdir)/ruby/internal/interpreter.h +ellipsize.o: $(hdrdir)/ruby/internal/iterator.h +ellipsize.o: $(hdrdir)/ruby/internal/memory.h +ellipsize.o: $(hdrdir)/ruby/internal/method.h +ellipsize.o: $(hdrdir)/ruby/internal/module.h +ellipsize.o: $(hdrdir)/ruby/internal/newobj.h +ellipsize.o: $(hdrdir)/ruby/internal/rgengc.h +ellipsize.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ellipsize.o: $(hdrdir)/ruby/internal/value.h +ellipsize.o: $(hdrdir)/ruby/internal/value_type.h +ellipsize.o: $(hdrdir)/ruby/internal/variable.h +ellipsize.o: $(hdrdir)/ruby/internal/warning_push.h +ellipsize.o: $(hdrdir)/ruby/internal/xmalloc.h ellipsize.o: $(hdrdir)/ruby/missing.h ellipsize.o: $(hdrdir)/ruby/ruby.h ellipsize.o: $(hdrdir)/ruby/st.h @@ -59,9 +681,165 @@ enc_associate.o: $(arch_hdrdir)/ruby/config.h enc_associate.o: $(hdrdir)/ruby.h enc_associate.o: $(hdrdir)/ruby/assert.h enc_associate.o: $(hdrdir)/ruby/backward.h +enc_associate.o: $(hdrdir)/ruby/backward/2/assume.h +enc_associate.o: $(hdrdir)/ruby/backward/2/attributes.h +enc_associate.o: $(hdrdir)/ruby/backward/2/bool.h +enc_associate.o: $(hdrdir)/ruby/backward/2/inttypes.h +enc_associate.o: $(hdrdir)/ruby/backward/2/limits.h +enc_associate.o: $(hdrdir)/ruby/backward/2/long_long.h +enc_associate.o: $(hdrdir)/ruby/backward/2/stdalign.h +enc_associate.o: $(hdrdir)/ruby/backward/2/stdarg.h enc_associate.o: $(hdrdir)/ruby/defines.h enc_associate.o: $(hdrdir)/ruby/encoding.h enc_associate.o: $(hdrdir)/ruby/intern.h +enc_associate.o: $(hdrdir)/ruby/internal/anyargs.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/char.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/double.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/int.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/short.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +enc_associate.o: $(hdrdir)/ruby/internal/assume.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/artificial.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/cold.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/const.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/constexpr.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/deprecated.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/error.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/forceinline.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/format.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/noalias.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/noexcept.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/noinline.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/nonnull.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/noreturn.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/pure.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/restrict.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/warning.h +enc_associate.o: $(hdrdir)/ruby/internal/attr/weakref.h +enc_associate.o: $(hdrdir)/ruby/internal/cast.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +enc_associate.o: $(hdrdir)/ruby/internal/compiler_since.h +enc_associate.o: $(hdrdir)/ruby/internal/config.h +enc_associate.o: $(hdrdir)/ruby/internal/constant_p.h +enc_associate.o: $(hdrdir)/ruby/internal/core.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rarray.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rbasic.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rbignum.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rclass.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rdata.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rfile.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rhash.h +enc_associate.o: $(hdrdir)/ruby/internal/core/robject.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rregexp.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rstring.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rstruct.h +enc_associate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +enc_associate.o: $(hdrdir)/ruby/internal/ctype.h +enc_associate.o: $(hdrdir)/ruby/internal/dllexport.h +enc_associate.o: $(hdrdir)/ruby/internal/dosish.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/coderange.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/ctype.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/encoding.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/pathname.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/re.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/string.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/symbol.h +enc_associate.o: $(hdrdir)/ruby/internal/encoding/transcode.h +enc_associate.o: $(hdrdir)/ruby/internal/error.h +enc_associate.o: $(hdrdir)/ruby/internal/eval.h +enc_associate.o: $(hdrdir)/ruby/internal/event.h +enc_associate.o: $(hdrdir)/ruby/internal/fl_type.h +enc_associate.o: $(hdrdir)/ruby/internal/gc.h +enc_associate.o: $(hdrdir)/ruby/internal/glob.h +enc_associate.o: $(hdrdir)/ruby/internal/globals.h +enc_associate.o: $(hdrdir)/ruby/internal/has/attribute.h +enc_associate.o: $(hdrdir)/ruby/internal/has/builtin.h +enc_associate.o: $(hdrdir)/ruby/internal/has/c_attribute.h +enc_associate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +enc_associate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +enc_associate.o: $(hdrdir)/ruby/internal/has/extension.h +enc_associate.o: $(hdrdir)/ruby/internal/has/feature.h +enc_associate.o: $(hdrdir)/ruby/internal/has/warning.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/array.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/bignum.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/class.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/compar.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/complex.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/cont.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/dir.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/enum.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/enumerator.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/error.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/eval.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/file.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/gc.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/hash.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/io.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/load.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/marshal.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/numeric.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/object.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/parse.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/proc.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/process.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/random.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/range.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/sprintf.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/string.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/struct.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/thread.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/time.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/variable.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/vm.h +enc_associate.o: $(hdrdir)/ruby/internal/interpreter.h +enc_associate.o: $(hdrdir)/ruby/internal/iterator.h +enc_associate.o: $(hdrdir)/ruby/internal/memory.h +enc_associate.o: $(hdrdir)/ruby/internal/method.h +enc_associate.o: $(hdrdir)/ruby/internal/module.h +enc_associate.o: $(hdrdir)/ruby/internal/newobj.h +enc_associate.o: $(hdrdir)/ruby/internal/rgengc.h +enc_associate.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +enc_associate.o: $(hdrdir)/ruby/internal/value.h +enc_associate.o: $(hdrdir)/ruby/internal/value_type.h +enc_associate.o: $(hdrdir)/ruby/internal/variable.h +enc_associate.o: $(hdrdir)/ruby/internal/warning_push.h +enc_associate.o: $(hdrdir)/ruby/internal/xmalloc.h enc_associate.o: $(hdrdir)/ruby/missing.h enc_associate.o: $(hdrdir)/ruby/onigmo.h enc_associate.o: $(hdrdir)/ruby/oniguruma.h @@ -73,9 +851,165 @@ enc_str_buf_cat.o: $(RUBY_EXTCONF_H) enc_str_buf_cat.o: $(arch_hdrdir)/ruby/config.h enc_str_buf_cat.o: $(hdrdir)/ruby/assert.h enc_str_buf_cat.o: $(hdrdir)/ruby/backward.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/assume.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/attributes.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/bool.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/inttypes.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/limits.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/long_long.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdalign.h +enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdarg.h enc_str_buf_cat.o: $(hdrdir)/ruby/defines.h enc_str_buf_cat.o: $(hdrdir)/ruby/encoding.h enc_str_buf_cat.o: $(hdrdir)/ruby/intern.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/anyargs.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/char.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/double.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/int.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/short.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/assume.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/artificial.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/cold.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/const.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/constexpr.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/deprecated.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/error.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/forceinline.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/format.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noalias.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noexcept.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noinline.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nonnull.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noreturn.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/pure.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/restrict.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/warning.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/weakref.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/cast.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_since.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/config.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/constant_p.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rarray.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbasic.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbignum.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rclass.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rdata.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rfile.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rhash.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/robject.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rregexp.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstring.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstruct.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/ctype.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dllexport.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dosish.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/coderange.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/ctype.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/encoding.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/pathname.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/re.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/string.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/symbol.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/transcode.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/error.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/eval.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/event.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/fl_type.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/gc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/glob.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/globals.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/attribute.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/builtin.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/c_attribute.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/extension.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/feature.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/warning.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/array.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/bignum.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/class.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/compar.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/complex.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/cont.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/dir.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enum.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enumerator.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/error.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/eval.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/file.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/gc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/hash.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/io.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/load.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/marshal.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/numeric.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/object.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/parse.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/proc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/process.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/random.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/range.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/sprintf.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/string.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/struct.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/thread.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/time.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/variable.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/vm.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/interpreter.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/iterator.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/memory.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/method.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/module.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/newobj.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/rgengc.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value_type.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/variable.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/warning_push.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/xmalloc.h enc_str_buf_cat.o: $(hdrdir)/ruby/missing.h enc_str_buf_cat.o: $(hdrdir)/ruby/onigmo.h enc_str_buf_cat.o: $(hdrdir)/ruby/oniguruma.h @@ -88,9 +1022,168 @@ fstring.o: $(arch_hdrdir)/ruby/config.h fstring.o: $(hdrdir)/ruby.h fstring.o: $(hdrdir)/ruby/assert.h 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/inttypes.h +fstring.o: $(hdrdir)/ruby/backward/2/limits.h +fstring.o: $(hdrdir)/ruby/backward/2/long_long.h +fstring.o: $(hdrdir)/ruby/backward/2/stdalign.h +fstring.o: $(hdrdir)/ruby/backward/2/stdarg.h fstring.o: $(hdrdir)/ruby/defines.h +fstring.o: $(hdrdir)/ruby/encoding.h fstring.o: $(hdrdir)/ruby/intern.h +fstring.o: $(hdrdir)/ruby/internal/anyargs.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/char.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/double.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/int.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/long.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/short.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +fstring.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +fstring.o: $(hdrdir)/ruby/internal/assume.h +fstring.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +fstring.o: $(hdrdir)/ruby/internal/attr/artificial.h +fstring.o: $(hdrdir)/ruby/internal/attr/cold.h +fstring.o: $(hdrdir)/ruby/internal/attr/const.h +fstring.o: $(hdrdir)/ruby/internal/attr/constexpr.h +fstring.o: $(hdrdir)/ruby/internal/attr/deprecated.h +fstring.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +fstring.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +fstring.o: $(hdrdir)/ruby/internal/attr/error.h +fstring.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +fstring.o: $(hdrdir)/ruby/internal/attr/forceinline.h +fstring.o: $(hdrdir)/ruby/internal/attr/format.h +fstring.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +fstring.o: $(hdrdir)/ruby/internal/attr/noalias.h +fstring.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +fstring.o: $(hdrdir)/ruby/internal/attr/noexcept.h +fstring.o: $(hdrdir)/ruby/internal/attr/noinline.h +fstring.o: $(hdrdir)/ruby/internal/attr/nonnull.h +fstring.o: $(hdrdir)/ruby/internal/attr/noreturn.h +fstring.o: $(hdrdir)/ruby/internal/attr/pure.h +fstring.o: $(hdrdir)/ruby/internal/attr/restrict.h +fstring.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +fstring.o: $(hdrdir)/ruby/internal/attr/warning.h +fstring.o: $(hdrdir)/ruby/internal/attr/weakref.h +fstring.o: $(hdrdir)/ruby/internal/cast.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +fstring.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +fstring.o: $(hdrdir)/ruby/internal/compiler_since.h +fstring.o: $(hdrdir)/ruby/internal/config.h +fstring.o: $(hdrdir)/ruby/internal/constant_p.h +fstring.o: $(hdrdir)/ruby/internal/core.h +fstring.o: $(hdrdir)/ruby/internal/core/rarray.h +fstring.o: $(hdrdir)/ruby/internal/core/rbasic.h +fstring.o: $(hdrdir)/ruby/internal/core/rbignum.h +fstring.o: $(hdrdir)/ruby/internal/core/rclass.h +fstring.o: $(hdrdir)/ruby/internal/core/rdata.h +fstring.o: $(hdrdir)/ruby/internal/core/rfile.h +fstring.o: $(hdrdir)/ruby/internal/core/rhash.h +fstring.o: $(hdrdir)/ruby/internal/core/robject.h +fstring.o: $(hdrdir)/ruby/internal/core/rregexp.h +fstring.o: $(hdrdir)/ruby/internal/core/rstring.h +fstring.o: $(hdrdir)/ruby/internal/core/rstruct.h +fstring.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +fstring.o: $(hdrdir)/ruby/internal/ctype.h +fstring.o: $(hdrdir)/ruby/internal/dllexport.h +fstring.o: $(hdrdir)/ruby/internal/dosish.h +fstring.o: $(hdrdir)/ruby/internal/encoding/coderange.h +fstring.o: $(hdrdir)/ruby/internal/encoding/ctype.h +fstring.o: $(hdrdir)/ruby/internal/encoding/encoding.h +fstring.o: $(hdrdir)/ruby/internal/encoding/pathname.h +fstring.o: $(hdrdir)/ruby/internal/encoding/re.h +fstring.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +fstring.o: $(hdrdir)/ruby/internal/encoding/string.h +fstring.o: $(hdrdir)/ruby/internal/encoding/symbol.h +fstring.o: $(hdrdir)/ruby/internal/encoding/transcode.h +fstring.o: $(hdrdir)/ruby/internal/error.h +fstring.o: $(hdrdir)/ruby/internal/eval.h +fstring.o: $(hdrdir)/ruby/internal/event.h +fstring.o: $(hdrdir)/ruby/internal/fl_type.h +fstring.o: $(hdrdir)/ruby/internal/gc.h +fstring.o: $(hdrdir)/ruby/internal/glob.h +fstring.o: $(hdrdir)/ruby/internal/globals.h +fstring.o: $(hdrdir)/ruby/internal/has/attribute.h +fstring.o: $(hdrdir)/ruby/internal/has/builtin.h +fstring.o: $(hdrdir)/ruby/internal/has/c_attribute.h +fstring.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +fstring.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +fstring.o: $(hdrdir)/ruby/internal/has/extension.h +fstring.o: $(hdrdir)/ruby/internal/has/feature.h +fstring.o: $(hdrdir)/ruby/internal/has/warning.h +fstring.o: $(hdrdir)/ruby/internal/intern/array.h +fstring.o: $(hdrdir)/ruby/internal/intern/bignum.h +fstring.o: $(hdrdir)/ruby/internal/intern/class.h +fstring.o: $(hdrdir)/ruby/internal/intern/compar.h +fstring.o: $(hdrdir)/ruby/internal/intern/complex.h +fstring.o: $(hdrdir)/ruby/internal/intern/cont.h +fstring.o: $(hdrdir)/ruby/internal/intern/dir.h +fstring.o: $(hdrdir)/ruby/internal/intern/enum.h +fstring.o: $(hdrdir)/ruby/internal/intern/enumerator.h +fstring.o: $(hdrdir)/ruby/internal/intern/error.h +fstring.o: $(hdrdir)/ruby/internal/intern/eval.h +fstring.o: $(hdrdir)/ruby/internal/intern/file.h +fstring.o: $(hdrdir)/ruby/internal/intern/gc.h +fstring.o: $(hdrdir)/ruby/internal/intern/hash.h +fstring.o: $(hdrdir)/ruby/internal/intern/io.h +fstring.o: $(hdrdir)/ruby/internal/intern/load.h +fstring.o: $(hdrdir)/ruby/internal/intern/marshal.h +fstring.o: $(hdrdir)/ruby/internal/intern/numeric.h +fstring.o: $(hdrdir)/ruby/internal/intern/object.h +fstring.o: $(hdrdir)/ruby/internal/intern/parse.h +fstring.o: $(hdrdir)/ruby/internal/intern/proc.h +fstring.o: $(hdrdir)/ruby/internal/intern/process.h +fstring.o: $(hdrdir)/ruby/internal/intern/random.h +fstring.o: $(hdrdir)/ruby/internal/intern/range.h +fstring.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +fstring.o: $(hdrdir)/ruby/internal/intern/sprintf.h +fstring.o: $(hdrdir)/ruby/internal/intern/string.h +fstring.o: $(hdrdir)/ruby/internal/intern/struct.h +fstring.o: $(hdrdir)/ruby/internal/intern/thread.h +fstring.o: $(hdrdir)/ruby/internal/intern/time.h +fstring.o: $(hdrdir)/ruby/internal/intern/variable.h +fstring.o: $(hdrdir)/ruby/internal/intern/vm.h +fstring.o: $(hdrdir)/ruby/internal/interpreter.h +fstring.o: $(hdrdir)/ruby/internal/iterator.h +fstring.o: $(hdrdir)/ruby/internal/memory.h +fstring.o: $(hdrdir)/ruby/internal/method.h +fstring.o: $(hdrdir)/ruby/internal/module.h +fstring.o: $(hdrdir)/ruby/internal/newobj.h +fstring.o: $(hdrdir)/ruby/internal/rgengc.h +fstring.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +fstring.o: $(hdrdir)/ruby/internal/value.h +fstring.o: $(hdrdir)/ruby/internal/value_type.h +fstring.o: $(hdrdir)/ruby/internal/variable.h +fstring.o: $(hdrdir)/ruby/internal/warning_push.h +fstring.o: $(hdrdir)/ruby/internal/xmalloc.h fstring.o: $(hdrdir)/ruby/missing.h +fstring.o: $(hdrdir)/ruby/onigmo.h +fstring.o: $(hdrdir)/ruby/oniguruma.h fstring.o: $(hdrdir)/ruby/ruby.h fstring.o: $(hdrdir)/ruby/st.h fstring.o: $(hdrdir)/ruby/subst.h @@ -100,8 +1193,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -112,8 +1352,155 @@ modify.o: $(arch_hdrdir)/ruby/config.h modify.o: $(hdrdir)/ruby.h modify.o: $(hdrdir)/ruby/assert.h modify.o: $(hdrdir)/ruby/backward.h +modify.o: $(hdrdir)/ruby/backward/2/assume.h +modify.o: $(hdrdir)/ruby/backward/2/attributes.h +modify.o: $(hdrdir)/ruby/backward/2/bool.h +modify.o: $(hdrdir)/ruby/backward/2/inttypes.h +modify.o: $(hdrdir)/ruby/backward/2/limits.h +modify.o: $(hdrdir)/ruby/backward/2/long_long.h +modify.o: $(hdrdir)/ruby/backward/2/stdalign.h +modify.o: $(hdrdir)/ruby/backward/2/stdarg.h modify.o: $(hdrdir)/ruby/defines.h modify.o: $(hdrdir)/ruby/intern.h +modify.o: $(hdrdir)/ruby/internal/anyargs.h +modify.o: $(hdrdir)/ruby/internal/arithmetic.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/char.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/double.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/int.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/long.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/short.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +modify.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +modify.o: $(hdrdir)/ruby/internal/assume.h +modify.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +modify.o: $(hdrdir)/ruby/internal/attr/artificial.h +modify.o: $(hdrdir)/ruby/internal/attr/cold.h +modify.o: $(hdrdir)/ruby/internal/attr/const.h +modify.o: $(hdrdir)/ruby/internal/attr/constexpr.h +modify.o: $(hdrdir)/ruby/internal/attr/deprecated.h +modify.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +modify.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +modify.o: $(hdrdir)/ruby/internal/attr/error.h +modify.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +modify.o: $(hdrdir)/ruby/internal/attr/forceinline.h +modify.o: $(hdrdir)/ruby/internal/attr/format.h +modify.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +modify.o: $(hdrdir)/ruby/internal/attr/noalias.h +modify.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +modify.o: $(hdrdir)/ruby/internal/attr/noexcept.h +modify.o: $(hdrdir)/ruby/internal/attr/noinline.h +modify.o: $(hdrdir)/ruby/internal/attr/nonnull.h +modify.o: $(hdrdir)/ruby/internal/attr/noreturn.h +modify.o: $(hdrdir)/ruby/internal/attr/pure.h +modify.o: $(hdrdir)/ruby/internal/attr/restrict.h +modify.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +modify.o: $(hdrdir)/ruby/internal/attr/warning.h +modify.o: $(hdrdir)/ruby/internal/attr/weakref.h +modify.o: $(hdrdir)/ruby/internal/cast.h +modify.o: $(hdrdir)/ruby/internal/compiler_is.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +modify.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +modify.o: $(hdrdir)/ruby/internal/compiler_since.h +modify.o: $(hdrdir)/ruby/internal/config.h +modify.o: $(hdrdir)/ruby/internal/constant_p.h +modify.o: $(hdrdir)/ruby/internal/core.h +modify.o: $(hdrdir)/ruby/internal/core/rarray.h +modify.o: $(hdrdir)/ruby/internal/core/rbasic.h +modify.o: $(hdrdir)/ruby/internal/core/rbignum.h +modify.o: $(hdrdir)/ruby/internal/core/rclass.h +modify.o: $(hdrdir)/ruby/internal/core/rdata.h +modify.o: $(hdrdir)/ruby/internal/core/rfile.h +modify.o: $(hdrdir)/ruby/internal/core/rhash.h +modify.o: $(hdrdir)/ruby/internal/core/robject.h +modify.o: $(hdrdir)/ruby/internal/core/rregexp.h +modify.o: $(hdrdir)/ruby/internal/core/rstring.h +modify.o: $(hdrdir)/ruby/internal/core/rstruct.h +modify.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +modify.o: $(hdrdir)/ruby/internal/ctype.h +modify.o: $(hdrdir)/ruby/internal/dllexport.h +modify.o: $(hdrdir)/ruby/internal/dosish.h +modify.o: $(hdrdir)/ruby/internal/error.h +modify.o: $(hdrdir)/ruby/internal/eval.h +modify.o: $(hdrdir)/ruby/internal/event.h +modify.o: $(hdrdir)/ruby/internal/fl_type.h +modify.o: $(hdrdir)/ruby/internal/gc.h +modify.o: $(hdrdir)/ruby/internal/glob.h +modify.o: $(hdrdir)/ruby/internal/globals.h +modify.o: $(hdrdir)/ruby/internal/has/attribute.h +modify.o: $(hdrdir)/ruby/internal/has/builtin.h +modify.o: $(hdrdir)/ruby/internal/has/c_attribute.h +modify.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +modify.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +modify.o: $(hdrdir)/ruby/internal/has/extension.h +modify.o: $(hdrdir)/ruby/internal/has/feature.h +modify.o: $(hdrdir)/ruby/internal/has/warning.h +modify.o: $(hdrdir)/ruby/internal/intern/array.h +modify.o: $(hdrdir)/ruby/internal/intern/bignum.h +modify.o: $(hdrdir)/ruby/internal/intern/class.h +modify.o: $(hdrdir)/ruby/internal/intern/compar.h +modify.o: $(hdrdir)/ruby/internal/intern/complex.h +modify.o: $(hdrdir)/ruby/internal/intern/cont.h +modify.o: $(hdrdir)/ruby/internal/intern/dir.h +modify.o: $(hdrdir)/ruby/internal/intern/enum.h +modify.o: $(hdrdir)/ruby/internal/intern/enumerator.h +modify.o: $(hdrdir)/ruby/internal/intern/error.h +modify.o: $(hdrdir)/ruby/internal/intern/eval.h +modify.o: $(hdrdir)/ruby/internal/intern/file.h +modify.o: $(hdrdir)/ruby/internal/intern/gc.h +modify.o: $(hdrdir)/ruby/internal/intern/hash.h +modify.o: $(hdrdir)/ruby/internal/intern/io.h +modify.o: $(hdrdir)/ruby/internal/intern/load.h +modify.o: $(hdrdir)/ruby/internal/intern/marshal.h +modify.o: $(hdrdir)/ruby/internal/intern/numeric.h +modify.o: $(hdrdir)/ruby/internal/intern/object.h +modify.o: $(hdrdir)/ruby/internal/intern/parse.h +modify.o: $(hdrdir)/ruby/internal/intern/proc.h +modify.o: $(hdrdir)/ruby/internal/intern/process.h +modify.o: $(hdrdir)/ruby/internal/intern/random.h +modify.o: $(hdrdir)/ruby/internal/intern/range.h +modify.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +modify.o: $(hdrdir)/ruby/internal/intern/sprintf.h +modify.o: $(hdrdir)/ruby/internal/intern/string.h +modify.o: $(hdrdir)/ruby/internal/intern/struct.h +modify.o: $(hdrdir)/ruby/internal/intern/thread.h +modify.o: $(hdrdir)/ruby/internal/intern/time.h +modify.o: $(hdrdir)/ruby/internal/intern/variable.h +modify.o: $(hdrdir)/ruby/internal/intern/vm.h +modify.o: $(hdrdir)/ruby/internal/interpreter.h +modify.o: $(hdrdir)/ruby/internal/iterator.h +modify.o: $(hdrdir)/ruby/internal/memory.h +modify.o: $(hdrdir)/ruby/internal/method.h +modify.o: $(hdrdir)/ruby/internal/module.h +modify.o: $(hdrdir)/ruby/internal/newobj.h +modify.o: $(hdrdir)/ruby/internal/rgengc.h +modify.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +modify.o: $(hdrdir)/ruby/internal/value.h +modify.o: $(hdrdir)/ruby/internal/value_type.h +modify.o: $(hdrdir)/ruby/internal/variable.h +modify.o: $(hdrdir)/ruby/internal/warning_push.h +modify.o: $(hdrdir)/ruby/internal/xmalloc.h modify.o: $(hdrdir)/ruby/missing.h modify.o: $(hdrdir)/ruby/ruby.h modify.o: $(hdrdir)/ruby/st.h @@ -124,9 +1511,165 @@ new.o: $(arch_hdrdir)/ruby/config.h new.o: $(hdrdir)/ruby.h new.o: $(hdrdir)/ruby/assert.h new.o: $(hdrdir)/ruby/backward.h +new.o: $(hdrdir)/ruby/backward/2/assume.h +new.o: $(hdrdir)/ruby/backward/2/attributes.h +new.o: $(hdrdir)/ruby/backward/2/bool.h +new.o: $(hdrdir)/ruby/backward/2/inttypes.h +new.o: $(hdrdir)/ruby/backward/2/limits.h +new.o: $(hdrdir)/ruby/backward/2/long_long.h +new.o: $(hdrdir)/ruby/backward/2/stdalign.h +new.o: $(hdrdir)/ruby/backward/2/stdarg.h new.o: $(hdrdir)/ruby/defines.h new.o: $(hdrdir)/ruby/encoding.h new.o: $(hdrdir)/ruby/intern.h +new.o: $(hdrdir)/ruby/internal/anyargs.h +new.o: $(hdrdir)/ruby/internal/arithmetic.h +new.o: $(hdrdir)/ruby/internal/arithmetic/char.h +new.o: $(hdrdir)/ruby/internal/arithmetic/double.h +new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/int.h +new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/short.h +new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +new.o: $(hdrdir)/ruby/internal/assume.h +new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +new.o: $(hdrdir)/ruby/internal/attr/artificial.h +new.o: $(hdrdir)/ruby/internal/attr/cold.h +new.o: $(hdrdir)/ruby/internal/attr/const.h +new.o: $(hdrdir)/ruby/internal/attr/constexpr.h +new.o: $(hdrdir)/ruby/internal/attr/deprecated.h +new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +new.o: $(hdrdir)/ruby/internal/attr/error.h +new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +new.o: $(hdrdir)/ruby/internal/attr/forceinline.h +new.o: $(hdrdir)/ruby/internal/attr/format.h +new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +new.o: $(hdrdir)/ruby/internal/attr/noalias.h +new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +new.o: $(hdrdir)/ruby/internal/attr/noexcept.h +new.o: $(hdrdir)/ruby/internal/attr/noinline.h +new.o: $(hdrdir)/ruby/internal/attr/nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/noreturn.h +new.o: $(hdrdir)/ruby/internal/attr/pure.h +new.o: $(hdrdir)/ruby/internal/attr/restrict.h +new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/warning.h +new.o: $(hdrdir)/ruby/internal/attr/weakref.h +new.o: $(hdrdir)/ruby/internal/cast.h +new.o: $(hdrdir)/ruby/internal/compiler_is.h +new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +new.o: $(hdrdir)/ruby/internal/compiler_since.h +new.o: $(hdrdir)/ruby/internal/config.h +new.o: $(hdrdir)/ruby/internal/constant_p.h +new.o: $(hdrdir)/ruby/internal/core.h +new.o: $(hdrdir)/ruby/internal/core/rarray.h +new.o: $(hdrdir)/ruby/internal/core/rbasic.h +new.o: $(hdrdir)/ruby/internal/core/rbignum.h +new.o: $(hdrdir)/ruby/internal/core/rclass.h +new.o: $(hdrdir)/ruby/internal/core/rdata.h +new.o: $(hdrdir)/ruby/internal/core/rfile.h +new.o: $(hdrdir)/ruby/internal/core/rhash.h +new.o: $(hdrdir)/ruby/internal/core/robject.h +new.o: $(hdrdir)/ruby/internal/core/rregexp.h +new.o: $(hdrdir)/ruby/internal/core/rstring.h +new.o: $(hdrdir)/ruby/internal/core/rstruct.h +new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +new.o: $(hdrdir)/ruby/internal/ctype.h +new.o: $(hdrdir)/ruby/internal/dllexport.h +new.o: $(hdrdir)/ruby/internal/dosish.h +new.o: $(hdrdir)/ruby/internal/encoding/coderange.h +new.o: $(hdrdir)/ruby/internal/encoding/ctype.h +new.o: $(hdrdir)/ruby/internal/encoding/encoding.h +new.o: $(hdrdir)/ruby/internal/encoding/pathname.h +new.o: $(hdrdir)/ruby/internal/encoding/re.h +new.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +new.o: $(hdrdir)/ruby/internal/encoding/string.h +new.o: $(hdrdir)/ruby/internal/encoding/symbol.h +new.o: $(hdrdir)/ruby/internal/encoding/transcode.h +new.o: $(hdrdir)/ruby/internal/error.h +new.o: $(hdrdir)/ruby/internal/eval.h +new.o: $(hdrdir)/ruby/internal/event.h +new.o: $(hdrdir)/ruby/internal/fl_type.h +new.o: $(hdrdir)/ruby/internal/gc.h +new.o: $(hdrdir)/ruby/internal/glob.h +new.o: $(hdrdir)/ruby/internal/globals.h +new.o: $(hdrdir)/ruby/internal/has/attribute.h +new.o: $(hdrdir)/ruby/internal/has/builtin.h +new.o: $(hdrdir)/ruby/internal/has/c_attribute.h +new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +new.o: $(hdrdir)/ruby/internal/has/extension.h +new.o: $(hdrdir)/ruby/internal/has/feature.h +new.o: $(hdrdir)/ruby/internal/has/warning.h +new.o: $(hdrdir)/ruby/internal/intern/array.h +new.o: $(hdrdir)/ruby/internal/intern/bignum.h +new.o: $(hdrdir)/ruby/internal/intern/class.h +new.o: $(hdrdir)/ruby/internal/intern/compar.h +new.o: $(hdrdir)/ruby/internal/intern/complex.h +new.o: $(hdrdir)/ruby/internal/intern/cont.h +new.o: $(hdrdir)/ruby/internal/intern/dir.h +new.o: $(hdrdir)/ruby/internal/intern/enum.h +new.o: $(hdrdir)/ruby/internal/intern/enumerator.h +new.o: $(hdrdir)/ruby/internal/intern/error.h +new.o: $(hdrdir)/ruby/internal/intern/eval.h +new.o: $(hdrdir)/ruby/internal/intern/file.h +new.o: $(hdrdir)/ruby/internal/intern/gc.h +new.o: $(hdrdir)/ruby/internal/intern/hash.h +new.o: $(hdrdir)/ruby/internal/intern/io.h +new.o: $(hdrdir)/ruby/internal/intern/load.h +new.o: $(hdrdir)/ruby/internal/intern/marshal.h +new.o: $(hdrdir)/ruby/internal/intern/numeric.h +new.o: $(hdrdir)/ruby/internal/intern/object.h +new.o: $(hdrdir)/ruby/internal/intern/parse.h +new.o: $(hdrdir)/ruby/internal/intern/proc.h +new.o: $(hdrdir)/ruby/internal/intern/process.h +new.o: $(hdrdir)/ruby/internal/intern/random.h +new.o: $(hdrdir)/ruby/internal/intern/range.h +new.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +new.o: $(hdrdir)/ruby/internal/intern/sprintf.h +new.o: $(hdrdir)/ruby/internal/intern/string.h +new.o: $(hdrdir)/ruby/internal/intern/struct.h +new.o: $(hdrdir)/ruby/internal/intern/thread.h +new.o: $(hdrdir)/ruby/internal/intern/time.h +new.o: $(hdrdir)/ruby/internal/intern/variable.h +new.o: $(hdrdir)/ruby/internal/intern/vm.h +new.o: $(hdrdir)/ruby/internal/interpreter.h +new.o: $(hdrdir)/ruby/internal/iterator.h +new.o: $(hdrdir)/ruby/internal/memory.h +new.o: $(hdrdir)/ruby/internal/method.h +new.o: $(hdrdir)/ruby/internal/module.h +new.o: $(hdrdir)/ruby/internal/newobj.h +new.o: $(hdrdir)/ruby/internal/rgengc.h +new.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +new.o: $(hdrdir)/ruby/internal/value.h +new.o: $(hdrdir)/ruby/internal/value_type.h +new.o: $(hdrdir)/ruby/internal/variable.h +new.o: $(hdrdir)/ruby/internal/warning_push.h +new.o: $(hdrdir)/ruby/internal/xmalloc.h new.o: $(hdrdir)/ruby/missing.h new.o: $(hdrdir)/ruby/onigmo.h new.o: $(hdrdir)/ruby/oniguruma.h @@ -139,8 +1682,155 @@ nofree.o: $(arch_hdrdir)/ruby/config.h nofree.o: $(hdrdir)/ruby.h nofree.o: $(hdrdir)/ruby/assert.h nofree.o: $(hdrdir)/ruby/backward.h +nofree.o: $(hdrdir)/ruby/backward/2/assume.h +nofree.o: $(hdrdir)/ruby/backward/2/attributes.h +nofree.o: $(hdrdir)/ruby/backward/2/bool.h +nofree.o: $(hdrdir)/ruby/backward/2/inttypes.h +nofree.o: $(hdrdir)/ruby/backward/2/limits.h +nofree.o: $(hdrdir)/ruby/backward/2/long_long.h +nofree.o: $(hdrdir)/ruby/backward/2/stdalign.h +nofree.o: $(hdrdir)/ruby/backward/2/stdarg.h nofree.o: $(hdrdir)/ruby/defines.h nofree.o: $(hdrdir)/ruby/intern.h +nofree.o: $(hdrdir)/ruby/internal/anyargs.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/char.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/double.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/int.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/long.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/short.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +nofree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +nofree.o: $(hdrdir)/ruby/internal/assume.h +nofree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +nofree.o: $(hdrdir)/ruby/internal/attr/artificial.h +nofree.o: $(hdrdir)/ruby/internal/attr/cold.h +nofree.o: $(hdrdir)/ruby/internal/attr/const.h +nofree.o: $(hdrdir)/ruby/internal/attr/constexpr.h +nofree.o: $(hdrdir)/ruby/internal/attr/deprecated.h +nofree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +nofree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +nofree.o: $(hdrdir)/ruby/internal/attr/error.h +nofree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +nofree.o: $(hdrdir)/ruby/internal/attr/forceinline.h +nofree.o: $(hdrdir)/ruby/internal/attr/format.h +nofree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +nofree.o: $(hdrdir)/ruby/internal/attr/noalias.h +nofree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +nofree.o: $(hdrdir)/ruby/internal/attr/noexcept.h +nofree.o: $(hdrdir)/ruby/internal/attr/noinline.h +nofree.o: $(hdrdir)/ruby/internal/attr/nonnull.h +nofree.o: $(hdrdir)/ruby/internal/attr/noreturn.h +nofree.o: $(hdrdir)/ruby/internal/attr/pure.h +nofree.o: $(hdrdir)/ruby/internal/attr/restrict.h +nofree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +nofree.o: $(hdrdir)/ruby/internal/attr/warning.h +nofree.o: $(hdrdir)/ruby/internal/attr/weakref.h +nofree.o: $(hdrdir)/ruby/internal/cast.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +nofree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +nofree.o: $(hdrdir)/ruby/internal/compiler_since.h +nofree.o: $(hdrdir)/ruby/internal/config.h +nofree.o: $(hdrdir)/ruby/internal/constant_p.h +nofree.o: $(hdrdir)/ruby/internal/core.h +nofree.o: $(hdrdir)/ruby/internal/core/rarray.h +nofree.o: $(hdrdir)/ruby/internal/core/rbasic.h +nofree.o: $(hdrdir)/ruby/internal/core/rbignum.h +nofree.o: $(hdrdir)/ruby/internal/core/rclass.h +nofree.o: $(hdrdir)/ruby/internal/core/rdata.h +nofree.o: $(hdrdir)/ruby/internal/core/rfile.h +nofree.o: $(hdrdir)/ruby/internal/core/rhash.h +nofree.o: $(hdrdir)/ruby/internal/core/robject.h +nofree.o: $(hdrdir)/ruby/internal/core/rregexp.h +nofree.o: $(hdrdir)/ruby/internal/core/rstring.h +nofree.o: $(hdrdir)/ruby/internal/core/rstruct.h +nofree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +nofree.o: $(hdrdir)/ruby/internal/ctype.h +nofree.o: $(hdrdir)/ruby/internal/dllexport.h +nofree.o: $(hdrdir)/ruby/internal/dosish.h +nofree.o: $(hdrdir)/ruby/internal/error.h +nofree.o: $(hdrdir)/ruby/internal/eval.h +nofree.o: $(hdrdir)/ruby/internal/event.h +nofree.o: $(hdrdir)/ruby/internal/fl_type.h +nofree.o: $(hdrdir)/ruby/internal/gc.h +nofree.o: $(hdrdir)/ruby/internal/glob.h +nofree.o: $(hdrdir)/ruby/internal/globals.h +nofree.o: $(hdrdir)/ruby/internal/has/attribute.h +nofree.o: $(hdrdir)/ruby/internal/has/builtin.h +nofree.o: $(hdrdir)/ruby/internal/has/c_attribute.h +nofree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +nofree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +nofree.o: $(hdrdir)/ruby/internal/has/extension.h +nofree.o: $(hdrdir)/ruby/internal/has/feature.h +nofree.o: $(hdrdir)/ruby/internal/has/warning.h +nofree.o: $(hdrdir)/ruby/internal/intern/array.h +nofree.o: $(hdrdir)/ruby/internal/intern/bignum.h +nofree.o: $(hdrdir)/ruby/internal/intern/class.h +nofree.o: $(hdrdir)/ruby/internal/intern/compar.h +nofree.o: $(hdrdir)/ruby/internal/intern/complex.h +nofree.o: $(hdrdir)/ruby/internal/intern/cont.h +nofree.o: $(hdrdir)/ruby/internal/intern/dir.h +nofree.o: $(hdrdir)/ruby/internal/intern/enum.h +nofree.o: $(hdrdir)/ruby/internal/intern/enumerator.h +nofree.o: $(hdrdir)/ruby/internal/intern/error.h +nofree.o: $(hdrdir)/ruby/internal/intern/eval.h +nofree.o: $(hdrdir)/ruby/internal/intern/file.h +nofree.o: $(hdrdir)/ruby/internal/intern/gc.h +nofree.o: $(hdrdir)/ruby/internal/intern/hash.h +nofree.o: $(hdrdir)/ruby/internal/intern/io.h +nofree.o: $(hdrdir)/ruby/internal/intern/load.h +nofree.o: $(hdrdir)/ruby/internal/intern/marshal.h +nofree.o: $(hdrdir)/ruby/internal/intern/numeric.h +nofree.o: $(hdrdir)/ruby/internal/intern/object.h +nofree.o: $(hdrdir)/ruby/internal/intern/parse.h +nofree.o: $(hdrdir)/ruby/internal/intern/proc.h +nofree.o: $(hdrdir)/ruby/internal/intern/process.h +nofree.o: $(hdrdir)/ruby/internal/intern/random.h +nofree.o: $(hdrdir)/ruby/internal/intern/range.h +nofree.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +nofree.o: $(hdrdir)/ruby/internal/intern/sprintf.h +nofree.o: $(hdrdir)/ruby/internal/intern/string.h +nofree.o: $(hdrdir)/ruby/internal/intern/struct.h +nofree.o: $(hdrdir)/ruby/internal/intern/thread.h +nofree.o: $(hdrdir)/ruby/internal/intern/time.h +nofree.o: $(hdrdir)/ruby/internal/intern/variable.h +nofree.o: $(hdrdir)/ruby/internal/intern/vm.h +nofree.o: $(hdrdir)/ruby/internal/interpreter.h +nofree.o: $(hdrdir)/ruby/internal/iterator.h +nofree.o: $(hdrdir)/ruby/internal/memory.h +nofree.o: $(hdrdir)/ruby/internal/method.h +nofree.o: $(hdrdir)/ruby/internal/module.h +nofree.o: $(hdrdir)/ruby/internal/newobj.h +nofree.o: $(hdrdir)/ruby/internal/rgengc.h +nofree.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +nofree.o: $(hdrdir)/ruby/internal/value.h +nofree.o: $(hdrdir)/ruby/internal/value_type.h +nofree.o: $(hdrdir)/ruby/internal/variable.h +nofree.o: $(hdrdir)/ruby/internal/warning_push.h +nofree.o: $(hdrdir)/ruby/internal/xmalloc.h nofree.o: $(hdrdir)/ruby/missing.h nofree.o: $(hdrdir)/ruby/ruby.h nofree.o: $(hdrdir)/ruby/st.h @@ -148,25 +1838,339 @@ nofree.o: $(hdrdir)/ruby/subst.h nofree.o: nofree.c normalize.o: $(RUBY_EXTCONF_H) normalize.o: $(arch_hdrdir)/ruby/config.h -normalize.o: $(hdrdir)/ruby.h normalize.o: $(hdrdir)/ruby/assert.h normalize.o: $(hdrdir)/ruby/backward.h +normalize.o: $(hdrdir)/ruby/backward/2/assume.h +normalize.o: $(hdrdir)/ruby/backward/2/attributes.h +normalize.o: $(hdrdir)/ruby/backward/2/bool.h +normalize.o: $(hdrdir)/ruby/backward/2/inttypes.h +normalize.o: $(hdrdir)/ruby/backward/2/limits.h +normalize.o: $(hdrdir)/ruby/backward/2/long_long.h +normalize.o: $(hdrdir)/ruby/backward/2/stdalign.h +normalize.o: $(hdrdir)/ruby/backward/2/stdarg.h normalize.o: $(hdrdir)/ruby/defines.h +normalize.o: $(hdrdir)/ruby/encoding.h normalize.o: $(hdrdir)/ruby/intern.h +normalize.o: $(hdrdir)/ruby/internal/anyargs.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/char.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/double.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/int.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/long.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/short.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +normalize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +normalize.o: $(hdrdir)/ruby/internal/assume.h +normalize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +normalize.o: $(hdrdir)/ruby/internal/attr/artificial.h +normalize.o: $(hdrdir)/ruby/internal/attr/cold.h +normalize.o: $(hdrdir)/ruby/internal/attr/const.h +normalize.o: $(hdrdir)/ruby/internal/attr/constexpr.h +normalize.o: $(hdrdir)/ruby/internal/attr/deprecated.h +normalize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +normalize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +normalize.o: $(hdrdir)/ruby/internal/attr/error.h +normalize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +normalize.o: $(hdrdir)/ruby/internal/attr/forceinline.h +normalize.o: $(hdrdir)/ruby/internal/attr/format.h +normalize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +normalize.o: $(hdrdir)/ruby/internal/attr/noalias.h +normalize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +normalize.o: $(hdrdir)/ruby/internal/attr/noexcept.h +normalize.o: $(hdrdir)/ruby/internal/attr/noinline.h +normalize.o: $(hdrdir)/ruby/internal/attr/nonnull.h +normalize.o: $(hdrdir)/ruby/internal/attr/noreturn.h +normalize.o: $(hdrdir)/ruby/internal/attr/pure.h +normalize.o: $(hdrdir)/ruby/internal/attr/restrict.h +normalize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +normalize.o: $(hdrdir)/ruby/internal/attr/warning.h +normalize.o: $(hdrdir)/ruby/internal/attr/weakref.h +normalize.o: $(hdrdir)/ruby/internal/cast.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +normalize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +normalize.o: $(hdrdir)/ruby/internal/compiler_since.h +normalize.o: $(hdrdir)/ruby/internal/config.h +normalize.o: $(hdrdir)/ruby/internal/constant_p.h +normalize.o: $(hdrdir)/ruby/internal/core.h +normalize.o: $(hdrdir)/ruby/internal/core/rarray.h +normalize.o: $(hdrdir)/ruby/internal/core/rbasic.h +normalize.o: $(hdrdir)/ruby/internal/core/rbignum.h +normalize.o: $(hdrdir)/ruby/internal/core/rclass.h +normalize.o: $(hdrdir)/ruby/internal/core/rdata.h +normalize.o: $(hdrdir)/ruby/internal/core/rfile.h +normalize.o: $(hdrdir)/ruby/internal/core/rhash.h +normalize.o: $(hdrdir)/ruby/internal/core/robject.h +normalize.o: $(hdrdir)/ruby/internal/core/rregexp.h +normalize.o: $(hdrdir)/ruby/internal/core/rstring.h +normalize.o: $(hdrdir)/ruby/internal/core/rstruct.h +normalize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +normalize.o: $(hdrdir)/ruby/internal/ctype.h +normalize.o: $(hdrdir)/ruby/internal/dllexport.h +normalize.o: $(hdrdir)/ruby/internal/dosish.h +normalize.o: $(hdrdir)/ruby/internal/encoding/coderange.h +normalize.o: $(hdrdir)/ruby/internal/encoding/ctype.h +normalize.o: $(hdrdir)/ruby/internal/encoding/encoding.h +normalize.o: $(hdrdir)/ruby/internal/encoding/pathname.h +normalize.o: $(hdrdir)/ruby/internal/encoding/re.h +normalize.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +normalize.o: $(hdrdir)/ruby/internal/encoding/string.h +normalize.o: $(hdrdir)/ruby/internal/encoding/symbol.h +normalize.o: $(hdrdir)/ruby/internal/encoding/transcode.h +normalize.o: $(hdrdir)/ruby/internal/error.h +normalize.o: $(hdrdir)/ruby/internal/eval.h +normalize.o: $(hdrdir)/ruby/internal/event.h +normalize.o: $(hdrdir)/ruby/internal/fl_type.h +normalize.o: $(hdrdir)/ruby/internal/gc.h +normalize.o: $(hdrdir)/ruby/internal/glob.h +normalize.o: $(hdrdir)/ruby/internal/globals.h +normalize.o: $(hdrdir)/ruby/internal/has/attribute.h +normalize.o: $(hdrdir)/ruby/internal/has/builtin.h +normalize.o: $(hdrdir)/ruby/internal/has/c_attribute.h +normalize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +normalize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +normalize.o: $(hdrdir)/ruby/internal/has/extension.h +normalize.o: $(hdrdir)/ruby/internal/has/feature.h +normalize.o: $(hdrdir)/ruby/internal/has/warning.h +normalize.o: $(hdrdir)/ruby/internal/intern/array.h +normalize.o: $(hdrdir)/ruby/internal/intern/bignum.h +normalize.o: $(hdrdir)/ruby/internal/intern/class.h +normalize.o: $(hdrdir)/ruby/internal/intern/compar.h +normalize.o: $(hdrdir)/ruby/internal/intern/complex.h +normalize.o: $(hdrdir)/ruby/internal/intern/cont.h +normalize.o: $(hdrdir)/ruby/internal/intern/dir.h +normalize.o: $(hdrdir)/ruby/internal/intern/enum.h +normalize.o: $(hdrdir)/ruby/internal/intern/enumerator.h +normalize.o: $(hdrdir)/ruby/internal/intern/error.h +normalize.o: $(hdrdir)/ruby/internal/intern/eval.h +normalize.o: $(hdrdir)/ruby/internal/intern/file.h +normalize.o: $(hdrdir)/ruby/internal/intern/gc.h +normalize.o: $(hdrdir)/ruby/internal/intern/hash.h +normalize.o: $(hdrdir)/ruby/internal/intern/io.h +normalize.o: $(hdrdir)/ruby/internal/intern/load.h +normalize.o: $(hdrdir)/ruby/internal/intern/marshal.h +normalize.o: $(hdrdir)/ruby/internal/intern/numeric.h +normalize.o: $(hdrdir)/ruby/internal/intern/object.h +normalize.o: $(hdrdir)/ruby/internal/intern/parse.h +normalize.o: $(hdrdir)/ruby/internal/intern/proc.h +normalize.o: $(hdrdir)/ruby/internal/intern/process.h +normalize.o: $(hdrdir)/ruby/internal/intern/random.h +normalize.o: $(hdrdir)/ruby/internal/intern/range.h +normalize.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +normalize.o: $(hdrdir)/ruby/internal/intern/sprintf.h +normalize.o: $(hdrdir)/ruby/internal/intern/string.h +normalize.o: $(hdrdir)/ruby/internal/intern/struct.h +normalize.o: $(hdrdir)/ruby/internal/intern/thread.h +normalize.o: $(hdrdir)/ruby/internal/intern/time.h +normalize.o: $(hdrdir)/ruby/internal/intern/variable.h +normalize.o: $(hdrdir)/ruby/internal/intern/vm.h +normalize.o: $(hdrdir)/ruby/internal/interpreter.h +normalize.o: $(hdrdir)/ruby/internal/iterator.h +normalize.o: $(hdrdir)/ruby/internal/memory.h +normalize.o: $(hdrdir)/ruby/internal/method.h +normalize.o: $(hdrdir)/ruby/internal/module.h +normalize.o: $(hdrdir)/ruby/internal/newobj.h +normalize.o: $(hdrdir)/ruby/internal/rgengc.h +normalize.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +normalize.o: $(hdrdir)/ruby/internal/value.h +normalize.o: $(hdrdir)/ruby/internal/value_type.h +normalize.o: $(hdrdir)/ruby/internal/variable.h +normalize.o: $(hdrdir)/ruby/internal/warning_push.h +normalize.o: $(hdrdir)/ruby/internal/xmalloc.h normalize.o: $(hdrdir)/ruby/missing.h +normalize.o: $(hdrdir)/ruby/onigmo.h +normalize.o: $(hdrdir)/ruby/oniguruma.h normalize.o: $(hdrdir)/ruby/ruby.h normalize.o: $(hdrdir)/ruby/st.h normalize.o: $(hdrdir)/ruby/subst.h -normalize.o: $(top_srcdir)/internal.h +normalize.o: $(top_srcdir)/internal/file.h normalize.o: normalize.c qsort.o: $(RUBY_EXTCONF_H) qsort.o: $(arch_hdrdir)/ruby/config.h qsort.o: $(hdrdir)/ruby.h qsort.o: $(hdrdir)/ruby/assert.h qsort.o: $(hdrdir)/ruby/backward.h +qsort.o: $(hdrdir)/ruby/backward/2/assume.h +qsort.o: $(hdrdir)/ruby/backward/2/attributes.h +qsort.o: $(hdrdir)/ruby/backward/2/bool.h +qsort.o: $(hdrdir)/ruby/backward/2/inttypes.h +qsort.o: $(hdrdir)/ruby/backward/2/limits.h +qsort.o: $(hdrdir)/ruby/backward/2/long_long.h +qsort.o: $(hdrdir)/ruby/backward/2/stdalign.h +qsort.o: $(hdrdir)/ruby/backward/2/stdarg.h qsort.o: $(hdrdir)/ruby/defines.h qsort.o: $(hdrdir)/ruby/encoding.h qsort.o: $(hdrdir)/ruby/intern.h +qsort.o: $(hdrdir)/ruby/internal/anyargs.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/char.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/double.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/int.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/long.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/short.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +qsort.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +qsort.o: $(hdrdir)/ruby/internal/assume.h +qsort.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +qsort.o: $(hdrdir)/ruby/internal/attr/artificial.h +qsort.o: $(hdrdir)/ruby/internal/attr/cold.h +qsort.o: $(hdrdir)/ruby/internal/attr/const.h +qsort.o: $(hdrdir)/ruby/internal/attr/constexpr.h +qsort.o: $(hdrdir)/ruby/internal/attr/deprecated.h +qsort.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +qsort.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +qsort.o: $(hdrdir)/ruby/internal/attr/error.h +qsort.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +qsort.o: $(hdrdir)/ruby/internal/attr/forceinline.h +qsort.o: $(hdrdir)/ruby/internal/attr/format.h +qsort.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +qsort.o: $(hdrdir)/ruby/internal/attr/noalias.h +qsort.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +qsort.o: $(hdrdir)/ruby/internal/attr/noexcept.h +qsort.o: $(hdrdir)/ruby/internal/attr/noinline.h +qsort.o: $(hdrdir)/ruby/internal/attr/nonnull.h +qsort.o: $(hdrdir)/ruby/internal/attr/noreturn.h +qsort.o: $(hdrdir)/ruby/internal/attr/pure.h +qsort.o: $(hdrdir)/ruby/internal/attr/restrict.h +qsort.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +qsort.o: $(hdrdir)/ruby/internal/attr/warning.h +qsort.o: $(hdrdir)/ruby/internal/attr/weakref.h +qsort.o: $(hdrdir)/ruby/internal/cast.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +qsort.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +qsort.o: $(hdrdir)/ruby/internal/compiler_since.h +qsort.o: $(hdrdir)/ruby/internal/config.h +qsort.o: $(hdrdir)/ruby/internal/constant_p.h +qsort.o: $(hdrdir)/ruby/internal/core.h +qsort.o: $(hdrdir)/ruby/internal/core/rarray.h +qsort.o: $(hdrdir)/ruby/internal/core/rbasic.h +qsort.o: $(hdrdir)/ruby/internal/core/rbignum.h +qsort.o: $(hdrdir)/ruby/internal/core/rclass.h +qsort.o: $(hdrdir)/ruby/internal/core/rdata.h +qsort.o: $(hdrdir)/ruby/internal/core/rfile.h +qsort.o: $(hdrdir)/ruby/internal/core/rhash.h +qsort.o: $(hdrdir)/ruby/internal/core/robject.h +qsort.o: $(hdrdir)/ruby/internal/core/rregexp.h +qsort.o: $(hdrdir)/ruby/internal/core/rstring.h +qsort.o: $(hdrdir)/ruby/internal/core/rstruct.h +qsort.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +qsort.o: $(hdrdir)/ruby/internal/ctype.h +qsort.o: $(hdrdir)/ruby/internal/dllexport.h +qsort.o: $(hdrdir)/ruby/internal/dosish.h +qsort.o: $(hdrdir)/ruby/internal/encoding/coderange.h +qsort.o: $(hdrdir)/ruby/internal/encoding/ctype.h +qsort.o: $(hdrdir)/ruby/internal/encoding/encoding.h +qsort.o: $(hdrdir)/ruby/internal/encoding/pathname.h +qsort.o: $(hdrdir)/ruby/internal/encoding/re.h +qsort.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +qsort.o: $(hdrdir)/ruby/internal/encoding/string.h +qsort.o: $(hdrdir)/ruby/internal/encoding/symbol.h +qsort.o: $(hdrdir)/ruby/internal/encoding/transcode.h +qsort.o: $(hdrdir)/ruby/internal/error.h +qsort.o: $(hdrdir)/ruby/internal/eval.h +qsort.o: $(hdrdir)/ruby/internal/event.h +qsort.o: $(hdrdir)/ruby/internal/fl_type.h +qsort.o: $(hdrdir)/ruby/internal/gc.h +qsort.o: $(hdrdir)/ruby/internal/glob.h +qsort.o: $(hdrdir)/ruby/internal/globals.h +qsort.o: $(hdrdir)/ruby/internal/has/attribute.h +qsort.o: $(hdrdir)/ruby/internal/has/builtin.h +qsort.o: $(hdrdir)/ruby/internal/has/c_attribute.h +qsort.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +qsort.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +qsort.o: $(hdrdir)/ruby/internal/has/extension.h +qsort.o: $(hdrdir)/ruby/internal/has/feature.h +qsort.o: $(hdrdir)/ruby/internal/has/warning.h +qsort.o: $(hdrdir)/ruby/internal/intern/array.h +qsort.o: $(hdrdir)/ruby/internal/intern/bignum.h +qsort.o: $(hdrdir)/ruby/internal/intern/class.h +qsort.o: $(hdrdir)/ruby/internal/intern/compar.h +qsort.o: $(hdrdir)/ruby/internal/intern/complex.h +qsort.o: $(hdrdir)/ruby/internal/intern/cont.h +qsort.o: $(hdrdir)/ruby/internal/intern/dir.h +qsort.o: $(hdrdir)/ruby/internal/intern/enum.h +qsort.o: $(hdrdir)/ruby/internal/intern/enumerator.h +qsort.o: $(hdrdir)/ruby/internal/intern/error.h +qsort.o: $(hdrdir)/ruby/internal/intern/eval.h +qsort.o: $(hdrdir)/ruby/internal/intern/file.h +qsort.o: $(hdrdir)/ruby/internal/intern/gc.h +qsort.o: $(hdrdir)/ruby/internal/intern/hash.h +qsort.o: $(hdrdir)/ruby/internal/intern/io.h +qsort.o: $(hdrdir)/ruby/internal/intern/load.h +qsort.o: $(hdrdir)/ruby/internal/intern/marshal.h +qsort.o: $(hdrdir)/ruby/internal/intern/numeric.h +qsort.o: $(hdrdir)/ruby/internal/intern/object.h +qsort.o: $(hdrdir)/ruby/internal/intern/parse.h +qsort.o: $(hdrdir)/ruby/internal/intern/proc.h +qsort.o: $(hdrdir)/ruby/internal/intern/process.h +qsort.o: $(hdrdir)/ruby/internal/intern/random.h +qsort.o: $(hdrdir)/ruby/internal/intern/range.h +qsort.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +qsort.o: $(hdrdir)/ruby/internal/intern/sprintf.h +qsort.o: $(hdrdir)/ruby/internal/intern/string.h +qsort.o: $(hdrdir)/ruby/internal/intern/struct.h +qsort.o: $(hdrdir)/ruby/internal/intern/thread.h +qsort.o: $(hdrdir)/ruby/internal/intern/time.h +qsort.o: $(hdrdir)/ruby/internal/intern/variable.h +qsort.o: $(hdrdir)/ruby/internal/intern/vm.h +qsort.o: $(hdrdir)/ruby/internal/interpreter.h +qsort.o: $(hdrdir)/ruby/internal/iterator.h +qsort.o: $(hdrdir)/ruby/internal/memory.h +qsort.o: $(hdrdir)/ruby/internal/method.h +qsort.o: $(hdrdir)/ruby/internal/module.h +qsort.o: $(hdrdir)/ruby/internal/newobj.h +qsort.o: $(hdrdir)/ruby/internal/rgengc.h +qsort.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +qsort.o: $(hdrdir)/ruby/internal/value.h +qsort.o: $(hdrdir)/ruby/internal/value_type.h +qsort.o: $(hdrdir)/ruby/internal/variable.h +qsort.o: $(hdrdir)/ruby/internal/warning_push.h +qsort.o: $(hdrdir)/ruby/internal/xmalloc.h qsort.o: $(hdrdir)/ruby/missing.h qsort.o: $(hdrdir)/ruby/onigmo.h qsort.o: $(hdrdir)/ruby/oniguruma.h @@ -175,13 +2179,319 @@ qsort.o: $(hdrdir)/ruby/st.h qsort.o: $(hdrdir)/ruby/subst.h qsort.o: $(hdrdir)/ruby/util.h qsort.o: qsort.c +rb_interned_str.o: $(RUBY_EXTCONF_H) +rb_interned_str.o: $(arch_hdrdir)/ruby/config.h +rb_interned_str.o: $(hdrdir)/ruby.h +rb_interned_str.o: $(hdrdir)/ruby/assert.h +rb_interned_str.o: $(hdrdir)/ruby/backward.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/assume.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/attributes.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/bool.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/inttypes.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/limits.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/long_long.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdalign.h +rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdarg.h +rb_interned_str.o: $(hdrdir)/ruby/defines.h +rb_interned_str.o: $(hdrdir)/ruby/intern.h +rb_interned_str.o: $(hdrdir)/ruby/internal/anyargs.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rb_interned_str.o: $(hdrdir)/ruby/internal/assume.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/artificial.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/cold.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/const.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/error.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/format.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noalias.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noinline.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/pure.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/restrict.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/warning.h +rb_interned_str.o: $(hdrdir)/ruby/internal/attr/weakref.h +rb_interned_str.o: $(hdrdir)/ruby/internal/cast.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_since.h +rb_interned_str.o: $(hdrdir)/ruby/internal/config.h +rb_interned_str.o: $(hdrdir)/ruby/internal/constant_p.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rarray.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbasic.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbignum.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rclass.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rdata.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rfile.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rhash.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/robject.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rregexp.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstring.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstruct.h +rb_interned_str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rb_interned_str.o: $(hdrdir)/ruby/internal/ctype.h +rb_interned_str.o: $(hdrdir)/ruby/internal/dllexport.h +rb_interned_str.o: $(hdrdir)/ruby/internal/dosish.h +rb_interned_str.o: $(hdrdir)/ruby/internal/error.h +rb_interned_str.o: $(hdrdir)/ruby/internal/eval.h +rb_interned_str.o: $(hdrdir)/ruby/internal/event.h +rb_interned_str.o: $(hdrdir)/ruby/internal/fl_type.h +rb_interned_str.o: $(hdrdir)/ruby/internal/gc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/glob.h +rb_interned_str.o: $(hdrdir)/ruby/internal/globals.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/attribute.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/builtin.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/extension.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/feature.h +rb_interned_str.o: $(hdrdir)/ruby/internal/has/warning.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/array.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/bignum.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/class.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/compar.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/complex.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/cont.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/dir.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enum.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/error.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/eval.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/file.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/gc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/hash.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/io.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/load.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/marshal.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/numeric.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/object.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/parse.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/proc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/process.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/random.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/range.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/string.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/struct.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/thread.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/time.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/variable.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/vm.h +rb_interned_str.o: $(hdrdir)/ruby/internal/interpreter.h +rb_interned_str.o: $(hdrdir)/ruby/internal/iterator.h +rb_interned_str.o: $(hdrdir)/ruby/internal/memory.h +rb_interned_str.o: $(hdrdir)/ruby/internal/method.h +rb_interned_str.o: $(hdrdir)/ruby/internal/module.h +rb_interned_str.o: $(hdrdir)/ruby/internal/newobj.h +rb_interned_str.o: $(hdrdir)/ruby/internal/rgengc.h +rb_interned_str.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rb_interned_str.o: $(hdrdir)/ruby/internal/value.h +rb_interned_str.o: $(hdrdir)/ruby/internal/value_type.h +rb_interned_str.o: $(hdrdir)/ruby/internal/variable.h +rb_interned_str.o: $(hdrdir)/ruby/internal/warning_push.h +rb_interned_str.o: $(hdrdir)/ruby/internal/xmalloc.h +rb_interned_str.o: $(hdrdir)/ruby/missing.h +rb_interned_str.o: $(hdrdir)/ruby/ruby.h +rb_interned_str.o: $(hdrdir)/ruby/st.h +rb_interned_str.o: $(hdrdir)/ruby/subst.h +rb_interned_str.o: rb_interned_str.c rb_str_dup.o: $(RUBY_EXTCONF_H) rb_str_dup.o: $(arch_hdrdir)/ruby/config.h rb_str_dup.o: $(hdrdir)/ruby.h rb_str_dup.o: $(hdrdir)/ruby/assert.h rb_str_dup.o: $(hdrdir)/ruby/backward.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/assume.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/attributes.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/bool.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/inttypes.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/limits.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/long_long.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdalign.h +rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdarg.h rb_str_dup.o: $(hdrdir)/ruby/defines.h rb_str_dup.o: $(hdrdir)/ruby/intern.h +rb_str_dup.o: $(hdrdir)/ruby/internal/anyargs.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rb_str_dup.o: $(hdrdir)/ruby/internal/assume.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/artificial.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/cold.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/const.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/error.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/format.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noalias.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noinline.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/pure.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/restrict.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/warning.h +rb_str_dup.o: $(hdrdir)/ruby/internal/attr/weakref.h +rb_str_dup.o: $(hdrdir)/ruby/internal/cast.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_since.h +rb_str_dup.o: $(hdrdir)/ruby/internal/config.h +rb_str_dup.o: $(hdrdir)/ruby/internal/constant_p.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rarray.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbasic.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbignum.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rclass.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rdata.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rfile.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rhash.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/robject.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rregexp.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstring.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstruct.h +rb_str_dup.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rb_str_dup.o: $(hdrdir)/ruby/internal/ctype.h +rb_str_dup.o: $(hdrdir)/ruby/internal/dllexport.h +rb_str_dup.o: $(hdrdir)/ruby/internal/dosish.h +rb_str_dup.o: $(hdrdir)/ruby/internal/error.h +rb_str_dup.o: $(hdrdir)/ruby/internal/eval.h +rb_str_dup.o: $(hdrdir)/ruby/internal/event.h +rb_str_dup.o: $(hdrdir)/ruby/internal/fl_type.h +rb_str_dup.o: $(hdrdir)/ruby/internal/gc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/glob.h +rb_str_dup.o: $(hdrdir)/ruby/internal/globals.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/attribute.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/builtin.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/extension.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/feature.h +rb_str_dup.o: $(hdrdir)/ruby/internal/has/warning.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/array.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/bignum.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/class.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/compar.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/complex.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/cont.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/dir.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enum.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/error.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/eval.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/file.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/gc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/hash.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/io.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/load.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/marshal.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/numeric.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/object.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/parse.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/proc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/process.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/random.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/range.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/string.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/struct.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/thread.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/time.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/variable.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/vm.h +rb_str_dup.o: $(hdrdir)/ruby/internal/interpreter.h +rb_str_dup.o: $(hdrdir)/ruby/internal/iterator.h +rb_str_dup.o: $(hdrdir)/ruby/internal/memory.h +rb_str_dup.o: $(hdrdir)/ruby/internal/method.h +rb_str_dup.o: $(hdrdir)/ruby/internal/module.h +rb_str_dup.o: $(hdrdir)/ruby/internal/newobj.h +rb_str_dup.o: $(hdrdir)/ruby/internal/rgengc.h +rb_str_dup.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rb_str_dup.o: $(hdrdir)/ruby/internal/value.h +rb_str_dup.o: $(hdrdir)/ruby/internal/value_type.h +rb_str_dup.o: $(hdrdir)/ruby/internal/variable.h +rb_str_dup.o: $(hdrdir)/ruby/internal/warning_push.h +rb_str_dup.o: $(hdrdir)/ruby/internal/xmalloc.h rb_str_dup.o: $(hdrdir)/ruby/missing.h rb_str_dup.o: $(hdrdir)/ruby/ruby.h rb_str_dup.o: $(hdrdir)/ruby/st.h @@ -192,8 +2502,155 @@ set_len.o: $(arch_hdrdir)/ruby/config.h set_len.o: $(hdrdir)/ruby.h set_len.o: $(hdrdir)/ruby/assert.h set_len.o: $(hdrdir)/ruby/backward.h +set_len.o: $(hdrdir)/ruby/backward/2/assume.h +set_len.o: $(hdrdir)/ruby/backward/2/attributes.h +set_len.o: $(hdrdir)/ruby/backward/2/bool.h +set_len.o: $(hdrdir)/ruby/backward/2/inttypes.h +set_len.o: $(hdrdir)/ruby/backward/2/limits.h +set_len.o: $(hdrdir)/ruby/backward/2/long_long.h +set_len.o: $(hdrdir)/ruby/backward/2/stdalign.h +set_len.o: $(hdrdir)/ruby/backward/2/stdarg.h set_len.o: $(hdrdir)/ruby/defines.h set_len.o: $(hdrdir)/ruby/intern.h +set_len.o: $(hdrdir)/ruby/internal/anyargs.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/char.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/double.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/int.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/long.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/short.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +set_len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +set_len.o: $(hdrdir)/ruby/internal/assume.h +set_len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +set_len.o: $(hdrdir)/ruby/internal/attr/artificial.h +set_len.o: $(hdrdir)/ruby/internal/attr/cold.h +set_len.o: $(hdrdir)/ruby/internal/attr/const.h +set_len.o: $(hdrdir)/ruby/internal/attr/constexpr.h +set_len.o: $(hdrdir)/ruby/internal/attr/deprecated.h +set_len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +set_len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +set_len.o: $(hdrdir)/ruby/internal/attr/error.h +set_len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +set_len.o: $(hdrdir)/ruby/internal/attr/forceinline.h +set_len.o: $(hdrdir)/ruby/internal/attr/format.h +set_len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +set_len.o: $(hdrdir)/ruby/internal/attr/noalias.h +set_len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +set_len.o: $(hdrdir)/ruby/internal/attr/noexcept.h +set_len.o: $(hdrdir)/ruby/internal/attr/noinline.h +set_len.o: $(hdrdir)/ruby/internal/attr/nonnull.h +set_len.o: $(hdrdir)/ruby/internal/attr/noreturn.h +set_len.o: $(hdrdir)/ruby/internal/attr/pure.h +set_len.o: $(hdrdir)/ruby/internal/attr/restrict.h +set_len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +set_len.o: $(hdrdir)/ruby/internal/attr/warning.h +set_len.o: $(hdrdir)/ruby/internal/attr/weakref.h +set_len.o: $(hdrdir)/ruby/internal/cast.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +set_len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +set_len.o: $(hdrdir)/ruby/internal/compiler_since.h +set_len.o: $(hdrdir)/ruby/internal/config.h +set_len.o: $(hdrdir)/ruby/internal/constant_p.h +set_len.o: $(hdrdir)/ruby/internal/core.h +set_len.o: $(hdrdir)/ruby/internal/core/rarray.h +set_len.o: $(hdrdir)/ruby/internal/core/rbasic.h +set_len.o: $(hdrdir)/ruby/internal/core/rbignum.h +set_len.o: $(hdrdir)/ruby/internal/core/rclass.h +set_len.o: $(hdrdir)/ruby/internal/core/rdata.h +set_len.o: $(hdrdir)/ruby/internal/core/rfile.h +set_len.o: $(hdrdir)/ruby/internal/core/rhash.h +set_len.o: $(hdrdir)/ruby/internal/core/robject.h +set_len.o: $(hdrdir)/ruby/internal/core/rregexp.h +set_len.o: $(hdrdir)/ruby/internal/core/rstring.h +set_len.o: $(hdrdir)/ruby/internal/core/rstruct.h +set_len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +set_len.o: $(hdrdir)/ruby/internal/ctype.h +set_len.o: $(hdrdir)/ruby/internal/dllexport.h +set_len.o: $(hdrdir)/ruby/internal/dosish.h +set_len.o: $(hdrdir)/ruby/internal/error.h +set_len.o: $(hdrdir)/ruby/internal/eval.h +set_len.o: $(hdrdir)/ruby/internal/event.h +set_len.o: $(hdrdir)/ruby/internal/fl_type.h +set_len.o: $(hdrdir)/ruby/internal/gc.h +set_len.o: $(hdrdir)/ruby/internal/glob.h +set_len.o: $(hdrdir)/ruby/internal/globals.h +set_len.o: $(hdrdir)/ruby/internal/has/attribute.h +set_len.o: $(hdrdir)/ruby/internal/has/builtin.h +set_len.o: $(hdrdir)/ruby/internal/has/c_attribute.h +set_len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +set_len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +set_len.o: $(hdrdir)/ruby/internal/has/extension.h +set_len.o: $(hdrdir)/ruby/internal/has/feature.h +set_len.o: $(hdrdir)/ruby/internal/has/warning.h +set_len.o: $(hdrdir)/ruby/internal/intern/array.h +set_len.o: $(hdrdir)/ruby/internal/intern/bignum.h +set_len.o: $(hdrdir)/ruby/internal/intern/class.h +set_len.o: $(hdrdir)/ruby/internal/intern/compar.h +set_len.o: $(hdrdir)/ruby/internal/intern/complex.h +set_len.o: $(hdrdir)/ruby/internal/intern/cont.h +set_len.o: $(hdrdir)/ruby/internal/intern/dir.h +set_len.o: $(hdrdir)/ruby/internal/intern/enum.h +set_len.o: $(hdrdir)/ruby/internal/intern/enumerator.h +set_len.o: $(hdrdir)/ruby/internal/intern/error.h +set_len.o: $(hdrdir)/ruby/internal/intern/eval.h +set_len.o: $(hdrdir)/ruby/internal/intern/file.h +set_len.o: $(hdrdir)/ruby/internal/intern/gc.h +set_len.o: $(hdrdir)/ruby/internal/intern/hash.h +set_len.o: $(hdrdir)/ruby/internal/intern/io.h +set_len.o: $(hdrdir)/ruby/internal/intern/load.h +set_len.o: $(hdrdir)/ruby/internal/intern/marshal.h +set_len.o: $(hdrdir)/ruby/internal/intern/numeric.h +set_len.o: $(hdrdir)/ruby/internal/intern/object.h +set_len.o: $(hdrdir)/ruby/internal/intern/parse.h +set_len.o: $(hdrdir)/ruby/internal/intern/proc.h +set_len.o: $(hdrdir)/ruby/internal/intern/process.h +set_len.o: $(hdrdir)/ruby/internal/intern/random.h +set_len.o: $(hdrdir)/ruby/internal/intern/range.h +set_len.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +set_len.o: $(hdrdir)/ruby/internal/intern/sprintf.h +set_len.o: $(hdrdir)/ruby/internal/intern/string.h +set_len.o: $(hdrdir)/ruby/internal/intern/struct.h +set_len.o: $(hdrdir)/ruby/internal/intern/thread.h +set_len.o: $(hdrdir)/ruby/internal/intern/time.h +set_len.o: $(hdrdir)/ruby/internal/intern/variable.h +set_len.o: $(hdrdir)/ruby/internal/intern/vm.h +set_len.o: $(hdrdir)/ruby/internal/interpreter.h +set_len.o: $(hdrdir)/ruby/internal/iterator.h +set_len.o: $(hdrdir)/ruby/internal/memory.h +set_len.o: $(hdrdir)/ruby/internal/method.h +set_len.o: $(hdrdir)/ruby/internal/module.h +set_len.o: $(hdrdir)/ruby/internal/newobj.h +set_len.o: $(hdrdir)/ruby/internal/rgengc.h +set_len.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +set_len.o: $(hdrdir)/ruby/internal/value.h +set_len.o: $(hdrdir)/ruby/internal/value_type.h +set_len.o: $(hdrdir)/ruby/internal/variable.h +set_len.o: $(hdrdir)/ruby/internal/warning_push.h +set_len.o: $(hdrdir)/ruby/internal/xmalloc.h set_len.o: $(hdrdir)/ruby/missing.h set_len.o: $(hdrdir)/ruby/ruby.h set_len.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/string/enc_str_buf_cat.c b/ruby/ext/-test-/string/enc_str_buf_cat.c index 9ac4a298b..4c1b262e1 100644 --- a/ruby/ext/-test-/string/enc_str_buf_cat.c +++ b/ruby/ext/-test-/string/enc_str_buf_cat.c @@ -7,8 +7,22 @@ enc_str_buf_cat(VALUE str, VALUE str2) return rb_enc_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2), rb_enc_get(str2)); } +static VALUE +str_conv_enc_opts(VALUE str, VALUE from, VALUE to, VALUE ecflags, VALUE ecopts) +{ + rb_encoding *from_enc = NIL_P(from) ? NULL : rb_to_encoding(from); + rb_encoding *to_enc = NIL_P(to) ? NULL : rb_to_encoding(to); + int flags = NUM2INT(ecflags); + if (!NIL_P(ecopts)) { + Check_Type(ecopts, T_HASH); + OBJ_FREEZE(ecopts); + } + return rb_str_conv_enc_opts(str, from_enc, to_enc, flags, ecopts); +} + void Init_string_enc_str_buf_cat(VALUE klass) { rb_define_method(klass, "enc_str_buf_cat", enc_str_buf_cat, 1); + rb_define_method(klass, "str_conv_enc_opts", str_conv_enc_opts, 4); } diff --git a/ruby/ext/-test-/string/fstring.c b/ruby/ext/-test-/string/fstring.c index 30120b42f..2374319fe 100644 --- a/ruby/ext/-test-/string/fstring.c +++ b/ruby/ext/-test-/string/fstring.c @@ -1,4 +1,5 @@ #include "ruby.h" +#include "ruby/encoding.h" VALUE rb_fstring(VALUE str); @@ -8,8 +9,22 @@ bug_s_fstring(VALUE self, VALUE str) return rb_fstring(str); } +VALUE +bug_s_rb_enc_interned_str(VALUE self, VALUE encoding) +{ + return rb_enc_interned_str("foo", 3, RDATA(encoding)->data); +} + +VALUE +bug_s_rb_enc_str_new(VALUE self, VALUE encoding) +{ + return rb_enc_str_new("foo", 3, RDATA(encoding)->data); +} + void Init_string_fstring(VALUE klass) { rb_define_singleton_method(klass, "fstring", bug_s_fstring, 1); + 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/ruby/ext/-test-/string/normalize.c b/ruby/ext/-test-/string/normalize.c index 0ba179763..a069288ee 100644 --- a/ruby/ext/-test-/string/normalize.c +++ b/ruby/ext/-test-/string/normalize.c @@ -1,4 +1,4 @@ -#include "internal.h" +#include "internal/file.h" #ifdef __APPLE__ static VALUE diff --git a/ruby/ext/-test-/string/rb_interned_str.c b/ruby/ext/-test-/string/rb_interned_str.c new file mode 100644 index 000000000..47643ec24 --- /dev/null +++ b/ruby/ext/-test-/string/rb_interned_str.c @@ -0,0 +1,14 @@ +#include "ruby.h" + +static VALUE +bug_rb_interned_str_dup(VALUE self, VALUE str) +{ + Check_Type(str, T_STRING); + return rb_interned_str(RSTRING_PTR(str), RSTRING_LEN(str)); +} + +void +Init_string_rb_interned_str(VALUE klass) +{ + rb_define_singleton_method(klass, "rb_interned_str_dup", bug_rb_interned_str_dup, 1); +} diff --git a/ruby/ext/-test-/struct/depend b/ruby/ext/-test-/struct/depend index 552daf0ac..c9dcffd3c 100644 --- a/ruby/ext/-test-/struct/depend +++ b/ruby/ext/-test-/struct/depend @@ -4,8 +4,155 @@ duplicate.o: $(arch_hdrdir)/ruby/config.h duplicate.o: $(hdrdir)/ruby.h duplicate.o: $(hdrdir)/ruby/assert.h duplicate.o: $(hdrdir)/ruby/backward.h +duplicate.o: $(hdrdir)/ruby/backward/2/assume.h +duplicate.o: $(hdrdir)/ruby/backward/2/attributes.h +duplicate.o: $(hdrdir)/ruby/backward/2/bool.h +duplicate.o: $(hdrdir)/ruby/backward/2/inttypes.h +duplicate.o: $(hdrdir)/ruby/backward/2/limits.h +duplicate.o: $(hdrdir)/ruby/backward/2/long_long.h +duplicate.o: $(hdrdir)/ruby/backward/2/stdalign.h +duplicate.o: $(hdrdir)/ruby/backward/2/stdarg.h duplicate.o: $(hdrdir)/ruby/defines.h duplicate.o: $(hdrdir)/ruby/intern.h +duplicate.o: $(hdrdir)/ruby/internal/anyargs.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/char.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/double.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/int.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/short.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +duplicate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +duplicate.o: $(hdrdir)/ruby/internal/assume.h +duplicate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +duplicate.o: $(hdrdir)/ruby/internal/attr/artificial.h +duplicate.o: $(hdrdir)/ruby/internal/attr/cold.h +duplicate.o: $(hdrdir)/ruby/internal/attr/const.h +duplicate.o: $(hdrdir)/ruby/internal/attr/constexpr.h +duplicate.o: $(hdrdir)/ruby/internal/attr/deprecated.h +duplicate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +duplicate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +duplicate.o: $(hdrdir)/ruby/internal/attr/error.h +duplicate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +duplicate.o: $(hdrdir)/ruby/internal/attr/forceinline.h +duplicate.o: $(hdrdir)/ruby/internal/attr/format.h +duplicate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +duplicate.o: $(hdrdir)/ruby/internal/attr/noalias.h +duplicate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +duplicate.o: $(hdrdir)/ruby/internal/attr/noexcept.h +duplicate.o: $(hdrdir)/ruby/internal/attr/noinline.h +duplicate.o: $(hdrdir)/ruby/internal/attr/nonnull.h +duplicate.o: $(hdrdir)/ruby/internal/attr/noreturn.h +duplicate.o: $(hdrdir)/ruby/internal/attr/pure.h +duplicate.o: $(hdrdir)/ruby/internal/attr/restrict.h +duplicate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +duplicate.o: $(hdrdir)/ruby/internal/attr/warning.h +duplicate.o: $(hdrdir)/ruby/internal/attr/weakref.h +duplicate.o: $(hdrdir)/ruby/internal/cast.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +duplicate.o: $(hdrdir)/ruby/internal/compiler_since.h +duplicate.o: $(hdrdir)/ruby/internal/config.h +duplicate.o: $(hdrdir)/ruby/internal/constant_p.h +duplicate.o: $(hdrdir)/ruby/internal/core.h +duplicate.o: $(hdrdir)/ruby/internal/core/rarray.h +duplicate.o: $(hdrdir)/ruby/internal/core/rbasic.h +duplicate.o: $(hdrdir)/ruby/internal/core/rbignum.h +duplicate.o: $(hdrdir)/ruby/internal/core/rclass.h +duplicate.o: $(hdrdir)/ruby/internal/core/rdata.h +duplicate.o: $(hdrdir)/ruby/internal/core/rfile.h +duplicate.o: $(hdrdir)/ruby/internal/core/rhash.h +duplicate.o: $(hdrdir)/ruby/internal/core/robject.h +duplicate.o: $(hdrdir)/ruby/internal/core/rregexp.h +duplicate.o: $(hdrdir)/ruby/internal/core/rstring.h +duplicate.o: $(hdrdir)/ruby/internal/core/rstruct.h +duplicate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +duplicate.o: $(hdrdir)/ruby/internal/ctype.h +duplicate.o: $(hdrdir)/ruby/internal/dllexport.h +duplicate.o: $(hdrdir)/ruby/internal/dosish.h +duplicate.o: $(hdrdir)/ruby/internal/error.h +duplicate.o: $(hdrdir)/ruby/internal/eval.h +duplicate.o: $(hdrdir)/ruby/internal/event.h +duplicate.o: $(hdrdir)/ruby/internal/fl_type.h +duplicate.o: $(hdrdir)/ruby/internal/gc.h +duplicate.o: $(hdrdir)/ruby/internal/glob.h +duplicate.o: $(hdrdir)/ruby/internal/globals.h +duplicate.o: $(hdrdir)/ruby/internal/has/attribute.h +duplicate.o: $(hdrdir)/ruby/internal/has/builtin.h +duplicate.o: $(hdrdir)/ruby/internal/has/c_attribute.h +duplicate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +duplicate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +duplicate.o: $(hdrdir)/ruby/internal/has/extension.h +duplicate.o: $(hdrdir)/ruby/internal/has/feature.h +duplicate.o: $(hdrdir)/ruby/internal/has/warning.h +duplicate.o: $(hdrdir)/ruby/internal/intern/array.h +duplicate.o: $(hdrdir)/ruby/internal/intern/bignum.h +duplicate.o: $(hdrdir)/ruby/internal/intern/class.h +duplicate.o: $(hdrdir)/ruby/internal/intern/compar.h +duplicate.o: $(hdrdir)/ruby/internal/intern/complex.h +duplicate.o: $(hdrdir)/ruby/internal/intern/cont.h +duplicate.o: $(hdrdir)/ruby/internal/intern/dir.h +duplicate.o: $(hdrdir)/ruby/internal/intern/enum.h +duplicate.o: $(hdrdir)/ruby/internal/intern/enumerator.h +duplicate.o: $(hdrdir)/ruby/internal/intern/error.h +duplicate.o: $(hdrdir)/ruby/internal/intern/eval.h +duplicate.o: $(hdrdir)/ruby/internal/intern/file.h +duplicate.o: $(hdrdir)/ruby/internal/intern/gc.h +duplicate.o: $(hdrdir)/ruby/internal/intern/hash.h +duplicate.o: $(hdrdir)/ruby/internal/intern/io.h +duplicate.o: $(hdrdir)/ruby/internal/intern/load.h +duplicate.o: $(hdrdir)/ruby/internal/intern/marshal.h +duplicate.o: $(hdrdir)/ruby/internal/intern/numeric.h +duplicate.o: $(hdrdir)/ruby/internal/intern/object.h +duplicate.o: $(hdrdir)/ruby/internal/intern/parse.h +duplicate.o: $(hdrdir)/ruby/internal/intern/proc.h +duplicate.o: $(hdrdir)/ruby/internal/intern/process.h +duplicate.o: $(hdrdir)/ruby/internal/intern/random.h +duplicate.o: $(hdrdir)/ruby/internal/intern/range.h +duplicate.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +duplicate.o: $(hdrdir)/ruby/internal/intern/sprintf.h +duplicate.o: $(hdrdir)/ruby/internal/intern/string.h +duplicate.o: $(hdrdir)/ruby/internal/intern/struct.h +duplicate.o: $(hdrdir)/ruby/internal/intern/thread.h +duplicate.o: $(hdrdir)/ruby/internal/intern/time.h +duplicate.o: $(hdrdir)/ruby/internal/intern/variable.h +duplicate.o: $(hdrdir)/ruby/internal/intern/vm.h +duplicate.o: $(hdrdir)/ruby/internal/interpreter.h +duplicate.o: $(hdrdir)/ruby/internal/iterator.h +duplicate.o: $(hdrdir)/ruby/internal/memory.h +duplicate.o: $(hdrdir)/ruby/internal/method.h +duplicate.o: $(hdrdir)/ruby/internal/module.h +duplicate.o: $(hdrdir)/ruby/internal/newobj.h +duplicate.o: $(hdrdir)/ruby/internal/rgengc.h +duplicate.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +duplicate.o: $(hdrdir)/ruby/internal/value.h +duplicate.o: $(hdrdir)/ruby/internal/value_type.h +duplicate.o: $(hdrdir)/ruby/internal/variable.h +duplicate.o: $(hdrdir)/ruby/internal/warning_push.h +duplicate.o: $(hdrdir)/ruby/internal/xmalloc.h duplicate.o: $(hdrdir)/ruby/missing.h duplicate.o: $(hdrdir)/ruby/ruby.h duplicate.o: $(hdrdir)/ruby/st.h @@ -16,8 +163,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -28,8 +322,155 @@ len.o: $(arch_hdrdir)/ruby/config.h len.o: $(hdrdir)/ruby.h len.o: $(hdrdir)/ruby/assert.h len.o: $(hdrdir)/ruby/backward.h +len.o: $(hdrdir)/ruby/backward/2/assume.h +len.o: $(hdrdir)/ruby/backward/2/attributes.h +len.o: $(hdrdir)/ruby/backward/2/bool.h +len.o: $(hdrdir)/ruby/backward/2/inttypes.h +len.o: $(hdrdir)/ruby/backward/2/limits.h +len.o: $(hdrdir)/ruby/backward/2/long_long.h +len.o: $(hdrdir)/ruby/backward/2/stdalign.h +len.o: $(hdrdir)/ruby/backward/2/stdarg.h len.o: $(hdrdir)/ruby/defines.h len.o: $(hdrdir)/ruby/intern.h +len.o: $(hdrdir)/ruby/internal/anyargs.h +len.o: $(hdrdir)/ruby/internal/arithmetic.h +len.o: $(hdrdir)/ruby/internal/arithmetic/char.h +len.o: $(hdrdir)/ruby/internal/arithmetic/double.h +len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/int.h +len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/long.h +len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/short.h +len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +len.o: $(hdrdir)/ruby/internal/assume.h +len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +len.o: $(hdrdir)/ruby/internal/attr/artificial.h +len.o: $(hdrdir)/ruby/internal/attr/cold.h +len.o: $(hdrdir)/ruby/internal/attr/const.h +len.o: $(hdrdir)/ruby/internal/attr/constexpr.h +len.o: $(hdrdir)/ruby/internal/attr/deprecated.h +len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +len.o: $(hdrdir)/ruby/internal/attr/error.h +len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +len.o: $(hdrdir)/ruby/internal/attr/forceinline.h +len.o: $(hdrdir)/ruby/internal/attr/format.h +len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +len.o: $(hdrdir)/ruby/internal/attr/noalias.h +len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +len.o: $(hdrdir)/ruby/internal/attr/noexcept.h +len.o: $(hdrdir)/ruby/internal/attr/noinline.h +len.o: $(hdrdir)/ruby/internal/attr/nonnull.h +len.o: $(hdrdir)/ruby/internal/attr/noreturn.h +len.o: $(hdrdir)/ruby/internal/attr/pure.h +len.o: $(hdrdir)/ruby/internal/attr/restrict.h +len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +len.o: $(hdrdir)/ruby/internal/attr/warning.h +len.o: $(hdrdir)/ruby/internal/attr/weakref.h +len.o: $(hdrdir)/ruby/internal/cast.h +len.o: $(hdrdir)/ruby/internal/compiler_is.h +len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +len.o: $(hdrdir)/ruby/internal/compiler_since.h +len.o: $(hdrdir)/ruby/internal/config.h +len.o: $(hdrdir)/ruby/internal/constant_p.h +len.o: $(hdrdir)/ruby/internal/core.h +len.o: $(hdrdir)/ruby/internal/core/rarray.h +len.o: $(hdrdir)/ruby/internal/core/rbasic.h +len.o: $(hdrdir)/ruby/internal/core/rbignum.h +len.o: $(hdrdir)/ruby/internal/core/rclass.h +len.o: $(hdrdir)/ruby/internal/core/rdata.h +len.o: $(hdrdir)/ruby/internal/core/rfile.h +len.o: $(hdrdir)/ruby/internal/core/rhash.h +len.o: $(hdrdir)/ruby/internal/core/robject.h +len.o: $(hdrdir)/ruby/internal/core/rregexp.h +len.o: $(hdrdir)/ruby/internal/core/rstring.h +len.o: $(hdrdir)/ruby/internal/core/rstruct.h +len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +len.o: $(hdrdir)/ruby/internal/ctype.h +len.o: $(hdrdir)/ruby/internal/dllexport.h +len.o: $(hdrdir)/ruby/internal/dosish.h +len.o: $(hdrdir)/ruby/internal/error.h +len.o: $(hdrdir)/ruby/internal/eval.h +len.o: $(hdrdir)/ruby/internal/event.h +len.o: $(hdrdir)/ruby/internal/fl_type.h +len.o: $(hdrdir)/ruby/internal/gc.h +len.o: $(hdrdir)/ruby/internal/glob.h +len.o: $(hdrdir)/ruby/internal/globals.h +len.o: $(hdrdir)/ruby/internal/has/attribute.h +len.o: $(hdrdir)/ruby/internal/has/builtin.h +len.o: $(hdrdir)/ruby/internal/has/c_attribute.h +len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +len.o: $(hdrdir)/ruby/internal/has/extension.h +len.o: $(hdrdir)/ruby/internal/has/feature.h +len.o: $(hdrdir)/ruby/internal/has/warning.h +len.o: $(hdrdir)/ruby/internal/intern/array.h +len.o: $(hdrdir)/ruby/internal/intern/bignum.h +len.o: $(hdrdir)/ruby/internal/intern/class.h +len.o: $(hdrdir)/ruby/internal/intern/compar.h +len.o: $(hdrdir)/ruby/internal/intern/complex.h +len.o: $(hdrdir)/ruby/internal/intern/cont.h +len.o: $(hdrdir)/ruby/internal/intern/dir.h +len.o: $(hdrdir)/ruby/internal/intern/enum.h +len.o: $(hdrdir)/ruby/internal/intern/enumerator.h +len.o: $(hdrdir)/ruby/internal/intern/error.h +len.o: $(hdrdir)/ruby/internal/intern/eval.h +len.o: $(hdrdir)/ruby/internal/intern/file.h +len.o: $(hdrdir)/ruby/internal/intern/gc.h +len.o: $(hdrdir)/ruby/internal/intern/hash.h +len.o: $(hdrdir)/ruby/internal/intern/io.h +len.o: $(hdrdir)/ruby/internal/intern/load.h +len.o: $(hdrdir)/ruby/internal/intern/marshal.h +len.o: $(hdrdir)/ruby/internal/intern/numeric.h +len.o: $(hdrdir)/ruby/internal/intern/object.h +len.o: $(hdrdir)/ruby/internal/intern/parse.h +len.o: $(hdrdir)/ruby/internal/intern/proc.h +len.o: $(hdrdir)/ruby/internal/intern/process.h +len.o: $(hdrdir)/ruby/internal/intern/random.h +len.o: $(hdrdir)/ruby/internal/intern/range.h +len.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +len.o: $(hdrdir)/ruby/internal/intern/sprintf.h +len.o: $(hdrdir)/ruby/internal/intern/string.h +len.o: $(hdrdir)/ruby/internal/intern/struct.h +len.o: $(hdrdir)/ruby/internal/intern/thread.h +len.o: $(hdrdir)/ruby/internal/intern/time.h +len.o: $(hdrdir)/ruby/internal/intern/variable.h +len.o: $(hdrdir)/ruby/internal/intern/vm.h +len.o: $(hdrdir)/ruby/internal/interpreter.h +len.o: $(hdrdir)/ruby/internal/iterator.h +len.o: $(hdrdir)/ruby/internal/memory.h +len.o: $(hdrdir)/ruby/internal/method.h +len.o: $(hdrdir)/ruby/internal/module.h +len.o: $(hdrdir)/ruby/internal/newobj.h +len.o: $(hdrdir)/ruby/internal/rgengc.h +len.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +len.o: $(hdrdir)/ruby/internal/value.h +len.o: $(hdrdir)/ruby/internal/value_type.h +len.o: $(hdrdir)/ruby/internal/variable.h +len.o: $(hdrdir)/ruby/internal/warning_push.h +len.o: $(hdrdir)/ruby/internal/xmalloc.h len.o: $(hdrdir)/ruby/missing.h len.o: $(hdrdir)/ruby/ruby.h len.o: $(hdrdir)/ruby/st.h @@ -40,8 +481,155 @@ member.o: $(arch_hdrdir)/ruby/config.h member.o: $(hdrdir)/ruby.h member.o: $(hdrdir)/ruby/assert.h member.o: $(hdrdir)/ruby/backward.h +member.o: $(hdrdir)/ruby/backward/2/assume.h +member.o: $(hdrdir)/ruby/backward/2/attributes.h +member.o: $(hdrdir)/ruby/backward/2/bool.h +member.o: $(hdrdir)/ruby/backward/2/inttypes.h +member.o: $(hdrdir)/ruby/backward/2/limits.h +member.o: $(hdrdir)/ruby/backward/2/long_long.h +member.o: $(hdrdir)/ruby/backward/2/stdalign.h +member.o: $(hdrdir)/ruby/backward/2/stdarg.h member.o: $(hdrdir)/ruby/defines.h member.o: $(hdrdir)/ruby/intern.h +member.o: $(hdrdir)/ruby/internal/anyargs.h +member.o: $(hdrdir)/ruby/internal/arithmetic.h +member.o: $(hdrdir)/ruby/internal/arithmetic/char.h +member.o: $(hdrdir)/ruby/internal/arithmetic/double.h +member.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +member.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/int.h +member.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/long.h +member.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +member.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/short.h +member.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +member.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +member.o: $(hdrdir)/ruby/internal/assume.h +member.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +member.o: $(hdrdir)/ruby/internal/attr/artificial.h +member.o: $(hdrdir)/ruby/internal/attr/cold.h +member.o: $(hdrdir)/ruby/internal/attr/const.h +member.o: $(hdrdir)/ruby/internal/attr/constexpr.h +member.o: $(hdrdir)/ruby/internal/attr/deprecated.h +member.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +member.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +member.o: $(hdrdir)/ruby/internal/attr/error.h +member.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +member.o: $(hdrdir)/ruby/internal/attr/forceinline.h +member.o: $(hdrdir)/ruby/internal/attr/format.h +member.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +member.o: $(hdrdir)/ruby/internal/attr/noalias.h +member.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +member.o: $(hdrdir)/ruby/internal/attr/noexcept.h +member.o: $(hdrdir)/ruby/internal/attr/noinline.h +member.o: $(hdrdir)/ruby/internal/attr/nonnull.h +member.o: $(hdrdir)/ruby/internal/attr/noreturn.h +member.o: $(hdrdir)/ruby/internal/attr/pure.h +member.o: $(hdrdir)/ruby/internal/attr/restrict.h +member.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +member.o: $(hdrdir)/ruby/internal/attr/warning.h +member.o: $(hdrdir)/ruby/internal/attr/weakref.h +member.o: $(hdrdir)/ruby/internal/cast.h +member.o: $(hdrdir)/ruby/internal/compiler_is.h +member.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +member.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +member.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +member.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +member.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +member.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +member.o: $(hdrdir)/ruby/internal/compiler_since.h +member.o: $(hdrdir)/ruby/internal/config.h +member.o: $(hdrdir)/ruby/internal/constant_p.h +member.o: $(hdrdir)/ruby/internal/core.h +member.o: $(hdrdir)/ruby/internal/core/rarray.h +member.o: $(hdrdir)/ruby/internal/core/rbasic.h +member.o: $(hdrdir)/ruby/internal/core/rbignum.h +member.o: $(hdrdir)/ruby/internal/core/rclass.h +member.o: $(hdrdir)/ruby/internal/core/rdata.h +member.o: $(hdrdir)/ruby/internal/core/rfile.h +member.o: $(hdrdir)/ruby/internal/core/rhash.h +member.o: $(hdrdir)/ruby/internal/core/robject.h +member.o: $(hdrdir)/ruby/internal/core/rregexp.h +member.o: $(hdrdir)/ruby/internal/core/rstring.h +member.o: $(hdrdir)/ruby/internal/core/rstruct.h +member.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +member.o: $(hdrdir)/ruby/internal/ctype.h +member.o: $(hdrdir)/ruby/internal/dllexport.h +member.o: $(hdrdir)/ruby/internal/dosish.h +member.o: $(hdrdir)/ruby/internal/error.h +member.o: $(hdrdir)/ruby/internal/eval.h +member.o: $(hdrdir)/ruby/internal/event.h +member.o: $(hdrdir)/ruby/internal/fl_type.h +member.o: $(hdrdir)/ruby/internal/gc.h +member.o: $(hdrdir)/ruby/internal/glob.h +member.o: $(hdrdir)/ruby/internal/globals.h +member.o: $(hdrdir)/ruby/internal/has/attribute.h +member.o: $(hdrdir)/ruby/internal/has/builtin.h +member.o: $(hdrdir)/ruby/internal/has/c_attribute.h +member.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +member.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +member.o: $(hdrdir)/ruby/internal/has/extension.h +member.o: $(hdrdir)/ruby/internal/has/feature.h +member.o: $(hdrdir)/ruby/internal/has/warning.h +member.o: $(hdrdir)/ruby/internal/intern/array.h +member.o: $(hdrdir)/ruby/internal/intern/bignum.h +member.o: $(hdrdir)/ruby/internal/intern/class.h +member.o: $(hdrdir)/ruby/internal/intern/compar.h +member.o: $(hdrdir)/ruby/internal/intern/complex.h +member.o: $(hdrdir)/ruby/internal/intern/cont.h +member.o: $(hdrdir)/ruby/internal/intern/dir.h +member.o: $(hdrdir)/ruby/internal/intern/enum.h +member.o: $(hdrdir)/ruby/internal/intern/enumerator.h +member.o: $(hdrdir)/ruby/internal/intern/error.h +member.o: $(hdrdir)/ruby/internal/intern/eval.h +member.o: $(hdrdir)/ruby/internal/intern/file.h +member.o: $(hdrdir)/ruby/internal/intern/gc.h +member.o: $(hdrdir)/ruby/internal/intern/hash.h +member.o: $(hdrdir)/ruby/internal/intern/io.h +member.o: $(hdrdir)/ruby/internal/intern/load.h +member.o: $(hdrdir)/ruby/internal/intern/marshal.h +member.o: $(hdrdir)/ruby/internal/intern/numeric.h +member.o: $(hdrdir)/ruby/internal/intern/object.h +member.o: $(hdrdir)/ruby/internal/intern/parse.h +member.o: $(hdrdir)/ruby/internal/intern/proc.h +member.o: $(hdrdir)/ruby/internal/intern/process.h +member.o: $(hdrdir)/ruby/internal/intern/random.h +member.o: $(hdrdir)/ruby/internal/intern/range.h +member.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +member.o: $(hdrdir)/ruby/internal/intern/sprintf.h +member.o: $(hdrdir)/ruby/internal/intern/string.h +member.o: $(hdrdir)/ruby/internal/intern/struct.h +member.o: $(hdrdir)/ruby/internal/intern/thread.h +member.o: $(hdrdir)/ruby/internal/intern/time.h +member.o: $(hdrdir)/ruby/internal/intern/variable.h +member.o: $(hdrdir)/ruby/internal/intern/vm.h +member.o: $(hdrdir)/ruby/internal/interpreter.h +member.o: $(hdrdir)/ruby/internal/iterator.h +member.o: $(hdrdir)/ruby/internal/memory.h +member.o: $(hdrdir)/ruby/internal/method.h +member.o: $(hdrdir)/ruby/internal/module.h +member.o: $(hdrdir)/ruby/internal/newobj.h +member.o: $(hdrdir)/ruby/internal/rgengc.h +member.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +member.o: $(hdrdir)/ruby/internal/value.h +member.o: $(hdrdir)/ruby/internal/value_type.h +member.o: $(hdrdir)/ruby/internal/variable.h +member.o: $(hdrdir)/ruby/internal/warning_push.h +member.o: $(hdrdir)/ruby/internal/xmalloc.h member.o: $(hdrdir)/ruby/missing.h member.o: $(hdrdir)/ruby/ruby.h member.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/symbol/depend b/ruby/ext/-test-/symbol/depend index bccb4afc1..f462855b4 100644 --- a/ruby/ext/-test-/symbol/depend +++ b/ruby/ext/-test-/symbol/depend @@ -4,8 +4,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -16,8 +163,155 @@ type.o: $(arch_hdrdir)/ruby/config.h type.o: $(hdrdir)/ruby.h type.o: $(hdrdir)/ruby/assert.h type.o: $(hdrdir)/ruby/backward.h +type.o: $(hdrdir)/ruby/backward/2/assume.h +type.o: $(hdrdir)/ruby/backward/2/attributes.h +type.o: $(hdrdir)/ruby/backward/2/bool.h +type.o: $(hdrdir)/ruby/backward/2/inttypes.h +type.o: $(hdrdir)/ruby/backward/2/limits.h +type.o: $(hdrdir)/ruby/backward/2/long_long.h +type.o: $(hdrdir)/ruby/backward/2/stdalign.h +type.o: $(hdrdir)/ruby/backward/2/stdarg.h type.o: $(hdrdir)/ruby/defines.h type.o: $(hdrdir)/ruby/intern.h +type.o: $(hdrdir)/ruby/internal/anyargs.h +type.o: $(hdrdir)/ruby/internal/arithmetic.h +type.o: $(hdrdir)/ruby/internal/arithmetic/char.h +type.o: $(hdrdir)/ruby/internal/arithmetic/double.h +type.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +type.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/int.h +type.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/long.h +type.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +type.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/short.h +type.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +type.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +type.o: $(hdrdir)/ruby/internal/assume.h +type.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +type.o: $(hdrdir)/ruby/internal/attr/artificial.h +type.o: $(hdrdir)/ruby/internal/attr/cold.h +type.o: $(hdrdir)/ruby/internal/attr/const.h +type.o: $(hdrdir)/ruby/internal/attr/constexpr.h +type.o: $(hdrdir)/ruby/internal/attr/deprecated.h +type.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +type.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +type.o: $(hdrdir)/ruby/internal/attr/error.h +type.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +type.o: $(hdrdir)/ruby/internal/attr/forceinline.h +type.o: $(hdrdir)/ruby/internal/attr/format.h +type.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +type.o: $(hdrdir)/ruby/internal/attr/noalias.h +type.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +type.o: $(hdrdir)/ruby/internal/attr/noexcept.h +type.o: $(hdrdir)/ruby/internal/attr/noinline.h +type.o: $(hdrdir)/ruby/internal/attr/nonnull.h +type.o: $(hdrdir)/ruby/internal/attr/noreturn.h +type.o: $(hdrdir)/ruby/internal/attr/pure.h +type.o: $(hdrdir)/ruby/internal/attr/restrict.h +type.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +type.o: $(hdrdir)/ruby/internal/attr/warning.h +type.o: $(hdrdir)/ruby/internal/attr/weakref.h +type.o: $(hdrdir)/ruby/internal/cast.h +type.o: $(hdrdir)/ruby/internal/compiler_is.h +type.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +type.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +type.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +type.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +type.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +type.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +type.o: $(hdrdir)/ruby/internal/compiler_since.h +type.o: $(hdrdir)/ruby/internal/config.h +type.o: $(hdrdir)/ruby/internal/constant_p.h +type.o: $(hdrdir)/ruby/internal/core.h +type.o: $(hdrdir)/ruby/internal/core/rarray.h +type.o: $(hdrdir)/ruby/internal/core/rbasic.h +type.o: $(hdrdir)/ruby/internal/core/rbignum.h +type.o: $(hdrdir)/ruby/internal/core/rclass.h +type.o: $(hdrdir)/ruby/internal/core/rdata.h +type.o: $(hdrdir)/ruby/internal/core/rfile.h +type.o: $(hdrdir)/ruby/internal/core/rhash.h +type.o: $(hdrdir)/ruby/internal/core/robject.h +type.o: $(hdrdir)/ruby/internal/core/rregexp.h +type.o: $(hdrdir)/ruby/internal/core/rstring.h +type.o: $(hdrdir)/ruby/internal/core/rstruct.h +type.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +type.o: $(hdrdir)/ruby/internal/ctype.h +type.o: $(hdrdir)/ruby/internal/dllexport.h +type.o: $(hdrdir)/ruby/internal/dosish.h +type.o: $(hdrdir)/ruby/internal/error.h +type.o: $(hdrdir)/ruby/internal/eval.h +type.o: $(hdrdir)/ruby/internal/event.h +type.o: $(hdrdir)/ruby/internal/fl_type.h +type.o: $(hdrdir)/ruby/internal/gc.h +type.o: $(hdrdir)/ruby/internal/glob.h +type.o: $(hdrdir)/ruby/internal/globals.h +type.o: $(hdrdir)/ruby/internal/has/attribute.h +type.o: $(hdrdir)/ruby/internal/has/builtin.h +type.o: $(hdrdir)/ruby/internal/has/c_attribute.h +type.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +type.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +type.o: $(hdrdir)/ruby/internal/has/extension.h +type.o: $(hdrdir)/ruby/internal/has/feature.h +type.o: $(hdrdir)/ruby/internal/has/warning.h +type.o: $(hdrdir)/ruby/internal/intern/array.h +type.o: $(hdrdir)/ruby/internal/intern/bignum.h +type.o: $(hdrdir)/ruby/internal/intern/class.h +type.o: $(hdrdir)/ruby/internal/intern/compar.h +type.o: $(hdrdir)/ruby/internal/intern/complex.h +type.o: $(hdrdir)/ruby/internal/intern/cont.h +type.o: $(hdrdir)/ruby/internal/intern/dir.h +type.o: $(hdrdir)/ruby/internal/intern/enum.h +type.o: $(hdrdir)/ruby/internal/intern/enumerator.h +type.o: $(hdrdir)/ruby/internal/intern/error.h +type.o: $(hdrdir)/ruby/internal/intern/eval.h +type.o: $(hdrdir)/ruby/internal/intern/file.h +type.o: $(hdrdir)/ruby/internal/intern/gc.h +type.o: $(hdrdir)/ruby/internal/intern/hash.h +type.o: $(hdrdir)/ruby/internal/intern/io.h +type.o: $(hdrdir)/ruby/internal/intern/load.h +type.o: $(hdrdir)/ruby/internal/intern/marshal.h +type.o: $(hdrdir)/ruby/internal/intern/numeric.h +type.o: $(hdrdir)/ruby/internal/intern/object.h +type.o: $(hdrdir)/ruby/internal/intern/parse.h +type.o: $(hdrdir)/ruby/internal/intern/proc.h +type.o: $(hdrdir)/ruby/internal/intern/process.h +type.o: $(hdrdir)/ruby/internal/intern/random.h +type.o: $(hdrdir)/ruby/internal/intern/range.h +type.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +type.o: $(hdrdir)/ruby/internal/intern/sprintf.h +type.o: $(hdrdir)/ruby/internal/intern/string.h +type.o: $(hdrdir)/ruby/internal/intern/struct.h +type.o: $(hdrdir)/ruby/internal/intern/thread.h +type.o: $(hdrdir)/ruby/internal/intern/time.h +type.o: $(hdrdir)/ruby/internal/intern/variable.h +type.o: $(hdrdir)/ruby/internal/intern/vm.h +type.o: $(hdrdir)/ruby/internal/interpreter.h +type.o: $(hdrdir)/ruby/internal/iterator.h +type.o: $(hdrdir)/ruby/internal/memory.h +type.o: $(hdrdir)/ruby/internal/method.h +type.o: $(hdrdir)/ruby/internal/module.h +type.o: $(hdrdir)/ruby/internal/newobj.h +type.o: $(hdrdir)/ruby/internal/rgengc.h +type.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +type.o: $(hdrdir)/ruby/internal/value.h +type.o: $(hdrdir)/ruby/internal/value_type.h +type.o: $(hdrdir)/ruby/internal/variable.h +type.o: $(hdrdir)/ruby/internal/warning_push.h +type.o: $(hdrdir)/ruby/internal/xmalloc.h type.o: $(hdrdir)/ruby/missing.h type.o: $(hdrdir)/ruby/ruby.h type.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/thread_fd/depend b/ruby/ext/-test-/thread_fd/depend new file mode 100644 index 000000000..0c8c31eac --- /dev/null +++ b/ruby/ext/-test-/thread_fd/depend @@ -0,0 +1,160 @@ +# 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/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/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/gc.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/rgengc.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/ruby/ext/-test-/thread_fd/extconf.rb b/ruby/ext/-test-/thread_fd/extconf.rb new file mode 100644 index 000000000..a8bbe9d16 --- /dev/null +++ b/ruby/ext/-test-/thread_fd/extconf.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: true +create_makefile('-test-/thread_fd') diff --git a/ruby/ext/-test-/thread_fd/thread_fd.c b/ruby/ext/-test-/thread_fd/thread_fd.c new file mode 100644 index 000000000..042b799dc --- /dev/null +++ b/ruby/ext/-test-/thread_fd/thread_fd.c @@ -0,0 +1,30 @@ +#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/ruby/ext/-test-/thread_fd_close/depend b/ruby/ext/-test-/thread_fd_close/depend deleted file mode 100644 index 8c49c2d4f..000000000 --- a/ruby/ext/-test-/thread_fd_close/depend +++ /dev/null @@ -1,13 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -thread_fd_close.o: $(RUBY_EXTCONF_H) -thread_fd_close.o: $(arch_hdrdir)/ruby/config.h -thread_fd_close.o: $(hdrdir)/ruby/assert.h -thread_fd_close.o: $(hdrdir)/ruby/backward.h -thread_fd_close.o: $(hdrdir)/ruby/defines.h -thread_fd_close.o: $(hdrdir)/ruby/intern.h -thread_fd_close.o: $(hdrdir)/ruby/missing.h -thread_fd_close.o: $(hdrdir)/ruby/ruby.h -thread_fd_close.o: $(hdrdir)/ruby/st.h -thread_fd_close.o: $(hdrdir)/ruby/subst.h -thread_fd_close.o: thread_fd_close.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/thread_fd_close/extconf.rb b/ruby/ext/-test-/thread_fd_close/extconf.rb deleted file mode 100644 index 0d9694539..000000000 --- a/ruby/ext/-test-/thread_fd_close/extconf.rb +++ /dev/null @@ -1,2 +0,0 @@ -# frozen_string_literal: true -create_makefile('-test-/thread_fd_close') diff --git a/ruby/ext/-test-/thread_fd_close/thread_fd_close.c b/ruby/ext/-test-/thread_fd_close/thread_fd_close.c deleted file mode 100644 index 4fd967c5b..000000000 --- a/ruby/ext/-test-/thread_fd_close/thread_fd_close.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "ruby/ruby.h" - -static VALUE -thread_fd_close(VALUE ign, VALUE fd) -{ - rb_thread_fd_close(NUM2INT(fd)); - return Qnil; -} - -void -Init_thread_fd_close(void) -{ - rb_define_singleton_method(rb_cIO, "thread_fd_close", thread_fd_close, 1); -} diff --git a/ruby/ext/-test-/time/depend b/ruby/ext/-test-/time/depend index 2f4b8d1f1..557f65af6 100644 --- a/ruby/ext/-test-/time/depend +++ b/ruby/ext/-test-/time/depend @@ -4,8 +4,155 @@ 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/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/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/gc.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/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/rgengc.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/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 @@ -16,20 +163,319 @@ leap_second.o: $(arch_hdrdir)/ruby/config.h leap_second.o: $(hdrdir)/ruby.h leap_second.o: $(hdrdir)/ruby/assert.h leap_second.o: $(hdrdir)/ruby/backward.h +leap_second.o: $(hdrdir)/ruby/backward/2/assume.h +leap_second.o: $(hdrdir)/ruby/backward/2/attributes.h +leap_second.o: $(hdrdir)/ruby/backward/2/bool.h +leap_second.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +leap_second.o: $(hdrdir)/ruby/backward/2/inttypes.h +leap_second.o: $(hdrdir)/ruby/backward/2/limits.h +leap_second.o: $(hdrdir)/ruby/backward/2/long_long.h +leap_second.o: $(hdrdir)/ruby/backward/2/stdalign.h +leap_second.o: $(hdrdir)/ruby/backward/2/stdarg.h leap_second.o: $(hdrdir)/ruby/defines.h leap_second.o: $(hdrdir)/ruby/intern.h +leap_second.o: $(hdrdir)/ruby/internal/anyargs.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/char.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/double.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/int.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/short.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +leap_second.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +leap_second.o: $(hdrdir)/ruby/internal/assume.h +leap_second.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +leap_second.o: $(hdrdir)/ruby/internal/attr/artificial.h +leap_second.o: $(hdrdir)/ruby/internal/attr/cold.h +leap_second.o: $(hdrdir)/ruby/internal/attr/const.h +leap_second.o: $(hdrdir)/ruby/internal/attr/constexpr.h +leap_second.o: $(hdrdir)/ruby/internal/attr/deprecated.h +leap_second.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +leap_second.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +leap_second.o: $(hdrdir)/ruby/internal/attr/error.h +leap_second.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +leap_second.o: $(hdrdir)/ruby/internal/attr/forceinline.h +leap_second.o: $(hdrdir)/ruby/internal/attr/format.h +leap_second.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +leap_second.o: $(hdrdir)/ruby/internal/attr/noalias.h +leap_second.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +leap_second.o: $(hdrdir)/ruby/internal/attr/noexcept.h +leap_second.o: $(hdrdir)/ruby/internal/attr/noinline.h +leap_second.o: $(hdrdir)/ruby/internal/attr/nonnull.h +leap_second.o: $(hdrdir)/ruby/internal/attr/noreturn.h +leap_second.o: $(hdrdir)/ruby/internal/attr/pure.h +leap_second.o: $(hdrdir)/ruby/internal/attr/restrict.h +leap_second.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +leap_second.o: $(hdrdir)/ruby/internal/attr/warning.h +leap_second.o: $(hdrdir)/ruby/internal/attr/weakref.h +leap_second.o: $(hdrdir)/ruby/internal/cast.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +leap_second.o: $(hdrdir)/ruby/internal/compiler_since.h +leap_second.o: $(hdrdir)/ruby/internal/config.h +leap_second.o: $(hdrdir)/ruby/internal/constant_p.h +leap_second.o: $(hdrdir)/ruby/internal/core.h +leap_second.o: $(hdrdir)/ruby/internal/core/rarray.h +leap_second.o: $(hdrdir)/ruby/internal/core/rbasic.h +leap_second.o: $(hdrdir)/ruby/internal/core/rbignum.h +leap_second.o: $(hdrdir)/ruby/internal/core/rclass.h +leap_second.o: $(hdrdir)/ruby/internal/core/rdata.h +leap_second.o: $(hdrdir)/ruby/internal/core/rfile.h +leap_second.o: $(hdrdir)/ruby/internal/core/rhash.h +leap_second.o: $(hdrdir)/ruby/internal/core/robject.h +leap_second.o: $(hdrdir)/ruby/internal/core/rregexp.h +leap_second.o: $(hdrdir)/ruby/internal/core/rstring.h +leap_second.o: $(hdrdir)/ruby/internal/core/rstruct.h +leap_second.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +leap_second.o: $(hdrdir)/ruby/internal/ctype.h +leap_second.o: $(hdrdir)/ruby/internal/dllexport.h +leap_second.o: $(hdrdir)/ruby/internal/dosish.h +leap_second.o: $(hdrdir)/ruby/internal/error.h +leap_second.o: $(hdrdir)/ruby/internal/eval.h +leap_second.o: $(hdrdir)/ruby/internal/event.h +leap_second.o: $(hdrdir)/ruby/internal/fl_type.h +leap_second.o: $(hdrdir)/ruby/internal/gc.h +leap_second.o: $(hdrdir)/ruby/internal/glob.h +leap_second.o: $(hdrdir)/ruby/internal/globals.h +leap_second.o: $(hdrdir)/ruby/internal/has/attribute.h +leap_second.o: $(hdrdir)/ruby/internal/has/builtin.h +leap_second.o: $(hdrdir)/ruby/internal/has/c_attribute.h +leap_second.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +leap_second.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +leap_second.o: $(hdrdir)/ruby/internal/has/extension.h +leap_second.o: $(hdrdir)/ruby/internal/has/feature.h +leap_second.o: $(hdrdir)/ruby/internal/has/warning.h +leap_second.o: $(hdrdir)/ruby/internal/intern/array.h +leap_second.o: $(hdrdir)/ruby/internal/intern/bignum.h +leap_second.o: $(hdrdir)/ruby/internal/intern/class.h +leap_second.o: $(hdrdir)/ruby/internal/intern/compar.h +leap_second.o: $(hdrdir)/ruby/internal/intern/complex.h +leap_second.o: $(hdrdir)/ruby/internal/intern/cont.h +leap_second.o: $(hdrdir)/ruby/internal/intern/dir.h +leap_second.o: $(hdrdir)/ruby/internal/intern/enum.h +leap_second.o: $(hdrdir)/ruby/internal/intern/enumerator.h +leap_second.o: $(hdrdir)/ruby/internal/intern/error.h +leap_second.o: $(hdrdir)/ruby/internal/intern/eval.h +leap_second.o: $(hdrdir)/ruby/internal/intern/file.h +leap_second.o: $(hdrdir)/ruby/internal/intern/gc.h +leap_second.o: $(hdrdir)/ruby/internal/intern/hash.h +leap_second.o: $(hdrdir)/ruby/internal/intern/io.h +leap_second.o: $(hdrdir)/ruby/internal/intern/load.h +leap_second.o: $(hdrdir)/ruby/internal/intern/marshal.h +leap_second.o: $(hdrdir)/ruby/internal/intern/numeric.h +leap_second.o: $(hdrdir)/ruby/internal/intern/object.h +leap_second.o: $(hdrdir)/ruby/internal/intern/parse.h +leap_second.o: $(hdrdir)/ruby/internal/intern/proc.h +leap_second.o: $(hdrdir)/ruby/internal/intern/process.h +leap_second.o: $(hdrdir)/ruby/internal/intern/random.h +leap_second.o: $(hdrdir)/ruby/internal/intern/range.h +leap_second.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +leap_second.o: $(hdrdir)/ruby/internal/intern/sprintf.h +leap_second.o: $(hdrdir)/ruby/internal/intern/string.h +leap_second.o: $(hdrdir)/ruby/internal/intern/struct.h +leap_second.o: $(hdrdir)/ruby/internal/intern/thread.h +leap_second.o: $(hdrdir)/ruby/internal/intern/time.h +leap_second.o: $(hdrdir)/ruby/internal/intern/variable.h +leap_second.o: $(hdrdir)/ruby/internal/intern/vm.h +leap_second.o: $(hdrdir)/ruby/internal/interpreter.h +leap_second.o: $(hdrdir)/ruby/internal/iterator.h +leap_second.o: $(hdrdir)/ruby/internal/memory.h +leap_second.o: $(hdrdir)/ruby/internal/method.h +leap_second.o: $(hdrdir)/ruby/internal/module.h +leap_second.o: $(hdrdir)/ruby/internal/newobj.h +leap_second.o: $(hdrdir)/ruby/internal/rgengc.h +leap_second.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +leap_second.o: $(hdrdir)/ruby/internal/value.h +leap_second.o: $(hdrdir)/ruby/internal/value_type.h +leap_second.o: $(hdrdir)/ruby/internal/variable.h +leap_second.o: $(hdrdir)/ruby/internal/warning_push.h +leap_second.o: $(hdrdir)/ruby/internal/xmalloc.h leap_second.o: $(hdrdir)/ruby/missing.h leap_second.o: $(hdrdir)/ruby/ruby.h leap_second.o: $(hdrdir)/ruby/st.h leap_second.o: $(hdrdir)/ruby/subst.h +leap_second.o: $(top_srcdir)/internal/bits.h +leap_second.o: $(top_srcdir)/internal/compilers.h +leap_second.o: $(top_srcdir)/internal/static_assert.h +leap_second.o: $(top_srcdir)/internal/time.h leap_second.o: leap_second.c new.o: $(RUBY_EXTCONF_H) new.o: $(arch_hdrdir)/ruby/config.h new.o: $(hdrdir)/ruby.h new.o: $(hdrdir)/ruby/assert.h new.o: $(hdrdir)/ruby/backward.h +new.o: $(hdrdir)/ruby/backward/2/assume.h +new.o: $(hdrdir)/ruby/backward/2/attributes.h +new.o: $(hdrdir)/ruby/backward/2/bool.h +new.o: $(hdrdir)/ruby/backward/2/inttypes.h +new.o: $(hdrdir)/ruby/backward/2/limits.h +new.o: $(hdrdir)/ruby/backward/2/long_long.h +new.o: $(hdrdir)/ruby/backward/2/stdalign.h +new.o: $(hdrdir)/ruby/backward/2/stdarg.h new.o: $(hdrdir)/ruby/defines.h new.o: $(hdrdir)/ruby/intern.h +new.o: $(hdrdir)/ruby/internal/anyargs.h +new.o: $(hdrdir)/ruby/internal/arithmetic.h +new.o: $(hdrdir)/ruby/internal/arithmetic/char.h +new.o: $(hdrdir)/ruby/internal/arithmetic/double.h +new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/int.h +new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/short.h +new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +new.o: $(hdrdir)/ruby/internal/assume.h +new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +new.o: $(hdrdir)/ruby/internal/attr/artificial.h +new.o: $(hdrdir)/ruby/internal/attr/cold.h +new.o: $(hdrdir)/ruby/internal/attr/const.h +new.o: $(hdrdir)/ruby/internal/attr/constexpr.h +new.o: $(hdrdir)/ruby/internal/attr/deprecated.h +new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +new.o: $(hdrdir)/ruby/internal/attr/error.h +new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +new.o: $(hdrdir)/ruby/internal/attr/forceinline.h +new.o: $(hdrdir)/ruby/internal/attr/format.h +new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +new.o: $(hdrdir)/ruby/internal/attr/noalias.h +new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +new.o: $(hdrdir)/ruby/internal/attr/noexcept.h +new.o: $(hdrdir)/ruby/internal/attr/noinline.h +new.o: $(hdrdir)/ruby/internal/attr/nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/noreturn.h +new.o: $(hdrdir)/ruby/internal/attr/pure.h +new.o: $(hdrdir)/ruby/internal/attr/restrict.h +new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/warning.h +new.o: $(hdrdir)/ruby/internal/attr/weakref.h +new.o: $(hdrdir)/ruby/internal/cast.h +new.o: $(hdrdir)/ruby/internal/compiler_is.h +new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +new.o: $(hdrdir)/ruby/internal/compiler_since.h +new.o: $(hdrdir)/ruby/internal/config.h +new.o: $(hdrdir)/ruby/internal/constant_p.h +new.o: $(hdrdir)/ruby/internal/core.h +new.o: $(hdrdir)/ruby/internal/core/rarray.h +new.o: $(hdrdir)/ruby/internal/core/rbasic.h +new.o: $(hdrdir)/ruby/internal/core/rbignum.h +new.o: $(hdrdir)/ruby/internal/core/rclass.h +new.o: $(hdrdir)/ruby/internal/core/rdata.h +new.o: $(hdrdir)/ruby/internal/core/rfile.h +new.o: $(hdrdir)/ruby/internal/core/rhash.h +new.o: $(hdrdir)/ruby/internal/core/robject.h +new.o: $(hdrdir)/ruby/internal/core/rregexp.h +new.o: $(hdrdir)/ruby/internal/core/rstring.h +new.o: $(hdrdir)/ruby/internal/core/rstruct.h +new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +new.o: $(hdrdir)/ruby/internal/ctype.h +new.o: $(hdrdir)/ruby/internal/dllexport.h +new.o: $(hdrdir)/ruby/internal/dosish.h +new.o: $(hdrdir)/ruby/internal/error.h +new.o: $(hdrdir)/ruby/internal/eval.h +new.o: $(hdrdir)/ruby/internal/event.h +new.o: $(hdrdir)/ruby/internal/fl_type.h +new.o: $(hdrdir)/ruby/internal/gc.h +new.o: $(hdrdir)/ruby/internal/glob.h +new.o: $(hdrdir)/ruby/internal/globals.h +new.o: $(hdrdir)/ruby/internal/has/attribute.h +new.o: $(hdrdir)/ruby/internal/has/builtin.h +new.o: $(hdrdir)/ruby/internal/has/c_attribute.h +new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +new.o: $(hdrdir)/ruby/internal/has/extension.h +new.o: $(hdrdir)/ruby/internal/has/feature.h +new.o: $(hdrdir)/ruby/internal/has/warning.h +new.o: $(hdrdir)/ruby/internal/intern/array.h +new.o: $(hdrdir)/ruby/internal/intern/bignum.h +new.o: $(hdrdir)/ruby/internal/intern/class.h +new.o: $(hdrdir)/ruby/internal/intern/compar.h +new.o: $(hdrdir)/ruby/internal/intern/complex.h +new.o: $(hdrdir)/ruby/internal/intern/cont.h +new.o: $(hdrdir)/ruby/internal/intern/dir.h +new.o: $(hdrdir)/ruby/internal/intern/enum.h +new.o: $(hdrdir)/ruby/internal/intern/enumerator.h +new.o: $(hdrdir)/ruby/internal/intern/error.h +new.o: $(hdrdir)/ruby/internal/intern/eval.h +new.o: $(hdrdir)/ruby/internal/intern/file.h +new.o: $(hdrdir)/ruby/internal/intern/gc.h +new.o: $(hdrdir)/ruby/internal/intern/hash.h +new.o: $(hdrdir)/ruby/internal/intern/io.h +new.o: $(hdrdir)/ruby/internal/intern/load.h +new.o: $(hdrdir)/ruby/internal/intern/marshal.h +new.o: $(hdrdir)/ruby/internal/intern/numeric.h +new.o: $(hdrdir)/ruby/internal/intern/object.h +new.o: $(hdrdir)/ruby/internal/intern/parse.h +new.o: $(hdrdir)/ruby/internal/intern/proc.h +new.o: $(hdrdir)/ruby/internal/intern/process.h +new.o: $(hdrdir)/ruby/internal/intern/random.h +new.o: $(hdrdir)/ruby/internal/intern/range.h +new.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +new.o: $(hdrdir)/ruby/internal/intern/sprintf.h +new.o: $(hdrdir)/ruby/internal/intern/string.h +new.o: $(hdrdir)/ruby/internal/intern/struct.h +new.o: $(hdrdir)/ruby/internal/intern/thread.h +new.o: $(hdrdir)/ruby/internal/intern/time.h +new.o: $(hdrdir)/ruby/internal/intern/variable.h +new.o: $(hdrdir)/ruby/internal/intern/vm.h +new.o: $(hdrdir)/ruby/internal/interpreter.h +new.o: $(hdrdir)/ruby/internal/iterator.h +new.o: $(hdrdir)/ruby/internal/memory.h +new.o: $(hdrdir)/ruby/internal/method.h +new.o: $(hdrdir)/ruby/internal/module.h +new.o: $(hdrdir)/ruby/internal/newobj.h +new.o: $(hdrdir)/ruby/internal/rgengc.h +new.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +new.o: $(hdrdir)/ruby/internal/value.h +new.o: $(hdrdir)/ruby/internal/value_type.h +new.o: $(hdrdir)/ruby/internal/variable.h +new.o: $(hdrdir)/ruby/internal/warning_push.h +new.o: $(hdrdir)/ruby/internal/xmalloc.h new.o: $(hdrdir)/ruby/missing.h new.o: $(hdrdir)/ruby/ruby.h new.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/time/leap_second.c b/ruby/ext/-test-/time/leap_second.c index 7eed421b7..ee7011fa9 100644 --- a/ruby/ext/-test-/time/leap_second.c +++ b/ruby/ext/-test-/time/leap_second.c @@ -1,6 +1,6 @@ #include "ruby.h" +#include "internal/time.h" -void ruby_reset_leap_second_info(void); static VALUE bug_time_s_reset_leap_second_info(VALUE klass) { diff --git a/ruby/ext/-test-/tracepoint/depend b/ruby/ext/-test-/tracepoint/depend index b811df447..f05f13d08 100644 --- a/ruby/ext/-test-/tracepoint/depend +++ b/ruby/ext/-test-/tracepoint/depend @@ -3,9 +3,156 @@ gc_hook.o: $(RUBY_EXTCONF_H) gc_hook.o: $(arch_hdrdir)/ruby/config.h gc_hook.o: $(hdrdir)/ruby/assert.h gc_hook.o: $(hdrdir)/ruby/backward.h +gc_hook.o: $(hdrdir)/ruby/backward/2/assume.h +gc_hook.o: $(hdrdir)/ruby/backward/2/attributes.h +gc_hook.o: $(hdrdir)/ruby/backward/2/bool.h +gc_hook.o: $(hdrdir)/ruby/backward/2/inttypes.h +gc_hook.o: $(hdrdir)/ruby/backward/2/limits.h +gc_hook.o: $(hdrdir)/ruby/backward/2/long_long.h +gc_hook.o: $(hdrdir)/ruby/backward/2/stdalign.h +gc_hook.o: $(hdrdir)/ruby/backward/2/stdarg.h gc_hook.o: $(hdrdir)/ruby/debug.h gc_hook.o: $(hdrdir)/ruby/defines.h gc_hook.o: $(hdrdir)/ruby/intern.h +gc_hook.o: $(hdrdir)/ruby/internal/anyargs.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/char.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/double.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/int.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/short.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +gc_hook.o: $(hdrdir)/ruby/internal/assume.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/artificial.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/cold.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/const.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/constexpr.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/deprecated.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/error.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/forceinline.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/format.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/noalias.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/noexcept.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/noinline.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/nonnull.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/noreturn.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/pure.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/restrict.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/warning.h +gc_hook.o: $(hdrdir)/ruby/internal/attr/weakref.h +gc_hook.o: $(hdrdir)/ruby/internal/cast.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +gc_hook.o: $(hdrdir)/ruby/internal/compiler_since.h +gc_hook.o: $(hdrdir)/ruby/internal/config.h +gc_hook.o: $(hdrdir)/ruby/internal/constant_p.h +gc_hook.o: $(hdrdir)/ruby/internal/core.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rarray.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rbasic.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rbignum.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rclass.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rdata.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rfile.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rhash.h +gc_hook.o: $(hdrdir)/ruby/internal/core/robject.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rregexp.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rstring.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rstruct.h +gc_hook.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +gc_hook.o: $(hdrdir)/ruby/internal/ctype.h +gc_hook.o: $(hdrdir)/ruby/internal/dllexport.h +gc_hook.o: $(hdrdir)/ruby/internal/dosish.h +gc_hook.o: $(hdrdir)/ruby/internal/error.h +gc_hook.o: $(hdrdir)/ruby/internal/eval.h +gc_hook.o: $(hdrdir)/ruby/internal/event.h +gc_hook.o: $(hdrdir)/ruby/internal/fl_type.h +gc_hook.o: $(hdrdir)/ruby/internal/gc.h +gc_hook.o: $(hdrdir)/ruby/internal/glob.h +gc_hook.o: $(hdrdir)/ruby/internal/globals.h +gc_hook.o: $(hdrdir)/ruby/internal/has/attribute.h +gc_hook.o: $(hdrdir)/ruby/internal/has/builtin.h +gc_hook.o: $(hdrdir)/ruby/internal/has/c_attribute.h +gc_hook.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +gc_hook.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +gc_hook.o: $(hdrdir)/ruby/internal/has/extension.h +gc_hook.o: $(hdrdir)/ruby/internal/has/feature.h +gc_hook.o: $(hdrdir)/ruby/internal/has/warning.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/array.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/bignum.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/class.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/compar.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/complex.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/cont.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/dir.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/enum.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/enumerator.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/error.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/eval.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/file.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/gc.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/hash.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/io.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/load.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/marshal.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/numeric.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/object.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/parse.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/proc.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/process.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/random.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/range.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/sprintf.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/string.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/struct.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/thread.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/time.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/variable.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/vm.h +gc_hook.o: $(hdrdir)/ruby/internal/interpreter.h +gc_hook.o: $(hdrdir)/ruby/internal/iterator.h +gc_hook.o: $(hdrdir)/ruby/internal/memory.h +gc_hook.o: $(hdrdir)/ruby/internal/method.h +gc_hook.o: $(hdrdir)/ruby/internal/module.h +gc_hook.o: $(hdrdir)/ruby/internal/newobj.h +gc_hook.o: $(hdrdir)/ruby/internal/rgengc.h +gc_hook.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +gc_hook.o: $(hdrdir)/ruby/internal/value.h +gc_hook.o: $(hdrdir)/ruby/internal/value_type.h +gc_hook.o: $(hdrdir)/ruby/internal/variable.h +gc_hook.o: $(hdrdir)/ruby/internal/warning_push.h +gc_hook.o: $(hdrdir)/ruby/internal/xmalloc.h gc_hook.o: $(hdrdir)/ruby/missing.h gc_hook.o: $(hdrdir)/ruby/ruby.h gc_hook.o: $(hdrdir)/ruby/st.h @@ -15,9 +162,156 @@ tracepoint.o: $(RUBY_EXTCONF_H) tracepoint.o: $(arch_hdrdir)/ruby/config.h tracepoint.o: $(hdrdir)/ruby/assert.h tracepoint.o: $(hdrdir)/ruby/backward.h +tracepoint.o: $(hdrdir)/ruby/backward/2/assume.h +tracepoint.o: $(hdrdir)/ruby/backward/2/attributes.h +tracepoint.o: $(hdrdir)/ruby/backward/2/bool.h +tracepoint.o: $(hdrdir)/ruby/backward/2/inttypes.h +tracepoint.o: $(hdrdir)/ruby/backward/2/limits.h +tracepoint.o: $(hdrdir)/ruby/backward/2/long_long.h +tracepoint.o: $(hdrdir)/ruby/backward/2/stdalign.h +tracepoint.o: $(hdrdir)/ruby/backward/2/stdarg.h tracepoint.o: $(hdrdir)/ruby/debug.h tracepoint.o: $(hdrdir)/ruby/defines.h tracepoint.o: $(hdrdir)/ruby/intern.h +tracepoint.o: $(hdrdir)/ruby/internal/anyargs.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/char.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/double.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/int.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/short.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +tracepoint.o: $(hdrdir)/ruby/internal/assume.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/artificial.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/cold.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/const.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/constexpr.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/deprecated.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/error.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/forceinline.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/format.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/noalias.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/noexcept.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/noinline.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/nonnull.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/pure.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/restrict.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/warning.h +tracepoint.o: $(hdrdir)/ruby/internal/attr/weakref.h +tracepoint.o: $(hdrdir)/ruby/internal/cast.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +tracepoint.o: $(hdrdir)/ruby/internal/compiler_since.h +tracepoint.o: $(hdrdir)/ruby/internal/config.h +tracepoint.o: $(hdrdir)/ruby/internal/constant_p.h +tracepoint.o: $(hdrdir)/ruby/internal/core.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rarray.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rbasic.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rbignum.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rclass.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rdata.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rfile.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rhash.h +tracepoint.o: $(hdrdir)/ruby/internal/core/robject.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rregexp.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rstring.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rstruct.h +tracepoint.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +tracepoint.o: $(hdrdir)/ruby/internal/ctype.h +tracepoint.o: $(hdrdir)/ruby/internal/dllexport.h +tracepoint.o: $(hdrdir)/ruby/internal/dosish.h +tracepoint.o: $(hdrdir)/ruby/internal/error.h +tracepoint.o: $(hdrdir)/ruby/internal/eval.h +tracepoint.o: $(hdrdir)/ruby/internal/event.h +tracepoint.o: $(hdrdir)/ruby/internal/fl_type.h +tracepoint.o: $(hdrdir)/ruby/internal/gc.h +tracepoint.o: $(hdrdir)/ruby/internal/glob.h +tracepoint.o: $(hdrdir)/ruby/internal/globals.h +tracepoint.o: $(hdrdir)/ruby/internal/has/attribute.h +tracepoint.o: $(hdrdir)/ruby/internal/has/builtin.h +tracepoint.o: $(hdrdir)/ruby/internal/has/c_attribute.h +tracepoint.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +tracepoint.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +tracepoint.o: $(hdrdir)/ruby/internal/has/extension.h +tracepoint.o: $(hdrdir)/ruby/internal/has/feature.h +tracepoint.o: $(hdrdir)/ruby/internal/has/warning.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/array.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/bignum.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/class.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/compar.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/complex.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/cont.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/dir.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/enum.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/enumerator.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/error.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/eval.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/file.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/gc.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/hash.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/io.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/load.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/marshal.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/numeric.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/object.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/parse.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/proc.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/process.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/random.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/range.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/sprintf.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/string.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/struct.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/thread.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/time.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/variable.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/vm.h +tracepoint.o: $(hdrdir)/ruby/internal/interpreter.h +tracepoint.o: $(hdrdir)/ruby/internal/iterator.h +tracepoint.o: $(hdrdir)/ruby/internal/memory.h +tracepoint.o: $(hdrdir)/ruby/internal/method.h +tracepoint.o: $(hdrdir)/ruby/internal/module.h +tracepoint.o: $(hdrdir)/ruby/internal/newobj.h +tracepoint.o: $(hdrdir)/ruby/internal/rgengc.h +tracepoint.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +tracepoint.o: $(hdrdir)/ruby/internal/value.h +tracepoint.o: $(hdrdir)/ruby/internal/value_type.h +tracepoint.o: $(hdrdir)/ruby/internal/variable.h +tracepoint.o: $(hdrdir)/ruby/internal/warning_push.h +tracepoint.o: $(hdrdir)/ruby/internal/xmalloc.h tracepoint.o: $(hdrdir)/ruby/missing.h tracepoint.o: $(hdrdir)/ruby/ruby.h tracepoint.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/tracepoint/gc_hook.c b/ruby/ext/-test-/tracepoint/gc_hook.c index 54b469dca..5fd46fa51 100644 --- a/ruby/ext/-test-/tracepoint/gc_hook.c +++ b/ruby/ext/-test-/tracepoint/gc_hook.c @@ -42,14 +42,12 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str, { VALUE tpval; ID tp_key = rb_intern(tp_str); - ID proc_key = rb_intern(proc_str); /* disable previous keys */ if (rb_ivar_defined(module, tp_key) != 0 && RTEST(tpval = rb_ivar_get(module, tp_key))) { rb_tracepoint_disable(tpval); rb_ivar_set(module, tp_key, Qnil); - rb_ivar_set(module, proc_key, Qnil); } if (RTEST(proc)) { @@ -59,7 +57,6 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str, tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc); rb_ivar_set(module, tp_key, tpval); - rb_ivar_set(module, proc_key, proc); /* GC guard */ rb_tracepoint_enable(tpval); } diff --git a/ruby/ext/-test-/typeddata/depend b/ruby/ext/-test-/typeddata/depend index e0dd0653a..9eb0666c7 100644 --- a/ruby/ext/-test-/typeddata/depend +++ b/ruby/ext/-test-/typeddata/depend @@ -4,8 +4,155 @@ typeddata.o: $(arch_hdrdir)/ruby/config.h typeddata.o: $(hdrdir)/ruby.h typeddata.o: $(hdrdir)/ruby/assert.h typeddata.o: $(hdrdir)/ruby/backward.h +typeddata.o: $(hdrdir)/ruby/backward/2/assume.h +typeddata.o: $(hdrdir)/ruby/backward/2/attributes.h +typeddata.o: $(hdrdir)/ruby/backward/2/bool.h +typeddata.o: $(hdrdir)/ruby/backward/2/inttypes.h +typeddata.o: $(hdrdir)/ruby/backward/2/limits.h +typeddata.o: $(hdrdir)/ruby/backward/2/long_long.h +typeddata.o: $(hdrdir)/ruby/backward/2/stdalign.h +typeddata.o: $(hdrdir)/ruby/backward/2/stdarg.h typeddata.o: $(hdrdir)/ruby/defines.h typeddata.o: $(hdrdir)/ruby/intern.h +typeddata.o: $(hdrdir)/ruby/internal/anyargs.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/char.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/double.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/int.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/short.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +typeddata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +typeddata.o: $(hdrdir)/ruby/internal/assume.h +typeddata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +typeddata.o: $(hdrdir)/ruby/internal/attr/artificial.h +typeddata.o: $(hdrdir)/ruby/internal/attr/cold.h +typeddata.o: $(hdrdir)/ruby/internal/attr/const.h +typeddata.o: $(hdrdir)/ruby/internal/attr/constexpr.h +typeddata.o: $(hdrdir)/ruby/internal/attr/deprecated.h +typeddata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +typeddata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +typeddata.o: $(hdrdir)/ruby/internal/attr/error.h +typeddata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +typeddata.o: $(hdrdir)/ruby/internal/attr/forceinline.h +typeddata.o: $(hdrdir)/ruby/internal/attr/format.h +typeddata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +typeddata.o: $(hdrdir)/ruby/internal/attr/noalias.h +typeddata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +typeddata.o: $(hdrdir)/ruby/internal/attr/noexcept.h +typeddata.o: $(hdrdir)/ruby/internal/attr/noinline.h +typeddata.o: $(hdrdir)/ruby/internal/attr/nonnull.h +typeddata.o: $(hdrdir)/ruby/internal/attr/noreturn.h +typeddata.o: $(hdrdir)/ruby/internal/attr/pure.h +typeddata.o: $(hdrdir)/ruby/internal/attr/restrict.h +typeddata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +typeddata.o: $(hdrdir)/ruby/internal/attr/warning.h +typeddata.o: $(hdrdir)/ruby/internal/attr/weakref.h +typeddata.o: $(hdrdir)/ruby/internal/cast.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +typeddata.o: $(hdrdir)/ruby/internal/compiler_since.h +typeddata.o: $(hdrdir)/ruby/internal/config.h +typeddata.o: $(hdrdir)/ruby/internal/constant_p.h +typeddata.o: $(hdrdir)/ruby/internal/core.h +typeddata.o: $(hdrdir)/ruby/internal/core/rarray.h +typeddata.o: $(hdrdir)/ruby/internal/core/rbasic.h +typeddata.o: $(hdrdir)/ruby/internal/core/rbignum.h +typeddata.o: $(hdrdir)/ruby/internal/core/rclass.h +typeddata.o: $(hdrdir)/ruby/internal/core/rdata.h +typeddata.o: $(hdrdir)/ruby/internal/core/rfile.h +typeddata.o: $(hdrdir)/ruby/internal/core/rhash.h +typeddata.o: $(hdrdir)/ruby/internal/core/robject.h +typeddata.o: $(hdrdir)/ruby/internal/core/rregexp.h +typeddata.o: $(hdrdir)/ruby/internal/core/rstring.h +typeddata.o: $(hdrdir)/ruby/internal/core/rstruct.h +typeddata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +typeddata.o: $(hdrdir)/ruby/internal/ctype.h +typeddata.o: $(hdrdir)/ruby/internal/dllexport.h +typeddata.o: $(hdrdir)/ruby/internal/dosish.h +typeddata.o: $(hdrdir)/ruby/internal/error.h +typeddata.o: $(hdrdir)/ruby/internal/eval.h +typeddata.o: $(hdrdir)/ruby/internal/event.h +typeddata.o: $(hdrdir)/ruby/internal/fl_type.h +typeddata.o: $(hdrdir)/ruby/internal/gc.h +typeddata.o: $(hdrdir)/ruby/internal/glob.h +typeddata.o: $(hdrdir)/ruby/internal/globals.h +typeddata.o: $(hdrdir)/ruby/internal/has/attribute.h +typeddata.o: $(hdrdir)/ruby/internal/has/builtin.h +typeddata.o: $(hdrdir)/ruby/internal/has/c_attribute.h +typeddata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +typeddata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +typeddata.o: $(hdrdir)/ruby/internal/has/extension.h +typeddata.o: $(hdrdir)/ruby/internal/has/feature.h +typeddata.o: $(hdrdir)/ruby/internal/has/warning.h +typeddata.o: $(hdrdir)/ruby/internal/intern/array.h +typeddata.o: $(hdrdir)/ruby/internal/intern/bignum.h +typeddata.o: $(hdrdir)/ruby/internal/intern/class.h +typeddata.o: $(hdrdir)/ruby/internal/intern/compar.h +typeddata.o: $(hdrdir)/ruby/internal/intern/complex.h +typeddata.o: $(hdrdir)/ruby/internal/intern/cont.h +typeddata.o: $(hdrdir)/ruby/internal/intern/dir.h +typeddata.o: $(hdrdir)/ruby/internal/intern/enum.h +typeddata.o: $(hdrdir)/ruby/internal/intern/enumerator.h +typeddata.o: $(hdrdir)/ruby/internal/intern/error.h +typeddata.o: $(hdrdir)/ruby/internal/intern/eval.h +typeddata.o: $(hdrdir)/ruby/internal/intern/file.h +typeddata.o: $(hdrdir)/ruby/internal/intern/gc.h +typeddata.o: $(hdrdir)/ruby/internal/intern/hash.h +typeddata.o: $(hdrdir)/ruby/internal/intern/io.h +typeddata.o: $(hdrdir)/ruby/internal/intern/load.h +typeddata.o: $(hdrdir)/ruby/internal/intern/marshal.h +typeddata.o: $(hdrdir)/ruby/internal/intern/numeric.h +typeddata.o: $(hdrdir)/ruby/internal/intern/object.h +typeddata.o: $(hdrdir)/ruby/internal/intern/parse.h +typeddata.o: $(hdrdir)/ruby/internal/intern/proc.h +typeddata.o: $(hdrdir)/ruby/internal/intern/process.h +typeddata.o: $(hdrdir)/ruby/internal/intern/random.h +typeddata.o: $(hdrdir)/ruby/internal/intern/range.h +typeddata.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +typeddata.o: $(hdrdir)/ruby/internal/intern/sprintf.h +typeddata.o: $(hdrdir)/ruby/internal/intern/string.h +typeddata.o: $(hdrdir)/ruby/internal/intern/struct.h +typeddata.o: $(hdrdir)/ruby/internal/intern/thread.h +typeddata.o: $(hdrdir)/ruby/internal/intern/time.h +typeddata.o: $(hdrdir)/ruby/internal/intern/variable.h +typeddata.o: $(hdrdir)/ruby/internal/intern/vm.h +typeddata.o: $(hdrdir)/ruby/internal/interpreter.h +typeddata.o: $(hdrdir)/ruby/internal/iterator.h +typeddata.o: $(hdrdir)/ruby/internal/memory.h +typeddata.o: $(hdrdir)/ruby/internal/method.h +typeddata.o: $(hdrdir)/ruby/internal/module.h +typeddata.o: $(hdrdir)/ruby/internal/newobj.h +typeddata.o: $(hdrdir)/ruby/internal/rgengc.h +typeddata.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +typeddata.o: $(hdrdir)/ruby/internal/value.h +typeddata.o: $(hdrdir)/ruby/internal/value_type.h +typeddata.o: $(hdrdir)/ruby/internal/variable.h +typeddata.o: $(hdrdir)/ruby/internal/warning_push.h +typeddata.o: $(hdrdir)/ruby/internal/xmalloc.h typeddata.o: $(hdrdir)/ruby/missing.h typeddata.o: $(hdrdir)/ruby/ruby.h typeddata.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/typeddata/typeddata.c b/ruby/ext/-test-/typeddata/typeddata.c index ae060960c..2adfd56ae 100644 --- a/ruby/ext/-test-/typeddata/typeddata.c +++ b/ruby/ext/-test-/typeddata/typeddata.c @@ -2,7 +2,7 @@ static const rb_data_type_t test_data = { "typed_data", - {NULL, ruby_xfree, NULL}, + {0, ruby_xfree, 0}, NULL, NULL, 0/* deferred free */, }; @@ -37,7 +37,7 @@ void Init_typeddata(void) { VALUE mBug = rb_define_module("Bug"); - VALUE klass = rb_define_class_under(mBug, "TypedData", rb_cData); + VALUE klass = rb_define_class_under(mBug, "TypedData", rb_cObject); rb_define_alloc_func(klass, test_alloc); rb_define_singleton_method(klass, "check", test_check, 1); rb_define_singleton_method(klass, "make", test_make, 1); diff --git a/ruby/ext/-test-/vm/depend b/ruby/ext/-test-/vm/depend index 0f85d69bb..a01669802 100644 --- a/ruby/ext/-test-/vm/depend +++ b/ruby/ext/-test-/vm/depend @@ -3,8 +3,155 @@ at_exit.o: $(RUBY_EXTCONF_H) at_exit.o: $(arch_hdrdir)/ruby/config.h at_exit.o: $(hdrdir)/ruby/assert.h at_exit.o: $(hdrdir)/ruby/backward.h +at_exit.o: $(hdrdir)/ruby/backward/2/assume.h +at_exit.o: $(hdrdir)/ruby/backward/2/attributes.h +at_exit.o: $(hdrdir)/ruby/backward/2/bool.h +at_exit.o: $(hdrdir)/ruby/backward/2/inttypes.h +at_exit.o: $(hdrdir)/ruby/backward/2/limits.h +at_exit.o: $(hdrdir)/ruby/backward/2/long_long.h +at_exit.o: $(hdrdir)/ruby/backward/2/stdalign.h +at_exit.o: $(hdrdir)/ruby/backward/2/stdarg.h at_exit.o: $(hdrdir)/ruby/defines.h at_exit.o: $(hdrdir)/ruby/intern.h +at_exit.o: $(hdrdir)/ruby/internal/anyargs.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/char.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/double.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/int.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/short.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +at_exit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +at_exit.o: $(hdrdir)/ruby/internal/assume.h +at_exit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +at_exit.o: $(hdrdir)/ruby/internal/attr/artificial.h +at_exit.o: $(hdrdir)/ruby/internal/attr/cold.h +at_exit.o: $(hdrdir)/ruby/internal/attr/const.h +at_exit.o: $(hdrdir)/ruby/internal/attr/constexpr.h +at_exit.o: $(hdrdir)/ruby/internal/attr/deprecated.h +at_exit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +at_exit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +at_exit.o: $(hdrdir)/ruby/internal/attr/error.h +at_exit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +at_exit.o: $(hdrdir)/ruby/internal/attr/forceinline.h +at_exit.o: $(hdrdir)/ruby/internal/attr/format.h +at_exit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +at_exit.o: $(hdrdir)/ruby/internal/attr/noalias.h +at_exit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +at_exit.o: $(hdrdir)/ruby/internal/attr/noexcept.h +at_exit.o: $(hdrdir)/ruby/internal/attr/noinline.h +at_exit.o: $(hdrdir)/ruby/internal/attr/nonnull.h +at_exit.o: $(hdrdir)/ruby/internal/attr/noreturn.h +at_exit.o: $(hdrdir)/ruby/internal/attr/pure.h +at_exit.o: $(hdrdir)/ruby/internal/attr/restrict.h +at_exit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +at_exit.o: $(hdrdir)/ruby/internal/attr/warning.h +at_exit.o: $(hdrdir)/ruby/internal/attr/weakref.h +at_exit.o: $(hdrdir)/ruby/internal/cast.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +at_exit.o: $(hdrdir)/ruby/internal/compiler_since.h +at_exit.o: $(hdrdir)/ruby/internal/config.h +at_exit.o: $(hdrdir)/ruby/internal/constant_p.h +at_exit.o: $(hdrdir)/ruby/internal/core.h +at_exit.o: $(hdrdir)/ruby/internal/core/rarray.h +at_exit.o: $(hdrdir)/ruby/internal/core/rbasic.h +at_exit.o: $(hdrdir)/ruby/internal/core/rbignum.h +at_exit.o: $(hdrdir)/ruby/internal/core/rclass.h +at_exit.o: $(hdrdir)/ruby/internal/core/rdata.h +at_exit.o: $(hdrdir)/ruby/internal/core/rfile.h +at_exit.o: $(hdrdir)/ruby/internal/core/rhash.h +at_exit.o: $(hdrdir)/ruby/internal/core/robject.h +at_exit.o: $(hdrdir)/ruby/internal/core/rregexp.h +at_exit.o: $(hdrdir)/ruby/internal/core/rstring.h +at_exit.o: $(hdrdir)/ruby/internal/core/rstruct.h +at_exit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +at_exit.o: $(hdrdir)/ruby/internal/ctype.h +at_exit.o: $(hdrdir)/ruby/internal/dllexport.h +at_exit.o: $(hdrdir)/ruby/internal/dosish.h +at_exit.o: $(hdrdir)/ruby/internal/error.h +at_exit.o: $(hdrdir)/ruby/internal/eval.h +at_exit.o: $(hdrdir)/ruby/internal/event.h +at_exit.o: $(hdrdir)/ruby/internal/fl_type.h +at_exit.o: $(hdrdir)/ruby/internal/gc.h +at_exit.o: $(hdrdir)/ruby/internal/glob.h +at_exit.o: $(hdrdir)/ruby/internal/globals.h +at_exit.o: $(hdrdir)/ruby/internal/has/attribute.h +at_exit.o: $(hdrdir)/ruby/internal/has/builtin.h +at_exit.o: $(hdrdir)/ruby/internal/has/c_attribute.h +at_exit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +at_exit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +at_exit.o: $(hdrdir)/ruby/internal/has/extension.h +at_exit.o: $(hdrdir)/ruby/internal/has/feature.h +at_exit.o: $(hdrdir)/ruby/internal/has/warning.h +at_exit.o: $(hdrdir)/ruby/internal/intern/array.h +at_exit.o: $(hdrdir)/ruby/internal/intern/bignum.h +at_exit.o: $(hdrdir)/ruby/internal/intern/class.h +at_exit.o: $(hdrdir)/ruby/internal/intern/compar.h +at_exit.o: $(hdrdir)/ruby/internal/intern/complex.h +at_exit.o: $(hdrdir)/ruby/internal/intern/cont.h +at_exit.o: $(hdrdir)/ruby/internal/intern/dir.h +at_exit.o: $(hdrdir)/ruby/internal/intern/enum.h +at_exit.o: $(hdrdir)/ruby/internal/intern/enumerator.h +at_exit.o: $(hdrdir)/ruby/internal/intern/error.h +at_exit.o: $(hdrdir)/ruby/internal/intern/eval.h +at_exit.o: $(hdrdir)/ruby/internal/intern/file.h +at_exit.o: $(hdrdir)/ruby/internal/intern/gc.h +at_exit.o: $(hdrdir)/ruby/internal/intern/hash.h +at_exit.o: $(hdrdir)/ruby/internal/intern/io.h +at_exit.o: $(hdrdir)/ruby/internal/intern/load.h +at_exit.o: $(hdrdir)/ruby/internal/intern/marshal.h +at_exit.o: $(hdrdir)/ruby/internal/intern/numeric.h +at_exit.o: $(hdrdir)/ruby/internal/intern/object.h +at_exit.o: $(hdrdir)/ruby/internal/intern/parse.h +at_exit.o: $(hdrdir)/ruby/internal/intern/proc.h +at_exit.o: $(hdrdir)/ruby/internal/intern/process.h +at_exit.o: $(hdrdir)/ruby/internal/intern/random.h +at_exit.o: $(hdrdir)/ruby/internal/intern/range.h +at_exit.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +at_exit.o: $(hdrdir)/ruby/internal/intern/sprintf.h +at_exit.o: $(hdrdir)/ruby/internal/intern/string.h +at_exit.o: $(hdrdir)/ruby/internal/intern/struct.h +at_exit.o: $(hdrdir)/ruby/internal/intern/thread.h +at_exit.o: $(hdrdir)/ruby/internal/intern/time.h +at_exit.o: $(hdrdir)/ruby/internal/intern/variable.h +at_exit.o: $(hdrdir)/ruby/internal/intern/vm.h +at_exit.o: $(hdrdir)/ruby/internal/interpreter.h +at_exit.o: $(hdrdir)/ruby/internal/iterator.h +at_exit.o: $(hdrdir)/ruby/internal/memory.h +at_exit.o: $(hdrdir)/ruby/internal/method.h +at_exit.o: $(hdrdir)/ruby/internal/module.h +at_exit.o: $(hdrdir)/ruby/internal/newobj.h +at_exit.o: $(hdrdir)/ruby/internal/rgengc.h +at_exit.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +at_exit.o: $(hdrdir)/ruby/internal/value.h +at_exit.o: $(hdrdir)/ruby/internal/value_type.h +at_exit.o: $(hdrdir)/ruby/internal/variable.h +at_exit.o: $(hdrdir)/ruby/internal/warning_push.h +at_exit.o: $(hdrdir)/ruby/internal/xmalloc.h at_exit.o: $(hdrdir)/ruby/missing.h at_exit.o: $(hdrdir)/ruby/ruby.h at_exit.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/-test-/wait/depend b/ruby/ext/-test-/wait/depend new file mode 100644 index 000000000..b5cdd1283 --- /dev/null +++ b/ruby/ext/-test-/wait/depend @@ -0,0 +1,173 @@ +# AUTOGENERATED DEPENDENCIES START +wait.o: $(RUBY_EXTCONF_H) +wait.o: $(arch_hdrdir)/ruby/config.h +wait.o: $(hdrdir)/ruby/assert.h +wait.o: $(hdrdir)/ruby/backward.h +wait.o: $(hdrdir)/ruby/backward/2/assume.h +wait.o: $(hdrdir)/ruby/backward/2/attributes.h +wait.o: $(hdrdir)/ruby/backward/2/bool.h +wait.o: $(hdrdir)/ruby/backward/2/inttypes.h +wait.o: $(hdrdir)/ruby/backward/2/limits.h +wait.o: $(hdrdir)/ruby/backward/2/long_long.h +wait.o: $(hdrdir)/ruby/backward/2/stdalign.h +wait.o: $(hdrdir)/ruby/backward/2/stdarg.h +wait.o: $(hdrdir)/ruby/defines.h +wait.o: $(hdrdir)/ruby/encoding.h +wait.o: $(hdrdir)/ruby/intern.h +wait.o: $(hdrdir)/ruby/internal/anyargs.h +wait.o: $(hdrdir)/ruby/internal/arithmetic.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/double.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/int.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/long.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/short.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +wait.o: $(hdrdir)/ruby/internal/assume.h +wait.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +wait.o: $(hdrdir)/ruby/internal/attr/artificial.h +wait.o: $(hdrdir)/ruby/internal/attr/cold.h +wait.o: $(hdrdir)/ruby/internal/attr/const.h +wait.o: $(hdrdir)/ruby/internal/attr/constexpr.h +wait.o: $(hdrdir)/ruby/internal/attr/deprecated.h +wait.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +wait.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +wait.o: $(hdrdir)/ruby/internal/attr/error.h +wait.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +wait.o: $(hdrdir)/ruby/internal/attr/forceinline.h +wait.o: $(hdrdir)/ruby/internal/attr/format.h +wait.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +wait.o: $(hdrdir)/ruby/internal/attr/noalias.h +wait.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +wait.o: $(hdrdir)/ruby/internal/attr/noexcept.h +wait.o: $(hdrdir)/ruby/internal/attr/noinline.h +wait.o: $(hdrdir)/ruby/internal/attr/nonnull.h +wait.o: $(hdrdir)/ruby/internal/attr/noreturn.h +wait.o: $(hdrdir)/ruby/internal/attr/pure.h +wait.o: $(hdrdir)/ruby/internal/attr/restrict.h +wait.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +wait.o: $(hdrdir)/ruby/internal/attr/warning.h +wait.o: $(hdrdir)/ruby/internal/attr/weakref.h +wait.o: $(hdrdir)/ruby/internal/cast.h +wait.o: $(hdrdir)/ruby/internal/compiler_is.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +wait.o: $(hdrdir)/ruby/internal/compiler_since.h +wait.o: $(hdrdir)/ruby/internal/config.h +wait.o: $(hdrdir)/ruby/internal/constant_p.h +wait.o: $(hdrdir)/ruby/internal/core.h +wait.o: $(hdrdir)/ruby/internal/core/rarray.h +wait.o: $(hdrdir)/ruby/internal/core/rbasic.h +wait.o: $(hdrdir)/ruby/internal/core/rbignum.h +wait.o: $(hdrdir)/ruby/internal/core/rclass.h +wait.o: $(hdrdir)/ruby/internal/core/rdata.h +wait.o: $(hdrdir)/ruby/internal/core/rfile.h +wait.o: $(hdrdir)/ruby/internal/core/rhash.h +wait.o: $(hdrdir)/ruby/internal/core/robject.h +wait.o: $(hdrdir)/ruby/internal/core/rregexp.h +wait.o: $(hdrdir)/ruby/internal/core/rstring.h +wait.o: $(hdrdir)/ruby/internal/core/rstruct.h +wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +wait.o: $(hdrdir)/ruby/internal/ctype.h +wait.o: $(hdrdir)/ruby/internal/dllexport.h +wait.o: $(hdrdir)/ruby/internal/dosish.h +wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h +wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h +wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h +wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h +wait.o: $(hdrdir)/ruby/internal/encoding/re.h +wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +wait.o: $(hdrdir)/ruby/internal/encoding/string.h +wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h +wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h +wait.o: $(hdrdir)/ruby/internal/error.h +wait.o: $(hdrdir)/ruby/internal/eval.h +wait.o: $(hdrdir)/ruby/internal/event.h +wait.o: $(hdrdir)/ruby/internal/fl_type.h +wait.o: $(hdrdir)/ruby/internal/gc.h +wait.o: $(hdrdir)/ruby/internal/glob.h +wait.o: $(hdrdir)/ruby/internal/globals.h +wait.o: $(hdrdir)/ruby/internal/has/attribute.h +wait.o: $(hdrdir)/ruby/internal/has/builtin.h +wait.o: $(hdrdir)/ruby/internal/has/c_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/extension.h +wait.o: $(hdrdir)/ruby/internal/has/feature.h +wait.o: $(hdrdir)/ruby/internal/has/warning.h +wait.o: $(hdrdir)/ruby/internal/intern/array.h +wait.o: $(hdrdir)/ruby/internal/intern/bignum.h +wait.o: $(hdrdir)/ruby/internal/intern/class.h +wait.o: $(hdrdir)/ruby/internal/intern/compar.h +wait.o: $(hdrdir)/ruby/internal/intern/complex.h +wait.o: $(hdrdir)/ruby/internal/intern/cont.h +wait.o: $(hdrdir)/ruby/internal/intern/dir.h +wait.o: $(hdrdir)/ruby/internal/intern/enum.h +wait.o: $(hdrdir)/ruby/internal/intern/enumerator.h +wait.o: $(hdrdir)/ruby/internal/intern/error.h +wait.o: $(hdrdir)/ruby/internal/intern/eval.h +wait.o: $(hdrdir)/ruby/internal/intern/file.h +wait.o: $(hdrdir)/ruby/internal/intern/gc.h +wait.o: $(hdrdir)/ruby/internal/intern/hash.h +wait.o: $(hdrdir)/ruby/internal/intern/io.h +wait.o: $(hdrdir)/ruby/internal/intern/load.h +wait.o: $(hdrdir)/ruby/internal/intern/marshal.h +wait.o: $(hdrdir)/ruby/internal/intern/numeric.h +wait.o: $(hdrdir)/ruby/internal/intern/object.h +wait.o: $(hdrdir)/ruby/internal/intern/parse.h +wait.o: $(hdrdir)/ruby/internal/intern/proc.h +wait.o: $(hdrdir)/ruby/internal/intern/process.h +wait.o: $(hdrdir)/ruby/internal/intern/random.h +wait.o: $(hdrdir)/ruby/internal/intern/range.h +wait.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h +wait.o: $(hdrdir)/ruby/internal/intern/string.h +wait.o: $(hdrdir)/ruby/internal/intern/struct.h +wait.o: $(hdrdir)/ruby/internal/intern/thread.h +wait.o: $(hdrdir)/ruby/internal/intern/time.h +wait.o: $(hdrdir)/ruby/internal/intern/variable.h +wait.o: $(hdrdir)/ruby/internal/intern/vm.h +wait.o: $(hdrdir)/ruby/internal/interpreter.h +wait.o: $(hdrdir)/ruby/internal/iterator.h +wait.o: $(hdrdir)/ruby/internal/memory.h +wait.o: $(hdrdir)/ruby/internal/method.h +wait.o: $(hdrdir)/ruby/internal/module.h +wait.o: $(hdrdir)/ruby/internal/newobj.h +wait.o: $(hdrdir)/ruby/internal/rgengc.h +wait.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +wait.o: $(hdrdir)/ruby/internal/value.h +wait.o: $(hdrdir)/ruby/internal/value_type.h +wait.o: $(hdrdir)/ruby/internal/variable.h +wait.o: $(hdrdir)/ruby/internal/warning_push.h +wait.o: $(hdrdir)/ruby/internal/xmalloc.h +wait.o: $(hdrdir)/ruby/io.h +wait.o: $(hdrdir)/ruby/missing.h +wait.o: $(hdrdir)/ruby/onigmo.h +wait.o: $(hdrdir)/ruby/oniguruma.h +wait.o: $(hdrdir)/ruby/ruby.h +wait.o: $(hdrdir)/ruby/st.h +wait.o: $(hdrdir)/ruby/subst.h +wait.o: wait.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/wait/extconf.rb b/ruby/ext/-test-/wait/extconf.rb new file mode 100644 index 000000000..92787876a --- /dev/null +++ b/ruby/ext/-test-/wait/extconf.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: false +create_makefile("-test-/wait") diff --git a/ruby/ext/-test-/wait/wait.c b/ruby/ext/-test-/wait/wait.c new file mode 100644 index 000000000..b73ee3580 --- /dev/null +++ b/ruby/ext/-test-/wait/wait.c @@ -0,0 +1,39 @@ +#include "ruby/ruby.h" +#include "ruby/io.h" + +static VALUE +io_wait(VALUE klass, VALUE io, VALUE events, VALUE timeout) +{ + return rb_io_wait(io, events, timeout); +} + +static VALUE +io_maybe_wait(VALUE klass, VALUE error, VALUE io, VALUE events, VALUE timeout) +{ + return rb_io_maybe_wait(RB_NUM2INT(error), io, events, timeout); +} + +static VALUE +io_maybe_wait_readable(VALUE klass, VALUE error, VALUE io, VALUE timeout) +{ + return RB_INT2NUM( + rb_io_maybe_wait_readable(RB_NUM2INT(error), io, timeout) + ); +} + +static VALUE +io_maybe_wait_writable(VALUE klass, VALUE error, VALUE io, VALUE timeout) +{ + return RB_INT2NUM( + rb_io_maybe_wait_writable(RB_NUM2INT(error), io, timeout) + ); +} + +void +Init_wait(void) +{ + rb_define_singleton_method(rb_cIO, "io_wait", io_wait, 3); + rb_define_singleton_method(rb_cIO, "io_maybe_wait", io_maybe_wait, 4); + rb_define_singleton_method(rb_cIO, "io_maybe_wait_readable", io_maybe_wait_readable, 3); + rb_define_singleton_method(rb_cIO, "io_maybe_wait_writable", io_maybe_wait_writable, 3); +} diff --git a/ruby/ext/-test-/wait_for_single_fd/depend b/ruby/ext/-test-/wait_for_single_fd/depend deleted file mode 100644 index 8549fca78..000000000 --- a/ruby/ext/-test-/wait_for_single_fd/depend +++ /dev/null @@ -1,17 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -wait_for_single_fd.o: $(RUBY_EXTCONF_H) -wait_for_single_fd.o: $(arch_hdrdir)/ruby/config.h -wait_for_single_fd.o: $(hdrdir)/ruby/assert.h -wait_for_single_fd.o: $(hdrdir)/ruby/backward.h -wait_for_single_fd.o: $(hdrdir)/ruby/defines.h -wait_for_single_fd.o: $(hdrdir)/ruby/encoding.h -wait_for_single_fd.o: $(hdrdir)/ruby/intern.h -wait_for_single_fd.o: $(hdrdir)/ruby/io.h -wait_for_single_fd.o: $(hdrdir)/ruby/missing.h -wait_for_single_fd.o: $(hdrdir)/ruby/onigmo.h -wait_for_single_fd.o: $(hdrdir)/ruby/oniguruma.h -wait_for_single_fd.o: $(hdrdir)/ruby/ruby.h -wait_for_single_fd.o: $(hdrdir)/ruby/st.h -wait_for_single_fd.o: $(hdrdir)/ruby/subst.h -wait_for_single_fd.o: wait_for_single_fd.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/-test-/wait_for_single_fd/extconf.rb b/ruby/ext/-test-/wait_for_single_fd/extconf.rb deleted file mode 100644 index 2a976c8f4..000000000 --- a/ruby/ext/-test-/wait_for_single_fd/extconf.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: false -headers = %w(sys/types.h sys/time.h sys/event.h).select { |h| have_header(h) } -have_func('kqueue', headers) -create_makefile("-test-/wait_for_single_fd") diff --git a/ruby/ext/-test-/wait_for_single_fd/wait_for_single_fd.c b/ruby/ext/-test-/wait_for_single_fd/wait_for_single_fd.c deleted file mode 100644 index b8a33979b..000000000 --- a/ruby/ext/-test-/wait_for_single_fd/wait_for_single_fd.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "ruby/ruby.h" -#include "ruby/io.h" - -static VALUE -wait_for_single_fd(VALUE ign, VALUE fd, VALUE events, VALUE timeout) -{ - struct timeval tv; - struct timeval *tvp = NULL; - int rc; - - if (!NIL_P(timeout)) { - tv = rb_time_timeval(timeout); - tvp = &tv; - } - - rc = rb_wait_for_single_fd(NUM2INT(fd), NUM2INT(events), tvp); - if (rc == -1) - rb_sys_fail("rb_wait_for_single_fd"); - return INT2NUM(rc); -} - -#ifdef HAVE_KQUEUE -/* ensure rb_wait_for_single_fd works on kqueue descriptors */ -#include -#include -#include -static VALUE -kqueue_test_wait(VALUE klass) -{ - int kqfd = -1; - int p[2] = { -1, -1 }; - struct timeval tv = { 0, 0 }; - const struct timespec ts = { 1, 0 }; - struct kevent kev; - const char *msg; - VALUE ret = Qfalse; - int e = 0; - int n; - - msg = "pipe"; - if (rb_cloexec_pipe(p) < 0) goto err; - - msg = "kqueue"; - kqfd = kqueue(); - if (kqfd < 0) goto err; - - n = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN, &tv); - if (n != 0) { - msg = "spurious wakeup"; - errno = 0; - goto err; - } - - msg = "write"; - if (write(p[1], "", 1) < 0) goto err; - - EV_SET(&kev, p[0], EVFILT_READ, EV_ADD, 0, 0, 0); - - msg = "kevent"; - n = kevent(kqfd, &kev, 1, &kev, 1, &ts); - if (n < 0) goto err; - msg = NULL; - if (n == 1) { - n = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN, &tv); - ret = INT2NUM(n); - } - else { - rb_warn("kevent did not return readiness"); - } -err: - if (msg) e = errno; - if (p[0] >= 0) close(p[0]); - if (p[1] >= 0) close(p[1]); - if (kqfd >= 0) close(kqfd); - if (msg) { - if (e) rb_syserr_fail(e, msg); - rb_raise(rb_eRuntimeError, "%s", msg); - } - return ret; -} -#endif /* HAVE_KQUEUE */ - -void -Init_wait_for_single_fd(void) -{ - rb_define_const(rb_cObject, "RB_WAITFD_IN", INT2NUM(RB_WAITFD_IN)); - rb_define_const(rb_cObject, "RB_WAITFD_OUT", INT2NUM(RB_WAITFD_OUT)); - rb_define_const(rb_cObject, "RB_WAITFD_PRI", INT2NUM(RB_WAITFD_PRI)); - rb_define_singleton_method(rb_cIO, "wait_for_single_fd", - wait_for_single_fd, 3); -#ifdef HAVE_KQUEUE - rb_define_singleton_method(rb_cIO, "kqueue_test_wait", kqueue_test_wait, 0); -#endif -} diff --git a/ruby/ext/-test-/win32/console/attribute.c b/ruby/ext/-test-/win32/console/attribute.c index a5f80fcaf..e3e80a199 100644 --- a/ruby/ext/-test-/win32/console/attribute.c +++ b/ruby/ext/-test-/win32/console/attribute.c @@ -13,7 +13,7 @@ io_handle(VALUE io) } static VALUE -console_info(VALUE io) +console_info(VALUE klass, VALUE io) { HANDLE h = io_handle(io); CONSOLE_SCREEN_BUFFER_INFO csbi; @@ -29,7 +29,7 @@ console_info(VALUE io) } static VALUE -console_set_attribute(VALUE io, VALUE attr) +console_set_attribute(VALUE klass, VALUE io, VALUE attr) { HANDLE h = io_handle(io); @@ -47,8 +47,8 @@ Init_attribute(VALUE m) "size_x", "size_y", "cur_x", "cur_y", "attr", NULL); - rb_define_method(rb_cIO, "console_info", console_info, 0); - rb_define_method(rb_cIO, "console_attribute", console_set_attribute, 1); + rb_define_singleton_method(m, "console_info", console_info, 1); + rb_define_singleton_method(m, "console_attribute", console_set_attribute, 2); rb_define_const(m, "FOREGROUND_MASK", INT2FIX(FOREGROUND_MASK)); rb_define_const(m, "FOREGROUND_BLUE", INT2FIX(FOREGROUND_BLUE)); diff --git a/ruby/ext/.document b/ruby/ext/.document index 6a491576a..aeb40c60f 100644 --- a/ruby/ext/.document +++ b/ruby/ext/.document @@ -2,9 +2,15 @@ bigdecimal/bigdecimal.c bigdecimal/lib +cgi/escape/escape.c continuation/continuation.c coverage/coverage.c +coverage/lib date/date_core.c +date/date_parse.c +date/date_strftime.c +date/date_strptime.c +date/lib dbm/dbm.c digest/bubblebabble/bubblebabble.c digest/digest.c @@ -13,6 +19,7 @@ digest/md5/md5init.c digest/rmd160/rmd160init.c digest/sha1/sha1init.c digest/sha2/sha2init.c +digest/sha2/lib etc/etc.c fcntl/fcntl.c fiber/fiber.c @@ -20,21 +27,26 @@ fiddle/closure.c fiddle/conversions.c fiddle/fiddle.c fiddle/function.c +fiddle/pinned.c fiddle/pointer.c fiddle/handle.c fiddle/lib gdbm/gdbm.c io/console/console.c +io/console/lib io/nonblock/nonblock.c io/wait/wait.c json/generator/generator.c json/lib json/parser/parser.c +monitor/lib +monitor/monitor.c nkf/lib nkf/nkf.c objspace/objspace.c objspace/objspace_dump.c objspace/object_tracing.c +objspace/lib openssl/lib openssl/ossl.c openssl/ossl_asn1.c @@ -58,6 +70,7 @@ openssl/ossl_pkey_rsa.c openssl/ossl_rand.c openssl/ossl_ssl.c openssl/ossl_ssl_session.c +openssl/ossl_ts.c openssl/ossl_x509.c openssl/ossl_x509attr.c openssl/ossl_x509cert.c @@ -78,14 +91,16 @@ psych/psych_yaml_tree.c pty/lib pty/pty.c racc/cparse/cparse.c +rbconfig/sizeof/*.c readline/readline.c ripper/lib -sdbm/init.c socket stringio/stringio.c strscan/strscan.c syslog/syslog.c syslog/lib +win32/lib +win32/resolv/*.c win32ole/lib win32ole/*.c zlib/zlib.c diff --git a/ruby/ext/Setup b/ruby/ext/Setup index ac79c86f8..0376e2fc6 100644 --- a/ruby/ext/Setup +++ b/ruby/ext/Setup @@ -33,7 +33,6 @@ #rbconfig/sizeof #readline #ripper -#sdbm #socket #stringio #strscan diff --git a/ruby/ext/Setup.atheos b/ruby/ext/Setup.atheos index 90a7d0134..3f6263b1e 100644 --- a/ruby/ext/Setup.atheos +++ b/ruby/ext/Setup.atheos @@ -20,7 +20,6 @@ pty racc/parse readline ripper -sdbm socket stringio strscan diff --git a/ruby/ext/Setup.nt b/ruby/ext/Setup.nt index fb5989b87..dc36aa868 100644 --- a/ruby/ext/Setup.nt +++ b/ruby/ext/Setup.nt @@ -21,7 +21,6 @@ nkf racc/cparse #readline #ripper -sdbm socket stringio strscan diff --git a/ruby/ext/bigdecimal/bigdecimal.c b/ruby/ext/bigdecimal/bigdecimal.c index 7ac883730..f4dcb2ee7 100644 --- a/ruby/ext/bigdecimal/bigdecimal.c +++ b/ruby/ext/bigdecimal/bigdecimal.c @@ -14,6 +14,7 @@ #include "ruby/util.h" #ifndef BIGDECIMAL_DEBUG +# undef NDEBUG # define NDEBUG #endif #include @@ -24,20 +25,16 @@ #include #include #include -#include "math.h" #ifdef HAVE_IEEEFP_H #include #endif +#include "bits.h" +#include "static_assert.h" + /* #define ENABLE_NUMERIC_STRING */ -#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))) #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) @@ -65,20 +62,22 @@ static ID id_eq; static ID id_half; /* 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 RMPD_COMPONENT_FIGURES -#define BASE RMPD_BASE +#define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES +#define BASE BIGDECIMAL_BASE #define HALF_BASE (BASE/2) #define BASE1 (BASE/10) -#ifndef DBLE_FIG -#define DBLE_FIG (DBL_DIG+1) /* figure of double */ -#endif +#define LOG10_2 0.3010299956639812 #ifndef RRATIONAL_ZERO_P # define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \ @@ -103,30 +102,6 @@ static ID id_half; # define RB_OBJ_STRING(obj) StringValueCStr(obj) #endif -#ifndef HAVE_RB_RATIONAL_NUM -static inline VALUE -rb_rational_num(VALUE rat) -{ -#ifdef HAVE_TYPE_STRUCT_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 HAVE_TYPE_STRUCT_RRATIONAL - return RRATIONAL(rat)->den; -#else - return rb_funcall(rat, rb_intern("denominator"), 0); -#endif -} -#endif - #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0) #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0) @@ -140,7 +115,9 @@ rb_rational_den(VALUE rat) */ static unsigned short VpGetException(void); static void VpSetException(unsigned short f); -static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v); +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); @@ -152,6 +129,12 @@ 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) { @@ -162,14 +145,19 @@ static size_t BigDecimal_memsize(const void *ptr) { const Real *pv = ptr; - return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT)); + 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 + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE #endif }; @@ -179,21 +167,6 @@ is_kind_of_BigDecimal(VALUE const v) return rb_typeddata_is_kind_of(v, &BigDecimal_data_type); } -static VALUE -ToValue(Real *p) -{ - if (VpIsNaN(p)) { - VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0); - } - else if (VpIsPosInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0); - } - else if (VpIsNegInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0); - } - return p->obj; -} - NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE)); static void @@ -213,95 +186,67 @@ cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v) } 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) { - ENTER(1); - Real *pv; - VALUE num, bg; - char szD[128]; - VALUE orig = Qundef; - double d; + const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec; -again: switch(TYPE(v)) { case T_FLOAT: - if (prec < 0) goto unable_to_coerce_without_prec; - if (prec > DBL_DIG+1) goto SomeOneMayDoIt; - d = RFLOAT_VALUE(v); - if (!isfinite(d)) { - pv = VpCreateRbObject(1, NULL); - VpDtoV(pv, d); - return pv; - } - if (d != 0.0) { - v = rb_funcall(v, id_to_r, 0); - goto again; - } - if (1/d < 0.0) { - return VpCreateRbObject(prec, "-0"); - } - return VpCreateRbObject(prec, "0"); + v = rb_float_convert_to_BigDecimal(v, digs, must); + break; case T_RATIONAL: - if (prec < 0) goto unable_to_coerce_without_prec; - - if (orig == Qundef ? (orig = v, 1) : orig != v) { - num = rb_rational_num(v); - pv = GetVpValueWithPrec(num, -1, must); - if (pv == NULL) goto SomeOneMayDoIt; - - v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec)); - goto again; - } - - v = orig; - goto SomeOneMayDoIt; + v = rb_rational_convert_to_BigDecimal(v, digs, must); + break; case T_DATA: - if (is_kind_of_BigDecimal(v)) { - pv = DATA_PTR(v); - return pv; - } - else { - goto SomeOneMayDoIt; - } - break; + if (!is_kind_of_BigDecimal(v)) { + goto SomeOneMayDoIt; + } + break; - case T_FIXNUM: - sprintf(szD, "%ld", FIX2LONG(v)); - return VpCreateRbObject(VpBaseFig() * 2 + 1, szD); + case T_FIXNUM: { + char szD[128]; + sprintf(szD, "%ld", FIX2LONG(v)); + v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must); + break; + } #ifdef ENABLE_NUMERIC_STRING - case T_STRING: - StringValueCStr(v); - return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1, - RSTRING_PTR(v)); + 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: - bg = rb_big2str(v, 10); - PUSH(bg); - return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1, - RSTRING_PTR(bg)); + 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 */ - -unable_to_coerce_without_prec: - if (must) { - rb_raise(rb_eArgError, - "%"PRIsVALUE" can't be coerced into BigDecimal without a precision", - RB_OBJ_CLASSNAME(v)); - } - return NULL; } static Real* @@ -311,11 +256,13 @@ GetVpValue(VALUE v, int must) } /* call-seq: - * BigDecimal.double_fig + * 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 * - * The BigDecimal.double_fig class method returns the number of digits a - * Float number is allowed to have. The result depends upon the CPU and OS - * in use. */ static VALUE BigDecimal_double_fig(VALUE self) @@ -324,15 +271,16 @@ BigDecimal_double_fig(VALUE self) } /* call-seq: - * big_decimal.precs -> array + * precs -> array * - * Returns an Array of two Integer values. + * Returns an Array of two Integer values that represent platform-dependent + * internal storage properties. * - * The first value is the current number of significant digits in the - * BigDecimal. The second value is the maximum number of significant digits - * for the BigDecimal. + * 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. * - * BigDecimal('5').precs #=> [9, 18] */ static VALUE @@ -342,19 +290,251 @@ BigDecimal_prec(VALUE self) 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(INT2NUM(p->Prec*VpBaseFig()), - INT2NUM(p->MaxPrec*VpBaseFig())); + 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: hash + * call-seq: + * precision -> integer * - * Creates a hash for this BigDecimal. + * 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").scale # => 0 + * BigDecimal("1").scale # => 1 + * BigDecimal("1.1").scale # => 2 + * BigDecimal("3.1415").scale # => 5 + * BigDecimal("-1e20").precision # => 1 + * BigDecimal("1e-20").precision # => 1 + * BigDecimal("Infinity").scale # => 0 + * BigDecimal("-Infinity").scale # => 0 + * BigDecimal("NaN").scale # => 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. * - * Two BigDecimals with equal sign, - * fractional part and exponent have the same hash. */ static VALUE BigDecimal_hash(VALUE self) @@ -367,23 +547,23 @@ BigDecimal_hash(VALUE self) 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(BDIGIT)*p->Prec); - hash += p->exponent; + hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec); + hash += p->exponent; } return ST2FIX(hash); } /* - * call-seq: _dump + * call-seq: + * _dump -> string * - * Method used to provide marshalling support. + * Returns a string representing the marshalling of +self+. + * See module Marshal. * - * inf = BigDecimal('Infinity') - * #=> Infinity - * BigDecimal._load(inf._dump) - * #=> Infinity + * inf = BigDecimal('Infinity') # => Infinity + * dumped = inf._dump # => "9:Infinity" + * BigDecimal._load(dumped) # => Infinity * - * See the Marshal module. */ static VALUE BigDecimal_dump(int argc, VALUE *argv, VALUE self) @@ -425,12 +605,12 @@ BigDecimal_load(VALUE self, VALUE str) m = m*10 + (unsigned long)(ch-'0'); } if (m > VpBaseFig()) m -= VpBaseFig(); - GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self)); + GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true)); m /= VpBaseFig(); if (m && pv->MaxPrec > m) { pv->MaxPrec = m+1; } - return ToValue(pv); + return VpCheckGetValue(pv); } static unsigned short @@ -517,42 +697,166 @@ check_rounding_mode(VALUE const v) return sw; } -/* call-seq: - * BigDecimal.mode(mode, value) - * - * Controls handling of arithmetic exceptions and rounding. If no value - * is supplied, the current value is returned. - * - * Six values of the mode parameter control the handling of arithmetic - * exceptions: - * - * BigDecimal::EXCEPTION_NaN - * BigDecimal::EXCEPTION_INFINITY - * BigDecimal::EXCEPTION_UNDERFLOW - * BigDecimal::EXCEPTION_OVERFLOW - * BigDecimal::EXCEPTION_ZERODIVIDE - * BigDecimal::EXCEPTION_ALL - * - * For each mode parameter above, if the value set is false, computation - * continues after an arithmetic exception of the appropriate type. - * When computation continues, results are as follows: - * - * EXCEPTION_NaN:: NaN - * EXCEPTION_INFINITY:: +Infinity or -Infinity - * EXCEPTION_UNDERFLOW:: 0 - * EXCEPTION_OVERFLOW:: +Infinity or -Infinity - * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity - * - * One value of the mode parameter controls the rounding of numeric values: - * BigDecimal::ROUND_MODE. The values it can take are: - * - * ROUND_UP, :up:: round away from zero - * ROUND_DOWN, :down, :truncate:: round towards zero (truncate) - * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default) - * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero. - * ROUND_HALF_EVEN, :half_even, :banker:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards the even neighbor (Banker's rounding) - * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil) - * ROUND_FLOOR, :floor:: round towards negative infinity (floor) +/* 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 @@ -640,25 +944,54 @@ GetPrecisionInt(VALUE v) 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) +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, 1, 1); - RTYPEDDATA_DATA(obj) = pv; - pv->obj = obj; - RB_OBJ_FREEZE(obj); + 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) +VpCreateRbObject(size_t mx, const char *str, bool raise_exception) { - return VpNewRbClass(mx, str, rb_cBigDecimal); + return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception); } -#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) -#define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) +#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG)) + +static Real * +VpReallocReal(Real *pv, size_t prec) +{ + VALUE obj = pv ? pv->obj : 0; + Real *new_pv = (Real *)VpMemRealloc(pv, offsetof(Real, frac) + prec * sizeof(DECDIG)); + if (obj) { + new_pv->obj = 0; + BigDecimal_wrap_struct(obj, new_pv); + } + return new_pv; +} static Real * VpCopy(Real *pv, Real const* const x) @@ -671,7 +1004,7 @@ VpCopy(Real *pv, Real const* const x) pv->exponent = x->exponent; pv->sign = x->sign; pv->flag = x->flag; - MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec); + MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec); return pv; } @@ -710,15 +1043,7 @@ BigDecimal_IsFinite(VALUE self) static void BigDecimal_check_num(Real *p) { - if (VpIsNaN(p)) { - VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1); - } - else if (VpIsPosInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1); - } - else if (VpIsNegInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1); - } + VpCheckException(p, true); } static VALUE BigDecimal_split(VALUE self); @@ -741,7 +1066,7 @@ BigDecimal_to_i(VALUE self) if (e <= 0) return INT2FIX(0); nf = VpBaseFig(); if (e <= nf) { - return LONG2NUM((long)(VpGetSign(p) * (BDIGIT_DBL_SIGNED)p->frac[0])); + return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0])); } else { VALUE a = BigDecimal_split(self); @@ -875,8 +1200,8 @@ BigDecimal_coerce(VALUE self, VALUE other) Real *b; if (RB_TYPE_P(other, T_FLOAT)) { - GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1)); - obj = rb_assoc_new(ToValue(b), self); + GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1)); + obj = rb_assoc_new(VpCheckGetValue(b), self); } else { if (RB_TYPE_P(other, T_RATIONAL)) { @@ -893,12 +1218,14 @@ BigDecimal_coerce(VALUE self, VALUE other) } /* - * call-seq: - * +big_decimal -> big_decimal + * call-seq: + * +big_decimal -> self + * + * Returns +self+: * - * Return self. + * +BigDecimal(5) # => 0.5e1 + * +BigDecimal(-5) # => -0.5e1 * - * +BigDecimal('5') #=> 0.5e1 */ static VALUE @@ -908,22 +1235,21 @@ BigDecimal_uplus(VALUE self) } /* - * Document-method: BigDecimal#add - * Document-method: BigDecimal#+ + * call-seq: + * self + value -> bigdecimal * - * call-seq: - * add(value, digits) + * Returns the \BigDecimal sum of +self+ and +value+: * - * Add the specified 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) * - * e.g. - * c = a.add(b,n) - * c = a + b + * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. * - * 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_add(VALUE self, VALUE r) { @@ -933,7 +1259,7 @@ BigDecimal_add(VALUE self, VALUE r) GUARD_OBJ(a, GetVpValue(self, 1)); if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + b = GetVpValueWithPrec(r, 0, 1); } else if (RB_TYPE_P(r, T_RATIONAL)) { b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); @@ -950,11 +1276,11 @@ BigDecimal_add(VALUE self, VALUE r) mx = GetAddSubPrec(a, b); if (mx == (size_t)-1L) { - GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); + GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true)); VpAddSub(c, a, b, 1); } else { - GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true)); if(!mx) { VpSetInf(c, VpGetSign(a)); } @@ -962,24 +1288,21 @@ BigDecimal_add(VALUE self, VALUE r) VpAddSub(c, a, b, 1); } } - return ToValue(c); + return VpCheckGetValue(c); } - /* call-seq: - * a - b -> bigdecimal - * - * Subtract the specified value. + /* call-seq: + * self - value -> bigdecimal * - * e.g. - * c = a - b + * Returns the \BigDecimal difference of +self+ and +value+: * - * The precision of the result value depends on the type of +b+. + * 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) * - * If +b+ is a Float, the precision of the result is Float::DIG+1. - * - * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of - * internal representation from platform. So, it's return value is platform - * dependent. + * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. * */ static VALUE @@ -991,7 +1314,7 @@ BigDecimal_sub(VALUE self, VALUE r) GUARD_OBJ(a, GetVpValue(self,1)); if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + b = GetVpValueWithPrec(r, 0, 1); } else if (RB_TYPE_P(r, T_RATIONAL)) { b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); @@ -1008,11 +1331,11 @@ BigDecimal_sub(VALUE self, VALUE r) mx = GetAddSubPrec(a,b); if (mx == (size_t)-1L) { - GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); + GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true)); VpAddSub(c, a, b, -1); } else { - GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true)); if (!mx) { VpSetInf(c,VpGetSign(a)); } @@ -1020,7 +1343,7 @@ BigDecimal_sub(VALUE self, VALUE r) VpAddSub(c, a, b, -1); } } - return ToValue(c); + return VpCheckGetValue(c); } static VALUE @@ -1041,7 +1364,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op) break; case T_FLOAT: - GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0)); + GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0)); break; case T_RATIONAL: @@ -1158,12 +1481,19 @@ BigDecimal_eq(VALUE self, VALUE r) return BigDecimalCmp(self, r, '='); } -/* call-seq: - * a < b +/* call-seq: + * self < other -> true or false + * + * Returns +true+ if +self+ is less than +other+, +false+ otherwise: * - * Returns true if a is less than b. + * 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. * - * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce). */ static VALUE BigDecimal_lt(VALUE self, VALUE r) @@ -1171,12 +1501,20 @@ BigDecimal_lt(VALUE self, VALUE r) return BigDecimalCmp(self, r, '<'); } -/* call-seq: - * a <= b +/* 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 * - * Returns true if a is less than or equal to b. + * Raises an exception if the comparison cannot be made. * - * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce). */ static VALUE BigDecimal_le(VALUE self, VALUE r) @@ -1184,12 +1522,19 @@ BigDecimal_le(VALUE self, VALUE r) return BigDecimalCmp(self, r, 'L'); } -/* call-seq: - * a > b +/* 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 * - * Returns true if a is greater than b. + * Raises an exception if the comparison cannot be made. * - * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce). */ static VALUE BigDecimal_gt(VALUE self, VALUE r) @@ -1197,12 +1542,20 @@ BigDecimal_gt(VALUE self, VALUE r) return BigDecimalCmp(self, r, '>'); } -/* call-seq: - * a >= b +/* 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 * - * Returns true if a is greater than or equal to b. + * Raises an exception if the comparison cannot be made. * - * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce) */ static VALUE BigDecimal_ge(VALUE self, VALUE r) @@ -1212,11 +1565,14 @@ BigDecimal_ge(VALUE self, VALUE r) /* * call-seq: - * -big_decimal -> big_decimal + * -self -> bigdecimal * - * Return the negation of self. + * Returns the \BigDecimal negation of self: + * + * b0 = BigDecimal('1.5') + * b1 = -b0 # => -0.15e1 + * b2 = -b1 # => 0.15e1 * - * -BigDecimal('5') #=> -0.5e1 */ static VALUE @@ -1225,26 +1581,11 @@ BigDecimal_neg(VALUE self) ENTER(5); Real *c, *a; GUARD_OBJ(a, GetVpValue(self, 1)); - GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true)); VpAsgn(c, a, -1); - return ToValue(c); + return VpCheckGetValue(c); } - /* - * Document-method: BigDecimal#mult - * - * call-seq: mult(value, digits) - * - * Multiply by the specified value. - * - * e.g. - * c = a.mult(b,n) - * c = a * b - * - * 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_mult(VALUE self, VALUE r) { @@ -1254,7 +1595,7 @@ BigDecimal_mult(VALUE self, VALUE r) GUARD_OBJ(a, GetVpValue(self, 1)); if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + b = GetVpValueWithPrec(r, 0, 1); } else if (RB_TYPE_P(r, T_RATIONAL)) { b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); @@ -1267,52 +1608,74 @@ BigDecimal_mult(VALUE self, VALUE r) SAVE(b); mx = a->Prec + b->Prec; - GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true)); VpMult(c, a, b); - return ToValue(c); + return VpCheckGetValue(c); } static VALUE -BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r) +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; - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + 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)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r, 0); + rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); } - if (!b) return DoSomeOne(self, r, '/'); - SAVE(b); + if (!is_kind_of_BigDecimal(rr)) { + return DoSomeOne(self, r, '/'); + } + TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b); + SAVE(b); *div = b; - mx = a->Prec + vabs(a->exponent); - if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); - mx++; /* NOTE: An additional digit is needed for the compatibility to - the version 1.2.1 and the former. */ - mx = (mx + 1) * VpBaseFig(); - GUARD_OBJ((*c), VpCreateRbObject(mx, "#0")); - GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + + mx = (a->Prec > b->Prec) ? a->Prec : b->Prec; + mx *= BASE_FIG; + + 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; + + if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) + mx = 2*BIGDECIMAL_DOUBLE_FIGURES; + + GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true)); + GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true)); VpDivd(*c, *res, a, b); + return Qnil; } +static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod); + /* call-seq: - * a / b -> bigdecimal - * quo(value) -> bigdecimal + * 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) @@ -1320,7 +1683,7 @@ BigDecimal_div(VALUE self, VALUE r) { ENTER(5); Real *c=NULL, *res=NULL, *div = NULL; - r = BigDecimal_divide(&c, &res, &div, self, r); + 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 */ @@ -1329,9 +1692,48 @@ BigDecimal_div(VALUE self, VALUE r) */ /* Round */ if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */ - VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal() * (BDIGIT_DBL)res->frac[0] / div->frac[0])); + 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 = GetPrecisionInt(digits); + } + + if (n > 0) { + result = BigDecimal_div2(self, value, digits); + } + else { + result = BigDecimal_div(self, value); } - return ToValue(c); + + return result; } /* @@ -1344,77 +1746,104 @@ 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; - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + 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)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); + rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); } - else { - b = GetVpValue(r, 0); + + if (!is_kind_of_BigDecimal(rr)) { + return Qfalse; } - if (!b) 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"); + rb_raise(rb_eZeroDivError, "divided by 0"); } if (VpIsInf(a)) { - GUARD_OBJ(d, VpCreateRbObject(1, "0")); - VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1)); - GUARD_OBJ(c, VpCreateRbObject(1, "NaN")); - *div = d; - *mod = c; - return Qtrue; + 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)) { - GUARD_OBJ(d, VpCreateRbObject(1, "0")); - *div = d; - *mod = a; - return Qtrue; + VALUE zero = BigDecimal_positive_zero(); + TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div); + *mod = a; + return Qtrue; } if (VpIsZero(a)) { - GUARD_OBJ(c, VpCreateRbObject(1, "0")); - GUARD_OBJ(d, VpCreateRbObject(1, "0")); - *div = d; - *mod = c; - return Qtrue; - } - - mx = a->Prec + vabs(a->exponent); - if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); - mx = (mx + 1) * VpBaseFig(); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); - GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + 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; + if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) + mx = 2*BIGDECIMAL_DOUBLE_FIGURES; + + GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true)); + GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true)); VpDivd(c, res, a, b); - mx = c->Prec * (VpBaseFig() + 1); - GUARD_OBJ(d, VpCreateRbObject(mx, "0")); + + mx = c->Prec * BASE_FIG; + GUARD_OBJ(d, VpCreateRbObject(mx, "0", true)); VpActiveRound(d, c, VP_ROUND_DOWN, 0); + VpMult(res, d, b); VpAddSub(c, a, res, -1); + if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) { - VpAddSub(res, d, VpOne(), -1); - GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0")); - VpAddSub(d, c, b, 1); - *div = res; - *mod = d; - } else { - *div = d; - *mod = c; + /* result adjustment for negative case */ + res = VpReallocReal(res, d->MaxPrec); + res->MaxPrec = d->MaxPrec; + VpAddSub(res, d, VpOne(), -1); + GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true)); + VpAddSub(d, c, b, 1); + *div = res; + *mod = d; + } + else { + *div = d; + *mod = c; } return Qtrue; -NaN: - GUARD_OBJ(c, VpCreateRbObject(1, "NaN")); - GUARD_OBJ(d, VpCreateRbObject(1, "NaN")); - *div = d; - *mod = c; + 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; } @@ -1434,7 +1863,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */ if (BigDecimal_DoDivmod(self, r, &div, &mod)) { SAVE(div); SAVE(mod); - return ToValue(mod); + return VpCheckGetValue(mod); } return DoSomeOne(self, r, '%'); } @@ -1449,7 +1878,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) GUARD_OBJ(a, GetVpValue(self, 1)); if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, DBL_DIG+1, 1); + b = GetVpValueWithPrec(r, 0, 1); } else if (RB_TYPE_P(r, T_RATIONAL)) { b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); @@ -1462,17 +1891,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) SAVE(b); mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig(); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); - GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); - GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); - GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); + GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); + GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); + GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); - GUARD_OBJ(d, VpCreateRbObject(mx, "0")); - GUARD_OBJ(f, VpCreateRbObject(mx, "0")); + GUARD_OBJ(d, VpCreateRbObject(mx, "0", true)); + GUARD_OBJ(f, VpCreateRbObject(mx, "0", true)); VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */ @@ -1499,7 +1928,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */ Real *d, *rv = 0; f = BigDecimal_divremain(self, r, &d, &rv); if (!NIL_P(f)) return f; - return ToValue(rv); + return VpCheckGetValue(rv); } /* call-seq: @@ -1532,13 +1961,14 @@ BigDecimal_divmod(VALUE self, VALUE r) if (BigDecimal_DoDivmod(self, r, &div, &mod)) { SAVE(div); SAVE(mod); - return rb_assoc_new(ToValue(div), ToValue(mod)); + return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod)); } return DoSomeOne(self,r,rb_intern("divmod")); } /* - * See BigDecimal#quo + * 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) @@ -1550,7 +1980,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n) Real *div = NULL; Real *mod; if (BigDecimal_DoDivmod(self, b, &div, &mod)) { - return BigDecimal_to_i(ToValue(div)); + return BigDecimal_to_i(VpCheckGetValue(div)); } return DoSomeOne(self, b, rb_intern("div")); } @@ -1564,18 +1994,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n) 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, VpCreateRbObject(mx + VpBaseFig(), "0")); + GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true)); GUARD_OBJ(av, GetVpValue(self, 1)); - GUARD_OBJ(bv, GetVpValue(b, 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, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0")); + GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true)); VpDivd(cv, res, av, bv); VpSetPrecLimit(pl); VpLeftRound(cv, VpGetRoundMode(), ix); - return ToValue(cv); + return VpCheckGetValue(cv); } } @@ -1583,6 +2020,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n) * Document-method: BigDecimal#div * * call-seq: + * div(value) -> integer * div(value, digits) -> bigdecimal or integer * * Divide by the specified value. @@ -1597,6 +2035,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n) * 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") @@ -1620,6 +2061,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self) 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) { @@ -1633,7 +2099,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n) VpSetPrecLimit(pl); GUARD_OBJ(cv, GetVpValue(c, 1)); VpLeftRound(cv, VpGetRoundMode(), mx); - return ToValue(cv); + return VpCheckGetValue(cv); } } @@ -1663,10 +2129,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n) VpSetPrecLimit(pl); GUARD_OBJ(cv, GetVpValue(c, 1)); VpLeftRound(cv, VpGetRoundMode(), mx); - return ToValue(cv); + 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) @@ -1681,18 +2172,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n) VpSetPrecLimit(pl); GUARD_OBJ(cv, GetVpValue(c, 1)); VpLeftRound(cv, VpGetRoundMode(), mx); - return ToValue(cv); + return VpCheckGetValue(cv); } } /* * call-seq: - * big_decimal.abs -> big_decimal + * abs -> bigdecimal + * + * Returns the \BigDecimal absolute value of +self+: * - * Returns the absolute value, as a BigDecimal. + * BigDecimal('5').abs # => 0.5e1 + * BigDecimal('-3').abs # => 0.3e1 * - * BigDecimal('5').abs #=> 0.5e1 - * BigDecimal('-3').abs #=> 0.3e1 */ static VALUE @@ -1704,10 +2196,10 @@ BigDecimal_abs(VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpAsgn(c, a, 1); VpChangeSign(c, 1); - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -1729,9 +2221,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig) n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG; if (mx <= n) mx = n; - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpSqrt(c, a); - return ToValue(c); + return VpCheckGetValue(c); } /* Return the integer part of the number, as a BigDecimal. @@ -1745,9 +2237,9 @@ BigDecimal_fix(VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */ - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -1767,10 +2259,10 @@ BigDecimal_fix(VALUE self) * 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. + * 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.0 + * 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. @@ -1783,6 +2275,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) int iLoc = 0; VALUE vLoc; VALUE vRound; + int round_to_int = 0; size_t mx, pl; unsigned short sw = VpGetRoundMode(); @@ -1790,6 +2283,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) 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)) { @@ -1797,6 +2291,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) } else { iLoc = NUM2INT(vLoc); + if (iLoc < 1) round_to_int = 1; } break; case 2: @@ -1815,13 +2310,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) pl = VpSetPrecLimit(0); GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpSetPrecLimit(pl); VpActiveRound(c, a, sw, iLoc); - if (argc == 0) { - return BigDecimal_to_i(ToValue(c)); + if (round_to_int) { + return BigDecimal_to_i(VpCheckGetValue(c)); } - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -1861,13 +2356,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpSetPrecLimit(pl); VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */ if (argc == 0) { - return BigDecimal_to_i(ToValue(c)); + return BigDecimal_to_i(VpCheckGetValue(c)); } - return ToValue(c); + return VpCheckGetValue(c); } /* Return the fractional part of the number, as a BigDecimal. @@ -1881,9 +2376,9 @@ BigDecimal_frac(VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpFrac(c, a); - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -1921,16 +2416,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); 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(ToValue(c)); + return BigDecimal_to_i(VpCheckGetValue(c)); } - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -1967,13 +2462,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self) GUARD_OBJ(a, GetVpValue(self, 1)); mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); VpSetPrecLimit(pl); VpActiveRound(c, a, VP_ROUND_CEIL, iLoc); if (argc == 0) { - return BigDecimal_to_i(ToValue(c)); + return BigDecimal_to_i(VpCheckGetValue(c)); } - return ToValue(c); + return VpCheckGetValue(c); } /* call-seq: @@ -2067,7 +2562,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) nc += (nc + mc - 1) / mc + 1; } - str = rb_str_new(0, nc); + str = rb_usascii_str_new(0, nc); psz = RSTRING_PTR(str); if (fmt) { @@ -2132,7 +2627,7 @@ BigDecimal_split(VALUE self) rb_ary_push(obj, str); rb_str_resize(str, strlen(psz1)); rb_ary_push(obj, INT2FIX(10)); - rb_ary_push(obj, INT2NUM(e)); + rb_ary_push(obj, SSIZET2NUM(e)); return obj; } @@ -2145,7 +2640,7 @@ static VALUE BigDecimal_exponent(VALUE self) { ssize_t e = VpExponent10(GetVpValue(self, 1)); - return INT2NUM(e); + return SSIZET2NUM(e); } /* Returns a string representation of self. @@ -2269,13 +2764,13 @@ is_even(VALUE x) } static VALUE -rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n) +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 ToValue(VpCreateRbObject(n, "1")); + return VpCheckGetValue(VpCreateRbObject(n, "1", true)); } log_x = BigMath_log(x->obj, SSIZET2NUM(n+1)); @@ -2313,10 +2808,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec); if (VpIsNaN(x)) { - y = VpCreateRbObject(n, "0"); + y = VpCreateRbObject(n, "0", true); RB_GC_GUARD(y->obj); VpSetNaN(y); - return ToValue(y); + return VpCheckGetValue(y); } retry: @@ -2338,7 +2833,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) } goto retry; } - exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1); + if (NIL_P(prec)) { + n += BIGDECIMAL_DOUBLE_FIGURES; + } + exp = GetVpValueWithPrec(vexp, 0, 1); break; case T_RATIONAL: @@ -2353,6 +2851,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) goto retry; } exp = GetVpValueWithPrec(vexp, n, 1); + if (NIL_P(prec)) { + n += n; + } break; case T_DATA: @@ -2363,6 +2864,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) 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; } @@ -2375,7 +2880,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) if (VpIsZero(x)) { if (is_negative(vexp)) { - y = VpCreateRbObject(n, "#0"); + y = VpCreateRbObject(n, "#0", true); RB_GC_GUARD(y->obj); if (BIGDECIMAL_NEGATIVE_P(x)) { if (is_integer(vexp)) { @@ -2397,18 +2902,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) /* (+0) ** (-num) -> Infinity */ VpSetPosInf(y); } - return ToValue(y); + return VpCheckGetValue(y); } else if (is_zero(vexp)) { - return ToValue(VpCreateRbObject(n, "1")); + return VpCheckGetValue(VpCreateRbObject(n, "1", true)); } else { - return ToValue(VpCreateRbObject(n, "0")); + return VpCheckGetValue(VpCreateRbObject(n, "0", true)); } } if (is_zero(vexp)) { - return ToValue(VpCreateRbObject(n, "1")); + return VpCheckGetValue(VpCreateRbObject(n, "1", true)); } else if (is_one(vexp)) { return self; @@ -2420,24 +2925,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) if (is_integer(vexp)) { if (is_even(vexp)) { /* (-Infinity) ** (-even_integer) -> +0 */ - return ToValue(VpCreateRbObject(n, "0")); + return VpCheckGetValue(VpCreateRbObject(n, "0", true)); } else { /* (-Infinity) ** (-odd_integer) -> -0 */ - return ToValue(VpCreateRbObject(n, "-0")); + return VpCheckGetValue(VpCreateRbObject(n, "-0", true)); } } else { /* (-Infinity) ** (-non_integer) -> -0 */ - return ToValue(VpCreateRbObject(n, "-0")); + return VpCheckGetValue(VpCreateRbObject(n, "-0", true)); } } else { - return ToValue(VpCreateRbObject(n, "0")); + return VpCheckGetValue(VpCreateRbObject(n, "0", true)); } } else { - y = VpCreateRbObject(n, "0"); + y = VpCreateRbObject(n, "0", true); if (BIGDECIMAL_NEGATIVE_P(x)) { if (is_integer(vexp)) { if (is_even(vexp)) { @@ -2456,52 +2961,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) else { VpSetPosInf(y); } - return ToValue(y); + return VpCheckGetValue(y); } } if (exp != NULL) { - return rmpd_power_by_big_decimal(x, exp, n); + 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 ToValue(VpCreateRbObject(n, "1")); + return VpCheckGetValue(VpCreateRbObject(n, "1", true)); } else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) { if (is_negative(vexp)) { - y = VpCreateRbObject(n, "0"); + y = VpCreateRbObject(n, "0", true); if (is_even(vexp)) { VpSetInf(y, VpGetSign(x)); } else { VpSetInf(y, -VpGetSign(x)); } - return ToValue(y); + return VpCheckGetValue(y); } else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) { - return ToValue(VpCreateRbObject(n, "-0")); + return VpCheckGetValue(VpCreateRbObject(n, "-0", true)); } else { - return ToValue(VpCreateRbObject(n, "0")); + return VpCheckGetValue(VpCreateRbObject(n, "0", true)); } } else { if (is_positive(vexp)) { - y = VpCreateRbObject(n, "0"); + y = VpCreateRbObject(n, "0", true); if (is_even(vexp)) { VpSetInf(y, VpGetSign(x)); } else { VpSetInf(y, -VpGetSign(x)); } - return ToValue(y); + return VpCheckGetValue(y); } else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) { - return ToValue(VpCreateRbObject(n, "-0")); + return VpCheckGetValue(VpCreateRbObject(n, "-0", true)); } else { - return ToValue(VpCreateRbObject(n, "0")); + return VpCheckGetValue(VpCreateRbObject(n, "0", true)); } } } @@ -2513,24 +3018,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) if (VpIsDef(x)) { mp = x->Prec * (VpBaseFig() + 1); - GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0")); + GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true)); } else { - GUARD_OBJ(y, VpCreateRbObject(1, "0")); + GUARD_OBJ(y, VpCreateRbObject(1, "0", true)); } - VpPower(y, x, int_exp); + VpPowerByInt(y, x, int_exp); if (!NIL_P(prec) && VpIsDef(y)) { VpMidRound(y, VpGetRoundMode(), n); } - return ToValue(y); + return VpCheckGetValue(y); } -/* call-seq: - * a ** n -> bigdecimal +/* call-seq: + * self ** other -> bigdecimal * - * Returns the value raised to the power of n. + * 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. * - * See BigDecimal#power. */ static VALUE BigDecimal_power_op(VALUE self, VALUE exp) @@ -2584,169 +3095,483 @@ opts_exception_p(VALUE opts) } #endif -static Real * -VpNewVarArg(int argc, VALUE *argv) +static VALUE +check_exception(VALUE bd) { - size_t mf; - VALUE opts = Qnil; - VALUE nFig; - VALUE iniValue; - double d; - int exc; + 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; +} - argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts); - exc = opts_exception_p(opts); +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); - if (argc == 1) { - mf = 0; + Real *vp; + if (uval == 0) { + vp = VpAllocReal(1); + vp->MaxPrec = 1; + vp->Prec = 1; + vp->exponent = 1; + VpSetZero(vp, 1); + vp->frac[0] = 0; + } + else if (uval < BASE) { + vp = VpAllocReal(1); + vp->MaxPrec = 1; + vp->Prec = 1; + vp->exponent = 1; + VpSetSign(vp, 1); + vp->frac[0] = (DECDIG)uval; } else { - /* expand GetPrecisionInt for exception suppression */ - ssize_t n = NUM2INT(nFig); - if (n < 0) { - if (!exc) { - return NULL; + 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; } - rb_raise(rb_eArgError, "negative precision"); } - mf = (size_t)n; - } - - if (SPECIAL_CONST_P(iniValue)) { - switch (iniValue) { - case Qnil: - if (!exc) return NULL; - rb_raise(rb_eTypeError, "can't convert nil into BigDecimal"); - case Qtrue: - if (!exc) return NULL; - rb_raise(rb_eTypeError, "can't convert true into BigDecimal"); - case Qfalse: - if (!exc) return NULL; - rb_raise(rb_eTypeError, "can't convert false into BigDecimal"); - default: - break; + 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 = VpAllocReal(len); + vp->MaxPrec = len; + vp->Prec = len; + vp->exponent = exp; + VpSetSign(vp, 1); + MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len); } - switch (TYPE(iniValue)) { - case T_DATA: - if (is_kind_of_BigDecimal(iniValue)) { - return DATA_PTR(iniValue); - } - break; + return BigDecimal_wrap_struct(obj, vp); +} - case T_FIXNUM: - /* fall through */ - case T_BIGNUM: - return GetVpValue(iniValue, 1); +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; +} - case T_FLOAT: - d = RFLOAT_VALUE(iniValue); - if (!isfinite(d)) { - Real *pv = VpCreateRbObject(1, NULL); - VpDtoV(pv, d); - return pv; +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); } - if (mf > DBL_DIG+1) { - if (!exc) { - return NULL; - } - rb_raise(rb_eArgError, "precision too large."); - } - /* fall through */ - case T_RATIONAL: - if (NIL_P(nFig)) { - if (!exc) { - return NULL; - } - rb_raise(rb_eArgError, - "can't omit precision for a %"PRIsVALUE".", - RB_OBJ_CLASSNAME(iniValue)); - } - return GetVpValueWithPrec(iniValue, mf, 1); + 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; + size_t 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; - case T_STRING: - /* fall through */ default: - break; + 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); } - /* TODO: support to_d */ - if (!exc) { - iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str"); - if (NIL_P(iniValue)) return NULL; + else if (RB_TYPE_P(val, T_RATIONAL)) { + return rb_rational_convert_to_BigDecimal(val, digs, raise_exception); } - StringValueCStr(iniValue); - return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc); + 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(initial, digits, exception: true) +/* call-seq: + * BigDecimal(value, exception: true) -> bigdecimal + * BigDecimal(value, ndigits, exception: true) -> bigdecimal * - * Create a new BigDecimal object. + * Returns the \BigDecimal converted from +value+ + * with a precision of +ndigits+ decimal digits. * - * initial:: The initial value, as an Integer, a Float, a Rational, - * a BigDecimal, or a String. + * 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. * - * If it is a String, spaces are ignored and unrecognized characters - * terminate the value. + * Returns +value+ converted to a \BigDecimal, depending on the type of +value+: * - * digits:: The number of significant digits, as an Integer. If omitted or 0, - * the number of significant digits is determined from the initial - * value. + * - Integer, Float, Rational, Complex, or BigDecimal: converted directly: * - * The actual number of significant digits used in computation is - * usually larger than the specified number. + * # 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 * - * exception:: Whether an exception should be raised on invalid arguments. - * +true+ by default, if passed +false+, just returns +nil+ - * for invalid. + * - 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 * - * ==== Exceptions + * - Other type that responds to method :to_str: + * first converted to a string, then converted to a \BigDecimal, as above. * - * TypeError:: If the +initial+ type is neither Integer, Float, - * Rational, nor BigDecimal, this exception is raised. + * - Other type: * - * TypeError:: If the +digits+ is not an Integer, this exception is raised. + * - Raises an exception if keyword argument +exception+ is +true+. + * - Returns +nil+ if keyword argument +exception+ is +true+. * - * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than - * Float::DIG + 1, this exception is raised. + * Raises an exception if +value+ evaluates to a Float + * and +digits+ is larger than Float::DIG + 1. * - * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+ - * value is omitted, this exception is raised. */ static VALUE f_BigDecimal(int argc, VALUE *argv, VALUE self) { - ENTER(1); - Real *pv; - VALUE obj; - - if (argc > 0 && CLASS_OF(argv[0]) == rb_cBigDecimal) { - if (argc == 1 || (argc == 2 && RB_TYPE_P(argv[1], T_HASH))) return argv[0]; + 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); + } } - obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - pv = VpNewVarArg(argc, argv); - if (pv == NULL) return Qnil; - SAVE(pv); - if (ToValue(pv)) pv = VpCopy(NULL, pv); - RTYPEDDATA_DATA(obj) = pv; - RB_OBJ_FREEZE(obj); - return pv->obj = obj; + + return rb_convert_to_BigDecimal(val, digs, exception); } static VALUE BigDecimal_s_interpret_loosely(VALUE klass, VALUE str) { - ENTER(1); - char const *c_str; - Real *pv; - - c_str = StringValueCStr(str); - GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1)); - pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv); - RB_OBJ_FREEZE(pv->obj); - return pv->obj; + 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: @@ -2765,7 +3590,7 @@ static VALUE BigDecimal_limit(int argc, VALUE *argv, VALUE self) { VALUE nFig; - VALUE nCur = INT2NUM(VpGetPrecLimit()); + VALUE nCur = SIZET2NUM(VpGetPrecLimit()); if (rb_scan_args(argc, argv, "01", &nFig) == 1) { int nf; @@ -2930,7 +3755,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) infinite = isinf(flo); nan = isnan(flo); if (!infinite && !nan) { - vx = GetVpValueWithPrec(x, DBL_DIG+1, 0); + vx = GetVpValueWithPrec(x, 0, 0); } break; @@ -2943,29 +3768,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) } if (infinite) { if (negative) { - return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1)); + return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1)); } else { Real* vy; - vy = VpCreateRbObject(prec, "#0"); + vy = VpCreateRbObject(prec, "#0", true); VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); RB_GC_GUARD(vy->obj); - return ToValue(vy); + return VpCheckGetValue(vy); } } else if (nan) { Real* vy; - vy = VpCreateRbObject(prec, "#0"); + vy = VpCreateRbObject(prec, "#0", true); VpSetNaN(vy); RB_GC_GUARD(vy->obj); - return ToValue(vy); + return VpCheckGetValue(vy); } else if (vx == NULL) { cannot_be_coerced_into_BigDecimal(rb_eArgError, x); } x = vx->obj; - n = prec + rmpd_double_figures(); + n = prec + BIGDECIMAL_DOUBLE_FIGURES; negative = BIGDECIMAL_NEGATIVE_P(vx); if (negative) { VALUE x_zero = INT2NUM(1); @@ -2975,7 +3800,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) VpSetSign(vx, 1); } - one = ToValue(VpCreateRbObject(1, "1")); + one = VpCheckGetValue(VpCreateRbObject(1, "1", true)); y = one; d = y; i = 1; @@ -2990,8 +3815,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) if (m <= 0) { break; } - else if ((size_t)m < rmpd_double_figures()) { - m = rmpd_double_figures(); + else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { + m = BIGDECIMAL_DOUBLE_FIGURES; } d = BigDecimal_mult(d, x); /* d <- d * x */ @@ -3083,7 +3908,7 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) infinite = isinf(flo); nan = isnan(flo); if (!zero && !negative && !infinite && !nan) { - vx = GetVpValueWithPrec(x, DBL_DIG+1, 1); + vx = GetVpValueWithPrec(x, 0, 1); } break; @@ -3103,17 +3928,17 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) } if (infinite && !negative) { Real* vy; - vy = VpCreateRbObject(prec, "#0"); + vy = VpCreateRbObject(prec, "#0", true); RB_GC_GUARD(vy->obj); VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); - return ToValue(vy); + return VpCheckGetValue(vy); } else if (nan) { Real* vy; - vy = VpCreateRbObject(prec, "#0"); + vy = VpCreateRbObject(prec, "#0", true); RB_GC_GUARD(vy->obj); VpSetNaN(vy); - return ToValue(vy); + return VpCheckGetValue(vy); } else if (zero || negative) { rb_raise(rb_eMathDomainError, @@ -3122,18 +3947,18 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) else if (vx == NULL) { cannot_be_coerced_into_BigDecimal(rb_eArgError, x); } - x = ToValue(vx); + x = VpCheckGetValue(vx); - RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1")); - RB_GC_GUARD(two) = ToValue(VpCreateRbObject(1, "2")); + RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true)); + RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true)); - n = prec + rmpd_double_figures(); + n = prec + BIGDECIMAL_DOUBLE_FIGURES; RB_GC_GUARD(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, ToValue(VpCreateRbObject(1, buf)), vn); + x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn); } else { expo = 0; @@ -3151,8 +3976,8 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) if (m <= 0) { break; } - else if ((size_t)m < rmpd_double_figures()) { - m = rmpd_double_figures(); + else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { + m = BIGDECIMAL_DOUBLE_FIGURES; } x = BigDecimal_mult2(x2, x, vn); @@ -3165,7 +3990,7 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) if (expo != 0) { VALUE log10, vexpo, dy; log10 = BigMath_s_log(klass, INT2FIX(10), vprec); - vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1)); + vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1)); dy = BigDecimal_mult(log10, vexpo); y = BigDecimal_add(y, dy); } @@ -3173,6 +3998,46 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) 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. * @@ -3216,6 +4081,18 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) * * (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 @@ -3301,6 +4178,9 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) 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"); @@ -3317,7 +4197,7 @@ Init_bigdecimal(void) rb_define_global_function("BigDecimal", f_BigDecimal, -1); /* Class methods */ - rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate"); + 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); @@ -3441,17 +4321,41 @@ Init_bigdecimal(void) /* -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)); - arg = rb_str_new2("+Infinity"); + /* 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. */ - rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal)); - arg = rb_str_new2("NaN"); + 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. */ - rb_define_const(rb_cBigDecimal, "NAN", f_BigDecimal(1, &arg, rb_cBigDecimal)); + 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, "initialize_copy", BigDecimal_initialize_copy, 1); 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); @@ -3469,7 +4373,7 @@ Init_bigdecimal(void) 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_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); @@ -3560,14 +4464,17 @@ enum op_sw { static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw); static int AddExponent(Real *a, SIGNED_VALUE n); -static BDIGIT VpAddAbs(Real *a,Real *b,Real *c); -static BDIGIT 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, BDIGIT *av, BDIGIT *bv); +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 */ @@ -3575,9 +4482,6 @@ VP_EXPORT void * VpMemAlloc(size_t mb) { void *p = xmalloc(mb); - if (!p) { - VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1); - } memset(p, 0, mb); #ifdef BIGDECIMAL_DEBUG gnAlloc++; /* Count allocation call */ @@ -3588,11 +4492,7 @@ VpMemAlloc(size_t mb) VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb) { - void *p = xrealloc(ptr, mb); - if (!p) { - VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1); - } - return p; + return xrealloc(ptr, mb); } VP_EXPORT void @@ -3618,7 +4518,7 @@ VpFree(Real *pv) * EXCEPTION Handling. */ -#define rmpd_set_thread_local_exception_mode(mode) \ +#define bigdecimal_set_thread_local_exception_mode(mode) \ rb_thread_local_aset( \ rb_thread_current(), \ id_BigDecimal_exception_mode, \ @@ -3634,8 +4534,8 @@ VpGetException (void) ); if (NIL_P(vmode)) { - rmpd_set_thread_local_exception_mode(RMPD_EXCEPTION_MODE_DEFAULT); - return RMPD_EXCEPTION_MODE_DEFAULT; + bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT); + return BIGDECIMAL_EXCEPTION_MODE_DEFAULT; } return NUM2USHORT(vmode); @@ -3644,20 +4544,41 @@ VpGetException (void) static void VpSetException(unsigned short f) { - rmpd_set_thread_local_exception_mode(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 rmpd_set_thread_local_precision_limit(limit) \ +#define bigdecimal_set_thread_local_precision_limit(limit) \ rb_thread_local_aset( \ rb_thread_current(), \ id_BigDecimal_precision_limit, \ SIZET2NUM(limit) \ ) -#define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0) +#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0) /* These 2 functions added at v1.1.7 */ VP_EXPORT size_t @@ -3669,8 +4590,8 @@ VpGetPrecLimit(void) ); if (NIL_P(vlimit)) { - rmpd_set_thread_local_precision_limit(RMPD_PRECISION_LIMIT_DEFAULT); - return RMPD_PRECISION_LIMIT_DEFAULT; + bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT); + return BIGDECIMAL_PRECISION_LIMIT_DEFAULT; } return NUM2SIZET(vlimit); @@ -3680,7 +4601,7 @@ VP_EXPORT size_t VpSetPrecLimit(size_t n) { size_t const s = VpGetPrecLimit(); - rmpd_set_thread_local_precision_limit(n); + bigdecimal_set_thread_local_precision_limit(n); return s; } @@ -3688,7 +4609,7 @@ VpSetPrecLimit(size_t n) * Rounding mode. */ -#define rmpd_set_thread_local_rounding_mode(mode) \ +#define bigdecimal_set_thread_local_rounding_mode(mode) \ rb_thread_local_aset( \ rb_thread_current(), \ id_BigDecimal_rounding_mode, \ @@ -3704,8 +4625,8 @@ VpGetRoundMode(void) ); if (NIL_P(vmode)) { - rmpd_set_thread_local_rounding_mode(RMPD_ROUNDING_MODE_DEFAULT); - return RMPD_ROUNDING_MODE_DEFAULT; + bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT); + return BIGDECIMAL_ROUNDING_MODE_DEFAULT; } return NUM2USHORT(vmode); @@ -3733,7 +4654,7 @@ VP_EXPORT unsigned short VpSetRoundMode(unsigned short n) { if (VpIsRoundMode(n)) { - rmpd_set_thread_local_rounding_mode(n); + bigdecimal_set_thread_local_rounding_mode(n); return n; } @@ -3810,7 +4731,7 @@ VpException(unsigned short f, const char *str,int always) { unsigned short const exception_mode = VpGetException(); - if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1; + if (f == VP_EXCEPTION_OP) always = 1; if (always || (exception_mode & f)) { switch(f) { @@ -3822,7 +4743,6 @@ VpException(unsigned short f, const char *str,int always) case VP_EXCEPTION_OP: rb_raise(rb_eFloatDomainError, "%s", str); break; - case VP_EXCEPTION_MEMORY: default: rb_fatal("%s", str); } @@ -3971,13 +4891,13 @@ VpNumOfChars(Real *vp,const char *pszFmt) * 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 BDIGIT word in the computer used. + * by one DECDIG word in the computer used. * * [Returns] - * 1+DBL_DIG ... OK + * BIGDECIMAL_DOUBLE_FIGURES ... OK */ VP_EXPORT size_t -VpInit(BDIGIT BaseVal) +VpInit(DECDIG BaseVal) { /* Setup +/- Inf NaN -0 */ VpGetDoubleNegZero(); @@ -3992,16 +4912,16 @@ VpInit(BDIGIT BaseVal) #ifdef BIGDECIMAL_DEBUG if (gfDebug) { - printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal); - printf("\tBASE = %"PRIuBDIGIT"\n", BASE); - printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE); - printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1); - printf("\tBASE_FIG = %u\n", BASE_FIG); - printf("\tDBLE_FIG = %d\n", DBLE_FIG); + 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 rmpd_double_figures(); + return BIGDECIMAL_DOUBLE_FIGURES; } VP_EXPORT Real * @@ -4049,7 +4969,7 @@ AddExponent(Real *a, SIGNED_VALUE n) } Real * -rmpd_parse_special_string(const char *str) +bigdecimal_parse_special_string(const char *str) { static const struct { const char *str; @@ -4144,14 +5064,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc) /* at least mx digits. */ /* szVal==NULL ==> allocate zero value. */ vp = VpAllocReal(mx); - /* xmalloc() alway returns(or throw interruption) */ vp->MaxPrec = mx; /* set max precision */ VpSetZero(vp, 1); /* initialize vp to zero. */ return vp; } /* Check on Inf & NaN */ - if ((vp = rmpd_parse_special_string(szVal)) != NULL) { + if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) { return vp; } @@ -4320,7 +5239,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc) nalloc = Max(nalloc, mx); mx = nalloc; vp = VpAllocReal(mx); - /* xmalloc() alway returns(or throw interruption) */ vp->MaxPrec = mx; /* set max precision */ VpSetZero(vp, sign); VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne); @@ -4359,7 +5277,7 @@ VpAsgn(Real *c, Real *a, int isw) 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(BDIGIT)); + memcpy(c->frac, a->frac, n * sizeof(DECDIG)); /* Needs round ? */ if (isw != 10) { /* Not in ActiveRound */ @@ -4390,7 +5308,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation) short sw, isw; Real *a_ptr, *b_ptr; size_t n, na, nb, i; - BDIGIT mrv; + DECDIG mrv; #ifdef BIGDECIMAL_DEBUG if (gfDebug) { @@ -4518,7 +5436,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation) * a and b assuming abs(a)>abs(b). * c = abs(a) + abs(b) ; where |a|>=|b| */ -static BDIGIT +static DECDIG VpAddAbs(Real *a, Real *b, Real *c) { size_t word_shift; @@ -4528,7 +5446,7 @@ VpAddAbs(Real *a, Real *b, Real *c) size_t a_pos; size_t b_pos, b_pos_with_word_shift; size_t c_pos; - BDIGIT av, bv, carry, mrv; + DECDIG av, bv, carry, mrv; #ifdef BIGDECIMAL_DEBUG if (gfDebug) { @@ -4613,7 +5531,7 @@ VpAddAbs(Real *a, Real *b, Real *c) /* * c = abs(a) - abs(b) */ -static BDIGIT +static DECDIG VpSubAbs(Real *a, Real *b, Real *c) { size_t word_shift; @@ -4623,7 +5541,7 @@ VpSubAbs(Real *a, Real *b, Real *c) size_t a_pos; size_t b_pos, b_pos_with_word_shift; size_t c_pos; - BDIGIT av, bv, borrow, mrv; + DECDIG av, bv, borrow, mrv; #ifdef BIGDECIMAL_DEBUG if (gfDebug) { @@ -4730,7 +5648,7 @@ VpSubAbs(Real *a, Real *b, Real *c) * c_pos = | */ static size_t -VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv) +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; @@ -4845,8 +5763,8 @@ 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; - BDIGIT carry; - BDIGIT_DBL s; + DECDIG carry; + DECDIG_DBL s; Real *w; #ifdef BIGDECIMAL_DEBUG @@ -4900,7 +5818,7 @@ VpMult(Real *c, Real *a, Real *b) VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */ carry = 0; nc = ind_c = MxIndAB; - memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT)); /* Initialize c */ + 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. */ @@ -4920,15 +5838,15 @@ VpMult(Real *c, Real *a, Real *b) } for (i = ind_as; i <= ind_ae; ++i) { - s = (BDIGIT_DBL)a->frac[i] * b->frac[ind_bs--]; - carry = (BDIGIT)(s / BASE); - s -= (BDIGIT_DBL)carry * BASE; - c->frac[ind_c] += (BDIGIT)s; - if (c->frac[ind_c] >= BASE) { - s = c->frac[ind_c] / BASE; - carry += (BDIGIT)s; - c->frac[ind_c] -= (BDIGIT)(s * BASE); - } + 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) { @@ -4974,9 +5892,9 @@ 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; - BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2; - BDIGIT borrow, borrow1, borrow2; - BDIGIT_DBL qb; + DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2; + DECDIG borrow, borrow1, borrow2; + DECDIG_DBL qb; #ifdef BIGDECIMAL_DEBUG if (gfDebug) { @@ -5048,7 +5966,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b) ++ind_c; continue; } - r1r2 = (BDIGIT_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1]; + 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; @@ -5085,17 +6003,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b) /* The first two word digits is not the same, */ /* then compare magnitude, and divide actually. */ if (r1r2 >= b1b2p1) { - q = r1r2 / b1b2p1; /* q == (BDIGIT)q */ - c->frac[ind_c] += (BDIGIT)q; - ind_r = b->Prec + ind_c - 1; - goto sub_mult; + 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 == (BDIGIT)q */ - c->frac[ind_c + 1] += (BDIGIT)q; - ind_r = b->Prec + ind_c; + 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; @@ -5107,16 +6025,16 @@ VpDivd(Real *c, Real *r, Real *a, Real *b) qb = q * b->frac[ind_b]; if (qb < BASE) borrow1 = 0; else { - borrow1 = (BDIGIT)(qb / BASE); - qb -= (BDIGIT_DBL)borrow1 * BASE; /* get qb < BASE */ + borrow1 = (DECDIG)(qb / BASE); + qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */ } if(r->frac[ind_r] < qb) { - r->frac[ind_r] += (BDIGIT)(BASE - qb); - borrow2 = borrow2 + borrow1 + 1; + r->frac[ind_r] += (DECDIG)(BASE - qb); + borrow2 = borrow2 + borrow1 + 1; } else { - r->frac[ind_r] -= (BDIGIT)qb; - borrow2 += borrow1; + r->frac[ind_r] -= (DECDIG)qb; + borrow2 += borrow1; } if (borrow2) { if(r->frac[ind_r - 1] < borrow2) { @@ -5198,9 +6116,9 @@ VpNmlz(Real *a) 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(BDIGIT)); + a->Prec -= i; + if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0; + memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG)); } return 1; } @@ -5323,7 +6241,7 @@ static int VPrint(FILE *fp, const char *cntl_chr, Real *a) { size_t i, j, nc, nd, ZeroSup, sep = 10; - BDIGIT m, e, nn; + DECDIG m, e, nn; j = 0; nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */ @@ -5358,7 +6276,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a) case '0': case 'z': ZeroSup = 0; ++j; - sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10; + sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10; break; } for (i = 0; i < a->Prec; ++i) { @@ -5467,7 +6385,7 @@ VP_EXPORT void VpSzMantissa(Real *a,char *psz) { size_t i, n, ZeroSup; - BDIGIT_DBL m, e, nn; + DECDIG_DBL m, e, nn; if (VpIsNaN(a)) { sprintf(psz, SZ_NaN); @@ -5550,7 +6468,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus) /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ { size_t i, n, ZeroSup; - BDIGIT shift, m, e, nn; + DECDIG shift, m, e, nn; char *pszSav = psz; ssize_t ex; @@ -5598,7 +6516,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus) /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ { size_t i, n; - BDIGIT m, e, nn; + DECDIG m, e, nn; char *pszSav = psz; ssize_t ex; @@ -5673,7 +6591,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con me = ne; signe = 1; exponent_overflow = 0; - memset(a->frac, 0, ma * sizeof(BDIGIT)); + memset(a->frac, 0, ma * sizeof(DECDIG)); if (ne > 0) { i = 0; if (exp_chr[0] == '-') { @@ -5810,7 +6728,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con * [Output] * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig. * *e ... exponent of m. - * DBLE_FIG ... Number of digits in a double variable. + * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable. * * m -> d*10**e, 0Prec); *d = 0.0; @@ -5874,7 +6792,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m) if (gfDebug) { VPrint(stdout, " VpVtoD: m=%\n", m); printf(" d=%e * 10 **%ld\n", *d, *e); - printf(" DBLE_FIG = %d\n", DBLE_FIG); + printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES); } #endif /*BIGDECIMAL_DEBUG */ return f; @@ -5888,7 +6806,7 @@ VpDtoV(Real *m, double d) { size_t ind_m, mm; SIGNED_VALUE ne; - BDIGIT i; + DECDIG i; double val, val2; if (isnan(d)) { @@ -5923,12 +6841,12 @@ VpDtoV(Real *m, double d) /* Now val = 0.xxxxx*BASE**ne */ mm = m->MaxPrec; - memset(m->frac, 0, mm * sizeof(BDIGIT)); + memset(m->frac, 0, mm * sizeof(DECDIG)); for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) { - val *= (double)BASE; - i = (BDIGIT)val; - val -= (double)i; - m->frac[ind_m] = i; + 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); @@ -5936,7 +6854,7 @@ VpDtoV(Real *m, double d) m->exponent = ne; VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0, - (BDIGIT)(val*(double)BASE)); + (DECDIG)(val*(double)BASE)); Exit: #ifdef BIGDECIMAL_DEBUG @@ -6075,7 +6993,7 @@ VpSqrt(Real *y, Real *x) } VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */ y->exponent += n; - n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG); + 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); @@ -6132,8 +7050,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) /* exptoadd: number of digits needed to compensate negative nf */ int fracf, fracf_1further; ssize_t n,i,ix,ioffset, exptoadd; - BDIGIT v, shifter; - BDIGIT div; + DECDIG v, shifter; + DECDIG div; nf += y->exponent * (ssize_t)BASE_FIG; exptoadd=0; @@ -6155,8 +7073,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) 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 BDIGIT, where - each BDIGIT contains a value between 0 and BASE-1, consisting of BASE_FIG + /* 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) @@ -6164,10 +7082,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) nf is now position (in decimal places) of the digit from the start of the array. - ix is the position (in BDIGITS) of the BDIGIT containing the decimal digit, + 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 BDIGIT + v is the value of this DECDIG ioffset is the number of extra decimal places along of this decimal digit within v. @@ -6193,7 +7111,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) now fracf_1further is whether any of the remaining digits within v are non-zero */ - /* now check all the remaining BDIGITS for zero-ness a whole BDIGIT at a time. + /* 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) @@ -6212,7 +7130,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) 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(BDIGIT)); + memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG)); switch (f) { case VP_ROUND_DOWN: /* Truncate */ @@ -6240,11 +7158,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf) } else { if (ioffset == 0) { - /* v is the first decimal digit of its BDIGIT; - need to grab the previous BDIGIT if present - to check for evenness of the previous decimal - digit (which is same as that of the BDIGIT since - base 10 has a factor of 2) */ + /* 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 { @@ -6292,7 +7210,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf) * Round from the left hand side of the digits. */ { - BDIGIT v; + DECDIG v; if (!VpHasVal(y)) return 0; /* Unable to round */ v = y->frac[0]; nf -= VpExponent(y) * (ssize_t)BASE_FIG; @@ -6323,7 +7241,7 @@ VpLimitRound(Real *c, size_t ixDigit) /* 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, BDIGIT vPrev, BDIGIT v) +VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v) { int f = 0; @@ -6373,7 +7291,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v) static int VpRdup(Real *m, size_t ind_m) { - BDIGIT carry; + DECDIG carry; if (!ind_m) ind_m = m->Prec; @@ -6445,7 +7363,7 @@ VpFrac(Real *y, Real *x) * y = x ** n */ VP_EXPORT int -VpPower(Real *y, Real *x, SIGNED_VALUE n) +VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n) { size_t s, ss; ssize_t sign; @@ -6532,8 +7450,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n) Exit: #ifdef BIGDECIMAL_DEBUG if (gfDebug) { - VPrint(stdout, "VpPower y=%\n", y); - VPrint(stdout, "VpPower x=%\n", x); + VPrint(stdout, "VpPowerByInt y=%\n", y); + VPrint(stdout, "VpPowerByInt x=%\n", x); printf(" n=%"PRIdVALUE"\n", n); } #endif /* BIGDECIMAL_DEBUG */ @@ -6568,12 +7486,12 @@ VpVarCheck(Real * v) } for (i = 0; i < v->Prec; ++i) { if (v->frac[i] >= BASE) { - printf("ERROR(VpVarCheck): Illegal fraction\n"); - printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]); - printf(" Prec. =%"PRIuSIZE"\n", v->Prec); - printf(" Exp. =%"PRIdVALUE"\n", v->exponent); - printf(" BASE =%"PRIuBDIGIT"\n", BASE); - return 3; + 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; diff --git a/ruby/ext/bigdecimal/bigdecimal.gemspec b/ruby/ext/bigdecimal/bigdecimal.gemspec index 7d767f598..fd49c1b00 100644 --- a/ruby/ext/bigdecimal/bigdecimal.gemspec +++ b/ruby/ext/bigdecimal/bigdecimal.gemspec @@ -1,17 +1,15 @@ # coding: utf-8 -bigdecimal_version = '2.0.0' - Gem::Specification.new do |s| s.name = "bigdecimal" - s.version = bigdecimal_version + s.version = "3.1.1" 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.license = "ruby" + s.license = "Ruby" s.require_paths = %w[lib] s.extensions = %w[ext/bigdecimal/extconf.rb] @@ -19,6 +17,12 @@ Gem::Specification.new do |s| bigdecimal.gemspec 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 lib/bigdecimal.rb lib/bigdecimal/jacobian.rb lib/bigdecimal/ludcmp.rb @@ -30,10 +34,5 @@ Gem::Specification.new do |s| sample/pi.rb ] - s.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - - s.add_development_dependency "rake", "~> 10.0" - s.add_development_dependency "rake-compiler", ">= 0.9" - s.add_development_dependency "minitest", "< 5.0.0" - s.add_development_dependency "pry" + s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") end diff --git a/ruby/ext/bigdecimal/bigdecimal.h b/ruby/ext/bigdecimal/bigdecimal.h index e3eae06e6..bd1c46743 100644 --- a/ruby/ext/bigdecimal/bigdecimal.h +++ b/ruby/ext/bigdecimal/bigdecimal.h @@ -10,62 +10,74 @@ #define RUBY_BIG_DECIMAL_H 1 #define RUBY_NO_OLD_COMPATIBILITY - #include "ruby/ruby.h" -#include - -#ifndef RB_UNUSED_VAR -# ifdef __GNUC__ -# define RB_UNUSED_VAR(x) x __attribute__ ((unused)) -# else -# define RB_UNUSED_VAR(x) x -# endif -#endif +#include "missing.h" -#ifndef UNREACHABLE -# define UNREACHABLE /* unreachable */ +#ifdef HAVE_FLOAT_H +# include #endif -#undef BDIGIT -#undef SIZEOF_BDIGITS -#undef BDIGIT_DBL -#undef BDIGIT_DBL_SIGNED -#undef PRI_BDIGIT_PREFIX -#undef PRI_BDIGIT_DBL_PREFIX - #ifdef HAVE_INT64_T -# define BDIGIT uint32_t -# define BDIGIT_DBL uint64_t -# define BDIGIT_DBL_SIGNED int64_t -# define SIZEOF_BDIGITS 4 -# define PRI_BDIGIT_PREFIX "" +# 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_BDIGIT_DBL_PREFIX PRI_LL_PREFIX +# define PRI_DECDIG_DBL_PREFIX PRI_LL_PREFIX # else -# define PRI_BDIGIT_DBL_PREFIX "l" +# define PRI_DECDIG_DBL_PREFIX "l" # endif #else -# define BDIGIT uint16_t -# define BDIGIT_DBL uint32_t -# define BDIGIT_DBL_SIGNED int32_t -# define SIZEOF_BDIGITS 2 -# define PRI_BDIGIT_PREFIX "h" -# define PRI_BDIGIT_DBL_PREFIX "" +# 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 PRIdBDIGIT PRI_BDIGIT_PREFIX"d" -#define PRIiBDIGIT PRI_BDIGIT_PREFIX"i" -#define PRIoBDIGIT PRI_BDIGIT_PREFIX"o" -#define PRIuBDIGIT PRI_BDIGIT_PREFIX"u" -#define PRIxBDIGIT PRI_BDIGIT_PREFIX"x" -#define PRIXBDIGIT PRI_BDIGIT_PREFIX"X" +#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 PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d" -#define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i" -#define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o" -#define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u" -#define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x" -#define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X" +#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG) #if defined(__cplusplus) extern "C" { @@ -74,111 +86,8 @@ extern "C" { #endif #endif -#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 - -#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 - -#ifndef FIX_CONST_VALUE_PTR -# if defined(__fcc__) || defined(__fcc_version) || \ - defined(__FCC__) || defined(__FCC_VERSION) -/* workaround for old version of Fujitsu C Compiler (fcc) */ -# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) -# else -# define FIX_CONST_VALUE_PTR(x) (x) -# endif -#endif - -#ifndef HAVE_RB_ARRAY_CONST_PTR -static inline const VALUE * -rb_array_const_ptr(VALUE a) -{ - return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? - RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); -} -#endif - -#ifndef RARRAY_CONST_PTR -# define RARRAY_CONST_PTR(a) rb_array_const_ptr(a) -#endif - -#ifndef RARRAY_AREF -# define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i]) -#endif - -#ifndef HAVE_RB_SYM2STR -static inline VALUE -rb_sym2str(VALUE sym) -{ - return rb_id2str(SYM2ID(sym)); -} -#endif - -#ifndef ST2FIX -# undef RB_ST2FIX -# define RB_ST2FIX(h) LONG2FIX((long)(h)) -# define ST2FIX(h) RB_ST2FIX(h) -#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 - extern VALUE rb_cBigDecimal; -#if 0 || SIZEOF_BDIGITS >= 16 -# define RMPD_COMPONENT_FIGURES 38 -# define RMPD_BASE ((BDIGIT)100000000000000000000000000000000000000U) -#elif SIZEOF_BDIGITS >= 8 -# define RMPD_COMPONENT_FIGURES 19 -# define RMPD_BASE ((BDIGIT)10000000000000000000U) -#elif SIZEOF_BDIGITS >= 4 -# define RMPD_COMPONENT_FIGURES 9 -# define RMPD_BASE ((BDIGIT)1000000000U) -#elif SIZEOF_BDIGITS >= 2 -# define RMPD_COMPONENT_FIGURES 4 -# define RMPD_BASE ((BDIGIT)10000U) -#else -# define RMPD_COMPONENT_FIGURES 2 -# define RMPD_BASE ((BDIGIT)100U) -#endif - - /* * NaN & Infinity */ @@ -203,9 +112,8 @@ extern VALUE rb_cBigDecimal; /* Following 2 exceptions can't controlled by user */ #define VP_EXCEPTION_OP ((unsigned short)0x0020) -#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040) -#define RMPD_EXCEPTION_MODE_DEFAULT 0U +#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U /* Computation mode */ #define VP_ROUND_MODE ((unsigned short)0x0100) @@ -217,7 +125,7 @@ extern VALUE rb_cBigDecimal; #define VP_ROUND_FLOOR 6 #define VP_ROUND_HALF_EVEN 7 -#define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP +#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP #define VP_SIGN_NaN 0 /* NaN */ #define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ @@ -259,7 +167,7 @@ typedef struct { * -3 : Negative infinite number */ short flag; /* Not used in vp_routines,space for user. */ - BDIGIT frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */ + DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */ } Real; /* @@ -268,21 +176,13 @@ typedef struct { * ------------------ */ -VP_EXPORT Real * -VpNewRbClass(size_t mx, char const *str, VALUE klass); - -VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str); +VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception); -static inline BDIGIT -rmpd_base_value(void) { return RMPD_BASE; } -static inline size_t -rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; } -static inline size_t -rmpd_double_figures(void) { return 1+DBL_DIG; } +VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception); -#define VpBaseFig() rmpd_component_figures() -#define VpDblFig() rmpd_double_figures() -#define VpBaseVal() rmpd_base_value() +#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); @@ -304,7 +204,7 @@ VP_EXPORT int VpException(unsigned short f,const char *str,int always); VP_EXPORT int VpIsNegDoubleZero(double v); #endif VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt); -VP_EXPORT size_t VpInit(BDIGIT BaseVal); +VP_EXPORT size_t VpInit(DECDIG BaseVal); VP_EXPORT void *VpMemAlloc(size_t mb); VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb); VP_EXPORT void VpFree(Real *pv); @@ -330,7 +230,8 @@ 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 VpPower(Real *y, Real *x, SIGNED_VALUE n); +VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n); +#define VpPower VpPowerByInt /* VP constants */ VP_EXPORT Real *VpOne(void); diff --git a/ruby/ext/bigdecimal/bits.h b/ruby/ext/bigdecimal/bits.h new file mode 100644 index 000000000..6e1e4776e --- /dev/null +++ b/ruby/ext/bigdecimal/bits.h @@ -0,0 +1,141 @@ +#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/ruby/ext/bigdecimal/depend b/ruby/ext/bigdecimal/depend index ffd61b896..d6f40714b 100644 --- a/ruby/ext/bigdecimal/depend +++ b/ruby/ext/bigdecimal/depend @@ -5,8 +5,155 @@ Makefile: $(BIGDECIMAL_RB) 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/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/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/gc.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/rgengc.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 @@ -14,4 +161,168 @@ 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/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/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/gc.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/rgengc.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/ruby/ext/bigdecimal/extconf.rb b/ruby/ext/bigdecimal/extconf.rb index b4098fdac..9b0c55b21 100644 --- a/ruby/ext/bigdecimal/extconf.rb +++ b/ruby/ext/bigdecimal/extconf.rb @@ -3,10 +3,7 @@ def check_bigdecimal_version(gemspec_path) message "checking RUBY_BIGDECIMAL_VERSION... " - - bigdecimal_version = - IO.readlines(gemspec_path) - .grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([^\']+)\'/, 1] + bigdecimal_version = File.read(gemspec_path).match(/^\s*s\.version\s+=\s+['"]([^'"]+)['"]\s*$/)[1] version_components = bigdecimal_version.split('.') bigdecimal_version = version_components[0, 3].join('.') @@ -16,6 +13,20 @@ def check_bigdecimal_version(gemspec_path) message "#{bigdecimal_version}\n" end +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/ruby/ext/bigdecimal/lib/bigdecimal/util.rb b/ruby/ext/bigdecimal/lib/bigdecimal/util.rb index 4ece8347b..cb645d2a7 100644 --- a/ruby/ext/bigdecimal/lib/bigdecimal/util.rb +++ b/ruby/ext/bigdecimal/lib/bigdecimal/util.rb @@ -43,7 +43,7 @@ class Float < Numeric # # See also BigDecimal::new. # - def to_d(precision=Float::DIG) + def to_d(precision=0) BigDecimal(self, precision) end end @@ -131,6 +131,39 @@ def to_d(precision) 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 diff --git a/ruby/ext/bigdecimal/missing.c b/ruby/ext/bigdecimal/missing.c new file mode 100644 index 000000000..703232d92 --- /dev/null +++ b/ruby/ext/bigdecimal/missing.c @@ -0,0 +1,27 @@ +#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/ruby/ext/bigdecimal/missing.h b/ruby/ext/bigdecimal/missing.h new file mode 100644 index 000000000..796984915 --- /dev/null +++ b/ruby/ext/bigdecimal/missing.h @@ -0,0 +1,235 @@ +#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 + +#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300 +# define HAVE___ASSUME +#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 HAVE_TYPE_STRUCT_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 HAVE_TYPE_STRUCT_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 HAVE_TYPE_STRUCT_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 HAVE_TYPE_STRUCT_RCOMPLEX + return RCOMPLEX(cmp)->imag; +# else + return rb_funcall(cmp, rb_intern("imag"), 0); +# endif +} +#endif + +/* array */ + +#ifndef FIX_CONST_VALUE_PTR +# if defined(__fcc__) || defined(__fcc_version) || \ + defined(__FCC__) || defined(__FCC_VERSION) +/* workaround for old version of Fujitsu C Compiler (fcc) */ +# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) +# else +# define FIX_CONST_VALUE_PTR(x) (x) +# endif +#endif + +#ifndef HAVE_RB_ARRAY_CONST_PTR +static inline const VALUE * +rb_array_const_ptr(VALUE a) +{ + return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? + RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); +} +#endif + +#ifndef RARRAY_CONST_PTR +# define RARRAY_CONST_PTR(a) rb_array_const_ptr(a) +#endif + +#ifndef RARRAY_AREF +# define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i]) +#endif + +/* symbol */ + +#ifndef HAVE_RB_SYM2STR +static inline VALUE +rb_sym2str(VALUE sym) +{ + return rb_id2str(SYM2ID(sym)); +} +#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/ruby/ext/bigdecimal/missing/dtoa.c b/ruby/ext/bigdecimal/missing/dtoa.c new file mode 100644 index 000000000..41b0a221d --- /dev/null +++ b/ruby/ext/bigdecimal/missing/dtoa.c @@ -0,0 +1,3462 @@ +/**************************************************************** + * + * 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/ruby/ext/bigdecimal/static_assert.h b/ruby/ext/bigdecimal/static_assert.h new file mode 100644 index 000000000..9295729bf --- /dev/null +++ b/ruby/ext/bigdecimal/static_assert.h @@ -0,0 +1,54 @@ +#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/ruby/ext/bigdecimal/util/depend b/ruby/ext/bigdecimal/util/depend deleted file mode 100644 index 96b6a7fea..000000000 --- a/ruby/ext/bigdecimal/util/depend +++ /dev/null @@ -1,14 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -util.o: $(RUBY_EXTCONF_H) -util.o: $(arch_hdrdir)/ruby/config.h -util.o: $(hdrdir)/ruby.h -util.o: $(hdrdir)/ruby/assert.h -util.o: $(hdrdir)/ruby/backward.h -util.o: $(hdrdir)/ruby/defines.h -util.o: $(hdrdir)/ruby/intern.h -util.o: $(hdrdir)/ruby/missing.h -util.o: $(hdrdir)/ruby/ruby.h -util.o: $(hdrdir)/ruby/st.h -util.o: $(hdrdir)/ruby/subst.h -util.o: util.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/cgi/escape/depend b/ruby/ext/cgi/escape/depend index 8d4736616..e726e579d 100644 --- a/ruby/ext/cgi/escape/depend +++ b/ruby/ext/cgi/escape/depend @@ -4,9 +4,165 @@ escape.o: $(arch_hdrdir)/ruby/config.h escape.o: $(hdrdir)/ruby.h escape.o: $(hdrdir)/ruby/assert.h escape.o: $(hdrdir)/ruby/backward.h +escape.o: $(hdrdir)/ruby/backward/2/assume.h +escape.o: $(hdrdir)/ruby/backward/2/attributes.h +escape.o: $(hdrdir)/ruby/backward/2/bool.h +escape.o: $(hdrdir)/ruby/backward/2/inttypes.h +escape.o: $(hdrdir)/ruby/backward/2/limits.h +escape.o: $(hdrdir)/ruby/backward/2/long_long.h +escape.o: $(hdrdir)/ruby/backward/2/stdalign.h +escape.o: $(hdrdir)/ruby/backward/2/stdarg.h escape.o: $(hdrdir)/ruby/defines.h escape.o: $(hdrdir)/ruby/encoding.h escape.o: $(hdrdir)/ruby/intern.h +escape.o: $(hdrdir)/ruby/internal/anyargs.h +escape.o: $(hdrdir)/ruby/internal/arithmetic.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/char.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/double.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/int.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/long.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/short.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +escape.o: $(hdrdir)/ruby/internal/assume.h +escape.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +escape.o: $(hdrdir)/ruby/internal/attr/artificial.h +escape.o: $(hdrdir)/ruby/internal/attr/cold.h +escape.o: $(hdrdir)/ruby/internal/attr/const.h +escape.o: $(hdrdir)/ruby/internal/attr/constexpr.h +escape.o: $(hdrdir)/ruby/internal/attr/deprecated.h +escape.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +escape.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +escape.o: $(hdrdir)/ruby/internal/attr/error.h +escape.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +escape.o: $(hdrdir)/ruby/internal/attr/forceinline.h +escape.o: $(hdrdir)/ruby/internal/attr/format.h +escape.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +escape.o: $(hdrdir)/ruby/internal/attr/noalias.h +escape.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +escape.o: $(hdrdir)/ruby/internal/attr/noexcept.h +escape.o: $(hdrdir)/ruby/internal/attr/noinline.h +escape.o: $(hdrdir)/ruby/internal/attr/nonnull.h +escape.o: $(hdrdir)/ruby/internal/attr/noreturn.h +escape.o: $(hdrdir)/ruby/internal/attr/pure.h +escape.o: $(hdrdir)/ruby/internal/attr/restrict.h +escape.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +escape.o: $(hdrdir)/ruby/internal/attr/warning.h +escape.o: $(hdrdir)/ruby/internal/attr/weakref.h +escape.o: $(hdrdir)/ruby/internal/cast.h +escape.o: $(hdrdir)/ruby/internal/compiler_is.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +escape.o: $(hdrdir)/ruby/internal/compiler_since.h +escape.o: $(hdrdir)/ruby/internal/config.h +escape.o: $(hdrdir)/ruby/internal/constant_p.h +escape.o: $(hdrdir)/ruby/internal/core.h +escape.o: $(hdrdir)/ruby/internal/core/rarray.h +escape.o: $(hdrdir)/ruby/internal/core/rbasic.h +escape.o: $(hdrdir)/ruby/internal/core/rbignum.h +escape.o: $(hdrdir)/ruby/internal/core/rclass.h +escape.o: $(hdrdir)/ruby/internal/core/rdata.h +escape.o: $(hdrdir)/ruby/internal/core/rfile.h +escape.o: $(hdrdir)/ruby/internal/core/rhash.h +escape.o: $(hdrdir)/ruby/internal/core/robject.h +escape.o: $(hdrdir)/ruby/internal/core/rregexp.h +escape.o: $(hdrdir)/ruby/internal/core/rstring.h +escape.o: $(hdrdir)/ruby/internal/core/rstruct.h +escape.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +escape.o: $(hdrdir)/ruby/internal/ctype.h +escape.o: $(hdrdir)/ruby/internal/dllexport.h +escape.o: $(hdrdir)/ruby/internal/dosish.h +escape.o: $(hdrdir)/ruby/internal/encoding/coderange.h +escape.o: $(hdrdir)/ruby/internal/encoding/ctype.h +escape.o: $(hdrdir)/ruby/internal/encoding/encoding.h +escape.o: $(hdrdir)/ruby/internal/encoding/pathname.h +escape.o: $(hdrdir)/ruby/internal/encoding/re.h +escape.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +escape.o: $(hdrdir)/ruby/internal/encoding/string.h +escape.o: $(hdrdir)/ruby/internal/encoding/symbol.h +escape.o: $(hdrdir)/ruby/internal/encoding/transcode.h +escape.o: $(hdrdir)/ruby/internal/error.h +escape.o: $(hdrdir)/ruby/internal/eval.h +escape.o: $(hdrdir)/ruby/internal/event.h +escape.o: $(hdrdir)/ruby/internal/fl_type.h +escape.o: $(hdrdir)/ruby/internal/gc.h +escape.o: $(hdrdir)/ruby/internal/glob.h +escape.o: $(hdrdir)/ruby/internal/globals.h +escape.o: $(hdrdir)/ruby/internal/has/attribute.h +escape.o: $(hdrdir)/ruby/internal/has/builtin.h +escape.o: $(hdrdir)/ruby/internal/has/c_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/extension.h +escape.o: $(hdrdir)/ruby/internal/has/feature.h +escape.o: $(hdrdir)/ruby/internal/has/warning.h +escape.o: $(hdrdir)/ruby/internal/intern/array.h +escape.o: $(hdrdir)/ruby/internal/intern/bignum.h +escape.o: $(hdrdir)/ruby/internal/intern/class.h +escape.o: $(hdrdir)/ruby/internal/intern/compar.h +escape.o: $(hdrdir)/ruby/internal/intern/complex.h +escape.o: $(hdrdir)/ruby/internal/intern/cont.h +escape.o: $(hdrdir)/ruby/internal/intern/dir.h +escape.o: $(hdrdir)/ruby/internal/intern/enum.h +escape.o: $(hdrdir)/ruby/internal/intern/enumerator.h +escape.o: $(hdrdir)/ruby/internal/intern/error.h +escape.o: $(hdrdir)/ruby/internal/intern/eval.h +escape.o: $(hdrdir)/ruby/internal/intern/file.h +escape.o: $(hdrdir)/ruby/internal/intern/gc.h +escape.o: $(hdrdir)/ruby/internal/intern/hash.h +escape.o: $(hdrdir)/ruby/internal/intern/io.h +escape.o: $(hdrdir)/ruby/internal/intern/load.h +escape.o: $(hdrdir)/ruby/internal/intern/marshal.h +escape.o: $(hdrdir)/ruby/internal/intern/numeric.h +escape.o: $(hdrdir)/ruby/internal/intern/object.h +escape.o: $(hdrdir)/ruby/internal/intern/parse.h +escape.o: $(hdrdir)/ruby/internal/intern/proc.h +escape.o: $(hdrdir)/ruby/internal/intern/process.h +escape.o: $(hdrdir)/ruby/internal/intern/random.h +escape.o: $(hdrdir)/ruby/internal/intern/range.h +escape.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h +escape.o: $(hdrdir)/ruby/internal/intern/string.h +escape.o: $(hdrdir)/ruby/internal/intern/struct.h +escape.o: $(hdrdir)/ruby/internal/intern/thread.h +escape.o: $(hdrdir)/ruby/internal/intern/time.h +escape.o: $(hdrdir)/ruby/internal/intern/variable.h +escape.o: $(hdrdir)/ruby/internal/intern/vm.h +escape.o: $(hdrdir)/ruby/internal/interpreter.h +escape.o: $(hdrdir)/ruby/internal/iterator.h +escape.o: $(hdrdir)/ruby/internal/memory.h +escape.o: $(hdrdir)/ruby/internal/method.h +escape.o: $(hdrdir)/ruby/internal/module.h +escape.o: $(hdrdir)/ruby/internal/newobj.h +escape.o: $(hdrdir)/ruby/internal/rgengc.h +escape.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +escape.o: $(hdrdir)/ruby/internal/value.h +escape.o: $(hdrdir)/ruby/internal/value_type.h +escape.o: $(hdrdir)/ruby/internal/variable.h +escape.o: $(hdrdir)/ruby/internal/warning_push.h +escape.o: $(hdrdir)/ruby/internal/xmalloc.h escape.o: $(hdrdir)/ruby/missing.h escape.o: $(hdrdir)/ruby/onigmo.h escape.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/cgi/escape/escape.c b/ruby/ext/cgi/escape/escape.c index 47188819c..f88b61478 100644 --- a/ruby/ext/cgi/escape/escape.c +++ b/ruby/ext/cgi/escape/escape.c @@ -32,11 +32,21 @@ preserve_original_state(VALUE orig, VALUE dest) rb_enc_associate(dest, rb_enc_get(orig)); } +static inline long +escaped_length(VALUE str) +{ + const long len = RSTRING_LEN(str); + if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) { + ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN); + } + return len * HTML_ESCAPE_MAX_LEN; +} + static VALUE optimized_escape_html(VALUE str) { VALUE vbuf; - char *buf = ALLOCV_N(char, vbuf, RSTRING_LEN(str) * HTML_ESCAPE_MAX_LEN); + char *buf = ALLOCV_N(char, vbuf, escaped_length(str)); const char *cstr = RSTRING_PTR(str); const char *end = cstr + RSTRING_LEN(str); @@ -388,6 +398,10 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self) void Init_escape(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + id_accept_charset = rb_intern_const("@@accept_charset"); InitVM(escape); } diff --git a/ruby/ext/continuation/depend b/ruby/ext/continuation/depend index 08844aa6b..14ecac144 100644 --- a/ruby/ext/continuation/depend +++ b/ruby/ext/continuation/depend @@ -3,8 +3,155 @@ continuation.o: $(RUBY_EXTCONF_H) continuation.o: $(arch_hdrdir)/ruby/config.h continuation.o: $(hdrdir)/ruby/assert.h continuation.o: $(hdrdir)/ruby/backward.h +continuation.o: $(hdrdir)/ruby/backward/2/assume.h +continuation.o: $(hdrdir)/ruby/backward/2/attributes.h +continuation.o: $(hdrdir)/ruby/backward/2/bool.h +continuation.o: $(hdrdir)/ruby/backward/2/inttypes.h +continuation.o: $(hdrdir)/ruby/backward/2/limits.h +continuation.o: $(hdrdir)/ruby/backward/2/long_long.h +continuation.o: $(hdrdir)/ruby/backward/2/stdalign.h +continuation.o: $(hdrdir)/ruby/backward/2/stdarg.h continuation.o: $(hdrdir)/ruby/defines.h continuation.o: $(hdrdir)/ruby/intern.h +continuation.o: $(hdrdir)/ruby/internal/anyargs.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/char.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/double.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/int.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/long.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/short.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +continuation.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +continuation.o: $(hdrdir)/ruby/internal/assume.h +continuation.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +continuation.o: $(hdrdir)/ruby/internal/attr/artificial.h +continuation.o: $(hdrdir)/ruby/internal/attr/cold.h +continuation.o: $(hdrdir)/ruby/internal/attr/const.h +continuation.o: $(hdrdir)/ruby/internal/attr/constexpr.h +continuation.o: $(hdrdir)/ruby/internal/attr/deprecated.h +continuation.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +continuation.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +continuation.o: $(hdrdir)/ruby/internal/attr/error.h +continuation.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +continuation.o: $(hdrdir)/ruby/internal/attr/forceinline.h +continuation.o: $(hdrdir)/ruby/internal/attr/format.h +continuation.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +continuation.o: $(hdrdir)/ruby/internal/attr/noalias.h +continuation.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +continuation.o: $(hdrdir)/ruby/internal/attr/noexcept.h +continuation.o: $(hdrdir)/ruby/internal/attr/noinline.h +continuation.o: $(hdrdir)/ruby/internal/attr/nonnull.h +continuation.o: $(hdrdir)/ruby/internal/attr/noreturn.h +continuation.o: $(hdrdir)/ruby/internal/attr/pure.h +continuation.o: $(hdrdir)/ruby/internal/attr/restrict.h +continuation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +continuation.o: $(hdrdir)/ruby/internal/attr/warning.h +continuation.o: $(hdrdir)/ruby/internal/attr/weakref.h +continuation.o: $(hdrdir)/ruby/internal/cast.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +continuation.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +continuation.o: $(hdrdir)/ruby/internal/compiler_since.h +continuation.o: $(hdrdir)/ruby/internal/config.h +continuation.o: $(hdrdir)/ruby/internal/constant_p.h +continuation.o: $(hdrdir)/ruby/internal/core.h +continuation.o: $(hdrdir)/ruby/internal/core/rarray.h +continuation.o: $(hdrdir)/ruby/internal/core/rbasic.h +continuation.o: $(hdrdir)/ruby/internal/core/rbignum.h +continuation.o: $(hdrdir)/ruby/internal/core/rclass.h +continuation.o: $(hdrdir)/ruby/internal/core/rdata.h +continuation.o: $(hdrdir)/ruby/internal/core/rfile.h +continuation.o: $(hdrdir)/ruby/internal/core/rhash.h +continuation.o: $(hdrdir)/ruby/internal/core/robject.h +continuation.o: $(hdrdir)/ruby/internal/core/rregexp.h +continuation.o: $(hdrdir)/ruby/internal/core/rstring.h +continuation.o: $(hdrdir)/ruby/internal/core/rstruct.h +continuation.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +continuation.o: $(hdrdir)/ruby/internal/ctype.h +continuation.o: $(hdrdir)/ruby/internal/dllexport.h +continuation.o: $(hdrdir)/ruby/internal/dosish.h +continuation.o: $(hdrdir)/ruby/internal/error.h +continuation.o: $(hdrdir)/ruby/internal/eval.h +continuation.o: $(hdrdir)/ruby/internal/event.h +continuation.o: $(hdrdir)/ruby/internal/fl_type.h +continuation.o: $(hdrdir)/ruby/internal/gc.h +continuation.o: $(hdrdir)/ruby/internal/glob.h +continuation.o: $(hdrdir)/ruby/internal/globals.h +continuation.o: $(hdrdir)/ruby/internal/has/attribute.h +continuation.o: $(hdrdir)/ruby/internal/has/builtin.h +continuation.o: $(hdrdir)/ruby/internal/has/c_attribute.h +continuation.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +continuation.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +continuation.o: $(hdrdir)/ruby/internal/has/extension.h +continuation.o: $(hdrdir)/ruby/internal/has/feature.h +continuation.o: $(hdrdir)/ruby/internal/has/warning.h +continuation.o: $(hdrdir)/ruby/internal/intern/array.h +continuation.o: $(hdrdir)/ruby/internal/intern/bignum.h +continuation.o: $(hdrdir)/ruby/internal/intern/class.h +continuation.o: $(hdrdir)/ruby/internal/intern/compar.h +continuation.o: $(hdrdir)/ruby/internal/intern/complex.h +continuation.o: $(hdrdir)/ruby/internal/intern/cont.h +continuation.o: $(hdrdir)/ruby/internal/intern/dir.h +continuation.o: $(hdrdir)/ruby/internal/intern/enum.h +continuation.o: $(hdrdir)/ruby/internal/intern/enumerator.h +continuation.o: $(hdrdir)/ruby/internal/intern/error.h +continuation.o: $(hdrdir)/ruby/internal/intern/eval.h +continuation.o: $(hdrdir)/ruby/internal/intern/file.h +continuation.o: $(hdrdir)/ruby/internal/intern/gc.h +continuation.o: $(hdrdir)/ruby/internal/intern/hash.h +continuation.o: $(hdrdir)/ruby/internal/intern/io.h +continuation.o: $(hdrdir)/ruby/internal/intern/load.h +continuation.o: $(hdrdir)/ruby/internal/intern/marshal.h +continuation.o: $(hdrdir)/ruby/internal/intern/numeric.h +continuation.o: $(hdrdir)/ruby/internal/intern/object.h +continuation.o: $(hdrdir)/ruby/internal/intern/parse.h +continuation.o: $(hdrdir)/ruby/internal/intern/proc.h +continuation.o: $(hdrdir)/ruby/internal/intern/process.h +continuation.o: $(hdrdir)/ruby/internal/intern/random.h +continuation.o: $(hdrdir)/ruby/internal/intern/range.h +continuation.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +continuation.o: $(hdrdir)/ruby/internal/intern/sprintf.h +continuation.o: $(hdrdir)/ruby/internal/intern/string.h +continuation.o: $(hdrdir)/ruby/internal/intern/struct.h +continuation.o: $(hdrdir)/ruby/internal/intern/thread.h +continuation.o: $(hdrdir)/ruby/internal/intern/time.h +continuation.o: $(hdrdir)/ruby/internal/intern/variable.h +continuation.o: $(hdrdir)/ruby/internal/intern/vm.h +continuation.o: $(hdrdir)/ruby/internal/interpreter.h +continuation.o: $(hdrdir)/ruby/internal/iterator.h +continuation.o: $(hdrdir)/ruby/internal/memory.h +continuation.o: $(hdrdir)/ruby/internal/method.h +continuation.o: $(hdrdir)/ruby/internal/module.h +continuation.o: $(hdrdir)/ruby/internal/newobj.h +continuation.o: $(hdrdir)/ruby/internal/rgengc.h +continuation.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +continuation.o: $(hdrdir)/ruby/internal/value.h +continuation.o: $(hdrdir)/ruby/internal/value_type.h +continuation.o: $(hdrdir)/ruby/internal/variable.h +continuation.o: $(hdrdir)/ruby/internal/warning_push.h +continuation.o: $(hdrdir)/ruby/internal/xmalloc.h continuation.o: $(hdrdir)/ruby/missing.h continuation.o: $(hdrdir)/ruby/ruby.h continuation.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/coverage/coverage.c b/ruby/ext/coverage/coverage.c index 8503c9d6c..3dc2490d4 100644 --- a/ruby/ext/coverage/coverage.c +++ b/ruby/ext/coverage/coverage.c @@ -8,25 +8,45 @@ ************************************************/ +#include "gc.h" +#include "internal/hash.h" +#include "internal/thread.h" +#include "internal/sanitizers.h" #include "ruby.h" #include "vm_core.h" -#include "gc.h" +static enum { + IDLE, + SUSPENDED, + RUNNING +} current_state = IDLE; static int current_mode; static VALUE me2counter = Qnil; /* * call-seq: - * Coverage.start => nil + * Coverage.setup => nil + * Coverage.setup(:all) => nil + * Coverage.setup(lines: bool, branches: bool, methods: bool) => nil + * Coverage.setup(oneshot_lines: true) => nil + * + * Set up the coverage measurement. + * + * Note that this method does not start the measurement itself. + * Use Coverage.resume to start the measurement. * - * Enables coverage measurement. + * You may want to use Coverage.start to setup and then start the measurement. */ static VALUE -rb_coverage_start(int argc, VALUE *argv, VALUE klass) +rb_coverage_setup(int argc, VALUE *argv, VALUE klass) { VALUE coverages, opt; int mode; + if (current_state != IDLE) { + rb_raise(rb_eRuntimeError, "coverage measurement is already setup"); + } + rb_scan_args(argc, argv, "01", &opt); if (argc == 0) { @@ -67,43 +87,116 @@ rb_coverage_start(int argc, VALUE *argv, VALUE klass) current_mode = mode; if (mode == 0) mode = COVERAGE_TARGET_LINES; rb_set_coverages(coverages, mode, me2counter); + current_state = SUSPENDED; } else if (current_mode != mode) { rb_raise(rb_eRuntimeError, "cannot change the measuring target during coverage measurement"); } + + + return Qnil; +} + +/* + * call-seq: + * Coverage.resume => nil + * + * Start/resume the coverage measurement. + * + * Caveat: Currently, only process-global coverage measurement is supported. + * You cannot measure per-thread covearge. If your process has multiple thread, + * using Coverage.resume/suspend to capture code coverage executed from only + * a limited code block, may yield misleading results. + */ +VALUE +rb_coverage_resume(VALUE klass) +{ + if (current_state == IDLE) { + rb_raise(rb_eRuntimeError, "coverage measurement is not set up yet"); + } + if (current_state == RUNNING) { + rb_raise(rb_eRuntimeError, "coverage measurement is already running"); + } + rb_resume_coverages(); + current_state = RUNNING; + return Qnil; +} + +/* + * call-seq: + * Coverage.start => nil + * Coverage.start(:all) => nil + * Coverage.start(lines: bool, branches: bool, methods: bool) => nil + * Coverage.start(oneshot_lines: true) => nil + * + * Enables the coverage measurement. + * See the documentation of Coverage class in detail. + * This is equivalent to Coverage.setup and Coverage.resume. + */ +static VALUE +rb_coverage_start(int argc, VALUE *argv, VALUE klass) +{ + rb_coverage_setup(argc, argv, klass); + rb_coverage_resume(klass); return Qnil; } +struct branch_coverage_result_builder +{ + int id; + VALUE result; + VALUE children; + VALUE counters; +}; + +static int +branch_coverage_ii(VALUE _key, VALUE branch, VALUE v) +{ + struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v; + + VALUE target_label = RARRAY_AREF(branch, 0); + VALUE target_first_lineno = RARRAY_AREF(branch, 1); + VALUE target_first_column = RARRAY_AREF(branch, 2); + VALUE target_last_lineno = RARRAY_AREF(branch, 3); + VALUE target_last_column = RARRAY_AREF(branch, 4); + long counter_idx = FIX2LONG(RARRAY_AREF(branch, 5)); + rb_hash_aset(b->children, rb_ary_new_from_args(6, target_label, LONG2FIX(b->id++), target_first_lineno, target_first_column, target_last_lineno, target_last_column), RARRAY_AREF(b->counters, counter_idx)); + + return ST_CONTINUE; +} + +static int +branch_coverage_i(VALUE _key, VALUE branch_base, VALUE v) +{ + struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v; + + VALUE base_type = RARRAY_AREF(branch_base, 0); + VALUE base_first_lineno = RARRAY_AREF(branch_base, 1); + VALUE base_first_column = RARRAY_AREF(branch_base, 2); + VALUE base_last_lineno = RARRAY_AREF(branch_base, 3); + VALUE base_last_column = RARRAY_AREF(branch_base, 4); + VALUE branches = RARRAY_AREF(branch_base, 5); + VALUE children = rb_hash_new(); + rb_hash_aset(b->result, rb_ary_new_from_args(6, base_type, LONG2FIX(b->id++), base_first_lineno, base_first_column, base_last_lineno, base_last_column), children); + b->children = children; + rb_hash_foreach(branches, branch_coverage_ii, v); + + return ST_CONTINUE; +} + static VALUE branch_coverage(VALUE branches) { - VALUE ret = rb_hash_new(); - VALUE structure = rb_ary_dup(RARRAY_AREF(branches, 0)); - VALUE counters = rb_ary_dup(RARRAY_AREF(branches, 1)); - int i, j; - long id = 0; - - for (i = 0; i < RARRAY_LEN(structure); i++) { - VALUE branches = RARRAY_AREF(structure, i); - VALUE base_type = RARRAY_AREF(branches, 0); - VALUE base_first_lineno = RARRAY_AREF(branches, 1); - VALUE base_first_column = RARRAY_AREF(branches, 2); - VALUE base_last_lineno = RARRAY_AREF(branches, 3); - VALUE base_last_column = RARRAY_AREF(branches, 4); - VALUE children = rb_hash_new(); - rb_hash_aset(ret, rb_ary_new_from_args(6, base_type, LONG2FIX(id++), base_first_lineno, base_first_column, base_last_lineno, base_last_column), children); - for (j = 5; j < RARRAY_LEN(branches); j += 6) { - VALUE target_label = RARRAY_AREF(branches, j); - VALUE target_first_lineno = RARRAY_AREF(branches, j + 1); - VALUE target_first_column = RARRAY_AREF(branches, j + 2); - VALUE target_last_lineno = RARRAY_AREF(branches, j + 3); - VALUE target_last_column = RARRAY_AREF(branches, j + 4); - int idx = FIX2INT(RARRAY_AREF(branches, j + 5)); - rb_hash_aset(children, rb_ary_new_from_args(6, target_label, LONG2FIX(id++), target_first_lineno, target_first_column, target_last_lineno, target_last_column), RARRAY_AREF(counters, idx)); - } - } + VALUE structure = RARRAY_AREF(branches, 0); + + struct branch_coverage_result_builder b; + b.id = 0; + b.result = rb_hash_new(); + b.counters = RARRAY_AREF(branches, 1); - return ret; + rb_hash_foreach(structure, branch_coverage_i, (VALUE)&b); + + return b.result; } static int @@ -122,6 +215,9 @@ 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); + if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) { const rb_method_entry_t *me = (rb_method_entry_t *) v; VALUE path, first_lineno, first_column, last_lineno, last_column; @@ -161,6 +257,10 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data) rb_hash_aset(methods, key, rcount); } } + + if (poisoned) { + asan_poison_object(v); + } } return 0; } @@ -224,7 +324,8 @@ rb_coverage_peek_result(VALUE klass) if (!RTEST(coverages)) { rb_raise(rb_eRuntimeError, "coverage measurement is not enabled"); } - st_foreach(RHASH_TBL(coverages), coverage_peek_result_i, ncoverages); + OBJ_WB_UNPROTECT(coverages); + st_foreach(RHASH_TBL_RAW(coverages), coverage_peek_result_i, ncoverages); if (current_mode & COVERAGE_TARGET_METHODS) { rb_objspace_each_objects(method_coverage_i, &ncoverages); @@ -242,6 +343,24 @@ clear_me2counter_i(VALUE key, VALUE value, VALUE unused) return ST_CONTINUE; } +/* + * call-seq: + * Coverage.suspend => nil + * + * Suspend the coverage measurement. + * You can use Coverage.resume to restart the measurement. + */ +VALUE +rb_coverage_suspend(VALUE klass) +{ + if (current_state != RUNNING) { + rb_raise(rb_eRuntimeError, "coverage measurement is not running"); + } + rb_suspend_coverages(); + current_state = SUSPENDED; + return Qnil; +} + /* * call-seq: * Coverage.result(stop: true, clear: true) => hash @@ -257,6 +376,10 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass) VALUE opt; int stop = 1, clear = 1; + if (current_state == IDLE) { + rb_raise(rb_eRuntimeError, "coverage measurement is not enabled"); + } + rb_scan_args(argc, argv, "01", &opt); if (argc == 1) { @@ -275,13 +398,34 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass) if (!NIL_P(me2counter)) rb_hash_foreach(me2counter, clear_me2counter_i, Qnil); } if (stop) { + if (current_state == RUNNING) { + rb_coverage_suspend(klass); + } rb_reset_coverages(); me2counter = Qnil; + current_state = IDLE; } return ncoverages; } +/* + * call-seq: + * Coverage.state => :idle, :suspended, :running + * + * Returns the state of the coverage measurement. + */ +static VALUE +rb_coverage_state(VALUE klass) +{ + switch (current_state) { + case IDLE: return ID2SYM(rb_intern("idle")); + case SUSPENDED: return ID2SYM(rb_intern("suspended")); + case RUNNING: return ID2SYM(rb_intern("running")); + } + return Qnil; +} + /* * call-seq: * Coverage.running? => bool @@ -292,13 +436,15 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass) static VALUE rb_coverage_running(VALUE klass) { - VALUE coverages = rb_get_coverages(); - return RTEST(coverages) ? Qtrue : Qfalse; + return current_state == RUNNING ? Qtrue : Qfalse; } /* Coverage provides coverage measurement feature for Ruby. * This feature is experimental, so these APIs may be changed in future. * + * Caveat: Currently, only process-global coverage measurement is supported. + * You cannot measure per-thread covearge. + * * = Usage * * 1. require "coverage" @@ -309,7 +455,7 @@ rb_coverage_running(VALUE klass) * number of line execution by the interpreter. A +nil+ value means * coverage is disabled for this line (lines like +else+ and +end+). * - * = Example + * = Examples * * [foo.rb] * s = 0 @@ -328,14 +474,128 @@ rb_coverage_running(VALUE klass) * Coverage.start * require "foo.rb" * p Coverage.result #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]} + * + * == Lines Coverage + * + * If a coverage mode is not explicitly specified when starting coverage, lines + * coverage is what will run. It reports the number of line executions for each + * line. + * + * require "coverage" + * Coverage.start(lines: true) + * require "foo.rb" + * p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}} + * + * The value of the lines coverage result is an array containing how many times + * each line was executed. Order in this array is important. For example, the + * first item in this array, at index 0, reports how many times line 1 of this + * file was executed while coverage was run (which, in this example, is one + * time). + * + * A +nil+ value means coverage is disabled for this line (lines like +else+ + * and +end+). + * + * == Oneshot Lines Coverage + * + * Oneshot lines coverage tracks and reports on the executed lines while + * coverage is running. It will not report how many times a line was executed, + * only that it was executed. + * + * require "coverage" + * Coverage.start(oneshot_lines: true) + * require "foo.rb" + * p Coverage.result #=> {"foo.rb"=>{:oneshot_lines=>[1, 2, 3, 6, 7]}} + * + * The value of the oneshot lines coverage result is an array containing the + * line numbers that were executed. + * + * == Branches Coverage + * + * Branches coverage reports how many times each branch within each conditional + * was executed. + * + * require "coverage" + * Coverage.start(branches: true) + * require "foo.rb" + * p Coverage.result #=> {"foo.rb"=>{:branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}}} + * + * Each entry within the branches hash is a conditional, the value of which is + * another hash where each entry is a branch in that conditional. The values + * are the number of times the method was executed, and the keys are identifying + * information about the branch. + * + * The information that makes up each key identifying branches or conditionals + * is the following, from left to right: + * + * 1. A label for the type of branch or conditional. + * 2. A unique identifier. + * 3. The starting line number it appears on in the file. + * 4. The starting column number it appears on in the file. + * 5. The ending line number it appears on in the file. + * 6. The ending column number it appears on in the file. + * + * == Methods Coverage + * + * Methods coverage reports how many times each method was executed. + * + * [foo_method.rb] + * class Greeter + * def greet + * "welcome!" + * end + * end + * + * def hello + * "Hi" + * end + * + * hello() + * Greeter.new.greet() + * [EOF] + * + * require "coverage" + * Coverage.start(methods: true) + * require "foo_method.rb" + * p Coverage.result #=> {"foo_method.rb"=>{:methods=>{[Object, :hello, 7, 0, 9, 3]=>1, [Greeter, :greet, 2, 2, 4, 5]=>1}}} + * + * Each entry within the methods hash represents a method. The values in this + * hash are the number of times the method was executed, and the keys are + * identifying information about the method. + * + * The information that makes up each key identifying a method is the following, + * from left to right: + * + * 1. The class. + * 2. The method name. + * 3. The starting line number the method appears on in the file. + * 4. The starting column number the method appears on in the file. + * 5. The ending line number the method appears on in the file. + * 6. The ending column number the method appears on in the file. + * + * == All Coverage Modes + * + * You can also run all modes of coverage simultaneously with this shortcut. + * Note that running all coverage modes does not run both lines and oneshot + * lines. Those modes cannot be run simultaneously. Lines coverage is run in + * this case, because you can still use it to determine whether or not a line + * was executed. + * + * require "coverage" + * Coverage.start(:all) + * require "foo.rb" + * p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil], :branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}, :methods=>{}}} */ void Init_coverage(void) { VALUE rb_mCoverage = rb_define_module("Coverage"); + rb_define_module_function(rb_mCoverage, "setup", rb_coverage_setup, -1); rb_define_module_function(rb_mCoverage, "start", rb_coverage_start, -1); + rb_define_module_function(rb_mCoverage, "resume", rb_coverage_resume, 0); + rb_define_module_function(rb_mCoverage, "suspend", rb_coverage_suspend, 0); rb_define_module_function(rb_mCoverage, "result", rb_coverage_result, -1); rb_define_module_function(rb_mCoverage, "peek_result", rb_coverage_peek_result, 0); + rb_define_module_function(rb_mCoverage, "state", rb_coverage_state, 0); rb_define_module_function(rb_mCoverage, "running?", rb_coverage_running, 0); rb_global_variable(&me2counter); } diff --git a/ruby/ext/coverage/depend b/ruby/ext/coverage/depend index 20b76be04..228ee7381 100644 --- a/ruby/ext/coverage/depend +++ b/ruby/ext/coverage/depend @@ -3,9 +3,158 @@ coverage.o: $(RUBY_EXTCONF_H) coverage.o: $(arch_hdrdir)/ruby/config.h coverage.o: $(hdrdir)/ruby.h coverage.o: $(hdrdir)/ruby/assert.h +coverage.o: $(hdrdir)/ruby/atomic.h coverage.o: $(hdrdir)/ruby/backward.h +coverage.o: $(hdrdir)/ruby/backward/2/assume.h +coverage.o: $(hdrdir)/ruby/backward/2/attributes.h +coverage.o: $(hdrdir)/ruby/backward/2/bool.h +coverage.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +coverage.o: $(hdrdir)/ruby/backward/2/inttypes.h +coverage.o: $(hdrdir)/ruby/backward/2/limits.h +coverage.o: $(hdrdir)/ruby/backward/2/long_long.h +coverage.o: $(hdrdir)/ruby/backward/2/stdalign.h +coverage.o: $(hdrdir)/ruby/backward/2/stdarg.h coverage.o: $(hdrdir)/ruby/defines.h coverage.o: $(hdrdir)/ruby/intern.h +coverage.o: $(hdrdir)/ruby/internal/anyargs.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/char.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/double.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/int.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/long.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/short.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +coverage.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +coverage.o: $(hdrdir)/ruby/internal/assume.h +coverage.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +coverage.o: $(hdrdir)/ruby/internal/attr/artificial.h +coverage.o: $(hdrdir)/ruby/internal/attr/cold.h +coverage.o: $(hdrdir)/ruby/internal/attr/const.h +coverage.o: $(hdrdir)/ruby/internal/attr/constexpr.h +coverage.o: $(hdrdir)/ruby/internal/attr/deprecated.h +coverage.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +coverage.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +coverage.o: $(hdrdir)/ruby/internal/attr/error.h +coverage.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +coverage.o: $(hdrdir)/ruby/internal/attr/forceinline.h +coverage.o: $(hdrdir)/ruby/internal/attr/format.h +coverage.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +coverage.o: $(hdrdir)/ruby/internal/attr/noalias.h +coverage.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +coverage.o: $(hdrdir)/ruby/internal/attr/noexcept.h +coverage.o: $(hdrdir)/ruby/internal/attr/noinline.h +coverage.o: $(hdrdir)/ruby/internal/attr/nonnull.h +coverage.o: $(hdrdir)/ruby/internal/attr/noreturn.h +coverage.o: $(hdrdir)/ruby/internal/attr/pure.h +coverage.o: $(hdrdir)/ruby/internal/attr/restrict.h +coverage.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +coverage.o: $(hdrdir)/ruby/internal/attr/warning.h +coverage.o: $(hdrdir)/ruby/internal/attr/weakref.h +coverage.o: $(hdrdir)/ruby/internal/cast.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +coverage.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +coverage.o: $(hdrdir)/ruby/internal/compiler_since.h +coverage.o: $(hdrdir)/ruby/internal/config.h +coverage.o: $(hdrdir)/ruby/internal/constant_p.h +coverage.o: $(hdrdir)/ruby/internal/core.h +coverage.o: $(hdrdir)/ruby/internal/core/rarray.h +coverage.o: $(hdrdir)/ruby/internal/core/rbasic.h +coverage.o: $(hdrdir)/ruby/internal/core/rbignum.h +coverage.o: $(hdrdir)/ruby/internal/core/rclass.h +coverage.o: $(hdrdir)/ruby/internal/core/rdata.h +coverage.o: $(hdrdir)/ruby/internal/core/rfile.h +coverage.o: $(hdrdir)/ruby/internal/core/rhash.h +coverage.o: $(hdrdir)/ruby/internal/core/robject.h +coverage.o: $(hdrdir)/ruby/internal/core/rregexp.h +coverage.o: $(hdrdir)/ruby/internal/core/rstring.h +coverage.o: $(hdrdir)/ruby/internal/core/rstruct.h +coverage.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +coverage.o: $(hdrdir)/ruby/internal/ctype.h +coverage.o: $(hdrdir)/ruby/internal/dllexport.h +coverage.o: $(hdrdir)/ruby/internal/dosish.h +coverage.o: $(hdrdir)/ruby/internal/error.h +coverage.o: $(hdrdir)/ruby/internal/eval.h +coverage.o: $(hdrdir)/ruby/internal/event.h +coverage.o: $(hdrdir)/ruby/internal/fl_type.h +coverage.o: $(hdrdir)/ruby/internal/gc.h +coverage.o: $(hdrdir)/ruby/internal/glob.h +coverage.o: $(hdrdir)/ruby/internal/globals.h +coverage.o: $(hdrdir)/ruby/internal/has/attribute.h +coverage.o: $(hdrdir)/ruby/internal/has/builtin.h +coverage.o: $(hdrdir)/ruby/internal/has/c_attribute.h +coverage.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +coverage.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +coverage.o: $(hdrdir)/ruby/internal/has/extension.h +coverage.o: $(hdrdir)/ruby/internal/has/feature.h +coverage.o: $(hdrdir)/ruby/internal/has/warning.h +coverage.o: $(hdrdir)/ruby/internal/intern/array.h +coverage.o: $(hdrdir)/ruby/internal/intern/bignum.h +coverage.o: $(hdrdir)/ruby/internal/intern/class.h +coverage.o: $(hdrdir)/ruby/internal/intern/compar.h +coverage.o: $(hdrdir)/ruby/internal/intern/complex.h +coverage.o: $(hdrdir)/ruby/internal/intern/cont.h +coverage.o: $(hdrdir)/ruby/internal/intern/dir.h +coverage.o: $(hdrdir)/ruby/internal/intern/enum.h +coverage.o: $(hdrdir)/ruby/internal/intern/enumerator.h +coverage.o: $(hdrdir)/ruby/internal/intern/error.h +coverage.o: $(hdrdir)/ruby/internal/intern/eval.h +coverage.o: $(hdrdir)/ruby/internal/intern/file.h +coverage.o: $(hdrdir)/ruby/internal/intern/gc.h +coverage.o: $(hdrdir)/ruby/internal/intern/hash.h +coverage.o: $(hdrdir)/ruby/internal/intern/io.h +coverage.o: $(hdrdir)/ruby/internal/intern/load.h +coverage.o: $(hdrdir)/ruby/internal/intern/marshal.h +coverage.o: $(hdrdir)/ruby/internal/intern/numeric.h +coverage.o: $(hdrdir)/ruby/internal/intern/object.h +coverage.o: $(hdrdir)/ruby/internal/intern/parse.h +coverage.o: $(hdrdir)/ruby/internal/intern/proc.h +coverage.o: $(hdrdir)/ruby/internal/intern/process.h +coverage.o: $(hdrdir)/ruby/internal/intern/random.h +coverage.o: $(hdrdir)/ruby/internal/intern/range.h +coverage.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +coverage.o: $(hdrdir)/ruby/internal/intern/sprintf.h +coverage.o: $(hdrdir)/ruby/internal/intern/string.h +coverage.o: $(hdrdir)/ruby/internal/intern/struct.h +coverage.o: $(hdrdir)/ruby/internal/intern/thread.h +coverage.o: $(hdrdir)/ruby/internal/intern/time.h +coverage.o: $(hdrdir)/ruby/internal/intern/variable.h +coverage.o: $(hdrdir)/ruby/internal/intern/vm.h +coverage.o: $(hdrdir)/ruby/internal/interpreter.h +coverage.o: $(hdrdir)/ruby/internal/iterator.h +coverage.o: $(hdrdir)/ruby/internal/memory.h +coverage.o: $(hdrdir)/ruby/internal/method.h +coverage.o: $(hdrdir)/ruby/internal/module.h +coverage.o: $(hdrdir)/ruby/internal/newobj.h +coverage.o: $(hdrdir)/ruby/internal/rgengc.h +coverage.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +coverage.o: $(hdrdir)/ruby/internal/value.h +coverage.o: $(hdrdir)/ruby/internal/value_type.h +coverage.o: $(hdrdir)/ruby/internal/variable.h +coverage.o: $(hdrdir)/ruby/internal/warning_push.h +coverage.o: $(hdrdir)/ruby/internal/xmalloc.h coverage.o: $(hdrdir)/ruby/missing.h coverage.o: $(hdrdir)/ruby/ruby.h coverage.o: $(hdrdir)/ruby/st.h @@ -15,8 +164,20 @@ coverage.o: $(top_srcdir)/ccan/check_type/check_type.h coverage.o: $(top_srcdir)/ccan/container_of/container_of.h coverage.o: $(top_srcdir)/ccan/list/list.h coverage.o: $(top_srcdir)/ccan/str/str.h +coverage.o: $(top_srcdir)/darray.h coverage.o: $(top_srcdir)/gc.h coverage.o: $(top_srcdir)/internal.h +coverage.o: $(top_srcdir)/internal/array.h +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/sanitizers.h +coverage.o: $(top_srcdir)/internal/serial.h +coverage.o: $(top_srcdir)/internal/static_assert.h +coverage.o: $(top_srcdir)/internal/thread.h +coverage.o: $(top_srcdir)/internal/vm.h +coverage.o: $(top_srcdir)/internal/warnings.h coverage.o: $(top_srcdir)/method.h coverage.o: $(top_srcdir)/node.h coverage.o: $(top_srcdir)/ruby_assert.h diff --git a/ruby/ext/date/date.gemspec b/ruby/ext/date/date.gemspec index bd323b7a0..cf0769697 100644 --- a/ruby/ext/date/date.gemspec +++ b/ruby/ext/date/date.gemspec @@ -1,7 +1,12 @@ # frozen_string_literal: true + +version = File.foreach(File.expand_path("../lib/date.rb", __FILE__)).find do |line| + /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1 +end + Gem::Specification.new do |s| s.name = "date" - s.version = '3.0.0' + 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." @@ -17,5 +22,5 @@ Gem::Specification.new do |s| s.authors = ["Tadayoshi Funaba"] s.email = [nil] s.homepage = "https://github.com/ruby/date" - s.license = "BSD-2-Clause" + s.licenses = ["Ruby", "BSD-2-Clause"] end diff --git a/ruby/ext/date/date_core.c b/ruby/ext/date/date_core.c index ccac90a32..f6579b81e 100644 --- a/ruby/ext/date/date_core.c +++ b/ruby/ext/date/date_core.c @@ -11,6 +11,7 @@ #include #endif +#undef NDEBUG #define NDEBUG #include @@ -52,6 +53,8 @@ static double positive_inf, negative_inf; #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__)) + static VALUE date_initialize(int argc, VALUE *argv, VALUE self); static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self); @@ -2970,11 +2973,15 @@ d_lite_memsize(const void *ptr) return complex_dat_p(dat) ? sizeof(struct ComplexDateData) : sizeof(struct SimpleDateData); } +#ifndef HAVE_RB_EXT_RACTOR_SAFE +# define RUBY_TYPED_FROZEN_SHAREABLE 0 +#endif + static const rb_data_type_t d_lite_type = { "Date", {d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,}, 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED, + RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE, }; inline static VALUE @@ -3766,89 +3773,89 @@ rt_complete_frags(VALUE klass, VALUE hash) VALUE k, a, d; if (NIL_P(tab)) { - tab = rb_ary_new3(11, - rb_ary_new3(2, + tab = f_frozen_ary(11, + f_frozen_ary(2, sym("time"), - rb_ary_new3(3, + f_frozen_ary(3, sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, Qnil, - rb_ary_new3(1, + f_frozen_ary(1, sym("jd"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("ordinal"), - rb_ary_new3(5, + f_frozen_ary(5, sym("year"), sym("yday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("civil"), - rb_ary_new3(6, + f_frozen_ary(6, sym("year"), sym("mon"), sym("mday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("commercial"), - rb_ary_new3(6, + f_frozen_ary(6, sym("cwyear"), sym("cweek"), sym("cwday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("wday"), - rb_ary_new3(4, + f_frozen_ary(4, sym("wday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("wnum0"), - rb_ary_new3(6, + f_frozen_ary(6, sym("year"), sym("wnum0"), sym("wday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, sym("wnum1"), - rb_ary_new3(6, + f_frozen_ary(6, sym("year"), sym("wnum1"), sym("wday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, Qnil, - rb_ary_new3(6, + f_frozen_ary(6, sym("cwyear"), sym("cweek"), sym("wday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, Qnil, - rb_ary_new3(6, + f_frozen_ary(6, sym("year"), sym("wnum0"), sym("cwday"), sym("hour"), sym("min"), sym("sec"))), - rb_ary_new3(2, + f_frozen_ary(2, Qnil, - rb_ary_new3(6, + f_frozen_ary(6, sym("year"), sym("wnum1"), sym("cwday"), @@ -4321,12 +4328,40 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) VALUE date__parse(VALUE str, VALUE comp); +static size_t +get_limit(VALUE opt) +{ + if (!NIL_P(opt)) { + VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit"))); + if (NIL_P(limit)) return SIZE_MAX; + return NUM2SIZET(limit); + } + return 128; +} + +static void +check_limit(VALUE str, VALUE opt) +{ + if (NIL_P(str)) return; + if (SYMBOL_P(str)) str = rb_sym2str(str); + + StringValue(str); + size_t slen = RSTRING_LEN(str); + size_t limit = get_limit(opt); + if (slen > limit) { + rb_raise(rb_eArgError, + "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit); + } +} + static VALUE date_s__parse_internal(int argc, VALUE *argv, VALUE klass) { - VALUE vstr, vcomp, hash; + VALUE vstr, vcomp, hash, opt; - rb_scan_args(argc, argv, "11", &vstr, &vcomp); + rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt); + if (!NIL_P(opt)) argc--; + check_limit(vstr, opt); StringValue(vstr); if (!rb_enc_str_asciicompat_p(vstr)) rb_raise(rb_eArgError, @@ -4341,17 +4376,25 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date._parse(string[, comp=true]) -> hash + * Date._parse(string[, comp=true], limit: 128) -> hash * * Parses the given representation of date and time, and returns a - * hash of parsed elements. This method does not function as a - * validator. + * hash of parsed elements. + * + * This method *does not* function as a validator. If the input + * string does not match valid formats strictly, you may get a cryptic + * result. Should consider to use `Date._strptime` or + * `DateTime._strptime` instead of this method as possible. * * If the optional second argument is true and the detected year is in * the range "00" to "99", considers the year a 2-digit form and makes * it full. * * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3} + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s__parse(int argc, VALUE *argv, VALUE klass) @@ -4361,10 +4404,15 @@ date_s__parse(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date + * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128) -> date * * Parses the given representation of date and time, and creates a - * date object. This method does not function as a validator. + * date object. + * + * This method *does not* function as a validator. If the input + * string does not match valid formats strictly, you may get a cryptic + * result. Should consider to use `Date.strptime` instead of this + * method as possible. * * If the optional second argument is true and the detected year is in * the range "00" to "99", considers the year a 2-digit form and makes @@ -4373,13 +4421,18 @@ date_s__parse(int argc, VALUE *argv, VALUE klass) * Date.parse('2001-02-03') #=> # * Date.parse('20010203') #=> # * Date.parse('3rd Feb 2001') #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_parse(int argc, VALUE *argv, VALUE klass) { - VALUE str, comp, sg; + VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03", &str, &comp, &sg); + rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -4391,11 +4444,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass) } { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); + int argc2 = 2; + VALUE argv2[3]; + argv2[0] = str; + argv2[1] = comp; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__parse(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } @@ -4409,19 +4463,28 @@ VALUE date__jisx0301(VALUE); /* * call-seq: - * Date._iso8601(string) -> hash + * Date._iso8601(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__iso8601(VALUE klass, VALUE str) +date_s__iso8601(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__iso8601(str); } /* * call-seq: - * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some typical ISO 8601 formats. @@ -4429,13 +4492,18 @@ date_s__iso8601(VALUE klass, VALUE str) * Date.iso8601('2001-02-03') #=> # * Date.iso8601('20010203') #=> # * Date.iso8601('2001-W05-6') #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_iso8601(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -4445,38 +4513,56 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__iso8601(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__iso8601(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._rfc3339(string) -> hash + * Date._rfc3339(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__rfc3339(VALUE klass, VALUE str) +date_s__rfc3339(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__rfc3339(str); } /* * call-seq: - * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date + * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some typical RFC 3339 formats. * * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_rfc3339(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -4486,38 +4572,56 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__rfc3339(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__rfc3339(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._xmlschema(string) -> hash + * Date._xmlschema(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__xmlschema(VALUE klass, VALUE str) +date_s__xmlschema(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__xmlschema(str); } /* * call-seq: - * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some typical XML Schema formats. * * Date.xmlschema('2001-02-03') #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_xmlschema(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -4527,41 +4631,58 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__xmlschema(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__xmlschema(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._rfc2822(string) -> hash - * Date._rfc822(string) -> hash + * Date._rfc2822(string, limit: 128) -> hash + * Date._rfc822(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__rfc2822(VALUE klass, VALUE str) +date_s__rfc2822(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__rfc2822(str); } /* * call-seq: - * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date - * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date + * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date + * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some typical RFC 2822 formats. * * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_rfc2822(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: @@ -4571,39 +4692,56 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__rfc2822(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__rfc2822(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._httpdate(string) -> hash + * Date._httpdate(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__httpdate(VALUE klass, VALUE str) +date_s__httpdate(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__httpdate(str); } /* * call-seq: - * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date + * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some RFC 2616 format. * * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_httpdate(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: @@ -4613,26 +4751,39 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__httpdate(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__httpdate(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._jisx0301(string) -> hash + * Date._jisx0301(string, limit: 128) -> hash * * Returns a hash of parsed elements. + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE -date_s__jisx0301(VALUE klass, VALUE str) +date_s__jisx0301(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + check_limit(str, opt); + return date__jisx0301(str); } /* * call-seq: - * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date * * Creates a new Date object by parsing from a string according to * some typical JIS X 0301 formats. @@ -4642,13 +4793,18 @@ date_s__jisx0301(VALUE klass, VALUE str) * For no-era year, legacy format, Heisei is assumed. * * Date.jisx0301('13.02.03') #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE date_s_jisx0301(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -4658,7 +4814,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__jisx0301(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + VALUE hash = date_s__jisx0301(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } @@ -6884,7 +7044,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self, * %c - date and time (%a %b %e %T %Y) * %D - Date (%m/%d/%y) * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) + * %v - VMS date (%e-%^b-%Y) * %x - Same as %D * %X - Same as %T * %r - 12-hour time (%I:%M:%S %p) @@ -7201,11 +7361,14 @@ d_lite_marshal_load(VALUE self, VALUE a) if (simple_dat_p(dat)) { if (df || !f_zero_p(sf) || of) { - rb_raise(rb_eArgError, - "cannot load complex into simple"); + /* loading a fractional date; promote to complex */ + dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData)); + RTYPEDDATA(self)->data = dat; + goto complex_data; } set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD); } else { + complex_data: set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg, 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF); @@ -7778,7 +7941,7 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass) #ifdef HAVE_STRUCT_TM_TM_GMTOFF of = tm.tm_gmtoff; #elif defined(HAVE_TIMEZONE) -#ifdef HAVE_ALTZONE +#if defined(HAVE_ALTZONE) && !defined(_AIX) of = (long)-((tm.tm_isdst > 0) ? altzone : timezone); #else of = (long)-timezone; @@ -7994,10 +8157,15 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime + * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime * * Parses the given representation of date and time, and creates a - * DateTime object. This method does not function as a validator. + * DateTime object. + * + * This method *does not* function as a validator. If the input + * string does not match valid formats strictly, you may get a cryptic + * result. Should consider to use `DateTime.strptime` instead of this + * method as possible. * * If the optional second argument is true and the detected year is in * the range "00" to "99", makes it full. @@ -8008,13 +8176,18 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) * #=> # * DateTime.parse('3rd Feb 2001 04:05:06 PM') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_parse(int argc, VALUE *argv, VALUE klass) { - VALUE str, comp, sg; + VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03", &str, &comp, &sg); + rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8026,18 +8199,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) } { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); + int argc2 = 2; + VALUE argv2[3]; + argv2[0] = str; + argv2[1] = comp; + argv2[2] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__parse(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical ISO 8601 formats. @@ -8048,13 +8223,18 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) * #=> # * DateTime.iso8601('2001-W05-6T04:05:06+07:00') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8064,27 +8244,37 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__iso8601(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2--; + VALUE hash = date_s__iso8601(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical RFC 3339 formats. * * DateTime.rfc3339('2001-02-03T04:05:06+07:00') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8094,27 +8284,37 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__rfc3339(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__rfc3339(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical XML Schema formats. * * DateTime.xmlschema('2001-02-03T04:05:06+07:00') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8124,28 +8324,38 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__xmlschema(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__xmlschema(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime - * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime + * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime + * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical RFC 2822 formats. * * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8155,7 +8365,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__rfc2822(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__rfc2822(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } @@ -8169,13 +8384,18 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) * * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8185,14 +8405,19 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__httpdate(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__httpdate(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical JIS X 0301 formats. @@ -8204,13 +8429,18 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) * * DateTime.jisx0301('13.02.03T04:05:06+07:00') * #=> # + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing `limit: nil`, but note that + * it may take a long time to parse. */ static VALUE datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + if (!NIL_P(opt)) argc--; switch (argc) { case 0: @@ -8220,7 +8450,12 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) } { - VALUE hash = date_s__jisx0301(klass, str); + int argc2 = 1; + VALUE argv2[2]; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + VALUE hash = date_s__jisx0301(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } @@ -8356,7 +8591,7 @@ dt_lite_to_s(VALUE self) * %c - date and time (%a %b %e %T %Y) * %D - Date (%m/%d/%y) * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) + * %v - VMS date (%e-%^b-%Y) * %x - Same as %D * %X - Same as %T * %r - 12-hour time (%I:%M:%S %p) @@ -9098,13 +9333,13 @@ d_lite_zero(VALUE x) void Init_date_core(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - id_cmp = rb_intern("<=>"); - id_le_p = rb_intern("<="); - id_ge_p = rb_intern(">="); - id_eqeq_p = rb_intern("=="); + #ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); + #endif + id_cmp = rb_intern_const("<=>"); + id_le_p = rb_intern_const("<="); + id_ge_p = rb_intern_const(">="); + id_eqeq_p = rb_intern_const("=="); half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2)); @@ -9379,19 +9614,19 @@ Init_date_core(void) rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1); rb_define_singleton_method(cDate, "_parse", date_s__parse, -1); rb_define_singleton_method(cDate, "parse", date_s_parse, -1); - rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1); + rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1); rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1); - rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1); + rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1); rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1); - rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1); + rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1); rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1); - rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1); - rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1); + rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1); + rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1); rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1); rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1); - rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1); + rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1); rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1); - rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1); + rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1); rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1); rb_define_method(cDate, "initialize", date_initialize, -1); @@ -9511,6 +9746,8 @@ Init_date_core(void) * A subclass of Date that easily handles date, hour, minute, second, * and offset. * + * DateTime class is considered deprecated. Use Time class. + * * DateTime does not consider any leap seconds, does not track * any summer time rules. * @@ -9571,18 +9808,18 @@ Init_date_core(void) * === When should you use DateTime and when should you use Time? * * It's a common misconception that - * {William Shakespeare}[http://en.wikipedia.org/wiki/William_Shakespeare] + * {William Shakespeare}[https://en.wikipedia.org/wiki/William_Shakespeare] * and - * {Miguel de Cervantes}[http://en.wikipedia.org/wiki/Miguel_de_Cervantes] + * {Miguel de Cervantes}[https://en.wikipedia.org/wiki/Miguel_de_Cervantes] * died on the same day in history - * so much so that UNESCO named April 23 as - * {World Book Day because of this fact}[http://en.wikipedia.org/wiki/World_Book_Day]. + * {World Book Day because of this fact}[https://en.wikipedia.org/wiki/World_Book_Day]. * However, because England hadn't yet adopted the - * {Gregorian Calendar Reform}[http://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform] - * (and wouldn't until {1752}[http://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750]) + * {Gregorian Calendar Reform}[https://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform] + * (and wouldn't until {1752}[https://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750]) * their deaths are actually 10 days apart. * Since Ruby's Time class implements a - * {proleptic Gregorian calendar}[http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar] + * {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar] * and has no concept of calendar reform there's no way * to express this with Time objects. This is where DateTime steps in: * @@ -9626,7 +9863,7 @@ Init_date_core(void) * #=> Fri, 04 May 1753 00:00:00 +0000 * * As you can see, if we're accurately tracking the number of - * {solar years}[http://en.wikipedia.org/wiki/Tropical_year] + * {solar years}[https://en.wikipedia.org/wiki/Tropical_year] * since Shakespeare's birthday then the correct anniversary date * would be the 4th May and not the 23rd April. * @@ -9638,10 +9875,10 @@ Init_date_core(void) * making the same mistakes as UNESCO. If you also have to deal * with timezones then best of luck - just bear in mind that * you'll probably be dealing with - * {local solar times}[http://en.wikipedia.org/wiki/Solar_time], + * {local solar times}[https://en.wikipedia.org/wiki/Solar_time], * since it wasn't until the 19th century that the introduction * of the railways necessitated the need for - * {Standard Time}[http://en.wikipedia.org/wiki/Standard_time#Great_Britain] + * {Standard Time}[https://en.wikipedia.org/wiki/Standard_time#Great_Britain] * and eventually timezones. */ diff --git a/ruby/ext/date/date_parse.c b/ruby/ext/date/date_parse.c index 519f29cbc..5fa036ed7 100644 --- a/ruby/ext/date/date_parse.c +++ b/ruby/ext/date/date_parse.c @@ -70,7 +70,7 @@ static size_t digit_span(const char *s, const char *e) { size_t i = 0; - while (s + i < e && isdigit(s[i])) i++; + while (s + i < e && isdigit((unsigned char)s[i])) i++; return i; } @@ -110,7 +110,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) s = RSTRING_PTR(y); ep = RSTRING_END(y); - while (s < ep && !issign(*s) && !isdigit(*s)) + while (s < ep && !issign(*s) && !isdigit((unsigned char)*s)) s++; if (s >= ep) goto no_date; bp = s; @@ -162,7 +162,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) s = RSTRING_PTR(y); ep = RSTRING_END(y); - while (s < ep && !issign(*s) && !isdigit(*s)) + while (s < ep && !issign(*s) && !isdigit((unsigned char)*s)) s++; if (s >= ep) goto no_year; bp = s; @@ -199,7 +199,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) s = RSTRING_PTR(m); ep = RSTRING_END(m); - while (s < ep && !isdigit(*s)) + while (s < ep && !isdigit((unsigned char)*s)) s++; if (s >= ep) goto no_month; bp = s; @@ -225,7 +225,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) s = RSTRING_PTR(d); ep = RSTRING_END(d); - while (s < ep && !isdigit(*s)) + while (s < ep && !isdigit((unsigned char)*s)) s++; if (s >= ep) goto no_mday; bp = s; @@ -276,6 +276,7 @@ regcomp(const char *source, long len, int opt) VALUE pat; pat = rb_reg_new(source, len, opt); + rb_obj_freeze(pat); rb_gc_register_mark_object(pat); return pat; } @@ -364,9 +365,9 @@ static int str_end_with_word(const char *s, long l, const char *w) { int n = (int)strlen(w); - if (l <= n || !isspace(s[l - n - 1])) return 0; + if (l <= n || !isspace((unsigned char)s[l - n - 1])) return 0; if (strncasecmp(&s[l - n], w, n)) return 0; - do ++n; while (l > n && isspace(s[l - n - 1])); + do ++n; while (l > n && isspace((unsigned char)s[l - n - 1])); return n; } @@ -376,7 +377,7 @@ shrunk_size(const char *s, long l) long i, ni; int sp = 0; for (i = ni = 0; i < l; ++i) { - if (!isspace(s[i])) { + if (!isspace((unsigned char)s[i])) { if (sp) ni++; sp = 0; ni++; @@ -394,7 +395,7 @@ shrink_space(char *d, const char *s, long l) long i, ni; int sp = 0; for (i = ni = 0; i < l; ++i) { - if (!isspace(s[i])) { + if (!isspace((unsigned char)s[i])) { if (sp) d[ni++] = ' '; sp = 0; d[ni++] = s[i]; @@ -754,8 +755,8 @@ check_year_width(VALUE y) l = RSTRING_LEN(y); if (l < 2) return 0; s = RSTRING_PTR(y); - if (!isdigit(s[1])) return 0; - return (l == 2 || !isdigit(s[2])); + if (!isdigit((unsigned char)s[1])) return 0; + return (l == 2 || !isdigit((unsigned char)s[2])); } static int diff --git a/ruby/ext/date/date_strftime.c b/ruby/ext/date/date_strftime.c index 9d8167b61..d7f28989d 100644 --- a/ruby/ext/date/date_strftime.c +++ b/ruby/ext/date/date_strftime.c @@ -393,7 +393,7 @@ date_strftime_with_tmx(char *s, const size_t maxsize, const char *format, continue; case 'v': - STRFTIME("%e-%b-%Y"); + STRFTIME("%e-%^b-%Y"); continue; case 'w': /* weekday, Sunday == 0, 0 - 6 */ diff --git a/ruby/ext/date/date_strptime.c b/ruby/ext/date/date_strptime.c index 26d9fd11b..7b06a3147 100644 --- a/ruby/ext/date/date_strptime.c +++ b/ruby/ext/date/date_strptime.c @@ -581,6 +581,7 @@ date__strptime_internal(const char *str, size_t slen, if (NIL_P(pat)) { pat = rb_reg_new(pat_source, sizeof pat_source - 1, ONIG_OPTION_IGNORECASE); + rb_obj_freeze(pat); rb_gc_register_mark_object(pat); } diff --git a/ruby/ext/date/depend b/ruby/ext/date/depend index 28847bef1..6841df724 100644 --- a/ruby/ext/date/depend +++ b/ruby/ext/date/depend @@ -4,9 +4,165 @@ date_core.o: $(arch_hdrdir)/ruby/config.h date_core.o: $(hdrdir)/ruby.h date_core.o: $(hdrdir)/ruby/assert.h date_core.o: $(hdrdir)/ruby/backward.h +date_core.o: $(hdrdir)/ruby/backward/2/assume.h +date_core.o: $(hdrdir)/ruby/backward/2/attributes.h +date_core.o: $(hdrdir)/ruby/backward/2/bool.h +date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_core.o: $(hdrdir)/ruby/backward/2/limits.h +date_core.o: $(hdrdir)/ruby/backward/2/long_long.h +date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h date_core.o: $(hdrdir)/ruby/defines.h date_core.o: $(hdrdir)/ruby/encoding.h date_core.o: $(hdrdir)/ruby/intern.h +date_core.o: $(hdrdir)/ruby/internal/anyargs.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/char.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/double.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/int.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/long.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/short.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +date_core.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +date_core.o: $(hdrdir)/ruby/internal/assume.h +date_core.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +date_core.o: $(hdrdir)/ruby/internal/attr/artificial.h +date_core.o: $(hdrdir)/ruby/internal/attr/cold.h +date_core.o: $(hdrdir)/ruby/internal/attr/const.h +date_core.o: $(hdrdir)/ruby/internal/attr/constexpr.h +date_core.o: $(hdrdir)/ruby/internal/attr/deprecated.h +date_core.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +date_core.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +date_core.o: $(hdrdir)/ruby/internal/attr/error.h +date_core.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +date_core.o: $(hdrdir)/ruby/internal/attr/forceinline.h +date_core.o: $(hdrdir)/ruby/internal/attr/format.h +date_core.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +date_core.o: $(hdrdir)/ruby/internal/attr/noalias.h +date_core.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +date_core.o: $(hdrdir)/ruby/internal/attr/noexcept.h +date_core.o: $(hdrdir)/ruby/internal/attr/noinline.h +date_core.o: $(hdrdir)/ruby/internal/attr/nonnull.h +date_core.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_core.o: $(hdrdir)/ruby/internal/attr/pure.h +date_core.o: $(hdrdir)/ruby/internal/attr/restrict.h +date_core.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +date_core.o: $(hdrdir)/ruby/internal/attr/warning.h +date_core.o: $(hdrdir)/ruby/internal/attr/weakref.h +date_core.o: $(hdrdir)/ruby/internal/cast.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +date_core.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +date_core.o: $(hdrdir)/ruby/internal/compiler_since.h +date_core.o: $(hdrdir)/ruby/internal/config.h +date_core.o: $(hdrdir)/ruby/internal/constant_p.h +date_core.o: $(hdrdir)/ruby/internal/core.h +date_core.o: $(hdrdir)/ruby/internal/core/rarray.h +date_core.o: $(hdrdir)/ruby/internal/core/rbasic.h +date_core.o: $(hdrdir)/ruby/internal/core/rbignum.h +date_core.o: $(hdrdir)/ruby/internal/core/rclass.h +date_core.o: $(hdrdir)/ruby/internal/core/rdata.h +date_core.o: $(hdrdir)/ruby/internal/core/rfile.h +date_core.o: $(hdrdir)/ruby/internal/core/rhash.h +date_core.o: $(hdrdir)/ruby/internal/core/robject.h +date_core.o: $(hdrdir)/ruby/internal/core/rregexp.h +date_core.o: $(hdrdir)/ruby/internal/core/rstring.h +date_core.o: $(hdrdir)/ruby/internal/core/rstruct.h +date_core.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +date_core.o: $(hdrdir)/ruby/internal/ctype.h +date_core.o: $(hdrdir)/ruby/internal/dllexport.h +date_core.o: $(hdrdir)/ruby/internal/dosish.h +date_core.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_core.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_core.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_core.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_core.o: $(hdrdir)/ruby/internal/encoding/re.h +date_core.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_core.o: $(hdrdir)/ruby/internal/encoding/string.h +date_core.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_core.o: $(hdrdir)/ruby/internal/encoding/transcode.h +date_core.o: $(hdrdir)/ruby/internal/error.h +date_core.o: $(hdrdir)/ruby/internal/eval.h +date_core.o: $(hdrdir)/ruby/internal/event.h +date_core.o: $(hdrdir)/ruby/internal/fl_type.h +date_core.o: $(hdrdir)/ruby/internal/gc.h +date_core.o: $(hdrdir)/ruby/internal/glob.h +date_core.o: $(hdrdir)/ruby/internal/globals.h +date_core.o: $(hdrdir)/ruby/internal/has/attribute.h +date_core.o: $(hdrdir)/ruby/internal/has/builtin.h +date_core.o: $(hdrdir)/ruby/internal/has/c_attribute.h +date_core.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +date_core.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +date_core.o: $(hdrdir)/ruby/internal/has/extension.h +date_core.o: $(hdrdir)/ruby/internal/has/feature.h +date_core.o: $(hdrdir)/ruby/internal/has/warning.h +date_core.o: $(hdrdir)/ruby/internal/intern/array.h +date_core.o: $(hdrdir)/ruby/internal/intern/bignum.h +date_core.o: $(hdrdir)/ruby/internal/intern/class.h +date_core.o: $(hdrdir)/ruby/internal/intern/compar.h +date_core.o: $(hdrdir)/ruby/internal/intern/complex.h +date_core.o: $(hdrdir)/ruby/internal/intern/cont.h +date_core.o: $(hdrdir)/ruby/internal/intern/dir.h +date_core.o: $(hdrdir)/ruby/internal/intern/enum.h +date_core.o: $(hdrdir)/ruby/internal/intern/enumerator.h +date_core.o: $(hdrdir)/ruby/internal/intern/error.h +date_core.o: $(hdrdir)/ruby/internal/intern/eval.h +date_core.o: $(hdrdir)/ruby/internal/intern/file.h +date_core.o: $(hdrdir)/ruby/internal/intern/gc.h +date_core.o: $(hdrdir)/ruby/internal/intern/hash.h +date_core.o: $(hdrdir)/ruby/internal/intern/io.h +date_core.o: $(hdrdir)/ruby/internal/intern/load.h +date_core.o: $(hdrdir)/ruby/internal/intern/marshal.h +date_core.o: $(hdrdir)/ruby/internal/intern/numeric.h +date_core.o: $(hdrdir)/ruby/internal/intern/object.h +date_core.o: $(hdrdir)/ruby/internal/intern/parse.h +date_core.o: $(hdrdir)/ruby/internal/intern/proc.h +date_core.o: $(hdrdir)/ruby/internal/intern/process.h +date_core.o: $(hdrdir)/ruby/internal/intern/random.h +date_core.o: $(hdrdir)/ruby/internal/intern/range.h +date_core.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h +date_core.o: $(hdrdir)/ruby/internal/intern/string.h +date_core.o: $(hdrdir)/ruby/internal/intern/struct.h +date_core.o: $(hdrdir)/ruby/internal/intern/thread.h +date_core.o: $(hdrdir)/ruby/internal/intern/time.h +date_core.o: $(hdrdir)/ruby/internal/intern/variable.h +date_core.o: $(hdrdir)/ruby/internal/intern/vm.h +date_core.o: $(hdrdir)/ruby/internal/interpreter.h +date_core.o: $(hdrdir)/ruby/internal/iterator.h +date_core.o: $(hdrdir)/ruby/internal/memory.h +date_core.o: $(hdrdir)/ruby/internal/method.h +date_core.o: $(hdrdir)/ruby/internal/module.h +date_core.o: $(hdrdir)/ruby/internal/newobj.h +date_core.o: $(hdrdir)/ruby/internal/rgengc.h +date_core.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +date_core.o: $(hdrdir)/ruby/internal/value.h +date_core.o: $(hdrdir)/ruby/internal/value_type.h +date_core.o: $(hdrdir)/ruby/internal/variable.h +date_core.o: $(hdrdir)/ruby/internal/warning_push.h +date_core.o: $(hdrdir)/ruby/internal/xmalloc.h date_core.o: $(hdrdir)/ruby/missing.h date_core.o: $(hdrdir)/ruby/onigmo.h date_core.o: $(hdrdir)/ruby/oniguruma.h @@ -21,9 +177,166 @@ date_parse.o: $(arch_hdrdir)/ruby/config.h date_parse.o: $(hdrdir)/ruby.h date_parse.o: $(hdrdir)/ruby/assert.h date_parse.o: $(hdrdir)/ruby/backward.h +date_parse.o: $(hdrdir)/ruby/backward/2/assume.h +date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h +date_parse.o: $(hdrdir)/ruby/backward/2/bool.h +date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_parse.o: $(hdrdir)/ruby/backward/2/limits.h +date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h +date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h date_parse.o: $(hdrdir)/ruby/defines.h date_parse.o: $(hdrdir)/ruby/encoding.h date_parse.o: $(hdrdir)/ruby/intern.h +date_parse.o: $(hdrdir)/ruby/internal/anyargs.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/char.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/double.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/int.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/short.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +date_parse.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +date_parse.o: $(hdrdir)/ruby/internal/assume.h +date_parse.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +date_parse.o: $(hdrdir)/ruby/internal/attr/artificial.h +date_parse.o: $(hdrdir)/ruby/internal/attr/cold.h +date_parse.o: $(hdrdir)/ruby/internal/attr/const.h +date_parse.o: $(hdrdir)/ruby/internal/attr/constexpr.h +date_parse.o: $(hdrdir)/ruby/internal/attr/deprecated.h +date_parse.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +date_parse.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +date_parse.o: $(hdrdir)/ruby/internal/attr/error.h +date_parse.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +date_parse.o: $(hdrdir)/ruby/internal/attr/forceinline.h +date_parse.o: $(hdrdir)/ruby/internal/attr/format.h +date_parse.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +date_parse.o: $(hdrdir)/ruby/internal/attr/noalias.h +date_parse.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +date_parse.o: $(hdrdir)/ruby/internal/attr/noexcept.h +date_parse.o: $(hdrdir)/ruby/internal/attr/noinline.h +date_parse.o: $(hdrdir)/ruby/internal/attr/nonnull.h +date_parse.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_parse.o: $(hdrdir)/ruby/internal/attr/pure.h +date_parse.o: $(hdrdir)/ruby/internal/attr/restrict.h +date_parse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +date_parse.o: $(hdrdir)/ruby/internal/attr/warning.h +date_parse.o: $(hdrdir)/ruby/internal/attr/weakref.h +date_parse.o: $(hdrdir)/ruby/internal/cast.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +date_parse.o: $(hdrdir)/ruby/internal/compiler_since.h +date_parse.o: $(hdrdir)/ruby/internal/config.h +date_parse.o: $(hdrdir)/ruby/internal/constant_p.h +date_parse.o: $(hdrdir)/ruby/internal/core.h +date_parse.o: $(hdrdir)/ruby/internal/core/rarray.h +date_parse.o: $(hdrdir)/ruby/internal/core/rbasic.h +date_parse.o: $(hdrdir)/ruby/internal/core/rbignum.h +date_parse.o: $(hdrdir)/ruby/internal/core/rclass.h +date_parse.o: $(hdrdir)/ruby/internal/core/rdata.h +date_parse.o: $(hdrdir)/ruby/internal/core/rfile.h +date_parse.o: $(hdrdir)/ruby/internal/core/rhash.h +date_parse.o: $(hdrdir)/ruby/internal/core/rmatch.h +date_parse.o: $(hdrdir)/ruby/internal/core/robject.h +date_parse.o: $(hdrdir)/ruby/internal/core/rregexp.h +date_parse.o: $(hdrdir)/ruby/internal/core/rstring.h +date_parse.o: $(hdrdir)/ruby/internal/core/rstruct.h +date_parse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +date_parse.o: $(hdrdir)/ruby/internal/ctype.h +date_parse.o: $(hdrdir)/ruby/internal/dllexport.h +date_parse.o: $(hdrdir)/ruby/internal/dosish.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/re.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/string.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/transcode.h +date_parse.o: $(hdrdir)/ruby/internal/error.h +date_parse.o: $(hdrdir)/ruby/internal/eval.h +date_parse.o: $(hdrdir)/ruby/internal/event.h +date_parse.o: $(hdrdir)/ruby/internal/fl_type.h +date_parse.o: $(hdrdir)/ruby/internal/gc.h +date_parse.o: $(hdrdir)/ruby/internal/glob.h +date_parse.o: $(hdrdir)/ruby/internal/globals.h +date_parse.o: $(hdrdir)/ruby/internal/has/attribute.h +date_parse.o: $(hdrdir)/ruby/internal/has/builtin.h +date_parse.o: $(hdrdir)/ruby/internal/has/c_attribute.h +date_parse.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +date_parse.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +date_parse.o: $(hdrdir)/ruby/internal/has/extension.h +date_parse.o: $(hdrdir)/ruby/internal/has/feature.h +date_parse.o: $(hdrdir)/ruby/internal/has/warning.h +date_parse.o: $(hdrdir)/ruby/internal/intern/array.h +date_parse.o: $(hdrdir)/ruby/internal/intern/bignum.h +date_parse.o: $(hdrdir)/ruby/internal/intern/class.h +date_parse.o: $(hdrdir)/ruby/internal/intern/compar.h +date_parse.o: $(hdrdir)/ruby/internal/intern/complex.h +date_parse.o: $(hdrdir)/ruby/internal/intern/cont.h +date_parse.o: $(hdrdir)/ruby/internal/intern/dir.h +date_parse.o: $(hdrdir)/ruby/internal/intern/enum.h +date_parse.o: $(hdrdir)/ruby/internal/intern/enumerator.h +date_parse.o: $(hdrdir)/ruby/internal/intern/error.h +date_parse.o: $(hdrdir)/ruby/internal/intern/eval.h +date_parse.o: $(hdrdir)/ruby/internal/intern/file.h +date_parse.o: $(hdrdir)/ruby/internal/intern/gc.h +date_parse.o: $(hdrdir)/ruby/internal/intern/hash.h +date_parse.o: $(hdrdir)/ruby/internal/intern/io.h +date_parse.o: $(hdrdir)/ruby/internal/intern/load.h +date_parse.o: $(hdrdir)/ruby/internal/intern/marshal.h +date_parse.o: $(hdrdir)/ruby/internal/intern/numeric.h +date_parse.o: $(hdrdir)/ruby/internal/intern/object.h +date_parse.o: $(hdrdir)/ruby/internal/intern/parse.h +date_parse.o: $(hdrdir)/ruby/internal/intern/proc.h +date_parse.o: $(hdrdir)/ruby/internal/intern/process.h +date_parse.o: $(hdrdir)/ruby/internal/intern/random.h +date_parse.o: $(hdrdir)/ruby/internal/intern/range.h +date_parse.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h +date_parse.o: $(hdrdir)/ruby/internal/intern/string.h +date_parse.o: $(hdrdir)/ruby/internal/intern/struct.h +date_parse.o: $(hdrdir)/ruby/internal/intern/thread.h +date_parse.o: $(hdrdir)/ruby/internal/intern/time.h +date_parse.o: $(hdrdir)/ruby/internal/intern/variable.h +date_parse.o: $(hdrdir)/ruby/internal/intern/vm.h +date_parse.o: $(hdrdir)/ruby/internal/interpreter.h +date_parse.o: $(hdrdir)/ruby/internal/iterator.h +date_parse.o: $(hdrdir)/ruby/internal/memory.h +date_parse.o: $(hdrdir)/ruby/internal/method.h +date_parse.o: $(hdrdir)/ruby/internal/module.h +date_parse.o: $(hdrdir)/ruby/internal/newobj.h +date_parse.o: $(hdrdir)/ruby/internal/rgengc.h +date_parse.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +date_parse.o: $(hdrdir)/ruby/internal/value.h +date_parse.o: $(hdrdir)/ruby/internal/value_type.h +date_parse.o: $(hdrdir)/ruby/internal/variable.h +date_parse.o: $(hdrdir)/ruby/internal/warning_push.h +date_parse.o: $(hdrdir)/ruby/internal/xmalloc.h date_parse.o: $(hdrdir)/ruby/missing.h date_parse.o: $(hdrdir)/ruby/onigmo.h date_parse.o: $(hdrdir)/ruby/oniguruma.h @@ -39,8 +352,155 @@ date_strftime.o: $(RUBY_EXTCONF_H) date_strftime.o: $(arch_hdrdir)/ruby/config.h date_strftime.o: $(hdrdir)/ruby/assert.h date_strftime.o: $(hdrdir)/ruby/backward.h +date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h +date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h +date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h +date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h +date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h +date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h date_strftime.o: $(hdrdir)/ruby/defines.h date_strftime.o: $(hdrdir)/ruby/intern.h +date_strftime.o: $(hdrdir)/ruby/internal/anyargs.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/char.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/double.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/int.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/short.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +date_strftime.o: $(hdrdir)/ruby/internal/assume.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/artificial.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/cold.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/const.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/constexpr.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/deprecated.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/error.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/forceinline.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/format.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/noalias.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/noexcept.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/noinline.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/nonnull.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/pure.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/restrict.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/warning.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/weakref.h +date_strftime.o: $(hdrdir)/ruby/internal/cast.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +date_strftime.o: $(hdrdir)/ruby/internal/compiler_since.h +date_strftime.o: $(hdrdir)/ruby/internal/config.h +date_strftime.o: $(hdrdir)/ruby/internal/constant_p.h +date_strftime.o: $(hdrdir)/ruby/internal/core.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rarray.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rbasic.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rbignum.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rclass.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rdata.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rfile.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rhash.h +date_strftime.o: $(hdrdir)/ruby/internal/core/robject.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rregexp.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rstring.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rstruct.h +date_strftime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +date_strftime.o: $(hdrdir)/ruby/internal/ctype.h +date_strftime.o: $(hdrdir)/ruby/internal/dllexport.h +date_strftime.o: $(hdrdir)/ruby/internal/dosish.h +date_strftime.o: $(hdrdir)/ruby/internal/error.h +date_strftime.o: $(hdrdir)/ruby/internal/eval.h +date_strftime.o: $(hdrdir)/ruby/internal/event.h +date_strftime.o: $(hdrdir)/ruby/internal/fl_type.h +date_strftime.o: $(hdrdir)/ruby/internal/gc.h +date_strftime.o: $(hdrdir)/ruby/internal/glob.h +date_strftime.o: $(hdrdir)/ruby/internal/globals.h +date_strftime.o: $(hdrdir)/ruby/internal/has/attribute.h +date_strftime.o: $(hdrdir)/ruby/internal/has/builtin.h +date_strftime.o: $(hdrdir)/ruby/internal/has/c_attribute.h +date_strftime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +date_strftime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +date_strftime.o: $(hdrdir)/ruby/internal/has/extension.h +date_strftime.o: $(hdrdir)/ruby/internal/has/feature.h +date_strftime.o: $(hdrdir)/ruby/internal/has/warning.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/array.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/bignum.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/class.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/compar.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/complex.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/cont.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/dir.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/enum.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/enumerator.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/error.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/eval.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/file.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/gc.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/hash.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/io.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/load.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/marshal.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/numeric.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/object.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/parse.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/proc.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/process.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/random.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/range.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/struct.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/thread.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/time.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/variable.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/vm.h +date_strftime.o: $(hdrdir)/ruby/internal/interpreter.h +date_strftime.o: $(hdrdir)/ruby/internal/iterator.h +date_strftime.o: $(hdrdir)/ruby/internal/memory.h +date_strftime.o: $(hdrdir)/ruby/internal/method.h +date_strftime.o: $(hdrdir)/ruby/internal/module.h +date_strftime.o: $(hdrdir)/ruby/internal/newobj.h +date_strftime.o: $(hdrdir)/ruby/internal/rgengc.h +date_strftime.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +date_strftime.o: $(hdrdir)/ruby/internal/value.h +date_strftime.o: $(hdrdir)/ruby/internal/value_type.h +date_strftime.o: $(hdrdir)/ruby/internal/variable.h +date_strftime.o: $(hdrdir)/ruby/internal/warning_push.h +date_strftime.o: $(hdrdir)/ruby/internal/xmalloc.h date_strftime.o: $(hdrdir)/ruby/missing.h date_strftime.o: $(hdrdir)/ruby/ruby.h date_strftime.o: $(hdrdir)/ruby/st.h @@ -52,9 +512,166 @@ date_strptime.o: $(arch_hdrdir)/ruby/config.h date_strptime.o: $(hdrdir)/ruby.h date_strptime.o: $(hdrdir)/ruby/assert.h date_strptime.o: $(hdrdir)/ruby/backward.h +date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h +date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h +date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h +date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h +date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h +date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h date_strptime.o: $(hdrdir)/ruby/defines.h date_strptime.o: $(hdrdir)/ruby/encoding.h date_strptime.o: $(hdrdir)/ruby/intern.h +date_strptime.o: $(hdrdir)/ruby/internal/anyargs.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/char.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/double.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/int.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/short.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +date_strptime.o: $(hdrdir)/ruby/internal/assume.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/artificial.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/cold.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/const.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/constexpr.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/deprecated.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/error.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/forceinline.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/format.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/noalias.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/noexcept.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/noinline.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/nonnull.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/pure.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/restrict.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/warning.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/weakref.h +date_strptime.o: $(hdrdir)/ruby/internal/cast.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +date_strptime.o: $(hdrdir)/ruby/internal/compiler_since.h +date_strptime.o: $(hdrdir)/ruby/internal/config.h +date_strptime.o: $(hdrdir)/ruby/internal/constant_p.h +date_strptime.o: $(hdrdir)/ruby/internal/core.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rarray.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rbasic.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rbignum.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rclass.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rdata.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rfile.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rhash.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rmatch.h +date_strptime.o: $(hdrdir)/ruby/internal/core/robject.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rregexp.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rstring.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rstruct.h +date_strptime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +date_strptime.o: $(hdrdir)/ruby/internal/ctype.h +date_strptime.o: $(hdrdir)/ruby/internal/dllexport.h +date_strptime.o: $(hdrdir)/ruby/internal/dosish.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/re.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/string.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/transcode.h +date_strptime.o: $(hdrdir)/ruby/internal/error.h +date_strptime.o: $(hdrdir)/ruby/internal/eval.h +date_strptime.o: $(hdrdir)/ruby/internal/event.h +date_strptime.o: $(hdrdir)/ruby/internal/fl_type.h +date_strptime.o: $(hdrdir)/ruby/internal/gc.h +date_strptime.o: $(hdrdir)/ruby/internal/glob.h +date_strptime.o: $(hdrdir)/ruby/internal/globals.h +date_strptime.o: $(hdrdir)/ruby/internal/has/attribute.h +date_strptime.o: $(hdrdir)/ruby/internal/has/builtin.h +date_strptime.o: $(hdrdir)/ruby/internal/has/c_attribute.h +date_strptime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +date_strptime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +date_strptime.o: $(hdrdir)/ruby/internal/has/extension.h +date_strptime.o: $(hdrdir)/ruby/internal/has/feature.h +date_strptime.o: $(hdrdir)/ruby/internal/has/warning.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/array.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/bignum.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/class.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/compar.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/complex.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/cont.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/dir.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/enum.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/enumerator.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/error.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/eval.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/file.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/gc.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/hash.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/io.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/load.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/marshal.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/numeric.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/object.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/parse.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/proc.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/process.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/random.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/range.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/struct.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/thread.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/time.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/variable.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/vm.h +date_strptime.o: $(hdrdir)/ruby/internal/interpreter.h +date_strptime.o: $(hdrdir)/ruby/internal/iterator.h +date_strptime.o: $(hdrdir)/ruby/internal/memory.h +date_strptime.o: $(hdrdir)/ruby/internal/method.h +date_strptime.o: $(hdrdir)/ruby/internal/module.h +date_strptime.o: $(hdrdir)/ruby/internal/newobj.h +date_strptime.o: $(hdrdir)/ruby/internal/rgengc.h +date_strptime.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +date_strptime.o: $(hdrdir)/ruby/internal/value.h +date_strptime.o: $(hdrdir)/ruby/internal/value_type.h +date_strptime.o: $(hdrdir)/ruby/internal/variable.h +date_strptime.o: $(hdrdir)/ruby/internal/warning_push.h +date_strptime.o: $(hdrdir)/ruby/internal/xmalloc.h date_strptime.o: $(hdrdir)/ruby/missing.h date_strptime.o: $(hdrdir)/ruby/onigmo.h date_strptime.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/date/extconf.rb b/ruby/ext/date/extconf.rb index 8938df13b..f891de403 100644 --- a/ruby/ext/date/extconf.rb +++ b/ruby/ext/date/extconf.rb @@ -3,7 +3,9 @@ config_string("strict_warnflags") {|w| $warnflags += " #{w}"} -have_var("timezone", "time.h") -have_var("altzone", "time.h") +with_werror("", {:werror => true}) do |opt, | + have_var("timezone", "time.h", opt) + have_var("altzone", "time.h", opt) +end create_makefile('date_core') diff --git a/ruby/ext/date/lib/date.rb b/ruby/ext/date/lib/date.rb index b72b4157f..5770187a8 100644 --- a/ruby/ext/date/lib/date.rb +++ b/ruby/ext/date/lib/date.rb @@ -4,6 +4,7 @@ require 'date_core' class Date + VERSION = '3.2.2' # :nodoc: def infinite? false @@ -11,8 +12,6 @@ def infinite? class Infinity < Numeric # :nodoc: - include Comparable - def initialize(d=1) @d = d <=> 0 end def d() @d end @@ -32,6 +31,8 @@ def +@() self.class.new(+d) end def <=>(other) case other when Infinity; return d <=> other.d + when Float::INFINITY; return d <=> 1 + when -Float::INFINITY; return d <=> -1 when Numeric; return d else begin diff --git a/ruby/ext/date/prereq.mk b/ruby/ext/date/prereq.mk index fa371e0d4..cee768597 100644 --- a/ruby/ext/date/prereq.mk +++ b/ruby/ext/date/prereq.mk @@ -9,4 +9,11 @@ zonetab.h: zonetab.list .PHONY: update-zonetab update-zonetab: - $(RUBY) -C $(srcdir) update-abbr.rb + $(RUBY) -C $(srcdir) update-abbr + +.PHONY: update-nothing +update-nothing: + +update = nothing + +zonetab.list: update-$(update) diff --git a/ruby/ext/date/update-abbr b/ruby/ext/date/update-abbr index e5f6a78c8..7fe9734e6 100644 --- a/ruby/ext/date/update-abbr +++ b/ruby/ext/date/update-abbr @@ -2,7 +2,7 @@ require 'nokogiri' require 'open-uri' -doc = Nokogiri::HTML(URI.open('https://www.timeanddate.com/time/zones/')) +doc = Nokogiri::HTML(URI.open(ARGV[0] || 'https://www.timeanddate.com/time/zones/')) h = {} @@ -26,9 +26,26 @@ end h.delete_if{|_,v| !v} lines = File.readlines('zonetab.list') -lines.select{|l| l.include?(',')}. - map{|l| l.split(',', 2)[0]}. - each{|a| h.delete(a)} +lines.map! do |l| + if (sep = /^%%/ =~ l)...(sep = /^%%/ =~ l) and !sep + z, o = l.split(/,\s*/, 2) + o.strip! + if ho = h.delete(z) and ho != eval(o) + warn "offset of #{z}: #{o} -> #{ho}" + l = l.sub(/,\s*\K.*/) { + if o.include?("*") + o1, o2 = ho.abs.divmod(3600) + o1 = "#{o1}*3600" + o1 = "(#{o1}+#{o2})" if o2 != 0 + ho < 0 ? "-#{o1}" : o1 + else + ho.to_s + end + } + end + end + l +end lines.insert(-2, h.sort.map{|k,v| "#{k},#{v}\n"}) lines.flatten! diff --git a/ruby/ext/date/zonetab.h b/ruby/ext/date/zonetab.h index 379f78e1b..d82b011dc 100644 --- a/ruby/ext/date/zonetab.h +++ b/ruby/ext/date/zonetab.h @@ -846,7 +846,7 @@ zonetab (register const char *str, register size_t len) {gperf_offsetof(stringpool, 22), 3*3600}, {-1}, #line 101 "zonetab.list" - {gperf_offsetof(stringpool, 24),10*3600}, + {gperf_offsetof(stringpool, 24),-6*3600}, #line 217 "zonetab.list" {gperf_offsetof(stringpool, 25),-18000}, #line 19 "zonetab.list" @@ -875,7 +875,7 @@ zonetab (register const char *str, register size_t len) #line 79 "zonetab.list" {gperf_offsetof(stringpool, 38), 2*3600}, #line 65 "zonetab.list" - {gperf_offsetof(stringpool, 39),-10*3600}, + {gperf_offsetof(stringpool, 39),2*3600}, {-1}, #line 202 "zonetab.list" {gperf_offsetof(stringpool, 41),28800}, @@ -998,7 +998,7 @@ zonetab (register const char *str, register size_t len) #line 148 "zonetab.list" {gperf_offsetof(stringpool, 107), -25200}, #line 96 "zonetab.list" - {gperf_offsetof(stringpool, 108), 8*3600}, + {gperf_offsetof(stringpool, 108), (6*3600+1800)}, #line 42 "zonetab.list" {gperf_offsetof(stringpool, 109), -10*3600}, #line 31 "zonetab.list" @@ -1017,11 +1017,11 @@ zonetab (register const char *str, register size_t len) {gperf_offsetof(stringpool, 117), 1*3600}, {-1}, #line 95 "zonetab.list" - {gperf_offsetof(stringpool, 119), 7*3600}, + {gperf_offsetof(stringpool, 119), 2*3600}, #line 313 "zonetab.list" {gperf_offsetof(stringpool, 120),43200}, #line 55 "zonetab.list" - {gperf_offsetof(stringpool, 121), -(3*3600+1800)}, + {gperf_offsetof(stringpool, 121), -(2*3600+1800)}, #line 184 "zonetab.list" {gperf_offsetof(stringpool, 122),31500}, #line 204 "zonetab.list" @@ -1168,7 +1168,7 @@ zonetab (register const char *str, register size_t len) #line 299 "zonetab.list" {gperf_offsetof(stringpool, 206),50400}, #line 85 "zonetab.list" - {gperf_offsetof(stringpool, 207), 2*3600}, + {gperf_offsetof(stringpool, 207), -11*3600}, {-1}, #line 142 "zonetab.list" {gperf_offsetof(stringpool, 209), 19800}, @@ -1371,7 +1371,7 @@ zonetab (register const char *str, register size_t len) {gperf_offsetof(stringpool, 324), 8*3600}, {-1}, #line 50 "zonetab.list" - {gperf_offsetof(stringpool, 326), -(2*3600+1800)}, + {gperf_offsetof(stringpool, 326), -(1*3600+1800)}, #line 285 "zonetab.list" {gperf_offsetof(stringpool, 327),-10800}, {-1}, {-1}, diff --git a/ruby/ext/date/zonetab.list b/ruby/ext/date/zonetab.list index 0618546eb..d2f902d2d 100644 --- a/ruby/ext/date/zonetab.list +++ b/ruby/ext/date/zonetab.list @@ -47,12 +47,12 @@ utc, 0*3600 wet, 0*3600 at, -2*3600 brst,-2*3600 -ndt, -(2*3600+1800) +ndt, -(1*3600+1800) art, -3*3600 adt, -3*3600 brt, -3*3600 clst,-3*3600 -nst, -(3*3600+1800) +nst, -(2*3600+1800) ast, -4*3600 clt, -4*3600 akdt,-8*3600 @@ -62,7 +62,7 @@ hadt,-9*3600 hdt, -9*3600 yst, -9*3600 ahst,-10*3600 -cat,-10*3600 +cat,2*3600 hast,-10*3600 hst,-10*3600 nt, -11*3600 @@ -82,7 +82,7 @@ fst, 2*3600 mest, 2*3600 mesz, 2*3600 sast, 2*3600 -sst, 2*3600 +sst, -11*3600 bt, 3*3600 eat, 3*3600 eest, 3*3600 @@ -92,13 +92,13 @@ zp4, 4*3600 zp5, 5*3600 ist, (5*3600+1800) zp6, 6*3600 -wast, 7*3600 -cct, 8*3600 +wast, 2*3600 +cct, (6*3600+1800) sgt, 8*3600 wadt, 8*3600 jst, 9*3600 kst, 9*3600 -east,10*3600 +east,-6*3600 gst, 10*3600 eadt,11*3600 idle,12*3600 diff --git a/ruby/ext/dbm/dbm.c b/ruby/ext/dbm/dbm.c deleted file mode 100644 index bc1d52773..000000000 --- a/ruby/ext/dbm/dbm.c +++ /dev/null @@ -1,1156 +0,0 @@ -/************************************************ - - dbm.c - - - $Author$ - created at: Mon Jan 24 15:59:52 JST 1994 - - Copyright (C) 1995-2001 Yukihiro Matsumoto - -************************************************/ - -#include "ruby.h" - -#ifdef HAVE_CDEFS_H -# include -#endif -#ifdef HAVE_SYS_CDEFS_H -# include -#endif -#include DBM_HDR -#include -#include - -#define DSIZE_TYPE TYPEOF_DATUM_DSIZE -#if SIZEOF_DATUM_DSIZE > SIZEOF_INT -# define RSTRING_DSIZE(s) RSTRING_LEN(s) -# define TOO_LONG(n) ((void)(n),0) -#else -# define RSTRING_DSIZE(s) RSTRING_LENINT(s) -# define TOO_LONG(n) ((long)(+(DSIZE_TYPE)(n)) != (n)) -#endif - -static VALUE rb_cDBM, rb_eDBMError; - -#define RUBY_DBM_RW_BIT 0x20000000 - -struct dbmdata { - long di_size; - DBM *di_dbm; -}; - -NORETURN(static void closed_dbm(void)); - -static void -closed_dbm(void) -{ - rb_raise(rb_eDBMError, "closed DBM file"); -} - -#define GetDBM(obj, dbmp) do {\ - TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\ - if ((dbmp)->di_dbm == 0) closed_dbm();\ -} while (0) - -#define GetDBM2(obj, dbmp, dbm) do {\ - GetDBM((obj), (dbmp));\ - (dbm) = (dbmp)->di_dbm;\ -} while (0) - -static void -free_dbm(void *ptr) -{ - struct dbmdata *dbmp = ptr; - if (dbmp->di_dbm) - dbm_close(dbmp->di_dbm); - xfree(dbmp); -} - -static size_t -memsize_dbm(const void *ptr) -{ - const struct dbmdata *dbmp = ptr; - size_t size = sizeof(*dbmp); - if (dbmp->di_dbm) - size += DBM_SIZEOF_DBM; - return size; -} - -static const rb_data_type_t dbm_type = { - "dbm", - {0, free_dbm, memsize_dbm,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, -}; - -/* - * call-seq: - * dbm.close - * - * Closes the database. - */ -static VALUE -fdbm_close(VALUE obj) -{ - struct dbmdata *dbmp; - - GetDBM(obj, dbmp); - dbm_close(dbmp->di_dbm); - dbmp->di_dbm = 0; - - return Qnil; -} - -/* - * call-seq: - * dbm.closed? -> true or false - * - * Returns true if the database is closed, false otherwise. - */ -static VALUE -fdbm_closed(VALUE obj) -{ - struct dbmdata *dbmp; - - TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp); - if (dbmp->di_dbm == 0) - return Qtrue; - - return Qfalse; -} - -static VALUE -fdbm_alloc(VALUE klass) -{ - struct dbmdata *dbmp; - - return TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp); -} - -/* - * call-seq: - * DBM.new(filename[, mode[, flags]]) -> dbm - * - * Open a dbm database with the specified name, which can include a directory - * path. Any file extensions needed will be supplied automatically by the dbm - * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two - * physical files with extensions '.dir' and '.pag'. - * - * The mode should be an integer, as for Unix chmod. - * - * Flags should be one of READER, WRITER, WRCREAT or NEWDB. - */ -static VALUE -fdbm_initialize(int argc, VALUE *argv, VALUE obj) -{ - VALUE file, vmode, vflags; - DBM *dbm; - struct dbmdata *dbmp; - int mode, flags = 0; - - TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp); - if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { - mode = 0666; /* default value */ - } - else if (NIL_P(vmode)) { - mode = -1; /* return nil if DB not exist */ - } - else { - mode = NUM2INT(vmode); - } - - if (!NIL_P(vflags)) - flags = NUM2INT(vflags); - - FilePathValue(file); - - /* - * Note: - * gdbm 1.10 works with O_CLOEXEC. gdbm 1.9.1 silently ignore it. - */ -#ifndef O_CLOEXEC -# define O_CLOEXEC 0 -#endif - - if (flags & RUBY_DBM_RW_BIT) { - flags &= ~RUBY_DBM_RW_BIT; - dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode); - } - else { - dbm = 0; - if (mode >= 0) { - dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode); - } - if (!dbm) { - dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0); - } - if (!dbm) { - dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0); - } - } - - if (dbm) { - /* - * History of dbm_pagfno() and dbm_dirfno() in ndbm and its compatibles. - * (dbm_pagfno() and dbm_dirfno() is not standardized.) - * - * 1986: 4.3BSD provides ndbm. - * It provides dbm_pagfno() and dbm_dirfno() as macros. - * 1991: gdbm-1.5 provides them as functions. - * They returns a same descriptor. - * (Earlier releases may have the functions too.) - * 1991: Net/2 provides Berkeley DB. - * It doesn't provide dbm_pagfno() and dbm_dirfno(). - * 1992: 4.4BSD Alpha provides Berkeley DB with dbm_dirfno() as a function. - * dbm_pagfno() is a macro as DBM_PAGFNO_NOT_AVAILABLE. - * 1997: Berkeley DB 2.0 is released by Sleepycat Software, Inc. - * It defines dbm_pagfno() and dbm_dirfno() as macros. - * 2011: gdbm-1.9 creates a separate dir file. - * dbm_pagfno() and dbm_dirfno() returns different descriptors. - */ -#if defined(HAVE_DBM_PAGFNO) - rb_fd_fix_cloexec(dbm_pagfno(dbm)); -#endif -#if defined(HAVE_DBM_DIRFNO) - rb_fd_fix_cloexec(dbm_dirfno(dbm)); -#endif - -#if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC) - /* Disable Berkeley DB error messages such as: - * DB->put: attempt to modify a read-only database */ - ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL); -#endif - } - - if (!dbm) { - if (mode == -1) return Qnil; - rb_sys_fail_str(file); - } - - if (dbmp->di_dbm) - dbm_close(dbmp->di_dbm); - dbmp->di_dbm = dbm; - dbmp->di_size = -1; - - return obj; -} - -/* - * call-seq: - * DBM.open(filename[, mode[, flags]]) -> dbm - * DBM.open(filename[, mode[, flags]]) {|dbm| block} - * - * Open a dbm database and yields it if a block is given. See also - * DBM.new. - */ -static VALUE -fdbm_s_open(int argc, VALUE *argv, VALUE klass) -{ - VALUE obj = fdbm_alloc(klass); - - if (NIL_P(fdbm_initialize(argc, argv, obj))) { - return Qnil; - } - - if (rb_block_given_p()) { - return rb_ensure(rb_yield, obj, fdbm_close, obj); - } - - return obj; -} - -static VALUE -fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) -{ - datum key, value; - struct dbmdata *dbmp; - DBM *dbm; - long len; - - ExportStringValue(keystr); - len = RSTRING_LEN(keystr); - if (TOO_LONG(len)) goto not_found; - key.dptr = RSTRING_PTR(keystr); - key.dsize = (DSIZE_TYPE)len; - - GetDBM2(obj, dbmp, dbm); - value = dbm_fetch(dbm, key); - if (value.dptr == 0) { - not_found: - if (NIL_P(ifnone) && rb_block_given_p()) { - keystr = rb_str_dup(keystr); - return rb_yield(keystr); - } - return ifnone; - } - return rb_str_new(value.dptr, value.dsize); -} - -/* - * call-seq: - * dbm[key] -> string value or nil - * - * Return a value from the database by locating the key string - * provided. If the key is not found, returns nil. - */ -static VALUE -fdbm_aref(VALUE obj, VALUE keystr) -{ - return fdbm_fetch(obj, keystr, Qnil); -} - -/* - * call-seq: - * dbm.fetch(key[, ifnone]) -> value - * - * Return a value from the database by locating the key string - * provided. If the key is not found, returns +ifnone+. If +ifnone+ - * is not given, raises IndexError. - */ -static VALUE -fdbm_fetch_m(int argc, VALUE *argv, VALUE obj) -{ - VALUE keystr, valstr, ifnone; - - rb_scan_args(argc, argv, "11", &keystr, &ifnone); - valstr = fdbm_fetch(obj, keystr, ifnone); - if (argc == 1 && !rb_block_given_p() && NIL_P(valstr)) - rb_raise(rb_eIndexError, "key not found"); - - return valstr; -} - -/* - * call-seq: - * dbm.key(value) -> string - * - * Returns the key for the specified value. - */ -static VALUE -fdbm_key(VALUE obj, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - long len; - - ExportStringValue(valstr); - len = RSTRING_LEN(valstr); - if (TOO_LONG(len)) return Qnil; - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - if ((long)val.dsize == RSTRING_LEN(valstr) && - memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) { - return rb_str_new(key.dptr, key.dsize); - } - } - return Qnil; -} - -/* :nodoc: */ -static VALUE -fdbm_index(VALUE hash, VALUE value) -{ - rb_warn("DBM#index is deprecated; use DBM#key"); - return fdbm_key(hash, value); -} - -/* - * call-seq: - * dbm.select {|key, value| block} -> array - * - * Returns a new array consisting of the [key, value] pairs for which the code - * block returns true. - */ -static VALUE -fdbm_select(VALUE obj) -{ - VALUE new = rb_ary_new(); - datum key, val; - DBM *dbm; - struct dbmdata *dbmp; - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - VALUE assoc, v; - val = dbm_fetch(dbm, key); - assoc = rb_assoc_new(rb_str_new(key.dptr, key.dsize), - rb_str_new(val.dptr, val.dsize)); - v = rb_yield(assoc); - if (RTEST(v)) { - rb_ary_push(new, assoc); - } - GetDBM2(obj, dbmp, dbm); - } - - return new; -} - -/* - * call-seq: - * dbm.values_at(key, ...) -> Array - * - * Returns an array containing the values associated with the given keys. - */ -static VALUE -fdbm_values_at(int argc, VALUE *argv, VALUE obj) -{ - VALUE new = rb_ary_new2(argc); - int i; - - for (i=0; idi_size = -1; - rb_raise(rb_eDBMError, "dbm_delete failed"); - } - else if (dbmp->di_size >= 0) { - dbmp->di_size--; - } - return valstr; -} - -/* - * call-seq: - * dbm.shift() -> [key, value] - * - * Removes a [key, value] pair from the database, and returns it. - * If the database is empty, returns nil. - * The order in which values are removed/returned is not guaranteed. - */ -static VALUE -fdbm_shift(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - - key = dbm_firstkey(dbm); - if (!key.dptr) return Qnil; - val = dbm_fetch(dbm, key); - keystr = rb_str_new(key.dptr, key.dsize); - valstr = rb_str_new(val.dptr, val.dsize); - dbm_delete(dbm, key); - - return rb_assoc_new(keystr, valstr); -} - -/* - * call-seq: - * dbm.reject! {|key, value| block} -> self - * dbm.delete_if {|key, value| block} -> self - * - * Deletes all entries for which the code block returns true. - * Returns self. - */ -static VALUE -fdbm_delete_if(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - VALUE ret, ary = rb_ary_tmp_new(0); - int status = 0; - long i, n; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - n = dbmp->di_size; - dbmp->di_size = -1; - - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - keystr = rb_str_new(key.dptr, key.dsize); - OBJ_FREEZE(keystr); - valstr = rb_str_new(val.dptr, val.dsize); - ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); - if (status != 0) break; - if (RTEST(ret)) rb_ary_push(ary, keystr); - GetDBM2(obj, dbmp, dbm); - } - - for (i = 0; i < RARRAY_LEN(ary); i++) { - keystr = RARRAY_AREF(ary, i); - key.dptr = RSTRING_PTR(keystr); - key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr); - if (dbm_delete(dbm, key)) { - rb_raise(rb_eDBMError, "dbm_delete failed"); - } - } - if (status) rb_jump_tag(status); - if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary); - rb_ary_clear(ary); - - return obj; -} - -/* - * call-seq: - * dbm.clear - * - * Deletes all data from the database. - */ -static VALUE -fdbm_clear(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - while (key = dbm_firstkey(dbm), key.dptr) { - if (dbm_delete(dbm, key)) { - rb_raise(rb_eDBMError, "dbm_delete failed"); - } - } - dbmp->di_size = 0; - - return obj; -} - -/* - * call-seq: - * dbm.invert -> hash - * - * Returns a Hash (not a DBM database) created by using each value in the - * database as a key, with the corresponding key as its value. - */ -static VALUE -fdbm_invert(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - VALUE hash = rb_hash_new(); - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - keystr = rb_str_new(key.dptr, key.dsize); - valstr = rb_str_new(val.dptr, val.dsize); - rb_hash_aset(hash, valstr, keystr); - } - return hash; -} - -static VALUE fdbm_store(VALUE,VALUE,VALUE); - -static VALUE -update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm)) -{ - const VALUE *ptr; - Check_Type(pair, T_ARRAY); - if (RARRAY_LEN(pair) < 2) { - rb_raise(rb_eArgError, "pair must be [key, value]"); - } - ptr = RARRAY_CONST_PTR(pair); - fdbm_store(dbm, ptr[0], ptr[1]); - return Qnil; -} - -/* - * call-seq: - * dbm.update(obj) - * - * Updates the database with multiple values from the specified object. - * Takes any object which implements the each_pair method, including - * Hash and DBM objects. - */ -static VALUE -fdbm_update(VALUE obj, VALUE other) -{ - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * dbm.replace(obj) - * - * Replaces the contents of the database with the contents of the specified - * object. Takes any object which implements the each_pair method, including - * Hash and DBM objects. - */ -static VALUE -fdbm_replace(VALUE obj, VALUE other) -{ - fdbm_clear(obj); - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * dbm.store(key, value) -> value - * dbm[key] = value - * - * Stores the specified string value in the database, indexed via the - * string key provided. - */ -static VALUE -fdbm_store(VALUE obj, VALUE keystr, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - fdbm_modify(obj); - keystr = rb_obj_as_string(keystr); - valstr = rb_obj_as_string(valstr); - - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_DSIZE(keystr); - - val.dptr = RSTRING_PTR(valstr); - val.dsize = RSTRING_DSIZE(valstr); - - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - if (dbm_store(dbm, key, val, DBM_REPLACE)) { - dbm_clearerr(dbm); - if (errno == EPERM) rb_sys_fail(0); - rb_raise(rb_eDBMError, "dbm_store failed"); - } - - return valstr; -} - -/* - * call-seq: - * dbm.length -> integer - * dbm.size -> integer - * - * Returns the number of entries in the database. - */ -static VALUE -fdbm_length(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - int i = 0; - - GetDBM2(obj, dbmp, dbm); - if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); - - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - i++; - } - dbmp->di_size = i; - - return INT2FIX(i); -} - -/* - * call-seq: - * dbm.empty? - * - * Returns true if the database is empty, false otherwise. - */ -static VALUE -fdbm_empty_p(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - GetDBM2(obj, dbmp, dbm); - if (dbmp->di_size < 0) { - dbm = dbmp->di_dbm; - - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - return Qfalse; - } - } - else { - if (dbmp->di_size) - return Qfalse; - } - return Qtrue; -} - -/* - * call-seq: - * dbm.each_value {|value| block} -> self - * - * Calls the block once for each value string in the database. Returns self. - */ -static VALUE -fdbm_each_value(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - rb_yield(rb_str_new(val.dptr, val.dsize)); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * dbm.each_key {|key| block} -> self - * - * Calls the block once for each key string in the database. Returns self. - */ -static VALUE -fdbm_each_key(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - rb_yield(rb_str_new(key.dptr, key.dsize)); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * dbm.each_pair {|key,value| block} -> self - * - * Calls the block once for each [key, value] pair in the database. - * Returns self. - */ -static VALUE -fdbm_each_pair(VALUE obj) -{ - datum key, val; - DBM *dbm; - struct dbmdata *dbmp; - VALUE keystr, valstr; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - keystr = rb_str_new(key.dptr, key.dsize); - valstr = rb_str_new(val.dptr, val.dsize); - rb_yield(rb_assoc_new(keystr, valstr)); - GetDBM2(obj, dbmp, dbm); - } - - return obj; -} - -/* - * call-seq: - * dbm.keys -> array - * - * Returns an array of all the string keys in the database. - */ -static VALUE -fdbm_keys(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - - ary = rb_ary_new(); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - rb_ary_push(ary, rb_str_new(key.dptr, key.dsize)); - } - - return ary; -} - -/* - * call-seq: - * dbm.values -> array - * - * Returns an array of all the string values in the database. - */ -static VALUE -fdbm_values(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - rb_ary_push(ary, rb_str_new(val.dptr, val.dsize)); - } - - return ary; -} - -/* - * call-seq: - * dbm.include?(key) -> boolean - * dbm.has_key?(key) -> boolean - * dbm.member?(key) -> boolean - * dbm.key?(key) -> boolean - * - * Returns true if the database contains the specified key, false otherwise. - */ -static VALUE -fdbm_has_key(VALUE obj, VALUE keystr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - long len; - - ExportStringValue(keystr); - len = RSTRING_LEN(keystr); - if (TOO_LONG(len)) return Qfalse; - key.dptr = RSTRING_PTR(keystr); - key.dsize = (DSIZE_TYPE)len; - - GetDBM2(obj, dbmp, dbm); - val = dbm_fetch(dbm, key); - if (val.dptr) return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * dbm.has_value?(value) -> boolean - * dbm.value?(value) -> boolean - * - * Returns true if the database contains the specified string value, false - * otherwise. - */ -static VALUE -fdbm_has_value(VALUE obj, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - long len; - - ExportStringValue(valstr); - len = RSTRING_LEN(valstr); - if (TOO_LONG(len)) return Qfalse; - val.dptr = RSTRING_PTR(valstr); - val.dsize = (DSIZE_TYPE)len; - - GetDBM2(obj, dbmp, dbm); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) && - memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) - return Qtrue; - } - return Qfalse; -} - -/* - * call-seq: - * dbm.to_a -> array - * - * Converts the contents of the database to an array of [key, value] arrays, - * and returns it. - */ -static VALUE -fdbm_to_a(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - rb_ary_push(ary, rb_assoc_new(rb_str_new(key.dptr, key.dsize), - rb_str_new(val.dptr, val.dsize))); - } - - return ary; -} - -/* - * call-seq: - * dbm.to_hash -> hash - * - * Converts the contents of the database to an in-memory Hash object, and - * returns it. - */ -static VALUE -fdbm_to_hash(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE hash; - - GetDBM2(obj, dbmp, dbm); - hash = rb_hash_new(); - for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - val = dbm_fetch(dbm, key); - rb_hash_aset(hash, rb_str_new(key.dptr, key.dsize), - rb_str_new(val.dptr, val.dsize)); - } - - return hash; -} - -/* - * call-seq: - * dbm.reject {|key,value| block} -> Hash - * - * Converts the contents of the database to an in-memory Hash, then calls - * Hash#reject with the specified code block, returning a new Hash. - */ -static VALUE -fdbm_reject(VALUE obj) -{ - return rb_hash_delete_if(fdbm_to_hash(obj)); -} - -/* - * == Introduction - * - * The DBM class provides a wrapper to a Unix-style - * {dbm}[http://en.wikipedia.org/wiki/Dbm] or Database Manager library. - * - * Dbm databases do not have tables or columns; they are simple key-value - * data stores, like a Ruby Hash except not resident in RAM. Keys and values - * must be strings. - * - * The exact library used depends on how Ruby was compiled. It could be any - * of the following: - * - * - The original ndbm library is released in 4.3BSD. - * It is based on dbm library in Unix Version 7 but has different API to - * support multiple databases in a process. - * - {Berkeley DB}[http://en.wikipedia.org/wiki/Berkeley_DB] versions - * 1 thru 6, also known as BDB and Sleepycat DB, now owned by Oracle - * Corporation. - * - Berkeley DB 1.x, still found in 4.4BSD derivatives (FreeBSD, OpenBSD, etc). - * - {gdbm}[http://www.gnu.org/software/gdbm/], the GNU implementation of dbm. - * - {qdbm}[http://fallabs.com/qdbm/index.html], another open source - * reimplementation of dbm. - * - * All of these dbm implementations have their own Ruby interfaces - * available, which provide richer (but varying) APIs. - * - * == Cautions - * - * Before you decide to use DBM, there are some issues you should consider: - * - * - Each implementation of dbm has its own file format. Generally, dbm - * libraries will not read each other's files. This makes dbm files - * a bad choice for data exchange. - * - * - Even running the same OS and the same dbm implementation, the database - * file format may depend on the CPU architecture. For example, files may - * not be portable between PowerPC and 386, or between 32 and 64 bit Linux. - * - * - Different versions of Berkeley DB use different file formats. A change to - * the OS may therefore break DBM access to existing files. - * - * - Data size limits vary between implementations. Original Berkeley DB was - * limited to 2GB of data. Dbm libraries also sometimes limit the total - * size of a key/value pair, and the total size of all the keys that hash - * to the same value. These limits can be as little as 512 bytes. That said, - * gdbm and recent versions of Berkeley DB do away with these limits. - * - * Given the above cautions, DBM is not a good choice for long term storage of - * important data. It is probably best used as a fast and easy alternative - * to a Hash for processing large amounts of data. - * - * == Example - * - * require 'dbm' - * db = DBM.open('rfcs', 0666, DBM::WRCREAT) - * db['822'] = 'Standard for the Format of ARPA Internet Text Messages' - * db['1123'] = 'Requirements for Internet Hosts - Application and Support' - * db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers' - * puts db['822'] - */ -void -Init_dbm(void) -{ - rb_cDBM = rb_define_class("DBM", rb_cObject); - /* Document-class: DBMError - * Exception class used to return errors from the dbm library. - */ - rb_eDBMError = rb_define_class("DBMError", rb_eStandardError); - rb_include_module(rb_cDBM, rb_mEnumerable); - - rb_define_alloc_func(rb_cDBM, fdbm_alloc); - rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1); - - rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1); - rb_define_method(rb_cDBM, "close", fdbm_close, 0); - rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0); - rb_define_method(rb_cDBM, "[]", fdbm_aref, 1); - rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1); - rb_define_method(rb_cDBM, "[]=", fdbm_store, 2); - rb_define_method(rb_cDBM, "store", fdbm_store, 2); - rb_define_method(rb_cDBM, "index", fdbm_index, 1); - rb_define_method(rb_cDBM, "key", fdbm_key, 1); - rb_define_method(rb_cDBM, "select", fdbm_select, 0); - rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1); - rb_define_method(rb_cDBM, "length", fdbm_length, 0); - rb_define_method(rb_cDBM, "size", fdbm_length, 0); - rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0); - rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0); - rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0); - rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0); - rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0); - rb_define_method(rb_cDBM, "keys", fdbm_keys, 0); - rb_define_method(rb_cDBM, "values", fdbm_values, 0); - rb_define_method(rb_cDBM, "shift", fdbm_shift, 0); - rb_define_method(rb_cDBM, "delete", fdbm_delete, 1); - rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0); - rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0); - rb_define_method(rb_cDBM, "reject", fdbm_reject, 0); - rb_define_method(rb_cDBM, "clear", fdbm_clear, 0); - rb_define_method(rb_cDBM, "invert", fdbm_invert, 0); - rb_define_method(rb_cDBM, "update", fdbm_update, 1); - rb_define_method(rb_cDBM, "replace", fdbm_replace, 1); - - rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1); - rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1); - rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1); - rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1); - rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1); - rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1); - - rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0); - rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0); - - /* Indicates that dbm_open() should open the database in read-only mode */ - rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT)); - - /* Indicates that dbm_open() should open the database in read/write mode */ - rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT)); - - /* Indicates that dbm_open() should open the database in read/write mode, - * and create it if it does not already exist - */ - rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT)); - - /* Indicates that dbm_open() should open the database in read/write mode, - * create it if it does not already exist, and delete all contents if it - * does already exist. - */ - rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT)); - - { - VALUE version; -#if defined(_DBM_IOERR) - version = rb_str_new2("ndbm (4.3BSD)"); -#elif defined(RUBYDBM_GDBM_HEADER) -# if defined(HAVE_DECLARED_LIBVAR_GDBM_VERSION) - /* since gdbm 1.9 */ - version = rb_str_new2(gdbm_version); -# elif defined(HAVE_UNDECLARED_LIBVAR_GDBM_VERSION) - /* ndbm.h doesn't declare gdbm_version until gdbm 1.8.3. - * See extconf.rb for more information. */ - RUBY_EXTERN char *gdbm_version; - version = rb_str_new2(gdbm_version); -# else - version = rb_str_new2("GDBM (unknown)"); -# endif -#elif defined(RUBYDBM_DB_HEADER) -# if defined(HAVE_DB_VERSION) - /* The version of the dbm library, if using Berkeley DB */ - version = rb_str_new2(db_version(NULL, NULL, NULL)); -# else - version = rb_str_new2("Berkeley DB (unknown)"); -# endif -#elif defined(_RELIC_H) -# if defined(HAVE_DPVERSION) - version = rb_sprintf("QDBM %s", dpversion); -# else - version = rb_str_new2("QDBM (unknown)"); -# endif -#else - version = rb_str_new2("ndbm (unknown)"); -#endif - /* - * Identifies ndbm library version. - * - * Examples: - * - * - "ndbm (4.3BSD)" - * - "Berkeley DB 4.8.30: (April 9, 2010)" - * - "Berkeley DB (unknown)" (4.4BSD, maybe) - * - "GDBM version 1.8.3. 10/15/2002 (built Jul 1 2011 12:32:45)" - * - "QDBM 1.8.78" - * - */ - rb_define_const(rb_cDBM, "VERSION", version); - } -} diff --git a/ruby/ext/dbm/dbm.gemspec b/ruby/ext/dbm/dbm.gemspec deleted file mode 100644 index 9de425b52..000000000 --- a/ruby/ext/dbm/dbm.gemspec +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true -Gem::Specification.new do |s| - s.name = "dbm" - s.version = '1.1.0' - s.summary = "Provides a wrapper for the UNIX-style Database Manager Library" - s.description = "Provides a wrapper for the UNIX-style Database Manager Library" - - s.require_path = %w{lib} - s.files = %w{ext/dbm/extconf.rb ext/dbm/dbm.c} - s.extensions = %w{ext/dbm/extconf.rb} - s.required_ruby_version = ">= 2.3.0" - - s.authors = ["Yukihiro Matsumoto"] - s.email = ["matz@ruby-lang.org"] - s.homepage = "https://github.com/ruby/dbm" - s.license = "BSD-2-Clause" - - s.add_development_dependency "rake-compiler" - s.add_development_dependency "test-unit" -end diff --git a/ruby/ext/dbm/depend b/ruby/ext/dbm/depend deleted file mode 100644 index 192527a8e..000000000 --- a/ruby/ext/dbm/depend +++ /dev/null @@ -1,14 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -dbm.o: $(RUBY_EXTCONF_H) -dbm.o: $(arch_hdrdir)/ruby/config.h -dbm.o: $(hdrdir)/ruby.h -dbm.o: $(hdrdir)/ruby/assert.h -dbm.o: $(hdrdir)/ruby/backward.h -dbm.o: $(hdrdir)/ruby/defines.h -dbm.o: $(hdrdir)/ruby/intern.h -dbm.o: $(hdrdir)/ruby/missing.h -dbm.o: $(hdrdir)/ruby/ruby.h -dbm.o: $(hdrdir)/ruby/st.h -dbm.o: $(hdrdir)/ruby/subst.h -dbm.o: dbm.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/dbm/extconf.rb b/ruby/ext/dbm/extconf.rb deleted file mode 100644 index c3d3d0789..000000000 --- a/ruby/ext/dbm/extconf.rb +++ /dev/null @@ -1,295 +0,0 @@ -# frozen_string_literal: true -# configure option: -# --with-dbm-type=COMMA-SEPARATED-NDBM-TYPES -# -# ndbm type: -# libc ndbm compatible library in libc. -# db Berkeley DB (libdb) -# db2 Berkeley DB (libdb2) -# db1 Berkeley DB (libdb1) -# db6 Berkeley DB (libdb6) -# db5 Berkeley DB (libdb5) -# db4 Berkeley DB (libdb4) -# db3 Berkeley DB (libdb3) -# gdbm_compat GDBM since 1.8.1 (libgdbm_compat) -# gdbm GDBM until 1.8.0 (libgdbm) -# qdbm QDBM (libqdbm) -# ndbm Some legacy OS may have libndbm. - -# :stopdoc: -require 'mkmf' - -dir_config("dbm") - -if dblib = with_config("dbm-type", nil) - dblib = dblib.split(/[ ,]+/) -else - dblib = %w(libc db db2 db1 db6 db5 db4 db3 gdbm_compat gdbm qdbm) -end -# --------- [Enclose.IO Hack start] --------- -dblib = %w(gdbm_compat) -# --------- [Enclose.IO Hack end] --------- - -headers = { - "libc" => ["ndbm.h"], # 4.3BSD original ndbm, Berkeley DB 1 in 4.4BSD libc. - "db" => ["db.h"], - "db1" => ["db1/ndbm.h", "db1.h", "ndbm.h"], - "db2" => ["db2/db.h", "db2.h", "db.h"], - "db3" => ["db3/db.h", "db3.h", "db.h"], - "db4" => ["db4/db.h", "db4.h", "db.h"], - "db5" => ["db5/db.h", "db5.h", "db.h"], - "db6" => ["db6/db.h", "db6.h", "db.h"], - "gdbm_compat" => ["gdbm-ndbm.h", "gdbm/ndbm.h", "ndbm.h"], # GDBM since 1.8.1 - "gdbm" => ["gdbm-ndbm.h", "gdbm/ndbm.h", "ndbm.h"], # GDBM until 1.8.0 - "qdbm" => ["qdbm/relic.h", "relic.h"], -} - -class << headers - attr_accessor :found - attr_accessor :defs -end -headers.found = [] -headers.defs = nil - -def headers.db_check(db, hdr) - old_libs = $libs.dup - old_defs = $defs.dup - result = db_check2(db, hdr) - if !result - $libs = old_libs - $defs = old_defs - end - result -end - -def have_declared_libvar(var, headers = nil, opt = "", &b) - checking_for checking_message([*var].compact.join(' '), headers, opt) do - try_declared_libvar(var, headers, opt, &b) - end -end - -def try_declared_libvar(var, headers = nil, opt = "", &b) - if try_link(<<"SRC", opt, &b) -#{cpp_include(headers)} -/*top*/ -int main(int argc, char *argv[]) { - void *conftest_var = &#{var}; - return 0; -} -SRC - $defs.push(format("-DHAVE_DECLARED_LIBVAR_%s", var.tr_cpp)) - true - else - false - end -end - -def have_undeclared_libvar(var, headers = nil, opt = "", &b) - checking_for checking_message([*var].compact.join(' '), headers, opt) do - try_undeclared_libvar(var, headers, opt, &b) - end -end - -def try_undeclared_libvar(var, headers = nil, opt = "", &b) - var, type = *var - if try_link(<<"SRC", opt, &b) -#{cpp_include(headers)} -/*top*/ -int main(int argc, char *argv[]) { - typedef #{type || 'int'} conftest_type; - extern conftest_type #{var}; - conftest_type *conftest_var = &#{var}; - return 0; -} -SRC - $defs.push(format("-DHAVE_UNDECLARED_LIBVAR_%s", var.tr_cpp)) - true - else - false - end -end - -def have_empty_macro_dbm_clearerr(headers = nil, opt = "", &b) - checking_for checking_message('empty macro of dbm_clearerr(foobarbaz)', - headers, opt) do - try_toplevel('dbm_clearerr(foobarbaz)', headers, opt, &b) - end -end - -def try_toplevel(src, headers = nil, opt = "", &b) - if try_compile(<<"SRC", opt, &b) -#{cpp_include(headers)} -/*top*/ -#{src} -SRC - true - else - false - end -end - - -def headers.db_check2(db, hdr) - $defs.push(%{-DRUBYDBM_DBM_HEADER='"#{hdr}"'}) - $defs.push(%{-DRUBYDBM_DBM_TYPE='"#{db}"'}) - - hsearch = nil - - case db - when /^db[2-6]?$/ - hsearch = "-DDB_DBM_HSEARCH" - when "gdbm_compat" - have_library("gdbm") or return false - end - - if !have_type("DBM", hdr, hsearch) - return false - end - - # 'libc' means ndbm is provided by libc. - # 4.3BSD original ndbm is contained in libc. - # 4.4BSD (and its derivatives such as NetBSD) contains Berkeley DB 1 in libc. - if !(db == 'libc' ? have_func('dbm_open("", 0, 0)', hdr, hsearch) : - have_library(db, 'dbm_open("", 0, 0)', hdr, hsearch)) - return false - end - - # Skip a mismatch of Berkeley DB's ndbm.h and old GDBM library. - # - # dbm_clearerr() should be available for any ndbm implementation. - # It is available since the original (4.3BSD) ndbm and standardized by POSIX. - # - # However "can't resolve symbol 'dbm_clearerr'" problem may be caused by - # header/library mismatch: Berkeley DB ndbm.h and GDBM library until 1.8.3. - # GDBM (until 1.8.3) provides dbm_clearerr() as a empty macro in the header - # and the library don't provide dbm_clearerr(). - # Berkeley DB provides dbm_clearerr() as a usual function. - # So Berkeley DB header with GDBM library causes the problem. - # - if !have_func('dbm_clearerr((DBM *)0)', hdr, hsearch) - return false - end - - # Berkeley DB's ndbm.h (since 1.85 at least) defines DBM_SUFFIX. - # Note that _DB_H_ is not defined on Mac OS X because - # it uses Berkeley DB 1 but ndbm.h doesn't include db.h. - have_db_header = have_macro('DBM_SUFFIX', hdr, hsearch) - - # Old GDBM's ndbm.h, until 1.8.3, defines dbm_clearerr as a macro which - # expands to no tokens. - have_gdbm_header1 = have_empty_macro_dbm_clearerr(hdr, hsearch) - - # Recent GDBM's ndbm.h, since 1.9, includes gdbm.h and it defines _GDBM_H_. - # ndbm compatibility layer of GDBM is provided by libgdbm (until 1.8.0) - # and libgdbm_compat (since 1.8.1). - have_gdbm_header2 = have_macro('_GDBM_H_', hdr, hsearch) - - # 4.3BSD's ndbm.h defines _DBM_IOERR. - # The original ndbm is provided by libc in 4.3BSD. - have_ndbm_header = have_macro('_DBM_IOERR', hdr, hsearch) - - # GDBM provides ndbm functions in libgdbm_compat since GDBM 1.8.1. - # GDBM's ndbm.h defines _GDBM_H_ since GDBM 1.9. - # If _GDBM_H_ is defined, 'gdbm_compat' is required and reject 'gdbm'. - if have_gdbm_header2 && db == 'gdbm' - return false - end - - if have_db_header - $defs.push('-DRUBYDBM_DB_HEADER') - end - - have_gdbm_header = have_gdbm_header1 | have_gdbm_header2 - if have_gdbm_header - $defs.push('-DRUBYDBM_GDBM_HEADER') - end - - # ndbm.h is provided by the original (4.3BSD) ndbm, - # Berkeley DB 1 in libc of 4.4BSD and - # ndbm compatibility layer of GDBM. - # So, try to check header/library mismatch. - # - # Several (possibly historical) distributions provides libndbm. - # It may be Berkeley DB, GDBM or 4.3BSD ndbm. - # So mismatch check is not performed for that. - # Note that libndbm is searched only when --with-dbm-type=ndbm is - # given for configure. - # - if hdr == 'ndbm.h' && db != 'libc' && db != 'ndbm' - if /\Adb\d?\z/ !~ db && have_db_header - return false - end - - if /\Agdbm/ !~ db && have_gdbm_header - return false - end - - if have_ndbm_header - return false - end - end - - # Berkeley DB - have_func('db_version((int *)0, (int *)0, (int *)0)', hdr, hsearch) - - # GDBM - have_gdbm_version = have_declared_libvar("gdbm_version", hdr, hsearch) - # gdbm_version is available since very old version (GDBM 1.5 at least). - # However it is not declared by ndbm.h until GDBM 1.8.3. - # We can't include both ndbm.h and gdbm.h because they both define datum type. - # ndbm.h includes gdbm.h and gdbm_version is declared since GDBM 1.9. - have_gdbm_version |= have_undeclared_libvar(["gdbm_version", "char *"], hdr, hsearch) - - # QDBM - have_var("dpversion", hdr, hsearch) - - # detect mismatch between GDBM header and other library. - # If GDBM header is included, GDBM library should be linked. - if have_gdbm_header && !have_gdbm_version - return false - end - - # DBC type is required to disable error messages by Berkeley DB 2 or later. - if have_db_header - have_type("DBC", hdr, hsearch) - end - - if hsearch - $defs << hsearch - @defs = hsearch - end - $defs << '-DDBM_HDR="<'+hdr+'>"' - @found << hdr - - puts "header: #{hdr}" - puts "library: #{db}" - - true -end - -if dblib.any? {|db| headers.fetch(db, ["ndbm.h"]).any? {|hdr| headers.db_check(db, hdr) } } - have_header("cdefs.h") - have_header("sys/cdefs.h") - have_func("dbm_pagfno((DBM *)0)", headers.found, headers.defs) - have_func("dbm_dirfno((DBM *)0)", headers.found, headers.defs) - convertible_int("datum.dsize", headers.found, headers.defs) - checking_for("sizeof(DBM) is available") { - if try_compile(< -#endif -#ifdef HAVE_SYS_CDEFS_H -# include -#endif -#include DBM_HDR - -const int sizeof_DBM = (int)sizeof(DBM); -SRC - $defs << '-DDBM_SIZEOF_DBM=sizeof(DBM)' - else - $defs << '-DDBM_SIZEOF_DBM=0' - end - } - create_makefile("dbm") -end -# :startdoc: diff --git a/ruby/ext/digest/bubblebabble/depend b/ruby/ext/digest/bubblebabble/depend index e7e2a8889..28d4f472a 100644 --- a/ruby/ext/digest/bubblebabble/depend +++ b/ruby/ext/digest/bubblebabble/depend @@ -4,8 +4,155 @@ bubblebabble.o: $(arch_hdrdir)/ruby/config.h bubblebabble.o: $(hdrdir)/ruby.h bubblebabble.o: $(hdrdir)/ruby/assert.h bubblebabble.o: $(hdrdir)/ruby/backward.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/assume.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/attributes.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/bool.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/inttypes.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/limits.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/long_long.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/stdalign.h +bubblebabble.o: $(hdrdir)/ruby/backward/2/stdarg.h bubblebabble.o: $(hdrdir)/ruby/defines.h bubblebabble.o: $(hdrdir)/ruby/intern.h +bubblebabble.o: $(hdrdir)/ruby/internal/anyargs.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bubblebabble.o: $(hdrdir)/ruby/internal/assume.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/artificial.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/cold.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/const.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/error.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/format.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/noalias.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/noinline.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/pure.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/restrict.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/warning.h +bubblebabble.o: $(hdrdir)/ruby/internal/attr/weakref.h +bubblebabble.o: $(hdrdir)/ruby/internal/cast.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bubblebabble.o: $(hdrdir)/ruby/internal/compiler_since.h +bubblebabble.o: $(hdrdir)/ruby/internal/config.h +bubblebabble.o: $(hdrdir)/ruby/internal/constant_p.h +bubblebabble.o: $(hdrdir)/ruby/internal/core.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rarray.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rbasic.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rbignum.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rclass.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rdata.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rfile.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rhash.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/robject.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rregexp.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rstring.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rstruct.h +bubblebabble.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bubblebabble.o: $(hdrdir)/ruby/internal/ctype.h +bubblebabble.o: $(hdrdir)/ruby/internal/dllexport.h +bubblebabble.o: $(hdrdir)/ruby/internal/dosish.h +bubblebabble.o: $(hdrdir)/ruby/internal/error.h +bubblebabble.o: $(hdrdir)/ruby/internal/eval.h +bubblebabble.o: $(hdrdir)/ruby/internal/event.h +bubblebabble.o: $(hdrdir)/ruby/internal/fl_type.h +bubblebabble.o: $(hdrdir)/ruby/internal/gc.h +bubblebabble.o: $(hdrdir)/ruby/internal/glob.h +bubblebabble.o: $(hdrdir)/ruby/internal/globals.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/attribute.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/builtin.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/extension.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/feature.h +bubblebabble.o: $(hdrdir)/ruby/internal/has/warning.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/array.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/bignum.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/class.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/compar.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/complex.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/cont.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/dir.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/enum.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/error.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/eval.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/file.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/gc.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/hash.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/io.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/load.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/marshal.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/numeric.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/object.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/parse.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/proc.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/process.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/random.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/range.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/string.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/struct.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/thread.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/time.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/variable.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/vm.h +bubblebabble.o: $(hdrdir)/ruby/internal/interpreter.h +bubblebabble.o: $(hdrdir)/ruby/internal/iterator.h +bubblebabble.o: $(hdrdir)/ruby/internal/memory.h +bubblebabble.o: $(hdrdir)/ruby/internal/method.h +bubblebabble.o: $(hdrdir)/ruby/internal/module.h +bubblebabble.o: $(hdrdir)/ruby/internal/newobj.h +bubblebabble.o: $(hdrdir)/ruby/internal/rgengc.h +bubblebabble.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +bubblebabble.o: $(hdrdir)/ruby/internal/value.h +bubblebabble.o: $(hdrdir)/ruby/internal/value_type.h +bubblebabble.o: $(hdrdir)/ruby/internal/variable.h +bubblebabble.o: $(hdrdir)/ruby/internal/warning_push.h +bubblebabble.o: $(hdrdir)/ruby/internal/xmalloc.h bubblebabble.o: $(hdrdir)/ruby/missing.h bubblebabble.o: $(hdrdir)/ruby/ruby.h bubblebabble.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/digest/bubblebabble/extconf.rb b/ruby/ext/digest/bubblebabble/extconf.rb index 21feed57f..8fb001c61 100644 --- a/ruby/ext/digest/bubblebabble/extconf.rb +++ b/ruby/ext/digest/bubblebabble/extconf.rb @@ -1,6 +1,4 @@ # frozen_string_literal: false require 'mkmf' -$defs << "-DHAVE_CONFIG_H" - create_makefile('digest/bubblebabble') diff --git a/ruby/ext/digest/depend b/ruby/ext/digest/depend index 87c39c8b8..041ba8be5 100644 --- a/ruby/ext/digest/depend +++ b/ruby/ext/digest/depend @@ -4,8 +4,155 @@ digest.o: $(arch_hdrdir)/ruby/config.h digest.o: $(hdrdir)/ruby.h digest.o: $(hdrdir)/ruby/assert.h digest.o: $(hdrdir)/ruby/backward.h +digest.o: $(hdrdir)/ruby/backward/2/assume.h +digest.o: $(hdrdir)/ruby/backward/2/attributes.h +digest.o: $(hdrdir)/ruby/backward/2/bool.h +digest.o: $(hdrdir)/ruby/backward/2/inttypes.h +digest.o: $(hdrdir)/ruby/backward/2/limits.h +digest.o: $(hdrdir)/ruby/backward/2/long_long.h +digest.o: $(hdrdir)/ruby/backward/2/stdalign.h +digest.o: $(hdrdir)/ruby/backward/2/stdarg.h digest.o: $(hdrdir)/ruby/defines.h digest.o: $(hdrdir)/ruby/intern.h +digest.o: $(hdrdir)/ruby/internal/anyargs.h +digest.o: $(hdrdir)/ruby/internal/arithmetic.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +digest.o: $(hdrdir)/ruby/internal/assume.h +digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +digest.o: $(hdrdir)/ruby/internal/attr/artificial.h +digest.o: $(hdrdir)/ruby/internal/attr/cold.h +digest.o: $(hdrdir)/ruby/internal/attr/const.h +digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h +digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h +digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +digest.o: $(hdrdir)/ruby/internal/attr/error.h +digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h +digest.o: $(hdrdir)/ruby/internal/attr/format.h +digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +digest.o: $(hdrdir)/ruby/internal/attr/noalias.h +digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h +digest.o: $(hdrdir)/ruby/internal/attr/noinline.h +digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h +digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h +digest.o: $(hdrdir)/ruby/internal/attr/pure.h +digest.o: $(hdrdir)/ruby/internal/attr/restrict.h +digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +digest.o: $(hdrdir)/ruby/internal/attr/warning.h +digest.o: $(hdrdir)/ruby/internal/attr/weakref.h +digest.o: $(hdrdir)/ruby/internal/cast.h +digest.o: $(hdrdir)/ruby/internal/compiler_is.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +digest.o: $(hdrdir)/ruby/internal/compiler_since.h +digest.o: $(hdrdir)/ruby/internal/config.h +digest.o: $(hdrdir)/ruby/internal/constant_p.h +digest.o: $(hdrdir)/ruby/internal/core.h +digest.o: $(hdrdir)/ruby/internal/core/rarray.h +digest.o: $(hdrdir)/ruby/internal/core/rbasic.h +digest.o: $(hdrdir)/ruby/internal/core/rbignum.h +digest.o: $(hdrdir)/ruby/internal/core/rclass.h +digest.o: $(hdrdir)/ruby/internal/core/rdata.h +digest.o: $(hdrdir)/ruby/internal/core/rfile.h +digest.o: $(hdrdir)/ruby/internal/core/rhash.h +digest.o: $(hdrdir)/ruby/internal/core/robject.h +digest.o: $(hdrdir)/ruby/internal/core/rregexp.h +digest.o: $(hdrdir)/ruby/internal/core/rstring.h +digest.o: $(hdrdir)/ruby/internal/core/rstruct.h +digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +digest.o: $(hdrdir)/ruby/internal/ctype.h +digest.o: $(hdrdir)/ruby/internal/dllexport.h +digest.o: $(hdrdir)/ruby/internal/dosish.h +digest.o: $(hdrdir)/ruby/internal/error.h +digest.o: $(hdrdir)/ruby/internal/eval.h +digest.o: $(hdrdir)/ruby/internal/event.h +digest.o: $(hdrdir)/ruby/internal/fl_type.h +digest.o: $(hdrdir)/ruby/internal/gc.h +digest.o: $(hdrdir)/ruby/internal/glob.h +digest.o: $(hdrdir)/ruby/internal/globals.h +digest.o: $(hdrdir)/ruby/internal/has/attribute.h +digest.o: $(hdrdir)/ruby/internal/has/builtin.h +digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h +digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +digest.o: $(hdrdir)/ruby/internal/has/extension.h +digest.o: $(hdrdir)/ruby/internal/has/feature.h +digest.o: $(hdrdir)/ruby/internal/has/warning.h +digest.o: $(hdrdir)/ruby/internal/intern/array.h +digest.o: $(hdrdir)/ruby/internal/intern/bignum.h +digest.o: $(hdrdir)/ruby/internal/intern/class.h +digest.o: $(hdrdir)/ruby/internal/intern/compar.h +digest.o: $(hdrdir)/ruby/internal/intern/complex.h +digest.o: $(hdrdir)/ruby/internal/intern/cont.h +digest.o: $(hdrdir)/ruby/internal/intern/dir.h +digest.o: $(hdrdir)/ruby/internal/intern/enum.h +digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h +digest.o: $(hdrdir)/ruby/internal/intern/error.h +digest.o: $(hdrdir)/ruby/internal/intern/eval.h +digest.o: $(hdrdir)/ruby/internal/intern/file.h +digest.o: $(hdrdir)/ruby/internal/intern/gc.h +digest.o: $(hdrdir)/ruby/internal/intern/hash.h +digest.o: $(hdrdir)/ruby/internal/intern/io.h +digest.o: $(hdrdir)/ruby/internal/intern/load.h +digest.o: $(hdrdir)/ruby/internal/intern/marshal.h +digest.o: $(hdrdir)/ruby/internal/intern/numeric.h +digest.o: $(hdrdir)/ruby/internal/intern/object.h +digest.o: $(hdrdir)/ruby/internal/intern/parse.h +digest.o: $(hdrdir)/ruby/internal/intern/proc.h +digest.o: $(hdrdir)/ruby/internal/intern/process.h +digest.o: $(hdrdir)/ruby/internal/intern/random.h +digest.o: $(hdrdir)/ruby/internal/intern/range.h +digest.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h +digest.o: $(hdrdir)/ruby/internal/intern/string.h +digest.o: $(hdrdir)/ruby/internal/intern/struct.h +digest.o: $(hdrdir)/ruby/internal/intern/thread.h +digest.o: $(hdrdir)/ruby/internal/intern/time.h +digest.o: $(hdrdir)/ruby/internal/intern/variable.h +digest.o: $(hdrdir)/ruby/internal/intern/vm.h +digest.o: $(hdrdir)/ruby/internal/interpreter.h +digest.o: $(hdrdir)/ruby/internal/iterator.h +digest.o: $(hdrdir)/ruby/internal/memory.h +digest.o: $(hdrdir)/ruby/internal/method.h +digest.o: $(hdrdir)/ruby/internal/module.h +digest.o: $(hdrdir)/ruby/internal/newobj.h +digest.o: $(hdrdir)/ruby/internal/rgengc.h +digest.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +digest.o: $(hdrdir)/ruby/internal/value.h +digest.o: $(hdrdir)/ruby/internal/value_type.h +digest.o: $(hdrdir)/ruby/internal/variable.h +digest.o: $(hdrdir)/ruby/internal/warning_push.h +digest.o: $(hdrdir)/ruby/internal/xmalloc.h digest.o: $(hdrdir)/ruby/missing.h digest.o: $(hdrdir)/ruby/ruby.h digest.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/digest/digest.c b/ruby/ext/digest/digest.c index a59f880ac..83f4ee42f 100644 --- a/ruby/ext/digest/digest.c +++ b/ruby/ext/digest/digest.c @@ -406,7 +406,7 @@ rb_digest_instance_digest_length(VALUE self) /* never blindly assume that #digest() returns a string */ StringValue(digest); - return INT2NUM(RSTRING_LEN(digest)); + return LONG2NUM(RSTRING_LEN(digest)); } /* @@ -725,7 +725,7 @@ rb_digest_base_digest_length(VALUE self) algo = get_digest_obj_metadata(self); - return INT2NUM(algo->digest_len); + return SIZET2NUM(algo->digest_len); } /* @@ -740,7 +740,7 @@ rb_digest_base_block_length(VALUE self) algo = get_digest_obj_metadata(self); - return INT2NUM(algo->block_len); + return SIZET2NUM(algo->block_len); } void @@ -765,6 +765,10 @@ InitVM_digest(void) */ rb_mDigest = rb_define_module("Digest"); +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + /* module functions */ rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1); diff --git a/ruby/ext/digest/digest.gemspec b/ruby/ext/digest/digest.gemspec new file mode 100644 index 000000000..4a01c5fde --- /dev/null +++ b/ruby/ext/digest/digest.gemspec @@ -0,0 +1,44 @@ +# coding: utf-8 +# frozen_string_literal: true + +Gem::Specification.new do |spec| + version_module = Module.new do + version_rb = File.join(__dir__, "lib/digest/version.rb") + module_eval(File.read(version_rb), version_rb) + end + + spec.name = "digest" + spec.version = version_module::Digest::VERSION + spec.authors = ["Akinori MUSHA"] + spec.email = ["knu@idaemons.org"] + + spec.summary = %q{Provides a framework for message digest libraries.} + spec.description = %q{Provides a framework for message digest libraries.} + spec.homepage = "https://github.com/ruby/digest" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + spec.files = [ + "LICENSE.txt", + "README.md", + *Dir["lib/digest{.rb,/**/*.rb}"], + ] + + spec.required_ruby_version = ">= 2.5.0" + + spec.bindir = "exe" + spec.executables = [] + + if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' + spec.platform = 'java' + + spec.files += Dir["ext/java/**/*.{rb,java}", "lib/digest.jar"] + spec.require_paths = %w[lib ext/java/org/jruby/ext/digest/lib] + else + spec.extensions = Dir["ext/digest/**/extconf.rb"] + + spec.files += Dir["ext/digest/**/{*.{rb,c,h,sh},depend}"] + spec.require_paths = %w[lib] + end + + spec.metadata["msys2_mingw_dependencies"] = "openssl" +end diff --git a/ruby/ext/digest/digest.h b/ruby/ext/digest/digest.h index 4b6954089..0d4f0e7cc 100644 --- a/ruby/ext/digest/digest.h +++ b/ruby/ext/digest/digest.h @@ -62,3 +62,11 @@ rb_id_metadata(void) { return rb_intern_const("metadata"); } + +static inline VALUE +rb_digest_make_metadata(const rb_digest_metadata_t *meta) +{ +#undef RUBY_UNTYPED_DATA_WARNING +#define RUBY_UNTYPED_DATA_WARNING 0 + return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); +} diff --git a/ruby/ext/digest/digest_conf.rb b/ruby/ext/digest/digest_conf.rb index 915b61877..1b929d873 100644 --- a/ruby/ext/digest/digest_conf.rb +++ b/ruby/ext/digest/digest_conf.rb @@ -1,57 +1,6 @@ # frozen_string_literal: false -# Copy from ext/openssl/extconf.rb -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 - - return false unless have_header("openssl/ssl.h") - - ret = have_library("crypto", "CRYPTO_malloc") && - have_library("ssl", "SSL_new") - return ret if ret - - if $mswin - # OpenSSL >= 1.1.0: libcrypto.lib and libssl.lib. - if have_library("libcrypto", "CRYPTO_malloc") && - have_library("libssl", "SSL_new") - 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 - libpath |= ENV["LIB"].split(File::PATH_SEPARATOR) - libpath.map! { |d| d.tr(File::ALT_SEPARATOR, File::SEPARATOR) } - - ret = [ - ["crypto", "CRYPTO_malloc"], - ["ssl", "SSL_new"] - ].all? do |base, func| - result = false - libs = ["lib#{base}-[0-9][0-9]", "lib#{base}-[0-9][0-9][0-9]"] - libs = Dir.glob(libs.map{|l| libpath.map{|d| File.join(d, l + ".*")}}.flatten).map{|path| File.basename(path, ".*")}.uniq - libs.each do |lib| - result = have_library(lib, func) - break if result - end - result - end - return ret if ret - end - return false -end - -def digest_conf(name, hdr = name, funcs = nil, types = nil) +def digest_conf(name) unless with_config("bundled-#{name}") cc = with_config("common-digest") if cc == true or /\b#{name}\b/ =~ cc @@ -62,22 +11,6 @@ def digest_conf(name, hdr = name, funcs = nil, types = nil) return :commondigest end end - - dir_config("openssl") - pkg_config("openssl") - require File.expand_path('../../openssl/deprecation', __FILE__) - if find_openssl_library - funcs ||= name.upcase - funcs = Array(funcs) - types ||= funcs - hdr = "openssl/#{hdr}.h" - if funcs.all? {|func| OpenSSL.check_func("#{func}_Transform", hdr)} && - types.all? {|type| have_type("#{type}_CTX", hdr)} - $defs << "-D#{name.upcase}_USE_OPENSSL" - $headers << "#{name}ossl.h" - return :ossl - end - end end $objs << "#{name}.#{$OBJEXT}" return diff --git a/ruby/ext/digest/extconf.rb b/ruby/ext/digest/extconf.rb index a8c68850a..0e5f08d79 100644 --- a/ruby/ext/digest/extconf.rb +++ b/ruby/ext/digest/extconf.rb @@ -6,6 +6,6 @@ $INSTALLFILES = { "digest.h" => "$(HDRDIR)" -} +} if $extmk create_makefile("digest") diff --git a/ruby/ext/digest/lib/digest.rb b/ruby/ext/digest/lib/digest.rb index ba0637af3..e995adb45 100644 --- a/ruby/ext/digest/lib/digest.rb +++ b/ruby/ext/digest/lib/digest.rb @@ -1,5 +1,19 @@ # frozen_string_literal: false -require 'digest.so' + +if defined?(Digest) && + /\A(?:2\.|3\.0\.[0-2]\z)/.match?(RUBY_VERSION) && + caller_locations.any? { |l| + %r{/(rubygems/gem_runner|bundler/cli)\.rb}.match?(l.path) + } + # Before Ruby 3.0.3/3.1.0, the gem and bundle commands used to load + # the digest library before loading additionally installed gems, so + # you will get constant redefinition warnings and unexpected + # implementation overwriting if we proceed here. Avoid that. + return +end + +require 'digest/version' +require 'digest/loader' module Digest # A mutex for Digest(). @@ -8,7 +22,7 @@ module Digest def self.const_missing(name) # :nodoc: case name when :SHA256, :SHA384, :SHA512 - lib = 'digest/sha2.so' + lib = 'digest/sha2' else lib = File.join('digest', name.to_s.downcase) end diff --git a/ruby/ext/digest/lib/digest/loader.rb b/ruby/ext/digest/lib/digest/loader.rb new file mode 100644 index 000000000..6b989e07b --- /dev/null +++ b/ruby/ext/digest/lib/digest/loader.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require 'digest.so' diff --git a/ruby/ext/digest/lib/digest/version.rb b/ruby/ext/digest/lib/digest/version.rb new file mode 100644 index 000000000..79e6aeee9 --- /dev/null +++ b/ruby/ext/digest/lib/digest/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Digest + VERSION = "3.1.0" +end diff --git a/ruby/ext/digest/md5/depend b/ruby/ext/digest/md5/depend index abfd8de6a..2e07652cc 100644 --- a/ruby/ext/digest/md5/depend +++ b/ruby/ext/digest/md5/depend @@ -2,18 +2,327 @@ md5.o: md5.c md5.h $(srcdir)/../defs.h md5init.o: $(LOCAL_HDRS) # AUTOGENERATED DEPENDENCIES START +md5.o: $(RUBY_EXTCONF_H) +md5.o: $(arch_hdrdir)/ruby/config.h +md5.o: $(hdrdir)/ruby.h +md5.o: $(hdrdir)/ruby/assert.h +md5.o: $(hdrdir)/ruby/backward.h +md5.o: $(hdrdir)/ruby/backward/2/assume.h +md5.o: $(hdrdir)/ruby/backward/2/attributes.h +md5.o: $(hdrdir)/ruby/backward/2/bool.h +md5.o: $(hdrdir)/ruby/backward/2/inttypes.h +md5.o: $(hdrdir)/ruby/backward/2/limits.h +md5.o: $(hdrdir)/ruby/backward/2/long_long.h +md5.o: $(hdrdir)/ruby/backward/2/stdalign.h +md5.o: $(hdrdir)/ruby/backward/2/stdarg.h +md5.o: $(hdrdir)/ruby/defines.h +md5.o: $(hdrdir)/ruby/intern.h +md5.o: $(hdrdir)/ruby/internal/anyargs.h +md5.o: $(hdrdir)/ruby/internal/arithmetic.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/char.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/double.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/int.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/long.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/short.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +md5.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +md5.o: $(hdrdir)/ruby/internal/assume.h +md5.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +md5.o: $(hdrdir)/ruby/internal/attr/artificial.h +md5.o: $(hdrdir)/ruby/internal/attr/cold.h +md5.o: $(hdrdir)/ruby/internal/attr/const.h +md5.o: $(hdrdir)/ruby/internal/attr/constexpr.h +md5.o: $(hdrdir)/ruby/internal/attr/deprecated.h +md5.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +md5.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +md5.o: $(hdrdir)/ruby/internal/attr/error.h +md5.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +md5.o: $(hdrdir)/ruby/internal/attr/forceinline.h +md5.o: $(hdrdir)/ruby/internal/attr/format.h +md5.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +md5.o: $(hdrdir)/ruby/internal/attr/noalias.h +md5.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +md5.o: $(hdrdir)/ruby/internal/attr/noexcept.h +md5.o: $(hdrdir)/ruby/internal/attr/noinline.h +md5.o: $(hdrdir)/ruby/internal/attr/nonnull.h +md5.o: $(hdrdir)/ruby/internal/attr/noreturn.h +md5.o: $(hdrdir)/ruby/internal/attr/pure.h +md5.o: $(hdrdir)/ruby/internal/attr/restrict.h +md5.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +md5.o: $(hdrdir)/ruby/internal/attr/warning.h +md5.o: $(hdrdir)/ruby/internal/attr/weakref.h +md5.o: $(hdrdir)/ruby/internal/cast.h +md5.o: $(hdrdir)/ruby/internal/compiler_is.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +md5.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +md5.o: $(hdrdir)/ruby/internal/compiler_since.h +md5.o: $(hdrdir)/ruby/internal/config.h +md5.o: $(hdrdir)/ruby/internal/constant_p.h +md5.o: $(hdrdir)/ruby/internal/core.h +md5.o: $(hdrdir)/ruby/internal/core/rarray.h +md5.o: $(hdrdir)/ruby/internal/core/rbasic.h +md5.o: $(hdrdir)/ruby/internal/core/rbignum.h +md5.o: $(hdrdir)/ruby/internal/core/rclass.h +md5.o: $(hdrdir)/ruby/internal/core/rdata.h +md5.o: $(hdrdir)/ruby/internal/core/rfile.h +md5.o: $(hdrdir)/ruby/internal/core/rhash.h +md5.o: $(hdrdir)/ruby/internal/core/robject.h +md5.o: $(hdrdir)/ruby/internal/core/rregexp.h +md5.o: $(hdrdir)/ruby/internal/core/rstring.h +md5.o: $(hdrdir)/ruby/internal/core/rstruct.h +md5.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +md5.o: $(hdrdir)/ruby/internal/ctype.h +md5.o: $(hdrdir)/ruby/internal/dllexport.h +md5.o: $(hdrdir)/ruby/internal/dosish.h +md5.o: $(hdrdir)/ruby/internal/error.h +md5.o: $(hdrdir)/ruby/internal/eval.h +md5.o: $(hdrdir)/ruby/internal/event.h +md5.o: $(hdrdir)/ruby/internal/fl_type.h +md5.o: $(hdrdir)/ruby/internal/gc.h +md5.o: $(hdrdir)/ruby/internal/glob.h +md5.o: $(hdrdir)/ruby/internal/globals.h +md5.o: $(hdrdir)/ruby/internal/has/attribute.h +md5.o: $(hdrdir)/ruby/internal/has/builtin.h +md5.o: $(hdrdir)/ruby/internal/has/c_attribute.h +md5.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +md5.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +md5.o: $(hdrdir)/ruby/internal/has/extension.h +md5.o: $(hdrdir)/ruby/internal/has/feature.h +md5.o: $(hdrdir)/ruby/internal/has/warning.h +md5.o: $(hdrdir)/ruby/internal/intern/array.h +md5.o: $(hdrdir)/ruby/internal/intern/bignum.h +md5.o: $(hdrdir)/ruby/internal/intern/class.h +md5.o: $(hdrdir)/ruby/internal/intern/compar.h +md5.o: $(hdrdir)/ruby/internal/intern/complex.h +md5.o: $(hdrdir)/ruby/internal/intern/cont.h +md5.o: $(hdrdir)/ruby/internal/intern/dir.h +md5.o: $(hdrdir)/ruby/internal/intern/enum.h +md5.o: $(hdrdir)/ruby/internal/intern/enumerator.h +md5.o: $(hdrdir)/ruby/internal/intern/error.h +md5.o: $(hdrdir)/ruby/internal/intern/eval.h +md5.o: $(hdrdir)/ruby/internal/intern/file.h +md5.o: $(hdrdir)/ruby/internal/intern/gc.h +md5.o: $(hdrdir)/ruby/internal/intern/hash.h +md5.o: $(hdrdir)/ruby/internal/intern/io.h +md5.o: $(hdrdir)/ruby/internal/intern/load.h +md5.o: $(hdrdir)/ruby/internal/intern/marshal.h +md5.o: $(hdrdir)/ruby/internal/intern/numeric.h +md5.o: $(hdrdir)/ruby/internal/intern/object.h +md5.o: $(hdrdir)/ruby/internal/intern/parse.h +md5.o: $(hdrdir)/ruby/internal/intern/proc.h +md5.o: $(hdrdir)/ruby/internal/intern/process.h +md5.o: $(hdrdir)/ruby/internal/intern/random.h +md5.o: $(hdrdir)/ruby/internal/intern/range.h +md5.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +md5.o: $(hdrdir)/ruby/internal/intern/sprintf.h +md5.o: $(hdrdir)/ruby/internal/intern/string.h +md5.o: $(hdrdir)/ruby/internal/intern/struct.h +md5.o: $(hdrdir)/ruby/internal/intern/thread.h +md5.o: $(hdrdir)/ruby/internal/intern/time.h +md5.o: $(hdrdir)/ruby/internal/intern/variable.h +md5.o: $(hdrdir)/ruby/internal/intern/vm.h +md5.o: $(hdrdir)/ruby/internal/interpreter.h +md5.o: $(hdrdir)/ruby/internal/iterator.h +md5.o: $(hdrdir)/ruby/internal/memory.h +md5.o: $(hdrdir)/ruby/internal/method.h +md5.o: $(hdrdir)/ruby/internal/module.h +md5.o: $(hdrdir)/ruby/internal/newobj.h +md5.o: $(hdrdir)/ruby/internal/rgengc.h +md5.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +md5.o: $(hdrdir)/ruby/internal/value.h +md5.o: $(hdrdir)/ruby/internal/value_type.h +md5.o: $(hdrdir)/ruby/internal/variable.h +md5.o: $(hdrdir)/ruby/internal/warning_push.h +md5.o: $(hdrdir)/ruby/internal/xmalloc.h +md5.o: $(hdrdir)/ruby/missing.h +md5.o: $(hdrdir)/ruby/ruby.h +md5.o: $(hdrdir)/ruby/st.h +md5.o: $(hdrdir)/ruby/subst.h +md5.o: $(srcdir)/../defs.h +md5.o: md5.c +md5.o: md5.h md5init.o: $(RUBY_EXTCONF_H) md5init.o: $(arch_hdrdir)/ruby/config.h md5init.o: $(hdrdir)/ruby.h md5init.o: $(hdrdir)/ruby/assert.h md5init.o: $(hdrdir)/ruby/backward.h +md5init.o: $(hdrdir)/ruby/backward/2/assume.h +md5init.o: $(hdrdir)/ruby/backward/2/attributes.h +md5init.o: $(hdrdir)/ruby/backward/2/bool.h +md5init.o: $(hdrdir)/ruby/backward/2/inttypes.h +md5init.o: $(hdrdir)/ruby/backward/2/limits.h +md5init.o: $(hdrdir)/ruby/backward/2/long_long.h +md5init.o: $(hdrdir)/ruby/backward/2/stdalign.h +md5init.o: $(hdrdir)/ruby/backward/2/stdarg.h md5init.o: $(hdrdir)/ruby/defines.h md5init.o: $(hdrdir)/ruby/intern.h +md5init.o: $(hdrdir)/ruby/internal/anyargs.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +md5init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +md5init.o: $(hdrdir)/ruby/internal/assume.h +md5init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +md5init.o: $(hdrdir)/ruby/internal/attr/artificial.h +md5init.o: $(hdrdir)/ruby/internal/attr/cold.h +md5init.o: $(hdrdir)/ruby/internal/attr/const.h +md5init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +md5init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +md5init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +md5init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +md5init.o: $(hdrdir)/ruby/internal/attr/error.h +md5init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +md5init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +md5init.o: $(hdrdir)/ruby/internal/attr/format.h +md5init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +md5init.o: $(hdrdir)/ruby/internal/attr/noalias.h +md5init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +md5init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +md5init.o: $(hdrdir)/ruby/internal/attr/noinline.h +md5init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +md5init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +md5init.o: $(hdrdir)/ruby/internal/attr/pure.h +md5init.o: $(hdrdir)/ruby/internal/attr/restrict.h +md5init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +md5init.o: $(hdrdir)/ruby/internal/attr/warning.h +md5init.o: $(hdrdir)/ruby/internal/attr/weakref.h +md5init.o: $(hdrdir)/ruby/internal/cast.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +md5init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +md5init.o: $(hdrdir)/ruby/internal/compiler_since.h +md5init.o: $(hdrdir)/ruby/internal/config.h +md5init.o: $(hdrdir)/ruby/internal/constant_p.h +md5init.o: $(hdrdir)/ruby/internal/core.h +md5init.o: $(hdrdir)/ruby/internal/core/rarray.h +md5init.o: $(hdrdir)/ruby/internal/core/rbasic.h +md5init.o: $(hdrdir)/ruby/internal/core/rbignum.h +md5init.o: $(hdrdir)/ruby/internal/core/rclass.h +md5init.o: $(hdrdir)/ruby/internal/core/rdata.h +md5init.o: $(hdrdir)/ruby/internal/core/rfile.h +md5init.o: $(hdrdir)/ruby/internal/core/rhash.h +md5init.o: $(hdrdir)/ruby/internal/core/robject.h +md5init.o: $(hdrdir)/ruby/internal/core/rregexp.h +md5init.o: $(hdrdir)/ruby/internal/core/rstring.h +md5init.o: $(hdrdir)/ruby/internal/core/rstruct.h +md5init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +md5init.o: $(hdrdir)/ruby/internal/ctype.h +md5init.o: $(hdrdir)/ruby/internal/dllexport.h +md5init.o: $(hdrdir)/ruby/internal/dosish.h +md5init.o: $(hdrdir)/ruby/internal/error.h +md5init.o: $(hdrdir)/ruby/internal/eval.h +md5init.o: $(hdrdir)/ruby/internal/event.h +md5init.o: $(hdrdir)/ruby/internal/fl_type.h +md5init.o: $(hdrdir)/ruby/internal/gc.h +md5init.o: $(hdrdir)/ruby/internal/glob.h +md5init.o: $(hdrdir)/ruby/internal/globals.h +md5init.o: $(hdrdir)/ruby/internal/has/attribute.h +md5init.o: $(hdrdir)/ruby/internal/has/builtin.h +md5init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +md5init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +md5init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +md5init.o: $(hdrdir)/ruby/internal/has/extension.h +md5init.o: $(hdrdir)/ruby/internal/has/feature.h +md5init.o: $(hdrdir)/ruby/internal/has/warning.h +md5init.o: $(hdrdir)/ruby/internal/intern/array.h +md5init.o: $(hdrdir)/ruby/internal/intern/bignum.h +md5init.o: $(hdrdir)/ruby/internal/intern/class.h +md5init.o: $(hdrdir)/ruby/internal/intern/compar.h +md5init.o: $(hdrdir)/ruby/internal/intern/complex.h +md5init.o: $(hdrdir)/ruby/internal/intern/cont.h +md5init.o: $(hdrdir)/ruby/internal/intern/dir.h +md5init.o: $(hdrdir)/ruby/internal/intern/enum.h +md5init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +md5init.o: $(hdrdir)/ruby/internal/intern/error.h +md5init.o: $(hdrdir)/ruby/internal/intern/eval.h +md5init.o: $(hdrdir)/ruby/internal/intern/file.h +md5init.o: $(hdrdir)/ruby/internal/intern/gc.h +md5init.o: $(hdrdir)/ruby/internal/intern/hash.h +md5init.o: $(hdrdir)/ruby/internal/intern/io.h +md5init.o: $(hdrdir)/ruby/internal/intern/load.h +md5init.o: $(hdrdir)/ruby/internal/intern/marshal.h +md5init.o: $(hdrdir)/ruby/internal/intern/numeric.h +md5init.o: $(hdrdir)/ruby/internal/intern/object.h +md5init.o: $(hdrdir)/ruby/internal/intern/parse.h +md5init.o: $(hdrdir)/ruby/internal/intern/proc.h +md5init.o: $(hdrdir)/ruby/internal/intern/process.h +md5init.o: $(hdrdir)/ruby/internal/intern/random.h +md5init.o: $(hdrdir)/ruby/internal/intern/range.h +md5init.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +md5init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +md5init.o: $(hdrdir)/ruby/internal/intern/string.h +md5init.o: $(hdrdir)/ruby/internal/intern/struct.h +md5init.o: $(hdrdir)/ruby/internal/intern/thread.h +md5init.o: $(hdrdir)/ruby/internal/intern/time.h +md5init.o: $(hdrdir)/ruby/internal/intern/variable.h +md5init.o: $(hdrdir)/ruby/internal/intern/vm.h +md5init.o: $(hdrdir)/ruby/internal/interpreter.h +md5init.o: $(hdrdir)/ruby/internal/iterator.h +md5init.o: $(hdrdir)/ruby/internal/memory.h +md5init.o: $(hdrdir)/ruby/internal/method.h +md5init.o: $(hdrdir)/ruby/internal/module.h +md5init.o: $(hdrdir)/ruby/internal/newobj.h +md5init.o: $(hdrdir)/ruby/internal/rgengc.h +md5init.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +md5init.o: $(hdrdir)/ruby/internal/value.h +md5init.o: $(hdrdir)/ruby/internal/value_type.h +md5init.o: $(hdrdir)/ruby/internal/variable.h +md5init.o: $(hdrdir)/ruby/internal/warning_push.h +md5init.o: $(hdrdir)/ruby/internal/xmalloc.h md5init.o: $(hdrdir)/ruby/missing.h md5init.o: $(hdrdir)/ruby/ruby.h md5init.o: $(hdrdir)/ruby/st.h md5init.o: $(hdrdir)/ruby/subst.h +md5init.o: $(srcdir)/../defs.h md5init.o: $(srcdir)/../digest.h +md5init.o: md5.h md5init.o: md5init.c -md5init.o: md5ossl.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/digest/md5/extconf.rb b/ruby/ext/digest/md5/extconf.rb index dead9a228..01658e1b6 100644 --- a/ruby/ext/digest/md5/extconf.rb +++ b/ruby/ext/digest/md5/extconf.rb @@ -6,8 +6,6 @@ require "mkmf" require File.expand_path("../../digest_conf", __FILE__) -$defs << "-DHAVE_CONFIG_H" - $objs = [ "md5init.#{$OBJEXT}" ] digest_conf("md5") diff --git a/ruby/ext/digest/md5/md5.c b/ruby/ext/digest/md5/md5.c index 19fe54a69..3a7fe2cda 100644 --- a/ruby/ext/digest/md5/md5.c +++ b/ruby/ext/digest/md5/md5.c @@ -225,7 +225,7 @@ md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/) uint32_t xbuf[16]; const uint32_t *X; - if (!((data - (const uint8_t *)0) & 3)) { + if (!(((uintptr_t)data) & 3)) { /* data are properly aligned */ X = (const uint32_t *)data; } else { diff --git a/ruby/ext/digest/md5/md5init.c b/ruby/ext/digest/md5/md5init.c index dafd38a29..52cba78bf 100644 --- a/ruby/ext/digest/md5/md5init.c +++ b/ruby/ext/digest/md5/md5init.c @@ -3,9 +3,7 @@ #include #include "../digest.h" -#if defined(MD5_USE_OPENSSL) -#include "md5ossl.h" -#elif defined(MD5_USE_COMMONDIGEST) +#if defined(MD5_USE_COMMONDIGEST) #include "md5cc.h" #else #include "md5.h" @@ -59,8 +57,5 @@ Init_md5(void) cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - rb_iv_set(cDigest_MD5, "metadata", - Data_Wrap_Struct(0, 0, 0, (void *)&md5)); + rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5)); } diff --git a/ruby/ext/digest/md5/md5ossl.h b/ruby/ext/digest/md5/md5ossl.h deleted file mode 100644 index 94aa7ae77..000000000 --- a/ruby/ext/digest/md5/md5ossl.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id$ */ - -#ifndef MD5OSSL_H_INCLUDED -#define MD5OSSL_H_INCLUDED - -#include -#include - -#define MD5_BLOCK_LENGTH MD5_CBLOCK - -static DEFINE_FINISH_FUNC_FROM_FINAL(MD5) -#undef MD5_Finish -#define MD5_Finish rb_digest_MD5_finish - -#endif diff --git a/ruby/ext/digest/rmd160/depend b/ruby/ext/digest/rmd160/depend index 07c406a7d..fe3652a2f 100644 --- a/ruby/ext/digest/rmd160/depend +++ b/ruby/ext/digest/rmd160/depend @@ -2,18 +2,327 @@ rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h rmd160init.o: $(LOCAL_HDRS) # AUTOGENERATED DEPENDENCIES START +rmd160.o: $(RUBY_EXTCONF_H) +rmd160.o: $(arch_hdrdir)/ruby/config.h +rmd160.o: $(hdrdir)/ruby.h +rmd160.o: $(hdrdir)/ruby/assert.h +rmd160.o: $(hdrdir)/ruby/backward.h +rmd160.o: $(hdrdir)/ruby/backward/2/assume.h +rmd160.o: $(hdrdir)/ruby/backward/2/attributes.h +rmd160.o: $(hdrdir)/ruby/backward/2/bool.h +rmd160.o: $(hdrdir)/ruby/backward/2/inttypes.h +rmd160.o: $(hdrdir)/ruby/backward/2/limits.h +rmd160.o: $(hdrdir)/ruby/backward/2/long_long.h +rmd160.o: $(hdrdir)/ruby/backward/2/stdalign.h +rmd160.o: $(hdrdir)/ruby/backward/2/stdarg.h +rmd160.o: $(hdrdir)/ruby/defines.h +rmd160.o: $(hdrdir)/ruby/intern.h +rmd160.o: $(hdrdir)/ruby/internal/anyargs.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rmd160.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rmd160.o: $(hdrdir)/ruby/internal/assume.h +rmd160.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rmd160.o: $(hdrdir)/ruby/internal/attr/artificial.h +rmd160.o: $(hdrdir)/ruby/internal/attr/cold.h +rmd160.o: $(hdrdir)/ruby/internal/attr/const.h +rmd160.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rmd160.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rmd160.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rmd160.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rmd160.o: $(hdrdir)/ruby/internal/attr/error.h +rmd160.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rmd160.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rmd160.o: $(hdrdir)/ruby/internal/attr/format.h +rmd160.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rmd160.o: $(hdrdir)/ruby/internal/attr/noalias.h +rmd160.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rmd160.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rmd160.o: $(hdrdir)/ruby/internal/attr/noinline.h +rmd160.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rmd160.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rmd160.o: $(hdrdir)/ruby/internal/attr/pure.h +rmd160.o: $(hdrdir)/ruby/internal/attr/restrict.h +rmd160.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rmd160.o: $(hdrdir)/ruby/internal/attr/warning.h +rmd160.o: $(hdrdir)/ruby/internal/attr/weakref.h +rmd160.o: $(hdrdir)/ruby/internal/cast.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rmd160.o: $(hdrdir)/ruby/internal/compiler_since.h +rmd160.o: $(hdrdir)/ruby/internal/config.h +rmd160.o: $(hdrdir)/ruby/internal/constant_p.h +rmd160.o: $(hdrdir)/ruby/internal/core.h +rmd160.o: $(hdrdir)/ruby/internal/core/rarray.h +rmd160.o: $(hdrdir)/ruby/internal/core/rbasic.h +rmd160.o: $(hdrdir)/ruby/internal/core/rbignum.h +rmd160.o: $(hdrdir)/ruby/internal/core/rclass.h +rmd160.o: $(hdrdir)/ruby/internal/core/rdata.h +rmd160.o: $(hdrdir)/ruby/internal/core/rfile.h +rmd160.o: $(hdrdir)/ruby/internal/core/rhash.h +rmd160.o: $(hdrdir)/ruby/internal/core/robject.h +rmd160.o: $(hdrdir)/ruby/internal/core/rregexp.h +rmd160.o: $(hdrdir)/ruby/internal/core/rstring.h +rmd160.o: $(hdrdir)/ruby/internal/core/rstruct.h +rmd160.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rmd160.o: $(hdrdir)/ruby/internal/ctype.h +rmd160.o: $(hdrdir)/ruby/internal/dllexport.h +rmd160.o: $(hdrdir)/ruby/internal/dosish.h +rmd160.o: $(hdrdir)/ruby/internal/error.h +rmd160.o: $(hdrdir)/ruby/internal/eval.h +rmd160.o: $(hdrdir)/ruby/internal/event.h +rmd160.o: $(hdrdir)/ruby/internal/fl_type.h +rmd160.o: $(hdrdir)/ruby/internal/gc.h +rmd160.o: $(hdrdir)/ruby/internal/glob.h +rmd160.o: $(hdrdir)/ruby/internal/globals.h +rmd160.o: $(hdrdir)/ruby/internal/has/attribute.h +rmd160.o: $(hdrdir)/ruby/internal/has/builtin.h +rmd160.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rmd160.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rmd160.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rmd160.o: $(hdrdir)/ruby/internal/has/extension.h +rmd160.o: $(hdrdir)/ruby/internal/has/feature.h +rmd160.o: $(hdrdir)/ruby/internal/has/warning.h +rmd160.o: $(hdrdir)/ruby/internal/intern/array.h +rmd160.o: $(hdrdir)/ruby/internal/intern/bignum.h +rmd160.o: $(hdrdir)/ruby/internal/intern/class.h +rmd160.o: $(hdrdir)/ruby/internal/intern/compar.h +rmd160.o: $(hdrdir)/ruby/internal/intern/complex.h +rmd160.o: $(hdrdir)/ruby/internal/intern/cont.h +rmd160.o: $(hdrdir)/ruby/internal/intern/dir.h +rmd160.o: $(hdrdir)/ruby/internal/intern/enum.h +rmd160.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rmd160.o: $(hdrdir)/ruby/internal/intern/error.h +rmd160.o: $(hdrdir)/ruby/internal/intern/eval.h +rmd160.o: $(hdrdir)/ruby/internal/intern/file.h +rmd160.o: $(hdrdir)/ruby/internal/intern/gc.h +rmd160.o: $(hdrdir)/ruby/internal/intern/hash.h +rmd160.o: $(hdrdir)/ruby/internal/intern/io.h +rmd160.o: $(hdrdir)/ruby/internal/intern/load.h +rmd160.o: $(hdrdir)/ruby/internal/intern/marshal.h +rmd160.o: $(hdrdir)/ruby/internal/intern/numeric.h +rmd160.o: $(hdrdir)/ruby/internal/intern/object.h +rmd160.o: $(hdrdir)/ruby/internal/intern/parse.h +rmd160.o: $(hdrdir)/ruby/internal/intern/proc.h +rmd160.o: $(hdrdir)/ruby/internal/intern/process.h +rmd160.o: $(hdrdir)/ruby/internal/intern/random.h +rmd160.o: $(hdrdir)/ruby/internal/intern/range.h +rmd160.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rmd160.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rmd160.o: $(hdrdir)/ruby/internal/intern/string.h +rmd160.o: $(hdrdir)/ruby/internal/intern/struct.h +rmd160.o: $(hdrdir)/ruby/internal/intern/thread.h +rmd160.o: $(hdrdir)/ruby/internal/intern/time.h +rmd160.o: $(hdrdir)/ruby/internal/intern/variable.h +rmd160.o: $(hdrdir)/ruby/internal/intern/vm.h +rmd160.o: $(hdrdir)/ruby/internal/interpreter.h +rmd160.o: $(hdrdir)/ruby/internal/iterator.h +rmd160.o: $(hdrdir)/ruby/internal/memory.h +rmd160.o: $(hdrdir)/ruby/internal/method.h +rmd160.o: $(hdrdir)/ruby/internal/module.h +rmd160.o: $(hdrdir)/ruby/internal/newobj.h +rmd160.o: $(hdrdir)/ruby/internal/rgengc.h +rmd160.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rmd160.o: $(hdrdir)/ruby/internal/value.h +rmd160.o: $(hdrdir)/ruby/internal/value_type.h +rmd160.o: $(hdrdir)/ruby/internal/variable.h +rmd160.o: $(hdrdir)/ruby/internal/warning_push.h +rmd160.o: $(hdrdir)/ruby/internal/xmalloc.h +rmd160.o: $(hdrdir)/ruby/missing.h +rmd160.o: $(hdrdir)/ruby/ruby.h +rmd160.o: $(hdrdir)/ruby/st.h +rmd160.o: $(hdrdir)/ruby/subst.h +rmd160.o: $(srcdir)/../defs.h +rmd160.o: rmd160.c +rmd160.o: rmd160.h rmd160init.o: $(RUBY_EXTCONF_H) rmd160init.o: $(arch_hdrdir)/ruby/config.h rmd160init.o: $(hdrdir)/ruby.h rmd160init.o: $(hdrdir)/ruby/assert.h rmd160init.o: $(hdrdir)/ruby/backward.h +rmd160init.o: $(hdrdir)/ruby/backward/2/assume.h +rmd160init.o: $(hdrdir)/ruby/backward/2/attributes.h +rmd160init.o: $(hdrdir)/ruby/backward/2/bool.h +rmd160init.o: $(hdrdir)/ruby/backward/2/inttypes.h +rmd160init.o: $(hdrdir)/ruby/backward/2/limits.h +rmd160init.o: $(hdrdir)/ruby/backward/2/long_long.h +rmd160init.o: $(hdrdir)/ruby/backward/2/stdalign.h +rmd160init.o: $(hdrdir)/ruby/backward/2/stdarg.h rmd160init.o: $(hdrdir)/ruby/defines.h rmd160init.o: $(hdrdir)/ruby/intern.h +rmd160init.o: $(hdrdir)/ruby/internal/anyargs.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +rmd160init.o: $(hdrdir)/ruby/internal/assume.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/artificial.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/cold.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/const.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/error.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/format.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/noalias.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/noinline.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/pure.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/restrict.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/warning.h +rmd160init.o: $(hdrdir)/ruby/internal/attr/weakref.h +rmd160init.o: $(hdrdir)/ruby/internal/cast.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +rmd160init.o: $(hdrdir)/ruby/internal/compiler_since.h +rmd160init.o: $(hdrdir)/ruby/internal/config.h +rmd160init.o: $(hdrdir)/ruby/internal/constant_p.h +rmd160init.o: $(hdrdir)/ruby/internal/core.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rarray.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rbasic.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rbignum.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rclass.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rdata.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rfile.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rhash.h +rmd160init.o: $(hdrdir)/ruby/internal/core/robject.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rregexp.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rstring.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rstruct.h +rmd160init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +rmd160init.o: $(hdrdir)/ruby/internal/ctype.h +rmd160init.o: $(hdrdir)/ruby/internal/dllexport.h +rmd160init.o: $(hdrdir)/ruby/internal/dosish.h +rmd160init.o: $(hdrdir)/ruby/internal/error.h +rmd160init.o: $(hdrdir)/ruby/internal/eval.h +rmd160init.o: $(hdrdir)/ruby/internal/event.h +rmd160init.o: $(hdrdir)/ruby/internal/fl_type.h +rmd160init.o: $(hdrdir)/ruby/internal/gc.h +rmd160init.o: $(hdrdir)/ruby/internal/glob.h +rmd160init.o: $(hdrdir)/ruby/internal/globals.h +rmd160init.o: $(hdrdir)/ruby/internal/has/attribute.h +rmd160init.o: $(hdrdir)/ruby/internal/has/builtin.h +rmd160init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +rmd160init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +rmd160init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +rmd160init.o: $(hdrdir)/ruby/internal/has/extension.h +rmd160init.o: $(hdrdir)/ruby/internal/has/feature.h +rmd160init.o: $(hdrdir)/ruby/internal/has/warning.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/array.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/bignum.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/class.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/compar.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/complex.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/cont.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/dir.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/enum.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/error.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/eval.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/file.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/gc.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/hash.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/io.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/load.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/marshal.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/numeric.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/object.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/parse.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/proc.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/process.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/random.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/range.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/string.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/struct.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/thread.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/time.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/variable.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/vm.h +rmd160init.o: $(hdrdir)/ruby/internal/interpreter.h +rmd160init.o: $(hdrdir)/ruby/internal/iterator.h +rmd160init.o: $(hdrdir)/ruby/internal/memory.h +rmd160init.o: $(hdrdir)/ruby/internal/method.h +rmd160init.o: $(hdrdir)/ruby/internal/module.h +rmd160init.o: $(hdrdir)/ruby/internal/newobj.h +rmd160init.o: $(hdrdir)/ruby/internal/rgengc.h +rmd160init.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +rmd160init.o: $(hdrdir)/ruby/internal/value.h +rmd160init.o: $(hdrdir)/ruby/internal/value_type.h +rmd160init.o: $(hdrdir)/ruby/internal/variable.h +rmd160init.o: $(hdrdir)/ruby/internal/warning_push.h +rmd160init.o: $(hdrdir)/ruby/internal/xmalloc.h rmd160init.o: $(hdrdir)/ruby/missing.h rmd160init.o: $(hdrdir)/ruby/ruby.h rmd160init.o: $(hdrdir)/ruby/st.h rmd160init.o: $(hdrdir)/ruby/subst.h +rmd160init.o: $(srcdir)/../defs.h rmd160init.o: $(srcdir)/../digest.h +rmd160init.o: rmd160.h rmd160init.o: rmd160init.c -rmd160init.o: rmd160ossl.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/digest/rmd160/extconf.rb b/ruby/ext/digest/rmd160/extconf.rb index a02ba5616..8b894da0c 100644 --- a/ruby/ext/digest/rmd160/extconf.rb +++ b/ruby/ext/digest/rmd160/extconf.rb @@ -6,11 +6,13 @@ require "mkmf" require File.expand_path("../../digest_conf", __FILE__) -$defs << "-DNDEBUG" << "-DHAVE_CONFIG_H" +if try_static_assert("RUBY_API_VERSION_MAJOR < 3", "ruby/version.h") + $defs << "-DNDEBUG" +end $objs = [ "rmd160init.#{$OBJEXT}" ] -digest_conf("rmd160", "ripemd", "RIPEMD160") +digest_conf("rmd160") have_header("sys/cdefs.h") diff --git a/ruby/ext/digest/rmd160/rmd160init.c b/ruby/ext/digest/rmd160/rmd160init.c index a2c0a023c..2ae81ec4d 100644 --- a/ruby/ext/digest/rmd160/rmd160init.c +++ b/ruby/ext/digest/rmd160/rmd160init.c @@ -3,11 +3,7 @@ #include #include "../digest.h" -#if defined(RMD160_USE_OPENSSL) -#include "rmd160ossl.h" -#else #include "rmd160.h" -#endif static const rb_digest_metadata_t rmd160 = { RUBY_DIGEST_API_VERSION, @@ -57,8 +53,5 @@ Init_rmd160(void) cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base); -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - rb_iv_set(cDigest_RMD160, "metadata", - Data_Wrap_Struct(0, 0, 0, (void *)&rmd160)); + rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160)); } diff --git a/ruby/ext/digest/rmd160/rmd160ossl.h b/ruby/ext/digest/rmd160/rmd160ossl.h deleted file mode 100644 index e6bf5ea8d..000000000 --- a/ruby/ext/digest/rmd160/rmd160ossl.h +++ /dev/null @@ -1,20 +0,0 @@ -/* $Id$ */ - -#ifndef RMD160OSSL_H_INCLUDED -#define RMD160OSSL_H_INCLUDED - -#include -#include - -#define RMD160_CTX RIPEMD160_CTX - -#define RMD160_Init RIPEMD160_Init -#define RMD160_Update RIPEMD160_Update - -#define RMD160_BLOCK_LENGTH RIPEMD160_CBLOCK -#define RMD160_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH - -static DEFINE_FINISH_FUNC_FROM_FINAL(RIPEMD160) -#define RMD160_Finish rb_digest_RIPEMD160_finish - -#endif diff --git a/ruby/ext/digest/sha1/depend b/ruby/ext/digest/sha1/depend index bc9e216ee..2b73455c0 100644 --- a/ruby/ext/digest/sha1/depend +++ b/ruby/ext/digest/sha1/depend @@ -2,18 +2,327 @@ sha1.o: sha1.c sha1.h $(srcdir)/../defs.h sha1init.o: $(LOCAL_HDRS) # AUTOGENERATED DEPENDENCIES START +sha1.o: $(RUBY_EXTCONF_H) +sha1.o: $(arch_hdrdir)/ruby/config.h +sha1.o: $(hdrdir)/ruby.h +sha1.o: $(hdrdir)/ruby/assert.h +sha1.o: $(hdrdir)/ruby/backward.h +sha1.o: $(hdrdir)/ruby/backward/2/assume.h +sha1.o: $(hdrdir)/ruby/backward/2/attributes.h +sha1.o: $(hdrdir)/ruby/backward/2/bool.h +sha1.o: $(hdrdir)/ruby/backward/2/inttypes.h +sha1.o: $(hdrdir)/ruby/backward/2/limits.h +sha1.o: $(hdrdir)/ruby/backward/2/long_long.h +sha1.o: $(hdrdir)/ruby/backward/2/stdalign.h +sha1.o: $(hdrdir)/ruby/backward/2/stdarg.h +sha1.o: $(hdrdir)/ruby/defines.h +sha1.o: $(hdrdir)/ruby/intern.h +sha1.o: $(hdrdir)/ruby/internal/anyargs.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sha1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sha1.o: $(hdrdir)/ruby/internal/assume.h +sha1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sha1.o: $(hdrdir)/ruby/internal/attr/artificial.h +sha1.o: $(hdrdir)/ruby/internal/attr/cold.h +sha1.o: $(hdrdir)/ruby/internal/attr/const.h +sha1.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sha1.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sha1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sha1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sha1.o: $(hdrdir)/ruby/internal/attr/error.h +sha1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sha1.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sha1.o: $(hdrdir)/ruby/internal/attr/format.h +sha1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sha1.o: $(hdrdir)/ruby/internal/attr/noalias.h +sha1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sha1.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sha1.o: $(hdrdir)/ruby/internal/attr/noinline.h +sha1.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sha1.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sha1.o: $(hdrdir)/ruby/internal/attr/pure.h +sha1.o: $(hdrdir)/ruby/internal/attr/restrict.h +sha1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sha1.o: $(hdrdir)/ruby/internal/attr/warning.h +sha1.o: $(hdrdir)/ruby/internal/attr/weakref.h +sha1.o: $(hdrdir)/ruby/internal/cast.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sha1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sha1.o: $(hdrdir)/ruby/internal/compiler_since.h +sha1.o: $(hdrdir)/ruby/internal/config.h +sha1.o: $(hdrdir)/ruby/internal/constant_p.h +sha1.o: $(hdrdir)/ruby/internal/core.h +sha1.o: $(hdrdir)/ruby/internal/core/rarray.h +sha1.o: $(hdrdir)/ruby/internal/core/rbasic.h +sha1.o: $(hdrdir)/ruby/internal/core/rbignum.h +sha1.o: $(hdrdir)/ruby/internal/core/rclass.h +sha1.o: $(hdrdir)/ruby/internal/core/rdata.h +sha1.o: $(hdrdir)/ruby/internal/core/rfile.h +sha1.o: $(hdrdir)/ruby/internal/core/rhash.h +sha1.o: $(hdrdir)/ruby/internal/core/robject.h +sha1.o: $(hdrdir)/ruby/internal/core/rregexp.h +sha1.o: $(hdrdir)/ruby/internal/core/rstring.h +sha1.o: $(hdrdir)/ruby/internal/core/rstruct.h +sha1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sha1.o: $(hdrdir)/ruby/internal/ctype.h +sha1.o: $(hdrdir)/ruby/internal/dllexport.h +sha1.o: $(hdrdir)/ruby/internal/dosish.h +sha1.o: $(hdrdir)/ruby/internal/error.h +sha1.o: $(hdrdir)/ruby/internal/eval.h +sha1.o: $(hdrdir)/ruby/internal/event.h +sha1.o: $(hdrdir)/ruby/internal/fl_type.h +sha1.o: $(hdrdir)/ruby/internal/gc.h +sha1.o: $(hdrdir)/ruby/internal/glob.h +sha1.o: $(hdrdir)/ruby/internal/globals.h +sha1.o: $(hdrdir)/ruby/internal/has/attribute.h +sha1.o: $(hdrdir)/ruby/internal/has/builtin.h +sha1.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sha1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sha1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sha1.o: $(hdrdir)/ruby/internal/has/extension.h +sha1.o: $(hdrdir)/ruby/internal/has/feature.h +sha1.o: $(hdrdir)/ruby/internal/has/warning.h +sha1.o: $(hdrdir)/ruby/internal/intern/array.h +sha1.o: $(hdrdir)/ruby/internal/intern/bignum.h +sha1.o: $(hdrdir)/ruby/internal/intern/class.h +sha1.o: $(hdrdir)/ruby/internal/intern/compar.h +sha1.o: $(hdrdir)/ruby/internal/intern/complex.h +sha1.o: $(hdrdir)/ruby/internal/intern/cont.h +sha1.o: $(hdrdir)/ruby/internal/intern/dir.h +sha1.o: $(hdrdir)/ruby/internal/intern/enum.h +sha1.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sha1.o: $(hdrdir)/ruby/internal/intern/error.h +sha1.o: $(hdrdir)/ruby/internal/intern/eval.h +sha1.o: $(hdrdir)/ruby/internal/intern/file.h +sha1.o: $(hdrdir)/ruby/internal/intern/gc.h +sha1.o: $(hdrdir)/ruby/internal/intern/hash.h +sha1.o: $(hdrdir)/ruby/internal/intern/io.h +sha1.o: $(hdrdir)/ruby/internal/intern/load.h +sha1.o: $(hdrdir)/ruby/internal/intern/marshal.h +sha1.o: $(hdrdir)/ruby/internal/intern/numeric.h +sha1.o: $(hdrdir)/ruby/internal/intern/object.h +sha1.o: $(hdrdir)/ruby/internal/intern/parse.h +sha1.o: $(hdrdir)/ruby/internal/intern/proc.h +sha1.o: $(hdrdir)/ruby/internal/intern/process.h +sha1.o: $(hdrdir)/ruby/internal/intern/random.h +sha1.o: $(hdrdir)/ruby/internal/intern/range.h +sha1.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +sha1.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sha1.o: $(hdrdir)/ruby/internal/intern/string.h +sha1.o: $(hdrdir)/ruby/internal/intern/struct.h +sha1.o: $(hdrdir)/ruby/internal/intern/thread.h +sha1.o: $(hdrdir)/ruby/internal/intern/time.h +sha1.o: $(hdrdir)/ruby/internal/intern/variable.h +sha1.o: $(hdrdir)/ruby/internal/intern/vm.h +sha1.o: $(hdrdir)/ruby/internal/interpreter.h +sha1.o: $(hdrdir)/ruby/internal/iterator.h +sha1.o: $(hdrdir)/ruby/internal/memory.h +sha1.o: $(hdrdir)/ruby/internal/method.h +sha1.o: $(hdrdir)/ruby/internal/module.h +sha1.o: $(hdrdir)/ruby/internal/newobj.h +sha1.o: $(hdrdir)/ruby/internal/rgengc.h +sha1.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +sha1.o: $(hdrdir)/ruby/internal/value.h +sha1.o: $(hdrdir)/ruby/internal/value_type.h +sha1.o: $(hdrdir)/ruby/internal/variable.h +sha1.o: $(hdrdir)/ruby/internal/warning_push.h +sha1.o: $(hdrdir)/ruby/internal/xmalloc.h +sha1.o: $(hdrdir)/ruby/missing.h +sha1.o: $(hdrdir)/ruby/ruby.h +sha1.o: $(hdrdir)/ruby/st.h +sha1.o: $(hdrdir)/ruby/subst.h +sha1.o: $(srcdir)/../defs.h +sha1.o: sha1.c +sha1.o: sha1.h sha1init.o: $(RUBY_EXTCONF_H) sha1init.o: $(arch_hdrdir)/ruby/config.h sha1init.o: $(hdrdir)/ruby.h sha1init.o: $(hdrdir)/ruby/assert.h sha1init.o: $(hdrdir)/ruby/backward.h +sha1init.o: $(hdrdir)/ruby/backward/2/assume.h +sha1init.o: $(hdrdir)/ruby/backward/2/attributes.h +sha1init.o: $(hdrdir)/ruby/backward/2/bool.h +sha1init.o: $(hdrdir)/ruby/backward/2/inttypes.h +sha1init.o: $(hdrdir)/ruby/backward/2/limits.h +sha1init.o: $(hdrdir)/ruby/backward/2/long_long.h +sha1init.o: $(hdrdir)/ruby/backward/2/stdalign.h +sha1init.o: $(hdrdir)/ruby/backward/2/stdarg.h sha1init.o: $(hdrdir)/ruby/defines.h sha1init.o: $(hdrdir)/ruby/intern.h +sha1init.o: $(hdrdir)/ruby/internal/anyargs.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sha1init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sha1init.o: $(hdrdir)/ruby/internal/assume.h +sha1init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sha1init.o: $(hdrdir)/ruby/internal/attr/artificial.h +sha1init.o: $(hdrdir)/ruby/internal/attr/cold.h +sha1init.o: $(hdrdir)/ruby/internal/attr/const.h +sha1init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sha1init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sha1init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sha1init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sha1init.o: $(hdrdir)/ruby/internal/attr/error.h +sha1init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sha1init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sha1init.o: $(hdrdir)/ruby/internal/attr/format.h +sha1init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sha1init.o: $(hdrdir)/ruby/internal/attr/noalias.h +sha1init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sha1init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sha1init.o: $(hdrdir)/ruby/internal/attr/noinline.h +sha1init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sha1init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sha1init.o: $(hdrdir)/ruby/internal/attr/pure.h +sha1init.o: $(hdrdir)/ruby/internal/attr/restrict.h +sha1init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sha1init.o: $(hdrdir)/ruby/internal/attr/warning.h +sha1init.o: $(hdrdir)/ruby/internal/attr/weakref.h +sha1init.o: $(hdrdir)/ruby/internal/cast.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sha1init.o: $(hdrdir)/ruby/internal/compiler_since.h +sha1init.o: $(hdrdir)/ruby/internal/config.h +sha1init.o: $(hdrdir)/ruby/internal/constant_p.h +sha1init.o: $(hdrdir)/ruby/internal/core.h +sha1init.o: $(hdrdir)/ruby/internal/core/rarray.h +sha1init.o: $(hdrdir)/ruby/internal/core/rbasic.h +sha1init.o: $(hdrdir)/ruby/internal/core/rbignum.h +sha1init.o: $(hdrdir)/ruby/internal/core/rclass.h +sha1init.o: $(hdrdir)/ruby/internal/core/rdata.h +sha1init.o: $(hdrdir)/ruby/internal/core/rfile.h +sha1init.o: $(hdrdir)/ruby/internal/core/rhash.h +sha1init.o: $(hdrdir)/ruby/internal/core/robject.h +sha1init.o: $(hdrdir)/ruby/internal/core/rregexp.h +sha1init.o: $(hdrdir)/ruby/internal/core/rstring.h +sha1init.o: $(hdrdir)/ruby/internal/core/rstruct.h +sha1init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sha1init.o: $(hdrdir)/ruby/internal/ctype.h +sha1init.o: $(hdrdir)/ruby/internal/dllexport.h +sha1init.o: $(hdrdir)/ruby/internal/dosish.h +sha1init.o: $(hdrdir)/ruby/internal/error.h +sha1init.o: $(hdrdir)/ruby/internal/eval.h +sha1init.o: $(hdrdir)/ruby/internal/event.h +sha1init.o: $(hdrdir)/ruby/internal/fl_type.h +sha1init.o: $(hdrdir)/ruby/internal/gc.h +sha1init.o: $(hdrdir)/ruby/internal/glob.h +sha1init.o: $(hdrdir)/ruby/internal/globals.h +sha1init.o: $(hdrdir)/ruby/internal/has/attribute.h +sha1init.o: $(hdrdir)/ruby/internal/has/builtin.h +sha1init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sha1init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sha1init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sha1init.o: $(hdrdir)/ruby/internal/has/extension.h +sha1init.o: $(hdrdir)/ruby/internal/has/feature.h +sha1init.o: $(hdrdir)/ruby/internal/has/warning.h +sha1init.o: $(hdrdir)/ruby/internal/intern/array.h +sha1init.o: $(hdrdir)/ruby/internal/intern/bignum.h +sha1init.o: $(hdrdir)/ruby/internal/intern/class.h +sha1init.o: $(hdrdir)/ruby/internal/intern/compar.h +sha1init.o: $(hdrdir)/ruby/internal/intern/complex.h +sha1init.o: $(hdrdir)/ruby/internal/intern/cont.h +sha1init.o: $(hdrdir)/ruby/internal/intern/dir.h +sha1init.o: $(hdrdir)/ruby/internal/intern/enum.h +sha1init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sha1init.o: $(hdrdir)/ruby/internal/intern/error.h +sha1init.o: $(hdrdir)/ruby/internal/intern/eval.h +sha1init.o: $(hdrdir)/ruby/internal/intern/file.h +sha1init.o: $(hdrdir)/ruby/internal/intern/gc.h +sha1init.o: $(hdrdir)/ruby/internal/intern/hash.h +sha1init.o: $(hdrdir)/ruby/internal/intern/io.h +sha1init.o: $(hdrdir)/ruby/internal/intern/load.h +sha1init.o: $(hdrdir)/ruby/internal/intern/marshal.h +sha1init.o: $(hdrdir)/ruby/internal/intern/numeric.h +sha1init.o: $(hdrdir)/ruby/internal/intern/object.h +sha1init.o: $(hdrdir)/ruby/internal/intern/parse.h +sha1init.o: $(hdrdir)/ruby/internal/intern/proc.h +sha1init.o: $(hdrdir)/ruby/internal/intern/process.h +sha1init.o: $(hdrdir)/ruby/internal/intern/random.h +sha1init.o: $(hdrdir)/ruby/internal/intern/range.h +sha1init.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +sha1init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sha1init.o: $(hdrdir)/ruby/internal/intern/string.h +sha1init.o: $(hdrdir)/ruby/internal/intern/struct.h +sha1init.o: $(hdrdir)/ruby/internal/intern/thread.h +sha1init.o: $(hdrdir)/ruby/internal/intern/time.h +sha1init.o: $(hdrdir)/ruby/internal/intern/variable.h +sha1init.o: $(hdrdir)/ruby/internal/intern/vm.h +sha1init.o: $(hdrdir)/ruby/internal/interpreter.h +sha1init.o: $(hdrdir)/ruby/internal/iterator.h +sha1init.o: $(hdrdir)/ruby/internal/memory.h +sha1init.o: $(hdrdir)/ruby/internal/method.h +sha1init.o: $(hdrdir)/ruby/internal/module.h +sha1init.o: $(hdrdir)/ruby/internal/newobj.h +sha1init.o: $(hdrdir)/ruby/internal/rgengc.h +sha1init.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +sha1init.o: $(hdrdir)/ruby/internal/value.h +sha1init.o: $(hdrdir)/ruby/internal/value_type.h +sha1init.o: $(hdrdir)/ruby/internal/variable.h +sha1init.o: $(hdrdir)/ruby/internal/warning_push.h +sha1init.o: $(hdrdir)/ruby/internal/xmalloc.h sha1init.o: $(hdrdir)/ruby/missing.h sha1init.o: $(hdrdir)/ruby/ruby.h sha1init.o: $(hdrdir)/ruby/st.h sha1init.o: $(hdrdir)/ruby/subst.h +sha1init.o: $(srcdir)/../defs.h sha1init.o: $(srcdir)/../digest.h +sha1init.o: sha1.h sha1init.o: sha1init.c -sha1init.o: sha1ossl.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/digest/sha1/extconf.rb b/ruby/ext/digest/sha1/extconf.rb index 0ff4158be..7582cd9ab 100644 --- a/ruby/ext/digest/sha1/extconf.rb +++ b/ruby/ext/digest/sha1/extconf.rb @@ -6,11 +6,9 @@ require "mkmf" require File.expand_path("../../digest_conf", __FILE__) -$defs << "-DHAVE_CONFIG_H" - $objs = [ "sha1init.#{$OBJEXT}" ] -digest_conf("sha1", "sha", nil, %w[SHA]) +digest_conf("sha1") have_header("sys/cdefs.h") diff --git a/ruby/ext/digest/sha1/sha1init.c b/ruby/ext/digest/sha1/sha1init.c index 3adf424b1..f7047bc6d 100644 --- a/ruby/ext/digest/sha1/sha1init.c +++ b/ruby/ext/digest/sha1/sha1init.c @@ -3,9 +3,7 @@ #include #include "../digest.h" -#if defined(SHA1_USE_OPENSSL) -#include "sha1ossl.h" -#elif defined(SHA1_USE_COMMONDIGEST) +#if defined(SHA1_USE_COMMONDIGEST) #include "sha1cc.h" #else #include "sha1.h" @@ -61,8 +59,5 @@ Init_sha1(void) cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base); -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - rb_iv_set(cDigest_SHA1, "metadata", - Data_Wrap_Struct(0, 0, 0, (void *)&sha1)); + rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1)); } diff --git a/ruby/ext/digest/sha1/sha1ossl.h b/ruby/ext/digest/sha1/sha1ossl.h deleted file mode 100644 index 599efe9a2..000000000 --- a/ruby/ext/digest/sha1/sha1ossl.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id$ */ - -#ifndef SHA1OSSL_H_INCLUDED -#define SHA1OSSL_H_INCLUDED - -#include -#include - -#define SHA1_CTX SHA_CTX - -#ifdef SHA_BLOCK_LENGTH -#define SHA1_BLOCK_LENGTH SHA_BLOCK_LENGTH -#else -#define SHA1_BLOCK_LENGTH SHA_CBLOCK -#endif -#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH - -static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1) -#undef SHA1_Finish -#define SHA1_Finish rb_digest_SHA1_finish - -#endif diff --git a/ruby/ext/digest/sha2/depend b/ruby/ext/digest/sha2/depend index 8946d44f3..b3e52c644 100644 --- a/ruby/ext/digest/sha2/depend +++ b/ruby/ext/digest/sha2/depend @@ -2,18 +2,326 @@ sha2.o: sha2.c sha2.h $(srcdir)/../defs.h sha2init.o: $(LOCAL_HDRS) # AUTOGENERATED DEPENDENCIES START +sha2.o: $(RUBY_EXTCONF_H) +sha2.o: $(arch_hdrdir)/ruby/config.h +sha2.o: $(hdrdir)/ruby.h +sha2.o: $(hdrdir)/ruby/assert.h +sha2.o: $(hdrdir)/ruby/backward.h +sha2.o: $(hdrdir)/ruby/backward/2/assume.h +sha2.o: $(hdrdir)/ruby/backward/2/attributes.h +sha2.o: $(hdrdir)/ruby/backward/2/bool.h +sha2.o: $(hdrdir)/ruby/backward/2/inttypes.h +sha2.o: $(hdrdir)/ruby/backward/2/limits.h +sha2.o: $(hdrdir)/ruby/backward/2/long_long.h +sha2.o: $(hdrdir)/ruby/backward/2/stdalign.h +sha2.o: $(hdrdir)/ruby/backward/2/stdarg.h +sha2.o: $(hdrdir)/ruby/defines.h +sha2.o: $(hdrdir)/ruby/intern.h +sha2.o: $(hdrdir)/ruby/internal/anyargs.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sha2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sha2.o: $(hdrdir)/ruby/internal/assume.h +sha2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sha2.o: $(hdrdir)/ruby/internal/attr/artificial.h +sha2.o: $(hdrdir)/ruby/internal/attr/cold.h +sha2.o: $(hdrdir)/ruby/internal/attr/const.h +sha2.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sha2.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sha2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sha2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sha2.o: $(hdrdir)/ruby/internal/attr/error.h +sha2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sha2.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sha2.o: $(hdrdir)/ruby/internal/attr/format.h +sha2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sha2.o: $(hdrdir)/ruby/internal/attr/noalias.h +sha2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sha2.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sha2.o: $(hdrdir)/ruby/internal/attr/noinline.h +sha2.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sha2.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sha2.o: $(hdrdir)/ruby/internal/attr/pure.h +sha2.o: $(hdrdir)/ruby/internal/attr/restrict.h +sha2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sha2.o: $(hdrdir)/ruby/internal/attr/warning.h +sha2.o: $(hdrdir)/ruby/internal/attr/weakref.h +sha2.o: $(hdrdir)/ruby/internal/cast.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sha2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sha2.o: $(hdrdir)/ruby/internal/compiler_since.h +sha2.o: $(hdrdir)/ruby/internal/config.h +sha2.o: $(hdrdir)/ruby/internal/constant_p.h +sha2.o: $(hdrdir)/ruby/internal/core.h +sha2.o: $(hdrdir)/ruby/internal/core/rarray.h +sha2.o: $(hdrdir)/ruby/internal/core/rbasic.h +sha2.o: $(hdrdir)/ruby/internal/core/rbignum.h +sha2.o: $(hdrdir)/ruby/internal/core/rclass.h +sha2.o: $(hdrdir)/ruby/internal/core/rdata.h +sha2.o: $(hdrdir)/ruby/internal/core/rfile.h +sha2.o: $(hdrdir)/ruby/internal/core/rhash.h +sha2.o: $(hdrdir)/ruby/internal/core/robject.h +sha2.o: $(hdrdir)/ruby/internal/core/rregexp.h +sha2.o: $(hdrdir)/ruby/internal/core/rstring.h +sha2.o: $(hdrdir)/ruby/internal/core/rstruct.h +sha2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sha2.o: $(hdrdir)/ruby/internal/ctype.h +sha2.o: $(hdrdir)/ruby/internal/dllexport.h +sha2.o: $(hdrdir)/ruby/internal/dosish.h +sha2.o: $(hdrdir)/ruby/internal/error.h +sha2.o: $(hdrdir)/ruby/internal/eval.h +sha2.o: $(hdrdir)/ruby/internal/event.h +sha2.o: $(hdrdir)/ruby/internal/fl_type.h +sha2.o: $(hdrdir)/ruby/internal/gc.h +sha2.o: $(hdrdir)/ruby/internal/glob.h +sha2.o: $(hdrdir)/ruby/internal/globals.h +sha2.o: $(hdrdir)/ruby/internal/has/attribute.h +sha2.o: $(hdrdir)/ruby/internal/has/builtin.h +sha2.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sha2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sha2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sha2.o: $(hdrdir)/ruby/internal/has/extension.h +sha2.o: $(hdrdir)/ruby/internal/has/feature.h +sha2.o: $(hdrdir)/ruby/internal/has/warning.h +sha2.o: $(hdrdir)/ruby/internal/intern/array.h +sha2.o: $(hdrdir)/ruby/internal/intern/bignum.h +sha2.o: $(hdrdir)/ruby/internal/intern/class.h +sha2.o: $(hdrdir)/ruby/internal/intern/compar.h +sha2.o: $(hdrdir)/ruby/internal/intern/complex.h +sha2.o: $(hdrdir)/ruby/internal/intern/cont.h +sha2.o: $(hdrdir)/ruby/internal/intern/dir.h +sha2.o: $(hdrdir)/ruby/internal/intern/enum.h +sha2.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sha2.o: $(hdrdir)/ruby/internal/intern/error.h +sha2.o: $(hdrdir)/ruby/internal/intern/eval.h +sha2.o: $(hdrdir)/ruby/internal/intern/file.h +sha2.o: $(hdrdir)/ruby/internal/intern/gc.h +sha2.o: $(hdrdir)/ruby/internal/intern/hash.h +sha2.o: $(hdrdir)/ruby/internal/intern/io.h +sha2.o: $(hdrdir)/ruby/internal/intern/load.h +sha2.o: $(hdrdir)/ruby/internal/intern/marshal.h +sha2.o: $(hdrdir)/ruby/internal/intern/numeric.h +sha2.o: $(hdrdir)/ruby/internal/intern/object.h +sha2.o: $(hdrdir)/ruby/internal/intern/parse.h +sha2.o: $(hdrdir)/ruby/internal/intern/proc.h +sha2.o: $(hdrdir)/ruby/internal/intern/process.h +sha2.o: $(hdrdir)/ruby/internal/intern/random.h +sha2.o: $(hdrdir)/ruby/internal/intern/range.h +sha2.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +sha2.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sha2.o: $(hdrdir)/ruby/internal/intern/string.h +sha2.o: $(hdrdir)/ruby/internal/intern/struct.h +sha2.o: $(hdrdir)/ruby/internal/intern/thread.h +sha2.o: $(hdrdir)/ruby/internal/intern/time.h +sha2.o: $(hdrdir)/ruby/internal/intern/variable.h +sha2.o: $(hdrdir)/ruby/internal/intern/vm.h +sha2.o: $(hdrdir)/ruby/internal/interpreter.h +sha2.o: $(hdrdir)/ruby/internal/iterator.h +sha2.o: $(hdrdir)/ruby/internal/memory.h +sha2.o: $(hdrdir)/ruby/internal/method.h +sha2.o: $(hdrdir)/ruby/internal/module.h +sha2.o: $(hdrdir)/ruby/internal/newobj.h +sha2.o: $(hdrdir)/ruby/internal/rgengc.h +sha2.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +sha2.o: $(hdrdir)/ruby/internal/value.h +sha2.o: $(hdrdir)/ruby/internal/value_type.h +sha2.o: $(hdrdir)/ruby/internal/variable.h +sha2.o: $(hdrdir)/ruby/internal/warning_push.h +sha2.o: $(hdrdir)/ruby/internal/xmalloc.h +sha2.o: $(hdrdir)/ruby/missing.h +sha2.o: $(hdrdir)/ruby/ruby.h +sha2.o: $(hdrdir)/ruby/st.h +sha2.o: $(hdrdir)/ruby/subst.h +sha2.o: $(srcdir)/../defs.h +sha2.o: sha2.c +sha2.o: sha2.h sha2init.o: $(RUBY_EXTCONF_H) sha2init.o: $(arch_hdrdir)/ruby/config.h sha2init.o: $(hdrdir)/ruby.h sha2init.o: $(hdrdir)/ruby/assert.h sha2init.o: $(hdrdir)/ruby/backward.h +sha2init.o: $(hdrdir)/ruby/backward/2/assume.h +sha2init.o: $(hdrdir)/ruby/backward/2/attributes.h +sha2init.o: $(hdrdir)/ruby/backward/2/bool.h +sha2init.o: $(hdrdir)/ruby/backward/2/inttypes.h +sha2init.o: $(hdrdir)/ruby/backward/2/limits.h +sha2init.o: $(hdrdir)/ruby/backward/2/long_long.h +sha2init.o: $(hdrdir)/ruby/backward/2/stdalign.h +sha2init.o: $(hdrdir)/ruby/backward/2/stdarg.h sha2init.o: $(hdrdir)/ruby/defines.h sha2init.o: $(hdrdir)/ruby/intern.h +sha2init.o: $(hdrdir)/ruby/internal/anyargs.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sha2init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sha2init.o: $(hdrdir)/ruby/internal/assume.h +sha2init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sha2init.o: $(hdrdir)/ruby/internal/attr/artificial.h +sha2init.o: $(hdrdir)/ruby/internal/attr/cold.h +sha2init.o: $(hdrdir)/ruby/internal/attr/const.h +sha2init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sha2init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sha2init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sha2init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sha2init.o: $(hdrdir)/ruby/internal/attr/error.h +sha2init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sha2init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sha2init.o: $(hdrdir)/ruby/internal/attr/format.h +sha2init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sha2init.o: $(hdrdir)/ruby/internal/attr/noalias.h +sha2init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sha2init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sha2init.o: $(hdrdir)/ruby/internal/attr/noinline.h +sha2init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sha2init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sha2init.o: $(hdrdir)/ruby/internal/attr/pure.h +sha2init.o: $(hdrdir)/ruby/internal/attr/restrict.h +sha2init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sha2init.o: $(hdrdir)/ruby/internal/attr/warning.h +sha2init.o: $(hdrdir)/ruby/internal/attr/weakref.h +sha2init.o: $(hdrdir)/ruby/internal/cast.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sha2init.o: $(hdrdir)/ruby/internal/compiler_since.h +sha2init.o: $(hdrdir)/ruby/internal/config.h +sha2init.o: $(hdrdir)/ruby/internal/constant_p.h +sha2init.o: $(hdrdir)/ruby/internal/core.h +sha2init.o: $(hdrdir)/ruby/internal/core/rarray.h +sha2init.o: $(hdrdir)/ruby/internal/core/rbasic.h +sha2init.o: $(hdrdir)/ruby/internal/core/rbignum.h +sha2init.o: $(hdrdir)/ruby/internal/core/rclass.h +sha2init.o: $(hdrdir)/ruby/internal/core/rdata.h +sha2init.o: $(hdrdir)/ruby/internal/core/rfile.h +sha2init.o: $(hdrdir)/ruby/internal/core/rhash.h +sha2init.o: $(hdrdir)/ruby/internal/core/robject.h +sha2init.o: $(hdrdir)/ruby/internal/core/rregexp.h +sha2init.o: $(hdrdir)/ruby/internal/core/rstring.h +sha2init.o: $(hdrdir)/ruby/internal/core/rstruct.h +sha2init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sha2init.o: $(hdrdir)/ruby/internal/ctype.h +sha2init.o: $(hdrdir)/ruby/internal/dllexport.h +sha2init.o: $(hdrdir)/ruby/internal/dosish.h +sha2init.o: $(hdrdir)/ruby/internal/error.h +sha2init.o: $(hdrdir)/ruby/internal/eval.h +sha2init.o: $(hdrdir)/ruby/internal/event.h +sha2init.o: $(hdrdir)/ruby/internal/fl_type.h +sha2init.o: $(hdrdir)/ruby/internal/gc.h +sha2init.o: $(hdrdir)/ruby/internal/glob.h +sha2init.o: $(hdrdir)/ruby/internal/globals.h +sha2init.o: $(hdrdir)/ruby/internal/has/attribute.h +sha2init.o: $(hdrdir)/ruby/internal/has/builtin.h +sha2init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sha2init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sha2init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sha2init.o: $(hdrdir)/ruby/internal/has/extension.h +sha2init.o: $(hdrdir)/ruby/internal/has/feature.h +sha2init.o: $(hdrdir)/ruby/internal/has/warning.h +sha2init.o: $(hdrdir)/ruby/internal/intern/array.h +sha2init.o: $(hdrdir)/ruby/internal/intern/bignum.h +sha2init.o: $(hdrdir)/ruby/internal/intern/class.h +sha2init.o: $(hdrdir)/ruby/internal/intern/compar.h +sha2init.o: $(hdrdir)/ruby/internal/intern/complex.h +sha2init.o: $(hdrdir)/ruby/internal/intern/cont.h +sha2init.o: $(hdrdir)/ruby/internal/intern/dir.h +sha2init.o: $(hdrdir)/ruby/internal/intern/enum.h +sha2init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sha2init.o: $(hdrdir)/ruby/internal/intern/error.h +sha2init.o: $(hdrdir)/ruby/internal/intern/eval.h +sha2init.o: $(hdrdir)/ruby/internal/intern/file.h +sha2init.o: $(hdrdir)/ruby/internal/intern/gc.h +sha2init.o: $(hdrdir)/ruby/internal/intern/hash.h +sha2init.o: $(hdrdir)/ruby/internal/intern/io.h +sha2init.o: $(hdrdir)/ruby/internal/intern/load.h +sha2init.o: $(hdrdir)/ruby/internal/intern/marshal.h +sha2init.o: $(hdrdir)/ruby/internal/intern/numeric.h +sha2init.o: $(hdrdir)/ruby/internal/intern/object.h +sha2init.o: $(hdrdir)/ruby/internal/intern/parse.h +sha2init.o: $(hdrdir)/ruby/internal/intern/proc.h +sha2init.o: $(hdrdir)/ruby/internal/intern/process.h +sha2init.o: $(hdrdir)/ruby/internal/intern/random.h +sha2init.o: $(hdrdir)/ruby/internal/intern/range.h +sha2init.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +sha2init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sha2init.o: $(hdrdir)/ruby/internal/intern/string.h +sha2init.o: $(hdrdir)/ruby/internal/intern/struct.h +sha2init.o: $(hdrdir)/ruby/internal/intern/thread.h +sha2init.o: $(hdrdir)/ruby/internal/intern/time.h +sha2init.o: $(hdrdir)/ruby/internal/intern/variable.h +sha2init.o: $(hdrdir)/ruby/internal/intern/vm.h +sha2init.o: $(hdrdir)/ruby/internal/interpreter.h +sha2init.o: $(hdrdir)/ruby/internal/iterator.h +sha2init.o: $(hdrdir)/ruby/internal/memory.h +sha2init.o: $(hdrdir)/ruby/internal/method.h +sha2init.o: $(hdrdir)/ruby/internal/module.h +sha2init.o: $(hdrdir)/ruby/internal/newobj.h +sha2init.o: $(hdrdir)/ruby/internal/rgengc.h +sha2init.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +sha2init.o: $(hdrdir)/ruby/internal/value.h +sha2init.o: $(hdrdir)/ruby/internal/value_type.h +sha2init.o: $(hdrdir)/ruby/internal/variable.h +sha2init.o: $(hdrdir)/ruby/internal/warning_push.h +sha2init.o: $(hdrdir)/ruby/internal/xmalloc.h sha2init.o: $(hdrdir)/ruby/missing.h sha2init.o: $(hdrdir)/ruby/ruby.h sha2init.o: $(hdrdir)/ruby/st.h sha2init.o: $(hdrdir)/ruby/subst.h sha2init.o: $(srcdir)/../digest.h +sha2init.o: sha2.h sha2init.o: sha2init.c -sha2init.o: sha2ossl.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/digest/sha2/extconf.rb b/ruby/ext/digest/sha2/extconf.rb index 5c7f76c7f..3b772675e 100644 --- a/ruby/ext/digest/sha2/extconf.rb +++ b/ruby/ext/digest/sha2/extconf.rb @@ -6,11 +6,9 @@ require "mkmf" require File.expand_path("../../digest_conf", __FILE__) -$defs << "-DHAVE_CONFIG_H" - $objs = [ "sha2init.#{$OBJEXT}" ] -unless digest_conf("sha2", "sha", %w[SHA256 SHA512]) +unless digest_conf("sha2") have_type("u_int8_t") end diff --git a/ruby/ext/digest/sha2/lib/sha2.rb b/ruby/ext/digest/sha2/lib/sha2.rb index 61a073485..f17593a20 100644 --- a/ruby/ext/digest/sha2/lib/sha2.rb +++ b/ruby/ext/digest/sha2/lib/sha2.rb @@ -11,7 +11,7 @@ # $Id$ require 'digest' -require 'digest/sha2.so' +require 'digest/sha2/loader' module Digest # diff --git a/ruby/ext/digest/sha2/lib/sha2/loader.rb b/ruby/ext/digest/sha2/lib/sha2/loader.rb new file mode 100644 index 000000000..7d6d04a59 --- /dev/null +++ b/ruby/ext/digest/sha2/lib/sha2/loader.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require 'digest/sha2.so' diff --git a/ruby/ext/digest/sha2/sha2.c b/ruby/ext/digest/sha2/sha2.c index c86eab37a..e7d7b15c5 100644 --- a/ruby/ext/digest/sha2/sha2.c +++ b/ruby/ext/digest/sha2/sha2.c @@ -94,7 +94,7 @@ /* * Define the followingsha2_* types to types of the correct length on - * the native archtecture. Most BSD systems and Linux define u_intXX_t + * the native architecture. Most BSD systems and Linux define u_intXX_t * types. Machines with very recent ANSI C headers, can use the * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H * during compile or in the sha.h header file. @@ -575,7 +575,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { usedspace = freespace = 0; } -int SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { +int SHA256_Final(sha2_byte digest[SHA256_DIGEST_LENGTH], SHA256_CTX* context) { sha2_word32 *d = (sha2_word32*)digest; unsigned int usedspace; @@ -640,7 +640,7 @@ int SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { return 1; } -char *SHA256_End(SHA256_CTX* context, char buffer[]) { +char *SHA256_End(SHA256_CTX* context, char buffer[SHA256_DIGEST_STRING_LENGTH]) { sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; int i; @@ -943,7 +943,7 @@ void SHA512_Last(SHA512_CTX* context) { SHA512_Transform(context, (sha2_word64*)context->buffer); } -int SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { +int SHA512_Final(sha2_byte digest[SHA512_DIGEST_LENGTH], SHA512_CTX* context) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ @@ -973,7 +973,7 @@ int SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { return 1; } -char *SHA512_End(SHA512_CTX* context, char buffer[]) { +char *SHA512_End(SHA512_CTX* context, char buffer[SHA512_DIGEST_STRING_LENGTH]) { sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; int i; @@ -1019,7 +1019,7 @@ void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { SHA512_Update((SHA512_CTX*)context, data, len); } -int SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { +int SHA384_Final(sha2_byte digest[SHA384_DIGEST_LENGTH], SHA384_CTX* context) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ @@ -1049,7 +1049,7 @@ int SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { return 1; } -char *SHA384_End(SHA384_CTX* context, char buffer[]) { +char *SHA384_End(SHA384_CTX* context, char buffer[SHA384_DIGEST_STRING_LENGTH]) { sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; int i; diff --git a/ruby/ext/digest/sha2/sha2init.c b/ruby/ext/digest/sha2/sha2init.c index 7d211784a..6ed275eb7 100644 --- a/ruby/ext/digest/sha2/sha2init.c +++ b/ruby/ext/digest/sha2/sha2init.c @@ -3,9 +3,7 @@ #include #include "../digest.h" -#if defined(SHA2_USE_OPENSSL) -#include "sha2ossl.h" -#elif defined(SHA2_USE_COMMONDIGEST) +#if defined(SHA2_USE_COMMONDIGEST) #include "sha2cc.h" #else #include "sha2.h" @@ -49,9 +47,7 @@ Init_sha2(void) cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \ \ rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \ - Data_Wrap_Struct(0, 0, 0, (void *)&sha##bitlen)); + rb_digest_make_metadata(&sha##bitlen)); -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 FOREACH_BITLEN(DEFINE_ALGO_CLASS) } diff --git a/ruby/ext/digest/sha2/sha2ossl.h b/ruby/ext/digest/sha2/sha2ossl.h deleted file mode 100644 index 8dd053010..000000000 --- a/ruby/ext/digest/sha2/sha2ossl.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2OSSL_H_INCLUDED -#define SHA2OSSL_H_INCLUDED - -#include -#include - -#define SHA256_BLOCK_LENGTH SHA256_CBLOCK -#define SHA384_BLOCK_LENGTH SHA512_CBLOCK -#define SHA512_BLOCK_LENGTH SHA512_CBLOCK - -#ifndef __DragonFly__ -#define SHA384_Final SHA512_Final -#endif - -typedef SHA512_CTX SHA384_CTX; - -#undef SHA256_Finish -#undef SHA384_Finish -#undef SHA512_Finish -#define SHA256_Finish rb_digest_SHA256_finish -#define SHA384_Finish rb_digest_SHA384_finish -#define SHA512_Finish rb_digest_SHA512_finish -static DEFINE_FINISH_FUNC_FROM_FINAL(SHA256) -static DEFINE_FINISH_FUNC_FROM_FINAL(SHA384) -static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512) - -#endif diff --git a/ruby/ext/etc/depend b/ruby/ext/etc/depend index 99e812c7e..9c2de2ba9 100644 --- a/ruby/ext/etc/depend +++ b/ruby/ext/etc/depend @@ -7,10 +7,167 @@ etc.o: $(RUBY_EXTCONF_H) etc.o: $(arch_hdrdir)/ruby/config.h etc.o: $(hdrdir)/ruby.h etc.o: $(hdrdir)/ruby/assert.h +etc.o: $(hdrdir)/ruby/atomic.h etc.o: $(hdrdir)/ruby/backward.h +etc.o: $(hdrdir)/ruby/backward/2/assume.h +etc.o: $(hdrdir)/ruby/backward/2/attributes.h +etc.o: $(hdrdir)/ruby/backward/2/bool.h +etc.o: $(hdrdir)/ruby/backward/2/inttypes.h +etc.o: $(hdrdir)/ruby/backward/2/limits.h +etc.o: $(hdrdir)/ruby/backward/2/long_long.h +etc.o: $(hdrdir)/ruby/backward/2/stdalign.h +etc.o: $(hdrdir)/ruby/backward/2/stdarg.h etc.o: $(hdrdir)/ruby/defines.h etc.o: $(hdrdir)/ruby/encoding.h etc.o: $(hdrdir)/ruby/intern.h +etc.o: $(hdrdir)/ruby/internal/anyargs.h +etc.o: $(hdrdir)/ruby/internal/arithmetic.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/char.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/double.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/int.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/long.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/short.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +etc.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +etc.o: $(hdrdir)/ruby/internal/assume.h +etc.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +etc.o: $(hdrdir)/ruby/internal/attr/artificial.h +etc.o: $(hdrdir)/ruby/internal/attr/cold.h +etc.o: $(hdrdir)/ruby/internal/attr/const.h +etc.o: $(hdrdir)/ruby/internal/attr/constexpr.h +etc.o: $(hdrdir)/ruby/internal/attr/deprecated.h +etc.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +etc.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +etc.o: $(hdrdir)/ruby/internal/attr/error.h +etc.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +etc.o: $(hdrdir)/ruby/internal/attr/forceinline.h +etc.o: $(hdrdir)/ruby/internal/attr/format.h +etc.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +etc.o: $(hdrdir)/ruby/internal/attr/noalias.h +etc.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +etc.o: $(hdrdir)/ruby/internal/attr/noexcept.h +etc.o: $(hdrdir)/ruby/internal/attr/noinline.h +etc.o: $(hdrdir)/ruby/internal/attr/nonnull.h +etc.o: $(hdrdir)/ruby/internal/attr/noreturn.h +etc.o: $(hdrdir)/ruby/internal/attr/pure.h +etc.o: $(hdrdir)/ruby/internal/attr/restrict.h +etc.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +etc.o: $(hdrdir)/ruby/internal/attr/warning.h +etc.o: $(hdrdir)/ruby/internal/attr/weakref.h +etc.o: $(hdrdir)/ruby/internal/cast.h +etc.o: $(hdrdir)/ruby/internal/compiler_is.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +etc.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +etc.o: $(hdrdir)/ruby/internal/compiler_since.h +etc.o: $(hdrdir)/ruby/internal/config.h +etc.o: $(hdrdir)/ruby/internal/constant_p.h +etc.o: $(hdrdir)/ruby/internal/core.h +etc.o: $(hdrdir)/ruby/internal/core/rarray.h +etc.o: $(hdrdir)/ruby/internal/core/rbasic.h +etc.o: $(hdrdir)/ruby/internal/core/rbignum.h +etc.o: $(hdrdir)/ruby/internal/core/rclass.h +etc.o: $(hdrdir)/ruby/internal/core/rdata.h +etc.o: $(hdrdir)/ruby/internal/core/rfile.h +etc.o: $(hdrdir)/ruby/internal/core/rhash.h +etc.o: $(hdrdir)/ruby/internal/core/robject.h +etc.o: $(hdrdir)/ruby/internal/core/rregexp.h +etc.o: $(hdrdir)/ruby/internal/core/rstring.h +etc.o: $(hdrdir)/ruby/internal/core/rstruct.h +etc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +etc.o: $(hdrdir)/ruby/internal/ctype.h +etc.o: $(hdrdir)/ruby/internal/dllexport.h +etc.o: $(hdrdir)/ruby/internal/dosish.h +etc.o: $(hdrdir)/ruby/internal/encoding/coderange.h +etc.o: $(hdrdir)/ruby/internal/encoding/ctype.h +etc.o: $(hdrdir)/ruby/internal/encoding/encoding.h +etc.o: $(hdrdir)/ruby/internal/encoding/pathname.h +etc.o: $(hdrdir)/ruby/internal/encoding/re.h +etc.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +etc.o: $(hdrdir)/ruby/internal/encoding/string.h +etc.o: $(hdrdir)/ruby/internal/encoding/symbol.h +etc.o: $(hdrdir)/ruby/internal/encoding/transcode.h +etc.o: $(hdrdir)/ruby/internal/error.h +etc.o: $(hdrdir)/ruby/internal/eval.h +etc.o: $(hdrdir)/ruby/internal/event.h +etc.o: $(hdrdir)/ruby/internal/fl_type.h +etc.o: $(hdrdir)/ruby/internal/gc.h +etc.o: $(hdrdir)/ruby/internal/glob.h +etc.o: $(hdrdir)/ruby/internal/globals.h +etc.o: $(hdrdir)/ruby/internal/has/attribute.h +etc.o: $(hdrdir)/ruby/internal/has/builtin.h +etc.o: $(hdrdir)/ruby/internal/has/c_attribute.h +etc.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +etc.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +etc.o: $(hdrdir)/ruby/internal/has/extension.h +etc.o: $(hdrdir)/ruby/internal/has/feature.h +etc.o: $(hdrdir)/ruby/internal/has/warning.h +etc.o: $(hdrdir)/ruby/internal/intern/array.h +etc.o: $(hdrdir)/ruby/internal/intern/bignum.h +etc.o: $(hdrdir)/ruby/internal/intern/class.h +etc.o: $(hdrdir)/ruby/internal/intern/compar.h +etc.o: $(hdrdir)/ruby/internal/intern/complex.h +etc.o: $(hdrdir)/ruby/internal/intern/cont.h +etc.o: $(hdrdir)/ruby/internal/intern/dir.h +etc.o: $(hdrdir)/ruby/internal/intern/enum.h +etc.o: $(hdrdir)/ruby/internal/intern/enumerator.h +etc.o: $(hdrdir)/ruby/internal/intern/error.h +etc.o: $(hdrdir)/ruby/internal/intern/eval.h +etc.o: $(hdrdir)/ruby/internal/intern/file.h +etc.o: $(hdrdir)/ruby/internal/intern/gc.h +etc.o: $(hdrdir)/ruby/internal/intern/hash.h +etc.o: $(hdrdir)/ruby/internal/intern/io.h +etc.o: $(hdrdir)/ruby/internal/intern/load.h +etc.o: $(hdrdir)/ruby/internal/intern/marshal.h +etc.o: $(hdrdir)/ruby/internal/intern/numeric.h +etc.o: $(hdrdir)/ruby/internal/intern/object.h +etc.o: $(hdrdir)/ruby/internal/intern/parse.h +etc.o: $(hdrdir)/ruby/internal/intern/proc.h +etc.o: $(hdrdir)/ruby/internal/intern/process.h +etc.o: $(hdrdir)/ruby/internal/intern/random.h +etc.o: $(hdrdir)/ruby/internal/intern/range.h +etc.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +etc.o: $(hdrdir)/ruby/internal/intern/sprintf.h +etc.o: $(hdrdir)/ruby/internal/intern/string.h +etc.o: $(hdrdir)/ruby/internal/intern/struct.h +etc.o: $(hdrdir)/ruby/internal/intern/thread.h +etc.o: $(hdrdir)/ruby/internal/intern/time.h +etc.o: $(hdrdir)/ruby/internal/intern/variable.h +etc.o: $(hdrdir)/ruby/internal/intern/vm.h +etc.o: $(hdrdir)/ruby/internal/interpreter.h +etc.o: $(hdrdir)/ruby/internal/iterator.h +etc.o: $(hdrdir)/ruby/internal/memory.h +etc.o: $(hdrdir)/ruby/internal/method.h +etc.o: $(hdrdir)/ruby/internal/module.h +etc.o: $(hdrdir)/ruby/internal/newobj.h +etc.o: $(hdrdir)/ruby/internal/rgengc.h +etc.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +etc.o: $(hdrdir)/ruby/internal/value.h +etc.o: $(hdrdir)/ruby/internal/value_type.h +etc.o: $(hdrdir)/ruby/internal/variable.h +etc.o: $(hdrdir)/ruby/internal/warning_push.h +etc.o: $(hdrdir)/ruby/internal/xmalloc.h etc.o: $(hdrdir)/ruby/io.h etc.o: $(hdrdir)/ruby/missing.h etc.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/etc/etc.c b/ruby/ext/etc/etc.c index 2f3fbb737..737d295ab 100644 --- a/ruby/ext/etc/etc.c +++ b/ruby/ext/etc/etc.c @@ -52,10 +52,33 @@ char *getenv(); #endif char *getlogin(); -#define RUBY_ETC_VERSION "1.1.0" +#define RUBY_ETC_VERSION "1.3.0" + +#ifdef HAVE_RB_DEPRECATE_CONSTANT +void rb_deprecate_constant(VALUE mod, const char *name); +#else +# define rb_deprecate_constant(mod,name) ((void)(mod),(void)(name)) +#endif #include "constdefs.h" +#ifdef HAVE_RUBY_ATOMIC_H +# include "ruby/atomic.h" +#else +typedef int rb_atomic_t; +# define RUBY_ATOMIC_CAS(var, oldval, newval) \ + ((var) == (oldval) ? ((var) = (newval), (oldval)) : (var)) +# define RUBY_ATOMIC_EXCHANGE(var, newval) \ + atomic_exchange(&var, newval) +static inline rb_atomic_t +atomic_exchange(volatile rb_atomic_t *var, rb_atomic_t newval) +{ + rb_atomic_t oldval = *var; + *var = newval; + return oldval; +} +#endif + /* call-seq: * getlogin -> String * @@ -119,6 +142,12 @@ safe_setup_filesystem_str(const char *str) #endif #ifdef HAVE_GETPWENT +# ifdef __APPLE__ +# define PW_TIME2VAL(t) INT2NUM((int)(t)) +# else +# define PW_TIME2VAL(t) TIMET2NUM(t) +# endif + static VALUE setup_passwd(struct passwd *pwd) { @@ -136,7 +165,7 @@ setup_passwd(struct passwd *pwd) safe_setup_filesystem_str(pwd->pw_dir), safe_setup_filesystem_str(pwd->pw_shell), #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE - INT2NUM(pwd->pw_change), + PW_TIME2VAL(pwd->pw_change), #endif #ifdef HAVE_STRUCT_PASSWD_PW_QUOTA INT2NUM(pwd->pw_quota), @@ -151,7 +180,7 @@ setup_passwd(struct passwd *pwd) safe_setup_locale_str(pwd->pw_comment), #endif #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE - INT2NUM(pwd->pw_expire), + PW_TIME2VAL(pwd->pw_expire), #endif 0 /*dummy*/ ); @@ -228,12 +257,14 @@ etc_getpwnam(VALUE obj, VALUE nam) } #ifdef HAVE_GETPWENT -static int passwd_blocking = 0; +static rb_atomic_t passwd_blocking; static VALUE passwd_ensure(VALUE _) { endpwent(); - passwd_blocking = (int)Qfalse; + if (RUBY_ATOMIC_EXCHANGE(passwd_blocking, 0) != 1) { + rb_raise(rb_eRuntimeError, "unexpected passwd_blocking"); + } return Qnil; } @@ -252,10 +283,9 @@ passwd_iterate(VALUE _) static void each_passwd(void) { - if (passwd_blocking) { + if (RUBY_ATOMIC_CAS(passwd_blocking, 0, 1)) { rb_raise(rb_eRuntimeError, "parallel passwd iteration"); } - passwd_blocking = (int)Qtrue; rb_ensure(passwd_iterate, 0, passwd_ensure, 0); } #endif @@ -471,12 +501,14 @@ etc_getgrnam(VALUE obj, VALUE nam) } #ifdef HAVE_GETGRENT -static int group_blocking = 0; +static rb_atomic_t group_blocking; static VALUE group_ensure(VALUE _) { endgrent(); - group_blocking = (int)Qfalse; + if (RUBY_ATOMIC_EXCHANGE(group_blocking, 0) != 1) { + rb_raise(rb_eRuntimeError, "unexpected group_blocking"); + } return Qnil; } @@ -496,10 +528,9 @@ group_iterate(VALUE _) static void each_group(void) { - if (group_blocking) { + if (RUBY_ATOMIC_CAS(group_blocking, 0, 1)) { rb_raise(rb_eRuntimeError, "parallel group iteration"); } - group_blocking = (int)Qtrue; rb_ensure(group_iterate, 0, group_ensure, 0); } #endif @@ -926,11 +957,13 @@ io_pathconf(VALUE io, VALUE arg) static int etc_nprocessors_affin(void) { - cpu_set_t *cpuset; + cpu_set_t *cpuset, cpuset_buff[1024 / sizeof(cpu_set_t)]; size_t size; int ret; int n; + CPU_ZERO_S(sizeof(cpuset_buff), cpuset_buff); + /* * XXX: * man page says CPU_ALLOC takes number of cpus. But it is not accurate @@ -949,13 +982,12 @@ etc_nprocessors_affin(void) */ for (n=64; n <= 16384; n *= 2) { size = CPU_ALLOC_SIZE(n); - if (size >= 1024) { + if (size >= sizeof(cpuset_buff)) { cpuset = xcalloc(1, size); if (!cpuset) return -1; } else { - cpuset = alloca(size); - CPU_ZERO_S(size, cpuset); + cpuset = cpuset_buff; } ret = sched_getaffinity(0, size, cpuset); @@ -964,10 +996,10 @@ etc_nprocessors_affin(void) ret = CPU_COUNT_S(size, cpuset); } - if (size >= 1024) { + if (size >= sizeof(cpuset_buff)) { xfree(cpuset); } - if (ret > 0) { + if (ret > 0 || errno != EINVAL) { return ret; } } @@ -1064,6 +1096,9 @@ Init_etc(void) { VALUE mEtc; + #ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); + #endif mEtc = rb_define_module("Etc"); rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION)); init_constants(mEtc); @@ -1165,9 +1200,9 @@ Init_etc(void) rb_define_const(mEtc, "Passwd", sPasswd); #endif rb_define_const(rb_cStruct, "Passwd", sPasswd); /* deprecated name */ + rb_deprecate_constant(rb_cStruct, "Passwd"); rb_extend_object(sPasswd, rb_mEnumerable); rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0); - #ifdef HAVE_GETGRENT sGroup = rb_struct_define_under(mEtc, "Group", "name", #ifdef HAVE_STRUCT_GROUP_GR_PASSWD @@ -1200,6 +1235,7 @@ Init_etc(void) rb_define_const(mEtc, "Group", sGroup); #endif rb_define_const(rb_cStruct, "Group", sGroup); /* deprecated name */ + rb_deprecate_constant(rb_cStruct, "Group"); rb_extend_object(sGroup, rb_mEnumerable); rb_define_singleton_method(sGroup, "each", etc_each_group, 0); #endif diff --git a/ruby/ext/etc/etc.gemspec b/ruby/ext/etc/etc.gemspec index f28016925..7d687e3b9 100644 --- a/ruby/ext/etc/etc.gemspec +++ b/ruby/ext/etc/etc.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |spec| spec.summary = %q{Provides access to information typically stored in UNIX /etc directory.} spec.description = spec.summary spec.homepage = "https://github.com/ruby/etc" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.files = %w[ LICENSE.txt @@ -29,7 +29,6 @@ Gem::Specification.new do |spec| ext/etc/etc.c ext/etc/extconf.rb ext/etc/mkconstants.rb - stub/etc.rb test/etc/test_etc.rb ] spec.bindir = "exe" diff --git a/ruby/ext/etc/extconf.rb b/ruby/ext/etc/extconf.rb index 435fbe7f3..6e7810a5e 100644 --- a/ruby/ext/etc/extconf.rb +++ b/ruby/ext/etc/extconf.rb @@ -47,6 +47,8 @@ %x[#{RbConfig.ruby} #{srcdir}/mkconstants.rb -o #{srcdir}/constdefs.h] end +have_func('rb_deprecate_constant(Qnil, "None")') + $distcleanfiles << "constdefs.h" create_makefile("etc") diff --git a/ruby/ext/extmk.rb b/ruby/ext/extmk.rb index 80a0a1208..4a087f294 100755 --- a/ruby/ext/extmk.rb +++ b/ruby/ext/extmk.rb @@ -647,6 +647,7 @@ def initialize(src) begin atomic_write_open($command_output) do |mf| mf.puts "V = 0" + mf.puts "V0 = $(V:0=)" mf.puts "Q1 = $(V:1=)" mf.puts "Q = $(Q1:0=@)" mf.puts "ECHO1 = $(V:1=@:)" diff --git a/ruby/ext/fcntl/depend b/ruby/ext/fcntl/depend index 60d6be6b8..46a9e7817 100644 --- a/ruby/ext/fcntl/depend +++ b/ruby/ext/fcntl/depend @@ -4,8 +4,155 @@ fcntl.o: $(arch_hdrdir)/ruby/config.h fcntl.o: $(hdrdir)/ruby.h fcntl.o: $(hdrdir)/ruby/assert.h fcntl.o: $(hdrdir)/ruby/backward.h +fcntl.o: $(hdrdir)/ruby/backward/2/assume.h +fcntl.o: $(hdrdir)/ruby/backward/2/attributes.h +fcntl.o: $(hdrdir)/ruby/backward/2/bool.h +fcntl.o: $(hdrdir)/ruby/backward/2/inttypes.h +fcntl.o: $(hdrdir)/ruby/backward/2/limits.h +fcntl.o: $(hdrdir)/ruby/backward/2/long_long.h +fcntl.o: $(hdrdir)/ruby/backward/2/stdalign.h +fcntl.o: $(hdrdir)/ruby/backward/2/stdarg.h fcntl.o: $(hdrdir)/ruby/defines.h fcntl.o: $(hdrdir)/ruby/intern.h +fcntl.o: $(hdrdir)/ruby/internal/anyargs.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +fcntl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +fcntl.o: $(hdrdir)/ruby/internal/assume.h +fcntl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +fcntl.o: $(hdrdir)/ruby/internal/attr/artificial.h +fcntl.o: $(hdrdir)/ruby/internal/attr/cold.h +fcntl.o: $(hdrdir)/ruby/internal/attr/const.h +fcntl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +fcntl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +fcntl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +fcntl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +fcntl.o: $(hdrdir)/ruby/internal/attr/error.h +fcntl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +fcntl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +fcntl.o: $(hdrdir)/ruby/internal/attr/format.h +fcntl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +fcntl.o: $(hdrdir)/ruby/internal/attr/noalias.h +fcntl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +fcntl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +fcntl.o: $(hdrdir)/ruby/internal/attr/noinline.h +fcntl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +fcntl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +fcntl.o: $(hdrdir)/ruby/internal/attr/pure.h +fcntl.o: $(hdrdir)/ruby/internal/attr/restrict.h +fcntl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +fcntl.o: $(hdrdir)/ruby/internal/attr/warning.h +fcntl.o: $(hdrdir)/ruby/internal/attr/weakref.h +fcntl.o: $(hdrdir)/ruby/internal/cast.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +fcntl.o: $(hdrdir)/ruby/internal/compiler_since.h +fcntl.o: $(hdrdir)/ruby/internal/config.h +fcntl.o: $(hdrdir)/ruby/internal/constant_p.h +fcntl.o: $(hdrdir)/ruby/internal/core.h +fcntl.o: $(hdrdir)/ruby/internal/core/rarray.h +fcntl.o: $(hdrdir)/ruby/internal/core/rbasic.h +fcntl.o: $(hdrdir)/ruby/internal/core/rbignum.h +fcntl.o: $(hdrdir)/ruby/internal/core/rclass.h +fcntl.o: $(hdrdir)/ruby/internal/core/rdata.h +fcntl.o: $(hdrdir)/ruby/internal/core/rfile.h +fcntl.o: $(hdrdir)/ruby/internal/core/rhash.h +fcntl.o: $(hdrdir)/ruby/internal/core/robject.h +fcntl.o: $(hdrdir)/ruby/internal/core/rregexp.h +fcntl.o: $(hdrdir)/ruby/internal/core/rstring.h +fcntl.o: $(hdrdir)/ruby/internal/core/rstruct.h +fcntl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +fcntl.o: $(hdrdir)/ruby/internal/ctype.h +fcntl.o: $(hdrdir)/ruby/internal/dllexport.h +fcntl.o: $(hdrdir)/ruby/internal/dosish.h +fcntl.o: $(hdrdir)/ruby/internal/error.h +fcntl.o: $(hdrdir)/ruby/internal/eval.h +fcntl.o: $(hdrdir)/ruby/internal/event.h +fcntl.o: $(hdrdir)/ruby/internal/fl_type.h +fcntl.o: $(hdrdir)/ruby/internal/gc.h +fcntl.o: $(hdrdir)/ruby/internal/glob.h +fcntl.o: $(hdrdir)/ruby/internal/globals.h +fcntl.o: $(hdrdir)/ruby/internal/has/attribute.h +fcntl.o: $(hdrdir)/ruby/internal/has/builtin.h +fcntl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +fcntl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +fcntl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +fcntl.o: $(hdrdir)/ruby/internal/has/extension.h +fcntl.o: $(hdrdir)/ruby/internal/has/feature.h +fcntl.o: $(hdrdir)/ruby/internal/has/warning.h +fcntl.o: $(hdrdir)/ruby/internal/intern/array.h +fcntl.o: $(hdrdir)/ruby/internal/intern/bignum.h +fcntl.o: $(hdrdir)/ruby/internal/intern/class.h +fcntl.o: $(hdrdir)/ruby/internal/intern/compar.h +fcntl.o: $(hdrdir)/ruby/internal/intern/complex.h +fcntl.o: $(hdrdir)/ruby/internal/intern/cont.h +fcntl.o: $(hdrdir)/ruby/internal/intern/dir.h +fcntl.o: $(hdrdir)/ruby/internal/intern/enum.h +fcntl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +fcntl.o: $(hdrdir)/ruby/internal/intern/error.h +fcntl.o: $(hdrdir)/ruby/internal/intern/eval.h +fcntl.o: $(hdrdir)/ruby/internal/intern/file.h +fcntl.o: $(hdrdir)/ruby/internal/intern/gc.h +fcntl.o: $(hdrdir)/ruby/internal/intern/hash.h +fcntl.o: $(hdrdir)/ruby/internal/intern/io.h +fcntl.o: $(hdrdir)/ruby/internal/intern/load.h +fcntl.o: $(hdrdir)/ruby/internal/intern/marshal.h +fcntl.o: $(hdrdir)/ruby/internal/intern/numeric.h +fcntl.o: $(hdrdir)/ruby/internal/intern/object.h +fcntl.o: $(hdrdir)/ruby/internal/intern/parse.h +fcntl.o: $(hdrdir)/ruby/internal/intern/proc.h +fcntl.o: $(hdrdir)/ruby/internal/intern/process.h +fcntl.o: $(hdrdir)/ruby/internal/intern/random.h +fcntl.o: $(hdrdir)/ruby/internal/intern/range.h +fcntl.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +fcntl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +fcntl.o: $(hdrdir)/ruby/internal/intern/string.h +fcntl.o: $(hdrdir)/ruby/internal/intern/struct.h +fcntl.o: $(hdrdir)/ruby/internal/intern/thread.h +fcntl.o: $(hdrdir)/ruby/internal/intern/time.h +fcntl.o: $(hdrdir)/ruby/internal/intern/variable.h +fcntl.o: $(hdrdir)/ruby/internal/intern/vm.h +fcntl.o: $(hdrdir)/ruby/internal/interpreter.h +fcntl.o: $(hdrdir)/ruby/internal/iterator.h +fcntl.o: $(hdrdir)/ruby/internal/memory.h +fcntl.o: $(hdrdir)/ruby/internal/method.h +fcntl.o: $(hdrdir)/ruby/internal/module.h +fcntl.o: $(hdrdir)/ruby/internal/newobj.h +fcntl.o: $(hdrdir)/ruby/internal/rgengc.h +fcntl.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +fcntl.o: $(hdrdir)/ruby/internal/value.h +fcntl.o: $(hdrdir)/ruby/internal/value_type.h +fcntl.o: $(hdrdir)/ruby/internal/variable.h +fcntl.o: $(hdrdir)/ruby/internal/warning_push.h +fcntl.o: $(hdrdir)/ruby/internal/xmalloc.h fcntl.o: $(hdrdir)/ruby/missing.h fcntl.o: $(hdrdir)/ruby/ruby.h fcntl.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/fcntl/fcntl.c b/ruby/ext/fcntl/fcntl.c index c93694c43..ee42d2abe 100644 --- a/ruby/ext/fcntl/fcntl.c +++ b/ruby/ext/fcntl/fcntl.c @@ -159,6 +159,20 @@ Init_fcntl(void) */ 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 * diff --git a/ruby/ext/fcntl/fcntl.gemspec b/ruby/ext/fcntl/fcntl.gemspec index 0e3194fbd..048e101aa 100644 --- a/ruby/ext/fcntl/fcntl.gemspec +++ b/ruby/ext/fcntl/fcntl.gemspec @@ -3,14 +3,14 @@ Gem::Specification.new do |spec| spec.name = "fcntl" - spec.version = "1.0.0" + spec.version = "1.0.1" spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = "Loads constants defined in the OS fcntl.h C header file" spec.description = "Loads constants defined in the OS fcntl.h C header file" spec.homepage = "https://github.com/ruby/fcntl" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"] spec.bindir = "exe" @@ -18,8 +18,4 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.extensions = "ext/fcntl/extconf.rb" spec.required_ruby_version = ">= 2.3.0" - - spec.add_development_dependency "bundler", "~> 1.14" - spec.add_development_dependency "rake", "~> 12" - spec.add_development_dependency "rake-compiler" end diff --git a/ruby/ext/fiber/depend b/ruby/ext/fiber/depend deleted file mode 100644 index 675263b95..000000000 --- a/ruby/ext/fiber/depend +++ /dev/null @@ -1,3 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -fiber.o: fiber.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/fiber/extconf.rb b/ruby/ext/fiber/extconf.rb deleted file mode 100644 index 7f11e0daf..000000000 --- a/ruby/ext/fiber/extconf.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' -create_makefile('fiber') - diff --git a/ruby/ext/fiber/fiber.c b/ruby/ext/fiber/fiber.c deleted file mode 100644 index 12fcaad73..000000000 --- a/ruby/ext/fiber/fiber.c +++ /dev/null @@ -1,8 +0,0 @@ - -void ruby_Init_Fiber_as_Coroutine(void); - -void -Init_fiber(void) -{ - ruby_Init_Fiber_as_Coroutine(); -} diff --git a/ruby/ext/fiddle/closure.c b/ruby/ext/fiddle/closure.c index 1a80b2b02..3679e5c9a 100644 --- a/ruby/ext/fiddle/closure.c +++ b/ruby/ext/fiddle/closure.c @@ -13,11 +13,12 @@ typedef struct { ffi_type **argv; } fiddle_closure; -#if defined(USE_FFI_CLOSURE_ALLOC) -#elif defined(__OpenBSD__) || defined(__APPLE__) || defined(__linux__) +#if defined(__OpenBSD__) # define USE_FFI_CLOSURE_ALLOC 0 -#elif defined(RUBY_LIBFFI_MODVERSION) && RUBY_LIBFFI_MODVERSION < 3000005 && \ - (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)) +#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 @@ -129,6 +130,10 @@ with_gvl_callback(void *ptr) 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); } @@ -174,6 +179,10 @@ with_gvl_callback(void *ptr) *(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); } @@ -220,6 +229,7 @@ initialize(int rbargc, VALUE argv[], VALUE self) { VALUE ret; VALUE args; + VALUE normalized_args; VALUE abi; fiddle_closure * cl; ffi_cif * cif; @@ -238,21 +248,26 @@ initialize(int rbargc, VALUE argv[], VALUE self) cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); + normalized_args = rb_ary_new_capa(argc); for (i = 0; i < argc; i++) { - int type = NUM2INT(RARRAY_AREF(args, i)); - cl->argv[i] = INT2FFI_TYPE(type); + 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(self, "@ctype", ret); - rb_iv_set(self, "@args", args); + rb_iv_set(self, "@args", normalized_args); cif = &cl->cif; pcl = cl->pcl; - result = ffi_prep_cif(cif, NUM2INT(abi), argc, - INT2FFI_TYPE(NUM2INT(ret)), - cl->argv); + 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); diff --git a/ruby/ext/fiddle/conversions.c b/ruby/ext/fiddle/conversions.c index d40ddc1f3..6e0ce3637 100644 --- a/ruby/ext/fiddle/conversions.c +++ b/ruby/ext/fiddle/conversions.c @@ -1,7 +1,159 @@ #include +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; + 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"); + 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 { + type = original_type; + } + } + + return rb_to_int(type); +} + ffi_type * -int_to_ffi_type(int type) +rb_fiddle_int_to_ffi_type(int type) { int signed_p = 1; @@ -33,66 +185,90 @@ int_to_ffi_type(int type) 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 -value_to_generic(int type, VALUE src, fiddle_generic * dst) +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)); + dst->pointer = NUM2PTR(rb_Integer(*src)); break; case TYPE_CHAR: - dst->schar = (signed char)NUM2INT(src); + dst->schar = (signed char)NUM2INT(*src); break; case -TYPE_CHAR: - dst->uchar = (unsigned char)NUM2UINT(src); + dst->uchar = (unsigned char)NUM2UINT(*src); break; case TYPE_SHORT: - dst->sshort = (unsigned short)NUM2INT(src); + dst->sshort = (unsigned short)NUM2INT(*src); break; case -TYPE_SHORT: - dst->sshort = (signed short)NUM2UINT(src); + dst->sshort = (signed short)NUM2UINT(*src); break; case TYPE_INT: - dst->sint = NUM2INT(src); + dst->sint = NUM2INT(*src); break; case -TYPE_INT: - dst->uint = NUM2UINT(src); + dst->uint = NUM2UINT(*src); break; case TYPE_LONG: - dst->slong = NUM2LONG(src); + dst->slong = NUM2LONG(*src); break; case -TYPE_LONG: - dst->ulong = NUM2ULONG(src); + dst->ulong = NUM2ULONG(*src); break; #if HAVE_LONG_LONG case TYPE_LONG_LONG: - dst->slong_long = NUM2LL(src); + dst->slong_long = NUM2LL(*src); break; case -TYPE_LONG_LONG: - dst->ulong_long = NUM2ULL(src); + dst->ulong_long = NUM2ULL(*src); break; #endif case TYPE_FLOAT: - dst->ffloat = (float)NUM2DBL(src); + dst->ffloat = (float)NUM2DBL(*src); break; case TYPE_DOUBLE: - dst->ddouble = NUM2DBL(src); + 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 -generic_to_value(VALUE rettype, fiddle_generic retval) +rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) { int type = NUM2INT(rettype); VALUE cPointer; @@ -131,6 +307,13 @@ generic_to_value(VALUE rettype, fiddle_generic retval) 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); } @@ -138,4 +321,10 @@ generic_to_value(VALUE rettype, fiddle_generic retval) 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/ruby/ext/fiddle/conversions.h b/ruby/ext/fiddle/conversions.h index cbc610bad..c7c12a923 100644 --- a/ruby/ext/fiddle/conversions.h +++ b/ruby/ext/fiddle/conversions.h @@ -24,13 +24,22 @@ typedef union void * pointer; /* ffi_type_pointer */ } fiddle_generic; +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); +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) value_to_generic((_type), (_src), (_dst)) -#define INT2FFI_TYPE(_type) int_to_ffi_type(_type) -#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_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))) diff --git a/ruby/ext/fiddle/depend b/ruby/ext/fiddle/depend index 5ed745fa0..4d33d46d3 100644 --- a/ruby/ext/fiddle/depend +++ b/ruby/ext/fiddle/depend @@ -57,8 +57,155 @@ 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/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/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/gc.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/rgengc.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 @@ -74,8 +221,155 @@ 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/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/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/gc.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/rgengc.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 @@ -90,8 +384,155 @@ 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/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/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/gc.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/rgengc.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 @@ -106,8 +547,155 @@ 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/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/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/gc.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/rgengc.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 @@ -123,8 +711,155 @@ 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/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/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/gc.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/rgengc.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 @@ -134,15 +869,511 @@ 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/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/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/gc.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/rgengc.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/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/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/gc.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/rgengc.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/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/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/gc.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/rgengc.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 diff --git a/ruby/ext/fiddle/extconf.rb b/ruby/ext/fiddle/extconf.rb index fce0cb407..053456d53 100644 --- a/ruby/ext/fiddle/extconf.rb +++ b/ruby/ext/fiddle/extconf.rb @@ -3,23 +3,73 @@ # :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 = enable_config('bundled-libffi') -if ! bundle +unless bundle dir_config 'libffi' - pkg_config("libffi") and - ver = pkg_config("libffi", "modversion") + if pkg_config("libffi") + libffi_version = pkg_config("libffi", "modversion") + end + have_ffi_header = false if have_header(ffi_header = 'ffi.h') - true + have_ffi_header = true elsif have_header(ffi_header = 'ffi/ffi.h') - $defs.push(format('-DUSE_HEADER_HACKS')) - true - end and (have_library('ffi') || have_library('libffi')) -end or -begin + $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 # for https://github.com/ruby/fiddle - if bundle && File.exist?("../../bin/extlibs.rb") + extlibs_rb = File.expand_path("../../bin/extlibs.rb", $srcdir) + if bundle && File.exist?(extlibs_rb) require "fileutils" require_relative "../../bin/extlibs" extlibs = ExtLibs.new @@ -28,31 +78,32 @@ Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)} extlibs.run(["--cache=#{cache_dir}", ext_dir]) end - ver = bundle != false && - Dir.glob("#{$srcdir}/libffi-*/") - .map {|n| File.basename(n)} - .max_by {|n| n.scan(/\d+/).map(&:to_i)} - unless ver + if bundle != false + libffi_package_name = Dir.glob("#{$srcdir}/libffi-*/") + .map {|n| File.basename(n)} + .max_by {|n| n.scan(/\d+/).map(&:to_i)} + end + unless libffi_package_name raise "missing libffi. Please install libffi." end - srcdir = "#{$srcdir}/#{ver}" + libffi_srcdir = "#{$srcdir}/#{libffi_package_name}" ffi_header = 'ffi.h' libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new - libffi.dir = ver + libffi.dir = libffi_package_name if $srcdir == "." - libffi.builddir = "#{ver}/#{RUBY_PLATFORM}" + libffi.builddir = libffi_package_name libffi.srcdir = "." else libffi.builddir = libffi.dir - libffi.srcdir = relative_from(srcdir, "..") + 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) - ver = ver[/libffi-(.*)/, 1] + libffi_version = libffi_package_name[/libffi-(.*)/, 1] FileUtils.mkdir_p(libffi.dir) libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1] @@ -81,7 +132,6 @@ args.concat %W[ --srcdir=#{libffi.srcdir} --host=#{libffi.arch} - --enable-builddir=#{RUBY_PLATFORM} ] args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static') args << libffi.opt if libffi.opt @@ -98,7 +148,7 @@ begin IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile)) rescue SystemCallError => e - Logfile.message("%s\n", e.message) + Logging.message("%s\n", e.message) end raise "failed to configure libffi. Please install libffi." end @@ -107,18 +157,37 @@ FileUtils.rm_f("#{libffi.include}/ffitarget.h") end unless File.file?("#{libffi.include}/ffitarget.h") - FileUtils.cp("#{srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true) + FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true) end $INCFLAGS << " -I" << libffi.include end -if ver - ver = ver.gsub(/-rc\d+/, '') # If ver contains rc version, just ignored. - ver = (ver.split('.') + [0,0])[0,3] - $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver }}) +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" @@ -128,10 +197,14 @@ end have_func "dlerror" + have_func "dlinfo" + have_const("RTLD_DI_LINKMAP", "dlfcn.h") elsif have_header "windows.h" - %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func| + %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) @@ -142,11 +215,13 @@ if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config if size = $2 and size != 'VOIDP' size = types.fetch(size) {size} - $defs << format("-DTYPE_%s=TYPE_%s", signed||type, 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 @@ -154,7 +229,6 @@ $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)') end -$INCFLAGS << " -I$(top_srcdir)" create_makefile 'fiddle' do |conf| if !libffi next conf << "LIBFFI_CLEAN = none\n" diff --git a/ruby/ext/fiddle/extlibs b/ruby/ext/fiddle/extlibs index 1f0c9348e..68dac46a9 100644 --- a/ruby/ext/fiddle/extlibs +++ b/ruby/ext/fiddle/extlibs @@ -1,5 +1,13 @@ -https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/libffi-3.2.1.tar.gz \ +ver = 3.2.1 +pkg = libffi-$(ver) + +https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/$(pkg).tar.gz \ md5:83b89587607e3eb65c70d361f13bab43 \ sha512:980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483 \ # - win32/libffi-3.2.1-mswin.patch -p0 + win32/$(pkg)-mswin.patch -p0 + +$(pkg)/config.guess -> /tool/config.guess +$(pkg)/config.sub -> /tool/config.sub + +! chdir: $(pkg)| autoconf || exit 0 diff --git a/ruby/ext/fiddle/fiddle.c b/ruby/ext/fiddle/fiddle.c index 9f3d1537d..a8b512326 100644 --- a/ruby/ext/fiddle/fiddle.c +++ b/ruby/ext/fiddle/fiddle.c @@ -1,41 +1,15 @@ #include VALUE mFiddle; +VALUE rb_eFiddleDLError; VALUE rb_eFiddleError; -#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 +void Init_fiddle_pointer(void); +void Init_fiddle_pinned(void); -#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 +#ifdef HAVE_RUBY_MEMORY_VIEW_H +void Init_fiddle_memory_view(void); #endif -#define TYPE_UINTPTR_T (-TYPE_INTPTR_T) - -void Init_fiddle_pointer(void); /* * call-seq: Fiddle.malloc(size) @@ -47,8 +21,7 @@ static VALUE rb_fiddle_malloc(VALUE self, VALUE size) { void *ptr; - - ptr = (void*)ruby_xmalloc(NUM2SIZET(size)); + ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size)); return PTR2NUM(ptr); } @@ -163,12 +136,33 @@ Init_fiddle(void) */ 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_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError); + rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError); /* Document-const: TYPE_VOID * @@ -214,6 +208,38 @@ Init_fiddle(void) rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG)); #endif +#ifdef TYPE_INT8_T + /* Document-const: TYPE_INT8_T + * + * C type - int8_t + */ + rb_define_const(mFiddle, "TYPE_INT8_T", INT2NUM(TYPE_INT8_T)); +#endif + +#ifdef TYPE_INT16_T + /* Document-const: TYPE_INT16_T + * + * C type - int16_t + */ + rb_define_const(mFiddle, "TYPE_INT16_T", INT2NUM(TYPE_INT16_T)); +#endif + +#ifdef TYPE_INT32_T + /* Document-const: TYPE_INT32_T + * + * C type - int32_t + */ + rb_define_const(mFiddle, "TYPE_INT32_T", INT2NUM(TYPE_INT32_T)); +#endif + +#ifdef TYPE_INT64_T + /* Document-const: TYPE_INT64_T + * + * C type - int64_t + */ + rb_define_const(mFiddle, "TYPE_INT64_T", INT2NUM(TYPE_INT64_T)); +#endif + /* Document-const: TYPE_FLOAT * * C type - float @@ -226,6 +252,20 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE)); +#ifdef HAVE_FFI_PREP_CIF_VAR + /* Document-const: TYPE_VARIADIC + * + * C type - ... + */ + rb_define_const(mFiddle, "TYPE_VARIADIC", INT2NUM(TYPE_VARIADIC)); +#endif + + /* Document-const: TYPE_CONST_STRING + * + * C type - const char* ('\0' terminated const char*) + */ + rb_define_const(mFiddle, "TYPE_CONST_STRING", INT2NUM(TYPE_CONST_STRING)); + /* Document-const: TYPE_SIZE_T * * C type - size_t @@ -294,6 +334,30 @@ Init_fiddle(void) 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 @@ -384,6 +448,30 @@ Init_fiddle(void) rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(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_INT16_T + * + * size of a int16_t + */ + rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_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_INT64_T + * + * size of a int64_t + */ + rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t))); + /* Document-const: SIZEOF_FLOAT * * size of a float @@ -426,6 +514,12 @@ Init_fiddle(void) */ 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: RUBY_FREE * * Address of the ruby_xfree() function @@ -450,5 +544,10 @@ Init_fiddle(void) 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/ruby/ext/fiddle/fiddle.gemspec b/ruby/ext/fiddle/fiddle.gemspec index b29f4ec78..a9c0ec402 100644 --- a/ruby/ext/fiddle/fiddle.gemspec +++ b/ruby/ext/fiddle/fiddle.gemspec @@ -1,23 +1,62 @@ # 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 = '1.0.0' + 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/fiddle/closure.c", "ext/fiddle/closure.h", "ext/fiddle/conversions.c", "ext/fiddle/conversions.h", "ext/fiddle/extconf.rb", "ext/fiddle/extlibs", "ext/fiddle/fiddle.c", "ext/fiddle/fiddle.h", "ext/fiddle/function.c", "ext/fiddle/function.h", "ext/fiddle/handle.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"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.files = [ + "LICENSE.txt", + "README.md", + "Rakefile", + "bin/downloader.rb", + "bin/extlibs.rb", + "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/extlibs", + "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.3.0" + spec.required_ruby_version = ">= 2.5.0" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "rake-compiler" + spec.metadata["msys2_mingw_dependencies"] = "libffi" end diff --git a/ruby/ext/fiddle/fiddle.h b/ruby/ext/fiddle/fiddle.h index d2583c1cb..9de62a58c 100644 --- a/ruby/ext/fiddle/fiddle.h +++ b/ruby/ext/fiddle/fiddle.h @@ -12,6 +12,10 @@ #include #endif +#if defined(HAVE_LINK_H) +# include +#endif + #if defined(HAVE_DLFCN_H) # include # /* some stranger systems may not define all of these */ @@ -58,38 +62,38 @@ # 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_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_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 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 @@ -115,12 +119,67 @@ #endif #define TYPE_FLOAT 7 #define TYPE_DOUBLE 8 +#define TYPE_VARIADIC 9 +#define TYPE_CONST_STRING 10 + +#define TYPE_INT8_T TYPE_CHAR +#if SIZEOF_SHORT == 2 +# define TYPE_INT16_T TYPE_SHORT +#elif SIZEOF_INT == 2 +# define TYPE_INT16_T TYPE_INT +#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 +#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 + +#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) #define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) #define ALIGN_VOIDP ALIGN_OF(void*) -#define ALIGN_SHORT ALIGN_OF(short) #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 @@ -129,10 +188,18 @@ #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_eFiddleError; +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/ruby/ext/fiddle/function.c b/ruby/ext/fiddle/function.c index 994402e26..274d181d1 100644 --- a/ruby/ext/fiddle/function.c +++ b/ruby/ext/fiddle/function.c @@ -1,6 +1,8 @@ #include #include +#include + #ifdef PRIsVALUE # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) # define RB_OBJ_STRING(obj) (obj) @@ -19,21 +21,21 @@ VALUE cFiddleFunction; #define Check_Max_Args_Long(name, len) \ Check_Max_Args_(name, len, "l") #define Check_Max_Args_(name, len, fmt) \ - if ((size_t)(len) < MAX_ARGS) { \ - /* OK */ \ - } \ - else { \ - rb_raise(rb_eTypeError, \ - name" is so large that it can cause integer overflow (%"fmt"d)", \ - (len)); \ - } + 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 *ptr = p; - if (ptr->arg_types) xfree(ptr->arg_types); - xfree(ptr); + ffi_cif *cif = p; + if (cif->arg_types) xfree(cif->arg_types); + xfree(cif); } static size_t @@ -75,74 +77,114 @@ rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type) return rb_class_new_instance(3, argv, cFiddleFunction); } -static int -parse_keyword_arg_i(VALUE key, VALUE value, VALUE self) +static VALUE +normalize_argument_types(const char *name, + VALUE arg_types, + bool *is_variadic) { - if (key == ID2SYM(rb_intern("name"))) { - rb_iv_set(self, "@name", value); - } else { - rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, - RB_OBJ_STRING(key)); + 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)); } - return ST_CONTINUE; + + /* 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; - ffi_type **arg_types, *rtype; - ffi_status result; - VALUE ptr, args, ret_type, abi, kwds, ary; - int i, len; - int nabi; + 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, &args, &ret_type, &abi, &kwds); + 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); - nabi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi); - abi = INT2FIX(nabi); - i = NUM2INT(ret_type); - rtype = INT2FFI_TYPE(i); - ret_type = INT2FIX(i); - - Check_Type(args, T_ARRAY); - len = RARRAY_LENINT(args); - Check_Max_Args("args", len); - ary = rb_ary_subseq(args, 0, len); - for (i = 0; i < RARRAY_LEN(args); i++) { - VALUE a = RARRAY_AREF(args, i); - int type = NUM2INT(a); - (void)INT2FFI_TYPE(type); /* raise */ - if (INT2FIX(type) != a) rb_ary_store(ary, i, INT2FIX(type)); + 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"); } - OBJ_FREEZE(ary); +#endif rb_iv_set(self, "@ptr", ptr); - rb_iv_set(self, "@args", args); + rb_iv_set(self, "@argument_types", arg_types); rb_iv_set(self, "@return_type", ret_type); rb_iv_set(self, "@abi", abi); - - if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self); + rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse); TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); - - arg_types = xcalloc(len + 1, sizeof(ffi_type *)); - - for (i = 0; i < RARRAY_LEN(args); i++) { - int type = NUM2INT(RARRAY_AREF(args, i)); - arg_types[i] = INT2FFI_TYPE(type); - } - arg_types[len] = NULL; - - result = ffi_prep_cif(cif, nabi, len, rtype, arg_types); - - if (result) - rb_raise(rb_eRuntimeError, "error creating CIF %d", result); + cif->arg_types = NULL; return self; } @@ -169,52 +211,182 @@ function_call(int argc, VALUE argv[], VALUE self) { struct nogvl_ffi_call_args args = { 0 }; fiddle_generic *generic_args; - VALUE cfunc, types, cPointer; + 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"); - types = rb_iv_get(self, "@args"); + abi = rb_iv_get(self, "@abi"); + arg_types = rb_iv_get(self, "@argument_types"); cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - Check_Max_Args("number of arguments", argc); - if (argc != (i = RARRAY_LENINT(types))) { - rb_error_arity(argc, i, i); + 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, - (size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic)); + sizeof(fiddle_generic) * n_call_args + + sizeof(void *) * (n_call_args + 1)); args.values = (void **)((char *)generic_args + - (size_t)argc * sizeof(fiddle_generic)); - - for (i = 0; i < argc; i++) { - VALUE type = RARRAY_AREF(types, i); - VALUE src = argv[i]; - int argtype = FIX2INT(type); - - if (argtype == TYPE_VOIDP) { - if(NIL_P(src)) { - src = INT2FIX(0); - } else if(cPointer != CLASS_OF(src)) { - src = rb_funcall(cPointer, rb_intern("[]"), 1, src); - } - src = rb_Integer(src); - } - - VALUE2GENERIC(argtype, src, &generic_args[i]); - args.values[i] = (void *)&generic_args[i]; + 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[argc] = NULL; + args.values[i_call] = NULL; args.fn = (void(*)(void))NUM2PTR(cfunc); - (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0); + 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); + } - rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno)); + { + int errno_keep = errno; #if defined(_WIN32) - rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno)); + 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); @@ -287,6 +459,10 @@ Init_fiddle_function(void) * 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 * */ @@ -294,13 +470,20 @@ Init_fiddle_function(void) /* * Document-method: new - * call-seq: new(ptr, args, ret_type, abi = DEFAULT) + * 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); diff --git a/ruby/ext/fiddle/handle.c b/ruby/ext/fiddle/handle.c index 700924afb..76b90909d 100644 --- a/ruby/ext/fiddle/handle.c +++ b/ruby/ext/fiddle/handle.c @@ -74,14 +74,14 @@ rb_fiddle_handle_close(VALUE self) /* Check dlclose for successful return value */ if(ret) { #if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleError, "%s", dlerror()); + rb_raise(rb_eFiddleDLError, "%s", dlerror()); #else - rb_raise(rb_eFiddleError, "could not close handle"); + rb_raise(rb_eFiddleDLError, "could not close handle"); #endif } return INT2NUM(ret); } - rb_raise(rb_eFiddleError, "dlclose() called too many times"); + rb_raise(rb_eFiddleDLError, "dlclose() called too many times"); UNREACHABLE; } @@ -177,12 +177,12 @@ rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self) ptr = dlopen(clib, cflag); #if defined(HAVE_DLERROR) if( !ptr && (err = dlerror()) ){ - rb_raise(rb_eFiddleError, "%s", err); + rb_raise(rb_eFiddleDLError, "%s", err); } #else if( !ptr ){ err = dlerror(); - rb_raise(rb_eFiddleError, "%s", err); + rb_raise(rb_eFiddleDLError, "%s", err); } #endif TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); @@ -259,7 +259,21 @@ 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); + 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); @@ -278,7 +292,7 @@ rb_fiddle_handle_sym(VALUE self, VALUE sym) TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); if( ! fiddle_handle->open ){ - rb_raise(rb_eFiddleError, "closed handle"); + rb_raise(rb_eFiddleDLError, "closed handle"); } return fiddle_handle_sym(fiddle_handle->ptr, sym); @@ -366,12 +380,54 @@ fiddle_handle_sym(void *handle, VALUE symbol) } #endif if( !func ){ - rb_raise(rb_eFiddleError, "unknown symbol \"%"PRIsVALUE"\"", symbol); + 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) { @@ -466,9 +522,11 @@ Init_fiddle_handle(void) 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, "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); diff --git a/ruby/ext/fiddle/lib/fiddle.rb b/ruby/ext/fiddle/lib/fiddle.rb index e9aa7e50a..451298931 100644 --- a/ruby/ext/fiddle/lib/fiddle.rb +++ b/ruby/ext/fiddle/lib/fiddle.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true + require 'fiddle.so' -require 'fiddle/function' require 'fiddle/closure' +require 'fiddle/function' +require 'fiddle/version' module Fiddle if WINDOWS @@ -15,6 +17,18 @@ def self.win32_last_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 diff --git a/ruby/ext/fiddle/lib/fiddle/cparser.rb b/ruby/ext/fiddle/lib/fiddle/cparser.rb index cd0a64fef..93a05513c 100644 --- a/ruby/ext/fiddle/lib/fiddle/cparser.rb +++ b/ruby/ext/fiddle/lib/fiddle/cparser.rb @@ -35,12 +35,37 @@ module CParser 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) + 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)) @@ -123,55 +148,97 @@ def parse_signature(signature, tymap=nil) # def parse_ctype(ty, tymap=nil) tymap ||= {} - case ty - when Array + 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 /^(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?$/ - if( defined?(TYPE_LONG_LONG) ) - return TYPE_LONG_LONG - else + 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 - when /^(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?$/ - if( defined?(TYPE_LONG_LONG) ) - return -TYPE_LONG_LONG - else + 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 - when /^(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?$/ + return -TYPE_LONG_LONG + when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_LONG - when /^unsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?$/ + when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/ return -TYPE_LONG - when /^(?:signed\s+)?int(?:\s+\w+)?$/ + when /\A(?:signed\s+)?int(?:\s+\w+)?\z/ return TYPE_INT - when /^(?:unsigned\s+int|uint)(?:\s+\w+)?$/ + when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/ return -TYPE_INT - when /^(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?$/ + when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_SHORT - when /^unsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?$/ + when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/ return -TYPE_SHORT - when /^(?:signed\s+)?char(?:\s+\w+)?$/ + when /\A(?:signed\s+)?char(?:\s+\w+)?\z/ return TYPE_CHAR - when /^unsigned\s+char(?:\s+\w+)?$/ + when /\Aunsigned\s+char(?:\s+\w+)?\z/ return -TYPE_CHAR - when /^float(?:\s+\w+)?$/ + 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_INT8_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_INT16_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_INT32_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_INT64_T + when /\Afloat(?:\s+\w+)?\z/ return TYPE_FLOAT - when /^double(?:\s+\w+)?$/ + when /\Adouble(?:\s+\w+)?\z/ return TYPE_DOUBLE - when /^size_t(?:\s+\w+)?$/ + when /\Asize_t(?:\s+\w+)?\z/ return TYPE_SIZE_T - when /^ssize_t(?:\s+\w+)?$/ + when /\Assize_t(?:\s+\w+)?\z/ return TYPE_SSIZE_T - when /^ptrdiff_t(?:\s+\w+)?$/ + when /\Aptrdiff_t(?:\s+\w+)?\z/ return TYPE_PTRDIFF_T - when /^intptr_t(?:\s+\w+)?$/ + when /\Aintptr_t(?:\s+\w+)?\z/ return TYPE_INTPTR_T - when /^uintptr_t(?:\s+\w+)?$/ + when /\Auintptr_t(?:\s+\w+)?\z/ return TYPE_UINTPTR_T when /\*/, /\[[\s\d]*\]/ return TYPE_VOIDP + when "..." + return TYPE_VARIADIC else ty = ty.split(' ', 2)[0] if( tymap[ty] ) @@ -186,7 +253,7 @@ def parse_ctype(ty, tymap=nil) def split_arguments(arguments, sep=',') return [] if arguments.strip == 'void' - arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+)(?:#{sep}\s*|$)/).collect {|m| m[0]} + arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]} end def compact(signature) diff --git a/ruby/ext/fiddle/lib/fiddle/function.rb b/ruby/ext/fiddle/lib/fiddle/function.rb index dd5e04e41..dc2e3e6bf 100644 --- a/ruby/ext/fiddle/lib/fiddle/function.rb +++ b/ruby/ext/fiddle/lib/fiddle/function.rb @@ -10,9 +10,20 @@ class Function # 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/ruby/ext/fiddle/lib/fiddle/import.rb b/ruby/ext/fiddle/lib/fiddle/import.rb index 178ebb8c7..09ffcef54 100644 --- a/ruby/ext/fiddle/lib/fiddle/import.rb +++ b/ruby/ext/fiddle/lib/fiddle/import.rb @@ -83,11 +83,7 @@ def dlload(*libs) when Importer lib.handlers else - begin - Fiddle.dlopen(lib) - rescue DLError - raise(DLError, "can't load #{lib}") - end + Fiddle.dlopen(lib) end }.flatten() @handler = CompositeHandler.new(handles) @@ -121,6 +117,8 @@ def sizeof(ty) 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 diff --git a/ruby/ext/fiddle/lib/fiddle/struct.rb b/ruby/ext/fiddle/lib/fiddle/struct.rb index 7c0dedb39..6d05bbd74 100644 --- a/ruby/ext/fiddle/lib/fiddle/struct.rb +++ b/ruby/ext/fiddle/lib/fiddle/struct.rb @@ -4,20 +4,168 @@ require 'fiddle/pack' module Fiddle - # C struct shell + # 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 - # C union shell + # 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) @@ -35,7 +183,7 @@ module CStructBuilder # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. # - # Example: + # Examples: # # require 'fiddle/struct' # require 'fiddle/cparser' @@ -46,47 +194,113 @@ module CStructBuilder # # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) # - # obj = MyStruct.allocate + # 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| - @entity = klass.entity_class.new(addr, types) + 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 } } - } - size = klass.entity_class.size(types) - new_class.module_eval(<<-EOS, __FILE__, __LINE__+1) - def new_class.size() - #{size} - end - def new_class.malloc() - addr = Fiddle.malloc(#{size}) - new(addr) + 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 - EOS + } return new_class end module_function :create end - # A C struct wrapper + # 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. # - # When the instance is garbage collected, the C function +func+ is called. - def CStructEntity.malloc(types, func = nil) - addr = Fiddle.malloc(CStructEntity.size(types)) - CStructEntity.new(addr, types, func) + # 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+. @@ -102,9 +316,15 @@ def CStructEntity.size(types) max_align = types.map { |type, count = 1| last_offset = offset - align = PackInfo::ALIGN_MAP[type] + 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) + - (PackInfo::SIZE_MAP[type] * count) + (type_size * count) align }.max @@ -118,13 +338,37 @@ def CStructEntity.size(types) # # 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 = 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. @@ -135,12 +379,18 @@ def set_ctypes(types) max_align = types.map { |type, count = 1| orig_offset = offset - align = ALIGN_MAP[type] + 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 += (SIZE_MAP[type] * count) + offset += (type_size * count) align }.max @@ -148,15 +398,34 @@ def set_ctypes(types) @size = PackInfo.align(offset, max_align) end - # Fetch struct member +name+ - def [](name) + # 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) ) - r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) + 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 @@ -176,14 +445,44 @@ def [](name) 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])} + return StructArray.new(self + @offset[idx], ty[0], val) else return val end end - # Set struct member +name+, to value +val+ - def []=(name, val) + # 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}") @@ -202,23 +501,16 @@ def []=(name, val) end end + undef_method :size= def to_s() # :nodoc: super(@size) end end - # A C union wrapper + # A pointer to a C union class CUnionEntity < CStructEntity include PackInfo - # Allocates a C union the +types+ provided. - # - # When the instance is garbage collected, the C function +func+ is called. - def CUnionEntity.malloc(types, func=nil) - addr = Fiddle.malloc(CUnionEntity.size(types)) - CUnionEntity.new(addr, types, func) - end - # Returns the size needed for the union with the given +types+. # # Fiddle::CUnionEntity.size( @@ -228,7 +520,11 @@ def CUnionEntity.malloc(types, func=nil) # Fiddle::TYPE_VOIDP ]) #=> 8 def CUnionEntity.size(types) types.map { |type, count = 1| - PackInfo::SIZE_MAP[type] * count + if type.respond_to?(:entity_class) + type.size * count + else + PackInfo::SIZE_MAP[type] * count + end }.max end @@ -241,4 +537,3 @@ def set_ctypes(types) end end end - diff --git a/ruby/ext/fiddle/lib/fiddle/types.rb b/ruby/ext/fiddle/lib/fiddle/types.rb index 8dc811d3e..7baf31ec9 100644 --- a/ruby/ext/fiddle/lib/fiddle/types.rb +++ b/ruby/ext/fiddle/lib/fiddle/types.rb @@ -27,28 +27,29 @@ module Fiddle # * WORD module Win32Types def included(m) # :nodoc: + # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types m.module_eval{ - typealias "DWORD", "unsigned long" - typealias "PDWORD", "unsigned long *" - typealias "DWORD32", "unsigned long" - typealias "DWORD64", "unsigned long long" - typealias "WORD", "unsigned short" - typealias "PWORD", "unsigned short *" + typealias "ATOM", "WORD" typealias "BOOL", "int" - typealias "ATOM", "int" typealias "BYTE", "unsigned char" - typealias "PBYTE", "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 "UCHAR", "unsigned char" - typealias "HANDLE", "uintptr_t" - typealias "PHANDLE", "void*" - typealias "PVOID", "void*" - typealias "LPCSTR", "char*" - typealias "LPSTR", "char*" - typealias "HINSTANCE", "unsigned int" - typealias "HDC", "unsigned int" - typealias "HWND", "unsigned int" + typealias "WORD", "unsigned short" } end module_function :included diff --git a/ruby/ext/fiddle/lib/fiddle/version.rb b/ruby/ext/fiddle/lib/fiddle/version.rb new file mode 100644 index 000000000..db6504b65 --- /dev/null +++ b/ruby/ext/fiddle/lib/fiddle/version.rb @@ -0,0 +1,3 @@ +module Fiddle + VERSION = "1.1.0" +end diff --git a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog b/ruby/ext/fiddle/libffi-3.2.1/ChangeLog deleted file mode 100644 index 68990e32c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog +++ /dev/null @@ -1,5505 +0,0 @@ -commit 20562ac0427c3578250d04c6e34fb0127d4551cf -Author: Anthony Green -Date: Wed Nov 12 07:00:59 2014 -0500 - - Fix for AArch64. Release as 3.2.1. - -commit a0bdc5250cd36f1d2578358e33299fd2408091ac -Author: Anthony Green -Date: Tue Nov 11 09:43:01 2014 -0500 - - Fix typo - -commit 67c0c0705318d2e567fd48e680d63dca3619a235 -Author: Anthony Green -Date: Tue Nov 11 07:30:49 2014 -0500 - - Final 3.2 changes - -commit ee826b933bbdeb68ee81876ffb508c3908eed371 -Author: Anthony Green -Date: Tue Nov 11 07:29:26 2014 -0500 - - Final 3.2 changes - -commit c81a705d53be97899d314953987936213244b1ba -Author: Anthony Green -Date: Tue Nov 4 13:29:58 2014 -0500 - - Mention OpenRISC - -commit 6a17ad540d7ddb7a812687f4380bd0ef2d2865bb -Merge: 990eb9d 0f316ab -Author: Anthony Green -Date: Sun Sep 28 00:54:00 2014 -0400 - - Merge pull request #134 from s-macke/openrisc - - Add OpenRISC support - -commit 990eb9d4c244324771a7d878a168bb8eba1850c0 -Author: Anthony Green -Date: Sun Sep 28 00:50:29 2014 -0400 - - Only run the complex type tests on supported platforms. - -commit 0f316ab7c11b8315a838a6ae4645d36ff2c46f4c -Author: Sebastian Macke -Date: Sat Sep 27 00:19:15 2014 +0000 - - Add OpenRISC support - - This patch adds support for the OpenRISC architecture. - (http://opencores.org/or1k/Main_Page) - - This patch has been tested under Linux with QEMU-user emulation support. - - 32 Bit - - big endian - - delayed instructions - This is the only available configuration under Linux. - - The description of the ABI can be found on the official website. - - Is passes the testsuite except of the unwindtest_ffi_call.cc - testcase, which seems to be a problem of gcc and not libffi. - Some testcases of the gcc testsuite still fail. - - Signed-off-by: Sebastian Macke - -commit 6695983d2f0857caab220862de12f3f94a55bcf6 -Author: Anthony Green -Date: Sat Sep 20 07:44:37 2014 -0400 - - Add complex type support. Mostly broken right now - -commit fbbf48fbdf9b1491af0aefc00523a1b5d8bb9349 -Author: Anthony Green -Date: Sat Sep 20 07:43:51 2014 -0400 - - Compile tests with -Wno-psabi when using GCC - -commit ae8d2554c5f192be54dadc9f99a1449b4df1b222 -Author: Anthony Green -Date: Sat Sep 20 07:08:37 2014 -0400 - - Update version to 3.2 - -commit b2ca59d39d2192021316561ea9dda3d35d8d35d9 -Author: Anthony Green -Date: Sat Sep 20 07:08:05 2014 -0400 - - More README updates for 3.2 - -commit f920a01ad8eafc79daaf331499ef9a97696c46a7 -Author: Anthony Green -Date: Sat Sep 20 06:54:06 2014 -0400 - - Update release notes. - -commit bfcbf329c5e4bebdb32134d4e53260e17e4e66cc -Author: Bernd Edlinger -Date: Sat Sep 20 06:51:45 2014 -0400 - - 2014-05-11 Bernd Edlinger - - Fix current cygwin-64 build problems. - * src/java_raw_api.c: Remove if !defined(FFI_NO_RAW_API). - * src/x86/ffi.c: Add if defined(__CYGWIN__). - * src/x86/win64.S (ffi_closure_win64, ffi_call_win64): Added - handling for FFI_TYPE_UINT64, FFI_TYPE_POINTER and FFI_TYPE_INT. - Added SEH information. Fixed formatting. - -commit 32cb2ce81db9457c6bd43a2587d7fa23a2edb9b1 -Author: Jakub Jelinek -Date: Sat Sep 20 06:39:55 2014 -0400 - - 2014-09-10 Jakub Jelinek - - * src/powerpc/linux64.S: Emit .note.GNU-stack even when - POWERPC64 is not defined. - * src/powerpc/linux64_closure.S: Likewise. Also test _CALL_ELF == 2. - -commit aaf3101ba81af8f488502881648e3f687721671e -Author: Matthias Klose -Date: Sat Sep 20 06:37:04 2014 -0400 - - Fix -Werror=declaration-after-statement problem - -commit 6e8a4460833594d5af1b4539178025da0077df19 -Author: Dominik Vogt -Date: Sat Sep 20 06:21:19 2014 -0400 - - 2014-07-22 Dominik Vogt - - * src/types.c (FFI_TYPEDEF, FFI_NONCONST_TYPEDEF): Merge the macros by - adding another argument that controls whether the result is const or not - (FFI_LDBL_CONST): Temporary macro to reduce ifdef confusion - * src/prep_cif.c (ffi_prep_cif_core): Replace list of systems with new - macro FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION - * src/pa/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): - Define. - * src/s390/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): - Define. - * src/x86/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): - Define. - - 2014-07-22 Dominik Vogt - - * doc/libffi.texi (Primitive Types): Document ffi_type_complex_float, - ffi_type_complex_double and ffi_type_complex_longdouble - (Complex Types): New subsection. - (Complex Type Example): Ditto. - * testsuite/libffi.call/cls_align_complex_double.c: New - FFI_TYPE_COMPLEX test. - * testsuite/libffi.call/cls_align_complex_float.c: Ditto. - * testsuite/libffi.call/cls_align_complex_longdouble.c: Ditto. - * testsuite/libffi.call/cls_complex_double.c: Ditto. - * testsuite/libffi.call/cls_complex_float.c: Ditto. - * testsuite/libffi.call/cls_complex_longdouble.c: Ditto. - * testsuite/libffi.call/cls_complex_struct_double.c: Ditto. - * testsuite/libffi.call/cls_complex_struct_float.c: Ditto. - * testsuite/libffi.call/cls_complex_struct_longdouble.c: Ditto. - * testsuite/libffi.call/cls_complex_va_double.c: Ditto. - * testsuite/libffi.call/cls_complex_va_float.c: Ditto. - * testsuite/libffi.call/cls_complex_va_longdouble.c: Ditto. - * testsuite/libffi.call/complex_double.c: Ditto. - * testsuite/libffi.call/complex_defs_double.c: Ditto. - * testsuite/libffi.call/complex_float.c: Ditto. - * testsuite/libffi.call/complex_defs_float.c: Ditto. - * testsuite/libffi.call/complex_longdouble.c: Ditto. - * testsuite/libffi.call/complex_defs_longdouble.c: Ditto. - * testsuite/libffi.call/complex_int.c: Ditto. - * testsuite/libffi.call/many_complex_double.c: Ditto. - * testsuite/libffi.call/many_complex_float.c: Ditto. - * testsuite/libffi.call/many_complex_longdouble.c: Ditto. - * testsuite/libffi.call/return_complex1_double.c: Ditto. - * testsuite/libffi.call/return_complex1_float.c: Ditto. - * testsuite/libffi.call/return_complex1_longdouble.c: Ditto. - * testsuite/libffi.call/return_complex2_double.c: Ditto. - * testsuite/libffi.call/return_complex2_float.c: Ditto. - * testsuite/libffi.call/return_complex2_longdouble.c: Ditto. - * testsuite/libffi.call/return_complex_double.c: Ditto. - * testsuite/libffi.call/return_complex_float.c: Ditto. - * testsuite/libffi.call/return_complex_longdouble.c: Ditto. - * src/raw_api.c (ffi_raw_to_ptrarray): Handle FFI_TYPE_COMPLEX - (ffi_ptrarray_to_raw): Ditto. - * src/prep_cif.c (ffi_prep_cif_core): Abort if FFI_TYPE_COMPLEX is not - implemented in libffi for the target. - * src/java_raw_api.c (ffi_java_raw_size): FFI_TYPE_COMPLEX not supported - yet (abort). - (ffi_java_raw_to_ptrarray): Ditto. - (ffi_java_rvalue_to_raw): Ditto. - (ffi_java_raw_to_rvalue): Ditto. - * src/debug.c (ffi_type_test): Add debug tests for complex types. - * include/ffi.h.in (FFI_TYPE_COMPLEX): Add new FFI_TYPE_COMPLEX. - (FFI_TYPE_LAST): Bump. - (ffi_type_complex_float): Add new ffi_type_.... - (ffi_type_complex_double): Ditto. - (ffi_type_complex_longdouble): Ditto. - - 2014-07-22 Dominik Vogt - - * src/s390/ffitarget.h (FFI_TARGET_HAS_COMPLEX_TYPE): Define to provide - FFI_TYPE_COMPLEX support. - * src/s390/ffi.c (ffi_check_struct_type): Implement FFI_TYPE_COMPLEX - (ffi_prep_args): Ditto. - (ffi_prep_cif_machdep): Ditto. - (ffi_closure_helper_SYSV): Ditto. - -commit 4c5c4088aa3e4d8103ff9ca441937da64fdd849a -Merge: 862f53d 5d6340e -Author: Anthony Green -Date: Thu Sep 18 19:10:54 2014 -0400 - - Merge pull request #132 from nielsAD/master - - Pascal and Register calling convention support on x86 - -commit 862f53de04ff898a128be7eec592bae60930d6df -Merge: 5df3840 aebf2c3 -Author: Anthony Green -Date: Thu Sep 18 19:06:08 2014 -0400 - - Merge pull request #130 from frida/fix/darwin-aarch64-float-alignment - - Fix alignment of FFI_TYPE_FLOAT for Apple's ARM64 ABI - -commit 5df384077f3633ec8cf2e08f9199e5a44994dbad -Merge: 7b7a528 0f4e09d -Author: Anthony Green -Date: Thu Sep 18 19:05:35 2014 -0400 - - Merge pull request #129 from frida/fix/darwin-aarch64-cif-prep - - Fix non-variadic CIF initialization for Apple/ARM64 - -commit 7b7a5284de7a99edfcee5ac362dbf76251698e1e -Merge: 4cd5e84 6172a99 -Author: Anthony Green -Date: Thu Sep 18 18:28:05 2014 -0400 - - Merge pull request #124 from knuesel/master - - Fix issue with builddir when calling configure with absolute path - -commit 4cd5e840122e22636b5838943372c4ed74618e35 -Merge: 1cee07b 08853e3 -Author: Anthony Green -Date: Thu Sep 18 18:27:15 2014 -0400 - - Merge pull request #123 from ehsan/clang-cl - - Add support for building with clang-cl - -commit 5d6340ef2cf81432da79ac8b0b1b1218ab391438 -Author: nielsAD -Date: Mon Aug 25 17:29:44 2014 +0200 - - Determine whether register arguments (THISCALL/FASTCALL/REGISTER) are really passed via register to closures. Use stack if not. - -commit 6e346487b879b4b056a847268e381ae6efec4c21 -Author: nielsAD -Date: Mon Aug 25 12:23:29 2014 +0200 - - Fixed THISCALL/FASTCALL closures and added basic support for PASCAL/REGISTER closures. - -commit 098dca6b31e42dd0256ed7d966729e31961f1461 -Author: nielsAD -Date: Sat Aug 23 00:18:47 2014 +0200 - - Support for calling functions with PASCAL and REGISTER calling conventions on x86 Windows/Linux. - Also changed indentation to be more consistent throughout the (adjusted) files. - -commit 08853e32fb6b750cda664ee6d3290d340429dd4d -Author: Ehsan Akhgari -Date: Thu Jul 31 20:33:33 2014 -0400 - - Enable forcing the usage of the static CRT in libffi's msvc wrapper - - This is required for AddressSanitizer builds with clang-cl. - -commit aebf2c3023b5ff056a708dc34169f7b549b2ec4f -Author: Ole André Vadla Ravnås -Date: Fri Jul 25 21:40:50 2014 +0200 - - Fix alignment of FFI_TYPE_FLOAT for Apple's ARM64 ABI - -commit 0f4e09d27dc175ce3e95d070b794351663c7220e -Author: Ole André Vadla Ravnås -Date: Sat Jul 26 00:11:06 2014 +0200 - - Fix non-variadic CIF initialization for Apple/ARM64 - - Turns out `aarch64_nfixedargs` wasn't initialized in the non-variadic - case, resulting in undefined behavior when allocating arguments. - -commit 6172a995e14bdbc6150aa02a361f710626a5c293 -Author: Jeremie Knuesel -Date: Wed Jun 25 12:28:17 2014 +0200 - - Fix issue with builddir when calling configure with absolute path - -commit fb25cd08ed5a87640b02f0feeb10a09b37cfddbe -Author: Ehsan Akhgari -Date: Wed Jun 11 12:07:24 2014 -0400 - - Add support for building with clang-cl - -commit 1cee07be4712411baa5eb8af22698bc8443a6d6e -Author: Anthony Green -Date: Thu Jun 12 06:30:59 2014 -0400 - - Remove compiler warning - -commit ad0d1d239afc7ad09203847793dcc020856d1035 -Author: Samuli Suominen -Date: Thu Jun 12 06:30:21 2014 -0400 - - Fix paths in libffi.pc.in - -commit df31a85103b0cc232bbc340d7e782a3853c7fad5 -Merge: 69289c1 360aa8c -Author: Anthony Green -Date: Fri Jun 6 08:24:35 2014 -0400 - - Merge pull request #122 from rvandermeulen/1014976 - - Don't make --enable-debug imply using the debug CRT in libffi - -commit 360aa8ca1ead2fdaefa7b1c6f01ad001d8abae7e -Author: Mike Hommey -Date: Mon Jun 2 09:21:10 2014 -0400 - - Bug 1014976 - Don't make --enable-debug imply using the debug CRT in libffi. - -commit 69289c10b0acb4b52c8b5df4cf738193c618db40 -Author: Anthony Green -Date: Sat May 31 08:54:08 2014 -0400 - - Prepare for libffi 3.1.1 - -commit 978c9540154d320525488db1b7049277122f736d -Author: Samuli Suominen -Date: Sat May 31 08:53:10 2014 -0400 - - Add missing GNU stack markings in win32.S - -commit cbc5a3c0200aa6c2cf8d6798d69a21501557c83f -Author: Ryan Hill -Date: Sat May 31 08:26:34 2014 -0400 - - Fix typo - -commit 9d8e3018ac3d0d338373bff7eefa9f006746f4ec -Author: Anthony Green -Date: Sat May 24 23:28:42 2014 -0400 - - Update current version. - -commit 18d56cca5a4ee95ad48b129100adf26231518ed0 -Author: Anthony Green -Date: Mon May 19 18:05:33 2014 -0400 - - Increment libtool version number - -commit 629f1029c47e522e4331988f02f32c203a070e28 -Merge: 0403f33 c1166d4 -Author: Anthony Green -Date: Mon May 19 18:04:28 2014 -0400 - - Merge pull request #120 from l0kod/tmpfile - - Create temporary file with O_TMPFILE and O_CLOEXEC when available - -commit c1166d4f653bf6d17ad8c265cf5e8da84e2e76dc -Author: Mickaël Salaün -Date: Mon May 12 19:44:08 2014 +0200 - - closures: Check for mkostemp(3) - -commit 8daeed9570af72eb135c8ded460d2888f05b2e68 -Author: Mickaël Salaün -Date: Sun May 11 22:54:58 2014 +0200 - - closures: Create temporary file with O_TMPFILE and O_CLOEXEC when available - - The open_temp_exec_file_dir function can create a temporary file without - file system accessible link. If the O_TMPFILE flag is not defined (old - Linux kernel or libc) the behavior is unchanged. - - The open_temp_exec_file_name function now need a new argument "flags" - (like O_CLOEXEC) used for temporary file creation. - - The O_TMPFILE flag allow temporary file creation without race condition. - This feature/fix prevent another process to access the (future) - executable file from the file system. - - The O_CLOEXEC flag automatically close the temporary file for any - execve. This avoid transmitting (executable) file descriptor to a child - process. - -commit 0403f332b1f478696c30d3d8a0e2f6eef24aaf88 -Author: Anthony Green -Date: Mon May 19 09:41:32 2014 -0400 - - Update date. Annoucing 3.1 today. - -commit 94ac0c168ee7b115409121d88b25a4979446c8da -Author: Anthony Green -Date: Mon May 19 09:37:21 2014 -0400 - - Increment libtool library revision number - -commit 57465744b6e1295d7202de5a7734df589518f1c8 -Author: Anthony Green -Date: Sun May 11 10:30:22 2014 -0400 - - Update to version 3.1 - -commit 0c2251a42df5108b6d9ebe5fe1cf83d0bcdf660e -Author: Anthony Green -Date: Sun May 11 10:22:30 2014 -0400 - - Support versions of git older than 1.8.5 - -commit 70c303cb88e23aaee91c87c56b108c50ab4f3c2f -Author: Anthony Green -Date: Sun May 11 09:56:40 2014 -0400 - - Fix testsuite for GCC 4.9.0 - -commit 52b3457093ed19b2a7c5fcf243c4014c90ce6225 -Author: Magnus Granberg -Date: Sun May 11 09:55:28 2014 -0400 - - Check /proc/self/status for PaX status. - -commit 7ba4c5d72aa440a4b21fb57e999e67c5957761da -Author: Dominik Vogt -Date: Sun May 11 09:52:47 2014 -0400 - - Use to get correct dir - -commit 31e0d4ecff6dc2a6c75a066ee099b52a43f6ba27 -Merge: 1c0e9a7 99909eb -Author: Anthony Green -Date: Wed Apr 23 19:24:47 2014 -0400 - - Merge pull request #119 from joshtriplett/fastcall-fastball - - src/x86/win32.S: Define ffi_closure_FASTCALL in the MASM section, too - -commit 99909eb6184b62408d88b6b4e7ab38e84e6d0bf3 -Author: Josh Triplett -Date: Tue Apr 22 21:17:52 2014 -0700 - - src/x86/win32.S: Define ffi_closure_FASTCALL in the MASM section, too - -commit 1c0e9a7297ced15413c2d2d5d35f6c650c4b46c9 -Merge: 93a24f2 d369522 -Author: Anthony Green -Date: Mon Apr 21 12:41:56 2014 -0400 - - Merge pull request #101 from joshtriplett/fastcall-closures - - Support closures for fastcall - -commit d36952273d4fafbda91ecc205fc0824f7cc65e70 -Author: Josh Triplett -Date: Sun Apr 20 12:03:25 2014 -0700 - - Support fastcall closures - - libffi on 32-bit x86 now supports closures for all supported ABIs. - Thus, rewrite the last remaining duplicated-by-ABI test (closure_stdcall - and closure_thiscall) to use the generic ABI_NUM/ABI_ATTR mechanism. - -commit 93a24f216bcdd1018b976d697179c6d49004015a -Merge: dd11a04 2349fec -Author: Anthony Green -Date: Sat Apr 12 19:38:07 2014 -0400 - - Merge pull request #80 from ueno/devel - - Fix typo in doc - -commit dd11a04061cb49ce1d702545693c24eb1267d648 -Merge: 8fa2812 03ca880 -Author: Anthony Green -Date: Sat Apr 12 19:37:21 2014 -0400 - - Merge pull request #86 from joshtriplett/testsuite-CC-CXX - - testsuite ignores CC parameter supplied to configure or make - -commit 8fa2812355e685a42abf9a62fbc674d616b2edee -Merge: 8a58e6b 419503f -Author: Anthony Green -Date: Sat Apr 12 19:32:08 2014 -0400 - - Merge pull request #116 from frida/fix/darwin-aarch64-variadic - - Fix handling of variadic calls on Darwin/AArch64 - -commit 8a58e6b7805b736def197b8baf8e465a2a3f6913 -Merge: 30b77c5 a539f7f -Author: Anthony Green -Date: Sat Apr 12 19:30:18 2014 -0400 - - Merge pull request #115 from frida/fix/darwin-aarch64-alignment - - Fix alignment of AArch64 assembler functions - -commit 30b77c56f95c63ecd83399aafdbad7b07330f2fd -Merge: dc33cb3 3e2b84d -Author: Anthony Green -Date: Sat Apr 12 19:29:13 2014 -0400 - - Merge pull request #117 from frida/fix/windows-regression - - Fix Windows regression - -commit 3e2b84d295531720917bf46afc532fc6d877e3ec -Author: Ole André Vadla Ravnås -Date: Sat Apr 12 01:04:04 2014 +0200 - - Fix Windows regression - - Introduced by b5fed601948237037513a9b7f967c8fc6c9ff1f6. - -commit 419503f409c321fe31ff59d963ef34bb913420d0 -Author: Ole André Vadla Ravnås -Date: Sun Apr 6 20:54:13 2014 +0200 - - Fix handling of variadic calls on Darwin/AArch64 - -commit a539f7ffd6783aa11353d13265520e453c565fb4 -Author: Ole André Vadla Ravnås -Date: Sun Apr 6 20:53:02 2014 +0200 - - Fix alignment of AArch64 assembler functions - -commit dc33cb3c998da521a960385c1269c3aef552f69f -Merge: c860a99 b5fed60 -Author: Anthony Green -Date: Sat Apr 5 23:41:22 2014 -0400 - - Merge pull request #114 from joshtriplett/bounce-on-a-tiny-trampoline - - Fix ABI on 32-bit non-Windows x86: go back to trampoline size 10 - -commit b5fed601948237037513a9b7f967c8fc6c9ff1f6 -Author: Josh Triplett -Date: Sat Apr 5 17:33:42 2014 -0700 - - Fix ABI on 32-bit non-Windows x86: go back to trampoline size 10 - - The trampoline size is part of the ABI, so it cannot change. Move the - logic from the stdcall and thiscall trampolines to the functions they - call, to reduce them both to 10 bytes. - - This drops the previously added support for raw THISCALL closures on - non-Windows. (Non-raw THISCALL closures still work.) - -commit 03ca880081b22efab09ba72268270f83017d3d7b -Author: Josh Triplett -Date: Thu Mar 27 08:44:34 2014 -0700 - - README: Note the testsuite changes to respect $CC and $CXX - -commit d74df8c5d8c6722ecb908da98c86cc8e2c755b84 -Author: Josh Triplett -Date: Thu Mar 27 00:44:12 2014 -0700 - - README: Update Windows example to set both CC and CXX - -commit 7d698125b1f05173f3656a89755a2eb58813b002 -Author: Josh Triplett -Date: Wed Mar 26 23:17:56 2014 -0700 - - Use the proper C++ compiler to run C++ tests - - Running the C compiler with -shared-libgcc -lstdc++ does not work on - non-GCC compilers. - -commit fa5e88f170cb37c7b2b9bb015c8c5b854ffd8a3e -Author: Josh Triplett -Date: Wed Mar 26 23:53:57 2014 -0700 - - .travis.yml: Make the build command more readable by splitting at && - - "script" can contain multiple commands to run in sequence. - -commit 0c3824702d3d59d37f8c177d646303f546187683 -Author: Josh Triplett -Date: Wed Mar 26 14:51:32 2014 -0700 - - Always set CC_FOR_TARGET for dejagnu, to make the testsuite respect $CC - - This fixes cross-compilation and compilation with CC="gcc -m32". - -commit 9946a92af31b30cb7760150d1f8ca6c11b01aeea -Author: Josh Triplett -Date: Wed Mar 26 20:18:58 2014 -0700 - - Stop looking for expect and runtest above top_builddir - - Users wishing to test hand-compiled versions of expect and runtest can - easily enough put them in their path or set EXPECT and RUNTEST - themselves. - -commit acb202325215058639234efb7af1f04c1c8a1f44 -Author: Josh Triplett -Date: Wed Mar 26 20:18:41 2014 -0700 - - Stop setting an empty AM_RUNTESTFLAGS - -commit c860a992fef5d7cd7bb0975b1632d17a9fafe007 -Author: Anthony Green -Date: Tue Mar 25 17:02:51 2014 -0400 - - Upgrade version to 3.1-rc1 - -commit 9837073e6203048a162a226798c5d252600219ed -Author: Anthony Green -Date: Tue Mar 25 16:24:14 2014 -0400 - - Update copyright date and clean up README notes. - -commit 18d3baa9f597b026675baa1b4e5a5eeef7577a08 -Merge: afee537 f0c8a31 -Author: Anthony Green -Date: Tue Mar 25 16:12:53 2014 -0400 - - Merge pull request #108 from joshtriplett/freebsd - - [3.1 blocker] Fix FreeBSD support - -commit afee53738a995e23bd2f89fd0f7b30b380566106 -Merge: 7d24785 b2d610e -Author: Anthony Green -Date: Tue Mar 25 16:12:35 2014 -0400 - - Merge pull request #106 from joshtriplett/darwin-award - - [3.1 blocker] Update OS X build system to include win32.S on 32-bit - -commit 7d2478568ed9f03cbf57627f449a2d2cf4d1571c -Merge: beab5f3 56be47f -Author: Anthony Green -Date: Tue Mar 25 16:12:17 2014 -0400 - - Merge pull request #110 from joshtriplett/w64 - - Fix 64-bit Windows support - -commit beab5f334d9ec5b8b91d1cc727d1029b40358e7e -Merge: 28fb197 ef5890e -Author: Anthony Green -Date: Tue Mar 25 16:07:47 2014 -0400 - - Merge pull request #105 from joshtriplett/win32-relocations - - [3.1 blocker] win32.S needs to handle relocations/GOT - -commit f0c8a31577172104049283f0a80c723084a5bd77 -Author: Josh Triplett -Date: Mon Mar 24 22:14:26 2014 -0700 - - Compile win32.S on FreeBSD - -commit b2d610e028b5ce48d1ad7e5d0debc9c321d891b2 -Author: Josh Triplett -Date: Fri Mar 21 11:10:13 2014 -0700 - - Compile win32.S on 32-bit Darwin as well - -commit be50b87a490e794362cb4a27ada2fbaab202adb8 -Author: Josh Triplett -Date: Mon Mar 24 21:44:13 2014 -0700 - - Always use configure to detect whether global symbols need underscores - - 64-bit Windows already used this check; make it universal, and use it in - place of an ifdef on X86_WIN32, to handle non-Windows platforms that use - the underscore, such as Darwin. - -commit 56be47f87629e31afbcb0774aa65735f539ee972 -Author: Josh Triplett -Date: Mon Mar 24 21:24:53 2014 -0700 - - Fix a warning on 64-bit Windows - - When sizeof(size_t) != sizeof(unsigned), adding a size_t to cif->bytes - produces a "possible loss of data" warning. However, the size_t in - question refers to the size of a single parameter. Use a cast to avoid - the warning. - -commit 48a8eda74aad8a21b6f26df5df08fe64c043d208 -Author: Josh Triplett -Date: Mon Mar 24 21:21:12 2014 -0700 - - Avoid referencing undefined ABIs on 64-bit Windows builds - - 64-bit Windows does not have FFI_STDCALL, FFI_THISCALL, or FFI_FASTCALL. - -commit f0f4138f90345d7d67dfa6783a7e1c7cc30d3c6f -Author: Josh Triplett -Date: Sat Mar 22 10:00:53 2014 -0700 - - win32.S: Add handling for position-independent code on Darwin - - Newer versions of Darwin generate the necessary stub functions - automatically and just need a call instruction, but accomodating older - versions as well requires adding the stub. - -commit ef5890ebafb7cd2fbf9acf161edb55fe1382871c -Author: Josh Triplett -Date: Fri Mar 21 11:01:39 2014 -0700 - - win32.S: Use shifting for multiplication rather than repeated addition - - The jump table code added a register to itself twice to multiply by 4; - shift the register left by 2 instead. - -commit 4fca48901e7e4f53bf490ed22607b2d2d8f4bfcc -Author: Josh Triplett -Date: Fri Mar 21 11:00:41 2014 -0700 - - win32.S: Make the jump tables position-independent - - Now that non-Windows platforms include win32.S, it needs to support - building as position-independent code. This fixes build failures on - target platforms that do not allow text relocations. - -commit 2087dcf736274286f76c69d3988fb6d7cc4fd0f5 -Author: Josh Triplett -Date: Fri Mar 21 10:57:06 2014 -0700 - - win32.S: Make calls to ffi_closure_SYSV_inner position-independent - - Now that non-Windows platforms include win32.S, it needs to support - building as position-independent code. This fixes one source of build - failures on target platforms that do not allow text relocations. - -commit 28fb197079cf1d11da4eef7c8c243ab05590c528 -Merge: c697472 c3dd0a1 -Author: Anthony Green -Date: Tue Mar 18 12:19:36 2014 -0400 - - Merge pull request #107 from rvandermeulen/msvcc - - Various compatibility fixes and improvements to msvcc.sh. - -commit c3dd0a1a0245fc174361a70876e88ae24285f861 -Author: Ryan VanderMeulen -Date: Tue Mar 18 12:09:45 2014 -0400 - - Various compatibility fixes and improvements to msvcc.sh. - - * Don't try to mix incompatible optimization flags in debug builds. - * Workaround ax_cc_maxopt.m4 not supporting MSVC and change -O3 to -O2. - * Fix MSVC warning by properly passing linker flags to compiler. - * Make msvcc.sh return 1 if invalid command line options are used rather than silently eating them. - * Add more comments. - -commit c697472fccfbb5b87b007c053cda9ef014b346b9 -Merge: 83fd2bc e48918e -Author: Anthony Green -Date: Mon Mar 17 00:32:42 2014 -0400 - - Merge pull request #102 from joshtriplett/test-generic - - Add ABIs to the test matrix; unify many bits of the testsuite - -commit e48918ecf876bc85d040fc50a232059c566553a8 -Author: Josh Triplett -Date: Sun Mar 16 20:29:27 2014 -0700 - - testsuite: Add ABIs to the test matrix; unify tests across ABIs - - This eliminates all the *_win32.c tests in favor of the tests they were - branched from, and expands test coverage to run many more tests on - stdcall, thiscall, and fastcall. - - This same mechanism also supports testing any other target that has - multiple ABIs. - -commit 4d4d368e5a55d9443c4c53b1b70d58ab6d8c941c -Author: Josh Triplett -Date: Sun Mar 16 17:02:05 2014 -0700 - - testsuite: Replace ffitestcxx.h with ffitest.h - - ffitest.h contains a superset of the functionality of ffitestcxx.h; - make the C++ tests include ffitest.h instead, and remove ffitestcxx.h. - -commit 3f97cf3413c46caf2a79f32ac9cda4620972c2d7 -Author: Josh Triplett -Date: Sun Mar 16 16:53:42 2014 -0700 - - testsuite: Unify the C and C++ testsuites - - These two testsuites differ only in the source file glob and a couple of - additional compiler options; unify the remaining bits. - -commit 0d9cce8edb937bbe771a6cdd25f671edf06d2128 -Author: Josh Triplett -Date: Sun Mar 16 16:22:58 2014 -0700 - - testsuite: ffitest.h: Parenthesize the CHECK macro - -commit 5695ec1444c5323e48fe4314f8c8f027625e67df -Author: Josh Triplett -Date: Sun Mar 16 16:04:58 2014 -0700 - - testsuite: Factor out a function to run a matrix of tests - - This commons up code from libffi.call/call.exp and - libffi.special/special.exp, unifies the optimization option matrix - between the two, and makes it easier to add more axes to the matrix - in the future. - -commit dfdb02cc869855d3b68571e5f7aa77ae8c9d254a -Author: Josh Triplett -Date: Sun Mar 16 15:26:26 2014 -0700 - - testsuite: Introduce a __THISCALL__ compiler-specific macro - -commit 83fd2bce0456224483435d4b764063f4513fd464 -Merge: 3658a07 06ff924 -Author: Anthony Green -Date: Sun Mar 16 22:03:29 2014 -0400 - - Merge pull request #99 from joshtriplett/gitignore - - .gitignore: Ignore more generated files - -commit 3658a0700a50d37a2fdba04fd9d79ad2f706d9f5 -Merge: d948d0a 46c5d3c -Author: Anthony Green -Date: Sun Mar 16 21:37:42 2014 -0400 - - Merge pull request #100 from rvandermeulen/bug-756740 - - Change double quotes in Makefile.am to single quotes. - -commit 46c5d3c30fdc2b43c076ad955078d7c5f1e75b37 -Author: Ryan VanderMeulen -Date: Sun Mar 16 21:16:08 2014 -0400 - - Change double quotes in Makefile.am to single quotes. - - This was originally done in PR #84, except the change was made to Makefile.in instead of Makefile.am and was therefore reverted the next time the files were regenerated. - -commit 06ff924215a2f9739efa2c059dc595bc4ec1c851 -Author: Josh Triplett -Date: Sun Mar 16 16:19:46 2014 -0700 - - .gitignore: Ignore more generated files - - The build process generates doc/libffi.info and fficonfig.h.in, so add - them to .gitignore. - -commit bad8948346e9b8813023a0cc78a3b6eb8d9c14c6 -Author: Josh Triplett -Date: Sun Mar 16 15:16:18 2014 -0700 - - testsuite: Introduce a __STDCALL__ compiler-specific macro - - Several tests want to use stdcall, which differs in syntax by compiler, - so introduce a macro for it in ffitest.h. - -commit 98a793fa36a4ab3ba24d059cb80a2891cdb940e1 -Author: Josh Triplett -Date: Sun Mar 16 15:20:36 2014 -0700 - - testsuite: Common up the ifdef blocks for compiler-specific macros - -commit d948d0a729c934b0224749338a3ba0a2c8f51c45 -Merge: b61b472 a86bd31 -Author: Anthony Green -Date: Sun Mar 16 10:53:48 2014 -0400 - - Merge pull request #98 from joshtriplett/unconfigure.host - - Merge configure.host into configure.ac - -commit a86bd318e2424d879d784ee7b29d6536d7a17c18 -Author: Josh Triplett -Date: Sun Mar 16 06:58:59 2014 -0700 - - Merge configure.host into configure.ac - - configure.host only has a single entry, and shows no signs of needing - more added. - -commit b61b472bd0647006d6685238721002017f1d119c -Author: Anthony Green -Date: Sun Mar 16 09:45:55 2014 -0400 - - Update version to 3.1-rc0. Clean up README. - -commit 7a64e7dbba54e6e9f69954adfb943be1856ff928 -Merge: 11a5c5c eef2e02 -Author: Anthony Green -Date: Sun Mar 16 09:39:08 2014 -0400 - - Merge pull request #97 from joshtriplett/remove-more-generated-files - - Remove more generated files - -commit 11a5c5c39f5861011f6c5ddf795da3a32b5f0082 -Merge: 9a62a21 1c68c07 -Author: Anthony Green -Date: Sun Mar 16 09:38:47 2014 -0400 - - Merge pull request #96 from joshtriplett/sawing-changelogs - - Generate ChangeLog from git in make dist; remove it from version control - -commit eef2e02a13d7d1c8145d47a64467f654406a3548 -Author: Josh Triplett -Date: Sun Mar 16 06:26:03 2014 -0700 - - doc: Remove autogenerated info file and stamp - -commit 9fb403d3c5d9643e0f561cab6d4a07b1e54907ff -Author: Josh Triplett -Date: Sun Mar 16 06:25:52 2014 -0700 - - fficonfig.h.in: Remove, configure generates it - -commit 1c68c07217fda78a779778c1480fedef7a58d5b4 -Author: Josh Triplett -Date: Sun Mar 16 06:11:58 2014 -0700 - - Generate ChangeLog from git in make dist - - Archive the existing ChangeLog to ChangeLog.libffi-3.1 - -commit c65ed55e655711e008282edbdd82ce95d008b4f6 -Author: Josh Triplett -Date: Sun Mar 16 05:52:00 2014 -0700 - - ChangeLog.v1: Fix typo in explanatory header. - -commit 9a62a21f5c3a8e1da463229f3170c8ab3031d920 -Author: Anthony Green -Date: Sun Mar 16 09:03:57 2014 -0400 - - Add missing ChangeLog entry. Clean up some entries. - -commit 9bc704c58cb7a049d867837e3a11e2e31886ec66 -Merge: 694447a e892e58 -Author: Anthony Green -Date: Sun Mar 16 08:41:00 2014 -0400 - - Merge pull request #95 from joshtriplett/news - - README: Update news for 3.0.14 - -commit e892e581d1838a06c18c7ecd50ebd79915cff92b -Author: Josh Triplett -Date: Sun Mar 16 05:38:24 2014 -0700 - - README: Update news for 3.0.14 - -commit 694447aa29deadd571efb4e9a26ee3f68ede1493 -Merge: fdc87f3 45a6c21 -Author: Anthony Green -Date: Sun Mar 16 08:32:05 2014 -0400 - - Merge pull request #93 from joshtriplett/travis-dist - - Make Travis check "make dist" - -commit 45a6c21efa944b520842e631dc54919b04884744 -Author: Josh Triplett -Date: Sun Mar 16 05:29:08 2014 -0700 - - .travis.yml: Test "make dist" too. - -commit fdc87f3b2ea37b58a4a9ae6c35083f544909fe3c -Merge: 7412b83 e1911f7 -Author: Anthony Green -Date: Sun Mar 16 08:05:51 2014 -0400 - - Merge pull request #85 from joshtriplett/stdcall - - stdcall support on Linux - -commit e1911f78df113ca58738b66089a070d4cf747de7 -Author: Josh Triplett -Date: Sun Mar 16 03:25:53 2014 -0700 - - Add support for stdcall, thiscall, and fastcall on non-Windows x86-32 - - Linux supports the stdcall calling convention, either via functions - explicitly declared with the stdcall attribute, or via code compiled - with -mrtd which effectively makes stdcall the default. - - This introduces FFI_STDCALL, FFI_THISCALL, and FFI_FASTCALL on - non-Windows x86-32 platforms, as non-default calling conventions. - -commit 7412b838d543aae4fa925862bd5702d3dacbc29a -Merge: c0cc5fd 9531d05 -Author: Anthony Green -Date: Sun Mar 16 07:58:16 2014 -0400 - - Merge pull request #90 from joshtriplett/win32-unifdef - - prep_cif.c: Remove unnecessary ifdef for X86_WIN32 - -commit c0cc5fdaa237b67e86f22d2f6e13f3b42d9aae33 -Merge: 98b5296 b3a5da0 -Author: Anthony Green -Date: Sun Mar 16 07:57:59 2014 -0400 - - Merge pull request #89 from joshtriplett/travis32 - - .travis.yml: Test on both 32-bit and 64-bit - -commit 9531d05f64c2a674e0197158ffad68d69f177bd0 -Author: Josh Triplett -Date: Sun Mar 16 01:50:02 2014 -0700 - - prep_cif.c: Remove unnecessary ifdef for X86_WIN32 - - ffi_prep_cif_core had a special case for X86_WIN32, checking for - FFI_THISCALL in addition to the FFI_FIRST_ABI-to-FFI_LAST_ABI range - before returning FFI_BAD_ABI. However, on X86_WIN32, FFI_THISCALL - already falls in that range, making the special case unnecessary. - Remove it. - -commit b3a5da068abd2f2983d9e67adbf41b0e0f34e37f -Author: Josh Triplett -Date: Sat Mar 15 23:27:56 2014 -0700 - - .travis.yml: Test on both 32-bit and 64-bit - -commit 98b52960485a261399f081915f36063de3854a5f -Merge: 134ce4c f6dd184 -Author: Anthony Green -Date: Sun Mar 16 07:51:33 2014 -0400 - - Merge pull request #94 from joshtriplett/esp-extra-stackery-perception - - ChangeLog: Document testsuite changes to remove fragile stack pointer checks - -commit f6dd1845434dd53e22129becdfa092c082df307c -Author: Josh Triplett -Date: Sun Mar 16 04:49:36 2014 -0700 - - ChangeLog: Document testsuite changes to remove fragile stack pointer checks - -commit 134ce4c0266bf994f07518fc534de53f1d3c8de8 -Merge: 2680e9e 9c27932 -Author: Anthony Green -Date: Sun Mar 16 07:47:17 2014 -0400 - - Merge pull request #91 from joshtriplett/esp-extra-stackery-perception - - testsuite: Remove fragile stack pointer checks - -commit 9c279328ee12fc869adff63ca81f1230977bd42b -Author: Josh Triplett -Date: Sun Mar 16 02:31:19 2014 -0700 - - testsuite: Remove fragile stack pointer checks - - testsuite/libffi.call/closure_stdcall.c and - testsuite/libffi.call/closure_thiscall.c include inline assembly to save - the stack pointer before and after the call, and compare the values. - However, compilers can and do leave the stack in different states for - these two pieces of inline assembly, such as by saving a temporary value - on the stack across the call; observed with gcc -Os, and verified as - spurious through careful inspection of disassembly. - -commit 2680e9ea9b4c87ea8042a61e551bd667493d4bd3 -Merge: 071eab3 82f8cb2 -Author: Anthony Green -Date: Sun Mar 16 07:44:08 2014 -0400 - - Merge pull request #88 from joshtriplett/such-precision-many-fail-wow - - testsuite/libffi.call/many.c: Avoid spurious failure due to excess precision - -commit 82f8cb24a1d976db35ae31a4b86cec8926da327d -Author: Josh Triplett -Date: Sun Mar 16 04:27:32 2014 -0700 - - ChangeLog: Document many.c and many_win32.c changes to avoid spurious failures - -commit 88d562a8b5912e99306063fe3bc289bab6ca6ebe -Author: Josh Triplett -Date: Sat Mar 15 22:08:19 2014 -0700 - - testsuite/libffi.call/many_win32.c: Avoid spurious failure due to excess precision - - The test case testsuite/libffi.call/many_win32.c can spuriously fail due - to excess floating-point precision. Instrumenting it with some printf - calls shows differences well above FLT_EPSILON. (Note when - instrumenting it that multiple computations of the difference, such as - one in a print and another in the conditional, may produce different - results.) - - Rather than complicating the test suite with architecture-specific flags - to avoid excess precision, just simplify the floating-point computation - to avoid a dependency on potential excess precision. - -commit c00a49ecd165b2d06c1c9b249d212dc843fa116f -Author: Josh Triplett -Date: Sat Mar 15 22:08:19 2014 -0700 - - testsuite/libffi.call/many.c: Avoid spurious failure due to excess precision - - The test case testsuite/libffi.call/many.c can spuriously fail due to - excess floating-point precision. Instrumenting it with some printf - calls shows differences well above FLT_EPSILON. (Note when - instrumenting it that multiple computations of the difference, such as - one in a print and another in the conditional, may produce different - results.) - - Rather than complicating the test suite with architecture-specific flags - to avoid excess precision, just simplify the floating-point computation - to avoid a dependency on potential excess precision. - -commit 071eab32a7f9fbbef46c0d8f37d9985bc9cceb37 -Merge: 2228c7a 2f44952 -Author: Anthony Green -Date: Sun Mar 16 07:36:52 2014 -0400 - - Merge pull request #92 from joshtriplett/autogen - - Re-add libtool-ldflags - -commit 2f44952c95765c1486fad66f57235f8d459a9748 -Author: Josh Triplett -Date: Sun Mar 16 04:35:12 2014 -0700 - - Re-add libtool-ldflags - -commit 2228c7ab190f3c529b9018495467b841fa21cba2 -Merge: 76d19d0 35634db -Author: Anthony Green -Date: Sun Mar 16 07:25:18 2014 -0400 - - Merge pull request #87 from joshtriplett/autogen - - Remove autogenerated files from the repository - -commit 35634dbceaac0a1544f7385addc01d21ef1ef6a8 -Author: Josh Triplett -Date: Sat Mar 15 18:11:16 2014 -0700 - - Remove autogenerated files from the repository - - Add an autogen.sh to regenerate them. - -commit 76d19d004e36e99d261ee78261e2f52cea5e4ab1 -Merge: c86d9b6 a1a6f71 -Author: Anthony Green -Date: Fri Mar 14 16:54:31 2014 -0400 - - Ensure the linker supports @unwind sections in libffi. - -commit c86d9b6cc6e16ee262844a33b40441374400758c -Merge: 4efb7db f8cdf11 -Author: Anthony Green -Date: Fri Mar 14 16:51:20 2014 -0400 - - Fix merge - -commit 4efb7dbfd9427c478a948cd0d464210123db8de8 -Merge: 634a475 18eb81d -Author: Anthony Green -Date: Fri Mar 14 16:47:57 2014 -0400 - - Merge pull request #81 from rvandermeulen/bug-756740 - - Allow building for mipsel with Android NDK r8. - -commit a1a6f71bfe4199293043b2e4cfb4c8d3cb1112f9 -Author: Ryan VanderMeulen -Date: Mon Mar 10 15:12:47 2014 -0400 - - Remove stray hunk that shouldn't have been included in this patch. - -commit f8cdf11467181f2a9a6b7e748167569aa58e3a81 -Author: Ryan VanderMeulen -Date: Mon Mar 10 15:04:58 2014 -0400 - - Replace double quotes with single quotes in Makefile.in to improve compatibility between some versions of MSYS and gmake. From Mozilla bug 943728. - https://bugzilla.mozilla.org/show_bug.cgi?id=943728 - -commit dfa3738732e1bc3a7f4130395ae4bab55fcebb99 -Author: Ryan VanderMeulen -Date: Mon Mar 10 14:53:48 2014 -0400 - - Ensure the linker supports @unwind sections in libffi. From Mozilla bug 756740. - https://bugzilla.mozilla.org/show_bug.cgi?id=778414 - - Also tracked as issue #42. - https://github.com/atgreen/libffi/issues/42 - -commit 18eb81d032f29d645d0498ba92bddfd651f009ae -Author: Ryan VanderMeulen -Date: Mon Mar 10 14:43:37 2014 -0400 - - Allow building for mipsel with Android NDK r8. From Mozilla bug 756740. - https://bugzilla.mozilla.org/show_bug.cgi?id=756740 - -commit 2349fec9a818fb52fd2f294bcbc7b3156cd113de -Author: Daiki Ueno -Date: Wed Mar 5 17:53:02 2014 +0900 - - Fix typo in doc - -commit 634a475eaf1bee31c09f7d519e31c13b64cd24df -Author: Anthony Green -Date: Sat Mar 1 18:37:29 2014 -0500 - - Update Makefile for new darwin scripts - -commit c7b67e874bb89859f9a07d1cf9606052b6c0dcc1 -Author: Anthony Green -Date: Sat Mar 1 18:34:18 2014 -0500 - - Add README note - -commit a04e30ba3dc303133d459c1ac273ceefe4d49b32 -Author: Anthony Green -Date: Fri Feb 28 17:20:59 2014 -0500 - - Add missing -DFFI_DEBUG flag - -commit 934dc1b5c8d6a9e727bedc72342831eb7d62c35f -Merge: 11d7aa9 67fbef3 -Author: Anthony Green -Date: Fri Feb 28 01:10:17 2014 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 11d7aa9d7a4bbe642944edc0f07cf96db9b270b6 -Merge: b40aeda 3b44d41 -Author: Anthony Green -Date: Fri Feb 28 01:06:48 2014 -0500 - - Merge pull request #46 from makotokato/android-clang - - Fix build failure when using clang for Android - -commit 67fbef3b56ff0ef88f9b1a7fe48cb77222fa6cec -Merge: b40aeda 3b44d41 -Author: Anthony Green -Date: Fri Feb 28 01:06:48 2014 -0500 - - Merge pull request #46 from makotokato/android-clang - - Fix build failure when using clang for Android - -commit b40aeda31a74d95a37c723b6243aabac466e67c4 -Merge: 20698ab 53ceaf1 -Author: Anthony Green -Date: Fri Feb 28 01:01:29 2014 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 53ceaf14c5eeb16ba09745f0ca87cca367d41a90 -Merge: 860fe66 cc9b518 -Author: Anthony Green -Date: Fri Feb 28 01:01:02 2014 -0500 - - Merge pull request #40 from wojdyr/master - - Correct the -L flag in libffi.pc.in - -commit 20698abc6a00092fd7fd3e434a3a29dc0f048f1e -Merge: 64bd069 1a0b01e -Author: Anthony Green -Date: Fri Feb 28 00:56:27 2014 -0500 - - Merge pull request #66 from ppizarro/master - - BlackFin fixes - Fatal error when calling a function defined in a shared library from within the function called by FFI - -commit 860fe6646f5ae603e99a8d1d722ddddba8b75769 -Merge: 64bd069 1a0b01e -Author: Anthony Green -Date: Fri Feb 28 00:56:27 2014 -0500 - - Merge pull request #66 from ppizarro/master - - BlackFin fixes - Fatal error when calling a function defined in a shared library from within the function called by FFI - -commit 64bd06990a7accf72271516a2110b86cdccd8df4 -Author: Anthony Green -Date: Fri Feb 28 00:52:56 2014 -0500 - - Add ChangeLog entry for Josh's change - -commit edf29c5169b06fcfc241445e152e325bc3c50e0e -Merge: 33c9954 3998d26 -Author: Anthony Green -Date: Fri Feb 28 00:50:25 2014 -0500 - - Merge pull request #75 from joshtriplett/longdouble - - Fix build error on x86 without distinct long double - -commit 33c9954f2eec539011a0f93270aaf013318837ae -Author: Anthony Green -Date: Fri Feb 28 00:38:41 2014 -0500 - - Rebuilt with new libtool - -commit 926b6989fbd08488b9105943293353d45ac527e0 -Merge: 5a88c85 cc82051 -Author: Anthony Green -Date: Fri Feb 28 00:26:57 2014 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - - Conflicts: - ChangeLog - -commit 5a88c85fde304052bed1581ed0b6452ac2c68838 -Author: Anthony Green -Date: Fri Feb 28 00:23:04 2014 -0500 - - Fix spelling errors - -commit cc82051c7e80cea772c4b72da026eb7e68d598fc -Author: Anthony Green -Date: Fri Feb 28 00:23:04 2014 -0500 - - Fix spelling errors - -commit 001aaf4b1b56349596bb6f6b5c1613dcbbd84ea8 -Author: Anthony Green -Date: Fri Feb 28 00:20:17 2014 -0500 - - When no VFP arguments are present the IP register is used - uninitialized. Initialize it to the value of FP. - - This fixes a number of testsuite failures when configured for - armv7l-unknown-linux-gnueabihf - -commit 49f7729c3ce697c12408c42ccb29cdf4eb66bb85 -Author: Anthony Green -Date: Fri Feb 28 00:17:16 2014 -0500 - - aarch64 fix - -commit 447483d51c6aa9df7116f346a73fc1cf795f4c2b -Merge: 51377bd b4df9cf -Author: Anthony Green -Date: Thu Feb 27 15:42:41 2014 -0500 - - Fix ChangeLog merge - -commit 3998d2604b5c0d45a098ff3119a9fd9710ef429d -Author: Josh Triplett -Date: Mon Feb 17 11:20:33 2014 -0800 - - Fix build error on x86 without distinct long double - - src/x86/ffi64.c: In function 'classify_argument': - src/x86/ffi64.c:205:5: error: duplicate case value - case FFI_TYPE_LONGDOUBLE: - ^ - src/x86/ffi64.c:202:5: error: previously used here - case FFI_TYPE_DOUBLE: - ^ - -commit 51377bda9aed0b2c1309c818460cab9d9ab3d46e -Merge: f08da54 40927bd -Author: Anthony Green -Date: Sat Feb 15 08:06:29 2014 -0500 - - Merge pull request #72 from heiher/devel - - MIPS N32: Fix call floating point va function - -commit f08da5465463e60a28f5e921f23ebf2ba984c148 -Merge: 3dc3f32 fa5f25c -Author: Anthony Green -Date: Sat Feb 15 08:06:11 2014 -0500 - - Merge pull request #68 from zeldin/master - - Linux/ppc64: Remove assumption on contents of r11 in closure - -commit 40927bd3e1e7c6007025ba10854fd8a0664e47df -Author: Heiher -Date: Tue Jan 21 23:18:27 2014 +0800 - - Fix call floating point va function - - I'm not sure floating-point arguments in GPR or FPR before calling - variable number arguments function. so, load all arguments to GPR and - FPR. - -commit b4df9cf9cc4a9a9401a53fd6bea1f3c2c283b97b -Author: Zachary Waldowski -Date: Wed Feb 5 14:22:52 2014 -0500 - - AArch64: Fix void fall-through case when assertions are enabled - -commit f466aad0d91a117e42571d1d6fb434fa0433c930 -Author: Zachary Waldowski -Date: Tue Jan 21 16:38:31 2014 -0500 - - AArch64: Fix missing semicolons when assertions are enabled - -commit 7ea677733bd98917241852b8901a6b7580728895 -Author: Anthony Green -Date: Sat Nov 30 20:58:31 2013 -0500 - - Remove build-ios from Makefile - - Conflicts: - ChangeLog - -commit 6ae046cc59c12b2cd40158d6bcb96f4a59886159 -Author: Anthony Green -Date: Sat Nov 30 21:06:51 2013 -0500 - - Mention Aarch64 on iOS - -commit bfc06b3fdb32abe90ce0749aedfec649df85a7ef -Author: Zachary Waldowski -Date: Mon Dec 30 17:36:39 2013 -0500 - - Update ChangeLog - -commit 0a0f12ce1f7be81006b08a3c81a636926d283a9b -Author: Zachary Waldowski -Date: Thu Jan 9 13:50:17 2014 -0500 - - AArch64: Remove duplicitous element_count call. - - This inhibits an analyzer warning by Clang. - -commit 4330fdcd92e67c816288d64ab230237065768206 -Author: Zachary Waldowski -Date: Thu Jan 9 13:53:30 2014 -0500 - - Darwin/aarch64: Respect iOS ABI re: stack argument alignment - -commit 0a333d6c3973935d4fe02aae76b10e39d3c88e07 -Author: Zachary Waldowski -Date: Thu Jan 9 14:03:29 2014 -0500 - - Darwin/aarch64: Fix size_t assumptions - -commit 2c18e3c76aad1b426617db05a4384e7c3a920176 -Author: Zachary Waldowski -Date: Mon Dec 30 16:14:02 2013 -0500 - - Darwin/aarch64: Fix "shadows declaration" warnings - -commit 1b8a8e20e344f3c55495ab6eb46bd14e843d4b3e -Author: Zachary Waldowski -Date: Thu Jan 9 13:55:21 2014 -0500 - - Darwin/aarch64: Use Clang cache invalidation builtin - -commit 6030cdcae776f8fb5876a53168f7d1e75d28a242 -Author: Zachary Waldowski -Date: Mon Dec 30 15:45:51 2013 -0500 - - Darwin/aarch64: Account for long double being equal to double - -commit 5658b0892683d2e24e4d5842978c184a7ad33858 -Author: Zachary Waldowski -Date: Mon Dec 30 16:33:47 2013 -0500 - - Darwin/aarch64: Use CNAME, restrict .size like ARM - -commit 07175780802acec5dc49fdedd6d20a62409a6707 -Author: Zachary Waldowski -Date: Mon Dec 30 17:48:22 2013 -0500 - - Darwin/aarch64: Fix invalid reference in assembly - -commit 9da28b44277fea3aeb827c35dd63d609d2524a8b -Author: Zachary Waldowski -Date: Mon Dec 30 16:23:21 2013 -0500 - - Darwin/x86_64: Fix 64-bit type shortening warnings - -commit 821d398f08bd1d540a5b235507812ffeee49b580 -Author: Zachary Waldowski -Date: Thu Jan 9 13:15:06 2014 -0500 - - Darwin: Merge build scripts, redo project, incl. arm64 - -commit 6eff9ff9e72463b9783be2514f944b6f05692054 -Author: Zachary Waldowski -Date: Mon Dec 30 17:48:10 2013 -0500 - - Darwin/iOS: Improve unified syntax use for LLVM - -commit ba0ea99c82aadd5957386a031e3122011bd36d52 -Author: Zachary Waldowski -Date: Mon Dec 30 15:27:44 2013 -0500 - - Fix dlmalloc warnings due to set_segment_flags, sizeof(size_t) - -commit 994be3a5c1d0d17b19103396103e128517fd62f9 -Author: Zachary Waldowski -Date: Mon Dec 30 15:27:14 2013 -0500 - - Darwin/iOS: Fix mis-typing of vfp_reg_free - -commit a8e0a835ab1f62d03ad6391760e3e8b7732d24f8 -Author: Zachary Waldowski -Date: Mon Dec 30 15:26:20 2013 -0500 - - Darwin/ARM: Assert on NULL dereference - - This inhibits an analyzer warning by Clang on all platforms. - -commit 13675341581c489ed9df8ba390c8e08a732decb2 -Author: Zachary Waldowski -Date: Thu Jan 9 13:42:08 2014 -0500 - - Darwin/i386: Inhibit Clang previous prototype warnings - -commit 66469c381e2e2cc96e7d409266dea0ffe177eeca -Author: Zachary Waldowski -Date: Thu Jan 9 13:41:45 2014 -0500 - - Darwin/ARM: Inhibit Clang previous prototype warnings - -commit 5bfe62a00d2d659eec9f19b39802b6e69844fc27 -Author: Zachary Waldowski -Date: Thu Jan 9 13:41:27 2014 -0500 - - Darwin/AArch64: Inhibit Clang previous prototype warnings - -commit fa5f25c20f76a6ef5e950a7ccbce826672c8a620 -Author: Marcus Comstedt -Date: Sat Jan 4 19:00:08 2014 +0100 - - Linux/ppc64: Remove assumption on contents of r11 in closure - -commit 1a0b01e171e9c750437cef2f18917f5a6e32c498 -Author: Paulo Pizarro -Date: Thu Jan 2 16:17:59 2014 -0200 - - When the function called by the ffi called a function defined in a shared library generate a fatal error - The correction was to take into consideration the GOT. - -commit 3dc3f32c35db5ab995a835225f6815369735ceb7 -Author: Anthony Green -Date: Thu Dec 5 16:23:25 2013 -0500 - - Undo iOS ARM64 changes. - -commit 356b2cbc304bfe5bdc28b8d1c68d1ff084e9ec37 -Merge: 484a758 07345a3 -Author: Anthony Green -Date: Sat Nov 30 22:38:13 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 484a7584260e2fbb399ce90083046834271bf9ff -Author: Anthony Green -Date: Sat Nov 30 21:06:51 2013 -0500 - - Mention Aarch64 on iOS - -commit 07345a30ec0a2fa45a7c363d301f57723690cfa0 -Author: Anthony Green -Date: Sat Nov 30 21:06:51 2013 -0500 - - Mention Aarch64 on iOS - -commit d4b931c1b872378c35f12ddbb9a6d55e7f17c65e -Author: Anthony Green -Date: Sat Nov 30 20:58:31 2013 -0500 - - Remove build-ios from Makefile - -commit dfbf236d70fc1ec68e6ff193584a154353508e2f -Merge: 852ac3b bb9740e -Author: Anthony Green -Date: Sat Nov 30 20:54:54 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - Add ChangeLog entry. - -commit bb9740e545205f93a525c77aa6d1cbf4ca9371f3 -Merge: ac75368 4d701e0 -Author: Anthony Green -Date: Sat Nov 30 17:54:39 2013 -0800 - - Merge pull request #60 from zwaldowski/ios-redo - - Mac/iOS support, including aarch64 port - -commit 4d701e03faa475a5eb3b54b90046114a1e27b813 -Author: Zachary Waldowski -Date: Sat Nov 30 13:25:27 2013 -0500 - - Darwin: Properly export headers from Xcode project - -commit 022f12eb9ad2264e838fa5fb453733f5177888f4 -Author: Zachary Waldowski -Date: Sat Nov 30 12:21:38 2013 -0500 - - Darwin: Freshen gen scripts, remove old build-ios.sh - -commit e820fe2025d7ad3df7584407946dfaad2af69599 -Author: Zachary Waldowski -Date: Sat Nov 30 12:03:51 2013 -0500 - - Darwin/iOS: Include x86_64+aarch64 pieces in library - -commit 0278284e470ec91db7cdc15ac3dcd64683305848 -Author: Zachary Waldowski -Date: Sat Nov 30 03:03:37 2013 -0500 - - Darwin/aarch64: size_t assumptions - -commit 9775446b6441c91cd9059215c106aa3bcf949767 -Author: Zachary Waldowski -Date: Sat Nov 30 02:39:34 2013 -0500 - - Darwin/aarch64: Fix “shadows declaration†warnings - -commit 4260badc37705d3618e774dfe61184ac709881c1 -Author: Zachary Waldowski -Date: Sat Nov 30 02:08:14 2013 -0500 - - Darwin/aarch64: Use Clang cache invalidation builtin - -commit 9fa7998d5f9250908cbf12a671479852ebadf9d1 -Author: Zachary Waldowski -Date: Sat Nov 30 02:07:48 2013 -0500 - - Darwin/aarch64: Inhibit Xcode warning - -commit 0e832048a93830575b0976406444e134e649a4f7 -Author: Zachary Waldowski -Date: Sat Nov 30 02:07:34 2013 -0500 - - Darwin/aarch64: double == long double - -commit 602dc22d76931092610234cf063f9f1b8dbc1a51 -Author: Zachary Waldowski -Date: Sat Nov 30 02:06:00 2013 -0500 - - Darwin/iOS prep script: try and compile for arm64 - -commit b513dfe79de4725e8a717325a9e3b5b9f69f63dc -Author: Zachary Waldowski -Date: Sat Nov 30 02:05:22 2013 -0500 - - Darwin/aarch64: Restrict .size to ELF like arm32. - -commit bc978099bf2812de755c076b67ef9c2547607572 -Author: Zachary Waldowski -Date: Sat Nov 30 02:04:57 2013 -0500 - - Darwin/aarch64: Potentially(?) fix compile error - -commit d6bb9314467c6e0683156559d23ca341c43fa3c8 -Author: Zachary Waldowski -Date: Sat Nov 30 02:04:22 2013 -0500 - - Darwin/aarch64: Use CNAME refs - -commit 33c46ce5680eea28d3437c8771ec1d137e226b45 -Author: Zachary Waldowski -Date: Sat Nov 30 04:13:42 2013 -0500 - - Darwin/Mac: Fix 64/32 shortening warnings - -commit 0612081e6c161d9d820742f995975d35da2adbc2 -Author: Zachary Waldowski -Date: Sat Nov 30 03:03:00 2013 -0500 - - Darwin: Misc size_t warnings - -commit 6a6247d179ec3859311c2d8775841b884f309f66 -Author: Zachary Waldowski -Date: Sat Nov 30 02:55:48 2013 -0500 - - Darwin: Fix dlmalloc warnings due to sizeof(size_t) - -commit 4d60d9e1e32de6166ffd63bbe9ce54cf961c78fc -Author: Zachary Waldowski -Date: Sat Nov 30 04:09:30 2013 -0500 - - Darwin: Rebuild Xcode project - -commit cb719a5c1c2eb391d6a5f5e02484ba4aa990a51b -Author: Zachary Waldowski -Date: Sat Nov 30 04:09:18 2013 -0500 - - Darwin/iOS: Fix LLVM 3.3 warning re: memcpy. - -commit 21bde92c9abb378f9c456a9d95e6f9b99ef8c920 -Author: Zachary Waldowski -Date: Sat Nov 30 03:43:42 2013 -0500 - - Darwin: Clean up, modernize generator scripts - -commit fd54eab74cef7891e4acaaafb71e783142ecb69e -Author: Zachary Waldowski -Date: Sat Nov 30 03:38:02 2013 -0500 - - Darwin/Mac: Also exclude OS X generated source - -commit 953b6f14c655141f9e7d82550a312c3eeb961091 -Author: Zachary Waldowski -Date: Tue Apr 24 11:16:20 2012 -0400 - - Darwin/iOS: More unified syntax support w/ Clang. - - Signed-off-by: Zachary Waldowski - -commit c713a55379481c339877f2e0003d97cb8d9ed80e -Author: Zachary Waldowski -Date: Tue Apr 24 10:25:29 2012 -0400 - - Darwin/iOS: Simplify RETLDM arguments for LLVM 3.1 - - Signed-off-by: Zachary Waldowski - -commit 16ba1b80028db5cb71cf86e5f79f5e48317f83c8 -Author: Zachary Waldowski -Date: Wed Apr 11 23:26:04 2012 -0400 - - Darwin: Silence Clang warnings. - -commit 852ac3bd302d6ed97b1ef65f4cbed69c258a48df -Merge: ab79d6e ac75368 -Author: Anthony Green -Date: Thu Nov 21 21:25:44 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - - Conflicts: - ChangeLog - -commit ab79d6e21992dd86139ba07530ff888833b78a04 -Author: Alan Modra -Date: Thu Nov 21 06:12:35 2013 -0500 - - This separates the 32-bit sysv/linux/bsd code from the 64-bit linux - code, and makes it possible to link code compiled with different - options to those used to compile libffi. For example, a - -mlong-double-128 libffi can be used with -mlong-double-64 code. - - Using the return value area as a place to pass parameters wasn't such - a good idea, causing a failure of cls_ulonglong.c. I didn't see this - when running the mainline gcc libffi testsuite because that version of - the test is inferior to the upstreamm libffi test. - - Using NUM_FPR_ARG_REGISTERS rather than NUM_FPR_ARG_REGISTERS64 meant - that a parameter save area could be allocated before it was strictly - necessary. Wrong but harmless. Found when splitting apart ffi.c - into 32-bit and 64-bit support. - -commit ac7536889334d4be50709006d7e23536364d7891 -Author: Alan Modra -Date: Thu Nov 21 06:12:35 2013 -0500 - - This separates the 32-bit sysv/linux/bsd code from the 64-bit linux - code, and makes it possible to link code compiled with different - options to those used to compile libffi. For example, a - -mlong-double-128 libffi can be used with -mlong-double-64 code. - - Using the return value area as a place to pass parameters wasn't such - a good idea, causing a failure of cls_ulonglong.c. I didn't see this - when running the mainline gcc libffi testsuite because that version of - the test is inferior to the upstreamm libffi test. - - Using NUM_FPR_ARG_REGISTERS rather than NUM_FPR_ARG_REGISTERS64 meant - that a parameter save area could be allocated before it was strictly - necessary. Wrong but harmless. Found when splitting apart ffi.c - into 32-bit and 64-bit support. - -commit 69df91cfb4fa6bcb644350a80bff970f27478a6a -Merge: 2f45082 aa1f62c -Author: Anthony Green -Date: Mon Nov 18 06:34:04 2013 -0800 - - Merge pull request #59 from iains/powerpc-darwin-unwind-fix - - Fix PowerPC Darwin FDE encodings to use pcrel correctly. Modernise the picbase labels. - -commit aa1f62c0a093c30325dff1d4d2b6b4b22eb96929 -Author: Iain Sandoe -Date: Mon Nov 18 13:11:56 2013 +0000 - - Fix PowerPC Darwin FDE encodings to use pcrel correctly. Modernise the picbase labels. - -commit 2f450822a8698ba88441c56d152c7dc8924b127f -Author: Anthony Green -Date: Mon Nov 18 06:52:29 2013 -0500 - - Clean up code to appease modern GCC compiler. - -commit 16d56c51aded374730920a4acde76ff3d2860ae1 -Author: Alan Modra -Date: Mon Nov 18 06:36:03 2013 -0500 - - An #endif in the wrong place would cause compile failure on powerpcle. - Using bl instead of b doesn't cause runtime failures as you might think, - but does mess the processor branch prediction. - -commit 34f878a5ef28663f6b1d7fd26fb099429ea1579e -Merge: 83f65b6 1fd0457 -Author: Anthony Green -Date: Sat Nov 16 06:57:54 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - - Conflicts: - ChangeLog - src/powerpc/ffi.c - -commit 83f65b63d9764a9cc7688fc5cda5ee2bd23faf54 -Author: Alan Modra -Date: Sat Nov 16 06:53:50 2013 -0500 - - Finally, this adds _CALL_ELF == 2 support. ELFv1 objects can't be - linked with ELFv2 objects, so this is one case where preprocessor - tests in ffi.c are fine. Also, there is no need to define a new - FFI_ELFv2 or somesuch value in enum ffi_abi. FFI_LINUX64 will happily - serve both ABIs. - -commit 1fd045784cac874b5d76b7fa931f67209a8280d3 -Author: Alan Modra -Date: Sat Nov 16 06:53:50 2013 -0500 - - Finally, this adds _CALL_ELF == 2 support. ELFv1 objects can't be - linked with ELFv2 objects, so this is one case where preprocessor - tests in ffi.c are fine. Also, there is no need to define a new - FFI_ELFv2 or somesuch value in enum ffi_abi. FFI_LINUX64 will happily - serve both ABIs. - -commit 362851379a49ce07d3e36e82c4e5c7b6cc16a352 -Author: Alan Modra -Date: Sat Nov 16 06:52:43 2013 -0500 - - Andreas' 2013-02-08 change reverted some breakage for struct return - values from 2011-11-12, but in so doing reintroduced string - instructions to sysv.S that are not supported on all powerpc variants. - This patch properly copies the bounce buffer to destination in C code - rather than in asm. - - I have tested this on powerpc64-linux, powerpc-linux and - powerpc-freebsd. Well, the last on powerpc-linux by lying to - configure with - - CC="gcc -m32 -msvr4-struct-return -mlong-double-64" \ - CXX="g++ -m32 -msvr4-struct-return -mlong-double-64" \ - /src/libffi-current/configure --build=powerpc-freebsd - - and then - - make && make CC="gcc -m32" CXX="g++ -m32" \ - RUNTESTFLAGS=--target_board=unix/-m32/-msvr4-struct-return/-mlong-double-64\ - check - -commit 1c06515d927d9de1582438d4eb5953890e79c5c7 -Author: Alan Modra -Date: Sat Nov 16 06:41:36 2013 -0500 - - The powerpc64 ABIs align structs passed by value, a fact ignored by - gcc for quite some time. Since gcc now does the correct alignment, - libffi needs to follow suit. This ought to be made selectable via - a new abi value, and the #ifdefs removed from ffi.c along with many - other #ifdefs present there and in assembly. I'll do that with a - followup patch sometime. - - This is a revised version of - https://sourceware.org/ml/libffi-discuss/2013/msg00162.html - -commit a97cf1fae575d8bfd5259c5c422025ad43911326 -Author: Alan Modra -Date: Sat Nov 16 06:40:13 2013 -0500 - - This patch prepares for ELFv2, where sizes of these areas change. It - also makes some minor changes to improve code efficiency. - -commit 164283f4ac5972ce2ab5e015cc2ab1014c23276c -Author: Alan Modra -Date: Sat Nov 16 06:38:55 2013 -0500 - - The powerpc64 support opted to pass floating point values both in the - fpr area and the parameter save area, necessary when the backend - doesn't know if a function argument corresponds to the ellipsis - arguments of a variadic function. This patch adds powerpc support for - variadic functions, and changes the code to only pass fp in the ABI - mandated area. ELFv2 needs this change since the parameter save area - may not exist there. - - This also fixes two faulty tests that used a non-variadic function - cast to call a variadic function, and spuriously reasoned that this is - somehow necessary for static functions.. - -commit 31257b3189f81a199bc2902c22bc5f2d7c54ccde -Author: Andrew Haley -Date: Sat Nov 16 06:35:51 2013 -0500 - - Fix sample closure code - -commit db0ace3a38496af73eae3df02ef353736d16909f -Author: Andrew Haley -Date: Sat Nov 16 06:29:25 2013 -0500 - - Fix broken test cases - -commit de10f5039ed7a53382ddcc95c368d03e535edb98 -Merge: 58c2577 f3657da -Author: Anthony Green -Date: Thu Nov 14 10:56:29 2013 -0500 - - Merge branch 'master' of https://github.com/bivab/libffi - - Conflicts: - ChangeLog - -commit f3657da278dd63afcdd8762894a9bdaea8ef028a -Author: David Schneider -Date: Thu Nov 14 13:02:16 2013 +0100 - - update Changelog - -commit 58c2577a3ff80e7416ef0434769e2af23365719c -Author: Alan Modra -Date: Wed Nov 13 16:55:36 2013 -0500 - - This enshrines the current testsuite practice of using ffi_arg for - returned values. It would be reasonable and logical to use the actual - return argument type as passed to ffi_prep_cif, but this would mean - changing a large number of tests that use ffi_arg and all backends - that write results to an ffi_arg. - -commit 8af42f9944f7ed72c81ae360aac6a84dc11f89dc -Author: Anthony Green -Date: Wed Nov 13 16:40:28 2013 -0500 - - Respect HAVE_ALLOCA_H - -commit cdf405d574f479b782454516366bd4f4b9b3415e -Author: David Schneider -Date: Wed Nov 13 15:50:21 2013 +0100 - - add a testcase for the double/float issue on ARMHF - -commit 77f823e31ffb557a466b24f7fba845fbf7831798 -Author: David Schneider -Date: Wed Nov 13 14:26:57 2013 +0100 - - stop trying to assing vfp regs once we are done with the registers - -commit 37067ec5036f2a6ed7a4799f83f8f53160460344 -Author: David Schneider -Date: Tue Nov 12 19:49:01 2013 +0100 - - mark all vfp registers as used when done. - - To avoid assigning registers the would fit, once arguments have been on - the stack, we mark all registers as used once we do not find a free - register for the first time. - -commit 2f5b7ce545473a7f6e41193edc29407cbebe82d5 -Author: Anthony Green -Date: Sat Nov 9 06:16:32 2013 -0500 - - UltraSPARC IIi fix. Update README and build configury. - -commit becd754434173032f426d22ffcbfe24f55b3c137 -Author: Mark Kettenis -Date: Wed Nov 6 06:43:49 2013 -0500 - - Align the stack pointer to 16-bytes. - -commit 05c31093409f7b3e6d795fac21d2c954313d8162 -Author: Konstantin Belousov -Date: Wed Nov 6 06:40:58 2013 -0500 - - Mark executable as not requiring executable stack. - -commit cf6bf9818e8394cfcdb07a40c6a5e2ee6b01d333 -Author: Anthony Green -Date: Sat Nov 2 17:23:59 2013 -0400 - - Fix up docs - -commit 02177176854d16fc0f1a5958aa34da2f306630ee -Merge: c242217 c265b4c -Author: Anthony Green -Date: Sat Nov 2 17:11:22 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit c2422174b3edc0de0b148dfd6b67087bb881c4a6 -Merge: f4b843f d918d47 -Author: Anthony Green -Date: Sat Nov 2 14:08:23 2013 -0700 - - Merge pull request #45 from foss-for-synopsys-dwc-arc-processors/arc_support - - arc: Fix build error - -commit c265b4cacb9130f042699a85de9c7242b3f49cc3 -Merge: f4b843f d918d47 -Author: Anthony Green -Date: Sat Nov 2 14:08:23 2013 -0700 - - Merge pull request #45 from foss-for-synopsys-dwc-arc-processors/arc_support - - arc: Fix build error - -commit f4b843f83710ac378c48abd87fe66bb519d30d2e -Author: Anthony Green -Date: Sat Nov 2 17:01:15 2013 -0400 - - Don't align stack for win32 - -commit f3cd39345713db8e414cf642b6cb65a4cfe6018c -Merge: 666f3e7 6aa1590 -Author: Anthony Green -Date: Sat Nov 2 13:17:57 2013 -0700 - - Merge pull request #51 from vbudovski/for_upstream - - Don't use 16 byte aligned stack for WIN32 - -commit 666f3e71b56d92c49fcd2d7f349b8f8ebca0f8a3 -Author: Anthony Green -Date: Sat Oct 26 09:12:42 2013 -0400 - - Add more credits to README. Tidy up. - -commit 73ada14e756bad97fad0e6915a821a3c7e079f81 -Author: Anthony Green -Date: Sat Oct 26 09:09:45 2013 -0400 - - Update README - -commit d3372c54ce7117e80d389ba875dc5b6b2213c71e -Author: Mark H Weaver -Date: Sat Oct 26 08:30:06 2013 -0400 - - Fix N32 ABI issue for MIPS. - -commit d6716aba8118eb0513885cfe557bedebb7016e8b -Author: Anthony Green -Date: Tue Oct 15 15:42:49 2013 -0400 - - Update travis-ci build dependencies to include texinfo - -commit 16b93a211bcfbe4bd0efdcf94de225a71aa0ee02 -Author: Sandra Loosemore -Date: Tue Oct 15 15:33:59 2013 -0400 - - Add nios2 port. - -commit 2f5626ce02fce8267ab48ceb6d7d0ed7d672a75e -Author: Sandra Loosemore -Date: Tue Oct 15 15:32:16 2013 -0400 - - Fix testsuite bug - -commit f64e4a865557e440774436b4c2b2fd7374290e97 -Author: Marcus Shawcroft -Date: Tue Oct 15 15:20:14 2013 -0400 - - Fix many.c testcase for Aarch64 - -commit 128cd1d2f358f26d9fa75a27cf2b30356f5dd903 -Author: Anthony Green -Date: Tue Oct 8 06:45:51 2013 -0400 - - Fix spelling errors - -commit ff06269d707cafbfef2a88afb07a79c9d1480c5f -Author: Anthony Green -Date: Tue Oct 8 06:32:18 2013 -0400 - - Update README for M88K and VAX - -commit d2fcbcdfbea750d1f6a9f493e2e6c4d5ffa71b34 -Author: Anthony Green -Date: Tue Oct 8 06:27:46 2013 -0400 - - Add m88k and VAX support. Update some configury bits. - -commit 6aa15900accc0a648cdebf11ec11d11697ebfffd -Author: Vitaly Budovski -Date: Thu Sep 5 12:05:06 2013 +1000 - - Don't use 16 byte aligned stack for WIN32 - - This fixes a crash when accessing __stdcall functions in Python ctypes. - -commit 3b44d41156149af8da2a58825fefdfa23274ae7a -Author: Makoto Kato -Date: Wed Jul 10 15:34:53 2013 +0900 - - Fix build failure when using clang for Android - - clang for Android generates __gnu_linux__ define, but gcc for Android doesn't. So we should add check it for Android - -commit d918d47809c174d62283306b282749f8db93661f -Author: Mischa Jonker -Date: Mon Jul 8 15:51:36 2013 +0200 - - arc: Fix build error - - One part of the patch for ARC support was missing in the upstreamed - version. - - Signed-off-by: Mischa Jonker - -commit d3d099b40c122550279789200263346f120f6909 -Author: Anthony Green -Date: Tue Jul 2 16:11:38 2013 -0400 - - little-endian ppc64 support - -commit 0f8690a84c874ec09a090c8c6adfb93c594acac6 -Author: Anthony Green -Date: Tue Jul 2 15:54:40 2013 -0400 - - Rebuild for ARC additions - -commit f88118b345f27c46f5445d6e4832c498ff9a6d85 -Author: Anthony Green -Date: Tue Jul 2 15:51:27 2013 -0400 - - Revert "Merge pull request #36 from abergmeier/emscripten_fix" - - This reverts commit 6a4d901dde7b3f87984c563505717cde3113d16e, reversing - changes made to b50a13b9c07ec09af4b9697e482acdad571e6961. - -commit 6a4d901dde7b3f87984c563505717cde3113d16e -Merge: b50a13b 587002c -Author: Anthony Green -Date: Tue Jul 2 12:12:34 2013 -0700 - - Merge pull request #36 from abergmeier/emscripten_fix - - Fixes for building with Emscripten - -commit b50a13b9c07ec09af4b9697e482acdad571e6961 -Merge: 767f1f9 b082e15 -Author: Anthony Green -Date: Tue Jul 2 12:10:26 2013 -0700 - - Merge pull request #44 from foss-for-synopsys-dwc-arc-processors/arc_support - - Add ARC support - -commit 767f1f96e5282da44d7340e6815e9820a3f78e39 -Merge: c3c40e0 b8a91d8 -Author: Anthony Green -Date: Tue Jul 2 12:08:04 2013 -0700 - - Merge pull request #43 from JensTimmerman/__m128 - - added include for xmmintrin.h - -commit b8a91d81be77d479327fdb6bdd9fdae6d18e6e63 -Author: Jens Timmerman -Date: Tue Jul 2 10:57:37 2013 +0200 - - added include for xmmintrin.h - -commit b082e15091961373c03d10ed0251f619ebb6ed76 -Author: Mischa Jonker -Date: Mon Jun 10 16:19:33 2013 +0200 - - Add ARC support - - This adds support for the ARC architecture to libffi. DesignWare ARC - is a family of processors from Synopsys, Inc. - - This patch has been tested on a little-endian system and passes - the testsuite. - - Signed-off-by: Mischa Jonker - -commit cc9b518687e46b0d1acafdd4bc3f3b281c25a3d9 -Author: Marcin Wojdyr -Date: Tue May 14 15:01:23 2013 +0200 - - Update libffi.pc.in - - use -L${toolexeclibdir} instead of -L${libdir} - to be consistent with Makefile.am - -commit 587002c092cffe6e7a8d7028f246c241d03b738c -Author: Andreas Bergmeier -Date: Fri Apr 19 17:12:24 2013 +0200 - - Enable disabling of libtool on platforms where it does not work (e.g. LLVM). - Build libraries normally then. - -commit c3c40e0290377d7cf948b072eedd8317c4bf215e -Merge: ede96e4 4750e3c -Author: Anthony Green -Date: Sat Mar 30 05:24:14 2013 -0700 - - Merge pull request #34 from davidsch/armhf - - Fix ARM hard-float support for large numbers of VFP arguments - -commit 4750e3c662fd9569cb3e2d28f539685fd1ca8caf -Author: David Schneider -Date: Thu Mar 28 16:56:36 2013 +0100 - - update changelog - -commit 9708e7cf09f1bf815f4d6485eb1f180fabb35804 -Author: David Schneider -Date: Wed Mar 27 19:31:04 2013 +0100 - - folow the ARM hard-float ABI in ffi_prep_incoming_args_VFP - -commit b41120981e5e49ca2da10b94b154775f50da5f36 -Author: David Schneider -Date: Wed Mar 27 16:38:35 2013 +0100 - - create separated versions of ffi_prep_incoming_args_* for SYSV and VFP ABIs. - - The different versions will be called depending on the value of cif->abi - -commit dd26f1f39c54861c5b91931f0f37a72942c2a072 -Author: David Schneider -Date: Thu Mar 28 15:39:01 2013 +0100 - - add a failing test for closures on ARM hardfloat - -commit 3c1608613ab3c2184222b98c5482cddedd6b559b -Author: David Schneider -Date: Tue Mar 26 19:24:47 2013 +0100 - - extend ffi_prepare_args for FFI_VFP (hard-float ABI), fixing an issue with passing VFP arguments in VFP registers and the stack, while at the same time not using all core registers. - -commit 0f2ff2d4c92719be8936179f9ab674f4d1a3fd14 -Author: David Schneider -Date: Tue Mar 26 19:22:02 2013 +0100 - - separate ARM ffi_prepare_args in a version implementing the simple SYSV calling convention and one for the hard-float calling convention - -commit 3a352b8a8252400a83de22c7c424bf1887b4a2ef -Author: David Schneider -Date: Tue Mar 26 14:24:04 2013 +0100 - - move the hardfloat specific argument copying code to the helper function - -commit 5df6b7944a4225b6eb329f3886be64e04e966f29 -Author: David Schneider -Date: Tue Mar 26 14:02:21 2013 +0100 - - extract setting of arguments to be passed to a helper function - -commit 7d1048c471bb4b1f9d67a9e9f8e95f9a1d2e6d45 -Author: David Schneider -Date: Tue Mar 26 11:33:33 2013 +0100 - - extract code to align the argument storage pointer to a helper function - -commit b9f013788f0f384c423ad963475aaacb55598135 -Author: David Schneider -Date: Mon Mar 25 13:27:36 2013 +0100 - - add a testcase, that on ARM hardfloat needs more than the 8 VFP argument registers to pass arguments to a call - -commit 2fbdb0f231cafdb77b025d3cd8afe90cda99b3ba -Author: David Schneider -Date: Mon Mar 25 13:26:02 2013 +0100 - - use the absolute value to check the test result against an epsilon - -commit ede96e4eb660bbf3e0fe048135efa8106f48af5d -Merge: f22ab3c 9e34992 -Author: Anthony Green -Date: Sun Mar 17 18:38:21 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit f22ab3c6877cbdd07f058b68816b0086b1cb0e1e -Merge: 12b1886 d08124b -Author: Anthony Green -Date: Sun Mar 17 18:34:54 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 9e34992a5ea2fda1dba5875bf96dc91a7230f51f -Merge: 12b1886 d08124b -Author: Anthony Green -Date: Sun Mar 17 18:34:54 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 12b1886d7b1f8aa264b1d348bfa47a0e14712df4 -Author: Anthony Green -Date: Sun Mar 17 18:32:12 2013 -0400 - - cygwin fix & updates for 3.0.13 - -commit d08124bedf2c6d61874fe215404783aeb9f6f1ac -Author: Anthony Green -Date: Sun Mar 17 18:32:12 2013 -0400 - - cygwin fix & updates for 3.0.13 - -commit cb32c812d04d1dfa72002cc04924e7e4fef89e02 -Author: Anthony Green -Date: Sun Mar 17 09:27:55 2013 -0400 - - Fix lib install dir - -commit efd7866a361a6f636bae8400d26c6811e56ca207 -Author: Anthony Green -Date: Sat Mar 16 08:35:57 2013 -0400 - - 2.0.13rc1 - -commit ff647ad4dff2f07dd153f295a1f70b1d906cd6ca -Merge: 4acf005 d9dd417 -Author: Anthony Green -Date: Sat Mar 16 08:20:40 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - - Conflicts: - ChangeLog - -commit 4acf0056f55c757490dae6c29a65b0321327ea8a -Author: Anthony Green -Date: Sat Mar 16 08:18:45 2013 -0400 - - Build fix for soft-float power targets - -commit 675c9839224e4268187f1ec6f512127f9db555d0 -Author: Anthony Green -Date: Sat Mar 16 08:12:38 2013 -0400 - - Documentation fix - -commit 8a286f570ccd41db81f74ea7f248da62241d898a -Author: Anthony Green -Date: Sat Mar 16 08:01:19 2013 -0400 - - Fix for m68000 systems - -commit d9dd417b09566af55b7b3000bb53ccaf2e1d6c92 -Author: Anthony Green -Date: Sat Mar 16 08:01:19 2013 -0400 - - Fix for m68000 systems - -commit 215763d012a944d95406b394d6013b80d220e870 -Author: Anthony Green -Date: Sat Mar 16 07:57:35 2013 -0400 - - Update configury. - -commit 9180d8f39c9b6afe17b78277c2711a5d9948e824 -Merge: 2fb527a 7e1b326 -Author: Anthony Green -Date: Sat Mar 16 07:46:55 2013 -0400 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 2fb527a017a4943e176a489ff103231b86464b59 -Author: Anthony Green -Date: Sat Mar 16 07:46:38 2013 -0400 - - Add Meta processor support - -commit 211a9ebf4d1a9801e15e103566aed2b8c42790be -Merge: f308faf ee18766 -Author: Anthony Green -Date: Sat Mar 16 04:24:40 2013 -0700 - - Merge pull request #32 from alex/patch-1 - - Fix for a crasher due to misaligned stack on x86-32. - -commit 7e1b32649efd24814e86172e196f390566f9e970 -Merge: f308faf ee18766 -Author: Anthony Green -Date: Sat Mar 16 04:24:40 2013 -0700 - - Merge pull request #32 from alex/patch-1 - - Fix for a crasher due to misaligned stack on x86-32. - -commit ee18766b169811426c14b011fbb46d81e344f926 -Author: Alex Gaynor -Date: Thu Mar 14 15:00:33 2013 -0700 - - Fix for a crasher due to misaligned stack on x86-32. - - Full information on reproduction (using Python's ctypes available here: http://bugs.python.org/issue17423) - -commit f308faf1eabaf8dc24966ab17fbf94368f46b9c7 -Author: Anthony Green -Date: Mon Feb 11 14:25:13 2013 -0500 - - Add moxie support. Release 3.0.12. - -commit 4ea22e54e3b143fe05c413f6dddd236af6bcbfb2 -Author: Anthony Green -Date: Sun Feb 10 08:48:38 2013 -0500 - - Update README - -commit 10e77227b6ae85f46f28590bfb09ca3608554358 -Author: Anthony Green -Date: Sun Feb 10 08:47:26 2013 -0500 - - mend - -commit a9521411a53d58f2bf88199242200ceb0d4dae3a -Author: Anthony Green -Date: Sat Feb 9 06:54:40 2013 -0500 - - sparc v8 and testsuite fixes - -commit 70b11b47eea93bf43627588d494d0b3b0d062481 -Author: Anthony Green -Date: Fri Feb 8 16:12:19 2013 -0500 - - Fix small struct passing on ppc - -commit 63ba1fa79f7c4ce42de848debe233aab31aecb51 -Author: Anthony Green -Date: Fri Feb 8 15:18:19 2013 -0500 - - Remove xfail for arm*-*-*. - -commit 24fbca4c1d57d4ea628c0a8ba643684daf54a37e -Author: Anthony Green -Date: Fri Feb 8 14:19:56 2013 -0500 - - Fix typo - -commit b0fa11cb0a94ce6baca058eab9b10e40475e71d6 -Author: Anthony Green -Date: Fri Feb 8 14:17:13 2013 -0500 - - More man page cleanup - -commit 8bd15d139a58a6e46dc90a1cb2d89f59f32f06c7 -Author: Anthony Green -Date: Fri Feb 8 13:56:37 2013 -0500 - - Fix many.c testcase for ppc - -commit 7aab825cf198be85490d3cd80e778d415d85ad9b -Author: Anthony Green -Date: Fri Feb 8 13:26:21 2013 -0500 - - Add missing files to dist - -commit cb03ea8f4eb08024e44abe4392edc77b89fbfbad -Author: Anthony Green -Date: Fri Feb 8 12:25:18 2013 -0500 - - sparc v9 fixes for sun tools - -commit 35ee8d44f31dd3d3b88083c837dc351593e13cc2 -Author: Anthony Green -Date: Fri Feb 8 07:12:41 2013 -0500 - - Fix microblaze big-endian struct issue - -commit 9db7e1a958fc484ba149efe027008b9a170395fb -Author: Anthony Green -Date: Thu Feb 7 21:06:08 2013 -0500 - - Fix botched sparc patch. Update version. - -commit ce0138e61455f268af326e26908b9680ec2c4bea -Author: Anthony Green -Date: Thu Feb 7 18:04:01 2013 -0500 - - Update bug report address. rc2. - -commit fd07c9e40451e0ec1d0475cd54a83d45ccaea2c0 -Author: Anthony Green -Date: Thu Feb 7 18:00:36 2013 -0500 - - Add cache flushing routine for sun compiler on sparc solaris 2.8 - -commit ed6ae9501b2bab45daf93b4935eb0c977635b763 -Author: Anthony Green -Date: Thu Feb 7 16:43:36 2013 -0500 - - Add libtool-ldflags. Define toolexeclibdir for non-GCC builds. - -commit ffef2e046aaec853be356f0b8770a335185ea9cf -Author: Anthony Green -Date: Thu Feb 7 15:47:01 2013 -0500 - - x32 and libtool fixes - -commit 95eecebb2858dc6f1495a61072ff36d0a8127144 -Author: Anthony Green -Date: Thu Feb 7 15:32:46 2013 -0500 - - Remove a.out cruft from dist - -commit 176aa9d2e23d9cd57d6f250692d910b408f9a651 -Author: Anthony Green -Date: Thu Feb 7 15:29:22 2013 -0500 - - Fix GCC usage test and update README - -commit f3a4f3fdde89b04d66983a42a25d09161c5d4d54 -Author: Anthony Green -Date: Thu Feb 7 09:57:20 2013 -0500 - - Fixes for AIX xlc compiler. - -commit 522f8fef49848927482bc63c94afaea5b84e5ec1 -Author: Anthony Green -Date: Wed Feb 6 20:31:31 2013 -0500 - - Fix man page. Clean out junk. - -commit c4dfa259eb4e8e6f4c397868d7fee80aa0bb6a12 -Author: Anthony Green -Date: Wed Feb 6 17:43:24 2013 -0500 - - Bump soversion - -commit f62bd63fe6123cadedb8b2b2c72eb549c40fbce9 -Author: Anthony Green -Date: Wed Feb 6 17:38:32 2013 -0500 - - Release candidate 1 - -commit f7cd61e9e68a4a51147df04d75bfe5b91b9d9286 -Author: Anthony Green -Date: Wed Feb 6 17:38:04 2013 -0500 - - Fix pkgconfig install bits - -commit 6a790129427121f7db2d876e7218a3104e6d2741 -Author: Anthony Green -Date: Wed Feb 6 17:37:15 2013 -0500 - - Work around LLVM ABI problem on x86-64 - -commit 370112938e705128fd5dd4017fc1a1210bd0271a -Merge: bada2e3 bcc0c28 -Author: Anthony Green -Date: Sun Jan 27 05:09:04 2013 -0800 - - Merge pull request #28 from jralls/master - - Reorder x86_64 checks - -commit bcc0c28001b6d427d5cd8037d2e3c892babc6b4c -Author: John Ralls -Date: Sat Jan 26 15:21:14 2013 -0800 - - Reorder x86_64 tests - - So that darwin and cygwin/mingw are tested before the generic check -- - which allows them to actually be set. - -commit bada2e326d9a9acf3ae40cfa4f5d7a9ba97b2ea8 -Author: Anthony Green -Date: Mon Jan 21 08:02:07 2013 -0500 - - Update README - -commit 655bb8f3690feba8e840a5f1854b1d78ed08f692 -Merge: 1035ffb 840f975 -Author: Anthony Green -Date: Mon Jan 21 08:01:24 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit 1035ffb2f468e1a1c401d58cff7e7abb69838e68 -Merge: aeb8719 4086024 -Author: Anthony Green -Date: Mon Jan 21 07:55:53 2013 -0500 - - Update README - -commit 840f975866052fdd91b2c224d56e01ae5900b60d -Merge: aeb8719 4086024 -Author: Anthony Green -Date: Mon Jan 21 07:55:53 2013 -0500 - - Merge branch 'master' of github.com:/atgreen/libffi - -commit aeb8719a34756969970603fca4568530d56708af -Author: Anthony Green -Date: Mon Jan 21 07:37:30 2013 -0500 - - New microblaze support - -commit 40860245a4fd91a1b88adc9171ec993c549e45d5 -Author: Anthony Green -Date: Mon Jan 21 07:37:30 2013 -0500 - - New microblaze support - -commit 20cae32b152b43679ae65a85db9a1c6bb8a143dd -Author: Anthony Green -Date: Mon Jan 21 07:07:38 2013 -0500 - - Xtensa support - -commit 9742f91782faef4a15941508a22c408fb7d1d227 -Author: Anthony Green -Date: Mon Jan 21 07:03:41 2013 -0500 - - Mention IBM XL compiler support on AIX. - -commit f03eab08248f122ce3b623a18df9e19fae1b6e98 -Author: Anthony Green -Date: Fri Jan 11 17:14:11 2013 -0500 - - Remove obsolete inline test functions - -commit 05fbe1faedc7b2580d5f14010d00e9e3cee73951 -Author: Anthony Green -Date: Fri Jan 11 16:54:40 2013 -0500 - - xlc compiler support - -commit 0b4986a7889ed1864674192228f1162c1b5770a8 -Author: Anthony Green -Date: Fri Jan 11 11:19:52 2013 -0500 - - [travis] install dejagnu with sudo - -commit 3c337eef51ab9a4993fc875bfa26289dd6a08881 -Author: Anthony Green -Date: Fri Jan 11 11:18:14 2013 -0500 - - [travis] install dejagnu - -commit 90720962ce1baf9fc35d1bde1738102bcd5bd5ed -Author: Anthony Green -Date: Fri Jan 11 10:57:30 2013 -0500 - - Add first travis config file - -commit bff052d9cd5be41ba9e47c76114054af487d3c30 -Author: Anthony Green -Date: Fri Jan 11 10:24:32 2013 -0500 - - 32-bit x86 fix and more - -commit cd41aeab6176f839167955c016ecc19f65f75df3 -Author: Anthony Green -Date: Thu Jan 10 17:25:45 2013 -0500 - - Add compiler column to table - -commit 8bf987d4df7c4d21435b9211f6cc86abf5904b42 -Author: Anthony Green -Date: Thu Jan 10 17:24:51 2013 -0500 - - Fix for sunpro compiler on Solaris - -commit 3ee74fd6dc8ccd32b608bbff73526838fc34f70b -Author: Anthony Green -Date: Thu Jan 10 17:15:03 2013 -0500 - - Update documentation version. - -commit 13e2d7b92557a9511a0414df82bf2df3edc55cba -Author: Anthony Green -Date: Thu Jan 10 10:52:02 2013 -0500 - - Handle both 32 and 64-bit x86 builds regardless of target triple - -commit 5141543000fc86a3d49a907a2313713ee79e504d -Author: Anthony Green -Date: Thu Jan 10 07:35:53 2013 -0500 - - Don't run EH tests with non-GNU compiler - -commit 56ba8d86f47937a0afb81a2b9e77c9d235d9db45 -Author: Anthony Green -Date: Thu Jan 10 07:25:10 2013 -0500 - - Don't use warning checking macro with sun compiler - -commit 6a028caec1b2c7904feb4c4f9cb7e1125e1d1b60 -Author: Anthony Green -Date: Thu Jan 10 01:19:43 2013 -0500 - - Don't use GCCisms to define types when - + building with the SUNPRO compiler. - -commit 2d9b3939751b3ef9739049509d353ade10b32a8f -Author: Anthony Green -Date: Wed Jan 9 21:14:54 2013 -0500 - - Fix for closures with sunpro compiler - -commit 8308984e479e3274a36e98e8272b5adbb6b774c2 -Author: Anthony Green -Date: Tue Jan 8 15:14:21 2013 -0500 - - Make sure we're running dejagnu tests with the right compiler. - -commit f26c7ca67147450db2fe25ea932944e6cf145d5c -Author: Anthony Green -Date: Tue Jan 8 14:47:05 2013 -0500 - - Make compiler options in dejagnu runs compiler specific - -commit 74c776e21907fc2e59257c021f23077f8b7966cb -Author: Anthony Green -Date: Tue Jan 8 12:25:54 2013 -0500 - - Switch x86 Solaris to X86 from X86_64 - -commit 8962c8c8d06803e310bac0ffc8e84ea15daeff3f -Author: Anthony Green -Date: Tue Jan 8 12:22:24 2013 -0500 - - Fix read-only eh_frame test - -commit 35ddb69c2b49746d940e919ca226ecc1be94f14a -Author: Anthony Green -Date: Tue Jan 8 07:53:37 2013 -0500 - - Only emit DWARF unwind info when building with GCC - -commit f7879bc3f3a8d0bbfcc38771732c160a58ba9cd8 -Author: Anthony Green -Date: Tue Jan 8 07:30:28 2013 -0500 - - Testsuite fix for Solaris vendor compiler - -commit 67cea90fc0897021466fd102671019d30db474cd -Author: Anthony Green -Date: Mon Jan 7 06:30:24 2013 -0500 - - mend - -commit 0de3277b18cf54be3b81d509b9be9b47d9bc1e82 -Author: Thorsten Glaser -Date: Mon Dec 3 00:02:31 2012 +0000 - - Testsuite fixes (was Re: [PATCH] Fix libffi on m68k-linux-gnu, completely) - - Dixi quod… - - >although I believe some 3.0.11 checks to be broken: - - And indeed, with a few minor changes on top of git master, - I still get a full run of PASS plus one XPASS on amd64-linux! - - With the other patches (from this message’s parent) and - these applied, I get a full PASS on m68k-linux as well. - - So, please git am these three diffs ☺ - - bye, - //mirabilos - -- - FWIW, I'm quite impressed with mksh interactively. I thought it was much - *much* more bare bones. But it turns out it beats the living hell out of - ksh93 in that respect. I'd even consider it for my daily use if I hadn't - wasted half my life on my zsh setup. :-) -- Frank Terbeck in #!/bin/mksh - From 5cb15a3bad1f0fb360520dd48bfc938c821cdcca Mon Sep 17 00:00:00 2001 - From: Thorsten Glaser - Date: Sun, 2 Dec 2012 23:20:56 +0000 - Subject: [PATCH 1/2] Fix tests writing to a closure retval via pointer casts - - As explained in - all other tests that do the same cast to an ffi_arg pointer instead. - - PASS on amd64-linux (Xen domU) and m68k-linux (ARAnyM) - - Signed-off-by: Thorsten Glaser - -commit 8f4772f383abd71cfa141c8a70ba11c1aa4ebe2c -Author: Anthony Green -Date: Mon Jan 7 06:14:53 2013 -0500 - - m68k fixes for signed 8 and 16-bit calls. - -commit ea7f8440d58afbebb181e295ff564fdf3d6590a0 -Author: Anthony Green -Date: Fri Jan 4 09:09:32 2013 -0500 - - remove gcc-ism - -commit f06c0f10377ac04eeba5e632dbe5c62c629df4e6 -Author: Anthony Green -Date: Wed Jan 2 09:39:17 2013 -0500 - - Add missing ChangeLog entry and generated files. - -commit 1f8675d4c101d19d67ca0a55ff2ba973349558ad -Merge: 335f419 f6b58d2 -Author: Anthony Green -Date: Wed Jan 2 06:34:38 2013 -0800 - - Merge pull request #26 from rofl0r/master - - fix build error on ppc when long double == double - -commit 335f419a86090cda9f215d149572f9481c3ad034 -Merge: 53236d5 6d6f711 -Author: Anthony Green -Date: Wed Jan 2 06:30:03 2013 -0800 - - Merge pull request #23 from rurban/master - - cygwin/mingw shared libs need libtool LDFLAGS = -no-undefined - -commit 53236d5061034cc0a7f4647fc1bd05ba1aeb3d2a -Author: Anthony Green -Date: Wed Jan 2 09:24:55 2013 -0500 - - Regenerate files - -commit 72222ca3fbe560e13c8dc89ca441b28b7cc74daf -Author: Anthony Green -Date: Wed Jan 2 09:06:38 2013 -0500 - - Update texinfo.tex - -commit 1e326c95431fc9896422fa36659f3e833852579c -Author: Anthony Green -Date: Wed Jan 2 09:05:02 2013 -0500 - - Update config.guess and config.sub - -commit cb6671f5b8a9596ff968c6b6c304f70adf71b368 -Author: Anthony Green -Date: Wed Jan 2 08:56:07 2013 -0500 - - Missing .gitignore changes for xcode support - -commit ebbe77966855395a2a47ed2c09a38f93eb0481cf -Author: Anthony Green -Date: Wed Jan 2 08:54:05 2013 -0500 - - missed x32 libtool patch. - -commit 4394096da0aca0dd422b479a043c18b4f05c5770 -Author: Anthony Green -Date: Wed Jan 2 08:51:35 2013 -0500 - - missed trampoline_table patch. Move to GCC. - -commit ed7a59c3ff7c84bd95c374a5aff21599f705e6dc -Author: Anthony Green -Date: Wed Jan 2 08:48:01 2013 -0500 - - Windows symbol export fix. Move to GCC. - -commit ccee09a4ff843b11c7d8b6819776f57d187305c7 -Author: Anthony Green -Date: Wed Jan 2 08:41:55 2013 -0500 - - +2012-03-21 Peter Rosin - + - + * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] - + (set_ld_library_path_env_vars): Add the library search dir to PATH - + (and save PATH for later). - + (restore_ld_library_path_env_vars): Restore PATH. - -commit 089dbce7cc0889eb26444d89ae062c73c69f26f0 -Author: Anthony Green -Date: Wed Jan 2 08:37:35 2013 -0500 - - med - -commit 980a334c42b4b0eff32e55929ec6727d1326b05d -Author: Anthony Green -Date: Wed Jan 2 07:36:42 2013 -0500 - - Test GCC update - -commit 8bad679ade5000e57cdc9cacde22e8b99840930f -Author: Anthony Green -Date: Wed Jan 2 08:28:35 2013 -0500 - - New stand-alone patch - -commit 981c32ee115e9f0d6546a74592875e138222a9d1 -Author: Anthony Green -Date: Wed Jan 2 07:34:03 2013 -0500 - - Merge with GCC. Eliminate quilt bits. - -commit 61a054929517fb80c437ba71c91f3e20cfff581a -Author: Anthony Green -Date: Wed Nov 28 06:07:41 2012 -0500 - - Refresh config.guess and config.sub - -commit f6b58d2bdc0a24ce94dedce59802f091979df265 -Author: rofl0r -Date: Thu Nov 22 16:26:21 2012 +0100 - - fix build on ppc when long double == double - -commit 69da33a0761aeac73f9e9646269da61c906d6020 -Author: Anthony Green -Date: Mon Nov 12 15:25:47 2012 -0500 - - Pull in config.sub for aarch64 support and more - -commit f680b598b7bdde325ac9349e8c35151c228bf2df -Author: Anthony Green -Date: Tue Nov 6 16:00:40 2012 -0500 - - Add missing aarch64 configury bits - -commit dfadfb19853c57c8623c436d0ef2bdafab24b433 -Author: Anthony Green -Date: Wed Oct 31 06:46:41 2012 -0400 - - Rebase for ppc64 fix - -commit e944b8c7eb1e2eeb9c0f3b9742b4d7f476860ce1 -Author: Anthony Green -Date: Tue Oct 30 14:06:09 2012 -0400 - - Add PaX work-around - -commit 9ccd51be1fdeb99f8b4f42f905166c2abbba8ac0 -Merge: f342996 fa5d747 -Author: Anthony Green -Date: Tue Oct 30 13:37:37 2012 -0400 - - Fix commit conflicts - -commit f342996cb50eb23b868afcff5ac0cdbb6b505d63 -Author: Anthony Green -Date: Tue Oct 30 07:42:27 2012 -0400 - - Darwin12 fix - -commit 58e8b66f70cef2e3c9b0e5a707b45d634cbbf5d9 -Author: Anthony Green -Date: Tue Oct 30 07:07:19 2012 -0400 - - AArch64 port - -commit fa5d747905472571fd472c07d4726017624f66b3 -Author: Anthony Green -Date: Tue Oct 30 07:07:19 2012 -0400 - - AArch64 port - -commit 6993a6686f43f2313b18142c1e96189a27db2aa3 -Author: Anthony Green -Date: Tue Oct 30 06:59:32 2012 -0400 - - Fix autoconf macros - -commit 70084e70ddb13b29dd05c751b1904de206bbe790 -Author: Anthony Green -Date: Fri Oct 12 23:55:06 2012 -0400 - - Update Tile* port info - -commit 9c00a3f6742d61404b31268cc773e7130ff43331 -Author: Anthony Green -Date: Fri Oct 12 16:46:06 2012 -0400 - - TILE-Gx/TILEPro support - -commit 048d2f41c3a6664b4b64bf21e804686662da4160 -Author: Anthony Green -Date: Thu Oct 11 10:55:25 2012 -0400 - - Rebase - -commit 6d6f71108064f5069edd7bf771059d3b82640135 -Author: Reini Urban -Date: Sat Jul 7 12:42:00 2012 -0500 - - cygwin/mingw shared libs need libtool LDFLAGS = -no-undefined - - otherwise only static libs are created. - -commit d330f19292da8f39a78a9e2b0ba08df8094e3bc5 -Author: Nicolas Lelong -Date: Sat May 5 09:37:02 2012 -0400 - - iOS build fixes. - -commit 09b23cfc1d6d15361eee18818851fd3cacb26559 -Author: Anthony Green -Date: Fri Apr 27 08:29:48 2012 -0400 - - Update README with Blackfin/uClinux support - -commit 213ed15c70e72d666154c08e2b41dae3f61f20d3 -Author: Anthony Green -Date: Fri Apr 27 01:34:15 2012 -0400 - - Add blackfin supprt from Alexandre Keunecke. - -commit ff3d76fd427382ce7d2b2ed54acdd0bce470ca4f -Author: Anthony Green -Date: Wed Apr 11 23:16:48 2012 -0400 - - 3.0.11 - -commit 7e0a412c4fd9cbe77b467a9bf86f56aea62632c3 -Author: Anthony Green -Date: Wed Apr 11 22:47:44 2012 -0400 - - Update files to ship - -commit 39e6a5860416f7bad992149817e1da1ba7c460d4 -Author: Zachary Waldowski -Date: Wed Apr 11 22:39:46 2012 -0400 - - More mac/ios build improvements - -commit 853cc722a16f8d1254573ef3bb73c7b8f3d8a110 -Author: Anthony Green -Date: Tue Apr 10 06:33:33 2012 -0400 - - Fix typo for darwin targets - -commit 3f5023068cda07a3dd6dacbaa875a5b5fc96d4bb -Author: Anthony Green -Date: Fri Apr 6 20:34:51 2012 -0400 - - mend - -commit ebb8e8945681ce0af7a5c47a980287e8ece84b84 -Author: Mike Lewis -Date: Fri Apr 6 20:02:08 2012 -0400 - - Build iOS library with xcode - -commit a098b44f4c592c2192fcdef4fad6108eb3f4301c -Author: Anthony Green -Date: Fri Apr 6 17:04:35 2012 -0400 - - Reapply missing testsuite changes for arm - -commit 10d1e51393f08c14045db85843208f44f9f1e9ba -Author: Anthony Green -Date: Fri Apr 6 11:57:14 2012 -0400 - - Update to rc4. Upgrade autoconf version. - -commit 9bcc884276dc0a807b2605e510b11b1740dd9aa2 -Author: Anthony Green -Date: Fri Apr 6 11:53:07 2012 -0400 - - Fix Linux/x32 reference in README - -commit a044a56b1cd2a0924f5ec0d6b5a5089d14fcd1a1 -Author: Anthony Green -Date: Fri Apr 6 10:39:10 2012 -0400 - - Linux/x32 libtool fix - -commit 59bb61a36661b972e8443531d3b7bc736e131a4b -Author: Anthony Green -Date: Fri Apr 6 08:26:14 2012 -0400 - - Update libtool version, README, tests dists - -commit f2981454cbe25cf9411b710f46c5f5552003a123 -Author: Anthony Green -Date: Thu Apr 5 15:45:19 2012 -0400 - - Revert debug code changes - -commit 39dccddb606f6fdb8dcb177d416e884041da6e30 -Author: Zachary Waldowski -Date: Thu Apr 5 12:32:41 2012 -0400 - - Fix building with Clang for Darwin (OS X 10.6+ and iOS - 4.0+) - -commit 3afaa9a34a81a305227ae8cf4f12b9d0484d055e -Author: Peter Rosin -Date: Tue Apr 3 07:40:31 2012 -0400 - - Fix return_uc.c test case on windows. - -commit 65f40c35a2873d8328359ec4512bd0736dbe32c7 -Author: Anthony Green -Date: Tue Apr 3 07:35:59 2012 -0400 - - Repair ppc build regression. - -commit 0a1ab12a8d15caa894116a82249551f23ef65612 -Author: Peter Rosin -Date: Fri Mar 30 08:14:08 2012 -0400 - - Various MSVC-related changes. - -commit e1539266e6c6dde3c99832323586f33f977d1dc0 -Author: Anthony Green -Date: Fri Mar 30 00:40:18 2012 -0400 - - ARM VFP fix for old toolchains - -commit 7c5e60b5f47d725036a72162f136272bc407e3a1 -Author: Anthony Green -Date: Thu Mar 29 08:48:22 2012 -0400 - - Rebase on fixed GCC sources - -commit e72ed5eeaa9cfb0fdc86f6b3422734177b659f96 -Author: Anthony Green -Date: Wed Mar 21 09:52:28 2012 -0400 - - Fix vararg float test - -commit bd78c9c3311244dd5f877c915b0dff91621dd253 -Author: Anthony Green -Date: Wed Mar 21 08:09:30 2012 -0400 - - More cygwin fixes - -commit 84d3253f86dad6b4f261231935675d35fd964b05 -Author: Anthony Green -Date: Mon Mar 19 23:07:35 2012 -0400 - - Rebase post GCC merge - -commit 964c5b93f80dcaacf73056b7d15a4d2b4b7a217c -Author: Anthony Green -Date: Sat Mar 3 14:46:20 2012 -0500 - - abi check fixes and Linux/x32 support - -commit 6c194233a5f6f1d274669afc5924a9e1f69d4876 -Author: Anthony Green -Date: Sat Mar 3 14:17:54 2012 -0500 - - Add -no-undefined for both 32- and 64-bit x86 - windows-like hosts. - -commit 8360bf1cd0aba8db5582266da70467de7e89a57a -Author: Anthony Green -Date: Thu Feb 23 07:01:13 2012 -0500 - - Ensure that users don't include ffitarget.h directly - -commit d578b89619cf3d2baff027b203619dc307fc12e3 -Author: Anthony Green -Date: Wed Feb 15 00:18:18 2012 -0500 - - Fix ABI check regression - -commit dee20f8e45c486f5018f31e09bb362992aa498c3 -Author: Anthony Green -Date: Fri Feb 10 13:06:46 2012 -0500 - - Rebased from gcc - -commit 4130e1972d001143e5e9f3c6b65f2a6f9524169e -Author: Anthony Green -Date: Fri Feb 3 13:18:27 2012 -0600 - - Refresh autoconf-archive m4 scripts - -commit 1ff9c604bb214b5a305064af1049577ef783730a -Author: Anthony Green -Date: Wed Feb 1 16:34:30 2012 -0600 - - Rebase from GCC - -commit 211060eb8f714af0e935430efa6bb45e8e3ffc5d -Author: Anthony Green -Date: Mon Jan 23 14:24:01 2012 -0500 - - Alpha fix - -commit 78d9c638ba0de6edfbc603fd65d19c6562663248 -Author: Anthony Green -Date: Mon Jan 23 14:17:24 2012 -0500 - - mend - -commit afaf3381604bd81803d8a5f3bf4d462299f1aac3 -Author: Anthony Green -Date: Mon Jan 23 14:17:13 2012 -0500 - - mend - -commit 9e9c4aeb77de5608d602109f22100c1c0c79faad -Author: Anthony Green -Date: Mon Jan 23 14:11:23 2012 -0500 - - Add Amiga support - -commit 8efc0b1f4027d5a3cbf205e55d422d94e60f3226 -Author: Anthony Green -Date: Mon Jan 23 13:47:38 2012 -0500 - - Unlikely fixes - -commit 1df51398ae183dc208ba4599ee867278b04d13d3 -Author: Anthony Green -Date: Mon Jan 23 13:43:59 2012 -0500 - - mend - -commit cd2277cc796b96b149cd284ae85326529fe7fb9c -Author: Anthony Green -Date: Mon Jan 23 13:43:38 2012 -0500 - - mend - -commit 164e6fe04b189746c8bd5810c6e3e919770bb9d4 -Author: Anthony Green -Date: Mon Jan 23 12:41:06 2012 -0500 - - m68k fixes - -commit c365ee7577bef00cb3c2c0b5224147aea04138d8 -Author: Anthony Green -Date: Mon Jan 23 11:13:18 2012 -0500 - - Refresh - -commit f22c38bbd93bcc0c04bf26c3e414556b3177c385 -Author: Anthony Green -Date: Fri Nov 18 15:13:41 2011 -0500 - - Update variadic patch - -commit 03e9ee321a3c208f88d2432587ce40b2bb2430ba -Author: Anthony Green -Date: Fri Nov 18 15:13:00 2011 -0500 - - Fix cls_double_va.c and update docs - -commit 95f31151ec792809cfb80d385350f9f56d95aa25 -Author: Anthony Green -Date: Sat Nov 12 23:46:05 2011 -0500 - - Rerun automake - -commit 198ed1ef85cf18342627f8d44bc3f12c9975a49d -Author: Anthony Green -Date: Sat Nov 12 23:45:20 2011 -0500 - - Update version number - -commit 4f17e1f142e805b13959ba2594ee735eae439f4e -Author: Anthony Green -Date: Sat Nov 12 17:22:24 2011 -0500 - - Fix last patch - -commit ff9454da44859716a5bd4eaa344499288c79694f -Author: Anthony Green -Date: Sat Nov 12 17:18:51 2011 -0500 - - Add David Gilbert's variadic function call support - -commit ea14ae85e8f54ff046b7fb8a9cfe349475272044 -Author: Anthony Green -Date: Sat Nov 12 16:36:59 2011 -0500 - - clean up - -commit 52891f8a93f9b8de801cca4cf05639422dc9773e -Author: Anthony Green -Date: Sat Nov 12 16:35:55 2011 -0500 - - Add powerpc soft float support - -commit c8f1bde8e2566c5a87474b4d08aa934d6d28ee75 -Author: Anthony Green -Date: Sat Nov 12 16:21:02 2011 -0500 - - Remove junk file - -commit 6a6e7f862f3cc677e19131587caa619e7f9c7ffd -Author: Anthony Green -Date: Sat Nov 12 16:20:42 2011 -0500 - - Fix kfreebsd - -commit d52fbed05ccbdee9ed8b9c911cbb4f85b0ff0f2a -Author: Anthony Green -Date: Sat Nov 12 16:13:41 2011 -0500 - - Add missing ChangeLog entry - -commit 322052ce65c4fdac85bedc24726fd0e0094ba521 -Author: Anthony Green -Date: Sat Nov 12 16:11:49 2011 -0500 - - Fix arm wince alignment issue - -commit af18df2bc2f52df81e7b5c619bd86db8489dc873 -Author: Anthony Green -Date: Sat Nov 12 15:52:08 2011 -0500 - - Remove use of ppc string instructions - -commit 236c9391321f83ad40daf03f40c35c9ebc1da6b3 -Author: Anthony Green -Date: Sat Nov 12 07:37:40 2011 -0500 - - Fix darwin11 build problem - -commit c411f140f305ebb00d33c92b7cb2742bcd241b6a -Author: Anthony Green -Date: Sat Nov 12 07:32:36 2011 -0500 - - Fix ax_enable_builddir macro on BSD systems - -commit 3d56106b07735abef6ae9f032e94f560a0ed2f30 -Author: Anthony Green -Date: Sat Nov 12 07:20:24 2011 -0500 - - Rebase - -commit 8c01954c50bf8ef2e00a3db166060a1b8f83a20d -Author: Anthony Green -Date: Tue Sep 6 14:26:32 2011 -0400 - - Build assembly files with debug info - -commit fed646a2078969f4ce89c29107f1e72e03f4a977 -Author: Anthony Green -Date: Tue Sep 6 09:50:20 2011 -0400 - - Regenerate configury with missing m4 macros - -commit d76441cf71216f8f1e62e7ec852a7f4e21371ec8 -Author: Anthony Green -Date: Wed Aug 24 10:14:23 2011 -0400 - - Update list of supported OpenBSD systems - -commit ee6696fdf4768ba6dd037fb6dd99435afa13816e -Author: Anthony Green -Date: Tue Aug 23 12:30:29 2011 -0400 - - 3.0.11-rc1. soname bump. - -commit c6265c36a91eab8175d0e72db84d8225418f2379 -Author: Anthony Green -Date: Tue Aug 23 10:31:33 2011 -0400 - - Version 3.0.10 - -commit cc5e41bf32d18a14dbdd653d52eacdbdc934c392 -Author: Anthony Green -Date: Mon Aug 22 16:34:24 2011 -0400 - - Fix use of autoconf macros - -commit 049d8386ff52399e69a530b55b9feedc8a2589d2 -Author: Anthony Green -Date: Mon Aug 22 14:50:10 2011 -0400 - - Many new patches - -commit 3b7efa4e74f0dcebf70b447391987aedd3473306 -Author: Anthony Green -Date: Mon Aug 15 13:25:13 2011 -0400 - - Revert remove-debug-code patch temporarily (for ARM Fedora release) - -commit d992ac54a2a9e7e064ffebcb91e05e7cb86185c7 -Author: Anthony Green -Date: Fri Jul 29 17:32:53 2011 -0400 - - Refresh from GCC - -commit 2d3fb36420e09304220ee6c0652bae5eccdb965d -Author: Anthony Green -Date: Wed Mar 30 16:54:42 2011 -0400 - - Fix darwin EH - -commit 30ff28e1d8cd9ed5319f1fbe9c7cccacc8161fb3 -Author: Anthony Green -Date: Mon Feb 28 15:36:23 2011 -0500 - - Fix permissions - -commit 09f8f310f4f53a24289682d3d28f4399d7bafc3b -Author: Anthony Green -Date: Mon Feb 28 15:36:07 2011 -0500 - - More AIX fixes. rc9. - -commit 53d7b165642c220aa5166ba350b490802f359b54 -Merge: 18dd85d 3000dc2 -Author: Anthony Green -Date: Mon Feb 28 15:23:31 2011 -0500 - - Merge branch 'master' of https://github.com/landonf/libffi-ios - -commit 18dd85d6cb9f3f3eea2a3b70eb4e150045905c55 -Author: Anthony Green -Date: Fri Feb 25 16:23:04 2011 -0500 - - rc8. fix last patch. - -commit 74ee6ea8b42e60d44a3ae8938b1e42a38c1e66b4 -Author: Anthony Green -Date: Fri Feb 25 15:52:14 2011 -0500 - - rc7. More AIX fixes. - -commit 2541679dbd3db0014890f42192dbf8008ab923fa -Author: Anthony Green -Date: Fri Feb 25 15:09:13 2011 -0500 - - Fix ppc32 bug - -commit cbb062cc35c518004f1ab45c847f8ec4f66069ad -Author: Anthony Green -Date: Thu Feb 17 20:39:21 2011 -0500 - - Another non-GCC configury fix - -commit 8cf8878425e9971866fa6b27a3e4914729ad3960 -Author: Anthony Green -Date: Tue Feb 15 15:19:49 2011 -0500 - - Fix ax_cc_maxopt.m4 - -commit 24b72070c0937f9000744c77a636f07e04786b6a -Author: Anthony Green -Date: Mon Feb 14 15:30:57 2011 -0500 - - Fix warning and msvcc patches - -commit d72c49e556a8c516e97f6722d1be2f1209c21207 -Author: Anthony Green -Date: Sun Feb 13 11:41:05 2011 -0500 - - Add missing msvcc.sh - -commit 3000dc237f6017a7445d8404097a4f46b73fdd29 -Merge: 55e4a5a 1fbf9dc -Author: Landon Fuller -Date: Sun Feb 13 08:55:53 2011 -0500 - - Merge remote branch 'upstream/master' - -commit 1fbf9dc44feea564e84ad7406d17c5d5906ce0e0 -Author: Anthony Green -Date: Sun Feb 13 08:06:39 2011 -0500 - - Fix bad_abi test. rc5. - -commit 90af15ef5c1614b76370c4d13954586fabf9e8e3 -Author: Anthony Green -Date: Sat Feb 12 12:29:36 2011 -0500 - - iOS fixes - -commit 55e4a5aa1568558a04aa40f16fc022e459af53e3 -Author: Landon Fuller -Date: Sat Feb 12 12:13:46 2011 -0500 - - Add support for building a full armv6/armv7/i386 universal iOS library - -commit a0c80f279b8733d001cb5e5c5a3289ecb7a6e56a -Author: Landon Fuller -Date: Sat Feb 12 11:43:49 2011 -0500 - - Update my e-mail address. - -commit 8195e0e11df7a53fa474caa9375f73ca1136ed66 -Author: Landon Fuller -Date: Sat Feb 12 11:27:00 2011 -0500 - - Fix symbol prefixes on Darwin. - -commit 56b3f8cef0f28cefaa0f40fe0cf7c524adef131d -Author: Landon Fuller -Date: Sat Feb 12 11:14:54 2011 -0500 - - Modify the ffi_closure structures to hold table/table entry pointers instead of a code buffer. - - This re-integrates commit da2773e02ab26cc11a7f. - -commit 28a00f61ff3f64c4eb2269ce2aea3d493274469e -Author: Landon Fuller -Date: Sat Feb 12 11:01:48 2011 -0500 - - Apple assembler support; fixed most gas/ELF-isms. - -commit 7f2ea33a80bfced5e48ed7292f3b8f057d54ff8f -Author: Landon Fuller -Date: Sat Feb 12 10:39:18 2011 -0500 - - Replace RETLDM macro. - - The macro is incompatible with Apple's assembler; switch to - a simple inline version. - -commit 92ff23e77fa586455b427b71f49e1d9502470e6e -Author: Landon Fuller -Date: Sat Feb 12 10:24:49 2011 -0500 - - Switch to the current iOS 4.2 SDK. - -commit 58fb8ca2dfb89ad70284bb9678d3d4dbb658c8a7 -Merge: cc3fbd9 71c792f -Author: Landon Fuller -Date: Sat Feb 12 10:23:19 2011 -0500 - - Merge remote branch 'upstream/master' - -commit cc3fbd975ce9366d4c40a6ff6c108f664867bd7c -Merge: e449a43 f6ab3ed -Author: Landon Fuller -Date: Sat Feb 12 10:21:02 2011 -0500 - - Merge branch 'master' of github.com:landonf/libffi-ios - -commit e449a43bbe12f8119399928db1ae26adc71dde14 -Author: Landon Fuller -Date: Sat Feb 12 10:20:42 2011 -0500 - - Allow specification of the minimum supported iOS version. - -commit 71c792f51bcf3e2f334e5ea1fb1a8b667cb3aedb -Author: Anthony Green -Date: Sat Feb 12 09:33:11 2011 -0500 - - rc4 - -commit 7c7c9f327299331022f6000603a35f2310dfe308 -Author: Anthony Green -Date: Sat Feb 12 09:29:29 2011 -0500 - - ungccify parts of the build - -commit ed62e48b95a0fa60b685f647cb73c9e190eec35c -Author: Anthony Green -Date: Fri Feb 11 12:23:58 2011 -0500 - - Fix permissions - -commit 17d9e9e68ddb1b915a0b9751713033861b598575 -Author: Anthony Green -Date: Fri Feb 11 12:23:20 2011 -0500 - - Use newer autotools. Only build debug.c when --enable-debug. - -commit 6972a4ffda75761eaab7dfbe0fb1516b255e8e0c -Author: Anthony Green -Date: Fri Feb 11 07:32:51 2011 -0500 - - Fix xlc build on AIX - -commit 1833aa0fb9831eb0725b63e35886c0f6d35df480 -Author: Anthony Green -Date: Fri Feb 11 07:11:04 2011 -0500 - - sparc ABI test fix. - -commit f1fb139b4e283fffdcf205a903943d5e9d2bb2a2 -Author: Anthony Green -Date: Wed Feb 9 18:30:02 2011 -0500 - - Fix tests - -commit 5cb470331d181c84d5d621e88868327a324a5898 -Author: Anthony Green -Date: Wed Feb 9 15:23:06 2011 -0500 - - Fix permissions - -commit 269deef6dbbb426695919d3398357fada3bb288c -Author: Anthony Green -Date: Wed Feb 9 15:22:23 2011 -0500 - - rc3 - -commit 42695e72504f647444b8e8e9b90bd24f1e3220e1 -Author: Anthony Green -Date: Wed Feb 9 15:12:35 2011 -0500 - - Fix IRIX support - -commit a6e56b97f62a3feeb3301c24a2e4cae55e546021 -Author: Anthony Green -Date: Wed Feb 9 15:00:42 2011 -0500 - - Add powerpc64-*-darwin* support - -commit 747d6c32d4abb07c10c3a1f93579c3929aaa2487 -Author: Anthony Green -Date: Wed Feb 9 14:56:23 2011 -0500 - - Add Interix support - -commit eab6e41cde382aa07de6c011d514a14c0d62eb47 -Author: Anthony Green -Date: Wed Feb 9 10:15:02 2011 -0500 - - Remove README.markdown form libffi-ios - -commit 69dbe845f4ee3e6ce8999f17a1e4f2179ef7da89 -Author: Anthony Green -Date: Wed Feb 9 07:38:43 2011 -0500 - - Fix xfails - -commit f498318c07b95137fe259d86bdbe15347588b84a -Author: Anthony Green -Date: Wed Feb 9 06:26:46 2011 -0500 - - Update README for iOS again - -commit 630b9c0ac43c7edcbfd892e23c09fb26724f4ac0 -Author: Anthony Green -Date: Wed Feb 9 06:24:23 2011 -0500 - - Update to rc2 - -commit 0cad4386fa4c9ea5f8ca88b16247db4e5c8fea90 -Author: Anthony Green -Date: Wed Feb 9 06:11:46 2011 -0500 - - Add ChangeLog entry. Fix copyright headers. - -commit 09cb76f2645bd2c151846e9249d8ea707ba01e8c -Author: Anthony Green -Date: Tue Feb 8 20:39:51 2011 -0500 - - Add missing change - -commit 2e3a48ccdd54340983c46a29a0b41985e3e789ac -Author: Anthony Green -Date: Tue Feb 8 20:37:26 2011 -0500 - - Fix make dist - -commit 5e4814d9928e236a2a4afe84d6e1d4fdaa473206 -Author: Anthony Green -Date: Tue Feb 8 19:46:28 2011 -0500 - - fix permissions - -commit 5c0cc6f1536aa1738795a97303810a823c7fa2cb -Author: Anthony Green -Date: Tue Feb 8 19:45:59 2011 -0500 - - 3.0.10rc1 - -commit 857fe3de46d2286afa2fe772920ecf4aefa1688f -Author: Anthony Green -Date: Tue Feb 8 19:39:20 2011 -0500 - - Clean ups - -commit e2214f8adb5577c247452e2cc9f4cbe304d7ca9f -Author: Anthony Green -Date: Tue Feb 8 19:22:56 2011 -0500 - - Update README - -commit 1106229a5721a659da5c231ec0e8211119615394 -Merge: bc9d0be f6ab3ed -Author: Anthony Green -Date: Tue Feb 8 19:20:09 2011 -0500 - - Add iOS support - -commit bc9d0be2958ce475757f34dd2c878948aa77a39f -Author: Anthony Green -Date: Tue Feb 8 17:04:26 2011 -0500 - - 3.0.10rc0 changes - -commit 3b836249feae6d08d3e6887486e4b9961ddafa09 -Author: Anthony Green -Date: Tue Feb 8 14:28:59 2011 -0500 - - Rebase from GCC - -commit a26e3940619faeba6de54824c9540c90b1aab513 -Author: Anthony Green -Date: Tue Feb 8 13:56:12 2011 -0500 - - copyright updates patch - -commit b8099539f00e224107594101e9760b6dc081a056 -Author: Anthony Green -Date: Tue Feb 8 13:50:43 2011 -0500 - - Fix msvcc.sh botch - -commit dc411e8f99113a34656bfd2d3ae51259972488cc -Author: Anthony Green -Date: Tue Feb 8 10:49:29 2011 -0500 - - Fix HP-UX build - -commit 404585d1348e30ac58203bbd876d9131e5aed874 -Author: Anthony Green -Date: Tue Feb 8 10:44:36 2011 -0500 - - Fix sparc v8 aggregate type returns for sun's compiler - -commit 19ce713188e193e4522740d24c20170411883d2d -Author: Anthony Green -Date: Tue Feb 8 10:34:23 2011 -0500 - - grammar fix - -commit 89284fe55f1a8ad3bddbea796ee00d0e3ba411ce -Author: Anthony Green -Date: Tue Feb 8 10:19:19 2011 -0500 - - Fix AIX build with IBM XLC - -commit ba022c338af97cb18d9f8ed5a607fd483a61c09c -Author: Anthony Green -Date: Tue Feb 8 10:12:48 2011 -0500 - - fix win64-underscore patch - -commit 097e5f3924ee92a3ba6cd72f787da8a3eb14fea3 -Author: Anthony Green -Date: Tue Feb 8 10:11:00 2011 -0500 - - x86 pcrel test part 2 - -commit ed2c518d960b91d444be74e5a55779a9c4602f3b -Author: Anthony Green -Date: Tue Feb 8 10:10:07 2011 -0500 - - x86 pcrel test - -commit 0e5843995f46900ef212531281e08b224464f413 -Author: Anthony Green -Date: Tue Feb 8 07:52:40 2011 -0500 - - Refresh from GCC - -commit 5b9cd52784339a42e417174a55e310e214d435f9 -Author: Anthony Green -Date: Mon Nov 22 15:19:57 2010 -0500 - - win64-underscore patch - -commit 2db72615b50eb5c0f29725c02c740a2f0d7fc7d9 -Author: Anthony Green -Date: Sun Nov 21 10:50:56 2010 -0500 - - Rebase - -commit f6ab3edc23dc8fc7c47a31c896044150c23f04b5 -Author: Landon Fuller -Date: Wed Oct 27 19:34:51 2010 -0400 - - Include the license header in the generated output. - -commit cef619462887fa0f360e3ee702d1e04f112b5b38 -Author: Landon Fuller -Date: Wed Oct 27 13:59:30 2010 -0400 - - Add missing copyright/license header. - -commit 53f387b203413c9aa6e31f49dbb70d37d816330b -Author: Landon Fuller -Date: Sun Sep 19 19:57:17 2010 -0700 - - Minor README fix. - -commit 4fbcb5b5fbce11f4b168060e00639db33c85b75b -Author: Landon Fuller -Date: Sun Sep 19 19:50:37 2010 -0700 - - Minor README fix. - -commit 8e7652ef6acab5db7a29f786686a54f05cdbdc7d -Author: Landon Fuller -Date: Sun Sep 19 19:49:39 2010 -0700 - - Add a libffi-ios-specific github README. - -commit 83038cf24aa1a92b62b91ffee1dcc25d79243484 -Author: Landon Fuller -Date: Sun Sep 19 14:36:45 2010 -0700 - - Implement FFI_EXEC_TRAMPOLINE_TABLE allocator for iOS/ARM. - - This provides working closure support on iOS/ARM devices where - PROT_WRITE|PROT_EXEC is not permitted. The code passes basic - smoke tests, but requires further review. - -commit b00ff3e98fdde622cef617030e14d5356dff988f -Author: Landon Fuller -Date: Sun Sep 19 14:22:26 2010 -0700 - - Rename the generated symbol - -commit da2773e02ab26cc11a7fe87e985599f35cdf0649 -Author: Landon Fuller -Date: Sun Sep 19 14:21:37 2010 -0700 - - Modify the ffi_closure structures to hold table/table entry pointers instead of a code buffer. - -commit 01d71b7bed41844f80cb9feef20dcc5ece5ba2d0 -Author: Landon Fuller -Date: Sun Sep 19 14:21:14 2010 -0700 - - Regenerated the autoconf script - -commit 19afda0069c42e51c81dca7b10a5cf884b4cdce0 -Author: Landon Fuller -Date: Sun Sep 19 14:20:52 2010 -0700 - - Enable AC_SUBST for FFI_EXEC_TRAMPOLINE_TABLE - -commit 9e1196444e78aef20028c18891f44ebe39a815fd -Author: Landon Fuller -Date: Sun Sep 19 10:43:06 2010 -0700 - - Add a hard-coded FFI_EXEC_TRAMPOLINE_TABLE arm implementation. - - This implements support for re-mapping a shared table of executable - trampolines directly in front of a writable configuration page, working - around PROT_WRITE restrictions for sandboxed applications on Apple's - iOS. - - This implementation is for testing purposes; a proper allocator is still - necessary, and ARM-specific code needs to be moved out of - src/closures.c. - -commit f38364b399184e682fc3e785084bd497827bc5af -Author: Landon Fuller -Date: Sun Sep 19 10:42:36 2010 -0700 - - Fix symbol prefix for ffi_closure_SYSV_inner on Darwin. - -commit 36849e7716b77aa25e4175d1f4be1b93dbf47aac -Author: Landon Fuller -Date: Sun Sep 19 09:35:04 2010 -0700 - - Whitespace/comment fixes. - -commit b764162526854686e579a48b6ac5981f4eb886a3 -Author: Landon Fuller -Date: Sun Sep 19 09:04:34 2010 -0700 - - Fix the script name (build-iphone.sh -> build-ios.sh) - -commit a3d9aa85013341451ea97766485b7a11852d32b2 -Author: Landon Fuller -Date: Sun Sep 19 09:03:52 2010 -0700 - - Update the autogenerated autoconf/automake files. - -commit c71480eaf839f26bbdfcd8965f65ac4d8defddc0 -Author: Landon Fuller -Date: Sun Sep 19 09:02:05 2010 -0700 - - Update automake/autoconf to conditionally build src/arm/trampoline.S if FFI_EXEC_TRAMPOLINE_TABLE is enabled. - -commit 9af9291b73bc5e27ecd949bec8157f20426d65b8 -Author: Landon Fuller -Date: Sun Sep 19 08:52:33 2010 -0700 - - Add the trampoline table generated by gentramp.sh - -commit 68ce0c383ece84f69945d1c8c3fed03f7f9cb5d6 -Author: Landon Fuller -Date: Sun Sep 19 08:38:19 2010 -0700 - - Add a shell script that generates the ARM trampoline page. - - This generates a page of 340 trampolines, aligned within one page. The - trampolines use pc-relative addressing to reference config data - (context, jump address) from a page placed directly prior to the - trampoline page. This can be used on systems -- such as iOS -- that do not - support writable, executable memory by remapping the executable page - containing the trampolines directly above a newly allocated writable - config page. - -commit 75af086be8830a8eafe9b1ebda199d788bcb0c62 -Author: Landon Fuller -Date: Sat Sep 18 18:12:19 2010 -0700 - - Update autoconf files - -commit 1ac92cca9b02ef8d6a769f0de1adccd5c9630355 -Author: Landon Fuller -Date: Sat Sep 18 18:08:14 2010 -0700 - - Add autoconf check for W^X platforms that require a trampoline table. - - This adds the FFI_EXEC_TRAMPOLINE_TABLE. The flag is enabled for - arm-apple-darwin, where PROT_EXEC on writable (or formerly writable) pages is - not permitted for sandboxed binaries. - -commit be72fbab29b7190c702d8e1ac3d149855e95879d -Author: Landon Fuller -Date: Sat Sep 18 18:02:25 2010 -0700 - - Use the correct host triple for arm/darwin - -commit 70150bdf4509269965c72f2032bf74f285767afe -Author: Landon Fuller -Date: Sat Sep 18 16:38:03 2010 -0700 - - Add missing UNWIND entry; disables .pad on non-EABI targets. - -commit 6b452bafaec498df975ba8ac4c99de174e5f74f7 -Author: Landon Fuller -Date: Sat Sep 18 16:21:32 2010 -0700 - - Apple assembler support; fixed most gas/ELF-isms. - -commit 8ddac835b6f8b54ede764d0ea977dee4c82e2d67 -Author: Landon Fuller -Date: Sat Sep 18 15:38:06 2010 -0700 - - Fix placement of the __APPLE__ macro. - -commit 69043d02936bb0579ac59b4ee1ed8dec38c38db7 -Author: Landon Fuller -Date: Sat Sep 18 15:32:08 2010 -0700 - - Work-around libffi's FP ABI detection. - - On iOS, we must use the AAPCS floating point return value calling - conventions. libffi's ARM implementation will only use these conventions - if __SOFTFP__ is defined, which is not the case when GCC's - -mfloat-abi defaults to 'softfp' instead of 'soft'. To work around this - we manually define __SOFTFP__ for Apple platforms in the ARM-specific - sysv.S. - - See also: - http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iPhoneOSABIReference/Introduction/Introduction.html - http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf - -commit a82e6c354ea805114642a6e440abd0832cb1d23f -Author: Landon Fuller -Date: Sat Sep 18 14:44:24 2010 -0700 - - Add a stub iOS build script to drive autoconf - -commit 84e8de6e9fc19388f6f1102c013b7d0d52940ecc -Author: Anthony Green -Date: Fri Aug 6 01:35:12 2010 -0400 - - Restore execute permissions - -commit 3aeecc9eb1a6feba6549849cdd335c926415a4fc -Author: Anthony Green -Date: Thu Aug 5 15:19:00 2010 -0400 - - Fix win64-struct-args patch - -commit 00d0b59cd13f89ab8b44bd894eb7f0a131fcb472 -Author: Anthony Green -Date: Thu Aug 5 14:56:53 2010 -0400 - - Fix debug build for windows - -commit bda487e87064f27965155459a62dc52a744778d0 -Author: Anthony Green -Date: Thu Aug 5 09:02:41 2010 -0400 - - Don't use -safeseh with ml64 - -commit c1d28ba8d5029795af313ffeb81c97efc6d4c847 -Author: Anthony Green -Date: Thu Aug 5 08:48:16 2010 -0400 - - stdcall-x86-closure-fix - -commit 5feacad4a56c85b3f23a267a30b2cf424cd59548 -Author: Anthony Green -Date: Thu Aug 5 08:30:04 2010 -0400 - - define generic symbols carefully - -commit 10ea848900bc3018ac213cef52b44cacbe5cbebc -Author: Anthony Green -Date: Thu Aug 5 08:24:27 2010 -0400 - - don't copy win64 struct args - -commit d14178be4c49c3ada44a9fe9efe11d444372ddab -Author: Anthony Green -Date: Fri Jul 23 09:14:00 2010 -0400 - - FFI_LAST_ABI fix - -commit 3f5b1375ab1e2b8e3d593e21b27097a4a50f9b83 -Author: Anthony Green -Date: Mon Jul 12 14:39:18 2010 -0400 - - rebase - -commit eaf444eabc4c78703c0f98ac0197b1619c1b1bef -Author: Anthony Green -Date: Sat Jul 10 08:59:09 2010 -0400 - - Fix selinux test - -commit 630974152247f100ece4d44f10c3721bb4599fbf -Author: Anthony Green -Date: Wed May 5 20:14:56 2010 -0400 - - Micharl Kohler's spelling fixes - -commit 9dc9a293f3d4589fcaf02dd4288c8cebaefa508e -Author: Anthony Green -Date: Tue Apr 13 10:33:52 2010 -0400 - - Rebase to latest GCC sources - -commit f2c2a4fce9b3eca9f39b4f3545118bc256da4a73 -Author: Anthony Green -Date: Tue Apr 13 10:19:28 2010 -0400 - - Remove warnings and add OS/2 support - -commit c0b69e57d529e33d18b658cc5572a21e3663247c -Author: Anthony Green -Date: Tue Mar 30 08:30:22 2010 -0400 - - Dan Witte's windows build fixes. - -commit 59a259f4d348f593b45f452309f4d020a28051c4 -Author: Anthony Green -Date: Mon Mar 15 05:57:51 2010 -0400 - - Remove junk file - -commit 3de1eb36d37a66829e606421939874d0d60d816d -Author: Anthony Green -Date: Mon Mar 15 05:57:24 2010 -0400 - - fix-comments patch - -commit c3813b6d7f8a777700f4c5862190c0db148d4de8 -Author: Anthony Green -Date: Tue Jan 26 16:48:56 2010 -0500 - - Rebuild Makefiles with automake 1.11.1 for CVE-2009-4029. - -commit 8d27f68baa365bf883b6053c5f6bc819646d5434 -Author: Anthony Green -Date: Fri Jan 15 11:35:37 2010 -0500 - - Mention recent changes in README - -commit ff3cd68b8cf2d9a28cad7aa9beff46236eacec8c -Author: Anthony Green -Date: Fri Jan 15 11:27:24 2010 -0500 - - Add msvc.sh wrapper - -commit cadeba6cb53414a1253582f1719c286665de7b6c -Author: Anthony Green -Date: Fri Jan 15 10:46:51 2010 -0500 - - Microsoft Visual C port - -commit 0739e7dc00db766eb64f502ec4137b817638c9a1 -Author: Anthony Green -Date: Fri Jan 15 09:48:33 2010 -0500 - - Add x86 Sun Studio compiler support - -commit edfdfd2e85b8d01d2455934f1d7f4d7eb2f3cf1c -Author: Anthony Green -Date: Wed Jan 13 02:56:19 2010 -0500 - - Add closure example doc - -commit 7b7a42f221cf171e8d09df34cac6dc1fd8458cc3 -Author: Anthony Green -Date: Tue Jan 12 09:14:14 2010 -0500 - - Rebase from GCC - -commit 4b18d1f73dc7733137869e4ab5725cb90c1c8fde -Author: Anthony Green -Date: Fri Jan 1 10:24:27 2010 -0500 - - Add x86-64 MingW to README - -commit c3042afaf3f84abbbe9c91bf9bc9896b0d9eb003 -Author: Anthony Green -Date: Fri Jan 1 08:08:02 2010 -0500 - - Reset quilt patches post 3.0.9 merge with GCC - -commit b0304e9679bdfec6ac45a57b5c96542697249418 -Author: Anthony Green -Date: Thu Dec 31 11:32:40 2009 -0500 - - Update version - -commit 2e7e03d014d9c9bf40e97ce75cba089ad052fa6b -Author: Anthony Green -Date: Thu Dec 31 07:43:22 2009 -0500 - - Final updates before 3.0.9 - -commit aea706c52825c8eee677ffa7fdbdd3aed1725492 -Author: Anthony Green -Date: Tue Dec 29 10:09:31 2009 -0500 - - really 3.0.9rc12 - -commit 0cfe60e9d13f132b88995cfee41f2156344f6fa2 -Author: Anthony Green -Date: Tue Dec 29 10:06:04 2009 -0500 - - 3.0.9rc12 - -commit 14e2e92e8645804b6940b3e96c98e9f7f384a6b2 -Author: Anthony Green -Date: Sun Dec 27 21:03:33 2009 -0500 - - 3.0.9rc11 - -commit 884402787bf8eaf7ec207085037cf8ace2f660ec -Author: Anthony Green -Date: Sat Dec 26 12:57:23 2009 -0500 - - HPUX support and avr32 test fixes. - -commit 01c78756aff22efb1f122f8e93e068d7bf2185c7 -Author: Anthony Green -Date: Sat Dec 26 10:05:18 2009 -0500 - - 3.0.9rc9 - -commit 70868464651320268d79c6894db5a50fdc11032a -Author: Anthony Green -Date: Sat Dec 26 09:58:03 2009 -0500 - - Remove xfails for mips and arm - -commit 838d4ad920ec85cf5ca3b511221d67f6d9a99024 -Author: Anthony Green -Date: Sat Dec 26 09:57:27 2009 -0500 - - Remove a bunch of xfails. - -commit 7e37eaaf772f48906e69618c773b0a36c3927de9 -Author: Anthony Green -Date: Sat Dec 26 07:46:50 2009 -0500 - - Fix huge_struct for solaris - -commit 07cc7a37194bc34064ebed7f2724333a798411c8 -Author: Anthony Green -Date: Sat Dec 26 07:23:04 2009 -0500 - - 3.0.9rc8 - -commit 2b9be16ffabc81326128bc1bbdddff8ddc5d13d3 -Author: Anthony Green -Date: Sat Dec 26 07:04:45 2009 -0500 - - 3.0.9rc8 - -commit 9458d88f676e9a21ab8993a54e16754b11687419 -Author: Anthony Green -Date: Sat Dec 26 07:02:27 2009 -0500 - - Rebase from GCC - -commit 6a3412417593f068a04dc6163f4269cb295ad5ca -Author: Anthony Green -Date: Sat Dec 26 06:51:33 2009 -0500 - - Add Andreas Schwab's powerpc fix - -commit 39c8792ece1043f41f4c395a2ce71f4cf0ff4674 -Author: Anthony Green -Date: Fri Dec 25 21:52:28 2009 -0500 - - 3.0.9rc7 - -commit 1d04af52e3e24db69f742064694c22f8df5cc70e -Author: Anthony Green -Date: Fri Dec 25 09:50:36 2009 -0500 - - Updated some mips XFAILs - -commit 26e9509c9b7929bc4fcf697071699051a652b1fd -Author: Anthony Green -Date: Fri Dec 25 02:19:23 2009 -0500 - - Clean up ChangeLog.libffi for older patches. - -commit 9c157d3215e4393777f83eb6fa801df6528f40d7 -Author: Anthony Green -Date: Fri Dec 25 02:15:40 2009 -0500 - - Clean up undefine_AC_ARG_VAR_PRECIOUS patch. - -commit d22de05b0bfc480766bc1240615ce2830eee71b8 -Author: Anthony Green -Date: Fri Dec 25 02:04:23 2009 -0500 - - Fix patches - -commit 1fe3dc7c20dc4dbd8fed0d19c8618027d44ed971 -Author: Anthony Green -Date: Fri Dec 25 01:39:00 2009 -0500 - - Add windows support patch. - -commit f7c0bc613a88f7dbc2d18b345c10fa438833c170 -Author: Anthony Green -Date: Fri Dec 25 01:22:11 2009 -0500 - - 3.0.9rc6 - -commit c7fa2da8260258c11ab1dc7ac06fb611a2c1b50f -Author: Anthony Green -Date: Thu Dec 24 07:22:44 2009 -0500 - - 3.0.9rc6 - -commit da11bece0fde66fc0268db3a01207dda857e25d2 -Author: Anthony Green -Date: Thu Dec 24 05:34:46 2009 -0500 - - Release 3.0.9rc5 - -commit e3399b11edeab546b066bfc18574f3edb905d0dc -Author: Anthony Green -Date: Thu Dec 24 01:09:32 2009 -0500 - - Update README - -commit 115ab36fceee69740a01ce49bc27e1908cc237b1 -Author: Anthony Green -Date: Thu Dec 24 00:22:00 2009 -0500 - - Update missing changes for 3.0.9r4. - -commit f8c7a245bf5a80bd7e730ec03fcad17c8dcfcb07 -Author: Anthony Green -Date: Wed Dec 23 23:46:22 2009 -0500 - - Switch to quilt. Rebase to latest GCC. - -commit ce806772f02387b9a74f6496a263a368bccd5d59 -Merge: cd98813 dcc1f6b -Author: Anthony Green -Date: Mon Oct 5 00:41:35 2009 -0400 - - Merge branch 'master' of git@github.com:atgreen/libffi - -commit dcc1f6b4f1ffd2713bf68b791a13f85d455c8b1b -Author: Anthony Green -Date: Mon Oct 5 00:29:33 2009 -0400 - - More clean up. - -commit 2829f5941a223b9d851d8ab6318318e6197d7e01 -Author: Anthony Green -Date: Mon Oct 5 00:28:03 2009 -0400 - - Clean up - -commit cd98813de517ea64041637e3e78d27a001d6d3b4 -Author: Anthony Green -Date: Mon Oct 5 00:25:29 2009 -0400 - - From Jens Rehsack. Fix for 64-bit AIX. - -commit e4a91de766acc47f6c50f13cc11719a65e23ecba -Author: Anthony Green -Date: Mon Oct 5 00:16:17 2009 -0400 - - From Abdulaziz Ghuloum. Adds special case for Snow Leopard. - -commit 3425a763bcdaadb8b430226f427ec833afdcc96a -Author: Anthony Green -Date: Sun Oct 4 23:57:29 2009 -0400 - - Fix detection of free/openbsd. From Alexis Ballier. - -commit 2340e7a777902de61499d47823ad8d5e0eeb6203 -Author: Anthony Green -Date: Sun Oct 4 23:53:17 2009 -0400 - - AVR support - -commit 5cbe2058c128e848446ae79fe15ee54260a90559 -Author: Anthony Green -Date: Sun Oct 4 23:53:11 2009 -0400 - - Initial stand-alone patch. - -commit c6dddbd02bad9654ed58cdb0feb360934d105dec -Author: Anthony Green -Date: Sun Oct 4 08:11:33 2009 -0400 - - Initial commit - -commit 5ffc0c37486fb1538bccc0ca7acc807d4f1af932 -Author: Anthony Green -Date: Sun Oct 4 07:58:22 2009 -0400 - - Update version to 3.0.9rc1. Add more useful things to .gitignore. - -commit bd29f83ee9f6fa6b65adee9d3f57834f364d9887 -Author: Anthony Green -Date: Tue Sep 29 12:07:26 2009 -0400 - - Add .gitignore - -commit 9474f853f83e3f0167c1b306177321bfcc93e56d -Author: Anthony Green -Date: Tue Sep 29 11:13:02 2009 -0400 - - Remove old CVSROOT files. - -commit 0c25275ec24bfe2c2c25a000465f0950ef9dd51b -Author: twall -Date: Wed Aug 19 12:57:34 2009 +0000 - - Apply Dave Korn's cygwin/GCC changes - -commit 39228c27ed3f677a95b46380a8d31602b5777e1a -Author: aph -Date: Tue Jun 16 18:00:47 2009 +0000 - - 2009-06-16 Wim Lewis - - * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are - supposed to be callee-saved. - * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of - return buffer for odd-size structs. - -commit 5e93cc704d127c2c8ae7f5d2cef621145d43e777 -Author: aph -Date: Tue Jun 16 17:41:47 2009 +0000 - - 2009-06-16 Andreas Tobler - - PR libffi/40444 - * testsuite/lib/libffi-dg.exp (libffi_target_compile): Add - allow_stack_execute for Darwin. - -commit b509af8959dc371b92392c623522ea6f4946a71d -Author: aph -Date: Tue Jun 16 16:17:52 2009 +0000 - - 2009-06-16 Andrew Haley - - * configure.ac (TARGETDIR): Add missing blank lines. - * configure: Regenerate. - -commit d57e96dc56ee76fbbb9b59d73aeaa92354db5ecb -Author: aph -Date: Tue Jun 16 09:59:02 2009 +0000 - - 2009-06-16 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs. - * testsuite/libffi.call/float2.c: Fix dg-excess-errors. - * testsuite/libffi.call/ffitest.h, - testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. - -commit b01d6d1982c9e020507029bfd5a58a8c60d111fa -Author: aph -Date: Tue Jun 16 09:44:54 2009 +0000 - - 2009-06-16 Andrew Haley - - * testsuite/libffi.call/err_bad_typedef.c: xfail everywhere. - * testsuite/libffi.call/err_bad_abi.c: Likewise. - -commit 35b6ded138591900a88055a8a8ac1fadc29a76d6 -Author: aph -Date: Fri Jun 12 15:29:20 2009 +0000 - - 2009-06-11 Kaz Kojima - - * testsuite/libffi.call/cls_longdouble_va.c: Add xfail sh*-*-linux-*. - * testsuite/libffi.call/err_bad_abi.c: Add xfail sh*-*-*. - * testsuite/libffi.call/err_bad_typedef.c: Likewise. - -commit acc46605f2d95d67d69398e7644610f10a157ce3 -Author: aph -Date: Fri Jun 12 14:21:28 2009 +0000 - - 2009-06-12 Andrew Haley - - * ChangeLog.libffi: testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - testsuite/libffi.special/unwindtest.cc: include stdint.h. - -commit 16d1996ed0797bd7c11aca2b0fe7e7748751aaf6 -Author: twall -Date: Thu Jun 11 14:27:42 2009 +0000 - - update changelog - -commit 92a515c33efe91be3cb0258f01c63aff208489c7 -Author: twall -Date: Thu Jun 11 14:27:28 2009 +0000 - - use ffi_closure_alloc instead of stack-based closure - -commit e4363160ba9e50167f9ca0a7399d537a1d2cd0ce -Author: twall -Date: Thu Jun 11 14:26:23 2009 +0000 - - remove unused extern - -commit 1dc2781d2ba38f5f000ff70069d617fb21e1d2af -Author: twall -Date: Thu Jun 11 11:36:16 2009 +0000 - - remove not-yet-applied changelog entries - -commit bb27735fe689dac97ec0dc847ed8d3d519620109 -Author: twall -Date: Wed Jun 10 10:42:36 2009 +0000 - - add win64 support - -commit b2a54c100c74854a409820817d54617fdda39eb8 -Author: aph -Date: Mon Jun 8 16:50:49 2009 +0000 - - 2009-06-08 Andrew Haley - - * testsuite/libffi.call/err_bad_abi.c: Add xfails. - * testsuite/libffi.call/cls_longdouble_va.c: Add xfails. - * testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*. - * testsuite/libffi.call/err_bad_typedef.c: Add xfails. - - * testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args. - * testsuite/libffi.call/stret_medium.c: Likewise. - * testsuite/libffi.call/stret_large2.c: Likewise. - * testsuite/libffi.call/stret_large.c: Likewise. - -commit 25723e7141f73d3736d7244b980c89d97db852b6 -Author: aph -Date: Fri Jun 5 13:03:40 2009 +0000 - - 2009-06-05 Andrew Haley - - * src/x86/win32.S (_ffi_closure_STDCALL): Import from gcc. - -commit 70758199c7cd41f411987360ccb302b497a56dc9 -Author: aph -Date: Thu Jun 4 16:29:58 2009 +0000 - - 2009-06-04 Andrew Haley - - * src/powerpc/ffitarget.h: Fix misapplied merge from gcc. - -commit e8bb12563f9aa23ddf36fa6a5b92b16b5c3e1a7f -Author: aph -Date: Thu Jun 4 14:59:18 2009 +0000 - - 2009-06-04 Andrew Haley - - * src/mips/o32.S, - src/mips/n32.S: Fix licence formatting. - -commit d66a8e32c3671479e3ce0f6819673e5932ba6b7f -Author: aph -Date: Thu Jun 4 14:43:40 2009 +0000 - - 2009-06-04 Andrew Haley - - * src/x86/darwin.S: Fix licence formatting. - src/x86/win32.S: Likewise. - src/sh64/sysv.S: Likewise. - src/sh/sysv.S: Likewise. - -commit 7c3b7fd6b5db746b5b09a718f3044f811372f941 -Author: aph -Date: Thu Jun 4 14:39:20 2009 +0000 - - 2009-06-04 Andrew Haley - - * src/sh64/ffi.c: Remove lint directives. Was missing from merge - of Andreas Tobler's patch from 2006-04-22. - -commit 1a2f93a8b362db13638afd9fcb3f2650180bfa17 -Author: aph -Date: Thu Jun 4 10:45:51 2009 +0000 - - 2009-06-04 Andrew Haley - - * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of - 2007-03-07. - -commit 944c95cf7aaaaf7c5fa368cda4673dd38f45020e -Author: aph -Date: Wed Jun 3 17:42:56 2009 +0000 - - 2009-05-22 Dave Korn - - * src/x86/win32.S (_ffi_closure_STDCALL): New function. - (.eh_frame): Add FDE for it. - - 2009-05-22 Dave Korn - - * configure.ac: Also check if assembler supports pc-relative - relocs on X86_WIN32 targets. - * configure: Regenerate. - * src/x86/win32.S (ffi_prep_args): Declare extern, not global. - (_ffi_call_SYSV): Add missing function type symbol .def and - add EH markup labels. - (_ffi_call_STDCALL): Likewise. - (_ffi_closure_SYSV): Likewise. - (_ffi_closure_raw_SYSV): Likewise. - (.eh_frame): Add hand-crafted EH data. - - 2008-11-21 Eric Botcazou - - * src/sparc/ffi.c (ffi_prep_cif_machdep): Add support for - signed/unsigned int8/16 return values. - * src/sparc/v8.S (ffi_call_v8): Likewise. - (ffi_closure_v8): Likewise. - - 2008-03-26 Kaz Kojima - - * src/sh/sysv.S: Add .note.GNU-stack on Linux. - * src/sh64/sysv.S: Likewise. - - 2008-03-26 Daniel Jacobowitz - - * src/arm/sysv.S: Fix ARM comment marker. - -commit 00fa972430bb1535a4b34bf029ebcad500027b0c -Author: twall -Date: Sat Dec 27 16:59:05 2008 +0000 - - properly glob-match - -commit f5179e6794ac35af26fe86e468b8508a7a570c55 -Author: twall -Date: Fri Dec 26 19:06:28 2008 +0000 - - Mark XFAIL on longdouble tests for x86_64/mingw - -commit 80e2b5a749208c8a18f994ec5bee84594d051cc8 -Author: twall -Date: Mon Dec 22 15:21:15 2008 +0000 - - clean up tests for win64 use - -commit 7063d9996f742576095c7b0eb5016c0f9a670aec -Author: green -Date: Fri Dec 19 16:13:46 2008 +0000 - - Version 3.0.8 with x86-solaris support - -commit bdfeb13f0df0a63b19d62597517237b54d92228b -Author: green -Date: Fri Dec 19 15:47:44 2008 +0000 - - Bump to 3.0.7 - -commit 69205de17d6ac4c11d4ba92d6a5b40a0c5f246b2 -Author: green -Date: Thu Jul 24 18:03:48 2008 +0000 - - Many test fixes (failures due to excessive compiler warnings). - -commit 260d513fea00b3613fe957a44a157fe72c4ca29e -Author: green -Date: Thu Jul 17 13:13:52 2008 +0000 - - Version 3.0.6. sh/sh64 fixes. - -commit 3704031875feabb74e3655ed03cff4c2b3c76ac6 -Author: green -Date: Thu Apr 3 18:57:57 2008 +0000 - - Rev 3.0.5. - -commit 8406f5f48f7f58a1c982a93a95d521cf82b3241f -Author: green -Date: Thu Apr 3 18:57:34 2008 +0000 - - 3.0.5 - -commit 23a9e73212b62f9684cedb0ce70e92c59cfdaffa -Author: green -Date: Wed Mar 5 00:07:02 2008 +0000 - - 2008-03-04 Anthony Green - Blake Chaffin - hos@tamanegi.org - - * testsuite/libffi.call/cls_align_longdouble_split2.c - testsuite/libffi.call/cls_align_longdouble_split.c - testsuite/libffi.call/cls_dbls_struct.c - testsuite/libffi.call/cls_double_va.c - testsuite/libffi.call/cls_longdouble.c - testsuite/libffi.call/cls_longdouble_va.c - testsuite/libffi.call/cls_pointer.c - testsuite/libffi.call/cls_pointer_stack.c - testsuite/libffi.call/err_bad_abi.c - testsuite/libffi.call/err_bad_typedef.c - testsuite/libffi.call/huge_struct.c - testsuite/libffi.call/stret_large2.c - testsuite/libffi.call/stret_large.c - testsuite/libffi.call/stret_medium2.c - testsuite/libffi.call/stret_medium.c: New tests from Apple. - -commit 429e37d3ad653e52e75bf725c883ab79e859f89a -Author: green -Date: Thu Feb 28 04:50:19 2008 +0000 - - clicky - -commit 51e79c428348c033314f54bcb30f7e388c59e347 -Author: green -Date: Thu Feb 28 04:47:35 2008 +0000 - - getclicky - -commit affcab04e280efeace45a72c4dc6152c0e4f1b7f -Author: green -Date: Tue Feb 26 19:01:53 2008 +0000 - - 2008-02-26 Jakub Jelinek - Anthony Green - - * src/alpha/osf.S: Add .note.GNU-stack on Linux. - * src/s390/sysv.S: Likewise. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/linux64_closure.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. - * src/powerpc/sysv.S: Likewise. - * src/x86/unix64.S: Likewise. - * src/x86/sysv.S: Likewise. - * src/sparc/v8.S: Likewise. - * src/sparc/v9.S: Likewise. - * src/m68k/sysv.S: Likewise. - * src/ia64/unix.S: Likewise. - * src/arm/sysv.S: Likewise. - -commit 59689d5522c159a3ac967adb6b891cf5f22c890f -Author: green -Date: Tue Feb 26 17:40:51 2008 +0000 - - 2008-02-26 Anthony Green - Thomas Heller - - * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C - comment. - -commit b13c84cf4668828ff8429ba4a2f94cd1eb574ae0 -Author: green -Date: Tue Feb 26 17:38:15 2008 +0000 - - 2008-02-26 Anthony Green - Thomas Heller - - * include/ffi.h.in: Change void (*)() to void (*)(void). - -commit 265289f679ffd24a88ae1aa2cef0e4aa14703cd8 -Author: green -Date: Tue Feb 26 17:34:36 2008 +0000 - - 2008-02-26 Anthony Green - - * src/alpha/ffi.c: Change void (*)() to void (*)(void). - src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c, - src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c, - src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S, - src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c, - src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c, - src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S,> src/x86/ffi64.c: Ditto. - -commit fb5036cd6d0f909918e90f7d2d9fd80d46682d5d -Author: green -Date: Sun Feb 24 17:25:25 2008 +0000 - - fix date - -commit 40bec108e7d0181e6c9928aa7a33187bcc0f3d6f -Author: green -Date: Sun Feb 24 17:25:02 2008 +0000 - - New release - -commit b922048fa82ea109a4af269ee47bbc2a586bbac2 -Author: green -Date: Sun Feb 24 17:24:00 2008 +0000 - - 2008-02-24 Anthony Green - - * configure.ac: Accept openbsd*, not just openbsd. - Bump version to 3.0.4. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -commit affca4b92d06e5554784c7e9b233029ef83f7d8a -Author: green -Date: Fri Feb 22 21:53:29 2008 +0000 - - sync readme with web page. - -commit 3e53d8752ea74859b4c64fbbf935e62a937c4d78 -Author: green -Date: Fri Feb 22 21:52:38 2008 +0000 - - New release - -commit 4d92f6c8e78fe084be65f3e8b58b859901ba796d -Author: green -Date: Fri Feb 22 21:49:46 2008 +0000 - - 2008-02-22 Anthony Green - - * configure.ac: Bump version to 3.0.3. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. Clean up test docs. - -commit 0e185fa11a01f816824ba2687ed3715ab6219bef -Author: green -Date: Fri Feb 22 21:43:18 2008 +0000 - - Update configure script. - -commit f73986bd211cfbbaa593d1309504d0dc68626191 -Author: green -Date: Fri Feb 22 21:40:53 2008 +0000 - - 2008-02-22 Bjoern Koenig - Andreas Tobler - - * configure.ac: Add amd64-*-freebsd* target. - * configure: Regenerate. - -commit 0208f68fe5de30c33e7f70ebc281635917013f5a -Author: green -Date: Fri Feb 22 21:15:44 2008 +0000 - - 2008-02-22 Thomas Heller - - * configure.ac: Add x86 OpenBSD support. - * configure: Rebuilt. - -commit 01adb0e638a86cf0d5e668ed8e08be9b0cd2505f -Author: green -Date: Thu Feb 21 16:17:26 2008 +0000 - - Fix README. - -commit 1edd4563225981a14f7d4fb9919b1ed88e38082f -Author: green -Date: Thu Feb 21 13:39:01 2008 +0000 - - 3.0.2 - -commit c9b542800864e2204db6e83f3843a17813ba6165 -Author: green -Date: Thu Feb 21 13:36:43 2008 +0000 - - add missing file - -commit d5fa5633d5c8d3c212a2267cfa38fba4091baa2c -Author: green -Date: Thu Feb 21 13:36:19 2008 +0000 - - 2008-02-21 Anthony Green - - * configure.ac: Bump version to 3.0.2. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - - 2008-02-21 Björn König - - * src/x86/freebsd.S: New file. - * configure.ac: Add x86 FreeBSD support. - * Makefile.am: Ditto. - -commit ac35bfc6fcadd8880c1efce36724820f9074b318 -Author: green -Date: Sat Feb 16 01:03:56 2008 +0000 - - Updated - -commit f7942975fee7b0162647dd79e2652615b737e98e -Author: green -Date: Sat Feb 16 01:02:00 2008 +0000 - - 2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.1. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - - 2008-02-15 David Daney - - * src/mips/ffi.c: Remove extra '>' from include directive. - (ffi_prep_closure_loc): Use clear_location instead of tramp. - -commit 59aa6bb1bfc86a610ac1a8b123443efd75854dd1 -Author: green -Date: Fri Feb 15 20:52:26 2008 +0000 - - Add more platforms. - -commit 45a45ab99074448be0ae1a8d2ade50d28b60f8de -Author: green -Date: Fri Feb 15 19:16:36 2008 +0000 - - 3.0 notes - -commit 4db74cbea888c9f1251b85baf00d99b83d3b994d -Author: green -Date: Fri Feb 15 19:10:26 2008 +0000 - - Update - -commit c3e1101ffabf44d8a2ee46e03ba9ab582050a825 -Author: green -Date: Fri Feb 15 18:43:40 2008 +0000 - - 2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.0, - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - - 2008-02-15 David Daney - - * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): - Define (conditionally), and use it to include cachectl.h. - (ffi_prep_closure_loc): Fix cache flushing. - * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. - -commit 7e0cc12e9233ad285db41ce8dbdda61ed2a7fb06 -Author: green -Date: Fri Feb 15 15:51:03 2008 +0000 - - New release - -commit 2d7dc885ec40d53866f29984d595511942c8b686 -Author: green -Date: Fri Feb 15 15:30:26 2008 +0000 - - * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3: - Update dates and remove all references to ffi_prep_closure. - * configure.ac: Bump version to 2.99.9. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -commit a0525f03eeaaed33b1eac80e0c016455cee3615d -Author: green -Date: Fri Feb 15 15:14:30 2008 +0000 - - New release. - -commit 2b30dfb3146ee26ad956d00ee05eb835ca1a95b4 -Author: green -Date: Fri Feb 15 15:12:43 2008 +0000 - - * man/ffi_prep_closure.3: Delete. - * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3. - (man_MANS): Ditto. - * man/Makefile.in: Rebuilt. - * configure.ac: Bump version to 2.99.8. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -commit bf41e64840ebcb6cc31a6f028253c1fde82705d8 -Author: green -Date: Fri Feb 15 01:56:50 2008 +0000 - - Update. - -commit 4d39ddee677bbb61d621893b91e11eac5e7c4af7 -Author: green -Date: Fri Feb 15 01:24:06 2008 +0000 - - * configure.ac: Bump version to 2.99.7. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * include/ffi.h.in LICENSE src/debug.c src/closures.c - src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h - src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c - src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S - src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c - src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c - src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S - src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h - src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c - src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S - src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h - src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h - src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S - src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h - src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S - src/arm/ffitarget.h src/prep_cif.c: Update license text. - -commit d58b032b41a12bd3d72148da6822ab59dd698ff9 -Author: green -Date: Fri Feb 15 00:59:25 2008 +0000 - - New release - -commit 91e5478df6d5ac63efbb10f025807b4606afab56 -Author: green -Date: Fri Feb 15 00:50:30 2008 +0000 - - Update supported platforms. Bump version. - -commit bd0768f877c8f7fd0d36af2191b203d4d057b1ce -Author: green -Date: Fri Feb 15 00:45:33 2008 +0000 - - * configure.ac: Bump version to 2.99.5. - * configure: Rebuilt. - * Makefile.am (EXTRA_DIST): Add darwin64.S - * Makefile.in: Rebuilt. - * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree. - * LICENSE: Update WARRANTY. - -commit 49d345f767bd2cfee951bceaab6a1a07986cf293 -Author: green -Date: Thu Feb 14 23:43:27 2008 +0000 - - update license reference - -commit 12ac48fc79b515db7c9accd9fcaa87b0dcefccdb -Author: green -Date: Thu Feb 14 23:42:08 2008 +0000 - - Update WARRANTY - -commit 6b91c41da87e78552f2990dfc504a0a3349f340b -Author: green -Date: Thu Feb 14 23:38:27 2008 +0000 - - fix tarball reference - -commit 2b59579e3533334bee4788e076b4e520c2ab518c -Author: green -Date: Thu Feb 14 23:35:58 2008 +0000 - - First update in 5 years! - -commit 6cbdf3f3a3777a93382a2d508ddef1c353ff0955 -Author: green -Date: Thu Feb 14 22:44:06 2008 +0000 - - Fix .pc file bug and bump version - -commit 1d1dc81104b209df3cfef0840735c59efae2f655 -Author: green -Date: Thu Feb 14 22:03:37 2008 +0000 - - Add man files and info file. Update README. Tag as 2.99.3. - -commit f045a2367f793fa8b01534cf2e25bcc46afc8fa1 -Author: tromey -Date: Thu Feb 14 20:46:57 2008 +0000 - - Move entry from ChangeLog to ChangeLog.libffi - -commit 6257f07d1a9efd27fa83639cfba281f5d3188731 -Author: tromey -Date: Thu Feb 14 20:33:17 2008 +0000 - - * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt. - * mdate-sh, texinfo.tex: New files. - * Makefile.am (info_TEXINFOS): New variable. - * doc/libffi.texi: New file. - * doc/version.texi: Likewise. - -commit 4232af563c5509c3760a33e3684a2b958be755e1 -Author: green -Date: Thu Feb 14 16:19:21 2008 +0000 - - * Makefile.am (AM_CFLAGS): Don't compile with -D. - (lib_LTLIBRARIES): Define. - (toolexeclib_LIBRARIES): Undefine. - * Makefile.in: Rebuilt. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - -commit 961543615c31f092b578a4b4cda914db64f9d0fa -Author: green -Date: Thu Feb 14 15:57:40 2008 +0000 - - Fix typo. - -commit aeb0abab87222f637fbf352d4effd3b76b52ed26 -Author: green -Date: Thu Feb 14 15:54:27 2008 +0000 - - * libffi.pc.in: Usse @PACKAGE_NAME@ and @PACKAGE_VERSION@. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi. - * Makefile.in: Rebuilt. - * LICENSE: Update copyright notice. - -commit 77fe243556433eae119d8bd7469bfccdd5bd8a1a -Author: green -Date: Thu Feb 14 15:37:00 2008 +0000 - - Fix make dist again - -commit d4970cf4529459bf0f0e43c602cac396786c6802 -Author: green -Date: Thu Feb 14 15:18:56 2008 +0000 - - Fix make dist - -commit f0b1462f2d3024922ad71421bd5c4311fcb16da5 -Author: green -Date: Thu Feb 14 15:01:41 2008 +0000 - - Use pkgconfig. Increment libtool CURRENT version. - -commit 27e52f33baa069012a5adb2a3807f9ca1f2165ab -Author: green -Date: Sun Feb 3 13:59:48 2008 +0000 - - Fix header installs when using DESTDIR. - -commit fadab28eb6e33fb6dcdd7b9323e147142216d548 -Author: twall -Date: Sun Feb 3 12:32:22 2008 +0000 - - update changelog - -commit b5e44c8dfa92c87b99762c303cf5574a16db8f27 -Author: twall -Date: Sun Feb 3 01:12:32 2008 +0000 - - offset from code base address, not data base address - -commit f359848d1a995c0e44566d815f218729dc996e22 -Author: green -Date: Fri Feb 1 21:29:43 2008 +0000 - - Fix header installs. - -commit c30df49e157c7bfc8e19e3f8a72b9464fe225e54 -Author: green -Date: Fri Feb 1 21:13:55 2008 +0000 - - Revert my broken changes to twall's patch. - -commit 675561bb9aa0732c76698df10dd3007b5d0ec759 -Author: green -Date: Thu Jan 31 13:44:25 2008 +0000 - - Fix make dist . - -commit abc0bbf3813dc43e23d4c23e6fe794dbf287639b -Author: green -Date: Thu Jan 31 11:58:57 2008 +0000 - - Add Tim Wall's x86 windows patch. - -commit e332366d15a31198735b593ec8f7fc0558d783b8 -Author: green -Date: Wed Jan 30 13:21:02 2008 +0000 - - Add HJ's -fomit-frame-pointer struct return fix - -commit d4204240392af5b7750a08671b08e9c22dff5e93 -Author: green -Date: Wed Jan 30 12:42:34 2008 +0000 - - Clean up for new automake. - -commit f4932dd020df574637c9fb3fc1bb18e5a8f304cc -Author: green -Date: Wed Jan 30 12:40:25 2008 +0000 - - Fixes to run testsuite - -commit 085520ddc8db6a916bfc416b871fcb2d00074d40 -Author: green -Date: Tue Jan 29 15:16:43 2008 +0000 - - New files from gcc tree. - -commit 77175b3f7234e4875a4ef554ed1fe9fdc4133794 -Author: green -Date: Tue Jan 29 15:15:20 2008 +0000 - - Latest gcc svn sources - -commit 2544e45a0b2b634053df02da3a2ed9680eeed2a1 -Author: green -Date: Tue Jan 29 14:28:13 2008 +0000 - - Install ffitarget.h in $prefix/include. - -commit 6002211b1cc4daeb587d054b4f83968bda2c981e -Author: green -Date: Tue Jan 29 12:30:10 2008 +0000 - - Add new files. - -commit ccabd2b16be883cd03e5f0cd88ccfdd6ca39239d -Author: green -Date: Tue Jan 29 12:28:15 2008 +0000 - - Merge from gcc - -commit e680ecfbfca1da8d1823e48bc89b8375e66e128b -Author: tromey -Date: Sun Dec 24 23:12:15 2006 +0000 - - Pulled in libffi from gcc trunk. - Fixed build and install for standalone use. - -commit e7ba08965942ce872fdbc69f70f9848cc3d0bad6 -Author: root -Date: Sun Jun 4 23:22:24 2006 +0000 - - sourcware.org - -commit 0cd4aa24e21aaa964dfbdebc25ec5c8188049375 -Author: root -Date: Sun May 30 01:51:57 2004 +0000 - - Add LockDir - -commit 5826120fbd940d26cca76ed2522187505581e1ed -Author: green -Date: Tue Nov 4 06:09:08 2003 +0000 - - Add link to Gianni's web site. - -commit 220aa4b27db42d7ffaac5056000d5179f00d5ea3 -Author: jsm -Date: Tue Jan 21 08:07:42 2003 +0000 - - Newer, better, increased from before! (list of acceptable anon usernames) - -commit 1c3adc892cc1403dc4d3d7003a2385899836612e -Author: green -Date: Fri Dec 6 01:28:03 2002 +0000 - - Fixed Cygnus references. - -commit 4af66bb62fab9a8e318af3bf01e5486596a0c8d4 -Author: green -Date: Sun Oct 21 19:18:42 2001 +0000 - - Testsuite fixes. - -commit 5435965f9015ce40584c98d3816c3d05e7de1d21 -Author: green -Date: Mon Apr 23 00:32:03 2001 +0000 - - * include/ffi_common.h: Delete, after moving contents to... - * include/ffi_private.h: Subsume contents of ffi_common.h. - * include/Makefile.am (noinst_HEADERS): Remove ffi_common.h. - * include/Makefile.in: Rebuilt. - * arm/ffi.c, m68k/ffi.c, mips/ffi.c, powerpc/ffi.c, s390/ffi.c, - ia64/ffi.c: Include ffi_private.h, not ffi_common.h. - * alpha/ffi.c, sparc/ffi.c, x86/ffi.c: Don't include ffi_common.h. - * types.c, raw_api.c, java_raw_api.c, prep_cif.c: Don't include - ffi_common.h. - * debug.c: Include ffi_private.h instead of ffi_common.h. - - * mips/ffi.c (calc_n32_struct_flags): Make static. - (FIX_ARGP): Remove call to debugging routine ffi_stop_here. - - * mips/n32.S: Include ffi_private.h. - * mips/o32.S: Include ffi_private.h. - -commit 6fdb7de0fe3b7385e1fd78812ae69d9b3069d994 -Author: green -Date: Sun Apr 22 19:38:34 2001 +0000 - - * README: Update some comments. - - * Makefile.am (SUBDIRS): Add include so ffi.h gets installed. - * Makefile.in: Rebuilt. - - * include/ffi.h: Change ALPHA to __alpha__ and SPARC to __sparc__. - * types.c: Ditto. - * prep_cif.c (ffi_prep_cif): Ditto. - - * alpha/ffi.c, alpha/osf.S, sparc/ffi.c, sparc/v8.S, sparc/v9.S: - Include ffi_private.h. - - * include/ffi_private.h (FFI_TYPE_LAST): Define. - -commit bc7144b01b9707ef35f1a2e3e6996e005e82953a -Author: green -Date: Sun Apr 22 18:28:36 2001 +0000 - - Moved files from old home - -commit e57279831e20368c1aa1d2b35462b8629be73959 -Author: green -Date: Sun Apr 22 18:23:47 2001 +0000 - - These are dead. - -commit 7247436b5fe71767b29dc02b4da0fe18b08082e6 -Author: green -Date: Sun Apr 22 18:22:43 2001 +0000 - - All these files live somewhere else now. - -commit a8b0d40ff908e275028f676870c31d0d70274a98 -Author: green -Date: Sun Apr 22 18:17:14 2001 +0000 - - Many changes. Not quite there yet. - -commit f893d2273355710a290a26faebf5f12c3a34d0e3 -Author: green -Date: Sun Apr 22 18:13:22 2001 +0000 - - Moved m68k files - -commit 688ddfeced89cbb9d37b53005e1f7f2b9c78a8d7 -Author: green -Date: Sun Apr 22 18:12:33 2001 +0000 - - New, target indepentent, header - -commit f9e40776d488d5ecf43b3ae21444a1a2f6eca528 -Author: green -Date: Sun Apr 22 18:11:57 2001 +0000 - - Many changes. - -commit 8c1d2eb47f6bc314c431b75c85c107e8e43c4a76 -Author: green -Date: Sun Apr 22 18:10:47 2001 +0000 - - Many changes - -commit 1359dfc6582680a158b3caa3efb7a368da4aa12d -Author: green -Date: Sun Apr 22 18:10:20 2001 +0000 - - Moved ia64 files - -commit 6e2de5eee316a4579869aff50c7c5f6f478582d8 -Author: green -Date: Sun Apr 22 18:08:11 2001 +0000 - - Moved arm files - -commit 8807355af34cba8ffe87aee51152dfccec2771fa -Author: green -Date: Mon Apr 9 00:58:38 2001 +0000 - - Many many updates. Merge from gcc and then some. - -commit f7e9f91adec4ff1c2e7a13b3de81d2c5a3f55e7e -Author: green -Date: Mon Apr 17 03:32:37 2000 +0000 - - Mnay fixes. - -commit c4860de618f4956283f5c8230a2544e403dfe390 -Author: green -Date: Mon Apr 17 03:18:46 2000 +0000 - - Merge from libgcj. Merged patches from net. See ChangeLog for details. - -commit c578b58314990c3853429297c38ba14015fec5fa -Author: jsm -Date: Sat Oct 9 20:18:16 1999 +0000 - - 1999-10-09 Jason Molenda (jsm@bugshack.cygnus.com) - - * CVSROOT/auto_checkout, CVSROOT/commit_prep, CVSROOT/log_accum: - Deleted; generic versions now used for all repositories. - - * CVSROOT/commitinfo, CVSROOT/loginfo: Change pathnames to - generic versions. - - * CVSROOT/checkoutlist: Don't try to check out the removed - files any longer. - -commit acdb20051207fed7652dd9f122f65de5458c474c -Author: jsm -Date: Sat Oct 9 20:18:15 1999 +0000 - - 1999-10-09 Jason Molenda (jsm@bugshack.cygnus.com) - - * CVSROOT/auto_checkout, CVSROOT/commit_prep, CVSROOT/log_accum: - Deleted; generic versions now used for all repositories. - - * CVSROOT/commitinfo, CVSROOT/loginfo: Change pathnames to - generic versions. - - * CVSROOT/checkoutlist: Don't try to check out the removed - files any longer. - -commit e75be655ceedf7ab24c4e99d75eec9efeb979bc7 -Author: green -Date: Sun Aug 8 13:16:41 1999 +0000 - - New configury - -commit d6669a0dd5b266005325bbf6d5a8ff34574d809e -Author: green -Date: Sun Aug 8 13:05:12 1999 +0000 - - * include/ffi.h.in: Try to work around messy header problem - with PACKAGE and VERSION. - - * configure: Rebuilt. - * configure.in: Change version to 2.00-beta. - - * fficonfig.h.in: Rebuilt. - * acconfig.h (FFI_NO_STRUCTS, FFI_NO_RAW_API): Define. - - * src/x86/ffi.c (ffi_raw_call): Rename. - -commit 4819d52b007934a40d6d29a75ee30e857c4a93ae -Author: green -Date: Wed Aug 4 18:02:34 1999 +0000 - - New file for Kresten's closure work - -commit 2dbf801eb427cbf5021a9e1e512b5fc523524700 -Author: green -Date: Wed Aug 4 18:00:05 1999 +0000 - - Kresten's closure work. Initial checkin. - -commit d170961701b0f2bf7e824d7caba2ebe10002ed84 -Author: green -Date: Thu Jul 8 14:36:52 1999 +0000 - - * configure.in: Add x86 and powerpc BeOS configurations. - From Makoto Kato . - -commit c7747d976924ec6f2229cbcfbbdb98d364e10de9 -Author: jsm -Date: Wed May 12 23:32:16 1999 +0000 - - 1999-05-12 Jason Molenda (jsm@bugshack.cygnus.com) - * index.html: Add links to libffi* mail list archives. - -commit dd2aa9a8de22e26df3bbc85d068358641f6202f7 -Author: green -Date: Thu May 6 05:34:36 1999 +0000 - - * configure.in: Add warning about this being beta code. - Remove src/Makefile.am from the picture. - * configure: Rebuilt. - * Makefile.am: Move logic from src/Makefile.am. Add changes - to support libffi as a target library. - * Makefile.in: Rebuilt. - * aclocal.m4, config.guess, config.sub, ltconfig, ltmain.sh: - Upgraded to new autoconf, automake, libtool. - * README: Tweaks. - * LICENSE: Update copyright date. - * src/Makefile.am, src/Makefile.in: Removed. - -commit 4e9452abed58a3058ccdb446f96a29d50dda1f34 -Author: green -Date: Wed May 5 22:06:13 1999 +0000 - - Updated to new automake, libtool, autoconf - nothing works :-) - -commit 6d3b2bddaf4967fba8b8656c01bfc77ec0f2800c -Author: jsm -Date: Mon Apr 26 15:55:28 1999 +0000 - - 1999-04-26 Jason Molenda (jsm@bugshack.cygnus.com) - * index.html: Missed a reference to libffi-discuss@cygnus.com. Fixed. - -commit ebc6a9c28af831d3d187af8ff17319f0f309bd98 -Author: jsm -Date: Mon Apr 26 15:53:29 1999 +0000 - - 1999-04-26 Jason Molenda (jsm@bugshack.cygnus.com) - * index.html: Change links to ftp directory to point to sourceware - directory. - Change mailing list subscription forms to point to sourceware lists. - -commit 78ffc52a8b257061348c576ccb6fbbf8b48b0fff -Author: jsm -Date: Sun Apr 18 01:33:21 1999 +0000 - - Standard sourceware setup. - -commit b4d77e827d7ebef7e57ebcd71e71c15c62f1e0a8 -Author: jsm -Date: Mon Nov 30 11:11:25 1998 +0000 - - Small typeo. (I wouldn't bother except that it made the sentence hard - for me to parse on a casual read.) - -commit bfb73f08fdc987e37070c5fb0b196fbd28872888 -Author: jsm -Date: Mon Nov 30 10:44:55 1998 +0000 - - A few cleanups. Most notably, point to the correct subscribe cgi-bin - script. - -commit af8b7f037ccee3b7939ee226a1a2bbc2f057b35c -Author: green -Date: Mon Nov 30 06:20:05 1998 +0000 - - * index.html: Reformatted and updated to reflect hosting on - sourceware.cygnus.com (new mailing lists, etc). - -commit 334f0b060942aff8d26badaf7dde7830450dc5da -Author: green -Date: Sun Nov 29 16:56:12 1998 +0000 - - initial snapshot of documentation - -commit 3ab5cb4a1dcc7ecd7e773c97582b0099976c4753 -Author: green -Date: Sun Nov 29 16:56:10 1998 +0000 - - Initial revision - -commit d2a9eb5a8b7cbc8b769809cad59c82b975c178e2 -Merge: d3782ec bc75c54 -Author: green -Date: Sun Nov 29 16:48:16 1998 +0000 - - This commit was generated by cvs2svn to compensate for changes in r7, which - included commits to RCS files with non-trunk default branches. - -commit bc75c54bd311658005b065f1bf201b204c81cbca -Author: green -Date: Sun Nov 29 16:48:16 1998 +0000 - - Import of v1 code. - -commit d3782ec8160c644421dcea17b605fec6e328f14e -Author: jsm -Date: Fri Nov 20 20:18:00 1998 +0000 - - Send commit messages to mailing lists. - -commit 8d8d3843c484c2bb70d8375b2b799f75eb03f709 -Author: jsm -Date: Thu Oct 1 22:08:36 1998 +0000 - - initial checkin - -commit 49634f3bf221cc1939abafc788f7e4e31293fe73 -Author: jsm -Date: Thu Oct 1 22:08:35 1998 +0000 - - Add standard setup. - -commit c64a84c7693f8cd400fb94bba3c9bcfd9ad1fc36 -Author: jsm -Date: Thu Oct 1 22:08:34 1998 +0000 - - Add readers and standard modules file. - -commit 9813273b07fd082da573b3b6bfb8d23809b59eea -Author: jsm -Date: Thu Oct 1 22:08:33 1998 +0000 - - initial checkin diff --git a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi b/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi deleted file mode 100644 index 49ba8dad3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi +++ /dev/null @@ -1,584 +0,0 @@ -2011-02-08 Andreas Tobler - - * testsuite/lib/libffi.exp: Tweak for stand-alone mode. - -2009-12-25 Samuli Suominen - - * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64. - * configure: Rebuilt. - * fficonfig.h.in: Rebuilt. - -2009-06-16 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs. - * testsuite/libffi.call/float2.c: Fix dg-excess-errors. - * testsuite/libffi.call/ffitest.h, - testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. - -2009-06-12 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - testsuite/libffi.special/unwindtest.cc: include stdint.h. - -2009-06-11 Timothy Wall - - * Makefile.am, - configure.ac, - include/ffi.h.in, - include/ffi_common.h, - src/closures.c, - src/dlmalloc.c, - src/x86/ffi.c, - src/x86/ffitarget.h, - src/x86/win64.S (new), - README: Added win64 support (mingw or MSVC) - * Makefile.in, - include/Makefile.in, - man/Makefile.in, - testsuite/Makefile.in, - configure, - aclocal.m4: Regenerated - * ltcf-c.sh: properly escape cygwin/w32 path - * man/ffi_call.3: Clarify size requirements for return value. - * src/x86/ffi64.c: Fix filename in comment. - * src/x86/win32.S: Remove unused extern. - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_12byte.c, - testsuite/libffi.call/cls_16byte.c, - testsuite/libffi.call/cls_18byte.c, - testsuite/libffi.call/cls_19byte.c, - testsuite/libffi.call/cls_1_1byte.c, - testsuite/libffi.call/cls_20byte.c, - testsuite/libffi.call/cls_20byte1.c, - testsuite/libffi.call/cls_24byte.c, - testsuite/libffi.call/cls_2byte.c, - testsuite/libffi.call/cls_3_1byte.c, - testsuite/libffi.call/cls_3byte1.c, - testsuite/libffi.call/cls_3byte2.c, - testsuite/libffi.call/cls_4_1byte.c, - testsuite/libffi.call/cls_4byte.c, - testsuite/libffi.call/cls_5_1_byte.c, - testsuite/libffi.call/cls_5byte.c, - testsuite/libffi.call/cls_64byte.c, - testsuite/libffi.call/cls_6_1_byte.c, - testsuite/libffi.call/cls_6byte.c, - testsuite/libffi.call/cls_7_1_byte.c, - testsuite/libffi.call/cls_7byte.c, - testsuite/libffi.call/cls_8byte.c, - testsuite/libffi.call/cls_9byte1.c, - testsuite/libffi.call/cls_9byte2.c, - testsuite/libffi.call/cls_align_double.c, - testsuite/libffi.call/cls_align_float.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_align_sint16.c, - testsuite/libffi.call/cls_align_sint32.c, - testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint16.c, - testsuite/libffi.call/cls_align_uint32.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_float.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_multi_schar.c, - testsuite/libffi.call/cls_multi_sshort.c, - testsuite/libffi.call/cls_multi_sshortchar.c, - testsuite/libffi.call/cls_multi_uchar.c, - testsuite/libffi.call/cls_multi_ushort.c, - testsuite/libffi.call/cls_multi_ushortchar.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/cls_schar.c, - testsuite/libffi.call/cls_sint.c, - testsuite/libffi.call/cls_sshort.c, - testsuite/libffi.call/cls_uchar.c, - testsuite/libffi.call/cls_uint.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/cls_ushort.c, - testsuite/libffi.call/err_bad_abi.c, - testsuite/libffi.call/err_bad_typedef.c, - testsuite/libffi.call/float2.c, - testsuite/libffi.call/huge_struct.c, - testsuite/libffi.call/nested_struct.c, - testsuite/libffi.call/nested_struct1.c, - testsuite/libffi.call/nested_struct10.c, - testsuite/libffi.call/nested_struct2.c, - testsuite/libffi.call/nested_struct3.c, - testsuite/libffi.call/nested_struct4.c, - testsuite/libffi.call/nested_struct5.c, - testsuite/libffi.call/nested_struct6.c, - testsuite/libffi.call/nested_struct7.c, - testsuite/libffi.call/nested_struct8.c, - testsuite/libffi.call/nested_struct9.c, - testsuite/libffi.call/problem1.c, - testsuite/libffi.call/return_ldl.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_large.c, - testsuite/libffi.call/stret_large2.c, - testsuite/libffi.call/stret_medium.c, - testsuite/libffi.call/stret_medium2.c, - testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead - of checking for MMAP. Use intptr_t instead of long casts. - -2009-06-04 Andrew Haley - - * src/powerpc/ffitarget.h: Fix misapplied merge from gcc. - -2009-06-04 Andrew Haley - - * src/mips/o32.S, - src/mips/n32.S: Fix licence formatting. - -2009-06-04 Andrew Haley - - * src/x86/darwin.S: Fix licence formatting. - src/x86/win32.S: Likewise. - src/sh64/sysv.S: Likewise. - src/sh/sysv.S: Likewise. - -2009-06-04 Andrew Haley - - * src/sh64/ffi.c: Remove lint directives. Was missing from merge - of Andreas Tobler's patch from 2006-04-22. - -2009-06-04 Andrew Haley - - * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of - 2007-03-07. - -2008-12-26 Timothy Wall - - * testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected - failures on x86_64 cygwin/mingw. - -2008-12-22 Timothy Wall - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_loc_fn0.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c: use portable cast from - pointer to integer (intptr_t). - * testsuite/libffi.call/cls_longdouble.c: disable for win64. - -2008-12-19 Anthony Green - - * configure.ac: Bump version to 3.0.8. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-11-11 Anthony Green - - * configure.ac: Bump version to 3.0.7. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-08-25 Andreas Tobler - - * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and - FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. - Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. - Adjust copyright notice. - * src/powerpc/ffi.c: Add two new flags to indicate if we have one - register or two register to use for FFI_SYSV structs. - (ffi_prep_cif_machdep): Pass the right register flag introduced above. - (ffi_closure_helper_SYSV): Fix the return type for - FFI_SYSV_TYPE_SMALL_STRUCT. Comment. - Adjust copyright notice. - -2008-07-24 Anthony Green - - * testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/err_bad_abi.c: Clean up failures from - compiler warnings. - -2008-07-17 Anthony Green - - * configure.ac: Bump version to 3.0.6. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. Add documentation. - * README: Update for new release. - -2008-07-16 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned - int. - -2008-07-16 Kaz Kojima - - * src/sh/sysv.S: Add .note.GNU-stack on Linux. - * src/sh64/sysv.S: Likewise. - -2008-04-03 Anthony Green - - * libffi.pc.in (Libs): Add -L${libdir}. - * configure.ac: Bump version to 3.0.5. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-04-03 Anthony Green - Xerces Ranby - - * include/ffi.h.in: Wrap definition of target architecture to - protect from double definitions. - -2008-03-22 Moriyoshi Koizumi - - * src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in - closure_loc_fn0.c. - * testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0): - New test. - -2008-03-04 Anthony Green - Blake Chaffin - hos@tamanegi.org - - * testsuite/libffi.call/cls_align_longdouble_split2.c - testsuite/libffi.call/cls_align_longdouble_split.c - testsuite/libffi.call/cls_dbls_struct.c - testsuite/libffi.call/cls_double_va.c - testsuite/libffi.call/cls_longdouble.c - testsuite/libffi.call/cls_longdouble_va.c - testsuite/libffi.call/cls_pointer.c - testsuite/libffi.call/cls_pointer_stack.c - testsuite/libffi.call/err_bad_abi.c - testsuite/libffi.call/err_bad_typedef.c - testsuite/libffi.call/huge_struct.c - testsuite/libffi.call/stret_large2.c - testsuite/libffi.call/stret_large.c - testsuite/libffi.call/stret_medium2.c - testsuite/libffi.call/stret_medium.c: New tests from Apple. - -2008-02-26 Jakub Jelinek - Anthony Green - - * src/alpha/osf.S: Add .note.GNU-stack on Linux. - * src/s390/sysv.S: Likewise. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/linux64_closure.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. - * src/powerpc/sysv.S: Likewise. - * src/x86/unix64.S: Likewise. - * src/x86/sysv.S: Likewise. - * src/sparc/v8.S: Likewise. - * src/sparc/v9.S: Likewise. - * src/m68k/sysv.S: Likewise. - * src/ia64/unix.S: Likewise. - * src/arm/sysv.S: Likewise. - -2008-02-26 Anthony Green - Thomas Heller - - * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C - comment. - -2008-02-26 Anthony Green - Thomas Heller - - * include/ffi.h.in: Change void (*)() to void (*)(void). - -2008-02-26 Anthony Green - Thomas Heller - - * src/alpha/ffi.c: Change void (*)() to void (*)(void). - src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c, - src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c, - src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S, - src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c, - src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c, - src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S, - src/x86/ffi64.c: Ditto. - -2008-02-24 Anthony Green - - * configure.ac: Accept openbsd*, not just openbsd. - Bump version to 3.0.4. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-22 Anthony Green - - * README: Clean up list of tested platforms. - -2008-02-22 Anthony Green - - * configure.ac: Bump version to 3.0.3. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. Clean up test docs. - -2008-02-22 Bjoern Koenig - Andreas Tobler - - * configure.ac: Add amd64-*-freebsd* target. - * configure: Regenerate. - -2008-02-22 Thomas Heller - - * configure.ac: Add x86 OpenBSD support. - * configure: Rebuilt. - -2008-02-21 Thomas Heller - - * README: Change "make test" to "make check". - -2008-02-21 Anthony Green - - * configure.ac: Bump version to 3.0.2. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-21 Björn König - - * src/x86/freebsd.S: New file. - * configure.ac: Add x86 FreeBSD support. - * Makefile.am: Ditto. - -2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.1. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-15 David Daney - - * src/mips/ffi.c: Remove extra '>' from include directive. - (ffi_prep_closure_loc): Use clear_location instead of tramp. - -2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.0. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-15 David Daney - - * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): - Define (conditionally), and use it to include cachectl.h. - (ffi_prep_closure_loc): Fix cache flushing. - * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. - -2008-02-15 Anthony Green - - * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3: - Update dates and remove all references to ffi_prep_closure. - * configure.ac: Bump version to 2.99.9. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-15 Anthony Green - - * man/ffi_prep_closure.3: Delete. - * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3. - (man_MANS): Ditto. - * man/Makefile.in: Rebuilt. - * configure.ac: Bump version to 2.99.8. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-14 Anthony Green - - * configure.ac: Bump version to 2.99.7. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * include/ffi.h.in LICENSE src/debug.c src/closures.c - src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h - src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c - src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S - src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c - src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c - src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S - src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h - src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c - src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S - src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h - src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h - src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S - src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h - src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S - src/arm/ffitarget.h src/prep_cif.c: Update license text. - -2008-02-14 Anthony Green - - * README: Update tested platforms. - * configure.ac: Bump version to 2.99.6. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * configure.ac: Bump version to 2.99.5. - * configure: Rebuilt. - * Makefile.am (EXTRA_DIST): Add darwin64.S - * Makefile.in: Rebuilt. - * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree. - * LICENSE: Update WARRANTY. - -2008-02-14 Anthony Green - - * libffi.pc.in (libdir): Fix libdir definition. - * configure.ac: Bump version to 2.99.4. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * README: Update. - * libffi.info: New file. - * doc/stamp-vti: New file. - * configure.ac: Bump version to 2.99.3. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * Makefile.am (SUBDIRS): Add man dir. - * Makefile.in: Rebuilt. - * configure.ac: Create Makefile. - * configure: Rebuilt. - * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3 - man/Makefile.am man/Makefile.in: New files. - -2008-02-14 Tom Tromey - - * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt. - * mdate-sh, texinfo.tex: New files. - * Makefile.am (info_TEXINFOS): New variable. - * doc/libffi.texi: New file. - * doc/version.texi: Likewise. - -2008-02-14 Anthony Green - - * Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET). - (lib_LTLIBRARIES): Define. - (toolexeclib_LIBRARIES): Undefine. - * Makefile.in: Rebuilt. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - -2008-02-14 Anthony Green - - * libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi. - * Makefile.in: Rebuilt. - * LICENSE: Update copyright notice. - -2008-02-14 Anthony Green - - * include/Makefile.am (nodist_includes_HEADERS): Define. Don't - distribute ffitarget.h or ffi.h from the build include dir. - * Makefile.in: Rebuilt. - -2008-02-14 Anthony Green - - * include/Makefile.am (includesdir): Install headers under libdir. - (pkgconfigdir): Define. Install libffi.pc. - * include/Makefile.in: Rebuilt. - * libffi.pc.in: Create. - * libtool-version: Increment CURRENT - * configure.ac: Add libffi.pc.in - * configure: Rebuilt. - -2008-02-03 Anthony Green - - * include/Makefile.am (includesdir): Fix header install with - DESTDIR. - * include/Makefile.in: Rebuilt. - -2008-02-03 Timothy Wall - - * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return - offset based on code pointer, not data pointer. - -2008-02-01 Anthony Green - - * include/Makefile.am: Fix header installs. - * Makefile.am: Ditto. - * include/Makefile.in: Rebuilt. - * Makefile.in: Ditto. - -2008-02-01 Anthony Green - - * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL, - FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last - patch. - -2008-01-31 Anthony Green - - * Makefile.am (EXTRA_DIST): Add missing files. - * testsuite/Makefile.am: Ditto. - * Makefile.in, testsuite/Makefile.in: Rebuilt. - -2008-01-31 Timothy Wall - - * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall - closures. - * src/x86/ffitarget.h: Increase size of trampoline for stdcall - closures. - * src/x86/win32.S: Add assembly for stdcall closure. - * src/x86/ffi.c: Initialize stdcall closure trampoline. - -2008-01-30 H.J. Lu - - PR libffi/34612 - * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when - returning struct. - - * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" - tests. - -2008-01-30 Anthony Green - - * Makefile.am, include/Makefile.am: Move headers to - libffi_la_SOURCES for new automake. - * Makefile.in, include/Makefile.in: Rebuilt. - - * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for - execution outside of gcc tree. - * testsuite/lib/target-libpath.exp: Ditto. - - * testsuite/lib/libffi-dg.exp: Many changes to allow for execution - outside of gcc tree. - diff --git a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi-3.1 b/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi-3.1 deleted file mode 100644 index 8f7f50d6f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libffi-3.1 +++ /dev/null @@ -1,6000 +0,0 @@ -2014-03-16 Josh Triplett - - * ChangeLog: Archive to ChangeLog.libffi-3.1 and delete. Future - changelogs will come from git, with autogenerated snapshots shipped in - distributed tarballs. - -2014-03-16 Josh Triplett - - Add support for stdcall, thiscall, and fastcall on non-Windows - x86-32. - - Linux supports the stdcall calling convention, either via - functions explicitly declared with the stdcall attribute, or via - code compiled with -mrtd which effectively makes stdcall the - default. - - This introduces FFI_STDCALL, FFI_THISCALL, and FFI_FASTCALL on - non-Windows x86-32 platforms, as non-default calling conventions. - - * Makefile.am: Compile in src/x86/win32.S on non-Windows x86-32. - * src/x86/ffitarget.h: Add FFI_STDCALL, FFI_THISCALL, and - FFI_FASTCALL on non-Windows x86-32. Increase trampoline size to - accomodate these calling conventions, and unify some ifdeffery. - * src/x86/ffi.c: Add support for FFI_STDCALL, FFI_THISCALL, and - FFI_FASTCALL on non-Windows x86-32 platforms; update ifdeffery. - * src/x86/win32.S: Support compiling on non-Windows x86-32 - platforms. On those platforms, avoid redefining the SYSV symbols - already provided by src/x86/sysv.S. - * testsuite/libffi.call/closure_stdcall.c: Run on non-Windows. - #define __stdcall if needed. - * testsuite/libffi.call/closure_thiscall.c: Run on non-Windows. - #define __fastcall if needed. - * testsuite/libffi.call/fastthis1_win32.c: Run on non-Windows. - * testsuite/libffi.call/fastthis2_win32.c: Ditto. - * testsuite/libffi.call/fastthis3_win32.c: Ditto. - * testsuite/libffi.call/many2_win32.c: Ditto. - * testsuite/libffi.call/many_win32.c: Ditto. - * testsuite/libffi.call/strlen2_win32.c: Ditto. - * testsuite/libffi.call/strlen_win32.c: Ditto. - * testsuite/libffi.call/struct1_win32.c: Ditto. - * testsuite/libffi.call/struct2_win32.c: Ditto. - -2014-03-16 Josh Triplett - - * prep_cif.c: Remove unnecessary ifdef for X86_WIN32. - ffi_prep_cif_core had a special case for X86_WIN32, checking for - FFI_THISCALL in addition to the FFI_FIRST_ABI-to-FFI_LAST_ABI - range before returning FFI_BAD_ABI. However, on X86_WIN32, - FFI_THISCALL already falls in that range, making the special case - unnecessary. Remove it. - -2014-03-16 Josh Triplett - - * testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/closure_thiscall.c: Remove fragile stack - pointer checks. These files included inline assembly to save the - stack pointer before and after the call, and compare the values. - However, compilers can and do leave the stack in different states - for these two pieces of inline assembly, such as by saving a - temporary value on the stack across the call; observed with gcc - -Os, and verified as spurious through careful inspection of - disassembly. - -2014-03-16 Josh Triplett - - * testsuite/libffi.call/many.c: Avoid spurious failure due to - excess floating-point precision. - * testsuite/libffi.call/many_win32.c: Ditto. - -2014-03-16 Josh Triplett - - * libtool-ldflags: Re-add. - -2014-03-16 Josh Triplett - - * Makefile.in, aclocal.m4, compile, config.guess, config.sub, - configure, depcomp, include/Makefile.in, install-sh, - libtool-ldflags, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, - m4/ltsugar.m4, m4/ltversion.m4, m4/lt~obsolete.m4, - man/Makefile.in, mdate-sh, missing, testsuite/Makefile.in: Delete - autogenerated files from version control. - * .gitignore: Add autogenerated files. - * autogen.sh: New script to generate the autogenerated files. - * README: Document requirement to run autogen.sh when building - directly from version control. - * .travis.yml: Run autogen.sh - -2014-03-14 Anthony Green - - * configure, Makefile.in: Rebuilt. - -2014-03-10 Mike Hommey - - * configure.ac: Allow building for mipsel with Android NDK r8. - * Makefile.am (AM_MAKEFLAGS): Replace double quotes with single - quotes. - -2014-03-10 Landry Breuil - - * configure.ac: Ensure the linker supports @unwind sections in libffi. - -2014-03-01 Anthony Green - - * Makefile.am (EXTRA_DIST): Replace old scripts with - generate-darwin-source-and-headers.py. - * Makefile.in: Rebuilt. - -2014-02-28 Anthony Green - - * Makefile.am (AM_CFLAGS): Reintroduce missing -DFFI_DEBUG for - --enable-debug builds. - * Makefile.in: Rebuilt. - -2014-02-28 Makoto Kato - - * src/closures.c: Fix build failure when using clang for Android. - -2014-02-28 Marcin Wojdyr - - * libffi.pc.in (toolexeclibdir): use -L${toolexeclibdir} instead - of -L${libdir}. - -2014-02-28 Paulo Pizarro - - * src/bfin/sysv.S: Calling functions in shared libraries requires - considering the GOT. - -2014-02-28 Josh Triplett - - * src/x86/ffi64.c (classify_argument): Handle case where - FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE. - -2014-02-28 Anthony Green - - * ltmain.sh: Generate with libtool-2.4.2.418. - * m4/libtool.m4, m4/ltoptions.m4, m4/ltversion.m4: Ditto. - * configure: Rebuilt. - -2014-02-28 Dominik Vogt - - * configure.ac (AC_ARG_ENABLE struct): Fix typo in help - message. - (AC_ARG_ENABLE raw_api): Ditto. - * configure, fficonfig.h.in: Rebuilt. - -2014-02-28 Will Newton - - * src/arm/sysv.S: Initialize IP register with FP. - -2014-02-28 Yufeng Zhang - - * src/aarch64/sysv.S (ffi_closure_SYSV): Use x29 as the - main CFA reg; update cfi_rel_offset. - -2014-02-15 Marcus Comstedt - - * src/powerpc/ffi_linux64.c, src/powerpc/linux64_closure.S: Remove - assumption on contents of r11 in closure. - -2014-02-09 Heiher - - * src/mips/n32.S: Fix call floating point va function. - -2014-01-21 Zachary Waldowski - - * src/aarch64/ffi.c: Fix missing semicolons on assertions under - debug mode. - -2013-12-30 Zachary Waldowski - - * .gitignore: Exclude darwin_* generated source and build_* trees. - * src/aarch64/ffi.c, src/arm/ffi.c, src/x86/ffi.c: Inhibit Clang - previous prototype warnings. - * src/arm/ffi.c: Prevent NULL dereference, fix short type warning - * src/dlmalloc.c: Fix warnings from set_segment_flags return type, - and the native use of size_t for malloc on platforms - * src/arm/sysv.S: Use unified syntax. Clang clean-ups for - ARM_FUNC_START. - * generate-osx-source-and-headers.py: Remove. - * build-ios.sh: Remove. - * libffi.xcodeproj/project.pbxproj: Rebuild targets. Include - x86_64+aarch64 pieces in library. Export headers properly. - * src/x86/ffi64.c: More Clang warning clean-ups. - * src/closures.c (open_temp_exec_file_dir): Use size_t. - * src/prep_cif.c (ffi_prep_cif_core): Cast ALIGN result. - * src/aarch64/sysv.S: Use CNAME for global symbols. Only use - .size for ELF targets. - * src/aarch64/ffi.c: Clean up for double == long double. Clean up - from Clang warnings. Use Clang cache invalidation builtin. Use - size_t in place of unsigned in many places. Accommodate for - differences in Apple AArch64 ABI. - -2013-12-02 Daniel Rodríguez Troitiño - - * generate-darwin-source-and-headers.py: Clean up, modernize, - merged version of previous scripts. - -2013-11-21 Anthony Green - - * configure, Makefile.in, include/Makefile.in, include/ffi.h.in, - man/Makefile.in, testsuite/Makefile.in, fficonfig.h.in: Rebuilt. - -2013-11-21 Alan Modra - - * Makefile.am (EXTRA_DIST): Add new src/powerpc files. - (nodist_libffi_la_SOURCES ): Likewise. - * configure.ac (HAVE_LONG_DOUBLE_VARIANT): Define for powerpc. - * include/ffi.h.in (ffi_prep_types): Declare. - * src/prep_cif.c (ffi_prep_cif_core): Call ffi_prep_types. - * src/types.c (FFI_NONCONST_TYPEDEF): Define and use for - HAVE_LONG_DOUBLE_VARIANT. - * src/powerpc/ffi_powerpc.h: New file. - * src/powerpc/ffi.c: Split into.. - * src/powerpc/ffi_sysv.c: ..new file, and.. - * src/powerpc/ffi_linux64.c: ..new file, rewriting parts. - * src/powerpc/ffitarget.h (enum ffi_abi): Rewrite powerpc ABI - selection as bits controlling features. - * src/powerpc/linux64.S: For consistency, use POWERPC64 rather - than __powerpc64__. - * src/powerpc/linux64_closure.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. Move .note.FNU-stack - inside guard. - * src/powerpc/sysv.S: Likewise. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * Makefile.in: Regenerate. - -2013-11-20 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use - NUM_FPR_ARG_REGISTERS64 and NUM_GPR_ARG_REGISTERS64 not their - 32-bit versions for 64-bit code. - * src/powerpc/linux64_closure.S: Don't use the return value area - as a parameter save area on ELFv2. - -2013-11-18 Iain Sandoe - - * src/powerpc/darwin.S (EH): Correct use of pcrel FDE encoding. - * src/powerpc/darwin_closure.S (EH): Likewise. Modernise picbase - labels. - -2013-11-18 Anthony Green - - * src/arm/ffi.c (ffi_call): Hoist declaration of temp to top of - function. - * src/arm/ffi.c (ffi_closure_inner): Moderize function declaration - to appease compiler. - Thanks for Gregory P. Smith . - -2013-11-18 Anthony Green - - * README (tested): Mention PowerPC ELFv2. - -2013-11-16 Alan Modra - - * src/powerpc/ppc_closure.S: Move errant #endif to where it belongs. - Don't bl .Luint128. - -2013-11-16 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use #if _CALL_ELF - test to select parameter save sizing for ELFv2 vs. ELFv1. - * src/powerpc/ffitarget.h (FFI_V2_TYPE_FLOAT_HOMOG, - FFI_V2_TYPE_DOUBLE_HOMOG, FFI_V2_TYPE_SMALL_STRUCT): Define. - (FFI_TRAMPOLINE_SIZE): Define variant for ELFv2. - * src/powerpc/ffi.c (FLAG_ARG_NEEDS_PSAVE): Define. - (discover_homogeneous_aggregate): New function. - (ffi_prep_args64): Adjust start of param save area for ELFv2. - Handle homogenous floating point struct parms. - (ffi_prep_cif_machdep_core): Adjust space calculation for ELFv2. - Handle ELFv2 return values. Set FLAG_ARG_NEEDS_PSAVE. Handle - homogenous floating point structs. - (ffi_call): Increase size of smst_buffer for ELFv2. Handle ELFv2. - (flush_icache): Compile for ELFv2. - (ffi_prep_closure_loc): Set up ELFv2 trampoline. - (ffi_closure_helper_LINUX64): Don't return all structs directly - to caller. Handle homogenous floating point structs. Handle - ELFv2 struct return values. - * src/powerpc/linux64.S (ffi_call_LINUX64): Set up r2 for - ELFv2. Adjust toc save location. Call function pointer using - r12. Handle FLAG_RETURNS_SMST. Don't predict branches. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Set up r2 - for ELFv2. Define ELFv2 versions of STACKFRAME, PARMSAVE, and - RETVAL. Handle possibly missing parameter save area. Handle - ELFv2 return values. - (.note.GNU-stack): Move inside outer #ifdef. - -2013-11-16 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_cif_machdep): Revert 2013-02-08 - change. Do not consume an int arg when returning a small struct - for FFI_SYSV ABI. - (ffi_call): Only use bounce buffer when FLAG_RETURNS_SMST. - Properly copy bounce buffer to destination. - * src/powerpc/sysv.S: Revert 2013-02-08 change. - * src/powerpc/ppc_closure.S: Remove stray '+'. - -2013-11-16 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_args64): Align struct parameters - according to __STRUCT_PARM_ALIGN__. - (ffi_prep_cif_machdep_core): Likewise. - (ffi_closure_helper_LINUX64): Likewise. - -2013-11-16 Alan Modra - - * src/powerpc/linux64.S (ffi_call_LINUX64): Tweak restore of r28. - (.note.GNU-stack): Move inside outer #ifdef. - * src/powerpc/linux64_closure.S (STACKFRAME, PARMSAVE, - RETVAL): Define and use throughout. - (ffi_closure_LINUX64): Save fprs before buying stack. - (.note.GNU-stack): Move inside outer #ifdef. - -2013-11-16 Alan Modra - - * src/powerpc/ffitarget.h (FFI_TARGET_SPECIFIC_VARIADIC): Define. - (FFI_EXTRA_CIF_FIELDS): Define. - * src/powerpc/ffi.c (ffi_prep_args64): Save fprs as per the - ABI, not to both fpr and param save area. - (ffi_prep_cif_machdep_core): Renamed from ffi_prep_cif_machdep. - Keep initial flags. Formatting. Remove dead FFI_LINUX_SOFT_FLOAT - code. - (ffi_prep_cif_machdep, ffi_prep_cif_machdep_var): New functions. - (ffi_closure_helper_LINUX64): Pass floating point as per ABI, - not to both fpr and parameter save areas. - - * libffi/testsuite/libffi.call/cls_double_va.c (main): Correct - function cast and don't call ffi_prep_cif. - * libffi/testsuite/libffi.call/cls_longdouble_va.c (main): Likewise. - -2013-11-15 Andrew Haley - - * doc/libffi.texi (Closure Example): Fix the sample code. - * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. - -2013-11-15 Andrew Haley - - * testsuite/libffi.call/va_struct1.c (main): Fix broken test. - * testsuite/libffi.call/cls_uint_va.c (cls_ret_T_fn): Likewise - * testsuite/libffi.call/cls_struct_va1.c (test_fn): Likewise. - * testsuite/libffi.call/va_1.c (main): Likewise. - -2013-11-14 David Schneider - - * src/arm/ffi.c: Fix register allocation for mixed float and - doubles. - * testsuite/libffi.call/cls_many_mixed_float_double.c: Testcase - for many mixed float and double arguments. - -2013-11-13 Alan Modra - - * doc/libffi.texi (Simple Example): Correct example code. - * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. - -2013-11-13 Anthony Green - - * include/ffi_common.h: Respect HAVE_ALLOCA_H for GNU compiler - based build. (Thanks to tmr111116 on github) - -2013-11-09 Anthony Green - - * m4/libtool.m4: Refresh. - * configure, Makefile.in: Rebuilt. - * README: Add more notes about next release. - -2013-11-09 Shigeharu TAKENO - - * m4/ax_gcc_archflag.m4 (ax_gcc_arch): Don't recognize - UltraSPARC-IIi as ultrasparc3. - -2013-11-06 Mark Kettenis - - * src/x86/freebsd.S (ffi_call_SYSV): Align the stack pointer to - 16-bytes. - -2013-11-06 Konstantin Belousov - - * src/x86/freebsd.S (ffi_closure_raw_SYSV): Mark the assembler - source as not requiring executable stack. - -2013-11-02 Anthony Green - - * doc/libffi.texi (The Basics): Clarify return value buffer size - requirements. Also, NULL result buffer pointers are no longer - supported. - * doc/libffi.info: Rebuilt. - -2013-11-02 Mischa Jonker - - * Makefile.am (nodist_libffi_la_SOURCES): Fix build error. - * Makefile.in: Rebuilt. - -2013-11-02 David Schneider - - * src/arm/ffi.c: more robust argument handling for closures on arm hardfloat - * testsuite/libffi.call/many_mixed.c: New file. - * testsuite/libffi.call/cls_many_mixed_args.c: More tests. - -2013-11-02 Vitaly Budovski - - * src/x86/ffi.c (ffi_prep_cif_machdep): Don't align stack for win32. - -2013-10-23 Mark H Weaver - - * src/mips/ffi.c: Fix handling of uint32_t arguments on the - MIPS N32 ABI. - -2013-10-13 Sandra Loosemore - - * README: Add Nios II to table of supported platforms. - * Makefile.am (EXTRA_DIST): Add nios2 files. - (nodist_libffi_la_SOURCES): Likewise. - * Makefile.in: Regenerated. - * configure.ac (nios2*-linux*): New host. - (NIOS2): Add AM_CONDITIONAL. - * configure: Regenerated. - * src/nios2/ffi.c: New. - * src/nios2/ffitarget.h: New. - * src/nios2/sysv.S: New. - * src/prep_cif.c (initialize_aggregate): Handle extra structure - alignment via FFI_AGGREGATE_ALIGNMENT. - (ffi_prep_cif_core): Conditionalize structure return for NIOS2. - -2013-10-10 Sandra Loosemore - - * testsuite/libffi.call/cls_many_mixed_args.c (cls_ret_double_fn): - Fix uninitialized variable. - -2013-10-11 Marcus Shawcroft - - * testsuite/libffi.call/many.c (many): Replace * with +. - -2013-10-08 Ondřej Bílka - - * src/aarch64/ffi.c, src/aarch64/sysv.S, src/arm/ffi.c, - src/arm/gentramp.sh, src/bfin/sysv.S, src/closures.c, - src/dlmalloc.c, src/ia64/ffi.c, src/microblaze/ffi.c, - src/microblaze/sysv.S, src/powerpc/darwin_closure.S, - src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/sh/ffi.c, - src/tile/tile.S, testsuite/libffi.call/nested_struct11.c: Fix - spelling errors. - -2013-10-08 Anthony Green - - * aclocal.m4, compile, config.guess, config.sub, depcomp, - install-sh, mdate-sh, missing, texinfo.tex: Update from upstream. - * configure.ac: Update version to 3.0.14-rc0. - * Makefile.in, configure, Makefile.in, include/Makefile.in, - man/Makefile.in, testsuite/Makefile.in: Rebuilt. - * README: Mention M88K and VAX. - -2013-07-15 Miod Vallat - - * Makefile.am, - configure.ac, - src/m88k/ffi.c, - src/m88k/ffitarget.h, - src/m88k/obsd.S, - src/vax/elfbsd.S, - src/vax/ffi.c, - src/vax/ffitarget.h: Add m88k and vax support. - -2013-06-24 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Move var declaration - before statements. - (ffi_prep_args64): Support little-endian. - (ffi_closure_helper_SYSV, ffi_closure_helper_LINUX64): Likewise. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Likewise. - * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Likewise. - -2013-06-12 Mischa Jonker - - * configure.ac: Add support for ARC. - * Makefile.am: Likewise. - * README: Add ARC details. - * src/arc/arcompact.S: New. - * src/arc/ffi.c: Likewise. - * src/arc/ffitarget.h: Likewise. - -2013-03-28 David Schneider - - * src/arm/ffi.c: Fix support for ARM hard-float calling convention. - * src/arm/sysv.S: call different methods for SYSV and VFP ABIs. - * testsuite/libffi.call/cls_many_mixed_args.c: testcase for a closure with - mixed arguments, many doubles. - * testsuite/libffi.call/many_double.c: testcase for calling a function using - more than 8 doubles. - * testcase/libffi.call/many.c: use absolute value to check result against an - epsilon - -2013-03-17 Anthony Green - - * README: Update for 3.0.13. - * configure.ac: Ditto. - * configure: Rebuilt. - * doc/*: Update version. - -2013-03-17 Dave Korn - - * src/closures.c (is_emutramp_enabled - [!FFI_MMAP_EXEC_EMUTRAMP_PAX]): Move default definition outside - enclosing #if scope. - -2013-03-17 Anthony Green - - * configure.ac: Only modify toolexecdir in certain cases. - * configure: Rebuilt. - -2013-03-16 Gilles Talis - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Don't use - fparg_count,etc on __NO_FPRS__ targets. - -2013-03-16 Alan Hourihane - - * src/m68k/sysv.S (epilogue): Don't use extb instruction on - m680000 machines. - -2013-03-16 Alex Gaynor - - * src/x86/ffi.c (ffi_prep_cif_machdep): Always align stack. - -2013-03-13 Markos Chandras - - * configure.ac: Add support for Imagination Technologies Meta. - * Makefile.am: Likewise. - * README: Add Imagination Technologies Meta details. - * src/metag/ffi.c: New. - * src/metag/ffitarget.h: Likewise. - * src/metag/sysv.S: Likewise. - -2013-02-24 Andreas Schwab - - * doc/libffi.texi (Structures): Fix missing category argument of - @deftp. - -2013-02-11 Anthony Green - - * configure.ac: Update release number to 3.0.12. - * configure: Rebuilt. - * README: Update release info. - -2013-02-10 Anthony Green - - * README: Add Moxie. - * src/moxie/ffi.c: Created. - * src/moxie/eabi.S: Created. - * src/moxie/ffitarget.h: Created. - * Makefile.am (nodist_libffi_la_SOURCES): Add Moxie. - * Makefile.in: Rebuilt. - * configure.ac: Add Moxie. - * configure: Rebuilt. - * testsuite/libffi.call/huge_struct.c: Disable format string - warnings for moxie*-*-elf tests. - -2013-02-10 Anthony Green - - * Makefile.am (LTLDFLAGS): Fix reference. - * Makefile.in: Rebuilt. - -2013-02-10 Anthony Green - - * README: Update supported platforms. Update test results link. - -2013-02-09 Anthony Green - - * testsuite/libffi.call/negint.c: Remove forced -O2. - * testsuite/libffi.call/many2.c (foo): Remove GCCism. - * testsuite/libffi.call/ffitest.h: Add default PRIuPTR definition. - - * src/sparc/v8.S (ffi_closure_v8): Import ancient ulonglong - closure return type fix developed by Martin v. Löwis for cpython - fork. - -2013-02-08 Andreas Tobler - - * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix small struct - support. - * src/powerpc/sysv.S: Ditto. - -2013-02-08 Anthony Green - - * testsuite/libffi.call/cls_longdouble.c: Remove xfail for - arm*-*-*. - -2013-02-08 Anthony Green - - * src/sparc/ffi.c (ffi_prep_closure_loc): Fix cache flushing for GCC. - -2013-02-08 Matthias Klose - - * man/ffi_prep_cif.3: Clean up for debian linter. - -2013-02-08 Peter Bergner - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Account for FP args pushed - on the stack. - -2013-02-08 Anthony Green - - * Makefile.am (EXTRA_DIST): Add missing files. - * testsuite/Makefile.am (EXTRA_DIST): Ditto. - * Makefile.in: Rebuilt. - -2013-02-08 Anthony Green - - * configure.ac: Move sparc asm config checks to within functions - for compatibility with sun tools. - * configure: Rebuilt. - * src/sparc/ffi.c (ffi_prep_closure_loc): Flush cache on v9 - systems. - * src/sparc/v8.S (ffi_flush_icache): Implement a sparc v9 cache - flusher. - -2013-02-08 Nathan Rossi - - * src/microblaze/ffi.c (ffi_closure_call_SYSV): Fix handling of - small big-endian structures. - (ffi_prep_args): Ditto. - -2013-02-07 Anthony Green - - * src/sparc/v8.S (ffi_call_v8): Fix typo from last patch - (effectively hiding ffi_call_v8). - -2013-02-07 Anthony Green - - * configure.ac: Update bug reporting address. - * configure.in: Rebuild. - - * src/sparc/v8.S (ffi_flush_icache): Out-of-line cache flusher for - Sun compiler. - * src/sparc/ffi.c (ffi_call): Remove warning. - Call ffi_flush_icache for non-GCC builds. - (ffi_prep_closure_loc): Use ffi_flush_icache. - - * Makefile.am (EXTRA_DIST): Add libtool-ldflags. - * Makefile.in: Rebuilt. - * libtool-ldflags: New file. - -2013-02-07 Daniel Schepler - - * configure.ac: Correctly identify x32 systems as 64-bit. - * m4/libtool.m4: Remove libtool expr error. - * aclocal.m4, configure: Rebuilt. - -2013-02-07 Anthony Green - - * configure.ac: Fix GCC usage test. - * configure: Rebuilt. - * README: Mention LLVM/GCC x86_64 issue. - * testsuite/Makefile.in: Rebuilt. - -2013-02-07 Anthony Green - - * testsuite/libffi.call/cls_double_va.c (main): Replace // style - comments with /* */ for xlc compiler. - * testsuite/libffi.call/stret_large.c (main): Ditto. - * testsuite/libffi.call/stret_large2.c (main): Ditto. - * testsuite/libffi.call/nested_struct1.c (main): Ditto. - * testsuite/libffi.call/huge_struct.c (main): Ditto. - * testsuite/libffi.call/float_va.c (main): Ditto. - * testsuite/libffi.call/cls_struct_va1.c (main): Ditto. - * testsuite/libffi.call/cls_pointer_stack.c (main): Ditto. - * testsuite/libffi.call/cls_pointer.c (main): Ditto. - * testsuite/libffi.call/cls_longdouble_va.c (main): Ditto. - -2013-02-06 Anthony Green - - * man/ffi_prep_cif.3: Clean up for debian lintian checker. - -2013-02-06 Anthony Green - - * Makefile.am (pkgconfigdir): Add missing pkgconfig install bits. - * Makefile.in: Rebuild. - -2013-02-02 Mark H Weaver - - * src/x86/ffi64.c (ffi_call): Sign-extend integer arguments passed - via general purpose registers. - -2013-01-21 Nathan Rossi - - * README: Add MicroBlaze details. - * Makefile.am: Add MicroBlaze support. - * configure.ac: Likewise. - * src/microblaze/ffi.c: New. - * src/microblaze/ffitarget.h: Likewise. - * src/microblaze/sysv.S: Likewise. - -2013-01-21 Nathan Rossi - * testsuite/libffi.call/return_uc.c: Fixed issue. - -2013-01-21 Chris Zankel - - * README: Add Xtensa support. - * Makefile.am: Likewise. - * configure.ac: Likewise. - * Makefile.in Regenerate. - * configure: Likewise. - * src/prep_cif.c: Handle Xtensa. - * src/xtensa: New directory. - * src/xtensa/ffi.c: New file. - * src/xtensa/ffitarget.h: Ditto. - * src/xtensa/sysv.S: Ditto. - -2013-01-11 Anthony Green - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Replace // style - comments with /* */ for xlc compiler. - * src/powerpc/aix.S (ffi_call_AIX): Ditto. - * testsuite/libffi.call/ffitest.h (allocate_mmap): Delete - deprecated inline function. - * testsuite/libffi.special/ffitestcxx.h: Ditto. - * README: Add update for AIX support. - -2013-01-11 Anthony Green - - * configure.ac: Robustify pc relative reloc check. - * m4/ax_cc_maxopt.m4: Don't -malign-double. This is an ABI - changing option for 32-bit x86. - * aclocal.m4, configure: Rebuilt. - * README: Update supported target list. - -2013-01-10 Anthony Green - - * README (tested): Add Compiler column to table. - -2013-01-10 Anthony Green - - * src/x86/ffi64.c (struct register_args): Make sse array and array - of unions for sunpro compiler compatibility. - -2013-01-10 Anthony Green - - * configure.ac: Test target platform size_t size. Handle both 32 - and 64-bit builds for x86_64-* and i?86-* targets (allowing for - CFLAG option to change default settings). - * configure, aclocal.m4: Rebuilt. - -2013-01-10 Anthony Green - - * testsuite/libffi.special/special.exp: Only run exception - handling tests when using GNU compiler. - - * m4/ax_compiler_vendor.m4: New file. - * configure.ac: Test for compiler vendor and don't use - AX_CFLAGS_WARN_ALL with the sun compiler. - * aclocal.m4, configure: Rebuilt. - -2013-01-10 Anthony Green - - * include/ffi_common.h: Don't use GCCisms to define types when - building with the SUNPRO compiler. - -2013-01-10 Anthony Green - - * configure.ac: Put local.exp in the right place. - * configure: Rebuilt. - - * src/x86/ffi.c: Update comment about regparm function attributes. - * src/x86/sysv.S (ffi_closure_SYSV): The SUNPRO compiler requires - that all function arguments be passed on the stack (no regparm - support). - -2013-01-08 Anthony Green - - * configure.ac: Generate local.exp. This sets CC_FOR_TARGET - when we are using the vendor compiler. - * testsuite/Makefile.am (EXTRA_DEJAGNU_SITE_CONFIG): Point to - ../local.exp. - * configure, testsuite/Makefile.in: Rebuilt. - - * testsuite/libffi.call/call.exp: Run tests with different - options, depending on whether or not we are using gcc or the - vendor compiler. - * testsuite/lib/libffi.exp (libffi-init): Set using_gcc based on - whether or not we are building/testing with gcc. - -2013-01-08 Anthony Green - - * configure.ac: Switch x86 solaris target to X86 by default. - * configure: Rebuilt. - -2013-01-08 Anthony Green - - * configure.ac: Fix test for read-only eh_frame. - * configure: Rebuilt. - -2013-01-08 Anthony Green - - * src/x86/sysv.S, src/x86/unix64.S: Only emit DWARF unwind info - when building with the GNU toolchain. - * testsuite/libffi.call/ffitest.h (CHECK): Fix for Solaris vendor - compiler. - -2013-01-07 Thorsten Glaser - - * testsuite/libffi.call/cls_uchar_va.c, - testsuite/libffi.call/cls_ushort_va.c, - testsuite/libffi.call/va_1.c: Testsuite fixes. - -2013-01-07 Thorsten Glaser - - * src/m68k/ffi.c (CIF_FLAGS_SINT8, CIF_FLAGS_SINT16): Define. - (ffi_prep_cif_machdep): Fix 8-bit and 16-bit signed calls. - * src/m68k/sysv.S (ffi_call_SYSV, ffi_closure_SYSV): Ditto. - -2013-01-04 Anthony Green - - * Makefile.am (AM_CFLAGS): Don't automatically add -fexceptions - and -Wall. This is set in the configure script after testing for - GCC. - * Makefile.in: Rebuilt. - -2013-01-02 rofl0r - - * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix build error on ppc - when long double == double. - -2013-01-02 Reini Urban - - * Makefile.am (libffi_la_LDFLAGS): Add -no-undefined to LDFLAGS - (required for shared libs on cygwin/mingw). - * Makefile.in: Rebuilt. - -2012-10-31 Alan Modra - - * src/powerpc/linux64_closure.S: Add new ABI support. - * src/powerpc/linux64.S: Likewise. - -2012-10-30 Magnus Granberg - Pavel Labushev - - * configure.ac: New options pax_emutramp - * configure, fficonfig.h.in: Regenerated - * src/closures.c: New function emutramp_enabled_check() and - checks. - -2012-10-30 Frederick Cheung - - * configure.ac: Enable FFI_MAP_EXEC_WRIT for Darwin 12 (mountain - lion) and future version. - * configure: Rebuild. - -2012-10-30 James Greenhalgh - Marcus Shawcroft - - * README: Add details of aarch64 port. - * src/aarch64/ffi.c: New. - * src/aarch64/ffitarget.h: Likewise. - * src/aarch64/sysv.S: Likewise. - * Makefile.am: Support aarch64. - * configure.ac: Support aarch64. - * Makefile.in, configure: Rebuilt. - -2012-10-30 James Greenhalgh - Marcus Shawcroft - - * testsuite/lib/libffi.exp: Add support for aarch64. - * testsuite/libffi.call/cls_struct_va1.c: New. - * testsuite/libffi.call/cls_uchar_va.c: Likewise. - * testsuite/libffi.call/cls_uint_va.c: Likewise. - * testsuite/libffi.call/cls_ulong_va.c: Likewise. - * testsuite/libffi.call/cls_ushort_va.c: Likewise. - * testsuite/libffi.call/nested_struct11.c: Likewise. - * testsuite/libffi.call/uninitialized.c: Likewise. - * testsuite/libffi.call/va_1.c: Likewise. - * testsuite/libffi.call/va_struct1.c: Likewise. - * testsuite/libffi.call/va_struct2.c: Likewise. - * testsuite/libffi.call/va_struct3.c: Likewise. - -2012-10-12 Walter Lee - - * Makefile.am: Add TILE-Gx/TILEPro support. - * configure.ac: Likewise. - * Makefile.in: Regenerate. - * configure: Likewise. - * src/prep_cif.c (ffi_prep_cif_core): Handle TILE-Gx/TILEPro. - * src/tile: New directory. - * src/tile/ffi.c: New file. - * src/tile/ffitarget.h: Ditto. - * src/tile/tile.S: Ditto. - -2012-10-12 Matthias Klose - - * generate-osx-source-and-headers.py: Normalize whitespace. - -2012-09-14 David Edelsohn - - * configure: Regenerated. - -2012-08-26 Andrew Pinski - - PR libffi/53014 - * src/mips/ffi.c (ffi_prep_closure_loc): Allow n32 with soft-float and n64 with - soft-float. - -2012-08-08 Uros Bizjak - - * src/s390/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, - just return FFI_BAD_ABI when things are wrong. - -2012-07-18 H.J. Lu - - PR libffi/53982 - PR libffi/53973 - * src/x86/ffitarget.h: Check __ILP32__ instead of __LP64__ for x32. - (FFI_SIZEOF_JAVA_RAW): Defined to 4 for x32. - -2012-05-16 H.J. Lu - - * configure: Regenerated. - -2012-05-05 Nicolas Lelong - - * libffi.xcodeproj/project.pbxproj: Fixes. - * README: Update for iOS builds. - -2012-04-23 Alexandre Keunecke I. de Mendonca - - * configure.ac: Add Blackfin/sysv support - * Makefile.am: Add Blackfin/sysv support - * src/bfin/ffi.c: Add Blackfin/sysv support - * src/bfin/ffitarget.h: Add Blackfin/sysv support - -2012-04-11 Anthony Green - - * Makefile.am (EXTRA_DIST): Add new script. - * Makefile.in: Rebuilt. - -2012-04-11 Zachary Waldowski - - * generate-ios-source-and-headers.py, - libffi.xcodeproj/project.pbxproj: Support a Mac static library via - Xcode. Set iOS compatibility to 4.0. Move iOS trampoline - generation into an Xcode "run script" phase. Include both as - Xcode build scripts. Don't always regenerate config files. - -2012-04-10 Anthony Green - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Add missing semicolon. - -2012-04-06 Anthony Green - - * Makefile.am (EXTRA_DIST): Add new iOS/xcode files. - * Makefile.in: Rebuilt. - -2012-04-06 Mike Lewis - - * generate-ios-source-and-headers.py: New file. - * libffi.xcodeproj/project.pbxproj: New file. - * README: Update instructions on building iOS binary. - * build-ios.sh: Delete. - -2012-04-06 Anthony Green - - * src/x86/ffi64.c (UINT128): Define differently for Intel and GNU - compilers, then use it. - -2012-04-06 H.J. Lu - - * m4/libtool.m4 (_LT_ENABLE_LOCK): Support x32. - -2012-04-06 Anthony Green - - * testsuite/Makefile.am (EXTRA_DIST): Add missing test cases. - * testsuite/Makefile.in: Rebuilt. - -2012-04-05 Zachary Waldowski - - * include/ffi.h.in: Add missing trampoline table fields. - * src/arm/sysv.S: Fix ENTRY definition, and wrap symbol references - in CNAME. - * src/x86/ffi.c: Wrap Windows specific code in ifdefs. - -2012-04-02 Peter Bergner - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Declare double_tmp. - Silence casting pointer to integer of different size warning. - Delete goto to previously deleted label. - (ffi_call): Silence possibly undefined warning. - (ffi_closure_helper_SYSV): Declare variable type. - -2012-04-02 Peter Rosin - - * src/x86/win32.S (ffi_call_win32): Sign/zero extend the return - value in the Intel version as is already done for the AT&T version. - (ffi_closure_SYSV): Likewise. - (ffi_closure_raw_SYSV): Likewise. - (ffi_closure_STDCALL): Likewise. - -2012-03-29 Peter Rosin - - * src/x86/win32.S (ffi_closure_raw_THISCALL): Unify the frame - generation, fix the ENDP label and remove the surplus third arg - from the 'lea' insn. - -2012-03-29 Peter Rosin - - * src/x86/win32.S (ffi_closure_raw_SYSV): Make the 'stubraw' label - visible outside the PROC, so that ffi_closure_raw_THISCALL can see - it. Also instruct the assembler to add a frame to the function. - -2012-03-23 Peter Rosin - - * Makefile.am (AM_CPPFLAGS): Add -DFFI_BUILDING. - * Makefile.in: Rebuilt. - * include/ffi.h.in [MSVC]: Add __declspec(dllimport) decorations - to all data exports, when compiling libffi clients using MSVC. - -2012-03-29 Peter Rosin - - * src/x86/ffitarget.h (ffi_abi): Add new ABI FFI_MS_CDECL and - make it the default for MSVC. - (FFI_TYPE_MS_STRUCT): New structure return convention. - * src/x86/ffi.c (ffi_prep_cif_machdep): Tweak the structure - return convention for FFI_MS_CDECL to be FFI_TYPE_MS_STRUCT - instead of an ordinary FFI_TYPE_STRUCT. - (ffi_prep_args): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. - (ffi_call): Likewise. - (ffi_prep_incoming_args_SYSV): Likewise. - (ffi_raw_call): Likewise. - (ffi_prep_closure_loc): Treat FFI_MS_CDECL as FFI_SYSV. - * src/x86/win32.S (ffi_closure_SYSV): For FFI_TYPE_MS_STRUCT, - return a pointer to the result structure in eax and don't pop - that pointer from the stack, the caller takes care of it. - (ffi_call_win32): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. - (ffi_closure_raw_SYSV): Likewise. - -2012-03-22 Peter Rosin - - * testsuite/libffi.call/closure_stdcall.c [MSVC]: Add inline - assembly version with Intel syntax. - * testsuite/libffi.call/closure_thiscall.c [MSVC]: Likewise. - -2012-03-23 Peter Rosin - - * testsuite/libffi.call/ffitest.h: Provide abstration of - __attribute__((fastcall)) in the form of a __FASTCALL__ - define. Define it to __fastcall for MSVC. - * testsuite/libffi.call/fastthis1_win32.c: Use the above. - * testsuite/libffi.call/fastthis2_win32.c: Likewise. - * testsuite/libffi.call/fastthis3_win32.c: Likewise. - * testsuite/libffi.call/strlen2_win32.c: Likewise. - * testsuite/libffi.call/struct1_win32.c: Likewise. - * testsuite/libffi.call/struct2_win32.c: Likewise. - -2012-03-22 Peter Rosin - - * src/x86/win32.S [MSVC] (ffi_closure_THISCALL): Remove the manual - frame on function entry, MASM adds one automatically. - -2012-03-22 Peter Rosin - - * testsuite/libffi.call/ffitest.h [MSVC]: Add kludge for missing - bits in the MSVC headers. - -2012-03-22 Peter Rosin - - * testsuite/libffi.call/cls_12byte.c: Adjust to the C89 style - with no declarations after statements. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_18byte.c: Likewise. - * testsuite/libffi.call/cls_19byte.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_20byte1.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_5_1_byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - * testsuite/libffi.call/cls_64byte.c: Likewise. - * testsuite/libffi.call/cls_6_1_byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7_1_byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_9byte1.c: Likewise. - * testsuite/libffi.call/cls_9byte2.c: Likewise. - * testsuite/libffi.call/cls_align_double.c: Likewise. - * testsuite/libffi.call/cls_align_float.c: Likewise. - * testsuite/libffi.call/cls_align_longdouble.c: Likewise. - * testsuite/libffi.call/cls_align_longdouble_split.c: Likewise. - * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. - * testsuite/libffi.call/cls_align_pointer.c: Likewise. - * testsuite/libffi.call/cls_align_sint16.c: Likewise. - * testsuite/libffi.call/cls_align_sint32.c: Likewise. - * testsuite/libffi.call/cls_align_sint64.c: Likewise. - * testsuite/libffi.call/cls_align_uint16.c: Likewise. - * testsuite/libffi.call/cls_align_uint32.c: Likewise. - * testsuite/libffi.call/cls_align_uint64.c: Likewise. - * testsuite/libffi.call/cls_dbls_struct.c: Likewise. - * testsuite/libffi.call/cls_pointer_stack.c: Likewise. - * testsuite/libffi.call/err_bad_typedef.c: Likewise. - * testsuite/libffi.call/huge_struct.c: Likewise. - * testsuite/libffi.call/nested_struct.c: Likewise. - * testsuite/libffi.call/nested_struct1.c: Likewise. - * testsuite/libffi.call/nested_struct10.c: Likewise. - * testsuite/libffi.call/nested_struct2.c: Likewise. - * testsuite/libffi.call/nested_struct3.c: Likewise. - * testsuite/libffi.call/nested_struct4.c: Likewise. - * testsuite/libffi.call/nested_struct5.c: Likewise. - * testsuite/libffi.call/nested_struct6.c: Likewise. - * testsuite/libffi.call/nested_struct7.c: Likewise. - * testsuite/libffi.call/nested_struct8.c: Likewise. - * testsuite/libffi.call/nested_struct9.c: Likewise. - * testsuite/libffi.call/stret_large.c: Likewise. - * testsuite/libffi.call/stret_large2.c: Likewise. - * testsuite/libffi.call/stret_medium.c: Likewise. - * testsuite/libffi.call/stret_medium2.c: Likewise. - * testsuite/libffi.call/struct1.c: Likewise. - * testsuite/libffi.call/struct1_win32.c: Likewise. - * testsuite/libffi.call/struct2.c: Likewise. - * testsuite/libffi.call/struct2_win32.c: Likewise. - * testsuite/libffi.call/struct3.c: Likewise. - * testsuite/libffi.call/struct4.c: Likewise. - * testsuite/libffi.call/struct5.c: Likewise. - * testsuite/libffi.call/struct6.c: Likewise. - * testsuite/libffi.call/struct7.c: Likewise. - * testsuite/libffi.call/struct8.c: Likewise. - * testsuite/libffi.call/struct9.c: Likewise. - * testsuite/libffi.call/testclosure.c: Likewise. - -2012-03-21 Peter Rosin - - * testsuite/libffi.call/float_va.c (float_va_fn): Use %f when - printing doubles (%lf is for long doubles). - (main): Likewise. - -2012-03-21 Peter Rosin - - * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] - (set_ld_library_path_env_vars): Add the library search dir to PATH - (and save PATH for later). - (restore_ld_library_path_env_vars): Restore PATH. - -2012-03-21 Peter Rosin - - * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] - (set_ld_library_path_env_vars): Add the library search dir to PATH - (and save PATH for later). - (restore_ld_library_path_env_vars): Restore PATH. - -2012-03-20 Peter Rosin - - * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. - * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label - visible outside the PROC, so that ffi_closure_THISCALL can see it. - -2012-03-20 Peter Rosin - - * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. - * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label - visible outside the PROC, so that ffi_closure_THISCALL can see it. - -2012-03-19 Alan Hourihane - - * src/m68k/ffi.c: Add MINT support. - * src/m68k/sysv.S: Ditto. - -2012-03-06 Chung-Lin Tang - - * src/arm/ffi.c (ffi_call): Add __ARM_EABI__ guard around call to - ffi_call_VFP(). - (ffi_prep_closure_loc): Add __ARM_EABI__ guard around use of - ffi_closure_VFP. - * src/arm/sysv.S: Add __ARM_EABI__ guard around VFP code. - -2012-03-19 chennam - - * src/powerpc/ffi_darwin.c (ffi_prep_closure_loc): Fix AIX closure - support. - -2012-03-13 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, - just return FFI_BAD_ABI when things are wrong. - * src/sh64/ffi.c (ffi_prep_closure_loc): Ditto. - -2012-03-09 David Edelsohn - - * src/powerpc/aix_closure.S (ffi_closure_ASM): Adjust for Darwin64 - change to return value of ffi_closure_helper_DARWIN and load type - from return type. - -2012-03-03 H.J. Lu - - * src/x86/ffi64.c (ffi_call): Cast the return value to unsigned - long. - (ffi_prep_closure_loc): Cast to 64bit address in trampoline. - (ffi_closure_unix64_inner): Cast return pointer to unsigned long - first. - - * src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32. - (ffi_arg): Set to unsigned long long for x32. - (ffi_sarg): Set to long long for x32. - -2012-03-03 H.J. Lu - - * src/prep_cif.c (ffi_prep_cif_core): Properly check bad ABI. - -2012-03-03 Andoni Morales Alastruey - - * configure.ac: Add -no-undefined for both 32- and 64-bit x86 - windows-like hosts. - * configure: Rebuilt. - -2012-02-27 Mikael Pettersson - - PR libffi/52223 - * Makefile.am (FLAGS_TO_PASS): Define. - * Makefile.in: Regenerate. - -2012-02-23 Anthony Green - - * src/*/ffitarget.h: Ensure that users never include ffitarget.h - directly. - -2012-02-23 Kai Tietz - - PR libffi/52221 - * src/x86/ffi.c (ffi_closure_raw_THISCALL): New - prototype. - (ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for - thiscall-convention. - (ffi_raw_call): Use ffi_prep_args_raw. - * src/x86/win32.S (ffi_closure_raw_THISCALL): Add - implementation for stub. - -2012-02-10 Kai Tietz - - * configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64 - windows target. - * configure: Regenerated. - -2012-02-08 Kai Tietz - - * src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32 - also FFI_THISCALL. - * src/x86/ffi.c (ffi_closure_THISCALL): Add prototype. - (FFI_INIT_TRAMPOLINE_THISCALL): New trampoline code. - (ffi_prep_closure_loc): Add FFI_THISCALL support. - * src/x86/ffitarget.h (FFI_TRAMPOLINE_SIZE): Adjust size. - * src/x86/win32.S (ffi_closure_THISCALL): New closure code - for thiscall-calling convention. - * testsuite/libffi.call/closure_thiscall.c: New test. - -2012-01-28 Kai Tietz - - * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new - argument to prototype for specify calling-convention. - (ffi_call): Add support for stdcall/thiscall convention. - (ffi_prep_args): Likewise. - (ffi_raw_call): Likewise. - * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and - FFI_FASTCALL. - * src/x86/win32.S (_ffi_call_win32): Add support for - fastcall/thiscall calling-convention calls. - * testsuite/libffi.call/fastthis1_win32.c: New test. - * testsuite/libffi.call/fastthis2_win32.c: New test. - * testsuite/libffi.call/fastthis3_win32.c: New test. - * testsuite/libffi.call/strlen2_win32.c: New test. - * testsuite/libffi.call/many2_win32.c: New test. - * testsuite/libffi.call/struct1_win32.c: New test. - * testsuite/libffi.call/struct2_win32.c: New test. - -2012-01-23 Uros Bizjak - - * src/alpha/ffi.c (ffi_prep_closure_loc): Check for bad ABI. - -2012-01-23 Anthony Green - Chris Young - - * configure.ac: Add Amiga support. - * configure: Rebuilt. - -2012-01-23 Dmitry Nadezhin - - * include/ffi_common.h (LIKELY, UNLIKELY): Fix definitions. - -2012-01-23 Andreas Schwab - - * src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain - mc68000. Test for __HAVE_68881__ in addition to __MC68881__. - -2012-01-19 Jakub Jelinek - - PR rtl-optimization/48496 - * src/ia64/ffi.c (ffi_call): Fix up aliasing violations. - -2012-01-09 Rainer Orth - - * configure.ac (i?86-*-*): Set TARGET to X86_64. - * configure: Regenerate. - -2011-12-07 Andrew Pinski - - PR libffi/50051 - * src/mips/n32.S: Add ".set mips4". - -2011-11-21 Andreas Tobler - - * configure: Regenerate. - -2011-11-12 David Gilbert - - * doc/libffi.texi, include/ffi.h.in, include/ffi_common.h, - man/Makefile.am, man/ffi.3, man/ffi_prep_cif.3, - man/ffi_prep_cif_var.3, src/arm/ffi.c, src/arm/ffitarget.h, - src/cris/ffi.c, src/prep_cif.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/float_va.c: Many changes to support variadic - function calls. - -2011-11-12 Kyle Moffett - - * src/powerpc/ffi.c, src/powerpc/ffitarget.h, - src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for - softfloat powerpc variants. - -2011-11-12 Petr Salinger - - * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support. - * configure: Rebuilt. - -2011-11-12 Timothy Wall - - * src/arm/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): Max - alignment of 4 for wince on ARM. - -2011-11-12 Kyle Moffett - Anthony Green - - * src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string - instructions (not available on some cores, like the PPC440). - -2011-11-12 Kimura Wataru - - * m4/ax_enable_builddir: Change from string comparison to numeric - comparison for wc output. - * configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS - X 10.7. - * configure: Rebuilt. - -2011-11-12 Anthony Green - - * Makefile.am (AM_CCASFLAGS): Add -g option to build assembly - files with debug info. - * Makefile.in: Rebuilt. - -2011-11-12 Jasper Lievisse Adriaanse - - * README: Update list of supported OpenBSD systems. - -2011-11-12 Anthony Green - - * libtool-version: Update. - * Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if - FFI_DEBUG. - (libffi_la_SOURCES): Remove src/debug.c - (EXTRA_DIST): Add src/debug.c - * Makefile.in: Rebuilt. - * README: Update for 3.0.11. - -2011-11-10 Richard Henderson - - * configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check. - * configure, aclocal.m4: Rebuild. - -2011-09-04 Iain Sandoe - - PR libffi/49594 - * src/powerpc/darwin_closure.S (stubs): Make the stub binding - helper reference track the architecture pointer size. - -2011-08-25 Andrew Haley - - * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Remove hard-coded assembly - instructions. - * src/arm/sysv.S (ffi_arm_trampoline): Put them here instead. - -2011-07-11 Andrew Haley - - * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Clear icache. - -2011-06-29 Rainer Orth - - * testsuite/libffi.call/cls_double_va.c: Move PR number to comment. - * testsuite/libffi.call/cls_longdouble_va.c: Likewise. - -2011-06-29 Rainer Orth - - PR libffi/46660 - * testsuite/libffi.call/cls_double_va.c: xfail dg-output on - mips-sgi-irix6*. - * testsuite/libffi.call/cls_longdouble_va.c: Likewise. - -2011-06-14 Rainer Orth - - * testsuite/libffi.call/huge_struct.c (test_large_fn): Use PRIu8, - PRId8 instead of %hhu, %hhd. - * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRId8, - PRIu8): Define. - [__sgi__] (PRId8, PRIu8): Define. - -2011-04-29 Rainer Orth - - * src/alpha/osf.S (UA_SI, FDE_ENCODING, FDE_ENCODE, FDE_ARANGE): - Define. - Use them to handle ELF vs. ECOFF differences. - [__osf__] (_GLOBAL__F_ffi_call_osf): Define. - -2011-03-30 Timothy Wall - - * src/powerpc/darwin.S: Fix unknown FDE encoding. - * src/powerpc/darwin_closure.S: ditto. - -2011-02-25 Anthony Green - - * src/powerpc/ffi.c (ffi_prep_closure_loc): Allow for more - 32-bit ABIs. - -2011-02-15 Anthony Green - - * m4/ax_cc_maxopt.m4: Don't -malign-double or use -ffast-math. - * configure: Rebuilt. - -2011-02-13 Ralf Wildenhues - - * configure: Regenerate. - -2011-02-13 Anthony Green - - * include/ffi_common.h (UNLIKELY, LIKELY): Define. - * src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition. - * src/prep_cif.c (UNLIKELY, LIKELY): Remove definition. - - * src/prep_cif.c (initialize_aggregate): Convert assertion into - FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0. - - * src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, - just return FFI_BAD_ABI when things are wrong. - * src/arm/ffi.c (ffi_prep_closure_loc): Ditto. - * src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto. - * src/mips/ffi.c (ffi_prep_closure_loc): Ditto. - * src/ia64/ffi.c (ffi_prep_closure_loc): Ditto. - * src/avr32/ffi.c (ffi_prep_closure_loc): Ditto. - -2011-02-11 Anthony Green - - * src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, - just return FFI_BAD_ABI when things are wrong. - -2012-02-11 Eric Botcazou - - * src/sparc/v9.S (STACKFRAME): Bump to 176. - -2011-02-09 Stuart Shelton - - http://bugs.gentoo.org/show_bug.cgi?id=286911 - * src/mips/ffitarget.h: Clean up error messages. - * src/java_raw_api.c (ffi_java_translate_args): Cast raw arg to - ffi_raw*. - * include/ffi.h.in: Add pragma for SGI compiler. - -2011-02-09 Anthony Green - - * configure.ac: Add powerpc64-*-darwin* support. - -2011-02-09 Anthony Green - - * README: Mention Interix. - -2011-02-09 Jonathan Callen - - * configure.ac: Add Interix to win32/cygwin/mingw case. - * configure: Ditto. - * src/closures.c: Treat Interix like Cygwin, instead of as a - generic win32. - -2011-02-09 Anthony Green - - * testsuite/libffi.call/err_bad_typedef.c: Remove xfail. - * testsuite/libffi.call/err_bad_abi.c: Remove xfail. - * src/x86/ffi64.c (UNLIKELY, LIKELY): Define. - (ffi_prep_closure_loc): Check for bad ABI. - * src/prep_cif.c (UNLIKELY, LIKELY): Define. - (initialize_aggregate): Check for bad types. - -2011-02-09 Landon Fuller - - * Makefile.am (EXTRA_DIST): Add build-ios.sh, src/arm/gentramp.sh, - src/arm/trampoline.S. - (nodist_libffi_la_SOURCES): Add src/arc/trampoline.S. - * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Define. - * src/arm/ffi.c (ffi_trampoline_table) - (ffi_closure_trampoline_table_page, ffi_trampoline_table_entry) - (FFI_TRAMPOLINE_CODELOC_CONFIG, FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) - (FFI_TRAMPOLINE_COUNT, ffi_trampoline_lock, ffi_trampoline_tables) - (ffi_trampoline_table_alloc, ffi_closure_alloc, ffi_closure_free): - Define for FFI_EXEC_TRAMPOLINE_TABLE case (iOS). - (ffi_prep_closure_loc): Handl FFI_EXEC_TRAMPOLINE_TABLE case - separately. - * src/arm/sysv.S: Handle Apple iOS host. - * src/closures.c: Handle FFI_EXEC_TRAMPOLINE_TABLE case. - * build-ios.sh: New file. - * fficonfig.h.in, configure, Makefile.in: Rebuilt. - * README: Mention ARM iOS. - -2011-02-08 Oren Held - - * src/dlmalloc.c (_STRUCT_MALLINFO): Define in order to avoid - redefinition of mallinfo on HP-UX. - -2011-02-08 Ginn Chen - - * src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio - aggregate return ABI. Flush cache. - (ffi_prep_closure_loc): Flush cache. - -2011-02-11 Anthony Green - - From Tom Honermann : - * src/powerpc/aix.S (ffi_call_AIX): Support for xlc toolchain on - AIX. Declare .ffi_prep_args. Insert nops after branch - instructions so that the AIX linker can insert TOC reload - instructions. - * src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN. - -2011-02-08 Ed - - * src/powerpc/asm.h: Fix grammar nit in comment. - -2011-02-08 Uli Link - - * include/ffi.h.in (FFI_64_BIT_MAX): Define and use. - -2011-02-09 Rainer Orth - - PR libffi/46661 - * testsuite/libffi.call/cls_pointer.c (main): Cast void * to - uintptr_t first. - * testsuite/libffi.call/cls_pointer_stack.c (main): Likewise. - -2011-02-08 Rafael Avila de Espindola - - * configure.ac: Fix x86 test for pc related relocs. - * configure: Rebuilt. - -2011-02-07 Joel Sherrill - - * libffi/src/m68k/ffi.c: Add RTEMS support for cache flushing. - Handle case when CPU variant does not have long double support. - * libffi/src/m68k/sysv.S: Add support for mc68000, Coldfire, - and cores with soft floating point. - -2011-02-07 Joel Sherrill - - * configure.ac: Add mips*-*-rtems* support. - * configure: Regenerate. - * src/mips/ffitarget.h: Ensure needed constants are available - for targets which do not have sgidefs.h. - -2011-01-26 Dave Korn - - PR target/40125 - * configure.ac (AM_LTLDFLAGS): Add -bindir option for windows DLLs. - * configure: Regenerate. - -2010-12-18 Iain Sandoe - - PR libffi/29152 - PR libffi/42378 - * src/powerpc/darwin_closure.S: Provide Darwin64 implementation, - update comments. - * src/powerpc/ffitarget.h (POWERPC_DARWIN64): New, - (FFI_TRAMPOLINE_SIZE): Update for Darwin64. - * src/powerpc/darwin.S: Provide Darwin64 implementation, - update comments. - * src/powerpc/ffi_darwin.c: Likewise. - -2010-12-06 Rainer Orth - - * configure.ac (libffi_cv_as_ascii_pseudo_op): Use double - backslashes. - (libffi_cv_as_string_pseudo_op): Likewise. - * configure: Regenerate. - -2010-12-03 Chung-Lin Tang - - * src/arm/sysv.S (ffi_closure_SYSV): Add UNWIND to .pad directive. - (ffi_closure_VFP): Same. - (ffi_call_VFP): Move down to before ffi_closure_VFP. Add '.fpu vfp' - directive. - -2010-12-01 Rainer Orth - - * testsuite/libffi.call/ffitest.h [__sgi] (PRId64, PRIu64): Define. - (PRIuPTR): Define. - -2010-11-29 Richard Henderson - Rainer Orth - - * src/x86/sysv.S (FDE_ENCODING, FDE_ENCODE): Define. - (.eh_frame): Use FDE_ENCODING. - (.LASFDE1, .LASFDE2, LASFDE3): Simplify with FDE_ENCODE. - -2010-11-22 Jacek Caban - - * configure.ac: Check for symbol underscores on mingw-w64. - * configure: Rebuilt. - * src/x86/win64.S: Correctly access extern symbols in respect to - underscores. - -2010-11-15 Rainer Orth - - * testsuite/lib/libffi-dg.exp: Rename ... - * testsuite/lib/libffi.exp: ... to this. - * libffi/testsuite/libffi.call/call.exp: Don't load libffi-dg.exp. - * libffi/testsuite/libffi.special/special.exp: Likewise. - -2010-10-28 Chung-Lin Tang - - * src/arm/ffi.c (ffi_prep_args): Add VFP register argument handling - code, new parameter, and return value. Update comments. - (ffi_prep_cif_machdep): Add case for VFP struct return values. Add - call to layout_vfp_args(). - (ffi_call_SYSV): Update declaration. - (ffi_call_VFP): New declaration. - (ffi_call): Add VFP struct return conditions. Call ffi_call_VFP() - when ABI is FFI_VFP. - (ffi_closure_VFP): New declaration. - (ffi_closure_SYSV_inner): Add new vfp_args parameter, update call to - ffi_prep_incoming_args_SYSV(). - (ffi_prep_incoming_args_SYSV): Update parameters. Add VFP argument - case handling. - (ffi_prep_closure_loc): Pass ffi_closure_VFP to trampoline - construction under VFP hard-float. - (rec_vfp_type_p): New function. - (vfp_type_p): Same. - (place_vfp_arg): Same. - (layout_vfp_args): Same. - * src/arm/ffitarget.h (ffi_abi): Add FFI_VFP. Define FFI_DEFAULT_ABI - based on __ARM_PCS_VFP. - (FFI_EXTRA_CIF_FIELDS): Define for adding VFP hard-float specific - fields. - (FFI_TYPE_STRUCT_VFP_FLOAT): Define internally used type code. - (FFI_TYPE_STRUCT_VFP_DOUBLE): Same. - * src/arm/sysv.S (ffi_call_SYSV): Change call of ffi_prep_args() to - direct call. Move function pointer load upwards. - (ffi_call_VFP): New function. - (ffi_closure_VFP): Same. - - * testsuite/lib/libffi-dg.exp (check-flags): New function. - (dg-skip-if): New function. - * testsuite/libffi.call/cls_double_va.c: Skip if target is arm*-*-* - and compiler options include -mfloat-abi=hard. - * testsuite/libffi.call/cls_longdouble_va.c: Same. - -2010-10-01 Jakub Jelinek - - PR libffi/45677 - * src/x86/ffi64.c (ffi_prep_cif_machdep): Ensure cif->bytes is - a multiple of 8. - * testsuite/libffi.call/many2.c: New test. - -2010-08-20 Mark Wielaard - - * src/closures.c (open_temp_exec_file_mnt): Check if getmntent_r - returns NULL. - -2010-08-09 Andreas Tobler - - * configure.ac: Add target powerpc64-*-freebsd*. - * configure: Regenerate. - * testsuite/libffi.call/cls_align_longdouble_split.c: Pass - -mlong-double-128 only to linux targets. - * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. - * testsuite/libffi.call/cls_longdouble.c: Likewise. - * testsuite/libffi.call/huge_struct.c: Likewise. - -2010-08-05 Dan Witte - - * Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the - debug CRT when --enable-debug is given. - * configure.ac: Define it. - * msvcc.sh: Translate -g and -DFFI_DEBUG appropriately. - -2010-08-04 Dan Witte - - * src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64 - platforms. - * src/x86/ffi.c: Remove redundant ifdef checks. - * src/prep_cif.c: Push stack space computation into src/x86/ffi.c - for X86_ANY so return value space doesn't get added twice. - -2010-08-03 Neil Rashbrooke - - * msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy. - -2010-07-22 Dan Witte - - * src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI. - * src/prep_cif.c: Fix ABI assertion. - * src/cris/ffi.c: Ditto. - -2010-07-10 Evan Phoenix - - * src/closures.c (selinux_enabled_check): Fix strncmp usage bug. - -2010-07-07 Dan Horák - - * include/ffi.h.in: Protect #define with #ifndef. - * src/powerpc/ffitarget.h: Ditto. - * src/s390/ffitarget.h: Ditto. - * src/sparc/ffitarget.h: Ditto. - -2010-07-07 Neil Roberts - - * src/x86/sysv.S (ffi_call_SYSV): Align the stack pointer to - 16-bytes. - -2010-07-02 Jakub Jelinek - - * Makefile.am (AM_MAKEFLAGS): Pass also mandir to submakes. - * Makefile.in: Regenerated. - -2010-05-19 Rainer Orth - - * configure.ac (libffi_cv_as_x86_pcrel): Check for illegal in as - output, too. - (libffi_cv_as_ascii_pseudo_op): Check for .ascii. - (libffi_cv_as_string_pseudo_op): Check for .string. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * src/x86/sysv.S (.eh_frame): Use .ascii, .string or error. - -2010-05-11 Dan Witte - - * doc/libffi.tex: Document previous change. - -2010-05-11 Makoto Kato - - * src/x86/ffi.c (ffi_call): Don't copy structs passed by value. - -2010-05-05 Michael Kohler - - * src/dlmalloc.c (dlfree): Fix spelling. - * src/ia64/ffi.c (ffi_prep_cif_machdep): Ditto. - * configure.ac: Ditto. - * configure: Rebuilt. - -2010-04-13 Dan Witte - - * msvcc.sh: Build with -W3 instead of -Wall. - * src/powerpc/ffi_darwin.c: Remove build warnings. - * src/x86/ffi.c: Ditto. - * src/x86/ffitarget.h: Ditto. - -2010-04-12 Dan Witte - Walter Meinl - - * configure.ac: Add OS/2 support. - * configure: Rebuilt. - * src/closures.c: Ditto. - * src/dlmalloc.c: Ditto. - * src/x86/win32.S: Ditto. - -2010-04-07 Jakub Jelinek - - * testsuite/libffi.call/err_bad_abi.c: Remove unused args variable. - -2010-04-02 Ralf Wildenhues - - * Makefile.in: Regenerate. - * aclocal.m4: Regenerate. - * include/Makefile.in: Regenerate. - * man/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2010-03-30 Dan Witte - - * msvcc.sh: Disable build warnings. - * README (tested): Clarify windows build procedure. - -2010-03-15 Rainer Orth - - * configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * libffi/src/x86/unix64.S (.eh_frame) - [HAVE_AS_X86_64_UNWIND_SECTION_TYPE]: Use @unwind section type. - -2010-03-14 Matthias Klose - - * src/x86/ffi64.c: Fix typo in comment. - * src/x86/ffi.c: Use /* ... */ comment style. - -2010-02-24 Rainer Orth - - * doc/libffi.texi (The Closure API): Fix typo. - * doc/libffi.info: Remove. - -2010-02-15 Matthias Klose - - * src/arm/sysv.S (__ARM_ARCH__): Define for processor - __ARM_ARCH_7EM__. - -2010-01-15 Anthony Green - - * README: Add notes on building with Microsoft Visual C++. - -2010-01-15 Daniel Witte - - * msvcc.sh: New file. - - * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. - * src/x86/ffi.c: Tweak function declaration and remove excess - parens. - * include/ffi.h.in: Add __declspec(align(8)) to typedef struct - ffi_closure. - - * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new - function ffi_call_win32 on X86_WIN32. - * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. - (ffi_call_STDCALL): Remove. - - * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code - to ffi_prep_cif_machdep for x86. - * src/x86/ffi.c (ffi_prep_cif_machdep): To here. - -2010-01-15 Oliver Kiddle - - * src/x86/ffitarget.h (ffi_abi): Check for __i386 and __amd64 for - Sun Studio compiler compatibility. - -2010-01-12 Conrad Irwin - - * doc/libffi.texi: Add closure example. - -2010-01-07 Rainer Orth - - PR libffi/40701 - * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRIdLL, - PRIuLL, PRId64, PRIu64, PRIuPTR): Define. - * testsuite/libffi.call/cls_align_sint64.c: Add -Wno-format on - alpha*-dec-osf*. - * testsuite/libffi.call/cls_align_uint64.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/return_ll1.c: Likewise. - * testsuite/libffi.call/stret_medium2.c: Likewise. - * testsuite/libffi.special/ffitestcxx.h (allocate_mmap): Cast - MAP_FAILED to char *. - -2010-01-06 Rainer Orth - - * src/mips/n32.S: Use .abicalls and .eh_frame with __GNUC__. - -2009-12-31 Anthony Green - - * README: Update for libffi 3.0.9. - -2009-12-27 Matthias Klose - - * configure.ac (HAVE_LONG_DOUBLE): Define for mips when - appropriate. - * configure: Rebuilt. - -2009-12-26 Anthony Green - - * testsuite/libffi.call/cls_longdouble_va.c: Mark as xfail for - avr32*-*-*. - * testsuite/libffi.call/cls_double_va.c: Ditto. - -2009-12-26 Andreas Tobler - - * testsuite/libffi.call/ffitest.h: Conditionally include stdint.h - and inttypes.h. - * testsuite/libffi.special/unwindtest.cc: Ditto. - -2009-12-26 Andreas Tobler - - * configure.ac: Add amd64-*-openbsd*. - * configure: Rebuilt. - * testsuite/lib/libffi-dg.exp (libffi_target_compile): Link - openbsd programs with -lpthread. - -2009-12-26 Anthony Green - - * testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c: Remove xfail for - mips*-*-* and arm*-*-*. - * testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c, - testsuite/libffi.call/stret_medium2.c, - testsuite/libffi.call/stret_medium.c, - testsuite/libffi.call/stret_large.c, - testsuite/libffi.call/stret_large2.c: Remove xfail for arm*-*-*. - -2009-12-31 Kay Tietz - - * testsuite/libffi.call/ffitest.h, - testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRuLL): Fix - definitions. - -2009-12-31 Carlo Bramini - - * configure.ac (AM_LTLDFLAGS): Define for windows hosts. - * Makefile.am (libffi_la_LDFLAGS): Add AM_LTLDFLAGS. - * configure: Rebuilt. - * Makefile.in: Rebuilt. - -2009-12-31 Anthony Green - Blake Chaffin. - - * testsuite/libffi.call/huge_struct.c: New test case from Blake - Chaffin @ Apple. - -2009-12-28 David Edelsohn - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to - local variables. - (aix_adjust_aggregate_sizes): New function. - (ffi_prep_cif_machdep): Call it. - -2009-12-26 Andreas Tobler - - * configure.ac: Define FFI_MMAP_EXEC_WRIT for the given targets. - * configure: Regenerate. - * fficonfig.h.in: Likewise. - * src/closures.c: Remove the FFI_MMAP_EXEC_WRIT definition for - Solaris/x86. - -2009-12-26 Andreas Schwab - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Advance intarg_count - when a float arguments is passed in memory. - (ffi_closure_helper_SYSV): Mark general registers as used up when - a 64bit or soft-float long double argument is passed in memory. - -2009-12-25 Matthias Klose - - * man/ffi_call.3: Fix #include in examples. - * doc/libffi.texi: Add dircategory. - -2009-12-25 Frank Everdij - - * include/ffi.h.in: Placed '__GNUC__' ifdef around - '__attribute__((aligned(8)))' in ffi_closure, fixes compile for - IRIX MIPSPro c99. - * include/ffi_common.h: Added '__sgi' define to non - '__attribute__((__mode__()))' integer typedefs. - * src/mips/ffi.c (ffi_call, ffi_closure_mips_inner_O32, - ffi_closure_mips_inner_N32): Added 'defined(_MIPSEB)' to BE check. - (ffi_closure_mips_inner_O32, ffi_closure_mips_inner_N32): Added - FFI_LONGDOUBLE support and alignment(N32 only). - * src/mips/ffitarget.h: Corrected '#include ' for IRIX and - fixed non '__attribute__((__mode__()))' integer typedefs. - * src/mips/n32.S: Put '#ifdef linux' around '.abicalls' and '.eh_frame' - since they are Linux/GNU Assembler specific. - -2009-12-25 Bradley Smith - - * configure.ac, Makefile.am, src/avr32/ffi.c, - src/avr32/ffitarget.h, - src/avr32/sysv.S: Add AVR32 port. - * configure, Makefile.in: Rebuilt. - -2009-12-21 Andreas Tobler - - * configure.ac: Make i?86 build on FreeBSD and OpenBSD. - * configure: Regenerate. - -2009-12-15 John David Anglin - - * testsuite/libffi.call/ffitest.h: Define PRIuPTR on PA HP-UX. - -2009-12-13 John David Anglin - - * src/pa/ffi.c (ffi_closure_inner_pa32): Handle FFI_TYPE_LONGDOUBLE - type on HP-UX. - -2012-02-13 Kai Tietz - - PR libffi/52221 - * src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall - support for X86_WIN32. - (FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement. - -2009-12-11 Eric Botcazou - - * src/sparc/ffi.c (ffi_closure_sparc_inner_v9): Properly align 'long - double' arguments. - -2009-12-11 Eric Botcazou - - * testsuite/libffi.call/ffitest.h: Define PRIuPTR on Solaris < 10. - -2009-12-10 Rainer Orth - - PR libffi/40700 - * src/closures.c [X86_64 && __sun__ && __svr4__] - (FFI_MMAP_EXEC_WRIT): Define. - -2009-12-08 David Daney - - * testsuite/libffi.call/stret_medium.c: Remove xfail for mips*-*-* - * testsuite/libffi.call/cls_align_longdouble_split2.c: Same. - * testsuite/libffi.call/stret_large.c: Same. - * testsuite/libffi.call/cls_align_longdouble_split.c: Same. - * testsuite/libffi.call/stret_large2.c: Same. - * testsuite/libffi.call/stret_medium2.c: Same. - -2009-12-07 David Edelsohn - - * src/powerpc/aix_closure.S (libffi_closure_ASM): Fix tablejump - typo. - -2009-12-05 David Edelsohn - - * src/powerpc/aix.S: Update AIX32 code to be consistent with AIX64 - code. - * src/powerpc/aix_closure.S: Same. - -2009-12-05 Ralf Wildenhues - - * Makefile.in: Regenerate. - * configure: Regenerate. - * include/Makefile.in: Regenerate. - * man/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2009-12-04 David Edelsohn - - * src/powerpc/aix_closure.S: Reorganize 64-bit code to match - linux64_closure.S. - -2009-12-04 Uros Bizjak - - PR libffi/41908 - * src/x86/ffi64.c (classify_argument): Update from - gcc/config/i386/i386.c. - (ffi_closure_unix64_inner): Do not use the address of two consecutive - SSE registers directly. - * testsuite/libffi.call/cls_dbls_struct.c (main): Remove xfail - for x86_64 linux targets. - -2009-12-04 David Edelsohn - - * src/powerpc/ffi_darwin.c (ffi_closure_helper_DARWIN): Increment - pfr for long double split between fpr13 and stack. - -2009-12-03 David Edelsohn - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Increment next_arg and - fparg_count twice for long double. - -2009-12-03 David Edelsohn - - PR libffi/42243 - * src/powerpc/ffi_darwin.c (ffi_prep_args): Remove extra parentheses. - -2009-12-03 Uros Bizjak - - * testsuite/libffi.call/cls_longdouble_va.c (main): Fix format string. - Remove xfails for x86 linux targets. - -2009-12-02 David Edelsohn - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Fix typo in INT64 - case. - -2009-12-01 David Edelsohn - - * src/powerpc/aix.S (ffi_call_AIX): Convert to more standard - register usage. Call ffi_prep_args directly. Add long double - return value support. - * src/powerpc/ffi_darwin.c (ffi_prep_args): Double arg increment - applies to FFI_TYPE_DOUBLE. Correct fpr_base increment typo. - Separate FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases. - (ffi_prep_cif_machdep): Only 16 byte stack alignment in 64 bit - mode. - (ffi_closure_helper_DARWIN): Remove nf and ng counters. Move temp - into case. - * src/powerpc/aix_closure.S: Maintain 16 byte stack alignment. - Allocate result area between params and FPRs. - -2009-11-30 David Edelsohn - - PR target/35484 - * src/powerpc/ffitarget.h (POWERPC64): Define for PPC64 Linux and - AIX64. - * src/powerpc/aix.S: Implement AIX64 version. - * src/powerpc/aix_closure.S: Implement AIX64 version. - (ffi_closure_ASM): Use extsb, lha and displament addresses. - * src/powerpc/ffi_darwin.c (ffi_prep_args): Implement AIX64 - support. - (ffi_prep_cif_machdep): Same. - (ffi_call): Same. - (ffi_closure_helper_DARWIN): Same. - -2009-11-02 Andreas Tobler - - PR libffi/41908 - * testsuite/libffi.call/testclosure.c: New test. - -2009-09-28 Kai Tietz - - * src/x86/win64.S (_ffi_call_win64 stack): Remove for gnu - assembly version use of ___chkstk. - -2009-09-23 Matthias Klose - - PR libffi/40242, PR libffi/41443 - * src/arm/sysv.S (__ARM_ARCH__): Define for processors - __ARM_ARCH_6T2__, __ARM_ARCH_6M__, __ARM_ARCH_7__, - __ARM_ARCH_7A__, __ARM_ARCH_7R__, __ARM_ARCH_7M__. - Change the conditionals to __SOFTFP__ || __ARM_EABI__ - for -mfloat-abi=softfp to work. - -2009-09-17 Loren J. Rittle - - PR testsuite/32843 (strikes again) - * src/x86/ffi.c (ffi_prep_cif_machdep): Add X86_FREEBSD to - enable proper extension on char and short. - -2009-09-15 David Daney - - * src/java_raw_api.c (ffi_java_raw_to_rvalue): Remove special - handling for FFI_TYPE_POINTER. - * src/mips/ffitarget.h (FFI_TYPE_STRUCT_D_SOFT, - FFI_TYPE_STRUCT_F_SOFT, FFI_TYPE_STRUCT_DD_SOFT, - FFI_TYPE_STRUCT_FF_SOFT, FFI_TYPE_STRUCT_FD_SOFT, - FFI_TYPE_STRUCT_DF_SOFT, FFI_TYPE_STRUCT_SOFT): New defines. - (FFI_N32_SOFT_FLOAT, FFI_N64_SOFT_FLOAT): New ffi_abi enumerations. - (enum ffi_abi): Set FFI_DEFAULT_ABI for soft-float. - * src/mips/n32.S (ffi_call_N32): Add handling for soft-float - structure and pointer returns. - (ffi_closure_N32): Add handling for pointer returns. - * src/mips/ffi.c (ffi_prep_args, calc_n32_struct_flags, - calc_n32_return_struct_flags): Handle soft-float. - (ffi_prep_cif_machdep): Handle soft-float, fix pointer handling. - (ffi_call_N32): Declare proper argument types. - (ffi_call, copy_struct_N32, ffi_closure_mips_inner_N32): Handle - soft-float. - -2009-08-24 Ralf Wildenhues - - * configure.ac (AC_PREREQ): Bump to 2.64. - -2009-08-22 Ralf Wildenhues - - * Makefile.am (install-html, install-pdf): Remove. - * Makefile.in: Regenerate. - - * Makefile.in: Regenerate. - * aclocal.m4: Regenerate. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * include/Makefile.in: Regenerate. - * man/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2011-08-22 Jasper Lievisse Adriaanse - - * configure.ac: Add OpenBSD/hppa and OpenBSD/powerpc support. - * configure: Rebuilt. - -2009-07-30 Ralf Wildenhues - - * configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force. - -2009-07-24 Dave Korn - - PR libffi/40807 - * src/x86/ffi.c (ffi_prep_cif_machdep): Also use sign/zero-extending - return types for X86_WIN32. - * src/x86/win32.S (_ffi_call_SYSV): Handle omitted return types. - (_ffi_call_STDCALL, _ffi_closure_SYSV, _ffi_closure_raw_SYSV, - _ffi_closure_STDCALL): Likewise. - - * src/closures.c (is_selinux_enabled): Define to const 0 for Cygwin. - (dlmmap, dlmunmap): Also use these functions on Cygwin. - -2009-07-11 Richard Sandiford - - PR testsuite/40699 - PR testsuite/40707 - PR testsuite/40709 - * testsuite/lib/libffi-dg.exp: Revert 2009-07-02, 2009-07-01 and - 2009-06-30 commits. - -2009-07-01 Richard Sandiford - - * testsuite/lib/libffi-dg.exp (libffi-init): Set ld_library_path - to "" before adding paths. (This reinstates an assignment that - was removed by my 2009-06-30 commit, but changes the initial - value from "." to "".) - -2009-07-01 H.J. Lu - - PR testsuite/40601 - * testsuite/lib/libffi-dg.exp (libffi-init): Properly set - gccdir. Adjust ld_library_path for gcc only if gccdir isn't - empty. - -2009-06-30 Richard Sandiford - - * testsuite/lib/libffi-dg.exp (libffi-init): Don't add "." - to ld_library_path. Use add_path. Add just find_libgcc_s - to ld_library_path, not every libgcc multilib directory. - -2009-06-16 Wim Lewis - - * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are - supposed to be callee-saved. - * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of - return buffer for odd-size structs. - -2009-06-16 Andreas Tobler - - PR libffi/40444 - * testsuite/lib/libffi-dg.exp (libffi_target_compile): Add - allow_stack_execute for Darwin. - -2009-06-16 Andrew Haley - - * configure.ac (TARGETDIR): Add missing blank lines. - * configure: Regenerate. - -2009-06-16 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - * testsuite/libffi.call/ffitest.h, - testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. - -2009-06-15 Andrew Haley - - * testsuite/libffi.call/err_bad_typedef.c: xfail everywhere. - * testsuite/libffi.call/err_bad_abi.c: Likewise. - -2009-06-12 Andrew Haley - - * Makefile.am: Remove info_TEXINFOS. - -2009-06-12 Andrew Haley - - * ChangeLog.libffi: testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - testsuite/libffi.special/unwindtest.cc: include stdint.h. - -2009-06-11 Timothy Wall - - * Makefile.am, - configure.ac, - include/ffi.h.in, - include/ffi_common.h, - src/closures.c, - src/dlmalloc.c, - src/x86/ffi.c, - src/x86/ffitarget.h, - src/x86/win64.S (new), - README: Added win64 support (mingw or MSVC) - * Makefile.in, - include/Makefile.in, - man/Makefile.in, - testsuite/Makefile.in, - configure, - aclocal.m4: Regenerated - * ltcf-c.sh: properly escape cygwin/w32 path - * man/ffi_call.3: Clarify size requirements for return value. - * src/x86/ffi64.c: Fix filename in comment. - * src/x86/win32.S: Remove unused extern. - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_12byte.c, - testsuite/libffi.call/cls_16byte.c, - testsuite/libffi.call/cls_18byte.c, - testsuite/libffi.call/cls_19byte.c, - testsuite/libffi.call/cls_1_1byte.c, - testsuite/libffi.call/cls_20byte.c, - testsuite/libffi.call/cls_20byte1.c, - testsuite/libffi.call/cls_24byte.c, - testsuite/libffi.call/cls_2byte.c, - testsuite/libffi.call/cls_3_1byte.c, - testsuite/libffi.call/cls_3byte1.c, - testsuite/libffi.call/cls_3byte2.c, - testsuite/libffi.call/cls_4_1byte.c, - testsuite/libffi.call/cls_4byte.c, - testsuite/libffi.call/cls_5_1_byte.c, - testsuite/libffi.call/cls_5byte.c, - testsuite/libffi.call/cls_64byte.c, - testsuite/libffi.call/cls_6_1_byte.c, - testsuite/libffi.call/cls_6byte.c, - testsuite/libffi.call/cls_7_1_byte.c, - testsuite/libffi.call/cls_7byte.c, - testsuite/libffi.call/cls_8byte.c, - testsuite/libffi.call/cls_9byte1.c, - testsuite/libffi.call/cls_9byte2.c, - testsuite/libffi.call/cls_align_double.c, - testsuite/libffi.call/cls_align_float.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_align_sint16.c, - testsuite/libffi.call/cls_align_sint32.c, - testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint16.c, - testsuite/libffi.call/cls_align_uint32.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_float.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_multi_schar.c, - testsuite/libffi.call/cls_multi_sshort.c, - testsuite/libffi.call/cls_multi_sshortchar.c, - testsuite/libffi.call/cls_multi_uchar.c, - testsuite/libffi.call/cls_multi_ushort.c, - testsuite/libffi.call/cls_multi_ushortchar.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/cls_schar.c, - testsuite/libffi.call/cls_sint.c, - testsuite/libffi.call/cls_sshort.c, - testsuite/libffi.call/cls_uchar.c, - testsuite/libffi.call/cls_uint.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/cls_ushort.c, - testsuite/libffi.call/err_bad_abi.c, - testsuite/libffi.call/err_bad_typedef.c, - testsuite/libffi.call/float2.c, - testsuite/libffi.call/huge_struct.c, - testsuite/libffi.call/nested_struct.c, - testsuite/libffi.call/nested_struct1.c, - testsuite/libffi.call/nested_struct10.c, - testsuite/libffi.call/nested_struct2.c, - testsuite/libffi.call/nested_struct3.c, - testsuite/libffi.call/nested_struct4.c, - testsuite/libffi.call/nested_struct5.c, - testsuite/libffi.call/nested_struct6.c, - testsuite/libffi.call/nested_struct7.c, - testsuite/libffi.call/nested_struct8.c, - testsuite/libffi.call/nested_struct9.c, - testsuite/libffi.call/problem1.c, - testsuite/libffi.call/return_ldl.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_large.c, - testsuite/libffi.call/stret_large2.c, - testsuite/libffi.call/stret_medium.c, - testsuite/libffi.call/stret_medium2.c, - testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead - of checking for MMAP. Use intptr_t instead of long casts. - -2009-06-11 Kaz Kojima - - * testsuite/libffi.call/cls_longdouble_va.c: Add xfail sh*-*-linux-*. - * testsuite/libffi.call/err_bad_abi.c: Add xfail sh*-*-*. - * testsuite/libffi.call/err_bad_typedef.c: Likewise. - -2009-06-09 Andrew Haley - - * src/x86/freebsd.S: Add missing file. - -2009-06-08 Andrew Haley - - Import from libffi 3.0.8: - - * doc/libffi.texi: New file. - * doc/libffi.info: Likewise. - * doc/stamp-vti: Likewise. - * man/Makefile.am: New file. - * man/ffi_call.3: New file. - - * Makefile.am (EXTRA_DIST): Add src/x86/darwin64.S, - src/dlmalloc.c. - (nodist_libffi_la_SOURCES): Add X86_FREEBSD. - - * configure.ac: Bump version to 3.0.8. - parisc*-*-linux*: Add. - i386-*-freebsd* | i386-*-openbsd*: Add. - powerpc-*-beos*: Add. - AM_CONDITIONAL X86_FREEBSD: Add. - AC_CONFIG_FILES: Add man/Makefile. - - * include/ffi.h.in (FFI_FN): Change void (*)() to void (*)(void). - -2009-06-08 Andrew Haley - - * README: Import from libffi 3.0.8. - -2009-06-08 Andrew Haley - - * testsuite/libffi.call/err_bad_abi.c: Add xfails. - * testsuite/libffi.call/cls_longdouble_va.c: Add xfails. - * testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*. - * testsuite/libffi.call/err_bad_typedef.c: Add xfails. - - * testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args. - * testsuite/libffi.call/stret_medium.c: Likewise. - * testsuite/libffi.call/stret_large2.c: Likewise. - * testsuite/libffi.call/stret_large.c: Likewise. - -2008-12-26 Timothy Wall - - * testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected - failures on x86_64 cygwin/mingw. - -2008-12-22 Timothy Wall - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_loc_fn0.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c: use portable cast from - pointer to integer (intptr_t). - * testsuite/libffi.call/cls_longdouble.c: disable for win64. - -2008-07-24 Anthony Green - - * testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/err_bad_abi.c: Clean up failures from - compiler warnings. - -2008-03-04 Anthony Green - Blake Chaffin - hos@tamanegi.org - - * testsuite/libffi.call/cls_align_longdouble_split2.c - testsuite/libffi.call/cls_align_longdouble_split.c - testsuite/libffi.call/cls_dbls_struct.c - testsuite/libffi.call/cls_double_va.c - testsuite/libffi.call/cls_longdouble.c - testsuite/libffi.call/cls_longdouble_va.c - testsuite/libffi.call/cls_pointer.c - testsuite/libffi.call/cls_pointer_stack.c - testsuite/libffi.call/err_bad_abi.c - testsuite/libffi.call/err_bad_typedef.c - testsuite/libffi.call/stret_large2.c - testsuite/libffi.call/stret_large.c - testsuite/libffi.call/stret_medium2.c - testsuite/libffi.call/stret_medium.c: New tests from Apple. - -2009-06-05 Andrew Haley - - * src/x86/ffitarget.h, src/x86/ffi.c: Merge stdcall changes from - libffi. - -2009-06-04 Andrew Haley - - * src/x86/ffitarget.h, src/x86/win32.S, src/x86/ffi.c: Back out - stdcall changes. - -2008-02-26 Anthony Green - Thomas Heller - - * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C - comment. - -2008-02-03 Timothy Wall - - * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return - offset based on code pointer, not data pointer. - -2008-01-31 Timothy Wall - - * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall - closures. - * src/x86/ffitarget.h: Increase size of trampoline for stdcall - closures. - * src/x86/win32.S: Add assembly for stdcall closure. - * src/x86/ffi.c: Initialize stdcall closure trampoline. - -2009-06-04 Andrew Haley - - * include/ffi.h.in: Change void (*)() to void (*)(void). - * src/x86/ffi.c: Likewise. - -2009-06-04 Andrew Haley - - * src/powerpc/ppc_closure.S: Insert licence header. - * src/powerpc/linux64_closure.S: Likewise. - * src/m68k/sysv.S: Likewise. - - * src/sh64/ffi.c: Change void (*)() to void (*)(void). - * src/powerpc/ffi.c: Likewise. - * src/powerpc/ffi_darwin.c: Likewise. - * src/m32r/ffi.c: Likewise. - * src/sh64/ffi.c: Likewise. - * src/x86/ffi64.c: Likewise. - * src/alpha/ffi.c: Likewise. - * src/alpha/osf.S: Likewise. - * src/frv/ffi.c: Likewise. - * src/s390/ffi.c: Likewise. - * src/pa/ffi.c: Likewise. - * src/pa/hpux32.S: Likewise. - * src/ia64/unix.S: Likewise. - * src/ia64/ffi.c: Likewise. - * src/sparc/ffi.c: Likewise. - * src/mips/ffi.c: Likewise. - * src/sh/ffi.c: Likewise. - -2008-02-15 David Daney - - * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): - Define (conditionally), and use it to include cachectl.h. - (ffi_prep_closure_loc): Fix cache flushing. - * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. - -2009-06-04 Andrew Haley - - include/ffi.h.in, - src/arm/ffitarget.h, - src/arm/ffi.c, - src/arm/sysv.S, - src/powerpc/ffitarget.h, - src/closures.c, - src/sh64/ffitarget.h, - src/sh64/ffi.c, - src/sh64/sysv.S, - src/types.c, - src/x86/ffi64.c, - src/x86/ffitarget.h, - src/x86/win32.S, - src/x86/darwin.S, - src/x86/ffi.c, - src/x86/sysv.S, - src/x86/unix64.S, - src/alpha/ffitarget.h, - src/alpha/ffi.c, - src/alpha/osf.S, - src/m68k/ffitarget.h, - src/frv/ffitarget.h, - src/frv/ffi.c, - src/s390/ffitarget.h, - src/s390/sysv.S, - src/cris/ffitarget.h, - src/pa/linux.S, - src/pa/ffitarget.h, - src/pa/ffi.c, - src/raw_api.c, - src/ia64/ffitarget.h, - src/ia64/unix.S, - src/ia64/ffi.c, - src/ia64/ia64_flags.h, - src/java_raw_api.c, - src/debug.c, - src/sparc/v9.S, - src/sparc/ffitarget.h, - src/sparc/ffi.c, - src/sparc/v8.S, - src/mips/ffitarget.h, - src/mips/n32.S, - src/mips/o32.S, - src/mips/ffi.c, - src/prep_cif.c, - src/sh/ffitarget.h, - src/sh/ffi.c, - src/sh/sysv.S: Update license text. - -2009-05-22 Dave Korn - - * src/x86/win32.S (_ffi_closure_STDCALL): New function. - (.eh_frame): Add FDE for it. - -2009-05-22 Dave Korn - - * configure.ac: Also check if assembler supports pc-relative - relocs on X86_WIN32 targets. - * configure: Regenerate. - * src/x86/win32.S (ffi_prep_args): Declare extern, not global. - (_ffi_call_SYSV): Add missing function type symbol .def and - add EH markup labels. - (_ffi_call_STDCALL): Likewise. - (_ffi_closure_SYSV): Likewise. - (_ffi_closure_raw_SYSV): Likewise. - (.eh_frame): Add hand-crafted EH data. - -2009-04-09 Jakub Jelinek - - * testsuite/lib/libffi-dg.exp: Change copyright header to refer to - version 3 of the GNU General Public License and to point readers - at the COPYING3 file and the FSF's license web page. - * testsuite/libffi.call/call.exp: Likewise. - * testsuite/libffi.special/special.exp: Likewise. - -2009-03-01 Ralf Wildenhues - - * configure: Regenerate. - -2008-12-18 Rainer Orth - - PR libffi/26048 - * configure.ac (HAVE_AS_X86_PCREL): New test. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * src/x86/sysv.S [!FFI_NO_RAW_API]: Precalculate - RAW_CLOSURE_CIF_OFFSET, RAW_CLOSURE_FUN_OFFSET, - RAW_CLOSURE_USER_DATA_OFFSET for the Solaris 10/x86 assembler. - (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. - * src/x86/unix64.S (.Lstore_table): Move to .text section. - (.Lload_table): Likewise. - (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. - -2008-12-18 Ralf Wildenhues - - * configure: Regenerate. - -2008-11-21 Eric Botcazou - - * src/sparc/ffi.c (ffi_prep_cif_machdep): Add support for - signed/unsigned int8/16 return values. - * src/sparc/v8.S (ffi_call_v8): Likewise. - (ffi_closure_v8): Likewise. - -2008-09-26 Peter O'Gorman - Steve Ellcey - - * configure: Regenerate for new libtool. - * Makefile.in: Ditto. - * include/Makefile.in: Ditto. - * aclocal.m4: Ditto. - -2008-08-25 Andreas Tobler - - * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and - FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. - Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. - Adjust copyright notice. - * src/powerpc/ffi.c: Add two new flags to indicate if we have one - register or two register to use for FFI_SYSV structs. - (ffi_prep_cif_machdep): Pass the right register flag introduced above. - (ffi_closure_helper_SYSV): Fix the return type for - FFI_SYSV_TYPE_SMALL_STRUCT. Comment. - Adjust copyright notice. - -2008-07-16 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned - int. - -2008-06-17 Ralf Wildenhues - - * configure: Regenerate. - * include/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2008-06-07 Joseph Myers - - * configure.ac (parisc*-*-linux*, powerpc-*-sysv*, - powerpc-*-beos*): Remove. - * configure: Regenerate. - -2008-05-09 Julian Brown - - * Makefile.am (LTLDFLAGS): New. - (libffi_la_LDFLAGS): Use above. - * Makefile.in: Regenerate. - -2008-04-18 Paolo Bonzini - - PR bootstrap/35457 - * aclocal.m4: Regenerate. - * configure: Regenerate. - -2008-03-26 Kaz Kojima - - * src/sh/sysv.S: Add .note.GNU-stack on Linux. - * src/sh64/sysv.S: Likewise. - -2008-03-26 Daniel Jacobowitz - - * src/arm/sysv.S: Fix ARM comment marker. - -2008-03-26 Jakub Jelinek - - * src/alpha/osf.S: Add .note.GNU-stack on Linux. - * src/s390/sysv.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. - * src/powerpc/sysv.S: Likewise. - * src/x86/unix64.S: Likewise. - * src/x86/sysv.S: Likewise. - * src/sparc/v8.S: Likewise. - * src/sparc/v9.S: Likewise. - * src/m68k/sysv.S: Likewise. - * src/arm/sysv.S: Likewise. - -2008-03-16 Ralf Wildenhues - - * aclocal.m4: Regenerate. - * configure: Likewise. - * Makefile.in: Likewise. - * include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - -2008-02-12 Bjoern Koenig - Andreas Tobler - - * configure.ac: Add amd64-*-freebsd* target. - * configure: Regenerate. - -2008-01-30 H.J. Lu - - PR libffi/34612 - * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when - returning struct. - - * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" - tests. - -2008-01-24 David Edelsohn - - * configure: Regenerate. - -2008-01-06 Andreas Tobler - - * src/x86/ffi.c (ffi_prep_cif_machdep): Fix thinko. - -2008-01-05 Andreas Tobler - - PR testsuite/32843 - * src/x86/ffi.c (ffi_prep_cif_machdep): Add code for - signed/unsigned int8/16 for X86_DARWIN. - Updated copyright info. - Handle one and two byte structs with special cif->flags. - * src/x86/ffitarget.h: Add special types for one and two byte structs. - Updated copyright info. - * src/x86/darwin.S (ffi_call_SYSV): Rewrite to use a jump table like - sysv.S - Remove code to pop args from the stack after call. - Special-case signed/unsigned for int8/16, one and two byte structs. - (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, - FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, - FFI_TYPE_SINT32. - Updated copyright info. - -2007-12-08 David Daney - - * src/mips/n32.S (ffi_call_N32): Replace dadd with ADDU, dsub with - SUBU, add with ADDU and use smaller code sequences. - -2007-12-07 David Daney - - * src/mips/ffi.c (ffi_prep_cif_machdep): Handle long double return - type. - -2007-12-06 David Daney - - * include/ffi.h.in (FFI_SIZEOF_JAVA_RAW): Define if not already - defined. - (ffi_java_raw): New typedef. - (ffi_java_raw_call, ffi_java_ptrarray_to_raw, - ffi_java_raw_to_ptrarray): Change parameter types from ffi_raw to - ffi_java_raw. - (ffi_java_raw_closure) : Same. - (ffi_prep_java_raw_closure, ffi_prep_java_raw_closure_loc): Change - parameter types. - * src/java_raw_api.c (ffi_java_raw_size): Replace FFI_SIZEOF_ARG with - FFI_SIZEOF_JAVA_RAW. - (ffi_java_raw_to_ptrarray): Change type of raw to ffi_java_raw. - Replace FFI_SIZEOF_ARG with FFI_SIZEOF_JAVA_RAW. Use - sizeof(ffi_java_raw) for alignment calculations. - (ffi_java_ptrarray_to_raw): Same. - (ffi_java_rvalue_to_raw): Add special handling for FFI_TYPE_POINTER - if FFI_SIZEOF_JAVA_RAW == 4. - (ffi_java_raw_to_rvalue): Same. - (ffi_java_raw_call): Change type of raw to ffi_java_raw. - (ffi_java_translate_args): Same. - (ffi_prep_java_raw_closure_loc, ffi_prep_java_raw_closure): Change - parameter types. - * src/mips/ffitarget.h (FFI_SIZEOF_JAVA_RAW): Define for N32 ABI. - -2007-12-06 David Daney - - * src/mips/n32.S (ffi_closure_N32): Use 64-bit add instruction on - pointer values. - -2007-12-01 Andreas Tobler - - PR libffi/31937 - * src/powerpc/ffitarget.h: Introduce new ABI FFI_LINUX_SOFT_FLOAT. - Add local FFI_TYPE_UINT128 to handle soft-float long-double-128. - * src/powerpc/ffi.c: Distinguish between __NO_FPRS__ and not and - set the NUM_FPR_ARG_REGISTERS according to. - Add support for potential soft-float support under hard-float - architecture. - (ffi_prep_args_SYSV): Set NUM_FPR_ARG_REGISTERS to 0 in case of - FFI_LINUX_SOFT_FLOAT, handle float, doubles and long-doubles according - to the FFI_LINUX_SOFT_FLOAT ABI. - (ffi_prep_cif_machdep): Likewise. - (ffi_closure_helper_SYSV): Likewise. - * src/powerpc/ppc_closure.S: Make sure not to store float/double - on archs where __NO_FPRS__ is true. - Add FFI_TYPE_UINT128 support. - * src/powerpc/sysv.S: Add support for soft-float long-double-128. - Adjust copyright notice. - -2007-11-25 Andreas Tobler - - * src/closures.c: Move defintion of MAYBE_UNUSED from here to ... - * include/ffi_common.h: ... here. - Update copyright. - -2007-11-17 Andreas Tobler - - * src/powerpc/sysv.S: Load correct cr to compare if we have long double. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/ffi.c: Add a comment to show which part goes into cr6. - * testsuite/libffi.call/return_ldl.c: New test. - -2007-09-04 - - * src/arm/sysv.S (UNWIND): New. - (Whole file): Conditionally compile unwinder directives. - * src/arm/sysv.S: Add unwinder directives. - - * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes. - Only treat r0 as a struct address if we're actually returning a - struct by address. - Only copy the bytes that are actually within a struct. - (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes - is returned in r0, not passed by address. - (ffi_call): Allocate a word-sized temporary for the case where - a composite is returned in r0. - (ffi_prep_incoming_args_SYSV): Align as necessary. - -2007-08-05 Steven Newbury - - * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of - directly using the sys_cacheflush syscall. - -2007-07-27 Andrew Haley - - * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float. - -2007-09-03 Maciej W. Rozycki - - * Makefile.am: Unify MIPS_IRIX and MIPS_LINUX into MIPS. - * configure.ac: Likewise. - * Makefile.in: Regenerate. - * include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - * configure: Likewise. - -2007-08-24 David Daney - - * testsuite/libffi.call/return_sl.c: New test. - -2007-08-10 David Daney - - * testsuite/libffi.call/cls_multi_ushort.c, - testsuite/libffi.call/cls_align_uint16.c, - testsuite/libffi.call/nested_struct1.c, - testsuite/libffi.call/nested_struct3.c, - testsuite/libffi.call/cls_7_1_byte.c, - testsuite/libffi.call/nested_struct5.c, - testsuite/libffi.call/cls_double.c, - testsuite/libffi.call/nested_struct7.c, - testsuite/libffi.call/cls_sint.c, - testsuite/libffi.call/nested_struct9.c, - testsuite/libffi.call/cls_20byte1.c, - testsuite/libffi.call/cls_multi_sshortchar.c, - testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_3byte2.c, - testsuite/libffi.call/cls_multi_schar.c, - testsuite/libffi.call/cls_multi_uchar.c, - testsuite/libffi.call/cls_19byte.c, - testsuite/libffi.call/cls_9byte1.c, - testsuite/libffi.call/cls_align_float.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/problem1.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/cls_sshort.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/cls_align_double.c, - testsuite/libffi.call/nested_struct.c, - testsuite/libffi.call/cls_2byte.c, - testsuite/libffi.call/nested_struct10.c, - testsuite/libffi.call/cls_4byte.c, - testsuite/libffi.call/cls_6byte.c, - testsuite/libffi.call/cls_8byte.c, - testsuite/libffi.call/cls_multi_sshort.c, - testsuite/libffi.call/cls_align_sint16.c, - testsuite/libffi.call/cls_align_uint32.c, - testsuite/libffi.call/cls_20byte.c, - testsuite/libffi.call/cls_float.c, - testsuite/libffi.call/nested_struct2.c, - testsuite/libffi.call/cls_5_1_byte.c, - testsuite/libffi.call/nested_struct4.c, - testsuite/libffi.call/cls_24byte.c, - testsuite/libffi.call/nested_struct6.c, - testsuite/libffi.call/cls_64byte.c, - testsuite/libffi.call/nested_struct8.c, - testsuite/libffi.call/cls_uint.c, - testsuite/libffi.call/cls_multi_ushortchar.c, - testsuite/libffi.call/cls_schar.c, - testsuite/libffi.call/cls_uchar.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_1_1byte.c, - testsuite/libffi.call/cls_12byte.c, - testsuite/libffi.call/cls_3_1byte.c, - testsuite/libffi.call/cls_3byte1.c, - testsuite/libffi.call/cls_4_1byte.c, - testsuite/libffi.call/cls_6_1_byte.c, - testsuite/libffi.call/cls_16byte.c, - testsuite/libffi.call/cls_18byte.c, - testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/cls_9byte2.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/cls_ushort.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/cls_5byte.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_7byte.c, - testsuite/libffi.call/cls_align_sint32.c, - testsuite/libffi.special/unwindtest_ffi_call.cc, - testsuite/libffi.special/unwindtest.cc: Remove xfail for mips64*-*-*. - -2007-08-10 David Daney - - PR libffi/28313 - * configure.ac: Don't treat mips64 as a special case. - * Makefile.am (nodist_libffi_la_SOURCES): Add n32.S. - * configure: Regenerate - * Makefile.in: Ditto. - * fficonfig.h.in: Ditto. - * src/mips/ffitarget.h (REG_L, REG_S, SUBU, ADDU, SRL, LI): Indent. - (LA, EH_FRAME_ALIGN, FDE_ADDR_BYTES): New preprocessor macros. - (FFI_DEFAULT_ABI): Set for n64 case. - (FFI_CLOSURES, FFI_TRAMPOLINE_SIZE): Define for n32 and n64 cases. - * src/mips/n32.S (ffi_call_N32): Add debug macros and labels for FDE. - (ffi_closure_N32): New function. - (.eh_frame): New section - * src/mips/o32.S: Clean up comments. - (ffi_closure_O32): Pass ffi_closure parameter in $12. - * src/mips/ffi.c: Use FFI_MIPS_N32 instead of - _MIPS_SIM == _ABIN32 throughout. - (FFI_MIPS_STOP_HERE): New, use in place of - ffi_stop_here. - (ffi_prep_args): Use unsigned long to hold pointer values. Rewrite - to support n32/n64 ABIs. - (calc_n32_struct_flags): Rewrite. - (calc_n32_return_struct_flags): Remove unused variable. Reverse - position of flag bits. - (ffi_prep_cif_machdep): Rewrite n32 portion. - (ffi_call): Enable for n64. Add special handling for small structure - return values. - (ffi_prep_closure_loc): Add n32 and n64 support. - (ffi_closure_mips_inner_O32): Add cast to silence warning. - (copy_struct_N32, ffi_closure_mips_inner_N32): New functions. - -2007-08-08 David Daney - - * testsuite/libffi.call/ffitest.h (ffi_type_mylong): Remove definition. - * testsuite/libffi.call/cls_align_uint16.c (main): Use correct type - specifiers. - * testsuite/libffi.call/nested_struct1.c (main): Ditto. - * testsuite/libffi.call/cls_sint.c (main): Ditto. - * testsuite/libffi.call/nested_struct9.c (main): Ditto. - * testsuite/libffi.call/cls_20byte1.c (main): Ditto. - * testsuite/libffi.call/cls_9byte1.c (main): Ditto. - * testsuite/libffi.call/closure_fn1.c (main): Ditto. - * testsuite/libffi.call/closure_fn3.c (main): Ditto. - * testsuite/libffi.call/return_dbl2.c (main): Ditto. - * testsuite/libffi.call/cls_sshort.c (main): Ditto. - * testsuite/libffi.call/return_fl3.c (main): Ditto. - * testsuite/libffi.call/closure_fn5.c (main): Ditto. - * testsuite/libffi.call/nested_struct.c (main): Ditto. - * testsuite/libffi.call/nested_struct10.c (main): Ditto. - * testsuite/libffi.call/return_ll1.c (main): Ditto. - * testsuite/libffi.call/cls_8byte.c (main): Ditto. - * testsuite/libffi.call/cls_align_uint32.c (main): Ditto. - * testsuite/libffi.call/cls_align_sint16.c (main): Ditto. - * testsuite/libffi.call/cls_20byte.c (main): Ditto. - * testsuite/libffi.call/nested_struct2.c (main): Ditto. - * testsuite/libffi.call/cls_24byte.c (main): Ditto. - * testsuite/libffi.call/nested_struct6.c (main): Ditto. - * testsuite/libffi.call/cls_uint.c (main): Ditto. - * testsuite/libffi.call/cls_12byte.c (main): Ditto. - * testsuite/libffi.call/cls_16byte.c (main): Ditto. - * testsuite/libffi.call/closure_fn0.c (main): Ditto. - * testsuite/libffi.call/cls_9byte2.c (main): Ditto. - * testsuite/libffi.call/closure_fn2.c (main): Ditto. - * testsuite/libffi.call/return_dbl1.c (main): Ditto. - * testsuite/libffi.call/closure_fn4.c (main): Ditto. - * testsuite/libffi.call/closure_fn6.c (main): Ditto. - * testsuite/libffi.call/cls_align_sint32.c (main): Ditto. - -2007-08-07 Andrew Haley - - * src/x86/sysv.S (ffi_closure_raw_SYSV): Fix typo in previous - checkin. - -2007-08-06 Andrew Haley - - PR testsuite/32843 - * src/x86/sysv.S (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, - FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, - FFI_TYPE_SINT32. - -2007-08-02 David Daney - - * testsuite/libffi.call/return_ul.c (main): Define return type as - ffi_arg. Use proper printf conversion specifier. - -2007-07-30 Andrew Haley - - PR testsuite/32843 - * src/x86/ffi.c (ffi_prep_cif_machdep): in x86 case, add code for - signed/unsigned int8/16. - * src/x86/sysv.S (ffi_call_SYSV): Rewrite to: - Use a jump table. - Remove code to pop args from the stack after call. - Special-case signed/unsigned int8/16. - * testsuite/libffi.call/return_sc.c (main): Revert. - -2007-07-26 Richard Guenther - - PR testsuite/32843 - * testsuite/libffi.call/return_sc.c (main): Verify call - result as signed char, not ffi_arg. - -2007-07-16 Rainer Orth - - * configure.ac (i?86-*-solaris2.1[0-9]): Set TARGET to X86_64. - * configure: Regenerate. - -2007-07-11 David Daney - - * src/mips/ffi.c: Don't include sys/cachectl.h. - (ffi_prep_closure_loc): Use __builtin___clear_cache() instead of - cacheflush(). - -2007-05-18 Aurelien Jarno - - * src/arm/ffi.c (ffi_prep_closure_loc): Renamed and ajusted - from (ffi_prep_closure): ... this. - (FFI_INIT_TRAMPOLINE): Adjust. - -2005-12-31 Phil Blundell - - * src/arm/ffi.c (ffi_prep_incoming_args_SYSV, - ffi_closure_SYSV_inner, ffi_prep_closure): New, add closure support. - * src/arm/sysv.S(ffi_closure_SYSV): Likewise. - * src/arm/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. - (FFI_CLOSURES): Enable closure support. - -2007-07-03 Andrew Haley - - * testsuite/libffi.call/cls_multi_ushort.c, - testsuite/libffi.call/cls_align_uint16.c, - testsuite/libffi.call/nested_struct1.c, - testsuite/libffi.call/nested_struct3.c, - testsuite/libffi.call/cls_7_1_byte.c, - testsuite/libffi.call/cls_double.c, - testsuite/libffi.call/nested_struct5.c, - testsuite/libffi.call/nested_struct7.c, - testsuite/libffi.call/cls_sint.c, - testsuite/libffi.call/nested_struct9.c, - testsuite/libffi.call/cls_20byte1.c, - testsuite/libffi.call/cls_multi_sshortchar.c, - testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_3byte2.c, - testsuite/libffi.call/cls_multi_schar.c, - testsuite/libffi.call/cls_multi_uchar.c, - testsuite/libffi.call/cls_19byte.c, - testsuite/libffi.call/cls_9byte1.c, - testsuite/libffi.call/cls_align_float.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/problem1.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/cls_sshort.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/cls_align_double.c, - testsuite/libffi.call/cls_2byte.c, - testsuite/libffi.call/nested_struct.c, - testsuite/libffi.call/nested_struct10.c, - testsuite/libffi.call/cls_4byte.c, - testsuite/libffi.call/cls_6byte.c, - testsuite/libffi.call/cls_8byte.c, - testsuite/libffi.call/cls_multi_sshort.c, - testsuite/libffi.call/cls_align_uint32.c, - testsuite/libffi.call/cls_align_sint16.c, - testsuite/libffi.call/cls_float.c, - testsuite/libffi.call/cls_20byte.c, - testsuite/libffi.call/cls_5_1_byte.c, - testsuite/libffi.call/nested_struct2.c, - testsuite/libffi.call/cls_24byte.c, - testsuite/libffi.call/nested_struct4.c, - testsuite/libffi.call/nested_struct6.c, - testsuite/libffi.call/cls_64byte.c, - testsuite/libffi.call/nested_struct8.c, - testsuite/libffi.call/cls_uint.c, - testsuite/libffi.call/cls_multi_ushortchar.c, - testsuite/libffi.call/cls_schar.c, - testsuite/libffi.call/cls_uchar.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_1_1byte.c, - testsuite/libffi.call/cls_12byte.c, - testsuite/libffi.call/cls_3_1byte.c, - testsuite/libffi.call/cls_3byte1.c, - testsuite/libffi.call/cls_4_1byte.c, - testsuite/libffi.call/cls_6_1_byte.c, - testsuite/libffi.call/cls_16byte.c, - testsuite/libffi.call/cls_18byte.c, - testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/cls_9byte2.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/cls_ushort.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/cls_5byte.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_7byte.c, - testsuite/libffi.call/cls_align_sint32.c, - testsuite/libffi.special/unwindtest_ffi_call.cc, - testsuite/libffi.special/unwindtest.cc: Enable for ARM. - -2007-07-05 H.J. Lu - - * aclocal.m4: Regenerated. - -2007-06-02 Paolo Bonzini - - * configure: Regenerate. - -2007-05-23 Steve Ellcey - - * Makefile.in: Regenerate. - * configure: Regenerate. - * aclocal.m4: Regenerate. - * include/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2007-05-10 Roman Zippel - - * src/m68k/ffi.c (ffi_prep_incoming_args_SYSV, - ffi_closure_SYSV_inner,ffi_prep_closure): New, add closure support. - * src/m68k/sysv.S(ffi_closure_SYSV,ffi_closure_struct_SYSV): Likewise. - * src/m68k/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. - (FFI_CLOSURES): Enable closure support. - -2007-05-10 Roman Zippel - - * configure.ac (HAVE_AS_CFI_PSEUDO_OP): New test. - * configure: Regenerate. - * fficonfig.h.in: Regenerate. - * src/m68k/sysv.S (CFI_STARTPROC,CFI_ENDPROC, - CFI_OFFSET,CFI_DEF_CFA): New macros. - (ffi_call_SYSV): Add callframe annotation. - -2007-05-10 Roman Zippel - - * src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix - numerous test suite failures. - * src/m68k/sysv.S (ffi_call_SYSV): Likewise. - -2007-04-11 Paolo Bonzini - - * Makefile.am (EXTRA_DIST): Bring up to date. - * Makefile.in: Regenerate. - * src/frv/eabi.S: Remove RCS keyword. - -2007-04-06 Richard Henderson - - * configure.ac: Tidy target case. - (HAVE_LONG_DOUBLE): Allow the target to override. - * configure: Regenerate. - * include/ffi.h.in: Don't define ffi_type_foo if - LIBFFI_HIDE_BASIC_TYPES is defined. - (ffi_type_longdouble): If not HAVE_LONG_DOUBLE, define - to ffi_type_double. - * types.c (LIBFFI_HIDE_BASIC_TYPES): Define. - (FFI_TYPEDEF, ffi_type_void): Mark the data const. - (ffi_type_longdouble): Special case for Alpha. Don't define - if long double == double. - - * src/alpha/ffi.c (FFI_TYPE_LONGDOUBLE): Assert unique value. - (ffi_prep_cif_machdep): Handle it as the 128-bit type. - (ffi_call, ffi_closure_osf_inner): Likewise. - (ffi_closure_osf_inner): Likewise. Mark hidden. - (ffi_call_osf, ffi_closure_osf): Mark hidden. - * src/alpha/ffitarget.h (FFI_LAST_ABI): Tidy definition. - * src/alpha/osf.S (ffi_call_osf, ffi_closure_osf): Mark hidden. - (load_table): Handle 128-bit long double. - - * testsuite/libffi.call/float4.c: Add -mieee for alpha. - -2007-04-06 Tom Tromey - - PR libffi/31491: - * README: Fixed bug in example. - -2007-04-03 Jakub Jelinek - - * src/closures.c: Include sys/statfs.h. - (_GNU_SOURCE): Define on Linux. - (FFI_MMAP_EXEC_SELINUX): Define. - (selinux_enabled): New variable. - (selinux_enabled_check): New function. - (is_selinux_enabled): Define. - (dlmmap): Use it. - -2007-03-24 Uros Bizjak - - * testsuite/libffi.call/return_fl2.c (return_fl): Mark as static. - Use 'volatile float sum' to create sum of floats to avoid false - negative due to excess precision on ix86 targets. - (main): Ditto. - -2007-03-08 Alexandre Oliva - - * src/powerpc/ffi.c (flush_icache): Fix left-over from previous - patch. - (ffi_prep_closure_loc): Remove unneeded casts. Add needed ones. - -2007-03-07 Alexandre Oliva - - * include/ffi.h.in (ffi_closure_alloc, ffi_closure_free): New. - (ffi_prep_closure_loc): New. - (ffi_prep_raw_closure_loc): New. - (ffi_prep_java_raw_closure_loc): New. - * src/closures.c: New file. - * src/dlmalloc.c [FFI_MMAP_EXEC_WRIT] (struct malloc_segment): - Replace sflags with exec_offset. - [FFI_MMAP_EXEC_WRIT] (mmap_exec_offset, add_segment_exec_offset, - sub_segment_exec_offset): New macros. - (get_segment_flags, set_segment_flags, check_segment_merge): New - macros. - (is_mmapped_segment, is_extern_segment): Use get_segment_flags. - (add_segment, sys_alloc, create_mspace, create_mspace_with_base, - destroy_mspace): Use new macros. - (sys_alloc): Silence warning. - * Makefile.am (libffi_la_SOURCES): Add src/closures.c. - * Makefile.in: Rebuilt. - * src/prep_cif [FFI_CLOSURES] (ffi_prep_closure): Implement in - terms of ffi_prep_closure_loc. - * src/raw_api.c (ffi_prep_raw_closure_loc): Renamed and adjusted - from... - (ffi_prep_raw_closure): ... this. Re-implement in terms of the - renamed version. - * src/java_raw_api (ffi_prep_java_raw_closure_loc): Renamed and - adjusted from... - (ffi_prep_java_raw_closure): ... this. Re-implement in terms of - the renamed version. - * src/alpha/ffi.c (ffi_prep_closure_loc): Renamed from - (ffi_prep_closure): ... this. - * src/pa/ffi.c: Likewise. - * src/cris/ffi.c: Likewise. Adjust. - * src/frv/ffi.c: Likewise. - * src/ia64/ffi.c: Likewise. - * src/mips/ffi.c: Likewise. - * src/powerpc/ffi_darwin.c: Likewise. - * src/s390/ffi.c: Likewise. - * src/sh/ffi.c: Likewise. - * src/sh64/ffi.c: Likewise. - * src/sparc/ffi.c: Likewise. - * src/x86/ffi64.c: Likewise. - * src/x86/ffi.c: Likewise. - (FFI_INIT_TRAMPOLINE): Adjust. - (ffi_prep_raw_closure_loc): Renamed and adjusted from... - (ffi_prep_raw_closure): ... this. - * src/powerpc/ffi.c (ffi_prep_closure_loc): Renamed from - (ffi_prep_closure): ... this. - (flush_icache): Adjust. - -2007-03-07 Alexandre Oliva - - * src/dlmalloc.c: New file, imported version 2.8.3 of Doug - Lea's malloc. - -2007-03-01 Brooks Moses - - * Makefile.am: Add dummy install-pdf target. - * Makefile.in: Regenerate - -2007-02-13 Andreas Krebbel - - * src/s390/ffi.c (ffi_prep_args, ffi_prep_cif_machdep, - ffi_closure_helper_SYSV): Add long double handling. - -2007-02-02 Jakub Jelinek - - * src/powerpc/linux64.S (ffi_call_LINUX64): Move restore of r2 - immediately after bctrl instruction. - -2007-01-18 Alexandre Oliva - - * Makefile.am (all-recursive, install-recursive, - mostlyclean-recursive, clean-recursive, distclean-recursive, - maintainer-clean-recursive): Add missing targets. - * Makefile.in: Rebuilt. - -2006-12-14 Andreas Tobler - - * configure.ac: Add TARGET for x86_64-*-darwin*. - * Makefile.am (nodist_libffi_la_SOURCES): Add rules for 64-bit sources - for X86_DARWIN. - * src/x86/ffitarget.h: Set trampoline size for x86_64-*-darwin*. - * src/x86/darwin64.S: New file for x86_64-*-darwin* support. - * configure: Regenerate. - * Makefile.in: Regenerate. - * include/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - * testsuite/libffi.special/unwindtest_ffi_call.cc: New test case for - ffi_call only. - -2006-12-13 Andreas Tobler - - * aclocal.m4: Regenerate with aclocal -I .. as written in the - Makefile.am. - -2006-10-31 Geoffrey Keating - - * src/powerpc/ffi_darwin.c (darwin_adjust_aggregate_sizes): New. - (ffi_prep_cif_machdep): Call darwin_adjust_aggregate_sizes for - Darwin. - * testsuite/libffi.call/nested_struct4.c: Remove Darwin XFAIL. - * testsuite/libffi.call/nested_struct6.c: Remove Darwin XFAIL. - -2006-10-10 Paolo Bonzini - Sandro Tolaini - - * configure.ac [i*86-*-darwin*]: Set X86_DARWIN symbol and - conditional. - * configure: Regenerated. - * Makefile.am (nodist_libffi_la_SOURCES) [X86_DARWIN]: New case. - (EXTRA_DIST): Add src/x86/darwin.S. - * Makefile.in: Regenerated. - * include/Makefile.in: Regenerated. - * testsuite/Makefile.in: Regenerated. - - * src/x86/ffi.c (ffi_prep_cif_machdep) [X86_DARWIN]: Treat like - X86_WIN32, and additionally align stack to 16 bytes. - * src/x86/darwin.S: New, based on sysv.S. - * src/prep_cif.c (ffi_prep_cif) [X86_DARWIN]: Align > 8-byte structs. - -2006-09-12 David Daney - - PR libffi/23935 - * include/Makefile.am: Install both ffi.h and ffitarget.h in - $(libdir)/gcc/$(target_alias)/$(gcc_version)/include. - * aclocal.m4: Regenerated for automake 1.9.6. - * Makefile.in: Regenerated. - * include/Makefile.in: Regenerated. - * testsuite/Makefile.in: Regenerated. - -2006-08-17 Andreas Tobler - - * include/ffi_common.h (struct): Revert accidental commit. - -2006-08-15 Andreas Tobler - - * include/ffi_common.h: Remove lint directives. - * include/ffi.h.in: Likewise. - -2006-07-25 Torsten Schoenfeld - - * include/ffi.h.in (ffi_type_ulong, ffi_type_slong): Define correctly - for 32-bit architectures. - * testsuite/libffi.call/return_ul.c: New test case. - -2006-07-19 David Daney - - * testsuite/libffi.call/closure_fn6.c: Remove xfail for mips, - xfail remains for mips64. - -2006-05-23 Carlos O'Donell - - * Makefile.am: Add install-html target. Add install-html to .PHONY - * Makefile.in: Regenerate. - * aclocal.m4: Regenerate. - * include/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2006-05-18 John David Anglin - - * pa/ffi.c (ffi_prep_args_pa32): Load floating point arguments from - stack slot. - -2006-04-22 Andreas Tobler - - * README: Remove notice about 'Crazy Comments'. - * src/debug.c: Remove lint directives. Cleanup white spaces. - * src/java_raw_api.c: Likewise. - * src/prep_cif.c: Likewise. - * src/raw_api.c: Likewise. - * src/ffitest.c: Delete. No longer needed, all test cases migrated - to the testsuite. - * src/arm/ffi.c: Remove lint directives. - * src/m32r/ffi.c: Likewise. - * src/pa/ffi.c: Likewise. - * src/powerpc/ffi.c: Likewise. - * src/powerpc/ffi_darwin.c: Likewise. - * src/sh/ffi.c: Likewise. - * src/sh64/ffi.c: Likewise. - * src/x86/ffi.c: Likewise. - * testsuite/libffi.call/float2.c: Likewise. - * testsuite/libffi.call/promotion.c: Likewise. - * testsuite/libffi.call/struct1.c: Likewise. - -2006-04-13 Andreas Tobler - - * src/pa/hpux32.S: Correct unwind offset calculation for - ffi_closure_pa32. - * src/pa/linux.S: Likewise. - -2006-04-12 James E Wilson - - PR libgcj/26483 - * src/ia64/ffi.c (stf_spill, ldf_fill): Rewrite as macros. - (hfa_type_load): Call stf_spill. - (hfa_type_store): Call ldf_fill. - (ffi_call): Adjust calls to above routines. Add local temps for - macro result. - -2006-04-10 Matthias Klose - - * testsuite/lib/libffi-dg.exp (libffi-init): Recognize multilib - directory names containing underscores. - -2006-04-07 James E Wilson - - * testsuite/libffi.call/float4.c: New testcase. - -2006-04-05 John David Anglin - Andreas Tobler - - * Makefile.am: Add PA_HPUX port. - * Makefile.in: Regenerate. - * include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - * configure.ac: Add PA_HPUX rules. - * configure: Regenerate. - * src/pa/ffitarget.h: Rename linux target to PA_LINUX. - Add PA_HPUX and PA64_HPUX. - Rename FFI_LINUX ABI to FFI_PA32 ABI. - (FFI_TRAMPOLINE_SIZE): Define for 32-bit HP-UX targets. - (FFI_TYPE_SMALL_STRUCT2): Define. - (FFI_TYPE_SMALL_STRUCT4): Likewise. - (FFI_TYPE_SMALL_STRUCT8): Likewise. - (FFI_TYPE_SMALL_STRUCT3): Redefine. - (FFI_TYPE_SMALL_STRUCT5): Likewise. - (FFI_TYPE_SMALL_STRUCT6): Likewise. - (FFI_TYPE_SMALL_STRUCT7): Likewise. - * src/pa/ffi.c (ROUND_DOWN): Delete. - (fldw, fstw, fldd, fstd): Use '__asm__'. - (ffi_struct_type): Add support for FFI_TYPE_SMALL_STRUCT2, - FFI_TYPE_SMALL_STRUCT4 and FFI_TYPE_SMALL_STRUCT8. - (ffi_prep_args_LINUX): Rename to ffi_prep_args_pa32. Update comment. - Simplify incrementing of stack slot variable. Change type of local - 'n' to unsigned int. - (ffi_size_stack_LINUX): Rename to ffi_size_stack_pa32. Handle long - double on PA_HPUX. - (ffi_prep_cif_machdep): Likewise. - (ffi_call): Likewise. - (ffi_closure_inner_LINUX): Rename to ffi_closure_inner_pa32. Change - return type to ffi_status. Simplify incrementing of stack slot - variable. Only copy floating point argument registers when PA_LINUX - is true. Reformat debug statement. - Add support for FFI_TYPE_SMALL_STRUCT2, FFI_TYPE_SMALL_STRUCT4 and - FFI_TYPE_SMALL_STRUCT8. - (ffi_closure_LINUX): Rename to ffi_closure_pa32. Add 'extern' to - declaration. - (ffi_prep_closure): Make linux trampoline conditional on PA_LINUX. - Add nops to cache flush. Add trampoline for PA_HPUX. - * src/pa/hpux32.S: New file. - * src/pa/linux.S (ffi_call_LINUX): Rename to ffi_call_pa32. Rename - ffi_prep_args_LINUX to ffi_prep_args_pa32. - Localize labels. Add support for 2, 4 and 8-byte small structs. Handle - unaligned destinations in 3, 5, 6 and 7-byte small structs. Order - argument type checks so that common argument types appear first. - (ffi_closure_LINUX): Rename to ffi_closure_pa32. Rename - ffi_closure_inner_LINUX to ffi_closure_inner_pa32. - -2006-03-24 Alan Modra - - * src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX. Default - for 32-bit using IBM extended double format. Fix FFI_LAST_ABI. - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of - FFI_TYPE_LONGDOUBLE. - (ffi_prep_args64): Assert using IBM extended double. - (ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type. - Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args. - (ffi_call): Handle FFI_LINUX. - (ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs - gpr3 return pointer as for struct return. Handle FFI_LINUX - FFI_TYPE_LONGDOUBLE return and args. Don't increment "nf" - unnecessarily. - * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2 - for FFI_TYPE_LONGDOUBLE. Move epilogue insns into case table. - Don't use r6 as pointer to results, instead use sp offset. Don't - make a special call to load lr with case table address, instead - use offset from previous call. - * src/powerpc/sysv.S (ffi_call_SYSV): Save long double return. - * src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double - return. - -2006-03-15 Kaz Kojima - - * src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments - passed with FP registers correctly. - (ffi_closure_helper_SYSV): Likewise. - * src/sh64/sysv.S: Likewise. - -2006-03-01 Andreas Tobler - - * testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif, - args and userdata unused. - (closure_test_fn1): Mark cif and userdata unused. - (main): Remove unused res. - -2006-02-28 Andreas Tobler - - * testsuite/libffi.call/call.exp: Adjust FSF address. Add test runs for - -O2, -O3, -Os and the warning flags -W -Wall. - * testsuite/libffi.special/special.exp: Likewise. - * testsuite/libffi.call/ffitest.h: Add an __UNUSED__ macro to mark - unused parameter unused for gcc or else do nothing. - * testsuite/libffi.special/ffitestcxx.h: Likewise. - * testsuite/libffi.call/cls_12byte.c (cls_struct_12byte_gn): Mark cif - and userdata unused. - * testsuite/libffi.call/cls_16byte.c (cls_struct_16byte_gn): Likewise. - * testsuite/libffi.call/cls_18byte.c (cls_struct_18byte_gn): Likewise. - * testsuite/libffi.call/cls_19byte.c (cls_struct_19byte_gn): Likewise. - * testsuite/libffi.call/cls_1_1byte.c (cls_struct_1_1byte_gn): Likewise. - * testsuite/libffi.call/cls_20byte.c (cls_struct_20byte_gn): Likewise. - * testsuite/libffi.call/cls_20byte1.c (cls_struct_20byte_gn): Likewise. - * testsuite/libffi.call/cls_24byte.c (cls_struct_24byte_gn): Likewise. - * testsuite/libffi.call/cls_2byte.c (cls_struct_2byte_gn): Likewise. - * testsuite/libffi.call/cls_3_1byte.c (cls_struct_3_1byte_gn): Likewise. - * testsuite/libffi.call/cls_3byte1.c (cls_struct_3byte_gn): Likewise. - * testsuite/libffi.call/cls_3byte2.c (cls_struct_3byte_gn1): Likewise. - * testsuite/libffi.call/cls_4_1byte.c (cls_struct_4_1byte_gn): Likewise. - * testsuite/libffi.call/cls_4byte.c (cls_struct_4byte_gn): Likewise. - * testsuite/libffi.call/cls_5_1_byte.c (cls_struct_5byte_gn): Likewise. - * testsuite/libffi.call/cls_5byte.c (cls_struct_5byte_gn): Likewise. - * testsuite/libffi.call/cls_64byte.c (cls_struct_64byte_gn): Likewise. - * testsuite/libffi.call/cls_6_1_byte.c (cls_struct_6byte_gn): Likewise. - * testsuite/libffi.call/cls_6byte.c (cls_struct_6byte_gn): Likewise. - * testsuite/libffi.call/cls_7_1_byte.c (cls_struct_7byte_gn): Likewise. - * testsuite/libffi.call/cls_7byte.c (cls_struct_7byte_gn): Likewise. - * testsuite/libffi.call/cls_8byte.c (cls_struct_8byte_gn): Likewise. - * testsuite/libffi.call/cls_9byte1.c (cls_struct_9byte_gn): Likewise. - * testsuite/libffi.call/cls_9byte2.c (cls_struct_9byte_gn): Likewise. - * testsuite/libffi.call/cls_align_double.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_float.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_longdouble.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_pointer.c (cls_struct_align_fn): Cast - void* to avoid compiler warning. - (main): Likewise. - (cls_struct_align_gn): Mark cif and userdata unused. - * testsuite/libffi.call/cls_align_sint16.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_sint32.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_sint64.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_uint16.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_align_uint32.c (cls_struct_align_gn): - Likewise. - * testsuite/libffi.call/cls_double.c (cls_ret_double_fn): Likewise. - * testsuite/libffi.call/cls_float.c (cls_ret_float_fn): Likewise. - * testsuite/libffi.call/cls_multi_schar.c (test_func_gn): Mark cif and - data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_multi_sshort.c (test_func_gn): Mark cif and - data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_multi_sshortchar.c (test_func_gn): Mark cif - and data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_multi_uchar.c (test_func_gn): Mark cif and - data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_multi_ushort.c (test_func_gn): Mark cif and - data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_multi_ushortchar.c (test_func_gn): Mark cif - and data unused. - (main): Cast res_call to silence gcc. - * testsuite/libffi.call/cls_schar.c (cls_ret_schar_fn): Mark cif and - userdata unused. - (cls_ret_schar_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/cls_sint.c (cls_ret_sint_fn): Mark cif and - userdata unused. - (cls_ret_sint_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/cls_sshort.c (cls_ret_sshort_fn): Mark cif and - userdata unused. - (cls_ret_sshort_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/cls_uchar.c (cls_ret_uchar_fn): Mark cif and - userdata unused. - (cls_ret_uchar_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Mark cif and - userdata unused. - (cls_ret_uint_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/cls_ulonglong.c (cls_ret_ulonglong_fn): Mark cif - and userdata unused. - * testsuite/libffi.call/cls_ushort.c (cls_ret_ushort_fn): Mark cif and - userdata unused. - (cls_ret_ushort_fn): Cast printf parameter to silence gcc. - * testsuite/libffi.call/float.c (floating): Remove unused parameter e. - * testsuite/libffi.call/float1.c (main): Remove unused variable i. - Cleanup white spaces. - * testsuite/libffi.call/negint.c (checking): Remove unused variable i. - * testsuite/libffi.call/nested_struct.c (cls_struct_combined_gn): Mark - cif and userdata unused. - * testsuite/libffi.call/nested_struct1.c (cls_struct_combined_gn): - Likewise. - * testsuite/libffi.call/nested_struct10.c (B_gn): Likewise. - * testsuite/libffi.call/nested_struct2.c (B_fn): Adjust printf - formatters to silence gcc. - (B_gn): Mark cif and userdata unused. - * testsuite/libffi.call/nested_struct3.c (B_gn): Mark cif and userdata - unused. - * testsuite/libffi.call/nested_struct4.c: Mention related PR. - (B_gn): Mark cif and userdata unused. - * testsuite/libffi.call/nested_struct5.c (B_gn): Mark cif and userdata - unused. - * testsuite/libffi.call/nested_struct6.c: Mention related PR. - (B_gn): Mark cif and userdata unused. - * testsuite/libffi.call/nested_struct7.c (B_gn): Mark cif and userdata - unused. - * testsuite/libffi.call/nested_struct8.c (B_gn): Likewise. - * testsuite/libffi.call/nested_struct9.c (B_gn): Likewise. - * testsuite/libffi.call/problem1.c (stub): Likewise. - * testsuite/libffi.call/pyobjc-tc.c (main): Cast the result to silence - gcc. - * testsuite/libffi.call/return_fl2.c (return_fl): Add the note mentioned - in the last commit for this test case in the test case itself. - * testsuite/libffi.call/closure_fn0.c (closure_test_fn0): Mark cif as - unused. - * testsuite/libffi.call/closure_fn1.c (closure_test_fn1): Likewise. - * testsuite/libffi.call/closure_fn2.c (closure_test_fn2): Likewise. - * testsuite/libffi.call/closure_fn3.c (closure_test_fn3): Likewise. - * testsuite/libffi.call/closure_fn4.c (closure_test_fn0): Likewise. - * testsuite/libffi.call/closure_fn5.c (closure_test_fn5): Likewise. - * testsuite/libffi.call/closure_fn6.c (closure_test_fn0): Likewise. - -2006-02-22 Kaz Kojima - - * src/sh/sysv.S: Fix register numbers in the FDE for - ffi_closure_SYSV. - -2006-02-20 Andreas Tobler - - * testsuite/libffi.call/return_fl2.c (return_fl): Remove static - declaration to avoid a false negative on ix86. See PR323. - -2006-02-18 Kaz Kojima - - * src/sh/ffi.c (ffi_closure_helper_SYSV): Remove unused variable - and cast integer to void * if needed. Update the pointer to - the FP register saved area correctly. - -2006-02-17 Andreas Tobler - - * testsuite/libffi.call/nested_struct6.c: XFAIL this test until PR25630 - is fixed. - * testsuite/libffi.call/nested_struct4.c: Likewise. - -2006-02-16 Andreas Tobler - - * testsuite/libffi.call/return_dbl.c: New test case. - * testsuite/libffi.call/return_dbl1.c: Likewise. - * testsuite/libffi.call/return_dbl2.c: Likewise. - * testsuite/libffi.call/return_fl.c: Likewise. - * testsuite/libffi.call/return_fl1.c: Likewise. - * testsuite/libffi.call/return_fl2.c: Likewise. - * testsuite/libffi.call/return_fl3.c: Likewise. - * testsuite/libffi.call/closure_fn6.c: Likewise. - - * testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong - definition. - * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition - here to be used by other test cases too. - - * testsuite/libffi.call/nested_struct10.c: New test case. - * testsuite/libffi.call/nested_struct9.c: Likewise. - * testsuite/libffi.call/nested_struct8.c: Likewise. - * testsuite/libffi.call/nested_struct7.c: Likewise. - * testsuite/libffi.call/nested_struct6.c: Likewise. - * testsuite/libffi.call/nested_struct5.c: Likewise. - * testsuite/libffi.call/nested_struct4.c: Likewise. - -2006-01-21 Andreas Tobler - - * configure.ac: Enable libffi for sparc64-*-freebsd*. - * configure: Rebuilt. - -2006-01-18 Jakub Jelinek - - * src/powerpc/sysv.S (smst_two_register): Don't call __ashldi3, - instead do the shifting inline. - * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't compute %r5 - shift count unconditionally. Simplify load sequences for 1, 2, 3, 4 - and 8 byte structs, for the remaining struct sizes don't call - __lshrdi3, instead do the shifting inline. - -2005-12-07 Thiemo Seufer - - * src/mips/ffitarget.h: Remove obsolete sgidefs.h include. Add - missing parentheses. - * src/mips/o32.S (ffi_call_O32): Code formatting. Define - and use A3_OFF, FP_OFF, RA_OFF. Micro-optimizations. - (ffi_closure_O32): Likewise, but with newly defined A3_OFF2, - A2_OFF2, A1_OFF2, A0_OFF2, RA_OFF2, FP_OFF2, S0_OFF2, GP_OFF2, - V1_OFF2, V0_OFF2, FA_1_1_OFF2, FA_1_0_OFF2, FA_0_1_OFF2, - FA_0_0_OFF2. - * src/mips/ffi.c (ffi_prep_args): Code formatting. Fix - endianness bugs. - (ffi_prep_closure): Improve trampoline instruction scheduling. - (ffi_closure_mips_inner_O32): Fix endianness bugs. - -2005-12-03 Alan Modra - - * src/powerpc/ffi.c: Formatting. - (ffi_prep_args_SYSV): Avoid possible aliasing problems by using unions. - (ffi_prep_args64): Likewise. - -2005-09-30 Geoffrey Keating - - * testsuite/lib/libffi-dg.exp (libffi_target_compile): For - darwin, use -shared-libgcc not -lgcc_s, and explain why. - -2005-09-26 Tom Tromey - - * testsuite/libffi.call/float1.c (value_type): New typedef. - (CANARY): New define. - (main): Check for result buffer overflow. - * src/powerpc/linux64.S: Handle linux64 long double returns. - * src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant. - (ffi_prep_cif_machdep): Handle linux64 long double returns. - -2005-08-25 Alan Modra - - PR target/23404 - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Correct placement of stack - homed fp args. - (ffi_status ffi_prep_cif_machdep): Correct stack sizing for same. - -2005-08-11 Jakub Jelinek - - * configure.ac (HAVE_HIDDEN_VISIBILITY_ATTRIBUTE): New test. - (AH_BOTTOM): Add FFI_HIDDEN definition. - * configure: Rebuilt. - * fficonfig.h.in: Rebuilt. - * src/powerpc/ffi.c (hidden): Remove. - (ffi_closure_LINUX64, ffi_prep_args64, ffi_call_LINUX64, - ffi_closure_helper_LINUX64): Use FFI_HIDDEN instead of hidden. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64, - .ffi_closure_LINUX64): Use FFI_HIDDEN instead of .hidden. - * src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): Remove, - add FFI_HIDDEN to its prototype. - (ffi_closure_SYSV_inner): New. - * src/x86/sysv.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. - * src/x86/win32.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. - -2005-08-10 Alfred M. Szmidt - - PR libffi/21819: - * configure: Rebuilt. - * configure.ac: Handle i*86-*-gnu*. - -2005-08-09 Jakub Jelinek - - * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Use - DW_CFA_offset_extended_sf rather than - DW_CFA_GNU_negative_offset_extended. - * src/powerpc/sysv.S (ffi_call_SYSV): Likewise. - -2005-07-22 SUGIOKA Toshinobu - - * src/sh/sysv.S (ffi_call_SYSV): Stop argument popping correctly - on sh3. - (ffi_closure_SYSV): Change the stack layout for sh3 struct argument. - * src/sh/ffi.c (ffi_prep_args): Fix sh3 argument copy, when it is - partially on register. - (ffi_closure_helper_SYSV): Likewise. - (ffi_prep_cif_machdep): Don't set too many cif->flags. - -2005-07-20 Kaz Kojima - - * src/sh/ffi.c (ffi_call): Handle small structures correctly. - Remove empty line. - * src/sh64/ffi.c (simple_type): Remove. - (return_type): Handle small structures correctly. - (ffi_prep_args): Likewise. - (ffi_call): Likewise. - (ffi_closure_helper_SYSV): Likewise. - * src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return. - Emit position independent code if PIC and remove wrong datalabel - prefixes from EH data. - -2005-07-19 Andreas Tobler - - * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD. - * Makefile.in: Regenerate. - * include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - * configure.ac: Add POWERPC_FREEBSD rules. - * configure: Regenerate. - * src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules. - (FFI_SYSV_TYPE_SMALL_STRUCT): Define. - * src/powerpc/ffi.c: Add flags to handle small structure returns - in ffi_call_SYSV. - (ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI. - Aka FFI_SYSV. - (ffi_closure_helper_SYSV): Likewise. - * src/powerpc/ppc_closure.S: Add return types for small structures. - * src/powerpc/sysv.S: Add bits to handle small structures for - final SYSV 4 ABI. - -2005-07-10 Andreas Tobler - - * testsuite/libffi.call/cls_5_1_byte.c: New test file. - * testsuite/libffi.call/cls_6_1_byte.c: Likewise. - * testsuite/libffi.call/cls_7_1_byte.c: Likewise. - -2005-07-05 Randolph Chung - - * src/pa/ffi.c (ffi_struct_type): Rename FFI_TYPE_SMALL_STRUCT1 - as FFI_TYPE_SMALL_STRUCT3. Break out handling for 5-7 byte - structures. Kill compilation warnings. - (ffi_closure_inner_LINUX): Print return values as hex in debug - message. Rename FFI_TYPE_SMALL_STRUCT1 as FFI_TYPE_SMALL_STRUCT3. - Properly handle 5-7 byte structure returns. - * src/pa/ffitarget.h (FFI_TYPE_SMALL_STRUCT1) - (FFI_TYPE_SMALL_STRUCT2): Remove. - (FFI_TYPE_SMALL_STRUCT3, FFI_TYPE_SMALL_STRUCT5) - (FFI_TYPE_SMALL_STRUCT6, FFI_TYPE_SMALL_STRUCT7): Define. - * src/pa/linux.S: Mark source file as using PA1.1 assembly. - (checksmst1, checksmst2): Remove. - (checksmst3): Optimize handling of 3-byte struct returns. - (checksmst567): Properly handle 5-7 byte struct returns. - -2005-06-15 Rainer Orth - - PR libgcj/21943 - * src/mips/n32.S: Enforce PIC code. - * src/mips/o32.S: Likewise. - -2005-06-15 Rainer Orth - - * configure.ac: Treat i*86-*-solaris2.10 and up as X86_64. - * configure: Regenerate. - -2005-06-01 Alan Modra - - * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't use JUMPTARGET - to call ffi_closure_helper_SYSV. Append @local instead. - * src/powerpc/sysv.S (ffi_call_SYSV): Likewise for ffi_prep_args_SYSV. - -2005-05-17 Kelley Cook - - * configure.ac: Use AC_C_BIGENDIAN instead of AC_C_BIGENDIAN_CROSS. - Use AC_CHECK_SIZEOF instead of AC_COMPILE_CHECK_SIZEOF. - * Makefile.am (ACLOCAL_AMFLAGS): Remove -I ../config. - * aclocal.m4, configure, fficonfig.h.in, Makefile.in, - include/Makefile.in, testsuite/Makefile.in: Regenerate. - -2005-05-09 Mike Stump - - * configure: Regenerate. - -2005-05-08 Richard Henderson - - PR libffi/21285 - * src/alpha/osf.S: Update unwind into to match code. - -2005-05-04 Andreas Degert - Richard Henderson - - * src/x86/ffi64.c (ffi_prep_cif_machdep): Save sse-used flag in - bit 11 of flags. - (ffi_call): Mask return type field. Pass ssecount to ffi_call_unix64. - (ffi_prep_closure): Set carry bit if sse-used flag set. - * src/x86/unix64.S (ffi_call_unix64): Add ssecount argument. - Only load sse registers if ssecount non-zero. - (ffi_closure_unix64): Only save sse registers if carry set on entry. - -2005-04-29 Ralf Corsepius - - * configure.ac: Add i*86-*-rtems*, sparc*-*-rtems*, - powerpc-*rtems*, arm*-*-rtems*, sh-*-rtems*. - * configure: Regenerate. - -2005-04-20 Hans-Peter Nilsson - - * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): In regsub use, - have Tcl8.3-compatible intermediate variable. - -2005-04-18 Simon Posnjak - Hans-Peter Nilsson - - * Makefile.am: Add CRIS support. - * configure.ac: Likewise. - * Makefile.in, configure, testsuite/Makefile.in, - include/Makefile.in: Regenerate. - * src/cris: New directory. - * src/cris/ffi.c, src/cris/sysv.S, src/cris/ffitarget.h: New files. - * src/prep_cif.c (ffi_prep_cif): Wrap in #ifndef __CRIS__. - - * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): Replace \n with - \r?\n in output tests. - -2005-04-12 Mike Stump - - * configure: Regenerate. - -2005-03-30 Hans Boehm - - * src/ia64/ffitarget.h (ffi_arg): Use long long instead of DI. - -2005-03-30 Steve Ellcey - - * src/ia64/ffitarget.h (ffi_arg) ADD DI attribute. - (ffi_sarg) Ditto. - * src/ia64/unix.S (ffi_closure_unix): Extend gp - to 64 bits in ILP32 mode. - Load 64 bits even for short data. - -2005-03-23 Mike Stump - - * src/powerpc/darwin.S: Update for -m64 multilib. - * src/powerpc/darwin_closure.S: Likewise. - -2005-03-21 Zack Weinberg - - * configure.ac: Do not invoke TL_AC_GCC_VERSION. - Do not set tool_include_dir. - * aclocal.m4, configure, Makefile.in, testsuite/Makefile.in: - Regenerate. - * include/Makefile.am: Set gcc_version and toollibffidir. - * include/Makefile.in: Regenerate. - -2005-02-22 Andrew Haley - - * src/powerpc/ffi.c (ffi_prep_cif_machdep): Bump alignment to - odd-numbered register pairs for 64-bit integer types. - -2005-02-23 Andreas Tobler - - PR libffi/20104 - * testsuite/libffi.call/return_ll1.c: New test case. - -2005-02-11 Janis Johnson - - * testsuite/libffi.call/cls_align_longdouble.c: Remove dg-options. - * testsuite/libffi.call/float.c: Ditto. - * testsuite/libffi.call/float2.c: Ditto. - * testsuite/libffi.call/float3.c: Ditto. - -2005-02-08 Andreas Tobler - - * src/frv/ffitarget.h: Remove PPC stuff which does not belong to frv. - -2005-01-12 Eric Botcazou - - * testsuite/libffi.special/special.exp (cxx_options): Add - -shared-libgcc. - -2004-12-31 Richard Henderson - - * src/types.c (FFI_AGGREGATE_TYPEDEF): Remove. - (FFI_TYPEDEF): Rename from FFI_INTEGRAL_TYPEDEF. Replace size and - offset parameters with a type parameter; deduce size and structure - alignment. Update all users. - -2004-12-31 Richard Henderson - - * src/types.c (FFI_TYPE_POINTER): Define with sizeof. - (FFI_TYPE_LONGDOUBLE): Fix for ia64. - * src/ia64/ffitarget.h (struct ffi_ia64_trampoline_struct): Move - into ffi_prep_closure. - * src/ia64/ia64_flags.h, src/ia64/ffi.c, src/ia64/unix.S: Rewrite - from scratch. - -2004-12-27 Richard Henderson - - * src/x86/unix64.S: Fix typo in unwind info. - -2004-12-25 Richard Henderson - - * src/x86/ffi64.c (struct register_args): Rename from stackLayout. - (enum x86_64_reg_class): Add X86_64_COMPLEX_X87_CLASS. - (merge_classes): Check for it. - (SSE_CLASS_P): New. - (classify_argument): Pass byte_offset by value; perform all updates - inside struct case. - (examine_argument): Add classes argument; handle - X86_64_COMPLEX_X87_CLASS. - (ffi_prep_args): Merge into ... - (ffi_call): ... here. Share stack frame with ffi_call_unix64. - (ffi_prep_cif_machdep): Setup cif->flags for proper structure return. - (ffi_fill_return_value): Remove. - (ffi_prep_closure): Remove dead assert. - (ffi_closure_unix64_inner): Rename from ffi_closure_UNIX64_inner. - Rewrite to use struct register_args instead of va_list. Create - flags for handling structure returns. - * src/x86/unix64.S: Remove dead strings. - (ffi_call_unix64): Rename from ffi_call_UNIX64. Rewrite to share - stack frame with ffi_call. Handle structure returns properly. - (float2sse, floatfloat2sse, double2sse): Remove. - (sse2float, sse2double, sse2floatfloat): Remove. - (ffi_closure_unix64): Rename from ffi_closure_UNIX64. Rewrite - to handle structure returns properly. - -2004-12-08 David Edelsohn - - * Makefile.am (AM_MAKEFLAGS): Remove duplicate LIBCFLAGS and - PICFLAG. - * Makefile.in: Regenerated. - -2004-12-02 Richard Sandiford - - * configure.ac: Use TL_AC_GCC_VERSION to set gcc_version. - * configure, aclocal.m4, Makefile.in: Regenerate. - * include/Makefile.in, testsuite/Makefile.in: Regenerate. - -2004-11-29 Kelley Cook - - * configure: Regenerate for libtool change. - -2004-11-25 Kelley Cook - - * configure: Regenerate for libtool reversion. - -2004-11-24 Kelley Cook - - * configure: Regenerate for libtool change. - -2004-11-23 John David Anglin - - * testsuite/lib/libffi-dg.exp: Use new procs in target-libpath.exp. - -2004-11-23 Richard Sandiford - - * src/mips/o32.S (ffi_call_O32, ffi_closure_O32): Use jalr instead - of jal. Use an absolute encoding for the frame information. - -2004-11-23 Kelley Cook - - * Makefile.am: Remove no-dependencies. Add ACLOCAL_AMFLAGS. - * acinclude.m4: Delete logic for sincludes. - * aclocal.m4, Makefile.in, configure: Regenerate. - * include/Makefile: Likewise. - * testsuite/Makefile: Likewise. - -2004-11-22 Eric Botcazou - - * src/sparc/ffi.c (ffi_prep_closure): Align doubles and 64-bit integers - on a 8-byte boundary. - * src/sparc/v8.S (ffi_closure_v8): Reserve frame space for arguments. - -2004-10-27 Richard Earnshaw - - * src/arm/ffi.c (ffi_prep_cif_machdep): Handle functions that return - long long values. Round stack allocation to a multiple of 8 bytes - for ATPCS compatibility. - * src/arm/sysv.S (ffi_call_SYSV): Rework to avoid use of APCS register - names. Handle returning long long types. Add Thumb and interworking - support. Improve soft-float code. - -2004-10-27 Richard Earnshaw - - * testsuite/lib/libffi-db.exp (load_gcc_lib): New function. - (libffi_exit): New function. - (libffi_init): Build the testglue wrapper if needed. - -2004-10-25 Eric Botcazou - - PR other/18138 - * testsuite/lib/libffi-dg.exp: Accept more than one multilib libgcc. - -2004-10-25 Kazuhiro Inaoka - - * src/m32r/libffitarget.h (FFI_CLOSURES): Set to 0. - -2004-10-20 Kaz Kojima - - * src/sh/sysv.S (ffi_call_SYSV): Don't align for double data. - * testsuite/libffi.call/float3.c: New test case. - -2004-10-18 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_closure): Set T bit in trampoline for - the function returning a structure pointed with R2. - * src/sh/sysv.S (ffi_closure_SYSV): Use R2 as the pointer to - the structure return value if T bit set. Emit position - independent code and EH data if PIC. - -2004-10-13 Kazuhiro Inaoka - - * Makefile.am: Add m32r support. - * configure.ac: Likewise. - * Makefile.in: Regenerate. - * confiugre: Regenerate. - * src/types.c: Add m32r port to FFI_INTERNAL_TYPEDEF - (uint64, sint64, double, longdouble) - * src/m32r: New directory. - * src/m32r/ffi.c: New file. - * src/m32r/sysv.S: Likewise. - * src/m32r/ffitarget.h: Likewise. - -2004-10-02 Kaz Kojima - - * testsuite/libffi.call/negint.c: New test case. - -2004-09-14 H.J. Lu - - PR libgcj/17465 - * testsuite/lib/libffi-dg.exp: Don't use global ld_library_path. - Set up LD_LIBRARY_PATH, SHLIB_PATH, LD_LIBRARYN32_PATH, - LD_LIBRARY64_PATH, LD_LIBRARY_PATH_32, LD_LIBRARY_PATH_64 and - DYLD_LIBRARY_PATH. - -2004-09-05 Andreas Tobler - - * testsuite/libffi.call/many_win32.c: Remove whitespaces. - * testsuite/libffi.call/promotion.c: Likewise. - * testsuite/libffi.call/return_ll.c: Remove unused var. Cleanup - whitespaces. - * testsuite/libffi.call/return_sc.c: Likewise. - * testsuite/libffi.call/return_uc.c: Likewise. - -2004-09-05 Andreas Tobler - - * src/powerpc/darwin.S: Fix comments and identation. - * src/powerpc/darwin_closure.S: Likewise. - -2004-09-02 Andreas Tobler - - * src/powerpc/ffi_darwin.c: Add flag for longdouble return values. - (ffi_prep_args): Handle longdouble arguments. - (ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for - longdouble. - (ffi_closure_helper_DARWIN): Add closure handling for longdouble. - * src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble - values. - * src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise. - * src/types.c: Defined longdouble size and alignment for darwin. - -2004-09-02 Andreas Tobler - - * src/powerpc/aix.S: Remove whitespaces. - * src/powerpc/aix_closure.S: Likewise. - * src/powerpc/asm.h: Likewise. - * src/powerpc/ffi.c: Likewise. - * src/powerpc/ffitarget.h: Likewise. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/linux64_closure.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. - * src/powerpc/sysv.S: Likewise. - -2004-08-30 Anthony Green - - * Makefile.am: Add frv support. - * Makefile.in, testsuite/Makefile.in: Rebuilt. - * configure.ac: Read configure.host. - * configure.in: Read configure.host. - * configure.host: New file. frv-elf needs libgloss. - * include/ffi.h.in: Force ffi_closure to have a nice big (8) - alignment. This is needed to frv and shouldn't harm the others. - * include/ffi_common.h (ALIGN_DOWN): New macro. - * src/frv/ffi.c, src/frv/ffitarget.h, src/frv/eabi.S: New files. - -2004-08-24 David Daney - - * testsuite/libffi.call/closure_fn0.c: Xfail mips64* instead of mips*. - * testsuite/libffi.call/closure_fn1.c: Likewise. - * testsuite/libffi.call/closure_fn2.c Likewise. - * testsuite/libffi.call/closure_fn3.c: Likewise. - * testsuite/libffi.call/closure_fn4.c: Likewise. - * testsuite/libffi.call/closure_fn5.c: Likewise. - * testsuite/libffi.call/cls_18byte.c: Likewise. - * testsuite/libffi.call/cls_19byte.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_20byte1.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_64byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_9byte1.c: Likewise. - * testsuite/libffi.call/cls_9byte2.c: Likewise. - * testsuite/libffi.call/cls_align_double.c: Likewise. - * testsuite/libffi.call/cls_align_float.c: Likewise. - * testsuite/libffi.call/cls_align_longdouble.c: Likewise. - * testsuite/libffi.call/cls_align_pointer.c: Likewise. - * testsuite/libffi.call/cls_align_sint16.c: Likewise. - * testsuite/libffi.call/cls_align_sint32.c: Likewise. - * testsuite/libffi.call/cls_align_sint64.c: Likewise. - * testsuite/libffi.call/cls_align_uint16.c: Likewise. - * testsuite/libffi.call/cls_align_uint32.c: Likewise. - * testsuite/libffi.call/cls_align_uint64.c: Likewise. - * testsuite/libffi.call/cls_double.c: Likewise. - * testsuite/libffi.call/cls_float.c: Likewise. - * testsuite/libffi.call/cls_multi_schar.c: Likewise. - * testsuite/libffi.call/cls_multi_sshort.c: Likewise. - * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. - * testsuite/libffi.call/cls_multi_uchar.c: Likewise. - * testsuite/libffi.call/cls_multi_ushort.c: Likewise. - * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. - * testsuite/libffi.call/cls_schar.c: Likewise. - * testsuite/libffi.call/cls_sint.c: Likewise. - * testsuite/libffi.call/cls_sshort.c: Likewise. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/nested_struct.c: Likewise. - * testsuite/libffi.call/nested_struct1.c: Likewise. - * testsuite/libffi.call/nested_struct2.c: Likewise. - * testsuite/libffi.call/nested_struct3.c: Likewise. - * testsuite/libffi.call/problem1.c: Likewise. - * testsuite/libffi.special/unwindtest.cc: Likewise. - * testsuite/libffi.call/cls_12byte.c: Likewise and set return value - to zero. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - -2004-08-23 David Daney - - PR libgcj/13141 - * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. - * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. - (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point - parameters and return types. - (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. - (ffi_prep_closure): Ditto. - (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix - alignment calculations. - * src/mips/o32.S (ffi_closure_O32): Don't use floating point - instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. - -2004-08-14 Casey Marshall - - * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to - contain `FFI_TYPE_UINT64' as return type for any 64-bit - integer (O32 ABI only). - (ffi_prep_closure): new function. - (ffi_closure_mips_inner_O32): new function. - * src/mips/ffitarget.h: Define `FFI_CLOSURES' and - `FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32. - * src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return - 64 bit integers correctly. - (ffi_closure_O32): new function. - Added DWARF-2 unwind info for both functions. - -2004-08-10 Andrew Haley - - * src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments. - -2004-08-01 Robert Millan - - * configure.ac: Detect knetbsd-gnu and kfreebsd-gnu. - * configure: Regenerate. - -2004-07-30 Maciej W. Rozycki - - * acinclude.m4 (AC_FUNC_MMAP_BLACKLIST): Check for - and mmap() explicitly instead of relying on preset autoconf cache - variables. - * aclocal.m4: Regenerate. - * configure: Regenerate. - -2004-07-11 Ulrich Weigand - - * src/s390/ffi.c (ffi_prep_args): Fix C aliasing violation. - (ffi_check_float_struct): Remove unused prototype. - -2004-06-30 Geoffrey Keating - - * src/powerpc/ffi_darwin.c (flush_icache): ';' is a comment - character on Darwin, use '\n\t' instead. - -2004-06-26 Matthias Klose - - * libtool-version: Fix typo in revision/age. - -2004-06-17 Matthias Klose - - * libtool-version: New. - * Makefile.am (libffi_la_LDFLAGS): Use -version-info for soname. - * Makefile.in: Regenerate. - -2004-06-15 Paolo Bonzini - - * Makefile.am: Remove useless multilib rules. - * Makefile.in: Regenerate. - * aclocal.m4: Regenerate with automake 1.8.5. - * configure.ac: Remove useless multilib configury. - * configure: Regenerate. - -2004-06-15 Paolo Bonzini - - * .cvsignore: New file. - -2004-06-10 Jakub Jelinek - - * src/ia64/unix.S (ffi_call_unix): Insert group barrier break - fp_done. - (ffi_closure_UNIX): Fix f14/f15 adjustment if FLOAT_SZ is ever - changed from 8. - -2004-06-06 Sean McNeil - - * configure.ac: Add x86_64-*-freebsd* support. - * configure: Regenerate. - -2004-04-26 Joe Buck - - Bug 15093 - * configure.ac: Test for existence of mmap and sys/mman.h before - checking blacklist. Fix suggested by Jim Wilson. - * configure: Regenerate. - -2004-04-26 Matt Austern - - * src/powerpc/darwin.S: Go through a non-lazy pointer for initial - FDE location. - * src/powerpc/darwin_closure.S: Likewise. - -2004-04-24 Andreas Tobler - - * testsuite/libffi.call/cls_multi_schar.c (main): Fix initialization - error. Reported by Thomas Heller . - * testsuite/libffi.call/cls_multi_sshort.c (main): Likewise. - * testsuite/libffi.call/cls_multi_ushort.c (main): Likewise. - -2004-03-20 Matthias Klose - - * src/pa/linux.S: Fix typo. - -2004-03-19 Matthias Klose - - * Makefile.am: Update. - * Makefile.in: Regenerate. - * src/pa/ffi.h.in: Remove. - * src/pa/ffitarget.h: New file. - -2004-02-10 Randolph Chung - - * Makefile.am: Add PA support. - * Makefile.in: Regenerate. - * include/Makefile.in: Regenerate. - * configure.ac: Add PA target. - * configure: Regenerate. - * src/pa/ffi.c: New file. - * src/pa/ffi.h.in: Add PA support. - * src/pa/linux.S: New file. - * prep_cif.c: Add PA support. - -2004-03-16 Hosaka Yuji - - * src/types.c: Fix alignment size of X86_WIN32 case int64 and - double. - * src/x86/ffi.c (ffi_prep_args): Replace ecif->cif->rtype->type - with ecif->cif->flags. - (ffi_call, ffi_prep_incoming_args_SYSV): Replace cif->rtype->type - with cif->flags. - (ffi_prep_cif_machdep): Add X86_WIN32 struct case. - (ffi_closure_SYSV): Add 1 or 2-bytes struct case for X86_WIN32. - * src/x86/win32.S (retstruct1b, retstruct2b, sc_retstruct1b, - sc_retstruct2b): Add for 1 or 2-bytes struct case. - -2004-03-15 Kelley Cook - - * configure.in: Rename file to ... - * configure.ac: ... this. - * fficonfig.h.in: Regenerate. - * Makefile.in: Regenerate. - * include/Makefile.in: Regenerate. - * testsuite/Makefile.in: Regenerate. - -2004-03-12 Matt Austern - - * src/powerpc/darwin.S: Fix EH information so it corresponds to - changes in EH format resulting from addition of linkonce support. - * src/powerpc/darwin_closure.S: Likewise. - -2004-03-11 Andreas Tobler - Paolo Bonzini - - * Makefile.am (AUTOMAKE_OPTIONS): Set them. - Remove VPATH. Remove rules for object files. Remove multilib support. - (AM_CCASFLAGS): Add. - * configure.in (AC_CONFIG_HEADERS): Relace AM_CONFIG_HEADER. - (AC_PREREQ): Bump version to 2.59. - (AC_INIT): Fill with version info and bug address. - (ORIGINAL_LD_FOR_MULTILIBS): Remove. - (AM_ENABLE_MULTILIB): Use this instead of AC_ARG_ENABLE. - De-precious CC so that the right flags are passed down to multilibs. - (AC_MSG_ERROR): Replace obsolete macro AC_ERROR. - (AC_CONFIG_FILES): Replace obsolete macro AC_LINK_FILES. - (AC_OUTPUT): Reorganize the output with AC_CONFIG_COMMANDS. - * configure: Rebuilt. - * aclocal.m4: Likewise. - * Makefile.in, include/Makefile.in, testsuite/Makefile.in: Likewise. - * fficonfig.h.in: Likewise. - -2004-03-11 Andreas Schwab - - * src/ia64/ffi.c (ffi_prep_incoming_args_UNIX): Get floating point - arguments from fp registers only for the first 8 parameter slots. - Don't convert a float parameter when passed in memory. - -2004-03-09 Hans-Peter Nilsson - - * configure: Regenerate for config/accross.m4 correction. - -2004-02-25 Matt Kraai - - * src/powerpc/ffi.c (ffi_prep_args_SYSV): Change - ecif->cif->bytes to bytes. - (ffi_prep_cif_machdep): Add braces around nested if statement. - -2004-02-09 Alan Modra - - * src/types.c (pointer): POWERPC64 has 8 byte pointers. - - * src/powerpc/ffi.c (ffi_prep_args64): Correct long double handling. - (ffi_closure_helper_LINUX64): Fix typo. - * testsuite/libffi.call/cls_align_longdouble.c: Pass -mlong-double-128 - for powerpc64-*-*. - * testsuite/libffi.call/float.c: Likewise. - * testsuite/libffi.call/float2.c: Likewise. - -2004-02-08 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_cif_machdep ): Correct - long double function return and long double arg handling. - (ffi_closure_helper_LINUX64): Formatting. Delete unused "ng" var. - Use "end_pfr" instead of "nf". Correct long double handling. - Localise "temp". - * src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double - return value. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate - space for long double return value. Adjust stack frame and offsets. - Load f2 long double return. - -2004-02-07 Alan Modra - - * src/types.c: Use 16 byte long double for POWERPC64. - -2004-01-25 Eric Botcazou - - * src/sparc/ffi.c (ffi_prep_args_v9): Shift the parameter array - when the structure return address is passed in %o0. - (ffi_V9_return_struct): Rename into ffi_v9_layout_struct. - (ffi_v9_layout_struct): Align the field following a nested structure - on a word boundary. Use memmove instead of memcpy. - (ffi_call): Update call to ffi_V9_return_struct. - (ffi_prep_closure): Define 'ctx' only for V8. - (ffi_closure_sparc_inner): Clone into ffi_closure_sparc_inner_v8 - and ffi_closure_sparc_inner_v9. - (ffi_closure_sparc_inner_v8): Return long doubles by reference. - Always skip the structure return address. For structures and long - doubles, copy the argument directly. - (ffi_closure_sparc_inner_v9): Skip the structure return address only - if required. Shift the maximum floating-point slot accordingly. For - big structures, copy the argument directly; otherwise, left-justify the - argument and call ffi_v9_layout_struct to lay out the structure on - the stack. - * src/sparc/v8.S: Undef STACKFRAME before defining it. - (ffi_closure_v8): Pass the structure return address. Update call to - ffi_closure_sparc_inner_v8. Short-circuit FFI_TYPE_INT handling. - Skip the 'unimp' insn when returning long doubles and structures. - * src/sparc/v9.S: Undef STACKFRAME before defining it. - (ffi_closure_v9): Increase the frame size by 2 words. Short-circuit - FFI_TYPE_INT handling. Load structures both in integers and - floating-point registers on return. - * README: Update status of the SPARC port. - -2004-01-24 Andreas Tobler - - * testsuite/libffi.call/pyobjc-tc.c (main): Treat result value - as of type ffi_arg. - * testsuite/libffi.call/struct3.c (main): Fix CHECK. - -2004-01-22 Ulrich Weigand - - * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Treat result - value as of type ffi_arg, not unsigned int. - -2004-01-21 Michael Ritzert - - * ffi64.c (ffi_prep_args): Cast the RHS of an assignment instead - of the LHS. - -2004-01-12 Andreas Tobler - - * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_32 for - Solaris. - -2004-01-08 Rainer Orth - - * testsuite/libffi.call/ffitest.h (allocate_mmap): Cast MAP_FAILED - to void *. - -2003-12-10 Richard Henderson - - * testsuite/libffi.call/cls_align_pointer.c: Cast pointers to - size_t instead of int. - -2003-12-04 Hosaka Yuji - - * testsuite/libffi.call/many_win32.c: Include . - * testsuite/libffi.call/many_win32.c (main): Replace variable - int i with unsigned long ul. - - * testsuite/libffi.call/cls_align_uint64.c: New test case. - * testsuite/libffi.call/cls_align_sint64.c: Likewise. - * testsuite/libffi.call/cls_align_uint32.c: Likewise. - * testsuite/libffi.call/cls_align_sint32.c: Likewise. - * testsuite/libffi.call/cls_align_uint16.c: Likewise. - * testsuite/libffi.call/cls_align_sint16.c: Likewise. - * testsuite/libffi.call/cls_align_float.c: Likewise. - * testsuite/libffi.call/cls_align_double.c: Likewise. - * testsuite/libffi.call/cls_align_longdouble.c: Likewise. - * testsuite/libffi.call/cls_align_pointer.c: Likewise. - -2003-12-02 Hosaka Yuji - - PR other/13221 - * src/x86/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): - Align arguments to 32 bits. - -2003-12-01 Andreas Tobler - - PR other/13221 - * testsuite/libffi.call/cls_multi_sshort.c: New test case. - * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. - * testsuite/libffi.call/cls_multi_uchar.c: Likewise. - * testsuite/libffi.call/cls_multi_schar.c: Likewise. - * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. - * testsuite/libffi.call/cls_multi_ushort.c: Likewise. - - * testsuite/libffi.special/unwindtest.cc: Cosmetics. - -2003-11-26 Kaveh R. Ghazi - - * testsuite/libffi.call/ffitest.h: Include . - * testsuite/libffi.special/ffitestcxx.h: Likewise. - -2003-11-22 Andreas Tobler - - * Makefile.in: Rebuilt. - * configure: Likewise. - * testsuite/libffi.special/unwindtest.cc: Convert the mmap to - the right type. - -2003-11-21 Andreas Jaeger - Andreas Tobler - - * acinclude.m4: Add AC_FUNC_MMAP_BLACKLIST. - * configure.in: Call AC_FUNC_MMAP_BLACKLIST. - * Makefile.in: Rebuilt. - * aclocal.m4: Likewise. - * configure: Likewise. - * fficonfig.h.in: Likewise. - * testsuite/lib/libffi-dg.exp: Add include dir. - * testsuite/libffi.call/ffitest.h: Add MMAP definitions. - * testsuite/libffi.special/ffitestcxx.h: Likewise. - * testsuite/libffi.call/closure_fn0.c: Use MMAP functionality - for ffi_closure if available. - * testsuite/libffi.call/closure_fn1.c: Likewise. - * testsuite/libffi.call/closure_fn2.c: Likewise. - * testsuite/libffi.call/closure_fn3.c: Likewise. - * testsuite/libffi.call/closure_fn4.c: Likewise. - * testsuite/libffi.call/closure_fn5.c: Likewise. - * testsuite/libffi.call/cls_12byte.c: Likewise. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_18byte.c: Likewise. - * testsuite/libffi.call/cls_19byte.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_20byte1.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - * testsuite/libffi.call/cls_64byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_9byte1.c: Likewise. - * testsuite/libffi.call/cls_9byte2.c: Likewise. - * testsuite/libffi.call/cls_double.c: Likewise. - * testsuite/libffi.call/cls_float.c: Likewise. - * testsuite/libffi.call/cls_schar.c: Likewise. - * testsuite/libffi.call/cls_sint.c: Likewise. - * testsuite/libffi.call/cls_sshort.c: Likewise. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/nested_struct.c: Likewise. - * testsuite/libffi.call/nested_struct1.c: Likewise. - * testsuite/libffi.call/nested_struct2.c: Likewise. - * testsuite/libffi.call/nested_struct3.c: Likewise. - * testsuite/libffi.call/problem1.c: Likewise. - * testsuite/libffi.special/unwindtest.cc: Likewise. - -2003-11-20 Andreas Tobler - - * testsuite/lib/libffi-dg.exp: Make the -lgcc_s conditional. - -2003-11-19 Andreas Tobler - - * testsuite/lib/libffi-dg.exp: Add DYLD_LIBRARY_PATH for darwin. - Add -lgcc_s to additional flags. - -2003-11-12 Andreas Tobler - - * configure.in, include/Makefile.am: PR libgcj/11147, install - the ffitarget.h header file in a gcc versioned and target - dependent place. - * configure: Regenerated. - * Makefile.in, include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - -2003-11-09 Andreas Tobler - - * testsuite/libffi.call/closure_fn0.c: Print result and check - with dg-output to make debugging easier. - * testsuite/libffi.call/closure_fn1.c: Likewise. - * testsuite/libffi.call/closure_fn2.c: Likewise. - * testsuite/libffi.call/closure_fn3.c: Likewise. - * testsuite/libffi.call/closure_fn4.c: Likewise. - * testsuite/libffi.call/closure_fn5.c: Likewise. - * testsuite/libffi.call/cls_12byte.c: Likewise. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_18byte.c: Likewise. - * testsuite/libffi.call/cls_19byte.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_20byte1.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - * testsuite/libffi.call/cls_64byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_9byte1.c: Likewise. - * testsuite/libffi.call/cls_9byte2.c: Likewise. - * testsuite/libffi.call/cls_double.c: Likewise. - * testsuite/libffi.call/cls_float.c: Likewise. - * testsuite/libffi.call/cls_schar.c: Likewise. - * testsuite/libffi.call/cls_sint.c: Likewise. - * testsuite/libffi.call/cls_sshort.c: Likewise. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/problem1.c: Likewise. - - * testsuite/libffi.special/unwindtest.cc: Make ffi_closure - static. - -2003-11-08 Andreas Tobler - - * testsuite/libffi.call/cls_9byte2.c: New test case. - * testsuite/libffi.call/cls_9byte1.c: Likewise. - * testsuite/libffi.call/cls_64byte.c: Likewise. - * testsuite/libffi.call/cls_20byte1.c: Likewise. - * testsuite/libffi.call/cls_19byte.c: Likewise. - * testsuite/libffi.call/cls_18byte.c: Likewise. - * testsuite/libffi.call/closure_fn4.c: Likewise. - * testsuite/libffi.call/closure_fn5.c: Likewise. - * testsuite/libffi.call/cls_schar.c: Likewise. - * testsuite/libffi.call/cls_sint.c: Likewise. - * testsuite/libffi.call/cls_sshort.c: Likewise. - * testsuite/libffi.call/nested_struct2.c: Likewise. - * testsuite/libffi.call/nested_struct3.c: Likewise. - -2003-11-08 Andreas Tobler - - * testsuite/libffi.call/cls_double.c: Do a check on the result. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/return_sc.c: Cleanup whitespaces. - -2003-11-06 Andreas Tobler - - * src/prep_cif.c (ffi_prep_cif): Move the validity check after - the initialization. - -2003-10-23 Andreas Tobler - - * src/java_raw_api.c (ffi_java_ptrarray_to_raw): Replace - FFI_ASSERT(FALSE) with FFI_ASSERT(0). - -2003-10-22 David Daney - - * src/mips/ffitarget.h: Replace undefined UINT32 and friends with - __attribute__((__mode__(__SI__))) and friends. - -2003-10-22 Andreas Schwab - - * src/ia64/ffi.c: Replace FALSE/TRUE with false/true. - -2003-10-21 Andreas Tobler - - * configure.in: AC_LINK_FILES(ffitarget.h). - * configure: Regenerate. - * Makefile.in: Likewise. - * include/Makefile.in: Likewise. - * testsuite/Makefile.in: Likewise. - * fficonfig.h.in: Likewise. - -2003-10-21 Paolo Bonzini - Richard Henderson - - Avoid that ffi.h includes fficonfig.h. - - * Makefile.am (EXTRA_DIST): Include ffitarget.h files - (TARGET_SRC_MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. - (TARGET_SRC_MIPS_SGI): Removed. - (MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. - (MIPS_SGI): Removed. - (CLEANFILES): Removed. - (mostlyclean-am, clean-am, mostlyclean-sub, clean-sub): New - targets. - * acconfig.h: Removed. - * configure.in: Compute sizeofs only for double and long double. - Use them to define and subst HAVE_LONG_DOUBLE. Include comments - into AC_DEFINE instead of using acconfig.h. Create - include/ffitarget.h instead of include/fficonfig.h. Rename - MIPS_GCC to MIPS_IRIX, drop MIPS_SGI since we are in gcc's tree. - AC_DEFINE EH_FRAME_FLAGS. - * include/Makefile.am (DISTCLEANFILES): New automake macro. - (hack_DATA): Add ffitarget.h. - * include/ffi.h.in: Remove all system specific definitions. - Declare raw API even if it is not installed, why bother? - Use limits.h instead of SIZEOF_* to define ffi_type_*. Do - not define EH_FRAME_FLAGS, it is in fficonfig.h now. Include - ffitarget.h instead of fficonfig.h. Remove ALIGN macro. - (UINT_ARG, INT_ARG): Removed, use ffi_arg and ffi_sarg instead. - * include/ffi_common.h (bool): Do not define. - (ffi_assert): Accept failed assertion. - (ffi_type_test): Return void and accept file/line. - (FFI_ASSERT): Pass stringized failed assertion. - (FFI_ASSERT_AT): New macro. - (FFI_ASSERT_VALID_TYPE): New macro. - (UINT8, SINT8, UINT16, SINT16, UINT32, SINT32, - UINT64, SINT64): Define here with gcc's __attribute__ macro - instead of in ffi.h - (FLOAT32, ALIGN): Define here instead of in ffi.h - * include/ffi-mips.h: Removed. Its content moved to - src/mips/ffitarget.h after separating assembly and C sections. - * src/alpha/ffi.c, src/alpha/ffi.c, src/java_raw_api.c - src/prep_cif.c, src/raw_api.c, src/ia64/ffi.c, - src/mips/ffi.c, src/mips/n32.S, src/mips/o32.S, - src/mips/ffitarget.h, src/sparc/ffi.c, src/x86/ffi64.c: - SIZEOF_ARG -> FFI_SIZEOF_ARG. - * src/ia64/ffi.c: Include stdbool.h (provided by GCC 2.95+). - * src/debug.c (ffi_assert): Accept stringized failed assertion. - (ffi_type_test): Rewritten. - * src/prep-cif.c (initialize_aggregate, ffi_prep_cif): Call - FFI_ASSERT_VALID_TYPE. - * src/alpha/ffitarget.h, src/arm/ffitarget.h, - src/ia64/ffitarget.h, src/m68k/ffitarget.h, - src/mips/ffitarget.h, src/powerpc/ffitarget.h, - src/s390/ffitarget.h, src/sh/ffitarget.h, - src/sh64/ffitarget.h, src/sparc/ffitarget.h, - src/x86/ffitarget.h: New files. - * src/alpha/osf.S, src/arm/sysv.S, src/ia64/unix.S, - src/m68k/sysv.S, src/mips/n32.S, src/mips/o32.S, - src/powerpc/aix.S, src/powerpc/darwin.S, - src/powerpc/ffi_darwin.c, src/powerpc/linux64.S, - src/powerpc/linux64_closure.S, src/powerpc/ppc_closure.S, - src/powerpc/sysv.S, src/s390/sysv.S, src/sh/sysv.S, - src/sh64/sysv.S, src/sparc/v8.S, src/sparc/v9.S, - src/x86/sysv.S, src/x86/unix64.S, src/x86/win32.S: - include fficonfig.h - -2003-10-20 Rainer Orth - - * src/mips/ffi.c: Use _ABIN32, _ABIO32 instead of external - _MIPS_SIM_NABI32, _MIPS_SIM_ABI32. - -2003-10-19 Andreas Tobler - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Declare bytes again. - Used when FFI_DEBUG = 1. - -2003-10-14 Alan Modra - - * src/types.c (double, longdouble): Default POWERPC64 to 8 byte size - and align. - -2003-10-06 Rainer Orth - - * include/ffi_mips.h: Define FFI_MIPS_N32 for N32/N64 ABIs, - FFI_MIPS_O32 for O32 ABI. - -2003-10-01 Andreas Tobler - - * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_64 for - SPARC64. Cleanup whitespaces. - -2003-09-19 Andreas Tobler - - * testsuite/libffi.call/closure_fn0.c: Xfail mips, arm, - strongarm, xscale. Cleanup whitespaces. - * testsuite/libffi.call/closure_fn1.c: Likewise. - * testsuite/libffi.call/closure_fn2.c: Likewise. - * testsuite/libffi.call/closure_fn3.c: Likewise. - * testsuite/libffi.call/cls_12byte.c: Likewise. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_double.c: Likewise. - * testsuite/libffi.call/cls_float.c: Likewise. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/nested_struct.c: Likewise. - * testsuite/libffi.call/nested_struct1.c: Likewise. - * testsuite/libffi.call/problem1.c: Likewise. - * testsuite/libffi.special/unwindtest.cc: Likewise. - * testsuite/libffi.call/pyobjc-tc.c: Cleanup whitespaces. - -2003-09-18 David Edelsohn - - * src/powerpc/aix.S: Cleanup whitespaces. - * src/powerpc/aix_closure.S: Likewise. - -2003-09-18 Andreas Tobler - - * src/powerpc/darwin.S: Cleanup whitespaces, comment formatting. - * src/powerpc/darwin_closure.S: Likewise. - * src/powerpc/ffi_darwin.c: Likewise. - -2003-09-18 Andreas Tobler - David Edelsohn - - * src/types.c (double): Add AIX and Darwin to the right TYPEDEF. - * src/powerpc/aix_closure.S: Remove the pointer to the outgoing - parameter stack. - * src/powerpc/darwin_closure.S: Likewise. - * src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures - according to the Darwin/AIX ABI. - (ffi_prep_cif_machdep): Likewise. - (ffi_closure_helper_DARWIN): Likewise. - Remove the outgoing parameter stack logic. Simplify the evaluation - of the different CASE types. - (ffi_prep_clousure): Avoid the casts on lvalues. Change the branch - statement in the trampoline code. - -2003-09-18 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_args): Take account into the alignement - for the register size. - (ffi_closure_helper_SYSV): Handle the structure return value - address correctly. - (ffi_closure_helper_SYSV): Return the appropriate type when - the registers are used for the structure return value. - * src/sh/sysv.S (ffi_closure_SYSV): Fix the stack layout for - the 64-bit return value. Update copyright years. - -2003-09-17 Rainer Orth - - * testsuite/lib/libffi-dg.exp (libffi_target_compile): Search in - srcdir for ffi_mips.h. - -2003-09-12 Alan Modra - - * src/prep_cif.c (initialize_aggregate): Include tail padding in - structure size. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Correct - placement of float result. - * testsuite/libffi.special/unwindtest.cc (closure_test_fn1): Correct - cast of "resp" for big-endian 64 bit machines. - -2003-09-11 Alan Modra - - * src/types.c (double, longdouble): Merge identical SH and ARM - typedefs, and add POWERPC64. - * src/powerpc/ffi.c (ffi_prep_args64): Correct next_arg calc for - struct split over gpr and rest. - (ffi_prep_cif_machdep): Correct intarg_count for structures. - * src/powerpc/linux64.S (ffi_call_LINUX64): Fix gpr offsets. - -2003-09-09 Andreas Tobler - - * src/powerpc/ffi.c (ffi_closure_helper_SYSV) Handle struct - passing correctly. - -2003-09-09 Alan Modra - - * configure: Regenerate. - -2003-09-04 Andreas Tobler - - * Makefile.am: Remove build rules for ffitest. - * Makefile.in: Rebuilt. - -2003-09-04 Andreas Tobler - - * src/java_raw_api.c: Include to fix compiler warning - about implicit declaration of abort(). - -2003-09-04 Andreas Tobler - - * Makefile.am: Add dejagnu test framework. Fixes PR other/11411. - * Makefile.in: Rebuilt. - * configure.in: Add dejagnu test framework. - * configure: Rebuilt. - - * testsuite/Makefile.am: New file. - * testsuite/Makefile.in: Built - * testsuite/lib/libffi-dg.exp: New file. - * testsuite/config/default.exp: Likewise. - * testsuite/libffi.call/call.exp: Likewise. - * testsuite/libffi.call/ffitest.h: Likewise. - * testsuite/libffi.call/closure_fn0.c: Likewise. - * testsuite/libffi.call/closure_fn1.c: Likewise. - * testsuite/libffi.call/closure_fn2.c: Likewise. - * testsuite/libffi.call/closure_fn3.c: Likewise. - * testsuite/libffi.call/cls_1_1byte.c: Likewise. - * testsuite/libffi.call/cls_3_1byte.c: Likewise. - * testsuite/libffi.call/cls_4_1byte.c: Likewise. - * testsuite/libffi.call/cls_2byte.c: Likewise. - * testsuite/libffi.call/cls_3byte1.c: Likewise. - * testsuite/libffi.call/cls_3byte2.c: Likewise. - * testsuite/libffi.call/cls_4byte.c: Likewise. - * testsuite/libffi.call/cls_5byte.c: Likewise. - * testsuite/libffi.call/cls_6byte.c: Likewise. - * testsuite/libffi.call/cls_7byte.c: Likewise. - * testsuite/libffi.call/cls_8byte.c: Likewise. - * testsuite/libffi.call/cls_12byte.c: Likewise. - * testsuite/libffi.call/cls_16byte.c: Likewise. - * testsuite/libffi.call/cls_20byte.c: Likewise. - * testsuite/libffi.call/cls_24byte.c: Likewise. - * testsuite/libffi.call/cls_double.c: Likewise. - * testsuite/libffi.call/cls_float.c: Likewise. - * testsuite/libffi.call/cls_uchar.c: Likewise. - * testsuite/libffi.call/cls_uint.c: Likewise. - * testsuite/libffi.call/cls_ulonglong.c: Likewise. - * testsuite/libffi.call/cls_ushort.c: Likewise. - * testsuite/libffi.call/float.c: Likewise. - * testsuite/libffi.call/float1.c: Likewise. - * testsuite/libffi.call/float2.c: Likewise. - * testsuite/libffi.call/many.c: Likewise. - * testsuite/libffi.call/many_win32.c: Likewise. - * testsuite/libffi.call/nested_struct.c: Likewise. - * testsuite/libffi.call/nested_struct1.c: Likewise. - * testsuite/libffi.call/pyobjc-tc.c: Likewise. - * testsuite/libffi.call/problem1.c: Likewise. - * testsuite/libffi.call/promotion.c: Likewise. - * testsuite/libffi.call/return_ll.c: Likewise. - * testsuite/libffi.call/return_sc.c: Likewise. - * testsuite/libffi.call/return_uc.c: Likewise. - * testsuite/libffi.call/strlen.c: Likewise. - * testsuite/libffi.call/strlen_win32.c: Likewise. - * testsuite/libffi.call/struct1.c: Likewise. - * testsuite/libffi.call/struct2.c: Likewise. - * testsuite/libffi.call/struct3.c: Likewise. - * testsuite/libffi.call/struct4.c: Likewise. - * testsuite/libffi.call/struct5.c: Likewise. - * testsuite/libffi.call/struct6.c: Likewise. - * testsuite/libffi.call/struct7.c: Likewise. - * testsuite/libffi.call/struct8.c: Likewise. - * testsuite/libffi.call/struct9.c: Likewise. - * testsuite/libffi.special/special.exp: New file. - * testsuite/libffi.special/ffitestcxx.h: Likewise. - * testsuite/libffi.special/unwindtest.cc: Likewise. - - -2003-08-13 Kaz Kojima - - * src/sh/ffi.c (OFS_INT16): Set 0 for little endian case. Update - copyright years. - -2003-08-02 Alan Modra - - * src/powerpc/ffi.c (ffi_prep_args64): Modify for changed gcc - structure passing. - (ffi_closure_helper_LINUX64): Likewise. - * src/powerpc/linux64.S: Remove code writing to parm save area. - * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Use return - address in lr from ffi_closure_helper_LINUX64 call to calculate - table address. Optimize function tail. - -2003-07-28 Andreas Tobler - - * src/sparc/ffi.c: Handle all floating point registers. - * src/sparc/v9.S: Likewise. Fixes second part of PR target/11410. - -2003-07-11 Gerald Pfeifer - - * README: Note that libffi is not part of GCC. Update the project - URL and status. - -2003-06-19 Franz Sirl - - * src/powerpc/ppc_closure.S: Include ffi.h. - -2003-06-13 Rainer Orth - - * src/x86/sysv.S: Avoid gas-only .uleb128/.sleb128 directives. - Use C style comments. - -2003-06-13 Kaz Kojima - - * Makefile.am: Add SHmedia support. Fix a typo of SH support. - * Makefile.in: Regenerate. - * configure.in (sh64-*-linux*, sh5*-*-linux*): Add target. - * configure: Regenerate. - * include/ffi.h.in: Add SHmedia support. - * src/sh64/ffi.c: New file. - * src/sh64/sysv.S: New file. - -2003-05-16 Jakub Jelinek - - * configure.in (HAVE_RO_EH_FRAME): Check whether .eh_frame section - should be read-only. - * configure: Rebuilt. - * fficonfig.h.in: Rebuilt. - * include/ffi.h.in (EH_FRAME_FLAGS): Define. - * src/alpha/osf.S: Use EH_FRAME_FLAGS. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/linux64_closure.S: Likewise. Include ffi.h. - * src/powerpc/sysv.S: Use EH_FRAME_FLAGS. Use pcrel encoding - if -fpic/-fPIC/-mrelocatable. - * src/powerpc/powerpc_closure.S: Likewise. - * src/sparc/v8.S: If HAVE_RO_EH_FRAME is defined, don't include - #write in .eh_frame flags. - * src/sparc/v9.S: Likewise. - * src/x86/unix64.S: Use EH_FRAME_FLAGS. - * src/x86/sysv.S: Likewise. Use pcrel encoding if -fpic/-fPIC. - * src/s390/sysv.S: Use EH_FRAME_FLAGS. Include ffi.h. - -2003-05-07 Jeff Sturm - - Fixes PR bootstrap/10656 - * configure.in (HAVE_AS_REGISTER_PSEUDO_OP): Test assembler - support for .register pseudo-op. - * src/sparc/v8.S: Use it. - * fficonfig.h.in: Rebuilt. - * configure: Rebuilt. - -2003-04-18 Jakub Jelinek - - * include/ffi.h.in (POWERPC64): Define if 64-bit. - (enum ffi_abi): Add FFI_LINUX64 on POWERPC. - Make it the default on POWERPC64. - (FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64. - * configure.in: Change powerpc-*-linux* into powerpc*-*-linux*. - * configure: Rebuilt. - * src/powerpc/ffi.c (hidden): Define. - (ffi_prep_args_SYSV): Renamed from - ffi_prep_args. Cast pointers to unsigned long to shut up warnings. - (NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64, - ASM_NEEDS_REGISTERS64): New. - (ffi_prep_args64): New function. - (ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI. - (ffi_call): Likewise. - (ffi_prep_closure): Likewise. - (flush_icache): Surround by #ifndef POWERPC64. - (ffi_dblfl): New union type. - (ffi_closure_helper_SYSV): Use it to avoid aliasing problems. - (ffi_closure_helper_LINUX64): New function. - * src/powerpc/ppc_closure.S: Surround whole file by #ifndef - __powerpc64__. - * src/powerpc/sysv.S: Likewise. - (ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV. - * src/powerpc/linux64.S: New file. - * src/powerpc/linux64_closure.S: New file. - * Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and - src/powerpc/linux64_closure.S. - (TARGET_SRC_POWERPC): Likewise. - - * src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2, - closure_test_fn3): Fix result printing on big-endian 64-bit - machines. - (main): Print tst2_arg instead of uninitialized tst2_result. - - * src/ffitest.c (main): Hide what closure pointer really points to - from the compiler. - -2003-04-16 Richard Earnshaw - - * configure.in (arm-*-netbsdelf*): Add configuration. - (configure): Regenerated. - -2003-04-04 Loren J. Rittle - - * include/Makefile.in: Regenerate. - -2003-03-21 Zdenek Dvorak - - * libffi/include/ffi.h.in: Define X86 instead of X86_64 in 32 - bit mode. - * libffi/src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): - Receive closure pointer through parameter, read args using - __builtin_dwarf_cfa. - (FFI_INIT_TRAMPOLINE): Send closure reference through eax. - -2003-03-12 Andreas Schwab - - * configure.in: Avoid trailing /. in toolexeclibdir. - * configure: Rebuilt. - -2003-03-03 Andreas Tobler - - * src/powerpc/darwin_closure.S: Recode to fit dynamic libraries. - -2003-02-06 Andreas Tobler - - * libffi/src/powerpc/darwin_closure.S: - Fix alignement bug, allocate 8 bytes for the result. - * libffi/src/powerpc/aix_closure.S: - Likewise. - * libffi/src/powerpc/ffi_darwin.c: - Update stackframe description for aix/darwin_closure.S. - -2003-02-06 Jakub Jelinek - - * src/s390/ffi.c (ffi_closure_helper_SYSV): Add hidden visibility - attribute. - -2003-01-31 Christian Cornelssen , - Andreas Schwab - - * configure.in: Adjust command to source config-ml.in to account - for changes to the libffi_basedir definition. - (libffi_basedir): Remove ${srcdir} from value and include trailing - slash if nonempty. - - * configure: Regenerate. - -2003-01-29 Franz Sirl - - * src/powerpc/ppc_closure.S: Recode to fit shared libs. - -2003-01-28 Andrew Haley - - * include/ffi.h.in: Enable FFI_CLOSURES for x86_64. - * src/x86/ffi64.c (ffi_prep_closure): New. - (ffi_closure_UNIX64_inner): New. - * src/x86/unix64.S (ffi_closure_UNIX64): New. - -2003-01-27 Alexandre Oliva - - * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. - Remove USE_LIBDIR conditional. - * Makefile.am (toolexecdir, toolexeclibdir): Don't override. - * Makefile.in, configure: Rebuilt. - -2003-01027 David Edelsohn - - * Makefile.am (TARGET_SRC_POWERPC_AIX): Fix typo. - * Makefile.in: Regenerate. - -2003-01-22 Andrew Haley - - * src/powerpc/darwin.S (_ffi_call_AIX): Add Augmentation size to - unwind info. - -2003-01-21 Andreas Tobler - - * src/powerpc/darwin.S: Add unwind info. - * src/powerpc/darwin_closure.S: Likewise. - -2003-01-14 Andrew Haley - - * src/x86/ffi64.c (ffi_prep_args): Check for void retval. - (ffi_prep_cif_machdep): Likewise. - * src/x86/unix64.S: Add unwind info. - -2003-01-14 Andreas Jaeger - - * src/ffitest.c (main): Only use ffi_closures if those are - supported. - -2003-01-13 Andreas Tobler - - * libffi/src/ffitest.c - add closure testcases - -2003-01-13 Kevin B. Hendricks - - * libffi/src/powerpc/ffi.c - fix alignment bug for float (4 byte aligned iso 8 byte) - -2003-01-09 Geoffrey Keating - - * src/powerpc/ffi_darwin.c: Remove RCS version string. - * src/powerpc/darwin.S: Remove RCS version string. - -2003-01-03 Jeff Sturm - - * include/ffi.h.in: Add closure defines for SPARC, SPARC64. - * src/ffitest.c (main): Use static storage for closure. - * src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New. - * src/sparc/v8.S (ffi_closure_v8): New. - * src/sparc/v9.S (ffi_closure_v9): New. - -2002-11-10 Ranjit Mathew - - * include/ffi.h.in: Added FFI_STDCALL ffi_type - enumeration for X86_WIN32. - * src/x86/win32.S: Added ffi_call_STDCALL function - definition. - * src/x86/ffi.c (ffi_call/ffi_raw_call): Added - switch cases for recognising FFI_STDCALL and - calling ffi_call_STDCALL if target is X86_WIN32. - * src/ffitest.c (my_stdcall_strlen/stdcall_many): - stdcall versions of the "my_strlen" and "many" - test functions (for X86_WIN32). - Added test cases to test stdcall invocation using - these functions. - -2002-12-02 Kaz Kojima - - * src/sh/sysv.S: Add DWARF2 unwind info. - -2002-11-27 Ulrich Weigand - - * src/s390/sysv.S (.eh_frame section): Make section read-only. - -2002-11-26 Jim Wilson - - * src/types.c (FFI_TYPE_POINTER): Has size 8 on IA64. - -2002-11-23 H.J. Lu - - * acinclude.m4: Add dummy AM_PROG_LIBTOOL. - Include ../config/accross.m4. - * aclocal.m4; Rebuild. - * configure: Likewise. - -2002-11-15 Ulrich Weigand - - * src/s390/sysv.S (.eh_frame section): Adapt to pcrel FDE encoding. - -2002-11-11 DJ Delorie - - * configure.in: Look for common files in the right place. - -2002-10-08 Ulrich Weigand - - * src/java_raw_api.c (ffi_java_raw_to_ptrarray): Interpret - raw data as _Jv_word values, not ffi_raw. - (ffi_java_ptrarray_to_raw): Likewise. - (ffi_java_rvalue_to_raw): New function. - (ffi_java_raw_call): Call it. - (ffi_java_raw_to_rvalue): New function. - (ffi_java_translate_args): Call it. - * src/ffitest.c (closure_test_fn): Interpret return value - as ffi_arg, not int. - * src/s390/ffi.c (ffi_prep_cif_machdep): Add missing - FFI_TYPE_POINTER case. - (ffi_closure_helper_SYSV): Likewise. Also, assume return - values extended to word size. - -2002-10-02 Andreas Jaeger - - * src/x86/ffi64.c (ffi_prep_cif_machdep): Remove debug output. - -2002-10-01 Bo Thorsen - - * include/ffi.h.in: Fix i386 win32 compilation. - -2002-09-30 Ulrich Weigand - - * configure.in: Add s390x-*-linux-* target. - * configure: Regenerate. - * include/ffi.h.in: Define S390X for s390x targets. - (FFI_CLOSURES): Define for s390/s390x. - (FFI_TRAMPOLINE_SIZE): Likewise. - (FFI_NATIVE_RAW_API): Likewise. - * src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390. - * src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x. - * src/s390/ffi.c: Major rework of existing code. Add support for - s390x targets. Add closure support. - * src/s390/sysv.S: Likewise. - -2002-09-29 Richard Earnshaw - - * src/arm/sysv.S: Fix typo. - -2002-09-28 Richard Earnshaw - - * src/arm/sysv.S: If we don't have machine/asm.h and the pre-processor - has defined __USER_LABEL_PREFIX__, then use it in CNAME. - (ffi_call_SYSV): Handle soft-float. - -2002-09-27 Bo Thorsen - - * include/ffi.h.in: Fix multilib x86-64 support. - -2002-09-22 Kaveh R. Ghazi - - * Makefile.am (all-multi): Fix multilib parallel build. - -2002-07-19 Kaz Kojima - - * configure.in (sh[34]*-*-linux*): Add brackets. - * configure: Regenerate. - -2002-07-18 Kaz Kojima - - * Makefile.am: Add SH support. - * Makefile.in: Regenerate. - * configure.in (sh-*-linux*, sh[34]*-*-linux*): Add target. - * configure: Regenerate. - * include/ffi.h.in: Add SH support. - * src/sh/ffi.c: New file. - * src/sh/sysv.S: New file. - * src/types.c: Add SH support. - -2002-07-16 Bo Thorsen - - * src/x86/ffi64.c: New file that adds x86-64 support. - * src/x86/unix64.S: New file that handles argument setup for - x86-64. - * src/x86/sysv.S: Don't use this on x86-64. - * src/x86/ffi.c: Don't use this on x86-64. - Remove unused vars. - * src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation - for x86-64. - * src/ffitest.c (struct6): New test that tests a special case in - the x86-64 ABI. - (struct7): Likewise. - (struct8): Likewise. - (struct9): Likewise. - (closure_test_fn): Silence warning about this when it's not used. - (main): Add the new tests. - (main): Fix a couple of wrong casts and silence some compiler warnings. - * include/ffi.h.in: Add x86-64 ABI definition. - * fficonfig.h.in: Regenerate. - * Makefile.am: Add x86-64 support. - * configure.in: Likewise. - * Makefile.in: Regenerate. - * configure: Likewise. - -2002-06-24 Bo Thorsen - - * src/types.c: Merge settings for similar architectures. - Add x86-64 sizes and alignments. - -2002-06-23 Bo Thorsen - - * src/arm/ffi.c (ffi_prep_args): Remove unused vars. - * src/sparc/ffi.c (ffi_prep_args_v8): Likewise. - * src/mips/ffi.c (ffi_prep_args): Likewise. - * src/m68k/ffi.c (ffi_prep_args): Likewise. - -2002-07-18 H.J. Lu (hjl@gnu.org) - - * Makefile.am (TARGET_SRC_MIPS_LINUX): New. - (libffi_la_SOURCES): Support MIPS_LINUX. - (libffi_convenience_la_SOURCES): Likewise. - * Makefile.in: Regenerated. - - * configure.in (mips64*-*): Skip. - (mips*-*-linux*): New. - * configure: Regenerated. - - * src/mips/ffi.c: Include . - -2002-06-06 Ulrich Weigand - - * src/s390/sysv.S: Save/restore %r6. Add DWARF-2 unwind info. - -2002-05-27 Roger Sayle - - * src/x86/ffi.c (ffi_prep_args): Remove reference to avn. - -2002-05-27 Bo Thorsen - - * src/x86/ffi.c (ffi_prep_args): Remove unused variable and - fix formatting. - -2002-05-13 Andreas Tobler - - * src/powerpc/ffi_darwin.c (ffi_prep_closure): Declare fd at - beginning of function (for older apple cc). - -2002-05-08 Alexandre Oliva - - * configure.in (ORIGINAL_LD_FOR_MULTILIBS): Preserve LD at - script entry, and set LD to it when configuring multilibs. - * configure: Rebuilt. - -2002-05-05 Jason Thorpe - - * configure.in (sparc64-*-netbsd*): Add target. - (sparc-*-netbsdelf*): Likewise. - * configure: Regenerate. - -2002-04-28 David S. Miller - - * configure.in, configure: Fix SPARC test in previous change. - -2002-04-29 Gerhard Tonn - - * Makefile.am: Add Linux for S/390 support. - * Makefile.in: Regenerate. - * configure.in: Add Linux for S/390 support. - * configure: Regenerate. - * include/ffi.h.in: Add Linux for S/390 support. - * src/s390/ffi.c: New file from libffi CVS tree. - * src/s390/sysv.S: New file from libffi CVS tree. - -2002-04-28 Jakub Jelinek - - * configure.in (HAVE_AS_SPARC_UA_PCREL): Check for working - %r_disp32(). - * src/sparc/v8.S: Use it. - * src/sparc/v9.S: Likewise. - * fficonfig.h.in: Rebuilt. - * configure: Rebuilt. - -2002-04-08 Hans Boehm - - * src/java_raw_api.c (ffi_java_raw_size): Handle FFI_TYPE_DOUBLE - correctly. - * src/ia64/unix.S: Add unwind information. Fix comments. - Save sp in a way that's compatible with unwind info. - (ffi_call_unix): Correctly restore sp in all cases. - * src/ia64/ffi.c: Add, fix comments. - -2002-04-08 Jakub Jelinek - - * src/sparc/v8.S: Make .eh_frame dependent on target word size. - -2002-04-06 Jason Thorpe - - * configure.in (alpha*-*-netbsd*): Add target. - * configure: Regenerate. - -2002-04-04 Jeff Sturm - - * src/sparc/v8.S: Add unwind info. - * src/sparc/v9.S: Likewise. - -2002-03-30 Krister Walfridsson - - * configure.in: Enable i*86-*-netbsdelf*. - * configure: Rebuilt. - -2002-03-29 David Billinghurst - - PR other/2620 - * src/mips/n32.s: Delete - * src/mips/o32.s: Delete - -2002-03-21 Loren J. Rittle - - * configure.in: Enable alpha*-*-freebsd*. - * configure: Rebuilt. - -2002-03-17 Bryce McKinlay - - * Makefile.am: libfficonvenience -> libffi_convenience. - * Makefile.in: Rebuilt. - - * Makefile.am: Define ffitest_OBJECTS. - * Makefile.in: Rebuilt. - -2002-03-07 Andreas Tobler - David Edelsohn - - * Makefile.am (EXTRA_DIST): Add Darwin and AIX closure files. - (TARGET_SRC_POWERPC_AIX): Add aix_closure.S. - (TARGET_SRC_POWERPC_DARWIN): Add darwin_closure.S. - * Makefile.in: Regenerate. - * include/ffi.h.in: Add AIX and Darwin closure definitions. - * src/powerpc/ffi_darwin.c (ffi_prep_closure): New function. - (flush_icache, flush_range): New functions. - (ffi_closure_helper_DARWIN): New function. - * src/powerpc/aix_closure.S: New file. - * src/powerpc/darwin_closure.S: New file. - -2002-02-24 Jeff Sturm - - * include/ffi.h.in: Add typedef for ffi_arg. - * src/ffitest.c (main): Declare rint with ffi_arg. - -2002-02-21 Andreas Tobler - - * src/powerpc/ffi_darwin.c (ffi_prep_args): Skip appropriate - number of GPRs for floating-point arguments. - -2002-01-31 Anthony Green - - * configure: Rebuilt. - * configure.in: Replace CHECK_SIZEOF and endian tests with - cross-compiler friendly macros. - * aclocal.m4 (AC_COMPILE_CHECK_SIZEOF, AC_C_BIGENDIAN_CROSS): New - macros. - -2002-01-18 David Edelsohn - - * src/powerpc/darwin.S (_ffi_call_AIX): New. - * src/powerpc/aix.S (ffi_call_DARWIN): New. - -2002-01-17 David Edelsohn - - * Makefile.am (EXTRA_DIST): Add Darwin and AIX files. - (TARGET_SRC_POWERPC_AIX): New. - (POWERPC_AIX): New stanza. - * Makefile.in: Regenerate. - * configure.in: Add AIX case. - * configure: Regenerate. - * include/ffi.h.in (ffi_abi): Add FFI_AIX. - * src/powerpc/ffi_darwin.c (ffi_status): Use "long" to scale frame - size. Fix "long double" support. - (ffi_call): Add FFI_AIX case. - * src/powerpc/aix.S: New. - -2001-10-09 John Hornkvist - - Implement Darwin PowerPC ABI. - * configure.in: Handle powerpc-*-darwin*. - * Makefile.am: Set source files for POWERPC_DARWIN. - * configure: Rebuilt. - * Makefile.in: Rebuilt. - * include/ffi.h.in: Define FFI_DARWIN and FFI_DEFAULT_ABI for - POWERPC_DARWIN. - * src/powerpc/darwin.S: New file. - * src/powerpc/ffi_darwin.c: New file. - -2001-10-07 Joseph S. Myers - - * src/x86/ffi.c: Fix spelling error of "separate" as "seperate". - -2001-07-16 Rainer Orth - - * src/x86/sysv.S: Avoid gas-only .balign directive. - Use C style comments. - -2001-07-16 Rainer Orth - - * src/alpha/ffi.c (ffi_prep_closure): Avoid gas-only mnemonic. - Fixes PR bootstrap/3563. - -2001-06-26 Rainer Orth - - * src/alpha/osf.S (ffi_closure_osf): Use .rdata for ECOFF. - -2001-06-25 Rainer Orth - - * configure.in: Recognize sparc*-sun-* host. - * configure: Regenerate. - -2001-06-06 Andrew Haley - - * src/alpha/osf.S (__FRAME_BEGIN__): Conditionalize for ELF. - -2001-06-03 Andrew Haley - - * src/alpha/osf.S: Add unwind info. - * src/powerpc/sysv.S: Add unwind info. - * src/powerpc/ppc_closure.S: Likewise. - -2000-05-31 Jeff Sturm - - * configure.in: Fix AC_ARG_ENABLE usage. - * configure: Rebuilt. - -2001-05-06 Bryce McKinlay - - * configure.in: Remove warning about beta code. - * configure: Rebuilt. - -2001-04-25 Hans Boehm - - * src/ia64/unix.S: Restore stack pointer when returning from - ffi_closure_UNIX. - * src/ia64/ffi.c: Fix typo in comment. - -2001-04-18 Jim Wilson - - * src/ia64/unix.S: Delete unnecessary increment and decrement of loc2 - to eliminate RAW DV. - -2001-04-12 Bryce McKinlay - - * Makefile.am: Make a libtool convenience library. - * Makefile.in: Rebuilt. - -2001-03-29 Bryce McKinlay - - * configure.in: Use different syntax for subdirectory creation. - * configure: Rebuilt. - -2001-03-27 Jon Beniston - - * configure.in: Added X86_WIN32 target (Win32, CygWin, MingW). - * configure: Rebuilt. - * Makefile.am: Added X86_WIN32 target support. - * Makefile.in: Rebuilt. - - * include/ffi.h.in: Added X86_WIN32 target support. - - * src/ffitest.c: Doesn't run structure tests for X86_WIN32 targets. - * src/types.c: Added X86_WIN32 target support. - - * src/x86/win32.S: New file. Based on sysv.S, but with EH - stuff removed and made to work with CygWin's gas. - -2001-03-26 Bryce McKinlay - - * configure.in: Make target subdirectory in build dir. - * Makefile.am: Override suffix based rules to specify correct output - subdirectory. - * Makefile.in: Rebuilt. - * configure: Rebuilt. - -2001-03-23 Kevin B Hendricks - - * src/powerpc/ppc_closure.S: New file. - * src/powerpc/ffi.c (ffi_prep_args): Fixed ABI compatibility bug - involving long long and register pairs. - (ffi_prep_closure): New function. - (flush_icache): Likewise. - (ffi_closure_helper_SYSV): Likewise. - * include/ffi.h.in (FFI_CLOSURES): Define on PPC. - (FFI_TRAMPOLINE_SIZE): Likewise. - (FFI_NATIVE_RAW_API): Likewise. - * Makefile.in: Rebuilt. - * Makefile.am (EXTRA_DIST): Added src/powerpc/ppc_closure.S. - (TARGET_SRC_POWERPC): Likewise. - -2001-03-19 Tom Tromey - - * Makefile.in: Rebuilt. - * Makefile.am (ffitest_LDFLAGS): New macro. - -2001-03-02 Nick Clifton - - * include/ffi.h.in: Remove RCS ident string. - * include/ffi_mips.h: Remove RCS ident string. - * src/debug.c: Remove RCS ident string. - * src/ffitest.c: Remove RCS ident string. - * src/prep_cif.c: Remove RCS ident string. - * src/types.c: Remove RCS ident string. - * src/alpha/ffi.c: Remove RCS ident string. - * src/alpha/osf.S: Remove RCS ident string. - * src/arm/ffi.c: Remove RCS ident string. - * src/arm/sysv.S: Remove RCS ident string. - * src/mips/ffi.c: Remove RCS ident string. - * src/mips/n32.S: Remove RCS ident string. - * src/mips/o32.S: Remove RCS ident string. - * src/sparc/ffi.c: Remove RCS ident string. - * src/sparc/v8.S: Remove RCS ident string. - * src/sparc/v9.S: Remove RCS ident string. - * src/x86/ffi.c: Remove RCS ident string. - * src/x86/sysv.S: Remove RCS ident string. - -2001-02-08 Joseph S. Myers - - * include/ffi.h.in: Change sourceware.cygnus.com references to - gcc.gnu.org. - -2000-12-09 Richard Henderson - - * src/alpha/ffi.c (ffi_call): Simplify struct return test. - (ffi_closure_osf_inner): Index rather than increment avalue - and arg_types. Give ffi_closure_osf the raw return value type. - * src/alpha/osf.S (ffi_closure_osf): Handle return value type - promotion. - -2000-12-07 Richard Henderson - - * src/raw_api.c (ffi_translate_args): Fix typo. - (ffi_prep_closure): Likewise. - - * include/ffi.h.in [ALPHA]: Define FFI_CLOSURES and - FFI_TRAMPOLINE_SIZE. - * src/alpha/ffi.c (ffi_prep_cif_machdep): Adjust minimal - cif->bytes for new ffi_call_osf implementation. - (ffi_prep_args): Absorb into ... - (ffi_call): ... here. Do all stack allocation here and - avoid a callback function. - (ffi_prep_closure, ffi_closure_osf_inner): New. - * src/alpha/osf.S (ffi_call_osf): Reimplement with no callback. - (ffi_closure_osf): New. - -2000-09-10 Alexandre Oliva - - * config.guess, config.sub, install-sh: Removed. - * ltconfig, ltmain.sh, missing, mkinstalldirs: Likewise. - * Makefile.in: Rebuilt. - - * acinclude.m4: Include libtool macros from the top level. - * aclocal.m4, configure: Rebuilt. - -2000-08-22 Alexandre Oliva - - * configure.in [i*86-*-freebsd*] (TARGET, TARGETDIR): Set. - * configure: Rebuilt. - -2000-05-11 Scott Bambrough - - * libffi/src/arm/sysv.S (ffi_call_SYSV): Doubles are not saved to - memory correctly. Use conditional instructions, not branches where - possible. - -2000-05-04 Tom Tromey - - * configure: Rebuilt. - * configure.in: Match `arm*-*-linux-*'. - From Chris Dornan . - -2000-04-28 Jakub Jelinek - - * Makefile.am (SUBDIRS): Define. - (AM_MAKEFLAGS): Likewise. - (Multilib support.): Add section. - * Makefile.in: Rebuilt. - * ltconfig (extra_compiler_flags, extra_compiler_flags_value): - New variables. Set for gcc using -print-multi-lib. Export them - to libtool. - (sparc64-*-linux-gnu*): Use libsuff 64 for search paths. - * ltmain.sh (B|b|V): Don't throw away gcc's -B, -b and -V options - for -shared links. - (extra_compiler_flags_value, extra_compiler_flags): Check these - for extra compiler options which need to be passed down in - compiler_flags. - -2000-04-16 Anthony Green - - * configure: Rebuilt. - * configure.in: Change i*86-pc-linux* to i*86-*-linux*. - -2000-04-14 Jakub Jelinek - - * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds. - Set SPARC FFI_DEFAULT_ABI based on SPARC64 define. - * src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args. - Replace all void * sizeofs with sizeof(int). - Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is - different than DOUBLE. - Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere). - (ffi_prep_args_v9): New function. - (ffi_prep_cif_machdep): Handle V9 ABI and long long on V8. - (ffi_V9_return_struct): New function. - (ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from - 32bit code (not yet cross-arch calls). - * src/sparc/v8.S: Add struct return delay nop. - Handle long long. - * src/sparc/v9.S: New file. - * src/prep_cif.c (ffi_prep_cif): Return structure pointer - is used on sparc64 only for structures larger than 32 bytes. - Pass by reference for structures is done for structure arguments - larger than 16 bytes. - * src/ffitest.c (main): Use 64bit rint on sparc64. - Run long long tests on sparc. - * src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and - sparc64. - (FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits - on sparc64. - * configure.in (sparc-*-linux*): New supported target. - (sparc64-*-linux*): Likewise. - * configure: Rebuilt. - * Makefile.am: Add v9.S to SPARC files. - * Makefile.in: Likewise. - (LINK): Surround $(CCLD) into double quotes, so that multilib - compiles work correctly. - -2000-04-04 Alexandre Petit-Bianco - - * configure: Rebuilt. - * configure.in: (i*86-*-solaris*): New libffi target. Patch - proposed by Bryce McKinlay. - -2000-03-20 Tom Tromey - - * Makefile.in: Hand edit for java_raw_api.lo. - -2000-03-08 Bryce McKinlay - - * config.guess, config.sub: Update from the gcc tree. - Fix for PR libgcj/168. - -2000-03-03 Tom Tromey - - * Makefile.in: Fixed ia64 by hand. - - * configure: Rebuilt. - * configure.in (--enable-multilib): New option. - (libffi_basedir): New subst. - (AC_OUTPUT): Added multilib code. - -2000-03-02 Tom Tromey - - * Makefile.in: Rebuilt. - * Makefile.am (TARGET_SRC_IA64): Use `ia64', not `alpha', as - directory name. - -2000-02-25 Hans Boehm - - * src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New - files. - * src/raw_api.c (ffi_translate_args): Fixed typo in argument - list. - (ffi_prep_raw_closure): Use ffi_translate_args, not - ffi_closure_translate. - * src/java_raw_api.c: New file. - * src/ffitest.c (closure_test_fn): New function. - (main): Define `rint' as long long on IA64. Added new test when - FFI_CLOSURES is defined. - * include/ffi.h.in (ALIGN): Use size_t, not unsigned. - (ffi_abi): Recognize IA64. - (ffi_raw): Added `flt' field. - Added "Java raw API" code. - * configure.in: Recognize ia64. - * Makefile.am (TARGET_SRC_IA64): New macro. - (libffi_la_common_SOURCES): Added java_raw_api.c. - (libffi_la_SOURCES): Define in IA64 case. - -2000-01-04 Tom Tromey - - * Makefile.in: Rebuilt with newer automake. - -1999-12-31 Tom Tromey - - * Makefile.am (INCLUDES): Added -I$(top_srcdir)/src. - -1999-09-01 Tom Tromey - - * include/ffi.h.in: Removed PACKAGE and VERSION defines and - undefs. - * fficonfig.h.in: Rebuilt. - * configure: Rebuilt. - * configure.in: Pass 3rd argument to AM_INIT_AUTOMAKE. - Use AM_PROG_LIBTOOL (automake 1.4 compatibility). - * acconfig.h: Don't #undef PACKAGE or VERSION. - -1999-08-09 Anthony Green - - * include/ffi.h.in: Try to work around messy header problem - with PACKAGE and VERSION. - - * configure: Rebuilt. - * configure.in: Change version to 2.00-beta. - - * fficonfig.h.in: Rebuilt. - * acconfig.h (FFI_NO_STRUCTS, FFI_NO_RAW_API): Define. - - * src/x86/ffi.c (ffi_raw_call): Rename. - -1999-08-02 Kresten Krab Thorup - - * src/x86/ffi.c (ffi_closure_SYSV): New function. - (ffi_prep_incoming_args_SYSV): Ditto. - (ffi_prep_closure): Ditto. - (ffi_closure_raw_SYSV): Ditto. - (ffi_prep_raw_closure): More ditto. - (ffi_call_raw): Final ditto. - - * include/ffi.h.in: Add definitions for closure and raw API. - - * src/x86/ffi.c (ffi_prep_cif_machdep): Added case for - FFI_TYPE_UINT64. - - * Makefile.am (libffi_la_common_SOURCES): Added raw_api.c - - * src/raw_api.c: New file. - - * include/ffi.h.in (ffi_raw): New type. - (UINT_ARG, SINT_ARG): New defines. - (ffi_closure, ffi_raw_closure): New types. - (ffi_prep_closure, ffi_prep_raw_closure): New declarations. - - * configure.in: Add check for endianness and sizeof void*. - - * src/x86/sysv.S (ffi_call_SYSV): Call fixup routine via argument, - instead of directly. - - * configure: Rebuilt. - -Thu Jul 8 14:28:42 1999 Anthony Green - - * configure.in: Add x86 and powerpc BeOS configurations. - From Makoto Kato . - -1999-05-09 Anthony Green - - * configure.in: Add warning about this being beta code. - Remove src/Makefile.am from the picture. - * configure: Rebuilt. - - * Makefile.am: Move logic from src/Makefile.am. Add changes - to support libffi as a target library. - * Makefile.in: Rebuilt. - - * aclocal.m4, config.guess, config.sub, ltconfig, ltmain.sh: - Upgraded to new autoconf, automake, libtool. - - * README: Tweaks. - - * LICENSE: Update copyright date. - - * src/Makefile.am, src/Makefile.in: Removed. - -1998-11-29 Anthony Green - - * include/ChangeLog: Removed. - * src/ChangeLog: Removed. - * src/mips/ChangeLog: Removed. - * src/sparc/ChangeLog: Remboved. - * src/x86/ChangeLog: Removed. - - * ChangeLog.v1: Created. diff --git a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libgcj b/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libgcj deleted file mode 100644 index ea5d02f19..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.libgcj +++ /dev/null @@ -1,40 +0,0 @@ -2004-01-14 Kelley Cook - - * configure.in: Add in AC_PREREQ(2.13) - -2003-02-20 Alexandre Oliva - - * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to - config.status. - * configure: Rebuilt. - -2002-01-27 Alexandre Oliva - - * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. - Remove USE_LIBDIR conditional. - * Makefile.am (toolexecdir, toolexeclibdir): Don't override. - * Makefile.in, configure: Rebuilt. - -Mon Aug 9 18:33:38 1999 Rainer Orth - - * include/Makefile.in: Rebuilt. - * Makefile.in: Rebuilt - * Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native - builds. - Use USE_LIBDIR. - - * configure: Rebuilt. - * configure.in (USE_LIBDIR): Define for native builds. - Use lowercase in configure --help explanations. - -1999-08-08 Anthony Green - - * include/ffi.h.in (FFI_FN): Remove `...'. - -1999-08-08 Anthony Green - - * Makefile.in: Rebuilt. - * Makefile.am (AM_CFLAGS): Compile with -fexceptions. - - * src/x86/sysv.S: Add exception handling metadata. - diff --git a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.v1 b/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.v1 deleted file mode 100644 index af3a37756..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ChangeLog.v1 +++ /dev/null @@ -1,764 +0,0 @@ -The libffi version 1 ChangeLog archive. - -Version 1 of libffi had per-directory ChangeLogs. Current and future -versions have a single ChangeLog file in the root directory. The -version 1 ChangeLogs have all been concatenated into this file for -future reference only. - ---- libffi ---------------------------------------------------------------- - -Mon Oct 5 02:17:50 1998 Anthony Green - - * configure.in: Boosted rev. - * configure, Makefile.in, aclocal.m4: Rebuilt. - * README: Boosted rev and updated release notes. - -Mon Oct 5 01:03:03 1998 Anthony Green - - * configure.in: Boosted rev. - * configure, Makefile.in, aclocal.m4: Rebuilt. - * README: Boosted rev and updated release notes. - -1998-07-25 Andreas Schwab - - * m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags. - Correctly handle small structures. - (ffi_prep_args): Also handle small structures. - (ffi_call): Pass size of return type to ffi_call_SYSV. - * m68k/sysv.S: Adjust for above changes. Correctly align small - structures in the return value. - - * types.c (uint64, sint64) [M68K]: Change alignment to 4. - -Fri Apr 17 17:26:58 1998 Anthony Green - - * configure.in: Boosted rev. - * configure,Makefile.in,aclocal.m4: Rebuilt. - * README: Boosted rev and added release notes. - -Sun Feb 22 00:50:41 1998 Geoff Keating - - * configure.in: Add PowerPC config bits. - -1998-02-14 Andreas Schwab - - * configure.in: Add m68k config bits. Change AC_CANONICAL_SYSTEM - to AC_CANONICAL_HOST, this is not a compiler. Use $host instead - of $target. Remove AC_CHECK_SIZEOF(char), we already know the - result. Fix argument of AC_ARG_ENABLE. - * configure, fficonfig.h.in: Rebuilt. - -Tue Feb 10 20:53:40 1998 Richard Henderson - - * configure.in: Add Alpha config bits. - -Tue May 13 13:39:20 1997 Anthony Green - - * README: Updated dates and reworded Irix comments. - - * configure.in: Removed AC_PROG_RANLIB. - - * Makefile.in, aclocal.m4, config.guess, config.sub, configure, - ltmain.sh, */Makefile.in: libtoolized again and rebuilt with - automake and autoconf. - -Sat May 10 18:44:50 1997 Tom Tromey - - * configure, aclocal.m4: Rebuilt. - * configure.in: Don't compute EXTRADIST; now handled in - src/Makefile.in. Removed macros implied by AM_INIT_AUTOMAKE. - Don't run AM_MAINTAINER_MODE. - -Thu May 8 14:34:05 1997 Anthony Green - - * missing, ltmain.sh, ltconfig.sh: Created. These are new files - required by automake and libtool. - - * README: Boosted rev to 1.14. Added notes. - - * acconfig.h: Moved PACKAGE and VERSION for new automake. - - * configure.in: Changes for libtool. - - * Makefile.am (check): make test now make check. Uses libtool now. - - * Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt. - -Thu May 1 16:27:07 1997 Anthony Green - - * missing: Added file required by new automake. - -Tue Nov 26 14:10:42 1996 Anthony Green - - * acconfig.h: Added USING_PURIFY flag. This is defined when - --enable-purify-safety was used at configure time. - - * configure.in (allsources): Added --enable-purify-safety switch. - (VERSION): Boosted rev to 1.13. - * configure: Rebuilt. - -Fri Nov 22 06:46:12 1996 Anthony Green - - * configure.in (VERSION): Boosted rev to 1.12. - Removed special CFLAGS hack for gcc. - * configure: Rebuilt. - - * README: Boosted rev to 1.12. Added notes. - - * Many files: Cygnus Support changed to Cygnus Solutions. - -Wed Oct 30 11:15:25 1996 Anthony Green - - * configure.in (VERSION): Boosted rev to 1.11. - * configure: Rebuilt. - - * README: Boosted rev to 1.11. Added notes about GNU make. - -Tue Oct 29 12:25:12 1996 Anthony Green - - * configure.in: Fixed -Wall trick. - (VERSION): Boosted rev. - * configure: Rebuilt - - * acconfig.h: Needed for --enable-debug configure switch. - - * README: Boosted rev to 1.09. Added more notes on building - libffi, and LCLint. - - * configure.in: Added --enable-debug switch. Boosted rev to - 1.09. - * configure: Rebuilt - -Tue Oct 15 13:11:28 1996 Anthony Green - - * configure.in (VERSION): Boosted rev to 1.08 - * configure: Rebuilt. - - * README: Added n32 bug fix notes. - - * Makefile.am: Added "make lint" production. - * Makefile.in: Rebuilt. - -Mon Oct 14 10:54:46 1996 Anthony Green - - * README: Added web page reference. - - * configure.in, README: Boosted rev to 1.05 - * configure: Rebuilt. - - * README: Fixed n32 sample code. - -Fri Oct 11 17:09:28 1996 Anthony Green - - * README: Added sparc notes. - - * configure.in, README: Boosted rev to 1.04. - * configure: Rebuilt. - -Thu Oct 10 10:31:03 1996 Anthony Green - - * configure.in, README: Boosted rev to 1.03. - * configure: Rebuilt. - - * README: Added struct notes. - - * Makefile.am (EXTRA_DIST): Added LICENSE to distribution. - * Makefile.in: Rebuilt. - - * README: Removed Linux section. No special notes now - because aggregates arg/return types work. - -Wed Oct 9 16:16:42 1996 Anthony Green - - * README, configure.in (VERSION): Boosted rev to 1.02 - * configure: Rebuilt. - -Tue Oct 8 11:56:33 1996 Anthony Green - - * README (NOTE): Added n32 notes. - - * Makefile.am: Added test production. - * Makefile: Rebuilt - - * README: spell checked! - - * configure.in (VERSION): Boosted rev to 1.01 - * configure: Rebuilt. - -Mon Oct 7 15:50:22 1996 Anthony Green - - * configure.in: Added nasty bit to support SGI tools. - * configure: Rebuilt. - - * README: Added SGI notes. Added note about automake bug. - -Mon Oct 7 11:00:28 1996 Anthony Green - - * README: Rewrote intro, and fixed examples. - -Fri Oct 4 10:19:55 1996 Anthony Green - - * configure.in: -D$TARGET is no longer used as a compiler switch. - It is now inserted into ffi.h at configure time. - * configure: Rebuilt. - - * FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status. - -Thu Oct 3 13:47:34 1996 Anthony Green - - * README, LICENSE: Created. Wrote some docs. - - * configure.in: Don't barf on i586-unknown-linuxaout. - Added EXTRADIST code for "make dist". - * configure: Rebuilt. - - * */Makefile.in: Rebuilt with patched automake. - -Tue Oct 1 17:12:25 1996 Anthony Green - - * Makefile.am, aclocal.m4, config.guess, config.sub, - configure.in, fficonfig.h.in, install-sh, mkinstalldirs, - stamp-h.in: Created - * Makefile.in, configure: Generated - ---- libffi/include -------------------------------------------------------- - -Tue Feb 24 13:09:36 1998 Anthony Green - - * ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on - ffi.h.in changes. This is a work-around for SGI's "simple" - assembler. - -Sun Feb 22 00:51:55 1998 Geoff Keating - - * ffi.h.in: PowerPC support. - -1998-02-14 Andreas Schwab - - * ffi.h.in: Add m68k support. - (FFI_TYPE_LONGDOUBLE): Make it a separate value. - -Tue Feb 10 20:55:16 1998 Richard Henderson - - * ffi.h.in (SIZEOF_ARG): Use a pointer type by default. - - * ffi.h.in: Alpha support. - -Fri Nov 22 06:48:45 1996 Anthony Green - - * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions. - -Wed Nov 20 22:31:01 1996 Anthony Green - - * ffi.h.in: Added ffi_type_void definition. - -Tue Oct 29 12:22:40 1996 Anthony Green - - * Makefile.am (hack_DATA): Always install ffi_mips.h. - - * ffi.h.in: Removed FFI_DEBUG. It's now in the correct - place (acconfig.h). - Added #include for size_t definition. - -Tue Oct 15 17:23:35 1996 Anthony Green - - * ffi.h.in, ffi_common.h, ffi_mips.h: More clean up. - Commented out #define of FFI_DEBUG. - -Tue Oct 15 13:01:06 1996 Anthony Green - - * ffi_common.h: Added bool definition. - - * ffi.h.in, ffi_common.h: Clean up based on LCLint output. - Added funny /*@...@*/ comments to annotate source. - -Mon Oct 14 12:29:23 1996 Anthony Green - - * ffi.h.in: Interface changes based on feedback from Jim - Blandy. - -Fri Oct 11 16:49:35 1996 Anthony Green - - * ffi.h.in: Small change for sparc support. - -Thu Oct 10 14:53:37 1996 Anthony Green - - * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for - special structure return types. - -Wed Oct 9 13:55:57 1996 Anthony Green - - * ffi.h.in: Added SIZEOF_ARG definition for X86 - -Tue Oct 8 11:40:36 1996 Anthony Green - - * ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings. - Use it to case your function pointers to the proper type. - - * ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug. - - * Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST. - * Makefile: Rebuilt. - - * ffi_mips.h: Created. Moved all common mips definitions here. - -Mon Oct 7 10:58:12 1996 Anthony Green - - * ffi.h.in: The SGI assember is very picky about parens. Redefined - some macros to avoid problems. - - * ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added - externs for pointer, and 64bit integral ffi_types. - -Fri Oct 4 09:51:37 1996 Anthony Green - - * ffi.h.in: Added FFI_ABI member to ffi_cif and changed - function prototypes accordingly. - Added #define @TARGET@. Now programs including ffi.h don't - have to specify this themselves. - -Thu Oct 3 15:36:44 1996 Anthony Green - - * ffi.h.in: Changed ffi_prep_cif's values from void* to void** - - * Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist" - to work. - * Makefile.in: Regenerated. - -Wed Oct 2 10:16:59 1996 Anthony Green - - * Makefile.am: Created - * Makefile.in: Generated - - * ffi_common.h: Added rcsid comment - -Tue Oct 1 17:13:51 1996 Anthony Green - - * ffi.h.in, ffi_common.h: Created - ---- libffi/src ------------------------------------------------------------ - -Mon Oct 5 02:17:50 1998 Anthony Green - - * arm/ffi.c, arm/sysv.S: Created. - - * Makefile.am: Added arm files. - * Makefile.in: Rebuilt. - -Mon Oct 5 01:41:38 1998 Anthony Green - - * Makefile.am (libffi_la_LDFLAGS): Incremented revision. - -Sun Oct 4 16:27:17 1998 Anthony Green - - * alpha/osf.S (ffi_call_osf): Patch for DU assembler. - - * ffitest.c (main): long long and long double return values work - for x86. - -Fri Apr 17 11:50:58 1998 Anthony Green - - * Makefile.in: Rebuilt. - - * ffitest.c (main): Floating point tests not executed for systems - with broken lond double (SunOS 4 w/ GCC). - - * types.c: Fixed x86 alignment info for long long types. - -Thu Apr 16 07:15:28 1998 Anthony Green - - * ffitest.c: Added more notes about GCC bugs under Irix 6. - -Wed Apr 15 08:42:22 1998 Anthony Green - - * ffitest.c (struct5): New test function. - (main): New test with struct5. - -Thu Mar 5 10:48:11 1998 Anthony Green - - * prep_cif.c (initialize_aggregate): Fix assertion for - nested structures. - -Tue Feb 24 16:33:41 1998 Anthony Green - - * prep_cif.c (ffi_prep_cif): Added long double support for sparc. - -Sun Feb 22 00:52:18 1998 Geoff Keating - - * powerpc/asm.h: New file. - * powerpc/ffi.c: New file. - * powerpc/sysv.S: New file. - * Makefile.am: PowerPC port. - * ffitest.c (main): Allow all tests to run even in presence of gcc - bug on PowerPC. - -1998-02-17 Anthony Green - - * mips/ffi.c: Fixed comment typo. - - * x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): - Fixed x86 long double return handling. - - * types.c: Fixed x86 long double alignment info. - -1998-02-14 Andreas Schwab - - * types.c: Add m68k support. - - * ffitest.c (floating): Add long double parameter. - (return_ll, ldblit): New functions to test long long and long - double return value. - (main): Fix type error in assignment of ts[1-4]_type.elements. - Add tests for long long and long double arguments and return - values. - - * prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for - struct value pointer. - - * m68k/ffi.c, m68k/sysv.S: New files. - * Makefile.am: Add bits for m68k port. Add kludge to work around - automake deficiency. - (test): Don't require "." in $PATH. - * Makefile.in: Rebuilt. - -Wed Feb 11 07:36:50 1998 Anthony Green - - * Makefile.in: Rebuilt. - -Tue Feb 10 20:56:00 1998 Richard Henderson - - * alpha/ffi.c, alpha/osf.S: New files. - * Makefile.am: Alpha port. - -Tue Nov 18 14:12:07 1997 Anthony Green - - * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag - for n32. - -Tue Jun 3 17:18:20 1997 Anthony Green - - * ffitest.c (main): Added hack to get structure tests working - correctly. - -Sat May 10 19:06:42 1997 Tom Tromey - - * Makefile.in: Rebuilt. - * Makefile.am (EXTRA_DIST): Explicitly list all distributable - files in subdirs. - (VERSION, CC): Removed. - -Thu May 8 17:19:01 1997 Anthony Green - - * Makefile.am: Many changes for new automake and libtool. - * Makefile.in: Rebuilt. - -Fri Nov 22 06:57:56 1996 Anthony Green - - * ffitest.c (main): Fixed test case for non mips machines. - -Wed Nov 20 22:31:59 1996 Anthony Green - - * types.c: Added ffi_type_void declaration. - -Tue Oct 29 13:07:19 1996 Anthony Green - - * ffitest.c (main): Fixed character constants. - (main): Emit warning for structure test 3 failure on Sun. - - * Makefile.am (VPATH): Fixed VPATH def'n so automake won't - strip it out. - Moved distdir hack from libffi to automake. - (ffitest): Added missing -c for $(COMPILE) (change in automake). - * Makefile.in: Rebuilt. - -Tue Oct 15 13:08:20 1996 Anthony Green - - * Makefile.am: Added "make lint" production. - * Makefile.in: Rebuilt. - - * prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro. - Clean up based on LCLint output. Added funny /*@...@*/ comments to - annotate source. - - * ffitest.c, debug.c: Cleaned up code. - -Mon Oct 14 12:26:56 1996 Anthony Green - - * ffitest.c: Changes based on interface changes. - - * prep_cif.c (ffi_prep_cif): Cleaned up interface based on - feedback from Jim Blandy. - -Fri Oct 11 15:53:18 1996 Anthony Green - - * ffitest.c: Reordered tests while porting to sparc. - Made changes to handle lame structure passing for sparc. - Removed calls to fflush(). - - * prep_cif.c (ffi_prep_cif): Added special case for sparc - aggregate type arguments. - -Thu Oct 10 09:56:51 1996 Anthony Green - - * ffitest.c (main): Added structure passing/returning tests. - - * prep_cif.c (ffi_prep_cif): Perform proper initialization - of structure return types if needed. - (initialize_aggregate): Bug fix - -Wed Oct 9 16:04:20 1996 Anthony Green - - * types.c: Added special definitions for x86 (double doesn't - need double word alignment). - - * ffitest.c: Added many tests - -Tue Oct 8 09:19:22 1996 Anthony Green - - * prep_cif.c (ffi_prep_cif): Fixed assertion. - - * debug.c (ffi_assert): Must return a non void now. - - * Makefile.am: Added test production. - * Makefile: Rebuilt. - - * ffitest.c (main): Created. - - * types.c: Created. Stripped common code out of */ffi.c. - - * prep_cif.c: Added missing stdlib.h include. - - * debug.c (ffi_type_test): Used "a" to eliminate compiler - warnings in non-debug builds. Included ffi_common.h. - -Mon Oct 7 15:36:42 1996 Anthony Green - - * Makefile.am: Added a rule for .s -> .o - This is required by the SGI compiler. - * Makefile: Rebuilt. - -Fri Oct 4 09:51:08 1996 Anthony Green - - * prep_cif.c (initialize_aggregate): Moved abi specification - to ffi_prep_cif(). - -Thu Oct 3 15:37:37 1996 Anthony Green - - * prep_cif.c (ffi_prep_cif): Changed values from void* to void**. - (initialize_aggregate): Fixed aggregate type initialization. - - * Makefile.am (EXTRA_DIST): Added support code for "make dist". - * Makefile.in: Regenerated. - -Wed Oct 2 11:41:57 1996 Anthony Green - - * debug.c, prep_cif: Created. - - * Makefile.am: Added debug.o and prep_cif.o to OBJ. - * Makefile.in: Regenerated. - - * Makefile.am (INCLUDES): Added missing -I../include - * Makefile.in: Regenerated. - -Tue Oct 1 17:11:51 1996 Anthony Green - - * error.c, Makefile.am: Created. - * Makefile.in: Generated. - ---- libffi/src/x86 -------------------------------------------------------- - -Sun Oct 4 16:27:17 1998 Anthony Green - - * sysv.S (retlongdouble): Fixed long long return value support. - * ffi.c (ffi_prep_cif_machdep): Ditto. - -Wed May 13 04:30:33 1998 Anthony Green - - * ffi.c (ffi_prep_cif_machdep): Fixed long double return value - support. - -Wed Apr 15 08:43:20 1998 Anthony Green - - * ffi.c (ffi_prep_args): small struct support was missing. - -Thu May 8 16:53:58 1997 Anthony Green - - * objects.mak: Removed. - -Mon Dec 2 15:12:58 1996 Tom Tromey - - * sysv.S: Use .balign, for a.out Linux boxes. - -Tue Oct 15 13:06:50 1996 Anthony Green - - * ffi.c: Clean up based on LCLint output. - Added funny /*@...@*/ comments to annotate source. - -Fri Oct 11 16:43:38 1996 Anthony Green - - * ffi.c (ffi_call): Added assertion for bad ABIs. - -Wed Oct 9 13:57:27 1996 Anthony Green - - * sysv.S (retdouble): Fixed double return problems. - - * ffi.c (ffi_call): Corrected fn arg definition. - (ffi_prep_cif_machdep): Fixed double return problems - -Tue Oct 8 12:12:49 1996 Anthony Green - - * ffi.c: Moved ffi_type definitions to types.c. - (ffi_prep_args): Fixed type promotion bug. - -Mon Oct 7 15:53:06 1996 Anthony Green - - * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' - -Fri Oct 4 09:54:53 1996 Anthony Green - - * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped - remaining args. - -Wed Oct 2 10:07:05 1996 Anthony Green - - * ffi.c, sysv.S, objects.mak: Created. - (ffi_prep_cif): cif->rvalue no longer initialized to NULL. - (ffi_prep_cif_machdep): Moved machine independent cif processing - to src/prep_cif.c. Introduced ffi_prep_cif_machdep(). - ---- libffi/src/mips ------------------------------------------------------- - -Tue Feb 17 17:18:07 1998 Anthony Green - - * o32.S: Fixed typo in comment. - - * ffi.c (ffi_prep_cif_machdep): Fixed argument processing. - -Thu May 8 16:53:58 1997 Anthony Green - - * o32.s, n32.s: Wrappers for SGI tool support. - - * objects.mak: Removed. - -Tue Oct 29 14:37:45 1996 Anthony Green - - * ffi.c (ffi_prep_args): Changed int z to size_t z. - -Tue Oct 15 13:17:25 1996 Anthony Green - - * n32.S: Fixed bad stack munging. - - * ffi.c: Moved prototypes for ffi_call_?32() to here from - ffi_mips.h because extended_cif is not defined in ffi_mips.h. - -Mon Oct 14 12:42:02 1996 Anthony Green - - * ffi.c: Interface changes based on feedback from Jim Blandy. - -Thu Oct 10 11:22:16 1996 Anthony Green - - * n32.S, ffi.c: Lots of changes to support passing and - returning structures with the n32 calling convention. - - * n32.S: Fixed fn pointer bug. - - * ffi.c (ffi_prep_cif_machdep): Fix for o32 structure - return values. - (ffi_prep_args): Fixed n32 structure passing when structures - partially fit in registers. - -Wed Oct 9 13:49:25 1996 Anthony Green - - * objects.mak: Added n32.o. - - * n32.S: Created. - - * ffi.c (ffi_prep_args): Added magic to support proper - n32 processing. - -Tue Oct 8 10:37:35 1996 Anthony Green - - * ffi.c: Moved ffi_type definitions to types.c. - (ffi_prep_args): Fixed type promotion bug. - - * o32.S: This code is only built for o32 compiles. - A lot of the #define cruft has moved to ffi_mips.h. - - * ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg - is only processed if the first is either a float or double. - -Mon Oct 7 15:33:59 1996 Anthony Green - - * o32.S: Modified to compile under each of o32, n32 and n64. - - * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' - -Fri Oct 4 09:53:25 1996 Anthony Green - - * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped - remaining args. - -Wed Oct 2 17:41:22 1996 Anthony Green - - * o32.S: Removed crufty definitions. - -Wed Oct 2 12:53:42 1996 Anthony Green - - * ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL. - (ffi_prep_cif_machdep): Moved all machine independent cif processing - to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types - of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT. - -Tue Oct 1 17:11:02 1996 Anthony Green - - * ffi.c, o32.S, object.mak: Created - ---- libffi/src/sparc ------------------------------------------------------ - -Tue Feb 24 16:33:18 1998 Anthony Green - - * ffi.c (ffi_prep_args): Added long double support. - -Thu May 8 16:53:58 1997 Anthony Green - - * objects.mak: Removed. - -Thu May 1 16:07:56 1997 Anthony Green - - * v8.S: Fixed minor portability problem reported by - Russ McManus . - -Tue Nov 26 14:12:43 1996 Anthony Green - - * v8.S: Used STACKFRAME define elsewhere. - - * ffi.c (ffi_prep_args): Zero out space when USING_PURIFY - is set. - (ffi_prep_cif_machdep): Allocate the correct stack frame - space for functions with < 6 args. - -Tue Oct 29 15:08:55 1996 Anthony Green - - * ffi.c (ffi_prep_args): int z is now size_t z. - -Mon Oct 14 13:31:24 1996 Anthony Green - - * v8.S (ffi_call_V8): Gordon rewrites this again. It looks - great now. - - * ffi.c (ffi_call): The comment about hijacked registers - is no longer valid after gordoni hacked v8.S. - - * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler. - - * v8.S, ffi.c: ffi_call() had changed to accept more than - two args, so v8.S had to change (because it hijacks incoming - arg registers). - - * ffi.c: Interface changes based on feedback from Jim Blandy. - -Thu Oct 10 17:48:16 1996 Anthony Green - - * ffi.c, v8.S, objects.mak: Created. - - diff --git a/ruby/ext/fiddle/libffi-3.2.1/LICENSE b/ruby/ext/fiddle/libffi-3.2.1/LICENSE deleted file mode 100644 index a66fab4f2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others. -See source files for details. - -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. diff --git a/ruby/ext/fiddle/libffi-3.2.1/Makefile.am b/ruby/ext/fiddle/libffi-3.2.1/Makefile.am deleted file mode 100644 index 0e4045100..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/Makefile.am +++ /dev/null @@ -1,258 +0,0 @@ -## Process this with automake to create Makefile.in - -AUTOMAKE_OPTIONS = foreign subdir-objects - -ACLOCAL_AMFLAGS = -I m4 - -SUBDIRS = include testsuite man - -EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \ - src/aarch64/ffi.c src/aarch64/ffitarget.h src/aarch64/sysv.S \ - src/alpha/ffi.c src/alpha/osf.S \ - src/alpha/ffitarget.h src/arc/ffi.c src/arc/arcompact.S \ - src/arc/ffitarget.h src/arm/ffi.c src/arm/sysv.S \ - src/arm/ffitarget.h src/avr32/ffi.c src/avr32/sysv.S \ - src/avr32/ffitarget.h src/cris/ffi.c src/cris/sysv.S \ - src/cris/ffitarget.h src/ia64/ffi.c src/ia64/ffitarget.h \ - src/ia64/ia64_flags.h src/ia64/unix.S src/mips/ffi.c \ - src/mips/n32.S src/mips/o32.S src/metag/ffi.c \ - src/metag/ffitarget.h src/metag/sysv.S src/moxie/ffi.c \ - src/moxie/ffitarget.h src/moxie/eabi.S src/mips/ffitarget.h \ - src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \ - src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \ - src/m88k/ffi.c src/m88k/obsd.S src/m88k/ffitarget.h \ - src/microblaze/ffi.c src/microblaze/sysv.S \ - src/microblaze/ffitarget.h \ - src/nios2/ffi.c src/nios2/ffitarget.h src/nios2/sysv.S \ - src/or1k/ffi.c src/or1k/ffitarget.h src/or1k/sysv.S \ - src/powerpc/ffi.c src/powerpc/ffi_powerpc.h \ - src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \ - src/powerpc/sysv.S src/powerpc/linux64.S \ - src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \ - src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \ - src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \ - src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \ - src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \ - src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \ - src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \ - src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c \ - src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S \ - src/x86/win32.S src/x86/darwin.S src/x86/win64.S \ - src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S \ - src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c \ - src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c \ - src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S \ - src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c \ - src/tile/ffitarget.h src/tile/tile.S libtool-version \ - src/vax/ffi.c src/vax/ffitarget.h src/vax/elfbsd.S \ - src/xtensa/ffitarget.h src/xtensa/ffi.c src/xtensa/sysv.S \ - ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \ - m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ - m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh \ - generate-darwin-source-and-headers.py \ - libffi.xcodeproj/project.pbxproj src/arm/trampoline.S \ - libtool-ldflags ChangeLog.libffi-3.1 - -info_TEXINFOS = doc/libffi.texi - -## ################################################################ - -## -## This section is for make and multilib madness. -## - -# Work around what appears to be a GNU make bug handling MAKEFLAGS -# values defined in terms of make variables, as is the case for CC and -# friends when we are called from the top level Makefile. -AM_MAKEFLAGS = \ - 'AR_FLAGS=$(AR_FLAGS)' \ - 'CC_FOR_BUILD=$(CC_FOR_BUILD)' \ - 'CFLAGS=$(CFLAGS)' \ - 'CXXFLAGS=$(CXXFLAGS)' \ - 'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \ - 'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \ - 'INSTALL=$(INSTALL)' \ - 'INSTALL_DATA=$(INSTALL_DATA)' \ - 'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \ - 'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \ - 'JC1FLAGS=$(JC1FLAGS)' \ - 'LDFLAGS=$(LDFLAGS)' \ - 'LIBCFLAGS=$(LIBCFLAGS)' \ - 'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \ - 'MAKE=$(MAKE)' \ - 'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \ - 'PICFLAG=$(PICFLAG)' \ - 'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \ - 'RUNTESTFLAGS=$(RUNTESTFLAGS)' \ - 'SHELL=$(SHELL)' \ - 'exec_prefix=$(exec_prefix)' \ - 'infodir=$(infodir)' \ - 'libdir=$(libdir)' \ - 'mandir=$(mandir)' \ - 'prefix=$(prefix)' \ - 'AR=$(AR)' \ - 'AS=$(AS)' \ - 'CC=$(CC)' \ - 'CXX=$(CXX)' \ - 'LD=$(LD)' \ - 'NM=$(NM)' \ - 'RANLIB=$(RANLIB)' \ - 'DESTDIR=$(DESTDIR)' - -# Subdir rules rely on $(FLAGS_TO_PASS) -FLAGS_TO_PASS = $(AM_MAKEFLAGS) - -MAKEOVERRIDES= - -toolexeclib_LTLIBRARIES = libffi.la -noinst_LTLIBRARIES = libffi_convenience.la - -libffi_la_SOURCES = src/prep_cif.c src/types.c \ - src/raw_api.c src/java_raw_api.c src/closures.c - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libffi.pc - -nodist_libffi_la_SOURCES = - -if FFI_DEBUG -nodist_libffi_la_SOURCES += src/debug.c -endif - -if MIPS -nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S -endif -if BFIN -nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S -endif -if X86 -nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S src/x86/win32.S -endif -if X86_FREEBSD -nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S src/x86/win32.S -endif -if X86_WIN32 -nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S -endif -if X86_WIN64 -nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S -endif -if X86_DARWIN -nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S -if X86_DARWIN32 -nodist_libffi_la_SOURCES += src/x86/win32.S -endif -endif -if SPARC -nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S -endif -if ALPHA -nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S -endif -if IA64 -nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S -endif -if M32R -nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c -endif -if M68K -nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S -endif -if M88K -nodist_libffi_la_SOURCES += src/m88k/ffi.c src/m88k/obsd.S -endif -if MOXIE -nodist_libffi_la_SOURCES += src/moxie/ffi.c src/moxie/eabi.S -endif -if MICROBLAZE -nodist_libffi_la_SOURCES += src/microblaze/ffi.c src/microblaze/sysv.S -endif -if NIOS2 -nodist_libffi_la_SOURCES += src/nios2/sysv.S src/nios2/ffi.c -endif -if OR1K -nodist_libffi_la_SOURCES += src/or1k/sysv.S src/or1k/ffi.c -endif -if POWERPC -nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S -endif -if POWERPC_AIX -nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S -endif -if POWERPC_DARWIN -nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S -endif -if POWERPC_FREEBSD -nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S -endif -if AARCH64 -nodist_libffi_la_SOURCES += src/aarch64/sysv.S src/aarch64/ffi.c -endif -if ARC -nodist_libffi_la_SOURCES += src/arc/arcompact.S src/arc/ffi.c -endif -if ARM -nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c -if FFI_EXEC_TRAMPOLINE_TABLE -nodist_libffi_la_SOURCES += src/arm/trampoline.S -endif -endif -if AVR32 -nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c -endif -if LIBFFI_CRIS -nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c -endif -if FRV -nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c -endif -if S390 -nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c -endif -if X86_64 -nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S -endif -if SH -nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c -endif -if SH64 -nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c -endif -if PA_LINUX -nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c -endif -if PA_HPUX -nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c -endif -if TILE -nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c -endif -if XTENSA -nodist_libffi_la_SOURCES += src/xtensa/sysv.S src/xtensa/ffi.c -endif -if METAG -nodist_libffi_la_SOURCES += src/metag/sysv.S src/metag/ffi.c -endif -if VAX -nodist_libffi_la_SOURCES += src/vax/elfbsd.S src/vax/ffi.c -endif - -libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) -nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) - -LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/libtool-ldflags $(LDFLAGS)) - -AM_CFLAGS = -if FFI_DEBUG -# Build debug. Define FFI_DEBUG on the commandline so that, when building with -# MSVC, it can link against the debug CRT. -AM_CFLAGS += -DFFI_DEBUG -endif - -libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS) - -AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src -AM_CCASFLAGS = $(AM_CPPFLAGS) - -dist-hook: - if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog diff --git a/ruby/ext/fiddle/libffi-3.2.1/Makefile.in b/ruby/ext/fiddle/libffi-3.2.1/Makefile.in deleted file mode 100644 index dcc5f4751..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/Makefile.in +++ /dev/null @@ -1,2177 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -@FFI_DEBUG_TRUE@am__append_1 = src/debug.c -@MIPS_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S -@BFIN_TRUE@am__append_3 = src/bfin/ffi.c src/bfin/sysv.S -@X86_TRUE@am__append_4 = src/x86/ffi.c src/x86/sysv.S src/x86/win32.S -@X86_FREEBSD_TRUE@am__append_5 = src/x86/ffi.c src/x86/freebsd.S src/x86/win32.S -@X86_WIN32_TRUE@am__append_6 = src/x86/ffi.c src/x86/win32.S -@X86_WIN64_TRUE@am__append_7 = src/x86/ffi.c src/x86/win64.S -@X86_DARWIN_TRUE@am__append_8 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S -@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__append_9 = src/x86/win32.S -@SPARC_TRUE@am__append_10 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S -@ALPHA_TRUE@am__append_11 = src/alpha/ffi.c src/alpha/osf.S -@IA64_TRUE@am__append_12 = src/ia64/ffi.c src/ia64/unix.S -@M32R_TRUE@am__append_13 = src/m32r/sysv.S src/m32r/ffi.c -@M68K_TRUE@am__append_14 = src/m68k/ffi.c src/m68k/sysv.S -@M88K_TRUE@am__append_15 = src/m88k/ffi.c src/m88k/obsd.S -@MOXIE_TRUE@am__append_16 = src/moxie/ffi.c src/moxie/eabi.S -@MICROBLAZE_TRUE@am__append_17 = src/microblaze/ffi.c src/microblaze/sysv.S -@NIOS2_TRUE@am__append_18 = src/nios2/sysv.S src/nios2/ffi.c -@OR1K_TRUE@am__append_19 = src/or1k/sysv.S src/or1k/ffi.c -@POWERPC_TRUE@am__append_20 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S -@POWERPC_AIX_TRUE@am__append_21 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S -@POWERPC_DARWIN_TRUE@am__append_22 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S -@POWERPC_FREEBSD_TRUE@am__append_23 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S -@AARCH64_TRUE@am__append_24 = src/aarch64/sysv.S src/aarch64/ffi.c -@ARC_TRUE@am__append_25 = src/arc/arcompact.S src/arc/ffi.c -@ARM_TRUE@am__append_26 = src/arm/sysv.S src/arm/ffi.c -@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__append_27 = src/arm/trampoline.S -@AVR32_TRUE@am__append_28 = src/avr32/sysv.S src/avr32/ffi.c -@LIBFFI_CRIS_TRUE@am__append_29 = src/cris/sysv.S src/cris/ffi.c -@FRV_TRUE@am__append_30 = src/frv/eabi.S src/frv/ffi.c -@S390_TRUE@am__append_31 = src/s390/sysv.S src/s390/ffi.c -@X86_64_TRUE@am__append_32 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S -@SH_TRUE@am__append_33 = src/sh/sysv.S src/sh/ffi.c -@SH64_TRUE@am__append_34 = src/sh64/sysv.S src/sh64/ffi.c -@PA_LINUX_TRUE@am__append_35 = src/pa/linux.S src/pa/ffi.c -@PA_HPUX_TRUE@am__append_36 = src/pa/hpux32.S src/pa/ffi.c -@TILE_TRUE@am__append_37 = src/tile/tile.S src/tile/ffi.c -@XTENSA_TRUE@am__append_38 = src/xtensa/sysv.S src/xtensa/ffi.c -@METAG_TRUE@am__append_39 = src/metag/sysv.S src/metag/ffi.c -@VAX_TRUE@am__append_40 = src/vax/elfbsd.S src/vax/ffi.c -# Build debug. Define FFI_DEBUG on the commandline so that, when building with -# MSVC, it can link against the debug CRT. -@FFI_DEBUG_TRUE@am__append_41 = -DFFI_DEBUG -subdir = . -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/fficonfig.h.in $(srcdir)/libffi.pc.in depcomp \ - mdate-sh $(srcdir)/doc/version.texi $(srcdir)/doc/stamp-vti \ - texinfo.tex README compile config.guess config.sub install-sh \ - missing ltmain.sh -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \ - $(top_srcdir)/m4/ax_append_flag.m4 \ - $(top_srcdir)/m4/ax_cc_maxopt.m4 \ - $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_compiler_vendor.m4 \ - $(top_srcdir)/m4/ax_configure_args.m4 \ - $(top_srcdir)/m4/ax_enable_builddir.m4 \ - $(top_srcdir)/m4/ax_gcc_archflag.m4 \ - $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno config.status.lineno -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = fficonfig.h -CONFIG_CLEAN_FILES = libffi.pc -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \ - "$(DESTDIR)$(pkgconfigdir)" -LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES) -libffi_la_LIBADD = -am__dirstamp = $(am__leading_dot)dirstamp -am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \ - src/java_raw_api.lo src/closures.lo -@FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo -@MIPS_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \ -@MIPS_TRUE@ src/mips/n32.lo -@BFIN_TRUE@am__objects_3 = src/bfin/ffi.lo src/bfin/sysv.lo -@X86_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/sysv.lo \ -@X86_TRUE@ src/x86/win32.lo -@X86_FREEBSD_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/freebsd.lo \ -@X86_FREEBSD_TRUE@ src/x86/win32.lo -@X86_WIN32_TRUE@am__objects_6 = src/x86/ffi.lo src/x86/win32.lo -@X86_WIN64_TRUE@am__objects_7 = src/x86/ffi.lo src/x86/win64.lo -@X86_DARWIN_TRUE@am__objects_8 = src/x86/ffi.lo src/x86/darwin.lo \ -@X86_DARWIN_TRUE@ src/x86/ffi64.lo src/x86/darwin64.lo -@X86_DARWIN32_TRUE@@X86_DARWIN_TRUE@am__objects_9 = src/x86/win32.lo -@SPARC_TRUE@am__objects_10 = src/sparc/ffi.lo src/sparc/v8.lo \ -@SPARC_TRUE@ src/sparc/v9.lo -@ALPHA_TRUE@am__objects_11 = src/alpha/ffi.lo src/alpha/osf.lo -@IA64_TRUE@am__objects_12 = src/ia64/ffi.lo src/ia64/unix.lo -@M32R_TRUE@am__objects_13 = src/m32r/sysv.lo src/m32r/ffi.lo -@M68K_TRUE@am__objects_14 = src/m68k/ffi.lo src/m68k/sysv.lo -@M88K_TRUE@am__objects_15 = src/m88k/ffi.lo src/m88k/obsd.lo -@MOXIE_TRUE@am__objects_16 = src/moxie/ffi.lo src/moxie/eabi.lo -@MICROBLAZE_TRUE@am__objects_17 = src/microblaze/ffi.lo \ -@MICROBLAZE_TRUE@ src/microblaze/sysv.lo -@NIOS2_TRUE@am__objects_18 = src/nios2/sysv.lo src/nios2/ffi.lo -@OR1K_TRUE@am__objects_19 = src/or1k/sysv.lo src/or1k/ffi.lo -@POWERPC_TRUE@am__objects_20 = src/powerpc/ffi.lo \ -@POWERPC_TRUE@ src/powerpc/ffi_sysv.lo \ -@POWERPC_TRUE@ src/powerpc/ffi_linux64.lo src/powerpc/sysv.lo \ -@POWERPC_TRUE@ src/powerpc/ppc_closure.lo \ -@POWERPC_TRUE@ src/powerpc/linux64.lo \ -@POWERPC_TRUE@ src/powerpc/linux64_closure.lo -@POWERPC_AIX_TRUE@am__objects_21 = src/powerpc/ffi_darwin.lo \ -@POWERPC_AIX_TRUE@ src/powerpc/aix.lo \ -@POWERPC_AIX_TRUE@ src/powerpc/aix_closure.lo -@POWERPC_DARWIN_TRUE@am__objects_22 = src/powerpc/ffi_darwin.lo \ -@POWERPC_DARWIN_TRUE@ src/powerpc/darwin.lo \ -@POWERPC_DARWIN_TRUE@ src/powerpc/darwin_closure.lo -@POWERPC_FREEBSD_TRUE@am__objects_23 = src/powerpc/ffi.lo \ -@POWERPC_FREEBSD_TRUE@ src/powerpc/ffi_sysv.lo \ -@POWERPC_FREEBSD_TRUE@ src/powerpc/sysv.lo \ -@POWERPC_FREEBSD_TRUE@ src/powerpc/ppc_closure.lo -@AARCH64_TRUE@am__objects_24 = src/aarch64/sysv.lo src/aarch64/ffi.lo -@ARC_TRUE@am__objects_25 = src/arc/arcompact.lo src/arc/ffi.lo -@ARM_TRUE@am__objects_26 = src/arm/sysv.lo src/arm/ffi.lo -@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__objects_27 = src/arm/trampoline.lo -@AVR32_TRUE@am__objects_28 = src/avr32/sysv.lo src/avr32/ffi.lo -@LIBFFI_CRIS_TRUE@am__objects_29 = src/cris/sysv.lo src/cris/ffi.lo -@FRV_TRUE@am__objects_30 = src/frv/eabi.lo src/frv/ffi.lo -@S390_TRUE@am__objects_31 = src/s390/sysv.lo src/s390/ffi.lo -@X86_64_TRUE@am__objects_32 = src/x86/ffi64.lo src/x86/unix64.lo \ -@X86_64_TRUE@ src/x86/ffi.lo src/x86/sysv.lo -@SH_TRUE@am__objects_33 = src/sh/sysv.lo src/sh/ffi.lo -@SH64_TRUE@am__objects_34 = src/sh64/sysv.lo src/sh64/ffi.lo -@PA_LINUX_TRUE@am__objects_35 = src/pa/linux.lo src/pa/ffi.lo -@PA_HPUX_TRUE@am__objects_36 = src/pa/hpux32.lo src/pa/ffi.lo -@TILE_TRUE@am__objects_37 = src/tile/tile.lo src/tile/ffi.lo -@XTENSA_TRUE@am__objects_38 = src/xtensa/sysv.lo src/xtensa/ffi.lo -@METAG_TRUE@am__objects_39 = src/metag/sysv.lo src/metag/ffi.lo -@VAX_TRUE@am__objects_40 = src/vax/elfbsd.lo src/vax/ffi.lo -nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) $(am__objects_4) $(am__objects_5) \ - $(am__objects_6) $(am__objects_7) $(am__objects_8) \ - $(am__objects_9) $(am__objects_10) $(am__objects_11) \ - $(am__objects_12) $(am__objects_13) $(am__objects_14) \ - $(am__objects_15) $(am__objects_16) $(am__objects_17) \ - $(am__objects_18) $(am__objects_19) $(am__objects_20) \ - $(am__objects_21) $(am__objects_22) $(am__objects_23) \ - $(am__objects_24) $(am__objects_25) $(am__objects_26) \ - $(am__objects_27) $(am__objects_28) $(am__objects_29) \ - $(am__objects_30) $(am__objects_31) $(am__objects_32) \ - $(am__objects_33) $(am__objects_34) $(am__objects_35) \ - $(am__objects_36) $(am__objects_37) $(am__objects_38) \ - $(am__objects_39) $(am__objects_40) -libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \ - $(nodist_libffi_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libffi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libffi_la_LDFLAGS) $(LDFLAGS) -o $@ -libffi_convenience_la_LIBADD = -am__objects_41 = src/prep_cif.lo src/types.lo src/raw_api.lo \ - src/java_raw_api.lo src/closures.lo -am_libffi_convenience_la_OBJECTS = $(am__objects_41) -am__objects_42 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) $(am__objects_5) $(am__objects_6) \ - $(am__objects_7) $(am__objects_8) $(am__objects_9) \ - $(am__objects_10) $(am__objects_11) $(am__objects_12) \ - $(am__objects_13) $(am__objects_14) $(am__objects_15) \ - $(am__objects_16) $(am__objects_17) $(am__objects_18) \ - $(am__objects_19) $(am__objects_20) $(am__objects_21) \ - $(am__objects_22) $(am__objects_23) $(am__objects_24) \ - $(am__objects_25) $(am__objects_26) $(am__objects_27) \ - $(am__objects_28) $(am__objects_29) $(am__objects_30) \ - $(am__objects_31) $(am__objects_32) $(am__objects_33) \ - $(am__objects_34) $(am__objects_35) $(am__objects_36) \ - $(am__objects_37) $(am__objects_38) $(am__objects_39) \ - $(am__objects_40) -nodist_libffi_convenience_la_OBJECTS = $(am__objects_42) -libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \ - $(nodist_libffi_convenience_la_OBJECTS) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CCASFLAGS) $(CCASFLAGS) -AM_V_CPPAS = $(am__v_CPPAS_@AM_V@) -am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@) -am__v_CPPAS_0 = @echo " CPPAS " $@; -am__v_CPPAS_1 = -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) \ - $(libffi_convenience_la_SOURCES) \ - $(nodist_libffi_convenience_la_SOURCES) -DIST_SOURCES = $(libffi_la_SOURCES) $(libffi_convenience_la_SOURCES) -AM_V_DVIPS = $(am__v_DVIPS_@AM_V@) -am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@) -am__v_DVIPS_0 = @echo " DVIPS " $@; -am__v_DVIPS_1 = -AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@) -am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@) -am__v_MAKEINFO_0 = @echo " MAKEINFO" $@; -am__v_MAKEINFO_1 = -AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@) -am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@) -am__v_INFOHTML_0 = @echo " INFOHTML" $@; -am__v_INFOHTML_1 = -AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@) -am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@) -am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@; -am__v_TEXI2DVI_1 = -AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@) -am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@) -am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@; -am__v_TEXI2PDF_1 = -AM_V_texinfo = $(am__v_texinfo_@AM_V@) -am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@) -am__v_texinfo_0 = -q -am__v_texinfo_1 = -AM_V_texidevnull = $(am__v_texidevnull_@AM_V@) -am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@) -am__v_texidevnull_0 = > /dev/null -am__v_texidevnull_1 = -INFO_DEPS = $(srcdir)/doc/libffi.info -am__TEXINFO_TEX_DIR = $(srcdir) -DVIS = doc/libffi.dvi -PDFS = doc/libffi.pdf -PSS = doc/libffi.ps -HTMLS = doc/libffi.html -TEXINFOS = doc/libffi.texi -TEXI2DVI = texi2dvi -TEXI2PDF = $(TEXI2DVI) --pdf --batch -MAKEINFOHTML = $(MAKEINFO) --html -AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) -DVIPS = dvips -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -DATA = $(pkgconfig_DATA) -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)fficonfig.h.in -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -CSCOPE = cscope -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - if test -d "$(distdir)"; then \ - find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -rf "$(distdir)" \ - || { sleep 5 && rm -rf "$(distdir)"; }; \ - else :; fi -am__post_remove_distdir = $(am__remove_distdir) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -DIST_TARGETS = dist-gzip -distuninstallcheck_listfiles = find . -type f -print -am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ - | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' -distcleancheck_listfiles = find . -type f -print -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AM_LTLDFLAGS = @AM_LTLDFLAGS@ -AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ -HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PRTDIAG = @PRTDIAG@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TARGET = @TARGET@ -TARGETDIR = @TARGETDIR@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -ax_enable_builddir_sed = @ax_enable_builddir_sed@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sys_symbol_underscore = @sys_symbol_underscore@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -toolexecdir = @toolexecdir@ -toolexeclibdir = @toolexeclibdir@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign subdir-objects -ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include testsuite man -EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \ - src/aarch64/ffi.c src/aarch64/ffitarget.h src/aarch64/sysv.S \ - src/alpha/ffi.c src/alpha/osf.S \ - src/alpha/ffitarget.h src/arc/ffi.c src/arc/arcompact.S \ - src/arc/ffitarget.h src/arm/ffi.c src/arm/sysv.S \ - src/arm/ffitarget.h src/avr32/ffi.c src/avr32/sysv.S \ - src/avr32/ffitarget.h src/cris/ffi.c src/cris/sysv.S \ - src/cris/ffitarget.h src/ia64/ffi.c src/ia64/ffitarget.h \ - src/ia64/ia64_flags.h src/ia64/unix.S src/mips/ffi.c \ - src/mips/n32.S src/mips/o32.S src/metag/ffi.c \ - src/metag/ffitarget.h src/metag/sysv.S src/moxie/ffi.c \ - src/moxie/ffitarget.h src/moxie/eabi.S src/mips/ffitarget.h \ - src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \ - src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \ - src/m88k/ffi.c src/m88k/obsd.S src/m88k/ffitarget.h \ - src/microblaze/ffi.c src/microblaze/sysv.S \ - src/microblaze/ffitarget.h \ - src/nios2/ffi.c src/nios2/ffitarget.h src/nios2/sysv.S \ - src/or1k/ffi.c src/or1k/ffitarget.h src/or1k/sysv.S \ - src/powerpc/ffi.c src/powerpc/ffi_powerpc.h \ - src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \ - src/powerpc/sysv.S src/powerpc/linux64.S \ - src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \ - src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \ - src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \ - src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \ - src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \ - src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \ - src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \ - src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c \ - src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S \ - src/x86/win32.S src/x86/darwin.S src/x86/win64.S \ - src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S \ - src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c \ - src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c \ - src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S \ - src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c \ - src/tile/ffitarget.h src/tile/tile.S libtool-version \ - src/vax/ffi.c src/vax/ffitarget.h src/vax/elfbsd.S \ - src/xtensa/ffitarget.h src/xtensa/ffi.c src/xtensa/sysv.S \ - ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \ - m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ - m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh \ - generate-darwin-source-and-headers.py \ - libffi.xcodeproj/project.pbxproj src/arm/trampoline.S \ - libtool-ldflags ChangeLog.libffi-3.1 - -info_TEXINFOS = doc/libffi.texi - -# Work around what appears to be a GNU make bug handling MAKEFLAGS -# values defined in terms of make variables, as is the case for CC and -# friends when we are called from the top level Makefile. -AM_MAKEFLAGS = \ - 'AR_FLAGS=$(AR_FLAGS)' \ - 'CC_FOR_BUILD=$(CC_FOR_BUILD)' \ - 'CFLAGS=$(CFLAGS)' \ - 'CXXFLAGS=$(CXXFLAGS)' \ - 'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \ - 'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \ - 'INSTALL=$(INSTALL)' \ - 'INSTALL_DATA=$(INSTALL_DATA)' \ - 'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \ - 'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \ - 'JC1FLAGS=$(JC1FLAGS)' \ - 'LDFLAGS=$(LDFLAGS)' \ - 'LIBCFLAGS=$(LIBCFLAGS)' \ - 'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \ - 'MAKE=$(MAKE)' \ - 'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \ - 'PICFLAG=$(PICFLAG)' \ - 'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \ - 'RUNTESTFLAGS=$(RUNTESTFLAGS)' \ - 'SHELL=$(SHELL)' \ - 'exec_prefix=$(exec_prefix)' \ - 'infodir=$(infodir)' \ - 'libdir=$(libdir)' \ - 'mandir=$(mandir)' \ - 'prefix=$(prefix)' \ - 'AR=$(AR)' \ - 'AS=$(AS)' \ - 'CC=$(CC)' \ - 'CXX=$(CXX)' \ - 'LD=$(LD)' \ - 'NM=$(NM)' \ - 'RANLIB=$(RANLIB)' \ - 'DESTDIR=$(DESTDIR)' - - -# Subdir rules rely on $(FLAGS_TO_PASS) -FLAGS_TO_PASS = $(AM_MAKEFLAGS) -MAKEOVERRIDES = -toolexeclib_LTLIBRARIES = libffi.la -noinst_LTLIBRARIES = libffi_convenience.la -libffi_la_SOURCES = src/prep_cif.c src/types.c \ - src/raw_api.c src/java_raw_api.c src/closures.c - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libffi.pc -nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \ - $(am__append_3) $(am__append_4) $(am__append_5) \ - $(am__append_6) $(am__append_7) $(am__append_8) \ - $(am__append_9) $(am__append_10) $(am__append_11) \ - $(am__append_12) $(am__append_13) $(am__append_14) \ - $(am__append_15) $(am__append_16) $(am__append_17) \ - $(am__append_18) $(am__append_19) $(am__append_20) \ - $(am__append_21) $(am__append_22) $(am__append_23) \ - $(am__append_24) $(am__append_25) $(am__append_26) \ - $(am__append_27) $(am__append_28) $(am__append_29) \ - $(am__append_30) $(am__append_31) $(am__append_32) \ - $(am__append_33) $(am__append_34) $(am__append_35) \ - $(am__append_36) $(am__append_37) $(am__append_38) \ - $(am__append_39) $(am__append_40) -libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) -nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) -LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/libtool-ldflags $(LDFLAGS)) -AM_CFLAGS = $(am__append_41) -libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS) -AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src -AM_CCASFLAGS = $(AM_CPPFLAGS) -all: fficonfig.h - $(MAKE) $(AM_MAKEFLAGS) all-recursive - -.SUFFIXES: -.SUFFIXES: .S .c .dvi .lo .o .obj .ps -am--refresh: Makefile - @: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ - $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - $(am__cd) $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) -$(am__aclocal_m4_deps): - -fficonfig.h: stamp-h1 - @if test ! -f $@; then rm -f stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi - -stamp-h1: $(srcdir)/fficonfig.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status fficonfig.h -$(srcdir)/fficonfig.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f fficonfig.h stamp-h1 -libffi.pc: $(top_builddir)/config.status $(srcdir)/libffi.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $@ - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(toolexeclibdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \ - } - -uninstall-toolexeclibLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \ - done - -clean-toolexeclibLTLIBRARIES: - -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES) - @list='$(toolexeclib_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } -src/$(am__dirstamp): - @$(MKDIR_P) src - @: > src/$(am__dirstamp) -src/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/$(DEPDIR) - @: > src/$(DEPDIR)/$(am__dirstamp) -src/prep_cif.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/mips/$(am__dirstamp): - @$(MKDIR_P) src/mips - @: > src/mips/$(am__dirstamp) -src/mips/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/mips/$(DEPDIR) - @: > src/mips/$(DEPDIR)/$(am__dirstamp) -src/mips/ffi.lo: src/mips/$(am__dirstamp) \ - src/mips/$(DEPDIR)/$(am__dirstamp) -src/mips/o32.lo: src/mips/$(am__dirstamp) \ - src/mips/$(DEPDIR)/$(am__dirstamp) -src/mips/n32.lo: src/mips/$(am__dirstamp) \ - src/mips/$(DEPDIR)/$(am__dirstamp) -src/bfin/$(am__dirstamp): - @$(MKDIR_P) src/bfin - @: > src/bfin/$(am__dirstamp) -src/bfin/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/bfin/$(DEPDIR) - @: > src/bfin/$(DEPDIR)/$(am__dirstamp) -src/bfin/ffi.lo: src/bfin/$(am__dirstamp) \ - src/bfin/$(DEPDIR)/$(am__dirstamp) -src/bfin/sysv.lo: src/bfin/$(am__dirstamp) \ - src/bfin/$(DEPDIR)/$(am__dirstamp) -src/x86/$(am__dirstamp): - @$(MKDIR_P) src/x86 - @: > src/x86/$(am__dirstamp) -src/x86/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/x86/$(DEPDIR) - @: > src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/ffi.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/sysv.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/win32.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/freebsd.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/win64.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/ffi64.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin64.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/sparc/$(am__dirstamp): - @$(MKDIR_P) src/sparc - @: > src/sparc/$(am__dirstamp) -src/sparc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/sparc/$(DEPDIR) - @: > src/sparc/$(DEPDIR)/$(am__dirstamp) -src/sparc/ffi.lo: src/sparc/$(am__dirstamp) \ - src/sparc/$(DEPDIR)/$(am__dirstamp) -src/sparc/v8.lo: src/sparc/$(am__dirstamp) \ - src/sparc/$(DEPDIR)/$(am__dirstamp) -src/sparc/v9.lo: src/sparc/$(am__dirstamp) \ - src/sparc/$(DEPDIR)/$(am__dirstamp) -src/alpha/$(am__dirstamp): - @$(MKDIR_P) src/alpha - @: > src/alpha/$(am__dirstamp) -src/alpha/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/alpha/$(DEPDIR) - @: > src/alpha/$(DEPDIR)/$(am__dirstamp) -src/alpha/ffi.lo: src/alpha/$(am__dirstamp) \ - src/alpha/$(DEPDIR)/$(am__dirstamp) -src/alpha/osf.lo: src/alpha/$(am__dirstamp) \ - src/alpha/$(DEPDIR)/$(am__dirstamp) -src/ia64/$(am__dirstamp): - @$(MKDIR_P) src/ia64 - @: > src/ia64/$(am__dirstamp) -src/ia64/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/ia64/$(DEPDIR) - @: > src/ia64/$(DEPDIR)/$(am__dirstamp) -src/ia64/ffi.lo: src/ia64/$(am__dirstamp) \ - src/ia64/$(DEPDIR)/$(am__dirstamp) -src/ia64/unix.lo: src/ia64/$(am__dirstamp) \ - src/ia64/$(DEPDIR)/$(am__dirstamp) -src/m32r/$(am__dirstamp): - @$(MKDIR_P) src/m32r - @: > src/m32r/$(am__dirstamp) -src/m32r/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/m32r/$(DEPDIR) - @: > src/m32r/$(DEPDIR)/$(am__dirstamp) -src/m32r/sysv.lo: src/m32r/$(am__dirstamp) \ - src/m32r/$(DEPDIR)/$(am__dirstamp) -src/m32r/ffi.lo: src/m32r/$(am__dirstamp) \ - src/m32r/$(DEPDIR)/$(am__dirstamp) -src/m68k/$(am__dirstamp): - @$(MKDIR_P) src/m68k - @: > src/m68k/$(am__dirstamp) -src/m68k/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/m68k/$(DEPDIR) - @: > src/m68k/$(DEPDIR)/$(am__dirstamp) -src/m68k/ffi.lo: src/m68k/$(am__dirstamp) \ - src/m68k/$(DEPDIR)/$(am__dirstamp) -src/m68k/sysv.lo: src/m68k/$(am__dirstamp) \ - src/m68k/$(DEPDIR)/$(am__dirstamp) -src/m88k/$(am__dirstamp): - @$(MKDIR_P) src/m88k - @: > src/m88k/$(am__dirstamp) -src/m88k/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/m88k/$(DEPDIR) - @: > src/m88k/$(DEPDIR)/$(am__dirstamp) -src/m88k/ffi.lo: src/m88k/$(am__dirstamp) \ - src/m88k/$(DEPDIR)/$(am__dirstamp) -src/m88k/obsd.lo: src/m88k/$(am__dirstamp) \ - src/m88k/$(DEPDIR)/$(am__dirstamp) -src/moxie/$(am__dirstamp): - @$(MKDIR_P) src/moxie - @: > src/moxie/$(am__dirstamp) -src/moxie/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/moxie/$(DEPDIR) - @: > src/moxie/$(DEPDIR)/$(am__dirstamp) -src/moxie/ffi.lo: src/moxie/$(am__dirstamp) \ - src/moxie/$(DEPDIR)/$(am__dirstamp) -src/moxie/eabi.lo: src/moxie/$(am__dirstamp) \ - src/moxie/$(DEPDIR)/$(am__dirstamp) -src/microblaze/$(am__dirstamp): - @$(MKDIR_P) src/microblaze - @: > src/microblaze/$(am__dirstamp) -src/microblaze/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/microblaze/$(DEPDIR) - @: > src/microblaze/$(DEPDIR)/$(am__dirstamp) -src/microblaze/ffi.lo: src/microblaze/$(am__dirstamp) \ - src/microblaze/$(DEPDIR)/$(am__dirstamp) -src/microblaze/sysv.lo: src/microblaze/$(am__dirstamp) \ - src/microblaze/$(DEPDIR)/$(am__dirstamp) -src/nios2/$(am__dirstamp): - @$(MKDIR_P) src/nios2 - @: > src/nios2/$(am__dirstamp) -src/nios2/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/nios2/$(DEPDIR) - @: > src/nios2/$(DEPDIR)/$(am__dirstamp) -src/nios2/sysv.lo: src/nios2/$(am__dirstamp) \ - src/nios2/$(DEPDIR)/$(am__dirstamp) -src/nios2/ffi.lo: src/nios2/$(am__dirstamp) \ - src/nios2/$(DEPDIR)/$(am__dirstamp) -src/or1k/$(am__dirstamp): - @$(MKDIR_P) src/or1k - @: > src/or1k/$(am__dirstamp) -src/or1k/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/or1k/$(DEPDIR) - @: > src/or1k/$(DEPDIR)/$(am__dirstamp) -src/or1k/sysv.lo: src/or1k/$(am__dirstamp) \ - src/or1k/$(DEPDIR)/$(am__dirstamp) -src/or1k/ffi.lo: src/or1k/$(am__dirstamp) \ - src/or1k/$(DEPDIR)/$(am__dirstamp) -src/powerpc/$(am__dirstamp): - @$(MKDIR_P) src/powerpc - @: > src/powerpc/$(am__dirstamp) -src/powerpc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/powerpc/$(DEPDIR) - @: > src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/ffi.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/ffi_sysv.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/ffi_linux64.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/sysv.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/ppc_closure.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/linux64.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/linux64_closure.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/ffi_darwin.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/aix.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/aix_closure.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/darwin.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/powerpc/darwin_closure.lo: src/powerpc/$(am__dirstamp) \ - src/powerpc/$(DEPDIR)/$(am__dirstamp) -src/aarch64/$(am__dirstamp): - @$(MKDIR_P) src/aarch64 - @: > src/aarch64/$(am__dirstamp) -src/aarch64/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/aarch64/$(DEPDIR) - @: > src/aarch64/$(DEPDIR)/$(am__dirstamp) -src/aarch64/sysv.lo: src/aarch64/$(am__dirstamp) \ - src/aarch64/$(DEPDIR)/$(am__dirstamp) -src/aarch64/ffi.lo: src/aarch64/$(am__dirstamp) \ - src/aarch64/$(DEPDIR)/$(am__dirstamp) -src/arc/$(am__dirstamp): - @$(MKDIR_P) src/arc - @: > src/arc/$(am__dirstamp) -src/arc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/arc/$(DEPDIR) - @: > src/arc/$(DEPDIR)/$(am__dirstamp) -src/arc/arcompact.lo: src/arc/$(am__dirstamp) \ - src/arc/$(DEPDIR)/$(am__dirstamp) -src/arc/ffi.lo: src/arc/$(am__dirstamp) \ - src/arc/$(DEPDIR)/$(am__dirstamp) -src/arm/$(am__dirstamp): - @$(MKDIR_P) src/arm - @: > src/arm/$(am__dirstamp) -src/arm/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/arm/$(DEPDIR) - @: > src/arm/$(DEPDIR)/$(am__dirstamp) -src/arm/sysv.lo: src/arm/$(am__dirstamp) \ - src/arm/$(DEPDIR)/$(am__dirstamp) -src/arm/ffi.lo: src/arm/$(am__dirstamp) \ - src/arm/$(DEPDIR)/$(am__dirstamp) -src/arm/trampoline.lo: src/arm/$(am__dirstamp) \ - src/arm/$(DEPDIR)/$(am__dirstamp) -src/avr32/$(am__dirstamp): - @$(MKDIR_P) src/avr32 - @: > src/avr32/$(am__dirstamp) -src/avr32/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/avr32/$(DEPDIR) - @: > src/avr32/$(DEPDIR)/$(am__dirstamp) -src/avr32/sysv.lo: src/avr32/$(am__dirstamp) \ - src/avr32/$(DEPDIR)/$(am__dirstamp) -src/avr32/ffi.lo: src/avr32/$(am__dirstamp) \ - src/avr32/$(DEPDIR)/$(am__dirstamp) -src/cris/$(am__dirstamp): - @$(MKDIR_P) src/cris - @: > src/cris/$(am__dirstamp) -src/cris/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/cris/$(DEPDIR) - @: > src/cris/$(DEPDIR)/$(am__dirstamp) -src/cris/sysv.lo: src/cris/$(am__dirstamp) \ - src/cris/$(DEPDIR)/$(am__dirstamp) -src/cris/ffi.lo: src/cris/$(am__dirstamp) \ - src/cris/$(DEPDIR)/$(am__dirstamp) -src/frv/$(am__dirstamp): - @$(MKDIR_P) src/frv - @: > src/frv/$(am__dirstamp) -src/frv/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/frv/$(DEPDIR) - @: > src/frv/$(DEPDIR)/$(am__dirstamp) -src/frv/eabi.lo: src/frv/$(am__dirstamp) \ - src/frv/$(DEPDIR)/$(am__dirstamp) -src/frv/ffi.lo: src/frv/$(am__dirstamp) \ - src/frv/$(DEPDIR)/$(am__dirstamp) -src/s390/$(am__dirstamp): - @$(MKDIR_P) src/s390 - @: > src/s390/$(am__dirstamp) -src/s390/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/s390/$(DEPDIR) - @: > src/s390/$(DEPDIR)/$(am__dirstamp) -src/s390/sysv.lo: src/s390/$(am__dirstamp) \ - src/s390/$(DEPDIR)/$(am__dirstamp) -src/s390/ffi.lo: src/s390/$(am__dirstamp) \ - src/s390/$(DEPDIR)/$(am__dirstamp) -src/x86/unix64.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/sh/$(am__dirstamp): - @$(MKDIR_P) src/sh - @: > src/sh/$(am__dirstamp) -src/sh/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/sh/$(DEPDIR) - @: > src/sh/$(DEPDIR)/$(am__dirstamp) -src/sh/sysv.lo: src/sh/$(am__dirstamp) \ - src/sh/$(DEPDIR)/$(am__dirstamp) -src/sh/ffi.lo: src/sh/$(am__dirstamp) src/sh/$(DEPDIR)/$(am__dirstamp) -src/sh64/$(am__dirstamp): - @$(MKDIR_P) src/sh64 - @: > src/sh64/$(am__dirstamp) -src/sh64/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/sh64/$(DEPDIR) - @: > src/sh64/$(DEPDIR)/$(am__dirstamp) -src/sh64/sysv.lo: src/sh64/$(am__dirstamp) \ - src/sh64/$(DEPDIR)/$(am__dirstamp) -src/sh64/ffi.lo: src/sh64/$(am__dirstamp) \ - src/sh64/$(DEPDIR)/$(am__dirstamp) -src/pa/$(am__dirstamp): - @$(MKDIR_P) src/pa - @: > src/pa/$(am__dirstamp) -src/pa/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/pa/$(DEPDIR) - @: > src/pa/$(DEPDIR)/$(am__dirstamp) -src/pa/linux.lo: src/pa/$(am__dirstamp) \ - src/pa/$(DEPDIR)/$(am__dirstamp) -src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp) -src/pa/hpux32.lo: src/pa/$(am__dirstamp) \ - src/pa/$(DEPDIR)/$(am__dirstamp) -src/tile/$(am__dirstamp): - @$(MKDIR_P) src/tile - @: > src/tile/$(am__dirstamp) -src/tile/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/tile/$(DEPDIR) - @: > src/tile/$(DEPDIR)/$(am__dirstamp) -src/tile/tile.lo: src/tile/$(am__dirstamp) \ - src/tile/$(DEPDIR)/$(am__dirstamp) -src/tile/ffi.lo: src/tile/$(am__dirstamp) \ - src/tile/$(DEPDIR)/$(am__dirstamp) -src/xtensa/$(am__dirstamp): - @$(MKDIR_P) src/xtensa - @: > src/xtensa/$(am__dirstamp) -src/xtensa/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/xtensa/$(DEPDIR) - @: > src/xtensa/$(DEPDIR)/$(am__dirstamp) -src/xtensa/sysv.lo: src/xtensa/$(am__dirstamp) \ - src/xtensa/$(DEPDIR)/$(am__dirstamp) -src/xtensa/ffi.lo: src/xtensa/$(am__dirstamp) \ - src/xtensa/$(DEPDIR)/$(am__dirstamp) -src/metag/$(am__dirstamp): - @$(MKDIR_P) src/metag - @: > src/metag/$(am__dirstamp) -src/metag/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/metag/$(DEPDIR) - @: > src/metag/$(DEPDIR)/$(am__dirstamp) -src/metag/sysv.lo: src/metag/$(am__dirstamp) \ - src/metag/$(DEPDIR)/$(am__dirstamp) -src/metag/ffi.lo: src/metag/$(am__dirstamp) \ - src/metag/$(DEPDIR)/$(am__dirstamp) -src/vax/$(am__dirstamp): - @$(MKDIR_P) src/vax - @: > src/vax/$(am__dirstamp) -src/vax/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/vax/$(DEPDIR) - @: > src/vax/$(DEPDIR)/$(am__dirstamp) -src/vax/elfbsd.lo: src/vax/$(am__dirstamp) \ - src/vax/$(DEPDIR)/$(am__dirstamp) -src/vax/ffi.lo: src/vax/$(am__dirstamp) \ - src/vax/$(DEPDIR)/$(am__dirstamp) - -libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) $(EXTRA_libffi_la_DEPENDENCIES) - $(AM_V_CCLD)$(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS) - -libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES) $(EXTRA_libffi_convenience_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -rm -f src/*.$(OBJEXT) - -rm -f src/*.lo - -rm -f src/aarch64/*.$(OBJEXT) - -rm -f src/aarch64/*.lo - -rm -f src/alpha/*.$(OBJEXT) - -rm -f src/alpha/*.lo - -rm -f src/arc/*.$(OBJEXT) - -rm -f src/arc/*.lo - -rm -f src/arm/*.$(OBJEXT) - -rm -f src/arm/*.lo - -rm -f src/avr32/*.$(OBJEXT) - -rm -f src/avr32/*.lo - -rm -f src/bfin/*.$(OBJEXT) - -rm -f src/bfin/*.lo - -rm -f src/cris/*.$(OBJEXT) - -rm -f src/cris/*.lo - -rm -f src/frv/*.$(OBJEXT) - -rm -f src/frv/*.lo - -rm -f src/ia64/*.$(OBJEXT) - -rm -f src/ia64/*.lo - -rm -f src/m32r/*.$(OBJEXT) - -rm -f src/m32r/*.lo - -rm -f src/m68k/*.$(OBJEXT) - -rm -f src/m68k/*.lo - -rm -f src/m88k/*.$(OBJEXT) - -rm -f src/m88k/*.lo - -rm -f src/metag/*.$(OBJEXT) - -rm -f src/metag/*.lo - -rm -f src/microblaze/*.$(OBJEXT) - -rm -f src/microblaze/*.lo - -rm -f src/mips/*.$(OBJEXT) - -rm -f src/mips/*.lo - -rm -f src/moxie/*.$(OBJEXT) - -rm -f src/moxie/*.lo - -rm -f src/nios2/*.$(OBJEXT) - -rm -f src/nios2/*.lo - -rm -f src/or1k/*.$(OBJEXT) - -rm -f src/or1k/*.lo - -rm -f src/pa/*.$(OBJEXT) - -rm -f src/pa/*.lo - -rm -f src/powerpc/*.$(OBJEXT) - -rm -f src/powerpc/*.lo - -rm -f src/s390/*.$(OBJEXT) - -rm -f src/s390/*.lo - -rm -f src/sh/*.$(OBJEXT) - -rm -f src/sh/*.lo - -rm -f src/sh64/*.$(OBJEXT) - -rm -f src/sh64/*.lo - -rm -f src/sparc/*.$(OBJEXT) - -rm -f src/sparc/*.lo - -rm -f src/tile/*.$(OBJEXT) - -rm -f src/tile/*.lo - -rm -f src/vax/*.$(OBJEXT) - -rm -f src/vax/*.lo - -rm -f src/x86/*.$(OBJEXT) - -rm -f src/x86/*.lo - -rm -f src/xtensa/*.$(OBJEXT) - -rm -f src/xtensa/*.lo - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/closures.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/raw_api.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/arcompact.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/trampoline.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/eabi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/unix.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m88k/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/m88k/$(DEPDIR)/obsd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/metag/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/metag/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/microblaze/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/microblaze/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/n32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/o32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/eabi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/nios2/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/nios2/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/or1k/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/or1k/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/hpux32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/linux.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/aix.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/aix_closure.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/darwin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/darwin_closure.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_darwin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_linux64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/linux64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/linux64_closure.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ppc_closure.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v8.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v9.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/elfbsd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/freebsd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/sysv.Plo@am__quote@ - -.S.o: -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $< - -.S.obj: -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.S.lo: -@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LTCPPASCOMPILE) -c -o $@ $< - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -rm -rf src/.libs src/_libs - -rm -rf src/aarch64/.libs src/aarch64/_libs - -rm -rf src/alpha/.libs src/alpha/_libs - -rm -rf src/arc/.libs src/arc/_libs - -rm -rf src/arm/.libs src/arm/_libs - -rm -rf src/avr32/.libs src/avr32/_libs - -rm -rf src/bfin/.libs src/bfin/_libs - -rm -rf src/cris/.libs src/cris/_libs - -rm -rf src/frv/.libs src/frv/_libs - -rm -rf src/ia64/.libs src/ia64/_libs - -rm -rf src/m32r/.libs src/m32r/_libs - -rm -rf src/m68k/.libs src/m68k/_libs - -rm -rf src/m88k/.libs src/m88k/_libs - -rm -rf src/metag/.libs src/metag/_libs - -rm -rf src/microblaze/.libs src/microblaze/_libs - -rm -rf src/mips/.libs src/mips/_libs - -rm -rf src/moxie/.libs src/moxie/_libs - -rm -rf src/nios2/.libs src/nios2/_libs - -rm -rf src/or1k/.libs src/or1k/_libs - -rm -rf src/pa/.libs src/pa/_libs - -rm -rf src/powerpc/.libs src/powerpc/_libs - -rm -rf src/s390/.libs src/s390/_libs - -rm -rf src/sh/.libs src/sh/_libs - -rm -rf src/sh64/.libs src/sh64/_libs - -rm -rf src/sparc/.libs src/sparc/_libs - -rm -rf src/tile/.libs src/tile/_libs - -rm -rf src/vax/.libs src/vax/_libs - -rm -rf src/x86/.libs src/x86/_libs - -rm -rf src/xtensa/.libs src/xtensa/_libs - -distclean-libtool: - -rm -f libtool config.lt -doc/$(am__dirstamp): - @$(MKDIR_P) doc - @: > doc/$(am__dirstamp) - -$(srcdir)/doc/libffi.info: doc/libffi.texi $(srcdir)/doc/version.texi - $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \ - am__cwd=`pwd` && $(am__cd) $(srcdir) && \ - rm -rf $$backupdir && mkdir $$backupdir && \ - if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ - for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ - if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ - done; \ - else :; fi && \ - cd "$$am__cwd"; \ - if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc \ - -o $@ $(srcdir)/doc/libffi.texi; \ - then \ - rc=0; \ - $(am__cd) $(srcdir); \ - else \ - rc=$$?; \ - $(am__cd) $(srcdir) && \ - $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ - fi; \ - rm -rf $$backupdir; exit $$rc - -doc/libffi.dvi: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp) - $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc' \ - $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \ - `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi - -doc/libffi.pdf: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp) - $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc' \ - $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \ - `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi - -doc/libffi.html: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp) - $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp) - $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I doc -I $(srcdir)/doc \ - -o $(@:.html=.htp) `test -f 'doc/libffi.texi' || echo '$(srcdir)/'`doc/libffi.texi; \ - then \ - rm -rf $@; \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ - else \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ - exit 1; \ - fi -$(srcdir)/doc/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/doc/stamp-vti -$(srcdir)/doc/stamp-vti: doc/libffi.texi $(top_srcdir)/configure - test -f doc/$(am__dirstamp) || $(MAKE) $(AM_MAKEFLAGS) doc/$(am__dirstamp) - @(dir=.; test -f ./doc/libffi.texi || dir=$(srcdir); \ - set `$(SHELL) $(srcdir)/mdate-sh $$dir/doc/libffi.texi`; \ - echo "@set UPDATED $$1 $$2 $$3"; \ - echo "@set UPDATED-MONTH $$2 $$3"; \ - echo "@set EDITION $(VERSION)"; \ - echo "@set VERSION $(VERSION)") > vti.tmp - @cmp -s vti.tmp $(srcdir)/doc/version.texi \ - || (echo "Updating $(srcdir)/doc/version.texi"; \ - cp vti.tmp $(srcdir)/doc/version.texi) - -@rm -f vti.tmp - @cp $(srcdir)/doc/version.texi $@ - -mostlyclean-vti: - -rm -f vti.tmp - -maintainer-clean-vti: -@MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/doc/stamp-vti $(srcdir)/doc/version.texi -.dvi.ps: - $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - $(DVIPS) $(AM_V_texinfo) -o $@ $< - -uninstall-dvi-am: - @$(NORMAL_UNINSTALL) - @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ - rm -f "$(DESTDIR)$(dvidir)/$$f"; \ - done - -uninstall-html-am: - @$(NORMAL_UNINSTALL) - @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ - rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ - done - -uninstall-info-am: - @$(PRE_UNINSTALL) - @if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \ - list='$(INFO_DEPS)'; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ - if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ - then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ - done; \ - else :; fi - @$(NORMAL_UNINSTALL) - @list='$(INFO_DEPS)'; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ - (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ - echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ - rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ - else :; fi); \ - done - -uninstall-pdf-am: - @$(NORMAL_UNINSTALL) - @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ - rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ - done - -uninstall-ps-am: - @$(NORMAL_UNINSTALL) - @list='$(PSS)'; test -n "$(psdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ - rm -f "$(DESTDIR)$(psdir)/$$f"; \ - done - -dist-info: $(INFO_DEPS) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - list='$(INFO_DEPS)'; \ - for base in $$list; do \ - case $$base in \ - $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ - esac; \ - if test -f $$base; then d=.; else d=$(srcdir); fi; \ - base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ - for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ - if test -f $$file; then \ - relfile=`expr "$$file" : "$$d/\(.*\)"`; \ - test -f "$(distdir)/$$relfile" || \ - cp -p $$file "$(distdir)/$$relfile"; \ - else :; fi; \ - done; \ - done - -mostlyclean-aminfo: - -rm -rf doc/libffi.t2d doc/libffi.t2p - -clean-aminfo: - -test -z "doc/libffi.dvi doc/libffi.pdf doc/libffi.ps doc/libffi.html" \ - || rm -rf doc/libffi.dvi doc/libffi.pdf doc/libffi.ps doc/libffi.html - -maintainer-clean-aminfo: - @list='$(INFO_DEPS)'; for i in $$list; do \ - i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ - echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ - rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ - done -install-pkgconfigDATA: $(pkgconfig_DATA) - @$(NORMAL_INSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ - done - -uninstall-pkgconfigDATA: - @$(NORMAL_UNINSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) - -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ - fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-recursive - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscope: cscope.files - test ! -s cscope.files \ - || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) -clean-cscope: - -rm -f cscope.files -cscope.files: clean-cscope cscopelist -cscopelist: cscopelist-recursive - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -rm -f cscope.out cscope.in.out cscope.po.out cscope.files - -distdir: $(DISTFILES) - $(am__remove_distdir) - test -d "$(distdir)" || mkdir "$(distdir)" - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-info dist-hook - -test -n "$(am__skip_mode_fix)" \ - || find "$(distdir)" -type d ! -perm -755 \ - -exec chmod u+rwx,go+rx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r "$(distdir)" -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__post_remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 - $(am__post_remove_distdir) - -dist-lzip: distdir - tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz - $(am__post_remove_distdir) - -dist-xz: distdir - tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz - $(am__post_remove_distdir) - -dist-tarZ: distdir - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__post_remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__post_remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__post_remove_distdir) - -dist dist-all: - $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' - $(am__post_remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lz*) \ - lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ - *.tar.xz*) \ - xz -dc $(distdir).tar.xz | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir) - chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst - chmod a-w $(distdir) - test -d $(distdir)/_build || exit 0; \ - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(AM_DISTCHECK_CONFIGURE_FLAGS) \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ - && cd "$$am__cwd" \ - || exit 1 - $(am__post_remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' -distuninstallcheck: - @test -n '$(distuninstallcheck_dir)' || { \ - echo 'ERROR: trying to run $@ with an empty' \ - '$$(distuninstallcheck_dir)' >&2; \ - exit 1; \ - }; \ - $(am__cd) '$(distuninstallcheck_dir)' || { \ - echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ - exit 1; \ - }; \ - test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am -check: check-recursive -all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(DATA) fficonfig.h -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(pkgconfigdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f doc/$(am__dirstamp) - -rm -f src/$(DEPDIR)/$(am__dirstamp) - -rm -f src/$(am__dirstamp) - -rm -f src/aarch64/$(DEPDIR)/$(am__dirstamp) - -rm -f src/aarch64/$(am__dirstamp) - -rm -f src/alpha/$(DEPDIR)/$(am__dirstamp) - -rm -f src/alpha/$(am__dirstamp) - -rm -f src/arc/$(DEPDIR)/$(am__dirstamp) - -rm -f src/arc/$(am__dirstamp) - -rm -f src/arm/$(DEPDIR)/$(am__dirstamp) - -rm -f src/arm/$(am__dirstamp) - -rm -f src/avr32/$(DEPDIR)/$(am__dirstamp) - -rm -f src/avr32/$(am__dirstamp) - -rm -f src/bfin/$(DEPDIR)/$(am__dirstamp) - -rm -f src/bfin/$(am__dirstamp) - -rm -f src/cris/$(DEPDIR)/$(am__dirstamp) - -rm -f src/cris/$(am__dirstamp) - -rm -f src/frv/$(DEPDIR)/$(am__dirstamp) - -rm -f src/frv/$(am__dirstamp) - -rm -f src/ia64/$(DEPDIR)/$(am__dirstamp) - -rm -f src/ia64/$(am__dirstamp) - -rm -f src/m32r/$(DEPDIR)/$(am__dirstamp) - -rm -f src/m32r/$(am__dirstamp) - -rm -f src/m68k/$(DEPDIR)/$(am__dirstamp) - -rm -f src/m68k/$(am__dirstamp) - -rm -f src/m88k/$(DEPDIR)/$(am__dirstamp) - -rm -f src/m88k/$(am__dirstamp) - -rm -f src/metag/$(DEPDIR)/$(am__dirstamp) - -rm -f src/metag/$(am__dirstamp) - -rm -f src/microblaze/$(DEPDIR)/$(am__dirstamp) - -rm -f src/microblaze/$(am__dirstamp) - -rm -f src/mips/$(DEPDIR)/$(am__dirstamp) - -rm -f src/mips/$(am__dirstamp) - -rm -f src/moxie/$(DEPDIR)/$(am__dirstamp) - -rm -f src/moxie/$(am__dirstamp) - -rm -f src/nios2/$(DEPDIR)/$(am__dirstamp) - -rm -f src/nios2/$(am__dirstamp) - -rm -f src/or1k/$(DEPDIR)/$(am__dirstamp) - -rm -f src/or1k/$(am__dirstamp) - -rm -f src/pa/$(DEPDIR)/$(am__dirstamp) - -rm -f src/pa/$(am__dirstamp) - -rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp) - -rm -f src/powerpc/$(am__dirstamp) - -rm -f src/s390/$(DEPDIR)/$(am__dirstamp) - -rm -f src/s390/$(am__dirstamp) - -rm -f src/sh/$(DEPDIR)/$(am__dirstamp) - -rm -f src/sh/$(am__dirstamp) - -rm -f src/sh64/$(DEPDIR)/$(am__dirstamp) - -rm -f src/sh64/$(am__dirstamp) - -rm -f src/sparc/$(DEPDIR)/$(am__dirstamp) - -rm -f src/sparc/$(am__dirstamp) - -rm -f src/tile/$(DEPDIR)/$(am__dirstamp) - -rm -f src/tile/$(am__dirstamp) - -rm -f src/vax/$(DEPDIR)/$(am__dirstamp) - -rm -f src/vax/$(am__dirstamp) - -rm -f src/x86/$(DEPDIR)/$(am__dirstamp) - -rm -f src/x86/$(am__dirstamp) - -rm -f src/xtensa/$(DEPDIR)/$(am__dirstamp) - -rm -f src/xtensa/$(am__dirstamp) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-aminfo clean-generic clean-libtool \ - clean-noinstLTLIBRARIES clean-toolexeclibLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-tags - -dvi: dvi-recursive - -dvi-am: $(DVIS) - -html: html-recursive - -html-am: $(HTMLS) - -info: info-recursive - -info-am: $(INFO_DEPS) - -install-data-am: install-info-am install-pkgconfigDATA - -install-dvi: install-dvi-recursive - -install-dvi-am: $(DVIS) - @$(NORMAL_INSTALL) - @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ - done -install-exec-am: install-toolexeclibLTLIBRARIES - -install-html: install-html-recursive - -install-html-am: $(HTMLS) - @$(NORMAL_INSTALL) - @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ - $(am__strip_dir) \ - d2=$$d$$p; \ - if test -d "$$d2"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ - $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ - echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \ - $(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ - else \ - list2="$$list2 $$d2"; \ - fi; \ - done; \ - test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ - done; } -install-info: install-info-recursive - -install-info-am: $(INFO_DEPS) - @$(NORMAL_INSTALL) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \ - fi; \ - for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - esac; \ - if test -f $$file; then d=.; else d=$(srcdir); fi; \ - file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ - for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ - $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ - if test -f $$ifile; then \ - echo "$$ifile"; \ - else : ; fi; \ - done; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done - @$(POST_INSTALL) - @if $(am__can_run_installinfo); then \ - list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ - install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ - done; \ - else : ; fi -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: $(PDFS) - @$(NORMAL_INSTALL) - @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done -install-ps: install-ps-recursive - -install-ps-am: $(PSS) - @$(NORMAL_INSTALL) - @list='$(PSS)'; test -n "$(psdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-aminfo \ - maintainer-clean-generic maintainer-clean-vti - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-aminfo mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool mostlyclean-vti - -pdf: pdf-recursive - -pdf-am: $(PDFS) - -ps: ps-recursive - -ps-am: $(PSS) - -uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ - uninstall-pdf-am uninstall-pkgconfigDATA uninstall-ps-am \ - uninstall-toolexeclibLTLIBRARIES - -.MAKE: $(am__recursive_targets) all install-am install-strip - -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ - am--refresh check check-am clean clean-aminfo clean-cscope \ - clean-generic clean-libtool clean-noinstLTLIBRARIES \ - clean-toolexeclibLTLIBRARIES cscope cscopelist-am ctags \ - ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ - dist-info dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ - distcheck distclean distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-pdf install-pdf-am install-pkgconfigDATA \ - install-ps install-ps-am install-strip \ - install-toolexeclibLTLIBRARIES installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ - maintainer-clean-aminfo maintainer-clean-generic \ - maintainer-clean-vti mostlyclean mostlyclean-aminfo \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - mostlyclean-vti pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-dvi-am uninstall-html-am \ - uninstall-info-am uninstall-pdf-am uninstall-pkgconfigDATA \ - uninstall-ps-am uninstall-toolexeclibLTLIBRARIES - - -dist-hook: - if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ruby/ext/fiddle/libffi-3.2.1/README b/ruby/ext/fiddle/libffi-3.2.1/README deleted file mode 100644 index 5acc19d70..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/README +++ /dev/null @@ -1,447 +0,0 @@ -Status -====== - -libffi-3.2.1 was released on November 12, 2014. Check the libffi web -page for updates: . - - -What is libffi? -=============== - -Compilers for high level languages generate code that follow certain -conventions. These conventions are necessary, in part, for separate -compilation to work. One such convention is the "calling -convention". The "calling convention" is essentially a set of -assumptions made by the compiler about where function arguments will -be found on entry to a function. A "calling convention" also specifies -where the return value for a function is found. - -Some programs may not know at the time of compilation what arguments -are to be passed to a function. For instance, an interpreter may be -told at run-time about the number and types of arguments used to call -a given function. Libffi can be used in such programs to provide a -bridge from the interpreter program to compiled code. - -The libffi library provides a portable, high level programming -interface to various calling conventions. This allows a programmer to -call any function specified by a call interface description at run -time. - -FFI stands for Foreign Function Interface. A foreign function -interface is the popular name for the interface that allows code -written in one language to call code written in another language. The -libffi library really only provides the lowest, machine dependent -layer of a fully featured foreign function interface. A layer must -exist above libffi that handles type conversions for values passed -between the two languages. - - -Supported Platforms -=================== - -Libffi has been ported to many different platforms. -For specific configuration details and testing status, please -refer to the wiki page here: - - http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2 - -At the time of release, the following basic configurations have been -tested: - -|-----------------+------------------+-------------------------| -| Architecture | Operating System | Compiler | -|-----------------+------------------+-------------------------| -| AArch64 (ARM64) | iOS | Clang | -| AArch64 | Linux | GCC | -| Alpha | Linux | GCC | -| Alpha | Tru64 | GCC | -| ARC | Linux | GCC | -| ARM | Linux | GCC | -| ARM | iOS | GCC | -| AVR32 | Linux | GCC | -| Blackfin | uClinux | GCC | -| HPPA | HPUX | GCC | -| IA-64 | Linux | GCC | -| M68K | FreeMiNT | GCC | -| M68K | Linux | GCC | -| M68K | RTEMS | GCC | -| M88K | OpenBSD/mvme88k | GCC | -| Meta | Linux | GCC | -| MicroBlaze | Linux | GCC | -| MIPS | IRIX | GCC | -| MIPS | Linux | GCC | -| MIPS | RTEMS | GCC | -| MIPS64 | Linux | GCC | -| Moxie | Bare metal | GCC | -| Nios II | Linux | GCC | -| OpenRISC | Linux | GCC | -| PowerPC 32-bit | AIX | IBM XL C | -| PowerPC 64-bit | AIX | IBM XL C | -| PowerPC | AMIGA | GCC | -| PowerPC | Linux | GCC | -| PowerPC | Mac OSX | GCC | -| PowerPC | FreeBSD | GCC | -| PowerPC 64-bit | FreeBSD | GCC | -| PowerPC 64-bit | Linux ELFv1 | GCC | -| PowerPC 64-bit | Linux ELFv2 | GCC | -| S390 | Linux | GCC | -| S390X | Linux | GCC | -| SPARC | Linux | GCC | -| SPARC | Solaris | GCC | -| SPARC | Solaris | Oracle Solaris Studio C | -| SPARC64 | Linux | GCC | -| SPARC64 | FreeBSD | GCC | -| SPARC64 | Solaris | Oracle Solaris Studio C | -| TILE-Gx/TILEPro | Linux | GCC | -| VAX | OpenBSD/vax | GCC | -| X86 | FreeBSD | GCC | -| X86 | GNU HURD | GCC | -| X86 | Interix | GCC | -| X86 | kFreeBSD | GCC | -| X86 | Linux | GCC | -| X86 | Mac OSX | GCC | -| X86 | OpenBSD | GCC | -| X86 | OS/2 | GCC | -| X86 | Solaris | GCC | -| X86 | Solaris | Oracle Solaris Studio C | -| X86 | Windows/Cygwin | GCC | -| X86 | Windows/MingW | GCC | -| X86-64 | FreeBSD | GCC | -| X86-64 | Linux | GCC | -| X86-64 | Linux/x32 | GCC | -| X86-64 | OpenBSD | GCC | -| X86-64 | Solaris | Oracle Solaris Studio C | -| X86-64 | Windows/Cygwin | GCC | -| X86-64 | Windows/MingW | GCC | -| Xtensa | Linux | GCC | -|-----------------+------------------+-------------------------| - -Please send additional platform test results to -libffi-discuss@sourceware.org and feel free to update the wiki page -above. - -Installing libffi -================= - -First you must configure the distribution for your particular -system. Go to the directory you wish to build libffi in and run the -"configure" program found in the root directory of the libffi source -distribution. - -If you're building libffi directly from version control, configure won't -exist yet; run ./autogen.sh first. - -You may want to tell configure where to install the libffi library and -header files. To do that, use the --prefix configure switch. Libffi -will install under /usr/local by default. - -If you want to enable extra run-time debugging checks use the the ---enable-debug configure switch. This is useful when your program dies -mysteriously while using libffi. - -Another useful configure switch is --enable-purify-safety. Using this -will add some extra code which will suppress certain warnings when you -are using Purify with libffi. Only use this switch when using -Purify, as it will slow down the library. - -It's also possible to build libffi on Windows platforms with -Microsoft's Visual C++ compiler. In this case, use the msvcc.sh -wrapper script during configuration like so: - -path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP" - -For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and -CXX="path/to/msvcc.sh -m64". You may also need to specify --build -appropriately. - -It is also possible to build libffi on Windows platforms with the LLVM -project's clang-cl compiler, like below: - -path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP" - -When building with MSVC under a MingW environment, you may need to -remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath' -command. ('cygpath' is not present in MingW, and is not required when -using MingW-style paths.) - -For iOS builds, the 'libffi.xcodeproj' Xcode project is available. - -Configure has many other options. Use "configure --help" to see them all. - -Once configure has finished, type "make". Note that you must be using -GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make . - -To ensure that libffi is working as advertised, type "make check". -This will require that you have DejaGNU installed. - -To install the library and header files, type "make install". - - -History -======= - -See the git log for details at http://github.com/atgreen/libffi. - -3.2.1 Nov-12-14 - Build fix for non-iOS AArch64 targets. - -3.2 Nov-11-14 - Add C99 Complex Type support (currently only supported on - s390). - Add support for PASCAL and REGISTER calling conventions on x86 - Windows/Linux. - Add OpenRISC and Cygwin-64 support. - Bug fixes. - -3.1 May-19-14 - Add AArch64 (ARM64) iOS support. - Add Nios II support. - Add m88k and DEC VAX support. - Add support for stdcall, thiscall, and fastcall on non-Windows - 32-bit x86 targets such as Linux. - Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi - fixes. - Make the testsuite more robust: eliminate several spurious - failures, and respect the $CC and $CXX environment variables. - Archive off the manually maintained ChangeLog in favor of git - log. - -3.0.13 Mar-17-13 - Add Meta support. - Add missing Moxie bits. - Fix stack alignment bug on 32-bit x86. - Build fix for m68000 targets. - Build fix for soft-float Power targets. - Fix the install dir location for some platforms when building - with GCC (OS X, Solaris). - Fix Cygwin regression. - -3.0.12 Feb-11-13 - Add Moxie support. - Add AArch64 support. - Add Blackfin support. - Add TILE-Gx/TILEPro support. - Add MicroBlaze support. - Add Xtensa support. - Add support for PaX enabled kernels with MPROTECT. - Add support for native vendor compilers on - Solaris and AIX. - Work around LLVM/GCC interoperability issue on x86_64. - -3.0.11 Apr-11-12 - Lots of build fixes. - Add support for variadic functions (ffi_prep_cif_var). - Add Linux/x32 support. - Add thiscall, fastcall and MSVC cdecl support on Windows. - Add Amiga and newer MacOS support. - Add m68k FreeMiNT support. - Integration with iOS' xcode build tools. - Fix Octeon and MC68881 support. - Fix code pessimizations. - -3.0.10 Aug-23-11 - Add support for Apple's iOS. - Add support for ARM VFP ABI. - Add RTEMS support for MIPS and M68K. - Fix instruction cache clearing problems on - ARM and SPARC. - Fix the N64 build on mips-sgi-irix6.5. - Enable builds with Microsoft's compiler. - Enable x86 builds with Oracle's Solaris compiler. - Fix support for calling code compiled with Oracle's Sparc - Solaris compiler. - Testsuite fixes for Tru64 Unix. - Additional platform support. - -3.0.9 Dec-31-09 - Add AVR32 and win64 ports. Add ARM softfp support. - Many fixes for AIX, Solaris, HP-UX, *BSD. - Several PowerPC and x86-64 bug fixes. - Build DLL for windows. - -3.0.8 Dec-19-08 - Add *BSD, BeOS, and PA-Linux support. - -3.0.7 Nov-11-08 - Fix for ppc FreeBSD. - (thanks to Andreas Tobler) - -3.0.6 Jul-17-08 - Fix for closures on sh. - Mark the sh/sh64 stack as non-executable. - (both thanks to Kaz Kojima) - -3.0.5 Apr-3-08 - Fix libffi.pc file. - Fix #define ARM for IcedTea users. - Fix x86 closure bug. - -3.0.4 Feb-24-08 - Fix x86 OpenBSD configury. - -3.0.3 Feb-22-08 - Enable x86 OpenBSD thanks to Thomas Heller, and - x86-64 FreeBSD thanks to Björn König and Andreas Tobler. - Clean up test instruction in README. - -3.0.2 Feb-21-08 - Improved x86 FreeBSD support. - Thanks to Björn König. - -3.0.1 Feb-15-08 - Fix instruction cache flushing bug on MIPS. - Thanks to David Daney. - -3.0.0 Feb-15-08 - Many changes, mostly thanks to the GCC project. - Cygnus Solutions is now Red Hat. - - [10 years go by...] - -1.20 Oct-5-98 - Raffaele Sena produces ARM port. - -1.19 Oct-5-98 - Fixed x86 long double and long long return support. - m68k bug fixes from Andreas Schwab. - Patch for DU assembler compatibility for the Alpha from Richard - Henderson. - -1.18 Apr-17-98 - Bug fixes and MIPS configuration changes. - -1.17 Feb-24-98 - Bug fixes and m68k port from Andreas Schwab. PowerPC port from - Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. - -1.16 Feb-11-98 - Richard Henderson produces Alpha port. - -1.15 Dec-4-97 - Fixed an n32 ABI bug. New libtool, auto* support. - -1.14 May-13-97 - libtool is now used to generate shared and static libraries. - Fixed a minor portability problem reported by Russ McManus - . - -1.13 Dec-2-96 - Added --enable-purify-safety to keep Purify from complaining - about certain low level code. - Sparc fix for calling functions with < 6 args. - Linux x86 a.out fix. - -1.12 Nov-22-96 - Added missing ffi_type_void, needed for supporting void return - types. Fixed test case for non MIPS machines. Cygnus Support - is now Cygnus Solutions. - -1.11 Oct-30-96 - Added notes about GNU make. - -1.10 Oct-29-96 - Added configuration fix for non GNU compilers. - -1.09 Oct-29-96 - Added --enable-debug configure switch. Clean-ups based on LCLint - feedback. ffi_mips.h is always installed. Many configuration - fixes. Fixed ffitest.c for sparc builds. - -1.08 Oct-15-96 - Fixed n32 problem. Many clean-ups. - -1.07 Oct-14-96 - Gordon Irlam rewrites v8.S again. Bug fixes. - -1.06 Oct-14-96 - Gordon Irlam improved the sparc port. - -1.05 Oct-14-96 - Interface changes based on feedback. - -1.04 Oct-11-96 - Sparc port complete (modulo struct passing bug). - -1.03 Oct-10-96 - Passing struct args, and returning struct values works for - all architectures/calling conventions. Expanded tests. - -1.02 Oct-9-96 - Added SGI n32 support. Fixed bugs in both o32 and Linux support. - Added "make test". - -1.01 Oct-8-96 - Fixed float passing bug in mips version. Restructured some - of the code. Builds cleanly with SGI tools. - -1.00 Oct-7-96 - First release. No public announcement. - - -Authors & Credits -================= - -libffi was originally written by Anthony Green . - -The developers of the GNU Compiler Collection project have made -innumerable valuable contributions. See the ChangeLog file for -details. - -Some of the ideas behind libffi were inspired by Gianni Mariani's free -gencall library for Silicon Graphics machines. - -The closure mechanism was designed and implemented by Kresten Krab -Thorup. - -Major processor architecture ports were contributed by the following -developers: - -aarch64 Marcus Shawcroft, James Greenhalgh -alpha Richard Henderson -arm Raffaele Sena -blackfin Alexandre Keunecke I. de Mendonca -cris Simon Posnjak, Hans-Peter Nilsson -frv Anthony Green -ia64 Hans Boehm -m32r Kazuhiro Inaoka -m68k Andreas Schwab -m88k Miod Vallat -microblaze Nathan Rossi -mips Anthony Green, Casey Marshall -mips64 David Daney -moxie Anthony Green -nios ii Sandra Loosemore -openrisc Sebastian Macke -pa Randolph Chung, Dave Anglin, Andreas Tobler -powerpc Geoffrey Keating, Andreas Tobler, - David Edelsohn, John Hornkvist -powerpc64 Jakub Jelinek -s390 Gerhard Tonn, Ulrich Weigand -sh Kaz Kojima -sh64 Kaz Kojima -sparc Anthony Green, Gordon Irlam -tile-gx/tilepro Walter Lee -vax Miod Vallat -x86 Anthony Green, Jon Beniston -x86-64 Bo Thorsen -xtensa Chris Zankel - -Jesper Skov and Andrew Haley both did more than their fair share of -stepping through the code and tracking down bugs. - -Thanks also to Tom Tromey for bug fixes, documentation and -configuration help. - -Thanks to Jim Blandy, who provided some useful feedback on the libffi -interface. - -Andreas Tobler has done a tremendous amount of work on the testsuite. - -Alex Oliva solved the executable page problem for SElinux. - -The list above is almost certainly incomplete and inaccurate. I'm -happy to make corrections or additions upon request. - -If you have a problem, or have found a bug, please send a note to the -author at green@moxielogic.com, or the project mailing list at -libffi-discuss@sourceware.org. diff --git a/ruby/ext/fiddle/libffi-3.2.1/acinclude.m4 b/ruby/ext/fiddle/libffi-3.2.1/acinclude.m4 deleted file mode 100644 index 3e8f8ba57..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/acinclude.m4 +++ /dev/null @@ -1,92 +0,0 @@ -# mmap(2) blacklisting. Some platforms provide the mmap library routine -# but don't support all of the features we need from it. -AC_DEFUN([AC_FUNC_MMAP_BLACKLIST], -[ -AC_CHECK_HEADER([sys/mman.h], - [libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no]) -AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no]) -if test "$libffi_header_sys_mman_h" != yes \ - || test "$libffi_func_mmap" != yes; then - ac_cv_func_mmap_file=no - ac_cv_func_mmap_dev_zero=no - ac_cv_func_mmap_anon=no -else - AC_CACHE_CHECK([whether read-only mmap of a plain file works], - ac_cv_func_mmap_file, - [# Add a system to this blacklist if - # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a - # memory area containing the same data that you'd get if you applied - # read() to the same fd. The only system known to have a problem here - # is VMS, where text files have record structure. - case "$host_os" in - vms* | ultrix*) - ac_cv_func_mmap_file=no ;; - *) - ac_cv_func_mmap_file=yes;; - esac]) - AC_CACHE_CHECK([whether mmap from /dev/zero works], - ac_cv_func_mmap_dev_zero, - [# Add a system to this blacklist if it has mmap() but /dev/zero - # does not exist, or if mmapping /dev/zero does not give anonymous - # zeroed pages with both the following properties: - # 1. If you map N consecutive pages in with one call, and then - # unmap any subset of those pages, the pages that were not - # explicitly unmapped remain accessible. - # 2. If you map two adjacent blocks of memory and then unmap them - # both at once, they must both go away. - # Systems known to be in this category are Windows (all variants), - # VMS, and Darwin. - case "$host_os" in - vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00) - ac_cv_func_mmap_dev_zero=no ;; - *) - ac_cv_func_mmap_dev_zero=yes;; - esac]) - - # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. - AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon, - [AC_TRY_COMPILE( -[#include -#include -#include - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -], -[int n = MAP_ANONYMOUS;], - ac_cv_decl_map_anon=yes, - ac_cv_decl_map_anon=no)]) - - if test $ac_cv_decl_map_anon = no; then - ac_cv_func_mmap_anon=no - else - AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works], - ac_cv_func_mmap_anon, - [# Add a system to this blacklist if it has mmap() and MAP_ANON or - # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) - # doesn't give anonymous zeroed pages with the same properties listed - # above for use of /dev/zero. - # Systems known to be in this category are Windows, VMS, and SCO Unix. - case "$host_os" in - vms* | cygwin* | pe | mingw* | sco* | udk* ) - ac_cv_func_mmap_anon=no ;; - *) - ac_cv_func_mmap_anon=yes;; - esac]) - fi -fi - -if test $ac_cv_func_mmap_file = yes; then - AC_DEFINE(HAVE_MMAP_FILE, 1, - [Define if read-only mmap of a plain file works.]) -fi -if test $ac_cv_func_mmap_dev_zero = yes; then - AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1, - [Define if mmap of /dev/zero works.]) -fi -if test $ac_cv_func_mmap_anon = yes; then - AC_DEFINE(HAVE_MMAP_ANON, 1, - [Define if mmap with MAP_ANON(YMOUS) works.]) -fi -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/aclocal.m4 b/ruby/ext/fiddle/libffi-3.2.1/aclocal.m4 deleted file mode 100644 index 6292fbab7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/aclocal.m4 +++ /dev/null @@ -1,1961 +0,0 @@ -# generated automatically by aclocal 1.13.4 -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. - -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, -[m4_warning([this file was generated for autoconf 2.69. -You have another version of autoconf. It may work, but is not guaranteed to. -If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically 'autoreconf'.])]) - -# ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- -# -# Copyright (C) 1999-2006, 2007, 2008, 2011 Free Software Foundation, Inc. -# Written by Thomas Tanner, 1999 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 18 LTDL_INIT - -# LT_CONFIG_LTDL_DIR(DIRECTORY, [LTDL-MODE]) -# ------------------------------------------ -# DIRECTORY contains the libltdl sources. It is okay to call this -# function multiple times, as long as the same DIRECTORY is always given. -AC_DEFUN([LT_CONFIG_LTDL_DIR], -[AC_BEFORE([$0], [LTDL_INIT]) -_$0($*) -])# LT_CONFIG_LTDL_DIR - -# We break this out into a separate macro, so that we can call it safely -# internally without being caught accidentally by the sed scan in libtoolize. -m4_defun([_LT_CONFIG_LTDL_DIR], -[dnl remove trailing slashes -m4_pushdef([_ARG_DIR], m4_bpatsubst([$1], [/*$])) -m4_case(_LTDL_DIR, - [], [dnl only set lt_ltdl_dir if _ARG_DIR is not simply `.' - m4_if(_ARG_DIR, [.], - [], - [m4_define([_LTDL_DIR], _ARG_DIR) - _LT_SHELL_INIT([lt_ltdl_dir=']_ARG_DIR['])])], - [m4_if(_ARG_DIR, _LTDL_DIR, - [], - [m4_fatal([multiple libltdl directories: `]_LTDL_DIR[', `]_ARG_DIR['])])]) -m4_popdef([_ARG_DIR]) -])# _LT_CONFIG_LTDL_DIR - -# Initialise: -m4_define([_LTDL_DIR], []) - - -# _LT_BUILD_PREFIX -# ---------------- -# If Autoconf is new enough, expand to `${top_build_prefix}', otherwise -# to `${top_builddir}/'. -m4_define([_LT_BUILD_PREFIX], -[m4_ifdef([AC_AUTOCONF_VERSION], - [m4_if(m4_version_compare(m4_defn([AC_AUTOCONF_VERSION]), [2.62]), - [-1], [m4_ifdef([_AC_HAVE_TOP_BUILD_PREFIX], - [${top_build_prefix}], - [${top_builddir}/])], - [${top_build_prefix}])], - [${top_builddir}/])[]dnl -]) - - -# LTDL_CONVENIENCE -# ---------------- -# sets LIBLTDL to the link flags for the libltdl convenience library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called here. LIBLTDL will be prefixed with -# '${top_build_prefix}' if available, otherwise with '${top_builddir}/', -# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single -# quotes!). If your package is not flat and you're not using automake, -# define top_build_prefix, top_builddir, and top_srcdir appropriately -# in your Makefiles. -AC_DEFUN([LTDL_CONVENIENCE], -[AC_BEFORE([$0], [LTDL_INIT])dnl -dnl Although the argument is deprecated and no longer documented, -dnl LTDL_CONVENIENCE used to take a DIRECTORY orgument, if we have one -dnl here make sure it is the same as any other declaration of libltdl's -dnl location! This also ensures lt_ltdl_dir is set when configure.ac is -dnl not yet using an explicit LT_CONFIG_LTDL_DIR. -m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl -_$0() -])# LTDL_CONVENIENCE - -# AC_LIBLTDL_CONVENIENCE accepted a directory argument in older libtools, -# now we have LT_CONFIG_LTDL_DIR: -AU_DEFUN([AC_LIBLTDL_CONVENIENCE], -[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])]) -_LTDL_CONVENIENCE]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBLTDL_CONVENIENCE], []) - - -# _LTDL_CONVENIENCE -# ----------------- -# Code shared by LTDL_CONVENIENCE and LTDL_INIT([convenience]). -m4_defun([_LTDL_CONVENIENCE], -[case $enable_ltdl_convenience in - no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; - "") enable_ltdl_convenience=yes - ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; -esac -LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdlc.la" -LTDLDEPS=$LIBLTDL -LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}" - -AC_SUBST([LIBLTDL]) -AC_SUBST([LTDLDEPS]) -AC_SUBST([LTDLINCL]) - -# For backwards non-gettext consistent compatibility... -INCLTDL="$LTDLINCL" -AC_SUBST([INCLTDL]) -])# _LTDL_CONVENIENCE - - -# LTDL_INSTALLABLE -# ---------------- -# sets LIBLTDL to the link flags for the libltdl installable library -# and LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called from here. If an installed libltdl -# is not found, LIBLTDL will be prefixed with '${top_build_prefix}' if -# available, otherwise with '${top_builddir}/', and LTDLINCL will be -# prefixed with '${top_srcdir}/' (note the single quotes!). If your -# package is not flat and you're not using automake, define top_build_prefix, -# top_builddir, and top_srcdir appropriately in your Makefiles. -# In the future, this macro may have to be called after LT_INIT. -AC_DEFUN([LTDL_INSTALLABLE], -[AC_BEFORE([$0], [LTDL_INIT])dnl -dnl Although the argument is deprecated and no longer documented, -dnl LTDL_INSTALLABLE used to take a DIRECTORY orgument, if we have one -dnl here make sure it is the same as any other declaration of libltdl's -dnl location! This also ensures lt_ltdl_dir is set when configure.ac is -dnl not yet using an explicit LT_CONFIG_LTDL_DIR. -m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl -_$0() -])# LTDL_INSTALLABLE - -# AC_LIBLTDL_INSTALLABLE accepted a directory argument in older libtools, -# now we have LT_CONFIG_LTDL_DIR: -AU_DEFUN([AC_LIBLTDL_INSTALLABLE], -[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])]) -_LTDL_INSTALLABLE]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBLTDL_INSTALLABLE], []) - - -# _LTDL_INSTALLABLE -# ----------------- -# Code shared by LTDL_INSTALLABLE and LTDL_INIT([installable]). -m4_defun([_LTDL_INSTALLABLE], -[if test -f $prefix/lib/libltdl.la; then - lt_save_LDFLAGS="$LDFLAGS" - LDFLAGS="-L$prefix/lib $LDFLAGS" - AC_CHECK_LIB([ltdl], [lt_dlinit], [lt_lib_ltdl=yes]) - LDFLAGS="$lt_save_LDFLAGS" - if test x"${lt_lib_ltdl-no}" = xyes; then - if test x"$enable_ltdl_install" != xyes; then - # Don't overwrite $prefix/lib/libltdl.la without --enable-ltdl-install - AC_MSG_WARN([not overwriting libltdl at $prefix, force with `--enable-ltdl-install']) - enable_ltdl_install=no - fi - elif test x"$enable_ltdl_install" = xno; then - AC_MSG_WARN([libltdl not installed, but installation disabled]) - fi -fi - -# If configure.ac declared an installable ltdl, and the user didn't override -# with --disable-ltdl-install, we will install the shipped libltdl. -case $enable_ltdl_install in - no) ac_configure_args="$ac_configure_args --enable-ltdl-install=no" - LIBLTDL="-lltdl" - LTDLDEPS= - LTDLINCL= - ;; - *) enable_ltdl_install=yes - ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdl.la" - LTDLDEPS=$LIBLTDL - LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}" - ;; -esac - -AC_SUBST([LIBLTDL]) -AC_SUBST([LTDLDEPS]) -AC_SUBST([LTDLINCL]) - -# For backwards non-gettext consistent compatibility... -INCLTDL="$LTDLINCL" -AC_SUBST([INCLTDL]) -])# LTDL_INSTALLABLE - - -# _LTDL_MODE_DISPATCH -# ------------------- -m4_define([_LTDL_MODE_DISPATCH], -[dnl If _LTDL_DIR is `.', then we are configuring libltdl itself: -m4_if(_LTDL_DIR, [], - [], - dnl if _LTDL_MODE was not set already, the default value is `subproject': - [m4_case(m4_default(_LTDL_MODE, [subproject]), - [subproject], [AC_CONFIG_SUBDIRS(_LTDL_DIR) - _LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"])], - [nonrecursive], [_LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"; lt_libobj_prefix="$lt_ltdl_dir/"])], - [recursive], [], - [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])dnl -dnl Be careful not to expand twice: -m4_define([$0], []) -])# _LTDL_MODE_DISPATCH - - -# _LT_LIBOBJ(MODULE_NAME) -# ----------------------- -# Like AC_LIBOBJ, except that MODULE_NAME goes into _LT_LIBOBJS instead -# of into LIBOBJS. -AC_DEFUN([_LT_LIBOBJ], [ - m4_pattern_allow([^_LT_LIBOBJS$]) - _LT_LIBOBJS="$_LT_LIBOBJS $1.$ac_objext" -])# _LT_LIBOBJS - - -# LTDL_INIT([OPTIONS]) -# -------------------- -# Clients of libltdl can use this macro to allow the installer to -# choose between a shipped copy of the ltdl sources or a preinstalled -# version of the library. If the shipped ltdl sources are not in a -# subdirectory named libltdl, the directory name must be given by -# LT_CONFIG_LTDL_DIR. -AC_DEFUN([LTDL_INIT], -[dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -dnl We need to keep our own list of libobjs separate from our parent project, -dnl and the easiest way to do that is redefine the AC_LIBOBJs macro while -dnl we look for our own LIBOBJs. -m4_pushdef([AC_LIBOBJ], m4_defn([_LT_LIBOBJ])) -m4_pushdef([AC_LIBSOURCES]) - -dnl If not otherwise defined, default to the 1.5.x compatible subproject mode: -m4_if(_LTDL_MODE, [], - [m4_define([_LTDL_MODE], m4_default([$2], [subproject])) - m4_if([-1], [m4_bregexp(_LTDL_MODE, [\(subproject\|\(non\)?recursive\)])], - [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])]) - -AC_ARG_WITH([included_ltdl], - [AS_HELP_STRING([--with-included-ltdl], - [use the GNU ltdl sources included here])]) - -if test "x$with_included_ltdl" != xyes; then - # We are not being forced to use the included libltdl sources, so - # decide whether there is a useful installed version we can use. - AC_CHECK_HEADER([ltdl.h], - [AC_CHECK_DECL([lt_dlinterface_register], - [AC_CHECK_LIB([ltdl], [lt_dladvise_preload], - [with_included_ltdl=no], - [with_included_ltdl=yes])], - [with_included_ltdl=yes], - [AC_INCLUDES_DEFAULT - #include ])], - [with_included_ltdl=yes], - [AC_INCLUDES_DEFAULT] - ) -fi - -dnl If neither LT_CONFIG_LTDL_DIR, LTDL_CONVENIENCE nor LTDL_INSTALLABLE -dnl was called yet, then for old times' sake, we assume libltdl is in an -dnl eponymous directory: -AC_PROVIDE_IFELSE([LT_CONFIG_LTDL_DIR], [], [_LT_CONFIG_LTDL_DIR([libltdl])]) - -AC_ARG_WITH([ltdl_include], - [AS_HELP_STRING([--with-ltdl-include=DIR], - [use the ltdl headers installed in DIR])]) - -if test -n "$with_ltdl_include"; then - if test -f "$with_ltdl_include/ltdl.h"; then : - else - AC_MSG_ERROR([invalid ltdl include directory: `$with_ltdl_include']) - fi -else - with_ltdl_include=no -fi - -AC_ARG_WITH([ltdl_lib], - [AS_HELP_STRING([--with-ltdl-lib=DIR], - [use the libltdl.la installed in DIR])]) - -if test -n "$with_ltdl_lib"; then - if test -f "$with_ltdl_lib/libltdl.la"; then : - else - AC_MSG_ERROR([invalid ltdl library directory: `$with_ltdl_lib']) - fi -else - with_ltdl_lib=no -fi - -case ,$with_included_ltdl,$with_ltdl_include,$with_ltdl_lib, in - ,yes,no,no,) - m4_case(m4_default(_LTDL_TYPE, [convenience]), - [convenience], [_LTDL_CONVENIENCE], - [installable], [_LTDL_INSTALLABLE], - [m4_fatal([unknown libltdl build type: ]_LTDL_TYPE)]) - ;; - ,no,no,no,) - # If the included ltdl is not to be used, then use the - # preinstalled libltdl we found. - AC_DEFINE([HAVE_LTDL], [1], - [Define this if a modern libltdl is already installed]) - LIBLTDL=-lltdl - LTDLDEPS= - LTDLINCL= - ;; - ,no*,no,*) - AC_MSG_ERROR([`--with-ltdl-include' and `--with-ltdl-lib' options must be used together]) - ;; - *) with_included_ltdl=no - LIBLTDL="-L$with_ltdl_lib -lltdl" - LTDLDEPS= - LTDLINCL="-I$with_ltdl_include" - ;; -esac -INCLTDL="$LTDLINCL" - -# Report our decision... -AC_MSG_CHECKING([where to find libltdl headers]) -AC_MSG_RESULT([$LTDLINCL]) -AC_MSG_CHECKING([where to find libltdl library]) -AC_MSG_RESULT([$LIBLTDL]) - -_LTDL_SETUP - -dnl restore autoconf definition. -m4_popdef([AC_LIBOBJ]) -m4_popdef([AC_LIBSOURCES]) - -AC_CONFIG_COMMANDS_PRE([ - _ltdl_libobjs= - _ltdl_ltlibobjs= - if test -n "$_LT_LIBOBJS"; then - # Remove the extension. - _lt_sed_drop_objext='s/\.o$//;s/\.obj$//' - for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do - _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext" - _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo" - done - fi - AC_SUBST([ltdl_LIBOBJS], [$_ltdl_libobjs]) - AC_SUBST([ltdl_LTLIBOBJS], [$_ltdl_ltlibobjs]) -]) - -# Only expand once: -m4_define([LTDL_INIT]) -])# LTDL_INIT - -# Old names: -AU_DEFUN([AC_LIB_LTDL], [LTDL_INIT($@)]) -AU_DEFUN([AC_WITH_LTDL], [LTDL_INIT($@)]) -AU_DEFUN([LT_WITH_LTDL], [LTDL_INIT($@)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIB_LTDL], []) -dnl AC_DEFUN([AC_WITH_LTDL], []) -dnl AC_DEFUN([LT_WITH_LTDL], []) - - -# _LTDL_SETUP -# ----------- -# Perform all the checks necessary for compilation of the ltdl objects -# -- including compiler checks and header checks. This is a public -# interface mainly for the benefit of libltdl's own configure.ac, most -# other users should call LTDL_INIT instead. -AC_DEFUN([_LTDL_SETUP], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_SYS_MODULE_EXT])dnl -AC_REQUIRE([LT_SYS_MODULE_PATH])dnl -AC_REQUIRE([LT_SYS_DLSEARCH_PATH])dnl -AC_REQUIRE([LT_LIB_DLLOAD])dnl -AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl -AC_REQUIRE([LT_FUNC_DLSYM_USCORE])dnl -AC_REQUIRE([LT_SYS_DLOPEN_DEPLIBS])dnl -AC_REQUIRE([gl_FUNC_ARGZ])dnl - -m4_require([_LT_CHECK_OBJDIR])dnl -m4_require([_LT_HEADER_DLFCN])dnl -m4_require([_LT_CHECK_DLPREOPEN])dnl -m4_require([_LT_DECL_SED])dnl - -dnl Don't require this, or it will be expanded earlier than the code -dnl that sets the variables it relies on: -_LT_ENABLE_INSTALL - -dnl _LTDL_MODE specific code must be called at least once: -_LTDL_MODE_DISPATCH - -# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS -# the user used. This is so that ltdl.h can pick up the parent projects -# config.h file, The first file in AC_CONFIG_HEADERS must contain the -# definitions required by ltdl.c. -# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility). -AC_CONFIG_COMMANDS_PRE([dnl -m4_pattern_allow([^LT_CONFIG_H$])dnl -m4_ifset([AH_HEADER], - [LT_CONFIG_H=AH_HEADER], - [m4_ifset([AC_LIST_HEADERS], - [LT_CONFIG_H=`echo "AC_LIST_HEADERS" | $SED 's,^[[ ]]*,,;s,[[ :]].*$,,'`], - [])])]) -AC_SUBST([LT_CONFIG_H]) - -AC_CHECK_HEADERS([unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h], - [], [], [AC_INCLUDES_DEFAULT]) - -AC_CHECK_FUNCS([closedir opendir readdir], [], [AC_LIBOBJ([lt__dirent])]) -AC_CHECK_FUNCS([strlcat strlcpy], [], [AC_LIBOBJ([lt__strl])]) - -m4_pattern_allow([LT_LIBEXT])dnl -AC_DEFINE_UNQUOTED([LT_LIBEXT],["$libext"],[The archive extension]) - -name= -eval "lt_libprefix=\"$libname_spec\"" -m4_pattern_allow([LT_LIBPREFIX])dnl -AC_DEFINE_UNQUOTED([LT_LIBPREFIX],["$lt_libprefix"],[The archive prefix]) - -name=ltdl -eval "LTDLOPEN=\"$libname_spec\"" -AC_SUBST([LTDLOPEN]) -])# _LTDL_SETUP - - -# _LT_ENABLE_INSTALL -# ------------------ -m4_define([_LT_ENABLE_INSTALL], -[AC_ARG_ENABLE([ltdl-install], - [AS_HELP_STRING([--enable-ltdl-install], [install libltdl])]) - -case ,${enable_ltdl_install},${enable_ltdl_convenience} in - *yes*) ;; - *) enable_ltdl_convenience=yes ;; -esac - -m4_ifdef([AM_CONDITIONAL], -[AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) - AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno)]) -])# _LT_ENABLE_INSTALL - - -# LT_SYS_DLOPEN_DEPLIBS -# --------------------- -AC_DEFUN([LT_SYS_DLOPEN_DEPLIBS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_CACHE_CHECK([whether deplibs are loaded by dlopen], - [lt_cv_sys_dlopen_deplibs], - [# PORTME does your system automatically load deplibs for dlopen? - # or its logical equivalent (e.g. shl_load for HP-UX < 11) - # For now, we just catch OSes we know something about -- in the - # future, we'll try test this programmatically. - lt_cv_sys_dlopen_deplibs=unknown - case $host_os in - aix3*|aix4.1.*|aix4.2.*) - # Unknown whether this is true for these versions of AIX, but - # we want this `case' here to explicitly catch those versions. - lt_cv_sys_dlopen_deplibs=unknown - ;; - aix[[4-9]]*) - lt_cv_sys_dlopen_deplibs=yes - ;; - amigaos*) - case $host_cpu in - powerpc) - lt_cv_sys_dlopen_deplibs=no - ;; - esac - ;; - darwin*) - # Assuming the user has installed a libdl from somewhere, this is true - # If you are looking for one http://www.opendarwin.org/projects/dlcompat - lt_cv_sys_dlopen_deplibs=yes - ;; - freebsd* | dragonfly*) - lt_cv_sys_dlopen_deplibs=yes - ;; - gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu) - # GNU and its variants, using gnu ld.so (Glibc) - lt_cv_sys_dlopen_deplibs=yes - ;; - hpux10*|hpux11*) - lt_cv_sys_dlopen_deplibs=yes - ;; - interix*) - lt_cv_sys_dlopen_deplibs=yes - ;; - irix[[12345]]*|irix6.[[01]]*) - # Catch all versions of IRIX before 6.2, and indicate that we don't - # know how it worked for any of those versions. - lt_cv_sys_dlopen_deplibs=unknown - ;; - irix*) - # The case above catches anything before 6.2, and it's known that - # at 6.2 and later dlopen does load deplibs. - lt_cv_sys_dlopen_deplibs=yes - ;; - netbsd*) - lt_cv_sys_dlopen_deplibs=yes - ;; - openbsd*) - lt_cv_sys_dlopen_deplibs=yes - ;; - osf[[1234]]*) - # dlopen did load deplibs (at least at 4.x), but until the 5.x series, - # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explicitly say `no'. - lt_cv_sys_dlopen_deplibs=no - ;; - osf5.0|osf5.0a|osf5.1) - # dlopen *does* load deplibs and with the right loader patch applied - # it even uses RPATH in a shared library to search for shared objects - # that the library depends on, but there's no easy way to know if that - # patch is installed. Since this is the case, all we can really - # say is unknown -- it depends on the patch being installed. If - # it is, this changes to `yes'. Without it, it would be `no'. - lt_cv_sys_dlopen_deplibs=unknown - ;; - osf*) - # the two cases above should catch all versions of osf <= 5.1. Read - # the comments above for what we know about them. - # At > 5.1, deplibs are loaded *and* any RPATH in a shared library - # is used to find them so we can finally say `yes'. - lt_cv_sys_dlopen_deplibs=yes - ;; - qnx*) - lt_cv_sys_dlopen_deplibs=yes - ;; - solaris*) - lt_cv_sys_dlopen_deplibs=yes - ;; - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - esac - ]) -if test "$lt_cv_sys_dlopen_deplibs" != yes; then - AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], - [Define if the OS needs help to load dependent libraries for dlopen().]) -fi -])# LT_SYS_DLOPEN_DEPLIBS - -# Old name: -AU_ALIAS([AC_LTDL_SYS_DLOPEN_DEPLIBS], [LT_SYS_DLOPEN_DEPLIBS]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], []) - - -# LT_SYS_MODULE_EXT -# ----------------- -AC_DEFUN([LT_SYS_MODULE_EXT], -[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl -AC_CACHE_CHECK([which extension is used for runtime loadable modules], - [libltdl_cv_shlibext], -[ -module=yes -eval libltdl_cv_shlibext=$shrext_cmds -module=no -eval libltdl_cv_shrext=$shrext_cmds - ]) -if test -n "$libltdl_cv_shlibext"; then - m4_pattern_allow([LT_MODULE_EXT])dnl - AC_DEFINE_UNQUOTED([LT_MODULE_EXT], ["$libltdl_cv_shlibext"], - [Define to the extension used for runtime loadable modules, say, ".so".]) -fi -if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then - m4_pattern_allow([LT_SHARED_EXT])dnl - AC_DEFINE_UNQUOTED([LT_SHARED_EXT], ["$libltdl_cv_shrext"], - [Define to the shared library suffix, say, ".dylib".]) -fi -])# LT_SYS_MODULE_EXT - -# Old name: -AU_ALIAS([AC_LTDL_SHLIBEXT], [LT_SYS_MODULE_EXT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_SHLIBEXT], []) - - -# LT_SYS_MODULE_PATH -# ------------------ -AC_DEFUN([LT_SYS_MODULE_PATH], -[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl -AC_CACHE_CHECK([which variable specifies run-time module search path], - [lt_cv_module_path_var], [lt_cv_module_path_var="$shlibpath_var"]) -if test -n "$lt_cv_module_path_var"; then - m4_pattern_allow([LT_MODULE_PATH_VAR])dnl - AC_DEFINE_UNQUOTED([LT_MODULE_PATH_VAR], ["$lt_cv_module_path_var"], - [Define to the name of the environment variable that determines the run-time module search path.]) -fi -])# LT_SYS_MODULE_PATH - -# Old name: -AU_ALIAS([AC_LTDL_SHLIBPATH], [LT_SYS_MODULE_PATH]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_SHLIBPATH], []) - - -# LT_SYS_DLSEARCH_PATH -# -------------------- -AC_DEFUN([LT_SYS_DLSEARCH_PATH], -[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl -AC_CACHE_CHECK([for the default library search path], - [lt_cv_sys_dlsearch_path], - [lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"]) -if test -n "$lt_cv_sys_dlsearch_path"; then - sys_dlsearch_path= - for dir in $lt_cv_sys_dlsearch_path; do - if test -z "$sys_dlsearch_path"; then - sys_dlsearch_path="$dir" - else - sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir" - fi - done - m4_pattern_allow([LT_DLSEARCH_PATH])dnl - AC_DEFINE_UNQUOTED([LT_DLSEARCH_PATH], ["$sys_dlsearch_path"], - [Define to the system default library search path.]) -fi -])# LT_SYS_DLSEARCH_PATH - -# Old name: -AU_ALIAS([AC_LTDL_SYSSEARCHPATH], [LT_SYS_DLSEARCH_PATH]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_SYSSEARCHPATH], []) - - -# _LT_CHECK_DLPREOPEN -# ------------------- -m4_defun([_LT_CHECK_DLPREOPEN], -[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], - [libltdl_cv_preloaded_symbols], - [if test -n "$lt_cv_sys_global_symbol_pipe"; then - libltdl_cv_preloaded_symbols=yes - else - libltdl_cv_preloaded_symbols=no - fi - ]) -if test x"$libltdl_cv_preloaded_symbols" = xyes; then - AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], - [Define if libtool can extract symbol lists from object files.]) -fi -])# _LT_CHECK_DLPREOPEN - - -# LT_LIB_DLLOAD -# ------------- -AC_DEFUN([LT_LIB_DLLOAD], -[m4_pattern_allow([^LT_DLLOADERS$]) -LT_DLLOADERS= -AC_SUBST([LT_DLLOADERS]) - -AC_LANG_PUSH([C]) - -LIBADD_DLOPEN= -AC_SEARCH_LIBS([dlopen], [dl], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - if test "$ac_cv_search_dlopen" != "none required" ; then - LIBADD_DLOPEN="-ldl" - fi - libltdl_cv_lib_dl_dlopen="yes" - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H -# include -#endif - ]], [[dlopen(0, 0);]])], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - libltdl_cv_func_dlopen="yes" - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"], - [AC_CHECK_LIB([svld], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes" - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"])])]) -if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes -then - lt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DLOPEN" - AC_CHECK_FUNCS([dlerror]) - LIBS="$lt_save_LIBS" -fi -AC_SUBST([LIBADD_DLOPEN]) - -LIBADD_SHL_LOAD= -AC_CHECK_FUNC([shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"], - [AC_CHECK_LIB([dld], [shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la" - LIBADD_SHL_LOAD="-ldld"])]) -AC_SUBST([LIBADD_SHL_LOAD]) - -case $host_os in -darwin[[1567]].*) -# We only want this for pre-Mac OS X 10.4. - AC_CHECK_FUNC([_dyld_func_lookup], - [AC_DEFINE([HAVE_DYLD], [1], - [Define if you have the _dyld_func_lookup function.]) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"]) - ;; -beos*) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la" - ;; -cygwin* | mingw* | os2* | pw32*) - AC_CHECK_DECLS([cygwin_conv_path], [], [], [[#include ]]) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la" - ;; -esac - -AC_CHECK_LIB([dld], [dld_link], - [AC_DEFINE([HAVE_DLD], [1], - [Define if you have the GNU dld library.]) - LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"]) -AC_SUBST([LIBADD_DLD_LINK]) - -m4_pattern_allow([^LT_DLPREOPEN$]) -LT_DLPREOPEN= -if test -n "$LT_DLLOADERS" -then - for lt_loader in $LT_DLLOADERS; do - LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader " - done - AC_DEFINE([HAVE_LIBDLLOADER], [1], - [Define if libdlloader will be built on this platform]) -fi -AC_SUBST([LT_DLPREOPEN]) - -dnl This isn't used anymore, but set it for backwards compatibility -LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD" -AC_SUBST([LIBADD_DL]) - -AC_LANG_POP -])# LT_LIB_DLLOAD - -# Old name: -AU_ALIAS([AC_LTDL_DLLIB], [LT_LIB_DLLOAD]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_DLLIB], []) - - -# LT_SYS_SYMBOL_USCORE -# -------------------- -# does the compiler prefix global symbols with an underscore? -AC_DEFUN([LT_SYS_SYMBOL_USCORE], -[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -AC_CACHE_CHECK([for _ prefix in compiled symbols], - [lt_cv_sys_symbol_underscore], - [lt_cv_sys_symbol_underscore=no - cat > conftest.$ac_ext <<_LT_EOF -void nm_test_func(){} -int main(){nm_test_func;return 0;} -_LT_EOF - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - ac_nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then - lt_cv_sys_symbol_underscore=yes - else - if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD - fi - fi - else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.c >&AS_MESSAGE_LOG_FD - fi - rm -rf conftest* - ]) - sys_symbol_underscore=$lt_cv_sys_symbol_underscore - AC_SUBST([sys_symbol_underscore]) -])# LT_SYS_SYMBOL_USCORE - -# Old name: -AU_ALIAS([AC_LTDL_SYMBOL_USCORE], [LT_SYS_SYMBOL_USCORE]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_SYMBOL_USCORE], []) - - -# LT_FUNC_DLSYM_USCORE -# -------------------- -AC_DEFUN([LT_FUNC_DLSYM_USCORE], -[AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl -if test x"$lt_cv_sys_symbol_underscore" = xyes; then - if test x"$libltdl_cv_func_dlopen" = xyes || - test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then - AC_CACHE_CHECK([whether we have to add an underscore for dlsym], - [libltdl_cv_need_uscore], - [libltdl_cv_need_uscore=unknown - save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DLOPEN" - _LT_TRY_DLOPEN_SELF( - [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], - [], [libltdl_cv_need_uscore=cross]) - LIBS="$save_LIBS" - ]) - fi -fi - -if test x"$libltdl_cv_need_uscore" = xyes; then - AC_DEFINE([NEED_USCORE], [1], - [Define if dlsym() requires a leading underscore in symbol names.]) -fi -])# LT_FUNC_DLSYM_USCORE - -# Old name: -AU_ALIAS([AC_LTDL_DLSYM_USCORE], [LT_FUNC_DLSYM_USCORE]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], []) - -# Copyright (C) 2002-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.13' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.13.4], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.13.4])dnl -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) - -# Figure out how to run the assembler. -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_AS -# ---------- -AC_DEFUN([AM_PROG_AS], -[# By default we simply use the C compiler to build assembly code. -AC_REQUIRE([AC_PROG_CC]) -test "${CCAS+set}" = set || CCAS=$CC -test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS -AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) -AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) -_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl -]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to -# '$srcdir', '$srcdir/..', or '$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is '.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ([2.52])dnl - m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -m4_define([_AM_COND_VALUE_$1], [$2])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], - [$1], [CXX], [depcc="$CXX" am_compiler_list=], - [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], - [$1], [UPC], [depcc="$UPC" am_compiler_list=], - [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - am__universal=false - m4_case([$1], [CC], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac], - [CXX], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac]) - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES. -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE([dependency-tracking], [dnl -AS_HELP_STRING( - [--enable-dependency-tracking], - [do not reject slow dependency extractors]) -AS_HELP_STRING( - [--disable-dependency-tracking], - [speeds up one-time build])]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -AC_SUBST([am__nodep])dnl -_AM_SUBST_NOTMAKE([am__nodep])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[{ - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.65])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[AC_DIAGNOSE([obsolete], - [$0: two- and three-arguments forms are deprecated.]) -m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if( - m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), - [ok:ok],, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) - AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) -AM_MISSING_PROG([AUTOCONF], [autoconf]) -AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) -AM_MISSING_PROG([AUTOHEADER], [autoheader]) -AM_MISSING_PROG([MAKEINFO], [makeinfo]) -AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES([CC])], - [m4_define([AC_PROG_CC], - m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES([CXX])], - [m4_define([AC_PROG_CXX], - m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES([OBJC])], - [m4_define([AC_PROG_OBJC], - m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], - [_AM_DEPENDENCIES([OBJCXX])], - [m4_define([AC_PROG_OBJCXX], - m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl -]) -AC_REQUIRE([AM_SILENT_RULES])dnl -dnl The testsuite driver may need to know about EXEEXT, so add the -dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This -dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. -AC_CONFIG_COMMANDS_PRE(dnl -[m4_provide_if([_AM_COMPILER_EXEEXT], - [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl -]) - -dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not -dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further -dnl mangled by Autoconf and run in a shell conditional statement. -m4_define([_AC_COMPILER_EXEEXT], -m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_arg=$1 -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi -AC_SUBST([install_sh])]) - -# Copyright (C) 2003-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- -# From Jim Meyering - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MAINTAINER_MODE([DEFAULT-MODE]) -# ---------------------------------- -# Control maintainer-specific portions of Makefiles. -# Default is to disable them, unless 'enable' is passed literally. -# For symmetry, 'disable' may be passed as well. Anyway, the user -# can override the default with the --enable/--disable switch. -AC_DEFUN([AM_MAINTAINER_MODE], -[m4_case(m4_default([$1], [disable]), - [enable], [m4_define([am_maintainer_other], [disable])], - [disable], [m4_define([am_maintainer_other], [enable])], - [m4_define([am_maintainer_other], [enable]) - m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) -AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) - dnl maintainer-mode's default is 'disable' unless 'enable' is passed - AC_ARG_ENABLE([maintainer-mode], - [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], - am_maintainer_other[ make rules and dependencies not useful - (and sometimes confusing) to the casual installer])], - [USE_MAINTAINER_MODE=$enableval], - [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) - AC_MSG_RESULT([$USE_MAINTAINER_MODE]) - AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) - MAINT=$MAINTAINER_MODE_TRUE - AC_SUBST([MAINT])dnl -] -) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_CC_C_O -# -------------- -# Like AC_PROG_CC_C_O, but changed for automake. -AC_DEFUN([AM_PROG_CC_C_O], -[AC_REQUIRE([AC_PROG_CC_C_O])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -dnl Make sure AC_PROG_CC is never called again, or it will override our -dnl setting of CC. -m4_define([AC_PROG_CC], - [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it is modern enough. -# If it is, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - AC_MSG_WARN(['missing' script is too old or missing]) -fi -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# -------------------- -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) - -# _AM_SET_OPTIONS(OPTIONS) -# ------------------------ -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[[\\\"\#\$\&\'\`$am_lf]]*) - AC_MSG_ERROR([unsafe absolute working directory name]);; -esac -case $srcdir in - *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken - alias in your environment]) - fi - if test "$[2]" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT([yes]) -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi -AC_CONFIG_COMMANDS_PRE( - [AC_MSG_CHECKING([that generated files are newer than configure]) - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - AC_MSG_RESULT([done])]) -rm -f conftest.file -]) - -# Copyright (C) 2009-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SILENT_RULES([DEFAULT]) -# -------------------------- -# Enable less verbose build rules; with the default set to DEFAULT -# ("yes" being less verbose, "no" or empty being verbose). -AC_DEFUN([AM_SILENT_RULES], -[AC_ARG_ENABLE([silent-rules], [dnl -AS_HELP_STRING( - [--enable-silent-rules], - [less verbose build output (undo: "make V=1")]) -AS_HELP_STRING( - [--disable-silent-rules], - [verbose build output (undo: "make V=0")])dnl -]) -case $enable_silent_rules in @%:@ ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; -esac -dnl -dnl A few 'make' implementations (e.g., NonStop OS and NextStep) -dnl do not support nested variable expansions. -dnl See automake bug#9928 and bug#10237. -am_make=${MAKE-make} -AC_CACHE_CHECK([whether $am_make supports nested variables], - [am_cv_make_support_nested_variables], - [if AS_ECHO([['TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi]) -if test $am_cv_make_support_nested_variables = yes; then - dnl Using '$V' instead of '$(V)' breaks IRIX make. - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AC_SUBST([AM_V])dnl -AM_SUBST_NOTMAKE([AM_V])dnl -AC_SUBST([AM_DEFAULT_V])dnl -AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl -AC_SUBST([AM_DEFAULT_VERBOSITY])dnl -AM_BACKSLASH='\' -AC_SUBST([AM_BACKSLASH])dnl -_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl -]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor 'install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in "make install-strip", and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# AM_SUBST_NOTMAKE(VARIABLE) -# -------------------------- -# Public sister of _AM_SUBST_NOTMAKE. -AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of 'v7', 'ustar', or 'pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -# -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AC_SUBST([AMTAR], ['$${TAR-tar}']) - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' - -m4_if([$1], [v7], - [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - - [m4_case([$1], - [ustar], - [# The POSIX 1988 'ustar' format is defined with fixed-size fields. - # There is notably a 21 bits limit for the UID and the GID. In fact, - # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 - # and bug#13588). - am_max_uid=2097151 # 2^21 - 1 - am_max_gid=$am_max_uid - # The $UID and $GID variables are not portable, so we need to resort - # to the POSIX-mandated id(1) utility. Errors in the 'id' calls - # below are definitely unexpected, so allow the users to see them - # (that is, avoid stderr redirection). - am_uid=`id -u || echo unknown` - am_gid=`id -g || echo unknown` - AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) - if test $am_uid -le $am_max_uid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi - AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) - if test $am_gid -le $am_max_gid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi], - - [pax], - [], - - [m4_fatal([Unknown tar format])]) - - AC_MSG_CHECKING([how to create a $1 tar archive]) - - # Go ahead even if we have the value already cached. We do so because we - # need to set the values for the 'am__tar' and 'am__untar' variables. - _am_tools=${am_cv_prog_tar_$1-$_am_tools} - - for _am_tool in $_am_tools; do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works. - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi - done - rm -rf conftest.dir - - AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) - AC_MSG_RESULT([$am_cv_prog_tar_$1])]) - -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - -m4_include([m4/asmcfi.m4]) -m4_include([m4/ax_append_flag.m4]) -m4_include([m4/ax_cc_maxopt.m4]) -m4_include([m4/ax_cflags_warn_all.m4]) -m4_include([m4/ax_check_compile_flag.m4]) -m4_include([m4/ax_compiler_vendor.m4]) -m4_include([m4/ax_configure_args.m4]) -m4_include([m4/ax_enable_builddir.m4]) -m4_include([m4/ax_gcc_archflag.m4]) -m4_include([m4/ax_gcc_x86_cpuid.m4]) -m4_include([m4/libtool.m4]) -m4_include([m4/ltoptions.m4]) -m4_include([m4/ltsugar.m4]) -m4_include([m4/ltversion.m4]) -m4_include([m4/lt~obsolete.m4]) -m4_include([acinclude.m4]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/compile b/ruby/ext/fiddle/libffi-3.2.1/compile deleted file mode 100755 index 531136b06..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/compile +++ /dev/null @@ -1,347 +0,0 @@ -#! /bin/sh -# Wrapper for compilers which do not understand '-c -o'. - -scriptversion=2012-10-14.11; # UTC - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# Written by Tom Tromey . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' - -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent tools from complaining about whitespace usage. -IFS=" "" $nl" - -file_conv= - -# func_file_conv build_file lazy -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. If the determined conversion -# type is listed in (the comma separated) LAZY, no conversion will -# take place. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv/,$2, in - *,$file_conv,*) - ;; - mingw/*) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin/*) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine/*) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_cl_dashL linkdir -# Make cl look for libraries in LINKDIR -func_cl_dashL () -{ - func_file_conv "$1" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" -} - -# func_cl_dashl library -# Do a library search-path lookup for cl -func_cl_dashl () -{ - lib=$1 - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - lib=$dir/$lib.dll.lib - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - lib=$dir/$lib.lib - break - fi - if test -f "$dir/lib$lib.a"; then - found=yes - lib=$dir/lib$lib.a - break - fi - done - IFS=$save_IFS - - if test "$found" != yes; then - lib=$lib.lib - fi -} - -# func_cl_wrapper cl arg... -# Adjust compile command to suit cl -func_cl_wrapper () -{ - # Assume a capable shell - lib_path= - shared=: - linker_opts= - for arg - do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - eat=1 - case $2 in - *.o | *.[oO][bB][jJ]) - func_file_conv "$2" - set x "$@" -Fo"$file" - shift - ;; - *) - func_file_conv "$2" - set x "$@" -Fe"$file" - shift - ;; - esac - ;; - -I) - eat=1 - func_file_conv "$2" mingw - set x "$@" -I"$file" - shift - ;; - -I*) - func_file_conv "${1#-I}" mingw - set x "$@" -I"$file" - shift - ;; - -l) - eat=1 - func_cl_dashl "$2" - set x "$@" "$lib" - shift - ;; - -l*) - func_cl_dashl "${1#-l}" - set x "$@" "$lib" - shift - ;; - -L) - eat=1 - func_cl_dashL "$2" - ;; - -L*) - func_cl_dashL "${1#-L}" - ;; - -static) - shared=false - ;; - -Wl,*) - arg=${1#-Wl,} - save_ifs="$IFS"; IFS=',' - for flag in $arg; do - IFS="$save_ifs" - linker_opts="$linker_opts $flag" - done - IFS="$save_ifs" - ;; - -Xlinker) - eat=1 - linker_opts="$linker_opts $2" - ;; - -*) - set x "$@" "$1" - shift - ;; - *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) - func_file_conv "$1" - set x "$@" -Tp"$file" - shift - ;; - *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) - func_file_conv "$1" mingw - set x "$@" "$file" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift - done - if test -n "$linker_opts"; then - linker_opts="-link$linker_opts" - fi - exec "$@" $linker_opts - exit 1 -} - -eat= - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: compile [--help] [--version] PROGRAM [ARGS] - -Wrapper for compilers which do not understand '-c -o'. -Remove '-o dest.o' from ARGS, run PROGRAM with the remaining -arguments, and rename the output as expected. - -If you are trying to build a whole package this is not the -right script to run: please start by reading the file 'INSTALL'. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "compile $scriptversion" - exit $? - ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) - func_cl_wrapper "$@" # Doesn't return... - ;; -esac - -ofile= -cfile= - -for arg -do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - # So we strip '-o arg' only if arg is an object. - eat=1 - case $2 in - *.o | *.obj) - ofile=$2 - ;; - *) - set x "$@" -o "$2" - shift - ;; - esac - ;; - *.c) - cfile=$1 - set x "$@" "$1" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift -done - -if test -z "$ofile" || test -z "$cfile"; then - # If no '-o' option was seen then we might have been invoked from a - # pattern rule where we don't need one. That is ok -- this is a - # normal compilation that the losing compiler can handle. If no - # '.c' file was seen then we are probably linking. That is also - # ok. - exec "$@" -fi - -# Name of file we expect compiler to create. -cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` - -# Create the lock directory. -# Note: use '[/\\:.-]' here to ensure that we don't use the same name -# that we are using for the .o file. Also, base the name on the expected -# object file name, since that is what matters with a parallel build. -lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d -while true; do - if mkdir "$lockdir" >/dev/null 2>&1; then - break - fi - sleep 1 -done -# FIXME: race condition here if user kills between mkdir and trap. -trap "rmdir '$lockdir'; exit 1" 1 2 15 - -# Run the compile. -"$@" -ret=$? - -if test -f "$cofile"; then - test "$cofile" = "$ofile" || mv "$cofile" "$ofile" -elif test -f "${cofile}bj"; then - test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" -fi - -rmdir "$lockdir" -exit $ret - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/config.guess b/ruby/ext/fiddle/libffi-3.2.1/config.guess deleted file mode 100755 index b79252d6b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/config.guess +++ /dev/null @@ -1,1558 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-06-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD -# -# Please send patches with a ChangeLog entry to config-patches@gnu.org. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; -esac - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/config.sub b/ruby/ext/fiddle/libffi-3.2.1/config.sub deleted file mode 100755 index c765b34b7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/config.sub +++ /dev/null @@ -1,1788 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-04-24' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches with a ChangeLog entry to config-patches@gnu.org. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or1k-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/configure b/ruby/ext/fiddle/libffi-3.2.1/configure deleted file mode 100755 index c6da4670a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/configure +++ /dev/null @@ -1,21768 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libffi 3.2.1. -# -# Report bugs to . -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 - - test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ - || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: http://github.com/atgreen/libffi/issues about your -$0: system, including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - -SHELL=${CONFIG_SHELL-/bin/sh} - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='libffi' -PACKAGE_TARNAME='libffi' -PACKAGE_VERSION='3.2.1' -PACKAGE_STRING='libffi 3.2.1' -PACKAGE_BUGREPORT='http://github.com/atgreen/libffi/issues' -PACKAGE_URL='' - -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='am__EXEEXT_FALSE -am__EXEEXT_TRUE -LTLIBOBJS -LIBOBJS -toolexeclibdir -toolexecdir -FFI_DEBUG_FALSE -FFI_DEBUG_TRUE -TARGETDIR -TARGET -FFI_EXEC_TRAMPOLINE_TABLE -FFI_EXEC_TRAMPOLINE_TABLE_FALSE -FFI_EXEC_TRAMPOLINE_TABLE_TRUE -sys_symbol_underscore -HAVE_LONG_DOUBLE_VARIANT -HAVE_LONG_DOUBLE -ALLOCA -XTENSA_FALSE -XTENSA_TRUE -VAX_FALSE -VAX_TRUE -TILE_FALSE -TILE_TRUE -PA64_HPUX_FALSE -PA64_HPUX_TRUE -PA_HPUX_FALSE -PA_HPUX_TRUE -PA_LINUX_FALSE -PA_LINUX_TRUE -SH64_FALSE -SH64_TRUE -SH_FALSE -SH_TRUE -X86_64_FALSE -X86_64_TRUE -S390_FALSE -S390_TRUE -FRV_FALSE -FRV_TRUE -LIBFFI_CRIS_FALSE -LIBFFI_CRIS_TRUE -AVR32_FALSE -AVR32_TRUE -ARM_FALSE -ARM_TRUE -ARC_FALSE -ARC_TRUE -AARCH64_FALSE -AARCH64_TRUE -POWERPC_FREEBSD_FALSE -POWERPC_FREEBSD_TRUE -POWERPC_DARWIN_FALSE -POWERPC_DARWIN_TRUE -POWERPC_AIX_FALSE -POWERPC_AIX_TRUE -POWERPC_FALSE -POWERPC_TRUE -OR1K_FALSE -OR1K_TRUE -NIOS2_FALSE -NIOS2_TRUE -MOXIE_FALSE -MOXIE_TRUE -METAG_FALSE -METAG_TRUE -MICROBLAZE_FALSE -MICROBLAZE_TRUE -M88K_FALSE -M88K_TRUE -M68K_FALSE -M68K_TRUE -M32R_FALSE -M32R_TRUE -IA64_FALSE -IA64_TRUE -ALPHA_FALSE -ALPHA_TRUE -X86_DARWIN64_FALSE -X86_DARWIN64_TRUE -X86_DARWIN32_FALSE -X86_DARWIN32_TRUE -X86_DARWIN_FALSE -X86_DARWIN_TRUE -X86_WIN64_FALSE -X86_WIN64_TRUE -X86_WIN32_FALSE -X86_WIN32_TRUE -X86_FREEBSD_FALSE -X86_FREEBSD_TRUE -X86_FALSE -X86_TRUE -SPARC_FALSE -SPARC_TRUE -BFIN_FALSE -BFIN_TRUE -MIPS_FALSE -MIPS_TRUE -AM_LTLDFLAGS -AM_RUNTESTFLAGS -TESTSUBDIR_FALSE -TESTSUBDIR_TRUE -MAINT -MAINTAINER_MODE_FALSE -MAINTAINER_MODE_TRUE -PRTDIAG -CXXCPP -CPP -OTOOL64 -OTOOL -LIPO -NMEDIT -DSYMUTIL -MANIFEST_TOOL -RANLIB -ac_ct_AR -AR -DLLTOOL -OBJDUMP -LN_S -NM -ac_ct_DUMPBIN -DUMPBIN -LD -FGREP -EGREP -GREP -SED -LIBTOOL -am__fastdepCCAS_FALSE -am__fastdepCCAS_TRUE -CCASDEPMODE -CCASFLAGS -CCAS -am__fastdepCXX_FALSE -am__fastdepCXX_TRUE -CXXDEPMODE -ac_ct_CXX -CXXFLAGS -CXX -am__fastdepCC_FALSE -am__fastdepCC_TRUE -CCDEPMODE -am__nodep -AMDEPBACKSLASH -AMDEP_FALSE -AMDEP_TRUE -am__quote -am__include -DEPDIR -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -AM_BACKSLASH -AM_DEFAULT_VERBOSITY -AM_DEFAULT_V -AM_V -am__untar -am__tar -AMTAR -am__leading_dot -SET_MAKE -AWK -mkdir_p -MKDIR_P -INSTALL_STRIP_PROGRAM -STRIP -install_sh -MAKEINFO -AUTOHEADER -AUTOMAKE -AUTOCONF -ACLOCAL -VERSION -PACKAGE -CYGPATH_W -am__isrc -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -ax_enable_builddir_sed -target_os -target_vendor -target_cpu -target -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -enable_builddir -enable_silent_rules -enable_dependency_tracking -enable_shared -enable_static -with_pic -enable_fast_install -with_gnu_ld -with_sysroot -enable_libtool_lock -enable_portable_binary -with_gcc_arch -enable_maintainer_mode -enable_pax_emutramp -enable_debug -enable_structs -enable_raw_api -enable_purify_safety -' - ac_precious_vars='build_alias -host_alias -target_alias -CCAS -CCASFLAGS -CPP -CPPFLAGS -CXXCPP' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures libffi 3.2.1 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/libffi] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of libffi 3.2.1:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --disable-builddir disable automatic build in subdir of sources - - --enable-silent-rules less verbose build output (undo: "make V=1") - --disable-silent-rules verbose build output (undo: "make V=0") - --enable-dependency-tracking - do not reject slow dependency extractors - --disable-dependency-tracking - speeds up one-time build - --enable-shared[=PKGS] build shared libraries [default=yes] - --enable-static[=PKGS] build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - --enable-portable-binary - disable compiler optimizations that would produce - unportable binaries - --enable-maintainer-mode - enable make rules and dependencies not useful (and - sometimes confusing) to the casual installer - --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC - --enable-debug debugging mode - --disable-structs omit code for struct support - --disable-raw-api make the raw api unavailable - --enable-purify-safety purify-safe mode - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use - both] - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot=DIR Search for dependent libraries within DIR - (or the compiler's sysroot if not specified). - --with-gcc-arch= use architecture for gcc -march/-mtune, - instead of guessing - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CXX C++ compiler command - CXXFLAGS C++ compiler flags - CCAS assembler compiler command (defaults to CC) - CCASFLAGS assembler compiler flags (defaults to CFLAGS) - CPP C preprocessor - CXXCPP C++ preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -libffi configure 3.2.1 -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_cxx_try_compile LINENO -# ---------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_func LINENO FUNC VAR -# ---------------------------------- -# Tests whether FUNC exists, setting the cache variable VAR accordingly -ac_fn_c_check_func () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Define $2 to an innocuous variant, in case declares $2. - For example, HP-UX 11i declares gettimeofday. */ -#define $2 innocuous_$2 - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $2 - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $2 (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$2 || defined __stub___$2 -choke me -#endif - -int -main () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_func - -# ac_fn_cxx_try_cpp LINENO -# ------------------------ -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_cpp - -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link - -# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES -# -------------------------------------------- -# Tries to find the compile-time value of EXPR in a program that includes -# INCLUDES, setting VAR accordingly. Returns whether the value could be -# computed -ac_fn_c_compute_int () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) >= 0)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_lo=0 ac_mid=0 - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=$ac_mid; break -else - as_fn_arith $ac_mid + 1 && ac_lo=$as_val - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) < 0)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=-1 ac_mid=-1 - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) >= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_lo=$ac_mid; break -else - as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - ac_lo= ac_hi= -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=$ac_mid -else - as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in #(( -?*) eval "$3=\$ac_lo"; ac_retval=0 ;; -'') ac_retval=1 ;; -esac - else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -static long int longval () { return $2; } -static unsigned long int ulongval () { return $2; } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - return 1; - if (($2) < 0) - { - long int i = longval (); - if (i != ($2)) - return 1; - fprintf (f, "%ld", i); - } - else - { - unsigned long int i = ulongval (); - if (i != ($2)) - return 1; - fprintf (f, "%lu", i); - } - /* Do not output a trailing newline, as this causes \r\n confusion - on some platforms. */ - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - echo >>conftest.val; read $3 &5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ------------------------------------------------------ ## -## Report this to http://github.com/atgreen/libffi/issues ## -## ------------------------------------------------------ ##" - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_mongrel - -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=no" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof ($2)) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof (($2))) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - eval "$3=yes" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_type -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libffi $as_me 3.2.1, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_config_headers="$ac_config_headers fficonfig.h" - - -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 -$as_echo_n "checking target system type... " >&6; } -if ${ac_cv_target+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$target_alias" = x; then - ac_cv_target=$ac_cv_host -else - ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 -$as_echo "$ac_cv_target" >&6; } -case $ac_cv_target in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; -esac -target=$ac_cv_target -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_target -shift -target_cpu=$1 -target_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -target_os=$* -IFS=$ac_save_IFS -case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - -target_alias=${target_alias-$host_alias} - -case "${host}" in - frv*-elf) - LDFLAGS=`echo $LDFLAGS | sed "s/\-B^ *libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/ - ;; -esac - - - # [$]@ is unsable in 2.60+ but earlier autoconf had no ac_configure_args - if test "${ac_configure_args+set}" != "set" ; then - ac_configure_args= - for ac_arg in ${1+"$@"}; do - ac_configure_args="$ac_configure_args '$ac_arg'" - done - fi - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - - -ax_enable_builddir="." -# Check whether --enable-builddir was given. -if test "${enable_builddir+set}" = set; then : - enableval=$enable_builddir; ax_enable_builddir="$enableval" -else - ax_enable_builddir="auto" -fi - -if test ".$ac_srcdir_defaulted" != ".no" ; then -if test ".$srcdir" = ".." ; then - if test -f config.status ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: toplevel srcdir already configured... skipping subdir build" >&5 -$as_echo "$as_me: toplevel srcdir already configured... skipping subdir build" >&6;} - else - test ".$ax_enable_builddir" = "." && ax_enable_builddir="." - test ".$ax_enable_builddir" = ".no" && ax_enable_builddir="." - test ".$TARGET" = "." && TARGET="$target" - test ".$ax_enable_builddir" = ".auto" && ax_enable_builddir="$TARGET" - if test ".$ax_enable_builddir" != ".." ; then # we know where to go and - as_dir=$ax_enable_builddir; as_fn_mkdir_p - echo __.$ax_enable_builddir.__ > $ax_enable_builddir/conftest.tmp - cd $ax_enable_builddir - if grep __.$ax_enable_builddir.__ conftest.tmp >/dev/null 2>/dev/null ; then - rm conftest.tmp - { $as_echo "$as_me:${as_lineno-$LINENO}: result: continue configure in default builddir \"./$ax_enable_builddir\"" >&5 -$as_echo "continue configure in default builddir \"./$ax_enable_builddir\"" >&6; } - else - as_fn_error $? "could not change to default builddir \"./$ax_enable_builddir\"" "$LINENO" 5 - fi - srcdir=`echo "$ax_enable_builddir" | - sed -e 's,^\./,,;s,[^/]$,&/,;s,[^/]*/,../,g;s,[/]$,,;'` - # going to restart from subdirectory location - test -f $srcdir/config.log && mv $srcdir/config.log . - test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h . - test -f $srcdir/conftest.log && mv $srcdir/conftest.log . - test -f $srcdir/$cache_file && mv $srcdir/$cache_file . - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ....exec $SHELL $srcdir/$0 \"--srcdir=$srcdir\" \"--enable-builddir=$ax_enable_builddir\" ${1+\"$@\"}" >&5 -$as_echo "....exec $SHELL $srcdir/$0 \"--srcdir=$srcdir\" \"--enable-builddir=$ax_enable_builddir\" ${1+\"$@\"}" >&6; } - case "$0" in # restart - [\\/]* | ?:[\\/]*) # Asbolute name - eval $SHELL "'$0'" "'--srcdir=$srcdir'" "'--enable-builddir=$ax_enable_builddir'" $ac_configure_args ;; - *) eval $SHELL "'$srcdir/$0'" "'--srcdir=$srcdir'" "'--enable-builddir=$ax_enable_builddir'" $ac_configure_args ;; - esac ; exit $? - fi - fi -fi fi -test ".$ax_enable_builddir" = ".auto" && ax_enable_builddir="." -# Extract the first word of "gsed sed", so it can be a program name with args. -set dummy gsed sed; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ax_enable_builddir_sed+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ax_enable_builddir_sed in - [\\/]* | ?:[\\/]*) - ac_cv_path_ax_enable_builddir_sed="$ax_enable_builddir_sed" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ax_enable_builddir_sed="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_ax_enable_builddir_sed" && ac_cv_path_ax_enable_builddir_sed="sed" - ;; -esac -fi -ax_enable_builddir_sed=$ac_cv_path_ax_enable_builddir_sed -if test -n "$ax_enable_builddir_sed"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_enable_builddir_sed" >&5 -$as_echo "$ax_enable_builddir_sed" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -ax_enable_builddir_auxdir="$am_aux_dir" -ac_config_commands="$ac_config_commands buildir" - - -am__api_version='1.13' - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken - alias in your environment" "$LINENO" 5 - fi - if test "$2" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error $? "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi - -rm -f conftest.file - -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=1;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='libffi' - VERSION='3.2.1' - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -mkdir_p='$(MKDIR_P)' - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AMTAR='$${TAR-tar}' - - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar pax cpio none' - -am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' - - - - - - - -# The same as in boehm-gc and libstdc++. Have to borrow it from there. -# We must force CC to /not/ be precious variables; otherwise -# the wrong, non-multilib-adjusted value will be used in multilibs. -# As a side effect, we have to subst CFLAGS ourselves. -# Also save and restore CFLAGS, since AC_PROG_CC will come up with -# defaults of its own if none are provided. - - - -save_CFLAGS=$CFLAGS -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - -CFLAGS=$save_CFLAGS - - - - - -# By default we simply use the C compiler to build assembly code. - -test "${CCAS+set}" = set || CCAS=$CC -test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS - - - -depcc="$CCAS" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CCAS_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CCAS_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CCAS_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } -CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then - am__fastdepCCAS_TRUE= - am__fastdepCCAS_FALSE='#' -else - am__fastdepCCAS_TRUE='#' - am__fastdepCCAS_FALSE= -fi - - -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 -$as_echo_n "checking whether cc understands -c and -o together... " >&6; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -# Make sure it works both with $CC and with simple cc. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; -then - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&5' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; - then - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi - - -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac - - - -macro_version='2.4.2' -macro_revision='1.3337' - - - - - - - - - - - - - -ltmain="$ac_aux_dir/ltmain.sh" - -# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "" -} - -case "$ECHO" in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; -esac - - - - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if ${ac_cv_path_SED+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for ac_i in 1 2 3 4 5 6 7; do - ac_script="$ac_script$as_nl$ac_script" - done - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - { ac_script=; unset ac_script;} - if test -z "$SED"; then - ac_path_SED_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_SED" || continue -# Check for GNU ac_path_SED and select it if it is found. - # Check for GNU $ac_path_SED -case `"$ac_path_SED" --version 2>&1` in -*GNU*) - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_SED_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_SED="$ac_path_SED" - ac_path_SED_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_SED_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_SED"; then - as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 - fi -else - ac_cv_path_SED=$SED -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } - SED="$ac_cv_path_SED" - rm -f conftest.sed - -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 -$as_echo_n "checking for fgrep... " >&6; } -if ${ac_cv_path_FGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 - then ac_cv_path_FGREP="$GREP -F" - else - if test -z "$FGREP"; then - ac_path_FGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_FGREP" || continue -# Check for GNU ac_path_FGREP and select it if it is found. - # Check for GNU $ac_path_FGREP -case `"$ac_path_FGREP" --version 2>&1` in -*GNU*) - ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'FGREP' >> "conftest.nl" - "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_FGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_FGREP="$ac_path_FGREP" - ac_path_FGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_FGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_FGREP"; then - as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_FGREP=$FGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 -$as_echo "$ac_cv_path_FGREP" >&6; } - FGREP="$ac_cv_path_FGREP" - - -test -z "$GREP" && GREP=grep - - - - - - - - - - - - - - - - - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 -$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if ${lt_cv_path_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - : ${lt_cv_path_NM=no} -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 -$as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - if test -n "$ac_tool_prefix"; then - for ac_prog in dumpbin "link -dump" - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DUMPBIN"; then - ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DUMPBIN=$ac_cv_prog_DUMPBIN -if test -n "$DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 -$as_echo "$DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$DUMPBIN" && break - done -fi -if test -z "$DUMPBIN"; then - ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in dumpbin "link -dump" -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DUMPBIN"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN -if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 -$as_echo "$ac_ct_DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_DUMPBIN" && break -done - - if test "x$ac_ct_DUMPBIN" = x; then - DUMPBIN=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DUMPBIN=$ac_ct_DUMPBIN - fi -fi - - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols" - ;; - *) - DUMPBIN=: - ;; - esac - fi - - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" - fi -fi -test -z "$NM" && NM=nm - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 -$as_echo_n "checking the name lister ($NM) interface... " >&6; } -if ${lt_cv_nm_interface+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: output\"" >&5) - cat conftest.out >&5 - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 -$as_echo "$lt_cv_nm_interface" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } -fi - -# find the maximum length of command line arguments -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 -$as_echo_n "checking the maximum length of command line arguments... " >&6; } -if ${lt_cv_sys_max_cmd_len+:} false; then : - $as_echo_n "(cached) " >&6 -else - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac - -fi - -if test -n $lt_cv_sys_max_cmd_len ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 -$as_echo "$lt_cv_sys_max_cmd_len" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } -fi -max_cmd_len=$lt_cv_sys_max_cmd_len - - - - - - -: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi - - - - - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 -$as_echo_n "checking how to convert $build file names to $host format... " >&6; } -if ${lt_cv_to_host_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac - -fi - -to_host_file_cmd=$lt_cv_to_host_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 -$as_echo "$lt_cv_to_host_file_cmd" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 -$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } -if ${lt_cv_to_tool_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - #assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac - -fi - -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 -$as_echo "$lt_cv_to_tool_file_cmd" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 -$as_echo_n "checking for $LD option to reload object files... " >&6; } -if ${lt_cv_ld_reload_flag+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_reload_flag='-r' -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 -$as_echo "$lt_cv_ld_reload_flag" >&6; } -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - if test "$GCC" != yes; then - reload_cmds=false - fi - ;; - darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OBJDUMP=$ac_ct_OBJDUMP - fi -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - -test -z "$OBJDUMP" && OBJDUMP=objdump - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 -$as_echo_n "checking how to recognize dependent libraries... " >&6; } -if ${lt_cv_deplibs_check_method+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. - -case $host_os in -aix[4-9]*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[3-9]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 -$as_echo "$lt_cv_deplibs_check_method" >&6; } - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - - - - - - - - - - - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DLLTOOL=$ac_ct_DLLTOOL - fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - -test -z "$DLLTOOL" && DLLTOOL=dlltool - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 -$as_echo_n "checking how to associate runtime and link libraries... " >&6; } -if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 -$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - - - - - - - - -if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AR" && break - done -fi -if test -z "$AR"; then - ac_ct_AR=$AR - for ac_prog in ar -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_AR" && break -done - - if test "x$ac_ct_AR" = x; then - AR="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -fi - -: ${AR=ar} -: ${AR_FLAGS=cru} - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 -$as_echo_n "checking for archiver @FILE support... " >&6; } -if ${lt_cv_ar_at_file+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ar_at_file=no - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test "$ac_status" -eq 0; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test "$ac_status" -ne 0; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 -$as_echo "$lt_cv_ar_at_file" >&6; } - -if test "x$lt_cv_ar_at_file" = xno; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -test -z "$STRIP" && STRIP=: - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -test -z "$RANLIB" && RANLIB=: - - - - - - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 -$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if ${lt_cv_sys_global_symbol_pipe+:} false; then : - $as_echo_n "(cached) " >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[ABCDGISTW]' - ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris*) - symcode='[BDRT]' - ;; -sco3.2v5*) - symcode='[DT]' - ;; -sysv4.2uw2*) - symcode='[DT]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[ABDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK '"\ -" {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Now try to grab the symbols. - nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -LT_DLSYM_CONST struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 -$as_echo "failed" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } -fi - -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then - nm_file_list_spec='@' -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 -$as_echo_n "checking for sysroot... " >&6; } - -# Check whether --with-sysroot was given. -if test "${with_sysroot+set}" = set; then : - withval=$with_sysroot; -else - with_sysroot=no -fi - - -lt_sysroot= -case ${with_sysroot} in #( - yes) - if test "$GCC" = yes; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 -$as_echo "${with_sysroot}" >&6; } - as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 - ;; -esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 -$as_echo "${lt_sysroot:-no}" >&6; } - - - - - -# Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then : - enableval=$enable_libtool_lock; -fi - -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 -$as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if ${lt_cv_cc_needs_belf+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_cc_needs_belf=yes -else - lt_cv_cc_needs_belf=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 -$as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" - fi - ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks="$enable_libtool_lock" - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. -set dummy ${ac_tool_prefix}mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MANIFEST_TOOL"; then - ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL -if test -n "$MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 -$as_echo "$MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_MANIFEST_TOOL"; then - ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL - # Extract the first word of "mt", so it can be a program name with args. -set dummy mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_MANIFEST_TOOL"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL -if test -n "$ac_ct_MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 -$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_MANIFEST_TOOL" = x; then - MANIFEST_TOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL - fi -else - MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" -fi - -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 -$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } -if ${lt_cv_path_mainfest_tool+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&5 - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 -$as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test "x$lt_cv_path_mainfest_tool" != xyes; then - MANIFEST_TOOL=: -fi - - - - - - - case $host_os in - rhapsody* | darwin*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. -set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DSYMUTIL"; then - ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DSYMUTIL=$ac_cv_prog_DSYMUTIL -if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 -$as_echo "$DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DSYMUTIL"; then - ac_ct_DSYMUTIL=$DSYMUTIL - # Extract the first word of "dsymutil", so it can be a program name with args. -set dummy dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DSYMUTIL"; then - ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL -if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 -$as_echo "$ac_ct_DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DSYMUTIL" = x; then - DSYMUTIL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DSYMUTIL=$ac_ct_DSYMUTIL - fi -else - DSYMUTIL="$ac_cv_prog_DSYMUTIL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. -set dummy ${ac_tool_prefix}nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NMEDIT"; then - ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -NMEDIT=$ac_cv_prog_NMEDIT -if test -n "$NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 -$as_echo "$NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_NMEDIT"; then - ac_ct_NMEDIT=$NMEDIT - # Extract the first word of "nmedit", so it can be a program name with args. -set dummy nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_NMEDIT"; then - ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_NMEDIT="nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT -if test -n "$ac_ct_NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 -$as_echo "$ac_ct_NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_NMEDIT" = x; then - NMEDIT=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - NMEDIT=$ac_ct_NMEDIT - fi -else - NMEDIT="$ac_cv_prog_NMEDIT" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. -set dummy ${ac_tool_prefix}lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$LIPO"; then - ac_cv_prog_LIPO="$LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_LIPO="${ac_tool_prefix}lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -LIPO=$ac_cv_prog_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_LIPO"; then - ac_ct_LIPO=$LIPO - # Extract the first word of "lipo", so it can be a program name with args. -set dummy lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_LIPO"; then - ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_LIPO="lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO -if test -n "$ac_ct_LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 -$as_echo "$ac_ct_LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_LIPO" = x; then - LIPO=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIPO=$ac_ct_LIPO - fi -else - LIPO="$ac_cv_prog_LIPO" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL"; then - ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OTOOL="${ac_tool_prefix}otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL=$ac_cv_prog_OTOOL -if test -n "$OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 -$as_echo "$OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL"; then - ac_ct_OTOOL=$OTOOL - # Extract the first word of "otool", so it can be a program name with args. -set dummy otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL"; then - ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OTOOL="otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL -if test -n "$ac_ct_OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 -$as_echo "$ac_ct_OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL" = x; then - OTOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL=$ac_ct_OTOOL - fi -else - OTOOL="$ac_cv_prog_OTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL64"; then - ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL64=$ac_cv_prog_OTOOL64 -if test -n "$OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 -$as_echo "$OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL64"; then - ac_ct_OTOOL64=$OTOOL64 - # Extract the first word of "otool64", so it can be a program name with args. -set dummy otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL64"; then - ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OTOOL64="otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 -if test -n "$ac_ct_OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 -$as_echo "$ac_ct_OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL64" = x; then - OTOOL64=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL64=$ac_ct_OTOOL64 - fi -else - OTOOL64="$ac_cv_prog_OTOOL64" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 -$as_echo_n "checking for -single_module linker flag... " >&6; } -if ${lt_cv_apple_cc_single_mod+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&5 - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&5 - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 -$as_echo "$lt_cv_apple_cc_single_mod" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 -$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if ${lt_cv_ld_exported_symbols_list+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_ld_exported_symbols_list=yes -else - lt_cv_ld_exported_symbols_list=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 -$as_echo_n "checking for -force_load linker flag... " >&6; } -if ${lt_cv_ld_force_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cru libconftest.a conftest.o" >&5 - $AR cru libconftest.a conftest.o 2>&5 - echo "$RANLIB libconftest.a" >&5 - $RANLIB libconftest.a 2>&5 - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&5 - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&5 - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 -$as_echo "$lt_cv_ld_force_load" >&6; } - case $host_os in - rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default -" -if test "x$ac_cv_header_dlfcn_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF - -fi - -done - - - - -func_stripname_cnf () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname_cnf - - - - - -# Set options - - - - enable_dlopen=no - - - enable_win32_dll=no - - - # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_shared=yes -fi - - - - - - - - - - # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi - - - - - - - - - - -# Check whether --with-pic was given. -if test "${with_pic+set}" = set; then : - withval=$with_pic; lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for lt_pkg in $withval; do - IFS="$lt_save_ifs" - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - pic_mode=default -fi - - -test -z "$pic_mode" && pic_mode=default - - - - - - - - # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then : - enableval=$enable_fast_install; p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_fast_install=yes -fi - - - - - - - - - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -test -z "$LN_S" && LN_S="ln -s" - - - - - - - - - - - - - - -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 -$as_echo_n "checking for objdir... " >&6; } -if ${lt_cv_objdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 -$as_echo "$lt_cv_objdir" >&6; } -objdir=$lt_cv_objdir - - - - - -cat >>confdefs.h <<_ACEOF -#define LT_OBJDIR "$lt_cv_objdir/" -_ACEOF - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` - - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 -$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - - - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 -$as_echo_n "checking for file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -# Use C for the default configuration in the libtool script - -lt_save_CC="$CC" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - -lt_prog_compiler_no_builtin_flag= - -if test "$GCC" = yes; then - case $cc_basename in - nvcc*) - lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; - *) - lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - - - - - - - lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - - - if test "$GCC" = yes; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static= - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - lt_prog_compiler_wl='-Xlinker ' - if test -n "$lt_prog_compiler_pic"; then - lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" - fi - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. - ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='--shared' - lt_prog_compiler_static='--static' - ;; - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-qpic' - lt_prog_compiler_static='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' - ;; - *Sun\ F* | *Sun*Fortran*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Qoption ld ' - ;; - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Wl,' - ;; - *Intel*\ [CF]*Compiler*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - *Portland\ Group*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - esac - ;; - esac - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) - lt_prog_compiler_wl='-Qoption ld ';; - *) - lt_prog_compiler_wl='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_can_build_shared=no - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic=$lt_prog_compiler_pic -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 -$as_echo "$lt_cv_prog_compiler_pic" >&6; } -lt_prog_compiler_pic=$lt_cv_prog_compiler_pic - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if ${lt_cv_prog_compiler_pic_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } - -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi - - - - - - - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works=yes - fi - else - lt_cv_prog_compiler_static_works=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 -$as_echo "$lt_cv_prog_compiler_static_works" >&6; } - -if test x"$lt_cv_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - runpath_var= - allow_undefined_flag= - always_export_symbols=no - archive_cmds= - archive_expsym_cmds= - compiler_needs_object=no - enable_shared_with_static_runtimes=no - export_dynamic_flag_spec= - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - hardcode_automatic=no - hardcode_direct=no - hardcode_direct_absolute=no - hardcode_libdir_flag_spec= - hardcode_libdir_separator= - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - inherit_rpath=no - link_all_deplibs=unknown - module_cmds= - module_expsym_cmds= - old_archive_from_new_cmds= - old_archive_from_expsyms_cmds= - thread_safe_flag_spec= - whole_archive_flag_spec= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; - *\ \(GNU\ Binutils\)\ [3-9]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test "$lt_use_gnu_ld_interface" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - supports_anon_versioning=no - case `$LD -v 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[3-9]*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.19, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='${wl}--export-all-symbols' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs=no - fi - ;; - - haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - link_all_deplibs=yes - ;; - - interix[3-9]*) - hardcode_direct=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test "$host_os" = linux-dietlibc; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no - then - tmp_addflag=' $pic_flag' - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - whole_archive_flag_spec= - tmp_sharedflag='--shared' ;; - xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - compiler_needs_object=yes - ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - compiler_needs_object=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - xlf* | bgf* | bgxlf* | mpixlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - ld_shlibs=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = no; then - runpath_var= - hardcode_libdir_flag_spec= - export_dynamic_flag_spec= - whole_archive_flag_spec= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_direct_absolute=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - file_list_spec='${wl}-f,' - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - export_dynamic_flag_spec='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - fi - archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - bsdi[45]*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - always_export_symbols=yes - file_list_spec='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, )='true' - enable_shared_with_static_runtimes=yes - exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - old_postinstall_cmds='chmod 644 $oldlib' - postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - enable_shared_with_static_runtimes=yes - ;; - esac - ;; - - darwin* | rhapsody*) - - - archive_cmds_need_lc=no - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec='' - fi - link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - - else - ld_shlibs=no - fi - - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 -$as_echo_n "checking if $CC understands -b... " >&6; } -if ${lt_cv_prog_compiler__b+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler__b=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -b" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler__b=yes - fi - else - lt_cv_prog_compiler__b=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 -$as_echo "$lt_cv_prog_compiler__b" >&6; } - -if test x"$lt_cv_prog_compiler__b" = xyes; then - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' -else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' -fi - - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - *) - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 -$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } -if ${lt_cv_irix_exported_symbol+:} false; then : - $as_echo_n "(cached) " >&6 -else - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int foo (void) { return 0; } -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_irix_exported_symbol=yes -else - lt_cv_irix_exported_symbol=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 -$as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test "$lt_cv_irix_exported_symbol" = yes; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - fi - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - inherit_rpath=yes - link_all_deplibs=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - *nto* | *qnx*) - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct=yes - hardcode_shlibpath_var=no - hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - else - ld_shlibs=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - archive_cmds_need_lc='no' - hardcode_libdir_separator=: - ;; - - solaris*) - no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' - hardcode_libdir_separator=':' - link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - - if test x$host_vendor = xsni; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' - ;; - esac - fi - fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 -$as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no - -with_gnu_ld=$with_gnu_ld - - - - - - - - - - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc=no - else - lt_cv_archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } - archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[lt_foo]++; } - if (lt_freq[lt_foo] == 1) { print lt_foo; } -}'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([A-Za-z]:\),\1,g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec="$LIB" - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[23].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Add ABI-specific directories to the system library path. - sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" - - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || - test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 -$as_echo "$hardcode_action" >&6; } - -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" -if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if ${ac_cv_lib_dld_shl_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_shl_load=yes -else - ac_cv_lib_dld_shl_load=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else - ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 -$as_echo_n "checking for dlopen in -lsvld... " >&6; } -if ${ac_cv_lib_svld_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_svld_dlopen=yes -else - ac_cv_lib_svld_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 -$as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 -$as_echo_n "checking for dld_link in -ldld... " >&6; } -if ${ac_cv_lib_dld_dld_link+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dld_link (); -int -main () -{ -return dld_link (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_dld_link=yes -else - ac_cv_lib_dld_dld_link=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 -$as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 -$as_echo_n "checking whether a program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisbility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 -$as_echo "$lt_cv_dlopen_self" >&6; } - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 -$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self_static+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisbility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 -$as_echo "$lt_cv_dlopen_self_static" >&6; } - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - - - - - - - - - - - - - - - - -striplib= -old_striplib= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 -$as_echo_n "checking whether stripping libraries is possible... " >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - ;; - esac -fi - - - - - - - - - - - - - # Report which library types will actually be built - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 -$as_echo_n "checking if libtool supports shared libraries... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 -$as_echo "$can_build_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 -$as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 -$as_echo "$enable_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 -$as_echo_n "checking whether to build static libraries... " >&6; } - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 -$as_echo "$enable_static" >&6; } - - - - -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -else - _lt_caught_CXX_error=yes -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -compiler_needs_object_CXX=no -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_direct_absolute_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_shlibpath_var_CXX=unsupported -hardcode_automatic_CXX=no -inherit_rpath_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -reload_flag_CXX=$reload_flag -reload_cmds_CXX=$reload_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - - # save warnings/boilerplate of simple test code - ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - - ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - compiler_CXX=$CC - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` - - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test "$GXX" = yes; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' - else - lt_prog_compiler_no_builtin_flag_CXX= - fi - - if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - ld_shlibs_CXX=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - file_list_spec_CXX='${wl}-f,' - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - export_dynamic_flag_spec_CXX='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - always_export_symbols_CXX=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_CXX='-berok' - # Determine the default libpath from the value encoded in an empty - # executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' ${wl}-bernotok' - allow_undefined_flag_CXX=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' - fi - archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_CXX=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_CXX=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_CXX=' ' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=yes - file_list_spec_CXX='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' - enable_shared_with_static_runtimes_CXX=yes - # Don't use ranlib - old_postinstall_cmds_CXX='chmod 644 $oldlib' - postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - - - archive_cmds_need_lc_CXX=no - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec_CXX='' - fi - link_all_deplibs_CXX=yes - allow_undefined_flag_CXX="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=func_echo_all - archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - if test "$lt_cv_apple_cc_single_mod" != "yes"; then - archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" - fi - - else - ld_shlibs_CXX=no - fi - - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - ld_shlibs_CXX=no - ;; - - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - - gnu*) - ;; - - haiku*) - archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - link_all_deplibs_CXX=yes - ;; - - hpux9*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - export_dynamic_flag_spec_CXX='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - *) - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - interix[3-9]*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - inherit_rpath_CXX=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [1-5].* | *pgcpp\ [1-5].*) - prelink_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - old_archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - compiler_needs_object_CXX=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - ld_shlibs_CXX=yes - ;; - - openbsd2*) - # C++ shared libraries are fairly broken - ld_shlibs_CXX=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - hardcode_direct_absolute_CXX=yes - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='${wl}-E' - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - ld_shlibs_CXX=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - case $host in - osf3*) - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - ;; - *) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - ;; - esac - - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - case $host in - osf3*) - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - *) - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - archive_cmds_need_lc_CXX=yes - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - no_undefined_flag_CXX=' ${wl}-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - fi - - hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='${wl}-z,text' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_CXX='${wl}-z,text' - allow_undefined_flag_CXX='${wl}-z,nodefs' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ - '"$old_archive_cmds_CXX" - reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ - '"$reload_cmds_CXX" - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } - test "$ld_shlibs_CXX" = no && can_build_shared=no - - GCC_CXX="$GXX" - LD_CXX="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - # Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF - - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" || - test $p = "-R"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX="${prev}${p}" - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX="${prev}${p}" - else - postdeps_CXX="${postdeps_CXX} ${prev}${p}" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX="$p" - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX="$p" - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -case $host_os in -interix[3-9]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - predep_objects_CXX= - postdep_objects_CXX= - postdeps_CXX= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac - - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - compiler_lib_search_dirs_CXX= -if test -n "${compiler_lib_search_path_CXX}"; then - compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - - - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic_CXX='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static_CXX= - ;; - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix[4-9]*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - dgux*) - case $cc_basename in - ec++*) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - lt_prog_compiler_static_CXX='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fpic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-qpic' - lt_prog_compiler_static_CXX='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd*) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx*) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc*) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } -lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } -if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works_CXX=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } - -if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works_CXX=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works_CXX=yes - fi - else - lt_cv_prog_compiler_static_works_CXX=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } - -if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then - : -else - lt_prog_compiler_static_CXX= -fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - case $host_os in - aix[4-9]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' - ;; - esac - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } -test "$ld_shlibs_CXX" = no && can_build_shared=no - -with_gnu_ld_CXX=$with_gnu_ld - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc_CXX=no - else - lt_cv_archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } - archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec="$LIB" - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[23].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Add ABI-specific directories to the system library path. - sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" - - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || - test -n "$runpath_var_CXX" || - test "X$hardcode_automatic_CXX" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$hardcode_direct_CXX" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && - test "$hardcode_minus_L_CXX" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 -$as_echo "$hardcode_action_CXX" >&6; } - -if test "$hardcode_action_CXX" = relink || - test "$inherit_rpath_CXX" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - ac_config_commands="$ac_config_commands libtool" - - - - -# Only expand once: - - - - -# Test for 64-bit build. -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 -$as_echo_n "checking size of size_t... " >&6; } -if ${ac_cv_sizeof_size_t+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_size_t" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (size_t) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_size_t=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 -$as_echo "$ac_cv_sizeof_size_t" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t -_ACEOF - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler vendor" >&5 -$as_echo_n "checking for C compiler vendor... " >&6; } -if ${ax_cv_c_compiler_vendor+:} false; then : - $as_echo_n "(cached) " >&6 -else - # note: don't check for gcc first since some other compilers define __GNUC__ - vendors="intel: __ICC,__ECC,__INTEL_COMPILER - ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ - pathscale: __PATHCC__,__PATHSCALE__ - clang: __clang__ - gnu: __GNUC__ - sun: __SUNPRO_C,__SUNPRO_CC - hp: __HP_cc,__HP_aCC - dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER - borland: __BORLANDC__,__TURBOC__ - comeau: __COMO__ - cray: _CRAYC - kai: __KCC - lcc: __LCC__ - sgi: __sgi,sgi - microsoft: _MSC_VER - metrowerks: __MWERKS__ - watcom: __WATCOMC__ - portland: __PGI - unknown: UNKNOWN" - for ventest in $vendors; do - case $ventest in - *:) vendor=$ventest; continue ;; - *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; - esac - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - #if !($vencpp) - thisisanerror; - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - break -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done - ax_cv_c_compiler_vendor=`echo $vendor | cut -d: -f1` - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_c_compiler_vendor" >&5 -$as_echo "$ax_cv_c_compiler_vendor" >&6; } - - - - - - -# Check whether --enable-portable-binary was given. -if test "${enable_portable_binary+set}" = set; then : - enableval=$enable_portable_binary; acx_maxopt_portable=$enableval -else - acx_maxopt_portable=no -fi - - -# Try to determine "good" native compiler flags if none specified via CFLAGS -if test "$ac_test_CFLAGS" != "set"; then - CFLAGS="" - case $ax_cv_c_compiler_vendor in - dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host" - if test "x$acx_maxopt_portable" = xno; then - CFLAGS="$CFLAGS -arch host" - fi;; - - sun) CFLAGS="-native -fast -xO5 -dalign" - if test "x$acx_maxopt_portable" = xyes; then - CFLAGS="$CFLAGS -xarch=generic" - fi;; - - hp) CFLAGS="+Oall +Optrs_ansi +DSnative" - if test "x$acx_maxopt_portable" = xyes; then - CFLAGS="$CFLAGS +DAportable" - fi;; - - ibm) if test "x$acx_maxopt_portable" = xno; then - xlc_opt="-qarch=auto -qtune=auto" - else - xlc_opt="-qtune=auto" - fi - as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$xlc_opt" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $xlc_opt" >&5 -$as_echo_n "checking whether C compiler accepts $xlc_opt... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS $xlc_opt" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - CFLAGS="-O3 -qansialias -w $xlc_opt" -else - CFLAGS="-O3 -qansialias -w" - echo "******************************************************" - echo "* You seem to have the IBM C compiler. It is *" - echo "* recommended for best performance that you use: *" - echo "* *" - echo "* CFLAGS=-O3 -qarch=xxx -qtune=xxx -qansialias -w *" - echo "* ^^^ ^^^ *" - echo "* where xxx is pwr2, pwr3, 604, or whatever kind of *" - echo "* CPU you have. (Set the CFLAGS environment var. *" - echo "* and re-run configure.) For more info, man cc. *" - echo "******************************************************" -fi - - ;; - - intel) CFLAGS="-O3 -ansi_alias" - if test "x$acx_maxopt_portable" = xno; then - icc_archflag=unknown - icc_flags="" - case $host_cpu in - i686*|x86_64*) - # icc accepts gcc assembly syntax, so these should work: - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 cpuid 0 output" >&5 -$as_echo_n "checking for x86 cpuid 0 output... " >&6; } -if ${ax_cv_gcc_x86_cpuid_0+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ax_cv_gcc_x86_cpuid_0=unknown -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - int op = 0, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ax_cv_gcc_x86_cpuid_0=`cat conftest_cpuid`; rm -f conftest_cpuid -else - ax_cv_gcc_x86_cpuid_0=unknown; rm -f conftest_cpuid -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_x86_cpuid_0" >&5 -$as_echo "$ax_cv_gcc_x86_cpuid_0" >&6; } -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 cpuid 1 output" >&5 -$as_echo_n "checking for x86 cpuid 1 output... " >&6; } -if ${ax_cv_gcc_x86_cpuid_1+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ax_cv_gcc_x86_cpuid_1=unknown -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - int op = 1, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ax_cv_gcc_x86_cpuid_1=`cat conftest_cpuid`; rm -f conftest_cpuid -else - ax_cv_gcc_x86_cpuid_1=unknown; rm -f conftest_cpuid -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_x86_cpuid_1" >&5 -$as_echo "$ax_cv_gcc_x86_cpuid_1" >&6; } -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG - *:756e6547:*:*) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *6a?:*[234]:*:*|*6[789b]?:*:*:*) icc_flags="-xK";; - *f3[347]:*:*:*|*f41347:*:*:*) icc_flags="-xP -xN -xW -xK";; - *f??:*:*:*) icc_flags="-xN -xW -xK";; - esac ;; - esac ;; - esac - if test "x$icc_flags" != x; then - for flag in $icc_flags; do - as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 -$as_echo_n "checking whether C compiler accepts $flag... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS $flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - icc_archflag=$flag; break -else - : -fi - - done - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for icc architecture flag" >&5 -$as_echo_n "checking for icc architecture flag... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $icc_archflag" >&5 -$as_echo "$icc_archflag" >&6; } - if test "x$icc_archflag" != xunknown; then - CFLAGS="$CFLAGS $icc_archflag" - fi - fi - ;; - - gnu) - # default optimization flags for gcc on all systems - CFLAGS="-O3 -fomit-frame-pointer" - - # -malign-double for x86 systems - # LIBFFI -- DON'T DO THIS - CHANGES ABI - # AX_CHECK_COMPILE_FLAG(-malign-double, CFLAGS="$CFLAGS -malign-double") - - # -fstrict-aliasing for gcc-2.95+ - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fstrict-aliasing" >&5 -$as_echo_n "checking whether C compiler accepts -fstrict-aliasing... " >&6; } -if ${ax_cv_check_cflags___fstrict_aliasing+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -fstrict-aliasing" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___fstrict_aliasing=yes -else - ax_cv_check_cflags___fstrict_aliasing=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fstrict_aliasing" >&5 -$as_echo "$ax_cv_check_cflags___fstrict_aliasing" >&6; } -if test x"$ax_cv_check_cflags___fstrict_aliasing" = xyes; then : - CFLAGS="$CFLAGS -fstrict-aliasing" -else - : -fi - - - # note that we enable "unsafe" fp optimization with other compilers, too - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -ffast-math" >&5 -$as_echo_n "checking whether C compiler accepts -ffast-math... " >&6; } -if ${ax_cv_check_cflags___ffast_math+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -ffast-math" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___ffast_math=yes -else - ax_cv_check_cflags___ffast_math=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___ffast_math" >&5 -$as_echo "$ax_cv_check_cflags___ffast_math" >&6; } -if test x"$ax_cv_check_cflags___ffast_math" = xyes; then : - CFLAGS="$CFLAGS -ffast-math" -else - : -fi - - - - - - -# Check whether --with-gcc-arch was given. -if test "${with_gcc_arch+set}" = set; then : - withval=$with_gcc_arch; ax_gcc_arch=$withval -else - ax_gcc_arch=yes -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc architecture flag" >&5 -$as_echo_n "checking for gcc architecture flag... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 -$as_echo "" >&6; } -if ${ax_cv_gcc_archflag+:} false; then : - $as_echo_n "(cached) " >&6 -else - -ax_cv_gcc_archflag="unknown" - -if test "$GCC" = yes; then - -if test "x$ax_gcc_arch" = xyes; then -ax_gcc_arch="" -if test "$cross_compiling" = no; then -case $host_cpu in - i[3456]86*|x86_64*) # use cpuid codes - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 cpuid 0 output" >&5 -$as_echo_n "checking for x86 cpuid 0 output... " >&6; } -if ${ax_cv_gcc_x86_cpuid_0+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ax_cv_gcc_x86_cpuid_0=unknown -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - int op = 0, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ax_cv_gcc_x86_cpuid_0=`cat conftest_cpuid`; rm -f conftest_cpuid -else - ax_cv_gcc_x86_cpuid_0=unknown; rm -f conftest_cpuid -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_x86_cpuid_0" >&5 -$as_echo "$ax_cv_gcc_x86_cpuid_0" >&6; } -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 cpuid 1 output" >&5 -$as_echo_n "checking for x86 cpuid 1 output... " >&6; } -if ${ax_cv_gcc_x86_cpuid_1+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ax_cv_gcc_x86_cpuid_1=unknown -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - int op = 1, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ax_cv_gcc_x86_cpuid_1=`cat conftest_cpuid`; rm -f conftest_cpuid -else - ax_cv_gcc_x86_cpuid_1=unknown; rm -f conftest_cpuid -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_x86_cpuid_1" >&5 -$as_echo "$ax_cv_gcc_x86_cpuid_1" >&6; } -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - case $ax_cv_gcc_x86_cpuid_0 in - *:756e6547:*:*) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *5[48]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; - *5??:*:*:*) ax_gcc_arch=pentium ;; - *0?6[3456]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[01]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[234]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6[9de]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; - *0?6[78b]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; - *1?6[7d]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; - *1?6[aef]?:*:*:*|*2?6[5cef]?:*:*:*) ax_gcc_arch="corei7 core2 pentium-m pentium3 pentiumpro" ;; - *1?6c?:*:*:*|*[23]?66?:*:*:*) ax_gcc_arch="atom core2 pentium-m pentium3 pentiumpro" ;; - *2?6[ad]?:*:*:*) ax_gcc_arch="corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *0?6??:*:*:*) ax_gcc_arch=pentiumpro ;; - *6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; - ?000?f3[347]:*:*:*|?000?f41347:*:*:*|?000?f6?:*:*:*) - case $host_cpu in - x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;; - *) ax_gcc_arch="prescott pentium4 pentiumpro" ;; - esac ;; - ?000?f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";; - esac ;; - *:68747541:*:*) # AMD - case $ax_cv_gcc_x86_cpuid_1 in - *5[67]?:*:*:*) ax_gcc_arch=k6 ;; - *5[8d]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; - *5[9]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; - *60?:*:*:*) ax_gcc_arch=k7 ;; - *6[12]?:*:*:*) ax_gcc_arch="athlon k7" ;; - *6[34]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; - *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;; - *6[68a]?:*:*:*) - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 cpuid 0x80000006 output" >&5 -$as_echo_n "checking for x86 cpuid 0x80000006 output... " >&6; } -if ${ax_cv_gcc_x86_cpuid_0x80000006+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ax_cv_gcc_x86_cpuid_0x80000006=unknown -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - int op = 0x80000006, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ax_cv_gcc_x86_cpuid_0x80000006=`cat conftest_cpuid`; rm -f conftest_cpuid -else - ax_cv_gcc_x86_cpuid_0x80000006=unknown; rm -f conftest_cpuid -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_x86_cpuid_0x80000006" >&5 -$as_echo "$ax_cv_gcc_x86_cpuid_0x80000006" >&6; } -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - # L2 cache size - case $ax_cv_gcc_x86_cpuid_0x80000006 in - *:*:*[1-9a-f]??????:*) # (L2 = ecx >> 16) >= 256 - ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; - *) ax_gcc_arch="athlon-4 athlon k7" ;; - esac ;; - ?00??f[4cef8b]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; - ?00??f5?:*:*:*) ax_gcc_arch="opteron k8" ;; - ?00??f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;; - ?00??f??:*:*:*) ax_gcc_arch="k8" ;; - ?05??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - ?06??f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; - esac ;; - *:746e6543:*:*) # IDT - case $ax_cv_gcc_x86_cpuid_1 in - *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; - *58?:*:*:*) ax_gcc_arch=winchip2 ;; - *6[78]?:*:*:*) ax_gcc_arch=c3 ;; - *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;; - esac ;; - esac - if test x"$ax_gcc_arch" = x; then # fallback - case $host_cpu in - i586*) ax_gcc_arch=pentium ;; - i686*) ax_gcc_arch=pentiumpro ;; - esac - fi - ;; - - sparc*) - # Extract the first word of "prtdiag", so it can be a program name with args. -set dummy prtdiag; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PRTDIAG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PRTDIAG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PRTDIAG="$PRTDIAG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PRTDIAG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_PRTDIAG" && ac_cv_path_PRTDIAG="prtdiag" - ;; -esac -fi -PRTDIAG=$ac_cv_path_PRTDIAG -if test -n "$PRTDIAG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PRTDIAG" >&5 -$as_echo "$PRTDIAG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` - cputype=`echo "$cputype" | tr -d ' -' | sed 's/SPARCIIi/SPARCII/' | tr $as_cr_LETTERS $as_cr_letters` - case $cputype in - *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; - *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; - *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; - *supersparc*|*tms390z5[05]*) ax_gcc_arch="supersparc v8" ;; - *hypersparc*|*rt62[056]*) ax_gcc_arch="hypersparc v8" ;; - *cypress*) ax_gcc_arch=cypress ;; - esac ;; - - alphaev5) ax_gcc_arch=ev5 ;; - alphaev56) ax_gcc_arch=ev56 ;; - alphapca56) ax_gcc_arch="pca56 ev56" ;; - alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; - alphaev6) ax_gcc_arch=ev6 ;; - alphaev67) ax_gcc_arch=ev67 ;; - alphaev68) ax_gcc_arch="ev68 ev67" ;; - alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; - alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; - alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; - - powerpc*) - cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` - cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'` - case $cputype in - *750*) ax_gcc_arch="750 G3" ;; - *740[0-9]*) ax_gcc_arch="$cputype 7400 G4" ;; - *74[4-5][0-9]*) ax_gcc_arch="$cputype 7450 G4" ;; - *74[0-9][0-9]*) ax_gcc_arch="$cputype G4" ;; - *970*) ax_gcc_arch="970 G5 power4";; - *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; - *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; - 603ev|8240) ax_gcc_arch="$cputype 603e 603";; - *) ax_gcc_arch=$cputype ;; - esac - ax_gcc_arch="$ax_gcc_arch powerpc" - ;; -esac -fi # not cross-compiling -fi # guess arch - -if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then -for arch in $ax_gcc_arch; do - if test "x$acx_maxopt_portable" = xyes; then # if we require portable code - flags="-mtune=$arch" - # -mcpu=$arch and m$arch generate nonportable code on every arch except - # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. - case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac - else - flags="-march=$arch -mcpu=$arch -m$arch" - fi - for flag in $flags; do - as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 -$as_echo_n "checking whether C compiler accepts $flag... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS $flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - ax_cv_gcc_archflag=$flag; break -else - : -fi - - done - test "x$ax_cv_gcc_archflag" = xunknown || break -done -fi - -fi # $GCC=yes - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc architecture flag" >&5 -$as_echo_n "checking for gcc architecture flag... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_gcc_archflag" >&5 -$as_echo "$ax_cv_gcc_archflag" >&6; } -if test "x$ax_cv_gcc_archflag" = xunknown; then - : -else - CFLAGS="$CFLAGS $ax_cv_gcc_archflag" -fi - - ;; - esac - - if test -z "$CFLAGS"; then - echo "" - echo "********************************************************" - echo "* WARNING: Don't know the best CFLAGS for this system *" - echo "* Use ./configure CFLAGS=... to specify your own flags *" - echo "* (otherwise, a default of CFLAGS=-O3 will be used) *" - echo "********************************************************" - echo "" - CFLAGS="-O3" - fi - - as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$CFLAGS" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $CFLAGS" >&5 -$as_echo_n "checking whether C compiler accepts $CFLAGS... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS $CFLAGS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - : -else - - echo "" - echo "********************************************************" - echo "* WARNING: The guessed CFLAGS don't seem to work with *" - echo "* your compiler. *" - echo "* Use ./configure CFLAGS=... to specify your own flags *" - echo "********************************************************" - echo "" - CFLAGS="" - -fi - - -fi - -# The AX_CFLAGS_WARN_ALL macro doesn't currently work for sunpro -# compiler. -if test "$ax_cv_c_compiler_vendor" != "sun"; then - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains "; } >&5 - (: CFLAGS already contains ) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \""; } >&5 - (: CFLAGS="$CFLAGS ") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CFLAGS="$CFLAGS " - ;; - esac -else - CFLAGS="" -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CFLAGS for maximum warnings" >&5 -$as_echo_n "checking CFLAGS for maximum warnings... " >&6; } -if ${ac_cv_cflags_warn_all+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_cflags_warn_all="no, unknown" -ac_save_CFLAGS="$CFLAGS" -for ac_arg in "-warn all % -warn all" "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" # -do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -done -CFLAGS="$ac_save_CFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags_warn_all" >&5 -$as_echo "$ac_cv_cflags_warn_all" >&6; } - -case ".$ac_cv_cflags_warn_all" in - .ok|.ok,*) ;; - .|.no|.no,*) ;; - *) if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $ac_cv_cflags_warn_all "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$ac_cv_cflags_warn_all"; } >&5 - (: CFLAGS already contains $ac_cv_cflags_warn_all) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_warn_all\""; } >&5 - (: CFLAGS="$CFLAGS $ac_cv_cflags_warn_all") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CFLAGS="$CFLAGS $ac_cv_cflags_warn_all" - ;; - esac -else - CFLAGS="$ac_cv_cflags_warn_all" -fi - ;; -esac - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -fi - -if test "x$GCC" = "xyes"; then - CFLAGS="$CFLAGS -fexceptions" -fi - -cat > local.exp <&5 -$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } - # Check whether --enable-maintainer-mode was given. -if test "${enable_maintainer_mode+set}" = set; then : - enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval -else - USE_MAINTAINER_MODE=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 -$as_echo "$USE_MAINTAINER_MODE" >&6; } - if test $USE_MAINTAINER_MODE = yes; then - MAINTAINER_MODE_TRUE= - MAINTAINER_MODE_FALSE='#' -else - MAINTAINER_MODE_TRUE='#' - MAINTAINER_MODE_FALSE= -fi - - MAINT=$MAINTAINER_MODE_TRUE - - - -for ac_header in sys/mman.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_mman_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_MMAN_H 1 -_ACEOF - -fi - -done - -for ac_func in mmap mkostemp -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - -ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_mman_h" = xyes; then : - libffi_header_sys_mman_h=yes -else - libffi_header_sys_mman_h=no -fi - - -ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap" -if test "x$ac_cv_func_mmap" = xyes; then : - libffi_func_mmap=yes -else - libffi_func_mmap=no -fi - -if test "$libffi_header_sys_mman_h" != yes \ - || test "$libffi_func_mmap" != yes; then - ac_cv_func_mmap_file=no - ac_cv_func_mmap_dev_zero=no - ac_cv_func_mmap_anon=no -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5 -$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; } -if ${ac_cv_func_mmap_file+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Add a system to this blacklist if - # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a - # memory area containing the same data that you'd get if you applied - # read() to the same fd. The only system known to have a problem here - # is VMS, where text files have record structure. - case "$host_os" in - vms* | ultrix*) - ac_cv_func_mmap_file=no ;; - *) - ac_cv_func_mmap_file=yes;; - esac -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_file" >&5 -$as_echo "$ac_cv_func_mmap_file" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5 -$as_echo_n "checking whether mmap from /dev/zero works... " >&6; } -if ${ac_cv_func_mmap_dev_zero+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Add a system to this blacklist if it has mmap() but /dev/zero - # does not exist, or if mmapping /dev/zero does not give anonymous - # zeroed pages with both the following properties: - # 1. If you map N consecutive pages in with one call, and then - # unmap any subset of those pages, the pages that were not - # explicitly unmapped remain accessible. - # 2. If you map two adjacent blocks of memory and then unmap them - # both at once, they must both go away. - # Systems known to be in this category are Windows (all variants), - # VMS, and Darwin. - case "$host_os" in - vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00) - ac_cv_func_mmap_dev_zero=no ;; - *) - ac_cv_func_mmap_dev_zero=yes;; - esac -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_dev_zero" >&5 -$as_echo "$ac_cv_func_mmap_dev_zero" >&6; } - - # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5 -$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; } -if ${ac_cv_decl_map_anon+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -int -main () -{ -int n = MAP_ANONYMOUS; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_decl_map_anon=yes -else - ac_cv_decl_map_anon=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_map_anon" >&5 -$as_echo "$ac_cv_decl_map_anon" >&6; } - - if test $ac_cv_decl_map_anon = no; then - ac_cv_func_mmap_anon=no - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5 -$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; } -if ${ac_cv_func_mmap_anon+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Add a system to this blacklist if it has mmap() and MAP_ANON or - # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) - # doesn't give anonymous zeroed pages with the same properties listed - # above for use of /dev/zero. - # Systems known to be in this category are Windows, VMS, and SCO Unix. - case "$host_os" in - vms* | cygwin* | pe | mingw* | sco* | udk* ) - ac_cv_func_mmap_anon=no ;; - *) - ac_cv_func_mmap_anon=yes;; - esac -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_anon" >&5 -$as_echo "$ac_cv_func_mmap_anon" >&6; } - fi -fi - -if test $ac_cv_func_mmap_file = yes; then - -$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h - -fi -if test $ac_cv_func_mmap_dev_zero = yes; then - -$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h - -fi -if test $ac_cv_func_mmap_anon = yes; then - -$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h - -fi - - - if test -d $srcdir/testsuite; then - TESTSUBDIR_TRUE= - TESTSUBDIR_FALSE='#' -else - TESTSUBDIR_TRUE='#' - TESTSUBDIR_FALSE= -fi - - -TARGETDIR="unknown" -HAVE_LONG_DOUBLE_VARIANT=0 -case "$host" in - aarch64*-*-*) - TARGET=AARCH64; TARGETDIR=aarch64 - ;; - - alpha*-*-*) - TARGET=ALPHA; TARGETDIR=alpha; - # Support 128-bit long double, changeable via command-line switch. - HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)' - ;; - - arc*-*-*) - TARGET=ARC; TARGETDIR=arc - ;; - - arm*-*-*) - TARGET=ARM; TARGETDIR=arm - ;; - - amd64-*-freebsd* | amd64-*-openbsd*) - TARGET=X86_64; TARGETDIR=x86 - ;; - - amd64-*-freebsd*) - TARGET=X86_64; TARGETDIR=x86 - ;; - - amd64-*-freebsd*) - TARGET=X86_64; TARGETDIR=x86 - ;; - - avr32*-*-*) - TARGET=AVR32; TARGETDIR=avr32 - ;; - - bfin*) - TARGET=BFIN; TARGETDIR=bfin - ;; - - cris-*-*) - TARGET=LIBFFI_CRIS; TARGETDIR=cris - ;; - - frv-*-*) - TARGET=FRV; TARGETDIR=frv - ;; - - hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*) - TARGET=PA_LINUX; TARGETDIR=pa - ;; - hppa*64-*-hpux*) - TARGET=PA64_HPUX; TARGETDIR=pa - ;; - hppa*-*-hpux*) - TARGET=PA_HPUX; TARGETDIR=pa - ;; - - i?86-*-freebsd* | i?86-*-openbsd*) - TARGET=X86_FREEBSD; TARGETDIR=x86 - ;; - i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*) - TARGET=X86_WIN32; TARGETDIR=x86 - # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. - # We must also check with_cross_host to decide if this is a native - # or cross-build and select where to install dlls appropriately. - if test -n "$with_cross_host" && - test x"$with_cross_host" != x"no"; then - AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"'; - else - AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"'; - fi - ;; - i?86-*-darwin*) - TARGET=X86_DARWIN; TARGETDIR=x86 - ;; - i?86-*-solaris2.1[0-9]*) - TARGETDIR=x86 - if test $ac_cv_sizeof_size_t = 4; then - TARGET=X86; - else - TARGET=X86_64; - fi - ;; - - x86_64-*-darwin*) - TARGET=X86_DARWIN; TARGETDIR=x86 - ;; - - x86_64-*-cygwin* | x86_64-*-mingw*) - TARGET=X86_WIN64; TARGETDIR=x86 - # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. - # We must also check with_cross_host to decide if this is a native - # or cross-build and select where to install dlls appropriately. - if test -n "$with_cross_host" && - test x"$with_cross_host" != x"no"; then - AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"'; - else - AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"'; - fi - ;; - - i?86-*-* | x86_64-*-*) - TARGETDIR=x86 - if test $ac_cv_sizeof_size_t = 4; then - case "$host" in - *-gnux32) - TARGET=X86_64 - ;; - *) - TARGET=X86 - ;; - esac - else - TARGET=X86_64; - fi - ;; - - ia64*-*-*) - TARGET=IA64; TARGETDIR=ia64 - ;; - - m32r*-*-*) - TARGET=M32R; TARGETDIR=m32r - ;; - - m68k-*-*) - TARGET=M68K; TARGETDIR=m68k - ;; - - m88k-*-*) - TARGET=M88K; TARGETDIR=m88k - ;; - - microblaze*-*-*) - TARGET=MICROBLAZE; TARGETDIR=microblaze - ;; - - moxie-*-*) - TARGET=MOXIE; TARGETDIR=moxie - ;; - - metag-*-*) - TARGET=METAG; TARGETDIR=metag - ;; - - mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*) - TARGET=MIPS; TARGETDIR=mips - ;; - mips*-*linux* | mips*-*-openbsd*) - # Support 128-bit long double for NewABI. - HAVE_LONG_DOUBLE='defined(__mips64)' - TARGET=MIPS; TARGETDIR=mips - ;; - - nios2*-linux*) - TARGET=NIOS2; TARGETDIR=nios2 - ;; - - or1k*-linux*) - TARGET=OR1K; TARGETDIR=or1k - ;; - - powerpc*-*-linux* | powerpc-*-sysv*) - TARGET=POWERPC; TARGETDIR=powerpc - HAVE_LONG_DOUBLE_VARIANT=1 - ;; - powerpc-*-amigaos*) - TARGET=POWERPC; TARGETDIR=powerpc - ;; - powerpc-*-beos*) - TARGET=POWERPC; TARGETDIR=powerpc - ;; - powerpc-*-darwin* | powerpc64-*-darwin*) - TARGET=POWERPC_DARWIN; TARGETDIR=powerpc - ;; - powerpc-*-aix* | rs6000-*-aix*) - TARGET=POWERPC_AIX; TARGETDIR=powerpc - ;; - powerpc-*-freebsd* | powerpc-*-openbsd*) - TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc - HAVE_LONG_DOUBLE_VARIANT=1 - ;; - powerpc64-*-freebsd*) - TARGET=POWERPC; TARGETDIR=powerpc - ;; - powerpc*-*-rtems*) - TARGET=POWERPC; TARGETDIR=powerpc - ;; - - s390-*-* | s390x-*-*) - TARGET=S390; TARGETDIR=s390 - ;; - - sh-*-* | sh[34]*-*-*) - TARGET=SH; TARGETDIR=sh - ;; - sh64-*-* | sh5*-*-*) - TARGET=SH64; TARGETDIR=sh64 - ;; - - sparc*-*-*) - TARGET=SPARC; TARGETDIR=sparc - ;; - - tile*-*) - TARGET=TILE; TARGETDIR=tile - ;; - - vax-*-*) - TARGET=VAX; TARGETDIR=vax - ;; - - xtensa*-*) - TARGET=XTENSA; TARGETDIR=xtensa - ;; - -esac - - - - -if test $TARGETDIR = unknown; then - as_fn_error $? "\"libffi has not been ported to $host.\"" "$LINENO" 5 -fi - - if test x$TARGET = xMIPS; then - MIPS_TRUE= - MIPS_FALSE='#' -else - MIPS_TRUE='#' - MIPS_FALSE= -fi - - if test x$TARGET = xBFIN; then - BFIN_TRUE= - BFIN_FALSE='#' -else - BFIN_TRUE='#' - BFIN_FALSE= -fi - - if test x$TARGET = xSPARC; then - SPARC_TRUE= - SPARC_FALSE='#' -else - SPARC_TRUE='#' - SPARC_FALSE= -fi - - if test x$TARGET = xX86; then - X86_TRUE= - X86_FALSE='#' -else - X86_TRUE='#' - X86_FALSE= -fi - - if test x$TARGET = xX86_FREEBSD; then - X86_FREEBSD_TRUE= - X86_FREEBSD_FALSE='#' -else - X86_FREEBSD_TRUE='#' - X86_FREEBSD_FALSE= -fi - - if test x$TARGET = xX86_WIN32; then - X86_WIN32_TRUE= - X86_WIN32_FALSE='#' -else - X86_WIN32_TRUE='#' - X86_WIN32_FALSE= -fi - - if test x$TARGET = xX86_WIN64; then - X86_WIN64_TRUE= - X86_WIN64_FALSE='#' -else - X86_WIN64_TRUE='#' - X86_WIN64_FALSE= -fi - - if test x$TARGET = xX86_DARWIN; then - X86_DARWIN_TRUE= - X86_DARWIN_FALSE='#' -else - X86_DARWIN_TRUE='#' - X86_DARWIN_FALSE= -fi - - if test x$TARGET = xX86_DARWIN && test $ac_cv_sizeof_size_t = 4; then - X86_DARWIN32_TRUE= - X86_DARWIN32_FALSE='#' -else - X86_DARWIN32_TRUE='#' - X86_DARWIN32_FALSE= -fi - - if test x$TARGET = xX86_DARWIN && test $ac_cv_sizeof_size_t = 8; then - X86_DARWIN64_TRUE= - X86_DARWIN64_FALSE='#' -else - X86_DARWIN64_TRUE='#' - X86_DARWIN64_FALSE= -fi - - if test x$TARGET = xALPHA; then - ALPHA_TRUE= - ALPHA_FALSE='#' -else - ALPHA_TRUE='#' - ALPHA_FALSE= -fi - - if test x$TARGET = xIA64; then - IA64_TRUE= - IA64_FALSE='#' -else - IA64_TRUE='#' - IA64_FALSE= -fi - - if test x$TARGET = xM32R; then - M32R_TRUE= - M32R_FALSE='#' -else - M32R_TRUE='#' - M32R_FALSE= -fi - - if test x$TARGET = xM68K; then - M68K_TRUE= - M68K_FALSE='#' -else - M68K_TRUE='#' - M68K_FALSE= -fi - - if test x$TARGET = xM88K; then - M88K_TRUE= - M88K_FALSE='#' -else - M88K_TRUE='#' - M88K_FALSE= -fi - - if test x$TARGET = xMICROBLAZE; then - MICROBLAZE_TRUE= - MICROBLAZE_FALSE='#' -else - MICROBLAZE_TRUE='#' - MICROBLAZE_FALSE= -fi - - if test x$TARGET = xMETAG; then - METAG_TRUE= - METAG_FALSE='#' -else - METAG_TRUE='#' - METAG_FALSE= -fi - - if test x$TARGET = xMOXIE; then - MOXIE_TRUE= - MOXIE_FALSE='#' -else - MOXIE_TRUE='#' - MOXIE_FALSE= -fi - - if test x$TARGET = xNIOS2; then - NIOS2_TRUE= - NIOS2_FALSE='#' -else - NIOS2_TRUE='#' - NIOS2_FALSE= -fi - - if test x$TARGET = xOR1K; then - OR1K_TRUE= - OR1K_FALSE='#' -else - OR1K_TRUE='#' - OR1K_FALSE= -fi - - if test x$TARGET = xPOWERPC; then - POWERPC_TRUE= - POWERPC_FALSE='#' -else - POWERPC_TRUE='#' - POWERPC_FALSE= -fi - - if test x$TARGET = xPOWERPC_AIX; then - POWERPC_AIX_TRUE= - POWERPC_AIX_FALSE='#' -else - POWERPC_AIX_TRUE='#' - POWERPC_AIX_FALSE= -fi - - if test x$TARGET = xPOWERPC_DARWIN; then - POWERPC_DARWIN_TRUE= - POWERPC_DARWIN_FALSE='#' -else - POWERPC_DARWIN_TRUE='#' - POWERPC_DARWIN_FALSE= -fi - - if test x$TARGET = xPOWERPC_FREEBSD; then - POWERPC_FREEBSD_TRUE= - POWERPC_FREEBSD_FALSE='#' -else - POWERPC_FREEBSD_TRUE='#' - POWERPC_FREEBSD_FALSE= -fi - - if test x$TARGET = xAARCH64; then - AARCH64_TRUE= - AARCH64_FALSE='#' -else - AARCH64_TRUE='#' - AARCH64_FALSE= -fi - - if test x$TARGET = xARC; then - ARC_TRUE= - ARC_FALSE='#' -else - ARC_TRUE='#' - ARC_FALSE= -fi - - if test x$TARGET = xARM; then - ARM_TRUE= - ARM_FALSE='#' -else - ARM_TRUE='#' - ARM_FALSE= -fi - - if test x$TARGET = xAVR32; then - AVR32_TRUE= - AVR32_FALSE='#' -else - AVR32_TRUE='#' - AVR32_FALSE= -fi - - if test x$TARGET = xLIBFFI_CRIS; then - LIBFFI_CRIS_TRUE= - LIBFFI_CRIS_FALSE='#' -else - LIBFFI_CRIS_TRUE='#' - LIBFFI_CRIS_FALSE= -fi - - if test x$TARGET = xFRV; then - FRV_TRUE= - FRV_FALSE='#' -else - FRV_TRUE='#' - FRV_FALSE= -fi - - if test x$TARGET = xS390; then - S390_TRUE= - S390_FALSE='#' -else - S390_TRUE='#' - S390_FALSE= -fi - - if test x$TARGET = xX86_64; then - X86_64_TRUE= - X86_64_FALSE='#' -else - X86_64_TRUE='#' - X86_64_FALSE= -fi - - if test x$TARGET = xSH; then - SH_TRUE= - SH_FALSE='#' -else - SH_TRUE='#' - SH_FALSE= -fi - - if test x$TARGET = xSH64; then - SH64_TRUE= - SH64_FALSE='#' -else - SH64_TRUE='#' - SH64_FALSE= -fi - - if test x$TARGET = xPA_LINUX; then - PA_LINUX_TRUE= - PA_LINUX_FALSE='#' -else - PA_LINUX_TRUE='#' - PA_LINUX_FALSE= -fi - - if test x$TARGET = xPA_HPUX; then - PA_HPUX_TRUE= - PA_HPUX_FALSE='#' -else - PA_HPUX_TRUE='#' - PA_HPUX_FALSE= -fi - - if test x$TARGET = xPA64_HPUX; then - PA64_HPUX_TRUE= - PA64_HPUX_FALSE='#' -else - PA64_HPUX_TRUE='#' - PA64_HPUX_FALSE= -fi - - if test x$TARGET = xTILE; then - TILE_TRUE= - TILE_FALSE='#' -else - TILE_TRUE='#' - TILE_FALSE= -fi - - if test x$TARGET = xVAX; then - VAX_TRUE= - VAX_FALSE='#' -else - VAX_TRUE='#' - VAX_FALSE= -fi - - if test x$TARGET = xXTENSA; then - XTENSA_TRUE= - XTENSA_FALSE='#' -else - XTENSA_TRUE='#' - XTENSA_FALSE= -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -for ac_func in memcpy -do : - ac_fn_c_check_func "$LINENO" "memcpy" "ac_cv_func_memcpy" -if test "x$ac_cv_func_memcpy" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_MEMCPY 1 -_ACEOF - -fi -done - -ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" -if test "x$ac_cv_type_size_t" = xyes; then : - -else - -cat >>confdefs.h <<_ACEOF -#define size_t unsigned int -_ACEOF - -fi - -# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works -# for constant arguments. Useless! -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 -$as_echo_n "checking for working alloca.h... " >&6; } -if ${ac_cv_working_alloca_h+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -char *p = (char *) alloca (2 * sizeof (int)); - if (p) return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_working_alloca_h=yes -else - ac_cv_working_alloca_h=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 -$as_echo "$ac_cv_working_alloca_h" >&6; } -if test $ac_cv_working_alloca_h = yes; then - -$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 -$as_echo_n "checking for alloca... " >&6; } -if ${ac_cv_func_alloca_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __GNUC__ -# define alloca __builtin_alloca -#else -# ifdef _MSC_VER -# include -# define alloca _alloca -# else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -void *alloca (size_t); -# endif -# endif -# endif -# endif -#endif - -int -main () -{ -char *p = (char *) alloca (1); - if (p) return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_func_alloca_works=yes -else - ac_cv_func_alloca_works=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 -$as_echo "$ac_cv_func_alloca_works" >&6; } - -if test $ac_cv_func_alloca_works = yes; then - -$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h - -else - # The SVR3 libPW and SVR4 libucb both contain incompatible functions -# that cause trouble. Some versions do not even contain alloca or -# contain a buggy version. If you still want to use their alloca, -# use ar to extract alloca.o from them instead of compiling alloca.c. - -ALLOCA=\${LIBOBJDIR}alloca.$ac_objext - -$as_echo "#define C_ALLOCA 1" >>confdefs.h - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 -$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } -if ${ac_cv_os_cray+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#if defined CRAY && ! defined CRAY2 -webecray -#else -wenotbecray -#endif - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "webecray" >/dev/null 2>&1; then : - ac_cv_os_cray=yes -else - ac_cv_os_cray=no -fi -rm -f conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 -$as_echo "$ac_cv_os_cray" >&6; } -if test $ac_cv_os_cray = yes; then - for ac_func in _getb67 GETB67 getb67; do - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - -cat >>confdefs.h <<_ACEOF -#define CRAY_STACKSEG_END $ac_func -_ACEOF - - break -fi - - done -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 -$as_echo_n "checking stack direction for C alloca... " >&6; } -if ${ac_cv_c_stack_direction+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_c_stack_direction=0 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -find_stack_direction (int *addr, int depth) -{ - int dir, dummy = 0; - if (! addr) - addr = &dummy; - *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; - dir = depth ? find_stack_direction (addr, depth - 1) : 0; - return dir + dummy; -} - -int -main (int argc, char **argv) -{ - return find_stack_direction (0, argc + !argv + 20) < 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_c_stack_direction=1 -else - ac_cv_c_stack_direction=-1 -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 -$as_echo "$ac_cv_c_stack_direction" >&6; } -cat >>confdefs.h <<_ACEOF -#define STACK_DIRECTION $ac_cv_c_stack_direction -_ACEOF - - -fi - - -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5 -$as_echo_n "checking size of double... " >&6; } -if ${ac_cv_sizeof_double+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_double" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (double) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_double=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5 -$as_echo "$ac_cv_sizeof_double" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_DOUBLE $ac_cv_sizeof_double -_ACEOF - - -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long double" >&5 -$as_echo_n "checking size of long double... " >&6; } -if ${ac_cv_sizeof_long_double+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long double))" "ac_cv_sizeof_long_double" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_long_double" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (long double) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_long_double=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_double" >&5 -$as_echo "$ac_cv_sizeof_long_double" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double -_ACEOF - - - -# Also AC_SUBST this variable for ffi.h. -if test -z "$HAVE_LONG_DOUBLE"; then - HAVE_LONG_DOUBLE=0 - if test $ac_cv_sizeof_long_double != 0; then - if test $HAVE_LONG_DOUBLE_VARIANT != 0; then - -$as_echo "#define HAVE_LONG_DOUBLE_VARIANT 1" >>confdefs.h - - HAVE_LONG_DOUBLE=1 - else - if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then - HAVE_LONG_DOUBLE=1 - -$as_echo "#define HAVE_LONG_DOUBLE 1" >>confdefs.h - - fi - fi - fi -fi - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -$as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if ${ac_cv_c_bigendian+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_c_bigendian=unknown - # See if we're dealing with a universal compiler. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifndef __APPLE_CC__ - not a universal capable compiler - #endif - typedef int dummy; - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - # Check for potential -arch flags. It is not universal unless - # there are at least two -arch flags with different values. - ac_arch= - ac_prev= - for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do - if test -n "$ac_prev"; then - case $ac_word in - i?86 | x86_64 | ppc | ppc64) - if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then - ac_arch=$ac_word - else - ac_cv_c_bigendian=universal - break - fi - ;; - esac - ac_prev= - elif test "x$ac_word" = "x-arch"; then - ac_prev=arch - fi - done -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test $ac_cv_c_bigendian = unknown; then - # See if sys/param.h defines the BYTE_ORDER macro. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include - -int -main () -{ -#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ - && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ - && LITTLE_ENDIAN) - bogus endian macros - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include - -int -main () -{ -#if BYTE_ORDER != BIG_ENDIAN - not big endian - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ -#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) - bogus endian macros - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to _BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ -#ifndef _BIG_ENDIAN - not big endian - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # Compile a test program. - if test "$cross_compiling" = yes; then : - # Try to guess by grepping values from an object file. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -short int ascii_mm[] = - { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - short int ascii_ii[] = - { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; - int use_ascii (int i) { - return ascii_mm[i] + ascii_ii[i]; - } - short int ebcdic_ii[] = - { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - short int ebcdic_mm[] = - { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; - int use_ebcdic (int i) { - return ebcdic_mm[i] + ebcdic_ii[i]; - } - extern int foo; - -int -main () -{ -return use_ascii (foo) == use_ebcdic (foo); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then - ac_cv_c_bigendian=yes - fi - if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi - fi -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ - - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long int l; - char c[sizeof (long int)]; - } u; - u.l = 1; - return u.c[sizeof (long int) - 1] == 1; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_c_bigendian=no -else - ac_cv_c_bigendian=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -$as_echo "$ac_cv_c_bigendian" >&6; } - case $ac_cv_c_bigendian in #( - yes) - $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h -;; #( - no) - ;; #( - universal) - -$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - - ;; #( - *) - as_fn_error $? "unknown endianness - presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; - esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .cfi pseudo-op support" >&5 -$as_echo_n "checking assembler .cfi pseudo-op support... " >&6; } -if ${gcc_cv_as_cfi_pseudo_op+:} false; then : - $as_echo_n "(cached) " >&6 -else - - gcc_cv_as_cfi_pseudo_op=unknown - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -asm (".cfi_startproc\n\t.cfi_endproc"); -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - gcc_cv_as_cfi_pseudo_op=yes -else - gcc_cv_as_cfi_pseudo_op=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_cfi_pseudo_op" >&5 -$as_echo "$gcc_cv_as_cfi_pseudo_op" >&6; } - if test "x$gcc_cv_as_cfi_pseudo_op" = xyes; then - -$as_echo "#define HAVE_AS_CFI_PSEUDO_OP 1" >>confdefs.h - - fi - - -if test x$TARGET = xSPARC; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker support unaligned pc related relocs" >&5 -$as_echo_n "checking assembler and linker support unaligned pc related relocs... " >&6; } -if ${libffi_cv_as_sparc_ua_pcrel+:} false; then : - $as_echo_n "(cached) " >&6 -else - - save_CFLAGS="$CFLAGS" - save_LDFLAGS="$LDFLAGS" - CFLAGS="$CFLAGS -fpic" - LDFLAGS="$LDFLAGS -shared" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text"); -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - libffi_cv_as_sparc_ua_pcrel=yes -else - libffi_cv_as_sparc_ua_pcrel=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS="$save_CFLAGS" - LDFLAGS="$save_LDFLAGS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_sparc_ua_pcrel" >&5 -$as_echo "$libffi_cv_as_sparc_ua_pcrel" >&6; } - if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then - -$as_echo "#define HAVE_AS_SPARC_UA_PCREL 1" >>confdefs.h - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .register pseudo-op support" >&5 -$as_echo_n "checking assembler .register pseudo-op support... " >&6; } -if ${libffi_cv_as_register_pseudo_op+:} false; then : - $as_echo_n "(cached) " >&6 -else - - libffi_cv_as_register_pseudo_op=unknown - # Check if we have .register - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -asm (".register %g2, #scratch"); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - libffi_cv_as_register_pseudo_op=yes -else - libffi_cv_as_register_pseudo_op=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_register_pseudo_op" >&5 -$as_echo "$libffi_cv_as_register_pseudo_op" >&6; } - if test "x$libffi_cv_as_register_pseudo_op" = xyes; then - -$as_echo "#define HAVE_AS_REGISTER_PSEUDO_OP 1" >>confdefs.h - - fi -fi - -if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports pc related relocs" >&5 -$as_echo_n "checking assembler supports pc related relocs... " >&6; } -if ${libffi_cv_as_x86_pcrel+:} false; then : - $as_echo_n "(cached) " >&6 -else - - libffi_cv_as_x86_pcrel=no - echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s - if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then - libffi_cv_as_x86_pcrel=yes - fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_pcrel" >&5 -$as_echo "$libffi_cv_as_x86_pcrel" >&6; } - if test "x$libffi_cv_as_x86_pcrel" = xyes; then - -$as_echo "#define HAVE_AS_X86_PCREL 1" >>confdefs.h - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .ascii pseudo-op support" >&5 -$as_echo_n "checking assembler .ascii pseudo-op support... " >&6; } -if ${libffi_cv_as_ascii_pseudo_op+:} false; then : - $as_echo_n "(cached) " >&6 -else - - libffi_cv_as_ascii_pseudo_op=unknown - # Check if we have .ascii - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -asm (".ascii \\"string\\""); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - libffi_cv_as_ascii_pseudo_op=yes -else - libffi_cv_as_ascii_pseudo_op=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_ascii_pseudo_op" >&5 -$as_echo "$libffi_cv_as_ascii_pseudo_op" >&6; } - if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then - -$as_echo "#define HAVE_AS_ASCII_PSEUDO_OP 1" >>confdefs.h - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .string pseudo-op support" >&5 -$as_echo_n "checking assembler .string pseudo-op support... " >&6; } -if ${libffi_cv_as_string_pseudo_op+:} false; then : - $as_echo_n "(cached) " >&6 -else - - libffi_cv_as_string_pseudo_op=unknown - # Check if we have .string - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -asm (".string \\"string\\""); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - libffi_cv_as_string_pseudo_op=yes -else - libffi_cv_as_string_pseudo_op=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_string_pseudo_op" >&5 -$as_echo "$libffi_cv_as_string_pseudo_op" >&6; } - if test "x$libffi_cv_as_string_pseudo_op" = xyes; then - -$as_echo "#define HAVE_AS_STRING_PSEUDO_OP 1" >>confdefs.h - - fi -fi - -# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. -# Check whether --enable-pax_emutramp was given. -if test "${enable_pax_emutramp+set}" = set; then : - enableval=$enable_pax_emutramp; if test "$enable_pax_emutramp" = "yes"; then - -$as_echo "#define FFI_MMAP_EXEC_EMUTRAMP_PAX 1" >>confdefs.h - - fi -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5 -$as_echo_n "checking for _ prefix in compiled symbols... " >&6; } -if ${lt_cv_sys_symbol_underscore+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_sys_symbol_underscore=no - cat > conftest.$ac_ext <<_LT_EOF -void nm_test_func(){} -int main(){nm_test_func;return 0;} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Now try to grab the symbols. - ac_nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then - lt_cv_sys_symbol_underscore=yes - else - if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&5 - fi - fi - else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "configure: failed program was:" >&5 - cat conftest.c >&5 - fi - rm -rf conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_symbol_underscore" >&5 -$as_echo "$lt_cv_sys_symbol_underscore" >&6; } - sys_symbol_underscore=$lt_cv_sys_symbol_underscore - - -if test "x$sys_symbol_underscore" = xyes; then - -$as_echo "#define SYMBOL_UNDERSCORE 1" >>confdefs.h - -fi - -FFI_EXEC_TRAMPOLINE_TABLE=0 -case "$target" in - *arm*-apple-darwin*) - FFI_EXEC_TRAMPOLINE_TABLE=1 - -$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h - - ;; - *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*) - -$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h - - ;; -esac - if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then - FFI_EXEC_TRAMPOLINE_TABLE_TRUE= - FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#' -else - FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#' - FFI_EXEC_TRAMPOLINE_TABLE_FALSE= -fi - - - -if test x$TARGET = xX86_64; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking toolchain supports unwind section type" >&5 -$as_echo_n "checking toolchain supports unwind section type... " >&6; } -if ${libffi_cv_as_x86_64_unwind_section_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - - cat > conftest1.s << EOF -.text -.globl foo -foo: -jmp bar -.section .eh_frame,"a",@unwind -bar: -EOF - - cat > conftest2.c << EOF -extern void foo(); -int main(){foo();} -EOF - - libffi_cv_as_x86_64_unwind_section_type=no - # we ensure that we can compile _and_ link an assembly file containing an @unwind section - # since the compiler can support it and not the linker (ie old binutils) - if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \ - $CC conftest2.c conftest1.o > /dev/null 2>&1 ; then - libffi_cv_as_x86_64_unwind_section_type=yes - fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_64_unwind_section_type" >&5 -$as_echo "$libffi_cv_as_x86_64_unwind_section_type" >&6; } - if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then - -$as_echo "#define HAVE_AS_X86_64_UNWIND_SECTION_TYPE 1" >>confdefs.h - - fi -fi - -if test "x$GCC" = "xyes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether .eh_frame section should be read-only" >&5 -$as_echo_n "checking whether .eh_frame section should be read-only... " >&6; } -if ${libffi_cv_ro_eh_frame+:} false; then : - $as_echo_n "(cached) " >&6 -else - - libffi_cv_ro_eh_frame=no - echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c - if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then - objdump -h conftest.o > conftest.dump 2>&1 - libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1` - libffi_test_line=`expr $libffi_eh_frame_line + 1`p - sed -n $libffi_test_line conftest.dump > conftest.line - if grep READONLY conftest.line > /dev/null; then - libffi_cv_ro_eh_frame=yes - fi - fi - rm -f conftest.* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_ro_eh_frame" >&5 -$as_echo "$libffi_cv_ro_eh_frame" >&6; } - if test "x$libffi_cv_ro_eh_frame" = xyes; then - -$as_echo "#define HAVE_RO_EH_FRAME 1" >>confdefs.h - - -$as_echo "#define EH_FRAME_FLAGS \"a\"" >>confdefs.h - - else - -$as_echo "#define EH_FRAME_FLAGS \"aw\"" >>confdefs.h - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((visibility(\"hidden\")))" >&5 -$as_echo_n "checking for __attribute__((visibility(\"hidden\")))... " >&6; } -if ${libffi_cv_hidden_visibility_attribute+:} false; then : - $as_echo_n "(cached) " >&6 -else - - echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c - libffi_cv_hidden_visibility_attribute=no - if { ac_try='${CC-cc} -Werror -S conftest.c -o conftest.s 1>&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - if grep '\.hidden.*foo' conftest.s >/dev/null; then - libffi_cv_hidden_visibility_attribute=yes - fi - fi - rm -f conftest.* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_hidden_visibility_attribute" >&5 -$as_echo "$libffi_cv_hidden_visibility_attribute" >&6; } - if test $libffi_cv_hidden_visibility_attribute = yes; then - -$as_echo "#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1" >>confdefs.h - - fi -fi - - - - - - - - -# Check whether --enable-debug was given. -if test "${enable_debug+set}" = set; then : - enableval=$enable_debug; if test "$enable_debug" = "yes"; then - -$as_echo "#define FFI_DEBUG 1" >>confdefs.h - - fi -fi - - if test "$enable_debug" = "yes"; then - FFI_DEBUG_TRUE= - FFI_DEBUG_FALSE='#' -else - FFI_DEBUG_TRUE='#' - FFI_DEBUG_FALSE= -fi - - -# Check whether --enable-structs was given. -if test "${enable_structs+set}" = set; then : - enableval=$enable_structs; if test "$enable_structs" = "no"; then - -$as_echo "#define FFI_NO_STRUCTS 1" >>confdefs.h - - fi -fi - - if test "$enable_debug" = "yes"; then - FFI_DEBUG_TRUE= - FFI_DEBUG_FALSE='#' -else - FFI_DEBUG_TRUE='#' - FFI_DEBUG_FALSE= -fi - - -# Check whether --enable-raw-api was given. -if test "${enable_raw_api+set}" = set; then : - enableval=$enable_raw_api; if test "$enable_raw_api" = "no"; then - -$as_echo "#define FFI_NO_RAW_API 1" >>confdefs.h - - fi -fi - - -# Check whether --enable-purify-safety was given. -if test "${enable_purify_safety+set}" = set; then : - enableval=$enable_purify_safety; if test "$enable_purify_safety" = "yes"; then - -$as_echo "#define USING_PURIFY 1" >>confdefs.h - - fi -fi - - -# These variables are only ever used when we cross-build to X86_WIN32. -# And we only support this with GCC, so... -if test "x$GCC" = "xyes"; then - if test -n "$with_cross_host" && - test x"$with_cross_host" != x"no"; then - toolexecdir="${exec_prefix}"/'$(target_alias)' - toolexeclibdir="${toolexecdir}"/lib - else - toolexecdir="${libdir}"/gcc-lib/'$(target_alias)' - toolexeclibdir="${libdir}" - fi - multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` - case $multi_os_directory in - .) ;; # Avoid trailing /. - ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; - esac - -else - toolexeclibdir="${libdir}" -fi - - -ac_config_commands="$ac_config_commands include" - -ac_config_commands="$ac_config_commands src" - - -ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h" - - -ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc" - - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 -$as_echo_n "checking that generated files are newer than configure... " >&6; } - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 -$as_echo "done" >&6; } - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then - as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${TESTSUBDIR_TRUE}" && test -z "${TESTSUBDIR_FALSE}"; then - as_fn_error $? "conditional \"TESTSUBDIR\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MIPS_TRUE}" && test -z "${MIPS_FALSE}"; then - as_fn_error $? "conditional \"MIPS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${BFIN_TRUE}" && test -z "${BFIN_FALSE}"; then - as_fn_error $? "conditional \"BFIN\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${SPARC_TRUE}" && test -z "${SPARC_FALSE}"; then - as_fn_error $? "conditional \"SPARC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_TRUE}" && test -z "${X86_FALSE}"; then - as_fn_error $? "conditional \"X86\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_FREEBSD_TRUE}" && test -z "${X86_FREEBSD_FALSE}"; then - as_fn_error $? "conditional \"X86_FREEBSD\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_WIN32_TRUE}" && test -z "${X86_WIN32_FALSE}"; then - as_fn_error $? "conditional \"X86_WIN32\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_WIN64_TRUE}" && test -z "${X86_WIN64_FALSE}"; then - as_fn_error $? "conditional \"X86_WIN64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_DARWIN_TRUE}" && test -z "${X86_DARWIN_FALSE}"; then - as_fn_error $? "conditional \"X86_DARWIN\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_DARWIN32_TRUE}" && test -z "${X86_DARWIN32_FALSE}"; then - as_fn_error $? "conditional \"X86_DARWIN32\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_DARWIN64_TRUE}" && test -z "${X86_DARWIN64_FALSE}"; then - as_fn_error $? "conditional \"X86_DARWIN64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${ALPHA_TRUE}" && test -z "${ALPHA_FALSE}"; then - as_fn_error $? "conditional \"ALPHA\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${IA64_TRUE}" && test -z "${IA64_FALSE}"; then - as_fn_error $? "conditional \"IA64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${M32R_TRUE}" && test -z "${M32R_FALSE}"; then - as_fn_error $? "conditional \"M32R\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${M68K_TRUE}" && test -z "${M68K_FALSE}"; then - as_fn_error $? "conditional \"M68K\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${M88K_TRUE}" && test -z "${M88K_FALSE}"; then - as_fn_error $? "conditional \"M88K\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MICROBLAZE_TRUE}" && test -z "${MICROBLAZE_FALSE}"; then - as_fn_error $? "conditional \"MICROBLAZE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${METAG_TRUE}" && test -z "${METAG_FALSE}"; then - as_fn_error $? "conditional \"METAG\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MOXIE_TRUE}" && test -z "${MOXIE_FALSE}"; then - as_fn_error $? "conditional \"MOXIE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${NIOS2_TRUE}" && test -z "${NIOS2_FALSE}"; then - as_fn_error $? "conditional \"NIOS2\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${OR1K_TRUE}" && test -z "${OR1K_FALSE}"; then - as_fn_error $? "conditional \"OR1K\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${POWERPC_TRUE}" && test -z "${POWERPC_FALSE}"; then - as_fn_error $? "conditional \"POWERPC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${POWERPC_AIX_TRUE}" && test -z "${POWERPC_AIX_FALSE}"; then - as_fn_error $? "conditional \"POWERPC_AIX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${POWERPC_DARWIN_TRUE}" && test -z "${POWERPC_DARWIN_FALSE}"; then - as_fn_error $? "conditional \"POWERPC_DARWIN\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${POWERPC_FREEBSD_TRUE}" && test -z "${POWERPC_FREEBSD_FALSE}"; then - as_fn_error $? "conditional \"POWERPC_FREEBSD\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${AARCH64_TRUE}" && test -z "${AARCH64_FALSE}"; then - as_fn_error $? "conditional \"AARCH64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${ARC_TRUE}" && test -z "${ARC_FALSE}"; then - as_fn_error $? "conditional \"ARC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then - as_fn_error $? "conditional \"ARM\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${AVR32_TRUE}" && test -z "${AVR32_FALSE}"; then - as_fn_error $? "conditional \"AVR32\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then - as_fn_error $? "conditional \"LIBFFI_CRIS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${FRV_TRUE}" && test -z "${FRV_FALSE}"; then - as_fn_error $? "conditional \"FRV\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${S390_TRUE}" && test -z "${S390_FALSE}"; then - as_fn_error $? "conditional \"S390\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then - as_fn_error $? "conditional \"X86_64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${SH_TRUE}" && test -z "${SH_FALSE}"; then - as_fn_error $? "conditional \"SH\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${SH64_TRUE}" && test -z "${SH64_FALSE}"; then - as_fn_error $? "conditional \"SH64\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${PA_LINUX_TRUE}" && test -z "${PA_LINUX_FALSE}"; then - as_fn_error $? "conditional \"PA_LINUX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${PA_HPUX_TRUE}" && test -z "${PA_HPUX_FALSE}"; then - as_fn_error $? "conditional \"PA_HPUX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then - as_fn_error $? "conditional \"PA64_HPUX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${TILE_TRUE}" && test -z "${TILE_FALSE}"; then - as_fn_error $? "conditional \"TILE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${VAX_TRUE}" && test -z "${VAX_FALSE}"; then - as_fn_error $? "conditional \"VAX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${XTENSA_TRUE}" && test -z "${XTENSA_FALSE}"; then - as_fn_error $? "conditional \"XTENSA\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - -if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then - as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then - as_fn_error $? "conditional \"FFI_DEBUG\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then - as_fn_error $? "conditional \"FFI_DEBUG\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by libffi $as_me 3.2.1, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - -case $ac_config_headers in *" -"*) set x $ac_config_headers; shift; ac_config_headers=$*;; -esac - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" -config_headers="$ac_config_headers" -config_links="$ac_config_links" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Configuration links: -$config_links - -Configuration commands: -$config_commands - -Report bugs to ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -libffi config.status 3.2.1 -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -AWK='$AWK' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_HEADERS " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h) - # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' -Try \`$0 --help' for more information.";; - --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# -# INIT-COMMANDS -# -ax_enable_builddir_srcdir="$srcdir" # $srcdir -ax_enable_builddir_host="$HOST" # $HOST / $host -ax_enable_builddir_version="$VERSION" # $VERSION -ax_enable_builddir_package="$PACKAGE" # $PACKAGE -ax_enable_builddir_auxdir="$ax_enable_builddir_auxdir" # $AUX -ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED -ax_enable_builddir="$ax_enable_builddir" # $SUB - -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' -macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' -enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' -enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' -pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' -SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' -ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' -PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' -host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' -host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' -host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' -build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' -build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' -build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' -SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' -Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' -GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' -EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' -FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' -LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' -NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' -LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' -ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' -exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' -lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' -lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' -lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' -reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' -file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' -want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' -DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' -sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' -AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' -archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' -STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' -RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' -lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' -CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' -compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' -GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' -nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' -lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' -objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' -need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' -MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' -LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' -OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' -libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' -module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' -postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' -need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' -version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' -runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' -libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' -soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' -install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' -finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' -old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' -striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' -predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' -postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' -predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' -postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' -LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' -reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' -reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' -GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' -inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' -link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' -always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' -exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' -predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' -postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' -predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' -postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' - -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in SHELL \ -ECHO \ -PATH_SEPARATOR \ -SED \ -GREP \ -EGREP \ -FGREP \ -LD \ -NM \ -LN_S \ -lt_SP2NL \ -lt_NL2SP \ -reload_flag \ -OBJDUMP \ -deplibs_check_method \ -file_magic_cmd \ -file_magic_glob \ -want_nocaseglob \ -DLLTOOL \ -sharedlib_from_linklib_cmd \ -AR \ -AR_FLAGS \ -archiver_list_spec \ -STRIP \ -RANLIB \ -CC \ -CFLAGS \ -compiler \ -lt_cv_sys_global_symbol_pipe \ -lt_cv_sys_global_symbol_to_cdecl \ -lt_cv_sys_global_symbol_to_c_name_address \ -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -nm_file_list_spec \ -lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_pic \ -lt_prog_compiler_wl \ -lt_prog_compiler_static \ -lt_cv_prog_compiler_c_o \ -need_locks \ -MANIFEST_TOOL \ -DSYMUTIL \ -NMEDIT \ -LIPO \ -OTOOL \ -OTOOL64 \ -shrext_cmds \ -export_dynamic_flag_spec \ -whole_archive_flag_spec \ -compiler_needs_object \ -with_gnu_ld \ -allow_undefined_flag \ -no_undefined_flag \ -hardcode_libdir_flag_spec \ -hardcode_libdir_separator \ -exclude_expsyms \ -include_expsyms \ -file_list_spec \ -variables_saved_for_relink \ -libname_spec \ -library_names_spec \ -soname_spec \ -install_override_mode \ -finish_eval \ -old_striplib \ -striplib \ -compiler_lib_search_dirs \ -predep_objects \ -postdep_objects \ -predeps \ -postdeps \ -compiler_lib_search_path \ -LD_CXX \ -reload_flag_CXX \ -compiler_CXX \ -lt_prog_compiler_no_builtin_flag_CXX \ -lt_prog_compiler_pic_CXX \ -lt_prog_compiler_wl_CXX \ -lt_prog_compiler_static_CXX \ -lt_cv_prog_compiler_c_o_CXX \ -export_dynamic_flag_spec_CXX \ -whole_archive_flag_spec_CXX \ -compiler_needs_object_CXX \ -with_gnu_ld_CXX \ -allow_undefined_flag_CXX \ -no_undefined_flag_CXX \ -hardcode_libdir_flag_spec_CXX \ -hardcode_libdir_separator_CXX \ -exclude_expsyms_CXX \ -include_expsyms_CXX \ -file_list_spec_CXX \ -compiler_lib_search_dirs_CXX \ -predep_objects_CXX \ -postdep_objects_CXX \ -predeps_CXX \ -postdeps_CXX \ -compiler_lib_search_path_CXX; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in reload_cmds \ -old_postinstall_cmds \ -old_postuninstall_cmds \ -old_archive_cmds \ -extract_expsyms_cmds \ -old_archive_from_new_cmds \ -old_archive_from_expsyms_cmds \ -archive_cmds \ -archive_expsym_cmds \ -module_cmds \ -module_expsym_cmds \ -export_symbols_cmds \ -prelink_cmds \ -postlink_cmds \ -postinstall_cmds \ -postuninstall_cmds \ -finish_cmds \ -sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec \ -reload_cmds_CXX \ -old_archive_cmds_CXX \ -old_archive_from_new_cmds_CXX \ -old_archive_from_expsyms_cmds_CXX \ -archive_cmds_CXX \ -archive_expsym_cmds_CXX \ -module_cmds_CXX \ -module_expsym_cmds_CXX \ -export_symbols_cmds_CXX \ -prelink_cmds_CXX \ -postlink_cmds_CXX; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' - -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - - - PACKAGE='$PACKAGE' - VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' - RM='$RM' - ofile='$ofile' - - - - - -TARGETDIR="$TARGETDIR" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "fficonfig.h") CONFIG_HEADERS="$CONFIG_HEADERS fficonfig.h" ;; - "buildir") CONFIG_COMMANDS="$CONFIG_COMMANDS buildir" ;; - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "include") CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;; - "src") CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;; - "include/ffitarget.h") CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;; - "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "include/ffi.h") CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; - "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; - "libffi.pc") CONFIG_FILES="$CONFIG_FILES libffi.pc" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - -# Set up the scripts for CONFIG_HEADERS section. -# No need to generate them if there are no CONFIG_HEADERS. -# This happens for instance with `./config.status Makefile'. -if test -n "$CONFIG_HEADERS"; then -cat >"$ac_tmp/defines.awk" <<\_ACAWK || -BEGIN { -_ACEOF - -# Transform confdefs.h into an awk script `defines.awk', embedded as -# here-document in config.status, that substitutes the proper values into -# config.h.in to produce config.h. - -# Create a delimiter string that does not exist in confdefs.h, to ease -# handling of long lines. -ac_delim='%!_!# ' -for ac_last_try in false false :; do - ac_tt=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_tt"; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -# For the awk script, D is an array of macro values keyed by name, -# likewise P contains macro parameters if any. Preserve backslash -# newline sequences. - -ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* -sed -n ' -s/.\{148\}/&'"$ac_delim"'/g -t rset -:rset -s/^[ ]*#[ ]*define[ ][ ]*/ / -t def -d -:def -s/\\$// -t bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3"/p -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p -d -:bsnl -s/["\\]/\\&/g -s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ -D["\1"]=" \3\\\\\\n"\\/p -t cont -s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p -t cont -d -:cont -n -s/.\{148\}/&'"$ac_delim"'/g -t clear -:clear -s/\\$// -t bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/"/p -d -:bsnlc -s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p -b cont -' >$CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - for (key in D) D_is_set[key] = 1 - FS = "" -} -/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { - line = \$ 0 - split(line, arg, " ") - if (arg[1] == "#") { - defundef = arg[2] - mac1 = arg[3] - } else { - defundef = substr(arg[1], 2) - mac1 = arg[2] - } - split(mac1, mac2, "(") #) - macro = mac2[1] - prefix = substr(line, 1, index(line, defundef) - 1) - if (D_is_set[macro]) { - # Preserve the white space surrounding the "#". - print prefix "define", macro P[macro] D[macro] - next - } else { - # Replace #undef with comments. This is necessary, for example, - # in the case of _POSIX_SOURCE, which is predefined and required - # on some systems where configure will not decide to define it. - if (defundef == "undef") { - print "/*", prefix defundef, macro, "*/" - next - } - } -} -{ print } -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 -fi # test -n "$CONFIG_HEADERS" - - -eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :L $CONFIG_LINKS :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - :H) - # - # CONFIG_HEADER - # - if test x"$ac_file" != x-; then - { - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" - } >"$ac_tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} - else - rm -f "$ac_file" - mv "$ac_tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - fi - else - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 - fi -# Compute "$ac_file"'s index in $config_headers. -_am_arg="$ac_file" -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || -$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$_am_arg" : 'X\(//\)[^/]' \| \ - X"$_am_arg" : 'X\(//\)$' \| \ - X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$_am_arg" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'`/stamp-h$_am_stamp_count - ;; - :L) - # - # CONFIG_LINK - # - - if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then - : - else - # Prefer the file from the source tree if names are identical. - if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then - ac_source=$srcdir/$ac_source - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5 -$as_echo "$as_me: linking $ac_source to $ac_file" >&6;} - - if test ! -r "$ac_source"; then - as_fn_error $? "$ac_source: file not found" "$LINENO" 5 - fi - rm -f "$ac_file" - - # Try a relative symlink, then a hard link, then a copy. - case $ac_source in - [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;; - *) ac_rel_source=$ac_top_build_prefix$ac_source ;; - esac - ln -s "$ac_rel_source" "$ac_file" 2>/dev/null || - ln "$ac_source" "$ac_file" 2>/dev/null || - cp -p "$ac_source" "$ac_file" || - as_fn_error $? "cannot link or copy $ac_source to $ac_file" "$LINENO" 5 - fi - ;; - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "buildir":C) ac_top_srcdir="$ax_enable_builddir_srcdir" - if test ".$ax_enable_builddir" = ".." ; then - if test -f "$top_srcdir/Makefile" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: skipping top_srcdir/Makefile - left untouched" >&5 -$as_echo "$as_me: skipping top_srcdir/Makefile - left untouched" >&6;} - else - { $as_echo "$as_me:${as_lineno-$LINENO}: skipping top_srcdir/Makefile - not created" >&5 -$as_echo "$as_me: skipping top_srcdir/Makefile - not created" >&6;} - fi - else - if test -f "$ac_top_srcdir/Makefile" ; then - a=`grep "^VERSION " "$ac_top_srcdir/Makefile"` ; b=`grep "^VERSION " Makefile` - test "$a" != "$b" && rm "$ac_top_srcdir/Makefile" - fi - if test -f "$ac_top_srcdir/Makefile" ; then - echo "$ac_top_srcdir/Makefile : $ac_top_srcdir/Makefile.in" > $tmp/conftemp.mk - echo " @ echo 'REMOVED,,,' >\$@" >> $tmp/conftemp.mk - eval "${MAKE-make} -f $tmp/conftemp.mk 2>/dev/null >/dev/null" - if grep '^REMOVED,,,' "$ac_top_srcdir/Makefile" >/dev/null - then rm $ac_top_srcdir/Makefile ; fi - cp $tmp/conftemp.mk $ac_top_srcdir/makefiles.mk~ ## DEBUGGING - fi - if test ! -f "$ac_top_srcdir/Makefile" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: create top_srcdir/Makefile guessed from local Makefile" >&5 -$as_echo "$as_me: create top_srcdir/Makefile guessed from local Makefile" >&6;} - x='`' ; cat >$tmp/conftemp.sed <<_EOF -/^\$/n -x -/^\$/bS -x -/\\\\\$/{H;d;} -{H;s/.*//;x;} -bM -:S -x -/\\\\\$/{h;d;} -{h;s/.*//;x;} -:M -s/\\(\\n\\) /\\1 /g -/^ /d -/^[ ]*[\\#]/d -/^VPATH *=/d -s/^srcdir *=.*/srcdir = ./ -s/^top_srcdir *=.*/top_srcdir = ./ -/[:=]/!d -/^\\./d -/ = /b -/ .= /b -/:/!b -s/:.*/:/ -s/ / /g -s/ \\([a-z][a-z-]*[a-zA-Z0-9]\\)\\([ :]\\)/ \\1 \\1-all\\2/g -s/^\\([a-z][a-z-]*[a-zA-Z0-9]\\)\\([ :]\\)/\\1 \\1-all\\2/ -s/ / /g -/^all all-all[ :]/i\\ -all-configured : all-all -s/ [a-zA-Z0-9-]*-all [a-zA-Z0-9-]*-all-all//g -/-all-all/d -a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $ax_enable_builddir_auxdir/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; use=$x basename "\$\@" -all $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$n * \$\@"; if test "\$\$n" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^####.*|" Makefile |tail -1| sed -e 's/.*|//' $x ; fi \\\\\\ - ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ - ; test "\$\$use" = "\$\@" && BUILD=$x echo "\$\$BUILD" | tail -1 $x \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; (cd "\$\$i" && test ! -f configure && \$(MAKE) \$\$use) || exit; done -/dist-all *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $ax_enable_builddir_auxdir/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).tar.*" \\\\\\ - ; if test "\$\$found" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ - ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).tar.* \\\\\\ - ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done -/dist-[a-zA-Z0-9]*-all *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh ./config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).*" \\\\\\ - ; if test "\$\$found" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ - ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).* \\\\\\ - ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done -/distclean-all *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $ax_enable_builddir_auxdir/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile | sed -e 's/.*|//' $x \\\\\\ - ; use=$x basename "\$\@" -all $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$n * \$\@ (all local builds)" \\\\\\ - ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; echo "# rm -r \$\$i"; done ; echo "# (sleep 3)" ; sleep 3 \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; echo "\$\$i" | grep "^/" > /dev/null && continue \\\\\\ - ; echo "\$\$i" | grep "^../" > /dev/null && continue \\\\\\ - ; echo "rm -r \$\$i"; (rm -r "\$\$i") ; done ; rm Makefile -_EOF - cp "$tmp/conftemp.sed" "$ac_top_srcdir/makefile.sed~" ## DEBUGGING - $ax_enable_builddir_sed -f $tmp/conftemp.sed Makefile >$ac_top_srcdir/Makefile - if test -f "$ac_top_srcdir/Makefile.mk" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: extend top_srcdir/Makefile with top_srcdir/Makefile.mk" >&5 -$as_echo "$as_me: extend top_srcdir/Makefile with top_srcdir/Makefile.mk" >&6;} - cat $ac_top_srcdir/Makefile.mk >>$ac_top_srcdir/Makefile - fi ; xxxx="####" - echo "$xxxx CONFIGURATIONS FOR TOPLEVEL MAKEFILE: " >>$ac_top_srcdir/Makefile - # sanity check - if grep '^; echo "MAKE ' $ac_top_srcdir/Makefile >/dev/null ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: buggy sed found - it deletes tab in \"a\" text parts" >&5 -$as_echo "$as_me: buggy sed found - it deletes tab in \"a\" text parts" >&6;} - $ax_enable_builddir_sed -e '/^@ HOST=/s/^/ /' -e '/^; /s/^/ /' $ac_top_srcdir/Makefile \ - >$ac_top_srcdir/Makefile~ - (test -s $ac_top_srcdir/Makefile~ && mv $ac_top_srcdir/Makefile~ $ac_top_srcdir/Makefile) 2>/dev/null - fi - else - xxxx="\\#\\#\\#\\#" - # echo "/^$xxxx *$ax_enable_builddir_host /d" >$tmp/conftemp.sed - echo "s!^$xxxx [^|]* | *$ax_enable_builddir *\$!$xxxx ...... $ax_enable_builddir!" >$tmp/conftemp.sed - $ax_enable_builddir_sed -f "$tmp/conftemp.sed" "$ac_top_srcdir/Makefile" >$tmp/mkfile.tmp - cp "$tmp/conftemp.sed" "$ac_top_srcdir/makefiles.sed~" ## DEBUGGING - cp "$tmp/mkfile.tmp" "$ac_top_srcdir/makefiles.out~" ## DEBUGGING - if cmp -s "$ac_top_srcdir/Makefile" "$tmp/mkfile.tmp" 2>/dev/null ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: keeping top_srcdir/Makefile from earlier configure" >&5 -$as_echo "$as_me: keeping top_srcdir/Makefile from earlier configure" >&6;} - rm "$tmp/mkfile.tmp" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: reusing top_srcdir/Makefile from earlier configure" >&5 -$as_echo "$as_me: reusing top_srcdir/Makefile from earlier configure" >&6;} - mv "$tmp/mkfile.tmp" "$ac_top_srcdir/Makefile" - fi - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: build in $ax_enable_builddir (HOST=$ax_enable_builddir_host)" >&5 -$as_echo "$as_me: build in $ax_enable_builddir (HOST=$ax_enable_builddir_host)" >&6;} - xxxx="####" - echo "$xxxx" "$ax_enable_builddir_host" "|$ax_enable_builddir" >>$ac_top_srcdir/Makefile - fi - ;; - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} - ;; - "libtool":C) - - # See if we are running on zsh, and set the options which allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - - cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -# The names of the tagged configurations supported by this script. -available_tags="CXX " - -# ### BEGIN LIBTOOL CONFIG - -# Which release of libtool.m4 was used? -macro_version=$macro_version -macro_revision=$macro_revision - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# What type of objects to build. -pic_mode=$pic_mode - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that protects backslashes. -ECHO=$lt_ECHO - -# The PATH separator for the build system. -PATH_SEPARATOR=$lt_PATH_SEPARATOR - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="\$SED -e 1s/^X//" - -# A grep program that handles long lines. -GREP=$lt_GREP - -# An ERE matcher. -EGREP=$lt_EGREP - -# A literal string matcher. -FGREP=$lt_FGREP - -# A BSD- or MS-compatible name lister. -NM=$lt_NM - -# Whether we need soft or hard links. -LN_S=$lt_LN_S - -# What is the maximum length of a command? -max_cmd_len=$max_cmd_len - -# Object file suffix (normally "o"). -objext=$ac_objext - -# Executable file suffix (normally ""). -exeext=$exeext - -# whether the shell understands "unset". -lt_unset=$lt_unset - -# turn spaces into newlines. -SP2NL=$lt_lt_SP2NL - -# turn newlines into spaces. -NL2SP=$lt_lt_NL2SP - -# convert \$build file names to \$host format. -to_host_file_cmd=$lt_cv_to_host_file_cmd - -# convert \$build files to toolchain format. -to_tool_file_cmd=$lt_cv_to_tool_file_cmd - -# An object symbol dumper. -OBJDUMP=$lt_OBJDUMP - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method = "file_magic". -file_magic_cmd=$lt_file_magic_cmd - -# How to find potential files when deplibs_check_method = "file_magic". -file_magic_glob=$lt_file_magic_glob - -# Find potential files using nocaseglob when deplibs_check_method = "file_magic". -want_nocaseglob=$lt_want_nocaseglob - -# DLL creation program. -DLLTOOL=$lt_DLLTOOL - -# Command to associate shared and link libraries. -sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd - -# The archiver. -AR=$lt_AR - -# Flags to create an archive. -AR_FLAGS=$lt_AR_FLAGS - -# How to feed a file listing to the archiver. -archiver_list_spec=$lt_archiver_list_spec - -# A symbol stripping program. -STRIP=$lt_STRIP - -# Commands used to install an old-style archive. -RANLIB=$lt_RANLIB -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Whether to use a lock for old archive extraction. -lock_old_archive_extraction=$lock_old_archive_extraction - -# A C compiler. -LTCC=$lt_CC - -# LTCC compiler flags. -LTCFLAGS=$lt_CFLAGS - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration. -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair. -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# Transform the output of nm in a C name address pair when lib prefix is needed. -global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix - -# Specify filename containing input files for \$NM. -nm_file_list_spec=$lt_nm_file_list_spec - -# The root where to search for dependent libraries,and in which our libraries should be installed. -lt_sysroot=$lt_sysroot - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# Used to examine libraries when file_magic_cmd begins with "file". -MAGIC_CMD=$MAGIC_CMD - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Manifest tool. -MANIFEST_TOOL=$lt_MANIFEST_TOOL - -# Tool to manipulate archived DWARF debug symbol files on Mac OS X. -DSYMUTIL=$lt_DSYMUTIL - -# Tool to change global to local symbols on Mac OS X. -NMEDIT=$lt_NMEDIT - -# Tool to manipulate fat objects and archives on Mac OS X. -LIPO=$lt_LIPO - -# ldd/readelf like tool for Mach-O binaries on Mac OS X. -OTOOL=$lt_OTOOL - -# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. -OTOOL64=$lt_OTOOL64 - -# Old archive suffix (normally "a"). -libext=$libext - -# Shared library suffix (normally ".so"). -shrext_cmds=$lt_shrext_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at link time. -variables_saved_for_relink=$lt_variables_saved_for_relink - -# Do we need the "lib" prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Library versioning type. -version_type=$version_type - -# Shared library runtime path variable. -runpath_var=$runpath_var - -# Shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Permission mode override for installation of shared libraries. -install_override_mode=$lt_install_override_mode - -# Command to use after installation of a shared archive. -postinstall_cmds=$lt_postinstall_cmds - -# Command to use after uninstallation of a shared archive. -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# As "finish_cmds", except a single script fragment to be evaled but -# not shown. -finish_eval=$lt_finish_eval - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Compile-time system search path for libraries. -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - - -# The linker used to build libraries. -LD=$lt_LD - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds - -# A language specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU compiler? -with_gcc=$GCC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects -postdep_objects=$lt_postdep_objects -predeps=$lt_predeps -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - -# ### END LIBTOOL CONFIG - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - -ltmain="$ac_aux_dir/ltmain.sh" - - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - if test x"$xsi_shell" = xyes; then - sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ -func_dirname ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_basename ()$/,/^} # func_basename /c\ -func_basename ()\ -{\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ -func_dirname_and_basename ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ -func_stripname ()\ -{\ -\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ -\ # positional parameters, so assign one to ordinary parameter first.\ -\ func_stripname_result=${3}\ -\ func_stripname_result=${func_stripname_result#"${1}"}\ -\ func_stripname_result=${func_stripname_result%"${2}"}\ -} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ -func_split_long_opt ()\ -{\ -\ func_split_long_opt_name=${1%%=*}\ -\ func_split_long_opt_arg=${1#*=}\ -} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ -func_split_short_opt ()\ -{\ -\ func_split_short_opt_arg=${1#??}\ -\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ -} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ -func_lo2o ()\ -{\ -\ case ${1} in\ -\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ -\ *) func_lo2o_result=${1} ;;\ -\ esac\ -} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_xform ()$/,/^} # func_xform /c\ -func_xform ()\ -{\ - func_xform_result=${1%.*}.lo\ -} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_arith ()$/,/^} # func_arith /c\ -func_arith ()\ -{\ - func_arith_result=$(( $* ))\ -} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_len ()$/,/^} # func_len /c\ -func_len ()\ -{\ - func_len_result=${#1}\ -} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - -fi - -if test x"$lt_shell_append" = xyes; then - sed -e '/^func_append ()$/,/^} # func_append /c\ -func_append ()\ -{\ - eval "${1}+=\\${2}"\ -} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ -func_append_quoted ()\ -{\ -\ func_quote_for_eval "${2}"\ -\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ -} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 -$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} -fi - - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - - - cat <<_LT_EOF >> "$ofile" - -# ### BEGIN LIBTOOL TAG CONFIG: CXX - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# How to create reloadable object files. -reload_flag=$lt_reload_flag_CXX -reload_cmds=$lt_reload_cmds_CXX - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds_CXX - -# A language specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU compiler? -with_gcc=$GCC_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object_CXX - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld_CXX - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute_CXX - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath_CXX - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds_CXX - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds_CXX - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec_CXX - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects_CXX -postdep_objects=$lt_postdep_objects_CXX -predeps=$lt_predeps_CXX -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# ### END LIBTOOL TAG CONFIG: CXX -_LT_EOF - - ;; - "include":C) test -d include || mkdir include ;; - "src":C) -test -d src || mkdir src -test -d src/$TARGETDIR || mkdir src/$TARGETDIR - ;; - - esac -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - diff --git a/ruby/ext/fiddle/libffi-3.2.1/configure.ac b/ruby/ext/fiddle/libffi-3.2.1/configure.ac deleted file mode 100644 index a7bf5eefa..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/configure.ac +++ /dev/null @@ -1,625 +0,0 @@ -dnl Process this with autoconf to create configure - -AC_PREREQ(2.68) - -AC_INIT([libffi], [3.2.1], [http://github.com/atgreen/libffi/issues]) -AC_CONFIG_HEADERS([fficonfig.h]) - -AC_CANONICAL_SYSTEM -target_alias=${target_alias-$host_alias} - -case "${host}" in - frv*-elf) - LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/ - ;; -esac - -AX_ENABLE_BUILDDIR - -AM_INIT_AUTOMAKE - -# The same as in boehm-gc and libstdc++. Have to borrow it from there. -# We must force CC to /not/ be precious variables; otherwise -# the wrong, non-multilib-adjusted value will be used in multilibs. -# As a side effect, we have to subst CFLAGS ourselves. -# Also save and restore CFLAGS, since AC_PROG_CC will come up with -# defaults of its own if none are provided. - -m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS]) -m4_define([_AC_ARG_VAR_PRECIOUS],[]) -save_CFLAGS=$CFLAGS -AC_PROG_CC -AC_PROG_CXX -CFLAGS=$save_CFLAGS -m4_undefine([_AC_ARG_VAR_PRECIOUS]) -m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS]) - -AC_SUBST(CFLAGS) - -AM_PROG_AS -AM_PROG_CC_C_O -AC_PROG_LIBTOOL -AC_CONFIG_MACRO_DIR([m4]) - -# Test for 64-bit build. -AC_CHECK_SIZEOF([size_t]) - -AX_COMPILER_VENDOR -AX_CC_MAXOPT -# The AX_CFLAGS_WARN_ALL macro doesn't currently work for sunpro -# compiler. -if test "$ax_cv_c_compiler_vendor" != "sun"; then - AX_CFLAGS_WARN_ALL -fi - -if test "x$GCC" = "xyes"; then - CFLAGS="$CFLAGS -fexceptions" -fi - -cat > local.exp < conftest.s - if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then - libffi_cv_as_x86_pcrel=yes - fi - ]) - if test "x$libffi_cv_as_x86_pcrel" = xyes; then - AC_DEFINE(HAVE_AS_X86_PCREL, 1, - [Define if your assembler supports PC relative relocs.]) - fi - - AC_CACHE_CHECK([assembler .ascii pseudo-op support], - libffi_cv_as_ascii_pseudo_op, [ - libffi_cv_as_ascii_pseudo_op=unknown - # Check if we have .ascii - AC_TRY_COMPILE(,[asm (".ascii \\"string\\"");], - [libffi_cv_as_ascii_pseudo_op=yes], - [libffi_cv_as_ascii_pseudo_op=no]) - ]) - if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1, - [Define if your assembler supports .ascii.]) - fi - - AC_CACHE_CHECK([assembler .string pseudo-op support], - libffi_cv_as_string_pseudo_op, [ - libffi_cv_as_string_pseudo_op=unknown - # Check if we have .string - AC_TRY_COMPILE(,[asm (".string \\"string\\"");], - [libffi_cv_as_string_pseudo_op=yes], - [libffi_cv_as_string_pseudo_op=no]) - ]) - if test "x$libffi_cv_as_string_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1, - [Define if your assembler supports .string.]) - fi -fi - -# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. -AC_ARG_ENABLE(pax_emutramp, - [ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC], - if test "$enable_pax_emutramp" = "yes"; then - AC_DEFINE(FFI_MMAP_EXEC_EMUTRAMP_PAX, 1, - [Define this if you want to enable pax emulated trampolines]) - fi) - -LT_SYS_SYMBOL_USCORE -if test "x$sys_symbol_underscore" = xyes; then - AC_DEFINE(SYMBOL_UNDERSCORE, 1, [Define if symbols are underscored.]) -fi - -FFI_EXEC_TRAMPOLINE_TABLE=0 -case "$target" in - *arm*-apple-darwin*) - FFI_EXEC_TRAMPOLINE_TABLE=1 - AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1, - [Cannot use PROT_EXEC on this target, so, we revert to - alternative means]) - ;; - *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*) - AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1, - [Cannot use malloc on this target, so, we revert to - alternative means]) - ;; -esac -AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1) -AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE) - -if test x$TARGET = xX86_64; then - AC_CACHE_CHECK([toolchain supports unwind section type], - libffi_cv_as_x86_64_unwind_section_type, [ - cat > conftest1.s << EOF -.text -.globl foo -foo: -jmp bar -.section .eh_frame,"a",@unwind -bar: -EOF - - cat > conftest2.c << EOF -extern void foo(); -int main(){foo();} -EOF - - libffi_cv_as_x86_64_unwind_section_type=no - # we ensure that we can compile _and_ link an assembly file containing an @unwind section - # since the compiler can support it and not the linker (ie old binutils) - if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \ - $CC conftest2.c conftest1.o > /dev/null 2>&1 ; then - libffi_cv_as_x86_64_unwind_section_type=yes - fi - ]) - if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then - AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1, - [Define if your assembler supports unwind section type.]) - fi -fi - -if test "x$GCC" = "xyes"; then - AC_CACHE_CHECK([whether .eh_frame section should be read-only], - libffi_cv_ro_eh_frame, [ - libffi_cv_ro_eh_frame=no - echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c - if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then - objdump -h conftest.o > conftest.dump 2>&1 - libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1` - libffi_test_line=`expr $libffi_eh_frame_line + 1`p - sed -n $libffi_test_line conftest.dump > conftest.line - if grep READONLY conftest.line > /dev/null; then - libffi_cv_ro_eh_frame=yes - fi - fi - rm -f conftest.* - ]) - if test "x$libffi_cv_ro_eh_frame" = xyes; then - AC_DEFINE(HAVE_RO_EH_FRAME, 1, - [Define if .eh_frame sections should be read-only.]) - AC_DEFINE(EH_FRAME_FLAGS, "a", - [Define to the flags needed for the .section .eh_frame directive. ]) - else - AC_DEFINE(EH_FRAME_FLAGS, "aw", - [Define to the flags needed for the .section .eh_frame directive. ]) - fi - - AC_CACHE_CHECK([for __attribute__((visibility("hidden")))], - libffi_cv_hidden_visibility_attribute, [ - echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c - libffi_cv_hidden_visibility_attribute=no - if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then - if grep '\.hidden.*foo' conftest.s >/dev/null; then - libffi_cv_hidden_visibility_attribute=yes - fi - fi - rm -f conftest.* - ]) - if test $libffi_cv_hidden_visibility_attribute = yes; then - AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1, - [Define if __attribute__((visibility("hidden"))) is supported.]) - fi -fi - -AH_BOTTOM([ -#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) .hidden name -#else -#define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) -#endif -#else -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) -#else -#define FFI_HIDDEN -#endif -#endif -]) - -AC_SUBST(TARGET) -AC_SUBST(TARGETDIR) - -AC_SUBST(SHELL) - -AC_ARG_ENABLE(debug, -[ --enable-debug debugging mode], - if test "$enable_debug" = "yes"; then - AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.]) - fi) -AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes") - -AC_ARG_ENABLE(structs, -[ --disable-structs omit code for struct support], - if test "$enable_structs" = "no"; then - AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this if you do not want support for aggregate types.]) - fi) -AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes") - -AC_ARG_ENABLE(raw-api, -[ --disable-raw-api make the raw api unavailable], - if test "$enable_raw_api" = "no"; then - AC_DEFINE(FFI_NO_RAW_API, 1, [Define this if you do not want support for the raw API.]) - fi) - -AC_ARG_ENABLE(purify-safety, -[ --enable-purify-safety purify-safe mode], - if test "$enable_purify_safety" = "yes"; then - AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.]) - fi) - -# These variables are only ever used when we cross-build to X86_WIN32. -# And we only support this with GCC, so... -if test "x$GCC" = "xyes"; then - if test -n "$with_cross_host" && - test x"$with_cross_host" != x"no"; then - toolexecdir="${exec_prefix}"/'$(target_alias)' - toolexeclibdir="${toolexecdir}"/lib - else - toolexecdir="${libdir}"/gcc-lib/'$(target_alias)' - toolexeclibdir="${libdir}" - fi - multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` - case $multi_os_directory in - .) ;; # Avoid trailing /. - ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; - esac - AC_SUBST(toolexecdir) -else - toolexeclibdir="${libdir}" -fi -AC_SUBST(toolexeclibdir) - -AC_CONFIG_COMMANDS(include, [test -d include || mkdir include]) -AC_CONFIG_COMMANDS(src, [ -test -d src || mkdir src -test -d src/$TARGETDIR || mkdir src/$TARGETDIR -], [TARGETDIR="$TARGETDIR"]) - -AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) - -AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc) - -AC_OUTPUT diff --git a/ruby/ext/fiddle/libffi-3.2.1/depcomp b/ruby/ext/fiddle/libffi-3.2.1/depcomp deleted file mode 100755 index 4ebd5b3a2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/depcomp +++ /dev/null @@ -1,791 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2013-05-30.07; # UTC - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by 'PROGRAMS ARGS'. - object Object file output by 'PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputting dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -# Get the directory component of the given path, and save it in the -# global variables '$dir'. Note that this directory component will -# be either empty or ending with a '/' character. This is deliberate. -set_dir_from () -{ - case $1 in - */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; - *) dir=;; - esac -} - -# Get the suffix-stripped basename of the given path, and save it the -# global variable '$base'. -set_base_from () -{ - base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` -} - -# If no dependency file was actually created by the compiler invocation, -# we still have to create a dummy depfile, to avoid errors with the -# Makefile "include basename.Plo" scheme. -make_dummy_depfile () -{ - echo "#dummy" > "$depfile" -} - -# Factor out some common post-processing of the generated depfile. -# Requires the auxiliary global variable '$tmpdepfile' to be set. -aix_post_process_depfile () -{ - # If the compiler actually managed to produce a dependency file, - # post-process it. - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependency.h'. - # Do two passes, one to just change these to - # $object: dependency.h - # and one to simply output - # dependency.h: - # which is needed to avoid the deleted-header problem. - { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" - sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" - } > "$depfile" - rm -f "$tmpdepfile" - else - make_dummy_depfile - fi -} - -# A tabulation character. -tab=' ' -# A newline character. -nl=' -' -# Character ranges might be problematic outside the C locale. -# These definitions help. -upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ -lower=abcdefghijklmnopqrstuvwxyz -digits=0123456789 -alpha=${upper}${lower} - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Avoid interferences from the environment. -gccflag= dashmflag= - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp -fi - -if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 -fi - -if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. - gccflag=-qmakedep=gcc,-MF - depmode=gcc -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. -## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. -## (see the conditional assignment to $gccflag above). -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). Also, it might not be -## supported by the other compilers which use the 'gcc' depmode. -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The second -e expression handles DOS-style file names with drive - # letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the "deleted header file" problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. -## Some versions of gcc put a space before the ':'. On the theory -## that the space means something, we add a space to the output as -## well. hp depmode also adds that space, but also prefixes the VPATH -## to the object. Take care to not repeat it in the output. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like '#:fec' to the end of the - # dependency line. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ - | tr "$nl" ' ' >> "$depfile" - echo >> "$depfile" - # The second pass generates a dummy entry for each header file. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" - ;; - -xlc) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts '$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - aix_post_process_depfile - ;; - -tcc) - # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 - # FIXME: That version still under development at the moment of writing. - # Make that this statement remains true also for stable, released - # versions. - # It will wrap lines (doesn't matter whether long or short) with a - # trailing '\', as in: - # - # foo.o : \ - # foo.c \ - # foo.h \ - # - # It will put a trailing '\' even on the last line, and will use leading - # spaces rather than leading tabs (at least since its commit 0394caf7 - # "Emit spaces for -MD"). - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. - # We have to change lines of the first kind to '$object: \'. - sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" - # And for each line of the second kind, we have to emit a 'dep.h:' - # dummy dependency, to avoid the deleted-header problem. - sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -## The order of this option in the case statement is important, since the -## shell code in configure will try each of these formats in the order -## listed in this file. A plain '-MD' option would be understood by many -## compilers, so we must ensure this comes after the gcc and icc options. -pgcc) - # Portland's C compiler understands '-MD'. - # Will always output deps to 'file.d' where file is the root name of the - # source file under compilation, even if file resides in a subdirectory. - # The object file name does not affect the name of the '.d' file. - # pgcc 10.2 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\' : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - set_dir_from "$object" - # Use the source, not the object, to determine the base name, since - # that's sadly what pgcc will do too. - set_base_from "$source" - tmpdepfile=$base.d - - # For projects that build the same source file twice into different object - # files, the pgcc approach of using the *source* file root name can cause - # problems in parallel builds. Use a locking strategy to avoid stomping on - # the same $tmpdepfile. - lockdir=$base.d-lock - trap " - echo '$0: caught signal, cleaning up...' >&2 - rmdir '$lockdir' - exit 1 - " 1 2 13 15 - numtries=100 - i=$numtries - while test $i -gt 0; do - # mkdir is a portable test-and-set. - if mkdir "$lockdir" 2>/dev/null; then - # This process acquired the lock. - "$@" -MD - stat=$? - # Release the lock. - rmdir "$lockdir" - break - else - # If the lock is being held by a different process, wait - # until the winning process is done or we timeout. - while test -d "$lockdir" && test $i -gt 0; do - sleep 1 - i=`expr $i - 1` - done - fi - i=`expr $i - 1` - done - trap - 1 2 13 15 - if test $i -le 0; then - echo "$0: failed to acquire lock after $numtries attempts" >&2 - echo "$0: check lockdir '$lockdir'" >&2 - exit 1 - fi - - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" - # Add 'dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - set_dir_from "$object" - set_base_from "$object" - - if test "$libtool" = yes; then - # Libtool generates 2 separate objects for the 2 libraries. These - # two compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir$base.o.d # libtool 1.5 - tmpdepfile2=$dir.libs/$base.o.d # Likewise. - tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - # Same post-processing that is required for AIX mode. - aix_post_process_depfile - ;; - -msvc7) - if test "$libtool" = yes; then - showIncludes=-Wc,-showIncludes - else - showIncludes=-showIncludes - fi - "$@" $showIncludes > "$tmpdepfile" - stat=$? - grep -v '^Note: including file: ' "$tmpdepfile" - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The first sed program below extracts the file names and escapes - # backslashes for cygpath. The second sed program outputs the file - # name when reading, but also accumulates all include files in the - # hold buffer in order to output them again at the end. This only - # works with sed implementations that can handle large buffers. - sed < "$tmpdepfile" -n ' -/^Note: including file: *\(.*\)/ { - s//\1/ - s/\\/\\\\/g - p -}' | $cygpath_u | sort -u | sed -n ' -s/ /\\ /g -s/\(.*\)/'"$tab"'\1 \\/p -s/.\(.*\) \\/\1:/ -H -$ { - s/.*/'"$tab"'/ - G - p -}' >> "$depfile" - echo >> "$depfile" # make sure the fragment doesn't end with a backslash - rm -f "$tmpdepfile" - ;; - -msvc7msys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for ':' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. - "$@" $dashmflag | - sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this sed invocation - # correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - # makedepend may prepend the VPATH from the source file name to the object. - # No need to regex-escape $object, excess matching of '.' is harmless. - sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process the last invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed '1,2d' "$tmpdepfile" \ - | tr ' ' "$nl" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E \ - | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - | sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" - echo "$tab" >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.info b/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.info deleted file mode 100644 index c4d0f0cfb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.info +++ /dev/null @@ -1,765 +0,0 @@ -This is libffi.info, produced by makeinfo version 5.1 from libffi.texi. - -This manual is for Libffi, a portable foreign-function interface -library. - - Copyright (C) 2008, 2010, 2011 Red Hat, Inc. - - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. A copy of the license is included - in the section entitled "GNU General Public License". - -INFO-DIR-SECTION Development -START-INFO-DIR-ENTRY -* libffi: (libffi). Portable foreign-function interface library. -END-INFO-DIR-ENTRY - - -File: libffi.info, Node: Top, Next: Introduction, Up: (dir) - -libffi -****** - -This manual is for Libffi, a portable foreign-function interface -library. - - Copyright (C) 2008, 2010, 2011 Red Hat, Inc. - - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. A copy of the license is included - in the section entitled "GNU General Public License". - -* Menu: - -* Introduction:: What is libffi? -* Using libffi:: How to use libffi. -* Missing Features:: Things libffi can't do. -* Index:: Index. - - -File: libffi.info, Node: Introduction, Next: Using libffi, Prev: Top, Up: Top - -1 What is libffi? -***************** - -Compilers for high level languages generate code that follow certain -conventions. These conventions are necessary, in part, for separate -compilation to work. One such convention is the "calling convention". -The calling convention is a set of assumptions made by the compiler -about where function arguments will be found on entry to a function. A -calling convention also specifies where the return value for a function -is found. The calling convention is also sometimes called the "ABI" or -"Application Binary Interface". - - Some programs may not know at the time of compilation what arguments -are to be passed to a function. For instance, an interpreter may be -told at run-time about the number and types of arguments used to call a -given function. 'Libffi' can be used in such programs to provide a -bridge from the interpreter program to compiled code. - - The 'libffi' library provides a portable, high level programming -interface to various calling conventions. This allows a programmer to -call any function specified by a call interface description at run time. - - FFI stands for Foreign Function Interface. A foreign function -interface is the popular name for the interface that allows code written -in one language to call code written in another language. The 'libffi' -library really only provides the lowest, machine dependent layer of a -fully featured foreign function interface. A layer must exist above -'libffi' that handles type conversions for values passed between the two -languages. - - -File: libffi.info, Node: Using libffi, Next: Missing Features, Prev: Introduction, Up: Top - -2 Using libffi -************** - -* Menu: - -* The Basics:: The basic libffi API. -* Simple Example:: A simple example. -* Types:: libffi type descriptions. -* Multiple ABIs:: Different passing styles on one platform. -* The Closure API:: Writing a generic function. -* Closure Example:: A closure example. - - -File: libffi.info, Node: The Basics, Next: Simple Example, Up: Using libffi - -2.1 The Basics -============== - -'Libffi' assumes that you have a pointer to the function you wish to -call and that you know the number and types of arguments to pass it, as -well as the return type of the function. - - The first thing you must do is create an 'ffi_cif' object that -matches the signature of the function you wish to call. This is a -separate step because it is common to make multiple calls using a single -'ffi_cif'. The "cif" in 'ffi_cif' stands for Call InterFace. To -prepare a call interface object, use the function 'ffi_prep_cif'. - - -- Function: ffi_status ffi_prep_cif (ffi_cif *CIF, ffi_abi ABI, - unsigned int NARGS, ffi_type *RTYPE, ffi_type **ARGTYPES) - This initializes CIF according to the given parameters. - - ABI is the ABI to use; normally 'FFI_DEFAULT_ABI' is what you want. - *note Multiple ABIs:: for more information. - - NARGS is the number of arguments that this function accepts. - - RTYPE is a pointer to an 'ffi_type' structure that describes the - return type of the function. *Note Types::. - - ARGTYPES is a vector of 'ffi_type' pointers. ARGTYPES must have - NARGS elements. If NARGS is 0, this argument is ignored. - - 'ffi_prep_cif' returns a 'libffi' status code, of type - 'ffi_status'. This will be either 'FFI_OK' if everything worked - properly; 'FFI_BAD_TYPEDEF' if one of the 'ffi_type' objects is - incorrect; or 'FFI_BAD_ABI' if the ABI parameter is invalid. - - If the function being called is variadic (varargs) then -'ffi_prep_cif_var' must be used instead of 'ffi_prep_cif'. - - -- Function: ffi_status ffi_prep_cif_var (ffi_cif *CIF, ffi_abi varabi, - unsigned int NFIXEDARGS, unsigned int varntotalargs, ffi_type - *RTYPE, ffi_type **ARGTYPES) - This initializes CIF according to the given parameters for a call - to a variadic function. In general it's operation is the same as - for 'ffi_prep_cif' except that: - - NFIXEDARGS is the number of fixed arguments, prior to any variadic - arguments. It must be greater than zero. - - NTOTALARGS the total number of arguments, including variadic and - fixed arguments. - - Note that, different cif's must be prepped for calls to the same - function when different numbers of arguments are passed. - - Also note that a call to 'ffi_prep_cif_var' with - NFIXEDARGS=NOTOTALARGS is NOT equivalent to a call to - 'ffi_prep_cif'. - - To call a function using an initialized 'ffi_cif', use the 'ffi_call' -function: - - -- Function: void ffi_call (ffi_cif *CIF, void *FN, void *RVALUE, void - **AVALUES) - This calls the function FN according to the description given in - CIF. CIF must have already been prepared using 'ffi_prep_cif'. - - RVALUE is a pointer to a chunk of memory that will hold the result - of the function call. This must be large enough to hold the - result, no smaller than the system register size (generally 32 or - 64 bits), and must be suitably aligned; it is the caller's - responsibility to ensure this. If CIF declares that the function - returns 'void' (using 'ffi_type_void'), then RVALUE is ignored. - - AVALUES is a vector of 'void *' pointers that point to the memory - locations holding the argument values for a call. If CIF declares - that the function has no arguments (i.e., NARGS was 0), then - AVALUES is ignored. Note that argument values may be modified by - the callee (for instance, structs passed by value); the burden of - copying pass-by-value arguments is placed on the caller. - - -File: libffi.info, Node: Simple Example, Next: Types, Prev: The Basics, Up: Using libffi - -2.2 Simple Example -================== - -Here is a trivial example that calls 'puts' a few times. - - #include - #include - - int main() - { - ffi_cif cif; - ffi_type *args[1]; - void *values[1]; - char *s; - ffi_arg rc; - - /* Initialize the argument info vectors */ - args[0] = &ffi_type_pointer; - values[0] = &s; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint, args) == FFI_OK) - { - s = "Hello World!"; - ffi_call(&cif, puts, &rc, values); - /* rc now holds the result of the call to puts */ - - /* values holds a pointer to the function's arg, so to - call puts() again all we need to do is change the - value of s */ - s = "This is cool!"; - ffi_call(&cif, puts, &rc, values); - } - - return 0; - } - - -File: libffi.info, Node: Types, Next: Multiple ABIs, Prev: Simple Example, Up: Using libffi - -2.3 Types -========= - -* Menu: - -* Primitive Types:: Built-in types. -* Structures:: Structure types. -* Type Example:: Structure type example. -* Complex:: Complex types. -* Complex Type Example:: Complex type example. - - -File: libffi.info, Node: Primitive Types, Next: Structures, Up: Types - -2.3.1 Primitive Types ---------------------- - -'Libffi' provides a number of built-in type descriptors that can be used -to describe argument and return types: - -'ffi_type_void' - The type 'void'. This cannot be used for argument types, only for - return values. - -'ffi_type_uint8' - An unsigned, 8-bit integer type. - -'ffi_type_sint8' - A signed, 8-bit integer type. - -'ffi_type_uint16' - An unsigned, 16-bit integer type. - -'ffi_type_sint16' - A signed, 16-bit integer type. - -'ffi_type_uint32' - An unsigned, 32-bit integer type. - -'ffi_type_sint32' - A signed, 32-bit integer type. - -'ffi_type_uint64' - An unsigned, 64-bit integer type. - -'ffi_type_sint64' - A signed, 64-bit integer type. - -'ffi_type_float' - The C 'float' type. - -'ffi_type_double' - The C 'double' type. - -'ffi_type_uchar' - The C 'unsigned char' type. - -'ffi_type_schar' - The C 'signed char' type. (Note that there is not an exact - equivalent to the C 'char' type in 'libffi'; ordinarily you should - either use 'ffi_type_schar' or 'ffi_type_uchar' depending on - whether 'char' is signed.) - -'ffi_type_ushort' - The C 'unsigned short' type. - -'ffi_type_sshort' - The C 'short' type. - -'ffi_type_uint' - The C 'unsigned int' type. - -'ffi_type_sint' - The C 'int' type. - -'ffi_type_ulong' - The C 'unsigned long' type. - -'ffi_type_slong' - The C 'long' type. - -'ffi_type_longdouble' - On platforms that have a C 'long double' type, this is defined. On - other platforms, it is not. - -'ffi_type_pointer' - A generic 'void *' pointer. You should use this for all pointers, - regardless of their real type. - -'ffi_type_complex_float' - The C '_Complex float' type. - -'ffi_type_complex_double' - The C '_Complex double' type. - -'ffi_type_complex_longdouble' - The C '_Complex long double' type. On platforms that have a C - 'long double' type, this is defined. On other platforms, it is - not. - - Each of these is of type 'ffi_type', so you must take the address -when passing to 'ffi_prep_cif'. - - -File: libffi.info, Node: Structures, Next: Type Example, Prev: Primitive Types, Up: Types - -2.3.2 Structures ----------------- - -Although 'libffi' has no special support for unions or bit-fields, it is -perfectly happy passing structures back and forth. You must first -describe the structure to 'libffi' by creating a new 'ffi_type' object -for it. - - -- Data type: ffi_type - The 'ffi_type' has the following members: - 'size_t size' - This is set by 'libffi'; you should initialize it to zero. - - 'unsigned short alignment' - This is set by 'libffi'; you should initialize it to zero. - - 'unsigned short type' - For a structure, this should be set to 'FFI_TYPE_STRUCT'. - - 'ffi_type **elements' - This is a 'NULL'-terminated array of pointers to 'ffi_type' - objects. There is one element per field of the struct. - - -File: libffi.info, Node: Type Example, Next: Complex, Prev: Structures, Up: Types - -2.3.3 Type Example ------------------- - -The following example initializes a 'ffi_type' object representing the -'tm' struct from Linux's 'time.h'. - - Here is how the struct is defined: - - struct tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - /* Those are for future use. */ - long int __tm_gmtoff__; - __const char *__tm_zone__; - }; - - Here is the corresponding code to describe this struct to 'libffi': - - { - ffi_type tm_type; - ffi_type *tm_type_elements[12]; - int i; - - tm_type.size = tm_type.alignment = 0; - tm_type.type = FFI_TYPE_STRUCT; - tm_type.elements = &tm_type_elements; - - for (i = 0; i < 9; i++) - tm_type_elements[i] = &ffi_type_sint; - - tm_type_elements[9] = &ffi_type_slong; - tm_type_elements[10] = &ffi_type_pointer; - tm_type_elements[11] = NULL; - - /* tm_type can now be used to represent tm argument types and - return types for ffi_prep_cif() */ - } - - -File: libffi.info, Node: Complex, Next: Complex Type Example, Prev: Type Example, Up: Types - -2.3.4 Complex Types -------------------- - -'libffi' supports the complex types defined by the C99 standard -('_Complex float', '_Complex double' and '_Complex long double' with the -built-in type descriptors 'ffi_type_complex_float', -'ffi_type_complex_double' and 'ffi_type_complex_longdouble'. - - Custom complex types like '_Complex int' can also be used. An -'ffi_type' object has to be defined to describe the complex type to -'libffi'. - - -- Data type: ffi_type - 'size_t size' - This must be manually set to the size of the complex type. - - 'unsigned short alignment' - This must be manually set to the alignment of the complex - type. - - 'unsigned short type' - For a complex type, this must be set to 'FFI_TYPE_COMPLEX'. - - 'ffi_type **elements' - - This is a 'NULL'-terminated array of pointers to 'ffi_type' - objects. The first element is set to the 'ffi_type' of the - complex's base type. The second element must be set to - 'NULL'. - - The section *note Complex Type Example:: shows a way to determine the -'size' and 'alignment' members in a platform independent way. - - For platforms that have no complex support in 'libffi' yet, the -functions 'ffi_prep_cif' and 'ffi_prep_args' abort the program if they -encounter a complex type. - - -File: libffi.info, Node: Complex Type Example, Prev: Complex, Up: Types - -2.3.5 Complex Type Example --------------------------- - -This example demonstrates how to use complex types: - - #include - #include - #include - - void complex_fn(_Complex float cf, - _Complex double cd, - _Complex long double cld) - { - printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n", - (float)creal (cf), (float)cimag (cf), - (float)creal (cd), (float)cimag (cd), - (float)creal (cld), (float)cimag (cld)); - } - - int main() - { - ffi_cif cif; - ffi_type *args[3]; - void *values[3]; - _Complex float cf; - _Complex double cd; - _Complex long double cld; - - /* Initialize the argument info vectors */ - args[0] = &ffi_type_complex_float; - args[1] = &ffi_type_complex_double; - args[2] = &ffi_type_complex_longdouble; - values[0] = &cf; - values[1] = &cd; - values[2] = &cld; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_void, args) == FFI_OK) - { - cf = 1.0 + 20.0 * I; - cd = 300.0 + 4000.0 * I; - cld = 50000.0 + 600000.0 * I; - /* Call the function */ - ffi_call(&cif, (void (*)(void))complex_fn, 0, values); - } - - return 0; - } - - This is an example for defining a custom complex type descriptor for -compilers that support them: - - /* - * This macro can be used to define new complex type descriptors - * in a platform independent way. - * - * name: Name of the new descriptor is ffi_type_complex_. - * type: The C base type of the complex type. - */ - #define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \ - static ffi_type *ffi_elements_complex_##name [2] = { \ - (ffi_type *)(&ffitype), NULL \ - }; \ - struct struct_align_complex_##name { \ - char c; \ - _Complex type x; \ - }; \ - ffi_type ffi_type_complex_##name = { \ - sizeof(_Complex type), \ - offsetof(struct struct_align_complex_##name, x), \ - FFI_TYPE_COMPLEX, \ - (ffi_type **)ffi_elements_complex_##name \ - } - - /* Define new complex type descriptors using the macro: */ - /* ffi_type_complex_sint */ - FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint); - /* ffi_type_complex_uchar */ - FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8); - - The new type descriptors can then be used like one of the built-in -type descriptors in the previous example. - - -File: libffi.info, Node: Multiple ABIs, Next: The Closure API, Prev: Types, Up: Using libffi - -2.4 Multiple ABIs -================= - -A given platform may provide multiple different ABIs at once. For -instance, the x86 platform has both 'stdcall' and 'fastcall' functions. - - 'libffi' provides some support for this. However, this is -necessarily platform-specific. - - -File: libffi.info, Node: The Closure API, Next: Closure Example, Prev: Multiple ABIs, Up: Using libffi - -2.5 The Closure API -=================== - -'libffi' also provides a way to write a generic function - a function -that can accept and decode any combination of arguments. This can be -useful when writing an interpreter, or to provide wrappers for arbitrary -functions. - - This facility is called the "closure API". Closures are not supported -on all platforms; you can check the 'FFI_CLOSURES' define to determine -whether they are supported on the current platform. - - Because closures work by assembling a tiny function at runtime, they -require special allocation on platforms that have a non-executable heap. -Memory management for closures is handled by a pair of functions: - - -- Function: void *ffi_closure_alloc (size_t SIZE, void **CODE) - Allocate a chunk of memory holding SIZE bytes. This returns a - pointer to the writable address, and sets *CODE to the - corresponding executable address. - - SIZE should be sufficient to hold a 'ffi_closure' object. - - -- Function: void ffi_closure_free (void *WRITABLE) - Free memory allocated using 'ffi_closure_alloc'. The argument is - the writable address that was returned. - - Once you have allocated the memory for a closure, you must construct -a 'ffi_cif' describing the function call. Finally you can prepare the -closure function: - - -- Function: ffi_status ffi_prep_closure_loc (ffi_closure *CLOSURE, - ffi_cif *CIF, void (*FUN) (ffi_cif *CIF, void *RET, void - **ARGS, void *USER_DATA), void *USER_DATA, void *CODELOC) - Prepare a closure function. - - CLOSURE is the address of a 'ffi_closure' object; this is the - writable address returned by 'ffi_closure_alloc'. - - CIF is the 'ffi_cif' describing the function parameters. - - USER_DATA is an arbitrary datum that is passed, uninterpreted, to - your closure function. - - CODELOC is the executable address returned by 'ffi_closure_alloc'. - - FUN is the function which will be called when the closure is - invoked. It is called with the arguments: - CIF - The 'ffi_cif' passed to 'ffi_prep_closure_loc'. - - RET - A pointer to the memory used for the function's return value. - FUN must fill this, unless the function is declared as - returning 'void'. - - ARGS - A vector of pointers to memory holding the arguments to the - function. - - USER_DATA - The same USER_DATA that was passed to 'ffi_prep_closure_loc'. - - 'ffi_prep_closure_loc' will return 'FFI_OK' if everything went ok, - and something else on error. - - After calling 'ffi_prep_closure_loc', you can cast CODELOC to the - appropriate pointer-to-function type. - - You may see old code referring to 'ffi_prep_closure'. This function -is deprecated, as it cannot handle the need for separate writable and -executable addresses. - - -File: libffi.info, Node: Closure Example, Prev: The Closure API, Up: Using libffi - -2.6 Closure Example -=================== - -A trivial example that creates a new 'puts' by binding 'fputs' with -'stdout'. - - #include - #include - - /* Acts like puts with the file given at time of enclosure. */ - void puts_binding(ffi_cif *cif, void *ret, void* args[], - void *stream) - { - *(ffi_arg *)ret = fputs(*(char **)args[0], (FILE *)stream); - } - - typedef int (*puts_t)(char *); - - int main() - { - ffi_cif cif; - ffi_type *args[1]; - ffi_closure *closure; - - void *bound_puts; - int rc; - - /* Allocate closure and bound_puts */ - closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts); - - if (closure) - { - /* Initialize the argument info vectors */ - args[0] = &ffi_type_pointer; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint, args) == FFI_OK) - { - /* Initialize the closure, setting stream to stdout */ - if (ffi_prep_closure_loc(closure, &cif, puts_binding, - stdout, bound_puts) == FFI_OK) - { - rc = ((puts_t)bound_puts)("Hello World!"); - /* rc now holds the result of the call to fputs */ - } - } - } - - /* Deallocate both closure, and bound_puts */ - ffi_closure_free(closure); - - return 0; - } - - -File: libffi.info, Node: Missing Features, Next: Index, Prev: Using libffi, Up: Top - -3 Missing Features -****************** - -'libffi' is missing a few features. We welcome patches to add support -for these. - - * Variadic closures. - - * There is no support for bit fields in structures. - - * The closure API is - - * The "raw" API is undocumented. - - Note that variadic support is very new and tested on a relatively -small number of platforms. - - -File: libffi.info, Node: Index, Prev: Missing Features, Up: Top - -Index -***** - -[index] -* Menu: - -* ABI: Introduction. (line 13) -* Application Binary Interface: Introduction. (line 13) -* calling convention: Introduction. (line 13) -* cif: The Basics. (line 14) -* closure API: The Closure API. (line 13) -* closures: The Closure API. (line 13) -* FFI: Introduction. (line 31) -* ffi_call: The Basics. (line 62) -* FFI_CLOSURES: The Closure API. (line 13) -* ffi_closure_alloc: The Closure API. (line 19) -* ffi_closure_free: The Closure API. (line 26) -* ffi_prep_cif: The Basics. (line 16) -* ffi_prep_cif_var: The Basics. (line 39) -* ffi_prep_closure_loc: The Closure API. (line 34) -* ffi_status: The Basics. (line 16) -* ffi_status <1>: The Basics. (line 39) -* ffi_status <2>: The Closure API. (line 34) -* ffi_type: Structures. (line 11) -* ffi_type <1>: Structures. (line 11) -* ffi_type <2>: Complex. (line 15) -* ffi_type <3>: Complex. (line 15) -* ffi_type_complex_double: Primitive Types. (line 82) -* ffi_type_complex_float: Primitive Types. (line 79) -* ffi_type_complex_longdouble: Primitive Types. (line 85) -* ffi_type_double: Primitive Types. (line 41) -* ffi_type_float: Primitive Types. (line 38) -* ffi_type_longdouble: Primitive Types. (line 71) -* ffi_type_pointer: Primitive Types. (line 75) -* ffi_type_schar: Primitive Types. (line 47) -* ffi_type_sint: Primitive Types. (line 62) -* ffi_type_sint16: Primitive Types. (line 23) -* ffi_type_sint32: Primitive Types. (line 29) -* ffi_type_sint64: Primitive Types. (line 35) -* ffi_type_sint8: Primitive Types. (line 17) -* ffi_type_slong: Primitive Types. (line 68) -* ffi_type_sshort: Primitive Types. (line 56) -* ffi_type_uchar: Primitive Types. (line 44) -* ffi_type_uint: Primitive Types. (line 59) -* ffi_type_uint16: Primitive Types. (line 20) -* ffi_type_uint32: Primitive Types. (line 26) -* ffi_type_uint64: Primitive Types. (line 32) -* ffi_type_uint8: Primitive Types. (line 14) -* ffi_type_ulong: Primitive Types. (line 65) -* ffi_type_ushort: Primitive Types. (line 53) -* ffi_type_void: Primitive Types. (line 10) -* Foreign Function Interface: Introduction. (line 31) -* void: The Basics. (line 62) -* void <1>: The Closure API. (line 19) -* void <2>: The Closure API. (line 26) - - - -Tag Table: -Node: Top682 -Node: Introduction1429 -Node: Using libffi3061 -Node: The Basics3547 -Node: Simple Example7198 -Node: Types8229 -Node: Primitive Types8613 -Node: Structures10734 -Node: Type Example11608 -Node: Complex12890 -Node: Complex Type Example14308 -Node: Multiple ABIs17360 -Node: The Closure API17731 -Node: Closure Example20675 -Node: Missing Features22284 -Node: Index22737 - -End Tag Table diff --git a/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.texi b/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.texi deleted file mode 100644 index b1c9bc367..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/doc/libffi.texi +++ /dev/null @@ -1,770 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename libffi.info -@settitle libffi -@setchapternewpage off -@c %**end of header - -@c Merge the standard indexes into a single one. -@syncodeindex fn cp -@syncodeindex vr cp -@syncodeindex ky cp -@syncodeindex pg cp -@syncodeindex tp cp - -@include version.texi - -@copying - -This manual is for Libffi, a portable foreign-function interface -library. - -Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. A copy of the license is included in the -section entitled ``GNU General Public License''. - -@end quotation -@end copying - -@dircategory Development -@direntry -* libffi: (libffi). Portable foreign-function interface library. -@end direntry - -@titlepage -@title Libffi -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - - -@ifnottex -@node Top -@top libffi - -@insertcopying - -@menu -* Introduction:: What is libffi? -* Using libffi:: How to use libffi. -* Missing Features:: Things libffi can't do. -* Index:: Index. -@end menu - -@end ifnottex - - -@node Introduction -@chapter What is libffi? - -Compilers for high level languages generate code that follow certain -conventions. These conventions are necessary, in part, for separate -compilation to work. One such convention is the @dfn{calling -convention}. The calling convention is a set of assumptions made by -the compiler about where function arguments will be found on entry to -a function. A calling convention also specifies where the return -value for a function is found. The calling convention is also -sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}. -@cindex calling convention -@cindex ABI -@cindex Application Binary Interface - -Some programs may not know at the time of compilation what arguments -are to be passed to a function. For instance, an interpreter may be -told at run-time about the number and types of arguments used to call -a given function. @samp{Libffi} can be used in such programs to -provide a bridge from the interpreter program to compiled code. - -The @samp{libffi} library provides a portable, high level programming -interface to various calling conventions. This allows a programmer to -call any function specified by a call interface description at run -time. - -@acronym{FFI} stands for Foreign Function Interface. A foreign -function interface is the popular name for the interface that allows -code written in one language to call code written in another language. -The @samp{libffi} library really only provides the lowest, machine -dependent layer of a fully featured foreign function interface. A -layer must exist above @samp{libffi} that handles type conversions for -values passed between the two languages. -@cindex FFI -@cindex Foreign Function Interface - - -@node Using libffi -@chapter Using libffi - -@menu -* The Basics:: The basic libffi API. -* Simple Example:: A simple example. -* Types:: libffi type descriptions. -* Multiple ABIs:: Different passing styles on one platform. -* The Closure API:: Writing a generic function. -* Closure Example:: A closure example. -@end menu - - -@node The Basics -@section The Basics - -@samp{Libffi} assumes that you have a pointer to the function you wish -to call and that you know the number and types of arguments to pass -it, as well as the return type of the function. - -The first thing you must do is create an @code{ffi_cif} object that -matches the signature of the function you wish to call. This is a -separate step because it is common to make multiple calls using a -single @code{ffi_cif}. The @dfn{cif} in @code{ffi_cif} stands for -Call InterFace. To prepare a call interface object, use the function -@code{ffi_prep_cif}. -@cindex cif - -@findex ffi_prep_cif -@defun ffi_status ffi_prep_cif (ffi_cif *@var{cif}, ffi_abi @var{abi}, unsigned int @var{nargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) -This initializes @var{cif} according to the given parameters. - -@var{abi} is the ABI to use; normally @code{FFI_DEFAULT_ABI} is what -you want. @ref{Multiple ABIs} for more information. - -@var{nargs} is the number of arguments that this function accepts. - -@var{rtype} is a pointer to an @code{ffi_type} structure that -describes the return type of the function. @xref{Types}. - -@var{argtypes} is a vector of @code{ffi_type} pointers. -@var{argtypes} must have @var{nargs} elements. If @var{nargs} is 0, -this argument is ignored. - -@code{ffi_prep_cif} returns a @code{libffi} status code, of type -@code{ffi_status}. This will be either @code{FFI_OK} if everything -worked properly; @code{FFI_BAD_TYPEDEF} if one of the @code{ffi_type} -objects is incorrect; or @code{FFI_BAD_ABI} if the @var{abi} parameter -is invalid. -@end defun - -If the function being called is variadic (varargs) then -@code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}. - -@findex ffi_prep_cif_var -@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) -This initializes @var{cif} according to the given parameters for -a call to a variadic function. In general it's operation is the -same as for @code{ffi_prep_cif} except that: - -@var{nfixedargs} is the number of fixed arguments, prior to any -variadic arguments. It must be greater than zero. - -@var{ntotalargs} the total number of arguments, including variadic -and fixed arguments. - -Note that, different cif's must be prepped for calls to the same -function when different numbers of arguments are passed. - -Also note that a call to @code{ffi_prep_cif_var} with -@var{nfixedargs}=@var{nototalargs} is NOT equivalent to a call to -@code{ffi_prep_cif}. - -@end defun - - -To call a function using an initialized @code{ffi_cif}, use the -@code{ffi_call} function: - -@findex ffi_call -@defun void ffi_call (ffi_cif *@var{cif}, void *@var{fn}, void *@var{rvalue}, void **@var{avalues}) -This calls the function @var{fn} according to the description given in -@var{cif}. @var{cif} must have already been prepared using -@code{ffi_prep_cif}. - -@var{rvalue} is a pointer to a chunk of memory that will hold the -result of the function call. This must be large enough to hold the -result, no smaller than the system register size (generally 32 or 64 -bits), and must be suitably aligned; it is the caller's responsibility -to ensure this. If @var{cif} declares that the function returns -@code{void} (using @code{ffi_type_void}), then @var{rvalue} is -ignored. - -@var{avalues} is a vector of @code{void *} pointers that point to the -memory locations holding the argument values for a call. If @var{cif} -declares that the function has no arguments (i.e., @var{nargs} was 0), -then @var{avalues} is ignored. Note that argument values may be -modified by the callee (for instance, structs passed by value); the -burden of copying pass-by-value arguments is placed on the caller. -@end defun - - -@node Simple Example -@section Simple Example - -Here is a trivial example that calls @code{puts} a few times. - -@example -#include -#include - -int main() -@{ - ffi_cif cif; - ffi_type *args[1]; - void *values[1]; - char *s; - ffi_arg rc; - - /* Initialize the argument info vectors */ - args[0] = &ffi_type_pointer; - values[0] = &s; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint, args) == FFI_OK) - @{ - s = "Hello World!"; - ffi_call(&cif, puts, &rc, values); - /* rc now holds the result of the call to puts */ - - /* values holds a pointer to the function's arg, so to - call puts() again all we need to do is change the - value of s */ - s = "This is cool!"; - ffi_call(&cif, puts, &rc, values); - @} - - return 0; -@} -@end example - - -@node Types -@section Types - -@menu -* Primitive Types:: Built-in types. -* Structures:: Structure types. -* Type Example:: Structure type example. -* Complex:: Complex types. -* Complex Type Example:: Complex type example. -@end menu - -@node Primitive Types -@subsection Primitive Types - -@code{Libffi} provides a number of built-in type descriptors that can -be used to describe argument and return types: - -@table @code -@item ffi_type_void -@tindex ffi_type_void -The type @code{void}. This cannot be used for argument types, only -for return values. - -@item ffi_type_uint8 -@tindex ffi_type_uint8 -An unsigned, 8-bit integer type. - -@item ffi_type_sint8 -@tindex ffi_type_sint8 -A signed, 8-bit integer type. - -@item ffi_type_uint16 -@tindex ffi_type_uint16 -An unsigned, 16-bit integer type. - -@item ffi_type_sint16 -@tindex ffi_type_sint16 -A signed, 16-bit integer type. - -@item ffi_type_uint32 -@tindex ffi_type_uint32 -An unsigned, 32-bit integer type. - -@item ffi_type_sint32 -@tindex ffi_type_sint32 -A signed, 32-bit integer type. - -@item ffi_type_uint64 -@tindex ffi_type_uint64 -An unsigned, 64-bit integer type. - -@item ffi_type_sint64 -@tindex ffi_type_sint64 -A signed, 64-bit integer type. - -@item ffi_type_float -@tindex ffi_type_float -The C @code{float} type. - -@item ffi_type_double -@tindex ffi_type_double -The C @code{double} type. - -@item ffi_type_uchar -@tindex ffi_type_uchar -The C @code{unsigned char} type. - -@item ffi_type_schar -@tindex ffi_type_schar -The C @code{signed char} type. (Note that there is not an exact -equivalent to the C @code{char} type in @code{libffi}; ordinarily you -should either use @code{ffi_type_schar} or @code{ffi_type_uchar} -depending on whether @code{char} is signed.) - -@item ffi_type_ushort -@tindex ffi_type_ushort -The C @code{unsigned short} type. - -@item ffi_type_sshort -@tindex ffi_type_sshort -The C @code{short} type. - -@item ffi_type_uint -@tindex ffi_type_uint -The C @code{unsigned int} type. - -@item ffi_type_sint -@tindex ffi_type_sint -The C @code{int} type. - -@item ffi_type_ulong -@tindex ffi_type_ulong -The C @code{unsigned long} type. - -@item ffi_type_slong -@tindex ffi_type_slong -The C @code{long} type. - -@item ffi_type_longdouble -@tindex ffi_type_longdouble -On platforms that have a C @code{long double} type, this is defined. -On other platforms, it is not. - -@item ffi_type_pointer -@tindex ffi_type_pointer -A generic @code{void *} pointer. You should use this for all -pointers, regardless of their real type. - -@item ffi_type_complex_float -@tindex ffi_type_complex_float -The C @code{_Complex float} type. - -@item ffi_type_complex_double -@tindex ffi_type_complex_double -The C @code{_Complex double} type. - -@item ffi_type_complex_longdouble -@tindex ffi_type_complex_longdouble -The C @code{_Complex long double} type. -On platforms that have a C @code{long double} type, this is defined. -On other platforms, it is not. -@end table - -Each of these is of type @code{ffi_type}, so you must take the address -when passing to @code{ffi_prep_cif}. - - -@node Structures -@subsection Structures - -Although @samp{libffi} has no special support for unions or -bit-fields, it is perfectly happy passing structures back and forth. -You must first describe the structure to @samp{libffi} by creating a -new @code{ffi_type} object for it. - -@tindex ffi_type -@deftp {Data type} ffi_type -The @code{ffi_type} has the following members: -@table @code -@item size_t size -This is set by @code{libffi}; you should initialize it to zero. - -@item unsigned short alignment -This is set by @code{libffi}; you should initialize it to zero. - -@item unsigned short type -For a structure, this should be set to @code{FFI_TYPE_STRUCT}. - -@item ffi_type **elements -This is a @samp{NULL}-terminated array of pointers to @code{ffi_type} -objects. There is one element per field of the struct. -@end table -@end deftp - - -@node Type Example -@subsection Type Example - -The following example initializes a @code{ffi_type} object -representing the @code{tm} struct from Linux's @file{time.h}. - -Here is how the struct is defined: - -@example -struct tm @{ - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - /* Those are for future use. */ - long int __tm_gmtoff__; - __const char *__tm_zone__; -@}; -@end example - -Here is the corresponding code to describe this struct to -@code{libffi}: - -@example - @{ - ffi_type tm_type; - ffi_type *tm_type_elements[12]; - int i; - - tm_type.size = tm_type.alignment = 0; - tm_type.type = FFI_TYPE_STRUCT; - tm_type.elements = &tm_type_elements; - - for (i = 0; i < 9; i++) - tm_type_elements[i] = &ffi_type_sint; - - tm_type_elements[9] = &ffi_type_slong; - tm_type_elements[10] = &ffi_type_pointer; - tm_type_elements[11] = NULL; - - /* tm_type can now be used to represent tm argument types and - return types for ffi_prep_cif() */ - @} -@end example - -@node Complex -@subsection Complex Types - -@samp{libffi} supports the complex types defined by the C99 -standard (@code{_Complex float}, @code{_Complex double} and -@code{_Complex long double} with the built-in type descriptors -@code{ffi_type_complex_float}, @code{ffi_type_complex_double} and -@code{ffi_type_complex_longdouble}. - -Custom complex types like @code{_Complex int} can also be used. -An @code{ffi_type} object has to be defined to describe the -complex type to @samp{libffi}. - -@tindex ffi_type -@deftp {Data type} ffi_type -@table @code -@item size_t size -This must be manually set to the size of the complex type. - -@item unsigned short alignment -This must be manually set to the alignment of the complex type. - -@item unsigned short type -For a complex type, this must be set to @code{FFI_TYPE_COMPLEX}. - -@item ffi_type **elements - -This is a @samp{NULL}-terminated array of pointers to -@code{ffi_type} objects. The first element is set to the -@code{ffi_type} of the complex's base type. The second element -must be set to @code{NULL}. -@end table -@end deftp - -The section @ref{Complex Type Example} shows a way to determine -the @code{size} and @code{alignment} members in a platform -independent way. - -For platforms that have no complex support in @code{libffi} yet, -the functions @code{ffi_prep_cif} and @code{ffi_prep_args} abort -the program if they encounter a complex type. - -@node Complex Type Example -@subsection Complex Type Example - -This example demonstrates how to use complex types: - -@example -#include -#include -#include - -void complex_fn(_Complex float cf, - _Complex double cd, - _Complex long double cld) -@{ - printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n", - (float)creal (cf), (float)cimag (cf), - (float)creal (cd), (float)cimag (cd), - (float)creal (cld), (float)cimag (cld)); -@} - -int main() -@{ - ffi_cif cif; - ffi_type *args[3]; - void *values[3]; - _Complex float cf; - _Complex double cd; - _Complex long double cld; - - /* Initialize the argument info vectors */ - args[0] = &ffi_type_complex_float; - args[1] = &ffi_type_complex_double; - args[2] = &ffi_type_complex_longdouble; - values[0] = &cf; - values[1] = &cd; - values[2] = &cld; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_void, args) == FFI_OK) - @{ - cf = 1.0 + 20.0 * I; - cd = 300.0 + 4000.0 * I; - cld = 50000.0 + 600000.0 * I; - /* Call the function */ - ffi_call(&cif, (void (*)(void))complex_fn, 0, values); - @} - - return 0; -@} -@end example - -This is an example for defining a custom complex type descriptor -for compilers that support them: - -@example -/* - * This macro can be used to define new complex type descriptors - * in a platform independent way. - * - * name: Name of the new descriptor is ffi_type_complex_. - * type: The C base type of the complex type. - */ -#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \ - static ffi_type *ffi_elements_complex_##name [2] = @{ \ - (ffi_type *)(&ffitype), NULL \ - @}; \ - struct struct_align_complex_##name @{ \ - char c; \ - _Complex type x; \ - @}; \ - ffi_type ffi_type_complex_##name = @{ \ - sizeof(_Complex type), \ - offsetof(struct struct_align_complex_##name, x), \ - FFI_TYPE_COMPLEX, \ - (ffi_type **)ffi_elements_complex_##name \ - @} - -/* Define new complex type descriptors using the macro: */ -/* ffi_type_complex_sint */ -FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint); -/* ffi_type_complex_uchar */ -FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8); -@end example - -The new type descriptors can then be used like one of the built-in -type descriptors in the previous example. - -@node Multiple ABIs -@section Multiple ABIs - -A given platform may provide multiple different ABIs at once. For -instance, the x86 platform has both @samp{stdcall} and @samp{fastcall} -functions. - -@code{libffi} provides some support for this. However, this is -necessarily platform-specific. - -@c FIXME: document the platforms - -@node The Closure API -@section The Closure API - -@code{libffi} also provides a way to write a generic function -- a -function that can accept and decode any combination of arguments. -This can be useful when writing an interpreter, or to provide wrappers -for arbitrary functions. - -This facility is called the @dfn{closure API}. Closures are not -supported on all platforms; you can check the @code{FFI_CLOSURES} -define to determine whether they are supported on the current -platform. -@cindex closures -@cindex closure API -@findex FFI_CLOSURES - -Because closures work by assembling a tiny function at runtime, they -require special allocation on platforms that have a non-executable -heap. Memory management for closures is handled by a pair of -functions: - -@findex ffi_closure_alloc -@defun void *ffi_closure_alloc (size_t @var{size}, void **@var{code}) -Allocate a chunk of memory holding @var{size} bytes. This returns a -pointer to the writable address, and sets *@var{code} to the -corresponding executable address. - -@var{size} should be sufficient to hold a @code{ffi_closure} object. -@end defun - -@findex ffi_closure_free -@defun void ffi_closure_free (void *@var{writable}) -Free memory allocated using @code{ffi_closure_alloc}. The argument is -the writable address that was returned. -@end defun - - -Once you have allocated the memory for a closure, you must construct a -@code{ffi_cif} describing the function call. Finally you can prepare -the closure function: - -@findex ffi_prep_closure_loc -@defun ffi_status ffi_prep_closure_loc (ffi_closure *@var{closure}, ffi_cif *@var{cif}, void (*@var{fun}) (ffi_cif *@var{cif}, void *@var{ret}, void **@var{args}, void *@var{user_data}), void *@var{user_data}, void *@var{codeloc}) -Prepare a closure function. - -@var{closure} is the address of a @code{ffi_closure} object; this is -the writable address returned by @code{ffi_closure_alloc}. - -@var{cif} is the @code{ffi_cif} describing the function parameters. - -@var{user_data} is an arbitrary datum that is passed, uninterpreted, -to your closure function. - -@var{codeloc} is the executable address returned by -@code{ffi_closure_alloc}. - -@var{fun} is the function which will be called when the closure is -invoked. It is called with the arguments: -@table @var -@item cif -The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. - -@item ret -A pointer to the memory used for the function's return value. -@var{fun} must fill this, unless the function is declared as returning -@code{void}. -@c FIXME: is this NULL for void-returning functions? - -@item args -A vector of pointers to memory holding the arguments to the function. - -@item user_data -The same @var{user_data} that was passed to -@code{ffi_prep_closure_loc}. -@end table - -@code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything -went ok, and something else on error. -@c FIXME: what? - -After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc} -to the appropriate pointer-to-function type. -@end defun - -You may see old code referring to @code{ffi_prep_closure}. This -function is deprecated, as it cannot handle the need for separate -writable and executable addresses. - -@node Closure Example -@section Closure Example - -A trivial example that creates a new @code{puts} by binding -@code{fputs} with @code{stdout}. - -@example -#include -#include - -/* Acts like puts with the file given at time of enclosure. */ -void puts_binding(ffi_cif *cif, void *ret, void* args[], - void *stream) -@{ - *(ffi_arg *)ret = fputs(*(char **)args[0], (FILE *)stream); -@} - -typedef int (*puts_t)(char *); - -int main() -@{ - ffi_cif cif; - ffi_type *args[1]; - ffi_closure *closure; - - void *bound_puts; - int rc; - - /* Allocate closure and bound_puts */ - closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts); - - if (closure) - @{ - /* Initialize the argument info vectors */ - args[0] = &ffi_type_pointer; - - /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint, args) == FFI_OK) - @{ - /* Initialize the closure, setting stream to stdout */ - if (ffi_prep_closure_loc(closure, &cif, puts_binding, - stdout, bound_puts) == FFI_OK) - @{ - rc = ((puts_t)bound_puts)("Hello World!"); - /* rc now holds the result of the call to fputs */ - @} - @} - @} - - /* Deallocate both closure, and bound_puts */ - ffi_closure_free(closure); - - return 0; -@} - -@end example - - -@node Missing Features -@chapter Missing Features - -@code{libffi} is missing a few features. We welcome patches to add -support for these. - -@itemize @bullet -@item -Variadic closures. - -@item -There is no support for bit fields in structures. - -@item -The closure API is - -@c FIXME: ... - -@item -The ``raw'' API is undocumented. -@c argument promotion? -@c unions? -@c anything else? -@end itemize - -Note that variadic support is very new and tested on a relatively -small number of platforms. - -@node Index -@unnumbered Index - -@printindex cp - -@bye diff --git a/ruby/ext/fiddle/libffi-3.2.1/doc/stamp-vti b/ruby/ext/fiddle/libffi-3.2.1/doc/stamp-vti deleted file mode 100644 index ccef70f49..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/doc/stamp-vti +++ /dev/null @@ -1,4 +0,0 @@ -@set UPDATED 8 November 2014 -@set UPDATED-MONTH November 2014 -@set EDITION 3.2.1 -@set VERSION 3.2.1 diff --git a/ruby/ext/fiddle/libffi-3.2.1/doc/version.texi b/ruby/ext/fiddle/libffi-3.2.1/doc/version.texi deleted file mode 100644 index ccef70f49..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/doc/version.texi +++ /dev/null @@ -1,4 +0,0 @@ -@set UPDATED 8 November 2014 -@set UPDATED-MONTH November 2014 -@set EDITION 3.2.1 -@set VERSION 3.2.1 diff --git a/ruby/ext/fiddle/libffi-3.2.1/fficonfig.h.in b/ruby/ext/fiddle/libffi-3.2.1/fficonfig.h.in deleted file mode 100644 index 8aec513a5..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/fficonfig.h.in +++ /dev/null @@ -1,214 +0,0 @@ -/* fficonfig.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -#undef CRAY_STACKSEG_END - -/* Define to 1 if using `alloca.c'. */ -#undef C_ALLOCA - -/* Define to the flags needed for the .section .eh_frame directive. */ -#undef EH_FRAME_FLAGS - -/* Define this if you want extra debugging. */ -#undef FFI_DEBUG - -/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */ -#undef FFI_EXEC_TRAMPOLINE_TABLE - -/* Define this if you want to enable pax emulated trampolines */ -#undef FFI_MMAP_EXEC_EMUTRAMP_PAX - -/* Cannot use malloc on this target, so, we revert to alternative means */ -#undef FFI_MMAP_EXEC_WRIT - -/* Define this if you do not want support for the raw API. */ -#undef FFI_NO_RAW_API - -/* Define this if you do not want support for aggregate types. */ -#undef FFI_NO_STRUCTS - -/* Define to 1 if you have `alloca', as a function or macro. */ -#undef HAVE_ALLOCA - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#undef HAVE_ALLOCA_H - -/* Define if your assembler supports .ascii. */ -#undef HAVE_AS_ASCII_PSEUDO_OP - -/* Define if your assembler supports .cfi_* directives. */ -#undef HAVE_AS_CFI_PSEUDO_OP - -/* Define if your assembler supports .register. */ -#undef HAVE_AS_REGISTER_PSEUDO_OP - -/* Define if your assembler and linker support unaligned PC relative relocs. - */ -#undef HAVE_AS_SPARC_UA_PCREL - -/* Define if your assembler supports .string. */ -#undef HAVE_AS_STRING_PSEUDO_OP - -/* Define if your assembler supports unwind section type. */ -#undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE - -/* Define if your assembler supports PC relative relocs. */ -#undef HAVE_AS_X86_PCREL - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define if __attribute__((visibility("hidden"))) is supported. */ -#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if you have the long double type and it is bigger than a double */ -#undef HAVE_LONG_DOUBLE - -/* Define if you support more than one size of the long double type */ -#undef HAVE_LONG_DOUBLE_VARIANT - -/* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `mkostemp' function. */ -#undef HAVE_MKOSTEMP - -/* Define to 1 if you have the `mmap' function. */ -#undef HAVE_MMAP - -/* Define if mmap with MAP_ANON(YMOUS) works. */ -#undef HAVE_MMAP_ANON - -/* Define if mmap of /dev/zero works. */ -#undef HAVE_MMAP_DEV_ZERO - -/* Define if read-only mmap of a plain file works. */ -#undef HAVE_MMAP_FILE - -/* Define if .eh_frame sections should be read-only. */ -#undef HAVE_RO_EH_FRAME - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_MMAN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* The size of `double', as computed by sizeof. */ -#undef SIZEOF_DOUBLE - -/* The size of `long double', as computed by sizeof. */ -#undef SIZEOF_LONG_DOUBLE - -/* The size of `size_t', as computed by sizeof. */ -#undef SIZEOF_SIZE_T - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#undef STACK_DIRECTION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define if symbols are underscored. */ -#undef SYMBOL_UNDERSCORE - -/* Define this if you are using Purify and want to suppress spurious messages. - */ -#undef USING_PURIFY - -/* Version number of package */ -#undef VERSION - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Define to `unsigned int' if does not define. */ -#undef size_t - - -#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) .hidden name -#else -#define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) -#endif -#else -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) -#else -#define FFI_HIDDEN -#endif -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/generate-darwin-source-and-headers.py b/ruby/ext/fiddle/libffi-3.2.1/generate-darwin-source-and-headers.py deleted file mode 100644 index 964e861d4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/generate-darwin-source-and-headers.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python -import subprocess -import os -import errno -import collections -import glob -import argparse - -class Platform(object): - pass - -class simulator_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphonesimulator' - arch = 'i386' - triple = 'i386-apple-darwin11' - version_min = '-miphoneos-version-min=5.1.1' - - prefix = "#ifdef __i386__\n\n" - suffix = "\n\n#endif" - src_dir = 'x86' - src_files = ['darwin.S', 'win32.S', 'ffi.c'] - - -class simulator64_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphonesimulator' - arch = 'x86_64' - triple = 'x86_64-apple-darwin13' - version_min = '-miphoneos-version-min=7.0' - - prefix = "#ifdef __x86_64__\n\n" - suffix = "\n\n#endif" - src_dir = 'x86' - src_files = ['darwin64.S', 'ffi64.c'] - - -class device_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphoneos' - arch = 'armv7' - triple = 'arm-apple-darwin11' - version_min = '-miphoneos-version-min=5.1.1' - - prefix = "#ifdef __arm__\n\n" - suffix = "\n\n#endif" - src_dir = 'arm' - src_files = ['sysv.S', 'trampoline.S', 'ffi.c'] - - -class device64_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphoneos' - arch = 'arm64' - triple = 'aarch64-apple-darwin13' - version_min = '-miphoneos-version-min=7.0' - - prefix = "#ifdef __arm64__\n\n" - suffix = "\n\n#endif" - src_dir = 'aarch64' - src_files = ['sysv.S', 'ffi.c'] - - -class desktop32_platform(Platform): - directory = 'darwin_osx' - sdk = 'macosx' - arch = 'i386' - triple = 'i386-apple-darwin10' - version_min = '-mmacosx-version-min=10.6' - src_dir = 'x86' - src_files = ['darwin.S', 'win32.S', 'ffi.c'] - - prefix = "#ifdef __i386__\n\n" - suffix = "\n\n#endif" - - -class desktop64_platform(Platform): - directory = 'darwin_osx' - sdk = 'macosx' - arch = 'x86_64' - triple = 'x86_64-apple-darwin10' - version_min = '-mmacosx-version-min=10.6' - - prefix = "#ifdef __x86_64__\n\n" - suffix = "\n\n#endif" - src_dir = 'x86' - src_files = ['darwin64.S', 'ffi64.c'] - - -def mkdir_p(path): - try: - os.makedirs(path) - except OSError as exc: # Python >2.5 - if exc.errno == errno.EEXIST: - pass - else: - raise - - -def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''): - mkdir_p(dst_dir) - out_filename = filename - - if file_suffix: - split_name = os.path.splitext(filename) - out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) - - with open(os.path.join(src_dir, filename)) as in_file: - with open(os.path.join(dst_dir, out_filename), 'w') as out_file: - if prefix: - out_file.write(prefix) - - out_file.write(in_file.read()) - - if suffix: - out_file.write(suffix) - - -def list_files(src_dir, pattern=None, filelist=None): - if pattern: filelist = glob.iglob(os.path.join(src_dir, pattern)) - for file in filelist: - yield os.path.basename(file) - - -def copy_files(src_dir, dst_dir, pattern=None, filelist=None, file_suffix=None, prefix=None, suffix=None): - for filename in list_files(src_dir, pattern=pattern, filelist=filelist): - move_file(src_dir, dst_dir, filename, file_suffix=file_suffix, prefix=prefix, suffix=suffix) - - -def copy_src_platform_files(platform): - src_dir = os.path.join('src', platform.src_dir) - dst_dir = os.path.join(platform.directory, 'src', platform.src_dir) - copy_files(src_dir, dst_dir, filelist=platform.src_files, file_suffix=platform.arch, prefix=platform.prefix, suffix=platform.suffix) - - -def build_target(platform, platform_headers): - def xcrun_cmd(cmd): - return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch) - - tag='%s-%s' % (platform.sdk, platform.arch) - build_dir = 'build_%s' % tag - mkdir_p(build_dir) - env = dict(CC=xcrun_cmd('clang'), - LD=xcrun_cmd('ld'), - CFLAGS='%s' % (platform.version_min)) - working_dir = os.getcwd() - try: - os.chdir(build_dir) - subprocess.check_call(['../configure', '-host', platform.triple], env=env) - finally: - os.chdir(working_dir) - - for src_dir in [build_dir, os.path.join(build_dir, 'include')]: - copy_files(src_dir, - os.path.join(platform.directory, 'include'), - pattern='*.h', - file_suffix=platform.arch, - prefix=platform.prefix, - suffix=platform.suffix) - - for filename in list_files(src_dir, pattern='*.h'): - platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix)) - - -def make_tramp(): - with open('src/arm/trampoline.S', 'w') as tramp_out: - p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out) - p.wait() - - -def generate_source_and_headers(generate_osx=True, generate_ios=True): - copy_files('src', 'darwin_common/src', pattern='*.c') - copy_files('include', 'darwin_common/include', pattern='*.h') - - if generate_ios: - make_tramp() - copy_src_platform_files(simulator_platform) - copy_src_platform_files(simulator64_platform) - copy_src_platform_files(device_platform) - copy_src_platform_files(device64_platform) - if generate_osx: - copy_src_platform_files(desktop32_platform) - copy_src_platform_files(desktop64_platform) - - platform_headers = collections.defaultdict(set) - - if generate_ios: - build_target(simulator_platform, platform_headers) - build_target(simulator64_platform, platform_headers) - build_target(device_platform, platform_headers) - build_target(device64_platform, platform_headers) - if generate_osx: - build_target(desktop32_platform, platform_headers) - build_target(desktop64_platform, platform_headers) - - mkdir_p('darwin_common/include') - for header_name, tag_tuples in platform_headers.iteritems(): - basename, suffix = os.path.splitext(header_name) - with open(os.path.join('darwin_common/include', header_name), 'w') as header: - for tag_tuple in tag_tuples: - header.write('%s#include <%s_%s%s>\n%s\n' % (tag_tuple[0], basename, tag_tuple[1], suffix, tag_tuple[2])) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--only-ios', action='store_true', default=False) - parser.add_argument('--only-osx', action='store_true', default=False) - args = parser.parse_args() - - generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx) diff --git a/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.am b/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.am deleted file mode 100644 index fd2802497..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -## Process this with automake to create Makefile.in - -AUTOMAKE_OPTIONS=foreign - -DISTCLEANFILES=ffitarget.h -EXTRA_DIST=ffi.h.in ffi_common.h - -includesdir = $(libdir)/@PACKAGE_NAME@-@PACKAGE_VERSION@/include -nodist_includes_HEADERS = ffi.h ffitarget.h diff --git a/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.in b/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.in deleted file mode 100644 index 9d747e80e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/include/Makefile.in +++ /dev/null @@ -1,587 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = include -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(srcdir)/ffi.h.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \ - $(top_srcdir)/m4/ax_append_flag.m4 \ - $(top_srcdir)/m4/ax_cc_maxopt.m4 \ - $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_compiler_vendor.m4 \ - $(top_srcdir)/m4/ax_configure_args.m4 \ - $(top_srcdir)/m4/ax_enable_builddir.m4 \ - $(top_srcdir)/m4/ax_gcc_archflag.m4 \ - $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/fficonfig.h -CONFIG_CLEAN_FILES = ffi.h ffitarget.h -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(includesdir)" -HEADERS = $(nodist_includes_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AM_LTLDFLAGS = @AM_LTLDFLAGS@ -AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ -HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PRTDIAG = @PRTDIAG@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TARGET = @TARGET@ -TARGETDIR = @TARGETDIR@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -ax_enable_builddir_sed = @ax_enable_builddir_sed@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sys_symbol_underscore = @sys_symbol_underscore@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -toolexecdir = @toolexecdir@ -toolexeclibdir = @toolexeclibdir@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign -DISTCLEANFILES = ffitarget.h -EXTRA_DIST = ffi.h.in ffi_common.h -includesdir = $(libdir)/@PACKAGE_NAME@-@PACKAGE_VERSION@/include -nodist_includes_HEADERS = ffi.h ffitarget.h -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign include/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -ffi.h: $(top_builddir)/config.status $(srcdir)/ffi.h.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-nodist_includesHEADERS: $(nodist_includes_HEADERS) - @$(NORMAL_INSTALL) - @list='$(nodist_includes_HEADERS)'; test -n "$(includesdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(includesdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(includesdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesdir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesdir)" || exit $$?; \ - done - -uninstall-nodist_includesHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nodist_includes_HEADERS)'; test -n "$(includesdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(includesdir)'; $(am__uninstall_files_from_dir) - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(includesdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-nodist_includesHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-nodist_includesHEADERS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool cscopelist-am ctags ctags-am distclean \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man \ - install-nodist_includesHEADERS install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-nodist_includesHEADERS - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ruby/ext/fiddle/libffi-3.2.1/include/ffi.h.in b/ruby/ext/fiddle/libffi-3.2.1/include/ffi.h.in deleted file mode 100644 index a20be0375..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/include/ffi.h.in +++ /dev/null @@ -1,492 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green - - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. - - 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. - - ----------------------------------------------------------------------- */ - -/* ------------------------------------------------------------------- - The basic API is described in the README file. - - The raw API is designed to bypass some of the argument packing - and unpacking on architectures for which it can be avoided. - - The closure API allows interpreted functions to be packaged up - inside a C function pointer, so that they can be called as C functions, - with no understanding on the client side that they are interpreted. - It can also be used in other cases in which it is necessary to package - up a user specified parameter and a function pointer as a single - function pointer. - - The closure API must be implemented in order to get its functionality, - e.g. for use by gij. Routines are provided to emulate the raw API - if the underlying platform doesn't allow faster implementation. - - More details on the raw and cloure API can be found in: - - http://gcc.gnu.org/ml/java/1999-q3/msg00138.html - - and - - http://gcc.gnu.org/ml/java/1999-q3/msg00174.html - -------------------------------------------------------------------- */ - -#ifndef LIBFFI_H -#define LIBFFI_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Specify which architecture libffi is configured for. */ -#ifndef @TARGET@ -#define @TARGET@ -#endif - -/* ---- System configuration information --------------------------------- */ - -#include - -#ifndef LIBFFI_ASM - -#if defined(_MSC_VER) && !defined(__clang__) -#define __attribute__(X) -#endif - -#include -#include - -/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). - But we can find it either under the correct ANSI name, or under GNU - C's internal name. */ - -#define FFI_64_BIT_MAX 9223372036854775807 - -#ifdef LONG_LONG_MAX -# define FFI_LONG_LONG_MAX LONG_LONG_MAX -#else -# ifdef LLONG_MAX -# define FFI_LONG_LONG_MAX LLONG_MAX -# ifdef _AIX52 /* or newer has C99 LLONG_MAX */ -# undef FFI_64_BIT_MAX -# define FFI_64_BIT_MAX 9223372036854775807LL -# endif /* _AIX52 or newer */ -# else -# ifdef __GNUC__ -# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ -# endif -# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */ -# ifndef __PPC64__ -# if defined (__IBMC__) || defined (__IBMCPP__) -# define FFI_LONG_LONG_MAX LONGLONG_MAX -# endif -# endif /* __PPC64__ */ -# 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 - -/* The closure code assumes that this works on pointers, i.e. a size_t */ -/* can hold a pointer. */ - -typedef struct _ffi_type -{ - size_t size; - unsigned short alignment; - unsigned short type; - struct _ffi_type **elements; -} ffi_type; - -#ifndef LIBFFI_HIDE_BASIC_TYPES -#if SCHAR_MAX == 127 -# define ffi_type_uchar ffi_type_uint8 -# define ffi_type_schar ffi_type_sint8 -#else - #error "char size not supported" -#endif - -#if SHRT_MAX == 32767 -# define ffi_type_ushort ffi_type_uint16 -# define ffi_type_sshort ffi_type_sint16 -#elif SHRT_MAX == 2147483647 -# define ffi_type_ushort ffi_type_uint32 -# define ffi_type_sshort ffi_type_sint32 -#else - #error "short size not supported" -#endif - -#if INT_MAX == 32767 -# define ffi_type_uint ffi_type_uint16 -# define ffi_type_sint ffi_type_sint16 -#elif INT_MAX == 2147483647 -# define ffi_type_uint ffi_type_uint32 -# define ffi_type_sint ffi_type_sint32 -#elif INT_MAX == 9223372036854775807 -# define ffi_type_uint ffi_type_uint64 -# define ffi_type_sint ffi_type_sint64 -#else - #error "int size not supported" -#endif - -#if LONG_MAX == 2147483647 -# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX - #error "no 64-bit data type supported" -# endif -#elif LONG_MAX != FFI_64_BIT_MAX - #error "long size not supported" -#endif - -#if LONG_MAX == 2147483647 -# define ffi_type_ulong ffi_type_uint32 -# define ffi_type_slong ffi_type_sint32 -#elif LONG_MAX == FFI_64_BIT_MAX -# define ffi_type_ulong ffi_type_uint64 -# define ffi_type_slong ffi_type_sint64 -#else - #error "long size not supported" -#endif - -/* Need minimal decorations for DLLs to works on Windows. */ -/* GCC has autoimport and autoexport. Rely on Libtool to */ -/* help MSVC export from a DLL, but always declare data */ -/* to be imported for MSVC clients. This costs an extra */ -/* indirection for MSVC clients using the static version */ -/* of the library, but don't worry about that. Besides, */ -/* as a workaround, they can define FFI_BUILDING if they */ -/* *know* they are going to link with the static library. */ -#if defined _MSC_VER && !defined FFI_BUILDING -#define FFI_EXTERN extern __declspec(dllimport) -#else -#define FFI_EXTERN extern -#endif - -/* These are defined in types.c */ -FFI_EXTERN ffi_type ffi_type_void; -FFI_EXTERN ffi_type ffi_type_uint8; -FFI_EXTERN ffi_type ffi_type_sint8; -FFI_EXTERN ffi_type ffi_type_uint16; -FFI_EXTERN ffi_type ffi_type_sint16; -FFI_EXTERN ffi_type ffi_type_uint32; -FFI_EXTERN ffi_type ffi_type_sint32; -FFI_EXTERN ffi_type ffi_type_uint64; -FFI_EXTERN ffi_type ffi_type_sint64; -FFI_EXTERN ffi_type ffi_type_float; -FFI_EXTERN ffi_type ffi_type_double; -FFI_EXTERN ffi_type ffi_type_pointer; - -#if @HAVE_LONG_DOUBLE@ -FFI_EXTERN ffi_type ffi_type_longdouble; -#else -#define ffi_type_longdouble ffi_type_double -#endif - -#ifdef FFI_TARGET_HAS_COMPLEX_TYPE -FFI_EXTERN ffi_type ffi_type_complex_float; -FFI_EXTERN ffi_type ffi_type_complex_double; -#if @HAVE_LONG_DOUBLE@ -FFI_EXTERN ffi_type ffi_type_complex_longdouble; -#else -#define ffi_type_complex_longdouble ffi_type_complex_double -#endif -#endif -#endif /* LIBFFI_HIDE_BASIC_TYPES */ - -typedef enum { - FFI_OK = 0, - FFI_BAD_TYPEDEF, - FFI_BAD_ABI -} ffi_status; - -typedef unsigned FFI_TYPE; - -typedef struct { - ffi_abi abi; - unsigned nargs; - ffi_type **arg_types; - ffi_type *rtype; - unsigned bytes; - unsigned flags; -#ifdef FFI_EXTRA_CIF_FIELDS - FFI_EXTRA_CIF_FIELDS; -#endif -} ffi_cif; - -#if @HAVE_LONG_DOUBLE_VARIANT@ -/* Used to adjust size/alignment of ffi types. */ -void ffi_prep_types (ffi_abi abi); -#endif - -/* Used internally, but overridden by some architectures */ -ffi_status ffi_prep_cif_core(ffi_cif *cif, - ffi_abi abi, - unsigned int isvariadic, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes); - -/* ---- Definitions for the raw API -------------------------------------- */ - -#ifndef FFI_SIZEOF_ARG -# if LONG_MAX == 2147483647 -# define FFI_SIZEOF_ARG 4 -# elif LONG_MAX == FFI_64_BIT_MAX -# define FFI_SIZEOF_ARG 8 -# endif -#endif - -#ifndef FFI_SIZEOF_JAVA_RAW -# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG -#endif - -typedef union { - ffi_sarg sint; - ffi_arg uint; - float flt; - char data[FFI_SIZEOF_ARG]; - void* ptr; -} ffi_raw; - -#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 -/* This is a special case for mips64/n32 ABI (and perhaps others) where - sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ -typedef union { - signed int sint; - unsigned int uint; - float flt; - char data[FFI_SIZEOF_JAVA_RAW]; - void* ptr; -} ffi_java_raw; -#else -typedef ffi_raw ffi_java_raw; -#endif - - -void ffi_raw_call (ffi_cif *cif, - void (*fn)(void), - void *rvalue, - ffi_raw *avalue); - -void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); -void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); -size_t ffi_raw_size (ffi_cif *cif); - -/* This is analogous to the raw API, except it uses Java parameter */ -/* packing, even on 64-bit machines. I.e. on 64-bit machines */ -/* longs and doubles are followed by an empty 64-bit word. */ - -void ffi_java_raw_call (ffi_cif *cif, - void (*fn)(void), - void *rvalue, - ffi_java_raw *avalue); - -void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); -void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); -size_t ffi_java_raw_size (ffi_cif *cif); - -/* ---- Definitions for closures ----------------------------------------- */ - -#if FFI_CLOSURES - -#ifdef _MSC_VER -__declspec(align(8)) -#endif -typedef struct { -#if @FFI_EXEC_TRAMPOLINE_TABLE@ - void *trampoline_table; - void *trampoline_table_entry; -#else - char tramp[FFI_TRAMPOLINE_SIZE]; -#endif - ffi_cif *cif; - void (*fun)(ffi_cif*,void*,void**,void*); - void *user_data; -#ifdef __GNUC__ -} ffi_closure __attribute__((aligned (8))); -#else -} ffi_closure; -# ifdef __sgi -# pragma pack 0 -# endif -#endif - -void *ffi_closure_alloc (size_t size, void **code); -void ffi_closure_free (void *); - -ffi_status -ffi_prep_closure (ffi_closure*, - ffi_cif *, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data); - -ffi_status -ffi_prep_closure_loc (ffi_closure*, - ffi_cif *, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void*codeloc); - -#ifdef __sgi -# pragma pack 8 -#endif -typedef struct { -#if @FFI_EXEC_TRAMPOLINE_TABLE@ - void *trampoline_table; - void *trampoline_table_entry; -#else - char tramp[FFI_TRAMPOLINE_SIZE]; -#endif - ffi_cif *cif; - -#if !FFI_NATIVE_RAW_API - - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ - - void (*translate_args)(ffi_cif*,void*,void**,void*); - void *this_closure; - -#endif - - void (*fun)(ffi_cif*,void*,ffi_raw*,void*); - void *user_data; - -} ffi_raw_closure; - -typedef struct { -#if @FFI_EXEC_TRAMPOLINE_TABLE@ - void *trampoline_table; - void *trampoline_table_entry; -#else - char tramp[FFI_TRAMPOLINE_SIZE]; -#endif - - ffi_cif *cif; - -#if !FFI_NATIVE_RAW_API - - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ - - void (*translate_args)(ffi_cif*,void*,void**,void*); - void *this_closure; - -#endif - - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); - void *user_data; - -} ffi_java_raw_closure; - -ffi_status -ffi_prep_raw_closure (ffi_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data); - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc); - -ffi_status -ffi_prep_java_raw_closure (ffi_java_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data); - -ffi_status -ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data, - void *codeloc); - -#endif /* FFI_CLOSURES */ - -/* ---- Public interface definition -------------------------------------- */ - -ffi_status ffi_prep_cif(ffi_cif *cif, - ffi_abi abi, - unsigned int nargs, - ffi_type *rtype, - ffi_type **atypes); - -ffi_status ffi_prep_cif_var(ffi_cif *cif, - ffi_abi abi, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes); - -void ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue); - -/* Useful for eliminating compiler warnings */ -#define FFI_FN(f) ((void (*)(void))f) - -/* ---- Definitions shared with assembly code ---------------------------- */ - -#endif - -/* If these change, update src/mips/ffitarget.h. */ -#define FFI_TYPE_VOID 0 -#define FFI_TYPE_INT 1 -#define FFI_TYPE_FLOAT 2 -#define FFI_TYPE_DOUBLE 3 -#if @HAVE_LONG_DOUBLE@ -#define FFI_TYPE_LONGDOUBLE 4 -#else -#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE -#endif -#define FFI_TYPE_UINT8 5 -#define FFI_TYPE_SINT8 6 -#define FFI_TYPE_UINT16 7 -#define FFI_TYPE_SINT16 8 -#define FFI_TYPE_UINT32 9 -#define FFI_TYPE_SINT32 10 -#define FFI_TYPE_UINT64 11 -#define FFI_TYPE_SINT64 12 -#define FFI_TYPE_STRUCT 13 -#define FFI_TYPE_POINTER 14 -#define FFI_TYPE_COMPLEX 15 - -/* This should always refer to the last type code (for sanity checks) */ -#define FFI_TYPE_LAST FFI_TYPE_COMPLEX - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/include/ffi_common.h b/ruby/ext/fiddle/libffi-3.2.1/include/ffi_common.h deleted file mode 100644 index 37f5a9e92..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/include/ffi_common.h +++ /dev/null @@ -1,132 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green - Copyright (C) 2007 Free Software Foundation, Inc - Copyright (c) 1996 Red Hat, Inc. - - Common internal definitions and macros. Only necessary for building - libffi. - ----------------------------------------------------------------------- */ - -#ifndef FFI_COMMON_H -#define FFI_COMMON_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Do not move this. Some versions of AIX are very picky about where - this is positioned. */ -#ifdef __GNUC__ -# if HAVE_ALLOCA_H -# include -# else - /* mingw64 defines this already in malloc.h. */ -# ifndef alloca -# define alloca __builtin_alloca -# endif -# endif -# define MAYBE_UNUSED __attribute__((__unused__)) -#else -# define MAYBE_UNUSED -# if HAVE_ALLOCA_H -# include -# else -# ifdef _AIX -# pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -# ifdef _MSC_VER -# define alloca _alloca -# else -char *alloca (); -# endif -# endif -# endif -# endif -#endif - -/* Check for the existence of memcpy. */ -#if STDC_HEADERS -# include -#else -# ifndef HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# endif -#endif - -#if defined(FFI_DEBUG) -#include -#endif - -#ifdef FFI_DEBUG -void ffi_assert(char *expr, char *file, int line); -void ffi_stop_here(void); -void ffi_type_test(ffi_type *a, char *file, int line); - -#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) -#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) -#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__) -#else -#define FFI_ASSERT(x) -#define FFI_ASSERT_AT(x, f, l) -#define FFI_ASSERT_VALID_TYPE(x) -#endif - -#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) -#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a) - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif); -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, unsigned int ntotalargs); - -/* Extended cif, used in callback from assembly routine */ -typedef struct -{ - ffi_cif *cif; - void *rvalue; - void **avalue; -} extended_cif; - -/* Terse sized type definitions. */ -#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C) -typedef unsigned char UINT8; -typedef signed char SINT8; -typedef unsigned short UINT16; -typedef signed short SINT16; -typedef unsigned int UINT32; -typedef signed int SINT32; -# ifdef _MSC_VER -typedef unsigned __int64 UINT64; -typedef signed __int64 SINT64; -# else -# include -typedef uint64_t UINT64; -typedef int64_t SINT64; -# endif -#else -typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); -typedef signed int SINT8 __attribute__((__mode__(__QI__))); -typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); -typedef signed int SINT16 __attribute__((__mode__(__HI__))); -typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); -typedef signed int SINT32 __attribute__((__mode__(__SI__))); -typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); -typedef signed int SINT64 __attribute__((__mode__(__DI__))); -#endif - -typedef float FLOAT32; - -#ifndef __GNUC__ -#define __builtin_expect(x, expected_value) (x) -#endif -#define LIKELY(x) __builtin_expect(!!(x),1) -#define UNLIKELY(x) __builtin_expect((x)!=0,0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/install-sh b/ruby/ext/fiddle/libffi-3.2.1/install-sh deleted file mode 100755 index 377bb8687..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-11-20.07; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# 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 -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/libffi.pc.in b/ruby/ext/fiddle/libffi-3.2.1/libffi.pc.in deleted file mode 100644 index edf6fde5e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/libffi.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -toolexeclibdir=@toolexeclibdir@ -includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include - -Name: @PACKAGE_NAME@ -Description: Library supporting Foreign Function Interfaces -Version: @PACKAGE_VERSION@ -Libs: -L${toolexeclibdir} -lffi -Cflags: -I${includedir} diff --git a/ruby/ext/fiddle/libffi-3.2.1/libffi.xcodeproj/project.pbxproj b/ruby/ext/fiddle/libffi-3.2.1/libffi.xcodeproj/project.pbxproj deleted file mode 100644 index 1cf396ffa..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/libffi.xcodeproj/project.pbxproj +++ /dev/null @@ -1,637 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; - DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; }; - DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; }; - DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; - DBFA714E187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; - DBFA714F187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; - DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; - DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; - DBFA7158187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; - DBFA7159187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; - DBFA715A187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; - DBFA715B187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; - DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; }; - DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; }; - DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; }; - DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; }; - DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; }; - DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; }; - DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; }; - DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; }; - DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; }; - DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7182187F1DA100A76262 /* ffi_i386.h */; }; - DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; }; - DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7184187F1DA100A76262 /* fficonfig_i386.h */; }; - DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; }; - DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7186187F1DA100A76262 /* ffitarget_i386.h */; }; - DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; }; - DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */; }; - DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; }; - DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; - DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - DB13B1641849DF1E0010F42D /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; - DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = ""; }; - DBFA713F187F1D8600A76262 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = ""; }; - DBFA7140187F1D8600A76262 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = ""; }; - DBFA7141187F1D8600A76262 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = ""; }; - DBFA7143187F1D8600A76262 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = closures.c; sourceTree = ""; }; - DBFA7145187F1D8600A76262 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dlmalloc.c; sourceTree = ""; }; - DBFA7147187F1D8600A76262 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = ""; }; - DBFA7148187F1D8600A76262 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = ""; }; - DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = ""; }; - DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = ""; }; - DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = ""; }; - DBFA7160187F1D9B00A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = ""; }; - DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = ""; }; - DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = ""; }; - DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = ""; }; - DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = ""; }; - DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = ""; }; - DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = ""; }; - DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = ""; }; - DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = ""; }; - DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = ""; }; - DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = ""; }; - DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = ""; }; - DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = ""; }; - DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = ""; }; - DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = ""; }; - DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = ""; }; - DBFA7174187F1D9B00A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = ""; }; - DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = ""; }; - DBFA7176187F1D9B00A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = ""; }; - DBFA7182187F1DA100A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = ""; }; - DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = ""; }; - DBFA7184187F1DA100A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = ""; }; - DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = ""; }; - DBFA7186187F1DA100A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = ""; }; - DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = ""; }; - DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = ""; }; - DBFA718B187F1DA100A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = ""; }; - DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = ""; }; - DBFA718D187F1DA100A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - DB13B15B1849DEB70010F42D = { - isa = PBXGroup; - children = ( - DBFA713C187F1D8600A76262 /* darwin_common */, - DBFA715C187F1D9B00A76262 /* darwin_ios */, - DBFA7180187F1DA100A76262 /* darwin_osx */, - DB13B1671849DF1E0010F42D /* Products */, - ); - sourceTree = ""; - }; - DB13B1671849DF1E0010F42D /* Products */ = { - isa = PBXGroup; - children = ( - DB13B1661849DF1E0010F42D /* libffi.a */, - DB13B1911849DF510010F42D /* ffi.dylib */, - ); - name = Products; - sourceTree = ""; - }; - DBFA713C187F1D8600A76262 /* darwin_common */ = { - isa = PBXGroup; - children = ( - DBFA713D187F1D8600A76262 /* include */, - DBFA7142187F1D8600A76262 /* src */, - ); - path = "darwin_common"; - sourceTree = ""; - }; - DBFA713D187F1D8600A76262 /* include */ = { - isa = PBXGroup; - children = ( - DBFA713E187F1D8600A76262 /* ffi.h */, - DBFA713F187F1D8600A76262 /* ffi_common.h */, - DBFA7140187F1D8600A76262 /* fficonfig.h */, - DBFA7141187F1D8600A76262 /* ffitarget.h */, - ); - path = include; - sourceTree = ""; - }; - DBFA7142187F1D8600A76262 /* src */ = { - isa = PBXGroup; - children = ( - DBFA7143187F1D8600A76262 /* closures.c */, - DBFA7145187F1D8600A76262 /* dlmalloc.c */, - DBFA7147187F1D8600A76262 /* prep_cif.c */, - DBFA7148187F1D8600A76262 /* raw_api.c */, - DBFA7149187F1D8600A76262 /* types.c */, - ); - path = src; - sourceTree = ""; - }; - DBFA715C187F1D9B00A76262 /* darwin_ios */ = { - isa = PBXGroup; - children = ( - DBFA715D187F1D9B00A76262 /* include */, - DBFA716A187F1D9B00A76262 /* src */, - ); - path = "darwin_ios"; - sourceTree = ""; - }; - DBFA715D187F1D9B00A76262 /* include */ = { - isa = PBXGroup; - children = ( - DBFA715E187F1D9B00A76262 /* ffi_arm64.h */, - DBFA715F187F1D9B00A76262 /* ffi_armv7.h */, - DBFA7160187F1D9B00A76262 /* ffi_i386.h */, - DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */, - DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */, - DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */, - DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */, - DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */, - DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */, - DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */, - DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */, - DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */, - ); - path = include; - sourceTree = ""; - }; - DBFA716A187F1D9B00A76262 /* src */ = { - isa = PBXGroup; - children = ( - DBFA716B187F1D9B00A76262 /* aarch64 */, - DBFA716E187F1D9B00A76262 /* arm */, - DBFA7172187F1D9B00A76262 /* x86 */, - ); - path = src; - sourceTree = ""; - }; - DBFA716B187F1D9B00A76262 /* aarch64 */ = { - isa = PBXGroup; - children = ( - DBFA716C187F1D9B00A76262 /* ffi_arm64.c */, - DBFA716D187F1D9B00A76262 /* sysv_arm64.S */, - ); - path = aarch64; - sourceTree = ""; - }; - DBFA716E187F1D9B00A76262 /* arm */ = { - isa = PBXGroup; - children = ( - DBFA716F187F1D9B00A76262 /* ffi_armv7.c */, - DBFA7170187F1D9B00A76262 /* sysv_armv7.S */, - DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */, - ); - path = arm; - sourceTree = ""; - }; - DBFA7172187F1D9B00A76262 /* x86 */ = { - isa = PBXGroup; - children = ( - DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */, - DBFA7174187F1D9B00A76262 /* darwin_i386.S */, - DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */, - DBFA7176187F1D9B00A76262 /* ffi_i386.c */, - ); - path = x86; - sourceTree = ""; - }; - DBFA7180187F1DA100A76262 /* darwin_osx */ = { - isa = PBXGroup; - children = ( - DBFA7181187F1DA100A76262 /* include */, - DBFA7188187F1DA100A76262 /* src */, - ); - path = "darwin_osx"; - sourceTree = ""; - }; - DBFA7181187F1DA100A76262 /* include */ = { - isa = PBXGroup; - children = ( - DBFA7182187F1DA100A76262 /* ffi_i386.h */, - DBFA7183187F1DA100A76262 /* ffi_x86_64.h */, - DBFA7184187F1DA100A76262 /* fficonfig_i386.h */, - DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */, - DBFA7186187F1DA100A76262 /* ffitarget_i386.h */, - DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */, - ); - path = include; - sourceTree = ""; - }; - DBFA7188187F1DA100A76262 /* src */ = { - isa = PBXGroup; - children = ( - DBFA7189187F1DA100A76262 /* x86 */, - ); - path = src; - sourceTree = ""; - }; - DBFA7189187F1DA100A76262 /* x86 */ = { - isa = PBXGroup; - children = ( - DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */, - DBFA718B187F1DA100A76262 /* darwin_i386.S */, - DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */, - DBFA718D187F1DA100A76262 /* ffi_i386.c */, - ); - path = x86; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - DB13B18F1849DF510010F42D /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */, - DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */, - DBFA714A187F1D8600A76262 /* ffi.h in Headers */, - DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */, - DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */, - DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */, - DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */, - DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */, - DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */, - DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - DB13B1651849DF1E0010F42D /* libffi-iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */; - buildPhases = ( - DB13B3051849E01C0010F42D /* ShellScript */, - DB13B1621849DF1E0010F42D /* Sources */, - DB13B1641849DF1E0010F42D /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "libffi-iOS"; - productName = ffi; - productReference = DB13B1661849DF1E0010F42D /* libffi.a */; - productType = "com.apple.product-type.library.static"; - }; - DB13B1901849DF510010F42D /* libffi-Mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */; - buildPhases = ( - DB13B3061849E0490010F42D /* ShellScript */, - DB13B18D1849DF510010F42D /* Sources */, - DB13B18F1849DF510010F42D /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "libffi-Mac"; - productName = ffi; - productReference = DB13B1911849DF510010F42D /* ffi.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - DB13B15C1849DEB70010F42D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0510; - }; - buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = DB13B15B1849DEB70010F42D; - productRefGroup = DB13B1671849DF1E0010F42D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DB13B1651849DF1E0010F42D /* libffi-iOS */, - DB13B1901849DF510010F42D /* libffi-Mac */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXShellScriptBuildPhase section */ - DB13B3051849E01C0010F42D /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios"; - }; - DB13B3061849E0490010F42D /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - DB13B1621849DF1E0010F42D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */, - DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */, - DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */, - DBFA714E187F1D8600A76262 /* closures.c in Sources */, - DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */, - DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */, - DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */, - DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */, - DBFA7158187F1D8600A76262 /* raw_api.c in Sources */, - DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */, - DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */, - DBFA715A187F1D8600A76262 /* types.c in Sources */, - DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DB13B18D1849DF510010F42D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */, - DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */, - DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */, - DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */, - DBFA715B187F1D8600A76262 /* types.c in Sources */, - DBFA7159187F1D8600A76262 /* raw_api.c in Sources */, - DBFA714F187F1D8600A76262 /* closures.c in Sources */, - DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - DB13B1601849DEB70010F42D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_common/include", - ); - ONLY_ACTIVE_ARCH = YES; - }; - name = Debug; - }; - DB13B1611849DEB70010F42D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_common/include", - ); - }; - name = Release; - }; - DB13B1871849DF1E0010F42D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DSTROOT = /tmp/ffi.dst; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_ios/include", - ); - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = ffi; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - DB13B1881849DF1E0010F42D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DSTROOT = /tmp/ffi.dst; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_ios/include", - ); - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = ffi; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - DB13B1B11849DF520010F42D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_osx/include", - ); - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; - PRODUCT_NAME = ffi; - SDKROOT = macosx; - }; - name = Debug; - }; - DB13B1B21849DF520010F42D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "darwin_osx/include", - ); - MACOSX_DEPLOYMENT_TARGET = 10.6; - OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; - PRODUCT_NAME = ffi; - SDKROOT = macosx; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DB13B1601849DEB70010F42D /* Debug */, - DB13B1611849DEB70010F42D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DB13B1871849DF1E0010F42D /* Debug */, - DB13B1881849DF1E0010F42D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DB13B1B11849DF520010F42D /* Debug */, - DB13B1B21849DF520010F42D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = DB13B15C1849DEB70010F42D /* Project object */; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/libtool-ldflags b/ruby/ext/fiddle/libffi-3.2.1/libtool-ldflags deleted file mode 100755 index e32e37bf1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/libtool-ldflags +++ /dev/null @@ -1,106 +0,0 @@ -#! /bin/sh - -# Script to translate LDFLAGS into a form suitable for use with libtool. - -# Copyright (C) 2005 Free Software Foundation, Inc. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. - -# Contributed by CodeSourcery, LLC. - -# This script is designed to be used from a Makefile that uses libtool -# to build libraries as follows: -# -# LTLDFLAGS = $(shell libtool-ldflags $(LDFLAGS)) -# -# Then, use (LTLDFLAGS) in place of $(LDFLAGS) in your link line. - -# The output of the script. This string is built up as we process the -# arguments. -result= -prev_arg= - -for arg -do - case $arg in - -f*|--*) - # Libtool does not ascribe any special meaning options - # that begin with -f or with a double-dash. So, it will - # think these options are linker options, and prefix them - # with "-Wl,". Then, the compiler driver will ignore the - # options. So, we prefix these options with -Xcompiler to - # make clear to libtool that they are in fact compiler - # options. - case $prev_arg in - -Xpreprocessor|-Xcompiler|-Xlinker) - # This option is already prefixed; don't prefix it again. - ;; - *) - result="$result -Xcompiler" - ;; - esac - ;; - *) - # We do not want to add -Xcompiler to other options because - # that would prevent libtool itself from recognizing them. - ;; - esac - prev_arg=$arg - - # If $(LDFLAGS) is (say): - # a "b'c d" e - # then the user expects that: - # $(LD) $(LDFLAGS) - # will pass three arguments to $(LD): - # 1) a - # 2) b'c d - # 3) e - # We must ensure, therefore, that the arguments are appropriately - # quoted so that using: - # libtool --mode=link ... $(LTLDFLAGS) - # will result in the same number of arguments being passed to - # libtool. In other words, when this script was invoked, the shell - # removed one level of quoting, present in $(LDFLAGS); we have to put - # it back. - - # Quote any embedded single quotes. - case $arg in - *"'"*) - # The following command creates the script: - # 1s,^X,,;s|'|'"'"'|g - # which removes a leading X, and then quotes and embedded single - # quotes. - sed_script="1s,^X,,;s|'|'\"'\"'|g" - # Add a leading "X" so that if $arg starts with a dash, - # the echo command will not try to interpret the argument - # as a command-line option. - arg="X$arg" - # Generate the quoted string. - quoted_arg=`echo "$arg" | sed -e "$sed_script"` - ;; - *) - quoted_arg=$arg - ;; - esac - # Surround the entire argument with single quotes. - quoted_arg="'"$quoted_arg"'" - - # Add it to the string. - result="$result $quoted_arg" -done - -# Output the string we have built up. -echo "$result" diff --git a/ruby/ext/fiddle/libffi-3.2.1/libtool-version b/ruby/ext/fiddle/libffi-3.2.1/libtool-version deleted file mode 100644 index 149a51a2a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/libtool-version +++ /dev/null @@ -1,29 +0,0 @@ -# This file is used to maintain libtool version info for libffi. See -# the libtool manual to understand the meaning of the fields. This is -# a separate file so that version updates don't involve re-running -# automake. -# -# Here are a set of rules to help you update your library version -# information: -# -# 1. Start with version information of `0:0:0' for each libtool library. -# -# 2. Update the version information only immediately before a public -# release of your software. More frequent updates are unnecessary, -# and only guarantee that the current interface number gets larger -# faster. -# -# 3. If the library source code has changed at all since the last -# update, then increment revision (`c:r:a' becomes `c:r+1:a'). -# -# 4. If any interfaces have been added, removed, or changed since the -# last update, increment current, and set revision to 0. -# -# 5. If any interfaces have been added since the last public release, -# then increment age. -# -# 6. If any interfaces have been removed since the last public -# release, then set age to 0. -# -# CURRENT:REVISION:AGE -6:4:0 diff --git a/ruby/ext/fiddle/libffi-3.2.1/ltmain.sh b/ruby/ext/fiddle/libffi-3.2.1/ltmain.sh deleted file mode 100644 index 63ae69dc6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/ltmain.sh +++ /dev/null @@ -1,9655 +0,0 @@ - -# libtool (GNU libtool) 2.4.2 -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . - -PROGRAM=libtool -PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" - fi" -done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL - -$lt_unset CDPATH - - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - - - -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -exit_status=$EXIT_SUCCESS - -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" - -dirname="s,/[^/]*$,," -basename="s,^.*/,," - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation - - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation - - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation - - -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' - -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () -{ - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi - - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} - -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result - -# Make sure we have an absolute path for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=$func_dirname_result - progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" - ;; - *) - save_IFS="$IFS" - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS="$save_IFS" - test -x "$progdir/$progname" && break - done - IFS="$save_IFS" - test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' - -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" - -# Standard options: -opt_dry_run=false -opt_help=false -opt_quiet=false -opt_verbose=false -opt_warning=: - -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} - -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} - -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 - - # bash bug again: - : -} - -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" -} -help="Try \`$progname --help' for more information." ## default - - -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - my_directory_path="$1" - my_dir_list= - - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" - - # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` - done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : - done - IFS="$save_mkdir_p_IFS" - - # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" - fi -} - - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$opt_dry_run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" - fi - - $ECHO "$my_tmpdir" -} - - -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () -{ - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac - - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" - ;; - *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" - esac -} - - -# func_quote_for_expand arg -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - case $1 in - *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; - *) - my_arg="$1" ;; - esac - - case $my_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" - ;; - esac - - func_quote_for_expand_result="$my_arg" -} - - -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - - -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_version -# Echo version message to standard output and exit. -func_version () -{ - $opt_debug - - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? -} - -# func_usage -# Echo short help message to standard output and exit. -func_usage () -{ - $opt_debug - - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? -} - -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. -func_help () -{ - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi -} - -# func_missing_arg argname -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $opt_debug - - func_error "missing argument for $1." - exit_cmd=exit -} - - -# func_split_short_opt shortopt -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () -{ - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' - - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation - - -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () -{ - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' - - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation - -exit_cmd=: - - - - - -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" - -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation - -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () -{ - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation - - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation - - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation - - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation - - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation - - -# func_fatal_configuration arg... -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." -} - - -# func_config -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - -# func_features -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - -# func_enable_tag tagname -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname="$1" - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - -# func_check_version_match -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - - - -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false - - -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; - esac - done - - # Validate options: - - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } - - - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE -} - - - - -## ----------- ## -## Main. ## -## ----------- ## - -# func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case "$lalib_p_line" in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test "$lalib_p" = yes -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - func_lalib_p "$1" -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $opt_debug - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$save_ifs - eval cmd=\"$cmd\" - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. -func_source () -{ - $opt_debug - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case "$lt_sysroot:$1" in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $opt_debug - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' - else - write_lobj=none - fi - - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $opt_debug - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $opt_debug - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $opt_debug - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $opt_debug - if test -z "$2" && test -n "$1" ; then - func_error "Could not determine host file name corresponding to" - func_error " \`$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result="$1" - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $opt_debug - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " \`$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result="$3" - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $opt_debug - case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via `$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $opt_debug - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $opt_debug - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result="$1" -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via `$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $opt_debug - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $opt_debug - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result="$1" -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_mode_compile arg... -func_mode_compile () -{ - $opt_debug - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - func_append_quoted lastarg "$arg" - done - IFS="$save_ifs" - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with \`-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj="$func_basename_result" - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from \`$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test "$pic_mode" != no; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test "$compiler_c_o" = yes; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode \`$opt_mode'" - ;; - esac - - echo - $ECHO "Try \`$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test "$opt_help" = :; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - sed '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $opt_debug - # The first argument is the command name. - cmd="$nonopt" - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "\`$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir="$func_dirname_result" - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir="$func_dirname_result" - ;; - - *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file="$progdir/$program" - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if test "X$opt_dry_run" = Xfalse; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $opt_debug - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "\`$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument \`$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $opt_debug - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "\`$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir="$func_dirname_result" - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking \`$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname="$1" - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme="$stripme" - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme="" - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - $opt_dry_run || { - if test "$finalize" = yes; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_silent || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink \`$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file="$outputname" - else - func_warning "cannot relink \`$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name="$func_basename_result" - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = install && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $opt_dry_run || { - $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" - func_basename "$dlprefile" - name="$func_basename_result" - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' - - # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $opt_debug - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s,.*,import, - p - q - } - }'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $opt_debug - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $opt_debug - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result="" - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $opt_debug - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib="$func_basename_result" - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result="$my_oldobjs" -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -/* declarations of non-ANSI functions */ -#if defined(__MINGW32__) -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined(__CYGWIN__) -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined (other platforms) ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined(__CYGWIN__) -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ -#endif - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -#if defined(LT_DEBUGWRAPPER) -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp (str, pat) == 0) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - int len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - int orig_value_len = strlen (orig_value); - int add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - int len = strlen (new_value); - while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[len-1] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $opt_debug - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $opt_debug - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=no - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module="${wl}-single_module" - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir="$arg" - prev= - continue - ;; - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file \`$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" - else - func_fatal_error "need path for \`-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module="${wl}-multi_module" - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs="$tmp_deplibs" - fi - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; - esac - fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs="$dlprefiles" - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test "$linkmode" = lib; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "\`-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - ;; - esac - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" - fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib="$l" - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" - fi - ;; - esac - func_basename "$lib" - laname="$func_basename_result" - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" - fi - case "$host" in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test "$installed" = no; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" - break - fi - done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - echo - if test "$linkmode" = prog; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname="$1" - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc*) - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - func_basename "$soroot" - soname="$func_basename_result" - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from \`$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$opt_mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - elif test -n "$old_library"; then - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$opt_mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path="$deplib" ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" - path= - fi - fi - ;; - *) - path="-L$absdir/$objdir" - ;; - esac - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" - - path="-L$absdir" - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "\`-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" - - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" - - install_libdir="$1" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - shift - IFS="$save_ifs" - - test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$1" - number_minor="$2" - number_revision="$3" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_minor" - lt_irix_increment=no - ;; - esac - ;; - no) - current="$1" - revision="$2" - age="$3" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current" - ;; - - irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - func_append verstring ":${current}.0" - ;; - - qnx) - major=".$current" - versuffix=".$current" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - - *) - func_fatal_configuration "unknown library version type \`$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - fi - - func_generate_dlsyms "$libname" "$libname" "yes" - func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= - - if test "$opt_mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs="$new_libs" - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname="$1" - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols="$export_symbols" - export_symbols= - always_export_symbols=yes - fi - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd1 in $cmds; do - IFS="$save_ifs" - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test "$try_normal_branch" = yes \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=${output_objdir}/${output_la}.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test "$compiler_needs_object" = yes; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test "X$objlist" = X || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - fi - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - if ${skipped_export-false}; then - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - fi - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "\`-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - else - gentop="$output_objdir/${obj}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "\`-release' is ignored for programs" - - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=yes - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no - ;; - *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - esac - if test "$wrappers_required" = no; then - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' - fi - - exit $exit_status - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase="$func_basename_result" - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name="$func_basename_result" - func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles="$newdlprefiles" - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that can not go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $opt_debug - RM="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" - else - odir="$dir/$objdir" - fi - func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" - - # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case "$opt_mode" in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$opt_mode" = clean ; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} - -test -z "$opt_mode" && { - help="$generic_help" - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: -# vi:sw=2 - diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/asmcfi.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/asmcfi.m4 deleted file mode 100644 index dbf73a0b3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/asmcfi.m4 +++ /dev/null @@ -1,13 +0,0 @@ -AC_DEFUN([GCC_AS_CFI_PSEUDO_OP], -[AC_CACHE_CHECK([assembler .cfi pseudo-op support], - gcc_cv_as_cfi_pseudo_op, [ - gcc_cv_as_cfi_pseudo_op=unknown - AC_TRY_COMPILE([asm (".cfi_startproc\n\t.cfi_endproc");],, - [gcc_cv_as_cfi_pseudo_op=yes], - [gcc_cv_as_cfi_pseudo_op=no]) - ]) - if test "x$gcc_cv_as_cfi_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_CFI_PSEUDO_OP, 1, - [Define if your assembler supports .cfi_* directives.]) - fi -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_append_flag.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_append_flag.m4 deleted file mode 100644 index 1d38b76fb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_append_flag.m4 +++ /dev/null @@ -1,69 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) -# -# DESCRIPTION -# -# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space -# added in between. -# -# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. -# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains -# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly -# FLAG. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 2 - -AC_DEFUN([AX_APPEND_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl -AS_VAR_SET_IF(FLAGS, - [case " AS_VAR_GET(FLAGS) " in - *" $1 "*) - AC_RUN_LOG([: FLAGS already contains $1]) - ;; - *) - AC_RUN_LOG([: FLAGS="$FLAGS $1"]) - AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) - ;; - esac], - [AS_VAR_SET(FLAGS,["$1"])]) -AS_VAR_POPDEF([FLAGS])dnl -])dnl AX_APPEND_FLAG diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cc_maxopt.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cc_maxopt.m4 deleted file mode 100644 index 62e3b5330..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cc_maxopt.m4 +++ /dev/null @@ -1,181 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cc_maxopt.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CC_MAXOPT -# -# DESCRIPTION -# -# Try to turn on "good" C optimization flags for various compilers and -# architectures, for some definition of "good". (In our case, good for -# FFTW and hopefully for other scientific codes. Modify as needed.) -# -# The user can override the flags by setting the CFLAGS environment -# variable. The user can also specify --enable-portable-binary in order to -# disable any optimization flags that might result in a binary that only -# runs on the host architecture. -# -# Note also that the flags assume that ANSI C aliasing rules are followed -# by the code (e.g. for gcc's -fstrict-aliasing), and that floating-point -# computations can be re-ordered as needed. -# -# Requires macros: AX_CHECK_COMPILE_FLAG, AX_COMPILER_VENDOR, -# AX_GCC_ARCHFLAG, AX_GCC_X86_CPUID. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 13 - -AC_DEFUN([AX_CC_MAXOPT], -[ -AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AX_COMPILER_VENDOR]) -AC_REQUIRE([AC_CANONICAL_HOST]) - -AC_ARG_ENABLE(portable-binary, [AS_HELP_STRING([--enable-portable-binary], [disable compiler optimizations that would produce unportable binaries])], - acx_maxopt_portable=$enableval, acx_maxopt_portable=no) - -# Try to determine "good" native compiler flags if none specified via CFLAGS -if test "$ac_test_CFLAGS" != "set"; then - CFLAGS="" - case $ax_cv_c_compiler_vendor in - dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host" - if test "x$acx_maxopt_portable" = xno; then - CFLAGS="$CFLAGS -arch host" - fi;; - - sun) CFLAGS="-native -fast -xO5 -dalign" - if test "x$acx_maxopt_portable" = xyes; then - CFLAGS="$CFLAGS -xarch=generic" - fi;; - - hp) CFLAGS="+Oall +Optrs_ansi +DSnative" - if test "x$acx_maxopt_portable" = xyes; then - CFLAGS="$CFLAGS +DAportable" - fi;; - - ibm) if test "x$acx_maxopt_portable" = xno; then - xlc_opt="-qarch=auto -qtune=auto" - else - xlc_opt="-qtune=auto" - fi - AX_CHECK_COMPILE_FLAG($xlc_opt, - CFLAGS="-O3 -qansialias -w $xlc_opt", - [CFLAGS="-O3 -qansialias -w" - echo "******************************************************" - echo "* You seem to have the IBM C compiler. It is *" - echo "* recommended for best performance that you use: *" - echo "* *" - echo "* CFLAGS=-O3 -qarch=xxx -qtune=xxx -qansialias -w *" - echo "* ^^^ ^^^ *" - echo "* where xxx is pwr2, pwr3, 604, or whatever kind of *" - echo "* CPU you have. (Set the CFLAGS environment var. *" - echo "* and re-run configure.) For more info, man cc. *" - echo "******************************************************"]) - ;; - - intel) CFLAGS="-O3 -ansi_alias" - if test "x$acx_maxopt_portable" = xno; then - icc_archflag=unknown - icc_flags="" - case $host_cpu in - i686*|x86_64*) - # icc accepts gcc assembly syntax, so these should work: - AX_GCC_X86_CPUID(0) - AX_GCC_X86_CPUID(1) - case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG - *:756e6547:*:*) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *6a?:*[[234]]:*:*|*6[[789b]]?:*:*:*) icc_flags="-xK";; - *f3[[347]]:*:*:*|*f4[1347]:*:*:*) icc_flags="-xP -xN -xW -xK";; - *f??:*:*:*) icc_flags="-xN -xW -xK";; - esac ;; - esac ;; - esac - if test "x$icc_flags" != x; then - for flag in $icc_flags; do - AX_CHECK_COMPILE_FLAG($flag, [icc_archflag=$flag; break]) - done - fi - AC_MSG_CHECKING([for icc architecture flag]) - AC_MSG_RESULT($icc_archflag) - if test "x$icc_archflag" != xunknown; then - CFLAGS="$CFLAGS $icc_archflag" - fi - fi - ;; - - gnu) - # default optimization flags for gcc on all systems - CFLAGS="-O3 -fomit-frame-pointer" - - # -malign-double for x86 systems - # LIBFFI -- DON'T DO THIS - CHANGES ABI - # AX_CHECK_COMPILE_FLAG(-malign-double, CFLAGS="$CFLAGS -malign-double") - - # -fstrict-aliasing for gcc-2.95+ - AX_CHECK_COMPILE_FLAG(-fstrict-aliasing, - CFLAGS="$CFLAGS -fstrict-aliasing") - - # note that we enable "unsafe" fp optimization with other compilers, too - AX_CHECK_COMPILE_FLAG(-ffast-math, CFLAGS="$CFLAGS -ffast-math") - - AX_GCC_ARCHFLAG($acx_maxopt_portable) - ;; - esac - - if test -z "$CFLAGS"; then - echo "" - echo "********************************************************" - echo "* WARNING: Don't know the best CFLAGS for this system *" - echo "* Use ./configure CFLAGS=... to specify your own flags *" - echo "* (otherwise, a default of CFLAGS=-O3 will be used) *" - echo "********************************************************" - echo "" - CFLAGS="-O3" - fi - - AX_CHECK_COMPILE_FLAG($CFLAGS, [], [ - echo "" - echo "********************************************************" - echo "* WARNING: The guessed CFLAGS don't seem to work with *" - echo "* your compiler. *" - echo "* Use ./configure CFLAGS=... to specify your own flags *" - echo "********************************************************" - echo "" - CFLAGS="" - ]) - -fi -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cflags_warn_all.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cflags_warn_all.m4 deleted file mode 100644 index 0fa3e186b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_cflags_warn_all.m4 +++ /dev/null @@ -1,122 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] -# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] -# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] -# -# DESCRIPTION -# -# Try to find a compiler option that enables most reasonable warnings. -# -# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result -# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default. -# -# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX, -# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and -# Intel compilers. For a given compiler, the Fortran flags are much more -# experimental than their C equivalents. -# -# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS -# - $2 add-value-if-not-found : nothing -# - $3 action-if-found : add value to shellvariable -# - $4 action-if-not-found : nothing -# -# NOTE: These macros depend on AX_APPEND_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2010 Rhys Ulerich -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 14 - -AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl -AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl -AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl -AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings], -VAR,[VAR="no, unknown" -ac_save_[]FLAGS="$[]FLAGS" -for ac_arg dnl -in "-warn all % -warn all" dnl Intel - "-pedantic % -Wall" dnl GCC - "-xstrconst % -v" dnl Solaris C - "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix - "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX - "-ansi -ansiE % -fullwarn" dnl IRIX - "+ESlit % +w1" dnl HP-UX C - "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10) - "-h conform % -h msglevel 2" dnl Cray C (Unicos) - # -do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` - AC_COMPILE_IFELSE([AC_LANG_PROGRAM], - [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) -done -FLAGS="$ac_save_[]FLAGS" -]) -AS_VAR_POPDEF([FLAGS])dnl -AC_REQUIRE([AX_APPEND_FLAG]) -case ".$VAR" in - .ok|.ok,*) m4_ifvaln($3,$3) ;; - .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; - *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;; -esac -AS_VAR_POPDEF([VAR])dnl -])dnl AX_FLAGS_WARN_ALL -dnl implementation tactics: -dnl the for-argument contains a list of options. The first part of -dnl these does only exist to detect the compiler - usually it is -dnl a global option to enable -ansi or -extrawarnings. All other -dnl compilers will fail about it. That was needed since a lot of -dnl compilers will give false positives for some option-syntax -dnl like -Woption or -Xoption as they think of it is a pass-through -dnl to later compile stages or something. The "%" is used as a -dnl delimiter. A non-option comment can be given after "%%" marks -dnl which will be shown but not added to the respective C/CXXFLAGS. - -AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl -AC_LANG_PUSH([C]) -AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) -AC_LANG_POP([C]) -]) - -AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl -AC_LANG_PUSH([C++]) -AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) -AC_LANG_POP([C++]) -]) - -AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl -AC_LANG_PUSH([Fortran]) -AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) -AC_LANG_POP([Fortran]) -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_check_compile_flag.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_check_compile_flag.m4 deleted file mode 100644 index c3a8d695a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,72 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 2 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_compiler_vendor.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_compiler_vendor.m4 deleted file mode 100644 index 73e32ea9e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_compiler_vendor.m4 +++ /dev/null @@ -1,84 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_COMPILER_VENDOR -# -# DESCRIPTION -# -# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, -# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, -# watcom, etc. The vendor is returned in the cache variable -# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 11 - -AC_DEFUN([AX_COMPILER_VENDOR], -[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, - [# note: don't check for gcc first since some other compilers define __GNUC__ - vendors="intel: __ICC,__ECC,__INTEL_COMPILER - ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ - pathscale: __PATHCC__,__PATHSCALE__ - clang: __clang__ - gnu: __GNUC__ - sun: __SUNPRO_C,__SUNPRO_CC - hp: __HP_cc,__HP_aCC - dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER - borland: __BORLANDC__,__TURBOC__ - comeau: __COMO__ - cray: _CRAYC - kai: __KCC - lcc: __LCC__ - sgi: __sgi,sgi - microsoft: _MSC_VER - metrowerks: __MWERKS__ - watcom: __WATCOMC__ - portland: __PGI - unknown: UNKNOWN" - for ventest in $vendors; do - case $ventest in - *:) vendor=$ventest; continue ;; - *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; - esac - AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ - #if !($vencpp) - thisisanerror; - #endif - ])], [break]) - done - ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` - ]) -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_configure_args.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_configure_args.m4 deleted file mode 100644 index 0726b1bc8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_configure_args.m4 +++ /dev/null @@ -1,70 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_configure_args.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CONFIGURE_ARGS -# -# DESCRIPTION -# -# Helper macro for AX_ENABLE_BUILDDIR. -# -# The traditional way of starting a subdir-configure is running the script -# with ${1+"$@"} but since autoconf 2.60 this is broken. Instead we have -# to rely on eval'ing $ac_configure_args however some old autoconf -# versions do not provide that. To ensure maximum portability of autoconf -# extension macros this helper can be AC_REQUIRE'd so that -# $ac_configure_args will alsways be present. -# -# Sadly, the traditional "exec $SHELL" of the enable_builddir macros is -# spoiled now and must be replaced by "eval + exit $?". -# -# Example: -# -# AC_DEFUN([AX_ENABLE_SUBDIR],[dnl -# AC_REQUIRE([AX_CONFIGURE_ARGS])dnl -# eval $SHELL $ac_configure_args || exit $? -# ...]) -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 9 - -AC_DEFUN([AX_CONFIGURE_ARGS],[ - # [$]@ is unsable in 2.60+ but earlier autoconf had no ac_configure_args - if test "${ac_configure_args+set}" != "set" ; then - ac_configure_args= - for ac_arg in ${1+"[$]@"}; do - ac_configure_args="$ac_configure_args '$ac_arg'" - done - fi -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_enable_builddir.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_enable_builddir.m4 deleted file mode 100644 index 3cb209371..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_enable_builddir.m4 +++ /dev/null @@ -1,301 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_enable_builddir.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_ENABLE_BUILDDIR [(dirstring-or-command [,Makefile.mk [,-all]])] -# -# DESCRIPTION -# -# If the current configure was run within the srcdir then we move all -# configure-files into a subdir and let the configure steps continue -# there. We provide an option --disable-builddir to suppress the move into -# a separate builddir. -# -# Defaults: -# -# $1 = $host (overridden with $HOST) -# $2 = Makefile.mk -# $3 = -all -# -# This macro must be called before AM_INIT_AUTOMAKE. It creates a default -# toplevel srcdir Makefile from the information found in the created -# toplevel builddir Makefile. It just copies the variables and -# rule-targets, each extended with a default rule-execution that recurses -# into the build directory of the current "HOST". You can override the -# auto-dection through `config.guess` and build-time of course, as in -# -# make HOST=i386-mingw-cross -# -# which can of course set at configure time as well using -# -# configure --host=i386-mingw-cross -# -# After the default has been created, additional rules can be appended -# that will not just recurse into the subdirectories and only ever exist -# in the srcdir toplevel makefile - these parts are read from the $2 = -# Makefile.mk file -# -# The automatic rules are usually scanning the toplevel Makefile for lines -# like '#### $host |$builddir' to recognize the place where to recurse -# into. Usually, the last one is the only one used. However, almost all -# targets have an additional "*-all" rule which makes the script to -# recurse into _all_ variants of the current HOST (!!) setting. The "-all" -# suffix can be overriden for the macro as well. -# -# a special rule is only given for things like "dist" that will copy the -# tarball from the builddir to the sourcedir (or $(PUB)) for reason of -# convenience. -# -# LICENSE -# -# Copyright (c) 2009 Guido U. Draheim -# Copyright (c) 2009 Alan Jenkins -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 23 - -AC_DEFUN([AX_ENABLE_BUILDDIR],[ -AC_REQUIRE([AC_CANONICAL_HOST])[]dnl -AC_REQUIRE([AX_CONFIGURE_ARGS])[]dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])[]dnl -AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl -AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl -AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl -AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl -SUB="." -AC_ARG_ENABLE([builddir], AS_HELP_STRING( - [--disable-builddir],[disable automatic build in subdir of sources]) - ,[SUB="$enableval"], [SUB="auto"]) -if test ".$ac_srcdir_defaulted" != ".no" ; then -if test ".$srcdir" = ".." ; then - if test -f config.status ; then - AC_MSG_NOTICE(toplevel srcdir already configured... skipping subdir build) - else - test ".$SUB" = "." && SUB="." - test ".$SUB" = ".no" && SUB="." - test ".$TARGET" = "." && TARGET="$target" - test ".$SUB" = ".auto" && SUB="m4_ifval([$1], [$1],[$TARGET])" - if test ".$SUB" != ".." ; then # we know where to go and - AS_MKDIR_P([$SUB]) - echo __.$SUB.__ > $SUB/conftest.tmp - cd $SUB - if grep __.$SUB.__ conftest.tmp >/dev/null 2>/dev/null ; then - rm conftest.tmp - AC_MSG_RESULT([continue configure in default builddir "./$SUB"]) - else - AC_MSG_ERROR([could not change to default builddir "./$SUB"]) - fi - srcdir=`echo "$SUB" | - sed -e 's,^\./,,;s,[[^/]]$,&/,;s,[[^/]]*/,../,g;s,[[/]]$,,;'` - # going to restart from subdirectory location - test -f $srcdir/config.log && mv $srcdir/config.log . - test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h . - test -f $srcdir/conftest.log && mv $srcdir/conftest.log . - test -f $srcdir/$cache_file && mv $srcdir/$cache_file . - AC_MSG_RESULT(....exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"}) - case "[$]0" in # restart - [[\\/]]* | ?:[[\\/]]*) # Asbolute name - eval $SHELL "'[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; - *) eval $SHELL "'$srcdir/[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; - esac ; exit $? - fi - fi -fi fi -test ".$SUB" = ".auto" && SUB="." -dnl ac_path_prog uses "set dummy" to override $@ which would defeat the "exec" -AC_PATH_PROG(SED,gsed sed, sed) -AUX="$am_aux_dir" -AS_VAR_POPDEF([SED])dnl -AS_VAR_POPDEF([AUX])dnl -AS_VAR_POPDEF([SUB])dnl -AC_CONFIG_COMMANDS([buildir],[dnl .............. config.status .............. -AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl -AS_VAR_PUSHDEF([TOP],[top_srcdir])dnl -AS_VAR_PUSHDEF([SRC],[ac_top_srcdir])dnl -AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl -AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl -pushdef([END],[Makefile.mk])dnl -pushdef([_ALL],[ifelse([$3],,[-all],[$3])])dnl - SRC="$ax_enable_builddir_srcdir" - if test ".$SUB" = ".." ; then - if test -f "$TOP/Makefile" ; then - AC_MSG_NOTICE([skipping TOP/Makefile - left untouched]) - else - AC_MSG_NOTICE([skipping TOP/Makefile - not created]) - fi - else - if test -f "$SRC/Makefile" ; then - a=`grep "^VERSION " "$SRC/Makefile"` ; b=`grep "^VERSION " Makefile` - test "$a" != "$b" && rm "$SRC/Makefile" - fi - if test -f "$SRC/Makefile" ; then - echo "$SRC/Makefile : $SRC/Makefile.in" > $tmp/conftemp.mk - echo " []@ echo 'REMOVED,,,' >\$[]@" >> $tmp/conftemp.mk - eval "${MAKE-make} -f $tmp/conftemp.mk 2>/dev/null >/dev/null" - if grep '^REMOVED,,,' "$SRC/Makefile" >/dev/null - then rm $SRC/Makefile ; fi - cp $tmp/conftemp.mk $SRC/makefiles.mk~ ## DEBUGGING - fi - if test ! -f "$SRC/Makefile" ; then - AC_MSG_NOTICE([create TOP/Makefile guessed from local Makefile]) - x='`' ; cat >$tmp/conftemp.sed <<_EOF -/^\$/n -x -/^\$/bS -x -/\\\\\$/{H;d;} -{H;s/.*//;x;} -bM -:S -x -/\\\\\$/{h;d;} -{h;s/.*//;x;} -:M -s/\\(\\n\\) /\\1 /g -/^ /d -/^[[ ]]*[[\\#]]/d -/^VPATH *=/d -s/^srcdir *=.*/srcdir = ./ -s/^top_srcdir *=.*/top_srcdir = ./ -/[[:=]]/!d -/^\\./d -dnl Now handle rules (i.e. lines containing ":" but not " = "). -/ = /b -/ .= /b -/:/!b -s/:.*/:/ -s/ / /g -s/ \\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/ \\1 \\1[]_ALL\\2/g -s/^\\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/\\1 \\1[]_ALL\\2/ -s/ / /g -/^all all[]_ALL[[ :]]/i\\ -all-configured : all[]_ALL -dnl dist-all exists... and would make for dist-all-all -s/ [[a-zA-Z0-9-]]*[]_ALL [[a-zA-Z0-9-]]*[]_ALL[]_ALL//g -/[]_ALL[]_ALL/d -a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$n * \$\@"; if test "\$\$n" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^####.*|" Makefile |tail -1| sed -e 's/.*|//' $x ; fi \\\\\\ - ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ - ; test "\$\$use" = "\$\@" && BUILD=$x echo "\$\$BUILD" | tail -1 $x \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; (cd "\$\$i" && test ! -f configure && \$(MAKE) \$\$use) || exit; done -dnl special rule add-on: "dist" copies the tarball to $(PUB). (source tree) -/dist[]_ALL *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).tar.*" \\\\\\ - ; if test "\$\$found" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ - ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).tar.* \\\\\\ - ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done -dnl special rule add-on: "dist-foo" copies all the archives to $(PUB). (source tree) -/dist-[[a-zA-Z0-9]]*[]_ALL *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh ./config.guess $x \\\\\\ - ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ - ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).*" \\\\\\ - ; if test "\$\$found" -eq "0" ; then : \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ - ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).* \\\\\\ - ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done -dnl special rule add-on: "distclean" removes all local builddirs completely -/distclean[]_ALL *:/a\\ - @ HOST="\$(HOST)\" \\\\\\ - ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ - ; BUILD=$x grep "^#### .*|" Makefile | sed -e 's/.*|//' $x \\\\\\ - ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ - ; echo "MAKE \$\$HOST : \$\$n * \$\@ (all local builds)" \\\\\\ - ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; echo "# rm -r \$\$i"; done ; echo "# (sleep 3)" ; sleep 3 \\\\\\ - ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ - ; echo "\$\$i" | grep "^/" > /dev/null && continue \\\\\\ - ; echo "\$\$i" | grep "^../" > /dev/null && continue \\\\\\ - ; echo "rm -r \$\$i"; (rm -r "\$\$i") ; done ; rm Makefile -_EOF - cp "$tmp/conftemp.sed" "$SRC/makefile.sed~" ## DEBUGGING - $SED -f $tmp/conftemp.sed Makefile >$SRC/Makefile - if test -f "$SRC/m4_ifval([$2],[$2],[END])" ; then - AC_MSG_NOTICE([extend TOP/Makefile with TOP/m4_ifval([$2],[$2],[END])]) - cat $SRC/END >>$SRC/Makefile - fi ; xxxx="####" - echo "$xxxx CONFIGURATIONS FOR TOPLEVEL MAKEFILE: " >>$SRC/Makefile - # sanity check - if grep '^; echo "MAKE ' $SRC/Makefile >/dev/null ; then - AC_MSG_NOTICE([buggy sed found - it deletes tab in "a" text parts]) - $SED -e '/^@ HOST=/s/^/ /' -e '/^; /s/^/ /' $SRC/Makefile \ - >$SRC/Makefile~ - (test -s $SRC/Makefile~ && mv $SRC/Makefile~ $SRC/Makefile) 2>/dev/null - fi - else - xxxx="\\#\\#\\#\\#" - # echo "/^$xxxx *$ax_enable_builddir_host /d" >$tmp/conftemp.sed - echo "s!^$xxxx [[^|]]* | *$SUB *\$!$xxxx ...... $SUB!" >$tmp/conftemp.sed - $SED -f "$tmp/conftemp.sed" "$SRC/Makefile" >$tmp/mkfile.tmp - cp "$tmp/conftemp.sed" "$SRC/makefiles.sed~" ## DEBUGGING - cp "$tmp/mkfile.tmp" "$SRC/makefiles.out~" ## DEBUGGING - if cmp -s "$SRC/Makefile" "$tmp/mkfile.tmp" 2>/dev/null ; then - AC_MSG_NOTICE([keeping TOP/Makefile from earlier configure]) - rm "$tmp/mkfile.tmp" - else - AC_MSG_NOTICE([reusing TOP/Makefile from earlier configure]) - mv "$tmp/mkfile.tmp" "$SRC/Makefile" - fi - fi - AC_MSG_NOTICE([build in $SUB (HOST=$ax_enable_builddir_host)]) - xxxx="####" - echo "$xxxx" "$ax_enable_builddir_host" "|$SUB" >>$SRC/Makefile - fi -popdef([END])dnl -AS_VAR_POPDEF([SED])dnl -AS_VAR_POPDEF([AUX])dnl -AS_VAR_POPDEF([SRC])dnl -AS_VAR_POPDEF([TOP])dnl -AS_VAR_POPDEF([SUB])dnl -],[dnl -ax_enable_builddir_srcdir="$srcdir" # $srcdir -ax_enable_builddir_host="$HOST" # $HOST / $host -ax_enable_builddir_version="$VERSION" # $VERSION -ax_enable_builddir_package="$PACKAGE" # $PACKAGE -ax_enable_builddir_auxdir="$ax_enable_builddir_auxdir" # $AUX -ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED -ax_enable_builddir="$ax_enable_builddir" # $SUB -])dnl -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_archflag.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_archflag.m4 deleted file mode 100644 index aab2661c3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_archflag.m4 +++ /dev/null @@ -1,225 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) -# -# DESCRIPTION -# -# This macro tries to guess the "native" arch corresponding to the target -# architecture for use with gcc's -march=arch or -mtune=arch flags. If -# found, the cache variable $ax_cv_gcc_archflag is set to this flag and -# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to -# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is -# to add $ax_cv_gcc_archflag to the end of $CFLAGS. -# -# PORTABLE? should be either [yes] (default) or [no]. In the former case, -# the flag is set to -mtune (or equivalent) so that the architecture is -# only used for tuning, but the instruction set used is still portable. In -# the latter case, the flag is set to -march (or equivalent) so that -# architecture-specific instructions are enabled. -# -# The user can specify --with-gcc-arch= in order to override the -# macro's choice of architecture, or --without-gcc-arch to disable this. -# -# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is -# called unless the user specified --with-gcc-arch manually. -# -# Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID -# -# (The main emphasis here is on recent CPUs, on the principle that doing -# high-performance computing on old hardware is uncommon.) -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2012 Tsukasa Oi -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 11 - -AC_DEFUN([AX_GCC_ARCHFLAG], -[AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_CANONICAL_HOST]) - -AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], - ax_gcc_arch=$withval, ax_gcc_arch=yes) - -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT([]) -AC_CACHE_VAL(ax_cv_gcc_archflag, -[ -ax_cv_gcc_archflag="unknown" - -if test "$GCC" = yes; then - -if test "x$ax_gcc_arch" = xyes; then -ax_gcc_arch="" -if test "$cross_compiling" = no; then -case $host_cpu in - i[[3456]]86*|x86_64*) # use cpuid codes - AX_GCC_X86_CPUID(0) - AX_GCC_X86_CPUID(1) - case $ax_cv_gcc_x86_cpuid_0 in - *:756e6547:*:*) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; - *5??:*:*:*) ax_gcc_arch=pentium ;; - *0?6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6[[9de]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; - *0?6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[aef]]?:*:*:*|*2?6[[5cef]]?:*:*:*) ax_gcc_arch="corei7 core2 pentium-m pentium3 pentiumpro" ;; - *1?6c?:*:*:*|*[[23]]?66?:*:*:*) ax_gcc_arch="atom core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[ad]]?:*:*:*) ax_gcc_arch="corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *0?6??:*:*:*) ax_gcc_arch=pentiumpro ;; - *6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; - ?000?f3[[347]]:*:*:*|?000?f4[1347]:*:*:*|?000?f6?:*:*:*) - case $host_cpu in - x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;; - *) ax_gcc_arch="prescott pentium4 pentiumpro" ;; - esac ;; - ?000?f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";; - esac ;; - *:68747541:*:*) # AMD - case $ax_cv_gcc_x86_cpuid_1 in - *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; - *5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; - *5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; - *60?:*:*:*) ax_gcc_arch=k7 ;; - *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; - *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; - *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;; - *6[[68a]]?:*:*:*) - AX_GCC_X86_CPUID(0x80000006) # L2 cache size - case $ax_cv_gcc_x86_cpuid_0x80000006 in - *:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256 - ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; - *) ax_gcc_arch="athlon-4 athlon k7" ;; - esac ;; - ?00??f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; - ?00??f5?:*:*:*) ax_gcc_arch="opteron k8" ;; - ?00??f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;; - ?00??f??:*:*:*) ax_gcc_arch="k8" ;; - ?05??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - ?06??f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; - esac ;; - *:746e6543:*:*) # IDT - case $ax_cv_gcc_x86_cpuid_1 in - *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; - *58?:*:*:*) ax_gcc_arch=winchip2 ;; - *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; - *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;; - esac ;; - esac - if test x"$ax_gcc_arch" = x; then # fallback - case $host_cpu in - i586*) ax_gcc_arch=pentium ;; - i686*) ax_gcc_arch=pentiumpro ;; - esac - fi - ;; - - sparc*) - AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) - cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` - cputype=`echo "$cputype" | tr -d ' -' | sed 's/SPARCIIi/SPARCII/' | tr $as_cr_LETTERS $as_cr_letters` - case $cputype in - *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; - *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; - *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; - *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;; - *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; - *cypress*) ax_gcc_arch=cypress ;; - esac ;; - - alphaev5) ax_gcc_arch=ev5 ;; - alphaev56) ax_gcc_arch=ev56 ;; - alphapca56) ax_gcc_arch="pca56 ev56" ;; - alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; - alphaev6) ax_gcc_arch=ev6 ;; - alphaev67) ax_gcc_arch=ev67 ;; - alphaev68) ax_gcc_arch="ev68 ev67" ;; - alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; - alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; - alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; - - powerpc*) - cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` - cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'` - case $cputype in - *750*) ax_gcc_arch="750 G3" ;; - *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; - *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;; - *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;; - *970*) ax_gcc_arch="970 G5 power4";; - *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; - *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; - 603ev|8240) ax_gcc_arch="$cputype 603e 603";; - *) ax_gcc_arch=$cputype ;; - esac - ax_gcc_arch="$ax_gcc_arch powerpc" - ;; -esac -fi # not cross-compiling -fi # guess arch - -if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then -for arch in $ax_gcc_arch; do - if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code - flags="-mtune=$arch" - # -mcpu=$arch and m$arch generate nonportable code on every arch except - # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. - case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac - else - flags="-march=$arch -mcpu=$arch -m$arch" - fi - for flag in $flags; do - AX_CHECK_COMPILE_FLAG($flag, [ax_cv_gcc_archflag=$flag; break]) - done - test "x$ax_cv_gcc_archflag" = xunknown || break -done -fi - -fi # $GCC=yes -]) -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT($ax_cv_gcc_archflag) -if test "x$ax_cv_gcc_archflag" = xunknown; then - m4_default([$3],:) -else - m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"]) -fi -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_x86_cpuid.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_x86_cpuid.m4 deleted file mode 100644 index 7d46fee02..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ax_gcc_x86_cpuid.m4 +++ /dev/null @@ -1,79 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_X86_CPUID(OP) -# -# DESCRIPTION -# -# On Pentium and later x86 processors, with gcc or a compiler that has a -# compatible syntax for inline assembly instructions, run a small program -# that executes the cpuid instruction with input OP. This can be used to -# detect the CPU type. -# -# On output, the values of the eax, ebx, ecx, and edx registers are stored -# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable -# ax_cv_gcc_x86_cpuid_OP. -# -# If the cpuid instruction fails (because you are running a -# cross-compiler, or because you are not using gcc, or because you are on -# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP -# is set to the string "unknown". -# -# This macro mainly exists to be used in AX_GCC_ARCHFLAG. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 7 - -AC_DEFUN([AX_GCC_X86_CPUID], -[AC_REQUIRE([AC_PROG_CC]) -AC_LANG_PUSH([C]) -AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, - [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ - int op = $1, eax, ebx, ecx, edx; - FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; -])], - [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown])]) -AC_LANG_POP([C]) -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/libtool.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/libtool.m4 deleted file mode 100644 index 56666f0ec..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/libtool.m4 +++ /dev/null @@ -1,7986 +0,0 @@ -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -]) - -# serial 57 LT_INIT - - -# LT_PREREQ(VERSION) -# ------------------ -# Complain and exit if this libtool version is less that VERSION. -m4_defun([LT_PREREQ], -[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, - [m4_default([$3], - [m4_fatal([Libtool version $1 or higher is required], - 63)])], - [$2])]) - - -# _LT_CHECK_BUILDDIR -# ------------------ -# Complain if the absolute build directory name contains unusual characters -m4_defun([_LT_CHECK_BUILDDIR], -[case `pwd` in - *\ * | *\ *) - AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; -esac -]) - - -# LT_INIT([OPTIONS]) -# ------------------ -AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT -AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl -AC_BEFORE([$0], [LT_LANG])dnl -AC_BEFORE([$0], [LT_OUTPUT])dnl -AC_BEFORE([$0], [LTDL_INIT])dnl -m4_require([_LT_CHECK_BUILDDIR])dnl - -dnl Autoconf doesn't catch unexpanded LT_ macros by default: -m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl -m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl -dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 -dnl unless we require an AC_DEFUNed macro: -AC_REQUIRE([LTOPTIONS_VERSION])dnl -AC_REQUIRE([LTSUGAR_VERSION])dnl -AC_REQUIRE([LTVERSION_VERSION])dnl -AC_REQUIRE([LTOBSOLETE_VERSION])dnl -m4_require([_LT_PROG_LTMAIN])dnl - -_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) - -dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -_LT_SETUP - -# Only expand once: -m4_define([LT_INIT]) -])# LT_INIT - -# Old names: -AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) -AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PROG_LIBTOOL], []) -dnl AC_DEFUN([AM_PROG_LIBTOOL], []) - - -# _LT_CC_BASENAME(CC) -# ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -]) - - -# _LT_FILEUTILS_DEFAULTS -# ---------------------- -# It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. -m4_defun([_LT_FILEUTILS_DEFAULTS], -[: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} -])# _LT_FILEUTILS_DEFAULTS - - -# _LT_SETUP -# --------- -m4_defun([_LT_SETUP], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl - -_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl -dnl -_LT_DECL([], [host_alias], [0], [The host system])dnl -_LT_DECL([], [host], [0])dnl -_LT_DECL([], [host_os], [0])dnl -dnl -_LT_DECL([], [build_alias], [0], [The build system])dnl -_LT_DECL([], [build], [0])dnl -_LT_DECL([], [build_os], [0])dnl -dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -test -z "$LN_S" && LN_S="ln -s" -_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl -dnl -AC_REQUIRE([LT_CMD_MAX_LEN])dnl -_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl -_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl -dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl -m4_require([_LT_CMD_RELOAD])dnl -m4_require([_LT_CHECK_MAGIC_METHOD])dnl -m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl -m4_require([_LT_CMD_OLD_ARCHIVE])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_WITH_SYSROOT])dnl - -_LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi -]) -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -_LT_CHECK_OBJDIR - -m4_require([_LT_TAG_COMPILER])dnl - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - _LT_PATH_MAGIC - fi - ;; -esac - -# Use C for the default configuration in the libtool script -LT_SUPPORTED_TAG([CC]) -_LT_LANG_C_CONFIG -_LT_LANG_DEFAULT_CONFIG -_LT_CONFIG_COMMANDS -])# _LT_SETUP - - -# _LT_PREPARE_SED_QUOTE_VARS -# -------------------------- -# Define a few sed substitution that help us do robust quoting. -m4_defun([_LT_PREPARE_SED_QUOTE_VARS], -[# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' -]) - -# _LT_PROG_LTMAIN -# --------------- -# Note that this code is called both from `configure', and `config.status' -# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, -# so we pass a copy along to make sure it has a sensible value anyway. -m4_defun([_LT_PROG_LTMAIN], -[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl -_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" -])# _LT_PROG_LTMAIN - - -## ------------------------------------- ## -## Accumulate code for creating libtool. ## -## ------------------------------------- ## - -# So that we can recreate a full libtool script including additional -# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' -# label. - - -# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) -# ---------------------------------------- -# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL_INIT], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_INIT], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_INIT]) - - -# _LT_CONFIG_LIBTOOL([COMMANDS]) -# ------------------------------ -# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) - - -# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) -# ----------------------------------------------------- -m4_defun([_LT_CONFIG_SAVE_COMMANDS], -[_LT_CONFIG_LIBTOOL([$1]) -_LT_CONFIG_LIBTOOL_INIT([$2]) -]) - - -# _LT_FORMAT_COMMENT([COMMENT]) -# ----------------------------- -# Add leading comment marks to the start of each line, and a trailing -# full-stop to the whole comment if one is not present already. -m4_define([_LT_FORMAT_COMMENT], -[m4_ifval([$1], [ -m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], - [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) -)]) - - - -## ------------------------ ## -## FIXME: Eliminate VARNAME ## -## ------------------------ ## - - -# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) -# ------------------------------------------------------------------- -# CONFIGNAME is the name given to the value in the libtool script. -# VARNAME is the (base) name used in the configure script. -# VALUE may be 0, 1 or 2 for a computed quote escaped value based on -# VARNAME. Any other value will be used directly. -m4_define([_LT_DECL], -[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], - [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], - [m4_ifval([$1], [$1], [$2])]) - lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) - m4_ifval([$4], - [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) - lt_dict_add_subkey([lt_decl_dict], [$2], - [tagged?], [m4_ifval([$5], [yes], [no])])]) -]) - - -# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) -# -------------------------------------------------------- -m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) - - -# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_tag_varnames], -[_lt_decl_filter([tagged?], [yes], $@)]) - - -# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) -# --------------------------------------------------------- -m4_define([_lt_decl_filter], -[m4_case([$#], - [0], [m4_fatal([$0: too few arguments: $#])], - [1], [m4_fatal([$0: too few arguments: $#: $1])], - [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], - [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], - [lt_dict_filter([lt_decl_dict], $@)])[]dnl -]) - - -# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) -# -------------------------------------------------- -m4_define([lt_decl_quote_varnames], -[_lt_decl_filter([value], [1], $@)]) - - -# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_dquote_varnames], -[_lt_decl_filter([value], [2], $@)]) - - -# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_varnames_tagged], -[m4_assert([$# <= 2])dnl -_$0(m4_quote(m4_default([$1], [[, ]])), - m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), - m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) -m4_define([_lt_decl_varnames_tagged], -[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) - - -# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_all_varnames], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_if([$2], [], - m4_quote(lt_decl_varnames), - m4_quote(m4_shift($@))))[]dnl -]) -m4_define([_lt_decl_all_varnames], -[lt_join($@, lt_decl_varnames_tagged([$1], - lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl -]) - - -# _LT_CONFIG_STATUS_DECLARE([VARNAME]) -# ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME -# must have a single quote delimited value for this to work. -m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) - - -# _LT_CONFIG_STATUS_DECLARATIONS -# ------------------------------ -# We delimit libtool config variables with single quotes, so when -# we write them to config.status, we have to be sure to quote all -# embedded single quotes properly. In configure, this macro expands -# each variable declared with _LT_DECL (and _LT_TAGDECL) into: -# -# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' -m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], -[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), - [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAGS -# ---------------- -# Output comment and list of tags supported by the script -m4_defun([_LT_LIBTOOL_TAGS], -[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl -]) - - -# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) -# ----------------------------------- -# Extract the dictionary values for VARNAME (optionally with TAG) and -# expand to a commented shell variable setting: -# -# # Some comment about what VAR is for. -# visible_name=$lt_internal_name -m4_define([_LT_LIBTOOL_DECLARE], -[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], - [description])))[]dnl -m4_pushdef([_libtool_name], - m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl -m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), - [0], [_libtool_name=[$]$1], - [1], [_libtool_name=$lt_[]$1], - [2], [_libtool_name=$lt_[]$1], - [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl -m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl -]) - - -# _LT_LIBTOOL_CONFIG_VARS -# ----------------------- -# Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' -# script. Tagged libtool config variables (even for the LIBTOOL CONFIG -# section) are produced by _LT_LIBTOOL_TAG_VARS. -m4_defun([_LT_LIBTOOL_CONFIG_VARS], -[m4_foreach([_lt_var], - m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAG_VARS(TAG) -# ------------------------- -m4_define([_LT_LIBTOOL_TAG_VARS], -[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) - - -# _LT_TAGVAR(VARNAME, [TAGNAME]) -# ------------------------------ -m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) - - -# _LT_CONFIG_COMMANDS -# ------------------- -# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of -# variables for single and double quote escaping we saved from calls -# to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated -# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. -m4_defun([_LT_CONFIG_COMMANDS], -[AC_PROVIDE_IFELSE([LT_OUTPUT], - dnl If the libtool generation code has been placed in $CONFIG_LT, - dnl instead of duplicating it all over again into config.status, - dnl then we will have config.status run $CONFIG_LT later, so it - dnl needs to know what name is stored there: - [AC_CONFIG_COMMANDS([libtool], - [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], - dnl If the libtool generation code is destined for config.status, - dnl expand the accumulated commands and init code now: - [AC_CONFIG_COMMANDS([libtool], - [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) -])#_LT_CONFIG_COMMANDS - - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], -[ - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -_LT_CONFIG_STATUS_DECLARATIONS -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$[]1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -_LT_OUTPUT_LIBTOOL_INIT -]) - -# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) -# ------------------------------------ -# Generate a child script FILE with all initialization necessary to -# reuse the environment learned by the parent script, and make the -# file executable. If COMMENT is supplied, it is inserted after the -# `#!' sequence but before initialization text begins. After this -# macro, additional text can be appended to FILE to form the body of -# the child script. The macro ends with non-zero status if the -# file could not be fully written (such as if the disk is full). -m4_ifdef([AS_INIT_GENERATED], -[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], -[m4_defun([_LT_GENERATED_FILE_INIT], -[m4_require([AS_PREPARE])]dnl -[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl -[lt_write_fail=0 -cat >$1 <<_ASEOF || lt_write_fail=1 -#! $SHELL -# Generated by $as_me. -$2 -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$1 <<\_ASEOF || lt_write_fail=1 -AS_SHELL_SANITIZE -_AS_PREPARE -exec AS_MESSAGE_FD>&1 -_ASEOF -test $lt_write_fail = 0 && chmod +x $1[]dnl -m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT - -# LT_OUTPUT -# --------- -# This macro allows early generation of the libtool script (before -# AC_OUTPUT is called), incase it is used in configure for compilation -# tests. -AC_DEFUN([LT_OUTPUT], -[: ${CONFIG_LT=./config.lt} -AC_MSG_NOTICE([creating $CONFIG_LT]) -_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], -[# Run this file to recreate a libtool stub with the current configuration.]) - -cat >>"$CONFIG_LT" <<\_LTEOF -lt_cl_silent=false -exec AS_MESSAGE_LOG_FD>>config.log -{ - echo - AS_BOX([Running $as_me.]) -} >&AS_MESSAGE_LOG_FD - -lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, -for use in further configure time tests before the real libtool is -generated. - -Usage: $[0] [[OPTIONS]] - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - -Report bugs to ." - -lt_cl_version="\ -m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl -m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) -configured by $[0], generated by m4_PACKAGE_STRING. - -Copyright (C) 2011 Free Software Foundation, Inc. -This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." - -while test $[#] != 0 -do - case $[1] in - --version | --v* | -V ) - echo "$lt_cl_version"; exit 0 ;; - --help | --h* | -h ) - echo "$lt_cl_help"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --quiet | --q* | --silent | --s* | -q ) - lt_cl_silent=: ;; - - -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; - - *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; - esac - shift -done - -if $lt_cl_silent; then - exec AS_MESSAGE_FD>/dev/null -fi -_LTEOF - -cat >>"$CONFIG_LT" <<_LTEOF -_LT_OUTPUT_LIBTOOL_COMMANDS_INIT -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AC_MSG_NOTICE([creating $ofile]) -_LT_OUTPUT_LIBTOOL_COMMANDS -AS_EXIT(0) -_LTEOF -chmod +x "$CONFIG_LT" - -# configure is writing to config.log, but config.lt does its own redirection, -# appending to config.log, which fails on DOS, as config.log is still kept -# open by configure. Here we exec the FD to /dev/null, effectively closing -# config.log, so it can be properly (re)opened and appended to by config.lt. -lt_cl_success=: -test "$silent" = yes && - lt_config_lt_args="$lt_config_lt_args --quiet" -exec AS_MESSAGE_LOG_FD>/dev/null -$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false -exec AS_MESSAGE_LOG_FD>>config.log -$lt_cl_success || AS_EXIT(1) -])# LT_OUTPUT - - -# _LT_CONFIG(TAG) -# --------------- -# If TAG is the built-in tag, create an initial libtool script with a -# default configuration from the untagged config vars. Otherwise add code -# to config.status for appending the configuration named by TAG from the -# matching tagged config vars. -m4_defun([_LT_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_CONFIG_SAVE_COMMANDS([ - m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl - m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - - cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -_LT_COPYING -_LT_LIBTOOL_TAGS - -# ### BEGIN LIBTOOL CONFIG -_LT_LIBTOOL_CONFIG_VARS -_LT_LIBTOOL_TAG_VARS -# ### END LIBTOOL CONFIG - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - _LT_PROG_LTMAIN - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - _LT_PROG_REPLACE_SHELLFNS - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -], -[cat <<_LT_EOF >> "$ofile" - -dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded -dnl in a comment (ie after a #). -# ### BEGIN LIBTOOL TAG CONFIG: $1 -_LT_LIBTOOL_TAG_VARS(_LT_TAG) -# ### END LIBTOOL TAG CONFIG: $1 -_LT_EOF -])dnl /m4_if -], -[m4_if([$1], [], [ - PACKAGE='$PACKAGE' - VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' - RM='$RM' - ofile='$ofile'], []) -])dnl /_LT_CONFIG_SAVE_COMMANDS -])# _LT_CONFIG - - -# LT_SUPPORTED_TAG(TAG) -# --------------------- -# Trace this macro to discover what tags are supported by the libtool -# --tag option, using: -# autoconf --trace 'LT_SUPPORTED_TAG:$1' -AC_DEFUN([LT_SUPPORTED_TAG], []) - - -# C support is built-in for now -m4_define([_LT_LANG_C_enabled], []) -m4_define([_LT_TAGS], []) - - -# LT_LANG(LANG) -# ------------- -# Enable libtool support for the given language if not already enabled. -AC_DEFUN([LT_LANG], -[AC_BEFORE([$0], [LT_OUTPUT])dnl -m4_case([$1], - [C], [_LT_LANG(C)], - [C++], [_LT_LANG(CXX)], - [Go], [_LT_LANG(GO)], - [Java], [_LT_LANG(GCJ)], - [Fortran 77], [_LT_LANG(F77)], - [Fortran], [_LT_LANG(FC)], - [Windows Resource], [_LT_LANG(RC)], - [m4_ifdef([_LT_LANG_]$1[_CONFIG], - [_LT_LANG($1)], - [m4_fatal([$0: unsupported language: "$1"])])])dnl -])# LT_LANG - - -# _LT_LANG(LANGNAME) -# ------------------ -m4_defun([_LT_LANG], -[m4_ifdef([_LT_LANG_]$1[_enabled], [], - [LT_SUPPORTED_TAG([$1])dnl - m4_append([_LT_TAGS], [$1 ])dnl - m4_define([_LT_LANG_]$1[_enabled], [])dnl - _LT_LANG_$1_CONFIG($1)])dnl -])# _LT_LANG - - -m4_ifndef([AC_PROG_GO], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_GO. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -m4_defun([AC_PROG_GO], -[AC_LANG_PUSH(Go)dnl -AC_ARG_VAR([GOC], [Go compiler command])dnl -AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl -_AC_ARG_VAR_LDFLAGS()dnl -AC_CHECK_TOOL(GOC, gccgo) -if test -z "$GOC"; then - if test -n "$ac_tool_prefix"; then - AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) - fi -fi -if test -z "$GOC"; then - AC_CHECK_PROG(GOC, gccgo, gccgo, false) -fi -])#m4_defun -])#m4_ifndef - - -# _LT_LANG_DEFAULT_CONFIG -# ----------------------- -m4_defun([_LT_LANG_DEFAULT_CONFIG], -[AC_PROVIDE_IFELSE([AC_PROG_CXX], - [LT_LANG(CXX)], - [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) - -AC_PROVIDE_IFELSE([AC_PROG_F77], - [LT_LANG(F77)], - [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) - -AC_PROVIDE_IFELSE([AC_PROG_FC], - [LT_LANG(FC)], - [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) - -dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal -dnl pulling things in needlessly. -AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([LT_PROG_GCJ], - [LT_LANG(GCJ)], - [m4_ifdef([AC_PROG_GCJ], - [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([A][M_PROG_GCJ], - [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([LT_PROG_GCJ], - [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) - -AC_PROVIDE_IFELSE([AC_PROG_GO], - [LT_LANG(GO)], - [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) - -AC_PROVIDE_IFELSE([LT_PROG_RC], - [LT_LANG(RC)], - [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) -])# _LT_LANG_DEFAULT_CONFIG - -# Obsolete macros: -AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) -AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) -AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) -AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) -AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_CXX], []) -dnl AC_DEFUN([AC_LIBTOOL_F77], []) -dnl AC_DEFUN([AC_LIBTOOL_FC], []) -dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) -dnl AC_DEFUN([AC_LIBTOOL_RC], []) - - -# _LT_TAG_COMPILER -# ---------------- -m4_defun([_LT_TAG_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl -_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl -_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl -_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_TAG_COMPILER - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -m4_defun([_LT_COMPILER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -m4_defun([_LT_LINKER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* -])# _LT_LINKER_BOILERPLATE - -# _LT_REQUIRED_DARWIN_CHECKS -# ------------------------- -m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ - case $host_os in - rhapsody* | darwin*) - AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) - AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) - AC_CHECK_TOOL([LIPO], [lipo], [:]) - AC_CHECK_TOOL([OTOOL], [otool], [:]) - AC_CHECK_TOOL([OTOOL64], [otool64], [:]) - _LT_DECL([], [DSYMUTIL], [1], - [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) - _LT_DECL([], [NMEDIT], [1], - [Tool to change global to local symbols on Mac OS X]) - _LT_DECL([], [LIPO], [1], - [Tool to manipulate fat objects and archives on Mac OS X]) - _LT_DECL([], [OTOOL], [1], - [ldd/readelf like tool for Mach-O binaries on Mac OS X]) - _LT_DECL([], [OTOOL64], [1], - [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) - - AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], - [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi]) - - AC_CACHE_CHECK([for -exported_symbols_list linker flag], - [lt_cv_ld_exported_symbols_list], - [lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [lt_cv_ld_exported_symbols_list=yes], - [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" - ]) - - AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], - [lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD - echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD - $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD - echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD - $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - ]) - case $host_os in - rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac -]) - - -# _LT_DARWIN_LINKER_FEATURES([TAG]) -# --------------------------------- -# Checks for linker and compiler features on darwin -m4_defun([_LT_DARWIN_LINKER_FEATURES], -[ - m4_require([_LT_REQUIRED_DARWIN_CHECKS]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_automatic, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], - [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='' - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" - fi -],[]) - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi -]) - -# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) -# ---------------------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -# Store the results from the different compilers for each TAGNAME. -# Allow to override them for all tags through lt_cv_aix_libpath. -m4_defun([_LT_SYS_MODULE_PATH_AIX], -[m4_require([_LT_DECL_SED])dnl -if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], - [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ - lt_aix_libpath_sed='[ - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }]' - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi],[]) - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" - fi - ]) - aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) -fi -])# _LT_SYS_MODULE_PATH_AIX - - -# _LT_SHELL_INIT(ARG) -# ------------------- -m4_define([_LT_SHELL_INIT], -[m4_divert_text([M4SH-INIT], [$1 -])])# _LT_SHELL_INIT - - - -# _LT_PROG_ECHO_BACKSLASH -# ----------------------- -# Find how we can fake an echo command that does not interpret backslash. -# In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script which will find a shell with a builtin -# printf (which we can use as an echo command). -m4_defun([_LT_PROG_ECHO_BACKSLASH], -[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -AC_MSG_CHECKING([how to print strings]) -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$[]1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -case "$ECHO" in - printf*) AC_MSG_RESULT([printf]) ;; - print*) AC_MSG_RESULT([print -r]) ;; - *) AC_MSG_RESULT([cat]) ;; -esac - -m4_ifdef([_AS_DETECT_SUGGESTED], -[_AS_DETECT_SUGGESTED([ - test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test "X`printf %s $ECHO`" = "X$ECHO" \ - || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) - -_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) -])# _LT_PROG_ECHO_BACKSLASH - - -# _LT_WITH_SYSROOT -# ---------------- -AC_DEFUN([_LT_WITH_SYSROOT], -[AC_MSG_CHECKING([for sysroot]) -AC_ARG_WITH([sysroot], -[ --with-sysroot[=DIR] Search for dependent libraries within DIR - (or the compiler's sysroot if not specified).], -[], [with_sysroot=no]) - -dnl lt_sysroot will always be passed unquoted. We quote it here -dnl in case the user passed a directory name. -lt_sysroot= -case ${with_sysroot} in #( - yes) - if test "$GCC" = yes; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - AC_MSG_RESULT([${with_sysroot}]) - AC_MSG_ERROR([The sysroot must be an absolute path.]) - ;; -esac - - AC_MSG_RESULT([${lt_sysroot:-no}]) -_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and in which our libraries should be installed.])]) - -# _LT_ENABLE_LOCK -# --------------- -m4_defun([_LT_ENABLE_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AS_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" - fi - ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks="$enable_libtool_lock" -])# _LT_ENABLE_LOCK - - -# _LT_PROG_AR -# ----------- -m4_defun([_LT_PROG_AR], -[AC_CHECK_TOOLS(AR, [ar], false) -: ${AR=ar} -: ${AR_FLAGS=cru} -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) - -AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], - [lt_cv_ar_at_file=no - AC_COMPILE_IFELSE([AC_LANG_PROGRAM], - [echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' - AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -eq 0; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -ne 0; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - ]) - ]) - -if test "x$lt_cv_ar_at_file" = xno; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi -_LT_DECL([], [archiver_list_spec], [1], - [How to feed a file listing to the archiver]) -])# _LT_PROG_AR - - -# _LT_CMD_OLD_ARCHIVE -# ------------------- -m4_defun([_LT_CMD_OLD_ARCHIVE], -[_LT_PROG_AR - -AC_CHECK_TOOL(STRIP, strip, :) -test -z "$STRIP" && STRIP=: -_LT_DECL([], [STRIP], [1], [A symbol stripping program]) - -AC_CHECK_TOOL(RANLIB, ranlib, :) -test -z "$RANLIB" && RANLIB=: -_LT_DECL([], [RANLIB], [1], - [Commands used to install an old-style archive]) - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac -_LT_DECL([], [old_postinstall_cmds], [2]) -_LT_DECL([], [old_postuninstall_cmds], [2]) -_LT_TAGDECL([], [old_archive_cmds], [2], - [Commands used to build an old-style archive]) -_LT_DECL([], [lock_old_archive_extraction], [0], - [Whether to use a lock for old archive extraction]) -])# _LT_CMD_OLD_ARCHIVE - - -# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([_LT_COMPILER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $RM conftest* -]) - -if test x"[$]$2" = xyes; then - m4_if([$5], , :, [$5]) -else - m4_if([$6], , :, [$6]) -fi -])# _LT_COMPILER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) - - -# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------- -# Check whether the given linker option works -AC_DEFUN([_LT_LINKER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - m4_if([$4], , :, [$4]) -else - m4_if([$5], , :, [$5]) -fi -])# _LT_LINKER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) - - -# LT_CMD_MAX_LEN -#--------------- -AC_DEFUN([LT_CMD_MAX_LEN], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -max_cmd_len=$lt_cv_sys_max_cmd_len -_LT_DECL([], [max_cmd_len], [0], - [What is the maximum length of a command?]) -])# LT_CMD_MAX_LEN - -# Old name: -AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) - - -# _LT_HEADER_DLFCN -# ---------------- -m4_defun([_LT_HEADER_DLFCN], -[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl -])# _LT_HEADER_DLFCN - - -# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ---------------------------------------------------------------- -m4_defun([_LT_TRY_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -[#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisbility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -}] -_LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_TRY_DLOPEN_SELF - - -# LT_SYS_DLOPEN_SELF -# ------------------ -AC_DEFUN([LT_SYS_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -_LT_DECL([dlopen_support], [enable_dlopen], [0], - [Whether dlopen is supported]) -_LT_DECL([dlopen_self], [enable_dlopen_self], [0], - [Whether dlopen of programs is supported]) -_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], - [Whether dlopen of statically linked programs is supported]) -])# LT_SYS_DLOPEN_SELF - -# Old name: -AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) - - -# _LT_COMPILER_C_O([TAGNAME]) -# --------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler. -# This macro does not hard code the compiler like AC_PROG_CC_C_O. -m4_defun([_LT_COMPILER_C_O], -[m4_require([_LT_DECL_SED])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* -]) -_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], - [Does compiler simultaneously support -c and -o options?]) -])# _LT_COMPILER_C_O - - -# _LT_COMPILER_FILE_LOCKS([TAGNAME]) -# ---------------------------------- -# Check to see if we can do hard links to lock some files if needed -m4_defun([_LT_COMPILER_FILE_LOCKS], -[m4_require([_LT_ENABLE_LOCK])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_COMPILER_C_O([$1]) - -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) -])# _LT_COMPILER_FILE_LOCKS - - -# _LT_CHECK_OBJDIR -# ---------------- -m4_defun([_LT_CHECK_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -_LT_DECL([], [objdir], [0], - [The name of the directory that contains temporary libtool files])dnl -m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) -])# _LT_CHECK_OBJDIR - - -# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) -# -------------------------------------- -# Check hardcoding attributes. -m4_defun([_LT_LINKER_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || - test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -_LT_TAGDECL([], [hardcode_action], [0], - [How to hardcode a shared library path into an executable]) -])# _LT_LINKER_HARDCODE_LIBPATH - - -# _LT_CMD_STRIPLIB -# ---------------- -m4_defun([_LT_CMD_STRIPLIB], -[m4_require([_LT_DECL_EGREP]) -striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) -_LT_DECL([], [striplib], [1]) -])# _LT_CMD_STRIPLIB - - -# _LT_SYS_DYNAMIC_LINKER([TAG]) -# ----------------------------- -# PORTME Fill in your ld.so characteristics -m4_defun([_LT_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_OBJDUMP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -m4_if([$1], - [], [ -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[[4-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec="$LIB" - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[23]].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[[3-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], - [lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [lt_cv_shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - ]) - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Add ABI-specific directories to the system library path. - sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" - - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - -_LT_DECL([], [variables_saved_for_relink], [1], - [Variables whose values should be saved in libtool wrapper scripts and - restored at link time]) -_LT_DECL([], [need_lib_prefix], [0], - [Do we need the "lib" prefix for modules?]) -_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) -_LT_DECL([], [version_type], [0], [Library versioning type]) -_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) -_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) -_LT_DECL([], [shlibpath_overrides_runpath], [0], - [Is shlibpath searched before the hard-coded library search path?]) -_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) -_LT_DECL([], [library_names_spec], [1], - [[List of archive names. First name is the real one, the rest are links. - The last name is the one that the linker finds with -lNAME]]) -_LT_DECL([], [soname_spec], [1], - [[The coded name of the library, if different from the real name]]) -_LT_DECL([], [install_override_mode], [1], - [Permission mode override for installation of shared libraries]) -_LT_DECL([], [postinstall_cmds], [2], - [Command to use after installation of a shared archive]) -_LT_DECL([], [postuninstall_cmds], [2], - [Command to use after uninstallation of a shared archive]) -_LT_DECL([], [finish_cmds], [2], - [Commands used to finish a libtool library installation in a directory]) -_LT_DECL([], [finish_eval], [1], - [[As "finish_cmds", except a single script fragment to be evaled but - not shown]]) -_LT_DECL([], [hardcode_into_libs], [0], - [Whether we should hardcode library paths into libraries]) -_LT_DECL([], [sys_lib_search_path_spec], [2], - [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) -])# _LT_SYS_DYNAMIC_LINKER - - -# _LT_PATH_TOOL_PREFIX(TOOL) -# -------------------------- -# find a file program which can recognize shared library -AC_DEFUN([_LT_PATH_TOOL_PREFIX], -[m4_require([_LT_DECL_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="m4_if([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -_LT_DECL([], [MAGIC_CMD], [0], - [Used to examine libraries when file_magic_cmd begins with "file"])dnl -])# _LT_PATH_TOOL_PREFIX - -# Old name: -AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) - - -# _LT_PATH_MAGIC -# -------------- -# find a file program which can recognize a shared library -m4_defun([_LT_PATH_MAGIC], -[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# _LT_PATH_MAGIC - - -# LT_PATH_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([LT_PATH_LD], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PROG_ECHO_BACKSLASH])dnl - -AC_ARG_WITH([gnu-ld], - [AS_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no])dnl - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - -_LT_DECL([], [deplibs_check_method], [1], - [Method to check whether dependent libraries are shared objects]) -_LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method = "file_magic"]) -_LT_DECL([], [file_magic_glob], [1], - [How to find potential files when deplibs_check_method = "file_magic"]) -_LT_DECL([], [want_nocaseglob], [1], - [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) -])# _LT_CHECK_MAGIC_METHOD - - -# LT_PATH_NM -# ---------- -# find the pathname to a BSD- or MS-compatible name lister -AC_DEFUN([LT_PATH_NM], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - : ${lt_cv_path_NM=no} -fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols" - ;; - *) - DUMPBIN=: - ;; - esac - fi - AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" - fi -fi -test -z "$NM" && NM=nm -AC_SUBST([NM]) -_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl - -AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], - [lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) - cat conftest.out >&AS_MESSAGE_LOG_FD - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest*]) -])# LT_PATH_NM - -# Old names: -AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) -AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_PROG_NM], []) -dnl AC_DEFUN([AC_PROG_NM], []) - -# _LT_CHECK_SHAREDLIB_FROM_LINKLIB -# -------------------------------- -# how to determine the name of the shared library -# associated with a specific link library. -# -- PORTME fill in with the dynamic library characteristics -m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], -[m4_require([_LT_DECL_EGREP]) -m4_require([_LT_DECL_OBJDUMP]) -m4_require([_LT_DECL_DLLTOOL]) -AC_CACHE_CHECK([how to associate runtime and link libraries], -lt_cv_sharedlib_from_linklib_cmd, -[lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" - ;; -esac -]) -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - -_LT_DECL([], [sharedlib_from_linklib_cmd], [1], - [Command to associate shared and link libraries]) -])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB - - -# _LT_PATH_MANIFEST_TOOL -# ---------------------- -# locate the manifest tool -m4_defun([_LT_PATH_MANIFEST_TOOL], -[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], - [lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&AS_MESSAGE_LOG_FD - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest*]) -if test "x$lt_cv_path_mainfest_tool" != xyes; then - MANIFEST_TOOL=: -fi -_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl -])# _LT_PATH_MANIFEST_TOOL - - -# LT_LIB_M -# -------- -# check for math library -AC_DEFUN([LT_LIB_M], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -AC_SUBST([LIBM]) -])# LT_LIB_M - -# Old name: -AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_CHECK_LIBM], []) - - -# _LT_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------- -m4_defun([_LT_COMPILER_NO_RTTI], -[m4_require([_LT_TAG_COMPILER])dnl - -_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - case $cc_basename in - nvcc*) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; - *) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; - esac - - _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], - [Compiler flag to turn off builtin functions]) -])# _LT_COMPILER_NO_RTTI - - -# _LT_CMD_GLOBAL_SYMBOLS -# ---------------------- -m4_defun([_LT_CMD_GLOBAL_SYMBOLS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([LT_PATH_NM])dnl -AC_REQUIRE([LT_PATH_LD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_TAG_COMPILER])dnl - -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK ['"\ -" {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx]" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT@&t@_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT@&t@_DLSYM_CONST -#else -# define LT@&t@_DLSYM_CONST const -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -LT@&t@_DLSYM_CONST struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[[]] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi - -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then - nm_file_list_spec='@' -fi - -_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], - [Take the output of nm and produce a listing of raw symbols and C names]) -_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], - [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_c_name_address], - [lt_cv_sys_global_symbol_to_c_name_address], [1], - [Transform the output of nm in a C name address pair]) -_LT_DECL([global_symbol_to_c_name_address_lib_prefix], - [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], - [Transform the output of nm in a C name address pair when lib prefix is needed]) -_LT_DECL([], [nm_file_list_spec], [1], - [Specify filename containing input files for $NM]) -]) # _LT_CMD_GLOBAL_SYMBOLS - - -# _LT_COMPILER_PIC([TAGNAME]) -# --------------------------- -m4_defun([_LT_COMPILER_PIC], -[m4_require([_LT_TAG_COMPILER])dnl -_LT_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_TAGVAR(lt_prog_compiler_static, $1)= - -m4_if([$1], [CXX], [ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix[[4-9]]*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd*) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' - if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" - fi - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - hpux9* | hpux10* | hpux11*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. - ecc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' - _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' - ;; - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - *Sun\ F* | *Sun*Fortran*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - *Sun\ C*) - # Sun C 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Intel*\ [[CF]]*Compiler*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - *Portland\ Group*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - esac - ;; - - newsos6) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" - ;; -esac - -AC_CACHE_CHECK([for $compiler option to produce PIC], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], - [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], - [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], - [Additional compiler flags for building library objects]) - -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) -# -# Check to make sure the static flag actually works. -# -wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" -_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) -_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], - [Compiler flag to prevent dynamic linking]) -])# _LT_COMPILER_PIC - - -# _LT_LINKER_SHLIBS([TAGNAME]) -# ---------------------------- -# See if the linker supports building shared libraries. -m4_defun([_LT_LINKER_SHLIBS], -[AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -m4_if([$1], [CXX], [ - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - case $host_os in - aix[[4-9]]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - ;; - esac - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -], [ - runpath_var= - _LT_TAGVAR(allow_undefined_flag, $1)= - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(archive_cmds, $1)= - _LT_TAGVAR(archive_expsym_cmds, $1)= - _LT_TAGVAR(compiler_needs_object, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(hardcode_automatic, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_separator, $1)= - _LT_TAGVAR(hardcode_minus_L, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(inherit_rpath, $1)=no - _LT_TAGVAR(link_all_deplibs, $1)=unknown - _LT_TAGVAR(module_cmds, $1)= - _LT_TAGVAR(module_expsym_cmds, $1)= - _LT_TAGVAR(old_archive_from_new_cmds, $1)= - _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_TAGVAR(thread_safe_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. -dnl Note also adjust exclude_expsyms for C++ above. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - _LT_TAGVAR(ld_shlibs, $1)=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; - *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test "$lt_use_gnu_ld_interface" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[[3-9]]*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.19, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test "$host_os" = linux-dietlibc; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no - then - tmp_addflag=' $pic_flag' - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - _LT_TAGVAR(whole_archive_flag_spec, $1)= - tmp_sharedflag='--shared' ;; - xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - xlf* | bgf* | bgxlf* | mpixlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then - runpath_var= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GCC" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - bsdi[[45]]*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - esac - ;; - - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - m4_if($1, [], [ - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - _LT_LINKER_OPTION([if $CC understands -b], - _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], - [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) - ;; - esac - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], - [lt_cv_irix_exported_symbol], - [save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - AC_LINK_IFELSE( - [AC_LANG_SOURCE( - [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], - [C++], [[int foo (void) { return 0; }]], - [Fortran 77], [[ - subroutine foo - end]], - [Fortran], [[ - subroutine foo - end]])])], - [lt_cv_irix_exported_symbol=yes], - [lt_cv_irix_exported_symbol=no]) - LDFLAGS="$save_LDFLAGS"]) - if test "$lt_cv_irix_exported_symbol" = yes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - fi - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *nto* | *qnx*) - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - if test x$host_vendor = xsni; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' - ;; - esac - fi - fi -]) -AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld - -_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl -_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl -_LT_DECL([], [extract_expsyms_cmds], [2], - [The commands to extract the exported symbol list from a shared archive]) - -# -# Do we need to explicitly link libc? -# -case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_CACHE_CHECK([whether -lc should be explicitly linked in], - [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), - [$RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - ]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) - ;; - esac - fi - ;; -esac - -_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], - [Whether or not to add -lc for building shared libraries]) -_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], - [enable_shared_with_static_runtimes], [0], - [Whether or not to disallow shared libs when runtime libs are static]) -_LT_TAGDECL([], [export_dynamic_flag_spec], [1], - [Compiler flag to allow reflexive dlopens]) -_LT_TAGDECL([], [whole_archive_flag_spec], [1], - [Compiler flag to generate shared objects directly from archives]) -_LT_TAGDECL([], [compiler_needs_object], [1], - [Whether the compiler copes with passing no objects directly]) -_LT_TAGDECL([], [old_archive_from_new_cmds], [2], - [Create an old-style archive from a shared archive]) -_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], - [Create a temporary old-style archive to link instead of a shared archive]) -_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) -_LT_TAGDECL([], [archive_expsym_cmds], [2]) -_LT_TAGDECL([], [module_cmds], [2], - [Commands used to build a loadable module if different from building - a shared archive.]) -_LT_TAGDECL([], [module_expsym_cmds], [2]) -_LT_TAGDECL([], [with_gnu_ld], [1], - [Whether we are building with GNU ld or not]) -_LT_TAGDECL([], [allow_undefined_flag], [1], - [Flag that allows shared libraries with undefined symbols to be built]) -_LT_TAGDECL([], [no_undefined_flag], [1], - [Flag that enforces no undefined symbols]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], - [Flag to hardcode $libdir into a binary during linking. - This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_separator], [1], - [Whether we need a single "-rpath" flag with a separated argument]) -_LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary]) -_LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the - library is relocated]) -_LT_TAGDECL([], [hardcode_minus_L], [0], - [Set to "yes" if using the -LDIR flag during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_shlibpath_var], [0], - [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_automatic], [0], - [Set to "yes" if building a shared library automatically hardcodes DIR - into the library and all subsequent libraries and executables linked - against it]) -_LT_TAGDECL([], [inherit_rpath], [0], - [Set to yes if linker adds runtime paths of dependent libraries - to runtime path list]) -_LT_TAGDECL([], [link_all_deplibs], [0], - [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [always_export_symbols], [0], - [Set to "yes" if exported symbols are required]) -_LT_TAGDECL([], [export_symbols_cmds], [2], - [The commands to list exported symbols]) -_LT_TAGDECL([], [exclude_expsyms], [1], - [Symbols that should not be listed in the preloaded symbols]) -_LT_TAGDECL([], [include_expsyms], [1], - [Symbols that must always be exported]) -_LT_TAGDECL([], [prelink_cmds], [2], - [Commands necessary for linking programs (against libraries) with templates]) -_LT_TAGDECL([], [postlink_cmds], [2], - [Commands necessary for finishing linking programs]) -_LT_TAGDECL([], [file_list_spec], [1], - [Specify filename containing input files]) -dnl FIXME: Not yet implemented -dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], -dnl [Compiler flag to generate thread safe objects]) -])# _LT_LINKER_SHLIBS - - -# _LT_LANG_C_CONFIG([TAG]) -# ------------------------ -# Ensure that the configuration variables for a C compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_C_CONFIG], -[m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_TAG_COMPILER -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - LT_SYS_DLOPEN_SELF - _LT_CMD_STRIPLIB - - # Report which library types will actually be built - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_CONFIG($1) -fi -AC_LANG_POP -CC="$lt_save_CC" -])# _LT_LANG_C_CONFIG - - -# _LT_LANG_CXX_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a C++ compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_CXX_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi - -AC_LANG_PUSH(C++) -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(compiler_needs_object, $1)=no -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - else - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - fi - - if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - LT_PATH_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) - _LT_TAGVAR(ld_shlibs, $1)=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GXX" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty - # executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - freebsd-elf*) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - gnu*) - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' - fi - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) - _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - case $host in - osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - ;; - *) - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - case $host in - osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - fi - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" - _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes - -AC_LANG_POP -])# _LT_LANG_CXX_CONFIG - - -# _LT_FUNC_STRIPNAME_CNF -# ---------------------- -# func_stripname_cnf prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# -# This function is identical to the (non-XSI) version of func_stripname, -# except this one can be used by m4 code that may be executed by configure, -# rather than the libtool script. -m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl -AC_REQUIRE([_LT_DECL_SED]) -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) -func_stripname_cnf () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname_cnf -])# _LT_FUNC_STRIPNAME_CNF - -# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) -# --------------------------------- -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -m4_defun([_LT_SYS_HIDDEN_LIBDEPS], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl -# Dependencies to place before and after the object being linked: -_LT_TAGVAR(predep_objects, $1)= -_LT_TAGVAR(postdep_objects, $1)= -_LT_TAGVAR(predeps, $1)= -_LT_TAGVAR(postdeps, $1)= -_LT_TAGVAR(compiler_lib_search_path, $1)= - -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF -int a; -void foo (void) { a = 0; } -_LT_EOF -], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF -], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer*4 a - a=0 - return - end -_LT_EOF -], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer a - a=0 - return - end -_LT_EOF -], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF -public class foo { - private int a; - public void bar (void) { - a = 0; - } -}; -_LT_EOF -], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF -package foo -func foo() { -} -_LT_EOF -]) - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -dnl Parse the compiler output and extract the necessary -dnl objects, libraries and library flags. -if AC_TRY_EVAL(ac_compile); then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" || - test $p = "-R"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" - else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" - else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" - else - _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" - fi - else - if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" - else - _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling $1 test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -m4_if([$1], [CXX], -[case $host_os in -interix[[3-9]]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - _LT_TAGVAR(predep_objects,$1)= - _LT_TAGVAR(postdep_objects,$1)= - _LT_TAGVAR(postdeps,$1)= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac -]) - -case " $_LT_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac - _LT_TAGVAR(compiler_lib_search_dirs, $1)= -if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` -fi -_LT_TAGDECL([], [compiler_lib_search_dirs], [1], - [The directories searched by this compiler when creating a shared library]) -_LT_TAGDECL([], [predep_objects], [1], - [Dependencies to place before and after the objects being linked to - create a shared library]) -_LT_TAGDECL([], [postdep_objects], [1]) -_LT_TAGDECL([], [predeps], [1]) -_LT_TAGDECL([], [postdeps], [1]) -_LT_TAGDECL([], [compiler_lib_search_path], [1], - [The library search path used internally by the compiler when linking - a shared library]) -])# _LT_SYS_HIDDEN_LIBDEPS - - -# _LT_LANG_F77_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a Fortran 77 compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_F77_CONFIG], -[AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test "X$F77" = "Xno"; then - _lt_disable_F77=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the F77 compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${F77-"f77"} - CFLAGS=$FFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - GCC=$G77 - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC="$lt_save_CC" - CFLAGS="$lt_save_CFLAGS" -fi # test "$_lt_disable_F77" != yes - -AC_LANG_POP -])# _LT_LANG_F77_CONFIG - - -# _LT_LANG_FC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for a Fortran compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_FC_CONFIG], -[AC_LANG_PUSH(Fortran) - -if test -z "$FC" || test "X$FC" = "Xno"; then - _lt_disable_FC=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for fc test sources. -ac_ext=${ac_fc_srcext-f} - -# Object file extension for compiled fc test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the FC compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${FC-"f95"} - CFLAGS=$FCFLAGS - compiler=$CC - GCC=$ac_cv_fc_compiler_gnu - - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test "$_lt_disable_FC" != yes - -AC_LANG_POP -])# _LT_LANG_FC_CONFIG - - -# _LT_LANG_GCJ_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Java Compiler compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_GCJ_CONFIG], -[AC_REQUIRE([LT_PROG_GCJ])dnl -AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GCJ-"gcj"} -CFLAGS=$GCJFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GCJ_CONFIG - - -# _LT_LANG_GO_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Go compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_GO_CONFIG], -[AC_REQUIRE([LT_PROG_GO])dnl -AC_LANG_SAVE - -# Source file extension for Go test sources. -ac_ext=go - -# Object file extension for compiled Go test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="package main; func main() { }" - -# Code to be used in simple link tests -lt_simple_link_test_code='package main; func main() { }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GOC-"gccgo"} -CFLAGS=$GOFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" -_LT_CC_BASENAME([$compiler]) - -# Go did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GO_CONFIG - - -# _LT_LANG_RC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for the Windows resource compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_RC_CONFIG], -[AC_REQUIRE([LT_PROG_RC])dnl -AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC= -CC=${RC-"windres"} -CFLAGS= -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -if test -n "$compiler"; then - : - _LT_CONFIG($1) -fi - -GCC=$lt_save_GCC -AC_LANG_RESTORE -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_RC_CONFIG - - -# LT_PROG_GCJ -# ----------- -AC_DEFUN([LT_PROG_GCJ], -[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], - [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], - [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS)])])[]dnl -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_GCJ], []) - - -# LT_PROG_GO -# ---------- -AC_DEFUN([LT_PROG_GO], -[AC_CHECK_TOOL(GOC, gccgo,) -]) - - -# LT_PROG_RC -# ---------- -AC_DEFUN([LT_PROG_RC], -[AC_CHECK_TOOL(RC, windres,) -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_RC], []) - - -# _LT_DECL_EGREP -# -------------- -# If we don't have a new enough Autoconf to choose the best grep -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_EGREP], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_REQUIRE([AC_PROG_FGREP])dnl -test -z "$GREP" && GREP=grep -_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) -_LT_DECL([], [EGREP], [1], [An ERE matcher]) -_LT_DECL([], [FGREP], [1], [A literal string matcher]) -dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too -AC_SUBST([GREP]) -]) - - -# _LT_DECL_OBJDUMP -# -------------- -# If we don't have a new enough Autoconf to choose the best objdump -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_OBJDUMP], -[AC_CHECK_TOOL(OBJDUMP, objdump, false) -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) -AC_SUBST([OBJDUMP]) -]) - -# _LT_DECL_DLLTOOL -# ---------------- -# Ensure DLLTOOL variable is set. -m4_defun([_LT_DECL_DLLTOOL], -[AC_CHECK_TOOL(DLLTOOL, dlltool, false) -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) -AC_SUBST([DLLTOOL]) -]) - -# _LT_DECL_SED -# ------------ -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -m4_defun([_LT_DECL_SED], -[AC_PROG_SED -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" -_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) -_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], - [Sed that helps us avoid accidentally triggering echo(1) options like -n]) -])# _LT_DECL_SED - -m4_ifndef([AC_PROG_SED], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ - -m4_defun([AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -])#AC_PROG_SED -])#m4_ifndef - -# Old name: -AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_SED], []) - - -# _LT_CHECK_SHELL_FEATURES -# ------------------------ -# Find out whether the shell is Bourne or XSI compatible, -# or has some other useful features. -m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi -_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac -_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl -_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl -])# _LT_CHECK_SHELL_FEATURES - - -# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) -# ------------------------------------------------------ -# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and -# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. -m4_defun([_LT_PROG_FUNCTION_REPLACE], -[dnl { -sed -e '/^$1 ()$/,/^} # $1 /c\ -$1 ()\ -{\ -m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) -} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: -]) - - -# _LT_PROG_REPLACE_SHELLFNS -# ------------------------- -# Replace existing portable implementations of several shell functions with -# equivalent extended shell implementations where those features are available.. -m4_defun([_LT_PROG_REPLACE_SHELLFNS], -[if test x"$xsi_shell" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl - func_split_long_opt_name=${1%%=*} - func_split_long_opt_arg=${1#*=}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) - - _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) - - _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) - - _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) -fi - -if test x"$lt_shell_append" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) - - _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl - func_quote_for_eval "${2}" -dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ - eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) -fi -]) - -# _LT_PATH_CONVERSION_FUNCTIONS -# ----------------------------- -# Determine which file name conversion functions should be used by -# func_to_host_file (and, implicitly, by func_to_host_path). These are needed -# for certain cross-compile configurations and native mingw. -m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_MSG_CHECKING([how to convert $build file names to $host format]) -AC_CACHE_VAL(lt_cv_to_host_file_cmd, -[case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac -]) -to_host_file_cmd=$lt_cv_to_host_file_cmd -AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) -_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], - [0], [convert $build file names to $host format])dnl - -AC_MSG_CHECKING([how to convert $build file names to toolchain format]) -AC_CACHE_VAL(lt_cv_to_tool_file_cmd, -[#assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac -]) -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) -_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], - [0], [convert $build files to toolchain format])dnl -])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ltoptions.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ltoptions.m4 deleted file mode 100644 index 5d9acd8e2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ltoptions.m4 +++ /dev/null @@ -1,384 +0,0 @@ -# Helper functions for option handling. -*- Autoconf -*- -# -# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 7 ltoptions.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) - - -# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) -# ------------------------------------------ -m4_define([_LT_MANGLE_OPTION], -[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) - - -# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) -# --------------------------------------- -# Set option OPTION-NAME for macro MACRO-NAME, and if there is a -# matching handler defined, dispatch to it. Other OPTION-NAMEs are -# saved as a flag. -m4_define([_LT_SET_OPTION], -[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl -m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), - _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl -]) - - -# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) -# ------------------------------------------------------------ -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -m4_define([_LT_IF_OPTION], -[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) - - -# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) -# ------------------------------------------------------- -# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME -# are set. -m4_define([_LT_UNLESS_OPTIONS], -[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), - [m4_define([$0_found])])])[]dnl -m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 -])[]dnl -]) - - -# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) -# ---------------------------------------- -# OPTION-LIST is a space-separated list of Libtool options associated -# with MACRO-NAME. If any OPTION has a matching handler declared with -# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about -# the unknown option and exit. -m4_defun([_LT_SET_OPTIONS], -[# Set options -m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [_LT_SET_OPTION([$1], _LT_Option)]) - -m4_if([$1],[LT_INIT],[ - dnl - dnl Simply set some default values (i.e off) if boolean options were not - dnl specified: - _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no - ]) - _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no - ]) - dnl - dnl If no reference was made to various pairs of opposing options, then - dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared - dnl archives by default: - _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) - _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - ]) -])# _LT_SET_OPTIONS - - -## --------------------------------- ## -## Macros to handle LT_INIT options. ## -## --------------------------------- ## - -# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) -# ----------------------------------------- -m4_define([_LT_MANGLE_DEFUN], -[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) - - -# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) -# ----------------------------------------------- -m4_define([LT_OPTION_DEFINE], -[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl -])# LT_OPTION_DEFINE - - -# dlopen -# ------ -LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes -]) - -AU_DEFUN([AC_LIBTOOL_DLOPEN], -[_LT_SET_OPTION([LT_INIT], [dlopen]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) - - -# win32-dll -# --------- -# Declare package support for building win32 dll's. -LT_OPTION_DEFINE([LT_INIT], [win32-dll], -[enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -esac - -test -z "$AS" && AS=as -_LT_DECL([], [AS], [1], [Assembler program])dnl - -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl - -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl -])# win32-dll - -AU_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -_LT_SET_OPTION([LT_INIT], [win32-dll]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) - - -# _LT_ENABLE_SHARED([DEFAULT]) -# ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_SHARED], -[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) - - _LT_DECL([build_libtool_libs], [enable_shared], [0], - [Whether or not to build shared libraries]) -])# _LT_ENABLE_SHARED - -LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) -]) - -AC_DEFUN([AC_DISABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], [disable-shared]) -]) - -AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_SHARED], []) -dnl AC_DEFUN([AM_DISABLE_SHARED], []) - - - -# _LT_ENABLE_STATIC([DEFAULT]) -# ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_STATIC], -[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]_LT_ENABLE_STATIC_DEFAULT) - - _LT_DECL([build_old_libs], [enable_static], [0], - [Whether or not to build static libraries]) -])# _LT_ENABLE_STATIC - -LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) -]) - -AC_DEFUN([AC_DISABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], [disable-static]) -]) - -AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_STATIC], []) -dnl AC_DEFUN([AM_DISABLE_STATIC], []) - - - -# _LT_ENABLE_FAST_INSTALL([DEFAULT]) -# ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_FAST_INSTALL], -[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([fast-install], - [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) - -_LT_DECL([fast_install], [enable_fast_install], [0], - [Whether or not to optimize for fast installation])dnl -])# _LT_ENABLE_FAST_INSTALL - -LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) - -# Old names: -AU_DEFUN([AC_ENABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) -]) - -AU_DEFUN([AC_DISABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) -dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) - - -# _LT_WITH_PIC([MODE]) -# -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' -# LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -m4_define([_LT_WITH_PIC], -[AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for lt_pkg in $withval; do - IFS="$lt_save_ifs" - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) - -_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl -])# _LT_WITH_PIC - -LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) - -# Old name: -AU_DEFUN([AC_LIBTOOL_PICMODE], -[_LT_SET_OPTION([LT_INIT], [pic-only]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) - -## ----------------- ## -## LTDL_INIT Options ## -## ----------------- ## - -m4_define([_LTDL_MODE], []) -LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], - [m4_define([_LTDL_MODE], [nonrecursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [recursive], - [m4_define([_LTDL_MODE], [recursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [subproject], - [m4_define([_LTDL_MODE], [subproject])]) - -m4_define([_LTDL_TYPE], []) -LT_OPTION_DEFINE([LTDL_INIT], [installable], - [m4_define([_LTDL_TYPE], [installable])]) -LT_OPTION_DEFINE([LTDL_INIT], [convenience], - [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ltsugar.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ltsugar.m4 deleted file mode 100644 index 9000a057d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ltsugar.m4 +++ /dev/null @@ -1,123 +0,0 @@ -# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltsugar.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) - - -# lt_join(SEP, ARG1, [ARG2...]) -# ----------------------------- -# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their -# associated separator. -# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier -# versions in m4sugar had bugs. -m4_define([lt_join], -[m4_if([$#], [1], [], - [$#], [2], [[$2]], - [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) -m4_define([_lt_join], -[m4_if([$#$2], [2], [], - [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) - - -# lt_car(LIST) -# lt_cdr(LIST) -# ------------ -# Manipulate m4 lists. -# These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. -m4_define([lt_car], [[$1]]) -m4_define([lt_cdr], -[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], - [$#], 1, [], - [m4_dquote(m4_shift($@))])]) -m4_define([lt_unquote], $1) - - -# lt_append(MACRO-NAME, STRING, [SEPARATOR]) -# ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. -# Note that neither SEPARATOR nor STRING are expanded; they are appended -# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). -# No SEPARATOR is output if MACRO-NAME was previously undefined (different -# than defined and empty). -# -# This macro is needed until we can rely on Autoconf 2.62, since earlier -# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. -m4_define([lt_append], -[m4_define([$1], - m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) - - - -# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) -# ---------------------------------------------------------- -# Produce a SEP delimited list of all paired combinations of elements of -# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list -# has the form PREFIXmINFIXSUFFIXn. -# Needed until we can rely on m4_combine added in Autoconf 2.62. -m4_define([lt_combine], -[m4_if(m4_eval([$# > 3]), [1], - [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl -[[m4_foreach([_Lt_prefix], [$2], - [m4_foreach([_Lt_suffix], - ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, - [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) - - -# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) -# ----------------------------------------------------------------------- -# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited -# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. -m4_define([lt_if_append_uniq], -[m4_ifdef([$1], - [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], - [lt_append([$1], [$2], [$3])$4], - [$5])], - [lt_append([$1], [$2], [$3])$4])]) - - -# lt_dict_add(DICT, KEY, VALUE) -# ----------------------------- -m4_define([lt_dict_add], -[m4_define([$1($2)], [$3])]) - - -# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) -# -------------------------------------------- -m4_define([lt_dict_add_subkey], -[m4_define([$1($2:$3)], [$4])]) - - -# lt_dict_fetch(DICT, KEY, [SUBKEY]) -# ---------------------------------- -m4_define([lt_dict_fetch], -[m4_ifval([$3], - m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), - m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) - - -# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) -# ----------------------------------------------------------------- -m4_define([lt_if_dict_fetch], -[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], - [$5], - [$6])]) - - -# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) -# -------------------------------------------------------------- -m4_define([lt_dict_filter], -[m4_if([$5], [], [], - [lt_join(m4_quote(m4_default([$4], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), - [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/ltversion.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/ltversion.m4 deleted file mode 100644 index 07a8602d4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/ltversion.m4 +++ /dev/null @@ -1,23 +0,0 @@ -# ltversion.m4 -- version numbers -*- Autoconf -*- -# -# Copyright (C) 2004 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# @configure_input@ - -# serial 3337 ltversion.m4 -# This file is part of GNU Libtool - -m4_define([LT_PACKAGE_VERSION], [2.4.2]) -m4_define([LT_PACKAGE_REVISION], [1.3337]) - -AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.2' -macro_revision='1.3337' -_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) -_LT_DECL(, macro_revision, 0) -]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/m4/lt~obsolete.m4 b/ruby/ext/fiddle/libffi-3.2.1/m4/lt~obsolete.m4 deleted file mode 100644 index c573da90c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/m4/lt~obsolete.m4 +++ /dev/null @@ -1,98 +0,0 @@ -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 5 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) -m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) -m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) -m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) -m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) -m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) -m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.am b/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.am deleted file mode 100644 index afcbfb69f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this with automake to create Makefile.in - -AUTOMAKE_OPTIONS=foreign - -EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3 - -man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3 - diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.in b/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.in deleted file mode 100644 index d92af74fb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/Makefile.in +++ /dev/null @@ -1,541 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = man -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \ - $(top_srcdir)/m4/ax_append_flag.m4 \ - $(top_srcdir)/m4/ax_cc_maxopt.m4 \ - $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_compiler_vendor.m4 \ - $(top_srcdir)/m4/ax_configure_args.m4 \ - $(top_srcdir)/m4/ax_enable_builddir.m4 \ - $(top_srcdir)/m4/ax_gcc_archflag.m4 \ - $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/fficonfig.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -man3dir = $(mandir)/man3 -am__installdirs = "$(DESTDIR)$(man3dir)" -NROFF = nroff -MANS = $(man_MANS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AM_LTLDFLAGS = @AM_LTLDFLAGS@ -AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ -HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PRTDIAG = @PRTDIAG@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TARGET = @TARGET@ -TARGETDIR = @TARGETDIR@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -ax_enable_builddir_sed = @ax_enable_builddir_sed@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sys_symbol_underscore = @sys_symbol_underscore@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -toolexecdir = @toolexecdir@ -toolexeclibdir = @toolexeclibdir@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign -EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3 -man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3 -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign man/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-man3: $(man_MANS) - @$(NORMAL_INSTALL) - @list1=''; \ - list2='$(man_MANS)'; \ - test -n "$(man3dir)" \ - && test -n "`echo $$list1$$list2`" \ - || exit 0; \ - echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ - { for i in $$list1; do echo "$$i"; done; \ - if test -n "$$list2"; then \ - for i in $$list2; do echo "$$i"; done \ - | sed -n '/\.3[a-z]*$$/p'; \ - fi; \ - } | while read p; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; echo "$$p"; \ - done | \ - sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ - sed 'N;N;s,\n, ,g' | { \ - list=; while read file base inst; do \ - if test "$$base" = "$$inst"; then list="$$list $$file"; else \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ - fi; \ - done; \ - for i in $$list; do echo "$$i"; done | $(am__base_list) | \ - while read files; do \ - test -z "$$files" || { \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ - done; } - -uninstall-man3: - @$(NORMAL_UNINSTALL) - @list=''; test -n "$(man3dir)" || exit 0; \ - files=`{ for i in $$list; do echo "$$i"; done; \ - l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ - sed -n '/\.3[a-z]*$$/p'; \ - } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(MANS) -installdirs: - for dir in "$(DESTDIR)$(man3dir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-man - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: install-man3 - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-man - -uninstall-man: uninstall-man3 - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - cscopelist-am ctags-am distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-man3 install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am tags-am uninstall uninstall-am uninstall-man \ - uninstall-man3 - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/ffi.3 b/ruby/ext/fiddle/libffi-3.2.1/man/ffi.3 deleted file mode 100644 index 1f1d3031c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/ffi.3 +++ /dev/null @@ -1,41 +0,0 @@ -.Dd February 15, 2008 -.Dt FFI 3 -.Sh NAME -.Nm FFI -.Nd Foreign Function Interface -.Sh LIBRARY -libffi, -lffi -.Sh SYNOPSIS -.In ffi.h -.Ft ffi_status -.Fo ffi_prep_cif -.Fa "ffi_cif *cif" -.Fa "ffi_abi abi" -.Fa "unsigned int nargs" -.Fa "ffi_type *rtype" -.Fa "ffi_type **atypes" -.Fc -.Ft void -.Fo ffi_prep_cif_var -.Fa "ffi_cif *cif" -.Fa "ffi_abi abi" -.Fa "unsigned int nfixedargs" -.Fa "unsigned int ntotalargs" -.Fa "ffi_type *rtype" -.Fa "ffi_type **atypes" -.Fc -.Ft void -.Fo ffi_call -.Fa "ffi_cif *cif" -.Fa "void (*fn)(void)" -.Fa "void *rvalue" -.Fa "void **avalue" -.Fc -.Sh DESCRIPTION -The foreign function interface provides a mechanism by which a function can -generate a call to another function at runtime without requiring knowledge of -the called function's interface at compile time. -.Sh SEE ALSO -.Xr ffi_prep_cif 3 , -.Xr ffi_prep_cif_var 3 , -.Xr ffi_call 3 diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_call.3 b/ruby/ext/fiddle/libffi-3.2.1/man/ffi_call.3 deleted file mode 100644 index 5351513f9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_call.3 +++ /dev/null @@ -1,103 +0,0 @@ -.Dd February 15, 2008 -.Dt ffi_call 3 -.Sh NAME -.Nm ffi_call -.Nd Invoke a foreign function. -.Sh SYNOPSIS -.In ffi.h -.Ft void -.Fo ffi_call -.Fa "ffi_cif *cif" -.Fa "void (*fn)(void)" -.Fa "void *rvalue" -.Fa "void **avalue" -.Fc -.Sh DESCRIPTION -The -.Nm ffi_call -function provides a simple mechanism for invoking a function without -requiring knowledge of the function's interface at compile time. -.Fa fn -is called with the values retrieved from the pointers in the -.Fa avalue -array. The return value from -.Fa fn -is placed in storage pointed to by -.Fa rvalue . -.Fa cif -contains information describing the data types, sizes and alignments of the -arguments to and return value from -.Fa fn , -and must be initialized with -.Nm ffi_prep_cif -before it is used with -.Nm ffi_call . -.Pp -.Fa rvalue -must point to storage that is sizeof(ffi_arg) or larger for non-floating point -types. For smaller-sized return value types, the -.Nm ffi_arg -or -.Nm ffi_sarg -integral type must be used to hold -the return value. -.Sh EXAMPLES -.Bd -literal -#include -#include - -unsigned char -foo(unsigned int, float); - -int -main(int argc, const char **argv) -{ - ffi_cif cif; - ffi_type *arg_types[2]; - void *arg_values[2]; - ffi_status status; - - // Because the return value from foo() is smaller than sizeof(long), it - // must be passed as ffi_arg or ffi_sarg. - ffi_arg result; - - // Specify the data type of each argument. Available types are defined - // in . - arg_types[0] = &ffi_type_uint; - arg_types[1] = &ffi_type_float; - - // Prepare the ffi_cif structure. - if ((status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, - 2, &ffi_type_uint8, arg_types)) != FFI_OK) - { - // Handle the ffi_status error. - } - - // Specify the values of each argument. - unsigned int arg1 = 42; - float arg2 = 5.1; - - arg_values[0] = &arg1; - arg_values[1] = &arg2; - - // Invoke the function. - ffi_call(&cif, FFI_FN(foo), &result, arg_values); - - // The ffi_arg 'result' now contains the unsigned char returned from foo(), - // which can be accessed by a typecast. - printf("result is %hhu", (unsigned char)result); - - return 0; -} - -// The target function. -unsigned char -foo(unsigned int x, float y) -{ - unsigned char result = x - y; - return result; -} -.Ed -.Sh SEE ALSO -.Xr ffi 3 , -.Xr ffi_prep_cif 3 diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif.3 b/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif.3 deleted file mode 100644 index ab2be8adc..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif.3 +++ /dev/null @@ -1,68 +0,0 @@ -.Dd February 15, 2008 -.Dt ffi_prep_cif 3 -.Sh NAME -.Nm ffi_prep_cif -.Nd Prepare a -.Nm ffi_cif -structure for use with -.Nm ffi_call -. -.Sh SYNOPSIS -.In ffi.h -.Ft ffi_status -.Fo ffi_prep_cif -.Fa "ffi_cif *cif" -.Fa "ffi_abi abi" -.Fa "unsigned int nargs" -.Fa "ffi_type *rtype" -.Fa "ffi_type **atypes" -.Fc -.Sh DESCRIPTION -The -.Nm ffi_prep_cif -function prepares a -.Nm ffi_cif -structure for use with -.Nm ffi_call -. -.Fa abi -specifies a set of calling conventions to use. -.Fa atypes -is an array of -.Fa nargs -pointers to -.Nm ffi_type -structs that describe the data type, size and alignment of each argument. -.Fa rtype -points to an -.Nm ffi_type -that describes the data type, size and alignment of the -return value. Note that to call a variadic function -.Nm ffi_prep_cif_var -must be used instead. -.Sh RETURN VALUES -Upon successful completion, -.Nm ffi_prep_cif -returns -.Nm FFI_OK . -It will return -.Nm FFI_BAD_TYPEDEF -if -.Fa cif -is -.Nm NULL -or -.Fa atypes -or -.Fa rtype -is malformed. If -.Fa abi -does not refer to a valid ABI, -.Nm FFI_BAD_ABI -will be returned. Available ABIs are -defined in -.Nm . -.Sh SEE ALSO -.Xr ffi 3 , -.Xr ffi_call 3 , -.Xr ffi_prep_cif_var 3 diff --git a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif_var.3 b/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif_var.3 deleted file mode 100644 index 7e19d0b07..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/man/ffi_prep_cif_var.3 +++ /dev/null @@ -1,73 +0,0 @@ -.Dd January 25, 2011 -.Dt ffi_prep_cif_var 3 -.Sh NAME -.Nm ffi_prep_cif_var -.Nd Prepare a -.Nm ffi_cif -structure for use with -.Nm ffi_call -for variadic functions. -.Sh SYNOPSIS -.In ffi.h -.Ft ffi_status -.Fo ffi_prep_cif_var -.Fa "ffi_cif *cif" -.Fa "ffi_abi abi" -.Fa "unsigned int nfixedargs" -.Fa "unsigned int ntotalargs" -.Fa "ffi_type *rtype" -.Fa "ffi_type **atypes" -.Fc -.Sh DESCRIPTION -The -.Nm ffi_prep_cif_var -function prepares a -.Nm ffi_cif -structure for use with -.Nm ffi_call -for variadic functions. -.Fa abi -specifies a set of calling conventions to use. -.Fa atypes -is an array of -.Fa ntotalargs -pointers to -.Nm ffi_type -structs that describe the data type, size and alignment of each argument. -.Fa rtype -points to an -.Nm ffi_type -that describes the data type, size and alignment of the -return value. -.Fa nfixedargs -must contain the number of fixed (non-variadic) arguments. -Note that to call a non-variadic function -.Nm ffi_prep_cif -must be used. -.Sh RETURN VALUES -Upon successful completion, -.Nm ffi_prep_cif_var -returns -.Nm FFI_OK . -It will return -.Nm FFI_BAD_TYPEDEF -if -.Fa cif -is -.Nm NULL -or -.Fa atypes -or -.Fa rtype -is malformed. If -.Fa abi -does not refer to a valid ABI, -.Nm FFI_BAD_ABI -will be returned. Available ABIs are -defined in -.Nm -. -.Sh SEE ALSO -.Xr ffi 3 , -.Xr ffi_call 3 , -.Xr ffi_prep_cif 3 diff --git a/ruby/ext/fiddle/libffi-3.2.1/mdate-sh b/ruby/ext/fiddle/libffi-3.2.1/mdate-sh deleted file mode 100755 index b3719cf76..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/mdate-sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/bin/sh -# Get modification time of a file or directory and pretty-print it. - -scriptversion=2010-08-21.06; # UTC - -# Copyright (C) 1995-2013 Free Software Foundation, Inc. -# written by Ulrich Drepper , June 1995 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -fi - -case $1 in - '') - echo "$0: No file. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: mdate-sh [--help] [--version] FILE - -Pretty-print the modification day of FILE, in the format: -1 January 1970 - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "mdate-sh $scriptversion" - exit $? - ;; -esac - -error () -{ - echo "$0: $1" >&2 - exit 1 -} - - -# Prevent date giving response in another language. -LANG=C -export LANG -LC_ALL=C -export LC_ALL -LC_TIME=C -export LC_TIME - -# GNU ls changes its time format in response to the TIME_STYLE -# variable. Since we cannot assume 'unset' works, revert this -# variable to its documented default. -if test "${TIME_STYLE+set}" = set; then - TIME_STYLE=posix-long-iso - export TIME_STYLE -fi - -save_arg1=$1 - -# Find out how to get the extended ls output of a file or directory. -if ls -L /dev/null 1>/dev/null 2>&1; then - ls_command='ls -L -l -d' -else - ls_command='ls -l -d' -fi -# Avoid user/group names that might have spaces, when possible. -if ls -n /dev/null 1>/dev/null 2>&1; then - ls_command="$ls_command -n" -fi - -# A 'ls -l' line looks as follows on OS/2. -# drwxrwx--- 0 Aug 11 2001 foo -# This differs from Unix, which adds ownership information. -# drwxrwx--- 2 root root 4096 Aug 11 2001 foo -# -# To find the date, we split the line on spaces and iterate on words -# until we find a month. This cannot work with files whose owner is a -# user named "Jan", or "Feb", etc. However, it's unlikely that '/' -# will be owned by a user whose name is a month. So we first look at -# the extended ls output of the root directory to decide how many -# words should be skipped to get the date. - -# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. -set x`$ls_command /` - -# Find which argument is the month. -month= -command= -until test $month -do - test $# -gt 0 || error "failed parsing '$ls_command /' output" - shift - # Add another shift to the command. - command="$command shift;" - case $1 in - Jan) month=January; nummonth=1;; - Feb) month=February; nummonth=2;; - Mar) month=March; nummonth=3;; - Apr) month=April; nummonth=4;; - May) month=May; nummonth=5;; - Jun) month=June; nummonth=6;; - Jul) month=July; nummonth=7;; - Aug) month=August; nummonth=8;; - Sep) month=September; nummonth=9;; - Oct) month=October; nummonth=10;; - Nov) month=November; nummonth=11;; - Dec) month=December; nummonth=12;; - esac -done - -test -n "$month" || error "failed parsing '$ls_command /' output" - -# Get the extended ls output of the file or directory. -set dummy x`eval "$ls_command \"\\\$save_arg1\""` - -# Remove all preceding arguments -eval $command - -# Because of the dummy argument above, month is in $2. -# -# On a POSIX system, we should have -# -# $# = 5 -# $1 = file size -# $2 = month -# $3 = day -# $4 = year or time -# $5 = filename -# -# On Darwin 7.7.0 and 7.6.0, we have -# -# $# = 4 -# $1 = day -# $2 = month -# $3 = year or time -# $4 = filename - -# Get the month. -case $2 in - Jan) month=January; nummonth=1;; - Feb) month=February; nummonth=2;; - Mar) month=March; nummonth=3;; - Apr) month=April; nummonth=4;; - May) month=May; nummonth=5;; - Jun) month=June; nummonth=6;; - Jul) month=July; nummonth=7;; - Aug) month=August; nummonth=8;; - Sep) month=September; nummonth=9;; - Oct) month=October; nummonth=10;; - Nov) month=November; nummonth=11;; - Dec) month=December; nummonth=12;; -esac - -case $3 in - ???*) day=$1;; - *) day=$3; shift;; -esac - -# Here we have to deal with the problem that the ls output gives either -# the time of day or the year. -case $3 in - *:*) set `date`; eval year=\$$# - case $2 in - Jan) nummonthtod=1;; - Feb) nummonthtod=2;; - Mar) nummonthtod=3;; - Apr) nummonthtod=4;; - May) nummonthtod=5;; - Jun) nummonthtod=6;; - Jul) nummonthtod=7;; - Aug) nummonthtod=8;; - Sep) nummonthtod=9;; - Oct) nummonthtod=10;; - Nov) nummonthtod=11;; - Dec) nummonthtod=12;; - esac - # For the first six month of the year the time notation can also - # be used for files modified in the last year. - if (expr $nummonth \> $nummonthtod) > /dev/null; - then - year=`expr $year - 1` - fi;; - *) year=$3;; -esac - -# The result. -echo $day $month $year - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/missing b/ruby/ext/fiddle/libffi-3.2.1/missing deleted file mode 100755 index cdea51493..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2012-06-26.16; # UTC - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/msvcc.sh b/ruby/ext/fiddle/libffi-3.2.1/msvcc.sh deleted file mode 100755 index 65fbfef7e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/msvcc.sh +++ /dev/null @@ -1,257 +0,0 @@ -#!/bin/sh - -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the MSVC wrappificator. -# -# The Initial Developer of the Original Code is -# Timothy Wall . -# Portions created by the Initial Developer are Copyright (C) 2009 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Daniel Witte -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# GCC-compatible wrapper for cl.exe and ml.exe. Arguments are given in GCC -# format and translated into something sensible for cl or ml. -# - -args_orig=$@ -args="-nologo -W3" -static_crt= -debug_crt= -cl="cl" -ml="ml" -safeseh="-safeseh" -output= - -while [ $# -gt 0 ] -do - case $1 - in - -fexceptions) - # Don't enable exceptions for now. - #args="$args -EHac" - shift 1 - ;; - -m32) - shift 1 - ;; - -m64) - ml="ml64" # "$MSVC/x86_amd64/ml64" - safeseh= - shift 1 - ;; - -clang-cl) - cl="clang-cl" - safeseh= - shift 1 - ;; - -O0) - args="$args -Od" - shift 1 - ;; - -O*) - # Runtime error checks (enabled by setting -RTC1 in the -DFFI_DEBUG - # case below) are not compatible with optimization flags and will - # cause the build to fail. Therefore, drop the optimization flag if - # -DFFI_DEBUG is also set. - case $args_orig in - *-DFFI_DEBUG*) - args="$args" - ;; - *) - # The ax_cc_maxopt.m4 macro from the upstream autoconf-archive - # project doesn't support MSVC and therefore ends up trying to - # use -O3. Use the equivalent "max optimization" flag for MSVC - # instead of erroring out. - case $1 in - -O3) - args="$args -O2" - ;; - *) - args="$args $1" - ;; - esac - opt="true" - ;; - esac - shift 1 - ;; - -g) - # Enable debug symbol generation. - args="$args -Zi" - shift 1 - ;; - -DFFI_DEBUG) - # Enable runtime error checks. - args="$args -RTC1" - defines="$defines $1" - shift 1 - ;; - -DUSE_STATIC_RTL) - # Link against static CRT. - static_crt=1 - shift 1 - ;; - -DUSE_DEBUG_RTL) - # Link against debug CRT. - debug_crt=1 - shift 1 - ;; - -c) - args="$args -c" - args="$(echo $args | sed 's%/Fe%/Fo%g')" - single="-c" - shift 1 - ;; - -D*=*) - name="$(echo $1|sed 's/-D\([^=][^=]*\)=.*/\1/g')" - value="$(echo $1|sed 's/-D[^=][^=]*=//g')" - args="$args -D${name}='$value'" - defines="$defines -D${name}='$value'" - shift 1 - ;; - -D*) - args="$args $1" - defines="$defines $1" - shift 1 - ;; - -I) - args="$args -I$2" - includes="$includes -I$2" - shift 2 - ;; - -I*) - args="$args $1" - includes="$includes $1" - shift 1 - ;; - -W|-Wextra) - # TODO map extra warnings - shift 1 - ;; - -Wall) - # -Wall on MSVC is overzealous, and we already build with -W3. Nothing - # to do here. - shift 1 - ;; - -pedantic) - # libffi tests -pedantic with -Wall, so drop it also. - shift 1 - ;; - -Werror) - args="$args -WX" - shift 1 - ;; - -W*) - # TODO map specific warnings - shift 1 - ;; - -S) - args="$args -FAs" - shift 1 - ;; - -o) - outdir="$(dirname $2)" - base="$(basename $2|sed 's/\.[^.]*//g')" - if [ -n "$single" ]; then - output="-Fo$2" - else - output="-Fe$2" - fi - if [ -n "$assembly" ]; then - args="$args $output" - else - args="$args $output -Fd$outdir/$base -Fp$outdir/$base -Fa$outdir/$base" - fi - shift 2 - ;; - *.S) - src=$1 - assembly="true" - shift 1 - ;; - *.c) - args="$args $1" - shift 1 - ;; - *) - # Assume it's an MSVC argument, and pass it through. - args="$args $1" - shift 1 - ;; - esac -done - -# If -Zi is specified, certain optimizations are implicitly disabled -# by MSVC. Add back those optimizations if this is an optimized build. -# NOTE: These arguments must come after all others. -if [ -n "$opt" ]; then - args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO" -fi - -if [ -n "$static_crt" ]; then - md=-MT -else - md=-MD -fi - -if [ -n "$debug_crt" ]; then - md="${md}d" -fi - -if [ -n "$assembly" ]; then - if [ -z "$outdir" ]; then - outdir="." - fi - ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')" - echo "$cl -nologo -EP $includes $defines $src > $ppsrc" - "$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $? - output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')" - args="-nologo $safeseh $single $output $ppsrc" - - echo "$ml $args" - eval "\"$ml\" $args" - result=$? - - # required to fix ml64 broken output? - #mv *.obj $outdir -else - args="$md $args" - echo "$cl $args" - # Return an error code of 1 if an invalid command line parameter is passed - # instead of just ignoring it. - eval "(\"$cl\" $args 2>&1 1>&3 | \ - awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1" - result=$? -fi - -exit $result - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffi.c deleted file mode 100644 index cdb7816e7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffi.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -``Software''), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include -#include - -#include - -/* Stack alignment requirement in bytes */ -#if defined (__APPLE__) -#define AARCH64_STACK_ALIGN 1 -#else -#define AARCH64_STACK_ALIGN 16 -#endif - -#define N_X_ARG_REG 8 -#define N_V_ARG_REG 8 - -#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT) - -union _d -{ - UINT64 d; - UINT32 s[2]; -}; - -struct call_context -{ - UINT64 x [AARCH64_N_XREG]; - struct - { - union _d d[2]; - } v [AARCH64_N_VREG]; -}; - -#if defined (__clang__) && defined (__APPLE__) -extern void -sys_icache_invalidate (void *start, size_t len); -#endif - -static inline void -ffi_clear_cache (void *start, void *end) -{ -#if defined (__clang__) && defined (__APPLE__) - sys_icache_invalidate (start, (char *)end - (char *)start); -#elif defined (__GNUC__) - __builtin___clear_cache (start, end); -#else -#error "Missing builtin to flush instruction cache" -#endif -} - -static void * -get_x_addr (struct call_context *context, unsigned n) -{ - return &context->x[n]; -} - -static void * -get_s_addr (struct call_context *context, unsigned n) -{ -#if defined __AARCH64EB__ - return &context->v[n].d[1].s[1]; -#else - return &context->v[n].d[0].s[0]; -#endif -} - -static void * -get_d_addr (struct call_context *context, unsigned n) -{ -#if defined __AARCH64EB__ - return &context->v[n].d[1]; -#else - return &context->v[n].d[0]; -#endif -} - -static void * -get_v_addr (struct call_context *context, unsigned n) -{ - return &context->v[n]; -} - -/* Return the memory location at which a basic type would reside - were it to have been stored in register n. */ - -static void * -get_basic_type_addr (unsigned short type, struct call_context *context, - unsigned n) -{ - switch (type) - { - case FFI_TYPE_FLOAT: - return get_s_addr (context, n); - case FFI_TYPE_DOUBLE: - return get_d_addr (context, n); -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - return get_v_addr (context, n); -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - return get_x_addr (context, n); - case FFI_TYPE_VOID: - return NULL; - default: - FFI_ASSERT (0); - return NULL; - } -} - -/* Return the alignment width for each of the basic types. */ - -static size_t -get_basic_type_alignment (unsigned short type) -{ - switch (type) - { - case FFI_TYPE_FLOAT: -#if defined (__APPLE__) - return sizeof (UINT32); -#endif - case FFI_TYPE_DOUBLE: - return sizeof (UINT64); -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - return sizeof (long double); -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: -#if defined (__APPLE__) - return sizeof (UINT8); -#endif - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: -#if defined (__APPLE__) - return sizeof (UINT16); -#endif - case FFI_TYPE_UINT32: - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: -#if defined (__APPLE__) - return sizeof (UINT32); -#endif - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - return sizeof (UINT64); - - default: - FFI_ASSERT (0); - return 0; - } -} - -/* Return the size in bytes for each of the basic types. */ - -static size_t -get_basic_type_size (unsigned short type) -{ - switch (type) - { - case FFI_TYPE_FLOAT: - return sizeof (UINT32); - case FFI_TYPE_DOUBLE: - return sizeof (UINT64); -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - return sizeof (long double); -#endif - case FFI_TYPE_UINT8: - return sizeof (UINT8); - case FFI_TYPE_SINT8: - return sizeof (SINT8); - case FFI_TYPE_UINT16: - return sizeof (UINT16); - case FFI_TYPE_SINT16: - return sizeof (SINT16); - case FFI_TYPE_UINT32: - return sizeof (UINT32); - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - return sizeof (SINT32); - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - return sizeof (UINT64); - case FFI_TYPE_SINT64: - return sizeof (SINT64); - - default: - FFI_ASSERT (0); - return 0; - } -} - -extern void -ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *, - extended_cif *), - struct call_context *context, - extended_cif *, - size_t, - void (*fn)(void)); - -extern void -ffi_closure_SYSV (ffi_closure *); - -/* Test for an FFI floating point representation. */ - -static unsigned -is_floating_type (unsigned short type) -{ - return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE - || type == FFI_TYPE_LONGDOUBLE); -} - -/* Test for a homogeneous structure. */ - -static unsigned short -get_homogeneous_type (ffi_type *ty) -{ - if (ty->type == FFI_TYPE_STRUCT && ty->elements) - { - unsigned i; - unsigned short candidate_type - = get_homogeneous_type (ty->elements[0]); - for (i =1; ty->elements[i]; i++) - { - unsigned short iteration_type = 0; - /* If we have a nested struct, we must find its homogeneous type. - If that fits with our candidate type, we are still - homogeneous. */ - if (ty->elements[i]->type == FFI_TYPE_STRUCT - && ty->elements[i]->elements) - { - iteration_type = get_homogeneous_type (ty->elements[i]); - } - else - { - iteration_type = ty->elements[i]->type; - } - - /* If we are not homogeneous, return FFI_TYPE_STRUCT. */ - if (candidate_type != iteration_type) - return FFI_TYPE_STRUCT; - } - return candidate_type; - } - - /* Base case, we have no more levels of nesting, so we - are a basic type, and so, trivially homogeneous in that type. */ - return ty->type; -} - -/* Determine the number of elements within a STRUCT. - - Note, we must handle nested structs. - - If ty is not a STRUCT this function will return 0. */ - -static unsigned -element_count (ffi_type *ty) -{ - if (ty->type == FFI_TYPE_STRUCT && ty->elements) - { - unsigned n; - unsigned elems = 0; - for (n = 0; ty->elements[n]; n++) - { - if (ty->elements[n]->type == FFI_TYPE_STRUCT - && ty->elements[n]->elements) - elems += element_count (ty->elements[n]); - else - elems++; - } - return elems; - } - return 0; -} - -/* Test for a homogeneous floating point aggregate. - - A homogeneous floating point aggregate is a homogeneous aggregate of - a half- single- or double- precision floating point type with one - to four elements. Note that this includes nested structs of the - basic type. */ - -static int -is_hfa (ffi_type *ty) -{ - if (ty->type == FFI_TYPE_STRUCT - && ty->elements[0] - && is_floating_type (get_homogeneous_type (ty))) - { - unsigned n = element_count (ty); - return n >= 1 && n <= 4; - } - return 0; -} - -/* Test if an ffi_type is a candidate for passing in a register. - - This test does not check that sufficient registers of the - appropriate class are actually available, merely that IFF - sufficient registers are available then the argument will be passed - in register(s). - - Note that an ffi_type that is deemed to be a register candidate - will always be returned in registers. - - Returns 1 if a register candidate else 0. */ - -static int -is_register_candidate (ffi_type *ty) -{ - switch (ty->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_UINT64: - case FFI_TYPE_POINTER: - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - case FFI_TYPE_SINT64: - return 1; - - case FFI_TYPE_STRUCT: - if (is_hfa (ty)) - { - return 1; - } - else if (ty->size > 16) - { - /* Too large. Will be replaced with a pointer to memory. The - pointer MAY be passed in a register, but the value will - not. This test specifically fails since the argument will - never be passed by value in registers. */ - return 0; - } - else - { - /* Might be passed in registers depending on the number of - registers required. */ - return (ty->size + 7) / 8 < N_X_ARG_REG; - } - break; - - default: - FFI_ASSERT (0); - break; - } - - return 0; -} - -/* Test if an ffi_type argument or result is a candidate for a vector - register. */ - -static int -is_v_register_candidate (ffi_type *ty) -{ - return is_floating_type (ty->type) - || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty)); -} - -/* Representation of the procedure call argument marshalling - state. - - The terse state variable names match the names used in the AARCH64 - PCS. */ - -struct arg_state -{ - unsigned ngrn; /* Next general-purpose register number. */ - unsigned nsrn; /* Next vector register number. */ - size_t nsaa; /* Next stack offset. */ - -#if defined (__APPLE__) - unsigned allocating_variadic; -#endif -}; - -/* Initialize a procedure call argument marshalling state. */ -static void -arg_init (struct arg_state *state, size_t call_frame_size) -{ - state->ngrn = 0; - state->nsrn = 0; - state->nsaa = 0; - -#if defined (__APPLE__) - state->allocating_variadic = 0; -#endif -} - -/* Return the number of available consecutive core argument - registers. */ - -static unsigned -available_x (struct arg_state *state) -{ - return N_X_ARG_REG - state->ngrn; -} - -/* Return the number of available consecutive vector argument - registers. */ - -static unsigned -available_v (struct arg_state *state) -{ - return N_V_ARG_REG - state->nsrn; -} - -static void * -allocate_to_x (struct call_context *context, struct arg_state *state) -{ - FFI_ASSERT (state->ngrn < N_X_ARG_REG); - return get_x_addr (context, (state->ngrn)++); -} - -static void * -allocate_to_s (struct call_context *context, struct arg_state *state) -{ - FFI_ASSERT (state->nsrn < N_V_ARG_REG); - return get_s_addr (context, (state->nsrn)++); -} - -static void * -allocate_to_d (struct call_context *context, struct arg_state *state) -{ - FFI_ASSERT (state->nsrn < N_V_ARG_REG); - return get_d_addr (context, (state->nsrn)++); -} - -static void * -allocate_to_v (struct call_context *context, struct arg_state *state) -{ - FFI_ASSERT (state->nsrn < N_V_ARG_REG); - return get_v_addr (context, (state->nsrn)++); -} - -/* Allocate an aligned slot on the stack and return a pointer to it. */ -static void * -allocate_to_stack (struct arg_state *state, void *stack, size_t alignment, - size_t size) -{ - void *allocation; - - /* Round up the NSAA to the larger of 8 or the natural - alignment of the argument's type. */ - state->nsaa = ALIGN (state->nsaa, alignment); - state->nsaa = ALIGN (state->nsaa, alignment); -#if defined (__APPLE__) - if (state->allocating_variadic) - state->nsaa = ALIGN (state->nsaa, 8); -#else - state->nsaa = ALIGN (state->nsaa, 8); -#endif - - allocation = stack + state->nsaa; - - state->nsaa += size; - return allocation; -} - -static void -copy_basic_type (void *dest, void *source, unsigned short type) -{ - /* This is necessary to ensure that basic types are copied - sign extended to 64-bits as libffi expects. */ - switch (type) - { - case FFI_TYPE_FLOAT: - *(float *) dest = *(float *) source; - break; - case FFI_TYPE_DOUBLE: - *(double *) dest = *(double *) source; - break; -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - *(long double *) dest = *(long double *) source; - break; -#endif - case FFI_TYPE_UINT8: - *(ffi_arg *) dest = *(UINT8 *) source; - break; - case FFI_TYPE_SINT8: - *(ffi_sarg *) dest = *(SINT8 *) source; - break; - case FFI_TYPE_UINT16: - *(ffi_arg *) dest = *(UINT16 *) source; - break; - case FFI_TYPE_SINT16: - *(ffi_sarg *) dest = *(SINT16 *) source; - break; - case FFI_TYPE_UINT32: - *(ffi_arg *) dest = *(UINT32 *) source; - break; - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - *(ffi_sarg *) dest = *(SINT32 *) source; - break; - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - *(ffi_arg *) dest = *(UINT64 *) source; - break; - case FFI_TYPE_SINT64: - *(ffi_sarg *) dest = *(SINT64 *) source; - break; - case FFI_TYPE_VOID: - break; - - default: - FFI_ASSERT (0); - } -} - -static void -copy_hfa_to_reg_or_stack (void *memory, - ffi_type *ty, - struct call_context *context, - unsigned char *stack, - struct arg_state *state) -{ - unsigned elems = element_count (ty); - if (available_v (state) < elems) - { - /* There are insufficient V registers. Further V register allocations - are prevented, the NSAA is adjusted (by allocate_to_stack ()) - and the argument is copied to memory at the adjusted NSAA. */ - state->nsrn = N_V_ARG_REG; - memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size), - memory, - ty->size); - } - else - { - int i; - unsigned short type = get_homogeneous_type (ty); - for (i = 0; i < elems; i++) - { - void *reg = allocate_to_v (context, state); - copy_basic_type (reg, memory, type); - memory += get_basic_type_size (type); - } - } -} - -/* Either allocate an appropriate register for the argument type, or if - none are available, allocate a stack slot and return a pointer - to the allocated space. */ - -static void * -allocate_to_register_or_stack (struct call_context *context, - unsigned char *stack, - struct arg_state *state, - unsigned short type) -{ - size_t alignment = get_basic_type_alignment (type); - size_t size = alignment; - switch (type) - { - case FFI_TYPE_FLOAT: - /* This is the only case for which the allocated stack size - should not match the alignment of the type. */ - size = sizeof (UINT32); - /* Fall through. */ - case FFI_TYPE_DOUBLE: - if (state->nsrn < N_V_ARG_REG) - return allocate_to_d (context, state); - state->nsrn = N_V_ARG_REG; - break; -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - if (state->nsrn < N_V_ARG_REG) - return allocate_to_v (context, state); - state->nsrn = N_V_ARG_REG; - break; -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (state->ngrn < N_X_ARG_REG) - return allocate_to_x (context, state); - state->ngrn = N_X_ARG_REG; - break; - default: - FFI_ASSERT (0); - } - - return allocate_to_stack (state, stack, alignment, size); -} - -/* Copy a value to an appropriate register, or if none are - available, to the stack. */ - -static void -copy_to_register_or_stack (struct call_context *context, - unsigned char *stack, - struct arg_state *state, - void *value, - unsigned short type) -{ - copy_basic_type ( - allocate_to_register_or_stack (context, stack, state, type), - value, - type); -} - -/* Marshall the arguments from FFI representation to procedure call - context and stack. */ - -static unsigned -aarch64_prep_args (struct call_context *context, unsigned char *stack, - extended_cif *ecif) -{ - int i; - struct arg_state state; - - arg_init (&state, ALIGN(ecif->cif->bytes, 16)); - - for (i = 0; i < ecif->cif->nargs; i++) - { - ffi_type *ty = ecif->cif->arg_types[i]; - switch (ty->type) - { - case FFI_TYPE_VOID: - FFI_ASSERT (0); - break; - - /* If the argument is a basic type the argument is allocated to an - appropriate register, or if none are available, to the stack. */ - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - copy_to_register_or_stack (context, stack, &state, - ecif->avalue[i], ty->type); - break; - - case FFI_TYPE_STRUCT: - if (is_hfa (ty)) - { - copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context, - stack, &state); - } - else if (ty->size > 16) - { - /* If the argument is a composite type that is larger than 16 - bytes, then the argument has been copied to memory, and - the argument is replaced by a pointer to the copy. */ - - copy_to_register_or_stack (context, stack, &state, - &(ecif->avalue[i]), FFI_TYPE_POINTER); - } - else if (available_x (&state) >= (ty->size + 7) / 8) - { - /* If the argument is a composite type and the size in - double-words is not more than the number of available - X registers, then the argument is copied into consecutive - X registers. */ - int j; - for (j = 0; j < (ty->size + 7) / 8; j++) - { - memcpy (allocate_to_x (context, &state), - &(((UINT64 *) ecif->avalue[i])[j]), - sizeof (UINT64)); - } - } - else - { - /* Otherwise, there are insufficient X registers. Further X - register allocations are prevented, the NSAA is adjusted - (by allocate_to_stack ()) and the argument is copied to - memory at the adjusted NSAA. */ - state.ngrn = N_X_ARG_REG; - - memcpy (allocate_to_stack (&state, stack, ty->alignment, - ty->size), ecif->avalue + i, ty->size); - } - break; - - default: - FFI_ASSERT (0); - break; - } - -#if defined (__APPLE__) - if (i + 1 == ecif->cif->aarch64_nfixedargs) - { - state.ngrn = N_X_ARG_REG; - state.nsrn = N_V_ARG_REG; - - state.allocating_variadic = 1; - } -#endif - } - - return ecif->cif->aarch64_flags; -} - -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* Round the stack up to a multiple of the stack alignment requirement. */ - cif->bytes = - (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1); - - /* Initialize our flags. We are interested if this CIF will touch a - vector register, if so we will enable context save and load to - those registers, otherwise not. This is intended to be friendly - to lazy float context switching in the kernel. */ - cif->aarch64_flags = 0; - - if (is_v_register_candidate (cif->rtype)) - { - cif->aarch64_flags |= AARCH64_FFI_WITH_V; - } - else - { - int i; - for (i = 0; i < cif->nargs; i++) - if (is_v_register_candidate (cif->arg_types[i])) - { - cif->aarch64_flags |= AARCH64_FFI_WITH_V; - break; - } - } - -#if defined (__APPLE__) - cif->aarch64_nfixedargs = 0; -#endif - - return FFI_OK; -} - -#if defined (__APPLE__) - -/* Perform Apple-specific cif processing for variadic calls */ -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, - unsigned int ntotalargs) -{ - ffi_status status; - - status = ffi_prep_cif_machdep (cif); - - cif->aarch64_nfixedargs = nfixedargs; - - return status; -} - -#endif - -/* Call a function with the provided arguments and capture the return - value. */ -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - { - struct call_context context; - size_t stack_bytes; - - /* Figure out the total amount of stack space we need, the - above call frame space needs to be 16 bytes aligned to - ensure correct alignment of the first object inserted in - that space hence the ALIGN applied to cif->bytes.*/ - stack_bytes = ALIGN(cif->bytes, 16); - - memset (&context, 0, sizeof (context)); - if (is_register_candidate (cif->rtype)) - { - ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn); - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_INT: - case FFI_TYPE_SINT64: - { - void *addr = get_basic_type_addr (cif->rtype->type, - &context, 0); - copy_basic_type (rvalue, addr, cif->rtype->type); - break; - } - - case FFI_TYPE_STRUCT: - if (is_hfa (cif->rtype)) - { - int j; - unsigned short type = get_homogeneous_type (cif->rtype); - unsigned elems = element_count (cif->rtype); - for (j = 0; j < elems; j++) - { - void *reg = get_basic_type_addr (type, &context, j); - copy_basic_type (rvalue, reg, type); - rvalue += get_basic_type_size (type); - } - } - else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) - { - size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)); - memcpy (rvalue, get_x_addr (&context, 0), size); - } - else - { - FFI_ASSERT (0); - } - break; - - default: - FFI_ASSERT (0); - break; - } - } - else - { - memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64)); - ffi_call_SYSV (aarch64_prep_args, &context, &ecif, - stack_bytes, fn); - } - break; - } - - default: - FFI_ASSERT (0); - break; - } -} - -static unsigned char trampoline [] = -{ 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */ - 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */ - 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ -}; - -/* Build a trampoline. */ - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \ - ({unsigned char *__tramp = (unsigned char*)(TRAMP); \ - UINT64 __fun = (UINT64)(FUN); \ - UINT64 __ctx = (UINT64)(CTX); \ - UINT64 __flags = (UINT64)(FLAGS); \ - memcpy (__tramp, trampoline, sizeof (trampoline)); \ - memcpy (__tramp + 12, &__fun, sizeof (__fun)); \ - memcpy (__tramp + 20, &__ctx, sizeof (__ctx)); \ - memcpy (__tramp + 28, &__flags, sizeof (__flags)); \ - ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \ - }) - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc, - cif->aarch64_flags); - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/* Primary handler to setup and invoke a function within a closure. - - A closure when invoked enters via the assembler wrapper - ffi_closure_SYSV(). The wrapper allocates a call context on the - stack, saves the interesting registers (from the perspective of - the calling convention) into the context then passes control to - ffi_closure_SYSV_inner() passing the saved context and a pointer to - the stack at the point ffi_closure_SYSV() was invoked. - - On the return path the assembler wrapper will reload call context - registers. - - ffi_closure_SYSV_inner() marshalls the call context into ffi value - descriptors, invokes the wrapped function, then marshalls the return - value back into the call context. */ - -void FFI_HIDDEN -ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context, - void *stack) -{ - ffi_cif *cif = closure->cif; - void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - void *rvalue = NULL; - int i; - struct arg_state state; - - arg_init (&state, ALIGN(cif->bytes, 16)); - - for (i = 0; i < cif->nargs; i++) - { - ffi_type *ty = cif->arg_types[i]; - - switch (ty->type) - { - case FFI_TYPE_VOID: - FFI_ASSERT (0); - break; - - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - avalue[i] = allocate_to_register_or_stack (context, stack, - &state, ty->type); - break; -#endif - - case FFI_TYPE_STRUCT: - if (is_hfa (ty)) - { - unsigned n = element_count (ty); - if (available_v (&state) < n) - { - state.nsrn = N_V_ARG_REG; - avalue[i] = allocate_to_stack (&state, stack, ty->alignment, - ty->size); - } - else - { - switch (get_homogeneous_type (ty)) - { - case FFI_TYPE_FLOAT: - { - /* Eeek! We need a pointer to the structure, - however the homogeneous float elements are - being passed in individual S registers, - therefore the structure is not represented as - a contiguous sequence of bytes in our saved - register context. We need to fake up a copy - of the structure laid out in memory - correctly. The fake can be tossed once the - closure function has returned hence alloca() - is sufficient. */ - int j; - UINT32 *p = avalue[i] = alloca (ty->size); - for (j = 0; j < element_count (ty); j++) - memcpy (&p[j], - allocate_to_s (context, &state), - sizeof (*p)); - break; - } - - case FFI_TYPE_DOUBLE: - { - /* Eeek! We need a pointer to the structure, - however the homogeneous float elements are - being passed in individual S registers, - therefore the structure is not represented as - a contiguous sequence of bytes in our saved - register context. We need to fake up a copy - of the structure laid out in memory - correctly. The fake can be tossed once the - closure function has returned hence alloca() - is sufficient. */ - int j; - UINT64 *p = avalue[i] = alloca (ty->size); - for (j = 0; j < element_count (ty); j++) - memcpy (&p[j], - allocate_to_d (context, &state), - sizeof (*p)); - break; - } - -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: - memcpy (&avalue[i], - allocate_to_v (context, &state), - sizeof (*avalue)); - break; -#endif - - default: - FFI_ASSERT (0); - break; - } - } - } - else if (ty->size > 16) - { - /* Replace Composite type of size greater than 16 with a - pointer. */ - memcpy (&avalue[i], - allocate_to_register_or_stack (context, stack, - &state, FFI_TYPE_POINTER), - sizeof (avalue[i])); - } - else if (available_x (&state) >= (ty->size + 7) / 8) - { - avalue[i] = get_x_addr (context, state.ngrn); - state.ngrn += (ty->size + 7) / 8; - } - else - { - state.ngrn = N_X_ARG_REG; - - avalue[i] = allocate_to_stack (&state, stack, ty->alignment, - ty->size); - } - break; - - default: - FFI_ASSERT (0); - break; - } - } - - /* Figure out where the return value will be passed, either in - registers or in a memory block allocated by the caller and passed - in x8. */ - - if (is_register_candidate (cif->rtype)) - { - /* Register candidates are *always* returned in registers. */ - - /* Allocate a scratchpad for the return value, we will let the - callee scrible the result into the scratch pad then move the - contents into the appropriate return value location for the - call convention. */ - rvalue = alloca (cif->rtype->size); - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Copy the return value into the call context so that it is returned - as expected to our caller. */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - break; - - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - { - void *addr = get_basic_type_addr (cif->rtype->type, context, 0); - copy_basic_type (addr, rvalue, cif->rtype->type); - break; - } - case FFI_TYPE_STRUCT: - if (is_hfa (cif->rtype)) - { - int j; - unsigned short type = get_homogeneous_type (cif->rtype); - unsigned elems = element_count (cif->rtype); - for (j = 0; j < elems; j++) - { - void *reg = get_basic_type_addr (type, context, j); - copy_basic_type (reg, rvalue, type); - rvalue += get_basic_type_size (type); - } - } - else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) - { - size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ; - memcpy (get_x_addr (context, 0), rvalue, size); - } - else - { - FFI_ASSERT (0); - } - break; - default: - FFI_ASSERT (0); - break; - } - } - else - { - memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64)); - (closure->fun) (cif, rvalue, avalue, closure->user_data); - } -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffitarget.h deleted file mode 100644 index 4bbced26f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/ffitarget.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. - -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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi - { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV - } ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 36 -#define FFI_NATIVE_RAW_API 0 - -/* ---- Internal ---- */ - -#if defined (__APPLE__) -#define FFI_TARGET_SPECIFIC_VARIADIC -#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags; unsigned aarch64_nfixedargs -#else -#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags -#endif - -#define AARCH64_FFI_WITH_V_BIT 0 - -#define AARCH64_N_XREG 32 -#define AARCH64_N_VREG 32 -#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16) - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/sysv.S deleted file mode 100644 index 169eab804..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/aarch64/sysv.S +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. - -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. */ - -#define LIBFFI_ASM -#include -#include - -#ifdef HAVE_MACHINE_ASM_H -#include -#else -#ifdef __USER_LABEL_PREFIX__ -#define CONCAT1(a, b) CONCAT2(a, b) -#define CONCAT2(a, b) a ## b - -/* Use the right prefix for global labels. */ -#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x) -#else -#define CNAME(x) x -#endif -#endif - -#define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off -#define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off -#define cfi_restore(reg) .cfi_restore reg -#define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg - - .text - .globl CNAME(ffi_call_SYSV) -#ifdef __ELF__ - .type CNAME(ffi_call_SYSV), #function -#endif -#ifdef __APPLE__ - .align 2 -#endif - -/* ffi_call_SYSV() - - Create a stack frame, setup an argument context, call the callee - and extract the result. - - The maximum required argument stack size is provided, - ffi_call_SYSV() allocates that stack space then calls the - prepare_fn to populate register context and stack. The - argument passing registers are loaded from the register - context and the callee called, on return the register passing - register are saved back to the context. Our caller will - extract the return value from the final state of the saved - register context. - - Prototype: - - extern unsigned - ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *, - extended_cif *), - struct call_context *context, - extended_cif *, - size_t required_stack_size, - void (*fn)(void)); - - Therefore on entry we have: - - x0 prepare_fn - x1 &context - x2 &ecif - x3 bytes - x4 fn - - This function uses the following stack frame layout: - - == - saved x30(lr) - x29(fp)-> saved x29(fp) - saved x24 - saved x23 - saved x22 - sp' -> saved x21 - ... - sp -> (constructed callee stack arguments) - == - - Voila! */ - -#define ffi_call_SYSV_FS (8 * 4) - - .cfi_startproc -CNAME(ffi_call_SYSV): - stp x29, x30, [sp, #-16]! - cfi_adjust_cfa_offset (16) - cfi_rel_offset (x29, 0) - cfi_rel_offset (x30, 8) - - mov x29, sp - cfi_def_cfa_register (x29) - sub sp, sp, #ffi_call_SYSV_FS - - stp x21, x22, [sp, #0] - cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS) - cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS) - - stp x23, x24, [sp, #16] - cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS) - cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS) - - mov x21, x1 - mov x22, x2 - mov x24, x4 - - /* Allocate the stack space for the actual arguments, many - arguments will be passed in registers, but we assume - worst case and allocate sufficient stack for ALL of - the arguments. */ - sub sp, sp, x3 - - /* unsigned (*prepare_fn) (struct call_context *context, - unsigned char *stack, extended_cif *ecif); - */ - mov x23, x0 - mov x0, x1 - mov x1, sp - /* x2 already in place */ - blr x23 - - /* Preserve the flags returned. */ - mov x23, x0 - - /* Figure out if we should touch the vector registers. */ - tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f - - /* Load the vector argument passing registers. */ - ldp q0, q1, [x21, #8*32 + 0] - ldp q2, q3, [x21, #8*32 + 32] - ldp q4, q5, [x21, #8*32 + 64] - ldp q6, q7, [x21, #8*32 + 96] -1: - /* Load the core argument passing registers. */ - ldp x0, x1, [x21, #0] - ldp x2, x3, [x21, #16] - ldp x4, x5, [x21, #32] - ldp x6, x7, [x21, #48] - - /* Don't forget x8 which may be holding the address of a return buffer. - */ - ldr x8, [x21, #8*8] - - blr x24 - - /* Save the core argument passing registers. */ - stp x0, x1, [x21, #0] - stp x2, x3, [x21, #16] - stp x4, x5, [x21, #32] - stp x6, x7, [x21, #48] - - /* Note nothing useful ever comes back in x8! */ - - /* Figure out if we should touch the vector registers. */ - tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f - - /* Save the vector argument passing registers. */ - stp q0, q1, [x21, #8*32 + 0] - stp q2, q3, [x21, #8*32 + 32] - stp q4, q5, [x21, #8*32 + 64] - stp q6, q7, [x21, #8*32 + 96] -1: - /* All done, unwind our stack frame. */ - ldp x21, x22, [x29, # - ffi_call_SYSV_FS] - cfi_restore (x21) - cfi_restore (x22) - - ldp x23, x24, [x29, # - ffi_call_SYSV_FS + 16] - cfi_restore (x23) - cfi_restore (x24) - - mov sp, x29 - cfi_def_cfa_register (sp) - - ldp x29, x30, [sp], #16 - cfi_adjust_cfa_offset (-16) - cfi_restore (x29) - cfi_restore (x30) - - ret - - .cfi_endproc -#ifdef __ELF__ - .size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV) -#endif - -#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE) - -/* ffi_closure_SYSV - - Closure invocation glue. This is the low level code invoked directly by - the closure trampoline to setup and call a closure. - - On entry x17 points to a struct trampoline_data, x16 has been clobbered - all other registers are preserved. - - We allocate a call context and save the argument passing registers, - then invoked the generic C ffi_closure_SYSV_inner() function to do all - the real work, on return we load the result passing registers back from - the call context. - - On entry - - extern void - ffi_closure_SYSV (struct trampoline_data *); - - struct trampoline_data - { - UINT64 *ffi_closure; - UINT64 flags; - }; - - This function uses the following stack frame layout: - - == - saved x30(lr) - x29(fp)-> saved x29(fp) - saved x22 - saved x21 - ... - sp -> call_context - == - - Voila! */ - - .text - .globl CNAME(ffi_closure_SYSV) -#ifdef __APPLE__ - .align 2 -#endif - .cfi_startproc -CNAME(ffi_closure_SYSV): - stp x29, x30, [sp, #-16]! - cfi_adjust_cfa_offset (16) - cfi_rel_offset (x29, 0) - cfi_rel_offset (x30, 8) - - mov x29, sp - cfi_def_cfa_register (x29) - - sub sp, sp, #ffi_closure_SYSV_FS - - stp x21, x22, [x29, #-16] - cfi_rel_offset (x21, -16) - cfi_rel_offset (x22, -8) - - /* Load x21 with &call_context. */ - mov x21, sp - /* Preserve our struct trampoline_data * */ - mov x22, x17 - - /* Save the rest of the argument passing registers. */ - stp x0, x1, [x21, #0] - stp x2, x3, [x21, #16] - stp x4, x5, [x21, #32] - stp x6, x7, [x21, #48] - /* Don't forget we may have been given a result scratch pad address. - */ - str x8, [x21, #64] - - /* Figure out if we should touch the vector registers. */ - ldr x0, [x22, #8] - tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f - - /* Save the argument passing vector registers. */ - stp q0, q1, [x21, #8*32 + 0] - stp q2, q3, [x21, #8*32 + 32] - stp q4, q5, [x21, #8*32 + 64] - stp q6, q7, [x21, #8*32 + 96] -1: - /* Load &ffi_closure.. */ - ldr x0, [x22, #0] - mov x1, x21 - /* Compute the location of the stack at the point that the - trampoline was called. */ - add x2, x29, #16 - - bl CNAME(ffi_closure_SYSV_inner) - - /* Figure out if we should touch the vector registers. */ - ldr x0, [x22, #8] - tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f - - /* Load the result passing vector registers. */ - ldp q0, q1, [x21, #8*32 + 0] - ldp q2, q3, [x21, #8*32 + 32] - ldp q4, q5, [x21, #8*32 + 64] - ldp q6, q7, [x21, #8*32 + 96] -1: - /* Load the result passing core registers. */ - ldp x0, x1, [x21, #0] - ldp x2, x3, [x21, #16] - ldp x4, x5, [x21, #32] - ldp x6, x7, [x21, #48] - /* Note nothing useful is returned in x8. */ - - /* We are done, unwind our frame. */ - ldp x21, x22, [x29, #-16] - cfi_restore (x21) - cfi_restore (x22) - - mov sp, x29 - cfi_def_cfa_register (sp) - - ldp x29, x30, [sp], #16 - cfi_adjust_cfa_offset (-16) - cfi_restore (x29) - cfi_restore (x30) - - ret - .cfi_endproc -#ifdef __ELF__ - .size CNAME(ffi_closure_SYSV), .-CNAME(ffi_closure_SYSV) -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffi.c deleted file mode 100644 index 192f691c4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffi.c +++ /dev/null @@ -1,288 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2012 Anthony Green - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. - - Alpha Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include -#include - -/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; - all further uses in this file will refer to the 128-bit type. */ -#if defined(__LONG_DOUBLE_128__) -# if FFI_TYPE_LONGDOUBLE != 4 -# error FFI_TYPE_LONGDOUBLE out of date -# endif -#else -# undef FFI_TYPE_LONGDOUBLE -# define FFI_TYPE_LONGDOUBLE 4 -#endif - -extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void)) - FFI_HIDDEN; -extern void ffi_closure_osf(void) FFI_HIDDEN; - - -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* Adjust cif->bytes to represent a minimum 6 words for the temporary - register argument loading area. */ - if (cif->bytes < 6*FFI_SIZEOF_ARG) - cif->bytes = 6*FFI_SIZEOF_ARG; - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_STRUCT: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags = cif->rtype->type; - break; - - case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is returned in memory, like a struct. */ - cif->flags = FFI_TYPE_STRUCT; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - - -void -ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - unsigned long *stack, *argp; - long i, avn; - ffi_type **arg_types; - - /* If the return value is a struct and we don't have a return - value address then we need to make one. */ - if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT) - rvalue = alloca(cif->rtype->size); - - /* Allocate the space for the arguments, plus 4 words of temp - space for ffi_call_osf. */ - argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); - - if (cif->flags == FFI_TYPE_STRUCT) - *(void **) argp++ = rvalue; - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - while (i < avn) - { - size_t size = (*arg_types)->size; - - switch ((*arg_types)->type) - { - case FFI_TYPE_SINT8: - *(SINT64 *) argp = *(SINT8 *)(* avalue); - break; - - case FFI_TYPE_UINT8: - *(SINT64 *) argp = *(UINT8 *)(* avalue); - break; - - case FFI_TYPE_SINT16: - *(SINT64 *) argp = *(SINT16 *)(* avalue); - break; - - case FFI_TYPE_UINT16: - *(SINT64 *) argp = *(UINT16 *)(* avalue); - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - /* Note that unsigned 32-bit quantities are sign extended. */ - *(SINT64 *) argp = *(SINT32 *)(* avalue); - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_POINTER: - *(UINT64 *) argp = *(UINT64 *)(* avalue); - break; - - case FFI_TYPE_FLOAT: - if (argp - stack < 6) - { - /* Note the conversion -- all the fp regs are loaded as - doubles. The in-register format is the same. */ - *(double *) argp = *(float *)(* avalue); - } - else - *(float *) argp = *(float *)(* avalue); - break; - - case FFI_TYPE_DOUBLE: - *(double *) argp = *(double *)(* avalue); - break; - - case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is passed by reference. */ - *(long double **) argp = (long double *)(* avalue); - size = sizeof (long double *); - break; - - case FFI_TYPE_STRUCT: - memcpy(argp, *avalue, (*arg_types)->size); - break; - - default: - FFI_ASSERT(0); - } - - argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++, arg_types++, avalue++; - } - - ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn); -} - - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp; - - if (cif->abi != FFI_OSF) - return FFI_BAD_ABI; - - tramp = (unsigned int *) &closure->tramp[0]; - tramp[0] = 0x47fb0401; /* mov $27,$1 */ - tramp[1] = 0xa77b0010; /* ldq $27,16($27) */ - tramp[2] = 0x6bfb0000; /* jmp $31,($27),0 */ - tramp[3] = 0x47ff041f; /* nop */ - *(void **) &tramp[4] = ffi_closure_osf; - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Flush the Icache. - - Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal - instead, since both Compaq as and gas can handle it. - - 0x86 is PAL_imb in Tru64 UNIX . */ - asm volatile ("call_pal 0x86" : : : "memory"); - - return FFI_OK; -} - - -long FFI_HIDDEN -ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) -{ - ffi_cif *cif; - void **avalue; - ffi_type **arg_types; - long i, avn, argn; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - - argn = 0; - - /* Copy the caller's structure return address to that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT) - { - rvalue = (void *) argp[0]; - argn = 1; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - size_t size = arg_types[i]->size; - - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_POINTER: - case FFI_TYPE_STRUCT: - avalue[i] = &argp[argn]; - break; - - case FFI_TYPE_FLOAT: - if (argn < 6) - { - /* Floats coming from registers need conversion from double - back to float format. */ - *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; - avalue[i] = &argp[argn - 6]; - } - else - avalue[i] = &argp[argn]; - break; - - case FFI_TYPE_DOUBLE: - avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)]; - break; - - case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is passed by reference. */ - avalue[i] = (long double *) argp[argn]; - size = sizeof (long double *); - break; - - default: - abort (); - } - - argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++; - } - - /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_osf how to perform return type promotions. */ - return cif->rtype->type; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffitarget.h deleted file mode 100644 index af145bce8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for Alpha. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_OSF, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_OSF -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 24 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/osf.S b/ruby/ext/fiddle/libffi-3.2.1/src/alpha/osf.S deleted file mode 100644 index 6b9f4dfa0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/alpha/osf.S +++ /dev/null @@ -1,387 +0,0 @@ -/* ----------------------------------------------------------------------- - osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat - - Alpha/OSF Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - .arch ev6 - .text - -/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); - - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame - for this function. This has been allocated by ffi_call. We also - deallocate some of the stack that has been alloca'd. */ - - .align 3 - .globl ffi_call_osf - .ent ffi_call_osf - FFI_HIDDEN(ffi_call_osf) - -ffi_call_osf: - .frame $15, 32, $26, 0 - .mask 0x4008000, -32 -$LFB1: - addq $16,$17,$1 - mov $16, $30 - stq $26, 0($1) - stq $15, 8($1) - stq $18, 16($1) - mov $1, $15 -$LCFI1: - .prologue 0 - - stq $19, 24($1) - mov $20, $27 - - # Load up all of the (potential) argument registers. - ldq $16, 0($30) - ldt $f16, 0($30) - ldt $f17, 8($30) - ldq $17, 8($30) - ldt $f18, 16($30) - ldq $18, 16($30) - ldt $f19, 24($30) - ldq $19, 24($30) - ldt $f20, 32($30) - ldq $20, 32($30) - ldt $f21, 40($30) - ldq $21, 40($30) - - # Deallocate the register argument area. - lda $30, 48($30) - - jsr $26, ($27), 0 - ldgp $29, 0($26) - - # If the return value pointer is NULL, assume no return value. - ldq $19, 24($15) - ldq $18, 16($15) - ldq $26, 0($15) -$LCFI2: - beq $19, $noretval - - # Store the return value out in the proper type. - cmpeq $18, FFI_TYPE_INT, $1 - bne $1, $retint - cmpeq $18, FFI_TYPE_FLOAT, $2 - bne $2, $retfloat - cmpeq $18, FFI_TYPE_DOUBLE, $3 - bne $3, $retdouble - - .align 3 -$noretval: - ldq $15, 8($15) - ret - - .align 4 -$retint: - stq $0, 0($19) - nop - ldq $15, 8($15) - ret - - .align 4 -$retfloat: - sts $f0, 0($19) - nop - ldq $15, 8($15) - ret - - .align 4 -$retdouble: - stt $f0, 0($19) - nop - ldq $15, 8($15) - ret -$LFE1: - - .end ffi_call_osf - -/* ffi_closure_osf(...) - - Receives the closure argument in $1. */ - - .align 3 - .globl ffi_closure_osf - .ent ffi_closure_osf - FFI_HIDDEN(ffi_closure_osf) - -ffi_closure_osf: - .frame $30, 16*8, $26, 0 - .mask 0x4000000, -16*8 -$LFB2: - ldgp $29, 0($27) - subq $30, 16*8, $30 -$LCFI5: - stq $26, 0($30) -$LCFI6: - .prologue 1 - - # Store all of the potential argument registers in va_list format. - stt $f16, 4*8($30) - stt $f17, 5*8($30) - stt $f18, 6*8($30) - stt $f19, 7*8($30) - stt $f20, 8*8($30) - stt $f21, 9*8($30) - stq $16, 10*8($30) - stq $17, 11*8($30) - stq $18, 12*8($30) - stq $19, 13*8($30) - stq $20, 14*8($30) - stq $21, 15*8($30) - - # Call ffi_closure_osf_inner to do the bulk of the work. - mov $1, $16 - lda $17, 2*8($30) - lda $18, 10*8($30) - jsr $26, ffi_closure_osf_inner - ldgp $29, 0($26) - ldq $26, 0($30) - - # Load up the return value in the proper type. - lda $1, $load_table - s4addq $0, $1, $1 - ldl $1, 0($1) - addq $1, $29, $1 - jmp $31, ($1), $load_32 - - .align 4 -$load_none: - addq $30, 16*8, $30 - ret - - .align 4 -$load_float: - lds $f0, 16($30) - nop - addq $30, 16*8, $30 - ret - - .align 4 -$load_double: - ldt $f0, 16($30) - nop - addq $30, 16*8, $30 - ret - - .align 4 -$load_u8: -#ifdef __alpha_bwx__ - ldbu $0, 16($30) - nop -#else - ldq $0, 16($30) - and $0, 255, $0 -#endif - addq $30, 16*8, $30 - ret - - .align 4 -$load_s8: -#ifdef __alpha_bwx__ - ldbu $0, 16($30) - sextb $0, $0 -#else - ldq $0, 16($30) - sll $0, 56, $0 - sra $0, 56, $0 -#endif - addq $30, 16*8, $30 - ret - - .align 4 -$load_u16: -#ifdef __alpha_bwx__ - ldwu $0, 16($30) - nop -#else - ldq $0, 16($30) - zapnot $0, 3, $0 -#endif - addq $30, 16*8, $30 - ret - - .align 4 -$load_s16: -#ifdef __alpha_bwx__ - ldwu $0, 16($30) - sextw $0, $0 -#else - ldq $0, 16($30) - sll $0, 48, $0 - sra $0, 48, $0 -#endif - addq $30, 16*8, $30 - ret - - .align 4 -$load_32: - ldl $0, 16($30) - nop - addq $30, 16*8, $30 - ret - - .align 4 -$load_64: - ldq $0, 16($30) - nop - addq $30, 16*8, $30 - ret -$LFE2: - - .end ffi_closure_osf - -#ifdef __ELF__ -.section .rodata -#else -.rdata -#endif -$load_table: - .gprel32 $load_none # FFI_TYPE_VOID - .gprel32 $load_32 # FFI_TYPE_INT - .gprel32 $load_float # FFI_TYPE_FLOAT - .gprel32 $load_double # FFI_TYPE_DOUBLE - .gprel32 $load_none # FFI_TYPE_LONGDOUBLE - .gprel32 $load_u8 # FFI_TYPE_UINT8 - .gprel32 $load_s8 # FFI_TYPE_SINT8 - .gprel32 $load_u16 # FFI_TYPE_UINT16 - .gprel32 $load_s16 # FFI_TYPE_SINT16 - .gprel32 $load_32 # FFI_TYPE_UINT32 - .gprel32 $load_32 # FFI_TYPE_SINT32 - .gprel32 $load_64 # FFI_TYPE_UINT64 - .gprel32 $load_64 # FFI_TYPE_SINT64 - .gprel32 $load_none # FFI_TYPE_STRUCT - .gprel32 $load_64 # FFI_TYPE_POINTER - -/* Assert that the table above is in sync with ffi.h. */ - -#if FFI_TYPE_FLOAT != 2 \ - || FFI_TYPE_DOUBLE != 3 \ - || FFI_TYPE_UINT8 != 5 \ - || FFI_TYPE_SINT8 != 6 \ - || FFI_TYPE_UINT16 != 7 \ - || FFI_TYPE_SINT16 != 8 \ - || FFI_TYPE_UINT32 != 9 \ - || FFI_TYPE_SINT32 != 10 \ - || FFI_TYPE_UINT64 != 11 \ - || FFI_TYPE_SINT64 != 12 \ - || FFI_TYPE_STRUCT != 13 \ - || FFI_TYPE_POINTER != 14 \ - || FFI_TYPE_LAST != 14 -#error "osf.S out of sync with ffi.h" -#endif - -#ifdef __ELF__ -# define UA_SI .4byte -# define FDE_ENCODING 0x1b /* pcrel sdata4 */ -# define FDE_ENCODE(X) .4byte X-. -# define FDE_ARANGE(X) .4byte X -#elif defined __osf__ -# define UA_SI .align 0; .long -# define FDE_ENCODING 0x50 /* aligned absolute */ -# define FDE_ENCODE(X) .align 3; .quad X -# define FDE_ARANGE(X) .align 0; .quad X -#endif - -#ifdef __ELF__ - .section .eh_frame,EH_FRAME_FLAGS,@progbits -#elif defined __osf__ - .data - .align 3 - .globl _GLOBAL__F_ffi_call_osf -_GLOBAL__F_ffi_call_osf: -#endif -__FRAME_BEGIN__: - UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry -$LSCIE1: - UA_SI 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor - .byte 0x78 # sleb128 -8; CIE Data Alignment Factor - .byte 26 # CIE RA Column - .byte 0x1 # uleb128 0x1; Augmentation size - .byte FDE_ENCODING # FDE Encoding - .byte 0xc # DW_CFA_def_cfa - .byte 30 # uleb128 column 30 - .byte 0 # uleb128 offset 0 - .align 3 -$LECIE1: -$LSFDE1: - UA_SI $LEFDE1-$LASFDE1 # FDE Length -$LASFDE1: - UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset - FDE_ENCODE($LFB1) # FDE initial location - FDE_ARANGE($LFE1-$LFB1) # FDE address range - .byte 0x0 # uleb128 0x0; Augmentation size - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI1-$LFB1 - .byte 0x9a # DW_CFA_offset, column 26 - .byte 4 # uleb128 4*-8 - .byte 0x8f # DW_CFA_offset, column 15 - .byte 0x3 # uleb128 3*-8 - .byte 0xc # DW_CFA_def_cfa - .byte 15 # uleb128 column 15 - .byte 32 # uleb128 offset 32 - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI2-$LCFI1 - .byte 0xda # DW_CFA_restore, column 26 - .align 3 -$LEFDE1: - -$LSFDE3: - UA_SI $LEFDE3-$LASFDE3 # FDE Length -$LASFDE3: - UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset - FDE_ENCODE($LFB2) # FDE initial location - FDE_ARANGE($LFE2-$LFB2) # FDE address range - .byte 0x0 # uleb128 0x0; Augmentation size - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI5-$LFB2 - .byte 0xe # DW_CFA_def_cfa_offset - .byte 0x80,0x1 # uleb128 128 - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI6-$LCFI5 - .byte 0x9a # DW_CFA_offset, column 26 - .byte 16 # uleb128 offset 16*-8 - .align 3 -$LEFDE3: -#if defined __osf__ - .align 0 - .long 0 # End of Table -#endif - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arc/arcompact.S b/ruby/ext/fiddle/libffi-3.2.1/src/arc/arcompact.S deleted file mode 100644 index 03715fde4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arc/arcompact.S +++ /dev/null @@ -1,135 +0,0 @@ -/* ----------------------------------------------------------------------- - arcompact.S - Copyright (c) 2013 Synposys, Inc. (www.synopsys.com) - - ARCompact Foreign Function Interface - - 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 RENESAS TECHNOLOGY 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -#define CNAME(x) x -#define ENTRY(x) .globl CNAME(x)` .type CNAME(x),%function` CNAME(x): -#endif - -.text - - /* R0: ffi_prep_args */ - /* R1: &ecif */ - /* R2: cif->bytes */ - /* R3: fig->flags */ - /* R4: ecif.rvalue */ - /* R5: fn */ -ENTRY(ffi_call_ARCompact) - /* Save registers. */ - st.a fp, [sp, -4] /* fp + 20, fp */ - push_s blink /* fp + 16, blink */ - st.a r4, [sp, -4] /* fp + 12, ecif.rvalue */ - push_s r3 /* fp + 8, fig->flags */ - st.a r5, [sp, -4] /* fp + 4, fn */ - push_s r2 /* fp + 0, cif->bytes */ - mov fp, sp - - /* Make room for all of the new args. */ - sub sp, sp, r2 - - /* Place all of the ffi_prep_args in position. */ - /* ffi_prep_args(char *stack, extended_cif *ecif) */ - /* R1 already set. */ - - /* And call. */ - jl_s.d [r0] - mov_s r0, sp - - ld.ab r12, [fp, 4] /* cif->bytes */ - ld.ab r11, [fp, 4] /* fn */ - - /* Move first 8 parameters in registers... */ - ld_s r0, [sp] - ld_s r1, [sp, 4] - ld_s r2, [sp, 8] - ld_s r3, [sp, 12] - ld r4, [sp, 16] - ld r5, [sp, 20] - ld r6, [sp, 24] - ld r7, [sp, 28] - - /* ...and adjust the stack. */ - min r12, r12, 32 - - /* Call the function. */ - jl.d [r11] - add sp, sp, r12 - - mov sp, fp - pop_s r3 /* fig->flags, return type */ - pop_s r2 /* ecif.rvalue, pointer for return value */ - - /* If the return value pointer is NULL, assume no return value. */ - breq.d r2, 0, epilogue - pop_s blink - - /* Return INT. */ - brne r3, FFI_TYPE_INT, return_double - b.d epilogue - st_s r0, [r2] - -return_double: - brne r3, FFI_TYPE_DOUBLE, epilogue - st_s r0, [r2] - st_s r1, [r2,4] - -epilogue: - j_s.d [blink] - ld.ab fp, [sp, 4] - -ENTRY(ffi_closure_ARCompact) - st.a r0, [sp, -32] - st_s r1, [sp, 4] - st_s r2, [sp, 8] - st_s r3, [sp, 12] - st r4, [sp, 16] - st r5, [sp, 20] - st r6, [sp, 24] - st r7, [sp, 28] - - /* pointer to arguments */ - mov_s r2, sp - - /* return value goes here */ - sub sp, sp, 8 - mov_s r1, sp - - push_s blink - - bl.d ffi_closure_inner_ARCompact - mov_s r0, r8 /* codeloc, set by trampoline */ - - pop_s blink - - /* set return value to r1:r0 */ - pop_s r0 - pop_s r1 - j_s.d [blink] - add_s sp, sp, 32 diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffi.c deleted file mode 100644 index 32f82a7d5..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffi.c +++ /dev/null @@ -1,268 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com) - - ARC Foreign Function Interface - - 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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include - -#include - -/* for little endian ARC, the code is in fact stored as mixed endian for - performance reasons */ -#if __BIG_ENDIAN__ -#define CODE_ENDIAN(x) (x) -#else -#define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16)) -#endif - -/* ffi_prep_args is called by the assembly routine once stack - space has been allocated for the function's arguments. */ - -void -ffi_prep_args (char *stack, extended_cif * ecif) -{ - unsigned int i; - int tmp; - void **p_argv; - char *argp; - ffi_type **p_arg; - - tmp = 0; - argp = stack; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) - { - *(void **) argp = ecif->rvalue; - argp += 4; - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); i--, p_arg++) - { - size_t z; - int alignment; - - /* align alignment to 4 */ - alignment = (((*p_arg)->alignment - 1) | 3) + 1; - - /* Align if necessary. */ - if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); - - z = (*p_arg)->size; - if (z < sizeof (int)) - { - z = sizeof (int); - - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv); - break; - - case FFI_TYPE_STRUCT: - memcpy (argp, *p_argv, (*p_arg)->size); - break; - - default: - FFI_ASSERT (0); - } - } - else if (z == sizeof (int)) - { - *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv); - } - else - { - if ((*p_arg)->type == FFI_TYPE_STRUCT) - { - memcpy (argp, *p_argv, z); - } - else - { - /* Double or long long 64bit. */ - memcpy (argp, *p_argv, z); - } - } - p_argv++; - argp += z; - } - - return; -} - -/* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep (ffi_cif * cif) -{ - /* Set the return type flag. */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_STRUCT: - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: - cif->flags = FFI_TYPE_DOUBLE; - break; - - case FFI_TYPE_FLOAT: - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - -extern void ffi_call_ARCompact (void (*)(char *, extended_cif *), - extended_cif *, unsigned, unsigned, - unsigned *, void (*fn) (void)); - -void -ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have - a return value address then we need to make one. */ - if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca (cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_ARCOMPACT: - ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; - } -} - -int -ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue, - ffi_arg * args) -{ - void **arg_area, **p_argv; - ffi_cif *cif = closure->cif; - char *argp = (char *) args; - ffi_type **p_argt; - int i; - - arg_area = (void **) alloca (cif->nargs * sizeof (void *)); - - /* handle hidden argument */ - if (cif->flags == FFI_TYPE_STRUCT) - { - rvalue = *(void **) argp; - argp += 4; - } - - p_argv = arg_area; - - for (i = 0, p_argt = cif->arg_types; i < cif->nargs; - i++, p_argt++, p_argv++) - { - size_t z; - int alignment; - - /* align alignment to 4 */ - alignment = (((*p_argt)->alignment - 1) | 3) + 1; - - /* Align if necessary. */ - if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); - - z = (*p_argt)->size; - *p_argv = (void *) argp; - argp += z; - } - - (closure->fun) (cif, rvalue, arg_area, closure->user_data); - - return cif->flags; -} - -extern void ffi_closure_ARCompact (void); - -ffi_status -ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif, - void (*fun) (ffi_cif *, void *, void **, void *), - void *user_data, void *codeloc) -{ - uint32_t *tramp = (uint32_t *) & (closure->tramp[0]); - - switch (cif->abi) - { - case FFI_ARCOMPACT: - FFI_ASSERT (tramp == codeloc); - tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */ - tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */ - tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact); - break; - - default: - return FFI_BAD_ABI; - } - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE); - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffitarget.h deleted file mode 100644 index bf8311bc8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arc/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ----------------------------------------------------------------------- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com) - Target configuration macros for ARC. - - 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 RENESAS TECHNOLOGY 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi -{ - FFI_FIRST_ABI = 0, - FFI_ARCOMPACT, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_ARCOMPACT -} ffi_abi; -#endif - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 12 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffi.c deleted file mode 100644 index 6691ab57d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffi.c +++ /dev/null @@ -1,931 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2011 Timothy Wall - Copyright (c) 2011 Plausible Labs Cooperative, Inc. - Copyright (c) 2011 Anthony Green - Copyright (c) 2011 Free Software Foundation - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. - - ARM Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -/* Forward declares. */ -static int vfp_type_p (ffi_type *); -static void layout_vfp_args (ffi_cif *); - -int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space); -int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space); - -static char* ffi_align(ffi_type **p_arg, char *argp) -{ - /* Align if necessary */ - register size_t alignment = (*p_arg)->alignment; - if (alignment < 4) - { - alignment = 4; - } -#ifdef _WIN32_WCE - if (alignment > 4) - { - alignment = 4; - } -#endif - if ((alignment - 1) & (unsigned) argp) - { - argp = (char *) ALIGN(argp, alignment); - } - - if ((*p_arg)->type == FFI_TYPE_STRUCT) - { - argp = (char *) ALIGN(argp, 4); - } - return argp; -} - -static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack) -{ - register char* argp = stack; - register ffi_type **p_arg = arg_type; - register void **p_argv = arg; - register size_t z = (*p_arg)->size; - if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - memcpy(argp, *p_argv, (*p_arg)->size); - break; - - default: - FFI_ASSERT(0); - } - } - else if (z == sizeof(int)) - { - if ((*p_arg)->type == FFI_TYPE_FLOAT) - *(float *) argp = *(float *)(* p_argv); - else - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - } - else if (z == sizeof(double) && (*p_arg)->type == FFI_TYPE_DOUBLE) - { - *(double *) argp = *(double *)(* p_argv); - } - else - { - memcpy(argp, *p_argv, z); - } - return z; -} -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments - - The vfp_space parameter is the load area for VFP regs, the return - value is cif->vfp_used (word bitset of VFP regs used for passing - arguments). These are only used for the VFP hard-float ABI. -*/ -int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - argp = stack; - - - if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { - *(void **) argp = ecif->rvalue; - argp += 4; - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); - i--, p_arg++, p_argv++) - { - argp = ffi_align(p_arg, argp); - argp += ffi_put_arg(p_arg, p_argv, argp); - } - - return 0; -} - -int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space) -{ - register unsigned int i, vi = 0; - register void **p_argv; - register char *argp, *regp, *eo_regp; - register ffi_type **p_arg; - char stack_used = 0; - char done_with_regs = 0; - char is_vfp_type; - - // make sure we are using FFI_VFP - FFI_ASSERT(ecif->cif->abi == FFI_VFP); - - /* the first 4 words on the stack are used for values passed in core - * registers. */ - regp = stack; - eo_regp = argp = regp + 16; - - - /* if the function returns an FFI_TYPE_STRUCT in memory, that address is - * passed in r0 to the function */ - if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { - *(void **) regp = ecif->rvalue; - regp += 4; - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); - i--, p_arg++, p_argv++) - { - is_vfp_type = vfp_type_p (*p_arg); - - /* Allocated in VFP registers. */ - if(vi < ecif->cif->vfp_nargs && is_vfp_type) - { - char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]); - ffi_put_arg(p_arg, p_argv, vfp_slot); - continue; - } - /* Try allocating in core registers. */ - else if (!done_with_regs && !is_vfp_type) - { - char *tregp = ffi_align(p_arg, regp); - size_t size = (*p_arg)->size; - size = (size < 4)? 4 : size; // pad - /* Check if there is space left in the aligned register area to place - * the argument */ - if(tregp + size <= eo_regp) - { - regp = tregp + ffi_put_arg(p_arg, p_argv, tregp); - done_with_regs = (regp == argp); - // ensure we did not write into the stack area - FFI_ASSERT(regp <= argp); - continue; - } - /* In case there are no arguments in the stack area yet, - the argument is passed in the remaining core registers and on the - stack. */ - else if (!stack_used) - { - stack_used = 1; - done_with_regs = 1; - argp = tregp + ffi_put_arg(p_arg, p_argv, tregp); - FFI_ASSERT(eo_regp < argp); - continue; - } - } - /* Base case, arguments are passed on the stack */ - stack_used = 1; - argp = ffi_align(p_arg, argp); - argp += ffi_put_arg(p_arg, p_argv, argp); - } - /* Indicate the VFP registers used. */ - return ecif->cif->vfp_used; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - int type_code; - /* Round the stack up to a multiple of 8 bytes. This isn't needed - everywhere, but it is on some platforms, and it doesn't harm anything - when it isn't needed. */ - cif->bytes = (cif->bytes + 7) & ~7; - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = (unsigned) FFI_TYPE_SINT64; - break; - - case FFI_TYPE_STRUCT: - if (cif->abi == FFI_VFP - && (type_code = vfp_type_p (cif->rtype)) != 0) - { - /* A Composite Type passed in VFP registers, either - FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */ - cif->flags = (unsigned) type_code; - } - else if (cif->rtype->size <= 4) - /* A Composite Type not larger than 4 bytes is returned in r0. */ - cif->flags = (unsigned)FFI_TYPE_INT; - else - /* A Composite Type larger than 4 bytes, or whose size cannot - be determined statically ... is stored in memory at an - address passed [in r0]. */ - cif->flags = (unsigned)FFI_TYPE_STRUCT; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - /* Map out the register placements of VFP register args. - The VFP hard-float calling conventions are slightly more sophisticated than - the base calling conventions, so we do it here instead of in ffi_prep_args(). */ - if (cif->abi == FFI_VFP) - layout_vfp_args (cif); - - return FFI_OK; -} - -/* Perform machine dependent cif processing for variadic calls */ -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, - unsigned int ntotalargs) -{ - /* VFP variadic calls actually use the SYSV ABI */ - if (cif->abi == FFI_VFP) - cif->abi = FFI_SYSV; - - return ffi_prep_cif_machdep(cif); -} - -/* Prototypes for assembly functions, in sysv.S */ -extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); -extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - int small_struct = (cif->flags == FFI_TYPE_INT - && cif->rtype->type == FFI_TYPE_STRUCT); - int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT - || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE); - - unsigned int temp; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->flags == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else if (small_struct) - ecif.rvalue = &temp; - else if (vfp_struct) - { - /* Largest case is double x 4. */ - ecif.rvalue = alloca(32); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); - break; - - case FFI_VFP: -#ifdef __ARM_EABI__ - ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); - break; -#endif - - default: - FFI_ASSERT(0); - break; - } - if (small_struct) - { - FFI_ASSERT(rvalue != NULL); - memcpy (rvalue, &temp, cif->rtype->size); - } - - else if (vfp_struct) - { - FFI_ASSERT(rvalue != NULL); - memcpy (rvalue, ecif.rvalue, cif->rtype->size); - } - -} - -/** private members **/ - -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif, float *vfp_stack); - -static void ffi_prep_incoming_args_VFP (char *stack, void **ret, - void** args, ffi_cif* cif, float *vfp_stack); - -void ffi_closure_SYSV (ffi_closure *); - -void ffi_closure_VFP (ffi_closure *); - -/* This function is jumped to by the trampoline */ - -unsigned int FFI_HIDDEN -ffi_closure_inner (ffi_closure *closure, - void **respp, void *args, void *vfp_args) -{ - // our various things... - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will re-set RESP to point to the - * structure return address. */ - if (cif->abi == FFI_VFP) - ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args); - else - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); - - (closure->fun) (cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} - -/*@-exportheader@*/ -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif, - /* Used only under VFP hard-float ABI. */ - float *vfp_stack) -/*@=exportheader@*/ -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - - if ( cif->flags == FFI_TYPE_STRUCT ) { - *rvalue = *(void **) argp; - argp += 4; - } - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - - argp = ffi_align(p_arg, argp); - - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - - p_argv++; - argp += z; - } - - return; -} - -/*@-exportheader@*/ -static void -ffi_prep_incoming_args_VFP(char *stack, void **rvalue, - void **avalue, ffi_cif *cif, - /* Used only under VFP hard-float ABI. */ - float *vfp_stack) -/*@=exportheader@*/ -{ - register unsigned int i, vi = 0; - register void **p_argv; - register char *argp, *regp, *eo_regp; - register ffi_type **p_arg; - char done_with_regs = 0; - char stack_used = 0; - char is_vfp_type; - - FFI_ASSERT(cif->abi == FFI_VFP); - regp = stack; - eo_regp = argp = regp + 16; - - if ( cif->flags == FFI_TYPE_STRUCT ) { - *rvalue = *(void **) regp; - regp += 4; - } - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - is_vfp_type = vfp_type_p (*p_arg); - - if(vi < cif->vfp_nargs && is_vfp_type) - { - *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]); - continue; - } - else if (!done_with_regs && !is_vfp_type) - { - char* tregp = ffi_align(p_arg, regp); - - z = (*p_arg)->size; - z = (z < 4)? 4 : z; // pad - - /* if the arguments either fits into the registers or uses registers - * and stack, while we haven't read other things from the stack */ - if(tregp + z <= eo_regp || !stack_used) - { - /* because we're little endian, this is what it turns into. */ - *p_argv = (void*) tregp; - - p_argv++; - regp = tregp + z; - // if we read past the last core register, make sure we have not read - // from the stack before and continue reading after regp - if(regp > eo_regp) - { - if(stack_used) - { - abort(); // we should never read past the end of the register - // are if the stack is already in use - } - argp = regp; - } - if(regp >= eo_regp) - { - done_with_regs = 1; - stack_used = 1; - } - continue; - } - } - stack_used = 1; - - argp = ffi_align(p_arg, argp); - - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - - p_argv++; - argp += z; - } - - return; -} - -/* How to make a trampoline. */ - -extern unsigned int ffi_arm_trampoline[3]; - -#if FFI_EXEC_TRAMPOLINE_TABLE - -#include -#include -#include -#include - -extern void *ffi_closure_trampoline_table_page; - -typedef struct ffi_trampoline_table ffi_trampoline_table; -typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; - -struct ffi_trampoline_table { - /* contiguous writable and executable pages */ - vm_address_t config_page; - vm_address_t trampoline_page; - - /* free list tracking */ - uint16_t free_count; - ffi_trampoline_table_entry *free_list; - ffi_trampoline_table_entry *free_list_pool; - - ffi_trampoline_table *prev; - ffi_trampoline_table *next; -}; - -struct ffi_trampoline_table_entry { - void *(*trampoline)(); - ffi_trampoline_table_entry *next; -}; - -/* Override the standard architecture trampoline size */ -// XXX TODO - Fix -#undef FFI_TRAMPOLINE_SIZE -#define FFI_TRAMPOLINE_SIZE 12 - -/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */ -#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080)); - -/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */ -#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16 - -/* Total number of trampolines that fit in one trampoline table */ -#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE) - -static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; -static ffi_trampoline_table *ffi_trampoline_tables = NULL; - -static ffi_trampoline_table * -ffi_trampoline_table_alloc () -{ - ffi_trampoline_table *table = NULL; - - /* Loop until we can allocate two contiguous pages */ - while (table == NULL) { - vm_address_t config_page = 0x0; - kern_return_t kt; - - /* Try to allocate two pages */ - kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } - - /* Now drop the second half of the allocation to make room for the trampoline table */ - vm_address_t trampoline_page = config_page+PAGE_SIZE; - kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } - - /* Remap the trampoline table to directly follow the config page */ - vm_prot_t cur_prot; - vm_prot_t max_prot; - - kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); - - /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ - if (kt != KERN_SUCCESS) { - /* Log unexpected failures */ - if (kt != KERN_NO_SPACE) { - fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - } - - vm_deallocate (mach_task_self (), config_page, PAGE_SIZE); - continue; - } - - /* We have valid trampoline and config pages */ - table = calloc (1, sizeof(ffi_trampoline_table)); - table->free_count = FFI_TRAMPOLINE_COUNT; - table->config_page = config_page; - table->trampoline_page = trampoline_page; - - /* Create and initialize the free list */ - table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry)); - - uint16_t i; - for (i = 0; i < table->free_count; i++) { - ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; - entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); - - if (i < table->free_count - 1) - entry->next = &table->free_list_pool[i+1]; - } - - table->free_list = table->free_list_pool; - } - - return table; -} - -void * -ffi_closure_alloc (size_t size, void **code) -{ - /* Create the closure */ - ffi_closure *closure = malloc(size); - if (closure == NULL) - return NULL; - - pthread_mutex_lock(&ffi_trampoline_lock); - - /* Check for an active trampoline table with available entries. */ - ffi_trampoline_table *table = ffi_trampoline_tables; - if (table == NULL || table->free_list == NULL) { - table = ffi_trampoline_table_alloc (); - if (table == NULL) { - free(closure); - return NULL; - } - - /* Insert the new table at the top of the list */ - table->next = ffi_trampoline_tables; - if (table->next != NULL) - table->next->prev = table; - - ffi_trampoline_tables = table; - } - - /* Claim the free entry */ - ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; - ffi_trampoline_tables->free_list = entry->next; - ffi_trampoline_tables->free_count--; - entry->next = NULL; - - pthread_mutex_unlock(&ffi_trampoline_lock); - - /* Initialize the return values */ - *code = entry->trampoline; - closure->trampoline_table = table; - closure->trampoline_table_entry = entry; - - return closure; -} - -void -ffi_closure_free (void *ptr) -{ - ffi_closure *closure = ptr; - - pthread_mutex_lock(&ffi_trampoline_lock); - - /* Fetch the table and entry references */ - ffi_trampoline_table *table = closure->trampoline_table; - ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; - - /* Return the entry to the free list */ - entry->next = table->free_list; - table->free_list = entry; - table->free_count++; - - /* If all trampolines within this table are free, and at least one other table exists, deallocate - * the table */ - if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) { - /* Remove from the list */ - if (table->prev != NULL) - table->prev->next = table->next; - - if (table->next != NULL) - table->next->prev = table->prev; - - /* Deallocate pages */ - kern_return_t kt; - kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - - kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - - /* Deallocate free list */ - free (table->free_list_pool); - free (table); - } else if (ffi_trampoline_tables != table) { - /* Otherwise, bump this table to the top of the list */ - table->prev = NULL; - table->next = ffi_trampoline_tables; - if (ffi_trampoline_tables != NULL) - ffi_trampoline_tables->prev = table; - - ffi_trampoline_tables = table; - } - - pthread_mutex_unlock (&ffi_trampoline_lock); - - /* Free the closure */ - free (closure); -} - -#else - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned char *insns = (unsigned char *)(CTX); \ - memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline); \ - *(unsigned int*) &__tramp[12] = __ctx; \ - *(unsigned int*) &__tramp[16] = __fun; \ - __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \ - __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \ - /* Clear instruction \ - mapping. */ \ - }) - -#endif - -/* the cif must already be prep'ed */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - void (*closure_func)(ffi_closure*) = NULL; - - if (cif->abi == FFI_SYSV) - closure_func = &ffi_closure_SYSV; -#ifdef __ARM_EABI__ - else if (cif->abi == FFI_VFP) - closure_func = &ffi_closure_VFP; -#endif - else - return FFI_BAD_ABI; - -#if FFI_EXEC_TRAMPOLINE_TABLE - void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc); - config[0] = closure; - config[1] = closure_func; -#else - FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ - closure_func, \ - codeloc); -#endif - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/* Below are routines for VFP hard-float support. */ - -static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum) -{ - switch (t->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - *elt = (int) t->type; - *elnum = 1; - return 1; - - case FFI_TYPE_STRUCT_VFP_FLOAT: - *elt = FFI_TYPE_FLOAT; - *elnum = t->size / sizeof (float); - return 1; - - case FFI_TYPE_STRUCT_VFP_DOUBLE: - *elt = FFI_TYPE_DOUBLE; - *elnum = t->size / sizeof (double); - return 1; - - case FFI_TYPE_STRUCT:; - { - int base_elt = 0, total_elnum = 0; - ffi_type **el = t->elements; - while (*el) - { - int el_elt = 0, el_elnum = 0; - if (! rec_vfp_type_p (*el, &el_elt, &el_elnum) - || (base_elt && base_elt != el_elt) - || total_elnum + el_elnum > 4) - return 0; - base_elt = el_elt; - total_elnum += el_elnum; - el++; - } - *elnum = total_elnum; - *elt = base_elt; - return 1; - } - default: ; - } - return 0; -} - -static int vfp_type_p (ffi_type *t) -{ - int elt, elnum; - if (rec_vfp_type_p (t, &elt, &elnum)) - { - if (t->type == FFI_TYPE_STRUCT) - { - if (elnum == 1) - t->type = elt; - else - t->type = (elt == FFI_TYPE_FLOAT - ? FFI_TYPE_STRUCT_VFP_FLOAT - : FFI_TYPE_STRUCT_VFP_DOUBLE); - } - return (int) t->type; - } - return 0; -} - -static int place_vfp_arg (ffi_cif *cif, ffi_type *t) -{ - short reg = cif->vfp_reg_free; - int nregs = t->size / sizeof (float); - int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT - || t->type == FFI_TYPE_FLOAT) ? 1 : 2); - /* Align register number. */ - if ((reg & 1) && align == 2) - reg++; - while (reg + nregs <= 16) - { - int s, new_used = 0; - for (s = reg; s < reg + nregs; s++) - { - new_used |= (1 << s); - if (cif->vfp_used & (1 << s)) - { - reg += align; - goto next_reg; - } - } - /* Found regs to allocate. */ - cif->vfp_used |= new_used; - cif->vfp_args[cif->vfp_nargs++] = reg; - - /* Update vfp_reg_free. */ - if (cif->vfp_used & (1 << cif->vfp_reg_free)) - { - reg += nregs; - while (cif->vfp_used & (1 << reg)) - reg += 1; - cif->vfp_reg_free = reg; - } - return 0; - next_reg: ; - } - // done, mark all regs as used - cif->vfp_reg_free = 16; - cif->vfp_used = 0xFFFF; - return 1; -} - -static void layout_vfp_args (ffi_cif *cif) -{ - int i; - /* Init VFP fields */ - cif->vfp_used = 0; - cif->vfp_nargs = 0; - cif->vfp_reg_free = 0; - memset (cif->vfp_args, -1, 16); /* Init to -1. */ - - for (i = 0; i < cif->nargs; i++) - { - ffi_type *t = cif->arg_types[i]; - if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1) - { - break; - } - } -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffitarget.h deleted file mode 100644 index 26d494d61..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arm/ffitarget.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 2010 CodeSourcery - Copyright (c) 1996-2003 Red Hat, Inc. - - Target configuration macros for ARM. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_VFP, - FFI_LAST_ABI, -#ifdef __ARM_PCS_VFP - FFI_DEFAULT_ABI = FFI_VFP, -#else - FFI_DEFAULT_ABI = FFI_SYSV, -#endif -} ffi_abi; -#endif - -#define FFI_EXTRA_CIF_FIELDS \ - int vfp_used; \ - short vfp_reg_free, vfp_nargs; \ - signed char vfp_args[16] \ - -/* Internally used. */ -#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1) -#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2) - -#define FFI_TARGET_SPECIFIC_VARIADIC - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 20 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arm/gentramp.sh b/ruby/ext/fiddle/libffi-3.2.1/src/arm/gentramp.sh deleted file mode 100755 index 05c43a30f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arm/gentramp.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/sh - -# ----------------------------------------------------------------------- -# gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc. -# -# ARM Trampoline Page Generator -# -# 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. -# ----------------------------------------------------------------------- - -PROGNAME=$0 - -# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change, -# the entire arm trampoline implementation must be updated to match, too. - -# Size of an individual trampoline, in bytes -TRAMPOLINE_SIZE=12 - -# Page size, in bytes -PAGE_SIZE=4096 - -# Compute the size of the reachable config page; The first 16 bytes of the config page -# are unreachable due to our maximum pc-relative ldr offset. -PAGE_AVAIL=`expr $PAGE_SIZE - 16` - -# Compute the number of of available trampolines. -TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE` - -header () { - echo "# GENERATED CODE - DO NOT EDIT" - echo "# This file was generated by $PROGNAME" - echo "" - - # Write out the license header -cat << EOF -# Copyright (c) 2010, Plausible Labs Cooperative, Inc. -# -# 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. -# ----------------------------------------------------------------------- - -EOF - - # Write out the trampoline table, aligned to the page boundary - echo ".text" - echo ".align 12" - echo ".globl _ffi_closure_trampoline_table_page" - echo "_ffi_closure_trampoline_table_page:" -} - - -# WARNING - Don't modify the trampoline code size without also updating the relevant libffi code -trampoline () { - cat << END - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - -END -} - -main () { - # Write out the header - header - - # Write out the trampolines - local i=0 - while [ $i -lt ${TRAMPOLINE_COUNT} ]; do - trampoline - local i=`expr $i + 1` - done -} - -main diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arm/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/arm/sysv.S deleted file mode 100644 index 541bbe923..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arm/sysv.S +++ /dev/null @@ -1,491 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. - Copyright (c) 2011 Plausible Labs Cooperative, Inc. - - ARM Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -#ifdef __USER_LABEL_PREFIX__ -#define CONCAT1(a, b) CONCAT2(a, b) -#define CONCAT2(a, b) a ## b - -/* Use the right prefix for global labels. */ -#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x) -#else -#define CNAME(x) x -#endif -#ifdef __APPLE__ -#define ENTRY(x) .globl _##x; _##x: -#else -#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): -#endif /* __APPLE__ */ -#endif - -#ifdef __ELF__ -#define LSYM(x) .x -#else -#define LSYM(x) x -#endif - -/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI - Function Call Guide */ -#ifdef __APPLE__ -#define __SOFTFP__ -#endif - -/* We need a better way of testing for this, but for now, this is all - we can do. */ -@ This selects the minimum architecture level required. -#define __ARM_ARCH__ 3 - -#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 4 -#endif - -#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ - || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 5 -#endif - -#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \ - || defined(__ARM_ARCH_6M__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 6 -#endif - -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7EM__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 7 -#endif - -#if __ARM_ARCH__ >= 5 -# define call_reg(x) blx x -#elif defined (__ARM_ARCH_4T__) -# define call_reg(x) mov lr, pc ; bx x -# if defined(__thumb__) || defined(__THUMB_INTERWORK__) -# define __INTERWORKING__ -# endif -#else -# define call_reg(x) mov lr, pc ; mov pc, x -#endif - -/* Conditionally compile unwinder directives. */ -#ifdef __ARM_EABI__ -#define UNWIND -#else -#define UNWIND @ -#endif - -.syntax unified - -#if defined(__thumb__) && !defined(__THUMB_INTERWORK__) -#define ARM_FUNC_START(name) \ - .text; \ - .align 2; \ - .thumb; \ - .thumb_func; \ - ENTRY(name); \ - bx pc; \ - nop; \ - .arm; \ - UNWIND .fnstart; \ -_L__##name: -#else -#define ARM_FUNC_START(name) \ - .text; \ - .align 2; \ - .arm; \ - ENTRY(name); \ - UNWIND .fnstart -#endif - -.macro RETLDM regs=, cond=, dirn=ia -#if defined (__INTERWORKING__) - .ifc "\regs","" - ldr\cond lr, [sp], #4 - .else - ldm\cond\dirn sp!, {\regs, lr} - .endif - bx\cond lr -#else - .ifc "\regs","" - ldr\cond pc, [sp], #4 - .else - ldm\cond\dirn sp!, {\regs, pc} - .endif -#endif -.endm - - @ r0: ffi_prep_args - @ r1: &ecif - @ r2: cif->bytes - @ r3: fig->flags - @ sp+0: ecif.rvalue - - @ This assumes we are using gas. -ARM_FUNC_START(ffi_call_SYSV) - @ Save registers - stmfd sp!, {r0-r3, fp, lr} - UNWIND .save {r0-r3, fp, lr} - mov fp, sp - - UNWIND .setfp fp, sp - - @ Make room for all of the new args. - sub sp, fp, r2 - - @ Place all of the ffi_prep_args in position - mov r0, sp - @ r1 already set - - @ Call ffi_prep_args(stack, &ecif) - bl CNAME(ffi_prep_args_SYSV) - - @ move first 4 parameters in registers - ldmia sp, {r0-r3} - - @ and adjust stack - sub lr, fp, sp @ cif->bytes == fp - sp - ldr ip, [fp] @ load fn() in advance - cmp lr, #16 - movhs lr, #16 - add sp, sp, lr - - @ call (fn) (...) - call_reg(ip) - - @ Remove the space we pushed for the args - mov sp, fp - - @ Load r2 with the pointer to storage for the return value - ldr r2, [sp, #24] - - @ Load r3 with the return type code - ldr r3, [sp, #12] - - @ If the return value pointer is NULL, assume no return value. - cmp r2, #0 - beq LSYM(Lepilogue) - -@ return INT - cmp r3, #FFI_TYPE_INT -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - cmpne r3, #FFI_TYPE_FLOAT -#endif - streq r0, [r2] - beq LSYM(Lepilogue) - - @ return INT64 - cmp r3, #FFI_TYPE_SINT64 -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - cmpne r3, #FFI_TYPE_DOUBLE -#endif - stmiaeq r2, {r0, r1} - -#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) - beq LSYM(Lepilogue) - -@ return FLOAT - cmp r3, #FFI_TYPE_FLOAT - stfeqs f0, [r2] - beq LSYM(Lepilogue) - -@ return DOUBLE or LONGDOUBLE - cmp r3, #FFI_TYPE_DOUBLE - stfeqd f0, [r2] -#endif - -LSYM(Lepilogue): -#if defined (__INTERWORKING__) - ldmia sp!, {r0-r3,fp, lr} - bx lr -#else - ldmia sp!, {r0-r3,fp, pc} -#endif - -.ffi_call_SYSV_end: - UNWIND .fnend -#ifdef __ELF__ - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) -#endif - - -/* - unsigned int FFI_HIDDEN - ffi_closure_inner (closure, respp, args) - ffi_closure *closure; - void **respp; - void *args; -*/ - -ARM_FUNC_START(ffi_closure_SYSV) - UNWIND .pad #16 - add ip, sp, #16 - stmfd sp!, {ip, lr} - UNWIND .save {r0, lr} - add r2, sp, #8 - UNWIND .pad #16 - sub sp, sp, #16 - str sp, [sp, #8] - add r1, sp, #8 - bl CNAME(ffi_closure_inner) - cmp r0, #FFI_TYPE_INT - beq .Lretint - - cmp r0, #FFI_TYPE_FLOAT -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - beq .Lretint -#else - beq .Lretfloat -#endif - - cmp r0, #FFI_TYPE_DOUBLE -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - beq .Lretlonglong -#else - beq .Lretdouble -#endif - - cmp r0, #FFI_TYPE_LONGDOUBLE -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - beq .Lretlonglong -#else - beq .Lretlongdouble -#endif - - cmp r0, #FFI_TYPE_SINT64 - beq .Lretlonglong -.Lclosure_epilogue: - add sp, sp, #16 - ldmfd sp, {sp, pc} -.Lretint: - ldr r0, [sp] - b .Lclosure_epilogue -.Lretlonglong: - ldr r0, [sp] - ldr r1, [sp, #4] - b .Lclosure_epilogue - -#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) -.Lretfloat: - ldfs f0, [sp] - b .Lclosure_epilogue -.Lretdouble: - ldfd f0, [sp] - b .Lclosure_epilogue -.Lretlongdouble: - ldfd f0, [sp] - b .Lclosure_epilogue -#endif - -.ffi_closure_SYSV_end: - UNWIND .fnend -#ifdef __ELF__ - .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) -#endif - - -/* Below are VFP hard-float ABI call and closure implementations. - Add VFP FPU directive here. This is only compiled into the library - under EABI. */ -#ifdef __ARM_EABI__ - .fpu vfp - - @ r0: fn - @ r1: &ecif - @ r2: cif->bytes - @ r3: fig->flags - @ sp+0: ecif.rvalue - -ARM_FUNC_START(ffi_call_VFP) - @ Save registers - stmfd sp!, {r0-r3, fp, lr} - UNWIND .save {r0-r3, fp, lr} - mov fp, sp - UNWIND .setfp fp, sp - - @ Make room for all of the new args. - sub sp, sp, r2 - - @ Make room for loading VFP args - sub sp, sp, #64 - - @ Place all of the ffi_prep_args in position - mov r0, sp - @ r1 already set - sub r2, fp, #64 @ VFP scratch space - - @ Call ffi_prep_args(stack, &ecif, vfp_space) - bl CNAME(ffi_prep_args_VFP) - - @ Load VFP register args if needed - cmp r0, #0 - mov ip, fp - beq LSYM(Lbase_args) - - @ Load only d0 if possible - cmp r0, #3 - sub ip, fp, #64 - flddle d0, [ip] - fldmiadgt ip, {d0-d7} - -LSYM(Lbase_args): - @ move first 4 parameters in registers - ldmia sp, {r0-r3} - - @ and adjust stack - sub lr, ip, sp @ cif->bytes == (fp - 64) - sp - ldr ip, [fp] @ load fn() in advance - cmp lr, #16 - movhs lr, #16 - add sp, sp, lr - - @ call (fn) (...) - call_reg(ip) - - @ Remove the space we pushed for the args - mov sp, fp - - @ Load r2 with the pointer to storage for - @ the return value - ldr r2, [sp, #24] - - @ Load r3 with the return type code - ldr r3, [sp, #12] - - @ If the return value pointer is NULL, - @ assume no return value. - cmp r2, #0 - beq LSYM(Lepilogue_vfp) - - cmp r3, #FFI_TYPE_INT - streq r0, [r2] - beq LSYM(Lepilogue_vfp) - - cmp r3, #FFI_TYPE_SINT64 - stmeqia r2, {r0, r1} - beq LSYM(Lepilogue_vfp) - - cmp r3, #FFI_TYPE_FLOAT - fstseq s0, [r2] - beq LSYM(Lepilogue_vfp) - - cmp r3, #FFI_TYPE_DOUBLE - fstdeq d0, [r2] - beq LSYM(Lepilogue_vfp) - - cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT - cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE - fstmiadeq r2, {d0-d3} - -LSYM(Lepilogue_vfp): - RETLDM "r0-r3,fp" - -.ffi_call_VFP_end: - UNWIND .fnend - .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP) - - -ARM_FUNC_START(ffi_closure_VFP) - fstmfdd sp!, {d0-d7} - @ r0-r3, then d0-d7 - UNWIND .pad #80 - add ip, sp, #80 - stmfd sp!, {ip, lr} - UNWIND .save {r0, lr} - add r2, sp, #72 - add r3, sp, #8 - UNWIND .pad #72 - sub sp, sp, #72 - str sp, [sp, #64] - add r1, sp, #64 - bl CNAME(ffi_closure_inner) - - cmp r0, #FFI_TYPE_INT - beq .Lretint_vfp - - cmp r0, #FFI_TYPE_FLOAT - beq .Lretfloat_vfp - - cmp r0, #FFI_TYPE_DOUBLE - cmpne r0, #FFI_TYPE_LONGDOUBLE - beq .Lretdouble_vfp - - cmp r0, #FFI_TYPE_SINT64 - beq .Lretlonglong_vfp - - cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT - beq .Lretfloat_struct_vfp - - cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE - beq .Lretdouble_struct_vfp - -.Lclosure_epilogue_vfp: - add sp, sp, #72 - ldmfd sp, {sp, pc} - -.Lretfloat_vfp: - flds s0, [sp] - b .Lclosure_epilogue_vfp -.Lretdouble_vfp: - fldd d0, [sp] - b .Lclosure_epilogue_vfp -.Lretint_vfp: - ldr r0, [sp] - b .Lclosure_epilogue_vfp -.Lretlonglong_vfp: - ldmia sp, {r0, r1} - b .Lclosure_epilogue_vfp -.Lretfloat_struct_vfp: - fldmiad sp, {d0-d1} - b .Lclosure_epilogue_vfp -.Lretdouble_struct_vfp: - fldmiad sp, {d0-d3} - b .Lclosure_epilogue_vfp - -.ffi_closure_VFP_end: - UNWIND .fnend - .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP) -#endif - -ENTRY(ffi_arm_trampoline) - stmfd sp!, {r0-r3} - ldr r0, [pc] - ldr pc, [pc] - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/arm/trampoline.S b/ruby/ext/fiddle/libffi-3.2.1/src/arm/trampoline.S deleted file mode 100644 index 935e8de17..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/arm/trampoline.S +++ /dev/null @@ -1,4450 +0,0 @@ -# GENERATED CODE - DO NOT EDIT -# This file was generated by src/arm/gentramp.sh - -# Copyright (c) 2010, Plausible Labs Cooperative, Inc. -# -# 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. -# ----------------------------------------------------------------------- - -.text -.align 12 -.globl _ffi_closure_trampoline_table_page -_ffi_closure_trampoline_table_page: - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffi.c deleted file mode 100644 index 3d43397b0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffi.c +++ /dev/null @@ -1,423 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2011 Anthony Green - Copyright (c) 2009 Bradley Smith - - AVR32 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include -#include -#include - -/* #define DEBUG */ - -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned int, unsigned int, unsigned int*, unsigned int, - void (*fn)(void)); -extern void ffi_closure_SYSV (ffi_closure *); - -unsigned int pass_struct_on_stack(ffi_type *type) -{ - if(type->type != FFI_TYPE_STRUCT) - return 0; - - if(type->alignment < type->size && - !(type->size == 4 || type->size == 8) && - !(type->size == 8 && type->alignment >= 4)) - return 1; - - if(type->size == 3 || type->size == 5 || type->size == 6 || - type->size == 7) - return 1; - - return 0; -} - -/* ffi_prep_args is called by the assembly routine once stack space - * has been allocated for the function's arguments - * - * This is annoyingly complex since we need to keep track of used - * registers. - */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - unsigned int i; - void **p_argv; - ffi_type **p_arg; - char *reg_base = stack; - char *stack_base = stack + 20; - unsigned int stack_offset = 0; - unsigned int reg_mask = 0; - - p_argv = ecif->avalue; - - /* If cif->flags is struct then we know it's not passed in registers */ - if(ecif->cif->flags == FFI_TYPE_STRUCT) - { - *(void**)reg_base = ecif->rvalue; - reg_mask |= 1; - } - - for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; - i++, p_arg++) - { - size_t z = (*p_arg)->size; - int alignment = (*p_arg)->alignment; - int type = (*p_arg)->type; - char *addr = 0; - - if(z % 4 != 0) - z += (4 - z % 4); - - if(reg_mask != 0x1f) - { - if(pass_struct_on_stack(*p_arg)) - { - addr = stack_base + stack_offset; - stack_offset += z; - } - else if(z == sizeof(int)) - { - char index = 0; - - while((reg_mask >> index) & 1) - index++; - - addr = reg_base + (index * 4); - reg_mask |= (1 << index); - } - else if(z == 2 * sizeof(int)) - { - if(!((reg_mask >> 1) & 1)) - { - addr = reg_base + 4; - reg_mask |= (3 << 1); - } - else if(!((reg_mask >> 3) & 1)) - { - addr = reg_base + 12; - reg_mask |= (3 << 3); - } - } - } - - if(!addr) - { - addr = stack_base + stack_offset; - stack_offset += z; - } - - if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL) - type = (*p_arg)->elements[0]->type; - - switch(type) - { - case FFI_TYPE_UINT8: - *(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv); - break; - case FFI_TYPE_SINT8: - *(signed int *)addr = (signed int)*(SINT8 *)(*p_argv); - break; - case FFI_TYPE_UINT16: - *(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv); - break; - case FFI_TYPE_SINT16: - *(signed int *)addr = (signed int)*(SINT16 *)(*p_argv); - break; - default: - memcpy(addr, *p_argv, z); - } - - p_argv++; - } - -#ifdef DEBUG - /* Debugging */ - for(i = 0; i < 5; i++) - { - if((reg_mask & (1 << i)) == 0) - printf("r%d: (unused)\n", 12 - i); - else - printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]); - } - - for(i = 0; i < stack_offset / 4; i++) - { - printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]); - } -#endif -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* Round the stack up to a multiple of 8 bytes. This isn't needed - * everywhere, but it is on some platforms, and it doesn't harm - * anything when it isn't needed. */ - cif->bytes = (cif->bytes + 7) & ~7; - - /* Flag to indicate that he return value is in fact a struct */ - cif->rstruct_flag = 0; - - /* Set the return type flag */ - switch(cif->rtype->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - cif->flags = (unsigned)FFI_TYPE_UINT8; - break; - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - cif->flags = (unsigned)FFI_TYPE_UINT16; - break; - case FFI_TYPE_FLOAT: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - cif->flags = (unsigned)FFI_TYPE_UINT32; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = (unsigned)FFI_TYPE_UINT64; - break; - case FFI_TYPE_STRUCT: - cif->rstruct_flag = 1; - if(!pass_struct_on_stack(cif->rtype)) - { - if(cif->rtype->size <= 1) - cif->flags = (unsigned)FFI_TYPE_UINT8; - else if(cif->rtype->size <= 2) - cif->flags = (unsigned)FFI_TYPE_UINT16; - else if(cif->rtype->size <= 4) - cif->flags = (unsigned)FFI_TYPE_UINT32; - else if(cif->rtype->size <= 8) - cif->flags = (unsigned)FFI_TYPE_UINT64; - else - cif->flags = (unsigned)cif->rtype->type; - } - else - cif->flags = (unsigned)cif->rtype->type; - break; - default: - cif->flags = (unsigned)cif->rtype->type; - break; - } - - return FFI_OK; -} - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - unsigned int size = 0, i = 0; - ffi_type **p_arg; - - ecif.cif = cif; - ecif.avalue = avalue; - - for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) - size += (*p_arg)->size + (4 - (*p_arg)->size % 4); - - /* If the return value is a struct and we don't have a return value - * address then we need to make one */ - - /* If cif->flags is struct then it's not suitable for registers */ - if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT)) - ecif.rvalue = alloca(cif->rtype->size); - else - ecif.rvalue = rvalue; - - switch(cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags, - ecif.rvalue, cif->rstruct_flag, fn); - break; - default: - FFI_ASSERT(0); - break; - } -} - -static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif) -{ - register unsigned int i, reg_mask = 0; - register void **p_argv; - register ffi_type **p_arg; - register char *reg_base = stack; - register char *stack_base = stack + 20; - register unsigned int stack_offset = 0; - -#ifdef DEBUG - /* Debugging */ - for(i = 0; i < cif->nargs + 7; i++) - { - printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]); - } -#endif - - /* If cif->flags is struct then we know it's not passed in registers */ - if(cif->flags == FFI_TYPE_STRUCT) - { - *rvalue = *(void **)reg_base; - reg_mask |= 1; - } - - p_argv = avalue; - - for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) - { - size_t z = (*p_arg)->size; - int alignment = (*p_arg)->alignment; - - *p_argv = 0; - - if(z % 4 != 0) - z += (4 - z % 4); - - if(reg_mask != 0x1f) - { - if(pass_struct_on_stack(*p_arg)) - { - *p_argv = (void*)stack_base + stack_offset; - stack_offset += z; - } - else if(z <= sizeof(int)) - { - char index = 0; - - while((reg_mask >> index) & 1) - index++; - - *p_argv = (void*)reg_base + (index * 4); - reg_mask |= (1 << index); - } - else if(z == 2 * sizeof(int)) - { - if(!((reg_mask >> 1) & 1)) - { - *p_argv = (void*)reg_base + 4; - reg_mask |= (3 << 1); - } - else if(!((reg_mask >> 3) & 1)) - { - *p_argv = (void*)reg_base + 12; - reg_mask |= (3 << 3); - } - } - } - - if(!*p_argv) - { - *p_argv = (void*)stack_base + stack_offset; - stack_offset += z; - } - - if((*p_arg)->type != FFI_TYPE_STRUCT || - (*p_arg)->elements[1] == NULL) - { - if(alignment == 1) - **(unsigned int**)p_argv <<= 24; - else if(alignment == 2) - **(unsigned int**)p_argv <<= 16; - } - - p_argv++; - } - -#ifdef DEBUG - /* Debugging */ - for(i = 0; i < cif->nargs; i++) - { - printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i])); - } -#endif -} - -/* This function is jumped to by the trampoline */ - -unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp, - void *args) -{ - ffi_cif *cif; - void **arg_area; - unsigned int i, size = 0; - ffi_type **p_arg; - - cif = closure->cif; - - for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++) - size += (*p_arg)->size + (4 - (*p_arg)->size % 4); - - arg_area = (void **)alloca(size); - - /* this call will initialize ARG_AREA, such that each element in that - * array points to the corresponding value on the stack; and if the - * function returns a structure, it will re-set RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); - - (closure->fun)(cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} - -ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, - void *codeloc) -{ - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]); - unsigned int __fun = (unsigned int)(&ffi_closure_SYSV); - unsigned int __ctx = (unsigned int)(codeloc); - unsigned int __rstruct_flag = (unsigned int)(cif->rstruct_flag); - unsigned int __inner = (unsigned int)(&ffi_closure_SYSV_inner); - *(unsigned int*) &__tramp[0] = 0xebcd1f00; /* pushm r8-r12 */ - *(unsigned int*) &__tramp[4] = 0xfefc0010; /* ld.w r12, pc[16] */ - *(unsigned int*) &__tramp[8] = 0xfefb0010; /* ld.w r11, pc[16] */ - *(unsigned int*) &__tramp[12] = 0xfefa0010; /* ld.w r10, pc[16] */ - *(unsigned int*) &__tramp[16] = 0xfeff0010; /* ld.w pc, pc[16] */ - *(unsigned int*) &__tramp[20] = __ctx; - *(unsigned int*) &__tramp[24] = __rstruct_flag; - *(unsigned int*) &__tramp[28] = __inner; - *(unsigned int*) &__tramp[32] = __fun; - syscall(__NR_cacheflush, 0, (&__tramp[0]), 36); - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffitarget.h deleted file mode 100644 index d0c7586f9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/ffitarget.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 2009 Bradley Smith - Target configuration macros for AVR32. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#define FFI_EXTRA_CIF_FIELDS unsigned int rstruct_flag - -/* Definitions for closures */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 36 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/avr32/sysv.S deleted file mode 100644 index a984b3c88..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/avr32/sysv.S +++ /dev/null @@ -1,208 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2009 Bradley Smith - - AVR32 Foreign Function Interface - - 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. - --------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - /* r12: ffi_prep_args - * r11: &ecif - * r10: size - * r9: cif->flags - * r8: ecif.rvalue - * sp+0: cif->rstruct_flag - * sp+4: fn */ - - .text - .align 1 - .globl ffi_call_SYSV - .type ffi_call_SYSV, @function -ffi_call_SYSV: - stm --sp, r0,r1,lr - stm --sp, r8-r12 - mov r0, sp - - /* Make room for all of the new args. */ - sub sp, r10 - /* Pad to make way for potential skipped registers */ - sub sp, 20 - - /* Call ffi_prep_args(stack, &ecif). */ - /* r11 already set */ - mov r1, r12 - mov r12, sp - icall r1 - - /* Save new argument size */ - mov r1, r12 - - /* Move first 5 parameters in registers. */ - ldm sp++, r8-r12 - - /* call (fn) (...). */ - ld.w r1, r0[36] - icall r1 - - /* Remove the space we pushed for the args. */ - mov sp, r0 - - /* Load r1 with the rstruct flag. */ - ld.w r1, sp[32] - - /* Load r9 with the return type code. */ - ld.w r9, sp[12] - - /* Load r8 with the return value pointer. */ - ld.w r8, sp[16] - - /* If the return value pointer is NULL, assume no return value. */ - cp.w r8, 0 - breq .Lend - - /* Check if return type is actually a struct */ - cp.w r1, 0 - breq 1f - - /* Return 8bit */ - cp.w r9, FFI_TYPE_UINT8 - breq .Lstore8 - - /* Return 16bit */ - cp.w r9, FFI_TYPE_UINT16 - breq .Lstore16 - -1: - /* Return 32bit */ - cp.w r9, FFI_TYPE_UINT32 - breq .Lstore32 - cp.w r9, FFI_TYPE_UINT16 - breq .Lstore32 - cp.w r9, FFI_TYPE_UINT8 - breq .Lstore32 - - /* Return 64bit */ - cp.w r9, FFI_TYPE_UINT64 - breq .Lstore64 - - /* Didn't match anything */ - bral .Lend - -.Lstore64: - st.w r8[0], r11 - st.w r8[4], r10 - bral .Lend - -.Lstore32: - st.w r8[0], r12 - bral .Lend - -.Lstore16: - st.h r8[0], r12 - bral .Lend - -.Lstore8: - st.b r8[0], r12 - bral .Lend - -.Lend: - sub sp, -20 - ldm sp++, r0,r1,pc - - .size ffi_call_SYSV, . - ffi_call_SYSV - - - /* r12: __ctx - * r11: __rstruct_flag - * r10: __inner */ - - .align 1 - .globl ffi_closure_SYSV - .type ffi_closure_SYSV, @function -ffi_closure_SYSV: - stm --sp, r0,lr - mov r0, r11 - mov r8, r10 - sub r10, sp, -8 - sub sp, 12 - st.w sp[8], sp - sub r11, sp, -8 - icall r8 - - /* Check if return type is actually a struct */ - cp.w r0, 0 - breq 1f - - /* Return 8bit */ - cp.w r12, FFI_TYPE_UINT8 - breq .Lget8 - - /* Return 16bit */ - cp.w r12, FFI_TYPE_UINT16 - breq .Lget16 - -1: - /* Return 32bit */ - cp.w r12, FFI_TYPE_UINT32 - breq .Lget32 - cp.w r12, FFI_TYPE_UINT16 - breq .Lget32 - cp.w r12, FFI_TYPE_UINT8 - breq .Lget32 - - /* Return 64bit */ - cp.w r12, FFI_TYPE_UINT64 - breq .Lget64 - - /* Didn't match anything */ - bral .Lclend - -.Lget64: - ld.w r11, sp[0] - ld.w r10, sp[4] - bral .Lclend - -.Lget32: - ld.w r12, sp[0] - bral .Lclend - -.Lget16: - ld.uh r12, sp[0] - bral .Lclend - -.Lget8: - ld.ub r12, sp[0] - bral .Lclend - -.Lclend: - sub sp, -12 - ldm sp++, r0,lr - sub sp, -20 - mov pc, lr - - .size ffi_closure_SYSV, . - ffi_closure_SYSV - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffi.c deleted file mode 100644 index 22a2acdac..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffi.c +++ /dev/null @@ -1,196 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca , - Paulo Pizarro - - Blackfin Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ -#include -#include - -#include -#include - -/* Maximum number of GPRs available for argument passing. */ -#define MAX_GPRARGS 3 - -/* - * Return types - */ -#define FFIBFIN_RET_VOID 0 -#define FFIBFIN_RET_BYTE 1 -#define FFIBFIN_RET_HALFWORD 2 -#define FFIBFIN_RET_INT64 3 -#define FFIBFIN_RET_INT32 4 - -/*====================================================================*/ -/* PROTOTYPE * - /*====================================================================*/ -void ffi_prep_args(unsigned char *, extended_cif *); - -/*====================================================================*/ -/* Externals */ -/* (Assembly) */ -/*====================================================================*/ - -extern void ffi_call_SYSV(unsigned, extended_cif *, void(*)(unsigned char *, extended_cif *), unsigned, void *, void(*fn)(void)); - -/*====================================================================*/ -/* Implementation */ -/* */ -/*====================================================================*/ - - -/* - * This function calculates the return type (size) based on type. - */ - -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* --------------------------------------* - * Return handling * - * --------------------------------------*/ - switch (cif->rtype->type) { - case FFI_TYPE_VOID: - cif->flags = FFIBFIN_RET_VOID; - break; - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - cif->flags = FFIBFIN_RET_HALFWORD; - break; - case FFI_TYPE_UINT8: - cif->flags = FFIBFIN_RET_BYTE; - break; - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_FLOAT: - case FFI_TYPE_POINTER: - case FFI_TYPE_SINT8: - cif->flags = FFIBFIN_RET_INT32; - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: - cif->flags = FFIBFIN_RET_INT64; - break; - case FFI_TYPE_STRUCT: - if (cif->rtype->size <= 4){ - cif->flags = FFIBFIN_RET_INT32; - }else if (cif->rtype->size == 8){ - cif->flags = FFIBFIN_RET_INT64; - }else{ - //it will return via a hidden pointer in P0 - cif->flags = FFIBFIN_RET_VOID; - } - break; - default: - FFI_ASSERT(0); - break; - } - return FFI_OK; -} - -/* - * This will prepare the arguments and will call the assembly routine - * cif = the call interface - * fn = the function to be called - * rvalue = the return value - * avalue = the arguments - */ -void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue) -{ - int ret_type = cif->flags; - extended_cif ecif; - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; - - switch (cif->abi) { - case FFI_SYSV: - ffi_call_SYSV(cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn); - break; - default: - FFI_ASSERT(0); - break; - } -} - - -/* -* This function prepares the parameters (copies them from the ecif to the stack) -* to call the function (ffi_prep_args is called by the assembly routine in file -* sysv.S, which also calls the actual function) -*/ -void ffi_prep_args(unsigned char *stack, extended_cif *ecif) -{ - register unsigned int i = 0; - void **p_argv; - unsigned char *argp; - ffi_type **p_arg; - argp = stack; - p_argv = ecif->avalue; - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); - i--, p_arg++) { - size_t z; - z = (*p_arg)->size; - if (z < sizeof(int)) { - z = sizeof(int); - switch ((*p_arg)->type) { - case FFI_TYPE_SINT8: { - signed char v = *(SINT8 *)(* p_argv); - signed int t = v; - *(signed int *) argp = t; - } - break; - case FFI_TYPE_UINT8: { - unsigned char v = *(UINT8 *)(* p_argv); - unsigned int t = v; - *(unsigned int *) argp = t; - } - break; - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) * (SINT16 *)(* p_argv); - break; - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) * (UINT16 *)(* p_argv); - break; - case FFI_TYPE_STRUCT: - memcpy(argp, *p_argv, (*p_arg)->size); - break; - default: - FFI_ASSERT(0); - break; - } - } else if (z == sizeof(int)) { - *(unsigned int *) argp = (unsigned int) * (UINT32 *)(* p_argv); - } else { - memcpy(argp, *p_argv, z); - } - p_argv++; - argp += z; - } -} - - - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffitarget.h deleted file mode 100644 index 2175c0101..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/ffitarget.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ----------------------------------------------------------------------- - ffitarget.h - Copyright (c) 2012 Alexandre K. I. de Mendonca - - Blackfin Foreign Function Interface - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/bfin/sysv.S deleted file mode 100644 index f4278be24..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/bfin/sysv.S +++ /dev/null @@ -1,179 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca , - Paulo Pizarro - - Blackfin Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -.text -.align 4 - - /* - There is a "feature" in the bfin toolchain that it puts a _ before function names - that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV - */ - .global _ffi_call_SYSV; - .type _ffi_call_SYSV, STT_FUNC; - .func ffi_call_SYSV - - /* - cif->bytes = R0 (fp+8) - &ecif = R1 (fp+12) - ffi_prep_args = R2 (fp+16) - ret_type = stack (fp+20) - ecif.rvalue = stack (fp+24) - fn = stack (fp+28) - got (fp+32) - - There is room for improvement here (we can use temporary registers - instead of saving the values in the memory) - REGS: - P5 => Stack pointer (function arguments) - R5 => cif->bytes - R4 => ret->type - - FP-20 = P3 - FP-16 = SP (parameters area) - FP-12 = SP (temp) - FP-08 = function return part 1 [R0] - FP-04 = function return part 2 [R1] - */ - -_ffi_call_SYSV: -.prologue: - LINK 20; - [FP-20] = P3; - [FP+8] = R0; - [FP+12] = R1; - [FP+16] = R2; - -.allocate_stack: - //alocate cif->bytes into the stack - R1 = [FP+8]; - R0 = SP; - R0 = R0 - R1; - R1 = 4; - R0 = R0 - R1; - [FP-12] = SP; - SP = R0; - [FP-16] = SP; - -.call_prep_args: - //get the addr of prep_args - P0 = [P3 + _ffi_prep_args@FUNCDESC_GOT17M4]; - P1 = [P0]; - P3 = [P0+4]; - R0 = [FP-16];//SP (parameter area) - R1 = [FP+12];//ecif - call (P1); - -.call_user_function: - //ajust SP so as to allow the user function access the parameters on the stack - SP = [FP-16]; //point to function parameters - R0 = [SP]; - R1 = [SP+4]; - R2 = [SP+8]; - //load user function address - P0 = FP; - P0 +=28; - P1 = [P0]; - P1 = [P1]; - P3 = [P0+4]; - /* - For functions returning aggregate values (struct) occupying more than 8 bytes, - the caller allocates the return value object on the stack and the address - of this object is passed to the callee as a hidden argument in register P0. - */ - P0 = [FP+24]; - - call (P1); - SP = [FP-12]; -.compute_return: - P2 = [FP-20]; - [FP-8] = R0; - [FP-4] = R1; - - R0 = [FP+20]; - R1 = R0 << 2; - - R0 = [P2+.rettable@GOT17M4]; - R0 = R1 + R0; - P2 = R0; - R1 = [P2]; - - P2 = [FP+-20]; - R0 = [P2+.rettable@GOT17M4]; - R0 = R1 + R0; - P2 = R0; - R0 = [FP-8]; - R1 = [FP-4]; - jump (P2); - -/* -#define FFIBFIN_RET_VOID 0 -#define FFIBFIN_RET_BYTE 1 -#define FFIBFIN_RET_HALFWORD 2 -#define FFIBFIN_RET_INT64 3 -#define FFIBFIN_RET_INT32 4 -*/ -.align 4 -.align 4 -.rettable: - .dd .epilogue - .rettable - .dd .rbyte - .rettable; - .dd .rhalfword - .rettable; - .dd .rint64 - .rettable; - .dd .rint32 - .rettable; - -.rbyte: - P0 = [FP+24]; - R0 = R0.B (Z); - [P0] = R0; - JUMP .epilogue -.rhalfword: - P0 = [FP+24]; - R0 = R0.L; - [P0] = R0; - JUMP .epilogue -.rint64: - P0 = [FP+24];// &rvalue - [P0] = R0; - [P0+4] = R1; - JUMP .epilogue -.rint32: - P0 = [FP+24]; - [P0] = R0; -.epilogue: - R0 = [FP+8]; - R1 = [FP+12]; - R2 = [FP+16]; - P3 = [FP-20]; - UNLINK; - RTS; - -.size _ffi_call_SYSV,.-_ffi_call_SYSV; -.endfunc diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/closures.c b/ruby/ext/fiddle/libffi-3.2.1/src/closures.c deleted file mode 100644 index 721ff00ea..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/closures.c +++ /dev/null @@ -1,688 +0,0 @@ -/* ----------------------------------------------------------------------- - closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc - Copyright (c) 2011 Plausible Labs Cooperative, Inc. - - Code to allocate and deallocate memory for closures. - - 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. - ----------------------------------------------------------------------- */ - -#if defined __linux__ && !defined _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#include -#include - -#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE -# if __gnu_linux__ && !defined(__ANDROID__) -/* This macro indicates it may be forbidden to map anonymous memory - with both write and execute permission. Code compiled when this - option is defined will attempt to map such pages once, but if it - fails, it falls back to creating a temporary file in a writable and - executable filesystem and mapping pages from it into separate - locations in the virtual memory space, one location writable and - another executable. */ -# define FFI_MMAP_EXEC_WRIT 1 -# define HAVE_MNTENT 1 -# endif -# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__) -/* Windows systems may have Data Execution Protection (DEP) enabled, - which requires the use of VirtualMalloc/VirtualFree to alloc/free - executable memory. */ -# define FFI_MMAP_EXEC_WRIT 1 -# endif -#endif - -#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX -# ifdef __linux__ -/* When defined to 1 check for SELinux and if SELinux is active, - don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that - might cause audit messages. */ -# define FFI_MMAP_EXEC_SELINUX 1 -# endif -#endif - -#if FFI_CLOSURES - -# if FFI_EXEC_TRAMPOLINE_TABLE - -// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations. - -# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ - -#define USE_LOCKS 1 -#define USE_DL_PREFIX 1 -#ifdef __GNUC__ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 1 -#endif -#endif - -/* We need to use mmap, not sbrk. */ -#define HAVE_MORECORE 0 - -/* We could, in theory, support mremap, but it wouldn't buy us anything. */ -#define HAVE_MREMAP 0 - -/* We have no use for this, so save some code and data. */ -#define NO_MALLINFO 1 - -/* We need all allocations to be in regular segments, otherwise we - lose track of the corresponding code address. */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T - -/* Don't allocate more than a page unless needed. */ -#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize) - -#if FFI_CLOSURE_TEST -/* Don't release single pages, to avoid a worst-case scenario of - continuously allocating and releasing single pages, but release - pairs of pages, which should do just as well given that allocations - are likely to be small. */ -#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize) -#endif - -#include -#include -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include -#if !defined(X86_WIN32) && !defined(X86_WIN64) -#ifdef HAVE_MNTENT -#include -#endif /* HAVE_MNTENT */ -#include -#include - -/* We don't want sys/mman.h to be included after we redefine mmap and - dlmunmap. */ -#include -#define LACKS_SYS_MMAN_H 1 - -#if FFI_MMAP_EXEC_SELINUX -#include -#include - -static int selinux_enabled = -1; - -static int -selinux_enabled_check (void) -{ - struct statfs sfs; - FILE *f; - char *buf = NULL; - size_t len = 0; - - if (statfs ("/selinux", &sfs) >= 0 - && (unsigned int) sfs.f_type == 0xf97cff8cU) - return 1; - f = fopen ("/proc/mounts", "r"); - if (f == NULL) - return 0; - while (getline (&buf, &len, f) >= 0) - { - char *p = strchr (buf, ' '); - if (p == NULL) - break; - p = strchr (p + 1, ' '); - if (p == NULL) - break; - if (strncmp (p + 1, "selinuxfs ", 10) == 0) - { - free (buf); - fclose (f); - return 1; - } - } - free (buf); - fclose (f); - return 0; -} - -#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \ - : (selinux_enabled = selinux_enabled_check ())) - -#else - -#define is_selinux_enabled() 0 - -#endif /* !FFI_MMAP_EXEC_SELINUX */ - -/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */ -#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX -#include - -static int emutramp_enabled = -1; - -static int -emutramp_enabled_check (void) -{ - char *buf = NULL; - size_t len = 0; - FILE *f; - int ret; - f = fopen ("/proc/self/status", "r"); - if (f == NULL) - return 0; - ret = 0; - - while (getline (&buf, &len, f) != -1) - if (!strncmp (buf, "PaX:", 4)) - { - char emutramp; - if (sscanf (buf, "%*s %*c%c", &emutramp) == 1) - ret = (emutramp == 'E'); - break; - } - free (buf); - fclose (f); - return ret; -} - -#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \ - : (emutramp_enabled = emutramp_enabled_check ())) -#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */ - -#elif defined (__CYGWIN__) || defined(__INTERIX) - -#include - -/* Cygwin is Linux-like, but not quite that Linux-like. */ -#define is_selinux_enabled() 0 - -#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */ - -#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX -#define is_emutramp_enabled() 0 -#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */ - -/* Declare all functions defined in dlmalloc.c as static. */ -static void *dlmalloc(size_t); -static void dlfree(void*); -static void *dlcalloc(size_t, size_t) MAYBE_UNUSED; -static void *dlrealloc(void *, size_t) MAYBE_UNUSED; -static void *dlmemalign(size_t, size_t) MAYBE_UNUSED; -static void *dlvalloc(size_t) MAYBE_UNUSED; -static int dlmallopt(int, int) MAYBE_UNUSED; -static size_t dlmalloc_footprint(void) MAYBE_UNUSED; -static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED; -static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED; -static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED; -static void *dlpvalloc(size_t) MAYBE_UNUSED; -static int dlmalloc_trim(size_t) MAYBE_UNUSED; -static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED; -static void dlmalloc_stats(void) MAYBE_UNUSED; - -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) -/* Use these for mmap and munmap within dlmalloc.c. */ -static void *dlmmap(void *, size_t, int, int, int, off_t); -static int dlmunmap(void *, size_t); -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ - -#define mmap dlmmap -#define munmap dlmunmap - -#include "dlmalloc.c" - -#undef mmap -#undef munmap - -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) - -/* A mutex used to synchronize access to *exec* variables in this file. */ -static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* A file descriptor of a temporary file from which we'll map - executable pages. */ -static int execfd = -1; - -/* The amount of space already allocated from the temporary file. */ -static size_t execsize = 0; - -/* Open a temporary file name, and immediately unlink it. */ -static int -open_temp_exec_file_name (char *name, int flags) -{ - int fd; - -#ifdef HAVE_MKOSTEMP - fd = mkostemp (name, flags); -#else - fd = mkstemp (name); -#endif - - if (fd != -1) - unlink (name); - - return fd; -} - -/* Open a temporary file in the named directory. */ -static int -open_temp_exec_file_dir (const char *dir) -{ - static const char suffix[] = "/ffiXXXXXX"; - int lendir, flags; - char *tempname; -#ifdef O_TMPFILE - int fd; -#endif - -#ifdef O_CLOEXEC - flags = O_CLOEXEC; -#else - flags = 0; -#endif - -#ifdef O_TMPFILE - fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700); - /* If the running system does not support the O_TMPFILE flag then retry without it. */ - if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) { - return fd; - } else { - errno = 0; - } -#endif - - lendir = strlen (dir); - tempname = __builtin_alloca (lendir + sizeof (suffix)); - - if (!tempname) - return -1; - - memcpy (tempname, dir, lendir); - memcpy (tempname + lendir, suffix, sizeof (suffix)); - - return open_temp_exec_file_name (tempname, flags); -} - -/* Open a temporary file in the directory in the named environment - variable. */ -static int -open_temp_exec_file_env (const char *envvar) -{ - const char *value = getenv (envvar); - - if (!value) - return -1; - - return open_temp_exec_file_dir (value); -} - -#ifdef HAVE_MNTENT -/* Open a temporary file in an executable and writable mount point - listed in the mounts file. Subsequent calls with the same mounts - keep searching for mount points in the same file. Providing NULL - as the mounts file closes the file. */ -static int -open_temp_exec_file_mnt (const char *mounts) -{ - static const char *last_mounts; - static FILE *last_mntent; - - if (mounts != last_mounts) - { - if (last_mntent) - endmntent (last_mntent); - - last_mounts = mounts; - - if (mounts) - last_mntent = setmntent (mounts, "r"); - else - last_mntent = NULL; - } - - if (!last_mntent) - return -1; - - for (;;) - { - int fd; - struct mntent mnt; - char buf[MAXPATHLEN * 3]; - - if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL) - return -1; - - if (hasmntopt (&mnt, "ro") - || hasmntopt (&mnt, "noexec") - || access (mnt.mnt_dir, W_OK)) - continue; - - fd = open_temp_exec_file_dir (mnt.mnt_dir); - - if (fd != -1) - return fd; - } -} -#endif /* HAVE_MNTENT */ - -/* Instructions to look for a location to hold a temporary file that - can be mapped in for execution. */ -static struct -{ - int (*func)(const char *); - const char *arg; - int repeat; -} open_temp_exec_file_opts[] = { - { open_temp_exec_file_env, "TMPDIR", 0 }, - { open_temp_exec_file_dir, "/tmp", 0 }, - { open_temp_exec_file_dir, "/var/tmp", 0 }, - { open_temp_exec_file_dir, "/dev/shm", 0 }, - { open_temp_exec_file_env, "HOME", 0 }, -#ifdef HAVE_MNTENT - { open_temp_exec_file_mnt, "/etc/mtab", 1 }, - { open_temp_exec_file_mnt, "/proc/mounts", 1 }, -#endif /* HAVE_MNTENT */ -}; - -/* Current index into open_temp_exec_file_opts. */ -static int open_temp_exec_file_opts_idx = 0; - -/* Reset a current multi-call func, then advances to the next entry. - If we're at the last, go back to the first and return nonzero, - otherwise return zero. */ -static int -open_temp_exec_file_opts_next (void) -{ - if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) - open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL); - - open_temp_exec_file_opts_idx++; - if (open_temp_exec_file_opts_idx - == (sizeof (open_temp_exec_file_opts) - / sizeof (*open_temp_exec_file_opts))) - { - open_temp_exec_file_opts_idx = 0; - return 1; - } - - return 0; -} - -/* Return a file descriptor of a temporary zero-sized file in a - writable and executable filesystem. */ -static int -open_temp_exec_file (void) -{ - int fd; - - do - { - fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func - (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg); - - if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat - || fd == -1) - { - if (open_temp_exec_file_opts_next ()) - break; - } - } - while (fd == -1); - - return fd; -} - -/* Map in a chunk of memory from the temporary exec file into separate - locations in the virtual memory address space, one writable and one - executable. Returns the address of the writable portion, after - storing an offset to the corresponding executable portion at the - last word of the requested chunk. */ -static void * -dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) -{ - void *ptr; - - if (execfd == -1) - { - open_temp_exec_file_opts_idx = 0; - retry_open: - execfd = open_temp_exec_file (); - if (execfd == -1) - return MFAIL; - } - - offset = execsize; - - if (ftruncate (execfd, offset + length)) - return MFAIL; - - flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS); - flags |= MAP_SHARED; - - ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC, - flags, execfd, offset); - if (ptr == MFAIL) - { - if (!offset) - { - close (execfd); - goto retry_open; - } - ftruncate (execfd, offset); - return MFAIL; - } - else if (!offset - && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) - open_temp_exec_file_opts_next (); - - start = mmap (start, length, prot, flags, execfd, offset); - - if (start == MFAIL) - { - munmap (ptr, length); - ftruncate (execfd, offset); - return start; - } - - mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start; - - execsize += length; - - return start; -} - -/* Map in a writable and executable chunk of memory if possible. - Failing that, fall back to dlmmap_locked. */ -static void * -dlmmap (void *start, size_t length, int prot, - int flags, int fd, off_t offset) -{ - void *ptr; - - assert (start == NULL && length % malloc_getpagesize == 0 - && prot == (PROT_READ | PROT_WRITE) - && flags == (MAP_PRIVATE | MAP_ANONYMOUS) - && fd == -1 && offset == 0); - -#if FFI_CLOSURE_TEST - printf ("mapping in %zi\n", length); -#endif - - if (execfd == -1 && is_emutramp_enabled ()) - { - ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset); - return ptr; - } - - if (execfd == -1 && !is_selinux_enabled ()) - { - ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset); - - if (ptr != MFAIL || (errno != EPERM && errno != EACCES)) - /* Cool, no need to mess with separate segments. */ - return ptr; - - /* If MREMAP_DUP is ever introduced and implemented, try mmap - with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with - MREMAP_DUP and prot at this point. */ - } - - if (execsize == 0 || execfd == -1) - { - pthread_mutex_lock (&open_temp_exec_file_mutex); - ptr = dlmmap_locked (start, length, prot, flags, offset); - pthread_mutex_unlock (&open_temp_exec_file_mutex); - - return ptr; - } - - return dlmmap_locked (start, length, prot, flags, offset); -} - -/* Release memory at the given address, as well as the corresponding - executable page if it's separate. */ -static int -dlmunmap (void *start, size_t length) -{ - /* We don't bother decreasing execsize or truncating the file, since - we can't quite tell whether we're unmapping the end of the file. - We don't expect frequent deallocation anyway. If we did, we - could locate pages in the file by writing to the pages being - deallocated and checking that the file contents change. - Yuck. */ - msegmentptr seg = segment_holding (gm, start); - void *code; - -#if FFI_CLOSURE_TEST - printf ("unmapping %zi\n", length); -#endif - - if (seg && (code = add_segment_exec_offset (start, seg)) != start) - { - int ret = munmap (code, length); - if (ret) - return ret; - } - - return munmap (start, length); -} - -#if FFI_CLOSURE_FREE_CODE -/* Return segment holding given code address. */ -static msegmentptr -segment_holding_code (mstate m, char* addr) -{ - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= add_segment_exec_offset (sp->base, sp) - && addr < add_segment_exec_offset (sp->base, sp) + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} -#endif - -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ - -/* Allocate a chunk of memory with the given size. Returns a pointer - to the writable address, and sets *CODE to the executable - corresponding virtual address. */ -void * -ffi_closure_alloc (size_t size, void **code) -{ - void *ptr; - - if (!code) - return NULL; - - ptr = dlmalloc (size); - - if (ptr) - { - msegmentptr seg = segment_holding (gm, ptr); - - *code = add_segment_exec_offset (ptr, seg); - } - - return ptr; -} - -/* Release a chunk of memory allocated with ffi_closure_alloc. If - FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the - writable or the executable address given. Otherwise, only the - writable address can be provided here. */ -void -ffi_closure_free (void *ptr) -{ -#if FFI_CLOSURE_FREE_CODE - msegmentptr seg = segment_holding_code (gm, ptr); - - if (seg) - ptr = sub_segment_exec_offset (ptr, seg); -#endif - - dlfree (ptr); -} - - -#if FFI_CLOSURE_TEST -/* Do some internal sanity testing to make sure allocation and - deallocation of pages are working as intended. */ -int main () -{ - void *p[3]; -#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0) -#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0) - GET (0, malloc_getpagesize / 2); - GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*)); - PUT (1); - GET (1, 2 * malloc_getpagesize); - GET (2, malloc_getpagesize / 2); - PUT (1); - PUT (0); - PUT (2); - return 0; -} -#endif /* FFI_CLOSURE_TEST */ -# else /* ! FFI_MMAP_EXEC_WRIT */ - -/* On many systems, memory returned by malloc is writable and - executable, so just use it. */ - -#include - -void * -ffi_closure_alloc (size_t size, void **code) -{ - if (!code) - return NULL; - - return *code = malloc (size); -} - -void -ffi_closure_free (void *ptr) -{ - free (ptr); -} - -# endif /* ! FFI_MMAP_EXEC_WRIT */ -#endif /* FFI_CLOSURES */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffi.c deleted file mode 100644 index aaca5b1cb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffi.c +++ /dev/null @@ -1,386 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1998 Cygnus Solutions - Copyright (c) 2004 Simon Posnjak - Copyright (c) 2005 Axis Communications AB - Copyright (C) 2007 Free Software Foundation, Inc. - - CRIS Foreign Function Interface - - 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 SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) - -static ffi_status -initialize_aggregate_packed_struct (ffi_type * arg) -{ - ffi_type **ptr; - - FFI_ASSERT (arg != NULL); - - FFI_ASSERT (arg->elements != NULL); - FFI_ASSERT (arg->size == 0); - FFI_ASSERT (arg->alignment == 0); - - ptr = &(arg->elements[0]); - - while ((*ptr) != NULL) - { - if (((*ptr)->size == 0) - && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) - return FFI_BAD_TYPEDEF; - - FFI_ASSERT (ffi_type_test ((*ptr))); - - arg->size += (*ptr)->size; - - arg->alignment = (arg->alignment > (*ptr)->alignment) ? - arg->alignment : (*ptr)->alignment; - - ptr++; - } - - if (arg->size == 0) - return FFI_BAD_TYPEDEF; - else - return FFI_OK; -} - -int -ffi_prep_args (char *stack, extended_cif * ecif) -{ - unsigned int i; - unsigned int struct_count = 0; - void **p_argv; - char *argp; - ffi_type **p_arg; - - argp = stack; - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); i--, p_arg++) - { - size_t z; - - switch ((*p_arg)->type) - { - case FFI_TYPE_STRUCT: - { - z = (*p_arg)->size; - if (z <= 4) - { - memcpy (argp, *p_argv, z); - z = 4; - } - else if (z <= 8) - { - memcpy (argp, *p_argv, z); - z = 8; - } - else - { - unsigned int uiLocOnStack; - z = sizeof (void *); - uiLocOnStack = 4 * ecif->cif->nargs + struct_count; - struct_count = struct_count + (*p_arg)->size; - *(unsigned int *) argp = - (unsigned int) (UINT32 *) (stack + uiLocOnStack); - memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size); - } - break; - } - default: - z = (*p_arg)->size; - if (z < sizeof (int)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = - (unsigned int) *(UINT8 *) (*p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = - (unsigned int) *(UINT16 *) (*p_argv); - break; - - default: - FFI_ASSERT (0); - } - z = sizeof (int); - } - else if (z == sizeof (int)) - *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv); - else - memcpy (argp, *p_argv, z); - break; - } - p_argv++; - argp += z; - } - - return (struct_count); -} - -ffi_status FFI_HIDDEN -ffi_prep_cif_core (ffi_cif * cif, - ffi_abi abi, unsigned int isvariadic, - unsigned int nfixedargs, unsigned int ntotalargs, - ffi_type * rtype, ffi_type ** atypes) -{ - unsigned bytes = 0; - unsigned int i; - ffi_type **ptr; - - FFI_ASSERT (cif != NULL); - FFI_ASSERT((!isvariadic) || (nfixedargs >= 1)); - FFI_ASSERT(nfixedargs <= ntotalargs); - FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI); - - cif->abi = abi; - cif->arg_types = atypes; - cif->nargs = ntotalargs; - cif->rtype = rtype; - - cif->flags = 0; - - if ((cif->rtype->size == 0) - && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK)) - return FFI_BAD_TYPEDEF; - - FFI_ASSERT_VALID_TYPE (cif->rtype); - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - if (((*ptr)->size == 0) - && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) - return FFI_BAD_TYPEDEF; - - FFI_ASSERT_VALID_TYPE (*ptr); - - if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN (bytes, (*ptr)->alignment); - if ((*ptr)->type == FFI_TYPE_STRUCT) - { - if ((*ptr)->size > 8) - { - bytes += (*ptr)->size; - bytes += sizeof (void *); - } - else - { - if ((*ptr)->size > 4) - bytes += 8; - else - bytes += 4; - } - } - else - bytes += STACK_ARG_SIZE ((*ptr)->size); - } - - cif->bytes = bytes; - - return ffi_prep_cif_machdep (cif); -} - -ffi_status -ffi_prep_cif_machdep (ffi_cif * cif) -{ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = (unsigned) cif->rtype->type; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - -extern void ffi_call_SYSV (int (*)(char *, extended_cif *), - extended_cif *, - unsigned, unsigned, unsigned *, void (*fn) ()) - __attribute__ ((__visibility__ ("hidden"))); - -void -ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca (cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; - default: - FFI_ASSERT (0); - break; - } -} - -/* Because the following variables are not exported outside libffi, we - mark them hidden. */ - -/* Assembly code for the jump stub. */ -extern const char ffi_cris_trampoline_template[] - __attribute__ ((__visibility__ ("hidden"))); - -/* Offset into ffi_cris_trampoline_template of where to put the - ffi_prep_closure_inner function. */ -extern const int ffi_cris_trampoline_fn_offset - __attribute__ ((__visibility__ ("hidden"))); - -/* Offset into ffi_cris_trampoline_template of where to put the - closure data. */ -extern const int ffi_cris_trampoline_closure_offset - __attribute__ ((__visibility__ ("hidden"))); - -/* This function is sibling-called (jumped to) by the closure - trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at - PARAMS[4] to simplify handling of a straddling parameter. A copy - of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are - put at the appropriate place in CLOSURE which is then executed and - the return value is passed back to the caller. */ - -static unsigned long long -ffi_prep_closure_inner (void **params, ffi_closure* closure) -{ - char *register_args = (char *) params; - void *struct_ret = params[5]; - char *stack_args = params[6]; - char *ptr = register_args; - ffi_cif *cif = closure->cif; - ffi_type **arg_types = cif->arg_types; - - /* Max room needed is number of arguments as 64-bit values. */ - void **avalue = alloca (closure->cif->nargs * sizeof(void *)); - int i; - int doing_regs; - long long llret = 0; - - /* Find the address of each argument. */ - for (i = 0, doing_regs = 1; i < cif->nargs; i++) - { - /* Types up to and including 8 bytes go by-value. */ - if (arg_types[i]->size <= 4) - { - avalue[i] = ptr; - ptr += 4; - } - else if (arg_types[i]->size <= 8) - { - avalue[i] = ptr; - ptr += 8; - } - else - { - FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT); - - /* Passed by-reference, so copy the pointer. */ - avalue[i] = *(void **) ptr; - ptr += 4; - } - - /* If we've handled more arguments than fit in registers, start - looking at the those passed on the stack. Step over the - first one if we had a straddling parameter. */ - if (doing_regs && ptr >= register_args + 4*4) - { - ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0); - doing_regs = 0; - } - } - - /* Invoke the closure. */ - (closure->fun) (cif, - - cif->rtype->type == FFI_TYPE_STRUCT - /* The caller allocated space for the return - structure, and passed a pointer to this space in - R9. */ - ? struct_ret - - /* We take advantage of being able to ignore that - the high part isn't set if the return value is - not in R10:R11, but in R10 only. */ - : (void *) &llret, - - avalue, closure->user_data); - - return llret; -} - -/* API function: Prepare the trampoline. */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif *, void *, void **, void*), - void *user_data, - void *codeloc) -{ - void *innerfn = ffi_prep_closure_inner; - FFI_ASSERT (cif->abi == FFI_SYSV); - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - memcpy (closure->tramp, ffi_cris_trampoline_template, - FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE); - memcpy (closure->tramp + ffi_cris_trampoline_fn_offset, - &innerfn, sizeof (void *)); - memcpy (closure->tramp + ffi_cris_trampoline_closure_offset, - &codeloc, sizeof (void *)); - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffitarget.h deleted file mode 100644 index b837e976e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/cris/ffitarget.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for CRIS. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36 -#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4) -#define FFI_TRAMPOLINE_SIZE \ - (FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE) -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/cris/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/cris/sysv.S deleted file mode 100644 index 79abaee4d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/cris/sysv.S +++ /dev/null @@ -1,215 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2004 Simon Posnjak - Copyright (c) 2005 Axis Communications AB - - CRIS Foreign Function Interface - - 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 SIMON POSNJAK 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#define CONCAT(x,y) x ## y -#define XCONCAT(x,y) CONCAT (x, y) -#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x) - - .text - - ;; OK, when we get called we should have this (according to - ;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3). - ;; - ;; R10: ffi_prep_args (func. pointer) - ;; R11: &ecif - ;; R12: cif->bytes - ;; R13: fig->flags - ;; sp+0: ecif.rvalue - ;; sp+4: fn (function pointer to the function that we need to call) - - .globl L(ffi_call_SYSV) - .type L(ffi_call_SYSV),@function - .hidden L(ffi_call_SYSV) - -L(ffi_call_SYSV): - ;; Save the regs to the stack. - push $srp - ;; Used for stack pointer saving. - push $r6 - ;; Used for function address pointer. - push $r7 - ;; Used for stack pointer saving. - push $r8 - ;; We save fig->flags to stack we will need them after we - ;; call The Function. - push $r13 - - ;; Saving current stack pointer. - move.d $sp,$r8 - move.d $sp,$r6 - - ;; Move address of ffi_prep_args to r13. - move.d $r10,$r13 - - ;; Make room on the stack for the args of fn. - sub.d $r12,$sp - - ;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are: - ;; r10 <-- stack pointer - ;; r11 <-- &ecif (already there) - move.d $sp,$r10 - - ;; Call the function. - jsr $r13 - - ;; Save the size of the structures which are passed on stack. - move.d $r10,$r7 - - ;; Move first four args in to r10..r13. - move.d [$sp+0],$r10 - move.d [$sp+4],$r11 - move.d [$sp+8],$r12 - move.d [$sp+12],$r13 - - ;; Adjust the stack and check if any parameters are given on stack. - addq 16,$sp - sub.d $r7,$r6 - cmp.d $sp,$r6 - - bpl go_on - nop - -go_on_no_params_on_stack: - move.d $r6,$sp - -go_on: - ;; Discover if we need to put rval address in to r9. - move.d [$r8+0],$r7 - cmpq FFI_TYPE_STRUCT,$r7 - bne call_now - nop - - ;; Move rval address to $r9. - move.d [$r8+20],$r9 - -call_now: - ;; Move address of The Function in to r7. - move.d [$r8+24],$r7 - - ;; Call The Function. - jsr $r7 - - ;; Reset stack. - move.d $r8,$sp - - ;; Load rval type (fig->flags) in to r13. - pop $r13 - - ;; Detect rval type. - cmpq FFI_TYPE_VOID,$r13 - beq epilogue - - cmpq FFI_TYPE_STRUCT,$r13 - beq epilogue - - cmpq FFI_TYPE_DOUBLE,$r13 - beq return_double_or_longlong - - cmpq FFI_TYPE_UINT64,$r13 - beq return_double_or_longlong - - cmpq FFI_TYPE_SINT64,$r13 - beq return_double_or_longlong - nop - - ;; Just return the 32 bit value. - ba return - nop - -return_double_or_longlong: - ;; Load half of the rval to r10 and the other half to r11. - move.d [$sp+16],$r13 - move.d $r10,[$r13] - addq 4,$r13 - move.d $r11,[$r13] - ba epilogue - nop - -return: - ;; Load the rval to r10. - move.d [$sp+16],$r13 - move.d $r10,[$r13] - -epilogue: - pop $r8 - pop $r7 - pop $r6 - Jump [$sp+] - - .size ffi_call_SYSV,.-ffi_call_SYSV - -/* Save R10..R13 into an array, somewhat like varargs. Copy the next - argument too, to simplify handling of any straddling parameter. - Save R9 and SP after those. Jump to function handling the rest. - Since this is a template, copied and the main function filled in by - the user. */ - - .globl L(ffi_cris_trampoline_template) - .type L(ffi_cris_trampoline_template),@function - .hidden L(ffi_cris_trampoline_template) - -L(ffi_cris_trampoline_template): -0: - /* The value we get for "PC" is right after the prefix instruction, - two bytes from the beginning, i.e. 0b+2. */ - move.d $r10,[$pc+2f-(0b+2)] - move.d $pc,$r10 -1: - addq 2f-1b+4,$r10 - move.d $r11,[$r10+] - move.d $r12,[$r10+] - move.d $r13,[$r10+] - move.d [$sp],$r11 - move.d $r11,[$r10+] - move.d $r9,[$r10+] - move.d $sp,[$r10+] - subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10 - move.d 0,$r11 -3: - jump 0 -2: - .size ffi_cris_trampoline_template,.-0b - -/* This macro create a constant usable as "extern const int \name" in - C from within libffi, when \name has no prefix decoration. */ - - .macro const name,value - .globl \name - .type \name,@object - .hidden \name -\name: - .dword \value - .size \name,4 - .endm - -/* Constants for offsets within the trampoline. We could do this with - just symbols, avoiding memory contents and memory accesses, but the - C usage code would look a bit stranger. */ - - const L(ffi_cris_trampoline_fn_offset),2b-4-0b - const L(ffi_cris_trampoline_closure_offset),3b-4-0b diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/debug.c b/ruby/ext/fiddle/libffi-3.2.1/src/debug.c deleted file mode 100644 index f3172b1ef..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/debug.c +++ /dev/null @@ -1,64 +0,0 @@ -/* ----------------------------------------------------------------------- - debug.c - Copyright (c) 1996 Red Hat, Inc. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include -#include -#include - -/* General debugging routines */ - -void ffi_stop_here(void) -{ - /* This function is only useful for debugging purposes. - Place a breakpoint on ffi_stop_here to be notified of - significant events. */ -} - -/* This function should only be called via the FFI_ASSERT() macro */ - -void ffi_assert(char *expr, char *file, int line) -{ - fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line); - ffi_stop_here(); - abort(); -} - -/* Perform a sanity check on an ffi_type structure */ - -void ffi_type_test(ffi_type *a, char *file, int line) -{ - FFI_ASSERT_AT(a != NULL, file, line); - - FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line); - FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line); - FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line); - FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX) - || a->elements != NULL, file, line); - FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX - || (a->elements != NULL - && a->elements[0] != NULL && a->elements[1] == NULL), - file, line); - -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/dlmalloc.c b/ruby/ext/fiddle/libffi-3.2.1/src/dlmalloc.c deleted file mode 100644 index 8725b4fd6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/dlmalloc.c +++ /dev/null @@ -1,5161 +0,0 @@ -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. Send questions, - comments, complaints, performance data, etc to dl@cs.oswego.edu - -* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O3), and link it into another program. All of - the compile-time options default to reasonable values for use on - most platforms. You might later want to step through various - compile-time and dynamic tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. Note that you may already by default be using a C - library containing a malloc that is based on some version of this - malloc (for example in linux). You might still want to use the one - in this file to customize settings or to avoid overheads associated - with library versions. - -* Vital statistics: - - Supported pointer/size_t representation: 4 or 8 bytes - size_t MUST be an unsigned type of the same width as - pointers. (If you are using an ancient system that declares - size_t as a signed type, or need it to be a different width - than pointers, you can use a previous release of this malloc - (e.g. 2.7.2) supporting these.) - - Alignment: 8 bytes (default) - This suffices for nearly all current machines and C compilers. - However, you can define MALLOC_ALIGNMENT to be wider than this - if necessary (up to 128bytes), at the expense of using more space. - - Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) - 8 or 16 bytes (if 8byte sizes) - Each malloced chunk has a hidden word of overhead holding size - and status information, and additional cross-check word - if FOOTERS is defined. - - Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) - 8-byte ptrs: 32 bytes (including overhead) - - Even a request for zero bytes (i.e., malloc(0)) returns a - pointer to something of the minimum allocatable size. - The maximum overhead wastage (i.e., number of extra bytes - allocated than were requested in malloc) is less than or equal - to the minimum size, except for requests >= mmap_threshold that - are serviced via mmap(), where the worst case wastage is about - 32 bytes plus the remainder from a system page (the minimal - mmap unit); typically 4096 or 8192 bytes. - - Security: static-safe; optionally more or less - The "security" of malloc refers to the ability of malicious - code to accentuate the effects of errors (for example, freeing - space that is not currently malloc'ed or overwriting past the - ends of chunks) in code that calls malloc. This malloc - guarantees not to modify any memory locations below the base of - heap, i.e., static variables, even in the presence of usage - errors. The routines additionally detect most improper frees - and reallocs. All this holds as long as the static bookkeeping - for malloc itself is not corrupted by some other means. This - is only one aspect of security -- these checks do not, and - cannot, detect all possible programming errors. - - If FOOTERS is defined nonzero, then each allocated chunk - carries an additional check word to verify that it was malloced - from its space. These check words are the same within each - execution of a program using malloc, but differ across - executions, so externally crafted fake chunks cannot be - freed. This improves security by rejecting frees/reallocs that - could corrupt heap memory, in addition to the checks preventing - writes to statics that are always on. This may further improve - security at the expense of time and space overhead. (Note that - FOOTERS may also be worth using with MSPACES.) - - By default detected errors cause the program to abort (calling - "abort()"). You can override this to instead proceed past - errors by defining PROCEED_ON_ERROR. In this case, a bad free - has no effect, and a malloc that encounters a bad address - caused by user overwrites will ignore the bad address by - dropping pointers and indices to all known memory. This may - be appropriate for programs that should continue if at all - possible in the face of programming errors, although they may - run out of memory because dropped memory is never reclaimed. - - If you don't like either of these options, you can define - CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has - no errors or vulnerabilities, you can define INSECURE to 1, - which might (or might not) provide a small performance improvement. - - Thread-safety: NOT thread-safe unless USE_LOCKS defined - When USE_LOCKS is defined, each public call to malloc, free, - etc is surrounded with either a pthread mutex or a win32 - spinlock (depending on WIN32). This is not especially fast, and - can be a major bottleneck. It is designed only to provide - minimal protection in concurrent environments, and to provide a - basis for extensions. If you are using malloc in a concurrent - program, consider instead using ptmalloc, which is derived from - a version of this malloc. (See http://www.malloc.de). - - System requirements: Any combination of MORECORE and/or MMAP/MUNMAP - This malloc can use unix sbrk or any emulation (invoked using - the CALL_MORECORE macro) and/or mmap/munmap or any emulation - (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system - memory. On most unix systems, it tends to work best if both - MORECORE and MMAP are enabled. On Win32, it uses emulations - based on VirtualAlloc. It also uses common C library functions - like memset. - - Compliance: I believe it is compliant with the Single Unix Specification - (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably - others as well. - -* Overview of algorithms - - This is not the fastest, most space-conserving, most portable, or - most tunable malloc ever written. However it is among the fastest - while also being among the most space-conserving, portable and - tunable. Consistent balance across these factors results in a good - general-purpose allocator for malloc-intensive programs. - - In most ways, this malloc is a best-fit allocator. Generally, it - chooses the best-fitting existing chunk for a request, with ties - broken in approximately least-recently-used order. (This strategy - normally maintains low fragmentation.) However, for requests less - than 256bytes, it deviates from best-fit when there is not an - exactly fitting available chunk by preferring to use space adjacent - to that used for the previous small request, as well as by breaking - ties in approximately most-recently-used order. (These enhance - locality of series of small allocations.) And for very large requests - (>= 256Kb by default), it relies on system memory mapping - facilities, if supported. (This helps avoid carrying around and - possibly fragmenting memory used only for large chunks.) - - All operations (except malloc_stats and mallinfo) have execution - times that are bounded by a constant factor of the number of bits in - a size_t, not counting any clearing in calloc or copying in realloc, - or actions surrounding MORECORE and MMAP that have times - proportional to the number of non-contiguous regions returned by - system allocation routines, which is often just 1. - - The implementation is not very modular and seriously overuses - macros. Perhaps someday all C compilers will do as good a job - inlining modular code as can now be done by brute-force expansion, - but now, enough of them seem not to. - - Some compilers issue a lot of warnings about code that is - dead/unreachable only on some platforms, and also about intentional - uses of negation on unsigned types. All known cases of each can be - ignored. - - For a longer but out of date high-level description, see - http://gee.cs.oswego.edu/dl/html/malloc.html - -* MSPACES - If MSPACES is defined, then in addition to malloc, free, etc., - this file also defines mspace_malloc, mspace_free, etc. These - are versions of malloc routines that take an "mspace" argument - obtained using create_mspace, to control all internal bookkeeping. - If ONLY_MSPACES is defined, only these versions are compiled. - So if you would like to use this allocator for only some allocations, - and your system malloc for others, you can compile with - ONLY_MSPACES and then do something like... - static mspace mymspace = create_mspace(0,0); // for example - #define mymalloc(bytes) mspace_malloc(mymspace, bytes) - - (Note: If you only need one instance of an mspace, you can instead - use "USE_DL_PREFIX" to relabel the global malloc.) - - You can similarly create thread-local allocators by storing - mspaces as thread-locals. For example: - static __thread mspace tlms = 0; - void* tlmalloc(size_t bytes) { - if (tlms == 0) tlms = create_mspace(0, 0); - return mspace_malloc(tlms, bytes); - } - void tlfree(void* mem) { mspace_free(tlms, mem); } - - Unless FOOTERS is defined, each mspace is completely independent. - You cannot allocate from one and free to another (although - conformance is only weakly checked, so usage errors are not always - caught). If FOOTERS is defined, then each chunk carries around a tag - indicating its originating mspace, and frees are directed to their - originating spaces. - - ------------------------- Compile-time options --------------------------- - -Be careful in setting #define values for numerical constants of type -size_t. On some systems, literal values are not automatically extended -to size_t precision unless they are explicitly casted. - -WIN32 default: defined if _WIN32 defined - Defining WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. - -MALLOC_ALIGNMENT default: (size_t)8 - Controls the minimum alignment for malloc'ed chunks. It must be a - power of two and at least 8, even on machines for which smaller - alignments would suffice. It may be defined as larger than this - though. Note however that code and data structures are optimized for - the case of 8-byte alignment. - -MSPACES default: 0 (false) - If true, compile in support for independent allocation spaces. - This is only supported if HAVE_MMAP is true. - -ONLY_MSPACES default: 0 (false) - If true, only compile in mspace versions, not regular versions. - -USE_LOCKS default: 0 (false) - Causes each call to each public routine to be surrounded with - pthread or WIN32 mutex lock/unlock. (If set true, this can be - overridden on a per-mspace basis for mspace versions.) - -FOOTERS default: 0 - If true, provide extra checking and dispatching by placing - information in the footers of allocated chunks. This adds - space and time overhead. - -INSECURE default: 0 - If true, omit checks for usage errors and heap space overwrites. - -USE_DL_PREFIX default: NOT defined - Causes compiler to prefix all public routines with the string 'dl'. - This can be useful when you only want to use this malloc in one part - of a program, using your regular system malloc elsewhere. - -ABORT default: defined as abort() - Defines how to abort on failed checks. On most systems, a failed - check cannot die with an "assert" or even print an informative - message, because the underlying print routines in turn call malloc, - which will fail again. Generally, the best policy is to simply call - abort(). It's not very useful to do more than this because many - errors due to overwriting will show up as address faults (null, odd - addresses etc) rather than malloc-triggered checks, so will also - abort. Also, most compilers know that abort() does not return, so - can better optimize code conditionally calling it. - -PROCEED_ON_ERROR default: defined as 0 (false) - Controls whether detected bad addresses cause them to bypassed - rather than aborting. If set, detected bad arguments to free and - realloc are ignored. And all bookkeeping information is zeroed out - upon a detected overwrite of freed heap space, thus losing the - ability to ever return it from malloc again, but enabling the - application to proceed. If PROCEED_ON_ERROR is defined, the - static variable malloc_corruption_error_count is compiled in - and can be examined to see if errors have occurred. This option - generates slower code than the default abort policy. - -DEBUG default: NOT defined - The DEBUG setting is mainly intended for people trying to modify - this code or diagnose problems when porting to new platforms. - However, it may also be able to better isolate user errors than just - using runtime checks. The assertions in the check routines spell - out in more detail the assumptions and invariants underlying the - algorithms. The checking is fairly extensive, and will slow down - execution noticeably. Calling malloc_stats or mallinfo with DEBUG - set will attempt to check every non-mmapped allocated and free chunk - in the course of computing the summaries. - -ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) - Debugging assertion failures can be nearly impossible if your - version of the assert macro causes malloc to be called, which will - lead to a cascade of further failures, blowing the runtime stack. - ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), - which will usually make debugging easier. - -MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 - The action to take before "return 0" when malloc fails to be able to - return memory because there is none available. - -HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES - True if this system supports sbrk or an emulation of it. - -MORECORE default: sbrk - The name of the sbrk-style system routine to call to obtain more - memory. See below for guidance on writing custom MORECORE - functions. The type of the argument to sbrk/MORECORE varies across - systems. It cannot be size_t, because it supports negative - arguments, so it is normally the signed type of the same width as - size_t (sometimes declared as "intptr_t"). It doesn't much matter - though. Internally, we only call it with arguments less than half - the max value of a size_t, which should work across all reasonable - possibilities, although sometimes generating compiler warnings. See - near the end of this file for guidelines for creating a custom - version of MORECORE. - -MORECORE_CONTIGUOUS default: 1 (true) - If true, take advantage of fact that consecutive calls to MORECORE - with positive arguments always return contiguous increasing - addresses. This is true of unix sbrk. It does not hurt too much to - set it true anyway, since malloc copes with non-contiguities. - Setting it false when definitely non-contiguous saves time - and possibly wasted space it would take to discover this though. - -MORECORE_CANNOT_TRIM default: NOT defined - True if MORECORE cannot release space back to the system when given - negative arguments. This is generally necessary only if you are - using a hand-crafted MORECORE function that cannot handle negative - arguments. - -HAVE_MMAP default: 1 (true) - True if this system supports mmap or an emulation of it. If so, and - HAVE_MORECORE is not true, MMAP is used for all system - allocation. If set and HAVE_MORECORE is true as well, MMAP is - primarily used to directly allocate very large blocks. It is also - used as a backup strategy in cases where MORECORE fails to provide - space from system. Note: A single call to MUNMAP is assumed to be - able to unmap memory that may have be allocated using multiple calls - to MMAP, so long as they are adjacent. - -HAVE_MREMAP default: 1 on linux, else 0 - If true realloc() uses mremap() to re-allocate large blocks and - extend or shrink allocation spaces. - -MMAP_CLEARS default: 1 on unix - True if mmap clears memory so calloc doesn't need to. This is true - for standard unix mmap using /dev/zero. - -USE_BUILTIN_FFS default: 0 (i.e., not used) - Causes malloc to use the builtin ffs() function to compute indices. - Some compilers may recognize and intrinsify ffs to be faster than the - supplied C version. Also, the case of x86 using gcc is special-cased - to an asm instruction, so is already as fast as it can be, and so - this setting has no effect. (On most x86s, the asm version is only - slightly faster than the C version.) - -malloc_getpagesize default: derive from system includes, or 4096. - The system page size. To the extent possible, this malloc manages - memory from the system in page-size units. This may be (and - usually is) a function rather than a constant. This is ignored - if WIN32, where page size is determined using getSystemInfo during - initialization. - -USE_DEV_RANDOM default: 0 (i.e., not used) - Causes malloc to use /dev/random to initialize secure magic seed for - stamping footers. Otherwise, the current time is used. - -NO_MALLINFO default: 0 - If defined, don't compile "mallinfo". This can be a simple way - of dealing with mismatches between system declarations and - those in this file. - -MALLINFO_FIELD_TYPE default: size_t - The type of the fields in the mallinfo struct. This was originally - defined as "int" in SVID etc, but is more usefully defined as - size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set - -REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does - realloc(p, 0). - -LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H -LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H -LACKS_STDLIB_H default: NOT defined unless on WIN32 - Define these if your system does not have these header files. - You might need to manually insert some of the declarations they provide. - -DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, - system_info.dwAllocationGranularity in WIN32, - otherwise 64K. - Also settable using mallopt(M_GRANULARITY, x) - The unit for allocating and deallocating memory from the system. On - most systems with contiguous MORECORE, there is no reason to - make this more than a page. However, systems with MMAP tend to - either require or encourage larger granularities. You can increase - this value to prevent system allocation functions to be called so - often, especially if they are slow. The value must be at least one - page and must be a power of two. Setting to 0 causes initialization - to either page size or win32 region size. (Note: In previous - versions of malloc, the equivalent of this option was called - "TOP_PAD") - -DEFAULT_TRIM_THRESHOLD default: 2MB - Also settable using mallopt(M_TRIM_THRESHOLD, x) - The maximum amount of unused top-most memory to keep before - releasing via malloc_trim in free(). Automatic trimming is mainly - useful in long-lived programs using contiguous MORECORE. Because - trimming via sbrk can be slow on some systems, and can sometimes be - wasteful (in cases where programs immediately afterward allocate - more large chunks) the value should be high enough so that your - overall system performance would improve by releasing this much - memory. As a rough guide, you might set to a value close to the - average size of a process (program) running on your system. - Releasing this much memory would allow such a process to run in - memory. Generally, it is worth tuning trim thresholds when a - program undergoes phases where several large chunks are allocated - and released in ways that can reuse each other's storage, perhaps - mixed with phases where there are no such chunks at all. The trim - value must be greater than page size to have any useful effect. To - disable trimming completely, you can set to MAX_SIZE_T. Note that the trick - some people use of mallocing a huge space and then freeing it at - program startup, in an attempt to reserve system memory, doesn't - have the intended effect under automatic trimming, since that memory - will immediately be returned to the system. - -DEFAULT_MMAP_THRESHOLD default: 256K - Also settable using mallopt(M_MMAP_THRESHOLD, x) - The request size threshold for using MMAP to directly service a - request. Requests of at least this size that cannot be allocated - using already-existing space will be serviced via mmap. (If enough - normal freed space already exists it is used instead.) Using mmap - segregates relatively large chunks of memory so that they can be - individually obtained and released from the host system. A request - serviced through mmap is never reused by any other request (at least - not directly; the system may just so happen to remap successive - requests to the same locations). Segregating space in this way has - the benefits that: Mmapped space can always be individually released - back to the system, which helps keep the system level memory demands - of a long-lived program low. Also, mapped memory doesn't become - `locked' between other chunks, as can happen with normally allocated - chunks, which means that even trimming via malloc_trim would not - release them. However, it has the disadvantage that the space - cannot be reclaimed, consolidated, and then used to service later - requests, as happens with normal chunks. The advantages of mmap - nearly always outweigh disadvantages for "large" chunks, but the - value of "large" may vary across systems. The default is an - empirically derived value that works well in most systems. You can - disable mmap by setting to MAX_SIZE_T. - -*/ - -#ifndef WIN32 -#ifdef _WIN32 -#define WIN32 1 -#endif /* _WIN32 */ -#endif /* WIN32 */ -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#define HAVE_MMAP 1 -#define HAVE_MORECORE 0 -#define LACKS_UNISTD_H -#define LACKS_SYS_PARAM_H -#define LACKS_SYS_MMAN_H -#define LACKS_STRING_H -#define LACKS_STRINGS_H -#define LACKS_SYS_TYPES_H -#define LACKS_ERRNO_H -#define MALLOC_FAILURE_ACTION -#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */ -#endif /* WIN32 */ - -#ifdef __OS2__ -#define INCL_DOS -#include -#define HAVE_MMAP 1 -#define HAVE_MORECORE 0 -#define LACKS_SYS_MMAN_H -#endif /* __OS2__ */ - -#if defined(DARWIN) || defined(_DARWIN) -/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ -#ifndef HAVE_MORECORE -#define HAVE_MORECORE 0 -#define HAVE_MMAP 1 -#endif /* HAVE_MORECORE */ -#endif /* DARWIN */ - -#ifndef LACKS_SYS_TYPES_H -#include /* For size_t */ -#endif /* LACKS_SYS_TYPES_H */ - -/* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -#ifndef ONLY_MSPACES -#define ONLY_MSPACES 0 -#endif /* ONLY_MSPACES */ -#ifndef MSPACES -#if ONLY_MSPACES -#define MSPACES 1 -#else /* ONLY_MSPACES */ -#define MSPACES 0 -#endif /* ONLY_MSPACES */ -#endif /* MSPACES */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)8U) -#endif /* MALLOC_ALIGNMENT */ -#ifndef FOOTERS -#define FOOTERS 0 -#endif /* FOOTERS */ -#ifndef ABORT -#define ABORT abort() -#endif /* ABORT */ -#ifndef ABORT_ON_ASSERT_FAILURE -#define ABORT_ON_ASSERT_FAILURE 1 -#endif /* ABORT_ON_ASSERT_FAILURE */ -#ifndef PROCEED_ON_ERROR -#define PROCEED_ON_ERROR 0 -#endif /* PROCEED_ON_ERROR */ -#ifndef USE_LOCKS -#define USE_LOCKS 0 -#endif /* USE_LOCKS */ -#ifndef INSECURE -#define INSECURE 0 -#endif /* INSECURE */ -#ifndef HAVE_MMAP -#define HAVE_MMAP 1 -#endif /* HAVE_MMAP */ -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 1 -#endif /* MMAP_CLEARS */ -#ifndef HAVE_MREMAP -#ifdef linux -#define HAVE_MREMAP 1 -#else /* linux */ -#define HAVE_MREMAP 0 -#endif /* linux */ -#endif /* HAVE_MREMAP */ -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION errno = ENOMEM; -#endif /* MALLOC_FAILURE_ACTION */ -#ifndef HAVE_MORECORE -#if ONLY_MSPACES -#define HAVE_MORECORE 0 -#else /* ONLY_MSPACES */ -#define HAVE_MORECORE 1 -#endif /* ONLY_MSPACES */ -#endif /* HAVE_MORECORE */ -#if !HAVE_MORECORE -#define MORECORE_CONTIGUOUS 0 -#else /* !HAVE_MORECORE */ -#ifndef MORECORE -#define MORECORE sbrk -#endif /* MORECORE */ -#ifndef MORECORE_CONTIGUOUS -#define MORECORE_CONTIGUOUS 1 -#endif /* MORECORE_CONTIGUOUS */ -#endif /* HAVE_MORECORE */ -#ifndef DEFAULT_GRANULARITY -#if MORECORE_CONTIGUOUS -#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ -#else /* MORECORE_CONTIGUOUS */ -#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) -#endif /* MORECORE_CONTIGUOUS */ -#endif /* DEFAULT_GRANULARITY */ -#ifndef DEFAULT_TRIM_THRESHOLD -#ifndef MORECORE_CANNOT_TRIM -#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) -#else /* MORECORE_CANNOT_TRIM */ -#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T -#endif /* MORECORE_CANNOT_TRIM */ -#endif /* DEFAULT_TRIM_THRESHOLD */ -#ifndef DEFAULT_MMAP_THRESHOLD -#if HAVE_MMAP -#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) -#else /* HAVE_MMAP */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* DEFAULT_MMAP_THRESHOLD */ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 0 -#endif /* USE_BUILTIN_FFS */ -#ifndef USE_DEV_RANDOM -#define USE_DEV_RANDOM 0 -#endif /* USE_DEV_RANDOM */ -#ifndef NO_MALLINFO -#define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ - -/* - mallopt tuning options. SVID/XPG defines four standard parameter - numbers for mallopt, normally defined in malloc.h. None of these - are used in this malloc, so setting them has no effect. But this - malloc does support the following options. -*/ - -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) - -/* ------------------------ Mallinfo declarations ------------------------ */ - -#if !NO_MALLINFO -/* - This version of malloc supports the standard SVID/XPG mallinfo - routine that returns a struct containing usage properties and - statistics. It should work on any system that has a - /usr/include/malloc.h defining struct mallinfo. The main - declaration needed is the mallinfo struct that is returned (by-copy) - by mallinfo(). The malloinfo struct contains a bunch of fields that - are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of - interest. - - HAVE_USR_INCLUDE_MALLOC_H should be set if you have a - /usr/include/malloc.h file that includes a declaration of struct - mallinfo. If so, it is included; else a compliant version is - declared below. These must be precisely the same for mallinfo() to - work. The original SVID version of this struct, defined on most - systems with mallinfo, declares all fields as ints. But some others - define as unsigned long. If your system defines the fields using a - type of different width than listed here, you MUST #include your - system version and #define HAVE_USR_INCLUDE_MALLOC_H. -*/ - -/* #define HAVE_USR_INCLUDE_MALLOC_H */ - -#ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" -#else /* HAVE_USR_INCLUDE_MALLOC_H */ - -/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */ -#define _STRUCT_MALLINFO - -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; - -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* NO_MALLINFO */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if !ONLY_MSPACES - -/* ------------------- Declarations of public routines ------------------- */ - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlrealloc realloc -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlmalloc_max_footprint malloc_max_footprint -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#endif /* USE_DL_PREFIX */ - - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cause the current program to abort. -*/ -void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ - -void* dlrealloc(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -void* dlmemalign(size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -int dlmallopt(int, int); - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -size_t dlmalloc_footprint(void); - -/* - malloc_max_footprint(); - Returns the maximum number of bytes obtained from the system. This - value will be greater than current footprint if deallocated space - has been reclaimed by the system. The peak number of bytes allocated - by malloc, realloc etc., is less than this value. Unlike mallinfo, - this function returns only a precomputed result, so can be called - frequently to monitor memory consumption. Even if locks are - otherwise defined, this function does not use them, so results might - not be up to date. -*/ -size_t dlmalloc_max_footprint(void); - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -void** dlindependent_comalloc(size_t, size_t*, void**); - - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -int dlmalloc_trim(size_t); - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ -void dlmalloc_stats(void); - -#endif /* ONLY_MSPACES */ - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_malloc behaves as malloc, but operates within - the given space. -*/ -void* mspace_malloc(mspace msp, size_t bytes); - -/* - mspace_free behaves as free, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_free is not actually needed. - free may be called instead of mspace_free because freed chunks from - any space are handled by their originating spaces. -*/ -void mspace_free(mspace msp, void* mem); - -/* - mspace_realloc behaves as realloc, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_realloc is not actually - needed. realloc may be called instead of mspace_realloc because - realloced chunks from any space are handled by their originating - spaces. -*/ -void* mspace_realloc(mspace msp, void* mem, size_t newsize); - -/* - mspace_calloc behaves as calloc, but operates within - the given space. -*/ -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); - -/* - mspace_memalign behaves as memalign, but operates within - the given space. -*/ -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); - -/* - mspace_independent_calloc behaves as independent_calloc, but - operates within the given space. -*/ -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); - -/* - mspace_independent_comalloc behaves as independent_comalloc, but - operates within the given space. -*/ -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); - -/* - mspace_footprint() returns the number of bytes obtained from the - system for this space. -*/ -size_t mspace_footprint(mspace msp); - -/* - mspace_max_footprint() returns the peak number of bytes obtained from the - system for this space. -*/ -size_t mspace_max_footprint(mspace msp); - - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - mspace_malloc_stats behaves as malloc_stats, but reports - properties of the given space. -*/ -void mspace_malloc_stats(mspace msp); - -/* - mspace_trim behaves as malloc_trim, but - operates within the given space. -*/ -int mspace_trim(mspace msp, size_t pad); - -/* - An alias for mallopt. -*/ -int mspace_mallopt(int, int); - -#endif /* MSPACES */ - -#ifdef __cplusplus -}; /* end of extern "C" */ -#endif /* __cplusplus */ - -/* - ======================================================================== - To make a fully customizable malloc.h header file, cut everything - above this line, put into file malloc.h, edit to suit, and #include it - on the next line, as well as in programs that use this malloc. - ======================================================================== -*/ - -/* #include "malloc.h" */ - -/*------------------------------ internal #includes ---------------------- */ - -#ifdef _MSC_VER -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -#endif /* _MSC_VER */ - -#include /* for printing in malloc_stats */ - -#ifndef LACKS_ERRNO_H -#include /* for MALLOC_FAILURE_ACTION */ -#endif /* LACKS_ERRNO_H */ -#if FOOTERS -#include /* for magic initialization */ -#endif /* FOOTERS */ -#ifndef LACKS_STDLIB_H -#include /* for abort() */ -#endif /* LACKS_STDLIB_H */ -#ifdef DEBUG -#if ABORT_ON_ASSERT_FAILURE -#define assert(x) if(!(x)) ABORT -#else /* ABORT_ON_ASSERT_FAILURE */ -#include -#endif /* ABORT_ON_ASSERT_FAILURE */ -#else /* DEBUG */ -#define assert(x) -#endif /* DEBUG */ -#ifndef LACKS_STRING_H -#include /* for memset etc */ -#endif /* LACKS_STRING_H */ -#if USE_BUILTIN_FFS -#ifndef LACKS_STRINGS_H -#include /* for ffs */ -#endif /* LACKS_STRINGS_H */ -#endif /* USE_BUILTIN_FFS */ -#if HAVE_MMAP -#ifndef LACKS_SYS_MMAN_H -#include /* for mmap */ -#endif /* LACKS_SYS_MMAN_H */ -#ifndef LACKS_FCNTL_H -#include -#endif /* LACKS_FCNTL_H */ -#endif /* HAVE_MMAP */ -#if HAVE_MORECORE -#ifndef LACKS_UNISTD_H -#include /* for sbrk */ -#else /* LACKS_UNISTD_H */ -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -extern void* sbrk(ptrdiff_t); -#endif /* FreeBSD etc */ -#endif /* LACKS_UNISTD_H */ -#endif /* HAVE_MMAP */ - -#ifndef WIN32 -#ifndef malloc_getpagesize -# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ -# ifndef _SC_PAGE_SIZE -# define _SC_PAGE_SIZE _SC_PAGESIZE -# endif -# endif -# ifdef _SC_PAGE_SIZE -# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) -# else -# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) - extern size_t getpagesize(); -# define malloc_getpagesize getpagesize() -# else -# ifdef WIN32 /* use supplied emulation of getpagesize */ -# define malloc_getpagesize getpagesize() -# else -# ifndef LACKS_SYS_PARAM_H -# include -# endif -# ifdef EXEC_PAGESIZE -# define malloc_getpagesize EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define malloc_getpagesize NBPG -# else -# define malloc_getpagesize (NBPG * CLSIZE) -# endif -# else -# ifdef NBPC -# define malloc_getpagesize NBPC -# else -# ifdef PAGESIZE -# define malloc_getpagesize PAGESIZE -# else /* just guess */ -# define malloc_getpagesize ((size_t)4096U) -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif -#endif - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) - -/* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some platforms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) - -/* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) - -/* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) - -/* the number of bytes to offset an address to align it */ -#define align_offset(A)\ - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ - ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) - -/* -------------------------- MMAP preliminaries ------------------------- */ - -/* - If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and - checks to fail so compiler optimizer can delete code rather than - using so many "#if"s. -*/ - - -/* MORECORE and MMAP must return MFAIL on failure */ -#define MFAIL ((void*)(MAX_SIZE_T)) -#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ - -#if !HAVE_MMAP -#define IS_MMAPPED_BIT (SIZE_T_ZERO) -#define USE_MMAP_BIT (SIZE_T_ZERO) -#define CALL_MMAP(s) MFAIL -#define CALL_MUNMAP(a, s) (-1) -#define DIRECT_MMAP(s) MFAIL - -#else /* HAVE_MMAP */ -#define IS_MMAPPED_BIT (SIZE_T_ONE) -#define USE_MMAP_BIT (SIZE_T_ONE) - -#if !defined(WIN32) && !defined (__OS2__) -#define CALL_MUNMAP(a, s) munmap((a), (s)) -#define MMAP_PROT (PROT_READ|PROT_WRITE) -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif /* MAP_ANON */ -#ifdef MAP_ANONYMOUS -#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) -#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) -#else /* MAP_ANONYMOUS */ -/* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. -*/ -#define MMAP_FLAGS (MAP_PRIVATE) -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ -#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \ - (dev_zero_fd = open("/dev/zero", O_RDWR), \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) -#endif /* MAP_ANONYMOUS */ - -#define DIRECT_MMAP(s) CALL_MMAP(s) - -#elif defined(__OS2__) - -/* OS/2 MMAP via DosAllocMem */ -static void* os2mmap(size_t size) { - void* ptr; - if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) && - DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE)) - return MFAIL; - return ptr; -} - -#define os2direct_mmap(n) os2mmap(n) - -/* This function supports releasing coalesed segments */ -static int os2munmap(void* ptr, size_t size) { - while (size) { - ULONG ulSize = size; - ULONG ulFlags = 0; - if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0) - return -1; - if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 || - ulSize > size) - return -1; - if (DosFreeMem(ptr) != 0) - return -1; - ptr = ( void * ) ( ( char * ) ptr + ulSize ); - size -= ulSize; - } - return 0; -} - -#define CALL_MMAP(s) os2mmap(s) -#define CALL_MUNMAP(a, s) os2munmap((a), (s)) -#define DIRECT_MMAP(s) os2direct_mmap(s) - -#else /* WIN32 */ - -/* Win32 MMAP via VirtualAlloc */ -static void* win32mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static void* win32direct_mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, - PAGE_EXECUTE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* This function supports releasing coalesed segments */ -static int win32munmap(void* ptr, size_t size) { - MEMORY_BASIC_INFORMATION minfo; - char* cptr = ptr; - while (size) { - if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) - return -1; - if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || - minfo.State != MEM_COMMIT || minfo.RegionSize > size) - return -1; - if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) - return -1; - cptr += minfo.RegionSize; - size -= minfo.RegionSize; - } - return 0; -} - -#define CALL_MMAP(s) win32mmap(s) -#define CALL_MUNMAP(a, s) win32munmap((a), (s)) -#define DIRECT_MMAP(s) win32direct_mmap(s) -#endif /* WIN32 */ -#endif /* HAVE_MMAP */ - -#if HAVE_MMAP && HAVE_MREMAP -#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) -#else /* HAVE_MMAP && HAVE_MREMAP */ -#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ - -#if HAVE_MORECORE -#define CALL_MORECORE(S) MORECORE(S) -#else /* HAVE_MORECORE */ -#define CALL_MORECORE(S) MFAIL -#endif /* HAVE_MORECORE */ - -/* mstate bit set if contiguous morecore disabled or failed */ -#define USE_NONCONTIGUOUS_BIT (4U) - -/* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) - - -/* --------------------------- Lock preliminaries ------------------------ */ - -#if USE_LOCKS - -/* - When locks are defined, there are up to two global locks: - - * If HAVE_MORECORE, morecore_mutex protects sequences of calls to - MORECORE. In many cases sys_alloc requires two calls, that should - not be interleaved with calls by other threads. This does not - protect against direct calls to MORECORE by other threads not - using this lock, so there is still code to cope the best we can on - interference. - - * magic_init_mutex ensures that mparams.magic and other - unique mparams values are initialized only once. -*/ - -#if !defined(WIN32) && !defined(__OS2__) -/* By default use posix locks */ -#include -#define MLOCK_T pthread_mutex_t -#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL) -#define ACQUIRE_LOCK(l) pthread_mutex_lock(l) -#define RELEASE_LOCK(l) pthread_mutex_unlock(l) - -#if HAVE_MORECORE -static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif /* HAVE_MORECORE */ - -static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER; - -#elif defined(__OS2__) -#define MLOCK_T HMTX -#define INITIAL_LOCK(l) DosCreateMutexSem(0, l, 0, FALSE) -#define ACQUIRE_LOCK(l) DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT) -#define RELEASE_LOCK(l) DosReleaseMutexSem(*l) -#if HAVE_MORECORE -static MLOCK_T morecore_mutex; -#endif /* HAVE_MORECORE */ -static MLOCK_T magic_init_mutex; - -#else /* WIN32 */ -/* - Because lock-protected regions have bounded times, and there - are no recursive lock calls, we can use simple spinlocks. -*/ - -#define MLOCK_T long -static int win32_acquire_lock (MLOCK_T *sl) { - for (;;) { -#ifdef InterlockedCompareExchangePointer - if (!InterlockedCompareExchange(sl, 1, 0)) - return 0; -#else /* Use older void* version */ - if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0)) - return 0; -#endif /* InterlockedCompareExchangePointer */ - Sleep (0); - } -} - -static void win32_release_lock (MLOCK_T *sl) { - InterlockedExchange (sl, 0); -} - -#define INITIAL_LOCK(l) *(l)=0 -#define ACQUIRE_LOCK(l) win32_acquire_lock(l) -#define RELEASE_LOCK(l) win32_release_lock(l) -#if HAVE_MORECORE -static MLOCK_T morecore_mutex; -#endif /* HAVE_MORECORE */ -static MLOCK_T magic_init_mutex; -#endif /* WIN32 */ - -#define USE_LOCK_BIT (2U) -#else /* USE_LOCKS */ -#define USE_LOCK_BIT (0U) -#define INITIAL_LOCK(l) -#endif /* USE_LOCKS */ - -#if USE_LOCKS && HAVE_MORECORE -#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex); -#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex); -#else /* USE_LOCKS && HAVE_MORECORE */ -#define ACQUIRE_MORECORE_LOCK() -#define RELEASE_MORECORE_LOCK() -#endif /* USE_LOCKS && HAVE_MORECORE */ - -#if USE_LOCKS -#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); -#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); -#else /* USE_LOCKS */ -#define ACQUIRE_MAGIC_INIT_LOCK() -#define RELEASE_MAGIC_INIT_LOCK() -#endif /* USE_LOCKS */ - - -/* ----------------------- Chunk representations ------------------------ */ - -/* - (The following includes lightly edited explanations by Colin Plumb.) - - The malloc_chunk declaration below is misleading (but accurate and - necessary). It declares a "view" into memory allowing access to - necessary fields at known offsets from a given base. - - Chunks of memory are maintained using a `boundary tag' method as - originally described by Knuth. (See the paper by Paul Wilson - ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such - techniques.) Sizes of free chunks are stored both in the front of - each chunk and at the end. This makes consolidating fragmented - chunks into bigger chunks fast. The head fields also hold bits - representing whether chunks are free or in use. - - Here are some pictures to make it clearer. They are "exploded" to - show that the state of a chunk can be thought of as extending from - the high 31 bits of the head field of its header through the - prev_foot and PINUSE_BIT bit of the following chunk header. - - A chunk that's in use looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk (if P = 1) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 1| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - +- -+ - | | - +- -+ - | : - +- size - sizeof(size_t) available payload bytes -+ - : | - chunk-> +- -+ - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| - | Size of next chunk (may or may not be in use) | +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - And if it's free, it looks like this: - - chunk-> +- -+ - | User payload (must be in use, or we would have merged!) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 0| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Next pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prev pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- size - sizeof(struct chunk) unused bytes -+ - : | - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| - | Size of next chunk (must be in use, or we would have merged)| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- User payload -+ - : | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0| - +-+ - Note that since we always merge adjacent free chunks, the chunks - adjacent to a free chunk must be in use. - - Given a pointer to a chunk (which can be derived trivially from the - payload pointer) we can, in O(1) time, find out whether the adjacent - chunks are free, and if so, unlink them from the lists that they - are on and merge them with the current chunk. - - Chunks always begin on even word boundaries, so the mem portion - (which is returned to the user) is also on an even word boundary, and - thus at least double-word aligned. - - The P (PINUSE_BIT) bit, stored in the unused low-order bit of the - chunk size (which is always a multiple of two words), is an in-use - bit for the *previous* chunk. If that bit is *clear*, then the - word before the current chunk size contains the previous chunk - size, and can be used to find the front of the previous chunk. - The very first chunk allocated always has this bit set, preventing - access to non-existent (or non-owned) memory. If pinuse is set for - any given chunk, then you CANNOT determine the size of the - previous chunk, and might even get a memory addressing fault when - trying to do so. - - The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of - the chunk size redundantly records whether the current chunk is - inuse. This redundancy enables usage checks within free and realloc, - and reduces indirection when freeing and consolidating chunks. - - Each freshly allocated chunk must have both cinuse and pinuse set. - That is, each allocated chunk borders either a previously allocated - and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any - found chunk. Further, no free chunk physically borders another one, - so each free chunk is known to be preceded and followed by either - inuse chunks or the ends of memory. - - Note that the `foot' of the current chunk is actually represented - as the prev_foot of the NEXT chunk. This makes it easier to - deal with alignments etc but can be very confusing when trying - to extend or adapt this code. - - The exceptions to all this are - - 1. The special chunk `top' is the top-most available chunk (i.e., - the one bordering the end of available memory). It is treated - specially. Top is never included in any bin, is used only if - no other chunk is available, and is released back to the - system if it is very large (see M_TRIM_THRESHOLD). In effect, - the top chunk is treated as larger (and thus less well - fitting) than any other available chunk. The top chunk - doesn't update its trailing size field since there is no next - contiguous chunk that would have to index off it. However, - space is still allocated for it (TOP_FOOT_SIZE) to enable - separation or merging when space is extended. - - 3. Chunks allocated via mmap, which have the lowest-order bit - (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set - PINUSE_BIT in their head fields. Because they are allocated - one-by-one, each must carry its own prev_foot field, which is - also used to hold the offset this chunk has within its mmapped - region, which is needed to preserve alignment. Each mmapped - chunk is trailed by the first two fields of a fake next-chunk - for sake of usage checks. - -*/ - -struct malloc_chunk { - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; -}; - -typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk* mchunkptr; -typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ -typedef size_t bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ -typedef unsigned int flag_t; /* The type of various bit flag sets */ - -/* ------------------- Chunks sizes and alignments ----------------------- */ - -#define MCHUNK_SIZE (sizeof(mchunk)) - -#if FOOTERS -#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -#else /* FOOTERS */ -#define CHUNK_OVERHEAD (SIZE_T_SIZE) -#endif /* FOOTERS */ - -/* MMapped chunks need a second word of overhead ... */ -#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -/* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) - -/* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE\ - ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) -/* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) - -/* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) - -/* pad request bytes into a usable size */ -#define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* pad request, checking for minimum (but not maximum) */ -#define request2size(req) \ - (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) - - -/* ------------------ Operations on head and foot fields ----------------- */ - -/* - The head field of a chunk is or'ed with PINUSE_BIT when previous - adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use. If the chunk was obtained with mmap, the prev_foot field has - IS_MMAPPED_BIT set, otherwise holding the offset of the base of the - mmapped region to the base of the chunk. -*/ - -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) - -/* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) - -/* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define chunksize(p) ((p)->head & ~(INUSE_BITS)) - -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) -#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) - -/* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) - -/* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) - -/* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) - -/* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) - -/* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s)\ - ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) - -/* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n)\ - (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) - -#define is_mmapped(p)\ - (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT)) - -/* Get the internal overhead associated with chunk p */ -#define overhead_for(p)\ - (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) - -/* Return true if malloced space is not necessarily cleared */ -#if MMAP_CLEARS -#define calloc_must_clear(p) (!is_mmapped(p)) -#else /* MMAP_CLEARS */ -#define calloc_must_clear(p) (1) -#endif /* MMAP_CLEARS */ - -/* ---------------------- Overlaid data structures ----------------------- */ - -/* - When chunks are not in use, they are treated as nodes of either - lists or trees. - - "Small" chunks are stored in circular doubly-linked lists, and look - like this: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space (may be 0 bytes long) . - . . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Larger chunks are kept in a form of bitwise digital trees (aka - tries) keyed on chunksizes. Because malloc_tree_chunks are only for - free chunks greater than 256 bytes, their size doesn't impose any - constraints on user chunk sizes. Each node looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to left child (child[0]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to right child (child[1]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to parent | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | bin index of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Each tree holding treenodes is a tree of unique chunk sizes. Chunks - of the same size are arranged in a circularly-linked list, with only - the oldest chunk (the next to be used, in our FIFO ordering) - actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node - is inserted, it is linked off the existing node using pointers that - work in the same way as fd/bk pointers of small chunks. - - Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each - tree level, with the chunks in the smaller half of the range (0x100 - <= x < 0x140 for the top nose) in the left subtree and the larger - half (0x140 <= x < 0x180) in the right subtree. This is, of course, - done by inspecting individual bits. - - Using these rules, each node's left subtree contains all smaller - sizes than its right subtree. However, the node at the root of each - subtree has no particular ordering relationship to either. (The - dividing line between the subtree sizes is based on trie relation.) - If we remove the last chunk of a given size from the interior of the - tree, we need to replace it with a leaf node. The tree ordering - rules permit a node to be replaced by any leaf below it. - - The smallest chunk in a tree (a common operation in a best-fit - allocator) can be found by walking a path to the leftmost leaf in - the tree. Unlike a usual binary tree, where we follow left child - pointers until we reach a null, here we follow the right child - pointer any time the left one is null, until we reach a leaf with - both child pointers null. The smallest chunk in the tree will be - somewhere along that path. - - The worst case number of steps to add, find, or remove a node is - bounded by the number of bits differentiating chunks within - bins. Under current bin calculations, this ranges from 6 up to 21 - (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case - is of course much better. -*/ - -struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ - size_t prev_foot; - size_t head; - struct malloc_tree_chunk* fd; - struct malloc_tree_chunk* bk; - - struct malloc_tree_chunk* child[2]; - struct malloc_tree_chunk* parent; - bindex_t index; -}; - -typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk* tchunkptr; -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ - -/* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) - -/* ----------------------------- Segments -------------------------------- */ - -/* - Each malloc space may include non-contiguous segments, held in a - list headed by an embedded malloc_segment record representing the - top-most space. Segments also include flags holding properties of - the space. Large chunks that are directly allocated by mmap are not - included in this list. They are instead independently created and - destroyed without otherwise keeping track of them. - - Segment management mainly comes into play for spaces allocated by - MMAP. Any call to MMAP might or might not return memory that is - adjacent to an existing segment. MORECORE normally contiguously - extends the current space, so this space is almost always adjacent, - which is simpler and faster to deal with. (This is why MORECORE is - used preferentially to MMAP when both are available -- see - sys_alloc.) When allocating using MMAP, we don't use any of the - hinting mechanisms (inconsistently) supported in various - implementations of unix mmap, or distinguish reserving from - committing memory. Instead, we just ask for space, and exploit - contiguity when we get it. It is probably possible to do - better than this on some systems, but no general scheme seems - to be significantly better. - - Management entails a simpler variant of the consolidation scheme - used for chunks to reduce fragmentation -- new adjacent memory is - normally prepended or appended to an existing segment. However, - there are limitations compared to chunk consolidation that mostly - reflect the fact that segment processing is relatively infrequent - (occurring only when getting memory from system) and that we - don't expect to have huge numbers of segments: - - * Segments are not indexed, so traversal requires linear scans. (It - would be possible to index these, but is not worth the extra - overhead and complexity for most programs on most platforms.) - * New segments are only appended to old ones when holding top-most - memory; if they cannot be prepended to others, they are held in - different segments. - - Except for the top-most segment of an mstate, each segment record - is kept at the tail of its segment. Segments are added by pushing - segment records onto the list headed by &mstate.seg for the - containing mstate. - - Segment flags control allocation/merge/deallocation policies: - * If EXTERN_BIT set, then we did not allocate this segment, - and so should not try to deallocate or merge with others. - (This currently holds only for the initial segment passed - into create_mspace_with_base.) - * If IS_MMAPPED_BIT set, the segment may be merged with - other surrounding mmapped segments and trimmed/de-allocated - using munmap. - * If neither bit is set, then the segment was obtained using - MORECORE so can be merged with surrounding MORECORE'd segments - and deallocated/trimmed using MORECORE with negative arguments. -*/ - -struct malloc_segment { - char* base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment* next; /* ptr to next segment */ -#if FFI_MMAP_EXEC_WRIT - /* The mmap magic is supposed to store the address of the executable - segment at the very end of the requested block. */ - -# define mmap_exec_offset(b,s) (*(ptrdiff_t*)((b)+(s)-sizeof(ptrdiff_t))) - - /* We can only merge segments if their corresponding executable - segments are at identical offsets. */ -# define check_segment_merge(S,b,s) \ - (mmap_exec_offset((b),(s)) == (S)->exec_offset) - -# define add_segment_exec_offset(p,S) ((char*)(p) + (S)->exec_offset) -# define sub_segment_exec_offset(p,S) ((char*)(p) - (S)->exec_offset) - - /* The removal of sflags only works with HAVE_MORECORE == 0. */ - -# define get_segment_flags(S) (IS_MMAPPED_BIT) -# define set_segment_flags(S,v) \ - (((v) != IS_MMAPPED_BIT) ? (ABORT, (v)) : \ - (((S)->exec_offset = \ - mmap_exec_offset((S)->base, (S)->size)), \ - (mmap_exec_offset((S)->base + (S)->exec_offset, (S)->size) != \ - (S)->exec_offset) ? (ABORT, (v)) : \ - (mmap_exec_offset((S)->base, (S)->size) = 0), (v))) - - /* We use an offset here, instead of a pointer, because then, when - base changes, we don't have to modify this. On architectures - with segmented addresses, this might not work. */ - ptrdiff_t exec_offset; -#else - -# define get_segment_flags(S) ((S)->sflags) -# define set_segment_flags(S,v) ((S)->sflags = (v)) -# define check_segment_merge(S,b,s) (1) - - flag_t sflags; /* mmap and extern flag */ -#endif -}; - -#define is_mmapped_segment(S) (get_segment_flags(S) & IS_MMAPPED_BIT) -#define is_extern_segment(S) (get_segment_flags(S) & EXTERN_BIT) - -typedef struct malloc_segment msegment; -typedef struct malloc_segment* msegmentptr; - -/* ---------------------------- malloc_state ----------------------------- */ - -/* - A malloc_state holds all of the bookkeeping for a space. - The main fields are: - - Top - The topmost chunk of the currently active segment. Its size is - cached in topsize. The actual size of topmost space is - topsize+TOP_FOOT_SIZE, which includes space reserved for adding - fenceposts and segment records if necessary when getting more - space from the system. The size at which to autotrim top is - cached from mparams in trim_check, except that it is disabled if - an autotrim fails. - - Designated victim (dv) - This is the preferred chunk for servicing small requests that - don't have exact fits. It is normally the chunk split off most - recently to service another small request. Its size is cached in - dvsize. The link fields of this chunk are not maintained since it - is not kept in a bin. - - SmallBins - An array of bin headers for free chunks. These bins hold chunks - with sizes less than MIN_LARGE_SIZE bytes. Each bin contains - chunks of all the same size, spaced 8 bytes apart. To simplify - use in double-linked lists, each bin header acts as a malloc_chunk - pointing to the real first node, if it exists (else pointing to - itself). This avoids special-casing for headers. But to avoid - waste, we allocate only the fd/bk pointers of bins, and then use - repositioning tricks to treat these as the fields of a chunk. - - TreeBins - Treebins are pointers to the roots of trees holding a range of - sizes. There are 2 equally spaced treebins for each power of two - from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything - larger. - - Bin maps - There is one bit map for small bins ("smallmap") and one for - treebins ("treemap). Each bin sets its bit when non-empty, and - clears the bit when empty. Bit operations are then used to avoid - bin-by-bin searching -- nearly all "search" is done without ever - looking at bins that won't be selected. The bit maps - conservatively use 32 bits per map word, even if on 64bit system. - For a good description of some of the bit-based techniques used - here, see Henry S. Warren Jr's book "Hacker's Delight" (and - supplement at http://hackersdelight.org/). Many of these are - intended to reduce the branchiness of paths through malloc etc, as - well as to reduce the number of memory locations read or written. - - Segments - A list of segments headed by an embedded malloc_segment record - representing the initial space. - - Address check support - The least_addr field is the least address ever obtained from - MORECORE or MMAP. Attempted frees and reallocs of any address less - than this are trapped (unless INSECURE is defined). - - Magic tag - A cross-check field that should always hold same value as mparams.magic. - - Flags - Bits recording whether to use MMAP, locks, or contiguous MORECORE - - Statistics - Each space keeps track of current and maximum system memory - obtained via MORECORE or MMAP. - - Locking - If USE_LOCKS is defined, the "mutex" lock is acquired and released - around every public call using this mspace. -*/ - -/* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) - -struct malloc_state { - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char* least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t magic; - mchunkptr smallbins[(NSMALLBINS+1)*2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - flag_t mflags; -#if USE_LOCKS - MLOCK_T mutex; /* locate lock among fields that rarely change */ -#endif /* USE_LOCKS */ - msegment seg; -}; - -typedef struct malloc_state* mstate; - -/* ------------- Global malloc_state and malloc_params ------------------- */ - -/* - malloc_params holds global properties, including those that can be - dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. -*/ - -struct malloc_params { - size_t magic; - size_t page_size; - size_t granularity; - size_t mmap_threshold; - size_t trim_threshold; - flag_t default_mflags; -}; - -static struct malloc_params mparams; - -/* The global malloc_state used for all non-"mspace" calls */ -static struct malloc_state _gm_; -#define gm (&_gm_) -#define is_global(M) ((M) == &_gm_) -#define is_initialized(M) ((M)->top != 0) - -/* -------------------------- system alloc setup ------------------------- */ - -/* Operations on mflags */ - -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) -#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) - -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) -#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) - -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) - -#define set_lock(M,L)\ - ((M)->mflags = (L)?\ - ((M)->mflags | USE_LOCK_BIT) :\ - ((M)->mflags & ~USE_LOCK_BIT)) - -/* page-align a size */ -#define page_align(S)\ - (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) - -/* granularity-align a size */ -#define granularity_align(S)\ - (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) - -#define is_page_aligned(S)\ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S)\ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) - -/* True if segment S holds address A */ -#define segment_holds(S, A)\ - ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) - -/* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char* addr) { - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= sp->base && addr < sp->base + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} - -/* Return true if segment contains a segment link */ -static int has_segment_link(mstate m, msegmentptr ss) { - msegmentptr sp = &m->seg; - for (;;) { - if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) - return 1; - if ((sp = sp->next) == 0) - return 0; - } -} - -#ifndef MORECORE_CANNOT_TRIM -#define should_trim(M,s) ((s) > (M)->trim_check) -#else /* MORECORE_CANNOT_TRIM */ -#define should_trim(M,s) (0) -#endif /* MORECORE_CANNOT_TRIM */ - -/* - TOP_FOOT_SIZE is padding at the end of a segment, including space - that may be needed to place segment records and fenceposts when new - noncontiguous segments are added. -*/ -#define TOP_FOOT_SIZE\ - (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) - - -/* ------------------------------- Hooks -------------------------------- */ - -/* - PREACTION should be defined to return 0 on success, and nonzero on - failure. If you are not using locking, you can redefine these to do - anything you like. -*/ - -#if USE_LOCKS - -/* Ensure locks are initialized */ -#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) - -#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) -#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } -#else /* USE_LOCKS */ - -#ifndef PREACTION -#define PREACTION(M) (0) -#endif /* PREACTION */ - -#ifndef POSTACTION -#define POSTACTION(M) -#endif /* POSTACTION */ - -#endif /* USE_LOCKS */ - -/* - CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. - USAGE_ERROR_ACTION is triggered on detected bad frees and - reallocs. The argument p is an address that might have triggered the - fault. It is ignored by the two predefined actions, but might be - useful in custom actions that try to help diagnose errors. -*/ - -#if PROCEED_ON_ERROR - -/* A count of the number of corruption errors causing resets */ -int malloc_corruption_error_count; - -/* default corruption action */ -static void reset_on_error(mstate m); - -#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) -#define USAGE_ERROR_ACTION(m, p) - -#else /* PROCEED_ON_ERROR */ - -#ifndef CORRUPTION_ERROR_ACTION -#define CORRUPTION_ERROR_ACTION(m) ABORT -#endif /* CORRUPTION_ERROR_ACTION */ - -#ifndef USAGE_ERROR_ACTION -#define USAGE_ERROR_ACTION(m,p) ABORT -#endif /* USAGE_ERROR_ACTION */ - -#endif /* PROCEED_ON_ERROR */ - -/* -------------------------- Debugging setup ---------------------------- */ - -#if ! DEBUG - -#define check_free_chunk(M,P) -#define check_inuse_chunk(M,P) -#define check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) -#define check_malloc_state(M) -#define check_top_chunk(M,P) - -#else /* DEBUG */ -#define check_free_chunk(M,P) do_check_free_chunk(M,P) -#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) -#define check_top_chunk(M,P) do_check_top_chunk(M,P) -#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) -#define check_malloc_state(M) do_check_malloc_state(M) - -static void do_check_any_chunk(mstate m, mchunkptr p); -static void do_check_top_chunk(mstate m, mchunkptr p); -static void do_check_mmapped_chunk(mstate m, mchunkptr p); -static void do_check_inuse_chunk(mstate m, mchunkptr p); -static void do_check_free_chunk(mstate m, mchunkptr p); -static void do_check_malloced_chunk(mstate m, void* mem, size_t s); -static void do_check_tree(mstate m, tchunkptr t); -static void do_check_treebin(mstate m, bindex_t i); -static void do_check_smallbin(mstate m, bindex_t i); -static void do_check_malloc_state(mstate m); -static int bin_find(mstate m, mchunkptr x); -static size_t traverse_and_check(mstate m); -#endif /* DEBUG */ - -/* ---------------------------- Indexing Bins ---------------------------- */ - -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) ((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) - -/* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) -#define treebin_at(M,i) (&((M)->treebins[i])) - -/* assign tree index for size S to variable I */ -#if defined(__GNUC__) && defined(i386) -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} -#else /* GNUC */ -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int Y = (unsigned int)X;\ - unsigned int N = ((Y - 0x100) >> 16) & 8;\ - unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ - N += K;\ - N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ - K = 14 - N + ((Y <<= K) >> 15);\ - I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ - }\ -} -#endif /* GNUC */ - -/* Bit representing maximum resolved size in a treebin at i */ -#define bit_for_tree_index(i) \ - (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) - -/* Shift placing maximum resolved bit in a treebin at i as sign bit */ -#define leftshift_for_tree_index(i) \ - ((i == NTREEBINS-1)? 0 : \ - ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) - -/* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) - - -/* ------------------------ Operations on bin maps ----------------------- */ - -/* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) - -/* Mark/Clear bits with given index */ -#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) - -#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) - -/* index corresponding to given bit */ - -#if defined(__GNUC__) && defined(i386) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ - I = (bindex_t)J;\ -} - -#else /* GNUC */ -#if USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 - -#else /* USE_BUILTIN_FFS */ -#define compute_bit2idx(X, I)\ -{\ - unsigned int Y = X - 1;\ - unsigned int K = Y >> (16-4) & 16;\ - unsigned int N = K; Y >>= K;\ - N += K = Y >> (8-3) & 8; Y >>= K;\ - N += K = Y >> (4-2) & 4; Y >>= K;\ - N += K = Y >> (2-1) & 2; Y >>= K;\ - N += K = Y >> (1-0) & 1; Y >>= K;\ - I = (bindex_t)(N + Y);\ -} -#endif /* USE_BUILTIN_FFS */ -#endif /* GNUC */ - -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - - -/* ----------------------- Runtime Check Support ------------------------- */ - -/* - For security, the main invariant is that malloc/free/etc never - writes to a static address other than malloc_state, unless static - malloc_state itself has been corrupted, which cannot occur via - malloc (because of these checks). In essence this means that we - believe all pointers, sizes, maps etc held in malloc_state, but - check all of those linked or offsetted from other embedded data - structures. These checks are interspersed with main code in a way - that tends to minimize their run-time cost. - - When FOOTERS is defined, in addition to range checking, we also - verify footer fields of inuse chunks, which can be used guarantee - that the mstate controlling malloc/free is intact. This is a - streamlined version of the approach described by William Robertson - et al in "Run-time Detection of Heap-based Overflows" LISA'03 - http://www.usenix.org/events/lisa03/tech/robertson.html The footer - of an inuse chunk holds the xor of its mstate and a random seed, - that is checked upon calls to free() and realloc(). This is - (probablistically) unguessable from outside the program, but can be - computed by any code successfully malloc'ing any chunk, so does not - itself provide protection against code that has already broken - security through some other means. Unlike Robertson et al, we - always dynamically check addresses of all offset chunks (previous, - next, etc). This turns out to be cheaper than relying on hashes. -*/ - -#if !INSECURE -/* Check if address a is at least as high as any from MORECORE or MMAP */ -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) -/* Check if address of next chunk n is higher than base chunk p */ -#define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has its cinuse bit on */ -#define ok_cinuse(p) cinuse(p) -/* Check if p has its pinuse bit on */ -#define ok_pinuse(p) pinuse(p) - -#else /* !INSECURE */ -#define ok_address(M, a) (1) -#define ok_next(b, n) (1) -#define ok_cinuse(p) (1) -#define ok_pinuse(p) (1) -#endif /* !INSECURE */ - -#if (FOOTERS && !INSECURE) -/* Check if (alleged) mstate m has expected magic field */ -#define ok_magic(M) ((M)->magic == mparams.magic) -#else /* (FOOTERS && !INSECURE) */ -#define ok_magic(M) (1) -#endif /* (FOOTERS && !INSECURE) */ - - -/* In gcc, use __builtin_expect to minimize impact of checks */ -#if !INSECURE -#if defined(__GNUC__) && __GNUC__ >= 3 -#define RTCHECK(e) __builtin_expect(e, 1) -#else /* GNUC */ -#define RTCHECK(e) (e) -#endif /* GNUC */ -#else /* !INSECURE */ -#define RTCHECK(e) (1) -#endif /* !INSECURE */ - -/* macros to set up inuse chunks with or without footers */ - -#if !FOOTERS - -#define mark_inuse_foot(M,p,s) - -/* Set cinuse bit and pinuse bit of next chunk */ -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set size, cinuse and pinuse bit of this chunk */ -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) - -#else /* FOOTERS */ - -/* Set foot of inuse chunk to be xor of mstate and seed */ -#define mark_inuse_foot(M,p,s)\ - (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) - -#define get_mstate_for(p)\ - ((mstate)(((mchunkptr)((char*)(p) +\ - (chunksize(p))))->prev_foot ^ mparams.magic)) - -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M,p,s)) - -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ - mark_inuse_foot(M,p,s)) - -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - mark_inuse_foot(M, p, s)) - -#endif /* !FOOTERS */ - -/* ---------------------------- setting mparams -------------------------- */ - -/* Initialize mparams */ -static int init_mparams(void) { - if (mparams.page_size == 0) { - size_t s; - - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; -#if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ - -#if (FOOTERS && !INSECURE) - { -#if USE_DEV_RANDOM - int fd; - unsigned char buf[sizeof(size_t)]; - /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { - s = *((size_t *) buf); - close(fd); - } - else -#endif /* USE_DEV_RANDOM */ - s = (size_t)(time(0) ^ (size_t)0x55555555U); - - s |= (size_t)8U; /* ensure nonzero */ - s &= ~(size_t)7U; /* improve chances of fault for bad values */ - - } -#else /* (FOOTERS && !INSECURE) */ - s = (size_t)0x58585858U; -#endif /* (FOOTERS && !INSECURE) */ - ACQUIRE_MAGIC_INIT_LOCK(); - if (mparams.magic == 0) { - mparams.magic = s; - /* Set up lock for main malloc area */ - INITIAL_LOCK(&gm->mutex); - gm->mflags = mparams.default_mflags; - } - RELEASE_MAGIC_INIT_LOCK(); - -#if !defined(WIN32) && !defined(__OS2__) - mparams.page_size = malloc_getpagesize; - mparams.granularity = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : mparams.page_size); -#elif defined (__OS2__) - /* if low-memory is used, os2munmap() would break - if it were anything other than 64k */ - mparams.page_size = 4096u; - mparams.granularity = 65536u; -#else /* WIN32 */ - { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - mparams.page_size = system_info.dwPageSize; - mparams.granularity = system_info.dwAllocationGranularity; - } -#endif /* WIN32 */ - - /* Sanity-check configuration: - size_t must be unsigned and as wide as pointer type. - ints must be at least 4 bytes. - alignment must be at least 8. - Alignment, min chunk size, and page size must all be powers of 2. - */ - if ((sizeof(size_t) != sizeof(char*)) || - (MAX_SIZE_T < MIN_CHUNK_SIZE) || - (sizeof(int) < 4) || - (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || - ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || - ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) - ABORT; - } - return 0; -} - -/* support for mallopt */ -static int change_mparam(int param_number, int value) { - size_t val = (size_t)value; - init_mparams(); - switch(param_number) { - case M_TRIM_THRESHOLD: - mparams.trim_threshold = val; - return 1; - case M_GRANULARITY: - if (val >= mparams.page_size && ((val & (val-1)) == 0)) { - mparams.granularity = val; - return 1; - } - else - return 0; - case M_MMAP_THRESHOLD: - mparams.mmap_threshold = val; - return 1; - default: - return 0; - } -} - -#if DEBUG -/* ------------------------- Debugging Support --------------------------- */ - -/* Check properties of any chunk, whether free, inuse, mmapped etc */ -static void do_check_any_chunk(mstate m, mchunkptr p) { - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); -} - -/* Check properties of top chunk */ -static void do_check_top_chunk(mstate m, mchunkptr p) { - msegmentptr sp = segment_holding(m, (char*)p); - size_t sz = chunksize(p); - assert(sp != 0); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(sz == m->topsize); - assert(sz > 0); - assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); - assert(pinuse(p)); - assert(!next_pinuse(p)); -} - -/* Check properties of (inuse) mmapped chunks */ -static void do_check_mmapped_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD); - assert(is_mmapped(p)); - assert(use_mmap(m)); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(!is_small(sz)); - assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); - assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); - assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); -} - -/* Check properties of inuse chunks */ -static void do_check_inuse_chunk(mstate m, mchunkptr p) { - do_check_any_chunk(m, p); - assert(cinuse(p)); - assert(next_pinuse(p)); - /* If not pinuse and not mmapped, previous chunk has OK offset */ - assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); - if (is_mmapped(p)) - do_check_mmapped_chunk(m, p); -} - -/* Check properties of free chunks */ -static void do_check_free_chunk(mstate m, mchunkptr p) { - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); - mchunkptr next = chunk_plus_offset(p, sz); - do_check_any_chunk(m, p); - assert(!cinuse(p)); - assert(!next_pinuse(p)); - assert (!is_mmapped(p)); - if (p != m->dv && p != m->top) { - if (sz >= MIN_CHUNK_SIZE) { - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(is_aligned(chunk2mem(p))); - assert(next->prev_foot == sz); - assert(pinuse(p)); - assert (next == m->top || cinuse(next)); - assert(p->fd->bk == p); - assert(p->bk->fd == p); - } - else /* markers are always of size SIZE_T_SIZE */ - assert(sz == SIZE_T_SIZE); - } -} - -/* Check properties of malloced chunks at the point they are malloced */ -static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); - do_check_inuse_chunk(m, p); - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(sz >= MIN_CHUNK_SIZE); - assert(sz >= s); - /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ - assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); - } -} - -/* Check a tree and its subtrees. */ -static void do_check_tree(mstate m, tchunkptr t) { - tchunkptr head = 0; - tchunkptr u = t; - bindex_t tindex = t->index; - size_t tsize = chunksize(t); - bindex_t idx; - compute_tree_index(tsize, idx); - assert(tindex == idx); - assert(tsize >= MIN_LARGE_SIZE); - assert(tsize >= minsize_for_tree_index(idx)); - assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); - - do { /* traverse through chain of same-sized nodes */ - do_check_any_chunk(m, ((mchunkptr)u)); - assert(u->index == tindex); - assert(chunksize(u) == tsize); - assert(!cinuse(u)); - assert(!next_pinuse(u)); - assert(u->fd->bk == u); - assert(u->bk->fd == u); - if (u->parent == 0) { - assert(u->child[0] == 0); - assert(u->child[1] == 0); - } - else { - assert(head == 0); /* only one node on chain has parent */ - head = u; - assert(u->parent != u); - assert (u->parent->child[0] == u || - u->parent->child[1] == u || - *((tbinptr*)(u->parent)) == u); - if (u->child[0] != 0) { - assert(u->child[0]->parent == u); - assert(u->child[0] != u); - do_check_tree(m, u->child[0]); - } - if (u->child[1] != 0) { - assert(u->child[1]->parent == u); - assert(u->child[1] != u); - do_check_tree(m, u->child[1]); - } - if (u->child[0] != 0 && u->child[1] != 0) { - assert(chunksize(u->child[0]) < chunksize(u->child[1])); - } - } - u = u->fd; - } while (u != t); - assert(head != 0); -} - -/* Check all the chunks in a treebin. */ -static void do_check_treebin(mstate m, bindex_t i) { - tbinptr* tb = treebin_at(m, i); - tchunkptr t = *tb; - int empty = (m->treemap & (1U << i)) == 0; - if (t == 0) - assert(empty); - if (!empty) - do_check_tree(m, t); -} - -/* Check all the chunks in a smallbin. */ -static void do_check_smallbin(mstate m, bindex_t i) { - sbinptr b = smallbin_at(m, i); - mchunkptr p = b->bk; - unsigned int empty = (m->smallmap & (1U << i)) == 0; - if (p == b) - assert(empty); - if (!empty) { - for (; p != b; p = p->bk) { - size_t size = chunksize(p); - mchunkptr q; - /* each chunk claims to be free */ - do_check_free_chunk(m, p); - /* chunk belongs in bin */ - assert(small_index(size) == i); - assert(p->bk == b || chunksize(p->bk) == chunksize(p)); - /* chunk is followed by an inuse chunk */ - q = next_chunk(p); - if (q->head != FENCEPOST_HEAD) - do_check_inuse_chunk(m, q); - } - } -} - -/* Find x in a bin. Used in other check functions. */ -static int bin_find(mstate m, mchunkptr x) { - size_t size = chunksize(x); - if (is_small(size)) { - bindex_t sidx = small_index(size); - sbinptr b = smallbin_at(m, sidx); - if (smallmap_is_marked(m, sidx)) { - mchunkptr p = b; - do { - if (p == x) - return 1; - } while ((p = p->fd) != b); - } - } - else { - bindex_t tidx; - compute_tree_index(size, tidx); - if (treemap_is_marked(m, tidx)) { - tchunkptr t = *treebin_at(m, tidx); - size_t sizebits = size << leftshift_for_tree_index(tidx); - while (t != 0 && chunksize(t) != size) { - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - sizebits <<= 1; - } - if (t != 0) { - tchunkptr u = t; - do { - if (u == (tchunkptr)x) - return 1; - } while ((u = u->fd) != t); - } - } - } - return 0; -} - -/* Traverse each chunk and check it; return total */ -static size_t traverse_and_check(mstate m) { - size_t sum = 0; - if (is_initialized(m)) { - msegmentptr s = &m->seg; - sum += m->topsize + TOP_FOOT_SIZE; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - mchunkptr lastq = 0; - assert(pinuse(q)); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - sum += chunksize(q); - if (cinuse(q)) { - assert(!bin_find(m, q)); - do_check_inuse_chunk(m, q); - } - else { - assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */ - do_check_free_chunk(m, q); - } - lastq = q; - q = next_chunk(q); - } - s = s->next; - } - } - return sum; -} - -/* Check all properties of malloc_state. */ -static void do_check_malloc_state(mstate m) { - bindex_t i; - size_t total; - /* check bins */ - for (i = 0; i < NSMALLBINS; ++i) - do_check_smallbin(m, i); - for (i = 0; i < NTREEBINS; ++i) - do_check_treebin(m, i); - - if (m->dvsize != 0) { /* check dv chunk */ - do_check_any_chunk(m, m->dv); - assert(m->dvsize == chunksize(m->dv)); - assert(m->dvsize >= MIN_CHUNK_SIZE); - assert(bin_find(m, m->dv) == 0); - } - - if (m->top != 0) { /* check top chunk */ - do_check_top_chunk(m, m->top); - assert(m->topsize == chunksize(m->top)); - assert(m->topsize > 0); - assert(bin_find(m, m->top) == 0); - } - - total = traverse_and_check(m); - assert(total <= m->footprint); - assert(m->footprint <= m->max_footprint); -} -#endif /* DEBUG */ - -/* ----------------------------- statistics ------------------------------ */ - -#if !NO_MALLINFO -static struct mallinfo internal_mallinfo(mstate m) { - struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (!PREACTION(m)) { - check_malloc_state(m); - if (is_initialized(m)) { - size_t nfree = SIZE_T_ONE; /* top always free */ - size_t mfree = m->topsize + TOP_FOOT_SIZE; - size_t sum = mfree; - msegmentptr s = &m->seg; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - size_t sz = chunksize(q); - sum += sz; - if (!cinuse(q)) { - mfree += sz; - ++nfree; - } - q = next_chunk(q); - } - s = s->next; - } - - nm.arena = sum; - nm.ordblks = nfree; - nm.hblkhd = m->footprint - sum; - nm.usmblks = m->max_footprint; - nm.uordblks = m->footprint - mfree; - nm.fordblks = mfree; - nm.keepcost = m->topsize; - } - - POSTACTION(m); - } - return nm; -} -#endif /* !NO_MALLINFO */ - -static void internal_malloc_stats(mstate m) { - if (!PREACTION(m)) { - size_t maxfp = 0; - size_t fp = 0; - size_t used = 0; - check_malloc_state(m); - if (is_initialized(m)) { - msegmentptr s = &m->seg; - maxfp = m->max_footprint; - fp = m->footprint; - used = fp - (m->topsize + TOP_FOOT_SIZE); - - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - if (!cinuse(q)) - used -= chunksize(q); - q = next_chunk(q); - } - s = s->next; - } - } - - fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); - fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); - fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - - POSTACTION(m); - } -} - -/* ----------------------- Operations on smallbins ----------------------- */ - -/* - Various forms of linking and unlinking are defined as macros. Even - the ones for trees, which are very long but have very short typical - paths. This is ugly but reduces reliance on inlining support of - compilers. -*/ - -/* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) {\ - bindex_t I = small_index(S);\ - mchunkptr B = smallbin_at(M, I);\ - mchunkptr F = B;\ - assert(S >= MIN_CHUNK_SIZE);\ - if (!smallmap_is_marked(M, I))\ - mark_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, B->fd)))\ - F = B->fd;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - B->fd = P;\ - F->bk = P;\ - P->fd = F;\ - P->bk = B;\ -} - -/* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) {\ - mchunkptr F = P->fd;\ - mchunkptr B = P->bk;\ - bindex_t I = small_index(S);\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (F == B)\ - clear_smallmap(M, I);\ - else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ - (B == smallbin_at(M,I) || ok_address(M, B)))) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) {\ - mchunkptr F = P->fd;\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (B == F)\ - clear_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, F))) {\ - B->fd = F;\ - F->bk = B;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Replace dv node, binning the old one */ -/* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) {\ - size_t DVS = M->dvsize;\ - if (DVS != 0) {\ - mchunkptr DV = M->dv;\ - assert(is_small(DVS));\ - insert_small_chunk(M, DV, DVS);\ - }\ - M->dvsize = S;\ - M->dv = P;\ -} - -/* ------------------------- Operations on trees ------------------------- */ - -/* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) {\ - tbinptr* H;\ - bindex_t I;\ - compute_tree_index(S, I);\ - H = treebin_at(M, I);\ - X->index = I;\ - X->child[0] = X->child[1] = 0;\ - if (!treemap_is_marked(M, I)) {\ - mark_treemap(M, I);\ - *H = X;\ - X->parent = (tchunkptr)H;\ - X->fd = X->bk = X;\ - }\ - else {\ - tchunkptr T = *H;\ - size_t K = S << leftshift_for_tree_index(I);\ - for (;;) {\ - if (chunksize(T) != S) {\ - tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ - K <<= 1;\ - if (*C != 0)\ - T = *C;\ - else if (RTCHECK(ok_address(M, C))) {\ - *C = X;\ - X->parent = T;\ - X->fd = X->bk = X;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - else {\ - tchunkptr F = T->fd;\ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ - T->fd = F->bk = X;\ - X->fd = F;\ - X->bk = T;\ - X->parent = 0;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - }\ - }\ -} - -/* - Unlink steps: - - 1. If x is a chained node, unlink it from its same-sized fd/bk links - and choose its bk node as its replacement. - 2. If x was the last node of its size, but not a leaf node, it must - be replaced with a leaf node (not merely one with an open left or - right), to make sure that lefts and rights of descendants - correspond properly to bit masks. We use the rightmost descendant - of x. We could use any other leaf, but this is easy to locate and - tends to counteract removal of leftmosts elsewhere, and so keeps - paths shorter than minimally guaranteed. This doesn't loop much - because on average a node in a tree is near the bottom. - 3. If x is the base of a chain (i.e., has parent links) relink - x's parent and children to x's replacement (or null if none). -*/ - -#define unlink_large_chunk(M, X) {\ - tchunkptr XP = X->parent;\ - tchunkptr R;\ - if (X->bk != X) {\ - tchunkptr F = X->fd;\ - R = X->bk;\ - if (RTCHECK(ok_address(M, F))) {\ - F->bk = R;\ - R->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - tchunkptr* RP;\ - if (((R = *(RP = &(X->child[1]))) != 0) ||\ - ((R = *(RP = &(X->child[0]))) != 0)) {\ - tchunkptr* CP;\ - while ((*(CP = &(R->child[1])) != 0) ||\ - (*(CP = &(R->child[0])) != 0)) {\ - R = *(RP = CP);\ - }\ - if (RTCHECK(ok_address(M, RP)))\ - *RP = 0;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - }\ - if (XP != 0) {\ - tbinptr* H = treebin_at(M, X->index);\ - if (X == *H) {\ - if ((*H = R) == 0) \ - clear_treemap(M, X->index);\ - }\ - else if (RTCHECK(ok_address(M, XP))) {\ - if (XP->child[0] == X) \ - XP->child[0] = R;\ - else \ - XP->child[1] = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - if (R != 0) {\ - if (RTCHECK(ok_address(M, R))) {\ - tchunkptr C0, C1;\ - R->parent = XP;\ - if ((C0 = X->child[0]) != 0) {\ - if (RTCHECK(ok_address(M, C0))) {\ - R->child[0] = C0;\ - C0->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - if ((C1 = X->child[1]) != 0) {\ - if (RTCHECK(ok_address(M, C1))) {\ - R->child[1] = C1;\ - C1->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ -} - -/* Relays to large vs small bin operations */ - -#define insert_chunk(M, P, S)\ - if (is_small(S)) insert_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } - -#define unlink_chunk(M, P, S)\ - if (is_small(S)) unlink_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } - - -/* Relays to internal calls to malloc/free from realloc, memalign etc */ - -#if ONLY_MSPACES -#define internal_malloc(m, b) mspace_malloc(m, b) -#define internal_free(m, mem) mspace_free(m,mem); -#else /* ONLY_MSPACES */ -#if MSPACES -#define internal_malloc(m, b)\ - (m == gm)? dlmalloc(b) : mspace_malloc(m, b) -#define internal_free(m, mem)\ - if (m == gm) dlfree(mem); else mspace_free(m,mem); -#else /* MSPACES */ -#define internal_malloc(m, b) dlmalloc(b) -#define internal_free(m, mem) dlfree(mem) -#endif /* MSPACES */ -#endif /* ONLY_MSPACES */ - -/* ----------------------- Direct-mmapping chunks ----------------------- */ - -/* - Directly mmapped chunks are set up with an offset to the start of - the mmapped region stored in the prev_foot field of the chunk. This - allows reconstruction of the required argument to MUNMAP when freed, - and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). There is also enough space - allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain - the PINUSE bit so frees can be checked. -*/ - -/* Malloc using mmap */ -static void* mmap_alloc(mstate m, size_t nb) { - size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - if (mmsize > nb) { /* Check for wrap around 0 */ - char* mm = (char*)(DIRECT_MMAP(mmsize)); - if (mm != CMFAIL) { - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; - mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset | IS_MMAPPED_BIT; - (p)->head = (psize|CINUSE_BIT); - mark_inuse_foot(m, p, psize); - chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - - if (mm < m->least_addr) - m->least_addr = mm; - if ((m->footprint += mmsize) > m->max_footprint) - m->max_footprint = m->footprint; - assert(is_aligned(chunk2mem(p))); - check_mmapped_chunk(m, p); - return chunk2mem(p); - } - } - return 0; -} - -/* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { - size_t oldsize = chunksize(oldp); - if (is_small(nb)) /* Can't shrink mmap regions below small size */ - return 0; - /* Keep old chunk if big enough but not too big */ - if (oldsize >= nb + SIZE_T_SIZE && - (oldsize - nb) <= (mparams.granularity << 1)) - return oldp; - else { - size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT; - size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES + - CHUNK_ALIGN_MASK); - char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, 1); - if (cp != CMFAIL) { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = (psize|CINUSE_BIT); - mark_inuse_foot(m, newp, psize); - chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - - if (cp < m->least_addr) - m->least_addr = cp; - if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) - m->max_footprint = m->footprint; - check_mmapped_chunk(m, newp); - return newp; - } - } - return 0; -} - -/* -------------------------- mspace management -------------------------- */ - -/* Initialize top chunk and its size */ -static void init_top(mstate m, mchunkptr p, size_t psize) { - /* Ensure alignment */ - size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char*)p + offset); - psize -= offset; - - m->top = p; - m->topsize = psize; - p->head = psize | PINUSE_BIT; - /* set size of fake trailing chunk holding overhead space only once */ - chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ -} - -/* Initialize bins for a new mstate that is otherwise zeroed out */ -static void init_bins(mstate m) { - /* Establish circular links for smallbins */ - bindex_t i; - for (i = 0; i < NSMALLBINS; ++i) { - sbinptr bin = smallbin_at(m,i); - bin->fd = bin->bk = bin; - } -} - -#if PROCEED_ON_ERROR - -/* default corruption action */ -static void reset_on_error(mstate m) { - int i; - ++malloc_corruption_error_count; - /* Reinitialize fields to forget about all memory */ - m->smallbins = m->treebins = 0; - m->dvsize = m->topsize = 0; - m->seg.base = 0; - m->seg.size = 0; - m->seg.next = 0; - m->top = m->dv = 0; - for (i = 0; i < NTREEBINS; ++i) - *treebin_at(m, i) = 0; - init_bins(m); -} -#endif /* PROCEED_ON_ERROR */ - -/* Allocate chunk and prepend remainder with chunk in successor base. */ -static void* prepend_alloc(mstate m, char* newbase, char* oldbase, - size_t nb) { - mchunkptr p = align_as_chunk(newbase); - mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char*)oldfirst - (char*)p; - mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - - assert((char*)oldfirst > (char*)q); - assert(pinuse(oldfirst)); - assert(qsize >= MIN_CHUNK_SIZE); - - /* consolidate remainder with first chunk of old base */ - if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; - m->top = q; - q->head = tsize | PINUSE_BIT; - check_top_chunk(m, q); - } - else if (oldfirst == m->dv) { - size_t dsize = m->dvsize += qsize; - m->dv = q; - set_size_and_pinuse_of_free_chunk(q, dsize); - } - else { - if (!cinuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); - unlink_chunk(m, oldfirst, nsize); - oldfirst = chunk_plus_offset(oldfirst, nsize); - qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); - insert_chunk(m, q, qsize); - check_free_chunk(m, q); - } - - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); -} - - -/* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { - /* Determine locations and sizes of segment, fenceposts, old top */ - char* old_top = (char*)m->top; - msegmentptr oldsp = segment_holding(m, old_top); - char* old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char* asp = rawsp + offset; - char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; - mchunkptr sp = (mchunkptr)csp; - msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; - - /* reset top to new space */ - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - - /* Set up segment record */ - assert(is_aligned(ss)); - set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ - m->seg.base = tbase; - m->seg.size = tsize; - (void)set_segment_flags(&m->seg, mmapped); - m->seg.next = ss; - - /* Insert trailing fenceposts */ - for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); - p->head = FENCEPOST_HEAD; - ++nfences; - if ((char*)(&(nextp->head)) < old_end) - p = nextp; - else - break; - } - assert(nfences >= 2); - - /* Insert the rest of old top into a bin as an ordinary free chunk */ - if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; - mchunkptr tn = chunk_plus_offset(q, psize); - set_free_with_pinuse(q, psize, tn); - insert_chunk(m, q, psize); - } - - check_top_chunk(m, m->top); -} - -/* -------------------------- System allocation -------------------------- */ - -/* Get memory from system using MORECORE or MMAP */ -static void* sys_alloc(mstate m, size_t nb) { - char* tbase = CMFAIL; - size_t tsize = 0; - flag_t mmap_flag = 0; - - init_mparams(); - - /* Directly map large chunks */ - if (use_mmap(m) && nb >= mparams.mmap_threshold) { - void* mem = mmap_alloc(m, nb); - if (mem != 0) - return mem; - } - - /* - Try getting memory in any of three ways (in most-preferred to - least-preferred order): - 1. A call to MORECORE that can normally contiguously extend memory. - (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) - 2. A call to MMAP new space (disabled if not HAVE_MMAP). - Note that under the default settings, if MORECORE is unable to - fulfill a request, and HAVE_MMAP is true, then mmap is - used as a noncontiguous system allocator. This is a useful backup - strategy for systems with holes in address spaces -- in this case - sbrk cannot contiguously expand the heap, but mmap may be able to - find space. - 3. A call to MORECORE that cannot usually contiguously extend memory. - (disabled if not HAVE_MORECORE) - */ - - if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { - char* br = CMFAIL; - msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); - size_t asize = 0; - ACQUIRE_MORECORE_LOCK(); - - if (ss == 0) { /* First time through or recovery */ - char* base = (char*)CALL_MORECORE(0); - if (base != CMFAIL) { - asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); - /* Adjust to end on a page boundary */ - if (!is_page_aligned(base)) - asize += (page_align((size_t)base) - (size_t)base); - /* Can't call MORECORE if size is negative when treated as signed */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == base) { - tbase = base; - tsize = asize; - } - } - } - else { - /* Subtract out existing available top space from MORECORE request. */ - asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE); - /* Use mem here only if it did continuously extend old space */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { - tbase = br; - tsize = asize; - } - } - - if (tbase == CMFAIL) { /* Cope with partial failure */ - if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (asize < HALF_MAX_SIZE_T && - asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) { - size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize); - if (esize < HALF_MAX_SIZE_T) { - char* end = (char*)CALL_MORECORE(esize); - if (end != CMFAIL) - asize += esize; - else { /* Can't use; try to release */ - (void)CALL_MORECORE(-asize); - br = CMFAIL; - } - } - } - } - if (br != CMFAIL) { /* Use the space we did get */ - tbase = br; - tsize = asize; - } - else - disable_contiguous(m); /* Don't try contiguous path in the future */ - } - - RELEASE_MORECORE_LOCK(); - } - - if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; - size_t rsize = granularity_align(req); - if (rsize > nb) { /* Fail if wraps around zero */ - char* mp = (char*)(CALL_MMAP(rsize)); - if (mp != CMFAIL) { - tbase = mp; - tsize = rsize; - mmap_flag = IS_MMAPPED_BIT; - } - } - } - - if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ - size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); - if (asize < HALF_MAX_SIZE_T) { - char* br = CMFAIL; - char* end = CMFAIL; - ACQUIRE_MORECORE_LOCK(); - br = (char*)(CALL_MORECORE(asize)); - end = (char*)(CALL_MORECORE(0)); - RELEASE_MORECORE_LOCK(); - if (br != CMFAIL && end != CMFAIL && br < end) { - size_t ssize = end - br; - if (ssize > nb + TOP_FOOT_SIZE) { - tbase = br; - tsize = ssize; - } - } - } - } - - if (tbase != CMFAIL) { - - if ((m->footprint += tsize) > m->max_footprint) - m->max_footprint = m->footprint; - - if (!is_initialized(m)) { /* first-time initialization */ - m->seg.base = m->least_addr = tbase; - m->seg.size = tsize; - (void)set_segment_flags(&m->seg, mmap_flag); - m->magic = mparams.magic; - init_bins(m); - if (is_global(m)) - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else { - /* Offset top by embedded malloc_state */ - mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); - } - } - - else { - /* Try to merge with an existing segment */ - msegmentptr sp = &m->seg; - while (sp != 0 && tbase != sp->base + sp->size) - sp = sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - check_segment_merge(sp, tbase, tsize) && - (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag && - segment_holds(sp, m->top)) { /* append */ - sp->size += tsize; - init_top(m, m->top, m->topsize + tsize); - } - else { - if (tbase < m->least_addr) - m->least_addr = tbase; - sp = &m->seg; - while (sp != 0 && sp->base != tbase + tsize) - sp = sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - check_segment_merge(sp, tbase, tsize) && - (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag) { - char* oldbase = sp->base; - sp->base = tbase; - sp->size += tsize; - return prepend_alloc(m, tbase, oldbase, nb); - } - else - add_segment(m, tbase, tsize, mmap_flag); - } - } - - if (nb < m->topsize) { /* Allocate from new or extended top space */ - size_t rsize = m->topsize -= nb; - mchunkptr p = m->top; - mchunkptr r = m->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - check_top_chunk(m, m->top); - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); - } - } - - MALLOC_FAILURE_ACTION; - return 0; -} - -/* ----------------------- system deallocation -------------------------- */ - -/* Unmap and unlink any mmapped segments that don't contain used chunks */ -static size_t release_unused_segments(mstate m) { - size_t released = 0; - msegmentptr pred = &m->seg; - msegmentptr sp = pred->next; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - msegmentptr next = sp->next; - if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); - /* Can unmap if first chunk holds entire segment and not pinned */ - if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { - tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char*)sp)); - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - else { - unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) { - released += size; - m->footprint -= size; - /* unlink obsoleted record */ - sp = pred; - sp->next = next; - } - else { /* back out if cannot unmap */ - insert_large_chunk(m, tp, psize); - } - } - } - pred = sp; - sp = next; - } - return released; -} - -static int sys_trim(mstate m, size_t pad) { - size_t released = 0; - if (pad < MAX_REQUEST && is_initialized(m)) { - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ - - if (m->topsize > pad) { - /* Shrink top space in granularity-size units, keeping at least one */ - size_t unit = mparams.granularity; - size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char*)m->top); - - if (!is_extern_segment(sp)) { - if (is_mmapped_segment(sp)) { - if (HAVE_MMAP && - sp->size >= extra && - !has_segment_link(m, sp)) { /* can't shrink if pinned */ - size_t newsize = sp->size - extra; - /* Prefer mremap, fall back to munmap */ - if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || - (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { - released = extra; - } - } - } - else if (HAVE_MORECORE) { - if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ - extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; - ACQUIRE_MORECORE_LOCK(); - { - /* Make sure end of memory is where we last set it. */ - char* old_br = (char*)(CALL_MORECORE(0)); - if (old_br == sp->base + sp->size) { - char* rel_br = (char*)(CALL_MORECORE(-extra)); - char* new_br = (char*)(CALL_MORECORE(0)); - if (rel_br != CMFAIL && new_br < old_br) - released = old_br - new_br; - } - } - RELEASE_MORECORE_LOCK(); - } - } - - if (released != 0) { - sp->size -= released; - m->footprint -= released; - init_top(m, m->top, m->topsize - released); - check_top_chunk(m, m->top); - } - } - - /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) - released += release_unused_segments(m); - - /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0) - m->trim_check = MAX_SIZE_T; - } - - return (released != 0)? 1 : 0; -} - -/* ---------------------------- malloc support --------------------------- */ - -/* allocate a large request from the best fitting chunk in a treebin */ -static void* tmalloc_large(mstate m, size_t nb) { - tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ - tchunkptr t; - bindex_t idx; - compute_tree_index(nb, idx); - - if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ - for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) - break; - } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) - rst = rt; - if (t == 0) { - t = rst; /* set t to least subtree holding sizes > nb */ - break; - } - sizebits <<= 1; - } - } - - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ - binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; - if (leftbits != 0) { - bindex_t i; - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - t = *treebin_at(m, i); - } - } - - while (t != 0) { /* find smallest of tree or subtree */ - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - t = leftmost_child(t); - } - - /* If dv is a better fit, return 0 so malloc will use it */ - if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - if (RTCHECK(ok_address(m, v))) { /* split */ - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; -} - -/* allocate a small request from the best fitting chunk in a treebin */ -static void* tmalloc_small(mstate m, size_t nb) { - tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); - compute_bit2idx(leastbit, i); - - v = t = *treebin_at(m, i); - rsize = chunksize(t) - nb; - - while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - } - - if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } - - CORRUPTION_ERROR_ACTION(m); - return 0; -} - -/* --------------------------- realloc support --------------------------- */ - -static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - return 0; - } - if (!PREACTION(m)) { - mchunkptr oldp = mem2chunk(oldmem); - size_t oldsize = chunksize(oldp); - mchunkptr next = chunk_plus_offset(oldp, oldsize); - mchunkptr newp = 0; - void* extra = 0; - - /* Try to either shrink or extend into top. Else malloc-copy-free */ - - if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && - ok_next(oldp, next) && ok_pinuse(next))) { - size_t nb = request2size(bytes); - if (is_mmapped(oldp)) - newp = mmap_resize(m, oldp, nb); - else if (oldsize >= nb) { /* already big enough */ - size_t rsize = oldsize - nb; - newp = oldp; - if (rsize >= MIN_CHUNK_SIZE) { - mchunkptr remainder = chunk_plus_offset(newp, nb); - set_inuse(m, newp, nb); - set_inuse(m, remainder, rsize); - extra = chunk2mem(remainder); - } - } - else if (next == m->top && oldsize + m->topsize > nb) { - /* Expand into top */ - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; - mchunkptr newtop = chunk_plus_offset(oldp, nb); - set_inuse(m, oldp, nb); - newtop->head = newtopsize |PINUSE_BIT; - m->top = newtop; - m->topsize = newtopsize; - newp = oldp; - } - } - else { - USAGE_ERROR_ACTION(m, oldmem); - POSTACTION(m); - return 0; - } - - POSTACTION(m); - - if (newp != 0) { - if (extra != 0) { - internal_free(m, extra); - } - check_inuse_chunk(m, newp); - return chunk2mem(newp); - } - else { - void* newmem = internal_malloc(m, bytes); - if (newmem != 0) { - size_t oc = oldsize - overhead_for(oldp); - memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); - internal_free(m, oldmem); - } - return newmem; - } - } - return 0; -} - -/* --------------------------- memalign support -------------------------- */ - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ - return internal_malloc(m, bytes); - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - MALLOC_FAILURE_ACTION; - } - } - else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - char* mem = (char*)internal_malloc(m, req); - if (mem != 0) { - void* leader = 0; - void* trailer = 0; - mchunkptr p = mem2chunk(mem); - - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)(mem + - alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = (newsize|CINUSE_BIT); - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - leader = chunk2mem(p); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - trailer = chunk2mem(remainder); - } - } - - assert (chunksize(p) >= nb); - assert((((size_t)(chunk2mem(p))) % alignment) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - if (leader != 0) { - internal_free(m, leader); - } - if (trailer != 0) { - internal_free(m, trailer); - } - return chunk2mem(p); - } - } - return 0; -} - -/* ------------------------ comalloc/coalloc support --------------------- */ - -static void** ialloc(mstate m, - size_t n_elements, - size_t* sizes, - int opts, - void* chunks[]) { - /* - This provides common support for independent_X routines, handling - all of the combinations that can result. - - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed - */ - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void* mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ - size_t size; - size_t i; - - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) - return chunks; /* nothing to do */ - marray = chunks; - array_size = 0; - } - else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) - return (void**)internal_malloc(m, 0); - marray = 0; - array_size = request2size(n_elements * (sizeof(void*))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } - else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) - contents_size += request2size(sizes[i]); - } - - size = contents_size + array_size; - - /* - Allocate the aggregate chunk. First disable direct-mmapping so - malloc won't use it, since we would not be able to later - free/realloc space internal to a segregated mmap region. - */ - was_enabled = use_mmap(m); - disable_mmap(m); - mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) - enable_mmap(m); - if (mem == 0) - return 0; - - if (PREACTION(m)) return 0; - p = mem2chunk(mem); - remainder_size = chunksize(p); - - assert(!is_mmapped(p)); - - if (opts & 0x2) { /* optionally clear the elements */ - memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - size_t array_chunk_size; - array_chunk = chunk_plus_offset(p, contents_size); - array_chunk_size = remainder_size - contents_size; - marray = (void**) (chunk2mem(array_chunk)); - set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0; ; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements-1) { - if (element_size != 0) - size = element_size; - else - size = request2size(sizes[i]); - remainder_size -= size; - set_size_and_pinuse_of_inuse_chunk(m, p, size); - p = chunk_plus_offset(p, size); - } - else { /* the final element absorbs any overallocation slop */ - set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); - break; - } - } - -#if DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } - else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) - check_inuse_chunk(m, mem2chunk(marray[i])); - -#endif /* DEBUG */ - - POSTACTION(m); - return marray; -} - - -/* -------------------------- public routines ---------------------------- */ - -#if !ONLY_MSPACES - -void* dlmalloc(size_t bytes) { - /* - Basic algorithm: - If a small request (< 256 bytes minus per-chunk overhead): - 1. If one exists, use a remainderless chunk in associated smallbin. - (Remainderless means that there are too few excess bytes to - represent as a chunk.) - 2. If it is big enough, use the dv chunk, which is normally the - chunk adjacent to the one used for the most recent small request. - 3. If one exists, split the smallest available chunk in a bin, - saving remainder in dv. - 4. If it is big enough, use the top chunk. - 5. If available, get memory from system and use it - Otherwise, for a large request: - 1. Find the smallest available binned chunk that fits, and use it - if it is better fitting than dv chunk, splitting if necessary. - 2. If better fitting than any binned chunk, use the dv chunk. - 3. If it is big enough, use the top chunk. - 4. If request size >= mmap threshold, try to directly mmap this chunk. - 5. If available, get memory from system and use it - - The ugly goto's here ensure that postaction occurs along all paths. - */ - - if (!PREACTION(gm)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = gm->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(gm, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(gm, b, p, idx); - set_inuse_and_pinuse(gm, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb > gm->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(gm, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(gm, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(gm, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - - if (nb <= gm->dvsize) { - size_t rsize = gm->dvsize - nb; - mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = gm->dv = chunk_plus_offset(p, nb); - gm->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - } - else { /* exhaust dv */ - size_t dvs = gm->dvsize; - gm->dvsize = 0; - gm->dv = 0; - set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; - mchunkptr p = gm->top; - mchunkptr r = gm->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - mem = chunk2mem(p); - check_top_chunk(gm, gm->top); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - mem = sys_alloc(gm, nb); - - postaction: - POSTACTION(gm); - return mem; - } - - return 0; -} - -void dlfree(void* mem) { - /* - Consolidate freed chunks with preceding or succeeding bordering - free chunks, if they exist, and then place in a bin. Intermixed - with special cases for top, dv, mmapped chunks, and usage errors. - */ - - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } -#else /* FOOTERS */ -#define fm gm -#endif /* FOOTERS */ - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -#if !FOOTERS -#undef fm -#endif /* FOOTERS */ -} - -void* dlcalloc(size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = dlmalloc(req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* dlrealloc(void* oldmem, size_t bytes) { - if (oldmem == 0) - return dlmalloc(bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - dlfree(oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if ! FOOTERS - mstate m = gm; -#else /* FOOTERS */ - mstate m = get_mstate_for(mem2chunk(oldmem)); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - return internal_realloc(m, oldmem, bytes); - } -} - -void* dlmemalign(size_t alignment, size_t bytes) { - return internal_memalign(gm, alignment, bytes); -} - -void** dlindependent_calloc(size_t n_elements, size_t elem_size, - void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - return ialloc(gm, n_elements, &sz, 3, chunks); -} - -void** dlindependent_comalloc(size_t n_elements, size_t sizes[], - void* chunks[]) { - return ialloc(gm, n_elements, sizes, 0, chunks); -} - -void* dlvalloc(size_t bytes) { - size_t pagesz; - init_mparams(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, bytes); -} - -void* dlpvalloc(size_t bytes) { - size_t pagesz; - init_mparams(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); -} - -int dlmalloc_trim(size_t pad) { - int result = 0; - if (!PREACTION(gm)) { - result = sys_trim(gm, pad); - POSTACTION(gm); - } - return result; -} - -size_t dlmalloc_footprint(void) { - return gm->footprint; -} - -size_t dlmalloc_max_footprint(void) { - return gm->max_footprint; -} - -#if !NO_MALLINFO -struct mallinfo dlmallinfo(void) { - return internal_mallinfo(gm); -} -#endif /* NO_MALLINFO */ - -void dlmalloc_stats() { - internal_malloc_stats(gm); -} - -size_t dlmalloc_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (cinuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* !ONLY_MSPACES */ - -/* ----------------------------- user mspaces ---------------------------- */ - -#if MSPACES - -static mstate init_user_mstate(char* tbase, size_t tsize) { - size_t msize = pad_request(sizeof(struct malloc_state)); - mchunkptr mn; - mchunkptr msp = align_as_chunk(tbase); - mstate m = (mstate)(chunk2mem(msp)); - memset(m, 0, msize); - INITIAL_LOCK(&m->mutex); - msp->head = (msize|PINUSE_BIT|CINUSE_BIT); - m->seg.base = m->least_addr = tbase; - m->seg.size = m->footprint = m->max_footprint = tsize; - m->magic = mparams.magic; - m->mflags = mparams.default_mflags; - disable_contiguous(m); - init_bins(m); - mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); - check_top_chunk(m, m->top); - return m; -} - -mspace create_mspace(size_t capacity, int locked) { - mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - - if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - size_t rs = ((capacity == 0)? mparams.granularity : - (capacity + TOP_FOOT_SIZE + msize)); - size_t tsize = granularity_align(rs); - char* tbase = (char*)(CALL_MMAP(tsize)); - if (tbase != CMFAIL) { - m = init_user_mstate(tbase, tsize); - set_segment_flags(&m->seg, IS_MMAPPED_BIT); - set_lock(m, locked); - } - } - return (mspace)m; -} - -mspace create_mspace_with_base(void* base, size_t capacity, int locked) { - mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - - if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - m = init_user_mstate((char*)base, capacity); - set_segment_flags(&m->seg, EXTERN_BIT); - set_lock(m, locked); - } - return (mspace)m; -} - -size_t destroy_mspace(mspace msp) { - size_t freed = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - msegmentptr sp = &ms->seg; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - flag_t flag = get_segment_flags(sp); - sp = sp->next; - if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) && - CALL_MUNMAP(base, size) == 0) - freed += size; - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return freed; -} - -/* - mspace versions of routines are near-clones of the global - versions. This is not so nice but better than the alternatives. -*/ - - -void* mspace_malloc(mspace msp, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (!PREACTION(ms)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = ms->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(ms, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(ms, b, p, idx); - set_inuse_and_pinuse(ms, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb > ms->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(ms, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(ms, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(ms, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(ms, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - - if (nb <= ms->dvsize) { - size_t rsize = ms->dvsize - nb; - mchunkptr p = ms->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = ms->dv = chunk_plus_offset(p, nb); - ms->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - } - else { /* exhaust dv */ - size_t dvs = ms->dvsize; - ms->dvsize = 0; - ms->dv = 0; - set_inuse_and_pinuse(ms, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb < ms->topsize) { /* Split top */ - size_t rsize = ms->topsize -= nb; - mchunkptr p = ms->top; - mchunkptr r = ms->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - mem = chunk2mem(p); - check_top_chunk(ms, ms->top); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - mem = sys_alloc(ms, nb); - - postaction: - POSTACTION(ms); - return mem; - } - - return 0; -} - -void mspace_free(mspace msp, void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); -#else /* FOOTERS */ - mstate fm = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -} - -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = internal_malloc(ms, req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { - if (oldmem == 0) - return mspace_malloc(msp, bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - mspace_free(msp, oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if FOOTERS - mchunkptr p = mem2chunk(oldmem); - mstate ms = get_mstate_for(p); -#else /* FOOTERS */ - mstate ms = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_realloc(ms, oldmem, bytes); - } -} - -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_memalign(ms, alignment, bytes); -} - -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, &sz, 3, chunks); -} - -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, sizes, 0, chunks); -} - -int mspace_trim(mspace msp, size_t pad) { - int result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (!PREACTION(ms)) { - result = sys_trim(ms, pad); - POSTACTION(ms); - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -void mspace_malloc_stats(mspace msp) { - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - internal_malloc_stats(ms); - } - else { - USAGE_ERROR_ACTION(ms,ms); - } -} - -size_t mspace_footprint(mspace msp) { - size_t result; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->footprint; - } - USAGE_ERROR_ACTION(ms,ms); - return result; -} - - -size_t mspace_max_footprint(mspace msp) { - size_t result; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->max_footprint; - } - USAGE_ERROR_ACTION(ms,ms); - return result; -} - - -#if !NO_MALLINFO -struct mallinfo mspace_mallinfo(mspace msp) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - } - return internal_mallinfo(ms); -} -#endif /* NO_MALLINFO */ - -int mspace_mallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* MSPACES */ - -/* -------------------- Alternative MORECORE functions ------------------- */ - -/* - Guidelines for creating a custom version of MORECORE: - - * For best performance, MORECORE should allocate in multiples of pagesize. - * MORECORE may allocate more memory than requested. (Or even less, - but this will usually result in a malloc failure.) - * MORECORE must not allocate memory when given argument zero, but - instead return one past the end address of memory from previous - nonzero call. - * For best performance, consecutive calls to MORECORE with positive - arguments should return increasing addresses, indicating that - space has been contiguously extended. - * Even though consecutive calls to MORECORE need not return contiguous - addresses, it must be OK for malloc'ed chunks to span multiple - regions in those cases where they do happen to be contiguous. - * MORECORE need not handle negative arguments -- it may instead - just return MFAIL when given negative arguments. - Negative arguments are always multiples of pagesize. MORECORE - must not misinterpret negative args as large positive unsigned - args. You can suppress all such calls from even occurring by defining - MORECORE_CANNOT_TRIM, - - As an example alternative MORECORE, here is a custom allocator - kindly contributed for pre-OSX macOS. It uses virtually but not - necessarily physically contiguous non-paged memory (locked in, - present and won't get swapped out). You can use it by uncommenting - this section, adding some #includes, and setting up the appropriate - defines above: - - #define MORECORE osMoreCore - - There is also a shutdown routine that should somehow be called for - cleanup upon program exit. - - #define MAX_POOL_ENTRIES 100 - #define MINIMUM_MORECORE_SIZE (64 * 1024U) - static int next_os_pool; - void *our_os_pools[MAX_POOL_ENTRIES]; - - void *osMoreCore(int size) - { - void *ptr = 0; - static void *sbrk_top = 0; - - if (size > 0) - { - if (size < MINIMUM_MORECORE_SIZE) - size = MINIMUM_MORECORE_SIZE; - if (CurrentExecutionLevel() == kTaskLevel) - ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); - if (ptr == 0) - { - return (void *) MFAIL; - } - // save ptrs so they can be freed during cleanup - our_os_pools[next_os_pool] = ptr; - next_os_pool++; - ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); - sbrk_top = (char *) ptr + size; - return ptr; - } - else if (size < 0) - { - // we don't currently support shrink behavior - return (void *) MFAIL; - } - else - { - return sbrk_top; - } - } - - // cleanup any allocated memory pools - // called as last thing before shutting down driver - - void osCleanupMem(void) - { - void **ptr; - - for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) - if (*ptr) - { - PoolDeallocate(*ptr); - *ptr = 0; - } - } - -*/ - - -/* ----------------------------------------------------------------------- -History: - V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) - * Add max_footprint functions - * Ensure all appropriate literals are size_t - * Fix conditional compilation problem for some #define settings - * Avoid concatenating segments with the one provided - in create_mspace_with_base - * Rename some variables to avoid compiler shadowing warnings - * Use explicit lock initialization. - * Better handling of sbrk interference. - * Simplify and fix segment insertion, trimming and mspace_destroy - * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x - * Thanks especially to Dennis Flanagan for help on these. - - V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) - * Fix memalign brace error. - - V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) - * Fix improper #endif nesting in C++ - * Add explicit casts needed for C++ - - V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) - * Use trees for large bins - * Support mspaces - * Use segments to unify sbrk-based and mmap-based system allocation, - removing need for emulation on most platforms without sbrk. - * Default safety checks - * Optional footer checks. Thanks to William Robertson for the idea. - * Internal code refactoring - * Incorporate suggestions and platform-specific changes. - Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, - Aaron Bachmann, Emery Berger, and others. - * Speed up non-fastbin processing enough to remove fastbins. - * Remove useless cfree() to avoid conflicts with other apps. - * Remove internal memcpy, memset. Compilers handle builtins better. - * Remove some options that no one ever used and rename others. - - V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - * Fix malloc_state bitmap array misdeclaration - - V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) - * Allow tuning of FIRST_SORTED_BIN_SIZE - * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. - * Better detection and support for non-contiguousness of MORECORE. - Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger - * Bypass most of malloc if no frees. Thanks To Emery Berger. - * Fix freeing of old top non-contiguous chunk im sysmalloc. - * Raised default trim and map thresholds to 256K. - * Fix mmap-related #defines. Thanks to Lubos Lunak. - * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. - * Branch-free bin calculation - * Default trim and mmap thresholds now 256K. - - V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) - * Introduce independent_comalloc and independent_calloc. - Thanks to Michael Pachos for motivation and help. - * Make optional .h file available - * Allow > 2GB requests on 32bit systems. - * new WIN32 sbrk, mmap, munmap, lock code from . - Thanks also to Andreas Mueller , - and Anonymous. - * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for - helping test this.) - * memalign: check alignment arg - * realloc: don't try to shift chunks backwards, since this - leads to more fragmentation in some programs and doesn't - seem to help in any others. - * Collect all cases in malloc requiring system memory into sysmalloc - * Use mmap as backup to sbrk - * Place all internal state in malloc_state - * Introduce fastbins (although similar to 2.5.1) - * Many minor tunings and cosmetic improvements - * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK - * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS - Thanks to Tony E. Bennett and others. - * Include errno.h to support default failure action. - - V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) - * return null for negative arguments - * Added Several WIN32 cleanups from Martin C. Fong - * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' - (e.g. WIN32 platforms) - * Cleanup header file inclusion for WIN32 platforms - * Cleanup code to avoid Microsoft Visual C++ compiler complaints - * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing - memory allocation routines - * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) - * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to - usage of 'assert' in non-WIN32 code - * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to - avoid infinite loop - * Always call 'fREe()' rather than 'free()' - - V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) - * Fixed ordering problem with boundary-stamping - - V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) - * Added pvalloc, as recommended by H.J. Liu - * Added 64bit pointer support mainly from Wolfram Gloger - * Added anonymously donated WIN32 sbrk emulation - * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen - * malloc_extend_top: fix mask error that caused wastage after - foreign sbrks - * Add linux mremap support code from HJ Liu - - V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) - * Integrated most documentation with the code. - * Add support for mmap, with help from - Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Use last_remainder in more cases. - * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshold - * Eliminate block-local decls to simplify tracing and debugging. - * Support another case of realloc via move into top - * Fix error occurring when initial sbrk_base not word-aligned. - * Rely on page size for units instead of SBRK_UNIT to - avoid surprises about sbrk alignment conventions. - * Add mallinfo, mallopt. Thanks to Raymond Nijssen - (raymond@es.ele.tue.nl) for the suggestion. - * Add `pad' argument to malloc_trim and top_pad mallopt parameter. - * More precautions for cases where other routines call sbrk, - courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Added macros etc., allowing use in linux libc from - H.J. Lu (hjl@gnu.ai.mit.edu) - * Inverted this history list - - V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) - * Re-tuned and fixed to behave more nicely with V2.6.0 changes. - * Removed all preallocation code since under current scheme - the work required to undo bad preallocations exceeds - the work saved in good cases for most test programs. - * No longer use return list or unconsolidated bins since - no scheme using them consistently outperforms those that don't - given above changes. - * Use best fit for very large chunks to prevent some worst-cases. - * Added some support for debugging - - V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) - * Removed footers when chunks are in use. Thanks to - Paul Wilson (wilson@cs.texas.edu) for the suggestion. - - V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) - * Added malloc_trim, with help from Wolfram Gloger - (wmglo@Dent.MED.Uni-Muenchen.DE). - - V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) - - V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) - * realloc: try to expand in both directions - * malloc: swap order of clean-bin strategy; - * realloc: only conditionally expand backwards - * Try not to scavenge used bins - * Use bin counts as a guide to preallocation - * Occasionally bin return list chunks in first scan - * Add a few optimizations from colin@nyx10.cs.du.edu - - V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) - * faster bin computation & slightly different binning - * merged all consolidations to one part of malloc proper - (eliminating old malloc_find_space & malloc_clean_bin) - * Scan 2 returns chunks (not just 1) - * Propagate failure in realloc if malloc returns 0 - * Add stuff to allow compilation on non-ANSI compilers - from kpv@research.att.com - - V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) - * removed potential for odd address access in prev_chunk - * removed dependency on getpagesize.h - * misc cosmetics and a bit more internal documentation - * anticosmetics: mangled names in macros to evade debugger strangeness - * tested on sparc, hp-700, dec-mips, rs6000 - with gcc & native cc (hp, dec only) allowing - Detlefs & Zorn comparison study (in SIGPLAN Notices.) - - Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) - * Based loosely on libg++-1.2X malloc. (It retains some of the overall - structure of old version, but most details differ.) - -*/ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/frv/eabi.S b/ruby/ext/fiddle/libffi-3.2.1/src/frv/eabi.S deleted file mode 100644 index 379ea4bb0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/frv/eabi.S +++ /dev/null @@ -1,128 +0,0 @@ -/* ----------------------------------------------------------------------- - eabi.S - Copyright (c) 2004 Anthony Green - - FR-V Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - .globl ffi_prep_args_EABI - - .text - .p2align 4 - .globl ffi_call_EABI - .type ffi_call_EABI, @function - - # gr8 : ffi_prep_args - # gr9 : &ecif - # gr10: cif->bytes - # gr11: fig->flags - # gr12: ecif.rvalue - # gr13: fn - -ffi_call_EABI: - addi sp, #-80, sp - sti fp, @(sp, #24) - addi sp, #24, fp - movsg lr, gr5 - - /* Make room for the new arguments. */ - /* subi sp, fp, gr10 */ - - /* Store return address and incoming args on stack. */ - sti gr5, @(fp, #8) - sti gr8, @(fp, #-4) - sti gr9, @(fp, #-8) - sti gr10, @(fp, #-12) - sti gr11, @(fp, #-16) - sti gr12, @(fp, #-20) - sti gr13, @(fp, #-24) - - sub sp, gr10, sp - - /* Call ffi_prep_args. */ - ldi @(fp, #-4), gr4 - addi sp, #0, gr8 - ldi @(fp, #-8), gr9 -#ifdef __FRV_FDPIC__ - ldd @(gr4, gr0), gr14 - calll @(gr14, gr0) -#else - calll @(gr4, gr0) -#endif - - /* ffi_prep_args returns the new stack pointer. */ - mov gr8, gr4 - - ldi @(sp, #0), gr8 - ldi @(sp, #4), gr9 - ldi @(sp, #8), gr10 - ldi @(sp, #12), gr11 - ldi @(sp, #16), gr12 - ldi @(sp, #20), gr13 - - /* Always copy the return value pointer into the hidden - parameter register. This is only strictly necessary - when we're returning an aggregate type, but it doesn't - hurt to do this all the time, and it saves a branch. */ - ldi @(fp, #-20), gr3 - - /* Use the ffi_prep_args return value for the new sp. */ - mov gr4, sp - - /* Call the target function. */ - ldi @(fp, -24), gr4 -#ifdef __FRV_FDPIC__ - ldd @(gr4, gr0), gr14 - calll @(gr14, gr0) -#else - calll @(gr4, gr0) -#endif - - /* Store the result. */ - ldi @(fp, #-16), gr10 /* fig->flags */ - ldi @(fp, #-20), gr4 /* ecif.rvalue */ - - /* Is the return value stored in two registers? */ - cmpi gr10, #8, icc0 - bne icc0, 0, .L2 - /* Yes, save them. */ - sti gr8, @(gr4, #0) - sti gr9, @(gr4, #4) - bra .L3 -.L2: - /* Is the return value a structure? */ - cmpi gr10, #-1, icc0 - beq icc0, 0, .L3 - /* No, save a 4 byte return value. */ - sti gr8, @(gr4, #0) -.L3: - - /* Restore the stack, and return. */ - ldi @(fp, 8), gr5 - ld @(fp, gr0), fp - addi sp,#80,sp - jmpl @(gr5,gr0) - .size ffi_call_EABI, .-ffi_call_EABI - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffi.c deleted file mode 100644 index 5698c89c3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffi.c +++ /dev/null @@ -1,292 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (C) 2004 Anthony Green - Copyright (C) 2007 Free Software Foundation, Inc. - Copyright (C) 2008 Red Hat, Inc. - - FR-V Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void *ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - register int count = 0; - - p_argv = ecif->avalue; - argp = stack; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); - i--, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - - if ((*p_arg)->type == FFI_TYPE_STRUCT) - { - z = sizeof(void*); - *(void **) argp = *p_argv; - } - /* if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (count > 24) - { - // This is going on the stack. Turn it into a double. - *(double *) argp = (double) *(float*)(* p_argv); - z = sizeof(double); - } - else - *(void **) argp = *(void **)(* p_argv); - } */ - else if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else if (z == sizeof(int)) - { - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - } - else - { - memcpy(argp, *p_argv, z); - } - p_argv++; - argp += z; - count += z; - } - - return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8))); -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - if (cif->rtype->type == FFI_TYPE_STRUCT) - cif->flags = -1; - else - cif->flags = cif->rtype->size; - - cif->bytes = ALIGN (cif->bytes, 8); - - return FFI_OK; -} - -extern void ffi_call_EABI(void *(*)(char *, extended_cif *), - extended_cif *, - unsigned, unsigned, - unsigned *, - void (*fn)(void)); - -void ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { - case FFI_EABI: - ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; - default: - FFI_ASSERT(0); - break; - } -} - -void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, - unsigned arg4, unsigned arg5, unsigned arg6) -{ - /* This function is called by a trampoline. The trampoline stows a - pointer to the ffi_closure object in gr7. We must save this - pointer in a place that will persist while we do our work. */ - register ffi_closure *creg __asm__ ("gr7"); - ffi_closure *closure = creg; - - /* Arguments that don't fit in registers are found on the stack - at a fixed offset above the current frame pointer. */ - register char *frame_pointer __asm__ ("fp"); - char *stack_args = frame_pointer + 16; - - /* Lay the register arguments down in a continuous chunk of memory. */ - unsigned register_args[6] = - { arg1, arg2, arg3, arg4, arg5, arg6 }; - - ffi_cif *cif = closure->cif; - ffi_type **arg_types = cif->arg_types; - void **avalue = alloca (cif->nargs * sizeof(void *)); - char *ptr = (char *) register_args; - int i; - - /* Find the address of each argument. */ - for (i = 0; i < cif->nargs; i++) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = ptr + 3; - break; - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = ptr + 2; - break; - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - avalue[i] = ptr; - break; - case FFI_TYPE_STRUCT: - avalue[i] = *(void**)ptr; - break; - default: - /* This is an 8-byte value. */ - avalue[i] = ptr; - ptr += 4; - break; - } - ptr += 4; - - /* If we've handled more arguments than fit in registers, - start looking at the those passed on the stack. */ - if (ptr == ((char *)register_args + (6*4))) - ptr = stack_args; - } - - /* Invoke the closure. */ - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - /* The caller allocates space for the return structure, and - passes a pointer to this space in gr3. Use this value directly - as the return value. */ - register void *return_struct_ptr __asm__("gr3"); - (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data); - } - else - { - /* Allocate space for the return value and call the function. */ - long long rvalue; - (closure->fun) (cif, &rvalue, avalue, closure->user_data); - - /* Functions return 4-byte or smaller results in gr8. 8-byte - values also use gr9. We fill the both, even for small return - values, just to avoid a branch. */ - asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue)); - asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1])); - } -} - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - unsigned long fn = (long) ffi_closure_eabi; - unsigned long cls = (long) codeloc; -#ifdef __FRV_FDPIC__ - register void *got __asm__("gr15"); -#endif - int i; - - fn = (unsigned long) ffi_closure_eabi; - -#ifdef __FRV_FDPIC__ - tramp[0] = &((unsigned int *)codeloc)[2]; - tramp[1] = got; - tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */ - tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */ - tramp[4] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */ - tramp[5] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */ - tramp[6] = 0x9cc86000; /* ldi @(gr6, #0), gr14 */ - tramp[7] = 0x8030e000; /* jmpl @(gr14, gr0) */ -#else - tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */ - tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */ - tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */ - tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */ - tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */ -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Cache flushing. */ - for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++) - __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i), - "r" (codeloc)); - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffitarget.h deleted file mode 100644 index d42540e53..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/frv/ffitarget.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2004 Red Hat, Inc. - Target configuration macros for FR-V - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_EABI, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_EABI -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -#ifdef __FRV_FDPIC__ -/* Trampolines are 8 4-byte instructions long. */ -#define FFI_TRAMPOLINE_SIZE (8*4) -#else -/* Trampolines are 5 4-byte instructions long. */ -#define FFI_TRAMPOLINE_SIZE (5*4) -#endif - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffi.c deleted file mode 100644 index b77a836dd..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffi.c +++ /dev/null @@ -1,586 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc. - Copyright (c) 2000 Hewlett Packard Company - Copyright (c) 2011 Anthony Green - - IA64 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include -#include - -#include "ia64_flags.h" - -/* A 64-bit pointer value. In LP64 mode, this is effectively a plain - pointer. In ILP32 mode, it's a pointer that's been extended to - 64 bits by "addp4". */ -typedef void *PTR64 __attribute__((mode(DI))); - -/* Memory image of fp register contents. This is the implementation - specific format used by ldf.fill/stf.spill. All we care about is - that it wants a 16 byte aligned slot. */ -typedef struct -{ - UINT64 x[2] __attribute__((aligned(16))); -} fpreg; - - -/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */ - -struct ia64_args -{ - fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */ - UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */ - UINT64 other_args[]; /* Arguments passed on stack, variable size. */ -}; - - -/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */ - -static inline void * -endian_adjust (void *addr, size_t len) -{ -#ifdef __BIG_ENDIAN__ - return addr + (8 - len); -#else - return addr; -#endif -} - -/* Store VALUE to ADDR in the current cpu implementation's fp spill format. - This is a macro instead of a function, so that it works for all 3 floating - point types without type conversions. Type conversion to long double breaks - the denorm support. */ - -#define stf_spill(addr, value) \ - asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value)); - -/* Load a value from ADDR, which is in the current cpu implementation's - fp spill format. As above, this must also be a macro. */ - -#define ldf_fill(result, addr) \ - asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); - -/* Return the size of the C type associated with with TYPE. Which will - be one of the FFI_IA64_TYPE_HFA_* values. */ - -static size_t -hfa_type_size (int type) -{ - switch (type) - { - case FFI_IA64_TYPE_HFA_FLOAT: - return sizeof(float); - case FFI_IA64_TYPE_HFA_DOUBLE: - return sizeof(double); - case FFI_IA64_TYPE_HFA_LDOUBLE: - return sizeof(__float80); - default: - abort (); - } -} - -/* Load from ADDR a value indicated by TYPE. Which will be one of - the FFI_IA64_TYPE_HFA_* values. */ - -static void -hfa_type_load (fpreg *fpaddr, int type, void *addr) -{ - switch (type) - { - case FFI_IA64_TYPE_HFA_FLOAT: - stf_spill (fpaddr, *(float *) addr); - return; - case FFI_IA64_TYPE_HFA_DOUBLE: - stf_spill (fpaddr, *(double *) addr); - return; - case FFI_IA64_TYPE_HFA_LDOUBLE: - stf_spill (fpaddr, *(__float80 *) addr); - return; - default: - abort (); - } -} - -/* Load VALUE into ADDR as indicated by TYPE. Which will be one of - the FFI_IA64_TYPE_HFA_* values. */ - -static void -hfa_type_store (int type, void *addr, fpreg *fpaddr) -{ - switch (type) - { - case FFI_IA64_TYPE_HFA_FLOAT: - { - float result; - ldf_fill (result, fpaddr); - *(float *) addr = result; - break; - } - case FFI_IA64_TYPE_HFA_DOUBLE: - { - double result; - ldf_fill (result, fpaddr); - *(double *) addr = result; - break; - } - case FFI_IA64_TYPE_HFA_LDOUBLE: - { - __float80 result; - ldf_fill (result, fpaddr); - *(__float80 *) addr = result; - break; - } - default: - abort (); - } -} - -/* Is TYPE a struct containing floats, doubles, or extended doubles, - all of the same fp type? If so, return the element type. Return - FFI_TYPE_VOID if not. */ - -static int -hfa_element_type (ffi_type *type, int nested) -{ - int element = FFI_TYPE_VOID; - - switch (type->type) - { - case FFI_TYPE_FLOAT: - /* We want to return VOID for raw floating-point types, but the - synthetic HFA type if we're nested within an aggregate. */ - if (nested) - element = FFI_IA64_TYPE_HFA_FLOAT; - break; - - case FFI_TYPE_DOUBLE: - /* Similarly. */ - if (nested) - element = FFI_IA64_TYPE_HFA_DOUBLE; - break; - - case FFI_TYPE_LONGDOUBLE: - /* Similarly, except that that HFA is true for double extended, - but not quad precision. Both have sizeof == 16, so tell the - difference based on the precision. */ - if (LDBL_MANT_DIG == 64 && nested) - element = FFI_IA64_TYPE_HFA_LDOUBLE; - break; - - case FFI_TYPE_STRUCT: - { - ffi_type **ptr = &type->elements[0]; - - for (ptr = &type->elements[0]; *ptr ; ptr++) - { - int sub_element = hfa_element_type (*ptr, 1); - if (sub_element == FFI_TYPE_VOID) - return FFI_TYPE_VOID; - - if (element == FFI_TYPE_VOID) - element = sub_element; - else if (element != sub_element) - return FFI_TYPE_VOID; - } - } - break; - - default: - return FFI_TYPE_VOID; - } - - return element; -} - - -/* Perform machine dependent cif processing. */ - -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) -{ - int flags; - - /* Adjust cif->bytes to include space for the bits of the ia64_args frame - that precedes the integer register portion. The estimate that the - generic bits did for the argument space required is good enough for the - integer component. */ - cif->bytes += offsetof(struct ia64_args, gp_regs[0]); - if (cif->bytes < sizeof(struct ia64_args)) - cif->bytes = sizeof(struct ia64_args); - - /* Set the return type flag. */ - flags = cif->rtype->type; - switch (cif->rtype->type) - { - case FFI_TYPE_LONGDOUBLE: - /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision, - and encode quad precision as a two-word integer structure. */ - if (LDBL_MANT_DIG != 64) - flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8); - break; - - case FFI_TYPE_STRUCT: - { - size_t size = cif->rtype->size; - int hfa_type = hfa_element_type (cif->rtype, 0); - - if (hfa_type != FFI_TYPE_VOID) - { - size_t nelts = size / hfa_type_size (hfa_type); - if (nelts <= 8) - flags = hfa_type | (size << 8); - } - else - { - if (size <= 32) - flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8); - } - } - break; - - default: - break; - } - cif->flags = flags; - - return FFI_OK; -} - -extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64); - -void -ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - struct ia64_args *stack; - long i, avn, gpcount, fpcount; - ffi_type **p_arg; - - FFI_ASSERT (cif->abi == FFI_UNIX); - - /* If we have no spot for a return value, make one. */ - if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID) - rvalue = alloca (cif->rtype->size); - - /* Allocate the stack frame. */ - stack = alloca (cif->bytes); - - gpcount = fpcount = 0; - avn = cif->nargs; - for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i]; - break; - case FFI_TYPE_UINT8: - stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i]; - break; - case FFI_TYPE_SINT16: - stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i]; - break; - case FFI_TYPE_UINT16: - stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i]; - break; - case FFI_TYPE_SINT32: - stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i]; - break; - case FFI_TYPE_UINT32: - stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i]; - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i]; - break; - - case FFI_TYPE_POINTER: - stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i]; - break; - - case FFI_TYPE_FLOAT: - if (gpcount < 8 && fpcount < 8) - stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]); - { - UINT32 tmp; - memcpy (&tmp, avalue[i], sizeof (UINT32)); - stack->gp_regs[gpcount++] = tmp; - } - break; - - case FFI_TYPE_DOUBLE: - if (gpcount < 8 && fpcount < 8) - stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]); - memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64)); - break; - - case FFI_TYPE_LONGDOUBLE: - if (gpcount & 1) - gpcount++; - if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) - stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]); - memcpy (&stack->gp_regs[gpcount], avalue[i], 16); - gpcount += 2; - break; - - case FFI_TYPE_STRUCT: - { - size_t size = (*p_arg)->size; - size_t align = (*p_arg)->alignment; - int hfa_type = hfa_element_type (*p_arg, 0); - - FFI_ASSERT (align <= 16); - if (align == 16 && (gpcount & 1)) - gpcount++; - - if (hfa_type != FFI_TYPE_VOID) - { - size_t hfa_size = hfa_type_size (hfa_type); - size_t offset = 0; - size_t gp_offset = gpcount * 8; - - while (fpcount < 8 - && offset < size - && gp_offset < 8 * 8) - { - hfa_type_load (&stack->fp_regs[fpcount], hfa_type, - avalue[i] + offset); - offset += hfa_size; - gp_offset += hfa_size; - fpcount += 1; - } - } - - memcpy (&stack->gp_regs[gpcount], avalue[i], size); - gpcount += (size + 7) / 8; - } - break; - - default: - abort (); - } - } - - ffi_call_unix (stack, rvalue, fn, cif->flags); -} - -/* Closures represent a pair consisting of a function pointer, and - some user data. A closure is invoked by reinterpreting the closure - as a function pointer, and branching to it. Thus we can make an - interpreted function callable as a C function: We turn the - interpreter itself, together with a pointer specifying the - interpreted procedure, into a closure. - - For IA64, function pointer are already pairs consisting of a code - pointer, and a gp pointer. The latter is needed to access global - variables. Here we set up such a pair as the first two words of - the closure (in the "trampoline" area), but we replace the gp - pointer with a pointer to the closure itself. We also add the real - gp pointer to the closure. This allows the function entry code to - both retrieve the user data, and to restore the correct gp pointer. */ - -extern void ffi_closure_unix (); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - /* The layout of a function descriptor. A C function pointer really - points to one of these. */ - struct ia64_fd - { - UINT64 code_pointer; - UINT64 gp; - }; - - struct ffi_ia64_trampoline_struct - { - UINT64 code_pointer; /* Pointer to ffi_closure_unix. */ - UINT64 fake_gp; /* Pointer to closure, installed as gp. */ - UINT64 real_gp; /* Real gp value. */ - }; - - struct ffi_ia64_trampoline_struct *tramp; - struct ia64_fd *fd; - - if (cif->abi != FFI_UNIX) - return FFI_BAD_ABI; - - tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp; - fd = (struct ia64_fd *)(void *)ffi_closure_unix; - - tramp->code_pointer = fd->code_pointer; - tramp->real_gp = fd->gp; - tramp->fake_gp = (UINT64)(PTR64)codeloc; - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - - -UINT64 -ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, - void *rvalue, void *r8) -{ - ffi_cif *cif; - void **avalue; - ffi_type **p_arg; - long i, avn, gpcount, fpcount; - - cif = closure->cif; - avn = cif->nargs; - avalue = alloca (avn * sizeof (void *)); - - /* If the structure return value is passed in memory get that location - from r8 so as to pass the value directly back to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT) - rvalue = r8; - - gpcount = fpcount = 0; - for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1); - break; - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2); - break; - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4); - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - avalue[i] = &stack->gp_regs[gpcount++]; - break; - case FFI_TYPE_POINTER: - avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*)); - break; - - case FFI_TYPE_FLOAT: - if (gpcount < 8 && fpcount < 8) - { - fpreg *addr = &stack->fp_regs[fpcount++]; - float result; - avalue[i] = addr; - ldf_fill (result, addr); - *(float *)addr = result; - } - else - avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4); - gpcount++; - break; - - case FFI_TYPE_DOUBLE: - if (gpcount < 8 && fpcount < 8) - { - fpreg *addr = &stack->fp_regs[fpcount++]; - double result; - avalue[i] = addr; - ldf_fill (result, addr); - *(double *)addr = result; - } - else - avalue[i] = &stack->gp_regs[gpcount]; - gpcount++; - break; - - case FFI_TYPE_LONGDOUBLE: - if (gpcount & 1) - gpcount++; - if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) - { - fpreg *addr = &stack->fp_regs[fpcount++]; - __float80 result; - avalue[i] = addr; - ldf_fill (result, addr); - *(__float80 *)addr = result; - } - else - avalue[i] = &stack->gp_regs[gpcount]; - gpcount += 2; - break; - - case FFI_TYPE_STRUCT: - { - size_t size = (*p_arg)->size; - size_t align = (*p_arg)->alignment; - int hfa_type = hfa_element_type (*p_arg, 0); - - FFI_ASSERT (align <= 16); - if (align == 16 && (gpcount & 1)) - gpcount++; - - if (hfa_type != FFI_TYPE_VOID) - { - size_t hfa_size = hfa_type_size (hfa_type); - size_t offset = 0; - size_t gp_offset = gpcount * 8; - void *addr = alloca (size); - - avalue[i] = addr; - - while (fpcount < 8 - && offset < size - && gp_offset < 8 * 8) - { - hfa_type_store (hfa_type, addr + offset, - &stack->fp_regs[fpcount]); - offset += hfa_size; - gp_offset += hfa_size; - fpcount += 1; - } - - if (offset < size) - memcpy (addr + offset, (char *)stack->gp_regs + gp_offset, - size - offset); - } - else - avalue[i] = &stack->gp_regs[gpcount]; - - gpcount += (size + 7) / 8; - } - break; - - default: - abort (); - } - } - - closure->fun (cif, rvalue, avalue, closure->user_data); - - return cif->flags; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffitarget.h deleted file mode 100644 index e68cea615..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ffitarget.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for IA-64. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long long ffi_arg; -typedef signed long long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_UNIX, /* Linux and all Unix variants use the same conventions */ - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_UNIX -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */ - /* can be interpreted as a C function */ - /* descriptor: */ - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ia64_flags.h b/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ia64_flags.h deleted file mode 100644 index 9d652cef1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/ia64_flags.h +++ /dev/null @@ -1,40 +0,0 @@ -/* ----------------------------------------------------------------------- - ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company - - IA64/unix Foreign Function Interface - - Original author: Hans Boehm, HP Labs - - 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. - ----------------------------------------------------------------------- */ - -/* "Type" codes used between assembly and C. When used as a part of - a cfi->flags value, the low byte will be these extra type codes, - and bits 8-31 will be the actual size of the type. */ - -/* Small structures containing N words in integer registers. */ -#define FFI_IA64_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 1) - -/* Homogeneous Floating Point Aggregates (HFAs) which are returned - in FP registers. */ -#define FFI_IA64_TYPE_HFA_FLOAT (FFI_TYPE_LAST + 2) -#define FFI_IA64_TYPE_HFA_DOUBLE (FFI_TYPE_LAST + 3) -#define FFI_IA64_TYPE_HFA_LDOUBLE (FFI_TYPE_LAST + 4) diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/unix.S b/ruby/ext/fiddle/libffi-3.2.1/src/ia64/unix.S deleted file mode 100644 index 4d2a86d42..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/ia64/unix.S +++ /dev/null @@ -1,560 +0,0 @@ -/* ----------------------------------------------------------------------- - unix.S - Copyright (c) 1998, 2008 Red Hat, Inc. - Copyright (c) 2000 Hewlett Packard Company - - IA64/unix Foreign Function Interface - - Primary author: Hans Boehm, HP Labs - - Loosely modeled on Cygnus code for other platforms. - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#include "ia64_flags.h" - - .pred.safe_across_calls p1-p5,p16-p63 -.text - -/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue, - void (*fn)(void), int flags); - */ - - .align 16 - .global ffi_call_unix - .proc ffi_call_unix -ffi_call_unix: - .prologue - /* Bit o trickiness. We actually share a stack frame with ffi_call. - Rely on the fact that ffi_call uses a vframe and don't bother - tracking one here at all. */ - .fframe 0 - .save ar.pfs, r36 // loc0 - alloc loc0 = ar.pfs, 4, 3, 8, 0 - .save rp, loc1 - mov loc1 = b0 - .body - add r16 = 16, in0 - mov loc2 = gp - mov r8 = in1 - ;; - - /* Load up all of the argument registers. */ - ldf.fill f8 = [in0], 32 - ldf.fill f9 = [r16], 32 - ;; - ldf.fill f10 = [in0], 32 - ldf.fill f11 = [r16], 32 - ;; - ldf.fill f12 = [in0], 32 - ldf.fill f13 = [r16], 32 - ;; - ldf.fill f14 = [in0], 32 - ldf.fill f15 = [r16], 24 - ;; - ld8 out0 = [in0], 16 - ld8 out1 = [r16], 16 - ;; - ld8 out2 = [in0], 16 - ld8 out3 = [r16], 16 - ;; - ld8 out4 = [in0], 16 - ld8 out5 = [r16], 16 - ;; - ld8 out6 = [in0] - ld8 out7 = [r16] - ;; - - /* Deallocate the register save area from the stack frame. */ - mov sp = in0 - - /* Call the target function. */ - ld8 r16 = [in2], 8 - ;; - ld8 gp = [in2] - mov b6 = r16 - br.call.sptk.many b0 = b6 - ;; - - /* Dispatch to handle return value. */ - mov gp = loc2 - zxt1 r16 = in3 - ;; - mov ar.pfs = loc0 - addl r18 = @ltoffx(.Lst_table), gp - ;; - ld8.mov r18 = [r18], .Lst_table - mov b0 = loc1 - ;; - shladd r18 = r16, 3, r18 - ;; - ld8 r17 = [r18] - shr in3 = in3, 8 - ;; - add r17 = r17, r18 - ;; - mov b6 = r17 - br b6 - ;; - -.Lst_void: - br.ret.sptk.many b0 - ;; -.Lst_uint8: - zxt1 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_sint8: - sxt1 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_uint16: - zxt2 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_sint16: - sxt2 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_uint32: - zxt4 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_sint32: - sxt4 r8 = r8 - ;; - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_int64: - st8 [in1] = r8 - br.ret.sptk.many b0 - ;; -.Lst_float: - stfs [in1] = f8 - br.ret.sptk.many b0 - ;; -.Lst_double: - stfd [in1] = f8 - br.ret.sptk.many b0 - ;; -.Lst_ldouble: - stfe [in1] = f8 - br.ret.sptk.many b0 - ;; - -.Lst_small_struct: - add sp = -16, sp - cmp.lt p6, p0 = 8, in3 - cmp.lt p7, p0 = 16, in3 - cmp.lt p8, p0 = 24, in3 - ;; - add r16 = 8, sp - add r17 = 16, sp - add r18 = 24, sp - ;; - st8 [sp] = r8 -(p6) st8 [r16] = r9 - mov out0 = in1 -(p7) st8 [r17] = r10 -(p8) st8 [r18] = r11 - mov out1 = sp - mov out2 = in3 - br.call.sptk.many b0 = memcpy# - ;; - mov ar.pfs = loc0 - mov b0 = loc1 - mov gp = loc2 - br.ret.sptk.many b0 - -.Lst_hfa_float: - add r16 = 4, in1 - cmp.lt p6, p0 = 4, in3 - ;; - stfs [in1] = f8, 8 -(p6) stfs [r16] = f9, 8 - cmp.lt p7, p0 = 8, in3 - cmp.lt p8, p0 = 12, in3 - ;; -(p7) stfs [in1] = f10, 8 -(p8) stfs [r16] = f11, 8 - cmp.lt p9, p0 = 16, in3 - cmp.lt p10, p0 = 20, in3 - ;; -(p9) stfs [in1] = f12, 8 -(p10) stfs [r16] = f13, 8 - cmp.lt p6, p0 = 24, in3 - cmp.lt p7, p0 = 28, in3 - ;; -(p6) stfs [in1] = f14 -(p7) stfs [r16] = f15 - br.ret.sptk.many b0 - ;; - -.Lst_hfa_double: - add r16 = 8, in1 - cmp.lt p6, p0 = 8, in3 - ;; - stfd [in1] = f8, 16 -(p6) stfd [r16] = f9, 16 - cmp.lt p7, p0 = 16, in3 - cmp.lt p8, p0 = 24, in3 - ;; -(p7) stfd [in1] = f10, 16 -(p8) stfd [r16] = f11, 16 - cmp.lt p9, p0 = 32, in3 - cmp.lt p10, p0 = 40, in3 - ;; -(p9) stfd [in1] = f12, 16 -(p10) stfd [r16] = f13, 16 - cmp.lt p6, p0 = 48, in3 - cmp.lt p7, p0 = 56, in3 - ;; -(p6) stfd [in1] = f14 -(p7) stfd [r16] = f15 - br.ret.sptk.many b0 - ;; - -.Lst_hfa_ldouble: - add r16 = 16, in1 - cmp.lt p6, p0 = 16, in3 - ;; - stfe [in1] = f8, 32 -(p6) stfe [r16] = f9, 32 - cmp.lt p7, p0 = 32, in3 - cmp.lt p8, p0 = 48, in3 - ;; -(p7) stfe [in1] = f10, 32 -(p8) stfe [r16] = f11, 32 - cmp.lt p9, p0 = 64, in3 - cmp.lt p10, p0 = 80, in3 - ;; -(p9) stfe [in1] = f12, 32 -(p10) stfe [r16] = f13, 32 - cmp.lt p6, p0 = 96, in3 - cmp.lt p7, p0 = 112, in3 - ;; -(p6) stfe [in1] = f14 -(p7) stfe [r16] = f15 - br.ret.sptk.many b0 - ;; - - .endp ffi_call_unix - - .align 16 - .global ffi_closure_unix - .proc ffi_closure_unix - -#define FRAME_SIZE (8*16 + 8*8 + 8*16) - -ffi_closure_unix: - .prologue - .save ar.pfs, r40 // loc0 - alloc loc0 = ar.pfs, 8, 4, 4, 0 - .fframe FRAME_SIZE - add r12 = -FRAME_SIZE, r12 - .save rp, loc1 - mov loc1 = b0 - .save ar.unat, loc2 - mov loc2 = ar.unat - .body - - /* Retrieve closure pointer and real gp. */ -#ifdef _ILP32 - addp4 out0 = 0, gp - addp4 gp = 16, gp -#else - mov out0 = gp - add gp = 16, gp -#endif - ;; - ld8 gp = [gp] - - /* Spill all of the possible argument registers. */ - add r16 = 16 + 8*16, sp - add r17 = 16 + 8*16 + 16, sp - ;; - stf.spill [r16] = f8, 32 - stf.spill [r17] = f9, 32 - mov loc3 = gp - ;; - stf.spill [r16] = f10, 32 - stf.spill [r17] = f11, 32 - ;; - stf.spill [r16] = f12, 32 - stf.spill [r17] = f13, 32 - ;; - stf.spill [r16] = f14, 32 - stf.spill [r17] = f15, 24 - ;; - .mem.offset 0, 0 - st8.spill [r16] = in0, 16 - .mem.offset 8, 0 - st8.spill [r17] = in1, 16 - add out1 = 16 + 8*16, sp - ;; - .mem.offset 0, 0 - st8.spill [r16] = in2, 16 - .mem.offset 8, 0 - st8.spill [r17] = in3, 16 - add out2 = 16, sp - ;; - .mem.offset 0, 0 - st8.spill [r16] = in4, 16 - .mem.offset 8, 0 - st8.spill [r17] = in5, 16 - mov out3 = r8 - ;; - .mem.offset 0, 0 - st8.spill [r16] = in6 - .mem.offset 8, 0 - st8.spill [r17] = in7 - - /* Invoke ffi_closure_unix_inner for the hard work. */ - br.call.sptk.many b0 = ffi_closure_unix_inner - ;; - - /* Dispatch to handle return value. */ - mov gp = loc3 - zxt1 r16 = r8 - ;; - addl r18 = @ltoffx(.Lld_table), gp - mov ar.pfs = loc0 - ;; - ld8.mov r18 = [r18], .Lld_table - mov b0 = loc1 - ;; - shladd r18 = r16, 3, r18 - mov ar.unat = loc2 - ;; - ld8 r17 = [r18] - shr r8 = r8, 8 - ;; - add r17 = r17, r18 - add r16 = 16, sp - ;; - mov b6 = r17 - br b6 - ;; - .label_state 1 - -.Lld_void: - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; -.Lld_int: - .body - .copy_state 1 - ld8 r8 = [r16] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; -.Lld_float: - .body - .copy_state 1 - ldfs f8 = [r16] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; -.Lld_double: - .body - .copy_state 1 - ldfd f8 = [r16] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; -.Lld_ldouble: - .body - .copy_state 1 - ldfe f8 = [r16] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; - -.Lld_small_struct: - .body - .copy_state 1 - add r17 = 8, r16 - cmp.lt p6, p0 = 8, r8 - cmp.lt p7, p0 = 16, r8 - cmp.lt p8, p0 = 24, r8 - ;; - ld8 r8 = [r16], 16 -(p6) ld8 r9 = [r17], 16 - ;; -(p7) ld8 r10 = [r16] -(p8) ld8 r11 = [r17] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; - -.Lld_hfa_float: - .body - .copy_state 1 - add r17 = 4, r16 - cmp.lt p6, p0 = 4, r8 - ;; - ldfs f8 = [r16], 8 -(p6) ldfs f9 = [r17], 8 - cmp.lt p7, p0 = 8, r8 - cmp.lt p8, p0 = 12, r8 - ;; -(p7) ldfs f10 = [r16], 8 -(p8) ldfs f11 = [r17], 8 - cmp.lt p9, p0 = 16, r8 - cmp.lt p10, p0 = 20, r8 - ;; -(p9) ldfs f12 = [r16], 8 -(p10) ldfs f13 = [r17], 8 - cmp.lt p6, p0 = 24, r8 - cmp.lt p7, p0 = 28, r8 - ;; -(p6) ldfs f14 = [r16] -(p7) ldfs f15 = [r17] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; - -.Lld_hfa_double: - .body - .copy_state 1 - add r17 = 8, r16 - cmp.lt p6, p0 = 8, r8 - ;; - ldfd f8 = [r16], 16 -(p6) ldfd f9 = [r17], 16 - cmp.lt p7, p0 = 16, r8 - cmp.lt p8, p0 = 24, r8 - ;; -(p7) ldfd f10 = [r16], 16 -(p8) ldfd f11 = [r17], 16 - cmp.lt p9, p0 = 32, r8 - cmp.lt p10, p0 = 40, r8 - ;; -(p9) ldfd f12 = [r16], 16 -(p10) ldfd f13 = [r17], 16 - cmp.lt p6, p0 = 48, r8 - cmp.lt p7, p0 = 56, r8 - ;; -(p6) ldfd f14 = [r16] -(p7) ldfd f15 = [r17] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; - -.Lld_hfa_ldouble: - .body - .copy_state 1 - add r17 = 16, r16 - cmp.lt p6, p0 = 16, r8 - ;; - ldfe f8 = [r16], 32 -(p6) ldfe f9 = [r17], 32 - cmp.lt p7, p0 = 32, r8 - cmp.lt p8, p0 = 48, r8 - ;; -(p7) ldfe f10 = [r16], 32 -(p8) ldfe f11 = [r17], 32 - cmp.lt p9, p0 = 64, r8 - cmp.lt p10, p0 = 80, r8 - ;; -(p9) ldfe f12 = [r16], 32 -(p10) ldfe f13 = [r17], 32 - cmp.lt p6, p0 = 96, r8 - cmp.lt p7, p0 = 112, r8 - ;; -(p6) ldfe f14 = [r16] -(p7) ldfe f15 = [r17] - .restore sp - add sp = FRAME_SIZE, sp - br.ret.sptk.many b0 - ;; - - .endp ffi_closure_unix - - .section .rodata - .align 8 -.Lst_table: - data8 @pcrel(.Lst_void) // FFI_TYPE_VOID - data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT - data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT - data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE - data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE - data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8 - data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8 - data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16 - data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16 - data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32 - data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32 - data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64 - data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64 - data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT - data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER - data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT - data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT - data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE - data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE - -.Lld_table: - data8 @pcrel(.Lld_void) // FFI_TYPE_VOID - data8 @pcrel(.Lld_int) // FFI_TYPE_INT - data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT - data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE - data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE - data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8 - data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8 - data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16 - data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16 - data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32 - data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32 - data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64 - data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64 - data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT - data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER - data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT - data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT - data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE - data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/java_raw_api.c b/ruby/ext/fiddle/libffi-3.2.1/src/java_raw_api.c deleted file mode 100644 index 127123d5b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/java_raw_api.c +++ /dev/null @@ -1,374 +0,0 @@ -/* ----------------------------------------------------------------------- - java_raw_api.c - Copyright (c) 1999, 2007, 2008 Red Hat, Inc. - - Cloned from raw_api.c - - Raw_api.c author: Kresten Krab Thorup - Java_raw_api.c author: Hans-J. Boehm - - $Id $ - - 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. - ----------------------------------------------------------------------- */ - -/* This defines a Java- and 64-bit specific variant of the raw API. */ -/* It assumes that "raw" argument blocks look like Java stacks on a */ -/* 64-bit machine. Arguments that can be stored in a single stack */ -/* stack slots (longs, doubles) occupy 128 bits, but only the first */ -/* 64 bits are actually used. */ - -#include -#include -#include - -#if !defined(NO_JAVA_RAW_API) - -size_t -ffi_java_raw_size (ffi_cif *cif) -{ - size_t result = 0; - int i; - - ffi_type **at = cif->arg_types; - - for (i = cif->nargs-1; i >= 0; i--, at++) - { - switch((*at) -> type) { - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - result += 2 * FFI_SIZEOF_JAVA_RAW; - break; - case FFI_TYPE_STRUCT: - /* No structure parameters in Java. */ - abort(); - case FFI_TYPE_COMPLEX: - /* Not supported yet. */ - abort(); - default: - result += FFI_SIZEOF_JAVA_RAW; - } - } - - return result; -} - - -void -ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - -#if WORDS_BIGENDIAN - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - *args = (void*) ((char*)(raw++) + 3); - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - *args = (void*) ((char*)(raw++) + 2); - break; - -#if FFI_SIZEOF_JAVA_RAW == 8 - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - *args = (void *)raw; - raw += 2; - break; -#endif - - case FFI_TYPE_POINTER: - *args = (void*) &(raw++)->ptr; - break; - - case FFI_TYPE_COMPLEX: - /* Not supported yet. */ - abort(); - - default: - *args = raw; - raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); - } - } - -#else /* WORDS_BIGENDIAN */ - -#if !PDP - - /* then assume little endian */ - for (i = 0; i < cif->nargs; i++, tp++, args++) - { -#if FFI_SIZEOF_JAVA_RAW == 8 - switch((*tp)->type) { - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - *args = (void*) raw; - raw += 2; - break; - case FFI_TYPE_COMPLEX: - /* Not supported yet. */ - abort(); - default: - *args = (void*) raw++; - } -#else /* FFI_SIZEOF_JAVA_RAW != 8 */ - *args = (void*) raw; - raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); -#endif /* FFI_SIZEOF_JAVA_RAW == 8 */ - } - -#else -#error "pdp endian not supported" -#endif /* ! PDP */ - -#endif /* WORDS_BIGENDIAN */ -} - -void -ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: -#if WORDS_BIGENDIAN - *(UINT32*)(raw++) = *(UINT8*) (*args); -#else - (raw++)->uint = *(UINT8*) (*args); -#endif - break; - - case FFI_TYPE_SINT8: -#if WORDS_BIGENDIAN - *(SINT32*)(raw++) = *(SINT8*) (*args); -#else - (raw++)->sint = *(SINT8*) (*args); -#endif - break; - - case FFI_TYPE_UINT16: -#if WORDS_BIGENDIAN - *(UINT32*)(raw++) = *(UINT16*) (*args); -#else - (raw++)->uint = *(UINT16*) (*args); -#endif - break; - - case FFI_TYPE_SINT16: -#if WORDS_BIGENDIAN - *(SINT32*)(raw++) = *(SINT16*) (*args); -#else - (raw++)->sint = *(SINT16*) (*args); -#endif - break; - - case FFI_TYPE_UINT32: -#if WORDS_BIGENDIAN - *(UINT32*)(raw++) = *(UINT32*) (*args); -#else - (raw++)->uint = *(UINT32*) (*args); -#endif - break; - - case FFI_TYPE_SINT32: -#if WORDS_BIGENDIAN - *(SINT32*)(raw++) = *(SINT32*) (*args); -#else - (raw++)->sint = *(SINT32*) (*args); -#endif - break; - - case FFI_TYPE_FLOAT: - (raw++)->flt = *(FLOAT32*) (*args); - break; - -#if FFI_SIZEOF_JAVA_RAW == 8 - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - raw->uint = *(UINT64*) (*args); - raw += 2; - break; -#endif - - case FFI_TYPE_POINTER: - (raw++)->ptr = **(void***) args; - break; - - default: -#if FFI_SIZEOF_JAVA_RAW == 8 - FFI_ASSERT(0); /* Should have covered all cases */ -#else - memcpy ((void*) raw->data, (void*)*args, (*tp)->size); - raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); -#endif - } - } -} - -#if !FFI_NATIVE_RAW_API - -static void -ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue) -{ -#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 - switch (cif->rtype->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_UINT32: - *(UINT64 *)rvalue <<= 32; - break; - - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: -#if FFI_SIZEOF_JAVA_RAW == 4 - case FFI_TYPE_POINTER: -#endif - *(SINT64 *)rvalue <<= 32; - break; - - case FFI_TYPE_COMPLEX: - /* Not supported yet. */ - abort(); - - default: - break; - } -#endif -} - -static void -ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue) -{ -#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 - switch (cif->rtype->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_UINT32: - *(UINT64 *)rvalue >>= 32; - break; - - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - *(SINT64 *)rvalue >>= 32; - break; - - case FFI_TYPE_COMPLEX: - /* Not supported yet. */ - abort(); - - default: - break; - } -#endif -} - -/* This is a generic definition of ffi_raw_call, to be used if the - * native system does not provide a machine-specific implementation. - * Having this, allows code to be written for the raw API, without - * the need for system-specific code to handle input in that format; - * these following couple of functions will handle the translation forth - * and back automatically. */ - -void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, - ffi_java_raw *raw) -{ - void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - ffi_java_raw_to_ptrarray (cif, raw, avalue); - ffi_call (cif, fn, rvalue, avalue); - ffi_java_rvalue_to_raw (cif, rvalue); -} - -#if FFI_CLOSURES /* base system provides closures */ - -static void -ffi_java_translate_args (ffi_cif *cif, void *rvalue, - void **avalue, void *user_data) -{ - ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif)); - ffi_raw_closure *cl = (ffi_raw_closure*)user_data; - - ffi_java_ptrarray_to_raw (cif, avalue, raw); - (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data); - ffi_java_raw_to_rvalue (cif, rvalue); -} - -ffi_status -ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data, - void *codeloc) -{ - ffi_status status; - - status = ffi_prep_closure_loc ((ffi_closure*) cl, - cif, - &ffi_java_translate_args, - codeloc, - codeloc); - if (status == FFI_OK) - { - cl->fun = fun; - cl->user_data = user_data; - } - - return status; -} - -/* Again, here is the generic version of ffi_prep_raw_closure, which - * will install an intermediate "hub" for translation of arguments from - * the pointer-array format, to the raw format */ - -ffi_status -ffi_prep_java_raw_closure (ffi_java_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data) -{ - return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl); -} - -#endif /* FFI_CLOSURES */ -#endif /* !FFI_NATIVE_RAW_API */ -#endif /* !NO_JAVA_RAW_API */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffi.c deleted file mode 100644 index 300006349..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffi.c +++ /dev/null @@ -1,232 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2004 Renesas Technology - Copyright (c) 2008 Red Hat, Inc. - - M32R Foreign Function Interface - - 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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -/* ffi_prep_args is called by the assembly routine once stack - space has been allocated for the function's arguments. */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - unsigned int i; - int tmp; - unsigned int avn; - void **p_argv; - char *argp; - ffi_type **p_arg; - - tmp = 0; - argp = stack; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8) - { - *(void **) argp = ecif->rvalue; - argp += 4; - } - - avn = ecif->cif->nargs; - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0) && (avn != 0); - i--, p_arg++) - { - size_t z; - - /* Align if necessary. */ - if (((*p_arg)->alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, (*p_arg)->alignment); - - if (avn != 0) - { - avn--; - z = (*p_arg)->size; - if (z < sizeof (int)) - { - z = sizeof (int); - - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - z = (*p_arg)->size; - if ((*p_arg)->alignment != 1) - memcpy (argp, *p_argv, z); - else - memcpy (argp + 4 - z, *p_argv, z); - z = sizeof (int); - break; - - default: - FFI_ASSERT(0); - } - } - else if (z == sizeof (int)) - { - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - } - else - { - if ((*p_arg)->type == FFI_TYPE_STRUCT) - { - if (z > 8) - { - *(unsigned int *) argp = (unsigned int)(void *)(* p_argv); - z = sizeof(void *); - } - else - { - memcpy(argp, *p_argv, z); - z = 8; - } - } - else - { - /* Double or long long 64bit. */ - memcpy (argp, *p_argv, z); - } - } - p_argv++; - argp += z; - } - } - - return; -} - -/* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* Set the return type flag. */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_STRUCT: - if (cif->rtype->size <= 4) - cif->flags = FFI_TYPE_INT; - - else if (cif->rtype->size <= 8) - cif->flags = FFI_TYPE_DOUBLE; - - else - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: - cif->flags = FFI_TYPE_DOUBLE; - break; - - case FFI_TYPE_FLOAT: - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have - a return value address then we need to make one. */ - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca (cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - int size = cif->rtype->size; - int align = cif->rtype->alignment; - - if (size < 4) - { - if (align == 1) - *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8; - } - else if (4 < size && size < 8) - { - if (align == 1) - { - memcpy (ecif.rvalue, ecif.rvalue + 8-size, size); - } - else if (align == 2) - { - if (size & 1) - size += 1; - - if (size != 8) - memcpy (ecif.rvalue, ecif.rvalue + 8-size, size); - } - } - } - break; - - default: - FFI_ASSERT(0); - break; - } -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffitarget.h deleted file mode 100644 index 6c3480198..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 2004 Renesas Technology. - Target configuration macros for M32R. - - 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 RENESAS TECHNOLOGY 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi - { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV - } ffi_abi; -#endif - -#define FFI_CLOSURES 0 -#define FFI_TRAMPOLINE_SIZE 24 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/m32r/sysv.S deleted file mode 100644 index 06b75c226..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m32r/sysv.S +++ /dev/null @@ -1,121 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2004 Renesas Technology - - M32R Foreign Function Interface - - 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 RENESAS TECHNOLOGY 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -/* XXX these lose for some platforms, I'm sure. */ -#define CNAME(x) x -#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x): -#endif - -.text - - /* R0: ffi_prep_args */ - /* R1: &ecif */ - /* R2: cif->bytes */ - /* R3: fig->flags */ - /* sp+0: ecif.rvalue */ - /* sp+4: fn */ - - /* This assumes we are using gas. */ -ENTRY(ffi_call_SYSV) - /* Save registers. */ - push fp - push lr - push r3 - push r2 - push r1 - push r0 - mv fp, sp - - /* Make room for all of the new args. */ - sub sp, r2 - - /* Place all of the ffi_prep_args in position. */ - mv lr, r0 - mv r0, sp - /* R1 already set. */ - - /* And call. */ - jl lr - - /* Move first 4 parameters in registers... */ - ld r0, @(0,sp) - ld r1, @(4,sp) - ld r2, @(8,sp) - ld r3, @(12,sp) - - /* ...and adjust the stack. */ - ld lr, @(8,fp) - cmpi lr, #16 - bc adjust_stack - ldi lr, #16 -adjust_stack: - add sp, lr - - /* Call the function. */ - ld lr, @(28,fp) - jl lr - - /* Remove the space we pushed for the args. */ - mv sp, fp - - /* Load R2 with the pointer to storage for the return value. */ - ld r2, @(24,sp) - - /* Load R3 with the return type code. */ - ld r3, @(12,sp) - - /* If the return value pointer is NULL, assume no return value. */ - beqz r2, epilogue - - /* Return INT. */ - ldi r4, #FFI_TYPE_INT - bne r3, r4, return_double - st r0, @r2 - bra epilogue - -return_double: - /* Return DOUBLE or LONGDOUBLE. */ - ldi r4, #FFI_TYPE_DOUBLE - bne r3, r4, epilogue - st r0, @r2 - st r1, @(4,r2) - -epilogue: - pop r0 - pop r1 - pop r2 - pop r3 - pop lr - pop fp - jmp lr - -.ffi_call_SYSV_end: - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffi.c deleted file mode 100644 index 0dee9383a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffi.c +++ /dev/null @@ -1,362 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - - m68k Foreign Function Interface - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include -#ifdef __rtems__ -void rtems_cache_flush_multiple_data_lines( const void *, size_t ); -#else -#include -#ifdef __MINT__ -#include -#include -#else -#include -#endif -#endif - -void ffi_call_SYSV (extended_cif *, - unsigned, unsigned, - void *, void (*fn) ()); -void *ffi_prep_args (void *stack, extended_cif *ecif); -void ffi_closure_SYSV (ffi_closure *); -void ffi_closure_struct_SYSV (ffi_closure *); -unsigned int ffi_closure_SYSV_inner (ffi_closure *closure, - void *resp, void *args); - -/* ffi_prep_args is called by the assembly routine once stack space has - been allocated for the function's arguments. */ - -void * -ffi_prep_args (void *stack, extended_cif *ecif) -{ - unsigned int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - void *struct_value_ptr; - - argp = stack; - - if ( -#ifdef __MINT__ - (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) || -#endif - (((ecif->cif->rtype->type == FFI_TYPE_STRUCT) - && !ecif->cif->flags))) - struct_value_ptr = ecif->rvalue; - else - struct_value_ptr = NULL; - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - i != 0; - i--, p_arg++) - { - size_t z = (*p_arg)->size; - int type = (*p_arg)->type; - - if (z < sizeof (int)) - { - switch (type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) *p_argv; - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv; - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) *p_argv; - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv; - break; - - case FFI_TYPE_STRUCT: -#ifdef __MINT__ - if (z == 1 || z == 2) - memcpy (argp + 2, *p_argv, z); - else - memcpy (argp, *p_argv, z); -#else - memcpy (argp + sizeof (int) - z, *p_argv, z); -#endif - break; - - default: - FFI_ASSERT (0); - } - z = sizeof (int); - } - else - { - memcpy (argp, *p_argv, z); - - /* Align if necessary. */ - if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); - } - - p_argv++; - argp += z; - } - - return struct_value_ptr; -} - -#define CIF_FLAGS_INT 1 -#define CIF_FLAGS_DINT 2 -#define CIF_FLAGS_FLOAT 4 -#define CIF_FLAGS_DOUBLE 8 -#define CIF_FLAGS_LDOUBLE 16 -#define CIF_FLAGS_POINTER 32 -#define CIF_FLAGS_STRUCT1 64 -#define CIF_FLAGS_STRUCT2 128 -#define CIF_FLAGS_SINT8 256 -#define CIF_FLAGS_SINT16 512 - -/* Perform machine dependent cif processing */ -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - cif->flags = 0; - break; - - case FFI_TYPE_STRUCT: - if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT && - cif->rtype->elements[1]) - { - cif->flags = 0; - break; - } - - switch (cif->rtype->size) - { - case 1: -#ifdef __MINT__ - cif->flags = CIF_FLAGS_STRUCT2; -#else - cif->flags = CIF_FLAGS_STRUCT1; -#endif - break; - case 2: - cif->flags = CIF_FLAGS_STRUCT2; - break; -#ifdef __MINT__ - case 3: -#endif - case 4: - cif->flags = CIF_FLAGS_INT; - break; -#ifdef __MINT__ - case 7: -#endif - case 8: - cif->flags = CIF_FLAGS_DINT; - break; - default: - cif->flags = 0; - break; - } - break; - - case FFI_TYPE_FLOAT: - cif->flags = CIF_FLAGS_FLOAT; - break; - - case FFI_TYPE_DOUBLE: - cif->flags = CIF_FLAGS_DOUBLE; - break; - -#if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE) - case FFI_TYPE_LONGDOUBLE: -#ifdef __MINT__ - cif->flags = 0; -#else - cif->flags = CIF_FLAGS_LDOUBLE; -#endif - break; -#endif - - case FFI_TYPE_POINTER: - cif->flags = CIF_FLAGS_POINTER; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = CIF_FLAGS_DINT; - break; - - case FFI_TYPE_SINT16: - cif->flags = CIF_FLAGS_SINT16; - break; - - case FFI_TYPE_SINT8: - cif->flags = CIF_FLAGS_SINT8; - break; - - default: - cif->flags = CIF_FLAGS_INT; - break; - } - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return value - address then we need to make one. */ - - if (rvalue == NULL - && cif->rtype->type == FFI_TYPE_STRUCT - && cif->rtype->size > 8) - ecif.rvalue = alloca (cif->rtype->size); - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (&ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; - } -} - -static void -ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif) -{ - unsigned int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - - argp = stack; - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - - z = (*p_arg)->size; -#ifdef __MINT__ - if (cif->flags && - cif->rtype->type == FFI_TYPE_STRUCT && - (z == 1 || z == 2)) - { - *p_argv = (void *) (argp + 2); - - z = 4; - } - else - if (cif->flags && - cif->rtype->type == FFI_TYPE_STRUCT && - (z == 3 || z == 4)) - { - *p_argv = (void *) (argp); - - z = 4; - } - else -#endif - if (z <= 4) - { - *p_argv = (void *) (argp + 4 - z); - - z = 4; - } - else - { - *p_argv = (void *) argp; - - /* Align if necessary */ - if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); - } - - p_argv++; - argp += z; - } -} - -unsigned int -ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args) -{ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void *)); - - ffi_prep_incoming_args_SYSV(args, arg_area, cif); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - return cif->flags; -} - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - *(unsigned short *)closure->tramp = 0x207c; - *(void **)(closure->tramp + 2) = codeloc; - *(unsigned short *)(closure->tramp + 6) = 0x4ef9; - - if ( -#ifdef __MINT__ - (cif->rtype->type == FFI_TYPE_LONGDOUBLE) || -#endif - (((cif->rtype->type == FFI_TYPE_STRUCT) - && !cif->flags))) - *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV; - else - *(void **)(closure->tramp + 8) = ffi_closure_SYSV; - -#ifdef __rtems__ - rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE ); -#elif defined(__MINT__) - Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE); -#else - syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE, - FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE); -#endif - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffitarget.h deleted file mode 100644 index e81dde2b2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/ffitarget.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for Motorola 68K. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 16 -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/m68k/sysv.S deleted file mode 100644 index ec2b14f3d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m68k/sysv.S +++ /dev/null @@ -1,330 +0,0 @@ -/* ----------------------------------------------------------------------- - - sysv.S - Copyright (c) 2012 Alan Hourihane - Copyright (c) 1998, 2012 Andreas Schwab - Copyright (c) 2008 Red Hat, Inc. - Copyright (c) 2012 Thorsten Glaser - - m68k Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#ifdef HAVE_AS_CFI_PSEUDO_OP -#define CFI_STARTPROC() .cfi_startproc -#define CFI_OFFSET(reg,off) .cfi_offset reg,off -#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off -#define CFI_ENDPROC() .cfi_endproc -#else -#define CFI_STARTPROC() -#define CFI_OFFSET(reg,off) -#define CFI_DEF_CFA(reg,off) -#define CFI_ENDPROC() -#endif - -#ifdef __MINT__ -#define CALLFUNC(funcname) _ ## funcname -#else -#define CALLFUNC(funcname) funcname -#endif - - .text - - .globl CALLFUNC(ffi_call_SYSV) - .type CALLFUNC(ffi_call_SYSV),@function - .align 4 - -CALLFUNC(ffi_call_SYSV): - CFI_STARTPROC() - link %fp,#0 - CFI_OFFSET(14,-8) - CFI_DEF_CFA(14,8) - move.l %d2,-(%sp) - CFI_OFFSET(2,-12) - - | Make room for all of the new args. - sub.l 12(%fp),%sp - - | Call ffi_prep_args - move.l 8(%fp),-(%sp) - pea 4(%sp) -#if !defined __PIC__ - jsr CALLFUNC(ffi_prep_args) -#else - bsr.l CALLFUNC(ffi_prep_args@PLTPC) -#endif - addq.l #8,%sp - - | Pass pointer to struct value, if any -#ifdef __MINT__ - move.l %d0,%a1 -#else - move.l %a0,%a1 -#endif - - | Call the function - move.l 24(%fp),%a0 - jsr (%a0) - - | Remove the space we pushed for the args - add.l 12(%fp),%sp - - | Load the pointer to storage for the return value - move.l 20(%fp),%a1 - - | Load the return type code - move.l 16(%fp),%d2 - - | If the return value pointer is NULL, assume no return value. - | NOTE: On the mc68000, tst on an address register is not supported. -#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) - cmp.w #0, %a1 -#else - tst.l %a1 -#endif - jbeq noretval - - btst #0,%d2 - jbeq retlongint - move.l %d0,(%a1) - jbra epilogue - -retlongint: - btst #1,%d2 - jbeq retfloat - move.l %d0,(%a1) - move.l %d1,4(%a1) - jbra epilogue - -retfloat: - btst #2,%d2 - jbeq retdouble -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.s %fp0,(%a1) -#else - move.l %d0,(%a1) -#endif - jbra epilogue - -retdouble: - btst #3,%d2 - jbeq retlongdouble -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.d %fp0,(%a1) -#else - move.l %d0,(%a1)+ - move.l %d1,(%a1) -#endif - jbra epilogue - -retlongdouble: - btst #4,%d2 - jbeq retpointer -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.x %fp0,(%a1) -#else - move.l %d0,(%a1)+ - move.l %d1,(%a1)+ - move.l %d2,(%a1) -#endif - jbra epilogue - -retpointer: - btst #5,%d2 - jbeq retstruct1 -#ifdef __MINT__ - move.l %d0,(%a1) -#else - move.l %a0,(%a1) -#endif - jbra epilogue - -retstruct1: - btst #6,%d2 - jbeq retstruct2 - move.b %d0,(%a1) - jbra epilogue - -retstruct2: - btst #7,%d2 - jbeq retsint8 - move.w %d0,(%a1) - jbra epilogue - -retsint8: - btst #8,%d2 - jbeq retsint16 - | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32. -#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) - ext.w %d0 - ext.l %d0 -#else - extb.l %d0 -#endif - move.l %d0,(%a1) - jbra epilogue - -retsint16: - btst #9,%d2 - jbeq noretval - ext.l %d0 - move.l %d0,(%a1) - -noretval: -epilogue: - move.l (%sp)+,%d2 - unlk %fp - rts - CFI_ENDPROC() - .size CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV) - - .globl CALLFUNC(ffi_closure_SYSV) - .type CALLFUNC(ffi_closure_SYSV), @function - .align 4 - -CALLFUNC(ffi_closure_SYSV): - CFI_STARTPROC() - link %fp,#-12 - CFI_OFFSET(14,-8) - CFI_DEF_CFA(14,8) - move.l %sp,-12(%fp) - pea 8(%fp) - pea -12(%fp) - move.l %a0,-(%sp) -#if !defined __PIC__ - jsr CALLFUNC(ffi_closure_SYSV_inner) -#else - bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) -#endif - - lsr.l #1,%d0 - jne 1f - jcc .Lcls_epilogue - | CIF_FLAGS_INT - move.l -12(%fp),%d0 -.Lcls_epilogue: - | no CIF_FLAGS_* - unlk %fp - rts -1: - lea -12(%fp),%a0 - lsr.l #2,%d0 - jne 1f - jcs .Lcls_ret_float - | CIF_FLAGS_DINT - move.l (%a0)+,%d0 - move.l (%a0),%d1 - jra .Lcls_epilogue -.Lcls_ret_float: -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.s (%a0),%fp0 -#else - move.l (%a0),%d0 -#endif - jra .Lcls_epilogue -1: - lsr.l #2,%d0 - jne 1f - jcs .Lcls_ret_ldouble - | CIF_FLAGS_DOUBLE -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.d (%a0),%fp0 -#else - move.l (%a0)+,%d0 - move.l (%a0),%d1 -#endif - jra .Lcls_epilogue -.Lcls_ret_ldouble: -#if defined(__MC68881__) || defined(__HAVE_68881__) - fmove.x (%a0),%fp0 -#else - move.l (%a0)+,%d0 - move.l (%a0)+,%d1 - move.l (%a0),%d2 -#endif - jra .Lcls_epilogue -1: - lsr.l #2,%d0 - jne 1f - jcs .Lcls_ret_struct1 - | CIF_FLAGS_POINTER - move.l (%a0),%a0 - move.l %a0,%d0 - jra .Lcls_epilogue -.Lcls_ret_struct1: - move.b (%a0),%d0 - jra .Lcls_epilogue -1: - lsr.l #2,%d0 - jne 1f - jcs .Lcls_ret_sint8 - | CIF_FLAGS_STRUCT2 - move.w (%a0),%d0 - jra .Lcls_epilogue -.Lcls_ret_sint8: - move.l (%a0),%d0 - | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32. -#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) - ext.w %d0 - ext.l %d0 -#else - extb.l %d0 -#endif - jra .Lcls_epilogue -1: - | CIF_FLAGS_SINT16 - move.l (%a0),%d0 - ext.l %d0 - jra .Lcls_epilogue - CFI_ENDPROC() - - .size CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV) - - .globl CALLFUNC(ffi_closure_struct_SYSV) - .type CALLFUNC(ffi_closure_struct_SYSV), @function - .align 4 - -CALLFUNC(ffi_closure_struct_SYSV): - CFI_STARTPROC() - link %fp,#0 - CFI_OFFSET(14,-8) - CFI_DEF_CFA(14,8) - move.l %sp,-12(%fp) - pea 8(%fp) - move.l %a1,-(%sp) - move.l %a0,-(%sp) -#if !defined __PIC__ - jsr CALLFUNC(ffi_closure_SYSV_inner) -#else - bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) -#endif - unlk %fp - rts - CFI_ENDPROC() - .size CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV) - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffi.c deleted file mode 100644 index 68df49495..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffi.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * m88k Foreign Function Interface - * - * This file attempts to provide all the FFI entry points which can reliably - * be implemented in C. - * - * Only OpenBSD/m88k is currently supported; other platforms (such as - * Motorola's SysV/m88k) could be supported with the following tweaks: - * - * - non-OpenBSD systems use an `outgoing parameter area' as part of the - * 88BCS calling convention, which is not supported under OpenBSD from - * release 3.6 onwards. Supporting it should be as easy as taking it - * into account when adjusting the stack, in the assembly code. - * - * - the logic deciding whether a function argument gets passed through - * registers, or on the stack, has changed several times in OpenBSD in - * edge cases (especially for structs larger than 32 bytes being passed - * by value). The code below attemps to match the logic used by the - * system compiler of OpenBSD 5.3, i.e. gcc 3.3.6 with many m88k backend - * fixes. - */ - -#include -#include - -#include -#include - -void ffi_call_OBSD (unsigned int, extended_cif *, unsigned int, void *, - void (*fn) ()); -void *ffi_prep_args (void *, extended_cif *); -void ffi_closure_OBSD (ffi_closure *); -void ffi_closure_struct_OBSD (ffi_closure *); -unsigned int ffi_closure_OBSD_inner (ffi_closure *, void *, unsigned int *, - char *); -void ffi_cacheflush_OBSD (unsigned int, unsigned int); - -#define CIF_FLAGS_INT (1 << 0) -#define CIF_FLAGS_DINT (1 << 1) - -/* - * Foreign Function Interface API - */ - -/* ffi_prep_args is called by the assembly routine once stack space has - been allocated for the function's arguments. */ - -void * -ffi_prep_args (void *stack, extended_cif *ecif) -{ - unsigned int i; - void **p_argv; - char *argp, *stackp; - unsigned int *regp; - unsigned int regused; - ffi_type **p_arg; - void *struct_value_ptr; - - regp = (unsigned int *)stack; - stackp = (char *)(regp + 8); - regused = 0; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT - && !ecif->cif->flags) - struct_value_ptr = ecif->rvalue; - else - struct_value_ptr = NULL; - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i != 0; i--, p_arg++) - { - size_t z; - unsigned short t, a; - - z = (*p_arg)->size; - t = (*p_arg)->type; - a = (*p_arg)->alignment; - - /* - * Figure out whether the argument can be passed through registers - * or on the stack. - * The rule is that registers can only receive simple types not larger - * than 64 bits, or structs the exact size of a register and aligned to - * the size of a register. - */ - if (t == FFI_TYPE_STRUCT) - { - if (z == sizeof (int) && a == sizeof (int) && regused < 8) - argp = (char *)regp; - else - argp = stackp; - } - else - { - if (z > sizeof (int) && regused < 8 - 1) - { - /* align to an even register pair */ - if (regused & 1) - { - regp++; - regused++; - } - } - if (regused < 8) - argp = (char *)regp; - else - argp = stackp; - } - - /* Enforce proper stack alignment of 64-bit types */ - if (argp == stackp && a > sizeof (int)) - { - stackp = (char *) ALIGN(stackp, a); - argp = stackp; - } - - switch (t) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) *p_argv; - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv; - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) *p_argv; - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_FLOAT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - *(unsigned int *) argp = *(unsigned int *) *p_argv; - break; - - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_STRUCT: - memcpy (argp, *p_argv, z); - break; - - default: - FFI_ASSERT (0); - } - - /* Align if necessary. */ - if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); - - p_argv++; - - /* Be careful, once all registers are filled, and about to continue - on stack, regp == stackp. Therefore the check for regused as well. */ - if (argp == (char *)regp && regused < 8) - { - regp += z / sizeof (int); - regused += z / sizeof (int); - } - else - stackp += z; - } - - return struct_value_ptr; -} - -/* Perform machine dependent cif processing */ -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - cif->flags = 0; - break; - - case FFI_TYPE_STRUCT: - if (cif->rtype->size == sizeof (int) && - cif->rtype->alignment == sizeof (int)) - cif->flags = CIF_FLAGS_INT; - else - cif->flags = 0; - break; - - case FFI_TYPE_DOUBLE: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = CIF_FLAGS_DINT; - break; - - default: - cif->flags = CIF_FLAGS_INT; - break; - } - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return value - address then we need to make one. */ - - if (rvalue == NULL - && cif->rtype->type == FFI_TYPE_STRUCT - && (cif->rtype->size != sizeof (int) - || cif->rtype->alignment != sizeof (int))) - ecif.rvalue = alloca (cif->rtype->size); - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_OBSD: - ffi_call_OBSD (cif->bytes, &ecif, cif->flags, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; - } -} - -/* - * Closure API - */ - -static void -ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp, - char *stackp) -{ - unsigned int i; - void **p_argv; - char *argp; - unsigned int regused; - ffi_type **p_arg; - - regused = 0; - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++) - { - size_t z; - unsigned short t, a; - - z = (*p_arg)->size; - t = (*p_arg)->type; - a = (*p_arg)->alignment; - - /* - * Figure out whether the argument has been passed through registers - * or on the stack. - * The rule is that registers can only receive simple types not larger - * than 64 bits, or structs the exact size of a register and aligned to - * the size of a register. - */ - if (t == FFI_TYPE_STRUCT) - { - if (z == sizeof (int) && a == sizeof (int) && regused < 8) - argp = (char *)regp; - else - argp = stackp; - } - else - { - if (z > sizeof (int) && regused < 8 - 1) - { - /* align to an even register pair */ - if (regused & 1) - { - regp++; - regused++; - } - } - if (regused < 8) - argp = (char *)regp; - else - argp = stackp; - } - - /* Enforce proper stack alignment of 64-bit types */ - if (argp == stackp && a > sizeof (int)) - { - stackp = (char *) ALIGN(stackp, a); - argp = stackp; - } - - if (z < sizeof (int) && t != FFI_TYPE_STRUCT) - *p_argv = (void *) (argp + sizeof (int) - z); - else - *p_argv = (void *) argp; - - /* Align if necessary */ - if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); - - p_argv++; - - /* Be careful, once all registers are exhausted, and about to fetch from - stack, regp == stackp. Therefore the check for regused as well. */ - if (argp == (char *)regp && regused < 8) - { - regp += z / sizeof (int); - regused += z / sizeof (int); - } - else - stackp += z; - } -} - -unsigned int -ffi_closure_OBSD_inner (ffi_closure *closure, void *resp, unsigned int *regp, - char *stackp) -{ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void *)); - - ffi_prep_closure_args_OBSD(cif, arg_area, regp, stackp); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - return cif->flags; -} - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, void *codeloc) -{ - unsigned int *tramp = (unsigned int *) codeloc; - void *fn; - - FFI_ASSERT (cif->abi == FFI_OBSD); - - if (cif->rtype->type == FFI_TYPE_STRUCT && !cif->flags) - fn = &ffi_closure_struct_OBSD; - else - fn = &ffi_closure_OBSD; - - /* or.u %r10, %r0, %hi16(fn) */ - tramp[0] = 0x5d400000 | (((unsigned int)fn) >> 16); - /* or.u %r13, %r0, %hi16(closure) */ - tramp[1] = 0x5da00000 | ((unsigned int)closure >> 16); - /* or %r10, %r10, %lo16(fn) */ - tramp[2] = 0x594a0000 | (((unsigned int)fn) & 0xffff); - /* jmp.n %r10 */ - tramp[3] = 0xf400c40a; - /* or %r13, %r13, %lo16(closure) */ - tramp[4] = 0x59ad0000 | ((unsigned int)closure & 0xffff); - - ffi_cacheflush_OBSD((unsigned int)codeloc, FFI_TRAMPOLINE_SIZE); - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffitarget.h deleted file mode 100644 index e52bf9fa3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/ffitarget.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * m88k Foreign Function Interface - */ - -#ifndef LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_OBSD, - FFI_DEFAULT_ABI = FFI_OBSD, - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 0x14 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/obsd.S b/ruby/ext/fiddle/libffi-3.2.1/src/m88k/obsd.S deleted file mode 100644 index 1944a23de..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/m88k/obsd.S +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * m88k Foreign Function Interface - */ - -#define LIBFFI_ASM -#include -#include - - .text - -/* - * ffi_cacheflush_OBSD(unsigned int addr, %r2 - * unsigned int size); %r3 - */ - .align 4 - .globl ffi_cacheflush_OBSD - .type ffi_cacheflush_OBSD,@function -ffi_cacheflush_OBSD: - tb0 0, %r0, 451 - or %r0, %r0, %r0 - jmp %r1 - .size ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD - -/* - * ffi_call_OBSD(unsigned bytes, %r2 - * extended_cif *ecif, %r3 - * unsigned flags, %r4 - * void *rvalue, %r5 - * void (*fn)()); %r6 - */ - .align 4 - .globl ffi_call_OBSD - .type ffi_call_OBSD,@function -ffi_call_OBSD: - subu %r31, %r31, 32 - st %r30, %r31, 4 - st %r1, %r31, 0 - addu %r30, %r31, 32 - - | Save the few arguments we'll need after ffi_prep_args() - st.d %r4, %r31, 8 - st %r6, %r31, 16 - - | Allocate room for the image of r2-r9, and the stack space for - | the args (rounded to a 16-byte boundary) - addu %r2, %r2, (8 * 4) + 15 - clr %r2, %r2, 4<0> - subu %r31, %r31, %r2 - - | Fill register and stack image - or %r2, %r31, %r0 -#ifdef PIC - bsr ffi_prep_args#plt -#else - bsr ffi_prep_args -#endif - - | Save pointer to return struct address, if any - or %r12, %r2, %r0 - - | Get function pointer - subu %r4, %r30, 32 - ld %r1, %r4, 16 - - | Fetch the register arguments - ld.d %r2, %r31, (0 * 4) - ld.d %r4, %r31, (2 * 4) - ld.d %r6, %r31, (4 * 4) - ld.d %r8, %r31, (6 * 4) - addu %r31, %r31, (8 * 4) - - | Invoke the function - jsr %r1 - - | Restore stack now that we don't need the args anymore - subu %r31, %r30, 32 - - | Figure out what to return as the function's return value - ld %r5, %r31, 12 | rvalue - ld %r4, %r31, 8 | flags - - bcnd eq0, %r5, 9f - - bb0 0, %r4, 1f | CIF_FLAGS_INT - st %r2, %r5, 0 - br 9f - -1: - bb0 1, %r4, 1f | CIF_FLAGS_DINT - st.d %r2, %r5, 0 - br 9f - -1: -9: - ld %r1, %r31, 0 - ld %r30, %r31, 4 - jmp.n %r1 - addu %r31, %r31, 32 - .size ffi_call_OBSD, . - ffi_call_OBSD - -/* - * ffi_closure_OBSD(ffi_closure *closure); %r13 - */ - .align 4 - .globl ffi_closure_OBSD - .type ffi_closure_OBSD, @function -ffi_closure_OBSD: - subu %r31, %r31, 16 - st %r30, %r31, 4 - st %r1, %r31, 0 - addu %r30, %r31, 16 - - | Make room on the stack for saved register arguments and return - | value - subu %r31, %r31, (8 * 4) + (2 * 4) - st.d %r2, %r31, (0 * 4) - st.d %r4, %r31, (2 * 4) - st.d %r6, %r31, (4 * 4) - st.d %r8, %r31, (6 * 4) - - | Invoke the closure function - or %r5, %r30, 0 | calling stack - addu %r4, %r31, 0 | saved registers - addu %r3, %r31, (8 * 4) | return value - or %r2, %r13, %r0 | closure -#ifdef PIC - bsr ffi_closure_OBSD_inner#plt -#else - bsr ffi_closure_OBSD_inner -#endif - - | Figure out what to return as the function's return value - bb0 0, %r2, 1f | CIF_FLAGS_INT - ld %r2, %r31, (8 * 4) - br 9f - -1: - bb0 1, %r2, 1f | CIF_FLAGS_DINT - ld.d %r2, %r31, (8 * 4) - br 9f - -1: -9: - subu %r31, %r30, 16 - ld %r1, %r31, 0 - ld %r30, %r31, 4 - jmp.n %r1 - addu %r31, %r31, 16 - .size ffi_closure_OBSD,.-ffi_closure_OBSD - -/* - * ffi_closure_struct_OBSD(ffi_closure *closure); %r13 - */ - .align 4 - .globl ffi_closure_struct_OBSD - .type ffi_closure_struct_OBSD, @function -ffi_closure_struct_OBSD: - subu %r31, %r31, 16 - st %r30, %r31, 4 - st %r1, %r31, 0 - addu %r30, %r31, 16 - - | Make room on the stack for saved register arguments - subu %r31, %r31, (8 * 4) - st.d %r2, %r31, (0 * 4) - st.d %r4, %r31, (2 * 4) - st.d %r6, %r31, (4 * 4) - st.d %r8, %r31, (6 * 4) - - | Invoke the closure function - or %r5, %r30, 0 | calling stack - addu %r4, %r31, 0 | saved registers - or %r3, %r12, 0 | return value - or %r2, %r13, %r0 | closure -#ifdef PIC - bsr ffi_closure_OBSD_inner#plt -#else - bsr ffi_closure_OBSD_inner -#endif - - subu %r31, %r30, 16 - ld %r1, %r31, 0 - ld %r30, %r31, 4 - jmp.n %r1 - addu %r31, %r31, 16 - .size ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffi.c deleted file mode 100644 index 46b383e7a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffi.c +++ /dev/null @@ -1,330 +0,0 @@ -/* ---------------------------------------------------------------------- - ffi.c - Copyright (c) 2013 Imagination Technologies - - Meta Foreign Function Interface - 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 SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------ */ - -#include -#include - -#include - -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) - -/* - * ffi_prep_args is called by the assembly routine once stack space has been - * allocated for the function's arguments - */ - -unsigned int ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - - /* Store return value */ - if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { - argp -= 4; - *(void **) argp = ecif->rvalue; - } - - p_argv = ecif->avalue; - - /* point to next location */ - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++) - { - size_t z; - - /* Move argp to address of argument */ - z = (*p_arg)->size; - argp -= z; - - /* Align if necessary */ - argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4); - - if (z < sizeof(int)) { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - case FFI_TYPE_STRUCT: - memcpy(argp, *p_argv, (*p_arg)->size); - break; - default: - FFI_ASSERT(0); - } - } else if ( z == sizeof(int)) { - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - } else { - memcpy(argp, *p_argv, z); - } - } - - /* return the size of the arguments to be passed in registers, - padded to an 8 byte boundary to preserve stack alignment */ - return ALIGN(MIN(stack - argp, 6*4), 8); -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - ffi_type **ptr; - unsigned i, bytes = 0; - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) { - if ((*ptr)->size == 0) - return FFI_BAD_TYPEDEF; - - /* Perform a sanity check on the argument type, do this - check after the initialization. */ - FFI_ASSERT_VALID_TYPE(*ptr); - - /* Add any padding if necessary */ - if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN(bytes, (*ptr)->alignment); - - bytes += ALIGN((*ptr)->size, 4); - } - - /* Ensure arg space is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); - - /* Make space for the return structure pointer */ - if (cif->rtype->type == FFI_TYPE_STRUCT) { - bytes += sizeof(void*); - - /* Ensure stack is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); - } - - cif->bytes = bytes; - - /* Set the return type flag */ - switch (cif->rtype->type) { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags = (unsigned) cif->rtype->type; - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = (unsigned) FFI_TYPE_SINT64; - break; - case FFI_TYPE_STRUCT: - /* Meta can store return values which are <= 64 bits */ - if (cif->rtype->size <= 4) - /* Returned to D0Re0 as 32-bit value */ - cif->flags = (unsigned)FFI_TYPE_INT; - else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8)) - /* Returned valued is stored to D1Re0|R0Re0 */ - cif->flags = (unsigned)FFI_TYPE_DOUBLE; - else - /* value stored in memory */ - cif->flags = (unsigned)FFI_TYPE_STRUCT; - break; - default: - cif->flags = (unsigned)FFI_TYPE_INT; - break; - } - return FFI_OK; -} - -extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *); - -/* - * Exported in API. Entry point - * cif -> ffi_cif object - * fn -> function pointer - * rvalue -> pointer to return value - * avalue -> vector of void * pointers pointing to memory locations holding the - * arguments - */ -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT)); - ecif.cif = cif; - ecif.avalue = avalue; - - double temp; - - /* - * If the return value is a struct and we don't have a return value address - * then we need to make one - */ - - if ((rvalue == NULL ) && (cif->flags == FFI_TYPE_STRUCT)) - ecif.rvalue = alloca(cif->rtype->size); - else if (small_struct) - ecif.rvalue = &temp; - else - ecif.rvalue = rvalue; - - switch (cif->abi) { - case FFI_SYSV: - ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); - break; - default: - FFI_ASSERT(0); - break; - } - - if (small_struct) - memcpy (rvalue, &temp, cif->rtype->size); -} - -/* private members */ - -static void ffi_prep_incoming_args_SYSV (char *, void **, void **, - ffi_cif*, float *); - -void ffi_closure_SYSV (ffi_closure *); - -/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */ -extern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */ - -/* end of private members */ - -/* - * __tramp: trampoline memory location - * __fun: assembly routine - * __ctx: memory location for wrapper - * - * At this point, tramp[0] == __ctx ! - */ -void ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) { - memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline)); - *(unsigned int*) &__tramp[40] = __ctx; - *(unsigned int*) &__tramp[44] = __fun; - /* This will flush the instruction cache */ - __builtin_meta2_cachewd(&__tramp[0], 1); - __builtin_meta2_cachewd(&__tramp[47], 1); -} - - - -/* the cif must already be prepared */ - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - void (*closure_func)(ffi_closure*) = NULL; - - if (cif->abi == FFI_SYSV) - closure_func = &ffi_closure_SYSV; - else - return FFI_BAD_ABI; - - ffi_init_trampoline( - (unsigned char*)&closure->tramp[0], - (unsigned int)closure_func, - (unsigned int)codeloc); - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - - -/* This function is jumped to by the trampoline */ -unsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args) - ffi_closure *closure; - void **respp; - void *args; - void *vfp_args; -{ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* - * This call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will re-set RESP to point to the - * structure return address. - */ - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); - - (closure->fun) ( cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} - -static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif, - float *vfp_stack) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - /* stack points to original arguments */ - argp = stack; - - /* Store return value */ - if ( cif->flags == FFI_TYPE_STRUCT ) { - argp -= 4; - *rvalue = *(void **) argp; - } - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) { - size_t z; - size_t alignment; - - alignment = (*p_arg)->alignment; - if (alignment < 4) - alignment = 4; - if ((alignment - 1) & (unsigned)argp) - argp = (char *) ALIGN(argp, alignment); - - z = (*p_arg)->size; - *p_argv = (void*) argp; - p_argv++; - argp -= z; - } - return; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffitarget.h deleted file mode 100644 index 7b9dbebca..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/metag/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2013 Imagination Technologies Ltd. - Target configuration macros for Meta - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_DEFAULT_ABI = FFI_SYSV, - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1, -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 48 -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/metag/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/metag/sysv.S deleted file mode 100644 index b4b2a3b26..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/metag/sysv.S +++ /dev/null @@ -1,311 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 Imagination Technologies Ltd. - - Meta Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -#ifdef __USER_LABEL_PREFIX__ -#define CONCAT1(a, b) CONCAT2(a, b) -#define CONCAT2(a, b) a ## b - -/* Use the right prefix for global labels. */ -#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x) -#else -#define CNAME(x) x -#endif -#define ENTRY(x) .globl CNAME(x); .type CNAME(x), %function; CNAME(x): -#endif - -#ifdef __ELF__ -#define LSYM(x) .x -#else -#define LSYM(x) x -#endif - -.macro call_reg x= - .text - .balign 4 - mov D1RtP, \x - swap D1RtP, PC -.endm - -! Save register arguments -.macro SAVE_ARGS - .text - .balign 4 - setl [A0StP++], D0Ar6, D1Ar5 - setl [A0StP++], D0Ar4, D1Ar3 - setl [A0StP++], D0Ar2, D1Ar1 -.endm - -! Save retrun, frame pointer and other regs -.macro SAVE_REGS regs= - .text - .balign 4 - setl [A0StP++], D0FrT, D1RtP - ! Needs to be a pair of regs - .ifnc "\regs","" - setl [A0StP++], \regs - .endif -.endm - -! Declare a global function -.macro METAG_FUNC_START name - .text - .balign 4 - ENTRY(\name) -.endm - -! Return registers from the stack. Reverse SAVE_REGS operation -.macro RET_REGS regs=, cond= - .ifnc "\regs", "" - getl \regs, [--A0StP] - .endif - getl D0FrT, D1RtP, [--A0StP] -.endm - -! Return arguments -.macro RET_ARGS - getl D0Ar2, D1Ar1, [--A0StP] - getl D0Ar4, D1Ar3, [--A0StP] - getl D0Ar6, D1Ar5, [--A0StP] -.endm - - - ! D1Ar1: fn - ! D0Ar2: &ecif - ! D1Ar3: cif->bytes - ! D0Ar4: fig->flags - ! D1Ar5: ecif.rvalue - - ! This assumes we are using GNU as -METAG_FUNC_START ffi_call_SYSV - ! Save argument registers - - SAVE_ARGS - - ! new frame - mov D0FrT, A0FrP - add A0FrP, A0StP, #0 - - ! Preserve the old frame pointer - SAVE_REGS "D1.5, D0.5" - - ! Make room for new args. cifs->bytes is the total space for input - ! and return arguments - - add A0StP, A0StP, D1Ar3 - - ! Preserve cifs->bytes & fn - mov D0.5, D1Ar3 - mov D1.5, D1Ar1 - - ! Place all of the ffi_prep_args in position - mov D1Ar1, A0StP - - ! Call ffi_prep_args(stack, &ecif) -#ifdef __PIC__ - callr D1RtP, CNAME(ffi_prep_args@PLT) -#else - callr D1RtP, CNAME(ffi_prep_args) -#endif - - ! Restore fn pointer - - ! The foreign stack should look like this - ! XXXXX XXXXXX <--- stack pointer - ! FnArgN rvalue - ! FnArgN+2 FnArgN+1 - ! FnArgN+4 FnArgN+3 - ! .... - ! - - ! A0StP now points to the first (or return) argument + 4 - - ! Preserve cif->bytes - getl D0Ar2, D1Ar1, [--A0StP] - getl D0Ar4, D1Ar3, [--A0StP] - getl D0Ar6, D1Ar5, [--A0StP] - - ! Place A0StP to the first argument again - add A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each - - ! A0FrP points to the initial stack without the reserved space for the - ! cifs->bytes, whilst A0StP points to the stack after the space allocation - - ! fn was the first argument of ffi_call_SYSV. - ! The stack at this point looks like this: - ! - ! A0StP(on entry to _SYSV) -> Arg6 Arg5 | low - ! Arg4 Arg3 | - ! Arg2 Arg1 | - ! A0FrP ----> D0FrtP D1RtP | - ! D1.5 D0.5 | - ! A0StP(bf prep_args) -> FnArgn FnArgn-1 | - ! FnArgn-2FnArgn-3 | - ! ................ | <= cifs->bytes - ! FnArg4 FnArg3 | - ! A0StP (prv_A0StP+cifs->bytes) FnArg2 FnArg1 | high - ! - ! fn was in Arg1 so it's located in in A0FrP+#-0xC - ! - - ! D0Re0 contains the size of arguments stored in registers - sub A0StP, A0StP, D0Re0 - - ! Arg1 is the function pointer for the foreign call. This has been - ! preserved in D1.5 - - ! Time to call (fn). Arguments should be like this: - ! Arg1-Arg6 are loaded to regs - ! The rest of the arguments are stored in stack pointed by A0StP - - call_reg D1.5 - - ! Reset stack. - - mov A0StP, A0FrP - - ! Load Arg1 with the pointer to storage for the return type - ! This was stored in Arg5 - - getd D1Ar1, [A0FrP+#-20] - - ! Load D0Ar2 with the return type code. This was stored in Arg4 (flags) - - getd D0Ar2, [A0FrP+#-16] - - ! We are ready to start processing the return value - ! D0Re0 (and D1Re0) hold the return value - - ! If the return value is NULL, assume no return value - cmp D1Ar1, #0 - beq LSYM(Lepilogue) - - ! return INT - cmp D0Ar2, #FFI_TYPE_INT - ! Sadly, there is no setd{cc} instruction so we need to workaround that - bne .INT64 - setd [D1Ar1], D0Re0 - b LSYM(Lepilogue) - - ! return INT64 -.INT64: - cmp D0Ar2, #FFI_TYPE_SINT64 - setleq [D1Ar1], D0Re0, D1Re0 - - ! return DOUBLE - cmp D0Ar2, #FFI_TYPE_DOUBLE - setl [D1AR1++], D0Re0, D1Re0 - -LSYM(Lepilogue): - ! At this point, the stack pointer points right after the argument - ! saved area. We need to restore 4 regs, therefore we need to move - ! 16 bytes ahead. - add A0StP, A0StP, #16 - RET_REGS "D1.5, D0.5" - RET_ARGS - getd D0Re0, [A0StP] - mov A0FrP, D0FrT - swap D1RtP, PC - -.ffi_call_SYSV_end: - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) - - -/* - (called by ffi_metag_trampoline) - void ffi_closure_SYSV (ffi_closure*) - - (called by ffi_closure_SYSV) - unsigned int FFI_HIDDEN - ffi_closure_SYSV_inner (closure,respp, args) - ffi_closure *closure; - void **respp; - void *args; -*/ - -METAG_FUNC_START ffi_closure_SYSV - ! We assume that D1Ar1 holds the address of the - ! ffi_closure struct. We will use that to fetch the - ! arguments. The stack pointer points to an empty space - ! and it is ready to store more data. - - ! D1Ar1 is ready - ! Allocate stack space for return value - add A0StP, A0StP, #8 - ! Store it to D0Ar2 - sub D0Ar2, A0StP, #8 - - sub D1Ar3, A0FrP, #4 - - ! D1Ar3 contains the address of the original D1Ar1 argument - ! We need to subtract #4 later on - - ! Preverve D0Ar2 - mov D0.5, D0Ar2 - -#ifdef __PIC__ - callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT) -#else - callr D1RtP, CNAME(ffi_closure_SYSV_inner) -#endif - - ! Check the return value and store it to D0.5 - cmp D0Re0, #FFI_TYPE_INT - beq .Lretint - cmp D0Re0, #FFI_TYPE_DOUBLE - beq .Lretdouble -.Lclosure_epilogue: - sub A0StP, A0StP, #8 - RET_REGS "D1.5, D0.5" - RET_ARGS - swap D1RtP, PC - -.Lretint: - setd [D0.5], D0Re0 - b .Lclosure_epilogue -.Lretdouble: - setl [D0.5++], D0Re0, D1Re0 - b .Lclosure_epilogue -.ffi_closure_SYSV_end: -.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) - - -ENTRY(ffi_metag_trampoline) - SAVE_ARGS - ! New frame - mov A0FrP, A0StP - SAVE_REGS "D1.5, D0.5" - mov D0.5, PC - ! Load D1Ar1 the value of ffi_metag_trampoline - getd D1Ar1, [D0.5 + #8] - ! Jump to ffi_closure_SYSV - getd PC, [D0.5 + #12] diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffi.c deleted file mode 100644 index ea962ea48..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffi.c +++ /dev/null @@ -1,321 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc - - MicroBlaze Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*, - unsigned int, unsigned int, unsigned int*, void (*fn)(void), - unsigned int, unsigned int); - -extern void ffi_closure_SYSV(void); - -#define WORD_SIZE sizeof(unsigned int) -#define ARGS_REGISTER_SIZE (WORD_SIZE * 6) -#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE) - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ -void ffi_prep_args(void* stack, extended_cif* ecif) -{ - unsigned int i; - ffi_type** p_arg; - void** p_argv; - void* stack_args_p = stack; - - p_argv = ecif->avalue; - - if (ecif == NULL || ecif->cif == NULL) { - return; /* no description to prepare */ - } - - if ((ecif->cif->rtype != NULL) && - (ecif->cif->rtype->type == FFI_TYPE_STRUCT)) - { - /* if return type is a struct which is referenced on the stack/reg5, - * by a pointer. Stored the return value pointer in r5. - */ - char* addr = stack_args_p; - memcpy(addr, &(ecif->rvalue), WORD_SIZE); - stack_args_p += WORD_SIZE; - } - - if (ecif->avalue == NULL) { - return; /* no arguments to prepare */ - } - - for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; - i++, p_arg++) - { - size_t size = (*p_arg)->size; - int type = (*p_arg)->type; - void* value = p_argv[i]; - char* addr = stack_args_p; - int aligned_size = WORD_ALIGN(size); - - /* force word alignment on the stack */ - stack_args_p += aligned_size; - - switch (type) - { - case FFI_TYPE_UINT8: - *(unsigned int *)addr = (unsigned int)*(UINT8*)(value); - break; - case FFI_TYPE_SINT8: - *(signed int *)addr = (signed int)*(SINT8*)(value); - break; - case FFI_TYPE_UINT16: - *(unsigned int *)addr = (unsigned int)*(UINT16*)(value); - break; - case FFI_TYPE_SINT16: - *(signed int *)addr = (signed int)*(SINT16*)(value); - break; - case FFI_TYPE_STRUCT: -#if __BIG_ENDIAN__ - /* - * MicroBlaze toolchain appears to emit: - * bsrli r5, r5, 8 (caller) - * ... - * - * ... - * bslli r5, r5, 8 (callee) - * - * For structs like "struct a { uint8_t a[3]; };", when passed - * by value. - * - * Structs like "struct b { uint16_t a; };" are also expected - * to be packed strangely in registers. - * - * This appears to be because the microblaze toolchain expects - * "struct b == uint16_t", which is only any issue for big - * endian. - * - * The following is a work around for big-endian only, for the - * above mentioned case, it will re-align the contents of a - * <= 3-byte struct value. - */ - if (size < WORD_SIZE) - { - memcpy (addr + (WORD_SIZE - size), value, size); - break; - } -#endif - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: - default: - memcpy(addr, value, aligned_size); - } - } -} - -ffi_status ffi_prep_cif_machdep(ffi_cif* cif) -{ - /* check ABI */ - switch (cif->abi) - { - case FFI_SYSV: - break; - default: - return FFI_BAD_ABI; - } - return FFI_OK; -} - -void ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue) -{ - extended_cif ecif; - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { - ecif.rvalue = alloca(cif->rtype->size); - } else { - ecif.rvalue = rvalue; - } - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn, cif->rtype->type, cif->rtype->size); - break; - default: - FFI_ASSERT(0); - break; - } -} - -void ffi_closure_call_SYSV(void* register_args, void* stack_args, - ffi_closure* closure, void* rvalue, - unsigned int* rtype, unsigned int* rsize) -{ - /* prepare arguments for closure call */ - ffi_cif* cif = closure->cif; - ffi_type** arg_types = cif->arg_types; - - /* re-allocate data for the args. This needs to be done in order to keep - * multi-word objects (e.g. structs) in contiguous memory. Callers are not - * required to store the value of args in the lower 6 words in the stack - * (although they are allocated in the stack). - */ - char* stackclone = alloca(cif->bytes); - void** avalue = alloca(cif->nargs * sizeof(void*)); - void* struct_rvalue = NULL; - char* ptr = stackclone; - int i; - - /* copy registers into stack clone */ - int registers_used = cif->bytes; - if (registers_used > ARGS_REGISTER_SIZE) { - registers_used = ARGS_REGISTER_SIZE; - } - memcpy(stackclone, register_args, registers_used); - - /* copy stack allocated args into stack clone */ - if (cif->bytes > ARGS_REGISTER_SIZE) { - int stack_used = cif->bytes - ARGS_REGISTER_SIZE; - memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used); - } - - /* preserve struct type return pointer passing */ - if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { - struct_rvalue = *((void**)ptr); - ptr += WORD_SIZE; - } - - /* populate arg pointer list */ - for (i = 0; i < cif->nargs; i++) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: -#ifdef __BIG_ENDIAN__ - avalue[i] = ptr + 3; -#else - avalue[i] = ptr; -#endif - break; - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: -#ifdef __BIG_ENDIAN__ - avalue[i] = ptr + 2; -#else - avalue[i] = ptr; -#endif - break; - case FFI_TYPE_STRUCT: -#if __BIG_ENDIAN__ - /* - * Work around strange ABI behaviour. - * (see info in ffi_prep_args) - */ - if (arg_types[i]->size < WORD_SIZE) - { - memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size); - } -#endif - avalue[i] = (void*)ptr; - break; - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - avalue[i] = ptr; - break; - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - default: - /* default 4-byte argument */ - avalue[i] = ptr; - break; - } - ptr += WORD_ALIGN(arg_types[i]->size); - } - - /* set the return type info passed back to the wrapper */ - *rsize = cif->rtype->size; - *rtype = cif->rtype->type; - if (struct_rvalue != NULL) { - closure->fun(cif, struct_rvalue, avalue, closure->user_data); - /* copy struct return pointer value into function return value */ - *((void**)rvalue) = struct_rvalue; - } else { - closure->fun(cif, rvalue, avalue, closure->user_data); - } -} - -ffi_status ffi_prep_closure_loc( - ffi_closure* closure, ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void* user_data, void* codeloc) -{ - unsigned long* tramp = (unsigned long*)&(closure->tramp[0]); - unsigned long cls = (unsigned long)codeloc; - unsigned long fn = 0; - unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV; - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - switch (cif->abi) - { - case FFI_SYSV: - fn = (unsigned long)ffi_closure_SYSV; - - /* load r11 (temp) with fn */ - /* imm fn(upper) */ - tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff); - /* addik r11, r0, fn(lower) */ - tramp[1] = 0x31600000 | (fn & 0xffff); - - /* load r12 (temp) with cls */ - /* imm cls(upper) */ - tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff); - /* addik r12, r0, cls(lower) */ - tramp[3] = 0x31800000 | (cls & 0xffff); - - /* load r3 (temp) with ffi_closure_call_SYSV */ - /* imm fn_closure_call_sysv(upper) */ - tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff); - /* addik r3, r0, fn_closure_call_sysv(lower) */ - tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff); - /* branch/jump to address stored in r11 (fn) */ - tramp[6] = 0x98085800; /* bra r11 */ - - break; - default: - return FFI_BAD_ABI; - } - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffitarget.h deleted file mode 100644 index c6fa5a411..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ----------------------------------------------------------------------- - ffitarget.h - Copyright (c) 2012, 2013 Xilinx, Inc - - Target configuration macros for MicroBlaze. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -/* Definitions for closures */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -#define FFI_TRAMPOLINE_SIZE (4*8) - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/sysv.S deleted file mode 100644 index ea43e9d54..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/microblaze/sysv.S +++ /dev/null @@ -1,302 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc - - MicroBlaze Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - /* - * arg[0] (r5) = ffi_prep_args, - * arg[1] (r6) = &ecif, - * arg[2] (r7) = cif->bytes, - * arg[3] (r8) = cif->flags, - * arg[4] (r9) = ecif.rvalue, - * arg[5] (r10) = fn - * arg[6] (sp[0]) = cif->rtype->type - * arg[7] (sp[4]) = cif->rtype->size - */ - .text - .globl ffi_call_SYSV - .type ffi_call_SYSV, @function -ffi_call_SYSV: - /* push callee saves */ - addik r1, r1, -20 - swi r19, r1, 0 /* Frame Pointer */ - swi r20, r1, 4 /* PIC register */ - swi r21, r1, 8 /* PIC register */ - swi r22, r1, 12 /* save for locals */ - swi r23, r1, 16 /* save for locals */ - - /* save the r5-r10 registers in the stack */ - addik r1, r1, -24 /* increment sp to store 6x 32-bit words */ - swi r5, r1, 0 - swi r6, r1, 4 - swi r7, r1, 8 - swi r8, r1, 12 - swi r9, r1, 16 - swi r10, r1, 20 - - /* save function pointer */ - addik r3, r5, 0 /* copy ffi_prep_args into r3 */ - addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */ - addik r23, r10, 0 /* save function address into r23 (callee-saved) */ - - /* prepare stack with allocation for n (bytes = r7) args */ - rsub r1, r7, r1 /* subtract bytes from sp */ - - /* prep args for ffi_prep_args call */ - addik r5, r1, 0 /* store stack pointer into arg[0] */ - /* r6 still holds ecif for arg[1] */ - - /* Call ffi_prep_args(stack, &ecif). */ - addik r1, r1, -4 - swi r15, r1, 0 /* store the link register in the frame */ - brald r15, r3 - nop /* branch has delay slot */ - lwi r15, r1, 0 - addik r1, r1, 4 /* restore the link register from the frame */ - /* returns calling stack pointer location */ - - /* prepare args for fn call, prep_args populates them onto the stack */ - lwi r5, r1, 0 /* arg[0] */ - lwi r6, r1, 4 /* arg[1] */ - lwi r7, r1, 8 /* arg[2] */ - lwi r8, r1, 12 /* arg[3] */ - lwi r9, r1, 16 /* arg[4] */ - lwi r10, r1, 20 /* arg[5] */ - - /* call (fn) (...). */ - addik r1, r1, -4 - swi r15, r1, 0 /* store the link register in the frame */ - brald r15, r23 - nop /* branch has delay slot */ - lwi r15, r1, 0 - addik r1, r1, 4 /* restore the link register from the frame */ - - /* Remove the space we pushed for the args. */ - addik r1, r22, 0 /* restore old SP */ - - /* restore this functions parameters */ - lwi r5, r1, 0 /* arg[0] */ - lwi r6, r1, 4 /* arg[1] */ - lwi r7, r1, 8 /* arg[2] */ - lwi r8, r1, 12 /* arg[3] */ - lwi r9, r1, 16 /* arg[4] */ - lwi r10, r1, 20 /* arg[5] */ - addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */ - - /* If the return value pointer is NULL, assume no return value. */ - beqi r9, ffi_call_SYSV_end - - lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */ - lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7]) */ - - /* Check if return type is actually a struct, do nothing */ - rsubi r11, r22, FFI_TYPE_STRUCT - beqi r11, ffi_call_SYSV_end - - /* Return 8bit */ - rsubi r11, r23, 1 - beqi r11, ffi_call_SYSV_store8 - - /* Return 16bit */ - rsubi r11, r23, 2 - beqi r11, ffi_call_SYSV_store16 - - /* Return 32bit */ - rsubi r11, r23, 4 - beqi r11, ffi_call_SYSV_store32 - - /* Return 64bit */ - rsubi r11, r23, 8 - beqi r11, ffi_call_SYSV_store64 - - /* Didn't match anything */ - bri ffi_call_SYSV_end - -ffi_call_SYSV_store64: - swi r3, r9, 0 /* store word r3 into return value */ - swi r4, r9, 4 /* store word r4 into return value */ - bri ffi_call_SYSV_end - -ffi_call_SYSV_store32: - swi r3, r9, 0 /* store word r3 into return value */ - bri ffi_call_SYSV_end - -ffi_call_SYSV_store16: -#ifdef __BIG_ENDIAN__ - shi r3, r9, 2 /* store half-word r3 into return value */ -#else - shi r3, r9, 0 /* store half-word r3 into return value */ -#endif - bri ffi_call_SYSV_end - -ffi_call_SYSV_store8: -#ifdef __BIG_ENDIAN__ - sbi r3, r9, 3 /* store byte r3 into return value */ -#else - sbi r3, r9, 0 /* store byte r3 into return value */ -#endif - bri ffi_call_SYSV_end - -ffi_call_SYSV_end: - /* callee restores */ - lwi r19, r1, 0 /* frame pointer */ - lwi r20, r1, 4 /* PIC register */ - lwi r21, r1, 8 /* PIC register */ - lwi r22, r1, 12 - lwi r23, r1, 16 - addik r1, r1, 20 - - /* return from sub-routine (with delay slot) */ - rtsd r15, 8 - nop - - .size ffi_call_SYSV, . - ffi_call_SYSV - -/* ------------------------------------------------------------------------- */ - - /* - * args passed into this function, are passed down to the callee. - * this function is the target of the closure trampoline, as such r12 is - * a pointer to the closure object. - */ - .text - .globl ffi_closure_SYSV - .type ffi_closure_SYSV, @function -ffi_closure_SYSV: - /* push callee saves */ - addik r11, r1, 28 /* save stack args start location (excluding regs/link) */ - addik r1, r1, -12 - swi r19, r1, 0 /* Frame Pointer */ - swi r20, r1, 4 /* PIC register */ - swi r21, r1, 8 /* PIC register */ - - /* store register args on stack */ - addik r1, r1, -24 - swi r5, r1, 0 - swi r6, r1, 4 - swi r7, r1, 8 - swi r8, r1, 12 - swi r9, r1, 16 - swi r10, r1, 20 - - /* setup args */ - addik r5, r1, 0 /* register_args */ - addik r6, r11, 0 /* stack_args */ - addik r7, r12, 0 /* closure object */ - addik r1, r1, -8 /* allocate return value */ - addik r8, r1, 0 /* void* rvalue */ - addik r1, r1, -8 /* allocate for return type/size values */ - addik r9, r1, 0 /* void* rtype */ - addik r10, r1, 4 /* void* rsize */ - - /* call the wrap_call function */ - addik r1, r1, -28 /* allocate args + link reg */ - swi r15, r1, 0 /* store the link register in the frame */ - brald r15, r3 - nop /* branch has delay slot */ - lwi r15, r1, 0 - addik r1, r1, 28 /* restore the link register from the frame */ - -ffi_closure_SYSV_prepare_return: - lwi r9, r1, 0 /* rtype */ - lwi r10, r1, 4 /* rsize */ - addik r1, r1, 8 /* de-allocate return info values */ - - /* Check if return type is actually a struct, store 4 bytes */ - rsubi r11, r9, FFI_TYPE_STRUCT - beqi r11, ffi_closure_SYSV_store32 - - /* Return 8bit */ - rsubi r11, r10, 1 - beqi r11, ffi_closure_SYSV_store8 - - /* Return 16bit */ - rsubi r11, r10, 2 - beqi r11, ffi_closure_SYSV_store16 - - /* Return 32bit */ - rsubi r11, r10, 4 - beqi r11, ffi_closure_SYSV_store32 - - /* Return 64bit */ - rsubi r11, r10, 8 - beqi r11, ffi_closure_SYSV_store64 - - /* Didn't match anything */ - bri ffi_closure_SYSV_end - -ffi_closure_SYSV_store64: - lwi r3, r1, 0 /* store word r3 into return value */ - lwi r4, r1, 4 /* store word r4 into return value */ - /* 64 bits == 2 words, no sign extend occurs */ - bri ffi_closure_SYSV_end - -ffi_closure_SYSV_store32: - lwi r3, r1, 0 /* store word r3 into return value */ - /* 32 bits == 1 word, no sign extend occurs */ - bri ffi_closure_SYSV_end - -ffi_closure_SYSV_store16: -#ifdef __BIG_ENDIAN__ - lhui r3, r1, 2 /* store half-word r3 into return value */ -#else - lhui r3, r1, 0 /* store half-word r3 into return value */ -#endif - rsubi r11, r9, FFI_TYPE_SINT16 - bnei r11, ffi_closure_SYSV_end - sext16 r3, r3 /* fix sign extend of sint8 */ - bri ffi_closure_SYSV_end - -ffi_closure_SYSV_store8: -#ifdef __BIG_ENDIAN__ - lbui r3, r1, 3 /* store byte r3 into return value */ -#else - lbui r3, r1, 0 /* store byte r3 into return value */ -#endif - rsubi r11, r9, FFI_TYPE_SINT8 - bnei r11, ffi_closure_SYSV_end - sext8 r3, r3 /* fix sign extend of sint8 */ - bri ffi_closure_SYSV_end - -ffi_closure_SYSV_end: - addik r1, r1, 8 /* de-allocate return value */ - - /* de-allocate stored args */ - addik r1, r1, 24 - - /* callee restores */ - lwi r19, r1, 0 /* frame pointer */ - lwi r20, r1, 4 /* PIC register */ - lwi r21, r1, 8 /* PIC register */ - addik r1, r1, 12 - - /* return from sub-routine (with delay slot) */ - rtsd r15, 8 - nop - - .size ffi_closure_SYSV, . - ffi_closure_SYSV diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffi.c deleted file mode 100644 index 5d0dd70cb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffi.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2011 Anthony Green - Copyright (c) 2008 David Daney - Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc. - - MIPS Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -#ifdef __GNUC__ -# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) -# define USE__BUILTIN___CLEAR_CACHE 1 -# endif -#endif - -#ifndef USE__BUILTIN___CLEAR_CACHE -# if defined(__OpenBSD__) -# include -# else -# include -# endif -#endif - -#ifdef FFI_DEBUG -# define FFI_MIPS_STOP_HERE() ffi_stop_here() -#else -# define FFI_MIPS_STOP_HERE() do {} while(0) -#endif - -#ifdef FFI_MIPS_N32 -#define FIX_ARGP \ -FFI_ASSERT(argp <= &stack[bytes]); \ -if (argp == &stack[bytes]) \ -{ \ - argp = stack; \ - FFI_MIPS_STOP_HERE(); \ -} -#else -#define FIX_ARGP -#endif - - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -static void ffi_prep_args(char *stack, - extended_cif *ecif, - int bytes, - int flags) -{ - int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - -#ifdef FFI_MIPS_N32 - /* If more than 8 double words are used, the remainder go - on the stack. We reorder stuff on the stack here to - support this easily. */ - if (bytes > 8 * sizeof(ffi_arg)) - argp = &stack[bytes - (8 * sizeof(ffi_arg))]; - else - argp = stack; -#else - argp = stack; -#endif - - memset(stack, 0, bytes); - -#ifdef FFI_MIPS_N32 - if ( ecif->cif->rstruct_flag != 0 ) -#else - if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) -#endif - { - *(ffi_arg *) argp = (ffi_arg) ecif->rvalue; - argp += sizeof(ffi_arg); - FIX_ARGP; - } - - p_argv = ecif->avalue; - - for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++) - { - size_t z; - unsigned int a; - - /* Align if necessary. */ - a = (*p_arg)->alignment; - if (a < sizeof(ffi_arg)) - a = sizeof(ffi_arg); - - if ((a - 1) & (unsigned long) argp) - { - argp = (char *) ALIGN(argp, a); - FIX_ARGP; - } - - z = (*p_arg)->size; - if (z <= sizeof(ffi_arg)) - { - int type = (*p_arg)->type; - z = sizeof(ffi_arg); - - /* The size of a pointer depends on the ABI */ - if (type == FFI_TYPE_POINTER) - type = (ecif->cif->abi == FFI_N64 - || ecif->cif->abi == FFI_N64_SOFT_FLOAT) - ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; - - if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT - || ecif->cif->abi == FFI_N64_SOFT_FLOAT)) - { - switch (type) - { - case FFI_TYPE_FLOAT: - type = FFI_TYPE_UINT32; - break; - case FFI_TYPE_DOUBLE: - type = FFI_TYPE_UINT64; - break; - default: - break; - } - } - switch (type) - { - case FFI_TYPE_SINT8: - *(ffi_arg *)argp = *(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(ffi_arg *)argp = *(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(ffi_arg *)argp = *(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(ffi_arg *)argp = *(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(ffi_arg *)argp = *(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: -#ifdef FFI_MIPS_N32 - /* The N32 ABI requires that 32-bit integers - be sign-extended to 64-bits, regardless of - whether they are signed or unsigned. */ - *(ffi_arg *)argp = *(SINT32 *)(* p_argv); -#else - *(ffi_arg *)argp = *(UINT32 *)(* p_argv); -#endif - break; - - /* This can only happen with 64bit slots. */ - case FFI_TYPE_FLOAT: - *(float *) argp = *(float *)(* p_argv); - break; - - /* Handle structures. */ - default: - memcpy(argp, *p_argv, (*p_arg)->size); - break; - } - } - else - { -#ifdef FFI_MIPS_O32 - memcpy(argp, *p_argv, z); -#else - { - unsigned long end = (unsigned long) argp + z; - unsigned long cap = (unsigned long) stack + bytes; - - /* Check if the data will fit within the register space. - Handle it if it doesn't. */ - - if (end <= cap) - memcpy(argp, *p_argv, z); - else - { - unsigned long portion = cap - (unsigned long)argp; - - memcpy(argp, *p_argv, portion); - argp = stack; - z -= portion; - memcpy(argp, (void*)((unsigned long)(*p_argv) + portion), - z); - } - } -#endif - } - p_argv++; - argp += z; - FIX_ARGP; - } -} - -#ifdef FFI_MIPS_N32 - -/* The n32 spec says that if "a chunk consists solely of a double - float field (but not a double, which is part of a union), it - is passed in a floating point register. Any other chunk is - passed in an integer register". This code traverses structure - definitions and generates the appropriate flags. */ - -static unsigned -calc_n32_struct_flags(int soft_float, ffi_type *arg, - unsigned *loc, unsigned *arg_reg) -{ - unsigned flags = 0; - unsigned index = 0; - - ffi_type *e; - - if (soft_float) - return 0; - - while ((e = arg->elements[index])) - { - /* Align this object. */ - *loc = ALIGN(*loc, e->alignment); - if (e->type == FFI_TYPE_DOUBLE) - { - /* Already aligned to FFI_SIZEOF_ARG. */ - *arg_reg = *loc / FFI_SIZEOF_ARG; - if (*arg_reg > 7) - break; - flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS)); - *loc += e->size; - } - else - *loc += e->size; - index++; - } - /* Next Argument register at alignment of FFI_SIZEOF_ARG. */ - *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - - return flags; -} - -static unsigned -calc_n32_return_struct_flags(int soft_float, ffi_type *arg) -{ - unsigned flags = 0; - unsigned small = FFI_TYPE_SMALLSTRUCT; - ffi_type *e; - - /* Returning structures under n32 is a tricky thing. - A struct with only one or two floating point fields - is returned in $f0 (and $f2 if necessary). Any other - struct results at most 128 bits are returned in $2 - (the first 64 bits) and $3 (remainder, if necessary). - Larger structs are handled normally. */ - - if (arg->size > 16) - return 0; - - if (arg->size > 8) - small = FFI_TYPE_SMALLSTRUCT2; - - e = arg->elements[0]; - - if (e->type == FFI_TYPE_DOUBLE) - flags = FFI_TYPE_DOUBLE; - else if (e->type == FFI_TYPE_FLOAT) - flags = FFI_TYPE_FLOAT; - - if (flags && (e = arg->elements[1])) - { - if (e->type == FFI_TYPE_DOUBLE) - flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS; - else if (e->type == FFI_TYPE_FLOAT) - flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS; - else - return small; - - if (flags && (arg->elements[2])) - { - /* There are three arguments and the first two are - floats! This must be passed the old way. */ - return small; - } - if (soft_float) - flags += FFI_TYPE_STRUCT_SOFT; - } - else - if (!flags) - return small; - - return flags; -} - -#endif - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - cif->flags = 0; - -#ifdef FFI_MIPS_O32 - /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT - * does not have special handling for floating point args. - */ - - if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32) - { - if (cif->nargs > 0) - { - switch ((cif->arg_types)[0]->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags += (cif->arg_types)[0]->type; - break; - - default: - break; - } - - if (cif->nargs > 1) - { - /* Only handle the second argument if the first - is a float or double. */ - if (cif->flags) - { - switch ((cif->arg_types)[1]->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS; - break; - - default: - break; - } - } - } - } - } - - /* Set the return type flag */ - - if (cif->abi == FFI_O32_SOFT_FLOAT) - { - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: - cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); - break; - - case FFI_TYPE_FLOAT: - default: - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); - break; - } - } - else - { - /* FFI_O32 */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); - break; - - default: - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); - break; - } - } -#endif - -#ifdef FFI_MIPS_N32 - /* Set the flags necessary for N32 processing */ - { - int type; - unsigned arg_reg = 0; - unsigned loc = 0; - unsigned count = (cif->nargs < 8) ? cif->nargs : 8; - unsigned index = 0; - - unsigned struct_flags = 0; - int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT - || cif->abi == FFI_N64_SOFT_FLOAT); - - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype); - - if (struct_flags == 0) - { - /* This means that the structure is being passed as - a hidden argument */ - - arg_reg = 1; - count = (cif->nargs < 7) ? cif->nargs : 7; - - cif->rstruct_flag = !0; - } - else - cif->rstruct_flag = 0; - } - else - cif->rstruct_flag = 0; - - while (count-- > 0 && arg_reg < 8) - { - type = (cif->arg_types)[index]->type; - if (soft_float) - { - switch (type) - { - case FFI_TYPE_FLOAT: - type = FFI_TYPE_UINT32; - break; - case FFI_TYPE_DOUBLE: - type = FFI_TYPE_UINT64; - break; - default: - break; - } - } - switch (type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags += - ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS)); - arg_reg++; - break; - case FFI_TYPE_LONGDOUBLE: - /* Align it. */ - arg_reg = ALIGN(arg_reg, 2); - /* Treat it as two adjacent doubles. */ - if (soft_float) - { - arg_reg += 2; - } - else - { - cif->flags += - (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); - arg_reg++; - cif->flags += - (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); - arg_reg++; - } - break; - - case FFI_TYPE_STRUCT: - loc = arg_reg * FFI_SIZEOF_ARG; - cif->flags += calc_n32_struct_flags(soft_float, - (cif->arg_types)[index], - &loc, &arg_reg); - break; - - default: - arg_reg++; - break; - } - - index++; - } - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_STRUCT: - { - if (struct_flags == 0) - { - /* The structure is returned through a hidden - first argument. Do nothing, 'cause FFI_TYPE_VOID - is 0 */ - } - else - { - /* The structure is returned via some tricky - mechanism */ - cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); - cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8)); - } - break; - } - - case FFI_TYPE_VOID: - /* Do nothing, 'cause FFI_TYPE_VOID is 0 */ - break; - - case FFI_TYPE_POINTER: - if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32) - cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8); - else - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); - break; - - case FFI_TYPE_FLOAT: - if (soft_float) - { - cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8); - break; - } - /* else fall through */ - case FFI_TYPE_DOUBLE: - if (soft_float) - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); - else - cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8); - break; - - case FFI_TYPE_LONGDOUBLE: - /* Long double is returned as if it were a struct containing - two doubles. */ - if (soft_float) - { - cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); - cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8)); - } - else - { - cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); - cif->flags += (FFI_TYPE_DOUBLE - + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS)) - << (4 + (FFI_FLAG_BITS * 8)); - } - break; - default: - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); - break; - } - } -#endif - - return FFI_OK; -} - -/* Low level routine for calling O32 functions */ -extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), - extended_cif *, unsigned, - unsigned, unsigned *, void (*)(void)); - -/* Low level routine for calling N32 functions */ -extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), - extended_cif *, unsigned, - unsigned, void *, void (*)(void)); - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - ecif.rvalue = alloca(cif->rtype->size); - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { -#ifdef FFI_MIPS_O32 - case FFI_O32: - case FFI_O32_SOFT_FLOAT: - ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; -#endif - -#ifdef FFI_MIPS_N32 - case FFI_N32: - case FFI_N32_SOFT_FLOAT: - case FFI_N64: - case FFI_N64_SOFT_FLOAT: - { - int copy_rvalue = 0; - int copy_offset = 0; - char *rvalue_copy = ecif.rvalue; - if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16) - { - /* For structures smaller than 16 bytes we clobber memory - in 8 byte increments. Make a copy so we don't clobber - the callers memory outside of the struct bounds. */ - rvalue_copy = alloca(16); - copy_rvalue = 1; - } - else if (cif->rtype->type == FFI_TYPE_FLOAT - && (cif->abi == FFI_N64_SOFT_FLOAT - || cif->abi == FFI_N32_SOFT_FLOAT)) - { - rvalue_copy = alloca (8); - copy_rvalue = 1; -#if defined(__MIPSEB__) || defined(_MIPSEB) - copy_offset = 4; -#endif - } - ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, rvalue_copy, fn); - if (copy_rvalue) - memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size); - } - break; -#endif - - default: - FFI_ASSERT(0); - break; - } -} - -#if FFI_CLOSURES -#if defined(FFI_MIPS_O32) -extern void ffi_closure_O32(void); -#else -extern void ffi_closure_N32(void); -#endif /* FFI_MIPS_O32 */ - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - void * fn; - char *clear_location = (char *) codeloc; - -#if defined(FFI_MIPS_O32) - if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT) - return FFI_BAD_ABI; - fn = ffi_closure_O32; -#else -#if _MIPS_SIM ==_ABIN32 - if (cif->abi != FFI_N32 - && cif->abi != FFI_N32_SOFT_FLOAT) - return FFI_BAD_ABI; -#else - if (cif->abi != FFI_N64 - && cif->abi != FFI_N64_SOFT_FLOAT) - return FFI_BAD_ABI; -#endif - fn = ffi_closure_N32; -#endif /* FFI_MIPS_O32 */ - -#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32) - /* lui $25,high(fn) */ - tramp[0] = 0x3c190000 | ((unsigned)fn >> 16); - /* ori $25,low(fn) */ - tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff); - /* lui $12,high(codeloc) */ - tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16); - /* jr $25 */ - tramp[3] = 0x03200008; - /* ori $12,low(codeloc) */ - tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff); -#else - /* N64 has a somewhat larger trampoline. */ - /* lui $25,high(fn) */ - tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48); - /* lui $12,high(codeloc) */ - tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48); - /* ori $25,mid-high(fn) */ - tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff); - /* ori $12,mid-high(codeloc) */ - tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff); - /* dsll $25,$25,16 */ - tramp[4] = 0x0019cc38; - /* dsll $12,$12,16 */ - tramp[5] = 0x000c6438; - /* ori $25,mid-low(fn) */ - tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff); - /* ori $12,mid-low(codeloc) */ - tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff); - /* dsll $25,$25,16 */ - tramp[8] = 0x0019cc38; - /* dsll $12,$12,16 */ - tramp[9] = 0x000c6438; - /* ori $25,low(fn) */ - tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff); - /* jr $25 */ - tramp[11] = 0x03200008; - /* ori $12,low(codeloc) */ - tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff); - -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - -#ifdef USE__BUILTIN___CLEAR_CACHE - __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE); -#else - cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE); -#endif - return FFI_OK; -} - -/* - * Decodes the arguments to a function, which will be stored on the - * stack. AR is the pointer to the beginning of the integer arguments - * (and, depending upon the arguments, some floating-point arguments - * as well). FPR is a pointer to the area where floating point - * registers have been saved, if any. - * - * RVALUE is the location where the function return value will be - * stored. CLOSURE is the prepared closure to invoke. - * - * This function should only be called from assembly, which is in - * turn called from a trampoline. - * - * Returns the function return type. - * - * Based on the similar routine for sparc. - */ -int -ffi_closure_mips_inner_O32 (ffi_closure *closure, - void *rvalue, ffi_arg *ar, - double *fpr) -{ - ffi_cif *cif; - void **avaluep; - ffi_arg *avalue; - ffi_type **arg_types; - int i, avn, argn, seen_int; - - cif = closure->cif; - avalue = alloca (cif->nargs * sizeof (ffi_arg)); - avaluep = alloca (cif->nargs * sizeof (ffi_arg)); - - seen_int = (cif->abi == FFI_O32_SOFT_FLOAT); - argn = 0; - - if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT) - { - rvalue = (void *)(UINT32)ar[0]; - argn = 1; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - while (i < avn) - { - if (i < 2 && !seen_int && - (arg_types[i]->type == FFI_TYPE_FLOAT || - arg_types[i]->type == FFI_TYPE_DOUBLE || - arg_types[i]->type == FFI_TYPE_LONGDOUBLE)) - { -#if defined(__MIPSEB__) || defined(_MIPSEB) - if (arg_types[i]->type == FFI_TYPE_FLOAT) - avaluep[i] = ((char *) &fpr[i]) + sizeof (float); - else -#endif - avaluep[i] = (char *) &fpr[i]; - } - else - { - if (arg_types[i]->alignment == 8 && (argn & 0x1)) - argn++; - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - avaluep[i] = &avalue[i]; - *(SINT8 *) &avalue[i] = (SINT8) ar[argn]; - break; - - case FFI_TYPE_UINT8: - avaluep[i] = &avalue[i]; - *(UINT8 *) &avalue[i] = (UINT8) ar[argn]; - break; - - case FFI_TYPE_SINT16: - avaluep[i] = &avalue[i]; - *(SINT16 *) &avalue[i] = (SINT16) ar[argn]; - break; - - case FFI_TYPE_UINT16: - avaluep[i] = &avalue[i]; - *(UINT16 *) &avalue[i] = (UINT16) ar[argn]; - break; - - default: - avaluep[i] = (char *) &ar[argn]; - break; - } - seen_int = 1; - } - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++; - } - - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); - - if (cif->abi == FFI_O32_SOFT_FLOAT) - { - switch (cif->rtype->type) - { - case FFI_TYPE_FLOAT: - return FFI_TYPE_INT; - case FFI_TYPE_DOUBLE: - return FFI_TYPE_UINT64; - default: - return cif->rtype->type; - } - } - else - { - return cif->rtype->type; - } -} - -#if defined(FFI_MIPS_N32) - -static void -copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, - int argn, unsigned arg_offset, ffi_arg *ar, - ffi_arg *fpr, int soft_float) -{ - ffi_type **elt_typep = type->elements; - while(*elt_typep) - { - ffi_type *elt_type = *elt_typep; - unsigned o; - char *tp; - char *argp; - char *fpp; - - o = ALIGN(offset, elt_type->alignment); - arg_offset += o - offset; - offset = o; - argn += arg_offset / sizeof(ffi_arg); - arg_offset = arg_offset % sizeof(ffi_arg); - - argp = (char *)(ar + argn); - fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn); - - tp = target + offset; - - if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float) - *(double *)tp = *(double *)fpp; - else - memcpy(tp, argp + arg_offset, elt_type->size); - - offset += elt_type->size; - arg_offset += elt_type->size; - elt_typep++; - argn += arg_offset / sizeof(ffi_arg); - arg_offset = arg_offset % sizeof(ffi_arg); - } -} - -/* - * Decodes the arguments to a function, which will be stored on the - * stack. AR is the pointer to the beginning of the integer - * arguments. FPR is a pointer to the area where floating point - * registers have been saved. - * - * RVALUE is the location where the function return value will be - * stored. CLOSURE is the prepared closure to invoke. - * - * This function should only be called from assembly, which is in - * turn called from a trampoline. - * - * Returns the function return flags. - * - */ -int -ffi_closure_mips_inner_N32 (ffi_closure *closure, - void *rvalue, ffi_arg *ar, - ffi_arg *fpr) -{ - ffi_cif *cif; - void **avaluep; - ffi_arg *avalue; - ffi_type **arg_types; - int i, avn, argn; - int soft_float; - ffi_arg *argp; - - cif = closure->cif; - soft_float = cif->abi == FFI_N64_SOFT_FLOAT - || cif->abi == FFI_N32_SOFT_FLOAT; - avalue = alloca (cif->nargs * sizeof (ffi_arg)); - avaluep = alloca (cif->nargs * sizeof (ffi_arg)); - - argn = 0; - - if (cif->rstruct_flag) - { -#if _MIPS_SIM==_ABIN32 - rvalue = (void *)(UINT32)ar[0]; -#else /* N64 */ - rvalue = (void *)ar[0]; -#endif - argn = 1; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - while (i < avn) - { - if (arg_types[i]->type == FFI_TYPE_FLOAT - || arg_types[i]->type == FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_LONGDOUBLE) - { - argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn; - if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1))) - { - argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment); - argn++; - } -#if defined(__MIPSEB__) || defined(_MIPSEB) - if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8) - avaluep[i] = ((char *) argp) + sizeof (float); - else -#endif - avaluep[i] = (char *) argp; - } - else - { - unsigned type = arg_types[i]->type; - - if (arg_types[i]->alignment > sizeof(ffi_arg)) - argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); - - argp = ar + argn; - - /* The size of a pointer depends on the ABI */ - if (type == FFI_TYPE_POINTER) - type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT) - ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; - - if (soft_float && type == FFI_TYPE_FLOAT) - type = FFI_TYPE_UINT32; - - switch (type) - { - case FFI_TYPE_SINT8: - avaluep[i] = &avalue[i]; - *(SINT8 *) &avalue[i] = (SINT8) *argp; - break; - - case FFI_TYPE_UINT8: - avaluep[i] = &avalue[i]; - *(UINT8 *) &avalue[i] = (UINT8) *argp; - break; - - case FFI_TYPE_SINT16: - avaluep[i] = &avalue[i]; - *(SINT16 *) &avalue[i] = (SINT16) *argp; - break; - - case FFI_TYPE_UINT16: - avaluep[i] = &avalue[i]; - *(UINT16 *) &avalue[i] = (UINT16) *argp; - break; - - case FFI_TYPE_SINT32: - avaluep[i] = &avalue[i]; - *(SINT32 *) &avalue[i] = (SINT32) *argp; - break; - - case FFI_TYPE_UINT32: - avaluep[i] = &avalue[i]; - *(UINT32 *) &avalue[i] = (UINT32) *argp; - break; - - case FFI_TYPE_STRUCT: - if (argn < 8) - { - /* Allocate space for the struct as at least part of - it was passed in registers. */ - avaluep[i] = alloca(arg_types[i]->size); - copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i], - argn, 0, ar, fpr, soft_float); - - break; - } - /* Else fall through. */ - default: - avaluep[i] = (char *) argp; - break; - } - } - argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); - i++; - } - - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); - - return cif->flags >> (FFI_FLAG_BITS * 8); -} - -#endif /* FFI_MIPS_N32 */ - -#endif /* FFI_CLOSURES */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffitarget.h deleted file mode 100644 index 717d65951..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/mips/ffitarget.h +++ /dev/null @@ -1,247 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for MIPS. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifdef linux -# include -#elif defined(__rtems__) -/* - * Subprogram calling convention - copied from sgidefs.h - */ -#define _MIPS_SIM_ABI32 1 -#define _MIPS_SIM_NABI32 2 -#define _MIPS_SIM_ABI64 3 -#elif !defined(__OpenBSD__) -# include -#endif - -# ifndef _ABIN32 -# define _ABIN32 _MIPS_SIM_NABI32 -# endif -# ifndef _ABI64 -# define _ABI64 _MIPS_SIM_ABI64 -# endif -# ifndef _ABIO32 -# define _ABIO32 _MIPS_SIM_ABI32 -# endif - -#if !defined(_MIPS_SIM) -# error -- something is very wrong -- -#else -# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64)) -# define FFI_MIPS_N32 -# else -# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32)) -# define FFI_MIPS_O32 -# else -# error -- this is an unsupported platform -- -# endif -# endif -#endif - -#ifdef FFI_MIPS_O32 -/* O32 stack frames have 32bit integer args */ -# define FFI_SIZEOF_ARG 4 -#else -/* N32 and N64 frames have 64bit integer args */ -# define FFI_SIZEOF_ARG 8 -# if _MIPS_SIM == _ABIN32 -# define FFI_SIZEOF_JAVA_RAW 4 -# endif -#endif - -#define FFI_FLAG_BITS 2 - -/* SGI's strange assembler requires that we multiply by 4 rather - than shift left by FFI_FLAG_BITS */ - -#define FFI_ARGS_D FFI_TYPE_DOUBLE -#define FFI_ARGS_F FFI_TYPE_FLOAT -#define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE -#define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT -#define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT -#define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE - -/* Needed for N32 structure returns */ -#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8 -#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8 - -#if 0 -/* The SGI assembler can't handle this.. */ -#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT -/* (and so on) */ -#else -/* ...so we calculate these by hand! */ -#define FFI_TYPE_STRUCT_D 61 -#define FFI_TYPE_STRUCT_F 45 -#define FFI_TYPE_STRUCT_DD 253 -#define FFI_TYPE_STRUCT_FF 173 -#define FFI_TYPE_STRUCT_FD 237 -#define FFI_TYPE_STRUCT_DF 189 -#define FFI_TYPE_STRUCT_SMALL 93 -#define FFI_TYPE_STRUCT_SMALL2 109 - -/* and for n32 soft float, add 16 * 2^4 */ -#define FFI_TYPE_STRUCT_D_SOFT 317 -#define FFI_TYPE_STRUCT_F_SOFT 301 -#define FFI_TYPE_STRUCT_DD_SOFT 509 -#define FFI_TYPE_STRUCT_FF_SOFT 429 -#define FFI_TYPE_STRUCT_FD_SOFT 493 -#define FFI_TYPE_STRUCT_DF_SOFT 445 -#define FFI_TYPE_STRUCT_SOFT 16 -#endif - -#ifdef LIBFFI_ASM -#define v0 $2 -#define v1 $3 -#define a0 $4 -#define a1 $5 -#define a2 $6 -#define a3 $7 -#define a4 $8 -#define a5 $9 -#define a6 $10 -#define a7 $11 -#define t0 $8 -#define t1 $9 -#define t2 $10 -#define t3 $11 -#define t4 $12 -#define t5 $13 -#define t6 $14 -#define t7 $15 -#define t8 $24 -#define t9 $25 -#define ra $31 - -#ifdef FFI_MIPS_O32 -# define REG_L lw -# define REG_S sw -# define SUBU subu -# define ADDU addu -# define SRL srl -# define LI li -#else /* !FFI_MIPS_O32 */ -# define REG_L ld -# define REG_S sd -# define SUBU dsubu -# define ADDU daddu -# define SRL dsrl -# define LI dli -# if (_MIPS_SIM==_ABI64) -# define LA dla -# define EH_FRAME_ALIGN 3 -# define FDE_ADDR_BYTES .8byte -# else -# define LA la -# define EH_FRAME_ALIGN 2 -# define FDE_ADDR_BYTES .4byte -# endif /* _MIPS_SIM==_ABI64 */ -#endif /* !FFI_MIPS_O32 */ -#else /* !LIBFFI_ASM */ -# ifdef __GNUC__ -# ifdef FFI_MIPS_O32 -/* O32 stack frames have 32bit integer args */ -typedef unsigned int ffi_arg __attribute__((__mode__(__SI__))); -typedef signed int ffi_sarg __attribute__((__mode__(__SI__))); -#else -/* N32 and N64 frames have 64bit integer args */ -typedef unsigned int ffi_arg __attribute__((__mode__(__DI__))); -typedef signed int ffi_sarg __attribute__((__mode__(__DI__))); -# endif -# else -# ifdef FFI_MIPS_O32 -/* O32 stack frames have 32bit integer args */ -typedef __uint32_t ffi_arg; -typedef __int32_t ffi_sarg; -# else -/* N32 and N64 frames have 64bit integer args */ -typedef __uint64_t ffi_arg; -typedef __int64_t ffi_sarg; -# endif -# endif /* __GNUC__ */ - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_O32, - FFI_N32, - FFI_N64, - FFI_O32_SOFT_FLOAT, - FFI_N32_SOFT_FLOAT, - FFI_N64_SOFT_FLOAT, - FFI_LAST_ABI, - -#ifdef FFI_MIPS_O32 -#ifdef __mips_soft_float - FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT -#else - FFI_DEFAULT_ABI = FFI_O32 -#endif -#else -# if _MIPS_SIM==_ABI64 -# ifdef __mips_soft_float - FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT -# else - FFI_DEFAULT_ABI = FFI_N64 -# endif -# else -# ifdef __mips_soft_float - FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT -# else - FFI_DEFAULT_ABI = FFI_N32 -# endif -# endif -#endif -} ffi_abi; - -#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag -#endif /* !LIBFFI_ASM */ - -/* ---- Definitions for closures ----------------------------------------- */ - -#if defined(FFI_MIPS_O32) -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 20 -#else -/* N32/N64. */ -# define FFI_CLOSURES 1 -#if _MIPS_SIM==_ABI64 -#define FFI_TRAMPOLINE_SIZE 52 -#else -#define FFI_TRAMPOLINE_SIZE 20 -#endif -#endif /* FFI_MIPS_O32 */ -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/mips/n32.S b/ruby/ext/fiddle/libffi-3.2.1/src/mips/n32.S deleted file mode 100644 index c6985d30a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/mips/n32.S +++ /dev/null @@ -1,576 +0,0 @@ -/* ----------------------------------------------------------------------- - n32.S - Copyright (c) 1996, 1998, 2005, 2007, 2009, 2010 Red Hat, Inc. - - MIPS Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -/* Only build this code if we are compiling for n32 */ - -#if defined(FFI_MIPS_N32) - -#define callback a0 -#define bytes a2 -#define flags a3 -#define raddr a4 -#define fn a5 - -#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG ) - -#ifdef __GNUC__ - .abicalls -#endif - .set mips4 - .text - .align 2 - .globl ffi_call_N32 - .ent ffi_call_N32 -ffi_call_N32: -.LFB3: - .frame $fp, SIZEOF_FRAME, ra - .mask 0xc0000000,-FFI_SIZEOF_ARG - .fmask 0x00000000,0 - - # Prologue - SUBU $sp, SIZEOF_FRAME # Frame size -.LCFI0: - REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer - REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address -.LCFI1: - move $fp, $sp -.LCFI3: - move t9, callback # callback function pointer - REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes - REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags - REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr - REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn - - # Allocate at least 4 words in the argstack - move v0, bytes - bge bytes, 4 * FFI_SIZEOF_ARG, bigger - LI v0, 4 * FFI_SIZEOF_ARG - b sixteen - - bigger: - ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned - and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry. - -sixteen: - SUBU $sp, $sp, v0 # move the stack pointer to reflect the - # arg space - - move a0, $sp # 4 * FFI_SIZEOF_ARG - ADDU a3, $fp, 3 * FFI_SIZEOF_ARG - - # Call ffi_prep_args - jal t9 - - # Copy the stack pointer to t9 - move t9, $sp - - # Fix the stack if there are more than 8 64bit slots worth - # of arguments. - - # Load the number of bytes - REG_L t6, 2*FFI_SIZEOF_ARG($fp) - - # Is it bigger than 8 * FFI_SIZEOF_ARG? - daddiu t8, t6, -(8 * FFI_SIZEOF_ARG) - bltz t8, loadregs - - ADDU t9, t9, t8 - -loadregs: - - REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6. - - and t4, t6, ((1< -#include - -/* Only build this code if we are compiling for o32 */ - -#if defined(FFI_MIPS_O32) - -#define callback a0 -#define bytes a2 -#define flags a3 - -#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG) -#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG) -#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG) -#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG) - - .abicalls - .text - .align 2 - .globl ffi_call_O32 - .ent ffi_call_O32 -ffi_call_O32: -$LFB0: - # Prologue - SUBU $sp, SIZEOF_FRAME # Frame size -$LCFI0: - REG_S $fp, FP_OFF($sp) # Save frame pointer -$LCFI1: - REG_S ra, RA_OFF($sp) # Save return address -$LCFI2: - move $fp, $sp - -$LCFI3: - move t9, callback # callback function pointer - REG_S flags, A3_OFF($fp) # flags - - # Allocate at least 4 words in the argstack - LI v0, 4 * FFI_SIZEOF_ARG - blt bytes, v0, sixteen - - ADDU v0, bytes, 7 # make sure it is aligned - and v0, -8 # to an 8 byte boundry - -sixteen: - SUBU $sp, v0 # move the stack pointer to reflect the - # arg space - - ADDU a0, $sp, 4 * FFI_SIZEOF_ARG - - jalr t9 - - REG_L t0, A3_OFF($fp) # load the flags word - SRL t2, t0, 4 # shift our arg info - and t0, ((1<<4)-1) # mask out the return type - - ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args - - bnez t0, pass_d # make it quick for int - REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the - REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs. - REG_L a2, 2*FFI_SIZEOF_ARG($sp) - REG_L a3, 3*FFI_SIZEOF_ARG($sp) - b call_it - -pass_d: - bne t0, FFI_ARGS_D, pass_f - l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double - REG_L a3, 3*FFI_SIZEOF_ARG($sp) - b call_it - -pass_f: - bne t0, FFI_ARGS_F, pass_d_d - l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float - REG_L a2, 2*FFI_SIZEOF_ARG($sp) - REG_L a3, 3*FFI_SIZEOF_ARG($sp) - b call_it - -pass_d_d: - bne t0, FFI_ARGS_DD, pass_f_f - l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles - b call_it - -pass_f_f: - bne t0, FFI_ARGS_FF, pass_d_f - l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats - REG_L a2, 2*FFI_SIZEOF_ARG($sp) - REG_L a3, 3*FFI_SIZEOF_ARG($sp) - b call_it - -pass_d_f: - bne t0, FFI_ARGS_DF, pass_f_d - l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float - REG_L a3, 3*FFI_SIZEOF_ARG($sp) - b call_it - -pass_f_d: - # assume that the only other combination must be float then double - # bne t0, FFI_ARGS_F_D, call_it - l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args - l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float - -call_it: - # Load the function pointer - REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp) - - # If the return value pointer is NULL, assume no return value. - REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) - beqz t1, noretval - - bne t2, FFI_TYPE_INT, retlonglong - jalr t9 - REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) - REG_S v0, 0(t0) - b epilogue - -retlonglong: - # Really any 64-bit int, signed or not. - bne t2, FFI_TYPE_UINT64, retfloat - jalr t9 - REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) - REG_S v1, 4(t0) - REG_S v0, 0(t0) - b epilogue - -retfloat: - bne t2, FFI_TYPE_FLOAT, retdouble - jalr t9 - REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) - s.s $f0, 0(t0) - b epilogue - -retdouble: - bne t2, FFI_TYPE_DOUBLE, noretval - jalr t9 - REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) - s.d $f0, 0(t0) - b epilogue - -noretval: - jalr t9 - - # Epilogue -epilogue: - move $sp, $fp - REG_L $fp, FP_OFF($sp) # Restore frame pointer - REG_L ra, RA_OFF($sp) # Restore return address - ADDU $sp, SIZEOF_FRAME # Fix stack pointer - j ra - -$LFE0: - .end ffi_call_O32 - - -/* ffi_closure_O32. Expects address of the passed-in ffi_closure - in t4 ($12). Stores any arguments passed in registers onto the - stack, then calls ffi_closure_mips_inner_O32, which - then decodes them. - - Stack layout: - - 3 - a3 save - 2 - a2 save - 1 - a1 save - 0 - a0 save, original sp - -1 - ra save - -2 - fp save - -3 - $16 (s0) save - -4 - cprestore - -5 - return value high (v1) - -6 - return value low (v0) - -7 - f14 (le high, be low) - -8 - f14 (le low, be high) - -9 - f12 (le high, be low) - -10 - f12 (le low, be high) - -11 - Called function a3 save - -12 - Called function a2 save - -13 - Called function a1 save - -14 - Called function a0 save, our sp and fp point here - */ - -#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG) -#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG) -#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG) -#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG) -#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG) -#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG) -#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG) -#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG) -#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG) -#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG) -#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG) -#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG) -#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG) -#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG) -#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG) - - .text - .align 2 - .globl ffi_closure_O32 - .ent ffi_closure_O32 -ffi_closure_O32: -$LFB1: - # Prologue - .frame $fp, SIZEOF_FRAME2, ra - .set noreorder - .cpload t9 - .set reorder - SUBU $sp, SIZEOF_FRAME2 - .cprestore GP_OFF2 -$LCFI4: - REG_S $16, S0_OFF2($sp) # Save s0 - REG_S $fp, FP_OFF2($sp) # Save frame pointer - REG_S ra, RA_OFF2($sp) # Save return address -$LCFI6: - move $fp, $sp - -$LCFI7: - # Store all possible argument registers. If there are more than - # four arguments, then they are stored above where we put a3. - REG_S a0, A0_OFF2($fp) - REG_S a1, A1_OFF2($fp) - REG_S a2, A2_OFF2($fp) - REG_S a3, A3_OFF2($fp) - - # Load ABI enum to s0 - REG_L $16, 20($12) # cif pointer follows tramp. - REG_L $16, 0($16) # abi is first member. - - li $13, 1 # FFI_O32 - bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT - - # Store all possible float/double registers. - s.d $f12, FA_0_0_OFF2($fp) - s.d $f14, FA_1_0_OFF2($fp) -1: - # Call ffi_closure_mips_inner_O32 to do the work. - la t9, ffi_closure_mips_inner_O32 - move a0, $12 # Pointer to the ffi_closure - addu a1, $fp, V0_OFF2 - addu a2, $fp, A0_OFF2 - addu a3, $fp, FA_0_0_OFF2 - jalr t9 - - # Load the return value into the appropriate register. - move $8, $2 - li $9, FFI_TYPE_VOID - beq $8, $9, closure_done - - li $13, 1 # FFI_O32 - bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT - - li $9, FFI_TYPE_FLOAT - l.s $f0, V0_OFF2($fp) - beq $8, $9, closure_done - - li $9, FFI_TYPE_DOUBLE - l.d $f0, V0_OFF2($fp) - beq $8, $9, closure_done -1: - REG_L $3, V1_OFF2($fp) - REG_L $2, V0_OFF2($fp) - -closure_done: - # Epilogue - move $sp, $fp - REG_L $16, S0_OFF2($sp) # Restore s0 - REG_L $fp, FP_OFF2($sp) # Restore frame pointer - REG_L ra, RA_OFF2($sp) # Restore return address - ADDU $sp, SIZEOF_FRAME2 - j ra -$LFE1: - .end ffi_closure_O32 - -/* DWARF-2 unwind info. */ - - .section .eh_frame,"a",@progbits -$Lframe0: - .4byte $LECIE0-$LSCIE0 # Length of Common Information Entry -$LSCIE0: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 4 # CIE Data Alignment Factor - .byte 0x1f # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x00 # FDE Encoding (absptr) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1d - .uleb128 0x0 - .align 2 -$LECIE0: -$LSFDE0: - .4byte $LEFDE0-$LASFDE0 # FDE Length -$LASFDE0: - .4byte $LASFDE0-$Lframe0 # FDE CIE offset - .4byte $LFB0 # FDE initial location - .4byte $LFE0-$LFB0 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI0-$LFB0 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x18 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI2-$LCFI0 - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x1e # $fp - .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x1f # $ra - .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI3-$LCFI2 - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1e - .uleb128 0x18 - .align 2 -$LEFDE0: -$LSFDE1: - .4byte $LEFDE1-$LASFDE1 # FDE Length -$LASFDE1: - .4byte $LASFDE1-$Lframe0 # FDE CIE offset - .4byte $LFB1 # FDE initial location - .4byte $LFE1-$LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI4-$LFB1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x38 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI6-$LCFI4 - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x10 # $16 - .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x1e # $fp - .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x1f # $ra - .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) - .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI7-$LCFI6 - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1e - .uleb128 0x38 - .align 2 -$LEFDE1: - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/eabi.S b/ruby/ext/fiddle/libffi-3.2.1/src/moxie/eabi.S deleted file mode 100644 index ac7aceb1a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/eabi.S +++ /dev/null @@ -1,101 +0,0 @@ -/* ----------------------------------------------------------------------- - eabi.S - Copyright (c) 2012, 2013 Anthony Green - - Moxie Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - .globl ffi_prep_args_EABI - - .text - .p2align 4 - .globl ffi_call_EABI - .type ffi_call_EABI, @function - - # $r0 : ffi_prep_args - # $r1 : &ecif - # $r2 : cif->bytes - # $r3 : fig->flags - # $r4 : ecif.rvalue - # $r5 : fn - -ffi_call_EABI: - push $sp, $r6 - push $sp, $r7 - push $sp, $r8 - dec $sp, 24 - - /* Store incoming args on stack. */ - sto.l 0($sp), $r0 /* ffi_prep_args */ - sto.l 4($sp), $r1 /* ecif */ - sto.l 8($sp), $r2 /* bytes */ - sto.l 12($sp), $r3 /* flags */ - sto.l 16($sp), $r4 /* &rvalue */ - sto.l 20($sp), $r5 /* fn */ - - /* Call ffi_prep_args. */ - mov $r6, $r4 /* Save result buffer */ - mov $r7, $r5 /* Save the target fn */ - mov $r8, $r3 /* Save the flags */ - sub.l $sp, $r2 /* Allocate stack space */ - mov $r0, $sp /* We can stomp over $r0 */ - /* $r1 is already set up */ - jsra ffi_prep_args - - /* Load register arguments. */ - ldo.l $r0, 0($sp) - ldo.l $r1, 4($sp) - ldo.l $r2, 8($sp) - ldo.l $r3, 12($sp) - ldo.l $r4, 16($sp) - ldo.l $r5, 20($sp) - - /* Call the target function. */ - jsr $r7 - - ldi.l $r7, 0xffffffff - cmp $r8, $r7 - beq retstruct - - ldi.l $r7, 4 - cmp $r8, $r7 - bgt ret2reg - - st.l ($r6), $r0 - jmpa retdone - -ret2reg: - st.l ($r6), $r0 - sto.l 4($r6), $r1 - -retstruct: -retdone: - /* Return. */ - ldo.l $r6, -4($fp) - ldo.l $r7, -8($fp) - ldo.l $r8, -12($fp) - ret - .size ffi_call_EABI, .-ffi_call_EABI - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffi.c deleted file mode 100644 index 540a04299..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffi.c +++ /dev/null @@ -1,272 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (C) 2012, 2013 Anthony Green - - Moxie Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void *ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - register int count = 0; - - p_argv = ecif->avalue; - argp = stack; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) - { - *(void **) argp = ecif->rvalue; - argp += 4; - } - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - (i != 0); - i--, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - - if ((*p_arg)->type == FFI_TYPE_STRUCT) - { - z = sizeof(void*); - *(void **) argp = *p_argv; - } - else if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else if (z == sizeof(int)) - { - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - } - else - { - memcpy(argp, *p_argv, z); - } - p_argv++; - argp += z; - count += z; - } - - return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8))); -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - if (cif->rtype->type == FFI_TYPE_STRUCT) - cif->flags = -1; - else - cif->flags = cif->rtype->size; - - cif->bytes = ALIGN (cif->bytes, 8); - - return FFI_OK; -} - -extern void ffi_call_EABI(void *(*)(char *, extended_cif *), - extended_cif *, - unsigned, unsigned, - unsigned *, - void (*fn)(void)); - -void ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_EABI: - ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; - default: - FFI_ASSERT(0); - break; - } -} - -void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, - unsigned arg4, unsigned arg5, unsigned arg6) -{ - /* This function is called by a trampoline. The trampoline stows a - pointer to the ffi_closure object in $r7. We must save this - pointer in a place that will persist while we do our work. */ - register ffi_closure *creg __asm__ ("$r12"); - ffi_closure *closure = creg; - - /* Arguments that don't fit in registers are found on the stack - at a fixed offset above the current frame pointer. */ - register char *frame_pointer __asm__ ("$fp"); - - /* Pointer to a struct return value. */ - void *struct_rvalue = (void *) arg1; - - /* 6 words reserved for register args + 3 words from jsr */ - char *stack_args = frame_pointer + 9*4; - - /* Lay the register arguments down in a continuous chunk of memory. */ - unsigned register_args[6] = - { arg1, arg2, arg3, arg4, arg5, arg6 }; - char *register_args_ptr = (char *) register_args; - - ffi_cif *cif = closure->cif; - ffi_type **arg_types = cif->arg_types; - void **avalue = alloca (cif->nargs * sizeof(void *)); - char *ptr = (char *) register_args; - int i; - - /* preserve struct type return pointer passing */ - if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { - ptr += 4; - register_args_ptr = (char *)®ister_args[1]; - } - - /* Find the address of each argument. */ - for (i = 0; i < cif->nargs; i++) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = ptr + 3; - break; - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = ptr + 2; - break; - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - case FFI_TYPE_POINTER: - avalue[i] = ptr; - break; - case FFI_TYPE_STRUCT: - avalue[i] = *(void**)ptr; - break; - default: - /* This is an 8-byte value. */ - avalue[i] = ptr; - ptr += 4; - break; - } - ptr += 4; - - /* If we've handled more arguments than fit in registers, - start looking at the those passed on the stack. */ - if (ptr == ®ister_args[6]) - ptr = stack_args; - } - - /* Invoke the closure. */ - if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT)) - { - (closure->fun) (cif, struct_rvalue, avalue, closure->user_data); - } - else - { - /* Allocate space for the return value and call the function. */ - long long rvalue; - (closure->fun) (cif, &rvalue, avalue, closure->user_data); - asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue)); - } -} - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned short *tramp = (unsigned short *) &closure->tramp[0]; - unsigned long fn = (long) ffi_closure_eabi; - unsigned long cls = (long) codeloc; - - if (cif->abi != FFI_EABI) - return FFI_BAD_ABI; - - fn = (unsigned long) ffi_closure_eabi; - - tramp[0] = 0x01e0; /* ldi.l $r7, .... */ - tramp[1] = cls >> 16; - tramp[2] = cls & 0xffff; - tramp[3] = 0x1a00; /* jmpa .... */ - tramp[4] = fn >> 16; - tramp[5] = fn & 0xffff; - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffitarget.h deleted file mode 100644 index 623e3ece5..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/moxie/ffitarget.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012, 2013 Anthony Green - Target configuration macros for Moxie - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -/* ---- System specific configurations ----------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_EABI, - FFI_DEFAULT_ABI = FFI_EABI, - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -/* Trampolines are 12-bytes long. See ffi_prep_closure_loc. */ -#define FFI_TRAMPOLINE_SIZE (12) - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffi.c deleted file mode 100644 index 2efa033f9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffi.c +++ /dev/null @@ -1,304 +0,0 @@ -/* libffi support for Altera Nios II. - - Copyright (c) 2013 Mentor Graphics. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - -#include -#include - -#include - -/* The Nios II Processor Reference Handbook defines the procedure call - ABI as follows. - - Arguments are passed as if a structure containing the types of - the arguments were constructed. The first 16 bytes are passed in r4 - through r7, the remainder on the stack. The first 16 bytes of a function - taking variable arguments are passed in r4-r7 in the same way. - - Return values of types up to 8 bytes are returned in r2 and r3. For - return values greater than 8 bytes, the caller must allocate memory for - the result and pass the address as if it were argument 0. - - While this isn't specified explicitly in the ABI documentation, GCC - promotes integral arguments smaller than int size to 32 bits. - - Also of note, the ABI specifies that all structure objects are - aligned to 32 bits even if all their fields have a smaller natural - alignment. See FFI_AGGREGATE_ALIGNMENT. */ - - -/* Declare the assembly language hooks. */ - -extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *), - extended_cif *, - unsigned, - void (*fn) (void)); -extern void ffi_closure_sysv (void); - -/* Perform machine-dependent cif processing. */ - -ffi_status ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* We always want at least 16 bytes in the parameter block since it - simplifies the low-level call function. Also round the parameter - block size up to a multiple of 4 bytes to preserve - 32-bit alignment of the stack pointer. */ - if (cif->bytes < 16) - cif->bytes = 16; - else - cif->bytes = (cif->bytes + 3) & ~3; - - return FFI_OK; -} - - -/* ffi_prep_args is called by the assembly routine to transfer arguments - to the stack using the pointers in the ecif array. - Note that the stack buffer is big enough to fit all the arguments, - but the first 16 bytes will be copied to registers for the actual - call. */ - -void ffi_prep_args (char *stack, extended_cif *ecif) -{ - char *argp = stack; - unsigned int i; - - /* The implicit return value pointer is passed as if it were a hidden - first argument. */ - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT - && ecif->cif->rtype->size > 8) - { - (*(void **) argp) = ecif->rvalue; - argp += 4; - } - - for (i = 0; i < ecif->cif->nargs; i++) - { - void *avalue = ecif->avalue[i]; - ffi_type *atype = ecif->cif->arg_types[i]; - size_t size = atype->size; - size_t alignment = atype->alignment; - - /* Align argp as appropriate for the argument type. */ - if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); - - /* Copy the argument, promoting integral types smaller than a - word to word size. */ - if (size < sizeof (int)) - { - size = sizeof (int); - switch (atype->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) avalue; - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue; - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) avalue; - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue; - break; - - case FFI_TYPE_STRUCT: - memcpy (argp, avalue, atype->size); - break; - - default: - FFI_ASSERT(0); - } - } - else if (size == sizeof (int)) - *(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue; - else - memcpy (argp, avalue, size); - argp += size; - } -} - - -/* Call FN using the prepared CIF. RVALUE points to space allocated by - the caller for the return value, and AVALUE is an array of argument - pointers. */ - -void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) -{ - - extended_cif ecif; - UINT64 result; - - /* If bigret is true, this is the case where a return value of larger - than 8 bytes is handled by being passed by reference as an implicit - argument. */ - int bigret = (cif->rtype->type == FFI_TYPE_STRUCT - && cif->rtype->size > 8); - - ecif.cif = cif; - ecif.avalue = avalue; - - /* Allocate space for return value if this is the pass-by-reference case - and the caller did not provide a buffer. */ - if (rvalue == NULL && bigret) - ecif.rvalue = alloca (cif->rtype->size); - else - ecif.rvalue = rvalue; - - result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn); - - /* Now result contains the 64 bit contents returned from fn in - r2 and r3. Copy the value of the appropriate size to the user-provided - rvalue buffer. */ - if (rvalue && !bigret) - switch (cif->rtype->size) - { - case 1: - *(UINT8 *)rvalue = (UINT8) result; - break; - case 2: - *(UINT16 *)rvalue = (UINT16) result; - break; - case 4: - *(UINT32 *)rvalue = (UINT32) result; - break; - case 8: - *(UINT64 *)rvalue = (UINT64) result; - break; - default: - memcpy (rvalue, (void *)&result, cif->rtype->size); - break; - } -} - -/* This function is invoked from the closure trampoline to invoke - CLOSURE with argument block ARGS. Parse ARGS according to - CLOSURE->cfi and invoke CLOSURE->fun. */ - -static UINT64 -ffi_closure_helper (unsigned char *args, - ffi_closure *closure) -{ - ffi_cif *cif = closure->cif; - unsigned char *argp = args; - void **parsed_args = alloca (cif->nargs * sizeof (void *)); - UINT64 result; - void *retptr; - unsigned int i; - - /* First figure out what to do about the return type. If this is the - big-structure-return case, the first arg is the hidden return buffer - allocated by the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT - && cif->rtype->size > 8) - { - retptr = *((void **) argp); - argp += 4; - } - else - retptr = (void *) &result; - - /* Fill in the array of argument pointers. */ - for (i = 0; i < cif->nargs; i++) - { - size_t size = cif->arg_types[i]->size; - size_t alignment = cif->arg_types[i]->alignment; - - /* Align argp as appropriate for the argument type. */ - if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); - - /* Arguments smaller than an int are promoted to int. */ - if (size < sizeof (int)) - size = sizeof (int); - - /* Store the pointer. */ - parsed_args[i] = argp; - argp += size; - } - - /* Call the user-supplied function. */ - (closure->fun) (cif, retptr, parsed_args, closure->user_data); - return result; -} - - -/* Initialize CLOSURE with a trampoline to call FUN with - CIF and USER_DATA. */ -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun) (ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - int i; - - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - /* The trampoline looks like: - movhi r8, %hi(ffi_closure_sysv) - ori r8, r8, %lo(ffi_closure_sysv) - movhi r9, %hi(ffi_closure_helper) - ori r0, r9, %lo(ffi_closure_helper) - movhi r10, %hi(closure) - ori r10, r10, %lo(closure) - jmp r8 - and then ffi_closure_sysv retrieves the closure pointer out of r10 - in addition to the arguments passed in the normal way for the call, - and invokes ffi_closure_helper. We encode the pointer to - ffi_closure_helper in the trampoline because making a PIC call - to it in ffi_closure_sysv would be messy (it would have to indirect - through the GOT). */ - -#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff) -#define LO(x) (((unsigned int) (x)) & 0xffff) - tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34; - tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14; - tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34; - tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14; - tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34; - tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14; - tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a; -#undef HI -#undef LO - - /* Flush the caches. - See Example 9-4 in the Nios II Software Developer's Handbook. */ - for (i = 0; i < 7; i++) - asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory"); - asm volatile ("flushp" ::: "memory"); - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffitarget.h deleted file mode 100644 index 134d118c1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/ffitarget.h +++ /dev/null @@ -1,52 +0,0 @@ -/* libffi target includes for Altera Nios II. - - Copyright (c) 2013 Mentor Graphics. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -/* Structures have a 4-byte alignment even if all the fields have lesser - alignment requirements. */ -#define FFI_AGGREGATE_ALIGNMENT 4 - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 28 /* 7 instructions */ -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/nios2/sysv.S deleted file mode 100644 index 75f442bbe..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/nios2/sysv.S +++ /dev/null @@ -1,136 +0,0 @@ -/* Low-level libffi support for Altera Nios II. - - Copyright (c) 2013 Mentor Graphics. - - 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. */ - -/* This function is declared on the C side as - - extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *), - extended_cif *ecif, - unsigned nbytes, - void (*fn) (void)); - - On input, the arguments appear as - r4 = arghook - r5 = ecif - r6 = nbytes - r7 = fn -*/ - - .section .text - .align 2 - .global ffi_call_sysv - .type ffi_call_sysv, @function - -ffi_call_sysv: - .cfi_startproc - - /* Create the stack frame, saving r16 so we can use it locally. */ - addi sp, sp, -12 - .cfi_def_cfa_offset 12 - stw ra, 8(sp) - stw fp, 4(sp) - stw r16, 0(sp) - .cfi_offset 31, -4 - .cfi_offset 28, -8 - .cfi_offset 16, -12 - mov fp, sp - .cfi_def_cfa_register 28 - mov r16, r7 - - /* Adjust the stack pointer to create the argument buffer - nbytes long. */ - sub sp, sp, r6 - - /* Call the arghook function. */ - mov r2, r4 /* fn */ - mov r4, sp /* argbuffer */ - callr r2 /* r5 already contains ecif */ - - /* Pop off the first 16 bytes of the argument buffer on the stack, - transferring the contents to the argument registers. */ - ldw r4, 0(sp) - ldw r5, 4(sp) - ldw r6, 8(sp) - ldw r7, 12(sp) - addi sp, sp, 16 - - /* Call the user function, which leaves its result in r2 and r3. */ - callr r16 - - /* Pop off the stack frame. */ - mov sp, fp - ldw ra, 8(sp) - ldw fp, 4(sp) - ldw r16, 0(sp) - addi sp, sp, 12 - ret - .cfi_endproc - .size ffi_call_sysv, .-ffi_call_sysv - - -/* Closure trampolines jump here after putting the C helper address - in r9 and the closure pointer in r10. The user-supplied arguments - to the closure are in the normal places, in r4-r7 and on the - stack. Push the register arguments on the stack too and then call the - C helper function to deal with them. */ - - .section .text - .align 2 - .global ffi_closure_sysv - .type ffi_closure_sysv, @function - -ffi_closure_sysv: - .cfi_startproc - - /* Create the stack frame, pushing the register args on the stack - just below the stack args. This is the same trick illustrated - in Figure 7-3 in the Nios II Processor Reference Handbook, used - for variable arguments and structures passed by value. */ - addi sp, sp, -20 - .cfi_def_cfa_offset 20 - stw ra, 0(sp) - .cfi_offset 31, -20 - stw r4, 4(sp) - .cfi_offset 4, -16 - stw r5, 8(sp) - .cfi_offset 5, -12 - stw r6, 12(sp) - .cfi_offset 6, -8 - stw r7, 16(sp) - .cfi_offset 7, -4 - - /* Call the helper. - r4 = pointer to arguments on stack - r5 = closure pointer (loaded in r10 by the trampoline) - r9 = address of helper function (loaded by trampoline) */ - addi r4, sp, 4 - mov r5, r10 - callr r9 - - /* Pop the stack and return. */ - ldw ra, 0(sp) - addi sp, sp, 20 - .cfi_def_cfa_offset -20 - ret - .cfi_endproc - .size ffi_closure_sysv, .-ffi_closure_sysv - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffi.c deleted file mode 100644 index 2bad938a2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffi.c +++ /dev/null @@ -1,328 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2014 Sebastian Macke - - OpenRISC Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include "ffi_common.h" - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void* ffi_prep_args(char *stack, extended_cif *ecif) -{ - char *stacktemp = stack; - int i, s; - ffi_type **arg; - int count = 0; - int nfixedargs; - - nfixedargs = ecif->cif->nfixedargs; - arg = ecif->cif->arg_types; - void **argv = ecif->avalue; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) - { - *(void **) stack = ecif->rvalue; - stack += 4; - count = 4; - } - for(i=0; icif->nargs; i++) - { - - /* variadic args are saved on stack */ - if ((nfixedargs == 0) && (count < 24)) - { - count = 24; - stack = stacktemp + 24; - } - nfixedargs--; - - s = 4; - switch((*arg)->type) - { - case FFI_TYPE_STRUCT: - *(void **)stack = *argv; - break; - - case FFI_TYPE_SINT8: - *(signed int *) stack = (signed int)*(SINT8 *)(* argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) stack = (signed int)*(SINT16 *)(* argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv); - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - case FFI_TYPE_POINTER: - *(int *)stack = *(int*)(*argv); - break; - - default: /* 8 byte types */ - if (count == 20) /* never split arguments */ - { - stack += 4; - count += 4; - } - s = (*arg)->size; - memcpy(stack, *argv, s); - break; - } - - stack += s; - count += s; - argv++; - arg++; - } - return stacktemp + ((count>24)?24:0); -} - -extern void ffi_call_SYSV(unsigned, - extended_cif *, - void *(*)(int *, extended_cif *), - unsigned *, - void (*fn)(void), - unsigned); - - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - int i; - int size; - ffi_type **arg; - - /* Calculate size to allocate on stack */ - - for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++) - { - if ((*arg)->type == FFI_TYPE_STRUCT) - size += 4; - else - if ((*arg)->size <= 4) - size += 4; - else - size += 8; - } - - /* for variadic functions more space is needed on the stack */ - if (cif->nargs != cif->nfixedargs) - size += 24; - - if (cif->rtype->type == FFI_TYPE_STRUCT) - size += 4; - - - extended_cif ecif; - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags); - break; - default: - FFI_ASSERT(0); - break; - } -} - - -void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8) -{ - register int *sp __asm__ ("r17"); - register int *r13 __asm__ ("r13"); - - ffi_closure* closure = (ffi_closure*) r13; - char *stack_args = sp; - - /* Lay the register arguments down in a continuous chunk of memory. */ - unsigned register_args[6] = - { r3, r4, r5, r6, r7, r8 }; - - /* Pointer to a struct return value. */ - void *struct_rvalue = (void *) r3; - - ffi_cif *cif = closure->cif; - ffi_type **arg_types = cif->arg_types; - void **avalue = alloca (cif->nargs * sizeof(void *)); - char *ptr = (char *) register_args; - int count = 0; - int nfixedargs = cif->nfixedargs; - int i; - - /* preserve struct type return pointer passing */ - - if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ptr += 4; - count = 4; - } - - /* Find the address of each argument. */ - for (i = 0; i < cif->nargs; i++) - { - - /* variadic args are saved on stack */ - if ((nfixedargs == 0) && (count < 24)) - { - ptr = stack_args; - count = 24; - } - nfixedargs--; - - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = ptr + 3; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = ptr + 2; - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_FLOAT: - case FFI_TYPE_POINTER: - avalue[i] = ptr; - break; - - case FFI_TYPE_STRUCT: - avalue[i] = *(void**)ptr; - break; - - default: - /* 8-byte values */ - - /* arguments are never splitted */ - if (ptr == ®ister_args[5]) - ptr = stack_args; - avalue[i] = ptr; - ptr += 4; - count += 4; - break; - } - ptr += 4; - count += 4; - - /* If we've handled more arguments than fit in registers, - start looking at the those passed on the stack. */ - - if (count == 24) - ptr = stack_args; - } - - if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT)) - { - (closure->fun) (cif, struct_rvalue, avalue, closure->user_data); - } else - { - long long rvalue; - (closure->fun) (cif, &rvalue, avalue, closure->user_data); - if (cif->rtype) - asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue)); - } -} - - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - unsigned short *tramp = (unsigned short *) closure->tramp; - unsigned long fn = (unsigned long) ffi_closure_SYSV; - unsigned long cls = (unsigned long) codeloc; - - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - /* write pointers to temporary registers */ - tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */ - tramp[1] = cls >> 16; - tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */ - tramp[3] = cls & 0xFFFF; - - tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */ - tramp[5] = fn >> 16; - tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */ - tramp[7] = fn & 0xFFFF; - - tramp[8] = (0x11 << 10); /* l.jr r15 */ - tramp[9] = 15 << 11; - - tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */ - tramp[11] = 0x0; - - return FFI_OK; -} - - -ffi_status ffi_prep_cif_machdep (ffi_cif *cif) -{ - cif->flags = 0; - - /* structures are returned as pointers */ - if (cif->rtype->type == FFI_TYPE_STRUCT) - cif->flags = FFI_TYPE_STRUCT; - else - if (cif->rtype->size > 4) - cif->flags = FFI_TYPE_UINT64; - - cif->nfixedargs = cif->nargs; - - return FFI_OK; -} - - -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, unsigned int ntotalargs) -{ - ffi_status status; - - status = ffi_prep_cif_machdep (cif); - cif->nfixedargs = nfixedargs; - return status; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffitarget.h deleted file mode 100644 index e55da2861..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/ffitarget.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------- - ffitarget.h - Copyright (c) 2014 Sebastian Macke - - OpenRISC Target configuration macros - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 -#define FFI_TRAMPOLINE_SIZE (24) - -#define FFI_TARGET_SPECIFIC_VARIADIC 1 -#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs; - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/or1k/sysv.S deleted file mode 100644 index df6570ba9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/or1k/sysv.S +++ /dev/null @@ -1,107 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2014 Sebastian Macke - - OpenRISC Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -.text - .globl ffi_call_SYSV - .type ffi_call_SYSV, @function -/* - r3: size to allocate on stack - r4: extended cif structure - r5: function pointer ffi_prep_args - r6: ret address - r7: function to call - r8: flag for return type -*/ - -ffi_call_SYSV: - /* Store registers used on stack */ - l.sw -4(r1), r9 /* return address */ - l.sw -8(r1), r1 /* stack address */ - l.sw -12(r1), r14 /* callee saved registers */ - l.sw -16(r1), r16 - l.sw -20(r1), r18 - l.sw -24(r1), r20 - - l.ori r14, r1, 0x0 /* save stack pointer */ - l.addi r1, r1, -24 - - l.ori r16, r7, 0x0 /* save function address */ - l.ori r18, r6, 0x0 /* save ret address */ - l.ori r20, r8, 0x0 /* save flag */ - - l.sub r1, r1, r3 /* reserve space on stack */ - - /* Call ffi_prep_args */ - l.ori r3, r1, 0x0 /* first argument stack address, second already ecif */ - l.jalr r5 - l.nop - - /* Load register arguments and call*/ - - l.lwz r3, 0(r1) - l.lwz r4, 4(r1) - l.lwz r5, 8(r1) - l.lwz r6, 12(r1) - l.lwz r7, 16(r1) - l.lwz r8, 20(r1) - l.ori r1, r11, 0x0 /* new stack pointer */ - l.jalr r16 - l.nop - - /* handle return values */ - - l.sfeqi r20, FFI_TYPE_STRUCT - l.bf ret /* structs don't return an rvalue */ - l.nop - - /* copy ret address */ - - l.sfeqi r20, FFI_TYPE_UINT64 - l.bnf four_byte_ret /* 8 byte value is returned */ - l.nop - - l.sw 4(r18), r12 - -four_byte_ret: - l.sw 0(r18), r11 - -ret: - /* return */ - l.ori r1, r14, 0x0 /* reset stack pointer */ - l.lwz r9, -4(r1) - l.lwz r1, -8(r1) - l.lwz r14, -12(r1) - l.lwz r16, -16(r1) - l.lwz r18, -20(r1) - l.lwz r20, -24(r1) - l.jr r9 - l.nop - -.size ffi_call_SYSV, .-ffi_call_SYSV diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffi.c deleted file mode 100644 index 4ce2bc6f0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffi.c +++ /dev/null @@ -1,719 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - (c) 2011 Anthony Green - (c) 2008 Red Hat, Inc. - (c) 2006 Free Software Foundation, Inc. - (c) 2003-2004 Randolph Chung - - HPPA Foreign Function Interface - HP-UX PA ABI support - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include - -#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) - -#define MIN_STACK_SIZE 64 -#define FIRST_ARG_SLOT 9 -#define DEBUG_LEVEL 0 - -#define fldw(addr, fpreg) \ - __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg) -#define fstw(fpreg, addr) \ - __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr)) -#define fldd(addr, fpreg) \ - __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg) -#define fstd(fpreg, addr) \ - __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr)) - -#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0) - -static inline int ffi_struct_type(ffi_type *t) -{ - size_t sz = t->size; - - /* Small structure results are passed in registers, - larger ones are passed by pointer. Note that - small structures of size 2, 4 and 8 differ from - the corresponding integer types in that they have - different alignment requirements. */ - - if (sz <= 1) - return FFI_TYPE_UINT8; - else if (sz == 2) - return FFI_TYPE_SMALL_STRUCT2; - else if (sz == 3) - return FFI_TYPE_SMALL_STRUCT3; - else if (sz == 4) - return FFI_TYPE_SMALL_STRUCT4; - else if (sz == 5) - return FFI_TYPE_SMALL_STRUCT5; - else if (sz == 6) - return FFI_TYPE_SMALL_STRUCT6; - else if (sz == 7) - return FFI_TYPE_SMALL_STRUCT7; - else if (sz <= 8) - return FFI_TYPE_SMALL_STRUCT8; - else - return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */ -} - -/* PA has a downward growing stack, which looks like this: - - Offset - [ Variable args ] - SP = (4*(n+9)) arg word N - ... - SP-52 arg word 4 - [ Fixed args ] - SP-48 arg word 3 - SP-44 arg word 2 - SP-40 arg word 1 - SP-36 arg word 0 - [ Frame marker ] - ... - SP-20 RP - SP-4 previous SP - - The first four argument words on the stack are reserved for use by - the callee. Instead, the general and floating registers replace - the first four argument slots. Non FP arguments are passed solely - in the general registers. FP arguments are passed in both general - and floating registers when using libffi. - - Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23. - Non-FP 64-bit args are passed in register pairs, starting - on an odd numbered register (i.e. r25+r26 and r23+r24). - FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L. - FP 64-bit arguments are passed in fr5 and fr7. - - The registers are allocated in the same manner as stack slots. - This allows the callee to save its arguments on the stack if - necessary: - - arg word 3 -> gr23 or fr7L - arg word 2 -> gr24 or fr6L or fr7R - arg word 1 -> gr25 or fr5L - arg word 0 -> gr26 or fr4L or fr5R - - Note that fr4R and fr6R are never used for arguments (i.e., - doubles are not passed in fr4 or fr6). - - The rest of the arguments are passed on the stack starting at SP-52, - but 64-bit arguments need to be aligned to an 8-byte boundary - - This means we can have holes either in the register allocation, - or in the stack. */ - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments - - The following code will put everything into the stack frame - (which was allocated by the asm routine), and on return - the asm routine will load the arguments that should be - passed by register into the appropriate registers - - NOTE: We load floating point args in this function... that means we - assume gcc will not mess with fp regs in here. */ - -void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes) -{ - register unsigned int i; - register ffi_type **p_arg; - register void **p_argv; - unsigned int slot = FIRST_ARG_SLOT; - char *dest_cpy; - size_t len; - - debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, - ecif, bytes); - - p_arg = ecif->cif->arg_types; - p_argv = ecif->avalue; - - for (i = 0; i < ecif->cif->nargs; i++) - { - int type = (*p_arg)->type; - - switch (type) - { - case FFI_TYPE_SINT8: - *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv); - break; - - case FFI_TYPE_UINT8: - *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv); - break; - - case FFI_TYPE_SINT16: - *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv); - break; - - case FFI_TYPE_UINT16: - *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv); - break; - - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), - slot); - *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv); - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* Align slot for 64-bit type. */ - slot += (slot & 1) ? 1 : 2; - *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv); - break; - - case FFI_TYPE_FLOAT: - /* First 4 args go in fr4L - fr7L. */ - debug(3, "Storing UINT32(float) in slot %u\n", slot); - *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv); - switch (slot - FIRST_ARG_SLOT) - { - /* First 4 args go in fr4L - fr7L. */ - case 0: fldw(stack - slot, fr4); break; - case 1: fldw(stack - slot, fr5); break; - case 2: fldw(stack - slot, fr6); break; - case 3: fldw(stack - slot, fr7); break; - } - break; - - case FFI_TYPE_DOUBLE: - /* Align slot for 64-bit type. */ - slot += (slot & 1) ? 1 : 2; - debug(3, "Storing UINT64(double) at slot %u\n", slot); - *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv); - switch (slot - FIRST_ARG_SLOT) - { - /* First 2 args go in fr5, fr7. */ - case 1: fldd(stack - slot, fr5); break; - case 3: fldd(stack - slot, fr7); break; - } - break; - -#ifdef PA_HPUX - case FFI_TYPE_LONGDOUBLE: - /* Long doubles are passed in the same manner as structures - larger than 8 bytes. */ - *(UINT32 *)(stack - slot) = (UINT32)(*p_argv); - break; -#endif - - case FFI_TYPE_STRUCT: - - /* Structs smaller or equal than 4 bytes are passed in one - register. Structs smaller or equal 8 bytes are passed in two - registers. Larger structures are passed by pointer. */ - - len = (*p_arg)->size; - if (len <= 4) - { - dest_cpy = (char *)(stack - slot) + 4 - len; - memcpy(dest_cpy, (char *)*p_argv, len); - } - else if (len <= 8) - { - slot += (slot & 1) ? 1 : 2; - dest_cpy = (char *)(stack - slot) + 8 - len; - memcpy(dest_cpy, (char *)*p_argv, len); - } - else - *(UINT32 *)(stack - slot) = (UINT32)(*p_argv); - break; - - default: - FFI_ASSERT(0); - } - - slot++; - p_arg++; - p_argv++; - } - - /* Make sure we didn't mess up and scribble on the stack. */ - { - unsigned int n; - - debug(5, "Stack setup:\n"); - for (n = 0; n < (bytes + 3) / 4; n++) - { - if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); } - debug(5, "%08x ", *(stack - n)); - } - debug(5, "\n"); - } - - FFI_ASSERT(slot * 4 <= bytes); - - return; -} - -static void ffi_size_stack_pa32(ffi_cif *cif) -{ - ffi_type **ptr; - int i; - int z = 0; /* # stack slots */ - - for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++) - { - int type = (*ptr)->type; - - switch (type) - { - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - z += 2 + (z & 1); /* must start on even regs, so we may waste one */ - break; - -#ifdef PA_HPUX - case FFI_TYPE_LONGDOUBLE: -#endif - case FFI_TYPE_STRUCT: - z += 1; /* pass by ptr, callee will copy */ - break; - - default: /* <= 32-bit values */ - z++; - } - } - - /* We can fit up to 6 args in the default 64-byte stack frame, - if we need more, we need more stack. */ - if (z <= 6) - cif->bytes = MIN_STACK_SIZE; /* min stack size */ - else - cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE); - - debug(3, "Calculated stack size is %u bytes\n", cif->bytes); -} - -/* Perform machine dependent cif processing. */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags = (unsigned) cif->rtype->type; - break; - -#ifdef PA_HPUX - case FFI_TYPE_LONGDOUBLE: - /* Long doubles are treated like a structure. */ - cif->flags = FFI_TYPE_STRUCT; - break; -#endif - - case FFI_TYPE_STRUCT: - /* For the return type we have to check the size of the structures. - If the size is smaller or equal 4 bytes, the result is given back - in one register. If the size is smaller or equal 8 bytes than we - return the result in two registers. But if the size is bigger than - 8 bytes, we work with pointers. */ - cif->flags = ffi_struct_type(cif->rtype); - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - cif->flags = FFI_TYPE_UINT64; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - /* Lucky us, because of the unique PA ABI we get to do our - own stack sizing. */ - switch (cif->abi) - { - case FFI_PA32: - ffi_size_stack_pa32(cif); - break; - - default: - FFI_ASSERT(0); - break; - } - - return FFI_OK; -} - -extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned), - extended_cif *, unsigned, unsigned, unsigned *, - void (*fn)(void)); - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return - value address then we need to make one. */ - - if (rvalue == NULL -#ifdef PA_HPUX - && (cif->rtype->type == FFI_TYPE_STRUCT - || cif->rtype->type == FFI_TYPE_LONGDOUBLE)) -#else - && cif->rtype->type == FFI_TYPE_STRUCT) -#endif - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { - case FFI_PA32: - debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn); - ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT(0); - break; - } -} - -#if FFI_CLOSURES -/* This is more-or-less an inverse of ffi_call -- we have arguments on - the stack, and we need to fill them into a cif structure and invoke - the user function. This really ought to be in asm to make sure - the compiler doesn't do things we don't expect. */ -ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) -{ - ffi_cif *cif; - void **avalue; - void *rvalue; - UINT32 ret[2]; /* function can return up to 64-bits in registers */ - ffi_type **p_arg; - char *tmp; - int i, avn; - unsigned int slot = FIRST_ARG_SLOT; - register UINT32 r28 asm("r28"); - - cif = closure->cif; - - /* If returning via structure, callee will write to our pointer. */ - if (cif->flags == FFI_TYPE_STRUCT) - rvalue = (void *)r28; - else - rvalue = &ret[0]; - - avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); - avn = cif->nargs; - p_arg = cif->arg_types; - - for (i = 0; i < avn; i++) - { - int type = (*p_arg)->type; - - switch (type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - slot += (slot & 1) ? 1 : 2; - avalue[i] = (void *)(stack - slot); - break; - - case FFI_TYPE_FLOAT: -#ifdef PA_LINUX - /* The closure call is indirect. In Linux, floating point - arguments in indirect calls with a prototype are passed - in the floating point registers instead of the general - registers. So, we need to replace what was previously - stored in the current slot with the value in the - corresponding floating point register. */ - switch (slot - FIRST_ARG_SLOT) - { - case 0: fstw(fr4, (void *)(stack - slot)); break; - case 1: fstw(fr5, (void *)(stack - slot)); break; - case 2: fstw(fr6, (void *)(stack - slot)); break; - case 3: fstw(fr7, (void *)(stack - slot)); break; - } -#endif - avalue[i] = (void *)(stack - slot); - break; - - case FFI_TYPE_DOUBLE: - slot += (slot & 1) ? 1 : 2; -#ifdef PA_LINUX - /* See previous comment for FFI_TYPE_FLOAT. */ - switch (slot - FIRST_ARG_SLOT) - { - case 1: fstd(fr5, (void *)(stack - slot)); break; - case 3: fstd(fr7, (void *)(stack - slot)); break; - } -#endif - avalue[i] = (void *)(stack - slot); - break; - -#ifdef PA_HPUX - case FFI_TYPE_LONGDOUBLE: - /* Long doubles are treated like a big structure. */ - avalue[i] = (void *) *(stack - slot); - break; -#endif - - case FFI_TYPE_STRUCT: - /* Structs smaller or equal than 4 bytes are passed in one - register. Structs smaller or equal 8 bytes are passed in two - registers. Larger structures are passed by pointer. */ - if((*p_arg)->size <= 4) - { - avalue[i] = (void *)(stack - slot) + sizeof(UINT32) - - (*p_arg)->size; - } - else if ((*p_arg)->size <= 8) - { - slot += (slot & 1) ? 1 : 2; - avalue[i] = (void *)(stack - slot) + sizeof(UINT64) - - (*p_arg)->size; - } - else - avalue[i] = (void *) *(stack - slot); - break; - - default: - FFI_ASSERT(0); - } - - slot++; - p_arg++; - } - - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], - ret[1]); - - /* Store the result using the lower 2 bytes of the flags. */ - switch (cif->flags) - { - case FFI_TYPE_UINT8: - *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); - break; - case FFI_TYPE_SINT8: - *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); - break; - case FFI_TYPE_UINT16: - *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); - break; - case FFI_TYPE_SINT16: - *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); - break; - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - *(stack - FIRST_ARG_SLOT) = ret[0]; - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - *(stack - FIRST_ARG_SLOT) = ret[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret[1]; - break; - - case FFI_TYPE_DOUBLE: - fldd(rvalue, fr4); - break; - - case FFI_TYPE_FLOAT: - fldw(rvalue, fr4); - break; - - case FFI_TYPE_STRUCT: - /* Don't need a return value, done by caller. */ - break; - - case FFI_TYPE_SMALL_STRUCT2: - case FFI_TYPE_SMALL_STRUCT3: - case FFI_TYPE_SMALL_STRUCT4: - tmp = (void*)(stack - FIRST_ARG_SLOT); - tmp += 4 - cif->rtype->size; - memcpy((void*)tmp, &ret[0], cif->rtype->size); - break; - - case FFI_TYPE_SMALL_STRUCT5: - case FFI_TYPE_SMALL_STRUCT6: - case FFI_TYPE_SMALL_STRUCT7: - case FFI_TYPE_SMALL_STRUCT8: - { - unsigned int ret2[2]; - int off; - - /* Right justify ret[0] and ret[1] */ - switch (cif->flags) - { - case FFI_TYPE_SMALL_STRUCT5: off = 3; break; - case FFI_TYPE_SMALL_STRUCT6: off = 2; break; - case FFI_TYPE_SMALL_STRUCT7: off = 1; break; - default: off = 0; break; - } - - memset (ret2, 0, sizeof (ret2)); - memcpy ((char *)ret2 + off, ret, 8 - off); - - *(stack - FIRST_ARG_SLOT) = ret2[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; - } - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_VOID: - break; - - default: - debug(0, "assert with cif->flags: %d\n",cif->flags); - FFI_ASSERT(0); - break; - } - return FFI_OK; -} - -/* Fill in a closure to refer to the specified fun and user_data. - cif specifies the argument and result types for fun. - The cif must already be prep'ed. */ - -extern void ffi_closure_pa32(void); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - UINT32 *tramp = (UINT32 *)(closure->tramp); -#ifdef PA_HPUX - UINT32 *tmp; -#endif - - if (cif->abi != FFI_PA32) - return FFI_BAD_ABI; - - /* Make a small trampoline that will branch to our - handler function. Use PC-relative addressing. */ - -#ifdef PA_LINUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ - tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush up 2 two lines because of - alignment. */ - __asm__ volatile( - "fdc 0(%0)\n\t" - "fdc %1(%0)\n\t" - "fic 0(%%sr4, %0)\n\t" - "fic %1(%%sr4, %0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : - : "r"((unsigned long)tramp & ~31), - "r"(32 /* stride */) - : "memory"); -#endif - -#ifdef PA_HPUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ - tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ - tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ - tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush three lines because of alignment. */ - __asm__ volatile( - "copy %1,%0\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "ldsid (%1),%0\n\t" - "mtsp %0,%%sr0\n\t" - "copy %1,%0\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : "=&r" ((unsigned long)tmp) - : "r" ((unsigned long)tramp & ~31), - "r" (32/* stride */) - : "memory"); -#endif - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffitarget.h deleted file mode 100644 index fff4c6b38..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/pa/ffitarget.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for hppa. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - -#ifdef PA_LINUX - FFI_PA32, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_PA32 -#endif - -#ifdef PA_HPUX - FFI_PA32, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_PA32 -#endif - -#ifdef PA64_HPUX -#error "PA64_HPUX FFI is not yet implemented" - FFI_PA64, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_PA64 -#endif -} ffi_abi; -#endif - -#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -#ifdef PA_LINUX -#define FFI_TRAMPOLINE_SIZE 32 -#else -#define FFI_TRAMPOLINE_SIZE 40 -#endif - -#define FFI_TYPE_SMALL_STRUCT2 -1 -#define FFI_TYPE_SMALL_STRUCT3 -2 -#define FFI_TYPE_SMALL_STRUCT4 -3 -#define FFI_TYPE_SMALL_STRUCT5 -4 -#define FFI_TYPE_SMALL_STRUCT6 -5 -#define FFI_TYPE_SMALL_STRUCT7 -6 -#define FFI_TYPE_SMALL_STRUCT8 -7 -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/pa/hpux32.S b/ruby/ext/fiddle/libffi-3.2.1/src/pa/hpux32.S deleted file mode 100644 index 40528bad7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/pa/hpux32.S +++ /dev/null @@ -1,368 +0,0 @@ -/* ----------------------------------------------------------------------- - hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc. - (c) 2008 Red Hat, Inc. - based on src/pa/linux.S - - HP-UX PA Foreign Function Interface - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - .LEVEL 1.1 - .SPACE $PRIVATE$ - .IMPORT $global$,DATA - .IMPORT $$dyncall,MILLICODE - .SUBSPA $DATA$ - .align 4 - - /* void ffi_call_pa32(void (*)(char *, extended_cif *), - extended_cif *ecif, - unsigned bytes, - unsigned flags, - unsigned *rvalue, - void (*fn)(void)); - */ - - .export ffi_call_pa32,ENTRY,PRIV_LEV=3 - .import ffi_prep_args_pa32,CODE - - .SPACE $TEXT$ - .SUBSPA $CODE$ - .align 4 - -L$FB1 -ffi_call_pa32 - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4 - .entry - stw %rp, -20(%sp) - copy %r3, %r1 -L$CFI11 - copy %sp, %r3 -L$CFI12 - - /* Setup the stack for calling prep_args... - We want the stack to look like this: - - [ Previous stack ] <- %r3 - - [ 64-bytes register save area ] <- %r4 - - [ Stack space for actual call, passed as ] <- %arg0 - [ arg0 to ffi_prep_args_pa32 ] - - [ Stack for calling prep_args ] <- %sp - */ - - stwm %r1, 64(%sp) - stw %r4, 12(%r3) -L$CFI13 - copy %sp, %r4 - - addl %arg2, %r4, %arg0 ; arg stack - stw %arg3, -48(%r3) ; save flags we need it later - - /* Call prep_args: - %arg0(stack) -- set up above - %arg1(ecif) -- same as incoming param - %arg2(bytes) -- same as incoming param */ - bl ffi_prep_args_pa32,%r2 - ldo 64(%arg0), %sp - ldo -64(%sp), %sp - - /* now %sp should point where %arg0 was pointing. */ - - /* Load the arguments that should be passed in registers - The fp args are loaded by the prep_args function. */ - ldw -36(%sp), %arg0 - ldw -40(%sp), %arg1 - ldw -44(%sp), %arg2 - ldw -48(%sp), %arg3 - - /* in case the function is going to return a structure - we need to give it a place to put the result. */ - ldw -52(%r3), %ret0 ; %ret0 <- rvalue - ldw -56(%r3), %r22 ; %r22 <- function to call - bl $$dyncall, %r31 ; Call the user function - copy %r31, %rp - - /* Prepare to store the result; we need to recover flags and rvalue. */ - ldw -48(%r3), %r21 ; r21 <- flags - ldw -52(%r3), %r20 ; r20 <- rvalue - - /* Store the result according to the return type. The most - likely types should come first. */ - -L$checkint - comib,<>,n FFI_TYPE_INT, %r21, L$checkint8 - b L$done - stw %ret0, 0(%r20) - -L$checkint8 - comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16 - b L$done - stb %ret0, 0(%r20) - -L$checkint16 - comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl - b L$done - sth %ret0, 0(%r20) - -L$checkdbl - comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat - b L$done - fstd %fr4,0(%r20) - -L$checkfloat - comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll - b L$done - fstw %fr4L,0(%r20) - -L$checkll - comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2 - stw %ret0, 0(%r20) - b L$done - stw %ret1, 4(%r20) - -L$checksmst2 - comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3 - /* 2-byte structs are returned in ret0 as ????xxyy. */ - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret0, 0(%r20) - -L$checksmst3 - comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4 - /* 3-byte structs are returned in ret0 as ??xxyyzz. */ - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret0, 0(%r20) - -L$checksmst4 - comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5 - /* 4-byte structs are returned in ret0 as wwxxyyzz. */ - extru %ret0, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret0, 0(%r20) - -L$checksmst5 - comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6 - /* 5 byte values are returned right justified: - ret0 ret1 - 5: ??????aa bbccddee */ - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret1, 0(%r20) - -L$checksmst6 - comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7 - /* 6 byte values are returned right justified: - ret0 ret1 - 6: ????aabb ccddeeff */ - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret1, 0(%r20) - -L$checksmst7 - comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8 - /* 7 byte values are returned right justified: - ret0 ret1 - 7: ??aabbcc ddeeffgg */ - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b L$done - stb %ret1, 0(%r20) - -L$checksmst8 - comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done - /* 8 byte values are returned right justified: - ret0 ret1 - 8: aabbccdd eeffgghh */ - extru %ret0, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stb %ret1, 0(%r20) - -L$done - /* all done, return */ - copy %r4, %sp ; pop arg stack - ldw 12(%r3), %r4 - ldwm -64(%sp), %r3 ; .. and pop stack - ldw -20(%sp), %rp - bv %r0(%rp) - nop - .exit - .procend -L$FE1 - - /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ - - .SPACE $TEXT$ - .SUBSPA $CODE$ - .export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR - .import ffi_closure_inner_pa32,CODE - .align 4 -L$FB2 -ffi_closure_pa32 - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 - .entry - - stw %rp, -20(%sp) - copy %r3, %r1 -L$CFI21 - copy %sp, %r3 -L$CFI22 - stwm %r1, 64(%sp) - - /* Put arguments onto the stack and call ffi_closure_inner. */ - stw %arg0, -36(%r3) - stw %arg1, -40(%r3) - stw %arg2, -44(%r3) - stw %arg3, -48(%r3) - - copy %r21, %arg0 - bl ffi_closure_inner_pa32, %r2 - copy %r3, %arg1 - ldwm -64(%sp), %r3 - ldw -20(%sp), %rp - ldw -36(%sp), %ret0 - bv %r0(%rp) - ldw -40(%sp), %ret1 - .exit - .procend -L$FE2: - - .SPACE $PRIVATE$ - .SUBSPA $DATA$ - - .align 4 - .EXPORT _GLOBAL__F_ffi_call_pa32,DATA -_GLOBAL__F_ffi_call_pa32 -L$frame1: - .word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry -L$SCIE1: - .word 0x0 ;# CIE Identifier Tag - .byte 0x1 ;# CIE Version - .ascii "\0" ;# CIE Augmentation - .uleb128 0x1 ;# CIE Code Alignment Factor - .sleb128 4 ;# CIE Data Alignment Factor - .byte 0x2 ;# CIE RA Column - .byte 0xc ;# DW_CFA_def_cfa - .uleb128 0x1e - .uleb128 0x0 - .align 4 -L$ECIE1: -L$SFDE1: - .word L$EFDE1-L$ASFDE1 ;# FDE Length -L$ASFDE1: - .word L$ASFDE1-L$frame1 ;# FDE CIE offset - .word L$FB1 ;# FDE initial location - .word L$FE1-L$FB1 ;# FDE address range - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI11-L$FB1 - .byte 0x83 ;# DW_CFA_offset, column 0x3 - .uleb128 0x0 - .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] - .uleb128 0x2 - .sleb128 -5 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI12-L$CFI11 - .byte 0xd ;# DW_CFA_def_cfa_register = r3 - .uleb128 0x3 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI13-L$CFI12 - .byte 0x84 ;# DW_CFA_offset, column 0x4 - .uleb128 0x3 - - .align 4 -L$EFDE1: - -L$SFDE2: - .word L$EFDE2-L$ASFDE2 ;# FDE Length -L$ASFDE2: - .word L$ASFDE2-L$frame1 ;# FDE CIE offset - .word L$FB2 ;# FDE initial location - .word L$FE2-L$FB2 ;# FDE address range - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI21-L$FB2 - .byte 0x83 ;# DW_CFA_offset, column 0x3 - .uleb128 0x0 - .byte 0x11 ;# DW_CFA_offset_extended_sf - .uleb128 0x2 - .sleb128 -5 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI22-L$CFI21 - .byte 0xd ;# DW_CFA_def_cfa_register = r3 - .uleb128 0x3 - - .align 4 -L$EFDE2: diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/pa/linux.S b/ruby/ext/fiddle/libffi-3.2.1/src/pa/linux.S deleted file mode 100644 index f11ae7680..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/pa/linux.S +++ /dev/null @@ -1,357 +0,0 @@ -/* ----------------------------------------------------------------------- - linux.S - (c) 2003-2004 Randolph Chung - (c) 2008 Red Hat, Inc. - - HPPA Foreign Function Interface - - 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 RENESAS TECHNOLOGY 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - - .text - .level 1.1 - .align 4 - - /* void ffi_call_pa32(void (*)(char *, extended_cif *), - extended_cif *ecif, - unsigned bytes, - unsigned flags, - unsigned *rvalue, - void (*fn)(void)); - */ - - .export ffi_call_pa32,code - .import ffi_prep_args_pa32,code - - .type ffi_call_pa32, @function -.LFB1: -ffi_call_pa32: - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4 - .entry - stw %rp, -20(%sp) - copy %r3, %r1 -.LCFI11: - - copy %sp, %r3 -.LCFI12: - - /* Setup the stack for calling prep_args... - We want the stack to look like this: - - [ Previous stack ] <- %r3 - - [ 64-bytes register save area ] <- %r4 - - [ Stack space for actual call, passed as ] <- %arg0 - [ arg0 to ffi_prep_args_pa32 ] - - [ Stack for calling prep_args ] <- %sp - */ - - stwm %r1, 64(%sp) - stw %r4, 12(%r3) -.LCFI13: - copy %sp, %r4 - - addl %arg2, %r4, %arg0 /* arg stack */ - stw %arg3, -48(%r3) /* save flags; we need it later */ - - /* Call prep_args: - %arg0(stack) -- set up above - %arg1(ecif) -- same as incoming param - %arg2(bytes) -- same as incoming param */ - bl ffi_prep_args_pa32,%r2 - ldo 64(%arg0), %sp - ldo -64(%sp), %sp - - /* now %sp should point where %arg0 was pointing. */ - - /* Load the arguments that should be passed in registers - The fp args were loaded by the prep_args function. */ - ldw -36(%sp), %arg0 - ldw -40(%sp), %arg1 - ldw -44(%sp), %arg2 - ldw -48(%sp), %arg3 - - /* in case the function is going to return a structure - we need to give it a place to put the result. */ - ldw -52(%r3), %ret0 /* %ret0 <- rvalue */ - ldw -56(%r3), %r22 /* %r22 <- function to call */ - bl $$dyncall, %r31 /* Call the user function */ - copy %r31, %rp - - /* Prepare to store the result; we need to recover flags and rvalue. */ - ldw -48(%r3), %r21 /* r21 <- flags */ - ldw -52(%r3), %r20 /* r20 <- rvalue */ - - /* Store the result according to the return type. */ - -.Lcheckint: - comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8 - b .Ldone - stw %ret0, 0(%r20) - -.Lcheckint8: - comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16 - b .Ldone - stb %ret0, 0(%r20) - -.Lcheckint16: - comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl - b .Ldone - sth %ret0, 0(%r20) - -.Lcheckdbl: - comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat - b .Ldone - fstd %fr4,0(%r20) - -.Lcheckfloat: - comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll - b .Ldone - fstw %fr4L,0(%r20) - -.Lcheckll: - comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2 - stw %ret0, 0(%r20) - b .Ldone - stw %ret1, 4(%r20) - -.Lchecksmst2: - comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3 - /* 2-byte structs are returned in ret0 as ????xxyy. */ - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret0, 0(%r20) - -.Lchecksmst3: - comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4 - /* 3-byte structs are returned in ret0 as ??xxyyzz. */ - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret0, 0(%r20) - -.Lchecksmst4: - comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5 - /* 4-byte structs are returned in ret0 as wwxxyyzz. */ - extru %ret0, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret0, 0(%r20) - -.Lchecksmst5: - comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6 - /* 5 byte values are returned right justified: - ret0 ret1 - 5: ??????aa bbccddee */ - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret1, 0(%r20) - -.Lchecksmst6: - comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7 - /* 6 byte values are returned right justified: - ret0 ret1 - 6: ????aabb ccddeeff */ - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret1, 0(%r20) - -.Lchecksmst7: - comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8 - /* 7 byte values are returned right justified: - ret0 ret1 - 7: ??aabbcc ddeeffgg */ - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - b .Ldone - stb %ret1, 0(%r20) - -.Lchecksmst8: - comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone - /* 8 byte values are returned right justified: - ret0 ret1 - 8: aabbccdd eeffgghh */ - extru %ret0, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret0, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stbs,ma %ret0, 1(%r20) - extru %ret1, 7, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 15, 8, %r22 - stbs,ma %r22, 1(%r20) - extru %ret1, 23, 8, %r22 - stbs,ma %r22, 1(%r20) - stb %ret1, 0(%r20) - -.Ldone: - /* all done, return */ - copy %r4, %sp /* pop arg stack */ - ldw 12(%r3), %r4 - ldwm -64(%sp), %r3 /* .. and pop stack */ - ldw -20(%sp), %rp - bv %r0(%rp) - nop - .exit - .procend -.LFE1: - - /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ - .export ffi_closure_pa32,code - .import ffi_closure_inner_pa32,code - - .type ffi_closure_pa32, @function -.LFB2: -ffi_closure_pa32: - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 - .entry - - stw %rp, -20(%sp) -.LCFI20: - copy %r3, %r1 -.LCFI21: - copy %sp, %r3 -.LCFI22: - stwm %r1, 64(%sp) - - /* Put arguments onto the stack and call ffi_closure_inner. */ - stw %arg0, -36(%r3) - stw %arg1, -40(%r3) - stw %arg2, -44(%r3) - stw %arg3, -48(%r3) - - copy %r21, %arg0 - bl ffi_closure_inner_pa32, %r2 - copy %r3, %arg1 - - ldwm -64(%sp), %r3 - ldw -20(%sp), %rp - ldw -36(%sp), %ret0 - bv %r0(%r2) - ldw -40(%sp), %ret1 - - .exit - .procend -.LFE2: - - .section ".eh_frame",EH_FRAME_FLAGS,@progbits -.Lframe1: - .word .LECIE1-.LSCIE1 ;# Length of Common Information Entry -.LSCIE1: - .word 0x0 ;# CIE Identifier Tag - .byte 0x1 ;# CIE Version - .ascii "\0" ;# CIE Augmentation - .uleb128 0x1 ;# CIE Code Alignment Factor - .sleb128 4 ;# CIE Data Alignment Factor - .byte 0x2 ;# CIE RA Column - .byte 0xc ;# DW_CFA_def_cfa - .uleb128 0x1e - .uleb128 0x0 - .align 4 -.LECIE1: -.LSFDE1: - .word .LEFDE1-.LASFDE1 ;# FDE Length -.LASFDE1: - .word .LASFDE1-.Lframe1 ;# FDE CIE offset - .word .LFB1 ;# FDE initial location - .word .LFE1-.LFB1 ;# FDE address range - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word .LCFI11-.LFB1 - .byte 0x83 ;# DW_CFA_offset, column 0x3 - .uleb128 0x0 - .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] - .uleb128 0x2 - .sleb128 -5 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word .LCFI12-.LCFI11 - .byte 0xd ;# DW_CFA_def_cfa_register = r3 - .uleb128 0x3 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word .LCFI13-.LCFI12 - .byte 0x84 ;# DW_CFA_offset, column 0x4 - .uleb128 0x3 - - .align 4 -.LEFDE1: - -.LSFDE2: - .word .LEFDE2-.LASFDE2 ;# FDE Length -.LASFDE2: - .word .LASFDE2-.Lframe1 ;# FDE CIE offset - .word .LFB2 ;# FDE initial location - .word .LFE2-.LFB2 ;# FDE address range - .byte 0x4 ;# DW_CFA_advance_loc4 - .word .LCFI21-.LFB2 - .byte 0x83 ;# DW_CFA_offset, column 0x3 - .uleb128 0x0 - .byte 0x11 ;# DW_CFA_offset_extended_sf - .uleb128 0x2 - .sleb128 -5 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word .LCFI22-.LCFI21 - .byte 0xd ;# DW_CFA_def_cfa_register = r3 - .uleb128 0x3 - - .align 4 -.LEFDE2: diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix.S deleted file mode 100644 index 349e78c26..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix.S +++ /dev/null @@ -1,328 +0,0 @@ -/* ----------------------------------------------------------------------- - aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc. - based on darwin.S by John Hornkvist - - PowerPC Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - - .set r0,0 - .set r1,1 - .set r2,2 - .set r3,3 - .set r4,4 - .set r5,5 - .set r6,6 - .set r7,7 - .set r8,8 - .set r9,9 - .set r10,10 - .set r11,11 - .set r12,12 - .set r13,13 - .set r14,14 - .set r15,15 - .set r16,16 - .set r17,17 - .set r18,18 - .set r19,19 - .set r20,20 - .set r21,21 - .set r22,22 - .set r23,23 - .set r24,24 - .set r25,25 - .set r26,26 - .set r27,27 - .set r28,28 - .set r29,29 - .set r30,30 - .set r31,31 - .set f0,0 - .set f1,1 - .set f2,2 - .set f3,3 - .set f4,4 - .set f5,5 - .set f6,6 - .set f7,7 - .set f8,8 - .set f9,9 - .set f10,10 - .set f11,11 - .set f12,12 - .set f13,13 - .set f14,14 - .set f15,15 - .set f16,16 - .set f17,17 - .set f18,18 - .set f19,19 - .set f20,20 - .set f21,21 - - .extern .ffi_prep_args - -#define LIBFFI_ASM -#include -#include -#define JUMPTARGET(name) name -#define L(x) x - .file "aix.S" - .toc - - /* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes, - * unsigned int flags, unsigned int *rvalue, - * void (*fn)(), - * void (*prep_args)(extended_cif*, unsigned *const)); - * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args - */ - -.csect .text[PR] - .align 2 - .globl ffi_call_AIX - .globl .ffi_call_AIX -.csect ffi_call_AIX[DS] -ffi_call_AIX: -#ifdef __64BIT__ - .llong .ffi_call_AIX, TOC[tc0], 0 - .csect .text[PR] -.ffi_call_AIX: - /* Save registers we use. */ - mflr r0 - - std r28,-32(r1) - std r29,-24(r1) - std r30,-16(r1) - std r31, -8(r1) - - std r0, 16(r1) - mr r28, r1 /* our AP. */ - stdux r1, r1, r4 - - /* Save arguments over call... */ - mr r31, r5 /* flags, */ - mr r30, r6 /* rvalue, */ - mr r29, r7 /* function address. */ - std r2, 40(r1) - - /* Call ffi_prep_args. */ - mr r4, r1 - bl .ffi_prep_args - nop - - /* Now do the call. */ - ld r0, 0(r29) - ld r2, 8(r29) - ld r11, 16(r29) - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40, r31 - mtctr r0 - /* Load all those argument registers. */ - /* We have set up a nice stack frame, just load it into registers. */ - ld r3, 40+(1*8)(r1) - ld r4, 40+(2*8)(r1) - ld r5, 40+(3*8)(r1) - ld r6, 40+(4*8)(r1) - nop - ld r7, 40+(5*8)(r1) - ld r8, 40+(6*8)(r1) - ld r9, 40+(7*8)(r1) - ld r10,40+(8*8)(r1) - -L1: - /* Load all the FP registers. */ - bf 6,L2 /* 2f + 0x18 */ - lfd f1,-32-(13*8)(r28) - lfd f2,-32-(12*8)(r28) - lfd f3,-32-(11*8)(r28) - lfd f4,-32-(10*8)(r28) - nop - lfd f5,-32-(9*8)(r28) - lfd f6,-32-(8*8)(r28) - lfd f7,-32-(7*8)(r28) - lfd f8,-32-(6*8)(r28) - nop - lfd f9,-32-(5*8)(r28) - lfd f10,-32-(4*8)(r28) - lfd f11,-32-(3*8)(r28) - lfd f12,-32-(2*8)(r28) - nop - lfd f13,-32-(1*8)(r28) - -L2: - /* Make the call. */ - bctrl - ld r2, 40(r1) - - /* Now, deal with the return value. */ - mtcrf 0x01, r31 - - bt 30, L(done_return_value) - bt 29, L(fp_return_value) - std r3, 0(r30) - - /* Fall through... */ - -L(done_return_value): - /* Restore the registers we used and return. */ - mr r1, r28 - ld r0, 16(r28) - ld r28, -32(r1) - mtlr r0 - ld r29, -24(r1) - ld r30, -16(r1) - ld r31, -8(r1) - blr - -L(fp_return_value): - bf 28, L(float_return_value) - stfd f1, 0(r30) - bf 31, L(done_return_value) - stfd f2, 8(r30) - b L(done_return_value) -L(float_return_value): - stfs f1, 0(r30) - b L(done_return_value) - -#else /* ! __64BIT__ */ - - .long .ffi_call_AIX, TOC[tc0], 0 - .csect .text[PR] -.ffi_call_AIX: - /* Save registers we use. */ - mflr r0 - - stw r28,-16(r1) - stw r29,-12(r1) - stw r30, -8(r1) - stw r31, -4(r1) - - stw r0, 8(r1) - mr r28, r1 /* out AP. */ - stwux r1, r1, r4 - - /* Save arguments over call... */ - mr r31, r5 /* flags, */ - mr r30, r6 /* rvalue, */ - mr r29, r7 /* function address, */ - stw r2, 20(r1) - - /* Call ffi_prep_args. */ - mr r4, r1 - bl .ffi_prep_args - nop - - /* Now do the call. */ - lwz r0, 0(r29) - lwz r2, 4(r29) - lwz r11, 8(r29) - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40, r31 - mtctr r0 - /* Load all those argument registers. */ - /* We have set up a nice stack frame, just load it into registers. */ - lwz r3, 20+(1*4)(r1) - lwz r4, 20+(2*4)(r1) - lwz r5, 20+(3*4)(r1) - lwz r6, 20+(4*4)(r1) - nop - lwz r7, 20+(5*4)(r1) - lwz r8, 20+(6*4)(r1) - lwz r9, 20+(7*4)(r1) - lwz r10,20+(8*4)(r1) - -L1: - /* Load all the FP registers. */ - bf 6,L2 /* 2f + 0x18 */ - lfd f1,-16-(13*8)(r28) - lfd f2,-16-(12*8)(r28) - lfd f3,-16-(11*8)(r28) - lfd f4,-16-(10*8)(r28) - nop - lfd f5,-16-(9*8)(r28) - lfd f6,-16-(8*8)(r28) - lfd f7,-16-(7*8)(r28) - lfd f8,-16-(6*8)(r28) - nop - lfd f9,-16-(5*8)(r28) - lfd f10,-16-(4*8)(r28) - lfd f11,-16-(3*8)(r28) - lfd f12,-16-(2*8)(r28) - nop - lfd f13,-16-(1*8)(r28) - -L2: - /* Make the call. */ - bctrl - lwz r2, 20(r1) - - /* Now, deal with the return value. */ - mtcrf 0x01, r31 - - bt 30, L(done_return_value) - bt 29, L(fp_return_value) - stw r3, 0(r30) - bf 28, L(done_return_value) - stw r4, 4(r30) - - /* Fall through... */ - -L(done_return_value): - /* Restore the registers we used and return. */ - mr r1, r28 - lwz r0, 8(r28) - lwz r28,-16(r1) - mtlr r0 - lwz r29,-12(r1) - lwz r30, -8(r1) - lwz r31, -4(r1) - blr - -L(fp_return_value): - bf 28, L(float_return_value) - stfd f1, 0(r30) - b L(done_return_value) -L(float_return_value): - stfs f1, 0(r30) - b L(done_return_value) -#endif - .long 0 - .byte 0,0,0,1,128,4,0,0 -/* END(ffi_call_AIX) */ - -.csect .text[PR] - .align 2 - .globl ffi_call_DARWIN - .globl .ffi_call_DARWIN -.csect ffi_call_DARWIN[DS] -ffi_call_DARWIN: -#ifdef __64BIT__ - .llong .ffi_call_DARWIN, TOC[tc0], 0 -#else - .long .ffi_call_DARWIN, TOC[tc0], 0 -#endif - .csect .text[PR] -.ffi_call_DARWIN: - blr - .long 0 - .byte 0,0,0,0,0,0,0,0 -/* END(ffi_call_DARWIN) */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix_closure.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix_closure.S deleted file mode 100644 index aabd3c3c1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/aix_closure.S +++ /dev/null @@ -1,447 +0,0 @@ -/* ----------------------------------------------------------------------- - aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc. - based on darwin_closure.S - - PowerPC Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - - .set r0,0 - .set r1,1 - .set r2,2 - .set r3,3 - .set r4,4 - .set r5,5 - .set r6,6 - .set r7,7 - .set r8,8 - .set r9,9 - .set r10,10 - .set r11,11 - .set r12,12 - .set r13,13 - .set r14,14 - .set r15,15 - .set r16,16 - .set r17,17 - .set r18,18 - .set r19,19 - .set r20,20 - .set r21,21 - .set r22,22 - .set r23,23 - .set r24,24 - .set r25,25 - .set r26,26 - .set r27,27 - .set r28,28 - .set r29,29 - .set r30,30 - .set r31,31 - .set f0,0 - .set f1,1 - .set f2,2 - .set f3,3 - .set f4,4 - .set f5,5 - .set f6,6 - .set f7,7 - .set f8,8 - .set f9,9 - .set f10,10 - .set f11,11 - .set f12,12 - .set f13,13 - .set f14,14 - .set f15,15 - .set f16,16 - .set f17,17 - .set f18,18 - .set f19,19 - .set f20,20 - .set f21,21 - - .extern .ffi_closure_helper_DARWIN - -#define LIBFFI_ASM -#define JUMPTARGET(name) name -#define L(x) x - .file "aix_closure.S" - .toc -LC..60: - .tc L..60[TC],L..60 - .csect .text[PR] - .align 2 - -.csect .text[PR] - .align 2 - .globl ffi_closure_ASM - .globl .ffi_closure_ASM -.csect ffi_closure_ASM[DS] -ffi_closure_ASM: -#ifdef __64BIT__ - .llong .ffi_closure_ASM, TOC[tc0], 0 - .csect .text[PR] -.ffi_closure_ASM: -/* we want to build up an area for the parameters passed */ -/* in registers (both floating point and integer) */ - - /* we store gpr 3 to gpr 10 (aligned to 4) - in the parents outgoing area */ - std r3, 48+(0*8)(r1) - std r4, 48+(1*8)(r1) - std r5, 48+(2*8)(r1) - std r6, 48+(3*8)(r1) - mflr r0 - - std r7, 48+(4*8)(r1) - std r8, 48+(5*8)(r1) - std r9, 48+(6*8)(r1) - std r10, 48+(7*8)(r1) - std r0, 16(r1) /* save the return address */ - - - /* 48 Bytes (Linkage Area) */ - /* 64 Bytes (params) */ - /* 16 Bytes (result) */ - /* 104 Bytes (13*8 from FPR) */ - /* 8 Bytes (alignment) */ - /* 240 Bytes */ - - stdu r1, -240(r1) /* skip over caller save area - keep stack aligned to 16 */ - - /* next save fpr 1 to fpr 13 (aligned to 8) */ - stfd f1, 128+(0*8)(r1) - stfd f2, 128+(1*8)(r1) - stfd f3, 128+(2*8)(r1) - stfd f4, 128+(3*8)(r1) - stfd f5, 128+(4*8)(r1) - stfd f6, 128+(5*8)(r1) - stfd f7, 128+(6*8)(r1) - stfd f8, 128+(7*8)(r1) - stfd f9, 128+(8*8)(r1) - stfd f10, 128+(9*8)(r1) - stfd f11, 128+(10*8)(r1) - stfd f12, 128+(11*8)(r1) - stfd f13, 128+(12*8)(r1) - - /* set up registers for the routine that actually does the work */ - /* get the context pointer from the trampoline */ - mr r3, r11 - - /* now load up the pointer to the result storage */ - addi r4, r1, 112 - - /* now load up the pointer to the saved gpr registers */ - addi r5, r1, 288 - - /* now load up the pointer to the saved fpr registers */ - addi r6, r1, 128 - - /* make the call */ - bl .ffi_closure_helper_DARWIN - nop - - /* now r3 contains the return type */ - /* so use it to look up in a table */ - /* so we know how to deal with each type */ - - /* look up the proper starting point in table */ - /* by using return type as offset */ - lhz r3, 10(r3) /* load type from return type */ - ld r4, LC..60(2) /* get address of jump table */ - sldi r3, r3, 4 /* now multiply return type by 16 */ - ld r0, 240+16(r1) /* load return address */ - add r3, r3, r4 /* add contents of table to table address */ - mtctr r3 - bctr /* jump to it */ - -/* Each fragment must be exactly 16 bytes long (4 instructions). - Align to 16 byte boundary for cache and dispatch efficiency. */ - .align 4 - -L..60: -/* case FFI_TYPE_VOID */ - mtlr r0 - addi r1, r1, 240 - blr - nop - -/* case FFI_TYPE_INT */ - lwa r3, 112+4(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_FLOAT */ - lfs f1, 112+0(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_DOUBLE */ - lfd f1, 112+0(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_LONGDOUBLE */ - lfd f1, 112+0(r1) - mtlr r0 - lfd f2, 112+8(r1) - b L..finish - -/* case FFI_TYPE_UINT8 */ - lbz r3, 112+7(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_SINT8 */ - lbz r3, 112+7(r1) - mtlr r0 - extsb r3, r3 - b L..finish - -/* case FFI_TYPE_UINT16 */ - lhz r3, 112+6(r1) - mtlr r0 -L..finish: - addi r1, r1, 240 - blr - -/* case FFI_TYPE_SINT16 */ - lha r3, 112+6(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_UINT32 */ - lwz r3, 112+4(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_SINT32 */ - lwa r3, 112+4(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_UINT64 */ - ld r3, 112+0(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_SINT64 */ - ld r3, 112+0(r1) - mtlr r0 - addi r1, r1, 240 - blr - -/* case FFI_TYPE_STRUCT */ - mtlr r0 - addi r1, r1, 240 - blr - nop - -/* case FFI_TYPE_POINTER */ - ld r3, 112+0(r1) - mtlr r0 - addi r1, r1, 240 - blr - -#else /* ! __64BIT__ */ - - .long .ffi_closure_ASM, TOC[tc0], 0 - .csect .text[PR] -.ffi_closure_ASM: -/* we want to build up an area for the parameters passed */ -/* in registers (both floating point and integer) */ - - /* we store gpr 3 to gpr 10 (aligned to 4) - in the parents outgoing area */ - stw r3, 24+(0*4)(r1) - stw r4, 24+(1*4)(r1) - stw r5, 24+(2*4)(r1) - stw r6, 24+(3*4)(r1) - mflr r0 - - stw r7, 24+(4*4)(r1) - stw r8, 24+(5*4)(r1) - stw r9, 24+(6*4)(r1) - stw r10, 24+(7*4)(r1) - stw r0, 8(r1) - - /* 24 Bytes (Linkage Area) */ - /* 32 Bytes (params) */ - /* 16 Bytes (result) */ - /* 104 Bytes (13*8 from FPR) */ - /* 176 Bytes */ - - stwu r1, -176(r1) /* skip over caller save area - keep stack aligned to 16 */ - - /* next save fpr 1 to fpr 13 (aligned to 8) */ - stfd f1, 72+(0*8)(r1) - stfd f2, 72+(1*8)(r1) - stfd f3, 72+(2*8)(r1) - stfd f4, 72+(3*8)(r1) - stfd f5, 72+(4*8)(r1) - stfd f6, 72+(5*8)(r1) - stfd f7, 72+(6*8)(r1) - stfd f8, 72+(7*8)(r1) - stfd f9, 72+(8*8)(r1) - stfd f10, 72+(9*8)(r1) - stfd f11, 72+(10*8)(r1) - stfd f12, 72+(11*8)(r1) - stfd f13, 72+(12*8)(r1) - - /* set up registers for the routine that actually does the work */ - /* get the context pointer from the trampoline */ - mr r3, r11 - - /* now load up the pointer to the result storage */ - addi r4, r1, 56 - - /* now load up the pointer to the saved gpr registers */ - addi r5, r1, 200 - - /* now load up the pointer to the saved fpr registers */ - addi r6, r1, 72 - - /* make the call */ - bl .ffi_closure_helper_DARWIN - nop - - /* now r3 contains the return type */ - /* so use it to look up in a table */ - /* so we know how to deal with each type */ - - /* look up the proper starting point in table */ - /* by using return type as offset */ - lhz r3, 6(r3) /* load type from return type */ - lwz r4, LC..60(2) /* get address of jump table */ - slwi r3, r3, 4 /* now multiply return type by 16 */ - lwz r0, 176+8(r1) /* load return address */ - add r3, r3, r4 /* add contents of table to table address */ - mtctr r3 - bctr /* jump to it */ - -/* Each fragment must be exactly 16 bytes long (4 instructions). - Align to 16 byte boundary for cache and dispatch efficiency. */ - .align 4 - -L..60: -/* case FFI_TYPE_VOID */ - mtlr r0 - addi r1, r1, 176 - blr - nop - -/* case FFI_TYPE_INT */ - lwz r3, 56+0(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_FLOAT */ - lfs f1, 56+0(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_DOUBLE */ - lfd f1, 56+0(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_LONGDOUBLE */ - lfd f1, 56+0(r1) - mtlr r0 - lfd f2, 56+8(r1) - b L..finish - -/* case FFI_TYPE_UINT8 */ - lbz r3, 56+3(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_SINT8 */ - lbz r3, 56+3(r1) - mtlr r0 - extsb r3, r3 - b L..finish - -/* case FFI_TYPE_UINT16 */ - lhz r3, 56+2(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_SINT16 */ - lha r3, 56+2(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_UINT32 */ - lwz r3, 56+0(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_SINT32 */ - lwz r3, 56+0(r1) - mtlr r0 - addi r1, r1, 176 - blr - -/* case FFI_TYPE_UINT64 */ - lwz r3, 56+0(r1) - mtlr r0 - lwz r4, 56+4(r1) - b L..finish - -/* case FFI_TYPE_SINT64 */ - lwz r3, 56+0(r1) - mtlr r0 - lwz r4, 56+4(r1) - b L..finish - -/* case FFI_TYPE_STRUCT */ - mtlr r0 - addi r1, r1, 176 - blr - nop - -/* case FFI_TYPE_POINTER */ - lwz r3, 56+0(r1) - mtlr r0 -L..finish: - addi r1, r1, 176 - blr -#endif -/* END(ffi_closure_ASM) */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/asm.h b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/asm.h deleted file mode 100644 index 994f62d07..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/asm.h +++ /dev/null @@ -1,125 +0,0 @@ -/* ----------------------------------------------------------------------- - asm.h - Copyright (c) 1998 Geoffrey Keating - - PowerPC Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define ASM_GLOBAL_DIRECTIVE .globl - - -#define C_SYMBOL_NAME(name) name -/* Macro for a label. */ -#ifdef __STDC__ -#define C_LABEL(name) name##: -#else -#define C_LABEL(name) name/**/: -#endif - -/* This seems to always be the case on PPC. */ -#define ALIGNARG(log2) log2 -/* For ELF we need the `.type' directive to make shared libs work right. */ -#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; -#define ASM_SIZE_DIRECTIVE(name) .size name,.-name - -/* If compiled for profiling, call `_mcount' at the start of each function. */ -#ifdef PROF -/* The mcount code relies on the return address being on the stack - to locate our caller and so it can restore it; so store one just - for its benefit. */ -#ifdef PIC -#define CALL_MCOUNT \ - .pushsection; \ - .section ".data"; \ - .align ALIGNARG(2); \ -0:.long 0; \ - .previous; \ - mflr %r0; \ - stw %r0,4(%r1); \ - bl _GLOBAL_OFFSET_TABLE_@local-4; \ - mflr %r11; \ - lwz %r0,0b@got(%r11); \ - bl JUMPTARGET(_mcount); -#else /* PIC */ -#define CALL_MCOUNT \ - .section ".data"; \ - .align ALIGNARG(2); \ -0:.long 0; \ - .previous; \ - mflr %r0; \ - lis %r11,0b@ha; \ - stw %r0,4(%r1); \ - addi %r0,%r11,0b@l; \ - bl JUMPTARGET(_mcount); -#endif /* PIC */ -#else /* PROF */ -#define CALL_MCOUNT /* Do nothing. */ -#endif /* PROF */ - -#define ENTRY(name) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(2); \ - C_LABEL(name) \ - CALL_MCOUNT - -#define EALIGN_W_0 /* No words to insert. */ -#define EALIGN_W_1 nop -#define EALIGN_W_2 nop;nop -#define EALIGN_W_3 nop;nop;nop -#define EALIGN_W_4 EALIGN_W_3;nop -#define EALIGN_W_5 EALIGN_W_4;nop -#define EALIGN_W_6 EALIGN_W_5;nop -#define EALIGN_W_7 EALIGN_W_6;nop - -/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes - past a 2^align boundary. */ -#ifdef PROF -#define EALIGN(name, alignt, words) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(2); \ - C_LABEL(name) \ - CALL_MCOUNT \ - b 0f; \ - .align ALIGNARG(alignt); \ - EALIGN_W_##words; \ - 0: -#else /* PROF */ -#define EALIGN(name, alignt, words) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(alignt); \ - EALIGN_W_##words; \ - C_LABEL(name) -#endif - -#define END(name) \ - ASM_SIZE_DIRECTIVE(name) - -#ifdef PIC -#define JUMPTARGET(name) name##@plt -#else -#define JUMPTARGET(name) name -#endif - -/* Local labels stripped out by the linker. */ -#define L(x) .L##x diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin.S deleted file mode 100644 index 066eb82ef..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin.S +++ /dev/null @@ -1,378 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin.S - Copyright (c) 2000 John Hornkvist - Copyright (c) 2004, 2010 Free Software Foundation, Inc. - - PowerPC Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#if defined(__ppc64__) -#define MODE_CHOICE(x, y) y -#else -#define MODE_CHOICE(x, y) x -#endif - -#define machine_choice MODE_CHOICE(ppc7400,ppc64) - -; Define some pseudo-opcodes for size-independent load & store of GPRs ... -#define lgu MODE_CHOICE(lwzu, ldu) -#define lg MODE_CHOICE(lwz,ld) -#define sg MODE_CHOICE(stw,std) -#define sgu MODE_CHOICE(stwu,stdu) -#define sgux MODE_CHOICE(stwux,stdux) - -; ... and the size of GPRs and their storage indicator. -#define GPR_BYTES MODE_CHOICE(4,8) -#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */ -#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */ - -; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04. -#define LINKAGE_SIZE MODE_CHOICE(24,48) -#define PARAM_AREA MODE_CHOICE(32,64) -#define SAVED_LR_OFFSET MODE_CHOICE(8,16) /* save position for lr */ - -/* If there is any FP stuff we make space for all of the regs. */ -#define SAVED_FPR_COUNT 13 -#define FPR_SIZE 8 -#define RESULT_BYTES 16 - -/* This should be kept in step with the same value in ffi_darwin.c. */ -#define ASM_NEEDS_REGISTERS 4 -#define SAVE_REGS_SIZE (ASM_NEEDS_REGISTERS * GPR_BYTES) - -#include -#include - -#define JUMPTARGET(name) name -#define L(x) x - - .text - .align 2 - .globl _ffi_prep_args - - .align 2 - .globl _ffi_call_DARWIN - - /* We arrive here with: - r3 = ptr to extended cif. - r4 = -bytes. - r5 = cif flags. - r6 = ptr to return value. - r7 = fn pointer (user func). - r8 = fn pointer (ffi_prep_args). - r9 = ffi_type* for the ret val. */ - -_ffi_call_DARWIN: -Lstartcode: - mr r12,r8 /* We only need r12 until the call, - so it does not have to be saved. */ -LFB1: - /* Save the old stack pointer as AP. */ - mr r8,r1 -LCFI0: - - /* Save the retval type in parents frame. */ - sg r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8) - - /* Allocate the stack space we need. */ - sgux r1,r1,r4 - - /* Save registers we use. */ - mflr r9 - sg r9,SAVED_LR_OFFSET(r8) - - sg r28,-(4 * GPR_BYTES)(r8) - sg r29,-(3 * GPR_BYTES)(r8) - sg r30,-(2 * GPR_BYTES)(r8) - sg r31,-( GPR_BYTES)(r8) - -#if !defined(POWERPC_DARWIN) - /* The TOC slot is reserved in the Darwin ABI and r2 is volatile. */ - sg r2,(5 * GPR_BYTES)(r1) -#endif - -LCFI1: - - /* Save arguments over call. */ - mr r31,r5 /* flags, */ - mr r30,r6 /* rvalue, */ - mr r29,r7 /* function address, */ - mr r28,r8 /* our AP. */ -LCFI2: - /* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy. */ - mr r4,r1 - li r9,0 - - mtctr r12 /* r12 holds address of _ffi_prep_args. */ - bctrl - -#if !defined(POWERPC_DARWIN) - /* The TOC slot is reserved in the Darwin ABI and r2 is volatile. */ - lg r2,(5 * GPR_BYTES)(r1) -#endif - /* Now do the call. - Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40,r31 - /* Get the address to call into CTR. */ - mtctr r29 - /* Load all those argument registers. - We have set up a nice stack frame, just load it into registers. */ - lg r3, (LINKAGE_SIZE )(r1) - lg r4, (LINKAGE_SIZE + GPR_BYTES)(r1) - lg r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r1) - lg r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r1) - nop - lg r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r1) - lg r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r1) - lg r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r1) - lg r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r1) - -L1: - /* ... Load all the FP registers. */ - bf 6,L2 /* No floats to load. */ - lfd f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28) - lfd f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28) - lfd f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28) - lfd f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28) - nop - lfd f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28) - lfd f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28) - lfd f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28) - lfd f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28) - nop - lfd f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28) - lfd f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28) - lfd f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28) - lfd f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28) - nop - lfd f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28) - -L2: - mr r12,r29 /* Put the target address in r12 as specified. */ - mtctr r12 - nop - nop - - /* Make the call. */ - bctrl - - /* Now, deal with the return value. */ - - /* m64 structure returns can occupy the same set of registers as - would be used to pass such a structure as arg0 - so take care - not to step on any possibly hot regs. */ - - /* Get the flags.. */ - mtcrf 0x03,r31 ; we need c6 & cr7 now. - ; FLAG_RETURNS_NOTHING also covers struct ret-by-ref. - bt 30,L(done_return_value) ; FLAG_RETURNS_NOTHING - bf 27,L(scalar_return_value) ; not FLAG_RETURNS_STRUCT - - /* OK, so we have a struct. */ -#if defined(__ppc64__) - bt 31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case - - /* OK, we have to map the return back to a mem struct. - We are about to trample the parents param area, so recover the - return type. r29 is free, since the call is done. */ - lg r29,(LINKAGE_SIZE + 6 * GPR_BYTES)(r28) - - sg r3, (LINKAGE_SIZE )(r28) - sg r4, (LINKAGE_SIZE + GPR_BYTES)(r28) - sg r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r28) - sg r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r28) - nop - sg r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r28) - sg r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r28) - sg r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r28) - sg r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28) - /* OK, so do the block move - we trust that memcpy will not trample - the fprs... */ - mr r3,r30 ; dest - addi r4,r28,LINKAGE_SIZE ; source - /* The size is a size_t, should be long. */ - lg r5,0(r29) - /* Figure out small structs */ - cmpi 0,r5,4 - bgt L3 ; 1, 2 and 4 bytes have special rules. - cmpi 0,r5,3 - beq L3 ; not 3 - addi r4,r4,8 - subf r4,r5,r4 -L3: - bl _memcpy - - /* ... do we need the FP registers? - recover the flags.. */ - mtcrf 0x03,r31 ; we need c6 & cr7 now. - bf 29,L(done_return_value) /* No floats in the struct. */ - stfd f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28) - stfd f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28) - stfd f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28) - stfd f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28) - nop - stfd f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28) - stfd f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28) - stfd f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28) - stfd f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28) - nop - stfd f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28) - stfd f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28) - stfd f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28) - stfd f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28) - nop - stfd f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28) - - mr r3,r29 ; ffi_type * - mr r4,r30 ; dest - addi r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs - xor r6,r6,r6 - sg r6,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28) - addi r6,r28,(LINKAGE_SIZE + 7 * GPR_BYTES) ; point to a zeroed counter. - bl _darwin64_struct_floats_to_mem - - b L(done_return_value) -#else - stw r3,0(r30) ; m32 the only struct return in reg is 4 bytes. -#endif - b L(done_return_value) - -L(fp_return_value): - /* Do we have long double to store? */ - bf 31,L(fd_return_value) ; FLAG_RETURNS_128BITS - stfd f1,0(r30) - stfd f2,FPR_SIZE(r30) - b L(done_return_value) - -L(fd_return_value): - /* Do we have double to store? */ - bf 28,L(float_return_value) - stfd f1,0(r30) - b L(done_return_value) - -L(float_return_value): - /* We only have a float to store. */ - stfs f1,0(r30) - b L(done_return_value) - -L(scalar_return_value): - bt 29,L(fp_return_value) ; FLAG_RETURNS_FP - ; ffi_arg is defined as unsigned long. - sg r3,0(r30) ; Save the reg. - bf 28,L(done_return_value) ; not FLAG_RETURNS_64BITS - -#if defined(__ppc64__) -L(maybe_return_128): - std r3,0(r30) - bf 31,L(done_return_value) ; not FLAG_RETURNS_128BITS - std r4,8(r30) -#else - stw r4,4(r30) -#endif - - /* Fall through. */ - /* We want this at the end to simplify eh epilog computation. */ - -L(done_return_value): - /* Restore the registers we used and return. */ - lg r29,SAVED_LR_OFFSET(r28) - ; epilog - lg r31,-(1 * GPR_BYTES)(r28) - mtlr r29 - lg r30,-(2 * GPR_BYTES)(r28) - lg r29,-(3 * GPR_BYTES)(r28) - lg r28,-(4 * GPR_BYTES)(r28) - lg r1,0(r1) - blr -LFE1: - .align 1 -/* END(_ffi_call_DARWIN) */ - -/* Provide a null definition of _ffi_call_AIX. */ - .text - .globl _ffi_call_AIX - .align 2 -_ffi_call_AIX: - blr -/* END(_ffi_call_AIX) */ - -/* EH stuff. */ - -#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78) - - .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 ; Length of Common Information Entry -LSCIE1: - .long 0x0 ; CIE Identifier Tag - .byte 0x1 ; CIE Version - .ascii "zR\0" ; CIE Augmentation - .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor - .byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor - .byte 0x41 ; CIE RA Column - .byte 0x1 ; uleb128 0x1; Augmentation size - .byte 0x10 ; FDE Encoding (pcrel) - .byte 0xc ; DW_CFA_def_cfa - .byte 0x1 ; uleb128 0x1 - .byte 0x0 ; uleb128 0x0 - .align LOG2_GPR_BYTES -LECIE1: - - .globl _ffi_call_DARWIN.eh -_ffi_call_DARWIN.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 ; FDE Length -LASFDE1: - .long LASFDE1-EH_frame1 ; FDE CIE offset - .g_long Lstartcode-. ; FDE initial location - .set L$set$3,LFE1-Lstartcode - .g_long L$set$3 ; FDE address range - .byte 0x0 ; uleb128 0x0; Augmentation size - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$4,LCFI0-Lstartcode - .long L$set$4 - .byte 0xd ; DW_CFA_def_cfa_register - .byte 0x08 ; uleb128 0x08 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$5,LCFI1-LCFI0 - .long L$set$5 - .byte 0x11 ; DW_CFA_offset_extended_sf - .byte 0x41 ; uleb128 0x41 - .byte 0x7e ; sleb128 -2 - .byte 0x9f ; DW_CFA_offset, column 0x1f - .byte 0x1 ; uleb128 0x1 - .byte 0x9e ; DW_CFA_offset, column 0x1e - .byte 0x2 ; uleb128 0x2 - .byte 0x9d ; DW_CFA_offset, column 0x1d - .byte 0x3 ; uleb128 0x3 - .byte 0x9c ; DW_CFA_offset, column 0x1c - .byte 0x4 ; uleb128 0x4 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$6,LCFI2-LCFI1 - .long L$set$6 - .byte 0xd ; DW_CFA_def_cfa_register - .byte 0x1c ; uleb128 0x1c - .align LOG2_GPR_BYTES -LEFDE1: - .align 1 - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin_closure.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin_closure.S deleted file mode 100644 index c7734d419..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/darwin_closure.S +++ /dev/null @@ -1,571 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin_closure.S - Copyright (c) 2002, 2003, 2004, 2010, - Free Software Foundation, Inc. - based on ppc_closure.S - - PowerPC Assembly glue. - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#define L(x) x - -#if defined(__ppc64__) -#define MODE_CHOICE(x, y) y -#else -#define MODE_CHOICE(x, y) x -#endif - -#define machine_choice MODE_CHOICE(ppc7400,ppc64) - -; Define some pseudo-opcodes for size-independent load & store of GPRs ... -#define lgu MODE_CHOICE(lwzu, ldu) -#define lg MODE_CHOICE(lwz,ld) -#define sg MODE_CHOICE(stw,std) -#define sgu MODE_CHOICE(stwu,stdu) - -; ... and the size of GPRs and their storage indicator. -#define GPR_BYTES MODE_CHOICE(4,8) -#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */ -#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */ - -; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04. -#define LINKAGE_SIZE MODE_CHOICE(24,48) -#define PARAM_AREA MODE_CHOICE(32,64) - -#define SAVED_CR_OFFSET MODE_CHOICE(4,8) /* save position for CR */ -#define SAVED_LR_OFFSET MODE_CHOICE(8,16) /* save position for lr */ - -/* WARNING: if ffi_type is changed... here be monsters. - Offsets of items within the result type. */ -#define FFI_TYPE_TYPE MODE_CHOICE(6,10) -#define FFI_TYPE_ELEM MODE_CHOICE(8,16) - -#define SAVED_FPR_COUNT 13 -#define FPR_SIZE 8 -/* biggest m64 struct ret is 8GPRS + 13FPRS = 168 bytes - rounded to 16bytes = 176. */ -#define RESULT_BYTES MODE_CHOICE(16,176) - -; The whole stack frame **MUST** be 16byte-aligned. -#define SAVE_SIZE (((LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES)+15) & -16LL) -#define PAD_SIZE (SAVE_SIZE-(LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES)) - -#define PARENT_PARM_BASE (SAVE_SIZE+LINKAGE_SIZE) -#define FP_SAVE_BASE (LINKAGE_SIZE+PARAM_AREA) - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 -; We no longer need the pic symbol stub for Darwin >= 9. -#define BLCLS_HELP _ffi_closure_helper_DARWIN -#define STRUCT_RETVALUE_P _darwin64_struct_ret_by_value_p -#define PASS_STR_FLOATS _darwin64_pass_struct_floats -#undef WANT_STUB -#else -#define BLCLS_HELP L_ffi_closure_helper_DARWIN$stub -#define STRUCT_RETVALUE_P L_darwin64_struct_ret_by_value_p$stub -#define PASS_STR_FLOATS L_darwin64_pass_struct_floats$stub -#define WANT_STUB -#endif - -/* m32/m64 - - The stack layout looks like this: - - | Additional params... | | Higher address - ~ ~ ~ - | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS - |--------------------------------------------| | - | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | - |--------------------------------------------| | - | Reserved 2*4/8 | | - |--------------------------------------------| | - | Space for callee`s LR 4/8 | | - |--------------------------------------------| | - | Saved CR [low word for m64] 4/8 | | - |--------------------------------------------| | - | Current backchain pointer 4/8 |-/ Parent`s frame. - |--------------------------------------------| <+ <<< on entry to - | Result Bytes 16/176 | | - |--------------------------------------------| | - ~ padding to 16-byte alignment ~ ~ - |--------------------------------------------| | - | NUM_FPR_ARG_REGISTERS slots | | - | here fp13 .. fp1 13*8 | | - |--------------------------------------------| | - | R3..R10 8*4/8=32/64 | | NUM_GPR_ARG_REGISTERS - |--------------------------------------------| | - | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | - |--------------------------------------------| | stack | - | Reserved [compiler,binder] 2*4/8 | | grows | - |--------------------------------------------| | down V - | Space for callees LR 4/8 | | - |--------------------------------------------| | lower addresses - | Saved CR [low word for m64] 4/8 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4/8 |-/ during - |--------------------------------------------| <<< call. - -*/ - - .file "darwin_closure.S" - - .machine machine_choice - - .text - .globl _ffi_closure_ASM - .align LOG2_GPR_BYTES -_ffi_closure_ASM: -LFB1: -Lstartcode: - mflr r0 /* extract return address */ - sg r0,SAVED_LR_OFFSET(r1) /* save the return address */ -LCFI0: - sgu r1,-SAVE_SIZE(r1) /* skip over caller save area - keep stack aligned to 16. */ -LCFI1: - /* We want to build up an area for the parameters passed - in registers. (both floating point and integer) */ - - /* Put gpr 3 to gpr 10 in the parents outgoing area... - ... the remainder of any params that overflowed the regs will - follow here. */ - sg r3, (PARENT_PARM_BASE )(r1) - sg r4, (PARENT_PARM_BASE + GPR_BYTES )(r1) - sg r5, (PARENT_PARM_BASE + GPR_BYTES * 2)(r1) - sg r6, (PARENT_PARM_BASE + GPR_BYTES * 3)(r1) - sg r7, (PARENT_PARM_BASE + GPR_BYTES * 4)(r1) - sg r8, (PARENT_PARM_BASE + GPR_BYTES * 5)(r1) - sg r9, (PARENT_PARM_BASE + GPR_BYTES * 6)(r1) - sg r10,(PARENT_PARM_BASE + GPR_BYTES * 7)(r1) - - /* We save fpr 1 to fpr 14 in our own save frame. */ - stfd f1, (FP_SAVE_BASE )(r1) - stfd f2, (FP_SAVE_BASE + FPR_SIZE )(r1) - stfd f3, (FP_SAVE_BASE + FPR_SIZE * 2 )(r1) - stfd f4, (FP_SAVE_BASE + FPR_SIZE * 3 )(r1) - stfd f5, (FP_SAVE_BASE + FPR_SIZE * 4 )(r1) - stfd f6, (FP_SAVE_BASE + FPR_SIZE * 5 )(r1) - stfd f7, (FP_SAVE_BASE + FPR_SIZE * 6 )(r1) - stfd f8, (FP_SAVE_BASE + FPR_SIZE * 7 )(r1) - stfd f9, (FP_SAVE_BASE + FPR_SIZE * 8 )(r1) - stfd f10,(FP_SAVE_BASE + FPR_SIZE * 9 )(r1) - stfd f11,(FP_SAVE_BASE + FPR_SIZE * 10)(r1) - stfd f12,(FP_SAVE_BASE + FPR_SIZE * 11)(r1) - stfd f13,(FP_SAVE_BASE + FPR_SIZE * 12)(r1) - - /* Set up registers for the routine that actually does the work - get the context pointer from the trampoline. */ - mr r3,r11 - - /* Now load up the pointer to the result storage. */ - addi r4,r1,(SAVE_SIZE-RESULT_BYTES) - - /* Now load up the pointer to the saved gpr registers. */ - addi r5,r1,PARENT_PARM_BASE - - /* Now load up the pointer to the saved fpr registers. */ - addi r6,r1,FP_SAVE_BASE - - /* Make the call. */ - bl BLCLS_HELP - - /* r3 contains the rtype pointer... save it since we will need - it later. */ - sg r3,LINKAGE_SIZE(r1) ; ffi_type * result_type - lg r0,0(r3) ; size => r0 - lhz r3,FFI_TYPE_TYPE(r3) ; type => r3 - - /* The helper will have intercepted structure returns and inserted - the caller`s destination address for structs returned by ref. */ - - /* r3 contains the return type so use it to look up in a table - so we know how to deal with each type. */ - - addi r5,r1,(SAVE_SIZE-RESULT_BYTES) /* Otherwise, our return is here. */ - bl Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR. */ - mflr r4 /* Move to r4. */ - slwi r3,r3,4 /* Now multiply return type by 16. */ - add r3,r3,r4 /* Add contents of table to table address. */ - mtctr r3 - bctr /* Jump to it. */ -LFE1: -/* Each of the ret_typeX code fragments has to be exactly 16 bytes long - (4 instructions). For cache effectiveness we align to a 16 byte boundary - first. */ - - .align 4 - - nop - nop - nop -Lget_ret_type0_addr: - blrl - -/* case FFI_TYPE_VOID */ -Lret_type0: - b Lfinish - nop - nop - nop - -/* case FFI_TYPE_INT */ -Lret_type1: - lg r3,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_FLOAT */ -Lret_type2: - lfs f1,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_DOUBLE */ -Lret_type3: - lfd f1,0(r5) - b Lfinish - nop - nop - -/* case FFI_TYPE_LONGDOUBLE */ -Lret_type4: - lfd f1,0(r5) - lfd f2,8(r5) - b Lfinish - nop - -/* case FFI_TYPE_UINT8 */ -Lret_type5: -#if defined(__ppc64__) - lbz r3,7(r5) -#else - lbz r3,3(r5) -#endif - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT8 */ -Lret_type6: -#if defined(__ppc64__) - lbz r3,7(r5) -#else - lbz r3,3(r5) -#endif - extsb r3,r3 - b Lfinish - nop - -/* case FFI_TYPE_UINT16 */ -Lret_type7: -#if defined(__ppc64__) - lhz r3,6(r5) -#else - lhz r3,2(r5) -#endif - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT16 */ -Lret_type8: -#if defined(__ppc64__) - lha r3,6(r5) -#else - lha r3,2(r5) -#endif - b Lfinish - nop - nop - -/* case FFI_TYPE_UINT32 */ -Lret_type9: -#if defined(__ppc64__) - lwz r3,4(r5) -#else - lwz r3,0(r5) -#endif - b Lfinish - nop - nop - -/* case FFI_TYPE_SINT32 */ -Lret_type10: -#if defined(__ppc64__) - lwz r3,4(r5) -#else - lwz r3,0(r5) -#endif - b Lfinish - nop - nop - -/* case FFI_TYPE_UINT64 */ -Lret_type11: -#if defined(__ppc64__) - lg r3,0(r5) - b Lfinish - nop -#else - lwz r3,0(r5) - lwz r4,4(r5) - b Lfinish -#endif - nop - -/* case FFI_TYPE_SINT64 */ -Lret_type12: -#if defined(__ppc64__) - lg r3,0(r5) - b Lfinish - nop -#else - lwz r3,0(r5) - lwz r4,4(r5) - b Lfinish -#endif - nop - -/* case FFI_TYPE_STRUCT */ -Lret_type13: -#if defined(__ppc64__) - lg r3,0(r5) ; we need at least this... - cmpi 0,r0,4 - bgt Lstructend ; not a special small case - b Lsmallstruct ; see if we need more. -#else - cmpi 0,r0,4 - bgt Lfinish ; not by value - lg r3,0(r5) - b Lfinish -#endif -/* case FFI_TYPE_POINTER */ -Lret_type14: - lg r3,0(r5) - b Lfinish - nop - nop - -#if defined(__ppc64__) -Lsmallstruct: - beq Lfour ; continuation of Lret13. - cmpi 0,r0,3 - beq Lfinish ; don`t adjust this - can`t be any floats here... - srdi r3,r3,48 - cmpi 0,r0,2 - beq Lfinish ; .. or here .. - srdi r3,r3,8 - b Lfinish ; .. or here. - -Lfour: - lg r6,LINKAGE_SIZE(r1) ; get the result type - lg r6,FFI_TYPE_ELEM(r6) ; elements array pointer - lg r6,0(r6) ; first element - lhz r0,FFI_TYPE_TYPE(r6) ; OK go the type - cmpi 0,r0,2 ; FFI_TYPE_FLOAT - bne Lfourint - lfs f1,0(r5) ; just one float in the struct. - b Lfinish - -Lfourint: - srdi r3,r3,32 ; four bytes. - b Lfinish - -Lstructend: - lg r3,LINKAGE_SIZE(r1) ; get the result type - bl STRUCT_RETVALUE_P - cmpi 0,r3,0 - beq Lfinish ; nope. - /* Recover a pointer to the results. */ - addi r11,r1,(SAVE_SIZE-RESULT_BYTES) - lg r3,0(r11) ; we need at least this... - lg r4,8(r11) - cmpi 0,r0,16 - beq Lfinish ; special case 16 bytes we don't consider floats. - - /* OK, frustratingly, the process of saving the struct to mem might have - messed with the FPRs, so we have to re-load them :(. - We`ll use our FPRs space again - calling: - void darwin64_pass_struct_floats (ffi_type *s, char *src, - unsigned *nfpr, double **fprs) - We`ll temporarily pinch the first two slots of the param area for local - vars used by the routine. */ - xor r6,r6,r6 - addi r5,r1,PARENT_PARM_BASE ; some space - sg r6,0(r5) ; *nfpr zeroed. - addi r6,r5,8 ; **fprs - addi r3,r1,FP_SAVE_BASE ; pointer to FPRs space - sg r3,0(r6) - mr r4,r11 ; the struct is here... - lg r3,LINKAGE_SIZE(r1) ; ffi_type * result_type. - bl PASS_STR_FLOATS ; get struct floats into FPR save space. - /* See if we used any floats */ - lwz r0,(SAVE_SIZE-RESULT_BYTES)(r1) - cmpi 0,r0,0 - beq Lstructints ; nope. - /* OK load `em up... */ - lfd f1, (FP_SAVE_BASE )(r1) - lfd f2, (FP_SAVE_BASE + FPR_SIZE )(r1) - lfd f3, (FP_SAVE_BASE + FPR_SIZE * 2 )(r1) - lfd f4, (FP_SAVE_BASE + FPR_SIZE * 3 )(r1) - lfd f5, (FP_SAVE_BASE + FPR_SIZE * 4 )(r1) - lfd f6, (FP_SAVE_BASE + FPR_SIZE * 5 )(r1) - lfd f7, (FP_SAVE_BASE + FPR_SIZE * 6 )(r1) - lfd f8, (FP_SAVE_BASE + FPR_SIZE * 7 )(r1) - lfd f9, (FP_SAVE_BASE + FPR_SIZE * 8 )(r1) - lfd f10,(FP_SAVE_BASE + FPR_SIZE * 9 )(r1) - lfd f11,(FP_SAVE_BASE + FPR_SIZE * 10)(r1) - lfd f12,(FP_SAVE_BASE + FPR_SIZE * 11)(r1) - lfd f13,(FP_SAVE_BASE + FPR_SIZE * 12)(r1) - - /* point back at our saved struct. */ -Lstructints: - addi r11,r1,(SAVE_SIZE-RESULT_BYTES) - lg r3,0(r11) ; we end up picking the - lg r4,8(r11) ; first two again. - lg r5,16(r11) - lg r6,24(r11) - lg r7,32(r11) - lg r8,40(r11) - lg r9,48(r11) - lg r10,56(r11) -#endif - -/* case done */ -Lfinish: - addi r1,r1,SAVE_SIZE /* Restore stack pointer. */ - lg r0,SAVED_LR_OFFSET(r1) /* Get return address. */ - mtlr r0 /* Reset link register. */ - blr -Lendcode: - .align 1 - -/* END(ffi_closure_ASM) */ - -/* EH frame stuff. */ -#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78) -/* 176, 400 */ -#define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90) -#define EH_FRAME_OFFSETB MODE_CHOICE(1,3) - - .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 ; Length of Common Information Entry -LSCIE1: - .long 0x0 ; CIE Identifier Tag - .byte 0x1 ; CIE Version - .ascii "zR\0" ; CIE Augmentation - .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor - .byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor - .byte 0x41 ; CIE RA Column - .byte 0x1 ; uleb128 0x1; Augmentation size - .byte 0x10 ; FDE Encoding (pcrel) - .byte 0xc ; DW_CFA_def_cfa - .byte 0x1 ; uleb128 0x1 - .byte 0x0 ; uleb128 0x0 - .align LOG2_GPR_BYTES -LECIE1: - .globl _ffi_closure_ASM.eh -_ffi_closure_ASM.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 ; FDE Length - -LASFDE1: - .long LASFDE1-EH_frame1 ; FDE CIE offset - .g_long Lstartcode-. ; FDE initial location - .set L$set$3,LFE1-Lstartcode - .g_long L$set$3 ; FDE address range - .byte 0x0 ; uleb128 0x0; Augmentation size - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$3,LCFI1-LCFI0 - .long L$set$3 - .byte 0xe ; DW_CFA_def_cfa_offset - .byte EH_FRAME_OFFSETA,EH_FRAME_OFFSETB ; uleb128 176,1/190,3 - .byte 0x4 ; DW_CFA_advance_loc4 - .set L$set$4,LCFI0-Lstartcode - .long L$set$4 - .byte 0x11 ; DW_CFA_offset_extended_sf - .byte 0x41 ; uleb128 0x41 - .byte 0x7e ; sleb128 -2 - .align LOG2_GPR_BYTES -LEFDE1: - .align 1 - -#ifdef WANT_STUB - .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 - .align 5 -L_ffi_closure_helper_DARWIN$stub: - .indirect_symbol _ffi_closure_helper_DARWIN - mflr r0 - bcl 20,31,"L1$spb" -"L1$spb": - mflr r11 - addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb") - mtlr r0 - lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")(r11) - mtctr r12 - bctr - .lazy_symbol_pointer -L_ffi_closure_helper_DARWIN$lazy_ptr: - .indirect_symbol _ffi_closure_helper_DARWIN - .g_long dyld_stub_binding_helper - -#if defined(__ppc64__) - .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 - .align 5 -L_darwin64_struct_ret_by_value_p$stub: - .indirect_symbol _darwin64_struct_ret_by_value_p - mflr r0 - bcl 20,31,"L2$spb" -"L2$spb": - mflr r11 - addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb") - mtlr r0 - lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")(r11) - mtctr r12 - bctr - .lazy_symbol_pointer -L_darwin64_struct_ret_by_value_p$lazy_ptr: - .indirect_symbol _darwin64_struct_ret_by_value_p - .g_long dyld_stub_binding_helper - - .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 - .align 5 -L_darwin64_pass_struct_floats$stub: - .indirect_symbol _darwin64_pass_struct_floats - mflr r0 - bcl 20,31,"L3$spb" -"L3$spb": - mflr r11 - addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb") - mtlr r0 - lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")(r11) - mtctr r12 - bctr - .lazy_symbol_pointer -L_darwin64_pass_struct_floats$lazy_ptr: - .indirect_symbol _darwin64_pass_struct_floats - .g_long dyld_stub_binding_helper -# endif -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi.c deleted file mode 100644 index efb441bbf..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi.c +++ /dev/null @@ -1,141 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (C) 2013 IBM - Copyright (C) 2011 Anthony Green - Copyright (C) 2011 Kyle Moffett - Copyright (C) 2008 Red Hat, Inc - Copyright (C) 2007, 2008 Free Software Foundation, Inc - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - 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 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include "ffi.h" -#include "ffi_common.h" -#include "ffi_powerpc.h" - -#if HAVE_LONG_DOUBLE_VARIANT -/* Adjust ffi_type_longdouble. */ -void FFI_HIDDEN -ffi_prep_types (ffi_abi abi) -{ -# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -# ifdef POWERPC64 - ffi_prep_types_linux64 (abi); -# else - ffi_prep_types_sysv (abi); -# endif -# endif -} -#endif - -/* Perform machine dependent cif processing */ -ffi_status FFI_HIDDEN -ffi_prep_cif_machdep (ffi_cif *cif) -{ -#ifdef POWERPC64 - return ffi_prep_cif_linux64 (cif); -#else - return ffi_prep_cif_sysv (cif); -#endif -} - -ffi_status FFI_HIDDEN -ffi_prep_cif_machdep_var (ffi_cif *cif, - unsigned int nfixedargs MAYBE_UNUSED, - unsigned int ntotalargs MAYBE_UNUSED) -{ -#ifdef POWERPC64 - return ffi_prep_cif_linux64_var (cif, nfixedargs, ntotalargs); -#else - return ffi_prep_cif_sysv (cif); -#endif -} - -void -ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - /* The final SYSV ABI says that structures smaller or equal 8 bytes - are returned in r3/r4. A draft ABI used by linux instead returns - them in memory. - - We bounce-buffer SYSV small struct return values so that sysv.S - can write r3 and r4 to memory without worrying about struct size. - - For ELFv2 ABI, use a bounce buffer for homogeneous structs too, - for similar reasons. */ - unsigned long smst_buffer[8]; - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - ecif.rvalue = rvalue; - if ((cif->flags & FLAG_RETURNS_SMST) != 0) - ecif.rvalue = smst_buffer; - /* Ensure that we have a valid struct return value. - FIXME: Isn't this just papering over a user problem? */ - else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT) - ecif.rvalue = alloca (cif->rtype->size); - -#ifdef POWERPC64 - ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn); -#else - ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); -#endif - - /* Check for a bounce-buffered return value */ - if (rvalue && ecif.rvalue == smst_buffer) - { - unsigned int rsize = cif->rtype->size; -#ifndef __LITTLE_ENDIAN__ - /* The SYSV ABI returns a structure of up to 4 bytes in size - left-padded in r3. */ -# ifndef POWERPC64 - if (rsize <= 4) - memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize); - else -# endif - /* The SYSV ABI returns a structure of up to 8 bytes in size - left-padded in r3/r4, and the ELFv2 ABI similarly returns a - structure of up to 8 bytes in size left-padded in r3. */ - if (rsize <= 8) - memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize); - else -#endif - memcpy (rvalue, smst_buffer, rsize); - } -} - - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif *cif, - void (*fun) (ffi_cif *, void *, void **, void *), - void *user_data, - void *codeloc) -{ -#ifdef POWERPC64 - return ffi_prep_closure_loc_linux64 (closure, cif, fun, user_data, codeloc); -#else - return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc); -#endif -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_darwin.c b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_darwin.c deleted file mode 100644 index cf6fb6d4b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_darwin.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_darwin.c - - Copyright (C) 1998 Geoffrey Keating - Copyright (C) 2001 John Hornkvist - Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. - - FFI support for Darwin and AIX. - - 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 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -extern void ffi_closure_ASM (void); - -enum { - /* The assembly depends on these exact flags. - For Darwin64 (when FLAG_RETURNS_STRUCT is set): - FLAG_RETURNS_FP indicates that the structure embeds FP data. - FLAG_RETURNS_128BITS signals a special struct size that is not - expanded for float content. */ - FLAG_RETURNS_128BITS = 1 << (31-31), /* These go in cr7 */ - FLAG_RETURNS_NOTHING = 1 << (31-30), - FLAG_RETURNS_FP = 1 << (31-29), - FLAG_RETURNS_64BITS = 1 << (31-28), - - FLAG_RETURNS_STRUCT = 1 << (31-27), /* This goes in cr6 */ - - FLAG_ARG_NEEDS_COPY = 1 << (31- 7), - FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ - FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), - FLAG_RETVAL_REFERENCE = 1 << (31- 4) -}; - -/* About the DARWIN ABI. */ -enum { - NUM_GPR_ARG_REGISTERS = 8, - NUM_FPR_ARG_REGISTERS = 13, - LINKAGE_AREA_GPRS = 6 -}; - -enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */ - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments. - - m32/m64 - - The stack layout we want looks like this: - - | Return address from ffi_call_DARWIN | higher addresses - |--------------------------------------------| - | Previous backchain pointer 4/8 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | ASM_NEEDS_REGISTERS=r28-r31 4*(4/8) | | ffi_call_DARWIN - |--------------------------------------------| | - | When we have any FP activity... the | | - | FPRs occupy NUM_FPR_ARG_REGISTERS slots | | - | here fp13 .. fp1 from high to low addr. | | - ~ ~ ~ - | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS - |--------------------------------------------| | - | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | - |--------------------------------------------| | stack | - | Reserved 2*4/8 | | grows | - |--------------------------------------------| | down V - | Space for callee's LR 4/8 | | - |--------------------------------------------| | lower addresses - | Saved CR [low word for m64] 4/8 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4/8 |-/ during - |--------------------------------------------| <<< ffi_call_DARWIN - - */ - -#if defined(POWERPC_DARWIN64) -static void -darwin64_pass_struct_by_value - (ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **); -#endif - -/* This depends on GPR_SIZE = sizeof (unsigned long) */ - -void -ffi_prep_args (extended_cif *ecif, unsigned long *const stack) -{ - const unsigned bytes = ecif->cif->bytes; - const unsigned flags = ecif->cif->flags; - const unsigned nargs = ecif->cif->nargs; -#if !defined(POWERPC_DARWIN64) - const ffi_abi abi = ecif->cif->abi; -#endif - - /* 'stacktop' points at the previous backchain pointer. */ - unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long)); - - /* 'fpr_base' points at the space for fpr1, and grows upwards as - we use FPR registers. */ - double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS; - int gp_count = 0, fparg_count = 0; - - /* 'next_arg' grows up as we put parameters in it. */ - unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions. */ - - int i; - double double_tmp; - void **p_argv = ecif->avalue; - unsigned long gprvalue; - ffi_type** ptr = ecif->cif->arg_types; -#if !defined(POWERPC_DARWIN64) - char *dest_cpy; -#endif - unsigned size_al = 0; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT(((unsigned) (char *) stack & 0xF) == 0); - FFI_ASSERT(((unsigned) (char *) stacktop & 0xF) == 0); - FFI_ASSERT((bytes & 0xF) == 0); - - /* Deal with return values that are actually pass-by-reference. - Rule: - Return values are referenced by r3, so r4 is the first parameter. */ - - if (flags & FLAG_RETVAL_REFERENCE) - *next_arg++ = (unsigned long) (char *) ecif->rvalue; - - /* Now for the arguments. */ - for (i = nargs; i > 0; i--, ptr++, p_argv++) - { - switch ((*ptr)->type) - { - /* If a floating-point parameter appears before all of the general- - purpose registers are filled, the corresponding GPRs that match - the size of the floating-point parameter are skipped. */ - case FFI_TYPE_FLOAT: - double_tmp = *(float *) *p_argv; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; -#if defined(POWERPC_DARWIN) - *(float *)next_arg = *(float *) *p_argv; -#else - *(double *)next_arg = double_tmp; -#endif - next_arg++; - gp_count++; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_DOUBLE: - double_tmp = *(double *) *p_argv; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; - *(double *)next_arg = double_tmp; -#ifdef POWERPC64 - next_arg++; - gp_count++; -#else - next_arg += 2; - gp_count += 2; -#endif - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - - case FFI_TYPE_LONGDOUBLE: -# if defined(POWERPC64) && !defined(POWERPC_DARWIN64) - /* ??? This will exceed the regs count when the value starts at fp13 - and it will not put the extra bit on the stack. */ - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *(long double *) fpr_base++ = *(long double *) *p_argv; - else - *(long double *) next_arg = *(long double *) *p_argv; - next_arg += 2; - fparg_count += 2; -# else - double_tmp = ((double *) *p_argv)[0]; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; - *(double *) next_arg = double_tmp; -# if defined(POWERPC_DARWIN64) - next_arg++; - gp_count++; -# else - next_arg += 2; - gp_count += 2; -# endif - fparg_count++; - double_tmp = ((double *) *p_argv)[1]; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; - *(double *) next_arg = double_tmp; -# if defined(POWERPC_DARWIN64) - next_arg++; - gp_count++; -# else - next_arg += 2; - gp_count += 2; -# endif - fparg_count++; -# endif - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; -#endif - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#ifdef POWERPC64 - gprvalue = *(long long *) *p_argv; - goto putgpr; -#else - *(long long *) next_arg = *(long long *) *p_argv; - next_arg += 2; - gp_count += 2; -#endif - break; - case FFI_TYPE_POINTER: - gprvalue = *(unsigned long *) *p_argv; - goto putgpr; - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char *) *p_argv; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char *) *p_argv; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short *) *p_argv; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short *) *p_argv; - goto putgpr; - - case FFI_TYPE_STRUCT: - size_al = (*ptr)->size; -#if defined(POWERPC_DARWIN64) - next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment); - darwin64_pass_struct_by_value (*ptr, (char *) *p_argv, - (unsigned) size_al, - (unsigned int *) &fparg_count, - &fpr_base, &next_arg); -#else - dest_cpy = (char *) next_arg; - - /* If the first member of the struct is a double, then include enough - padding in the struct size to align it to double-word. */ - if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); - -# if defined(POWERPC64) - FFI_ASSERT (abi != FFI_DARWIN); - memcpy ((char *) dest_cpy, (char *) *p_argv, size_al); - next_arg += (size_al + 7) / 8; -# else - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. - Structures with 3 byte in size are padded upwards. */ - if (size_al < 3 && abi == FFI_DARWIN) - dest_cpy += 4 - size_al; - - memcpy((char *) dest_cpy, (char *) *p_argv, size_al); - next_arg += (size_al + 3) / 4; -# endif -#endif - break; - - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - gprvalue = *(signed int *) *p_argv; - goto putgpr; - - case FFI_TYPE_UINT32: - gprvalue = *(unsigned int *) *p_argv; - putgpr: - *next_arg++ = gprvalue; - gp_count++; - break; - default: - break; - } - } - - /* Check that we didn't overrun the stack... */ - /* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); - FFI_ASSERT((unsigned *)fpr_base - <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); - FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); */ -} - -#if defined(POWERPC_DARWIN64) - -/* See if we can put some of the struct into fprs. - This should not be called for structures of size 16 bytes, since these are not - broken out this way. */ -static void -darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr) -{ - int i; - - FFI_ASSERT (s->type == FFI_TYPE_STRUCT) - - for (i = 0; s->elements[i] != NULL; i++) - { - ffi_type *p = s->elements[i]; - switch (p->type) - { - case FFI_TYPE_STRUCT: - darwin64_scan_struct_for_floats (p, nfpr); - break; - case FFI_TYPE_LONGDOUBLE: - (*nfpr) += 2; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_FLOAT: - (*nfpr) += 1; - break; - default: - break; - } - } -} - -static int -darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr) -{ - unsigned struct_offset=0, i; - - for (i = 0; s->elements[i] != NULL; i++) - { - char *item_base; - ffi_type *p = s->elements[i]; - /* Find the start of this item (0 for the first one). */ - if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); - - item_base = src + struct_offset; - - switch (p->type) - { - case FFI_TYPE_STRUCT: - if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr)) - return 1; - break; - case FFI_TYPE_LONGDOUBLE: - if (*nfpr >= NUM_FPR_ARG_REGISTERS) - return 1; - (*nfpr) += 1; - item_base += 8; - /* FALL THROUGH */ - case FFI_TYPE_DOUBLE: - if (*nfpr >= NUM_FPR_ARG_REGISTERS) - return 1; - (*nfpr) += 1; - break; - case FFI_TYPE_FLOAT: - if (*nfpr >= NUM_FPR_ARG_REGISTERS) - return 1; - (*nfpr) += 1; - break; - default: - /* If we try and place any item, that is non-float, once we've - exceeded the 8 GPR mark, then we can't fit the struct. */ - if ((unsigned long)item_base >= 8*8) - return 1; - break; - } - /* now count the size of what we just used. */ - struct_offset += p->size; - } - return 0; -} - -/* Can this struct be returned by value? */ -int -darwin64_struct_ret_by_value_p (ffi_type *s) -{ - unsigned nfp = 0; - - FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT); - - /* The largest structure we can return is 8long + 13 doubles. */ - if (s->size > 168) - return 0; - - /* We can't pass more than 13 floats. */ - darwin64_scan_struct_for_floats (s, &nfp); - if (nfp > 13) - return 0; - - /* If there are not too many floats, and the struct is - small enough to accommodate in the GPRs, then it must be OK. */ - if (s->size <= 64) - return 1; - - /* Well, we have to look harder. */ - nfp = 0; - if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp)) - return 0; - - return 1; -} - -void -darwin64_pass_struct_floats (ffi_type *s, char *src, - unsigned *nfpr, double **fprs) -{ - int i; - double *fpr_base = *fprs; - unsigned struct_offset = 0; - - /* We don't assume anything about the alignment of the source. */ - for (i = 0; s->elements[i] != NULL; i++) - { - char *item_base; - ffi_type *p = s->elements[i]; - /* Find the start of this item (0 for the first one). */ - if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); - item_base = src + struct_offset; - - switch (p->type) - { - case FFI_TYPE_STRUCT: - darwin64_pass_struct_floats (p, item_base, nfpr, - &fpr_base); - break; - case FFI_TYPE_LONGDOUBLE: - if (*nfpr < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = *(double *)item_base; - (*nfpr) += 1; - item_base += 8; - /* FALL THROUGH */ - case FFI_TYPE_DOUBLE: - if (*nfpr < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = *(double *)item_base; - (*nfpr) += 1; - break; - case FFI_TYPE_FLOAT: - if (*nfpr < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = (double) *(float *)item_base; - (*nfpr) += 1; - break; - default: - break; - } - /* now count the size of what we just used. */ - struct_offset += p->size; - } - /* Update the scores. */ - *fprs = fpr_base; -} - -/* Darwin64 special rules. - Break out a struct into params and float registers. */ -static void -darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size, - unsigned *nfpr, double **fprs, unsigned long **arg) -{ - unsigned long *next_arg = *arg; - char *dest_cpy = (char *)next_arg; - - FFI_ASSERT (s->type == FFI_TYPE_STRUCT) - - if (!size) - return; - - /* First... special cases. */ - if (size < 3 - || (size == 4 - && s->elements[0] - && s->elements[0]->type != FFI_TYPE_FLOAT)) - { - /* Must be at least one GPR, padding is unspecified in value, - let's make it zero. */ - *next_arg = 0UL; - dest_cpy += 8 - size; - memcpy ((char *) dest_cpy, src, size); - next_arg++; - } - else if (size == 16) - { - memcpy ((char *) dest_cpy, src, size); - next_arg += 2; - } - else - { - /* now the general case, we consider embedded floats. */ - memcpy ((char *) dest_cpy, src, size); - darwin64_pass_struct_floats (s, src, nfpr, fprs); - next_arg += (size+7)/8; - } - - *arg = next_arg; -} - -double * -darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf) -{ - int i; - unsigned struct_offset = 0; - - /* We don't assume anything about the alignment of the source. */ - for (i = 0; s->elements[i] != NULL; i++) - { - char *item_base; - ffi_type *p = s->elements[i]; - /* Find the start of this item (0 for the first one). */ - if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); - item_base = dest + struct_offset; - - switch (p->type) - { - case FFI_TYPE_STRUCT: - fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf); - break; - case FFI_TYPE_LONGDOUBLE: - if (*nf < NUM_FPR_ARG_REGISTERS) - { - *(double *)item_base = *fprs++ ; - (*nf) += 1; - } - item_base += 8; - /* FALL THROUGH */ - case FFI_TYPE_DOUBLE: - if (*nf < NUM_FPR_ARG_REGISTERS) - { - *(double *)item_base = *fprs++ ; - (*nf) += 1; - } - break; - case FFI_TYPE_FLOAT: - if (*nf < NUM_FPR_ARG_REGISTERS) - { - *(float *)item_base = (float) *fprs++ ; - (*nf) += 1; - } - break; - default: - break; - } - /* now count the size of what we just used. */ - struct_offset += p->size; - } - return fprs; -} - -#endif - -/* Adjust the size of S to be correct for Darwin. - On Darwin m32, the first field of a structure has natural alignment. - On Darwin m64, all fields have natural alignment. */ - -static void -darwin_adjust_aggregate_sizes (ffi_type *s) -{ - int i; - - if (s->type != FFI_TYPE_STRUCT) - return; - - s->size = 0; - for (i = 0; s->elements[i] != NULL; i++) - { - ffi_type *p; - int align; - - p = s->elements[i]; - if (p->type == FFI_TYPE_STRUCT) - darwin_adjust_aggregate_sizes (p); -#if defined(POWERPC_DARWIN64) - /* Natural alignment for all items. */ - align = p->alignment; -#else - /* Natural alignment for the first item... */ - if (i == 0) - align = p->alignment; - else if (p->alignment == 16 || p->alignment < 4) - /* .. subsequent items with vector or align < 4 have natural align. */ - align = p->alignment; - else - /* .. or align is 4. */ - align = 4; -#endif - /* Pad, if necessary, before adding the current item. */ - s->size = ALIGN(s->size, align) + p->size; - } - - s->size = ALIGN(s->size, s->alignment); - - /* This should not be necessary on m64, but harmless. */ - if (s->elements[0]->type == FFI_TYPE_UINT64 - || s->elements[0]->type == FFI_TYPE_SINT64 - || s->elements[0]->type == FFI_TYPE_DOUBLE - || s->elements[0]->alignment == 8) - s->alignment = s->alignment > 8 ? s->alignment : 8; - /* Do not add additional tail padding. */ -} - -/* Adjust the size of S to be correct for AIX. - Word-align double unless it is the first member of a structure. */ - -static void -aix_adjust_aggregate_sizes (ffi_type *s) -{ - int i; - - if (s->type != FFI_TYPE_STRUCT) - return; - - s->size = 0; - for (i = 0; s->elements[i] != NULL; i++) - { - ffi_type *p; - int align; - - p = s->elements[i]; - aix_adjust_aggregate_sizes (p); - align = p->alignment; - if (i != 0 && p->type == FFI_TYPE_DOUBLE) - align = 4; - s->size = ALIGN(s->size, align) + p->size; - } - - s->size = ALIGN(s->size, s->alignment); - - if (s->elements[0]->type == FFI_TYPE_UINT64 - || s->elements[0]->type == FFI_TYPE_SINT64 - || s->elements[0]->type == FFI_TYPE_DOUBLE - || s->elements[0]->alignment == 8) - s->alignment = s->alignment > 8 ? s->alignment : 8; - /* Do not add additional tail padding. */ -} - -/* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* All this is for the DARWIN ABI. */ - unsigned i; - ffi_type **ptr; - unsigned bytes; - unsigned fparg_count = 0, intarg_count = 0; - unsigned flags = 0; - unsigned size_al = 0; - - /* All the machine-independent calculation of cif->bytes will be wrong. - All the calculation of structure sizes will also be wrong. - Redo the calculation for DARWIN. */ - - if (cif->abi == FFI_DARWIN) - { - darwin_adjust_aggregate_sizes (cif->rtype); - for (i = 0; i < cif->nargs; i++) - darwin_adjust_aggregate_sizes (cif->arg_types[i]); - } - - if (cif->abi == FFI_AIX) - { - aix_adjust_aggregate_sizes (cif->rtype); - for (i = 0; i < cif->nargs; i++) - aix_adjust_aggregate_sizes (cif->arg_types[i]); - } - - /* Space for the frame pointer, callee's LR, CR, etc, and for - the asm's temp regs. */ - - bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long); - - /* Return value handling. - The rules m32 are as follows: - - 32-bit (or less) integer values are returned in gpr3; - - structures of size <= 4 bytes also returned in gpr3; - - 64-bit integer values [??? and structures between 5 and 8 bytes] are - returned in gpr3 and gpr4; - - Single/double FP values are returned in fpr1; - - Long double FP (if not equivalent to double) values are returned in - fpr1 and fpr2; - m64: - - 64-bit or smaller integral values are returned in GPR3 - - Single/double FP values are returned in fpr1; - - Long double FP values are returned in fpr1 and fpr2; - m64 Structures: - - If the structure could be accommodated in registers were it to be the - first argument to a routine, then it is returned in those registers. - m32/m64 structures otherwise: - - Larger structures values are allocated space and a pointer is passed - as the first argument. */ - switch (cif->rtype->type) - { - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - flags |= FLAG_RETURNS_128BITS; - flags |= FLAG_RETURNS_FP; - break; -#endif - - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#ifdef POWERPC64 - case FFI_TYPE_POINTER: -#endif - flags |= FLAG_RETURNS_64BITS; - break; - - case FFI_TYPE_STRUCT: -#if defined(POWERPC_DARWIN64) - { - /* Can we fit the struct into regs? */ - if (darwin64_struct_ret_by_value_p (cif->rtype)) - { - unsigned nfpr = 0; - flags |= FLAG_RETURNS_STRUCT; - if (cif->rtype->size != 16) - darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ; - else - flags |= FLAG_RETURNS_128BITS; - /* Will be 0 for 16byte struct. */ - if (nfpr) - flags |= FLAG_RETURNS_FP; - } - else /* By ref. */ - { - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; - } - } -#elif defined(DARWIN_PPC) - if (cif->rtype->size <= 4) - flags |= FLAG_RETURNS_STRUCT; - else /* else by reference. */ - { - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; - } -#else /* assume we pass by ref. */ - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; -#endif - break; - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the - first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest - goes on the stack. - ??? Structures are passed as a pointer to a copy of the structure. - Stuff on the stack needs to keep proper alignment. - For m64 the count is effectively of half-GPRs. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - unsigned align_words; - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - fparg_count++; -#if !defined(POWERPC_DARWIN64) - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && (intarg_count & 0x01) != 0) - intarg_count++; -#endif - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - fparg_count += 2; - /* If this FP arg is going on the stack, it must be - 16-byte-aligned. */ - if (fparg_count >= NUM_FPR_ARG_REGISTERS) -#if defined (POWERPC64) - intarg_count = ALIGN(intarg_count, 2); -#else - intarg_count = ALIGN(intarg_count, 4); -#endif - break; -#endif - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#if defined(POWERPC64) - intarg_count++; -#else - /* 'long long' arguments are passed as two words, but - either both words must fit in registers or both go - on the stack. If they go on the stack, they must - be 8-byte-aligned. */ - if (intarg_count == NUM_GPR_ARG_REGISTERS-1 - || (intarg_count >= NUM_GPR_ARG_REGISTERS - && (intarg_count & 0x01) != 0)) - intarg_count++; - intarg_count += 2; -#endif - break; - - case FFI_TYPE_STRUCT: - size_al = (*ptr)->size; -#if defined(POWERPC_DARWIN64) - align_words = (*ptr)->alignment >> 3; - if (align_words) - intarg_count = ALIGN(intarg_count, align_words); - /* Base size of the struct. */ - intarg_count += (size_al + 7) / 8; - /* If 16 bytes then don't worry about floats. */ - if (size_al != 16) - /* Scan through for floats to be placed in regs. */ - darwin64_scan_struct_for_floats (*ptr, &fparg_count) ; -#else - align_words = (*ptr)->alignment >> 2; - if (align_words) - intarg_count = ALIGN(intarg_count, align_words); - /* If the first member of the struct is a double, then align - the struct to double-word. - if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); */ -# ifdef POWERPC64 - intarg_count += (size_al + 7) / 8; -# else - intarg_count += (size_al + 3) / 4; -# endif -#endif - break; - - default: - /* Everything else is passed as a 4-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } - } - - if (fparg_count != 0) - flags |= FLAG_FP_ARGUMENTS; - -#if defined(POWERPC_DARWIN64) - /* Space to image the FPR registers, if needed - which includes when they might be - used in a struct return. */ - if (fparg_count != 0 - || ((flags & FLAG_RETURNS_STRUCT) - && (flags & FLAG_RETURNS_FP))) - bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); -#else - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); -#endif - - /* Stack space. */ -#ifdef POWERPC64 - if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count + fparg_count) * sizeof(long); -#else - if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count + 2 * fparg_count) * sizeof(long); -#endif - else - bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); - - /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = ALIGN(bytes, 16) ; - - cif->flags = flags; - cif->bytes = bytes; - - return FFI_OK; -} - -extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *, - void (*fn)(void), void (*fn2)(void)); - -extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *, - void (*fn)(void), void (*fn2)(void), ffi_type*); - -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return - value address then we need to make one. */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca (cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_AIX: - ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn, - FFI_FN(ffi_prep_args)); - break; - case FFI_DARWIN: - ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn, - FFI_FN(ffi_prep_args), cif->rtype); - break; - default: - FFI_ASSERT(0); - break; - } -} - -static void flush_icache(char *); -static void flush_range(char *, int); - -/* The layout of a function descriptor. A C function pointer really - points to one of these. */ - -typedef struct aix_fd_struct { - void *code_pointer; - void *toc; -} aix_fd; - -/* here I'd like to add the stack frame layout we use in darwin_closure.S - and aix_closure.S - - m32/m64 - - The stack layout looks like this: - - | Additional params... | | Higher address - ~ ~ ~ - | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS - |--------------------------------------------| | - | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | - |--------------------------------------------| | - | Reserved 2*4/8 | | - |--------------------------------------------| | - | Space for callee's LR 4/8 | | - |--------------------------------------------| | - | Saved CR [low word for m64] 4/8 | | - |--------------------------------------------| | - | Current backchain pointer 4/8 |-/ Parent's frame. - |--------------------------------------------| <+ <<< on entry to ffi_closure_ASM - | Result Bytes 16 | | - |--------------------------------------------| | - ~ padding to 16-byte alignment ~ ~ - |--------------------------------------------| | - | NUM_FPR_ARG_REGISTERS slots | | - | here fp13 .. fp1 13*8 | | - |--------------------------------------------| | - | R3..R10 8*4/8=32/64 | | NUM_GPR_ARG_REGISTERS - |--------------------------------------------| | - | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | - |--------------------------------------------| | stack | - | Reserved [compiler,binder] 2*4/8 | | grows | - |--------------------------------------------| | down V - | Space for callee's LR 4/8 | | - |--------------------------------------------| | lower addresses - | Saved CR [low word for m64] 4/8 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4/8 |-/ during - |--------------------------------------------| <<< ffi_closure_ASM. - -*/ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp; - struct ffi_aix_trampoline_struct *tramp_aix; - aix_fd *fd; - - switch (cif->abi) - { - case FFI_DARWIN: - - FFI_ASSERT (cif->abi == FFI_DARWIN); - - tramp = (unsigned int *) &closure->tramp[0]; -#if defined(POWERPC_DARWIN64) - tramp[0] = 0x7c0802a6; /* mflr r0 */ - tramp[1] = 0x429f0015; /* bcl- 20,4*cr7+so, +0x18 (L1) */ - /* We put the addresses here. */ - tramp[6] = 0x7d6802a6; /*L1: mflr r11 */ - tramp[7] = 0xe98b0000; /* ld r12,0(r11) function address */ - tramp[8] = 0x7c0803a6; /* mtlr r0 */ - tramp[9] = 0x7d8903a6; /* mtctr r12 */ - tramp[10] = 0xe96b0008; /* lwz r11,8(r11) static chain */ - tramp[11] = 0x4e800420; /* bctr */ - - *((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function */ - *((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context */ -#else - tramp[0] = 0x7c0802a6; /* mflr r0 */ - tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */ - tramp[4] = 0x7d6802a6; /* mflr r11 */ - tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */ - tramp[6] = 0x7c0803a6; /* mtlr r0 */ - tramp[7] = 0x7d8903a6; /* mtctr r12 */ - tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */ - tramp[9] = 0x4e800420; /* bctr */ - tramp[2] = (unsigned long) ffi_closure_ASM; /* function */ - tramp[3] = (unsigned long) codeloc; /* context */ -#endif - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Flush the icache. Only necessary on Darwin. */ - flush_range(codeloc, FFI_TRAMPOLINE_SIZE); - - break; - - case FFI_AIX: - - tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp); - fd = (aix_fd *)(void *)ffi_closure_ASM; - - FFI_ASSERT (cif->abi == FFI_AIX); - - tramp_aix->code_pointer = fd->code_pointer; - tramp_aix->toc = fd->toc; - tramp_aix->static_chain = codeloc; - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - break; - - default: - return FFI_BAD_ABI; - break; - } - return FFI_OK; -} - -static void -flush_icache(char *addr) -{ -#ifndef _AIX - __asm__ volatile ( - "dcbf 0,%0\n" - "\tsync\n" - "\ticbi 0,%0\n" - "\tsync\n" - "\tisync" - : : "r"(addr) : "memory"); -#endif -} - -static void -flush_range(char * addr1, int size) -{ -#define MIN_LINE_SIZE 32 - int i; - for (i = 0; i < size; i += MIN_LINE_SIZE) - flush_icache(addr1+i); - flush_icache(addr1+size-1); -} - -typedef union -{ - float f; - double d; -} ffi_dblfl; - -ffi_type * -ffi_closure_helper_DARWIN (ffi_closure *, void *, - unsigned long *, ffi_dblfl *); - -/* Basically the trampoline invokes ffi_closure_ASM, and on - entry, r11 holds the address of the closure. - After storing the registers that could possibly contain - parameters to be passed into the stack frame and setting - up space for a return value, ffi_closure_ASM invokes the - following helper function to do most of the work. */ - -ffi_type * -ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, - unsigned long *pgr, ffi_dblfl *pfr) -{ - /* rvalue is the pointer to space for return value in closure assembly - pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM - pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ - - typedef double ldbits[2]; - - union ldu - { - ldbits lb; - long double ld; - }; - - void ** avalue; - ffi_type ** arg_types; - long i, avn; - ffi_cif * cif; - ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS; - unsigned size_al; -#if defined(POWERPC_DARWIN64) - unsigned fpsused = 0; -#endif - - cif = closure->cif; - avalue = alloca (cif->nargs * sizeof(void *)); - - if (cif->rtype->type == FFI_TYPE_STRUCT) - { -#if defined(POWERPC_DARWIN64) - if (!darwin64_struct_ret_by_value_p (cif->rtype)) - { - /* Won't fit into the regs - return by ref. */ - rvalue = (void *) *pgr; - pgr++; - } -#elif defined(DARWIN_PPC) - if (cif->rtype->size > 4) - { - rvalue = (void *) *pgr; - pgr++; - } -#else /* assume we return by ref. */ - rvalue = (void *) *pgr; - pgr++; -#endif - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: -#if defined(POWERPC64) - avalue[i] = (char *) pgr + 7; -#else - avalue[i] = (char *) pgr + 3; -#endif - pgr++; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: -#if defined(POWERPC64) - avalue[i] = (char *) pgr + 6; -#else - avalue[i] = (char *) pgr + 2; -#endif - pgr++; - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: -#if defined(POWERPC64) - avalue[i] = (char *) pgr + 4; -#else - case FFI_TYPE_POINTER: - avalue[i] = pgr; -#endif - pgr++; - break; - - case FFI_TYPE_STRUCT: - size_al = arg_types[i]->size; -#if defined(POWERPC_DARWIN64) - pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment); - if (size_al < 3 || size_al == 4) - { - avalue[i] = ((char *)pgr)+8-size_al; - if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT - && fpsused < NUM_FPR_ARG_REGISTERS) - { - *(float *)pgr = (float) *(double *)pfr; - pfr++; - fpsused++; - } - } - else - { - if (size_al != 16) - pfr = (ffi_dblfl *) - darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr, - (double *)pfr, &fpsused); - avalue[i] = pgr; - } - pgr += (size_al + 7) / 8; -#else - /* If the first member of the struct is a double, then align - the struct to double-word. */ - if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN(arg_types[i]->size, 8); -# if defined(POWERPC64) - FFI_ASSERT (cif->abi != FFI_DARWIN); - avalue[i] = pgr; - pgr += (size_al + 7) / 8; -# else - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. */ - if (size_al < 3 && cif->abi == FFI_DARWIN) - avalue[i] = (char*) pgr + 4 - size_al; - else - avalue[i] = pgr; - pgr += (size_al + 3) / 4; -# endif -#endif - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: -#if defined(POWERPC64) - case FFI_TYPE_POINTER: - avalue[i] = pgr; - pgr++; - break; -#else - /* Long long ints are passed in two gpr's. */ - avalue[i] = pgr; - pgr += 2; - break; -#endif - - case FFI_TYPE_FLOAT: - /* A float value consumes a GPR. - There are 13 64bit floating point registers. */ - if (pfr < end_pfr) - { - double temp = pfr->d; - pfr->f = (float) temp; - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } - pgr++; - break; - - case FFI_TYPE_DOUBLE: - /* A double value consumes two GPRs. - There are 13 64bit floating point registers. */ - if (pfr < end_pfr) - { - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } -#ifdef POWERPC64 - pgr++; -#else - pgr += 2; -#endif - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - - case FFI_TYPE_LONGDOUBLE: -#ifdef POWERPC64 - if (pfr + 1 < end_pfr) - { - avalue[i] = pfr; - pfr += 2; - } - else - { - if (pfr < end_pfr) - { - *pgr = *(unsigned long *) pfr; - pfr++; - } - avalue[i] = pgr; - } - pgr += 2; -#else /* POWERPC64 */ - /* A long double value consumes four GPRs and two FPRs. - There are 13 64bit floating point registers. */ - if (pfr + 1 < end_pfr) - { - avalue[i] = pfr; - pfr += 2; - } - /* Here we have the situation where one part of the long double - is stored in fpr13 and the other part is already on the stack. - We use a union to pass the long double to avalue[i]. */ - else if (pfr + 1 == end_pfr) - { - union ldu temp_ld; - memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits)); - memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits)); - avalue[i] = &temp_ld.ld; - pfr++; - } - else - { - avalue[i] = pgr; - } - pgr += 4; -#endif /* POWERPC64 */ - break; -#endif - default: - FFI_ASSERT(0); - } - i++; - } - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_ASM to perform return type promotions. */ - return cif->rtype; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_linux64.c b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_linux64.c deleted file mode 100644 index b087af8c6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_linux64.c +++ /dev/null @@ -1,943 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_linux64.c - Copyright (C) 2013 IBM - Copyright (C) 2011 Anthony Green - Copyright (C) 2011 Kyle Moffett - Copyright (C) 2008 Red Hat, Inc - Copyright (C) 2007, 2008 Free Software Foundation, Inc - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - 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 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include "ffi.h" - -#ifdef POWERPC64 -#include "ffi_common.h" -#include "ffi_powerpc.h" - - -/* About the LINUX64 ABI. */ -enum { - NUM_GPR_ARG_REGISTERS64 = 8, - NUM_FPR_ARG_REGISTERS64 = 13 -}; -enum { ASM_NEEDS_REGISTERS64 = 4 }; - - -#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -/* Adjust size of ffi_type_longdouble. */ -void FFI_HIDDEN -ffi_prep_types_linux64 (ffi_abi abi) -{ - if ((abi & (FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128)) == FFI_LINUX) - { - ffi_type_longdouble.size = 8; - ffi_type_longdouble.alignment = 8; - } - else - { - ffi_type_longdouble.size = 16; - ffi_type_longdouble.alignment = 16; - } -} -#endif - - -#if _CALL_ELF == 2 -static unsigned int -discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) -{ - switch (t->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - *elnum = 1; - return (int) t->type; - - case FFI_TYPE_STRUCT:; - { - unsigned int base_elt = 0, total_elnum = 0; - ffi_type **el = t->elements; - while (*el) - { - unsigned int el_elt, el_elnum = 0; - el_elt = discover_homogeneous_aggregate (*el, &el_elnum); - if (el_elt == 0 - || (base_elt && base_elt != el_elt)) - return 0; - base_elt = el_elt; - total_elnum += el_elnum; - if (total_elnum > 8) - return 0; - el++; - } - *elnum = total_elnum; - return base_elt; - } - - default: - return 0; - } -} -#endif - - -/* Perform machine dependent cif processing */ -static ffi_status -ffi_prep_cif_linux64_core (ffi_cif *cif) -{ - ffi_type **ptr; - unsigned bytes; - unsigned i, fparg_count = 0, intarg_count = 0; - unsigned flags = cif->flags; -#if _CALL_ELF == 2 - unsigned int elt, elnum; -#endif - -#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE - /* If compiled without long double support.. */ - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) - return FFI_BAD_ABI; -#endif - - /* The machine-independent calculation of cif->bytes doesn't work - for us. Redo the calculation. */ -#if _CALL_ELF == 2 - /* Space for backchain, CR, LR, TOC and the asm's temp regs. */ - bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long); - - /* Space for the general registers. */ - bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long); -#else - /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp - regs. */ - bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long); - - /* Space for the mandatory parm save area and general registers. */ - bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long); -#endif - - /* Return value handling. */ - switch (cif->rtype->type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) - flags |= FLAG_RETURNS_128BITS; - /* Fall through. */ -#endif - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; - break; - - case FFI_TYPE_UINT128: - flags |= FLAG_RETURNS_128BITS; - /* Fall through. */ - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - flags |= FLAG_RETURNS_64BITS; - break; - - case FFI_TYPE_STRUCT: -#if _CALL_ELF == 2 - elt = discover_homogeneous_aggregate (cif->rtype, &elnum); - if (elt) - { - if (elt == FFI_TYPE_DOUBLE) - flags |= FLAG_RETURNS_64BITS; - flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST; - break; - } - if (cif->rtype->size <= 16) - { - flags |= FLAG_RETURNS_SMST; - break; - } -#endif - intarg_count++; - flags |= FLAG_RETVAL_REFERENCE; - /* Fall through. */ - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - unsigned int align; - - switch ((*ptr)->type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) - { - fparg_count++; - intarg_count++; - } - /* Fall through. */ -#endif - case FFI_TYPE_DOUBLE: - case FFI_TYPE_FLOAT: - fparg_count++; - intarg_count++; - if (fparg_count > NUM_FPR_ARG_REGISTERS64) - flags |= FLAG_ARG_NEEDS_PSAVE; - break; - - case FFI_TYPE_STRUCT: - if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) - { - align = (*ptr)->alignment; - if (align > 16) - align = 16; - align = align / 8; - if (align > 1) - intarg_count = ALIGN (intarg_count, align); - } - intarg_count += ((*ptr)->size + 7) / 8; -#if _CALL_ELF == 2 - elt = discover_homogeneous_aggregate (*ptr, &elnum); - if (elt) - { - fparg_count += elnum; - if (fparg_count > NUM_FPR_ARG_REGISTERS64) - flags |= FLAG_ARG_NEEDS_PSAVE; - } - else -#endif - { - if (intarg_count > NUM_GPR_ARG_REGISTERS64) - flags |= FLAG_ARG_NEEDS_PSAVE; - } - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - /* Everything else is passed as a 8-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - if (intarg_count > NUM_GPR_ARG_REGISTERS64) - flags |= FLAG_ARG_NEEDS_PSAVE; - break; - default: - FFI_ASSERT (0); - } - } - - if (fparg_count != 0) - flags |= FLAG_FP_ARGUMENTS; - if (intarg_count > 4) - flags |= FLAG_4_GPR_ARGUMENTS; - - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double); - - /* Stack space. */ -#if _CALL_ELF == 2 - if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0) - bytes += intarg_count * sizeof (long); -#else - if (intarg_count > NUM_GPR_ARG_REGISTERS64) - bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long); -#endif - - /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = (bytes + 15) & ~0xF; - - cif->flags = flags; - cif->bytes = bytes; - - return FFI_OK; -} - -ffi_status FFI_HIDDEN -ffi_prep_cif_linux64 (ffi_cif *cif) -{ - if ((cif->abi & FFI_LINUX) != 0) - cif->nfixedargs = cif->nargs; -#if _CALL_ELF != 2 - else if (cif->abi == FFI_COMPAT_LINUX64) - { - /* This call is from old code. Don't touch cif->nfixedargs - since old code will be using a smaller cif. */ - cif->flags |= FLAG_COMPAT; - /* Translate to new abi value. */ - cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128; - } -#endif - else - return FFI_BAD_ABI; - return ffi_prep_cif_linux64_core (cif); -} - -ffi_status FFI_HIDDEN -ffi_prep_cif_linux64_var (ffi_cif *cif, - unsigned int nfixedargs, - unsigned int ntotalargs MAYBE_UNUSED) -{ - if ((cif->abi & FFI_LINUX) != 0) - cif->nfixedargs = nfixedargs; -#if _CALL_ELF != 2 - else if (cif->abi == FFI_COMPAT_LINUX64) - { - /* This call is from old code. Don't touch cif->nfixedargs - since old code will be using a smaller cif. */ - cif->flags |= FLAG_COMPAT; - /* Translate to new abi value. */ - cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128; - } -#endif - else - return FFI_BAD_ABI; -#if _CALL_ELF == 2 - cif->flags |= FLAG_ARG_NEEDS_PSAVE; -#endif - return ffi_prep_cif_linux64_core (cif); -} - - -/* ffi_prep_args64 is called by the assembly routine once stack space - has been allocated for the function's arguments. - - The stack layout we want looks like this: - - | Ret addr from ffi_call_LINUX64 8bytes | higher addresses - |--------------------------------------------| - | CR save area 8bytes | - |--------------------------------------------| - | Previous backchain pointer 8 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*8 | | ffi_call_LINUX64 - |--------------------------------------------| | - | GPR registers r3-r10 8*8 | | - |--------------------------------------------| | - | FPR registers f1-f13 (optional) 13*8 | | - |--------------------------------------------| | - | Parameter save area | | - |--------------------------------------------| | - | TOC save area 8 | | - |--------------------------------------------| | stack | - | Linker doubleword 8 | | grows | - |--------------------------------------------| | down V - | Compiler doubleword 8 | | - |--------------------------------------------| | lower addresses - | Space for callee's LR 8 | | - |--------------------------------------------| | - | CR save area 8 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 8 |-/ during - |--------------------------------------------| <<< ffi_call_LINUX64 - -*/ - -void FFI_HIDDEN -ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) -{ - const unsigned long bytes = ecif->cif->bytes; - const unsigned long flags = ecif->cif->flags; - - typedef union - { - char *c; - unsigned long *ul; - float *f; - double *d; - size_t p; - } valp; - - /* 'stacktop' points at the previous backchain pointer. */ - valp stacktop; - - /* 'next_arg' points at the space for gpr3, and grows upwards as - we use GPR registers, then continues at rest. */ - valp gpr_base; - valp gpr_end; - valp rest; - valp next_arg; - - /* 'fpr_base' points at the space for fpr3, and grows upwards as - we use FPR registers. */ - valp fpr_base; - unsigned int fparg_count; - - unsigned int i, words, nargs, nfixedargs; - ffi_type **ptr; - double double_tmp; - union - { - void **v; - char **c; - signed char **sc; - unsigned char **uc; - signed short **ss; - unsigned short **us; - signed int **si; - unsigned int **ui; - unsigned long **ul; - float **f; - double **d; - } p_argv; - unsigned long gprvalue; - unsigned long align; - - stacktop.c = (char *) stack + bytes; - gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64; - gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64; -#if _CALL_ELF == 2 - rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64; -#else - rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64; -#endif - fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64; - fparg_count = 0; - next_arg.ul = gpr_base.ul; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); - FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); - FFI_ASSERT ((bytes & 0xF) == 0); - - /* Deal with return values that are actually pass-by-reference. */ - if (flags & FLAG_RETVAL_REFERENCE) - *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue; - - /* Now for the arguments. */ - p_argv.v = ecif->avalue; - nargs = ecif->cif->nargs; -#if _CALL_ELF != 2 - nfixedargs = (unsigned) -1; - if ((flags & FLAG_COMPAT) == 0) -#endif - nfixedargs = ecif->cif->nfixedargs; - for (ptr = ecif->cif->arg_types, i = 0; - i < nargs; - i++, ptr++, p_argv.v++) - { -#if _CALL_ELF == 2 - unsigned int elt, elnum; -#endif - - switch ((*ptr)->type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) - { - double_tmp = (*p_argv.d)[0]; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) - { - *fpr_base.d++ = double_tmp; -# if _CALL_ELF != 2 - if ((flags & FLAG_COMPAT) != 0) - *next_arg.d = double_tmp; -# endif - } - else - *next_arg.d = double_tmp; - if (++next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - fparg_count++; - double_tmp = (*p_argv.d)[1]; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) - { - *fpr_base.d++ = double_tmp; -# if _CALL_ELF != 2 - if ((flags & FLAG_COMPAT) != 0) - *next_arg.d = double_tmp; -# endif - } - else - *next_arg.d = double_tmp; - if (++next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - fparg_count++; - FFI_ASSERT (__LDBL_MANT_DIG__ == 106); - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; - } - /* Fall through. */ -#endif - case FFI_TYPE_DOUBLE: - double_tmp = **p_argv.d; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) - { - *fpr_base.d++ = double_tmp; -#if _CALL_ELF != 2 - if ((flags & FLAG_COMPAT) != 0) - *next_arg.d = double_tmp; -#endif - } - else - *next_arg.d = double_tmp; - if (++next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - fparg_count++; - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_FLOAT: - double_tmp = **p_argv.f; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) - { - *fpr_base.d++ = double_tmp; -#if _CALL_ELF != 2 - if ((flags & FLAG_COMPAT) != 0) - *next_arg.f = (float) double_tmp; -#endif - } - else - *next_arg.f = (float) double_tmp; - if (++next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - fparg_count++; - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_STRUCT: - if ((ecif->cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) - { - align = (*ptr)->alignment; - if (align > 16) - align = 16; - if (align > 1) - next_arg.p = ALIGN (next_arg.p, align); - } -#if _CALL_ELF == 2 - elt = discover_homogeneous_aggregate (*ptr, &elnum); - if (elt) - { - union { - void *v; - float *f; - double *d; - } arg; - - arg.v = *p_argv.v; - if (elt == FFI_TYPE_FLOAT) - { - do - { - double_tmp = *arg.f++; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 - && i < nfixedargs) - *fpr_base.d++ = double_tmp; - else - *next_arg.f = (float) double_tmp; - if (++next_arg.f == gpr_end.f) - next_arg.f = rest.f; - fparg_count++; - } - while (--elnum != 0); - if ((next_arg.p & 3) != 0) - { - if (++next_arg.f == gpr_end.f) - next_arg.f = rest.f; - } - } - else - do - { - double_tmp = *arg.d++; - if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) - *fpr_base.d++ = double_tmp; - else - *next_arg.d = double_tmp; - if (++next_arg.d == gpr_end.d) - next_arg.d = rest.d; - fparg_count++; - } - while (--elnum != 0); - } - else -#endif - { - words = ((*ptr)->size + 7) / 8; - if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) - { - size_t first = gpr_end.c - next_arg.c; - memcpy (next_arg.c, *p_argv.c, first); - memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first); - next_arg.c = rest.c + words * 8 - first; - } - else - { - char *where = next_arg.c; - -#ifndef __LITTLE_ENDIAN__ - /* Structures with size less than eight bytes are passed - left-padded. */ - if ((*ptr)->size < 8) - where += 8 - (*ptr)->size; -#endif - memcpy (where, *p_argv.c, (*ptr)->size); - next_arg.ul += words; - if (next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - } - } - break; - - case FFI_TYPE_UINT8: - gprvalue = **p_argv.uc; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = **p_argv.sc; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = **p_argv.us; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = **p_argv.ss; - goto putgpr; - case FFI_TYPE_UINT32: - gprvalue = **p_argv.ui; - goto putgpr; - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - gprvalue = **p_argv.si; - goto putgpr; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_POINTER: - gprvalue = **p_argv.ul; - putgpr: - *next_arg.ul++ = gprvalue; - if (next_arg.ul == gpr_end.ul) - next_arg.ul = rest.ul; - break; - } - } - - FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS - || (next_arg.ul >= gpr_base.ul - && next_arg.ul <= gpr_base.ul + 4)); -} - - -#if _CALL_ELF == 2 -#define MIN_CACHE_LINE_SIZE 8 - -static void -flush_icache (char *wraddr, char *xaddr, int size) -{ - int i; - for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" - : : "r" (xaddr + i), "r" (wraddr + i) : "memory"); - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;" - : : "r"(xaddr + size - 1), "r"(wraddr + size - 1) - : "memory"); -} -#endif - -ffi_status -ffi_prep_closure_loc_linux64 (ffi_closure *closure, - ffi_cif *cif, - void (*fun) (ffi_cif *, void *, void **, void *), - void *user_data, - void *codeloc) -{ -#if _CALL_ELF == 2 - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - - if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) - return FFI_BAD_ABI; - - tramp[0] = 0xe96c0018; /* 0: ld 11,2f-0b(12) */ - tramp[1] = 0xe98c0010; /* ld 12,1f-0b(12) */ - tramp[2] = 0x7d8903a6; /* mtctr 12 */ - tramp[3] = 0x4e800420; /* bctr */ - /* 1: .quad function_addr */ - /* 2: .quad context */ - *(void **) &tramp[4] = (void *) ffi_closure_LINUX64; - *(void **) &tramp[6] = codeloc; - flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); -#else - void **tramp = (void **) &closure->tramp[0]; - - if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) - return FFI_BAD_ABI; - - /* Copy function address and TOC from ffi_closure_LINUX64. */ - memcpy (tramp, (char *) ffi_closure_LINUX64, 16); - tramp[2] = tramp[1]; - tramp[1] = codeloc; -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - - -int FFI_HIDDEN -ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, - unsigned long *pst, ffi_dblfl *pfr) -{ - /* rvalue is the pointer to space for return value in closure assembly */ - /* pst is the pointer to parameter save area - (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */ - /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */ - - void **avalue; - ffi_type **arg_types; - unsigned long i, avn, nfixedargs; - ffi_cif *cif; - ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; - unsigned long align; - - cif = closure->cif; - avalue = alloca (cif->nargs * sizeof (void *)); - - /* Copy the caller's structure return value address so that the - closure returns the data directly to the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT - && (cif->flags & FLAG_RETURNS_SMST) == 0) - { - rvalue = (void *) *pst; - pst++; - } - - i = 0; - avn = cif->nargs; -#if _CALL_ELF != 2 - nfixedargs = (unsigned) -1; - if ((cif->flags & FLAG_COMPAT) == 0) -#endif - nfixedargs = cif->nfixedargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) - { - unsigned int elt, elnum; - - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: -#ifndef __LITTLE_ENDIAN__ - avalue[i] = (char *) pst + 7; - pst++; - break; -#endif - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: -#ifndef __LITTLE_ENDIAN__ - avalue[i] = (char *) pst + 6; - pst++; - break; -#endif - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: -#ifndef __LITTLE_ENDIAN__ - avalue[i] = (char *) pst + 4; - pst++; - break; -#endif - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_POINTER: - avalue[i] = pst; - pst++; - break; - - case FFI_TYPE_STRUCT: - if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) - { - align = arg_types[i]->alignment; - if (align > 16) - align = 16; - if (align > 1) - pst = (unsigned long *) ALIGN ((size_t) pst, align); - } - elt = 0; -#if _CALL_ELF == 2 - elt = discover_homogeneous_aggregate (arg_types[i], &elnum); -#endif - if (elt) - { - union { - void *v; - unsigned long *ul; - float *f; - double *d; - size_t p; - } to, from; - - /* Repackage the aggregate from its parts. The - aggregate size is not greater than the space taken by - the registers so store back to the register/parameter - save arrays. */ - if (pfr + elnum <= end_pfr) - to.v = pfr; - else - to.v = pst; - - avalue[i] = to.v; - from.ul = pst; - if (elt == FFI_TYPE_FLOAT) - { - do - { - if (pfr < end_pfr && i < nfixedargs) - { - *to.f = (float) pfr->d; - pfr++; - } - else - *to.f = *from.f; - to.f++; - from.f++; - } - while (--elnum != 0); - } - else - { - do - { - if (pfr < end_pfr && i < nfixedargs) - { - *to.d = pfr->d; - pfr++; - } - else - *to.d = *from.d; - to.d++; - from.d++; - } - while (--elnum != 0); - } - } - else - { -#ifndef __LITTLE_ENDIAN__ - /* Structures with size less than eight bytes are passed - left-padded. */ - if (arg_types[i]->size < 8) - avalue[i] = (char *) pst + 8 - arg_types[i]->size; - else -#endif - avalue[i] = pst; - } - pst += (arg_types[i]->size + 7) / 8; - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) - { - if (pfr + 1 < end_pfr && i + 1 < nfixedargs) - { - avalue[i] = pfr; - pfr += 2; - } - else - { - if (pfr < end_pfr && i < nfixedargs) - { - /* Passed partly in f13 and partly on the stack. - Move it all to the stack. */ - *pst = *(unsigned long *) pfr; - pfr++; - } - avalue[i] = pst; - } - pst += 2; - break; - } - /* Fall through. */ -#endif - case FFI_TYPE_DOUBLE: - /* On the outgoing stack all values are aligned to 8 */ - /* there are 13 64bit floating point registers */ - - if (pfr < end_pfr && i < nfixedargs) - { - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pst; - pst++; - break; - - case FFI_TYPE_FLOAT: - if (pfr < end_pfr && i < nfixedargs) - { - /* Float values are stored as doubles in the - ffi_closure_LINUX64 code. Fix them here. */ - pfr->f = (float) pfr->d; - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pst; - pst++; - break; - - default: - FFI_ASSERT (0); - } - - i++; - } - - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ - if ((cif->flags & FLAG_RETURNS_SMST) != 0) - { - if ((cif->flags & FLAG_RETURNS_FP) == 0) - return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; - else if ((cif->flags & FLAG_RETURNS_64BITS) != 0) - return FFI_V2_TYPE_DOUBLE_HOMOG; - else - return FFI_V2_TYPE_FLOAT_HOMOG; - } - return cif->rtype->type; -} -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_powerpc.h b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_powerpc.h deleted file mode 100644 index 2e61653d1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_powerpc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_powerpc.h - Copyright (C) 2013 IBM - Copyright (C) 2011 Anthony Green - Copyright (C) 2011 Kyle Moffett - Copyright (C) 2008 Red Hat, Inc - Copyright (C) 2007, 2008 Free Software Foundation, Inc - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ - -enum { - /* The assembly depends on these exact flags. */ - /* These go in cr7 */ - FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ - FLAG_RETURNS_NOTHING = 1 << (31-30), - FLAG_RETURNS_FP = 1 << (31-29), - FLAG_RETURNS_64BITS = 1 << (31-28), - - /* This goes in cr6 */ - FLAG_RETURNS_128BITS = 1 << (31-27), - - FLAG_COMPAT = 1 << (31- 8), /* Not used by assembly */ - - /* These go in cr1 */ - FLAG_ARG_NEEDS_COPY = 1 << (31- 7), /* Used by sysv code */ - FLAG_ARG_NEEDS_PSAVE = FLAG_ARG_NEEDS_COPY, /* Used by linux64 code */ - FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ - FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), - FLAG_RETVAL_REFERENCE = 1 << (31- 4) -}; - -typedef union -{ - float f; - double d; -} ffi_dblfl; - -void FFI_HIDDEN ffi_closure_SYSV (void); -void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *, - void (*)(void)); - -void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi); -ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *); -int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *, - ffi_dblfl *, unsigned long *); - -void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long, - unsigned long *, void (*)(void)); -void FFI_HIDDEN ffi_closure_LINUX64 (void); - -void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi); -ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *); -ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int, - unsigned int); -void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const); -int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *, - unsigned long *, ffi_dblfl *); diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_sysv.c b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_sysv.c deleted file mode 100644 index fbe85fe91..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffi_sysv.c +++ /dev/null @@ -1,931 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_sysv.c - Copyright (C) 2013 IBM - Copyright (C) 2011 Anthony Green - Copyright (C) 2011 Kyle Moffett - Copyright (C) 2008 Red Hat, Inc - Copyright (C) 2007, 2008 Free Software Foundation, Inc - Copyright (c) 1998 Geoffrey Keating - - PowerPC Foreign Function Interface - - 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 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include "ffi.h" - -#ifndef POWERPC64 -#include "ffi_common.h" -#include "ffi_powerpc.h" - - -/* About the SYSV ABI. */ -#define ASM_NEEDS_REGISTERS 4 -#define NUM_GPR_ARG_REGISTERS 8 -#define NUM_FPR_ARG_REGISTERS 8 - - -#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -/* Adjust size of ffi_type_longdouble. */ -void FFI_HIDDEN -ffi_prep_types_sysv (ffi_abi abi) -{ - if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV) - { - ffi_type_longdouble.size = 8; - ffi_type_longdouble.alignment = 8; - } - else - { - ffi_type_longdouble.size = 16; - ffi_type_longdouble.alignment = 16; - } -} -#endif - -/* Transform long double, double and float to other types as per abi. */ -static int -translate_float (int abi, int type) -{ -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - if (type == FFI_TYPE_LONGDOUBLE - && (abi & FFI_SYSV_LONG_DOUBLE_128) == 0) - type = FFI_TYPE_DOUBLE; -#endif - if ((abi & FFI_SYSV_SOFT_FLOAT) != 0) - { - if (type == FFI_TYPE_FLOAT) - type = FFI_TYPE_UINT32; - else if (type == FFI_TYPE_DOUBLE) - type = FFI_TYPE_UINT64; -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - else if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_UINT128; - } - else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0) - { - if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_STRUCT; -#endif - } - return type; -} - -/* Perform machine dependent cif processing */ -static ffi_status -ffi_prep_cif_sysv_core (ffi_cif *cif) -{ - ffi_type **ptr; - unsigned bytes; - unsigned i, fparg_count = 0, intarg_count = 0; - unsigned flags = cif->flags; - unsigned struct_copy_size = 0; - unsigned type = cif->rtype->type; - unsigned size = cif->rtype->size; - - /* The machine-independent calculation of cif->bytes doesn't work - for us. Redo the calculation. */ - - /* Space for the frame pointer, callee's LR, and the asm's temp regs. */ - bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int); - - /* Space for the GPR registers. */ - bytes += NUM_GPR_ARG_REGISTERS * sizeof (int); - - /* Return value handling. The rules for SYSV are as follows: - - 32-bit (or less) integer values are returned in gpr3; - - Structures of size <= 4 bytes also returned in gpr3; - - 64-bit integer values and structures between 5 and 8 bytes are returned - in gpr3 and gpr4; - - Larger structures are allocated space and a pointer is passed as - the first argument. - - Single/double FP values are returned in fpr1; - - long doubles (if not equivalent to double) are returned in - fpr1,fpr2 for Linux and as for large structs for SysV. */ - - type = translate_float (cif->abi, type); - - switch (type) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - flags |= FLAG_RETURNS_128BITS; - /* Fall through. */ -#endif - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; -#ifdef __NO_FPRS__ - return FFI_BAD_ABI; -#endif - break; - - case FFI_TYPE_UINT128: - flags |= FLAG_RETURNS_128BITS; - /* Fall through. */ - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - flags |= FLAG_RETURNS_64BITS; - break; - - case FFI_TYPE_STRUCT: - /* The final SYSV ABI says that structures smaller or equal 8 bytes - are returned in r3/r4. A draft ABI used by linux instead - returns them in memory. */ - if ((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8) - { - flags |= FLAG_RETURNS_SMST; - break; - } - intarg_count++; - flags |= FLAG_RETVAL_REFERENCE; - /* Fall through. */ - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the - first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest - goes on the stack. Structures and long doubles (if not equivalent - to double) are passed as a pointer to a copy of the structure. - Stuff on the stack needs to keep proper alignment. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - unsigned short typenum = (*ptr)->type; - - typenum = translate_float (cif->abi, typenum); - - switch (typenum) - { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - fparg_count++; - /* Fall thru */ -#endif - case FFI_TYPE_DOUBLE: - fparg_count++; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count >= NUM_GPR_ARG_REGISTERS - && intarg_count % 2 != 0) - intarg_count++; -#ifdef __NO_FPRS__ - return FFI_BAD_ABI; -#endif - break; - - case FFI_TYPE_FLOAT: - fparg_count++; -#ifdef __NO_FPRS__ - return FFI_BAD_ABI; -#endif - break; - - case FFI_TYPE_UINT128: - /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set - of four consecutive gprs. If we do not have enough, we - have to adjust the intarg_count value. */ - if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3 - && intarg_count < NUM_GPR_ARG_REGISTERS) - intarg_count = NUM_GPR_ARG_REGISTERS; - intarg_count += 4; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* 'long long' arguments are passed as two words, but - either both words must fit in registers or both go - on the stack. If they go on the stack, they must - be 8-byte-aligned. - - Also, only certain register pairs can be used for - passing long long int -- specifically (r3,r4), (r5,r6), - (r7,r8), (r9,r10). */ - if (intarg_count == NUM_GPR_ARG_REGISTERS-1 - || intarg_count % 2 != 0) - intarg_count++; - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: - /* We must allocate space for a copy of these to enforce - pass-by-value. Pad the space up to a multiple of 16 - bytes (the maximum alignment required for anything under - the SYSV ABI). */ - struct_copy_size += ((*ptr)->size + 15) & ~0xF; - /* Fall through (allocate space for the pointer). */ - - case FFI_TYPE_POINTER: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - /* Everything else is passed as a 4-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - - default: - FFI_ASSERT (0); - } - } - - if (fparg_count != 0) - flags |= FLAG_FP_ARGUMENTS; - if (intarg_count > 4) - flags |= FLAG_4_GPR_ARGUMENTS; - if (struct_copy_size != 0) - flags |= FLAG_ARG_NEEDS_COPY; - - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - bytes += NUM_FPR_ARG_REGISTERS * sizeof (double); - - /* Stack space. */ - if (intarg_count > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int); - if (fparg_count > NUM_FPR_ARG_REGISTERS) - bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double); - - /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = (bytes + 15) & ~0xF; - - /* Add in the space for the copied structures. */ - bytes += struct_copy_size; - - cif->flags = flags; - cif->bytes = bytes; - - return FFI_OK; -} - -ffi_status FFI_HIDDEN -ffi_prep_cif_sysv (ffi_cif *cif) -{ - if ((cif->abi & FFI_SYSV) == 0) - { - /* This call is from old code. Translate to new ABI values. */ - cif->flags |= FLAG_COMPAT; - switch (cif->abi) - { - default: - return FFI_BAD_ABI; - - case FFI_COMPAT_SYSV: - cif->abi = FFI_SYSV | FFI_SYSV_STRUCT_RET | FFI_SYSV_LONG_DOUBLE_128; - break; - - case FFI_COMPAT_GCC_SYSV: - cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128; - break; - - case FFI_COMPAT_LINUX: - cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE - | FFI_SYSV_LONG_DOUBLE_128); - break; - - case FFI_COMPAT_LINUX_SOFT_FLOAT: - cif->abi = (FFI_SYSV | FFI_SYSV_SOFT_FLOAT | FFI_SYSV_IBM_LONG_DOUBLE - | FFI_SYSV_LONG_DOUBLE_128); - break; - } - } - return ffi_prep_cif_sysv_core (cif); -} - -/* ffi_prep_args_SYSV is called by the assembly routine once stack space - has been allocated for the function's arguments. - - The stack layout we want looks like this: - - | Return address from ffi_call_SYSV 4bytes | higher addresses - |--------------------------------------------| - | Previous backchain pointer 4 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*4 | | ffi_call_SYSV - |--------------------------------------------| | - | GPR registers r3-r10 8*4 | | ffi_call_SYSV - |--------------------------------------------| | - | FPR registers f1-f8 (optional) 8*8 | | - |--------------------------------------------| | stack | - | Space for copied structures | | grows | - |--------------------------------------------| | down V - | Parameters that didn't fit in registers | | - |--------------------------------------------| | lower addresses - | Space for callee's LR 4 | | - |--------------------------------------------| | stack pointer here - | Current backchain pointer 4 |-/ during - |--------------------------------------------| <<< ffi_call_SYSV - -*/ - -void FFI_HIDDEN -ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) -{ - const unsigned bytes = ecif->cif->bytes; - const unsigned flags = ecif->cif->flags; - - typedef union - { - char *c; - unsigned *u; - long long *ll; - float *f; - double *d; - } valp; - - /* 'stacktop' points at the previous backchain pointer. */ - valp stacktop; - - /* 'gpr_base' points at the space for gpr3, and grows upwards as - we use GPR registers. */ - valp gpr_base; - int intarg_count; - -#ifndef __NO_FPRS__ - /* 'fpr_base' points at the space for fpr1, and grows upwards as - we use FPR registers. */ - valp fpr_base; - int fparg_count; -#endif - - /* 'copy_space' grows down as we put structures in it. It should - stay 16-byte aligned. */ - valp copy_space; - - /* 'next_arg' grows up as we put parameters in it. */ - valp next_arg; - - int i; - ffi_type **ptr; -#ifndef __NO_FPRS__ - double double_tmp; -#endif - union - { - void **v; - char **c; - signed char **sc; - unsigned char **uc; - signed short **ss; - unsigned short **us; - unsigned int **ui; - long long **ll; - float **f; - double **d; - } p_argv; - size_t struct_copy_size; - unsigned gprvalue; - - stacktop.c = (char *) stack + bytes; - gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS; - intarg_count = 0; -#ifndef __NO_FPRS__ - fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS; - fparg_count = 0; - copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c); -#else - copy_space.c = gpr_base.c; -#endif - next_arg.u = stack + 2; - - /* Check that everything starts aligned properly. */ - FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); - FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0); - FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); - FFI_ASSERT ((bytes & 0xF) == 0); - FFI_ASSERT (copy_space.c >= next_arg.c); - - /* Deal with return values that are actually pass-by-reference. */ - if (flags & FLAG_RETVAL_REFERENCE) - { - *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue; - intarg_count++; - } - - /* Now for the arguments. */ - p_argv.v = ecif->avalue; - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; - i > 0; - i--, ptr++, p_argv.v++) - { - unsigned int typenum = (*ptr)->type; - - typenum = translate_float (ecif->cif->abi, typenum); - - /* Now test the translated value */ - switch (typenum) - { -#ifndef __NO_FPRS__ -# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - double_tmp = (*p_argv.d)[0]; - - if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1) - { - if (intarg_count >= NUM_GPR_ARG_REGISTERS - && intarg_count % 2 != 0) - { - intarg_count++; - next_arg.u++; - } - *next_arg.d = double_tmp; - next_arg.u += 2; - double_tmp = (*p_argv.d)[1]; - *next_arg.d = double_tmp; - next_arg.u += 2; - } - else - { - *fpr_base.d++ = double_tmp; - double_tmp = (*p_argv.d)[1]; - *fpr_base.d++ = double_tmp; - } - - fparg_count += 2; - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; -# endif - case FFI_TYPE_DOUBLE: - double_tmp = **p_argv.d; - - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - { - if (intarg_count >= NUM_GPR_ARG_REGISTERS - && intarg_count % 2 != 0) - { - intarg_count++; - next_arg.u++; - } - *next_arg.d = double_tmp; - next_arg.u += 2; - } - else - *fpr_base.d++ = double_tmp; - fparg_count++; - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_FLOAT: - double_tmp = **p_argv.f; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - { - *next_arg.f = (float) double_tmp; - next_arg.u += 1; - intarg_count++; - } - else - *fpr_base.d++ = double_tmp; - fparg_count++; - FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); - break; -#endif /* have FPRs */ - - case FFI_TYPE_UINT128: - /* The soft float ABI for long doubles works like this, a long double - is passed in four consecutive GPRs if available. A maximum of 2 - long doubles can be passed in gprs. If we do not have 4 GPRs - left, the long double is passed on the stack, 4-byte aligned. */ - { - unsigned int int_tmp; - unsigned int ii; - if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) - { - if (intarg_count < NUM_GPR_ARG_REGISTERS) - intarg_count = NUM_GPR_ARG_REGISTERS; - for (ii = 0; ii < 4; ii++) - { - int_tmp = (*p_argv.ui)[ii]; - *next_arg.u++ = int_tmp; - } - } - else - { - for (ii = 0; ii < 4; ii++) - { - int_tmp = (*p_argv.ui)[ii]; - *gpr_base.u++ = int_tmp; - } - } - intarg_count += 4; - break; - } - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (intarg_count == NUM_GPR_ARG_REGISTERS-1) - intarg_count++; - if (intarg_count >= NUM_GPR_ARG_REGISTERS) - { - if (intarg_count % 2 != 0) - { - intarg_count++; - next_arg.u++; - } - *next_arg.ll = **p_argv.ll; - next_arg.u += 2; - } - else - { - /* The abi states only certain register pairs can be - used for passing long long int specifically (r3,r4), - (r5,r6), (r7,r8), (r9,r10). If next arg is long long - but not correct starting register of pair then skip - until the proper starting register. */ - if (intarg_count % 2 != 0) - { - intarg_count ++; - gpr_base.u++; - } - *gpr_base.ll++ = **p_argv.ll; - } - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: - struct_copy_size = ((*ptr)->size + 15) & ~0xF; - copy_space.c -= struct_copy_size; - memcpy (copy_space.c, *p_argv.c, (*ptr)->size); - - gprvalue = (unsigned long) copy_space.c; - - FFI_ASSERT (copy_space.c > next_arg.c); - FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY); - goto putgpr; - - case FFI_TYPE_UINT8: - gprvalue = **p_argv.uc; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = **p_argv.sc; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = **p_argv.us; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = **p_argv.ss; - goto putgpr; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - - gprvalue = **p_argv.ui; - - putgpr: - if (intarg_count >= NUM_GPR_ARG_REGISTERS) - *next_arg.u++ = gprvalue; - else - *gpr_base.u++ = gprvalue; - intarg_count++; - break; - } - } - - /* Check that we didn't overrun the stack... */ - FFI_ASSERT (copy_space.c >= next_arg.c); - FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS); - /* The assert below is testing that the number of integer arguments agrees - with the number found in ffi_prep_cif_machdep(). However, intarg_count - is incremented whenever we place an FP arg on the stack, so account for - that before our assert test. */ -#ifndef __NO_FPRS__ - if (fparg_count > NUM_FPR_ARG_REGISTERS) - intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS; - FFI_ASSERT (fpr_base.u - <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); -#endif - FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); -} - -#define MIN_CACHE_LINE_SIZE 8 - -static void -flush_icache (char *wraddr, char *xaddr, int size) -{ - int i; - for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" - : : "r" (xaddr + i), "r" (wraddr + i) : "memory"); - __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;" - : : "r"(xaddr + size - 1), "r"(wraddr + size - 1) - : "memory"); -} - -ffi_status FFI_HIDDEN -ffi_prep_closure_loc_sysv (ffi_closure *closure, - ffi_cif *cif, - void (*fun) (ffi_cif *, void *, void **, void *), - void *user_data, - void *codeloc) -{ - unsigned int *tramp; - - if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI) - return FFI_BAD_ABI; - - tramp = (unsigned int *) &closure->tramp[0]; - tramp[0] = 0x7c0802a6; /* mflr r0 */ - tramp[1] = 0x4800000d; /* bl 10 */ - tramp[4] = 0x7d6802a6; /* mflr r11 */ - tramp[5] = 0x7c0803a6; /* mtlr r0 */ - tramp[6] = 0x800b0000; /* lwz r0,0(r11) */ - tramp[7] = 0x816b0004; /* lwz r11,4(r11) */ - tramp[8] = 0x7c0903a6; /* mtctr r0 */ - tramp[9] = 0x4e800420; /* bctr */ - *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */ - *(void **) &tramp[3] = codeloc; /* context */ - - /* Flush the icache. */ - flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - -/* Basically the trampoline invokes ffi_closure_SYSV, and on - entry, r11 holds the address of the closure. - After storing the registers that could possibly contain - parameters to be passed into the stack frame and setting - up space for a return value, ffi_closure_SYSV invokes the - following helper function to do most of the work. */ - -int -ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, - unsigned long *pgr, ffi_dblfl *pfr, - unsigned long *pst) -{ - /* rvalue is the pointer to space for return value in closure assembly */ - /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */ - /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */ - /* pst is the pointer to outgoing parameter stack in original caller */ - - void ** avalue; - ffi_type ** arg_types; - long i, avn; -#ifndef __NO_FPRS__ - long nf = 0; /* number of floating registers already used */ -#endif - long ng = 0; /* number of general registers already used */ - - ffi_cif *cif = closure->cif; - unsigned size = cif->rtype->size; - unsigned short rtypenum = cif->rtype->type; - - avalue = alloca (cif->nargs * sizeof (void *)); - - /* First translate for softfloat/nonlinux */ - rtypenum = translate_float (cif->abi, rtypenum); - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. - For FFI_SYSV the result is passed in r3/r4 if the struct size is less - or equal 8 bytes. */ - if (rtypenum == FFI_TYPE_STRUCT - && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)) - { - rvalue = (void *) *pgr; - ng++; - pgr++; - } - - i = 0; - avn = cif->nargs; - arg_types = cif->arg_types; - - /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) { - unsigned short typenum = arg_types[i]->type; - - /* We may need to handle some values depending on ABI. */ - typenum = translate_float (cif->abi, typenum); - - switch (typenum) - { -#ifndef __NO_FPRS__ - case FFI_TYPE_FLOAT: - /* Unfortunately float values are stored as doubles - in the ffi_closure_SYSV code (since we don't check - the type in that routine). */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - /* FIXME? here we are really changing the values - stored in the original calling routines outgoing - parameter stack. This is probably a really - naughty thing to do but... */ - double temp = pfr->d; - pfr->f = (float) temp; - avalue[i] = pfr; - nf++; - pfr++; - } - else - { - avalue[i] = pst; - pst += 1; - } - break; - - case FFI_TYPE_DOUBLE: - if (nf < NUM_FPR_ARG_REGISTERS) - { - avalue[i] = pfr; - nf++; - pfr++; - } - else - { - if (((long) pst) & 4) - pst++; - avalue[i] = pst; - pst += 2; - } - break; - -# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - if (nf < NUM_FPR_ARG_REGISTERS - 1) - { - avalue[i] = pfr; - pfr += 2; - nf += 2; - } - else - { - if (((long) pst) & 4) - pst++; - avalue[i] = pst; - pst += 4; - nf = 8; - } - break; -# endif -#endif - - case FFI_TYPE_UINT128: - /* Test if for the whole long double, 4 gprs are available. - otherwise the stuff ends up on the stack. */ - if (ng < NUM_GPR_ARG_REGISTERS - 3) - { - avalue[i] = pgr; - pgr += 4; - ng += 4; - } - else - { - avalue[i] = pst; - pst += 4; - ng = 8+4; - } - break; - - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: -#ifndef __LITTLE_ENDIAN__ - if (ng < NUM_GPR_ARG_REGISTERS) - { - avalue[i] = (char *) pgr + 3; - ng++; - pgr++; - } - else - { - avalue[i] = (char *) pst + 3; - pst++; - } - break; -#endif - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: -#ifndef __LITTLE_ENDIAN__ - if (ng < NUM_GPR_ARG_REGISTERS) - { - avalue[i] = (char *) pgr + 2; - ng++; - pgr++; - } - else - { - avalue[i] = (char *) pst + 2; - pst++; - } - break; -#endif - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - if (ng < NUM_GPR_ARG_REGISTERS) - { - avalue[i] = pgr; - ng++; - pgr++; - } - else - { - avalue[i] = pst; - pst++; - } - break; - - case FFI_TYPE_STRUCT: - /* Structs are passed by reference. The address will appear in a - gpr if it is one of the first 8 arguments. */ - if (ng < NUM_GPR_ARG_REGISTERS) - { - avalue[i] = (void *) *pgr; - ng++; - pgr++; - } - else - { - avalue[i] = (void *) *pst; - pst++; - } - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - /* Passing long long ints are complex, they must - be passed in suitable register pairs such as - (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10) - and if the entire pair aren't available then the outgoing - parameter stack is used for both but an alignment of 8 - must will be kept. So we must either look in pgr - or pst to find the correct address for this type - of parameter. */ - if (ng < NUM_GPR_ARG_REGISTERS - 1) - { - if (ng & 1) - { - /* skip r4, r6, r8 as starting points */ - ng++; - pgr++; - } - avalue[i] = pgr; - ng += 2; - pgr += 2; - } - else - { - if (((long) pst) & 4) - pst++; - avalue[i] = pst; - pst += 2; - ng = NUM_GPR_ARG_REGISTERS; - } - break; - - default: - FFI_ASSERT (0); - } - - i++; - } - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_SYSV how to perform return type promotions. - Because the FFI_SYSV ABI returns the structures <= 8 bytes in - r3/r4 we have to tell ffi_closure_SYSV how to treat them. We - combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of - the struct less one. We never have a struct with size zero. - See the comment in ffitarget.h about ordering. */ - if (rtypenum == FFI_TYPE_STRUCT - && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8) - return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size; - return rtypenum; -} -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffitarget.h deleted file mode 100644 index b47b0f5d3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ffitarget.h +++ /dev/null @@ -1,183 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc - Copyright (c) 1996-2003 Red Hat, Inc. - - Target configuration macros for PowerPC. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */ -#ifndef POWERPC64 -#define POWERPC64 -#endif -#elif defined (POWERPC_DARWIN) && defined (__ppc64__) /* Darwin64 */ -#ifndef POWERPC64 -#define POWERPC64 -#endif -#ifndef POWERPC_DARWIN64 -#define POWERPC_DARWIN64 -#endif -#elif defined (POWERPC_AIX) && defined (__64BIT__) /* AIX64 */ -#ifndef POWERPC64 -#define POWERPC64 -#endif -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - -#if defined (POWERPC_AIX) - FFI_AIX, - FFI_DARWIN, - FFI_DEFAULT_ABI = FFI_AIX, - FFI_LAST_ABI - -#elif defined (POWERPC_DARWIN) - FFI_AIX, - FFI_DARWIN, - FFI_DEFAULT_ABI = FFI_DARWIN, - FFI_LAST_ABI - -#else - /* The FFI_COMPAT values are used by old code. Since libffi may be - a shared library we have to support old values for backwards - compatibility. */ - FFI_COMPAT_SYSV, - FFI_COMPAT_GCC_SYSV, - FFI_COMPAT_LINUX64, - FFI_COMPAT_LINUX, - FFI_COMPAT_LINUX_SOFT_FLOAT, - -# if defined (POWERPC64) - /* This bit, always set in new code, must not be set in any of the - old FFI_COMPAT values that might be used for 64-bit linux. We - only need worry about FFI_COMPAT_LINUX64, but to be safe avoid - all old values. */ - FFI_LINUX = 8, - /* This and following bits can reuse FFI_COMPAT values. */ - FFI_LINUX_STRUCT_ALIGN = 1, - FFI_LINUX_LONG_DOUBLE_128 = 2, - FFI_DEFAULT_ABI = (FFI_LINUX -# ifdef __STRUCT_PARM_ALIGN__ - | FFI_LINUX_STRUCT_ALIGN -# endif -# ifdef __LONG_DOUBLE_128__ - | FFI_LINUX_LONG_DOUBLE_128 -# endif - ), - FFI_LAST_ABI = 12 - -# else - /* This bit, always set in new code, must not be set in any of the - old FFI_COMPAT values that might be used for 32-bit linux/sysv/bsd. */ - FFI_SYSV = 8, - /* This and following bits can reuse FFI_COMPAT values. */ - FFI_SYSV_SOFT_FLOAT = 1, - FFI_SYSV_STRUCT_RET = 2, - FFI_SYSV_IBM_LONG_DOUBLE = 4, - FFI_SYSV_LONG_DOUBLE_128 = 16, - - FFI_DEFAULT_ABI = (FFI_SYSV -# ifdef __NO_FPRS__ - | FFI_SYSV_SOFT_FLOAT -# endif -# if (defined (__SVR4_STRUCT_RETURN) \ - || defined (POWERPC_FREEBSD) && !defined (__AIX_STRUCT_RETURN)) - | FFI_SYSV_STRUCT_RET -# endif -# if __LDBL_MANT_DIG__ == 106 - | FFI_SYSV_IBM_LONG_DOUBLE -# endif -# ifdef __LONG_DOUBLE_128__ - | FFI_SYSV_LONG_DOUBLE_128 -# endif - ), - FFI_LAST_ABI = 32 -# endif -#endif - -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 -#if defined (POWERPC) || defined (POWERPC_FREEBSD) -# define FFI_TARGET_SPECIFIC_VARIADIC 1 -# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs -#endif - -/* For additional types like the below, take care about the order in - ppc_closures.S. They must follow after the FFI_TYPE_LAST. */ - -/* Needed for soft-float long-double-128 support. */ -#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1) - -/* Needed for FFI_SYSV small structure returns. */ -#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2) - -/* Used by ELFv2 for homogenous structure returns. */ -#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1) -#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2) -#define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3) - -#if _CALL_ELF == 2 -# define FFI_TRAMPOLINE_SIZE 32 -#else -# if defined(POWERPC64) || defined(POWERPC_AIX) -# if defined(POWERPC_DARWIN64) -# define FFI_TRAMPOLINE_SIZE 48 -# else -# define FFI_TRAMPOLINE_SIZE 24 -# endif -# else /* POWERPC || POWERPC_AIX */ -# define FFI_TRAMPOLINE_SIZE 40 -# endif -#endif - -#ifndef LIBFFI_ASM -#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) -struct ffi_aix_trampoline_struct { - void * code_pointer; /* Pointer to ffi_closure_ASM */ - void * toc; /* TOC */ - void * static_chain; /* Pointer to closure */ -}; -#endif -#endif - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64.S deleted file mode 100644 index d2acb7007..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64.S +++ /dev/null @@ -1,261 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.h - Copyright (c) 2003 Jakub Jelinek - Copyright (c) 2008 Red Hat, Inc. - - PowerPC64 Assembly glue. - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#ifdef POWERPC64 - .hidden ffi_call_LINUX64 - .globl ffi_call_LINUX64 -# if _CALL_ELF == 2 - .text -ffi_call_LINUX64: - addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha - addi %r2, %r2, .TOC.-ffi_call_LINUX64@l - .localentry ffi_call_LINUX64, . - ffi_call_LINUX64 -# else - .section ".opd","aw" - .align 3 -ffi_call_LINUX64: -# ifdef _CALL_LINUX - .quad .L.ffi_call_LINUX64,.TOC.@tocbase,0 - .type ffi_call_LINUX64,@function - .text -.L.ffi_call_LINUX64: -# else - .hidden .ffi_call_LINUX64 - .globl .ffi_call_LINUX64 - .quad .ffi_call_LINUX64,.TOC.@tocbase,0 - .size ffi_call_LINUX64,24 - .type .ffi_call_LINUX64,@function - .text -.ffi_call_LINUX64: -# endif -# endif -.LFB1: - mflr %r0 - std %r28, -32(%r1) - std %r29, -24(%r1) - std %r30, -16(%r1) - std %r31, -8(%r1) - std %r0, 16(%r1) - - mr %r28, %r1 /* our AP. */ -.LCFI0: - stdux %r1, %r1, %r4 - mr %r31, %r5 /* flags, */ - mr %r30, %r6 /* rvalue, */ - mr %r29, %r7 /* function address. */ -/* Save toc pointer, not for the ffi_prep_args64 call, but for the later - bctrl function call. */ -# if _CALL_ELF == 2 - std %r2, 24(%r1) -# else - std %r2, 40(%r1) -# endif - - /* Call ffi_prep_args64. */ - mr %r4, %r1 -# if defined _CALL_LINUX || _CALL_ELF == 2 - bl ffi_prep_args64 -# else - bl .ffi_prep_args64 -# endif - -# if _CALL_ELF == 2 - mr %r12, %r29 -# else - ld %r12, 0(%r29) - ld %r2, 8(%r29) - ld %r11, 16(%r29) -# endif - /* Now do the call. */ - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40, %r31 - - /* Get the address to call into CTR. */ - mtctr %r12 - /* Load all those argument registers. */ - ld %r3, -32-(8*8)(%r28) - ld %r4, -32-(7*8)(%r28) - ld %r5, -32-(6*8)(%r28) - ld %r6, -32-(5*8)(%r28) - bf- 5, 1f - ld %r7, -32-(4*8)(%r28) - ld %r8, -32-(3*8)(%r28) - ld %r9, -32-(2*8)(%r28) - ld %r10, -32-(1*8)(%r28) -1: - - /* Load all the FP registers. */ - bf- 6, 2f - lfd %f1, -32-(21*8)(%r28) - lfd %f2, -32-(20*8)(%r28) - lfd %f3, -32-(19*8)(%r28) - lfd %f4, -32-(18*8)(%r28) - lfd %f5, -32-(17*8)(%r28) - lfd %f6, -32-(16*8)(%r28) - lfd %f7, -32-(15*8)(%r28) - lfd %f8, -32-(14*8)(%r28) - lfd %f9, -32-(13*8)(%r28) - lfd %f10, -32-(12*8)(%r28) - lfd %f11, -32-(11*8)(%r28) - lfd %f12, -32-(10*8)(%r28) - lfd %f13, -32-(9*8)(%r28) -2: - - /* Make the call. */ - bctrl - - /* This must follow the call immediately, the unwinder - uses this to find out if r2 has been saved or not. */ -# if _CALL_ELF == 2 - ld %r2, 24(%r1) -# else - ld %r2, 40(%r1) -# endif - - /* Now, deal with the return value. */ - mtcrf 0x01, %r31 - bt 31, .Lstruct_return_value - bt 30, .Ldone_return_value - bt 29, .Lfp_return_value - std %r3, 0(%r30) - /* Fall through... */ - -.Ldone_return_value: - /* Restore the registers we used and return. */ - mr %r1, %r28 - ld %r0, 16(%r28) - ld %r28, -32(%r28) - mtlr %r0 - ld %r29, -24(%r1) - ld %r30, -16(%r1) - ld %r31, -8(%r1) - blr - -.Lfp_return_value: - bf 28, .Lfloat_return_value - stfd %f1, 0(%r30) - mtcrf 0x02, %r31 /* cr6 */ - bf 27, .Ldone_return_value - stfd %f2, 8(%r30) - b .Ldone_return_value -.Lfloat_return_value: - stfs %f1, 0(%r30) - b .Ldone_return_value - -.Lstruct_return_value: - bf 29, .Lsmall_struct - bf 28, .Lfloat_homog_return_value - stfd %f1, 0(%r30) - stfd %f2, 8(%r30) - stfd %f3, 16(%r30) - stfd %f4, 24(%r30) - stfd %f5, 32(%r30) - stfd %f6, 40(%r30) - stfd %f7, 48(%r30) - stfd %f8, 56(%r30) - b .Ldone_return_value - -.Lfloat_homog_return_value: - stfs %f1, 0(%r30) - stfs %f2, 4(%r30) - stfs %f3, 8(%r30) - stfs %f4, 12(%r30) - stfs %f5, 16(%r30) - stfs %f6, 20(%r30) - stfs %f7, 24(%r30) - stfs %f8, 28(%r30) - b .Ldone_return_value - -.Lsmall_struct: - std %r3, 0(%r30) - std %r4, 8(%r30) - b .Ldone_return_value - -.LFE1: - .long 0 - .byte 0,12,0,1,128,4,0,0 -# if _CALL_ELF == 2 - .size ffi_call_LINUX64,.-ffi_call_LINUX64 -# else -# ifdef _CALL_LINUX - .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 -# else - .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 -# endif -# endif - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x14 # FDE Encoding (pcrel udata8) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 3 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .8byte .LFB1-. # FDE initial location - .8byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x2 # DW_CFA_advance_loc1 - .byte .LCFI0-.LFB1 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0x1c - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -2 - .byte 0x9f # DW_CFA_offset, column 0x1f - .uleb128 0x1 - .byte 0x9e # DW_CFA_offset, column 0x1e - .uleb128 0x2 - .byte 0x9d # DW_CFA_offset, column 0x1d - .uleb128 0x3 - .byte 0x9c # DW_CFA_offset, column 0x1c - .uleb128 0x4 - .align 3 -.LEFDE1: - -#endif - -#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64_closure.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64_closure.S deleted file mode 100644 index 97421a43c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/linux64_closure.S +++ /dev/null @@ -1,392 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.h - Copyright (c) 2003 Jakub Jelinek - Copyright (c) 2008 Red Hat, Inc. - - PowerPC64 Assembly glue. - - 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. - ----------------------------------------------------------------------- */ -#define LIBFFI_ASM -#include -#include - - .file "linux64_closure.S" - -#ifdef POWERPC64 - FFI_HIDDEN (ffi_closure_LINUX64) - .globl ffi_closure_LINUX64 -# if _CALL_ELF == 2 - .text -ffi_closure_LINUX64: - addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha - addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l - .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64 -# else - .section ".opd","aw" - .align 3 -ffi_closure_LINUX64: -# ifdef _CALL_LINUX - .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0 - .type ffi_closure_LINUX64,@function - .text -.L.ffi_closure_LINUX64: -# else - FFI_HIDDEN (.ffi_closure_LINUX64) - .globl .ffi_closure_LINUX64 - .quad .ffi_closure_LINUX64,.TOC.@tocbase,0 - .size ffi_closure_LINUX64,24 - .type .ffi_closure_LINUX64,@function - .text -.ffi_closure_LINUX64: -# endif -# endif - -# if _CALL_ELF == 2 -# 32 byte special reg save area + 64 byte parm save area -# + 64 byte retval area + 13*8 fpr save area + round to 16 -# define STACKFRAME 272 -# define PARMSAVE 32 -# define RETVAL PARMSAVE+64 -# else -# 48 bytes special reg save area + 64 bytes parm save area -# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 -# define STACKFRAME 240 -# define PARMSAVE 48 -# define RETVAL PARMSAVE+64 -# endif - -.LFB1: -# if _CALL_ELF == 2 - ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif - mflr %r0 - lwz %r12, 28(%r12) # cif->flags - mtcrf 0x40, %r12 - addi %r12, %r1, PARMSAVE - bt 7, .Lparmsave - # Our caller has not allocated a parameter save area. - # We need to allocate one here and use it to pass gprs to - # ffi_closure_helper_LINUX64. - addi %r12, %r1, -STACKFRAME+PARMSAVE -.Lparmsave: - std %r0, 16(%r1) - # Save general regs into parm save area - std %r3, 0(%r12) - std %r4, 8(%r12) - std %r5, 16(%r12) - std %r6, 24(%r12) - std %r7, 32(%r12) - std %r8, 40(%r12) - std %r9, 48(%r12) - std %r10, 56(%r12) - - # load up the pointer to the parm save area - mr %r5, %r12 -# else - # copy r2 to r11 and load TOC into r2 - mr %r11, %r2 - ld %r2, 16(%r11) - - mflr %r0 - # Save general regs into parm save area - # This is the parameter save area set up by our caller. - std %r3, PARMSAVE+0(%r1) - std %r4, PARMSAVE+8(%r1) - std %r5, PARMSAVE+16(%r1) - std %r6, PARMSAVE+24(%r1) - std %r7, PARMSAVE+32(%r1) - std %r8, PARMSAVE+40(%r1) - std %r9, PARMSAVE+48(%r1) - std %r10, PARMSAVE+56(%r1) - - std %r0, 16(%r1) - - # load up the pointer to the parm save area - addi %r5, %r1, PARMSAVE -# endif - - # next save fpr 1 to fpr 13 - stfd %f1, -104+(0*8)(%r1) - stfd %f2, -104+(1*8)(%r1) - stfd %f3, -104+(2*8)(%r1) - stfd %f4, -104+(3*8)(%r1) - stfd %f5, -104+(4*8)(%r1) - stfd %f6, -104+(5*8)(%r1) - stfd %f7, -104+(6*8)(%r1) - stfd %f8, -104+(7*8)(%r1) - stfd %f9, -104+(8*8)(%r1) - stfd %f10, -104+(9*8)(%r1) - stfd %f11, -104+(10*8)(%r1) - stfd %f12, -104+(11*8)(%r1) - stfd %f13, -104+(12*8)(%r1) - - # load up the pointer to the saved fpr registers */ - addi %r6, %r1, -104 - - # load up the pointer to the result storage - addi %r4, %r1, -STACKFRAME+RETVAL - - stdu %r1, -STACKFRAME(%r1) -.LCFI0: - - # get the context pointer from the trampoline - mr %r3, %r11 - - # make the call -# if defined _CALL_LINUX || _CALL_ELF == 2 - bl ffi_closure_helper_LINUX64 -# else - bl .ffi_closure_helper_LINUX64 -# endif -.Lret: - - # now r3 contains the return type - # so use it to look up in a table - # so we know how to deal with each type - - # look up the proper starting point in table - # by using return type as offset - ld %r0, STACKFRAME+16(%r1) - cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT - bge .Lsmall - mflr %r4 # move address of .Lret to r4 - sldi %r3, %r3, 4 # now multiply return type by 16 - addi %r4, %r4, .Lret_type0 - .Lret - add %r3, %r3, %r4 # add contents of table to table address - mtctr %r3 - bctr # jump to it - -# Each of the ret_typeX code fragments has to be exactly 16 bytes long -# (4 instructions). For cache effectiveness we align to a 16 byte boundary -# first. - .align 4 - -.Lret_type0: -# case FFI_TYPE_VOID - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr - nop -# case FFI_TYPE_INT -# ifdef __LITTLE_ENDIAN__ - lwa %r3, RETVAL+0(%r1) -# else - lwa %r3, RETVAL+4(%r1) -# endif - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_FLOAT - lfs %f1, RETVAL+0(%r1) - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_DOUBLE - lfd %f1, RETVAL+0(%r1) - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_LONGDOUBLE - lfd %f1, RETVAL+0(%r1) - mtlr %r0 - lfd %f2, RETVAL+8(%r1) - b .Lfinish -# case FFI_TYPE_UINT8 -# ifdef __LITTLE_ENDIAN__ - lbz %r3, RETVAL+0(%r1) -# else - lbz %r3, RETVAL+7(%r1) -# endif - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_SINT8 -# ifdef __LITTLE_ENDIAN__ - lbz %r3, RETVAL+0(%r1) -# else - lbz %r3, RETVAL+7(%r1) -# endif - extsb %r3,%r3 - mtlr %r0 - b .Lfinish -# case FFI_TYPE_UINT16 -# ifdef __LITTLE_ENDIAN__ - lhz %r3, RETVAL+0(%r1) -# else - lhz %r3, RETVAL+6(%r1) -# endif - mtlr %r0 -.Lfinish: - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_SINT16 -# ifdef __LITTLE_ENDIAN__ - lha %r3, RETVAL+0(%r1) -# else - lha %r3, RETVAL+6(%r1) -# endif - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_UINT32 -# ifdef __LITTLE_ENDIAN__ - lwz %r3, RETVAL+0(%r1) -# else - lwz %r3, RETVAL+4(%r1) -# endif - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_SINT32 -# ifdef __LITTLE_ENDIAN__ - lwa %r3, RETVAL+0(%r1) -# else - lwa %r3, RETVAL+4(%r1) -# endif - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_UINT64 - ld %r3, RETVAL+0(%r1) - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_SINT64 - ld %r3, RETVAL+0(%r1) - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_TYPE_STRUCT - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr - nop -# case FFI_TYPE_POINTER - ld %r3, RETVAL+0(%r1) - mtlr %r0 - addi %r1, %r1, STACKFRAME - blr -# case FFI_V2_TYPE_FLOAT_HOMOG - lfs %f1, RETVAL+0(%r1) - lfs %f2, RETVAL+4(%r1) - lfs %f3, RETVAL+8(%r1) - b .Lmorefloat -# case FFI_V2_TYPE_DOUBLE_HOMOG - lfd %f1, RETVAL+0(%r1) - lfd %f2, RETVAL+8(%r1) - lfd %f3, RETVAL+16(%r1) - lfd %f4, RETVAL+24(%r1) - mtlr %r0 - lfd %f5, RETVAL+32(%r1) - lfd %f6, RETVAL+40(%r1) - lfd %f7, RETVAL+48(%r1) - lfd %f8, RETVAL+56(%r1) - addi %r1, %r1, STACKFRAME - blr -.Lmorefloat: - lfs %f4, RETVAL+12(%r1) - mtlr %r0 - lfs %f5, RETVAL+16(%r1) - lfs %f6, RETVAL+20(%r1) - lfs %f7, RETVAL+24(%r1) - lfs %f8, RETVAL+28(%r1) - addi %r1, %r1, STACKFRAME - blr -.Lsmall: -# ifdef __LITTLE_ENDIAN__ - ld %r3,RETVAL+0(%r1) - mtlr %r0 - ld %r4,RETVAL+8(%r1) - addi %r1, %r1, STACKFRAME - blr -# else - # A struct smaller than a dword is returned in the low bits of r3 - # ie. right justified. Larger structs are passed left justified - # in r3 and r4. The return value area on the stack will have - # the structs as they are usually stored in memory. - cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes? - neg %r5, %r3 - ld %r3,RETVAL+0(%r1) - blt .Lsmalldown - mtlr %r0 - ld %r4,RETVAL+8(%r1) - addi %r1, %r1, STACKFRAME - blr -.Lsmalldown: - addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7 - mtlr %r0 - sldi %r5, %r5, 3 - addi %r1, %r1, STACKFRAME - srd %r3, %r3, %r5 - blr -# endif - -.LFE1: - .long 0 - .byte 0,12,0,1,128,0,0,0 -# if _CALL_ELF == 2 - .size ffi_closure_LINUX64,.-ffi_closure_LINUX64 -# else -# ifdef _CALL_LINUX - .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64 -# else - .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 -# endif -# endif - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x14 # FDE Encoding (pcrel udata8) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 3 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .8byte .LFB1-. # FDE initial location - .8byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x2 # DW_CFA_advance_loc1 - .byte .LCFI0-.LFB1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 STACKFRAME - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -2 - .align 3 -.LEFDE1: - -#endif - -#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ppc_closure.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ppc_closure.S deleted file mode 100644 index 075922cbb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/ppc_closure.S +++ /dev/null @@ -1,384 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.h - Copyright (c) 2003 Jakub Jelinek - Copyright (c) 2008 Red Hat, Inc. - - PowerPC Assembly glue. - - 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. - ----------------------------------------------------------------------- */ -#define LIBFFI_ASM -#include -#include -#include - - .file "ppc_closure.S" - -#ifndef POWERPC64 - -ENTRY(ffi_closure_SYSV) -.LFB1: - stwu %r1,-144(%r1) -.LCFI0: - mflr %r0 -.LCFI1: - stw %r0,148(%r1) - -# we want to build up an areas for the parameters passed -# in registers (both floating point and integer) - - # so first save gpr 3 to gpr 10 (aligned to 4) - stw %r3, 16(%r1) - stw %r4, 20(%r1) - stw %r5, 24(%r1) - stw %r6, 28(%r1) - stw %r7, 32(%r1) - stw %r8, 36(%r1) - stw %r9, 40(%r1) - stw %r10,44(%r1) - -#ifndef __NO_FPRS__ - # next save fpr 1 to fpr 8 (aligned to 8) - stfd %f1, 48(%r1) - stfd %f2, 56(%r1) - stfd %f3, 64(%r1) - stfd %f4, 72(%r1) - stfd %f5, 80(%r1) - stfd %f6, 88(%r1) - stfd %f7, 96(%r1) - stfd %f8, 104(%r1) -#endif - - # set up registers for the routine that actually does the work - # get the context pointer from the trampoline - mr %r3,%r11 - - # now load up the pointer to the result storage - addi %r4,%r1,112 - - # now load up the pointer to the saved gpr registers - addi %r5,%r1,16 - - # now load up the pointer to the saved fpr registers */ - addi %r6,%r1,48 - - # now load up the pointer to the outgoing parameter - # stack in the previous frame - # i.e. the previous frame pointer + 8 - addi %r7,%r1,152 - - # make the call - bl ffi_closure_helper_SYSV@local -.Lret: - # now r3 contains the return type - # so use it to look up in a table - # so we know how to deal with each type - - # look up the proper starting point in table - # by using return type as offset - - mflr %r4 # move address of .Lret to r4 - slwi %r3,%r3,4 # now multiply return type by 16 - addi %r4, %r4, .Lret_type0 - .Lret - lwz %r0,148(%r1) - add %r3,%r3,%r4 # add contents of table to table address - mtctr %r3 - bctr # jump to it -.LFE1: - -# Each of the ret_typeX code fragments has to be exactly 16 bytes long -# (4 instructions). For cache effectiveness we align to a 16 byte boundary -# first. - .align 4 -# case FFI_TYPE_VOID -.Lret_type0: - mtlr %r0 - addi %r1,%r1,144 - blr - nop - -# case FFI_TYPE_INT - lwz %r3,112+0(%r1) - mtlr %r0 -.Lfinish: - addi %r1,%r1,144 - blr - -# case FFI_TYPE_FLOAT -#ifndef __NO_FPRS__ - lfs %f1,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 -#else - nop - nop - nop -#endif - blr - -# case FFI_TYPE_DOUBLE -#ifndef __NO_FPRS__ - lfd %f1,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 -#else - nop - nop - nop -#endif - blr - -# case FFI_TYPE_LONGDOUBLE -#ifndef __NO_FPRS__ - lfd %f1,112+0(%r1) - lfd %f2,112+8(%r1) - mtlr %r0 - b .Lfinish -#else - nop - nop - nop - blr -#endif - -# case FFI_TYPE_UINT8 -#ifdef __LITTLE_ENDIAN__ - lbz %r3,112+0(%r1) -#else - lbz %r3,112+3(%r1) -#endif - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_SINT8 -#ifdef __LITTLE_ENDIAN__ - lbz %r3,112+0(%r1) -#else - lbz %r3,112+3(%r1) -#endif - extsb %r3,%r3 - mtlr %r0 - b .Lfinish - -# case FFI_TYPE_UINT16 -#ifdef __LITTLE_ENDIAN__ - lhz %r3,112+0(%r1) -#else - lhz %r3,112+2(%r1) -#endif - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_SINT16 -#ifdef __LITTLE_ENDIAN__ - lha %r3,112+0(%r1) -#else - lha %r3,112+2(%r1) -#endif - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_UINT32 - lwz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_SINT32 - lwz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_UINT64 - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) - mtlr %r0 - b .Lfinish - -# case FFI_TYPE_SINT64 - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) - mtlr %r0 - b .Lfinish - -# case FFI_TYPE_STRUCT - mtlr %r0 - addi %r1,%r1,144 - blr - nop - -# case FFI_TYPE_POINTER - lwz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_TYPE_UINT128 - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) - lwz %r5,112+8(%r1) - b .Luint128 - -# The return types below are only used when the ABI type is FFI_SYSV. -# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct. - lbz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct. - lhz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. - lwz %r3,112+0(%r1) -#ifdef __LITTLE_ENDIAN__ - mtlr %r0 - addi %r1,%r1,144 - blr -#else - srwi %r3,%r3,8 - mtlr %r0 - b .Lfinish -#endif - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct. - lwz %r3,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) -#ifdef __LITTLE_ENDIAN__ - mtlr %r0 - b .Lfinish -#else - li %r5,24 - b .Lstruct567 -#endif - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct. - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) -#ifdef __LITTLE_ENDIAN__ - mtlr %r0 - b .Lfinish -#else - li %r5,16 - b .Lstruct567 -#endif - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct. - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) -#ifdef __LITTLE_ENDIAN__ - mtlr %r0 - b .Lfinish -#else - li %r5,8 - b .Lstruct567 -#endif - -# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct. - lwz %r3,112+0(%r1) - lwz %r4,112+4(%r1) - mtlr %r0 - b .Lfinish - -#ifndef __LITTLE_ENDIAN__ -.Lstruct567: - subfic %r6,%r5,32 - srw %r4,%r4,%r5 - slw %r6,%r3,%r6 - srw %r3,%r3,%r5 - or %r4,%r6,%r4 - mtlr %r0 - addi %r1,%r1,144 - blr -#endif - -.Luint128: - lwz %r6,112+12(%r1) - mtlr %r0 - addi %r1,%r1,144 - blr - -END(ffi_closure_SYSV) - - .section ".eh_frame",EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version -#if defined _RELOCATABLE || defined __PIC__ - .ascii "zR\0" # CIE Augmentation -#else - .ascii "\0" # CIE Augmentation -#endif - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -4 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) -#endif - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 2 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset -#if defined _RELOCATABLE || defined __PIC__ - .4byte .LFB1-. # FDE initial location -#else - .4byte .LFB1 # FDE initial location -#endif - .4byte .LFE1-.LFB1 # FDE address range -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x0 # Augmentation size -#endif - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 144 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -1 - .align 2 -.LEFDE1: - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/sysv.S deleted file mode 100644 index fed2380c9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/powerpc/sysv.S +++ /dev/null @@ -1,220 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 1998 Geoffrey Keating - Copyright (C) 2007 Free Software Foundation, Inc - - PowerPC Assembly glue. - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#include - -#ifndef POWERPC64 - .globl ffi_prep_args_SYSV -ENTRY(ffi_call_SYSV) -.LFB1: - /* Save the old stack pointer as AP. */ - mr %r8,%r1 - -.LCFI0: - /* Allocate the stack space we need. */ - stwux %r1,%r1,%r4 - /* Save registers we use. */ - mflr %r9 - stw %r28,-16(%r8) -.LCFI1: - stw %r29,-12(%r8) -.LCFI2: - stw %r30, -8(%r8) -.LCFI3: - stw %r31, -4(%r8) -.LCFI4: - stw %r9, 4(%r8) -.LCFI5: - - /* Save arguments over call... */ - mr %r31,%r5 /* flags, */ - mr %r30,%r6 /* rvalue, */ - mr %r29,%r7 /* function address, */ - mr %r28,%r8 /* our AP. */ -.LCFI6: - - /* Call ffi_prep_args_SYSV. */ - mr %r4,%r1 - bl ffi_prep_args_SYSV@local - - /* Now do the call. */ - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40,%r31 - /* Get the address to call into CTR. */ - mtctr %r29 - /* Load all those argument registers. */ - lwz %r3,-16-(8*4)(%r28) - lwz %r4,-16-(7*4)(%r28) - lwz %r5,-16-(6*4)(%r28) - lwz %r6,-16-(5*4)(%r28) - bf- 5,1f - nop - lwz %r7,-16-(4*4)(%r28) - lwz %r8,-16-(3*4)(%r28) - lwz %r9,-16-(2*4)(%r28) - lwz %r10,-16-(1*4)(%r28) - nop -1: - -#ifndef __NO_FPRS__ - /* Load all the FP registers. */ - bf- 6,2f - lfd %f1,-16-(8*4)-(8*8)(%r28) - lfd %f2,-16-(8*4)-(7*8)(%r28) - lfd %f3,-16-(8*4)-(6*8)(%r28) - lfd %f4,-16-(8*4)-(5*8)(%r28) - nop - lfd %f5,-16-(8*4)-(4*8)(%r28) - lfd %f6,-16-(8*4)-(3*8)(%r28) - lfd %f7,-16-(8*4)-(2*8)(%r28) - lfd %f8,-16-(8*4)-(1*8)(%r28) -#endif -2: - - /* Make the call. */ - bctrl - - /* Now, deal with the return value. */ - mtcrf 0x01,%r31 /* cr7 */ - bt- 31,L(small_struct_return_value) - bt- 30,L(done_return_value) -#ifndef __NO_FPRS__ - bt- 29,L(fp_return_value) -#endif - stw %r3,0(%r30) - bf+ 28,L(done_return_value) - stw %r4,4(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) - stw %r5,8(%r30) - stw %r6,12(%r30) - /* Fall through... */ - -L(done_return_value): - /* Restore the registers we used and return. */ - lwz %r9, 4(%r28) - lwz %r31, -4(%r28) - mtlr %r9 - lwz %r30, -8(%r28) - lwz %r29,-12(%r28) - lwz %r28,-16(%r28) - lwz %r1,0(%r1) - blr - -#ifndef __NO_FPRS__ -L(fp_return_value): - bf 28,L(float_return_value) - stfd %f1,0(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) - stfd %f2,8(%r30) - b L(done_return_value) -L(float_return_value): - stfs %f1,0(%r30) - b L(done_return_value) -#endif - -L(small_struct_return_value): - /* - * The C code always allocates a properly-aligned 8-byte bounce - * buffer to make this assembly code very simple. Just write out - * r3 and r4 to the buffer to allow the C code to handle the rest. - */ - stw %r3, 0(%r30) - stw %r4, 4(%r30) - b L(done_return_value) - -.LFE1: -END(ffi_call_SYSV) - - .section ".eh_frame",EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .4byte 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#if defined _RELOCATABLE || defined __PIC__ - .ascii "zR\0" /* CIE Augmentation */ -#else - .ascii "\0" /* CIE Augmentation */ -#endif - .uleb128 0x1 /* CIE Code Alignment Factor */ - .sleb128 -4 /* CIE Data Alignment Factor */ - .byte 0x41 /* CIE RA Column */ -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x1 /* Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ -#endif - .byte 0xc /* DW_CFA_def_cfa */ - .uleb128 0x1 - .uleb128 0x0 - .align 2 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .4byte .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if defined _RELOCATABLE || defined __PIC__ - .4byte .LFB1-. /* FDE initial location */ -#else - .4byte .LFB1 /* FDE initial location */ -#endif - .4byte .LFE1-.LFB1 /* FDE address range */ -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x0 /* Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI0-.LFB1 - .byte 0xd /* DW_CFA_def_cfa_register */ - .uleb128 0x08 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI5-.LCFI0 - .byte 0x11 /* DW_CFA_offset_extended_sf */ - .uleb128 0x41 - .sleb128 -1 - .byte 0x9f /* DW_CFA_offset, column 0x1f */ - .uleb128 0x1 - .byte 0x9e /* DW_CFA_offset, column 0x1e */ - .uleb128 0x2 - .byte 0x9d /* DW_CFA_offset, column 0x1d */ - .uleb128 0x3 - .byte 0x9c /* DW_CFA_offset, column 0x1c */ - .uleb128 0x4 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI6-.LCFI5 - .byte 0xd /* DW_CFA_def_cfa_register */ - .uleb128 0x1c - .align 2 -.LEFDE1: - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/prep_cif.c b/ruby/ext/fiddle/libffi-3.2.1/src/prep_cif.c deleted file mode 100644 index be5eae379..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/prep_cif.c +++ /dev/null @@ -1,253 +0,0 @@ -/* ----------------------------------------------------------------------- - prep_cif.c - Copyright (c) 2011, 2012 Anthony Green - Copyright (c) 1996, 1998, 2007 Red Hat, Inc. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include -#include - -/* Round up to FFI_SIZEOF_ARG. */ - -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) - -/* Perform machine independent initialization of aggregate type - specifications. */ - -static ffi_status initialize_aggregate(ffi_type *arg) -{ - ffi_type **ptr; - - if (UNLIKELY(arg == NULL || arg->elements == NULL)) - return FFI_BAD_TYPEDEF; - - arg->size = 0; - arg->alignment = 0; - - ptr = &(arg->elements[0]); - - if (UNLIKELY(ptr == 0)) - return FFI_BAD_TYPEDEF; - - while ((*ptr) != NULL) - { - if (UNLIKELY(((*ptr)->size == 0) - && (initialize_aggregate((*ptr)) != FFI_OK))) - return FFI_BAD_TYPEDEF; - - /* Perform a sanity check on the argument type */ - FFI_ASSERT_VALID_TYPE(*ptr); - - arg->size = ALIGN(arg->size, (*ptr)->alignment); - arg->size += (*ptr)->size; - - arg->alignment = (arg->alignment > (*ptr)->alignment) ? - arg->alignment : (*ptr)->alignment; - - ptr++; - } - - /* Structure size includes tail padding. This is important for - structures that fit in one register on ABIs like the PowerPC64 - Linux ABI that right justify small structs in a register. - It's also needed for nested structure layout, for example - struct A { long a; char b; }; struct B { struct A x; char y; }; - should find y at an offset of 2*sizeof(long) and result in a - total size of 3*sizeof(long). */ - arg->size = ALIGN (arg->size, arg->alignment); - - /* On some targets, the ABI defines that structures have an additional - alignment beyond the "natural" one based on their elements. */ -#ifdef FFI_AGGREGATE_ALIGNMENT - if (FFI_AGGREGATE_ALIGNMENT > arg->alignment) - arg->alignment = FFI_AGGREGATE_ALIGNMENT; -#endif - - if (arg->size == 0) - return FFI_BAD_TYPEDEF; - else - return FFI_OK; -} - -#ifndef __CRIS__ -/* The CRIS ABI specifies structure elements to have byte - alignment only, so it completely overrides this functions, - which assumes "natural" alignment and padding. */ - -/* Perform machine independent ffi_cif preparation, then call - machine dependent routine. */ - -/* For non variadic functions isvariadic should be 0 and - nfixedargs==ntotalargs. - - For variadic calls, isvariadic should be 1 and nfixedargs - and ntotalargs set as appropriate. nfixedargs must always be >=1 */ - - -ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, - unsigned int isvariadic, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, ffi_type **atypes) -{ - unsigned bytes = 0; - unsigned int i; - ffi_type **ptr; - - FFI_ASSERT(cif != NULL); - FFI_ASSERT((!isvariadic) || (nfixedargs >= 1)); - FFI_ASSERT(nfixedargs <= ntotalargs); - - if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)) - return FFI_BAD_ABI; - - cif->abi = abi; - cif->arg_types = atypes; - cif->nargs = ntotalargs; - cif->rtype = rtype; - - cif->flags = 0; - -#if HAVE_LONG_DOUBLE_VARIANT - ffi_prep_types (abi); -#endif - - /* Initialize the return type if necessary */ - if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) - return FFI_BAD_TYPEDEF; - -#ifndef FFI_TARGET_HAS_COMPLEX_TYPE - if (rtype->type == FFI_TYPE_COMPLEX) - abort(); -#endif - /* Perform a sanity check on the return type */ - FFI_ASSERT_VALID_TYPE(cif->rtype); - - /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */ -#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION - /* Make space for the return structure pointer */ - if (cif->rtype->type == FFI_TYPE_STRUCT -#ifdef SPARC - && (cif->abi != FFI_V9 || cif->rtype->size > 32) -#endif -#ifdef TILE - && (cif->rtype->size > 10 * FFI_SIZEOF_ARG) -#endif -#ifdef XTENSA - && (cif->rtype->size > 16) -#endif -#ifdef NIOS2 - && (cif->rtype->size > 8) -#endif - ) - bytes = STACK_ARG_SIZE(sizeof(void*)); -#endif - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - - /* Initialize any uninitialized aggregate type definitions */ - if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) - return FFI_BAD_TYPEDEF; - -#ifndef FFI_TARGET_HAS_COMPLEX_TYPE - if ((*ptr)->type == FFI_TYPE_COMPLEX) - abort(); -#endif - /* Perform a sanity check on the argument type, do this - check after the initialization. */ - FFI_ASSERT_VALID_TYPE(*ptr); - -#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION -#ifdef SPARC - if (((*ptr)->type == FFI_TYPE_STRUCT - && ((*ptr)->size > 16 || cif->abi != FFI_V9)) - || ((*ptr)->type == FFI_TYPE_LONGDOUBLE - && cif->abi != FFI_V9)) - bytes += sizeof(void*); - else -#endif - { - /* Add any padding if necessary */ - if (((*ptr)->alignment - 1) & bytes) - bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment); - -#ifdef TILE - if (bytes < 10 * FFI_SIZEOF_ARG && - bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG) - { - /* An argument is never split between the 10 parameter - registers and the stack. */ - bytes = 10 * FFI_SIZEOF_ARG; - } -#endif -#ifdef XTENSA - if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4) - bytes = 6*4; -#endif - - bytes += STACK_ARG_SIZE((*ptr)->size); - } -#endif - } - - cif->bytes = bytes; - - /* Perform machine dependent cif processing */ -#ifdef FFI_TARGET_SPECIFIC_VARIADIC - if (isvariadic) - return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs); -#endif - - return ffi_prep_cif_machdep(cif); -} -#endif /* not __CRIS__ */ - -ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, - ffi_type *rtype, ffi_type **atypes) -{ - return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes); -} - -ffi_status ffi_prep_cif_var(ffi_cif *cif, - ffi_abi abi, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes) -{ - return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes); -} - -#if FFI_CLOSURES - -ffi_status -ffi_prep_closure (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data) -{ - return ffi_prep_closure_loc (closure, cif, fun, user_data, closure); -} - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/raw_api.c b/ruby/ext/fiddle/libffi-3.2.1/src/raw_api.c deleted file mode 100644 index 276cb2280..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/raw_api.c +++ /dev/null @@ -1,267 +0,0 @@ -/* ----------------------------------------------------------------------- - raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc. - - Author: Kresten Krab Thorup - - 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. - ----------------------------------------------------------------------- */ - -/* This file defines generic functions for use with the raw api. */ - -#include -#include - -#if !FFI_NO_RAW_API - -size_t -ffi_raw_size (ffi_cif *cif) -{ - size_t result = 0; - int i; - - ffi_type **at = cif->arg_types; - - for (i = cif->nargs-1; i >= 0; i--, at++) - { -#if !FFI_NO_STRUCTS - if ((*at)->type == FFI_TYPE_STRUCT) - result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); - else -#endif - result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); - } - - return result; -} - - -void -ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - -#if WORDS_BIGENDIAN - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1); - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2); - break; - -#if FFI_SIZEOF_ARG >= 4 - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4); - break; -#endif - -#if !FFI_NO_STRUCTS - case FFI_TYPE_STRUCT: - *args = (raw++)->ptr; - break; -#endif - - case FFI_TYPE_COMPLEX: - *args = (raw++)->ptr; - break; - - case FFI_TYPE_POINTER: - *args = (void*) &(raw++)->ptr; - break; - - default: - *args = raw; - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - } - } - -#else /* WORDS_BIGENDIAN */ - -#if !PDP - - /* then assume little endian */ - for (i = 0; i < cif->nargs; i++, tp++, args++) - { -#if !FFI_NO_STRUCTS - if ((*tp)->type == FFI_TYPE_STRUCT) - { - *args = (raw++)->ptr; - } - else -#endif - if ((*tp)->type == FFI_TYPE_COMPLEX) - { - *args = (raw++)->ptr; - } - else - { - *args = (void*) raw; - raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); - } - } - -#else -#error "pdp endian not supported" -#endif /* ! PDP */ - -#endif /* WORDS_BIGENDIAN */ -} - -void -ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: - (raw++)->uint = *(UINT8*) (*args); - break; - - case FFI_TYPE_SINT8: - (raw++)->sint = *(SINT8*) (*args); - break; - - case FFI_TYPE_UINT16: - (raw++)->uint = *(UINT16*) (*args); - break; - - case FFI_TYPE_SINT16: - (raw++)->sint = *(SINT16*) (*args); - break; - -#if FFI_SIZEOF_ARG >= 4 - case FFI_TYPE_UINT32: - (raw++)->uint = *(UINT32*) (*args); - break; - - case FFI_TYPE_SINT32: - (raw++)->sint = *(SINT32*) (*args); - break; -#endif - -#if !FFI_NO_STRUCTS - case FFI_TYPE_STRUCT: - (raw++)->ptr = *args; - break; -#endif - - case FFI_TYPE_COMPLEX: - (raw++)->ptr = *args; - break; - - case FFI_TYPE_POINTER: - (raw++)->ptr = **(void***) args; - break; - - default: - memcpy ((void*) raw->data, (void*)*args, (*tp)->size); - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - } - } -} - -#if !FFI_NATIVE_RAW_API - - -/* This is a generic definition of ffi_raw_call, to be used if the - * native system does not provide a machine-specific implementation. - * Having this, allows code to be written for the raw API, without - * the need for system-specific code to handle input in that format; - * these following couple of functions will handle the translation forth - * and back automatically. */ - -void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw) -{ - void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - ffi_raw_to_ptrarray (cif, raw, avalue); - ffi_call (cif, fn, rvalue, avalue); -} - -#if FFI_CLOSURES /* base system provides closures */ - -static void -ffi_translate_args (ffi_cif *cif, void *rvalue, - void **avalue, void *user_data) -{ - ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif)); - ffi_raw_closure *cl = (ffi_raw_closure*)user_data; - - ffi_ptrarray_to_raw (cif, avalue, raw); - (*cl->fun) (cif, rvalue, raw, cl->user_data); -} - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc) -{ - ffi_status status; - - status = ffi_prep_closure_loc ((ffi_closure*) cl, - cif, - &ffi_translate_args, - codeloc, - codeloc); - if (status == FFI_OK) - { - cl->fun = fun; - cl->user_data = user_data; - } - - return status; -} - -#endif /* FFI_CLOSURES */ -#endif /* !FFI_NATIVE_RAW_API */ - -#if FFI_CLOSURES - -/* Again, here is the generic version of ffi_prep_raw_closure, which - * will install an intermediate "hub" for translation of arguments from - * the pointer-array format, to the raw format */ - -ffi_status -ffi_prep_raw_closure (ffi_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data) -{ - return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl); -} - -#endif /* FFI_CLOSURES */ - -#endif /* !FFI_NO_RAW_API */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffi.c deleted file mode 100644 index 520ec7c61..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffi.c +++ /dev/null @@ -1,792 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2000, 2007 Software AG - Copyright (c) 2008 Red Hat, Inc - - S390 Foreign Function Interface - - 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 AUTHOR 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. - ----------------------------------------------------------------------- */ -/*====================================================================*/ -/* Includes */ -/* -------- */ -/*====================================================================*/ - -#include -#include - -#include -#include - -/*====================== End of Includes =============================*/ - -/*====================================================================*/ -/* Defines */ -/* ------- */ -/*====================================================================*/ - -/* Maximum number of GPRs available for argument passing. */ -#define MAX_GPRARGS 5 - -/* Maximum number of FPRs available for argument passing. */ -#ifdef __s390x__ -#define MAX_FPRARGS 4 -#else -#define MAX_FPRARGS 2 -#endif - -/* Round to multiple of 16. */ -#define ROUND_SIZE(size) (((size) + 15) & ~15) - -/* If these values change, sysv.S must be adapted! */ -#define FFI390_RET_VOID 0 -#define FFI390_RET_STRUCT 1 -#define FFI390_RET_FLOAT 2 -#define FFI390_RET_DOUBLE 3 -#define FFI390_RET_INT32 4 -#define FFI390_RET_INT64 5 - -/*===================== End of Defines ===============================*/ - -/*====================================================================*/ -/* Prototypes */ -/* ---------- */ -/*====================================================================*/ - -static void ffi_prep_args (unsigned char *, extended_cif *); -void -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) -__attribute__ ((visibility ("hidden"))) -#endif -ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, - unsigned long long *, unsigned long *); - -/*====================== End of Prototypes ===========================*/ - -/*====================================================================*/ -/* Externals */ -/* --------- */ -/*====================================================================*/ - -extern void ffi_call_SYSV(unsigned, - extended_cif *, - void (*)(unsigned char *, extended_cif *), - unsigned, - void *, - void (*fn)(void)); - -extern void ffi_closure_SYSV(void); - -/*====================== End of Externals ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_check_struct_type. */ -/* */ -/* Function - Determine if a structure can be passed within a */ -/* general purpose or floating point register. */ -/* */ -/*====================================================================*/ - -static int -ffi_check_struct_type (ffi_type *arg) -{ - size_t size = arg->size; - - /* If the struct has just one element, look at that element - to find out whether to consider the struct as floating point. */ - while (arg->type == FFI_TYPE_STRUCT - && arg->elements[0] && !arg->elements[1]) - arg = arg->elements[0]; - - /* Structs of size 1, 2, 4, and 8 are passed in registers, - just like the corresponding int/float types. */ - switch (size) - { - case 1: - return FFI_TYPE_UINT8; - - case 2: - return FFI_TYPE_UINT16; - - case 4: - if (arg->type == FFI_TYPE_FLOAT) - return FFI_TYPE_FLOAT; - else - return FFI_TYPE_UINT32; - - case 8: - if (arg->type == FFI_TYPE_DOUBLE) - return FFI_TYPE_DOUBLE; - else - return FFI_TYPE_UINT64; - - default: - break; - } - - /* Other structs are passed via a pointer to the data. */ - return FFI_TYPE_POINTER; -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_prep_args. */ -/* */ -/* Function - Prepare parameters for call to function. */ -/* */ -/* ffi_prep_args is called by the assembly routine once stack space */ -/* has been allocated for the function's arguments. */ -/* */ -/*====================================================================*/ - -static void -ffi_prep_args (unsigned char *stack, extended_cif *ecif) -{ - /* The stack space will be filled with those areas: - - FPR argument register save area (highest addresses) - GPR argument register save area - temporary struct copies - overflow argument area (lowest addresses) - - We set up the following pointers: - - p_fpr: bottom of the FPR area (growing upwards) - p_gpr: bottom of the GPR area (growing upwards) - p_ov: bottom of the overflow area (growing upwards) - p_struct: top of the struct copy area (growing downwards) - - All areas are kept aligned to twice the word size. */ - - int gpr_off = ecif->cif->bytes; - int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long)); - - unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off); - unsigned long *p_gpr = (unsigned long *)(stack + gpr_off); - unsigned char *p_struct = (unsigned char *)p_gpr; - unsigned long *p_ov = (unsigned long *)stack; - - int n_fpr = 0; - int n_gpr = 0; - int n_ov = 0; - - ffi_type **ptr; - void **p_argv = ecif->avalue; - int i; - - /* If we returning a structure then we set the first parameter register - to the address of where we are returning this structure. */ - - if (ecif->cif->flags == FFI390_RET_STRUCT) - p_gpr[n_gpr++] = (unsigned long) ecif->rvalue; - - /* Now for the arguments. */ - - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; - i > 0; - i--, ptr++, p_argv++) - { - void *arg = *p_argv; - int type = (*ptr)->type; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - /* 16-byte long double is passed like a struct. */ - if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_STRUCT; -#endif - - /* Check how a structure type is passed. */ - if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX) - { - if (type == FFI_TYPE_COMPLEX) - type = FFI_TYPE_POINTER; - else - type = ffi_check_struct_type (*ptr); - - /* If we pass the struct via pointer, copy the data. */ - if (type == FFI_TYPE_POINTER) - { - p_struct -= ROUND_SIZE ((*ptr)->size); - memcpy (p_struct, (char *)arg, (*ptr)->size); - arg = &p_struct; - } - } - - /* Now handle all primitive int/pointer/float data types. */ - switch (type) - { - case FFI_TYPE_DOUBLE: - if (n_fpr < MAX_FPRARGS) - p_fpr[n_fpr++] = *(unsigned long long *) arg; - else -#ifdef __s390x__ - p_ov[n_ov++] = *(unsigned long *) arg; -#else - p_ov[n_ov++] = ((unsigned long *) arg)[0], - p_ov[n_ov++] = ((unsigned long *) arg)[1]; -#endif - break; - - case FFI_TYPE_FLOAT: - if (n_fpr < MAX_FPRARGS) - p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32; - else - p_ov[n_ov++] = *(unsigned int *) arg; - break; - - case FFI_TYPE_POINTER: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg; - else - p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#ifdef __s390x__ - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(unsigned long *) arg; - else - p_ov[n_ov++] = *(unsigned long *) arg; -#else - if (n_gpr == MAX_GPRARGS-1) - n_gpr = MAX_GPRARGS; - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = ((unsigned long *) arg)[0], - p_gpr[n_gpr++] = ((unsigned long *) arg)[1]; - else - p_ov[n_ov++] = ((unsigned long *) arg)[0], - p_ov[n_ov++] = ((unsigned long *) arg)[1]; -#endif - break; - - case FFI_TYPE_UINT32: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(unsigned int *) arg; - else - p_ov[n_ov++] = *(unsigned int *) arg; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(signed int *) arg; - else - p_ov[n_ov++] = *(signed int *) arg; - break; - - case FFI_TYPE_UINT16: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(unsigned short *) arg; - else - p_ov[n_ov++] = *(unsigned short *) arg; - break; - - case FFI_TYPE_SINT16: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(signed short *) arg; - else - p_ov[n_ov++] = *(signed short *) arg; - break; - - case FFI_TYPE_UINT8: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(unsigned char *) arg; - else - p_ov[n_ov++] = *(unsigned char *) arg; - break; - - case FFI_TYPE_SINT8: - if (n_gpr < MAX_GPRARGS) - p_gpr[n_gpr++] = *(signed char *) arg; - else - p_ov[n_ov++] = *(signed char *) arg; - break; - - default: - FFI_ASSERT (0); - break; - } - } -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_prep_cif_machdep. */ -/* */ -/* Function - Perform machine dependent CIF processing. */ -/* */ -/*====================================================================*/ - -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) -{ - size_t struct_size = 0; - int n_gpr = 0; - int n_fpr = 0; - int n_ov = 0; - - ffi_type **ptr; - int i; - - /* Determine return value handling. */ - - switch (cif->rtype->type) - { - /* Void is easy. */ - case FFI_TYPE_VOID: - cif->flags = FFI390_RET_VOID; - break; - - /* Structures and complex are returned via a hidden pointer. */ - case FFI_TYPE_STRUCT: - case FFI_TYPE_COMPLEX: - cif->flags = FFI390_RET_STRUCT; - n_gpr++; /* We need one GPR to pass the pointer. */ - break; - - /* Floating point values are returned in fpr 0. */ - case FFI_TYPE_FLOAT: - cif->flags = FFI390_RET_FLOAT; - break; - - case FFI_TYPE_DOUBLE: - cif->flags = FFI390_RET_DOUBLE; - break; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - cif->flags = FFI390_RET_STRUCT; - n_gpr++; - break; -#endif - /* Integer values are returned in gpr 2 (and gpr 3 - for 64-bit values on 31-bit machines). */ - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - cif->flags = FFI390_RET_INT64; - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - /* These are to be extended to word size. */ -#ifdef __s390x__ - cif->flags = FFI390_RET_INT64; -#else - cif->flags = FFI390_RET_INT32; -#endif - break; - - default: - FFI_ASSERT (0); - break; - } - - /* Now for the arguments. */ - - for (ptr = cif->arg_types, i = cif->nargs; - i > 0; - i--, ptr++) - { - int type = (*ptr)->type; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - /* 16-byte long double is passed like a struct. */ - if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_STRUCT; -#endif - - /* Check how a structure type is passed. */ - if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX) - { - if (type == FFI_TYPE_COMPLEX) - type = FFI_TYPE_POINTER; - else - type = ffi_check_struct_type (*ptr); - - /* If we pass the struct via pointer, we must reserve space - to copy its data for proper call-by-value semantics. */ - if (type == FFI_TYPE_POINTER) - struct_size += ROUND_SIZE ((*ptr)->size); - } - - /* Now handle all primitive int/float data types. */ - switch (type) - { - /* The first MAX_FPRARGS floating point arguments - go in FPRs, the rest overflow to the stack. */ - - case FFI_TYPE_DOUBLE: - if (n_fpr < MAX_FPRARGS) - n_fpr++; - else - n_ov += sizeof (double) / sizeof (long); - break; - - case FFI_TYPE_FLOAT: - if (n_fpr < MAX_FPRARGS) - n_fpr++; - else - n_ov++; - break; - - /* On 31-bit machines, 64-bit integers are passed in GPR pairs, - if one is still available, or else on the stack. If only one - register is free, skip the register (it won't be used for any - subsequent argument either). */ - -#ifndef __s390x__ - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (n_gpr == MAX_GPRARGS-1) - n_gpr = MAX_GPRARGS; - if (n_gpr < MAX_GPRARGS) - n_gpr += 2; - else - n_ov += 2; - break; -#endif - - /* Everything else is passed in GPRs (until MAX_GPRARGS - have been used) or overflows to the stack. */ - - default: - if (n_gpr < MAX_GPRARGS) - n_gpr++; - else - n_ov++; - break; - } - } - - /* Total stack space as required for overflow arguments - and temporary structure copies. */ - - cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size; - - return FFI_OK; -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_call. */ -/* */ -/* Function - Call the FFI routine. */ -/* */ -/*====================================================================*/ - -void -ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue) -{ - int ret_type = cif->flags; - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; - - /* If we don't have a return value, we need to fake one. */ - if (rvalue == NULL) - { - if (ret_type == FFI390_RET_STRUCT) - ecif.rvalue = alloca (cif->rtype->size); - else - ret_type = FFI390_RET_VOID; - } - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, - ret_type, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; - } -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_closure_helper_SYSV. */ -/* */ -/* Function - Call a FFI closure target function. */ -/* */ -/*====================================================================*/ - -void -ffi_closure_helper_SYSV (ffi_closure *closure, - unsigned long *p_gpr, - unsigned long long *p_fpr, - unsigned long *p_ov) -{ - unsigned long long ret_buffer; - - void *rvalue = &ret_buffer; - void **avalue; - void **p_arg; - - int n_gpr = 0; - int n_fpr = 0; - int n_ov = 0; - - ffi_type **ptr; - int i; - - /* Allocate buffer for argument list pointers. */ - - p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); - - /* If we returning a structure, pass the structure address - directly to the target function. Otherwise, have the target - function store the return value to the GPR save area. */ - - if (closure->cif->flags == FFI390_RET_STRUCT) - rvalue = (void *) p_gpr[n_gpr++]; - - /* Now for the arguments. */ - - for (ptr = closure->cif->arg_types, i = closure->cif->nargs; - i > 0; - i--, p_arg++, ptr++) - { - int deref_struct_pointer = 0; - int type = (*ptr)->type; - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - /* 16-byte long double is passed like a struct. */ - if (type == FFI_TYPE_LONGDOUBLE) - type = FFI_TYPE_STRUCT; -#endif - - /* Check how a structure type is passed. */ - if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX) - { - if (type == FFI_TYPE_COMPLEX) - type = FFI_TYPE_POINTER; - else - type = ffi_check_struct_type (*ptr); - - /* If we pass the struct via pointer, remember to - retrieve the pointer later. */ - if (type == FFI_TYPE_POINTER) - deref_struct_pointer = 1; - } - - /* Pointers are passed like UINTs of the same size. */ - if (type == FFI_TYPE_POINTER) -#ifdef __s390x__ - type = FFI_TYPE_UINT64; -#else - type = FFI_TYPE_UINT32; -#endif - - /* Now handle all primitive int/float data types. */ - switch (type) - { - case FFI_TYPE_DOUBLE: - if (n_fpr < MAX_FPRARGS) - *p_arg = &p_fpr[n_fpr++]; - else - *p_arg = &p_ov[n_ov], - n_ov += sizeof (double) / sizeof (long); - break; - - case FFI_TYPE_FLOAT: - if (n_fpr < MAX_FPRARGS) - *p_arg = &p_fpr[n_fpr++]; - else - *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#ifdef __s390x__ - if (n_gpr < MAX_GPRARGS) - *p_arg = &p_gpr[n_gpr++]; - else - *p_arg = &p_ov[n_ov++]; -#else - if (n_gpr == MAX_GPRARGS-1) - n_gpr = MAX_GPRARGS; - if (n_gpr < MAX_GPRARGS) - *p_arg = &p_gpr[n_gpr], n_gpr += 2; - else - *p_arg = &p_ov[n_ov], n_ov += 2; -#endif - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - if (n_gpr < MAX_GPRARGS) - *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4; - else - *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - if (n_gpr < MAX_GPRARGS) - *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2; - else - *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2; - break; - - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - if (n_gpr < MAX_GPRARGS) - *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1; - else - *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; - break; - - default: - FFI_ASSERT (0); - break; - } - - /* If this is a struct passed via pointer, we need to - actually retrieve that pointer. */ - if (deref_struct_pointer) - *p_arg = *(void **)*p_arg; - } - - - /* Call the target function. */ - (closure->fun) (closure->cif, rvalue, avalue, closure->user_data); - - /* Convert the return value. */ - switch (closure->cif->rtype->type) - { - /* Void is easy, and so is struct. */ - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - case FFI_TYPE_COMPLEX: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - break; - - /* Floating point values are returned in fpr 0. */ - case FFI_TYPE_FLOAT: - p_fpr[0] = (long long) *(unsigned int *) rvalue << 32; - break; - - case FFI_TYPE_DOUBLE: - p_fpr[0] = *(unsigned long long *) rvalue; - break; - - /* Integer values are returned in gpr 2 (and gpr 3 - for 64-bit values on 31-bit machines). */ - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: -#ifdef __s390x__ - p_gpr[0] = *(unsigned long *) rvalue; -#else - p_gpr[0] = ((unsigned long *) rvalue)[0], - p_gpr[1] = ((unsigned long *) rvalue)[1]; -#endif - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT32: - case FFI_TYPE_UINT16: - case FFI_TYPE_UINT8: - p_gpr[0] = *(unsigned long *) rvalue; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - case FFI_TYPE_SINT16: - case FFI_TYPE_SINT8: - p_gpr[0] = *(signed long *) rvalue; - break; - - default: - FFI_ASSERT (0); - break; - } -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_prep_closure_loc. */ -/* */ -/* Function - Prepare a FFI closure. */ -/* */ -/*====================================================================*/ - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif *cif, - void (*fun) (ffi_cif *, void *, void **, void *), - void *user_data, - void *codeloc) -{ - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - -#ifndef __s390x__ - *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ - *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */ - *(short *)&closure->tramp [4] = 0x1006; - *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */ - *(long *)&closure->tramp [8] = (long)codeloc; - *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV; -#else - *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ - *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ - *(short *)&closure->tramp [4] = 0x100e; - *(short *)&closure->tramp [6] = 0x0004; - *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ - *(long *)&closure->tramp[16] = (long)codeloc; - *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; -#endif - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/*======================== End of Routine ============================*/ - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffitarget.h deleted file mode 100644 index 0e4868a1c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/s390/ffitarget.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for S390. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#if defined (__s390x__) -#ifndef S390X -#define S390X -#endif -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION -#define FFI_TARGET_HAS_COMPLEX_TYPE - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#ifdef S390X -#define FFI_TRAMPOLINE_SIZE 32 -#else -#define FFI_TRAMPOLINE_SIZE 16 -#endif -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/s390/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/s390/sysv.S deleted file mode 100644 index 4731a3177..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/s390/sysv.S +++ /dev/null @@ -1,434 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2000 Software AG - Copyright (c) 2008 Red Hat, Inc. - - S390 Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#ifndef __s390x__ - -.text - - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - - # This assumes we are using gas. - .globl ffi_call_SYSV - .type ffi_call_SYSV,%function -ffi_call_SYSV: -.LFB1: - stm %r6,%r15,24(%r15) # Save registers -.LCFI0: - basr %r13,0 # Set up base register -.Lbase: - lr %r11,%r15 # Set up frame pointer -.LCFI1: - sr %r15,%r2 - ahi %r15,-96-48 # Allocate stack - lr %r8,%r6 # Save ecif.rvalue - sr %r9,%r9 - ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - l %r7,96(%r11) # Load function address - st %r11,0(%r15) # Set up back chain - ahi %r11,-48 # Register save area -.LCFI2: - - la %r2,96(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - lm %r2,%r6,0(%r11) # Load arguments - ld %f0,32(%r11) - ld %f2,40(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.LretNone: # Return void - l %r4,48+56(%r11) - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretFloat: - l %r4,48+56(%r11) - ste %f0,0(%r8) # Return float - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretDouble: - l %r4,48+56(%r11) - std %f0,0(%r8) # Return double - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretInt32: - l %r4,48+56(%r11) - st %r2,0(%r8) # Return int - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretInt64: - l %r4,48+56(%r11) - stm %r2,%r3,0(%r8) # Return long long - lm %r6,%r15,48+24(%r11) - br %r4 - -.Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte .LretInt32-.Lbase # FFI390_RET_INT32 - .byte .LretInt64-.Lbase # FFI390_RET_INT64 - -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV - - - .globl ffi_closure_SYSV - .type ffi_closure_SYSV,%function -ffi_closure_SYSV: -.LFB2: - stm %r12,%r15,48(%r15) # Save registers -.LCFI10: - basr %r13,0 # Set up base register -.Lcbase: - stm %r2,%r6,8(%r15) # Save arguments - std %f0,64(%r15) - std %f2,72(%r15) - lr %r1,%r15 # Set up stack frame - ahi %r15,-96 -.LCFI11: - l %r12,.Lchelper-.Lcbase(%r13) # Get helper function - lr %r2,%r0 # Closure - la %r3,8(%r1) # GPRs - la %r4,64(%r1) # FPRs - la %r5,96(%r1) # Overflow - st %r1,0(%r15) # Set up back chain - - bas %r14,0(%r12,%r13) # Call helper - - l %r4,96+56(%r15) - ld %f0,96+64(%r15) # Load return registers - lm %r2,%r3,96+8(%r15) - lm %r12,%r15,96+48(%r15) - br %r4 - - .align 4 -.Lchelper: - .long ffi_closure_helper_SYSV-.Lcbase - -.LFE2: - -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -4 # CIE Data Alignment Factor - .byte 0xe # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0xf - .uleb128 0x60 - .align 4 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .4byte .LFB1-. # FDE initial location - .4byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x9 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0xa - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0xb - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0xc - .byte 0x8b # DW_CFA_offset, column 0xb - .uleb128 0xd - .byte 0x8a # DW_CFA_offset, column 0xa - .uleb128 0xe - .byte 0x89 # DW_CFA_offset, column 0x9 - .uleb128 0xf - .byte 0x88 # DW_CFA_offset, column 0x8 - .uleb128 0x10 - .byte 0x87 # DW_CFA_offset, column 0x7 - .uleb128 0x11 - .byte 0x86 # DW_CFA_offset, column 0x6 - .uleb128 0x12 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0xb - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI2-.LCFI1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x90 - .align 4 -.LEFDE1: -.LSFDE2: - .4byte .LEFDE2-.LASFDE2 # FDE Length -.LASFDE2: - .4byte .LASFDE2-.Lframe1 # FDE CIE offset - .4byte .LFB2-. # FDE initial location - .4byte .LFE2-.LFB2 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI10-.LFB2 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x9 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0xa - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0xb - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0xc - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI11-.LCFI10 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0xc0 - .align 4 -.LEFDE2: - -#else - -.text - - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - - # This assumes we are using gas. - .globl ffi_call_SYSV - .type ffi_call_SYSV,%function -ffi_call_SYSV: -.LFB1: - stmg %r6,%r15,48(%r15) # Save registers -.LCFI0: - larl %r13,.Lbase # Set up base register - lgr %r11,%r15 # Set up frame pointer -.LCFI1: - sgr %r15,%r2 - aghi %r15,-160-80 # Allocate stack - lgr %r8,%r6 # Save ecif.rvalue - llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - lg %r7,160(%r11) # Load function address - stg %r11,0(%r15) # Set up back chain - aghi %r11,-80 # Register save area -.LCFI2: - - la %r2,160(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - lmg %r2,%r6,0(%r11) # Load arguments - ld %f0,48(%r11) - ld %f2,56(%r11) - ld %f4,64(%r11) - ld %f6,72(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.Lbase: -.LretNone: # Return void - lg %r4,80+112(%r11) - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretFloat: - lg %r4,80+112(%r11) - ste %f0,0(%r8) # Return float - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretDouble: - lg %r4,80+112(%r11) - std %f0,0(%r8) # Return double - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretInt32: - lg %r4,80+112(%r11) - st %r2,0(%r8) # Return int - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretInt64: - lg %r4,80+112(%r11) - stg %r2,0(%r8) # Return long - lmg %r6,%r15,80+48(%r11) - br %r4 - -.Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte .LretInt32-.Lbase # FFI390_RET_INT32 - .byte .LretInt64-.Lbase # FFI390_RET_INT64 - -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV - - - .globl ffi_closure_SYSV - .type ffi_closure_SYSV,%function -ffi_closure_SYSV: -.LFB2: - stmg %r14,%r15,112(%r15) # Save registers -.LCFI10: - stmg %r2,%r6,16(%r15) # Save arguments - std %f0,128(%r15) - std %f2,136(%r15) - std %f4,144(%r15) - std %f6,152(%r15) - lgr %r1,%r15 # Set up stack frame - aghi %r15,-160 -.LCFI11: - lgr %r2,%r0 # Closure - la %r3,16(%r1) # GPRs - la %r4,128(%r1) # FPRs - la %r5,160(%r1) # Overflow - stg %r1,0(%r15) # Set up back chain - - brasl %r14,ffi_closure_helper_SYSV # Call helper - - lg %r14,160+112(%r15) - ld %f0,160+128(%r15) # Load return registers - lg %r2,160+16(%r15) - la %r15,160(%r15) - br %r14 -.LFE2: - -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0xe # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0xf - .uleb128 0xa0 - .align 8 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .4byte .LFB1-. # FDE initial location - .4byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x5 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0x6 - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0x7 - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0x8 - .byte 0x8b # DW_CFA_offset, column 0xb - .uleb128 0x9 - .byte 0x8a # DW_CFA_offset, column 0xa - .uleb128 0xa - .byte 0x89 # DW_CFA_offset, column 0x9 - .uleb128 0xb - .byte 0x88 # DW_CFA_offset, column 0x8 - .uleb128 0xc - .byte 0x87 # DW_CFA_offset, column 0x7 - .uleb128 0xd - .byte 0x86 # DW_CFA_offset, column 0x6 - .uleb128 0xe - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0xb - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI2-.LCFI1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0xf0 - .align 8 -.LEFDE1: -.LSFDE2: - .4byte .LEFDE2-.LASFDE2 # FDE Length -.LASFDE2: - .4byte .LASFDE2-.Lframe1 # FDE CIE offset - .4byte .LFB2-. # FDE initial location - .4byte .LFE2-.LFB2 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI10-.LFB2 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x5 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0x6 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI11-.LCFI10 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x140 - .align 8 -.LEFDE2: - -#endif - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffi.c deleted file mode 100644 index 9ec86bfb2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffi.c +++ /dev/null @@ -1,717 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima - Copyright (c) 2008 Red Hat, Inc. - - SuperH Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -#define NGREGARG 4 -#if defined(__SH4__) -#define NFREGARG 8 -#endif - -#if defined(__HITACHI__) -#define STRUCT_VALUE_ADDRESS_WITH_ARG 1 -#else -#define STRUCT_VALUE_ADDRESS_WITH_ARG 0 -#endif - -/* If the structure has essentially an unique element, return its type. */ -static int -simple_type (ffi_type *arg) -{ - if (arg->type != FFI_TYPE_STRUCT) - return arg->type; - else if (arg->elements[1]) - return FFI_TYPE_STRUCT; - - return simple_type (arg->elements[0]); -} - -static int -return_type (ffi_type *arg) -{ - unsigned short type; - - if (arg->type != FFI_TYPE_STRUCT) - return arg->type; - - type = simple_type (arg->elements[0]); - if (! arg->elements[1]) - { - switch (type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - return FFI_TYPE_INT; - - default: - return type; - } - } - - /* gcc uses r0/r1 pair for some kind of structures. */ - if (arg->size <= 2 * sizeof (int)) - { - int i = 0; - ffi_type *e; - - while ((e = arg->elements[i++])) - { - type = simple_type (e); - switch (type) - { - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_INT: - case FFI_TYPE_FLOAT: - return FFI_TYPE_UINT64; - - default: - break; - } - } - } - - return FFI_TYPE_STRUCT; -} - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register int tmp; - register unsigned int avn; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - int greg, ireg; -#if defined(__SH4__) - int freg = 0; -#endif - - tmp = 0; - argp = stack; - - if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) - { - *(void **) argp = ecif->rvalue; - argp += 4; - ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; - } - else - ireg = 0; - - /* Set arguments for registers. */ - greg = ireg; - avn = ecif->cif->nargs; - p_argv = ecif->avalue; - - for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) - { - size_t z; - - z = (*p_arg)->size; - if (z < sizeof(int)) - { - if (greg++ >= NGREGARG) - continue; - - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - argp += z; - } - else if (z == sizeof(int)) - { -#if defined(__SH4__) - if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (freg++ >= NFREGARG) - continue; - } - else -#endif - { - if (greg++ >= NGREGARG) - continue; - } - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - argp += z; - } -#if defined(__SH4__) - else if ((*p_arg)->type == FFI_TYPE_DOUBLE) - { - if (freg + 1 >= NFREGARG) - continue; - freg = (freg + 1) & ~1; - freg += 2; - memcpy (argp, *p_argv, z); - argp += z; - } -#endif - else - { - int n = (z + sizeof (int) - 1) / sizeof (int); -#if defined(__SH4__) - if (greg + n - 1 >= NGREGARG) - continue; -#else - if (greg >= NGREGARG) - continue; -#endif - greg += n; - memcpy (argp, *p_argv, z); - argp += n * sizeof (int); - } - } - - /* Set arguments on stack. */ - greg = ireg; -#if defined(__SH4__) - freg = 0; -#endif - p_argv = ecif->avalue; - - for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) - { - size_t z; - - z = (*p_arg)->size; - if (z < sizeof(int)) - { - if (greg++ < NGREGARG) - continue; - - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - argp += z; - } - else if (z == sizeof(int)) - { -#if defined(__SH4__) - if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (freg++ < NFREGARG) - continue; - } - else -#endif - { - if (greg++ < NGREGARG) - continue; - } - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - argp += z; - } -#if defined(__SH4__) - else if ((*p_arg)->type == FFI_TYPE_DOUBLE) - { - if (freg + 1 < NFREGARG) - { - freg = (freg + 1) & ~1; - freg += 2; - continue; - } - memcpy (argp, *p_argv, z); - argp += z; - } -#endif - else - { - int n = (z + sizeof (int) - 1) / sizeof (int); - if (greg + n - 1 < NGREGARG) - { - greg += n; - continue; - } -#if (! defined(__SH4__)) - else if (greg < NGREGARG) - { - greg = NGREGARG; - continue; - } -#endif - memcpy (argp, *p_argv, z); - argp += n * sizeof (int); - } - } - - return; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - int i, j; - int size, type; - int n, m; - int greg; -#if defined(__SH4__) - int freg = 0; -#endif - - cif->flags = 0; - - greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) && - STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0; - -#if defined(__SH4__) - for (i = j = 0; i < cif->nargs && j < 12; i++) - { - type = (cif->arg_types)[i]->type; - switch (type) - { - case FFI_TYPE_FLOAT: - if (freg >= NFREGARG) - continue; - freg++; - cif->flags += ((cif->arg_types)[i]->type) << (2 * j); - j++; - break; - - case FFI_TYPE_DOUBLE: - if ((freg + 1) >= NFREGARG) - continue; - freg = (freg + 1) & ~1; - freg += 2; - cif->flags += ((cif->arg_types)[i]->type) << (2 * j); - j++; - break; - - default: - size = (cif->arg_types)[i]->size; - n = (size + sizeof (int) - 1) / sizeof (int); - if (greg + n - 1 >= NGREGARG) - continue; - greg += n; - for (m = 0; m < n; m++) - cif->flags += FFI_TYPE_INT << (2 * j++); - break; - } - } -#else - for (i = j = 0; i < cif->nargs && j < 4; i++) - { - size = (cif->arg_types)[i]->size; - n = (size + sizeof (int) - 1) / sizeof (int); - if (greg >= NGREGARG) - continue; - else if (greg + n - 1 >= NGREGARG) - n = NGREGARG - greg; - greg += n; - for (m = 0; m < n; m++) - cif->flags += FFI_TYPE_INT << (2 * j++); - } -#endif - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_STRUCT: - cif->flags += (unsigned) (return_type (cif->rtype)) << 24; - break; - - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags += (unsigned) cif->rtype->type << 24; - break; - - default: - cif->flags += FFI_TYPE_INT << 24; - break; - } - - return FFI_OK; -} - -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - UINT64 trvalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (cif->rtype->type == FFI_TYPE_STRUCT - && return_type (cif->rtype) != FFI_TYPE_STRUCT) - ecif.rvalue = &trvalue; - else if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; - default: - FFI_ASSERT(0); - break; - } - - if (rvalue - && cif->rtype->type == FFI_TYPE_STRUCT - && return_type (cif->rtype) != FFI_TYPE_STRUCT) - memcpy (rvalue, &trvalue, cif->rtype->size); -} - -extern void ffi_closure_SYSV (void); -#if defined(__SH4__) -extern void __ic_invalidate (void *line); -#endif - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp; - unsigned int insn; - - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - tramp = (unsigned int *) &closure->tramp[0]; - /* Set T bit if the function returns a struct pointed with R2. */ - insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT - ? 0x0018 /* sett */ - : 0x0008 /* clrt */); - -#ifdef __LITTLE_ENDIAN__ - tramp[0] = 0xd301d102; - tramp[1] = 0x0000412b | (insn << 16); -#else - tramp[0] = 0xd102d301; - tramp[1] = 0x412b0000 | insn; -#endif - *(void **) &tramp[2] = (void *)codeloc; /* ctx */ - *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - -#if defined(__SH4__) - /* Flush the icache. */ - __ic_invalidate(codeloc); -#endif - - return FFI_OK; -} - -/* Basically the trampoline invokes ffi_closure_SYSV, and on - * entry, r3 holds the address of the closure. - * After storing the registers that could possibly contain - * parameters to be passed into the stack frame and setting - * up space for a return value, ffi_closure_SYSV invokes the - * following helper function to do most of the work. - */ - -#ifdef __LITTLE_ENDIAN__ -#define OFS_INT8 0 -#define OFS_INT16 0 -#else -#define OFS_INT8 3 -#define OFS_INT16 2 -#endif - -int -ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, - unsigned long *pgr, unsigned long *pfr, - unsigned long *pst) -{ - void **avalue; - ffi_type **p_arg; - int i, avn; - int ireg, greg = 0; -#if defined(__SH4__) - int freg = 0; -#endif - ffi_cif *cif; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ - if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG) - { - rvalue = (void *) *pgr++; - ireg = 1; - } - else - ireg = 0; - - cif = closure->cif; - greg = ireg; - avn = cif->nargs; - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - if (z < sizeof(int)) - { - if (greg++ >= NGREGARG) - continue; - - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (((char *)pgr) + OFS_INT8); - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (((char *)pgr) + OFS_INT16); - break; - - case FFI_TYPE_STRUCT: - avalue[i] = pgr; - break; - - default: - FFI_ASSERT(0); - } - pgr++; - } - else if (z == sizeof(int)) - { -#if defined(__SH4__) - if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (freg++ >= NFREGARG) - continue; - avalue[i] = pfr; - pfr++; - } - else -#endif - { - if (greg++ >= NGREGARG) - continue; - avalue[i] = pgr; - pgr++; - } - } -#if defined(__SH4__) - else if ((*p_arg)->type == FFI_TYPE_DOUBLE) - { - if (freg + 1 >= NFREGARG) - continue; - if (freg & 1) - pfr++; - freg = (freg + 1) & ~1; - freg += 2; - avalue[i] = pfr; - pfr += 2; - } -#endif - else - { - int n = (z + sizeof (int) - 1) / sizeof (int); -#if defined(__SH4__) - if (greg + n - 1 >= NGREGARG) - continue; -#else - if (greg >= NGREGARG) - continue; -#endif - greg += n; - avalue[i] = pgr; - pgr += n; - } - } - - greg = ireg; -#if defined(__SH4__) - freg = 0; -#endif - - for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - if (z < sizeof(int)) - { - if (greg++ < NGREGARG) - continue; - - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (((char *)pst) + OFS_INT8); - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (((char *)pst) + OFS_INT16); - break; - - case FFI_TYPE_STRUCT: - avalue[i] = pst; - break; - - default: - FFI_ASSERT(0); - } - pst++; - } - else if (z == sizeof(int)) - { -#if defined(__SH4__) - if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (freg++ < NFREGARG) - continue; - } - else -#endif - { - if (greg++ < NGREGARG) - continue; - } - avalue[i] = pst; - pst++; - } -#if defined(__SH4__) - else if ((*p_arg)->type == FFI_TYPE_DOUBLE) - { - if (freg + 1 < NFREGARG) - { - freg = (freg + 1) & ~1; - freg += 2; - continue; - } - avalue[i] = pst; - pst += 2; - } -#endif - else - { - int n = (z + sizeof (int) - 1) / sizeof (int); - if (greg + n - 1 < NGREGARG) - { - greg += n; - continue; - } -#if (! defined(__SH4__)) - else if (greg < NGREGARG) - { - greg += n; - pst += greg - NGREGARG; - continue; - } -#endif - avalue[i] = pst; - pst += n; - } - } - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_SYSV how to perform return type promotions. */ - return return_type (cif->rtype); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffitarget.h deleted file mode 100644 index a36bf4207..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh/ffitarget.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for SuperH. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 16 -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/sh/sysv.S deleted file mode 100644 index 5be7516d6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh/sysv.S +++ /dev/null @@ -1,850 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2002, 2003, 2004, 2006, 2008 Kaz Kojima - - SuperH Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -/* XXX these lose for some platforms, I'm sure. */ -#define CNAME(x) x -#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): -#endif - -#if defined(__HITACHI__) -#define STRUCT_VALUE_ADDRESS_WITH_ARG 1 -#else -#define STRUCT_VALUE_ADDRESS_WITH_ARG 0 -#endif - -.text - - # r4: ffi_prep_args - # r5: &ecif - # r6: bytes - # r7: flags - # sp+0: rvalue - # sp+4: fn - - # This assumes we are using gas. -ENTRY(ffi_call_SYSV) - # Save registers -.LFB1: - mov.l r8,@-r15 -.LCFI0: - mov.l r9,@-r15 -.LCFI1: - mov.l r10,@-r15 -.LCFI2: - mov.l r12,@-r15 -.LCFI3: - mov.l r14,@-r15 -.LCFI4: - sts.l pr,@-r15 -.LCFI5: - mov r15,r14 -.LCFI6: -#if defined(__SH4__) - mov r6,r8 - mov r7,r9 - - sub r6,r15 - add #-16,r15 - mov #~7,r0 - and r0,r15 - - mov r4,r0 - jsr @r0 - mov r15,r4 - - mov r9,r1 - shlr8 r9 - shlr8 r9 - shlr8 r9 - - mov #FFI_TYPE_STRUCT,r2 - cmp/eq r2,r9 - bf 1f -#if STRUCT_VALUE_ADDRESS_WITH_ARG - mov.l @r15+,r4 - bra 2f - mov #5,r2 -#else - mov.l @r15+,r10 -#endif -1: - mov #4,r2 -2: - mov #4,r3 - -L_pass: - cmp/pl r8 - bf L_call_it - - mov r1,r0 - and #3,r0 - -L_pass_d: - cmp/eq #FFI_TYPE_DOUBLE,r0 - bf L_pass_f - - mov r3,r0 - and #1,r0 - tst r0,r0 - bt 1f - add #1,r3 -1: - mov #12,r0 - cmp/hs r0,r3 - bt/s 3f - shlr2 r1 - bsr L_pop_d - nop -3: - add #2,r3 - bra L_pass - add #-8,r8 - -L_pop_d: - mov r3,r0 - add r0,r0 - add r3,r0 - add #-12,r0 - braf r0 - nop -#ifdef __LITTLE_ENDIAN__ - fmov.s @r15+,fr5 - rts - fmov.s @r15+,fr4 - fmov.s @r15+,fr7 - rts - fmov.s @r15+,fr6 - fmov.s @r15+,fr9 - rts - fmov.s @r15+,fr8 - fmov.s @r15+,fr11 - rts - fmov.s @r15+,fr10 -#else - fmov.s @r15+,fr4 - rts - fmov.s @r15+,fr5 - fmov.s @r15+,fr6 - rts - fmov.s @r15+,fr7 - fmov.s @r15+,fr8 - rts - fmov.s @r15+,fr9 - fmov.s @r15+,fr10 - rts - fmov.s @r15+,fr11 -#endif - -L_pass_f: - cmp/eq #FFI_TYPE_FLOAT,r0 - bf L_pass_i - - mov #12,r0 - cmp/hs r0,r3 - bt/s 2f - shlr2 r1 - bsr L_pop_f - nop -2: - add #1,r3 - bra L_pass - add #-4,r8 - -L_pop_f: - mov r3,r0 - shll2 r0 - add #-16,r0 - braf r0 - nop -#ifdef __LITTLE_ENDIAN__ - rts - fmov.s @r15+,fr5 - rts - fmov.s @r15+,fr4 - rts - fmov.s @r15+,fr7 - rts - fmov.s @r15+,fr6 - rts - fmov.s @r15+,fr9 - rts - fmov.s @r15+,fr8 - rts - fmov.s @r15+,fr11 - rts - fmov.s @r15+,fr10 -#else - rts - fmov.s @r15+,fr4 - rts - fmov.s @r15+,fr5 - rts - fmov.s @r15+,fr6 - rts - fmov.s @r15+,fr7 - rts - fmov.s @r15+,fr8 - rts - fmov.s @r15+,fr9 - rts - fmov.s @r15+,fr10 - rts - fmov.s @r15+,fr11 -#endif - -L_pass_i: - cmp/eq #FFI_TYPE_INT,r0 - bf L_call_it - - mov #8,r0 - cmp/hs r0,r2 - bt/s 2f - shlr2 r1 - bsr L_pop_i - nop -2: - add #1,r2 - bra L_pass - add #-4,r8 - -L_pop_i: - mov r2,r0 - shll2 r0 - add #-16,r0 - braf r0 - nop - rts - mov.l @r15+,r4 - rts - mov.l @r15+,r5 - rts - mov.l @r15+,r6 - rts - mov.l @r15+,r7 - -L_call_it: - # call function -#if (! STRUCT_VALUE_ADDRESS_WITH_ARG) - mov r10, r2 -#endif - mov.l @(28,r14),r1 - jsr @r1 - nop - -L_ret_d: - mov #FFI_TYPE_DOUBLE,r2 - cmp/eq r2,r9 - bf L_ret_ll - - mov.l @(24,r14),r1 -#ifdef __LITTLE_ENDIAN__ - fmov.s fr1,@r1 - add #4,r1 - bra L_epilogue - fmov.s fr0,@r1 -#else - fmov.s fr0,@r1 - add #4,r1 - bra L_epilogue - fmov.s fr1,@r1 -#endif - -L_ret_ll: - mov #FFI_TYPE_SINT64,r2 - cmp/eq r2,r9 - bt/s 1f - mov #FFI_TYPE_UINT64,r2 - cmp/eq r2,r9 - bf L_ret_f - -1: - mov.l @(24,r14),r2 - mov.l r0,@r2 - bra L_epilogue - mov.l r1,@(4,r2) - -L_ret_f: - mov #FFI_TYPE_FLOAT,r2 - cmp/eq r2,r9 - bf L_ret_i - - mov.l @(24,r14),r1 - bra L_epilogue - fmov.s fr0,@r1 - -L_ret_i: - mov #FFI_TYPE_INT,r2 - cmp/eq r2,r9 - bf L_epilogue - - mov.l @(24,r14),r1 - bra L_epilogue - mov.l r0,@r1 - -L_epilogue: - # Remove the space we pushed for the args - mov r14,r15 - - lds.l @r15+,pr - mov.l @r15+,r14 - mov.l @r15+,r12 - mov.l @r15+,r10 - mov.l @r15+,r9 - rts - mov.l @r15+,r8 -#else - mov r6,r8 - mov r7,r9 - - sub r6,r15 - add #-16,r15 - mov #~7,r0 - and r0,r15 - - mov r4,r0 - jsr @r0 - mov r15,r4 - - mov r9,r3 - shlr8 r9 - shlr8 r9 - shlr8 r9 - - mov #FFI_TYPE_STRUCT,r2 - cmp/eq r2,r9 - bf 1f -#if STRUCT_VALUE_ADDRESS_WITH_ARG - mov.l @r15+,r4 - bra 2f - mov #5,r2 -#else - mov.l @r15+,r10 -#endif -1: - mov #4,r2 -2: - -L_pass: - cmp/pl r8 - bf L_call_it - - mov r3,r0 - and #3,r0 - -L_pass_d: - cmp/eq #FFI_TYPE_DOUBLE,r0 - bf L_pass_i - - mov r15,r0 - and #7,r0 - tst r0,r0 - bt 1f - add #4,r15 -1: - mov #8,r0 - cmp/hs r0,r2 - bt/s 2f - shlr2 r3 - bsr L_pop_d - nop -2: - add #2,r2 - bra L_pass - add #-8,r8 - -L_pop_d: - mov r2,r0 - add r0,r0 - add r2,r0 - add #-12,r0 - add r0,r0 - braf r0 - nop - mov.l @r15+,r4 - rts - mov.l @r15+,r5 - mov.l @r15+,r5 - rts - mov.l @r15+,r6 - mov.l @r15+,r6 - rts - mov.l @r15+,r7 - rts - mov.l @r15+,r7 - -L_pass_i: - cmp/eq #FFI_TYPE_INT,r0 - bf L_call_it - - mov #8,r0 - cmp/hs r0,r2 - bt/s 2f - shlr2 r3 - bsr L_pop_i - nop -2: - add #1,r2 - bra L_pass - add #-4,r8 - -L_pop_i: - mov r2,r0 - shll2 r0 - add #-16,r0 - braf r0 - nop - rts - mov.l @r15+,r4 - rts - mov.l @r15+,r5 - rts - mov.l @r15+,r6 - rts - mov.l @r15+,r7 - -L_call_it: - # call function -#if (! STRUCT_VALUE_ADDRESS_WITH_ARG) - mov r10, r2 -#endif - mov.l @(28,r14),r1 - jsr @r1 - nop - -L_ret_d: - mov #FFI_TYPE_DOUBLE,r2 - cmp/eq r2,r9 - bf L_ret_ll - - mov.l @(24,r14),r2 - mov.l r0,@r2 - bra L_epilogue - mov.l r1,@(4,r2) - -L_ret_ll: - mov #FFI_TYPE_SINT64,r2 - cmp/eq r2,r9 - bt/s 1f - mov #FFI_TYPE_UINT64,r2 - cmp/eq r2,r9 - bf L_ret_i - -1: - mov.l @(24,r14),r2 - mov.l r0,@r2 - bra L_epilogue - mov.l r1,@(4,r2) - -L_ret_i: - mov #FFI_TYPE_FLOAT,r2 - cmp/eq r2,r9 - bt 1f - mov #FFI_TYPE_INT,r2 - cmp/eq r2,r9 - bf L_epilogue -1: - mov.l @(24,r14),r1 - bra L_epilogue - mov.l r0,@r1 - -L_epilogue: - # Remove the space we pushed for the args - mov r14,r15 - - lds.l @r15+,pr - mov.l @r15+,r14 - mov.l @r15+,r12 - mov.l @r15+,r10 - mov.l @r15+,r9 - rts - mov.l @r15+,r8 -#endif -.LFE1: -.ffi_call_SYSV_end: - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) - -.globl ffi_closure_helper_SYSV - -ENTRY(ffi_closure_SYSV) -.LFB2: - mov.l r7,@-r15 -.LCFI7: - mov.l r6,@-r15 -.LCFI8: - mov.l r5,@-r15 -.LCFI9: - mov.l r4,@-r15 -.LCFIA: - mov.l r14,@-r15 -.LCFIB: - sts.l pr,@-r15 - - /* Stack layout: - xx bytes (on stack parameters) - 16 bytes (register parameters) - 4 bytes (saved frame pointer) - 4 bytes (saved return address) - 32 bytes (floating register parameters, SH-4 only) - 8 bytes (result) - 4 bytes (pad) - 4 bytes (5th arg) - <- new stack pointer - */ -.LCFIC: -#if defined(__SH4__) - add #-48,r15 -#else - add #-16,r15 -#endif -.LCFID: - mov r15,r14 -.LCFIE: - -#if defined(__SH4__) - mov r14,r1 - add #48,r1 -#ifdef __LITTLE_ENDIAN__ - fmov.s fr10,@-r1 - fmov.s fr11,@-r1 - fmov.s fr8,@-r1 - fmov.s fr9,@-r1 - fmov.s fr6,@-r1 - fmov.s fr7,@-r1 - fmov.s fr4,@-r1 - fmov.s fr5,@-r1 -#else - fmov.s fr11,@-r1 - fmov.s fr10,@-r1 - fmov.s fr9,@-r1 - fmov.s fr8,@-r1 - fmov.s fr7,@-r1 - fmov.s fr6,@-r1 - fmov.s fr5,@-r1 - fmov.s fr4,@-r1 -#endif - mov r1,r7 - mov r14,r6 - add #56,r6 -#else - mov r14,r6 - add #24,r6 -#endif - - bt/s 10f - mov r2, r5 - mov r14,r1 - add #8,r1 - mov r1,r5 -10: - - mov r14,r1 -#if defined(__SH4__) - add #72,r1 -#else - add #40,r1 -#endif - mov.l r1,@r14 - -#ifdef PIC - mov.l L_got,r1 - mova L_got,r0 - add r0,r1 - mov.l L_helper,r0 - add r1,r0 -#else - mov.l L_helper,r0 -#endif - jsr @r0 - mov r3,r4 - - shll r0 - mov r0,r1 - mova L_table,r0 - add r1,r0 - mov.w @r0,r0 - mov r14,r2 - braf r0 - add #8,r2 -0: - .align 2 -#ifdef PIC -L_got: - .long _GLOBAL_OFFSET_TABLE_ -L_helper: - .long ffi_closure_helper_SYSV@GOTOFF -#else -L_helper: - .long ffi_closure_helper_SYSV -#endif -L_table: - .short L_case_v - 0b /* FFI_TYPE_VOID */ - .short L_case_i - 0b /* FFI_TYPE_INT */ -#if defined(__SH4__) - .short L_case_f - 0b /* FFI_TYPE_FLOAT */ - .short L_case_d - 0b /* FFI_TYPE_DOUBLE */ - .short L_case_d - 0b /* FFI_TYPE_LONGDOUBLE */ -#else - .short L_case_i - 0b /* FFI_TYPE_FLOAT */ - .short L_case_ll - 0b /* FFI_TYPE_DOUBLE */ - .short L_case_ll - 0b /* FFI_TYPE_LONGDOUBLE */ -#endif - .short L_case_uq - 0b /* FFI_TYPE_UINT8 */ - .short L_case_q - 0b /* FFI_TYPE_SINT8 */ - .short L_case_uh - 0b /* FFI_TYPE_UINT16 */ - .short L_case_h - 0b /* FFI_TYPE_SINT16 */ - .short L_case_i - 0b /* FFI_TYPE_UINT32 */ - .short L_case_i - 0b /* FFI_TYPE_SINT32 */ - .short L_case_ll - 0b /* FFI_TYPE_UINT64 */ - .short L_case_ll - 0b /* FFI_TYPE_SINT64 */ - .short L_case_v - 0b /* FFI_TYPE_STRUCT */ - .short L_case_i - 0b /* FFI_TYPE_POINTER */ - -#if defined(__SH4__) -L_case_d: -#ifdef __LITTLE_ENDIAN__ - fmov.s @r2+,fr1 - bra L_case_v - fmov.s @r2,fr0 -#else - fmov.s @r2+,fr0 - bra L_case_v - fmov.s @r2,fr1 -#endif - -L_case_f: - bra L_case_v - fmov.s @r2,fr0 -#endif - -L_case_ll: - mov.l @r2+,r0 - bra L_case_v - mov.l @r2,r1 - -L_case_i: - bra L_case_v - mov.l @r2,r0 - -L_case_q: -#ifdef __LITTLE_ENDIAN__ -#else - add #3,r2 -#endif - bra L_case_v - mov.b @r2,r0 - -L_case_uq: -#ifdef __LITTLE_ENDIAN__ -#else - add #3,r2 -#endif - mov.b @r2,r0 - bra L_case_v - extu.b r0,r0 - -L_case_h: -#ifdef __LITTLE_ENDIAN__ -#else - add #2,r2 -#endif - bra L_case_v - mov.w @r2,r0 - -L_case_uh: -#ifdef __LITTLE_ENDIAN__ -#else - add #2,r2 -#endif - mov.w @r2,r0 - extu.w r0,r0 - /* fall through */ - -L_case_v: -#if defined(__SH4__) - add #48,r15 -#else - add #16,r15 -#endif - lds.l @r15+,pr - mov.l @r15+,r14 - rts - add #16,r15 -.LFE2: -.ffi_closure_SYSV_end: - .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif - - .section ".eh_frame","aw",@progbits -__FRAME_BEGIN__: - .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .4byte 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef PIC - .ascii "zR\0" /* CIE Augmentation */ -#else - .byte 0x0 /* CIE Augmentation */ -#endif - .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* sleb128 -4; CIE Data Alignment Factor */ - .byte 0x11 /* CIE RA Column */ -#ifdef PIC - .uleb128 0x1 /* Augmentation size */ - .byte 0x10 /* FDE Encoding (pcrel) */ -#endif - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0xf /* uleb128 0xf */ - .byte 0x0 /* uleb128 0x0 */ - .align 2 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .4byte .LASFDE1-__FRAME_BEGIN__ /* FDE CIE offset */ -#ifdef PIC - .4byte .LFB1-. /* FDE initial location */ -#else - .4byte .LFB1 /* FDE initial location */ -#endif - .4byte .LFE1-.LFB1 /* FDE address range */ -#ifdef PIC - .uleb128 0x0 /* Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x4 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI1-.LCFI0 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI2-.LCFI1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0xc /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI3-.LCFI2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x10 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI4-.LCFI3 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x14 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI5-.LCFI4 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x18 /* uleb128 0x4 */ - .byte 0x91 /* DW_CFA_offset, column 0x11 */ - .byte 0x6 /* uleb128 0x6 */ - .byte 0x8e /* DW_CFA_offset, column 0xe */ - .byte 0x5 /* uleb128 0x5 */ - .byte 0x8c /* DW_CFA_offset, column 0xc */ - .byte 0x4 /* uleb128 0x4 */ - .byte 0x8a /* DW_CFA_offset, column 0xa */ - .byte 0x3 /* uleb128 0x3 */ - .byte 0x89 /* DW_CFA_offset, column 0x9 */ - .byte 0x2 /* uleb128 0x2 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .byte 0x1 /* uleb128 0x1 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI6-.LCFI5 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0xe /* uleb128 0xe */ - .align 2 -.LEFDE1: - -.LSFDE3: - .4byte .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .4byte .LASFDE3-__FRAME_BEGIN__ /* FDE CIE offset */ -#ifdef PIC - .4byte .LFB2-. /* FDE initial location */ -#else - .4byte .LFB2 /* FDE initial location */ -#endif - .4byte .LFE2-.LFB2 /* FDE address range */ -#ifdef PIC - .uleb128 0x0 /* Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI7-.LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x4 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI8-.LCFI7 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFI9-.LCFI8 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0xc /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFIA-.LCFI9 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x10 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFIB-.LCFIA - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x14 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFIC-.LCFIB - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x18 /* uleb128 0x4 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFID-.LCFIC - .byte 0xe /* DW_CFA_def_cfa_offset */ -#if defined(__SH4__) - .byte 24+48 /* uleb128 24+48 */ -#else - .byte 24+16 /* uleb128 24+16 */ -#endif - .byte 0x91 /* DW_CFA_offset, column 0x11 */ - .byte 0x6 /* uleb128 0x6 */ - .byte 0x8e /* DW_CFA_offset, column 0xe */ - .byte 0x5 /* uleb128 0x5 */ - .byte 0x84 /* DW_CFA_offset, column 0x4 */ - .byte 0x4 /* uleb128 0x4 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x3 /* uleb128 0x3 */ - .byte 0x86 /* DW_CFA_offset, column 0x6 */ - .byte 0x2 /* uleb128 0x2 */ - .byte 0x87 /* DW_CFA_offset, column 0x7 */ - .byte 0x1 /* uleb128 0x1 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte .LCFIE-.LCFID - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0xe /* uleb128 0xe */ - .align 2 -.LEFDE3: diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffi.c deleted file mode 100644 index 123b87ace..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffi.c +++ /dev/null @@ -1,469 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2003, 2004, 2006, 2007, 2012 Kaz Kojima - Copyright (c) 2008 Anthony Green - - SuperH SHmedia Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - -#define NGREGARG 8 -#define NFREGARG 12 - -static int -return_type (ffi_type *arg) -{ - - if (arg->type != FFI_TYPE_STRUCT) - return arg->type; - - /* gcc uses r2 if the result can be packed in on register. */ - if (arg->size <= sizeof (UINT8)) - return FFI_TYPE_UINT8; - else if (arg->size <= sizeof (UINT16)) - return FFI_TYPE_UINT16; - else if (arg->size <= sizeof (UINT32)) - return FFI_TYPE_UINT32; - else if (arg->size <= sizeof (UINT64)) - return FFI_TYPE_UINT64; - - return FFI_TYPE_STRUCT; -} - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register unsigned int avn; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - - if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) - { - *(void **) argp = ecif->rvalue; - argp += sizeof (UINT64); - } - - avn = ecif->cif->nargs; - p_argv = ecif->avalue; - - for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) - { - size_t z; - int align; - - z = (*p_arg)->size; - align = (*p_arg)->alignment; - if (z < sizeof (UINT32)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv); - break; - - case FFI_TYPE_UINT8: - *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv); - break; - - case FFI_TYPE_SINT16: - *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv); - break; - - case FFI_TYPE_UINT16: - *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv); - break; - - case FFI_TYPE_STRUCT: - memcpy (argp, *p_argv, z); - break; - - default: - FFI_ASSERT(0); - } - argp += sizeof (UINT64); - } - else if (z == sizeof (UINT32) && align == sizeof (UINT32)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_INT: - case FFI_TYPE_SINT32: - *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv); - break; - - case FFI_TYPE_FLOAT: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT32: - case FFI_TYPE_STRUCT: - *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv); - break; - - default: - FFI_ASSERT(0); - break; - } - argp += sizeof (UINT64); - } - else if (z == sizeof (UINT64) - && align == sizeof (UINT64) - && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0) - { - *(UINT64 *) argp = *(UINT64 *) (*p_argv); - argp += sizeof (UINT64); - } - else - { - int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); - - memcpy (argp, *p_argv, z); - argp += n * sizeof (UINT64); - } - } - - return; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - int i, j; - int size, type; - int n, m; - int greg; - int freg; - int fpair = -1; - - greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0); - freg = 0; - cif->flags2 = 0; - - for (i = j = 0; i < cif->nargs; i++) - { - type = (cif->arg_types)[i]->type; - switch (type) - { - case FFI_TYPE_FLOAT: - greg++; - cif->bytes += sizeof (UINT64) - sizeof (float); - if (freg >= NFREGARG - 1) - continue; - if (fpair < 0) - { - fpair = freg; - freg += 2; - } - else - fpair = -1; - cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); - break; - - case FFI_TYPE_DOUBLE: - if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG) - continue; - if ((freg + 1) < NFREGARG) - { - freg += 2; - cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); - } - else - cif->flags2 += FFI_TYPE_INT << (2 * j++); - break; - - default: - size = (cif->arg_types)[i]->size; - if (size < sizeof (UINT64)) - cif->bytes += sizeof (UINT64) - size; - n = (size + sizeof (UINT64) - 1) / sizeof (UINT64); - if (greg >= NGREGARG) - continue; - else if (greg + n - 1 >= NGREGARG) - greg = NGREGARG; - else - greg += n; - for (m = 0; m < n; m++) - cif->flags2 += FFI_TYPE_INT << (2 * j++); - break; - } - } - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_STRUCT: - cif->flags = return_type (cif->rtype); - break; - - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags = cif->rtype->type; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - -/*@-declundef@*/ -/*@-exportheader@*/ -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), - /*@out@*/ extended_cif *, - unsigned, unsigned, long long, - /*@out@*/ unsigned *, - void (*fn)(void)); -/*@=declundef@*/ -/*@=exportheader@*/ - -void ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(void), - /*@out@*/ void *rvalue, - /*@dependent@*/ void **avalue) -{ - extended_cif ecif; - UINT64 trvalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (cif->rtype->type == FFI_TYPE_STRUCT - && return_type (cif->rtype) != FFI_TYPE_STRUCT) - ecif.rvalue = &trvalue; - else if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2, - ecif.rvalue, fn); - break; - default: - FFI_ASSERT(0); - break; - } - - if (rvalue - && cif->rtype->type == FFI_TYPE_STRUCT - && return_type (cif->rtype) != FFI_TYPE_STRUCT) - memcpy (rvalue, &trvalue, cif->rtype->size); -} - -extern void ffi_closure_SYSV (void); -extern void __ic_invalidate (void *line); - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif *cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp; - - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - tramp = (unsigned int *) &closure->tramp[0]; - /* Since ffi_closure is an aligned object, the ffi trampoline is - called as an SHcompact code. Sigh. - SHcompact part: - mova @(1,pc),r0; add #1,r0; jmp @r0; nop; - SHmedia part: - movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0 - movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63 */ -#ifdef __LITTLE_ENDIAN__ - tramp[0] = 0x7001c701; - tramp[1] = 0x0009402b; -#else - tramp[0] = 0xc7017001; - tramp[1] = 0x402b0009; -#endif - tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10; - tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10; - tramp[4] = 0x6bf10600; - tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10; - tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10; - tramp[7] = 0x4401fff0; - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Flush the icache. */ - asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp), - "r"(codeloc)); - - return FFI_OK; -} - -/* Basically the trampoline invokes ffi_closure_SYSV, and on - * entry, r3 holds the address of the closure. - * After storing the registers that could possibly contain - * parameters to be passed into the stack frame and setting - * up space for a return value, ffi_closure_SYSV invokes the - * following helper function to do most of the work. - */ - -int -ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, - UINT64 *pgr, UINT64 *pfr, UINT64 *pst) -{ - void **avalue; - ffi_type **p_arg; - int i, avn; - int greg, freg; - ffi_cif *cif; - int fpair = -1; - - cif = closure->cif; - avalue = alloca (cif->nargs * sizeof (void *)); - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ - if (return_type (cif->rtype) == FFI_TYPE_STRUCT) - { - rvalue = (UINT64 *) *pgr; - greg = 1; - } - else - greg = 0; - - freg = 0; - cif = closure->cif; - avn = cif->nargs; - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) - { - size_t z; - void *p; - - z = (*p_arg)->size; - if (z < sizeof (UINT32)) - { - p = pgr + greg++; - - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - case FFI_TYPE_STRUCT: -#ifdef __LITTLE_ENDIAN__ - avalue[i] = p; -#else - avalue[i] = ((char *) p) + sizeof (UINT32) - z; -#endif - break; - - default: - FFI_ASSERT(0); - } - } - else if (z == sizeof (UINT32)) - { - if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - if (freg < NFREGARG - 1) - { - if (fpair >= 0) - { - avalue[i] = (UINT32 *) pfr + fpair; - fpair = -1; - } - else - { -#ifdef __LITTLE_ENDIAN__ - fpair = freg; - avalue[i] = (UINT32 *) pfr + (1 ^ freg); -#else - fpair = 1 ^ freg; - avalue[i] = (UINT32 *) pfr + freg; -#endif - freg += 2; - } - } - else -#ifdef __LITTLE_ENDIAN__ - avalue[i] = pgr + greg; -#else - avalue[i] = (UINT32 *) (pgr + greg) + 1; -#endif - } - else -#ifdef __LITTLE_ENDIAN__ - avalue[i] = pgr + greg; -#else - avalue[i] = (UINT32 *) (pgr + greg) + 1; -#endif - greg++; - } - else if ((*p_arg)->type == FFI_TYPE_DOUBLE) - { - if (freg + 1 >= NFREGARG) - avalue[i] = pgr + greg; - else - { - avalue[i] = pfr + (freg >> 1); - freg += 2; - } - greg++; - } - else - { - int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); - - avalue[i] = pgr + greg; - greg += n; - } - } - - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_SYSV how to perform return type promotions. */ - return return_type (cif->rtype); -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffitarget.h deleted file mode 100644 index 08a6fe96c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/ffitarget.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for SuperH - SHmedia. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; - -#define FFI_EXTRA_CIF_FIELDS long long flags2 -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 32 -#define FFI_NATIVE_RAW_API 0 - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/sh64/sysv.S deleted file mode 100644 index c4587d5f3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sh64/sysv.S +++ /dev/null @@ -1,539 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima - - SuperH SHmedia Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include -#ifdef HAVE_MACHINE_ASM_H -#include -#else -/* XXX these lose for some platforms, I'm sure. */ -#define CNAME(x) x -#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): -#endif - -#ifdef __LITTLE_ENDIAN__ -#define OFS_FLT 0 -#else -#define OFS_FLT 4 -#endif - - .section .text..SHmedia32,"ax" - - # r2: ffi_prep_args - # r3: &ecif - # r4: bytes - # r5: flags - # r6: flags2 - # r7: rvalue - # r8: fn - - # This assumes we are using gas. - .align 5 -ENTRY(ffi_call_SYSV) - # Save registers -.LFB1: - addi.l r15, -48, r15 -.LCFI0: - st.q r15, 40, r32 - st.q r15, 32, r31 - st.q r15, 24, r30 - st.q r15, 16, r29 - st.q r15, 8, r28 - st.l r15, 4, r18 - st.l r15, 0, r14 -.LCFI1: - add.l r15, r63, r14 -.LCFI2: -# add r4, r63, r28 - add r5, r63, r29 - add r6, r63, r30 - add r7, r63, r31 - add r8, r63, r32 - - addi r4, (64 + 7), r4 - andi r4, ~7, r4 - sub.l r15, r4, r15 - - ptabs/l r2, tr0 - add r15, r63, r2 - blink tr0, r18 - - addi r15, 64, r22 - movi 0, r0 - movi 0, r1 - movi -1, r23 - - pt/l 1f, tr1 - bnei/l r29, FFI_TYPE_STRUCT, tr1 - ld.l r15, 0, r19 - addi r15, 8, r15 - addi r0, 1, r0 -1: - -.L_pass: - andi r30, 3, r20 - shlri r30, 2, r30 - - pt/l .L_call_it, tr0 - pt/l .L_pass_i, tr1 - pt/l .L_pass_f, tr2 - - beqi/l r20, FFI_TYPE_VOID, tr0 - beqi/l r20, FFI_TYPE_INT, tr1 - beqi/l r20, FFI_TYPE_FLOAT, tr2 - -.L_pass_d: - addi r0, 1, r0 - pt/l 3f, tr0 - movi 12, r20 - bge/l r1, r20, tr0 - - pt/l .L_pop_d, tr1 - pt/l 2f, tr0 - blink tr1, r63 -2: - addi.l r15, 8, r15 -3: - pt/l .L_pass, tr0 - addi r1, 2, r1 - blink tr0, r63 - -.L_pop_d: - pt/l .L_pop_d_tbl, tr1 - gettr tr1, r20 - shlli r1, 2, r21 - add r20, r21, r20 - ptabs/l r20, tr1 - blink tr1, r63 - -.L_pop_d_tbl: - fld.d r15, 0, dr0 - blink tr0, r63 - fld.d r15, 0, dr2 - blink tr0, r63 - fld.d r15, 0, dr4 - blink tr0, r63 - fld.d r15, 0, dr6 - blink tr0, r63 - fld.d r15, 0, dr8 - blink tr0, r63 - fld.d r15, 0, dr10 - blink tr0, r63 - -.L_pass_f: - addi r0, 1, r0 - pt/l 3f, tr0 - movi 12, r20 - bge/l r1, r20, tr0 - - pt/l .L_pop_f, tr1 - pt/l 2f, tr0 - blink tr1, r63 -2: - addi.l r15, 8, r15 -3: - pt/l .L_pass, tr0 - blink tr0, r63 - -.L_pop_f: - pt/l .L_pop_f_tbl, tr1 - pt/l 5f, tr2 - gettr tr1, r20 - bge/l r23, r63, tr2 - add r1, r63, r23 - shlli r1, 3, r21 - addi r1, 2, r1 - add r20, r21, r20 - ptabs/l r20, tr1 - blink tr1, r63 -5: - addi r23, 1, r21 - movi -1, r23 - shlli r21, 3, r21 - add r20, r21, r20 - ptabs/l r20, tr1 - blink tr1, r63 - -.L_pop_f_tbl: - fld.s r15, OFS_FLT, fr0 - blink tr0, r63 - fld.s r15, OFS_FLT, fr1 - blink tr0, r63 - fld.s r15, OFS_FLT, fr2 - blink tr0, r63 - fld.s r15, OFS_FLT, fr3 - blink tr0, r63 - fld.s r15, OFS_FLT, fr4 - blink tr0, r63 - fld.s r15, OFS_FLT, fr5 - blink tr0, r63 - fld.s r15, OFS_FLT, fr6 - blink tr0, r63 - fld.s r15, OFS_FLT, fr7 - blink tr0, r63 - fld.s r15, OFS_FLT, fr8 - blink tr0, r63 - fld.s r15, OFS_FLT, fr9 - blink tr0, r63 - fld.s r15, OFS_FLT, fr10 - blink tr0, r63 - fld.s r15, OFS_FLT, fr11 - blink tr0, r63 - -.L_pass_i: - pt/l 3f, tr0 - movi 8, r20 - bge/l r0, r20, tr0 - - pt/l .L_pop_i, tr1 - pt/l 2f, tr0 - blink tr1, r63 -2: - addi.l r15, 8, r15 -3: - pt/l .L_pass, tr0 - addi r0, 1, r0 - blink tr0, r63 - -.L_pop_i: - pt/l .L_pop_i_tbl, tr1 - gettr tr1, r20 - shlli r0, 3, r21 - add r20, r21, r20 - ptabs/l r20, tr1 - blink tr1, r63 - -.L_pop_i_tbl: - ld.q r15, 0, r2 - blink tr0, r63 - ld.q r15, 0, r3 - blink tr0, r63 - ld.q r15, 0, r4 - blink tr0, r63 - ld.q r15, 0, r5 - blink tr0, r63 - ld.q r15, 0, r6 - blink tr0, r63 - ld.q r15, 0, r7 - blink tr0, r63 - ld.q r15, 0, r8 - blink tr0, r63 - ld.q r15, 0, r9 - blink tr0, r63 - -.L_call_it: - # call function - pt/l 1f, tr1 - bnei/l r29, FFI_TYPE_STRUCT, tr1 - add r19, r63, r2 -1: - add r22, r63, r15 - ptabs/l r32, tr0 - blink tr0, r18 - - pt/l .L_ret_i, tr0 - pt/l .L_ret_ll, tr1 - pt/l .L_ret_d, tr2 - pt/l .L_ret_f, tr3 - pt/l .L_epilogue, tr4 - - beqi/l r29, FFI_TYPE_INT, tr0 - beqi/l r29, FFI_TYPE_UINT32, tr0 - beqi/l r29, FFI_TYPE_SINT64, tr1 - beqi/l r29, FFI_TYPE_UINT64, tr1 - beqi/l r29, FFI_TYPE_DOUBLE, tr2 - beqi/l r29, FFI_TYPE_FLOAT, tr3 - - pt/l .L_ret_q, tr0 - pt/l .L_ret_h, tr1 - - beqi/l r29, FFI_TYPE_UINT8, tr0 - beqi/l r29, FFI_TYPE_UINT16, tr1 - blink tr4, r63 - -.L_ret_d: - fst.d r31, 0, dr0 - blink tr4, r63 - -.L_ret_ll: - st.q r31, 0, r2 - blink tr4, r63 - -.L_ret_f: - fst.s r31, OFS_FLT, fr0 - blink tr4, r63 - -.L_ret_q: - st.b r31, 0, r2 - blink tr4, r63 - -.L_ret_h: - st.w r31, 0, r2 - blink tr4, r63 - -.L_ret_i: - st.l r31, 0, r2 - # Fall - -.L_epilogue: - # Remove the space we pushed for the args - add r14, r63, r15 - - ld.l r15, 0, r14 - ld.l r15, 4, r18 - ld.q r15, 8, r28 - ld.q r15, 16, r29 - ld.q r15, 24, r30 - ld.q r15, 32, r31 - ld.q r15, 40, r32 - addi.l r15, 48, r15 - ptabs r18, tr0 - blink tr0, r63 - -.LFE1: -.ffi_call_SYSV_end: - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) - - .align 5 -ENTRY(ffi_closure_SYSV) -.LFB2: - addi.l r15, -136, r15 -.LCFI3: - st.l r15, 12, r18 - st.l r15, 8, r14 - st.l r15, 4, r12 -.LCFI4: - add r15, r63, r14 -.LCFI5: - /* Stack layout: - ... - 64 bytes (register parameters) - 48 bytes (floating register parameters) - 8 bytes (result) - 4 bytes (r18) - 4 bytes (r14) - 4 bytes (r12) - 4 bytes (for align) - <- new stack pointer - */ - fst.d r14, 24, dr0 - fst.d r14, 32, dr2 - fst.d r14, 40, dr4 - fst.d r14, 48, dr6 - fst.d r14, 56, dr8 - fst.d r14, 64, dr10 - st.q r14, 72, r2 - st.q r14, 80, r3 - st.q r14, 88, r4 - st.q r14, 96, r5 - st.q r14, 104, r6 - st.q r14, 112, r7 - st.q r14, 120, r8 - st.q r14, 128, r9 - - add r1, r63, r2 - addi r14, 16, r3 - addi r14, 72, r4 - addi r14, 24, r5 - addi r14, 136, r6 -#ifdef PIC - movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 - shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 -.LPCS0: ptrel/u r12, tr0 - movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1 - gettr tr0, r12 - ldx.l r1, r12, r1 - ptabs r1, tr0 -#else - pt/l ffi_closure_helper_SYSV, tr0 -#endif - blink tr0, r18 - - shlli r2, 1, r1 - movi (((datalabel .L_table) >> 16) & 65535), r2 - shori ((datalabel .L_table) & 65535), r2 - ldx.w r2, r1, r1 - add r1, r2, r1 - pt/l .L_case_v, tr1 - ptabs r1, tr0 - blink tr0, r63 - - .align 2 -.L_table: - .word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */ - .word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */ - .word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */ - .word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */ - .word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */ - .word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */ - .word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */ - .word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */ - .word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */ - .word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */ - .word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */ - .word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */ - .word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */ - .word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */ - .word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */ - - .align 2 -.L_case_d: - fld.d r14, 16, dr0 - blink tr1, r63 -.L_case_f: - fld.s r14, 16, fr0 - blink tr1, r63 -.L_case_ll: - ld.q r14, 16, r2 - blink tr1, r63 -.L_case_i: - ld.l r14, 16, r2 - blink tr1, r63 -.L_case_q: - ld.b r14, 16, r2 - blink tr1, r63 -.L_case_uq: - ld.ub r14, 16, r2 - blink tr1, r63 -.L_case_h: - ld.w r14, 16, r2 - blink tr1, r63 -.L_case_uh: - ld.uw r14, 16, r2 - blink tr1, r63 -.L_case_v: - add.l r14, r63, r15 - ld.l r15, 4, r12 - ld.l r15, 8, r14 - ld.l r15, 12, r18 - addi.l r15, 136, r15 - ptabs r18, tr0 - blink tr0, r63 - -.LFE2: -.ffi_closure_SYSV_end: - .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif - - .section ".eh_frame","aw",@progbits -__FRAME_BEGIN__: - .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .4byte 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef PIC - .ascii "zR\0" /* CIE Augmentation */ -#else - .byte 0x0 /* CIE Augmentation */ -#endif - .uleb128 0x1 /* CIE Code Alignment Factor */ - .sleb128 -4 /* CIE Data Alignment Factor */ - .byte 0x12 /* CIE RA Column */ -#ifdef PIC - .uleb128 0x1 /* Augmentation size */ - .byte 0x10 /* FDE Encoding (pcrel) */ -#endif - .byte 0xc /* DW_CFA_def_cfa */ - .uleb128 0xf - .uleb128 0x0 - .align 2 -.LECIE1: -.LSFDE1: - .4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */ -.LASFDE1: - .4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__ -#ifdef PIC - .4byte .LFB1-. /* FDE initial location */ -#else - .4byte .LFB1 /* FDE initial location */ -#endif - .4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */ -#ifdef PIC - .uleb128 0x0 /* Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI0-datalabel .LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 0x30 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI1-datalabel .LCFI0 - .byte 0x8e /* DW_CFA_offset, column 0xe */ - .uleb128 0xc - .byte 0x92 /* DW_CFA_offset, column 0x12 */ - .uleb128 0xb - .byte 0x9c /* DW_CFA_offset, column 0x1c */ - .uleb128 0xa - .byte 0x9d /* DW_CFA_offset, column 0x1d */ - .uleb128 0x8 - .byte 0x9e /* DW_CFA_offset, column 0x1e */ - .uleb128 0x6 - .byte 0x9f /* DW_CFA_offset, column 0x1f */ - .uleb128 0x4 - .byte 0xa0 /* DW_CFA_offset, column 0x20 */ - .uleb128 0x2 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI2-datalabel .LCFI1 - .byte 0xd /* DW_CFA_def_cfa_register */ - .uleb128 0xe - .align 2 -.LEFDE1: - -.LSFDE3: - .4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */ -.LASFDE3: - .4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__ -#ifdef PIC - .4byte .LFB2-. /* FDE initial location */ -#else - .4byte .LFB2 /* FDE initial location */ -#endif - .4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */ -#ifdef PIC - .uleb128 0x0 /* Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI3-datalabel .LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 0x88 - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI4-datalabel .LCFI3 - .byte 0x8c /* DW_CFA_offset, column 0xc */ - .uleb128 0x21 - .byte 0x8e /* DW_CFA_offset, column 0xe */ - .uleb128 0x20 - .byte 0x92 /* DW_CFA_offset, column 0x12 */ - .uleb128 0x1f - .byte 0x4 /* DW_CFA_advance_loc4 */ - .4byte datalabel .LCFI5-datalabel .LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register */ - .uleb128 0xe - .align 2 -.LEFDE3: diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffi.c deleted file mode 100644 index 9f0fded48..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffi.c +++ /dev/null @@ -1,681 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2011, 2013 Anthony Green - Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc. - - SPARC Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include - - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args_v8(char *stack, extended_cif *ecif) -{ - int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - - /* Skip 16 words for the window save area */ - argp = stack + 16*sizeof(int); - - /* This should only really be done when we are returning a structure, - however, it's faster just to do it all the time... - - if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */ - *(int *) argp = (long)ecif->rvalue; - - /* And 1 word for the structure return value. */ - argp += sizeof(int); - -#ifdef USING_PURIFY - /* Purify will probably complain in our assembly routine, unless we - zero out this memory. */ - - ((int*)argp)[0] = 0; - ((int*)argp)[1] = 0; - ((int*)argp)[2] = 0; - ((int*)argp)[3] = 0; - ((int*)argp)[4] = 0; - ((int*)argp)[5] = 0; -#endif - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) - { - size_t z; - - if ((*p_arg)->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || (*p_arg)->type == FFI_TYPE_LONGDOUBLE -#endif - ) - { - *(unsigned int *) argp = (unsigned long)(* p_argv); - z = sizeof(int); - } - else - { - z = (*p_arg)->size; - if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = *(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = *(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = *(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = *(UINT16 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - } - p_argv++; - argp += z; - } - - return; -} - -int ffi_prep_args_v9(char *stack, extended_cif *ecif) -{ - int i, ret = 0; - int tmp; - void **p_argv; - char *argp; - ffi_type **p_arg; - - tmp = 0; - - /* Skip 16 words for the window save area */ - argp = stack + 16*sizeof(long long); - -#ifdef USING_PURIFY - /* Purify will probably complain in our assembly routine, unless we - zero out this memory. */ - - ((long long*)argp)[0] = 0; - ((long long*)argp)[1] = 0; - ((long long*)argp)[2] = 0; - ((long long*)argp)[3] = 0; - ((long long*)argp)[4] = 0; - ((long long*)argp)[5] = 0; -#endif - - p_argv = ecif->avalue; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && - ecif->cif->rtype->size > 32) - { - *(unsigned long long *) argp = (unsigned long)ecif->rvalue; - argp += sizeof(long long); - tmp = 1; - } - - for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; - i++, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - switch ((*p_arg)->type) - { - case FFI_TYPE_STRUCT: - if (z > 16) - { - /* For structures larger than 16 bytes we pass reference. */ - *(unsigned long long *) argp = (unsigned long)* p_argv; - argp += sizeof(long long); - tmp++; - p_argv++; - continue; - } - /* FALLTHROUGH */ - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - ret = 1; /* We should promote into FP regs as well as integer. */ - break; - } - if (z < sizeof(long long)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed long long *) argp = *(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned long long *) argp = *(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed long long *) argp = *(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned long long *) argp = *(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(signed long long *) argp = *(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(unsigned long long *) argp = *(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_FLOAT: - *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */ - break; - - case FFI_TYPE_STRUCT: - memcpy(argp, *p_argv, z); - break; - - default: - FFI_ASSERT(0); - } - z = sizeof(long long); - tmp++; - } - else if (z == sizeof(long long)) - { - memcpy(argp, *p_argv, z); - z = sizeof(long long); - tmp++; - } - else - { - if ((tmp & 1) && (*p_arg)->alignment > 8) - { - tmp++; - argp += sizeof(long long); - } - memcpy(argp, *p_argv, z); - z = 2 * sizeof(long long); - tmp += 2; - } - p_argv++; - argp += z; - } - - return ret; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - int wordsize; - - if (cif->abi != FFI_V9) - { - wordsize = 4; - - /* If we are returning a struct, this will already have been added. - Otherwise we need to add it because it's always got to be there! */ - - if (cif->rtype->type != FFI_TYPE_STRUCT) - cif->bytes += wordsize; - - /* sparc call frames require that space is allocated for 6 args, - even if they aren't used. Make that space if necessary. */ - - if (cif->bytes < 4*6+4) - cif->bytes = 4*6+4; - } - else - { - wordsize = 8; - - /* sparc call frames require that space is allocated for 6 args, - even if they aren't used. Make that space if necessary. */ - - if (cif->bytes < 8*6) - cif->bytes = 8*6; - } - - /* Adjust cif->bytes. to include 16 words for the window save area, - and maybe the struct/union return pointer area, */ - - cif->bytes += 16 * wordsize; - - /* The stack must be 2 word aligned, so round bytes up - appropriately. */ - - cif->bytes = ALIGN(cif->bytes, 2 * wordsize); - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - cif->flags = cif->rtype->type; - break; - - case FFI_TYPE_STRUCT: - if (cif->abi == FFI_V9 && cif->rtype->size > 32) - cif->flags = FFI_TYPE_VOID; - else - cif->flags = FFI_TYPE_STRUCT; - break; - - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - if (cif->abi == FFI_V9) - cif->flags = FFI_TYPE_INT; - else - cif->flags = cif->rtype->type; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - if (cif->abi == FFI_V9) - cif->flags = FFI_TYPE_INT; - else - cif->flags = FFI_TYPE_SINT64; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - return FFI_OK; -} - -int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt) -{ - ffi_type **ptr = &arg->elements[0]; - - while (*ptr != NULL) - { - if (off & ((*ptr)->alignment - 1)) - off = ALIGN(off, (*ptr)->alignment); - - switch ((*ptr)->type) - { - case FFI_TYPE_STRUCT: - off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt); - off = ALIGN(off, FFI_SIZEOF_ARG); - break; - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - memmove(ret + off, flt + off, (*ptr)->size); - off += (*ptr)->size; - break; - default: - memmove(ret + off, intg + off, (*ptr)->size); - off += (*ptr)->size; - break; - } - ptr++; - } - return off; -} - - -#ifdef SPARC64 -extern int ffi_call_v9(void *, extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); -#else -extern int ffi_call_v8(void *, extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); -#endif - -#ifndef __GNUC__ -void ffi_flush_icache (void *, size_t); -#endif - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - void *rval = rvalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - ecif.rvalue = rvalue; - if (cif->rtype->type == FFI_TYPE_STRUCT) - { - if (cif->rtype->size <= 32) - rval = alloca(64); - else - { - rval = NULL; - if (rvalue == NULL) - ecif.rvalue = alloca(cif->rtype->size); - } - } - - switch (cif->abi) - { - case FFI_V8: -#ifdef SPARC64 - /* We don't yet support calling 32bit code from 64bit */ - FFI_ASSERT(0); -#else - if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || cif->flags == FFI_TYPE_LONGDOUBLE -#endif - )) - { - /* For v8, we need an "unimp" with size of returning struct */ - /* behind "call", so we alloc some executable space for it. */ - /* l7 is used, we need to make sure v8.S doesn't use %l7. */ - unsigned int *call_struct = NULL; - ffi_closure_alloc(32, (void **)&call_struct); - if (call_struct) - { - unsigned long f = (unsigned long)fn; - call_struct[0] = 0xae10001f; /* mov %i7, %l7 */ - call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */ - call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */ - call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */ - call_struct[4] = 0x01000000; /* nop */ - if (cif->rtype->size < 0x7f) - call_struct[5] = cif->rtype->size; /* unimp */ - else - call_struct[5] = 0x01000000; /* nop */ - call_struct[6] = 0x81c7e008; /* ret */ - call_struct[7] = 0xbe100017; /* mov %l7, %i7 */ -#ifdef __GNUC__ - asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : : - "r" (call_struct) : "memory"); - /* SPARC v8 requires 5 instructions for flush to be visible */ - asm volatile ("nop; nop; nop; nop; nop"); -#else - ffi_flush_icache (call_struct, 32); -#endif - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, call_struct); - ffi_closure_free(call_struct); - } - else - { - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, fn); - } - } - else - { - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, fn); - } -#endif - break; - case FFI_V9: -#ifdef SPARC64 - ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, - cif->flags, rval, fn); - if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT) - ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32); -#else - /* And vice versa */ - FFI_ASSERT(0); -#endif - break; - default: - FFI_ASSERT(0); - break; - } -} - - -#ifdef SPARC64 -extern void ffi_closure_v9(void); -#else -extern void ffi_closure_v8(void); -#endif - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - unsigned long fn; -#ifdef SPARC64 - /* Trampoline address is equal to the closure address. We take advantage - of that to reduce the trampoline size by 8 bytes. */ - if (cif->abi != FFI_V9) - return FFI_BAD_ABI; - fn = (unsigned long) ffi_closure_v9; - tramp[0] = 0x83414000; /* rd %pc, %g1 */ - tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ - tramp[2] = 0x81c14000; /* jmp %g5 */ - tramp[3] = 0x01000000; /* nop */ - *((unsigned long *) &tramp[4]) = fn; -#else - unsigned long ctx = (unsigned long) codeloc; - if (cif->abi != FFI_V8) - return FFI_BAD_ABI; - fn = (unsigned long) ffi_closure_v8; - tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ - tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */ - tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */ - tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */ -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - /* Flush the Icache. closure is 8 bytes aligned. */ -#ifdef __GNUC__ -#ifdef SPARC64 - asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory"); -#else - asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory"); - /* SPARC v8 requires 5 instructions for flush to be visible */ - asm volatile ("nop; nop; nop; nop; nop"); -#endif -#else - ffi_flush_icache (closure, 16); -#endif - - return FFI_OK; -} - -int -ffi_closure_sparc_inner_v8(ffi_closure *closure, - void *rvalue, unsigned long *gpr, unsigned long *scratch) -{ - ffi_cif *cif; - ffi_type **arg_types; - void **avalue; - int i, argn; - - cif = closure->cif; - arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); - - /* Copy the caller's structure return address so that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || cif->flags == FFI_TYPE_LONGDOUBLE -#endif - ) - rvalue = (void *) gpr[0]; - - /* Always skip the structure return address. */ - argn = 1; - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0; i < cif->nargs; i++) - { - if (arg_types[i]->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_LONGDOUBLE -#endif - ) - { - /* Straight copy of invisible reference. */ - avalue[i] = (void *)gpr[argn++]; - } - else if ((arg_types[i]->type == FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_SINT64 - || arg_types[i]->type == FFI_TYPE_UINT64) - /* gpr is 8-byte aligned. */ - && (argn % 2) != 0) - { - /* Align on a 8-byte boundary. */ - scratch[0] = gpr[argn]; - scratch[1] = gpr[argn+1]; - avalue[i] = scratch; - scratch -= 2; - argn += 2; - } - else - { - /* Always right-justify. */ - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; - } - } - - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_sparc how to perform return type promotions. */ - return cif->rtype->type; -} - -int -ffi_closure_sparc_inner_v9(ffi_closure *closure, - void *rvalue, unsigned long *gpr, double *fpr) -{ - ffi_cif *cif; - ffi_type **arg_types; - void **avalue; - int i, argn, fp_slot_max; - - cif = closure->cif; - arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); - - /* Copy the caller's structure return address so that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_VOID - && cif->rtype->type == FFI_TYPE_STRUCT) - { - rvalue = (void *) gpr[0]; - /* Skip the structure return address. */ - argn = 1; - } - else - argn = 0; - - fp_slot_max = 16 - argn; - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0; i < cif->nargs; i++) - { - if (arg_types[i]->type == FFI_TYPE_STRUCT) - { - if (arg_types[i]->size > 16) - { - /* Straight copy of invisible reference. */ - avalue[i] = (void *)gpr[argn++]; - } - else - { - /* Left-justify. */ - ffi_v9_layout_struct(arg_types[i], - 0, - (char *) &gpr[argn], - (char *) &gpr[argn], - (char *) &fpr[argn]); - avalue[i] = &gpr[argn]; - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - } - } - else - { - /* Right-justify. */ - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - - /* Align on a 16-byte boundary. */ -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0) - argn++; -#endif - if (i < fp_slot_max - && (arg_types[i]->type == FFI_TYPE_FLOAT - || arg_types[i]->type == FFI_TYPE_DOUBLE -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_LONGDOUBLE -#endif - )) - avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size; - else - avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; - } - } - - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); - - /* Tell ffi_closure_sparc how to perform return type promotions. */ - return cif->rtype->type; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffitarget.h deleted file mode 100644 index d89f7877a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/ffitarget.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003 Red Hat, Inc. - Target configuration macros for SPARC. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -#if defined(__arch64__) || defined(__sparcv9) -#ifndef SPARC64 -#define SPARC64 -#endif -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_V8, - FFI_V8PLUS, - FFI_V9, - FFI_LAST_ABI, -#ifdef SPARC64 - FFI_DEFAULT_ABI = FFI_V9 -#else - FFI_DEFAULT_ABI = FFI_V8 -#endif -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 - -#ifdef SPARC64 -#define FFI_TRAMPOLINE_SIZE 24 -#else -#define FFI_TRAMPOLINE_SIZE 16 -#endif - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v8.S b/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v8.S deleted file mode 100644 index 6bf7ac056..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v8.S +++ /dev/null @@ -1,346 +0,0 @@ -/* ----------------------------------------------------------------------- - v8.S - Copyright (c) 2013 The Written Word, Inc. - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. - - SPARC Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#define STACKFRAME 96 /* Minimum stack framesize for SPARC */ -#define ARGS (64+4) /* Offset of register area in frame */ - -#ifndef __GNUC__ - .text - .align 8 -.globl ffi_flush_icache -.globl _ffi_flush_icache - -ffi_flush_icache: -_ffi_flush_icache: - add %o0, %o1, %o2 -#ifdef SPARC64 -1: flush %o0 -#else -1: iflush %o0 -#endif - add %o0, 8, %o0 - cmp %o0, %o2 - blt 1b - nop - nop - nop - nop - nop - retl - nop -.ffi_flush_icache_end: - .size ffi_flush_icache,.ffi_flush_icache_end-ffi_flush_icache -#endif - - .text - .align 8 -.globl ffi_call_v8 -.globl _ffi_call_v8 - -ffi_call_v8: -_ffi_call_v8: -.LLFB1: - save %sp, -STACKFRAME, %sp -.LLCFI0: - - sub %sp, %i2, %sp ! alloca() space in stack for frame to set up - add %sp, STACKFRAME, %l0 ! %l0 has start of - ! frame to set up - - mov %l0, %o0 ! call routine to set up frame - call %i0 - mov %i1, %o1 ! (delay) - - ld [%l0+ARGS], %o0 ! call foreign function - ld [%l0+ARGS+4], %o1 - ld [%l0+ARGS+8], %o2 - ld [%l0+ARGS+12], %o3 - ld [%l0+ARGS+16], %o4 - ld [%l0+ARGS+20], %o5 - call %i5 - mov %l0, %sp ! (delay) switch to frame - nop ! STRUCT returning functions skip 12 instead of 8 bytes - - ! If the return value pointer is NULL, assume no return value. - tst %i4 - bz done - nop - - cmp %i3, FFI_TYPE_INT - be,a done - st %o0, [%i4] ! (delay) - - cmp %i3, FFI_TYPE_FLOAT - be,a done - st %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_DOUBLE - be,a double - st %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_SINT8 - be,a sint8 - sll %o0, 24, %o0 ! (delay) - - cmp %i3, FFI_TYPE_UINT8 - be,a uint8 - sll %o0, 24, %o0 ! (delay) - - cmp %i3, FFI_TYPE_SINT16 - be,a sint16 - sll %o0, 16, %o0 ! (delay) - - cmp %i3, FFI_TYPE_UINT16 - be,a uint16 - sll %o0, 16, %o0 ! (delay) - - cmp %i3, FFI_TYPE_SINT64 - be,a longlong - st %o0, [%i4+0] ! (delay) -done: - ret - restore - -double: - st %f1, [%i4+4] - ret - restore - -sint8: - sra %o0, 24, %o0 - st %o0, [%i4+0] - ret - restore - -uint8: - srl %o0, 24, %o0 - st %o0, [%i4+0] - ret - restore - -sint16: - sra %o0, 16, %o0 - st %o0, [%i4+0] - ret - restore - -uint16: - srl %o0, 16, %o0 - st %o0, [%i4+0] - ret - restore - -longlong: - st %o1, [%i4+4] - ret - restore -.LLFE1: - -.ffi_call_v8_end: - .size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8 - - -#undef STACKFRAME -#define STACKFRAME 104 /* 16*4 register window + - 1*4 struct return + - 6*4 args backing store + - 3*4 locals */ - -/* ffi_closure_v8(...) - - Receives the closure argument in %g2. */ - - .text - .align 8 - .globl ffi_closure_v8 - -ffi_closure_v8: -#ifdef HAVE_AS_REGISTER_PSEUDO_OP - .register %g2, #scratch -#endif -.LLFB2: - ! Reserve frame space for all arguments in case - ! we need to align them on a 8-byte boundary. - ld [%g2+FFI_TRAMPOLINE_SIZE], %g1 - ld [%g1+4], %g1 - sll %g1, 3, %g1 - add %g1, STACKFRAME, %g1 - ! %g1 == STACKFRAME + 8*nargs - neg %g1 - save %sp, %g1, %sp -.LLCFI1: - - ! Store all of the potential argument registers in va_list format. - st %i0, [%fp+68+0] - st %i1, [%fp+68+4] - st %i2, [%fp+68+8] - st %i3, [%fp+68+12] - st %i4, [%fp+68+16] - st %i5, [%fp+68+20] - - ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g2, %o0 - add %fp, -8, %o1 - add %fp, 64, %o2 - call ffi_closure_sparc_inner_v8 - add %fp, -16, %o3 - - ! Load up the return value in the proper type. - ! See ffi_prep_cif_machdep for the list of cases. - cmp %o0, FFI_TYPE_VOID - be done1 - - cmp %o0, FFI_TYPE_INT - be done1 - ld [%fp-8], %i0 - - cmp %o0, FFI_TYPE_FLOAT - be,a done1 - ld [%fp-8], %f0 - - cmp %o0, FFI_TYPE_DOUBLE - be,a done1 - ldd [%fp-8], %f0 - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - cmp %o0, FFI_TYPE_LONGDOUBLE - be done2 -#endif - - cmp %o0, FFI_TYPE_STRUCT - be done2 - - cmp %o0, FFI_TYPE_SINT64 - be,a done1 - ldd [%fp-8], %i0 - - cmp %o0, FFI_TYPE_UINT64 - be,a done1 - ldd [%fp-8], %i0 - - ld [%fp-8], %i0 -done1: - jmp %i7+8 - restore -done2: - ! Skip 'unimp'. - jmp %i7+12 - restore -.LLFE2: - -.ffi_closure_v8_end: - .size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8 - -#ifdef SPARC64 -#define WS 8 -#define nword xword -#define uanword uaxword -#else -#define WS 4 -#define nword long -#define uanword uaword -#endif - -#ifdef HAVE_RO_EH_FRAME - .section ".eh_frame",#alloc -#else - .section ".eh_frame",#alloc,#write -#endif -.LLframe1: - .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry -.LLSCIE1: - .uaword 0x0 ! CIE Identifier Tag - .byte 0x1 ! CIE Version - .ascii "zR\0" ! CIE Augmentation - .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor - .byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor - .byte 0xf ! CIE RA Column - .byte 0x1 ! uleb128 0x1; Augmentation size -#ifdef HAVE_AS_SPARC_UA_PCREL - .byte 0x1b ! FDE Encoding (pcrel sdata4) -#else - .byte 0x50 ! FDE Encoding (aligned absolute) -#endif - .byte 0xc ! DW_CFA_def_cfa - .byte 0xe ! uleb128 0xe - .byte 0x0 ! uleb128 0x0 - .align WS -.LLECIE1: -.LLSFDE1: - .uaword .LLEFDE1-.LLASFDE1 ! FDE Length -.LLASFDE1: - .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset -#ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB1) - .uaword .LLFE1-.LLFB1 ! FDE address range -#else - .align WS - .nword .LLFB1 - .uanword .LLFE1-.LLFB1 ! FDE address range -#endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI0-.LLFB1 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align WS -.LLEFDE1: -.LLSFDE2: - .uaword .LLEFDE2-.LLASFDE2 ! FDE Length -.LLASFDE2: - .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset -#ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB2) - .uaword .LLFE2-.LLFB2 ! FDE address range -#else - .align WS - .nword .LLFB2 - .uanword .LLFE2-.LLFB2 ! FDE address range -#endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI1-.LLFB2 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align WS -.LLEFDE2: - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v9.S b/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v9.S deleted file mode 100644 index bf31a2b51..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/sparc/v9.S +++ /dev/null @@ -1,307 +0,0 @@ -/* ----------------------------------------------------------------------- - v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc. - - SPARC 64-bit Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#ifdef SPARC64 -/* Only compile this in for 64bit builds, because otherwise the object file - will have inproper architecture due to used instructions. */ - -#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */ -#define STACK_BIAS 2047 -#define ARGS (128) /* Offset of register area in frame */ - -.text - .align 8 -.globl ffi_call_v9 -.globl _ffi_call_v9 - -ffi_call_v9: -_ffi_call_v9: -.LLFB1: - save %sp, -STACKFRAME, %sp -.LLCFI0: - - sub %sp, %i2, %sp ! alloca() space in stack for frame to set up - add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of - ! frame to set up - - mov %l0, %o0 ! call routine to set up frame - call %i0 - mov %i1, %o1 ! (delay) - brz,pt %o0, 1f - ldx [%l0+ARGS], %o0 ! call foreign function - - ldd [%l0+ARGS], %f0 - ldd [%l0+ARGS+8], %f2 - ldd [%l0+ARGS+16], %f4 - ldd [%l0+ARGS+24], %f6 - ldd [%l0+ARGS+32], %f8 - ldd [%l0+ARGS+40], %f10 - ldd [%l0+ARGS+48], %f12 - ldd [%l0+ARGS+56], %f14 - ldd [%l0+ARGS+64], %f16 - ldd [%l0+ARGS+72], %f18 - ldd [%l0+ARGS+80], %f20 - ldd [%l0+ARGS+88], %f22 - ldd [%l0+ARGS+96], %f24 - ldd [%l0+ARGS+104], %f26 - ldd [%l0+ARGS+112], %f28 - ldd [%l0+ARGS+120], %f30 - -1: ldx [%l0+ARGS+8], %o1 - ldx [%l0+ARGS+16], %o2 - ldx [%l0+ARGS+24], %o3 - ldx [%l0+ARGS+32], %o4 - ldx [%l0+ARGS+40], %o5 - call %i5 - sub %l0, STACK_BIAS, %sp ! (delay) switch to frame - - ! If the return value pointer is NULL, assume no return value. - brz,pn %i4, done - nop - - cmp %i3, FFI_TYPE_INT - be,a,pt %icc, done - stx %o0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_FLOAT - be,a,pn %icc, done - st %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_DOUBLE - be,a,pn %icc, done - std %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_STRUCT - be,pn %icc, dostruct - - cmp %i3, FFI_TYPE_LONGDOUBLE - bne,pt %icc, done - nop - std %f0, [%i4+0] - std %f2, [%i4+8] - -done: ret - restore - -dostruct: - /* This will not work correctly for unions. */ - stx %o0, [%i4+0] - stx %o1, [%i4+8] - stx %o2, [%i4+16] - stx %o3, [%i4+24] - std %f0, [%i4+32] - std %f2, [%i4+40] - std %f4, [%i4+48] - std %f6, [%i4+56] - ret - restore -.LLFE1: - -.ffi_call_v9_end: - .size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9 - - -#undef STACKFRAME -#define STACKFRAME 336 /* 16*8 register window + - 6*8 args backing store + - 20*8 locals */ -#define FP %fp+STACK_BIAS - -/* ffi_closure_v9(...) - - Receives the closure argument in %g1. */ - - .text - .align 8 - .globl ffi_closure_v9 - -ffi_closure_v9: -.LLFB2: - save %sp, -STACKFRAME, %sp -.LLCFI1: - - ! Store all of the potential argument registers in va_list format. - stx %i0, [FP+128+0] - stx %i1, [FP+128+8] - stx %i2, [FP+128+16] - stx %i3, [FP+128+24] - stx %i4, [FP+128+32] - stx %i5, [FP+128+40] - - ! Store possible floating point argument registers too. - std %f0, [FP-128] - std %f2, [FP-120] - std %f4, [FP-112] - std %f6, [FP-104] - std %f8, [FP-96] - std %f10, [FP-88] - std %f12, [FP-80] - std %f14, [FP-72] - std %f16, [FP-64] - std %f18, [FP-56] - std %f20, [FP-48] - std %f22, [FP-40] - std %f24, [FP-32] - std %f26, [FP-24] - std %f28, [FP-16] - std %f30, [FP-8] - - ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g1, %o0 - add %fp, STACK_BIAS-160, %o1 - add %fp, STACK_BIAS+128, %o2 - call ffi_closure_sparc_inner_v9 - add %fp, STACK_BIAS-128, %o3 - - ! Load up the return value in the proper type. - ! See ffi_prep_cif_machdep for the list of cases. - cmp %o0, FFI_TYPE_VOID - be,pn %icc, done1 - - cmp %o0, FFI_TYPE_INT - be,pn %icc, integer - - cmp %o0, FFI_TYPE_FLOAT - be,a,pn %icc, done1 - ld [FP-160], %f0 - - cmp %o0, FFI_TYPE_DOUBLE - be,a,pn %icc, done1 - ldd [FP-160], %f0 - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - cmp %o0, FFI_TYPE_LONGDOUBLE - be,a,pn %icc, longdouble1 - ldd [FP-160], %f0 -#endif - - ! FFI_TYPE_STRUCT - ldx [FP-152], %i1 - ldx [FP-144], %i2 - ldx [FP-136], %i3 - ldd [FP-160], %f0 - ldd [FP-152], %f2 - ldd [FP-144], %f4 - ldd [FP-136], %f6 - -integer: - ldx [FP-160], %i0 - -done1: - ret - restore - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -longdouble1: - ldd [FP-152], %f2 - ret - restore -#endif -.LLFE2: - -.ffi_closure_v9_end: - .size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9 - -#ifdef HAVE_RO_EH_FRAME - .section ".eh_frame",#alloc -#else - .section ".eh_frame",#alloc,#write -#endif -.LLframe1: - .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry -.LLSCIE1: - .uaword 0x0 ! CIE Identifier Tag - .byte 0x1 ! CIE Version - .ascii "zR\0" ! CIE Augmentation - .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor - .byte 0x78 ! sleb128 -8; CIE Data Alignment Factor - .byte 0xf ! CIE RA Column - .byte 0x1 ! uleb128 0x1; Augmentation size -#ifdef HAVE_AS_SPARC_UA_PCREL - .byte 0x1b ! FDE Encoding (pcrel sdata4) -#else - .byte 0x50 ! FDE Encoding (aligned absolute) -#endif - .byte 0xc ! DW_CFA_def_cfa - .byte 0xe ! uleb128 0xe - .byte 0xff,0xf ! uleb128 0x7ff - .align 8 -.LLECIE1: -.LLSFDE1: - .uaword .LLEFDE1-.LLASFDE1 ! FDE Length -.LLASFDE1: - .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset -#ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB1) - .uaword .LLFE1-.LLFB1 ! FDE address range -#else - .align 8 - .xword .LLFB1 - .uaxword .LLFE1-.LLFB1 ! FDE address range -#endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI0-.LLFB1 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align 8 -.LLEFDE1: -.LLSFDE2: - .uaword .LLEFDE2-.LLASFDE2 ! FDE Length -.LLASFDE2: - .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset -#ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB2) - .uaword .LLFE2-.LLFB2 ! FDE address range -#else - .align 8 - .xword .LLFB2 - .uaxword .LLFE2-.LLFB2 ! FDE address range -#endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI1-.LLFB2 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align 8 -.LLEFDE2: -#endif - -#ifdef __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffi.c deleted file mode 100644 index 3a94469c7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffi.c +++ /dev/null @@ -1,355 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2012 Tilera Corp. - - TILE Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -/* The first 10 registers are used to pass arguments and return values. */ -#define NUM_ARG_REGS 10 - -/* Performs a raw function call with the given NUM_ARG_REGS register arguments - and the specified additional stack arguments (if any). */ -extern void ffi_call_tile(ffi_sarg reg_args[NUM_ARG_REGS], - const ffi_sarg *stack_args, - size_t stack_args_bytes, - void (*fnaddr)(void)) - FFI_HIDDEN; - -/* This handles the raw call from the closure stub, cleaning up the - parameters and delegating to ffi_closure_tile_inner. */ -extern void ffi_closure_tile(void) FFI_HIDDEN; - - -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* We always allocate room for all registers. Even if we don't - use them as parameters, they get returned in the same array - as struct return values so we need to make room. */ - if (cif->bytes < NUM_ARG_REGS * FFI_SIZEOF_ARG) - cif->bytes = NUM_ARG_REGS * FFI_SIZEOF_ARG; - - if (cif->rtype->size > NUM_ARG_REGS * FFI_SIZEOF_ARG) - cif->flags = FFI_TYPE_STRUCT; - else - cif->flags = FFI_TYPE_INT; - - /* Nothing to do. */ - return FFI_OK; -} - - -static long -assign_to_ffi_arg(ffi_sarg *out, void *in, const ffi_type *type, - int write_to_reg) -{ - switch (type->type) - { - case FFI_TYPE_SINT8: - *out = *(SINT8 *)in; - return 1; - - case FFI_TYPE_UINT8: - *out = *(UINT8 *)in; - return 1; - - case FFI_TYPE_SINT16: - *out = *(SINT16 *)in; - return 1; - - case FFI_TYPE_UINT16: - *out = *(UINT16 *)in; - return 1; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: -#ifndef __LP64__ - case FFI_TYPE_POINTER: -#endif - /* Note that even unsigned 32-bit quantities are sign extended - on tilegx when stored in a register. */ - *out = *(SINT32 *)in; - return 1; - - case FFI_TYPE_FLOAT: -#ifdef __tilegx__ - if (write_to_reg) - { - /* Properly sign extend the value. */ - union { float f; SINT32 s32; } val; - val.f = *(float *)in; - *out = val.s32; - } - else -#endif - { - *(float *)out = *(float *)in; - } - return 1; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - case FFI_TYPE_DOUBLE: -#ifdef __LP64__ - case FFI_TYPE_POINTER: -#endif - *(UINT64 *)out = *(UINT64 *)in; - return sizeof(UINT64) / FFI_SIZEOF_ARG; - - case FFI_TYPE_STRUCT: - memcpy(out, in, type->size); - return (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG; - - case FFI_TYPE_VOID: - /* Must be a return type. Nothing to do. */ - return 0; - - default: - FFI_ASSERT(0); - return -1; - } -} - - -void -ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - ffi_sarg * const arg_mem = alloca(cif->bytes); - ffi_sarg * const reg_args = arg_mem; - ffi_sarg * const stack_args = ®_args[NUM_ARG_REGS]; - ffi_sarg *argp = arg_mem; - ffi_type ** const arg_types = cif->arg_types; - const long num_args = cif->nargs; - long i; - - if (cif->flags == FFI_TYPE_STRUCT) - { - /* Pass a hidden pointer to the return value. We make sure there - is scratch space for the callee to store the return value even if - our caller doesn't care about it. */ - *argp++ = (intptr_t)(rvalue ? rvalue : alloca(cif->rtype->size)); - - /* No more work needed to return anything. */ - rvalue = NULL; - } - - for (i = 0; i < num_args; i++) - { - ffi_type *type = arg_types[i]; - void * const arg_in = avalue[i]; - ptrdiff_t arg_word = argp - arg_mem; - -#ifndef __tilegx__ - /* Doubleword-aligned values are always in an even-number register - pair, or doubleword-aligned stack slot if out of registers. */ - long align = arg_word & (type->alignment > FFI_SIZEOF_ARG); - argp += align; - arg_word += align; -#endif - - if (type->type == FFI_TYPE_STRUCT) - { - const size_t arg_size_in_words = - (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG; - - if (arg_word < NUM_ARG_REGS && - arg_word + arg_size_in_words > NUM_ARG_REGS) - { - /* Args are not allowed to span registers and the stack. */ - argp = stack_args; - } - - memcpy(argp, arg_in, type->size); - argp += arg_size_in_words; - } - else - { - argp += assign_to_ffi_arg(argp, arg_in, arg_types[i], 1); - } - } - - /* Actually do the call. */ - ffi_call_tile(reg_args, stack_args, - cif->bytes - (NUM_ARG_REGS * FFI_SIZEOF_ARG), fn); - - if (rvalue != NULL) - assign_to_ffi_arg(rvalue, reg_args, cif->rtype, 0); -} - - -/* Template code for closure. */ -extern const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN; - - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, - ffi_cif *cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ -#ifdef __tilegx__ - /* TILE-Gx */ - SINT64 c; - SINT64 h; - int s; - UINT64 *out; - - if (cif->abi != FFI_UNIX) - return FFI_BAD_ABI; - - out = (UINT64 *)closure->tramp; - - c = (intptr_t)closure; - h = (intptr_t)ffi_closure_tile; - s = 0; - - /* Find the smallest shift count that doesn't lose information - (i.e. no need to explicitly insert high bits of the address that - are just the sign extension of the low bits). */ - while ((c >> s) != (SINT16)(c >> s) || (h >> s) != (SINT16)(h >> s)) - s += 16; - -#define OPS(a, b, shift) \ - (create_Imm16_X0((a) >> (shift)) | create_Imm16_X1((b) >> (shift))) - - /* Emit the moveli. */ - *out++ = ffi_template_tramp_tile[0] | OPS(c, h, s); - for (s -= 16; s >= 0; s -= 16) - *out++ = ffi_template_tramp_tile[1] | OPS(c, h, s); - -#undef OPS - - *out++ = ffi_template_tramp_tile[2]; - -#else - /* TILEPro */ - UINT64 *out; - intptr_t delta; - - if (cif->abi != FFI_UNIX) - return FFI_BAD_ABI; - - out = (UINT64 *)closure->tramp; - delta = (intptr_t)ffi_closure_tile - (intptr_t)codeloc; - - *out++ = ffi_template_tramp_tile[0] | create_JOffLong_X1(delta >> 3); -#endif - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - invalidate_icache(closure->tramp, (char *)out - closure->tramp, - getpagesize()); - - return FFI_OK; -} - - -/* This is called by the assembly wrapper for closures. This does - all of the work. On entry reg_args[0] holds the values the registers - had when the closure was invoked. On return reg_args[1] holds the register - values to be returned to the caller (many of which may be garbage). */ -void FFI_HIDDEN -ffi_closure_tile_inner(ffi_closure *closure, - ffi_sarg reg_args[2][NUM_ARG_REGS], - ffi_sarg *stack_args) -{ - ffi_cif * const cif = closure->cif; - void ** const avalue = alloca(cif->nargs * sizeof(void *)); - void *rvalue; - ffi_type ** const arg_types = cif->arg_types; - ffi_sarg * const reg_args_in = reg_args[0]; - ffi_sarg * const reg_args_out = reg_args[1]; - ffi_sarg * argp; - long i, arg_word, nargs = cif->nargs; - /* Use a union to guarantee proper alignment for double. */ - union { ffi_sarg arg[NUM_ARG_REGS]; double d; UINT64 u64; } closure_ret; - - /* Start out reading register arguments. */ - argp = reg_args_in; - - /* Copy the caller's structure return address to that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT) - { - /* Return by reference via hidden pointer. */ - rvalue = (void *)(intptr_t)*argp++; - arg_word = 1; - } - else - { - /* Return the value in registers. */ - rvalue = &closure_ret; - arg_word = 0; - } - - /* Grab the addresses of the arguments. */ - for (i = 0; i < nargs; i++) - { - ffi_type * const type = arg_types[i]; - const size_t arg_size_in_words = - (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG; - -#ifndef __tilegx__ - /* Doubleword-aligned values are always in an even-number register - pair, or doubleword-aligned stack slot if out of registers. */ - long align = arg_word & (type->alignment > FFI_SIZEOF_ARG); - argp += align; - arg_word += align; -#endif - - if (arg_word == NUM_ARG_REGS || - (arg_word < NUM_ARG_REGS && - arg_word + arg_size_in_words > NUM_ARG_REGS)) - { - /* Switch to reading arguments from the stack. */ - argp = stack_args; - arg_word = NUM_ARG_REGS; - } - - avalue[i] = argp; - argp += arg_size_in_words; - arg_word += arg_size_in_words; - } - - /* Invoke the closure. */ - closure->fun(cif, rvalue, avalue, closure->user_data); - - if (cif->flags != FFI_TYPE_STRUCT) - { - /* Canonicalize for register representation. */ - assign_to_ffi_arg(reg_args_out, &closure_ret, cif->rtype, 1); - } -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffitarget.h deleted file mode 100644 index 679fb5d90..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/tile/ffitarget.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Tilera Corp. - Target configuration macros for TILE. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM - -#include - -typedef uint_reg_t ffi_arg; -typedef int_reg_t ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_UNIX, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_UNIX -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ -#define FFI_CLOSURES 1 - -#ifdef __tilegx__ -/* We always pass 8-byte values, even in -m32 mode. */ -# define FFI_SIZEOF_ARG 8 -# ifdef __LP64__ -# define FFI_TRAMPOLINE_SIZE (8 * 5) /* 5 bundles */ -# else -# define FFI_TRAMPOLINE_SIZE (8 * 3) /* 3 bundles */ -# endif -#else -# define FFI_SIZEOF_ARG 4 -# define FFI_TRAMPOLINE_SIZE 8 /* 1 bundle */ -#endif -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/tile/tile.S b/ruby/ext/fiddle/libffi-3.2.1/src/tile/tile.S deleted file mode 100644 index d1f82cb3d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/tile/tile.S +++ /dev/null @@ -1,360 +0,0 @@ -/* ----------------------------------------------------------------------- - tile.S - Copyright (c) 2011 Tilera Corp. - - Tilera TILEPro and TILE-Gx Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -/* Number of bytes in a register. */ -#define REG_SIZE FFI_SIZEOF_ARG - -/* Number of bytes in stack linkage area for backtracing. - - A note about the ABI: on entry to a procedure, sp points to a stack - slot where it must spill the return address if it's not a leaf. - REG_SIZE bytes beyond that is a slot owned by the caller which - contains the sp value that the caller had when it was originally - entered (i.e. the caller's frame pointer). */ -#define LINKAGE_SIZE (2 * REG_SIZE) - -/* The first 10 registers are used to pass arguments and return values. */ -#define NUM_ARG_REGS 10 - -#ifdef __tilegx__ -#define SW st -#define LW ld -#define BGZT bgtzt -#else -#define SW sw -#define LW lw -#define BGZT bgzt -#endif - - -/* void ffi_call_tile (int_reg_t reg_args[NUM_ARG_REGS], - const int_reg_t *stack_args, - unsigned long stack_args_bytes, - void (*fnaddr)(void)); - - On entry, REG_ARGS contain the outgoing register values, - and STACK_ARGS contains STACK_ARG_BYTES of additional values - to be passed on the stack. If STACK_ARG_BYTES is zero, then - STACK_ARGS is ignored. - - When the invoked function returns, the values of r0-r9 are - blindly stored back into REG_ARGS for the caller to examine. */ - - .section .text.ffi_call_tile, "ax", @progbits - .align 8 - .globl ffi_call_tile - FFI_HIDDEN(ffi_call_tile) -ffi_call_tile: - -/* Incoming arguments. */ -#define REG_ARGS r0 -#define INCOMING_STACK_ARGS r1 -#define STACK_ARG_BYTES r2 -#define ORIG_FNADDR r3 - -/* Temporary values. */ -#define FRAME_SIZE r10 -#define TMP r11 -#define TMP2 r12 -#define OUTGOING_STACK_ARGS r13 -#define REG_ADDR_PTR r14 -#define RETURN_REG_ADDR r15 -#define FNADDR r16 - - .cfi_startproc - { - /* Save return address. */ - SW sp, lr - .cfi_offset lr, 0 - /* Prepare to spill incoming r52. */ - addi TMP, sp, -REG_SIZE - /* Increase frame size to have room to spill r52 and REG_ARGS. - The +7 is to round up mod 8. */ - addi FRAME_SIZE, STACK_ARG_BYTES, \ - REG_SIZE + REG_SIZE + LINKAGE_SIZE + 7 - } - { - /* Round stack frame size to a multiple of 8 to satisfy ABI. */ - andi FRAME_SIZE, FRAME_SIZE, -8 - /* Compute where to spill REG_ARGS value. */ - addi TMP2, sp, -(REG_SIZE * 2) - } - { - /* Spill incoming r52. */ - SW TMP, r52 - .cfi_offset r52, -REG_SIZE - /* Set up our frame pointer. */ - move r52, sp - .cfi_def_cfa_register r52 - /* Push stack frame. */ - sub sp, sp, FRAME_SIZE - } - { - /* Prepare to set up stack linkage. */ - addi TMP, sp, REG_SIZE - /* Prepare to memcpy stack args. */ - addi OUTGOING_STACK_ARGS, sp, LINKAGE_SIZE - /* Save REG_ARGS which we will need after we call the subroutine. */ - SW TMP2, REG_ARGS - } - { - /* Set up linkage info to hold incoming stack pointer. */ - SW TMP, r52 - } - { - /* Skip stack args memcpy if we don't have any stack args (common). */ - blezt STACK_ARG_BYTES, .Ldone_stack_args_memcpy - } - -.Lmemcpy_stack_args: - { - /* Load incoming argument from stack_args. */ - LW TMP, INCOMING_STACK_ARGS - addi INCOMING_STACK_ARGS, INCOMING_STACK_ARGS, REG_SIZE - } - { - /* Store stack argument into outgoing stack argument area. */ - SW OUTGOING_STACK_ARGS, TMP - addi OUTGOING_STACK_ARGS, OUTGOING_STACK_ARGS, REG_SIZE - addi STACK_ARG_BYTES, STACK_ARG_BYTES, -REG_SIZE - } - { - BGZT STACK_ARG_BYTES, .Lmemcpy_stack_args - } -.Ldone_stack_args_memcpy: - - { - /* Copy aside ORIG_FNADDR so we can overwrite its register. */ - move FNADDR, ORIG_FNADDR - /* Prepare to load argument registers. */ - addi REG_ADDR_PTR, r0, REG_SIZE - /* Load outgoing r0. */ - LW r0, r0 - } - - /* Load up argument registers from the REG_ARGS array. */ -#define LOAD_REG(REG, PTR) \ - { \ - LW REG, PTR ; \ - addi PTR, PTR, REG_SIZE \ - } - - LOAD_REG(r1, REG_ADDR_PTR) - LOAD_REG(r2, REG_ADDR_PTR) - LOAD_REG(r3, REG_ADDR_PTR) - LOAD_REG(r4, REG_ADDR_PTR) - LOAD_REG(r5, REG_ADDR_PTR) - LOAD_REG(r6, REG_ADDR_PTR) - LOAD_REG(r7, REG_ADDR_PTR) - LOAD_REG(r8, REG_ADDR_PTR) - LOAD_REG(r9, REG_ADDR_PTR) - - { - /* Call the subroutine. */ - jalr FNADDR - } - - { - /* Restore original lr. */ - LW lr, r52 - /* Prepare to recover ARGS, which we spilled earlier. */ - addi TMP, r52, -(2 * REG_SIZE) - } - { - /* Restore ARGS, so we can fill it in with the return regs r0-r9. */ - LW RETURN_REG_ADDR, TMP - /* Prepare to restore original r52. */ - addi TMP, r52, -REG_SIZE - } - - { - /* Pop stack frame. */ - move sp, r52 - /* Restore original r52. */ - LW r52, TMP - } - -#define STORE_REG(REG, PTR) \ - { \ - SW PTR, REG ; \ - addi PTR, PTR, REG_SIZE \ - } - - /* Return all register values by reference. */ - STORE_REG(r0, RETURN_REG_ADDR) - STORE_REG(r1, RETURN_REG_ADDR) - STORE_REG(r2, RETURN_REG_ADDR) - STORE_REG(r3, RETURN_REG_ADDR) - STORE_REG(r4, RETURN_REG_ADDR) - STORE_REG(r5, RETURN_REG_ADDR) - STORE_REG(r6, RETURN_REG_ADDR) - STORE_REG(r7, RETURN_REG_ADDR) - STORE_REG(r8, RETURN_REG_ADDR) - STORE_REG(r9, RETURN_REG_ADDR) - - { - jrp lr - } - - .cfi_endproc - .size ffi_call_tile, .-ffi_call_tile - -/* ffi_closure_tile(...) - - On entry, lr points to the closure plus 8 bytes, and r10 - contains the actual return address. - - This function simply dumps all register parameters into a stack array - and passes the closure, the registers array, and the stack arguments - to C code that does all of the actual closure processing. */ - - .section .text.ffi_closure_tile, "ax", @progbits - .align 8 - .globl ffi_closure_tile - FFI_HIDDEN(ffi_closure_tile) - - .cfi_startproc -/* Room to spill all NUM_ARG_REGS incoming registers, plus frame linkage. */ -#define CLOSURE_FRAME_SIZE (((NUM_ARG_REGS * REG_SIZE * 2 + LINKAGE_SIZE) + 7) & -8) -ffi_closure_tile: - { -#ifdef __tilegx__ - st sp, lr - .cfi_offset lr, 0 -#else - /* Save return address (in r10 due to closure stub wrapper). */ - SW sp, r10 - .cfi_return_column r10 - .cfi_offset r10, 0 -#endif - /* Compute address for stack frame linkage. */ - addli r10, sp, -(CLOSURE_FRAME_SIZE - REG_SIZE) - } - { - /* Save incoming stack pointer in linkage area. */ - SW r10, sp - .cfi_offset sp, -(CLOSURE_FRAME_SIZE - REG_SIZE) - /* Push a new stack frame. */ - addli sp, sp, -CLOSURE_FRAME_SIZE - .cfi_adjust_cfa_offset CLOSURE_FRAME_SIZE - } - - { - /* Create pointer to where to start spilling registers. */ - addi r10, sp, LINKAGE_SIZE - } - - /* Spill all the incoming registers. */ - STORE_REG(r0, r10) - STORE_REG(r1, r10) - STORE_REG(r2, r10) - STORE_REG(r3, r10) - STORE_REG(r4, r10) - STORE_REG(r5, r10) - STORE_REG(r6, r10) - STORE_REG(r7, r10) - STORE_REG(r8, r10) - { - /* Save r9. */ - SW r10, r9 -#ifdef __tilegx__ - /* Pointer to closure is passed in r11. */ - move r0, r11 -#else - /* Compute pointer to the closure object. Because the closure - starts with a "jal ffi_closure_tile", we can just take the - value of lr (a phony return address pointing into the closure) - and subtract 8. */ - addi r0, lr, -8 -#endif - /* Compute a pointer to the register arguments we just spilled. */ - addi r1, sp, LINKAGE_SIZE - } - { - /* Compute a pointer to the extra stack arguments (if any). */ - addli r2, sp, CLOSURE_FRAME_SIZE + LINKAGE_SIZE - /* Call C code to deal with all of the grotty details. */ - jal ffi_closure_tile_inner - } - { - addli r10, sp, CLOSURE_FRAME_SIZE - } - { - /* Restore the return address. */ - LW lr, r10 - /* Compute pointer to registers array. */ - addli r10, sp, LINKAGE_SIZE + (NUM_ARG_REGS * REG_SIZE) - } - /* Return all the register values, which C code may have set. */ - LOAD_REG(r0, r10) - LOAD_REG(r1, r10) - LOAD_REG(r2, r10) - LOAD_REG(r3, r10) - LOAD_REG(r4, r10) - LOAD_REG(r5, r10) - LOAD_REG(r6, r10) - LOAD_REG(r7, r10) - LOAD_REG(r8, r10) - LOAD_REG(r9, r10) - { - /* Pop the frame. */ - addli sp, sp, CLOSURE_FRAME_SIZE - jrp lr - } - - .cfi_endproc - .size ffi_closure_tile, . - ffi_closure_tile - - -/* What follows are code template instructions that get copied to the - closure trampoline by ffi_prep_closure_loc. The zeroed operands - get replaced by their proper values at runtime. */ - - .section .text.ffi_template_tramp_tile, "ax", @progbits - .align 8 - .globl ffi_template_tramp_tile - FFI_HIDDEN(ffi_template_tramp_tile) -ffi_template_tramp_tile: -#ifdef __tilegx__ - { - moveli r11, 0 /* backpatched to address of containing closure. */ - moveli r10, 0 /* backpatched to ffi_closure_tile. */ - } - /* Note: the following bundle gets generated multiple times - depending on the pointer value (esp. useful for -m32 mode). */ - { shl16insli r11, r11, 0 ; shl16insli r10, r10, 0 } - { info 2+8 /* for backtracer: -> pc in lr, frame size 0 */ ; jr r10 } -#else - /* 'jal .' yields a PC-relative offset of zero so we can OR in the - right offset at runtime. */ - { move r10, lr ; jal . /* ffi_closure_tile */ } -#endif - - .size ffi_template_tramp_tile, . - ffi_template_tramp_tile diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/types.c b/ruby/ext/fiddle/libffi-3.2.1/src/types.c deleted file mode 100644 index 7e80aec6e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/types.c +++ /dev/null @@ -1,106 +0,0 @@ -/* ----------------------------------------------------------------------- - types.c - Copyright (c) 1996, 1998 Red Hat, Inc. - - Predefined ffi_types needed by libffi. - - 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. - ----------------------------------------------------------------------- */ - -/* Hide the basic type definitions from the header file, so that we - can redefine them here as "const". */ -#define LIBFFI_HIDE_BASIC_TYPES - -#include -#include - -/* Type definitions */ - -#define FFI_TYPEDEF(name, type, id, maybe_const)\ -struct struct_align_##name { \ - char c; \ - type x; \ -}; \ -maybe_const ffi_type ffi_type_##name = { \ - sizeof(type), \ - offsetof(struct struct_align_##name, x), \ - id, NULL \ -} - -#define FFI_COMPLEX_TYPEDEF(name, type, maybe_const) \ -static ffi_type *ffi_elements_complex_##name [2] = { \ - (ffi_type *)(&ffi_type_##name), NULL \ -}; \ -struct struct_align_complex_##name { \ - char c; \ - _Complex type x; \ -}; \ -maybe_const ffi_type ffi_type_complex_##name = { \ - sizeof(_Complex type), \ - offsetof(struct struct_align_complex_##name, x), \ - FFI_TYPE_COMPLEX, \ - (ffi_type **)ffi_elements_complex_##name \ -} - -/* Size and alignment are fake here. They must not be 0. */ -const ffi_type ffi_type_void = { - 1, 1, FFI_TYPE_VOID, NULL -}; - -FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8, const); -FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8, const); -FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16, const); -FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16, const); -FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32, const); -FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32, const); -FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64, const); -FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64, const); - -FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const); - -FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const); -FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const); - -#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__ -#define FFI_LDBL_CONST const -#else -#define FFI_LDBL_CONST -#endif - -#ifdef __alpha__ -/* Even if we're not configured to default to 128-bit long double, - maintain binary compatibility, as -mlong-double-128 can be used - at any time. */ -/* Validate the hard-coded number below. */ -# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4 -# error FFI_TYPE_LONGDOUBLE out of date -# endif -const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL }; -#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE, FFI_LDBL_CONST); -#endif - -#ifdef FFI_TARGET_HAS_COMPLEX_TYPE -FFI_COMPLEX_TYPEDEF(float, float, const); -FFI_COMPLEX_TYPEDEF(double, double, const); -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -FFI_COMPLEX_TYPEDEF(longdouble, long double, FFI_LDBL_CONST); -#endif -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/vax/elfbsd.S b/ruby/ext/fiddle/libffi-3.2.1/src/vax/elfbsd.S deleted file mode 100644 index 01ca31340..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/vax/elfbsd.S +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * vax Foreign Function Interface - */ - -#define LIBFFI_ASM -#include -#include - - .text - -/* - * void * %r0 - * ffi_call_elfbsd(extended_cif *ecif, 4(%ap) - * unsigned bytes, 8(%ap) - * unsigned flags, 12(%ap) - * void *rvalue, 16(%ap) - * void (*fn)()); 20(%ap) - */ - .globl ffi_call_elfbsd - .type ffi_call_elfbsd,@function - .align 2 -ffi_call_elfbsd: - .word 0x00c # save R2 and R3 - - # Allocate stack space for the args - subl2 8(%ap), %sp - - # Call ffi_prep_args - pushl %sp - pushl 4(%ap) - calls $2, ffi_prep_args - - # Get function pointer - movl 20(%ap), %r1 - - # Build a CALLS frame - ashl $-2, 8(%ap), %r0 - pushl %r0 # argument stack usage - movl %sp, %r0 # future %ap - # saved registers - bbc $11, 0(%r1), 1f - pushl %r11 -1: bbc $10, 0(%r1), 1f - pushl %r10 -1: bbc $9, 0(%r1), 1f - pushl %r9 -1: bbc $8, 0(%r1), 1f - pushl %r8 -1: bbc $7, 0(%r1), 1f - pushl %r7 -1: bbc $6, 0(%r1), 1f - pushl %r6 -1: bbc $5, 0(%r1), 1f - pushl %r5 -1: bbc $4, 0(%r1), 1f - pushl %r4 -1: bbc $3, 0(%r1), 1f - pushl %r3 -1: bbc $2, 0(%r1), 1f - pushl %r2 -1: - pushal 9f - pushl %fp - pushl %ap - movl 16(%ap), %r3 # struct return address, if needed - movl %r0, %ap - movzwl 4(%fp), %r0 # previous PSW, without the saved registers mask - bisl2 $0x20000000, %r0 # calls frame - movzwl 0(%r1), %r2 - bicw2 $0xf003, %r2 # only keep R11-R2 - ashl $16, %r2, %r2 - bisl2 %r2, %r0 # saved register mask of the called function - pushl %r0 - pushl $0 - movl %sp, %fp - - # Invoke the function - pushal 2(%r1) # skip procedure entry mask - movl %r3, %r1 - bicpsw $0x000f - rsb - -9: - # Copy return value if necessary - tstl 16(%ap) - jeql 9f - movl 16(%ap), %r2 - - bbc $0, 12(%ap), 1f # CIF_FLAGS_CHAR - movb %r0, 0(%r2) - brb 9f -1: - bbc $1, 12(%ap), 1f # CIF_FLAGS_SHORT - movw %r0, 0(%r2) - brb 9f -1: - bbc $2, 12(%ap), 1f # CIF_FLAGS_INT - movl %r0, 0(%r2) - brb 9f -1: - bbc $3, 12(%ap), 1f # CIF_FLAGS_DINT - movq %r0, 0(%r2) - brb 9f -1: - movl %r1, %r0 # might have been a struct - #brb 9f - -9: - ret - -/* - * ffi_closure_elfbsd(void); - * invoked with %r0: ffi_closure *closure - */ - .globl ffi_closure_elfbsd - .type ffi_closure_elfbsd, @function - .align 2 -ffi_closure_elfbsd: - .word 0 - - # Allocate room on stack for return value - subl2 $8, %sp - - # Invoke the closure function - pushal 4(%ap) # calling stack - pushal 4(%sp) # return value - pushl %r0 # closure - calls $3, ffi_closure_elfbsd_inner - - # Copy return value if necessary - bitb $1, %r0 # CIF_FLAGS_CHAR - beql 1f - movb 0(%sp), %r0 - brb 9f -1: - bitb $2, %r0 # CIF_FLAGS_SHORT - beql 1f - movw 0(%sp), %r0 - brb 9f -1: - bitb $4, %r0 # CIF_FLAGS_INT - beql 1f - movl 0(%sp), %r0 - brb 9f -1: - bitb $8, %r0 # CIF_FLAGS_DINT - beql 1f - movq 0(%sp), %r0 - #brb 9f -1: - -9: - ret - -/* - * ffi_closure_struct_elfbsd(void); - * invoked with %r0: ffi_closure *closure - * %r1: struct return address - */ - .globl ffi_closure_struct_elfbsd - .type ffi_closure_struct_elfbsd, @function - .align 2 -ffi_closure_struct_elfbsd: - .word 0 - - # Invoke the closure function - pushal 4(%ap) # calling stack - pushl %r1 # return value - pushl %r0 # closure - calls $3, ffi_closure_elfbsd_inner - - ret diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffi.c deleted file mode 100644 index f4d6bbb4f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffi.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * vax Foreign Function Interface - * - * This file attempts to provide all the FFI entry points which can reliably - * be implemented in C. - */ - -#include -#include - -#include -#include - -#define CIF_FLAGS_CHAR 1 /* for struct only */ -#define CIF_FLAGS_SHORT 2 /* for struct only */ -#define CIF_FLAGS_INT 4 -#define CIF_FLAGS_DINT 8 - -/* - * Foreign Function Interface API - */ - -void ffi_call_elfbsd (extended_cif *, unsigned, unsigned, void *, - void (*) ()); -void *ffi_prep_args (extended_cif *ecif, void *stack); - -void * -ffi_prep_args (extended_cif *ecif, void *stack) -{ - unsigned int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - void *struct_value_ptr; - - argp = stack; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT - && !ecif->cif->flags) - struct_value_ptr = ecif->rvalue; - else - struct_value_ptr = NULL; - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - i != 0; - i--, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - if (z < sizeof (int)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int) *(SINT8 *) *p_argv; - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv; - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int) *(SINT16 *) *p_argv; - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv; - break; - - case FFI_TYPE_STRUCT: - memcpy (argp, *p_argv, z); - break; - - default: - FFI_ASSERT (0); - } - z = sizeof (int); - } - else - { - memcpy (argp, *p_argv, z); - - /* Align if necessary. */ - if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); - } - - p_argv++; - argp += z; - } - - return struct_value_ptr; -} - -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - cif->flags = 0; - break; - - case FFI_TYPE_STRUCT: - if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT && - cif->rtype->elements[1]) - { - cif->flags = 0; - break; - } - - if (cif->rtype->size == sizeof (char)) - cif->flags = CIF_FLAGS_CHAR; - else if (cif->rtype->size == sizeof (short)) - cif->flags = CIF_FLAGS_SHORT; - else if (cif->rtype->size == sizeof (int)) - cif->flags = CIF_FLAGS_INT; - else if (cif->rtype->size == 2 * sizeof (int)) - cif->flags = CIF_FLAGS_DINT; - else - cif->flags = 0; - break; - - default: - if (cif->rtype->size <= sizeof (int)) - cif->flags = CIF_FLAGS_INT; - else - cif->flags = CIF_FLAGS_DINT; - break; - } - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return value - address then we need to make one. */ - - if (rvalue == NULL - && cif->rtype->type == FFI_TYPE_STRUCT - && cif->flags == 0) - ecif.rvalue = alloca (cif->rtype->size); - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_ELFBSD: - ffi_call_elfbsd (&ecif, cif->bytes, cif->flags, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; - } -} - -/* - * Closure API - */ - -void ffi_closure_elfbsd (void); -void ffi_closure_struct_elfbsd (void); -unsigned int ffi_closure_elfbsd_inner (ffi_closure *, void *, char *); - -static void -ffi_prep_closure_elfbsd (ffi_cif *cif, void **avalue, char *stackp) -{ - unsigned int i; - void **p_argv; - ffi_type **p_arg; - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - *p_argv = stackp; - - /* Align if necessary */ - if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); - - p_argv++; - stackp += z; - } -} - -unsigned int -ffi_closure_elfbsd_inner (ffi_closure *closure, void *resp, char *stack) -{ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void **) alloca (cif->nargs * sizeof (void *)); - - ffi_prep_closure_elfbsd (cif, arg_area, stack); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - return cif->flags; -} - -ffi_status -ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, - void (*fun)(ffi_cif *, void *, void **, void *), - void *user_data, void *codeloc) -{ - char *tramp = (char *) codeloc; - void *fn; - - FFI_ASSERT (cif->abi == FFI_ELFBSD); - - /* entry mask */ - *(unsigned short *)(tramp + 0) = 0x0000; - /* movl #closure, r0 */ - tramp[2] = 0xd0; - tramp[3] = 0x8f; - *(unsigned int *)(tramp + 4) = (unsigned int) closure; - tramp[8] = 0x50; - - if (cif->rtype->type == FFI_TYPE_STRUCT - && !cif->flags) - fn = &ffi_closure_struct_elfbsd; - else - fn = &ffi_closure_elfbsd; - - /* jmpl #fn */ - tramp[9] = 0x17; - tramp[10] = 0xef; - *(unsigned int *)(tramp + 11) = (unsigned int)fn + 2 - - (unsigned int)tramp - 9 - 6; - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffitarget.h deleted file mode 100644 index 2fc94881a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/vax/ffitarget.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013 Miodrag Vallat. - * - * 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. - */ - -/* - * vax Foreign Function Interface - */ - -#ifndef LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_ELFBSD, - FFI_DEFAULT_ABI = FFI_ELFBSD, - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 15 -#define FFI_NATIVE_RAW_API 0 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin.S deleted file mode 100644 index 8f0f0707a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin.S +++ /dev/null @@ -1,444 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. - - X86 Foreign Function Interface - - 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 __x86_64__ - -#define LIBFFI_ASM -#include -#include - -.text - -.globl _ffi_prep_args - - .align 4 -.globl _ffi_call_SYSV - -_ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - subl $8,%esp - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - subl $8,%esp - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $16,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue -0: - .align 4 - call 1f -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - .long retstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long retstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */ -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint - -retsint16: - movswl %ax, %eax - jmp retint - -retuint8: - movzbl %al, %eax - jmp retint - -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retstruct1b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movb %al,0(%ecx) - jmp epilogue - -retstruct2b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movw %ax,0(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret - -.LFE1: -.ffi_call_SYSV_end: - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl _ffi_closure_SYSV - -_ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ - movl %ebx, 8(%esp) -.LCFI7: - call L_ffi_closure_SYSV_inner$stub - movl 8(%esp), %ebx - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_SMALL_STRUCT_1B, %eax - je .Lcls_retstruct1b - cmpl $FFI_TYPE_SMALL_STRUCT_2B, %eax - je .Lcls_retstruct2b - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct1b: - movsbl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct2b: - movswl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct: - lea -8(%ebp),%esp - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl _ffi_closure_raw_SYSV - -_ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: -#endif - -.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 -L_ffi_closure_SYSV_inner$stub: - .indirect_symbol _ffi_closure_SYSV_inner - hlt ; hlt ; hlt ; hlt ; hlt - - -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 -LSCIE1: - .long 0x0 - .byte 0x1 - .ascii "zR\0" - .byte 0x1 - .byte 0x7c - .byte 0x8 - .byte 0x1 - .byte 0x10 - .byte 0xc - .byte 0x5 - .byte 0x4 - .byte 0x88 - .byte 0x1 - .align 2 -LECIE1: -.globl _ffi_call_SYSV.eh -_ffi_call_SYSV.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 - .long .LFB1-. - .set L$set$2,.LFE1-.LFB1 - .long L$set$2 - .byte 0x0 - .byte 0x4 - .set L$set$3,.LCFI0-.LFB1 - .long L$set$3 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$4,.LCFI1-.LCFI0 - .long L$set$4 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE1: -.globl _ffi_closure_SYSV.eh -_ffi_closure_SYSV.eh: -LSFDE2: - .set L$set$5,LEFDE2-LASFDE2 - .long L$set$5 -LASFDE2: - .long LASFDE2-EH_frame1 - .long .LFB2-. - .set L$set$6,.LFE2-.LFB2 - .long L$set$6 - .byte 0x0 - .byte 0x4 - .set L$set$7,.LCFI2-.LFB2 - .long L$set$7 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$8,.LCFI3-.LCFI2 - .long L$set$8 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE2: - -#if !FFI_NO_RAW_API - -.globl _ffi_closure_raw_SYSV.eh -_ffi_closure_raw_SYSV.eh: -LSFDE3: - .set L$set$10,LEFDE3-LASFDE3 - .long L$set$10 -LASFDE3: - .long LASFDE3-EH_frame1 - .long .LFB3-. - .set L$set$11,.LFE3-.LFB3 - .long L$set$11 - .byte 0x0 - .byte 0x4 - .set L$set$12,.LCFI4-.LFB3 - .long L$set$12 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$13,.LCFI5-.LCFI4 - .long L$set$13 - .byte 0xd - .byte 0x4 - .byte 0x4 - .set L$set$14,.LCFI6-.LCFI5 - .long L$set$14 - .byte 0x85 - .byte 0x3 - .align 2 -LEFDE3: - -#endif - -#endif /* ifndef __x86_64__ */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin64.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin64.S deleted file mode 100644 index 2f7394ef4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/darwin64.S +++ /dev/null @@ -1,416 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. - Copyright (c) 2008 Red Hat, Inc. - derived from unix64.S - - x86-64 Foreign Function Interface for Darwin. - - 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 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#ifdef __x86_64__ -#define LIBFFI_ASM -#include -#include - - .file "darwin64.S" -.text - -/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); - - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame - for this function. This has been allocated by ffi_call. We also - deallocate some of the stack that has been alloca'd. */ - - .align 3 - .globl _ffi_call_unix64 - -_ffi_call_unix64: -LUW0: - movq (%rsp), %r10 /* Load return address. */ - leaq (%rdi, %rsi), %rax /* Find local stack base. */ - movq %rdx, (%rax) /* Save flags. */ - movq %rcx, 8(%rax) /* Save raddr. */ - movq %rbp, 16(%rax) /* Save old frame pointer. */ - movq %r10, 24(%rax) /* Relocate return address. */ - movq %rax, %rbp /* Finalize local stack frame. */ -LUW1: - movq %rdi, %r10 /* Save a copy of the register area. */ - movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ - - /* Load up all argument registers. */ - movq (%r10), %rdi - movq 8(%r10), %rsi - movq 16(%r10), %rdx - movq 24(%r10), %rcx - movq 32(%r10), %r8 - movq 40(%r10), %r9 - testl %eax, %eax - jnz Lload_sse -Lret_from_load_sse: - - /* Deallocate the reg arg area. */ - leaq 176(%r10), %rsp - - /* Call the user function. */ - call *%r11 - - /* Deallocate stack arg area; local stack frame in redzone. */ - leaq 24(%rbp), %rsp - - movq 0(%rbp), %rcx /* Reload flags. */ - movq 8(%rbp), %rdi /* Reload raddr. */ - movq 16(%rbp), %rbp /* Reload old frame pointer. */ -LUW2: - - /* The first byte of the flags contains the FFI_TYPE. */ - movzbl %cl, %r10d - leaq Lstore_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lstore_table: - .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ - .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ - .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ - .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ - .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ - .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ - .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ - .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ - .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ - .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lst_void: - ret - .align 3 -Lst_uint8: - movzbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_sint8: - movsbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint16: - movzwq %ax, %rax - movq %rax, (%rdi) - .align 3 -Lst_sint16: - movswq %ax, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint32: - movl %eax, %eax - movq %rax, (%rdi) - .align 3 -Lst_sint32: - cltq - movq %rax, (%rdi) - ret - .align 3 -Lst_int64: - movq %rax, (%rdi) - ret - .align 3 -Lst_float: - movss %xmm0, (%rdi) - ret - .align 3 -Lst_double: - movsd %xmm0, (%rdi) - ret -Lst_ldouble: - fstpt (%rdi) - ret - .align 3 -Lst_struct: - leaq -20(%rsp), %rsi /* Scratch area in redzone. */ - - /* We have to locate the values now, and since we don't want to - write too much data into the user's return value, we spill the - value to a 16 byte scratch area first. Bits 8, 9, and 10 - control where the values are located. Only one of the three - bits will be set; see ffi_prep_cif_machdep for the pattern. */ - movd %xmm0, %r10 - movd %xmm1, %r11 - testl $0x100, %ecx - cmovnz %rax, %rdx - cmovnz %r10, %rax - testl $0x200, %ecx - cmovnz %r10, %rdx - testl $0x400, %ecx - cmovnz %r10, %rax - cmovnz %r11, %rdx - movq %rax, (%rsi) - movq %rdx, 8(%rsi) - - /* Bits 12-31 contain the true size of the structure. Copy from - the scratch area to the true destination. */ - shrl $12, %ecx - rep movsb - ret - - /* Many times we can avoid loading any SSE registers at all. - It's not worth an indirect jump to load the exact set of - SSE registers needed; zero or all is a good compromise. */ - .align 3 -LUW3: -Lload_sse: - movdqa 48(%r10), %xmm0 - movdqa 64(%r10), %xmm1 - movdqa 80(%r10), %xmm2 - movdqa 96(%r10), %xmm3 - movdqa 112(%r10), %xmm4 - movdqa 128(%r10), %xmm5 - movdqa 144(%r10), %xmm6 - movdqa 160(%r10), %xmm7 - jmp Lret_from_load_sse - -LUW4: - .align 3 - .globl _ffi_closure_unix64 - -_ffi_closure_unix64: -LUW5: - /* The carry flag is set by the trampoline iff SSE registers - are used. Don't clobber it before the branch instruction. */ - leaq -200(%rsp), %rsp -LUW6: - movq %rdi, (%rsp) - movq %rsi, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rcx, 24(%rsp) - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - jc Lsave_sse -Lret_from_save_sse: - - movq %r10, %rdi - leaq 176(%rsp), %rsi - movq %rsp, %rdx - leaq 208(%rsp), %rcx - call _ffi_closure_unix64_inner - - /* Deallocate stack frame early; return value is now in redzone. */ - addq $200, %rsp -LUW7: - - /* The first byte of the return value contains the FFI_TYPE. */ - movzbl %al, %r10d - leaq Lload_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lload_table: - .long Lld_void-Lload_table /* FFI_TYPE_VOID */ - .long Lld_int32-Lload_table /* FFI_TYPE_INT */ - .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ - .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ - .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ - .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ - .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ - .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ - .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ - .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ - .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ - .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ - .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ - .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ - .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lld_void: - ret - .align 3 -Lld_int8: - movzbl -24(%rsp), %eax - ret - .align 3 -Lld_int16: - movzwl -24(%rsp), %eax - ret - .align 3 -Lld_int32: - movl -24(%rsp), %eax - ret - .align 3 -Lld_int64: - movq -24(%rsp), %rax - ret - .align 3 -Lld_float: - movss -24(%rsp), %xmm0 - ret - .align 3 -Lld_double: - movsd -24(%rsp), %xmm0 - ret - .align 3 -Lld_ldouble: - fldt -24(%rsp) - ret - .align 3 -Lld_struct: - /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, - %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading - both rdx and xmm1 with the second word. For the remaining, - bit 8 set means xmm0 gets the second word, and bit 9 means - that rax gets the second word. */ - movq -24(%rsp), %rcx - movq -16(%rsp), %rdx - movq -16(%rsp), %xmm1 - testl $0x100, %eax - cmovnz %rdx, %rcx - movd %rcx, %xmm0 - testl $0x200, %eax - movq -24(%rsp), %rax - cmovnz %rdx, %rax - ret - - /* See the comment above Lload_sse; the same logic applies here. */ - .align 3 -LUW8: -Lsave_sse: - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) - jmp Lret_from_save_sse - -LUW9: -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ - .long L$set$0 -LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .byte 0x1 /* uleb128 0x1; Augmentation size */ - .byte 0x10 /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 /* uleb128 0x7 */ - .byte 0x8 /* uleb128 0x8 */ - .byte 0x90 /* DW_CFA_offset, column 0x10 */ - .byte 0x1 - .align 3 -LECIE1: - .globl _ffi_call_unix64.eh -_ffi_call_unix64.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 /* FDE CIE offset */ - .quad LUW0-. /* FDE initial location */ - .set L$set$2,LUW4-LUW0 /* FDE address range */ - .quad L$set$2 - .byte 0x0 /* Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$3,LUW1-LUW0 - .long L$set$3 - - /* New stack frame based off rbp. This is a itty bit of unwind - trickery in that the CFA *has* changed. There is no easy way - to describe it correctly on entry to the function. Fortunately, - it doesn't matter too much since at all points we can correctly - unwind back to ffi_call. Note that the location to which we - moved the return address is (the new) CFA-8, so from the - perspective of the unwind info, it hasn't moved. */ - .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ - .byte 0x6 - .byte 0x20 - .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ - .byte 0x2 - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$4,LUW2-LUW1 - .long L$set$4 - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 - .byte 0x8 - .byte 0xc0+6 /* DW_CFA_restore, %rbp */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$5,LUW3-LUW2 - .long L$set$5 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE1: - .globl _ffi_closure_unix64.eh -_ffi_closure_unix64.eh: -LSFDE3: - .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ - .long L$set$6 -LASFDE3: - .long LASFDE3-EH_frame1 /* FDE CIE offset */ - .quad LUW5-. /* FDE initial location */ - .set L$set$7,LUW9-LUW5 /* FDE address range */ - .quad L$set$7 - .byte 0x0 /* Augmentation size */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$8,LUW6-LUW5 - .long L$set$8 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 208,1 /* uleb128 208 */ - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$9,LUW7-LUW6 - .long L$set$9 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$10,LUW8-LUW7 - .long L$set$10 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE3: - .subsections_via_symbols - -#endif /* __x86_64__ */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi.c deleted file mode 100644 index fba8b0156..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi.c +++ /dev/null @@ -1,937 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2002 Bo Thorsen - Copyright (c) 2002 Roger Sayle - Copyright (C) 2008, 2010 Free Software Foundation, Inc. - - x86 Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__) - -#ifdef _WIN64 -#include -#endif - -#include -#include - -#include - - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -unsigned int ffi_prep_args(char *stack, extended_cif *ecif); -unsigned int ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; -#ifndef X86_WIN64 - const int cabi = ecif->cif->abi; - const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1; - unsigned int stack_args_count = 0; - void *p_stack_data[3]; - char *argp2 = stack; -#else - #define dir 1 -#endif - - argp = stack; - - if ((ecif->cif->flags == FFI_TYPE_STRUCT - || ecif->cif->flags == FFI_TYPE_MS_STRUCT) -#ifdef X86_WIN64 - && ((ecif->cif->rtype->size & (1 | 2 | 4 | 8)) == 0) -#endif - ) - { -#ifndef X86_WIN64 - /* For fastcall/thiscall/register this is first register-passed - argument. */ - if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_REGISTER) - { - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } -#endif - - *(void **) argp = ecif->rvalue; - argp += sizeof(void*); - } - - p_arg = ecif->cif->arg_types; - p_argv = ecif->avalue; - if (dir < 0) - { - const int nargs = ecif->cif->nargs - 1; - if (nargs > 0) - { - p_arg += nargs; - p_argv += nargs; - } - } - - for (i = ecif->cif->nargs; - 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*)); - - z = (*p_arg)->size; - -#ifdef X86_WIN64 - if (z > FFI_SIZEOF_ARG - || ((*p_arg)->type == FFI_TYPE_STRUCT - && (z & (1 | 2 | 4 | 8)) == 0) -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) -#endif - ) - { - z = FFI_SIZEOF_ARG; - *(void **)argp = *p_argv; - } - else if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - memcpy(argp, *p_argv, z); - } - else -#endif - if (z < FFI_SIZEOF_ARG) - { - z = FFI_SIZEOF_ARG; - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(ffi_arg *) argp = *(ffi_arg *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - -#ifndef X86_WIN64 - /* For thiscall/fastcall/register convention register-passed arguments - are the first two none-floating-point arguments with a size - smaller or equal to sizeof (void*). */ - if ((z == FFI_SIZEOF_ARG) - && ((cabi == FFI_REGISTER) - || (cabi == FFI_THISCALL && stack_args_count < 1) - || (cabi == FFI_FASTCALL && stack_args_count < 2)) - && ((*p_arg)->type != FFI_TYPE_FLOAT && (*p_arg)->type != FFI_TYPE_STRUCT) - ) - { - if (dir < 0 && stack_args_count > 2) - { - /* Iterating arguments backwards, so first register-passed argument - will be passed last. Shift temporary values to make place. */ - p_stack_data[0] = p_stack_data[1]; - p_stack_data[1] = p_stack_data[2]; - stack_args_count = 2; - } - - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } -#endif - -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - -#ifndef X86_WIN64 - /* We need to move the register-passed arguments for thiscall/fastcall/register - 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 */ - ffi_arg tmp = *(ffi_arg*) p_stack_data[0]; - *(ffi_arg*) p_stack_data[0] = *(ffi_arg*) p_stack_data[stack_args_count - 1]; - *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp; - } - - for (i = 0; i < stack_args_count; i++) - { - if (p_stack_data[i] != argp2) - { - ffi_arg tmp = *(ffi_arg*) p_stack_data[i]; - memmove (argp2 + FFI_SIZEOF_ARG, argp2, (size_t) ((char*) p_stack_data[i] - (char*)argp2)); - *(ffi_arg *) argp2 = tmp; - } - - argp2 += FFI_SIZEOF_ARG; - } - } - - return stack_args_count; -#endif - return 0; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - unsigned int i; - ffi_type **ptr; - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: -#ifdef X86_WIN64 - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: -#endif - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#ifndef X86_WIN64 -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif -#endif - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_UINT64: -#ifdef X86_WIN64 - case FFI_TYPE_POINTER: -#endif - cif->flags = FFI_TYPE_SINT64; - break; - - case FFI_TYPE_STRUCT: -#ifndef X86 - if (cif->rtype->size == 1) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */ - } - else if (cif->rtype->size == 2) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */ - } - else if (cif->rtype->size == 4) - { -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SMALL_STRUCT_4B; -#else - cif->flags = FFI_TYPE_INT; /* same as int type */ -#endif - } - else if (cif->rtype->size == 8) - { - cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ - } - else -#endif - { -#ifdef X86_WIN32 - if (cif->abi == FFI_MS_CDECL) - cif->flags = FFI_TYPE_MS_STRUCT; - else -#endif - cif->flags = FFI_TYPE_STRUCT; - /* allocate space for return value pointer */ - cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG); - } - break; - - default: -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SINT64; - break; - case FFI_TYPE_INT: - cif->flags = FFI_TYPE_SINT32; -#else - cif->flags = FFI_TYPE_INT; -#endif - break; - } - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - if (((*ptr)->alignment - 1) & cif->bytes) - cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); - cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG); - } - -#ifdef X86_WIN64 - /* ensure space for storing four registers */ - cif->bytes += 4 * FFI_SIZEOF_ARG; -#endif - -#ifndef X86_WIN32 -#ifndef X86_WIN64 - if (cif->abi == FFI_SYSV || cif->abi == FFI_UNIX64) -#endif - cif->bytes = (cif->bytes + 15) & ~0xF; -#endif - - return FFI_OK; -} - -#ifdef X86_WIN64 -extern int -ffi_call_win64(unsigned int (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#else -extern void -ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#endif - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - -#ifdef X86_WIN64 - if (rvalue == NULL - && cif->flags == FFI_TYPE_STRUCT - && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0)) - { - ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); - } -#else - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } -#endif - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifdef X86_WIN64 - case FFI_WIN64: - ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; -#else -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#else - case FFI_SYSV: - case FFI_MS_CDECL: -#endif - case FFI_STDCALL: - case FFI_THISCALL: - case FFI_FASTCALL: - case FFI_PASCAL: - case FFI_REGISTER: - ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - - -/** private members **/ - -/* The following __attribute__((regparm(1))) decorations will have no effect - on MSVC or SUNPRO_C -- standard conventions apply. */ -static unsigned int ffi_prep_incoming_args (char *stack, void **ret, - void** args, ffi_cif* cif); -void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *) - __attribute__ ((regparm(1))); -unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) - __attribute__ ((regparm(1))); -unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *) - __attribute__ ((regparm(1))); -#ifdef X86_WIN32 -void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *) - __attribute__ ((regparm(1))); -#endif -#ifndef X86_WIN64 -void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *); -void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *); -void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *); -void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *); -#else -void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); -#endif - -/* This function is jumped to by the trampoline */ - -#ifdef X86_WIN64 -void * FFI_HIDDEN -ffi_closure_win64_inner (ffi_closure *closure, void *args) { - ffi_cif *cif; - void **arg_area; - void *result; - void *resp = &result; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args(args, &resp, arg_area, cif); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - /* The result is returned in rax. This does the right thing for - result types except for floats; we have to 'mov xmm0, rax' in the - caller to correct this. - TODO: structure sizes of 3 5 6 7 are returned by reference, too!!! - */ - return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp; -} - -#else -unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) -ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) -{ - /* our various things... */ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args(args, respp, arg_area, cif); - - (closure->fun) (cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} - -unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) -ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args) -{ - /* our various things... */ - ffi_cif *cif; - void **arg_area; - unsigned int ret; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ret = ffi_prep_incoming_args(args, respp, arg_area, cif); - - (closure->fun) (cif, *respp, arg_area, closure->user_data); - - return ret; -} -#endif /* !X86_WIN64 */ - -static unsigned int -ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue, - ffi_cif *cif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; -#ifndef X86_WIN64 - const int cabi = cif->abi; - const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1; - const unsigned int max_stack_count = (cabi == FFI_THISCALL) ? 1 - : (cabi == FFI_FASTCALL) ? 2 - : (cabi == FFI_REGISTER) ? 3 - : 0; - unsigned int passed_regs = 0; - void *p_stack_data[3] = { stack - 1 }; -#else - #define dir 1 -#endif - - argp = stack; -#ifndef X86_WIN64 - argp += max_stack_count * FFI_SIZEOF_ARG; -#endif - - if ((cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT) -#ifdef X86_WIN64 - && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0) -#endif - ) - { -#ifndef X86_WIN64 - if (passed_regs < max_stack_count) - { - *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG)); - ++passed_regs; - } - else -#endif - { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } - } - -#ifndef X86_WIN64 - /* Do register arguments first */ - for (i = 0, p_arg = cif->arg_types; - 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; - - sz = (*p_arg)->size; - if(sz == 0 || sz > FFI_SIZEOF_ARG) - continue; - - p_stack_data[passed_regs] = avalue + i; - avalue[i] = stack + (passed_regs*FFI_SIZEOF_ARG); - ++passed_regs; - } -#endif - - p_arg = cif->arg_types; - p_argv = avalue; - if (dir < 0) - { - const int nargs = cif->nargs - 1; - if (nargs > 0) - { - p_arg += nargs; - p_argv += nargs; - } - } - - for (i = cif->nargs; - 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*)); - - z = (*p_arg)->size; - -#ifdef X86_WIN64 - if (z > FFI_SIZEOF_ARG - || ((*p_arg)->type == FFI_TYPE_STRUCT - && (z & (1 | 2 | 4 | 8)) == 0) -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) -#endif - ) - { - z = FFI_SIZEOF_ARG; - *p_argv = *(void **)argp; - } - else -#else - if (passed_regs > 0 - && z <= FFI_SIZEOF_ARG - && (p_argv == p_stack_data[0] - || p_argv == p_stack_data[1] - || p_argv == p_stack_data[2])) - { - /* Already assigned a register value */ - continue; - } - else -#endif - { - /* because we're little endian, this is what it turns into. */ - *p_argv = (void*) argp; - } - -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - - return (int)((size_t)argp - (size_t)stack); -} - -#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - void* __fun = (void*)(FUN); \ - void* __ctx = (void*)(CTX); \ - *(unsigned char*) &__tramp[0] = 0x41; \ - *(unsigned char*) &__tramp[1] = 0xbb; \ - *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \ - *(unsigned char*) &__tramp[6] = 0x48; \ - *(unsigned char*) &__tramp[7] = 0xb8; \ - *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \ - *(unsigned char *) &__tramp[16] = 0x49; \ - *(unsigned char *) &__tramp[17] = 0xba; \ - *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \ - *(unsigned char *) &__tramp[26] = 0x41; \ - *(unsigned char *) &__tramp[27] = 0xff; \ - *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \ - } - -/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char*) &__tramp[5] = 0xe9; \ - *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ - } - -#define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 49); \ - unsigned short __size = (unsigned short)(SIZE); \ - *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ - *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ - *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \ - *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \ - *(unsigned char*) &__tramp[13] = 0xb8; \ - *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \ - *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \ - *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \ - *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \ - *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \ - *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \ - *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \ - *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \ - *(unsigned char*) &__tramp[39] = 0xb8; \ - *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[44] = 0xe8; \ - *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \ - *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \ - *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \ - } - -#define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - *(unsigned char*) &__tramp[0] = 0x68; \ - *(unsigned int*) &__tramp[1] = __ctx; /* push __ctx */ \ - *(unsigned char*) &__tramp[5] = 0xe9; \ - *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ - } - -/* the cif must already be prep'ed */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ -#ifdef X86_WIN64 -#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE) -#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0) - if (cif->abi == FFI_WIN64) - { - int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3); - FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0], - &ffi_closure_win64, - codeloc, mask); - /* make sure we can execute here */ - } -#else - if (cif->abi == FFI_SYSV) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } - else if (cif->abi == FFI_REGISTER) - { - FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], - &ffi_closure_REGISTER, - (void*)codeloc); - } - else if (cif->abi == FFI_FASTCALL) - { - FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], - &ffi_closure_FASTCALL, - (void*)codeloc); - } - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], - &ffi_closure_THISCALL, - (void*)codeloc); - } - else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL) - { - FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], - &ffi_closure_STDCALL, - (void*)codeloc); - } -#ifdef X86_WIN32 - else if (cif->abi == FFI_MS_CDECL) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } -#endif /* X86_WIN32 */ -#endif /* !X86_WIN64 */ - else - { - return FFI_BAD_ABI; - } - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/* ------- Native raw API support -------------------------------- */ - -#if !FFI_NO_RAW_API - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc) -{ - int i; - - if (cif->abi != FFI_SYSV -#ifdef X86_WIN32 - && cif->abi != FFI_THISCALL -#endif - ) - return FFI_BAD_ABI; - - /* we currently don't support certain kinds of arguments for raw - closures. This should be implemented by a separate assembly - language routine, since it would require argument processing, - something we don't do now for performance. */ - - for (i = cif->nargs-1; i >= 0; i--) - { - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT); - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); - } - -#ifdef X86_WIN32 - if (cif->abi == FFI_SYSV) - { -#endif - FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, - codeloc); -#ifdef X86_WIN32 - } - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc, cif->bytes); - } -#endif - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -static unsigned int -ffi_prep_args_raw(char *stack, extended_cif *ecif) -{ - const ffi_cif *cif = ecif->cif; - unsigned int i, passed_regs = 0; - -#ifndef X86_WIN64 - const unsigned int abi = cif->abi; - const unsigned int max_regs = (abi == FFI_THISCALL) ? 1 - : (abi == FFI_FASTCALL) ? 2 - : (abi == FFI_REGISTER) ? 3 - : 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - 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; - - sz = cif->arg_types[i]->size; - if (sz == 0 || sz > FFI_SIZEOF_ARG) - continue; - - ++passed_regs; - } -#endif - - memcpy (stack, ecif->avalue, cif->bytes); - return passed_regs; -} - -/* we borrow this routine from libffi (it must be changed, though, to - * actually call the function passed in the first argument. as of - * libffi-1.20, this is not the case.) - */ - -void -ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) -{ - extended_cif ecif; - void **avalue = (void **)fake_avalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#else - case FFI_SYSV: - case FFI_MS_CDECL: -#endif -#ifndef X86_WIN64 - case FFI_STDCALL: - case FFI_THISCALL: - case FFI_FASTCALL: - case FFI_PASCAL: - case FFI_REGISTER: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - -#endif - -#endif /* !__x86_64__ || X86_WIN64 */ - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi64.c b/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi64.c deleted file mode 100644 index 5a5e04383..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffi64.c +++ /dev/null @@ -1,676 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 2013 The Written Word, Inc. - Copyright (c) 2011 Anthony Green - Copyright (c) 2008, 2010 Red Hat, Inc. - Copyright (c) 2002, 2007 Bo Thorsen - - x86-64 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include - -#ifdef __x86_64__ - -#define MAX_GPR_REGS 6 -#define MAX_SSE_REGS 8 - -#if defined(__INTEL_COMPILER) -#include "xmmintrin.h" -#define UINT128 __m128 -#else -#if defined(__SUNPRO_C) -#include -#define UINT128 __m128i -#else -#define UINT128 __int128_t -#endif -#endif - -union big_int_union -{ - UINT32 i32; - UINT64 i64; - UINT128 i128; -}; - -struct register_args -{ - /* Registers for argument passing. */ - UINT64 gpr[MAX_GPR_REGS]; - union big_int_union sse[MAX_SSE_REGS]; -}; - -extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void), unsigned ssecount); - -/* All reference to register classes here is identical to the code in - gcc/config/i386/i386.c. Do *not* change one without the other. */ - -/* Register class used for passing given 64bit part of the argument. - These represent classes as documented by the PS ABI, with the - exception of SSESF, SSEDF classes, that are basically SSE class, - just gcc will use SF or DFmode move instead of DImode to avoid - reformatting penalties. - - Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves - whenever possible (upper half does contain padding). */ -enum x86_64_reg_class - { - X86_64_NO_CLASS, - X86_64_INTEGER_CLASS, - X86_64_INTEGERSI_CLASS, - X86_64_SSE_CLASS, - X86_64_SSESF_CLASS, - X86_64_SSEDF_CLASS, - X86_64_SSEUP_CLASS, - X86_64_X87_CLASS, - X86_64_X87UP_CLASS, - X86_64_COMPLEX_X87_CLASS, - X86_64_MEMORY_CLASS - }; - -#define MAX_CLASSES 4 - -#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) - -/* x86-64 register passing implementation. See x86-64 ABI for details. Goal - of this code is to classify each 8bytes of incoming argument by the register - class and assign registers accordingly. */ - -/* Return the union class of CLASS1 and CLASS2. - See the x86-64 PS ABI for details. */ - -static enum x86_64_reg_class -merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) -{ - /* Rule #1: If both classes are equal, this is the resulting class. */ - if (class1 == class2) - return class1; - - /* Rule #2: If one of the classes is NO_CLASS, the resulting class is - the other class. */ - if (class1 == X86_64_NO_CLASS) - return class2; - if (class2 == X86_64_NO_CLASS) - return class1; - - /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ - if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ - if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) - || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) - return X86_64_INTEGERSI_CLASS; - if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS - || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) - return X86_64_INTEGER_CLASS; - - /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, - MEMORY is used. */ - if (class1 == X86_64_X87_CLASS - || class1 == X86_64_X87UP_CLASS - || class1 == X86_64_COMPLEX_X87_CLASS - || class2 == X86_64_X87_CLASS - || class2 == X86_64_X87UP_CLASS - || class2 == X86_64_COMPLEX_X87_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #6: Otherwise class SSE is used. */ - return X86_64_SSE_CLASS; -} - -/* Classify the argument of type TYPE and mode MODE. - CLASSES will be filled by the register class used to pass each word - of the operand. The number of words is returned. In case the parameter - should be passed in memory, 0 is returned. As a special case for zero - sized containers, classes[0] will be NO_CLASS and 1 is returned. - - See the x86-64 PS ABI for details. -*/ -static size_t -classify_argument (ffi_type *type, enum x86_64_reg_class classes[], - size_t byte_offset) -{ - switch (type->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_POINTER: - { - size_t size = byte_offset + type->size; - - if (size <= 4) - { - classes[0] = X86_64_INTEGERSI_CLASS; - return 1; - } - else if (size <= 8) - { - classes[0] = X86_64_INTEGER_CLASS; - return 1; - } - else if (size <= 12) - { - classes[0] = X86_64_INTEGER_CLASS; - classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else if (size <= 16) - { - classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else - FFI_ASSERT (0); - } - case FFI_TYPE_FLOAT: - if (!(byte_offset % 8)) - classes[0] = X86_64_SSESF_CLASS; - else - classes[0] = X86_64_SSE_CLASS; - return 1; - case FFI_TYPE_DOUBLE: - classes[0] = X86_64_SSEDF_CLASS; - return 1; -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - classes[0] = X86_64_X87_CLASS; - classes[1] = X86_64_X87UP_CLASS; - return 2; -#endif - case FFI_TYPE_STRUCT: - { - const size_t UNITS_PER_WORD = 8; - size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - ffi_type **ptr; - int i; - enum x86_64_reg_class subclasses[MAX_CLASSES]; - - /* If the struct is larger than 32 bytes, pass it on the stack. */ - if (type->size > 32) - return 0; - - for (i = 0; i < words; i++) - classes[i] = X86_64_NO_CLASS; - - /* Zero sized arrays or structures are NO_CLASS. We return 0 to - signalize memory class, so handle it as special case. */ - if (!words) - { - classes[0] = X86_64_NO_CLASS; - return 1; - } - - /* Merge the fields of structure. */ - for (ptr = type->elements; *ptr != NULL; ptr++) - { - size_t num; - - byte_offset = ALIGN (byte_offset, (*ptr)->alignment); - - num = classify_argument (*ptr, subclasses, byte_offset % 8); - if (num == 0) - return 0; - for (i = 0; i < num; i++) - { - size_t pos = byte_offset / 8; - classes[i + pos] = - merge_classes (subclasses[i], classes[i + pos]); - } - - byte_offset += (*ptr)->size; - } - - if (words > 2) - { - /* When size > 16 bytes, if the first one isn't - X86_64_SSE_CLASS or any other ones aren't - X86_64_SSEUP_CLASS, everything should be passed in - memory. */ - if (classes[0] != X86_64_SSE_CLASS) - return 0; - - for (i = 1; i < words; i++) - if (classes[i] != X86_64_SSEUP_CLASS) - return 0; - } - - /* Final merger cleanup. */ - for (i = 0; i < words; i++) - { - /* If one class is MEMORY, everything should be passed in - memory. */ - if (classes[i] == X86_64_MEMORY_CLASS) - return 0; - - /* The X86_64_SSEUP_CLASS should be always preceded by - X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */ - if (classes[i] == X86_64_SSEUP_CLASS - && classes[i - 1] != X86_64_SSE_CLASS - && classes[i - 1] != X86_64_SSEUP_CLASS) - { - /* The first one should never be X86_64_SSEUP_CLASS. */ - FFI_ASSERT (i != 0); - classes[i] = X86_64_SSE_CLASS; - } - - /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, - everything should be passed in memory. */ - if (classes[i] == X86_64_X87UP_CLASS - && (classes[i - 1] != X86_64_X87_CLASS)) - { - /* The first one should never be X86_64_X87UP_CLASS. */ - FFI_ASSERT (i != 0); - return 0; - } - } - return words; - } - - default: - FFI_ASSERT(0); - } - return 0; /* Never reached. */ -} - -/* Examine the argument and return set number of register required in each - class. Return zero iff parameter should be passed in memory, otherwise - the number of registers. */ - -static size_t -examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], - _Bool in_return, int *pngpr, int *pnsse) -{ - size_t n; - int i, ngpr, nsse; - - n = classify_argument (type, classes, 0); - if (n == 0) - return 0; - - ngpr = nsse = 0; - for (i = 0; i < n; ++i) - switch (classes[i]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - ngpr++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSESF_CLASS: - case X86_64_SSEDF_CLASS: - nsse++; - break; - case X86_64_NO_CLASS: - case X86_64_SSEUP_CLASS: - break; - case X86_64_X87_CLASS: - case X86_64_X87UP_CLASS: - case X86_64_COMPLEX_X87_CLASS: - return in_return != 0; - default: - abort (); - } - - *pngpr = ngpr; - *pnsse = nsse; - - return n; -} - -/* Perform machine dependent cif processing. */ - -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - int gprcount, ssecount, i, avn, ngpr, nsse, flags; - enum x86_64_reg_class classes[MAX_CLASSES]; - size_t bytes, n; - - gprcount = ssecount = 0; - - flags = cif->rtype->type; - if (flags != FFI_TYPE_VOID) - { - n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value is passed in memory. A pointer to that - memory is the first argument. Allocate a register for it. */ - gprcount++; - /* We don't have to do anything in asm for the return. */ - flags = FFI_TYPE_VOID; - } - else if (flags == FFI_TYPE_STRUCT) - { - /* Mark which registers the result appears in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]); - if (sse0 && !sse1) - flags |= 1 << 8; - else if (!sse0 && sse1) - flags |= 1 << 9; - else if (sse0 && sse1) - flags |= 1 << 10; - /* Mark the true size of the structure. */ - flags |= cif->rtype->size << 12; - } - } - - /* Go over all arguments and determine the way they should be passed. - If it's in a register and there is space for it, let that be so. If - not, add it's size to the stack byte count. */ - for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) - { - if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = cif->arg_types[i]->alignment; - - if (align < 8) - align = 8; - - bytes = ALIGN (bytes, align); - bytes += cif->arg_types[i]->size; - } - else - { - gprcount += ngpr; - ssecount += nsse; - } - } - if (ssecount) - flags |= 1 << 11; - cif->flags = flags; - cif->bytes = (unsigned)ALIGN (bytes, 8); - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - enum x86_64_reg_class classes[MAX_CLASSES]; - char *stack, *argp; - ffi_type **arg_types; - int gprcount, ssecount, ngpr, nsse, i, avn; - _Bool ret_in_memory; - struct register_args *reg_args; - - /* Can't call 32-bit mode from 64-bit mode. */ - FFI_ASSERT (cif->abi == FFI_UNIX64); - - /* If the return value is a struct and we don't have a return value - address then we need to make one. Note the setting of flags to - VOID above in ffi_prep_cif_machdep. */ - ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT - && (cif->flags & 0xff) == FFI_TYPE_VOID); - if (rvalue == NULL && ret_in_memory) - rvalue = alloca (cif->rtype->size); - - /* Allocate the space for the arguments, plus 4 words of temp space. */ - stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8); - reg_args = (struct register_args *) stack; - argp = stack + sizeof (struct register_args); - - gprcount = ssecount = 0; - - /* If the return value is passed in memory, add the pointer as the - first integer argument. */ - if (ret_in_memory) - reg_args->gpr[gprcount++] = (unsigned long) rvalue; - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - size_t n, size = arg_types[i]->size; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - memcpy (argp, avalue[i], size); - argp += size; - } - else - { - /* The argument is passed entirely in registers. */ - char *a = (char *) avalue[i]; - int j; - - for (j = 0; j < n; j++, a += 8, size -= 8) - { - switch (classes[j]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - /* Sign-extend integer arguments passed in general - purpose registers, to cope with the fact that - LLVM incorrectly assumes that this will be done - (the x86-64 PS ABI does not specify this). */ - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a); - break; - case FFI_TYPE_SINT16: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a); - break; - case FFI_TYPE_SINT32: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a); - break; - default: - reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); - } - gprcount++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSEDF_CLASS: - reg_args->sse[ssecount++].i64 = *(UINT64 *) a; - break; - case X86_64_SSESF_CLASS: - reg_args->sse[ssecount++].i32 = *(UINT32 *) a; - break; - default: - abort(); - } - } - } - } - - ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args), - cif->flags, rvalue, fn, ssecount); -} - - -extern void ffi_closure_unix64(void); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - volatile unsigned short *tramp; - - /* Sanity check on the cif ABI. */ - { - int abi = cif->abi; - if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))) - return FFI_BAD_ABI; - } - - tramp = (volatile unsigned short *) &closure->tramp[0]; - - tramp[0] = 0xbb49; /* mov , %r11 */ - *((unsigned long long * volatile) &tramp[1]) - = (unsigned long) ffi_closure_unix64; - tramp[5] = 0xba49; /* mov , %r10 */ - *((unsigned long long * volatile) &tramp[6]) - = (unsigned long) codeloc; - - /* Set the carry bit iff the function uses any sse registers. - This is clc or stc, together with the first byte of the jmp. */ - tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; - - tramp[11] = 0xe3ff; /* jmp *%r11 */ - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - -int -ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, - struct register_args *reg_args, char *argp) -{ - ffi_cif *cif; - void **avalue; - ffi_type **arg_types; - long i, avn; - int gprcount, ssecount, ngpr, nsse; - int ret; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - gprcount = ssecount = 0; - - ret = cif->rtype->type; - if (ret != FFI_TYPE_VOID) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - size_t n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value goes in memory. Arrange for the closure - return value to go directly back to the original caller. */ - rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++]; - /* We don't have to do anything in asm for the return. */ - ret = FFI_TYPE_VOID; - } - else if (ret == FFI_TYPE_STRUCT && n == 2) - { - /* Mark which register the second word of the structure goes in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = SSE_CLASS_P (classes[1]); - if (!sse0 && sse1) - ret |= 1 << 8; - else if (sse0 && !sse1) - ret |= 1 << 9; - } - } - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - size_t n; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - avalue[i] = argp; - argp += arg_types[i]->size; - } - /* If the argument is in a single register, or two consecutive - integer registers, then we can use that address directly. */ - else if (n == 1 - || (n == 2 && !(SSE_CLASS_P (classes[0]) - || SSE_CLASS_P (classes[1])))) - { - /* The argument is in a single register. */ - if (SSE_CLASS_P (classes[0])) - { - avalue[i] = ®_args->sse[ssecount]; - ssecount += n; - } - else - { - avalue[i] = ®_args->gpr[gprcount]; - gprcount += n; - } - } - /* Otherwise, allocate space to make them consecutive. */ - else - { - char *a = alloca (16); - int j; - - avalue[i] = a; - for (j = 0; j < n; j++, a += 8) - { - if (SSE_CLASS_P (classes[j])) - memcpy (a, ®_args->sse[ssecount++], 8); - else - memcpy (a, ®_args->gpr[gprcount++], 8); - } - } - } - - /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); - - /* Tell assembly how to perform return type promotions. */ - return ret; -} - -#endif /* __x86_64__ */ diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffitarget.h deleted file mode 100644 index ff0f71857..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/ffitarget.h +++ /dev/null @@ -1,152 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012, 2014 Anthony Green - Copyright (c) 1996-2003, 2010 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. - - Target configuration macros for x86 and x86-64. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -/* For code common to all platforms on x86 and x86_64. */ -#define X86_ANY - -#if defined (X86_64) && defined (__i386__) -#undef X86_64 -#define X86 -#endif - -#ifdef X86_WIN64 -#define FFI_SIZEOF_ARG 8 -#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */ -#endif - -#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION -#ifndef _MSC_VER -#define FFI_TARGET_HAS_COMPLEX_TYPE -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -#ifdef X86_WIN64 -#ifdef _MSC_VER -typedef unsigned __int64 ffi_arg; -typedef __int64 ffi_sarg; -#else -typedef unsigned long long ffi_arg; -typedef long long ffi_sarg; -#endif -#else -#if defined __x86_64__ && defined __ILP32__ -#define FFI_SIZEOF_ARG 8 -#define FFI_SIZEOF_JAVA_RAW 4 -typedef unsigned long long ffi_arg; -typedef long long ffi_sarg; -#else -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; -#endif -#endif - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - - /* ---- Intel x86 Win32 ---------- */ -#ifdef X86_WIN32 - FFI_SYSV, - FFI_STDCALL, - FFI_THISCALL, - FFI_FASTCALL, - FFI_MS_CDECL, - FFI_PASCAL, - FFI_REGISTER, - FFI_LAST_ABI, -#ifdef _MSC_VER - FFI_DEFAULT_ABI = FFI_MS_CDECL -#else - FFI_DEFAULT_ABI = FFI_SYSV -#endif - -#elif defined(X86_WIN64) - FFI_WIN64, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_WIN64 - -#else - /* ---- Intel x86 and AMD x86-64 - */ - FFI_SYSV, - FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ - FFI_THISCALL, - FFI_FASTCALL, - FFI_STDCALL, - FFI_PASCAL, - FFI_REGISTER, - FFI_LAST_ABI, -#if defined(__i386__) || defined(__i386) - FFI_DEFAULT_ABI = FFI_SYSV -#else - FFI_DEFAULT_ABI = FFI_UNIX64 -#endif -#endif -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) -#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) -#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) -#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) - -#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) -#define FFI_TRAMPOLINE_SIZE 24 -#define FFI_NATIVE_RAW_API 0 -#else -#ifdef X86_WIN32 -#define FFI_TRAMPOLINE_SIZE 52 -#else -#ifdef X86_WIN64 -#define FFI_TRAMPOLINE_SIZE 29 -#define FFI_NATIVE_RAW_API 0 -#define FFI_NO_RAW_API 1 -#else -#define FFI_TRAMPOLINE_SIZE 10 -#endif -#endif -#ifndef X86_WIN64 -#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ -#endif -#endif - -#endif - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/freebsd.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/freebsd.S deleted file mode 100644 index 97e0b4eb8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/freebsd.S +++ /dev/null @@ -1,463 +0,0 @@ -/* ----------------------------------------------------------------------- - freebsd.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc. - Copyright (c) 2008 Björn König - - X86 Foreign Function Interface for FreeBSD - - 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 __x86_64__ - -#define LIBFFI_ASM -#include -#include - -.text - -.globl ffi_prep_args - - .align 4 -.globl ffi_call_SYSV - .type ffi_call_SYSV,@function - -ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - /* Align the stack pointer to 16-bytes */ - andl $0xfffffff0, %esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $8,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue - -0: - call 1f - -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - .long retstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long retstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */ - -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint - -retsint16: - movswl %ax, %eax - jmp retint - -retuint8: - movzbl %al, %eax - jmp retint - -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retstruct1b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movb %al,0(%ecx) - jmp epilogue - -retstruct2b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movw %ax,0(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl ffi_closure_SYSV - .type ffi_closure_SYSV, @function - -ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ -#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__ - call ffi_closure_SYSV_inner -#else - movl %ebx, 8(%esp) -.LCFI7: - call 1f -1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx - call ffi_closure_SYSV_inner@PLT - movl 8(%esp), %ebx -#endif - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_SMALL_STRUCT_1B, %eax - je .Lcls_retstruct1b - cmpl $FFI_TYPE_SMALL_STRUCT_2B, %eax - je .Lcls_retstruct2b - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct1b: - movsbl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct2b: - movswl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct: - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - .size ffi_closure_SYSV, .-ffi_closure_SYSV - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl ffi_closure_raw_SYSV - .type ffi_closure_raw_SYSV, @function - -ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: - .size ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV -#endif - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ -#else - .ascii "\0" /* CIE Augmentation */ -#endif - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ -#ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ -#endif - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#ifdef __PIC__ - .long .LFB1-. /* FDE initial location */ -#else - .long .LFB1 /* FDE initial location */ -#endif - .long .LFE1-.LFB1 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .align 4 -.LEFDE1: -.LSFDE2: - .long .LEFDE2-.LASFDE2 /* FDE Length */ -.LASFDE2: - .long .LASFDE2-.Lframe1 /* FDE CIE offset */ -#ifdef __PIC__ - .long .LFB2-. /* FDE initial location */ -#else - .long .LFB2 -#endif - .long .LFE2-.LFB2 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI2-.LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI3-.LCFI2 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ -#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI7-.LCFI3 - .byte 0x83 /* DW_CFA_offset, column 0x3 */ - .byte 0xa /* .uleb128 0xa */ -#endif - .align 4 -.LEFDE2: - -#if !FFI_NO_RAW_API - -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ -#ifdef __PIC__ - .long .LFB3-. /* FDE initial location */ -#else - .long .LFB3 -#endif - .long .LFE3-.LFB3 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LFB3 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI5-.LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI6-.LCFI5 - .byte 0x86 /* DW_CFA_offset, column 0x6 */ - .byte 0x3 /* .uleb128 0x3 */ - .align 4 -.LEFDE3: - -#endif - -#endif /* ifndef __x86_64__ */ - - .section .note.GNU-stack,"",%progbits diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/sysv.S deleted file mode 100644 index 3bd5477e4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/sysv.S +++ /dev/null @@ -1,483 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 The Written Word, Inc. - - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. - - X86 Foreign Function Interface - - 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 __x86_64__ - -#define LIBFFI_ASM -#include -#include - -.text - -.globl ffi_prep_args - - .align 4 -.globl ffi_call_SYSV - .type ffi_call_SYSV,@function - -ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - /* Align the stack pointer to 16-bytes */ - andl $0xfffffff0, %esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $8,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue - -0: - call 1f - -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint - -retsint16: - movswl %ax, %eax - jmp retint - -retuint8: - movzbl %al, %eax - jmp retint - -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl ffi_closure_SYSV - .type ffi_closure_SYSV, @function - -ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx -#ifdef __SUNPRO_C - /* The SUNPRO compiler doesn't support GCC's regparm function - attribute, so we have to pass all three arguments to - ffi_closure_SYSV_inner on the stack. */ - movl %edx, 8(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, 4(%esp) /* &resp */ - movl %eax, (%esp) /* closure */ -#else - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ -#endif -#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__ - call ffi_closure_SYSV_inner -#else - movl %ebx, 8(%esp) -.LCFI7: - call 1f -1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx - call ffi_closure_SYSV_inner@PLT - movl 8(%esp), %ebx -#endif - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct: - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - .size ffi_closure_SYSV, .-ffi_closure_SYSV - -#if !FFI_NO_RAW_API - -/* Precalculate for e.g. the Solaris 10/x86 assembler. */ -#if FFI_TRAMPOLINE_SIZE == 10 -#define RAW_CLOSURE_CIF_OFFSET 12 -#define RAW_CLOSURE_FUN_OFFSET 16 -#define RAW_CLOSURE_USER_DATA_OFFSET 20 -#elif FFI_TRAMPOLINE_SIZE == 24 -#define RAW_CLOSURE_CIF_OFFSET 24 -#define RAW_CLOSURE_FUN_OFFSET 28 -#define RAW_CLOSURE_USER_DATA_OFFSET 32 -#else -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#endif -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl ffi_closure_raw_SYSV - .type ffi_closure_raw_SYSV, @function - -ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: - .size ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV -#endif - -#if defined __GNUC__ -/* Only emit dwarf unwind info when building with GNU toolchain. */ - -#if defined __PIC__ -# if defined __sun__ && defined __svr4__ -/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22 - doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */ -# define FDE_ENCODING 0x30 /* datarel */ -# define FDE_ENCODE(X) X@GOTOFF -# else -# define FDE_ENCODING 0x1b /* pcrel sdata4 */ -# if defined HAVE_AS_X86_PCREL -# define FDE_ENCODE(X) X-. -# else -# define FDE_ENCODE(X) X@rel -# endif -# endif -#else -# define FDE_ENCODING 0 /* absolute */ -# define FDE_ENCODE(X) X -#endif - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef HAVE_AS_ASCII_PSEUDO_OP -#ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ -#else - .ascii "\0" /* CIE Augmentation */ -#endif -#elif defined HAVE_AS_STRING_PSEUDO_OP -#ifdef __PIC__ - .string "zR" /* CIE Augmentation */ -#else - .string "" /* CIE Augmentation */ -#endif -#else -#error missing .ascii/.string -#endif - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ -#ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte FDE_ENCODING -#endif - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB1) /* FDE initial location */ - .long .LFE1-.LFB1 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .align 4 -.LEFDE1: -.LSFDE2: - .long .LEFDE2-.LASFDE2 /* FDE Length */ -.LASFDE2: - .long .LASFDE2-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB2) /* FDE initial location */ - .long .LFE2-.LFB2 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI2-.LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI3-.LCFI2 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ -#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI7-.LCFI3 - .byte 0x83 /* DW_CFA_offset, column 0x3 */ - .byte 0xa /* .uleb128 0xa */ -#endif - .align 4 -.LEFDE2: - -#if !FFI_NO_RAW_API - -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB3) /* FDE initial location */ - .long .LFE3-.LFB3 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LFB3 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI5-.LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI6-.LCFI5 - .byte 0x86 /* DW_CFA_offset, column 0x6 */ - .byte 0x3 /* .uleb128 0x3 */ - .align 4 -.LEFDE3: - -#endif -#endif - -#endif /* ifndef __x86_64__ */ - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/unix64.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/unix64.S deleted file mode 100644 index dcd6bc71e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/unix64.S +++ /dev/null @@ -1,432 +0,0 @@ -/* ----------------------------------------------------------------------- - unix64.S - Copyright (c) 2013 The Written Word, Inc. - - Copyright (c) 2008 Red Hat, Inc - - Copyright (c) 2002 Bo Thorsen - - x86-64 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#ifdef __x86_64__ -#define LIBFFI_ASM -#include -#include - -.text - -/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); - - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame - for this function. This has been allocated by ffi_call. We also - deallocate some of the stack that has been alloca'd. */ - - .align 2 - .globl ffi_call_unix64 - .type ffi_call_unix64,@function - -ffi_call_unix64: -.LUW0: - movq (%rsp), %r10 /* Load return address. */ - leaq (%rdi, %rsi), %rax /* Find local stack base. */ - movq %rdx, (%rax) /* Save flags. */ - movq %rcx, 8(%rax) /* Save raddr. */ - movq %rbp, 16(%rax) /* Save old frame pointer. */ - movq %r10, 24(%rax) /* Relocate return address. */ - movq %rax, %rbp /* Finalize local stack frame. */ -.LUW1: - movq %rdi, %r10 /* Save a copy of the register area. */ - movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ - - /* Load up all argument registers. */ - movq (%r10), %rdi - movq 8(%r10), %rsi - movq 16(%r10), %rdx - movq 24(%r10), %rcx - movq 32(%r10), %r8 - movq 40(%r10), %r9 - testl %eax, %eax - jnz .Lload_sse -.Lret_from_load_sse: - - /* Deallocate the reg arg area. */ - leaq 176(%r10), %rsp - - /* Call the user function. */ - call *%r11 - - /* Deallocate stack arg area; local stack frame in redzone. */ - leaq 24(%rbp), %rsp - - movq 0(%rbp), %rcx /* Reload flags. */ - movq 8(%rbp), %rdi /* Reload raddr. */ - movq 16(%rbp), %rbp /* Reload old frame pointer. */ -.LUW2: - - /* The first byte of the flags contains the FFI_TYPE. */ - movzbl %cl, %r10d - leaq .Lstore_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -.Lstore_table: - .long .Lst_void-.Lstore_table /* FFI_TYPE_VOID */ - .long .Lst_sint32-.Lstore_table /* FFI_TYPE_INT */ - .long .Lst_float-.Lstore_table /* FFI_TYPE_FLOAT */ - .long .Lst_double-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long .Lst_ldouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lst_uint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long .Lst_sint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long .Lst_uint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long .Lst_sint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long .Lst_uint32-.Lstore_table /* FFI_TYPE_UINT32 */ - .long .Lst_sint32-.Lstore_table /* FFI_TYPE_SINT32 */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long .Lst_struct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_POINTER */ - - .align 2 -.Lst_void: - ret - .align 2 - -.Lst_uint8: - movzbq %al, %rax - movq %rax, (%rdi) - ret - .align 2 -.Lst_sint8: - movsbq %al, %rax - movq %rax, (%rdi) - ret - .align 2 -.Lst_uint16: - movzwq %ax, %rax - movq %rax, (%rdi) - .align 2 -.Lst_sint16: - movswq %ax, %rax - movq %rax, (%rdi) - ret - .align 2 -.Lst_uint32: - movl %eax, %eax - movq %rax, (%rdi) - .align 2 -.Lst_sint32: - cltq - movq %rax, (%rdi) - ret - .align 2 -.Lst_int64: - movq %rax, (%rdi) - ret - - .align 2 -.Lst_float: - movss %xmm0, (%rdi) - ret - .align 2 -.Lst_double: - movsd %xmm0, (%rdi) - ret -.Lst_ldouble: - fstpt (%rdi) - ret - - .align 2 -.Lst_struct: - leaq -20(%rsp), %rsi /* Scratch area in redzone. */ - - /* We have to locate the values now, and since we don't want to - write too much data into the user's return value, we spill the - value to a 16 byte scratch area first. Bits 8, 9, and 10 - control where the values are located. Only one of the three - bits will be set; see ffi_prep_cif_machdep for the pattern. */ - movd %xmm0, %r10 - movd %xmm1, %r11 - testl $0x100, %ecx - cmovnz %rax, %rdx - cmovnz %r10, %rax - testl $0x200, %ecx - cmovnz %r10, %rdx - testl $0x400, %ecx - cmovnz %r10, %rax - cmovnz %r11, %rdx - movq %rax, (%rsi) - movq %rdx, 8(%rsi) - - /* Bits 12-31 contain the true size of the structure. Copy from - the scratch area to the true destination. */ - shrl $12, %ecx - rep movsb - ret - - /* Many times we can avoid loading any SSE registers at all. - It's not worth an indirect jump to load the exact set of - SSE registers needed; zero or all is a good compromise. */ - .align 2 -.LUW3: -.Lload_sse: - movdqa 48(%r10), %xmm0 - movdqa 64(%r10), %xmm1 - movdqa 80(%r10), %xmm2 - movdqa 96(%r10), %xmm3 - movdqa 112(%r10), %xmm4 - movdqa 128(%r10), %xmm5 - movdqa 144(%r10), %xmm6 - movdqa 160(%r10), %xmm7 - jmp .Lret_from_load_sse - -.LUW4: - .size ffi_call_unix64,.-ffi_call_unix64 - - .align 2 - .globl ffi_closure_unix64 - .type ffi_closure_unix64,@function - -ffi_closure_unix64: -.LUW5: - /* The carry flag is set by the trampoline iff SSE registers - are used. Don't clobber it before the branch instruction. */ - leaq -200(%rsp), %rsp -.LUW6: - movq %rdi, (%rsp) - movq %rsi, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rcx, 24(%rsp) - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - jc .Lsave_sse -.Lret_from_save_sse: - - movq %r10, %rdi - leaq 176(%rsp), %rsi - movq %rsp, %rdx - leaq 208(%rsp), %rcx - call ffi_closure_unix64_inner@PLT - - /* Deallocate stack frame early; return value is now in redzone. */ - addq $200, %rsp -.LUW7: - - /* The first byte of the return value contains the FFI_TYPE. */ - movzbl %al, %r10d - leaq .Lload_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -.Lload_table: - .long .Lld_void-.Lload_table /* FFI_TYPE_VOID */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_INT */ - .long .Lld_float-.Lload_table /* FFI_TYPE_FLOAT */ - .long .Lld_double-.Lload_table /* FFI_TYPE_DOUBLE */ - .long .Lld_ldouble-.Lload_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lld_int8-.Lload_table /* FFI_TYPE_UINT8 */ - .long .Lld_int8-.Lload_table /* FFI_TYPE_SINT8 */ - .long .Lld_int16-.Lload_table /* FFI_TYPE_UINT16 */ - .long .Lld_int16-.Lload_table /* FFI_TYPE_SINT16 */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_UINT32 */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_SINT32 */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_UINT64 */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_SINT64 */ - .long .Lld_struct-.Lload_table /* FFI_TYPE_STRUCT */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_POINTER */ - - .align 2 -.Lld_void: - ret - - .align 2 -.Lld_int8: - movzbl -24(%rsp), %eax - ret - .align 2 -.Lld_int16: - movzwl -24(%rsp), %eax - ret - .align 2 -.Lld_int32: - movl -24(%rsp), %eax - ret - .align 2 -.Lld_int64: - movq -24(%rsp), %rax - ret - - .align 2 -.Lld_float: - movss -24(%rsp), %xmm0 - ret - .align 2 -.Lld_double: - movsd -24(%rsp), %xmm0 - ret - .align 2 -.Lld_ldouble: - fldt -24(%rsp) - ret - - .align 2 -.Lld_struct: - /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, - %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading - both rdx and xmm1 with the second word. For the remaining, - bit 8 set means xmm0 gets the second word, and bit 9 means - that rax gets the second word. */ - movq -24(%rsp), %rcx - movq -16(%rsp), %rdx - movq -16(%rsp), %xmm1 - testl $0x100, %eax - cmovnz %rdx, %rcx - movd %rcx, %xmm0 - testl $0x200, %eax - movq -24(%rsp), %rax - cmovnz %rdx, %rax - ret - - /* See the comment above .Lload_sse; the same logic applies here. */ - .align 2 -.LUW8: -.Lsave_sse: - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) - jmp .Lret_from_save_sse - -.LUW9: - .size ffi_closure_unix64,.-ffi_closure_unix64 - -#ifdef __GNUC__ -/* Only emit DWARF unwind info when building with the GNU toolchain. */ - -#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE - .section .eh_frame,"a",@unwind -#else - .section .eh_frame,"a",@progbits -#endif -.Lframe1: - .long .LECIE1-.LSCIE1 /* CIE Length */ -.LSCIE1: - .long 0 /* CIE Identifier Tag */ - .byte 1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .uleb128 1 /* CIE Code Alignment Factor */ - .sleb128 -8 /* CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .uleb128 1 /* Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .uleb128 7 - .uleb128 8 - .byte 0x80+16 /* DW_CFA_offset, %rip offset 1*-8 */ - .uleb128 1 - .align 8 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if HAVE_AS_X86_PCREL - .long .LUW0-. /* FDE initial location */ -#else - .long .LUW0@rel -#endif - .long .LUW4-.LUW0 /* FDE address range */ - .uleb128 0x0 /* Augmentation size */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW1-.LUW0 - - /* New stack frame based off rbp. This is a itty bit of unwind - trickery in that the CFA *has* changed. There is no easy way - to describe it correctly on entry to the function. Fortunately, - it doesn't matter too much since at all points we can correctly - unwind back to ffi_call. Note that the location to which we - moved the return address is (the new) CFA-8, so from the - perspective of the unwind info, it hasn't moved. */ - .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ - .uleb128 6 - .uleb128 32 - .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ - .uleb128 2 - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW2-.LUW1 - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .uleb128 7 - .uleb128 8 - .byte 0xc0+6 /* DW_CFA_restore, %rbp */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW3-.LUW2 - .byte 0xb /* DW_CFA_restore_state */ - - .align 8 -.LEFDE1: -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ -#if HAVE_AS_X86_PCREL - .long .LUW5-. /* FDE initial location */ -#else - .long .LUW5@rel -#endif - .long .LUW9-.LUW5 /* FDE address range */ - .uleb128 0x0 /* Augmentation size */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW6-.LUW5 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 208 - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW7-.LUW6 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 8 - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW8-.LUW7 - .byte 0xb /* DW_CFA_restore_state */ - - .align 8 -.LEFDE3: - -#endif /* __GNUC__ */ - -#endif /* __x86_64__ */ - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/win32.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/win32.S deleted file mode 100644 index 3680bf538..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/win32.S +++ /dev/null @@ -1,1351 +0,0 @@ -/* ----------------------------------------------------------------------- - win32.S - Copyright (c) 2014 Anthony Green - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc. - Copyright (c) 2001 John Beniton - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2009 Daniel Witte - - - X86 Foreign Function Interface - - 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. - ----------------------------------------------------------------------- - */ - -#define LIBFFI_ASM -#include -#include - -#define CIF_BYTES_OFFSET 16 -#define CIF_FLAGS_OFFSET 20 - -#ifdef _MSC_VER - -#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3) - -.386 -.MODEL FLAT, C - -EXTRN ffi_closure_SYSV_inner:NEAR -EXTRN ffi_closure_WIN32_inner:NEAR - -_TEXT SEGMENT - -ffi_call_win32 PROC NEAR, - ffi_prep_args : NEAR PTR DWORD, - ecif : NEAR PTR DWORD, - cif_abi : DWORD, - cif_bytes : DWORD, - cif_flags : DWORD, - rvalue : NEAR PTR DWORD, - fn : NEAR PTR DWORD - - ;; Make room for all of the new args. - mov ecx, cif_bytes - sub esp, ecx - - mov eax, esp - - ;; Call ffi_prep_args - push ecif - push eax - call ffi_prep_args - add esp, 8 - - ;; Prepare registers - ;; EAX stores the number of register arguments - cmp eax, 0 - je fun - cmp eax, 3 - jl prepr_two_cmp - - mov ecx, esp - add esp, 12 - mov eax, DWORD PTR [ecx+8] - jmp prepr_two -prepr_two_cmp: - cmp eax, 2 - jl prepr_one_prep - mov ecx, esp - add esp, 8 -prepr_two: - mov edx, DWORD PTR [ecx+4] - jmp prepr_one -prepr_one_prep: - mov ecx, esp - add esp, 4 -prepr_one: - mov ecx, DWORD PTR [ecx] - cmp cif_abi, 7 ;; FFI_REGISTER - jne fun - - xchg ecx, eax - -fun: - ;; Call function - call fn - - ;; Load ecx with the return type code - mov ecx, cif_flags - - ;; If the return value pointer is NULL, assume no return value. - cmp rvalue, 0 - jne ca_jumptable - - ;; Even if there is no space for the return value, we are - ;; obliged to handle floating-point values. - cmp ecx, FFI_TYPE_FLOAT - jne ca_epilogue - fstp st(0) - - jmp ca_epilogue - -ca_jumptable: - jmp [ca_jumpdata + 4 * ecx] -ca_jumpdata: - ;; Do not insert anything here between label and jump table. - dd offset ca_epilogue ;; FFI_TYPE_VOID - dd offset ca_retint ;; FFI_TYPE_INT - dd offset ca_retfloat ;; FFI_TYPE_FLOAT - dd offset ca_retdouble ;; FFI_TYPE_DOUBLE - dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset ca_retuint8 ;; FFI_TYPE_UINT8 - dd offset ca_retsint8 ;; FFI_TYPE_SINT8 - dd offset ca_retuint16 ;; FFI_TYPE_UINT16 - dd offset ca_retsint16 ;; FFI_TYPE_SINT16 - dd offset ca_retint ;; FFI_TYPE_UINT32 - dd offset ca_retint ;; FFI_TYPE_SINT32 - dd offset ca_retint64 ;; FFI_TYPE_UINT64 - dd offset ca_retint64 ;; FFI_TYPE_SINT64 - dd offset ca_epilogue ;; FFI_TYPE_STRUCT - dd offset ca_retint ;; FFI_TYPE_POINTER - dd offset ca_retstruct1b ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset ca_retstruct2b ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset ca_epilogue ;; FFI_TYPE_MS_STRUCT - - /* Sign/zero extend as appropriate. */ -ca_retuint8: - movzx eax, al - jmp ca_retint - -ca_retsint8: - movsx eax, al - jmp ca_retint - -ca_retuint16: - movzx eax, ax - jmp ca_retint - -ca_retsint16: - movsx eax, ax - jmp ca_retint - -ca_retint: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], eax - jmp ca_epilogue - -ca_retint64: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], eax - mov [ecx + 4], edx - jmp ca_epilogue - -ca_retfloat: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp DWORD PTR [ecx] - jmp ca_epilogue - -ca_retdouble: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp QWORD PTR [ecx] - jmp ca_epilogue - -ca_retlongdouble: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp TBYTE PTR [ecx] - jmp ca_epilogue - -ca_retstruct1b: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], al - jmp ca_epilogue - -ca_retstruct2b: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], ax - jmp ca_epilogue - -ca_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_call_win32 ENDP - -ffi_closure_THISCALL PROC NEAR - ;; Insert the register argument on the stack as the first argument - xchg DWORD PTR [esp+4], ecx - xchg DWORD PTR [esp], ecx - push ecx - jmp ffi_closure_STDCALL -ffi_closure_THISCALL ENDP - -ffi_closure_FASTCALL PROC NEAR - ;; Insert the 2 register arguments on the stack as the first argument - xchg DWORD PTR [esp+4], edx - xchg DWORD PTR [esp], ecx - push edx - push ecx - jmp ffi_closure_STDCALL -ffi_closure_FASTCALL ENDP - -ffi_closure_REGISTER PROC NEAR - ;; Insert the 3 register arguments on the stack as the first argument - push eax - xchg DWORD PTR [esp+8], ecx - xchg DWORD PTR [esp+4], edx - push ecx - push edx - jmp ffi_closure_STDCALL -ffi_closure_REGISTER ENDP - -ffi_closure_SYSV PROC NEAR FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. - - sub esp, 40 - lea edx, [ebp - 24] - mov [ebp - 12], edx ;; resp - lea edx, [ebp + 8] -stub:: - mov [esp + 8], edx ;; args - lea edx, [ebp - 12] - mov [esp + 4], edx ;; &resp - mov [esp], eax ;; closure - call ffi_closure_SYSV_inner - mov ecx, [ebp - 12] - -cs_jumptable: - jmp [cs_jumpdata + 4 * eax] -cs_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cs_epilogue ;; FFI_TYPE_VOID - dd offset cs_retint ;; FFI_TYPE_INT - dd offset cs_retfloat ;; FFI_TYPE_FLOAT - dd offset cs_retdouble ;; FFI_TYPE_DOUBLE - dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cs_retuint8 ;; FFI_TYPE_UINT8 - dd offset cs_retsint8 ;; FFI_TYPE_SINT8 - dd offset cs_retuint16 ;; FFI_TYPE_UINT16 - dd offset cs_retsint16 ;; FFI_TYPE_SINT16 - dd offset cs_retint ;; FFI_TYPE_UINT32 - dd offset cs_retint ;; FFI_TYPE_SINT32 - dd offset cs_retint64 ;; FFI_TYPE_UINT64 - dd offset cs_retint64 ;; FFI_TYPE_SINT64 - dd offset cs_retstruct ;; FFI_TYPE_STRUCT - dd offset cs_retint ;; FFI_TYPE_POINTER - dd offset cs_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cs_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset cs_retmsstruct ;; FFI_TYPE_MS_STRUCT - -cs_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cs_epilogue - -cs_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cs_epilogue - -cs_retuint16: - movzx eax, WORD PTR [ecx] - jmp cs_epilogue - -cs_retsint16: - movsx eax, WORD PTR [ecx] - jmp cs_epilogue - -cs_retint: - mov eax, [ecx] - jmp cs_epilogue - -cs_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cs_epilogue - -cs_retfloat: - fld DWORD PTR [ecx] - jmp cs_epilogue - -cs_retdouble: - fld QWORD PTR [ecx] - jmp cs_epilogue - -cs_retlongdouble: - fld TBYTE PTR [ecx] - jmp cs_epilogue - -cs_retstruct: - ;; Caller expects us to pop struct return value pointer hidden arg. - ;; Epilogue code is autogenerated. - ret 4 - -cs_retmsstruct: - ;; Caller expects us to return a pointer to the real return value. - mov eax, ecx - ;; Caller doesn't expects us to pop struct return value pointer hidden arg. - jmp cs_epilogue - -cs_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_closure_SYSV ENDP - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) - -ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME - sub esp, 36 - mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif - mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data - mov [esp + 12], edx - lea edx, [ebp + 12] - jmp stubraw -ffi_closure_raw_THISCALL ENDP - -ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. - - sub esp, 40 - mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif - mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data - mov [esp + 12], edx ;; user_data - lea edx, [ebp + 8] -stubraw:: - mov [esp + 8], edx ;; raw_args - lea edx, [ebp - 24] - mov [esp + 4], edx ;; &res - mov [esp], esi ;; cif - call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun - mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags - lea ecx, [ebp - 24] - -cr_jumptable: - jmp [cr_jumpdata + 4 * eax] -cr_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cr_epilogue ;; FFI_TYPE_VOID - dd offset cr_retint ;; FFI_TYPE_INT - dd offset cr_retfloat ;; FFI_TYPE_FLOAT - dd offset cr_retdouble ;; FFI_TYPE_DOUBLE - dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cr_retuint8 ;; FFI_TYPE_UINT8 - dd offset cr_retsint8 ;; FFI_TYPE_SINT8 - dd offset cr_retuint16 ;; FFI_TYPE_UINT16 - dd offset cr_retsint16 ;; FFI_TYPE_SINT16 - dd offset cr_retint ;; FFI_TYPE_UINT32 - dd offset cr_retint ;; FFI_TYPE_SINT32 - dd offset cr_retint64 ;; FFI_TYPE_UINT64 - dd offset cr_retint64 ;; FFI_TYPE_SINT64 - dd offset cr_epilogue ;; FFI_TYPE_STRUCT - dd offset cr_retint ;; FFI_TYPE_POINTER - dd offset cr_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cr_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset cr_epilogue ;; FFI_TYPE_MS_STRUCT - -cr_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cr_epilogue - -cr_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cr_epilogue - -cr_retuint16: - movzx eax, WORD PTR [ecx] - jmp cr_epilogue - -cr_retsint16: - movsx eax, WORD PTR [ecx] - jmp cr_epilogue - -cr_retint: - mov eax, [ecx] - jmp cr_epilogue - -cr_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cr_epilogue - -cr_retfloat: - fld DWORD PTR [ecx] - jmp cr_epilogue - -cr_retdouble: - fld QWORD PTR [ecx] - jmp cr_epilogue - -cr_retlongdouble: - fld TBYTE PTR [ecx] - jmp cr_epilogue - -cr_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_closure_raw_SYSV ENDP - -#endif /* !FFI_NO_RAW_API */ - -ffi_closure_STDCALL PROC NEAR FORCEFRAME - mov eax, [esp] ;; the ffi_closure ctx passed by the trampoline. - - sub esp, 40 - lea edx, [ebp - 24] - mov [ebp - 12], edx ;; resp - lea edx, [ebp + 12] ;; account for stub return address on stack - mov [esp + 8], edx ;; args - lea edx, [ebp - 12] - mov [esp + 4], edx ;; &resp - mov [esp], eax ;; closure - call ffi_closure_WIN32_inner - mov ecx, [ebp - 12] - - xchg [ebp + 4], eax ;;xchg size of stack parameters and ffi_closure ctx - mov eax, DWORD PTR [eax + CLOSURE_CIF_OFFSET] - mov eax, DWORD PTR [eax + CIF_FLAGS_OFFSET] - -cd_jumptable: - jmp [cd_jumpdata + 4 * eax] -cd_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cd_epilogue ;; FFI_TYPE_VOID - dd offset cd_retint ;; FFI_TYPE_INT - dd offset cd_retfloat ;; FFI_TYPE_FLOAT - dd offset cd_retdouble ;; FFI_TYPE_DOUBLE - dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cd_retuint8 ;; FFI_TYPE_UINT8 - dd offset cd_retsint8 ;; FFI_TYPE_SINT8 - dd offset cd_retuint16 ;; FFI_TYPE_UINT16 - dd offset cd_retsint16 ;; FFI_TYPE_SINT16 - dd offset cd_retint ;; FFI_TYPE_UINT32 - dd offset cd_retint ;; FFI_TYPE_SINT32 - dd offset cd_retint64 ;; FFI_TYPE_UINT64 - dd offset cd_retint64 ;; FFI_TYPE_SINT64 - dd offset cd_epilogue ;; FFI_TYPE_STRUCT - dd offset cd_retint ;; FFI_TYPE_POINTER - dd offset cd_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cd_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B - -cd_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cd_epilogue - -cd_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cd_epilogue - -cd_retuint16: - movzx eax, WORD PTR [ecx] - jmp cd_epilogue - -cd_retsint16: - movsx eax, WORD PTR [ecx] - jmp cd_epilogue - -cd_retint: - mov eax, [ecx] - jmp cd_epilogue - -cd_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cd_epilogue - -cd_retfloat: - fld DWORD PTR [ecx] - jmp cd_epilogue - -cd_retdouble: - fld QWORD PTR [ecx] - jmp cd_epilogue - -cd_retlongdouble: - fld TBYTE PTR [ecx] - jmp cd_epilogue - -cd_epilogue: - mov esp, ebp - pop ebp - mov ecx, [esp + 4] ;; Return address - add esp, [esp] ;; Parameters stack size - add esp, 8 - jmp ecx -ffi_closure_STDCALL ENDP - -_TEXT ENDS -END - -#else - -#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) - -#if defined(SYMBOL_UNDERSCORE) -#define USCORE_SYMBOL(x) _##x -#else -#define USCORE_SYMBOL(x) x -#endif - .text - - # This assumes we are using gas. - .balign 16 -FFI_HIDDEN(ffi_call_win32) - .globl USCORE_SYMBOL(ffi_call_win32) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_call_win32; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_call_win32): -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - # Make room for all of the new args. - movl 20(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - # Call ffi_prep_args - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - addl $8,%esp - - # Prepare registers - # EAX stores the number of register arguments - cmpl $0, %eax - je .fun - cmpl $3, %eax - jl .prepr_two_cmp - - movl %esp, %ecx - addl $12, %esp - movl 8(%ecx), %eax - jmp .prepr_two -.prepr_two_cmp: - cmpl $2, %eax - jl .prepr_one_prep - movl %esp, %ecx - addl $8, %esp -.prepr_two: - movl 4(%ecx), %edx - jmp .prepr_one -.prepr_one_prep: - movl %esp, %ecx - addl $4, %esp -.prepr_one: - movl (%ecx), %ecx - cmpl $7, 16(%ebp) # FFI_REGISTER - jne .fun - - xchgl %eax, %ecx - -.fun: - # FIXME: Align the stack to a 128-bit boundary to avoid - # potential performance hits. - - # Call function - call *32(%ebp) - - # stdcall functions pop arguments off the stack themselves - - # Load %ecx with the return type code - movl 24(%ebp),%ecx - - # If the return value pointer is NULL, assume no return value. - cmpl $0,28(%ebp) - jne 0f - - # Even if there is no space for the return value, we are - # obliged to handle floating-point values. - cmpl $FFI_TYPE_FLOAT,%ecx - jne .Lnoretval - fstp %st(0) - - jmp .Lepilogue - -0: - call 1f - # Do not insert anything here between the call and the jump table. -.Lstore_table: - .long .Lnoretval-.Lstore_table /* FFI_TYPE_VOID */ - .long .Lretint-.Lstore_table /* FFI_TYPE_INT */ - .long .Lretfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long .Lretdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long .Lretlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lretuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long .Lretsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long .Lretuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long .Lretsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long .Lretint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long .Lretint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long .Lretint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long .Lretint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long .Lretstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long .Lretint-.Lstore_table /* FFI_TYPE_POINTER */ - .long .Lretstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lretstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lretstruct4b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lretstruct-.Lstore_table /* FFI_TYPE_MS_STRUCT */ -1: - shl $2, %ecx - add (%esp),%ecx - mov (%ecx),%ecx - add (%esp),%ecx - add $4, %esp - jmp *%ecx - - /* Sign/zero extend as appropriate. */ -.Lretsint8: - movsbl %al, %eax - jmp .Lretint - -.Lretsint16: - movswl %ax, %eax - jmp .Lretint - -.Lretuint8: - movzbl %al, %eax - jmp .Lretint - -.Lretuint16: - movzwl %ax, %eax - jmp .Lretint - -.Lretint: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretfloat: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstps (%ecx) - jmp .Lepilogue - -.Lretdouble: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstpl (%ecx) - jmp .Lepilogue - -.Lretlongdouble: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstpt (%ecx) - jmp .Lepilogue - -.Lretint64: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp .Lepilogue - -.Lretstruct1b: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movb %al,0(%ecx) - jmp .Lepilogue - -.Lretstruct2b: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movw %ax,0(%ecx) - jmp .Lepilogue - -.Lretstruct4b: - # Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretstruct: - # Nothing to do! - -.Lnoretval: -.Lepilogue: - movl %ebp,%esp - popl %ebp - ret -.ffi_call_win32_end: - .balign 16 -FFI_HIDDEN(ffi_closure_THISCALL) - .globl USCORE_SYMBOL(ffi_closure_THISCALL) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_THISCALL): - /* Insert the register argument on the stack as the first argument */ - xchg %ecx, 4(%esp) - xchg %ecx, (%esp) - push %ecx - jmp .ffi_closure_STDCALL_internal - - .balign 16 -FFI_HIDDEN(ffi_closure_FASTCALL) - .globl USCORE_SYMBOL(ffi_closure_FASTCALL) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_FASTCALL; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_FASTCALL): - /* Insert the 2 register arguments on the stack as the first two arguments */ - xchg %edx, 4(%esp) - xchg %ecx, (%esp) - push %edx - push %ecx - jmp .ffi_closure_STDCALL_internal -FFI_HIDDEN(ffi_closure_REGISTER) - .globl USCORE_SYMBOL(ffi_closure_REGISTER) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_REGISTER; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_REGISTER): - /* Insert the 3 register arguments on the stack as the first two arguments */ - push %eax - xchg %ecx, 8(%esp) - xchg %edx, 4(%esp) - push %ecx - push %edx - jmp .ffi_closure_STDCALL_internal - -.LFE1: - # This assumes we are using gas. - .balign 16 -FFI_HIDDEN(ffi_closure_SYSV) -#if defined(X86_WIN32) - .globl USCORE_SYMBOL(ffi_closure_SYSV) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_SYSV; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_SYSV): -#endif -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ -#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__) - call USCORE_SYMBOL(ffi_closure_SYSV_inner) -#elif defined(X86_DARWIN) - calll L_ffi_closure_SYSV_inner$stub -#else - movl %ebx, 8(%esp) - call 1f -1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx - call ffi_closure_SYSV_inner@PLT - movl 8(%esp), %ebx -#endif - movl -12(%ebp), %ecx - -0: - call 1f - # Do not insert anything here between the call and the jump table. -.Lcls_store_table: - .long .Lcls_noretval-.Lcls_store_table /* FFI_TYPE_VOID */ - .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_INT */ - .long .Lcls_retfloat-.Lcls_store_table /* FFI_TYPE_FLOAT */ - .long .Lcls_retdouble-.Lcls_store_table /* FFI_TYPE_DOUBLE */ - .long .Lcls_retldouble-.Lcls_store_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lcls_retuint8-.Lcls_store_table /* FFI_TYPE_UINT8 */ - .long .Lcls_retsint8-.Lcls_store_table /* FFI_TYPE_SINT8 */ - .long .Lcls_retuint16-.Lcls_store_table /* FFI_TYPE_UINT16 */ - .long .Lcls_retsint16-.Lcls_store_table /* FFI_TYPE_SINT16 */ - .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_UINT32 */ - .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_SINT32 */ - .long .Lcls_retllong-.Lcls_store_table /* FFI_TYPE_UINT64 */ - .long .Lcls_retllong-.Lcls_store_table /* FFI_TYPE_SINT64 */ - .long .Lcls_retstruct-.Lcls_store_table /* FFI_TYPE_STRUCT */ - .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_POINTER */ - .long .Lcls_retstruct1-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lcls_retstruct2-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lcls_retstruct4-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lcls_retmsstruct-.Lcls_store_table /* FFI_TYPE_MS_STRUCT */ - -1: - shl $2, %eax - add (%esp),%eax - mov (%eax),%eax - add (%esp),%eax - add $4, %esp - jmp *%eax - - /* Sign/zero extend as appropriate. */ -.Lcls_retsint8: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retsint16: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint8: - movzbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint16: - movzwl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue - -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue - -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue - -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue - -.Lcls_retstruct1: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct2: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct4: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct: - # Caller expects us to pop struct return value pointer hidden arg. - movl %ebp, %esp - popl %ebp - ret $0x4 - -.Lcls_retmsstruct: - # Caller expects us to return a pointer to the real return value. - mov %ecx, %eax - # Caller doesn't expects us to pop struct return value pointer hidden arg. - jmp .Lcls_epilogue - -.Lcls_noretval: -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.ffi_closure_SYSV_end: -.LFE3: - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) - -#ifdef X86_WIN32 - .balign 16 -FFI_HIDDEN(ffi_closure_raw_THISCALL) - .globl USCORE_SYMBOL(ffi_closure_raw_THISCALL) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_raw_THISCALL): - pushl %ebp - movl %esp, %ebp - pushl %esi - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */ - jmp .stubraw -#endif /* X86_WIN32 */ - - # This assumes we are using gas. - .balign 16 -#if defined(X86_WIN32) - .globl USCORE_SYMBOL(ffi_closure_raw_SYSV) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_raw_SYSV): -#endif /* defined(X86_WIN32) */ -.LFB4: - pushl %ebp -.LCFI6: - movl %esp, %ebp -.LCFI7: - pushl %esi -.LCFI8: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ -.stubraw: - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ -0: - call 1f - # Do not insert anything here between the call and the jump table. -.Lrcls_store_table: - .long .Lrcls_noretval-.Lrcls_store_table /* FFI_TYPE_VOID */ - .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_INT */ - .long .Lrcls_retfloat-.Lrcls_store_table /* FFI_TYPE_FLOAT */ - .long .Lrcls_retdouble-.Lrcls_store_table /* FFI_TYPE_DOUBLE */ - .long .Lrcls_retldouble-.Lrcls_store_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lrcls_retuint8-.Lrcls_store_table /* FFI_TYPE_UINT8 */ - .long .Lrcls_retsint8-.Lrcls_store_table /* FFI_TYPE_SINT8 */ - .long .Lrcls_retuint16-.Lrcls_store_table /* FFI_TYPE_UINT16 */ - .long .Lrcls_retsint16-.Lrcls_store_table /* FFI_TYPE_SINT16 */ - .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_UINT32 */ - .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_SINT32 */ - .long .Lrcls_retllong-.Lrcls_store_table /* FFI_TYPE_UINT64 */ - .long .Lrcls_retllong-.Lrcls_store_table /* FFI_TYPE_SINT64 */ - .long .Lrcls_retstruct-.Lrcls_store_table /* FFI_TYPE_STRUCT */ - .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_POINTER */ - .long .Lrcls_retstruct1-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lrcls_retstruct2-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lrcls_retstruct4-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lrcls_retstruct-.Lrcls_store_table /* FFI_TYPE_MS_STRUCT */ -1: - shl $2, %eax - add (%esp),%eax - mov (%eax),%eax - add (%esp),%eax - add $4, %esp - jmp *%eax - - /* Sign/zero extend as appropriate. */ -.Lrcls_retsint8: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retsint16: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint8: - movzbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint16: - movzwl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue - -.Lrcls_retstruct1: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct2: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct4: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct: - # Nothing to do! - -.Lrcls_noretval: -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.ffi_closure_raw_SYSV_end: -.LFE4: - -#endif /* !FFI_NO_RAW_API */ - - # This assumes we are using gas. - .balign 16 -FFI_HIDDEN(ffi_closure_STDCALL) - .globl USCORE_SYMBOL(ffi_closure_STDCALL) -#if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef -#endif -USCORE_SYMBOL(ffi_closure_STDCALL): -.ffi_closure_STDCALL_internal: - /* ffi_closure ctx is at top of the stack */ - movl (%esp), %eax -.LFB5: - pushl %ebp -.LCFI9: - movl %esp, %ebp -.LCFI10: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 12(%ebp), %edx /* account for stub return address on stack */ - movl %edx, 4(%esp) /* args */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ -#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__) - call USCORE_SYMBOL(ffi_closure_WIN32_inner) -#elif defined(X86_DARWIN) - calll L_ffi_closure_WIN32_inner$stub -#else - movl %ebx, 8(%esp) - call 1f -1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx - call ffi_closure_WIN32_inner@PLT - movl 8(%esp), %ebx -#endif - movl -12(%ebp), %ecx -0: - xchgl 4(%ebp), %eax /* xchg size of stack parameters and ffi_closure ctx */ - movl CLOSURE_CIF_OFFSET(%eax), %eax - movl CIF_FLAGS_OFFSET(%eax), %eax - - call 1f - # Do not insert anything here between the call and the jump table. -.Lscls_store_table: - .long .Lscls_noretval-.Lscls_store_table /* FFI_TYPE_VOID */ - .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_INT */ - .long .Lscls_retfloat-.Lscls_store_table /* FFI_TYPE_FLOAT */ - .long .Lscls_retdouble-.Lscls_store_table /* FFI_TYPE_DOUBLE */ - .long .Lscls_retldouble-.Lscls_store_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lscls_retuint8-.Lscls_store_table /* FFI_TYPE_UINT8 */ - .long .Lscls_retsint8-.Lscls_store_table /* FFI_TYPE_SINT8 */ - .long .Lscls_retuint16-.Lscls_store_table /* FFI_TYPE_UINT16 */ - .long .Lscls_retsint16-.Lscls_store_table /* FFI_TYPE_SINT16 */ - .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_UINT32 */ - .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_SINT32 */ - .long .Lscls_retllong-.Lscls_store_table /* FFI_TYPE_UINT64 */ - .long .Lscls_retllong-.Lscls_store_table /* FFI_TYPE_SINT64 */ - .long .Lscls_retstruct-.Lscls_store_table /* FFI_TYPE_STRUCT */ - .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_POINTER */ - .long .Lscls_retstruct1-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lscls_retstruct2-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lscls_retstruct4-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */ -1: - shl $2, %eax - add (%esp),%eax - mov (%eax),%eax - add (%esp),%eax - add $4, %esp - jmp *%eax - - /* Sign/zero extend as appropriate. */ -.Lscls_retsint8: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retsint16: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint8: - movzbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint16: - movzwl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retint: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retfloat: - flds (%ecx) - jmp .Lscls_epilogue - -.Lscls_retdouble: - fldl (%ecx) - jmp .Lscls_epilogue - -.Lscls_retldouble: - fldt (%ecx) - jmp .Lscls_epilogue - -.Lscls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lscls_epilogue - -.Lscls_retstruct1: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct2: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct4: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct: - # Nothing to do! - -.Lscls_noretval: -.Lscls_epilogue: - movl %ebp, %esp - popl %ebp - movl 4(%esp), %ecx /* Return address */ - addl (%esp), %esp /* Parameters stack size */ - addl $8, %esp - jmp *%ecx -.ffi_closure_STDCALL_end: -.LFE5: - -#if defined(X86_DARWIN) -.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 -L_ffi_closure_SYSV_inner$stub: - .indirect_symbol _ffi_closure_SYSV_inner - hlt ; hlt ; hlt ; hlt ; hlt -L_ffi_closure_WIN32_inner$stub: - .indirect_symbol _ffi_closure_WIN32_inner - hlt ; hlt ; hlt ; hlt ; hlt -#endif - -#if defined(X86_WIN32) && !defined(__OS2__) - .section .eh_frame,"w" -#endif -.Lframe1: -.LSCIE1: - .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */ -.LASCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ -#else - .ascii "\0" /* CIE Augmentation */ -#endif - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ -#ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ -#endif - .byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: - -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB1-. /* FDE initial location */ -#else - .long .LFB1 -#endif - .long .LFE1-.LFB1 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE1: - -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB3-. /* FDE initial location */ -#else - .long .LFB3 -#endif - .long .LFE3-.LFB3 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LFB3 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI5-.LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE3: - -#if !FFI_NO_RAW_API - -.LSFDE4: - .long .LEFDE4-.LASFDE4 /* FDE Length */ -.LASFDE4: - .long .LASFDE4-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB4-. /* FDE initial location */ -#else - .long .LFB4 -#endif - .long .LFE4-.LFB4 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI6-.LFB4 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI7-.LCFI6 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI8-.LCFI7 - .byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */ - .byte 0x3 /* .uleb128 0x3 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE4: - -#endif /* !FFI_NO_RAW_API */ - -.LSFDE5: - .long .LEFDE5-.LASFDE5 /* FDE Length */ -.LASFDE5: - .long .LASFDE5-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB5-. /* FDE initial location */ -#else - .long .LFB5 -#endif - .long .LFE5-.LFB5 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI9-.LFB5 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI10-.LCFI9 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE5: - -#endif /* !_MSC_VER */ - -#if defined __ELF__ && defined __linux__ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/x86/win64.S b/ruby/ext/fiddle/libffi-3.2.1/src/x86/win64.S deleted file mode 100644 index 347a26a85..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/x86/win64.S +++ /dev/null @@ -1,519 +0,0 @@ -#define LIBFFI_ASM -#include -#include - -/* Constants for ffi_call_win64 */ -#define STACK 0 -#define PREP_ARGS_FN 32 -#define ECIF 40 -#define CIF_BYTES 48 -#define CIF_FLAGS 56 -#define RVALUE 64 -#define FN 72 - -/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *), - extended_cif *ecif, unsigned bytes, unsigned flags, - unsigned *rvalue, void (*fn)()); - */ - -#ifdef _MSC_VER -PUBLIC ffi_call_win64 - -EXTRN __chkstk:NEAR -EXTRN ffi_closure_win64_inner:NEAR - -_TEXT SEGMENT - -;;; ffi_closure_win64 will be called with these registers set: -;;; rax points to 'closure' -;;; r11 contains a bit mask that specifies which of the -;;; first four parameters are float or double -;;; -;;; It must move the parameters passed in registers to their stack location, -;;; call ffi_closure_win64_inner for the actual work, then return the result. -;;; -ffi_closure_win64 PROC FRAME - ;; copy register arguments onto stack - test r11, 1 - jne first_is_float - mov QWORD PTR [rsp+8], rcx - jmp second -first_is_float: - movlpd QWORD PTR [rsp+8], xmm0 - -second: - test r11, 2 - jne second_is_float - mov QWORD PTR [rsp+16], rdx - jmp third -second_is_float: - movlpd QWORD PTR [rsp+16], xmm1 - -third: - test r11, 4 - jne third_is_float - mov QWORD PTR [rsp+24], r8 - jmp fourth -third_is_float: - movlpd QWORD PTR [rsp+24], xmm2 - -fourth: - test r11, 8 - jne fourth_is_float - mov QWORD PTR [rsp+32], r9 - jmp done -fourth_is_float: - movlpd QWORD PTR [rsp+32], xmm3 - -done: - .ALLOCSTACK 40 - sub rsp, 40 - .ENDPROLOG - mov rcx, rax ; context is first parameter - mov rdx, rsp ; stack is second parameter - add rdx, 48 ; point to start of arguments - mov rax, ffi_closure_win64_inner - call rax ; call the real closure function - add rsp, 40 - movd xmm0, rax ; If the closure returned a float, - ; ffi_closure_win64_inner wrote it to rax - ret 0 -ffi_closure_win64 ENDP - -ffi_call_win64 PROC FRAME - ;; copy registers onto stack - mov QWORD PTR [rsp+32], r9 - mov QWORD PTR [rsp+24], r8 - mov QWORD PTR [rsp+16], rdx - mov QWORD PTR [rsp+8], rcx - .PUSHREG rbp - push rbp - .ALLOCSTACK 48 - sub rsp, 48 ; 00000030H - .SETFRAME rbp, 32 - lea rbp, QWORD PTR [rsp+32] - .ENDPROLOG - - mov eax, DWORD PTR CIF_BYTES[rbp] - add rax, 15 - and rax, -16 - call __chkstk - sub rsp, rax - lea rax, QWORD PTR [rsp+32] - mov QWORD PTR STACK[rbp], rax - - mov rdx, QWORD PTR ECIF[rbp] - mov rcx, QWORD PTR STACK[rbp] - call QWORD PTR PREP_ARGS_FN[rbp] - - mov rsp, QWORD PTR STACK[rbp] - - movlpd xmm3, QWORD PTR [rsp+24] - movd r9, xmm3 - - movlpd xmm2, QWORD PTR [rsp+16] - movd r8, xmm2 - - movlpd xmm1, QWORD PTR [rsp+8] - movd rdx, xmm1 - - movlpd xmm0, QWORD PTR [rsp] - movd rcx, xmm0 - - call QWORD PTR FN[rbp] -ret_struct4b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B - jne ret_struct2b$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov DWORD PTR [rcx], eax - jmp SHORT ret_void$ - -ret_struct2b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B - jne ret_struct1b$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov WORD PTR [rcx], ax - jmp SHORT ret_void$ - -ret_struct1b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B - jne ret_uint8$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov BYTE PTR [rcx], al - jmp SHORT ret_void$ - -ret_uint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8 - jne ret_sint8$ - - mov rcx, QWORD PTR RVALUE[rbp] - movzx rax, al - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_sint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8 - jne ret_uint16$ - - mov rcx, QWORD PTR RVALUE[rbp] - movsx rax, al - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_uint16$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16 - jne ret_sint16$ - - mov rcx, QWORD PTR RVALUE[rbp] - movzx rax, ax - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_sint16$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16 - jne ret_uint32$ - - mov rcx, QWORD PTR RVALUE[rbp] - movsx rax, ax - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_uint32$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32 - jne ret_sint32$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov eax, eax - mov QWORD PTR [rcx], rax - -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 - jne ret_float$ - - mov rcx, QWORD PTR RVALUE[rbp] - cdqe - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_float$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT - jne SHORT ret_double$ - - mov rax, QWORD PTR RVALUE[rbp] - movss DWORD PTR [rax], xmm0 - jmp SHORT ret_void$ - -ret_double$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE - jne SHORT ret_uint64$ - - mov rax, QWORD PTR RVALUE[rbp] - movlpd QWORD PTR [rax], xmm0 - jmp SHORT ret_void$ - -ret_uint64$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64 - jne SHORT ret_sint64$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_sint64$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 - jne SHORT ret_pointer$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_pointer$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER - jne SHORT ret_int$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_int$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT - jne SHORT ret_void$ - - mov rcx, QWORD PTR RVALUE[rbp] - cdqe - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ -ffi_call_win64 ENDP -_TEXT ENDS -END - -#else - -#ifdef SYMBOL_UNDERSCORE -#define SYMBOL_NAME(name) _##name -#else -#define SYMBOL_NAME(name) name -#endif - -.text - -.extern SYMBOL_NAME(ffi_closure_win64_inner) - -# ffi_closure_win64 will be called with these registers set: -# rax points to 'closure' -# r11 contains a bit mask that specifies which of the -# first four parameters are float or double -# -# It must move the parameters passed in registers to their stack location, -# call ffi_closure_win64_inner for the actual work, then return the result. -# - .balign 16 - .globl SYMBOL_NAME(ffi_closure_win64) - .seh_proc SYMBOL_NAME(ffi_closure_win64) -SYMBOL_NAME(ffi_closure_win64): - # copy register arguments onto stack - test $1,%r11 - jne .Lfirst_is_float - mov %rcx, 8(%rsp) - jmp .Lsecond -.Lfirst_is_float: - movlpd %xmm0, 8(%rsp) - -.Lsecond: - test $2, %r11 - jne .Lsecond_is_float - mov %rdx, 16(%rsp) - jmp .Lthird -.Lsecond_is_float: - movlpd %xmm1, 16(%rsp) - -.Lthird: - test $4, %r11 - jne .Lthird_is_float - mov %r8,24(%rsp) - jmp .Lfourth -.Lthird_is_float: - movlpd %xmm2, 24(%rsp) - -.Lfourth: - test $8, %r11 - jne .Lfourth_is_float - mov %r9, 32(%rsp) - jmp .Ldone -.Lfourth_is_float: - movlpd %xmm3, 32(%rsp) - -.Ldone: - .seh_stackalloc 40 - sub $40, %rsp - .seh_endprologue - mov %rax, %rcx # context is first parameter - mov %rsp, %rdx # stack is second parameter - add $48, %rdx # point to start of arguments - leaq SYMBOL_NAME(ffi_closure_win64_inner)(%rip), %rax - callq *%rax # call the real closure function - add $40, %rsp - movq %rax, %xmm0 # If the closure returned a float, - # ffi_closure_win64_inner wrote it to rax - retq - .seh_endproc - - .balign 16 - .globl SYMBOL_NAME(ffi_call_win64) - .seh_proc SYMBOL_NAME(ffi_call_win64) -SYMBOL_NAME(ffi_call_win64): - # copy registers onto stack - mov %r9,32(%rsp) - mov %r8,24(%rsp) - mov %rdx,16(%rsp) - mov %rcx,8(%rsp) - .seh_pushreg rbp - push %rbp - .seh_stackalloc 48 - sub $48,%rsp - .seh_setframe rbp, 32 - lea 32(%rsp),%rbp - .seh_endprologue - - mov CIF_BYTES(%rbp),%eax - add $15, %rax - and $-16, %rax - cmpq $0x1000, %rax - jb Lch_done -Lch_probe: - subq $0x1000,%rsp - orl $0x0, (%rsp) - subq $0x1000,%rax - cmpq $0x1000,%rax - ja Lch_probe -Lch_done: - subq %rax, %rsp - orl $0x0, (%rsp) - lea 32(%rsp), %rax - mov %rax, STACK(%rbp) - - mov ECIF(%rbp), %rdx - mov STACK(%rbp), %rcx - callq *PREP_ARGS_FN(%rbp) - - mov STACK(%rbp), %rsp - - movlpd 24(%rsp), %xmm3 - movd %xmm3, %r9 - - movlpd 16(%rsp), %xmm2 - movd %xmm2, %r8 - - movlpd 8(%rsp), %xmm1 - movd %xmm1, %rdx - - movlpd (%rsp), %xmm0 - movd %xmm0, %rcx - - callq *FN(%rbp) -.Lret_struct4b: - cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp) - jne .Lret_struct2b - - mov RVALUE(%rbp), %rcx - mov %eax, (%rcx) - jmp .Lret_void - -.Lret_struct2b: - cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp) - jne .Lret_struct1b - - mov RVALUE(%rbp), %rcx - mov %ax, (%rcx) - jmp .Lret_void - -.Lret_struct1b: - cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp) - jne .Lret_uint8 - - mov RVALUE(%rbp), %rcx - mov %al, (%rcx) - jmp .Lret_void - -.Lret_uint8: - cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp) - jne .Lret_sint8 - - mov RVALUE(%rbp), %rcx - movzbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint8: - cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp) - jne .Lret_uint16 - - mov RVALUE(%rbp), %rcx - movsbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint16: - cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp) - jne .Lret_sint16 - - mov RVALUE(%rbp), %rcx - movzwq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint16: - cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp) - jne .Lret_uint32 - - mov RVALUE(%rbp), %rcx - movswq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint32: - cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp) - jne .Lret_sint32 - - mov RVALUE(%rbp), %rcx - movl %eax, %eax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint32: - cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp) - jne .Lret_float - - mov RVALUE(%rbp), %rcx - cltq - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_float: - cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp) - jne .Lret_double - - mov RVALUE(%rbp), %rax - movss %xmm0, (%rax) - jmp .Lret_void - -.Lret_double: - cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) - jne .Lret_uint64 - - mov RVALUE(%rbp), %rax - movlpd %xmm0, (%rax) - jmp .Lret_void - -.Lret_uint64: - cmpl $FFI_TYPE_UINT64, CIF_FLAGS(%rbp) - jne .Lret_sint64 - - mov RVALUE(%rbp), %rcx - mov %rax, (%rcx) - jmp .Lret_void - -.Lret_sint64: - cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) - jne .Lret_pointer - - mov RVALUE(%rbp), %rcx - mov %rax, (%rcx) - jmp .Lret_void - -.Lret_pointer: - cmpl $FFI_TYPE_POINTER, CIF_FLAGS(%rbp) - jne .Lret_int - - mov RVALUE(%rbp), %rcx - mov %rax, (%rcx) - jmp .Lret_void - -.Lret_int: - cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp) - jne .Lret_void - - mov RVALUE(%rbp), %rcx - cltq - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_void: - xor %rax, %rax - - lea 16(%rbp), %rsp - pop %rbp - retq - .seh_endproc -#endif /* !_MSC_VER */ - diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffi.c b/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffi.c deleted file mode 100644 index fd94dafbe..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffi.c +++ /dev/null @@ -1,298 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2013 Tensilica, Inc. - - XTENSA Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -/* - |----------------------------------------| - | | - on entry to ffi_call ----> |----------------------------------------| - | caller stack frame for registers a0-a3 | - |----------------------------------------| - | | - | additional arguments | - entry of the function ---> |----------------------------------------| - | copy of function arguments a2-a7 | - | - - - - - - - - - - - - - | - | | - - The area below the entry line becomes the new stack frame for the function. - -*/ - - -#define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST - - -extern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags, - void(*fn)(void), unsigned nbytes, extended_cif*); -extern void ffi_closure_SYSV(void) FFI_HIDDEN; - -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - switch(cif->rtype->type) { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - cif->flags = cif->rtype->type; - break; - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - cif->flags = FFI_TYPE_UINT32; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - cif->flags = FFI_TYPE_UINT64; // cif->rtype->type; - break; - case FFI_TYPE_STRUCT: - cif->flags = FFI_TYPE_STRUCT; //_REGS; - /* Up to 16 bytes are returned in registers */ - if (cif->rtype->size > 4 * 4) { - /* returned structure is referenced by a register; use 8 bytes - (including 4 bytes for potential additional alignment) */ - cif->flags = FFI_TYPE_STRUCT; - cif->bytes += 8; - } - break; - - default: - cif->flags = FFI_TYPE_UINT32; - break; - } - - /* Round the stack up to a full 4 register frame, just in case - (we use this size in movsp). This way, it's also a multiple of - 8 bytes for 64-bit arguments. */ - cif->bytes = ALIGN(cif->bytes, 16); - - return FFI_OK; -} - -void ffi_prep_args(extended_cif *ecif, unsigned char* stack) -{ - unsigned int i; - unsigned long *addr; - ffi_type **ptr; - - union { - void **v; - char **c; - signed char **sc; - unsigned char **uc; - signed short **ss; - unsigned short **us; - unsigned int **i; - long long **ll; - float **f; - double **d; - } p_argv; - - /* Verify that everything is aligned up properly */ - FFI_ASSERT (((unsigned long) stack & 0x7) == 0); - - p_argv.v = ecif->avalue; - addr = (unsigned long*)stack; - - /* structures with a size greater than 16 bytes are passed in memory */ - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16) - { - *addr++ = (unsigned long)ecif->rvalue; - } - - for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types; - i > 0; - i--, ptr++, p_argv.v++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_SINT8: - *addr++ = **p_argv.sc; - break; - case FFI_TYPE_UINT8: - *addr++ = **p_argv.uc; - break; - case FFI_TYPE_SINT16: - *addr++ = **p_argv.ss; - break; - case FFI_TYPE_UINT16: - *addr++ = **p_argv.us; - break; - case FFI_TYPE_FLOAT: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - *addr++ = **p_argv.i; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (((unsigned long)addr & 4) != 0) - addr++; - *(unsigned long long*)addr = **p_argv.ll; - addr += sizeof(unsigned long long) / sizeof (addr); - break; - - case FFI_TYPE_STRUCT: - { - unsigned long offs; - unsigned long size; - - if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4) - addr++; - - offs = (unsigned long) addr - (unsigned long) stack; - size = (*ptr)->size; - - /* Entire structure must fit the argument registers or referenced */ - if (offs < FFI_REGISTER_NARGS * 4 - && offs + size > FFI_REGISTER_NARGS * 4) - addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4); - - memcpy((char*) addr, *p_argv.c, size); - addr += (size + 3) / 4; - break; - } - - default: - FFI_ASSERT(0); - } - } -} - - -void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - unsigned long rsize = cif->rtype->size; - int flags = cif->flags; - void *alloc = NULL; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* Note that for structures that are returned in registers (size <= 16 bytes) - we allocate a temporary buffer and use memcpy to copy it to the final - destination. The reason is that the target address might be misaligned or - the length not a multiple of 4 bytes. Handling all those cases would be - very complex. */ - - if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL)) - { - alloc = alloca(ALIGN(rsize, 4)); - ecif.rvalue = alloc; - } - else - { - ecif.rvalue = rvalue; - } - - if (cif->abi != FFI_SYSV) - FFI_ASSERT(0); - - ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif); - - if (alloc != NULL && rvalue != NULL) - memcpy(rvalue, alloc, rsize); -} - -extern void ffi_trampoline(); -extern void ffi_cacheflush(void* start, void* end); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */ - memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE); - *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV; - - // Do we have this function? - // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE) - ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE); - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - return FFI_OK; -} - - -long FFI_HIDDEN -ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue) -{ - ffi_cif *cif; - ffi_type **arg_types; - void **avalue; - int i, areg; - - cif = closure->cif; - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - areg = 0; - - int rtype = cif->rtype->type; - if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4) - { - rvalue = *values; - areg++; - } - - cif = closure->cif; - arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); - - for (i = 0; i < cif->nargs; i++) - { - if (arg_types[i]->alignment == 8 && (areg & 1) != 0) - areg++; - - // skip the entry 16,a1 framework, add 16 bytes (4 registers) - if (areg == FFI_REGISTER_NARGS) - areg += 4; - - if (arg_types[i]->type == FFI_TYPE_STRUCT) - { - int numregs = ((arg_types[i]->size + 3) & ~3) / 4; - if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS) - areg = FFI_REGISTER_NARGS + 4; - } - - avalue[i] = &values[areg]; - areg += (arg_types[i]->size + 3) / 4; - } - - (closure->fun)(cif, rvalue, avalue, closure->user_data); - - return rtype; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffitarget.h b/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffitarget.h deleted file mode 100644 index 0ba728bc9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2013 Tensilica, Inc. - Target configuration macros for XTENSA. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#define FFI_REGISTER_NARGS 6 - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 -#define FFI_TRAMPOLINE_SIZE 24 - -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/sysv.S b/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/sysv.S deleted file mode 100644 index 64e6a0918..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/src/xtensa/sysv.S +++ /dev/null @@ -1,253 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 Tensilica, Inc. - - XTENSA Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#define ENTRY(name) .text; .globl name; .type name,@function; .align 4; name: -#define END(name) .size name , . - name - -/* Assert that the table below is in sync with ffi.h. */ - -#if FFI_TYPE_UINT8 != 5 \ - || FFI_TYPE_SINT8 != 6 \ - || FFI_TYPE_UINT16 != 7 \ - || FFI_TYPE_SINT16 != 8 \ - || FFI_TYPE_UINT32 != 9 \ - || FFI_TYPE_SINT32 != 10 \ - || FFI_TYPE_UINT64 != 11 -#error "xtensa/sysv.S out of sync with ffi.h" -#endif - - -/* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif) - void *rvalue; a2 - unsigned long rbytes; a3 - unsigned flags; a4 - void (*fnaddr)(); a5 - unsigned long bytes; a6 - extended_cif* ecif) a7 -*/ - -ENTRY(ffi_call_SYSV) - - entry a1, 32 # 32 byte frame for using call8 below - - mov a10, a7 # a10(->arg0): ecif - sub a11, a1, a6 # a11(->arg1): stack pointer - mov a7, a1 # fp - movsp a1, a11 # set new sp = old_sp - bytes - - movi a8, ffi_prep_args - callx8 a8 # ffi_prep_args(ecif, stack) - - # prepare to move stack pointer back up to 6 arguments - # note that 'bytes' is already aligned - - movi a10, 6*4 - sub a11, a6, a10 - movgez a6, a10, a11 - add a6, a1, a6 - - - # we can pass up to 6 arguments in registers - # for simplicity, just load 6 arguments - # (the stack size is at least 32 bytes, so no risk to cross boundaries) - - l32i a10, a1, 0 - l32i a11, a1, 4 - l32i a12, a1, 8 - l32i a13, a1, 12 - l32i a14, a1, 16 - l32i a15, a1, 20 - - # move stack pointer - - movsp a1, a6 - - callx8 a5 # (*fn)(args...) - - # Handle return value(s) - - beqz a2, .Lexit - - movi a5, FFI_TYPE_STRUCT - bne a4, a5, .Lstore - movi a5, 16 - blt a5, a3, .Lexit - - s32i a10, a2, 0 - blti a3, 5, .Lexit - addi a3, a3, -1 - s32i a11, a2, 4 - blti a3, 8, .Lexit - s32i a12, a2, 8 - blti a3, 12, .Lexit - s32i a13, a2, 12 - -.Lexit: retw - -.Lstore: - addi a4, a4, -FFI_TYPE_UINT8 - bgei a4, 7, .Lexit # should never happen - movi a6, store_calls - add a4, a4, a4 - addx4 a6, a4, a6 # store_table + idx * 8 - jx a6 - - .align 8 -store_calls: - # UINT8 - s8i a10, a2, 0 - retw - - # SINT8 - .align 8 - s8i a10, a2, 0 - retw - - # UINT16 - .align 8 - s16i a10, a2, 0 - retw - - # SINT16 - .align 8 - s16i a10, a2, 0 - retw - - # UINT32 - .align 8 - s32i a10, a2, 0 - retw - - # SINT32 - .align 8 - s32i a10, a2, 0 - retw - - # UINT64 - .align 8 - s32i a10, a2, 0 - s32i a11, a2, 4 - retw - -END(ffi_call_SYSV) - - -/* - * void ffi_cacheflush (unsigned long start, unsigned long end) - */ - -#define EXTRA_ARGS_SIZE 24 - -ENTRY(ffi_cacheflush) - - entry a1, 16 - -1: dhwbi a2, 0 - ihi a2, 0 - addi a2, a2, 4 - blt a2, a3, 1b - - retw - -END(ffi_cacheflush) - -/* ffi_trampoline is copied to the stack */ - -ENTRY(ffi_trampoline) - - entry a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4) # [ 0] - j 2f # [ 3] - .align 4 # [ 6] -1: .long 0 # [ 8] -2: l32r a15, 1b # [12] - _mov a14, a0 # [15] - callx0 a15 # [18] - # [21] -END(ffi_trampoline) - -/* - * ffi_closure() - * - * a0: closure + 21 - * a14: return address (a0) - */ - -ENTRY(ffi_closure_SYSV) - - /* intentionally omitting entry here */ - - # restore return address (a0) and move pointer to closure to a10 - addi a10, a0, -21 - mov a0, a14 - - # allow up to 4 arguments as return values - addi a11, a1, 4 * 4 - - # save up to 6 arguments to stack (allocated by entry below) - s32i a2, a11, 0 - s32i a3, a11, 4 - s32i a4, a11, 8 - s32i a5, a11, 12 - s32i a6, a11, 16 - s32i a7, a11, 20 - - movi a8, ffi_closure_SYSV_inner - mov a12, a1 - callx8 a8 # .._inner(*closure, **avalue, *rvalue) - - # load up to four return arguments - l32i a2, a1, 0 - l32i a3, a1, 4 - l32i a4, a1, 8 - l32i a5, a1, 12 - - # (sign-)extend return value - movi a11, FFI_TYPE_UINT8 - bne a10, a11, 1f - extui a2, a2, 0, 8 - retw - -1: movi a11, FFI_TYPE_SINT8 - bne a10, a11, 1f - sext a2, a2, 7 - retw - -1: movi a11, FFI_TYPE_UINT16 - bne a10, a11, 1f - extui a2, a2, 0, 16 - retw - -1: movi a11, FFI_TYPE_SINT16 - bne a10, a11, 1f - sext a2, a2, 15 - -1: retw - -END(ffi_closure_SYSV) diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.am b/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.am deleted file mode 100644 index da10465d2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.am +++ /dev/null @@ -1,85 +0,0 @@ -## Process this file with automake to produce Makefile.in. - -AUTOMAKE_OPTIONS = foreign dejagnu - -EXTRA_DEJAGNU_SITE_CONFIG=../local.exp - -CLEANFILES = *.exe core* *.log *.sum - -EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \ -libffi.call/cls_align_longdouble_split.c \ -libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c \ -libffi.call/closure_fn1.c \ -libffi.call/return_ul.c libffi.call/cls_align_double.c \ -libffi.call/return_fl2.c libffi.call/cls_1_1byte.c \ -libffi.call/cls_64byte.c libffi.call/nested_struct7.c \ -libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c \ -libffi.call/ffitest.h libffi.call/nested_struct4.c \ -libffi.call/cls_multi_ushort.c libffi.call/struct3.c \ -libffi.call/cls_3byte1.c libffi.call/cls_16byte.c \ -libffi.call/struct8.c libffi.call/nested_struct8.c \ -libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c \ -libffi.call/cls_pointer.c \ -libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c \ -libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c \ -libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c \ -libffi.call/call.exp libffi.call/cls_double.c \ -libffi.call/cls_align_sint16.c libffi.call/cls_uint.c \ -libffi.call/return_ll1.c libffi.call/nested_struct3.c \ -libffi.call/cls_20byte1.c libffi.call/closure_fn4.c \ -libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c \ -libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c \ -libffi.call/return_fl.c libffi.call/struct5.c \ -libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \ -libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \ -libffi.call/return_fl3.c libffi.call/stret_medium.c \ -libffi.call/nested_struct6.c libffi.call/closure_fn3.c \ -libffi.call/float3.c libffi.call/many2.c \ -libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \ -libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \ -libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \ -libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \ -libffi.call/cls_sshort.c \ -libffi.call/nested_struct.c libffi.call/cls_20byte.c \ -libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \ -libffi.call/return_uc.c \ -libffi.call/cls_18byte.c libffi.call/cls_8byte.c \ -libffi.call/promotion.c \ -libffi.call/return_dbl.c libffi.call/cls_24byte.c \ -libffi.call/struct4.c libffi.call/cls_6byte.c \ -libffi.call/cls_align_uint32.c libffi.call/float.c \ -libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \ -libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \ -libffi.call/cls_align_float.c libffi.call/return_fl1.c \ -libffi.call/nested_struct10.c libffi.call/nested_struct5.c \ -libffi.call/cls_align_sint64.c \ -libffi.call/stret_large2.c libffi.call/return_sl.c \ -libffi.call/closure_fn0.c libffi.call/cls_5byte.c \ -libffi.call/cls_2byte.c libffi.call/float2.c \ -libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \ -libffi.call/stret_large.c libffi.call/cls_ulonglong.c \ -libffi.call/cls_ushort.c libffi.call/nested_struct1.c \ -libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \ -libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \ -libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \ -libffi.call/struct1.c libffi.call/nested_struct9.c \ -libffi.call/huge_struct.c libffi.call/problem1.c \ -libffi.call/float4.c \ -libffi.call/return_ldl.c \ -libffi.call/closure_fn5.c \ -libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c \ -libffi.call/return_sc.c libffi.call/struct7.c \ -libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c \ -libffi.call/cls_6_1_byte.c \ -libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc \ -libffi.call/unwindtest_ffi_call.cc \ -lib/wrapper.exp lib/target-libpath.exp \ -lib/libffi.exp libffi.call/cls_struct_va1.c \ -libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c \ -libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c \ -libffi.call/nested_struct11.c libffi.call/uninitialized.c \ -libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c \ -libffi.call/va_struct3.c \ -libffi.call/strlen2.c \ -libffi.call/strlen3.c \ -libffi.call/strlen4.c diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.in b/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.in deleted file mode 100644 index 99e226c40..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/Makefile.in +++ /dev/null @@ -1,590 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = testsuite -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \ - $(top_srcdir)/m4/ax_append_flag.m4 \ - $(top_srcdir)/m4/ax_cc_maxopt.m4 \ - $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_compiler_vendor.m4 \ - $(top_srcdir)/m4/ax_configure_args.m4 \ - $(top_srcdir)/m4/ax_enable_builddir.m4 \ - $(top_srcdir)/m4/ax_gcc_archflag.m4 \ - $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/fficonfig.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -DEJATOOL = $(PACKAGE) -RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir -EXPECT = expect -RUNTEST = runtest -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AM_LTLDFLAGS = @AM_LTLDFLAGS@ -AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ -HAVE_LONG_DOUBLE_VARIANT = @HAVE_LONG_DOUBLE_VARIANT@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PRTDIAG = @PRTDIAG@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TARGET = @TARGET@ -TARGETDIR = @TARGETDIR@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -ax_enable_builddir_sed = @ax_enable_builddir_sed@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sys_symbol_underscore = @sys_symbol_underscore@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -toolexecdir = @toolexecdir@ -toolexeclibdir = @toolexeclibdir@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign dejagnu -EXTRA_DEJAGNU_SITE_CONFIG = ../local.exp -CLEANFILES = *.exe core* *.log *.sum -EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \ -libffi.call/cls_align_longdouble_split.c \ -libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c \ -libffi.call/closure_fn1.c \ -libffi.call/return_ul.c libffi.call/cls_align_double.c \ -libffi.call/return_fl2.c libffi.call/cls_1_1byte.c \ -libffi.call/cls_64byte.c libffi.call/nested_struct7.c \ -libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c \ -libffi.call/ffitest.h libffi.call/nested_struct4.c \ -libffi.call/cls_multi_ushort.c libffi.call/struct3.c \ -libffi.call/cls_3byte1.c libffi.call/cls_16byte.c \ -libffi.call/struct8.c libffi.call/nested_struct8.c \ -libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c \ -libffi.call/cls_pointer.c \ -libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c \ -libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c \ -libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c \ -libffi.call/call.exp libffi.call/cls_double.c \ -libffi.call/cls_align_sint16.c libffi.call/cls_uint.c \ -libffi.call/return_ll1.c libffi.call/nested_struct3.c \ -libffi.call/cls_20byte1.c libffi.call/closure_fn4.c \ -libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c \ -libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c \ -libffi.call/return_fl.c libffi.call/struct5.c \ -libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \ -libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \ -libffi.call/return_fl3.c libffi.call/stret_medium.c \ -libffi.call/nested_struct6.c libffi.call/closure_fn3.c \ -libffi.call/float3.c libffi.call/many2.c \ -libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \ -libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \ -libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \ -libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \ -libffi.call/cls_sshort.c \ -libffi.call/nested_struct.c libffi.call/cls_20byte.c \ -libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \ -libffi.call/return_uc.c \ -libffi.call/cls_18byte.c libffi.call/cls_8byte.c \ -libffi.call/promotion.c \ -libffi.call/return_dbl.c libffi.call/cls_24byte.c \ -libffi.call/struct4.c libffi.call/cls_6byte.c \ -libffi.call/cls_align_uint32.c libffi.call/float.c \ -libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \ -libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \ -libffi.call/cls_align_float.c libffi.call/return_fl1.c \ -libffi.call/nested_struct10.c libffi.call/nested_struct5.c \ -libffi.call/cls_align_sint64.c \ -libffi.call/stret_large2.c libffi.call/return_sl.c \ -libffi.call/closure_fn0.c libffi.call/cls_5byte.c \ -libffi.call/cls_2byte.c libffi.call/float2.c \ -libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \ -libffi.call/stret_large.c libffi.call/cls_ulonglong.c \ -libffi.call/cls_ushort.c libffi.call/nested_struct1.c \ -libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \ -libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \ -libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \ -libffi.call/struct1.c libffi.call/nested_struct9.c \ -libffi.call/huge_struct.c libffi.call/problem1.c \ -libffi.call/float4.c \ -libffi.call/return_ldl.c \ -libffi.call/closure_fn5.c \ -libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c \ -libffi.call/return_sc.c libffi.call/struct7.c \ -libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c \ -libffi.call/cls_6_1_byte.c \ -libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc \ -libffi.call/unwindtest_ffi_call.cc \ -lib/wrapper.exp lib/target-libpath.exp \ -lib/libffi.exp libffi.call/cls_struct_va1.c \ -libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c \ -libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c \ -libffi.call/nested_struct11.c libffi.call/uninitialized.c \ -libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c \ -libffi.call/va_struct3.c \ -libffi.call/strlen2.c \ -libffi.call/strlen3.c \ -libffi.call/strlen4.c - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign testsuite/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -check-DEJAGNU: site.exp - srcdir='$(srcdir)'; export srcdir; \ - EXPECT=$(EXPECT); export EXPECT; \ - if $(SHELL) -c "$(RUNTEST) --version" > /dev/null 2>&1; then \ - exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \ - if $(RUNTEST) $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \ - then :; else exit_status=1; fi; \ - done; \ - else echo "WARNING: could not find '$(RUNTEST)'" 1>&2; :;\ - fi; \ - exit $$exit_status -site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG) - @echo 'Making a new site.exp file ...' - @echo '## these variables are automatically generated by make ##' >site.tmp - @echo '# Do not edit here. If you wish to override these values' >>site.tmp - @echo '# edit the last section' >>site.tmp - @echo 'set srcdir "$(srcdir)"' >>site.tmp - @echo "set objdir `pwd`" >>site.tmp - @echo 'set build_alias "$(build_alias)"' >>site.tmp - @echo 'set build_triplet $(build_triplet)' >>site.tmp - @echo 'set host_alias "$(host_alias)"' >>site.tmp - @echo 'set host_triplet $(host_triplet)' >>site.tmp - @echo 'set target_alias "$(target_alias)"' >>site.tmp - @echo 'set target_triplet $(target_triplet)' >>site.tmp - @list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \ - echo "## Begin content included from file $$f. Do not modify. ##" \ - && cat `test -f "$$f" || echo '$(srcdir)/'`$$f \ - && echo "## End content included from file $$f. ##" \ - || exit 1; \ - done >> site.tmp - @echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp - @if test -f site.exp; then \ - sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \ - fi - @-rm -f site.bak - @test ! -f site.exp || mv site.exp site.bak - @mv site.tmp site.exp - -distclean-DEJAGNU: - -rm -f site.exp site.bak - -l='$(DEJATOOL)'; for tool in $$l; do \ - rm -f $$tool.sum $$tool.log; \ - done - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-DEJAGNU distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: check-am install-am install-strip - -.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \ - clean-libtool cscopelist-am ctags-am distclean \ - distclean-DEJAGNU distclean-generic distclean-libtool distdir \ - dvi dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ - uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/config/default.exp b/ruby/ext/fiddle/libffi-3.2.1/testsuite/config/default.exp deleted file mode 100644 index 90967cccc..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/config/default.exp +++ /dev/null @@ -1 +0,0 @@ -load_lib "standard.exp" diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/libffi.exp b/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/libffi.exp deleted file mode 100644 index 5051d3175..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/libffi.exp +++ /dev/null @@ -1,413 +0,0 @@ -# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING3. If not see -# . - -proc load_gcc_lib { filename } { - global srcdir - load_file $srcdir/lib/$filename -} - -load_lib dg.exp -load_lib libgloss.exp -load_gcc_lib target-libpath.exp -load_gcc_lib wrapper.exp - - -# Define libffi callbacks for dg.exp. - -proc libffi-dg-test-1 { target_compile prog do_what extra_tool_flags } { - - # To get all \n in dg-output test strings to match printf output - # in a system that outputs it as \015\012 (i.e. not just \012), we - # need to change all \n into \r?\n. As there is no dejagnu flag - # or hook to do that, we simply change the text being tested. - # Unfortunately, we have to know that the variable is called - # dg-output-text and lives in the caller of libffi-dg-test, which - # is two calls up. Overriding proc dg-output would be longer and - # would necessarily have the same assumption. - upvar 2 dg-output-text output_match - - if { [llength $output_match] > 1 } { - regsub -all "\n" [lindex $output_match 1] "\r?\n" x - set output_match [lreplace $output_match 1 1 $x] - } - - # Set up the compiler flags, based on what we're going to do. - - set options [list] - switch $do_what { - "compile" { - set compile_type "assembly" - set output_file "[file rootname [file tail $prog]].s" - } - "link" { - set compile_type "executable" - set output_file "[file rootname [file tail $prog]].exe" - # The following line is needed for targets like the i960 where - # the default output file is b.out. Sigh. - } - "run" { - set compile_type "executable" - # FIXME: "./" is to cope with "." not being in $PATH. - # Should this be handled elsewhere? - # YES. - set output_file "./[file rootname [file tail $prog]].exe" - # This is the only place where we care if an executable was - # created or not. If it was, dg.exp will try to run it. - remote_file build delete $output_file; - } - default { - perror "$do_what: not a valid dg-do keyword" - return "" - } - } - - if { $extra_tool_flags != "" } { - lappend options "additional_flags=$extra_tool_flags" - } - - set comp_output [libffi_target_compile "$prog" "$output_file" "$compile_type" $options]; - - - return [list $comp_output $output_file] -} - - -proc libffi-dg-test { prog do_what extra_tool_flags } { - return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags] -} - -proc libffi-init { args } { - global gluefile wrap_flags; - global srcdir - global blddirffi - global objdir - global TOOL_OPTIONS - global tool - global libffi_include - global libffi_link_flags - global tool_root_dir - global ld_library_path - - global using_gcc - - set blddirffi [pwd]/.. - verbose "libffi $blddirffi" - - # Are we building with GCC? - set tmp [grep ../config.status "GCC='yes'"] - if { [string match $tmp "GCC='yes'"] } { - - set using_gcc "yes" - - set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] - if {$gccdir != ""} { - set gccdir [file dirname $gccdir] - } - verbose "gccdir $gccdir" - - set ld_library_path "." - append ld_library_path ":${gccdir}" - - set compiler "${gccdir}/xgcc" - if { [is_remote host] == 0 && [which $compiler] != 0 } { - foreach i "[exec $compiler --print-multi-lib]" { - set mldir "" - regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir - set mldir [string trimright $mldir "\;@"] - if { "$mldir" == "." } { - continue - } - if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { - append ld_library_path ":${gccdir}/${mldir}" - } - } - } - - } else { - - set using_gcc "no" - - } - - # add the library path for libffi. - append ld_library_path ":${blddirffi}/.libs" - - verbose "ld_library_path: $ld_library_path" - - # Point to the Libffi headers in libffi. - set libffi_include "${blddirffi}/include" - verbose "libffi_include $libffi_include" - - set libffi_dir "${blddirffi}/.libs" - verbose "libffi_dir $libffi_dir" - if { $libffi_dir != "" } { - set libffi_dir [file dirname ${libffi_dir}] - set libffi_link_flags "-L${libffi_dir}/.libs" - } - - set_ld_library_path_env_vars - libffi_maybe_build_wrapper "${objdir}/testglue.o" -} - -proc libffi_exit { } { - global gluefile; - - if [info exists gluefile] { - file_on_build delete $gluefile; - unset gluefile; - } -} - -proc libffi_target_compile { source dest type options } { - global gluefile wrap_flags; - global srcdir - global blddirffi - global TOOL_OPTIONS - global libffi_link_flags - global libffi_include - global target_triplet - - - if { [target_info needs_status_wrapper]!="" && [info exists gluefile] } { - lappend options "libs=${gluefile}" - lappend options "ldflags=$wrap_flags" - } - - # TOOL_OPTIONS must come first, so that it doesn't override testcase - # specific options. - if [info exists TOOL_OPTIONS] { - lappend options [concat "additional_flags=$TOOL_OPTIONS" $options]; - } - - # search for ffi_mips.h in srcdir, too - lappend options "additional_flags=-I${libffi_include} -I${srcdir}/../include -I${libffi_include}/.." - lappend options "additional_flags=${libffi_link_flags}" - - # Darwin needs a stack execution allowed flag. - - if { [istarget "*-*-darwin9*"] || [istarget "*-*-darwin1*"] - || [istarget "*-*-darwin2*"] } { - lappend options "additional_flags=-Wl,-allow_stack_execute" - } - - # If you're building the compiler with --prefix set to a place - # where it's not yet installed, then the linker won't be able to - # find the libgcc used by libffi.dylib. We could pass the - # -dylib_file option, but that's complicated, and it's much easier - # to just make the linker find libgcc using -L options. - if { [string match "*-*-darwin*" $target_triplet] } { - lappend options "libs= -shared-libgcc" - } - - if { [string match "*-*-openbsd*" $target_triplet] } { - lappend options "libs= -lpthread" - } - - lappend options "libs= -lffi" - - if { [string match "aarch64*-*-linux*" $target_triplet] } { - lappend options "libs= -lpthread" - } - - if { [string match "*.cc" $source] } { - lappend options "c++" - } - - verbose "options: $options" - return [target_compile $source $dest $type $options] -} - -# Utility routines. - -# -# search_for -- looks for a string match in a file -# -proc search_for { file pattern } { - set fd [open $file r] - while { [gets $fd cur_line]>=0 } { - if [string match "*$pattern*" $cur_line] then { - close $fd - return 1 - } - } - close $fd - return 0 -} - -# Modified dg-runtest that can cycle through a list of optimization options -# as c-torture does. -proc libffi-dg-runtest { testcases default-extra-flags } { - global runtests - - foreach test $testcases { - # If we're only testing specific files and this isn't one of - # them, skip it. - if ![runtest_file_p $runtests $test] { - continue - } - - # Look for a loop within the source code - if we don't find one, - # don't pass -funroll[-all]-loops. - global torture_with_loops torture_without_loops - if [expr [search_for $test "for*("]+[search_for $test "while*("]] { - set option_list $torture_with_loops - } else { - set option_list $torture_without_loops - } - - set nshort [file tail [file dirname $test]]/[file tail $test] - - foreach flags $option_list { - verbose "Testing $nshort, $flags" 1 - dg-test $test $flags ${default-extra-flags} - } - } -} - -proc run-many-tests { testcases extra_flags } { - global using_gcc - if { [string match $using_gcc "yes"] } { - set common "-W -Wall -Wno-psabi" - set optimizations { "-O0" "-O2" "-O3" "-Os" "-O2 -fomit-frame-pointer" } - } else { - # Assume we are using the vendor compiler. - set common "" - set optimizations { "" } - } - - set targetabis { "" } - if [string match $using_gcc "yes"] { - if [istarget "i?86-*-*"] { - set targetabis { - "" - "-DABI_NUM=FFI_STDCALL -DABI_ATTR=__STDCALL__" - "-DABI_NUM=FFI_THISCALL -DABI_ATTR=__THISCALL__" - "-DABI_NUM=FFI_FASTCALL -DABI_ATTR=__FASTCALL__" - } - } - } - - set common [ concat $common $extra_flags ] - foreach test $testcases { - set testname [file tail $test] - if [search_for $test "ABI_NUM"] { - set abis $targetabis - } else { - set abis { "" } - } - foreach opt $optimizations { - foreach abi $abis { - set options [concat $common $opt $abi] - verbose "Testing $testname, $options" 1 - dg-test $test $options "" - } - } - } -} - -# Like check_conditional_xfail, but callable from a dg test. - -proc dg-xfail-if { args } { - set args [lreplace $args 0 0] - set selector "target [join [lindex $args 1]]" - if { [dg-process-target $selector] == "S" } { - global compiler_conditional_xfail_data - set compiler_conditional_xfail_data $args - } -} - -proc check-flags { args } { - - # The args are within another list; pull them out. - set args [lindex $args 0] - - # The next two arguments are optional. If they were not specified, - # use the defaults. - if { [llength $args] == 2 } { - lappend $args [list "*"] - } - if { [llength $args] == 3 } { - lappend $args [list ""] - } - - # If the option strings are the defaults, or the same as the - # defaults, there is no need to call check_conditional_xfail to - # compare them to the actual options. - if { [string compare [lindex $args 2] "*"] == 0 - && [string compare [lindex $args 3] "" ] == 0 } { - set result 1 - } else { - # The target list might be an effective-target keyword, so replace - # the original list with "*-*-*", since we already know it matches. - set result [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]] - } - - return $result -} - -proc dg-skip-if { args } { - # Verify the number of arguments. The last two are optional. - set args [lreplace $args 0 0] - if { [llength $args] < 2 || [llength $args] > 4 } { - error "dg-skip-if 2: need 2, 3, or 4 arguments" - } - - # Don't bother if we're already skipping the test. - upvar dg-do-what dg-do-what - if { [lindex ${dg-do-what} 1] == "N" } { - return - } - - set selector [list target [lindex $args 1]] - if { [dg-process-target $selector] == "S" } { - if [check-flags $args] { - upvar dg-do-what dg-do-what - set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"] - } - } -} - -# We need to make sure that additional_files and additional_sources -# are both cleared out after every test. It is not enough to clear -# them out *before* the next test run because gcc-target-compile gets -# run directly from some .exp files (outside of any test). (Those -# uses should eventually be eliminated.) - -# Because the DG framework doesn't provide a hook that is run at the -# end of a test, we must replace dg-test with a wrapper. - -if { [info procs saved-dg-test] == [list] } { - rename dg-test saved-dg-test - - proc dg-test { args } { - global additional_files - global additional_sources - global errorInfo - - if { [ catch { eval saved-dg-test $args } errmsg ] } { - set saved_info $errorInfo - set additional_files "" - set additional_sources "" - error $errmsg $saved_info - } - set additional_files "" - set additional_sources "" - } -} - -# Local Variables: -# tcl-indent-level:4 -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/target-libpath.exp b/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/target-libpath.exp deleted file mode 100644 index 6b7beba93..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/target-libpath.exp +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# This file was contributed by John David Anglin (dave.anglin@nrc-cnrc.gc.ca) - -set orig_environment_saved 0 -set orig_ld_library_path_saved 0 -set orig_ld_run_path_saved 0 -set orig_shlib_path_saved 0 -set orig_ld_libraryn32_path_saved 0 -set orig_ld_library64_path_saved 0 -set orig_ld_library_path_32_saved 0 -set orig_ld_library_path_64_saved 0 -set orig_dyld_library_path_saved 0 -set orig_path_saved 0 - -####################################### -# proc set_ld_library_path_env_vars { } -####################################### - -proc set_ld_library_path_env_vars { } { - global ld_library_path - global orig_environment_saved - global orig_ld_library_path_saved - global orig_ld_run_path_saved - global orig_shlib_path_saved - global orig_ld_libraryn32_path_saved - global orig_ld_library64_path_saved - global orig_ld_library_path_32_saved - global orig_ld_library_path_64_saved - global orig_dyld_library_path_saved - global orig_path_saved - global orig_ld_library_path - global orig_ld_run_path - global orig_shlib_path - global orig_ld_libraryn32_path - global orig_ld_library64_path - global orig_ld_library_path_32 - global orig_ld_library_path_64 - global orig_dyld_library_path - global orig_path - global GCC_EXEC_PREFIX - - # Set the relocated compiler prefix, but only if the user hasn't specified one. - if { [info exists GCC_EXEC_PREFIX] && ![info exists env(GCC_EXEC_PREFIX)] } { - setenv GCC_EXEC_PREFIX "$GCC_EXEC_PREFIX" - } - - # Setting the ld library path causes trouble when testing cross-compilers. - if { [is_remote target] } { - return - } - - if { $orig_environment_saved == 0 } { - global env - - set orig_environment_saved 1 - - # Save the original environment. - if [info exists env(LD_LIBRARY_PATH)] { - set orig_ld_library_path "$env(LD_LIBRARY_PATH)" - set orig_ld_library_path_saved 1 - } - if [info exists env(LD_RUN_PATH)] { - set orig_ld_run_path "$env(LD_RUN_PATH)" - set orig_ld_run_path_saved 1 - } - if [info exists env(SHLIB_PATH)] { - set orig_shlib_path "$env(SHLIB_PATH)" - set orig_shlib_path_saved 1 - } - if [info exists env(LD_LIBRARYN32_PATH)] { - set orig_ld_libraryn32_path "$env(LD_LIBRARYN32_PATH)" - set orig_ld_libraryn32_path_saved 1 - } - if [info exists env(LD_LIBRARY64_PATH)] { - set orig_ld_library64_path "$env(LD_LIBRARY64_PATH)" - set orig_ld_library64_path_saved 1 - } - if [info exists env(LD_LIBRARY_PATH_32)] { - set orig_ld_library_path_32 "$env(LD_LIBRARY_PATH_32)" - set orig_ld_library_path_32_saved 1 - } - if [info exists env(LD_LIBRARY_PATH_64)] { - set orig_ld_library_path_64 "$env(LD_LIBRARY_PATH_64)" - set orig_ld_library_path_64_saved 1 - } - if [info exists env(DYLD_LIBRARY_PATH)] { - set orig_dyld_library_path "$env(DYLD_LIBRARY_PATH)" - set orig_dyld_library_path_saved 1 - } - if [info exists env(PATH)] { - set orig_path "$env(PATH)" - set orig_path_saved 1 - } - } - - # We need to set ld library path in the environment. Currently, - # unix.exp doesn't set the environment correctly for all systems. - # It only sets SHLIB_PATH and LD_LIBRARY_PATH when it executes a - # program. We also need the environment set for compilations, etc. - # - # On IRIX 6, we have to set variables akin to LD_LIBRARY_PATH, but - # called LD_LIBRARYN32_PATH (for the N32 ABI) and LD_LIBRARY64_PATH - # (for the 64-bit ABI). The same applies to Darwin (DYLD_LIBRARY_PATH), - # Solaris 32 bit (LD_LIBRARY_PATH_32), Solaris 64 bit (LD_LIBRARY_PATH_64), - # and HP-UX (SHLIB_PATH). In some cases, the variables are independent - # of LD_LIBRARY_PATH, and in other cases LD_LIBRARY_PATH is used if the - # variable is not defined. - # - # Doing this is somewhat of a hack as ld_library_path gets repeated in - # SHLIB_PATH and LD_LIBRARY_PATH when unix_load sets these variables. - if { $orig_ld_library_path_saved } { - setenv LD_LIBRARY_PATH "$ld_library_path:$orig_ld_library_path" - } else { - setenv LD_LIBRARY_PATH "$ld_library_path" - } - if { $orig_ld_run_path_saved } { - setenv LD_RUN_PATH "$ld_library_path:$orig_ld_run_path" - } else { - setenv LD_RUN_PATH "$ld_library_path" - } - # The default shared library dynamic path search for 64-bit - # HP-UX executables searches LD_LIBRARY_PATH before SHLIB_PATH. - # LD_LIBRARY_PATH isn't used for 32-bit executables. Thus, we - # set LD_LIBRARY_PATH and SHLIB_PATH as if they were independent. - if { $orig_shlib_path_saved } { - setenv SHLIB_PATH "$ld_library_path:$orig_shlib_path" - } else { - setenv SHLIB_PATH "$ld_library_path" - } - if { $orig_ld_libraryn32_path_saved } { - setenv LD_LIBRARYN32_PATH "$ld_library_path:$orig_ld_libraryn32_path" - } elseif { $orig_ld_library_path_saved } { - setenv LD_LIBRARYN32_PATH "$ld_library_path:$orig_ld_library_path" - } else { - setenv LD_LIBRARYN32_PATH "$ld_library_path" - } - if { $orig_ld_library64_path_saved } { - setenv LD_LIBRARY64_PATH "$ld_library_path:$orig_ld_library64_path" - } elseif { $orig_ld_library_path_saved } { - setenv LD_LIBRARY64_PATH "$ld_library_path:$orig_ld_library_path" - } else { - setenv LD_LIBRARY64_PATH "$ld_library_path" - } - if { $orig_ld_library_path_32_saved } { - setenv LD_LIBRARY_PATH_32 "$ld_library_path:$orig_ld_library_path_32" - } elseif { $orig_ld_library_path_saved } { - setenv LD_LIBRARY_PATH_32 "$ld_library_path:$orig_ld_library_path" - } else { - setenv LD_LIBRARY_PATH_32 "$ld_library_path" - } - if { $orig_ld_library_path_64_saved } { - setenv LD_LIBRARY_PATH_64 "$ld_library_path:$orig_ld_library_path_64" - } elseif { $orig_ld_library_path_saved } { - setenv LD_LIBRARY_PATH_64 "$ld_library_path:$orig_ld_library_path" - } else { - setenv LD_LIBRARY_PATH_64 "$ld_library_path" - } - if { $orig_dyld_library_path_saved } { - setenv DYLD_LIBRARY_PATH "$ld_library_path:$orig_dyld_library_path" - } else { - setenv DYLD_LIBRARY_PATH "$ld_library_path" - } - if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } { - if { $orig_path_saved } { - setenv PATH "$ld_library_path:$orig_path" - } else { - setenv PATH "$ld_library_path" - } - } - - verbose -log "set_ld_library_path_env_vars: ld_library_path=$ld_library_path" -} - -####################################### -# proc restore_ld_library_path_env_vars { } -####################################### - -proc restore_ld_library_path_env_vars { } { - global orig_environment_saved - global orig_ld_library_path_saved - global orig_ld_run_path_saved - global orig_shlib_path_saved - global orig_ld_libraryn32_path_saved - global orig_ld_library64_path_saved - global orig_ld_library_path_32_saved - global orig_ld_library_path_64_saved - global orig_dyld_library_path_saved - global orig_path_saved - global orig_ld_library_path - global orig_ld_run_path - global orig_shlib_path - global orig_ld_libraryn32_path - global orig_ld_library64_path - global orig_ld_library_path_32 - global orig_ld_library_path_64 - global orig_dyld_library_path - global orig_path - - if { $orig_environment_saved == 0 } { - return - } - - if { $orig_ld_library_path_saved } { - setenv LD_LIBRARY_PATH "$orig_ld_library_path" - } elseif [info exists env(LD_LIBRARY_PATH)] { - unsetenv LD_LIBRARY_PATH - } - if { $orig_ld_run_path_saved } { - setenv LD_RUN_PATH "$orig_ld_run_path" - } elseif [info exists env(LD_RUN_PATH)] { - unsetenv LD_RUN_PATH - } - if { $orig_shlib_path_saved } { - setenv SHLIB_PATH "$orig_shlib_path" - } elseif [info exists env(SHLIB_PATH)] { - unsetenv SHLIB_PATH - } - if { $orig_ld_libraryn32_path_saved } { - setenv LD_LIBRARYN32_PATH "$orig_ld_libraryn32_path" - } elseif [info exists env(LD_LIBRARYN32_PATH)] { - unsetenv LD_LIBRARYN32_PATH - } - if { $orig_ld_library64_path_saved } { - setenv LD_LIBRARY64_PATH "$orig_ld_library64_path" - } elseif [info exists env(LD_LIBRARY64_PATH)] { - unsetenv LD_LIBRARY64_PATH - } - if { $orig_ld_library_path_32_saved } { - setenv LD_LIBRARY_PATH_32 "$orig_ld_library_path_32" - } elseif [info exists env(LD_LIBRARY_PATH_32)] { - unsetenv LD_LIBRARY_PATH_32 - } - if { $orig_ld_library_path_64_saved } { - setenv LD_LIBRARY_PATH_64 "$orig_ld_library_path_64" - } elseif [info exists env(LD_LIBRARY_PATH_64)] { - unsetenv LD_LIBRARY_PATH_64 - } - if { $orig_dyld_library_path_saved } { - setenv DYLD_LIBRARY_PATH "$orig_dyld_library_path" - } elseif [info exists env(DYLD_LIBRARY_PATH)] { - unsetenv DYLD_LIBRARY_PATH - } - if { $orig_path_saved } { - setenv PATH "$orig_path" - } elseif [info exists env(PATH)] { - unsetenv PATH - } -} - -####################################### -# proc get_shlib_extension { } -####################################### - -proc get_shlib_extension { } { - global shlib_ext - - if { [ istarget *-*-darwin* ] } { - set shlib_ext "dylib" - } elseif { [ istarget *-*-cygwin* ] || [ istarget *-*-mingw* ] } { - set shlib_ext "dll" - } elseif { [ istarget hppa*-*-hpux* ] } { - set shlib_ext "sl" - } else { - set shlib_ext "so" - } - return $shlib_ext -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/wrapper.exp b/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/wrapper.exp deleted file mode 100644 index 4e5ae435a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/lib/wrapper.exp +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2004, 2007 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# This file contains GCC-specifics for status wrappers for test programs. - -# ${tool}_maybe_build_wrapper -- Build wrapper object if the target -# needs it. FILENAME is the path to the wrapper file. If there are -# additional arguments, they are command-line options to provide to -# the compiler when compiling FILENAME. - -proc ${tool}_maybe_build_wrapper { filename args } { - global gluefile wrap_flags - - if { [target_info needs_status_wrapper] != "" \ - && [target_info needs_status_wrapper] != "0" \ - && ![info exists gluefile] } { - set saved_wrap_compile_flags [target_info wrap_compile_flags] - set flags [join $args " "] - # The wrapper code may contain code that gcc objects on. This - # became true for dejagnu-1.4.4. The set of warnings and code - # that gcc objects on may change, so just make sure -w is always - # passed to turn off all warnings. - set_currtarget_info wrap_compile_flags \ - "$saved_wrap_compile_flags -w $flags" - set result [build_wrapper $filename] - set_currtarget_info wrap_compile_flags "$saved_wrap_compile_flags" - if { $result != "" } { - set gluefile [lindex $result 0] - set wrap_flags [lindex $result 1] - } - } -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/call.exp b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/call.exp deleted file mode 100644 index 5177f07f1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/call.exp +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2003, 2006, 2009, 2010, 2014 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING3. If not see -# . - -dg-init -libffi-init - -global srcdir subdir - -set tlist [lsearch -inline -all -not -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*] -set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*] - -run-many-tests $tlist "" - -if { ![istarget s390*] } { - - foreach test $ctlist { - unsupported "$test" - } - -} else { - - run-many-tests $ctlist "" - -} - -dg-finish - -# Local Variables: -# tcl-indent-level:4 -# End: diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn0.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn0.c deleted file mode 100644 index a579ff6c9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn0.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20030828 */ - - - - -/* { dg-do run } */ -#include "ffitest.h" - -static void -closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) + - (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] + - (int)(*(signed short *)args[4]) + - (int)(*(unsigned long long *)args[5]) + - (int)*(int *)args[6] + (int)(*(int *)args[7]) + - (int)(*(double *)args[8]) + (int)*(int *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(int *)args[13]) + - (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]), - (int)(*(unsigned long long *)args[2]), - (int)*(int *)args[3], (int)(*(signed short *)args[4]), - (int)(*(unsigned long long *)args[5]), - (int)*(int *)args[6], (int)(*(int *)args[7]), - (int)(*(double *)args[8]), (int)*(int *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(int *)args[13]), - (int)(*(int *)args[14]),*(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); - -} - -typedef int (*closure_test_type0)(unsigned long long, int, unsigned long long, - int, signed short, unsigned long long, int, - int, double, int, int, float, int, int, - int, int); - -int main (void) -{ - ffi_cif cif; - void * code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_uint64; - cl_arg_types[1] = &ffi_type_sint; - cl_arg_types[2] = &ffi_type_uint64; - cl_arg_types[3] = &ffi_type_sint; - cl_arg_types[4] = &ffi_type_sshort; - cl_arg_types[5] = &ffi_type_uint64; - cl_arg_types[6] = &ffi_type_sint; - cl_arg_types[7] = &ffi_type_sint; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_sint; - cl_arg_types[10] = &ffi_type_sint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_sint; - cl_arg_types[14] = &ffi_type_sint; - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type0)code)) - (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, - 19, 21, 1); - /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 680" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn1.c deleted file mode 100644 index 91231738c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn1.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Area: closure_call. - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - - -static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(float *)args[0] +(int)(*(float *)args[1]) + - (int)(*(float *)args[2]) + (int)*(float *)args[3] + - (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) + - (int)*(float *)args[6] + (int)(*(int *)args[7]) + - (int)(*(double*)args[8]) + (int)*(int *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(int *)args[13]) + - (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(float *)args[0], (int)(*(float *)args[1]), - (int)(*(float *)args[2]), (int)*(float *)args[3], - (int)(*(signed short *)args[4]), (int)(*(float *)args[5]), - (int)*(float *)args[6], (int)(*(int *)args[7]), - (int)(*(double *)args[8]), (int)*(int *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(int *)args[13]), - (int)(*(int *)args[14]), *(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); -} - -typedef int (*closure_test_type1)(float, float, float, float, signed short, - float, float, int, double, int, int, float, - int, int, int, int); -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_float; - cl_arg_types[1] = &ffi_type_float; - cl_arg_types[2] = &ffi_type_float; - cl_arg_types[3] = &ffi_type_float; - cl_arg_types[4] = &ffi_type_sshort; - cl_arg_types[5] = &ffi_type_float; - cl_arg_types[6] = &ffi_type_float; - cl_arg_types[7] = &ffi_type_sint; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_sint; - cl_arg_types[10] = &ffi_type_sint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_sint; - cl_arg_types[14] = &ffi_type_sint; - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type1)code)) - (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13, - 19, 21, 1); - /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 255" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn2.c deleted file mode 100644 index 08ff9d922..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn2.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(double *)args[0] +(int)(*(double *)args[1]) + - (int)(*(double *)args[2]) + (int)*(double *)args[3] + - (int)(*(signed short *)args[4]) + (int)(*(double *)args[5]) + - (int)*(double *)args[6] + (int)(*(int *)args[7]) + - (int)(*(double *)args[8]) + (int)*(int *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(float *)args[13]) + - (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(double *)args[0], (int)(*(double *)args[1]), - (int)(*(double *)args[2]), (int)*(double *)args[3], - (int)(*(signed short *)args[4]), (int)(*(double *)args[5]), - (int)*(double *)args[6], (int)(*(int *)args[7]), - (int)(*(double*)args[8]), (int)*(int *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(float *)args[13]), - (int)(*(int *)args[14]), *(int *)args[15], (int)(intptr_t)userdata, - (int)*(ffi_arg *)resp); -} - -typedef int (*closure_test_type2)(double, double, double, double, signed short, - double, double, int, double, int, int, float, - int, float, int, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_double; - cl_arg_types[1] = &ffi_type_double; - cl_arg_types[2] = &ffi_type_double; - cl_arg_types[3] = &ffi_type_double; - cl_arg_types[4] = &ffi_type_sshort; - cl_arg_types[5] = &ffi_type_double; - cl_arg_types[6] = &ffi_type_double; - cl_arg_types[7] = &ffi_type_sint; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_sint; - cl_arg_types[10] = &ffi_type_sint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_float; - cl_arg_types[14] = &ffi_type_sint; - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn2, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type2)code)) - (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13, - 19.0, 21, 1); - /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 255" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn3.c deleted file mode 100644 index 9b54d805c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn3.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) - { - *(ffi_arg*)resp = - (int)*(float *)args[0] +(int)(*(float *)args[1]) + - (int)(*(float *)args[2]) + (int)*(float *)args[3] + - (int)(*(float *)args[4]) + (int)(*(float *)args[5]) + - (int)*(float *)args[6] + (int)(*(float *)args[7]) + - (int)(*(double *)args[8]) + (int)*(int *)args[9] + - (int)(*(float *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(float *)args[13]) + - (int)(*(float *)args[14]) + *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(float *)args[0], (int)(*(float *)args[1]), - (int)(*(float *)args[2]), (int)*(float *)args[3], - (int)(*(float *)args[4]), (int)(*(float *)args[5]), - (int)*(float *)args[6], (int)(*(float *)args[7]), - (int)(*(double *)args[8]), (int)*(int *)args[9], - (int)(*(float *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(float *)args[13]), - (int)(*(float *)args[14]), *(int *)args[15], (int)(intptr_t)userdata, - (int)*(ffi_arg *)resp); - - } - -typedef int (*closure_test_type3)(float, float, float, float, float, float, - float, float, double, int, float, float, int, - float, float, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_float; - cl_arg_types[1] = &ffi_type_float; - cl_arg_types[2] = &ffi_type_float; - cl_arg_types[3] = &ffi_type_float; - cl_arg_types[4] = &ffi_type_float; - cl_arg_types[5] = &ffi_type_float; - cl_arg_types[6] = &ffi_type_float; - cl_arg_types[7] = &ffi_type_float; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_sint; - cl_arg_types[10] = &ffi_type_float; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_float; - cl_arg_types[14] = &ffi_type_float; - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn3, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type3)code)) - (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13, - 19.19, 21.21, 1); - /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 19 21 1 3: 135" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 135" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn4.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn4.c deleted file mode 100644 index d4a1530b0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn4.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple long long values passing. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20031026 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static void -closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] + - (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] + - (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] + - (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] + - (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] + - (int)*(unsigned long long *)args[10] + - (int)*(unsigned long long *)args[11] + - (int)*(unsigned long long *)args[12] + - (int)*(unsigned long long *)args[13] + - (int)*(unsigned long long *)args[14] + - *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(unsigned long long *)args[0], - (int)*(unsigned long long *)args[1], - (int)*(unsigned long long *)args[2], - (int)*(unsigned long long *)args[3], - (int)*(unsigned long long *)args[4], - (int)*(unsigned long long *)args[5], - (int)*(unsigned long long *)args[6], - (int)*(unsigned long long *)args[7], - (int)*(unsigned long long *)args[8], - (int)*(unsigned long long *)args[9], - (int)*(unsigned long long *)args[10], - (int)*(unsigned long long *)args[11], - (int)*(unsigned long long *)args[12], - (int)*(unsigned long long *)args[13], - (int)*(unsigned long long *)args[14], - *(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); - -} - -typedef int (*closure_test_type0)(unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int i, res; - - for (i = 0; i < 15; i++) { - cl_arg_types[i] = &ffi_type_uint64; - } - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type0)code)) - (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11LL, 12LL, - 13LL, 19LL, 21LL, 1); - /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 680" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn5.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn5.c deleted file mode 100644 index 99074426c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn5.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple long long values passing. - Exceed the limit of gpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20031026 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void -closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] + - (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] + - (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] + - (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] + - (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] + - (int)*(int *)args[10] + - (int)*(unsigned long long *)args[11] + - (int)*(unsigned long long *)args[12] + - (int)*(unsigned long long *)args[13] + - (int)*(unsigned long long *)args[14] + - *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(unsigned long long *)args[0], - (int)*(unsigned long long *)args[1], - (int)*(unsigned long long *)args[2], - (int)*(unsigned long long *)args[3], - (int)*(unsigned long long *)args[4], - (int)*(unsigned long long *)args[5], - (int)*(unsigned long long *)args[6], - (int)*(unsigned long long *)args[7], - (int)*(unsigned long long *)args[8], - (int)*(unsigned long long *)args[9], - (int)*(int *)args[10], - (int)*(unsigned long long *)args[11], - (int)*(unsigned long long *)args[12], - (int)*(unsigned long long *)args[13], - (int)*(unsigned long long *)args[14], - *(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); - -} - -typedef int (*closure_test_type0)(unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, unsigned long long, - int, unsigned long long, - unsigned long long, unsigned long long, - unsigned long long, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int i, res; - - for (i = 0; i < 10; i++) { - cl_arg_types[i] = &ffi_type_uint64; - } - cl_arg_types[10] = &ffi_type_sint; - for (i = 11; i < 15; i++) { - cl_arg_types[i] = &ffi_type_uint64; - } - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn5, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type0)code)) - (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11, 12LL, - 13LL, 19LL, 21LL, 1); - /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 680" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn6.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn6.c deleted file mode 100644 index 73c54fd6b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_fn6.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC. - Limitations: none. - PR: PR23404 - Originator: 20050830 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void -closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(unsigned long long *)args[0] + - (int)(*(unsigned long long *)args[1]) + - (int)(*(unsigned long long *)args[2]) + - (int)*(unsigned long long *)args[3] + - (int)(*(int *)args[4]) + (int)(*(double *)args[5]) + - (int)*(double *)args[6] + (int)(*(float *)args[7]) + - (int)(*(double *)args[8]) + (int)*(double *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(int *)args[13]) + - (int)(*(double *)args[14]) + (int)*(double *)args[15] + - (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(unsigned long long *)args[0], - (int)(*(unsigned long long *)args[1]), - (int)(*(unsigned long long *)args[2]), - (int)*(unsigned long long *)args[3], - (int)(*(int *)args[4]), (int)(*(double *)args[5]), - (int)*(double *)args[6], (int)(*(float *)args[7]), - (int)(*(double *)args[8]), (int)*(double *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(int *)args[13]), - (int)(*(double *)args[14]), (int)(*(double *)args[15]), - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); - -} - -typedef int (*closure_test_type0)(unsigned long long, - unsigned long long, - unsigned long long, - unsigned long long, - int, double, double, float, double, double, - int, float, int, int, double, double); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_uint64; - cl_arg_types[1] = &ffi_type_uint64; - cl_arg_types[2] = &ffi_type_uint64; - cl_arg_types[3] = &ffi_type_uint64; - cl_arg_types[4] = &ffi_type_sint; - cl_arg_types[5] = &ffi_type_double; - cl_arg_types[6] = &ffi_type_double; - cl_arg_types[7] = &ffi_type_float; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_double; - cl_arg_types[10] = &ffi_type_sint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_sint; - cl_arg_types[14] = &ffi_type_double; - cl_arg_types[15] = &ffi_type_double; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*((closure_test_type0)code)) - (1, 2, 3, 4, 127, 429., 7., 8., 9.5, 10., 11, 12., 13, - 19, 21., 1.); - /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 680" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_loc_fn0.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_loc_fn0.c deleted file mode 100644 index b3afa0bbd..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_loc_fn0.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Area: closure_call - Purpose: Check multiple values passing from different type. - Also, exceed the limit of gpr and fpr registers on PowerPC - Darwin. - Limitations: none. - PR: none. - Originator: 20030828 */ - - - - -/* { dg-do run } */ -#include "ffitest.h" - -static void -closure_loc_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata) -{ - *(ffi_arg*)resp = - (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) + - (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] + - (int)(*(signed short *)args[4]) + - (int)(*(unsigned long long *)args[5]) + - (int)*(int *)args[6] + (int)(*(int *)args[7]) + - (int)(*(double *)args[8]) + (int)*(int *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(int *)args[13]) + - (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]), - (int)(*(unsigned long long *)args[2]), - (int)*(int *)args[3], (int)(*(signed short *)args[4]), - (int)(*(unsigned long long *)args[5]), - (int)*(int *)args[6], (int)(*(int *)args[7]), - (int)(*(double *)args[8]), (int)*(int *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(int *)args[13]), - (int)(*(int *)args[14]),*(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg *)resp); - -} - -typedef int (*closure_loc_test_type0)(unsigned long long, int, unsigned long long, - int, signed short, unsigned long long, int, - int, double, int, int, float, int, int, - int, int); - -int main (void) -{ - ffi_cif cif; - ffi_closure *pcl; - ffi_type * cl_arg_types[17]; - int res; - void *codeloc; - - cl_arg_types[0] = &ffi_type_uint64; - cl_arg_types[1] = &ffi_type_sint; - cl_arg_types[2] = &ffi_type_uint64; - cl_arg_types[3] = &ffi_type_sint; - cl_arg_types[4] = &ffi_type_sshort; - cl_arg_types[5] = &ffi_type_uint64; - cl_arg_types[6] = &ffi_type_sint; - cl_arg_types[7] = &ffi_type_sint; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_sint; - cl_arg_types[10] = &ffi_type_sint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_sint; - cl_arg_types[13] = &ffi_type_sint; - cl_arg_types[14] = &ffi_type_sint; - cl_arg_types[15] = &ffi_type_sint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - pcl = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - CHECK(pcl != NULL); - CHECK(codeloc != NULL); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_loc_test_fn0, - (void *) 3 /* userdata */, codeloc) == FFI_OK); - - CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0); - - res = (*((closure_loc_test_type0)codeloc)) - (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, - 19, 21, 1); - /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 680" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_simple.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_simple.c deleted file mode 100644 index 5a4e728d4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/closure_simple.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Area: closure_call - Purpose: Check simple closure handling with all ABIs - Limitations: none. - PR: none. - Originator: */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void -closure_test(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata) -{ - *(ffi_arg*)resp = - (int)*(int *)args[0] + (int)(*(int *)args[1]) - + (int)(*(int *)args[2]) + (int)(*(int *)args[3]) - + (int)(intptr_t)userdata; - - printf("%d %d %d %d: %d\n", - (int)*(int *)args[0], (int)(*(int *)args[1]), - (int)(*(int *)args[2]), (int)(*(int *)args[3]), - (int)*(ffi_arg *)resp); - -} - -typedef int (ABI_ATTR *closure_test_type0)(int, int, int, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - int res; - - cl_arg_types[0] = &ffi_type_uint; - cl_arg_types[1] = &ffi_type_uint; - cl_arg_types[2] = &ffi_type_uint; - cl_arg_types[3] = &ffi_type_uint; - cl_arg_types[4] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test, - (void *) 3 /* userdata */, code) == FFI_OK); - - res = (*(closure_test_type0)code)(0, 1, 2, 3); - /* { dg-output "0 1 2 3: 9" } */ - - printf("res: %d\n",res); - /* { dg-output "\nres: 9" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_12byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_12byte.c deleted file mode 100644 index ea0825d17..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_12byte.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_12byte { - int a; - int b; - int c; -} cls_struct_12byte; - -cls_struct_12byte cls_struct_12byte_fn(struct cls_struct_12byte b1, - struct cls_struct_12byte b2) -{ - struct cls_struct_12byte result; - - result.a = b1.a + b2.a; - result.b = b1.b + b2.b; - result.c = b1.c + b2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c, - result.a, result.b, result.c); - - return result; -} - -static void cls_struct_12byte_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args , void* userdata __UNUSED__) -{ - struct cls_struct_12byte b1, b2; - - b1 = *(struct cls_struct_12byte*)(args[0]); - b2 = *(struct cls_struct_12byte*)(args[1]); - - *(cls_struct_12byte*)resp = cls_struct_12byte_fn(b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_12byte h_dbl = { 7, 4, 9 }; - struct cls_struct_12byte j_dbl = { 1, 5, 3 }; - struct cls_struct_12byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_sint; - cls_struct_fields[1] = &ffi_type_sint; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &h_dbl; - args_dbl[1] = &j_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_12byte_fn), &res_dbl, args_dbl); - /* { dg-output "7 4 9 1 5 3: 8 9 12" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 8 9 12" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_12byte_gn, NULL, code) == FFI_OK); - - res_dbl.a = 0; - res_dbl.b = 0; - res_dbl.c = 0; - - res_dbl = ((cls_struct_12byte(*)(cls_struct_12byte, cls_struct_12byte))(code))(h_dbl, j_dbl); - /* { dg-output "\n7 4 9 1 5 3: 8 9 12" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 8 9 12" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_16byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_16byte.c deleted file mode 100644 index 89a08a2d9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_16byte.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_16byte { - int a; - double b; - int c; -} cls_struct_16byte; - -cls_struct_16byte cls_struct_16byte_fn(struct cls_struct_16byte b1, - struct cls_struct_16byte b2) -{ - struct cls_struct_16byte result; - - result.a = b1.a + b2.a; - result.b = b1.b + b2.b; - result.c = b1.c + b2.c; - - printf("%d %g %d %d %g %d: %d %g %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c, - result.a, result.b, result.c); - - return result; -} - -static void cls_struct_16byte_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - struct cls_struct_16byte b1, b2; - - b1 = *(struct cls_struct_16byte*)(args[0]); - b2 = *(struct cls_struct_16byte*)(args[1]); - - *(cls_struct_16byte*)resp = cls_struct_16byte_fn(b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_16byte h_dbl = { 7, 8.0, 9 }; - struct cls_struct_16byte j_dbl = { 1, 9.0, 3 }; - struct cls_struct_16byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_sint; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &h_dbl; - args_dbl[1] = &j_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_16byte_fn), &res_dbl, args_dbl); - /* { dg-output "7 8 9 1 9 3: 8 17 12" } */ - printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 8 17 12" } */ - - res_dbl.a = 0; - res_dbl.b = 0.0; - res_dbl.c = 0; - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_16byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(code))(h_dbl, j_dbl); - /* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */ - printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 8 17 12" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_18byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_18byte.c deleted file mode 100644 index 9f75da80a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_18byte.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Double alignment check on darwin. - Limitations: none. - PR: none. - Originator: 20030915 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_18byte { - double a; - unsigned char b; - unsigned char c; - double d; -} cls_struct_18byte; - -cls_struct_18byte cls_struct_18byte_fn(struct cls_struct_18byte a1, - struct cls_struct_18byte a2) -{ - struct cls_struct_18byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - - - printf("%g %d %d %g %g %d %d %g: %g %d %d %g\n", a1.a, a1.b, a1.c, a1.d, - a2.a, a2.b, a2.c, a2.d, - result.a, result.b, result.c, result.d); - return result; -} - -static void -cls_struct_18byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_18byte a1, a2; - - a1 = *(struct cls_struct_18byte*)(args[0]); - a2 = *(struct cls_struct_18byte*)(args[1]); - - *(cls_struct_18byte*)resp = cls_struct_18byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[5]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_18byte g_dbl = { 1.0, 127, 126, 3.0 }; - struct cls_struct_18byte f_dbl = { 4.0, 125, 124, 5.0 }; - struct cls_struct_18byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_18byte_fn), &res_dbl, args_dbl); - /* { dg-output "1 127 126 3 4 125 124 5: 5 252 250 8" } */ - printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 5 252 250 8" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_18byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_18byte(*)(cls_struct_18byte, cls_struct_18byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 127 126 3 4 125 124 5: 5 252 250 8" } */ - printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 5 252 250 8" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_19byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_19byte.c deleted file mode 100644 index 278794b5b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_19byte.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Double alignment check on darwin. - Limitations: none. - PR: none. - Originator: 20030915 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_19byte { - double a; - unsigned char b; - unsigned char c; - double d; - unsigned char e; -} cls_struct_19byte; - -cls_struct_19byte cls_struct_19byte_fn(struct cls_struct_19byte a1, - struct cls_struct_19byte a2) -{ - struct cls_struct_19byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - result.e = a1.e + a2.e; - - - printf("%g %d %d %g %d %g %d %d %g %d: %g %d %d %g %d\n", - a1.a, a1.b, a1.c, a1.d, a1.e, - a2.a, a2.b, a2.c, a2.d, a2.e, - result.a, result.b, result.c, result.d, result.e); - return result; -} - -static void -cls_struct_19byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_19byte a1, a2; - - a1 = *(struct cls_struct_19byte*)(args[0]); - a2 = *(struct cls_struct_19byte*)(args[1]); - - *(cls_struct_19byte*)resp = cls_struct_19byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[6]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_19byte g_dbl = { 1.0, 127, 126, 3.0, 120 }; - struct cls_struct_19byte f_dbl = { 4.0, 125, 124, 5.0, 119 }; - struct cls_struct_19byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_uchar; - cls_struct_fields[5] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_19byte_fn), &res_dbl, args_dbl); - /* { dg-output "1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */ - printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e); - /* { dg-output "\nres: 5 252 250 8 239" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_19byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_19byte(*)(cls_struct_19byte, cls_struct_19byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */ - printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e); - /* { dg-output "\nres: 5 252 250 8 239" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_1_1byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_1_1byte.c deleted file mode 100644 index 82492c020..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_1_1byte.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. - Limitations: none. - PR: none. - Originator: 20030902 */ - - - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_1_1byte { - unsigned char a; -} cls_struct_1_1byte; - -cls_struct_1_1byte cls_struct_1_1byte_fn(struct cls_struct_1_1byte a1, - struct cls_struct_1_1byte a2) -{ - struct cls_struct_1_1byte result; - - result.a = a1.a + a2.a; - - printf("%d %d: %d\n", a1.a, a2.a, result.a); - - return result; -} - -static void -cls_struct_1_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_1_1byte a1, a2; - - a1 = *(struct cls_struct_1_1byte*)(args[0]); - a2 = *(struct cls_struct_1_1byte*)(args[1]); - - *(cls_struct_1_1byte*)resp = cls_struct_1_1byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[2]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_1_1byte g_dbl = { 12 }; - struct cls_struct_1_1byte f_dbl = { 178 }; - struct cls_struct_1_1byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_1_1byte_fn), &res_dbl, args_dbl); - /* { dg-output "12 178: 190" } */ - printf("res: %d\n", res_dbl.a); - /* { dg-output "\nres: 190" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_1_1byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_1_1byte(*)(cls_struct_1_1byte, cls_struct_1_1byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 178: 190" } */ - printf("res: %d\n", res_dbl.a); - /* { dg-output "\nres: 190" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte.c deleted file mode 100644 index 3f8bb28ad..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_20byte { - double a; - double b; - int c; -} cls_struct_20byte; - -cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, - struct cls_struct_20byte a2) -{ - struct cls_struct_20byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%g %g %d %g %g %d: %g %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, - result.a, result.b, result.c); - return result; -} - -static void -cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_20byte a1, a2; - - a1 = *(struct cls_struct_20byte*)(args[0]); - a2 = *(struct cls_struct_20byte*)(args[1]); - - *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_20byte g_dbl = { 1.0, 2.0, 3 }; - struct cls_struct_20byte f_dbl = { 4.0, 5.0, 7 }; - struct cls_struct_20byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl); - /* { dg-output "1 2 3 4 5 7: 5 7 10" } */ - printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 5 7 10" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */ - printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 5 7 10" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte1.c deleted file mode 100644 index 65627273c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_20byte1.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - - - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_20byte { - int a; - double b; - double c; -} cls_struct_20byte; - -cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, - struct cls_struct_20byte a2) -{ - struct cls_struct_20byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %g %g %d %g %g: %d %g %g\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, - result.a, result.b, result.c); - return result; -} - -static void -cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_20byte a1, a2; - - a1 = *(struct cls_struct_20byte*)(args[0]); - a2 = *(struct cls_struct_20byte*)(args[1]); - - *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_20byte g_dbl = { 1, 2.0, 3.0 }; - struct cls_struct_20byte f_dbl = { 4, 5.0, 7.0 }; - struct cls_struct_20byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_sint; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl); - /* { dg-output "1 2 3 4 5 7: 5 7 10" } */ - printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 5 7 10" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */ - printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 5 7 10" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_24byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_24byte.c deleted file mode 100644 index 1d82f6e4a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_24byte.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_24byte { - double a; - double b; - int c; - float d; -} cls_struct_24byte; - -cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0, - struct cls_struct_24byte b1, - struct cls_struct_24byte b2, - struct cls_struct_24byte b3) -{ - struct cls_struct_24byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - - printf("%g %g %d %g %g %g %d %g %g %g %d %g %g %g %d %g: %g %g %d %g\n", - b0.a, b0.b, b0.c, b0.d, - b1.a, b1.b, b1.c, b1.d, - b2.a, b2.b, b2.c, b2.d, - b3.a, b3.b, b3.c, b2.d, - result.a, result.b, result.c, result.d); - - return result; -} - -static void -cls_struct_24byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_24byte b0, b1, b2, b3; - - b0 = *(struct cls_struct_24byte*)(args[0]); - b1 = *(struct cls_struct_24byte*)(args[1]); - b2 = *(struct cls_struct_24byte*)(args[2]); - b3 = *(struct cls_struct_24byte*)(args[3]); - - *(cls_struct_24byte*)resp = cls_struct_24byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_24byte e_dbl = { 9.0, 2.0, 6, 5.0 }; - struct cls_struct_24byte f_dbl = { 1.0, 2.0, 3, 7.0 }; - struct cls_struct_24byte g_dbl = { 4.0, 5.0, 7, 9.0 }; - struct cls_struct_24byte h_dbl = { 8.0, 6.0, 1, 4.0 }; - struct cls_struct_24byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = &ffi_type_float; - cls_struct_fields[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_24byte_fn), &res_dbl, args_dbl); - /* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */ - printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 22 15 17 25" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_24byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_24byte(*)(cls_struct_24byte, - cls_struct_24byte, - cls_struct_24byte, - cls_struct_24byte)) - (code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */ - printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 22 15 17 25" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_2byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_2byte.c deleted file mode 100644 index 81bb0a64a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_2byte.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_2byte { - unsigned char a; - unsigned char b; -} cls_struct_2byte; - -cls_struct_2byte cls_struct_2byte_fn(struct cls_struct_2byte a1, - struct cls_struct_2byte a2) -{ - struct cls_struct_2byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - - printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b); - - return result; -} - -static void -cls_struct_2byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_2byte a1, a2; - - a1 = *(struct cls_struct_2byte*)(args[0]); - a2 = *(struct cls_struct_2byte*)(args[1]); - - *(cls_struct_2byte*)resp = cls_struct_2byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_2byte g_dbl = { 12, 127 }; - struct cls_struct_2byte f_dbl = { 1, 13 }; - struct cls_struct_2byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_2byte_fn), &res_dbl, args_dbl); - /* { dg-output "12 127 1 13: 13 140" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 13 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_2byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_2byte(*)(cls_struct_2byte, cls_struct_2byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 127 1 13: 13 140" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 13 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3_1byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3_1byte.c deleted file mode 100644 index b7827466f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3_1byte.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. - Limitations: none. - PR: none. - Originator: 20030902 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_3_1byte { - unsigned char a; - unsigned char b; - unsigned char c; -} cls_struct_3_1byte; - -cls_struct_3_1byte cls_struct_3_1byte_fn(struct cls_struct_3_1byte a1, - struct cls_struct_3_1byte a2) -{ - struct cls_struct_3_1byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, - a2.a, a2.b, a2.c, - result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_3_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_3_1byte a1, a2; - - a1 = *(struct cls_struct_3_1byte*)(args[0]); - a2 = *(struct cls_struct_3_1byte*)(args[1]); - - *(cls_struct_3_1byte*)resp = cls_struct_3_1byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_3_1byte g_dbl = { 12, 13, 14 }; - struct cls_struct_3_1byte f_dbl = { 178, 179, 180 }; - struct cls_struct_3_1byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_3_1byte_fn), &res_dbl, args_dbl); - /* { dg-output "12 13 14 178 179 180: 190 192 194" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 190 192 194" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3_1byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_3_1byte(*)(cls_struct_3_1byte, cls_struct_3_1byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 13 14 178 179 180: 190 192 194" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 190 192 194" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte1.c deleted file mode 100644 index a02c463af..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte1.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_3byte { - unsigned short a; - unsigned char b; -} cls_struct_3byte; - -cls_struct_3byte cls_struct_3byte_fn(struct cls_struct_3byte a1, - struct cls_struct_3byte a2) -{ - struct cls_struct_3byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - - printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b); - - return result; -} - -static void -cls_struct_3byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_3byte a1, a2; - - a1 = *(struct cls_struct_3byte*)(args[0]); - a2 = *(struct cls_struct_3byte*)(args[1]); - - *(cls_struct_3byte*)resp = cls_struct_3byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_3byte g_dbl = { 12, 119 }; - struct cls_struct_3byte f_dbl = { 1, 15 }; - struct cls_struct_3byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_ushort; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_3byte_fn), &res_dbl, args_dbl); - /* { dg-output "12 119 1 15: 13 134" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 13 134" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 119 1 15: 13 134" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 13 134" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte2.c deleted file mode 100644 index c7251cead..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_3byte2.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_3byte_1 { - unsigned char a; - unsigned short b; -} cls_struct_3byte_1; - -cls_struct_3byte_1 cls_struct_3byte_fn1(struct cls_struct_3byte_1 a1, - struct cls_struct_3byte_1 a2) -{ - struct cls_struct_3byte_1 result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - - printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b); - - return result; -} - -static void -cls_struct_3byte_gn1(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_3byte_1 a1, a2; - - a1 = *(struct cls_struct_3byte_1*)(args[0]); - a2 = *(struct cls_struct_3byte_1*)(args[1]); - - *(cls_struct_3byte_1*)resp = cls_struct_3byte_fn1(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_3byte_1 g_dbl = { 15, 125 }; - struct cls_struct_3byte_1 f_dbl = { 9, 19 }; - struct cls_struct_3byte_1 res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_3byte_fn1), &res_dbl, args_dbl); - /* { dg-output "15 125 9 19: 24 144" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 24 144" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn1, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(code))(g_dbl, f_dbl); - /* { dg-output "\n15 125 9 19: 24 144" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 24 144" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4_1byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4_1byte.c deleted file mode 100644 index 2d6d8b622..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4_1byte.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Especially with small structures which may fit in one - register. Depending on the ABI. - Limitations: none. - PR: none. - Originator: 20030902 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_4_1byte { - unsigned char a; - unsigned char b; - unsigned char c; - unsigned char d; -} cls_struct_4_1byte; - -cls_struct_4_1byte cls_struct_4_1byte_fn(struct cls_struct_4_1byte a1, - struct cls_struct_4_1byte a2) -{ - struct cls_struct_4_1byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - - printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d, - a2.a, a2.b, a2.c, a2.d, - result.a, result.b, result.c, result.d); - - return result; -} - -static void -cls_struct_4_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_4_1byte a1, a2; - - a1 = *(struct cls_struct_4_1byte*)(args[0]); - a2 = *(struct cls_struct_4_1byte*)(args[1]); - - *(cls_struct_4_1byte*)resp = cls_struct_4_1byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_4_1byte g_dbl = { 12, 13, 14, 15 }; - struct cls_struct_4_1byte f_dbl = { 178, 179, 180, 181 }; - struct cls_struct_4_1byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_uchar; - cls_struct_fields[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_4_1byte_fn), &res_dbl, args_dbl); - /* { dg-output "12 13 14 15 178 179 180 181: 190 192 194 196" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 190 192 194 196" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4_1byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 190 192 194 196" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4byte.c deleted file mode 100644 index 4ac378776..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_4byte.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -typedef struct cls_struct_4byte { - unsigned short a; - unsigned short b; -} cls_struct_4byte; - -cls_struct_4byte cls_struct_4byte_fn(struct cls_struct_4byte a1, - struct cls_struct_4byte a2) -{ - struct cls_struct_4byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - - printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b); - - return result; -} - -static void -cls_struct_4byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_4byte a1, a2; - - a1 = *(struct cls_struct_4byte*)(args[0]); - a2 = *(struct cls_struct_4byte*)(args[1]); - - *(cls_struct_4byte*)resp = cls_struct_4byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_4byte g_dbl = { 127, 120 }; - struct cls_struct_4byte f_dbl = { 12, 128 }; - struct cls_struct_4byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_ushort; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_4byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 12 128: 139 248" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 139 248" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_4byte(*)(cls_struct_4byte, cls_struct_4byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 12 128: 139 248" } */ - printf("res: %d %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 139 248" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5_1_byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5_1_byte.c deleted file mode 100644 index ad9d51c24..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5_1_byte.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20050708 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_5byte { - unsigned char a; - unsigned char b; - unsigned char c; - unsigned char d; - unsigned char e; -} cls_struct_5byte; - -cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, - struct cls_struct_5byte a2) -{ - struct cls_struct_5byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - result.e = a1.e + a2.e; - - printf("%d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d\n", - a1.a, a1.b, a1.c, a1.d, a1.e, - a2.a, a2.b, a2.c, a2.d, a2.e, - result.a, result.b, result.c, result.d, result.e); - - return result; -} - -static void -cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_5byte a1, a2; - - a1 = *(struct cls_struct_5byte*)(args[0]); - a2 = *(struct cls_struct_5byte*)(args[1]); - - *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[6]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_5byte g_dbl = { 127, 120, 1, 3, 4 }; - struct cls_struct_5byte f_dbl = { 12, 128, 9, 3, 4 }; - struct cls_struct_5byte res_dbl = { 0, 0, 0, 0, 0 }; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_uchar; - cls_struct_fields[4] = &ffi_type_uchar; - cls_struct_fields[5] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */ - printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e); - /* { dg-output "\nres: 139 248 10 6 8" } */ - - res_dbl.a = 0; - res_dbl.b = 0; - res_dbl.c = 0; - res_dbl.d = 0; - res_dbl.e = 0; - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */ - printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e); - /* { dg-output "\nres: 139 248 10 6 8" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5byte.c deleted file mode 100644 index 4e0c0003c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_5byte.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_5byte { - unsigned short a; - unsigned short b; - unsigned char c; -} cls_struct_5byte; - -cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, - struct cls_struct_5byte a2) -{ - struct cls_struct_5byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, - a2.a, a2.b, a2.c, - result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_5byte a1, a2; - - a1 = *(struct cls_struct_5byte*)(args[0]); - a2 = *(struct cls_struct_5byte*)(args[1]); - - *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_5byte g_dbl = { 127, 120, 1 }; - struct cls_struct_5byte f_dbl = { 12, 128, 9 }; - struct cls_struct_5byte res_dbl = { 0, 0, 0 }; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_ushort; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 12 128 9: 139 248 10" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 139 248 10" } */ - - res_dbl.a = 0; - res_dbl.b = 0; - res_dbl.c = 0; - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 12 128 9: 139 248 10" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 139 248 10" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_64byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_64byte.c deleted file mode 100644 index a55edc2c7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_64byte.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check bigger struct which overlaps - the gp and fp register count on Darwin/AIX/ppc64. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_64byte { - double a; - double b; - double c; - double d; - double e; - double f; - double g; - double h; -} cls_struct_64byte; - -cls_struct_64byte cls_struct_64byte_fn(struct cls_struct_64byte b0, - struct cls_struct_64byte b1, - struct cls_struct_64byte b2, - struct cls_struct_64byte b3) -{ - struct cls_struct_64byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - result.e = b0.e + b1.e + b2.e + b3.e; - result.f = b0.f + b1.f + b2.f + b3.f; - result.g = b0.g + b1.g + b2.g + b3.g; - result.h = b0.h + b1.h + b2.h + b3.h; - - printf("%g %g %g %g %g %g %g %g\n", result.a, result.b, result.c, - result.d, result.e, result.f, result.g, result.h); - - return result; -} - -static void -cls_struct_64byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_64byte b0, b1, b2, b3; - - b0 = *(struct cls_struct_64byte*)(args[0]); - b1 = *(struct cls_struct_64byte*)(args[1]); - b2 = *(struct cls_struct_64byte*)(args[2]); - b3 = *(struct cls_struct_64byte*)(args[3]); - - *(cls_struct_64byte*)resp = cls_struct_64byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[9]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_64byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0 }; - struct cls_struct_64byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0 }; - struct cls_struct_64byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0 }; - struct cls_struct_64byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0 }; - struct cls_struct_64byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_double; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_double; - cls_struct_fields[7] = &ffi_type_double; - cls_struct_fields[8] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_64byte_fn), &res_dbl, args_dbl); - /* { dg-output "22 15 17 25 6 13 19 18" } */ - printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_64byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_64byte(*)(cls_struct_64byte, - cls_struct_64byte, - cls_struct_64byte, - cls_struct_64byte)) - (code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n22 15 17 25 6 13 19 18" } */ - printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6_1_byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6_1_byte.c deleted file mode 100644 index b4dcdba47..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6_1_byte.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20050708 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_6byte { - unsigned char a; - unsigned char b; - unsigned char c; - unsigned char d; - unsigned char e; - unsigned char f; -} cls_struct_6byte; - -cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, - struct cls_struct_6byte a2) -{ - struct cls_struct_6byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - result.e = a1.e + a2.e; - result.f = a1.f + a2.f; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d\n", - a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, - a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, - result.a, result.b, result.c, result.d, result.e, result.f); - - return result; -} - -static void -cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_6byte a1, a2; - - a1 = *(struct cls_struct_6byte*)(args[0]); - a2 = *(struct cls_struct_6byte*)(args[1]); - - *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[7]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_6byte g_dbl = { 127, 120, 1, 3, 4, 5 }; - struct cls_struct_6byte f_dbl = { 12, 128, 9, 3, 4, 5 }; - struct cls_struct_6byte res_dbl = { 0, 0, 0, 0, 0, 0 }; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_uchar; - cls_struct_fields[4] = &ffi_type_uchar; - cls_struct_fields[5] = &ffi_type_uchar; - cls_struct_fields[6] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */ - printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f); - /* { dg-output "\nres: 139 248 10 6 8 10" } */ - - res_dbl.a = 0; - res_dbl.b = 0; - res_dbl.c = 0; - res_dbl.d = 0; - res_dbl.e = 0; - res_dbl.f = 0; - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */ - printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f); - /* { dg-output "\nres: 139 248 10 6 8 10" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6byte.c deleted file mode 100644 index 740678017..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_6byte.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_6byte { - unsigned short a; - unsigned short b; - unsigned char c; - unsigned char d; -} cls_struct_6byte; - -cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, - struct cls_struct_6byte a2) -{ - struct cls_struct_6byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - - printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d, - a2.a, a2.b, a2.c, a2.d, - result.a, result.b, result.c, result.d); - - return result; -} - -static void -cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_6byte a1, a2; - - a1 = *(struct cls_struct_6byte*)(args[0]); - a2 = *(struct cls_struct_6byte*)(args[1]); - - *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_6byte g_dbl = { 127, 120, 1, 128 }; - struct cls_struct_6byte f_dbl = { 12, 128, 9, 127 }; - struct cls_struct_6byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_ushort; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_uchar; - cls_struct_fields[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 128 12 128 9 127: 139 248 10 255" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 139 248 10 255" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 128 12 128 9 127: 139 248 10 255" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 139 248 10 255" } */ - - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7_1_byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7_1_byte.c deleted file mode 100644 index 14a7e96f9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7_1_byte.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20050708 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_7byte { - unsigned char a; - unsigned char b; - unsigned char c; - unsigned char d; - unsigned char e; - unsigned char f; - unsigned char g; -} cls_struct_7byte; - -cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, - struct cls_struct_7byte a2) -{ - struct cls_struct_7byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - result.e = a1.e + a2.e; - result.f = a1.f + a2.f; - result.g = a1.g + a2.g; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d %d\n", - a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g, - a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g, - result.a, result.b, result.c, result.d, result.e, result.f, result.g); - - return result; -} - -static void -cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_7byte a1, a2; - - a1 = *(struct cls_struct_7byte*)(args[0]); - a2 = *(struct cls_struct_7byte*)(args[1]); - - *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[8]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_7byte g_dbl = { 127, 120, 1, 3, 4, 5, 6 }; - struct cls_struct_7byte f_dbl = { 12, 128, 9, 3, 4, 5, 6 }; - struct cls_struct_7byte res_dbl = { 0, 0, 0, 0, 0, 0, 0 }; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_uchar; - cls_struct_fields[4] = &ffi_type_uchar; - cls_struct_fields[5] = &ffi_type_uchar; - cls_struct_fields[6] = &ffi_type_uchar; - cls_struct_fields[7] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */ - printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 139 248 10 6 8 10 12" } */ - - res_dbl.a = 0; - res_dbl.b = 0; - res_dbl.c = 0; - res_dbl.d = 0; - res_dbl.e = 0; - res_dbl.f = 0; - res_dbl.g = 0; - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */ - printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 139 248 10 6 8 10 12" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7byte.c deleted file mode 100644 index 1645cc635..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_7byte.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_7byte { - unsigned short a; - unsigned short b; - unsigned char c; - unsigned short d; -} cls_struct_7byte; - -cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, - struct cls_struct_7byte a2) -{ - struct cls_struct_7byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - result.d = a1.d + a2.d; - - printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d, - a2.a, a2.b, a2.c, a2.d, - result.a, result.b, result.c, result.d); - - return result; -} - -static void -cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_7byte a1, a2; - - a1 = *(struct cls_struct_7byte*)(args[0]); - a2 = *(struct cls_struct_7byte*)(args[1]); - - *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_7byte g_dbl = { 127, 120, 1, 254 }; - struct cls_struct_7byte f_dbl = { 12, 128, 9, 255 }; - struct cls_struct_7byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_ushort; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = &ffi_type_ushort; - cls_struct_fields[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl); - /* { dg-output "127 120 1 254 12 128 9 255: 139 248 10 509" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 139 248 10 509" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */ - printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); - /* { dg-output "\nres: 139 248 10 509" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_8byte.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_8byte.c deleted file mode 100644 index f6c1ea570..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_8byte.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Check overlapping. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_8byte { - int a; - float b; -} cls_struct_8byte; - -cls_struct_8byte cls_struct_8byte_fn(struct cls_struct_8byte a1, - struct cls_struct_8byte a2) -{ - struct cls_struct_8byte result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - - printf("%d %g %d %g: %d %g\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b); - - return result; -} - -static void -cls_struct_8byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_8byte a1, a2; - - a1 = *(struct cls_struct_8byte*)(args[0]); - a2 = *(struct cls_struct_8byte*)(args[1]); - - *(cls_struct_8byte*)resp = cls_struct_8byte_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_8byte g_dbl = { 1, 2.0 }; - struct cls_struct_8byte f_dbl = { 4, 5.0 }; - struct cls_struct_8byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_sint; - cls_struct_fields[1] = &ffi_type_float; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_8byte_fn), &res_dbl, args_dbl); - /* { dg-output "1 2 4 5: 5 7" } */ - printf("res: %d %g\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 5 7" } */ - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_8byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_8byte(*)(cls_struct_8byte, cls_struct_8byte))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 2 4 5: 5 7" } */ - printf("res: %d %g\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 5 7" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte1.c deleted file mode 100644 index 0b8572223..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte1.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Darwin/AIX do double-word - alignment of the struct if the first element is a double. - Check that it does not here. - Limitations: none. - PR: none. - Originator: 20030914 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_9byte { - int a; - double b; -} cls_struct_9byte; - -cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, - struct cls_struct_9byte b2) -{ - struct cls_struct_9byte result; - - result.a = b1.a + b2.a; - result.b = b1.b + b2.b; - - printf("%d %g %d %g: %d %g\n", b1.a, b1.b, b2.a, b2.b, - result.a, result.b); - - return result; -} - -static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - struct cls_struct_9byte b1, b2; - - b1 = *(struct cls_struct_9byte*)(args[0]); - b2 = *(struct cls_struct_9byte*)(args[1]); - - *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_9byte h_dbl = { 7, 8.0}; - struct cls_struct_9byte j_dbl = { 1, 9.0}; - struct cls_struct_9byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_sint; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &h_dbl; - args_dbl[1] = &j_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl); - /* { dg-output "7 8 1 9: 8 17" } */ - printf("res: %d %g\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 8 17" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl); - /* { dg-output "\n7 8 1 9: 8 17" } */ - printf("res: %d %g\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 8 17" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte2.c deleted file mode 100644 index edf991de7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_9byte2.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Depending on the ABI. Darwin/AIX do double-word - alignment of the struct if the first element is a double. - Check that it does here. - Limitations: none. - PR: none. - Originator: 20030914 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_9byte { - double a; - int b; -} cls_struct_9byte; - -cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, - struct cls_struct_9byte b2) -{ - struct cls_struct_9byte result; - - result.a = b1.a + b2.a; - result.b = b1.b + b2.b; - - printf("%g %d %g %d: %g %d\n", b1.a, b1.b, b2.a, b2.b, - result.a, result.b); - - return result; -} - -static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - struct cls_struct_9byte b1, b2; - - b1 = *(struct cls_struct_9byte*)(args[0]); - b2 = *(struct cls_struct_9byte*)(args[1]); - - *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_9byte h_dbl = { 7.0, 8}; - struct cls_struct_9byte j_dbl = { 1.0, 9}; - struct cls_struct_9byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_sint; - cls_struct_fields[2] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &h_dbl; - args_dbl[1] = &j_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl); - /* { dg-output "7 8 1 9: 8 17" } */ - printf("res: %g %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 8 17" } */ - - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl); - /* { dg-output "\n7 8 1 9: 8 17" } */ - printf("res: %g %d\n", res_dbl.a, res_dbl.b); - /* { dg-output "\nres: 8 17" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_double.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_double.c deleted file mode 100644 index aad5f3ced..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_double.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of double. - Limitations: none. - PR: none. - Originator: 20031203 */ - - - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - double b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_float.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_float.c deleted file mode 100644 index 37e085529..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_float.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of float. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - float b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_float; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble.c deleted file mode 100644 index b3322d861..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of long double. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - long double b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_longdouble; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split.c deleted file mode 100644 index 15f936546..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of long double. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ - -#include "ffitest.h" - -typedef struct cls_struct_align { - long double a; - long double b; - long double c; - long double d; - long double e; - long double f; - long double g; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn( - cls_struct_align a1, - cls_struct_align a2) -{ - struct cls_struct_align r; - - r.a = a1.a + a2.a; - r.b = a1.b + a2.b; - r.c = a1.c + a2.c; - r.d = a1.d + a2.d; - r.e = a1.e + a2.e; - r.f = a1.f + a2.f; - r.g = a1.g + a2.g; - - printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: " - "%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", - a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g, - a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g, - r.a, r.b, r.c, r.d, r.e, r.f, r.g); - - return r; -} - -cls_struct_align cls_struct_align_fn2( - cls_struct_align a1) -{ - struct cls_struct_align r; - - r.a = a1.a + 1; - r.b = a1.b + 1; - r.c = a1.c + 1; - r.d = a1.d + 1; - r.e = a1.e + 1; - r.f = a1.f + 1; - r.g = a1.g + 1; - - printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg: " - "%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", - a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g, - r.a, r.b, r.c, r.d, r.e, r.f, r.g); - - return r; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[8]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 }; - struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_longdouble; - cls_struct_fields[1] = &ffi_type_longdouble; - cls_struct_fields[2] = &ffi_type_longdouble; - cls_struct_fields[3] = &ffi_type_longdouble; - cls_struct_fields[4] = &ffi_type_longdouble; - cls_struct_fields[5] = &ffi_type_longdouble; - cls_struct_fields[6] = &ffi_type_longdouble; - cls_struct_fields[7] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */ - printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 9 11 13 15 17 19 21" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */ - printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 9 11 13 15 17 19 21" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split2.c deleted file mode 100644 index ca1c356cb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_longdouble_split2.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of long double. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/18/2007 -*/ - -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ -/* { dg-do run { xfail strongarm*-*-* } } */ -/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ - -#include "ffitest.h" - -typedef struct cls_struct_align { - long double a; - long double b; - long double c; - long double d; - long double e; - double f; - long double g; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn( - cls_struct_align a1, - cls_struct_align a2) -{ - struct cls_struct_align r; - - r.a = a1.a + a2.a; - r.b = a1.b + a2.b; - r.c = a1.c + a2.c; - r.d = a1.d + a2.d; - r.e = a1.e + a2.e; - r.f = a1.f + a2.f; - r.g = a1.g + a2.g; - - printf("%Lg %Lg %Lg %Lg %Lg %g %Lg %Lg %Lg %Lg %Lg %Lg %g %Lg: " - "%Lg %Lg %Lg %Lg %Lg %g %Lg\n", - a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g, - a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g, - r.a, r.b, r.c, r.d, r.e, r.f, r.g); - - return r; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[8]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[3]; - - struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 }; - struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_longdouble; - cls_struct_fields[1] = &ffi_type_longdouble; - cls_struct_fields[2] = &ffi_type_longdouble; - cls_struct_fields[3] = &ffi_type_longdouble; - cls_struct_fields[4] = &ffi_type_longdouble; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_longdouble; - cls_struct_fields[7] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */ - printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 9 11 13 15 17 19 21" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */ - printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g); - /* { dg-output "\nres: 9 11 13 15 17 19 21" } */ - - exit(0); -} - - - diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_pointer.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_pointer.c deleted file mode 100644 index 8fbf36a5c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_pointer.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of pointer. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - void *b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = (void *)((uintptr_t)a1.b + (uintptr_t)a2.b); - result.c = a1.c + a2.c; - - printf("%d %" PRIuPTR " %d %d %" PRIuPTR " %d: %d %" PRIuPTR " %d\n", - a1.a, (uintptr_t)a1.b, a1.c, - a2.a, (uintptr_t)a2.b, a2.c, - result.a, (uintptr_t)result.b, - result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, (void *)4951, 127 }; - struct cls_struct_align f_dbl = { 1, (void *)9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_pointer; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint16.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint16.c deleted file mode 100644 index 039b87473..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint16.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of sint16. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - signed short b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_sshort; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint32.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint32.c deleted file mode 100644 index c96c6d136..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint32.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of sint32. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - signed int b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_sint; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint64.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint64.c deleted file mode 100644 index 9aa7bdddf..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_sint64.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of sint64. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - signed long long b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_sint64; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint16.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint16.c deleted file mode 100644 index 97620b79d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint16.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of uint16. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - unsigned short b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_ushort; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint32.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint32.c deleted file mode 100644 index 5766fadf0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint32.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of uint32. - Limitations: none. - PR: none. - Originator: 20031203 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - unsigned int b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uint; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint64.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint64.c deleted file mode 100644 index a52cb8939..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_align_uint64.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure alignment of uint64. - Limitations: none. - PR: none. - Originator: 20031203 */ - - -/* { dg-do run } */ -/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */ -#include "ffitest.h" - -typedef struct cls_struct_align { - unsigned char a; - unsigned long long b; - unsigned char c; -} cls_struct_align; - -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, - struct cls_struct_align a2) -{ - struct cls_struct_align result; - - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -static void -cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - - struct cls_struct_align a1, a2; - - a1 = *(struct cls_struct_align*)(args[0]); - a2 = *(struct cls_struct_align*)(args[1]); - - *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[4]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_align g_dbl = { 12, 4951, 127 }; - struct cls_struct_align f_dbl = { 1, 9320, 13 }; - struct cls_struct_align res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uint64; - cls_struct_fields[2] = &ffi_type_uchar; - cls_struct_fields[3] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &g_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); - /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl); - /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ - printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c); - /* { dg-output "\nres: 13 14271 140" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_dbls_struct.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_dbls_struct.c deleted file mode 100644 index d6637911e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_dbls_struct.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check double arguments in structs. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/23/2007 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -typedef struct Dbls { - double x; - double y; -} Dbls; - -void -closure_test_fn(Dbls p) -{ - printf("%.1f %.1f\n", p.x, p.y); -} - -void -closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, - void** args, void* userdata __UNUSED__) -{ - closure_test_fn(*(Dbls*)args[0]); -} - -int main(int argc __UNUSED__, char** argv __UNUSED__) -{ - ffi_cif cif; - - void *code; - ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type* cl_arg_types[1]; - - ffi_type ts1_type; - ffi_type* ts1_type_elements[4]; - - Dbls arg = { 1.0, 2.0 }; - - ts1_type.size = 0; - ts1_type.alignment = 0; - ts1_type.type = FFI_TYPE_STRUCT; - ts1_type.elements = ts1_type_elements; - - ts1_type_elements[0] = &ffi_type_double; - ts1_type_elements[1] = &ffi_type_double; - ts1_type_elements[2] = NULL; - - cl_arg_types[0] = &ts1_type; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_void, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK); - - ((void*(*)(Dbls))(code))(arg); - /* { dg-output "1.0 2.0\n" } */ - - closure_test_fn(arg); - /* { dg-output "1.0 2.0\n" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double.c deleted file mode 100644 index 84ad4cb7d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Area: closure_call - Purpose: Check return value double. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(double *)resp = *(double *)args[0]; - - printf("%f: %f\n",*(double *)args[0], - *(double *)resp); - } -typedef double (*cls_ret_double)(double); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - double res; - - cl_arg_types[0] = &ffi_type_double; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_double, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_double_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_double)code))(21474.789); - /* { dg-output "21474.789000: 21474.789000" } */ - printf("res: %.6f\n", res); - /* { dg-output "\nres: 21474.789000" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double_va.c deleted file mode 100644 index e077f92b8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_double_va.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Test doubles passed in variable argument lists. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -/* { dg-output "" { xfail avr32*-*-* } } */ -/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */ - -#include "ffitest.h" - -static void -cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - char* format = *(char**)args[0]; - double doubleValue = *(double*)args[1]; - - *(ffi_arg*)resp = printf(format, doubleValue); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[3]; - ffi_type* arg_types[3]; - - char* format = "%.1f\n"; - double doubleArg = 7; - ffi_arg res = 0; - - arg_types[0] = &ffi_type_pointer; - arg_types[1] = &ffi_type_double; - arg_types[2] = NULL; - - /* This printf call is variadic */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint, - arg_types) == FFI_OK); - - args[0] = &format; - args[1] = &doubleArg; - args[2] = NULL; - - ffi_call(&cif, FFI_FN(printf), &res, args); - /* { dg-output "7.0" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 4" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, - code) == FFI_OK); - - res = ((int(*)(char*, ...))(code))(format, doubleArg); - /* { dg-output "\n7.0" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 4" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_float.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_float.c deleted file mode 100644 index 0090fed90..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_float.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: closure_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_float_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(float *)resp = *(float *)args[0]; - - printf("%g: %g\n",*(float *)args[0], - *(float *)resp); - } - -typedef float (*cls_ret_float)(float); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - float res; - - cl_arg_types[0] = &ffi_type_float; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_float, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_float_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_float)code)(-2122.12))); - /* { dg-output "\\-2122.12: \\-2122.12" } */ - printf("res: %.6f\n", res); - /* { dg-output "\nres: \-2122.120117" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble.c deleted file mode 100644 index 5dc9ac768..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check long double arguments. - Limitations: none. - PR: none. - Originator: Blake Chaffin */ - -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ -/* This test is known to PASS on armv7l-unknown-linux-gnueabihf, so I have - remove the xfail for arm*-*-* below, until we know more. */ -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ - -#include "ffitest.h" - -long double cls_ldouble_fn( - long double a1, - long double a2, - long double a3, - long double a4, - long double a5, - long double a6, - long double a7, - long double a8) -{ - long double r = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8; - - printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: %Lg\n", - a1, a2, a3, a4, a5, a6, a7, a8, r); - - return r; -} - -static void -cls_ldouble_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - long double a1 = *(long double*)args[0]; - long double a2 = *(long double*)args[1]; - long double a3 = *(long double*)args[2]; - long double a4 = *(long double*)args[3]; - long double a5 = *(long double*)args[4]; - long double a6 = *(long double*)args[5]; - long double a7 = *(long double*)args[6]; - long double a8 = *(long double*)args[7]; - - *(long double*)resp = cls_ldouble_fn( - a1, a2, a3, a4, a5, a6, a7, a8); -} - -int main(void) -{ - ffi_cif cif; - void* code; - ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[9]; - ffi_type* arg_types[9]; - long double res = 0; - - long double arg1 = 1; - long double arg2 = 2; - long double arg3 = 3; - long double arg4 = 4; - long double arg5 = 5; - long double arg6 = 6; - long double arg7 = 7; - long double arg8 = 8; - - arg_types[0] = &ffi_type_longdouble; - arg_types[1] = &ffi_type_longdouble; - arg_types[2] = &ffi_type_longdouble; - arg_types[3] = &ffi_type_longdouble; - arg_types[4] = &ffi_type_longdouble; - arg_types[5] = &ffi_type_longdouble; - arg_types[6] = &ffi_type_longdouble; - arg_types[7] = &ffi_type_longdouble; - arg_types[8] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 8, &ffi_type_longdouble, - arg_types) == FFI_OK); - - args[0] = &arg1; - args[1] = &arg2; - args[2] = &arg3; - args[3] = &arg4; - args[4] = &arg5; - args[5] = &arg6; - args[6] = &arg7; - args[7] = &arg8; - args[8] = NULL; - - ffi_call(&cif, FFI_FN(cls_ldouble_fn), &res, args); - /* { dg-output "1 2 3 4 5 6 7 8: 36" } */ - printf("res: %Lg\n", res); - /* { dg-output "\nres: 36" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ldouble_gn, NULL, code) == FFI_OK); - - res = ((long double(*)(long double, long double, long double, long double, - long double, long double, long double, long double))(code))(arg1, arg2, - arg3, arg4, arg5, arg6, arg7, arg8); - /* { dg-output "\n1 2 3 4 5 6 7 8: 36" } */ - printf("res: %Lg\n", res); - /* { dg-output "\nres: 36" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble_va.c deleted file mode 100644 index 39b438b28..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_longdouble_va.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Test long doubles passed in variable argument lists. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -/* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */ -/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */ - -#include "ffitest.h" - -static void -cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - char* format = *(char**)args[0]; - long double ldValue = *(long double*)args[1]; - - *(ffi_arg*)resp = printf(format, ldValue); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[3]; - ffi_type* arg_types[3]; - - char* format = "%.1Lf\n"; - long double ldArg = 7; - ffi_arg res = 0; - - arg_types[0] = &ffi_type_pointer; - arg_types[1] = &ffi_type_longdouble; - arg_types[2] = NULL; - - /* This printf call is variadic */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint, - arg_types) == FFI_OK); - - args[0] = &format; - args[1] = &ldArg; - args[2] = NULL; - - ffi_call(&cif, FFI_FN(printf), &res, args); - /* { dg-output "7.0" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 4" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, - code) == FFI_OK); - - res = ((int(*)(char*, ...))(code))(format, ldArg); - /* { dg-output "\n7.0" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 4" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_schar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_schar.c deleted file mode 100644 index 71df7b651..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_schar.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple signed char values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -signed char test_func_fn(signed char a1, signed char a2) -{ - signed char result; - - result = a1 + a2; - - printf("%d %d: %d\n", a1, a2, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - signed char a1, a2; - - a1 = *(signed char *)avals[0]; - a2 = *(signed char *)avals[1]; - - *(ffi_arg *)rval = test_func_fn(a1, a2); - -} - -typedef signed char (*test_type)(signed char, signed char); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[3]; - ffi_type * cl_arg_types[3]; - ffi_arg res_call; - signed char a, b, res_closure; - - a = 2; - b = 125; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = NULL; - - cl_arg_types[0] = &ffi_type_schar; - cl_arg_types[1] = &ffi_type_schar; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_schar, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "2 125: 127" } */ - printf("res: %d\n", (signed char)res_call); - /* { dg-output "\nres: 127" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(2, 125); - /* { dg-output "\n2 125: 127" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 127" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshort.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshort.c deleted file mode 100644 index 4c3915326..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshort.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple signed short values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -signed short test_func_fn(signed short a1, signed short a2) -{ - signed short result; - - result = a1 + a2; - - printf("%d %d: %d\n", a1, a2, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - signed short a1, a2; - - a1 = *(signed short *)avals[0]; - a2 = *(signed short *)avals[1]; - - *(ffi_arg *)rval = test_func_fn(a1, a2); - -} - -typedef signed short (*test_type)(signed short, signed short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[3]; - ffi_type * cl_arg_types[3]; - ffi_arg res_call; - unsigned short a, b, res_closure; - - a = 2; - b = 32765; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = NULL; - - cl_arg_types[0] = &ffi_type_sshort; - cl_arg_types[1] = &ffi_type_sshort; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_sshort, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "2 32765: 32767" } */ - printf("res: %d\n", (unsigned short)res_call); - /* { dg-output "\nres: 32767" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(2, 32765); - /* { dg-output "\n2 32765: 32767" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 32767" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshortchar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshortchar.c deleted file mode 100644 index 1c3aeb5a6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_sshortchar.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple signed short/char values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -signed short test_func_fn(signed char a1, signed short a2, - signed char a3, signed short a4) -{ - signed short result; - - result = a1 + a2 + a3 + a4; - - printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - signed char a1, a3; - signed short a2, a4; - - a1 = *(signed char *)avals[0]; - a2 = *(signed short *)avals[1]; - a3 = *(signed char *)avals[2]; - a4 = *(signed short *)avals[3]; - - *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4); - -} - -typedef signed short (*test_type)(signed char, signed short, - signed char, signed short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[5]; - ffi_type * cl_arg_types[5]; - ffi_arg res_call; - signed char a, c; - signed short b, d, res_closure; - - a = 1; - b = 32765; - c = 127; - d = -128; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = &c; - args_dbl[3] = &d; - args_dbl[4] = NULL; - - cl_arg_types[0] = &ffi_type_schar; - cl_arg_types[1] = &ffi_type_sshort; - cl_arg_types[2] = &ffi_type_schar; - cl_arg_types[3] = &ffi_type_sshort; - cl_arg_types[4] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_sshort, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "1 32765 127 -128: 32765" } */ - printf("res: %d\n", (signed short)res_call); - /* { dg-output "\nres: 32765" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(1, 32765, 127, -128); - /* { dg-output "\n1 32765 127 -128: 32765" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 32765" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_uchar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_uchar.c deleted file mode 100644 index 009c02c72..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_uchar.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple unsigned char values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -unsigned char test_func_fn(unsigned char a1, unsigned char a2, - unsigned char a3, unsigned char a4) -{ - unsigned char result; - - result = a1 + a2 + a3 + a4; - - printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - unsigned char a1, a2, a3, a4; - - a1 = *(unsigned char *)avals[0]; - a2 = *(unsigned char *)avals[1]; - a3 = *(unsigned char *)avals[2]; - a4 = *(unsigned char *)avals[3]; - - *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4); - -} - -typedef unsigned char (*test_type)(unsigned char, unsigned char, - unsigned char, unsigned char); - -void test_func(ffi_cif *cif __UNUSED__, void *rval __UNUSED__, void **avals, - void *data __UNUSED__) -{ - printf("%d %d %d %d\n", *(unsigned char *)avals[0], - *(unsigned char *)avals[1], *(unsigned char *)avals[2], - *(unsigned char *)avals[3]); -} -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[5]; - ffi_type * cl_arg_types[5]; - ffi_arg res_call; - unsigned char a, b, c, d, res_closure; - - a = 1; - b = 2; - c = 127; - d = 125; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = &c; - args_dbl[3] = &d; - args_dbl[4] = NULL; - - cl_arg_types[0] = &ffi_type_uchar; - cl_arg_types[1] = &ffi_type_uchar; - cl_arg_types[2] = &ffi_type_uchar; - cl_arg_types[3] = &ffi_type_uchar; - cl_arg_types[4] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_uchar, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "1 2 127 125: 255" } */ - printf("res: %d\n", (unsigned char)res_call); - /* { dg-output "\nres: 255" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(1, 2, 127, 125); - /* { dg-output "\n1 2 127 125: 255" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 255" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushort.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushort.c deleted file mode 100644 index dd10ca734..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushort.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple unsigned short values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -unsigned short test_func_fn(unsigned short a1, unsigned short a2) -{ - unsigned short result; - - result = a1 + a2; - - printf("%d %d: %d\n", a1, a2, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - unsigned short a1, a2; - - a1 = *(unsigned short *)avals[0]; - a2 = *(unsigned short *)avals[1]; - - *(ffi_arg *)rval = test_func_fn(a1, a2); - -} - -typedef unsigned short (*test_type)(unsigned short, unsigned short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[3]; - ffi_type * cl_arg_types[3]; - ffi_arg res_call; - unsigned short a, b, res_closure; - - a = 2; - b = 32765; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = NULL; - - cl_arg_types[0] = &ffi_type_ushort; - cl_arg_types[1] = &ffi_type_ushort; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_ushort, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "2 32765: 32767" } */ - printf("res: %d\n", (unsigned short)res_call); - /* { dg-output "\nres: 32767" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(2, 32765); - /* { dg-output "\n2 32765: 32767" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 32767" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushortchar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushortchar.c deleted file mode 100644 index 2588e97f9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_multi_ushortchar.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check passing of multiple unsigned short/char values. - Limitations: none. - PR: PR13221. - Originator: 20031129 */ - -/* { dg-do run } */ -#include "ffitest.h" - -unsigned short test_func_fn(unsigned char a1, unsigned short a2, - unsigned char a3, unsigned short a4) -{ - unsigned short result; - - result = a1 + a2 + a3 + a4; - - printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result); - - return result; - -} - -static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals, - void *data __UNUSED__) -{ - unsigned char a1, a3; - unsigned short a2, a4; - - a1 = *(unsigned char *)avals[0]; - a2 = *(unsigned short *)avals[1]; - a3 = *(unsigned char *)avals[2]; - a4 = *(unsigned short *)avals[3]; - - *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4); - -} - -typedef unsigned short (*test_type)(unsigned char, unsigned short, - unsigned char, unsigned short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void * args_dbl[5]; - ffi_type * cl_arg_types[5]; - ffi_arg res_call; - unsigned char a, c; - unsigned short b, d, res_closure; - - a = 1; - b = 2; - c = 127; - d = 128; - - args_dbl[0] = &a; - args_dbl[1] = &b; - args_dbl[2] = &c; - args_dbl[3] = &d; - args_dbl[4] = NULL; - - cl_arg_types[0] = &ffi_type_uchar; - cl_arg_types[1] = &ffi_type_ushort; - cl_arg_types[2] = &ffi_type_uchar; - cl_arg_types[3] = &ffi_type_ushort; - cl_arg_types[4] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_ushort, cl_arg_types) == FFI_OK); - - ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); - /* { dg-output "1 2 127 128: 258" } */ - printf("res: %d\n", (unsigned short)res_call); - /* { dg-output "\nres: 258" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK); - - res_closure = (*((test_type)code))(1, 2, 127, 128); - /* { dg-output "\n1 2 127 128: 258" } */ - printf("res: %d\n", res_closure); - /* { dg-output "\nres: 258" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer.c deleted file mode 100644 index d82a87a71..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check pointer arguments. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -#include "ffitest.h" - -void* cls_pointer_fn(void* a1, void* a2) -{ - void* result = (void*)((intptr_t)a1 + (intptr_t)a2); - - printf("0x%08x 0x%08x: 0x%08x\n", - (unsigned int)(uintptr_t) a1, - (unsigned int)(uintptr_t) a2, - (unsigned int)(uintptr_t) result); - - return result; -} - -static void -cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - void* a1 = *(void**)(args[0]); - void* a2 = *(void**)(args[1]); - - *(void**)resp = cls_pointer_fn(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[3]; - /* ffi_type cls_pointer_type; */ - ffi_type* arg_types[3]; - -/* cls_pointer_type.size = sizeof(void*); - cls_pointer_type.alignment = 0; - cls_pointer_type.type = FFI_TYPE_POINTER; - cls_pointer_type.elements = NULL;*/ - - void* arg1 = (void*)0x12345678; - void* arg2 = (void*)0x89abcdef; - ffi_arg res = 0; - - arg_types[0] = &ffi_type_pointer; - arg_types[1] = &ffi_type_pointer; - arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, - arg_types) == FFI_OK); - - args[0] = &arg1; - args[1] = &arg2; - args[2] = NULL; - - ffi_call(&cif, FFI_FN(cls_pointer_fn), &res, args); - /* { dg-output "0x12345678 0x89abcdef: 0x9be02467" } */ - printf("res: 0x%08x\n", (unsigned int) res); - /* { dg-output "\nres: 0x9be02467" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK); - - res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2); - /* { dg-output "\n0x12345678 0x89abcdef: 0x9be02467" } */ - printf("res: 0x%08x\n", (unsigned int) res); - /* { dg-output "\nres: 0x9be02467" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer_stack.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer_stack.c deleted file mode 100644 index 1f1d9157b..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_pointer_stack.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check pointer arguments across multiple hideous stack frames. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/7/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -#include "ffitest.h" - -static long dummyVar; - -long dummy_func( - long double a1, char b1, - long double a2, char b2, - long double a3, char b3, - long double a4, char b4) -{ - return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4; -} - -void* cls_pointer_fn2(void* a1, void* a2) -{ - long double trample1 = (intptr_t)a1 + (intptr_t)a2; - char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0]; - long double trample3 = (intptr_t)trample1 + (intptr_t)a1; - char trample4 = trample2 + ((char*)&a1)[1]; - long double trample5 = (intptr_t)trample3 + (intptr_t)a2; - char trample6 = trample4 + ((char*)&a2)[1]; - long double trample7 = (intptr_t)trample5 + (intptr_t)trample1; - char trample8 = trample6 + trample2; - void* result; - - dummyVar = dummy_func(trample1, trample2, trample3, trample4, - trample5, trample6, trample7, trample8); - - result = (void*)((intptr_t)a1 + (intptr_t)a2); - - printf("0x%08x 0x%08x: 0x%08x\n", - (unsigned int)(uintptr_t) a1, - (unsigned int)(uintptr_t) a2, - (unsigned int)(uintptr_t) result); - - return result; -} - -void* cls_pointer_fn1(void* a1, void* a2) -{ - long double trample1 = (intptr_t)a1 + (intptr_t)a2; - char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0]; - long double trample3 = (intptr_t)trample1 + (intptr_t)a1; - char trample4 = trample2 + ((char*)&a1)[1]; - long double trample5 = (intptr_t)trample3 + (intptr_t)a2; - char trample6 = trample4 + ((char*)&a2)[1]; - long double trample7 = (intptr_t)trample5 + (intptr_t)trample1; - char trample8 = trample6 + trample2; - void* result; - - dummyVar = dummy_func(trample1, trample2, trample3, trample4, - trample5, trample6, trample7, trample8); - - result = (void*)((intptr_t)a1 + (intptr_t)a2); - - printf("0x%08x 0x%08x: 0x%08x\n", - (unsigned int)(intptr_t) a1, - (unsigned int)(intptr_t) a2, - (unsigned int)(intptr_t) result); - - result = cls_pointer_fn2(result, a1); - - return result; -} - -static void -cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - void* a1 = *(void**)(args[0]); - void* a2 = *(void**)(args[1]); - - long double trample1 = (intptr_t)a1 + (intptr_t)a2; - char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0]; - long double trample3 = (intptr_t)trample1 + (intptr_t)a1; - char trample4 = trample2 + ((char*)&a1)[1]; - long double trample5 = (intptr_t)trample3 + (intptr_t)a2; - char trample6 = trample4 + ((char*)&a2)[1]; - long double trample7 = (intptr_t)trample5 + (intptr_t)trample1; - char trample8 = trample6 + trample2; - - dummyVar = dummy_func(trample1, trample2, trample3, trample4, - trample5, trample6, trample7, trample8); - - *(void**)resp = cls_pointer_fn1(a1, a2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[3]; - /* ffi_type cls_pointer_type; */ - ffi_type* arg_types[3]; - -/* cls_pointer_type.size = sizeof(void*); - cls_pointer_type.alignment = 0; - cls_pointer_type.type = FFI_TYPE_POINTER; - cls_pointer_type.elements = NULL;*/ - - void* arg1 = (void*)0x01234567; - void* arg2 = (void*)0x89abcdef; - ffi_arg res = 0; - - arg_types[0] = &ffi_type_pointer; - arg_types[1] = &ffi_type_pointer; - arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, - arg_types) == FFI_OK); - - args[0] = &arg1; - args[1] = &arg2; - args[2] = NULL; - - printf("\n"); - ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args); - - printf("res: 0x%08x\n", (unsigned int) res); - /* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */ - /* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */ - /* { dg-output "\nres: 0x8bf258bd" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK); - - res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2); - - printf("res: 0x%08x\n", (unsigned int) res); - /* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */ - /* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */ - /* { dg-output "\nres: 0x8bf258bd" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_schar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_schar.c deleted file mode 100644 index 82986b172..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_schar.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: closure_call - Purpose: Check return value schar. - Limitations: none. - PR: none. - Originator: 20031108 */ - - - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_schar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg*)resp = *(signed char *)args[0]; - printf("%d: %d\n",*(signed char *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef signed char (*cls_ret_schar)(signed char); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - signed char res; - - cl_arg_types[0] = &ffi_type_schar; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_schar, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_schar_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_schar)code))(127); - /* { dg-output "127: 127" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 127" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sint.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sint.c deleted file mode 100644 index c7e13b73a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sint.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: closure_call - Purpose: Check return value sint32. - Limitations: none. - PR: none. - Originator: 20031108 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_sint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg*)resp = *(signed int *)args[0]; - printf("%d: %d\n",*(signed int *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef signed int (*cls_ret_sint)(signed int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - signed int res; - - cl_arg_types[0] = &ffi_type_sint; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sint_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_sint)code))(65534); - /* { dg-output "65534: 65534" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 65534" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sshort.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sshort.c deleted file mode 100644 index 846d57ed1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_sshort.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: closure_call - Purpose: Check return value sshort. - Limitations: none. - PR: none. - Originator: 20031108 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_sshort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg*)resp = *(signed short *)args[0]; - printf("%d: %d\n",*(signed short *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef signed short (*cls_ret_sshort)(signed short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - signed short res; - - cl_arg_types[0] = &ffi_type_sshort; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sshort, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sshort_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_sshort)code))(255); - /* { dg-output "255: 255" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 255" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_struct_va1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_struct_va1.c deleted file mode 100644 index 6d1fdaeb6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_struct_va1.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Test doubles passed in variable argument lists. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ -#include "ffitest.h" - -struct small_tag -{ - unsigned char a; - unsigned char b; -}; - -struct large_tag -{ - unsigned a; - unsigned b; - unsigned c; - unsigned d; - unsigned e; -}; - -static void -test_fn (ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - int n = *(int*)args[0]; - struct small_tag s1 = * (struct small_tag *) args[1]; - struct large_tag l1 = * (struct large_tag *) args[2]; - struct small_tag s2 = * (struct small_tag *) args[3]; - - printf ("%d %d %d %d %d %d %d %d %d %d\n", n, s1.a, s1.b, - l1.a, l1.b, l1.c, l1.d, l1.e, - s2.a, s2.b); - * (ffi_arg*) resp = 42; -} - -int -main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc (sizeof (ffi_closure), &code); - ffi_type* arg_types[5]; - - ffi_arg res = 0; - - ffi_type s_type; - ffi_type *s_type_elements[3]; - - ffi_type l_type; - ffi_type *l_type_elements[6]; - - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int si; - - s_type.size = 0; - s_type.alignment = 0; - s_type.type = FFI_TYPE_STRUCT; - s_type.elements = s_type_elements; - - s_type_elements[0] = &ffi_type_uchar; - s_type_elements[1] = &ffi_type_uchar; - s_type_elements[2] = NULL; - - l_type.size = 0; - l_type.alignment = 0; - l_type.type = FFI_TYPE_STRUCT; - l_type.elements = l_type_elements; - - l_type_elements[0] = &ffi_type_uint; - l_type_elements[1] = &ffi_type_uint; - l_type_elements[2] = &ffi_type_uint; - l_type_elements[3] = &ffi_type_uint; - l_type_elements[4] = &ffi_type_uint; - l_type_elements[5] = NULL; - - arg_types[0] = &ffi_type_sint; - arg_types[1] = &s_type; - arg_types[2] = &l_type; - arg_types[3] = &s_type; - arg_types[4] = NULL; - - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, - arg_types) == FFI_OK); - - si = 4; - s1.a = 5; - s1.b = 6; - - s2.a = 20; - s2.b = 21; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK); - - res = ((int (*)(int, ...))(code))(si, s1, l1, s2); - /* { dg-output "4 5 6 10 11 12 13 14 20 21" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 42" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar.c deleted file mode 100644 index c1317e795..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: closure_call - Purpose: Check return value uchar. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_uchar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg*)resp = *(unsigned char *)args[0]; - printf("%d: %d\n",*(unsigned char *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef unsigned char (*cls_ret_uchar)(unsigned char); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - unsigned char res; - - cl_arg_types[0] = &ffi_type_uchar; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_uchar, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_uchar_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_uchar)code))(127); - /* { dg-output "127: 127" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 127" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar_va.c deleted file mode 100644 index 6491c5b3d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uchar_va.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned char argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef unsigned char T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(ffi_arg *)resp = *(T *)args[0]; - - printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_uchar; - cl_arg_types[1] = &ffi_type_uchar; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_uchar, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint.c deleted file mode 100644 index 885cff5c3..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Area: closure_call - Purpose: Check return value uint. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_uint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg *)resp = *(unsigned int *)args[0]; - - printf("%d: %d\n",*(unsigned int *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef unsigned int (*cls_ret_uint)(unsigned int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - unsigned int res; - - cl_arg_types[0] = &ffi_type_uint; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_uint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_uint_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_uint)code))(2147483647); - /* { dg-output "2147483647: 2147483647" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 2147483647" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint_va.c deleted file mode 100644 index b04cfd19c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_uint_va.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned int argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ - -#include "ffitest.h" - -typedef unsigned int T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(ffi_arg *)resp = *(T *)args[0]; - - printf("%d: %d %d\n", (int)*(ffi_arg *)resp, *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_uint; - cl_arg_types[1] = &ffi_type_uint; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_uint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulong_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulong_va.c deleted file mode 100644 index 0315082e0..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulong_va.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned long argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ - -#include "ffitest.h" - -typedef unsigned long T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(T *)resp = *(T *)args[0]; - - printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_ulong; - cl_arg_types[1] = &ffi_type_ulong; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_ulong, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %ld\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulonglong.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulonglong.c deleted file mode 100644 index 62f2cae63..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ulonglong.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Area: closure_call - Purpose: Check return value long long. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */ -#include "ffitest.h" - -static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) -{ - *(unsigned long long *)resp= 0xfffffffffffffffLL ^ *(unsigned long long *)args[0]; - - printf("%" PRIuLL ": %" PRIuLL "\n",*(unsigned long long *)args[0], - *(unsigned long long *)(resp)); -} -typedef unsigned long long (*cls_ret_ulonglong)(unsigned long long); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - unsigned long long res; - - cl_arg_types[0] = &ffi_type_uint64; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_uint64, cl_arg_types) == FFI_OK); - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ulonglong_fn, NULL, code) == FFI_OK); - res = (*((cls_ret_ulonglong)code))(214LL); - /* { dg-output "214: 1152921504606846761" } */ - printf("res: %" PRIdLL "\n", res); - /* { dg-output "\nres: 1152921504606846761" } */ - - res = (*((cls_ret_ulonglong)code))(9223372035854775808LL); - /* { dg-output "\n9223372035854775808: 8070450533247928831" } */ - printf("res: %" PRIdLL "\n", res); - /* { dg-output "\nres: 8070450533247928831" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort.c deleted file mode 100644 index a00100e07..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Area: closure_call - Purpose: Check return value ushort. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static void cls_ret_ushort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - *(ffi_arg*)resp = *(unsigned short *)args[0]; - - printf("%d: %d\n",*(unsigned short *)args[0], - (int)*(ffi_arg *)(resp)); -} -typedef unsigned short (*cls_ret_ushort)(unsigned short); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[2]; - unsigned short res; - - cl_arg_types[0] = &ffi_type_ushort; - cl_arg_types[1] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_ushort, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ushort_fn, NULL, code) == FFI_OK); - - res = (*((cls_ret_ushort)code))(65535); - /* { dg-output "65535: 65535" } */ - printf("res: %d\n",res); - /* { dg-output "\nres: 65535" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort_va.c deleted file mode 100644 index 37aa1064e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/cls_ushort_va.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned short argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef unsigned short T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(ffi_arg *)resp = *(T *)args[0]; - - printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_ushort; - cl_arg_types[1] = &ffi_type_ushort; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_ushort, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_abi.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_abi.c deleted file mode 100644 index f5a73179e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_abi.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Area: ffi_prep_cif, ffi_prep_closure - Purpose: Test error return for bad ABIs. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static void -dummy_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, - void** args __UNUSED__, void* userdata __UNUSED__) -{} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type* arg_types[1]; - - arg_types[0] = NULL; - - CHECK(ffi_prep_cif(&cif, 255, 0, &ffi_type_void, - arg_types) == FFI_BAD_ABI); - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void, - arg_types) == FFI_OK); - - cif.abi= 255; - - CHECK(ffi_prep_closure_loc(pcl, &cif, dummy_fn, NULL, code) == FFI_BAD_ABI); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_typedef.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_typedef.c deleted file mode 100644 index bf6016186..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/err_bad_typedef.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Area: ffi_prep_cif - Purpose: Test error return for bad typedefs. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/6/2007 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -int main (void) -{ - ffi_cif cif; - ffi_type* arg_types[1]; - - ffi_type badType = ffi_type_void; - - arg_types[0] = NULL; - - badType.size = 0; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType, - arg_types) == FFI_BAD_TYPEDEF); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/ffitest.h b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/ffitest.h deleted file mode 100644 index 15d5e4412..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/ffitest.h +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include -#include -#include "fficonfig.h" - -#if defined HAVE_STDINT_H -#include -#endif - -#if defined HAVE_INTTYPES_H -#include -#endif - -#define MAX_ARGS 256 - -#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0) - -/* Define macros so that compilers other than gcc can run the tests. */ -#undef __UNUSED__ -#if defined(__GNUC__) -#define __UNUSED__ __attribute__((__unused__)) -#define __STDCALL__ __attribute__((stdcall)) -#define __THISCALL__ __attribute__((thiscall)) -#define __FASTCALL__ __attribute__((fastcall)) -#else -#define __UNUSED__ -#define __STDCALL__ __stdcall -#define __THISCALL__ __thiscall -#define __FASTCALL__ __fastcall -#endif - -#ifndef ABI_NUM -#define ABI_NUM FFI_DEFAULT_ABI -#define ABI_ATTR -#endif - -/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a - file open. */ -#ifdef HAVE_MMAP_ANON -# undef HAVE_MMAP_DEV_ZERO - -# include -# ifndef MAP_FAILED -# define MAP_FAILED -1 -# endif -# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -# endif -# define USING_MMAP - -#endif - -#ifdef HAVE_MMAP_DEV_ZERO - -# include -# ifndef MAP_FAILED -# define MAP_FAILED -1 -# endif -# define USING_MMAP - -#endif - -/* MinGW kludge. */ -#ifdef _WIN64 -#define PRIdLL "I64d" -#define PRIuLL "I64u" -#else -#define PRIdLL "lld" -#define PRIuLL "llu" -#endif - -/* Tru64 UNIX kludge. */ -#if defined(__alpha__) && defined(__osf__) -/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit. */ -#undef PRIdLL -#define PRIdLL "ld" -#undef PRIuLL -#define PRIuLL "lu" -#define PRId8 "hd" -#define PRIu8 "hu" -#define PRId64 "ld" -#define PRIu64 "lu" -#define PRIuPTR "lu" -#endif - -/* PA HP-UX kludge. */ -#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR) -#define PRIuPTR "lu" -#endif - -/* IRIX kludge. */ -#if defined(__sgi) -/* IRIX 6.5 provides all definitions, but only for C99 - compilations. */ -#define PRId8 "hhd" -#define PRIu8 "hhu" -#if (_MIPS_SZLONG == 32) -#define PRId64 "lld" -#define PRIu64 "llu" -#endif -/* This doesn't match , which always has "lld" here, but the - arguments are uint64_t, int64_t, which are unsigned long, long for - 64-bit in . */ -#if (_MIPS_SZLONG == 64) -#define PRId64 "ld" -#define PRIu64 "lu" -#endif -/* This doesn't match , which has "u" here, but the arguments - are uintptr_t, which is always unsigned long. */ -#define PRIuPTR "lu" -#endif - -/* Solaris < 10 kludge. */ -#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR) -#if defined(__arch64__) || defined (__x86_64__) -#define PRIuPTR "lu" -#else -#define PRIuPTR "u" -#endif -#endif - -/* MSVC kludge. */ -#if defined _MSC_VER -#define PRIuPTR "lu" -#define PRIu8 "u" -#define PRId8 "d" -#define PRIu64 "I64u" -#define PRId64 "I64d" -#endif - -#ifndef PRIuPTR -#define PRIuPTR "u" -#endif diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float.c deleted file mode 100644 index fbc272d84..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static int floating(int a, float b, double c, long double d) -{ - int i; - - i = (int) ((float)a/b + ((float)c/(float)d)); - - return i; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - - float f; - signed int si1; - double d; - long double ld; - - args[0] = &ffi_type_sint; - values[0] = &si1; - args[1] = &ffi_type_float; - values[1] = &f; - args[2] = &ffi_type_double; - values[2] = &d; - args[3] = &ffi_type_longdouble; - values[3] = &ld; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_sint, args) == FFI_OK); - - si1 = 6; - f = 3.14159; - d = (double)1.0/(double)3.0; - ld = 2.71828182846L; - - floating (si1, f, d, ld); - - ffi_call(&cif, FFI_FN(floating), &rint, values); - - printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld)); - - CHECK((int)rint == floating(si1, f, d, ld)); - - exit (0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float1.c deleted file mode 100644 index 991d059fe..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float1.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value double. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -#include "float.h" - -typedef union -{ - double d; - unsigned char c[sizeof (double)]; -} value_type; - -#define CANARY 0xba - -static double dblit(float f) -{ - return f/3.0; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float f; - value_type result[2]; - unsigned int i; - - args[0] = &ffi_type_float; - values[0] = &f; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_double, args) == FFI_OK); - - f = 3.14159; - - /* Put a canary in the return array. This is a regression test for - a buffer overrun. */ - memset(result[1].c, CANARY, sizeof (double)); - - ffi_call(&cif, FFI_FN(dblit), &result[0].d, values); - - /* These are not always the same!! Check for a reasonable delta */ - - CHECK(result[0].d - dblit(f) < DBL_EPSILON); - - /* Check the canary. */ - for (i = 0; i < sizeof (double); ++i) - CHECK(result[1].c[i] == CANARY); - - exit(0); - -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float2.c deleted file mode 100644 index a0b296cf4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float2.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value long double. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-excess-errors "fails" { target x86_64-*-mingw* x86_64-*-cygwin* } } */ -/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ - -#include "ffitest.h" -#include "float.h" - -static long double ldblit(float f) -{ - return (long double) (((long double) f)/ (long double) 3.0); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float f; - long double ld; - - args[0] = &ffi_type_float; - values[0] = &f; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_longdouble, args) == FFI_OK); - - f = 3.14159; - -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ - printf ("%Lf\n", ldblit(f)); -#endif - ld = 666; - ffi_call(&cif, FFI_FN(ldblit), &ld, values); - -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ - printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON); -#endif - - /* These are not always the same!! Check for a reasonable delta */ - if (ld - ldblit(f) < LDBL_EPSILON) - puts("long double return value tests ok!"); - else - CHECK(0); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float3.c deleted file mode 100644 index 76bd5f287..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float3.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Area: ffi_call - Purpose: Check float arguments with different orders. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" -#include "float.h" - -static double floating_1(float a, double b, long double c) -{ - return (double) a + b + (double) c; -} - -static double floating_2(long double a, double b, float c) -{ - return (double) a + b + (double) c; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - double rd; - - float f; - double d; - long double ld; - - args[0] = &ffi_type_float; - values[0] = &f; - args[1] = &ffi_type_double; - values[1] = &d; - args[2] = &ffi_type_longdouble; - values[2] = &ld; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_double, args) == FFI_OK); - - f = 3.14159; - d = (double)1.0/(double)3.0; - ld = 2.71828182846L; - - floating_1 (f, d, ld); - - ffi_call(&cif, FFI_FN(floating_1), &rd, values); - - CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON); - - args[0] = &ffi_type_longdouble; - values[0] = &ld; - args[1] = &ffi_type_double; - values[1] = &d; - args[2] = &ffi_type_float; - values[2] = &f; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_double, args) == FFI_OK); - - floating_2 (ld, d, f); - - ffi_call(&cif, FFI_FN(floating_2), &rd, values); - - CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON); - - exit (0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float4.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float4.c deleted file mode 100644 index 0dd6d85e7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float4.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Area: ffi_call - Purpose: Check denorm double value. - Limitations: none. - PR: PR26483. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -/* { dg-options "-mieee" { target alpha*-*-* } } */ - -#include "ffitest.h" -#include "float.h" - -typedef union -{ - double d; - unsigned char c[sizeof (double)]; -} value_type; - -#define CANARY 0xba - -static double dblit(double d) -{ - return d; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - double d; - value_type result[2]; - unsigned int i; - - args[0] = &ffi_type_double; - values[0] = &d; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_double, args) == FFI_OK); - - d = DBL_MIN / 2; - - /* Put a canary in the return array. This is a regression test for - a buffer overrun. */ - memset(result[1].c, CANARY, sizeof (double)); - - ffi_call(&cif, FFI_FN(dblit), &result[0].d, values); - - /* The standard delta check doesn't work for denorms. Since we didn't do - any arithmetic, we should get the original result back, and hence an - exact check should be OK here. */ - - CHECK(result[0].d == dblit(d)); - - /* Check the canary. */ - for (i = 0; i < sizeof (double); ++i) - CHECK(result[1].c[i] == CANARY); - - exit(0); - -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float_va.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float_va.c deleted file mode 100644 index 5acff91f6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/float_va.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Area: fp and variadics - Purpose: check fp inputs and returns work on variadics, even the fixed params - Limitations: None - PR: none - Originator: 2011-01-25 - - Intended to stress the difference in ABI on ARM vfp -*/ - -/* { dg-do run } */ - -#include - -#include "ffitest.h" - -/* prints out all the parameters, and returns the sum of them all. - * 'x' is the number of variadic parameters all of which are double in this test - */ -double float_va_fn(unsigned int x, double y,...) -{ - double total=0.0; - va_list ap; - unsigned int i; - - total+=(double)x; - total+=y; - - printf("%u: %.1f :", x, y); - - va_start(ap, y); - for(i=0;i -#include -#include - -static float ABI_ATTR many(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13) -{ -#if 0 - printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n", - (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, - (double) f6, (double) f7, (double) f8, (double) f9, (double) f10, - (double) f11, (double) f12, (double) f13); -#endif - - return f1+f2+f3+f4+f5+f6+f7+f8+f9+f10+f11+f12+f13; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[13]; - void *values[13]; - float fa[13]; - float f, ff; - int i; - - for (i = 0; i < 13; i++) - { - args[i] = &ffi_type_float; - values[i] = &fa[i]; - fa[i] = (float) i; - } - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 13, - &ffi_type_float, args) == FFI_OK); - - ffi_call(&cif, FFI_FN(many), &f, values); - - ff = many(fa[0], fa[1], - fa[2], fa[3], - fa[4], fa[5], - fa[6], fa[7], - fa[8], fa[9], - fa[10],fa[11],fa[12]); - - if (fabs(f - ff) < FLT_EPSILON) - exit(0); - else - abort(); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/many2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/many2.c deleted file mode 100644 index 1c85746e4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/many2.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Area: ffi_call - Purpose: Check uint8_t arguments. - Limitations: none. - PR: PR45677. - Originator: Dan Witte 20100916 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -#define NARGS 7 - -typedef unsigned char u8; - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -uint8_t -foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d, - uint8_t e, uint8_t f, uint8_t g) -{ - return a + b + c + d + e + f + g; -} - -uint8_t ABI_ATTR -bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d, - uint8_t e, uint8_t f, uint8_t g) -{ - return foo (a, b, c, d, e, f, g); -} - -int -main (void) -{ - ffi_type *ffitypes[NARGS]; - int i; - ffi_cif cif; - ffi_arg result = 0; - uint8_t args[NARGS]; - void *argptrs[NARGS]; - - for (i = 0; i < NARGS; ++i) - ffitypes[i] = &ffi_type_uint8; - - CHECK (ffi_prep_cif (&cif, ABI_NUM, NARGS, - &ffi_type_uint8, ffitypes) == FFI_OK); - - for (i = 0; i < NARGS; ++i) - { - args[i] = i; - argptrs[i] = &args[i]; - } - ffi_call (&cif, FFI_FN (bar), &result, argptrs); - - CHECK (result == 21); - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/negint.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/negint.c deleted file mode 100644 index 6e2f26fc1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/negint.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Area: ffi_call - Purpose: Check that negative integers are passed correctly. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static int checking(int a, short b, signed char c) -{ - - return (a < 0 && b < 0 && c < 0); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - - signed int si; - signed short ss; - signed char sc; - - args[0] = &ffi_type_sint; - values[0] = &si; - args[1] = &ffi_type_sshort; - values[1] = &ss; - args[2] = &ffi_type_schar; - values[2] = ≻ - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_sint, args) == FFI_OK); - - si = -6; - ss = -12; - sc = -1; - - checking (si, ss, sc); - - ffi_call(&cif, FFI_FN(checking), &rint, values); - - printf ("%d vs %d\n", (int)rint, checking (si, ss, sc)); - - CHECK(rint != 0); - - exit (0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct.c deleted file mode 100644 index c15e3a033..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_16byte1 { - double a; - float b; - int c; -} cls_struct_16byte1; - -typedef struct cls_struct_16byte2 { - int ii; - double dd; - float ff; -} cls_struct_16byte2; - -typedef struct cls_struct_combined { - cls_struct_16byte1 d; - cls_struct_16byte2 e; -} cls_struct_combined; - -cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, - struct cls_struct_16byte2 b1, - struct cls_struct_combined b2) -{ - struct cls_struct_combined result; - - result.d.a = b0.a + b1.dd + b2.d.a; - result.d.b = b0.b + b1.ff + b2.d.b; - result.d.c = b0.c + b1.ii + b2.d.c; - result.e.ii = b0.c + b1.ii + b2.e.ii; - result.e.dd = b0.a + b1.dd + b2.e.dd; - result.e.ff = b0.b + b1.ff + b2.e.ff; - - printf("%g %g %d %d %g %g %g %g %d %d %g %g: %g %g %d %d %g %g\n", - b0.a, b0.b, b0.c, - b1.ii, b1.dd, b1.ff, - b2.d.a, b2.d.b, b2.d.c, - b2.e.ii, b2.e.dd, b2.e.ff, - result.d.a, result.d.b, result.d.c, - result.e.ii, result.e.dd, result.e.ff); - - return result; -} - -static void -cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_16byte1 b0; - struct cls_struct_16byte2 b1; - struct cls_struct_combined b2; - - b0 = *(struct cls_struct_16byte1*)(args[0]); - b1 = *(struct cls_struct_16byte2*)(args[1]); - b2 = *(struct cls_struct_combined*)(args[2]); - - - *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type* cls_struct_fields1[5]; - ffi_type* cls_struct_fields2[5]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6}; - struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0}; - struct cls_struct_combined g_dbl = {{4.0, 5.0, 6}, - {3, 1.0, 8.0}}; - struct cls_struct_combined res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_float; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = NULL; - - cls_struct_fields1[0] = &ffi_type_sint; - cls_struct_fields1[1] = &ffi_type_double; - cls_struct_fields1[2] = &ffi_type_float; - cls_struct_fields1[3] = NULL; - - cls_struct_fields2[0] = &cls_struct_type; - cls_struct_fields2[1] = &cls_struct_type1; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type2, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl); - /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */ - CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a)); - CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b)); - CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c)); - CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii)); - CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd)); - CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1, - cls_struct_16byte2, - cls_struct_combined)) - (code))(e_dbl, f_dbl, g_dbl); - /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */ - CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a)); - CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b)); - CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c)); - CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii)); - CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd)); - CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff)); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct1.c deleted file mode 100644 index 477a6b9bd..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct1.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_16byte1 { - double a; - float b; - int c; -} cls_struct_16byte1; - -typedef struct cls_struct_16byte2 { - int ii; - double dd; - float ff; -} cls_struct_16byte2; - -typedef struct cls_struct_combined { - cls_struct_16byte1 d; - cls_struct_16byte2 e; -} cls_struct_combined; - -cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, - struct cls_struct_16byte2 b1, - struct cls_struct_combined b2, - struct cls_struct_16byte1 b3) -{ - struct cls_struct_combined result; - - result.d.a = b0.a + b1.dd + b2.d.a; - result.d.b = b0.b + b1.ff + b2.d.b; - result.d.c = b0.c + b1.ii + b2.d.c; - result.e.ii = b0.c + b1.ii + b2.e.ii; - result.e.dd = b0.a + b1.dd + b2.e.dd; - result.e.ff = b0.b + b1.ff + b2.e.ff; - - printf("%g %g %d %d %g %g %g %g %d %d %g %g %g %g %d: %g %g %d %d %g %g\n", - b0.a, b0.b, b0.c, - b1.ii, b1.dd, b1.ff, - b2.d.a, b2.d.b, b2.d.c, - b2.e.ii, b2.e.dd, b2.e.ff, - b3.a, b3.b, b3.c, - result.d.a, result.d.b, result.d.c, - result.e.ii, result.e.dd, result.e.ff); - - return result; -} - -static void -cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct cls_struct_16byte1 b0; - struct cls_struct_16byte2 b1; - struct cls_struct_combined b2; - struct cls_struct_16byte1 b3; - - b0 = *(struct cls_struct_16byte1*)(args[0]); - b1 = *(struct cls_struct_16byte2*)(args[1]); - b2 = *(struct cls_struct_combined*)(args[2]); - b3 = *(struct cls_struct_16byte1*)(args[3]); - - - *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[5]; - ffi_type* cls_struct_fields1[5]; - ffi_type* cls_struct_fields2[5]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6}; - struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0}; - struct cls_struct_combined g_dbl = {{4.0, 5.0, 6}, - {3, 1.0, 8.0}}; - struct cls_struct_16byte1 h_dbl = { 3.0, 2.0, 4}; - struct cls_struct_combined res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_float; - cls_struct_fields[2] = &ffi_type_sint; - cls_struct_fields[3] = NULL; - - cls_struct_fields1[0] = &ffi_type_sint; - cls_struct_fields1[1] = &ffi_type_double; - cls_struct_fields1[2] = &ffi_type_float; - cls_struct_fields1[3] = NULL; - - cls_struct_fields2[0] = &cls_struct_type; - cls_struct_fields2[1] = &cls_struct_type1; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type2, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl); - /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */ - CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a)); - CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b)); - CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c)); - CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii)); - CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd)); - CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK); - - res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1, - cls_struct_16byte2, - cls_struct_combined, - cls_struct_16byte1)) - (code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */ - CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a)); - CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b)); - CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c)); - CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii)); - CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd)); - CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff)); - /* CHECK( 1 == 0); */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct10.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct10.c deleted file mode 100644 index 34a74e718..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct10.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned long long a; - unsigned char b; -} A; - -typedef struct B { - unsigned char y; - struct A x; - unsigned int z; -} B; - -typedef struct C { - unsigned long long d; - unsigned char e; -} C; - -static B B_fn(struct A b2, struct B b3, struct C b4) -{ - struct B result; - - result.x.a = b2.a + b3.x.a + b3.z + b4.d; - result.x.b = b2.b + b3.x.b + b3.y + b4.e; - result.y = b2.b + b3.x.b + b4.e; - - printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - struct C b2; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - b2 = *(struct C*)(args[2]); - - *(B*)resp = B_fn(b0, b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[4]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[4]; - ffi_type* cls_struct_fields2[3]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[4]; - - struct A e_dbl = { 1LL, 7}; - struct B f_dbl = { 99, {12LL , 127}, 255}; - struct C g_dbl = { 2LL, 9}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_uint64; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &ffi_type_uchar; - cls_struct_fields1[1] = &cls_struct_type; - cls_struct_fields1[2] = &ffi_type_uint; - cls_struct_fields1[3] = NULL; - - cls_struct_fields2[0] = &ffi_type_uint64; - cls_struct_fields2[1] = &ffi_type_uchar; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl); - /* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct11.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct11.c deleted file mode 100644 index 351049382..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct11.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check parameter passing with nested structs - of a single type. This tests the special cases - for homogeneous floating-point aggregates in the - AArch64 PCS. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - float a_x; - float a_y; -} A; - -typedef struct B { - float b_x; - float b_y; -} B; - -typedef struct C { - A a; - B b; -} C; - -static C C_fn (int x, int y, int z, C source, int i, int j, int k) -{ - C result; - result.a.a_x = source.a.a_x; - result.a.a_y = source.a.a_y; - result.b.b_x = source.b.b_x; - result.b.b_y = source.b.b_y; - - printf ("%d, %d, %d, %d, %d, %d\n", x, y, z, i, j, k); - - printf ("%.1f, %.1f, %.1f, %.1f, " - "%.1f, %.1f, %.1f, %.1f\n", - source.a.a_x, source.a.a_y, - source.b.b_x, source.b.b_y, - result.a.a_x, result.a.a_y, - result.b.b_x, result.b.b_y); - - return result; -} - -int main (void) -{ - ffi_cif cif; - - ffi_type* struct_fields_source_a[3]; - ffi_type* struct_fields_source_b[3]; - ffi_type* struct_fields_source_c[3]; - ffi_type* arg_types[8]; - - ffi_type struct_type_a, struct_type_b, struct_type_c; - - struct A source_fld_a = {1.0, 2.0}; - struct B source_fld_b = {4.0, 8.0}; - int k = 1; - - struct C result; - struct C source = {source_fld_a, source_fld_b}; - - struct_type_a.size = 0; - struct_type_a.alignment = 0; - struct_type_a.type = FFI_TYPE_STRUCT; - struct_type_a.elements = struct_fields_source_a; - - struct_type_b.size = 0; - struct_type_b.alignment = 0; - struct_type_b.type = FFI_TYPE_STRUCT; - struct_type_b.elements = struct_fields_source_b; - - struct_type_c.size = 0; - struct_type_c.alignment = 0; - struct_type_c.type = FFI_TYPE_STRUCT; - struct_type_c.elements = struct_fields_source_c; - - struct_fields_source_a[0] = &ffi_type_float; - struct_fields_source_a[1] = &ffi_type_float; - struct_fields_source_a[2] = NULL; - - struct_fields_source_b[0] = &ffi_type_float; - struct_fields_source_b[1] = &ffi_type_float; - struct_fields_source_b[2] = NULL; - - struct_fields_source_c[0] = &struct_type_a; - struct_fields_source_c[1] = &struct_type_b; - struct_fields_source_c[2] = NULL; - - arg_types[0] = &ffi_type_sint32; - arg_types[1] = &ffi_type_sint32; - arg_types[2] = &ffi_type_sint32; - arg_types[3] = &struct_type_c; - arg_types[4] = &ffi_type_sint32; - arg_types[5] = &ffi_type_sint32; - arg_types[6] = &ffi_type_sint32; - arg_types[7] = NULL; - - void *args[7]; - args[0] = &k; - args[1] = &k; - args[2] = &k; - args[3] = &source; - args[4] = &k; - args[5] = &k; - args[6] = &k; - CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, 7, &struct_type_c, - arg_types) == FFI_OK); - - ffi_call (&cif, FFI_FN (C_fn), &result, args); - /* { dg-output "1, 1, 1, 1, 1, 1\n" } */ - /* { dg-output "1.0, 2.0, 4.0, 8.0, 1.0, 2.0, 4.0, 8.0" } */ - CHECK (result.a.a_x == source.a.a_x); - CHECK (result.a.a_y == source.a.a_y); - CHECK (result.b.b_x == source.b.b_x); - CHECK (result.b.b_y == source.b.b_y); - exit (0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct2.c deleted file mode 100644 index 69268cdb8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct2.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20030911 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned long a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -B B_fn(struct A b0, struct B b1) -{ - struct B result; - - result.x.a = b0.a + b1.x.a; - result.x.b = b0.b + b1.x.b + b1.y; - result.y = b0.b + b1.x.b; - - printf("%lu %d %lu %d %d: %lu %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y, - result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - - *(B*)resp = B_fn(b0, b1); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type cls_struct_type, cls_struct_type1; - ffi_type* dbl_arg_types[3]; - - struct A e_dbl = { 1, 7}; - struct B f_dbl = {{12 , 127}, 99}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_fields[0] = &ffi_type_ulong; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl); - /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct3.c deleted file mode 100644 index ab18cad73..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct3.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20030911 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned long long a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -B B_fn(struct A b0, struct B b1) -{ - struct B result; - - result.x.a = b0.a + b1.x.a; - result.x.b = b0.b + b1.x.b + b1.y; - result.y = b0.b + b1.x.b; - - printf("%d %d %d %d %d: %d %d %d\n", (int)b0.a, b0.b, - (int)b1.x.a, b1.x.b, b1.y, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - - *(B*)resp = B_fn(b0, b1); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type cls_struct_type, cls_struct_type1; - ffi_type* dbl_arg_types[3]; - - struct A e_dbl = { 1LL, 7}; - struct B f_dbl = {{12LL , 127}, 99}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_fields[0] = &ffi_type_uint64; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl); - /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct4.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct4.c deleted file mode 100644 index 2ffb4d65a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct4.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: PR 25630. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - double a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -static B B_fn(struct A b2, struct B b3) -{ - struct B result; - - result.x.a = b2.a + b3.x.a; - result.x.b = b2.b + b3.x.b + b3.y; - result.y = b2.b + b3.x.b; - - printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - - *(B*)resp = B_fn(b0, b1); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type cls_struct_type, cls_struct_type1; - ffi_type* dbl_arg_types[3]; - - struct A e_dbl = { 1.0, 7}; - struct B f_dbl = {{12.0 , 127}, 99}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl); - /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct5.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct5.c deleted file mode 100644 index 6c79845d9..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct5.c +++ /dev/null @@ -1,112 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - long double a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -static B B_fn(struct A b2, struct B b3) -{ - struct B result; - - result.x.a = b2.a + b3.x.a; - result.x.b = b2.b + b3.x.b + b3.y; - result.y = b2.b + b3.x.b; - - printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - - *(B*)resp = B_fn(b0, b1); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type cls_struct_type, cls_struct_type1; - ffi_type* dbl_arg_types[3]; - - struct A e_dbl = { 1.0, 7}; - struct B f_dbl = {{12.0 , 127}, 99}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_fields[0] = &ffi_type_longdouble; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl); - /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct6.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct6.c deleted file mode 100644 index 59d35796f..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct6.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: PR 25630. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - double a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -typedef struct C { - long d; - unsigned char e; -} C; - -static B B_fn(struct A b2, struct B b3, struct C b4) -{ - struct B result; - - result.x.a = b2.a + b3.x.a + b4.d; - result.x.b = b2.b + b3.x.b + b3.y + b4.e; - result.y = b2.b + b3.x.b + b4.e; - - printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - struct C b2; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - b2 = *(struct C*)(args[2]); - - *(B*)resp = B_fn(b0, b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[4]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type* cls_struct_fields2[3]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[4]; - - struct A e_dbl = { 1.0, 7}; - struct B f_dbl = {{12.0 , 127}, 99}; - struct C g_dbl = { 2, 9}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - cls_struct_fields2[0] = &ffi_type_slong; - cls_struct_fields2[1] = &ffi_type_uchar; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl); - /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct7.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct7.c deleted file mode 100644 index 27595e6f5..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct7.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned long long a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -static B B_fn(struct A b2, struct B b3) -{ - struct B result; - - result.x.a = b2.a + b3.x.a; - result.x.b = b2.b + b3.x.b + b3.y; - result.y = b2.b + b3.x.b; - - printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - - *(B*)resp = B_fn(b0, b1); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[3]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type cls_struct_type, cls_struct_type1; - ffi_type* dbl_arg_types[3]; - - struct A e_dbl = { 1LL, 7}; - struct B f_dbl = {{12.0 , 127}, 99}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_fields[0] = &ffi_type_uint64; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl); - /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct8.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct8.c deleted file mode 100644 index 0e6c68281..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct8.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned long long a; - unsigned char b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -typedef struct C { - unsigned long long d; - unsigned char e; -} C; - -static B B_fn(struct A b2, struct B b3, struct C b4) -{ - struct B result; - - result.x.a = b2.a + b3.x.a + b4.d; - result.x.b = b2.b + b3.x.b + b3.y + b4.e; - result.y = b2.b + b3.x.b + b4.e; - - printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, - (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e, - (int)result.x.a, result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - struct C b2; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - b2 = *(struct C*)(args[2]); - - *(B*)resp = B_fn(b0, b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[4]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type* cls_struct_fields2[3]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[4]; - - struct A e_dbl = { 1LL, 7}; - struct B f_dbl = {{12LL , 127}, 99}; - struct C g_dbl = { 2LL, 9}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_uint64; - cls_struct_fields[1] = &ffi_type_uchar; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - cls_struct_fields2[0] = &ffi_type_uint64; - cls_struct_fields2[1] = &ffi_type_uchar; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl); - /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct9.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct9.c deleted file mode 100644 index 5f7ac6775..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/nested_struct9.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Contains structs as parameter of the struct itself. - Sample taken from Alan Modras patch to src/prep_cif.c. - Limitations: none. - PR: none. - Originator: 20051010 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct A { - unsigned char a; - unsigned long long b; -} A; - -typedef struct B { - struct A x; - unsigned char y; -} B; - -typedef struct C { - unsigned long d; - unsigned char e; -} C; - -static B B_fn(struct A b2, struct B b3, struct C b4) -{ - struct B result; - - result.x.a = b2.a + b3.x.a + b4.d; - result.x.b = b2.b + b3.x.b + b3.y + b4.e; - result.y = b2.b + b3.x.b + b4.e; - - printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b, - b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e, - result.x.a, (int)result.x.b, result.y); - - return result; -} - -static void -B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct A b0; - struct B b1; - struct C b2; - - b0 = *(struct A*)(args[0]); - b1 = *(struct B*)(args[1]); - b2 = *(struct C*)(args[2]); - - *(B*)resp = B_fn(b0, b1, b2); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[4]; - ffi_type* cls_struct_fields[3]; - ffi_type* cls_struct_fields1[3]; - ffi_type* cls_struct_fields2[3]; - ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2; - ffi_type* dbl_arg_types[4]; - - struct A e_dbl = { 1, 7LL}; - struct B f_dbl = {{12.0 , 127}, 99}; - struct C g_dbl = { 2, 9}; - - struct B res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_type1.size = 0; - cls_struct_type1.alignment = 0; - cls_struct_type1.type = FFI_TYPE_STRUCT; - cls_struct_type1.elements = cls_struct_fields1; - - cls_struct_type2.size = 0; - cls_struct_type2.alignment = 0; - cls_struct_type2.type = FFI_TYPE_STRUCT; - cls_struct_type2.elements = cls_struct_fields2; - - cls_struct_fields[0] = &ffi_type_uchar; - cls_struct_fields[1] = &ffi_type_uint64; - cls_struct_fields[2] = NULL; - - cls_struct_fields1[0] = &cls_struct_type; - cls_struct_fields1[1] = &ffi_type_uchar; - cls_struct_fields1[2] = NULL; - - cls_struct_fields2[0] = &ffi_type_ulong; - cls_struct_fields2[1] = &ffi_type_uchar; - cls_struct_fields2[2] = NULL; - - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type1; - dbl_arg_types[2] = &cls_struct_type2; - dbl_arg_types[3] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = NULL; - - ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); - /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); - - res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl); - /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */ - CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d)); - CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e)); - CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e)); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/problem1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/problem1.c deleted file mode 100644 index 6a91555a1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/problem1.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing with different structure size. - Limitations: none. - PR: none. - Originator: 20030828 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct my_ffi_struct { - double a; - double b; - double c; -} my_ffi_struct; - -my_ffi_struct callee(struct my_ffi_struct a1, struct my_ffi_struct a2) -{ - struct my_ffi_struct result; - result.a = a1.a + a2.a; - result.b = a1.b + a2.b; - result.c = a1.c + a2.c; - - - printf("%g %g %g %g %g %g: %g %g %g\n", a1.a, a1.b, a1.c, - a2.a, a2.b, a2.c, result.a, result.b, result.c); - - return result; -} - -void stub(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) -{ - struct my_ffi_struct a1; - struct my_ffi_struct a2; - - a1 = *(struct my_ffi_struct*)(args[0]); - a2 = *(struct my_ffi_struct*)(args[1]); - - *(my_ffi_struct *)resp = callee(a1, a2); -} - - -int main(void) -{ - ffi_type* my_ffi_struct_fields[4]; - ffi_type my_ffi_struct_type; - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args[4]; - ffi_type* arg_types[3]; - - struct my_ffi_struct g = { 1.0, 2.0, 3.0 }; - struct my_ffi_struct f = { 1.0, 2.0, 3.0 }; - struct my_ffi_struct res; - - my_ffi_struct_type.size = 0; - my_ffi_struct_type.alignment = 0; - my_ffi_struct_type.type = FFI_TYPE_STRUCT; - my_ffi_struct_type.elements = my_ffi_struct_fields; - - my_ffi_struct_fields[0] = &ffi_type_double; - my_ffi_struct_fields[1] = &ffi_type_double; - my_ffi_struct_fields[2] = &ffi_type_double; - my_ffi_struct_fields[3] = NULL; - - arg_types[0] = &my_ffi_struct_type; - arg_types[1] = &my_ffi_struct_type; - arg_types[2] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &my_ffi_struct_type, - arg_types) == FFI_OK); - - args[0] = &g; - args[1] = &f; - args[2] = NULL; - ffi_call(&cif, FFI_FN(callee), &res, args); - /* { dg-output "1 2 3 1 2 3: 2 4 6" } */ - printf("res: %g %g %g\n", res.a, res.b, res.c); - /* { dg-output "\nres: 2 4 6" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, stub, NULL, code) == FFI_OK); - - res = ((my_ffi_struct(*)(struct my_ffi_struct, struct my_ffi_struct))(code))(g, f); - /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */ - printf("res: %g %g %g\n", res.a, res.b, res.c); - /* { dg-output "\nres: 2 4 6" } */ - - exit(0);; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/promotion.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/promotion.c deleted file mode 100644 index 44561615d..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/promotion.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Area: ffi_call - Purpose: Promotion test. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -static int promotion(signed char sc, signed short ss, - unsigned char uc, unsigned short us) -{ - int r = (int) sc + (int) ss + (int) uc + (int) us; - - return r; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - signed char sc; - unsigned char uc; - signed short ss; - unsigned short us; - unsigned long ul; - - args[0] = &ffi_type_schar; - args[1] = &ffi_type_sshort; - args[2] = &ffi_type_uchar; - args[3] = &ffi_type_ushort; - values[0] = ≻ - values[1] = &ss; - values[2] = &uc; - values[3] = &us; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_sint, args) == FFI_OK); - - us = 0; - ul = 0; - - for (sc = (signed char) -127; - sc <= (signed char) 120; sc += 1) - for (ss = -30000; ss <= 30000; ss += 10000) - for (uc = (unsigned char) 0; - uc <= (unsigned char) 200; uc += 20) - for (us = 0; us <= 60000; us += 10000) - { - ul++; - ffi_call(&cif, FFI_FN(promotion), &rint, values); - CHECK((int)rint == (signed char) sc + (signed short) ss + - (unsigned char) uc + (unsigned short) us); - } - printf("%lu promotion tests run\n", ul); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/pyobjc-tc.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/pyobjc-tc.c deleted file mode 100644 index e29bd6c28..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/pyobjc-tc.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Area: ffi_call - Purpose: Check different structures. - Limitations: none. - PR: none. - Originator: Ronald Oussoren 20030824 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct Point { - float x; - float y; -} Point; - -typedef struct Size { - float h; - float w; -} Size; - -typedef struct Rect { - Point o; - Size s; -} Rect; - -int doit(int o, char* s, Point p, Rect r, int last) -{ - printf("CALLED WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n", - o, s, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, last); - return 42; -} - - -int main(void) -{ - ffi_type point_type; - ffi_type size_type; - ffi_type rect_type; - ffi_cif cif; - ffi_type* arglist[6]; - void* values[6]; - int r; - - /* - * First set up FFI types for the 3 struct types - */ - - point_type.size = 0; /*sizeof(Point);*/ - point_type.alignment = 0; /*__alignof__(Point);*/ - point_type.type = FFI_TYPE_STRUCT; - point_type.elements = malloc(3 * sizeof(ffi_type*)); - point_type.elements[0] = &ffi_type_float; - point_type.elements[1] = &ffi_type_float; - point_type.elements[2] = NULL; - - size_type.size = 0;/* sizeof(Size);*/ - size_type.alignment = 0;/* __alignof__(Size);*/ - size_type.type = FFI_TYPE_STRUCT; - size_type.elements = malloc(3 * sizeof(ffi_type*)); - size_type.elements[0] = &ffi_type_float; - size_type.elements[1] = &ffi_type_float; - size_type.elements[2] = NULL; - - rect_type.size = 0;/*sizeof(Rect);*/ - rect_type.alignment =0;/* __alignof__(Rect);*/ - rect_type.type = FFI_TYPE_STRUCT; - rect_type.elements = malloc(3 * sizeof(ffi_type*)); - rect_type.elements[0] = &point_type; - rect_type.elements[1] = &size_type; - rect_type.elements[2] = NULL; - - /* - * Create a CIF - */ - arglist[0] = &ffi_type_sint; - arglist[1] = &ffi_type_pointer; - arglist[2] = &point_type; - arglist[3] = &rect_type; - arglist[4] = &ffi_type_sint; - arglist[5] = NULL; - - r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, - 5, &ffi_type_sint, arglist); - if (r != FFI_OK) { - abort(); - } - - - /* And call the function through the CIF */ - - { - Point p = { 1.0, 2.0 }; - Rect r = { { 9.0, 10.0}, { -1.0, -2.0 } }; - int o = 0; - int l = 42; - char* m = "myMethod"; - ffi_arg result; - - values[0] = &o; - values[1] = &m; - values[2] = &p; - values[3] = &r; - values[4] = &l; - values[5] = NULL; - - printf("CALLING WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n", - o, m, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, l); - - ffi_call(&cif, FFI_FN(doit), &result, values); - - printf ("The result is %d\n", (int)result); - - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl.c deleted file mode 100644 index fd07e5017..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value double. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static double return_dbl(double dbl) -{ - printf ("%f\n", dbl); - return 2 * dbl; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - double dbl, rdbl; - - args[0] = &ffi_type_double; - values[0] = &dbl; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_double, args) == FFI_OK); - - for (dbl = -127.3; dbl < 127; dbl++) - { - ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values); - printf ("%f vs %f\n", rdbl, return_dbl(dbl)); - CHECK(rdbl == 2 * dbl); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl1.c deleted file mode 100644 index 0ea5d5055..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl1.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value double. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static double return_dbl(double dbl1, float fl2, unsigned int in3, double dbl4) -{ - return dbl1 + fl2 + in3 + dbl4; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - double dbl1, dbl4, rdbl; - float fl2; - unsigned int in3; - args[0] = &ffi_type_double; - args[1] = &ffi_type_float; - args[2] = &ffi_type_uint; - args[3] = &ffi_type_double; - values[0] = &dbl1; - values[1] = &fl2; - values[2] = &in3; - values[3] = &dbl4; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_double, args) == FFI_OK); - dbl1 = 127.0; - fl2 = 128.0; - in3 = 255; - dbl4 = 512.7; - - ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values); - printf ("%f vs %f\n", rdbl, return_dbl(dbl1, fl2, in3, dbl4)); - CHECK(rdbl == dbl1 + fl2 + in3 + dbl4); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl2.c deleted file mode 100644 index b3818f866..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_dbl2.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value double. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static double return_dbl(double dbl1, double dbl2, unsigned int in3, double dbl4) -{ - return dbl1 + dbl2 + in3 + dbl4; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - double dbl1, dbl2, dbl4, rdbl; - unsigned int in3; - args[0] = &ffi_type_double; - args[1] = &ffi_type_double; - args[2] = &ffi_type_uint; - args[3] = &ffi_type_double; - values[0] = &dbl1; - values[1] = &dbl2; - values[2] = &in3; - values[3] = &dbl4; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_double, args) == FFI_OK); - dbl1 = 127.0; - dbl2 = 128.0; - in3 = 255; - dbl4 = 512.7; - - ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values); - printf ("%f vs %f\n", rdbl, return_dbl(dbl1, dbl2, in3, dbl4)); - CHECK(rdbl == dbl1 + dbl2 + in3 + dbl4); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl.c deleted file mode 100644 index fb8a09e32..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static float return_fl(float fl) -{ - return 2 * fl; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float fl, rfl; - - args[0] = &ffi_type_float; - values[0] = &fl; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_float, args) == FFI_OK); - - for (fl = -127.0; fl < 127; fl++) - { - ffi_call(&cif, FFI_FN(return_fl), &rfl, values); - printf ("%f vs %f\n", rfl, return_fl(fl)); - CHECK(rfl == 2 * fl); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl1.c deleted file mode 100644 index c3d92c283..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl1.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static float return_fl(float fl1, float fl2) -{ - return fl1 + fl2; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float fl1, fl2, rfl; - - args[0] = &ffi_type_float; - args[1] = &ffi_type_float; - values[0] = &fl1; - values[1] = &fl2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_float, args) == FFI_OK); - fl1 = 127.0; - fl2 = 128.0; - - ffi_call(&cif, FFI_FN(return_fl), &rfl, values); - printf ("%f vs %f\n", rfl, return_fl(fl1, fl2)); - CHECK(rfl == fl1 + fl2); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl2.c deleted file mode 100644 index ddb976cc2..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl2.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -/* Use volatile float to avoid false negative on ix86. See PR target/323. */ -static float return_fl(float fl1, float fl2, float fl3, float fl4) -{ - volatile float sum; - - sum = fl1 + fl2 + fl3 + fl4; - return sum; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float fl1, fl2, fl3, fl4, rfl; - volatile float sum; - - args[0] = &ffi_type_float; - args[1] = &ffi_type_float; - args[2] = &ffi_type_float; - args[3] = &ffi_type_float; - values[0] = &fl1; - values[1] = &fl2; - values[2] = &fl3; - values[3] = &fl4; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_float, args) == FFI_OK); - fl1 = 127.0; - fl2 = 128.0; - fl3 = 255.1; - fl4 = 512.7; - - ffi_call(&cif, FFI_FN(return_fl), &rfl, values); - printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, fl3, fl4)); - - sum = fl1 + fl2 + fl3 + fl4; - CHECK(rfl == sum); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl3.c deleted file mode 100644 index c37877b18..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_fl3.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value float. - Limitations: none. - PR: none. - Originator: 20050212 */ - -/* { dg-do run } */ -#include "ffitest.h" - -static float return_fl(float fl1, float fl2, unsigned int in3, float fl4) -{ - return fl1 + fl2 + in3 + fl4; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - float fl1, fl2, fl4, rfl; - unsigned int in3; - args[0] = &ffi_type_float; - args[1] = &ffi_type_float; - args[2] = &ffi_type_uint; - args[3] = &ffi_type_float; - values[0] = &fl1; - values[1] = &fl2; - values[2] = &in3; - values[3] = &fl4; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, - &ffi_type_float, args) == FFI_OK); - fl1 = 127.0; - fl2 = 128.0; - in3 = 255; - fl4 = 512.7; - - ffi_call(&cif, FFI_FN(return_fl), &rfl, values); - printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, in3, fl4)); - CHECK(rfl == fl1 + fl2 + in3 + fl4); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ldl.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ldl.c deleted file mode 100644 index 5c2fe65ae..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ldl.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value long double. - Limitations: none. - PR: none. - Originator: 20071113 */ - -/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ -#include "ffitest.h" - -static long double return_ldl(long double ldl) -{ - return 2*ldl; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - long double ldl, rldl; - - args[0] = &ffi_type_longdouble; - values[0] = &ldl; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_longdouble, args) == FFI_OK); - - for (ldl = -127.0; ldl < 127.0; ldl++) - { - ffi_call(&cif, FFI_FN(return_ldl), &rldl, values); - CHECK(rldl == 2 * ldl); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll.c deleted file mode 100644 index ea4a1e447..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value long long. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -static long long return_ll(long long ll) -{ - return ll; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - long long rlonglong; - long long ll; - - args[0] = &ffi_type_sint64; - values[0] = ≪ - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_sint64, args) == FFI_OK); - - for (ll = 0LL; ll < 100LL; ll++) - { - ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); - CHECK(rlonglong == ll); - } - - for (ll = 55555555555000LL; ll < 55555555555100LL; ll++) - { - ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); - CHECK(rlonglong == ll); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll1.c deleted file mode 100644 index 593e8a307..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ll1.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Area: ffi_call - Purpose: Check if long long are passed in the corresponding regs on ppc. - Limitations: none. - PR: 20104. - Originator: 20050222 */ - -/* { dg-do run } */ -/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */ -#include "ffitest.h" -static long long return_ll(int ll0, long long ll1, int ll2) -{ - return ll0 + ll1 + ll2; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - long long rlonglong; - long long ll1; - unsigned ll0, ll2; - - args[0] = &ffi_type_sint; - args[1] = &ffi_type_sint64; - args[2] = &ffi_type_sint; - values[0] = &ll0; - values[1] = &ll1; - values[2] = &ll2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_sint64, args) == FFI_OK); - - ll0 = 11111111; - ll1 = 11111111111000LL; - ll2 = 11111111; - - ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); - printf("res: %" PRIdLL ", %" PRIdLL "\n", rlonglong, ll0 + ll1 + ll2); - /* { dg-output "res: 11111133333222, 11111133333222" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sc.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sc.c deleted file mode 100644 index a36cf3eb8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sc.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value signed char. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -static signed char return_sc(signed char sc) -{ - return sc; -} -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - signed char sc; - - args[0] = &ffi_type_schar; - values[0] = ≻ - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_schar, args) == FFI_OK); - - for (sc = (signed char) -127; - sc < (signed char) 127; sc++) - { - ffi_call(&cif, FFI_FN(return_sc), &rint, values); - CHECK((signed char)rint == sc); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sl.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sl.c deleted file mode 100644 index f0fd345f7..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_sl.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Area: ffi_call - Purpose: Check if long as return type is handled correctly. - Limitations: none. - PR: none. - */ - -/* { dg-do run } */ -#include "ffitest.h" -static long return_sl(long l1, long l2) -{ - return l1 - l2; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg res; - unsigned long l1, l2; - - args[0] = &ffi_type_slong; - args[1] = &ffi_type_slong; - values[0] = &l1; - values[1] = &l2; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_slong, args) == FFI_OK); - - l1 = 1073741823L; - l2 = 1073741824L; - - ffi_call(&cif, FFI_FN(return_sl), &res, values); - printf("res: %ld, %ld\n", (long)res, l1 - l2); - /* { dg-output "res: -1, -1" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_uc.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_uc.c deleted file mode 100644 index 6fe554619..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_uc.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Area: ffi_call - Purpose: Check return value unsigned char. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -static unsigned char return_uc(unsigned char uc) -{ - return uc; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - - unsigned char uc; - - args[0] = &ffi_type_uchar; - values[0] = &uc; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ffi_type_uchar, args) == FFI_OK); - - for (uc = (unsigned char) '\x00'; - uc < (unsigned char) '\xff'; uc++) - { - ffi_call(&cif, FFI_FN(return_uc), &rint, values); - CHECK((unsigned char)rint == uc); - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ul.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ul.c deleted file mode 100644 index 12b266f03..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/return_ul.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Area: ffi_call - Purpose: Check if unsigned long as return type is handled correctly. - Limitations: none. - PR: none. - Originator: 20060724 */ - -/* { dg-do run } */ -#include "ffitest.h" -static unsigned long return_ul(unsigned long ul1, unsigned long ul2) -{ - return ul1 + ul2; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg res; - unsigned long ul1, ul2; - - args[0] = &ffi_type_ulong; - args[1] = &ffi_type_ulong; - values[0] = &ul1; - values[1] = &ul2; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, - &ffi_type_ulong, args) == FFI_OK); - - ul1 = 1073741823L; - ul2 = 1073741824L; - - ffi_call(&cif, FFI_FN(return_ul), &res, values); - printf("res: %lu, %lu\n", (unsigned long)res, ul1 + ul2); - /* { dg-output "res: 2147483647, 2147483647" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large.c deleted file mode 100644 index 71c2469e1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure returning with different structure size. - Depending on the ABI. Check bigger struct which overlaps - the gp and fp register count on Darwin/AIX/ppc64. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/21/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -#include "ffitest.h" - -/* 13 FPRs: 104 bytes */ -/* 14 FPRs: 112 bytes */ - -typedef struct struct_108byte { - double a; - double b; - double c; - double d; - double e; - double f; - double g; - double h; - double i; - double j; - double k; - double l; - double m; - int n; -} struct_108byte; - -struct_108byte cls_struct_108byte_fn( - struct_108byte b0, - struct_108byte b1, - struct_108byte b2, - struct_108byte b3) -{ - struct_108byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - result.e = b0.e + b1.e + b2.e + b3.e; - result.f = b0.f + b1.f + b2.f + b3.f; - result.g = b0.g + b1.g + b2.g + b3.g; - result.h = b0.h + b1.h + b2.h + b3.h; - result.i = b0.i + b1.i + b2.i + b3.i; - result.j = b0.j + b1.j + b2.j + b3.j; - result.k = b0.k + b1.k + b2.k + b3.k; - result.l = b0.l + b1.l + b2.l + b3.l; - result.m = b0.m + b1.m + b2.m + b3.m; - result.n = b0.n + b1.n + b2.n + b3.n; - - printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c, - result.d, result.e, result.f, result.g, result.h, result.i, - result.j, result.k, result.l, result.m, result.n); - - return result; -} - -static void -cls_struct_108byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__) -{ - struct_108byte b0, b1, b2, b3; - - b0 = *(struct_108byte*)(args[0]); - b1 = *(struct_108byte*)(args[1]); - b2 = *(struct_108byte*)(args[2]); - b3 = *(struct_108byte*)(args[3]); - - *(struct_108byte*)resp = cls_struct_108byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[15]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct_108byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 7 }; - struct_108byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 4 }; - struct_108byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 3 }; - struct_108byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 2 }; - struct_108byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_double; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_double; - cls_struct_fields[7] = &ffi_type_double; - cls_struct_fields[8] = &ffi_type_double; - cls_struct_fields[9] = &ffi_type_double; - cls_struct_fields[10] = &ffi_type_double; - cls_struct_fields[11] = &ffi_type_double; - cls_struct_fields[12] = &ffi_type_double; - cls_struct_fields[13] = &ffi_type_sint32; - cls_struct_fields[14] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_108byte_fn), &res_dbl, args_dbl); - /* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i, - res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_108byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((struct_108byte(*)(struct_108byte, struct_108byte, - struct_108byte, struct_108byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i, - res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large2.c deleted file mode 100644 index d9c750ee1..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_large2.c +++ /dev/null @@ -1,148 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure returning with different structure size. - Depending on the ABI. Check bigger struct which overlaps - the gp and fp register count on Darwin/AIX/ppc64. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/21/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -#include "ffitest.h" - -/* 13 FPRs: 104 bytes */ -/* 14 FPRs: 112 bytes */ - -typedef struct struct_116byte { - double a; - double b; - double c; - double d; - double e; - double f; - double g; - double h; - double i; - double j; - double k; - double l; - double m; - double n; - int o; -} struct_116byte; - -struct_116byte cls_struct_116byte_fn( - struct_116byte b0, - struct_116byte b1, - struct_116byte b2, - struct_116byte b3) -{ - struct_116byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - result.e = b0.e + b1.e + b2.e + b3.e; - result.f = b0.f + b1.f + b2.f + b3.f; - result.g = b0.g + b1.g + b2.g + b3.g; - result.h = b0.h + b1.h + b2.h + b3.h; - result.i = b0.i + b1.i + b2.i + b3.i; - result.j = b0.j + b1.j + b2.j + b3.j; - result.k = b0.k + b1.k + b2.k + b3.k; - result.l = b0.l + b1.l + b2.l + b3.l; - result.m = b0.m + b1.m + b2.m + b3.m; - result.n = b0.n + b1.n + b2.n + b3.n; - result.o = b0.o + b1.o + b2.o + b3.o; - - printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c, - result.d, result.e, result.f, result.g, result.h, result.i, - result.j, result.k, result.l, result.m, result.n, result.o); - - return result; -} - -static void -cls_struct_116byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__) -{ - struct_116byte b0, b1, b2, b3; - - b0 = *(struct_116byte*)(args[0]); - b1 = *(struct_116byte*)(args[1]); - b2 = *(struct_116byte*)(args[2]); - b3 = *(struct_116byte*)(args[3]); - - *(struct_116byte*)resp = cls_struct_116byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[16]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct_116byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 7 }; - struct_116byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 6.0, 4 }; - struct_116byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 7.0, 3 }; - struct_116byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 8.0, 2 }; - struct_116byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_double; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_double; - cls_struct_fields[7] = &ffi_type_double; - cls_struct_fields[8] = &ffi_type_double; - cls_struct_fields[9] = &ffi_type_double; - cls_struct_fields[10] = &ffi_type_double; - cls_struct_fields[11] = &ffi_type_double; - cls_struct_fields[12] = &ffi_type_double; - cls_struct_fields[13] = &ffi_type_double; - cls_struct_fields[14] = &ffi_type_sint32; - cls_struct_fields[15] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_116byte_fn), &res_dbl, args_dbl); - /* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i, - res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_116byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((struct_116byte(*)(struct_116byte, struct_116byte, - struct_116byte, struct_116byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b, - res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i, - res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium.c deleted file mode 100644 index 973ee02ed..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure returning with different structure size. - Depending on the ABI. Check bigger struct which overlaps - the gp and fp register count on Darwin/AIX/ppc64. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/21/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -#include "ffitest.h" - -typedef struct struct_72byte { - double a; - double b; - double c; - double d; - double e; - double f; - double g; - double h; - double i; -} struct_72byte; - -struct_72byte cls_struct_72byte_fn( - struct_72byte b0, - struct_72byte b1, - struct_72byte b2, - struct_72byte b3) -{ - struct_72byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - result.e = b0.e + b1.e + b2.e + b3.e; - result.f = b0.f + b1.f + b2.f + b3.f; - result.g = b0.g + b1.g + b2.g + b3.g; - result.h = b0.h + b1.h + b2.h + b3.h; - result.i = b0.i + b1.i + b2.i + b3.i; - - printf("%g %g %g %g %g %g %g %g %g\n", result.a, result.b, result.c, - result.d, result.e, result.f, result.g, result.h, result.i); - - return result; -} - -static void -cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__) -{ - struct_72byte b0, b1, b2, b3; - - b0 = *(struct_72byte*)(args[0]); - b1 = *(struct_72byte*)(args[1]); - b2 = *(struct_72byte*)(args[2]); - b3 = *(struct_72byte*)(args[3]); - - *(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[10]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7.0 }; - struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0 }; - struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3.0 }; - struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2.0 }; - struct_72byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_double; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_double; - cls_struct_fields[7] = &ffi_type_double; - cls_struct_fields[8] = &ffi_type_double; - cls_struct_fields[9] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl); - /* { dg-output "22 15 17 25 6 13 19 18 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte, - struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n22 15 17 25 6 13 19 18 16" } */ - printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium2.c deleted file mode 100644 index 84323d16a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/stret_medium2.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure returning with different structure size. - Depending on the ABI. Check bigger struct which overlaps - the gp and fp register count on Darwin/AIX/ppc64. - Limitations: none. - PR: none. - Originator: Blake Chaffin 6/21/2007 */ - -/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ -/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */ -#include "ffitest.h" - -typedef struct struct_72byte { - double a; - double b; - double c; - double d; - double e; - double f; - double g; - double h; - long long i; -} struct_72byte; - -struct_72byte cls_struct_72byte_fn( - struct_72byte b0, - struct_72byte b1, - struct_72byte b2, - struct_72byte b3) -{ - struct_72byte result; - - result.a = b0.a + b1.a + b2.a + b3.a; - result.b = b0.b + b1.b + b2.b + b3.b; - result.c = b0.c + b1.c + b2.c + b3.c; - result.d = b0.d + b1.d + b2.d + b3.d; - result.e = b0.e + b1.e + b2.e + b3.e; - result.f = b0.f + b1.f + b2.f + b3.f; - result.g = b0.g + b1.g + b2.g + b3.g; - result.h = b0.h + b1.h + b2.h + b3.h; - result.i = b0.i + b1.i + b2.i + b3.i; - - printf("%g %g %g %g %g %g %g %g %" PRIdLL "\n", result.a, result.b, result.c, - result.d, result.e, result.f, result.g, result.h, result.i); - - return result; -} - -static void -cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__) -{ - struct_72byte b0, b1, b2, b3; - - b0 = *(struct_72byte*)(args[0]); - b1 = *(struct_72byte*)(args[1]); - b2 = *(struct_72byte*)(args[2]); - b3 = *(struct_72byte*)(args[3]); - - *(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3); -} - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - void* args_dbl[5]; - ffi_type* cls_struct_fields[10]; - ffi_type cls_struct_type; - ffi_type* dbl_arg_types[5]; - - struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 }; - struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 }; - struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 }; - struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 }; - struct_72byte res_dbl; - - cls_struct_type.size = 0; - cls_struct_type.alignment = 0; - cls_struct_type.type = FFI_TYPE_STRUCT; - cls_struct_type.elements = cls_struct_fields; - - cls_struct_fields[0] = &ffi_type_double; - cls_struct_fields[1] = &ffi_type_double; - cls_struct_fields[2] = &ffi_type_double; - cls_struct_fields[3] = &ffi_type_double; - cls_struct_fields[4] = &ffi_type_double; - cls_struct_fields[5] = &ffi_type_double; - cls_struct_fields[6] = &ffi_type_double; - cls_struct_fields[7] = &ffi_type_double; - cls_struct_fields[8] = &ffi_type_sint64; - cls_struct_fields[9] = NULL; - - dbl_arg_types[0] = &cls_struct_type; - dbl_arg_types[1] = &cls_struct_type; - dbl_arg_types[2] = &cls_struct_type; - dbl_arg_types[3] = &cls_struct_type; - dbl_arg_types[4] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, - dbl_arg_types) == FFI_OK); - - args_dbl[0] = &e_dbl; - args_dbl[1] = &f_dbl; - args_dbl[2] = &g_dbl; - args_dbl[3] = &h_dbl; - args_dbl[4] = NULL; - - ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl); - /* { dg-output "22 15 17 25 6 13 19 18 16" } */ - printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK); - - res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte, - struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n22 15 17 25 6 13 19 18 16" } */ - printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c, - res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); - /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen.c deleted file mode 100644 index 35b70ea4e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: ffi_call - Purpose: Check strlen function call. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -static size_t ABI_ATTR my_strlen(char *s) -{ - return (strlen(s)); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - char *s; - - args[0] = &ffi_type_pointer; - values[0] = (void*) &s; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, - &ffi_type_sint, args) == FFI_OK); - - s = "a"; - ffi_call(&cif, FFI_FN(my_strlen), &rint, values); - CHECK(rint == 1); - - s = "1234567"; - ffi_call(&cif, FFI_FN(my_strlen), &rint, values); - CHECK(rint == 7); - - s = "1234567890123456789012345"; - ffi_call(&cif, FFI_FN(my_strlen), &rint, values); - CHECK(rint == 25); - - exit (0); -} - diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen2.c deleted file mode 100644 index 96282bc0a..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen2.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Area: ffi_call - Purpose: Check strlen function call with additional arguments. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static size_t ABI_ATTR my_f(char *s, float a) -{ - return (size_t) ((int) strlen(s) + (int) a); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - char *s; - float v2; - args[0] = &ffi_type_pointer; - args[1] = &ffi_type_float; - values[0] = (void*) &s; - values[1] = (void*) &v2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, - &ffi_type_sint, args) == FFI_OK); - - s = "a"; - v2 = 0.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 1); - - s = "1234567"; - v2 = -1.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 6); - - s = "1234567890123456789012345"; - v2 = 1.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 26); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen3.c deleted file mode 100644 index beba86e9e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen3.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Area: ffi_call - Purpose: Check strlen function call with additional arguments. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static size_t ABI_ATTR my_f(float a, char *s) -{ - return (size_t) ((int) strlen(s) + (int) a); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - char *s; - float v2; - args[1] = &ffi_type_pointer; - args[0] = &ffi_type_float; - values[1] = (void*) &s; - values[0] = (void*) &v2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, - &ffi_type_sint, args) == FFI_OK); - - s = "a"; - v2 = 0.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 1); - - s = "1234567"; - v2 = -1.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 6); - - s = "1234567890123456789012345"; - v2 = 1.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 26); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen4.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen4.c deleted file mode 100644 index d5d42b4f6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/strlen4.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Area: ffi_call - Purpose: Check strlen function call with additional arguments. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static size_t ABI_ATTR my_f(float a, char *s, int i) -{ - return (size_t) ((int) strlen(s) + (int) a + i); -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - char *s; - int v1; - float v2; - args[2] = &ffi_type_sint; - args[1] = &ffi_type_pointer; - args[0] = &ffi_type_float; - values[2] = (void*) &v1; - values[1] = (void*) &s; - values[0] = (void*) &v2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 3, - &ffi_type_sint, args) == FFI_OK); - - s = "a"; - v1 = 1; - v2 = 0.0; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 2); - - s = "1234567"; - v2 = -1.0; - v1 = -2; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 4); - - s = "1234567890123456789012345"; - v2 = 1.0; - v1 = 2; - ffi_call(&cif, FFI_FN(my_f), &rint, values); - CHECK(rint == 28); - - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct1.c deleted file mode 100644 index c13e23f87..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct1.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - unsigned char uc; - double d; - unsigned int ui; -} test_structure_1; - -static test_structure_1 ABI_ATTR struct1(test_structure_1 ts) -{ - ts.uc++; - ts.d--; - ts.ui++; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts1_type; - ffi_type *ts1_type_elements[4]; - - test_structure_1 ts1_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_1 *ts1_result = - (test_structure_1 *) malloc (sizeof(test_structure_1)); - - ts1_type.size = 0; - ts1_type.alignment = 0; - ts1_type.type = FFI_TYPE_STRUCT; - ts1_type.elements = ts1_type_elements; - ts1_type_elements[0] = &ffi_type_uchar; - ts1_type_elements[1] = &ffi_type_double; - ts1_type_elements[2] = &ffi_type_uint; - ts1_type_elements[3] = NULL; - - args[0] = &ts1_type; - values[0] = &ts1_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, - &ts1_type, args) == FFI_OK); - - ts1_arg.uc = '\x01'; - ts1_arg.d = 3.14159; - ts1_arg.ui = 555; - - ffi_call(&cif, FFI_FN(struct1), ts1_result, values); - - CHECK(ts1_result->ui == 556); - CHECK(ts1_result->d == 3.14159 - 1); - - free (ts1_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct2.c deleted file mode 100644 index 5077a5ee4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct2.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - double d1; - double d2; -} test_structure_2; - -static test_structure_2 ABI_ATTR struct2(test_structure_2 ts) -{ - ts.d1--; - ts.d2--; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - test_structure_2 ts2_arg; - ffi_type ts2_type; - ffi_type *ts2_type_elements[3]; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_2 *ts2_result = - (test_structure_2 *) malloc (sizeof(test_structure_2)); - - ts2_type.size = 0; - ts2_type.alignment = 0; - ts2_type.type = FFI_TYPE_STRUCT; - ts2_type.elements = ts2_type_elements; - ts2_type_elements[0] = &ffi_type_double; - ts2_type_elements[1] = &ffi_type_double; - ts2_type_elements[2] = NULL; - - args[0] = &ts2_type; - values[0] = &ts2_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts2_type, args) == FFI_OK); - - ts2_arg.d1 = 5.55; - ts2_arg.d2 = 6.66; - - printf ("%g\n", ts2_arg.d1); - printf ("%g\n", ts2_arg.d2); - - ffi_call(&cif, FFI_FN(struct2), ts2_result, values); - - printf ("%g\n", ts2_result->d1); - printf ("%g\n", ts2_result->d2); - - CHECK(ts2_result->d1 == 5.55 - 1); - CHECK(ts2_result->d2 == 6.66 - 1); - - free (ts2_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct3.c deleted file mode 100644 index 7eba0ead6..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct3.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - int si; -} test_structure_3; - -static test_structure_3 ABI_ATTR struct3(test_structure_3 ts) -{ - ts.si = -(ts.si*2); - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - int compare_value; - ffi_type ts3_type; - ffi_type *ts3_type_elements[2]; - - test_structure_3 ts3_arg; - test_structure_3 *ts3_result = - (test_structure_3 *) malloc (sizeof(test_structure_3)); - - ts3_type.size = 0; - ts3_type.alignment = 0; - ts3_type.type = FFI_TYPE_STRUCT; - ts3_type.elements = ts3_type_elements; - ts3_type_elements[0] = &ffi_type_sint; - ts3_type_elements[1] = NULL; - - args[0] = &ts3_type; - values[0] = &ts3_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, - &ts3_type, args) == FFI_OK); - - ts3_arg.si = -123; - compare_value = ts3_arg.si; - - ffi_call(&cif, FFI_FN(struct3), ts3_result, values); - - printf ("%d %d\n", ts3_result->si, -(compare_value*2)); - - CHECK(ts3_result->si == -(compare_value*2)); - - free (ts3_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct4.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct4.c deleted file mode 100644 index 66a9551dd..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct4.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - unsigned ui1; - unsigned ui2; - unsigned ui3; -} test_structure_4; - -static test_structure_4 ABI_ATTR struct4(test_structure_4 ts) -{ - ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts4_type; - ffi_type *ts4_type_elements[4]; - - test_structure_4 ts4_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_4 *ts4_result = - (test_structure_4 *) malloc (sizeof(test_structure_4)); - - ts4_type.size = 0; - ts4_type.alignment = 0; - ts4_type.type = FFI_TYPE_STRUCT; - ts4_type.elements = ts4_type_elements; - ts4_type_elements[0] = &ffi_type_uint; - ts4_type_elements[1] = &ffi_type_uint; - ts4_type_elements[2] = &ffi_type_uint; - ts4_type_elements[3] = NULL; - - args[0] = &ts4_type; - values[0] = &ts4_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts4_type, args) == FFI_OK); - - ts4_arg.ui1 = 2; - ts4_arg.ui2 = 3; - ts4_arg.ui3 = 4; - - ffi_call (&cif, FFI_FN(struct4), ts4_result, values); - - CHECK(ts4_result->ui3 == 2U * 3U * 4U); - - - free (ts4_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct5.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct5.c deleted file mode 100644 index 23e2a3f74..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct5.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -typedef struct -{ - char c1; - char c2; -} test_structure_5; - -static test_structure_5 ABI_ATTR struct5(test_structure_5 ts1, test_structure_5 ts2) -{ - ts1.c1 += ts2.c1; - ts1.c2 -= ts2.c2; - - return ts1; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts5_type; - ffi_type *ts5_type_elements[3]; - - test_structure_5 ts5_arg1, ts5_arg2; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_5 *ts5_result = - (test_structure_5 *) malloc (sizeof(test_structure_5)); - - ts5_type.size = 0; - ts5_type.alignment = 0; - ts5_type.type = FFI_TYPE_STRUCT; - ts5_type.elements = ts5_type_elements; - ts5_type_elements[0] = &ffi_type_schar; - ts5_type_elements[1] = &ffi_type_schar; - ts5_type_elements[2] = NULL; - - args[0] = &ts5_type; - args[1] = &ts5_type; - values[0] = &ts5_arg1; - values[1] = &ts5_arg2; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, &ts5_type, args) == FFI_OK); - - ts5_arg1.c1 = 2; - ts5_arg1.c2 = 6; - ts5_arg2.c1 = 5; - ts5_arg2.c2 = 3; - - ffi_call (&cif, FFI_FN(struct5), ts5_result, values); - - CHECK(ts5_result->c1 == 7); - CHECK(ts5_result->c2 == 3); - - - free (ts5_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct6.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct6.c deleted file mode 100644 index 173c66eb4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct6.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -typedef struct -{ - float f; - double d; -} test_structure_6; - -static test_structure_6 ABI_ATTR struct6 (test_structure_6 ts) -{ - ts.f += 1; - ts.d += 1; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts6_type; - ffi_type *ts6_type_elements[3]; - - test_structure_6 ts6_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_6 *ts6_result = - (test_structure_6 *) malloc (sizeof(test_structure_6)); - - ts6_type.size = 0; - ts6_type.alignment = 0; - ts6_type.type = FFI_TYPE_STRUCT; - ts6_type.elements = ts6_type_elements; - ts6_type_elements[0] = &ffi_type_float; - ts6_type_elements[1] = &ffi_type_double; - ts6_type_elements[2] = NULL; - - args[0] = &ts6_type; - values[0] = &ts6_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts6_type, args) == FFI_OK); - - ts6_arg.f = 5.55f; - ts6_arg.d = 6.66; - - printf ("%g\n", ts6_arg.f); - printf ("%g\n", ts6_arg.d); - - ffi_call(&cif, FFI_FN(struct6), ts6_result, values); - - CHECK(ts6_result->f == 5.55f + 1); - CHECK(ts6_result->d == 6.66 + 1); - - free (ts6_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct7.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct7.c deleted file mode 100644 index badc7e055..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct7.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -typedef struct -{ - float f1; - float f2; - double d; -} test_structure_7; - -static test_structure_7 ABI_ATTR struct7 (test_structure_7 ts) -{ - ts.f1 += 1; - ts.f2 += 1; - ts.d += 1; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts7_type; - ffi_type *ts7_type_elements[4]; - - test_structure_7 ts7_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_7 *ts7_result = - (test_structure_7 *) malloc (sizeof(test_structure_7)); - - ts7_type.size = 0; - ts7_type.alignment = 0; - ts7_type.type = FFI_TYPE_STRUCT; - ts7_type.elements = ts7_type_elements; - ts7_type_elements[0] = &ffi_type_float; - ts7_type_elements[1] = &ffi_type_float; - ts7_type_elements[2] = &ffi_type_double; - ts7_type_elements[3] = NULL; - - args[0] = &ts7_type; - values[0] = &ts7_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts7_type, args) == FFI_OK); - - ts7_arg.f1 = 5.55f; - ts7_arg.f2 = 55.5f; - ts7_arg.d = 6.66; - - printf ("%g\n", ts7_arg.f1); - printf ("%g\n", ts7_arg.f2); - printf ("%g\n", ts7_arg.d); - - ffi_call(&cif, FFI_FN(struct7), ts7_result, values); - - printf ("%g\n", ts7_result->f1); - printf ("%g\n", ts7_result->f2); - printf ("%g\n", ts7_result->d); - - CHECK(ts7_result->f1 == 5.55f + 1); - CHECK(ts7_result->f2 == 55.5f + 1); - CHECK(ts7_result->d == 6.66 + 1); - - free (ts7_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct8.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct8.c deleted file mode 100644 index ef204ecbb..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct8.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" -typedef struct -{ - float f1; - float f2; - float f3; - float f4; -} test_structure_8; - -static test_structure_8 ABI_ATTR struct8 (test_structure_8 ts) -{ - ts.f1 += 1; - ts.f2 += 1; - ts.f3 += 1; - ts.f4 += 1; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts8_type; - ffi_type *ts8_type_elements[5]; - - test_structure_8 ts8_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_8 *ts8_result = - (test_structure_8 *) malloc (sizeof(test_structure_8)); - - ts8_type.size = 0; - ts8_type.alignment = 0; - ts8_type.type = FFI_TYPE_STRUCT; - ts8_type.elements = ts8_type_elements; - ts8_type_elements[0] = &ffi_type_float; - ts8_type_elements[1] = &ffi_type_float; - ts8_type_elements[2] = &ffi_type_float; - ts8_type_elements[3] = &ffi_type_float; - ts8_type_elements[4] = NULL; - - args[0] = &ts8_type; - values[0] = &ts8_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts8_type, args) == FFI_OK); - - ts8_arg.f1 = 5.55f; - ts8_arg.f2 = 55.5f; - ts8_arg.f3 = -5.55f; - ts8_arg.f4 = -55.5f; - - printf ("%g\n", ts8_arg.f1); - printf ("%g\n", ts8_arg.f2); - printf ("%g\n", ts8_arg.f3); - printf ("%g\n", ts8_arg.f4); - - ffi_call(&cif, FFI_FN(struct8), ts8_result, values); - - printf ("%g\n", ts8_result->f1); - printf ("%g\n", ts8_result->f2); - printf ("%g\n", ts8_result->f3); - printf ("%g\n", ts8_result->f4); - - CHECK(ts8_result->f1 == 5.55f + 1); - CHECK(ts8_result->f2 == 55.5f + 1); - CHECK(ts8_result->f3 == -5.55f + 1); - CHECK(ts8_result->f4 == -55.5f + 1); - - free (ts8_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct9.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct9.c deleted file mode 100644 index 4a13b818c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/struct9.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Area: ffi_call - Purpose: Check structures. - Limitations: none. - PR: none. - Originator: From the original ffitest.c */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - float f; - int i; -} test_structure_9; - -static test_structure_9 ABI_ATTR struct9 (test_structure_9 ts) -{ - ts.f += 1; - ts.i += 1; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts9_type; - ffi_type *ts9_type_elements[3]; - - test_structure_9 ts9_arg; - - /* This is a hack to get a properly aligned result buffer */ - test_structure_9 *ts9_result = - (test_structure_9 *) malloc (sizeof(test_structure_9)); - - ts9_type.size = 0; - ts9_type.alignment = 0; - ts9_type.type = FFI_TYPE_STRUCT; - ts9_type.elements = ts9_type_elements; - ts9_type_elements[0] = &ffi_type_float; - ts9_type_elements[1] = &ffi_type_sint; - ts9_type_elements[2] = NULL; - - args[0] = &ts9_type; - values[0] = &ts9_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts9_type, args) == FFI_OK); - - ts9_arg.f = 5.55f; - ts9_arg.i = 5; - - printf ("%g\n", ts9_arg.f); - printf ("%d\n", ts9_arg.i); - - ffi_call(&cif, FFI_FN(struct9), ts9_result, values); - - printf ("%g\n", ts9_result->f); - printf ("%d\n", ts9_result->i); - - CHECK(ts9_result->f == 5.55f + 1); - CHECK(ts9_result->i == 5 + 1); - - free (ts9_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/testclosure.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/testclosure.c deleted file mode 100644 index ca31056d8..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/testclosure.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Area: closure_call - Purpose: Check return value float. - Limitations: none. - PR: 41908. - Originator: 20091102 */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct cls_struct_combined { - float a; - float b; - float c; - float d; -} cls_struct_combined; - -void cls_struct_combined_fn(struct cls_struct_combined arg) -{ - printf("%g %g %g %g\n", - arg.a, arg.b, - arg.c, arg.d); - fflush(stdout); -} - -static void -cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, - void** args, void* userdata __UNUSED__) -{ - struct cls_struct_combined a0; - - a0 = *(struct cls_struct_combined*)(args[0]); - - cls_struct_combined_fn(a0); -} - - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type* cls_struct_fields0[5]; - ffi_type cls_struct_type0; - ffi_type* dbl_arg_types[5]; - - struct cls_struct_combined g_dbl = {4.0, 5.0, 1.0, 8.0}; - - cls_struct_type0.size = 0; - cls_struct_type0.alignment = 0; - cls_struct_type0.type = FFI_TYPE_STRUCT; - cls_struct_type0.elements = cls_struct_fields0; - - cls_struct_fields0[0] = &ffi_type_float; - cls_struct_fields0[1] = &ffi_type_float; - cls_struct_fields0[2] = &ffi_type_float; - cls_struct_fields0[3] = &ffi_type_float; - cls_struct_fields0[4] = NULL; - - dbl_arg_types[0] = &cls_struct_type0; - dbl_arg_types[1] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_void, - dbl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK); - - ((void(*)(cls_struct_combined)) (code))(g_dbl); - /* { dg-output "4 5 1 8" } */ - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/uninitialized.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/uninitialized.c deleted file mode 100644 index f00d83023..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/uninitialized.c +++ /dev/null @@ -1,61 +0,0 @@ -/* { dg-do run } */ -#include "ffitest.h" - -typedef struct -{ - unsigned char uc; - double d; - unsigned int ui; -} test_structure_1; - -static test_structure_1 struct1(test_structure_1 ts) -{ - ts.uc++; - ts.d--; - ts.ui++; - - return ts; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_type ts1_type; - ffi_type *ts1_type_elements[4]; - - memset(&cif, 1, sizeof(cif)); - ts1_type.size = 0; - ts1_type.alignment = 0; - ts1_type.type = FFI_TYPE_STRUCT; - ts1_type.elements = ts1_type_elements; - ts1_type_elements[0] = &ffi_type_uchar; - ts1_type_elements[1] = &ffi_type_double; - ts1_type_elements[2] = &ffi_type_uint; - ts1_type_elements[3] = NULL; - - test_structure_1 ts1_arg; - /* This is a hack to get a properly aligned result buffer */ - test_structure_1 *ts1_result = - (test_structure_1 *) malloc (sizeof(test_structure_1)); - - args[0] = &ts1_type; - values[0] = &ts1_arg; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, - &ts1_type, args) == FFI_OK); - - ts1_arg.uc = '\x01'; - ts1_arg.d = 3.14159; - ts1_arg.ui = 555; - - ffi_call(&cif, FFI_FN(struct1), ts1_result, values); - - CHECK(ts1_result->ui == 556); - CHECK(ts1_result->d == 3.14159 - 1); - - free (ts1_result); - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest.cc b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest.cc deleted file mode 100644 index 67cfefeca..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* Area: ffi_closure, unwind info - Purpose: Check if the unwind information is passed correctly. - Limitations: none. - PR: none. - Originator: Jeff Sturm */ - -/* { dg-do run } */ - -#include "ffitest.h" - -void ABI_ATTR -closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, - void** args __UNUSED__, void* userdata __UNUSED__) -{ - throw 9; -} - -typedef void (*closure_test_type)(); - -void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, - void** args, void* userdata __UNUSED__) - { - *(ffi_arg*)resp = - (int)*(float *)args[0] +(int)(*(float *)args[1]) + - (int)(*(float *)args[2]) + (int)*(float *)args[3] + - (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) + - (int)*(float *)args[6] + (int)(*(int *)args[7]) + - (int)(*(double*)args[8]) + (int)*(int *)args[9] + - (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + - (int)*(int *)args[12] + (int)(*(int *)args[13]) + - (int)(*(int *)args[14]) + *(int *)args[15] + (int)(intptr_t)userdata; - - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", - (int)*(float *)args[0], (int)(*(float *)args[1]), - (int)(*(float *)args[2]), (int)*(float *)args[3], - (int)(*(signed short *)args[4]), (int)(*(float *)args[5]), - (int)*(float *)args[6], (int)(*(int *)args[7]), - (int)(*(double *)args[8]), (int)*(int *)args[9], - (int)(*(int *)args[10]), (int)(*(float *)args[11]), - (int)*(int *)args[12], (int)(*(int *)args[13]), - (int)(*(int *)args[14]), *(int *)args[15], - (int)(intptr_t)userdata, (int)*(ffi_arg*)resp); - - throw (int)*(ffi_arg*)resp; -} - -typedef int (*closure_test_type1)(float, float, float, float, signed short, - float, float, int, double, int, int, float, - int, int, int, int); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[17]; - - { - cl_arg_types[1] = NULL; - - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, - &ffi_type_void, cl_arg_types) == FFI_OK); - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn, NULL, code) == FFI_OK); - - try - { - (*((closure_test_type)(code)))(); - } catch (int exception_code) - { - CHECK(exception_code == 9); - } - - printf("part one OK\n"); - /* { dg-output "part one OK" } */ - } - - { - - cl_arg_types[0] = &ffi_type_float; - cl_arg_types[1] = &ffi_type_float; - cl_arg_types[2] = &ffi_type_float; - cl_arg_types[3] = &ffi_type_float; - cl_arg_types[4] = &ffi_type_sshort; - cl_arg_types[5] = &ffi_type_float; - cl_arg_types[6] = &ffi_type_float; - cl_arg_types[7] = &ffi_type_uint; - cl_arg_types[8] = &ffi_type_double; - cl_arg_types[9] = &ffi_type_uint; - cl_arg_types[10] = &ffi_type_uint; - cl_arg_types[11] = &ffi_type_float; - cl_arg_types[12] = &ffi_type_uint; - cl_arg_types[13] = &ffi_type_uint; - cl_arg_types[14] = &ffi_type_uint; - cl_arg_types[15] = &ffi_type_uint; - cl_arg_types[16] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, - &ffi_type_sint, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1, - (void *) 3 /* userdata */, code) == FFI_OK); - try - { - (*((closure_test_type1)code)) - (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13, - 19, 21, 1); - /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */ - } catch (int exception_code) - { - CHECK(exception_code == 255); - } - printf("part two OK\n"); - /* { dg-output "\npart two OK" } */ - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest_ffi_call.cc b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest_ffi_call.cc deleted file mode 100644 index ec611647e..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/unwindtest_ffi_call.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* Area: ffi_call, unwind info - Purpose: Check if the unwind information is passed correctly. - Limitations: none. - PR: none. - Originator: Andreas Tobler 20061213 */ - -/* { dg-do run } */ - -#include "ffitest.h" - -static int checking(int a __UNUSED__, short b __UNUSED__, - signed char c __UNUSED__) -{ - throw 9; -} - -int main (void) -{ - ffi_cif cif; - ffi_type *args[MAX_ARGS]; - void *values[MAX_ARGS]; - ffi_arg rint; - - signed int si; - signed short ss; - signed char sc; - - args[0] = &ffi_type_sint; - values[0] = &si; - args[1] = &ffi_type_sshort; - values[1] = &ss; - args[2] = &ffi_type_schar; - values[2] = ≻ - - /* Initialize the cif */ - CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, - &ffi_type_sint, args) == FFI_OK); - - si = -6; - ss = -12; - sc = -1; - { - try - { - ffi_call(&cif, FFI_FN(checking), &rint, values); - } catch (int exception_code) - { - CHECK(exception_code == 9); - } - printf("part one OK\n"); - /* { dg-output "part one OK" } */ - } - exit(0); -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_1.c deleted file mode 100644 index 7f96809ea..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_1.c +++ /dev/null @@ -1,196 +0,0 @@ -/* Area: ffi_call - Purpose: Test passing struct in variable argument lists. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ - -#include "ffitest.h" -#include - -struct small_tag -{ - unsigned char a; - unsigned char b; -}; - -struct large_tag -{ - unsigned a; - unsigned b; - unsigned c; - unsigned d; - unsigned e; -}; - -static int -test_fn (int n, ...) -{ - va_list ap; - struct small_tag s1; - struct small_tag s2; - struct large_tag l; - unsigned char uc; - signed char sc; - unsigned short us; - signed short ss; - unsigned int ui; - signed int si; - unsigned long ul; - signed long sl; - float f; - double d; - - va_start (ap, n); - s1 = va_arg (ap, struct small_tag); - l = va_arg (ap, struct large_tag); - s2 = va_arg (ap, struct small_tag); - - uc = va_arg (ap, unsigned); - sc = va_arg (ap, signed); - - us = va_arg (ap, unsigned); - ss = va_arg (ap, signed); - - ui = va_arg (ap, unsigned int); - si = va_arg (ap, signed int); - - ul = va_arg (ap, unsigned long); - sl = va_arg (ap, signed long); - - f = va_arg (ap, double); /* C standard promotes float->double - when anonymous */ - d = va_arg (ap, double); - - printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n", - s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, - s2.a, s2.b, - uc, sc, - us, ss, - ui, si, - ul, sl, - f, d); - va_end (ap); - return n + 1; -} - -int -main (void) -{ - ffi_cif cif; - void* args[15]; - ffi_type* arg_types[15]; - - ffi_type s_type; - ffi_type *s_type_elements[3]; - - ffi_type l_type; - ffi_type *l_type_elements[6]; - - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int n; - ffi_arg res; - - unsigned char uc; - signed char sc; - unsigned short us; - signed short ss; - unsigned int ui; - signed int si; - unsigned long ul; - signed long sl; - double d1; - double f1; - - s_type.size = 0; - s_type.alignment = 0; - s_type.type = FFI_TYPE_STRUCT; - s_type.elements = s_type_elements; - - s_type_elements[0] = &ffi_type_uchar; - s_type_elements[1] = &ffi_type_uchar; - s_type_elements[2] = NULL; - - l_type.size = 0; - l_type.alignment = 0; - l_type.type = FFI_TYPE_STRUCT; - l_type.elements = l_type_elements; - - l_type_elements[0] = &ffi_type_uint; - l_type_elements[1] = &ffi_type_uint; - l_type_elements[2] = &ffi_type_uint; - l_type_elements[3] = &ffi_type_uint; - l_type_elements[4] = &ffi_type_uint; - l_type_elements[5] = NULL; - - arg_types[0] = &ffi_type_sint; - arg_types[1] = &s_type; - arg_types[2] = &l_type; - arg_types[3] = &s_type; - arg_types[4] = &ffi_type_uchar; - arg_types[5] = &ffi_type_schar; - arg_types[6] = &ffi_type_ushort; - arg_types[7] = &ffi_type_sshort; - arg_types[8] = &ffi_type_uint; - arg_types[9] = &ffi_type_sint; - arg_types[10] = &ffi_type_ulong; - arg_types[11] = &ffi_type_slong; - arg_types[12] = &ffi_type_double; - arg_types[13] = &ffi_type_double; - arg_types[14] = NULL; - - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK); - - s1.a = 5; - s1.b = 6; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - s2.a = 7; - s2.b = 8; - - n = 41; - - uc = 9; - sc = 10; - us = 11; - ss = 12; - ui = 13; - si = 14; - ul = 15; - sl = 16; - f1 = 2.12; - d1 = 3.13; - - args[0] = &n; - args[1] = &s1; - args[2] = &l1; - args[3] = &s2; - args[4] = &uc; - args[5] = ≻ - args[6] = &us; - args[7] = &ss; - args[8] = &ui; - args[9] = &si; - args[10] = &ul; - args[11] = &sl; - args[12] = &f1; - args[13] = &d1; - args[14] = NULL; - - ffi_call(&cif, FFI_FN(test_fn), &res, args); - /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 42" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct1.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct1.c deleted file mode 100644 index e6452061c..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct1.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Area: ffi_call - Purpose: Test passing struct in variable argument lists. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ - -#include "ffitest.h" -#include - -struct small_tag -{ - unsigned char a; - unsigned char b; -}; - -struct large_tag -{ - unsigned a; - unsigned b; - unsigned c; - unsigned d; - unsigned e; -}; - -static int -test_fn (int n, ...) -{ - va_list ap; - struct small_tag s1; - struct small_tag s2; - struct large_tag l; - - va_start (ap, n); - s1 = va_arg (ap, struct small_tag); - l = va_arg (ap, struct large_tag); - s2 = va_arg (ap, struct small_tag); - printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, - s2.a, s2.b); - va_end (ap); - return n + 1; -} - -int -main (void) -{ - ffi_cif cif; - void* args[5]; - ffi_type* arg_types[5]; - - ffi_type s_type; - ffi_type *s_type_elements[3]; - - ffi_type l_type; - ffi_type *l_type_elements[6]; - - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int n; - ffi_arg res; - - s_type.size = 0; - s_type.alignment = 0; - s_type.type = FFI_TYPE_STRUCT; - s_type.elements = s_type_elements; - - s_type_elements[0] = &ffi_type_uchar; - s_type_elements[1] = &ffi_type_uchar; - s_type_elements[2] = NULL; - - l_type.size = 0; - l_type.alignment = 0; - l_type.type = FFI_TYPE_STRUCT; - l_type.elements = l_type_elements; - - l_type_elements[0] = &ffi_type_uint; - l_type_elements[1] = &ffi_type_uint; - l_type_elements[2] = &ffi_type_uint; - l_type_elements[3] = &ffi_type_uint; - l_type_elements[4] = &ffi_type_uint; - l_type_elements[5] = NULL; - - arg_types[0] = &ffi_type_sint; - arg_types[1] = &s_type; - arg_types[2] = &l_type; - arg_types[3] = &s_type; - arg_types[4] = NULL; - - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK); - - s1.a = 5; - s1.b = 6; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - s2.a = 7; - s2.b = 8; - - n = 41; - - args[0] = &n; - args[1] = &s1; - args[2] = &l1; - args[3] = &s2; - args[4] = NULL; - - ffi_call(&cif, FFI_FN(test_fn), &res, args); - /* { dg-output "5 6 10 11 12 13 14 7 8" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 42" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct2.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct2.c deleted file mode 100644 index 56f5b9c75..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct2.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Area: ffi_call - Purpose: Test passing struct in variable argument lists. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ - -#include "ffitest.h" -#include - -struct small_tag -{ - unsigned char a; - unsigned char b; -}; - -struct large_tag -{ - unsigned a; - unsigned b; - unsigned c; - unsigned d; - unsigned e; -}; - -static struct small_tag -test_fn (int n, ...) -{ - va_list ap; - struct small_tag s1; - struct small_tag s2; - struct large_tag l; - - va_start (ap, n); - s1 = va_arg (ap, struct small_tag); - l = va_arg (ap, struct large_tag); - s2 = va_arg (ap, struct small_tag); - printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, - s2.a, s2.b); - va_end (ap); - s1.a += s2.a; - s1.b += s2.b; - return s1; -} - -int -main (void) -{ - ffi_cif cif; - void* args[5]; - ffi_type* arg_types[5]; - - ffi_type s_type; - ffi_type *s_type_elements[3]; - - ffi_type l_type; - ffi_type *l_type_elements[6]; - - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int n; - struct small_tag res; - - s_type.size = 0; - s_type.alignment = 0; - s_type.type = FFI_TYPE_STRUCT; - s_type.elements = s_type_elements; - - s_type_elements[0] = &ffi_type_uchar; - s_type_elements[1] = &ffi_type_uchar; - s_type_elements[2] = NULL; - - l_type.size = 0; - l_type.alignment = 0; - l_type.type = FFI_TYPE_STRUCT; - l_type.elements = l_type_elements; - - l_type_elements[0] = &ffi_type_uint; - l_type_elements[1] = &ffi_type_uint; - l_type_elements[2] = &ffi_type_uint; - l_type_elements[3] = &ffi_type_uint; - l_type_elements[4] = &ffi_type_uint; - l_type_elements[5] = NULL; - - arg_types[0] = &ffi_type_sint; - arg_types[1] = &s_type; - arg_types[2] = &l_type; - arg_types[3] = &s_type; - arg_types[4] = NULL; - - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK); - - s1.a = 5; - s1.b = 6; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - s2.a = 7; - s2.b = 8; - - n = 41; - - args[0] = &n; - args[1] = &s1; - args[2] = &l1; - args[3] = &s2; - args[4] = NULL; - - ffi_call(&cif, FFI_FN(test_fn), &res, args); - /* { dg-output "5 6 10 11 12 13 14 7 8" } */ - printf("res: %d %d\n", res.a, res.b); - /* { dg-output "\nres: 12 14" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct3.c b/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct3.c deleted file mode 100644 index 9a27e7fd4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/testsuite/libffi.call/va_struct3.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Area: ffi_call - Purpose: Test passing struct in variable argument lists. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ - -#include "ffitest.h" -#include - -struct small_tag -{ - unsigned char a; - unsigned char b; -}; - -struct large_tag -{ - unsigned a; - unsigned b; - unsigned c; - unsigned d; - unsigned e; -}; - -static struct large_tag -test_fn (int n, ...) -{ - va_list ap; - struct small_tag s1; - struct small_tag s2; - struct large_tag l; - - va_start (ap, n); - s1 = va_arg (ap, struct small_tag); - l = va_arg (ap, struct large_tag); - s2 = va_arg (ap, struct small_tag); - printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, - s2.a, s2.b); - va_end (ap); - l.a += s1.a; - l.b += s1.b; - l.c += s2.a; - l.d += s2.b; - return l; -} - -int -main (void) -{ - ffi_cif cif; - void* args[5]; - ffi_type* arg_types[5]; - - ffi_type s_type; - ffi_type *s_type_elements[3]; - - ffi_type l_type; - ffi_type *l_type_elements[6]; - - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int n; - struct large_tag res; - - s_type.size = 0; - s_type.alignment = 0; - s_type.type = FFI_TYPE_STRUCT; - s_type.elements = s_type_elements; - - s_type_elements[0] = &ffi_type_uchar; - s_type_elements[1] = &ffi_type_uchar; - s_type_elements[2] = NULL; - - l_type.size = 0; - l_type.alignment = 0; - l_type.type = FFI_TYPE_STRUCT; - l_type.elements = l_type_elements; - - l_type_elements[0] = &ffi_type_uint; - l_type_elements[1] = &ffi_type_uint; - l_type_elements[2] = &ffi_type_uint; - l_type_elements[3] = &ffi_type_uint; - l_type_elements[4] = &ffi_type_uint; - l_type_elements[5] = NULL; - - arg_types[0] = &ffi_type_sint; - arg_types[1] = &s_type; - arg_types[2] = &l_type; - arg_types[3] = &s_type; - arg_types[4] = NULL; - - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK); - - s1.a = 5; - s1.b = 6; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - s2.a = 7; - s2.b = 8; - - n = 41; - - args[0] = &n; - args[1] = &s1; - args[2] = &l1; - args[3] = &s2; - args[4] = NULL; - - ffi_call(&cif, FFI_FN(test_fn), &res, args); - /* { dg-output "5 6 10 11 12 13 14 7 8" } */ - printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e); - /* { dg-output "\nres: 15 17 19 21 14" } */ - - return 0; -} diff --git a/ruby/ext/fiddle/libffi-3.2.1/texinfo.tex b/ruby/ext/fiddle/libffi-3.2.1/texinfo.tex deleted file mode 100644 index 85f184cc4..000000000 --- a/ruby/ext/fiddle/libffi-3.2.1/texinfo.tex +++ /dev/null @@ -1,10079 +0,0 @@ -% texinfo.tex -- TeX macros to handle Texinfo files. -% -% Load plain if necessary, i.e., if running under initex. -\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi -% -\def\texinfoversion{2013-02-01.11} -% -% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, -% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -% 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. -% -% This texinfo.tex file is free software: you can redistribute it and/or -% modify it under the terms of the GNU General Public License as -% published by the Free Software Foundation, either version 3 of the -% License, or (at your option) any later version. -% -% This texinfo.tex file is distributed in the hope that it will be -% useful, but WITHOUT ANY WARRANTY; without even the implied warranty -% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -% General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program. If not, see . -% -% As a special exception, when this file is read by TeX when processing -% a Texinfo source document, you may use the result without -% restriction. This Exception is an additional permission under section 7 -% of the GNU General Public License, version 3 ("GPLv3"). -% -% Please try the latest version of texinfo.tex before submitting bug -% reports; you can get the latest version from: -% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or -% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or -% http://www.gnu.org/software/texinfo/ (the Texinfo home page) -% The texinfo.tex in any given distribution could well be out -% of date, so if that's what you're using, please check. -% -% Send bug reports to bug-texinfo@gnu.org. Please include including a -% complete document in each bug report with which we can reproduce the -% problem. Patches are, of course, greatly appreciated. -% -% To process a Texinfo manual with TeX, it's most reliable to use the -% texi2dvi shell script that comes with the distribution. For a simple -% manual foo.texi, however, you can get away with this: -% tex foo.texi -% texindex foo.?? -% tex foo.texi -% tex foo.texi -% dvips foo.dvi -o # or whatever; this makes foo.ps. -% The extra TeX runs get the cross-reference information correct. -% Sometimes one run after texindex suffices, and sometimes you need more -% than two; texi2dvi does it as many times as necessary. -% -% It is possible to adapt texinfo.tex for other languages, to some -% extent. You can get the existing language-specific files from the -% full Texinfo distribution. -% -% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. - - -\message{Loading texinfo [version \texinfoversion]:} - -% If in a .fmt file, print the version number -% and turn on active characters that we couldn't do earlier because -% they might have appeared in the input file name. -\everyjob{\message{[Texinfo version \texinfoversion]}% - \catcode`+=\active \catcode`\_=\active} - -\chardef\other=12 - -% We never want plain's \outer definition of \+ in Texinfo. -% For @tex, we can use \tabalign. -\let\+ = \relax - -% Save some plain tex macros whose names we will redefine. -\let\ptexb=\b -\let\ptexbullet=\bullet -\let\ptexc=\c -\let\ptexcomma=\, -\let\ptexdot=\. -\let\ptexdots=\dots -\let\ptexend=\end -\let\ptexequiv=\equiv -\let\ptexexclam=\! -\let\ptexfootnote=\footnote -\let\ptexgtr=> -\let\ptexhat=^ -\let\ptexi=\i -\let\ptexindent=\indent -\let\ptexinsert=\insert -\let\ptexlbrace=\{ -\let\ptexless=< -\let\ptexnewwrite\newwrite -\let\ptexnoindent=\noindent -\let\ptexplus=+ -\let\ptexraggedright=\raggedright -\let\ptexrbrace=\} -\let\ptexslash=\/ -\let\ptexstar=\* -\let\ptext=\t -\let\ptextop=\top -{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode - -% If this character appears in an error message or help string, it -% starts a new line in the output. -\newlinechar = `^^J - -% Use TeX 3.0's \inputlineno to get the line number, for better error -% messages, but if we're using an old version of TeX, don't do anything. -% -\ifx\inputlineno\thisisundefined - \let\linenumber = \empty % Pre-3.0. -\else - \def\linenumber{l.\the\inputlineno:\space} -\fi - -% Set up fixed words for English if not already set. -\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi -\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi -\ifx\putworderror\undefined \gdef\putworderror{error}\fi -\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi -\ifx\putwordin\undefined \gdef\putwordin{in}\fi -\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi -\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi -\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi -\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi -\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi -\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi -\ifx\putwordof\undefined \gdef\putwordof{of}\fi -\ifx\putwordon\undefined \gdef\putwordon{on}\fi -\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi -\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi -\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi -\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi -\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi -\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi -\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi -% -\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi -\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi -\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi -\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi -\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi -\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi -\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi -\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi -\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi -\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi -\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi -\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi -% -\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi -\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi -\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi -\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi -\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi - -% Since the category of space is not known, we have to be careful. -\chardef\spacecat = 10 -\def\spaceisspace{\catcode`\ =\spacecat} - -% sometimes characters are active, so we need control sequences. -\chardef\ampChar = `\& -\chardef\colonChar = `\: -\chardef\commaChar = `\, -\chardef\dashChar = `\- -\chardef\dotChar = `\. -\chardef\exclamChar= `\! -\chardef\hashChar = `\# -\chardef\lquoteChar= `\` -\chardef\questChar = `\? -\chardef\rquoteChar= `\' -\chardef\semiChar = `\; -\chardef\slashChar = `\/ -\chardef\underChar = `\_ - -% Ignore a token. -% -\def\gobble#1{} - -% The following is used inside several \edef's. -\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} - -% Hyphenation fixes. -\hyphenation{ - Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script - ap-pen-dix bit-map bit-maps - data-base data-bases eshell fall-ing half-way long-est man-u-script - man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm - par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces - spell-ing spell-ings - stand-alone strong-est time-stamp time-stamps which-ever white-space - wide-spread wrap-around -} - -% Margin to add to right of even pages, to left of odd pages. -\newdimen\bindingoffset -\newdimen\normaloffset -\newdimen\pagewidth \newdimen\pageheight - -% For a final copy, take out the rectangles -% that mark overfull boxes (in case you have decided -% that the text looks ok even though it passes the margin). -% -\def\finalout{\overfullrule=0pt } - -% Sometimes it is convenient to have everything in the transcript file -% and nothing on the terminal. We don't just call \tracingall here, -% since that produces some useless output on the terminal. We also make -% some effort to order the tracing commands to reduce output in the log -% file; cf. trace.sty in LaTeX. -% -\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% -\def\loggingall{% - \tracingstats2 - \tracingpages1 - \tracinglostchars2 % 2 gives us more in etex - \tracingparagraphs1 - \tracingoutput1 - \tracingmacros2 - \tracingrestores1 - \showboxbreadth\maxdimen \showboxdepth\maxdimen - \ifx\eTeXversion\thisisundefined\else % etex gives us more logging - \tracingscantokens1 - \tracingifs1 - \tracinggroups1 - \tracingnesting2 - \tracingassigns1 - \fi - \tracingcommands3 % 3 gives us more in etex - \errorcontextlines16 -}% - -% @errormsg{MSG}. Do the index-like expansions on MSG, but if things -% aren't perfect, it's not the end of the world, being an error message, -% after all. -% -\def\errormsg{\begingroup \indexnofonts \doerrormsg} -\def\doerrormsg#1{\errmessage{#1}} - -% add check for \lastpenalty to plain's definitions. If the last thing -% we did was a \nobreak, we don't want to insert more space. -% -\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount - \removelastskip\penalty-50\smallskip\fi\fi} -\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount - \removelastskip\penalty-100\medskip\fi\fi} -\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount - \removelastskip\penalty-200\bigskip\fi\fi} - -% Do @cropmarks to get crop marks. -% -\newif\ifcropmarks -\let\cropmarks = \cropmarkstrue -% -% Dimensions to add cropmarks at corners. -% Added by P. A. MacKay, 12 Nov. 1986 -% -\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines -\newdimen\cornerlong \cornerlong=1pc -\newdimen\cornerthick \cornerthick=.3pt -\newdimen\topandbottommargin \topandbottommargin=.75in - -% Output a mark which sets \thischapter, \thissection and \thiscolor. -% We dump everything together because we only have one kind of mark. -% This works because we only use \botmark / \topmark, not \firstmark. -% -% A mark contains a subexpression of the \ifcase ... \fi construct. -% \get*marks macros below extract the needed part using \ifcase. -% -% Another complication is to let the user choose whether \thischapter -% (\thissection) refers to the chapter (section) in effect at the top -% of a page, or that at the bottom of a page. The solution is -% described on page 260 of The TeXbook. It involves outputting two -% marks for the sectioning macros, one before the section break, and -% one after. I won't pretend I can describe this better than DEK... -\def\domark{% - \toks0=\expandafter{\lastchapterdefs}% - \toks2=\expandafter{\lastsectiondefs}% - \toks4=\expandafter{\prevchapterdefs}% - \toks6=\expandafter{\prevsectiondefs}% - \toks8=\expandafter{\lastcolordefs}% - \mark{% - \the\toks0 \the\toks2 - \noexpand\or \the\toks4 \the\toks6 - \noexpand\else \the\toks8 - }% -} -% \topmark doesn't work for the very first chapter (after the title -% page or the contents), so we use \firstmark there -- this gets us -% the mark with the chapter defs, unless the user sneaks in, e.g., -% @setcolor (or @url, or @link, etc.) between @contents and the very -% first @chapter. -\def\gettopheadingmarks{% - \ifcase0\topmark\fi - \ifx\thischapter\empty \ifcase0\firstmark\fi \fi -} -\def\getbottomheadingmarks{\ifcase1\botmark\fi} -\def\getcolormarks{\ifcase2\topmark\fi} - -% Avoid "undefined control sequence" errors. -\def\lastchapterdefs{} -\def\lastsectiondefs{} -\def\prevchapterdefs{} -\def\prevsectiondefs{} -\def\lastcolordefs{} - -% Main output routine. -\chardef\PAGE = 255 -\output = {\onepageout{\pagecontents\PAGE}} - -\newbox\headlinebox -\newbox\footlinebox - -% \onepageout takes a vbox as an argument. Note that \pagecontents -% does insertions, but you have to call it yourself. -\def\onepageout#1{% - \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi - % - \ifodd\pageno \advance\hoffset by \bindingoffset - \else \advance\hoffset by -\bindingoffset\fi - % - % Do this outside of the \shipout so @code etc. will be expanded in - % the headline as they should be, not taken literally (outputting ''code). - \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi - \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% - \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi - \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% - % - {% - % Have to do this stuff outside the \shipout because we want it to - % take effect in \write's, yet the group defined by the \vbox ends - % before the \shipout runs. - % - \indexdummies % don't expand commands in the output. - \normalturnoffactive % \ in index entries must not stay \, e.g., if - % the page break happens to be in the middle of an example. - % We don't want .vr (or whatever) entries like this: - % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} - % "\acronym" won't work when it's read back in; - % it needs to be - % {\code {{\tt \backslashcurfont }acronym} - \shipout\vbox{% - % Do this early so pdf references go to the beginning of the page. - \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi - % - \ifcropmarks \vbox to \outervsize\bgroup - \hsize = \outerhsize - \vskip-\topandbottommargin - \vtop to0pt{% - \line{\ewtop\hfil\ewtop}% - \nointerlineskip - \line{% - \vbox{\moveleft\cornerthick\nstop}% - \hfill - \vbox{\moveright\cornerthick\nstop}% - }% - \vss}% - \vskip\topandbottommargin - \line\bgroup - \hfil % center the page within the outer (page) hsize. - \ifodd\pageno\hskip\bindingoffset\fi - \vbox\bgroup - \fi - % - \unvbox\headlinebox - \pagebody{#1}% - \ifdim\ht\footlinebox > 0pt - % Only leave this space if the footline is nonempty. - % (We lessened \vsize for it in \oddfootingyyy.) - % The \baselineskip=24pt in plain's \makefootline has no effect. - \vskip 24pt - \unvbox\footlinebox - \fi - % - \ifcropmarks - \egroup % end of \vbox\bgroup - \hfil\egroup % end of (centering) \line\bgroup - \vskip\topandbottommargin plus1fill minus1fill - \boxmaxdepth = \cornerthick - \vbox to0pt{\vss - \line{% - \vbox{\moveleft\cornerthick\nsbot}% - \hfill - \vbox{\moveright\cornerthick\nsbot}% - }% - \nointerlineskip - \line{\ewbot\hfil\ewbot}% - }% - \egroup % \vbox from first cropmarks clause - \fi - }% end of \shipout\vbox - }% end of group with \indexdummies - \advancepageno - \ifnum\outputpenalty>-20000 \else\dosupereject\fi -} - -\newinsert\margin \dimen\margin=\maxdimen - -\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} -{\catcode`\@ =11 -\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi -% marginal hacks, juha@viisa.uucp (Juha Takala) -\ifvoid\margin\else % marginal info is present - \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi -\dimen@=\dp#1\relax \unvbox#1\relax -\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi -\ifr@ggedbottom \kern-\dimen@ \vfil \fi} -} - -% Here are the rules for the cropmarks. Note that they are -% offset so that the space between them is truly \outerhsize or \outervsize -% (P. A. MacKay, 12 November, 1986) -% -\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} -\def\nstop{\vbox - {\hrule height\cornerthick depth\cornerlong width\cornerthick}} -\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} -\def\nsbot{\vbox - {\hrule height\cornerlong depth\cornerthick width\cornerthick}} - -% Parse an argument, then pass it to #1. The argument is the rest of -% the input line (except we remove a trailing comment). #1 should be a -% macro which expects an ordinary undelimited TeX argument. -% -\def\parsearg{\parseargusing{}} -\def\parseargusing#1#2{% - \def\argtorun{#2}% - \begingroup - \obeylines - \spaceisspace - #1% - \parseargline\empty% Insert the \empty token, see \finishparsearg below. -} - -{\obeylines % - \gdef\parseargline#1^^M{% - \endgroup % End of the group started in \parsearg. - \argremovecomment #1\comment\ArgTerm% - }% -} - -% First remove any @comment, then any @c comment. -\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} -\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} - -% Each occurrence of `\^^M' or `\^^M' is replaced by a single space. -% -% \argremovec might leave us with trailing space, e.g., -% @end itemize @c foo -% This space token undergoes the same procedure and is eventually removed -% by \finishparsearg. -% -\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} -\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} -\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% - \def\temp{#3}% - \ifx\temp\empty - % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: - \let\temp\finishparsearg - \else - \let\temp\argcheckspaces - \fi - % Put the space token in: - \temp#1 #3\ArgTerm -} - -% If a _delimited_ argument is enclosed in braces, they get stripped; so -% to get _exactly_ the rest of the line, we had to prevent such situation. -% We prepended an \empty token at the very beginning and we expand it now, -% just before passing the control to \argtorun. -% (Similarly, we have to think about #3 of \argcheckspacesY above: it is -% either the null string, or it ends with \^^M---thus there is no danger -% that a pair of braces would be stripped. -% -% But first, we have to remove the trailing space token. -% -\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} - -% \parseargdef\foo{...} -% is roughly equivalent to -% \def\foo{\parsearg\Xfoo} -% \def\Xfoo#1{...} -% -% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my -% favourite TeX trick. --kasal, 16nov03 - -\def\parseargdef#1{% - \expandafter \doparseargdef \csname\string#1\endcsname #1% -} -\def\doparseargdef#1#2{% - \def#2{\parsearg#1}% - \def#1##1% -} - -% Several utility definitions with active space: -{ - \obeyspaces - \gdef\obeyedspace{ } - - % Make each space character in the input produce a normal interword - % space in the output. Don't allow a line break at this space, as this - % is used only in environments like @example, where each line of input - % should produce a line of output anyway. - % - \gdef\sepspaces{\obeyspaces\let =\tie} - - % If an index command is used in an @example environment, any spaces - % therein should become regular spaces in the raw index file, not the - % expansion of \tie (\leavevmode \penalty \@M \ ). - \gdef\unsepspaces{\let =\space} -} - - -\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} - -% Define the framework for environments in texinfo.tex. It's used like this: -% -% \envdef\foo{...} -% \def\Efoo{...} -% -% It's the responsibility of \envdef to insert \begingroup before the -% actual body; @end closes the group after calling \Efoo. \envdef also -% defines \thisenv, so the current environment is known; @end checks -% whether the environment name matches. The \checkenv macro can also be -% used to check whether the current environment is the one expected. -% -% Non-false conditionals (@iftex, @ifset) don't fit into this, so they -% are not treated as environments; they don't open a group. (The -% implementation of @end takes care not to call \endgroup in this -% special case.) - - -% At run-time, environments start with this: -\def\startenvironment#1{\begingroup\def\thisenv{#1}} -% initialize -\let\thisenv\empty - -% ... but they get defined via ``\envdef\foo{...}'': -\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} -\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} - -% Check whether we're in the right environment: -\def\checkenv#1{% - \def\temp{#1}% - \ifx\thisenv\temp - \else - \badenverr - \fi -} - -% Environment mismatch, #1 expected: -\def\badenverr{% - \errhelp = \EMsimple - \errmessage{This command can appear only \inenvironment\temp, - not \inenvironment\thisenv}% -} -\def\inenvironment#1{% - \ifx#1\empty - outside of any environment% - \else - in environment \expandafter\string#1% - \fi -} - -% @end foo executes the definition of \Efoo. -% But first, it executes a specialized version of \checkenv -% -\parseargdef\end{% - \if 1\csname iscond.#1\endcsname - \else - % The general wording of \badenverr may not be ideal. - \expandafter\checkenv\csname#1\endcsname - \csname E#1\endcsname - \endgroup - \fi -} - -\newhelp\EMsimple{Press RETURN to continue.} - - -% Be sure we're in horizontal mode when doing a tie, since we make space -% equivalent to this in @example-like environments. Otherwise, a space -% at the beginning of a line will start with \penalty -- and -% since \penalty is valid in vertical mode, we'd end up putting the -% penalty on the vertical list instead of in the new paragraph. -{\catcode`@ = 11 - % Avoid using \@M directly, because that causes trouble - % if the definition is written into an index file. - \global\let\tiepenalty = \@M - \gdef\tie{\leavevmode\penalty\tiepenalty\ } -} - -% @: forces normal size whitespace following. -\def\:{\spacefactor=1000 } - -% @* forces a line break. -\def\*{\unskip\hfil\break\hbox{}\ignorespaces} - -% @/ allows a line break. -\let\/=\allowbreak - -% @. is an end-of-sentence period. -\def\.{.\spacefactor=\endofsentencespacefactor\space} - -% @! is an end-of-sentence bang. -\def\!{!\spacefactor=\endofsentencespacefactor\space} - -% @? is an end-of-sentence query. -\def\?{?\spacefactor=\endofsentencespacefactor\space} - -% @frenchspacing on|off says whether to put extra space after punctuation. -% -\def\onword{on} -\def\offword{off} -% -\parseargdef\frenchspacing{% - \def\temp{#1}% - \ifx\temp\onword \plainfrenchspacing - \else\ifx\temp\offword \plainnonfrenchspacing - \else - \errhelp = \EMsimple - \errmessage{Unknown @frenchspacing option `\temp', must be on|off}% - \fi\fi -} - -% @w prevents a word break. Without the \leavevmode, @w at the -% beginning of a paragraph, when TeX is still in vertical mode, would -% produce a whole line of output instead of starting the paragraph. -\def\w#1{\leavevmode\hbox{#1}} - -% @group ... @end group forces ... to be all on one page, by enclosing -% it in a TeX vbox. We use \vtop instead of \vbox to construct the box -% to keep its height that of a normal line. According to the rules for -% \topskip (p.114 of the TeXbook), the glue inserted is -% max (\topskip - \ht (first item), 0). If that height is large, -% therefore, no glue is inserted, and the space between the headline and -% the text is small, which looks bad. -% -% Another complication is that the group might be very large. This can -% cause the glue on the previous page to be unduly stretched, because it -% does not have much material. In this case, it's better to add an -% explicit \vfill so that the extra space is at the bottom. The -% threshold for doing this is if the group is more than \vfilllimit -% percent of a page (\vfilllimit can be changed inside of @tex). -% -\newbox\groupbox -\def\vfilllimit{0.7} -% -\envdef\group{% - \ifnum\catcode`\^^M=\active \else - \errhelp = \groupinvalidhelp - \errmessage{@group invalid in context where filling is enabled}% - \fi - \startsavinginserts - % - \setbox\groupbox = \vtop\bgroup - % Do @comment since we are called inside an environment such as - % @example, where each end-of-line in the input causes an - % end-of-line in the output. We don't want the end-of-line after - % the `@group' to put extra space in the output. Since @group - % should appear on a line by itself (according to the Texinfo - % manual), we don't worry about eating any user text. - \comment -} -% -% The \vtop produces a box with normal height and large depth; thus, TeX puts -% \baselineskip glue before it, and (when the next line of text is done) -% \lineskip glue after it. Thus, space below is not quite equal to space -% above. But it's pretty close. -\def\Egroup{% - % To get correct interline space between the last line of the group - % and the first line afterwards, we have to propagate \prevdepth. - \endgraf % Not \par, as it may have been set to \lisppar. - \global\dimen1 = \prevdepth - \egroup % End the \vtop. - % \dimen0 is the vertical size of the group's box. - \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox - % \dimen2 is how much space is left on the page (more or less). - \dimen2 = \pageheight \advance\dimen2 by -\pagetotal - % if the group doesn't fit on the current page, and it's a big big - % group, force a page break. - \ifdim \dimen0 > \dimen2 - \ifdim \pagetotal < \vfilllimit\pageheight - \page - \fi - \fi - \box\groupbox - \prevdepth = \dimen1 - \checkinserts -} -% -% TeX puts in an \escapechar (i.e., `@') at the beginning of the help -% message, so this ends up printing `@group can only ...'. -% -\newhelp\groupinvalidhelp{% -group can only be used in environments such as @example,^^J% -where each line of input produces a line of output.} - -% @need space-in-mils -% forces a page break if there is not space-in-mils remaining. - -\newdimen\mil \mil=0.001in - -\parseargdef\need{% - % Ensure vertical mode, so we don't make a big box in the middle of a - % paragraph. - \par - % - % If the @need value is less than one line space, it's useless. - \dimen0 = #1\mil - \dimen2 = \ht\strutbox - \advance\dimen2 by \dp\strutbox - \ifdim\dimen0 > \dimen2 - % - % Do a \strut just to make the height of this box be normal, so the - % normal leading is inserted relative to the preceding line. - % And a page break here is fine. - \vtop to #1\mil{\strut\vfil}% - % - % TeX does not even consider page breaks if a penalty added to the - % main vertical list is 10000 or more. But in order to see if the - % empty box we just added fits on the page, we must make it consider - % page breaks. On the other hand, we don't want to actually break the - % page after the empty box. So we use a penalty of 9999. - % - % There is an extremely small chance that TeX will actually break the - % page at this \penalty, if there are no other feasible breakpoints in - % sight. (If the user is using lots of big @group commands, which - % almost-but-not-quite fill up a page, TeX will have a hard time doing - % good page breaking, for example.) However, I could not construct an - % example where a page broke at this \penalty; if it happens in a real - % document, then we can reconsider our strategy. - \penalty9999 - % - % Back up by the size of the box, whether we did a page break or not. - \kern -#1\mil - % - % Do not allow a page break right after this kern. - \nobreak - \fi -} - -% @br forces paragraph break (and is undocumented). - -\let\br = \par - -% @page forces the start of a new page. -% -\def\page{\par\vfill\supereject} - -% @exdent text.... -% outputs text on separate line in roman font, starting at standard page margin - -% This records the amount of indent in the innermost environment. -% That's how much \exdent should take out. -\newskip\exdentamount - -% This defn is used inside fill environments such as @defun. -\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} - -% This defn is used inside nofill environments such as @example. -\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount - \leftline{\hskip\leftskip{\rm#1}}}} - -% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current -% paragraph. For more general purposes, use the \margin insertion -% class. WHICH is `l' or `r'. Not documented, written for gawk manual. -% -\newskip\inmarginspacing \inmarginspacing=1cm -\def\strutdepth{\dp\strutbox} -% -\def\doinmargin#1#2{\strut\vadjust{% - \nobreak - \kern-\strutdepth - \vtop to \strutdepth{% - \baselineskip=\strutdepth - \vss - % if you have multiple lines of stuff to put here, you'll need to - % make the vbox yourself of the appropriate size. - \ifx#1l% - \llap{\ignorespaces #2\hskip\inmarginspacing}% - \else - \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% - \fi - \null - }% -}} -\def\inleftmargin{\doinmargin l} -\def\inrightmargin{\doinmargin r} -% -% @inmargin{TEXT [, RIGHT-TEXT]} -% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; -% else use TEXT for both). -% -\def\inmargin#1{\parseinmargin #1,,\finish} -\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \def\lefttext{#1}% have both texts - \def\righttext{#2}% - \else - \def\lefttext{#1}% have only one text - \def\righttext{#1}% - \fi - % - \ifodd\pageno - \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin - \else - \def\temp{\inleftmargin\lefttext}% - \fi - \temp -} - -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). This command -% is not documented, not supported, and doesn't work. -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% -} - -% @include FILE -- \input text of FILE. -% -\def\include{\parseargusing\filenamecatcodes\includezzz} -\def\includezzz#1{% - \pushthisfilestack - \def\thisfile{#1}% - {% - \makevalueexpandable % we want to expand any @value in FILE. - \turnoffactive % and allow special characters in the expansion - \indexnofonts % Allow `@@' and other weird things in file names. - \wlog{texinfo.tex: doing @include of #1^^J}% - \edef\temp{\noexpand\input #1 }% - % - % This trickery is to read FILE outside of a group, in case it makes - % definitions, etc. - \expandafter - }\temp - \popthisfilestack -} -\def\filenamecatcodes{% - \catcode`\\=\other - \catcode`~=\other - \catcode`^=\other - \catcode`_=\other - \catcode`|=\other - \catcode`<=\other - \catcode`>=\other - \catcode`+=\other - \catcode`-=\other - \catcode`\`=\other - \catcode`\'=\other -} - -\def\pushthisfilestack{% - \expandafter\pushthisfilestackX\popthisfilestack\StackTerm -} -\def\pushthisfilestackX{% - \expandafter\pushthisfilestackY\thisfile\StackTerm -} -\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% - \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% -} - -\def\popthisfilestack{\errthisfilestackempty} -\def\errthisfilestackempty{\errmessage{Internal error: - the stack of filenames is empty.}} -% -\def\thisfile{} - -% @center line -% outputs that line, centered. -% -\parseargdef\center{% - \ifhmode - \let\centersub\centerH - \else - \let\centersub\centerV - \fi - \centersub{\hfil \ignorespaces#1\unskip \hfil}% - \let\centersub\relax % don't let the definition persist, just in case -} -\def\centerH#1{{% - \hfil\break - \advance\hsize by -\leftskip - \advance\hsize by -\rightskip - \line{#1}% - \break -}} -% -\newcount\centerpenalty -\def\centerV#1{% - % The idea here is the same as in \startdefun, \cartouche, etc.: if - % @center is the first thing after a section heading, we need to wipe - % out the negative parskip inserted by \sectionheading, but still - % prevent a page break here. - \centerpenalty = \lastpenalty - \ifnum\centerpenalty>10000 \vskip\parskip \fi - \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi - \line{\kern\leftskip #1\kern\rightskip}% -} - -% @sp n outputs n lines of vertical space -% -\parseargdef\sp{\vskip #1\baselineskip} - -% @comment ...line which is ignored... -% @c is the same as @comment -% @ignore ... @end ignore is another way to write a comment -% -\def\comment{\begingroup \catcode`\^^M=\other% -\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% -\commentxxx} -{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} -% -\let\c=\comment - -% @paragraphindent NCHARS -% We'll use ems for NCHARS, close enough. -% NCHARS can also be the word `asis' or `none'. -% We cannot feasibly implement @paragraphindent asis, though. -% -\def\asisword{asis} % no translation, these are keywords -\def\noneword{none} -% -\parseargdef\paragraphindent{% - \def\temp{#1}% - \ifx\temp\asisword - \else - \ifx\temp\noneword - \defaultparindent = 0pt - \else - \defaultparindent = #1em - \fi - \fi - \parindent = \defaultparindent -} - -% @exampleindent NCHARS -% We'll use ems for NCHARS like @paragraphindent. -% It seems @exampleindent asis isn't necessary, but -% I preserve it to make it similar to @paragraphindent. -\parseargdef\exampleindent{% - \def\temp{#1}% - \ifx\temp\asisword - \else - \ifx\temp\noneword - \lispnarrowing = 0pt - \else - \lispnarrowing = #1em - \fi - \fi -} - -% @firstparagraphindent WORD -% If WORD is `none', then suppress indentation of the first paragraph -% after a section heading. If WORD is `insert', then do indent at such -% paragraphs. -% -% The paragraph indentation is suppressed or not by calling -% \suppressfirstparagraphindent, which the sectioning commands do. -% We switch the definition of this back and forth according to WORD. -% By default, we suppress indentation. -% -\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} -\def\insertword{insert} -% -\parseargdef\firstparagraphindent{% - \def\temp{#1}% - \ifx\temp\noneword - \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent - \else\ifx\temp\insertword - \let\suppressfirstparagraphindent = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @firstparagraphindent option `\temp'}% - \fi\fi -} - -% Here is how we actually suppress indentation. Redefine \everypar to -% \kern backwards by \parindent, and then reset itself to empty. -% -% We also make \indent itself not actually do anything until the next -% paragraph. -% -\gdef\dosuppressfirstparagraphindent{% - \gdef\indent{% - \restorefirstparagraphindent - \indent - }% - \gdef\noindent{% - \restorefirstparagraphindent - \noindent - }% - \global\everypar = {% - \kern -\parindent - \restorefirstparagraphindent - }% -} - -\gdef\restorefirstparagraphindent{% - \global \let \indent = \ptexindent - \global \let \noindent = \ptexnoindent - \global \everypar = {}% -} - - -% @refill is a no-op. -\let\refill=\relax - -% If working on a large document in chapters, it is convenient to -% be able to disable indexing, cross-referencing, and contents, for test runs. -% This is done with @novalidate (before @setfilename). -% -\newif\iflinks \linkstrue % by default we want the aux files. -\let\novalidate = \linksfalse - -% @setfilename is done at the beginning of every texinfo file. -% So open here the files we need to have open while reading the input. -% This makes it possible to make a .fmt file for texinfo. -\def\setfilename{% - \fixbackslash % Turn off hack to swallow `\input texinfo'. - \iflinks - \tryauxfile - % Open the new aux file. TeX will close it automatically at exit. - \immediate\openout\auxfile=\jobname.aux - \fi % \openindices needs to do some work in any case. - \openindices - \let\setfilename=\comment % Ignore extra @setfilename cmds. - % - % If texinfo.cnf is present on the system, read it. - % Useful for site-wide @afourpaper, etc. - \openin 1 texinfo.cnf - \ifeof 1 \else \input texinfo.cnf \fi - \closein 1 - % - \comment % Ignore the actual filename. -} - -% Called from \setfilename. -% -\def\openindices{% - \newindex{cp}% - \newcodeindex{fn}% - \newcodeindex{vr}% - \newcodeindex{tp}% - \newcodeindex{ky}% - \newcodeindex{pg}% -} - -% @bye. -\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} - - -\message{pdf,} -% adobe `portable' document format -\newcount\tempnum -\newcount\lnkcount -\newtoks\filename -\newcount\filenamelength -\newcount\pgn -\newtoks\toksA -\newtoks\toksB -\newtoks\toksC -\newtoks\toksD -\newbox\boxA -\newcount\countA -\newif\ifpdf -\newif\ifpdfmakepagedest - -% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 -% can be set). So we test for \relax and 0 as well as being undefined. -\ifx\pdfoutput\thisisundefined -\else - \ifx\pdfoutput\relax - \else - \ifcase\pdfoutput - \else - \pdftrue - \fi - \fi -\fi - -% PDF uses PostScript string constants for the names of xref targets, -% for display in the outlines, and in other places. Thus, we have to -% double any backslashes. Otherwise, a name like "\node" will be -% interpreted as a newline (\n), followed by o, d, e. Not good. -% -% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and -% related messages. The final outcome is that it is up to the TeX user -% to double the backslashes and otherwise make the string valid, so -% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to -% do this reliably, so we use it. - -% #1 is a control sequence in which to do the replacements, -% which we \xdef. -\def\txiescapepdf#1{% - \ifx\pdfescapestring\thisisundefined - % No primitive available; should we give a warning or log? - % Many times it won't matter. - \else - % The expandable \pdfescapestring primitive escapes parentheses, - % backslashes, and other special chars. - \xdef#1{\pdfescapestring{#1}}% - \fi -} - -\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images -with PDF output, and none of those formats could be found. (.eps cannot -be supported due to the design of the PDF format; use regular TeX (DVI -output) for that.)} - -\ifpdf - % - % Color manipulation macros based on pdfcolor.tex, - % except using rgb instead of cmyk; the latter is said to render as a - % very dark gray on-screen and a very dark halftone in print, instead - % of actual black. - \def\rgbDarkRed{0.50 0.09 0.12} - \def\rgbBlack{0 0 0} - % - % k sets the color for filling (usual text, etc.); - % K sets the color for stroking (thin rules, e.g., normal _'s). - \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} - % - % Set color, and create a mark which defines \thiscolor accordingly, - % so that \makeheadline knows which color to restore. - \def\setcolor#1{% - \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% - \domark - \pdfsetcolor{#1}% - } - % - \def\maincolor{\rgbBlack} - \pdfsetcolor{\maincolor} - \edef\thiscolor{\maincolor} - \def\lastcolordefs{} - % - \def\makefootline{% - \baselineskip24pt - \line{\pdfsetcolor{\maincolor}\the\footline}% - } - % - \def\makeheadline{% - \vbox to 0pt{% - \vskip-22.5pt - \line{% - \vbox to8.5pt{}% - % Extract \thiscolor definition from the marks. - \getcolormarks - % Typeset the headline with \maincolor, then restore the color. - \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% - }% - \vss - }% - \nointerlineskip - } - % - % - \pdfcatalog{/PageMode /UseOutlines} - % - % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). - \def\dopdfimage#1#2#3{% - \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% - \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% - % - % pdftex (and the PDF format) support .pdf, .png, .jpg (among - % others). Let's try in that order, PDF first since if - % someone has a scalable image, presumably better to use that than a - % bitmap. - \let\pdfimgext=\empty - \begingroup - \openin 1 #1.pdf \ifeof 1 - \openin 1 #1.PDF \ifeof 1 - \openin 1 #1.png \ifeof 1 - \openin 1 #1.jpg \ifeof 1 - \openin 1 #1.jpeg \ifeof 1 - \openin 1 #1.JPG \ifeof 1 - \errhelp = \nopdfimagehelp - \errmessage{Could not find image file #1 for pdf}% - \else \gdef\pdfimgext{JPG}% - \fi - \else \gdef\pdfimgext{jpeg}% - \fi - \else \gdef\pdfimgext{jpg}% - \fi - \else \gdef\pdfimgext{png}% - \fi - \else \gdef\pdfimgext{PDF}% - \fi - \else \gdef\pdfimgext{pdf}% - \fi - \closein 1 - \endgroup - % - % without \immediate, ancient pdftex seg faults when the same image is - % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) - \ifnum\pdftexversion < 14 - \immediate\pdfimage - \else - \immediate\pdfximage - \fi - \ifdim \wd0 >0pt width \pdfimagewidth \fi - \ifdim \wd2 >0pt height \pdfimageheight \fi - \ifnum\pdftexversion<13 - #1.\pdfimgext - \else - {#1.\pdfimgext}% - \fi - \ifnum\pdftexversion < 14 \else - \pdfrefximage \pdflastximage - \fi} - % - \def\pdfmkdest#1{{% - % We have to set dummies so commands such as @code, and characters - % such as \, aren't expanded when present in a section title. - \indexnofonts - \turnoffactive - \makevalueexpandable - \def\pdfdestname{#1}% - \txiescapepdf\pdfdestname - \safewhatsit{\pdfdest name{\pdfdestname} xyz}% - }} - % - % used to mark target names; must be expandable. - \def\pdfmkpgn#1{#1} - % - % by default, use a color that is dark enough to print on paper as - % nearly black, but still distinguishable for online viewing. - \def\urlcolor{\rgbDarkRed} - \def\linkcolor{\rgbDarkRed} - \def\endlink{\setcolor{\maincolor}\pdfendlink} - % - % Adding outlines to PDF; macros for calculating structure of outlines - % come from Petr Olsak - \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% - \else \csname#1\endcsname \fi} - \def\advancenumber#1{\tempnum=\expnumber{#1}\relax - \advance\tempnum by 1 - \expandafter\xdef\csname#1\endcsname{\the\tempnum}} - % - % #1 is the section text, which is what will be displayed in the - % outline by the pdf viewer. #2 is the pdf expression for the number - % of subentries (or empty, for subsubsections). #3 is the node text, - % which might be empty if this toc entry had no corresponding node. - % #4 is the page number - % - \def\dopdfoutline#1#2#3#4{% - % Generate a link to the node text if that exists; else, use the - % page number. We could generate a destination for the section - % text in the case where a section has no node, but it doesn't - % seem worth the trouble, since most documents are normally structured. - \edef\pdfoutlinedest{#3}% - \ifx\pdfoutlinedest\empty - \def\pdfoutlinedest{#4}% - \else - \txiescapepdf\pdfoutlinedest - \fi - % - % Also escape PDF chars in the display string. - \edef\pdfoutlinetext{#1}% - \txiescapepdf\pdfoutlinetext - % - \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% - } - % - \def\pdfmakeoutlines{% - \begingroup - % Read toc silently, to get counts of subentries for \pdfoutline. - \def\partentry##1##2##3##4{}% ignore parts in the outlines - \def\numchapentry##1##2##3##4{% - \def\thischapnum{##2}% - \def\thissecnum{0}% - \def\thissubsecnum{0}% - }% - \def\numsecentry##1##2##3##4{% - \advancenumber{chap\thischapnum}% - \def\thissecnum{##2}% - \def\thissubsecnum{0}% - }% - \def\numsubsecentry##1##2##3##4{% - \advancenumber{sec\thissecnum}% - \def\thissubsecnum{##2}% - }% - \def\numsubsubsecentry##1##2##3##4{% - \advancenumber{subsec\thissubsecnum}% - }% - \def\thischapnum{0}% - \def\thissecnum{0}% - \def\thissubsecnum{0}% - % - % use \def rather than \let here because we redefine \chapentry et - % al. a second time, below. - \def\appentry{\numchapentry}% - \def\appsecentry{\numsecentry}% - \def\appsubsecentry{\numsubsecentry}% - \def\appsubsubsecentry{\numsubsubsecentry}% - \def\unnchapentry{\numchapentry}% - \def\unnsecentry{\numsecentry}% - \def\unnsubsecentry{\numsubsecentry}% - \def\unnsubsubsecentry{\numsubsubsecentry}% - \readdatafile{toc}% - % - % Read toc second time, this time actually producing the outlines. - % The `-' means take the \expnumber as the absolute number of - % subentries, which we calculated on our first read of the .toc above. - % - % We use the node names as the destinations. - \def\numchapentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% - \def\numsecentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% - \def\numsubsecentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% - \def\numsubsubsecentry##1##2##3##4{% count is always zero - \dopdfoutline{##1}{}{##3}{##4}}% - % - % PDF outlines are displayed using system fonts, instead of - % document fonts. Therefore we cannot use special characters, - % since the encoding is unknown. For example, the eogonek from - % Latin 2 (0xea) gets translated to a | character. Info from - % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. - % - % TODO this right, we have to translate 8-bit characters to - % their "best" equivalent, based on the @documentencoding. Too - % much work for too little return. Just use the ASCII equivalents - % we use for the index sort strings. - % - \indexnofonts - \setupdatafile - % We can have normal brace characters in the PDF outlines, unlike - % Texinfo index files. So set that up. - \def\{{\lbracecharliteral}% - \def\}{\rbracecharliteral}% - \catcode`\\=\active \otherbackslash - \input \tocreadfilename - \endgroup - } - {\catcode`[=1 \catcode`]=2 - \catcode`{=\other \catcode`}=\other - \gdef\lbracecharliteral[{]% - \gdef\rbracecharliteral[}]% - ] - % - \def\skipspaces#1{\def\PP{#1}\def\D{|}% - \ifx\PP\D\let\nextsp\relax - \else\let\nextsp\skipspaces - \addtokens{\filename}{\PP}% - \advance\filenamelength by 1 - \fi - \nextsp} - \def\getfilename#1{% - \filenamelength=0 - % If we don't expand the argument now, \skipspaces will get - % snagged on things like "@value{foo}". - \edef\temp{#1}% - \expandafter\skipspaces\temp|\relax - } - \ifnum\pdftexversion < 14 - \let \startlink \pdfannotlink - \else - \let \startlink \pdfstartlink - \fi - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - % do we want to go so far as to use \indexnofonts instead of just - % special-casing \var here? - \def\var##1{##1}% - % - \leavevmode\setcolor{\urlcolor}% - \startlink attr{/Border [0 0 0]}% - user{/Subtype /Link /A << /S /URI /URI (#1) >>}% - \endgroup} - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} - \def\pdflink#1{% - \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} - \setcolor{\linkcolor}#1\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} -\else - % non-pdf mode - \let\pdfmkdest = \gobble - \let\pdfurl = \gobble - \let\endlink = \relax - \let\setcolor = \gobble - \let\pdfsetcolor = \gobble - \let\pdfmakeoutlines = \relax -\fi % \ifx\pdfoutput - - -\message{fonts,} - -% Change the current font style to #1, remembering it in \curfontstyle. -% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in -% italics, not bold italics. -% -\def\setfontstyle#1{% - \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. - \csname ten#1\endcsname % change the current font -} - -% Select #1 fonts with the current style. -% -\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} - -\def\rm{\fam=0 \setfontstyle{rm}} -\def\it{\fam=\itfam \setfontstyle{it}} -\def\sl{\fam=\slfam \setfontstyle{sl}} -\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} -\def\tt{\fam=\ttfam \setfontstyle{tt}} - -% Unfortunately, we have to override this for titles and the like, since -% in those cases "rm" is bold. Sigh. -\def\rmisbold{\rm\def\curfontstyle{bf}} - -% Texinfo sort of supports the sans serif font style, which plain TeX does not. -% So we set up a \sf. -\newfam\sffam -\def\sf{\fam=\sffam \setfontstyle{sf}} -\let\li = \sf % Sometimes we call it \li, not \sf. - -% We don't need math for this font style. -\def\ttsl{\setfontstyle{ttsl}} - - -% Set the baselineskip to #1, and the lineskip and strut size -% correspondingly. There is no deep meaning behind these magic numbers -% used as factors; they just match (closely enough) what Knuth defined. -% -\def\lineskipfactor{.08333} -\def\strutheightpercent{.70833} -\def\strutdepthpercent {.29167} -% -% can get a sort of poor man's double spacing by redefining this. -\def\baselinefactor{1} -% -\newdimen\textleading -\def\setleading#1{% - \dimen0 = #1\relax - \normalbaselineskip = \baselinefactor\dimen0 - \normallineskip = \lineskipfactor\normalbaselineskip - \normalbaselines - \setbox\strutbox =\hbox{% - \vrule width0pt height\strutheightpercent\baselineskip - depth \strutdepthpercent \baselineskip - }% -} - -% PDF CMaps. See also LaTeX's t1.cmap. -% -% do nothing with this by default. -\expandafter\let\csname cmapOT1\endcsname\gobble -\expandafter\let\csname cmapOT1IT\endcsname\gobble -\expandafter\let\csname cmapOT1TT\endcsname\gobble - -% if we are producing pdf, and we have \pdffontattr, then define cmaps. -% (\pdffontattr was introduced many years ago, but people still run -% older pdftex's; it's easy to conditionalize, so we do.) -\ifpdf \ifx\pdffontattr\thisisundefined \else - \begingroup - \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. - \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-OT1-0) -%%Title: (TeX-OT1-0 TeX OT1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (OT1) -/Supplement 0 ->> def -/CMapName /TeX-OT1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <7F> -endcodespacerange -8 beginbfrange -<00> <01> <0393> -<09> <0A> <03A8> -<23> <26> <0023> -<28> <3B> <0028> -<3F> <5B> <003F> -<5D> <5E> <005D> -<61> <7A> <0061> -<7B> <7C> <2013> -endbfrange -40 beginbfchar -<02> <0398> -<03> <039B> -<04> <039E> -<05> <03A0> -<06> <03A3> -<07> <03D2> -<08> <03A6> -<0B> <00660066> -<0C> <00660069> -<0D> <0066006C> -<0E> <006600660069> -<0F> <00660066006C> -<10> <0131> -<11> <0237> -<12> <0060> -<13> <00B4> -<14> <02C7> -<15> <02D8> -<16> <00AF> -<17> <02DA> -<18> <00B8> -<19> <00DF> -<1A> <00E6> -<1B> <0153> -<1C> <00F8> -<1D> <00C6> -<1E> <0152> -<1F> <00D8> -<21> <0021> -<22> <201D> -<27> <2019> -<3C> <00A1> -<3D> <003D> -<3E> <00BF> -<5C> <201C> -<5F> <02D9> -<60> <2018> -<7D> <02DD> -<7E> <007E> -<7F> <00A8> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - }\endgroup - \expandafter\edef\csname cmapOT1\endcsname#1{% - \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% - }% -% -% \cmapOT1IT - \begingroup - \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. - \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-OT1IT-0) -%%Title: (TeX-OT1IT-0 TeX OT1IT 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (OT1IT) -/Supplement 0 ->> def -/CMapName /TeX-OT1IT-0 def -/CMapType 2 def -1 begincodespacerange -<00> <7F> -endcodespacerange -8 beginbfrange -<00> <01> <0393> -<09> <0A> <03A8> -<25> <26> <0025> -<28> <3B> <0028> -<3F> <5B> <003F> -<5D> <5E> <005D> -<61> <7A> <0061> -<7B> <7C> <2013> -endbfrange -42 beginbfchar -<02> <0398> -<03> <039B> -<04> <039E> -<05> <03A0> -<06> <03A3> -<07> <03D2> -<08> <03A6> -<0B> <00660066> -<0C> <00660069> -<0D> <0066006C> -<0E> <006600660069> -<0F> <00660066006C> -<10> <0131> -<11> <0237> -<12> <0060> -<13> <00B4> -<14> <02C7> -<15> <02D8> -<16> <00AF> -<17> <02DA> -<18> <00B8> -<19> <00DF> -<1A> <00E6> -<1B> <0153> -<1C> <00F8> -<1D> <00C6> -<1E> <0152> -<1F> <00D8> -<21> <0021> -<22> <201D> -<23> <0023> -<24> <00A3> -<27> <2019> -<3C> <00A1> -<3D> <003D> -<3E> <00BF> -<5C> <201C> -<5F> <02D9> -<60> <2018> -<7D> <02DD> -<7E> <007E> -<7F> <00A8> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - }\endgroup - \expandafter\edef\csname cmapOT1IT\endcsname#1{% - \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% - }% -% -% \cmapOT1TT - \begingroup - \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. - \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-OT1TT-0) -%%Title: (TeX-OT1TT-0 TeX OT1TT 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (OT1TT) -/Supplement 0 ->> def -/CMapName /TeX-OT1TT-0 def -/CMapType 2 def -1 begincodespacerange -<00> <7F> -endcodespacerange -5 beginbfrange -<00> <01> <0393> -<09> <0A> <03A8> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -endbfrange -32 beginbfchar -<02> <0398> -<03> <039B> -<04> <039E> -<05> <03A0> -<06> <03A3> -<07> <03D2> -<08> <03A6> -<0B> <2191> -<0C> <2193> -<0D> <0027> -<0E> <00A1> -<0F> <00BF> -<10> <0131> -<11> <0237> -<12> <0060> -<13> <00B4> -<14> <02C7> -<15> <02D8> -<16> <00AF> -<17> <02DA> -<18> <00B8> -<19> <00DF> -<1A> <00E6> -<1B> <0153> -<1C> <00F8> -<1D> <00C6> -<1E> <0152> -<1F> <00D8> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <00A8> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - }\endgroup - \expandafter\edef\csname cmapOT1TT\endcsname#1{% - \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% - }% -\fi\fi - - -% Set the font macro #1 to the font named \fontprefix#2. -% #3 is the font's design size, #4 is a scale factor, #5 is the CMap -% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). -% Example: -% #1 = \textrm -% #2 = \rmshape -% #3 = 10 -% #4 = \mainmagstep -% #5 = OT1 -% -\def\setfont#1#2#3#4#5{% - \font#1=\fontprefix#2#3 scaled #4 - \csname cmap#5\endcsname#1% -} -% This is what gets called when #5 of \setfont is empty. -\let\cmap\gobble -% -% (end of cmaps) - -% Use cm as the default font prefix. -% To specify the font prefix, you must define \fontprefix -% before you read in texinfo.tex. -\ifx\fontprefix\thisisundefined -\def\fontprefix{cm} -\fi -% Support font families that don't use the same naming scheme as CM. -\def\rmshape{r} -\def\rmbshape{bx} % where the normal face is bold -\def\bfshape{b} -\def\bxshape{bx} -\def\ttshape{tt} -\def\ttbshape{tt} -\def\ttslshape{sltt} -\def\itshape{ti} -\def\itbshape{bxti} -\def\slshape{sl} -\def\slbshape{bxsl} -\def\sfshape{ss} -\def\sfbshape{ss} -\def\scshape{csc} -\def\scbshape{csc} - -% Definitions for a main text size of 11pt. (The default in Texinfo.) -% -\def\definetextfontsizexi{% -% Text fonts (11.2pt, magstep1). -\def\textnominalsize{11pt} -\edef\mainmagstep{\magstephalf} -\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} -\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} -\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} -\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} -\setfont\textsl\slshape{10}{\mainmagstep}{OT1} -\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} -\setfont\textsc\scshape{10}{\mainmagstep}{OT1} -\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} -\font\texti=cmmi10 scaled \mainmagstep -\font\textsy=cmsy10 scaled \mainmagstep -\def\textecsize{1095} - -% A few fonts for @defun names and args. -\setfont\defbf\bfshape{10}{\magstep1}{OT1} -\setfont\deftt\ttshape{10}{\magstep1}{OT1TT} -\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} - -% Fonts for indices, footnotes, small examples (9pt). -\def\smallnominalsize{9pt} -\setfont\smallrm\rmshape{9}{1000}{OT1} -\setfont\smalltt\ttshape{9}{1000}{OT1TT} -\setfont\smallbf\bfshape{10}{900}{OT1} -\setfont\smallit\itshape{9}{1000}{OT1IT} -\setfont\smallsl\slshape{9}{1000}{OT1} -\setfont\smallsf\sfshape{9}{1000}{OT1} -\setfont\smallsc\scshape{10}{900}{OT1} -\setfont\smallttsl\ttslshape{10}{900}{OT1TT} -\font\smalli=cmmi9 -\font\smallsy=cmsy9 -\def\smallecsize{0900} - -% Fonts for small examples (8pt). -\def\smallernominalsize{8pt} -\setfont\smallerrm\rmshape{8}{1000}{OT1} -\setfont\smallertt\ttshape{8}{1000}{OT1TT} -\setfont\smallerbf\bfshape{10}{800}{OT1} -\setfont\smallerit\itshape{8}{1000}{OT1IT} -\setfont\smallersl\slshape{8}{1000}{OT1} -\setfont\smallersf\sfshape{8}{1000}{OT1} -\setfont\smallersc\scshape{10}{800}{OT1} -\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} -\font\smalleri=cmmi8 -\font\smallersy=cmsy8 -\def\smallerecsize{0800} - -% Fonts for title page (20.4pt): -\def\titlenominalsize{20pt} -\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} -\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} -\setfont\titlesl\slbshape{10}{\magstep4}{OT1} -\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} -\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} -\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} -\let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4}{OT1} -\font\titlei=cmmi12 scaled \magstep3 -\font\titlesy=cmsy10 scaled \magstep4 -\def\titleecsize{2074} - -% Chapter (and unnumbered) fonts (17.28pt). -\def\chapnominalsize{17pt} -\setfont\chaprm\rmbshape{12}{\magstep2}{OT1} -\setfont\chapit\itbshape{10}{\magstep3}{OT1IT} -\setfont\chapsl\slbshape{10}{\magstep3}{OT1} -\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} -\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} -\setfont\chapsf\sfbshape{17}{1000}{OT1} -\let\chapbf=\chaprm -\setfont\chapsc\scbshape{10}{\magstep3}{OT1} -\font\chapi=cmmi12 scaled \magstep2 -\font\chapsy=cmsy10 scaled \magstep3 -\def\chapecsize{1728} - -% Section fonts (14.4pt). -\def\secnominalsize{14pt} -\setfont\secrm\rmbshape{12}{\magstep1}{OT1} -\setfont\secit\itbshape{10}{\magstep2}{OT1IT} -\setfont\secsl\slbshape{10}{\magstep2}{OT1} -\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} -\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} -\setfont\secsf\sfbshape{12}{\magstep1}{OT1} -\let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep2}{OT1} -\font\seci=cmmi12 scaled \magstep1 -\font\secsy=cmsy10 scaled \magstep2 -\def\sececsize{1440} - -% Subsection fonts (13.15pt). -\def\ssecnominalsize{13pt} -\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} -\setfont\ssecit\itbshape{10}{1315}{OT1IT} -\setfont\ssecsl\slbshape{10}{1315}{OT1} -\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} -\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} -\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} -\let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{1315}{OT1} -\font\sseci=cmmi12 scaled \magstephalf -\font\ssecsy=cmsy10 scaled 1315 -\def\ssececsize{1200} - -% Reduced fonts for @acro in text (10pt). -\def\reducednominalsize{10pt} -\setfont\reducedrm\rmshape{10}{1000}{OT1} -\setfont\reducedtt\ttshape{10}{1000}{OT1TT} -\setfont\reducedbf\bfshape{10}{1000}{OT1} -\setfont\reducedit\itshape{10}{1000}{OT1IT} -\setfont\reducedsl\slshape{10}{1000}{OT1} -\setfont\reducedsf\sfshape{10}{1000}{OT1} -\setfont\reducedsc\scshape{10}{1000}{OT1} -\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} -\font\reducedi=cmmi10 -\font\reducedsy=cmsy10 -\def\reducedecsize{1000} - -\textleading = 13.2pt % line spacing for 11pt CM -\textfonts % reset the current fonts -\rm -} % end of 11pt text font size definitions, \definetextfontsizexi - - -% Definitions to make the main text be 10pt Computer Modern, with -% section, chapter, etc., sizes following suit. This is for the GNU -% Press printing of the Emacs 22 manual. Maybe other manuals in the -% future. Used with @smallbook, which sets the leading to 12pt. -% -\def\definetextfontsizex{% -% Text fonts (10pt). -\def\textnominalsize{10pt} -\edef\mainmagstep{1000} -\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} -\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} -\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} -\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} -\setfont\textsl\slshape{10}{\mainmagstep}{OT1} -\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} -\setfont\textsc\scshape{10}{\mainmagstep}{OT1} -\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} -\font\texti=cmmi10 scaled \mainmagstep -\font\textsy=cmsy10 scaled \mainmagstep -\def\textecsize{1000} - -% A few fonts for @defun names and args. -\setfont\defbf\bfshape{10}{\magstephalf}{OT1} -\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} -\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} - -% Fonts for indices, footnotes, small examples (9pt). -\def\smallnominalsize{9pt} -\setfont\smallrm\rmshape{9}{1000}{OT1} -\setfont\smalltt\ttshape{9}{1000}{OT1TT} -\setfont\smallbf\bfshape{10}{900}{OT1} -\setfont\smallit\itshape{9}{1000}{OT1IT} -\setfont\smallsl\slshape{9}{1000}{OT1} -\setfont\smallsf\sfshape{9}{1000}{OT1} -\setfont\smallsc\scshape{10}{900}{OT1} -\setfont\smallttsl\ttslshape{10}{900}{OT1TT} -\font\smalli=cmmi9 -\font\smallsy=cmsy9 -\def\smallecsize{0900} - -% Fonts for small examples (8pt). -\def\smallernominalsize{8pt} -\setfont\smallerrm\rmshape{8}{1000}{OT1} -\setfont\smallertt\ttshape{8}{1000}{OT1TT} -\setfont\smallerbf\bfshape{10}{800}{OT1} -\setfont\smallerit\itshape{8}{1000}{OT1IT} -\setfont\smallersl\slshape{8}{1000}{OT1} -\setfont\smallersf\sfshape{8}{1000}{OT1} -\setfont\smallersc\scshape{10}{800}{OT1} -\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} -\font\smalleri=cmmi8 -\font\smallersy=cmsy8 -\def\smallerecsize{0800} - -% Fonts for title page (20.4pt): -\def\titlenominalsize{20pt} -\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} -\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} -\setfont\titlesl\slbshape{10}{\magstep4}{OT1} -\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} -\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} -\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} -\let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4}{OT1} -\font\titlei=cmmi12 scaled \magstep3 -\font\titlesy=cmsy10 scaled \magstep4 -\def\titleecsize{2074} - -% Chapter fonts (14.4pt). -\def\chapnominalsize{14pt} -\setfont\chaprm\rmbshape{12}{\magstep1}{OT1} -\setfont\chapit\itbshape{10}{\magstep2}{OT1IT} -\setfont\chapsl\slbshape{10}{\magstep2}{OT1} -\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} -\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} -\setfont\chapsf\sfbshape{12}{\magstep1}{OT1} -\let\chapbf\chaprm -\setfont\chapsc\scbshape{10}{\magstep2}{OT1} -\font\chapi=cmmi12 scaled \magstep1 -\font\chapsy=cmsy10 scaled \magstep2 -\def\chapecsize{1440} - -% Section fonts (12pt). -\def\secnominalsize{12pt} -\setfont\secrm\rmbshape{12}{1000}{OT1} -\setfont\secit\itbshape{10}{\magstep1}{OT1IT} -\setfont\secsl\slbshape{10}{\magstep1}{OT1} -\setfont\sectt\ttbshape{12}{1000}{OT1TT} -\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} -\setfont\secsf\sfbshape{12}{1000}{OT1} -\let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep1}{OT1} -\font\seci=cmmi12 -\font\secsy=cmsy10 scaled \magstep1 -\def\sececsize{1200} - -% Subsection fonts (10pt). -\def\ssecnominalsize{10pt} -\setfont\ssecrm\rmbshape{10}{1000}{OT1} -\setfont\ssecit\itbshape{10}{1000}{OT1IT} -\setfont\ssecsl\slbshape{10}{1000}{OT1} -\setfont\ssectt\ttbshape{10}{1000}{OT1TT} -\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} -\setfont\ssecsf\sfbshape{10}{1000}{OT1} -\let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{1000}{OT1} -\font\sseci=cmmi10 -\font\ssecsy=cmsy10 -\def\ssececsize{1000} - -% Reduced fonts for @acro in text (9pt). -\def\reducednominalsize{9pt} -\setfont\reducedrm\rmshape{9}{1000}{OT1} -\setfont\reducedtt\ttshape{9}{1000}{OT1TT} -\setfont\reducedbf\bfshape{10}{900}{OT1} -\setfont\reducedit\itshape{9}{1000}{OT1IT} -\setfont\reducedsl\slshape{9}{1000}{OT1} -\setfont\reducedsf\sfshape{9}{1000}{OT1} -\setfont\reducedsc\scshape{10}{900}{OT1} -\setfont\reducedttsl\ttslshape{10}{900}{OT1TT} -\font\reducedi=cmmi9 -\font\reducedsy=cmsy9 -\def\reducedecsize{0900} - -\divide\parskip by 2 % reduce space between paragraphs -\textleading = 12pt % line spacing for 10pt CM -\textfonts % reset the current fonts -\rm -} % end of 10pt text font size definitions, \definetextfontsizex - - -% We provide the user-level command -% @fonttextsize 10 -% (or 11) to redefine the text font size. pt is assumed. -% -\def\xiword{11} -\def\xword{10} -\def\xwordpt{10pt} -% -\parseargdef\fonttextsize{% - \def\textsizearg{#1}% - %\wlog{doing @fonttextsize \textsizearg}% - % - % Set \globaldefs so that documents can use this inside @tex, since - % makeinfo 4.8 does not support it, but we need it nonetheless. - % - \begingroup \globaldefs=1 - \ifx\textsizearg\xword \definetextfontsizex - \else \ifx\textsizearg\xiword \definetextfontsizexi - \else - \errhelp=\EMsimple - \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} - \fi\fi - \endgroup -} - - -% In order for the font changes to affect most math symbols and letters, -% we have to define the \textfont of the standard families. Since -% texinfo doesn't allow for producing subscripts and superscripts except -% in the main text, we don't bother to reset \scriptfont and -% \scriptscriptfont (which would also require loading a lot more fonts). -% -\def\resetmathfonts{% - \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy - \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf - \textfont\ttfam=\tentt \textfont\sffam=\tensf -} - -% The font-changing commands redefine the meanings of \tenSTYLE, instead -% of just \STYLE. We do this because \STYLE needs to also set the -% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire -% \tenSTYLE to set the current font. -% -% Each font-changing command also sets the names \lsize (one size lower) -% and \lllsize (three sizes lower). These relative commands are used in -% the LaTeX logo and acronyms. -% -% This all needs generalizing, badly. -% -\def\textfonts{% - \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl - \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc - \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy - \let\tenttsl=\textttsl - \def\curfontsize{text}% - \def\lsize{reduced}\def\lllsize{smaller}% - \resetmathfonts \setleading{\textleading}} -\def\titlefonts{% - \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl - \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc - \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy - \let\tenttsl=\titlettsl - \def\curfontsize{title}% - \def\lsize{chap}\def\lllsize{subsec}% - \resetmathfonts \setleading{27pt}} -\def\titlefont#1{{\titlefonts\rmisbold #1}} -\def\chapfonts{% - \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl - \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy - \let\tenttsl=\chapttsl - \def\curfontsize{chap}% - \def\lsize{sec}\def\lllsize{text}% - \resetmathfonts \setleading{19pt}} -\def\secfonts{% - \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl - \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc - \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy - \let\tenttsl=\secttsl - \def\curfontsize{sec}% - \def\lsize{subsec}\def\lllsize{reduced}% - \resetmathfonts \setleading{16pt}} -\def\subsecfonts{% - \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl - \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc - \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy - \let\tenttsl=\ssecttsl - \def\curfontsize{ssec}% - \def\lsize{text}\def\lllsize{small}% - \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts -\def\reducedfonts{% - \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl - \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc - \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy - \let\tenttsl=\reducedttsl - \def\curfontsize{reduced}% - \def\lsize{small}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallfonts{% - \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl - \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc - \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy - \let\tenttsl=\smallttsl - \def\curfontsize{small}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallerfonts{% - \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl - \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc - \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy - \let\tenttsl=\smallerttsl - \def\curfontsize{smaller}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{9.5pt}} - -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000}{OT1} -\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 -\setfont\shortcontsl\slshape{12}{1000}{OT1} -\setfont\shortconttt\ttshape{12}{1000}{OT1TT} - -% Define these just so they can be easily changed for other fonts. -\def\angleleft{$\langle$} -\def\angleright{$\rangle$} - -% Set the fonts to use with the @small... environments. -\let\smallexamplefonts = \smallfonts - -% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample -% can fit this many characters: -% 8.5x11=86 smallbook=72 a4=90 a5=69 -% If we use \scriptfonts (8pt), then we can fit this many characters: -% 8.5x11=90+ smallbook=80 a4=90+ a5=77 -% For me, subjectively, the few extra characters that fit aren't worth -% the additional smallness of 8pt. So I'm making the default 9pt. -% -% By the way, for comparison, here's what fits with @example (10pt): -% 8.5x11=71 smallbook=60 a4=75 a5=58 -% --karl, 24jan03. - -% Set up the default fonts, so we can use them for creating boxes. -% -\definetextfontsizexi - - -\message{markup,} - -% Check if we are currently using a typewriter font. Since all the -% Computer Modern typewriter fonts have zero interword stretch (and -% shrink), and it is reasonable to expect all typewriter fonts to have -% this property, we can check that font parameter. -% -\def\ifmonospace{\ifdim\fontdimen3\font=0pt } - -% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will -% define and register \INITMACRO to be called on markup style changes. -% \INITMACRO can check \currentmarkupstyle for the innermost -% style and the set of \ifmarkupSTYLE switches for all styles -% currently in effect. -\newif\ifmarkupvar -\newif\ifmarkupsamp -\newif\ifmarkupkey -%\newif\ifmarkupfile % @file == @samp. -%\newif\ifmarkupoption % @option == @samp. -\newif\ifmarkupcode -\newif\ifmarkupkbd -%\newif\ifmarkupenv % @env == @code. -%\newif\ifmarkupcommand % @command == @code. -\newif\ifmarkuptex % @tex (and part of @math, for now). -\newif\ifmarkupexample -\newif\ifmarkupverb -\newif\ifmarkupverbatim - -\let\currentmarkupstyle\empty - -\def\setupmarkupstyle#1{% - \csname markup#1true\endcsname - \def\currentmarkupstyle{#1}% - \markupstylesetup -} - -\let\markupstylesetup\empty - -\def\defmarkupstylesetup#1{% - \expandafter\def\expandafter\markupstylesetup - \expandafter{\markupstylesetup #1}% - \def#1% -} - -% Markup style setup for left and right quotes. -\defmarkupstylesetup\markupsetuplq{% - \expandafter\let\expandafter \temp - \csname markupsetuplq\currentmarkupstyle\endcsname - \ifx\temp\relax \markupsetuplqdefault \else \temp \fi -} - -\defmarkupstylesetup\markupsetuprq{% - \expandafter\let\expandafter \temp - \csname markupsetuprq\currentmarkupstyle\endcsname - \ifx\temp\relax \markupsetuprqdefault \else \temp \fi -} - -{ -\catcode`\'=\active -\catcode`\`=\active - -\gdef\markupsetuplqdefault{\let`\lq} -\gdef\markupsetuprqdefault{\let'\rq} - -\gdef\markupsetcodequoteleft{\let`\codequoteleft} -\gdef\markupsetcodequoteright{\let'\codequoteright} -} - -\let\markupsetuplqcode \markupsetcodequoteleft -\let\markupsetuprqcode \markupsetcodequoteright -% -\let\markupsetuplqexample \markupsetcodequoteleft -\let\markupsetuprqexample \markupsetcodequoteright -% -\let\markupsetuplqkbd \markupsetcodequoteleft -\let\markupsetuprqkbd \markupsetcodequoteright -% -\let\markupsetuplqsamp \markupsetcodequoteleft -\let\markupsetuprqsamp \markupsetcodequoteright -% -\let\markupsetuplqverb \markupsetcodequoteleft -\let\markupsetuprqverb \markupsetcodequoteright -% -\let\markupsetuplqverbatim \markupsetcodequoteleft -\let\markupsetuprqverbatim \markupsetcodequoteright - -% Allow an option to not use regular directed right quote/apostrophe -% (char 0x27), but instead the undirected quote from cmtt (char 0x0d). -% The undirected quote is ugly, so don't make it the default, but it -% works for pasting with more pdf viewers (at least evince), the -% lilypond developers report. xpdf does work with the regular 0x27. -% -\def\codequoteright{% - \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax - \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax - '% - \else \char'15 \fi - \else \char'15 \fi -} -% -% and a similar option for the left quote char vs. a grave accent. -% Modern fonts display ASCII 0x60 as a grave accent, so some people like -% the code environments to do likewise. -% -\def\codequoteleft{% - \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax - \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax - % [Knuth] pp. 380,381,391 - % \relax disables Spanish ligatures ?` and !` of \tt font. - \relax`% - \else \char'22 \fi - \else \char'22 \fi -} - -% Commands to set the quote options. -% -\parseargdef\codequoteundirected{% - \def\temp{#1}% - \ifx\temp\onword - \expandafter\let\csname SETtxicodequoteundirected\endcsname - = t% - \else\ifx\temp\offword - \expandafter\let\csname SETtxicodequoteundirected\endcsname - = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}% - \fi\fi -} -% -\parseargdef\codequotebacktick{% - \def\temp{#1}% - \ifx\temp\onword - \expandafter\let\csname SETtxicodequotebacktick\endcsname - = t% - \else\ifx\temp\offword - \expandafter\let\csname SETtxicodequotebacktick\endcsname - = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}% - \fi\fi -} - -% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. -\def\noligaturesquoteleft{\relax\lq} - -% Count depth in font-changes, for error checks -\newcount\fontdepth \fontdepth=0 - -% Font commands. - -% #1 is the font command (\sl or \it), #2 is the text to slant. -% If we are in a monospaced environment, however, 1) always use \ttsl, -% and 2) do not add an italic correction. -\def\dosmartslant#1#2{% - \ifusingtt - {{\ttsl #2}\let\next=\relax}% - {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% - \next -} -\def\smartslanted{\dosmartslant\sl} -\def\smartitalic{\dosmartslant\it} - -% Output an italic correction unless \next (presumed to be the following -% character) is such as not to need one. -\def\smartitaliccorrection{% - \ifx\next,% - \else\ifx\next-% - \else\ifx\next.% - \else\ptexslash - \fi\fi\fi - \aftersmartic -} - -% Unconditional use \ttsl, and no ic. @var is set to this for defuns. -\def\ttslanted#1{{\ttsl #1}} - -% @cite is like \smartslanted except unconditionally use \sl. We never want -% ttsl for book titles, do we? -\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} - -\def\aftersmartic{} -\def\var#1{% - \let\saveaftersmartic = \aftersmartic - \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% - \smartslanted{#1}% -} - -\let\i=\smartitalic -\let\slanted=\smartslanted -\let\dfn=\smartslanted -\let\emph=\smartitalic - -% Explicit font changes: @r, @sc, undocumented @ii. -\def\r#1{{\rm #1}} % roman font -\def\sc#1{{\smallcaps#1}} % smallcaps font -\def\ii#1{{\it #1}} % italic font - -% @b, explicit bold. Also @strong. -\def\b#1{{\bf #1}} -\let\strong=\b - -% @sansserif, explicit sans. -\def\sansserif#1{{\sf #1}} - -% We can't just use \exhyphenpenalty, because that only has effect at -% the end of a paragraph. Restore normal hyphenation at the end of the -% group within which \nohyphenation is presumably called. -% -\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} -\def\restorehyphenation{\hyphenchar\font = `- } - -% Set sfcode to normal for the chars that usually have another value. -% Can't use plain's \frenchspacing because it uses the `\x notation, and -% sometimes \x has an active definition that messes things up. -% -\catcode`@=11 - \def\plainfrenchspacing{% - \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m - \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m - \def\endofsentencespacefactor{1000}% for @. and friends - } - \def\plainnonfrenchspacing{% - \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 - \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 - \def\endofsentencespacefactor{3000}% for @. and friends - } -\catcode`@=\other -\def\endofsentencespacefactor{3000}% default - -% @t, explicit typewriter. -\def\t#1{% - {\tt \rawbackslash \plainfrenchspacing #1}% - \null -} - -% @samp. -\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} - -% @indicateurl is \samp, that is, with quotes. -\let\indicateurl=\samp - -% @code (and similar) prints in typewriter, but with spaces the same -% size as normal in the surrounding text, without hyphenation, etc. -% This is a subroutine for that. -\def\tclose#1{% - {% - % Change normal interword space to be same as for the current font. - \spaceskip = \fontdimen2\font - % - % Switch to typewriter. - \tt - % - % But `\ ' produces the large typewriter interword space. - \def\ {{\spaceskip = 0pt{} }}% - % - % Turn off hyphenation. - \nohyphenation - % - \rawbackslash - \plainfrenchspacing - #1% - }% - \null % reset spacefactor to 1000 -} - -% We *must* turn on hyphenation at `-' and `_' in @code. -% Otherwise, it is too hard to avoid overfull hboxes -% in the Emacs manual, the Library manual, etc. -% -% Unfortunately, TeX uses one parameter (\hyphenchar) to control -% both hyphenation at - and hyphenation within words. -% We must therefore turn them both off (\tclose does that) -% and arrange explicitly to hyphenate at a dash. -% -- rms. -{ - \catcode`\-=\active \catcode`\_=\active - \catcode`\'=\active \catcode`\`=\active - \global\let'=\rq \global\let`=\lq % default definitions - % - \global\def\code{\begingroup - \setupmarkupstyle{code}% - % The following should really be moved into \setupmarkupstyle handlers. - \catcode\dashChar=\active \catcode\underChar=\active - \ifallowcodebreaks - \let-\codedash - \let_\codeunder - \else - \let-\normaldash - \let_\realunder - \fi - \codex - } -} - -\def\codex #1{\tclose{#1}\endgroup} - -\def\normaldash{-} -\def\codedash{-\discretionary{}{}{}} -\def\codeunder{% - % this is all so @math{@code{var_name}+1} can work. In math mode, _ - % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) - % will therefore expand the active definition of _, which is us - % (inside @code that is), therefore an endless loop. - \ifusingtt{\ifmmode - \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. - \else\normalunderscore \fi - \discretionary{}{}{}}% - {\_}% -} - -% An additional complication: the above will allow breaks after, e.g., -% each of the four underscores in __typeof__. This is bad. -% @allowcodebreaks provides a document-level way to turn breaking at - -% and _ on and off. -% -\newif\ifallowcodebreaks \allowcodebreakstrue - -\def\keywordtrue{true} -\def\keywordfalse{false} - -\parseargdef\allowcodebreaks{% - \def\txiarg{#1}% - \ifx\txiarg\keywordtrue - \allowcodebreakstrue - \else\ifx\txiarg\keywordfalse - \allowcodebreaksfalse - \else - \errhelp = \EMsimple - \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}% - \fi\fi -} - -% For @command, @env, @file, @option quotes seem unnecessary, -% so use \code rather than \samp. -\let\command=\code -\let\env=\code -\let\file=\code -\let\option=\code - -% @uref (abbreviation for `urlref') takes an optional (comma-separated) -% second argument specifying the text to display and an optional third -% arg as text to display instead of (rather than in addition to) the url -% itself. First (mandatory) arg is the url. -% (This \urefnobreak definition isn't used now, leaving it for a while -% for comparison.) -\def\urefnobreak#1{\dourefnobreak #1,,,\finish} -\def\dourefnobreak#1,#2,#3,#4\finish{\begingroup - \unsepspaces - \pdfurl{#1}% - \setbox0 = \hbox{\ignorespaces #3}% - \ifdim\wd0 > 0pt - \unhbox0 % third arg given, show only that - \else - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \ifpdf - \unhbox0 % PDF: 2nd arg given, show only it - \else - \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url - \fi - \else - \code{#1}% only url given, so show it - \fi - \fi - \endlink -\endgroup} - -% This \urefbreak definition is the active one. -\def\urefbreak{\begingroup \urefcatcodes \dourefbreak} -\let\uref=\urefbreak -\def\dourefbreak#1{\urefbreakfinish #1,,,\finish} -\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example - \unsepspaces - \pdfurl{#1}% - \setbox0 = \hbox{\ignorespaces #3}% - \ifdim\wd0 > 0pt - \unhbox0 % third arg given, show only that - \else - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \ifpdf - \unhbox0 % PDF: 2nd arg given, show only it - \else - \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url - \fi - \else - \urefcode{#1}% only url given, so show it - \fi - \fi - \endlink -\endgroup} - -% Allow line breaks around only a few characters (only). -\def\urefcatcodes{% - \catcode\ampChar=\active \catcode\dotChar=\active - \catcode\hashChar=\active \catcode\questChar=\active - \catcode\slashChar=\active -} -{ - \urefcatcodes - % - \global\def\urefcode{\begingroup - \setupmarkupstyle{code}% - \urefcatcodes - \let&\urefcodeamp - \let.\urefcodedot - \let#\urefcodehash - \let?\urefcodequest - \let/\urefcodeslash - \codex - } - % - % By default, they are just regular characters. - \global\def&{\normalamp} - \global\def.{\normaldot} - \global\def#{\normalhash} - \global\def?{\normalquest} - \global\def/{\normalslash} -} - -% we put a little stretch before and after the breakable chars, to help -% line breaking of long url's. The unequal skips make look better in -% cmtt at least, especially for dots. -\def\urefprestretch{\urefprebreak \hskip0pt plus.13em } -\def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em } -% -\def\urefcodeamp{\urefprestretch \&\urefpoststretch} -\def\urefcodedot{\urefprestretch .\urefpoststretch} -\def\urefcodehash{\urefprestretch \#\urefpoststretch} -\def\urefcodequest{\urefprestretch ?\urefpoststretch} -\def\urefcodeslash{\futurelet\next\urefcodeslashfinish} -{ - \catcode`\/=\active - \global\def\urefcodeslashfinish{% - \urefprestretch \slashChar - % Allow line break only after the final / in a sequence of - % slashes, to avoid line break between the slashes in http://. - \ifx\next/\else \urefpoststretch \fi - } -} - -% One more complication: by default we'll break after the special -% characters, but some people like to break before the special chars, so -% allow that. Also allow no breaking at all, for manual control. -% -\parseargdef\urefbreakstyle{% - \def\txiarg{#1}% - \ifx\txiarg\wordnone - \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} - \else\ifx\txiarg\wordbefore - \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak} - \else\ifx\txiarg\wordafter - \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak} - \else - \errhelp = \EMsimple - \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% - \fi\fi\fi -} -\def\wordafter{after} -\def\wordbefore{before} -\def\wordnone{none} - -\urefbreakstyle after - -% @url synonym for @uref, since that's how everyone uses it. -% -\let\url=\uref - -% rms does not like angle brackets --karl, 17may97. -% So now @email is just like @uref, unless we are pdf. -% -%\def\email#1{\angleleft{\tt #1}\angleright} -\ifpdf - \def\email#1{\doemail#1,,\finish} - \def\doemail#1,#2,#3\finish{\begingroup - \unsepspaces - \pdfurl{mailto:#1}% - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi - \endlink - \endgroup} -\else - \let\email=\uref -\fi - -% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), -% `example' (@kbd uses ttsl only inside of @example and friends), -% or `code' (@kbd uses normal tty font always). -\parseargdef\kbdinputstyle{% - \def\txiarg{#1}% - \ifx\txiarg\worddistinct - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% - \else\ifx\txiarg\wordexample - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% - \else\ifx\txiarg\wordcode - \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% - \else - \errhelp = \EMsimple - \errmessage{Unknown @kbdinputstyle setting `\txiarg'}% - \fi\fi\fi -} -\def\worddistinct{distinct} -\def\wordexample{example} -\def\wordcode{code} - -% Default is `distinct'. -\kbdinputstyle distinct - -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. -\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} - -\def\xkey{\key} -\def\kbdsub#1#2#3\par{% - \def\one{#1}\def\three{#3}\def\threex{??}% - \ifx\one\xkey\ifx\threex\three \key{#2}% - \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi - \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi -} - -% definition of @key that produces a lozenge. Doesn't adjust to text size. -%\setfont\keyrm\rmshape{8}{1000}{OT1} -%\font\keysy=cmsy9 -%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% -% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% -% \vbox{\hrule\kern-0.4pt -% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% -% \kern-0.4pt\hrule}% -% \kern-.06em\raise0.4pt\hbox{\angleright}}}} - -% definition of @key with no lozenge. If the current font is already -% monospace, don't change it; that way, we respect @kbdinputstyle. But -% if it isn't monospace, then use \tt. -% -\def\key#1{{\setupmarkupstyle{key}% - \nohyphenation - \ifmonospace\else\tt\fi - #1}\null} - -% @clicksequence{File @click{} Open ...} -\def\clicksequence#1{\begingroup #1\endgroup} - -% @clickstyle @arrow (by default) -\parseargdef\clickstyle{\def\click{#1}} -\def\click{\arrow} - -% Typeset a dimension, e.g., `in' or `pt'. The only reason for the -% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. -% -\def\dmn#1{\thinspace #1} - -% @l was never documented to mean ``switch to the Lisp font'', -% and it is not used as such in any manual I can find. We need it for -% Polish suppressed-l. --karl, 22sep96. -%\def\l#1{{\li #1}\null} - -% @acronym for "FBI", "NATO", and the like. -% We print this one point size smaller, since it's intended for -% all-uppercase. -% -\def\acronym#1{\doacronym #1,,\finish} -\def\doacronym#1,#2,#3\finish{% - {\selectfonts\lsize #1}% - \def\temp{#2}% - \ifx\temp\empty \else - \space ({\unsepspaces \ignorespaces \temp \unskip})% - \fi - \null % reset \spacefactor=1000 -} - -% @abbr for "Comput. J." and the like. -% No font change, but don't do end-of-sentence spacing. -% -\def\abbr#1{\doabbr #1,,\finish} -\def\doabbr#1,#2,#3\finish{% - {\plainfrenchspacing #1}% - \def\temp{#2}% - \ifx\temp\empty \else - \space ({\unsepspaces \ignorespaces \temp \unskip})% - \fi - \null % reset \spacefactor=1000 -} - -% @asis just yields its argument. Used with @table, for example. -% -\def\asis#1{#1} - -% @math outputs its argument in math mode. -% -% One complication: _ usually means subscripts, but it could also mean -% an actual _ character, as in @math{@var{some_variable} + 1}. So make -% _ active, and distinguish by seeing if the current family is \slfam, -% which is what @var uses. -{ - \catcode`\_ = \active - \gdef\mathunderscore{% - \catcode`\_=\active - \def_{\ifnum\fam=\slfam \_\else\sb\fi}% - } -} -% Another complication: we want \\ (and @\) to output a math (or tt) \. -% FYI, plain.tex uses \\ as a temporary control sequence (for no -% particular reason), but this is not advertised and we don't care. -% -% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. -\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} -% -\def\math{% - \tex - \mathunderscore - \let\\ = \mathbackslash - \mathactive - % make the texinfo accent commands work in math mode - \let\"=\ddot - \let\'=\acute - \let\==\bar - \let\^=\hat - \let\`=\grave - \let\u=\breve - \let\v=\check - \let\~=\tilde - \let\dotaccent=\dot - $\finishmath -} -\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. - -% Some active characters (such as <) are spaced differently in math. -% We have to reset their definitions in case the @math was an argument -% to a command which sets the catcodes (such as @item or @section). -% -{ - \catcode`^ = \active - \catcode`< = \active - \catcode`> = \active - \catcode`+ = \active - \catcode`' = \active - \gdef\mathactive{% - \let^ = \ptexhat - \let< = \ptexless - \let> = \ptexgtr - \let+ = \ptexplus - \let' = \ptexquoteright - } -} - -% ctrl is no longer a Texinfo command, but leave this definition for fun. -\def\ctrl #1{{\tt \rawbackslash \hat}#1} - -% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. -% Ignore unless FMTNAME == tex; then it is like @iftex and @tex, -% except specified as a normal braced arg, so no newlines to worry about. -% -\def\outfmtnametex{tex} -% -\long\def\inlinefmt#1{\doinlinefmt #1,\finish} -\long\def\doinlinefmt#1,#2,\finish{% - \def\inlinefmtname{#1}% - \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi -} -% For raw, must switch into @tex before parsing the argument, to avoid -% setting catcodes prematurely. Doing it this way means that, for -% example, @inlineraw{html, foo{bar} gets a parse error instead of being -% ignored. But this isn't important because if people want a literal -% *right* brace they would have to use a command anyway, so they may as -% well use a command to get a left brace too. We could re-use the -% delimiter character idea from \verb, but it seems like overkill. -% -\long\def\inlineraw{\tex \doinlineraw} -\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} -\def\doinlinerawtwo#1,#2,\finish{% - \def\inlinerawname{#1}% - \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi - \endgroup % close group opened by \tex. -} - - -\message{glyphs,} -% and logos. - -% @@ prints an @, as does @atchar{}. -\def\@{\char64 } -\let\atchar=\@ - -% @{ @} @lbracechar{} @rbracechar{} all generate brace characters. -% Unless we're in typewriter, use \ecfont because the CM text fonts do -% not have braces, and we don't want to switch into math. -\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}} -\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}} -\let\{=\mylbrace \let\lbracechar=\{ -\let\}=\myrbrace \let\rbracechar=\} -\begingroup - % Definitions to produce \{ and \} commands for indices, - % and @{ and @} for the aux/toc files. - \catcode`\{ = \other \catcode`\} = \other - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\! = 0 \catcode`\\ = \other - !gdef!lbracecmd[\{]% - !gdef!rbracecmd[\}]% - !gdef!lbraceatcmd[@{]% - !gdef!rbraceatcmd[@}]% -!endgroup - -% @comma{} to avoid , parsing problems. -\let\comma = , - -% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent -% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. -\let\, = \ptexc -\let\dotaccent = \ptexdot -\def\ringaccent#1{{\accent23 #1}} -\let\tieaccent = \ptext -\let\ubaraccent = \ptexb -\let\udotaccent = \d - -% Other special characters: @questiondown @exclamdown @ordf @ordm -% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. -\def\questiondown{?`} -\def\exclamdown{!`} -\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} -\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} - -% Dotless i and dotless j, used for accents. -\def\imacro{i} -\def\jmacro{j} -\def\dotless#1{% - \def\temp{#1}% - \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi - \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi - \else \errmessage{@dotless can be used only with i or j}% - \fi\fi -} - -% The \TeX{} logo, as in plain, but resetting the spacing so that a -% period following counts as ending a sentence. (Idea found in latex.) -% -\edef\TeX{\TeX \spacefactor=1000 } - -% @LaTeX{} logo. Not quite the same results as the definition in -% latex.ltx, since we use a different font for the raised A; it's most -% convenient for us to use an explicitly smaller font, rather than using -% the \scriptstyle font (since we don't reset \scriptstyle and -% \scriptscriptstyle). -% -\def\LaTeX{% - L\kern-.36em - {\setbox0=\hbox{T}% - \vbox to \ht0{\hbox{% - \ifx\textnominalsize\xwordpt - % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX. - % Revert to plain's \scriptsize, which is 7pt. - \count255=\the\fam $\fam\count255 \scriptstyle A$% - \else - % For 11pt, we can use our lllsize. - \selectfonts\lllsize A% - \fi - }% - \vss - }}% - \kern-.15em - \TeX -} - -% Some math mode symbols. -\def\bullet{$\ptexbullet$} -\def\geq{\ifmmode \ge\else $\ge$\fi} -\def\leq{\ifmmode \le\else $\le$\fi} -\def\minus{\ifmmode -\else $-$\fi} - -% @dots{} outputs an ellipsis using the current font. -% We do .5em per period so that it has the same spacing in the cm -% typewriter fonts as three actual period characters; on the other hand, -% in other typewriter fonts three periods are wider than 1.5em. So do -% whichever is larger. -% -\def\dots{% - \leavevmode - \setbox0=\hbox{...}% get width of three periods - \ifdim\wd0 > 1.5em - \dimen0 = \wd0 - \else - \dimen0 = 1.5em - \fi - \hbox to \dimen0{% - \hskip 0pt plus.25fil - .\hskip 0pt plus1fil - .\hskip 0pt plus1fil - .\hskip 0pt plus.5fil - }% -} - -% @enddots{} is an end-of-sentence ellipsis. -% -\def\enddots{% - \dots - \spacefactor=\endofsentencespacefactor -} - -% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. -% -% Since these characters are used in examples, they should be an even number of -% \tt widths. Each \tt character is 1en, so two makes it 1em. -% -\def\point{$\star$} -\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} -\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} -\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} -\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} -\def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} - -% The @error{} command. -% Adapted from the TeXbook's \boxit. -% -\newbox\errorbox -% -{\tentt \global\dimen0 = 3em}% Width of the box. -\dimen2 = .55pt % Thickness of rules -% The text. (`r' is open on the right, `e' somewhat less so on the left.) -\setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} -% -\setbox\errorbox=\hbox to \dimen0{\hfil - \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. - \advance\hsize by -2\dimen2 % Rules. - \vbox{% - \hrule height\dimen2 - \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. - \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. - \kern3pt\vrule width\dimen2}% Space to right. - \hrule height\dimen2} - \hfil} -% -\def\error{\leavevmode\lower.7ex\copy\errorbox} - -% @pounds{} is a sterling sign, which Knuth put in the CM italic font. -% -\def\pounds{{\it\$}} - -% @euro{} comes from a separate font, depending on the current style. -% We use the free feym* fonts from the eurosym package by Henrik -% Theiling, which support regular, slanted, bold and bold slanted (and -% "outlined" (blackboard board, sort of) versions, which we don't need). -% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. -% -% Although only regular is the truly official Euro symbol, we ignore -% that. The Euro is designed to be slightly taller than the regular -% font height. -% -% feymr - regular -% feymo - slanted -% feybr - bold -% feybo - bold slanted -% -% There is no good (free) typewriter version, to my knowledge. -% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. -% Hmm. -% -% Also doesn't work in math. Do we need to do math with euro symbols? -% Hope not. -% -% -\def\euro{{\eurofont e}} -\def\eurofont{% - % We set the font at each command, rather than predefining it in - % \textfonts and the other font-switching commands, so that - % installations which never need the symbol don't have to have the - % font installed. - % - % There is only one designed size (nominal 10pt), so we always scale - % that to the current nominal size. - % - % By the way, simply using "at 1em" works for cmr10 and the like, but - % does not work for cmbx10 and other extended/shrunken fonts. - % - \def\eurosize{\csname\curfontsize nominalsize\endcsname}% - % - \ifx\curfontstyle\bfstylename - % bold: - \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize - \else - % regular: - \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize - \fi - \thiseurofont -} - -% Glyphs from the EC fonts. We don't use \let for the aliases, because -% sometimes we redefine the original macro, and the alias should reflect -% the redefinition. -% -% Use LaTeX names for the Icelandic letters. -\def\DH{{\ecfont \char"D0}} % Eth -\def\dh{{\ecfont \char"F0}} % eth -\def\TH{{\ecfont \char"DE}} % Thorn -\def\th{{\ecfont \char"FE}} % thorn -% -\def\guillemetleft{{\ecfont \char"13}} -\def\guillemotleft{\guillemetleft} -\def\guillemetright{{\ecfont \char"14}} -\def\guillemotright{\guillemetright} -\def\guilsinglleft{{\ecfont \char"0E}} -\def\guilsinglright{{\ecfont \char"0F}} -\def\quotedblbase{{\ecfont \char"12}} -\def\quotesinglbase{{\ecfont \char"0D}} -% -% This positioning is not perfect (see the ogonek LaTeX package), but -% we have the precomposed glyphs for the most common cases. We put the -% tests to use those glyphs in the single \ogonek macro so we have fewer -% dummy definitions to worry about for index entries, etc. -% -% ogonek is also used with other letters in Lithuanian (IOU), but using -% the precomposed glyphs for those is not so easy since they aren't in -% the same EC font. -\def\ogonek#1{{% - \def\temp{#1}% - \ifx\temp\macrocharA\Aogonek - \else\ifx\temp\macrochara\aogonek - \else\ifx\temp\macrocharE\Eogonek - \else\ifx\temp\macrochare\eogonek - \else - \ecfont \setbox0=\hbox{#1}% - \ifdim\ht0=1ex\accent"0C #1% - \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% - \fi - \fi\fi\fi\fi - }% -} -\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} -\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} -\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} -\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} -% -% Use the ec* fonts (cm-super in outline format) for non-CM glyphs. -\def\ecfont{% - % We can't distinguish serif/sans and italic/slanted, but this - % is used for crude hacks anyway (like adding French and German - % quotes to documents typeset with CM, where we lose kerning), so - % hopefully nobody will notice/care. - \edef\ecsize{\csname\curfontsize ecsize\endcsname}% - \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% - \ifmonospace - % typewriter: - \font\thisecfont = ectt\ecsize \space at \nominalsize - \else - \ifx\curfontstyle\bfstylename - % bold: - \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize - \else - % regular: - \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize - \fi - \fi - \thisecfont -} - -% @registeredsymbol - R in a circle. The font for the R should really -% be smaller yet, but lllsize is the best we can do for now. -% Adapted from the plain.tex definition of \copyright. -% -\def\registeredsymbol{% - $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% - \hfil\crcr\Orb}}% - }$% -} - -% @textdegree - the normal degrees sign. -% -\def\textdegree{$^\circ$} - -% Laurent Siebenmann reports \Orb undefined with: -% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 -% so we'll define it if necessary. -% -\ifx\Orb\thisisundefined -\def\Orb{\mathhexbox20D} -\fi - -% Quotes. -\chardef\quotedblleft="5C -\chardef\quotedblright=`\" -\chardef\quoteleft=`\` -\chardef\quoteright=`\' - - -\message{page headings,} - -\newskip\titlepagetopglue \titlepagetopglue = 1.5in -\newskip\titlepagebottomglue \titlepagebottomglue = 2pc - -% First the title page. Must do @settitle before @titlepage. -\newif\ifseenauthor -\newif\iffinishedtitlepage - -% Do an implicit @contents or @shortcontents after @end titlepage if the -% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. -% -\newif\ifsetcontentsaftertitlepage - \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue -\newif\ifsetshortcontentsaftertitlepage - \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue - -\parseargdef\shorttitlepage{% - \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% - \endgroup\page\hbox{}\page} - -\envdef\titlepage{% - % Open one extra group, as we want to close it in the middle of \Etitlepage. - \begingroup - \parindent=0pt \textfonts - % Leave some space at the very top of the page. - \vglue\titlepagetopglue - % No rule at page bottom unless we print one at the top with @title. - \finishedtitlepagetrue - % - % Most title ``pages'' are actually two pages long, with space - % at the top of the second. We don't want the ragged left on the second. - \let\oldpage = \page - \def\page{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - \let\page = \oldpage - \page - \null - }% -} - -\def\Etitlepage{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - % It is important to do the page break before ending the group, - % because the headline and footline are only empty inside the group. - % If we use the new definition of \page, we always get a blank page - % after the title page, which we certainly don't want. - \oldpage - \endgroup - % - % Need this before the \...aftertitlepage checks so that if they are - % in effect the toc pages will come out with page numbers. - \HEADINGSon - % - % If they want short, they certainly want long too. - \ifsetshortcontentsaftertitlepage - \shortcontents - \contents - \global\let\shortcontents = \relax - \global\let\contents = \relax - \fi - % - \ifsetcontentsaftertitlepage - \contents - \global\let\contents = \relax - \global\let\shortcontents = \relax - \fi -} - -\def\finishtitlepage{% - \vskip4pt \hrule height 2pt width \hsize - \vskip\titlepagebottomglue - \finishedtitlepagetrue -} - -% Settings used for typesetting titles: no hyphenation, no indentation, -% don't worry much about spacing, ragged right. This should be used -% inside a \vbox, and fonts need to be set appropriately first. Because -% it is always used for titles, nothing else, we call \rmisbold. \par -% should be specified before the end of the \vbox, since a vbox is a group. -% -\def\raggedtitlesettings{% - \rmisbold - \hyphenpenalty=10000 - \parindent=0pt - \tolerance=5000 - \ptexraggedright -} - -% Macros to be used within @titlepage: - -\let\subtitlerm=\tenrm -\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} - -\parseargdef\title{% - \checkenv\titlepage - \vbox{\titlefonts \raggedtitlesettings #1\par}% - % print a rule at the page bottom also. - \finishedtitlepagefalse - \vskip4pt \hrule height 4pt width \hsize \vskip4pt -} - -\parseargdef\subtitle{% - \checkenv\titlepage - {\subtitlefont \rightline{#1}}% -} - -% @author should come last, but may come many times. -% It can also be used inside @quotation. -% -\parseargdef\author{% - \def\temp{\quotation}% - \ifx\thisenv\temp - \def\quotationauthor{#1}% printed in \Equotation. - \else - \checkenv\titlepage - \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi - {\secfonts\rmisbold \leftline{#1}}% - \fi -} - - -% Set up page headings and footings. - -\let\thispage=\folio - -\newtoks\evenheadline % headline on even pages -\newtoks\oddheadline % headline on odd pages -\newtoks\evenfootline % footline on even pages -\newtoks\oddfootline % footline on odd pages - -% Now make TeX use those variables -\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline - \else \the\evenheadline \fi}} -\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline - \else \the\evenfootline \fi}\HEADINGShook} -\let\HEADINGShook=\relax - -% Commands to set those variables. -% For example, this is what @headings on does -% @evenheading @thistitle|@thispage|@thischapter -% @oddheading @thischapter|@thispage|@thistitle -% @evenfooting @thisfile|| -% @oddfooting ||@thisfile - - -\def\evenheading{\parsearg\evenheadingxxx} -\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} -\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% -\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\def\oddheading{\parsearg\oddheadingxxx} -\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} -\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% -\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% - -\def\evenfooting{\parsearg\evenfootingxxx} -\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} -\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% -\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\def\oddfooting{\parsearg\oddfootingxxx} -\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} -\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% - \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% - % - % Leave some space for the footline. Hopefully ok to assume - % @evenfooting will not be used by itself. - \global\advance\pageheight by -12pt - \global\advance\vsize by -12pt -} - -\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} - -% @evenheadingmarks top \thischapter <- chapter at the top of a page -% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page -% -% The same set of arguments for: -% -% @oddheadingmarks -% @evenfootingmarks -% @oddfootingmarks -% @everyheadingmarks -% @everyfootingmarks - -\def\evenheadingmarks{\headingmarks{even}{heading}} -\def\oddheadingmarks{\headingmarks{odd}{heading}} -\def\evenfootingmarks{\headingmarks{even}{footing}} -\def\oddfootingmarks{\headingmarks{odd}{footing}} -\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} - \headingmarks{odd}{heading}{#1} } -\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} - \headingmarks{odd}{footing}{#1} } -% #1 = even/odd, #2 = heading/footing, #3 = top/bottom. -\def\headingmarks#1#2#3 {% - \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname - \global\expandafter\let\csname get#1#2marks\endcsname \temp -} - -\everyheadingmarks bottom -\everyfootingmarks bottom - -% @headings double turns headings on for double-sided printing. -% @headings single turns headings on for single-sided printing. -% @headings off turns them off. -% @headings on same as @headings double, retained for compatibility. -% @headings after turns on double-sided headings after this page. -% @headings doubleafter turns on double-sided headings after this page. -% @headings singleafter turns on single-sided headings after this page. -% By default, they are off at the start of a document, -% and turned `on' after @end titlepage. - -\def\headings #1 {\csname HEADINGS#1\endcsname} - -\def\headingsoff{% non-global headings elimination - \evenheadline={\hfil}\evenfootline={\hfil}% - \oddheadline={\hfil}\oddfootline={\hfil}% -} - -\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting -\HEADINGSoff % it's the default - -% When we turn headings on, set the page number to 1. -% For double-sided printing, put current file name in lower left corner, -% chapter name on inside top of right hand pages, document -% title on inside top of left hand pages, and page numbers on outside top -% edge of all pages. -\def\HEADINGSdouble{% -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} -\let\contentsalignmacro = \chappager - -% For single-sided printing, chapter title goes across top left of page, -% page number on top right. -\def\HEADINGSsingle{% -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} -\def\HEADINGSon{\HEADINGSdouble} - -\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} -\let\HEADINGSdoubleafter=\HEADINGSafter -\def\HEADINGSdoublex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} - -\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} -\def\HEADINGSsinglex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} - -% Subroutines used in generating headings -% This produces Day Month Year style of output. -% Only define if not already defined, in case a txi-??.tex file has set -% up a different format (e.g., txi-cs.tex does this). -\ifx\today\thisisundefined -\def\today{% - \number\day\space - \ifcase\month - \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr - \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug - \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec - \fi - \space\number\year} -\fi - -% @settitle line... specifies the title of the document, for headings. -% It generates no output of its own. -\def\thistitle{\putwordNoTitle} -\def\settitle{\parsearg{\gdef\thistitle}} - - -\message{tables,} -% Tables -- @table, @ftable, @vtable, @item(x). - -% default indentation of table text -\newdimen\tableindent \tableindent=.8in -% default indentation of @itemize and @enumerate text -\newdimen\itemindent \itemindent=.3in -% margin between end of table item and start of table text. -\newdimen\itemmargin \itemmargin=.1in - -% used internally for \itemindent minus \itemmargin -\newdimen\itemmax - -% Note @table, @ftable, and @vtable define @item, @itemx, etc., with -% these defs. -% They also define \itemindex -% to index the item name in whatever manner is desired (perhaps none). - -\newif\ifitemxneedsnegativevskip - -\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} - -\def\internalBitem{\smallbreak \parsearg\itemzzz} -\def\internalBitemx{\itemxpar \parsearg\itemzzz} - -\def\itemzzz #1{\begingroup % - \advance\hsize by -\rightskip - \advance\hsize by -\tableindent - \setbox0=\hbox{\itemindicate{#1}}% - \itemindex{#1}% - \nobreak % This prevents a break before @itemx. - % - % If the item text does not fit in the space we have, put it on a line - % by itself, and do not allow a page break either before or after that - % line. We do not start a paragraph here because then if the next - % command is, e.g., @kindex, the whatsit would get put into the - % horizontal list on a line by itself, resulting in extra blank space. - \ifdim \wd0>\itemmax - % - % Make this a paragraph so we get the \parskip glue and wrapping, - % but leave it ragged-right. - \begingroup - \advance\leftskip by-\tableindent - \advance\hsize by\tableindent - \advance\rightskip by0pt plus1fil\relax - \leavevmode\unhbox0\par - \endgroup - % - % We're going to be starting a paragraph, but we don't want the - % \parskip glue -- logically it's part of the @item we just started. - \nobreak \vskip-\parskip - % - % Stop a page break at the \parskip glue coming up. However, if - % what follows is an environment such as @example, there will be no - % \parskip glue; then the negative vskip we just inserted would - % cause the example and the item to crash together. So we use this - % bizarre value of 10001 as a signal to \aboveenvbreak to insert - % \parskip glue after all. Section titles are handled this way also. - % - \penalty 10001 - \endgroup - \itemxneedsnegativevskipfalse - \else - % The item text fits into the space. Start a paragraph, so that the - % following text (if any) will end up on the same line. - \noindent - % Do this with kerns and \unhbox so that if there is a footnote in - % the item text, it can migrate to the main vertical list and - % eventually be printed. - \nobreak\kern-\tableindent - \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 - \unhbox0 - \nobreak\kern\dimen0 - \endgroup - \itemxneedsnegativevskiptrue - \fi -} - -\def\item{\errmessage{@item while not in a list environment}} -\def\itemx{\errmessage{@itemx while not in a list environment}} - -% @table, @ftable, @vtable. -\envdef\table{% - \let\itemindex\gobble - \tablecheck{table}% -} -\envdef\ftable{% - \def\itemindex ##1{\doind {fn}{\code{##1}}}% - \tablecheck{ftable}% -} -\envdef\vtable{% - \def\itemindex ##1{\doind {vr}{\code{##1}}}% - \tablecheck{vtable}% -} -\def\tablecheck#1{% - \ifnum \the\catcode`\^^M=\active - \endgroup - \errmessage{This command won't work in this context; perhaps the problem is - that we are \inenvironment\thisenv}% - \def\next{\doignore{#1}}% - \else - \let\next\tablex - \fi - \next -} -\def\tablex#1{% - \def\itemindicate{#1}% - \parsearg\tabley -} -\def\tabley#1{% - {% - \makevalueexpandable - \edef\temp{\noexpand\tablez #1\space\space\space}% - \expandafter - }\temp \endtablez -} -\def\tablez #1 #2 #3 #4\endtablez{% - \aboveenvbreak - \ifnum 0#1>0 \advance \leftskip by #1\mil \fi - \ifnum 0#2>0 \tableindent=#2\mil \fi - \ifnum 0#3>0 \advance \rightskip by #3\mil \fi - \itemmax=\tableindent - \advance \itemmax by -\itemmargin - \advance \leftskip by \tableindent - \exdentamount=\tableindent - \parindent = 0pt - \parskip = \smallskipamount - \ifdim \parskip=0pt \parskip=2pt \fi - \let\item = \internalBitem - \let\itemx = \internalBitemx -} -\def\Etable{\endgraf\afterenvbreak} -\let\Eftable\Etable -\let\Evtable\Etable -\let\Eitemize\Etable -\let\Eenumerate\Etable - -% This is the counter used by @enumerate, which is really @itemize - -\newcount \itemno - -\envdef\itemize{\parsearg\doitemize} - -\def\doitemize#1{% - \aboveenvbreak - \itemmax=\itemindent - \advance\itemmax by -\itemmargin - \advance\leftskip by \itemindent - \exdentamount=\itemindent - \parindent=0pt - \parskip=\smallskipamount - \ifdim\parskip=0pt \parskip=2pt \fi - % - % Try typesetting the item mark that if the document erroneously says - % something like @itemize @samp (intending @table), there's an error - % right away at the @itemize. It's not the best error message in the - % world, but it's better than leaving it to the @item. This means if - % the user wants an empty mark, they have to say @w{} not just @w. - \def\itemcontents{#1}% - \setbox0 = \hbox{\itemcontents}% - % - % @itemize with no arg is equivalent to @itemize @bullet. - \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi - % - \let\item=\itemizeitem -} - -% Definition of @item while inside @itemize and @enumerate. -% -\def\itemizeitem{% - \advance\itemno by 1 % for enumerations - {\let\par=\endgraf \smallbreak}% reasonable place to break - {% - % If the document has an @itemize directly after a section title, a - % \nobreak will be last on the list, and \sectionheading will have - % done a \vskip-\parskip. In that case, we don't want to zero - % parskip, or the item text will crash with the heading. On the - % other hand, when there is normal text preceding the item (as there - % usually is), we do want to zero parskip, or there would be too much - % space. In that case, we won't have a \nobreak before. At least - % that's the theory. - \ifnum\lastpenalty<10000 \parskip=0in \fi - \noindent - \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% - % - \vadjust{\penalty 1200}}% not good to break after first line of item. - \flushcr -} - -% \splitoff TOKENS\endmark defines \first to be the first token in -% TOKENS, and \rest to be the remainder. -% -\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% - -% Allow an optional argument of an uppercase letter, lowercase letter, -% or number, to specify the first label in the enumerated list. No -% argument is the same as `1'. -% -\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} -\def\enumeratey #1 #2\endenumeratey{% - % If we were given no argument, pretend we were given `1'. - \def\thearg{#1}% - \ifx\thearg\empty \def\thearg{1}\fi - % - % Detect if the argument is a single token. If so, it might be a - % letter. Otherwise, the only valid thing it can be is a number. - % (We will always have one token, because of the test we just made. - % This is a good thing, since \splitoff doesn't work given nothing at - % all -- the first parameter is undelimited.) - \expandafter\splitoff\thearg\endmark - \ifx\rest\empty - % Only one token in the argument. It could still be anything. - % A ``lowercase letter'' is one whose \lccode is nonzero. - % An ``uppercase letter'' is one whose \lccode is both nonzero, and - % not equal to itself. - % Otherwise, we assume it's a number. - % - % We need the \relax at the end of the \ifnum lines to stop TeX from - % continuing to look for a . - % - \ifnum\lccode\expandafter`\thearg=0\relax - \numericenumerate % a number (we hope) - \else - % It's a letter. - \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax - \lowercaseenumerate % lowercase letter - \else - \uppercaseenumerate % uppercase letter - \fi - \fi - \else - % Multiple tokens in the argument. We hope it's a number. - \numericenumerate - \fi -} - -% An @enumerate whose labels are integers. The starting integer is -% given in \thearg. -% -\def\numericenumerate{% - \itemno = \thearg - \startenumeration{\the\itemno}% -} - -% The starting (lowercase) letter is in \thearg. -\def\lowercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more lowercase letters in @enumerate; get a bigger - alphabet}% - \fi - \char\lccode\itemno - }% -} - -% The starting (uppercase) letter is in \thearg. -\def\uppercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more uppercase letters in @enumerate; get a bigger - alphabet} - \fi - \char\uccode\itemno - }% -} - -% Call \doitemize, adding a period to the first argument and supplying the -% common last two arguments. Also subtract one from the initial value in -% \itemno, since @item increments \itemno. -% -\def\startenumeration#1{% - \advance\itemno by -1 - \doitemize{#1.}\flushcr -} - -% @alphaenumerate and @capsenumerate are abbreviations for giving an arg -% to @enumerate. -% -\def\alphaenumerate{\enumerate{a}} -\def\capsenumerate{\enumerate{A}} -\def\Ealphaenumerate{\Eenumerate} -\def\Ecapsenumerate{\Eenumerate} - - -% @multitable macros -% Amy Hendrickson, 8/18/94, 3/6/96 -% -% @multitable ... @end multitable will make as many columns as desired. -% Contents of each column will wrap at width given in preamble. Width -% can be specified either with sample text given in a template line, -% or in percent of \hsize, the current width of text on page. - -% Table can continue over pages but will only break between lines. - -% To make preamble: -% -% Either define widths of columns in terms of percent of \hsize: -% @multitable @columnfractions .25 .3 .45 -% @item ... -% -% Numbers following @columnfractions are the percent of the total -% current hsize to be used for each column. You may use as many -% columns as desired. - - -% Or use a template: -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item ... -% using the widest term desired in each column. - -% Each new table line starts with @item, each subsequent new column -% starts with @tab. Empty columns may be produced by supplying @tab's -% with nothing between them for as many times as empty columns are needed, -% ie, @tab@tab@tab will produce two empty columns. - -% @item, @tab do not need to be on their own lines, but it will not hurt -% if they are. - -% Sample multitable: - -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item first col stuff @tab second col stuff @tab third col -% @item -% first col stuff -% @tab -% second col stuff -% @tab -% third col -% @item first col stuff @tab second col stuff -% @tab Many paragraphs of text may be used in any column. -% -% They will wrap at the width determined by the template. -% @item@tab@tab This will be in third column. -% @end multitable - -% Default dimensions may be reset by user. -% @multitableparskip is vertical space between paragraphs in table. -% @multitableparindent is paragraph indent in table. -% @multitablecolmargin is horizontal space to be left between columns. -% @multitablelinespace is space to leave between table items, baseline -% to baseline. -% 0pt means it depends on current normal line spacing. -% -\newskip\multitableparskip -\newskip\multitableparindent -\newdimen\multitablecolspace -\newskip\multitablelinespace -\multitableparskip=0pt -\multitableparindent=6pt -\multitablecolspace=12pt -\multitablelinespace=0pt - -% Macros used to set up halign preamble: -% -\let\endsetuptable\relax -\def\xendsetuptable{\endsetuptable} -\let\columnfractions\relax -\def\xcolumnfractions{\columnfractions} -\newif\ifsetpercent - -% #1 is the @columnfraction, usually a decimal number like .5, but might -% be just 1. We just use it, whatever it is. -% -\def\pickupwholefraction#1 {% - \global\advance\colcount by 1 - \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% - \setuptable -} - -\newcount\colcount -\def\setuptable#1{% - \def\firstarg{#1}% - \ifx\firstarg\xendsetuptable - \let\go = \relax - \else - \ifx\firstarg\xcolumnfractions - \global\setpercenttrue - \else - \ifsetpercent - \let\go\pickupwholefraction - \else - \global\advance\colcount by 1 - \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a - % separator; typically that is always in the input, anyway. - \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% - \fi - \fi - \ifx\go\pickupwholefraction - % Put the argument back for the \pickupwholefraction call, so - % we'll always have a period there to be parsed. - \def\go{\pickupwholefraction#1}% - \else - \let\go = \setuptable - \fi% - \fi - \go -} - -% multitable-only commands. -% -% @headitem starts a heading row, which we typeset in bold. -% Assignments have to be global since we are inside the implicit group -% of an alignment entry. \everycr resets \everytab so we don't have to -% undo it ourselves. -\def\headitemfont{\b}% for people to use in the template row; not changeable -\def\headitem{% - \checkenv\multitable - \crcr - \global\everytab={\bf}% can't use \headitemfont since the parsing differs - \the\everytab % for the first item -}% -% -% A \tab used to include \hskip1sp. But then the space in a template -% line is not enough. That is bad. So let's go back to just `&' until -% we again encounter the problem the 1sp was intended to solve. -% --karl, nathan@acm.org, 20apr99. -\def\tab{\checkenv\multitable &\the\everytab}% - -% @multitable ... @end multitable definitions: -% -\newtoks\everytab % insert after every tab. -% -\envdef\multitable{% - \vskip\parskip - \startsavinginserts - % - % @item within a multitable starts a normal row. - % We use \def instead of \let so that if one of the multitable entries - % contains an @itemize, we don't choke on the \item (seen as \crcr aka - % \endtemplate) expanding \doitemize. - \def\item{\crcr}% - % - \tolerance=9500 - \hbadness=9500 - \setmultitablespacing - \parskip=\multitableparskip - \parindent=\multitableparindent - \overfullrule=0pt - \global\colcount=0 - % - \everycr = {% - \noalign{% - \global\everytab={}% - \global\colcount=0 % Reset the column counter. - % Check for saved footnotes, etc. - \checkinserts - % Keeps underfull box messages off when table breaks over pages. - %\filbreak - % Maybe so, but it also creates really weird page breaks when the - % table breaks over pages. Wouldn't \vfil be better? Wait until the - % problem manifests itself, so it can be fixed for real --karl. - }% - }% - % - \parsearg\domultitable -} -\def\domultitable#1{% - % To parse everything between @multitable and @item: - \setuptable#1 \endsetuptable - % - % This preamble sets up a generic column definition, which will - % be used as many times as user calls for columns. - % \vtop will set a single line and will also let text wrap and - % continue for many paragraphs if desired. - \halign\bgroup &% - \global\advance\colcount by 1 - \multistrut - \vtop{% - % Use the current \colcount to find the correct column width: - \hsize=\expandafter\csname col\the\colcount\endcsname - % - % In order to keep entries from bumping into each other - % we will add a \leftskip of \multitablecolspace to all columns after - % the first one. - % - % If a template has been used, we will add \multitablecolspace - % to the width of each template entry. - % - % If the user has set preamble in terms of percent of \hsize we will - % use that dimension as the width of the column, and the \leftskip - % will keep entries from bumping into each other. Table will start at - % left margin and final column will justify at right margin. - % - % Make sure we don't inherit \rightskip from the outer environment. - \rightskip=0pt - \ifnum\colcount=1 - % The first column will be indented with the surrounding text. - \advance\hsize by\leftskip - \else - \ifsetpercent \else - % If user has not set preamble in terms of percent of \hsize - % we will advance \hsize by \multitablecolspace. - \advance\hsize by \multitablecolspace - \fi - % In either case we will make \leftskip=\multitablecolspace: - \leftskip=\multitablecolspace - \fi - % Ignoring space at the beginning and end avoids an occasional spurious - % blank line, when TeX decides to break the line at the space before the - % box from the multistrut, so the strut ends up on a line by itself. - % For example: - % @multitable @columnfractions .11 .89 - % @item @code{#} - % @tab Legal holiday which is valid in major parts of the whole country. - % Is automatically provided with highlighting sequences respectively - % marking characters. - \noindent\ignorespaces##\unskip\multistrut - }\cr -} -\def\Emultitable{% - \crcr - \egroup % end the \halign - \global\setpercentfalse -} - -\def\setmultitablespacing{% - \def\multistrut{\strut}% just use the standard line spacing - % - % Compute \multitablelinespace (if not defined by user) for use in - % \multitableparskip calculation. We used define \multistrut based on - % this, but (ironically) that caused the spacing to be off. - % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. -\ifdim\multitablelinespace=0pt -\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip -\global\advance\multitablelinespace by-\ht0 -\fi -% Test to see if parskip is larger than space between lines of -% table. If not, do nothing. -% If so, set to same dimension as multitablelinespace. -\ifdim\multitableparskip>\multitablelinespace -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller - % than skip between lines in the table. -\fi% -\ifdim\multitableparskip=0pt -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller - % than skip between lines in the table. -\fi} - - -\message{conditionals,} - -% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, -% @ifnotxml always succeed. They currently do nothing; we don't -% attempt to check whether the conditionals are properly nested. But we -% have to remember that they are conditionals, so that @end doesn't -% attempt to close an environment group. -% -\def\makecond#1{% - \expandafter\let\csname #1\endcsname = \relax - \expandafter\let\csname iscond.#1\endcsname = 1 -} -\makecond{iftex} -\makecond{ifnotdocbook} -\makecond{ifnothtml} -\makecond{ifnotinfo} -\makecond{ifnotplaintext} -\makecond{ifnotxml} - -% Ignore @ignore, @ifhtml, @ifinfo, and the like. -% -\def\direntry{\doignore{direntry}} -\def\documentdescription{\doignore{documentdescription}} -\def\docbook{\doignore{docbook}} -\def\html{\doignore{html}} -\def\ifdocbook{\doignore{ifdocbook}} -\def\ifhtml{\doignore{ifhtml}} -\def\ifinfo{\doignore{ifinfo}} -\def\ifnottex{\doignore{ifnottex}} -\def\ifplaintext{\doignore{ifplaintext}} -\def\ifxml{\doignore{ifxml}} -\def\ignore{\doignore{ignore}} -\def\menu{\doignore{menu}} -\def\xml{\doignore{xml}} - -% Ignore text until a line `@end #1', keeping track of nested conditionals. -% -% A count to remember the depth of nesting. -\newcount\doignorecount - -\def\doignore#1{\begingroup - % Scan in ``verbatim'' mode: - \obeylines - \catcode`\@ = \other - \catcode`\{ = \other - \catcode`\} = \other - % - % Make sure that spaces turn into tokens that match what \doignoretext wants. - \spaceisspace - % - % Count number of #1's that we've seen. - \doignorecount = 0 - % - % Swallow text until we reach the matching `@end #1'. - \dodoignore{#1}% -} - -{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. - \obeylines % - % - \gdef\dodoignore#1{% - % #1 contains the command name as a string, e.g., `ifinfo'. - % - % Define a command to find the next `@end #1'. - \long\def\doignoretext##1^^M@end #1{% - \doignoretextyyy##1^^M@#1\_STOP_}% - % - % And this command to find another #1 command, at the beginning of a - % line. (Otherwise, we would consider a line `@c @ifset', for - % example, to count as an @ifset for nesting.) - \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% - % - % And now expand that command. - \doignoretext ^^M% - }% -} - -\def\doignoreyyy#1{% - \def\temp{#1}% - \ifx\temp\empty % Nothing found. - \let\next\doignoretextzzz - \else % Found a nested condition, ... - \advance\doignorecount by 1 - \let\next\doignoretextyyy % ..., look for another. - % If we're here, #1 ends with ^^M\ifinfo (for example). - \fi - \next #1% the token \_STOP_ is present just after this macro. -} - -% We have to swallow the remaining "\_STOP_". -% -\def\doignoretextzzz#1{% - \ifnum\doignorecount = 0 % We have just found the outermost @end. - \let\next\enddoignore - \else % Still inside a nested condition. - \advance\doignorecount by -1 - \let\next\doignoretext % Look for the next @end. - \fi - \next -} - -% Finish off ignored text. -{ \obeylines% - % Ignore anything after the last `@end #1'; this matters in verbatim - % environments, where otherwise the newline after an ignored conditional - % would result in a blank line in the output. - \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% -} - - -% @set VAR sets the variable VAR to an empty value. -% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. -% -% Since we want to separate VAR from REST-OF-LINE (which might be -% empty), we can't just use \parsearg; we have to insert a space of our -% own to delimit the rest of the line, and then take it out again if we -% didn't need it. -% We rely on the fact that \parsearg sets \catcode`\ =10. -% -\parseargdef\set{\setyyy#1 \endsetyyy} -\def\setyyy#1 #2\endsetyyy{% - {% - \makevalueexpandable - \def\temp{#2}% - \edef\next{\gdef\makecsname{SET#1}}% - \ifx\temp\empty - \next{}% - \else - \setzzz#2\endsetzzz - \fi - }% -} -% Remove the trailing space \setxxx inserted. -\def\setzzz#1 \endsetzzz{\next{#1}} - -% @clear VAR clears (i.e., unsets) the variable VAR. -% -\parseargdef\clear{% - {% - \makevalueexpandable - \global\expandafter\let\csname SET#1\endcsname=\relax - }% -} - -% @value{foo} gets the text saved in variable foo. -\def\value{\begingroup\makevalueexpandable\valuexxx} -\def\valuexxx#1{\expandablevalue{#1}\endgroup} -{ - \catcode`\- = \active \catcode`\_ = \active - % - \gdef\makevalueexpandable{% - \let\value = \expandablevalue - % We don't want these characters active, ... - \catcode`\-=\other \catcode`\_=\other - % ..., but we might end up with active ones in the argument if - % we're called from @code, as @code{@value{foo-bar_}}, though. - % So \let them to their normal equivalents. - \let-\normaldash \let_\normalunderscore - } -} - -% We have this subroutine so that we can handle at least some @value's -% properly in indexes (we call \makevalueexpandable in \indexdummies). -% The command has to be fully expandable (if the variable is set), since -% the result winds up in the index file. This means that if the -% variable's value contains other Texinfo commands, it's almost certain -% it will fail (although perhaps we could fix that with sufficient work -% to do a one-level expansion on the result, instead of complete). -% -\def\expandablevalue#1{% - \expandafter\ifx\csname SET#1\endcsname\relax - {[No value for ``#1'']}% - \message{Variable `#1', used in @value, is not set.}% - \else - \csname SET#1\endcsname - \fi -} - -% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined -% with @set. -% -% To get special treatment of `@end ifset,' call \makeond and the redefine. -% -\makecond{ifset} -\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} -\def\doifset#1#2{% - {% - \makevalueexpandable - \let\next=\empty - \expandafter\ifx\csname SET#2\endcsname\relax - #1% If not set, redefine \next. - \fi - \expandafter - }\next -} -\def\ifsetfail{\doignore{ifset}} - -% @ifclear VAR ... @end executes the `...' iff VAR has never been -% defined with @set, or has been undefined with @clear. -% -% The `\else' inside the `\doifset' parameter is a trick to reuse the -% above code: if the variable is not set, do nothing, if it is set, -% then redefine \next to \ifclearfail. -% -\makecond{ifclear} -\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} -\def\ifclearfail{\doignore{ifclear}} - -% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written -% without the @) is in fact defined. We can only feasibly check at the -% TeX level, so something like `mathcode' is going to considered -% defined even though it is not a Texinfo command. -% -\makecond{ifcommanddefined} -\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} -% -\def\doifcmddefined#1#2{{% - \makevalueexpandable - \let\next=\empty - \expandafter\ifx\csname #2\endcsname\relax - #1% If not defined, \let\next as above. - \fi - \expandafter - }\next -} -\def\ifcmddefinedfail{\doignore{ifcommanddefined}} - -% @ifcommandnotdefined CMD ... handled similar to @ifclear above. -\makecond{ifcommandnotdefined} -\def\ifcommandnotdefined{% - \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} -\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} - -% Set the `txicommandconditionals' variable, so documents have a way to -% test if the @ifcommand...defined conditionals are available. -\set txicommandconditionals - -% @dircategory CATEGORY -- specify a category of the dir file -% which this file should belong to. Ignore this in TeX. -\let\dircategory=\comment - -% @defininfoenclose. -\let\definfoenclose=\comment - - -\message{indexing,} -% Index generation facilities - -% Define \newwrite to be identical to plain tex's \newwrite -% except not \outer, so it can be used within macros and \if's. -\edef\newwrite{\makecsname{ptexnewwrite}} - -% \newindex {foo} defines an index named foo. -% It automatically defines \fooindex such that -% \fooindex ...rest of line... puts an entry in the index foo. -% It also defines \fooindfile to be the number of the output channel for -% the file that accumulates this index. The file's extension is foo. -% The name of an index should be no more than 2 characters long -% for the sake of vms. -% -\def\newindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 % Open the file - \fi - \expandafter\xdef\csname#1index\endcsname{% % Define @#1index - \noexpand\doindex{#1}} -} - -% @defindex foo == \newindex{foo} -% -\def\defindex{\parsearg\newindex} - -% Define @defcodeindex, like @defindex except put all entries in @code. -% -\def\defcodeindex{\parsearg\newcodeindex} -% -\def\newcodeindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 - \fi - \expandafter\xdef\csname#1index\endcsname{% - \noexpand\docodeindex{#1}}% -} - - -% @synindex foo bar makes index foo feed into index bar. -% Do this instead of @defindex foo if you don't want it as a separate index. -% -% @syncodeindex foo bar similar, but put all entries made for index foo -% inside @code. -% -\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} -\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} - -% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), -% #3 the target index (bar). -\def\dosynindex#1#2#3{% - % Only do \closeout if we haven't already done it, else we'll end up - % closing the target index. - \expandafter \ifx\csname donesynindex#2\endcsname \relax - % The \closeout helps reduce unnecessary open files; the limit on the - % Acorn RISC OS is a mere 16 files. - \expandafter\closeout\csname#2indfile\endcsname - \expandafter\let\csname donesynindex#2\endcsname = 1 - \fi - % redefine \fooindfile: - \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname - \expandafter\let\csname#2indfile\endcsname=\temp - % redefine \fooindex: - \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% -} - -% Define \doindex, the driver for all \fooindex macros. -% Argument #1 is generated by the calling \fooindex macro, -% and it is "foo", the name of the index. - -% \doindex just uses \parsearg; it calls \doind for the actual work. -% This is because \doind is more useful to call from other macros. - -% There is also \dosubind {index}{topic}{subtopic} -% which makes an entry in a two-level index such as the operation index. - -\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} -\def\singleindexer #1{\doind{\indexname}{#1}} - -% like the previous two, but they put @code around the argument. -\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} -\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} - -% Take care of Texinfo commands that can appear in an index entry. -% Since there are some commands we want to expand, and others we don't, -% we have to laboriously prevent expansion for those that we don't. -% -\def\indexdummies{% - \escapechar = `\\ % use backslash in output files. - \def\@{@}% change to @@ when we switch to @ as escape char in index files. - \def\ {\realbackslash\space }% - % - % Need these unexpandable (because we define \tt as a dummy) - % definitions when @{ or @} appear in index entry text. Also, more - % complicated, when \tex is in effect and \{ is a \delimiter again. - % We can't use \lbracecmd and \rbracecmd because texindex assumes - % braces and backslashes are used only as delimiters. Perhaps we - % should define @lbrace and @rbrace commands a la @comma. - \def\{{{\tt\char123}}% - \def\}{{\tt\char125}}% - % - % I don't entirely understand this, but when an index entry is - % generated from a macro call, the \endinput which \scanmacro inserts - % causes processing to be prematurely terminated. This is, - % apparently, because \indexsorttmp is fully expanded, and \endinput - % is an expandable command. The redefinition below makes \endinput - % disappear altogether for that purpose -- although logging shows that - % processing continues to some further point. On the other hand, it - % seems \endinput does not hurt in the printed index arg, since that - % is still getting written without apparent harm. - % - % Sample source (mac-idx3.tex, reported by Graham Percival to - % help-texinfo, 22may06): - % @macro funindex {WORD} - % @findex xyz - % @end macro - % ... - % @funindex commtest - % - % The above is not enough to reproduce the bug, but it gives the flavor. - % - % Sample whatsit resulting: - % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} - % - % So: - \let\endinput = \empty - % - % Do the redefinitions. - \commondummies -} - -% For the aux and toc files, @ is the escape character. So we want to -% redefine everything using @ as the escape character (instead of -% \realbackslash, still used for index files). When everything uses @, -% this will be simpler. -% -\def\atdummies{% - \def\@{@@}% - \def\ {@ }% - \let\{ = \lbraceatcmd - \let\} = \rbraceatcmd - % - % Do the redefinitions. - \commondummies - \otherbackslash -} - -% Called from \indexdummies and \atdummies. -% -\def\commondummies{% - % - % \definedummyword defines \#1 as \string\#1\space, thus effectively - % preventing its expansion. This is used only for control words, - % not control letters, because the \space would be incorrect for - % control characters, but is needed to separate the control word - % from whatever follows. - % - % For control letters, we have \definedummyletter, which omits the - % space. - % - % These can be used both for control words that take an argument and - % those that do not. If it is followed by {arg} in the input, then - % that will dutifully get written to the index (or wherever). - % - \def\definedummyword ##1{\def##1{\string##1\space}}% - \def\definedummyletter##1{\def##1{\string##1}}% - \let\definedummyaccent\definedummyletter - % - \commondummiesnofonts - % - \definedummyletter\_% - \definedummyletter\-% - % - % Non-English letters. - \definedummyword\AA - \definedummyword\AE - \definedummyword\DH - \definedummyword\L - \definedummyword\O - \definedummyword\OE - \definedummyword\TH - \definedummyword\aa - \definedummyword\ae - \definedummyword\dh - \definedummyword\exclamdown - \definedummyword\l - \definedummyword\o - \definedummyword\oe - \definedummyword\ordf - \definedummyword\ordm - \definedummyword\questiondown - \definedummyword\ss - \definedummyword\th - % - % Although these internal commands shouldn't show up, sometimes they do. - \definedummyword\bf - \definedummyword\gtr - \definedummyword\hat - \definedummyword\less - \definedummyword\sf - \definedummyword\sl - \definedummyword\tclose - \definedummyword\tt - % - \definedummyword\LaTeX - \definedummyword\TeX - % - % Assorted special characters. - \definedummyword\arrow - \definedummyword\bullet - \definedummyword\comma - \definedummyword\copyright - \definedummyword\registeredsymbol - \definedummyword\dots - \definedummyword\enddots - \definedummyword\entrybreak - \definedummyword\equiv - \definedummyword\error - \definedummyword\euro - \definedummyword\expansion - \definedummyword\geq - \definedummyword\guillemetleft - \definedummyword\guillemetright - \definedummyword\guilsinglleft - \definedummyword\guilsinglright - \definedummyword\lbracechar - \definedummyword\leq - \definedummyword\minus - \definedummyword\ogonek - \definedummyword\pounds - \definedummyword\point - \definedummyword\print - \definedummyword\quotedblbase - \definedummyword\quotedblleft - \definedummyword\quotedblright - \definedummyword\quoteleft - \definedummyword\quoteright - \definedummyword\quotesinglbase - \definedummyword\rbracechar - \definedummyword\result - \definedummyword\textdegree - % - % We want to disable all macros so that they are not expanded by \write. - \macrolist - % - \normalturnoffactive - % - % Handle some cases of @value -- where it does not contain any - % (non-fully-expandable) commands. - \makevalueexpandable -} - -% \commondummiesnofonts: common to \commondummies and \indexnofonts. -% -\def\commondummiesnofonts{% - % Control letters and accents. - \definedummyletter\!% - \definedummyaccent\"% - \definedummyaccent\'% - \definedummyletter\*% - \definedummyaccent\,% - \definedummyletter\.% - \definedummyletter\/% - \definedummyletter\:% - \definedummyaccent\=% - \definedummyletter\?% - \definedummyaccent\^% - \definedummyaccent\`% - \definedummyaccent\~% - \definedummyword\u - \definedummyword\v - \definedummyword\H - \definedummyword\dotaccent - \definedummyword\ogonek - \definedummyword\ringaccent - \definedummyword\tieaccent - \definedummyword\ubaraccent - \definedummyword\udotaccent - \definedummyword\dotless - % - % Texinfo font commands. - \definedummyword\b - \definedummyword\i - \definedummyword\r - \definedummyword\sansserif - \definedummyword\sc - \definedummyword\slanted - \definedummyword\t - % - % Commands that take arguments. - \definedummyword\abbr - \definedummyword\acronym - \definedummyword\anchor - \definedummyword\cite - \definedummyword\code - \definedummyword\command - \definedummyword\dfn - \definedummyword\dmn - \definedummyword\email - \definedummyword\emph - \definedummyword\env - \definedummyword\file - \definedummyword\image - \definedummyword\indicateurl - \definedummyword\inforef - \definedummyword\kbd - \definedummyword\key - \definedummyword\math - \definedummyword\option - \definedummyword\pxref - \definedummyword\ref - \definedummyword\samp - \definedummyword\strong - \definedummyword\tie - \definedummyword\uref - \definedummyword\url - \definedummyword\var - \definedummyword\verb - \definedummyword\w - \definedummyword\xref -} - -% \indexnofonts is used when outputting the strings to sort the index -% by, and when constructing control sequence names. It eliminates all -% control sequences and just writes whatever the best ASCII sort string -% would be for a given command (usually its argument). -% -\def\indexnofonts{% - % Accent commands should become @asis. - \def\definedummyaccent##1{\let##1\asis}% - % We can just ignore other control letters. - \def\definedummyletter##1{\let##1\empty}% - % All control words become @asis by default; overrides below. - \let\definedummyword\definedummyaccent - % - \commondummiesnofonts - % - % Don't no-op \tt, since it isn't a user-level command - % and is used in the definitions of the active chars like <, >, |, etc. - % Likewise with the other plain tex font commands. - %\let\tt=\asis - % - \def\ { }% - \def\@{@}% - \def\_{\normalunderscore}% - \def\-{}% @- shouldn't affect sorting - % - % Unfortunately, texindex is not prepared to handle braces in the - % content at all. So for index sorting, we map @{ and @} to strings - % starting with |, since that ASCII character is between ASCII { and }. - \def\{{|a}% - \def\lbracechar{|a}% - % - \def\}{|b}% - \def\rbracechar{|b}% - % - % Non-English letters. - \def\AA{AA}% - \def\AE{AE}% - \def\DH{DZZ}% - \def\L{L}% - \def\OE{OE}% - \def\O{O}% - \def\TH{ZZZ}% - \def\aa{aa}% - \def\ae{ae}% - \def\dh{dzz}% - \def\exclamdown{!}% - \def\l{l}% - \def\oe{oe}% - \def\ordf{a}% - \def\ordm{o}% - \def\o{o}% - \def\questiondown{?}% - \def\ss{ss}% - \def\th{zzz}% - % - \def\LaTeX{LaTeX}% - \def\TeX{TeX}% - % - % Assorted special characters. - % (The following {} will end up in the sort string, but that's ok.) - \def\arrow{->}% - \def\bullet{bullet}% - \def\comma{,}% - \def\copyright{copyright}% - \def\dots{...}% - \def\enddots{...}% - \def\equiv{==}% - \def\error{error}% - \def\euro{euro}% - \def\expansion{==>}% - \def\geq{>=}% - \def\guillemetleft{<<}% - \def\guillemetright{>>}% - \def\guilsinglleft{<}% - \def\guilsinglright{>}% - \def\leq{<=}% - \def\minus{-}% - \def\point{.}% - \def\pounds{pounds}% - \def\print{-|}% - \def\quotedblbase{"}% - \def\quotedblleft{"}% - \def\quotedblright{"}% - \def\quoteleft{`}% - \def\quoteright{'}% - \def\quotesinglbase{,}% - \def\registeredsymbol{R}% - \def\result{=>}% - \def\textdegree{o}% - % - \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax - \else \indexlquoteignore \fi - % - % We need to get rid of all macros, leaving only the arguments (if present). - % Of course this is not nearly correct, but it is the best we can do for now. - % makeinfo does not expand macros in the argument to @deffn, which ends up - % writing an index entry, and texindex isn't prepared for an index sort entry - % that starts with \. - % - % Since macro invocations are followed by braces, we can just redefine them - % to take a single TeX argument. The case of a macro invocation that - % goes to end-of-line is not handled. - % - \macrolist -} - -% Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us -% ignore left quotes in the sort term. -{\catcode`\`=\active - \gdef\indexlquoteignore{\let`=\empty}} - -\let\indexbackslash=0 %overridden during \printindex. -\let\SETmarginindex=\relax % put index entries in margin (undocumented)? - -% Most index entries go through here, but \dosubind is the general case. -% #1 is the index name, #2 is the entry text. -\def\doind#1#2{\dosubind{#1}{#2}{}} - -% Workhorse for all \fooindexes. -% #1 is name of index, #2 is stuff to put there, #3 is subentry -- -% empty if called from \doind, as we usually are (the main exception -% is with most defuns, which call us directly). -% -\def\dosubind#1#2#3{% - \iflinks - {% - % Store the main index entry text (including the third arg). - \toks0 = {#2}% - % If third arg is present, precede it with a space. - \def\thirdarg{#3}% - \ifx\thirdarg\empty \else - \toks0 = \expandafter{\the\toks0 \space #3}% - \fi - % - \edef\writeto{\csname#1indfile\endcsname}% - % - \safewhatsit\dosubindwrite - }% - \fi -} - -% Write the entry in \toks0 to the index file: -% -\def\dosubindwrite{% - % Put the index entry in the margin if desired. - \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% - \fi - % - % Remember, we are within a group. - \indexdummies % Must do this here, since \bf, etc expand at this stage - \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now - % so it will be output as is; and it will print as backslash. - % - % Process the index entry with all font commands turned off, to - % get the string to sort by. - {\indexnofonts - \edef\temp{\the\toks0}% need full expansion - \xdef\indexsorttmp{\temp}% - }% - % - % Set up the complete index entry, with both the sort key and - % the original text, including any font commands. We write - % three arguments to \entry to the .?? file (four in the - % subentry case), texindex reduces to two when writing the .??s - % sorted result. - \edef\temp{% - \write\writeto{% - \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% - }% - \temp -} - -% Take care of unwanted page breaks/skips around a whatsit: -% -% If a skip is the last thing on the list now, preserve it -% by backing up by \lastskip, doing the \write, then inserting -% the skip again. Otherwise, the whatsit generated by the -% \write or \pdfdest will make \lastskip zero. The result is that -% sequences like this: -% @end defun -% @tindex whatever -% @defun ... -% will have extra space inserted, because the \medbreak in the -% start of the @defun won't see the skip inserted by the @end of -% the previous defun. -% -% But don't do any of this if we're not in vertical mode. We -% don't want to do a \vskip and prematurely end a paragraph. -% -% Avoid page breaks due to these extra skips, too. -% -% But wait, there is a catch there: -% We'll have to check whether \lastskip is zero skip. \ifdim is not -% sufficient for this purpose, as it ignores stretch and shrink parts -% of the skip. The only way seems to be to check the textual -% representation of the skip. -% -% The following is almost like \def\zeroskipmacro{0.0pt} except that -% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). -% -\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} -% -\newskip\whatsitskip -\newcount\whatsitpenalty -% -% ..., ready, GO: -% -\def\safewhatsit#1{\ifhmode - #1% - \else - % \lastskip and \lastpenalty cannot both be nonzero simultaneously. - \whatsitskip = \lastskip - \edef\lastskipmacro{\the\lastskip}% - \whatsitpenalty = \lastpenalty - % - % If \lastskip is nonzero, that means the last item was a - % skip. And since a skip is discardable, that means this - % -\whatsitskip glue we're inserting is preceded by a - % non-discardable item, therefore it is not a potential - % breakpoint, therefore no \nobreak needed. - \ifx\lastskipmacro\zeroskipmacro - \else - \vskip-\whatsitskip - \fi - % - #1% - % - \ifx\lastskipmacro\zeroskipmacro - % If \lastskip was zero, perhaps the last item was a penalty, and - % perhaps it was >=10000, e.g., a \nobreak. In that case, we want - % to re-insert the same penalty (values >10000 are used for various - % signals); since we just inserted a non-discardable item, any - % following glue (such as a \parskip) would be a breakpoint. For example: - % @deffn deffn-whatever - % @vindex index-whatever - % Description. - % would allow a break between the index-whatever whatsit - % and the "Description." paragraph. - \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi - \else - % On the other hand, if we had a nonzero \lastskip, - % this make-up glue would be preceded by a non-discardable item - % (the whatsit from the \write), so we must insert a \nobreak. - \nobreak\vskip\whatsitskip - \fi -\fi} - -% The index entry written in the file actually looks like -% \entry {sortstring}{page}{topic} -% or -% \entry {sortstring}{page}{topic}{subtopic} -% The texindex program reads in these files and writes files -% containing these kinds of lines: -% \initial {c} -% before the first topic whose initial is c -% \entry {topic}{pagelist} -% for a topic that is used without subtopics -% \primary {topic} -% for the beginning of a topic that is used with subtopics -% \secondary {subtopic}{pagelist} -% for each subtopic. - -% Define the user-accessible indexing commands -% @findex, @vindex, @kindex, @cindex. - -\def\findex {\fnindex} -\def\kindex {\kyindex} -\def\cindex {\cpindex} -\def\vindex {\vrindex} -\def\tindex {\tpindex} -\def\pindex {\pgindex} - -\def\cindexsub {\begingroup\obeylines\cindexsub} -{\obeylines % -\gdef\cindexsub "#1" #2^^M{\endgroup % -\dosubind{cp}{#2}{#1}}} - -% Define the macros used in formatting output of the sorted index material. - -% @printindex causes a particular index (the ??s file) to get printed. -% It does not print any chapter heading (usually an @unnumbered). -% -\parseargdef\printindex{\begingroup - \dobreak \chapheadingskip{10000}% - % - \smallfonts \rm - \tolerance = 9500 - \plainfrenchspacing - \everypar = {}% don't want the \kern\-parindent from indentation suppression. - % - % See if the index file exists and is nonempty. - % Change catcode of @ here so that if the index file contains - % \initial {@} - % as its first line, TeX doesn't complain about mismatched braces - % (because it thinks @} is a control sequence). - \catcode`\@ = 11 - \openin 1 \jobname.#1s - \ifeof 1 - % \enddoublecolumns gets confused if there is no text in the index, - % and it loses the chapter title and the aux file entries for the - % index. The easiest way to prevent this problem is to make sure - % there is some text. - \putwordIndexNonexistent - \else - % - % If the index file exists but is empty, then \openin leaves \ifeof - % false. We have to make TeX try to read something from the file, so - % it can discover if there is anything in it. - \read 1 to \temp - \ifeof 1 - \putwordIndexIsEmpty - \else - % Index files are almost Texinfo source, but we use \ as the escape - % character. It would be better to use @, but that's too big a change - % to make right now. - \def\indexbackslash{\backslashcurfont}% - \catcode`\\ = 0 - \escapechar = `\\ - \begindoublecolumns - \input \jobname.#1s - \enddoublecolumns - \fi - \fi - \closein 1 -\endgroup} - -% These macros are used by the sorted index file itself. -% Change them to control the appearance of the index. - -\def\initial#1{{% - % Some minor font changes for the special characters. - \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt - % - % Remove any glue we may have, we'll be inserting our own. - \removelastskip - % - % We like breaks before the index initials, so insert a bonus. - \nobreak - \vskip 0pt plus 3\baselineskip - \penalty 0 - \vskip 0pt plus -3\baselineskip - % - % Typeset the initial. Making this add up to a whole number of - % baselineskips increases the chance of the dots lining up from column - % to column. It still won't often be perfect, because of the stretch - % we need before each entry, but it's better. - % - % No shrink because it confuses \balancecolumns. - \vskip 1.67\baselineskip plus .5\baselineskip - \leftline{\secbf #1}% - % Do our best not to break after the initial. - \nobreak - \vskip .33\baselineskip plus .1\baselineskip -}} - -% \entry typesets a paragraph consisting of the text (#1), dot leaders, and -% then page number (#2) flushed to the right margin. It is used for index -% and table of contents entries. The paragraph is indented by \leftskip. -% -% A straightforward implementation would start like this: -% \def\entry#1#2{... -% But this freezes the catcodes in the argument, and can cause problems to -% @code, which sets - active. This problem was fixed by a kludge--- -% ``-'' was active throughout whole index, but this isn't really right. -% The right solution is to prevent \entry from swallowing the whole text. -% --kasal, 21nov03 -\def\entry{% - \begingroup - % - % Start a new paragraph if necessary, so our assignments below can't - % affect previous text. - \par - % - % Do not fill out the last line with white space. - \parfillskip = 0in - % - % No extra space above this paragraph. - \parskip = 0in - % - % Do not prefer a separate line ending with a hyphen to fewer lines. - \finalhyphendemerits = 0 - % - % \hangindent is only relevant when the entry text and page number - % don't both fit on one line. In that case, bob suggests starting the - % dots pretty far over on the line. Unfortunately, a large - % indentation looks wrong when the entry text itself is broken across - % lines. So we use a small indentation and put up with long leaders. - % - % \hangafter is reset to 1 (which is the value we want) at the start - % of each paragraph, so we need not do anything with that. - \hangindent = 2em - % - % When the entry text needs to be broken, just fill out the first line - % with blank space. - \rightskip = 0pt plus1fil - % - % A bit of stretch before each entry for the benefit of balancing - % columns. - \vskip 0pt plus1pt - % - % When reading the text of entry, convert explicit line breaks - % from @* into spaces. The user might give these in long section - % titles, for instance. - \def\*{\unskip\space\ignorespaces}% - \def\entrybreak{\hfil\break}% - % - % Swallow the left brace of the text (first parameter): - \afterassignment\doentry - \let\temp = -} -\def\entrybreak{\unskip\space\ignorespaces}% -\def\doentry{% - \bgroup % Instead of the swallowed brace. - \noindent - \aftergroup\finishentry - % And now comes the text of the entry. -} -\def\finishentry#1{% - % #1 is the page number. - % - % The following is kludged to not output a line of dots in the index if - % there are no page numbers. The next person who breaks this will be - % cursed by a Unix daemon. - \setbox\boxA = \hbox{#1}% - \ifdim\wd\boxA = 0pt - \ % - \else - % - % If we must, put the page number on a line of its own, and fill out - % this line with blank space. (The \hfil is overwhelmed with the - % fill leaders glue in \indexdotfill if the page number does fit.) - \hfil\penalty50 - \null\nobreak\indexdotfill % Have leaders before the page number. - % - % The `\ ' here is removed by the implicit \unskip that TeX does as - % part of (the primitive) \par. Without it, a spurious underfull - % \hbox ensues. - \ifpdf - \pdfgettoks#1.% - \ \the\toksA - \else - \ #1% - \fi - \fi - \par - \endgroup -} - -% Like plain.tex's \dotfill, except uses up at least 1 em. -\def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} - -\def\primary #1{\line{#1\hfil}} - -\newskip\secondaryindent \secondaryindent=0.5cm -\def\secondary#1#2{{% - \parfillskip=0in - \parskip=0in - \hangindent=1in - \hangafter=1 - \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill - \ifpdf - \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. - \else - #2 - \fi - \par -}} - -% Define two-column mode, which we use to typeset indexes. -% Adapted from the TeXbook, page 416, which is to say, -% the manmac.tex format used to print the TeXbook itself. -\catcode`\@=11 - -\newbox\partialpage -\newdimen\doublecolumnhsize - -\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns - % Grab any single-column material above us. - \output = {% - % - % Here is a possibility not foreseen in manmac: if we accumulate a - % whole lot of material, we might end up calling this \output - % routine twice in a row (see the doublecol-lose test, which is - % essentially a couple of indexes with @setchapternewpage off). In - % that case we just ship out what is in \partialpage with the normal - % output routine. Generally, \partialpage will be empty when this - % runs and this will be a no-op. See the indexspread.tex test case. - \ifvoid\partialpage \else - \onepageout{\pagecontents\partialpage}% - \fi - % - \global\setbox\partialpage = \vbox{% - % Unvbox the main output page. - \unvbox\PAGE - \kern-\topskip \kern\baselineskip - }% - }% - \eject % run that output routine to set \partialpage - % - % Use the double-column output routine for subsequent pages. - \output = {\doublecolumnout}% - % - % Change the page size parameters. We could do this once outside this - % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 - % format, but then we repeat the same computation. Repeating a couple - % of assignments once per index is clearly meaningless for the - % execution time, so we may as well do it in one place. - % - % First we halve the line length, less a little for the gutter between - % the columns. We compute the gutter based on the line length, so it - % changes automatically with the paper format. The magic constant - % below is chosen so that the gutter has the same value (well, +-<1pt) - % as it did when we hard-coded it. - % - % We put the result in a separate register, \doublecolumhsize, so we - % can restore it in \pagesofar, after \hsize itself has (potentially) - % been clobbered. - % - \doublecolumnhsize = \hsize - \advance\doublecolumnhsize by -.04154\hsize - \divide\doublecolumnhsize by 2 - \hsize = \doublecolumnhsize - % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) - \vsize = 2\vsize -} - -% The double-column output routine for all double-column pages except -% the last. -% -\def\doublecolumnout{% - \splittopskip=\topskip \splitmaxdepth=\maxdepth - % Get the available space for the double columns -- the normal - % (undoubled) page height minus any material left over from the - % previous page. - \dimen@ = \vsize - \divide\dimen@ by 2 - \advance\dimen@ by -\ht\partialpage - % - % box0 will be the left-hand column, box2 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ - \onepageout\pagesofar - \unvbox255 - \penalty\outputpenalty -} -% -% Re-output the contents of the output page -- any previous material, -% followed by the two boxes we just split, in box0 and box2. -\def\pagesofar{% - \unvbox\partialpage - % - \hsize = \doublecolumnhsize - \wd0=\hsize \wd2=\hsize - \hbox to\pagewidth{\box0\hfil\box2}% -} -% -% All done with double columns. -\def\enddoublecolumns{% - % The following penalty ensures that the page builder is exercised - % _before_ we change the output routine. This is necessary in the - % following situation: - % - % The last section of the index consists only of a single entry. - % Before this section, \pagetotal is less than \pagegoal, so no - % break occurs before the last section starts. However, the last - % section, consisting of \initial and the single \entry, does not - % fit on the page and has to be broken off. Without the following - % penalty the page builder will not be exercised until \eject - % below, and by that time we'll already have changed the output - % routine to the \balancecolumns version, so the next-to-last - % double-column page will be processed with \balancecolumns, which - % is wrong: The two columns will go to the main vertical list, with - % the broken-off section in the recent contributions. As soon as - % the output routine finishes, TeX starts reconsidering the page - % break. The two columns and the broken-off section both fit on the - % page, because the two columns now take up only half of the page - % goal. When TeX sees \eject from below which follows the final - % section, it invokes the new output routine that we've set after - % \balancecolumns below; \onepageout will try to fit the two columns - % and the final section into the vbox of \pageheight (see - % \pagebody), causing an overfull box. - % - % Note that glue won't work here, because glue does not exercise the - % page builder, unlike penalties (see The TeXbook, pp. 280-281). - \penalty0 - % - \output = {% - % Split the last of the double-column material. Leave it on the - % current page, no automatic page break. - \balancecolumns - % - % If we end up splitting too much material for the current page, - % though, there will be another page break right after this \output - % invocation ends. Having called \balancecolumns once, we do not - % want to call it again. Therefore, reset \output to its normal - % definition right away. (We hope \balancecolumns will never be - % called on to balance too much material, but if it is, this makes - % the output somewhat more palatable.) - \global\output = {\onepageout{\pagecontents\PAGE}}% - }% - \eject - \endgroup % started in \begindoublecolumns - % - % \pagegoal was set to the doubled \vsize above, since we restarted - % the current page. We're now back to normal single-column - % typesetting, so reset \pagegoal to the normal \vsize (after the - % \endgroup where \vsize got restored). - \pagegoal = \vsize -} -% -% Called at the end of the double column material. -\def\balancecolumns{% - \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. - \dimen@ = \ht0 - \advance\dimen@ by \topskip - \advance\dimen@ by-\baselineskip - \divide\dimen@ by 2 % target to split to - %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% - \splittopskip = \topskip - % Loop until we get a decent breakpoint. - {% - \vbadness = 10000 - \loop - \global\setbox3 = \copy0 - \global\setbox1 = \vsplit3 to \dimen@ - \ifdim\ht3>\dimen@ - \global\advance\dimen@ by 1pt - \repeat - }% - %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% - \setbox0=\vbox to\dimen@{\unvbox1}% - \setbox2=\vbox to\dimen@{\unvbox3}% - % - \pagesofar -} -\catcode`\@ = \other - - -\message{sectioning,} -% Chapters, sections, etc. - -% Let's start with @part. -\outer\parseargdef\part{\partzzz{#1}} -\def\partzzz#1{% - \chapoddpage - \null - \vskip.3\vsize % move it down on the page a bit - \begingroup - \noindent \titlefonts\rmisbold #1\par % the text - \let\lastnode=\empty % no node to associate with - \writetocentry{part}{#1}{}% but put it in the toc - \headingsoff % no headline or footline on the part page - \chapoddpage - \endgroup -} - -% \unnumberedno is an oxymoron. But we count the unnumbered -% sections so that we can refer to them unambiguously in the pdf -% outlines by their "section number". We avoid collisions with chapter -% numbers by starting them at 10000. (If a document ever has 10000 -% chapters, we're in trouble anyway, I'm sure.) -\newcount\unnumberedno \unnumberedno = 10000 -\newcount\chapno -\newcount\secno \secno=0 -\newcount\subsecno \subsecno=0 -\newcount\subsubsecno \subsubsecno=0 - -% This counter is funny since it counts through charcodes of letters A, B, ... -\newcount\appendixno \appendixno = `\@ -% -% \def\appendixletter{\char\the\appendixno} -% We do the following ugly conditional instead of the above simple -% construct for the sake of pdftex, which needs the actual -% letter in the expansion, not just typeset. -% -\def\appendixletter{% - \ifnum\appendixno=`A A% - \else\ifnum\appendixno=`B B% - \else\ifnum\appendixno=`C C% - \else\ifnum\appendixno=`D D% - \else\ifnum\appendixno=`E E% - \else\ifnum\appendixno=`F F% - \else\ifnum\appendixno=`G G% - \else\ifnum\appendixno=`H H% - \else\ifnum\appendixno=`I I% - \else\ifnum\appendixno=`J J% - \else\ifnum\appendixno=`K K% - \else\ifnum\appendixno=`L L% - \else\ifnum\appendixno=`M M% - \else\ifnum\appendixno=`N N% - \else\ifnum\appendixno=`O O% - \else\ifnum\appendixno=`P P% - \else\ifnum\appendixno=`Q Q% - \else\ifnum\appendixno=`R R% - \else\ifnum\appendixno=`S S% - \else\ifnum\appendixno=`T T% - \else\ifnum\appendixno=`U U% - \else\ifnum\appendixno=`V V% - \else\ifnum\appendixno=`W W% - \else\ifnum\appendixno=`X X% - \else\ifnum\appendixno=`Y Y% - \else\ifnum\appendixno=`Z Z% - % The \the is necessary, despite appearances, because \appendixletter is - % expanded while writing the .toc file. \char\appendixno is not - % expandable, thus it is written literally, thus all appendixes come out - % with the same letter (or @) in the toc without it. - \else\char\the\appendixno - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} - -% Each @chapter defines these (using marks) as the number+name, number -% and name of the chapter. Page headings and footings can use -% these. @section does likewise. -\def\thischapter{} -\def\thischapternum{} -\def\thischaptername{} -\def\thissection{} -\def\thissectionnum{} -\def\thissectionname{} - -\newcount\absseclevel % used to calculate proper heading level -\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count - -% @raisesections: treat @section as chapter, @subsection as section, etc. -\def\raisesections{\global\advance\secbase by -1} -\let\up=\raisesections % original BFox name - -% @lowersections: treat @chapter as section, @section as subsection, etc. -\def\lowersections{\global\advance\secbase by 1} -\let\down=\lowersections % original BFox name - -% we only have subsub. -\chardef\maxseclevel = 3 -% -% A numbered section within an unnumbered changes to unnumbered too. -% To achieve this, remember the "biggest" unnum. sec. we are currently in: -\chardef\unnlevel = \maxseclevel -% -% Trace whether the current chapter is an appendix or not: -% \chapheadtype is "N" or "A", unnumbered chapters are ignored. -\def\chapheadtype{N} - -% Choose a heading macro -% #1 is heading type -% #2 is heading level -% #3 is text for heading -\def\genhead#1#2#3{% - % Compute the abs. sec. level: - \absseclevel=#2 - \advance\absseclevel by \secbase - % Make sure \absseclevel doesn't fall outside the range: - \ifnum \absseclevel < 0 - \absseclevel = 0 - \else - \ifnum \absseclevel > 3 - \absseclevel = 3 - \fi - \fi - % The heading type: - \def\headtype{#1}% - \if \headtype U% - \ifnum \absseclevel < \unnlevel - \chardef\unnlevel = \absseclevel - \fi - \else - % Check for appendix sections: - \ifnum \absseclevel = 0 - \edef\chapheadtype{\headtype}% - \else - \if \headtype A\if \chapheadtype N% - \errmessage{@appendix... within a non-appendix chapter}% - \fi\fi - \fi - % Check for numbered within unnumbered: - \ifnum \absseclevel > \unnlevel - \def\headtype{U}% - \else - \chardef\unnlevel = 3 - \fi - \fi - % Now print the heading: - \if \headtype U% - \ifcase\absseclevel - \unnumberedzzz{#3}% - \or \unnumberedseczzz{#3}% - \or \unnumberedsubseczzz{#3}% - \or \unnumberedsubsubseczzz{#3}% - \fi - \else - \if \headtype A% - \ifcase\absseclevel - \appendixzzz{#3}% - \or \appendixsectionzzz{#3}% - \or \appendixsubseczzz{#3}% - \or \appendixsubsubseczzz{#3}% - \fi - \else - \ifcase\absseclevel - \chapterzzz{#3}% - \or \seczzz{#3}% - \or \numberedsubseczzz{#3}% - \or \numberedsubsubseczzz{#3}% - \fi - \fi - \fi - \suppressfirstparagraphindent -} - -% an interface: -\def\numhead{\genhead N} -\def\apphead{\genhead A} -\def\unnmhead{\genhead U} - -% @chapter, @appendix, @unnumbered. Increment top-level counter, reset -% all lower-level sectioning counters to zero. -% -% Also set \chaplevelprefix, which we prepend to @float sequence numbers -% (e.g., figures), q.v. By default (before any chapter), that is empty. -\let\chaplevelprefix = \empty -% -\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz -\def\chapterzzz#1{% - % section resetting is \global in case the chapter is in a group, such - % as an @include file. - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\chapno by 1 - % - % Used for \float. - \gdef\chaplevelprefix{\the\chapno.}% - \resetallfloatnos - % - % \putwordChapter can contain complex things in translations. - \toks0=\expandafter{\putwordChapter}% - \message{\the\toks0 \space \the\chapno}% - % - % Write the actual heading. - \chapmacro{#1}{Ynumbered}{\the\chapno}% - % - % So @section and the like are numbered underneath this chapter. - \global\let\section = \numberedsec - \global\let\subsection = \numberedsubsec - \global\let\subsubsection = \numberedsubsubsec -} - -\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz -% -\def\appendixzzz#1{% - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\appendixno by 1 - \gdef\chaplevelprefix{\appendixletter.}% - \resetallfloatnos - % - % \putwordAppendix can contain complex things in translations. - \toks0=\expandafter{\putwordAppendix}% - \message{\the\toks0 \space \appendixletter}% - % - \chapmacro{#1}{Yappendix}{\appendixletter}% - % - \global\let\section = \appendixsec - \global\let\subsection = \appendixsubsec - \global\let\subsubsection = \appendixsubsubsec -} - -% normally unnmhead0 calls unnumberedzzz: -\outer\parseargdef\unnumbered{\unnmhead0{#1}} -\def\unnumberedzzz#1{% - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\unnumberedno by 1 - % - % Since an unnumbered has no number, no prefix for figures. - \global\let\chaplevelprefix = \empty - \resetallfloatnos - % - % This used to be simply \message{#1}, but TeX fully expands the - % argument to \message. Therefore, if #1 contained @-commands, TeX - % expanded them. For example, in `@unnumbered The @cite{Book}', TeX - % expanded @cite (which turns out to cause errors because \cite is meant - % to be executed, not expanded). - % - % Anyway, we don't want the fully-expanded definition of @cite to appear - % as a result of the \message, we just want `@cite' itself. We use - % \the to achieve this: TeX expands \the only once, - % simply yielding the contents of . (We also do this for - % the toc entries.) - \toks0 = {#1}% - \message{(\the\toks0)}% - % - \chapmacro{#1}{Ynothing}{\the\unnumberedno}% - % - \global\let\section = \unnumberedsec - \global\let\subsection = \unnumberedsubsec - \global\let\subsubsection = \unnumberedsubsubsec -} - -% @centerchap is like @unnumbered, but the heading is centered. -\outer\parseargdef\centerchap{% - % Well, we could do the following in a group, but that would break - % an assumption that \chapmacro is called at the outermost level. - % Thus we are safer this way: --kasal, 24feb04 - \let\centerparametersmaybe = \centerparameters - \unnmhead0{#1}% - \let\centerparametersmaybe = \relax -} - -% @top is like @unnumbered. -\let\top\unnumbered - -% Sections. -% -\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz -\def\seczzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% -} - -% normally calls appendixsectionzzz: -\outer\parseargdef\appendixsection{\apphead1{#1}} -\def\appendixsectionzzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% -} -\let\appendixsec\appendixsection - -% normally calls unnumberedseczzz: -\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} -\def\unnumberedseczzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% -} - -% Subsections. -% -% normally calls numberedsubseczzz: -\outer\parseargdef\numberedsubsec{\numhead2{#1}} -\def\numberedsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% -} - -% normally calls appendixsubseczzz: -\outer\parseargdef\appendixsubsec{\apphead2{#1}} -\def\appendixsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Yappendix}% - {\appendixletter.\the\secno.\the\subsecno}% -} - -% normally calls unnumberedsubseczzz: -\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} -\def\unnumberedsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Ynothing}% - {\the\unnumberedno.\the\secno.\the\subsecno}% -} - -% Subsubsections. -% -% normally numberedsubsubseczzz: -\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} -\def\numberedsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Ynumbered}% - {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -% normally appendixsubsubseczzz: -\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} -\def\appendixsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Yappendix}% - {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -% normally unnumberedsubsubseczzz: -\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} -\def\unnumberedsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Ynothing}% - {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -% These macros control what the section commands do, according -% to what kind of chapter we are in (ordinary, appendix, or unnumbered). -% Define them by default for a numbered chapter. -\let\section = \numberedsec -\let\subsection = \numberedsubsec -\let\subsubsection = \numberedsubsubsec - -% Define @majorheading, @heading and @subheading - -\def\majorheading{% - {\advance\chapheadingskip by 10pt \chapbreak }% - \parsearg\chapheadingzzz -} - -\def\chapheading{\chapbreak \parsearg\chapheadingzzz} -\def\chapheadingzzz#1{% - \vbox{\chapfonts \raggedtitlesettings #1\par}% - \nobreak\bigskip \nobreak - \suppressfirstparagraphindent -} - -% @heading, @subheading, @subsubheading. -\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} -\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} -\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} - -% These macros generate a chapter, section, etc. heading only -% (including whitespace, linebreaking, etc. around it), -% given all the information in convenient, parsed form. - -% Args are the skip and penalty (usually negative) -\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} - -% Parameter controlling skip before chapter headings (if needed) -\newskip\chapheadingskip - -% Define plain chapter starts, and page on/off switching for it. -\def\chapbreak{\dobreak \chapheadingskip {-4000}} -\def\chappager{\par\vfill\supereject} -% Because \domark is called before \chapoddpage, the filler page will -% get the headings for the next chapter, which is wrong. But we don't -% care -- we just disable all headings on the filler page. -\def\chapoddpage{% - \chappager - \ifodd\pageno \else - \begingroup - \headingsoff - \null - \chappager - \endgroup - \fi -} - -\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} - -\def\CHAPPAGoff{% -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chapbreak -\global\let\pagealignmacro=\chappager} - -\def\CHAPPAGon{% -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chappager -\global\let\pagealignmacro=\chappager -\global\def\HEADINGSon{\HEADINGSsingle}} - -\def\CHAPPAGodd{% -\global\let\contentsalignmacro = \chapoddpage -\global\let\pchapsepmacro=\chapoddpage -\global\let\pagealignmacro=\chapoddpage -\global\def\HEADINGSon{\HEADINGSdouble}} - -\CHAPPAGon - -% Chapter opening. -% -% #1 is the text, #2 is the section type (Ynumbered, Ynothing, -% Yappendix, Yomitfromtoc), #3 the chapter number. -% -% To test against our argument. -\def\Ynothingkeyword{Ynothing} -\def\Yomitfromtockeyword{Yomitfromtoc} -\def\Yappendixkeyword{Yappendix} -% -\def\chapmacro#1#2#3{% - % Insert the first mark before the heading break (see notes for \domark). - \let\prevchapterdefs=\lastchapterdefs - \let\prevsectiondefs=\lastsectiondefs - \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% - \gdef\thissection{}}% - % - \def\temptype{#2}% - \ifx\temptype\Ynothingkeyword - \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% - \gdef\thischapter{\thischaptername}}% - \else\ifx\temptype\Yomitfromtockeyword - \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% - \gdef\thischapter{}}% - \else\ifx\temptype\Yappendixkeyword - \toks0={#1}% - \xdef\lastchapterdefs{% - \gdef\noexpand\thischaptername{\the\toks0}% - \gdef\noexpand\thischapternum{\appendixletter}% - % \noexpand\putwordAppendix avoids expanding indigestible - % commands in some of the translations. - \gdef\noexpand\thischapter{\noexpand\putwordAppendix{} - \noexpand\thischapternum: - \noexpand\thischaptername}% - }% - \else - \toks0={#1}% - \xdef\lastchapterdefs{% - \gdef\noexpand\thischaptername{\the\toks0}% - \gdef\noexpand\thischapternum{\the\chapno}% - % \noexpand\putwordChapter avoids expanding indigestible - % commands in some of the translations. - \gdef\noexpand\thischapter{\noexpand\putwordChapter{} - \noexpand\thischapternum: - \noexpand\thischaptername}% - }% - \fi\fi\fi - % - % Output the mark. Pass it through \safewhatsit, to take care of - % the preceding space. - \safewhatsit\domark - % - % Insert the chapter heading break. - \pchapsepmacro - % - % Now the second mark, after the heading break. No break points - % between here and the heading. - \let\prevchapterdefs=\lastchapterdefs - \let\prevsectiondefs=\lastsectiondefs - \domark - % - {% - \chapfonts \rmisbold - % - % Have to define \lastsection before calling \donoderef, because the - % xref code eventually uses it. On the other hand, it has to be called - % after \pchapsepmacro, or the headline will change too soon. - \gdef\lastsection{#1}% - % - % Only insert the separating space if we have a chapter/appendix - % number, and don't print the unnumbered ``number''. - \ifx\temptype\Ynothingkeyword - \setbox0 = \hbox{}% - \def\toctype{unnchap}% - \else\ifx\temptype\Yomitfromtockeyword - \setbox0 = \hbox{}% contents like unnumbered, but no toc entry - \def\toctype{omit}% - \else\ifx\temptype\Yappendixkeyword - \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% - \def\toctype{app}% - \else - \setbox0 = \hbox{#3\enspace}% - \def\toctype{numchap}% - \fi\fi\fi - % - % Write the toc entry for this chapter. Must come before the - % \donoderef, because we include the current node name in the toc - % entry, and \donoderef resets it to empty. - \writetocentry{\toctype}{#1}{#3}% - % - % For pdftex, we have to write out the node definition (aka, make - % the pdfdest) after any page break, but before the actual text has - % been typeset. If the destination for the pdf outline is after the - % text, then jumping from the outline may wind up with the text not - % being visible, for instance under high magnification. - \donoderef{#2}% - % - % Typeset the actual heading. - \nobreak % Avoid page breaks at the interline glue. - \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe - \unhbox0 #1\par}% - }% - \nobreak\bigskip % no page break after a chapter title - \nobreak -} - -% @centerchap -- centered and unnumbered. -\let\centerparametersmaybe = \relax -\def\centerparameters{% - \advance\rightskip by 3\rightskip - \leftskip = \rightskip - \parfillskip = 0pt -} - - -% I don't think this chapter style is supported any more, so I'm not -% updating it with the new noderef stuff. We'll see. --karl, 11aug03. -% -\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} -% -\def\unnchfopen #1{% - \chapoddpage - \vbox{\chapfonts \raggedtitlesettings #1\par}% - \nobreak\bigskip\nobreak -} -\def\chfopen #1#2{\chapoddpage {\chapfonts -\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% -\par\penalty 5000 % -} -\def\centerchfopen #1{% - \chapoddpage - \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% - \nobreak\bigskip \nobreak -} -\def\CHAPFopen{% - \global\let\chapmacro=\chfopen - \global\let\centerchapmacro=\centerchfopen} - - -% Section titles. These macros combine the section number parts and -% call the generic \sectionheading to do the printing. -% -\newskip\secheadingskip -\def\secheadingbreak{\dobreak \secheadingskip{-1000}} - -% Subsection titles. -\newskip\subsecheadingskip -\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} - -% Subsubsection titles. -\def\subsubsecheadingskip{\subsecheadingskip} -\def\subsubsecheadingbreak{\subsecheadingbreak} - - -% Print any size, any type, section title. -% -% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is -% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the -% section number. -% -\def\seckeyword{sec} -% -\def\sectionheading#1#2#3#4{% - {% - \checkenv{}% should not be in an environment. - % - % Switch to the right set of fonts. - \csname #2fonts\endcsname \rmisbold - % - \def\sectionlevel{#2}% - \def\temptype{#3}% - % - % Insert first mark before the heading break (see notes for \domark). - \let\prevsectiondefs=\lastsectiondefs - \ifx\temptype\Ynothingkeyword - \ifx\sectionlevel\seckeyword - \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% - \gdef\thissection{\thissectionname}}% - \fi - \else\ifx\temptype\Yomitfromtockeyword - % Don't redefine \thissection. - \else\ifx\temptype\Yappendixkeyword - \ifx\sectionlevel\seckeyword - \toks0={#1}% - \xdef\lastsectiondefs{% - \gdef\noexpand\thissectionname{\the\toks0}% - \gdef\noexpand\thissectionnum{#4}% - % \noexpand\putwordSection avoids expanding indigestible - % commands in some of the translations. - \gdef\noexpand\thissection{\noexpand\putwordSection{} - \noexpand\thissectionnum: - \noexpand\thissectionname}% - }% - \fi - \else - \ifx\sectionlevel\seckeyword - \toks0={#1}% - \xdef\lastsectiondefs{% - \gdef\noexpand\thissectionname{\the\toks0}% - \gdef\noexpand\thissectionnum{#4}% - % \noexpand\putwordSection avoids expanding indigestible - % commands in some of the translations. - \gdef\noexpand\thissection{\noexpand\putwordSection{} - \noexpand\thissectionnum: - \noexpand\thissectionname}% - }% - \fi - \fi\fi\fi - % - % Go into vertical mode. Usually we'll already be there, but we - % don't want the following whatsit to end up in a preceding paragraph - % if the document didn't happen to have a blank line. - \par - % - % Output the mark. Pass it through \safewhatsit, to take care of - % the preceding space. - \safewhatsit\domark - % - % Insert space above the heading. - \csname #2headingbreak\endcsname - % - % Now the second mark, after the heading break. No break points - % between here and the heading. - \let\prevsectiondefs=\lastsectiondefs - \domark - % - % Only insert the space after the number if we have a section number. - \ifx\temptype\Ynothingkeyword - \setbox0 = \hbox{}% - \def\toctype{unn}% - \gdef\lastsection{#1}% - \else\ifx\temptype\Yomitfromtockeyword - % for @headings -- no section number, don't include in toc, - % and don't redefine \lastsection. - \setbox0 = \hbox{}% - \def\toctype{omit}% - \let\sectionlevel=\empty - \else\ifx\temptype\Yappendixkeyword - \setbox0 = \hbox{#4\enspace}% - \def\toctype{app}% - \gdef\lastsection{#1}% - \else - \setbox0 = \hbox{#4\enspace}% - \def\toctype{num}% - \gdef\lastsection{#1}% - \fi\fi\fi - % - % Write the toc entry (before \donoderef). See comments in \chapmacro. - \writetocentry{\toctype\sectionlevel}{#1}{#4}% - % - % Write the node reference (= pdf destination for pdftex). - % Again, see comments in \chapmacro. - \donoderef{#3}% - % - % Interline glue will be inserted when the vbox is completed. - % That glue will be a valid breakpoint for the page, since it'll be - % preceded by a whatsit (usually from the \donoderef, or from the - % \writetocentry if there was no node). We don't want to allow that - % break, since then the whatsits could end up on page n while the - % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. - \nobreak - % - % Output the actual section heading. - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright - \hangindent=\wd0 % zero if no section number - \unhbox0 #1}% - }% - % Add extra space after the heading -- half of whatever came above it. - % Don't allow stretch, though. - \kern .5 \csname #2headingskip\endcsname - % - % Do not let the kern be a potential breakpoint, as it would be if it - % was followed by glue. - \nobreak - % - % We'll almost certainly start a paragraph next, so don't let that - % glue accumulate. (Not a breakpoint because it's preceded by a - % discardable item.) However, when a paragraph is not started next - % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out - % or the negative glue will cause weirdly wrong output, typically - % obscuring the section heading with something else. - \vskip-\parskip - % - % This is so the last item on the main vertical list is a known - % \penalty > 10000, so \startdefun, etc., can recognize the situation - % and do the needful. - \penalty 10001 -} - - -\message{toc,} -% Table of contents. -\newwrite\tocfile - -% Write an entry to the toc file, opening it if necessary. -% Called from @chapter, etc. -% -% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} -% We append the current node name (if any) and page number as additional -% arguments for the \{chap,sec,...}entry macros which will eventually -% read this. The node name is used in the pdf outlines as the -% destination to jump to. -% -% We open the .toc file for writing here instead of at @setfilename (or -% any other fixed time) so that @contents can be anywhere in the document. -% But if #1 is `omit', then we don't do anything. This is used for the -% table of contents chapter openings themselves. -% -\newif\iftocfileopened -\def\omitkeyword{omit}% -% -\def\writetocentry#1#2#3{% - \edef\writetoctype{#1}% - \ifx\writetoctype\omitkeyword \else - \iftocfileopened\else - \immediate\openout\tocfile = \jobname.toc - \global\tocfileopenedtrue - \fi - % - \iflinks - {\atdummies - \edef\temp{% - \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% - \temp - }% - \fi - \fi - % - % Tell \shipout to create a pdf destination on each page, if we're - % writing pdf. These are used in the table of contents. We can't - % just write one on every page because the title pages are numbered - % 1 and 2 (the page numbers aren't printed), and so are the first - % two pages of the document. Thus, we'd have two destinations named - % `1', and two named `2'. - \ifpdf \global\pdfmakepagedesttrue \fi -} - - -% These characters do not print properly in the Computer Modern roman -% fonts, so we must take special care. This is more or less redundant -% with the Texinfo input format setup at the end of this file. -% -\def\activecatcodes{% - \catcode`\"=\active - \catcode`\$=\active - \catcode`\<=\active - \catcode`\>=\active - \catcode`\\=\active - \catcode`\^=\active - \catcode`\_=\active - \catcode`\|=\active - \catcode`\~=\active -} - - -% Read the toc file, which is essentially Texinfo input. -\def\readtocfile{% - \setupdatafile - \activecatcodes - \input \tocreadfilename -} - -\newskip\contentsrightmargin \contentsrightmargin=1in -\newcount\savepageno -\newcount\lastnegativepageno \lastnegativepageno = -1 - -% Prepare to read what we've written to \tocfile. -% -\def\startcontents#1{% - % If @setchapternewpage on, and @headings double, the contents should - % start on an odd page, unlike chapters. Thus, we maintain - % \contentsalignmacro in parallel with \pagealignmacro. - % From: Torbjorn Granlund - \contentsalignmacro - \immediate\closeout\tocfile - % - % Don't need to put `Contents' or `Short Contents' in the headline. - % It is abundantly clear what they are. - \chapmacro{#1}{Yomitfromtoc}{}% - % - \savepageno = \pageno - \begingroup % Set up to handle contents files properly. - \raggedbottom % Worry more about breakpoints than the bottom. - \advance\hsize by -\contentsrightmargin % Don't use the full line length. - % - % Roman numerals for page numbers. - \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi -} - -% redefined for the two-volume lispref. We always output on -% \jobname.toc even if this is redefined. -% -\def\tocreadfilename{\jobname.toc} - -% Normal (long) toc. -% -\def\contents{% - \startcontents{\putwordTOC}% - \openin 1 \tocreadfilename\space - \ifeof 1 \else - \readtocfile - \fi - \vfill \eject - \contentsalignmacro % in case @setchapternewpage odd is in effect - \ifeof 1 \else - \pdfmakeoutlines - \fi - \closein 1 - \endgroup - \lastnegativepageno = \pageno - \global\pageno = \savepageno -} - -% And just the chapters. -\def\summarycontents{% - \startcontents{\putwordShortTOC}% - % - \let\partentry = \shortpartentry - \let\numchapentry = \shortchapentry - \let\appentry = \shortchapentry - \let\unnchapentry = \shortunnchapentry - % We want a true roman here for the page numbers. - \secfonts - \let\rm=\shortcontrm \let\bf=\shortcontbf - \let\sl=\shortcontsl \let\tt=\shortconttt - \rm - \hyphenpenalty = 10000 - \advance\baselineskip by 1pt % Open it up a little. - \def\numsecentry##1##2##3##4{} - \let\appsecentry = \numsecentry - \let\unnsecentry = \numsecentry - \let\numsubsecentry = \numsecentry - \let\appsubsecentry = \numsecentry - \let\unnsubsecentry = \numsecentry - \let\numsubsubsecentry = \numsecentry - \let\appsubsubsecentry = \numsecentry - \let\unnsubsubsecentry = \numsecentry - \openin 1 \tocreadfilename\space - \ifeof 1 \else - \readtocfile - \fi - \closein 1 - \vfill \eject - \contentsalignmacro % in case @setchapternewpage odd is in effect - \endgroup - \lastnegativepageno = \pageno - \global\pageno = \savepageno -} -\let\shortcontents = \summarycontents - -% Typeset the label for a chapter or appendix for the short contents. -% The arg is, e.g., `A' for an appendix, or `3' for a chapter. -% -\def\shortchaplabel#1{% - % This space should be enough, since a single number is .5em, and the - % widest letter (M) is 1em, at least in the Computer Modern fonts. - % But use \hss just in case. - % (This space doesn't include the extra space that gets added after - % the label; that gets put in by \shortchapentry above.) - % - % We'd like to right-justify chapter numbers, but that looks strange - % with appendix letters. And right-justifying numbers and - % left-justifying letters looks strange when there is less than 10 - % chapters. Have to read the whole toc once to know how many chapters - % there are before deciding ... - \hbox to 1em{#1\hss}% -} - -% These macros generate individual entries in the table of contents. -% The first argument is the chapter or section name. -% The last argument is the page number. -% The arguments in between are the chapter number, section number, ... - -% Parts, in the main contents. Replace the part number, which doesn't -% exist, with an empty box. Let's hope all the numbers have the same width. -% Also ignore the page number, which is conventionally not printed. -\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} -\def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}} -% -% Parts, in the short toc. -\def\shortpartentry#1#2#3#4{% - \penalty-300 - \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip - \shortchapentry{{\bf #1}}{\numeralbox}{}{}% -} - -% Chapters, in the main contents. -\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} -% -% Chapters, in the short toc. -% See comments in \dochapentry re vbox and related settings. -\def\shortchapentry#1#2#3#4{% - \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% -} - -% Appendices, in the main contents. -% Need the word Appendix, and a fixed-size box. -% -\def\appendixbox#1{% - % We use M since it's probably the widest letter. - \setbox0 = \hbox{\putwordAppendix{} M}% - \hbox to \wd0{\putwordAppendix{} #1\hss}} -% -\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} - -% Unnumbered chapters. -\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} -\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} - -% Sections. -\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} -\let\appsecentry=\numsecentry -\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} - -% Subsections. -\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} -\let\appsubsecentry=\numsubsecentry -\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} - -% And subsubsections. -\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} -\let\appsubsubsecentry=\numsubsubsecentry -\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} - -% This parameter controls the indentation of the various levels. -% Same as \defaultparindent. -\newdimen\tocindent \tocindent = 15pt - -% Now for the actual typesetting. In all these, #1 is the text and #2 is the -% page number. -% -% If the toc has to be broken over pages, we want it to be at chapters -% if at all possible; hence the \penalty. -\def\dochapentry#1#2{% - \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip - \begingroup - \chapentryfonts - \tocentry{#1}{\dopageno\bgroup#2\egroup}% - \endgroup - \nobreak\vskip .25\baselineskip plus.1\baselineskip -} - -\def\dosecentry#1#2{\begingroup - \secentryfonts \leftskip=\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -\def\dosubsecentry#1#2{\begingroup - \subsecentryfonts \leftskip=2\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -\def\dosubsubsecentry#1#2{\begingroup - \subsubsecentryfonts \leftskip=3\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -% We use the same \entry macro as for the index entries. -\let\tocentry = \entry - -% Space between chapter (or whatever) number and the title. -\def\labelspace{\hskip1em \relax} - -\def\dopageno#1{{\rm #1}} -\def\doshortpageno#1{{\rm #1}} - -\def\chapentryfonts{\secfonts \rm} -\def\secentryfonts{\textfonts} -\def\subsecentryfonts{\textfonts} -\def\subsubsecentryfonts{\textfonts} - - -\message{environments,} -% @foo ... @end foo. - -% @tex ... @end tex escapes into raw TeX temporarily. -% One exception: @ is still an escape character, so that @end tex works. -% But \@ or @@ will get a plain @ character. - -\envdef\tex{% - \setupmarkupstyle{tex}% - \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 - \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 - \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie - \catcode `\%=14 - \catcode `\+=\other - \catcode `\"=\other - \catcode `\|=\other - \catcode `\<=\other - \catcode `\>=\other - \catcode`\`=\other - \catcode`\'=\other - \escapechar=`\\ - % - % ' is active in math mode (mathcode"8000). So reset it, and all our - % other math active characters (just in case), to plain's definitions. - \mathactive - % - \let\b=\ptexb - \let\bullet=\ptexbullet - \let\c=\ptexc - \let\,=\ptexcomma - \let\.=\ptexdot - \let\dots=\ptexdots - \let\equiv=\ptexequiv - \let\!=\ptexexclam - \let\i=\ptexi - \let\indent=\ptexindent - \let\noindent=\ptexnoindent - \let\{=\ptexlbrace - \let\+=\tabalign - \let\}=\ptexrbrace - \let\/=\ptexslash - \let\*=\ptexstar - \let\t=\ptext - \expandafter \let\csname top\endcsname=\ptextop % outer - \let\frenchspacing=\plainfrenchspacing - % - \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% - \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% - \def\@{@}% -} -% There is no need to define \Etex. - -% Define @lisp ... @end lisp. -% @lisp environment forms a group so it can rebind things, -% including the definition of @end lisp (which normally is erroneous). - -% Amount to narrow the margins by for @lisp. -\newskip\lispnarrowing \lispnarrowing=0.4in - -% This is the definition that ^^M gets inside @lisp, @example, and other -% such environments. \null is better than a space, since it doesn't -% have any width. -\def\lisppar{\null\endgraf} - -% This space is always present above and below environments. -\newskip\envskipamount \envskipamount = 0pt - -% Make spacing and below environment symmetrical. We use \parskip here -% to help in doing that, since in @example-like environments \parskip -% is reset to zero; thus the \afterenvbreak inserts no space -- but the -% start of the next paragraph will insert \parskip. -% -\def\aboveenvbreak{{% - % =10000 instead of <10000 because of a special case in \itemzzz and - % \sectionheading, q.v. - \ifnum \lastpenalty=10000 \else - \advance\envskipamount by \parskip - \endgraf - \ifdim\lastskip<\envskipamount - \removelastskip - % it's not a good place to break if the last penalty was \nobreak - % or better ... - \ifnum\lastpenalty<10000 \penalty-50 \fi - \vskip\envskipamount - \fi - \fi -}} - -\let\afterenvbreak = \aboveenvbreak - -% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will -% also clear it, so that its embedded environments do the narrowing again. -\let\nonarrowing=\relax - -% @cartouche ... @end cartouche: draw rectangle w/rounded corners around -% environment contents. -\font\circle=lcircle10 -\newdimen\circthick -\newdimen\cartouter\newdimen\cartinner -\newskip\normbskip\newskip\normpskip\newskip\normlskip -\circthick=\fontdimen8\circle -% -\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth -\def\ctr{{\hskip 6pt\circle\char'010}} -\def\cbl{{\circle\char'012\hskip -6pt}} -\def\cbr{{\hskip 6pt\circle\char'011}} -\def\carttop{\hbox to \cartouter{\hskip\lskip - \ctl\leaders\hrule height\circthick\hfil\ctr - \hskip\rskip}} -\def\cartbot{\hbox to \cartouter{\hskip\lskip - \cbl\leaders\hrule height\circthick\hfil\cbr - \hskip\rskip}} -% -\newskip\lskip\newskip\rskip - -\envdef\cartouche{% - \ifhmode\par\fi % can't be in the midst of a paragraph. - \startsavinginserts - \lskip=\leftskip \rskip=\rightskip - \leftskip=0pt\rightskip=0pt % we want these *outside*. - \cartinner=\hsize \advance\cartinner by-\lskip - \advance\cartinner by-\rskip - \cartouter=\hsize - \advance\cartouter by 18.4pt % allow for 3pt kerns on either - % side, and for 6pt waste from - % each corner char, and rule thickness - \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip - % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing = t% - % - % If this cartouche directly follows a sectioning command, we need the - % \parskip glue (backspaced over by default) or the cartouche can - % collide with the section heading. - \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi - % - \vbox\bgroup - \baselineskip=0pt\parskip=0pt\lineskip=0pt - \carttop - \hbox\bgroup - \hskip\lskip - \vrule\kern3pt - \vbox\bgroup - \kern3pt - \hsize=\cartinner - \baselineskip=\normbskip - \lineskip=\normlskip - \parskip=\normpskip - \vskip -\parskip - \comment % For explanation, see the end of def\group. -} -\def\Ecartouche{% - \ifhmode\par\fi - \kern3pt - \egroup - \kern3pt\vrule - \hskip\rskip - \egroup - \cartbot - \egroup - \checkinserts -} - - -% This macro is called at the beginning of all the @example variants, -% inside a group. -\newdimen\nonfillparindent -\def\nonfillstart{% - \aboveenvbreak - \hfuzz = 12pt % Don't be fussy - \sepspaces % Make spaces be word-separators rather than space tokens. - \let\par = \lisppar % don't ignore blank lines - \obeylines % each line of input is a line of output - \parskip = 0pt - % Turn off paragraph indentation but redefine \indent to emulate - % the normal \indent. - \nonfillparindent=\parindent - \parindent = 0pt - \let\indent\nonfillindent - % - \emergencystretch = 0pt % don't try to avoid overfull boxes - \ifx\nonarrowing\relax - \advance \leftskip by \lispnarrowing - \exdentamount=\lispnarrowing - \else - \let\nonarrowing = \relax - \fi - \let\exdent=\nofillexdent -} - -\begingroup -\obeyspaces -% We want to swallow spaces (but not other tokens) after the fake -% @indent in our nonfill-environments, where spaces are normally -% active and set to @tie, resulting in them not being ignored after -% @indent. -\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}% -\gdef\nonfillindentcheck{% -\ifx\temp % -\expandafter\nonfillindentgobble% -\else% -\leavevmode\nonfillindentbox% -\fi% -}% -\endgroup -\def\nonfillindentgobble#1{\nonfillindent} -\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}} - -% If you want all examples etc. small: @set dispenvsize small. -% If you want even small examples the full size: @set dispenvsize nosmall. -% This affects the following displayed environments: -% @example, @display, @format, @lisp -% -\def\smallword{small} -\def\nosmallword{nosmall} -\let\SETdispenvsize\relax -\def\setnormaldispenv{% - \ifx\SETdispenvsize\smallword - % end paragraph for sake of leading, in case document has no blank - % line. This is redundant with what happens in \aboveenvbreak, but - % we need to do it before changing the fonts, and it's inconvenient - % to change the fonts afterward. - \ifnum \lastpenalty=10000 \else \endgraf \fi - \smallexamplefonts \rm - \fi -} -\def\setsmalldispenv{% - \ifx\SETdispenvsize\nosmallword - \else - \ifnum \lastpenalty=10000 \else \endgraf \fi - \smallexamplefonts \rm - \fi -} - -% We often define two environments, @foo and @smallfoo. -% Let's do it in one command. #1 is the env name, #2 the definition. -\def\makedispenvdef#1#2{% - \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}% - \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}% - \expandafter\let\csname E#1\endcsname \afterenvbreak - \expandafter\let\csname Esmall#1\endcsname \afterenvbreak -} - -% Define two environment synonyms (#1 and #2) for an environment. -\def\maketwodispenvdef#1#2#3{% - \makedispenvdef{#1}{#3}% - \makedispenvdef{#2}{#3}% -} -% -% @lisp: indented, narrowed, typewriter font; -% @example: same as @lisp. -% -% @smallexample and @smalllisp: use smaller fonts. -% Originally contributed by Pavel@xerox. -% -\maketwodispenvdef{lisp}{example}{% - \nonfillstart - \tt\setupmarkupstyle{example}% - \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. - \gobble % eat return -} -% @display/@smalldisplay: same as @lisp except keep current font. -% -\makedispenvdef{display}{% - \nonfillstart - \gobble -} - -% @format/@smallformat: same as @display except don't narrow margins. -% -\makedispenvdef{format}{% - \let\nonarrowing = t% - \nonfillstart - \gobble -} - -% @flushleft: same as @format, but doesn't obey \SETdispenvsize. -\envdef\flushleft{% - \let\nonarrowing = t% - \nonfillstart - \gobble -} -\let\Eflushleft = \afterenvbreak - -% @flushright. -% -\envdef\flushright{% - \let\nonarrowing = t% - \nonfillstart - \advance\leftskip by 0pt plus 1fill\relax - \gobble -} -\let\Eflushright = \afterenvbreak - - -% @raggedright does more-or-less normal line breaking but no right -% justification. From plain.tex. -\envdef\raggedright{% - \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax -} -\let\Eraggedright\par - -\envdef\raggedleft{% - \parindent=0pt \leftskip0pt plus2em - \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt - \hbadness=10000 % Last line will usually be underfull, so turn off - % badness reporting. -} -\let\Eraggedleft\par - -\envdef\raggedcenter{% - \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em - \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt - \hbadness=10000 % Last line will usually be underfull, so turn off - % badness reporting. -} -\let\Eraggedcenter\par - - -% @quotation does normal linebreaking (hence we can't use \nonfillstart) -% and narrows the margins. We keep \parskip nonzero in general, since -% we're doing normal filling. So, when using \aboveenvbreak and -% \afterenvbreak, temporarily make \parskip 0. -% -\makedispenvdef{quotation}{\quotationstart} -% -\def\quotationstart{% - \indentedblockstart % same as \indentedblock, but increase right margin too. - \ifx\nonarrowing\relax - \advance\rightskip by \lispnarrowing - \fi - \parsearg\quotationlabel -} - -% We have retained a nonzero parskip for the environment, since we're -% doing normal filling. -% -\def\Equotation{% - \par - \ifx\quotationauthor\thisisundefined\else - % indent a bit. - \leftline{\kern 2\leftskip \sl ---\quotationauthor}% - \fi - {\parskip=0pt \afterenvbreak}% -} -\def\Esmallquotation{\Equotation} - -% If we're given an argument, typeset it in bold with a colon after. -\def\quotationlabel#1{% - \def\temp{#1}% - \ifx\temp\empty \else - {\bf #1: }% - \fi -} - -% @indentedblock is like @quotation, but indents only on the left and -% has no optional argument. -% -\makedispenvdef{indentedblock}{\indentedblockstart} -% -\def\indentedblockstart{% - {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip - \parindent=0pt - % - % @cartouche defines \nonarrowing to inhibit narrowing at next level down. - \ifx\nonarrowing\relax - \advance\leftskip by \lispnarrowing - \exdentamount = \lispnarrowing - \else - \let\nonarrowing = \relax - \fi -} - -% Keep a nonzero parskip for the environment, since we're doing normal filling. -% -\def\Eindentedblock{% - \par - {\parskip=0pt \afterenvbreak}% -} -\def\Esmallindentedblock{\Eindentedblock} - - -% LaTeX-like @verbatim...@end verbatim and @verb{...} -% If we want to allow any as delimiter, -% we need the curly braces so that makeinfo sees the @verb command, eg: -% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org -% -% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. -% -% [Knuth] p.344; only we need to do the other characters Texinfo sets -% active too. Otherwise, they get lost as the first character on a -% verbatim line. -\def\dospecials{% - \do\ \do\\\do\{\do\}\do\$\do\&% - \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% - \do\<\do\>\do\|\do\@\do+\do\"% - % Don't do the quotes -- if we do, @set txicodequoteundirected and - % @set txicodequotebacktick will not have effect on @verb and - % @verbatim, and ?` and !` ligatures won't get disabled. - %\do\`\do\'% -} -% -% [Knuth] p. 380 -\def\uncatcodespecials{% - \def\do##1{\catcode`##1=\other}\dospecials} -% -% Setup for the @verb command. -% -% Eight spaces for a tab -\begingroup - \catcode`\^^I=\active - \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} -\endgroup -% -\def\setupverb{% - \tt % easiest (and conventionally used) font for verbatim - \def\par{\leavevmode\endgraf}% - \setupmarkupstyle{verb}% - \tabeightspaces - % Respect line breaks, - % print special symbols as themselves, and - % make each space count - % must do in this order: - \obeylines \uncatcodespecials \sepspaces -} - -% Setup for the @verbatim environment -% -% Real tab expansion. -\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount -% -% We typeset each line of the verbatim in an \hbox, so we can handle -% tabs. The \global is in case the verbatim line starts with an accent, -% or some other command that starts with a begin-group. Otherwise, the -% entire \verbbox would disappear at the corresponding end-group, before -% it is typeset. Meanwhile, we can't have nested verbatim commands -% (can we?), so the \global won't be overwriting itself. -\newbox\verbbox -\def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} -% -\begingroup - \catcode`\^^I=\active - \gdef\tabexpand{% - \catcode`\^^I=\active - \def^^I{\leavevmode\egroup - \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab - \divide\dimen\verbbox by\tabw - \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw - \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw - \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox - }% - } -\endgroup - -% start the verbatim environment. -\def\setupverbatim{% - \let\nonarrowing = t% - \nonfillstart - \tt % easiest (and conventionally used) font for verbatim - % The \leavevmode here is for blank lines. Otherwise, we would - % never \starttabox and the \egroup would end verbatim mode. - \def\par{\leavevmode\egroup\box\verbbox\endgraf}% - \tabexpand - \setupmarkupstyle{verbatim}% - % Respect line breaks, - % print special symbols as themselves, and - % make each space count. - % Must do in this order: - \obeylines \uncatcodespecials \sepspaces - \everypar{\starttabbox}% -} - -% Do the @verb magic: verbatim text is quoted by unique -% delimiter characters. Before first delimiter expect a -% right brace, after last delimiter expect closing brace: -% -% \def\doverb'{'#1'}'{#1} -% -% [Knuth] p. 382; only eat outer {} -\begingroup - \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other - \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] -\endgroup -% -\def\verb{\begingroup\setupverb\doverb} -% -% -% Do the @verbatim magic: define the macro \doverbatim so that -% the (first) argument ends when '@end verbatim' is reached, ie: -% -% \def\doverbatim#1@end verbatim{#1} -% -% For Texinfo it's a lot easier than for LaTeX, -% because texinfo's \verbatim doesn't stop at '\end{verbatim}': -% we need not redefine '\', '{' and '}'. -% -% Inspired by LaTeX's verbatim command set [latex.ltx] -% -\begingroup - \catcode`\ =\active - \obeylines % - % ignore everything up to the first ^^M, that's the newline at the end - % of the @verbatim input line itself. Otherwise we get an extra blank - % line in the output. - \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% - % We really want {...\end verbatim} in the body of the macro, but - % without the active space; thus we have to use \xdef and \gobble. -\endgroup -% -\envdef\verbatim{% - \setupverbatim\doverbatim -} -\let\Everbatim = \afterenvbreak - - -% @verbatiminclude FILE - insert text of file in verbatim environment. -% -\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} -% -\def\doverbatiminclude#1{% - {% - \makevalueexpandable - \setupverbatim - \indexnofonts % Allow `@@' and other weird things in file names. - \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% - \input #1 - \afterenvbreak - }% -} - -% @copying ... @end copying. -% Save the text away for @insertcopying later. -% -% We save the uninterpreted tokens, rather than creating a box. -% Saving the text in a box would be much easier, but then all the -% typesetting commands (@smallbook, font changes, etc.) have to be done -% beforehand -- and a) we want @copying to be done first in the source -% file; b) letting users define the frontmatter in as flexible order as -% possible is very desirable. -% -\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} -\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} -% -\def\insertcopying{% - \begingroup - \parindent = 0pt % paragraph indentation looks wrong on title page - \scanexp\copyingtext - \endgroup -} - - -\message{defuns,} -% @defun etc. - -\newskip\defbodyindent \defbodyindent=.4in -\newskip\defargsindent \defargsindent=50pt -\newskip\deflastargmargin \deflastargmargin=18pt -\newcount\defunpenalty - -% Start the processing of @deffn: -\def\startdefun{% - \ifnum\lastpenalty<10000 - \medbreak - \defunpenalty=10003 % Will keep this @deffn together with the - % following @def command, see below. - \else - % If there are two @def commands in a row, we'll have a \nobreak, - % which is there to keep the function description together with its - % header. But if there's nothing but headers, we need to allow a - % break somewhere. Check specifically for penalty 10002, inserted - % by \printdefunline, instead of 10000, since the sectioning - % commands also insert a nobreak penalty, and we don't want to allow - % a break between a section heading and a defun. - % - % As a further refinement, we avoid "club" headers by signalling - % with penalty of 10003 after the very first @deffn in the - % sequence (see above), and penalty of 10002 after any following - % @def command. - \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi - % - % Similarly, after a section heading, do not allow a break. - % But do insert the glue. - \medskip % preceded by discardable penalty, so not a breakpoint - \fi - % - \parindent=0in - \advance\leftskip by \defbodyindent - \exdentamount=\defbodyindent -} - -\def\dodefunx#1{% - % First, check whether we are in the right environment: - \checkenv#1% - % - % As above, allow line break if we have multiple x headers in a row. - % It's not a great place, though. - \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi - % - % And now, it's time to reuse the body of the original defun: - \expandafter\gobbledefun#1% -} -\def\gobbledefun#1\startdefun{} - -% \printdefunline \deffnheader{text} -% -\def\printdefunline#1#2{% - \begingroup - % call \deffnheader: - #1#2 \endheader - % common ending: - \interlinepenalty = 10000 - \advance\rightskip by 0pt plus 1fil\relax - \endgraf - \nobreak\vskip -\parskip - \penalty\defunpenalty % signal to \startdefun and \dodefunx - % Some of the @defun-type tags do not enable magic parentheses, - % rendering the following check redundant. But we don't optimize. - \checkparencounts - \endgroup -} - -\def\Edefun{\endgraf\medbreak} - -% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; -% the only thing remaining is to define \deffnheader. -% -\def\makedefun#1{% - \expandafter\let\csname E#1\endcsname = \Edefun - \edef\temp{\noexpand\domakedefun - \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% - \temp -} - -% \domakedefun \deffn \deffnx \deffnheader -% -% Define \deffn and \deffnx, without parameters. -% \deffnheader has to be defined explicitly. -% -\def\domakedefun#1#2#3{% - \envdef#1{% - \startdefun - \doingtypefnfalse % distinguish typed functions from all else - \parseargusing\activeparens{\printdefunline#3}% - }% - \def#2{\dodefunx#1}% - \def#3% -} - -\newif\ifdoingtypefn % doing typed function? -\newif\ifrettypeownline % typeset return type on its own line? - -% @deftypefnnewline on|off says whether the return type of typed functions -% are printed on their own line. This affects @deftypefn, @deftypefun, -% @deftypeop, and @deftypemethod. -% -\parseargdef\deftypefnnewline{% - \def\temp{#1}% - \ifx\temp\onword - \expandafter\let\csname SETtxideftypefnnl\endcsname - = \empty - \else\ifx\temp\offword - \expandafter\let\csname SETtxideftypefnnl\endcsname - = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @txideftypefnnl value `\temp', - must be on|off}% - \fi\fi -} - -% Untyped functions: - -% @deffn category name args -\makedefun{deffn}{\deffngeneral{}} - -% @deffn category class name args -\makedefun{defop}#1 {\defopon{#1\ \putwordon}} - -% \defopon {category on}class name args -\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } - -% \deffngeneral {subind}category name args -% -\def\deffngeneral#1#2 #3 #4\endheader{% - % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. - \dosubind{fn}{\code{#3}}{#1}% - \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% -} - -% Typed functions: - -% @deftypefn category type name args -\makedefun{deftypefn}{\deftypefngeneral{}} - -% @deftypeop category class type name args -\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} - -% \deftypeopon {category on}class type name args -\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } - -% \deftypefngeneral {subind}category type name args -% -\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% - \dosubind{fn}{\code{#4}}{#1}% - \doingtypefntrue - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% -} - -% Typed variables: - -% @deftypevr category type var args -\makedefun{deftypevr}{\deftypecvgeneral{}} - -% @deftypecv category class type var args -\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} - -% \deftypecvof {category of}class type var args -\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } - -% \deftypecvgeneral {subind}category type var args -% -\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% - \dosubind{vr}{\code{#4}}{#1}% - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% -} - -% Untyped variables: - -% @defvr category var args -\makedefun{defvr}#1 {\deftypevrheader{#1} {} } - -% @defcv category class var args -\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} - -% \defcvof {category of}class var args -\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } - -% Types: - -% @deftp category name args -\makedefun{deftp}#1 #2 #3\endheader{% - \doind{tp}{\code{#2}}% - \defname{#1}{}{#2}\defunargs{#3\unskip}% -} - -% Remaining @defun-like shortcuts: -\makedefun{defun}{\deffnheader{\putwordDeffunc} } -\makedefun{defmac}{\deffnheader{\putwordDefmac} } -\makedefun{defspec}{\deffnheader{\putwordDefspec} } -\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } -\makedefun{defvar}{\defvrheader{\putwordDefvar} } -\makedefun{defopt}{\defvrheader{\putwordDefopt} } -\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } -\makedefun{defmethod}{\defopon\putwordMethodon} -\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} -\makedefun{defivar}{\defcvof\putwordInstanceVariableof} -\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} - -% \defname, which formats the name of the @def (not the args). -% #1 is the category, such as "Function". -% #2 is the return type, if any. -% #3 is the function name. -% -% We are followed by (but not passed) the arguments, if any. -% -\def\defname#1#2#3{% - \par - % Get the values of \leftskip and \rightskip as they were outside the @def... - \advance\leftskip by -\defbodyindent - % - % Determine if we are typesetting the return type of a typed function - % on a line by itself. - \rettypeownlinefalse - \ifdoingtypefn % doing a typed function specifically? - % then check user option for putting return type on its own line: - \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else - \rettypeownlinetrue - \fi - \fi - % - % How we'll format the category name. Putting it in brackets helps - % distinguish it from the body text that may end up on the next line - % just below it. - \def\temp{#1}% - \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} - % - % Figure out line sizes for the paragraph shape. We'll always have at - % least two. - \tempnum = 2 - % - % The first line needs space for \box0; but if \rightskip is nonzero, - % we need only space for the part of \box0 which exceeds it: - \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip - % - % If doing a return type on its own line, we'll have another line. - \ifrettypeownline - \advance\tempnum by 1 - \def\maybeshapeline{0in \hsize}% - \else - \def\maybeshapeline{}% - \fi - % - % The continuations: - \dimen2=\hsize \advance\dimen2 by -\defargsindent - % - % The final paragraph shape: - \parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2 - % - % Put the category name at the right margin. - \noindent - \hbox to 0pt{% - \hfil\box0 \kern-\hsize - % \hsize has to be shortened this way: - \kern\leftskip - % Intentionally do not respect \rightskip, since we need the space. - }% - % - % Allow all lines to be underfull without complaint: - \tolerance=10000 \hbadness=10000 - \exdentamount=\defbodyindent - {% - % defun fonts. We use typewriter by default (used to be bold) because: - % . we're printing identifiers, they should be in tt in principle. - % . in languages with many accents, such as Czech or French, it's - % common to leave accents off identifiers. The result looks ok in - % tt, but exceedingly strange in rm. - % . we don't want -- and --- to be treated as ligatures. - % . this still does not fix the ?` and !` ligatures, but so far no - % one has made identifiers using them :). - \df \tt - \def\temp{#2}% text of the return type - \ifx\temp\empty\else - \tclose{\temp}% typeset the return type - \ifrettypeownline - % put return type on its own line; prohibit line break following: - \hfil\vadjust{\nobreak}\break - \else - \space % type on same line, so just followed by a space - \fi - \fi % no return type - #3% output function name - }% - {\rm\enskip}% hskip 0.5 em of \tenrm - % - \boldbrax - % arguments will be output next, if any. -} - -% Print arguments in slanted roman (not ttsl), inconsistently with using -% tt for the name. This is because literal text is sometimes needed in -% the argument list (groff manual), and ttsl and tt are not very -% distinguishable. Prevent hyphenation at `-' chars. -% -\def\defunargs#1{% - % use sl by default (not ttsl), - % tt for the names. - \df \sl \hyphenchar\font=0 - % - % On the other hand, if an argument has two dashes (for instance), we - % want a way to get ttsl. We used to recommend @var for that, so - % leave the code in, but it's strange for @var to lead to typewriter. - % Nowadays we recommend @code, since the difference between a ttsl hyphen - % and a tt hyphen is pretty tiny. @code also disables ?` !`. - \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% - #1% - \sl\hyphenchar\font=45 -} - -% We want ()&[] to print specially on the defun line. -% -\def\activeparens{% - \catcode`\(=\active \catcode`\)=\active - \catcode`\[=\active \catcode`\]=\active - \catcode`\&=\active -} - -% Make control sequences which act like normal parenthesis chars. -\let\lparen = ( \let\rparen = ) - -% Be sure that we always have a definition for `(', etc. For example, -% if the fn name has parens in it, \boldbrax will not be in effect yet, -% so TeX would otherwise complain about undefined control sequence. -{ - \activeparens - \global\let(=\lparen \global\let)=\rparen - \global\let[=\lbrack \global\let]=\rbrack - \global\let& = \& - - \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} - \gdef\magicamp{\let&=\amprm} -} - -\newcount\parencount - -% If we encounter &foo, then turn on ()-hacking afterwards -\newif\ifampseen -\def\amprm#1 {\ampseentrue{\bf\ }} - -\def\parenfont{% - \ifampseen - % At the first level, print parens in roman, - % otherwise use the default font. - \ifnum \parencount=1 \rm \fi - \else - % The \sf parens (in \boldbrax) actually are a little bolder than - % the contained text. This is especially needed for [ and ] . - \sf - \fi -} -\def\infirstlevel#1{% - \ifampseen - \ifnum\parencount=1 - #1% - \fi - \fi -} -\def\bfafterword#1 {#1 \bf} - -\def\opnr{% - \global\advance\parencount by 1 - {\parenfont(}% - \infirstlevel \bfafterword -} -\def\clnr{% - {\parenfont)}% - \infirstlevel \sl - \global\advance\parencount by -1 -} - -\newcount\brackcount -\def\lbrb{% - \global\advance\brackcount by 1 - {\bf[}% -} -\def\rbrb{% - {\bf]}% - \global\advance\brackcount by -1 -} - -\def\checkparencounts{% - \ifnum\parencount=0 \else \badparencount \fi - \ifnum\brackcount=0 \else \badbrackcount \fi -} -% these should not use \errmessage; the glibc manual, at least, actually -% has such constructs (when documenting function pointers). -\def\badparencount{% - \message{Warning: unbalanced parentheses in @def...}% - \global\parencount=0 -} -\def\badbrackcount{% - \message{Warning: unbalanced square brackets in @def...}% - \global\brackcount=0 -} - - -\message{macros,} -% @macro. - -% To do this right we need a feature of e-TeX, \scantokens, -% which we arrange to emulate with a temporary file in ordinary TeX. -\ifx\eTeXversion\thisisundefined - \newwrite\macscribble - \def\scantokens#1{% - \toks0={#1}% - \immediate\openout\macscribble=\jobname.tmp - \immediate\write\macscribble{\the\toks0}% - \immediate\closeout\macscribble - \input \jobname.tmp - } -\fi - -\def\scanmacro#1{\begingroup - \newlinechar`\^^M - \let\xeatspaces\eatspaces - % - % Undo catcode changes of \startcontents and \doprintindex - % When called from @insertcopying or (short)caption, we need active - % backslash to get it printed correctly. Previously, we had - % \catcode`\\=\other instead. We'll see whether a problem appears - % with macro expansion. --kasal, 19aug04 - \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ - % - % ... and for \example: - \spaceisspace - % - % The \empty here causes a following catcode 5 newline to be eaten as - % part of reading whitespace after a control sequence. It does not - % eat a catcode 13 newline. There's no good way to handle the two - % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX - % would then have different behavior). See the Macro Details node in - % the manual for the workaround we recommend for macros and - % line-oriented commands. - % - \scantokens{#1\empty}% -\endgroup} - -\def\scanexp#1{% - \edef\temp{\noexpand\scanmacro{#1}}% - \temp -} - -\newcount\paramno % Count of parameters -\newtoks\macname % Macro name -\newif\ifrecursive % Is it recursive? - -% List of all defined macros in the form -% \definedummyword\macro1\definedummyword\macro2... -% Currently is also contains all @aliases; the list can be split -% if there is a need. -\def\macrolist{} - -% Add the macro to \macrolist -\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} -\def\addtomacrolistxxx#1{% - \toks0 = \expandafter{\macrolist\definedummyword#1}% - \xdef\macrolist{\the\toks0}% -} - -% Utility routines. -% This does \let #1 = #2, with \csnames; that is, -% \let \csname#1\endcsname = \csname#2\endcsname -% (except of course we have to play expansion games). -% -\def\cslet#1#2{% - \expandafter\let - \csname#1\expandafter\endcsname - \csname#2\endcsname -} - -% Trim leading and trailing spaces off a string. -% Concepts from aro-bend problem 15 (see CTAN). -{\catcode`\@=11 -\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} -\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} -\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} -\def\unbrace#1{#1} -\unbrace{\gdef\trim@@@ #1 } #2@{#1} -} - -% Trim a single trailing ^^M off a string. -{\catcode`\^^M=\other \catcode`\Q=3% -\gdef\eatcr #1{\eatcra #1Q^^MQ}% -\gdef\eatcra#1^^MQ{\eatcrb#1Q}% -\gdef\eatcrb#1Q#2Q{#1}% -} - -% Macro bodies are absorbed as an argument in a context where -% all characters are catcode 10, 11 or 12, except \ which is active -% (as in normal texinfo). It is necessary to change the definition of \ -% to recognize macro arguments; this is the job of \mbodybackslash. -% -% Non-ASCII encodings make 8-bit characters active, so un-activate -% them to avoid their expansion. Must do this non-globally, to -% confine the change to the current group. -% -% It's necessary to have hard CRs when the macro is executed. This is -% done by making ^^M (\endlinechar) catcode 12 when reading the macro -% body, and then making it the \newlinechar in \scanmacro. -% -\def\scanctxt{% used as subroutine - \catcode`\"=\other - \catcode`\+=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\@=\other - \catcode`\^=\other - \catcode`\_=\other - \catcode`\|=\other - \catcode`\~=\other - \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi -} - -\def\scanargctxt{% used for copying and captions, not macros. - \scanctxt - \catcode`\\=\other - \catcode`\^^M=\other -} - -\def\macrobodyctxt{% used for @macro definitions - \scanctxt - \catcode`\{=\other - \catcode`\}=\other - \catcode`\^^M=\other - \usembodybackslash -} - -\def\macroargctxt{% used when scanning invocations - \scanctxt - \catcode`\\=0 -} -% why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes" -% for the single characters \ { }. Thus, we end up with the "commands" -% that would be written @\ @{ @} in a Texinfo document. -% -% We already have @{ and @}. For @\, we define it here, and only for -% this purpose, to produce a typewriter backslash (so, the @\ that we -% define for @math can't be used with @macro calls): -% -\def\\{\normalbackslash}% -% -% We would like to do this for \, too, since that is what makeinfo does. -% But it is not possible, because Texinfo already has a command @, for a -% cedilla accent. Documents must use @comma{} instead. -% -% \anythingelse will almost certainly be an error of some kind. - - -% \mbodybackslash is the definition of \ in @macro bodies. -% It maps \foo\ => \csname macarg.foo\endcsname => #N -% where N is the macro parameter number. -% We define \csname macarg.\endcsname to be \realbackslash, so -% \\ in macro replacement text gets you a backslash. -% -{\catcode`@=0 @catcode`@\=@active - @gdef@usembodybackslash{@let\=@mbodybackslash} - @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} -} -\expandafter\def\csname macarg.\endcsname{\realbackslash} - -\def\margbackslash#1{\char`\#1 } - -\def\macro{\recursivefalse\parsearg\macroxxx} -\def\rmacro{\recursivetrue\parsearg\macroxxx} - -\def\macroxxx#1{% - \getargs{#1}% now \macname is the macname and \argl the arglist - \ifx\argl\empty % no arguments - \paramno=0\relax - \else - \expandafter\parsemargdef \argl;% - \if\paramno>256\relax - \ifx\eTeXversion\thisisundefined - \errhelp = \EMsimple - \errmessage{You need eTeX to compile a file with macros with more than 256 arguments} - \fi - \fi - \fi - \if1\csname ismacro.\the\macname\endcsname - \message{Warning: redefining \the\macname}% - \else - \expandafter\ifx\csname \the\macname\endcsname \relax - \else \errmessage{Macro name \the\macname\space already defined}\fi - \global\cslet{macsave.\the\macname}{\the\macname}% - \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% - \addtomacrolist{\the\macname}% - \fi - \begingroup \macrobodyctxt - \ifrecursive \expandafter\parsermacbody - \else \expandafter\parsemacbody - \fi} - -\parseargdef\unmacro{% - \if1\csname ismacro.#1\endcsname - \global\cslet{#1}{macsave.#1}% - \global\expandafter\let \csname ismacro.#1\endcsname=0% - % Remove the macro name from \macrolist: - \begingroup - \expandafter\let\csname#1\endcsname \relax - \let\definedummyword\unmacrodo - \xdef\macrolist{\macrolist}% - \endgroup - \else - \errmessage{Macro #1 not defined}% - \fi -} - -% Called by \do from \dounmacro on each macro. The idea is to omit any -% macro definitions that have been changed to \relax. -% -\def\unmacrodo#1{% - \ifx #1\relax - % remove this - \else - \noexpand\definedummyword \noexpand#1% - \fi -} - -% This makes use of the obscure feature that if the last token of a -% is #, then the preceding argument is delimited by -% an opening brace, and that opening brace is not consumed. -\def\getargs#1{\getargsxxx#1{}} -\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} -\def\getmacname#1 #2\relax{\macname={#1}} -\def\getmacargs#1{\def\argl{#1}} - -% For macro processing make @ a letter so that we can make Texinfo private macro names. -\edef\texiatcatcode{\the\catcode`\@} -\catcode `@=11\relax - -% Parse the optional {params} list. Set up \paramno and \paramlist -% so \defmacro knows what to do. Define \macarg.BLAH for each BLAH -% in the params list to some hook where the argument si to be expanded. If -% there are less than 10 arguments that hook is to be replaced by ##N where N -% is the position in that list, that is to say the macro arguments are to be -% defined `a la TeX in the macro body. -% -% That gets used by \mbodybackslash (above). -% -% We need to get `macro parameter char #' into several definitions. -% The technique used is stolen from LaTeX: let \hash be something -% unexpandable, insert that wherever you need a #, and then redefine -% it to # just before using the token list produced. -% -% The same technique is used to protect \eatspaces till just before -% the macro is used. -% -% If there are 10 or more arguments, a different technique is used, where the -% hook remains in the body, and when macro is to be expanded the body is -% processed again to replace the arguments. -% -% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the -% argument N value and then \edef the body (nothing else will expand because of -% the catcode regime underwhich the body was input). -% -% If you compile with TeX (not eTeX), and you have macros with 10 or more -% arguments, you need that no macro has more than 256 arguments, otherwise an -% error is produced. -\def\parsemargdef#1;{% - \paramno=0\def\paramlist{}% - \let\hash\relax - \let\xeatspaces\relax - \parsemargdefxxx#1,;,% - % In case that there are 10 or more arguments we parse again the arguments - % list to set new definitions for the \macarg.BLAH macros corresponding to - % each BLAH argument. It was anyhow needed to parse already once this list - % in order to count the arguments, and as macros with at most 9 arguments - % are by far more frequent than macro with 10 or more arguments, defining - % twice the \macarg.BLAH macros does not cost too much processing power. - \ifnum\paramno<10\relax\else - \paramno0\relax - \parsemmanyargdef@@#1,;,% 10 or more arguments - \fi -} -\def\parsemargdefxxx#1,{% - \if#1;\let\next=\relax - \else \let\next=\parsemargdefxxx - \advance\paramno by 1 - \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname - {\xeatspaces{\hash\the\paramno}}% - \edef\paramlist{\paramlist\hash\the\paramno,}% - \fi\next} - -\def\parsemmanyargdef@@#1,{% - \if#1;\let\next=\relax - \else - \let\next=\parsemmanyargdef@@ - \edef\tempb{\eatspaces{#1}}% - \expandafter\def\expandafter\tempa - \expandafter{\csname macarg.\tempb\endcsname}% - % Note that we need some extra \noexpand\noexpand, this is because we - % don't want \the to be expanded in the \parsermacbody as it uses an - % \xdef . - \expandafter\edef\tempa - {\noexpand\noexpand\noexpand\the\toks\the\paramno}% - \advance\paramno by 1\relax - \fi\next} - -% These two commands read recursive and nonrecursive macro bodies. -% (They're different since rec and nonrec macros end differently.) -% - -\catcode `\@\texiatcatcode -\long\def\parsemacbody#1@end macro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\long\def\parsermacbody#1@end rmacro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\catcode `\@=11\relax - -\let\endargs@\relax -\let\nil@\relax -\def\nilm@{\nil@}% -\long\def\nillm@{\nil@}% - -% This macro is expanded during the Texinfo macro expansion, not during its -% definition. It gets all the arguments values and assigns them to macros -% macarg.ARGNAME -% -% #1 is the macro name -% #2 is the list of argument names -% #3 is the list of argument values -\def\getargvals@#1#2#3{% - \def\macargdeflist@{}% - \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion. - \def\paramlist{#2,\nil@}% - \def\macroname{#1}% - \begingroup - \macroargctxt - \def\argvaluelist{#3,\nil@}% - \def\@tempa{#3}% - \ifx\@tempa\empty - \setemptyargvalues@ - \else - \getargvals@@ - \fi -} - -% -\def\getargvals@@{% - \ifx\paramlist\nilm@ - % Some sanity check needed here that \argvaluelist is also empty. - \ifx\argvaluelist\nillm@ - \else - \errhelp = \EMsimple - \errmessage{Too many arguments in macro `\macroname'!}% - \fi - \let\next\macargexpandinbody@ - \else - \ifx\argvaluelist\nillm@ - % No more arguments values passed to macro. Set remaining named-arg - % macros to empty. - \let\next\setemptyargvalues@ - \else - % pop current arg name into \@tempb - \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}% - \expandafter\@tempa\expandafter{\paramlist}% - % pop current argument value into \@tempc - \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}% - \expandafter\@tempa\expandafter{\argvaluelist}% - % Here \@tempb is the current arg name and \@tempc is the current arg value. - % First place the new argument macro definition into \@tempd - \expandafter\macname\expandafter{\@tempc}% - \expandafter\let\csname macarg.\@tempb\endcsname\relax - \expandafter\def\expandafter\@tempe\expandafter{% - \csname macarg.\@tempb\endcsname}% - \edef\@tempd{\long\def\@tempe{\the\macname}}% - \push@\@tempd\macargdeflist@ - \let\next\getargvals@@ - \fi - \fi - \next -} - -\def\push@#1#2{% - \expandafter\expandafter\expandafter\def - \expandafter\expandafter\expandafter#2% - \expandafter\expandafter\expandafter{% - \expandafter#1#2}% -} - -% Replace arguments by their values in the macro body, and place the result -% in macro \@tempa -\def\macvalstoargs@{% - % To do this we use the property that token registers that are \the'ed - % within an \edef expand only once. So we are going to place all argument - % values into respective token registers. - % - % First we save the token context, and initialize argument numbering. - \begingroup - \paramno0\relax - % Then, for each argument number #N, we place the corresponding argument - % value into a new token list register \toks#N - \expandafter\putargsintokens@\saveparamlist@,;,% - % Then, we expand the body so that argument are replaced by their - % values. The trick for values not to be expanded themselves is that they - % are within tokens and that tokens expand only once in an \edef . - \edef\@tempc{\csname mac.\macroname .body\endcsname}% - % Now we restore the token stack pointer to free the token list registers - % which we have used, but we make sure that expanded body is saved after - % group. - \expandafter - \endgroup - \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% - } - -\def\macargexpandinbody@{% - %% Define the named-macro outside of this group and then close this group. - \expandafter - \endgroup - \macargdeflist@ - % First the replace in body the macro arguments by their values, the result - % is in \@tempa . - \macvalstoargs@ - % Then we point at the \norecurse or \gobble (for recursive) macro value - % with \@tempb . - \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname - % Depending on whether it is recursive or not, we need some tailing - % \egroup . - \ifx\@tempb\gobble - \let\@tempc\relax - \else - \let\@tempc\egroup - \fi - % And now we do the real job: - \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}% - \@tempd -} - -\def\putargsintokens@#1,{% - \if#1;\let\next\relax - \else - \let\next\putargsintokens@ - % First we allocate the new token list register, and give it a temporary - % alias \@tempb . - \toksdef\@tempb\the\paramno - % Then we place the argument value into that token list register. - \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname - \expandafter\@tempb\expandafter{\@tempa}% - \advance\paramno by 1\relax - \fi - \next -} - -% Save the token stack pointer into macro #1 -\def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}} -% Restore the token stack pointer from number in macro #1 -\def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax} -% newtoks that can be used non \outer . -\def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi} - -% Tailing missing arguments are set to empty -\def\setemptyargvalues@{% - \ifx\paramlist\nilm@ - \let\next\macargexpandinbody@ - \else - \expandafter\setemptyargvaluesparser@\paramlist\endargs@ - \let\next\setemptyargvalues@ - \fi - \next -} - -\def\setemptyargvaluesparser@#1,#2\endargs@{% - \expandafter\def\expandafter\@tempa\expandafter{% - \expandafter\def\csname macarg.#1\endcsname{}}% - \push@\@tempa\macargdeflist@ - \def\paramlist{#2}% -} - -% #1 is the element target macro -% #2 is the list macro -% #3,#4\endargs@ is the list value -\def\pop@#1#2#3,#4\endargs@{% - \def#1{#3}% - \def#2{#4}% -} -\long\def\longpop@#1#2#3,#4\endargs@{% - \long\def#1{#3}% - \long\def#2{#4}% -} - -% This defines a Texinfo @macro. There are eight cases: recursive and -% nonrecursive macros of zero, one, up to nine, and many arguments. -% Much magic with \expandafter here. -% \xdef is used so that macro definitions will survive the file -% they're defined in; @include reads the file inside a group. -% -\def\defmacro{% - \let\hash=##% convert placeholders to macro parameter chars - \ifrecursive - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\scanmacro{\temp}}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup\noexpand\scanmacro{\temp}}% - \else - \ifnum\paramno<10\relax % at most 9 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{\egroup\noexpand\scanmacro{\temp}}% - \else % 10 or more - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\getargvals@{\the\macname}{\argl}% - }% - \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp - \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble - \fi - \fi - \else - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % at most 9 - \ifnum\paramno<10\relax - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \expandafter\noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % 10 or more: - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\getargvals@{\the\macname}{\argl}% - }% - \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp - \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse - \fi - \fi - \fi} - -\catcode `\@\texiatcatcode\relax - -\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} - -% \braceorline decides whether the next nonwhitespace character is a -% {. If so it reads up to the closing }, if not, it reads the whole -% line. Whatever was read is then fed to the next control sequence -% as an argument (by \parsebrace or \parsearg). -% -\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} -\def\braceorlinexxx{% - \ifx\nchar\bgroup\else - \expandafter\parsearg - \fi \macnamexxx} - - -% @alias. -% We need some trickery to remove the optional spaces around the equal -% sign. Make them active and then expand them all to nothing. -% -\def\alias{\parseargusing\obeyspaces\aliasxxx} -\def\aliasxxx #1{\aliasyyy#1\relax} -\def\aliasyyy #1=#2\relax{% - {% - \expandafter\let\obeyedspace=\empty - \addtomacrolist{#1}% - \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% - }% - \next -} - - -\message{cross references,} - -\newwrite\auxfile -\newif\ifhavexrefs % True if xref values are known. -\newif\ifwarnedxrefs % True if we warned once that they aren't known. - -% @inforef is relatively simple. -\def\inforef #1{\inforefzzz #1,,,,**} -\def\inforefzzz #1,#2,#3,#4**{% - \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, - node \samp{\ignorespaces#1{}}} - -% @node's only job in TeX is to define \lastnode, which is used in -% cross-references. The @node line might or might not have commas, and -% might or might not have spaces before the first comma, like: -% @node foo , bar , ... -% We don't want such trailing spaces in the node name. -% -\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} -% -% also remove a trailing comma, in case of something like this: -% @node Help-Cross, , , Cross-refs -\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} -\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} - -\let\nwnode=\node -\let\lastnode=\empty - -% Write a cross-reference definition for the current node. #1 is the -% type (Ynumbered, Yappendix, Ynothing). -% -\def\donoderef#1{% - \ifx\lastnode\empty\else - \setref{\lastnode}{#1}% - \global\let\lastnode=\empty - \fi -} - -% @anchor{NAME} -- define xref target at arbitrary point. -% -\newcount\savesfregister -% -\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} -\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} -\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} - -% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an -% anchor), which consists of three parts: -% 1) NAME-title - the current sectioning name taken from \lastsection, -% or the anchor name. -% 2) NAME-snt - section number and type, passed as the SNT arg, or -% empty for anchors. -% 3) NAME-pg - the page number. -% -% This is called from \donoderef, \anchor, and \dofloat. In the case of -% floats, there is an additional part, which is not written here: -% 4) NAME-lof - the text as it should appear in a @listoffloats. -% -\def\setref#1#2{% - \pdfmkdest{#1}% - \iflinks - {% - \atdummies % preserve commands, but don't expand them - \edef\writexrdef##1##2{% - \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef - ##1}{##2}}% these are parameters of \writexrdef - }% - \toks0 = \expandafter{\lastsection}% - \immediate \writexrdef{title}{\the\toks0 }% - \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. - \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout - }% - \fi -} - -% @xrefautosectiontitle on|off says whether @section(ing) names are used -% automatically in xrefs, if the third arg is not explicitly specified. -% This was provided as a "secret" @set xref-automatic-section-title -% variable, now it's official. -% -\parseargdef\xrefautomaticsectiontitle{% - \def\temp{#1}% - \ifx\temp\onword - \expandafter\let\csname SETxref-automatic-section-title\endcsname - = \empty - \else\ifx\temp\offword - \expandafter\let\csname SETxref-automatic-section-title\endcsname - = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @xrefautomaticsectiontitle value `\temp', - must be on|off}% - \fi\fi -} - -% -% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is -% the node name, #2 the name of the Info cross-reference, #3 the printed -% node name, #4 the name of the Info file, #5 the name of the printed -% manual. All but the node name can be omitted. -% -\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} -\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} -\def\ref#1{\xrefX[#1,,,,,,,]} -% -\newbox\toprefbox -\newbox\printedrefnamebox -\newbox\infofilenamebox -\newbox\printedmanualbox -% -\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup - \unsepspaces - % - % Get args without leading/trailing spaces. - \def\printedrefname{\ignorespaces #3}% - \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% - % - \def\infofilename{\ignorespaces #4}% - \setbox\infofilenamebox = \hbox{\infofilename\unskip}% - % - \def\printedmanual{\ignorespaces #5}% - \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% - % - % If the printed reference name (arg #3) was not explicitly given in - % the @xref, figure out what we want to use. - \ifdim \wd\printedrefnamebox = 0pt - % No printed node name was explicitly given. - \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax - % Not auto section-title: use node name inside the square brackets. - \def\printedrefname{\ignorespaces #1}% - \else - % Auto section-title: use chapter/section title inside - % the square brackets if we have it. - \ifdim \wd\printedmanualbox > 0pt - % It is in another manual, so we don't have it; use node name. - \def\printedrefname{\ignorespaces #1}% - \else - \ifhavexrefs - % We (should) know the real title if we have the xref values. - \def\printedrefname{\refx{#1-title}{}}% - \else - % Otherwise just copy the Info node name. - \def\printedrefname{\ignorespaces #1}% - \fi% - \fi - \fi - \fi - % - % Make link in pdf output. - \ifpdf - {\indexnofonts - \turnoffactive - \makevalueexpandable - % This expands tokens, so do it after making catcode changes, so _ - % etc. don't get their TeX definitions. This ignores all spaces in - % #4, including (wrongly) those in the middle of the filename. - \getfilename{#4}% - % - % This (wrongly) does not take account of leading or trailing - % spaces in #1, which should be ignored. - \edef\pdfxrefdest{#1}% - \ifx\pdfxrefdest\empty - \def\pdfxrefdest{Top}% no empty targets - \else - \txiescapepdf\pdfxrefdest % escape PDF special chars - \fi - % - \leavevmode - \startlink attr{/Border [0 0 0]}% - \ifnum\filenamelength>0 - goto file{\the\filename.pdf} name{\pdfxrefdest}% - \else - goto name{\pdfmkpgn{\pdfxrefdest}}% - \fi - }% - \setcolor{\linkcolor}% - \fi - % - % Float references are printed completely differently: "Figure 1.2" - % instead of "[somenode], p.3". We distinguish them by the - % LABEL-title being set to a magic string. - {% - % Have to otherify everything special to allow the \csname to - % include an _ in the xref name, etc. - \indexnofonts - \turnoffactive - \expandafter\global\expandafter\let\expandafter\Xthisreftitle - \csname XR#1-title\endcsname - }% - \iffloat\Xthisreftitle - % If the user specified the print name (third arg) to the ref, - % print it instead of our usual "Figure 1.2". - \ifdim\wd\printedrefnamebox = 0pt - \refx{#1-snt}{}% - \else - \printedrefname - \fi - % - % If the user also gave the printed manual name (fifth arg), append - % "in MANUALNAME". - \ifdim \wd\printedmanualbox > 0pt - \space \putwordin{} \cite{\printedmanual}% - \fi - \else - % node/anchor (non-float) references. - % - % If we use \unhbox to print the node names, TeX does not insert - % empty discretionaries after hyphens, which means that it will not - % find a line break at a hyphen in a node names. Since some manuals - % are best written with fairly long node names, containing hyphens, - % this is a loss. Therefore, we give the text of the node name - % again, so it is as if TeX is seeing it for the first time. - % - \ifdim \wd\printedmanualbox > 0pt - % Cross-manual reference with a printed manual name. - % - \crossmanualxref{\cite{\printedmanual\unskip}}% - % - \else\ifdim \wd\infofilenamebox > 0pt - % Cross-manual reference with only an info filename (arg 4), no - % printed manual name (arg 5). This is essentially the same as - % the case above; we output the filename, since we have nothing else. - % - \crossmanualxref{\code{\infofilename\unskip}}% - % - \else - % Reference within this manual. - % - % _ (for example) has to be the character _ for the purposes of the - % control sequence corresponding to the node, but it has to expand - % into the usual \leavevmode...\vrule stuff for purposes of - % printing. So we \turnoffactive for the \refx-snt, back on for the - % printing, back off for the \refx-pg. - {\turnoffactive - % Only output a following space if the -snt ref is nonempty; for - % @unnumbered and @anchor, it won't be. - \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% - \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi - }% - % output the `[mynode]' via the macro below so it can be overridden. - \xrefprintnodename\printedrefname - % - % But we always want a comma and a space: - ,\space - % - % output the `page 3'. - \turnoffactive \putwordpage\tie\refx{#1-pg}{}% - \fi\fi - \fi - \endlink -\endgroup} - -% Output a cross-manual xref to #1. Used just above (twice). -% -% Only include the text "Section ``foo'' in" if the foo is neither -% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply -% "see The Foo Manual", the idea being to refer to the whole manual. -% -% But, this being TeX, we can't easily compare our node name against the -% string "Top" while ignoring the possible spaces before and after in -% the input. By adding the arbitrary 7sp below, we make it much less -% likely that a real node name would have the same width as "Top" (e.g., -% in a monospaced font). Hopefully it will never happen in practice. -% -% For the same basic reason, we retypeset the "Top" at every -% reference, since the current font is indeterminate. -% -\def\crossmanualxref#1{% - \setbox\toprefbox = \hbox{Top\kern7sp}% - \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% - \ifdim \wd2 > 7sp % nonempty? - \ifdim \wd2 = \wd\toprefbox \else % same as Top? - \putwordSection{} ``\printedrefname'' \putwordin{}\space - \fi - \fi - #1% -} - -% This macro is called from \xrefX for the `[nodename]' part of xref -% output. It's a separate macro only so it can be changed more easily, -% since square brackets don't work well in some documents. Particularly -% one that Bob is working on :). -% -\def\xrefprintnodename#1{[#1]} - -% Things referred to by \setref. -% -\def\Ynothing{} -\def\Yomitfromtoc{} -\def\Ynumbered{% - \ifnum\secno=0 - \putwordChapter@tie \the\chapno - \else \ifnum\subsecno=0 - \putwordSection@tie \the\chapno.\the\secno - \else \ifnum\subsubsecno=0 - \putwordSection@tie \the\chapno.\the\secno.\the\subsecno - \else - \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno - \fi\fi\fi -} -\def\Yappendix{% - \ifnum\secno=0 - \putwordAppendix@tie @char\the\appendixno{}% - \else \ifnum\subsecno=0 - \putwordSection@tie @char\the\appendixno.\the\secno - \else \ifnum\subsubsecno=0 - \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno - \else - \putwordSection@tie - @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno - \fi\fi\fi -} - -% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. -% If its value is nonempty, SUFFIX is output afterward. -% -\def\refx#1#2{% - {% - \indexnofonts - \otherbackslash - \expandafter\global\expandafter\let\expandafter\thisrefX - \csname XR#1\endcsname - }% - \ifx\thisrefX\relax - % If not defined, say something at least. - \angleleft un\-de\-fined\angleright - \iflinks - \ifhavexrefs - {\toks0 = {#1}% avoid expansion of possibly-complex value - \message{\linenumber Undefined cross reference `\the\toks0'.}}% - \else - \ifwarnedxrefs\else - \global\warnedxrefstrue - \message{Cross reference values unknown; you must run TeX again.}% - \fi - \fi - \fi - \else - % It's defined, so just use it. - \thisrefX - \fi - #2% Output the suffix in any case. -} - -% This is the macro invoked by entries in the aux file. Usually it's -% just a \def (we prepend XR to the control sequence name to avoid -% collisions). But if this is a float type, we have more work to do. -% -\def\xrdef#1#2{% - {% The node name might contain 8-bit characters, which in our current - % implementation are changed to commands like @'e. Don't let these - % mess up the control sequence name. - \indexnofonts - \turnoffactive - \xdef\safexrefname{#1}% - }% - % - \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref - % - % Was that xref control sequence that we just defined for a float? - \expandafter\iffloat\csname XR\safexrefname\endcsname - % it was a float, and we have the (safe) float type in \iffloattype. - \expandafter\let\expandafter\floatlist - \csname floatlist\iffloattype\endcsname - % - % Is this the first time we've seen this float type? - \expandafter\ifx\floatlist\relax - \toks0 = {\do}% yes, so just \do - \else - % had it before, so preserve previous elements in list. - \toks0 = \expandafter{\floatlist\do}% - \fi - % - % Remember this xref in the control sequence \floatlistFLOATTYPE, - % for later use in \listoffloats. - \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 - {\safexrefname}}% - \fi -} - -% Read the last existing aux file, if any. No error if none exists. -% -\def\tryauxfile{% - \openin 1 \jobname.aux - \ifeof 1 \else - \readdatafile{aux}% - \global\havexrefstrue - \fi - \closein 1 -} - -\def\setupdatafile{% - \catcode`\^^@=\other - \catcode`\^^A=\other - \catcode`\^^B=\other - \catcode`\^^C=\other - \catcode`\^^D=\other - \catcode`\^^E=\other - \catcode`\^^F=\other - \catcode`\^^G=\other - \catcode`\^^H=\other - \catcode`\^^K=\other - \catcode`\^^L=\other - \catcode`\^^N=\other - \catcode`\^^P=\other - \catcode`\^^Q=\other - \catcode`\^^R=\other - \catcode`\^^S=\other - \catcode`\^^T=\other - \catcode`\^^U=\other - \catcode`\^^V=\other - \catcode`\^^W=\other - \catcode`\^^X=\other - \catcode`\^^Z=\other - \catcode`\^^[=\other - \catcode`\^^\=\other - \catcode`\^^]=\other - \catcode`\^^^=\other - \catcode`\^^_=\other - % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. - % in xref tags, i.e., node names. But since ^^e4 notation isn't - % supported in the main text, it doesn't seem desirable. Furthermore, - % that is not enough: for node names that actually contain a ^ - % character, we would end up writing a line like this: 'xrdef {'hat - % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first - % argument, and \hat is not an expandable control sequence. It could - % all be worked out, but why? Either we support ^^ or we don't. - % - % The other change necessary for this was to define \auxhat: - % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter - % and then to call \auxhat in \setq. - % - \catcode`\^=\other - % - % Special characters. Should be turned off anyway, but... - \catcode`\~=\other - \catcode`\[=\other - \catcode`\]=\other - \catcode`\"=\other - \catcode`\_=\other - \catcode`\|=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\$=\other - \catcode`\#=\other - \catcode`\&=\other - \catcode`\%=\other - \catcode`+=\other % avoid \+ for paranoia even though we've turned it off - % - % This is to support \ in node names and titles, since the \ - % characters end up in a \csname. It's easier than - % leaving it active and making its active definition an actual \ - % character. What I don't understand is why it works in the *value* - % of the xrdef. Seems like it should be a catcode12 \, and that - % should not typeset properly. But it works, so I'm moving on for - % now. --karl, 15jan04. - \catcode`\\=\other - % - % Make the characters 128-255 be printing characters. - {% - \count1=128 - \def\loop{% - \catcode\count1=\other - \advance\count1 by 1 - \ifnum \count1<256 \loop \fi - }% - }% - % - % @ is our escape character in .aux files, and we need braces. - \catcode`\{=1 - \catcode`\}=2 - \catcode`\@=0 -} - -\def\readdatafile#1{% -\begingroup - \setupdatafile - \input\jobname.#1 -\endgroup} - - -\message{insertions,} -% including footnotes. - -\newcount \footnoteno - -% The trailing space in the following definition for supereject is -% vital for proper filling; pages come out unaligned when you do a -% pagealignmacro call if that space before the closing brace is -% removed. (Generally, numeric constants should always be followed by a -% space to prevent strange expansion errors.) -\def\supereject{\par\penalty -20000\footnoteno =0 } - -% @footnotestyle is meaningful for Info output only. -\let\footnotestyle=\comment - -{\catcode `\@=11 -% -% Auto-number footnotes. Otherwise like plain. -\gdef\footnote{% - \let\indent=\ptexindent - \let\noindent=\ptexnoindent - \global\advance\footnoteno by \@ne - \edef\thisfootno{$^{\the\footnoteno}$}% - % - % In case the footnote comes at the end of a sentence, preserve the - % extra spacing after we do the footnote number. - \let\@sf\empty - \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi - % - % Remove inadvertent blank space before typesetting the footnote number. - \unskip - \thisfootno\@sf - \dofootnote -}% - -% Don't bother with the trickery in plain.tex to not require the -% footnote text as a parameter. Our footnotes don't need to be so general. -% -% Oh yes, they do; otherwise, @ifset (and anything else that uses -% \parseargline) fails inside footnotes because the tokens are fixed when -% the footnote is read. --karl, 16nov96. -% -\gdef\dofootnote{% - \insert\footins\bgroup - % We want to typeset this text as a normal paragraph, even if the - % footnote reference occurs in (for example) a display environment. - % So reset some parameters. - \hsize=\pagewidth - \interlinepenalty\interfootnotelinepenalty - \splittopskip\ht\strutbox % top baseline for broken footnotes - \splitmaxdepth\dp\strutbox - \floatingpenalty\@MM - \leftskip\z@skip - \rightskip\z@skip - \spaceskip\z@skip - \xspaceskip\z@skip - \parindent\defaultparindent - % - \smallfonts \rm - % - % Because we use hanging indentation in footnotes, a @noindent appears - % to exdent this text, so make it be a no-op. makeinfo does not use - % hanging indentation so @noindent can still be needed within footnote - % text after an @example or the like (not that this is good style). - \let\noindent = \relax - % - % Hang the footnote text off the number. Use \everypar in case the - % footnote extends for more than one paragraph. - \everypar = {\hang}% - \textindent{\thisfootno}% - % - % Don't crash into the line above the footnote text. Since this - % expands into a box, it must come within the paragraph, lest it - % provide a place where TeX can split the footnote. - \footstrut - % - % Invoke rest of plain TeX footnote routine. - \futurelet\next\fo@t -} -}%end \catcode `\@=11 - -% In case a @footnote appears in a vbox, save the footnote text and create -% the real \insert just after the vbox finished. Otherwise, the insertion -% would be lost. -% Similarly, if a @footnote appears inside an alignment, save the footnote -% text to a box and make the \insert when a row of the table is finished. -% And the same can be done for other insert classes. --kasal, 16nov03. - -% Replace the \insert primitive by a cheating macro. -% Deeper inside, just make sure that the saved insertions are not spilled -% out prematurely. -% -\def\startsavinginserts{% - \ifx \insert\ptexinsert - \let\insert\saveinsert - \else - \let\checkinserts\relax - \fi -} - -% This \insert replacement works for both \insert\footins{foo} and -% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. -% -\def\saveinsert#1{% - \edef\next{\noexpand\savetobox \makeSAVEname#1}% - \afterassignment\next - % swallow the left brace - \let\temp = -} -\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} -\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} - -\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} - -\def\placesaveins#1{% - \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname - {\box#1}% -} - -% eat @SAVE -- beware, all of them have catcode \other: -{ - \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) - \gdef\gobblesave @SAVE{} -} - -% initialization: -\def\newsaveins #1{% - \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% - \next -} -\def\newsaveinsX #1{% - \csname newbox\endcsname #1% - \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts - \checksaveins #1}% -} - -% initialize: -\let\checkinserts\empty -\newsaveins\footins -\newsaveins\margin - - -% @image. We use the macros from epsf.tex to support this. -% If epsf.tex is not installed and @image is used, we complain. -% -% Check for and read epsf.tex up front. If we read it only at @image -% time, we might be inside a group, and then its definitions would get -% undone and the next image would fail. -\openin 1 = epsf.tex -\ifeof 1 \else - % Do not bother showing banner with epsf.tex v2.7k (available in - % doc/epsf.tex and on ctan). - \def\epsfannounce{\toks0 = }% - \input epsf.tex -\fi -\closein 1 -% -% We will only complain once about lack of epsf.tex. -\newif\ifwarnednoepsf -\newhelp\noepsfhelp{epsf.tex must be installed for images to - work. It is also included in the Texinfo distribution, or you can get - it from ftp://tug.org/tex/epsf.tex.} -% -\def\image#1{% - \ifx\epsfbox\thisisundefined - \ifwarnednoepsf \else - \errhelp = \noepsfhelp - \errmessage{epsf.tex not found, images will be ignored}% - \global\warnednoepsftrue - \fi - \else - \imagexxx #1,,,,,\finish - \fi -} -% -% Arguments to @image: -% #1 is (mandatory) image filename; we tack on .eps extension. -% #2 is (optional) width, #3 is (optional) height. -% #4 is (ignored optional) html alt text. -% #5 is (ignored optional) extension. -% #6 is just the usual extra ignored arg for parsing stuff. -\newif\ifimagevmode -\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup - \catcode`\^^M = 5 % in case we're inside an example - \normalturnoffactive % allow _ et al. in names - % If the image is by itself, center it. - \ifvmode - \imagevmodetrue - \else \ifx\centersub\centerV - % for @center @image, we need a vbox so we can have our vertical space - \imagevmodetrue - \vbox\bgroup % vbox has better behavior than vtop herev - \fi\fi - % - \ifimagevmode - \nobreak\medskip - % Usually we'll have text after the image which will insert - % \parskip glue, so insert it here too to equalize the space - % above and below. - \nobreak\vskip\parskip - \nobreak - \fi - % - % Leave vertical mode so that indentation from an enclosing - % environment such as @quotation is respected. - % However, if we're at the top level, we don't want the - % normal paragraph indentation. - % On the other hand, if we are in the case of @center @image, we don't - % want to start a paragraph, which will create a hsize-width box and - % eradicate the centering. - \ifx\centersub\centerV\else \noindent \fi - % - % Output the image. - \ifpdf - \dopdfimage{#1}{#2}{#3}% - \else - % \epsfbox itself resets \epsf?size at each figure. - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi - \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi - \epsfbox{#1.eps}% - \fi - % - \ifimagevmode - \medskip % space after a standalone image - \fi - \ifx\centersub\centerV \egroup \fi -\endgroup} - - -% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, -% etc. We don't actually implement floating yet, we always include the -% float "here". But it seemed the best name for the future. -% -\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} - -% There may be a space before second and/or third parameter; delete it. -\def\eatcommaspace#1, {#1,} - -% #1 is the optional FLOATTYPE, the text label for this float, typically -% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, -% this float will not be numbered and cannot be referred to. -% -% #2 is the optional xref label. Also must be present for the float to -% be referable. -% -% #3 is the optional positioning argument; for now, it is ignored. It -% will somehow specify the positions allowed to float to (here, top, bottom). -% -% We keep a separate counter for each FLOATTYPE, which we reset at each -% chapter-level command. -\let\resetallfloatnos=\empty -% -\def\dofloat#1,#2,#3,#4\finish{% - \let\thiscaption=\empty - \let\thisshortcaption=\empty - % - % don't lose footnotes inside @float. - % - % BEWARE: when the floats start float, we have to issue warning whenever an - % insert appears inside a float which could possibly float. --kasal, 26may04 - % - \startsavinginserts - % - % We can't be used inside a paragraph. - \par - % - \vtop\bgroup - \def\floattype{#1}% - \def\floatlabel{#2}% - \def\floatloc{#3}% we do nothing with this yet. - % - \ifx\floattype\empty - \let\safefloattype=\empty - \else - {% - % the floattype might have accents or other special characters, - % but we need to use it in a control sequence name. - \indexnofonts - \turnoffactive - \xdef\safefloattype{\floattype}% - }% - \fi - % - % If label is given but no type, we handle that as the empty type. - \ifx\floatlabel\empty \else - % We want each FLOATTYPE to be numbered separately (Figure 1, - % Table 1, Figure 2, ...). (And if no label, no number.) - % - \expandafter\getfloatno\csname\safefloattype floatno\endcsname - \global\advance\floatno by 1 - % - {% - % This magic value for \lastsection is output by \setref as the - % XREFLABEL-title value. \xrefX uses it to distinguish float - % labels (which have a completely different output format) from - % node and anchor labels. And \xrdef uses it to construct the - % lists of floats. - % - \edef\lastsection{\floatmagic=\safefloattype}% - \setref{\floatlabel}{Yfloat}% - }% - \fi - % - % start with \parskip glue, I guess. - \vskip\parskip - % - % Don't suppress indentation if a float happens to start a section. - \restorefirstparagraphindent -} - -% we have these possibilities: -% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap -% @float Foo,lbl & no caption: Foo 1.1 -% @float Foo & @caption{Cap}: Foo: Cap -% @float Foo & no caption: Foo -% @float ,lbl & Caption{Cap}: 1.1: Cap -% @float ,lbl & no caption: 1.1 -% @float & @caption{Cap}: Cap -% @float & no caption: -% -\def\Efloat{% - \let\floatident = \empty - % - % In all cases, if we have a float type, it comes first. - \ifx\floattype\empty \else \def\floatident{\floattype}\fi - % - % If we have an xref label, the number comes next. - \ifx\floatlabel\empty \else - \ifx\floattype\empty \else % if also had float type, need tie first. - \appendtomacro\floatident{\tie}% - \fi - % the number. - \appendtomacro\floatident{\chaplevelprefix\the\floatno}% - \fi - % - % Start the printed caption with what we've constructed in - % \floatident, but keep it separate; we need \floatident again. - \let\captionline = \floatident - % - \ifx\thiscaption\empty \else - \ifx\floatident\empty \else - \appendtomacro\captionline{: }% had ident, so need a colon between - \fi - % - % caption text. - \appendtomacro\captionline{\scanexp\thiscaption}% - \fi - % - % If we have anything to print, print it, with space before. - % Eventually this needs to become an \insert. - \ifx\captionline\empty \else - \vskip.5\parskip - \captionline - % - % Space below caption. - \vskip\parskip - \fi - % - % If have an xref label, write the list of floats info. Do this - % after the caption, to avoid chance of it being a breakpoint. - \ifx\floatlabel\empty \else - % Write the text that goes in the lof to the aux file as - % \floatlabel-lof. Besides \floatident, we include the short - % caption if specified, else the full caption if specified, else nothing. - {% - \atdummies - % - % since we read the caption text in the macro world, where ^^M - % is turned into a normal character, we have to scan it back, so - % we don't write the literal three characters "^^M" into the aux file. - \scanexp{% - \xdef\noexpand\gtemp{% - \ifx\thisshortcaption\empty - \thiscaption - \else - \thisshortcaption - \fi - }% - }% - \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident - \ifx\gtemp\empty \else : \gtemp \fi}}% - }% - \fi - \egroup % end of \vtop - % - % place the captured inserts - % - % BEWARE: when the floats start floating, we have to issue warning - % whenever an insert appears inside a float which could possibly - % float. --kasal, 26may04 - % - \checkinserts -} - -% Append the tokens #2 to the definition of macro #1, not expanding either. -% -\def\appendtomacro#1#2{% - \expandafter\def\expandafter#1\expandafter{#1#2}% -} - -% @caption, @shortcaption -% -\def\caption{\docaption\thiscaption} -\def\shortcaption{\docaption\thisshortcaption} -\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} -\def\defcaption#1#2{\egroup \def#1{#2}} - -% The parameter is the control sequence identifying the counter we are -% going to use. Create it if it doesn't exist and assign it to \floatno. -\def\getfloatno#1{% - \ifx#1\relax - % Haven't seen this figure type before. - \csname newcount\endcsname #1% - % - % Remember to reset this floatno at the next chap. - \expandafter\gdef\expandafter\resetallfloatnos - \expandafter{\resetallfloatnos #1=0 }% - \fi - \let\floatno#1% -} - -% \setref calls this to get the XREFLABEL-snt value. We want an @xref -% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we -% first read the @float command. -% -\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% - -% Magic string used for the XREFLABEL-title value, so \xrefX can -% distinguish floats from other xref types. -\def\floatmagic{!!float!!} - -% #1 is the control sequence we are passed; we expand into a conditional -% which is true if #1 represents a float ref. That is, the magic -% \lastsection value which we \setref above. -% -\def\iffloat#1{\expandafter\doiffloat#1==\finish} -% -% #1 is (maybe) the \floatmagic string. If so, #2 will be the -% (safe) float type for this float. We set \iffloattype to #2. -% -\def\doiffloat#1=#2=#3\finish{% - \def\temp{#1}% - \def\iffloattype{#2}% - \ifx\temp\floatmagic -} - -% @listoffloats FLOATTYPE - print a list of floats like a table of contents. -% -\parseargdef\listoffloats{% - \def\floattype{#1}% floattype - {% - % the floattype might have accents or other special characters, - % but we need to use it in a control sequence name. - \indexnofonts - \turnoffactive - \xdef\safefloattype{\floattype}% - }% - % - % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. - \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax - \ifhavexrefs - % if the user said @listoffloats foo but never @float foo. - \message{\linenumber No `\safefloattype' floats to list.}% - \fi - \else - \begingroup - \leftskip=\tocindent % indent these entries like a toc - \let\do=\listoffloatsdo - \csname floatlist\safefloattype\endcsname - \endgroup - \fi -} - -% This is called on each entry in a list of floats. We're passed the -% xref label, in the form LABEL-title, which is how we save it in the -% aux file. We strip off the -title and look up \XRLABEL-lof, which -% has the text we're supposed to typeset here. -% -% Figures without xref labels will not be included in the list (since -% they won't appear in the aux file). -% -\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} -\def\listoffloatsdoentry#1-title\finish{{% - % Can't fully expand XR#1-lof because it can contain anything. Just - % pass the control sequence. On the other hand, XR#1-pg is just the - % page number, and we want to fully expand that so we can get a link - % in pdf output. - \toksA = \expandafter{\csname XR#1-lof\endcsname}% - % - % use the same \entry macro we use to generate the TOC and index. - \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% - \writeentry -}} - - -\message{localization,} - -% For single-language documents, @documentlanguage is usually given very -% early, just after @documentencoding. Single argument is the language -% (de) or locale (de_DE) abbreviation. -% -{ - \catcode`\_ = \active - \globaldefs=1 -\parseargdef\documentlanguage{\begingroup - \let_=\normalunderscore % normal _ character for filenames - \tex % read txi-??.tex file in plain TeX. - % Read the file by the name they passed if it exists. - \openin 1 txi-#1.tex - \ifeof 1 - \documentlanguagetrywithoutunderscore{#1_\finish}% - \else - \globaldefs = 1 % everything in the txi-LL files needs to persist - \input txi-#1.tex - \fi - \closein 1 - \endgroup % end raw TeX -\endgroup} -% -% If they passed de_DE, and txi-de_DE.tex doesn't exist, -% try txi-de.tex. -% -\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% - \openin 1 txi-#1.tex - \ifeof 1 - \errhelp = \nolanghelp - \errmessage{Cannot read language file txi-#1.tex}% - \else - \globaldefs = 1 % everything in the txi-LL files needs to persist - \input txi-#1.tex - \fi - \closein 1 -} -}% end of special _ catcode -% -\newhelp\nolanghelp{The given language definition file cannot be found or -is empty. Maybe you need to install it? Putting it in the current -directory should work if nowhere else does.} - -% This macro is called from txi-??.tex files; the first argument is the -% \language name to set (without the "\lang@" prefix), the second and -% third args are \{left,right}hyphenmin. -% -% The language names to pass are determined when the format is built. -% See the etex.log file created at that time, e.g., -% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. -% -% With TeX Live 2008, etex now includes hyphenation patterns for all -% available languages. This means we can support hyphenation in -% Texinfo, at least to some extent. (This still doesn't solve the -% accented characters problem.) -% -\catcode`@=11 -\def\txisetlanguage#1#2#3{% - % do not set the language if the name is undefined in the current TeX. - \expandafter\ifx\csname lang@#1\endcsname \relax - \message{no patterns for #1}% - \else - \global\language = \csname lang@#1\endcsname - \fi - % but there is no harm in adjusting the hyphenmin values regardless. - \global\lefthyphenmin = #2\relax - \global\righthyphenmin = #3\relax -} - -% Helpers for encodings. -% Set the catcode of characters 128 through 255 to the specified number. -% -\def\setnonasciicharscatcode#1{% - \count255=128 - \loop\ifnum\count255<256 - \global\catcode\count255=#1\relax - \advance\count255 by 1 - \repeat -} - -\def\setnonasciicharscatcodenonglobal#1{% - \count255=128 - \loop\ifnum\count255<256 - \catcode\count255=#1\relax - \advance\count255 by 1 - \repeat -} - -% @documentencoding sets the definition of non-ASCII characters -% according to the specified encoding. -% -\parseargdef\documentencoding{% - % Encoding being declared for the document. - \def\declaredencoding{\csname #1.enc\endcsname}% - % - % Supported encodings: names converted to tokens in order to be able - % to compare them with \ifx. - \def\ascii{\csname US-ASCII.enc\endcsname}% - \def\latnine{\csname ISO-8859-15.enc\endcsname}% - \def\latone{\csname ISO-8859-1.enc\endcsname}% - \def\lattwo{\csname ISO-8859-2.enc\endcsname}% - \def\utfeight{\csname UTF-8.enc\endcsname}% - % - \ifx \declaredencoding \ascii - \asciichardefs - % - \else \ifx \declaredencoding \lattwo - \setnonasciicharscatcode\active - \lattwochardefs - % - \else \ifx \declaredencoding \latone - \setnonasciicharscatcode\active - \latonechardefs - % - \else \ifx \declaredencoding \latnine - \setnonasciicharscatcode\active - \latninechardefs - % - \else \ifx \declaredencoding \utfeight - \setnonasciicharscatcode\active - \utfeightchardefs - % - \else - \message{Unknown document encoding #1, ignoring.}% - % - \fi % utfeight - \fi % latnine - \fi % latone - \fi % lattwo - \fi % ascii -} - -% A message to be logged when using a character that isn't available -% the default font encoding (OT1). -% -\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} - -% Take account of \c (plain) vs. \, (Texinfo) difference. -\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} - -% First, make active non-ASCII characters in order for them to be -% correctly categorized when TeX reads the replacement text of -% macros containing the character definitions. -\setnonasciicharscatcode\active -% -% Latin1 (ISO-8859-1) character definitions. -\def\latonechardefs{% - \gdef^^a0{\tie} - \gdef^^a1{\exclamdown} - \gdef^^a2{\missingcharmsg{CENT SIGN}} - \gdef^^a3{{\pounds}} - \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} - \gdef^^a5{\missingcharmsg{YEN SIGN}} - \gdef^^a6{\missingcharmsg{BROKEN BAR}} - \gdef^^a7{\S} - \gdef^^a8{\"{}} - \gdef^^a9{\copyright} - \gdef^^aa{\ordf} - \gdef^^ab{\guillemetleft} - \gdef^^ac{$\lnot$} - \gdef^^ad{\-} - \gdef^^ae{\registeredsymbol} - \gdef^^af{\={}} - % - \gdef^^b0{\textdegree} - \gdef^^b1{$\pm$} - \gdef^^b2{$^2$} - \gdef^^b3{$^3$} - \gdef^^b4{\'{}} - \gdef^^b5{$\mu$} - \gdef^^b6{\P} - % - \gdef^^b7{$^.$} - \gdef^^b8{\cedilla\ } - \gdef^^b9{$^1$} - \gdef^^ba{\ordm} - % - \gdef^^bb{\guillemetright} - \gdef^^bc{$1\over4$} - \gdef^^bd{$1\over2$} - \gdef^^be{$3\over4$} - \gdef^^bf{\questiondown} - % - \gdef^^c0{\`A} - \gdef^^c1{\'A} - \gdef^^c2{\^A} - \gdef^^c3{\~A} - \gdef^^c4{\"A} - \gdef^^c5{\ringaccent A} - \gdef^^c6{\AE} - \gdef^^c7{\cedilla C} - \gdef^^c8{\`E} - \gdef^^c9{\'E} - \gdef^^ca{\^E} - \gdef^^cb{\"E} - \gdef^^cc{\`I} - \gdef^^cd{\'I} - \gdef^^ce{\^I} - \gdef^^cf{\"I} - % - \gdef^^d0{\DH} - \gdef^^d1{\~N} - \gdef^^d2{\`O} - \gdef^^d3{\'O} - \gdef^^d4{\^O} - \gdef^^d5{\~O} - \gdef^^d6{\"O} - \gdef^^d7{$\times$} - \gdef^^d8{\O} - \gdef^^d9{\`U} - \gdef^^da{\'U} - \gdef^^db{\^U} - \gdef^^dc{\"U} - \gdef^^dd{\'Y} - \gdef^^de{\TH} - \gdef^^df{\ss} - % - \gdef^^e0{\`a} - \gdef^^e1{\'a} - \gdef^^e2{\^a} - \gdef^^e3{\~a} - \gdef^^e4{\"a} - \gdef^^e5{\ringaccent a} - \gdef^^e6{\ae} - \gdef^^e7{\cedilla c} - \gdef^^e8{\`e} - \gdef^^e9{\'e} - \gdef^^ea{\^e} - \gdef^^eb{\"e} - \gdef^^ec{\`{\dotless i}} - \gdef^^ed{\'{\dotless i}} - \gdef^^ee{\^{\dotless i}} - \gdef^^ef{\"{\dotless i}} - % - \gdef^^f0{\dh} - \gdef^^f1{\~n} - \gdef^^f2{\`o} - \gdef^^f3{\'o} - \gdef^^f4{\^o} - \gdef^^f5{\~o} - \gdef^^f6{\"o} - \gdef^^f7{$\div$} - \gdef^^f8{\o} - \gdef^^f9{\`u} - \gdef^^fa{\'u} - \gdef^^fb{\^u} - \gdef^^fc{\"u} - \gdef^^fd{\'y} - \gdef^^fe{\th} - \gdef^^ff{\"y} -} - -% Latin9 (ISO-8859-15) encoding character definitions. -\def\latninechardefs{% - % Encoding is almost identical to Latin1. - \latonechardefs - % - \gdef^^a4{\euro} - \gdef^^a6{\v S} - \gdef^^a8{\v s} - \gdef^^b4{\v Z} - \gdef^^b8{\v z} - \gdef^^bc{\OE} - \gdef^^bd{\oe} - \gdef^^be{\"Y} -} - -% Latin2 (ISO-8859-2) character definitions. -\def\lattwochardefs{% - \gdef^^a0{\tie} - \gdef^^a1{\ogonek{A}} - \gdef^^a2{\u{}} - \gdef^^a3{\L} - \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} - \gdef^^a5{\v L} - \gdef^^a6{\'S} - \gdef^^a7{\S} - \gdef^^a8{\"{}} - \gdef^^a9{\v S} - \gdef^^aa{\cedilla S} - \gdef^^ab{\v T} - \gdef^^ac{\'Z} - \gdef^^ad{\-} - \gdef^^ae{\v Z} - \gdef^^af{\dotaccent Z} - % - \gdef^^b0{\textdegree} - \gdef^^b1{\ogonek{a}} - \gdef^^b2{\ogonek{ }} - \gdef^^b3{\l} - \gdef^^b4{\'{}} - \gdef^^b5{\v l} - \gdef^^b6{\'s} - \gdef^^b7{\v{}} - \gdef^^b8{\cedilla\ } - \gdef^^b9{\v s} - \gdef^^ba{\cedilla s} - \gdef^^bb{\v t} - \gdef^^bc{\'z} - \gdef^^bd{\H{}} - \gdef^^be{\v z} - \gdef^^bf{\dotaccent z} - % - \gdef^^c0{\'R} - \gdef^^c1{\'A} - \gdef^^c2{\^A} - \gdef^^c3{\u A} - \gdef^^c4{\"A} - \gdef^^c5{\'L} - \gdef^^c6{\'C} - \gdef^^c7{\cedilla C} - \gdef^^c8{\v C} - \gdef^^c9{\'E} - \gdef^^ca{\ogonek{E}} - \gdef^^cb{\"E} - \gdef^^cc{\v E} - \gdef^^cd{\'I} - \gdef^^ce{\^I} - \gdef^^cf{\v D} - % - \gdef^^d0{\DH} - \gdef^^d1{\'N} - \gdef^^d2{\v N} - \gdef^^d3{\'O} - \gdef^^d4{\^O} - \gdef^^d5{\H O} - \gdef^^d6{\"O} - \gdef^^d7{$\times$} - \gdef^^d8{\v R} - \gdef^^d9{\ringaccent U} - \gdef^^da{\'U} - \gdef^^db{\H U} - \gdef^^dc{\"U} - \gdef^^dd{\'Y} - \gdef^^de{\cedilla T} - \gdef^^df{\ss} - % - \gdef^^e0{\'r} - \gdef^^e1{\'a} - \gdef^^e2{\^a} - \gdef^^e3{\u a} - \gdef^^e4{\"a} - \gdef^^e5{\'l} - \gdef^^e6{\'c} - \gdef^^e7{\cedilla c} - \gdef^^e8{\v c} - \gdef^^e9{\'e} - \gdef^^ea{\ogonek{e}} - \gdef^^eb{\"e} - \gdef^^ec{\v e} - \gdef^^ed{\'{\dotless{i}}} - \gdef^^ee{\^{\dotless{i}}} - \gdef^^ef{\v d} - % - \gdef^^f0{\dh} - \gdef^^f1{\'n} - \gdef^^f2{\v n} - \gdef^^f3{\'o} - \gdef^^f4{\^o} - \gdef^^f5{\H o} - \gdef^^f6{\"o} - \gdef^^f7{$\div$} - \gdef^^f8{\v r} - \gdef^^f9{\ringaccent u} - \gdef^^fa{\'u} - \gdef^^fb{\H u} - \gdef^^fc{\"u} - \gdef^^fd{\'y} - \gdef^^fe{\cedilla t} - \gdef^^ff{\dotaccent{}} -} - -% UTF-8 character definitions. -% -% This code to support UTF-8 is based on LaTeX's utf8.def, with some -% changes for Texinfo conventions. It is included here under the GPL by -% permission from Frank Mittelbach and the LaTeX team. -% -\newcount\countUTFx -\newcount\countUTFy -\newcount\countUTFz - -\gdef\UTFviiiTwoOctets#1#2{\expandafter - \UTFviiiDefined\csname u8:#1\string #2\endcsname} -% -\gdef\UTFviiiThreeOctets#1#2#3{\expandafter - \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} -% -\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter - \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} - -\gdef\UTFviiiDefined#1{% - \ifx #1\relax - \message{\linenumber Unicode char \string #1 not defined for Texinfo}% - \else - \expandafter #1% - \fi -} - -\begingroup - \catcode`\~13 - \catcode`\"12 - - \def\UTFviiiLoop{% - \global\catcode\countUTFx\active - \uccode`\~\countUTFx - \uppercase\expandafter{\UTFviiiTmp}% - \advance\countUTFx by 1 - \ifnum\countUTFx < \countUTFy - \expandafter\UTFviiiLoop - \fi} - - \countUTFx = "C2 - \countUTFy = "E0 - \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiTwoOctets\string~}} - \UTFviiiLoop - - \countUTFx = "E0 - \countUTFy = "F0 - \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiThreeOctets\string~}} - \UTFviiiLoop - - \countUTFx = "F0 - \countUTFy = "F4 - \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiFourOctets\string~}} - \UTFviiiLoop -\endgroup - -\begingroup - \catcode`\"=12 - \catcode`\<=12 - \catcode`\.=12 - \catcode`\,=12 - \catcode`\;=12 - \catcode`\!=12 - \catcode`\~=13 - - \gdef\DeclareUnicodeCharacter#1#2{% - \countUTFz = "#1\relax - %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% - \begingroup - \parseXMLCharref - \def\UTFviiiTwoOctets##1##2{% - \csname u8:##1\string ##2\endcsname}% - \def\UTFviiiThreeOctets##1##2##3{% - \csname u8:##1\string ##2\string ##3\endcsname}% - \def\UTFviiiFourOctets##1##2##3##4{% - \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% - \expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter - \gdef\UTFviiiTmp{#2}% - \endgroup} - - \gdef\parseXMLCharref{% - \ifnum\countUTFz < "A0\relax - \errhelp = \EMsimple - \errmessage{Cannot define Unicode char value < 00A0}% - \else\ifnum\countUTFz < "800\relax - \parseUTFviiiA,% - \parseUTFviiiB C\UTFviiiTwoOctets.,% - \else\ifnum\countUTFz < "10000\relax - \parseUTFviiiA;% - \parseUTFviiiA,% - \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% - \else - \parseUTFviiiA;% - \parseUTFviiiA,% - \parseUTFviiiA!% - \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% - \fi\fi\fi - } - - \gdef\parseUTFviiiA#1{% - \countUTFx = \countUTFz - \divide\countUTFz by 64 - \countUTFy = \countUTFz - \multiply\countUTFz by 64 - \advance\countUTFx by -\countUTFz - \advance\countUTFx by 128 - \uccode `#1\countUTFx - \countUTFz = \countUTFy} - - \gdef\parseUTFviiiB#1#2#3#4{% - \advance\countUTFz by "#10\relax - \uccode `#3\countUTFz - \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} -\endgroup - -\def\utfeightchardefs{% - \DeclareUnicodeCharacter{00A0}{\tie} - \DeclareUnicodeCharacter{00A1}{\exclamdown} - \DeclareUnicodeCharacter{00A3}{\pounds} - \DeclareUnicodeCharacter{00A8}{\"{ }} - \DeclareUnicodeCharacter{00A9}{\copyright} - \DeclareUnicodeCharacter{00AA}{\ordf} - \DeclareUnicodeCharacter{00AB}{\guillemetleft} - \DeclareUnicodeCharacter{00AD}{\-} - \DeclareUnicodeCharacter{00AE}{\registeredsymbol} - \DeclareUnicodeCharacter{00AF}{\={ }} - - \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} - \DeclareUnicodeCharacter{00B4}{\'{ }} - \DeclareUnicodeCharacter{00B8}{\cedilla{ }} - \DeclareUnicodeCharacter{00BA}{\ordm} - \DeclareUnicodeCharacter{00BB}{\guillemetright} - \DeclareUnicodeCharacter{00BF}{\questiondown} - - \DeclareUnicodeCharacter{00C0}{\`A} - \DeclareUnicodeCharacter{00C1}{\'A} - \DeclareUnicodeCharacter{00C2}{\^A} - \DeclareUnicodeCharacter{00C3}{\~A} - \DeclareUnicodeCharacter{00C4}{\"A} - \DeclareUnicodeCharacter{00C5}{\AA} - \DeclareUnicodeCharacter{00C6}{\AE} - \DeclareUnicodeCharacter{00C7}{\cedilla{C}} - \DeclareUnicodeCharacter{00C8}{\`E} - \DeclareUnicodeCharacter{00C9}{\'E} - \DeclareUnicodeCharacter{00CA}{\^E} - \DeclareUnicodeCharacter{00CB}{\"E} - \DeclareUnicodeCharacter{00CC}{\`I} - \DeclareUnicodeCharacter{00CD}{\'I} - \DeclareUnicodeCharacter{00CE}{\^I} - \DeclareUnicodeCharacter{00CF}{\"I} - - \DeclareUnicodeCharacter{00D0}{\DH} - \DeclareUnicodeCharacter{00D1}{\~N} - \DeclareUnicodeCharacter{00D2}{\`O} - \DeclareUnicodeCharacter{00D3}{\'O} - \DeclareUnicodeCharacter{00D4}{\^O} - \DeclareUnicodeCharacter{00D5}{\~O} - \DeclareUnicodeCharacter{00D6}{\"O} - \DeclareUnicodeCharacter{00D8}{\O} - \DeclareUnicodeCharacter{00D9}{\`U} - \DeclareUnicodeCharacter{00DA}{\'U} - \DeclareUnicodeCharacter{00DB}{\^U} - \DeclareUnicodeCharacter{00DC}{\"U} - \DeclareUnicodeCharacter{00DD}{\'Y} - \DeclareUnicodeCharacter{00DE}{\TH} - \DeclareUnicodeCharacter{00DF}{\ss} - - \DeclareUnicodeCharacter{00E0}{\`a} - \DeclareUnicodeCharacter{00E1}{\'a} - \DeclareUnicodeCharacter{00E2}{\^a} - \DeclareUnicodeCharacter{00E3}{\~a} - \DeclareUnicodeCharacter{00E4}{\"a} - \DeclareUnicodeCharacter{00E5}{\aa} - \DeclareUnicodeCharacter{00E6}{\ae} - \DeclareUnicodeCharacter{00E7}{\cedilla{c}} - \DeclareUnicodeCharacter{00E8}{\`e} - \DeclareUnicodeCharacter{00E9}{\'e} - \DeclareUnicodeCharacter{00EA}{\^e} - \DeclareUnicodeCharacter{00EB}{\"e} - \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} - \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} - \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} - \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} - - \DeclareUnicodeCharacter{00F0}{\dh} - \DeclareUnicodeCharacter{00F1}{\~n} - \DeclareUnicodeCharacter{00F2}{\`o} - \DeclareUnicodeCharacter{00F3}{\'o} - \DeclareUnicodeCharacter{00F4}{\^o} - \DeclareUnicodeCharacter{00F5}{\~o} - \DeclareUnicodeCharacter{00F6}{\"o} - \DeclareUnicodeCharacter{00F8}{\o} - \DeclareUnicodeCharacter{00F9}{\`u} - \DeclareUnicodeCharacter{00FA}{\'u} - \DeclareUnicodeCharacter{00FB}{\^u} - \DeclareUnicodeCharacter{00FC}{\"u} - \DeclareUnicodeCharacter{00FD}{\'y} - \DeclareUnicodeCharacter{00FE}{\th} - \DeclareUnicodeCharacter{00FF}{\"y} - - \DeclareUnicodeCharacter{0100}{\=A} - \DeclareUnicodeCharacter{0101}{\=a} - \DeclareUnicodeCharacter{0102}{\u{A}} - \DeclareUnicodeCharacter{0103}{\u{a}} - \DeclareUnicodeCharacter{0104}{\ogonek{A}} - \DeclareUnicodeCharacter{0105}{\ogonek{a}} - \DeclareUnicodeCharacter{0106}{\'C} - \DeclareUnicodeCharacter{0107}{\'c} - \DeclareUnicodeCharacter{0108}{\^C} - \DeclareUnicodeCharacter{0109}{\^c} - \DeclareUnicodeCharacter{0118}{\ogonek{E}} - \DeclareUnicodeCharacter{0119}{\ogonek{e}} - \DeclareUnicodeCharacter{010A}{\dotaccent{C}} - \DeclareUnicodeCharacter{010B}{\dotaccent{c}} - \DeclareUnicodeCharacter{010C}{\v{C}} - \DeclareUnicodeCharacter{010D}{\v{c}} - \DeclareUnicodeCharacter{010E}{\v{D}} - - \DeclareUnicodeCharacter{0112}{\=E} - \DeclareUnicodeCharacter{0113}{\=e} - \DeclareUnicodeCharacter{0114}{\u{E}} - \DeclareUnicodeCharacter{0115}{\u{e}} - \DeclareUnicodeCharacter{0116}{\dotaccent{E}} - \DeclareUnicodeCharacter{0117}{\dotaccent{e}} - \DeclareUnicodeCharacter{011A}{\v{E}} - \DeclareUnicodeCharacter{011B}{\v{e}} - \DeclareUnicodeCharacter{011C}{\^G} - \DeclareUnicodeCharacter{011D}{\^g} - \DeclareUnicodeCharacter{011E}{\u{G}} - \DeclareUnicodeCharacter{011F}{\u{g}} - - \DeclareUnicodeCharacter{0120}{\dotaccent{G}} - \DeclareUnicodeCharacter{0121}{\dotaccent{g}} - \DeclareUnicodeCharacter{0124}{\^H} - \DeclareUnicodeCharacter{0125}{\^h} - \DeclareUnicodeCharacter{0128}{\~I} - \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} - \DeclareUnicodeCharacter{012A}{\=I} - \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} - \DeclareUnicodeCharacter{012C}{\u{I}} - \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} - - \DeclareUnicodeCharacter{0130}{\dotaccent{I}} - \DeclareUnicodeCharacter{0131}{\dotless{i}} - \DeclareUnicodeCharacter{0132}{IJ} - \DeclareUnicodeCharacter{0133}{ij} - \DeclareUnicodeCharacter{0134}{\^J} - \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} - \DeclareUnicodeCharacter{0139}{\'L} - \DeclareUnicodeCharacter{013A}{\'l} - - \DeclareUnicodeCharacter{0141}{\L} - \DeclareUnicodeCharacter{0142}{\l} - \DeclareUnicodeCharacter{0143}{\'N} - \DeclareUnicodeCharacter{0144}{\'n} - \DeclareUnicodeCharacter{0147}{\v{N}} - \DeclareUnicodeCharacter{0148}{\v{n}} - \DeclareUnicodeCharacter{014C}{\=O} - \DeclareUnicodeCharacter{014D}{\=o} - \DeclareUnicodeCharacter{014E}{\u{O}} - \DeclareUnicodeCharacter{014F}{\u{o}} - - \DeclareUnicodeCharacter{0150}{\H{O}} - \DeclareUnicodeCharacter{0151}{\H{o}} - \DeclareUnicodeCharacter{0152}{\OE} - \DeclareUnicodeCharacter{0153}{\oe} - \DeclareUnicodeCharacter{0154}{\'R} - \DeclareUnicodeCharacter{0155}{\'r} - \DeclareUnicodeCharacter{0158}{\v{R}} - \DeclareUnicodeCharacter{0159}{\v{r}} - \DeclareUnicodeCharacter{015A}{\'S} - \DeclareUnicodeCharacter{015B}{\'s} - \DeclareUnicodeCharacter{015C}{\^S} - \DeclareUnicodeCharacter{015D}{\^s} - \DeclareUnicodeCharacter{015E}{\cedilla{S}} - \DeclareUnicodeCharacter{015F}{\cedilla{s}} - - \DeclareUnicodeCharacter{0160}{\v{S}} - \DeclareUnicodeCharacter{0161}{\v{s}} - \DeclareUnicodeCharacter{0162}{\cedilla{t}} - \DeclareUnicodeCharacter{0163}{\cedilla{T}} - \DeclareUnicodeCharacter{0164}{\v{T}} - - \DeclareUnicodeCharacter{0168}{\~U} - \DeclareUnicodeCharacter{0169}{\~u} - \DeclareUnicodeCharacter{016A}{\=U} - \DeclareUnicodeCharacter{016B}{\=u} - \DeclareUnicodeCharacter{016C}{\u{U}} - \DeclareUnicodeCharacter{016D}{\u{u}} - \DeclareUnicodeCharacter{016E}{\ringaccent{U}} - \DeclareUnicodeCharacter{016F}{\ringaccent{u}} - - \DeclareUnicodeCharacter{0170}{\H{U}} - \DeclareUnicodeCharacter{0171}{\H{u}} - \DeclareUnicodeCharacter{0174}{\^W} - \DeclareUnicodeCharacter{0175}{\^w} - \DeclareUnicodeCharacter{0176}{\^Y} - \DeclareUnicodeCharacter{0177}{\^y} - \DeclareUnicodeCharacter{0178}{\"Y} - \DeclareUnicodeCharacter{0179}{\'Z} - \DeclareUnicodeCharacter{017A}{\'z} - \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} - \DeclareUnicodeCharacter{017C}{\dotaccent{z}} - \DeclareUnicodeCharacter{017D}{\v{Z}} - \DeclareUnicodeCharacter{017E}{\v{z}} - - \DeclareUnicodeCharacter{01C4}{D\v{Z}} - \DeclareUnicodeCharacter{01C5}{D\v{z}} - \DeclareUnicodeCharacter{01C6}{d\v{z}} - \DeclareUnicodeCharacter{01C7}{LJ} - \DeclareUnicodeCharacter{01C8}{Lj} - \DeclareUnicodeCharacter{01C9}{lj} - \DeclareUnicodeCharacter{01CA}{NJ} - \DeclareUnicodeCharacter{01CB}{Nj} - \DeclareUnicodeCharacter{01CC}{nj} - \DeclareUnicodeCharacter{01CD}{\v{A}} - \DeclareUnicodeCharacter{01CE}{\v{a}} - \DeclareUnicodeCharacter{01CF}{\v{I}} - - \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} - \DeclareUnicodeCharacter{01D1}{\v{O}} - \DeclareUnicodeCharacter{01D2}{\v{o}} - \DeclareUnicodeCharacter{01D3}{\v{U}} - \DeclareUnicodeCharacter{01D4}{\v{u}} - - \DeclareUnicodeCharacter{01E2}{\={\AE}} - \DeclareUnicodeCharacter{01E3}{\={\ae}} - \DeclareUnicodeCharacter{01E6}{\v{G}} - \DeclareUnicodeCharacter{01E7}{\v{g}} - \DeclareUnicodeCharacter{01E8}{\v{K}} - \DeclareUnicodeCharacter{01E9}{\v{k}} - - \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} - \DeclareUnicodeCharacter{01F1}{DZ} - \DeclareUnicodeCharacter{01F2}{Dz} - \DeclareUnicodeCharacter{01F3}{dz} - \DeclareUnicodeCharacter{01F4}{\'G} - \DeclareUnicodeCharacter{01F5}{\'g} - \DeclareUnicodeCharacter{01F8}{\`N} - \DeclareUnicodeCharacter{01F9}{\`n} - \DeclareUnicodeCharacter{01FC}{\'{\AE}} - \DeclareUnicodeCharacter{01FD}{\'{\ae}} - \DeclareUnicodeCharacter{01FE}{\'{\O}} - \DeclareUnicodeCharacter{01FF}{\'{\o}} - - \DeclareUnicodeCharacter{021E}{\v{H}} - \DeclareUnicodeCharacter{021F}{\v{h}} - - \DeclareUnicodeCharacter{0226}{\dotaccent{A}} - \DeclareUnicodeCharacter{0227}{\dotaccent{a}} - \DeclareUnicodeCharacter{0228}{\cedilla{E}} - \DeclareUnicodeCharacter{0229}{\cedilla{e}} - \DeclareUnicodeCharacter{022E}{\dotaccent{O}} - \DeclareUnicodeCharacter{022F}{\dotaccent{o}} - - \DeclareUnicodeCharacter{0232}{\=Y} - \DeclareUnicodeCharacter{0233}{\=y} - \DeclareUnicodeCharacter{0237}{\dotless{j}} - - \DeclareUnicodeCharacter{02DB}{\ogonek{ }} - - \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} - \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} - \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} - \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} - \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} - \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} - \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} - \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} - \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} - \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} - \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} - \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} - - \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} - \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} - - \DeclareUnicodeCharacter{1E20}{\=G} - \DeclareUnicodeCharacter{1E21}{\=g} - \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} - \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} - \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} - \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} - \DeclareUnicodeCharacter{1E26}{\"H} - \DeclareUnicodeCharacter{1E27}{\"h} - - \DeclareUnicodeCharacter{1E30}{\'K} - \DeclareUnicodeCharacter{1E31}{\'k} - \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} - \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} - \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} - \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} - \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} - \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} - \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} - \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} - \DeclareUnicodeCharacter{1E3E}{\'M} - \DeclareUnicodeCharacter{1E3F}{\'m} - - \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} - \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} - \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} - \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} - \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} - \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} - \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} - \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} - \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} - \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} - - \DeclareUnicodeCharacter{1E54}{\'P} - \DeclareUnicodeCharacter{1E55}{\'p} - \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} - \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} - \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} - \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} - \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} - \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} - \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} - \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} - - \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} - \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} - \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} - \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} - \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} - \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} - \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} - \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} - \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} - \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} - - \DeclareUnicodeCharacter{1E7C}{\~V} - \DeclareUnicodeCharacter{1E7D}{\~v} - \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} - \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} - - \DeclareUnicodeCharacter{1E80}{\`W} - \DeclareUnicodeCharacter{1E81}{\`w} - \DeclareUnicodeCharacter{1E82}{\'W} - \DeclareUnicodeCharacter{1E83}{\'w} - \DeclareUnicodeCharacter{1E84}{\"W} - \DeclareUnicodeCharacter{1E85}{\"w} - \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} - \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} - \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} - \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} - \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} - \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} - \DeclareUnicodeCharacter{1E8C}{\"X} - \DeclareUnicodeCharacter{1E8D}{\"x} - \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} - \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} - - \DeclareUnicodeCharacter{1E90}{\^Z} - \DeclareUnicodeCharacter{1E91}{\^z} - \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} - \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} - \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} - \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} - \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} - \DeclareUnicodeCharacter{1E97}{\"t} - \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} - \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} - - \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} - \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} - - \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} - \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} - \DeclareUnicodeCharacter{1EBC}{\~E} - \DeclareUnicodeCharacter{1EBD}{\~e} - - \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} - \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} - \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} - \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} - - \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} - \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} - - \DeclareUnicodeCharacter{1EF2}{\`Y} - \DeclareUnicodeCharacter{1EF3}{\`y} - \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} - - \DeclareUnicodeCharacter{1EF8}{\~Y} - \DeclareUnicodeCharacter{1EF9}{\~y} - - \DeclareUnicodeCharacter{2013}{--} - \DeclareUnicodeCharacter{2014}{---} - \DeclareUnicodeCharacter{2018}{\quoteleft} - \DeclareUnicodeCharacter{2019}{\quoteright} - \DeclareUnicodeCharacter{201A}{\quotesinglbase} - \DeclareUnicodeCharacter{201C}{\quotedblleft} - \DeclareUnicodeCharacter{201D}{\quotedblright} - \DeclareUnicodeCharacter{201E}{\quotedblbase} - \DeclareUnicodeCharacter{2022}{\bullet} - \DeclareUnicodeCharacter{2026}{\dots} - \DeclareUnicodeCharacter{2039}{\guilsinglleft} - \DeclareUnicodeCharacter{203A}{\guilsinglright} - \DeclareUnicodeCharacter{20AC}{\euro} - - \DeclareUnicodeCharacter{2192}{\expansion} - \DeclareUnicodeCharacter{21D2}{\result} - - \DeclareUnicodeCharacter{2212}{\minus} - \DeclareUnicodeCharacter{2217}{\point} - \DeclareUnicodeCharacter{2261}{\equiv} -}% end of \utfeightchardefs - - -% US-ASCII character definitions. -\def\asciichardefs{% nothing need be done - \relax -} - -% Make non-ASCII characters printable again for compatibility with -% existing Texinfo documents that may use them, even without declaring a -% document encoding. -% -\setnonasciicharscatcode \other - - -\message{formatting,} - -\newdimen\defaultparindent \defaultparindent = 15pt - -\chapheadingskip = 15pt plus 4pt minus 2pt -\secheadingskip = 12pt plus 3pt minus 2pt -\subsecheadingskip = 9pt plus 2pt minus 2pt - -% Prevent underfull vbox error messages. -\vbadness = 10000 - -% Don't be very finicky about underfull hboxes, either. -\hbadness = 6666 - -% Following George Bush, get rid of widows and orphans. -\widowpenalty=10000 -\clubpenalty=10000 - -% Use TeX 3.0's \emergencystretch to help line breaking, but if we're -% using an old version of TeX, don't do anything. We want the amount of -% stretch added to depend on the line length, hence the dependence on -% \hsize. We call this whenever the paper size is set. -% -\def\setemergencystretch{% - \ifx\emergencystretch\thisisundefined - % Allow us to assign to \emergencystretch anyway. - \def\emergencystretch{\dimen0}% - \else - \emergencystretch = .15\hsize - \fi -} - -% Parameters in order: 1) textheight; 2) textwidth; -% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; -% 7) physical page height; 8) physical page width. -% -% We also call \setleading{\textleading}, so the caller should define -% \textleading. The caller should also set \parskip. -% -\def\internalpagesizes#1#2#3#4#5#6#7#8{% - \voffset = #3\relax - \topskip = #6\relax - \splittopskip = \topskip - % - \vsize = #1\relax - \advance\vsize by \topskip - \outervsize = \vsize - \advance\outervsize by 2\topandbottommargin - \pageheight = \vsize - % - \hsize = #2\relax - \outerhsize = \hsize - \advance\outerhsize by 0.5in - \pagewidth = \hsize - % - \normaloffset = #4\relax - \bindingoffset = #5\relax - % - \ifpdf - \pdfpageheight #7\relax - \pdfpagewidth #8\relax - % if we don't reset these, they will remain at "1 true in" of - % whatever layout pdftex was dumped with. - \pdfhorigin = 1 true in - \pdfvorigin = 1 true in - \fi - % - \setleading{\textleading} - % - \parindent = \defaultparindent - \setemergencystretch -} - -% @letterpaper (the default). -\def\letterpaper{{\globaldefs = 1 - \parskip = 3pt plus 2pt minus 1pt - \textleading = 13.2pt - % - % If page is nothing but text, make it come out even. - \internalpagesizes{607.2pt}{6in}% that's 46 lines - {\voffset}{.25in}% - {\bindingoffset}{36pt}% - {11in}{8.5in}% -}} - -% Use @smallbook to reset parameters for 7x9.25 trim size. -\def\smallbook{{\globaldefs = 1 - \parskip = 2pt plus 1pt - \textleading = 12pt - % - \internalpagesizes{7.5in}{5in}% - {-.2in}{0in}% - {\bindingoffset}{16pt}% - {9.25in}{7in}% - % - \lispnarrowing = 0.3in - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = .5cm -}} - -% Use @smallerbook to reset parameters for 6x9 trim size. -% (Just testing, parameters still in flux.) -\def\smallerbook{{\globaldefs = 1 - \parskip = 1.5pt plus 1pt - \textleading = 12pt - % - \internalpagesizes{7.4in}{4.8in}% - {-.2in}{-.4in}% - {0pt}{14pt}% - {9in}{6in}% - % - \lispnarrowing = 0.25in - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = .4cm -}} - -% Use @afourpaper to print on European A4 paper. -\def\afourpaper{{\globaldefs = 1 - \parskip = 3pt plus 2pt minus 1pt - \textleading = 13.2pt - % - % Double-side printing via postscript on Laserjet 4050 - % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. - % To change the settings for a different printer or situation, adjust - % \normaloffset until the front-side and back-side texts align. Then - % do the same for \bindingoffset. You can set these for testing in - % your texinfo source file like this: - % @tex - % \global\normaloffset = -6mm - % \global\bindingoffset = 10mm - % @end tex - \internalpagesizes{673.2pt}{160mm}% that's 51 lines - {\voffset}{\hoffset}% - {\bindingoffset}{44pt}% - {297mm}{210mm}% - % - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = 5mm -}} - -% Use @afivepaper to print on European A5 paper. -% From romildo@urano.iceb.ufop.br, 2 July 2000. -% He also recommends making @example and @lisp be small. -\def\afivepaper{{\globaldefs = 1 - \parskip = 2pt plus 1pt minus 0.1pt - \textleading = 12.5pt - % - \internalpagesizes{160mm}{120mm}% - {\voffset}{\hoffset}% - {\bindingoffset}{8pt}% - {210mm}{148mm}% - % - \lispnarrowing = 0.2in - \tolerance = 800 - \hfuzz = 1.2pt - \contentsrightmargin = 0pt - \defbodyindent = 2mm - \tableindent = 12mm -}} - -% A specific text layout, 24x15cm overall, intended for A4 paper. -\def\afourlatex{{\globaldefs = 1 - \afourpaper - \internalpagesizes{237mm}{150mm}% - {\voffset}{4.6mm}% - {\bindingoffset}{7mm}% - {297mm}{210mm}% - % - % Must explicitly reset to 0 because we call \afourpaper. - \globaldefs = 0 -}} - -% Use @afourwide to print on A4 paper in landscape format. -\def\afourwide{{\globaldefs = 1 - \afourpaper - \internalpagesizes{241mm}{165mm}% - {\voffset}{-2.95mm}% - {\bindingoffset}{7mm}% - {297mm}{210mm}% - \globaldefs = 0 -}} - -% @pagesizes TEXTHEIGHT[,TEXTWIDTH] -% Perhaps we should allow setting the margins, \topskip, \parskip, -% and/or leading, also. Or perhaps we should compute them somehow. -% -\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} -\def\pagesizesyyy#1,#2,#3\finish{{% - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi - \globaldefs = 1 - % - \parskip = 3pt plus 2pt minus 1pt - \setleading{\textleading}% - % - \dimen0 = #1\relax - \advance\dimen0 by \voffset - % - \dimen2 = \hsize - \advance\dimen2 by \normaloffset - % - \internalpagesizes{#1}{\hsize}% - {\voffset}{\normaloffset}% - {\bindingoffset}{44pt}% - {\dimen0}{\dimen2}% -}} - -% Set default to letter. -% -\letterpaper - - -\message{and turning on texinfo input format.} - -\def^^L{\par} % remove \outer, so ^L can appear in an @comment - -% DEL is a comment character, in case @c does not suffice. -\catcode`\^^? = 14 - -% Define macros to output various characters with catcode for normal text. -\catcode`\"=\other \def\normaldoublequote{"} -\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix -\catcode`\+=\other \def\normalplus{+} -\catcode`\<=\other \def\normalless{<} -\catcode`\>=\other \def\normalgreater{>} -\catcode`\^=\other \def\normalcaret{^} -\catcode`\_=\other \def\normalunderscore{_} -\catcode`\|=\other \def\normalverticalbar{|} -\catcode`\~=\other \def\normaltilde{~} - -% This macro is used to make a character print one way in \tt -% (where it can probably be output as-is), and another way in other fonts, -% where something hairier probably needs to be done. -% -% #1 is what to print if we are indeed using \tt; #2 is what to print -% otherwise. Since all the Computer Modern typewriter fonts have zero -% interword stretch (and shrink), and it is reasonable to expect all -% typewriter fonts to have this, we can check that font parameter. -% -\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} - -% Same as above, but check for italic font. Actually this also catches -% non-italic slanted fonts since it is impossible to distinguish them from -% italic fonts. But since this is only used by $ and it uses \sl anyway -% this is not a problem. -\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} - -% Turn off all special characters except @ -% (and those which the user can use as if they were ordinary). -% Most of these we simply print from the \tt font, but for some, we can -% use math or other variants that look better in normal text. - -\catcode`\"=\active -\def\activedoublequote{{\tt\char34}} -\let"=\activedoublequote -\catcode`\~=\active -\def~{{\tt\char126}} -\chardef\hat=`\^ -\catcode`\^=\active -\def^{{\tt \hat}} - -\catcode`\_=\active -\def_{\ifusingtt\normalunderscore\_} -\let\realunder=_ -% Subroutine for the previous macro. -\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } - -\catcode`\|=\active -\def|{{\tt\char124}} -\chardef \less=`\< -\catcode`\<=\active -\def<{{\tt \less}} -\chardef \gtr=`\> -\catcode`\>=\active -\def>{{\tt \gtr}} -\catcode`\+=\active -\def+{{\tt \char 43}} -\catcode`\$=\active -\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix - -% If a .fmt file is being used, characters that might appear in a file -% name cannot be active until we have parsed the command line. -% So turn them off again, and have \everyjob (or @setfilename) turn them on. -% \otherifyactive is called near the end of this file. -\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} - -% Used sometimes to turn off (effectively) the active characters even after -% parsing them. -\def\turnoffactive{% - \normalturnoffactive - \otherbackslash -} - -\catcode`\@=0 - -% \backslashcurfont outputs one backslash character in current font, -% as in \char`\\. -\global\chardef\backslashcurfont=`\\ -\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work - -% \realbackslash is an actual character `\' with catcode other, and -% \doublebackslash is two of them (for the pdf outlines). -{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} - -% In texinfo, backslash is an active character; it prints the backslash -% in fixed width font. -\catcode`\\=\active % @ for escape char from now on. - -% The story here is that in math mode, the \char of \backslashcurfont -% ends up printing the roman \ from the math symbol font (because \char -% in math mode uses the \mathcode, and plain.tex sets -% \mathcode`\\="026E). It seems better for @backslashchar{} to always -% print a typewriter backslash, hence we use an explicit \mathchar, -% which is the decimal equivalent of "715c (class 7, e.g., use \fam; -% ignored family value; char position "5C). We can't use " for the -% usual hex value because it has already been made active. -@def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} -@let@backslashchar = @normalbackslash % @backslashchar{} is for user documents. - -% On startup, @fixbackslash assigns: -% @let \ = @normalbackslash -% \rawbackslash defines an active \ to do \backslashcurfont. -% \otherbackslash defines an active \ to be a literal `\' character with -% catcode other. We switch back and forth between these. -@gdef@rawbackslash{@let\=@backslashcurfont} -@gdef@otherbackslash{@let\=@realbackslash} - -% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of -% the literal character `\'. Also revert - to its normal character, in -% case the active - from code has slipped in. -% -{@catcode`- = @active - @gdef@normalturnoffactive{% - @let-=@normaldash - @let"=@normaldoublequote - @let$=@normaldollar %$ font-lock fix - @let+=@normalplus - @let<=@normalless - @let>=@normalgreater - @let\=@normalbackslash - @let^=@normalcaret - @let_=@normalunderscore - @let|=@normalverticalbar - @let~=@normaltilde - @markupsetuplqdefault - @markupsetuprqdefault - @unsepspaces - } -} - -% Make _ and + \other characters, temporarily. -% This is canceled by @fixbackslash. -@otherifyactive - -% If a .fmt file is being used, we don't want the `\input texinfo' to show up. -% That is what \eatinput is for; after that, the `\' should revert to printing -% a backslash. -% -@gdef@eatinput input texinfo{@fixbackslash} -@global@let\ = @eatinput - -% On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\' in the file would cause an error. This macro tries to fix -% that, assuming it is called before the first `\' could plausibly occur. -% Also turn back on active characters that might appear in the input -% file name, in case not using a pre-dumped format. -% -@gdef@fixbackslash{% - @ifx\@eatinput @let\ = @normalbackslash @fi - @catcode`+=@active - @catcode`@_=@active -} - -% Say @foo, not \foo, in error messages. -@escapechar = `@@ - -% These (along with & and #) are made active for url-breaking, so need -% active definitions as the normal characters. -@def@normaldot{.} -@def@normalquest{?} -@def@normalslash{/} - -% These look ok in all fonts, so just make them not special. -% @hashchar{} gets its own user-level command, because of #line. -@catcode`@& = @other @def@normalamp{&} -@catcode`@# = @other @def@normalhash{#} -@catcode`@% = @other @def@normalpercent{%} - -@let @hashchar = @normalhash - -@c Finally, make ` and ' active, so that txicodequoteundirected and -@c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we -@c don't make ` and ' active, @code will not get them as active chars. -@c Do this last of all since we use ` in the previous @catcode assignments. -@catcode`@'=@active -@catcode`@`=@active -@markupsetuplqdefault -@markupsetuprqdefault - -@c Local variables: -@c eval: (add-hook 'write-file-hooks 'time-stamp) -@c page-delimiter: "^\\\\message" -@c time-stamp-start: "def\\\\texinfoversion{" -@c time-stamp-format: "%:y-%02m-%02d.%02H" -@c time-stamp-end: "}" -@c End: - -@c vim:sw=2: - -@ignore - arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 -@end ignore diff --git a/ruby/ext/fiddle/memory_view.c b/ruby/ext/fiddle/memory_view.c new file mode 100644 index 000000000..fa66fc2c7 --- /dev/null +++ b/ruby/ext/fiddle/memory_view.c @@ -0,0 +1,321 @@ +#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/ruby/ext/fiddle/pinned.c b/ruby/ext/fiddle/pinned.c new file mode 100644 index 000000000..019a3020e --- /dev/null +++ b/ruby/ext/fiddle/pinned.c @@ -0,0 +1,123 @@ +#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/ruby/ext/fiddle/pointer.c b/ruby/ext/fiddle/pointer.c index 117cc9b82..15107e386 100644 --- a/ruby/ext/fiddle/pointer.c +++ b/ruby/ext/fiddle/pointer.c @@ -2,11 +2,17 @@ * $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) @@ -18,12 +24,13 @@ VALUE rb_cPointer; -typedef void (*freefunc_t)(void*); +typedef rb_fiddle_freefunc_t freefunc_t; struct ptr_data { void *ptr; long size; freefunc_t free; + bool freed; VALUE wrap[2]; }; @@ -57,14 +64,19 @@ fiddle_ptr_mark(void *ptr) } static void -fiddle_ptr_free(void *ptr) +fiddle_ptr_free_ptr(void *ptr) { struct ptr_data *data = ptr; - if (data->ptr) { - if (data->free) { - (*(data->free))(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); } @@ -80,8 +92,40 @@ static const rb_data_type_t fiddle_ptr_data_type = { {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,}, }; +#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) +rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) { struct ptr_data *data; VALUE val; @@ -89,25 +133,34 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func) 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; + data->wrap[0] = wrap0; + 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); + return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0); } static VALUE -rb_fiddle_ptr_malloc(long size, freefunc_t func) +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_new(ptr, size, func); + return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0); } static void * @@ -140,6 +193,7 @@ rb_fiddle_ptr_s_allocate(VALUE klass) data->ptr = 0; data->size = 0; data->free = 0; + data->freed = false; return obj; } @@ -191,16 +245,53 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self) 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+ that will be called when the pointer is garbage collected. + * +freefunc+. * - * +freefunc+ must be an address pointing to a function or an instance of - * Fiddle::Function + * 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) @@ -222,10 +313,17 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) rb_bug("rb_fiddle_ptr_s_malloc"); } - obj = rb_fiddle_ptr_malloc(s,f); + obj = rb_fiddle_ptr_malloc(klass, s,f); if (wrap) RPTR_DATA(obj)->wrap[1] = wrap; - return obj; + 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; + } } /* @@ -350,6 +448,34 @@ rb_fiddle_ptr_free_get(VALUE self) 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: * @@ -541,7 +667,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self) struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference"); + if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference"); switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){ case 1: offset = NUM2ULONG(arg0); @@ -579,7 +705,7 @@ rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self) struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference"); + 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); @@ -652,6 +778,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) } 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){ @@ -660,7 +787,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) wrap = 0; } else{ - rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object"); + rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object"); } } else{ @@ -691,6 +818,8 @@ Init_fiddle_pointer(void) 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); @@ -712,6 +841,10 @@ Init_fiddle_pointer(void) 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 diff --git a/ruby/ext/fiddle/win32/fficonfig.h b/ruby/ext/fiddle/win32/fficonfig.h old mode 100755 new mode 100644 diff --git a/ruby/ext/fiddle/win32/libffi-config.rb b/ruby/ext/fiddle/win32/libffi-config.rb index 6abc9b2c0..985fc29d3 100755 --- a/ruby/ext/fiddle/win32/libffi-config.rb +++ b/ruby/ext/fiddle/win32/libffi-config.rb @@ -32,7 +32,7 @@ end end -builddir = srcdir == "." ? enable['builddir'] : "." +builddir = srcdir == "." ? (enable['builddir'] || ".") : "." conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32" FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"]) diff --git a/ruby/ext/fiddle/win32/libffi.mk.tmpl b/ruby/ext/fiddle/win32/libffi.mk.tmpl old mode 100755 new mode 100644 diff --git a/ruby/ext/gdbm/README b/ruby/ext/gdbm/README deleted file mode 100644 index df7a261c6..000000000 --- a/ruby/ext/gdbm/README +++ /dev/null @@ -1 +0,0 @@ -gdbm ext-library for Ruby 1.3 or later diff --git a/ruby/ext/gdbm/depend b/ruby/ext/gdbm/depend deleted file mode 100644 index 33635bc09..000000000 --- a/ruby/ext/gdbm/depend +++ /dev/null @@ -1,14 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -gdbm.o: $(RUBY_EXTCONF_H) -gdbm.o: $(arch_hdrdir)/ruby/config.h -gdbm.o: $(hdrdir)/ruby.h -gdbm.o: $(hdrdir)/ruby/assert.h -gdbm.o: $(hdrdir)/ruby/backward.h -gdbm.o: $(hdrdir)/ruby/defines.h -gdbm.o: $(hdrdir)/ruby/intern.h -gdbm.o: $(hdrdir)/ruby/missing.h -gdbm.o: $(hdrdir)/ruby/ruby.h -gdbm.o: $(hdrdir)/ruby/st.h -gdbm.o: $(hdrdir)/ruby/subst.h -gdbm.o: gdbm.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/gdbm/extconf.rb b/ruby/ext/gdbm/extconf.rb deleted file mode 100644 index d1908ffa5..000000000 --- a/ruby/ext/gdbm/extconf.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' - -dir_config("gdbm") -if have_library("gdbm", "gdbm_open") and - have_header("gdbm.h") - checking_for("sizeof(DBM) is available") { - if try_compile(< - -const int sizeof_DBM = (int)sizeof(DBM); -SRC - $defs << '-DDBM_SIZEOF_DBM=sizeof(DBM)' - else - $defs << '-DDBM_SIZEOF_DBM=0' - end - } - create_makefile("gdbm") -end diff --git a/ruby/ext/gdbm/gdbm.c b/ruby/ext/gdbm/gdbm.c deleted file mode 100644 index 4a6377b68..000000000 --- a/ruby/ext/gdbm/gdbm.c +++ /dev/null @@ -1,1306 +0,0 @@ -/************************************************ - - gdbm.c - - - $Author$ - modified at: Mon Jan 24 15:59:52 JST 1994 - - Documentation by Peter Adolphs < futzilogik at users dot sourceforge dot net > - -************************************************/ - -#include "ruby.h" - -#include -#include -#include - -/* - * Document-class: GDBM - * - * == Summary - * - * Ruby extension for GNU dbm (gdbm) -- a simple database engine for storing - * key-value pairs on disk. - * - * == Description - * - * GNU dbm is a library for simple databases. A database is a file that stores - * key-value pairs. Gdbm allows the user to store, retrieve, and delete data by - * key. It furthermore allows a non-sorted traversal of all key-value pairs. - * A gdbm database thus provides the same functionality as a hash. As - * with objects of the Hash class, elements can be accessed with []. - * Furthermore, GDBM mixes in the Enumerable module, thus providing convenient - * methods such as #find, #collect, #map, etc. - * - * A process is allowed to open several different databases at the same time. - * A process can open a database as a "reader" or a "writer". Whereas a reader - * has only read-access to the database, a writer has read- and write-access. - * A database can be accessed either by any number of readers or by exactly one - * writer at the same time. - * - * == Examples - * - * 1. Opening/creating a database, and filling it with some entries: - * - * require 'gdbm' - * - * gdbm = GDBM.new("fruitstore.db") - * gdbm["ananas"] = "3" - * gdbm["banana"] = "8" - * gdbm["cranberry"] = "4909" - * gdbm.close - * - * 2. Reading out a database: - * - * require 'gdbm' - * - * gdbm = GDBM.new("fruitstore.db") - * gdbm.each_pair do |key, value| - * print "#{key}: #{value}\n" - * end - * gdbm.close - * - * produces - * - * banana: 8 - * ananas: 3 - * cranberry: 4909 - * - * == Links - * - * * http://www.gnu.org/software/gdbm/ - */ -static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError; - -#if SIZEOF_LONG > SIZEOF_INT -#define TOO_LONG(n) ((long)(+(int)(n)) != (long)(n)) -#else -#define TOO_LONG(n) 0 -#endif - -#define RUBY_GDBM_RW_BIT 0x20000000 - -#define MY_BLOCK_SIZE (2048) -#define MY_FATAL_FUNC rb_gdbm_fatal - -NORETURN(static void rb_gdbm_fatal(const char *msg)); -NORETURN(static void closed_dbm(void)); - -static void -rb_gdbm_fatal(const char *msg) -{ - rb_raise(rb_eGDBMFatalError, "%s", msg); -} - -struct dbmdata { - int di_size; - GDBM_FILE di_dbm; -}; - -static void -closed_dbm(void) -{ - rb_raise(rb_eRuntimeError, "closed GDBM file"); -} - -#define GetDBM(obj, dbmp) do {\ - TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\ - if ((dbmp)->di_dbm == 0) closed_dbm();\ -} while (0) - -#define GetDBM2(obj, dbmp, dbm) do {\ - GetDBM((obj), (dbmp));\ - (dbm) = (dbmp)->di_dbm;\ -} while (0) - -static void -free_dbm(void *ptr) -{ - struct dbmdata *dbmp = ptr; - if (dbmp->di_dbm) - gdbm_close(dbmp->di_dbm); - xfree(dbmp); -} - -static size_t -memsize_dbm(const void *ptr) -{ - const struct dbmdata *dbmp = ptr; - size_t size = sizeof(*dbmp); - if (dbmp->di_dbm) - size += DBM_SIZEOF_DBM; - return size; -} - -static const rb_data_type_t dbm_type = { - "gdbm", - {0, free_dbm, memsize_dbm,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, -}; - -/* - * call-seq: - * gdbm.close -> nil - * - * Closes the associated database file. - */ -static VALUE -fgdbm_close(VALUE obj) -{ - struct dbmdata *dbmp; - - GetDBM(obj, dbmp); - gdbm_close(dbmp->di_dbm); - dbmp->di_dbm = 0; - - return Qnil; -} - -/* - * call-seq: - * gdbm.closed? -> true or false - * - * Returns true if the associated database file has been closed. - */ -static VALUE -fgdbm_closed(VALUE obj) -{ - struct dbmdata *dbmp; - - TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp); - if (dbmp->di_dbm == 0) - return Qtrue; - - return Qfalse; -} - -static VALUE -fgdbm_s_alloc(VALUE klass) -{ - struct dbmdata *dbmp; - - return TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp); -} - -/* - * call-seq: - * GDBM.new(filename, mode = 0666, flags = nil) - * - * Creates a new GDBM instance by opening a gdbm file named _filename_. - * If the file does not exist, a new file with file mode _mode_ will be - * created. _flags_ may be one of the following: - * * *READER* - open as a reader - * * *WRITER* - open as a writer - * * *WRCREAT* - open as a writer; if the database does not exist, create a new one - * * *NEWDB* - open as a writer; overwrite any existing databases - * - * The values *WRITER*, *WRCREAT* and *NEWDB* may be combined with the following - * values by bitwise or: - * * *SYNC* - cause all database operations to be synchronized to the disk - * * *NOLOCK* - do not lock the database file - * - * If no _flags_ are specified, the GDBM object will try to open the database - * file as a writer and will create it if it does not already exist - * (cf. flag WRCREAT). If this fails (for instance, if another process - * has already opened the database as a reader), it will try to open the - * database file as a reader (cf. flag READER). - */ -static VALUE -fgdbm_initialize(int argc, VALUE *argv, VALUE obj) -{ - VALUE file, vmode, vflags; - GDBM_FILE dbm; - struct dbmdata *dbmp; - int mode, flags = 0; - - TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp); - if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { - mode = 0666; /* default value */ - } - else if (NIL_P(vmode)) { - mode = -1; /* return nil if DB does not exist */ - } - else { - mode = NUM2INT(vmode); - } - - if (!NIL_P(vflags)) - flags = NUM2INT(vflags); - - FilePathValue(file); - -#ifdef GDBM_CLOEXEC - /* GDBM_CLOEXEC is available since gdbm 1.10. */ - flags |= GDBM_CLOEXEC; -#endif - - if (flags & RUBY_GDBM_RW_BIT) { - flags &= ~RUBY_GDBM_RW_BIT; - dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE, - flags, mode, MY_FATAL_FUNC); - } - else { - dbm = 0; - if (mode >= 0) - dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE, - GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC); - if (!dbm) - dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE, - GDBM_WRITER|flags, 0, MY_FATAL_FUNC); - if (!dbm) - dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE, - GDBM_READER|flags, 0, MY_FATAL_FUNC); - } - - if (dbm) { - rb_fd_fix_cloexec(gdbm_fdesc(dbm)); - } - - if (!dbm) { - if (mode == -1) return Qnil; - - if (gdbm_errno == GDBM_FILE_OPEN_ERROR || - gdbm_errno == GDBM_CANT_BE_READER || - gdbm_errno == GDBM_CANT_BE_WRITER) - rb_sys_fail_str(file); - else - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - - if (dbmp->di_dbm) - gdbm_close(dbmp->di_dbm); - dbmp->di_dbm = dbm; - dbmp->di_size = -1; - - return obj; -} - -/* - * call-seq: - * GDBM.open(filename, mode = 0666, flags = nil) - * GDBM.open(filename, mode = 0666, flags = nil) { |gdbm| ... } - * - * If called without a block, this is synonymous to GDBM::new. - * If a block is given, the new GDBM instance will be passed to the block - * as a parameter, and the corresponding database file will be closed - * after the execution of the block code has been finished. - * - * Example for an open call with a block: - * - * require 'gdbm' - * GDBM.open("fruitstore.db") do |gdbm| - * gdbm.each_pair do |key, value| - * print "#{key}: #{value}\n" - * end - * end - */ -static VALUE -fgdbm_s_open(int argc, VALUE *argv, VALUE klass) -{ - VALUE obj = fgdbm_s_alloc(klass); - - if (NIL_P(fgdbm_initialize(argc, argv, obj))) { - return Qnil; - } - - if (rb_block_given_p()) { - return rb_ensure(rb_yield, obj, fgdbm_close, obj); - } - - return obj; -} - -static VALUE -rb_gdbm_fetch(GDBM_FILE dbm, datum key) -{ - datum val; - VALUE str; - - val = gdbm_fetch(dbm, key); - if (val.dptr == 0) - return Qnil; - - str = rb_str_new(val.dptr, val.dsize); - free(val.dptr); - return str; -} - -static VALUE -rb_gdbm_fetch2(GDBM_FILE dbm, VALUE keystr) -{ - datum key; - long len; - - ExportStringValue(keystr); - len = RSTRING_LEN(keystr); - if (TOO_LONG(len)) return Qnil; - key.dptr = RSTRING_PTR(keystr); - key.dsize = (int)len; - - return rb_gdbm_fetch(dbm, key); -} - -static VALUE -rb_gdbm_fetch3(VALUE obj, VALUE keystr) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - - GetDBM2(obj, dbmp, dbm); - return rb_gdbm_fetch2(dbm, keystr); -} - -static VALUE -rb_gdbm_firstkey(GDBM_FILE dbm) -{ - datum key; - VALUE str; - - key = gdbm_firstkey(dbm); - if (key.dptr == 0) - return Qnil; - - str = rb_str_new(key.dptr, key.dsize); - free(key.dptr); - return str; -} - -static VALUE -rb_gdbm_nextkey(GDBM_FILE dbm, VALUE keystr) -{ - datum key, key2; - VALUE str; - long len; - - len = RSTRING_LEN(keystr); - if (TOO_LONG(len)) return Qnil; - key.dptr = RSTRING_PTR(keystr); - key.dsize = (int)len; - key2 = gdbm_nextkey(dbm, key); - if (key2.dptr == 0) - return Qnil; - - str = rb_str_new(key2.dptr, key2.dsize); - free(key2.dptr); - return str; -} - -static VALUE -fgdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) -{ - VALUE valstr; - - valstr = rb_gdbm_fetch3(obj, keystr); - if (NIL_P(valstr)) { - if (ifnone == Qnil && rb_block_given_p()) - return rb_yield(keystr); - return ifnone; - } - return valstr; -} - -/* - * call-seq: - * gdbm[key] -> value - * - * Retrieves the _value_ corresponding to _key_. - */ -static VALUE -fgdbm_aref(VALUE obj, VALUE keystr) -{ - return rb_gdbm_fetch3(obj, keystr); -} - -/* - * call-seq: - * gdbm.fetch(key [, default]) -> value - * - * Retrieves the _value_ corresponding to _key_. If there is no value - * associated with _key_, _default_ will be returned instead. - */ -static VALUE -fgdbm_fetch_m(int argc, VALUE *argv, VALUE obj) -{ - VALUE keystr, valstr, ifnone; - - rb_scan_args(argc, argv, "11", &keystr, &ifnone); - valstr = fgdbm_fetch(obj, keystr, ifnone); - if (argc == 1 && !rb_block_given_p() && NIL_P(valstr)) - rb_raise(rb_eIndexError, "key not found"); - - return valstr; -} - -/* - * call-seq: - * gdbm.key(value) -> key - * - * Returns the _key_ for a given _value_. If several keys may map to the - * same value, the key that is found first will be returned. - */ -static VALUE -fgdbm_key(VALUE obj, VALUE valstr) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, valstr2; - - ExportStringValue(valstr); - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - valstr2 = rb_gdbm_fetch2(dbm, keystr); - if (!NIL_P(valstr2) && - (int)RSTRING_LEN(valstr) == (int)RSTRING_LEN(valstr2) && - memcmp(RSTRING_PTR(valstr), RSTRING_PTR(valstr2), - (int)RSTRING_LEN(valstr)) == 0) { - return keystr; - } - } - return Qnil; -} - -/* :nodoc: */ -static VALUE -fgdbm_index(VALUE obj, VALUE value) -{ - rb_warn("GDBM#index is deprecated; use GDBM#key"); - return fgdbm_key(obj, value); -} - -/* - * call-seq: - * gdbm.select { |key, value| block } -> array - * - * Returns a new array of all key-value pairs of the database for which _block_ - * evaluates to true. - */ -static VALUE -fgdbm_select(VALUE obj) -{ - VALUE new = rb_ary_new(); - GDBM_FILE dbm; - struct dbmdata *dbmp; - VALUE keystr; - - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - VALUE assoc = rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)); - VALUE v = rb_yield(assoc); - - if (RTEST(v)) { - rb_ary_push(new, assoc); - } - GetDBM2(obj, dbmp, dbm); - } - - return new; -} - -/* - * call-seq: - * gdbm.values_at(key, ...) -> array - * - * Returns an array of the values associated with each specified _key_. - */ -static VALUE -fgdbm_values_at(int argc, VALUE *argv, VALUE obj) -{ - VALUE new = rb_ary_new2(argc); - int i; - - for (i=0; idi_size = -1; - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - else if (dbmp->di_size >= 0) { - dbmp->di_size--; - } - return obj; -} - -/* - * call-seq: - * gdbm.delete(key) -> value or nil - * - * Removes the key-value-pair with the specified _key_ from this database and - * returns the corresponding _value_. Returns nil if the database is empty. - */ -static VALUE -fgdbm_delete(VALUE obj, VALUE keystr) -{ - VALUE valstr; - - valstr = fgdbm_fetch(obj, keystr, Qnil); - rb_gdbm_delete(obj, keystr); - return valstr; -} - -/* - * call-seq: - * gdbm.shift -> (key, value) or nil - * - * Removes a key-value-pair from this database and returns it as a - * two-item array [ _key_, _value_ ]. Returns nil if the database is empty. - */ -static VALUE -fgdbm_shift(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, valstr; - - rb_gdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - keystr = rb_gdbm_firstkey(dbm); - if (NIL_P(keystr)) return Qnil; - valstr = rb_gdbm_fetch2(dbm, keystr); - rb_gdbm_delete(obj, keystr); - - return rb_assoc_new(keystr, valstr); -} - -/* - * call-seq: - * gdbm.delete_if { |key, value| block } -> gdbm - * gdbm.reject! { |key, value| block } -> gdbm - * - * Deletes every key-value pair from _gdbm_ for which _block_ evaluates to true. - */ -static VALUE -fgdbm_delete_if(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, valstr; - VALUE ret, ary = rb_ary_tmp_new(0); - long i; - int status = 0, n; - - rb_gdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - n = dbmp->di_size; - dbmp->di_size = -1; - - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - OBJ_FREEZE(keystr); - valstr = rb_gdbm_fetch2(dbm, keystr); - ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); - if (status != 0) break; - if (RTEST(ret)) rb_ary_push(ary, keystr); - GetDBM2(obj, dbmp, dbm); - } - - for (i = 0; i < RARRAY_LEN(ary); i++) - rb_gdbm_delete(obj, RARRAY_AREF(ary, i)); - if (status) rb_jump_tag(status); - if (n > 0) dbmp->di_size = n - (int)RARRAY_LEN(ary); - rb_ary_clear(ary); - - return obj; -} - -/* - * call-seq: - * gdbm.clear -> gdbm - * - * Removes all the key-value pairs within _gdbm_. - */ -static VALUE -fgdbm_clear(VALUE obj) -{ - datum key, nextkey; - struct dbmdata *dbmp; - GDBM_FILE dbm; - - rb_gdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - -#if 0 - while (key = gdbm_firstkey(dbm), key.dptr) { - if (gdbm_delete(dbm, key)) { - free(key.dptr); - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - free(key.dptr); - } -#else - while (key = gdbm_firstkey(dbm), key.dptr) { - for (; key.dptr; key = nextkey) { - nextkey = gdbm_nextkey(dbm, key); - if (gdbm_delete(dbm, key)) { - free(key.dptr); - if (nextkey.dptr) free(nextkey.dptr); - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - free(key.dptr); - } - } -#endif - dbmp->di_size = 0; - - return obj; -} - -/* - * call-seq: - * gdbm.invert -> hash - * - * Returns a hash created by using _gdbm_'s values as keys, and the keys - * as values. - */ -static VALUE -fgdbm_invert(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, valstr; - VALUE hash = rb_hash_new(); - - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - valstr = rb_gdbm_fetch2(dbm, keystr); - - rb_hash_aset(hash, valstr, keystr); - } - return hash; -} - -/* - * call-seq: - * gdbm[key]= value -> value - * gdbm.store(key, value) -> value - * - * Associates the value _value_ with the specified _key_. - */ -static VALUE -fgdbm_store(VALUE obj, VALUE keystr, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - GDBM_FILE dbm; - - rb_gdbm_modify(obj); - ExportStringValue(keystr); - ExportStringValue(valstr); - - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - - val.dptr = RSTRING_PTR(valstr); - val.dsize = RSTRING_LENINT(valstr); - - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - if (gdbm_store(dbm, key, val, GDBM_REPLACE)) { - if (errno == EPERM) rb_sys_fail(0); - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - - return valstr; -} - -static VALUE -update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm)) -{ - const VALUE *ptr; - Check_Type(pair, T_ARRAY); - if (RARRAY_LEN(pair) < 2) { - rb_raise(rb_eArgError, "pair must be [key, value]"); - } - ptr = RARRAY_CONST_PTR(pair); - fgdbm_store(dbm, ptr[0], ptr[1]); - return Qnil; -} - -/* - * call-seq: - * gdbm.update(other) -> gdbm - * - * Adds the key-value pairs of _other_ to _gdbm_, overwriting entries with - * duplicate keys with those from _other_. _other_ must have an each_pair - * method. - */ -static VALUE -fgdbm_update(VALUE obj, VALUE other) -{ - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * gdbm.replace(other) -> gdbm - * - * Replaces the content of _gdbm_ with the key-value pairs of _other_. - * _other_ must have an each_pair method. - */ -static VALUE -fgdbm_replace(VALUE obj, VALUE other) -{ - fgdbm_clear(obj); - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * gdbm.length -> fixnum - * gdbm.size -> fixnum - * - * Returns the number of key-value pairs in this database. - */ -static VALUE -fgdbm_length(VALUE obj) -{ - datum key, nextkey; - struct dbmdata *dbmp; - GDBM_FILE dbm; - int i = 0; - - GetDBM2(obj, dbmp, dbm); - if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); - - for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { - nextkey = gdbm_nextkey(dbm, key); - free(key.dptr); - i++; - } - dbmp->di_size = i; - - return INT2FIX(i); -} - -/* - * call-seq: - * gdbm.empty? -> true or false - * - * Returns true if the database is empty. - */ -static VALUE -fgdbm_empty_p(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - GDBM_FILE dbm; - - GetDBM(obj, dbmp); - if (dbmp->di_size < 0) { - dbm = dbmp->di_dbm; - - key = gdbm_firstkey(dbm); - if (key.dptr) { - free(key.dptr); - return Qfalse; - } - return Qtrue; - } - - if (dbmp->di_size == 0) return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * gdbm.each_value { |value| block } -> gdbm - * - * Executes _block_ for each key in the database, passing the corresponding - * _value_ as a parameter. - */ -static VALUE -fgdbm_each_value(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_yield(rb_gdbm_fetch2(dbm, keystr)); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * gdbm.each_key { |key| block } -> gdbm - * - * Executes _block_ for each key in the database, passing the - * _key_ as a parameter. - */ -static VALUE -fgdbm_each_key(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_yield(keystr); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * gdbm.each_pair { |key, value| block } -> gdbm - * - * Executes _block_ for each key in the database, passing the _key_ and the - * corresponding _value_ as a parameter. - */ -static VALUE -fgdbm_each_pair(VALUE obj) -{ - GDBM_FILE dbm; - struct dbmdata *dbmp; - VALUE keystr; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr))); - GetDBM2(obj, dbmp, dbm); - } - - return obj; -} - -/* - * call-seq: - * gdbm.keys -> array - * - * Returns an array of all keys of this database. - */ -static VALUE -fgdbm_keys(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_ary_push(ary, keystr); - } - - return ary; -} - -/* - * call-seq: - * gdbm.values -> array - * - * Returns an array of all values of this database. - */ -static VALUE -fgdbm_values(VALUE obj) -{ - datum key, nextkey; - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE valstr, ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { - nextkey = gdbm_nextkey(dbm, key); - valstr = rb_gdbm_fetch(dbm, key); - free(key.dptr); - rb_ary_push(ary, valstr); - } - - return ary; -} - -/* - * call-seq: - * gdbm.include?(k) -> true or false - * gdbm.has_key?(k) -> true or false - * gdbm.member?(k) -> true or false - * gdbm.key?(k) -> true or false - * - * Returns true if the given key _k_ exists within the database. - * Returns false otherwise. - */ -static VALUE -fgdbm_has_key(VALUE obj, VALUE keystr) -{ - datum key; - struct dbmdata *dbmp; - GDBM_FILE dbm; - long len; - - ExportStringValue(keystr); - len = RSTRING_LENINT(keystr); - if (TOO_LONG(len)) return Qfalse; - key.dptr = RSTRING_PTR(keystr); - key.dsize = (int)len; - - GetDBM2(obj, dbmp, dbm); - if (gdbm_exists(dbm, key)) - return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * gdbm.has_value?(v) -> true or false - * gdbm.value?(v) -> true or false - * - * Returns true if the given value _v_ exists within the database. - * Returns false otherwise. - */ -static VALUE -fgdbm_has_value(VALUE obj, VALUE valstr) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, valstr2; - - ExportStringValue(valstr); - GetDBM2(obj, dbmp, dbm); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - valstr2 = rb_gdbm_fetch2(dbm, keystr); - - if (!NIL_P(valstr2) && - (int)RSTRING_LEN(valstr) == (int)RSTRING_LEN(valstr2) && - memcmp(RSTRING_PTR(valstr), RSTRING_PTR(valstr2), - (int)RSTRING_LEN(valstr)) == 0) { - return Qtrue; - } - } - return Qfalse; -} - -/* - * call-seq: - * gdbm.to_a -> array - * - * Returns an array of all key-value pairs contained in the database. - */ -static VALUE -fgdbm_to_a(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_ary_push(ary, rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr))); - } - - return ary; -} - -/* - * call-seq: - * gdbm.reorganize -> gdbm - * - * Reorganizes the database file. This operation removes reserved space of - * elements that have already been deleted. It is only useful after a lot of - * deletions in the database. - */ -static VALUE -fgdbm_reorganize(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - - rb_gdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - gdbm_reorganize(dbm); - rb_fd_fix_cloexec(gdbm_fdesc(dbm)); - return obj; -} - -/* - * call-seq: - * gdbm.sync -> gdbm - * - * Unless the _gdbm_ object has been opened with the *SYNC* flag, it is not - * guaranteed that database modification operations are immediately applied to - * the database file. This method ensures that all recent modifications - * to the database are written to the file. Blocks until all writing operations - * to the disk have been finished. - */ -static VALUE -fgdbm_sync(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - - rb_gdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - gdbm_sync(dbm); - return obj; -} - -/* - * call-seq: - * gdbm.cachesize = size -> size - * - * Sets the size of the internal bucket cache to _size_. - */ -static VALUE -fgdbm_set_cachesize(VALUE obj, VALUE val) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - int optval; - - GetDBM2(obj, dbmp, dbm); - optval = FIX2INT(val); - if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) { - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - return val; -} - -/* - * call-seq: - * gdbm.fastmode = boolean -> boolean - * - * Turns the database's fast mode on or off. If fast mode is turned on, gdbm - * does not wait for writes to be flushed to the disk before continuing. - * - * This option is obsolete for gdbm >= 1.8 since fast mode is turned on by - * default. See also: #syncmode= - */ -static VALUE -fgdbm_set_fastmode(VALUE obj, VALUE val) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - int optval; - - GetDBM2(obj, dbmp, dbm); - optval = 0; - if (RTEST(val)) - optval = 1; - - if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) { - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - return val; -} - -/* - * call-seq: - * gdbm.syncmode = boolean -> boolean - * - * Turns the database's synchronization mode on or off. If the synchronization - * mode is turned on, the database's in-memory state will be synchronized to - * disk after every database modification operation. If the synchronization - * mode is turned off, GDBM does not wait for writes to be flushed to the disk - * before continuing. - * - * This option is only available for gdbm >= 1.8 where syncmode is turned off - * by default. See also: #fastmode= - */ -static VALUE -fgdbm_set_syncmode(VALUE obj, VALUE val) -{ -#if !defined(GDBM_SYNCMODE) - fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue); - return val; -#else - struct dbmdata *dbmp; - GDBM_FILE dbm; - int optval; - - GetDBM2(obj, dbmp, dbm); - optval = 0; - if (RTEST(val)) - optval = 1; - - if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) { - rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno)); - } - return val; -#endif -} - -/* - * call-seq: - * gdbm.to_hash -> hash - * - * Returns a hash of all key-value pairs contained in the database. - */ -static VALUE -fgdbm_to_hash(VALUE obj) -{ - struct dbmdata *dbmp; - GDBM_FILE dbm; - VALUE keystr, hash; - - GetDBM2(obj, dbmp, dbm); - hash = rb_hash_new(); - for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr); - keystr = rb_gdbm_nextkey(dbm, keystr)) { - - rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr)); - } - - return hash; -} - -/* - * call-seq: - * gdbm.reject { |key, value| block } -> hash - * - * Returns a hash copy of _gdbm_ where all key-value pairs from _gdbm_ for - * which _block_ evaluates to true are removed. See also: #delete_if - */ -static VALUE -fgdbm_reject(VALUE obj) -{ - return rb_hash_delete_if(fgdbm_to_hash(obj)); -} - -void -Init_gdbm(void) -{ - rb_cGDBM = rb_define_class("GDBM", rb_cObject); - rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError); - rb_eGDBMFatalError = rb_define_class("GDBMFatalError", rb_eException); - rb_include_module(rb_cGDBM, rb_mEnumerable); - - rb_define_alloc_func(rb_cGDBM, fgdbm_s_alloc); - rb_define_singleton_method(rb_cGDBM, "open", fgdbm_s_open, -1); - - rb_define_method(rb_cGDBM, "initialize", fgdbm_initialize, -1); - rb_define_method(rb_cGDBM, "close", fgdbm_close, 0); - rb_define_method(rb_cGDBM, "closed?", fgdbm_closed, 0); - rb_define_method(rb_cGDBM, "[]", fgdbm_aref, 1); - rb_define_method(rb_cGDBM, "fetch", fgdbm_fetch_m, -1); - rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2); - rb_define_method(rb_cGDBM, "store", fgdbm_store, 2); - rb_define_method(rb_cGDBM, "index", fgdbm_index, 1); - rb_define_method(rb_cGDBM, "key", fgdbm_key, 1); - rb_define_method(rb_cGDBM, "select", fgdbm_select, 0); - rb_define_method(rb_cGDBM, "values_at", fgdbm_values_at, -1); - rb_define_method(rb_cGDBM, "length", fgdbm_length, 0); - rb_define_method(rb_cGDBM, "size", fgdbm_length, 0); - rb_define_method(rb_cGDBM, "empty?", fgdbm_empty_p, 0); - rb_define_method(rb_cGDBM, "each", fgdbm_each_pair, 0); - rb_define_method(rb_cGDBM, "each_value", fgdbm_each_value, 0); - rb_define_method(rb_cGDBM, "each_key", fgdbm_each_key, 0); - rb_define_method(rb_cGDBM, "each_pair", fgdbm_each_pair, 0); - rb_define_method(rb_cGDBM, "keys", fgdbm_keys, 0); - rb_define_method(rb_cGDBM, "values", fgdbm_values, 0); - rb_define_method(rb_cGDBM, "shift", fgdbm_shift, 0); - rb_define_method(rb_cGDBM, "delete", fgdbm_delete, 1); - rb_define_method(rb_cGDBM, "delete_if", fgdbm_delete_if, 0); - rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0); - rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0); - rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0); - rb_define_method(rb_cGDBM, "invert", fgdbm_invert, 0); - rb_define_method(rb_cGDBM, "update", fgdbm_update, 1); - rb_define_method(rb_cGDBM, "replace", fgdbm_replace, 1); - rb_define_method(rb_cGDBM, "reorganize", fgdbm_reorganize, 0); - rb_define_method(rb_cGDBM, "sync", fgdbm_sync, 0); - /* rb_define_method(rb_cGDBM, "setopt", fgdbm_setopt, 2); */ - rb_define_method(rb_cGDBM, "cachesize=", fgdbm_set_cachesize, 1); - rb_define_method(rb_cGDBM, "fastmode=", fgdbm_set_fastmode, 1); - rb_define_method(rb_cGDBM, "syncmode=", fgdbm_set_syncmode, 1); - - rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1); - rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1); - rb_define_method(rb_cGDBM, "member?", fgdbm_has_key, 1); - rb_define_method(rb_cGDBM, "has_value?", fgdbm_has_value, 1); - rb_define_method(rb_cGDBM, "key?", fgdbm_has_key, 1); - rb_define_method(rb_cGDBM, "value?", fgdbm_has_value, 1); - - rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0); - rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0); - - /* flag for #new and #open: open database as a reader */ - rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER|RUBY_GDBM_RW_BIT)); - /* flag for #new and #open: open database as a writer */ - rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER|RUBY_GDBM_RW_BIT)); - /* flag for #new and #open: open database as a writer; if the database does not exist, create a new one */ - rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT|RUBY_GDBM_RW_BIT)); - /* flag for #new and #open: open database as a writer; overwrite any existing databases */ - rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB|RUBY_GDBM_RW_BIT)); - - /* flag for #new and #open. this flag is obsolete for gdbm >= 1.8 */ - rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST)); - /* this flag is obsolete in gdbm 1.8. - On gdbm 1.8, fast mode is default behavior. */ - - /* gdbm version 1.8 specific */ -#if defined(GDBM_SYNC) - /* flag for #new and #open. only for gdbm >= 1.8 */ - rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC)); -#endif -#if defined(GDBM_NOLOCK) - /* flag for #new and #open */ - rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK)); -#endif - /* version of the gdbm library*/ - rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version)); -} diff --git a/ruby/ext/gdbm/gdbm.gemspec b/ruby/ext/gdbm/gdbm.gemspec deleted file mode 100644 index da074b018..000000000 --- a/ruby/ext/gdbm/gdbm.gemspec +++ /dev/null @@ -1,21 +0,0 @@ -# coding: utf-8 -# frozen_string_literal: true - -Gem::Specification.new do |spec| - spec.name = "gdbm" - spec.version = "2.1.0" - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = "Ruby extension for GNU dbm." - spec.description = "Ruby extension for GNU dbm." - spec.homepage = "https://github.com/ruby/gdbm" - spec.license = "BSD-2-Clause" - - spec.files = ["ext/gdbm/extconf.rb", "ext/gdbm/gdbm.c"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - spec.extensions = ["ext/gdbm/extconf.rb"] - spec.required_ruby_version = ">= 2.3.0" -end diff --git a/ruby/ext/io/console/console.c b/ruby/ext/io/console/console.c index 9baad2bf1..4ec24178c 100644 --- a/ruby/ext/io/console/console.c +++ b/ruby/ext/io/console/console.c @@ -1,4 +1,4 @@ -/* -*- c-file-style: "ruby" -*- */ +/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */ /* * console IO module */ @@ -77,10 +77,23 @@ getattr(int fd, conmode *t) static ID id_getc, id_console, id_close, id_min, id_time, id_intr; #if ENABLE_IO_GETPASS -static ID id_gets; +static ID id_gets, id_chomp_bang; #endif +#if defined HAVE_RUBY_FIBER_SCHEDULER_H +# include "ruby/fiber/scheduler.h" +#elif defined HAVE_RB_SCHEDULER_TIMEOUT +extern VALUE rb_scheduler_timeout(struct timeval *timeout); +# define rb_fiber_scheduler_make_timeout rb_scheduler_timeout +#endif + +#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv) + #ifndef HAVE_RB_F_SEND +#ifndef RB_PASS_CALLED_KEYWORDS +# define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv) +#endif + static ID id___send__; static VALUE @@ -95,7 +108,7 @@ rb_f_send(int argc, VALUE *argv, VALUE recv) else { vid = id___send__; } - return rb_funcallv(recv, vid, argc, argv); + return rb_funcallv_kw(recv, vid, argc, argv, RB_PASS_CALLED_KEYWORDS); } #endif @@ -410,9 +423,9 @@ console_set_raw(int argc, VALUE *argv, VALUE io) GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!getattr(fd, &t)) rb_sys_fail(0); + if (!getattr(fd, &t)) sys_fail_fptr(fptr); set_rawmode(&t, optp); - if (!setattr(fd, &t)) rb_sys_fail(0); + if (!setattr(fd, &t)) sys_fail_fptr(fptr); return io; } @@ -453,9 +466,9 @@ console_set_cooked(VALUE io) GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!getattr(fd, &t)) rb_sys_fail(0); + if (!getattr(fd, &t)) sys_fail_fptr(fptr); set_cookedmode(&t, NULL); - if (!setattr(fd, &t)) rb_sys_fail(0); + if (!setattr(fd, &t)) sys_fail_fptr(fptr); return io; } @@ -508,28 +521,50 @@ console_getch(int argc, VALUE *argv, VALUE io) rb_io_t *fptr; VALUE str; wint_t c; - int w, len; + int len; char buf[8]; wint_t wbuf[2]; +# ifndef HAVE_RB_IO_WAIT struct timeval *to = NULL, tv; +# else + VALUE timeout = Qnil; +# endif GetOpenFile(io, fptr); if (optp) { if (optp->vtime) { +# ifndef HAVE_RB_IO_WAIT to = &tv; +# else + struct timeval tv; +# endif tv.tv_sec = optp->vtime / 10; tv.tv_usec = (optp->vtime % 10) * 100000; +# ifdef HAVE_RB_IO_WAIT + timeout = rb_fiber_scheduler_make_timeout(&tv); +# endif } - if (optp->vmin != 1) { - rb_warning("min option ignored"); + switch (optp->vmin) { + case 1: /* default */ + break; + case 0: /* return nil when timed out */ + if (optp->vtime) break; + /* fallthru */ + default: + rb_warning("min option larger than 1 ignored"); } if (optp->intr) { - w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to); +# ifndef HAVE_RB_IO_WAIT + int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to); if (w < 0) rb_eof_error(); if (!(w & RB_WAITFD_IN)) return Qnil; +# else + VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout); + if (!RTEST(result)) return Qnil; +# endif } - else { - rb_warning("vtime option ignored if intr flag is unset"); + else if (optp->vtime) { + rb_warning("Non-zero vtime option ignored if intr flag is unset"); } } len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0); @@ -590,12 +625,12 @@ console_set_echo(VALUE io, VALUE f) GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!getattr(fd, &t)) rb_sys_fail(0); + if (!getattr(fd, &t)) sys_fail_fptr(fptr); if (RTEST(f)) set_echo(&t, NULL); else set_noecho(&t, NULL); - if (!setattr(fd, &t)) rb_sys_fail(0); + if (!setattr(fd, &t)) sys_fail_fptr(fptr); return io; } @@ -616,7 +651,7 @@ console_echo_p(VALUE io) GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!getattr(fd, &t)) rb_sys_fail(0); + if (!getattr(fd, &t)) sys_fail_fptr(fptr); return echo_p(&t) ? Qtrue : Qfalse; } @@ -700,7 +735,7 @@ console_conmode_get(VALUE io) GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!getattr(fd, &t)) rb_sys_fail(0); + if (!getattr(fd, &t)) sys_fail_fptr(fptr); return conmode_new(cConmode, &t); } @@ -724,7 +759,7 @@ console_conmode_set(VALUE io, VALUE mode) r = *t; GetOpenFile(io, fptr); fd = GetReadFD(fptr); - if (!setattr(fd, &r)) rb_sys_fail(0); + if (!setattr(fd, &r)) sys_fail_fptr(fptr); return mode; } @@ -766,7 +801,7 @@ console_winsize(VALUE io) GetOpenFile(io, fptr); fd = GetWriteFD(fptr); - if (!getwinsize(fd, &ws)) rb_sys_fail(0); + if (!getwinsize(fd, &ws)) sys_fail_fptr(fptr); return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws))); } @@ -813,7 +848,7 @@ console_set_winsize(VALUE io, VALUE size) SET(xpixel); SET(ypixel); #undef SET - if (!setwinsize(fd, &ws)) rb_sys_fail(0); + if (!setwinsize(fd, &ws)) sys_fail_fptr(fptr); #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(fd); #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) @@ -888,7 +923,7 @@ console_iflush(VALUE io) GetOpenFile(io, fptr); fd = GetReadFD(fptr); #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H - if (tcflush(fd, TCIFLUSH)) rb_sys_fail(0); + if (tcflush(fd, TCIFLUSH)) sys_fail_fptr(fptr); #endif (void)fd; return io; @@ -911,7 +946,7 @@ console_oflush(VALUE io) GetOpenFile(io, fptr); fd = GetWriteFD(fptr); #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H - if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0); + if (tcflush(fd, TCOFLUSH)) sys_fail_fptr(fptr); #endif (void)fd; return io; @@ -938,11 +973,11 @@ console_ioflush(VALUE io) fd1 = GetReadFD(fptr); fd2 = GetWriteFD(fptr); if (fd2 != -1 && fd1 != fd2) { - if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0); - if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0); + if (tcflush(fd1, TCIFLUSH)) sys_fail_fptr(fptr); + if (tcflush(fd2, TCOFLUSH)) sys_fail_fptr(fptr); } else { - if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0); + if (tcflush(fd1, TCIOFLUSH)) sys_fail_fptr(fptr); } #endif return io; @@ -961,7 +996,7 @@ console_beep(VALUE io) MessageBeep(0); #else if (write(fd, "\a", 1) < 0) - rb_sys_fail(0); + sys_fail_fptr(fptr); #endif return io; } @@ -1195,8 +1230,8 @@ console_key_pressed_p(VALUE io, VALUE k) } #else struct query_args { - const char *qstr; - int opt; + char qstr[6]; + unsigned char opt; }; static int @@ -1534,7 +1569,7 @@ static VALUE str_chomp(VALUE str) { if (!NIL_P(str)) { - str = rb_funcallv(str, rb_intern("chomp!"), 0, 0); + rb_funcallv(str, id_chomp_bang, 0, 0); } return str; } @@ -1546,6 +1581,10 @@ str_chomp(VALUE str) * Reads and returns a line without echo back. * Prints +prompt+ unless it is +nil+. * + * The newline character that terminates the + * read line is removed from the returned string, + * see String#chomp!. + * * You must require 'io/console' to use this method. */ static VALUE @@ -1590,6 +1629,7 @@ Init_console(void) id_getc = rb_intern("getc"); #if ENABLE_IO_GETPASS id_gets = rb_intern("gets"); + id_chomp_bang = rb_intern("chomp!"); #endif id_console = rb_intern("console"); id_close = rb_intern("close"); diff --git a/ruby/ext/io/console/depend b/ruby/ext/io/console/depend index 9c8f9cd22..e6014dcc5 100644 --- a/ruby/ext/io/console/depend +++ b/ruby/ext/io/console/depend @@ -4,9 +4,166 @@ console.o: $(arch_hdrdir)/ruby/config.h console.o: $(hdrdir)/ruby.h console.o: $(hdrdir)/ruby/assert.h console.o: $(hdrdir)/ruby/backward.h +console.o: $(hdrdir)/ruby/backward/2/assume.h +console.o: $(hdrdir)/ruby/backward/2/attributes.h +console.o: $(hdrdir)/ruby/backward/2/bool.h +console.o: $(hdrdir)/ruby/backward/2/inttypes.h +console.o: $(hdrdir)/ruby/backward/2/limits.h +console.o: $(hdrdir)/ruby/backward/2/long_long.h +console.o: $(hdrdir)/ruby/backward/2/stdalign.h +console.o: $(hdrdir)/ruby/backward/2/stdarg.h console.o: $(hdrdir)/ruby/defines.h console.o: $(hdrdir)/ruby/encoding.h +console.o: $(hdrdir)/ruby/fiber/scheduler.h console.o: $(hdrdir)/ruby/intern.h +console.o: $(hdrdir)/ruby/internal/anyargs.h +console.o: $(hdrdir)/ruby/internal/arithmetic.h +console.o: $(hdrdir)/ruby/internal/arithmetic/char.h +console.o: $(hdrdir)/ruby/internal/arithmetic/double.h +console.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +console.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/int.h +console.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/long.h +console.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +console.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/short.h +console.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +console.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +console.o: $(hdrdir)/ruby/internal/assume.h +console.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +console.o: $(hdrdir)/ruby/internal/attr/artificial.h +console.o: $(hdrdir)/ruby/internal/attr/cold.h +console.o: $(hdrdir)/ruby/internal/attr/const.h +console.o: $(hdrdir)/ruby/internal/attr/constexpr.h +console.o: $(hdrdir)/ruby/internal/attr/deprecated.h +console.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +console.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +console.o: $(hdrdir)/ruby/internal/attr/error.h +console.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +console.o: $(hdrdir)/ruby/internal/attr/forceinline.h +console.o: $(hdrdir)/ruby/internal/attr/format.h +console.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +console.o: $(hdrdir)/ruby/internal/attr/noalias.h +console.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +console.o: $(hdrdir)/ruby/internal/attr/noexcept.h +console.o: $(hdrdir)/ruby/internal/attr/noinline.h +console.o: $(hdrdir)/ruby/internal/attr/nonnull.h +console.o: $(hdrdir)/ruby/internal/attr/noreturn.h +console.o: $(hdrdir)/ruby/internal/attr/pure.h +console.o: $(hdrdir)/ruby/internal/attr/restrict.h +console.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +console.o: $(hdrdir)/ruby/internal/attr/warning.h +console.o: $(hdrdir)/ruby/internal/attr/weakref.h +console.o: $(hdrdir)/ruby/internal/cast.h +console.o: $(hdrdir)/ruby/internal/compiler_is.h +console.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +console.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +console.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +console.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +console.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +console.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +console.o: $(hdrdir)/ruby/internal/compiler_since.h +console.o: $(hdrdir)/ruby/internal/config.h +console.o: $(hdrdir)/ruby/internal/constant_p.h +console.o: $(hdrdir)/ruby/internal/core.h +console.o: $(hdrdir)/ruby/internal/core/rarray.h +console.o: $(hdrdir)/ruby/internal/core/rbasic.h +console.o: $(hdrdir)/ruby/internal/core/rbignum.h +console.o: $(hdrdir)/ruby/internal/core/rclass.h +console.o: $(hdrdir)/ruby/internal/core/rdata.h +console.o: $(hdrdir)/ruby/internal/core/rfile.h +console.o: $(hdrdir)/ruby/internal/core/rhash.h +console.o: $(hdrdir)/ruby/internal/core/robject.h +console.o: $(hdrdir)/ruby/internal/core/rregexp.h +console.o: $(hdrdir)/ruby/internal/core/rstring.h +console.o: $(hdrdir)/ruby/internal/core/rstruct.h +console.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +console.o: $(hdrdir)/ruby/internal/ctype.h +console.o: $(hdrdir)/ruby/internal/dllexport.h +console.o: $(hdrdir)/ruby/internal/dosish.h +console.o: $(hdrdir)/ruby/internal/encoding/coderange.h +console.o: $(hdrdir)/ruby/internal/encoding/ctype.h +console.o: $(hdrdir)/ruby/internal/encoding/encoding.h +console.o: $(hdrdir)/ruby/internal/encoding/pathname.h +console.o: $(hdrdir)/ruby/internal/encoding/re.h +console.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +console.o: $(hdrdir)/ruby/internal/encoding/string.h +console.o: $(hdrdir)/ruby/internal/encoding/symbol.h +console.o: $(hdrdir)/ruby/internal/encoding/transcode.h +console.o: $(hdrdir)/ruby/internal/error.h +console.o: $(hdrdir)/ruby/internal/eval.h +console.o: $(hdrdir)/ruby/internal/event.h +console.o: $(hdrdir)/ruby/internal/fl_type.h +console.o: $(hdrdir)/ruby/internal/gc.h +console.o: $(hdrdir)/ruby/internal/glob.h +console.o: $(hdrdir)/ruby/internal/globals.h +console.o: $(hdrdir)/ruby/internal/has/attribute.h +console.o: $(hdrdir)/ruby/internal/has/builtin.h +console.o: $(hdrdir)/ruby/internal/has/c_attribute.h +console.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +console.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +console.o: $(hdrdir)/ruby/internal/has/extension.h +console.o: $(hdrdir)/ruby/internal/has/feature.h +console.o: $(hdrdir)/ruby/internal/has/warning.h +console.o: $(hdrdir)/ruby/internal/intern/array.h +console.o: $(hdrdir)/ruby/internal/intern/bignum.h +console.o: $(hdrdir)/ruby/internal/intern/class.h +console.o: $(hdrdir)/ruby/internal/intern/compar.h +console.o: $(hdrdir)/ruby/internal/intern/complex.h +console.o: $(hdrdir)/ruby/internal/intern/cont.h +console.o: $(hdrdir)/ruby/internal/intern/dir.h +console.o: $(hdrdir)/ruby/internal/intern/enum.h +console.o: $(hdrdir)/ruby/internal/intern/enumerator.h +console.o: $(hdrdir)/ruby/internal/intern/error.h +console.o: $(hdrdir)/ruby/internal/intern/eval.h +console.o: $(hdrdir)/ruby/internal/intern/file.h +console.o: $(hdrdir)/ruby/internal/intern/gc.h +console.o: $(hdrdir)/ruby/internal/intern/hash.h +console.o: $(hdrdir)/ruby/internal/intern/io.h +console.o: $(hdrdir)/ruby/internal/intern/load.h +console.o: $(hdrdir)/ruby/internal/intern/marshal.h +console.o: $(hdrdir)/ruby/internal/intern/numeric.h +console.o: $(hdrdir)/ruby/internal/intern/object.h +console.o: $(hdrdir)/ruby/internal/intern/parse.h +console.o: $(hdrdir)/ruby/internal/intern/proc.h +console.o: $(hdrdir)/ruby/internal/intern/process.h +console.o: $(hdrdir)/ruby/internal/intern/random.h +console.o: $(hdrdir)/ruby/internal/intern/range.h +console.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +console.o: $(hdrdir)/ruby/internal/intern/sprintf.h +console.o: $(hdrdir)/ruby/internal/intern/string.h +console.o: $(hdrdir)/ruby/internal/intern/struct.h +console.o: $(hdrdir)/ruby/internal/intern/thread.h +console.o: $(hdrdir)/ruby/internal/intern/time.h +console.o: $(hdrdir)/ruby/internal/intern/variable.h +console.o: $(hdrdir)/ruby/internal/intern/vm.h +console.o: $(hdrdir)/ruby/internal/interpreter.h +console.o: $(hdrdir)/ruby/internal/iterator.h +console.o: $(hdrdir)/ruby/internal/memory.h +console.o: $(hdrdir)/ruby/internal/method.h +console.o: $(hdrdir)/ruby/internal/module.h +console.o: $(hdrdir)/ruby/internal/newobj.h +console.o: $(hdrdir)/ruby/internal/rgengc.h +console.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +console.o: $(hdrdir)/ruby/internal/value.h +console.o: $(hdrdir)/ruby/internal/value_type.h +console.o: $(hdrdir)/ruby/internal/variable.h +console.o: $(hdrdir)/ruby/internal/warning_push.h +console.o: $(hdrdir)/ruby/internal/xmalloc.h console.o: $(hdrdir)/ruby/io.h console.o: $(hdrdir)/ruby/missing.h console.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/io/console/extconf.rb b/ruby/ext/io/console/extconf.rb index 3d7e75e2a..e8c5923b1 100644 --- a/ruby/ext/io/console/extconf.rb +++ b/ruby/ext/io/console/extconf.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require 'mkmf' -ok = true if RUBY_ENGINE == "ruby" +ok = true if RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby" hdr = nil case when macro_defined?("_WIN32", "") @@ -24,6 +24,11 @@ # rb_funcallv: 2.1.0 # RARRAY_CONST_PTR: 2.1.0 # rb_sym2str: 2.2.0 + if have_macro("HAVE_RUBY_FIBER_SCHEDULER_H") + $defs << "-D""HAVE_RB_IO_WAIT=1" + elsif have_func("rb_scheduler_timeout") # 3.0 + have_func("rb_io_wait") + end $defs << "-D""ENABLE_IO_GETPASS=1" create_makefile("io/console") {|conf| conf << "\n""VK_HEADER = #{vk_header}\n" diff --git a/ruby/ext/io/console/io-console.gemspec b/ruby/ext/io/console/io-console.gemspec index 814bd4ef7..aa57f8ac5 100644 --- a/ruby/ext/io/console/io-console.gemspec +++ b/ruby/ext/io/console/io-console.gemspec @@ -1,15 +1,13 @@ # -*- ruby -*- -_VERSION = "0.5.6" -date = %w$Date:: $[1] +_VERSION = "0.5.11" Gem::Specification.new do |s| s.name = "io-console" s.version = _VERSION - s.date = date s.summary = "Console interface" s.email = "nobu@ruby-lang.org" s.description = "add console capabilities to IO instances." - s.required_ruby_version = ">= 2.4.0" + s.required_ruby_version = ">= 2.6.0" s.homepage = "https://github.com/ruby/io-console" s.metadata["source_code_url"] = s.homepage s.authors = ["Nobu Nakada"] @@ -23,5 +21,21 @@ Gem::Specification.new do |s| lib/io/console/size.rb ] s.extensions = %w[ext/io/console/extconf.rb] - s.license = "BSD-2-Clause" + + if Gem::Platform === s.platform and s.platform =~ 'java' + s.files.delete_if {|f| f.start_with?("ext/")} + s.extensions.clear + 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 + ]) + end + + s.licenses = ["Ruby", "BSD-2-Clause"] end diff --git a/ruby/ext/io/nonblock/depend b/ruby/ext/io/nonblock/depend index bea4a15e2..664c262e3 100644 --- a/ruby/ext/io/nonblock/depend +++ b/ruby/ext/io/nonblock/depend @@ -4,9 +4,165 @@ nonblock.o: $(arch_hdrdir)/ruby/config.h nonblock.o: $(hdrdir)/ruby.h nonblock.o: $(hdrdir)/ruby/assert.h nonblock.o: $(hdrdir)/ruby/backward.h +nonblock.o: $(hdrdir)/ruby/backward/2/assume.h +nonblock.o: $(hdrdir)/ruby/backward/2/attributes.h +nonblock.o: $(hdrdir)/ruby/backward/2/bool.h +nonblock.o: $(hdrdir)/ruby/backward/2/inttypes.h +nonblock.o: $(hdrdir)/ruby/backward/2/limits.h +nonblock.o: $(hdrdir)/ruby/backward/2/long_long.h +nonblock.o: $(hdrdir)/ruby/backward/2/stdalign.h +nonblock.o: $(hdrdir)/ruby/backward/2/stdarg.h nonblock.o: $(hdrdir)/ruby/defines.h nonblock.o: $(hdrdir)/ruby/encoding.h nonblock.o: $(hdrdir)/ruby/intern.h +nonblock.o: $(hdrdir)/ruby/internal/anyargs.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/char.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/double.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/int.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/short.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +nonblock.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +nonblock.o: $(hdrdir)/ruby/internal/assume.h +nonblock.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +nonblock.o: $(hdrdir)/ruby/internal/attr/artificial.h +nonblock.o: $(hdrdir)/ruby/internal/attr/cold.h +nonblock.o: $(hdrdir)/ruby/internal/attr/const.h +nonblock.o: $(hdrdir)/ruby/internal/attr/constexpr.h +nonblock.o: $(hdrdir)/ruby/internal/attr/deprecated.h +nonblock.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +nonblock.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +nonblock.o: $(hdrdir)/ruby/internal/attr/error.h +nonblock.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +nonblock.o: $(hdrdir)/ruby/internal/attr/forceinline.h +nonblock.o: $(hdrdir)/ruby/internal/attr/format.h +nonblock.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +nonblock.o: $(hdrdir)/ruby/internal/attr/noalias.h +nonblock.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +nonblock.o: $(hdrdir)/ruby/internal/attr/noexcept.h +nonblock.o: $(hdrdir)/ruby/internal/attr/noinline.h +nonblock.o: $(hdrdir)/ruby/internal/attr/nonnull.h +nonblock.o: $(hdrdir)/ruby/internal/attr/noreturn.h +nonblock.o: $(hdrdir)/ruby/internal/attr/pure.h +nonblock.o: $(hdrdir)/ruby/internal/attr/restrict.h +nonblock.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +nonblock.o: $(hdrdir)/ruby/internal/attr/warning.h +nonblock.o: $(hdrdir)/ruby/internal/attr/weakref.h +nonblock.o: $(hdrdir)/ruby/internal/cast.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +nonblock.o: $(hdrdir)/ruby/internal/compiler_since.h +nonblock.o: $(hdrdir)/ruby/internal/config.h +nonblock.o: $(hdrdir)/ruby/internal/constant_p.h +nonblock.o: $(hdrdir)/ruby/internal/core.h +nonblock.o: $(hdrdir)/ruby/internal/core/rarray.h +nonblock.o: $(hdrdir)/ruby/internal/core/rbasic.h +nonblock.o: $(hdrdir)/ruby/internal/core/rbignum.h +nonblock.o: $(hdrdir)/ruby/internal/core/rclass.h +nonblock.o: $(hdrdir)/ruby/internal/core/rdata.h +nonblock.o: $(hdrdir)/ruby/internal/core/rfile.h +nonblock.o: $(hdrdir)/ruby/internal/core/rhash.h +nonblock.o: $(hdrdir)/ruby/internal/core/robject.h +nonblock.o: $(hdrdir)/ruby/internal/core/rregexp.h +nonblock.o: $(hdrdir)/ruby/internal/core/rstring.h +nonblock.o: $(hdrdir)/ruby/internal/core/rstruct.h +nonblock.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +nonblock.o: $(hdrdir)/ruby/internal/ctype.h +nonblock.o: $(hdrdir)/ruby/internal/dllexport.h +nonblock.o: $(hdrdir)/ruby/internal/dosish.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/coderange.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/ctype.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/encoding.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/pathname.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/re.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/string.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/symbol.h +nonblock.o: $(hdrdir)/ruby/internal/encoding/transcode.h +nonblock.o: $(hdrdir)/ruby/internal/error.h +nonblock.o: $(hdrdir)/ruby/internal/eval.h +nonblock.o: $(hdrdir)/ruby/internal/event.h +nonblock.o: $(hdrdir)/ruby/internal/fl_type.h +nonblock.o: $(hdrdir)/ruby/internal/gc.h +nonblock.o: $(hdrdir)/ruby/internal/glob.h +nonblock.o: $(hdrdir)/ruby/internal/globals.h +nonblock.o: $(hdrdir)/ruby/internal/has/attribute.h +nonblock.o: $(hdrdir)/ruby/internal/has/builtin.h +nonblock.o: $(hdrdir)/ruby/internal/has/c_attribute.h +nonblock.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +nonblock.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +nonblock.o: $(hdrdir)/ruby/internal/has/extension.h +nonblock.o: $(hdrdir)/ruby/internal/has/feature.h +nonblock.o: $(hdrdir)/ruby/internal/has/warning.h +nonblock.o: $(hdrdir)/ruby/internal/intern/array.h +nonblock.o: $(hdrdir)/ruby/internal/intern/bignum.h +nonblock.o: $(hdrdir)/ruby/internal/intern/class.h +nonblock.o: $(hdrdir)/ruby/internal/intern/compar.h +nonblock.o: $(hdrdir)/ruby/internal/intern/complex.h +nonblock.o: $(hdrdir)/ruby/internal/intern/cont.h +nonblock.o: $(hdrdir)/ruby/internal/intern/dir.h +nonblock.o: $(hdrdir)/ruby/internal/intern/enum.h +nonblock.o: $(hdrdir)/ruby/internal/intern/enumerator.h +nonblock.o: $(hdrdir)/ruby/internal/intern/error.h +nonblock.o: $(hdrdir)/ruby/internal/intern/eval.h +nonblock.o: $(hdrdir)/ruby/internal/intern/file.h +nonblock.o: $(hdrdir)/ruby/internal/intern/gc.h +nonblock.o: $(hdrdir)/ruby/internal/intern/hash.h +nonblock.o: $(hdrdir)/ruby/internal/intern/io.h +nonblock.o: $(hdrdir)/ruby/internal/intern/load.h +nonblock.o: $(hdrdir)/ruby/internal/intern/marshal.h +nonblock.o: $(hdrdir)/ruby/internal/intern/numeric.h +nonblock.o: $(hdrdir)/ruby/internal/intern/object.h +nonblock.o: $(hdrdir)/ruby/internal/intern/parse.h +nonblock.o: $(hdrdir)/ruby/internal/intern/proc.h +nonblock.o: $(hdrdir)/ruby/internal/intern/process.h +nonblock.o: $(hdrdir)/ruby/internal/intern/random.h +nonblock.o: $(hdrdir)/ruby/internal/intern/range.h +nonblock.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +nonblock.o: $(hdrdir)/ruby/internal/intern/sprintf.h +nonblock.o: $(hdrdir)/ruby/internal/intern/string.h +nonblock.o: $(hdrdir)/ruby/internal/intern/struct.h +nonblock.o: $(hdrdir)/ruby/internal/intern/thread.h +nonblock.o: $(hdrdir)/ruby/internal/intern/time.h +nonblock.o: $(hdrdir)/ruby/internal/intern/variable.h +nonblock.o: $(hdrdir)/ruby/internal/intern/vm.h +nonblock.o: $(hdrdir)/ruby/internal/interpreter.h +nonblock.o: $(hdrdir)/ruby/internal/iterator.h +nonblock.o: $(hdrdir)/ruby/internal/memory.h +nonblock.o: $(hdrdir)/ruby/internal/method.h +nonblock.o: $(hdrdir)/ruby/internal/module.h +nonblock.o: $(hdrdir)/ruby/internal/newobj.h +nonblock.o: $(hdrdir)/ruby/internal/rgengc.h +nonblock.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +nonblock.o: $(hdrdir)/ruby/internal/value.h +nonblock.o: $(hdrdir)/ruby/internal/value_type.h +nonblock.o: $(hdrdir)/ruby/internal/variable.h +nonblock.o: $(hdrdir)/ruby/internal/warning_push.h +nonblock.o: $(hdrdir)/ruby/internal/xmalloc.h nonblock.o: $(hdrdir)/ruby/io.h nonblock.o: $(hdrdir)/ruby/missing.h nonblock.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/io/nonblock/io-nonblock.gemspec b/ruby/ext/io/nonblock/io-nonblock.gemspec new file mode 100644 index 000000000..34d736650 --- /dev/null +++ b/ruby/ext/io/nonblock/io-nonblock.gemspec @@ -0,0 +1,25 @@ +Gem::Specification.new do |spec| + spec.name = "io-nonblock" + spec.version = "0.1.0" + spec.authors = ["Nobu Nakada"] + spec.email = ["nobu@ruby-lang.org"] + + spec.summary = %q{Enables non-blocking mode with IO class} + 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.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + + spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do + %x[git ls-files -z].split("\x0").reject do |f| + f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)}) + end + end + spec.extensions = %w[ext/io/nonblock/extconf.rb] + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] +end diff --git a/ruby/ext/io/wait/depend b/ruby/ext/io/wait/depend index bbf1266ab..0426a6a1e 100644 --- a/ruby/ext/io/wait/depend +++ b/ruby/ext/io/wait/depend @@ -1,12 +1,169 @@ # 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 wait.o: $(hdrdir)/ruby/assert.h wait.o: $(hdrdir)/ruby/backward.h +wait.o: $(hdrdir)/ruby/backward/2/assume.h +wait.o: $(hdrdir)/ruby/backward/2/attributes.h +wait.o: $(hdrdir)/ruby/backward/2/bool.h +wait.o: $(hdrdir)/ruby/backward/2/inttypes.h +wait.o: $(hdrdir)/ruby/backward/2/limits.h +wait.o: $(hdrdir)/ruby/backward/2/long_long.h +wait.o: $(hdrdir)/ruby/backward/2/stdalign.h +wait.o: $(hdrdir)/ruby/backward/2/stdarg.h wait.o: $(hdrdir)/ruby/defines.h wait.o: $(hdrdir)/ruby/encoding.h wait.o: $(hdrdir)/ruby/intern.h +wait.o: $(hdrdir)/ruby/internal/anyargs.h +wait.o: $(hdrdir)/ruby/internal/arithmetic.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/double.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/int.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/long.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/short.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +wait.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +wait.o: $(hdrdir)/ruby/internal/assume.h +wait.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +wait.o: $(hdrdir)/ruby/internal/attr/artificial.h +wait.o: $(hdrdir)/ruby/internal/attr/cold.h +wait.o: $(hdrdir)/ruby/internal/attr/const.h +wait.o: $(hdrdir)/ruby/internal/attr/constexpr.h +wait.o: $(hdrdir)/ruby/internal/attr/deprecated.h +wait.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +wait.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +wait.o: $(hdrdir)/ruby/internal/attr/error.h +wait.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +wait.o: $(hdrdir)/ruby/internal/attr/forceinline.h +wait.o: $(hdrdir)/ruby/internal/attr/format.h +wait.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +wait.o: $(hdrdir)/ruby/internal/attr/noalias.h +wait.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +wait.o: $(hdrdir)/ruby/internal/attr/noexcept.h +wait.o: $(hdrdir)/ruby/internal/attr/noinline.h +wait.o: $(hdrdir)/ruby/internal/attr/nonnull.h +wait.o: $(hdrdir)/ruby/internal/attr/noreturn.h +wait.o: $(hdrdir)/ruby/internal/attr/pure.h +wait.o: $(hdrdir)/ruby/internal/attr/restrict.h +wait.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +wait.o: $(hdrdir)/ruby/internal/attr/warning.h +wait.o: $(hdrdir)/ruby/internal/attr/weakref.h +wait.o: $(hdrdir)/ruby/internal/cast.h +wait.o: $(hdrdir)/ruby/internal/compiler_is.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +wait.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +wait.o: $(hdrdir)/ruby/internal/compiler_since.h +wait.o: $(hdrdir)/ruby/internal/config.h +wait.o: $(hdrdir)/ruby/internal/constant_p.h +wait.o: $(hdrdir)/ruby/internal/core.h +wait.o: $(hdrdir)/ruby/internal/core/rarray.h +wait.o: $(hdrdir)/ruby/internal/core/rbasic.h +wait.o: $(hdrdir)/ruby/internal/core/rbignum.h +wait.o: $(hdrdir)/ruby/internal/core/rclass.h +wait.o: $(hdrdir)/ruby/internal/core/rdata.h +wait.o: $(hdrdir)/ruby/internal/core/rfile.h +wait.o: $(hdrdir)/ruby/internal/core/rhash.h +wait.o: $(hdrdir)/ruby/internal/core/robject.h +wait.o: $(hdrdir)/ruby/internal/core/rregexp.h +wait.o: $(hdrdir)/ruby/internal/core/rstring.h +wait.o: $(hdrdir)/ruby/internal/core/rstruct.h +wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +wait.o: $(hdrdir)/ruby/internal/ctype.h +wait.o: $(hdrdir)/ruby/internal/dllexport.h +wait.o: $(hdrdir)/ruby/internal/dosish.h +wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h +wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h +wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h +wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h +wait.o: $(hdrdir)/ruby/internal/encoding/re.h +wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +wait.o: $(hdrdir)/ruby/internal/encoding/string.h +wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h +wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h +wait.o: $(hdrdir)/ruby/internal/error.h +wait.o: $(hdrdir)/ruby/internal/eval.h +wait.o: $(hdrdir)/ruby/internal/event.h +wait.o: $(hdrdir)/ruby/internal/fl_type.h +wait.o: $(hdrdir)/ruby/internal/gc.h +wait.o: $(hdrdir)/ruby/internal/glob.h +wait.o: $(hdrdir)/ruby/internal/globals.h +wait.o: $(hdrdir)/ruby/internal/has/attribute.h +wait.o: $(hdrdir)/ruby/internal/has/builtin.h +wait.o: $(hdrdir)/ruby/internal/has/c_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +wait.o: $(hdrdir)/ruby/internal/has/extension.h +wait.o: $(hdrdir)/ruby/internal/has/feature.h +wait.o: $(hdrdir)/ruby/internal/has/warning.h +wait.o: $(hdrdir)/ruby/internal/intern/array.h +wait.o: $(hdrdir)/ruby/internal/intern/bignum.h +wait.o: $(hdrdir)/ruby/internal/intern/class.h +wait.o: $(hdrdir)/ruby/internal/intern/compar.h +wait.o: $(hdrdir)/ruby/internal/intern/complex.h +wait.o: $(hdrdir)/ruby/internal/intern/cont.h +wait.o: $(hdrdir)/ruby/internal/intern/dir.h +wait.o: $(hdrdir)/ruby/internal/intern/enum.h +wait.o: $(hdrdir)/ruby/internal/intern/enumerator.h +wait.o: $(hdrdir)/ruby/internal/intern/error.h +wait.o: $(hdrdir)/ruby/internal/intern/eval.h +wait.o: $(hdrdir)/ruby/internal/intern/file.h +wait.o: $(hdrdir)/ruby/internal/intern/gc.h +wait.o: $(hdrdir)/ruby/internal/intern/hash.h +wait.o: $(hdrdir)/ruby/internal/intern/io.h +wait.o: $(hdrdir)/ruby/internal/intern/load.h +wait.o: $(hdrdir)/ruby/internal/intern/marshal.h +wait.o: $(hdrdir)/ruby/internal/intern/numeric.h +wait.o: $(hdrdir)/ruby/internal/intern/object.h +wait.o: $(hdrdir)/ruby/internal/intern/parse.h +wait.o: $(hdrdir)/ruby/internal/intern/proc.h +wait.o: $(hdrdir)/ruby/internal/intern/process.h +wait.o: $(hdrdir)/ruby/internal/intern/random.h +wait.o: $(hdrdir)/ruby/internal/intern/range.h +wait.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h +wait.o: $(hdrdir)/ruby/internal/intern/string.h +wait.o: $(hdrdir)/ruby/internal/intern/struct.h +wait.o: $(hdrdir)/ruby/internal/intern/thread.h +wait.o: $(hdrdir)/ruby/internal/intern/time.h +wait.o: $(hdrdir)/ruby/internal/intern/variable.h +wait.o: $(hdrdir)/ruby/internal/intern/vm.h +wait.o: $(hdrdir)/ruby/internal/interpreter.h +wait.o: $(hdrdir)/ruby/internal/iterator.h +wait.o: $(hdrdir)/ruby/internal/memory.h +wait.o: $(hdrdir)/ruby/internal/method.h +wait.o: $(hdrdir)/ruby/internal/module.h +wait.o: $(hdrdir)/ruby/internal/newobj.h +wait.o: $(hdrdir)/ruby/internal/rgengc.h +wait.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +wait.o: $(hdrdir)/ruby/internal/value.h +wait.o: $(hdrdir)/ruby/internal/value_type.h +wait.o: $(hdrdir)/ruby/internal/variable.h +wait.o: $(hdrdir)/ruby/internal/warning_push.h +wait.o: $(hdrdir)/ruby/internal/xmalloc.h wait.o: $(hdrdir)/ruby/io.h wait.o: $(hdrdir)/ruby/missing.h wait.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/io/wait/extconf.rb b/ruby/ext/io/wait/extconf.rb index b5d36c3fe..d20ff4553 100644 --- a/ruby/ext/io/wait/extconf.rb +++ b/ruby/ext/io/wait/extconf.rb @@ -2,6 +2,7 @@ require 'mkmf' target = "io/wait" +have_func("rb_io_wait") 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| diff --git a/ruby/ext/io/wait/io-wait.gemspec b/ruby/ext/io/wait/io-wait.gemspec new file mode 100644 index 000000000..ec7c05dd8 --- /dev/null +++ b/ruby/ext/io/wait/io-wait.gemspec @@ -0,0 +1,27 @@ +_VERSION = "0.2.1" + +Gem::Specification.new do |spec| + spec.name = "io-wait" + spec.version = _VERSION + spec.authors = ["Nobu Nakada"] + spec.email = ["nobu@ruby-lang.org"] + + spec.summary = %q{Waits until IO is readable or writable without blocking.} + 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(">= 2.6.0") + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + + spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do + `git ls-files -z`.split("\x0").reject do |f| + f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)}) + end + end + spec.extensions = %w[ext/io/wait/extconf.rb] + spec.bindir = "exe" + spec.executables = [] + spec.require_paths = ["lib"] +end diff --git a/ruby/ext/io/wait/wait.c b/ruby/ext/io/wait/wait.c index d846bba49..8f0d16e16 100644 --- a/ruby/ext/io/wait/wait.c +++ b/ruby/ext/io/wait/wait.c @@ -1,3 +1,4 @@ +/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */ /********************************************************************** io/wait.c - @@ -39,6 +40,7 @@ #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue) #endif +#ifndef HAVE_RB_IO_WAIT static VALUE io_ready_p _((VALUE io)); static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io)); static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io)); @@ -67,6 +69,7 @@ wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv) rb_io_check_closed(fptr); return (i & events); } +#endif /* * call-seq: @@ -93,34 +96,63 @@ io_nread(VALUE io) return INT2FIX(0); } +#ifdef HAVE_RB_IO_WAIT +static VALUE +io_wait_event(VALUE io, int event, VALUE timeout) +{ + VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout); + + if (!RB_TEST(result)) { + return Qnil; + } + + int mask = RB_NUM2INT(result); + + if (mask & event) { + return io; + } + else { + return Qfalse; + } +} +#endif + /* * call-seq: * io.ready? -> true or false * - * Returns true if input available without blocking, or false. + * Returns +true+ if input available without blocking, or +false+. */ static VALUE io_ready_p(VALUE io) { rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT struct timeval tv = {0, 0}; +#endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; + +#ifndef HAVE_RB_IO_WAIT if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv)) return Qtrue; +#else + if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0)))) + return Qtrue; +#endif return Qfalse; } /* * call-seq: - * io.wait_readable -> IO, true or nil - * io.wait_readable(timeout) -> IO, true or nil + * io.wait_readable -> true or false + * io.wait_readable(timeout) -> true or false * - * Waits until IO is readable without blocking and returns +self+, or - * +nil+ when times out. + * Waits until IO is readable and returns +true+, or + * +false+ when times out. * Returns +true+ immediately when buffered data is available. */ @@ -128,42 +160,91 @@ static VALUE io_wait_readable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; +#endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); + +#ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); +#endif if (rb_io_read_pending(fptr)) return Qtrue; + +#ifndef HAVE_RB_IO_WAIT if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) { return io; } return Qnil; +#else + rb_check_arity(argc, 0, 1); + VALUE timeout = (argc == 1 ? argv[0] : Qnil); + + return io_wait_event(io, RUBY_IO_READABLE, timeout); +#endif } /* * call-seq: - * io.wait_writable -> IO - * io.wait_writable(timeout) -> IO or nil + * io.wait_writable -> true or false + * io.wait_writable(timeout) -> true or false * - * Waits until IO is writable without blocking and returns +self+ or - * +nil+ when times out. + * Waits until IO is writable and returns +true+ or + * +false+ when times out. */ static VALUE io_wait_writable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; +#endif GetOpenFile(io, fptr); rb_io_check_writable(fptr); + +#ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) { return io; } return Qnil; +#else + rb_check_arity(argc, 0, 1); + VALUE timeout = (argc == 1 ? argv[0] : Qnil); + + return io_wait_event(io, RUBY_IO_WRITABLE, timeout); +#endif +} + +#ifdef HAVE_RB_IO_WAIT +/* + * call-seq: + * io.wait_priority -> true or false + * io.wait_priority(timeout) -> true or false + * + * Waits until IO is priority and returns +true+ or + * +false+ when times out. + */ +static VALUE +io_wait_priority(int argc, VALUE *argv, VALUE io) +{ + rb_io_t *fptr = NULL; + + RB_IO_POINTER(io, fptr); + rb_io_check_readable(fptr); + + if (rb_io_read_pending(fptr)) return Qtrue; + + rb_check_arity(argc, 0, 1); + VALUE timeout = argc == 1 ? argv[0] : Qnil; + + return io_wait_event(io, RUBY_IO_PRIORITY, timeout); } +#endif static int wait_mode_sym(VALUE mode) @@ -201,18 +282,25 @@ wait_mode_sym(VALUE mode) /* * call-seq: - * io.wait(timeout = nil, mode = :read) -> IO, true or nil + * io.wait(events, timeout) -> event mask or false. + * io.wait(timeout = nil, mode = :read) -> event mask or false. + * + * Waits until the IO becomes ready for the specified events and returns the + * subset of events that become ready, or +false+ when times out. + * + * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or + * +IO::PRIORITY+. * - * Waits until IO is readable or writable without blocking and returns - * +self+, or +nil+ when times out. * Returns +true+ immediately when buffered data is available. + * * Optional parameter +mode+ is one of +:read+, +:write+, or * +:read_write+. */ static VALUE -io_wait_readwrite(int argc, VALUE *argv, VALUE io) +io_wait(int argc, VALUE *argv, VALUE io) { +#ifndef HAVE_RB_IO_WAIT rb_io_t *fptr; struct timeval timerec; struct timeval *tv = NULL; @@ -236,6 +324,44 @@ io_wait_readwrite(int argc, VALUE *argv, VALUE io) if (wait_for_single_fd(fptr, event, tv)) return io; return Qnil; +#else + VALUE timeout = Qundef; + rb_io_event_t events = 0; + + if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) { + for (int i = 0; i < argc; i += 1) { + if (RB_SYMBOL_P(argv[i])) { + events |= wait_mode_sym(argv[i]); + } + else if (timeout == Qundef) { + rb_time_interval(timeout = argv[i]); + } + else { + rb_raise(rb_eArgError, "timeout given more than once"); + } + } + if (timeout == Qundef) timeout = Qnil; + } + else /* argc == 2 */ { + events = RB_NUM2UINT(argv[0]); + timeout = argv[1]; + } + + if (events == 0) { + events = RUBY_IO_READABLE; + } + + if (events & RUBY_IO_READABLE) { + rb_io_t *fptr = NULL; + RB_IO_POINTER(io, fptr); + + if (rb_io_read_pending(fptr)) { + return Qtrue; + } + } + + return io_wait_event(io, events, timeout); +#endif } /* @@ -245,9 +371,18 @@ io_wait_readwrite(int argc, VALUE *argv, VALUE io) void Init_wait(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); +#endif + rb_define_method(rb_cIO, "nread", io_nread, 0); rb_define_method(rb_cIO, "ready?", io_ready_p, 0); - rb_define_method(rb_cIO, "wait", io_wait_readwrite, -1); + + rb_define_method(rb_cIO, "wait", io_wait, -1); + rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1); rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1); +#ifdef HAVE_RB_IO_WAIT + rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1); +#endif } diff --git a/ruby/ext/json/VERSION b/ruby/ext/json/VERSION new file mode 100644 index 000000000..6a6a3d8e3 --- /dev/null +++ b/ruby/ext/json/VERSION @@ -0,0 +1 @@ +2.6.1 diff --git a/ruby/ext/json/extconf.rb b/ruby/ext/json/extconf.rb index 7595d58a9..8a99b6a5c 100644 --- a/ruby/ext/json/extconf.rb +++ b/ruby/ext/json/extconf.rb @@ -1,2 +1,3 @@ require 'mkmf' + create_makefile('json') diff --git a/ruby/ext/json/generator/depend b/ruby/ext/json/generator/depend index 3f04c0d62..1de5fb0b9 100644 --- a/ruby/ext/json/generator/depend +++ b/ruby/ext/json/generator/depend @@ -7,9 +7,166 @@ generator.o: $(arch_hdrdir)/ruby/config.h generator.o: $(hdrdir)/ruby.h generator.o: $(hdrdir)/ruby/assert.h generator.o: $(hdrdir)/ruby/backward.h +generator.o: $(hdrdir)/ruby/backward/2/assume.h +generator.o: $(hdrdir)/ruby/backward/2/attributes.h +generator.o: $(hdrdir)/ruby/backward/2/bool.h +generator.o: $(hdrdir)/ruby/backward/2/inttypes.h +generator.o: $(hdrdir)/ruby/backward/2/limits.h +generator.o: $(hdrdir)/ruby/backward/2/long_long.h +generator.o: $(hdrdir)/ruby/backward/2/stdalign.h +generator.o: $(hdrdir)/ruby/backward/2/stdarg.h generator.o: $(hdrdir)/ruby/defines.h generator.o: $(hdrdir)/ruby/encoding.h generator.o: $(hdrdir)/ruby/intern.h +generator.o: $(hdrdir)/ruby/internal/anyargs.h +generator.o: $(hdrdir)/ruby/internal/arithmetic.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/char.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/double.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/int.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/long.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/short.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +generator.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +generator.o: $(hdrdir)/ruby/internal/assume.h +generator.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +generator.o: $(hdrdir)/ruby/internal/attr/artificial.h +generator.o: $(hdrdir)/ruby/internal/attr/cold.h +generator.o: $(hdrdir)/ruby/internal/attr/const.h +generator.o: $(hdrdir)/ruby/internal/attr/constexpr.h +generator.o: $(hdrdir)/ruby/internal/attr/deprecated.h +generator.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +generator.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +generator.o: $(hdrdir)/ruby/internal/attr/error.h +generator.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +generator.o: $(hdrdir)/ruby/internal/attr/forceinline.h +generator.o: $(hdrdir)/ruby/internal/attr/format.h +generator.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +generator.o: $(hdrdir)/ruby/internal/attr/noalias.h +generator.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +generator.o: $(hdrdir)/ruby/internal/attr/noexcept.h +generator.o: $(hdrdir)/ruby/internal/attr/noinline.h +generator.o: $(hdrdir)/ruby/internal/attr/nonnull.h +generator.o: $(hdrdir)/ruby/internal/attr/noreturn.h +generator.o: $(hdrdir)/ruby/internal/attr/pure.h +generator.o: $(hdrdir)/ruby/internal/attr/restrict.h +generator.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +generator.o: $(hdrdir)/ruby/internal/attr/warning.h +generator.o: $(hdrdir)/ruby/internal/attr/weakref.h +generator.o: $(hdrdir)/ruby/internal/cast.h +generator.o: $(hdrdir)/ruby/internal/compiler_is.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +generator.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +generator.o: $(hdrdir)/ruby/internal/compiler_since.h +generator.o: $(hdrdir)/ruby/internal/config.h +generator.o: $(hdrdir)/ruby/internal/constant_p.h +generator.o: $(hdrdir)/ruby/internal/core.h +generator.o: $(hdrdir)/ruby/internal/core/rarray.h +generator.o: $(hdrdir)/ruby/internal/core/rbasic.h +generator.o: $(hdrdir)/ruby/internal/core/rbignum.h +generator.o: $(hdrdir)/ruby/internal/core/rclass.h +generator.o: $(hdrdir)/ruby/internal/core/rdata.h +generator.o: $(hdrdir)/ruby/internal/core/rfile.h +generator.o: $(hdrdir)/ruby/internal/core/rhash.h +generator.o: $(hdrdir)/ruby/internal/core/rmatch.h +generator.o: $(hdrdir)/ruby/internal/core/robject.h +generator.o: $(hdrdir)/ruby/internal/core/rregexp.h +generator.o: $(hdrdir)/ruby/internal/core/rstring.h +generator.o: $(hdrdir)/ruby/internal/core/rstruct.h +generator.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +generator.o: $(hdrdir)/ruby/internal/ctype.h +generator.o: $(hdrdir)/ruby/internal/dllexport.h +generator.o: $(hdrdir)/ruby/internal/dosish.h +generator.o: $(hdrdir)/ruby/internal/encoding/coderange.h +generator.o: $(hdrdir)/ruby/internal/encoding/ctype.h +generator.o: $(hdrdir)/ruby/internal/encoding/encoding.h +generator.o: $(hdrdir)/ruby/internal/encoding/pathname.h +generator.o: $(hdrdir)/ruby/internal/encoding/re.h +generator.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +generator.o: $(hdrdir)/ruby/internal/encoding/string.h +generator.o: $(hdrdir)/ruby/internal/encoding/symbol.h +generator.o: $(hdrdir)/ruby/internal/encoding/transcode.h +generator.o: $(hdrdir)/ruby/internal/error.h +generator.o: $(hdrdir)/ruby/internal/eval.h +generator.o: $(hdrdir)/ruby/internal/event.h +generator.o: $(hdrdir)/ruby/internal/fl_type.h +generator.o: $(hdrdir)/ruby/internal/gc.h +generator.o: $(hdrdir)/ruby/internal/glob.h +generator.o: $(hdrdir)/ruby/internal/globals.h +generator.o: $(hdrdir)/ruby/internal/has/attribute.h +generator.o: $(hdrdir)/ruby/internal/has/builtin.h +generator.o: $(hdrdir)/ruby/internal/has/c_attribute.h +generator.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +generator.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +generator.o: $(hdrdir)/ruby/internal/has/extension.h +generator.o: $(hdrdir)/ruby/internal/has/feature.h +generator.o: $(hdrdir)/ruby/internal/has/warning.h +generator.o: $(hdrdir)/ruby/internal/intern/array.h +generator.o: $(hdrdir)/ruby/internal/intern/bignum.h +generator.o: $(hdrdir)/ruby/internal/intern/class.h +generator.o: $(hdrdir)/ruby/internal/intern/compar.h +generator.o: $(hdrdir)/ruby/internal/intern/complex.h +generator.o: $(hdrdir)/ruby/internal/intern/cont.h +generator.o: $(hdrdir)/ruby/internal/intern/dir.h +generator.o: $(hdrdir)/ruby/internal/intern/enum.h +generator.o: $(hdrdir)/ruby/internal/intern/enumerator.h +generator.o: $(hdrdir)/ruby/internal/intern/error.h +generator.o: $(hdrdir)/ruby/internal/intern/eval.h +generator.o: $(hdrdir)/ruby/internal/intern/file.h +generator.o: $(hdrdir)/ruby/internal/intern/gc.h +generator.o: $(hdrdir)/ruby/internal/intern/hash.h +generator.o: $(hdrdir)/ruby/internal/intern/io.h +generator.o: $(hdrdir)/ruby/internal/intern/load.h +generator.o: $(hdrdir)/ruby/internal/intern/marshal.h +generator.o: $(hdrdir)/ruby/internal/intern/numeric.h +generator.o: $(hdrdir)/ruby/internal/intern/object.h +generator.o: $(hdrdir)/ruby/internal/intern/parse.h +generator.o: $(hdrdir)/ruby/internal/intern/proc.h +generator.o: $(hdrdir)/ruby/internal/intern/process.h +generator.o: $(hdrdir)/ruby/internal/intern/random.h +generator.o: $(hdrdir)/ruby/internal/intern/range.h +generator.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +generator.o: $(hdrdir)/ruby/internal/intern/sprintf.h +generator.o: $(hdrdir)/ruby/internal/intern/string.h +generator.o: $(hdrdir)/ruby/internal/intern/struct.h +generator.o: $(hdrdir)/ruby/internal/intern/thread.h +generator.o: $(hdrdir)/ruby/internal/intern/time.h +generator.o: $(hdrdir)/ruby/internal/intern/variable.h +generator.o: $(hdrdir)/ruby/internal/intern/vm.h +generator.o: $(hdrdir)/ruby/internal/interpreter.h +generator.o: $(hdrdir)/ruby/internal/iterator.h +generator.o: $(hdrdir)/ruby/internal/memory.h +generator.o: $(hdrdir)/ruby/internal/method.h +generator.o: $(hdrdir)/ruby/internal/module.h +generator.o: $(hdrdir)/ruby/internal/newobj.h +generator.o: $(hdrdir)/ruby/internal/rgengc.h +generator.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +generator.o: $(hdrdir)/ruby/internal/value.h +generator.o: $(hdrdir)/ruby/internal/value_type.h +generator.o: $(hdrdir)/ruby/internal/variable.h +generator.o: $(hdrdir)/ruby/internal/warning_push.h +generator.o: $(hdrdir)/ruby/internal/xmalloc.h generator.o: $(hdrdir)/ruby/missing.h generator.o: $(hdrdir)/ruby/onigmo.h generator.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/json/generator/generator.c b/ruby/ext/json/generator/generator.c index 881435e3d..e3a83472e 100644 --- a/ruby/ext/json/generator/generator.c +++ b/ruby/ext/json/generator/generator.c @@ -1,11 +1,6 @@ #include "../fbuffer/fbuffer.h" #include "generator.h" -#ifdef HAVE_RUBY_ENCODING_H -static VALUE CEncoding_UTF_8; -static ID i_encoding, i_encode; -#endif - static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, mHash, mArray, #ifdef RUBY_INTEGER_UNIFICATION @@ -15,14 +10,13 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, #endif mFloat, mString, mString_Extend, mTrueClass, mFalseClass, mNilClass, eGeneratorError, - eNestingError, - i_SAFE_STATE_PROTOTYPE; + 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_buffer_initial_length, i_dup, i_escape_slash; /* * Copyright 2001-2004 Unicode, Inc. @@ -130,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 /* 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) +static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash) { const UTF8 *source = (UTF8 *) RSTRING_PTR(string); const UTF8 *sourceEnd = source + RSTRING_LEN(string); @@ -180,6 +174,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string) case '"': fbuffer_append(buffer, "\\\"", 2); break; + case '/': + if(escape_slash) { + fbuffer_append(buffer, "\\/", 2); + break; + } default: fbuffer_append_char(buffer, (char)ch); break; @@ -229,7 +228,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string) * 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) +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; @@ -280,6 +279,12 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string) escape = "\\\""; escape_len = 2; break; + case '/': + if(escape_slash) { + escape = "\\/"; + escape_len = 2; + break; + } default: { unsigned short clen = 1; @@ -328,6 +333,76 @@ static char *fstrndup(const char *ptr, unsigned long len) { * */ +/* Explanation of the following: that's the only way to not pollute + * standard library's docs with GeneratorMethods:: which + * are uninformative and take a large place in a list of classes + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Array + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Float + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Hash + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Integer + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::Object + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::String + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend + * :nodoc: + */ + +/* + * Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass + * :nodoc: + */ + /* * call-seq: to_json(state = nil) * @@ -539,13 +614,18 @@ static size_t State_memsize(const void *ptr) return size; } +#ifndef HAVE_RB_EXT_RACTOR_SAFE +# undef RUBY_TYPED_FROZEN_SHAREABLE +# 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 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, + RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE, #endif }; #endif @@ -646,6 +726,8 @@ static VALUE cState_configure(VALUE self, VALUE opts) 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; } @@ -680,6 +762,7 @@ static VALUE cState_to_h(VALUE self) 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; @@ -860,13 +943,13 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S fbuffer_append_char(buffer, '"'); #ifdef HAVE_RUBY_ENCODING_H if (!enc_utf8_compatible_p(rb_enc_get(obj))) { - obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil); + obj = rb_str_export_to_enc(obj, rb_utf8_encoding()); } #endif if (state->ascii_only) { - convert_UTF8_to_JSON_ASCII(buffer, obj); + convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash); } else { - convert_UTF8_to_JSON(buffer, obj); + convert_UTF8_to_JSON(buffer, obj, state->escape_slash); } fbuffer_append_char(buffer, '"'); } @@ -1026,7 +1109,7 @@ static VALUE cState_generate(VALUE self, VALUE obj) * 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 - * ontions defaults to false. + * option defaults to false. * * *buffer_initial_length*: sets the initial length of the generator's * internal buffer. */ @@ -1082,8 +1165,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts) } else if (rb_obj_is_kind_of(opts, rb_cHash)) { return rb_funcall(self, i_new, 1, opts); } else { - VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE); - return rb_funcall(prototype, i_dup, 0); + return rb_class_new_instance(0, NULL, cState); } } @@ -1307,6 +1389,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth) return state->max_nesting = FIX2LONG(depth); } +/* + * call-seq: escape_slash + * + * If this boolean is true, the forward slashes will be escaped in + * the json output. + */ +static VALUE cState_escape_slash(VALUE self) +{ + GET_STATE(self); + return state->escape_slash ? Qtrue : Qfalse; +} + +/* + * call-seq: escape_slash=(depth) + * + * 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) +{ + GET_STATE(self); + state->escape_slash = RTEST(enable); + return Qnil; +} + /* * call-seq: allow_nan? * @@ -1390,6 +1497,10 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l */ void Init_generator(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + #undef rb_intern rb_require("json/common"); @@ -1419,6 +1530,9 @@ void Init_generator(void) rb_define_method(cState, "array_nl=", cState_array_nl_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, "check_circular?", cState_check_circular_p, 0); rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0); rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0); @@ -1475,6 +1589,7 @@ void Init_generator(void) 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"); @@ -1490,10 +1605,4 @@ void Init_generator(void) i_match = rb_intern("match"); i_keys = rb_intern("keys"); i_dup = rb_intern("dup"); -#ifdef HAVE_RUBY_ENCODING_H - CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8")); - i_encoding = rb_intern("encoding"); - i_encode = rb_intern("encode"); -#endif - i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE"); } diff --git a/ruby/ext/json/generator/generator.h b/ruby/ext/json/generator/generator.h index c367a6209..3ebd62255 100644 --- a/ruby/ext/json/generator/generator.h +++ b/ruby/ext/json/generator/generator.h @@ -49,8 +49,8 @@ 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); -static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string); +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 */ @@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct { long max_nesting; char allow_nan; char ascii_only; + char escape_slash; long depth; long buffer_initial_length; } JSON_Generator_State; @@ -150,6 +151,8 @@ 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))) diff --git a/ruby/ext/json/json.gemspec b/ruby/ext/json/json.gemspec index d8be2e52c..948e92c50 100644 --- a/ruby/ext/json/json.gemspec +++ b/ruby/ext/json/json.gemspec @@ -2,26 +2,22 @@ Gem::Specification.new do |s| s.name = "json" - s.version = "2.3.0" + s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib"] - s.authors = ["Florian Frank"] - s.date = "2019-12-11" + s.summary = "JSON Implementation for Ruby" s.description = "This is a JSON implementation as a Ruby extension in C." + 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 = [ - ".gitignore", - ".travis.yml", "CHANGES.md", - "Gemfile", - "README-json-jruby.md", + "LICENSE", "README.md", - "Rakefile", "VERSION", - "diagrams/.keep", "ext/json/ext/fbuffer/fbuffer.h", "ext/json/ext/generator/depend", "ext/json/ext/generator/extconf.rb", @@ -33,23 +29,7 @@ Gem::Specification.new do |s| "ext/json/ext/parser/parser.h", "ext/json/ext/parser/parser.rl", "ext/json/extconf.rb", - "install.rb", - "java/src/json/ext/ByteListTranscoder.java", - "java/src/json/ext/Generator.java", - "java/src/json/ext/GeneratorMethods.java", - "java/src/json/ext/GeneratorService.java", - "java/src/json/ext/GeneratorState.java", - "java/src/json/ext/OptionsReader.java", - "java/src/json/ext/Parser.java", - "java/src/json/ext/Parser.rl", - "java/src/json/ext/ParserService.java", - "java/src/json/ext/RuntimeInfo.java", - "java/src/json/ext/StringDecoder.java", - "java/src/json/ext/StringEncoder.java", - "java/src/json/ext/Utils.java", - "json-java.gemspec", "json.gemspec", - "json_pure.gemspec", "lib/json.rb", "lib/json/add/bigdecimal.rb", "lib/json/add/complex.rb", @@ -67,67 +47,21 @@ Gem::Specification.new do |s| "lib/json/add/time.rb", "lib/json/common.rb", "lib/json/ext.rb", - "lib/json/ext/.keep", "lib/json/generic_object.rb", "lib/json/pure.rb", "lib/json/pure/generator.rb", "lib/json/pure/parser.rb", "lib/json/version.rb", - "references/rfc7159.txt", - "tests/fixtures/fail10.json", - "tests/fixtures/fail11.json", - "tests/fixtures/fail12.json", - "tests/fixtures/fail13.json", - "tests/fixtures/fail14.json", - "tests/fixtures/fail18.json", - "tests/fixtures/fail19.json", - "tests/fixtures/fail2.json", - "tests/fixtures/fail20.json", - "tests/fixtures/fail21.json", - "tests/fixtures/fail22.json", - "tests/fixtures/fail23.json", - "tests/fixtures/fail24.json", - "tests/fixtures/fail25.json", - "tests/fixtures/fail27.json", - "tests/fixtures/fail28.json", - "tests/fixtures/fail3.json", - "tests/fixtures/fail4.json", - "tests/fixtures/fail5.json", - "tests/fixtures/fail6.json", - "tests/fixtures/fail7.json", - "tests/fixtures/fail8.json", - "tests/fixtures/fail9.json", - "tests/fixtures/obsolete_fail1.json", - "tests/fixtures/pass1.json", - "tests/fixtures/pass15.json", - "tests/fixtures/pass16.json", - "tests/fixtures/pass17.json", - "tests/fixtures/pass2.json", - "tests/fixtures/pass26.json", - "tests/fixtures/pass3.json", - "tests/json_addition_test.rb", - "tests/json_common_interface_test.rb", - "tests/json_encoding_test.rb", - "tests/json_ext_parser_test.rb", - "tests/json_fixtures_test.rb", - "tests/json_generator_test.rb", - "tests/json_generic_object_test.rb", - "tests/json_parser_test.rb", - "tests/json_string_matching_test.rb", - "tests/test_helper.rb", - "tests/test_helper.rb", - "tools/diff.sh", - "tools/fuzz.rb", - "tools/server.rb", ] s.homepage = "http://flori.github.com/json" - s.licenses = ["Ruby"] - s.rdoc_options = ["--title", "JSON implemention for Ruby", "--main", "README.md"] - s.required_ruby_version = Gem::Requirement.new(">= 1.9") - s.rubygems_version = "3.0.3" - s.summary = "JSON Implementation for Ruby" - s.test_files = ["tests/test_helper.rb"] + s.metadata = { + 'bug_tracker_uri' => 'https://github.com/flori/json/issues', + 'changelog_uri' => 'https://github.com/flori/json/blob/master/CHANGES.md', + 'documentation_uri' => 'http://flori.github.io/json/doc/index.html', + 'homepage_uri' => 'http://flori.github.io/json/', + 'source_code_uri' => 'https://github.com/flori/json', + 'wiki_uri' => 'https://github.com/flori/json/wiki' + } - s.add_development_dependency("rake", [">= 0"]) - s.add_development_dependency("test-unit", ["~> 2.0"]) + s.required_ruby_version = Gem::Requirement.new(">= 2.3") end diff --git a/ruby/ext/json/lib/json.rb b/ruby/ext/json/lib/json.rb index b5a691241..1e64bfcb1 100644 --- a/ruby/ext/json/lib/json.rb +++ b/ruby/ext/json/lib/json.rb @@ -2,55 +2,575 @@ require 'json/common' ## -# = JavaScript Object Notation (JSON) +# = JavaScript \Object Notation (\JSON) # -# JSON is a lightweight data-interchange format. It is easy for us -# humans to read and write. Plus, equally simple for machines to generate or parse. -# JSON is completely language agnostic, making it the ideal interchange format. +# \JSON is a lightweight data-interchange format. # -# Built on two universally available structures: -# 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array. -# 2. An ordered list of values. More commonly called an _array_, vector, sequence or list. +# A \JSON value is one of the following: +# - Double-quoted text: "foo". +# - Number: +1+, +1.0+, +2.0e2+. +# - Boolean: +true+, +false+. +# - Null: +null+. +# - \Array: an ordered list of values, enclosed by square brackets: +# ["foo", 1, 1.0, 2.0e2, true, false, null] # -# To read more about JSON visit: http://json.org +# - \Object: a collection of name/value pairs, enclosed by curly braces; +# each name is double-quoted text; +# the values may be any \JSON values: +# {"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null} # -# == Parsing JSON +# A \JSON array or object may contain nested arrays, objects, and scalars +# to any depth: +# {"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]} +# [{"foo": 0, "bar": 1}, ["baz", 2]] # -# To parse a JSON string received by another application or generated within -# your existing application: +# == Using \Module \JSON # +# To make module \JSON available in your code, begin with: # require 'json' # -# my_hash = JSON.parse('{"hello": "goodbye"}') -# puts my_hash["hello"] => "goodbye" +# All examples here assume that this has been done. # -# Notice the extra quotes '' around the hash notation. Ruby expects -# the argument to be a string and can't convert objects like a hash or array. +# === Parsing \JSON # -# Ruby converts your string into a hash +# You can parse a \String containing \JSON data using +# either of two methods: +# - JSON.parse(source, opts) +# - JSON.parse!(source, opts) # -# == Generating JSON +# where +# - +source+ is a Ruby object. +# - +opts+ is a \Hash object containing options +# that control both input allowed and output formatting. # -# Creating a JSON string for communication or serialization is -# just as simple. +# The difference between the two methods +# is that JSON.parse! omits some checks +# and may not be safe for some +source+ data; +# use it only for data from trusted sources. +# Use the safer method JSON.parse for less trusted sources. # -# require 'json' +# ==== Parsing \JSON Arrays # -# my_hash = {:hello => "goodbye"} -# puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}" +# When +source+ is a \JSON array, JSON.parse by default returns a Ruby \Array: +# json = '["foo", 1, 1.0, 2.0e2, true, false, null]' +# ruby = JSON.parse(json) +# ruby # => ["foo", 1, 1.0, 200.0, true, false, nil] +# ruby.class # => Array # -# Or an alternative way: +# The \JSON array may contain nested arrays, objects, and scalars +# to any depth: +# json = '[{"foo": 0, "bar": 1}, ["baz", 2]]' +# JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]] # -# require 'json' -# puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}" +# ==== Parsing \JSON \Objects +# +# When the source is a \JSON object, JSON.parse by default returns a Ruby \Hash: +# json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}' +# ruby = JSON.parse(json) +# ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil} +# ruby.class # => Hash +# +# The \JSON object may contain nested arrays, objects, and scalars +# to any depth: +# json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}' +# JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]} +# +# ==== Parsing \JSON Scalars +# +# When the source is a \JSON scalar (not an array or object), +# JSON.parse returns a Ruby scalar. +# +# \String: +# ruby = JSON.parse('"foo"') +# ruby # => 'foo' +# ruby.class # => String +# \Integer: +# ruby = JSON.parse('1') +# ruby # => 1 +# ruby.class # => Integer +# \Float: +# ruby = JSON.parse('1.0') +# ruby # => 1.0 +# ruby.class # => Float +# ruby = JSON.parse('2.0e2') +# ruby # => 200 +# ruby.class # => Float +# Boolean: +# ruby = JSON.parse('true') +# ruby # => true +# ruby.class # => TrueClass +# ruby = JSON.parse('false') +# ruby # => false +# ruby.class # => FalseClass +# Null: +# ruby = JSON.parse('null') +# ruby # => nil +# ruby.class # => NilClass +# +# ==== Parsing Options +# +# ====== Input Options +# +# Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed; +# defaults to +100+; specify +false+ to disable depth checking. +# +# With the default, +false+: +# source = '[0, [1, [2, [3]]]]' +# ruby = JSON.parse(source) +# ruby # => [0, [1, [2, [3]]]] +# Too deep: +# # Raises JSON::NestingError (nesting of 2 is too deep): +# JSON.parse(source, {max_nesting: 1}) +# Bad value: +# # Raises TypeError (wrong argument type Symbol (expected Fixnum)): +# JSON.parse(source, {max_nesting: :foo}) +# +# --- +# +# Option +allow_nan+ (boolean) specifies whether to allow +# NaN, Infinity, and MinusInfinity in +source+; +# defaults to +false+. +# +# With the default, +false+: +# # Raises JSON::ParserError (225: unexpected token at '[NaN]'): +# JSON.parse('[NaN]') +# # Raises JSON::ParserError (232: unexpected token at '[Infinity]'): +# JSON.parse('[Infinity]') +# # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'): +# JSON.parse('[-Infinity]') +# Allow: +# source = '[NaN, Infinity, -Infinity]' +# ruby = JSON.parse(source, {allow_nan: true}) +# ruby # => [NaN, Infinity, -Infinity] +# +# ====== Output Options +# +# Option +symbolize_names+ (boolean) specifies whether returned \Hash keys +# should be Symbols; +# defaults to +false+ (use Strings). +# +# With the default, +false+: +# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' +# ruby = JSON.parse(source) +# ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil} +# Use Symbols: +# ruby = JSON.parse(source, {symbolize_names: true}) +# ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil} +# +# --- +# +# Option +object_class+ (\Class) specifies the Ruby class to be used +# for each \JSON object; +# defaults to \Hash. +# +# With the default, \Hash: +# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' +# ruby = JSON.parse(source) +# ruby.class # => Hash +# Use class \OpenStruct: +# ruby = JSON.parse(source, {object_class: OpenStruct}) +# ruby # => # +# +# --- +# +# Option +array_class+ (\Class) specifies the Ruby class to be used +# for each \JSON array; +# defaults to \Array. +# +# With the default, \Array: +# source = '["foo", 1.0, true, false, null]' +# ruby = JSON.parse(source) +# ruby.class # => Array +# Use class \Set: +# ruby = JSON.parse(source, {array_class: Set}) +# ruby # => # +# +# --- +# +# Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing. +# See {\JSON Additions}[#module-JSON-label-JSON+Additions]. +# +# === Generating \JSON +# +# To generate a Ruby \String containing \JSON data, +# use method JSON.generate(source, opts), where +# - +source+ is a Ruby object. +# - +opts+ is a \Hash object containing options +# that control both input allowed and output formatting. +# +# ==== Generating \JSON from Arrays +# +# When the source is a Ruby \Array, JSON.generate returns +# a \String containing a \JSON array: +# ruby = [0, 's', :foo] +# json = JSON.generate(ruby) +# json # => '[0,"s","foo"]' +# +# The Ruby \Array array may contain nested arrays, hashes, and scalars +# to any depth: +# ruby = [0, [1, 2], {foo: 3, bar: 4}] +# json = JSON.generate(ruby) +# json # => '[0,[1,2],{"foo":3,"bar":4}]' +# +# ==== Generating \JSON from Hashes +# +# When the source is a Ruby \Hash, JSON.generate returns +# a \String containing a \JSON object: +# ruby = {foo: 0, bar: 's', baz: :bat} +# json = JSON.generate(ruby) +# json # => '{"foo":0,"bar":"s","baz":"bat"}' +# +# The Ruby \Hash array may contain nested arrays, hashes, and scalars +# to any depth: +# ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} +# json = JSON.generate(ruby) +# json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}' +# +# ==== Generating \JSON from Other Objects +# +# When the source is neither an \Array nor a \Hash, +# the generated \JSON data depends on the class of the source. +# +# When the source is a Ruby \Integer or \Float, JSON.generate returns +# a \String containing a \JSON number: +# JSON.generate(42) # => '42' +# JSON.generate(0.42) # => '0.42' +# +# When the source is a Ruby \String, JSON.generate returns +# a \String containing a \JSON string (with double-quotes): +# JSON.generate('A string') # => '"A string"' +# +# When the source is +true+, +false+ or +nil+, JSON.generate returns +# a \String containing the corresponding \JSON token: +# JSON.generate(true) # => 'true' +# JSON.generate(false) # => 'false' +# JSON.generate(nil) # => 'null' +# +# When the source is none of the above, JSON.generate returns +# a \String containing a \JSON string representation of the source: +# JSON.generate(:foo) # => '"foo"' +# JSON.generate(Complex(0, 0)) # => '"0+0i"' +# JSON.generate(Dir.new('.')) # => '"#"' +# +# ==== Generating Options +# +# ====== Input Options # -# JSON.generate only allows objects or arrays to be converted -# to JSON syntax. to_json, however, accepts many Ruby classes -# even though it acts only as a method for serialization: +# Option +allow_nan+ (boolean) specifies whether +# +NaN+, +Infinity+, and -Infinity may be generated; +# defaults to +false+. # +# With the default, +false+: +# # Raises JSON::GeneratorError (920: NaN not allowed in JSON): +# JSON.generate(JSON::NaN) +# # Raises JSON::GeneratorError (917: Infinity not allowed in JSON): +# JSON.generate(JSON::Infinity) +# # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON): +# JSON.generate(JSON::MinusInfinity) +# +# Allow: +# ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity] +# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]' +# +# --- +# +# Option +max_nesting+ (\Integer) specifies the maximum nesting depth +# in +obj+; defaults to +100+. +# +# With the default, +100+: +# obj = [[[[[[0]]]]]] +# JSON.generate(obj) # => '[[[[[[0]]]]]]' +# +# Too deep: +# # Raises JSON::NestingError (nesting of 2 is too deep): +# JSON.generate(obj, max_nesting: 2) +# +# ====== Output Options +# +# The default formatting options generate the most compact +# \JSON data, all on one line and with no whitespace. +# +# You can use these formatting options to generate +# \JSON data in a more open format, using whitespace. +# See also JSON.pretty_generate. +# +# - Option +array_nl+ (\String) specifies a string (usually a newline) +# to be inserted after each \JSON array; defaults to the empty \String, ''. +# - Option +object_nl+ (\String) specifies a string (usually a newline) +# to be inserted after each \JSON object; defaults to the empty \String, ''. +# - Option +indent+ (\String) specifies the string (usually spaces) to be +# used for indentation; defaults to the empty \String, ''; +# defaults to the empty \String, ''; +# has no effect unless options +array_nl+ or +object_nl+ specify newlines. +# - Option +space+ (\String) specifies a string (usually a space) to be +# inserted after the colon in each \JSON object's pair; +# defaults to the empty \String, ''. +# - Option +space_before+ (\String) specifies a string (usually a space) to be +# inserted before the colon in each \JSON object's pair; +# defaults to the empty \String, ''. +# +# In this example, +obj+ is used first to generate the shortest +# \JSON data (no whitespace), then again with all formatting options +# specified: +# +# obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} +# json = JSON.generate(obj) +# puts 'Compact:', json +# opts = { +# array_nl: "\n", +# object_nl: "\n", +# indent: ' ', +# space_before: ' ', +# space: ' ' +# } +# puts 'Open:', JSON.generate(obj, opts) +# +# Output: +# Compact: +# {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}} +# Open: +# { +# "foo" : [ +# "bar", +# "baz" +# ], +# "bat" : { +# "bam" : 0, +# "bad" : 1 +# } +# } +# +# == \JSON Additions +# +# When you "round trip" a non-\String object from Ruby to \JSON and back, +# you have a new \String, instead of the object you began with: +# ruby0 = Range.new(0, 2) +# json = JSON.generate(ruby0) +# json # => '0..2"' +# ruby1 = JSON.parse(json) +# ruby1 # => '0..2' +# ruby1.class # => String +# +# You can use \JSON _additions_ to preserve the original object. +# The addition is an extension of a ruby class, so that: +# - \JSON.generate stores more information in the \JSON string. +# - \JSON.parse, called with option +create_additions+, +# uses that information to create a proper Ruby object. +# +# This example shows a \Range being generated into \JSON +# and parsed back into Ruby, both without and with +# the addition for \Range: +# ruby = Range.new(0, 2) +# # This passage does not use the addition for Range. +# json0 = JSON.generate(ruby) +# ruby0 = JSON.parse(json0) +# # This passage uses the addition for Range. +# require 'json/add/range' +# json1 = JSON.generate(ruby) +# ruby1 = JSON.parse(json1, create_additions: true) +# # Make a nice display. +# display = <require 'json/add/bigdecimal' +# - Complex: require 'json/add/complex' +# - Date: require 'json/add/date' +# - DateTime: require 'json/add/date_time' +# - Exception: require 'json/add/exception' +# - OpenStruct: require 'json/add/ostruct' +# - Range: require 'json/add/range' +# - Rational: require 'json/add/rational' +# - Regexp: require 'json/add/regexp' +# - Set: require 'json/add/set' +# - Struct: require 'json/add/struct' +# - Symbol: require 'json/add/symbol' +# - Time: require 'json/add/time' +# +# To reduce punctuation clutter, the examples below +# show the generated \JSON via +puts+, rather than the usual +inspect+, +# +# \BigDecimal: +# require 'json/add/bigdecimal' +# ruby0 = BigDecimal(0) # 0.0 +# json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"} +# ruby1 = JSON.parse(json, create_additions: true) # 0.0 +# ruby1.class # => BigDecimal +# +# \Complex: +# require 'json/add/complex' +# ruby0 = Complex(1+0i) # 1+0i +# json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0} +# ruby1 = JSON.parse(json, create_additions: true) # 1+0i +# ruby1.class # Complex +# +# \Date: +# require 'json/add/date' +# ruby0 = Date.today # 2020-05-02 +# json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0} +# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 +# ruby1.class # Date +# +# \DateTime: +# require 'json/add/date_time' +# ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00 +# json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0} +# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00 +# ruby1.class # DateTime +# +# \Exception (and its subclasses including \RuntimeError): +# require 'json/add/exception' +# ruby0 = Exception.new('A message') # A message +# json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null} +# ruby1 = JSON.parse(json, create_additions: true) # A message +# ruby1.class # Exception +# ruby0 = RuntimeError.new('Another message') # Another message +# json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null} +# ruby1 = JSON.parse(json, create_additions: true) # Another message +# ruby1.class # RuntimeError +# +# \OpenStruct: +# require 'json/add/ostruct' +# ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # # +# json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}} +# ruby1 = JSON.parse(json, create_additions: true) # # +# ruby1.class # OpenStruct +# +# \Range: +# require 'json/add/range' +# ruby0 = Range.new(0, 2) # 0..2 +# json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]} +# ruby1 = JSON.parse(json, create_additions: true) # 0..2 +# ruby1.class # Range +# +# \Rational: +# require 'json/add/rational' +# ruby0 = Rational(1, 3) # 1/3 +# json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3} +# ruby1 = JSON.parse(json, create_additions: true) # 1/3 +# ruby1.class # Rational +# +# \Regexp: +# require 'json/add/regexp' +# ruby0 = Regexp.new('foo') # (?-mix:foo) +# json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"} +# ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo) +# ruby1.class # Regexp +# +# \Set: +# require 'json/add/set' +# ruby0 = Set.new([0, 1, 2]) # # +# json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]} +# ruby1 = JSON.parse(json, create_additions: true) # # +# ruby1.class # Set +# +# \Struct: +# require 'json/add/struct' +# Customer = Struct.new(:name, :address) # Customer +# ruby0 = Customer.new("Dave", "123 Main") # # +# json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]} +# ruby1 = JSON.parse(json, create_additions: true) # # +# ruby1.class # Customer +# +# \Symbol: +# require 'json/add/symbol' +# ruby0 = :foo # foo +# json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"} +# ruby1 = JSON.parse(json, create_additions: true) # foo +# ruby1.class # Symbol +# +# \Time: +# require 'json/add/time' +# ruby0 = Time.now # 2020-05-02 11:28:26 -0500 +# json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000} +# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500 +# ruby1.class # Time +# +# +# === Custom \JSON Additions +# +# In addition to the \JSON additions provided, +# you can craft \JSON additions of your own, +# either for Ruby built-in classes or for user-defined classes. +# +# Here's a user-defined class +Foo+: +# class Foo +# attr_accessor :bar, :baz +# def initialize(bar, baz) +# self.bar = bar +# self.baz = baz +# end +# end +# +# Here's the \JSON addition for it: +# # Extend class Foo with JSON addition. +# class Foo +# # Serialize Foo object with its class name and arguments +# def to_json(*args) +# { +# JSON.create_id => self.class.name, +# 'a' => [ bar, baz ] +# }.to_json(*args) +# end +# # Deserialize JSON string by constructing new Foo object with arguments. +# def self.json_create(object) +# new(*object['a']) +# end +# end +# +# Demonstration: # require 'json' +# # This Foo object has no custom addition. +# foo0 = Foo.new(0, 1) +# json0 = JSON.generate(foo0) +# obj0 = JSON.parse(json0) +# # Lood the custom addition. +# require_relative 'foo_addition' +# # This foo has the custom addition. +# foo1 = Foo.new(0, 1) +# json1 = JSON.generate(foo1) +# obj1 = JSON.parse(json1, create_additions: true) +# # Make a nice display. +# display = < "1" +# Generated JSON: +# Without custom addition: "#" (String) +# With custom addition: {"json_class":"Foo","a":[0,1]} (String) +# Parsed JSON: +# Without custom addition: "#" (String) +# With custom addition: # (Foo) # module JSON require 'json/version' diff --git a/ruby/ext/json/lib/json/add/complex.rb b/ruby/ext/json/lib/json/add/complex.rb index 4d977e758..e63e29fd2 100644 --- a/ruby/ext/json/lib/json/add/complex.rb +++ b/ruby/ext/json/lib/json/add/complex.rb @@ -2,7 +2,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end -defined?(::Complex) or require 'complex' class Complex diff --git a/ruby/ext/json/lib/json/add/rational.rb b/ruby/ext/json/lib/json/add/rational.rb index 6be403458..f77622604 100644 --- a/ruby/ext/json/lib/json/add/rational.rb +++ b/ruby/ext/json/lib/json/add/rational.rb @@ -2,7 +2,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end -defined?(::Rational) or require 'rational' class Rational # Deserializes JSON string by converting numerator value n, diff --git a/ruby/ext/json/lib/json/common.rb b/ruby/ext/json/lib/json/common.rb index 3be9fd8dc..ea46896fc 100644 --- a/ruby/ext/json/lib/json/common.rb +++ b/ruby/ext/json/lib/json/common.rb @@ -4,12 +4,17 @@ module JSON class << self - # If _object_ is string-like, parse the string and return the parsed - # result as a Ruby data structure. Otherwise generate a JSON text from the - # Ruby data structure object and return it. + # :call-seq: + # JSON[object] -> new_array or new_string # - # The _opts_ argument is passed through to generate/parse respectively. - # See generate and parse for their documentation. + # If +object+ is a \String, + # calls JSON.parse with +object+ and +opts+ (see method #parse): + # json = '[0, 1, null]' + # JSON[json]# => [0, 1, nil] + # + # 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) @@ -19,7 +24,8 @@ def [](object, opts = {}) end # Returns the JSON parser class that is used by JSON. This is either - # JSON::Ext::Parser or JSON::Pure::Parser. + # JSON::Ext::Parser or JSON::Pure::Parser: + # JSON.parser # => JSON::Ext::Parser attr_reader :parser # Set the JSON parser class _parser_ to be used by JSON. @@ -65,37 +71,61 @@ def generator=(generator) # :nodoc: end self.state = generator::State const_set :State, self.state - const_set :SAFE_STATE_PROTOTYPE, State.new - const_set :FAST_STATE_PROTOTYPE, State.new( + 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 + ensure + $VERBOSE = old + end + + def create_fast_state + State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) - const_set :PRETTY_STATE_PROTOTYPE, State.new( + end + + def create_pretty_state + State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) - ensure - $VERBOSE = old end # Returns the JSON generator module that is used by JSON. This is - # either JSON::Ext::Generator or JSON::Pure::Generator. + # either JSON::Ext::Generator or JSON::Pure::Generator: + # JSON.generator # => JSON::Ext::Generator attr_reader :generator - # Returns the JSON generator state class that is used by JSON. This is - # either JSON::Ext::Generator::State or JSON::Pure::Generator::State. + # 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 attr_accessor :state + end + + DEFAULT_CREATE_ID = 'json_class'.freeze + private_constant :DEFAULT_CREATE_ID + + CREATE_ID_TLS_KEY = "JSON.create_id".freeze + private_constant :CREATE_ID_TLS_KEY + + # 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 + end - # This is create identifier, which is used to decide if the _json_create_ - # hook of a class should be called. It defaults to 'json_class'. - attr_accessor :create_id + # Returns the current create identifier. + # See also JSON.create_id=. + def self.create_id + Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID end - self.create_id = 'json_class' NaN = 0.0/0 @@ -126,7 +156,7 @@ class CircularDatastructure < NestingError; end # This exception is raised if a generator or unparser error occurs. class GeneratorError < JSONError; end # For backwards compatibility - UnparserError = GeneratorError + UnparserError = GeneratorError # :nodoc: # This exception is raised if the required unicode support is missing on the # system. Usually this means that the iconv library is not installed. @@ -134,43 +164,69 @@ class MissingUnicodeSupport < JSONError; end module_function - # Parse the JSON document _source_ into a Ruby data structure and return it. - # - # _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. It - # defaults to 100. - # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in - # defiance of RFC 7159 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. Strings are - # the default. - # * *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 + # :call-seq: + # JSON.parse(source, opts) -> object + # + # Returns the Ruby objects created by parsing the given +source+. + # + # Argument +source+ contains the \String to be parsed. + # + # Argument +opts+, if given, contains a \Hash of options for the parsing. + # See {Parsing Options}[#module-JSON-label-Parsing+Options]. + # + # --- + # + # When +source+ is a \JSON array, returns a Ruby \Array: + # source = '["foo", 1.0, true, false, null]' + # ruby = JSON.parse(source) + # ruby # => ["foo", 1.0, true, false, nil] + # ruby.class # => Array + # + # When +source+ is a \JSON object, returns a Ruby \Hash: + # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' + # ruby = JSON.parse(source) + # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil} + # ruby.class # => Hash + # + # For examples of parsing for all \JSON data types, see + # {Parsing \JSON}[#module-JSON-label-Parsing+JSON]. + # + # Parses nested JSON objects: + # source = <<-EOT + # { + # "name": "Dave", + # "age" :40, + # "hats": [ + # "Cattleman's", + # "Panama", + # "Tophat" + # ] + # } + # EOT + # ruby = JSON.parse(source) + # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} + # + # --- + # + # Raises an exception if +source+ is not valid JSON: + # # Raises JSON::ParserError (783: unexpected token at ''): + # JSON.parse('') + # def parse(source, opts = {}) Parser.new(source, **(opts||{})).parse end - # Parse the JSON document _source_ into a Ruby data structure and return it. - # The bang version of the parse method defaults to the more dangerous values - # for the _opts_ hash, so be sure only to parse trusted _source_ documents. - # - # _opts_ can have the following keys: - # * *max_nesting*: The maximum depth of nesting allowed in the parsed data - # structures. Enable depth checking with :max_nesting => anInteger. The - # parse! methods defaults to not doing max depth checking: This can be - # dangerous if someone wants to fill up your stack. - # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in - # defiance of RFC 7159 to be parsed by the Parser. This option defaults - # to true. - # * *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. + # :call-seq: + # JSON.parse!(source, opts) -> object + # + # Calls + # parse(source, opts) + # with +source+ and possibly modified +opts+. + # + # Differences from JSON.parse: + # - 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, @@ -179,37 +235,69 @@ def parse!(source, opts = {}) Parser.new(source, **(opts||{})).parse end - # Generate a JSON document from the Ruby data structure _obj_ and return - # it. _state_ is * a JSON::State object, - # * or a Hash like object (responding to to_hash), - # * an object convertible into a hash by a to_h method, - # that is used as or to configure a State object. - # - # It defaults to a state object, that creates the shortest possible JSON text - # in one line, checks for circular data structures and doesn't allow NaN, - # Infinity, and -Infinity. - # - # A _state_ hash 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. - # * *max_nesting*: The maximum depth of nesting allowed in the data - # structures from which JSON is to be generated. Disable depth checking - # with :max_nesting => false, it defaults to 100. - # - # See also the fast_generate for the fastest creation method with the least - # amount of sanity checks, and the pretty_generate method for some - # defaults for pretty output. + # :call-seq: + # JSON.load_file(path, opts={}) -> object + # + # Calls: + # parse(File.read(path), opts) + # + # See method #parse. + def load_file(filespec, opts = {}) + parse(File.read(filespec), opts) + end + + # :call-seq: + # JSON.load_file!(path, opts = {}) + # + # Calls: + # JSON.parse!(File.read(path, opts)) + # + # See method #parse! + def load_file!(filespec, opts = {}) + parse!(File.read(filespec), opts) + end + + # :call-seq: + # JSON.generate(obj, opts = nil) -> new_string + # + # Returns a \String containing the generated \JSON data. + # + # See also JSON.fast_generate, JSON.pretty_generate. + # + # Argument +obj+ is the Ruby object to be converted to \JSON. + # + # Argument +opts+, if given, contains a \Hash of options for the generation. + # See {Generating Options}[#module-JSON-label-Generating+Options]. + # + # --- + # + # When +obj+ is an \Array, returns a \String containing a \JSON array: + # obj = ["foo", 1.0, true, false, nil] + # json = JSON.generate(obj) + # json # => '["foo",1.0,true,false,null]' + # + # When +obj+ is a \Hash, returns a \String containing a \JSON object: + # obj = {foo: 0, bar: 's', baz: :bat} + # json = JSON.generate(obj) + # json # => '{"foo":0,"bar":"s","baz":"bat"}' + # + # For examples of generating from other Ruby objects, see + # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects]. + # + # --- + # + # Raises an exception if any formatting option is not a \String. + # + # Raises an exception if +obj+ contains circular references: + # a = []; b = []; a.push(b); b.push(a) + # # Raises JSON::NestingError (nesting of 100 is too deep): + # JSON.generate(a) + # def generate(obj, opts = nil) if State === opts state, opts = opts, nil else - state = SAFE_STATE_PROTOTYPE.dup + state = State.new end if opts if opts.respond_to? :to_hash @@ -231,16 +319,24 @@ def generate(obj, opts = nil) module_function :unparse # :startdoc: - # Generate a JSON document from the Ruby data structure _obj_ and return it. - # This method disables the checks for circles in Ruby objects. + # :call-seq: + # JSON.fast_generate(obj, opts) -> new_string + # + # Arguments +obj+ and +opts+ here are the same as + # arguments +obj+ and +opts+ in JSON.generate. + # + # By default, generates \JSON data without checking + # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled). # - # *WARNING*: Be careful not to pass any Ruby data structures with circles as - # _obj_ argument because this will cause JSON to go into an infinite loop. + # Raises an exception if +obj+ contains circular references: + # a = []; b = []; a.push(b); b.push(a) + # # Raises SystemStackError (stack level too deep): + # JSON.fast_generate(a) def fast_generate(obj, opts = nil) if State === opts state, opts = opts, nil else - state = FAST_STATE_PROTOTYPE.dup + state = JSON.create_fast_state end if opts if opts.respond_to? :to_hash @@ -261,17 +357,41 @@ def fast_generate(obj, opts = nil) module_function :fast_unparse # :startdoc: - # Generate a JSON document from the Ruby data structure _obj_ and return it. - # The returned document is a prettier form of the document returned by - # #unparse. + # :call-seq: + # JSON.pretty_generate(obj, opts = nil) -> new_string + # + # Arguments +obj+ and +opts+ here are the same as + # arguments +obj+ and +opts+ in JSON.generate. + # + # Default options are: + # { + # indent: ' ', # Two spaces + # space: ' ', # One space + # array_nl: "\n", # Newline + # object_nl: "\n" # Newline + # } + # + # Example: + # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} + # json = JSON.pretty_generate(obj) + # puts json + # Output: + # { + # "foo": [ + # "bar", + # "baz" + # ], + # "bat": { + # "bam": 0, + # "bad": 1 + # } + # } # - # The _opts_ argument can be used to configure the generator. See the - # generate method for a more detailed explanation. def pretty_generate(obj, opts = nil) if State === opts state, opts = opts, nil else - state = PRETTY_STATE_PROTOTYPE.dup + state = JSON.create_pretty_state end if opts if opts.respond_to? :to_hash @@ -293,10 +413,10 @@ def pretty_generate(obj, opts = nil) # :startdoc: class << self - # The global default options for the JSON.load method: - # :max_nesting: false - # :allow_nan: true - # :allow_blank: 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} attr_accessor :load_default_options end self.load_default_options = { @@ -306,20 +426,134 @@ class << self :create_additions => true, } - # Load a ruby data structure from a JSON _source_ and return it. A source can - # either be a string-like object, an IO-like object, or an object responding - # to the read method. If _proc_ was given, it will be called with any nested - # Ruby object as an argument recursively in depth first order. To modify the - # default options pass in the optional _options_ argument as well. + # :call-seq: + # JSON.load(source, proc = nil, options = {}) -> object + # + # Returns the Ruby objects created by parsing the given +source+. + # + # - 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. + # 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=. + # + # --- + # + # When no +proc+ is given, modifies +source+ as above and returns the result of + # parse(source, opts); see #parse. + # + # Source for following examples: + # source = <<-EOT + # { + # "name": "Dave", + # "age" :40, + # "hats": [ + # "Cattleman's", + # "Panama", + # "Tophat" + # ] + # } + # EOT # - # 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. The - # default options for the parser can be changed via the load_default_options - # method. + # Load a \String: + # ruby = JSON.load(source) + # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} + # + # Load an \IO object: + # require 'stringio' + # object = JSON.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.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 + # { + # "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"} + # } + # 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.load + # ruby = JSON.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"}>} # - # This method is part of the implementation of the load/dump interface of - # Marshal and YAML. def load(source, proc = nil, options = {}) opts = load_default_options.merge options if source.respond_to? :to_str @@ -338,7 +572,7 @@ def load(source, proc = nil, options = {}) end # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_ - def recurse_proc(result, &proc) + def recurse_proc(result, &proc) # :nodoc: case result when Array result.each { |x| recurse_proc x, &proc } @@ -355,32 +589,45 @@ def recurse_proc(result, &proc) module_function :restore class << self - # The global default options for the JSON.dump method: - # :max_nesting: false - # :allow_nan: true - # :allow_blank: true + # 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 end self.dump_default_options = { :max_nesting => false, :allow_nan => true, + :escape_slash => false, } - # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns - # the result. + # :call-seq: + # JSON.dump(obj, io = nil, limit = nil) + # + # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result. + # + # The default options can be changed via method JSON.dump_default_options. # - # If anIO (an IO-like object or an object that responds to the write method) - # was given, the resulting JSON is written to it. + # - Argument +io+, if given, should respond to method +write+; + # the \JSON \String is written to +io+, and +io+ is returned. + # If +io+ is not given, the \JSON \String is returned. + # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+. # - # If the number of nested arrays or objects exceeds _limit_, an ArgumentError - # exception is raised. This argument is similar (but not exactly the - # same!) to the _limit_ argument in Marshal.dump. + # --- # - # The default options for the generator can be changed via the - # dump_default_options method. + # When argument +io+ is not given, returns the \JSON \String generated from +obj+: + # obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} + # json = JSON.dump(obj) + # json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}" # - # This method is part of the implementation of the load/dump interface of - # Marshal and YAML. + # When argument +io+ is given, writes the \JSON \String to +io+ and returns +io+: + # path = 't.json' + # File.open(path, 'w') do |file| + # JSON.dump(obj, file) + # end # => # + # 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) @@ -402,7 +649,7 @@ def dump(obj, anIO = nil, limit = nil) raise ArgumentError, "exceed depth limit" end - # Encodes string using Ruby's _String.encode_ + # Encodes string using String.encode. def self.iconv(to, from, string) string.encode(to, from) end diff --git a/ruby/ext/json/lib/json/version.rb b/ruby/ext/json/lib/json/version.rb index 9d781df87..35e8dd325 100644 --- a/ruby/ext/json/lib/json/version.rb +++ b/ruby/ext/json/lib/json/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module JSON # JSON version - VERSION = '2.3.0' + VERSION = '2.6.1' VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: diff --git a/ruby/ext/json/parser/depend b/ruby/ext/json/parser/depend index d0c9c2d2a..df261fdfb 100644 --- a/ruby/ext/json/parser/depend +++ b/ruby/ext/json/parser/depend @@ -7,9 +7,165 @@ parser.o: $(arch_hdrdir)/ruby/config.h parser.o: $(hdrdir)/ruby.h parser.o: $(hdrdir)/ruby/assert.h parser.o: $(hdrdir)/ruby/backward.h +parser.o: $(hdrdir)/ruby/backward/2/assume.h +parser.o: $(hdrdir)/ruby/backward/2/attributes.h +parser.o: $(hdrdir)/ruby/backward/2/bool.h +parser.o: $(hdrdir)/ruby/backward/2/inttypes.h +parser.o: $(hdrdir)/ruby/backward/2/limits.h +parser.o: $(hdrdir)/ruby/backward/2/long_long.h +parser.o: $(hdrdir)/ruby/backward/2/stdalign.h +parser.o: $(hdrdir)/ruby/backward/2/stdarg.h parser.o: $(hdrdir)/ruby/defines.h parser.o: $(hdrdir)/ruby/encoding.h parser.o: $(hdrdir)/ruby/intern.h +parser.o: $(hdrdir)/ruby/internal/anyargs.h +parser.o: $(hdrdir)/ruby/internal/arithmetic.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +parser.o: $(hdrdir)/ruby/internal/assume.h +parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +parser.o: $(hdrdir)/ruby/internal/attr/artificial.h +parser.o: $(hdrdir)/ruby/internal/attr/cold.h +parser.o: $(hdrdir)/ruby/internal/attr/const.h +parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h +parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h +parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +parser.o: $(hdrdir)/ruby/internal/attr/error.h +parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h +parser.o: $(hdrdir)/ruby/internal/attr/format.h +parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +parser.o: $(hdrdir)/ruby/internal/attr/noalias.h +parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h +parser.o: $(hdrdir)/ruby/internal/attr/noinline.h +parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h +parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h +parser.o: $(hdrdir)/ruby/internal/attr/pure.h +parser.o: $(hdrdir)/ruby/internal/attr/restrict.h +parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +parser.o: $(hdrdir)/ruby/internal/attr/warning.h +parser.o: $(hdrdir)/ruby/internal/attr/weakref.h +parser.o: $(hdrdir)/ruby/internal/cast.h +parser.o: $(hdrdir)/ruby/internal/compiler_is.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +parser.o: $(hdrdir)/ruby/internal/compiler_since.h +parser.o: $(hdrdir)/ruby/internal/config.h +parser.o: $(hdrdir)/ruby/internal/constant_p.h +parser.o: $(hdrdir)/ruby/internal/core.h +parser.o: $(hdrdir)/ruby/internal/core/rarray.h +parser.o: $(hdrdir)/ruby/internal/core/rbasic.h +parser.o: $(hdrdir)/ruby/internal/core/rbignum.h +parser.o: $(hdrdir)/ruby/internal/core/rclass.h +parser.o: $(hdrdir)/ruby/internal/core/rdata.h +parser.o: $(hdrdir)/ruby/internal/core/rfile.h +parser.o: $(hdrdir)/ruby/internal/core/rhash.h +parser.o: $(hdrdir)/ruby/internal/core/robject.h +parser.o: $(hdrdir)/ruby/internal/core/rregexp.h +parser.o: $(hdrdir)/ruby/internal/core/rstring.h +parser.o: $(hdrdir)/ruby/internal/core/rstruct.h +parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +parser.o: $(hdrdir)/ruby/internal/ctype.h +parser.o: $(hdrdir)/ruby/internal/dllexport.h +parser.o: $(hdrdir)/ruby/internal/dosish.h +parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h +parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h +parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h +parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h +parser.o: $(hdrdir)/ruby/internal/encoding/re.h +parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +parser.o: $(hdrdir)/ruby/internal/encoding/string.h +parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h +parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h +parser.o: $(hdrdir)/ruby/internal/error.h +parser.o: $(hdrdir)/ruby/internal/eval.h +parser.o: $(hdrdir)/ruby/internal/event.h +parser.o: $(hdrdir)/ruby/internal/fl_type.h +parser.o: $(hdrdir)/ruby/internal/gc.h +parser.o: $(hdrdir)/ruby/internal/glob.h +parser.o: $(hdrdir)/ruby/internal/globals.h +parser.o: $(hdrdir)/ruby/internal/has/attribute.h +parser.o: $(hdrdir)/ruby/internal/has/builtin.h +parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h +parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +parser.o: $(hdrdir)/ruby/internal/has/extension.h +parser.o: $(hdrdir)/ruby/internal/has/feature.h +parser.o: $(hdrdir)/ruby/internal/has/warning.h +parser.o: $(hdrdir)/ruby/internal/intern/array.h +parser.o: $(hdrdir)/ruby/internal/intern/bignum.h +parser.o: $(hdrdir)/ruby/internal/intern/class.h +parser.o: $(hdrdir)/ruby/internal/intern/compar.h +parser.o: $(hdrdir)/ruby/internal/intern/complex.h +parser.o: $(hdrdir)/ruby/internal/intern/cont.h +parser.o: $(hdrdir)/ruby/internal/intern/dir.h +parser.o: $(hdrdir)/ruby/internal/intern/enum.h +parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h +parser.o: $(hdrdir)/ruby/internal/intern/error.h +parser.o: $(hdrdir)/ruby/internal/intern/eval.h +parser.o: $(hdrdir)/ruby/internal/intern/file.h +parser.o: $(hdrdir)/ruby/internal/intern/gc.h +parser.o: $(hdrdir)/ruby/internal/intern/hash.h +parser.o: $(hdrdir)/ruby/internal/intern/io.h +parser.o: $(hdrdir)/ruby/internal/intern/load.h +parser.o: $(hdrdir)/ruby/internal/intern/marshal.h +parser.o: $(hdrdir)/ruby/internal/intern/numeric.h +parser.o: $(hdrdir)/ruby/internal/intern/object.h +parser.o: $(hdrdir)/ruby/internal/intern/parse.h +parser.o: $(hdrdir)/ruby/internal/intern/proc.h +parser.o: $(hdrdir)/ruby/internal/intern/process.h +parser.o: $(hdrdir)/ruby/internal/intern/random.h +parser.o: $(hdrdir)/ruby/internal/intern/range.h +parser.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h +parser.o: $(hdrdir)/ruby/internal/intern/string.h +parser.o: $(hdrdir)/ruby/internal/intern/struct.h +parser.o: $(hdrdir)/ruby/internal/intern/thread.h +parser.o: $(hdrdir)/ruby/internal/intern/time.h +parser.o: $(hdrdir)/ruby/internal/intern/variable.h +parser.o: $(hdrdir)/ruby/internal/intern/vm.h +parser.o: $(hdrdir)/ruby/internal/interpreter.h +parser.o: $(hdrdir)/ruby/internal/iterator.h +parser.o: $(hdrdir)/ruby/internal/memory.h +parser.o: $(hdrdir)/ruby/internal/method.h +parser.o: $(hdrdir)/ruby/internal/module.h +parser.o: $(hdrdir)/ruby/internal/newobj.h +parser.o: $(hdrdir)/ruby/internal/rgengc.h +parser.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +parser.o: $(hdrdir)/ruby/internal/value.h +parser.o: $(hdrdir)/ruby/internal/value_type.h +parser.o: $(hdrdir)/ruby/internal/variable.h +parser.o: $(hdrdir)/ruby/internal/warning_push.h +parser.o: $(hdrdir)/ruby/internal/xmalloc.h parser.o: $(hdrdir)/ruby/missing.h parser.o: $(hdrdir)/ruby/onigmo.h parser.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/json/parser/extconf.rb b/ruby/ext/json/parser/extconf.rb index f7360d46b..feb586e1b 100644 --- a/ruby/ext/json/parser/extconf.rb +++ b/ruby/ext/json/parser/extconf.rb @@ -2,5 +2,31 @@ require 'mkmf' have_func("rb_enc_raise", "ruby.h") +have_func("rb_enc_interned_str", "ruby.h") + +# 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 + +# 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 ' +end create_makefile 'json/ext/parser' diff --git a/ruby/ext/json/parser/parser.c b/ruby/ext/json/parser/parser.c index 0f98cf982..b1dc8810c 100644 --- a/ruby/ext/json/parser/parser.c +++ b/ruby/ext/json/parser/parser.c @@ -9,14 +9,14 @@ static void enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) { - va_list args; - VALUE mesg; + va_list args; + VALUE mesg; - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); + va_start(args, fmt); + mesg = rb_enc_vsprintf(enc, fmt, args); + va_end(args); - rb_exc_raise(rb_exc_new3(exc, mesg)); + rb_exc_raise(rb_exc_new3(exc, mesg)); } # define rb_enc_raise enc_raise # endif @@ -28,2109 +28,3311 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) /* 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 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -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; + 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; + 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 VALUE cBigDecimal = Qundef; 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_BigDecimal; +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; -#line 126 "parser.rl" +#line 125 "parser.rl" -#line 108 "parser.c" enum {JSON_object_start = 1}; enum {JSON_object_first_final = 27}; enum {JSON_object_error = 0}; enum {JSON_object_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_object_nfa_targs)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_object_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 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 char MAYBE_UNUSED(_JSON_object_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_object_nfa_pop_trans)[] = { + 0, 0 +}; + #line 167 "parser.rl" 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; + 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); - } + 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); + *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); -#line 132 "parser.c" { - cs = JSON_object_start; + cs = (int)JSON_object_start; } -#line 182 "parser.rl" + #line 182 "parser.rl" + -#line 139 "parser.c" { - if ( p == pe ) + 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 ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 7: + goto st_case_7; + case 8: + goto st_case_8; + case 9: + goto st_case_9; + case 10: + goto st_case_10; + case 11: + goto st_case_11; + case 12: + goto st_case_12; + case 13: + goto st_case_13; + case 14: + goto st_case_14; + case 15: + goto st_case_15; + case 16: + goto st_case_16; + case 17: + goto st_case_17; + case 18: + goto st_case_18; + case 27: + goto st_case_27; + case 19: + goto st_case_19; + case 20: + goto st_case_20; + case 21: + goto st_case_21; + case 22: + goto st_case_22; + case 23: + goto st_case_23; + case 24: + goto st_case_24; + case 25: + goto st_case_25; + case 26: + goto st_case_26; + } + goto st_out; + st_case_1: + if ( ( (*( p))) == 123 ) { + goto st2; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + st2: + p+= 1; + 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 180 "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 ) + st_case_2: + switch( ( (*( p))) ) { + case 13: { + goto st2; + } + case 32: { + goto st2; + } + case 34: { + goto ctr2; + } + case 47: { + goto st23; + } + case 125: { + goto ctr4; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st2; + } + { + goto st0; + } + ctr2: + { + #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 - 1; } {p+= 1; cs = 3; goto _out;} } else {p = (( np))-1;} + + } + goto st3; - goto st0; -st4: - if ( ++p == pe ) + st3: + p+= 1; + if ( p == pe ) + goto _test_eof3; + st_case_3: + 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: + p+= 1; + if ( p == pe ) goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st5; - case 47: goto st7; - } - goto st0; -st5: - if ( ++p == pe ) + st_case_4: + switch( ( (*( p))) ) { + case 42: { + goto st5; + } + case 47: { + goto st7; + } + } + { + goto st0; + } + st5: + p+= 1; + if ( p == pe ) goto _test_eof5; -case 5: - if ( (*p) == 42 ) - goto st6; - goto st5; -st6: - if ( ++p == pe ) + st_case_5: + if ( ( (*( p))) == 42 ) { + goto st6; + } + { + goto st5; + } + st6: + p+= 1; + if ( p == pe ) goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st6; - case 47: goto st3; - } - goto st5; -st7: - if ( ++p == pe ) + st_case_6: + switch( ( (*( p))) ) { + case 42: { + goto st6; + } + case 47: { + goto st3; + } + } + { + goto st5; + } + st7: + p+= 1; + if ( p == pe ) goto _test_eof7; -case 7: - if ( (*p) == 10 ) - goto st3; - goto st7; -st8: - if ( ++p == pe ) + st_case_7: + if ( ( (*( p))) == 10 ) { + goto st3; + } + { + goto st7; + } + st8: + p+= 1; + 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 134 "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)) { - 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 ) + st_case_8: + switch( ( (*( p))) ) { + case 13: { + goto st8; + } + case 32: { + goto st8; + } + case 34: { + goto ctr11; + } + case 45: { + goto ctr11; + } + case 47: { + goto st19; + } + case 73: { + goto ctr11; + } + case 78: { + goto ctr11; + } + case 91: { + goto ctr11; + } + case 102: { + goto ctr11; + } + case 110: { + goto ctr11; + } + case 116: { + goto ctr11; + } + case 123: { + goto ctr11; + } + } + if ( ( (*( p))) > 10 ) { + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto ctr11; + } + } else if ( ( (*( p))) >= 9 ) { + goto st8; + } + { + goto st0; + } + ctr11: + { + #line 133 "parser.rl" + + VALUE v = Qnil; + char *np = JSON_parse_value(json, p, pe, &v, current_nesting); + if (np == NULL) { + {p = p - 1; } {p+= 1; 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; - goto st0; -st10: - if ( ++p == pe ) + st9: + p+= 1; + if ( p == pe ) + goto _test_eof9; + st_case_9: + switch( ( (*( p))) ) { + case 13: { + goto st9; + } + case 32: { + goto st9; + } + case 44: { + goto st10; + } + case 47: { + goto st15; + } + case 125: { + goto ctr4; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st9; + } + { + goto st0; + } + st10: + p+= 1; + 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 ) + st_case_10: + switch( ( (*( p))) ) { + case 13: { + goto st10; + } + case 32: { + goto st10; + } + case 34: { + goto ctr2; + } + case 47: { + goto st11; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st10; + } + { + goto st0; + } + st11: + p+= 1; + if ( p == pe ) goto _test_eof11; -case 11: - switch( (*p) ) { - case 42: goto st12; - case 47: goto st14; - } - goto st0; -st12: - if ( ++p == pe ) + st_case_11: + switch( ( (*( p))) ) { + case 42: { + goto st12; + } + case 47: { + goto st14; + } + } + { + goto st0; + } + st12: + p+= 1; + if ( p == pe ) goto _test_eof12; -case 12: - if ( (*p) == 42 ) - goto st13; - goto st12; -st13: - if ( ++p == pe ) + st_case_12: + if ( ( (*( p))) == 42 ) { + goto st13; + } + { + goto st12; + } + st13: + p+= 1; + if ( p == pe ) goto _test_eof13; -case 13: - switch( (*p) ) { - case 42: goto st13; - case 47: goto st10; - } - goto st12; -st14: - if ( ++p == pe ) + st_case_13: + switch( ( (*( p))) ) { + case 42: { + goto st13; + } + case 47: { + goto st10; + } + } + { + goto st12; + } + st14: + p+= 1; + if ( p == pe ) goto _test_eof14; -case 14: - if ( (*p) == 10 ) - goto st10; - goto st14; -st15: - if ( ++p == pe ) + st_case_14: + if ( ( (*( p))) == 10 ) { + goto st10; + } + { + goto st14; + } + st15: + p+= 1; + if ( p == pe ) goto _test_eof15; -case 15: - switch( (*p) ) { - case 42: goto st16; - case 47: goto st18; - } - goto st0; -st16: - if ( ++p == pe ) + st_case_15: + switch( ( (*( p))) ) { + case 42: { + goto st16; + } + case 47: { + goto st18; + } + } + { + goto st0; + } + st16: + p+= 1; + if ( p == pe ) goto _test_eof16; -case 16: - if ( (*p) == 42 ) - goto st17; - goto st16; -st17: - if ( ++p == pe ) + st_case_16: + if ( ( (*( p))) == 42 ) { + goto st17; + } + { + goto st16; + } + st17: + p+= 1; + if ( p == pe ) goto _test_eof17; -case 17: - switch( (*p) ) { - case 42: goto st17; - case 47: goto st9; - } - goto st16; -st18: - if ( ++p == pe ) + st_case_17: + switch( ( (*( p))) ) { + case 42: { + goto st17; + } + case 47: { + goto st9; + } + } + { + goto st16; + } + st18: + p+= 1; + 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 ) + st_case_18: + if ( ( (*( p))) == 10 ) { + goto st9; + } + { + goto st18; + } + ctr4: + { + #line 157 "parser.rl" + {p = p - 1; } {p+= 1; cs = 27; goto _out;} } + + goto st27; + st27: + p+= 1; + if ( p == pe ) goto _test_eof27; -case 27: -#line 363 "parser.c" - goto st0; -st19: - if ( ++p == pe ) + st_case_27: + { + goto st0; + } + st19: + p+= 1; + if ( p == pe ) goto _test_eof19; -case 19: - switch( (*p) ) { - case 42: goto st20; - case 47: goto st22; - } - goto st0; -st20: - if ( ++p == pe ) + st_case_19: + switch( ( (*( p))) ) { + case 42: { + goto st20; + } + case 47: { + goto st22; + } + } + { + goto st0; + } + st20: + p+= 1; + if ( p == pe ) goto _test_eof20; -case 20: - if ( (*p) == 42 ) - goto st21; - goto st20; -st21: - if ( ++p == pe ) + st_case_20: + if ( ( (*( p))) == 42 ) { + goto st21; + } + { + goto st20; + } + st21: + p+= 1; + if ( p == pe ) goto _test_eof21; -case 21: - switch( (*p) ) { - case 42: goto st21; - case 47: goto st8; - } - goto st20; -st22: - if ( ++p == pe ) + st_case_21: + switch( ( (*( p))) ) { + case 42: { + goto st21; + } + case 47: { + goto st8; + } + } + { + goto st20; + } + st22: + p+= 1; + if ( p == pe ) goto _test_eof22; -case 22: - if ( (*p) == 10 ) - goto st8; - goto st22; -st23: - if ( ++p == pe ) + st_case_22: + if ( ( (*( p))) == 10 ) { + goto st8; + } + { + goto st22; + } + st23: + p+= 1; + if ( p == pe ) goto _test_eof23; -case 23: - switch( (*p) ) { - case 42: goto st24; - case 47: goto st26; - } - goto st0; -st24: - if ( ++p == pe ) + st_case_23: + switch( ( (*( p))) ) { + case 42: { + goto st24; + } + case 47: { + goto st26; + } + } + { + goto st0; + } + st24: + p+= 1; + if ( p == pe ) goto _test_eof24; -case 24: - if ( (*p) == 42 ) - goto st25; - goto st24; -st25: - if ( ++p == pe ) + st_case_24: + if ( ( (*( p))) == 42 ) { + goto st25; + } + { + goto st24; + } + st25: + p+= 1; + if ( p == pe ) goto _test_eof25; -case 25: - switch( (*p) ) { - case 42: goto st25; - case 47: goto st2; - } - goto st24; -st26: - if ( ++p == pe ) + st_case_25: + switch( ( (*( p))) ) { + case 42: { + goto st25; + } + case 47: { + goto st2; + } + } + { + goto st24; + } + st26: + p+= 1; + 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: {} + st_case_26: + if ( ( (*( p))) == 10 ) { + goto st2; + } + { + goto st26; + } + st_out: + _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); + } + 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; } - -#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); - } - 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; - } } -#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}; +static const char MAYBE_UNUSED(_JSON_value_nfa_targs)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_value_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0, 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 char MAYBE_UNUSED(_JSON_value_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_value_nfa_pop_trans)[] = { + 0, 0 +}; + #line 283 "parser.rl" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { - int cs = EVIL; + int cs = EVIL; -#line 502 "parser.c" { - cs = JSON_value_start; + cs = (int)JSON_value_start; } -#line 290 "parser.rl" + #line 290 "parser.rl" + -#line 509 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { -st1: - if ( ++p == pe ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 29: + goto st_case_29; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 7: + goto st_case_7; + case 8: + goto st_case_8; + case 9: + goto st_case_9; + case 10: + goto st_case_10; + case 11: + goto st_case_11; + case 12: + goto st_case_12; + case 13: + goto st_case_13; + case 14: + goto st_case_14; + case 15: + goto st_case_15; + case 16: + goto st_case_16; + case 17: + goto st_case_17; + case 18: + goto st_case_18; + case 19: + goto st_case_19; + case 20: + goto st_case_20; + case 21: + goto st_case_21; + case 22: + goto st_case_22; + case 23: + goto st_case_23; + case 24: + goto st_case_24; + case 25: + goto st_case_25; + case 26: + goto st_case_26; + case 27: + goto st_case_27; + case 28: + goto st_case_28; + } + goto st_out; + st1: + p+= 1; + 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, "%u: unexpected token at '%s'", __LINE__, p); - } - } - 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; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); - } - } - goto st29; -tr27: -#line 221 "parser.rl" - { - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); - } - } - goto st29; -tr31: -#line 215 "parser.rl" - { - *result = Qfalse; - } - goto st29; -tr34: -#line 212 "parser.rl" - { - *result = Qnil; - } - goto st29; -tr37: -#line 218 "parser.rl" - { - *result = Qtrue; - } - 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 ) + st_case_1: + switch( ( (*( p))) ) { + case 13: { + goto st1; + } + case 32: { + goto st1; + } + case 34: { + goto ctr2; + } + case 45: { + goto ctr3; + } + case 47: { + goto st6; + } + case 73: { + goto st10; + } + case 78: { + goto st17; + } + case 91: { + goto ctr7; + } + case 102: { + goto st19; + } + case 110: { + goto st23; + } + case 116: { + goto st26; + } + case 123: { + goto ctr11; + } + } + if ( ( (*( p))) > 10 ) { + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto ctr3; + } + } else if ( ( (*( p))) >= 9 ) { + goto st1; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + ctr2: + { + #line 235 "parser.rl" + + char *np = JSON_parse_string(json, p, pe, result); + if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} + + } + goto st29; - goto st0; -st2: - if ( ++p == pe ) + ctr3: + { + #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 - 1; } {p+= 1; cs = 29; goto _out;} + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + } + } + 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 - 1; } {p+= 1; cs = 29; goto _out;} + } + + goto st29; + ctr7: + { + #line 258 "parser.rl" + + char *np; + np = JSON_parse_array(json, p, pe, result, current_nesting + 1); + if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} + + } + + goto st29; + ctr11: + { + #line 264 "parser.rl" + + char *np; + np = JSON_parse_object(json, p, pe, result, current_nesting + 1); + if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} + + } + + goto st29; + ctr25: + { + #line 228 "parser.rl" + + if (json->allow_nan) { + *result = CInfinity; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); + } + } + + goto st29; + ctr27: + { + #line 221 "parser.rl" + + if (json->allow_nan) { + *result = CNaN; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); + } + } + + goto st29; + ctr31: + { + #line 215 "parser.rl" + + *result = Qfalse; + } + + goto st29; + ctr34: + { + #line 212 "parser.rl" + + *result = Qnil; + } + + goto st29; + ctr37: + { + #line 218 "parser.rl" + + *result = Qtrue; + } + + goto st29; + st29: + p+= 1; + if ( p == pe ) + goto _test_eof29; + st_case_29: + { + #line 270 "parser.rl" + {p = p - 1; } {p+= 1; cs = 29; goto _out;} } + switch( ( (*( p))) ) { + case 13: { + goto st29; + } + case 32: { + goto st29; + } + case 47: { + goto st2; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st29; + } + { + goto st0; + } + st2: + p+= 1; + if ( p == pe ) goto _test_eof2; -case 2: - switch( (*p) ) { - case 42: goto st3; - case 47: goto st5; - } - goto st0; -st3: - if ( ++p == pe ) + st_case_2: + switch( ( (*( p))) ) { + case 42: { + goto st3; + } + case 47: { + goto st5; + } + } + { + goto st0; + } + st3: + p+= 1; + if ( p == pe ) goto _test_eof3; -case 3: - if ( (*p) == 42 ) - goto st4; - goto st3; -st4: - if ( ++p == pe ) + st_case_3: + if ( ( (*( p))) == 42 ) { + goto st4; + } + { + goto st3; + } + st4: + p+= 1; + if ( p == pe ) goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st4; - case 47: goto st29; - } - goto st3; -st5: - if ( ++p == pe ) + st_case_4: + switch( ( (*( p))) ) { + case 42: { + goto st4; + } + case 47: { + goto st29; + } + } + { + goto st3; + } + st5: + p+= 1; + if ( p == pe ) goto _test_eof5; -case 5: - if ( (*p) == 10 ) - goto st29; - goto st5; -st6: - if ( ++p == pe ) + st_case_5: + if ( ( (*( p))) == 10 ) { + goto st29; + } + { + goto st5; + } + st6: + p+= 1; + if ( p == pe ) goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st9; - } - goto st0; -st7: - if ( ++p == pe ) + st_case_6: + switch( ( (*( p))) ) { + case 42: { + goto st7; + } + case 47: { + goto st9; + } + } + { + goto st0; + } + st7: + p+= 1; + if ( p == pe ) goto _test_eof7; -case 7: - if ( (*p) == 42 ) - goto st8; - goto st7; -st8: - if ( ++p == pe ) + st_case_7: + if ( ( (*( p))) == 42 ) { + goto st8; + } + { + goto st7; + } + st8: + p+= 1; + if ( p == pe ) goto _test_eof8; -case 8: - switch( (*p) ) { - case 42: goto st8; - case 47: goto st1; - } - goto st7; -st9: - if ( ++p == pe ) + st_case_8: + switch( ( (*( p))) ) { + case 42: { + goto st8; + } + case 47: { + goto st1; + } + } + { + goto st7; + } + st9: + p+= 1; + if ( p == pe ) goto _test_eof9; -case 9: - if ( (*p) == 10 ) - goto st1; - goto st9; -st10: - if ( ++p == pe ) + st_case_9: + if ( ( (*( p))) == 10 ) { + goto st1; + } + { + goto st9; + } + st10: + p+= 1; + if ( p == pe ) goto _test_eof10; -case 10: - if ( (*p) == 110 ) - goto st11; - goto st0; -st11: - if ( ++p == pe ) + st_case_10: + if ( ( (*( p))) == 110 ) { + goto st11; + } + { + goto st0; + } + st11: + p+= 1; + if ( p == pe ) goto _test_eof11; -case 11: - if ( (*p) == 102 ) - goto st12; - goto st0; -st12: - if ( ++p == pe ) + st_case_11: + if ( ( (*( p))) == 102 ) { + goto st12; + } + { + goto st0; + } + st12: + p+= 1; + if ( p == pe ) goto _test_eof12; -case 12: - if ( (*p) == 105 ) - goto st13; - goto st0; -st13: - if ( ++p == pe ) + st_case_12: + if ( ( (*( p))) == 105 ) { + goto st13; + } + { + goto st0; + } + st13: + p+= 1; + if ( p == pe ) goto _test_eof13; -case 13: - if ( (*p) == 110 ) - goto st14; - goto st0; -st14: - if ( ++p == pe ) + st_case_13: + if ( ( (*( p))) == 110 ) { + goto st14; + } + { + goto st0; + } + st14: + p+= 1; + if ( p == pe ) goto _test_eof14; -case 14: - if ( (*p) == 105 ) - goto st15; - goto st0; -st15: - if ( ++p == pe ) + st_case_14: + if ( ( (*( p))) == 105 ) { + goto st15; + } + { + goto st0; + } + st15: + p+= 1; + if ( p == pe ) goto _test_eof15; -case 15: - if ( (*p) == 116 ) - goto st16; - goto st0; -st16: - if ( ++p == pe ) + st_case_15: + if ( ( (*( p))) == 116 ) { + goto st16; + } + { + goto st0; + } + st16: + p+= 1; + if ( p == pe ) goto _test_eof16; -case 16: - if ( (*p) == 121 ) - goto tr25; - goto st0; -st17: - if ( ++p == pe ) + st_case_16: + if ( ( (*( p))) == 121 ) { + goto ctr25; + } + { + goto st0; + } + st17: + p+= 1; + if ( p == pe ) goto _test_eof17; -case 17: - if ( (*p) == 97 ) - goto st18; - goto st0; -st18: - if ( ++p == pe ) + st_case_17: + if ( ( (*( p))) == 97 ) { + goto st18; + } + { + goto st0; + } + st18: + p+= 1; + if ( p == pe ) goto _test_eof18; -case 18: - if ( (*p) == 78 ) - goto tr27; - goto st0; -st19: - if ( ++p == pe ) + st_case_18: + if ( ( (*( p))) == 78 ) { + goto ctr27; + } + { + goto st0; + } + st19: + p+= 1; + if ( p == pe ) goto _test_eof19; -case 19: - if ( (*p) == 97 ) - goto st20; - goto st0; -st20: - if ( ++p == pe ) + st_case_19: + if ( ( (*( p))) == 97 ) { + goto st20; + } + { + goto st0; + } + st20: + p+= 1; + if ( p == pe ) goto _test_eof20; -case 20: - if ( (*p) == 108 ) - goto st21; - goto st0; -st21: - if ( ++p == pe ) + st_case_20: + if ( ( (*( p))) == 108 ) { + goto st21; + } + { + goto st0; + } + st21: + p+= 1; + if ( p == pe ) goto _test_eof21; -case 21: - if ( (*p) == 115 ) - goto st22; - goto st0; -st22: - if ( ++p == pe ) + st_case_21: + if ( ( (*( p))) == 115 ) { + goto st22; + } + { + goto st0; + } + st22: + p+= 1; + if ( p == pe ) goto _test_eof22; -case 22: - if ( (*p) == 101 ) - goto tr31; - goto st0; -st23: - if ( ++p == pe ) + st_case_22: + if ( ( (*( p))) == 101 ) { + goto ctr31; + } + { + goto st0; + } + st23: + p+= 1; + if ( p == pe ) goto _test_eof23; -case 23: - if ( (*p) == 117 ) - goto st24; - goto st0; -st24: - if ( ++p == pe ) + st_case_23: + if ( ( (*( p))) == 117 ) { + goto st24; + } + { + goto st0; + } + st24: + p+= 1; + if ( p == pe ) goto _test_eof24; -case 24: - if ( (*p) == 108 ) - goto st25; - goto st0; -st25: - if ( ++p == pe ) + st_case_24: + if ( ( (*( p))) == 108 ) { + goto st25; + } + { + goto st0; + } + st25: + p+= 1; + if ( p == pe ) goto _test_eof25; -case 25: - if ( (*p) == 108 ) - goto tr34; - goto st0; -st26: - if ( ++p == pe ) + st_case_25: + if ( ( (*( p))) == 108 ) { + goto ctr34; + } + { + goto st0; + } + st26: + p+= 1; + if ( p == pe ) goto _test_eof26; -case 26: - if ( (*p) == 114 ) - goto st27; - goto st0; -st27: - if ( ++p == pe ) + st_case_26: + if ( ( (*( p))) == 114 ) { + goto st27; + } + { + goto st0; + } + st27: + p+= 1; + if ( p == pe ) goto _test_eof27; -case 27: - if ( (*p) == 117 ) - goto st28; - goto st0; -st28: - if ( ++p == pe ) + st_case_27: + if ( ( (*( p))) == 117 ) { + goto st28; + } + { + goto st0; + } + st28: + p+= 1; + 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: {} + st_case_28: + if ( ( (*( p))) == 101 ) { + goto ctr37; + } + { + goto st0; + } + st_out: + _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); + } + + if (cs >= JSON_value_first_final) { + return p; + } else { + return NULL; } - -#line 291 "parser.rl" - - if (cs >= JSON_value_first_final) { - return p; - } else { - return NULL; - } } -#line 880 "parser.c" enum {JSON_integer_start = 1}; enum {JSON_integer_first_final = 3}; enum {JSON_integer_error = 0}; enum {JSON_integer_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_integer_nfa_targs)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_integer_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_integer_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_integer_nfa_pop_trans)[] = { + 0, 0 +}; -#line 307 "parser.rl" + +#line 311 "parser.rl" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; -#line 896 "parser.c" { - cs = JSON_integer_start; + cs = (int)JSON_integer_start; } -#line 314 "parser.rl" - json->memo = p; + #line 318 "parser.rl" + + json->memo = p; -#line 904 "parser.c" { - if ( p == pe ) + 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 ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + } + goto st_out; + st_case_1: + switch( ( (*( p))) ) { + case 45: { + goto st2; + } + case 48: { + goto st3; + } + } + if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st5; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + st2: + p+= 1; + 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 ) + st_case_2: + if ( ( (*( p))) == 48 ) { + goto st3; + } + if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st5; + } + { + goto st0; + } + st3: + p+= 1; + if ( p == pe ) goto _test_eof3; -case 3: - if ( 48 <= (*p) && (*p) <= 57 ) - goto st0; - goto tr4; -tr4: -#line 304 "parser.rl" - { p--; {p++; cs = 4; goto _out;} } - goto st4; -st4: - if ( ++p == pe ) + st_case_3: + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st0; + } + { + goto ctr4; + } + ctr4: + { + #line 308 "parser.rl" + {p = p - 1; } {p+= 1; cs = 4; goto _out;} } + + goto st4; + st4: + p+= 1; + if ( p == pe ) goto _test_eof4; -case 4: -#line 945 "parser.c" - goto st0; -st5: - if ( ++p == pe ) + st_case_4: + { + goto st0; + } + st5: + p+= 1; + 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; + st_case_5: + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st5; + } + { + goto ctr4; + } + st_out: + _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: {} + _test_eof: {} + _out: {} } -#line 316 "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; - } else { - return NULL; - } + #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; + } else { + return NULL; + } } -#line 979 "parser.c" enum {JSON_float_start = 1}; enum {JSON_float_first_final = 8}; enum {JSON_float_error = 0}; enum {JSON_float_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_float_nfa_targs)[] = { + 0, 0 +}; -#line 341 "parser.rl" +static const char MAYBE_UNUSED(_JSON_float_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static const char MAYBE_UNUSED(_JSON_float_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_float_nfa_pop_trans)[] = { + 0, 0 +}; + + +#line 345 "parser.rl" -static int is_bigdecimal_class(VALUE obj) -{ - if (cBigDecimal == Qundef) { - if (rb_const_defined(rb_cObject, i_BigDecimal)) { - cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal); - } - else { - return 0; - } - } - return obj == cBigDecimal; -} static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; -#line 1008 "parser.c" { - cs = JSON_float_start; + cs = (int)JSON_float_start; } -#line 361 "parser.rl" - json->memo = p; + #line 352 "parser.rl" + + json->memo = p; -#line 1016 "parser.c" { - if ( p == pe ) + 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 ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 8: + goto st_case_8; + case 9: + goto st_case_9; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 10: + goto st_case_10; + case 7: + goto st_case_7; + } + goto st_out; + st_case_1: + switch( ( (*( p))) ) { + case 45: { + goto st2; + } + case 48: { + goto st3; + } + } + if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st7; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + st2: + p+= 1; + 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 ) + st_case_2: + if ( ( (*( p))) == 48 ) { + goto st3; + } + if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st7; + } + { + goto st0; + } + st3: + p+= 1; + 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 ) + st_case_3: + switch( ( (*( p))) ) { + case 46: { + goto st4; + } + case 69: { + goto st5; + } + case 101: { + goto st5; + } + } + { + goto st0; + } + st4: + p+= 1; + 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 ) + st_case_4: + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { goto st8; - } else if ( (*p) >= 45 ) - goto st0; - goto tr9; -tr9: -#line 335 "parser.rl" - { p--; {p++; cs = 9; goto _out;} } - goto st9; -st9: - if ( ++p == pe ) + } + { + goto st0; + } + st8: + p+= 1; + if ( p == pe ) + goto _test_eof8; + st_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 ctr9; + } + ctr9: + { + #line 339 "parser.rl" + {p = p - 1; } {p+= 1; cs = 9; goto _out;} } + + goto st9; + st9: + p+= 1; + if ( p == pe ) goto _test_eof9; -case 9: -#line 1081 "parser.c" - goto st0; -st5: - if ( ++p == pe ) + st_case_9: + { + goto st0; + } + st5: + p+= 1; + 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 ) + st_case_5: + switch( ( (*( p))) ) { + case 43: { + goto st6; + } + case 45: { + goto st6; + } + } + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto st10; + } + { + goto st0; + } + st6: + p+= 1; + 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 ) + st_case_6: + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { goto st10; - } else if ( (*p) >= 45 ) - goto st0; - goto tr9; -st7: - if ( ++p == pe ) + } + { + goto st0; + } + st10: + p+= 1; + if ( p == pe ) + goto _test_eof10; + st_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 ctr9; + } + st7: + p+= 1; + 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: {} + st_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; + } + st_out: + _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)); + } + } + + 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; } - -#line 363 "parser.rl" - - if (cs >= JSON_float_first_final) { - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - if (NIL_P(json->decimal_class)) { - *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); - } else { - VALUE text; - text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); - if (is_bigdecimal_class(json->decimal_class)) { - *result = rb_funcall(Qnil, i_BigDecimal, 1, text); - } else { - *result = rb_funcall(json->decimal_class, i_new, 1, text); - } - } - return p + 1; - } else { - return NULL; - } } -#line 1168 "parser.c" enum {JSON_array_start = 1}; enum {JSON_array_first_final = 17}; enum {JSON_array_error = 0}; enum {JSON_array_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_array_nfa_targs)[] = { + 0, 0 +}; -#line 416 "parser.rl" +static const char MAYBE_UNUSED(_JSON_array_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_array_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_array_nfa_pop_trans)[] = { + 0, 0 +}; + + +#line 432 "parser.rl" 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; + 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); + 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 1190 "parser.c" { - cs = JSON_array_start; + cs = (int)JSON_array_start; } -#line 429 "parser.rl" + #line 445 "parser.rl" + -#line 1197 "parser.c" { - if ( p == pe ) + 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 ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 7: + goto st_case_7; + case 8: + goto st_case_8; + case 9: + goto st_case_9; + case 10: + goto st_case_10; + case 11: + goto st_case_11; + case 12: + goto st_case_12; + case 17: + goto st_case_17; + case 13: + goto st_case_13; + case 14: + goto st_case_14; + case 15: + goto st_case_15; + case 16: + goto st_case_16; + } + goto st_out; + st_case_1: + if ( ( (*( p))) == 91 ) { + goto st2; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + st2: + p+= 1; + 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 393 "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); - } - {p = (( np))-1;} - } - } - goto st3; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: -#line 1256 "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 ) + st_case_2: + switch( ( (*( p))) ) { + case 13: { + goto st2; + } + case 32: { + goto st2; + } + case 34: { + goto ctr2; + } + case 45: { + goto ctr2; + } + case 47: { + goto st13; + } + case 73: { + goto ctr2; + } + case 78: { + goto ctr2; + } + case 91: { + goto ctr2; + } + case 93: { + goto ctr4; + } + case 102: { + goto ctr2; + } + case 110: { + goto ctr2; + } + case 116: { + goto ctr2; + } + case 123: { + goto ctr2; + } + } + if ( ( (*( p))) > 10 ) { + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto ctr2; + } + } else if ( ( (*( p))) >= 9 ) { + goto st2; + } + { + goto st0; + } + ctr2: + { + #line 409 "parser.rl" + + VALUE v = Qnil; + char *np = JSON_parse_value(json, p, pe, &v, current_nesting); + if (np == NULL) { + {p = p - 1; } {p+= 1; cs = 3; goto _out;} + } else { + if (NIL_P(json->array_class)) { + rb_ary_push(*result, v); + } else { + rb_funcall(*result, i_leftshift, 1, v); + } + {p = (( np))-1;} + + } + } + goto st3; - goto st0; -st4: - if ( ++p == pe ) + st3: + p+= 1; + if ( p == pe ) + goto _test_eof3; + st_case_3: + switch( ( (*( p))) ) { + case 13: { + goto st3; + } + case 32: { + goto st3; + } + case 44: { + goto st4; + } + case 47: { + goto st9; + } + case 93: { + goto ctr4; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st3; + } + { + goto st0; + } + st4: + p+= 1; + 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 ) + st_case_4: + switch( ( (*( p))) ) { + case 13: { + goto st4; + } + case 32: { + goto st4; + } + case 34: { + goto ctr2; + } + case 45: { + goto ctr2; + } + case 47: { + goto st5; + } + case 73: { + goto ctr2; + } + case 78: { + goto ctr2; + } + case 91: { + goto ctr2; + } + case 102: { + goto ctr2; + } + case 110: { + goto ctr2; + } + case 116: { + goto ctr2; + } + case 123: { + goto ctr2; + } + } + if ( ( (*( p))) > 10 ) { + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto ctr2; + } + } else if ( ( (*( p))) >= 9 ) { + goto st4; + } + { + goto st0; + } + st5: + p+= 1; + if ( p == pe ) goto _test_eof5; -case 5: - switch( (*p) ) { - case 42: goto st6; - case 47: goto st8; - } - goto st0; -st6: - if ( ++p == pe ) + st_case_5: + switch( ( (*( p))) ) { + case 42: { + goto st6; + } + case 47: { + goto st8; + } + } + { + goto st0; + } + st6: + p+= 1; + if ( p == pe ) goto _test_eof6; -case 6: - if ( (*p) == 42 ) - goto st7; - goto st6; -st7: - if ( ++p == pe ) + st_case_6: + if ( ( (*( p))) == 42 ) { + goto st7; + } + { + goto st6; + } + st7: + p+= 1; + if ( p == pe ) goto _test_eof7; -case 7: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st4; - } - goto st6; -st8: - if ( ++p == pe ) + st_case_7: + switch( ( (*( p))) ) { + case 42: { + goto st7; + } + case 47: { + goto st4; + } + } + { + goto st6; + } + st8: + p+= 1; + if ( p == pe ) goto _test_eof8; -case 8: - if ( (*p) == 10 ) - goto st4; - goto st8; -st9: - if ( ++p == pe ) + st_case_8: + if ( ( (*( p))) == 10 ) { + goto st4; + } + { + goto st8; + } + st9: + p+= 1; + if ( p == pe ) goto _test_eof9; -case 9: - switch( (*p) ) { - case 42: goto st10; - case 47: goto st12; - } - goto st0; -st10: - if ( ++p == pe ) + st_case_9: + switch( ( (*( p))) ) { + case 42: { + goto st10; + } + case 47: { + goto st12; + } + } + { + goto st0; + } + st10: + p+= 1; + if ( p == pe ) goto _test_eof10; -case 10: - if ( (*p) == 42 ) - goto st11; - goto st10; -st11: - if ( ++p == pe ) + st_case_10: + if ( ( (*( p))) == 42 ) { + goto st11; + } + { + goto st10; + } + st11: + p+= 1; + if ( p == pe ) goto _test_eof11; -case 11: - switch( (*p) ) { - case 42: goto st11; - case 47: goto st3; - } - goto st10; -st12: - if ( ++p == pe ) + st_case_11: + switch( ( (*( p))) ) { + case 42: { + goto st11; + } + case 47: { + goto st3; + } + } + { + goto st10; + } + st12: + p+= 1; + if ( p == pe ) goto _test_eof12; -case 12: - if ( (*p) == 10 ) - goto st3; - goto st12; -tr4: -#line 408 "parser.rl" - { p--; {p++; cs = 17; goto _out;} } - goto st17; -st17: - if ( ++p == pe ) + st_case_12: + if ( ( (*( p))) == 10 ) { + goto st3; + } + { + goto st12; + } + ctr4: + { + #line 424 "parser.rl" + {p = p - 1; } {p+= 1; cs = 17; goto _out;} } + + goto st17; + st17: + p+= 1; + if ( p == pe ) goto _test_eof17; -case 17: -#line 1363 "parser.c" - goto st0; -st13: - if ( ++p == pe ) + st_case_17: + { + goto st0; + } + st13: + p+= 1; + if ( p == pe ) goto _test_eof13; -case 13: - switch( (*p) ) { - case 42: goto st14; - case 47: goto st16; - } - goto st0; -st14: - if ( ++p == pe ) + st_case_13: + switch( ( (*( p))) ) { + case 42: { + goto st14; + } + case 47: { + goto st16; + } + } + { + goto st0; + } + st14: + p+= 1; + if ( p == pe ) goto _test_eof14; -case 14: - if ( (*p) == 42 ) - goto st15; - goto st14; -st15: - if ( ++p == pe ) + st_case_14: + if ( ( (*( p))) == 42 ) { + goto st15; + } + { + goto st14; + } + st15: + p+= 1; + if ( p == pe ) goto _test_eof15; -case 15: - switch( (*p) ) { - case 42: goto st15; - case 47: goto st2; - } - goto st14; -st16: - if ( ++p == pe ) + st_case_15: + switch( ( (*( p))) ) { + case 42: { + goto st15; + } + case 47: { + goto st2; + } + } + { + goto st14; + } + st16: + p+= 1; + 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: {} + st_case_16: + if ( ( (*( p))) == 10 ) { + goto st2; + } + { + goto st16; + } + st_out: + _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, "%u: unexpected token at '%s'", __LINE__, p); + return NULL; } - -#line 430 "parser.rl" - - if(cs >= JSON_array_first_final) { - return p + 1; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); - return NULL; - } } -static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) +static const size_t MAX_STACK_BUFFER_SIZE = 128; +static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) { - char *p = string, *pe = string, *unescape; - int unescape_len; - char buf[4]; - - while (pe < stringEnd) { - if (*pe == '\\') { - unescape = (char *) "?"; - unescape_len = 1; - if (pe > p) rb_str_buf_cat(result, p, 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) { - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p - ); - } else { - UTF32 ch = unescape_unicode((unsigned char *) ++pe); - pe += 3; - if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { - pe++; - if (pe > stringEnd - 6) { - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete surrogate pair at '%s'", __LINE__, 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; - } - rb_str_buf_cat(result, unescape, unescape_len); - p = ++pe; - } else { - pe++; - } - } - rb_str_buf_cat(result, p, pe - p); - return result; + 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) { + bufferStart = buffer = ALLOC_N(char, bufferSize); + } else { + bufferStart = buffer = ALLOCA_N(char, bufferSize); + } + + 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, + "%u: incomplete unicode character escape sequence at '%s'", __LINE__, 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, + "%u: incomplete surrogate pair at '%s'", __LINE__, 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; } -#line 1508 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 8}; enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_string_nfa_targs)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_string_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_string_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_string_nfa_pop_trans)[] = { + 0, 0 +}; + -#line 537 "parser.rl" +#line 612 "parser.rl" 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; + 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; + int cs = EVIL; + VALUE match_string; - *result = rb_str_buf_new(0); -#line 1538 "parser.c" { - cs = JSON_string_start; + cs = (int)JSON_string_start; } -#line 558 "parser.rl" - json->memo = p; + #line 632 "parser.rl" + + json->memo = p; -#line 1546 "parser.c" { - if ( p == pe ) + 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 ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 2: + goto st_case_2; + case 8: + goto st_case_8; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 7: + goto st_case_7; + } + goto st_out; + st_case_1: + if ( ( (*( p))) == 34 ) { + goto st2; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + st2: + p+= 1; + if ( p == pe ) goto _test_eof2; -case 2: - switch( (*p) ) { - case 34: goto tr2; - case 92: goto st3; - } - if ( 0 <= (*p) && (*p) <= 31 ) - goto st0; - goto st2; -tr2: -#line 523 "parser.rl" - { - *result = json_string_unescape(*result, json->memo + 1, p); - if (NIL_P(*result)) { - p--; - {p++; cs = 8; goto _out;} - } else { - FORCE_UTF8(*result); - {p = (( p + 1))-1;} - } - } -#line 534 "parser.rl" - { p--; {p++; cs = 8; goto _out;} } - goto st8; -st8: - if ( ++p == pe ) + st_case_2: + switch( ( (*( p))) ) { + case 34: { + goto ctr2; + } + case 92: { + goto st3; + } + } + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) { + goto st0; + } + { + goto st2; + } + ctr2: + { + #line 599 "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 - 1; } + {p+= 1; cs = 8; goto _out;} + } else { + {p = (( p + 1))-1;} + + } + } + { + #line 609 "parser.rl" + {p = p - 1; } {p+= 1; cs = 8; goto _out;} } + + goto st8; + st8: + p+= 1; + if ( p == pe ) goto _test_eof8; -case 8: -#line 1589 "parser.c" - goto st0; -st3: - if ( ++p == pe ) + st_case_8: + { + goto st0; + } + st3: + p+= 1; + if ( p == pe ) goto _test_eof3; -case 3: - if ( (*p) == 117 ) - goto st4; - if ( 0 <= (*p) && (*p) <= 31 ) - goto st0; - goto st2; -st4: - if ( ++p == pe ) + st_case_3: + if ( ( (*( p))) == 117 ) { + goto st4; + } + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) { + goto st0; + } + { + goto st2; + } + st4: + p+= 1; + if ( p == pe ) goto _test_eof4; -case 4: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) + st_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; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st5; - } else - goto st5; - goto st0; -st5: - if ( ++p == pe ) + } + { + goto st0; + } + st5: + p+= 1; + 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 ) + st_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; - } else - goto st6; - goto st0; -st6: - if ( ++p == pe ) + } + { + goto st0; + } + st6: + p+= 1; + if ( p == pe ) goto _test_eof6; -case 6: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) + st_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; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st7; - } else - goto st7; - goto st0; -st7: - if ( ++p == pe ) + } + { + goto st0; + } + st7: + p+= 1; + 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 ) + st_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; - } else - goto st2; - goto st0; + } + { + goto st0; + } + st_out: + _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 634 "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); + } + } + + if (cs >= JSON_string_first_final) { + return p + 1; + } else { + return NULL; } - _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 560 "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); - } - } - - if (json->symbolize_names && json->parsing_name) { - *result = rb_str_intern(*result); - } else if (RB_TYPE_P(*result, T_STRING)) { - rb_str_resize(*result, RSTRING_LEN(*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. - * - */ +* 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; + #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_. - * - * 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 - */ +* call-seq: new(source, opts => {}) +* +* Creates a new JSON::Ext::Parser instance for the string _source_. +* +* 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"); - } -#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - rb_scan_args(argc, argv, "1:", &source, &opts); -#else - rb_scan_args(argc, argv, "11", &source, &opts); -#endif - if (!NIL_P(opts)) { -#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); - if (NIL_P(opts)) { - rb_raise(rb_eArgError, "opts needs to be like a hash"); - } else { -#endif - 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_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; - } -#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - } -#endif - } 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; + VALUE source, opts; + GET_PARSER_INIT; + + if (json->Vsource) { + rb_raise(rb_eTypeError, "already initialized instance"); + } + #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + rb_scan_args(argc, argv, "1:", &source, &opts); + #else + rb_scan_args(argc, argv, "11", &source, &opts); + #endif + if (!NIL_P(opts)) { + #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); + if (NIL_P(opts)) { + rb_raise(rb_eArgError, "opts needs to be like a hash"); + } else { + #endif + 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; + } + #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + } + #endif + } 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; } -#line 1852 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; enum {JSON_en_main = 1}; +static const char MAYBE_UNUSED(_JSON_nfa_targs)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_nfa_offsets)[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_nfa_push_actions)[] = { + 0, 0 +}; + +static const char MAYBE_UNUSED(_JSON_nfa_pop_trans)[] = { + 0, 0 +}; + -#line 760 "parser.rl" +#line 835 "parser.rl" /* - * call-seq: parse() - * - * Parses the current JSON text _source_ and returns the complete data - * structure as a result. - */ +* call-seq: parse() +* +* Parses the current JSON text _source_ and returns the complete data +* structure as a result. +*/ static VALUE cParser_parse(VALUE self) { - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; + char *p, *pe; + int cs = EVIL; + VALUE result = Qnil; + GET_PARSER; -#line 1877 "parser.c" { - cs = JSON_start; + cs = (int)JSON_start; } -#line 776 "parser.rl" - p = json->source; - pe = p + json->len; + #line 851 "parser.rl" + + p = json->source; + pe = p + json->len; -#line 1886 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { -st1: - if ( ++p == pe ) + switch ( cs ) + { + case 1: + goto st_case_1; + case 0: + goto st_case_0; + case 10: + goto st_case_10; + case 2: + goto st_case_2; + case 3: + goto st_case_3; + case 4: + goto st_case_4; + case 5: + goto st_case_5; + case 6: + goto st_case_6; + case 7: + goto st_case_7; + case 8: + goto st_case_8; + case 9: + goto st_case_9; + } + goto st_out; + st1: + p+= 1; + 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 752 "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 1930 "parser.c" - switch( (*p) ) { - case 13: goto st10; - case 32: goto st10; - case 47: goto st2; - } - if ( 9 <= (*p) && (*p) <= 10 ) + st_case_1: + switch( ( (*( p))) ) { + case 13: { + goto st1; + } + case 32: { + goto st1; + } + case 34: { + goto ctr2; + } + case 45: { + goto ctr2; + } + case 47: { + goto st6; + } + case 73: { + goto ctr2; + } + case 78: { + goto ctr2; + } + case 91: { + goto ctr2; + } + case 102: { + goto ctr2; + } + case 110: { + goto ctr2; + } + case 116: { + goto ctr2; + } + case 123: { + goto ctr2; + } + } + if ( ( (*( p))) > 10 ) { + if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { + goto ctr2; + } + } else if ( ( (*( p))) >= 9 ) { + goto st1; + } + { + goto st0; + } + st_case_0: + st0: + cs = 0; + goto _out; + ctr2: + { + #line 827 "parser.rl" + + char *np = JSON_parse_value(json, p, pe, &result, 0); + if (np == NULL) { {p = p - 1; } {p+= 1; cs = 10; goto _out;} } else {p = (( np))-1;} + + } + goto st10; - goto st0; -st2: - if ( ++p == pe ) + st10: + p+= 1; + if ( p == pe ) + goto _test_eof10; + st_case_10: + switch( ( (*( p))) ) { + case 13: { + goto st10; + } + case 32: { + goto st10; + } + case 47: { + goto st2; + } + } + if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + goto st10; + } + { + goto st0; + } + st2: + p+= 1; + if ( p == pe ) goto _test_eof2; -case 2: - switch( (*p) ) { - case 42: goto st3; - case 47: goto st5; - } - goto st0; -st3: - if ( ++p == pe ) + st_case_2: + switch( ( (*( p))) ) { + case 42: { + goto st3; + } + case 47: { + goto st5; + } + } + { + goto st0; + } + st3: + p+= 1; + if ( p == pe ) goto _test_eof3; -case 3: - if ( (*p) == 42 ) - goto st4; - goto st3; -st4: - if ( ++p == pe ) + st_case_3: + if ( ( (*( p))) == 42 ) { + goto st4; + } + { + goto st3; + } + st4: + p+= 1; + if ( p == pe ) goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st4; - case 47: goto st10; - } - goto st3; -st5: - if ( ++p == pe ) + st_case_4: + switch( ( (*( p))) ) { + case 42: { + goto st4; + } + case 47: { + goto st10; + } + } + { + goto st3; + } + st5: + p+= 1; + if ( p == pe ) goto _test_eof5; -case 5: - if ( (*p) == 10 ) - goto st10; - goto st5; -st6: - if ( ++p == pe ) + st_case_5: + if ( ( (*( p))) == 10 ) { + goto st10; + } + { + goto st5; + } + st6: + p+= 1; + if ( p == pe ) goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st9; - } - goto st0; -st7: - if ( ++p == pe ) + st_case_6: + switch( ( (*( p))) ) { + case 42: { + goto st7; + } + case 47: { + goto st9; + } + } + { + goto st0; + } + st7: + p+= 1; + if ( p == pe ) goto _test_eof7; -case 7: - if ( (*p) == 42 ) - goto st8; - goto st7; -st8: - if ( ++p == pe ) + st_case_7: + if ( ( (*( p))) == 42 ) { + goto st8; + } + { + goto st7; + } + st8: + p+= 1; + if ( p == pe ) goto _test_eof8; -case 8: - switch( (*p) ) { - case 42: goto st8; - case 47: goto st1; - } - goto st7; -st9: - if ( ++p == pe ) + st_case_8: + switch( ( (*( p))) ) { + case 42: { + goto st8; + } + case 47: { + goto st1; + } + } + { + goto st7; + } + st9: + p+= 1; + if ( p == pe ) goto _test_eof9; -case 9: - if ( (*p) == 10 ) - goto st1; - goto st9; + st_case_9: + if ( ( (*( p))) == 10 ) { + goto st1; + } + { + goto st9; + } + st_out: + _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 854 "parser.rl" + + + if (cs >= JSON_first_final && p == pe) { + return result; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + return Qnil; } - _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 779 "parser.rl" - - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, 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); + 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); + 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); + 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 + "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; + 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. - */ +* 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); + GET_PARSER; + return rb_str_dup(json->Vsource); } 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"); - 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_BigDecimal = rb_intern("BigDecimal"); + #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: - */ +* Local variables: +* mode: c +* c-file-style: ruby +* indent-tabs-mode: nil +* End: +*/ diff --git a/ruby/ext/json/parser/parser.h b/ruby/ext/json/parser/parser.h index e6cf77902..92ed3fdc5 100644 --- a/ruby/ext/json/parser/parser.h +++ b/ruby/ext/json/parser/parser.h @@ -13,6 +13,10 @@ #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 */ @@ -37,6 +41,7 @@ typedef struct JSON_ParserStruct { int allow_nan; int parsing_name; int symbolize_names; + int freeze; VALUE object_class; VALUE array_class; VALUE decimal_class; @@ -62,7 +67,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul 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(VALUE result, char *string, char *stringEnd); +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); diff --git a/ruby/ext/json/parser/parser.rl b/ruby/ext/json/parser/parser.rl index 6b38bb283..f7be1a5ac 100644 --- a/ruby/ext/json/parser/parser.rl +++ b/ruby/ext/json/parser/parser.rl @@ -89,13 +89,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) static VALUE mJSON, mExt, cParser, eParserError, eNestingError; static VALUE CNaN, CInfinity, CMinusInfinity; -static VALUE cBigDecimal = Qundef; 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_BigDecimal; + i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; %%{ machine JSON_common; @@ -138,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, 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); @@ -289,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul %% write init; %% write exec; + if (json->freeze) { + OBJ_FREEZE(*result); + } + if (cs >= JSON_value_first_final) { return p; } else { @@ -340,19 +344,6 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res ) (^[0-9Ee.\-]? @exit ); }%% -static int is_bigdecimal_class(VALUE obj) -{ - if (cBigDecimal == Qundef) { - if (rb_const_defined(rb_cObject, i_BigDecimal)) { - cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal); - } - else { - return 0; - } - } - return obj == cBigDecimal; -} - static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; @@ -362,21 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul %% 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 (NIL_P(json->decimal_class)) { - *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); + + if (method_id) { + VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); + *result = rb_funcallv(mod, method_id, 1, &text); } else { - VALUE text; - text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); - if (is_bigdecimal_class(json->decimal_class)) { - *result = rb_funcall(Qnil, i_BigDecimal, 1, text); - } else { - *result = rb_funcall(json->decimal_class, i_new, 1, text); - } + *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); } + return p + 1; } else { return NULL; @@ -436,17 +452,29 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul } } -static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) +static const size_t MAX_STACK_BUFFER_SIZE = 128; +static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) { - char *p = string, *pe = string, *unescape; + 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) { + bufferStart = buffer = ALLOC_N(char, bufferSize); + } else { + bufferStart = buffer = ALLOCA_N(char, bufferSize); + } + while (pe < stringEnd) { if (*pe == '\\') { unescape = (char *) "?"; unescape_len = 1; - if (pe > p) rb_str_buf_cat(result, p, pe - p); + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; + } switch (*++pe) { case 'n': unescape = (char *) "\n"; @@ -471,6 +499,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) break; case 'u': if (pe > stringEnd - 4) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + free(bufferStart); + } rb_enc_raise( EXC_ENCODING eParserError, "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p @@ -481,6 +512,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) 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, "%u: incomplete surrogate pair at '%s'", __LINE__, p @@ -504,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) p = pe; continue; } - rb_str_buf_cat(result, unescape, unescape_len); + MEMCPY(buffer, unescape, char, unescape_len); + buffer += unescape_len; p = ++pe; } else { pe++; } } - rb_str_buf_cat(result, p, pe - p); + + 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; } @@ -521,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) write data; action parse_string { - *result = json_string_unescape(*result, json->memo + 1, p); + *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 { - FORCE_UTF8(*result); fexec p + 1; } } @@ -553,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu int cs = EVIL; VALUE match_string; - *result = rb_str_buf_new(0); %% write init; json->memo = p; %% write exec; @@ -569,11 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu } } - if (json->symbolize_names && json->parsing_name) { - *result = rb_str_intern(*result); - } else if (RB_TYPE_P(*result, T_STRING)) { - rb_str_resize(*result, RSTRING_LEN(*result)); - } if (cs >= JSON_string_first_final) { return p + 1; } else { @@ -680,6 +749,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } 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)); @@ -842,6 +917,10 @@ static VALUE cParser_source(VALUE self) 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"); @@ -884,7 +963,9 @@ void Init_parser(void) i_aref = rb_intern("[]"); i_leftshift = rb_intern("<<"); i_new = rb_intern("new"); - i_BigDecimal = rb_intern("BigDecimal"); + i_try_convert = rb_intern("try_convert"); + i_freeze = rb_intern("freeze"); + i_uminus = rb_intern("-@"); } /* diff --git a/ruby/ext/json/parser/prereq.mk b/ruby/ext/json/parser/prereq.mk index 37bacc338..fc5916905 100644 --- a/ruby/ext/json/parser/prereq.mk +++ b/ruby/ext/json/parser/prereq.mk @@ -6,6 +6,8 @@ RAGEL = ragel $(RAGEL) -G2 $< $(BASERUBY) -pli -e '$$_.sub!(/[ \t]+$$/, "")' \ -e '$$_.sub!(/^static const int (JSON_.*=.*);$$/, "enum {\\1};")' \ - -e '$$_ = "/* This file is automatically generated from parser.rl by using ragel */" + $$_ if $$. == 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/ruby/ext/monitor/depend b/ruby/ext/monitor/depend index 89efe1766..a8fca7f0b 100644 --- a/ruby/ext/monitor/depend +++ b/ruby/ext/monitor/depend @@ -3,8 +3,155 @@ monitor.o: $(RUBY_EXTCONF_H) monitor.o: $(arch_hdrdir)/ruby/config.h monitor.o: $(hdrdir)/ruby/assert.h monitor.o: $(hdrdir)/ruby/backward.h +monitor.o: $(hdrdir)/ruby/backward/2/assume.h +monitor.o: $(hdrdir)/ruby/backward/2/attributes.h +monitor.o: $(hdrdir)/ruby/backward/2/bool.h +monitor.o: $(hdrdir)/ruby/backward/2/inttypes.h +monitor.o: $(hdrdir)/ruby/backward/2/limits.h +monitor.o: $(hdrdir)/ruby/backward/2/long_long.h +monitor.o: $(hdrdir)/ruby/backward/2/stdalign.h +monitor.o: $(hdrdir)/ruby/backward/2/stdarg.h monitor.o: $(hdrdir)/ruby/defines.h monitor.o: $(hdrdir)/ruby/intern.h +monitor.o: $(hdrdir)/ruby/internal/anyargs.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/char.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/double.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/int.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/long.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/short.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +monitor.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +monitor.o: $(hdrdir)/ruby/internal/assume.h +monitor.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +monitor.o: $(hdrdir)/ruby/internal/attr/artificial.h +monitor.o: $(hdrdir)/ruby/internal/attr/cold.h +monitor.o: $(hdrdir)/ruby/internal/attr/const.h +monitor.o: $(hdrdir)/ruby/internal/attr/constexpr.h +monitor.o: $(hdrdir)/ruby/internal/attr/deprecated.h +monitor.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +monitor.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +monitor.o: $(hdrdir)/ruby/internal/attr/error.h +monitor.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +monitor.o: $(hdrdir)/ruby/internal/attr/forceinline.h +monitor.o: $(hdrdir)/ruby/internal/attr/format.h +monitor.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +monitor.o: $(hdrdir)/ruby/internal/attr/noalias.h +monitor.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +monitor.o: $(hdrdir)/ruby/internal/attr/noexcept.h +monitor.o: $(hdrdir)/ruby/internal/attr/noinline.h +monitor.o: $(hdrdir)/ruby/internal/attr/nonnull.h +monitor.o: $(hdrdir)/ruby/internal/attr/noreturn.h +monitor.o: $(hdrdir)/ruby/internal/attr/pure.h +monitor.o: $(hdrdir)/ruby/internal/attr/restrict.h +monitor.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +monitor.o: $(hdrdir)/ruby/internal/attr/warning.h +monitor.o: $(hdrdir)/ruby/internal/attr/weakref.h +monitor.o: $(hdrdir)/ruby/internal/cast.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +monitor.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +monitor.o: $(hdrdir)/ruby/internal/compiler_since.h +monitor.o: $(hdrdir)/ruby/internal/config.h +monitor.o: $(hdrdir)/ruby/internal/constant_p.h +monitor.o: $(hdrdir)/ruby/internal/core.h +monitor.o: $(hdrdir)/ruby/internal/core/rarray.h +monitor.o: $(hdrdir)/ruby/internal/core/rbasic.h +monitor.o: $(hdrdir)/ruby/internal/core/rbignum.h +monitor.o: $(hdrdir)/ruby/internal/core/rclass.h +monitor.o: $(hdrdir)/ruby/internal/core/rdata.h +monitor.o: $(hdrdir)/ruby/internal/core/rfile.h +monitor.o: $(hdrdir)/ruby/internal/core/rhash.h +monitor.o: $(hdrdir)/ruby/internal/core/robject.h +monitor.o: $(hdrdir)/ruby/internal/core/rregexp.h +monitor.o: $(hdrdir)/ruby/internal/core/rstring.h +monitor.o: $(hdrdir)/ruby/internal/core/rstruct.h +monitor.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +monitor.o: $(hdrdir)/ruby/internal/ctype.h +monitor.o: $(hdrdir)/ruby/internal/dllexport.h +monitor.o: $(hdrdir)/ruby/internal/dosish.h +monitor.o: $(hdrdir)/ruby/internal/error.h +monitor.o: $(hdrdir)/ruby/internal/eval.h +monitor.o: $(hdrdir)/ruby/internal/event.h +monitor.o: $(hdrdir)/ruby/internal/fl_type.h +monitor.o: $(hdrdir)/ruby/internal/gc.h +monitor.o: $(hdrdir)/ruby/internal/glob.h +monitor.o: $(hdrdir)/ruby/internal/globals.h +monitor.o: $(hdrdir)/ruby/internal/has/attribute.h +monitor.o: $(hdrdir)/ruby/internal/has/builtin.h +monitor.o: $(hdrdir)/ruby/internal/has/c_attribute.h +monitor.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +monitor.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +monitor.o: $(hdrdir)/ruby/internal/has/extension.h +monitor.o: $(hdrdir)/ruby/internal/has/feature.h +monitor.o: $(hdrdir)/ruby/internal/has/warning.h +monitor.o: $(hdrdir)/ruby/internal/intern/array.h +monitor.o: $(hdrdir)/ruby/internal/intern/bignum.h +monitor.o: $(hdrdir)/ruby/internal/intern/class.h +monitor.o: $(hdrdir)/ruby/internal/intern/compar.h +monitor.o: $(hdrdir)/ruby/internal/intern/complex.h +monitor.o: $(hdrdir)/ruby/internal/intern/cont.h +monitor.o: $(hdrdir)/ruby/internal/intern/dir.h +monitor.o: $(hdrdir)/ruby/internal/intern/enum.h +monitor.o: $(hdrdir)/ruby/internal/intern/enumerator.h +monitor.o: $(hdrdir)/ruby/internal/intern/error.h +monitor.o: $(hdrdir)/ruby/internal/intern/eval.h +monitor.o: $(hdrdir)/ruby/internal/intern/file.h +monitor.o: $(hdrdir)/ruby/internal/intern/gc.h +monitor.o: $(hdrdir)/ruby/internal/intern/hash.h +monitor.o: $(hdrdir)/ruby/internal/intern/io.h +monitor.o: $(hdrdir)/ruby/internal/intern/load.h +monitor.o: $(hdrdir)/ruby/internal/intern/marshal.h +monitor.o: $(hdrdir)/ruby/internal/intern/numeric.h +monitor.o: $(hdrdir)/ruby/internal/intern/object.h +monitor.o: $(hdrdir)/ruby/internal/intern/parse.h +monitor.o: $(hdrdir)/ruby/internal/intern/proc.h +monitor.o: $(hdrdir)/ruby/internal/intern/process.h +monitor.o: $(hdrdir)/ruby/internal/intern/random.h +monitor.o: $(hdrdir)/ruby/internal/intern/range.h +monitor.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +monitor.o: $(hdrdir)/ruby/internal/intern/sprintf.h +monitor.o: $(hdrdir)/ruby/internal/intern/string.h +monitor.o: $(hdrdir)/ruby/internal/intern/struct.h +monitor.o: $(hdrdir)/ruby/internal/intern/thread.h +monitor.o: $(hdrdir)/ruby/internal/intern/time.h +monitor.o: $(hdrdir)/ruby/internal/intern/variable.h +monitor.o: $(hdrdir)/ruby/internal/intern/vm.h +monitor.o: $(hdrdir)/ruby/internal/interpreter.h +monitor.o: $(hdrdir)/ruby/internal/iterator.h +monitor.o: $(hdrdir)/ruby/internal/memory.h +monitor.o: $(hdrdir)/ruby/internal/method.h +monitor.o: $(hdrdir)/ruby/internal/module.h +monitor.o: $(hdrdir)/ruby/internal/newobj.h +monitor.o: $(hdrdir)/ruby/internal/rgengc.h +monitor.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +monitor.o: $(hdrdir)/ruby/internal/value.h +monitor.o: $(hdrdir)/ruby/internal/value_type.h +monitor.o: $(hdrdir)/ruby/internal/variable.h +monitor.o: $(hdrdir)/ruby/internal/warning_push.h +monitor.o: $(hdrdir)/ruby/internal/xmalloc.h monitor.o: $(hdrdir)/ruby/missing.h monitor.o: $(hdrdir)/ruby/ruby.h monitor.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/monitor/lib/monitor.rb b/ruby/ext/monitor/lib/monitor.rb index 1883cb72f..11c5ac17d 100644 --- a/ruby/ext/monitor/lib/monitor.rb +++ b/ruby/ext/monitor/lib/monitor.rb @@ -17,7 +17,7 @@ # structure. # # You can read more about the general principles on the Wikipedia page for -# Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29] +# Monitors[https://en.wikipedia.org/wiki/Monitor_%28synchronization%29] # # == Examples # @@ -220,7 +220,7 @@ def new_cond # Use extend MonitorMixin or include MonitorMixin instead # of this constructor. Have look at the examples above to understand how to # use this module. - def initialize(*args) + def initialize(...) super mon_initialize end @@ -230,7 +230,7 @@ def initialize(*args) def mon_initialize if defined?(@mon_data) if defined?(@mon_initialized_by_new_cond) - return # already initalized. + return # already initialized. elsif @mon_data_owner_object_id == self.object_id raise ThreadError, "already initialized" end diff --git a/ruby/ext/monitor/monitor.c b/ruby/ext/monitor/monitor.c index 256fc4d7d..10209cf2a 100644 --- a/ruby/ext/monitor/monitor.c +++ b/ruby/ext/monitor/monitor.c @@ -53,7 +53,7 @@ monitor_ptr(VALUE monitor) static int mc_owner_p(struct rb_monitor *mc) { - return mc->owner == rb_thread_current(); + return mc->owner == rb_fiber_current(); } static VALUE @@ -65,7 +65,7 @@ monitor_try_enter(VALUE monitor) if (!rb_mutex_trylock(mc->mutex)) { return Qfalse; } - RB_OBJ_WRITE(monitor, &mc->owner, rb_thread_current()); + RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current()); mc->count = 0; } mc->count += 1; @@ -78,7 +78,7 @@ monitor_enter(VALUE monitor) struct rb_monitor *mc = monitor_ptr(monitor); if (!mc_owner_p(mc)) { rb_mutex_lock(mc->mutex); - RB_OBJ_WRITE(monitor, &mc->owner, rb_thread_current()); + RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current()); mc->count = 0; } mc->count++; @@ -90,7 +90,7 @@ monitor_check_owner(VALUE monitor) { struct rb_monitor *mc = monitor_ptr(monitor); if (!mc_owner_p(mc)) { - rb_raise(rb_eThreadError, "current thread not owner"); + rb_raise(rb_eThreadError, "current fiber not owner"); } return Qnil; } @@ -149,8 +149,8 @@ monitor_wait_for_cond_body(VALUE v) struct wait_for_cond_data *data = (struct wait_for_cond_data *)v; struct rb_monitor *mc = monitor_ptr(data->monitor); // cond.wait(monitor.mutex, timeout) - rb_funcall(data->cond, rb_intern("wait"), 2, mc->mutex, data->timeout); - return Qtrue; + VALUE signaled = rb_funcall(data->cond, rb_intern("wait"), 2, mc->mutex, data->timeout); + return RTEST(signaled) ? Qtrue : Qfalse; } static VALUE @@ -161,7 +161,7 @@ monitor_enter_for_cond(VALUE v) struct wait_for_cond_data *data = (struct wait_for_cond_data *)v; struct rb_monitor *mc = monitor_ptr(data->monitor); - RB_OBJ_WRITE(data->monitor, &mc->owner, rb_thread_current()); + RB_OBJ_WRITE(data->monitor, &mc->owner, rb_fiber_current()); mc->count = NUM2LONG(data->count); return Qnil; } @@ -203,6 +203,10 @@ monitor_synchronize(VALUE monitor) void Init_monitor(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + VALUE rb_cMonitor = rb_define_class("Monitor", rb_cObject); rb_define_alloc_func(rb_cMonitor, monitor_alloc); @@ -216,6 +220,6 @@ Init_monitor(void) rb_define_method(rb_cMonitor, "mon_check_owner", monitor_check_owner, 0); rb_define_method(rb_cMonitor, "mon_owned?", monitor_owned_p, 0); - /* internal methods for MonitorMixin::ConditionalVariable */ + /* internal methods for MonitorMixin::ConditionVariable */ rb_define_method(rb_cMonitor, "wait_for_cond", monitor_wait_for_cond, 2); } diff --git a/ruby/ext/nkf/depend b/ruby/ext/nkf/depend index 82580ff7f..8951e0b3d 100644 --- a/ruby/ext/nkf/depend +++ b/ruby/ext/nkf/depend @@ -7,9 +7,165 @@ 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/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/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/gc.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/rgengc.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 diff --git a/ruby/ext/nkf/nkf-utf8/config.h b/ruby/ext/nkf/nkf-utf8/config.h index 51dc2a515..36898c0b4 100644 --- a/ruby/ext/nkf/nkf-utf8/config.h +++ b/ruby/ext/nkf/nkf-utf8/config.h @@ -30,7 +30,7 @@ /* --exec-in, --exec-out option * require pipe, fork, execvp and so on. * please undef this on MS-DOS, MinGW - * this is still buggy arround child process + * this is still buggy around child process */ /* #define EXEC_IO */ diff --git a/ruby/ext/nkf/nkf-utf8/nkf.c b/ruby/ext/nkf/nkf-utf8/nkf.c index cc438a50d..08b372ffa 100644 --- a/ruby/ext/nkf/nkf-utf8/nkf.c +++ b/ruby/ext/nkf/nkf-utf8/nkf.c @@ -581,7 +581,7 @@ static const unsigned char cv[]= { 0x00,0x00}; -/* X0201 kana conversion table for daguten */ +/* X0201 kana conversion table for dakuten */ /* 90-9F A0-DF */ static const unsigned char dv[]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -602,7 +602,7 @@ static const unsigned char dv[]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}; -/* X0201 kana conversion table for han-daguten */ +/* X0201 kana conversion table for han-dakuten */ /* 90-9F A0-DF */ static const unsigned char ev[]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -623,7 +623,7 @@ static const unsigned char ev[]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}; -/* X0201 kana to X0213 conversion table for han-daguten */ +/* 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, @@ -3817,7 +3817,7 @@ oconv_newline(void (*func)(nkf_char, nkf_char)) LF new line SP space - This fold algorthm does not preserve heading space in a line. + This fold algorithm does not preserve heading space in a line. This is the main difference from fmt. */ @@ -6787,7 +6787,7 @@ options(unsigned char *cp) case 'S': /* Shift_JIS input */ input_encoding = nkf_enc_from_index(SHIFT_JIS); continue; - case 'Z': /* Convert X0208 alphabet to asii */ + 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 diff --git a/ruby/ext/nkf/nkf-utf8/nkf.h b/ruby/ext/nkf/nkf-utf8/nkf.h index cd3037601..b3a520da5 100644 --- a/ruby/ext/nkf/nkf-utf8/nkf.h +++ b/ruby/ext/nkf/nkf-utf8/nkf.h @@ -16,8 +16,8 @@ #define X0201_DEFAULT TRUE #endif -#if DEFAULT_NEWLINE == 0x0D0A -#elif DEFAULT_NEWLINE == 0x0D +#if defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D0A +#elif defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D #else #define DEFAULT_NEWLINE 0x0A #endif diff --git a/ruby/ext/nkf/nkf.c b/ruby/ext/nkf/nkf.c index 37717e479..533f9b782 100644 --- a/ruby/ext/nkf/nkf.c +++ b/ruby/ext/nkf/nkf.c @@ -358,7 +358,7 @@ rb_nkf_guess(VALUE obj, VALUE src) * * [-MB] MIME encode Base64 stream. * - * [-MQ] Perfome quoted encoding. + * [-MQ] Perform quoted encoding. * * === -l * @@ -458,7 +458,7 @@ rb_nkf_guess(VALUE obj, VALUE src) * 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 opion. + * When nkf convert string which related to path, you should use this option. * * === --cap-input * diff --git a/ruby/ext/nkf/nkf.gemspec b/ruby/ext/nkf/nkf.gemspec new file mode 100644 index 000000000..2d77c71ff --- /dev/null +++ b/ruby/ext/nkf/nkf.gemspec @@ -0,0 +1,24 @@ +Gem::Specification.new do |spec| + spec.name = "nkf" + spec.version = "0.1.1" + 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"] +end diff --git a/ruby/ext/objspace/depend b/ruby/ext/objspace/depend index 18be4fe8a..bea8ba231 100644 --- a/ruby/ext/objspace/depend +++ b/ruby/ext/objspace/depend @@ -1,12 +1,158 @@ # AUTOGENERATED DEPENDENCIES START object_tracing.o: $(RUBY_EXTCONF_H) object_tracing.o: $(arch_hdrdir)/ruby/config.h -object_tracing.o: $(hdrdir)/ruby.h object_tracing.o: $(hdrdir)/ruby/assert.h object_tracing.o: $(hdrdir)/ruby/backward.h +object_tracing.o: $(hdrdir)/ruby/backward/2/assume.h +object_tracing.o: $(hdrdir)/ruby/backward/2/attributes.h +object_tracing.o: $(hdrdir)/ruby/backward/2/bool.h +object_tracing.o: $(hdrdir)/ruby/backward/2/inttypes.h +object_tracing.o: $(hdrdir)/ruby/backward/2/limits.h +object_tracing.o: $(hdrdir)/ruby/backward/2/long_long.h +object_tracing.o: $(hdrdir)/ruby/backward/2/stdalign.h +object_tracing.o: $(hdrdir)/ruby/backward/2/stdarg.h object_tracing.o: $(hdrdir)/ruby/debug.h object_tracing.o: $(hdrdir)/ruby/defines.h object_tracing.o: $(hdrdir)/ruby/intern.h +object_tracing.o: $(hdrdir)/ruby/internal/anyargs.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/char.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/double.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/int.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/short.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +object_tracing.o: $(hdrdir)/ruby/internal/assume.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/artificial.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/cold.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/const.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/constexpr.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/deprecated.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/error.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/forceinline.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/format.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/noalias.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/noexcept.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/noinline.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/nonnull.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/noreturn.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/pure.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/restrict.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/warning.h +object_tracing.o: $(hdrdir)/ruby/internal/attr/weakref.h +object_tracing.o: $(hdrdir)/ruby/internal/cast.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +object_tracing.o: $(hdrdir)/ruby/internal/compiler_since.h +object_tracing.o: $(hdrdir)/ruby/internal/config.h +object_tracing.o: $(hdrdir)/ruby/internal/constant_p.h +object_tracing.o: $(hdrdir)/ruby/internal/core.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rarray.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rbasic.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rbignum.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rclass.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rdata.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rfile.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rhash.h +object_tracing.o: $(hdrdir)/ruby/internal/core/robject.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rregexp.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rstring.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rstruct.h +object_tracing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +object_tracing.o: $(hdrdir)/ruby/internal/ctype.h +object_tracing.o: $(hdrdir)/ruby/internal/dllexport.h +object_tracing.o: $(hdrdir)/ruby/internal/dosish.h +object_tracing.o: $(hdrdir)/ruby/internal/error.h +object_tracing.o: $(hdrdir)/ruby/internal/eval.h +object_tracing.o: $(hdrdir)/ruby/internal/event.h +object_tracing.o: $(hdrdir)/ruby/internal/fl_type.h +object_tracing.o: $(hdrdir)/ruby/internal/gc.h +object_tracing.o: $(hdrdir)/ruby/internal/glob.h +object_tracing.o: $(hdrdir)/ruby/internal/globals.h +object_tracing.o: $(hdrdir)/ruby/internal/has/attribute.h +object_tracing.o: $(hdrdir)/ruby/internal/has/builtin.h +object_tracing.o: $(hdrdir)/ruby/internal/has/c_attribute.h +object_tracing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +object_tracing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +object_tracing.o: $(hdrdir)/ruby/internal/has/extension.h +object_tracing.o: $(hdrdir)/ruby/internal/has/feature.h +object_tracing.o: $(hdrdir)/ruby/internal/has/warning.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/array.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/bignum.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/class.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/compar.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/complex.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/cont.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/dir.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/enum.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/enumerator.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/error.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/eval.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/file.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/gc.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/hash.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/io.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/load.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/marshal.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/numeric.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/object.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/parse.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/proc.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/process.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/random.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/range.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/sprintf.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/string.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/struct.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/thread.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/time.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/variable.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/vm.h +object_tracing.o: $(hdrdir)/ruby/internal/interpreter.h +object_tracing.o: $(hdrdir)/ruby/internal/iterator.h +object_tracing.o: $(hdrdir)/ruby/internal/memory.h +object_tracing.o: $(hdrdir)/ruby/internal/method.h +object_tracing.o: $(hdrdir)/ruby/internal/module.h +object_tracing.o: $(hdrdir)/ruby/internal/newobj.h +object_tracing.o: $(hdrdir)/ruby/internal/rgengc.h +object_tracing.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +object_tracing.o: $(hdrdir)/ruby/internal/value.h +object_tracing.o: $(hdrdir)/ruby/internal/value_type.h +object_tracing.o: $(hdrdir)/ruby/internal/variable.h +object_tracing.o: $(hdrdir)/ruby/internal/warning_push.h +object_tracing.o: $(hdrdir)/ruby/internal/xmalloc.h object_tracing.o: $(hdrdir)/ruby/missing.h object_tracing.o: $(hdrdir)/ruby/ruby.h object_tracing.o: $(hdrdir)/ruby/st.h @@ -16,12 +162,169 @@ object_tracing.o: object_tracing.c object_tracing.o: objspace.h objspace.o: $(RUBY_EXTCONF_H) objspace.o: $(arch_hdrdir)/ruby/config.h -objspace.o: $(hdrdir)/ruby.h objspace.o: $(hdrdir)/ruby/assert.h objspace.o: $(hdrdir)/ruby/backward.h +objspace.o: $(hdrdir)/ruby/backward/2/assume.h +objspace.o: $(hdrdir)/ruby/backward/2/attributes.h +objspace.o: $(hdrdir)/ruby/backward/2/bool.h +objspace.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +objspace.o: $(hdrdir)/ruby/backward/2/inttypes.h +objspace.o: $(hdrdir)/ruby/backward/2/limits.h +objspace.o: $(hdrdir)/ruby/backward/2/long_long.h +objspace.o: $(hdrdir)/ruby/backward/2/stdalign.h +objspace.o: $(hdrdir)/ruby/backward/2/stdarg.h objspace.o: $(hdrdir)/ruby/defines.h objspace.o: $(hdrdir)/ruby/encoding.h objspace.o: $(hdrdir)/ruby/intern.h +objspace.o: $(hdrdir)/ruby/internal/anyargs.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/char.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/double.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/int.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/long.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/short.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +objspace.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +objspace.o: $(hdrdir)/ruby/internal/assume.h +objspace.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +objspace.o: $(hdrdir)/ruby/internal/attr/artificial.h +objspace.o: $(hdrdir)/ruby/internal/attr/cold.h +objspace.o: $(hdrdir)/ruby/internal/attr/const.h +objspace.o: $(hdrdir)/ruby/internal/attr/constexpr.h +objspace.o: $(hdrdir)/ruby/internal/attr/deprecated.h +objspace.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +objspace.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +objspace.o: $(hdrdir)/ruby/internal/attr/error.h +objspace.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +objspace.o: $(hdrdir)/ruby/internal/attr/forceinline.h +objspace.o: $(hdrdir)/ruby/internal/attr/format.h +objspace.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +objspace.o: $(hdrdir)/ruby/internal/attr/noalias.h +objspace.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +objspace.o: $(hdrdir)/ruby/internal/attr/noexcept.h +objspace.o: $(hdrdir)/ruby/internal/attr/noinline.h +objspace.o: $(hdrdir)/ruby/internal/attr/nonnull.h +objspace.o: $(hdrdir)/ruby/internal/attr/noreturn.h +objspace.o: $(hdrdir)/ruby/internal/attr/pure.h +objspace.o: $(hdrdir)/ruby/internal/attr/restrict.h +objspace.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +objspace.o: $(hdrdir)/ruby/internal/attr/warning.h +objspace.o: $(hdrdir)/ruby/internal/attr/weakref.h +objspace.o: $(hdrdir)/ruby/internal/cast.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +objspace.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +objspace.o: $(hdrdir)/ruby/internal/compiler_since.h +objspace.o: $(hdrdir)/ruby/internal/config.h +objspace.o: $(hdrdir)/ruby/internal/constant_p.h +objspace.o: $(hdrdir)/ruby/internal/core.h +objspace.o: $(hdrdir)/ruby/internal/core/rarray.h +objspace.o: $(hdrdir)/ruby/internal/core/rbasic.h +objspace.o: $(hdrdir)/ruby/internal/core/rbignum.h +objspace.o: $(hdrdir)/ruby/internal/core/rclass.h +objspace.o: $(hdrdir)/ruby/internal/core/rdata.h +objspace.o: $(hdrdir)/ruby/internal/core/rfile.h +objspace.o: $(hdrdir)/ruby/internal/core/rhash.h +objspace.o: $(hdrdir)/ruby/internal/core/rmatch.h +objspace.o: $(hdrdir)/ruby/internal/core/robject.h +objspace.o: $(hdrdir)/ruby/internal/core/rregexp.h +objspace.o: $(hdrdir)/ruby/internal/core/rstring.h +objspace.o: $(hdrdir)/ruby/internal/core/rstruct.h +objspace.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +objspace.o: $(hdrdir)/ruby/internal/ctype.h +objspace.o: $(hdrdir)/ruby/internal/dllexport.h +objspace.o: $(hdrdir)/ruby/internal/dosish.h +objspace.o: $(hdrdir)/ruby/internal/encoding/coderange.h +objspace.o: $(hdrdir)/ruby/internal/encoding/ctype.h +objspace.o: $(hdrdir)/ruby/internal/encoding/encoding.h +objspace.o: $(hdrdir)/ruby/internal/encoding/pathname.h +objspace.o: $(hdrdir)/ruby/internal/encoding/re.h +objspace.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +objspace.o: $(hdrdir)/ruby/internal/encoding/string.h +objspace.o: $(hdrdir)/ruby/internal/encoding/symbol.h +objspace.o: $(hdrdir)/ruby/internal/encoding/transcode.h +objspace.o: $(hdrdir)/ruby/internal/error.h +objspace.o: $(hdrdir)/ruby/internal/eval.h +objspace.o: $(hdrdir)/ruby/internal/event.h +objspace.o: $(hdrdir)/ruby/internal/fl_type.h +objspace.o: $(hdrdir)/ruby/internal/gc.h +objspace.o: $(hdrdir)/ruby/internal/glob.h +objspace.o: $(hdrdir)/ruby/internal/globals.h +objspace.o: $(hdrdir)/ruby/internal/has/attribute.h +objspace.o: $(hdrdir)/ruby/internal/has/builtin.h +objspace.o: $(hdrdir)/ruby/internal/has/c_attribute.h +objspace.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +objspace.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +objspace.o: $(hdrdir)/ruby/internal/has/extension.h +objspace.o: $(hdrdir)/ruby/internal/has/feature.h +objspace.o: $(hdrdir)/ruby/internal/has/warning.h +objspace.o: $(hdrdir)/ruby/internal/intern/array.h +objspace.o: $(hdrdir)/ruby/internal/intern/bignum.h +objspace.o: $(hdrdir)/ruby/internal/intern/class.h +objspace.o: $(hdrdir)/ruby/internal/intern/compar.h +objspace.o: $(hdrdir)/ruby/internal/intern/complex.h +objspace.o: $(hdrdir)/ruby/internal/intern/cont.h +objspace.o: $(hdrdir)/ruby/internal/intern/dir.h +objspace.o: $(hdrdir)/ruby/internal/intern/enum.h +objspace.o: $(hdrdir)/ruby/internal/intern/enumerator.h +objspace.o: $(hdrdir)/ruby/internal/intern/error.h +objspace.o: $(hdrdir)/ruby/internal/intern/eval.h +objspace.o: $(hdrdir)/ruby/internal/intern/file.h +objspace.o: $(hdrdir)/ruby/internal/intern/gc.h +objspace.o: $(hdrdir)/ruby/internal/intern/hash.h +objspace.o: $(hdrdir)/ruby/internal/intern/io.h +objspace.o: $(hdrdir)/ruby/internal/intern/load.h +objspace.o: $(hdrdir)/ruby/internal/intern/marshal.h +objspace.o: $(hdrdir)/ruby/internal/intern/numeric.h +objspace.o: $(hdrdir)/ruby/internal/intern/object.h +objspace.o: $(hdrdir)/ruby/internal/intern/parse.h +objspace.o: $(hdrdir)/ruby/internal/intern/proc.h +objspace.o: $(hdrdir)/ruby/internal/intern/process.h +objspace.o: $(hdrdir)/ruby/internal/intern/random.h +objspace.o: $(hdrdir)/ruby/internal/intern/range.h +objspace.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +objspace.o: $(hdrdir)/ruby/internal/intern/sprintf.h +objspace.o: $(hdrdir)/ruby/internal/intern/string.h +objspace.o: $(hdrdir)/ruby/internal/intern/struct.h +objspace.o: $(hdrdir)/ruby/internal/intern/thread.h +objspace.o: $(hdrdir)/ruby/internal/intern/time.h +objspace.o: $(hdrdir)/ruby/internal/intern/variable.h +objspace.o: $(hdrdir)/ruby/internal/intern/vm.h +objspace.o: $(hdrdir)/ruby/internal/interpreter.h +objspace.o: $(hdrdir)/ruby/internal/iterator.h +objspace.o: $(hdrdir)/ruby/internal/memory.h +objspace.o: $(hdrdir)/ruby/internal/method.h +objspace.o: $(hdrdir)/ruby/internal/module.h +objspace.o: $(hdrdir)/ruby/internal/newobj.h +objspace.o: $(hdrdir)/ruby/internal/rgengc.h +objspace.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +objspace.o: $(hdrdir)/ruby/internal/value.h +objspace.o: $(hdrdir)/ruby/internal/value_type.h +objspace.o: $(hdrdir)/ruby/internal/variable.h +objspace.o: $(hdrdir)/ruby/internal/warning_push.h +objspace.o: $(hdrdir)/ruby/internal/xmalloc.h objspace.o: $(hdrdir)/ruby/io.h objspace.o: $(hdrdir)/ruby/missing.h objspace.o: $(hdrdir)/ruby/onigmo.h @@ -32,20 +335,188 @@ objspace.o: $(hdrdir)/ruby/ruby.h objspace.o: $(hdrdir)/ruby/st.h objspace.o: $(hdrdir)/ruby/subst.h objspace.o: $(top_srcdir)/gc.h +objspace.o: $(top_srcdir)/id_table.h objspace.o: $(top_srcdir)/internal.h +objspace.o: $(top_srcdir)/internal/array.h +objspace.o: $(top_srcdir)/internal/class.h +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/sanitizers.h +objspace.o: $(top_srcdir)/internal/serial.h +objspace.o: $(top_srcdir)/internal/static_assert.h +objspace.o: $(top_srcdir)/internal/warnings.h objspace.o: $(top_srcdir)/node.h objspace.o: $(top_srcdir)/symbol.h objspace.o: objspace.c objspace.o: {$(VPATH)}id.h objspace_dump.o: $(RUBY_EXTCONF_H) objspace_dump.o: $(arch_hdrdir)/ruby/config.h -objspace_dump.o: $(hdrdir)/ruby.h objspace_dump.o: $(hdrdir)/ruby/assert.h +objspace_dump.o: $(hdrdir)/ruby/atomic.h objspace_dump.o: $(hdrdir)/ruby/backward.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/assume.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/attributes.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/bool.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/inttypes.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/limits.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/long_long.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/stdalign.h +objspace_dump.o: $(hdrdir)/ruby/backward/2/stdarg.h objspace_dump.o: $(hdrdir)/ruby/debug.h objspace_dump.o: $(hdrdir)/ruby/defines.h objspace_dump.o: $(hdrdir)/ruby/encoding.h objspace_dump.o: $(hdrdir)/ruby/intern.h +objspace_dump.o: $(hdrdir)/ruby/internal/anyargs.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/char.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/double.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/int.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/short.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +objspace_dump.o: $(hdrdir)/ruby/internal/assume.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/artificial.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/cold.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/const.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/constexpr.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/deprecated.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/error.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/forceinline.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/format.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/noalias.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/noexcept.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/noinline.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/nonnull.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/noreturn.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/pure.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/restrict.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/warning.h +objspace_dump.o: $(hdrdir)/ruby/internal/attr/weakref.h +objspace_dump.o: $(hdrdir)/ruby/internal/cast.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +objspace_dump.o: $(hdrdir)/ruby/internal/compiler_since.h +objspace_dump.o: $(hdrdir)/ruby/internal/config.h +objspace_dump.o: $(hdrdir)/ruby/internal/constant_p.h +objspace_dump.o: $(hdrdir)/ruby/internal/core.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rarray.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rbasic.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rbignum.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rclass.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rdata.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rfile.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rhash.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/robject.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rregexp.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rstring.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rstruct.h +objspace_dump.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +objspace_dump.o: $(hdrdir)/ruby/internal/ctype.h +objspace_dump.o: $(hdrdir)/ruby/internal/dllexport.h +objspace_dump.o: $(hdrdir)/ruby/internal/dosish.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/coderange.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/ctype.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/encoding.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/pathname.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/re.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/string.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/symbol.h +objspace_dump.o: $(hdrdir)/ruby/internal/encoding/transcode.h +objspace_dump.o: $(hdrdir)/ruby/internal/error.h +objspace_dump.o: $(hdrdir)/ruby/internal/eval.h +objspace_dump.o: $(hdrdir)/ruby/internal/event.h +objspace_dump.o: $(hdrdir)/ruby/internal/fl_type.h +objspace_dump.o: $(hdrdir)/ruby/internal/gc.h +objspace_dump.o: $(hdrdir)/ruby/internal/glob.h +objspace_dump.o: $(hdrdir)/ruby/internal/globals.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/attribute.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/builtin.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/c_attribute.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/extension.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/feature.h +objspace_dump.o: $(hdrdir)/ruby/internal/has/warning.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/array.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/bignum.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/class.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/compar.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/complex.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/cont.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/dir.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/enum.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/enumerator.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/error.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/eval.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/file.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/gc.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/hash.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/io.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/load.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/marshal.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/numeric.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/object.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/parse.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/proc.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/process.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/random.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/range.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/sprintf.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/string.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/struct.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/thread.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/time.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/variable.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/vm.h +objspace_dump.o: $(hdrdir)/ruby/internal/interpreter.h +objspace_dump.o: $(hdrdir)/ruby/internal/iterator.h +objspace_dump.o: $(hdrdir)/ruby/internal/memory.h +objspace_dump.o: $(hdrdir)/ruby/internal/method.h +objspace_dump.o: $(hdrdir)/ruby/internal/module.h +objspace_dump.o: $(hdrdir)/ruby/internal/newobj.h +objspace_dump.o: $(hdrdir)/ruby/internal/rgengc.h +objspace_dump.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +objspace_dump.o: $(hdrdir)/ruby/internal/value.h +objspace_dump.o: $(hdrdir)/ruby/internal/value_type.h +objspace_dump.o: $(hdrdir)/ruby/internal/variable.h +objspace_dump.o: $(hdrdir)/ruby/internal/warning_push.h +objspace_dump.o: $(hdrdir)/ruby/internal/xmalloc.h objspace_dump.o: $(hdrdir)/ruby/io.h objspace_dump.o: $(hdrdir)/ruby/missing.h objspace_dump.o: $(hdrdir)/ruby/onigmo.h @@ -54,12 +525,25 @@ objspace_dump.o: $(hdrdir)/ruby/ruby.h objspace_dump.o: $(hdrdir)/ruby/st.h objspace_dump.o: $(hdrdir)/ruby/subst.h objspace_dump.o: $(hdrdir)/ruby/thread_native.h +objspace_dump.o: $(hdrdir)/ruby/util.h objspace_dump.o: $(top_srcdir)/ccan/check_type/check_type.h 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)/darray.h objspace_dump.o: $(top_srcdir)/gc.h objspace_dump.o: $(top_srcdir)/internal.h +objspace_dump.o: $(top_srcdir)/internal/array.h +objspace_dump.o: $(top_srcdir)/internal/compilers.h +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/sanitizers.h +objspace_dump.o: $(top_srcdir)/internal/serial.h +objspace_dump.o: $(top_srcdir)/internal/static_assert.h +objspace_dump.o: $(top_srcdir)/internal/string.h +objspace_dump.o: $(top_srcdir)/internal/vm.h +objspace_dump.o: $(top_srcdir)/internal/warnings.h objspace_dump.o: $(top_srcdir)/method.h objspace_dump.o: $(top_srcdir)/node.h objspace_dump.o: $(top_srcdir)/ruby_assert.h diff --git a/ruby/ext/objspace/lib/objspace.rb b/ruby/ext/objspace/lib/objspace.rb new file mode 100644 index 000000000..0298b0646 --- /dev/null +++ b/ruby/ext/objspace/lib/objspace.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +require 'objspace.so' + +module ObjectSpace + class << self + private :_dump + private :_dump_all + end + + module_function + + # call-seq: + # ObjectSpace.dump(obj[, output: :string]) # => "{ ... }" + # ObjectSpace.dump(obj, output: :file) # => # + # ObjectSpace.dump(obj, output: :stdout) # => nil + # + # Dump the contents of a ruby object as JSON. + # + # This method is only expected to work with C Ruby. + # This is an experimental method and is subject to change. + # In particular, the function signature and output format are + # not guaranteed to be compatible in future versions of ruby. + def dump(obj, output: :string) + out = case output + when :file, nil + require 'tempfile' + Tempfile.create(%w(rubyobj .json)) + when :stdout + STDOUT + when :string + +'' + when IO + output + else + raise ArgumentError, "wrong output option: #{output.inspect}" + end + + ret = _dump(obj, out) + return nil if output == :stdout + ret + end + + + # call-seq: + # ObjectSpace.dump_all([output: :file]) # => # + # ObjectSpace.dump_all(output: :stdout) # => nil + # ObjectSpace.dump_all(output: :string) # => "{...}\n{...}\n..." + # ObjectSpace.dump_all(output: + # File.open('heap.json','w')) # => # + # ObjectSpace.dump_all(output: :string, + # since: 42) # => "{...}\n{...}\n..." + # + # Dump the contents of the ruby heap as JSON. + # + # _since_ must be a non-negative integer or +nil+. + # + # If _since_ is a positive integer, only objects of that generation and + # newer generations are dumped. The current generation can be accessed using + # GC::count. + # + # Objects that were allocated without object allocation tracing enabled + # are ignored. See ::trace_object_allocations for more information and + # examples. + # + # If _since_ is omitted or is +nil+, all objects are dumped. + # + # This method is only expected to work with C Ruby. + # This is an experimental method and is subject to change. + # In particular, the function signature and output format are + # not guaranteed to be compatible in future versions of ruby. + def dump_all(output: :file, full: false, since: nil) + out = case output + when :file, nil + require 'tempfile' + Tempfile.create(%w(rubyheap .json)) + when :stdout + STDOUT + when :string + +'' + when IO + output + else + raise ArgumentError, "wrong output option: #{output.inspect}" + end + + ret = _dump_all(out, full, since) + return nil if output == :stdout + ret + end +end diff --git a/ruby/ext/objspace/lib/objspace/trace.rb b/ruby/ext/objspace/lib/objspace/trace.rb new file mode 100644 index 000000000..c23f5a9d5 --- /dev/null +++ b/ruby/ext/objspace/lib/objspace/trace.rb @@ -0,0 +1,45 @@ +# This is a simple tool to enable the object allocation tracer. +# When you have an object of unknown provenance, you can use this +# to investigate where the object in question is created. +# +# = Important notice +# +# This is only for debugging purpose. Do not use this in production. +# Require'ing this file immediately starts tracing the object allocation, +# which brings a large performance overhead. +# +# = Usage +# +# 1. Add `require "objspace/trace"` into your code (or add `-robjspace/trace` into the command line) +# 2. `p obj` will show the allocation site of `obj` +# +# Note: This redefines `Kernel#p` method, but not `Object#inspect`. +# +# = Examples +# +# 1: require "objspace/trace" +# 2: +# 3: obj = "str" +# 4: +# 5: p obj #=> "str" @ test.rb:3 + +require 'objspace.so' + +module Kernel + remove_method :p + define_method(:p) do |*objs| + objs.each do |obj| + file = ObjectSpace.allocation_sourcefile(obj) + line = ObjectSpace.allocation_sourceline(obj) + if file + puts "#{ obj.inspect } @ #{ file }:#{ line }" + else + puts obj.inspect + end + end + end +end + +ObjectSpace.trace_object_allocations_start + +warn "objspace/trace is enabled" diff --git a/ruby/ext/objspace/object_tracing.c b/ruby/ext/objspace/object_tracing.c index a057ac2a9..66d6baa49 100644 --- a/ruby/ext/objspace/object_tracing.c +++ b/ruby/ext/objspace/object_tracing.c @@ -151,6 +151,81 @@ free_values_i(st_data_t key, st_data_t value, st_data_t data) return ST_CONTINUE; } +static void +allocation_info_tracer_mark(void *ptr) +{ + struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr; + rb_gc_mark(trace_arg->newobj_trace); + rb_gc_mark(trace_arg->freeobj_trace); +} + +static void +allocation_info_tracer_free(void *ptr) +{ + struct traceobj_arg *arg = (struct traceobj_arg *)ptr; + /* clear tables */ + st_foreach(arg->object_table, free_values_i, 0); + st_free_table(arg->object_table); + st_foreach(arg->str_table, free_keys_i, 0); + st_free_table(arg->str_table); + xfree(arg); +} + +static size_t +allocation_info_tracer_memsize(const void *ptr) +{ + size_t size; + struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr; + size = sizeof(*trace_arg); + size += st_memsize(trace_arg->object_table); + size += st_memsize(trace_arg->str_table); + return size; +} + +static int +hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error) +{ + VALUE allocated_object; + + allocated_object = (VALUE)value; + if (allocated_object != rb_gc_location(allocated_object)) { + return ST_REPLACE; + } + + return ST_CONTINUE; +} + +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_CONTINUE; +} + +static void +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)) { + rb_raise(rb_eRuntimeError, "hash modified during iteration"); + } +} + +static const rb_data_type_t allocation_info_tracer_type = { + "ObjectTracing/allocation_info_tracer", + { + allocation_info_tracer_mark, + allocation_info_tracer_free, /* Never called because global */ + allocation_info_tracer_memsize, + allocation_info_tracer_compact, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static VALUE traceobj_arg; static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */ static int tmp_keep_remains; /* TODO: Do not use global variables */ @@ -158,7 +233,9 @@ static struct traceobj_arg * get_traceobj_arg(void) { if (tmp_trace_arg == 0) { - tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1); + VALUE obj = TypedData_Make_Struct(rb_cObject, struct traceobj_arg, &allocation_info_tracer_type, tmp_trace_arg); + traceobj_arg = obj; + rb_gc_register_mark_object(traceobj_arg); tmp_trace_arg->running = 0; tmp_trace_arg->keep_remains = tmp_keep_remains; tmp_trace_arg->newobj_trace = 0; @@ -186,9 +263,7 @@ trace_object_allocations_start(VALUE self) else { if (arg->newobj_trace == 0) { arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg); - rb_gc_register_mark_object(arg->newobj_trace); arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg); - rb_gc_register_mark_object(arg->freeobj_trace); } rb_tracepoint_enable(arg->newobj_trace); rb_tracepoint_enable(arg->freeobj_trace); @@ -216,8 +291,12 @@ trace_object_allocations_stop(VALUE self) } if (arg->running == 0) { - rb_tracepoint_disable(arg->newobj_trace); - rb_tracepoint_disable(arg->freeobj_trace); + if (arg->newobj_trace != 0) { + rb_tracepoint_disable(arg->newobj_trace); + } + if (arg->freeobj_trace != 0) { + rb_tracepoint_disable(arg->freeobj_trace); + } } return Qnil; diff --git a/ruby/ext/objspace/objspace.c b/ruby/ext/objspace/objspace.c index 311e68720..ad5bbe7d0 100644 --- a/ruby/ext/objspace/objspace.c +++ b/ruby/ext/objspace/objspace.c @@ -12,19 +12,28 @@ **********************************************************************/ -#include +#include "gc.h" #include "internal.h" -#include -#include +#include "internal/class.h" +#include "internal/compilers.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/sanitizers.h" #include "node.h" -#include "gc.h" +#include "ruby/io.h" +#include "ruby/re.h" +#include "ruby/st.h" #include "symbol.h" +#undef rb_funcall + +#include "ruby/ruby.h" + /* * call-seq: * ObjectSpace.memsize_of(obj) -> Integer * - * Return consuming memory size of obj. + * Return consuming memory size of obj in bytes. * * Note that the return size is incomplete. You need to deal with this * information as only a *HINT*. Especially, the size of +T_DATA+ may not be @@ -47,37 +56,68 @@ struct total_data { VALUE klass; }; +static void +total_i(VALUE v, void *ptr) +{ + struct total_data *data = (struct total_data *)ptr; + + switch (BUILTIN_TYPE(v)) { + case T_NONE: + case T_IMEMO: + case T_ICLASS: + case T_NODE: + case T_ZOMBIE: + return; + default: + if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) { + data->total += rb_obj_memsize_of(v); + } + } +} + +typedef void (*each_obj_with_flags)(VALUE, void*); + +struct obj_itr { + each_obj_with_flags cb; + void *data; +}; + static int -total_i(void *vstart, void *vend, size_t stride, void *ptr) +heap_iter(void *vstart, void *vend, size_t stride, void *ptr) { + struct obj_itr * ctx = (struct obj_itr *)ptr; VALUE v; - struct total_data *data = (struct total_data *)ptr; for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags) { - switch (BUILTIN_TYPE(v)) { - case T_NONE: - case T_IMEMO: - case T_ICLASS: - case T_NODE: - case T_ZOMBIE: - continue; - default: - if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) { - data->total += rb_obj_memsize_of(v); - } - } - } + void *poisoned = asan_poisoned_object_p(v); + asan_unpoison_object(v, false); + + if (RBASIC(v)->flags) { + (*ctx->cb)(v, ctx->data); + } + + if (poisoned) { + asan_poison_object(v); + } } return 0; } +static void +each_object_with_flags(each_obj_with_flags cb, void *ctx) +{ + struct obj_itr data; + data.cb = cb; + data.data = ctx; + rb_objspace_each_objects(heap_iter, &data); +} + /* * call-seq: * ObjectSpace.memsize_of_all([klass]) -> Integer * - * Return consuming memory size of all living objects. + * Return consuming memory size of all living objects in bytes. * * If +klass+ (should be Class object) is given, return the total memory size * of instances of the given class. @@ -110,7 +150,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "01", &data.klass); } - rb_objspace_each_objects(total_i, &data); + each_object_with_flags(total_i, &data); return SIZET2NUM(data.total); } @@ -137,24 +177,18 @@ setup_hash(int argc, VALUE *argv) hash = rb_hash_new(); } else if (!RHASH_EMPTY_P(hash)) { - st_foreach(RHASH_TBL(hash), set_zero_i, hash); + /* WB: no new reference */ + st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash); } return hash; } -static int -cos_i(void *vstart, void *vend, size_t stride, void *data) +static void +cos_i(VALUE v, void *data) { size_t *counts = (size_t *)data; - VALUE v = (VALUE)vstart; - - for (;v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags) { - counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v); - } - } - return 0; + counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v); } static VALUE @@ -231,7 +265,7 @@ count_objects_size(int argc, VALUE *argv, VALUE os) counts[i] = 0; } - rb_objspace_each_objects(cos_i, &counts[0]); + each_object_with_flags(cos_i, &counts[0]); for (i = 0; i <= T_MASK; i++) { if (counts[i]) { @@ -249,25 +283,20 @@ struct dynamic_symbol_counts { size_t immortal; }; -static int -cs_i(void *vstart, void *vend, size_t stride, void *n) +static void +cs_i(VALUE v, void *n) { struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n; - VALUE v = (VALUE)vstart; - for (; v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) { - ID id = RSYMBOL(v)->id; - if ((id & ~ID_SCOPE_MASK) == 0) { - counts->mortal++; - } - else { - counts->immortal++; - } - } + if (BUILTIN_TYPE(v) == T_SYMBOL) { + ID id = RSYMBOL(v)->id; + if ((id & ~ID_SCOPE_MASK) == 0) { + counts->mortal++; + } + else { + counts->immortal++; + } } - - return 0; } size_t rb_sym_immortal_count(void); @@ -305,7 +334,7 @@ count_symbols(int argc, VALUE *argv, VALUE os) VALUE hash = setup_hash(argc, argv); size_t immortal_symbols = rb_sym_immortal_count(); - rb_objspace_each_objects(cs_i, &dynamic_counts); + each_object_with_flags(cs_i, &dynamic_counts); rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal)); rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal)); @@ -315,20 +344,15 @@ count_symbols(int argc, VALUE *argv, VALUE os) return hash; } -static int -cn_i(void *vstart, void *vend, size_t stride, void *n) +static void +cn_i(VALUE v, void *n) { size_t *nodes = (size_t *)n; - VALUE v = (VALUE)vstart; - for (; v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) { - size_t s = nd_type((NODE *)v); - nodes[s]++; - } + if (BUILTIN_TYPE(v) == T_NODE) { + size_t s = nd_type((NODE *)v); + nodes[s]++; } - - return 0; } /* @@ -365,7 +389,7 @@ count_nodes(int argc, VALUE *argv, VALUE os) nodes[i] = 0; } - rb_objspace_each_objects(cn_i, &nodes[0]); + each_object_with_flags(cn_i, &nodes[0]); for (i=0; iflags && BUILTIN_TYPE(v) == T_DATA) { - VALUE counter; - VALUE key = RBASIC(v)->klass; - - if (key == 0) { - const char *name = rb_objspace_data_type_name(v); - if (name == 0) name = "unknown"; - key = ID2SYM(rb_intern(name)); - } - counter = rb_hash_aref(hash, key); - if (NIL_P(counter)) { - counter = INT2FIX(1); - } - else { - counter = INT2FIX(FIX2INT(counter) + 1); - } - - rb_hash_aset(hash, key, counter); - } + if (BUILTIN_TYPE(v) == T_DATA) { + VALUE counter; + VALUE key = RBASIC(v)->klass; + + if (key == 0) { + const char *name = rb_objspace_data_type_name(v); + if (name == 0) name = "unknown"; + key = ID2SYM(rb_intern(name)); + } + + counter = rb_hash_aref(hash, key); + if (NIL_P(counter)) { + counter = INT2FIX(1); + } + else { + counter = INT2FIX(FIX2INT(counter) + 1); + } + + rb_hash_aset(hash, key, counter); } - - return 0; } /* @@ -555,37 +574,32 @@ static VALUE count_tdata_objects(int argc, VALUE *argv, VALUE self) { VALUE hash = setup_hash(argc, argv); - rb_objspace_each_objects(cto_i, (void *)hash); + each_object_with_flags(cto_i, (void *)hash); return hash; } static ID imemo_type_ids[IMEMO_MASK+1]; -static int -count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data) +static void +count_imemo_objects_i(VALUE v, void *data) { VALUE hash = (VALUE)data; - VALUE v = (VALUE)vstart; - for (; v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_IMEMO) { - VALUE counter; - VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]); + if (BUILTIN_TYPE(v) == T_IMEMO) { + VALUE counter; + VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]); - counter = rb_hash_aref(hash, key); + counter = rb_hash_aref(hash, key); - if (NIL_P(counter)) { - counter = INT2FIX(1); - } - else { - counter = INT2FIX(FIX2INT(counter) + 1); - } + if (NIL_P(counter)) { + counter = INT2FIX(1); + } + else { + counter = INT2FIX(FIX2INT(counter) + 1); + } - rb_hash_aset(hash, key, counter); - } + rb_hash_aset(hash, key, counter); } - - return 0; } /* @@ -633,9 +647,12 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self) imemo_type_ids[8] = rb_intern("imemo_tmpbuf"); imemo_type_ids[9] = rb_intern("imemo_ast"); imemo_type_ids[10] = rb_intern("imemo_parser_strterm"); + imemo_type_ids[11] = rb_intern("imemo_callinfo"); + imemo_type_ids[12] = rb_intern("imemo_callcache"); + imemo_type_ids[13] = rb_intern("imemo_constcache"); } - rb_objspace_each_objects(count_imemo_objects_i, (void *)hash); + each_object_with_flags(count_imemo_objects_i, (void *)hash); return hash; } @@ -659,12 +676,12 @@ static const rb_data_type_t iow_data_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; -static VALUE rb_mInternalObjectWrapper; +static VALUE rb_cInternalObjectWrapper; static VALUE iow_newobj(VALUE obj) { - return TypedData_Wrap_Struct(rb_mInternalObjectWrapper, &iow_data_type, (void *)obj); + return TypedData_Wrap_Struct(rb_cInternalObjectWrapper, &iow_data_type, (void *)obj); } /* Returns the type of the internal object. */ @@ -694,7 +711,7 @@ iow_internal_object_id(VALUE self) } struct rof_data { - st_table *refs; + VALUE refs; VALUE internals; }; @@ -710,7 +727,7 @@ reachable_object_from_i(VALUE obj, void *data_ptr) val = iow_newobj(obj); rb_ary_push(data->internals, val); } - st_insert(data->refs, key, val); + rb_hash_aset(data->refs, key, val); } } @@ -768,20 +785,18 @@ static VALUE reachable_objects_from(VALUE self, VALUE obj) { if (rb_objspace_markable_object_p(obj)) { - VALUE ret = rb_ary_new(); struct rof_data data; if (rb_typeddata_is_kind_of(obj, &iow_data_type)) { obj = (VALUE)DATA_PTR(obj); } - data.refs = st_init_numtable(); + data.refs = rb_ident_hash_new(); data.internals = rb_ary_new(); rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data); - st_foreach(data.refs, collect_values, (st_data_t)ret); - return ret; + return rb_funcall(data.refs, rb_intern("values"), 0); } else { return Qnil; @@ -860,7 +875,8 @@ wrap_klass_iow(VALUE klass) if (!RTEST(klass)) { return Qnil; } - else if (RB_TYPE_P(klass, T_ICLASS)) { + else if (RB_TYPE_P(klass, T_ICLASS) || + CLASS_OF(klass) == Qfalse /* hidden object */) { return iow_newobj(klass); } else { @@ -886,8 +902,13 @@ objspace_internal_class_of(VALUE self, VALUE obj) obj = (VALUE)DATA_PTR(obj); } - klass = CLASS_OF(obj); - return wrap_klass_iow(klass); + if (RB_TYPE_P(obj, T_IMEMO)) { + return Qnil; + } + else { + klass = CLASS_OF(obj); + return wrap_klass_iow(klass); + } } /* @@ -973,10 +994,11 @@ Init_objspace(void) * * You can use the #type method to check the type of the internal object. */ - rb_mInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject); - rb_define_method(rb_mInternalObjectWrapper, "type", iow_type, 0); - rb_define_method(rb_mInternalObjectWrapper, "inspect", iow_inspect, 0); - rb_define_method(rb_mInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0); + rb_cInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject); + rb_undef_alloc_func(rb_cInternalObjectWrapper); + rb_define_method(rb_cInternalObjectWrapper, "type", iow_type, 0); + rb_define_method(rb_cInternalObjectWrapper, "inspect", iow_inspect, 0); + rb_define_method(rb_cInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0); Init_object_tracing(rb_mObjSpace); Init_objspace_dump(rb_mObjSpace); diff --git a/ruby/ext/objspace/objspace_dump.c b/ruby/ext/objspace/objspace_dump.c index 5fa9d98e3..cf7acb5c6 100644 --- a/ruby/ext/objspace/objspace_dump.c +++ b/ruby/ext/objspace/objspace_dump.c @@ -12,20 +12,25 @@ **********************************************************************/ -#include "ruby/io.h" -#include "internal.h" -#include "ruby/debug.h" #include "gc.h" +#include "internal.h" +#include "internal/hash.h" +#include "internal/string.h" +#include "internal/sanitizers.h" #include "node.h" -#include "vm_core.h" #include "objspace.h" +#include "ruby/debug.h" +#include "ruby/util.h" +#include "ruby/io.h" +#include "vm_core.h" + +RUBY_EXTERN const char ruby_hexdigits[]; -static VALUE sym_output, sym_stdout, sym_string, sym_file; -static VALUE sym_full; +#define BUFFER_CAPACITY 4096 struct dump_config { VALUE type; - FILE *stream; + VALUE stream; VALUE string; const char *root_category; VALUE cur_obj; @@ -33,22 +38,143 @@ struct dump_config { size_t cur_obj_references; unsigned int roots: 1; unsigned int full_heap: 1; + unsigned int partial_dump; + size_t since; + unsigned long buffer_len; + char buffer[BUFFER_CAPACITY]; }; -PRINTF_ARGS(static void dump_append(struct dump_config *, const char *, ...), 2, 3); static void -dump_append(struct dump_config *dc, const char *format, ...) +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); + if (written < dc->buffer_len) { + MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written); + dc->buffer_len -= written; + return; + } + } + else if (dc->string) { + rb_str_cat(dc->string, dc->buffer, dc->buffer_len); + } + dc->buffer_len = 0; + } +} + +static inline void +buffer_ensure_capa(struct dump_config *dc, unsigned long requested) +{ + RUBY_ASSERT(requested <= BUFFER_CAPACITY); + if (requested + dc->buffer_len >= BUFFER_CAPACITY) { + dump_flush(dc); + if (requested + dc->buffer_len >= BUFFER_CAPACITY) { + rb_raise(rb_eIOError, "full buffer"); + } + } +} + +static void buffer_append(struct dump_config *dc, const char *cstr, unsigned long len) +{ + if (LIKELY(len > 0)) { + buffer_ensure_capa(dc, len); + MEMCPY(dc->buffer + dc->buffer_len, cstr, char, len); + dc->buffer_len += len; + } +} + +# define dump_append(dc, str) buffer_append(dc, (str), (long)strlen(str)) + +static void +dump_append_ld(struct dump_config *dc, const long number) +{ + const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2; + buffer_ensure_capa(dc, width); + unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%ld", number); + RUBY_ASSERT(required <= width); + dc->buffer_len += required; +} + +static void +dump_append_lu(struct dump_config *dc, const unsigned long number) +{ + const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1; + buffer_ensure_capa(dc, width); + unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%lu", number); + RUBY_ASSERT(required <= width); + dc->buffer_len += required; +} + +static void +dump_append_g(struct dump_config *dc, const double number) +{ + unsigned long capa_left = BUFFER_CAPACITY - dc->buffer_len; + unsigned long required = snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number); + + if (required >= capa_left) { + buffer_ensure_capa(dc, required); + capa_left = BUFFER_CAPACITY - dc->buffer_len; + snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number); + } + dc->buffer_len += required; +} + +static void +dump_append_d(struct dump_config *dc, const int number) +{ + const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2; + buffer_ensure_capa(dc, width); + unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%d", number); + RUBY_ASSERT(required <= width); + dc->buffer_len += required; +} + +static void +dump_append_sizet(struct dump_config *dc, const size_t number) { - va_list vl; - va_start(vl, format); + const unsigned int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1; + buffer_ensure_capa(dc, width); + unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%"PRIuSIZE, number); + RUBY_ASSERT(required <= width); + dc->buffer_len += required; +} - if (dc->stream) { - vfprintf(dc->stream, format, vl); +static void +dump_append_c(struct dump_config *dc, char c) +{ + if (c <= 0x1f) { + const unsigned int width = (sizeof(c) * CHAR_BIT / 4) + 5; + buffer_ensure_capa(dc, width); + unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "\\u00%02x", c); + RUBY_ASSERT(required <= width); + dc->buffer_len += required; + } + else { + buffer_ensure_capa(dc, 1); + dc->buffer[dc->buffer_len] = c; + dc->buffer_len++; } - else if (dc->string) - rb_str_vcatf(dc->string, format, vl); +} + +static void +dump_append_ref(struct dump_config *dc, VALUE ref) +{ + RUBY_ASSERT(ref > 0); + + char buffer[((sizeof(VALUE) * CHAR_BIT + 3) / 4) + 4]; + char *buffer_start, *buffer_end; - va_end(vl); + buffer_start = buffer_end = &buffer[sizeof(buffer)]; + *--buffer_start = '"'; + while (ref) { + *--buffer_start = ruby_hexdigits[ref & 0xF]; + ref >>= 4; + } + *--buffer_start = 'x'; + *--buffer_start = '0'; + *--buffer_start = '"'; + buffer_append(dc, buffer_start, buffer_end - buffer_start); } static void @@ -60,35 +186,37 @@ dump_append_string_value(struct dump_config *dc, VALUE obj) dump_append(dc, "\""); for (i = 0, value = RSTRING_PTR(obj); i < RSTRING_LEN(obj); i++) { - switch ((c = value[i])) { - case '\\': - case '"': - dump_append(dc, "\\%c", c); - break; - case '\0': - dump_append(dc, "\\u0000"); - break; - case '\b': - dump_append(dc, "\\b"); - break; - case '\t': - dump_append(dc, "\\t"); - break; - case '\f': - dump_append(dc, "\\f"); - break; - case '\n': - dump_append(dc, "\\n"); - break; - case '\r': - dump_append(dc, "\\r"); - break; - default: - if (c <= 0x1f) - dump_append(dc, "\\u%04d", c); - else - dump_append(dc, "%c", c); - } + switch ((c = value[i])) { + case '\\': + dump_append(dc, "\\\\"); + break; + case '"': + dump_append(dc, "\\\""); + break; + case '\0': + dump_append(dc, "\\u0000"); + break; + case '\b': + dump_append(dc, "\\b"); + break; + case '\t': + dump_append(dc, "\\t"); + break; + case '\f': + dump_append(dc, "\\f"); + break; + case '\n': + dump_append(dc, "\\n"); + break; + case '\r': + dump_append(dc, "\\r"); + break; + case '\177': + dump_append(dc, "\\u007f"); + break; + default: + dump_append_c(dc, c); + } } dump_append(dc, "\""); } @@ -133,6 +261,7 @@ obj_type(VALUE obj) CASE_TYPE(NODE); CASE_TYPE(ZOMBIE); #undef CASE_TYPE + default: break; } return "UNKNOWN"; } @@ -141,25 +270,25 @@ static void dump_append_special_const(struct dump_config *dc, VALUE value) { if (value == Qtrue) { - dump_append(dc, "true"); + dump_append(dc, "true"); } else if (value == Qfalse) { - dump_append(dc, "false"); + dump_append(dc, "false"); } else if (value == Qnil) { - dump_append(dc, "null"); + dump_append(dc, "null"); } else if (FIXNUM_P(value)) { - dump_append(dc, "%ld", FIX2LONG(value)); + dump_append_ld(dc, FIX2LONG(value)); } else if (FLONUM_P(value)) { - dump_append(dc, "%#g", RFLOAT_VALUE(value)); + dump_append_g(dc, RFLOAT_VALUE(value)); } else if (SYMBOL_P(value)) { - dump_append_symbol_value(dc, value); + dump_append_symbol_value(dc, value); } else { - dump_append(dc, "{}"); + dump_append(dc, "{}"); } } @@ -169,12 +298,16 @@ reachable_object_i(VALUE ref, void *data) struct dump_config *dc = (struct dump_config *)data; if (dc->cur_obj_klass == ref) - return; + return; - if (dc->cur_obj_references == 0) - dump_append(dc, ", \"references\":[\"%#"PRIxVALUE"\"", ref); - else - dump_append(dc, ", \"%#"PRIxVALUE"\"", ref); + if (dc->cur_obj_references == 0) { + dump_append(dc, ", \"references\":["); + dump_append_ref(dc, ref); + } + else { + dump_append(dc, ", "); + dump_append_ref(dc, ref); + } dc->cur_obj_references++; } @@ -182,35 +315,16 @@ reachable_object_i(VALUE ref, void *data) static void dump_append_string_content(struct dump_config *dc, VALUE obj) { - dump_append(dc, ", \"bytesize\":%ld", RSTRING_LEN(obj)); - if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) - dump_append(dc, ", \"capacity\":%"PRIuSIZE, rb_str_capacity(obj)); - - if (is_ascii_string(obj)) { - dump_append(dc, ", \"value\":"); - dump_append_string_value(dc, obj); + dump_append(dc, ", \"bytesize\":"); + dump_append_ld(dc, RSTRING_LEN(obj)); + if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) { + dump_append(dc, ", \"capacity\":"); + dump_append_sizet(dc, rb_str_capacity(obj)); } -} -static const char * -imemo_name(int imemo) -{ - switch(imemo) { -#define TYPE_STR(t) case(imemo_##t): return #t - TYPE_STR(env); - TYPE_STR(cref); - TYPE_STR(svar); - TYPE_STR(throw_data); - TYPE_STR(ifunc); - TYPE_STR(memo); - TYPE_STR(ment); - TYPE_STR(iseq); - TYPE_STR(tmpbuf); - TYPE_STR(ast); - TYPE_STR(parser_strterm); - default: - return "unknown"; -#undef TYPE_STR + if (is_ascii_string(obj)) { + dump_append(dc, ", \"value\":"); + dump_append_string_value(dc, obj); } } @@ -218,126 +332,200 @@ static void dump_object(VALUE obj, struct dump_config *dc) { size_t memsize; - struct allocation_info *ainfo; + struct allocation_info *ainfo = objspace_lookup_allocation_info(obj); rb_io_t *fptr; ID flags[RB_OBJ_GC_FLAGS_MAX]; size_t n, i; if (SPECIAL_CONST_P(obj)) { - dump_append_special_const(dc, obj); - return; + dump_append_special_const(dc, obj); + return; } dc->cur_obj = obj; dc->cur_obj_references = 0; dc->cur_obj_klass = BUILTIN_TYPE(obj) == T_NODE ? 0 : RBASIC_CLASS(obj); + if (dc->partial_dump && (!ainfo || ainfo->generation < dc->since)) { + return; + } + if (dc->cur_obj == dc->string) - return; + return; - dump_append(dc, "{\"address\":\"%#"PRIxVALUE"\", \"type\":\"%s\"", obj, obj_type(obj)); + dump_append(dc, "{\"address\":"); + dump_append_ref(dc, obj); - if (dc->cur_obj_klass) - dump_append(dc, ", \"class\":\"%#"PRIxVALUE"\"", dc->cur_obj_klass); + dump_append(dc, ", \"type\":\""); + dump_append(dc, obj_type(obj)); + dump_append(dc, "\""); + + if (dc->cur_obj_klass) { + dump_append(dc, ", \"class\":"); + dump_append_ref(dc, dc->cur_obj_klass); + } if (rb_obj_frozen_p(obj)) - dump_append(dc, ", \"frozen\":true"); + dump_append(dc, ", \"frozen\":true"); switch (BUILTIN_TYPE(obj)) { case T_NONE: - dump_append(dc, "}\n"); - return; + dump_append(dc, "}\n"); + return; case T_IMEMO: - dump_append(dc, ", \"imemo_type\":\"%s\"", imemo_name(imemo_type(obj))); - break; + dump_append(dc, ", \"imemo_type\":\""); + dump_append(dc, rb_imemo_name(imemo_type(obj))); + dump_append(dc, "\""); + break; case T_SYMBOL: - dump_append_string_content(dc, rb_sym2str(obj)); - break; + dump_append_string_content(dc, rb_sym2str(obj)); + break; case T_STRING: - if (STR_EMBED_P(obj)) - dump_append(dc, ", \"embedded\":true"); - if (is_broken_string(obj)) - dump_append(dc, ", \"broken\":true"); - if (FL_TEST(obj, RSTRING_FSTR)) - dump_append(dc, ", \"fstring\":true"); - if (STR_SHARED_P(obj)) - dump_append(dc, ", \"shared\":true"); - else - dump_append_string_content(dc, obj); - - if (!ENCODING_IS_ASCII8BIT(obj)) - dump_append(dc, ", \"encoding\":\"%s\"", rb_enc_name(rb_enc_from_index(ENCODING_GET(obj)))); - break; + if (STR_EMBED_P(obj)) + dump_append(dc, ", \"embedded\":true"); + if (is_broken_string(obj)) + dump_append(dc, ", \"broken\":true"); + if (FL_TEST(obj, RSTRING_FSTR)) + dump_append(dc, ", \"fstring\":true"); + if (STR_SHARED_P(obj)) + dump_append(dc, ", \"shared\":true"); + else + dump_append_string_content(dc, obj); + + if (!ENCODING_IS_ASCII8BIT(obj)) { + dump_append(dc, ", \"encoding\":\""); + dump_append(dc, rb_enc_name(rb_enc_from_index(ENCODING_GET(obj)))); + dump_append(dc, "\""); + } + break; case T_HASH: - dump_append(dc, ", \"size\":%"PRIuSIZE, (size_t)RHASH_SIZE(obj)); - if (FL_TEST(obj, RHASH_PROC_DEFAULT)) - dump_append(dc, ", \"default\":\"%#"PRIxVALUE"\"", RHASH_IFNONE(obj)); - break; + dump_append(dc, ", \"size\":"); + dump_append_sizet(dc, (size_t)RHASH_SIZE(obj)); + if (FL_TEST(obj, RHASH_PROC_DEFAULT)) { + dump_append(dc, ", \"default\":"); + dump_append_ref(dc, RHASH_IFNONE(obj)); + } + break; case T_ARRAY: - dump_append(dc, ", \"length\":%ld", RARRAY_LEN(obj)); - if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED)) - dump_append(dc, ", \"shared\":true"); - if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG)) - dump_append(dc, ", \"embedded\":true"); - break; + dump_append(dc, ", \"length\":"); + dump_append_ld(dc, RARRAY_LEN(obj)); + if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED)) + dump_append(dc, ", \"shared\":true"); + if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG)) + dump_append(dc, ", \"embedded\":true"); + break; + + case T_ICLASS: + if (rb_class_get_superclass(obj)) { + dump_append(dc, ", \"superclass\":"); + dump_append_ref(dc, rb_class_get_superclass(obj)); + } + break; case T_CLASS: case T_MODULE: - if (dc->cur_obj_klass) - dump_append(dc, ", \"name\":\"%s\"", rb_class2name(obj)); - break; + if (rb_class_get_superclass(obj)) { + dump_append(dc, ", \"superclass\":"); + dump_append_ref(dc, rb_class_get_superclass(obj)); + } + + 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, "\""); + } else { + VALUE real_mod_name = rb_mod_name(rb_class_real(obj)); + if (RTEST(real_mod_name)) { + dump_append(dc, ", \"real_class_name\":\""); + dump_append(dc, RSTRING_PTR(real_mod_name)); + dump_append(dc, "\""); + } + } + + if (FL_TEST(obj, FL_SINGLETON)) { + dump_append(dc, ", \"singleton\":true"); + } + } + break; case T_DATA: - if (RTYPEDDATA_P(obj)) - dump_append(dc, ", \"struct\":\"%s\"", RTYPEDDATA_TYPE(obj)->wrap_struct_name); - break; + if (RTYPEDDATA_P(obj)) { + dump_append(dc, ", \"struct\":\""); + dump_append(dc, RTYPEDDATA_TYPE(obj)->wrap_struct_name); + dump_append(dc, "\""); + } + break; case T_FLOAT: - dump_append(dc, ", \"value\":\"%g\"", RFLOAT_VALUE(obj)); - break; + dump_append(dc, ", \"value\":\""); + dump_append_g(dc, RFLOAT_VALUE(obj)); + dump_append(dc, "\""); + break; case T_OBJECT: - dump_append(dc, ", \"ivars\":%u", ROBJECT_NUMIV(obj)); - break; + dump_append(dc, ", \"ivars\":"); + dump_append_lu(dc, ROBJECT_NUMIV(obj)); + break; case T_FILE: - fptr = RFILE(obj)->fptr; - if (fptr) - dump_append(dc, ", \"fd\":%d", fptr->fd); - break; + fptr = RFILE(obj)->fptr; + if (fptr) { + dump_append(dc, ", \"fd\":"); + dump_append_d(dc, fptr->fd); + } + break; case T_ZOMBIE: - dump_append(dc, "}\n"); - return; + dump_append(dc, "}\n"); + return; + + default: + break; } rb_objspace_reachable_objects_from(obj, reachable_object_i, dc); if (dc->cur_obj_references > 0) - dump_append(dc, "]"); - - if ((ainfo = objspace_lookup_allocation_info(obj))) { - dump_append(dc, ", \"file\":\"%s\", \"line\":%lu", ainfo->path, ainfo->line); - if (RTEST(ainfo->mid)) { - VALUE m = rb_sym2str(ainfo->mid); - dump_append(dc, ", \"method\":\"%s\"", RSTRING_PTR(m)); - } - dump_append(dc, ", \"generation\":%"PRIuSIZE, ainfo->generation); + dump_append(dc, "]"); + + if (ainfo) { + if (ainfo->path) { + dump_append(dc, ", \"file\":\""); + dump_append(dc, ainfo->path); + dump_append(dc, "\""); + } + if (ainfo->line) { + dump_append(dc, ", \"line\":"); + dump_append_lu(dc, ainfo->line); + } + if (RTEST(ainfo->mid)) { + VALUE m = rb_sym2str(ainfo->mid); + dump_append(dc, ", \"method\":"); + dump_append_string_value(dc, m); + } + dump_append(dc, ", \"generation\":"); + dump_append_sizet(dc, ainfo->generation); } - if ((memsize = rb_obj_memsize_of(obj)) > 0) - dump_append(dc, ", \"memsize\":%"PRIuSIZE, memsize); + if ((memsize = rb_obj_memsize_of(obj)) > 0) { + dump_append(dc, ", \"memsize\":"); + dump_append_sizet(dc, memsize); + } if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) { - dump_append(dc, ", \"flags\":{"); - for (i=0; ifull_heap || RBASIC(v)->flags) dump_object(v, dc); + + if (ptr) { + asan_poison_object(v); + } } return 0; } @@ -361,138 +556,89 @@ root_obj_i(const char *category, VALUE obj, void *data) struct dump_config *dc = (struct dump_config *)data; if (dc->root_category != NULL && category != dc->root_category) - dump_append(dc, "]}\n"); - if (dc->root_category == NULL || category != dc->root_category) - dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"%s\", \"references\":[\"%#"PRIxVALUE"\"", category, obj); - else - dump_append(dc, ", \"%#"PRIxVALUE"\"", obj); + dump_append(dc, "]}\n"); + if (dc->root_category == NULL || category != dc->root_category) { + dump_append(dc, "{\"type\":\"ROOT\", \"root\":\""); + dump_append(dc, category); + dump_append(dc, "\", \"references\":["); + dump_append_ref(dc, obj); + } + else { + dump_append(dc, ", "); + dump_append_ref(dc, obj); + } dc->root_category = category; dc->roots = 1; } -static VALUE -dump_output(struct dump_config *dc, VALUE opts, VALUE output, const char *filename) +static void +dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since) { - VALUE tmp; dc->full_heap = 0; - - if (RTEST(opts)) { - output = rb_hash_aref(opts, sym_output); - - if (Qtrue == rb_hash_lookup2(opts, sym_full, Qfalse)) - dc->full_heap = 1; + dc->buffer_len = 0; + + if (TYPE(output) == T_STRING) { + dc->stream = Qfalse; + dc->string = output; + } else { + dc->stream = output; + dc->string = Qfalse; } - if (output == sym_stdout) { - dc->stream = stdout; - dc->string = Qnil; - } - else if (output == sym_file) { - rb_io_t *fptr; - rb_require("tempfile"); - tmp = rb_assoc_new(rb_str_new_cstr(filename), rb_str_new_cstr(".json")); - tmp = rb_funcallv(rb_path2class("Tempfile"), rb_intern("create"), 1, &tmp); - io: - dc->string = rb_io_get_write_io(tmp); - rb_io_flush(dc->string); - GetOpenFile(dc->string, fptr); - dc->stream = rb_io_stdio_file(fptr); - } - else if (output == sym_string) { - dc->string = rb_str_new_cstr(""); + if (full == Qtrue) { + dc->full_heap = 1; } - else if (!NIL_P(tmp = rb_io_check_io(output))) { - output = sym_file; - goto io; - } - else { - rb_raise(rb_eArgError, "wrong output option: %"PRIsVALUE, output); + + if (RTEST(since)) { + dc->partial_dump = 1; + dc->since = NUM2SIZET(since); + } else { + dc->partial_dump = 0; } - return output; } static VALUE -dump_result(struct dump_config *dc, VALUE output) +dump_result(struct dump_config *dc) { - if (output == sym_string) { - return rb_str_resurrect(dc->string); - } - else if (output == sym_file) { - rb_io_flush(dc->string); - return dc->string; - } - else { - return Qnil; + dump_flush(dc); + + if (dc->string) { + return dc->string; + } else { + rb_io_flush(dc->stream); + return dc->stream; } } -/* - * call-seq: - * ObjectSpace.dump(obj[, output: :string]) # => "{ ... }" - * ObjectSpace.dump(obj, output: :file) # => # - * ObjectSpace.dump(obj, output: :stdout) # => nil - * - * Dump the contents of a ruby object as JSON. - * - * This method is only expected to work with C Ruby. - * This is an experimental method and is subject to change. - * In particular, the function signature and output format are - * not guaranteed to be compatible in future versions of ruby. - */ - static VALUE -objspace_dump(int argc, VALUE *argv, VALUE os) +objspace_dump(VALUE os, VALUE obj, VALUE output) { - static const char filename[] = "rubyobj"; - VALUE obj = Qnil, opts = Qnil, output; struct dump_config dc = {0,}; - - rb_scan_args(argc, argv, "1:", &obj, &opts); - - output = dump_output(&dc, opts, sym_string, filename); + dump_output(&dc, output, Qnil, Qnil); dump_object(obj, &dc); - return dump_result(&dc, output); + return dump_result(&dc); } -/* - * call-seq: - * ObjectSpace.dump_all([output: :file]) # => # - * ObjectSpace.dump_all(output: :stdout) # => nil - * ObjectSpace.dump_all(output: :string) # => "{...}\n{...}\n..." - * ObjectSpace.dump_all(output: - * File.open('heap.json','w')) # => # - * - * Dump the contents of the ruby heap as JSON. - * - * This method is only expected to work with C Ruby. - * This is an experimental method and is subject to change. - * In particular, the function signature and output format are - * not guaranteed to be compatible in future versions of ruby. - */ - static VALUE -objspace_dump_all(int argc, VALUE *argv, VALUE os) +objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since) { - static const char filename[] = "rubyheap"; - VALUE opts = Qnil, output; struct dump_config dc = {0,}; + dump_output(&dc, output, full, since); - rb_scan_args(argc, argv, "0:", &opts); - - output = dump_output(&dc, opts, sym_file, filename); - - /* dump roots */ - rb_objspace_reachable_objects_from_root(root_obj_i, &dc); - if (dc.roots) dump_append(&dc, "]}\n"); + if (!dc.partial_dump || dc.since == 0) { + /* dump roots */ + rb_objspace_reachable_objects_from_root(root_obj_i, &dc); + if (dc.roots) dump_append(&dc, "]}\n"); + } /* dump all objects */ rb_objspace_each_objects(heap_i, &dc); - return dump_result(&dc, output); + return dump_result(&dc); } void @@ -503,14 +649,8 @@ Init_objspace_dump(VALUE rb_mObjSpace) rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */ #endif - rb_define_module_function(rb_mObjSpace, "dump", objspace_dump, -1); - rb_define_module_function(rb_mObjSpace, "dump_all", objspace_dump_all, -1); - - sym_output = ID2SYM(rb_intern("output")); - sym_stdout = ID2SYM(rb_intern("stdout")); - sym_string = ID2SYM(rb_intern("string")); - sym_file = ID2SYM(rb_intern("file")); - sym_full = ID2SYM(rb_intern("full")); + rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2); + rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 3); /* force create static IDs */ rb_obj_gc_flags(rb_mObjSpace, 0, 0); diff --git a/ruby/ext/openssl/History.md b/ruby/ext/openssl/History.md index db5050014..479ec3b4a 100644 --- a/ruby/ext/openssl/History.md +++ b/ruby/ext/openssl/History.md @@ -1,3 +1,235 @@ +Version 3.0.0 +============= + +Compatibility notes +------------------- + +* OpenSSL 1.0.1 and Ruby 2.3-2.5 are no longer supported. + [[GitHub #396]](https://github.com/ruby/openssl/pull/396) + [[GitHub #466]](https://github.com/ruby/openssl/pull/466) + +* OpenSSL 3.0 support is added. It is the first major version bump from OpenSSL + 1.1 and contains incompatible changes that affect Ruby/OpenSSL. + Note that OpenSSL 3.0 support is preliminary and not all features are + currently available: + [[GitHub #369]](https://github.com/ruby/openssl/issues/369) + + - Deprecate the ability to modify `OpenSSL::PKey::PKey` instances. OpenSSL 3.0 + made EVP_PKEY structure immutable, and hence the following methods are not + available when Ruby/OpenSSL is linked against OpenSSL 3.0. + [[GitHub #480]](https://github.com/ruby/openssl/pull/480) + + - `OpenSSL::PKey::RSA#set_key`, `#set_factors`, `#set_crt_params` + - `OpenSSL::PKey::DSA#set_pqg`, `#set_key` + - `OpenSSL::PKey::DH#set_pqg`, `#set_key`, `#generate_key!` + - `OpenSSL::PKey::EC#private_key=`, `#public_key=`, `#group=`, `#generate_key!` + + - Deprecate `OpenSSL::Engine`. The ENGINE API has been deprecated in OpenSSL 3.0 + in favor of the new "provider" concept and will be removed in a future + version. + [[GitHub #481]](https://github.com/ruby/openssl/pull/481) + +* `OpenSSL::SSL::SSLContext#tmp_ecdh_callback` has been removed. It has been + deprecated since v2.0.0 because it is incompatible with modern OpenSSL + versions. + [[GitHub #394]](https://github.com/ruby/openssl/pull/394) + +* `OpenSSL::SSL::SSLSocket#read` and `#write` now raise `OpenSSL::SSL::SSLError` + if called before a TLS connection is established. Historically, they + read/wrote unencrypted data to the underlying socket directly in that case. + [[GitHub #9]](https://github.com/ruby/openssl/issues/9) + [[GitHub #469]](https://github.com/ruby/openssl/pull/469) + + +Notable changes +--------------- + +* Enhance OpenSSL::PKey's common interface. + [[GitHub #370]](https://github.com/ruby/openssl/issues/370) + + - Key deserialization: Enhance `OpenSSL::PKey.read` to handle PEM encoding of + DH parameters, which used to be only deserialized by `OpenSSL::PKey::DH.new`. + [[GitHub #328]](https://github.com/ruby/openssl/issues/328) + - Key generation: Add `OpenSSL::PKey.generate_parameters` and + `OpenSSL::PKey.generate_key`. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Public key signing: Enhance `OpenSSL::PKey::PKey#sign` and `#verify` to use + the new EVP_DigestSign() family to enable PureEdDSA support on OpenSSL 1.1.1 + or later. They also now take optional algorithm-specific parameters for more + control. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Low-level public key signing and verification: Add + `OpenSSL::PKey::PKey#sign_raw`, `#verify_raw`, and `#verify_recover`. + [[GitHub #382]](https://github.com/ruby/openssl/issues/382) + - Public key encryption: Add `OpenSSL::PKey::PKey#encrypt` and `#decrypt`. + [[GitHub #382]](https://github.com/ruby/openssl/issues/382) + - Key agreement: Add `OpenSSL::PKey::PKey#derive`. + [[GitHub #329]](https://github.com/ruby/openssl/issues/329) + - Key comparison: Add `OpenSSL::PKey::PKey#compare?` to conveniently check + that two keys have common parameters and a public key. + [[GitHub #383]](https://github.com/ruby/openssl/issues/383) + +* Add `OpenSSL::BN#set_flags` and `#get_flags`. This can be used in combination + with `OpenSSL::BN::CONSTTIME` to force constant-time computation. + [[GitHub #417]](https://github.com/ruby/openssl/issues/417) + +* Add `OpenSSL::BN#abs` to get the absolute value of the BIGNUM. + [[GitHub #430]](https://github.com/ruby/openssl/issues/430) + +* Add `OpenSSL::SSL::SSLSocket#getbyte`. + [[GitHub #438]](https://github.com/ruby/openssl/issues/438) + +* Add `OpenSSL::SSL::SSLContext#tmp_dh=`. + [[GitHub #459]](https://github.com/ruby/openssl/pull/459) + +* Add `OpenSSL::X509::Certificate.load` to load a PEM-encoded and concatenated + list of X.509 certificates at once. + [[GitHub #441]](https://github.com/ruby/openssl/pull/441) + +* Change `OpenSSL::X509::Certificate.new` to attempt to deserialize the given + string first as DER encoding first and then as PEM encoding to ensure the + round-trip consistency. + [[GitHub #442]](https://github.com/ruby/openssl/pull/442) + +* Update various part of the code base to use the modern API. No breaking + changes are intended with this. This includes: + + - `OpenSSL::HMAC` uses the EVP API. + [[GitHub #371]](https://github.com/ruby/openssl/issues/371) + - `OpenSSL::Config` uses native OpenSSL API to parse config files. + [[GitHub #342]](https://github.com/ruby/openssl/issues/342) + + +Version 2.2.1 +============= + +Merged changes in 2.1.3. Additionally, the following issues are fixed by this +release. + +Bug fixes +--------- + +* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when + invalid arguments are given. + [[GitHub #407]](https://github.com/ruby/openssl/pull/407) +* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms + where `time_t` has a different size from `long`. + [[GitHub #454]](https://github.com/ruby/openssl/pull/454) + + +Version 2.2.0 +============= + +Compatibility notes +------------------- + +* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms. +* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`. + [[GitHub #266]](https://github.com/ruby/openssl/pull/266) +* Deprecate `OpenSSL::Config#add_value` and `#[]=` for future removal. + [[GitHub #322]](https://github.com/ruby/openssl/pull/322) + + +Notable changes +--------------- + +* Change default `OpenSSL::SSL::SSLServer#listen` backlog argument from + 5 to `Socket::SOMAXCONN`. + [[GitHub #286]](https://github.com/ruby/openssl/issues/286) +* Make `OpenSSL::HMAC#==` use a timing safe string comparison. + [[GitHub #284]](https://github.com/ruby/openssl/pull/284) +* Add support for SHA3 and BLAKE digests. + [[GitHub #282]](https://github.com/ruby/openssl/pull/282) +* Add `OpenSSL::SSL::SSLSocket.open` for opening a `TCPSocket` and + returning an `OpenSSL::SSL::SSLSocket` for it. + [[GitHub #225]](https://github.com/ruby/openssl/issues/225) +* Support marshalling of `OpenSSL::X509` and `OpenSSL::PKey` objects. + [[GitHub #281]](https://github.com/ruby/openssl/pull/281) + [[GitHub #363]](https://github.com/ruby/openssl/pull/363) +* Add `OpenSSL.secure_compare` for timing safe string comparison for + strings of possibly unequal length. + [[GitHub #280]](https://github.com/ruby/openssl/pull/280) +* Add `OpenSSL.fixed_length_secure_compare` for timing safe string + comparison for strings of equal length. + [[GitHub #269]](https://github.com/ruby/openssl/pull/269) +* Add `OpenSSL::SSL::SSLSocket#{finished_message,peer_finished_message}` + for last finished message sent and received. + [[GitHub #250]](https://github.com/ruby/openssl/pull/250) +* Add `OpenSSL::Timestamp` module for handing timestamp requests and + responses. + [[GitHub #204]](https://github.com/ruby/openssl/pull/204) +* Add helper methods for `OpenSSL::X509::Certificate`: + `find_extension`, `subject_key_identifier`, + `authority_key_identifier`, `crl_uris`, `ca_issuer_uris` and + `ocsp_uris`, and for `OpenSSL::X509::CRL`: + `find_extension` and `subject_key_identifier`. + [[GitHub #260]](https://github.com/ruby/openssl/pull/260) + [[GitHub #275]](https://github.com/ruby/openssl/pull/275) + [[GitHub #293]](https://github.com/ruby/openssl/pull/293) +* Add `OpenSSL::ECPoint#add` for performing elliptic curve point addition. + [[GitHub #261]](https://github.com/ruby/openssl/pull/261) +* Make `OpenSSL::PKey::RSA#{export,to_der}` check `key`, `factors`, and + `crt_params` to do proper private key serialization. + [[GitHub #258]](https://github.com/ruby/openssl/pull/258) +* Add `OpenSSL::SSL::{SSLSocket,SSLServer}#fileno`, returning the + underlying socket file descriptor number. + [[GitHub #247]](https://github.com/ruby/openssl/pull/247) +* Support client certificates with TLS 1.3, and support post-handshake + authentication with OpenSSL 1.1.1+. + [[GitHub #239]](https://github.com/ruby/openssl/pull/239) +* Add `OpenSSL::ASN1::ObjectId#==` for equality testing. +* Add `OpenSSL::X509::Extension#value_der` for the raw value of + the extension. + [[GitHub #234]](https://github.com/ruby/openssl/pull/234) +* Significantly reduce allocated memory in `OpenSSL::Buffering#do_write`. + [[GitHub #212]](https://github.com/ruby/openssl/pull/212) +* Ensure all valid IPv6 addresses are considered valid as elements + of subjectAlternativeName in certificates. + [[GitHub #185]](https://github.com/ruby/openssl/pull/185) +* Allow recipient's certificate to be omitted in PCKS7#decrypt. + [[GitHub #183]](https://github.com/ruby/openssl/pull/183) +* Add support for reading keys in PKCS #8 format and export via instance methods + added to `OpenSSL::PKey` classes: `private_to_der`, `private_to_pem`, + `public_to_der` and `public_to_pem`. + [[GitHub #297]](https://github.com/ruby/openssl/pull/297) + + +Version 2.1.3 +============= + +Bug fixes +--------- + +* Fix deprecation warnings on Ruby 3.0. +* Add ".include" directive support in `OpenSSL::Config`. + [[GitHub #216]](https://github.com/ruby/openssl/pull/216) +* Fix handling of IPv6 address SANs. + [[GitHub #185]](https://github.com/ruby/openssl/pull/185) +* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=` + sets a proper error code. + [[GitHub #350]](https://github.com/ruby/openssl/pull/350) +* Fix crash with `OpenSSL::BN.new(nil, 2)`. + [[Bug #15760]](https://bugs.ruby-lang.org/issues/15760) +* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from + being modified by another thread. + [[GitHub #453]](https://github.com/ruby/openssl/pull/453) +* Fix misuse of input record separator in `OpenSSL::Buffering` where it was + for output. +* Fix wrong integer casting in `OpenSSL::PKey::EC#dsa_verify_asn1`. + [[GitHub #460]](https://github.com/ruby/openssl/pull/460) +* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or + newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support + OpenSSL 3.0 API. + [[GitHub #458]](https://github.com/ruby/openssl/pull/458) +* Activate `digest` gem correctly. `digest` library could go into an + inconsistent state if there are multiple versions of `digest` is installed + and `openssl` is `require`d before `digest`. + [[GitHub #463]](https://github.com/ruby/openssl/pull/463) +* Fix GC.compact compatibility. + [[GitHub #464]](https://github.com/ruby/openssl/issues/464) + [[GitHub #465]](https://github.com/ruby/openssl/pull/465) + + Version 2.1.2 ============= diff --git a/ruby/ext/openssl/depend b/ruby/ext/openssl/depend index 68cf35729..742c8bbd1 100644 --- a/ruby/ext/openssl/depend +++ b/ruby/ext/openssl/depend @@ -8,9 +8,165 @@ ossl.o: $(arch_hdrdir)/ruby/config.h ossl.o: $(hdrdir)/ruby.h ossl.o: $(hdrdir)/ruby/assert.h ossl.o: $(hdrdir)/ruby/backward.h +ossl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl.o: $(hdrdir)/ruby/defines.h ossl.o: $(hdrdir)/ruby/encoding.h ossl.o: $(hdrdir)/ruby/intern.h +ossl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl.o: $(hdrdir)/ruby/internal/assume.h +ossl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl.o: $(hdrdir)/ruby/internal/cast.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl.o: $(hdrdir)/ruby/internal/config.h +ossl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl.o: $(hdrdir)/ruby/internal/core.h +ossl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl.o: $(hdrdir)/ruby/internal/ctype.h +ossl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl.o: $(hdrdir)/ruby/internal/dosish.h +ossl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl.o: $(hdrdir)/ruby/internal/error.h +ossl.o: $(hdrdir)/ruby/internal/eval.h +ossl.o: $(hdrdir)/ruby/internal/event.h +ossl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl.o: $(hdrdir)/ruby/internal/gc.h +ossl.o: $(hdrdir)/ruby/internal/glob.h +ossl.o: $(hdrdir)/ruby/internal/globals.h +ossl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl.o: $(hdrdir)/ruby/internal/iterator.h +ossl.o: $(hdrdir)/ruby/internal/memory.h +ossl.o: $(hdrdir)/ruby/internal/method.h +ossl.o: $(hdrdir)/ruby/internal/module.h +ossl.o: $(hdrdir)/ruby/internal/newobj.h +ossl.o: $(hdrdir)/ruby/internal/rgengc.h +ossl.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl.o: $(hdrdir)/ruby/internal/value.h +ossl.o: $(hdrdir)/ruby/internal/value_type.h +ossl.o: $(hdrdir)/ruby/internal/variable.h +ossl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl.o: $(hdrdir)/ruby/io.h ossl.o: $(hdrdir)/ruby/missing.h ossl.o: $(hdrdir)/ruby/onigmo.h @@ -19,7 +175,6 @@ ossl.o: $(hdrdir)/ruby/ruby.h ossl.o: $(hdrdir)/ruby/st.h ossl.o: $(hdrdir)/ruby/subst.h ossl.o: $(hdrdir)/ruby/thread.h -ossl.o: $(hdrdir)/ruby/thread_native.h ossl.o: openssl_missing.h ossl.o: ossl.c ossl.o: ossl.h @@ -39,17 +194,172 @@ ossl.o: ossl_pkcs7.h ossl.o: ossl_pkey.h ossl.o: ossl_rand.h ossl.o: ossl_ssl.h -ossl.o: ossl_version.h +ossl.o: ossl_ts.h ossl.o: ossl_x509.h -ossl.o: ruby_missing.h ossl_asn1.o: $(RUBY_EXTCONF_H) ossl_asn1.o: $(arch_hdrdir)/ruby/config.h ossl_asn1.o: $(hdrdir)/ruby.h ossl_asn1.o: $(hdrdir)/ruby/assert.h ossl_asn1.o: $(hdrdir)/ruby/backward.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_asn1.o: $(hdrdir)/ruby/defines.h ossl_asn1.o: $(hdrdir)/ruby/encoding.h ossl_asn1.o: $(hdrdir)/ruby/intern.h +ossl_asn1.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_asn1.o: $(hdrdir)/ruby/internal/assume.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_asn1.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_asn1.o: $(hdrdir)/ruby/internal/cast.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_asn1.o: $(hdrdir)/ruby/internal/config.h +ossl_asn1.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_asn1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_asn1.o: $(hdrdir)/ruby/internal/ctype.h +ossl_asn1.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_asn1.o: $(hdrdir)/ruby/internal/dosish.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_asn1.o: $(hdrdir)/ruby/internal/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/eval.h +ossl_asn1.o: $(hdrdir)/ruby/internal/event.h +ossl_asn1.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_asn1.o: $(hdrdir)/ruby/internal/gc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/glob.h +ossl_asn1.o: $(hdrdir)/ruby/internal/globals.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_asn1.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_asn1.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_asn1.o: $(hdrdir)/ruby/internal/iterator.h +ossl_asn1.o: $(hdrdir)/ruby/internal/memory.h +ossl_asn1.o: $(hdrdir)/ruby/internal/method.h +ossl_asn1.o: $(hdrdir)/ruby/internal/module.h +ossl_asn1.o: $(hdrdir)/ruby/internal/newobj.h +ossl_asn1.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_asn1.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_asn1.o: $(hdrdir)/ruby/internal/value.h +ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h +ossl_asn1.o: $(hdrdir)/ruby/internal/variable.h +ossl_asn1.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_asn1.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_asn1.o: $(hdrdir)/ruby/io.h ossl_asn1.o: $(hdrdir)/ruby/missing.h ossl_asn1.o: $(hdrdir)/ruby/onigmo.h @@ -77,17 +387,172 @@ ossl_asn1.o: ossl_pkcs7.h ossl_asn1.o: ossl_pkey.h ossl_asn1.o: ossl_rand.h ossl_asn1.o: ossl_ssl.h -ossl_asn1.o: ossl_version.h +ossl_asn1.o: ossl_ts.h ossl_asn1.o: ossl_x509.h -ossl_asn1.o: ruby_missing.h ossl_bio.o: $(RUBY_EXTCONF_H) ossl_bio.o: $(arch_hdrdir)/ruby/config.h ossl_bio.o: $(hdrdir)/ruby.h ossl_bio.o: $(hdrdir)/ruby/assert.h ossl_bio.o: $(hdrdir)/ruby/backward.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_bio.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_bio.o: $(hdrdir)/ruby/defines.h ossl_bio.o: $(hdrdir)/ruby/encoding.h ossl_bio.o: $(hdrdir)/ruby/intern.h +ossl_bio.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_bio.o: $(hdrdir)/ruby/internal/assume.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_bio.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_bio.o: $(hdrdir)/ruby/internal/cast.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_bio.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_bio.o: $(hdrdir)/ruby/internal/config.h +ossl_bio.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_bio.o: $(hdrdir)/ruby/internal/core.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_bio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_bio.o: $(hdrdir)/ruby/internal/ctype.h +ossl_bio.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_bio.o: $(hdrdir)/ruby/internal/dosish.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_bio.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_bio.o: $(hdrdir)/ruby/internal/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/eval.h +ossl_bio.o: $(hdrdir)/ruby/internal/event.h +ossl_bio.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_bio.o: $(hdrdir)/ruby/internal/gc.h +ossl_bio.o: $(hdrdir)/ruby/internal/glob.h +ossl_bio.o: $(hdrdir)/ruby/internal/globals.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_bio.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_bio.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_bio.o: $(hdrdir)/ruby/internal/iterator.h +ossl_bio.o: $(hdrdir)/ruby/internal/memory.h +ossl_bio.o: $(hdrdir)/ruby/internal/method.h +ossl_bio.o: $(hdrdir)/ruby/internal/module.h +ossl_bio.o: $(hdrdir)/ruby/internal/newobj.h +ossl_bio.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_bio.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_bio.o: $(hdrdir)/ruby/internal/value.h +ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h +ossl_bio.o: $(hdrdir)/ruby/internal/variable.h +ossl_bio.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_bio.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_bio.o: $(hdrdir)/ruby/io.h ossl_bio.o: $(hdrdir)/ruby/missing.h ossl_bio.o: $(hdrdir)/ruby/onigmo.h @@ -115,21 +580,177 @@ ossl_bio.o: ossl_pkcs7.h ossl_bio.o: ossl_pkey.h ossl_bio.o: ossl_rand.h ossl_bio.o: ossl_ssl.h -ossl_bio.o: ossl_version.h +ossl_bio.o: ossl_ts.h ossl_bio.o: ossl_x509.h -ossl_bio.o: ruby_missing.h ossl_bn.o: $(RUBY_EXTCONF_H) ossl_bn.o: $(arch_hdrdir)/ruby/config.h ossl_bn.o: $(hdrdir)/ruby.h ossl_bn.o: $(hdrdir)/ruby/assert.h ossl_bn.o: $(hdrdir)/ruby/backward.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_bn.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_bn.o: $(hdrdir)/ruby/defines.h ossl_bn.o: $(hdrdir)/ruby/encoding.h ossl_bn.o: $(hdrdir)/ruby/intern.h +ossl_bn.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_bn.o: $(hdrdir)/ruby/internal/assume.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_bn.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_bn.o: $(hdrdir)/ruby/internal/cast.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_bn.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_bn.o: $(hdrdir)/ruby/internal/config.h +ossl_bn.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_bn.o: $(hdrdir)/ruby/internal/core.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_bn.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_bn.o: $(hdrdir)/ruby/internal/ctype.h +ossl_bn.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_bn.o: $(hdrdir)/ruby/internal/dosish.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_bn.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_bn.o: $(hdrdir)/ruby/internal/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/eval.h +ossl_bn.o: $(hdrdir)/ruby/internal/event.h +ossl_bn.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_bn.o: $(hdrdir)/ruby/internal/gc.h +ossl_bn.o: $(hdrdir)/ruby/internal/glob.h +ossl_bn.o: $(hdrdir)/ruby/internal/globals.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_bn.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_bn.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_bn.o: $(hdrdir)/ruby/internal/iterator.h +ossl_bn.o: $(hdrdir)/ruby/internal/memory.h +ossl_bn.o: $(hdrdir)/ruby/internal/method.h +ossl_bn.o: $(hdrdir)/ruby/internal/module.h +ossl_bn.o: $(hdrdir)/ruby/internal/newobj.h +ossl_bn.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_bn.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_bn.o: $(hdrdir)/ruby/internal/value.h +ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h +ossl_bn.o: $(hdrdir)/ruby/internal/variable.h +ossl_bn.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_bn.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_bn.o: $(hdrdir)/ruby/io.h ossl_bn.o: $(hdrdir)/ruby/missing.h ossl_bn.o: $(hdrdir)/ruby/onigmo.h ossl_bn.o: $(hdrdir)/ruby/oniguruma.h +ossl_bn.o: $(hdrdir)/ruby/ractor.h ossl_bn.o: $(hdrdir)/ruby/ruby.h ossl_bn.o: $(hdrdir)/ruby/st.h ossl_bn.o: $(hdrdir)/ruby/subst.h @@ -153,17 +774,172 @@ ossl_bn.o: ossl_pkcs7.h ossl_bn.o: ossl_pkey.h ossl_bn.o: ossl_rand.h ossl_bn.o: ossl_ssl.h -ossl_bn.o: ossl_version.h +ossl_bn.o: ossl_ts.h ossl_bn.o: ossl_x509.h -ossl_bn.o: ruby_missing.h ossl_cipher.o: $(RUBY_EXTCONF_H) ossl_cipher.o: $(arch_hdrdir)/ruby/config.h ossl_cipher.o: $(hdrdir)/ruby.h ossl_cipher.o: $(hdrdir)/ruby/assert.h ossl_cipher.o: $(hdrdir)/ruby/backward.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_cipher.o: $(hdrdir)/ruby/defines.h ossl_cipher.o: $(hdrdir)/ruby/encoding.h ossl_cipher.o: $(hdrdir)/ruby/intern.h +ossl_cipher.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_cipher.o: $(hdrdir)/ruby/internal/assume.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_cipher.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_cipher.o: $(hdrdir)/ruby/internal/cast.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_cipher.o: $(hdrdir)/ruby/internal/config.h +ossl_cipher.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_cipher.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_cipher.o: $(hdrdir)/ruby/internal/ctype.h +ossl_cipher.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_cipher.o: $(hdrdir)/ruby/internal/dosish.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_cipher.o: $(hdrdir)/ruby/internal/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/eval.h +ossl_cipher.o: $(hdrdir)/ruby/internal/event.h +ossl_cipher.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_cipher.o: $(hdrdir)/ruby/internal/gc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/glob.h +ossl_cipher.o: $(hdrdir)/ruby/internal/globals.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_cipher.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_cipher.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_cipher.o: $(hdrdir)/ruby/internal/iterator.h +ossl_cipher.o: $(hdrdir)/ruby/internal/memory.h +ossl_cipher.o: $(hdrdir)/ruby/internal/method.h +ossl_cipher.o: $(hdrdir)/ruby/internal/module.h +ossl_cipher.o: $(hdrdir)/ruby/internal/newobj.h +ossl_cipher.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_cipher.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_cipher.o: $(hdrdir)/ruby/internal/value.h +ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h +ossl_cipher.o: $(hdrdir)/ruby/internal/variable.h +ossl_cipher.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_cipher.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_cipher.o: $(hdrdir)/ruby/io.h ossl_cipher.o: $(hdrdir)/ruby/missing.h ossl_cipher.o: $(hdrdir)/ruby/onigmo.h @@ -191,17 +967,172 @@ ossl_cipher.o: ossl_pkcs7.h ossl_cipher.o: ossl_pkey.h ossl_cipher.o: ossl_rand.h ossl_cipher.o: ossl_ssl.h -ossl_cipher.o: ossl_version.h +ossl_cipher.o: ossl_ts.h ossl_cipher.o: ossl_x509.h -ossl_cipher.o: ruby_missing.h ossl_config.o: $(RUBY_EXTCONF_H) ossl_config.o: $(arch_hdrdir)/ruby/config.h ossl_config.o: $(hdrdir)/ruby.h ossl_config.o: $(hdrdir)/ruby/assert.h ossl_config.o: $(hdrdir)/ruby/backward.h +ossl_config.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_config.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_config.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_config.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_config.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_config.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_config.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_config.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_config.o: $(hdrdir)/ruby/defines.h ossl_config.o: $(hdrdir)/ruby/encoding.h ossl_config.o: $(hdrdir)/ruby/intern.h +ossl_config.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_config.o: $(hdrdir)/ruby/internal/assume.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_config.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_config.o: $(hdrdir)/ruby/internal/cast.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_config.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_config.o: $(hdrdir)/ruby/internal/config.h +ossl_config.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_config.o: $(hdrdir)/ruby/internal/core.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_config.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_config.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_config.o: $(hdrdir)/ruby/internal/ctype.h +ossl_config.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_config.o: $(hdrdir)/ruby/internal/dosish.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_config.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_config.o: $(hdrdir)/ruby/internal/error.h +ossl_config.o: $(hdrdir)/ruby/internal/eval.h +ossl_config.o: $(hdrdir)/ruby/internal/event.h +ossl_config.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_config.o: $(hdrdir)/ruby/internal/gc.h +ossl_config.o: $(hdrdir)/ruby/internal/glob.h +ossl_config.o: $(hdrdir)/ruby/internal/globals.h +ossl_config.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_config.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_config.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_config.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_config.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_config.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_config.o: $(hdrdir)/ruby/internal/iterator.h +ossl_config.o: $(hdrdir)/ruby/internal/memory.h +ossl_config.o: $(hdrdir)/ruby/internal/method.h +ossl_config.o: $(hdrdir)/ruby/internal/module.h +ossl_config.o: $(hdrdir)/ruby/internal/newobj.h +ossl_config.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_config.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_config.o: $(hdrdir)/ruby/internal/value.h +ossl_config.o: $(hdrdir)/ruby/internal/value_type.h +ossl_config.o: $(hdrdir)/ruby/internal/variable.h +ossl_config.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_config.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_config.o: $(hdrdir)/ruby/io.h ossl_config.o: $(hdrdir)/ruby/missing.h ossl_config.o: $(hdrdir)/ruby/onigmo.h @@ -229,17 +1160,172 @@ ossl_config.o: ossl_pkcs7.h ossl_config.o: ossl_pkey.h ossl_config.o: ossl_rand.h ossl_config.o: ossl_ssl.h -ossl_config.o: ossl_version.h +ossl_config.o: ossl_ts.h ossl_config.o: ossl_x509.h -ossl_config.o: ruby_missing.h ossl_digest.o: $(RUBY_EXTCONF_H) ossl_digest.o: $(arch_hdrdir)/ruby/config.h ossl_digest.o: $(hdrdir)/ruby.h ossl_digest.o: $(hdrdir)/ruby/assert.h ossl_digest.o: $(hdrdir)/ruby/backward.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_digest.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_digest.o: $(hdrdir)/ruby/defines.h ossl_digest.o: $(hdrdir)/ruby/encoding.h ossl_digest.o: $(hdrdir)/ruby/intern.h +ossl_digest.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_digest.o: $(hdrdir)/ruby/internal/assume.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_digest.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_digest.o: $(hdrdir)/ruby/internal/cast.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_digest.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_digest.o: $(hdrdir)/ruby/internal/config.h +ossl_digest.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_digest.o: $(hdrdir)/ruby/internal/core.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_digest.o: $(hdrdir)/ruby/internal/ctype.h +ossl_digest.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_digest.o: $(hdrdir)/ruby/internal/dosish.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_digest.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_digest.o: $(hdrdir)/ruby/internal/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/eval.h +ossl_digest.o: $(hdrdir)/ruby/internal/event.h +ossl_digest.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_digest.o: $(hdrdir)/ruby/internal/gc.h +ossl_digest.o: $(hdrdir)/ruby/internal/glob.h +ossl_digest.o: $(hdrdir)/ruby/internal/globals.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_digest.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_digest.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_digest.o: $(hdrdir)/ruby/internal/iterator.h +ossl_digest.o: $(hdrdir)/ruby/internal/memory.h +ossl_digest.o: $(hdrdir)/ruby/internal/method.h +ossl_digest.o: $(hdrdir)/ruby/internal/module.h +ossl_digest.o: $(hdrdir)/ruby/internal/newobj.h +ossl_digest.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_digest.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_digest.o: $(hdrdir)/ruby/internal/value.h +ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h +ossl_digest.o: $(hdrdir)/ruby/internal/variable.h +ossl_digest.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_digest.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_digest.o: $(hdrdir)/ruby/io.h ossl_digest.o: $(hdrdir)/ruby/missing.h ossl_digest.o: $(hdrdir)/ruby/onigmo.h @@ -267,17 +1353,172 @@ ossl_digest.o: ossl_pkcs7.h ossl_digest.o: ossl_pkey.h ossl_digest.o: ossl_rand.h ossl_digest.o: ossl_ssl.h -ossl_digest.o: ossl_version.h +ossl_digest.o: ossl_ts.h ossl_digest.o: ossl_x509.h -ossl_digest.o: ruby_missing.h ossl_engine.o: $(RUBY_EXTCONF_H) ossl_engine.o: $(arch_hdrdir)/ruby/config.h ossl_engine.o: $(hdrdir)/ruby.h ossl_engine.o: $(hdrdir)/ruby/assert.h ossl_engine.o: $(hdrdir)/ruby/backward.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_engine.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_engine.o: $(hdrdir)/ruby/defines.h ossl_engine.o: $(hdrdir)/ruby/encoding.h ossl_engine.o: $(hdrdir)/ruby/intern.h +ossl_engine.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_engine.o: $(hdrdir)/ruby/internal/assume.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_engine.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_engine.o: $(hdrdir)/ruby/internal/cast.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_engine.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_engine.o: $(hdrdir)/ruby/internal/config.h +ossl_engine.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_engine.o: $(hdrdir)/ruby/internal/core.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_engine.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_engine.o: $(hdrdir)/ruby/internal/ctype.h +ossl_engine.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_engine.o: $(hdrdir)/ruby/internal/dosish.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_engine.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_engine.o: $(hdrdir)/ruby/internal/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/eval.h +ossl_engine.o: $(hdrdir)/ruby/internal/event.h +ossl_engine.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_engine.o: $(hdrdir)/ruby/internal/gc.h +ossl_engine.o: $(hdrdir)/ruby/internal/glob.h +ossl_engine.o: $(hdrdir)/ruby/internal/globals.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_engine.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_engine.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_engine.o: $(hdrdir)/ruby/internal/iterator.h +ossl_engine.o: $(hdrdir)/ruby/internal/memory.h +ossl_engine.o: $(hdrdir)/ruby/internal/method.h +ossl_engine.o: $(hdrdir)/ruby/internal/module.h +ossl_engine.o: $(hdrdir)/ruby/internal/newobj.h +ossl_engine.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_engine.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_engine.o: $(hdrdir)/ruby/internal/value.h +ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h +ossl_engine.o: $(hdrdir)/ruby/internal/variable.h +ossl_engine.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_engine.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_engine.o: $(hdrdir)/ruby/io.h ossl_engine.o: $(hdrdir)/ruby/missing.h ossl_engine.o: $(hdrdir)/ruby/onigmo.h @@ -305,17 +1546,172 @@ ossl_engine.o: ossl_pkcs7.h ossl_engine.o: ossl_pkey.h ossl_engine.o: ossl_rand.h ossl_engine.o: ossl_ssl.h -ossl_engine.o: ossl_version.h +ossl_engine.o: ossl_ts.h ossl_engine.o: ossl_x509.h -ossl_engine.o: ruby_missing.h ossl_hmac.o: $(RUBY_EXTCONF_H) ossl_hmac.o: $(arch_hdrdir)/ruby/config.h ossl_hmac.o: $(hdrdir)/ruby.h ossl_hmac.o: $(hdrdir)/ruby/assert.h ossl_hmac.o: $(hdrdir)/ruby/backward.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_hmac.o: $(hdrdir)/ruby/defines.h ossl_hmac.o: $(hdrdir)/ruby/encoding.h ossl_hmac.o: $(hdrdir)/ruby/intern.h +ossl_hmac.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_hmac.o: $(hdrdir)/ruby/internal/assume.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_hmac.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_hmac.o: $(hdrdir)/ruby/internal/cast.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_hmac.o: $(hdrdir)/ruby/internal/config.h +ossl_hmac.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_hmac.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_hmac.o: $(hdrdir)/ruby/internal/ctype.h +ossl_hmac.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_hmac.o: $(hdrdir)/ruby/internal/dosish.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_hmac.o: $(hdrdir)/ruby/internal/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/eval.h +ossl_hmac.o: $(hdrdir)/ruby/internal/event.h +ossl_hmac.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_hmac.o: $(hdrdir)/ruby/internal/gc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/glob.h +ossl_hmac.o: $(hdrdir)/ruby/internal/globals.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_hmac.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_hmac.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_hmac.o: $(hdrdir)/ruby/internal/iterator.h +ossl_hmac.o: $(hdrdir)/ruby/internal/memory.h +ossl_hmac.o: $(hdrdir)/ruby/internal/method.h +ossl_hmac.o: $(hdrdir)/ruby/internal/module.h +ossl_hmac.o: $(hdrdir)/ruby/internal/newobj.h +ossl_hmac.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_hmac.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_hmac.o: $(hdrdir)/ruby/internal/value.h +ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h +ossl_hmac.o: $(hdrdir)/ruby/internal/variable.h +ossl_hmac.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_hmac.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_hmac.o: $(hdrdir)/ruby/io.h ossl_hmac.o: $(hdrdir)/ruby/missing.h ossl_hmac.o: $(hdrdir)/ruby/onigmo.h @@ -343,17 +1739,172 @@ ossl_hmac.o: ossl_pkcs7.h ossl_hmac.o: ossl_pkey.h ossl_hmac.o: ossl_rand.h ossl_hmac.o: ossl_ssl.h -ossl_hmac.o: ossl_version.h +ossl_hmac.o: ossl_ts.h ossl_hmac.o: ossl_x509.h -ossl_hmac.o: ruby_missing.h ossl_kdf.o: $(RUBY_EXTCONF_H) ossl_kdf.o: $(arch_hdrdir)/ruby/config.h ossl_kdf.o: $(hdrdir)/ruby.h ossl_kdf.o: $(hdrdir)/ruby/assert.h ossl_kdf.o: $(hdrdir)/ruby/backward.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_kdf.o: $(hdrdir)/ruby/defines.h ossl_kdf.o: $(hdrdir)/ruby/encoding.h ossl_kdf.o: $(hdrdir)/ruby/intern.h +ossl_kdf.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_kdf.o: $(hdrdir)/ruby/internal/assume.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_kdf.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_kdf.o: $(hdrdir)/ruby/internal/cast.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_kdf.o: $(hdrdir)/ruby/internal/config.h +ossl_kdf.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_kdf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_kdf.o: $(hdrdir)/ruby/internal/ctype.h +ossl_kdf.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_kdf.o: $(hdrdir)/ruby/internal/dosish.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_kdf.o: $(hdrdir)/ruby/internal/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/eval.h +ossl_kdf.o: $(hdrdir)/ruby/internal/event.h +ossl_kdf.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_kdf.o: $(hdrdir)/ruby/internal/gc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/glob.h +ossl_kdf.o: $(hdrdir)/ruby/internal/globals.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_kdf.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_kdf.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_kdf.o: $(hdrdir)/ruby/internal/iterator.h +ossl_kdf.o: $(hdrdir)/ruby/internal/memory.h +ossl_kdf.o: $(hdrdir)/ruby/internal/method.h +ossl_kdf.o: $(hdrdir)/ruby/internal/module.h +ossl_kdf.o: $(hdrdir)/ruby/internal/newobj.h +ossl_kdf.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_kdf.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_kdf.o: $(hdrdir)/ruby/internal/value.h +ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h +ossl_kdf.o: $(hdrdir)/ruby/internal/variable.h +ossl_kdf.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_kdf.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_kdf.o: $(hdrdir)/ruby/io.h ossl_kdf.o: $(hdrdir)/ruby/missing.h ossl_kdf.o: $(hdrdir)/ruby/onigmo.h @@ -381,17 +1932,172 @@ ossl_kdf.o: ossl_pkcs7.h ossl_kdf.o: ossl_pkey.h ossl_kdf.o: ossl_rand.h ossl_kdf.o: ossl_ssl.h -ossl_kdf.o: ossl_version.h +ossl_kdf.o: ossl_ts.h ossl_kdf.o: ossl_x509.h -ossl_kdf.o: ruby_missing.h ossl_ns_spki.o: $(RUBY_EXTCONF_H) ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h ossl_ns_spki.o: $(hdrdir)/ruby.h ossl_ns_spki.o: $(hdrdir)/ruby/assert.h ossl_ns_spki.o: $(hdrdir)/ruby/backward.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ns_spki.o: $(hdrdir)/ruby/defines.h ossl_ns_spki.o: $(hdrdir)/ruby/encoding.h ossl_ns_spki.o: $(hdrdir)/ruby/intern.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/assume.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/cast.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/config.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/eval.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/event.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/gc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/glob.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/globals.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/memory.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/method.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/module.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/variable.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ns_spki.o: $(hdrdir)/ruby/io.h ossl_ns_spki.o: $(hdrdir)/ruby/missing.h ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h @@ -419,17 +2125,172 @@ ossl_ns_spki.o: ossl_pkcs7.h ossl_ns_spki.o: ossl_pkey.h ossl_ns_spki.o: ossl_rand.h ossl_ns_spki.o: ossl_ssl.h -ossl_ns_spki.o: ossl_version.h +ossl_ns_spki.o: ossl_ts.h ossl_ns_spki.o: ossl_x509.h -ossl_ns_spki.o: ruby_missing.h ossl_ocsp.o: $(RUBY_EXTCONF_H) ossl_ocsp.o: $(arch_hdrdir)/ruby/config.h ossl_ocsp.o: $(hdrdir)/ruby.h ossl_ocsp.o: $(hdrdir)/ruby/assert.h ossl_ocsp.o: $(hdrdir)/ruby/backward.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ocsp.o: $(hdrdir)/ruby/defines.h ossl_ocsp.o: $(hdrdir)/ruby/encoding.h ossl_ocsp.o: $(hdrdir)/ruby/intern.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/assume.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/cast.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/config.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/eval.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/event.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/gc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/glob.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/globals.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/memory.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/method.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/module.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/variable.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ocsp.o: $(hdrdir)/ruby/io.h ossl_ocsp.o: $(hdrdir)/ruby/missing.h ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h @@ -457,17 +2318,172 @@ ossl_ocsp.o: ossl_pkcs7.h ossl_ocsp.o: ossl_pkey.h ossl_ocsp.o: ossl_rand.h ossl_ocsp.o: ossl_ssl.h -ossl_ocsp.o: ossl_version.h +ossl_ocsp.o: ossl_ts.h ossl_ocsp.o: ossl_x509.h -ossl_ocsp.o: ruby_missing.h ossl_pkcs12.o: $(RUBY_EXTCONF_H) ossl_pkcs12.o: $(arch_hdrdir)/ruby/config.h ossl_pkcs12.o: $(hdrdir)/ruby.h ossl_pkcs12.o: $(hdrdir)/ruby/assert.h ossl_pkcs12.o: $(hdrdir)/ruby/backward.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkcs12.o: $(hdrdir)/ruby/defines.h ossl_pkcs12.o: $(hdrdir)/ruby/encoding.h ossl_pkcs12.o: $(hdrdir)/ruby/intern.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/config.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/event.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/method.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/module.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkcs12.o: $(hdrdir)/ruby/io.h ossl_pkcs12.o: $(hdrdir)/ruby/missing.h ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h @@ -495,17 +2511,172 @@ ossl_pkcs12.o: ossl_pkcs7.h ossl_pkcs12.o: ossl_pkey.h ossl_pkcs12.o: ossl_rand.h ossl_pkcs12.o: ossl_ssl.h -ossl_pkcs12.o: ossl_version.h +ossl_pkcs12.o: ossl_ts.h ossl_pkcs12.o: ossl_x509.h -ossl_pkcs12.o: ruby_missing.h ossl_pkcs7.o: $(RUBY_EXTCONF_H) ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h ossl_pkcs7.o: $(hdrdir)/ruby.h ossl_pkcs7.o: $(hdrdir)/ruby/assert.h ossl_pkcs7.o: $(hdrdir)/ruby/backward.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkcs7.o: $(hdrdir)/ruby/defines.h ossl_pkcs7.o: $(hdrdir)/ruby/encoding.h ossl_pkcs7.o: $(hdrdir)/ruby/intern.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/config.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/event.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/method.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/module.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkcs7.o: $(hdrdir)/ruby/io.h ossl_pkcs7.o: $(hdrdir)/ruby/missing.h ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h @@ -533,17 +2704,172 @@ ossl_pkcs7.o: ossl_pkcs7.h ossl_pkcs7.o: ossl_pkey.h ossl_pkcs7.o: ossl_rand.h ossl_pkcs7.o: ossl_ssl.h -ossl_pkcs7.o: ossl_version.h +ossl_pkcs7.o: ossl_ts.h ossl_pkcs7.o: ossl_x509.h -ossl_pkcs7.o: ruby_missing.h ossl_pkey.o: $(RUBY_EXTCONF_H) ossl_pkey.o: $(arch_hdrdir)/ruby/config.h ossl_pkey.o: $(hdrdir)/ruby.h ossl_pkey.o: $(hdrdir)/ruby/assert.h ossl_pkey.o: $(hdrdir)/ruby/backward.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey.o: $(hdrdir)/ruby/defines.h ossl_pkey.o: $(hdrdir)/ruby/encoding.h ossl_pkey.o: $(hdrdir)/ruby/intern.h +ossl_pkey.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkey.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkey.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey.o: $(hdrdir)/ruby/io.h ossl_pkey.o: $(hdrdir)/ruby/missing.h ossl_pkey.o: $(hdrdir)/ruby/onigmo.h @@ -571,17 +2897,172 @@ ossl_pkey.o: ossl_pkey.c ossl_pkey.o: ossl_pkey.h ossl_pkey.o: ossl_rand.h ossl_pkey.o: ossl_ssl.h -ossl_pkey.o: ossl_version.h +ossl_pkey.o: ossl_ts.h ossl_pkey.o: ossl_x509.h -ossl_pkey.o: ruby_missing.h ossl_pkey_dh.o: $(RUBY_EXTCONF_H) ossl_pkey_dh.o: $(arch_hdrdir)/ruby/config.h ossl_pkey_dh.o: $(hdrdir)/ruby.h ossl_pkey_dh.o: $(hdrdir)/ruby/assert.h ossl_pkey_dh.o: $(hdrdir)/ruby/backward.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_dh.o: $(hdrdir)/ruby/defines.h ossl_pkey_dh.o: $(hdrdir)/ruby/encoding.h ossl_pkey_dh.o: $(hdrdir)/ruby/intern.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_dh.o: $(hdrdir)/ruby/io.h ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h @@ -609,17 +3090,172 @@ ossl_pkey_dh.o: ossl_pkey.h ossl_pkey_dh.o: ossl_pkey_dh.c ossl_pkey_dh.o: ossl_rand.h ossl_pkey_dh.o: ossl_ssl.h -ossl_pkey_dh.o: ossl_version.h +ossl_pkey_dh.o: ossl_ts.h ossl_pkey_dh.o: ossl_x509.h -ossl_pkey_dh.o: ruby_missing.h ossl_pkey_dsa.o: $(RUBY_EXTCONF_H) ossl_pkey_dsa.o: $(arch_hdrdir)/ruby/config.h ossl_pkey_dsa.o: $(hdrdir)/ruby.h ossl_pkey_dsa.o: $(hdrdir)/ruby/assert.h ossl_pkey_dsa.o: $(hdrdir)/ruby/backward.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_dsa.o: $(hdrdir)/ruby/defines.h ossl_pkey_dsa.o: $(hdrdir)/ruby/encoding.h ossl_pkey_dsa.o: $(hdrdir)/ruby/intern.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h @@ -647,17 +3283,172 @@ ossl_pkey_dsa.o: ossl_pkey.h ossl_pkey_dsa.o: ossl_pkey_dsa.c ossl_pkey_dsa.o: ossl_rand.h ossl_pkey_dsa.o: ossl_ssl.h -ossl_pkey_dsa.o: ossl_version.h +ossl_pkey_dsa.o: ossl_ts.h ossl_pkey_dsa.o: ossl_x509.h -ossl_pkey_dsa.o: ruby_missing.h ossl_pkey_ec.o: $(RUBY_EXTCONF_H) ossl_pkey_ec.o: $(arch_hdrdir)/ruby/config.h ossl_pkey_ec.o: $(hdrdir)/ruby.h ossl_pkey_ec.o: $(hdrdir)/ruby/assert.h ossl_pkey_ec.o: $(hdrdir)/ruby/backward.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_ec.o: $(hdrdir)/ruby/defines.h ossl_pkey_ec.o: $(hdrdir)/ruby/encoding.h ossl_pkey_ec.o: $(hdrdir)/ruby/intern.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_ec.o: $(hdrdir)/ruby/io.h ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h @@ -685,17 +3476,172 @@ ossl_pkey_ec.o: ossl_pkey.h ossl_pkey_ec.o: ossl_pkey_ec.c ossl_pkey_ec.o: ossl_rand.h ossl_pkey_ec.o: ossl_ssl.h -ossl_pkey_ec.o: ossl_version.h +ossl_pkey_ec.o: ossl_ts.h ossl_pkey_ec.o: ossl_x509.h -ossl_pkey_ec.o: ruby_missing.h ossl_pkey_rsa.o: $(RUBY_EXTCONF_H) ossl_pkey_rsa.o: $(arch_hdrdir)/ruby/config.h ossl_pkey_rsa.o: $(hdrdir)/ruby.h ossl_pkey_rsa.o: $(hdrdir)/ruby/assert.h ossl_pkey_rsa.o: $(hdrdir)/ruby/backward.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_pkey_rsa.o: $(hdrdir)/ruby/defines.h ossl_pkey_rsa.o: $(hdrdir)/ruby/encoding.h ossl_pkey_rsa.o: $(hdrdir)/ruby/intern.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/assume.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/cast.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/config.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/ctype.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dosish.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/eval.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/event.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/gc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/glob.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/globals.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/iterator.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/memory.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/method.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/module.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/newobj.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/variable.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h @@ -723,17 +3669,172 @@ ossl_pkey_rsa.o: ossl_pkey.h ossl_pkey_rsa.o: ossl_pkey_rsa.c ossl_pkey_rsa.o: ossl_rand.h ossl_pkey_rsa.o: ossl_ssl.h -ossl_pkey_rsa.o: ossl_version.h +ossl_pkey_rsa.o: ossl_ts.h ossl_pkey_rsa.o: ossl_x509.h -ossl_pkey_rsa.o: ruby_missing.h ossl_rand.o: $(RUBY_EXTCONF_H) ossl_rand.o: $(arch_hdrdir)/ruby/config.h ossl_rand.o: $(hdrdir)/ruby.h ossl_rand.o: $(hdrdir)/ruby/assert.h ossl_rand.o: $(hdrdir)/ruby/backward.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_rand.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_rand.o: $(hdrdir)/ruby/defines.h ossl_rand.o: $(hdrdir)/ruby/encoding.h ossl_rand.o: $(hdrdir)/ruby/intern.h +ossl_rand.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_rand.o: $(hdrdir)/ruby/internal/assume.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_rand.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_rand.o: $(hdrdir)/ruby/internal/cast.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_rand.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_rand.o: $(hdrdir)/ruby/internal/config.h +ossl_rand.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_rand.o: $(hdrdir)/ruby/internal/core.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_rand.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_rand.o: $(hdrdir)/ruby/internal/ctype.h +ossl_rand.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_rand.o: $(hdrdir)/ruby/internal/dosish.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_rand.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_rand.o: $(hdrdir)/ruby/internal/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/eval.h +ossl_rand.o: $(hdrdir)/ruby/internal/event.h +ossl_rand.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_rand.o: $(hdrdir)/ruby/internal/gc.h +ossl_rand.o: $(hdrdir)/ruby/internal/glob.h +ossl_rand.o: $(hdrdir)/ruby/internal/globals.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_rand.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_rand.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_rand.o: $(hdrdir)/ruby/internal/iterator.h +ossl_rand.o: $(hdrdir)/ruby/internal/memory.h +ossl_rand.o: $(hdrdir)/ruby/internal/method.h +ossl_rand.o: $(hdrdir)/ruby/internal/module.h +ossl_rand.o: $(hdrdir)/ruby/internal/newobj.h +ossl_rand.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_rand.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_rand.o: $(hdrdir)/ruby/internal/value.h +ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h +ossl_rand.o: $(hdrdir)/ruby/internal/variable.h +ossl_rand.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_rand.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_rand.o: $(hdrdir)/ruby/io.h ossl_rand.o: $(hdrdir)/ruby/missing.h ossl_rand.o: $(hdrdir)/ruby/onigmo.h @@ -761,17 +3862,172 @@ ossl_rand.o: ossl_pkey.h ossl_rand.o: ossl_rand.c ossl_rand.o: ossl_rand.h ossl_rand.o: ossl_ssl.h -ossl_rand.o: ossl_version.h +ossl_rand.o: ossl_ts.h ossl_rand.o: ossl_x509.h -ossl_rand.o: ruby_missing.h ossl_ssl.o: $(RUBY_EXTCONF_H) ossl_ssl.o: $(arch_hdrdir)/ruby/config.h ossl_ssl.o: $(hdrdir)/ruby.h ossl_ssl.o: $(hdrdir)/ruby/assert.h ossl_ssl.o: $(hdrdir)/ruby/backward.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ssl.o: $(hdrdir)/ruby/defines.h ossl_ssl.o: $(hdrdir)/ruby/encoding.h ossl_ssl.o: $(hdrdir)/ruby/intern.h +ossl_ssl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ssl.o: $(hdrdir)/ruby/internal/assume.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ssl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ssl.o: $(hdrdir)/ruby/internal/cast.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ssl.o: $(hdrdir)/ruby/internal/config.h +ossl_ssl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ssl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ssl.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ssl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ssl.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ssl.o: $(hdrdir)/ruby/internal/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/eval.h +ossl_ssl.o: $(hdrdir)/ruby/internal/event.h +ossl_ssl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ssl.o: $(hdrdir)/ruby/internal/gc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/glob.h +ossl_ssl.o: $(hdrdir)/ruby/internal/globals.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ssl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ssl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ssl.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ssl.o: $(hdrdir)/ruby/internal/memory.h +ossl_ssl.o: $(hdrdir)/ruby/internal/method.h +ossl_ssl.o: $(hdrdir)/ruby/internal/module.h +ossl_ssl.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ssl.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_ssl.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_ssl.o: $(hdrdir)/ruby/internal/value.h +ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ssl.o: $(hdrdir)/ruby/internal/variable.h +ossl_ssl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ssl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ssl.o: $(hdrdir)/ruby/io.h ossl_ssl.o: $(hdrdir)/ruby/missing.h ossl_ssl.o: $(hdrdir)/ruby/onigmo.h @@ -799,17 +4055,172 @@ ossl_ssl.o: ossl_pkey.h ossl_ssl.o: ossl_rand.h ossl_ssl.o: ossl_ssl.c ossl_ssl.o: ossl_ssl.h -ossl_ssl.o: ossl_version.h +ossl_ssl.o: ossl_ts.h ossl_ssl.o: ossl_x509.h -ossl_ssl.o: ruby_missing.h ossl_ssl_session.o: $(RUBY_EXTCONF_H) ossl_ssl_session.o: $(arch_hdrdir)/ruby/config.h ossl_ssl_session.o: $(hdrdir)/ruby.h ossl_ssl_session.o: $(hdrdir)/ruby/assert.h ossl_ssl_session.o: $(hdrdir)/ruby/backward.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_ssl_session.o: $(hdrdir)/ruby/defines.h ossl_ssl_session.o: $(hdrdir)/ruby/encoding.h ossl_ssl_session.o: $(hdrdir)/ruby/intern.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/assume.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/cast.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/config.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/eval.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/event.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/gc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/glob.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/globals.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/memory.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/method.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/module.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/variable.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_ssl_session.o: $(hdrdir)/ruby/io.h ossl_ssl_session.o: $(hdrdir)/ruby/missing.h ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h @@ -837,17 +4248,365 @@ ossl_ssl_session.o: ossl_pkey.h ossl_ssl_session.o: ossl_rand.h ossl_ssl_session.o: ossl_ssl.h ossl_ssl_session.o: ossl_ssl_session.c -ossl_ssl_session.o: ossl_version.h +ossl_ssl_session.o: ossl_ts.h ossl_ssl_session.o: ossl_x509.h -ossl_ssl_session.o: ruby_missing.h +ossl_ts.o: $(RUBY_EXTCONF_H) +ossl_ts.o: $(arch_hdrdir)/ruby/config.h +ossl_ts.o: $(hdrdir)/ruby.h +ossl_ts.o: $(hdrdir)/ruby/assert.h +ossl_ts.o: $(hdrdir)/ruby/backward.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_ts.o: $(hdrdir)/ruby/backward/2/stdarg.h +ossl_ts.o: $(hdrdir)/ruby/defines.h +ossl_ts.o: $(hdrdir)/ruby/encoding.h +ossl_ts.o: $(hdrdir)/ruby/intern.h +ossl_ts.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_ts.o: $(hdrdir)/ruby/internal/assume.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_ts.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_ts.o: $(hdrdir)/ruby/internal/cast.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_ts.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_ts.o: $(hdrdir)/ruby/internal/config.h +ossl_ts.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_ts.o: $(hdrdir)/ruby/internal/core.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_ts.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_ts.o: $(hdrdir)/ruby/internal/ctype.h +ossl_ts.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_ts.o: $(hdrdir)/ruby/internal/dosish.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_ts.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_ts.o: $(hdrdir)/ruby/internal/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/eval.h +ossl_ts.o: $(hdrdir)/ruby/internal/event.h +ossl_ts.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_ts.o: $(hdrdir)/ruby/internal/gc.h +ossl_ts.o: $(hdrdir)/ruby/internal/glob.h +ossl_ts.o: $(hdrdir)/ruby/internal/globals.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_ts.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_ts.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_ts.o: $(hdrdir)/ruby/internal/iterator.h +ossl_ts.o: $(hdrdir)/ruby/internal/memory.h +ossl_ts.o: $(hdrdir)/ruby/internal/method.h +ossl_ts.o: $(hdrdir)/ruby/internal/module.h +ossl_ts.o: $(hdrdir)/ruby/internal/newobj.h +ossl_ts.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_ts.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_ts.o: $(hdrdir)/ruby/internal/value.h +ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h +ossl_ts.o: $(hdrdir)/ruby/internal/variable.h +ossl_ts.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_ts.o: $(hdrdir)/ruby/internal/xmalloc.h +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/ruby.h +ossl_ts.o: $(hdrdir)/ruby/st.h +ossl_ts.o: $(hdrdir)/ruby/subst.h +ossl_ts.o: $(hdrdir)/ruby/thread.h +ossl_ts.o: openssl_missing.h +ossl_ts.o: ossl.h +ossl_ts.o: ossl_asn1.h +ossl_ts.o: ossl_bio.h +ossl_ts.o: ossl_bn.h +ossl_ts.o: ossl_cipher.h +ossl_ts.o: ossl_config.h +ossl_ts.o: ossl_digest.h +ossl_ts.o: ossl_engine.h +ossl_ts.o: ossl_hmac.h +ossl_ts.o: ossl_kdf.h +ossl_ts.o: ossl_ns_spki.h +ossl_ts.o: ossl_ocsp.h +ossl_ts.o: ossl_pkcs12.h +ossl_ts.o: ossl_pkcs7.h +ossl_ts.o: ossl_pkey.h +ossl_ts.o: ossl_rand.h +ossl_ts.o: ossl_ssl.h +ossl_ts.o: ossl_ts.c +ossl_ts.o: ossl_ts.h +ossl_ts.o: ossl_x509.h ossl_x509.o: $(RUBY_EXTCONF_H) ossl_x509.o: $(arch_hdrdir)/ruby/config.h ossl_x509.o: $(hdrdir)/ruby.h ossl_x509.o: $(hdrdir)/ruby/assert.h ossl_x509.o: $(hdrdir)/ruby/backward.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509.o: $(hdrdir)/ruby/defines.h ossl_x509.o: $(hdrdir)/ruby/encoding.h ossl_x509.o: $(hdrdir)/ruby/intern.h +ossl_x509.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509.o: $(hdrdir)/ruby/internal/config.h +ossl_x509.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509.o: $(hdrdir)/ruby/internal/core.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509.o: $(hdrdir)/ruby/internal/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509.o: $(hdrdir)/ruby/internal/event.h +ossl_x509.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509.o: $(hdrdir)/ruby/internal/method.h +ossl_x509.o: $(hdrdir)/ruby/internal/module.h +ossl_x509.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509.o: $(hdrdir)/ruby/internal/value.h +ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509.o: $(hdrdir)/ruby/io.h ossl_x509.o: $(hdrdir)/ruby/missing.h ossl_x509.o: $(hdrdir)/ruby/onigmo.h @@ -874,18 +4633,173 @@ ossl_x509.o: ossl_pkcs7.h ossl_x509.o: ossl_pkey.h ossl_x509.o: ossl_rand.h ossl_x509.o: ossl_ssl.h -ossl_x509.o: ossl_version.h +ossl_x509.o: ossl_ts.h ossl_x509.o: ossl_x509.c ossl_x509.o: ossl_x509.h -ossl_x509.o: ruby_missing.h ossl_x509attr.o: $(RUBY_EXTCONF_H) ossl_x509attr.o: $(arch_hdrdir)/ruby/config.h ossl_x509attr.o: $(hdrdir)/ruby.h ossl_x509attr.o: $(hdrdir)/ruby/assert.h ossl_x509attr.o: $(hdrdir)/ruby/backward.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509attr.o: $(hdrdir)/ruby/defines.h ossl_x509attr.o: $(hdrdir)/ruby/encoding.h ossl_x509attr.o: $(hdrdir)/ruby/intern.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/config.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/event.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/method.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/module.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509attr.o: $(hdrdir)/ruby/io.h ossl_x509attr.o: $(hdrdir)/ruby/missing.h ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h @@ -912,18 +4826,173 @@ ossl_x509attr.o: ossl_pkcs7.h ossl_x509attr.o: ossl_pkey.h ossl_x509attr.o: ossl_rand.h ossl_x509attr.o: ossl_ssl.h -ossl_x509attr.o: ossl_version.h +ossl_x509attr.o: ossl_ts.h ossl_x509attr.o: ossl_x509.h ossl_x509attr.o: ossl_x509attr.c -ossl_x509attr.o: ruby_missing.h ossl_x509cert.o: $(RUBY_EXTCONF_H) ossl_x509cert.o: $(arch_hdrdir)/ruby/config.h ossl_x509cert.o: $(hdrdir)/ruby.h ossl_x509cert.o: $(hdrdir)/ruby/assert.h ossl_x509cert.o: $(hdrdir)/ruby/backward.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509cert.o: $(hdrdir)/ruby/defines.h ossl_x509cert.o: $(hdrdir)/ruby/encoding.h ossl_x509cert.o: $(hdrdir)/ruby/intern.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/config.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/event.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/method.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/module.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509cert.o: $(hdrdir)/ruby/io.h ossl_x509cert.o: $(hdrdir)/ruby/missing.h ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h @@ -950,18 +5019,173 @@ ossl_x509cert.o: ossl_pkcs7.h ossl_x509cert.o: ossl_pkey.h ossl_x509cert.o: ossl_rand.h ossl_x509cert.o: ossl_ssl.h -ossl_x509cert.o: ossl_version.h +ossl_x509cert.o: ossl_ts.h ossl_x509cert.o: ossl_x509.h ossl_x509cert.o: ossl_x509cert.c -ossl_x509cert.o: ruby_missing.h ossl_x509crl.o: $(RUBY_EXTCONF_H) ossl_x509crl.o: $(arch_hdrdir)/ruby/config.h ossl_x509crl.o: $(hdrdir)/ruby.h ossl_x509crl.o: $(hdrdir)/ruby/assert.h ossl_x509crl.o: $(hdrdir)/ruby/backward.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509crl.o: $(hdrdir)/ruby/defines.h ossl_x509crl.o: $(hdrdir)/ruby/encoding.h ossl_x509crl.o: $(hdrdir)/ruby/intern.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/config.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/event.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/method.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/module.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509crl.o: $(hdrdir)/ruby/io.h ossl_x509crl.o: $(hdrdir)/ruby/missing.h ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h @@ -988,18 +5212,173 @@ ossl_x509crl.o: ossl_pkcs7.h ossl_x509crl.o: ossl_pkey.h ossl_x509crl.o: ossl_rand.h ossl_x509crl.o: ossl_ssl.h -ossl_x509crl.o: ossl_version.h +ossl_x509crl.o: ossl_ts.h ossl_x509crl.o: ossl_x509.h ossl_x509crl.o: ossl_x509crl.c -ossl_x509crl.o: ruby_missing.h ossl_x509ext.o: $(RUBY_EXTCONF_H) ossl_x509ext.o: $(arch_hdrdir)/ruby/config.h ossl_x509ext.o: $(hdrdir)/ruby.h ossl_x509ext.o: $(hdrdir)/ruby/assert.h ossl_x509ext.o: $(hdrdir)/ruby/backward.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509ext.o: $(hdrdir)/ruby/defines.h ossl_x509ext.o: $(hdrdir)/ruby/encoding.h ossl_x509ext.o: $(hdrdir)/ruby/intern.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/config.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/event.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/method.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/module.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509ext.o: $(hdrdir)/ruby/io.h ossl_x509ext.o: $(hdrdir)/ruby/missing.h ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h @@ -1026,18 +5405,173 @@ ossl_x509ext.o: ossl_pkcs7.h ossl_x509ext.o: ossl_pkey.h ossl_x509ext.o: ossl_rand.h ossl_x509ext.o: ossl_ssl.h -ossl_x509ext.o: ossl_version.h +ossl_x509ext.o: ossl_ts.h ossl_x509ext.o: ossl_x509.h ossl_x509ext.o: ossl_x509ext.c -ossl_x509ext.o: ruby_missing.h ossl_x509name.o: $(RUBY_EXTCONF_H) ossl_x509name.o: $(arch_hdrdir)/ruby/config.h ossl_x509name.o: $(hdrdir)/ruby.h ossl_x509name.o: $(hdrdir)/ruby/assert.h ossl_x509name.o: $(hdrdir)/ruby/backward.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509name.o: $(hdrdir)/ruby/defines.h ossl_x509name.o: $(hdrdir)/ruby/encoding.h ossl_x509name.o: $(hdrdir)/ruby/intern.h +ossl_x509name.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509name.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509name.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509name.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509name.o: $(hdrdir)/ruby/internal/config.h +ossl_x509name.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509name.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509name.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509name.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509name.o: $(hdrdir)/ruby/internal/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509name.o: $(hdrdir)/ruby/internal/event.h +ossl_x509name.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509name.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509name.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509name.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509name.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509name.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509name.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509name.o: $(hdrdir)/ruby/internal/method.h +ossl_x509name.o: $(hdrdir)/ruby/internal/module.h +ossl_x509name.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509name.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509name.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509name.o: $(hdrdir)/ruby/internal/value.h +ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509name.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509name.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509name.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509name.o: $(hdrdir)/ruby/io.h ossl_x509name.o: $(hdrdir)/ruby/missing.h ossl_x509name.o: $(hdrdir)/ruby/onigmo.h @@ -1064,18 +5598,173 @@ ossl_x509name.o: ossl_pkcs7.h ossl_x509name.o: ossl_pkey.h ossl_x509name.o: ossl_rand.h ossl_x509name.o: ossl_ssl.h -ossl_x509name.o: ossl_version.h +ossl_x509name.o: ossl_ts.h ossl_x509name.o: ossl_x509.h ossl_x509name.o: ossl_x509name.c -ossl_x509name.o: ruby_missing.h ossl_x509req.o: $(RUBY_EXTCONF_H) ossl_x509req.o: $(arch_hdrdir)/ruby/config.h ossl_x509req.o: $(hdrdir)/ruby.h ossl_x509req.o: $(hdrdir)/ruby/assert.h ossl_x509req.o: $(hdrdir)/ruby/backward.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509req.o: $(hdrdir)/ruby/defines.h ossl_x509req.o: $(hdrdir)/ruby/encoding.h ossl_x509req.o: $(hdrdir)/ruby/intern.h +ossl_x509req.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509req.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509req.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509req.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509req.o: $(hdrdir)/ruby/internal/config.h +ossl_x509req.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509req.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509req.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509req.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509req.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509req.o: $(hdrdir)/ruby/internal/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509req.o: $(hdrdir)/ruby/internal/event.h +ossl_x509req.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509req.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509req.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509req.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509req.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509req.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509req.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509req.o: $(hdrdir)/ruby/internal/method.h +ossl_x509req.o: $(hdrdir)/ruby/internal/module.h +ossl_x509req.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509req.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509req.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509req.o: $(hdrdir)/ruby/internal/value.h +ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509req.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509req.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509req.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509req.o: $(hdrdir)/ruby/io.h ossl_x509req.o: $(hdrdir)/ruby/missing.h ossl_x509req.o: $(hdrdir)/ruby/onigmo.h @@ -1102,18 +5791,173 @@ ossl_x509req.o: ossl_pkcs7.h ossl_x509req.o: ossl_pkey.h ossl_x509req.o: ossl_rand.h ossl_x509req.o: ossl_ssl.h -ossl_x509req.o: ossl_version.h +ossl_x509req.o: ossl_ts.h ossl_x509req.o: ossl_x509.h ossl_x509req.o: ossl_x509req.c -ossl_x509req.o: ruby_missing.h ossl_x509revoked.o: $(RUBY_EXTCONF_H) ossl_x509revoked.o: $(arch_hdrdir)/ruby/config.h ossl_x509revoked.o: $(hdrdir)/ruby.h ossl_x509revoked.o: $(hdrdir)/ruby/assert.h ossl_x509revoked.o: $(hdrdir)/ruby/backward.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509revoked.o: $(hdrdir)/ruby/defines.h ossl_x509revoked.o: $(hdrdir)/ruby/encoding.h ossl_x509revoked.o: $(hdrdir)/ruby/intern.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/config.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/event.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/method.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/module.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509revoked.o: $(hdrdir)/ruby/io.h ossl_x509revoked.o: $(hdrdir)/ruby/missing.h ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h @@ -1140,18 +5984,173 @@ ossl_x509revoked.o: ossl_pkcs7.h ossl_x509revoked.o: ossl_pkey.h ossl_x509revoked.o: ossl_rand.h ossl_x509revoked.o: ossl_ssl.h -ossl_x509revoked.o: ossl_version.h +ossl_x509revoked.o: ossl_ts.h ossl_x509revoked.o: ossl_x509.h ossl_x509revoked.o: ossl_x509revoked.c -ossl_x509revoked.o: ruby_missing.h ossl_x509store.o: $(RUBY_EXTCONF_H) ossl_x509store.o: $(arch_hdrdir)/ruby/config.h ossl_x509store.o: $(hdrdir)/ruby.h ossl_x509store.o: $(hdrdir)/ruby/assert.h ossl_x509store.o: $(hdrdir)/ruby/backward.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/assume.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/attributes.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/bool.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/inttypes.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/limits.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/long_long.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdalign.h +ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdarg.h ossl_x509store.o: $(hdrdir)/ruby/defines.h ossl_x509store.o: $(hdrdir)/ruby/encoding.h ossl_x509store.o: $(hdrdir)/ruby/intern.h +ossl_x509store.o: $(hdrdir)/ruby/internal/anyargs.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ossl_x509store.o: $(hdrdir)/ruby/internal/assume.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/artificial.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/cold.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/const.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/format.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noalias.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noinline.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/pure.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/restrict.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/warning.h +ossl_x509store.o: $(hdrdir)/ruby/internal/attr/weakref.h +ossl_x509store.o: $(hdrdir)/ruby/internal/cast.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_since.h +ossl_x509store.o: $(hdrdir)/ruby/internal/config.h +ossl_x509store.o: $(hdrdir)/ruby/internal/constant_p.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rarray.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbasic.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbignum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rclass.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rdata.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rfile.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rhash.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/robject.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rregexp.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstring.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstruct.h +ossl_x509store.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ossl_x509store.o: $(hdrdir)/ruby/internal/ctype.h +ossl_x509store.o: $(hdrdir)/ruby/internal/dllexport.h +ossl_x509store.o: $(hdrdir)/ruby/internal/dosish.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/re.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/string.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ossl_x509store.o: $(hdrdir)/ruby/internal/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/eval.h +ossl_x509store.o: $(hdrdir)/ruby/internal/event.h +ossl_x509store.o: $(hdrdir)/ruby/internal/fl_type.h +ossl_x509store.o: $(hdrdir)/ruby/internal/gc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/glob.h +ossl_x509store.o: $(hdrdir)/ruby/internal/globals.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/builtin.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/extension.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/feature.h +ossl_x509store.o: $(hdrdir)/ruby/internal/has/warning.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/array.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/bignum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/class.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/compar.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/complex.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/cont.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/dir.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enum.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/error.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/eval.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/file.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/gc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/hash.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/io.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/load.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/marshal.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/numeric.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/object.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/parse.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/proc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/process.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/random.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/range.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/struct.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/thread.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/time.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/variable.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/vm.h +ossl_x509store.o: $(hdrdir)/ruby/internal/interpreter.h +ossl_x509store.o: $(hdrdir)/ruby/internal/iterator.h +ossl_x509store.o: $(hdrdir)/ruby/internal/memory.h +ossl_x509store.o: $(hdrdir)/ruby/internal/method.h +ossl_x509store.o: $(hdrdir)/ruby/internal/module.h +ossl_x509store.o: $(hdrdir)/ruby/internal/newobj.h +ossl_x509store.o: $(hdrdir)/ruby/internal/rgengc.h +ossl_x509store.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ossl_x509store.o: $(hdrdir)/ruby/internal/value.h +ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h +ossl_x509store.o: $(hdrdir)/ruby/internal/variable.h +ossl_x509store.o: $(hdrdir)/ruby/internal/warning_push.h +ossl_x509store.o: $(hdrdir)/ruby/internal/xmalloc.h ossl_x509store.o: $(hdrdir)/ruby/io.h ossl_x509store.o: $(hdrdir)/ruby/missing.h ossl_x509store.o: $(hdrdir)/ruby/onigmo.h @@ -1178,8 +6177,7 @@ ossl_x509store.o: ossl_pkcs7.h ossl_x509store.o: ossl_pkey.h ossl_x509store.o: ossl_rand.h ossl_x509store.o: ossl_ssl.h -ossl_x509store.o: ossl_version.h +ossl_x509store.o: ossl_ts.h ossl_x509store.o: ossl_x509.h ossl_x509store.o: ossl_x509store.c -ossl_x509store.o: ruby_missing.h # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/openssl/deprecation.rb b/ruby/ext/openssl/deprecation.rb deleted file mode 100644 index afe989ead..000000000 --- a/ruby/ext/openssl/deprecation.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: false -module OpenSSL - def self.deprecated_warning_flag - unless flag = (@deprecated_warning_flag ||= nil) - if try_compile("", flag = "-Werror=deprecated-declarations") - $warnflags = "#{@warnflags = $warnflags}" #{flag}" - else - flag = "" - end - @deprecated_warning_flag = flag - end - flag - end - - def self.restore_warning_flag - $warnflags = @warnflags - end - - def self.check_func(func, header) - have_func(func, header, deprecated_warning_flag) - end - - def self.check_func_or_macro(func, header) - check_func(func, header) or - have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}") - end -end diff --git a/ruby/ext/openssl/extconf.rb b/ruby/ext/openssl/extconf.rb index 264130bb5..fedcb930f 100644 --- a/ruby/ext/openssl/extconf.rb +++ b/ruby/ext/openssl/extconf.rb @@ -1,5 +1,5 @@ # -*- coding: us-ascii -*- -# frozen_string_literal: false +# frozen_string_literal: true =begin = Info 'OpenSSL for Ruby 2' project @@ -12,16 +12,12 @@ =end require "mkmf" -require File.expand_path('../deprecation', __FILE__) dir_config("openssl") dir_config("kerberos") Logging::message "=== OpenSSL for Ruby configurator ===\n" -# Check with -Werror=deprecated-declarations if available -OpenSSL.deprecated_warning_flag - ## # Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used # To turn it on, use: --with-debug or --enable-debug @@ -30,6 +26,8 @@ $defs.push("-DOSSL_DEBUG") end +have_func("rb_io_maybe_wait") # Ruby 3.1 + Logging::message "=== Checking for system dependent stuff... ===\n" have_library("nsl", "t_open") have_library("socket", "socket") @@ -37,8 +35,11 @@ have_library("ws2_32") end -Logging::message "=== Checking for required stuff... ===\n" -result = pkg_config("openssl") && have_header("openssl/ssl.h") +if $mingw + append_cflags '-D_FORTIFY_SOURCE=2' + append_ldflags '-fstack-protector' + have_library 'ssp' +end def find_openssl_library if $mswin || $mingw @@ -90,60 +91,53 @@ def find_openssl_library return false end -unless result - unless find_openssl_library - Logging::message "=== Checking for required stuff failed. ===\n" - Logging::message "Makefile wasn't created. Fix the errors above.\n" - raise "OpenSSL library could not be found. You might want to use " \ - "--with-openssl-dir= option to specify the prefix where OpenSSL " \ - "is installed." - end +Logging::message "=== Checking for required stuff... ===\n" +pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h") + +if !pkg_config_found && !find_openssl_library + Logging::message "=== Checking for required stuff failed. ===\n" + Logging::message "Makefile wasn't created. Fix the errors above.\n" + raise "OpenSSL library could not be found. You might want to use " \ + "--with-openssl-dir= option to specify the prefix where OpenSSL " \ + "is installed." +end + +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") } +else + checking_for("OpenSSL version >= 1.0.2") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10002000L", "openssl/opensslv.h") } +end +unless version_ok + raise "OpenSSL >= 1.0.2 or LibreSSL >= 3.1.0 is required" end -unless checking_for("OpenSSL version is 1.0.1 or later") { - try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") } - raise "OpenSSL >= 1.0.1 or LibreSSL is required" +# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h +if is_libressl && ($mswin || $mingw) + $defs.push("-DNOCRYPT") end Logging::message "=== Checking for OpenSSL features... ===\n" # compile options have_func("RAND_egd") -engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil - cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni} +engines = %w{dynamic 4758cca aep atalla chil + cswift nuron sureware ubsec padlock capi gmp gost cryptodev} engines.each { |name| - OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") + have_func("ENGINE_load_#{name}()", "openssl/engine.h") } -if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") - $defs.push("-DNOCRYPT") -end - -# added in 1.0.2 -have_func("EC_curve_nist2nid") -have_func("X509_REVOKED_dup") -have_func("X509_STORE_CTX_get0_store") -have_func("SSL_CTX_set_alpn_select_cb") -OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h") -OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h") -OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h") -have_func("SSL_is_server") - # added in 1.1.0 -if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || - try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x2070000fL", "openssl/opensslv.h") +if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || is_libressl $defs.push("-DHAVE_OPAQUE_OPENSSL") end -have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API") -have_func("BN_GENCB_new") -have_func("BN_GENCB_free") -have_func("BN_GENCB_get_arg") have_func("EVP_MD_CTX_new") have_func("EVP_MD_CTX_free") -have_func("HMAC_CTX_new") -have_func("HMAC_CTX_free") -OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated +have_func("EVP_MD_CTX_pkey_ctx") have_func("X509_STORE_get_ex_data") have_func("X509_STORE_set_ex_data") +have_func("X509_STORE_get_ex_new_index") have_func("X509_CRL_get0_signature") have_func("X509_REQ_get0_signature") have_func("X509_REVOKED_get0_serialNumber") @@ -159,16 +153,36 @@ def find_openssl_library have_func("X509_STORE_up_ref") have_func("SSL_SESSION_up_ref") have_func("EVP_PKEY_up_ref") -OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed -OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h") +have_func("SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h") have_func("SSL_CTX_get_security_level") have_func("X509_get0_notBefore") have_func("SSL_SESSION_get_protocol_version") +have_func("TS_STATUS_INFO_get0_status") +have_func("TS_STATUS_INFO_get0_text") +have_func("TS_STATUS_INFO_get0_failure_info") +have_func("TS_VERIFY_CTS_set_certs(NULL, NULL)", "openssl/ts.h") +have_func("TS_VERIFY_CTX_set_store") +have_func("TS_VERIFY_CTX_add_flags") +have_func("TS_RESP_CTX_set_time_cb") have_func("EVP_PBE_scrypt") +have_func("SSL_CTX_set_post_handshake_auth") + +# added in 1.1.1 +have_func("EVP_PKEY_check") + +# added in 3.0.0 +have_func("SSL_set0_tmp_dh_pkey") +have_func("ERR_get_error_all") +have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") +have_func("SSL_CTX_load_verify_file") +have_func("BN_check_prime") +have_func("EVP_MD_CTX_get0_md") +have_func("EVP_MD_CTX_get_pkey_ctx") +have_func("EVP_PKEY_eq") +have_func("EVP_PKEY_dup") Logging::message "=== Checking done. ===\n" create_header -OpenSSL.restore_warning_flag create_makefile("openssl") Logging::message "Done.\n" diff --git a/ruby/ext/openssl/lib/openssl.rb b/ruby/ext/openssl/lib/openssl.rb index 091428292..8a342f15b 100644 --- a/ruby/ext/openssl/lib/openssl.rb +++ b/ruby/ext/openssl/lib/openssl.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true =begin = Info 'OpenSSL for Ruby 2' project @@ -12,11 +12,26 @@ require 'openssl.so' -require 'openssl/bn' -require 'openssl/pkey' -require 'openssl/cipher' -require 'openssl/config' -require 'openssl/digest' -require 'openssl/x509' -require 'openssl/ssl' -require 'openssl/pkcs5' +require_relative 'openssl/bn' +require_relative 'openssl/pkey' +require_relative 'openssl/cipher' +require_relative 'openssl/digest' +require_relative 'openssl/hmac' +require_relative 'openssl/x509' +require_relative 'openssl/ssl' +require_relative 'openssl/pkcs5' +require_relative 'openssl/version' + +module OpenSSL + # call-seq: + # OpenSSL.secure_compare(string, string) -> boolean + # + # Constant time memory comparison. Inputs are hashed using SHA-256 to mask + # the length of the secret. Returns +true+ if the strings are identical, + # +false+ otherwise. + def self.secure_compare(a, b) + hashed_a = OpenSSL::Digest.digest('SHA256', a) + hashed_b = OpenSSL::Digest.digest('SHA256', b) + OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b + end +end diff --git a/ruby/ext/openssl/lib/openssl/bn.rb b/ruby/ext/openssl/lib/openssl/bn.rb index 8d1ebefb6..0a5e11b4c 100644 --- a/ruby/ext/openssl/lib/openssl/bn.rb +++ b/ruby/ext/openssl/lib/openssl/bn.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # # = Ruby-space definitions that completes C-space funcs for BN diff --git a/ruby/ext/openssl/lib/openssl/buffering.rb b/ruby/ext/openssl/lib/openssl/buffering.rb index 5d1586e59..d47e1082e 100644 --- a/ruby/ext/openssl/lib/openssl/buffering.rb +++ b/ruby/ext/openssl/lib/openssl/buffering.rb @@ -1,5 +1,5 @@ # coding: binary -# frozen_string_literal: false +# frozen_string_literal: true #-- #= Info # 'OpenSSL for Ruby 2' project @@ -22,6 +22,29 @@ module OpenSSL::Buffering include Enumerable + # A buffer which will retain binary encoding. + class Buffer < String + BINARY = Encoding::BINARY + + def initialize + super + + force_encoding(BINARY) + end + + def << string + if string.encoding == BINARY + super(string) + else + super(string.b) + end + + return self + end + + alias concat << + end + ## # The "sync mode" of the SSLSocket. # @@ -40,7 +63,7 @@ module OpenSSL::Buffering def initialize(*) super @eof = false - @rbuffer = "" + @rbuffer = Buffer.new @sync = @io.sync end @@ -78,6 +101,15 @@ def consume_rbuff(size=nil) public + # call-seq: + # ssl.getbyte => 81 + # + # Get the next 8bit byte from `ssl`. Returns `nil` on EOF + def getbyte + byte = read(1) + byte && byte.unpack1("C") + end + ## # Reads _size_ bytes from the stream. If _buf_ is provided it must # reference a string which will receive the data. @@ -312,7 +344,7 @@ def eof? # buffer is flushed to the underlying socket. def do_write(s) - @wbuffer = "" unless defined? @wbuffer + @wbuffer = Buffer.new unless defined? @wbuffer @wbuffer << s @wbuffer.force_encoding(Encoding::BINARY) @sync ||= false @@ -398,7 +430,7 @@ def <<(s) # See IO#puts for full details. def puts(*args) - s = "" + s = Buffer.new if args.empty? s << "\n" end @@ -416,7 +448,7 @@ def puts(*args) # See IO#print for full details. def print(*args) - s = "" + s = Buffer.new args.each{ |arg| s << arg.to_s } do_write(s) nil diff --git a/ruby/ext/openssl/lib/openssl/cipher.rb b/ruby/ext/openssl/lib/openssl/cipher.rb index af721b3a8..8ad8c35dd 100644 --- a/ruby/ext/openssl/lib/openssl/cipher.rb +++ b/ruby/ext/openssl/lib/openssl/cipher.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # = Ruby-space predefined Cipher subclasses # diff --git a/ruby/ext/openssl/lib/openssl/config.rb b/ruby/ext/openssl/lib/openssl/config.rb deleted file mode 100644 index 48d8be006..000000000 --- a/ruby/ext/openssl/lib/openssl/config.rb +++ /dev/null @@ -1,474 +0,0 @@ -# frozen_string_literal: false -=begin -= Ruby-space definitions that completes C-space funcs for Config - -= Info - Copyright (C) 2010 Hiroshi Nakamura - -= Licence - This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) - -=end - -require 'stringio' - -module OpenSSL - ## - # = OpenSSL::Config - # - # Configuration for the openssl library. - # - # Many system's installation of openssl library will depend on your system - # configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for - # the location of the file for your host. - # - # See also http://www.openssl.org/docs/apps/config.html - class Config - include Enumerable - - class << self - - ## - # Parses a given _string_ as a blob that contains configuration for - # OpenSSL. - # - # If the source of the IO is a file, then consider using #parse_config. - def parse(string) - c = new() - parse_config(StringIO.new(string)).each do |section, hash| - c[section] = hash - end - c - end - - ## - # load is an alias to ::new - alias load new - - ## - # Parses the configuration data read from _io_, see also #parse. - # - # Raises a ConfigError on invalid configuration data. - def parse_config(io) - begin - parse_config_lines(io) - rescue ConfigError => e - e.message.replace("error in line #{io.lineno}: " + e.message) - raise - end - end - - def get_key_string(data, section, key) # :nodoc: - if v = data[section] && data[section][key] - return v - elsif section == 'ENV' - if v = ENV[key] - return v - end - end - if v = data['default'] && data['default'][key] - return v - end - end - - private - - def parse_config_lines(io) - section = 'default' - data = {section => {}} - while definition = get_definition(io) - definition = clear_comments(definition) - next if definition.empty? - if definition[0] == ?[ - if /\[([^\]]*)\]/ =~ definition - section = $1.strip - data[section] ||= {} - else - raise ConfigError, "missing close square bracket" - end - else - if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition - if $2 - section = $1 - key = $2 - else - key = $1 - end - value = unescape_value(data, section, $3) - (data[section] ||= {})[key] = value.strip - else - raise ConfigError, "missing equal sign" - end - end - end - data - end - - # escape with backslash - QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ - # escape with backslash and doubled dq - QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ - # escaped char map - ESCAPE_MAP = { - "r" => "\r", - "n" => "\n", - "b" => "\b", - "t" => "\t", - } - - def unescape_value(data, section, value) - scanned = [] - while m = value.match(/['"\\$]/) - scanned << m.pre_match - c = m[0] - value = m.post_match - case c - when "'" - if m = value.match(QUOTE_REGEXP_SQ) - scanned << m[1].gsub(/\\(.)/, '\\1') - value = m.post_match - else - break - end - when '"' - if m = value.match(QUOTE_REGEXP_DQ) - scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') - value = m.post_match - else - break - end - when "\\" - c = value.slice!(0, 1) - scanned << (ESCAPE_MAP[c] || c) - when "$" - ref, value = extract_reference(value) - refsec = section - if ref.index('::') - refsec, ref = ref.split('::', 2) - end - if v = get_key_string(data, refsec, ref) - scanned << v - else - raise ConfigError, "variable has no value" - end - else - raise 'must not reaced' - end - end - scanned << value - scanned.join - end - - def extract_reference(value) - rest = '' - if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) - value = m[1] || m[2] - rest = m.post_match - elsif [?(, ?{].include?(value[0]) - raise ConfigError, "no close brace" - end - if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) - return m[0], m.post_match + rest - else - raise - end - end - - def clear_comments(line) - # FCOMMENT - if m = line.match(/\A([\t\n\f ]*);.*\z/) - return m[1] - end - # COMMENT - scanned = [] - while m = line.match(/[#'"\\]/) - scanned << m.pre_match - c = m[0] - line = m.post_match - case c - when '#' - line = nil - break - when "'", '"' - regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ - scanned << c - if m = line.match(regexp) - scanned << m[0] - line = m.post_match - else - scanned << line - line = nil - break - end - when "\\" - scanned << c - scanned << line.slice!(0, 1) - else - raise 'must not reaced' - end - end - scanned << line - scanned.join - end - - def get_definition(io) - if line = get_line(io) - while /[^\\]\\\z/ =~ line - if extra = get_line(io) - line += extra - else - break - end - end - return line.strip - end - end - - def get_line(io) - if line = io.gets - line.gsub(/[\r\n]*/, '') - end - end - end - - ## - # Creates an instance of OpenSSL's configuration class. - # - # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= - # - # If the optional _filename_ parameter is provided, then it is read in and - # parsed via #parse_config. - # - # This can raise IO exceptions based on the access, or availability of the - # file. A ConfigError exception may be raised depending on the validity of - # the data being configured. - # - def initialize(filename = nil) - @data = {} - if filename - File.open(filename.to_s) do |file| - Config.parse_config(file).each do |section, hash| - self[section] = hash - end - end - end - end - - ## - # Gets the value of _key_ from the given _section_ - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> # - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can get a specific value from the config if you know the _section_ - # and _key_ like so: - # - # config.get_value('default','foo') - # #=> "bar" - # - def get_value(section, key) - if section.nil? - raise TypeError.new('nil not allowed') - end - section = 'default' if section.empty? - get_key_string(section, key) - end - - ## - # - # *Deprecated* - # - # Use #get_value instead - def value(arg1, arg2 = nil) # :nodoc: - warn('Config#value is deprecated; use Config#get_value') - if arg2.nil? - section, key = 'default', arg1 - else - section, key = arg1, arg2 - end - section ||= 'default' - section = 'default' if section.empty? - get_key_string(section, key) - end - - ## - # Set the target _key_ with a given _value_ under a specific _section_. - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> # - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can set the value of _foo_ under the _default_ section to a new - # value: - # - # config.add_value('default', 'foo', 'buzz') - # #=> "buzz" - # puts config.to_s - # #=> [ default ] - # # foo=buzz - # - def add_value(section, key, value) - check_modify - (@data[section] ||= {})[key] = value - end - - ## - # Get a specific _section_ from the current configuration - # - # Given the following configurating file being loaded: - # - # config = OpenSSL::Config.load('foo.cnf') - # #=> # - # puts config.to_s - # #=> [ default ] - # # foo=bar - # - # You can get a hash of the specific section like so: - # - # config['default'] - # #=> {"foo"=>"bar"} - # - def [](section) - @data[section] || {} - end - - ## - # Deprecated - # - # Use #[] instead - def section(name) # :nodoc: - warn('Config#section is deprecated; use Config#[]') - @data[name] || {} - end - - ## - # Sets a specific _section_ name with a Hash _pairs_. - # - # Given the following configuration being created: - # - # config = OpenSSL::Config.new - # #=> # - # config['default'] = {"foo"=>"bar","baz"=>"buz"} - # #=> {"foo"=>"bar", "baz"=>"buz"} - # puts config.to_s - # #=> [ default ] - # # foo=bar - # # baz=buz - # - # It's important to note that this will essentially merge any of the keys - # in _pairs_ with the existing _section_. For example: - # - # config['default'] - # #=> {"foo"=>"bar", "baz"=>"buz"} - # config['default'] = {"foo" => "changed"} - # #=> {"foo"=>"changed"} - # config['default'] - # #=> {"foo"=>"changed", "baz"=>"buz"} - # - def []=(section, pairs) - check_modify - @data[section] ||= {} - pairs.each do |key, value| - self.add_value(section, key, value) - end - end - - ## - # Get the names of all sections in the current configuration - def sections - @data.keys - end - - ## - # Get the parsable form of the current configuration - # - # Given the following configuration being created: - # - # config = OpenSSL::Config.new - # #=> # - # config['default'] = {"foo"=>"bar","baz"=>"buz"} - # #=> {"foo"=>"bar", "baz"=>"buz"} - # puts config.to_s - # #=> [ default ] - # # foo=bar - # # baz=buz - # - # You can parse get the serialized configuration using #to_s and then parse - # it later: - # - # serialized_config = config.to_s - # # much later... - # new_config = OpenSSL::Config.parse(serialized_config) - # #=> # - # puts new_config - # #=> [ default ] - # foo=bar - # baz=buz - # - def to_s - ary = [] - @data.keys.sort.each do |section| - ary << "[ #{section} ]\n" - @data[section].keys.each do |key| - ary << "#{key}=#{@data[section][key]}\n" - end - ary << "\n" - end - ary.join - end - - ## - # For a block. - # - # Receive the section and its pairs for the current configuration. - # - # config.each do |section, key, value| - # # ... - # end - # - def each - @data.each do |section, hash| - hash.each do |key, value| - yield [section, key, value] - end - end - end - - ## - # String representation of this configuration object, including the class - # name and its sections. - def inspect - "#<#{self.class.name} sections=#{sections.inspect}>" - end - - protected - - def data # :nodoc: - @data - end - - private - - def initialize_copy(other) - @data = other.data.dup - end - - def check_modify - raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? - end - - def get_key_string(section, key) - Config.get_key_string(@data, section, key) - end - end -end diff --git a/ruby/ext/openssl/lib/openssl/digest.rb b/ruby/ext/openssl/lib/openssl/digest.rb index b6744de6b..2ff8398e4 100644 --- a/ruby/ext/openssl/lib/openssl/digest.rb +++ b/ruby/ext/openssl/lib/openssl/digest.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # = Ruby-space predefined Digest subclasses # @@ -15,11 +15,6 @@ module OpenSSL class Digest - alg = %w(MD2 MD4 MD5 MDC2 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512) - if OPENSSL_VERSION_NUMBER < 0x10100000 - alg += %w(DSS DSS1 SHA) - end - # Return the hash value computed with _name_ Digest. _name_ is either the # long name or short name of a supported digest algorithm. # @@ -29,23 +24,26 @@ class Digest # # which is equivalent to: # - # OpenSSL::Digest::SHA256.digest("abc") + # OpenSSL::Digest.digest('SHA256', "abc") def self.digest(name, data) super(data, name) end - alg.each{|name| + %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name| klass = Class.new(self) { define_method(:initialize, ->(data = nil) {super(name, data)}) } + singleton = (class << klass; self; end) + singleton.class_eval{ - define_method(:digest){|data| new.digest(data) } - define_method(:hexdigest){|data| new.hexdigest(data) } + define_method(:digest) {|data| new.digest(data)} + define_method(:hexdigest) {|data| new.hexdigest(data)} } - const_set(name, klass) - } + + const_set(name.tr('-', '_'), klass) + end # Deprecated. # diff --git a/ruby/ext/openssl/lib/openssl/hmac.rb b/ruby/ext/openssl/lib/openssl/hmac.rb new file mode 100644 index 000000000..c8c844d8d --- /dev/null +++ b/ruby/ext/openssl/lib/openssl/hmac.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module OpenSSL + class HMAC + # Securely compare with another HMAC instance in constant time. + def ==(other) + return false unless HMAC === other + return false unless self.digest.bytesize == other.digest.bytesize + + OpenSSL.fixed_length_secure_compare(self.digest, other.digest) + end + + # :call-seq: + # hmac.base64digest -> string + # + # Returns the authentication code an a Base64-encoded string. + def base64digest + [digest].pack("m0") + end + + class << self + # :call-seq: + # HMAC.digest(digest, key, data) -> aString + # + # Returns the authentication code as a binary string. The _digest_ parameter + # specifies the digest algorithm to use. This may be a String representing + # the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.digest('SHA1', key, data) + # #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" + def digest(digest, key, data) + hmac = new(key, digest) + hmac << data + hmac.digest + end + + # :call-seq: + # HMAC.hexdigest(digest, key, data) -> aString + # + # Returns the authentication code as a hex-encoded string. The _digest_ + # parameter specifies the digest algorithm to use. This may be a String + # representing the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) + # #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" + def hexdigest(digest, key, data) + hmac = new(key, digest) + hmac << data + hmac.hexdigest + end + + # :call-seq: + # HMAC.base64digest(digest, key, data) -> aString + # + # Returns the authentication code as a Base64-encoded string. The _digest_ + # parameter specifies the digest algorithm to use. This may be a String + # representing the algorithm name or an instance of OpenSSL::Digest. + # + # === Example + # key = 'key' + # data = 'The quick brown fox jumps over the lazy dog' + # + # hmac = OpenSSL::HMAC.base64digest('SHA1', key, data) + # #=> "3nybhbi3iqa8ino29wqQcBydtNk=" + def base64digest(digest, key, data) + [digest(digest, key, data)].pack("m0") + end + end + end +end diff --git a/ruby/ext/openssl/lib/openssl/marshal.rb b/ruby/ext/openssl/lib/openssl/marshal.rb new file mode 100644 index 000000000..af5647192 --- /dev/null +++ b/ruby/ext/openssl/lib/openssl/marshal.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +#-- +# = Ruby-space definitions to add DER (de)serialization to classes +# +# = Info +# 'OpenSSL for Ruby 2' project +# Copyright (C) 2002 Michal Rokos +# All rights reserved. +# +# = Licence +# This program is licensed under the same licence as Ruby. +# (See the file 'LICENCE'.) +#++ +module OpenSSL + module Marshal + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def _load(string) + new(string) + end + end + + def _dump(_level) + to_der + end + end +end diff --git a/ruby/ext/openssl/lib/openssl/pkcs5.rb b/ruby/ext/openssl/lib/openssl/pkcs5.rb index 959447df5..8dedc4bee 100644 --- a/ruby/ext/openssl/lib/openssl/pkcs5.rb +++ b/ruby/ext/openssl/lib/openssl/pkcs5.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # Ruby/OpenSSL Project # Copyright (C) 2017 Ruby/OpenSSL Project Authors diff --git a/ruby/ext/openssl/lib/openssl/pkey.rb b/ruby/ext/openssl/lib/openssl/pkey.rb index 8a547c340..c3e062909 100644 --- a/ruby/ext/openssl/lib/openssl/pkey.rb +++ b/ruby/ext/openssl/lib/openssl/pkey.rb @@ -1,11 +1,290 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # Ruby/OpenSSL Project # Copyright (C) 2017 Ruby/OpenSSL Project Authors #++ +require_relative 'marshal' + module OpenSSL::PKey + class DH + include OpenSSL::Marshal + + # :call-seq: + # dh.public_key -> dhnew + # + # Returns a new DH instance that carries just the \DH parameters. + # + # Contrary to the method name, the returned DH object contains only + # parameters and not the public key. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of re-generating the key pair while keeping the + # parameters, check OpenSSL::PKey.generate_key. + # + # Example: + # # OpenSSL::PKey::DH.generate by default generates a random key pair + # dh1 = OpenSSL::PKey::DH.generate(2048) + # p dh1.priv_key #=> # + # dhcopy = dh1.public_key + # p dhcopy.priv_key #=> nil + def public_key + DH.new(to_der) + end + + # :call-seq: + # dh.compute_key(pub_bn) -> string + # + # Returns a String containing a shared secret computed from the other + # party's public value. + # + # This method is provided for backwards compatibility, and calls #derive + # internally. + # + # === Parameters + # * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by + # DH#public_key as that contains the DH parameters only. + def compute_key(pub_bn) + # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very + # inefficient + obj = OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.ObjectId("dhKeyAgreement"), + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Integer(p), + OpenSSL::ASN1.Integer(g), + ]), + ]), + OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der), + ]) + derive(OpenSSL::PKey.read(obj.to_der)) + end + + # :call-seq: + # dh.generate_key! -> self + # + # Generates a private and public key unless a private key already exists. + # If this DH instance was generated from public \DH parameters (e.g. by + # encoding the result of DH#public_key), then this method needs to be + # called first in order to generate the per-session keys before performing + # the actual key exchange. + # + # Deprecated in version 3.0. This method is incompatible with + # OpenSSL 3.0.0 or later. + # + # See also OpenSSL::PKey.generate_key. + # + # Example: + # # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later + # dh0 = OpenSSL::PKey::DH.new(2048) + # dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name) + # dh.generate_key! + # puts dh.private? # => true + # puts dh0.pub_key == dh.pub_key #=> false + # + # # With OpenSSL::PKey.generate_key + # dh0 = OpenSSL::PKey::DH.new(2048) + # dh = OpenSSL::PKey.generate_key(dh0) + # puts dh0.pub_key == dh.pub_key #=> false + def generate_key! + if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000 + raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \ + "use OpenSSL::PKey.generate_key instead" + end + + unless priv_key + tmp = OpenSSL::PKey.generate_key(self) + set_key(tmp.pub_key, tmp.priv_key) + end + self + end + + class << self + # :call-seq: + # DH.generate(size, generator = 2) -> dh + # + # Creates a new DH instance from scratch by generating random parameters + # and a key pair. + # + # See also OpenSSL::PKey.generate_parameters and + # OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + # +generator+:: + # The generator. + def generate(size, generator = 2, &blk) + dhparams = OpenSSL::PKey.generate_parameters("DH", { + "dh_paramgen_prime_len" => size, + "dh_paramgen_generator" => generator, + }, &blk) + OpenSSL::PKey.generate_key(dhparams) + end + + # Handle DH.new(size, generator) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + end + + class DSA + include OpenSSL::Marshal + + # :call-seq: + # dsa.public_key -> dsanew + # + # Returns a new DSA instance that carries just the \DSA parameters and the + # public key. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of serializing the public key, to PEM or DER encoding of + # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and + # PKey#public_to_der. + def public_key + OpenSSL::PKey.read(public_to_der) + end + + class << self + # :call-seq: + # DSA.generate(size) -> dsa + # + # Creates a new DSA instance by generating a private/public key pair + # from scratch. + # + # See also OpenSSL::PKey.generate_parameters and + # OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + def generate(size, &blk) + dsaparams = OpenSSL::PKey.generate_parameters("DSA", { + "dsa_paramgen_bits" => size, + }, &blk) + OpenSSL::PKey.generate_key(dsaparams) + end + + # Handle DSA.new(size) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + + # :call-seq: + # dsa.syssign(string) -> string + # + # Computes and returns the \DSA signature of +string+, where +string+ is + # expected to be an already-computed message digest of the original input + # data. The signature is issued using the private key of this DSA instance. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + # + # +string+:: + # A message digest of the original input data to be signed. + # + # Example: + # dsa = OpenSSL::PKey::DSA.new(2048) + # doc = "Sign me" + # digest = OpenSSL::Digest.digest('SHA1', doc) + # + # # With legacy #syssign and #sysverify: + # sig = dsa.syssign(digest) + # p dsa.sysverify(digest, sig) #=> true + # + # # With #sign_raw and #verify_raw: + # sig = dsa.sign_raw(nil, digest) + # p dsa.verify_raw(nil, sig, digest) #=> true + def syssign(string) + q or raise OpenSSL::PKey::DSAError, "incomplete DSA" + private? or raise OpenSSL::PKey::DSAError, "Private DSA key needed!" + begin + sign_raw(nil, string) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::DSAError, $!.message + end + end + + # :call-seq: + # dsa.sysverify(digest, sig) -> true | false + # + # Verifies whether the signature is valid given the message digest input. + # It does so by validating +sig+ using the public key of this DSA instance. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + # + # +digest+:: + # A message digest of the original input data to be signed. + # +sig+:: + # A \DSA signature value. + def sysverify(digest, sig) + verify_raw(nil, sig, digest) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::DSAError, $!.message + end + end + if defined?(EC) + class EC + include OpenSSL::Marshal + + # :call-seq: + # key.dsa_sign_asn1(data) -> String + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + def dsa_sign_asn1(data) + sign_raw(nil, data) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::ECError, $!.message + end + + # :call-seq: + # key.dsa_verify_asn1(data, sig) -> true | false + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. + def dsa_verify_asn1(data, sig) + verify_raw(nil, sig, data) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::ECError, $!.message + end + + # :call-seq: + # ec.dh_compute_key(pubkey) -> string + # + # Derives a shared secret by ECDH. _pubkey_ must be an instance of + # OpenSSL::PKey::EC::Point and must belong to the same group. + # + # This method is provided for backwards compatibility, and calls #derive + # internally. + def dh_compute_key(pubkey) + obj = OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.Sequence([ + OpenSSL::ASN1.ObjectId("id-ecPublicKey"), + group.to_der, + ]), + OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)), + ]) + derive(OpenSSL::PKey.read(obj.to_der)) + end + end + class EC::Point # :call-seq: # point.to_bn([conversion_form]) -> OpenSSL::BN @@ -22,4 +301,159 @@ def to_bn(conversion_form = group.point_conversion_form) end end end + + class RSA + include OpenSSL::Marshal + + # :call-seq: + # rsa.public_key -> rsanew + # + # Returns a new RSA instance that carries just the public key components. + # + # This method is provided for backwards compatibility. In most cases, there + # is no need to call this method. + # + # For the purpose of serializing the public key, to PEM or DER encoding of + # X.509 SubjectPublicKeyInfo format, check PKey#public_to_pem and + # PKey#public_to_der. + def public_key + OpenSSL::PKey.read(public_to_der) + end + + class << self + # :call-seq: + # RSA.generate(size, exponent = 65537) -> RSA + # + # Generates an \RSA keypair. + # + # See also OpenSSL::PKey.generate_key. + # + # +size+:: + # The desired key size in bits. + # +exponent+:: + # An odd Integer, normally 3, 17, or 65537. + def generate(size, exp = 0x10001, &blk) + OpenSSL::PKey.generate_key("RSA", { + "rsa_keygen_bits" => size, + "rsa_keygen_pubexp" => exp, + }, &blk) + end + + # Handle RSA.new(size, exponent) form here; new(str) and new() forms + # are handled by #initialize + def new(*args, &blk) # :nodoc: + if args[0].is_a?(Integer) + generate(*args, &blk) + else + super + end + end + end + + # :call-seq: + # rsa.private_encrypt(string) -> String + # rsa.private_encrypt(string, padding) -> String + # + # Encrypt +string+ with the private key. +padding+ defaults to + # PKCS1_PADDING. The encrypted string output can be decrypted using + # #public_decrypt. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and + # PKey::PKey#verify_recover instead. + def private_encrypt(string, padding = PKCS1_PADDING) + n or raise OpenSSL::PKey::RSAError, "incomplete RSA" + private? or raise OpenSSL::PKey::RSAError, "private key needed." + begin + sign_raw(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::RSAError, $!.message + end + end + + # :call-seq: + # rsa.public_decrypt(string) -> String + # rsa.public_decrypt(string, padding) -> String + # + # Decrypt +string+, which has been encrypted with the private key, with the + # public key. +padding+ defaults to PKCS1_PADDING. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and + # PKey::PKey#verify_recover instead. + def public_decrypt(string, padding = PKCS1_PADDING) + n or raise OpenSSL::PKey::RSAError, "incomplete RSA" + begin + verify_recover(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::RSAError, $!.message + end + end + + # :call-seq: + # rsa.public_encrypt(string) -> String + # rsa.public_encrypt(string, padding) -> String + # + # Encrypt +string+ with the public key. +padding+ defaults to + # PKCS1_PADDING. The encrypted string output can be decrypted using + # #private_decrypt. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. + def public_encrypt(data, padding = PKCS1_PADDING) + n or raise OpenSSL::PKey::RSAError, "incomplete RSA" + begin + encrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::RSAError, $!.message + end + end + + # :call-seq: + # rsa.private_decrypt(string) -> String + # rsa.private_decrypt(string, padding) -> String + # + # Decrypt +string+, which has been encrypted with the public key, with the + # private key. +padding+ defaults to PKCS1_PADDING. + # + # Deprecated in version 3.0. + # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. + def private_decrypt(data, padding = PKCS1_PADDING) + n or raise OpenSSL::PKey::RSAError, "incomplete RSA" + private? or raise OpenSSL::PKey::RSAError, "private key needed." + begin + decrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) + rescue OpenSSL::PKey::PKeyError + raise OpenSSL::PKey::RSAError, $!.message + end + end + + PKCS1_PADDING = 1 + SSLV23_PADDING = 2 + NO_PADDING = 3 + PKCS1_OAEP_PADDING = 4 + + private def translate_padding_mode(num) + case num + when PKCS1_PADDING + "pkcs1" + when SSLV23_PADDING + "sslv23" + when NO_PADDING + "none" + when PKCS1_OAEP_PADDING + "oaep" + else + raise OpenSSL::PKey::PKeyError, "unsupported padding mode" + end + end + end end diff --git a/ruby/ext/openssl/lib/openssl/ssl.rb b/ruby/ext/openssl/lib/openssl/ssl.rb index 355eb2ebb..a9103ecd2 100644 --- a/ruby/ext/openssl/lib/openssl/ssl.rb +++ b/ruby/ext/openssl/lib/openssl/ssl.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true =begin = Info 'OpenSSL for Ruby 2' project @@ -13,6 +13,7 @@ require "openssl/buffering" require "io/nonblock" require "ipaddr" +require "socket" module OpenSSL module SSL @@ -90,15 +91,17 @@ class SSLContext DEFAULT_CERT_STORE.set_default_paths DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL - # A callback invoked when DH parameters are required. + # A callback invoked when DH parameters are required for ephemeral DH key + # exchange. # - # The callback is invoked with the Session for the key exchange, an + # The callback is invoked with the SSLSocket, a # flag indicating the use of an export cipher and the keylength # required. # # The callback must return an OpenSSL::PKey::DH instance of the correct # key length. - + # + # Deprecated in version 3.0. Use #tmp_dh= instead. attr_accessor :tmp_dh_callback # A callback invoked at connect time to distinguish between multiple @@ -121,6 +124,8 @@ class SSLContext 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 end ## @@ -231,6 +236,11 @@ def ssl_version=(meth) end module SocketForwarder + # The file descriptor for the socket. + def fileno + to_io.fileno + end + def addr to_io.addr end @@ -424,10 +434,6 @@ def tmp_dh_callback @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK end - def tmp_ecdh_callback - @context.tmp_ecdh_callback - end - def session_new_cb @context.session_new_cb end @@ -435,6 +441,38 @@ def session_new_cb def session_get_cb @context.session_get_cb end + + class << self + + # call-seq: + # open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) + # + # Creates a new instance of SSLSocket. + # _remote\_host_ and _remote\_port_ are used to open TCPSocket. + # If _local\_host_ and _local\_port_ are specified, + # then those parameters are used on the local end to establish the connection. + # If _context_ is provided, + # the SSL Sockets initial params will be taken from the context. + # + # === Examples + # + # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443) + # sock.connect # Initiates a connection to localhost:443 + # + # with SSLContext: + # + # ctx = OpenSSL::SSL::SSLContext.new + # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx) + # sock.connect # Initiates a connection to localhost:443 with SSLContext + def open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil) + sock = ::TCPSocket.open(remote_host, remote_port, local_host, local_port) + if context.nil? + return OpenSSL::SSL::SSLSocket.new(sock) + else + return OpenSSL::SSL::SSLSocket.new(sock, context) + end + end + end end ## @@ -465,7 +503,7 @@ def to_io end # See TCPServer#listen for details. - def listen(backlog=5) + def listen(backlog=Socket::SOMAXCONN) @svr.listen(backlog) end diff --git a/ruby/ext/openssl/lib/openssl/version.rb b/ruby/ext/openssl/lib/openssl/version.rb new file mode 100644 index 000000000..5e6060435 --- /dev/null +++ b/ruby/ext/openssl/lib/openssl/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module OpenSSL + VERSION = "3.0.0" +end diff --git a/ruby/ext/openssl/lib/openssl/x509.rb b/ruby/ext/openssl/lib/openssl/x509.rb index 98358f90d..f973f4f4d 100644 --- a/ruby/ext/openssl/lib/openssl/x509.rb +++ b/ruby/ext/openssl/lib/openssl/x509.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true #-- # = Ruby-space definitions that completes C-space funcs for X509 and subclasses # @@ -12,6 +12,8 @@ # (See the file 'LICENCE'.) #++ +require_relative 'marshal' + module OpenSSL module X509 class ExtensionFactory @@ -41,6 +43,8 @@ def create_ext_from_hash(hash) end class Extension + include OpenSSL::Marshal + def ==(other) return false unless Extension === other to_der == other.to_der @@ -60,9 +64,146 @@ def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} def to_a [ self.oid, self.value, self.critical? ] end + + module Helpers + def find_extension(oid) + extensions.find { |e| e.oid == oid } + end + end + + module SubjectKeyIdentifier + include Helpers + + # Get the subject's key identifier from the subjectKeyIdentifier + # exteension, as described in RFC5280 Section 4.2.1.2. + # + # Returns the binary String key identifier or nil or raises + # ASN1::ASN1Error. + def subject_key_identifier + ext = find_extension("subjectKeyIdentifier") + return nil if ext.nil? + + ski_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || ski_asn1.tag_class != :UNIVERSAL || ski_asn1.tag != ASN1::OCTET_STRING + raise ASN1::ASN1Error, "invalid extension" + end + + ski_asn1.value + end + end + + module AuthorityKeyIdentifier + include Helpers + + # Get the issuing certificate's key identifier from the + # authorityKeyIdentifier extension, as described in RFC5280 + # Section 4.2.1.1 + # + # Returns the binary String keyIdentifier or nil or raises + # ASN1::ASN1Error. + def authority_key_identifier + ext = find_extension("authorityKeyIdentifier") + return nil if ext.nil? + + aki_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || aki_asn1.tag_class != :UNIVERSAL || aki_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + key_id = aki_asn1.value.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + + key_id.nil? ? nil : key_id.value + end + end + + 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 + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def crl_uris + ext = find_extension("crlDistributionPoints") + return nil if ext.nil? + + cdp_asn1 = ASN1.decode(ext.value_der) + if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + crl_uris = cdp_asn1.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| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier + end + end + + crl_uris&.map(&:value) + end + end + + module AuthorityInfoAccess + include Helpers + + # Get the information and services for the issuer from the certificate's + # authority information access extension exteension, as described in RFC5280 + # Section 4.2.2.1. + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def ca_issuer_uris + aia_asn1 = parse_aia_asn1 + return nil if aia_asn1.nil? + + ca_issuer = aia_asn1.value.select do |authority_info_access| + authority_info_access.value.first.value == "caIssuers" + end + + ca_issuer&.map(&:value)&.map(&:last)&.map(&:value) + end + + # Get the URIs for OCSP from the certificate's authority information access + # extension exteension, as described in RFC5280 Section 4.2.2.1. + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def ocsp_uris + aia_asn1 = parse_aia_asn1 + return nil if aia_asn1.nil? + + ocsp = aia_asn1.value.select do |authority_info_access| + authority_info_access.value.first.value == "OCSP" + end + + ocsp&.map(&:value)&.map(&:last)&.map(&:value) + end + + private + + def parse_aia_asn1 + ext = find_extension("authorityInfoAccess") + return nil if ext.nil? + + aia_asn1 = ASN1.decode(ext.value_der) + if ext.critical? || aia_asn1.tag_class != :UNIVERSAL || aia_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error, "invalid extension" + end + + aia_asn1 + end + end end class Name + include OpenSSL::Marshal + module RFC2253DN Special = ',=+<>#;' HexChar = /[0-9a-fA-F]/ @@ -138,11 +279,29 @@ def scan(dn) end class << self + # Parses the UTF-8 string representation of a distinguished name, + # according to RFC 2253. + # + # See also #to_utf8 for the opposite operation. def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE) ary = OpenSSL::X509::Name::RFC2253DN.scan(str) self.new(ary, template) end + # Parses the string representation of a distinguished name. Two + # different forms are supported: + # + # - \OpenSSL format (X509_NAME_oneline()) used by + # #to_s. For example: /DC=com/DC=example/CN=nobody + # - \OpenSSL format (X509_NAME_print()) + # used by #to_s(OpenSSL::X509::Name::COMPAT). For example: + # DC=com, DC=example, CN=nobody + # + # Neither of them is standardized and has quirks and inconsistencies + # in handling of escaped characters or multi-valued RDNs. + # + # Use of this method is discouraged in new applications. See + # Name.parse_rfc2253 and #to_utf8 for the alternative. def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE) if str.start_with?("/") # /A=B/C=D format @@ -166,6 +325,8 @@ def pretty_print(q) end class Attribute + include OpenSSL::Marshal + def ==(other) return false unless Attribute === other to_der == other.to_der @@ -179,6 +340,12 @@ def cleanup end class Certificate + include OpenSSL::Marshal + include Extension::SubjectKeyIdentifier + include Extension::AuthorityKeyIdentifier + include Extension::CRLDistributionPoints + include Extension::AuthorityInfoAccess + def pretty_print(q) q.object_group(self) { q.breakable @@ -189,9 +356,16 @@ def pretty_print(q) q.text 'not_after='; q.pp self.not_after } end + + def self.load_file(path) + load(File.binread(path)) + end end class CRL + include OpenSSL::Marshal + include Extension::AuthorityKeyIdentifier + def ==(other) return false unless CRL === other to_der == other.to_der @@ -206,6 +380,8 @@ def ==(other) end class Request + include OpenSSL::Marshal + def ==(other) return false unless Request === other to_der == other.to_der diff --git a/ruby/ext/openssl/openssl.gemspec b/ruby/ext/openssl/openssl.gemspec index 295379fb6..c6cd81833 100644 --- a/ruby/ext/openssl/openssl.gemspec +++ b/ruby/ext/openssl/openssl.gemspec @@ -1,29 +1,21 @@ -# -*- encoding: utf-8 -*- +Gem::Specification.new do |spec| + spec.name = "openssl" + spec.version = "3.0.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.homepage = "https://github.com/ruby/openssl" + spec.license = "Ruby" -Gem::Specification.new do |s| - s.name = "openssl" - s.version = "2.1.2" + spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "LICENSE.txt"] + spec.require_paths = ["lib"] + spec.extensions = ["ext/openssl/extconf.rb"] - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= - s.require_paths = ["lib"] - s.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] - s.date = "2018-10-17" - s.description = "It wraps the OpenSSL library." - s.email = ["ruby-core@ruby-lang.org"] - s.extensions = ["ext/openssl/extconf.rb"] - s.extra_rdoc_files = ["README.md", "CONTRIBUTING.md", "History.md"] - s.files = ["BSDL", "CONTRIBUTING.md", "History.md", "LICENSE.txt", "README.md", "ext/openssl/deprecation.rb", "ext/openssl/extconf.rb", "ext/openssl/openssl_missing.c", "ext/openssl/openssl_missing.h", "ext/openssl/ossl.c", "ext/openssl/ossl.h", "ext/openssl/ossl_asn1.c", "ext/openssl/ossl_asn1.h", "ext/openssl/ossl_bio.c", "ext/openssl/ossl_bio.h", "ext/openssl/ossl_bn.c", "ext/openssl/ossl_bn.h", "ext/openssl/ossl_cipher.c", "ext/openssl/ossl_cipher.h", "ext/openssl/ossl_config.c", "ext/openssl/ossl_config.h", "ext/openssl/ossl_digest.c", "ext/openssl/ossl_digest.h", "ext/openssl/ossl_engine.c", "ext/openssl/ossl_engine.h", "ext/openssl/ossl_hmac.c", "ext/openssl/ossl_hmac.h", "ext/openssl/ossl_kdf.c", "ext/openssl/ossl_kdf.h", "ext/openssl/ossl_ns_spki.c", "ext/openssl/ossl_ns_spki.h", "ext/openssl/ossl_ocsp.c", "ext/openssl/ossl_ocsp.h", "ext/openssl/ossl_pkcs12.c", "ext/openssl/ossl_pkcs12.h", "ext/openssl/ossl_pkcs7.c", "ext/openssl/ossl_pkcs7.h", "ext/openssl/ossl_pkey.c", "ext/openssl/ossl_pkey.h", "ext/openssl/ossl_pkey_dh.c", "ext/openssl/ossl_pkey_dsa.c", "ext/openssl/ossl_pkey_ec.c", "ext/openssl/ossl_pkey_rsa.c", "ext/openssl/ossl_rand.c", "ext/openssl/ossl_rand.h", "ext/openssl/ossl_ssl.c", "ext/openssl/ossl_ssl.h", "ext/openssl/ossl_ssl_session.c", "ext/openssl/ossl_version.h", "ext/openssl/ossl_x509.c", "ext/openssl/ossl_x509.h", "ext/openssl/ossl_x509attr.c", "ext/openssl/ossl_x509cert.c", "ext/openssl/ossl_x509crl.c", "ext/openssl/ossl_x509ext.c", "ext/openssl/ossl_x509name.c", "ext/openssl/ossl_x509req.c", "ext/openssl/ossl_x509revoked.c", "ext/openssl/ossl_x509store.c", "ext/openssl/ruby_missing.h", "lib/openssl.rb", "lib/openssl/bn.rb", "lib/openssl/buffering.rb", "lib/openssl/cipher.rb", "lib/openssl/config.rb", "lib/openssl/digest.rb", "lib/openssl/pkcs5.rb", "lib/openssl/pkey.rb", "lib/openssl/ssl.rb", "lib/openssl/x509.rb"] - s.homepage = "https://github.com/ruby/openssl" - s.licenses = ["Ruby"] - s.rdoc_options = ["--main", "README.md"] - s.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - s.rubygems_version = "3.0.0.beta1" - s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography." + spec.extra_rdoc_files = Dir["*.md"] + spec.rdoc_options = ["--main", "README.md"] - s.add_runtime_dependency("ipaddr", [">= 0"]) - s.add_development_dependency("rake", [">= 0"]) - s.add_development_dependency("rake-compiler", [">= 0"]) - s.add_development_dependency("test-unit", ["~> 3.0"]) - s.add_development_dependency("rdoc", [">= 0"]) + spec.required_ruby_version = ">= 2.6.0" + + spec.metadata["msys2_mingw_dependencies"] = "openssl" end diff --git a/ruby/ext/openssl/openssl_missing.c b/ruby/ext/openssl/openssl_missing.c index b36ef0288..4415703db 100644 --- a/ruby/ext/openssl/openssl_missing.c +++ b/ruby/ext/openssl/openssl_missing.c @@ -10,77 +10,11 @@ #include RUBY_EXTCONF_H #include /* memcpy() */ -#if !defined(OPENSSL_NO_ENGINE) -# include -#endif -#if !defined(OPENSSL_NO_HMAC) -# include -#endif #include #include "openssl_missing.h" -/* added in 1.0.2 */ -#if !defined(OPENSSL_NO_EC) -#if !defined(HAVE_EC_CURVE_NIST2NID) -static struct { - const char *name; - int nid; -} nist_curves[] = { - {"B-163", NID_sect163r2}, - {"B-233", NID_sect233r1}, - {"B-283", NID_sect283r1}, - {"B-409", NID_sect409r1}, - {"B-571", NID_sect571r1}, - {"K-163", NID_sect163k1}, - {"K-233", NID_sect233k1}, - {"K-283", NID_sect283k1}, - {"K-409", NID_sect409k1}, - {"K-571", NID_sect571k1}, - {"P-192", NID_X9_62_prime192v1}, - {"P-224", NID_secp224r1}, - {"P-256", NID_X9_62_prime256v1}, - {"P-384", NID_secp384r1}, - {"P-521", NID_secp521r1} -}; - -int -ossl_EC_curve_nist2nid(const char *name) -{ - size_t i; - for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) { - if (!strcmp(nist_curves[i].name, name)) - return nist_curves[i].nid; - } - return NID_undef; -} -#endif -#endif - /*** added in 1.1.0 ***/ -#if !defined(HAVE_HMAC_CTX_NEW) -HMAC_CTX * -ossl_HMAC_CTX_new(void) -{ - HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); - if (!ctx) - return NULL; - HMAC_CTX_init(ctx); - return ctx; -} -#endif - -#if !defined(HAVE_HMAC_CTX_FREE) -void -ossl_HMAC_CTX_free(HMAC_CTX *ctx) -{ - if (ctx) { - HMAC_CTX_cleanup(ctx); - OPENSSL_free(ctx); - } -} -#endif - #if !defined(HAVE_X509_CRL_GET0_SIGNATURE) void ossl_X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, diff --git a/ruby/ext/openssl/openssl_missing.h b/ruby/ext/openssl/openssl_missing.h index 09998214e..8629bfe50 100644 --- a/ruby/ext/openssl/openssl_missing.h +++ b/ruby/ext/openssl/openssl_missing.h @@ -12,40 +12,7 @@ #include "ruby/config.h" -/* added in 1.0.2 */ -#if !defined(OPENSSL_NO_EC) -#if !defined(HAVE_EC_CURVE_NIST2NID) -int ossl_EC_curve_nist2nid(const char *); -# define EC_curve_nist2nid ossl_EC_curve_nist2nid -#endif -#endif - -#if !defined(HAVE_X509_REVOKED_DUP) -# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ - (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) -#endif - -#if !defined(HAVE_X509_STORE_CTX_GET0_STORE) -# define X509_STORE_CTX_get0_store(x) ((x)->ctx) -#endif - -#if !defined(HAVE_SSL_IS_SERVER) -# define SSL_is_server(s) ((s)->server) -#endif - /* added in 1.1.0 */ -#if !defined(HAVE_BN_GENCB_NEW) -# define BN_GENCB_new() ((BN_GENCB *)OPENSSL_malloc(sizeof(BN_GENCB))) -#endif - -#if !defined(HAVE_BN_GENCB_FREE) -# define BN_GENCB_free(cb) OPENSSL_free(cb) -#endif - -#if !defined(HAVE_BN_GENCB_GET_ARG) -# define BN_GENCB_get_arg(cb) (cb)->arg -#endif - #if !defined(HAVE_EVP_MD_CTX_NEW) # define EVP_MD_CTX_new EVP_MD_CTX_create #endif @@ -54,16 +21,6 @@ int ossl_EC_curve_nist2nid(const char *); # define EVP_MD_CTX_free EVP_MD_CTX_destroy #endif -#if !defined(HAVE_HMAC_CTX_NEW) -HMAC_CTX *ossl_HMAC_CTX_new(void); -# define HMAC_CTX_new ossl_HMAC_CTX_new -#endif - -#if !defined(HAVE_HMAC_CTX_FREE) -void ossl_HMAC_CTX_free(HMAC_CTX *); -# define HMAC_CTX_free ossl_HMAC_CTX_free -#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)) @@ -72,6 +29,9 @@ void ossl_HMAC_CTX_free(HMAC_CTX *); #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)) @@ -219,4 +179,60 @@ IMPL_PKEY_GETTER(EC_KEY, ec) # 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 + +/* + * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to + * 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 +# define EVP_PKEY_eq(a, b) EVP_PKEY_cmp(a, b) +#endif + #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ruby/ext/openssl/ossl.c b/ruby/ext/openssl/ossl.c index e4196f075..6c532aca9 100644 --- a/ruby/ext/openssl/ossl.c +++ b/ruby/ext/openssl/ossl.c @@ -9,13 +9,19 @@ */ #include "ossl.h" #include /* for ossl_raise */ -#include /* for OpenSSL < 1.1.0 locks */ + +/* 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 */ #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \ -STACK_OF(type) * \ +VALUE \ ossl_##name##_ary2sk0(VALUE ary) \ { \ STACK_OF(type) *sk; \ @@ -37,7 +43,7 @@ ossl_##name##_ary2sk0(VALUE ary) \ x = dup(val); /* NEED TO DUP */ \ sk_##type##_push(sk, x); \ } \ - return sk; \ + return (VALUE)sk; \ } \ \ STACK_OF(type) * \ @@ -262,15 +268,11 @@ ossl_to_der_if_possible(VALUE obj) /* * Errors */ -static VALUE -ossl_make_error(VALUE exc, const char *fmt, va_list args) +VALUE +ossl_make_error(VALUE exc, VALUE str) { - VALUE str = Qnil; unsigned long e; - if (fmt) { - str = rb_vsprintf(fmt, args); - } e = ERR_peek_last_error(); if (e) { const char *msg = ERR_reason_error_string(e); @@ -294,37 +296,48 @@ ossl_raise(VALUE exc, const char *fmt, ...) { va_list args; VALUE err; - va_start(args, fmt); - err = ossl_make_error(exc, fmt, args); - va_end(args); - rb_exc_raise(err); + + if (fmt) { + va_start(args, fmt); + err = rb_vsprintf(fmt, args); + va_end(args); + } + else { + err = Qnil; + } + + rb_exc_raise(ossl_make_error(exc, err)); } void ossl_clear_error(void) { if (dOSSL == Qtrue) { - unsigned long e; - const char *file, *data, *errstr; - int line, flags; - - while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { - errstr = ERR_error_string(e, NULL); - if (!errstr) - errstr = "(null)"; - - if (flags & ERR_TXT_STRING) { - if (!data) - data = "(null)"; - rb_warn("error on stack: %s (%s)", errstr, data); - } - else { - rb_warn("error on stack: %s", errstr); - } - } + unsigned long e; + const char *file, *data, *func, *lib, *reason; + char append[256] = ""; + int line, flags; + +#ifdef HAVE_ERR_GET_ERROR_ALL + while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) { +#else + while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { + func = ERR_func_error_string(e); +#endif + lib = ERR_lib_error_string(e); + reason = ERR_reason_error_string(e); + + if (flags & ERR_TXT_STRING) { + if (!data) + data = "(null)"; + snprintf(append, sizeof(append), " (%s)", data); + } + rb_warn("error on stack: error:%08lX:%s:%s:%s%s", e, lib ? lib : "", + func ? func : "", reason ? reason : "", append); + } } else { - ERR_clear_error(); + ERR_clear_error(); } } @@ -386,7 +399,7 @@ ossl_debug_get(VALUE self) * call-seq: * OpenSSL.debug = boolean -> boolean * - * Turns on or off debug mode. With debug mode, all erros added to the OpenSSL + * Turns on or off debug mode. With debug mode, all errors added to the OpenSSL * error queue will be printed to stderr. */ static VALUE @@ -497,8 +510,11 @@ print_mem_leaks(VALUE self) int ret; #endif - BN_CTX_free(ossl_bn_ctx); - ossl_bn_ctx = NULL; +#ifndef HAVE_RB_EXT_RACTOR_SAFE + // for Ruby 2.x + void ossl_bn_ctx_free(void); // ossl_bn.c + ossl_bn_ctx_free(); +#endif #if OPENSSL_VERSION_NUMBER >= 0x10100000 ret = CRYPTO_mem_leaks_fp(stderr); @@ -604,6 +620,35 @@ static void Init_ossl_locks(void) } #endif /* !HAVE_OPENSSL_110_THREADING_API */ +/* + * call-seq: + * OpenSSL.fixed_length_secure_compare(string, string) -> boolean + * + * Constant time memory comparison for fixed length strings, such as results + * of HMAC calculations. + * + * Returns +true+ if the strings are identical, +false+ if they are of the same + * length but not identical. If the length is different, +ArgumentError+ is + * raised. + */ +static VALUE +ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) +{ + const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1); + const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2); + long len1 = RSTRING_LEN(str1); + long len2 = RSTRING_LEN(str2); + + if (len1 != len2) { + ossl_raise(rb_eArgError, "inputs must be of equal length"); + } + + switch (CRYPTO_memcmp(p1, p2, len1)) { + case 0: return Qtrue; + default: return Qfalse; + } +} + /* * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the * OpenSSL[https://www.openssl.org/] library. @@ -635,7 +680,7 @@ static void Init_ossl_locks(void) * ahold of the key may use it unless it is encrypted. In order to securely * export a key you may export it with a pass phrase. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * pass_phrase = 'my secure pass phrase goes here' * * key_secure = key.export cipher, pass_phrase @@ -650,13 +695,13 @@ static void Init_ossl_locks(void) * * A key can also be loaded from a file. * - * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem' + * key2 = OpenSSL::PKey.read File.read 'private_key.pem' * key2.public? # => true * key2.private? # => true * * or * - * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem' + * key3 = OpenSSL::PKey.read File.read 'public_key.pem' * key3.public? # => true * key3.private? # => false * @@ -668,7 +713,7 @@ static void Init_ossl_locks(void) * * key4_pem = File.read 'private.secure.pem' * pass_phrase = 'my secure pass phrase goes here' - * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase + * key4 = OpenSSL::PKey.read key4_pem, pass_phrase * * == RSA Encryption * @@ -710,16 +755,14 @@ static void Init_ossl_locks(void) * To sign a document, a cryptographically secure hash of the document is * computed first, which is then signed using the private key. * - * digest = OpenSSL::Digest::SHA256.new - * signature = key.sign digest, document + * signature = key.sign 'SHA256', document * * To validate the signature, again a hash of the document is computed and * the signature is decrypted using the public key. The result is then * compared to the hash just computed, if they are equal the signature was * valid. * - * digest = OpenSSL::Digest::SHA256.new - * if key.verify digest, signature, document + * if key.verify 'SHA256', signature, document * puts 'Valid' * else * puts 'Invalid' @@ -745,7 +788,7 @@ static void Init_ossl_locks(void) * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt, * the number of iterations largely depends on the hardware being used. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * cipher.encrypt * iv = cipher.random_iv * @@ -753,7 +796,7 @@ static void Init_ossl_locks(void) * salt = OpenSSL::Random.random_bytes 16 * iter = 20000 * key_len = cipher.key_len - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) * cipher.key = key @@ -768,7 +811,7 @@ static void Init_ossl_locks(void) * Use the same steps as before to derive the symmetric AES key, this time * setting the Cipher up for decryption. * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * cipher.decrypt * cipher.iv = iv # the one generated with #random_iv * @@ -776,7 +819,7 @@ static void Init_ossl_locks(void) * salt = ... # the one generated above * iter = 20000 * key_len = cipher.key_len - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest) * cipher.key = key @@ -803,7 +846,7 @@ static void Init_ossl_locks(void) * * First set up the cipher for encryption * - * encryptor = OpenSSL::Cipher.new 'AES-128-CBC' + * encryptor = OpenSSL::Cipher.new 'aes-256-cbc' * encryptor.encrypt * encryptor.pkcs5_keyivgen pass_phrase, salt * @@ -816,7 +859,7 @@ static void Init_ossl_locks(void) * * Use a new Cipher instance set up for decryption * - * decryptor = OpenSSL::Cipher.new 'AES-128-CBC' + * decryptor = OpenSSL::Cipher.new 'aes-256-cbc' * decryptor.decrypt * decryptor.pkcs5_keyivgen pass_phrase, salt * @@ -833,7 +876,7 @@ static void Init_ossl_locks(void) * signature. * * key = OpenSSL::PKey::RSA.new 2048 - * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' + * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example' * * cert = OpenSSL::X509::Certificate.new * cert.version = 2 @@ -872,7 +915,7 @@ static void Init_ossl_locks(void) * certificate. * * cert.issuer = name - * cert.sign key, OpenSSL::Digest::SHA1.new + * cert.sign key, OpenSSL::Digest.new('SHA1') * * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end * @@ -904,7 +947,7 @@ static void Init_ossl_locks(void) * ca_key = OpenSSL::PKey::RSA.new 2048 * pass_phrase = 'my secure pass phrase goes here' * - * cipher = OpenSSL::Cipher.new 'AES-128-CBC' + * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * * open 'ca_key.pem', 'w', 0400 do |io| * io.write ca_key.export(cipher, pass_phrase) @@ -915,7 +958,7 @@ static void Init_ossl_locks(void) * A CA certificate is created the same way we created a certificate above, but * with different extensions. * - * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example' + * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example' * * ca_cert = OpenSSL::X509::Certificate.new * ca_cert.serial = 0 @@ -948,7 +991,7 @@ static void Init_ossl_locks(void) * * Root CA certificates are self-signed. * - * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new + * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1') * * The CA certificate is saved to disk so it may be distributed to all the * users of the keys this CA will sign. @@ -966,7 +1009,7 @@ static void Init_ossl_locks(void) * csr.version = 0 * csr.subject = name * csr.public_key = key.public_key - * csr.sign key, OpenSSL::Digest::SHA1.new + * csr.sign key, OpenSSL::Digest.new('SHA1') * * A CSR is saved to disk and sent to the CA for signing. * @@ -1010,7 +1053,7 @@ static void Init_ossl_locks(void) * csr_cert.add_extension \ * extension_factory.create_extension('subjectKeyIdentifier', 'hash') * - * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new + * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1') * * open 'csr_cert.pem', 'w' do |io| * io.write csr_cert.to_pem @@ -1042,13 +1085,13 @@ static void Init_ossl_locks(void) * loop do * ssl_connection = ssl_server.accept * - * data = connection.gets + * data = ssl_connection.gets * * response = "I got #{data.dump}" * puts response * - * connection.puts "I got #{data.dump}" - * connection.close + * ssl_connection.puts "I got #{data.dump}" + * ssl_connection.close * end * * === SSL client @@ -1099,6 +1142,10 @@ static void Init_ossl_locks(void) void Init_openssl(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + #undef rb_intern /* * Init timezone info @@ -1125,11 +1172,7 @@ Init_openssl(void) */ mOSSL = rb_define_module("OpenSSL"); rb_global_variable(&mOSSL); - - /* - * OpenSSL ruby extension version - */ - rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); + rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2); /* * Version of OpenSSL the ruby OpenSSL extension was built with @@ -1205,6 +1248,9 @@ Init_openssl(void) Init_ossl_pkey(); Init_ossl_rand(); Init_ossl_ssl(); +#ifndef OPENSSL_NO_TS + Init_ossl_ts(); +#endif Init_ossl_x509(); Init_ossl_ocsp(); Init_ossl_engine(); diff --git a/ruby/ext/openssl/ossl.h b/ruby/ext/openssl/ossl.h index 6af7ddd7d..4b5126893 100644 --- a/ruby/ext/openssl/ossl.h +++ b/ruby/ext/openssl/ossl.h @@ -18,19 +18,19 @@ #include #include #include + #include #include #include #include #include #include -#include #include #include -#include -#if !defined(OPENSSL_NO_ENGINE) -# include +#ifndef OPENSSL_NO_TS + #include #endif +#include #if !defined(OPENSSL_NO_OCSP) # include #endif @@ -40,6 +40,22 @@ #include #include +#ifndef LIBRESSL_VERSION_NUMBER +# define OSSL_IS_LIBRESSL 0 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) \ + (OPENSSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0 +#else +# define OSSL_IS_LIBRESSL 1 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) 0 +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) \ + (LIBRESSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) +#endif + +#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_USE_ENGINE +#endif + /* * Common Module */ @@ -85,9 +101,8 @@ VALUE ossl_buf2str(char *buf, int len); VALUE ossl_str_new(const char *, long, int *); #define ossl_str_adjust(str, p) \ do{\ - long len = RSTRING_LEN(str);\ long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\ - assert(newlen <= len);\ + assert(newlen <= RSTRING_LEN(str));\ rb_str_set_len((str), newlen);\ }while(0) /* @@ -119,7 +134,9 @@ int ossl_pem_passwd_cb(char *, int, int, void *); /* * ERRor messages */ -NORETURN(void ossl_raise(VALUE, const char *, ...)); +PRINTF_ARGS(NORETURN(void ossl_raise(VALUE, const char *, ...)), 2, 3); +/* Make exception instance from str and OpenSSL error reason string. */ +VALUE ossl_make_error(VALUE exc, VALUE str); /* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */ void ossl_clear_error(void); @@ -152,7 +169,6 @@ void ossl_debug(const char *, ...); * Include all parts */ #include "openssl_missing.h" -#include "ruby_missing.h" #include "ossl_asn1.h" #include "ossl_bio.h" #include "ossl_bn.h" @@ -167,7 +183,9 @@ void ossl_debug(const char *, ...); #include "ossl_pkey.h" #include "ossl_rand.h" #include "ossl_ssl.h" -#include "ossl_version.h" +#ifndef OPENSSL_NO_TS + #include "ossl_ts.h" +#endif #include "ossl_x509.h" #include "ossl_engine.h" #include "ossl_kdf.h" diff --git a/ruby/ext/openssl/ossl_asn1.c b/ruby/ext/openssl/ossl_asn1.c index 0085d4bea..a61d3eefb 100644 --- a/ruby/ext/openssl/ossl_asn1.c +++ b/ruby/ext/openssl/ossl_asn1.c @@ -69,6 +69,12 @@ asn1time_to_time(const ASN1_TIME *time) return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); } +static VALUE +asn1time_to_time_i(VALUE arg) +{ + return asn1time_to_time((ASN1_TIME *)arg); +} + void ossl_time_split(VALUE time, time_t *sec, int *days) { @@ -136,6 +142,12 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) return ai; } +static VALUE +asn1integer_to_num_i(VALUE arg) +{ + return asn1integer_to_num((ASN1_INTEGER *)arg); +} + /********/ /* * ASN1 module @@ -325,7 +337,7 @@ decode_int(unsigned char* der, long length) p = der; if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length))) ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num, + ret = rb_protect(asn1integer_to_num_i, (VALUE)ai, &status); ASN1_INTEGER_free(ai); if(status) rb_jump_tag(status); @@ -365,7 +377,7 @@ decode_enum(unsigned char* der, long length) p = der; if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length))) ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num, + ret = rb_protect(asn1integer_to_num_i, (VALUE)ai, &status); ASN1_ENUMERATED_free(ai); if(status) rb_jump_tag(status); @@ -427,7 +439,7 @@ decode_time(unsigned char* der, long length) p = der; if(!(time = d2i_ASN1_TIME(NULL, &p, length))) ossl_raise(eASN1Error, NULL); - ret = rb_protect((VALUE (*)(VALUE))asn1time_to_time, + ret = rb_protect(asn1time_to_time_i, (VALUE)time, &status); ASN1_TIME_free(time); if(status) rb_jump_tag(status); @@ -1285,6 +1297,30 @@ 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) { @@ -1486,7 +1522,7 @@ Init_ossl_asn1(void) * * An Array that stores the name of a given tag number. These names are * the same as the name of the tag constant that is additionally defined, - * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2. + * e.g. +UNIVERSAL_TAG_NAME[2] = "INTEGER"+ and +OpenSSL::ASN1::INTEGER = 2+. * * == Example usage * @@ -1818,6 +1854,7 @@ do{\ rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0); 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); diff --git a/ruby/ext/openssl/ossl_bn.c b/ruby/ext/openssl/ossl_bn.c index 6f0064e96..56fa0ec30 100644 --- a/ruby/ext/openssl/ossl_bn.c +++ b/ruby/ext/openssl/ossl_bn.c @@ -10,6 +10,10 @@ /* 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 { \ @@ -150,12 +154,58 @@ ossl_bn_value_ptr(volatile VALUE *ptr) /* * Private */ -/* - * BN_CTX - is used in more difficult math. ops - * (Why just 1? Because Ruby itself isn't thread safe, - * we don't need to care about threads) - */ -BN_CTX *ossl_bn_ctx; + +#ifdef HAVE_RB_EXT_RACTOR_SAFE +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 = { + NULL, // mark + ossl_bn_ctx_free, +}; + +rb_ractor_local_key_t ossl_bn_ctx_key; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + // stored in ractor local storage + + BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key); + if (!ctx) { + if (!(ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx); + } + return ctx; +} +#else +// for ruby 2.x +static BN_CTX *gv_ossl_bn_ctx; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + if (gv_ossl_bn_ctx == NULL) { + if (!(gv_ossl_bn_ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + } + return gv_ossl_bn_ctx; +} + +void +ossl_bn_ctx_free(void) +{ + BN_CTX_free(gv_ossl_bn_ctx); + gv_ossl_bn_ctx = NULL; +} +#endif static VALUE ossl_bn_alloc(VALUE klass) @@ -173,13 +223,29 @@ ossl_bn_alloc(VALUE klass) /* * call-seq: - * OpenSSL::BN.new => aBN - * OpenSSL::BN.new(bn) => aBN - * OpenSSL::BN.new(integer) => aBN - * OpenSSL::BN.new(string) => aBN - * OpenSSL::BN.new(string, 0 | 2 | 10 | 16) => aBN + * OpenSSL::BN.new(bn) -> aBN + * OpenSSL::BN.new(integer) -> aBN + * OpenSSL::BN.new(string, base = 10) -> aBN + * + * Construct a new \OpenSSL BIGNUM object. * - * Construct a new OpenSSL BIGNUM object. + * If +bn+ is an Integer or OpenSSL::BN, a new instance of OpenSSL::BN + * representing the same value is returned. See also Integer#to_bn for the + * short-hand. + * + * If a String is given, the content will be parsed according to +base+. + * + * +string+:: + * The string to be parsed. + * +base+:: + * The format. Must be one of the following: + * - +0+ - MPI format. See the man page BN_mpi2bn(3) for details. + * - +2+ - Variable-length and big-endian binary encoding of a positive + * number. + * - +10+ - Decimal number representation, with a leading '-' for a negative + * number. + * - +16+ - Hexadeciaml number representation, with a leading '-' for a + * negative number. */ static VALUE ossl_bn_initialize(int argc, VALUE *argv, VALUE self) @@ -193,6 +259,10 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) base = NUM2INT(bs); } + if (NIL_P(str)) { + ossl_raise(rb_eArgError, "invalid argument"); + } + if (RB_INTEGER_TYPE_P(str)) { GetBN(self, bn); integer_to_bnptr(str, bn); @@ -243,16 +313,21 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * bn.to_s => string - * bn.to_s(base) => string + * bn.to_s(base = 10) -> string * - * === Parameters - * * _base_ - Integer - * Valid values: - * * 0 - MPI - * * 2 - binary - * * 10 - the default - * * 16 - hex + * Returns the string representation of the bignum. + * + * BN.new can parse the encoded string to convert back into an OpenSSL::BN. + * + * +base+:: + * The format. Must be one of the following: + * - +0+ - MPI format. See the man page BN_bn2mpi(3) for details. + * - +2+ - Variable-length and big-endian binary encoding. The sign of + * the bignum is ignored. + * - +10+ - Decimal number representation, with a leading '-' for a negative + * bignum. + * - +16+ - Hexadeciaml number representation, with a leading '-' for a + * negative bignum. */ static VALUE ossl_bn_to_s(int argc, VALUE *argv, VALUE self) @@ -400,7 +475,7 @@ ossl_bn_is_negative(VALUE self) if (!(result = BN_new())) { \ ossl_raise(eBNError, NULL); \ } \ - if (!BN_##func(result, bn, ossl_bn_ctx)) { \ + if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \ BN_free(result); \ ossl_raise(eBNError, NULL); \ } \ @@ -426,7 +501,7 @@ BIGNUM_1c(sqr) if (!(result = BN_new())) { \ ossl_raise(eBNError, NULL); \ } \ - if (!BN_##func(result, bn1, bn2)) { \ + if (BN_##func(result, bn1, bn2) <= 0) { \ BN_free(result); \ ossl_raise(eBNError, NULL); \ } \ @@ -459,7 +534,7 @@ BIGNUM_2(sub) if (!(result = BN_new())) { \ ossl_raise(eBNError, NULL); \ } \ - if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ + if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \ BN_free(result); \ ossl_raise(eBNError, NULL); \ } \ @@ -503,11 +578,21 @@ BIGNUM_2c(gcd) BIGNUM_2c(mod_sqr) /* - * Document-method: OpenSSL::BN#mod_inverse * call-seq: - * bn.mod_inverse(bn2) => aBN + * bn.mod_inverse(bn2) => aBN */ -BIGNUM_2c(mod_inverse) +static VALUE +ossl_bn_mod_inverse(VALUE self, VALUE other) +{ + BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; + VALUE obj; + GetBN(self, bn1); + obj = NewBN(rb_obj_class(self)); + if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx))) + ossl_raise(eBNError, "BN_mod_inverse"); + SetBN(obj, result); + return obj; +} /* * call-seq: @@ -556,7 +641,7 @@ ossl_bn_div(VALUE self, VALUE other) if (!(result = BN_new())) { \ ossl_raise(eBNError, NULL); \ } \ - if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ + if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \ BN_free(result); \ ossl_raise(eBNError, NULL); \ } \ @@ -598,7 +683,7 @@ BIGNUM_3c(mod_exp) { \ BIGNUM *bn; \ GetBN(self, bn); \ - if (!BN_##func(bn, NUM2INT(bit))) { \ + if (BN_##func(bn, NUM2INT(bit)) <= 0) { \ ossl_raise(eBNError, NULL); \ } \ return self; \ @@ -658,7 +743,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit) if (!(result = BN_new())) { \ ossl_raise(eBNError, NULL); \ } \ - if (!BN_##func(result, bn, b)) { \ + if (BN_##func(result, bn, b) <= 0) { \ BN_free(result); \ ossl_raise(eBNError, NULL); \ } \ @@ -688,7 +773,7 @@ BIGNUM_SHIFT(rshift) int b; \ b = NUM2INT(bits); \ GetBN(self, bn); \ - if (!BN_##func(bn, bn, b)) \ + if (BN_##func(bn, bn, b) <= 0) \ ossl_raise(eBNError, NULL); \ return self; \ } @@ -707,78 +792,64 @@ BIGNUM_SELF_SHIFT(lshift) */ BIGNUM_SELF_SHIFT(rshift) -#define BIGNUM_RAND(func) \ - static VALUE \ - ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ - { \ - BIGNUM *result; \ - int bottom = 0, top = 0, b; \ - VALUE bits, fill, odd, obj; \ - \ - switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ - case 3: \ - bottom = (odd == Qtrue) ? 1 : 0; \ - /* FALLTHROUGH */ \ - case 2: \ - top = NUM2INT(fill); \ - } \ - b = NUM2INT(bits); \ - obj = NewBN(klass); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func(result, b, top, bottom)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - SetBN(obj, result); \ - return obj; \ - } - -/* - * Document-method: OpenSSL::BN.rand - * BN.rand(bits [, fill [, odd]]) -> aBN - */ -BIGNUM_RAND(rand) - -/* - * Document-method: OpenSSL::BN.pseudo_rand - * BN.pseudo_rand(bits [, fill [, odd]]) -> aBN - */ -BIGNUM_RAND(pseudo_rand) - -#define BIGNUM_RAND_RANGE(func) \ - static VALUE \ - ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ - { \ - BIGNUM *bn = GetBNPtr(range), *result; \ - VALUE obj = NewBN(klass); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (!BN_##func##_range(result, bn)) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - SetBN(obj, result); \ - return obj; \ - } - /* - * Document-method: OpenSSL::BN.rand_range * call-seq: - * BN.rand_range(range) -> aBN + * BN.rand(bits [, fill [, odd]]) -> aBN * + * Generates a cryptographically strong pseudo-random number of +bits+. + * + * See also the man page BN_rand(3). */ -BIGNUM_RAND_RANGE(rand) +static VALUE +ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass) +{ + BIGNUM *result; + int bottom = 0, top = 0, b; + VALUE bits, fill, odd, obj; + + switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { + case 3: + bottom = (odd == Qtrue) ? 1 : 0; + /* FALLTHROUGH */ + case 2: + top = NUM2INT(fill); + } + b = NUM2INT(bits); + obj = NewBN(klass); + if (!(result = BN_new())) { + ossl_raise(eBNError, "BN_new"); + } + if (BN_rand(result, b, top, bottom) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand"); + } + SetBN(obj, result); + return obj; +} /* - * Document-method: OpenSSL::BN.pseudo_rand_range * call-seq: - * BN.pseudo_rand_range(range) -> aBN + * BN.rand_range(range) -> aBN + * + * Generates a cryptographically strong pseudo-random number in the range + * 0...+range+. * + * See also the man page BN_rand_range(3). */ -BIGNUM_RAND_RANGE(pseudo_rand) +static VALUE +ossl_bn_s_rand_range(VALUE klass, VALUE range) +{ + BIGNUM *bn = GetBNPtr(range), *result; + VALUE obj = NewBN(klass); + if (!(result = BN_new())) + ossl_raise(eBNError, "BN_new"); + if (BN_rand_range(result, bn) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand_range"); + } + SetBN(obj, result); + return obj; +} /* * call-seq: @@ -873,7 +944,17 @@ ossl_bn_copy(VALUE self, VALUE other) static VALUE ossl_bn_uplus(VALUE self) { - return self; + VALUE obj; + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + obj = NewBN(cBN); + bn2 = BN_dup(bn1); + if (!bn2) + ossl_raise(eBNError, "BN_dup"); + SetBN(obj, bn2); + + return obj; } /* @@ -897,6 +978,24 @@ ossl_bn_uminus(VALUE self) return obj; } +/* + * call-seq: + * bn.abs -> aBN + */ +static VALUE +ossl_bn_abs(VALUE self) +{ + BIGNUM *bn1; + + GetBN(self, bn1); + if (BN_is_negative(bn1)) { + return ossl_bn_uminus(self); + } + else { + return ossl_bn_uplus(self); + } +} + #define BIGNUM_CMP(func) \ static VALUE \ ossl_bn_##func(VALUE self, VALUE other) \ @@ -1005,34 +1104,29 @@ ossl_bn_hash(VALUE self) * bn.prime? => true | false * bn.prime?(checks) => true | false * - * Performs a Miller-Rabin probabilistic primality test with _checks_ - * iterations. If _checks_ is not specified, a number of iterations is used - * that yields a false positive rate of at most 2^-80 for random input. + * Performs a Miller-Rabin probabilistic primality test for +bn+. * - * === Parameters - * * _checks_ - integer + * +checks+ parameter is deprecated in version 3.0. It has no effect. */ static VALUE ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) { BIGNUM *bn; - VALUE vchecks; - int checks = BN_prime_checks; + int ret; - if (rb_scan_args(argc, argv, "01", &vchecks) == 1) { - checks = NUM2INT(vchecks); - } + rb_check_arity(argc, 0, 1); GetBN(self, bn); - switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) { - case 1: - return Qtrue; - case 0: - return Qfalse; - default: - ossl_raise(eBNError, NULL); - } - /* not reachable */ - return Qnil; + +#ifdef HAVE_BN_CHECK_PRIME + ret = BN_check_prime(bn, ossl_bn_ctx, NULL); + if (ret < 0) + ossl_raise(eBNError, "BN_check_prime"); +#else + ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL); + if (ret < 0) + ossl_raise(eBNError, "BN_is_prime_fasttest_ex"); +#endif + return ret ? Qtrue : Qfalse; } /* @@ -1041,39 +1135,52 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) * bn.prime_fasttest?(checks) => true | false * bn.prime_fasttest?(checks, trial_div) => true | false * - * Performs a Miller-Rabin primality test. This is same as #prime? except this - * first attempts trial divisions with some small primes. + * Performs a Miller-Rabin probabilistic primality test for +bn+. * - * === Parameters - * * _checks_ - integer - * * _trial_div_ - boolean + * Deprecated in version 3.0. Use #prime? instead. + * + * +checks+ and +trial_div+ parameters no longer have any effect. */ static VALUE ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) +{ + rb_check_arity(argc, 0, 2); + return ossl_bn_is_prime(0, argv, self); +} + +/* + * call-seq: + * bn.get_flags(flags) => flags + * + * Returns the flags on the BN object. + * The argument is used as a bit mask. + * + * === Parameters + * * _flags_ - integer + */ +static VALUE +ossl_bn_get_flags(VALUE self, VALUE arg) { BIGNUM *bn; - VALUE vchecks, vtrivdiv; - int checks = BN_prime_checks, do_trial_division = 1; + GetBN(self, bn); - rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); + return INT2NUM(BN_get_flags(bn, NUM2INT(arg))); +} - if (!NIL_P(vchecks)) { - checks = NUM2INT(vchecks); - } +/* + * call-seq: + * bn.set_flags(flags) => nil + * + * Enables the flags on the BN object. + * Currently, the flags argument can contain zero of OpenSSL::BN::CONSTTIME. + */ +static VALUE +ossl_bn_set_flags(VALUE self, VALUE arg) +{ + BIGNUM *bn; GetBN(self, bn); - /* handle true/false */ - if (vtrivdiv == Qfalse) { - do_trial_division = 0; - } - switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) { - case 1: - return Qtrue; - case 0: - return Qfalse; - default: - ossl_raise(eBNError, NULL); - } - /* not reachable */ + + BN_set_flags(bn, NUM2INT(arg)); return Qnil; } @@ -1089,9 +1196,11 @@ Init_ossl_bn(void) eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); #endif - if (!(ossl_bn_ctx = BN_CTX_new())) { - ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); - } +#ifdef HAVE_RB_EXT_RACTOR_SAFE + ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type); +#else + ossl_bn_ctx_get(); +#endif eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); @@ -1111,6 +1220,7 @@ Init_ossl_bn(void) rb_define_method(cBN, "+@", ossl_bn_uplus, 0); rb_define_method(cBN, "-@", ossl_bn_uminus, 0); + rb_define_method(cBN, "abs", ossl_bn_abs, 0); rb_define_method(cBN, "+", ossl_bn_add, 1); rb_define_method(cBN, "-", ossl_bn_sub, 1); @@ -1154,9 +1264,9 @@ Init_ossl_bn(void) * get_word */ rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); - rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); - rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); + rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand"); + rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range"); rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); @@ -1173,6 +1283,23 @@ Init_ossl_bn(void) /* lshift1 - DON'T IMPL. */ /* rshift1 - DON'T IMPL. */ + rb_define_method(cBN, "get_flags", ossl_bn_get_flags, 1); + rb_define_method(cBN, "set_flags", ossl_bn_set_flags, 1); + +#ifdef BN_FLG_CONSTTIME + rb_define_const(cBN, "CONSTTIME", INT2NUM(BN_FLG_CONSTTIME)); +#endif + /* BN_FLG_MALLOCED and BN_FLG_STATIC_DATA seems for C programming. + * Allowing them leads to memory leak. + * So, for now, they are not exported +#ifdef BN_FLG_MALLOCED + rb_define_const(cBN, "MALLOCED", INT2NUM(BN_FLG_MALLOCED)); +#endif +#ifdef BN_FLG_STATIC_DATA + rb_define_const(cBN, "STATIC_DATA", INT2NUM(BN_FLG_STATIC_DATA)); +#endif + */ + /* * bn2bin * bin2bn diff --git a/ruby/ext/openssl/ossl_bn.h b/ruby/ext/openssl/ossl_bn.h index a19ba1948..1cc041fc2 100644 --- a/ruby/ext/openssl/ossl_bn.h +++ b/ruby/ext/openssl/ossl_bn.h @@ -13,7 +13,8 @@ extern VALUE cBN; extern VALUE eBNError; -extern BN_CTX *ossl_bn_ctx; +BN_CTX *ossl_bn_ctx_get(void); +#define ossl_bn_ctx ossl_bn_ctx_get() #define GetBNPtr(obj) ossl_bn_value_ptr(&(obj)) diff --git a/ruby/ext/openssl/ossl_cipher.c b/ruby/ext/openssl/ossl_cipher.c index 0840c84a7..d9c789143 100644 --- a/ruby/ext/openssl/ossl_cipher.c +++ b/ruby/ext/openssl/ossl_cipher.c @@ -104,7 +104,7 @@ ossl_cipher_alloc(VALUE klass) * call-seq: * Cipher.new(string) -> cipher * - * The string must be a valid cipher name like "AES-128-CBC" or "3DES". + * The string must contain a valid cipher name like "aes-256-cbc". * * A list of cipher names is available by calling OpenSSL::Cipher.ciphers. */ @@ -149,11 +149,11 @@ ossl_cipher_copy(VALUE self, VALUE other) return self; } -static void* -add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary) +static void +add_cipher_name_to_ary(const OBJ_NAME *name, void *arg) { + VALUE ary = (VALUE)arg; rb_ary_push(ary, rb_str_new2(name->name)); - return NULL; } /* @@ -169,7 +169,7 @@ ossl_s_ciphers(VALUE self) ary = rb_ary_new(); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, - (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary, + add_cipher_name_to_ary, (void*)ary); return ary; @@ -237,8 +237,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) ossl_raise(eCipherError, NULL); } - if (p_key) - rb_ivar_set(self, id_key_set, Qtrue); + rb_ivar_set(self, id_key_set, p_key ? Qtrue : Qfalse); return self; } @@ -814,6 +813,31 @@ ossl_cipher_block_size(VALUE self) return INT2NUM(EVP_CIPHER_CTX_block_size(ctx)); } +/* + * call-seq: + * cipher.ccm_data_len = integer -> integer + * + * Sets the length of the plaintext / ciphertext message that will be + * processed in CCM mode. Make sure to call this method after #key= and + * #iv= have been set, and before #auth_data=. + * + * Only call this method after calling Cipher#encrypt or Cipher#decrypt. + */ +static VALUE +ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len) +{ + int in_len, out_len; + EVP_CIPHER_CTX *ctx; + + in_len = NUM2INT(data_len); + + GetCipher(self, ctx); + if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1) + ossl_raise(eCipherError, NULL); + + return data_len; +} + /* * INIT */ @@ -850,23 +874,7 @@ Init_ossl_cipher(void) * individual components name, key length and mode. Either all uppercase * or all lowercase strings may be used, for example: * - * cipher = OpenSSL::Cipher.new('AES-128-CBC') - * - * For each algorithm supported, there is a class defined under the - * Cipher class that goes by the name of the cipher, e.g. to obtain an - * instance of AES, you could also use - * - * # these are equivalent - * cipher = OpenSSL::Cipher::AES.new(128, :CBC) - * cipher = OpenSSL::Cipher::AES.new(128, 'CBC') - * cipher = OpenSSL::Cipher::AES.new('128-CBC') - * - * Finally, due to its wide-spread use, there are also extra classes - * defined for the different key sizes of AES - * - * cipher = OpenSSL::Cipher::AES128.new(:CBC) - * cipher = OpenSSL::Cipher::AES192.new(:CBC) - * cipher = OpenSSL::Cipher::AES256.new(:CBC) + * cipher = OpenSSL::Cipher.new('aes-128-cbc') * * === Choosing either encryption or decryption mode * @@ -896,7 +904,7 @@ Init_ossl_cipher(void) * without processing the password further. A simple and secure way to * create a key for a particular Cipher is * - * cipher = OpenSSL::AES256.new(:CFB) + * cipher = OpenSSL::Cipher.new('aes-256-cfb') * cipher.encrypt * key = cipher.random_key # also sets the generated key on the Cipher * @@ -964,14 +972,14 @@ Init_ossl_cipher(void) * * data = "Very, very confidential data" * - * cipher = OpenSSL::Cipher::AES.new(128, :CBC) + * cipher = OpenSSL::Cipher.new('aes-128-cbc') * cipher.encrypt * key = cipher.random_key * iv = cipher.random_iv * * encrypted = cipher.update(data) + cipher.final * ... - * decipher = OpenSSL::Cipher::AES.new(128, :CBC) + * decipher = OpenSSL::Cipher.new('aes-128-cbc') * decipher.decrypt * decipher.key = key * decipher.iv = iv @@ -1007,7 +1015,7 @@ Init_ossl_cipher(void) * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the * security guarantees of GCM mode. * - * cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt + * cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt * cipher.key = key * cipher.iv = nonce * cipher.auth_data = auth_data @@ -1023,7 +1031,7 @@ Init_ossl_cipher(void) * ciphertext with a probability of 1/256. * * raise "tag is truncated!" unless tag.bytesize == 16 - * decipher = OpenSSL::Cipher::AES.new(128, :GCM).decrypt + * decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt * decipher.key = key * decipher.iv = nonce * decipher.auth_tag = tag @@ -1060,6 +1068,7 @@ Init_ossl_cipher(void) rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); + rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1); id_auth_tag_len = rb_intern_const("auth_tag_len"); id_key_set = rb_intern_const("key_set"); diff --git a/ruby/ext/openssl/ossl_config.c b/ruby/ext/openssl/ossl_config.c index 28392e208..0bac02748 100644 --- a/ruby/ext/openssl/ossl_config.c +++ b/ruby/ext/openssl/ossl_config.c @@ -9,81 +9,452 @@ */ #include "ossl.h" +static VALUE cConfig, eConfigError; + +static void +nconf_free(void *conf) +{ + NCONF_free(conf); +} + +static const rb_data_type_t ossl_config_type = { + "OpenSSL/CONF", + { + 0, nconf_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + +CONF * +GetConfig(VALUE obj) +{ + CONF *conf; + + TypedData_Get_Struct(obj, CONF, &ossl_config_type, conf); + if (!conf) + rb_raise(rb_eRuntimeError, "CONF is not initialized"); + return conf; +} + +static VALUE +config_s_alloc(VALUE klass) +{ + VALUE obj; + CONF *conf; + + obj = TypedData_Wrap_Struct(klass, &ossl_config_type, 0); + conf = NCONF_new(NULL); + if (!conf) + ossl_raise(eConfigError, "NCONF_new"); + RTYPEDDATA_DATA(obj) = conf; + return obj; +} + +static void +config_load_bio(CONF *conf, BIO *bio) +{ + long eline = -1; + + if (!NCONF_load_bio(conf, bio, &eline)) { + BIO_free(bio); + if (eline <= 0) + ossl_raise(eConfigError, "wrong config format"); + else + ossl_raise(eConfigError, "error in line %ld", eline); + } + BIO_free(bio); + + /* + * Clear the error queue even if it is parsed successfully. + * Particularly, when the .include directive refers to a non-existent file, + * it is only reported in the error queue. + */ + ossl_clear_error(); +} /* - * Classes - */ -VALUE cConfig; -/* Document-class: OpenSSL::ConfigError + * call-seq: + * Config.parse(string) -> OpenSSL::Config * - * General error for openssl library configuration files. Including formatting, - * parsing errors, etc. + * Parses a given _string_ as a blob that contains configuration for OpenSSL. */ -VALUE eConfigError; +static VALUE +config_s_parse(VALUE klass, VALUE str) +{ + VALUE obj = config_s_alloc(klass); + CONF *conf = GetConfig(obj); + BIO *bio; + + bio = ossl_obj2bio(&str); + config_load_bio(conf, bio); /* Consumes BIO */ + return obj; +} + +static VALUE config_get_sections(VALUE self); +static VALUE config_get_section(VALUE self, VALUE section); /* - * Public + * call-seq: + * Config.parse_config(io) -> hash + * + * Parses the configuration data read from _io_ and returns the whole content + * as a Hash. */ +static VALUE +config_s_parse_config(VALUE klass, VALUE io) +{ + VALUE obj, sections, ret; + long i; + + obj = config_s_parse(klass, io); + sections = config_get_sections(obj); + ret = rb_hash_new(); + for (i = 0; i < RARRAY_LEN(sections); i++) { + VALUE section = rb_ary_entry(sections, i); + rb_hash_aset(ret, section, config_get_section(obj, section)); + } + return ret; +} /* - * DupConfigPtr is a public C-level function for getting OpenSSL CONF struct - * from an OpenSSL::Config(eConfig) instance. We decided to implement - * OpenSSL::Config in Ruby level but we need to pass native CONF struct for - * some OpenSSL features such as X509V3_EXT_*. + * call-seq: + * Config.new(filename) -> OpenSSL::Config + * + * Creates an instance of OpenSSL::Config from the content of the file + * specified by _filename_. + * + * This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= + * + * This can raise IO exceptions based on the access, or availability of the + * file. A ConfigError exception may be raised depending on the validity of + * the data being configured. */ -CONF * -DupConfigPtr(VALUE obj) +static VALUE +config_initialize(int argc, VALUE *argv, VALUE self) { - CONF *conf; + CONF *conf = GetConfig(self); + VALUE filename; + + /* 0-arguments call has no use-case, but is kept for compatibility */ + rb_scan_args(argc, argv, "01", &filename); + rb_check_frozen(self); + if (!NIL_P(filename)) { + BIO *bio = BIO_new_file(StringValueCStr(filename), "rb"); + if (!bio) + ossl_raise(eConfigError, "BIO_new_file"); + config_load_bio(conf, bio); /* Consumes BIO */ + } + return self; +} + +static VALUE +config_initialize_copy(VALUE self, VALUE other) +{ + CONF *conf = GetConfig(self); VALUE str; BIO *bio; - long eline = -1; - OSSL_Check_Kind(obj, cConfig); - str = rb_funcall(obj, rb_intern("to_s"), 0); + str = rb_funcall(other, rb_intern("to_s"), 0); + rb_check_frozen(self); bio = ossl_obj2bio(&str); - conf = NCONF_new(NULL); - if(!conf){ - BIO_free(bio); - ossl_raise(eConfigError, NULL); + config_load_bio(conf, bio); /* Consumes BIO */ + return self; +} + +/* + * call-seq: + * config.get_value(section, key) -> string + * + * Gets the value of _key_ from the given _section_. + * + * Given the following configurating file being loaded: + * + * config = OpenSSL::Config.load('foo.cnf') + * #=> # + * puts config.to_s + * #=> [ default ] + * # foo=bar + * + * You can get a specific value from the config if you know the _section_ + * and _key_ like so: + * + * config.get_value('default','foo') + * #=> "bar" + */ +static VALUE +config_get_value(VALUE self, VALUE section, VALUE key) +{ + CONF *conf = GetConfig(self); + const char *str, *sectionp; + + StringValueCStr(section); + StringValueCStr(key); + /* For compatibility; NULL means "default". */ + sectionp = RSTRING_LEN(section) ? RSTRING_PTR(section) : NULL; + str = NCONF_get_string(conf, sectionp, RSTRING_PTR(key)); + if (!str) { + ossl_clear_error(); + return Qnil; + } + return rb_str_new_cstr(str); +} + +/* + * call-seq: + * config[section] -> hash + * + * Gets all key-value pairs in a specific _section_ from the current + * configuration. + * + * Given the following configurating file being loaded: + * + * config = OpenSSL::Config.load('foo.cnf') + * #=> # + * puts config.to_s + * #=> [ default ] + * # foo=bar + * + * You can get a hash of the specific section like so: + * + * config['default'] + * #=> {"foo"=>"bar"} + * + */ +static VALUE +config_get_section(VALUE self, VALUE section) +{ + CONF *conf = GetConfig(self); + STACK_OF(CONF_VALUE) *sk; + int i, entries; + VALUE hash; + + hash = rb_hash_new(); + StringValueCStr(section); + if (!(sk = NCONF_get_section(conf, RSTRING_PTR(section)))) { + ossl_clear_error(); + return hash; } - if(!NCONF_load_bio(conf, bio, &eline)){ - BIO_free(bio); - NCONF_free(conf); - if (eline <= 0) - ossl_raise(eConfigError, "wrong config format"); - else - ossl_raise(eConfigError, "error in line %d", eline); + entries = sk_CONF_VALUE_num(sk); + for (i = 0; i < entries; i++) { + CONF_VALUE *entry = sk_CONF_VALUE_value(sk, i); + rb_hash_aset(hash, rb_str_new_cstr(entry->name), + rb_str_new_cstr(entry->value)); } - BIO_free(bio); + return hash; +} - return conf; +static void +get_conf_section_doall_arg(CONF_VALUE *cv, VALUE *aryp) +{ + if (cv->name) + return; + rb_ary_push(*aryp, rb_str_new_cstr(cv->section)); } -/* Document-const: DEFAULT_CONFIG_FILE +/* IMPLEMENT_LHASH_DOALL_ARG_CONST() requires >= OpenSSL 1.1.0 */ +static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE, VALUE) + +/* + * call-seq: + * config.sections -> array of string * - * The default system configuration file for openssl + * Get the names of all sections in the current configuration. */ +static VALUE +config_get_sections(VALUE self) +{ + CONF *conf = GetConfig(self); + VALUE ary; + + ary = rb_ary_new(); + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(get_conf_section), + &ary); + return ary; +} + +static void +dump_conf_value_doall_arg(CONF_VALUE *cv, VALUE *strp) +{ + VALUE str = *strp; + STACK_OF(CONF_VALUE) *sk; + int i, num; + + if (cv->name) + return; + sk = (STACK_OF(CONF_VALUE) *)cv->value; + num = sk_CONF_VALUE_num(sk); + rb_str_cat_cstr(str, "[ "); + rb_str_cat_cstr(str, cv->section); + rb_str_cat_cstr(str, " ]\n"); + for (i = 0; i < num; i++){ + CONF_VALUE *v = sk_CONF_VALUE_value(sk, i); + rb_str_cat_cstr(str, v->name ? v->name : "None"); + rb_str_cat_cstr(str, "="); + rb_str_cat_cstr(str, v->value ? v->value : "None"); + rb_str_cat_cstr(str, "\n"); + } + rb_str_cat_cstr(str, "\n"); +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE) /* - * INIT + * call-seq: + * config.to_s -> string + * + * + * Gets the parsable form of the current configuration. + * + * Given the following configuration being created: + * + * config = OpenSSL::Config.new + * #=> # + * config['default'] = {"foo"=>"bar","baz"=>"buz"} + * #=> {"foo"=>"bar", "baz"=>"buz"} + * puts config.to_s + * #=> [ default ] + * # foo=bar + * # baz=buz + * + * You can parse get the serialized configuration using #to_s and then parse + * it later: + * + * serialized_config = config.to_s + * # much later... + * new_config = OpenSSL::Config.parse(serialized_config) + * #=> # + * puts new_config + * #=> [ default ] + * foo=bar + * baz=buz */ +static VALUE +config_to_s(VALUE self) +{ + CONF *conf = GetConfig(self); + VALUE str; + + str = rb_str_new(NULL, 0); + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), + &str); + return str; +} + +static void +each_conf_value_doall_arg(CONF_VALUE *cv, void *unused) +{ + STACK_OF(CONF_VALUE) *sk; + VALUE section; + int i, num; + + if (cv->name) + return; + sk = (STACK_OF(CONF_VALUE) *)cv->value; + num = sk_CONF_VALUE_num(sk); + section = rb_str_new_cstr(cv->section); + for (i = 0; i < num; i++){ + CONF_VALUE *v = sk_CONF_VALUE_value(sk, i); + VALUE name = v->name ? rb_str_new_cstr(v->name) : Qnil; + VALUE value = v->value ? rb_str_new_cstr(v->value) : Qnil; + rb_yield(rb_ary_new3(3, section, name, value)); + } +} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE, void) + +/* + * call-seq: + * config.each { |section, key, value| } + * + * Retrieves the section and its pairs for the current configuration. + * + * config.each do |section, key, value| + * # ... + * end + */ +static VALUE +config_each(VALUE self) +{ + CONF *conf = GetConfig(self); + + RETURN_ENUMERATOR(self, 0, 0); + + lh_doall_arg((_LHASH *)conf->data, LHASH_DOALL_ARG_FN(each_conf_value), + NULL); + return self; +} + +/* + * call-seq: + * config.inspect -> string + * + * String representation of this configuration object, including the class + * name and its sections. + */ +static VALUE +config_inspect(VALUE self) +{ + VALUE str, ary = config_get_sections(self); + const char *cname = rb_class2name(rb_obj_class(self)); + + str = rb_str_new_cstr("#<"); + rb_str_cat_cstr(str, cname); + rb_str_cat_cstr(str, " sections="); + rb_str_append(str, rb_inspect(ary)); + rb_str_cat_cstr(str, ">"); + + return str; +} + void Init_ossl_config(void) { - char *default_config_file; + char *path; + VALUE path_str; #if 0 mOSSL = rb_define_module("OpenSSL"); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); #endif - eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); + /* Document-class: OpenSSL::Config + * + * Configuration for the openssl library. + * + * Many system's installation of openssl library will depend on your system + * configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for + * the location of the file for your host. + * + * See also http://www.openssl.org/docs/apps/config.html + */ cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); - default_config_file = CONF_get1_default_config_file(); - rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", - rb_str_new2(default_config_file)); - OPENSSL_free(default_config_file); - /* methods are defined by openssl/config.rb */ + /* Document-class: OpenSSL::ConfigError + * + * General error for openssl library configuration files. Including formatting, + * parsing errors, etc. + */ + eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError); + + rb_include_module(cConfig, rb_mEnumerable); + rb_define_singleton_method(cConfig, "parse", config_s_parse, 1); + rb_define_singleton_method(cConfig, "parse_config", config_s_parse_config, 1); + rb_define_alias(CLASS_OF(cConfig), "load", "new"); + rb_define_alloc_func(cConfig, config_s_alloc); + rb_define_method(cConfig, "initialize", config_initialize, -1); + rb_define_method(cConfig, "initialize_copy", config_initialize_copy, 1); + rb_define_method(cConfig, "get_value", config_get_value, 2); + rb_define_method(cConfig, "[]", config_get_section, 1); + rb_define_method(cConfig, "sections", config_get_sections, 0); + rb_define_method(cConfig, "to_s", config_to_s, 0); + rb_define_method(cConfig, "each", config_each, 0); + rb_define_method(cConfig, "inspect", config_inspect, 0); + + /* Document-const: DEFAULT_CONFIG_FILE + * + * The default system configuration file for OpenSSL. + */ + path = CONF_get1_default_config_file(); + path_str = ossl_buf2str(path, rb_long2int(strlen(path))); + rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str); } diff --git a/ruby/ext/openssl/ossl_config.h b/ruby/ext/openssl/ossl_config.h index 627d297ba..4e604f1ae 100644 --- a/ruby/ext/openssl/ossl_config.h +++ b/ruby/ext/openssl/ossl_config.h @@ -7,13 +7,10 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(_OSSL_CONFIG_H_) -#define _OSSL_CONFIG_H_ +#ifndef OSSL_CONFIG_H +#define OSSL_CONFIG_H -extern VALUE cConfig; -extern VALUE eConfigError; - -CONF* DupConfigPtr(VALUE obj); +CONF *GetConfig(VALUE obj); void Init_ossl_config(void); -#endif /* _OSSL_CONFIG_H_ */ +#endif /* OSSL_CONFIG_H */ diff --git a/ruby/ext/openssl/ossl_digest.c b/ruby/ext/openssl/ossl_digest.c index 112ce3364..fc326ec14 100644 --- a/ruby/ext/openssl/ossl_digest.c +++ b/ruby/ext/openssl/ossl_digest.c @@ -63,7 +63,7 @@ ossl_evp_get_digestbyname(VALUE obj) GetDigest(obj, ctx); - md = EVP_MD_CTX_md(ctx); + md = EVP_MD_CTX_get0_md(ctx); } return md; @@ -176,7 +176,7 @@ ossl_digest_reset(VALUE self) EVP_MD_CTX *ctx; GetDigest(self, ctx); - if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) { + if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) { ossl_raise(eDigestError, "Digest initialization failed."); } @@ -192,7 +192,7 @@ ossl_digest_reset(VALUE self) * be passed individually to the Digest instance. * * === Example - * digest = OpenSSL::Digest::SHA256.new + * digest = OpenSSL::Digest.new('SHA256') * digest.update('First input') * digest << 'Second input' # equivalent to digest.update('Second input') * result = digest.digest @@ -248,7 +248,7 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self) * Returns the sn of this Digest algorithm. * * === Example - * digest = OpenSSL::Digest::SHA512.new + * digest = OpenSSL::Digest.new('SHA512') * puts digest.name # => SHA512 * */ @@ -259,7 +259,7 @@ ossl_digest_name(VALUE self) GetDigest(self, ctx); - return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); + return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx))); } /* @@ -270,7 +270,7 @@ ossl_digest_name(VALUE self) * final message digest result. * * === Example - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * puts digest.digest_length # => 20 * */ @@ -294,7 +294,7 @@ ossl_digest_size(VALUE self) * consecutively. * * === Example - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * puts digest.block_length # => 64 */ static VALUE @@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self) void Init_ossl_digest(void) { - rb_require("digest"); - #if 0 mOSSL = rb_define_module("OpenSSL"); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); @@ -348,54 +346,19 @@ Init_ossl_digest(void) * the integrity of a signed document, it suffices to re-compute the hash * and verify that it is equal to that in the signature. * - * Among the supported message digest algorithms are: - * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512 - * * MD2, MD4, MDC2 and MD5 - * * RIPEMD160 - * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is - * equal to SHA and DSS1 is equal to SHA1) + * You can get a list of all digest algorithms supported on your system by + * running this command in your terminal: * - * For each of these algorithms, there is a sub-class of Digest that - * can be instantiated as simply as e.g. + * openssl list -digest-algorithms * - * digest = OpenSSL::Digest::SHA1.new + * Among the OpenSSL 1.1.1 supported message digest algorithms are: + * * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256 + * * SHA3-224, SHA3-256, SHA3-384 and SHA3-512 + * * BLAKE2s256 and BLAKE2b512 * - * === Mapping between Digest class and sn/ln + * Each of these algorithms can be instantiated using the name: * - * The sn (short names) and ln (long names) are defined in - * and . They are textual - * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest - * algorithm has an OBJECT IDENTIFIER associated to it and those again - * have short/long names assigned to them. - * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its - * sn is "SHA1" and its ln is "sha1". - * ==== MD2 - * * sn: MD2 - * * ln: md2 - * ==== MD4 - * * sn: MD4 - * * ln: md4 - * ==== MD5 - * * sn: MD5 - * * ln: md5 - * ==== SHA - * * sn: SHA - * * ln: SHA - * ==== SHA-1 - * * sn: SHA1 - * * ln: sha1 - * ==== SHA-224 - * * sn: SHA224 - * * ln: sha224 - * ==== SHA-256 - * * sn: SHA256 - * * ln: sha256 - * ==== SHA-384 - * * sn: SHA384 - * * ln: sha384 - * ==== SHA-512 - * * sn: SHA512 - * * ln: sha512 + * digest = OpenSSL::Digest.new('SHA256') * * "Breaking" a message digest algorithm means defying its one-way * function characteristics, i.e. producing a collision or finding a way @@ -407,16 +370,16 @@ Init_ossl_digest(void) * * === Hashing a file * - * data = File.read('document') - * sha256 = OpenSSL::Digest::SHA256.new + * data = File.binread('document') + * sha256 = OpenSSL::Digest.new('SHA256') * digest = sha256.digest(data) * * === Hashing several pieces of data at once * - * data1 = File.read('file1') - * data2 = File.read('file2') - * data3 = File.read('file3') - * sha256 = OpenSSL::Digest::SHA256.new + * data1 = File.binread('file1') + * data2 = File.binread('file2') + * data3 = File.binread('file3') + * sha256 = OpenSSL::Digest.new('SHA256') * sha256 << data1 * sha256 << data2 * sha256 << data3 @@ -424,15 +387,21 @@ Init_ossl_digest(void) * * === Reuse a Digest instance * - * data1 = File.read('file1') - * sha256 = OpenSSL::Digest::SHA256.new + * data1 = File.binread('file1') + * sha256 = OpenSSL::Digest.new('SHA256') * digest1 = sha256.digest(data1) * - * data2 = File.read('file2') + * data2 = File.binread('file2') * sha256.reset * digest2 = sha256.digest(data2) * */ + + /* + * Digest::Class is defined by the digest library. rb_require() cannot be + * used here because it bypasses RubyGems. + */ + rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest")); cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class")); /* Document-class: OpenSSL::Digest::DigestError * diff --git a/ruby/ext/openssl/ossl_engine.c b/ruby/ext/openssl/ossl_engine.c index 5ca0d4ca3..1abde7f76 100644 --- a/ruby/ext/openssl/ossl_engine.c +++ b/ruby/ext/openssl/ossl_engine.c @@ -9,7 +9,8 @@ */ #include "ossl.h" -#if !defined(OPENSSL_NO_ENGINE) +#ifdef OSSL_USE_ENGINE +# include #define NewEngine(klass) \ TypedData_Wrap_Struct((klass), &ossl_engine_type, 0) @@ -93,9 +94,6 @@ static const rb_data_type_t ossl_engine_type = { static VALUE ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) { -#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES) - return Qnil; -#else VALUE name; rb_scan_args(argc, argv, "01", &name); @@ -104,60 +102,53 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) return Qtrue; } StringValueCStr(name); -#ifndef OPENSSL_NO_STATIC_ENGINE -#if HAVE_ENGINE_LOAD_DYNAMIC +#ifdef HAVE_ENGINE_LOAD_DYNAMIC OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC); #endif -#if HAVE_ENGINE_LOAD_4758CCA +#ifndef OPENSSL_NO_STATIC_ENGINE +#ifdef HAVE_ENGINE_LOAD_4758CCA OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA); #endif -#if HAVE_ENGINE_LOAD_AEP +#ifdef HAVE_ENGINE_LOAD_AEP OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP); #endif -#if HAVE_ENGINE_LOAD_ATALLA +#ifdef HAVE_ENGINE_LOAD_ATALLA OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA); #endif -#if HAVE_ENGINE_LOAD_CHIL +#ifdef HAVE_ENGINE_LOAD_CHIL OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL); #endif -#if HAVE_ENGINE_LOAD_CSWIFT +#ifdef HAVE_ENGINE_LOAD_CSWIFT OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT); #endif -#if HAVE_ENGINE_LOAD_NURON +#ifdef HAVE_ENGINE_LOAD_NURON OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON); #endif -#if HAVE_ENGINE_LOAD_SUREWARE +#ifdef HAVE_ENGINE_LOAD_SUREWARE OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE); #endif -#if HAVE_ENGINE_LOAD_UBSEC +#ifdef HAVE_ENGINE_LOAD_UBSEC OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC); #endif -#if HAVE_ENGINE_LOAD_PADLOCK +#ifdef HAVE_ENGINE_LOAD_PADLOCK OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK); #endif -#if HAVE_ENGINE_LOAD_CAPI +#ifdef HAVE_ENGINE_LOAD_CAPI OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI); #endif -#if HAVE_ENGINE_LOAD_GMP +#ifdef HAVE_ENGINE_LOAD_GMP OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP); #endif -#if HAVE_ENGINE_LOAD_GOST +#ifdef HAVE_ENGINE_LOAD_GOST OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST); #endif -#if HAVE_ENGINE_LOAD_CRYPTODEV - OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV); -#endif -#if HAVE_ENGINE_LOAD_AESNI - OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI); #endif -#endif -#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO - OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto, OPENBSD_DEV_CRYPTO); +#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; -#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ } /* diff --git a/ruby/ext/openssl/ossl_hmac.c b/ruby/ext/openssl/ossl_hmac.c index 564dcab52..bfe3a74b1 100644 --- a/ruby/ext/openssl/ossl_hmac.c +++ b/ruby/ext/openssl/ossl_hmac.c @@ -7,14 +7,12 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(OPENSSL_NO_HMAC) - #include "ossl.h" #define NewHMAC(klass) \ TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0) #define GetHMAC(obj, ctx) do { \ - TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \ + TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \ if (!(ctx)) { \ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ } \ @@ -36,7 +34,7 @@ VALUE eHMACError; static void ossl_hmac_free(void *ctx) { - HMAC_CTX_free(ctx); + EVP_MD_CTX_free(ctx); } static const rb_data_type_t ossl_hmac_type = { @@ -51,12 +49,12 @@ static VALUE ossl_hmac_alloc(VALUE klass) { VALUE obj; - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; obj = NewHMAC(klass); - ctx = HMAC_CTX_new(); + ctx = EVP_MD_CTX_new(); if (!ctx) - ossl_raise(eHMACError, NULL); + ossl_raise(eHMACError, "EVP_MD_CTX"); RTYPEDDATA_DATA(obj) = ctx; return obj; @@ -76,37 +74,41 @@ ossl_hmac_alloc(VALUE klass) * === Example * * key = 'key' - * digest = OpenSSL::Digest.new('sha1') - * instance = OpenSSL::HMAC.new(key, digest) + * instance = OpenSSL::HMAC.new(key, 'SHA1') * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance.class * #=> OpenSSL::HMAC * * === A note about comparisons * - * Two instances won't be equal when they're compared, even if they have the - * same value. Use #to_s or #hexdigest to return the authentication code that - * the instance represents. For example: + * Two instances can be securely compared with #== in constant time: * - * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance - * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f - * instance == other_instance - * #=> false - * instance.to_s == other_instance.to_s - * #=> true + * other_instance = OpenSSL::HMAC.new('key', 'SHA1') + * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f + * instance == other_instance + * #=> true * */ static VALUE ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; + EVP_PKEY *pkey; - StringValue(key); GetHMAC(self, ctx); - HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), - ossl_evp_get_digestbyname(digest), NULL); + StringValue(key); + 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"); + if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest), + NULL, pkey) != 1) { + EVP_PKEY_free(pkey); + ossl_raise(eHMACError, "EVP_DigestSignInit"); + } + /* Decrement reference counter; EVP_MD_CTX still keeps it */ + EVP_PKEY_free(pkey); return self; } @@ -114,16 +116,15 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) static VALUE ossl_hmac_copy(VALUE self, VALUE other) { - HMAC_CTX *ctx1, *ctx2; + EVP_MD_CTX *ctx1, *ctx2; rb_check_frozen(self); if (self == other) return self; GetHMAC(self, ctx1); GetHMAC(other, ctx2); - - if (!HMAC_CTX_copy(ctx1, ctx2)) - ossl_raise(eHMACError, "HMAC_CTX_copy"); + if (EVP_MD_CTX_copy(ctx1, ctx2) != 1) + ossl_raise(eHMACError, "EVP_MD_CTX_copy"); return self; } @@ -148,33 +149,16 @@ ossl_hmac_copy(VALUE self, VALUE other) static VALUE ossl_hmac_update(VALUE self, VALUE data) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; StringValue(data); GetHMAC(self, ctx); - HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)); + if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) + ossl_raise(eHMACError, "EVP_DigestSignUpdate"); return self; } -static void -hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len) -{ - HMAC_CTX *final; - - final = HMAC_CTX_new(); - if (!final) - ossl_raise(eHMACError, "HMAC_CTX_new"); - - if (!HMAC_CTX_copy(final, ctx)) { - HMAC_CTX_free(final); - ossl_raise(eHMACError, "HMAC_CTX_copy"); - } - - HMAC_Final(final, buf, buf_len); - HMAC_CTX_free(final); -} - /* * call-seq: * hmac.digest -> string @@ -182,7 +166,7 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len) * Returns the authentication code an instance represents as a binary string. * * === Example - * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) + * instance = OpenSSL::HMAC.new('key', 'SHA1') * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance.digest * #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?" @@ -190,15 +174,16 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len) static VALUE ossl_hmac_digest(VALUE self) { - HMAC_CTX *ctx; - unsigned int buf_len; + EVP_MD_CTX *ctx; + size_t buf_len = EVP_MAX_MD_SIZE; VALUE ret; GetHMAC(self, ctx); ret = rb_str_new(NULL, EVP_MAX_MD_SIZE); - hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len); - assert(buf_len <= EVP_MAX_MD_SIZE); - rb_str_set_len(ret, buf_len); + if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret), + &buf_len) != 1) + ossl_raise(eHMACError, "EVP_DigestSignFinal"); + rb_str_set_len(ret, (long)buf_len); return ret; } @@ -213,13 +198,14 @@ ossl_hmac_digest(VALUE self) static VALUE ossl_hmac_hexdigest(VALUE self) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; unsigned char buf[EVP_MAX_MD_SIZE]; - unsigned int buf_len; + size_t buf_len = EVP_MAX_MD_SIZE; VALUE ret; GetHMAC(self, ctx); - hmac_final(ctx, buf, &buf_len); + if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1) + ossl_raise(eHMACError, "EVP_DigestSignFinal"); ret = rb_str_new(NULL, buf_len * 2); ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len); @@ -236,7 +222,7 @@ ossl_hmac_hexdigest(VALUE self) * === Example * * data = "The quick brown fox jumps over the lazy dog" - * instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) + * instance = OpenSSL::HMAC.new('key', 'SHA1') * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * * instance.update(data) @@ -248,84 +234,17 @@ ossl_hmac_hexdigest(VALUE self) static VALUE ossl_hmac_reset(VALUE self) { - HMAC_CTX *ctx; + EVP_MD_CTX *ctx; + EVP_PKEY *pkey; GetHMAC(self, ctx); - HMAC_Init_ex(ctx, NULL, 0, NULL, NULL); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); + if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1) + ossl_raise(eHMACError, "EVP_DigestSignInit"); return self; } -/* - * call-seq: - * HMAC.digest(digest, key, data) -> aString - * - * Returns the authentication code as a binary string. The _digest_ parameter - * specifies the digest algorithm to use. This may be a String representing - * the algorithm name or an instance of OpenSSL::Digest. - * - * === Example - * - * key = 'key' - * data = 'The quick brown fox jumps over the lazy dog' - * - * hmac = OpenSSL::HMAC.digest('sha1', key, data) - * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" - * - */ -static VALUE -ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data) -{ - unsigned char *buf; - unsigned int buf_len; - - StringValue(key); - StringValue(data); - buf = HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key), - RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data), - RSTRING_LEN(data), NULL, &buf_len); - - return rb_str_new((const char *)buf, buf_len); -} - -/* - * call-seq: - * HMAC.hexdigest(digest, key, data) -> aString - * - * Returns the authentication code as a hex-encoded string. The _digest_ - * parameter specifies the digest algorithm to use. This may be a String - * representing the algorithm name or an instance of OpenSSL::Digest. - * - * === Example - * - * key = 'key' - * data = 'The quick brown fox jumps over the lazy dog' - * - * hmac = OpenSSL::HMAC.hexdigest('sha1', key, data) - * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" - * - */ -static VALUE -ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data) -{ - unsigned char buf[EVP_MAX_MD_SIZE]; - unsigned int buf_len; - VALUE ret; - - StringValue(key); - StringValue(data); - - if (!HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key), - RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data), - RSTRING_LEN(data), buf, &buf_len)) - ossl_raise(eHMACError, "HMAC"); - - ret = rb_str_new(NULL, buf_len * 2); - ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len); - - return ret; -} - /* * INIT */ @@ -356,11 +275,10 @@ Init_ossl_hmac(void) * * === HMAC-SHA256 using incremental interface * - * data1 = File.read("file1") - * data2 = File.read("file2") + * data1 = File.binread("file1") + * data2 = File.binread("file2") * key = "key" - * digest = OpenSSL::Digest::SHA256.new - * hmac = OpenSSL::HMAC.new(key, digest) + * hmac = OpenSSL::HMAC.new(key, 'SHA256') * hmac << data1 * hmac << data2 * mac = hmac.digest @@ -370,8 +288,6 @@ Init_ossl_hmac(void) cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject); rb_define_alloc_func(cHMAC, ossl_hmac_alloc); - rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3); - rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3); rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1); @@ -384,12 +300,3 @@ Init_ossl_hmac(void) rb_define_alias(cHMAC, "inspect", "hexdigest"); rb_define_alias(cHMAC, "to_s", "hexdigest"); } - -#else /* NO_HMAC */ -# warning >>> OpenSSL is compiled without HMAC support <<< -void -Init_ossl_hmac(void) -{ - rb_warning("HMAC is not available: OpenSSL is compiled without HMAC."); -} -#endif /* NO_HMAC */ diff --git a/ruby/ext/openssl/ossl_kdf.c b/ruby/ext/openssl/ossl_kdf.c index ee124718b..7fa38b865 100644 --- a/ruby/ext/openssl/ossl_kdf.c +++ b/ruby/ext/openssl/ossl_kdf.c @@ -163,6 +163,14 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self) * HashLen is the length of the hash function output in octets. * _hash_:: * The hash function. + * + * === Example + * # The values from https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1 + * ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") + * salt = ["000102030405060708090a0b0c"].pack("H*") + * info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*") + * p OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: 42, hash: "SHA256").unpack1("H*") + * # => "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" */ static VALUE kdf_hkdf(int argc, VALUE *argv, VALUE self) @@ -272,7 +280,7 @@ Init_ossl_kdf(void) * # store this with the generated value * salt = OpenSSL::Random.random_bytes(16) * iter = 20_000 - * hash = OpenSSL::Digest::SHA256.new + * hash = OpenSSL::Digest.new('SHA256') * len = hash.digest_length * # the final value to be stored * value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, @@ -284,24 +292,8 @@ Init_ossl_kdf(void) * Typically, "==" short-circuits on evaluation, and is therefore * vulnerable to timing attacks. The proper way is to use a method that * always takes the same amount of time when comparing two values, thus - * not leaking any information to potential attackers. To compare two - * values, the following could be used: - * - * def eql_time_cmp(a, b) - * unless a.length == b.length - * return false - * end - * cmp = b.bytes - * result = 0 - * a.bytes.each_with_index {|c,i| - * result |= c ^ cmp[i] - * } - * result == 0 - * end - * - * Please note that the premature return in case of differing lengths - * typically does not leak valuable information - when using PBKDF2, the - * length of the values to be compared is of fixed size. + * not leaking any information to potential attackers. To do this, use + * +OpenSSL.fixed_length_secure_compare+. */ mKDF = rb_define_module_under(mOSSL, "KDF"); /* diff --git a/ruby/ext/openssl/ossl_ns_spki.c b/ruby/ext/openssl/ossl_ns_spki.c index 6f61e61bf..9b1147367 100644 --- a/ruby/ext/openssl/ossl_ns_spki.c +++ b/ruby/ext/openssl/ossl_ns_spki.c @@ -350,7 +350,7 @@ ossl_spki_verify(VALUE self, VALUE key) * spki = OpenSSL::Netscape::SPKI.new * spki.challenge = "RandomChallenge" * spki.public_key = key.public_key - * spki.sign(key, OpenSSL::Digest::SHA256.new) + * spki.sign(key, OpenSSL::Digest.new('SHA256')) * #send a request containing this to a server generating a certificate * === Verifying an SPKI request * request = #... diff --git a/ruby/ext/openssl/ossl_ocsp.c b/ruby/ext/openssl/ossl_ocsp.c index c0237791d..1e87484af 100644 --- a/ruby/ext/openssl/ossl_ocsp.c +++ b/ruby/ext/openssl/ossl_ocsp.c @@ -157,7 +157,7 @@ ossl_ocspcertid_new(OCSP_CERTID *cid) } /* - * OCSP::Resquest + * OCSP::Request */ static VALUE ossl_ocspreq_alloc(VALUE klass) @@ -803,7 +803,7 @@ add_status_convert_time(VALUE obj) * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. * _revocation_time_ is the time when the certificate is revoked. * - * _this_update_ and _next_update_ indicate the time at which ths status is + * _this_update_ and _next_update_ indicate the time at which the status is * verified to be correct and the time at or before which newer information * will be available, respectively. _next_update_ is optional. * @@ -1069,55 +1069,7 @@ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self) x509st = GetX509StorePtr(store); flg = NIL_P(flags) ? 0 : NUM2INT(flags); x509s = ossl_x509_ary2sk(certs); -#if (OPENSSL_VERSION_NUMBER < 0x1000202fL) || defined(LIBRESSL_VERSION_NUMBER) - /* - * OpenSSL had a bug that it doesn't use the certificates in x509s for - * verifying the chain. This can be a problem when the response is signed by - * a certificate issued by an intermediate CA. - * - * root_ca - * | - * intermediate_ca - * |-------------| - * end_entity ocsp_signer - * - * When the certificate hierarchy is like this, and the response contains - * only ocsp_signer certificate, the following code wrongly fails. - * - * store = OpenSSL::X509::Store.new; store.add_cert(root_ca) - * basic_response.verify([intermediate_ca], store) - * - * So add the certificates in x509s to the embedded certificates list first. - * - * This is fixed in OpenSSL 0.9.8zg, 1.0.0s, 1.0.1n, 1.0.2b. But it still - * exists in LibreSSL 2.1.10, 2.2.9, 2.3.6, 2.4.1. - */ - if (!(flg & (OCSP_NOCHAIN | OCSP_NOVERIFY)) && - sk_X509_num(x509s) && sk_X509_num(bs->certs)) { - int i; - - bs = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs); - if (!bs) { - sk_X509_pop_free(x509s, X509_free); - ossl_raise(eOCSPError, "ASN1_item_dup"); - } - - for (i = 0; i < sk_X509_num(x509s); i++) { - if (!OCSP_basic_add1_cert(bs, sk_X509_value(x509s, i))) { - sk_X509_pop_free(x509s, X509_free); - OCSP_BASICRESP_free(bs); - ossl_raise(eOCSPError, "OCSP_basic_add1_cert"); - } - } - result = OCSP_basic_verify(bs, x509s, x509st, flg); - OCSP_BASICRESP_free(bs); - } - else { - result = OCSP_basic_verify(bs, x509s, x509st, flg); - } -#else result = OCSP_basic_verify(bs, x509s, x509st, flg); -#endif sk_X509_pop_free(x509s, X509_free); if (result <= 0) ossl_clear_error(); @@ -1489,13 +1441,15 @@ ossl_ocspcid_initialize_copy(VALUE self, VALUE other) * call-seq: * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id * OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id + * OpenSSL::OCSP::CertificateId.new(obj) -> certificate_id * * Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and * _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used * to compute the hash values. This defaults to SHA-1. * * If only one argument is given, decodes it as DER representation of a - * certificate ID. + * certificate ID or generates certificate ID from the object that responds to + * the to_der method. */ static VALUE ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) @@ -1717,7 +1671,7 @@ Init_ossl_ocsp(void) * subject certificate so the CA knows which certificate we are asking * about: * - * digest = OpenSSL::Digest::SHA1.new + * digest = OpenSSL::Digest.new('SHA1') * certificate_id = * OpenSSL::OCSP::CertificateId.new subject, issuer, digest * @@ -1734,18 +1688,11 @@ Init_ossl_ocsp(void) * To submit the request to the CA for verification we need to extract the * OCSP URI from the subject certificate: * - * authority_info_access = subject.extensions.find do |extension| - * extension.oid == 'authorityInfoAccess' - * end - * - * descriptions = authority_info_access.value.split "\n" - * ocsp = descriptions.find do |description| - * description.start_with? 'OCSP' - * end + * ocsp_uris = subject.ocsp_uris * * require 'uri' * - * ocsp_uri = URI ocsp[/URI:(.*)/, 1] + * ocsp_uri = URI ocsp_uris[0] * * To submit the request we'll POST the request to the OCSP URI (per RFC * 2560). Note that we only handle HTTP requests and don't handle any @@ -1792,7 +1739,7 @@ Init_ossl_ocsp(void) * single_response = basic_response.find_response(certificate_id) * * unless single_response - * raise 'basic_response does not have the status for the certificiate' + * raise 'basic_response does not have the status for the certificate' * end * * Then check the validity. A status issued in the future must be rejected. diff --git a/ruby/ext/openssl/ossl_ocsp.h b/ruby/ext/openssl/ossl_ocsp.h index 21e2c99a2..6d2aac865 100644 --- a/ruby/ext/openssl/ossl_ocsp.h +++ b/ruby/ext/openssl/ossl_ocsp.h @@ -13,9 +13,9 @@ #if !defined(OPENSSL_NO_OCSP) extern VALUE mOCSP; -extern VALUE cOPCSReq; -extern VALUE cOPCSRes; -extern VALUE cOPCSBasicRes; +extern VALUE cOCSPReq; +extern VALUE cOCSPRes; +extern VALUE cOCSPBasicRes; #endif void Init_ossl_ocsp(void); diff --git a/ruby/ext/openssl/ossl_pkcs12.c b/ruby/ext/openssl/ossl_pkcs12.c index 456633448..fb947df1d 100644 --- a/ruby/ext/openssl/ossl_pkcs12.c +++ b/ruby/ext/openssl/ossl_pkcs12.c @@ -149,6 +149,24 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) return obj; } +static VALUE +ossl_pkey_new_i(VALUE arg) +{ + return ossl_pkey_new((EVP_PKEY *)arg); +} + +static VALUE +ossl_x509_new_i(VALUE arg) +{ + return ossl_x509_new((X509 *)arg); +} + +static VALUE +ossl_x509_sk2ary_i(VALUE arg) +{ + return ossl_x509_sk2ary((STACK_OF(X509) *)arg); +} + /* * call-seq: * PKCS12.new -> pkcs12 @@ -186,15 +204,15 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) ossl_raise(ePKCS12Error, "PKCS12_parse"); ERR_pop_to_mark(); if (key) { - pkey = rb_protect((VALUE (*)(VALUE))ossl_pkey_new, (VALUE)key, &st); + pkey = rb_protect(ossl_pkey_new_i, (VALUE)key, &st); if (st) goto err; } if (x509) { - cert = rb_protect((VALUE (*)(VALUE))ossl_x509_new, (VALUE)x509, &st); + cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st); if (st) goto err; } if (x509s) { - ca = rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st); + ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st); if (st) goto err; } diff --git a/ruby/ext/openssl/ossl_pkcs7.c b/ruby/ext/openssl/ossl_pkcs7.c index 28010c81f..dbe534763 100644 --- a/ruby/ext/openssl/ossl_pkcs7.c +++ b/ruby/ext/openssl/ossl_pkcs7.c @@ -9,21 +9,6 @@ */ #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 { \ @@ -75,7 +60,7 @@ ossl_pkcs7_free(void *ptr) PKCS7_free(ptr); } -static const rb_data_type_t ossl_pkcs7_type = { +const rb_data_type_t ossl_pkcs7_type = { "OpenSSL/PKCS7", { 0, ossl_pkcs7_free, @@ -116,19 +101,24 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = { * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) */ static PKCS7_SIGNER_INFO * -ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si) +ossl_PKCS7_SIGNER_INFO_dup(PKCS7_SIGNER_INFO *si) { - return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, - (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, - (char *)si); + PKCS7_SIGNER_INFO *si_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, + (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, + si); + if (si_new && si->pkey) { + EVP_PKEY_up_ref(si->pkey); + si_new->pkey = si->pkey; + } + return si_new; } static PKCS7_RECIP_INFO * -ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si) +ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *si) { - return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, - (d2i_of_void *)d2i_PKCS7_RECIP_INFO, - (char *)si); + return ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, + (d2i_of_void *)d2i_PKCS7_RECIP_INFO, + si); } static VALUE @@ -145,19 +135,6 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) return obj; } -static PKCS7_SIGNER_INFO * -DupPKCS7SignerPtr(VALUE obj) -{ - PKCS7_SIGNER_INFO *p7si, *pkcs7; - - GetPKCS7si(obj, p7si); - if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) { - ossl_raise(ePKCS7Error, NULL); - } - - return pkcs7; -} - static VALUE ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) { @@ -172,19 +149,6 @@ ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) return obj; } -static PKCS7_RECIP_INFO * -DupPKCS7RecipientPtr(VALUE obj) -{ - PKCS7_RECIP_INFO *p7ri, *pkcs7; - - GetPKCS7ri(obj, p7ri); - if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) { - ossl_raise(ePKCS7Error, NULL); - } - - return pkcs7; -} - /* * call-seq: * PKCS7.read_smime(string) => pkcs7 @@ -366,7 +330,7 @@ ossl_pkcs7_alloc(VALUE klass) static VALUE ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) { - PKCS7 *p7, *pkcs = DATA_PTR(self); + PKCS7 *p7, *p7_orig = RTYPEDDATA_DATA(self); BIO *in; VALUE arg; @@ -374,19 +338,17 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) return self; arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); - p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL); + p7 = d2i_PKCS7_bio(in, NULL); if (!p7) { - OSSL_BIO_reset(in); - p7 = d2i_PKCS7_bio(in, &pkcs); - if (!p7) { - BIO_free(in); - PKCS7_free(pkcs); - DATA_PTR(self) = NULL; - ossl_raise(rb_eArgError, "Could not parse the PKCS7"); - } + OSSL_BIO_reset(in); + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); } - DATA_PTR(self) = pkcs; BIO_free(in); + if (!p7) + ossl_raise(rb_eArgError, "Could not parse the PKCS7"); + + RTYPEDDATA_DATA(self) = p7; + PKCS7_free(p7_orig); ossl_pkcs7_set_data(self, Qnil); ossl_pkcs7_set_err_string(self, Qnil); @@ -536,17 +498,18 @@ static VALUE ossl_pkcs7_add_signer(VALUE self, VALUE signer) { PKCS7 *pkcs7; - PKCS7_SIGNER_INFO *p7si; + PKCS7_SIGNER_INFO *si, *si_new; - p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */ GetPKCS7(self, pkcs7); - if (!PKCS7_add_signer(pkcs7, p7si)) { - PKCS7_SIGNER_INFO_free(p7si); - ossl_raise(ePKCS7Error, "Could not add signer."); - } - if (PKCS7_type_is_signed(pkcs7)){ - PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, - V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); + GetPKCS7si(signer, si); + + si_new = ossl_PKCS7_SIGNER_INFO_dup(si); + if (!si_new) + ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_dup"); + + if (PKCS7_add_signer(pkcs7, si_new) != 1) { + PKCS7_SIGNER_INFO_free(si_new); + ossl_raise(ePKCS7Error, "PKCS7_add_signer"); } return self; @@ -582,13 +545,18 @@ static VALUE ossl_pkcs7_add_recipient(VALUE self, VALUE recip) { PKCS7 *pkcs7; - PKCS7_RECIP_INFO *ri; + PKCS7_RECIP_INFO *ri, *ri_new; - ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */ GetPKCS7(self, pkcs7); - if (!PKCS7_add_recipient_info(pkcs7, ri)) { - PKCS7_RECIP_INFO_free(ri); - ossl_raise(ePKCS7Error, "Could not add recipient."); + GetPKCS7ri(recip, ri); + + ri_new = ossl_PKCS7_RECIP_INFO_dup(ri); + if (!ri_new) + ossl_raise(ePKCS7Error, "PKCS7_RECIP_INFO_dup"); + + if (PKCS7_add_recipient_info(pkcs7, ri_new) != 1) { + PKCS7_RECIP_INFO_free(ri_new); + ossl_raise(ePKCS7Error, "PKCS7_add_recipient_info"); } return self; @@ -1088,7 +1056,6 @@ Init_ossl_pkcs7(void) rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3); rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0); - rb_define_alias(cPKCS7Signer, "name", "issuer"); rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0); rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0); diff --git a/ruby/ext/openssl/ossl_pkcs7.h b/ruby/ext/openssl/ossl_pkcs7.h index 139e00d64..3e1b09467 100644 --- a/ruby/ext/openssl/ossl_pkcs7.h +++ b/ruby/ext/openssl/ossl_pkcs7.h @@ -10,6 +10,22 @@ #if !defined(_OSSL_PKCS7_H_) #define _OSSL_PKCS7_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) + +extern const rb_data_type_t ossl_pkcs7_type; extern VALUE cPKCS7; extern VALUE cPKCS7Signer; extern VALUE cPKCS7Recipient; diff --git a/ruby/ext/openssl/ossl_pkey.c b/ruby/ext/openssl/ossl_pkey.c index e1fffb244..2a4835a28 100644 --- a/ruby/ext/openssl/ossl_pkey.c +++ b/ruby/ext/openssl/ossl_pkey.c @@ -9,6 +9,10 @@ */ #include "ossl.h" +#ifdef OSSL_USE_ENGINE +# include +#endif + /* * Classes */ @@ -17,64 +21,6 @@ VALUE cPKey; VALUE ePKeyError; static ID id_private_q; -/* - * callback for generating keys - */ -static VALUE -call_check_ints0(VALUE arg) -{ - rb_thread_check_ints(); - return Qnil; -} - -static void * -call_check_ints(void *arg) -{ - int state; - rb_protect(call_check_ints0, Qnil, &state); - return (void *)(VALUE)state; -} - -int -ossl_generate_cb_2(int p, int n, BN_GENCB *cb) -{ - VALUE ary; - struct ossl_generate_cb_arg *arg; - int state; - - arg = (struct ossl_generate_cb_arg *)BN_GENCB_get_arg(cb); - if (arg->yield) { - ary = rb_ary_new2(2); - rb_ary_store(ary, 0, INT2NUM(p)); - rb_ary_store(ary, 1, INT2NUM(n)); - - /* - * can be break by raising exception or 'break' - */ - rb_protect(rb_yield, ary, &state); - if (state) { - arg->state = state; - return 0; - } - } - if (arg->interrupted) { - arg->interrupted = 0; - state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL); - if (state) { - arg->state = state; - return 0; - } - } - return 1; -} - -void -ossl_generate_cb_stop(void *ptr) -{ - struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr; - arg->interrupted = 1; -} - static void ossl_evp_pkey_free(void *ptr) { @@ -93,36 +39,29 @@ const rb_data_type_t ossl_evp_pkey_type = { }; static VALUE -pkey_new0(EVP_PKEY *pkey) +pkey_new0(VALUE arg) { - VALUE obj; - int type; + EVP_PKEY *pkey = (EVP_PKEY *)arg; + VALUE klass, obj; - if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE) - ossl_raise(rb_eRuntimeError, "pkey is empty"); - - switch (type) { + switch (EVP_PKEY_base_id(pkey)) { #if !defined(OPENSSL_NO_RSA) - case EVP_PKEY_RSA: - return ossl_rsa_new(pkey); + case EVP_PKEY_RSA: klass = cRSA; break; #endif #if !defined(OPENSSL_NO_DSA) - case EVP_PKEY_DSA: - return ossl_dsa_new(pkey); + case EVP_PKEY_DSA: klass = cDSA; break; #endif #if !defined(OPENSSL_NO_DH) - case EVP_PKEY_DH: - return ossl_dh_new(pkey); + case EVP_PKEY_DH: klass = cDH; break; #endif #if !defined(OPENSSL_NO_EC) - case EVP_PKEY_EC: - return ossl_ec_new(pkey); + case EVP_PKEY_EC: klass = cEC; break; #endif - default: - obj = NewPKey(cPKey); - SetPKey(obj, pkey); - return obj; + default: klass = cPKey; break; } + obj = rb_obj_alloc(klass); + RTYPEDDATA_DATA(obj) = pkey; + return obj; } VALUE @@ -131,7 +70,7 @@ ossl_pkey_new(EVP_PKEY *pkey) VALUE obj; int status; - obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status); + obj = rb_protect(pkey_new0, (VALUE)pkey, &status); if (status) { EVP_PKEY_free(pkey); rb_jump_tag(status); @@ -140,6 +79,75 @@ ossl_pkey_new(EVP_PKEY *pkey) return obj; } +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# include + +EVP_PKEY * +ossl_pkey_read_generic(BIO *bio, VALUE pass) +{ + void *ppass = (void *)pass; + OSSL_DECODER_CTX *dctx; + EVP_PKEY *pkey = NULL; + int pos = 0, pos2; + + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL); + if (!dctx) + goto out; + if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1) + goto out; + + /* First check DER */ + if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; + + /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ + OSSL_BIO_reset(bio); + if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) + goto out; + while (OSSL_DECODER_from_bio(dctx, bio) != 1) { + if (BIO_eof(bio)) + goto out; + pos2 = BIO_tell(bio); + if (pos2 < 0 || pos2 <= pos) + goto out; + pos = pos2; + } + + out: + OSSL_DECODER_CTX_free(dctx); + return pkey; +} +#else +EVP_PKEY * +ossl_pkey_read_generic(BIO *bio, VALUE pass) +{ + void *ppass = (void *)pass; + EVP_PKEY *pkey; + + if ((pkey = d2i_PrivateKey_bio(bio, NULL))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = d2i_PUBKEY_bio(bio, NULL))) + goto out; + OSSL_BIO_reset(bio); + /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */ + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) + goto out; + OSSL_BIO_reset(bio); + if ((pkey = PEM_read_bio_Parameters(bio, NULL))) + goto out; + + out: + return pkey; +} +#endif + /* * call-seq: * OpenSSL::PKey.read(string [, pwd ]) -> PKey @@ -149,7 +157,7 @@ ossl_pkey_new(EVP_PKEY *pkey) * instance of the appropriate PKey class. * * === Parameters - * * _string+ is a DER- or PEM-encoded string containing an arbitrary private + * * _string_ is a DER- or PEM-encoded string containing an arbitrary private * or public key. * * _io_ is an instance of IO containing a DER- or PEM-encoded * arbitrary private or public key. @@ -164,30 +172,282 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) VALUE data, pass; rb_scan_args(argc, argv, "11", &data, &pass); - pass = ossl_pem_passwd_value(pass); - bio = ossl_obj2bio(&data); - if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) { - OSSL_BIO_reset(bio); - if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) { - OSSL_BIO_reset(bio); - if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) { - OSSL_BIO_reset(bio); - pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass); - } - } - } - + pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass)); BIO_free(bio); if (!pkey) ossl_raise(ePKeyError, "Could not parse PKey"); - return ossl_pkey_new(pkey); } +static VALUE +pkey_ctx_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v)) +{ + VALUE key = rb_ary_entry(i, 0), value = rb_ary_entry(i, 1); + EVP_PKEY_CTX *ctx = (EVP_PKEY_CTX *)ctx_v; + + if (SYMBOL_P(key)) + key = rb_sym2str(key); + value = rb_String(value); + + if (EVP_PKEY_CTX_ctrl_str(ctx, StringValueCStr(key), StringValueCStr(value)) <= 0) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_ctrl_str(ctx, %+"PRIsVALUE", %+"PRIsVALUE")", + key, value); + return Qnil; +} + +static VALUE +pkey_ctx_apply_options0(VALUE args_v) +{ + VALUE *args = (VALUE *)args_v; + + rb_block_call(args[1], rb_intern("each"), 0, NULL, + pkey_ctx_apply_options_i, args[0]); + return Qnil; +} + +static void +pkey_ctx_apply_options(EVP_PKEY_CTX *ctx, VALUE options, int *state) +{ + VALUE args[2]; + args[0] = (VALUE)ctx; + args[1] = options; + + rb_protect(pkey_ctx_apply_options0, (VALUE)args, state); +} + +struct pkey_blocking_generate_arg { + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey; + int state; + int yield: 1; + int genparam: 1; + int interrupted: 1; +}; + +static VALUE +pkey_gen_cb_yield(VALUE ctx_v) +{ + EVP_PKEY_CTX *ctx = (void *)ctx_v; + int i, info_num; + VALUE *argv; + + info_num = EVP_PKEY_CTX_get_keygen_info(ctx, -1); + argv = ALLOCA_N(VALUE, info_num); + for (i = 0; i < info_num; i++) + argv[i] = INT2NUM(EVP_PKEY_CTX_get_keygen_info(ctx, i)); + + return rb_yield_values2(info_num, argv); +} + +static VALUE +call_check_ints0(VALUE arg) +{ + rb_thread_check_ints(); + return Qnil; +} + +static void * +call_check_ints(void *arg) +{ + int state; + rb_protect(call_check_ints0, Qnil, &state); + return (void *)(VALUE)state; +} + +static int +pkey_gen_cb(EVP_PKEY_CTX *ctx) +{ + struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx); + int state; + + if (arg->yield) { + rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state); + if (state) { + arg->state = state; + return 0; + } + } + if (arg->interrupted) { + arg->interrupted = 0; + state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL); + if (state) { + arg->state = state; + return 0; + } + } + return 1; +} + +static void +pkey_blocking_gen_stop(void *ptr) +{ + struct pkey_blocking_generate_arg *arg = ptr; + arg->interrupted = 1; +} + +static void * +pkey_blocking_gen(void *ptr) +{ + struct pkey_blocking_generate_arg *arg = ptr; + + if (arg->genparam && EVP_PKEY_paramgen(arg->ctx, &arg->pkey) <= 0) + return NULL; + if (!arg->genparam && EVP_PKEY_keygen(arg->ctx, &arg->pkey) <= 0) + return NULL; + return arg->pkey; +} + +static VALUE +pkey_generate(int argc, VALUE *argv, VALUE self, int genparam) +{ + EVP_PKEY_CTX *ctx; + VALUE alg, options; + struct pkey_blocking_generate_arg gen_arg = { 0 }; + int state; + + rb_scan_args(argc, argv, "11", &alg, &options); + if (rb_obj_is_kind_of(alg, cPKey)) { + EVP_PKEY *base_pkey; + + GetPKey(alg, base_pkey); + ctx = EVP_PKEY_CTX_new(base_pkey, NULL/* engine */); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + } + else { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name"); +#else + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng; + int pkey_id; + + StringValue(alg); + ameth = EVP_PKEY_asn1_find_str(&tmpeng, RSTRING_PTR(alg), + RSTRING_LENINT(alg)); + if (!ameth) + ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", alg); + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); +#if !defined(OPENSSL_NO_ENGINE) + if (tmpeng) + ENGINE_finish(tmpeng); +#endif + + ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id"); +#endif + } + + if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_paramgen_init"); + } + if (!genparam && EVP_PKEY_keygen_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_keygen_init"); + } + + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + + gen_arg.genparam = genparam; + gen_arg.ctx = ctx; + gen_arg.yield = rb_block_given_p(); + EVP_PKEY_CTX_set_app_data(ctx, &gen_arg); + EVP_PKEY_CTX_set_cb(ctx, pkey_gen_cb); + if (gen_arg.yield) + pkey_blocking_gen(&gen_arg); + else + rb_thread_call_without_gvl(pkey_blocking_gen, &gen_arg, + pkey_blocking_gen_stop, &gen_arg); + EVP_PKEY_CTX_free(ctx); + if (!gen_arg.pkey) { + if (gen_arg.state) { + ossl_clear_error(); + rb_jump_tag(gen_arg.state); + } + else { + ossl_raise(ePKeyError, genparam ? "EVP_PKEY_paramgen" : "EVP_PKEY_keygen"); + } + } + + return ossl_pkey_new(gen_arg.pkey); +} + +/* + * call-seq: + * OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey + * + * Generates new parameters for the algorithm. _algo_name_ is a String that + * represents the algorithm. The optional argument _options_ is a Hash that + * specifies the options specific to the algorithm. The order of the options + * can be important. + * + * A block can be passed optionally. The meaning of the arguments passed to + * the block varies depending on the implementation of the algorithm. The block + * may be called once or multiple times, or may not even be called. + * + * For the supported options, see the documentation for the 'openssl genpkey' + * utility command. + * + * == Example + * pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) + * p pkey.p.num_bits #=> 2048 + */ +static VALUE +ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self) +{ + return pkey_generate(argc, argv, self, 1); +} + +/* + * call-seq: + * OpenSSL::PKey.generate_key(algo_name [, options]) -> pkey + * OpenSSL::PKey.generate_key(pkey [, options]) -> pkey + * + * Generates a new key (pair). + * + * If a String is given as the first argument, it generates a new random key + * for the algorithm specified by the name just as ::generate_parameters does. + * If an OpenSSL::PKey::PKey is given instead, it generates a new random key + * for the same algorithm as the key, using the parameters the key contains. + * + * See ::generate_parameters for the details of _options_ and the given block. + * + * == Example + * pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) + * pkey_params.priv_key #=> nil + * pkey = OpenSSL::PKey.generate_key(pkey_params) + * pkey.priv_key #=> # string + * + * Returns the short name of the OID associated with _pkey_. + */ +static VALUE +ossl_pkey_oid(VALUE self) +{ + EVP_PKEY *pkey; + int nid; + + GetPKey(self, pkey); + nid = EVP_PKEY_id(pkey); + return rb_str_new_cstr(OBJ_nid2sn(nid)); +} + +/* + * call-seq: + * pkey.inspect -> string + * + * Returns a string describing the PKey object. + */ +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)); +} + +/* + * call-seq: + * pkey.to_text -> string + * + * Dumps key parameters, public key, and private key components contained in + * the key into a human-readable text. + * + * This is intended for debugging purpose. + * + * See also the man page EVP_PKEY_print_private(3). + */ +static VALUE +ossl_pkey_to_text(VALUE self) +{ + EVP_PKEY *pkey; + BIO *bio; + + GetPKey(self, pkey); + if (!(bio = BIO_new(BIO_s_mem()))) + ossl_raise(ePKeyError, "BIO_new"); + + if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1) + goto out; + OSSL_BIO_reset(bio); + if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1) + goto out; + OSSL_BIO_reset(bio); + if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1) + goto out; + + BIO_free(bio); + ossl_raise(ePKeyError, "EVP_PKEY_print_params"); + + out: + return ossl_membio2str(bio); +} + +VALUE +ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) +{ + EVP_PKEY *pkey; + VALUE cipher, pass; + const EVP_CIPHER *enc = NULL; + BIO *bio; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "02", &cipher, &pass); + if (!NIL_P(cipher)) { + enc = ossl_evp_get_cipherbyname(cipher); + pass = ossl_pem_passwd_value(pass); + } + + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PrivateKey_bio(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PrivateKey_bio"); + } + } + else { +#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + 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"); + } + } + return ossl_membio2str(bio); +} + +static VALUE +do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der) +{ + EVP_PKEY *pkey; + VALUE cipher, pass; + const EVP_CIPHER *enc = NULL; + BIO *bio; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "02", &cipher, &pass); + if (argc > 0) { + /* + * TODO: EncryptedPrivateKeyInfo actually has more options. + * Should they be exposed? + */ + enc = ossl_evp_get_cipherbyname(cipher); + pass = ossl_pem_passwd_value(pass); + } + + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PKCS8PrivateKey_bio(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, (void *)pass)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PKCS8PrivateKey_bio"); + } + } + else { + if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey, enc, NULL, 0, + ossl_pem_passwd_cb, (void *)pass)) { + BIO_free(bio); + ossl_raise(ePKeyError, "PEM_write_bio_PKCS8PrivateKey"); + } + } + return ossl_membio2str(bio); +} + +/* + * call-seq: + * pkey.private_to_der -> string + * pkey.private_to_der(cipher, password) -> string + * + * Serializes the private key to DER-encoded PKCS #8 format. If called without + * arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with + * a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with + * PBES2 encryption scheme is used. + */ +static VALUE +ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self) +{ + return do_pkcs8_export(argc, argv, self, 1); +} + +/* + * call-seq: + * pkey.private_to_pem -> string + * pkey.private_to_pem(cipher, password) -> string + * + * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der + * for more details. + */ +static VALUE +ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self) +{ + return do_pkcs8_export(argc, argv, self, 0); +} + +VALUE +ossl_pkey_export_spki(VALUE self, int to_der) +{ + EVP_PKEY *pkey; + BIO *bio; + + GetPKey(self, pkey); + bio = BIO_new(BIO_s_mem()); + if (!bio) + ossl_raise(ePKeyError, "BIO_new"); + if (to_der) { + if (!i2d_PUBKEY_bio(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "i2d_PUBKEY_bio"); + } + } + else { + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + BIO_free(bio); + ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY"); + } + } + return ossl_membio2str(bio); +} + +/* + * call-seq: + * pkey.public_to_der -> string + * + * Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format. + */ +static VALUE +ossl_pkey_public_to_der(VALUE self) +{ + return ossl_pkey_export_spki(self, 1); +} + +/* + * call-seq: + * pkey.public_to_pem -> string + * + * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. + */ +static VALUE +ossl_pkey_public_to_pem(VALUE self) +{ + return ossl_pkey_export_spki(self, 0); +} + /* * call-seq: - * pkey.sign(digest, data) -> String + * pkey.compare?(another_pkey) -> true | false * - * To sign the String _data_, _digest_, an instance of OpenSSL::Digest, must - * be provided. The return value is again a String containing the signature. - * A PKeyError is raised should errors occur. - * Any previous state of the Digest instance is irrelevant to the signature - * outcome, the digest instance is reset to its initial state during the - * operation. + * Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key. * * == Example - * data = 'Sign me!' - * digest = OpenSSL::Digest::SHA256.new - * pkey = OpenSSL::PKey::RSA.new(2048) - * signature = pkey.sign(digest, data) + * x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate) + * rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key) + * + * rsa_key.compare?(x509.public_key) => true | false */ static VALUE -ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) +ossl_pkey_compare(VALUE self, VALUE other) +{ + int ret; + EVP_PKEY *selfPKey; + EVP_PKEY *otherPKey; + + GetPKey(self, selfPKey); + GetPKey(other, otherPKey); + + /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3) + * docs param_cmp could return any negative number. + */ + if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey)) + ossl_raise(rb_eTypeError, "cannot match different PKey types"); + + ret = EVP_PKEY_eq(selfPKey, otherPKey); + + if (ret == 0) + return Qfalse; + else if (ret == 1) + return Qtrue; + else + ossl_raise(ePKeyError, "EVP_PKEY_eq"); +} + +/* + * call-seq: + * pkey.sign(digest, data [, options]) -> string + * + * Hashes and signs the +data+ using a message digest algorithm +digest+ and + * a private key +pkey+. + * + * See #verify for the verification operation. + * + * See also the man page EVP_DigestSign(3). + * + * +digest+:: + * A String that represents the message digest algorithm name, or +nil+ + * if the PKey type requires no digest algorithm. + * For backwards compatibility, this can be an instance of OpenSSL::Digest. + * Its state will not affect the signature. + * +data+:: + * A String. The data to be hashed and signed. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * +options+ parameter was added in version 3.0. + * + * Example: + * data = "Sign me!" + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * signopts = { rsa_padding_mode: "pss" } + * signature = pkey.sign("SHA256", data, signopts) + * + * # Creates a copy of the RSA key pkey, but without the private components + * pub_key = pkey.public_key + * puts pub_key.verify("SHA256", signature, data, signopts) # => true + */ +static VALUE +ossl_pkey_sign(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - const EVP_MD *md; + VALUE digest, data, options, sig; + const EVP_MD *md = NULL; EVP_MD_CTX *ctx; - unsigned int buf_len; - VALUE str; - int result; + EVP_PKEY_CTX *pctx; + size_t siglen; + int state; pkey = GetPrivPKeyPtr(self); - md = ossl_evp_get_digestbyname(digest); + rb_scan_args(argc, argv, "21", &digest, &data, &options); + if (!NIL_P(digest)) + md = ossl_evp_get_digestbyname(digest); StringValue(data); - str = rb_str_new(0, EVP_PKEY_size(pkey)); ctx = EVP_MD_CTX_new(); if (!ctx) - ossl_raise(ePKeyError, "EVP_MD_CTX_new"); - if (!EVP_SignInit_ex(ctx, md, NULL)) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_SignInit_ex"); + ossl_raise(ePKeyError, "EVP_MD_CTX_new"); + if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSignInit"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(pctx, options, &state); + if (state) { + EVP_MD_CTX_free(ctx); + rb_jump_tag(state); + } + } +#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) + if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSign"); + } + 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_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_SignUpdate"); + if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestSign"); } - result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey); +#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); - if (!result) - ossl_raise(ePKeyError, "EVP_SignFinal"); - rb_str_set_len(str, buf_len); - - return str; + rb_str_set_len(sig, siglen); + return sig; } /* - * call-seq: - * pkey.verify(digest, signature, data) -> String + * call-seq: + * pkey.verify(digest, signature, data [, options]) -> true or false * - * To verify the String _signature_, _digest_, an instance of - * OpenSSL::Digest, must be provided to re-compute the message digest of the - * original _data_, also a String. The return value is +true+ if the - * signature is valid, +false+ otherwise. A PKeyError is raised should errors - * occur. - * Any previous state of the Digest instance is irrelevant to the validation - * outcome, the digest instance is reset to its initial state during the - * operation. + * Verifies the +signature+ for the +data+ using a message digest algorithm + * +digest+ and a public key +pkey+. * - * == Example - * data = 'Sign me!' - * digest = OpenSSL::Digest::SHA256.new - * pkey = OpenSSL::PKey::RSA.new(2048) - * signature = pkey.sign(digest, data) - * pub_key = pkey.public_key - * puts pub_key.verify(digest, signature, data) # => true + * Returns +true+ if the signature is successfully verified, +false+ otherwise. + * The caller must check the return value. + * + * See #sign for the signing operation and an example. + * + * See also the man page EVP_DigestVerify(3). + * + * +digest+:: + * See #sign. + * +signature+:: + * A String containing the signature to be verified. + * +data+:: + * See #sign. + * +options+:: + * See #sign. +options+ parameter was added in version 3.0. */ static VALUE -ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) +ossl_pkey_verify(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - const EVP_MD *md; + VALUE digest, sig, data, options; + const EVP_MD *md = NULL; EVP_MD_CTX *ctx; - int siglen, result; + EVP_PKEY_CTX *pctx; + int state, ret; GetPKey(self, pkey); + rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options); ossl_pkey_check_public_key(pkey); - md = ossl_evp_get_digestbyname(digest); + if (!NIL_P(digest)) + md = ossl_evp_get_digestbyname(digest); StringValue(sig); - siglen = RSTRING_LENINT(sig); StringValue(data); ctx = EVP_MD_CTX_new(); if (!ctx) - ossl_raise(ePKeyError, "EVP_MD_CTX_new"); - if (!EVP_VerifyInit_ex(ctx, md, NULL)) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_VerifyInit_ex"); + ossl_raise(ePKeyError, "EVP_MD_CTX_new"); + if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) { + EVP_MD_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_DigestVerifyInit"); } - if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_VerifyUpdate"); + if (!NIL_P(options)) { + pkey_ctx_apply_options(pctx, options, &state); + if (state) { + EVP_MD_CTX_free(ctx); + rb_jump_tag(state); + } } - result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey); +#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) + 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); - switch (result) { - case 0: - ossl_clear_error(); - return Qfalse; - case 1: - return Qtrue; - default: - ossl_raise(ePKeyError, "EVP_VerifyFinal"); + 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 { + ossl_clear_error(); + return Qfalse; + } +} + +/* + * call-seq: + * pkey.sign_raw(digest, data [, options]) -> string + * + * Signs +data+ using a private key +pkey+. Unlike #sign, +data+ will not be + * hashed by +digest+ automatically. + * + * See #verify_raw for the verification operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_sign(3). + * + * +digest+:: + * A String that represents the message digest algorithm name, or +nil+ + * if the PKey type requires no digest algorithm. + * Although this method will not hash +data+ with it, this parameter may still + * be required depending on the signature algorithm. + * +data+:: + * A String. The data to be signed. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * + * Example: + * data = "Sign me!" + * hash = OpenSSL::Digest.digest("SHA256", data) + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * signopts = { rsa_padding_mode: "pss" } + * signature = pkey.sign_raw("SHA256", hash, signopts) + * + * # Creates a copy of the RSA key pkey, but without the private components + * pub_key = pkey.public_key + * puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true + */ +static VALUE +ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, data, options, sig; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + size_t outlen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "21", &digest, &data, &options); + if (!NIL_P(digest)) + md = ossl_evp_get_digestbyname(digest); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_sign_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "signature would be too large"); + } + sig = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_sign"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(sig, outlen); + return sig; +} + +/* + * call-seq: + * pkey.verify_raw(digest, signature, data [, options]) -> true or false + * + * Verifies the +signature+ for the +data+ using a public key +pkey+. Unlike + * #verify, this method will not hash +data+ with +digest+ automatically. + * + * Returns +true+ if the signature is successfully verified, +false+ otherwise. + * The caller must check the return value. + * + * See #sign_raw for the signing operation and an example code. + * + * Added in version 3.0. See also the man page EVP_PKEY_verify(3). + * + * +signature+:: + * A String containing the signature to be verified. + */ +static VALUE +ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, sig, data, options; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + int state, ret; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options); + ossl_pkey_check_public_key(pkey); + if (!NIL_P(digest)) + md = ossl_evp_get_digestbyname(digest); + StringValue(sig); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_verify_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig), + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)); + EVP_PKEY_CTX_free(ctx); + if (ret < 0) + ossl_raise(ePKeyError, "EVP_PKEY_verify"); + + if (ret) + return Qtrue; + else { + ossl_clear_error(); + return Qfalse; } } +/* + * call-seq: + * pkey.verify_recover(digest, signature [, options]) -> string + * + * Recovers the signed data from +signature+ using a public key +pkey+. Not all + * signature algorithms support this operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_verify_recover(3). + * + * +signature+:: + * A String containing the signature to be verified. + */ +static VALUE +ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + VALUE digest, sig, options, out; + const EVP_MD *md = NULL; + EVP_PKEY_CTX *ctx; + int state; + size_t outlen; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "21", &digest, &sig, &options); + ossl_pkey_check_public_key(pkey); + if (!NIL_P(digest)) + md = ossl_evp_get_digestbyname(digest); + StringValue(sig); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_verify_recover_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init"); + } + if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_verify_recover(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover"); + } + out = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen, + (unsigned char *)RSTRING_PTR(sig), + RSTRING_LEN(sig)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_verify_recover"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(out, outlen); + return out; +} + +/* + * call-seq: + * pkey.derive(peer_pkey) -> string + * + * Derives a shared secret from _pkey_ and _peer_pkey_. _pkey_ must contain + * the private components, _peer_pkey_ must contain the public components. + */ +static VALUE +ossl_pkey_derive(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey, *peer_pkey; + EVP_PKEY_CTX *ctx; + VALUE peer_pkey_obj, str; + size_t keylen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "1", &peer_pkey_obj); + GetPKey(peer_pkey_obj, peer_pkey); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_derive_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive_init"); + } + if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer"); + } + if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive"); + } + if (keylen > LONG_MAX) + rb_raise(ePKeyError, "derived key would be too large"); + str = ossl_str_new(NULL, (long)keylen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_derive"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, keylen); + return str; +} + +/* + * call-seq: + * pkey.encrypt(data [, options]) -> string + * + * Performs a public key encryption operation using +pkey+. + * + * See #decrypt for the reverse operation. + * + * Added in version 3.0. See also the man page EVP_PKEY_encrypt(3). + * + * +data+:: + * A String to be encrypted. + * +options+:: + * A Hash that contains algorithm specific control operations to \OpenSSL. + * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details. + * + * Example: + * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) + * data = "secret data" + * encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep") + * decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep") + * p decrypted #=> "secret data" + */ +static VALUE +ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; + VALUE data, options, str; + size_t outlen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "11", &data, &options); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_encrypt(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "encrypted data would be too large"); + } + str = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_encrypt"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, outlen); + return str; +} + +/* + * call-seq: + * pkey.decrypt(data [, options]) -> string + * + * Performs a public key decryption operation using +pkey+. + * + * See #encrypt for a description of the parameters and an example. + * + * Added in version 3.0. See also the man page EVP_PKEY_decrypt(3). + */ +static VALUE +ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; + VALUE data, options, str; + size_t outlen; + int state; + + GetPKey(self, pkey); + rb_scan_args(argc, argv, "11", &data, &options); + StringValue(data); + + ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!ctx) + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init"); + } + if (!NIL_P(options)) { + pkey_ctx_apply_options(ctx, options, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + } + if (EVP_PKEY_decrypt(ctx, NULL, &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt"); + } + if (outlen > LONG_MAX) { + EVP_PKEY_CTX_free(ctx); + rb_raise(ePKeyError, "decrypted data would be too large"); + } + str = ossl_str_new(NULL, (long)outlen, &state); + if (state) { + EVP_PKEY_CTX_free(ctx); + rb_jump_tag(state); + } + if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen, + (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data)) <= 0) { + EVP_PKEY_CTX_free(ctx); + ossl_raise(ePKeyError, "EVP_PKEY_decrypt"); + } + EVP_PKEY_CTX_free(ctx); + rb_str_set_len(str, outlen); + return str; +} + /* * INIT */ @@ -488,12 +1544,33 @@ Init_ossl_pkey(void) cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject); 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); rb_define_alloc_func(cPKey, ossl_pkey_alloc); rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); +#ifdef HAVE_EVP_PKEY_DUP + rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1); +#else + rb_undef_method(cPKey, "initialize_copy"); +#endif + rb_define_method(cPKey, "oid", ossl_pkey_oid, 0); + rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0); + rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0); + rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1); + 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); + rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1); - rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); - rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); + rb_define_method(cPKey, "sign", ossl_pkey_sign, -1); + rb_define_method(cPKey, "verify", ossl_pkey_verify, -1); + rb_define_method(cPKey, "sign_raw", ossl_pkey_sign_raw, -1); + rb_define_method(cPKey, "verify_raw", ossl_pkey_verify_raw, -1); + rb_define_method(cPKey, "verify_recover", ossl_pkey_verify_recover, -1); + rb_define_method(cPKey, "derive", ossl_pkey_derive, -1); + rb_define_method(cPKey, "encrypt", ossl_pkey_encrypt, -1); + rb_define_method(cPKey, "decrypt", ossl_pkey_decrypt, -1); id_private_q = rb_intern("private?"); diff --git a/ruby/ext/openssl/ossl_pkey.h b/ruby/ext/openssl/ossl_pkey.h index 0db59305f..38fb9fad1 100644 --- a/ruby/ext/openssl/ossl_pkey.h +++ b/ruby/ext/openssl/ossl_pkey.h @@ -7,27 +7,18 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(_OSSL_PKEY_H_) -#define _OSSL_PKEY_H_ +#if !defined(OSSL_PKEY_H) +#define OSSL_PKEY_H extern VALUE mPKey; extern VALUE cPKey; extern VALUE ePKeyError; extern const rb_data_type_t ossl_evp_pkey_type; -#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue) -#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse) -#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue) +/* For ENGINE */ +#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue) +#define OSSL_PKEY_IS_PRIVATE(obj) (rb_attr_get((obj), rb_intern("private")) == Qtrue) -#define NewPKey(klass) \ - TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, 0) -#define SetPKey(obj, pkey) do { \ - if (!(pkey)) { \ - rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \ - } \ - RTYPEDDATA_DATA(obj) = (pkey); \ - OSSL_PKEY_SET_PUBLIC(obj); \ -} while (0) #define GetPKey(obj, pkey) do {\ TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \ if (!(pkey)) { \ @@ -35,19 +26,27 @@ extern const rb_data_type_t ossl_evp_pkey_type; } \ } while (0) -struct ossl_generate_cb_arg { - int yield; - int interrupted; - int state; -}; -int ossl_generate_cb_2(int p, int n, BN_GENCB *cb); -void ossl_generate_cb_stop(void *ptr); - +/* Takes ownership of the EVP_PKEY */ VALUE ossl_pkey_new(EVP_PKEY *); void ossl_pkey_check_public_key(const EVP_PKEY *); +EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); EVP_PKEY *GetPKeyPtr(VALUE); EVP_PKEY *DupPKeyPtr(VALUE); EVP_PKEY *GetPrivPKeyPtr(VALUE); + +/* + * Serializes _self_ in X.509 SubjectPublicKeyInfo format and returns the + * resulting String. Sub-classes use this when overriding #to_der. + */ +VALUE ossl_pkey_export_spki(VALUE self, int to_der); +/* + * Serializes the private key _self_ in the traditional private key format + * and returns the resulting String. Sub-classes use this when overriding + * #to_der. + */ +VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, + int to_der); + void Init_ossl_pkey(void); /* @@ -56,7 +55,6 @@ void Init_ossl_pkey(void); extern VALUE cRSA; extern VALUE eRSAError; -VALUE ossl_rsa_new(EVP_PKEY *); void Init_ossl_rsa(void); /* @@ -65,7 +63,6 @@ void Init_ossl_rsa(void); extern VALUE cDSA; extern VALUE eDSAError; -VALUE ossl_dsa_new(EVP_PKEY *); void Init_ossl_dsa(void); /* @@ -74,7 +71,6 @@ void Init_ossl_dsa(void); extern VALUE cDH; extern VALUE eDHError; -VALUE ossl_dh_new(EVP_PKEY *); void Init_ossl_dh(void); /* @@ -120,6 +116,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ _type##_get0_##_group(obj, NULL, &bn)) +#if !OSSL_OPENSSL_PREREQ(3, 0, 0) #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ /* \ * call-seq: \ @@ -177,36 +174,22 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ } \ return self; \ } +#else +#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \ +{ \ + rb_raise(ePKeyError, \ + #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \ +} -#define OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, _name) \ -/* \ - * call-seq: \ - * _keytype##.##_name = bn -> bn \ - */ \ -static VALUE ossl_##_keytype##_set_##_name(VALUE self, VALUE bignum) \ +#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ { \ - _type *obj; \ - BIGNUM *bn; \ - \ - rb_warning("#"#_name"= is deprecated; use #set_"#_group); \ - Get##_type(self, obj); \ - if (NIL_P(bignum)) { \ - BN_clear_free(obj->_name); \ - obj->_name = NULL; \ - return Qnil; \ - } \ - \ - bn = GetBNPtr(bignum); \ - if (obj->_name == NULL) \ - obj->_name = BN_new(); \ - if (obj->_name == NULL) \ - ossl_raise(eBNError, NULL); \ - if (BN_copy(obj->_name, bn) == NULL) \ - ossl_raise(eBNError, NULL); \ - return bignum; \ + rb_raise(ePKeyError, \ + #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \ } +#endif -#if defined(HAVE_OPAQUE_OPENSSL) /* OpenSSL 1.1.0 */ #define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) @@ -218,24 +201,4 @@ static VALUE ossl_##_keytype##_set_##_name(VALUE self, VALUE bignum) \ #define DEF_OSSL_PKEY_BN(class, keytype, name) \ rb_define_method((class), #name, ossl_##keytype##_get_##name, 0) -#else -#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ - OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ - OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ - OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \ - OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2) \ - OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a3) - -#define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \ - OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ - OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ - OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \ - OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2) - -#define DEF_OSSL_PKEY_BN(class, keytype, name) do { \ - rb_define_method((class), #name, ossl_##keytype##_get_##name, 0);\ - rb_define_method((class), #name "=", ossl_##keytype##_set_##name, 1);\ -} while (0) -#endif /* HAVE_OPAQUE_OPENSSL */ - -#endif /* _OSSL_PKEY_H_ */ +#endif /* OSSL_PKEY_H */ diff --git a/ruby/ext/openssl/ossl_pkey_dh.c b/ruby/ext/openssl/ossl_pkey_dh.c index bf4e3f932..696455dcf 100644 --- a/ruby/ext/openssl/ossl_pkey_dh.c +++ b/ruby/ext/openssl/ossl_pkey_dh.c @@ -29,217 +29,105 @@ VALUE cDH; VALUE eDHError; -/* - * Public - */ -static VALUE -dh_instance(VALUE klass, DH *dh) -{ - EVP_PKEY *pkey; - VALUE obj; - - if (!dh) { - return Qfalse; - } - obj = NewPKey(klass); - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_DH(pkey, dh)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - SetPKey(obj, pkey); - - return obj; -} - -VALUE -ossl_dh_new(EVP_PKEY *pkey) -{ - VALUE obj; - - if (!pkey) { - obj = dh_instance(cDH, DH_new()); - } else { - obj = NewPKey(cDH); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { - ossl_raise(rb_eTypeError, "Not a DH key!"); - } - SetPKey(obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eDHError, NULL); - } - - return obj; -} - /* * Private */ -struct dh_blocking_gen_arg { - DH *dh; - int size; - int gen; - BN_GENCB *cb; - int result; -}; - -static void * -dh_blocking_gen(void *arg) -{ - struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg; - gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb); - return 0; -} - -static DH * -dh_generate(int size, int gen) -{ - struct ossl_generate_cb_arg cb_arg = { 0 }; - struct dh_blocking_gen_arg gen_arg; - DH *dh = DH_new(); - BN_GENCB *cb = BN_GENCB_new(); - - if (!dh || !cb) { - DH_free(dh); - BN_GENCB_free(cb); - return NULL; - } - - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg); - gen_arg.dh = dh; - gen_arg.size = size; - gen_arg.gen = gen; - gen_arg.cb = cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - dh_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - - BN_GENCB_free(cb); - if (!gen_arg.result) { - DH_free(dh); - if (cb_arg.state) { - /* Clear OpenSSL error queue before re-raising. */ - ossl_clear_error(); - rb_jump_tag(cb_arg.state); - } - return NULL; - } - - if (!DH_generate_key(dh)) { - DH_free(dh); - return NULL; - } - - return dh; -} - -/* - * call-seq: - * DH.generate(size [, generator]) -> dh - * - * Creates a new DH instance from scratch by generating the private and public - * components alike. - * - * === Parameters - * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * _generator_ is a small number > 1, typically 2 or 5. - * - */ -static VALUE -ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) -{ - DH *dh ; - int g = 2; - VALUE size, gen, obj; - - if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) { - g = NUM2INT(gen); - } - dh = dh_generate(NUM2INT(size), g); - obj = dh_instance(klass, dh); - if (obj == Qfalse) { - DH_free(dh); - ossl_raise(eDHError, NULL); - } - - return obj; -} - /* * call-seq: * DH.new -> dh * DH.new(string) -> dh * DH.new(size [, generator]) -> dh * - * Either generates a DH instance from scratch or by reading already existing - * DH parameters from _string_. Note that when reading a DH instance from - * data that was encoded from a DH instance by using DH#to_pem or DH#to_der - * the result will *not* contain a public/private key pair yet. This needs to - * be generated using DH#generate_key! first. + * Creates a new instance of OpenSSL::PKey::DH. + * + * If called without arguments, an empty instance without any parameter or key + * components is created. Use #set_pqg to manually set the parameters afterwards + * (and optionally #set_key to set private and public key components). + * + * If a String is given, tries to parse it as a DER- or PEM- encoded parameters. + * See also OpenSSL::PKey.read which can parse keys of any kinds. + * + * The DH.new(size [, generator]) form is an alias of DH.generate. + * + * +string+:: + * A String that contains the DER or PEM encoded key. + * +size+:: + * See DH.generate. + * +generator+:: + * See DH.generate. + * + * Examples: + * # Creating an instance from scratch + * # Note that this is deprecated and will not work on OpenSSL 3.0 or later. + * dh = OpenSSL::PKey::DH.new + * dh.set_pqg(bn_p, nil, bn_g) * - * === Parameters - * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * _generator_ is a small number > 1, typically 2 or 5. - * * _string_ contains the DER or PEM encoded key. + * # Generating a parameters and a key pair + * dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048) * - * === Examples - * DH.new # -> dh - * DH.new(1024) # -> dh - * DH.new(1024, 5) # -> dh - * #Reading DH parameters - * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet - * dh.generate_key! # -> dh with public and private key + * # Reading DH parameters + * dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only + * dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair */ static VALUE ossl_dh_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; + int type; DH *dh; - int g = 2; - BIO *in; - VALUE arg, gen; - - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) { - dh = DH_new(); - } - else if (RB_INTEGER_TYPE_P(arg)) { - if (!NIL_P(gen)) { - g = NUM2INT(gen); - } - if (!(dh = dh_generate(NUM2INT(arg), g))) { - ossl_raise(eDHError, NULL); - } + BIO *in = NULL; + VALUE arg; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + + /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */ + if (rb_scan_args(argc, argv, "01", &arg) == 0) { + dh = DH_new(); + if (!dh) + ossl_raise(eDHError, "DH_new"); + goto legacy; } - else { - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(&arg); - dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); - if (!dh){ - OSSL_BIO_reset(in); - dh = d2i_DHparams_bio(in, NULL); - } - BIO_free(in); - if (!dh) { - ossl_raise(eDHError, NULL); - } + + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* + * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic + * routine does not support DER-encoded parameters + */ + dh = d2i_DHparams_bio(in, NULL); + if (dh) + goto legacy; + OSSL_BIO_reset(in); + + pkey = ossl_pkey_read_generic(in, Qnil); + BIO_free(in); + if (!pkey) + ossl_raise(eDHError, "could not parse pkey"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_DH) { + EVP_PKEY_free(pkey); + rb_raise(eDHError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } - if (!EVP_PKEY_assign_DH(pkey, dh)) { - DH_free(dh); - ossl_raise(eDHError, NULL); + RTYPEDDATA_DATA(self) = pkey; + return self; + + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { + EVP_PKEY_free(pkey); + DH_free(dh); + ossl_raise(eDHError, "EVP_PKEY_assign_DH"); } + RTYPEDDATA_DATA(self) = pkey; return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_dh_initialize_copy(VALUE self, VALUE other) { @@ -247,15 +135,14 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) DH *dh, *dh_other; const BIGNUM *pub, *priv; - GetPKey(self, pkey); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) - ossl_raise(eDHError, "DH already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); GetDH(other, dh_other); dh = DHparams_dup(dh_other); if (!dh) ossl_raise(eDHError, "DHparams_dup"); - EVP_PKEY_assign_DH(pkey, dh); DH_get0_key(dh_other, &pub, &priv); if (pub) { @@ -270,8 +157,16 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) DH_set0_key(dh, pub2, priv2); } + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { + EVP_PKEY_free(pkey); + DH_free(dh); + ossl_raise(eDHError, "EVP_PKEY_assign_DH"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -403,72 +298,6 @@ ossl_dh_get_params(VALUE self) return hash; } -/* - * call-seq: - * dh.to_text -> aString - * - * Prints all parameters of key to buffer - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dh_to_text(VALUE self) -{ - DH *dh; - BIO *out; - VALUE str; - - GetDH(self, dh); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDHError, NULL); - } - if (!DHparams_print(out, dh)) { - BIO_free(out); - ossl_raise(eDHError, NULL); - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * dh.public_key -> aDH - * - * Returns a new DH instance that carries just the public information, i.e. - * the prime _p_ and the generator _g_, but no public/private key yet. Such - * a pair may be generated using DH#generate_key!. The "public key" needed - * for a key exchange with DH#compute_key is considered as per-session - * information and may be retrieved with DH#pub_key once a key pair has - * been generated. - * If the current instance already contains private information (and thus a - * valid public/private key pair), this information will no longer be present - * in the new instance generated by DH#public_key. This feature is helpful for - * publishing the Diffie-Hellman parameters without leaking any of the private - * per-session information. - * - * === Example - * dh = OpenSSL::PKey::DH.new(2048) # has public and private key set - * public_key = dh.public_key # contains only prime and generator - * parameters = public_key.to_der # it's safe to publish this - */ -static VALUE -ossl_dh_to_public_key(VALUE self) -{ - DH *orig_dh, *dh; - VALUE obj; - - GetDH(self, orig_dh); - dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */ - obj = dh_instance(rb_obj_class(self), dh); - if (obj == Qfalse) { - DH_free(dh); - ossl_raise(eDHError, NULL); - } - - return obj; -} - /* * call-seq: * dh.params_ok? -> true | false @@ -476,80 +305,38 @@ ossl_dh_to_public_key(VALUE self) * Validates the Diffie-Hellman parameters associated with this instance. * It checks whether a safe prime and a suitable generator are used. If this * is not the case, +false+ is returned. + * + * See also the man page EVP_PKEY_param_check(3). */ static VALUE ossl_dh_check_params(VALUE self) { - DH *dh; - int codes; - - GetDH(self, dh); - if (!DH_check(dh, &codes)) { - return Qfalse; - } - - return codes == 0 ? Qtrue : Qfalse; -} + int ret; +#ifdef HAVE_EVP_PKEY_CHECK + EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; -/* - * call-seq: - * dh.generate_key! -> self - * - * Generates a private and public key unless a private key already exists. - * If this DH instance was generated from public DH parameters (e.g. by - * encoding the result of DH#public_key), then this method needs to be - * called first in order to generate the per-session keys before performing - * the actual key exchange. - * - * === Example - * dh = OpenSSL::PKey::DH.new(2048) - * public_key = dh.public_key #contains no private/public key yet - * public_key.generate_key! - * puts public_key.private? # => true - */ -static VALUE -ossl_dh_generate_key(VALUE self) -{ + GetPKey(self, pkey); + pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!pctx) + ossl_raise(eDHError, "EVP_PKEY_CTX_new"); + ret = EVP_PKEY_param_check(pctx); + EVP_PKEY_CTX_free(pctx); +#else DH *dh; + int codes; GetDH(self, dh); - if (!DH_generate_key(dh)) - ossl_raise(eDHError, "Failed to generate key"); - return self; -} - -/* - * call-seq: - * dh.compute_key(pub_bn) -> aString - * - * Returns a String containing a shared secret computed from the other party's public value. - * See DH_compute_key() for further information. - * - * === Parameters - * * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by - * DH#public_key as that contains the DH parameters only. - */ -static VALUE -ossl_dh_compute_key(VALUE self, VALUE pub) -{ - DH *dh; - const BIGNUM *pub_key, *dh_p; - VALUE str; - int len; + ret = DH_check(dh, &codes) == 1 && codes == 0; +#endif - GetDH(self, dh); - DH_get0_pqg(dh, &dh_p, NULL, NULL); - if (!dh_p) - ossl_raise(eDHError, "incomplete DH"); - pub_key = GetBNPtr(pub); - len = DH_size(dh); - str = rb_str_new(0, len); - if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) { - ossl_raise(eDHError, NULL); + if (ret == 1) + return Qtrue; + else { + /* DH_check_ex() will put error entry on failure */ + ossl_clear_error(); + return Qfalse; } - rb_str_set_len(str, len); - - return str; } /* @@ -606,30 +393,33 @@ Init_ossl_dh(void) * The per-session private key, an OpenSSL::BN. * * === Example of a key exchange - * dh1 = OpenSSL::PKey::DH.new(2048) - * der = dh1.public_key.to_der #you may send this publicly to the participating party - * dh2 = OpenSSL::PKey::DH.new(der) - * dh2.generate_key! #generate the per-session key pair - * symm_key1 = dh1.compute_key(dh2.pub_key) - * symm_key2 = dh2.compute_key(dh1.pub_key) + * # you may send the parameters (der) and own public key (pub1) publicly + * # to the participating party + * dh1 = OpenSSL::PKey::DH.new(2048) + * der = dh1.to_der + * pub1 = dh1.pub_key * - * puts symm_key1 == symm_key2 # => true + * # the other party generates its per-session key pair + * dhparams = OpenSSL::PKey::DH.new(der) + * dh2 = OpenSSL::PKey.generate_key(dhparams) + * pub2 = dh2.pub_key + * + * symm_key1 = dh1.compute_key(pub2) + * symm_key2 = dh2.compute_key(pub1) + * puts symm_key1 == symm_key2 # => true */ cDH = rb_define_class_under(mPKey, "DH", cPKey); - rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1); +#endif rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); - rb_define_method(cDH, "to_text", ossl_dh_to_text, 0); rb_define_method(cDH, "export", ossl_dh_export, 0); rb_define_alias(cDH, "to_pem", "export"); rb_define_alias(cDH, "to_s", "export"); rb_define_method(cDH, "to_der", ossl_dh_to_der, 0); - rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0); rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0); - rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0); - rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); DEF_OSSL_PKEY_BN(cDH, dh, p); DEF_OSSL_PKEY_BN(cDH, dh, q); diff --git a/ruby/ext/openssl/ossl_pkey_dsa.c b/ruby/ext/openssl/ossl_pkey_dsa.c index 56cc9dd4f..25404aa7f 100644 --- a/ruby/ext/openssl/ossl_pkey_dsa.c +++ b/ruby/ext/openssl/ossl_pkey_dsa.c @@ -43,246 +43,131 @@ DSA_PRIVATE(VALUE obj, DSA *dsa) VALUE cDSA; VALUE eDSAError; -/* - * Public - */ -static VALUE -dsa_instance(VALUE klass, DSA *dsa) -{ - EVP_PKEY *pkey; - VALUE obj; - - if (!dsa) { - return Qfalse; - } - obj = NewPKey(klass); - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - SetPKey(obj, pkey); - - return obj; -} - -VALUE -ossl_dsa_new(EVP_PKEY *pkey) -{ - VALUE obj; - - if (!pkey) { - obj = dsa_instance(cDSA, DSA_new()); - } else { - obj = NewPKey(cDSA); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { - ossl_raise(rb_eTypeError, "Not a DSA key!"); - } - SetPKey(obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eDSAError, NULL); - } - - return obj; -} - /* * Private */ -struct dsa_blocking_gen_arg { - DSA *dsa; - int size; - int *counter; - unsigned long *h; - BN_GENCB *cb; - int result; -}; - -static void * -dsa_blocking_gen(void *arg) -{ - struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg; - gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0, - gen->counter, gen->h, gen->cb); - return 0; -} - -static DSA * -dsa_generate(int size) -{ - struct ossl_generate_cb_arg cb_arg = { 0 }; - struct dsa_blocking_gen_arg gen_arg; - DSA *dsa = DSA_new(); - BN_GENCB *cb = BN_GENCB_new(); - int counter; - unsigned long h; - - if (!dsa || !cb) { - DSA_free(dsa); - BN_GENCB_free(cb); - return NULL; - } - - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg); - gen_arg.dsa = dsa; - gen_arg.size = size; - gen_arg.counter = &counter; - gen_arg.h = &h; - gen_arg.cb = cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - dsa_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - - BN_GENCB_free(cb); - if (!gen_arg.result) { - DSA_free(dsa); - if (cb_arg.state) { - /* Clear OpenSSL error queue before re-raising. By the way, the - * documentation of DSA_generate_parameters_ex() says the error code - * can be obtained by ERR_get_error(), but the default - * implementation, dsa_builtin_paramgen() doesn't put any error... */ - ossl_clear_error(); - rb_jump_tag(cb_arg.state); - } - return NULL; - } - - if (!DSA_generate_key(dsa)) { - DSA_free(dsa); - return NULL; - } - - return dsa; -} - -/* - * call-seq: - * DSA.generate(size) -> dsa - * - * Creates a new DSA instance by generating a private/public key pair - * from scratch. - * - * === Parameters - * * _size_ is an integer representing the desired key size. - * - */ -static VALUE -ossl_dsa_s_generate(VALUE klass, VALUE size) -{ - DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */ - VALUE obj = dsa_instance(klass, dsa); - - if (obj == Qfalse) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); - } - - return obj; -} - /* * call-seq: * DSA.new -> dsa - * DSA.new(size) -> dsa * DSA.new(string [, pass]) -> dsa + * DSA.new(size) -> dsa * * Creates a new DSA instance by reading an existing key from _string_. * - * === Parameters - * * _size_ is an integer representing the desired key size. - * * _string_ contains a DER or PEM encoded key. - * * _pass_ is a string that contains an optional password. + * If called without arguments, creates a new instance with no key components + * set. They can be set individually by #set_pqg and #set_key. * - * === Examples - * DSA.new -> dsa - * DSA.new(1024) -> dsa - * DSA.new(File.read('dsa.pem')) -> dsa - * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa + * If called with a String, tries to parse as DER or PEM encoding of a \DSA key. + * See also OpenSSL::PKey.read which can parse keys of any kinds. * + * If called with a number, generates random parameters and a key pair. This + * form works as an alias of DSA.generate. + * + * +string+:: + * A String that contains a DER or PEM encoded key. + * +pass+:: + * A String that contains an optional password. + * +size+:: + * See DSA.generate. + * + * Examples: + * p OpenSSL::PKey::DSA.new(1024) + * #=> # + * + * p OpenSSL::PKey::DSA.new(File.read('dsa.pem')) + * #=> # + * + * p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword') + * #=> # */ static VALUE ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; DSA *dsa; - BIO *in; + BIO *in = NULL; VALUE arg, pass; + int type; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { + /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ + rb_scan_args(argc, argv, "02", &arg, &pass); + if (argc == 0) { dsa = DSA_new(); + if (!dsa) + ossl_raise(eDSAError, "DSA_new"); + goto legacy; } - else if (RB_INTEGER_TYPE_P(arg)) { - if (!(dsa = dsa_generate(NUM2INT(arg)))) { - ossl_raise(eDSAError, NULL); - } - } - else { - pass = ossl_pem_passwd_value(pass); - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(&arg); - dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); - if (!dsa) { - OSSL_BIO_reset(in); - dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); - dsa = d2i_DSAPrivateKey_bio(in, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); - dsa = d2i_DSA_PUBKEY_bio(in, NULL); - } - if (!dsa) { - OSSL_BIO_reset(in); -#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ - (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u)) - dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); -#undef PEM_read_bio_DSAPublicKey - } - BIO_free(in); - if (!dsa) { - ossl_clear_error(); - ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); - } - } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); + + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* DER-encoded DSAPublicKey format isn't supported by the generic routine */ + dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey, + PEM_STRING_DSA_PUBLIC, + in, NULL, NULL, NULL); + if (dsa) + goto legacy; + OSSL_BIO_reset(in); + + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) + ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_DSA) { + EVP_PKEY_free(pkey); + rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } + RTYPEDDATA_DATA(self) = pkey; + return self; + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) { + EVP_PKEY_free(pkey); + DSA_free(dsa); + ossl_raise(eDSAError, "EVP_PKEY_assign_DSA"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_dsa_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; DSA *dsa, *dsa_new; - GetPKey(self, pkey); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) - ossl_raise(eDSAError, "DSA already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); GetDSA(other, dsa); - dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa); + dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, + (d2i_of_void *)d2i_DSAPrivateKey, + (char *)dsa); if (!dsa_new) ossl_raise(eDSAError, "ASN1_dup"); - EVP_PKEY_assign_DSA(pkey, dsa_new); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) { + EVP_PKEY_free(pkey); + DSA_free(dsa_new); + ossl_raise(eDSAError, "EVP_PKEY_assign_DSA"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -341,34 +226,12 @@ static VALUE ossl_dsa_export(int argc, VALUE *argv, VALUE self) { DSA *dsa; - BIO *out; - const EVP_CIPHER *ciph = NULL; - VALUE cipher, pass, str; GetDSA(self, dsa); - rb_scan_args(argc, argv, "02", &cipher, &pass); - if (!NIL_P(cipher)) { - ciph = ossl_evp_get_cipherbyname(cipher); - pass = ossl_pem_passwd_value(pass); - } - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDSAError, NULL); - } - if (DSA_HAS_PRIVATE(dsa)) { - if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0, - ossl_pem_passwd_cb, (void *)pass)){ - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - } else { - if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) { - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - } - str = ossl_membio2str(out); - - return str; + if (DSA_HAS_PRIVATE(dsa)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else + return ossl_pkey_export_spki(self, 0); } /* @@ -382,25 +245,12 @@ static VALUE ossl_dsa_to_der(VALUE self) { DSA *dsa; - int (*i2d_func)(DSA *, unsigned char **); - unsigned char *p; - long len; - VALUE str; GetDSA(self, dsa); - if(DSA_HAS_PRIVATE(dsa)) - i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey; + if (DSA_HAS_PRIVATE(dsa)) + return ossl_pkey_export_traditional(0, NULL, self, 1); else - i2d_func = i2d_DSA_PUBKEY; - if((len = i2d_func(dsa, NULL)) <= 0) - ossl_raise(eDSAError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(dsa, &p) < 0) - ossl_raise(eDSAError, NULL); - ossl_str_adjust(str, p); - - return str; + return ossl_pkey_export_spki(self, 1); } @@ -433,158 +283,6 @@ ossl_dsa_get_params(VALUE self) return hash; } -/* - * call-seq: - * dsa.to_text -> aString - * - * Prints all parameters of key to buffer - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dsa_to_text(VALUE self) -{ - DSA *dsa; - BIO *out; - VALUE str; - - GetDSA(self, dsa); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eDSAError, NULL); - } - if (!DSA_print(out, dsa, 0)) { /* offset = 0 */ - BIO_free(out); - ossl_raise(eDSAError, NULL); - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * dsa.public_key -> aDSA - * - * Returns a new DSA instance that carries just the public key information. - * If the current instance has also private key information, this will no - * longer be present in the new instance. This feature is helpful for - * publishing the public key information without leaking any of the private - * information. - * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information - * pub_key = dsa.public_key # has only the public part available - * pub_key_der = pub_key.to_der # it's safe to publish this - * - * - */ -static VALUE -ossl_dsa_to_public_key(VALUE self) -{ - EVP_PKEY *pkey; - DSA *dsa; - VALUE obj; - - GetPKeyDSA(self, pkey); - /* err check performed by dsa_instance */ -#define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \ - (i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa)) - dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey)); -#undef DSAPublicKey_dup - obj = dsa_instance(rb_obj_class(self), dsa); - if (obj == Qfalse) { - DSA_free(dsa); - ossl_raise(eDSAError, NULL); - } - return obj; -} - -/* - * call-seq: - * dsa.syssign(string) -> aString - * - * Computes and returns the DSA signature of _string_, where _string_ is - * expected to be an already-computed message digest of the original input - * data. The signature is issued using the private key of this DSA instance. - * - * === Parameters - * * _string_ is a message digest of the original input data to be signed. - * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) - * doc = "Sign me" - * digest = OpenSSL::Digest::SHA1.digest(doc) - * sig = dsa.syssign(digest) - * - * - */ -static VALUE -ossl_dsa_sign(VALUE self, VALUE data) -{ - DSA *dsa; - const BIGNUM *dsa_q; - unsigned int buf_len; - VALUE str; - - GetDSA(self, dsa); - DSA_get0_pqg(dsa, NULL, &dsa_q, NULL); - if (!dsa_q) - ossl_raise(eDSAError, "incomplete DSA"); - if (!DSA_PRIVATE(self, dsa)) - ossl_raise(eDSAError, "Private DSA key needed!"); - StringValue(data); - str = rb_str_new(0, DSA_size(dsa)); - if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data), - (unsigned char *)RSTRING_PTR(str), - &buf_len, dsa)) { /* type is ignored (0) */ - ossl_raise(eDSAError, NULL); - } - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * dsa.sysverify(digest, sig) -> true | false - * - * Verifies whether the signature is valid given the message digest input. It - * does so by validating _sig_ using the public key of this DSA instance. - * - * === Parameters - * * _digest_ is a message digest of the original input data to be signed - * * _sig_ is a DSA signature value - * - * === Example - * dsa = OpenSSL::PKey::DSA.new(2048) - * doc = "Sign me" - * digest = OpenSSL::Digest::SHA1.digest(doc) - * sig = dsa.syssign(digest) - * puts dsa.sysverify(digest, sig) # => true - * - */ -static VALUE -ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) -{ - DSA *dsa; - int ret; - - GetDSA(self, dsa); - StringValue(digest); - StringValue(sig); - /* type is ignored (0) */ - ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest), - (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa); - if (ret < 0) { - ossl_raise(eDSAError, NULL); - } - else if (ret == 1) { - return Qtrue; - } - - return Qfalse; -} - /* * Document-method: OpenSSL::PKey::DSA#set_pqg * call-seq: @@ -630,20 +328,17 @@ Init_ossl_dsa(void) */ cDSA = rb_define_class_under(mPKey, "DSA", cPKey); - rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1); +#endif rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); - rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0); rb_define_method(cDSA, "export", ossl_dsa_export, -1); rb_define_alias(cDSA, "to_pem", "export"); rb_define_alias(cDSA, "to_s", "export"); rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0); - rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0); - rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1); - rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2); DEF_OSSL_PKEY_BN(cDSA, dsa, p); DEF_OSSL_PKEY_BN(cDSA, dsa, q); diff --git a/ruby/ext/openssl/ossl_pkey_ec.c b/ruby/ext/openssl/ossl_pkey_ec.c index 8bb611248..dee215447 100644 --- a/ruby/ext/openssl/ossl_pkey_ec.c +++ b/ruby/ext/openssl/ossl_pkey_ec.c @@ -47,12 +47,7 @@ VALUE eEC_GROUP; VALUE cEC_POINT; VALUE eEC_POINT; -static ID s_GFp; -static ID s_GFp_simple; -static ID s_GFp_mont; -static ID s_GFp_nist; -static ID s_GF2m; -static ID s_GF2m_simple; +static ID s_GFp, s_GF2m; static ID ID_uncompressed; static ID ID_compressed; @@ -63,47 +58,6 @@ static ID id_i_group; static VALUE ec_group_new(const EC_GROUP *group); static VALUE ec_point_new(const EC_POINT *point, const EC_GROUP *group); -static VALUE ec_instance(VALUE klass, EC_KEY *ec) -{ - EVP_PKEY *pkey; - VALUE obj; - - if (!ec) { - return Qfalse; - } - obj = NewPKey(klass); - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - SetPKey(obj, pkey); - - return obj; -} - -VALUE ossl_ec_new(EVP_PKEY *pkey) -{ - VALUE obj; - - if (!pkey) { - obj = ec_instance(cEC, EC_KEY_new()); - } else { - obj = NewPKey(cEC); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { - ossl_raise(rb_eTypeError, "Not a EC key!"); - } - SetPKey(obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eECError, NULL); - } - - return obj; -} - /* * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String * representing an OID. @@ -150,16 +104,20 @@ ec_key_new_from_group(VALUE arg) static VALUE ossl_ec_key_s_generate(VALUE klass, VALUE arg) { + EVP_PKEY *pkey; EC_KEY *ec; VALUE obj; - ec = ec_key_new_from_group(arg); + obj = rb_obj_alloc(klass); - obj = ec_instance(klass, ec); - if (obj == Qfalse) { - EC_KEY_free(ec); - ossl_raise(eECError, NULL); + ec = ec_key_new_from_group(arg); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { + EVP_PKEY_free(pkey); + EC_KEY_free(ec); + ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); } + RTYPEDDATA_DATA(obj) = pkey; if (!EC_KEY_generate_key(ec)) ossl_raise(eECError, "EC_KEY_generate_key"); @@ -182,81 +140,82 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; EC_KEY *ec; + BIO *in; VALUE arg, pass; + int type; - GetPKey(self, pkey); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) - ossl_raise(eECError, "EC_KEY already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); rb_scan_args(argc, argv, "02", &arg, &pass); - if (NIL_P(arg)) { if (!(ec = EC_KEY_new())) - ossl_raise(eECError, NULL); - } else if (rb_obj_is_kind_of(arg, cEC)) { - EC_KEY *other_ec = NULL; - - GetEC(arg, other_ec); - if (!(ec = EC_KEY_dup(other_ec))) - ossl_raise(eECError, NULL); - } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { - ec = ec_key_new_from_group(arg); - } else { - BIO *in; - - pass = ossl_pem_passwd_value(pass); - in = ossl_obj2bio(&arg); + ossl_raise(eECError, "EC_KEY_new"); + goto legacy; + } + else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + ec = ec_key_new_from_group(arg); + goto legacy; + } - ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); - if (!ec) { - OSSL_BIO_reset(in); - ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_ECPrivateKey_bio(in, NULL); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_EC_PUBKEY_bio(in, NULL); - } - BIO_free(in); + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); - if (!ec) { - ossl_clear_error(); - ec = ec_key_new_from_group(arg); - } + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) { + ossl_clear_error(); + ec = ec_key_new_from_group(arg); + goto legacy; } - if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { - EC_KEY_free(ec); - ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); + 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)); } + RTYPEDDATA_DATA(self) = pkey; + return self; + legacy: + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { + EVP_PKEY_free(pkey); + EC_KEY_free(ec); + ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_ec_key_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; EC_KEY *ec, *ec_new; - GetPKey(self, pkey); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) - ossl_raise(eECError, "EC already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); GetEC(other, ec); ec_new = EC_KEY_dup(ec); if (!ec_new) ossl_raise(eECError, "EC_KEY_dup"); - if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) { - EC_KEY_free(ec_new); - ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) { + EC_KEY_free(ec_new); + ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -289,6 +248,9 @@ ossl_ec_key_get_group(VALUE self) static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v) { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; EC_GROUP *group; @@ -299,6 +261,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v) ossl_raise(eECError, "EC_KEY_set_group"); return group_v; +#endif } /* @@ -327,6 +290,9 @@ static VALUE ossl_ec_key_get_private_key(VALUE self) */ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; BIGNUM *bn = NULL; @@ -340,11 +306,13 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) case 0: if (bn == NULL) break; + /* fallthrough */ default: ossl_raise(eECError, "EC_KEY_set_private_key"); } return private_key; +#endif } /* @@ -373,6 +341,9 @@ static VALUE ossl_ec_key_get_public_key(VALUE self) */ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; EC_POINT *point = NULL; @@ -386,11 +357,13 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) case 0: if (point == NULL) break; + /* fallthrough */ default: ossl_raise(eECError, "EC_KEY_set_public_key"); } return public_key; +#endif } /* @@ -425,66 +398,6 @@ static VALUE ossl_ec_key_is_private(VALUE self) return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse; } -static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format) -{ - EC_KEY *ec; - BIO *out; - int i = -1; - int private = 0; - VALUE str; - const EVP_CIPHER *cipher = NULL; - - GetEC(self, ec); - - if (EC_KEY_get0_public_key(ec) == NULL) - ossl_raise(eECError, "can't export - no public key set"); - - if (EC_KEY_check_key(ec) != 1) - ossl_raise(eECError, "can't export - EC_KEY_check_key failed"); - - if (EC_KEY_get0_private_key(ec)) - private = 1; - - if (!NIL_P(ciph)) { - cipher = ossl_evp_get_cipherbyname(ciph); - pass = ossl_pem_passwd_value(pass); - } - - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eECError, "BIO_new(BIO_s_mem())"); - - switch(format) { - case EXPORT_PEM: - if (private) { - i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass); - } else { - i = PEM_write_bio_EC_PUBKEY(out, ec); - } - - break; - case EXPORT_DER: - if (private) { - i = i2d_ECPrivateKey_bio(out, ec); - } else { - i = i2d_EC_PUBKEY_bio(out, ec); - } - - break; - default: - BIO_free(out); - ossl_raise(rb_eRuntimeError, "unknown format (internal error)"); - } - - if (i != 1) { - BIO_free(out); - ossl_raise(eECError, "outlen=%d", i); - } - - str = ossl_membio2str(out); - - return str; -} - /* * call-seq: * key.export([cipher, pass_phrase]) => String @@ -495,11 +408,16 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma * instance. Note that encryption will only be effective for a private key, * public keys will always be encoded in plain text. */ -static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self) +static VALUE +ossl_ec_key_export(int argc, VALUE *argv, VALUE self) { - VALUE cipher, passwd; - rb_scan_args(argc, argv, "02", &cipher, &passwd); - return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM); + EC_KEY *ec; + + GetEC(self, ec); + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else + return ossl_pkey_export_spki(self, 0); } /* @@ -508,36 +426,17 @@ static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self) * * See the OpenSSL documentation for i2d_ECPrivateKey_bio() */ -static VALUE ossl_ec_key_to_der(VALUE self) -{ - return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER); -} - -/* - * call-seq: - * key.to_text => String - * - * See the OpenSSL documentation for EC_KEY_print() - */ -static VALUE ossl_ec_key_to_text(VALUE self) +static VALUE +ossl_ec_key_to_der(VALUE self) { EC_KEY *ec; - BIO *out; - VALUE str; GetEC(self, ec); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eECError, "BIO_new(BIO_s_mem())"); - } - if (!EC_KEY_print(out, ec, 0)) { - BIO_free(out); - ossl_raise(eECError, "EC_KEY_print"); - } - str = ossl_membio2str(out); - - return str; + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(0, NULL, self, 1); + else + return ossl_pkey_export_spki(self, 1); } - /* * call-seq: * key.generate_key! => self @@ -554,6 +453,9 @@ static VALUE ossl_ec_key_to_text(VALUE self) */ static VALUE ossl_ec_key_generate_key(VALUE self) { +#if OSSL_OPENSSL_PREREQ(3, 0, 0) + rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); +#else EC_KEY *ec; GetEC(self, ec); @@ -561,116 +463,50 @@ static VALUE ossl_ec_key_generate_key(VALUE self) ossl_raise(eECError, "EC_KEY_generate_key"); return self; +#endif } /* - * call-seq: - * key.check_key => true + * call-seq: + * key.check_key => true * - * Raises an exception if the key is invalid. + * Raises an exception if the key is invalid. * - * See the OpenSSL documentation for EC_KEY_check_key() + * See also the man page EVP_PKEY_public_check(3). */ static VALUE ossl_ec_key_check_key(VALUE self) { +#ifdef HAVE_EVP_PKEY_CHECK + EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; + int ret; + + GetPKey(self, pkey); + pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); + if (!pctx) + ossl_raise(eDHError, "EVP_PKEY_CTX_new"); + ret = EVP_PKEY_public_check(pctx); + EVP_PKEY_CTX_free(pctx); + if (ret != 1) + ossl_raise(eECError, "EVP_PKEY_public_check"); +#else EC_KEY *ec; GetEC(self, ec); if (EC_KEY_check_key(ec) != 1) ossl_raise(eECError, "EC_KEY_check_key"); +#endif return Qtrue; } -/* - * call-seq: - * key.dh_compute_key(pubkey) => String - * - * See the OpenSSL documentation for ECDH_compute_key() - */ -static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey) -{ - EC_KEY *ec; - EC_POINT *point; - int buf_len; - VALUE str; - - GetEC(self, ec); - GetECPoint(pubkey, point); - -/* BUG: need a way to figure out the maximum string size */ - buf_len = 1024; - str = rb_str_new(0, buf_len); -/* BUG: take KDF as a block */ - buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL); - if (buf_len < 0) - ossl_raise(eECError, "ECDH_compute_key"); - - rb_str_resize(str, buf_len); - - return str; -} - -/* sign_setup */ - -/* - * call-seq: - * key.dsa_sign_asn1(data) => String - * - * See the OpenSSL documentation for ECDSA_sign() - */ -static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data) -{ - EC_KEY *ec; - unsigned int buf_len; - VALUE str; - - GetEC(self, ec); - StringValue(data); - - if (EC_KEY_get0_private_key(ec) == NULL) - ossl_raise(eECError, "Private EC key needed!"); - - str = rb_str_new(0, ECDSA_size(ec)); - if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1) - ossl_raise(eECError, "ECDSA_sign"); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * key.dsa_verify_asn1(data, sig) => true or false - * - * See the OpenSSL documentation for ECDSA_verify() - */ -static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig) -{ - EC_KEY *ec; - - GetEC(self, ec); - StringValue(data); - StringValue(sig); - - switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: break; - } - - ossl_raise(eECError, "ECDSA_verify"); - - UNREACHABLE; -} - /* * OpenSSL::PKey::EC::Group */ static void ossl_ec_group_free(void *ptr) { - EC_GROUP_clear_free(ptr); + EC_GROUP_free(ptr); } static const rb_data_type_t ossl_ec_group_type = { @@ -706,20 +542,11 @@ ec_group_new(const EC_GROUP *group) * call-seq: * OpenSSL::PKey::EC::Group.new(ec_group) * OpenSSL::PKey::EC::Group.new(pem_or_der_encoded) - * OpenSSL::PKey::EC::Group.new(ec_method) * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b) * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b) * * Creates a new EC::Group object. * - * _ec_method_ is a symbol that represents an EC_METHOD. Currently the following - * are supported: - * - * * :GFp_simple - * * :GFp_mont - * * :GFp_nist - * * :GF2m_simple - * * If the first argument is :GFp or :GF2m, creates a new curve with given * parameters. */ @@ -734,29 +561,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) { case 1: - if (SYMBOL_P(arg1)) { - const EC_METHOD *method = NULL; - ID id = SYM2ID(arg1); - - if (id == s_GFp_simple) { - method = EC_GFp_simple_method(); - } else if (id == s_GFp_mont) { - method = EC_GFp_mont_method(); - } else if (id == s_GFp_nist) { - method = EC_GFp_nist_method(); -#if !defined(OPENSSL_NO_EC2M) - } else if (id == s_GF2m_simple) { - method = EC_GF2m_simple_method(); -#endif - } - - if (method) { - if ((group = EC_GROUP_new(method)) == NULL) - ossl_raise(eEC_GROUP, "EC_GROUP_new"); - } else { - ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple"); - } - } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { + if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { const EC_GROUP *arg1_group; GetECGroup(arg1, arg1_group); @@ -820,8 +625,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) ossl_raise(rb_eArgError, "wrong number of arguments"); } - if (group == NULL) - ossl_raise(eEC_GROUP, ""); + ASSUME(group); RTYPEDDATA_DATA(self) = group; return self; @@ -1475,6 +1279,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self) /* * call-seq: * point.make_affine! => self + * + * This method is deprecated and should not be used. This is a no-op. */ static VALUE ossl_ec_point_make_affine(VALUE self) { @@ -1484,8 +1290,11 @@ static VALUE ossl_ec_point_make_affine(VALUE self) GetECPoint(self, point); GetECPointGroup(self, group); + rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated"); +#if !OSSL_OPENSSL_PREREQ(3, 0, 0) if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) ossl_raise(cEC_POINT, "EC_POINT_make_affine"); +#endif return self; } @@ -1562,6 +1371,34 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form) return str; } +/* + * call-seq: + * point.add(point) => point + * + * Performs elliptic curve point addition. + */ +static VALUE ossl_ec_point_add(VALUE self, VALUE other) +{ + EC_POINT *point_self, *point_other, *point_result; + const EC_GROUP *group; + VALUE group_v = rb_attr_get(self, id_i_group); + VALUE result; + + GetECPoint(self, point_self); + GetECPoint(other, point_other); + GetECGroup(group_v, group); + + result = rb_obj_alloc(cEC_POINT); + ossl_ec_point_initialize(1, &group_v, result); + GetECPoint(result, point_result); + + if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) { + ossl_raise(eEC_POINT, "EC_POINT_add"); + } + + return result; +} + /* * call-seq: * point.mul(bn1 [, bn2]) => point @@ -1603,6 +1440,10 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) 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] | ... @@ -1617,6 +1458,9 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) 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); @@ -1642,6 +1486,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) ALLOCV_END(tmp_b); ALLOCV_END(tmp_p); +#endif } return result; @@ -1682,10 +1527,6 @@ void Init_ossl_ec(void) s_GFp = rb_intern("GFp"); s_GF2m = rb_intern("GF2m"); - s_GFp_simple = rb_intern("GFp_simple"); - s_GFp_mont = rb_intern("GFp_mont"); - s_GFp_nist = rb_intern("GFp_nist"); - s_GF2m_simple = rb_intern("GF2m_simple"); ID_uncompressed = rb_intern("uncompressed"); ID_compressed = rb_intern("compressed"); @@ -1700,8 +1541,9 @@ void Init_ossl_ec(void) rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1); rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1); -/* copy/dup/cmp */ +#endif rb_define_method(cEC, "group", ossl_ec_key_get_group, 0); rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1); @@ -1724,15 +1566,9 @@ void Init_ossl_ec(void) rb_define_alias(cEC, "generate_key", "generate_key!"); rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0); - rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1); - rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1); - rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2); -/* do_sign/do_verify */ - rb_define_method(cEC, "export", ossl_ec_key_export, -1); rb_define_alias(cEC, "to_pem", "export"); rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0); - rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0); rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc); @@ -1786,6 +1622,7 @@ void Init_ossl_ec(void) /* all the other methods */ rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1); + rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1); rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1); id_i_group = rb_intern("@group"); diff --git a/ruby/ext/openssl/ossl_pkey_rsa.c b/ruby/ext/openssl/ossl_pkey_rsa.c index 4800fb271..4d66010f4 100644 --- a/ruby/ext/openssl/ossl_pkey_rsa.c +++ b/ruby/ext/openssl/ossl_pkey_rsa.c @@ -26,10 +26,10 @@ static inline int RSA_HAS_PRIVATE(RSA *rsa) { - const BIGNUM *p, *q; + const BIGNUM *e, *d; - RSA_get0_factors(rsa, &p, &q); - return p && q; /* d? why? */ + RSA_get0_key(rsa, NULL, &e, &d); + return e && d; } static inline int @@ -44,175 +44,31 @@ RSA_PRIVATE(VALUE obj, RSA *rsa) VALUE cRSA; VALUE eRSAError; -/* - * Public - */ -static VALUE -rsa_instance(VALUE klass, RSA *rsa) -{ - EVP_PKEY *pkey; - VALUE obj; - - if (!rsa) { - return Qfalse; - } - obj = NewPKey(klass); - if (!(pkey = EVP_PKEY_new())) { - return Qfalse; - } - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { - EVP_PKEY_free(pkey); - return Qfalse; - } - SetPKey(obj, pkey); - - return obj; -} - -VALUE -ossl_rsa_new(EVP_PKEY *pkey) -{ - VALUE obj; - - if (!pkey) { - obj = rsa_instance(cRSA, RSA_new()); - } - else { - obj = NewPKey(cRSA); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { - ossl_raise(rb_eTypeError, "Not a RSA key!"); - } - SetPKey(obj, pkey); - } - if (obj == Qfalse) { - ossl_raise(eRSAError, NULL); - } - - return obj; -} - /* * Private */ -struct rsa_blocking_gen_arg { - RSA *rsa; - BIGNUM *e; - int size; - BN_GENCB *cb; - int result; -}; - -static void * -rsa_blocking_gen(void *arg) -{ - struct rsa_blocking_gen_arg *gen = (struct rsa_blocking_gen_arg *)arg; - gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb); - return 0; -} - -static RSA * -rsa_generate(int size, unsigned long exp) -{ - int i; - struct ossl_generate_cb_arg cb_arg = { 0 }; - struct rsa_blocking_gen_arg gen_arg; - RSA *rsa = RSA_new(); - BIGNUM *e = BN_new(); - BN_GENCB *cb = BN_GENCB_new(); - - if (!rsa || !e || !cb) { - RSA_free(rsa); - BN_free(e); - BN_GENCB_free(cb); - return NULL; - } - for (i = 0; i < (int)sizeof(exp) * 8; ++i) { - if (exp & (1UL << i)) { - if (BN_set_bit(e, i) == 0) { - BN_free(e); - RSA_free(rsa); - BN_GENCB_free(cb); - return NULL; - } - } - } - - if (rb_block_given_p()) - cb_arg.yield = 1; - BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg); - gen_arg.rsa = rsa; - gen_arg.e = e; - gen_arg.size = size; - gen_arg.cb = cb; - if (cb_arg.yield == 1) { - /* we cannot release GVL when callback proc is supplied */ - rsa_blocking_gen(&gen_arg); - } else { - /* there's a chance to unblock */ - rb_thread_call_without_gvl(rsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); - } - - BN_GENCB_free(cb); - BN_free(e); - if (!gen_arg.result) { - RSA_free(rsa); - if (cb_arg.state) { - /* must clear OpenSSL error stack */ - ossl_clear_error(); - rb_jump_tag(cb_arg.state); - } - return NULL; - } - - return rsa; -} - /* * call-seq: - * RSA.generate(size) => RSA instance - * RSA.generate(size, exponent) => RSA instance + * RSA.new -> rsa + * RSA.new(encoded_key [, passphrase]) -> rsa + * RSA.new(encoded_key) { passphrase } -> rsa + * RSA.new(size [, exponent]) -> rsa * - * Generates an RSA keypair. _size_ is an integer representing the desired key - * size. Keys smaller than 1024 should be considered insecure. _exponent_ is - * an odd number normally 3, 17, or 65537. - */ -static VALUE -ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) -{ -/* why does this method exist? why can't initialize take an optional exponent? */ - RSA *rsa; - VALUE size, exp; - VALUE obj; - - rb_scan_args(argc, argv, "11", &size, &exp); - - rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp)); /* err handled by rsa_instance */ - obj = rsa_instance(klass, rsa); - - if (obj == Qfalse) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); - } - - return obj; -} - -/* - * call-seq: - * RSA.new(key_size) => RSA instance - * RSA.new(encoded_key) => RSA instance - * RSA.new(encoded_key, pass_phrase) => RSA instance + * Generates or loads an \RSA keypair. * - * Generates or loads an RSA keypair. If an integer _key_size_ is given it - * represents the desired key size. Keys less than 1024 bits should be - * considered insecure. + * If called without arguments, creates a new instance with no key components + * set. They can be set individually by #set_key, #set_factors, and + * #set_crt_params. * - * A key can instead be loaded from an _encoded_key_ which must be PEM or DER - * encoded. A _pass_phrase_ can be used to decrypt the key. If none is given - * OpenSSL will prompt for the pass phrase. + * If called with a String, tries to parse as DER or PEM encoding of an \RSA key. + * Note that, if _passphrase_ is not specified but the key is encrypted with a + * passphrase, \OpenSSL will prompt for it. + * See also OpenSSL::PKey.read which can parse keys of any kinds. * - * = Examples + * If called with a number, generates a new key pair. This form works as an + * alias of RSA.generate. * + * Examples: * OpenSSL::PKey::RSA.new 2048 * OpenSSL::PKey::RSA.new File.read 'rsa.pem' * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' @@ -222,74 +78,91 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; RSA *rsa; - BIO *in; + BIO *in = NULL; VALUE arg, pass; + int type; - GetPKey(self, pkey); - if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + + /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ + rb_scan_args(argc, argv, "02", &arg, &pass); + if (argc == 0) { rsa = RSA_new(); + if (!rsa) + ossl_raise(eRSAError, "RSA_new"); + goto legacy; } - else if (RB_INTEGER_TYPE_P(arg)) { - rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass)); - if (!rsa) ossl_raise(eRSAError, NULL); - } - else { - pass = ossl_pem_passwd_value(pass); - arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(&arg); - rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); - if (!rsa) { - OSSL_BIO_reset(in); - rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSAPrivateKey_bio(in, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSA_PUBKEY_bio(in, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); - } - if (!rsa) { - OSSL_BIO_reset(in); - rsa = d2i_RSAPublicKey_bio(in, NULL); - } - BIO_free(in); - if (!rsa) { - ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); - } - } - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); + + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + + /* First try RSAPublicKey format */ + rsa = d2i_RSAPublicKey_bio(in, NULL); + if (rsa) + goto legacy; + OSSL_BIO_reset(in); + rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); + if (rsa) + goto legacy; + OSSL_BIO_reset(in); + + /* Use the generic routine */ + pkey = ossl_pkey_read_generic(in, pass); + BIO_free(in); + if (!pkey) + ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); + + type = EVP_PKEY_base_id(pkey); + if (type != EVP_PKEY_RSA) { + EVP_PKEY_free(pkey); + rb_raise(eRSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } + RTYPEDDATA_DATA(self) = pkey; + return self; + legacy: + BIO_free(in); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) { + EVP_PKEY_free(pkey); + RSA_free(rsa); + ossl_raise(eRSAError, "EVP_PKEY_assign_RSA"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_rsa_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; RSA *rsa, *rsa_new; - GetPKey(self, pkey); - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) - ossl_raise(eRSAError, "RSA already initialized"); + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); GetRSA(other, rsa); - rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa); + rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, + (d2i_of_void *)d2i_RSAPrivateKey, + (char *)rsa); if (!rsa_new) ossl_raise(eRSAError, "ASN1_dup"); - EVP_PKEY_assign_RSA(pkey, rsa_new); + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) { + RSA_free(rsa_new); + ossl_raise(eRSAError, "EVP_PKEY_assign_RSA"); + } + RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -327,6 +200,21 @@ ossl_rsa_is_private(VALUE self) return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse; } +static int +can_export_rsaprivatekey(VALUE self) +{ + RSA *rsa; + 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); + + return n && e && d && p && q && dmp1 && dmq1 && iqmp; +} + /* * call-seq: * rsa.export([cipher, pass_phrase]) => PEM-format String @@ -340,37 +228,10 @@ ossl_rsa_is_private(VALUE self) static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) { - RSA *rsa; - BIO *out; - const EVP_CIPHER *ciph = NULL; - VALUE cipher, pass, str; - - GetRSA(self, rsa); - - rb_scan_args(argc, argv, "02", &cipher, &pass); - - if (!NIL_P(cipher)) { - ciph = ossl_evp_get_cipherbyname(cipher); - pass = ossl_pem_passwd_value(pass); - } - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eRSAError, NULL); - } - if (RSA_HAS_PRIVATE(rsa)) { - if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0, - ossl_pem_passwd_cb, (void *)pass)) { - BIO_free(out); - ossl_raise(eRSAError, NULL); - } - } else { - if (!PEM_write_bio_RSA_PUBKEY(out, rsa)) { - BIO_free(out); - ossl_raise(eRSAError, NULL); - } - } - str = ossl_membio2str(out); - - return str; + if (can_export_rsaprivatekey(self)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else + return ossl_pkey_export_spki(self, 0); } /* @@ -382,158 +243,10 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_to_der(VALUE self) { - RSA *rsa; - int (*i2d_func)(const RSA *, unsigned char **); - unsigned char *p; - long len; - VALUE str; - - GetRSA(self, rsa); - if (RSA_HAS_PRIVATE(rsa)) - i2d_func = i2d_RSAPrivateKey; + if (can_export_rsaprivatekey(self)) + return ossl_pkey_export_traditional(0, NULL, self, 1); else - i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY; - if((len = i2d_func(rsa, NULL)) <= 0) - ossl_raise(eRSAError, NULL); - str = rb_str_new(0, len); - p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(rsa, &p) < 0) - ossl_raise(eRSAError, NULL); - ossl_str_adjust(str, p); - - return str; -} - -/* - * call-seq: - * rsa.public_encrypt(string) => String - * rsa.public_encrypt(string, padding) => String - * - * Encrypt _string_ with the public key. _padding_ defaults to PKCS1_PADDING. - * The encrypted string output can be decrypted using #private_decrypt. - */ -static VALUE -ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) -{ - RSA *rsa; - const BIGNUM *rsa_n; - int buf_len, pad; - VALUE str, buffer, padding; - - GetRSA(self, rsa); - RSA_get0_key(rsa, &rsa_n, NULL, NULL); - if (!rsa_n) - ossl_raise(eRSAError, "incomplete RSA"); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, RSA_size(rsa)); - buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), rsa, pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.public_decrypt(string) => String - * rsa.public_decrypt(string, padding) => String - * - * Decrypt _string_, which has been encrypted with the private key, with the - * public key. _padding_ defaults to PKCS1_PADDING. - */ -static VALUE -ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) -{ - RSA *rsa; - const BIGNUM *rsa_n; - int buf_len, pad; - VALUE str, buffer, padding; - - GetRSA(self, rsa); - RSA_get0_key(rsa, &rsa_n, NULL, NULL); - if (!rsa_n) - ossl_raise(eRSAError, "incomplete RSA"); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, RSA_size(rsa)); - buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), rsa, pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.private_encrypt(string) => String - * rsa.private_encrypt(string, padding) => String - * - * Encrypt _string_ with the private key. _padding_ defaults to PKCS1_PADDING. - * The encrypted string output can be decrypted using #public_decrypt. - */ -static VALUE -ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) -{ - RSA *rsa; - const BIGNUM *rsa_n; - int buf_len, pad; - VALUE str, buffer, padding; - - GetRSA(self, rsa); - RSA_get0_key(rsa, &rsa_n, NULL, NULL); - if (!rsa_n) - ossl_raise(eRSAError, "incomplete RSA"); - if (!RSA_PRIVATE(self, rsa)) - ossl_raise(eRSAError, "private key needed."); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, RSA_size(rsa)); - buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), rsa, pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; -} - -/* - * call-seq: - * rsa.private_decrypt(string) => String - * rsa.private_decrypt(string, padding) => String - * - * Decrypt _string_, which has been encrypted with the public key, with the - * private key. _padding_ defaults to PKCS1_PADDING. - */ -static VALUE -ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) -{ - RSA *rsa; - const BIGNUM *rsa_n; - int buf_len, pad; - VALUE str, buffer, padding; - - GetRSA(self, rsa); - RSA_get0_key(rsa, &rsa_n, NULL, NULL); - if (!rsa_n) - ossl_raise(eRSAError, "incomplete RSA"); - if (!RSA_PRIVATE(self, rsa)) - ossl_raise(eRSAError, "private key needed."); - rb_scan_args(argc, argv, "11", &buffer, &padding); - pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); - StringValue(buffer); - str = rb_str_new(0, RSA_size(rsa)); - buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), rsa, pad); - if (buf_len < 0) ossl_raise(eRSAError, NULL); - rb_str_set_len(str, buf_len); - - return str; + return ossl_pkey_export_spki(self, 1); } /* @@ -565,7 +278,7 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) * data = "Sign me!" * pkey = OpenSSL::PKey::RSA.new(2048) * signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256") - * pub_key = pkey.public_key + * pub_key = OpenSSL::PKey.read(pkey.public_to_der) * puts pub_key.verify_pss("SHA256", signature, data, * salt_length: :auto, mgf1_hash: "SHA256") # => true */ @@ -762,88 +475,6 @@ ossl_rsa_get_params(VALUE self) return hash; } -/* - * call-seq: - * rsa.to_text => String - * - * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! - * - * Dumps all parameters of a keypair to a String - * - * Don't use :-)) (It's up to you) - */ -static VALUE -ossl_rsa_to_text(VALUE self) -{ - RSA *rsa; - BIO *out; - VALUE str; - - GetRSA(self, rsa); - if (!(out = BIO_new(BIO_s_mem()))) { - ossl_raise(eRSAError, NULL); - } - if (!RSA_print(out, rsa, 0)) { /* offset = 0 */ - BIO_free(out); - ossl_raise(eRSAError, NULL); - } - str = ossl_membio2str(out); - - return str; -} - -/* - * call-seq: - * rsa.public_key -> RSA - * - * Makes new RSA instance containing the public key from the private key. - */ -static VALUE -ossl_rsa_to_public_key(VALUE self) -{ - EVP_PKEY *pkey; - RSA *rsa; - VALUE obj; - - GetPKeyRSA(self, pkey); - /* err check performed by rsa_instance */ - rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey)); - obj = rsa_instance(rb_obj_class(self), rsa); - if (obj == Qfalse) { - RSA_free(rsa); - ossl_raise(eRSAError, NULL); - } - return obj; -} - -/* - * TODO: Test me - -static VALUE -ossl_rsa_blinding_on(VALUE self) -{ - RSA *rsa; - - GetRSA(self, rsa); - - if (RSA_blinding_on(rsa, ossl_bn_ctx) != 1) { - ossl_raise(eRSAError, NULL); - } - return self; -} - -static VALUE -ossl_rsa_blinding_off(VALUE self) -{ - RSA *rsa; - - GetRSA(self, rsa); - RSA_blinding_off(rsa); - - return self; -} - */ - /* * Document-method: OpenSSL::PKey::RSA#set_key * call-seq: @@ -905,22 +536,17 @@ Init_ossl_rsa(void) */ cRSA = rb_define_class_under(mPKey, "RSA", cPKey); - rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1); rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1); +#endif rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); - rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0); rb_define_method(cRSA, "export", ossl_rsa_export, -1); rb_define_alias(cRSA, "to_pem", "export"); rb_define_alias(cRSA, "to_s", "export"); rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); - rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0); - rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1); - rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1); - rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1); - rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1); rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1); rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1); @@ -938,11 +564,6 @@ Init_ossl_rsa(void) rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); - DefRSAConst(PKCS1_PADDING); - DefRSAConst(SSLV23_PADDING); - DefRSAConst(NO_PADDING); - DefRSAConst(PKCS1_OAEP_PADDING); - /* * TODO: Test it rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0); diff --git a/ruby/ext/openssl/ossl_rand.c b/ruby/ext/openssl/ossl_rand.c index 4a4f9dd5b..659dc818b 100644 --- a/ruby/ext/openssl/ossl_rand.c +++ b/ruby/ext/openssl/ossl_rand.c @@ -120,36 +120,6 @@ ossl_rand_bytes(VALUE self, VALUE len) return str; } -#if defined(HAVE_RAND_PSEUDO_BYTES) -/* - * call-seq: - * pseudo_bytes(length) -> string - * - * Generates a String with _length_ number of pseudo-random bytes. - * - * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if - * they are of sufficient length, but are not necessarily unpredictable. - * - * === Example - * - * OpenSSL::Random.pseudo_bytes(12) - * #=> "..." - */ -static VALUE -ossl_rand_pseudo_bytes(VALUE self, VALUE len) -{ - VALUE str; - int n = NUM2INT(len); - - str = rb_str_new(0, n); - if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) { - ossl_raise(eRandomError, NULL); - } - - return str; -} -#endif - #ifdef HAVE_RAND_EGD /* * call-seq: @@ -219,8 +189,8 @@ 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 defined(HAVE_RAND_PSEUDO_BYTES) - rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_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); diff --git a/ruby/ext/openssl/ossl_ssl.c b/ruby/ext/openssl/ossl_ssl.c index de0556f54..9a0682a7c 100644 --- a/ruby/ext/openssl/ossl_ssl.c +++ b/ruby/ext/openssl/ossl_ssl.c @@ -13,6 +13,12 @@ #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) +#if !defined(TLS1_3_VERSION) && \ + defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER >= 0x3020000fL +# define TLS1_3_VERSION 0x0304 +#endif + #ifdef _WIN32 # define TO_SOCKET(s) _get_osfhandle(s) #else @@ -32,14 +38,14 @@ VALUE cSSLSocket; static VALUE eSSLErrorWaitReadable; static VALUE eSSLErrorWaitWritable; -static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback, - id_npn_protocols_encoded; +static ID id_call, ID_callback_state, id_tmp_dh_callback, + id_npn_protocols_encoded, id_each; static VALUE sym_exception, sym_wait_readable, sym_wait_writable; static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode, id_i_verify_depth, id_i_verify_callback, id_i_client_ca, id_i_renegotiation_cb, id_i_cert, id_i_key, id_i_extra_chain_cert, - id_i_client_cert_cb, id_i_tmp_ecdh_callback, id_i_timeout, + id_i_client_cert_cb, id_i_timeout, id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb, id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols, id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb, @@ -49,25 +55,24 @@ 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; -#if !defined(HAVE_X509_STORE_UP_REF) -static int ossl_sslctx_ex_store_p; -#endif static void -ossl_sslctx_free(void *ptr) +ossl_sslctx_mark(void *ptr) { SSL_CTX *ctx = ptr; -#if !defined(HAVE_X509_STORE_UP_REF) - if (ctx && SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_store_p)) - ctx->cert_store = NULL; -#endif - SSL_CTX_free(ctx); + rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx)); +} + +static void +ossl_sslctx_free(void *ptr) +{ + SSL_CTX_free(ptr); } static const rb_data_type_t ossl_sslctx_type = { "OpenSSL/SSL/CTX", { - 0, ossl_sslctx_free, + ossl_sslctx_mark, ossl_sslctx_free, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, }; @@ -83,7 +88,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) +#if OPENSSL_VERSION_NUMBER >= 0x10100000 || defined(LIBRESSL_VERSION_NUMBER) ctx = SSL_CTX_new(TLS_method()); #else ctx = SSL_CTX_new(SSLv23_method()); @@ -95,14 +100,15 @@ 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) && defined(HAVE_SSL_CTX_SET_ECDH_AUTO) +#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. But OpenSSL 1.1.0 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=. */ + * 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 @@ -231,8 +237,7 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) return 1; } -#if !defined(OPENSSL_NO_DH) || \ - !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) +#if !defined(OPENSSL_NO_DH) struct tmp_dh_callback_args { VALUE ssl_obj; ID id; @@ -241,22 +246,23 @@ struct tmp_dh_callback_args { int keylength; }; -static EVP_PKEY * -ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args) +static VALUE +ossl_call_tmp_dh_callback(VALUE arg) { + struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg; VALUE cb, dh; EVP_PKEY *pkey; cb = rb_funcall(args->ssl_obj, args->id, 0); if (NIL_P(cb)) - return NULL; + return (VALUE)NULL; dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export), INT2NUM(args->keylength)); pkey = GetPKeyPtr(dh); if (EVP_PKEY_base_id(pkey) != args->type) - return NULL; + return (VALUE)NULL; - return pkey; + return (VALUE)pkey; } #endif @@ -276,7 +282,7 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) args.keylength = keylength; args.type = EVP_PKEY_DH; - pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback, + pkey = (EVP_PKEY *)rb_protect(ossl_call_tmp_dh_callback, (VALUE)&args, &state); if (state) { rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state)); @@ -289,35 +295,6 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) } #endif /* OPENSSL_NO_DH */ -#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) -static EC_KEY * -ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength) -{ - VALUE rb_ssl; - EVP_PKEY *pkey; - struct tmp_dh_callback_args args; - int state; - - rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); - args.ssl_obj = rb_ssl; - args.id = id_tmp_ecdh_callback; - args.is_export = is_export; - args.keylength = keylength; - args.type = EVP_PKEY_EC; - - pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback, - (VALUE)&args, &state); - if (state) { - rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state)); - return NULL; - } - if (!pkey) - return NULL; - - return EVP_PKEY_get0_EC_KEY(pkey); -} -#endif - static VALUE call_verify_certificate_identity(VALUE ctx_v) { @@ -359,7 +336,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status)); return 0; } - preverify_ok = ret == Qtrue; + 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 + } } return ossl_verify_cb_call(cb, preverify_ok, ctx); @@ -380,7 +364,7 @@ ossl_call_session_get_cb(VALUE ary) } static SSL_SESSION * -#if (!defined(LIBRESSL_VERSION_NUMBER) ? OPENSSL_VERSION_NUMBER >= 0x10100000 : LIBRESSL_VERSION_NUMBER >= 0x2080000f) +#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) @@ -589,8 +573,6 @@ ssl_renegotiation_cb(const SSL *ssl) rb_funcallv(cb, id_call, 1, &ssl_obj); } -#if !defined(OPENSSL_NO_NEXTPROTONEG) || \ - defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) static VALUE ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded)) { @@ -609,7 +591,7 @@ static VALUE ssl_encode_npn_protocols(VALUE protocols) { VALUE encoded = rb_str_new(NULL, 0); - rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded); + rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded); return encoded; } @@ -672,14 +654,13 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out, return SSL_TLSEXT_ERR_OK; } -#endif #ifndef OPENSSL_NO_NEXTPROTONEG static int ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) { - VALUE protocols = (VALUE)arg; + VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded); *out = (const unsigned char *) RSTRING_PTR(protocols); *outlen = RSTRING_LENINT(protocols); @@ -701,7 +682,6 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, } #endif -#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB static int ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) @@ -713,7 +693,6 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen); } -#endif /* This function may serve as the entry point to support further callbacks. */ static void @@ -790,41 +769,15 @@ ossl_sslctx_setup(VALUE self) SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); #endif -#if !defined(OPENSSL_NO_EC) - /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0, - * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */ - if (RTEST(rb_attr_get(self, id_i_tmp_ecdh_callback))) { -# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) - rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead"); - SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback); -# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO) - /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores - * tmp_ecdh_callback. So disable ecdh_auto. */ - if (!SSL_CTX_set_ecdh_auto(ctx, 0)) - ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); -# endif -# else - ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; " - "use #ecdh_curves= instead"); -# endif - } -#endif /* OPENSSL_NO_EC */ +#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH + SSL_CTX_set_post_handshake_auth(ctx, 1); +#endif val = rb_attr_get(self, id_i_cert_store); if (!NIL_P(val)) { X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */ SSL_CTX_set_cert_store(ctx, store); -#if !defined(HAVE_X509_STORE_UP_REF) - /* - * WORKAROUND: - * X509_STORE can count references, but - * X509_STORE_free() doesn't care it. - * So we won't increment it but mark it by ex_data. - */ - SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_store_p, ctx); -#else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */ X509_STORE_up_ref(store); -#endif } val = rb_attr_get(self, id_i_extra_chain_cert); @@ -875,10 +828,17 @@ ossl_sslctx_setup(VALUE self) ca_file = NIL_P(val) ? NULL : StringValueCStr(val); val = rb_attr_get(self, id_i_ca_path); ca_path = NIL_P(val) ? NULL : StringValueCStr(val); +#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE + if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_file"); + if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_dir"); +#else if(ca_file || ca_path){ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) rb_warning("can't set verify locations"); } +#endif val = rb_attr_get(self, id_i_verify_mode); verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); @@ -897,7 +857,7 @@ ossl_sslctx_setup(VALUE self) if (!NIL_P(val)) { VALUE encoded = ssl_encode_npn_protocols(val); rb_ivar_set(self, id_npn_protocols_encoded, encoded); - SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded); + SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self); OSSL_Debug("SSL NPN advertise callback added"); } if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) { @@ -906,7 +866,6 @@ ossl_sslctx_setup(VALUE self) } #endif -#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB val = rb_attr_get(self, id_i_alpn_protocols); if (!NIL_P(val)) { VALUE rprotos = ssl_encode_npn_protocols(val); @@ -921,7 +880,6 @@ ossl_sslctx_setup(VALUE self) SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self); OSSL_Debug("SSL ALPN select callback added"); } -#endif rb_obj_freeze(self); @@ -1043,6 +1001,52 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) return v; } +#ifndef OPENSSL_NO_DH +/* + * call-seq: + * ctx.tmp_dh = pkey + * + * Sets DH parameters used for ephemeral DH key exchange. This is relevant for + * servers only. + * + * +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components + * contained in the key object, if any, are ignored. The server will always + * generate a new key pair for each handshake. + * + * Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey(3). + * + * Example: + * ctx = OpenSSL::SSL::SSLContext.new + * ctx.tmp_dh = OpenSSL::DH.generate(2048) + * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx) + * Thread.new { svr.accept } + */ +static VALUE +ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg) +{ + SSL_CTX *ctx; + EVP_PKEY *pkey; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + pkey = GetPKeyPtr(arg); + + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) + rb_raise(eSSLError, "invalid pkey type %s (expected DH)", + OBJ_nid2sn(EVP_PKEY_base_id(pkey))); +#ifdef HAVE_SSL_SET0_TMP_DH_PKEY + if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey)) + ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey"); + EVP_PKEY_up_ref(pkey); +#else + if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey))) + ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh"); +#endif + + return arg; +} +#endif + #if !defined(OPENSSL_NO_EC) /* * call-seq: @@ -1054,9 +1058,6 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) * 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. * - * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve - * can be set, and this has no effect for TLS clients. - * * === Example * ctx1 = OpenSSL::SSL::SSLContext.new * ctx1.ecdh_curves = "X25519:P-256:P-224" @@ -1080,48 +1081,8 @@ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg) GetSSLCTX(self, ctx); StringValueCStr(arg); -#if defined(HAVE_SSL_CTX_SET1_CURVES_LIST) if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg))) ossl_raise(eSSLError, NULL); -#else - /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to - * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */ - { - VALUE curve, splitted; - EC_KEY *ec; - int nid; - - splitted = rb_str_split(arg, ":"); - if (!RARRAY_LEN(splitted)) - ossl_raise(eSSLError, "invalid input format"); - curve = RARRAY_AREF(splitted, 0); - StringValueCStr(curve); - - /* SSL_CTX_set1_curves_list() accepts NIST names */ - nid = EC_curve_nist2nid(RSTRING_PTR(curve)); - if (nid == NID_undef) - nid = OBJ_txt2nid(RSTRING_PTR(curve)); - if (nid == NID_undef) - ossl_raise(eSSLError, "unknown curve name"); - - ec = EC_KEY_new_by_curve_name(nid); - if (!ec) - ossl_raise(eSSLError, NULL); - EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); - if (!SSL_CTX_set_tmp_ecdh(ctx, ec)) { - EC_KEY_free(ec); - ossl_raise(eSSLError, "SSL_CTX_set_tmp_ecdh"); - } - EC_KEY_free(ec); -# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO) - /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto - * is enabled. So disable ecdh_auto. */ - if (!SSL_CTX_set_ecdh_auto(ctx, 0)) - ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); -# endif - } -#endif - return arg; } #else @@ -1212,7 +1173,7 @@ ossl_sslctx_enable_fallback_scsv(VALUE self) /* * call-seq: - * ctx.add_certificate(certiticate, pkey [, extra_certs]) -> self + * ctx.add_certificate(certificate, pkey [, extra_certs]) -> self * * Adds a certificate to the context. _pkey_ must be a corresponding private * key with _certificate_. @@ -1244,10 +1205,6 @@ ossl_sslctx_enable_fallback_scsv(VALUE self) * ecdsa_pkey = ... * another_ca_cert = ... * ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert]) - * - * === Note - * OpenSSL before the version 1.0.2 could handle only one extra chain across - * all key types. Calling this method discards the chain set previously. */ static VALUE ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) @@ -1272,7 +1229,7 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) EVP_PKEY_free(pub_pkey); if (!pub_pkey) rb_raise(rb_eArgError, "certificate does not contain public key"); - if (EVP_PKEY_cmp(pub_pkey, pkey) != 1) + if (EVP_PKEY_eq(pub_pkey, pkey) != 1) rb_raise(rb_eArgError, "public key mismatch"); if (argc >= 3) @@ -1286,34 +1243,9 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) sk_X509_pop_free(extra_chain, X509_free); ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey"); } - - if (extra_chain) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000 && !defined(LIBRESSL_VERSION_NUMBER) - if (!SSL_CTX_set0_chain(ctx, extra_chain)) { - sk_X509_pop_free(extra_chain, X509_free); - ossl_raise(eSSLError, "SSL_CTX_set0_chain"); - } -#else - STACK_OF(X509) *orig_extra_chain; - X509 *x509_tmp; - - /* First, clear the existing chain */ - SSL_CTX_get_extra_chain_certs(ctx, &orig_extra_chain); - if (orig_extra_chain && sk_X509_num(orig_extra_chain)) { - rb_warning("SSL_CTX_set0_chain() is not available; " \ - "clearing previously set certificate chain"); - SSL_CTX_clear_extra_chain_certs(ctx); - } - while ((x509_tmp = sk_X509_shift(extra_chain))) { - /* Transfers ownership */ - if (!SSL_CTX_add_extra_chain_cert(ctx, x509_tmp)) { - X509_free(x509_tmp); - sk_X509_pop_free(extra_chain, X509_free); - ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert"); - } - } - sk_X509_free(extra_chain); -#endif + if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) { + sk_X509_pop_free(extra_chain, X509_free); + ossl_raise(eSSLError, "SSL_CTX_set0_chain"); } return self; } @@ -1511,8 +1443,16 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) static inline int ssl_started(SSL *ssl) { - /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */ - return SSL_get_fd(ssl) >= 0; + /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */ + return SSL_get_rbio(ssl) != NULL; +} + +static void +ossl_ssl_mark(void *ptr) +{ + SSL *ssl = ptr; + rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)); + rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx)); } static void @@ -1524,7 +1464,7 @@ ossl_ssl_free(void *ssl) const rb_data_type_t ossl_ssl_type = { "OpenSSL/SSL", { - 0, ossl_ssl_free, + ossl_ssl_mark, ossl_ssl_free, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, }; @@ -1535,6 +1475,29 @@ ossl_ssl_s_alloc(VALUE klass) return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL); } +static VALUE +peer_ip_address(VALUE self) +{ + VALUE remote_address = rb_funcall(rb_attr_get(self, id_i_io), rb_intern("remote_address"), 0); + + return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0); +} + +static VALUE +fallback_peer_ip_address(VALUE self, VALUE args) +{ + return rb_str_new_cstr("(null)"); +} + +static VALUE +peeraddr_ip_str(VALUE self) +{ + VALUE rb_mErrno = rb_const_get(rb_cObject, rb_intern("Errno")); + VALUE rb_eSystemCallError = rb_const_get(rb_mErrno, rb_intern("SystemCallError")); + + return rb_rescue2(peer_ip_address, self, fallback_peer_ip_address, (VALUE)0, rb_eSystemCallError, NULL); +} + /* * call-seq: * SSLSocket.new(io) => aSSLSocket @@ -1571,6 +1534,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) if (rb_respond_to(io, rb_intern("nonblock="))) rb_funcall(io, rb_intern("nonblock="), 1, Qtrue); + Check_Type(io, T_FILE); rb_ivar_set(self, id_i_io, io); ssl = SSL_new(ctx); @@ -1638,6 +1602,26 @@ no_exception_p(VALUE opts) return 0; } +static void +io_wait_writable(rb_io_t *fptr) +{ +#ifdef HAVE_RB_IO_MAYBE_WAIT + rb_io_maybe_wait_writable(errno, fptr->self, Qnil); +#else + rb_io_wait_writable(fptr->fd); +#endif +} + +static void +io_wait_readable(rb_io_t *fptr) +{ +#ifdef HAVE_RB_IO_MAYBE_WAIT + rb_io_maybe_wait_readable(errno, fptr->self, Qnil); +#else + rb_io_wait_readable(fptr->fd); +#endif +} + static VALUE ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) { @@ -1672,16 +1656,23 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) case SSL_ERROR_WANT_WRITE: if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); - rb_io_wait_writable(fptr->fd); + io_wait_writable(fptr); continue; case SSL_ERROR_WANT_READ: if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(fptr->fd); + io_wait_readable(fptr); continue; case SSL_ERROR_SYSCALL: +#ifdef __APPLE__ + /* See ossl_ssl_write_internal() */ + if (errno == EPROTOTYPE) + continue; +#endif if (errno) rb_sys_fail(funcname); - ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); + ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); + #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) case SSL_ERROR_SSL: err = ERR_peek_last_error(); @@ -1694,13 +1685,15 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) if (!verify_msg) verify_msg = "(null)"; ossl_clear_error(); /* let ossl_raise() not append message */ - ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s: %s (%s)", - funcname, ret2, errno, SSL_state_string_long(ssl), + ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl), err_msg, verify_msg); } #endif + /* fallthrough */ default: - ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); + ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); } } @@ -1711,8 +1704,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) * call-seq: * ssl.connect => self * - * Initiates an SSL/TLS handshake with a server. The handshake may be started - * after unencrypted data has been sent over the socket. + * Initiates an SSL/TLS handshake with a server. */ static VALUE ossl_ssl_connect(VALUE self) @@ -1759,8 +1751,7 @@ ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self) * call-seq: * ssl.accept => self * - * Waits for a SSL/TLS client to initiate a handshake. The handshake may be - * started after unencrypted data has been sent over the socket. + * Waits for a SSL/TLS client to initiate a handshake. */ static VALUE ossl_ssl_accept(VALUE self) @@ -1807,7 +1798,7 @@ static VALUE ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) { SSL *ssl; - int ilen, nread = 0; + int ilen; VALUE len, str; rb_io_t *fptr; VALUE io, opts = Qnil; @@ -1817,6 +1808,9 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) } else { rb_scan_args(argc, argv, "11", &len, &str); } + GetSSL(self, ssl); + if (!ssl_started(ssl)) + rb_raise(eSSLError, "SSL session is not started yet"); ilen = NUM2INT(len); if (NIL_P(str)) @@ -1832,68 +1826,60 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) if (ilen == 0) return str; - GetSSL(self, ssl); io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); - if (ssl_started(ssl)) { - for (;;){ - nread = SSL_read(ssl, RSTRING_PTR(str), ilen); - switch(ssl_get_error(ssl, nread)){ - case SSL_ERROR_NONE: - goto end; - case SSL_ERROR_ZERO_RETURN: - if (no_exception_p(opts)) { return Qnil; } - rb_eof_error(); - case SSL_ERROR_WANT_WRITE: - if (no_exception_p(opts)) { return sym_wait_writable; } + + rb_str_locktmp(str); + for (;;) { + int nread = SSL_read(ssl, RSTRING_PTR(str), ilen); + 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); - rb_io_wait_writable(fptr->fd); - continue; - case SSL_ERROR_WANT_READ: - if (no_exception_p(opts)) { return sym_wait_readable; } + } + io_wait_writable(fptr); + continue; + case SSL_ERROR_WANT_READ: + if (nonblock) { + rb_str_unlocktmp(str); + if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(fptr->fd); - continue; - case SSL_ERROR_SYSCALL: - if (!ERR_peek_error()) { - if (errno) - rb_sys_fail(0); - else { - /* - * The underlying BIO returned 0. This is actually a - * protocol error. But unfortunately, not all - * implementations cleanly shutdown the TLS connection - * but just shutdown/close the TCP connection. So report - * EOF for now... - */ - if (no_exception_p(opts)) { return Qnil; } - rb_eof_error(); - } - } - /* fall through */ - default: - ossl_raise(eSSLError, "SSL_read"); - } - } - } - else { - ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread"); - - rb_warning("SSL session is not started yet."); - if (nonblock) { - VALUE argv[3]; - argv[0] = len; - argv[1] = str; - argv[2] = opts; - return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS); + } + io_wait_readable(fptr); + continue; + case SSL_ERROR_SYSCALL: + if (!ERR_peek_error()) { + rb_str_unlocktmp(str); + if (errno) + rb_sys_fail(0); + else { + /* + * The underlying BIO returned 0. This is actually a + * protocol error. But unfortunately, not all + * implementations cleanly shutdown the TLS connection + * but just shutdown/close the TCP connection. So report + * EOF for now... + */ + if (no_exception_p(opts)) { return Qnil; } + rb_eof_error(); + } + } + /* fall through */ + default: + rb_str_unlocktmp(str); + ossl_raise(eSSLError, "SSL_read"); } - else - return rb_funcall(io, meth, 2, len, str); } - - end: - rb_str_set_len(str, nread); - return str; } /* @@ -1933,61 +1919,55 @@ static VALUE ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) { SSL *ssl; - int nwrite = 0; rb_io_t *fptr; - int nonblock = opts != Qfalse; - VALUE io; + int num, nonblock = opts != Qfalse; + VALUE tmp, io; - StringValue(str); GetSSL(self, ssl); + if (!ssl_started(ssl)) + rb_raise(eSSLError, "SSL session is not started yet"); + + tmp = rb_str_new_frozen(StringValue(str)); io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); - if (ssl_started(ssl)) { - for (;;){ - int num = RSTRING_LENINT(str); - - /* SSL_write(3ssl) manpage states num == 0 is undefined */ - if (num == 0) - goto end; - - nwrite = SSL_write(ssl, RSTRING_PTR(str), num); - switch(ssl_get_error(ssl, nwrite)){ - case SSL_ERROR_NONE: - goto end; - case SSL_ERROR_WANT_WRITE: - if (no_exception_p(opts)) { return sym_wait_writable; } - write_would_block(nonblock); - rb_io_wait_writable(fptr->fd); - continue; - case SSL_ERROR_WANT_READ: - if (no_exception_p(opts)) { return sym_wait_readable; } - read_would_block(nonblock); - rb_io_wait_readable(fptr->fd); + + /* SSL_write(3ssl) manpage states num == 0 is undefined */ + num = RSTRING_LENINT(tmp); + if (num == 0) + return INT2FIX(0); + + for (;;) { + int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num); + switch (ssl_get_error(ssl, nwritten)) { + case SSL_ERROR_NONE: + return INT2NUM(nwritten); + case SSL_ERROR_WANT_WRITE: + if (no_exception_p(opts)) { return sym_wait_writable; } + write_would_block(nonblock); + io_wait_writable(fptr); + continue; + case SSL_ERROR_WANT_READ: + if (no_exception_p(opts)) { return sym_wait_readable; } + read_would_block(nonblock); + io_wait_readable(fptr); + continue; + case SSL_ERROR_SYSCALL: +#ifdef __APPLE__ + /* + * It appears that send syscall can return EPROTOTYPE if the + * socket is being torn down. Retry to get a proper errno to + * make the error handling in line with the socket library. + * [Bug #14713] https://bugs.ruby-lang.org/issues/14713 + */ + if (errno == EPROTOTYPE) continue; - case SSL_ERROR_SYSCALL: - if (errno) rb_sys_fail(0); - default: - ossl_raise(eSSLError, "SSL_write"); - } +#endif + if (errno) rb_sys_fail(0); + /* fallthrough */ + default: + ossl_raise(eSSLError, "SSL_write"); } } - else { - ID meth = nonblock ? - rb_intern("write_nonblock") : rb_intern("syswrite"); - - rb_warning("SSL session is not started yet."); - if (nonblock) { - VALUE argv[2]; - argv[0] = str; - argv[1] = opts; - return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS); - } - else - return rb_funcall(io, meth, 1, str); - } - - end: - return INT2NUM(nwrite); } /* @@ -2286,7 +2266,57 @@ ossl_ssl_get_verify_result(VALUE self) GetSSL(self, ssl); - return INT2NUM(SSL_get_verify_result(ssl)); + return LONG2NUM(SSL_get_verify_result(ssl)); +} + +/* + * call-seq: + * ssl.finished_message => "finished message" + * + * Returns the last *Finished* message sent + * + */ +static VALUE +ossl_ssl_get_finished(VALUE self) +{ + SSL *ssl; + char sizer[1], *buf; + size_t len; + + GetSSL(self, ssl); + + len = SSL_get_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; + + buf = ALLOCA_N(char, len); + SSL_get_finished(ssl, buf, len); + return rb_str_new(buf, len); +} + +/* + * call-seq: + * ssl.peer_finished_message => "peer finished message" + * + * Returns the last *Finished* message received + * + */ +static VALUE +ossl_ssl_get_peer_finished(VALUE self) +{ + SSL *ssl; + char sizer[1], *buf; + size_t len; + + GetSSL(self, ssl); + + len = SSL_get_peer_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; + + buf = ALLOCA_N(char, len); + SSL_get_peer_finished(ssl, buf, len); + return rb_str_new(buf, len); } /* @@ -2337,7 +2367,6 @@ ossl_ssl_npn_protocol(VALUE self) } # endif -# ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB /* * call-seq: * ssl.alpn_protocol => String | nil @@ -2360,9 +2389,7 @@ ossl_ssl_alpn_protocol(VALUE self) else return rb_str_new((const char *) out, outlen); } -# endif -# ifdef HAVE_SSL_GET_SERVER_TMP_KEY /* * call-seq: * ssl.tmp_key => PKey or nil @@ -2380,11 +2407,8 @@ ossl_ssl_tmp_key(VALUE self) return Qnil; return ossl_pkey_new(key); } -# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */ #endif /* !defined(OPENSSL_NO_SOCK) */ -#undef rb_intern -#define rb_intern(s) rb_intern_const(s) void Init_ossl_ssl(void) { @@ -2395,8 +2419,8 @@ Init_ossl_ssl(void) rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable"); #endif - id_call = rb_intern("call"); - ID_callback_state = rb_intern("callback_state"); + 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) @@ -2407,11 +2431,6 @@ Init_ossl_ssl(void) ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_ptr_idx", 0, 0, 0); if (ossl_sslctx_ex_ptr_idx < 0) ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index"); -#if !defined(HAVE_X509_STORE_UP_REF) - ossl_sslctx_ex_store_p = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_store_p", 0, 0, 0); - if (ossl_sslctx_ex_store_p < 0) - ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index"); -#endif /* Document-module: OpenSSL::SSL * @@ -2463,7 +2482,7 @@ Init_ossl_ssl(void) * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("cert"), 1, 1, Qfalse); /* * Context private key @@ -2471,29 +2490,29 @@ Init_ossl_ssl(void) * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("key"), 1, 1, Qfalse); /* * A certificate or Array of certificates that will be sent to the client. */ - rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("client_ca"), 1, 1, Qfalse); /* * The path to a file containing a PEM-format CA certificate */ - rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("ca_file"), 1, 1, Qfalse); /* * The path to a directory containing CA certificates in PEM format. * * Files are looked up by subject's X509 name's hash value. */ - rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("ca_path"), 1, 1, Qfalse); /* * Maximum session lifetime in seconds. */ - rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("timeout"), 1, 1, Qfalse); /* * Session verification mode. @@ -2506,12 +2525,12 @@ Init_ossl_ssl(void) * * See SSL_CTX_set_verify(3) for details. */ - rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_mode"), 1, 1, Qfalse); /* * Number of CA certificates to walk when verifying a certificate chain. */ - rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_depth"), 1, 1, Qfalse); /* * A callback for additional certificate verification. The callback is @@ -2525,7 +2544,7 @@ Init_ossl_ssl(void) * If the callback returns +false+, the chain verification is immediately * stopped and a bad_certificate alert is then sent. */ - rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_callback"), 1, 1, Qfalse); /* * Whether to check the server certificate is valid for the hostname. @@ -2533,12 +2552,12 @@ Init_ossl_ssl(void) * In order to make this work, verify_mode must be set to VERIFY_PEER and * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=. */ - rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("verify_hostname"), 1, 1, Qfalse); /* * An OpenSSL::X509::Store used for certificate verification. */ - rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("cert_store"), 1, 1, Qfalse); /* * An Array of extra X509 certificates to be added to the certificate @@ -2547,7 +2566,7 @@ Init_ossl_ssl(void) * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated. * It is recommended to use #add_certificate instead. */ - rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("extra_chain_cert"), 1, 1, Qfalse); /* * A callback invoked when a client certificate is requested by a server @@ -2557,28 +2576,14 @@ Init_ossl_ssl(void) * containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any * other value is returned the handshake is suspended. */ - rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse); - -#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) - /* - * A callback invoked when ECDH parameters are required. - * - * The callback is invoked with the Session for the key exchange, an - * flag indicating the use of an export cipher and the keylength - * required. - * - * The callback is deprecated. This does not work with recent versions of - * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead. - */ - rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse); -#endif + rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse); /* * Sets the context in which a session can be reused. This allows * sessions for multiple applications to be distinguished, for example, by * name. */ - rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_id_context"), 1, 1, Qfalse); /* * A callback invoked on a server when a session is proposed by the client @@ -2587,7 +2592,7 @@ Init_ossl_ssl(void) * The callback is invoked with the SSLSocket and session id. The * callback may return a Session from an external cache. */ - rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_get_cb"), 1, 1, Qfalse); /* * A callback invoked when a new session was negotiated. @@ -2595,7 +2600,7 @@ Init_ossl_ssl(void) * The callback is invoked with an SSLSocket. If +false+ is returned the * session will be removed from the internal cache. */ - rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_new_cb"), 1, 1, Qfalse); /* * A callback invoked when a session is removed from the internal cache. @@ -2606,18 +2611,18 @@ Init_ossl_ssl(void) * multi-threaded application. The callback is called inside a global lock * and it can randomly cause deadlock on Ruby thread switching. */ - rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("session_remove_cb"), 1, 1, Qfalse); rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue); /* - * A callback invoked whenever a new handshake is initiated. May be used - * to disable renegotiation entirely. + * A callback invoked whenever a new handshake is initiated on an + * established connection. May be used to disable renegotiation entirely. * * The callback is invoked with the active SSLSocket. The callback's - * return value is irrelevant, normal return indicates "approval" of the + * return value is ignored. A normal return indicates "approval" of the * renegotiation and will continue the process. To forbid renegotiation - * and to cancel the process, an Error may be raised within the callback. + * and to cancel the process, raise an exception within the callback. * * === Disable client renegotiation * @@ -2625,13 +2630,11 @@ Init_ossl_ssl(void) * renegotiation entirely. You may use a callback as follows to implement * this feature: * - * num_handshakes = 0 * ctx.renegotiation_cb = lambda do |ssl| - * num_handshakes += 1 - * raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1 + * raise RuntimeError, "Client renegotiation disabled" * end */ - rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse); #ifndef OPENSSL_NO_NEXTPROTONEG /* * An Enumerable of Strings. Each String represents a protocol to be @@ -2644,7 +2647,7 @@ Init_ossl_ssl(void) * * ctx.npn_protocols = ["http/1.1", "spdy/2"] */ - rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("npn_protocols"), 1, 1, Qfalse); /* * A callback invoked on the client side when the client needs to select * a protocol from the list sent by the server. Supported in OpenSSL 1.0.1 @@ -2661,10 +2664,9 @@ Init_ossl_ssl(void) * protocols.first * end */ - rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("npn_select_cb"), 1, 1, Qfalse); #endif -#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB /* * An Enumerable of Strings. Each String represents a protocol to be * advertised as the list of supported protocols for Application-Layer @@ -2676,7 +2678,7 @@ Init_ossl_ssl(void) * * ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"] */ - rb_attr(cSSLContext, rb_intern("alpn_protocols"), 1, 1, Qfalse); + rb_attr(cSSLContext, rb_intern_const("alpn_protocols"), 1, 1, Qfalse); /* * A callback invoked on the server side when the server needs to select * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2 @@ -2693,8 +2695,7 @@ Init_ossl_ssl(void) * protocols.first * end */ - rb_attr(cSSLContext, rb_intern("alpn_select_cb"), 1, 1, Qfalse); -#endif + rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse); rb_define_alias(cSSLContext, "ssl_timeout", "timeout"); rb_define_alias(cSSLContext, "ssl_timeout=", "timeout="); @@ -2702,6 +2703,9 @@ Init_ossl_ssl(void) ossl_sslctx_set_minmax_proto_version, 2); rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); +#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, "security_level", ossl_sslctx_get_security_level, 0); rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1); @@ -2806,12 +2810,10 @@ Init_ossl_ssl(void) rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); /* #hostname is defined in lib/openssl/ssl.rb */ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1); -# ifdef HAVE_SSL_GET_SERVER_TMP_KEY + rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0); + rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0); rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); -# endif -# ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); -# endif # ifndef OPENSSL_NO_NEXTPROTONEG rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0); # endif @@ -2823,12 +2825,23 @@ Init_ossl_ssl(void) rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE)); rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL)); +#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT)); +#endif rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT)); -#ifdef SSL_OP_TLSEXT_PADDING /* OpenSSL 1.0.1h and OpenSSL 1.0.2 */ - rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING)); +#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS)); #endif -#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG /* OpenSSL 1.0.1f and OpenSSL 1.0.2 */ + rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING)); rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG)); +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF)); +#endif +#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */ + rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION)); +#endif +#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 */ rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX)); @@ -2841,13 +2854,15 @@ Init_ossl_ssl(void) #ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */ rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC)); #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 */ - rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION)); +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT)); +#endif +#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA)); +#endif +#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY)); #endif - rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG)); - 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)); @@ -2855,6 +2870,12 @@ Init_ossl_ssl(void) #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 */ + 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)); /* SSL_OP_* flags for DTLS */ #if 0 @@ -2919,16 +2940,16 @@ Init_ossl_ssl(void) #endif - sym_exception = ID2SYM(rb_intern("exception")); - sym_wait_readable = ID2SYM(rb_intern("wait_readable")); - sym_wait_writable = ID2SYM(rb_intern("wait_writable")); + sym_exception = ID2SYM(rb_intern_const("exception")); + sym_wait_readable = ID2SYM(rb_intern_const("wait_readable")); + sym_wait_writable = ID2SYM(rb_intern_const("wait_writable")); - id_tmp_dh_callback = rb_intern("tmp_dh_callback"); - id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback"); - id_npn_protocols_encoded = rb_intern("npn_protocols_encoded"); + id_tmp_dh_callback = rb_intern_const("tmp_dh_callback"); + id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded"); + id_each = rb_intern_const("each"); #define DefIVarID(name) do \ - id_i_##name = rb_intern("@"#name); while (0) + id_i_##name = rb_intern_const("@"#name); while (0) DefIVarID(cert_store); DefIVarID(ca_file); @@ -2942,7 +2963,6 @@ Init_ossl_ssl(void) DefIVarID(key); DefIVarID(extra_chain_cert); DefIVarID(client_cert_cb); - DefIVarID(tmp_ecdh_callback); DefIVarID(timeout); DefIVarID(session_id_context); DefIVarID(session_get_cb); diff --git a/ruby/ext/openssl/ossl_ssl_session.c b/ruby/ext/openssl/ossl_ssl_session.c index 551408738..92eb1365f 100644 --- a/ruby/ext/openssl/ossl_ssl_session.c +++ b/ruby/ext/openssl/ossl_ssl_session.c @@ -34,43 +34,38 @@ static VALUE ossl_ssl_session_alloc(VALUE klass) * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded * String. */ -static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1) +static VALUE +ossl_ssl_session_initialize(VALUE self, VALUE arg1) { - SSL_SESSION *ctx = NULL; - - if (RDATA(self)->data) - ossl_raise(eSSLSession, "SSL Session already initialized"); - - if (rb_obj_is_instance_of(arg1, cSSLSocket)) { - SSL *ssl; - - GetSSL(arg1, ssl); - - if ((ctx = SSL_get1_session(ssl)) == NULL) - ossl_raise(eSSLSession, "no session available"); - } else { - BIO *in = ossl_obj2bio(&arg1); + SSL_SESSION *ctx; - ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); + if (RTYPEDDATA_DATA(self)) + ossl_raise(eSSLSession, "SSL Session already initialized"); - if (!ctx) { - OSSL_BIO_reset(in); - ctx = d2i_SSL_SESSION_bio(in, NULL); - } + if (rb_obj_is_instance_of(arg1, cSSLSocket)) { + SSL *ssl; - BIO_free(in); + GetSSL(arg1, ssl); - if (!ctx) - ossl_raise(rb_eArgError, "unknown type"); - } + if ((ctx = SSL_get1_session(ssl)) == NULL) + ossl_raise(eSSLSession, "no session available"); + } + else { + BIO *in = ossl_obj2bio(&arg1); - /* should not happen */ - if (ctx == NULL) - ossl_raise(eSSLSession, "ctx not set - internal error"); + ctx = d2i_SSL_SESSION_bio(in, NULL); + if (!ctx) { + OSSL_BIO_reset(in); + ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); + } + BIO_free(in); + if (!ctx) + ossl_raise(rb_eArgError, "unknown type"); + } - RDATA(self)->data = ctx; + RTYPEDDATA_DATA(self) = ctx; - return self; + return self; } static VALUE diff --git a/ruby/ext/openssl/ossl_ts.c b/ruby/ext/openssl/ossl_ts.c new file mode 100644 index 000000000..b33ff10c1 --- /dev/null +++ b/ruby/ext/openssl/ossl_ts.c @@ -0,0 +1,1539 @@ +/* + * + * Copyright (C) 2010 Martin Bosslet + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#include "ossl.h" + +#ifndef OPENSSL_NO_TS + +#define NewTSRequest(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0) +#define SetTSRequest(obj, req) do { \ + if (!(req)) { \ + ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (req); \ +} while (0) +#define GetTSRequest(obj, req) do { \ + TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \ + if (!(req)) { \ + ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \ + } \ +} while (0) + +#define NewTSResponse(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0) +#define SetTSResponse(obj, resp) do { \ + if (!(resp)) { \ + ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (resp); \ +} while (0) +#define GetTSResponse(obj, resp) do { \ + TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \ + if (!(resp)) { \ + ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \ + } \ +} while (0) + +#define NewTSTokenInfo(klass) \ + TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0) +#define SetTSTokenInfo(obj, info) do { \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (info); \ +} while (0) +#define GetTSTokenInfo(obj, info) do { \ + TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \ + if (!(info)) { \ + ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \ + } \ +} while (0) + +#define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id")) +#define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number")) +#define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time")) +#define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs")) +#define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests")) + +static VALUE mTimestamp; +static VALUE eTimestampError; +static VALUE cTimestampRequest; +static VALUE cTimestampResponse; +static VALUE cTimestampTokenInfo; +static VALUE cTimestampFactory; +static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE; +static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE; +static VALUE sSYSTEM_FAILURE; + +static void +ossl_ts_req_free(void *ptr) +{ + TS_REQ_free(ptr); +} + +static const rb_data_type_t ossl_ts_req_type = { + "OpenSSL/Timestamp/Request", + { + 0, ossl_ts_req_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static void +ossl_ts_resp_free(void *ptr) +{ + TS_RESP_free(ptr); +} + +static const rb_data_type_t ossl_ts_resp_type = { + "OpenSSL/Timestamp/Response", + { + 0, ossl_ts_resp_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static void +ossl_ts_token_info_free(void *ptr) +{ + TS_TST_INFO_free(ptr); +} + +static const rb_data_type_t ossl_ts_token_info_type = { + "OpenSSL/Timestamp/TokenInfo", + { + 0, ossl_ts_token_info_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static VALUE +asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp)) +{ + VALUE str; + int len; + unsigned char *p; + + if((len = i2d(template, NULL)) <= 0) + ossl_raise(eTimestampError, "Error when encoding to DER"); + str = rb_str_new(0, len); + p = (unsigned char *)RSTRING_PTR(str); + if(i2d(template, &p) <= 0) + ossl_raise(eTimestampError, "Error when encoding to DER"); + rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str)); + + return str; +} + +static ASN1_OBJECT* +obj_to_asn1obj(VALUE obj) +{ + ASN1_OBJECT *a1obj; + + StringValue(obj); + a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0); + if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1); + if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID"); + + return a1obj; +} + +static VALUE +obj_to_asn1obj_i(VALUE obj) +{ + return (VALUE)obj_to_asn1obj(obj); +} + +static VALUE +get_asn1obj(ASN1_OBJECT *obj) +{ + BIO *out; + VALUE ret; + int nid; + if ((nid = OBJ_obj2nid(obj)) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); + else{ + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509AttrError, NULL); + i2a_ASN1_OBJECT(out, obj); + ret = ossl_membio2str(out); + } + + return ret; +} + +static VALUE +ossl_ts_req_alloc(VALUE klass) +{ + TS_REQ *req; + VALUE obj; + + obj = NewTSRequest(klass); + if (!(req = TS_REQ_new())) + ossl_raise(eTimestampError, NULL); + SetTSRequest(obj, req); + + /* Defaults */ + TS_REQ_set_version(req, 1); + TS_REQ_set_cert_req(req, 1); + + return obj; +} + +/* + * When creating a Request with the +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. + * + * call-seq: + * OpenSSL::Timestamp::Request.new(file) -> request + * OpenSSL::Timestamp::Request.new(string) -> request + * OpenSSL::Timestamp::Request.new -> empty request + */ +static VALUE +ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self) +{ + TS_REQ *ts_req = DATA_PTR(self); + BIO *in; + VALUE arg; + + if(rb_scan_args(argc, argv, "01", &arg) == 0) { + return self; + } + + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); + ts_req = d2i_TS_REQ_bio(in, &ts_req); + BIO_free(in); + if (!ts_req) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp request"); + } + DATA_PTR(self) = ts_req; + + return self; +} + +/* + * Returns the 'short name' of the object identifier that represents the + * algorithm that was used to create the message imprint digest. + * + * call-seq: + * request.algorithm -> string + */ +static VALUE +ossl_ts_req_get_algorithm(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algor; + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + algor = TS_MSG_IMPRINT_get_algo(mi); + return get_asn1obj(algor->algorithm); +} + +/* + * Allows to set the object identifier or the 'short name' of the + * algorithm that was used to create the message imprint digest. + * + * ===Example: + * request.algorithm = "SHA1" + * + * call-seq: + * request.algorithm = "string" -> string + */ +static VALUE +ossl_ts_req_set_algorithm(VALUE self, VALUE algo) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + ASN1_OBJECT *obj; + X509_ALGOR *algor; + + GetTSRequest(self, req); + obj = obj_to_asn1obj(algo); + mi = TS_REQ_get_msg_imprint(req); + algor = TS_MSG_IMPRINT_get_algo(mi); + if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) { + ASN1_OBJECT_free(obj); + ossl_raise(eTimestampError, "X509_ALGOR_set0"); + } + + return algo; +} + +/* + * Returns the message imprint (digest) of the data to be timestamped. + * + * call-seq: + * request.message_imprint -> string or nil + */ +static VALUE +ossl_ts_req_get_msg_imprint(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + ASN1_OCTET_STRING *hashed_msg; + VALUE ret; + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + + ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length); + + return ret; +} + +/* + * Set the message imprint digest. + * + * call-seq: + * request.message_imprint = "string" -> string + */ +static VALUE +ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + StringValue(hash); + + GetTSRequest(self, req); + mi = TS_REQ_get_msg_imprint(req); + if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash))) + ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg"); + + return hash; +} + +/* + * Returns the version of this request. +1+ is the default value. + * + * call-seq: + * request.version -> Integer + */ +static VALUE +ossl_ts_req_get_version(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + return LONG2NUM(TS_REQ_get_version(req)); +} + +/* + * Sets the version number for this Request. This should be +1+ for compliant + * servers. + * + * call-seq: + * request.version = number -> Integer + */ +static VALUE +ossl_ts_req_set_version(VALUE self, VALUE version) +{ + TS_REQ *req; + long ver; + + if ((ver = NUM2LONG(version)) < 0) + ossl_raise(eTimestampError, "version must be >= 0!"); + GetTSRequest(self, req); + if (!TS_REQ_set_version(req, ver)) + ossl_raise(eTimestampError, "TS_REQ_set_version"); + + return version; +} + +/* + * Returns the 'short name' of the object identifier that represents the + * timestamp policy under which the server shall create the timestamp. + * + * call-seq: + * request.policy_id -> string or nil + */ +static VALUE +ossl_ts_req_get_policy_id(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + if (!TS_REQ_get_policy_id(req)) + return Qnil; + return get_asn1obj(TS_REQ_get_policy_id(req)); +} + +/* + * Allows to set the object identifier that represents the + * timestamp policy under which the server shall create the timestamp. This + * may be left +nil+, implying that the timestamp server will issue the + * timestamp using some default policy. + * + * ===Example: + * request.policy_id = "1.2.3.4.5" + * + * call-seq: + * request.policy_id = "string" -> string + */ +static VALUE +ossl_ts_req_set_policy_id(VALUE self, VALUE oid) +{ + TS_REQ *req; + ASN1_OBJECT *obj; + int ok; + + GetTSRequest(self, req); + obj = obj_to_asn1obj(oid); + ok = TS_REQ_set_policy_id(req, obj); + ASN1_OBJECT_free(obj); + if (!ok) + ossl_raise(eTimestampError, "TS_REQ_set_policy_id"); + + return oid; +} + +/* + * Returns the nonce (number used once) that the server shall include in its + * response. + * + * call-seq: + * request.nonce -> BN or nil + */ +static VALUE +ossl_ts_req_get_nonce(VALUE self) +{ + TS_REQ *req; + const ASN1_INTEGER * nonce; + + GetTSRequest(self, req); + if (!(nonce = TS_REQ_get_nonce(req))) + return Qnil; + return asn1integer_to_num(nonce); +} + +/* + * Sets the nonce (number used once) that the server shall include in its + * response. If the nonce is set, the server must return the same nonce value in + * a valid Response. + * + * call-seq: + * request.nonce = number -> BN + */ +static VALUE +ossl_ts_req_set_nonce(VALUE self, VALUE num) +{ + TS_REQ *req; + ASN1_INTEGER *nonce; + int ok; + + GetTSRequest(self, req); + nonce = num_to_asn1integer(num, NULL); + ok = TS_REQ_set_nonce(req, nonce); + ASN1_INTEGER_free(nonce); + if (!ok) + ossl_raise(eTimestampError, NULL); + return num; +} + +/* + * Indicates whether the response shall contain the timestamp authority's + * certificate or not. + * + * call-seq: + * request.cert_requested? -> true or false + */ +static VALUE +ossl_ts_req_get_cert_requested(VALUE self) +{ + TS_REQ *req; + + GetTSRequest(self, req); + return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse; +} + +/* + * Specify whether the response shall contain the timestamp authority's + * certificate or not. The default value is +true+. + * + * call-seq: + * request.cert_requested = boolean -> true or false + */ +static VALUE +ossl_ts_req_set_cert_requested(VALUE self, VALUE requested) +{ + TS_REQ *req; + + GetTSRequest(self, req); + TS_REQ_set_cert_req(req, RTEST(requested)); + + return requested; +} + +/* + * DER-encodes this Request. + * + * call-seq: + * request.to_der -> DER-encoded string + */ +static VALUE +ossl_ts_req_to_der(VALUE self) +{ + TS_REQ *req; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algo; + 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) + ossl_raise(eTimestampError, "Message imprint missing algorithm"); + + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + if (!hashed_msg->length) + ossl_raise(eTimestampError, "Message imprint missing hashed message"); + + return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ); +} + +static VALUE +ossl_ts_resp_alloc(VALUE klass) +{ + TS_RESP *resp; + VALUE obj; + + obj = NewTSResponse(klass); + if (!(resp = TS_RESP_new())) + ossl_raise(eTimestampError, NULL); + SetTSResponse(obj, resp); + + return obj; +} + +/* + * Creates a Response from a +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. Please note + * that Response is an immutable read-only class. If you'd like to create + * timestamps please refer to Factory instead. + * + * call-seq: + * OpenSSL::Timestamp::Response.new(file) -> response + * OpenSSL::Timestamp::Response.new(string) -> response + */ +static VALUE +ossl_ts_resp_initialize(VALUE self, VALUE der) +{ + TS_RESP *ts_resp = DATA_PTR(self); + BIO *in; + + der = ossl_to_der_if_possible(der); + in = ossl_obj2bio(&der); + ts_resp = d2i_TS_RESP_bio(in, &ts_resp); + BIO_free(in); + if (!ts_resp) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp response"); + } + DATA_PTR(self) = ts_resp; + + return self; +} + +/* + * Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING, + * REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has + * been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS. + * + * call-seq: + * response.status -> BN (never nil) + */ +static VALUE +ossl_ts_resp_get_status(VALUE self) +{ + TS_RESP *resp; + TS_STATUS_INFO *si; + const ASN1_INTEGER *st; + + GetTSResponse(self, resp); + si = TS_RESP_get_status_info(resp); + st = TS_STATUS_INFO_get0_status(si); + + return asn1integer_to_num(st); +} + +/* + * In cases no timestamp token has been created, this field contains further + * info about the reason why response creation failed. The method returns either + * nil (the request was successful and a timestamp token was created) or one of + * the following: + * * :BAD_ALG - Indicates that the timestamp server rejects the message + * imprint algorithm used in the Request + * * :BAD_REQUEST - Indicates that the timestamp server was not able to process + * the Request properly + * * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to + * parse certain data in the Request + * * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time + * source + * * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not + * recognized or supported by the timestamp server + * * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is + * not supported by the timestamp server + * * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested + * is either not understood or currently not available + * * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that + * occurred on the timestamp server + * + * call-seq: + * response.failure_info -> nil or symbol + */ +static VALUE +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); + fi = TS_STATUS_INFO_get0_failure_info(si); + if (!fi) + return Qnil; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG)) + return sBAD_ALG; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST)) + return sBAD_REQUEST; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT)) + return sBAD_DATA_FORMAT; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE)) + return sTIME_NOT_AVAILABLE; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY)) + return sUNACCEPTED_POLICY; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION)) + return sUNACCEPTED_EXTENSION; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE)) + return sADD_INFO_NOT_AVAILABLE; + if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE)) + return sSYSTEM_FAILURE; + + ossl_raise(eTimestampError, "Unrecognized failure info."); +} + +/* + * In cases of failure this field may contain an array of strings further + * describing the origin of the failure. + * + * call-seq: + * response.status_text -> Array of strings or nil + */ +static VALUE +ossl_ts_resp_get_status_text(VALUE self) +{ + TS_RESP *resp; + TS_STATUS_INFO *si; + const STACK_OF(ASN1_UTF8STRING) *text; + ASN1_UTF8STRING *current; + int i; + VALUE ret = rb_ary_new(); + + GetTSResponse(self, resp); + si = TS_RESP_get_status_info(resp); + if ((text = TS_STATUS_INFO_get0_text(si))) { + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { + current = sk_ASN1_UTF8STRING_value(text, i); + rb_ary_push(ret, asn1str_to_str(current)); + } + } + + return ret; +} + +/* + * If a timestamp token is present, this returns it in the form of a + * OpenSSL::PKCS7. + * + * call-seq: + * response.token -> nil or OpenSSL::PKCS7 + */ +static VALUE +ossl_ts_resp_get_token(VALUE self) +{ + TS_RESP *resp; + PKCS7 *p7, *copy; + VALUE obj; + + 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; +} + +/* + * Get the response's token info if present. + * + * call-seq: + * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo + */ +static VALUE +ossl_ts_resp_get_token_info(VALUE self) +{ + TS_RESP *resp; + TS_TST_INFO *info, *copy; + VALUE obj; + + GetTSResponse(self, resp); + if (!(info = TS_RESP_get_tst_info(resp))) + return Qnil; + + obj = NewTSTokenInfo(cTimestampTokenInfo); + + if (!(copy = TS_TST_INFO_dup(info))) + ossl_raise(eTimestampError, NULL); + + SetTSTokenInfo(obj, copy); + + return obj; +} + +/* + * If the Request specified to request the TSA certificate + * (Request#cert_requested = true), then this field contains the + * certificate of the timestamp authority. + * + * call-seq: + * response.tsa_certificate -> OpenSSL::X509::Certificate or nil + */ +static VALUE +ossl_ts_resp_get_tsa_certificate(VALUE self) +{ + TS_RESP *resp; + PKCS7 *p7; + PKCS7_SIGNER_INFO *ts_info; + X509 *cert; + + GetTSResponse(self, resp); + if (!(p7 = TS_RESP_get_token(resp))) + return Qnil; + ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0); + cert = PKCS7_cert_from_signer_info(p7, ts_info); + if (!cert) + return Qnil; + return ossl_x509_new(cert); +} + +/* + * Returns the Response in DER-encoded form. + * + * call-seq: + * response.to_der -> string + */ +static VALUE +ossl_ts_resp_to_der(VALUE self) +{ + TS_RESP *resp; + + GetTSResponse(self, resp); + return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); +} + +/* + * Verifies a timestamp token by checking the signature, validating the + * certificate chain implied by tsa_certificate and by checking conformance to + * a given Request. Mandatory parameters are the Request associated to this + * Response, and an OpenSSL::X509::Store of trusted roots. + * + * Intermediate certificates can optionally be supplied for creating the + * certificate chain. These intermediate certificates must all be + * instances of OpenSSL::X509::Certificate. + * + * If validation fails, several kinds of exceptions can be raised: + * * TypeError if types don't fit + * * TimestampError if something is wrong with the timestamp token itself, if + * it is not conformant to the Request, or if validation of the timestamp + * certificate chain fails. + * + * call-seq: + * response.verify(Request, root_store) -> Response + * response.verify(Request, root_store, [intermediate_cert]) -> Response + */ +static VALUE +ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) +{ + VALUE ts_req, store, intermediates; + TS_RESP *resp; + TS_REQ *req; + X509_STORE *x509st; + TS_VERIFY_CTX *ctx; + STACK_OF(X509) *x509inter = NULL; + PKCS7* p7; + X509 *cert; + int status, i, ok; + + rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates); + + GetTSResponse(self, resp); + GetTSRequest(ts_req, req); + x509st = GetX509StorePtr(store); + + if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) { + ossl_raise(eTimestampError, "Error when creating the verification context."); + } + + if (!NIL_P(intermediates)) { + x509inter = ossl_protect_x509_ary2sk(intermediates, &status); + if (status) { + TS_VERIFY_CTX_free(ctx); + rb_jump_tag(status); + } + } else if (!(x509inter = sk_X509_new_null())) { + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "sk_X509_new_null"); + } + + if (!(p7 = TS_RESP_get_token(resp))) { + TS_VERIFY_CTX_free(ctx); + sk_X509_pop_free(x509inter, X509_free); + ossl_raise(eTimestampError, "TS_RESP_get_token"); + } + for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) { + cert = sk_X509_value(p7->d.sign->cert, i); + if (!sk_X509_push(x509inter, cert)) { + sk_X509_pop_free(x509inter, X509_free); + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "sk_X509_push"); + } + X509_up_ref(cert); + } + + TS_VERIFY_CTX_set_certs(ctx, x509inter); + TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); + TS_VERIFY_CTX_set_store(ctx, x509st); + + 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) + ossl_raise(eTimestampError, "TS_RESP_verify_response"); + + return self; +} + +static VALUE +ossl_ts_token_info_alloc(VALUE klass) +{ + TS_TST_INFO *info; + VALUE obj; + + obj = NewTSTokenInfo(klass); + if (!(info = TS_TST_INFO_new())) + ossl_raise(eTimestampError, NULL); + SetTSTokenInfo(obj, info); + + return obj; +} + +/* + * Creates a TokenInfo from a +File+ or +string+ parameter, the + * corresponding +File+ or +string+ must be DER-encoded. Please note + * that TokenInfo is an immutable read-only class. If you'd like to create + * timestamps please refer to Factory instead. + * + * call-seq: + * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info + * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info + */ +static VALUE +ossl_ts_token_info_initialize(VALUE self, VALUE der) +{ + TS_TST_INFO *info = DATA_PTR(self); + BIO *in; + + der = ossl_to_der_if_possible(der); + in = ossl_obj2bio(&der); + info = d2i_TS_TST_INFO_bio(in, &info); + BIO_free(in); + if (!info) { + DATA_PTR(self) = NULL; + ossl_raise(eTimestampError, "Error when decoding the timestamp token info"); + } + DATA_PTR(self) = info; + + return self; +} + +/* + * Returns the version number of the token info. With compliant servers, + * this value should be +1+ if present. If status is GRANTED or + * GRANTED_WITH_MODS. + * + * call-seq: + * token_info.version -> Integer or nil + */ +static VALUE +ossl_ts_token_info_get_version(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return LONG2NUM(TS_TST_INFO_get_version(info)); +} + +/* + * Returns the timestamp policy object identifier of the policy this timestamp + * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never + * +nil+. + * + * ===Example: + * id = token_info.policy_id + * puts id -> "1.2.3.4.5" + * + * call-seq: + * token_info.policy_id -> string or nil + */ +static VALUE +ossl_ts_token_info_get_policy_id(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return get_asn1obj(TS_TST_INFO_get_policy_id(info)); +} + +/* + * Returns the 'short name' of the object identifier representing the algorithm + * that was used to derive the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. If status is + * GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * algo = token_info.algorithm + * puts algo -> "SHA1" + * + * call-seq: + * token_info.algorithm -> string or nil + */ +static VALUE +ossl_ts_token_info_get_algorithm(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + X509_ALGOR *algo; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + algo = TS_MSG_IMPRINT_get_algo(mi); + return get_asn1obj(algo->algorithm); +} + +/* + * Returns the message imprint digest. For valid timestamps, + * this is the same value that was already given in the Request. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * ===Example: + * mi = token_info.msg_imprint + * puts mi -> "DEADBEEF" + * + * call-seq: + * token_info.msg_imprint -> string. + */ +static VALUE +ossl_ts_token_info_get_msg_imprint(VALUE self) +{ + TS_TST_INFO *info; + TS_MSG_IMPRINT *mi; + ASN1_OCTET_STRING *hashed_msg; + VALUE ret; + + GetTSTokenInfo(self, info); + mi = TS_TST_INFO_get_msg_imprint(info); + hashed_msg = TS_MSG_IMPRINT_get_msg(mi); + ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length); + + return ret; +} + +/* + * Returns serial number of the timestamp token. This value shall never be the + * same for two timestamp tokens issued by a dedicated timestamp authority. + * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.serial_number -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_serial_number(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1integer_to_num(TS_TST_INFO_get_serial(info)); +} + +/* + * Returns time when this timestamp token was created. If status is GRANTED or + * GRANTED_WITH_MODS, this is never +nil+. + * + * call-seq: + * token_info.gen_time -> Time + */ +static VALUE +ossl_ts_token_info_get_gen_time(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1time_to_time(TS_TST_INFO_get_time(info)); +} + +/* + * If the ordering field is missing, or if the ordering field is present + * and set to false, then the genTime field only indicates the time at + * which the time-stamp token has been created by the TSA. In such a + * case, the ordering of time-stamp tokens issued by the same TSA or + * different TSAs is only possible when the difference between the + * genTime of the first time-stamp token and the genTime of the second + * time-stamp token is greater than the sum of the accuracies of the + * genTime for each time-stamp token. + * + * If the ordering field is present and set to true, every time-stamp + * token from the same TSA can always be ordered based on the genTime + * field, regardless of the genTime accuracy. + * + * call-seq: + * token_info.ordering -> true, falses or nil + */ +static VALUE +ossl_ts_token_info_get_ordering(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse; +} + +/* + * If the timestamp token is valid then this field contains the same nonce that + * was passed to the timestamp server in the initial Request. + * + * call-seq: + * token_info.nonce -> BN or nil + */ +static VALUE +ossl_ts_token_info_get_nonce(VALUE self) +{ + TS_TST_INFO *info; + const ASN1_INTEGER *nonce; + + GetTSTokenInfo(self, info); + if (!(nonce = TS_TST_INFO_get_nonce(info))) + return Qnil; + + return asn1integer_to_num(nonce); +} + +/* + * Returns the TokenInfo in DER-encoded form. + * + * call-seq: + * token_info.to_der -> string + */ +static VALUE +ossl_ts_token_info_to_der(VALUE self) +{ + TS_TST_INFO *info; + + GetTSTokenInfo(self, info); + return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO); +} + +static ASN1_INTEGER * +ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data) +{ + ASN1_INTEGER **snptr = (ASN1_INTEGER **)data; + ASN1_INTEGER *sn = *snptr; + *snptr = NULL; + return sn; +} + +static int +#if !defined(LIBRESSL_VERSION_NUMBER) +ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec) +#else +ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec) +#endif +{ + *sec = *((long *)data); + *usec = 0; + return 1; +} + +static VALUE +ossl_evp_get_digestbyname_i(VALUE arg) +{ + return (VALUE)ossl_evp_get_digestbyname(arg); +} + +static VALUE +ossl_obj2bio_i(VALUE arg) +{ + return (VALUE)ossl_obj2bio((VALUE *)arg); +} + +/* + * Creates a Response with the help of an OpenSSL::PKey, an + * OpenSSL::X509::Certificate and a Request. + * + * Mandatory parameters for timestamp creation that need to be set in the + * Request: + * + * * Request#algorithm + * * Request#message_imprint + * + * Mandatory parameters that need to be set in the Factory: + * * Factory#serial_number + * * Factory#gen_time + * * Factory#allowed_digests + * + * In addition one of either Request#policy_id or Factory#default_policy_id + * must be set. + * + * Raises a TimestampError if creation fails, though successfully created error + * responses may be returned. + * + * call-seq: + * factory.create_timestamp(key, certificate, request) -> Response + */ +static VALUE +ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request) +{ + VALUE serial_number, def_policy_id, gen_time, additional_certs, allowed_digests; + VALUE str; + STACK_OF(X509) *inter_certs; + VALUE tsresp, ret = Qnil; + EVP_PKEY *sign_key; + X509 *tsa_cert; + TS_REQ *req; + TS_RESP *response = NULL; + TS_RESP_CTX *ctx = NULL; + BIO *req_bio; + ASN1_INTEGER *asn1_serial = NULL; + ASN1_OBJECT *def_policy_id_obj = NULL; + long lgen_time; + const char * err_msg = NULL; + int status = 0; + + tsresp = NewTSResponse(cTimestampResponse); + tsa_cert = GetX509CertPtr(certificate); + sign_key = GetPrivPKeyPtr(key); + GetTSRequest(request, req); + + gen_time = ossl_tsfac_get_gen_time(self); + if (!rb_obj_is_instance_of(gen_time, rb_cTime)) { + err_msg = "@gen_time must be a Time."; + goto end; + } + lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0)); + + serial_number = ossl_tsfac_get_serial_number(self); + if (NIL_P(serial_number)) { + err_msg = "@serial_number must be set."; + goto end; + } + asn1_serial = num_to_asn1integer(serial_number, NULL); + + def_policy_id = ossl_tsfac_get_default_policy_id(self); + if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) { + err_msg = "No policy id in the request and no default policy set"; + goto end; + } + if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) { + def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status); + if (status) + goto end; + } + + if (!(ctx = TS_RESP_CTX_new())) { + err_msg = "Memory allocation failed."; + goto end; + } + + TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial); + if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) { + err_msg = "Certificate does not contain the timestamping extension"; + goto end; + } + + additional_certs = ossl_tsfac_get_additional_certs(self); + if (rb_obj_is_kind_of(additional_certs, rb_cArray)) { + inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status); + if (status) + goto end; + + /* this dups the sk_X509 and ups each cert's ref count */ + TS_RESP_CTX_set_certs(ctx, inter_certs); + sk_X509_pop_free(inter_certs, X509_free); + } + + TS_RESP_CTX_set_signer_key(ctx, sign_key); + if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) + TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj); + if (TS_REQ_get_policy_id(req)) + TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req)); + TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time); + + allowed_digests = ossl_tsfac_get_allowed_digests(self); + if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) { + int i; + VALUE rbmd; + const EVP_MD *md; + + for (i = 0; i < RARRAY_LEN(allowed_digests); i++) { + rbmd = rb_ary_entry(allowed_digests, i); + md = (const EVP_MD *)rb_protect(ossl_evp_get_digestbyname_i, rbmd, &status); + if (status) + goto end; + TS_RESP_CTX_add_md(ctx, md); + } + } + + str = rb_protect(ossl_to_der, request, &status); + if (status) + goto end; + + req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status); + if (status) + goto end; + + response = TS_RESP_create_response(ctx, req_bio); + BIO_free(req_bio); + + if (!response) { + err_msg = "Error during response generation"; + goto end; + } + + /* bad responses aren't exceptional, but openssl still sets error + * information. */ + ossl_clear_error(); + + SetTSResponse(tsresp, response); + ret = tsresp; + +end: + ASN1_INTEGER_free(asn1_serial); + ASN1_OBJECT_free(def_policy_id_obj); + TS_RESP_CTX_free(ctx); + if (err_msg) + rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg))); + if (status) + rb_jump_tag(status); + return ret; +} + +/* + * INIT + */ +void +Init_ossl_ts(void) +{ + #if 0 + mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ + #endif + + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server rejects the message imprint algorithm used in the + * +Request+ + */ + sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG")); + + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server was not able to process the +Request+ properly. + */ + sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST")); + /* + * Possible return value for +Response#failure_info+. Indicates that the + * timestamp server was not able to parse certain data in the +Request+. + */ + sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT")); + + sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE")); + sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY")); + sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION")); + sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE")); + sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE")); + + /* Document-class: OpenSSL::Timestamp + * Provides classes and methods to request, create and validate + * {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps. + * Request may be used to either create requests from scratch or to parse + * existing requests that again can be used to request timestamps from a + * timestamp server, e.g. via the net/http. The resulting timestamp + * response may be parsed using Response. + * + * Please note that Response is read-only and immutable. To create a + * Response, an instance of Factory as well as a valid Request are needed. + * + * ===Create a Response: + * #Assumes ts.p12 is a PKCS#12-compatible file with a private key + * #and a certificate that has an extended key usage of 'timeStamping' + * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') + * md = OpenSSL::Digest.new('SHA1') + * hash = md.digest(data) #some binary data to be timestamped + * req = OpenSSL::Timestamp::Request.new + * req.algorithm = 'SHA1' + * req.message_imprint = hash + * req.policy_id = "1.2.3.4.5" + * req.nonce = 42 + * fac = OpenSSL::Timestamp::Factory.new + * fac.gen_time = Time.now + * fac.serial_number = 1 + * timestamp = fac.create_timestamp(p12.key, p12.certificate, req) + * + * ===Verify a timestamp response: + * #Assume we have a timestamp token in a file called ts.der + * ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der')) + * #Assume we have the Request for this token in a file called req.der + * req = OpenSSL::Timestamp::Request.new(File.binread('req.der')) + * # Assume the associated root CA certificate is contained in a + * # DER-encoded file named root.cer + * root = OpenSSL::X509::Certificate.new(File.binread('root.cer')) + * # get the necessary intermediate certificates, available in + * # DER-encoded form in inter1.cer and inter2.cer + * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) + * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) + * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails + * + */ + mTimestamp = rb_define_module_under(mOSSL, "Timestamp"); + + /* Document-class: OpenSSL::Timestamp::TimestampError + * Generic exception class of the Timestamp module. + */ + eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError); + + /* Document-class: OpenSSL::Timestamp::Response + * Immutable and read-only representation of a timestamp response returned + * from a timestamp server after receiving an associated Request. Allows + * access to specific information about the response but also allows to + * verify the Response. + */ + cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject); + rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc); + rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1); + rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0); + rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0); + rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0); + rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0); + 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, "verify", ossl_ts_resp_verify, -1); + + /* Document-class: OpenSSL::Timestamp::TokenInfo + * Immutable and read-only representation of a timestamp token info from a + * Response. + */ + cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject); + rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc); + rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1); + rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0); + rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0); + rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0); + rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0); + rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0); + rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0); + 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); + + /* Document-class: OpenSSL::Timestamp::Request + * Allows to create timestamp requests or parse existing ones. A Request is + * also needed for creating timestamps from scratch with Factory. When + * created from scratch, some default values are set: + * * version is set to +1+ + * * cert_requested is set to +true+ + * * algorithm, message_imprint, policy_id, and nonce are set to +false+ + */ + cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject); + rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc); + rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1); + rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1); + rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0); + rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1); + rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0); + rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1); + rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0); + rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1); + rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0); + rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1); + rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0); + 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); + + /* + * Indicates a successful response. Equal to +0+. + */ + rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED)); + /* + * Indicates a successful response that probably contains modifications + * from the initial request. Equal to +1+. + */ + rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS)); + /* + * Indicates a failure. No timestamp token was created. Equal to +2+. + */ + rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION)); + /* + * Indicates a failure. No timestamp token was created. Equal to +3+. + */ + rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING)); + /* + * Indicates a failure. No timestamp token was created. Revocation of a + * certificate is imminent. Equal to +4+. + */ + rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING)); + /* + * Indicates a failure. No timestamp token was created. A certificate + * has been revoked. Equal to +5+. + */ + rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION)); + + /* Document-class: OpenSSL::Timestamp::Factory + * + * Used to generate a Response from scratch. + * + * Please bear in mind that the implementation will always apply and prefer + * the policy object identifier given in the request over the default policy + * id specified in the Factory. As a consequence, +default_policy_id+ will + * only be applied if no Request#policy_id was given. But this also means + * that one needs to check the policy identifier in the request manually + * before creating the Response, e.g. to check whether it complies to a + * specific set of acceptable policies. + * + * There exists also the possibility to add certificates (instances of + * OpenSSL::X509::Certificate) besides the timestamping certificate + * that will be included in the resulting timestamp token if + * Request#cert_requested? is +true+. Ideally, one would also include any + * intermediate certificates (the root certificate can be left out - in + * order to trust it any verifying party will have to be in its possession + * anyway). This simplifies validation of the timestamp since these + * intermediate certificates are "already there" and need not be passed as + * external parameters to Response#verify anymore, thus minimizing external + * resources needed for verification. + * + * ===Example: Inclusion of (untrusted) intermediate certificates + * + * Assume we received a timestamp request that has set Request#policy_id to + * +nil+ and Request#cert_requested? to true. The raw request bytes are + * stored in a variable called +req_raw+. We'd still like to integrate + * the necessary intermediate certificates (in +inter1.cer+ and + * +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+ + * is a PKCS#12-compatible file including the private key and the + * timestamping certificate. + * + * req = OpenSSL::Timestamp::Request.new(raw_bytes) + * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') + * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) + * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) + * fac = OpenSSL::Timestamp::Factory.new + * fac.gen_time = Time.now + * fac.serial_number = 1 + * fac.allowed_digests = ["sha256", "sha384", "sha512"] + * #needed because the Request contained no policy identifier + * fac.default_policy_id = '1.2.3.4.5' + * fac.additional_certificates = [ inter1, inter2 ] + * timestamp = fac.create_timestamp(p12.key, p12.certificate, req) + * + * ==Attributes + * + * ===default_policy_id + * + * Request#policy_id will always be preferred over this if present in the + * Request, only if Request#policy_id is nil default_policy will be used. + * If none of both is present, a TimestampError will be raised when trying + * to create a Response. + * + * call-seq: + * factory.default_policy_id = "string" -> string + * factory.default_policy_id -> string or nil + * + * ===serial_number + * + * Sets or retrieves the serial number to be used for timestamp creation. + * Must be present for timestamp creation. + * + * call-seq: + * factory.serial_number = number -> number + * factory.serial_number -> number or nil + * + * ===gen_time + * + * Sets or retrieves the Time value to be used in the Response. Must be + * present for timestamp creation. + * + * call-seq: + * factory.gen_time = Time -> Time + * factory.gen_time -> Time or nil + * + * ===additional_certs + * + * Sets or retrieves additional certificates apart from the timestamp + * certificate (e.g. intermediate certificates) to be added to the Response. + * Must be an Array of OpenSSL::X509::Certificate. + * + * call-seq: + * factory.additional_certs = [cert1, cert2] -> [ cert1, cert2 ] + * factory.additional_certs -> array or nil + * + * ===allowed_digests + * + * Sets or retrieves the digest algorithms that the factory is allowed + * create timestamps for. Known vulnerable or weak algorithms should not be + * allowed where possible. + * Must be an Array of String or OpenSSL::Digest subclass instances. + * + * call-seq: + * factory.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA256').new] -> [ "sha1", OpenSSL::Digest) ] + * factory.allowed_digests -> array or nil + * + */ + cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject); + rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0); + rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0); + rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0); + rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0); + rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0); + rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3); +} + +#endif diff --git a/ruby/ext/openssl/ossl_ts.h b/ruby/ext/openssl/ossl_ts.h new file mode 100644 index 000000000..25fb0e1d6 --- /dev/null +++ b/ruby/ext/openssl/ossl_ts.h @@ -0,0 +1,16 @@ +/* + * + * Copyright (C) 2010 Martin Bosslet + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ + +#if !defined(_OSSL_TS_H_) +#define _OSSL_TS_H_ + +void Init_ossl_ts(void); + +#endif diff --git a/ruby/ext/openssl/ossl_version.h b/ruby/ext/openssl/ossl_version.h deleted file mode 100644 index c162f8c2a..000000000 --- a/ruby/ext/openssl/ossl_version.h +++ /dev/null @@ -1,15 +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'.) - */ -#if !defined(_OSSL_VERSION_H_) -#define _OSSL_VERSION_H_ - -#define OSSL_VERSION "2.1.2" - -#endif /* _OSSL_VERSION_H_ */ diff --git a/ruby/ext/openssl/ossl_x509.c b/ruby/ext/openssl/ossl_x509.c index 8a061b068..f8470703f 100644 --- a/ruby/ext/openssl/ossl_x509.c +++ b/ruby/ext/openssl/ossl_x509.c @@ -44,7 +44,13 @@ Init_ossl_x509(void) Init_ossl_x509revoked(); Init_ossl_x509store(); + /* Constants are up-to-date with 1.1.1. */ + + /* 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); @@ -76,8 +82,71 @@ Init_ossl_x509(void) DefX509Const(V_ERR_AKID_SKID_MISMATCH); DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH); DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN); + DefX509Const(V_ERR_UNABLE_TO_GET_CRL_ISSUER); + DefX509Const(V_ERR_UNHANDLED_CRITICAL_EXTENSION); + DefX509Const(V_ERR_KEYUSAGE_NO_CRL_SIGN); + DefX509Const(V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION); + DefX509Const(V_ERR_INVALID_NON_CA); + DefX509Const(V_ERR_PROXY_PATH_LENGTH_EXCEEDED); + DefX509Const(V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE); + DefX509Const(V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED); + DefX509Const(V_ERR_INVALID_EXTENSION); + DefX509Const(V_ERR_INVALID_POLICY_EXTENSION); + DefX509Const(V_ERR_NO_EXPLICIT_POLICY); + DefX509Const(V_ERR_DIFFERENT_CRL_SCOPE); + DefX509Const(V_ERR_UNSUPPORTED_EXTENSION_FEATURE); + DefX509Const(V_ERR_UNNESTED_RESOURCE); + DefX509Const(V_ERR_PERMITTED_VIOLATION); + DefX509Const(V_ERR_EXCLUDED_VIOLATION); + DefX509Const(V_ERR_SUBTREE_MINMAX); DefX509Const(V_ERR_APPLICATION_VERIFICATION); + DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_TYPE); + 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) + DefX509Const(V_ERR_PATH_LOOP); +#endif +#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) + DefX509Const(V_ERR_SUITE_B_INVALID_VERSION); + DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM); + DefX509Const(V_ERR_SUITE_B_INVALID_CURVE); + DefX509Const(V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM); + DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED); + DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256); +#endif + DefX509Const(V_ERR_HOSTNAME_MISMATCH); + DefX509Const(V_ERR_EMAIL_MISMATCH); + DefX509Const(V_ERR_IP_ADDRESS_MISMATCH); +#if defined(X509_V_ERR_DANE_NO_MATCH) + 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) + DefX509Const(V_ERR_NO_VALID_SCTS); +#endif +#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) + DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION); +#endif +#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) + DefX509Const(V_ERR_OCSP_VERIFY_NEEDED); + DefX509Const(V_ERR_OCSP_VERIFY_FAILED); + DefX509Const(V_ERR_OCSP_CERT_UNKNOWN); +#endif + /* Certificate verify flags */ + /* Set by Store#flags= and StoreContext#flags=. */ + DefX509Const(V_FLAG_USE_CHECK_TIME); /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the * certificate chain leaf. */ DefX509Const(V_FLAG_CRL_CHECK); @@ -116,12 +185,28 @@ Init_ossl_x509(void) /* Set by Store#flags= and StoreContext#flags=. Enables checking of the * signature of the root self-signed CA. */ DefX509Const(V_FLAG_CHECK_SS_SIGNATURE); -#if defined(X509_V_FLAG_TRUSTED_FIRST) /* Set by Store#flags= and StoreContext#flags=. When constructing a * 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) + /* 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); +#endif + /* 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. */ diff --git a/ruby/ext/openssl/ossl_x509cert.c b/ruby/ext/openssl/ossl_x509cert.c index 40542c4a7..996f18417 100644 --- a/ruby/ext/openssl/ossl_x509cert.c +++ b/ruby/ext/openssl/ossl_x509cert.c @@ -115,24 +115,27 @@ static VALUE ossl_x509_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509 *x509, *x = DATA_PTR(self); + X509 *x509, *x509_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { /* create just empty X509Cert */ return self; } arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); - x509 = PEM_read_bio_X509(in, &x, NULL, NULL); - DATA_PTR(self) = x; + x509 = d2i_X509_bio(in, NULL); if (!x509) { - OSSL_BIO_reset(in); - x509 = d2i_X509_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + x509 = PEM_read_bio_X509(in, NULL, NULL, NULL); } BIO_free(in); - if (!x509) ossl_raise(eX509CertError, NULL); + if (!x509) + ossl_raise(eX509CertError, "PEM_read_bio_X509"); + + RTYPEDDATA_DATA(self) = x509; + X509_free(x509_orig); return self; } @@ -704,6 +707,157 @@ ossl_x509_eq(VALUE self, VALUE other) return !X509_cmp(a, b) ? Qtrue : Qfalse; } +struct load_chained_certificates_arguments { + VALUE certificates; + X509 *certificate; +}; + +static VALUE +load_chained_certificates_append_push(VALUE _arguments) { + struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments; + + if (arguments->certificates == Qnil) { + arguments->certificates = rb_ary_new(); + } + + rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate)); + + return Qnil; +} + +static VALUE +load_chained_certificate_append_ensure(VALUE _arguments) { + struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments; + + X509_free(arguments->certificate); + + return Qnil; +} + +inline static VALUE +load_chained_certificates_append(VALUE certificates, X509 *certificate) { + struct load_chained_certificates_arguments arguments; + arguments.certificates = certificates; + arguments.certificate = certificate; + + rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments); + + return arguments.certificates; +} + +static VALUE +load_chained_certificates_PEM(BIO *in) { + VALUE certificates = Qnil; + X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL); + + /* If we cannot read even one certificate: */ + if (certificate == NULL) { + /* If we cannot read one certificate because we could not read the PEM encoding: */ + if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) { + ossl_clear_error(); + } + + if (ERR_peek_last_error()) + ossl_raise(eX509CertError, NULL); + else + return Qnil; + } + + certificates = load_chained_certificates_append(Qnil, certificate); + + while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) { + load_chained_certificates_append(certificates, certificate); + } + + /* We tried to read one more certificate but could not read start line: */ + if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) { + /* This is not an error, it means we are finished: */ + ossl_clear_error(); + + return certificates; + } + + /* Alternatively, if we reached the end of the file and there was no error: */ + if (BIO_eof(in) && !ERR_peek_last_error()) { + return certificates; + } else { + /* Otherwise, we tried to read a certificate but failed somewhere: */ + ossl_raise(eX509CertError, NULL); + } +} + +static VALUE +load_chained_certificates_DER(BIO *in) { + X509 *certificate = d2i_X509_bio(in, NULL); + + /* If we cannot read one certificate: */ + if (certificate == NULL) { + /* Ignore error. We could not load. */ + ossl_clear_error(); + + return Qnil; + } + + return load_chained_certificates_append(Qnil, certificate); +} + +static VALUE +load_chained_certificates(VALUE _io) { + BIO *in = (BIO*)_io; + VALUE certificates = Qnil; + + /* + DER is a binary format and it may contain octets within it that look like + PEM encoded certificates. So we need to check DER first. + */ + certificates = load_chained_certificates_DER(in); + + if (certificates != Qnil) + return certificates; + + OSSL_BIO_reset(in); + + certificates = load_chained_certificates_PEM(in); + + if (certificates != Qnil) + return certificates; + + /* Otherwise we couldn't read the output correctly so fail: */ + ossl_raise(eX509CertError, "Could not detect format of certificate data!"); +} + +static VALUE +load_chained_certificates_ensure(VALUE _io) { + BIO *in = (BIO*)_io; + + BIO_free(in); + + return Qnil; +} + +/* + * call-seq: + * OpenSSL::X509::Certificate.load(string) -> [certs...] + * OpenSSL::X509::Certificate.load(file) -> [certs...] + * + * Read the chained certificates from the given input. Supports both PEM + * and DER encoded certificates. + * + * PEM is a text format and supports more than one certificate. + * + * DER is a binary format and only supports one certificate. + * + * If the file is empty, or contains only unrelated data, an + * +OpenSSL::X509::CertificateError+ exception will be raised. + */ +static VALUE +ossl_x509_load(VALUE klass, VALUE buffer) +{ + BIO *in = ossl_obj2bio(&buffer); + + return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in); +} + /* * INIT */ @@ -730,7 +884,7 @@ Init_ossl_x509cert(void) * Certificate is capable of handling DER-encoded certificates and * certificates encoded in OpenSSL's PEM format. * - * raw = File.read "cert.cer" # DER- or PEM-encoded + * raw = File.binread "cert.cer" # DER- or PEM-encoded * certificate = OpenSSL::X509::Certificate.new raw * * === Saving a certificate to a file @@ -788,7 +942,7 @@ Init_ossl_x509cert(void) * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true)) * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false)) - * root_ca.sign(root_key, OpenSSL::Digest::SHA256.new) + * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256')) * * The next step is to create the end-entity certificate using the root CA * certificate. @@ -807,11 +961,13 @@ Init_ossl_x509cert(void) * ef.issuer_certificate = root_ca * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true)) * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false)) - * cert.sign(root_key, OpenSSL::Digest::SHA256.new) + * cert.sign(root_key, OpenSSL::Digest.new('SHA256')) * */ cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject); + rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1); + rb_define_alloc_func(cX509Cert, ossl_x509_alloc); rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1); rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1); diff --git a/ruby/ext/openssl/ossl_x509crl.c b/ruby/ext/openssl/ossl_x509crl.c index b0badf45c..863f0286c 100644 --- a/ruby/ext/openssl/ossl_x509crl.c +++ b/ruby/ext/openssl/ossl_x509crl.c @@ -93,23 +93,26 @@ static VALUE ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509_CRL *crl, *x = DATA_PTR(self); + X509_CRL *crl, *crl_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { return self; } arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); - crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL); - DATA_PTR(self) = x; + crl = d2i_X509_CRL_bio(in, NULL); if (!crl) { - OSSL_BIO_reset(in); - crl = d2i_X509_CRL_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); } BIO_free(in); - if (!crl) ossl_raise(eX509CRLError, NULL); + if (!crl) + ossl_raise(eX509CRLError, "PEM_read_bio_X509_CRL"); + + RTYPEDDATA_DATA(self) = crl; + X509_CRL_free(crl_orig); return self; } diff --git a/ruby/ext/openssl/ossl_x509ext.c b/ruby/ext/openssl/ossl_x509ext.c index 30ec09d7a..e54102c77 100644 --- a/ruby/ext/openssl/ossl_x509ext.c +++ b/ruby/ext/openssl/ossl_x509ext.c @@ -226,11 +226,10 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) GetX509ExtFactory(self, ctx); obj = NewX509Ext(cX509Ext); rconf = rb_iv_get(self, "@config"); - conf = NIL_P(rconf) ? NULL : DupConfigPtr(rconf); + conf = NIL_P(rconf) ? NULL : GetConfig(rconf); X509V3_set_nconf(ctx, conf); ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr)); X509V3_set_ctx_nodb(ctx); - NCONF_free(conf); if (!ext){ ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr); } @@ -402,6 +401,19 @@ ossl_x509ext_get_value(VALUE obj) return ret; } +static VALUE +ossl_x509ext_get_value_der(VALUE obj) +{ + X509_EXTENSION *ext; + ASN1_OCTET_STRING *value; + + GetX509Ext(obj, ext); + if ((value = X509_EXTENSION_get_data(ext)) == NULL) + ossl_raise(eX509ExtError, NULL); + + return rb_str_new((const char *)value->data, value->length); +} + static VALUE ossl_x509ext_get_critical(VALUE obj) { @@ -472,6 +484,7 @@ Init_ossl_x509ext(void) rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0); rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0); + rb_define_method(cX509Ext, "value_der", ossl_x509ext_get_value_der, 0); rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0); rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0); } diff --git a/ruby/ext/openssl/ossl_x509name.c b/ruby/ext/openssl/ossl_x509name.c index 1ea8400db..13a2b2c03 100644 --- a/ruby/ext/openssl/ossl_x509name.c +++ b/ruby/ext/openssl/ossl_x509name.c @@ -291,7 +291,14 @@ x509name_print(VALUE self, unsigned long iflag) * * OpenSSL::X509::Name::MULTILINE * * If _format_ is omitted, the largely broken and traditional OpenSSL format - * is used. + * (X509_NAME_oneline() format) is chosen. + * + * Use of this method is discouraged. None of the formats other than + * OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent + * behavior through \OpenSSL versions. + * + * It is recommended to use #to_utf8 instead, which is equivalent to calling + * name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8"). */ static VALUE ossl_x509name_to_s(int argc, VALUE *argv, VALUE self) @@ -387,17 +394,21 @@ ossl_x509name_cmp0(VALUE self, VALUE other) /* * call-seq: - * name.cmp(other) -> -1 | 0 | 1 - * name <=> other -> -1 | 0 | 1 + * name.cmp(other) -> -1 | 0 | 1 | nil + * name <=> other -> -1 | 0 | 1 | nil * * Compares this Name with _other_ and returns +0+ if they are the same and +-1+ * or ++1+ if they are greater or less than each other respectively. + * Returns +nil+ if they are not comparable (i.e. different types). */ static VALUE ossl_x509name_cmp(VALUE self, VALUE other) { int result; + if (!rb_obj_is_kind_of(other, cX509Name)) + return Qnil; + result = ossl_x509name_cmp0(self, other); if (result < 0) return INT2FIX(-1); if (result > 0) return INT2FIX(1); @@ -494,7 +505,7 @@ ossl_x509name_to_der(VALUE self) * You can create a Name by parsing a distinguished name String or by * supplying the distinguished name as an Array. * - * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example' + * name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody' * * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] */ diff --git a/ruby/ext/openssl/ossl_x509req.c b/ruby/ext/openssl/ossl_x509req.c index 2c20042a9..6eb91e9c2 100644 --- a/ruby/ext/openssl/ossl_x509req.c +++ b/ruby/ext/openssl/ossl_x509req.c @@ -79,23 +79,26 @@ static VALUE ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; - X509_REQ *req, *x = DATA_PTR(self); + X509_REQ *req, *req_orig = RTYPEDDATA_DATA(self); VALUE arg; + rb_check_frozen(self); if (rb_scan_args(argc, argv, "01", &arg) == 0) { return self; } arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); - req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL); - DATA_PTR(self) = x; + req = d2i_X509_REQ_bio(in, NULL); if (!req) { - OSSL_BIO_reset(in); - req = d2i_X509_REQ_bio(in, &x); - DATA_PTR(self) = x; + OSSL_BIO_reset(in); + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); } BIO_free(in); - if (!req) ossl_raise(eX509ReqError, NULL); + if (!req) + ossl_raise(eX509ReqError, "PEM_read_bio_X509_REQ"); + + RTYPEDDATA_DATA(self) = req; + X509_REQ_free(req_orig); return self; } diff --git a/ruby/ext/openssl/ossl_x509store.c b/ruby/ext/openssl/ossl_x509store.c index 74bc7763a..7c546187c 100644 --- a/ruby/ext/openssl/ossl_x509store.c +++ b/ruby/ext/openssl/ossl_x509store.c @@ -52,8 +52,15 @@ struct ossl_verify_cb_args { }; static VALUE -call_verify_cb_proc(struct ossl_verify_cb_args *args) +ossl_x509stctx_new_i(VALUE arg) { + return ossl_x509stctx_new((X509_STORE_CTX *)arg); +} + +static VALUE +call_verify_cb_proc(VALUE arg) +{ + struct ossl_verify_cb_args *args = (struct ossl_verify_cb_args *)arg; return rb_funcall(args->proc, rb_intern("call"), 2, args->preverify_ok, args->store_ctx); } @@ -69,7 +76,7 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx) return ok; ret = Qfalse; - rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state); + rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state); if (state) { rb_set_errinfo(Qnil); rb_warn("StoreContext initialization failure"); @@ -78,7 +85,7 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx) args.proc = proc; args.preverify_ok = ok ? Qtrue : Qfalse; args.store_ctx = rctx; - ret = rb_protect((VALUE(*)(VALUE))call_verify_cb_proc, (VALUE)&args, &state); + ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state); if (state) { rb_set_errinfo(Qnil); rb_warn("exception in verify_callback is ignored"); @@ -105,6 +112,13 @@ VALUE cX509Store; VALUE cX509StoreContext; VALUE eX509StoreError; +static void +ossl_x509store_mark(void *ptr) +{ + X509_STORE *store = ptr; + rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx)); +} + static void ossl_x509store_free(void *ptr) { @@ -114,7 +128,7 @@ ossl_x509store_free(void *ptr) static const rb_data_type_t ossl_x509store_type = { "OpenSSL/X509/STORE", { - 0, ossl_x509store_free, + ossl_x509store_mark, ossl_x509store_free, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, }; @@ -157,9 +171,8 @@ ossl_x509store_alloc(VALUE klass) VALUE obj; obj = NewX509Store(klass); - if((store = X509_STORE_new()) == NULL){ - ossl_raise(eX509StoreError, NULL); - } + if ((store = X509_STORE_new()) == NULL) + ossl_raise(eX509StoreError, "X509_STORE_new"); SetX509Store(obj, store); return obj; @@ -192,8 +205,9 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) { X509_STORE *store; -/* BUG: This method takes any number of arguments but appears to ignore them. */ GetX509Store(self, store); + if (argc != 0) + rb_warn("OpenSSL::X509::Store.new does not take any arguments"); #if !defined(HAVE_OPAQUE_OPENSSL) /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */ store->ex_data.sk = NULL; @@ -214,8 +228,16 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * store.flags = flags * - * Sets _flags_ to the Store. _flags_ consists of zero or more of the constants - * defined in with name V_FLAG_* or'ed together. + * Sets the default flags used by certificate chain verification performed with + * the Store. + * + * _flags_ consists of zero or more of the constants defined in OpenSSL::X509 + * with name V_FLAG_* or'ed together. + * + * OpenSSL::X509::StoreContext#flags= can be used to change the flags for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_flags(3). */ static VALUE ossl_x509store_set_flags(VALUE self, VALUE flags) @@ -233,9 +255,9 @@ ossl_x509store_set_flags(VALUE self, VALUE flags) * call-seq: * store.purpose = purpose * - * Sets the store's purpose to _purpose_. If specified, the verifications on - * the store will check every untrusted certificate's extensions are consistent - * with the purpose. The purpose is specified by constants: + * Sets the store's default verification purpose. If specified, + * the verifications on the store will check every certificate's extensions are + * consistent with the purpose. The purpose is specified by constants: * * * X509::PURPOSE_SSL_CLIENT * * X509::PURPOSE_SSL_SERVER @@ -246,6 +268,11 @@ ossl_x509store_set_flags(VALUE self, VALUE flags) * * X509::PURPOSE_ANY * * X509::PURPOSE_OCSP_HELPER * * X509::PURPOSE_TIMESTAMP_SIGN + * + * OpenSSL::X509::StoreContext#purpose= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_purpose(3). */ static VALUE ossl_x509store_set_purpose(VALUE self, VALUE purpose) @@ -262,6 +289,14 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose) /* * call-seq: * store.trust = trust + * + * Sets the default trust settings used by the certificate verification with + * the store. + * + * OpenSSL::X509::StoreContext#trust= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_trust(3). */ static VALUE ossl_x509store_set_trust(VALUE self, VALUE trust) @@ -279,7 +314,13 @@ ossl_x509store_set_trust(VALUE self, VALUE trust) * call-seq: * store.time = time * - * Sets the time to be used in verifications. + * Sets the time to be used in the certificate verifications with the store. + * By default, if not specified, the current system time is used. + * + * OpenSSL::X509::StoreContext#time= can be used to change the value for a + * single verification operation. + * + * See also the man page X509_VERIFY_PARAM_set_time(3). */ static VALUE ossl_x509store_set_time(VALUE self, VALUE time) @@ -295,23 +336,23 @@ ossl_x509store_set_time(VALUE self, VALUE time) * Adds the certificates in _file_ to the certificate store. _file_ is the path * to the file, and the file contains one or more certificates in PEM format * concatenated together. + * + * See also the man page X509_LOOKUP_file(3). */ static VALUE ossl_x509store_add_file(VALUE self, VALUE file) { X509_STORE *store; X509_LOOKUP *lookup; - char *path = NULL; + const char *path; - if(file != Qnil){ - path = StringValueCStr(file); - } GetX509Store(self, store); + path = StringValueCStr(file); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if(lookup == NULL) ossl_raise(eX509StoreError, NULL); - if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (!lookup) + 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() @@ -330,32 +371,23 @@ ossl_x509store_add_file(VALUE self, VALUE file) * store.add_path(path) -> self * * Adds _path_ as the hash dir to be looked up by the store. + * + * See also the man page X509_LOOKUP_hash_dir(3). */ -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io_prelude.h" -#include "enclose_io_common.h" -// --------- [Enclose.IO Hack end] --------- static VALUE ossl_x509store_add_path(VALUE self, VALUE dir) { X509_STORE *store; X509_LOOKUP *lookup; - char *path = NULL; + const char *path; - if(dir != Qnil){ - path = StringValueCStr(dir); - } GetX509Store(self, store); + path = StringValueCStr(dir); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); - if(lookup == NULL) ossl_raise(eX509StoreError, NULL); - // --------- [Enclose.IO Hack start] --------- - #ifdef ENCLOSE_IO_RUBYC_2ND_PASS - path = enclose_io_ifextract(path, NULL); - #endif - // --------- [Enclose.IO Hack end] --------- - if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (!lookup) + ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) + ossl_raise(eX509StoreError, "X509_LOOKUP_add_dir"); return self; } @@ -370,6 +402,8 @@ ossl_x509store_add_path(VALUE self, VALUE dir) * * * OpenSSL::X509::DEFAULT_CERT_FILE * * OpenSSL::X509::DEFAULT_CERT_DIR + * + * See also the man page X509_STORE_set_default_paths(3). */ static VALUE ossl_x509store_set_default_paths(VALUE self) @@ -377,18 +411,19 @@ ossl_x509store_set_default_paths(VALUE self) X509_STORE *store; GetX509Store(self, store); - if (X509_STORE_set_default_paths(store) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_set_default_paths(store) != 1) + ossl_raise(eX509StoreError, "X509_STORE_set_default_paths"); return Qnil; } /* * call-seq: - * store.add_cert(cert) + * store.add_cert(cert) -> self * * Adds the OpenSSL::X509::Certificate _cert_ to the certificate store. + * + * See also the man page X509_STORE_add_cert(3). */ static VALUE ossl_x509store_add_cert(VALUE self, VALUE arg) @@ -398,9 +433,8 @@ ossl_x509store_add_cert(VALUE self, VALUE arg) cert = GetX509CertPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); - if (X509_STORE_add_cert(store, cert) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_add_cert(store, cert) != 1) + ossl_raise(eX509StoreError, "X509_STORE_add_cert"); return self; } @@ -410,6 +444,8 @@ ossl_x509store_add_cert(VALUE self, VALUE arg) * store.add_crl(crl) -> self * * Adds the OpenSSL::X509::CRL _crl_ to the store. + * + * See also the man page X509_STORE_add_crl(3). */ static VALUE ossl_x509store_add_crl(VALUE self, VALUE arg) @@ -419,9 +455,8 @@ ossl_x509store_add_crl(VALUE self, VALUE arg) crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); - if (X509_STORE_add_crl(store, crl) != 1){ - ossl_raise(eX509StoreError, NULL); - } + if (X509_STORE_add_crl(store, crl) != 1) + ossl_raise(eX509StoreError, "X509_STORE_add_crl"); return self; } @@ -465,23 +500,16 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self) return result; } -/* - * Public Functions - */ -static void ossl_x509stctx_free(void*); - - -static const rb_data_type_t ossl_x509stctx_type = { - "OpenSSL/X509/STORE_CTX", - { - 0, ossl_x509stctx_free, - }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, -}; - /* * Private functions */ +static void +ossl_x509stctx_mark(void *ptr) +{ + X509_STORE_CTX *ctx = ptr; + rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx)); +} + static void ossl_x509stctx_free(void *ptr) { @@ -493,6 +521,14 @@ ossl_x509stctx_free(void *ptr) X509_STORE_CTX_free(ctx); } +static const rb_data_type_t ossl_x509stctx_type = { + "OpenSSL/X509/STORE_CTX", + { + ossl_x509stctx_mark, ossl_x509stctx_free, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, +}; + static VALUE ossl_x509stctx_alloc(VALUE klass) { @@ -500,9 +536,8 @@ ossl_x509stctx_alloc(VALUE klass) VALUE obj; obj = NewX509StCtx(klass); - if((ctx = X509_STORE_CTX_new()) == NULL){ - ossl_raise(eX509StoreError, NULL); - } + if ((ctx = X509_STORE_CTX_new()) == NULL) + ossl_raise(eX509StoreError, "X509_STORE_CTX_new"); SetX509StCtx(obj, ctx); return obj; @@ -526,7 +561,9 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE); /* * call-seq: - * StoreContext.new(store, cert = nil, chain = nil) + * StoreContext.new(store, cert = nil, untrusted = nil) + * + * Sets up a StoreContext for a verification of the X.509 certificate _cert_. */ static VALUE ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) @@ -536,15 +573,24 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) X509_STORE *x509st; X509 *x509 = NULL; STACK_OF(X509) *x509s = NULL; + int state; rb_scan_args(argc, argv, "12", &store, &cert, &chain); GetX509StCtx(self, ctx); GetX509Store(store, x509st); - if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ - if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); - if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ + if (!NIL_P(cert)) + x509 = DupX509CertPtr(cert); /* NEED TO DUP */ + if (!NIL_P(chain)) { + x509s = ossl_protect_x509_ary2sk(chain, &state); + if (state) { + X509_free(x509); + rb_jump_tag(state); + } + } + if (X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ + X509_free(x509); sk_X509_pop_free(x509s, X509_free); - ossl_raise(eX509StoreError, NULL); + ossl_raise(eX509StoreError, "X509_STORE_CTX_init"); } if (!NIL_P(t = rb_iv_get(store, "@time"))) ossl_x509stctx_set_time(self, t); @@ -557,6 +603,10 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: * stctx.verify -> true | false + * + * Performs the certificate verification using the parameters set to _stctx_. + * + * See also the man page X509_verify_cert(3). */ static VALUE ossl_x509stctx_verify(VALUE self) @@ -569,48 +619,45 @@ ossl_x509stctx_verify(VALUE self) switch (X509_verify_cert(ctx)) { case 1: - return Qtrue; + return Qtrue; case 0: - ossl_clear_error(); - return Qfalse; + ossl_clear_error(); + return Qfalse; default: - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, "X509_verify_cert"); } } /* * call-seq: - * stctx.chain -> Array of X509::Certificate + * stctx.chain -> nil | Array of X509::Certificate + * + * Returns the verified chain. + * + * See also the man page X509_STORE_CTX_set0_verified_chain(3). */ static VALUE ossl_x509stctx_get_chain(VALUE self) { X509_STORE_CTX *ctx; - STACK_OF(X509) *chain; - X509 *x509; - int i, num; - VALUE ary; + const STACK_OF(X509) *chain; GetX509StCtx(self, ctx); - if((chain = X509_STORE_CTX_get0_chain(ctx)) == NULL){ - return Qnil; - } - if((num = sk_X509_num(chain)) < 0){ - OSSL_Debug("certs in chain < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(num); - for(i = 0; i < num; i++) { - x509 = sk_X509_value(chain, i); - rb_ary_push(ary, ossl_x509_new(x509)); - } - - return ary; + chain = X509_STORE_CTX_get0_chain(ctx); + if (!chain) + return Qnil; /* Could be an empty array instead? */ + return ossl_x509_sk2ary(chain); } /* * call-seq: * stctx.error -> Integer + * + * Returns the error code of _stctx_. This is typically called after #verify + * is done, or from the verification callback set to + * OpenSSL::X509::Store#verify_callback=. + * + * See also the man page X509_STORE_CTX_get_error(3). */ static VALUE ossl_x509stctx_get_err(VALUE self) @@ -625,6 +672,11 @@ ossl_x509stctx_get_err(VALUE self) /* * call-seq: * stctx.error = error_code + * + * Sets the error code of _stctx_. This is used by the verification callback + * set to OpenSSL::X509::Store#verify_callback=. + * + * See also the man page X509_STORE_CTX_set_error(3). */ static VALUE ossl_x509stctx_set_error(VALUE self, VALUE err) @@ -641,7 +693,10 @@ ossl_x509stctx_set_error(VALUE self, VALUE err) * call-seq: * stctx.error_string -> String * - * Returns the error string corresponding to the error code retrieved by #error. + * Returns the human readable error string corresponding to the error code + * retrieved by #error. + * + * See also the man page X509_verify_cert_error_string(3). */ static VALUE ossl_x509stctx_get_err_string(VALUE self) @@ -658,6 +713,10 @@ ossl_x509stctx_get_err_string(VALUE self) /* * call-seq: * stctx.error_depth -> Integer + * + * Returns the depth of the chain. This is used in combination with #error. + * + * See also the man page X509_STORE_CTX_get_error_depth(3). */ static VALUE ossl_x509stctx_get_err_depth(VALUE self) @@ -672,6 +731,10 @@ ossl_x509stctx_get_err_depth(VALUE self) /* * call-seq: * stctx.current_cert -> X509::Certificate + * + * Returns the certificate which caused the error. + * + * See also the man page X509_STORE_CTX_get_current_cert(3). */ static VALUE ossl_x509stctx_get_curr_cert(VALUE self) @@ -686,6 +749,10 @@ ossl_x509stctx_get_curr_cert(VALUE self) /* * call-seq: * stctx.current_crl -> X509::CRL + * + * Returns the CRL which caused the error. + * + * See also the man page X509_STORE_CTX_get_current_crl(3). */ static VALUE ossl_x509stctx_get_curr_crl(VALUE self) @@ -705,7 +772,10 @@ ossl_x509stctx_get_curr_crl(VALUE self) * call-seq: * stctx.flags = flags * - * Sets the verification flags to the context. See Store#flags=. + * Sets the verification flags to the context. This overrides the default value + * set by Store#flags=. + * + * See also the man page X509_VERIFY_PARAM_set_flags(3). */ static VALUE ossl_x509stctx_set_flags(VALUE self, VALUE flags) @@ -723,7 +793,10 @@ ossl_x509stctx_set_flags(VALUE self, VALUE flags) * call-seq: * stctx.purpose = purpose * - * Sets the purpose of the context. See Store#purpose=. + * Sets the purpose of the context. This overrides the default value set by + * Store#purpose=. + * + * See also the man page X509_VERIFY_PARAM_set_purpose(3). */ static VALUE ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) @@ -740,6 +813,11 @@ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) /* * call-seq: * stctx.trust = trust + * + * Sets the trust settings of the context. This overrides the default value set + * by Store#trust=. + * + * See also the man page X509_VERIFY_PARAM_set_trust(3). */ static VALUE ossl_x509stctx_set_trust(VALUE self, VALUE trust) @@ -758,6 +836,8 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust) * stctx.time = time * * Sets the time used in the verification. If not set, the current time is used. + * + * See also the man page X509_VERIFY_PARAM_set_time(3). */ static VALUE ossl_x509stctx_set_time(VALUE self, VALUE time) @@ -833,23 +913,37 @@ Init_ossl_x509store(void) cX509Store = rb_define_class_under(mX509, "Store", rb_cObject); /* * The callback for additional certificate verification. It is invoked for - * each untrusted certificate in the chain. + * each certificate in the chain and can be used to implement custom + * certificate verification conditions. * * The callback is invoked with two values, a boolean that indicates if the * pre-verification by OpenSSL has succeeded or not, and the StoreContext in - * use. The callback must return either true or false. + * use. + * + * The callback can use StoreContext#error= to change the error code as + * needed. The callback must return either true or false. + * + * NOTE: any exception raised within the callback will be ignored. + * + * See also the man page X509_STORE_CTX_set_verify_cb(3). */ rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse); /* * The error code set by the last call of #verify. + * + * See also StoreContext#error. */ rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse); /* * The description for the error code set by the last call of #verify. + * + * See also StoreContext#error_string. */ rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse); /* * The certificate chain constructed by the last call of #verify. + * + * See also StoreContext#chain. */ rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse); rb_define_alloc_func(cX509Store, ossl_x509store_alloc); diff --git a/ruby/ext/openssl/ruby_missing.h b/ruby/ext/openssl/ruby_missing.h deleted file mode 100644 index 069acc8b1..000000000 --- a/ruby/ext/openssl/ruby_missing.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 'OpenSSL for Ruby' project - * Copyright (C) 2001-2003 Michal Rokos - * All rights reserved. - */ -/* - * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#if !defined(_OSSL_RUBY_MISSING_H_) -#define _OSSL_RUBY_MISSING_H_ - -/* Ruby 2.4 */ -#ifndef RB_INTEGER_TYPE_P -# define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM)) -#endif - -/* Ruby 2.5 */ -#ifndef ST2FIX -# define RB_ST2FIX(h) LONG2FIX((long)(h)) -# define ST2FIX(h) RB_ST2FIX(h) -#endif - -#endif /* _OSSL_RUBY_MISSING_H_ */ diff --git a/ruby/ext/pathname/depend b/ruby/ext/pathname/depend index 1e13dd5f3..53041d2ef 100644 --- a/ruby/ext/pathname/depend +++ b/ruby/ext/pathname/depend @@ -4,9 +4,165 @@ pathname.o: $(arch_hdrdir)/ruby/config.h pathname.o: $(hdrdir)/ruby.h pathname.o: $(hdrdir)/ruby/assert.h pathname.o: $(hdrdir)/ruby/backward.h +pathname.o: $(hdrdir)/ruby/backward/2/assume.h +pathname.o: $(hdrdir)/ruby/backward/2/attributes.h +pathname.o: $(hdrdir)/ruby/backward/2/bool.h +pathname.o: $(hdrdir)/ruby/backward/2/inttypes.h +pathname.o: $(hdrdir)/ruby/backward/2/limits.h +pathname.o: $(hdrdir)/ruby/backward/2/long_long.h +pathname.o: $(hdrdir)/ruby/backward/2/stdalign.h +pathname.o: $(hdrdir)/ruby/backward/2/stdarg.h pathname.o: $(hdrdir)/ruby/defines.h pathname.o: $(hdrdir)/ruby/encoding.h pathname.o: $(hdrdir)/ruby/intern.h +pathname.o: $(hdrdir)/ruby/internal/anyargs.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/char.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/double.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/int.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/long.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/short.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +pathname.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +pathname.o: $(hdrdir)/ruby/internal/assume.h +pathname.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +pathname.o: $(hdrdir)/ruby/internal/attr/artificial.h +pathname.o: $(hdrdir)/ruby/internal/attr/cold.h +pathname.o: $(hdrdir)/ruby/internal/attr/const.h +pathname.o: $(hdrdir)/ruby/internal/attr/constexpr.h +pathname.o: $(hdrdir)/ruby/internal/attr/deprecated.h +pathname.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +pathname.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +pathname.o: $(hdrdir)/ruby/internal/attr/error.h +pathname.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +pathname.o: $(hdrdir)/ruby/internal/attr/forceinline.h +pathname.o: $(hdrdir)/ruby/internal/attr/format.h +pathname.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +pathname.o: $(hdrdir)/ruby/internal/attr/noalias.h +pathname.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +pathname.o: $(hdrdir)/ruby/internal/attr/noexcept.h +pathname.o: $(hdrdir)/ruby/internal/attr/noinline.h +pathname.o: $(hdrdir)/ruby/internal/attr/nonnull.h +pathname.o: $(hdrdir)/ruby/internal/attr/noreturn.h +pathname.o: $(hdrdir)/ruby/internal/attr/pure.h +pathname.o: $(hdrdir)/ruby/internal/attr/restrict.h +pathname.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +pathname.o: $(hdrdir)/ruby/internal/attr/warning.h +pathname.o: $(hdrdir)/ruby/internal/attr/weakref.h +pathname.o: $(hdrdir)/ruby/internal/cast.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +pathname.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +pathname.o: $(hdrdir)/ruby/internal/compiler_since.h +pathname.o: $(hdrdir)/ruby/internal/config.h +pathname.o: $(hdrdir)/ruby/internal/constant_p.h +pathname.o: $(hdrdir)/ruby/internal/core.h +pathname.o: $(hdrdir)/ruby/internal/core/rarray.h +pathname.o: $(hdrdir)/ruby/internal/core/rbasic.h +pathname.o: $(hdrdir)/ruby/internal/core/rbignum.h +pathname.o: $(hdrdir)/ruby/internal/core/rclass.h +pathname.o: $(hdrdir)/ruby/internal/core/rdata.h +pathname.o: $(hdrdir)/ruby/internal/core/rfile.h +pathname.o: $(hdrdir)/ruby/internal/core/rhash.h +pathname.o: $(hdrdir)/ruby/internal/core/robject.h +pathname.o: $(hdrdir)/ruby/internal/core/rregexp.h +pathname.o: $(hdrdir)/ruby/internal/core/rstring.h +pathname.o: $(hdrdir)/ruby/internal/core/rstruct.h +pathname.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +pathname.o: $(hdrdir)/ruby/internal/ctype.h +pathname.o: $(hdrdir)/ruby/internal/dllexport.h +pathname.o: $(hdrdir)/ruby/internal/dosish.h +pathname.o: $(hdrdir)/ruby/internal/encoding/coderange.h +pathname.o: $(hdrdir)/ruby/internal/encoding/ctype.h +pathname.o: $(hdrdir)/ruby/internal/encoding/encoding.h +pathname.o: $(hdrdir)/ruby/internal/encoding/pathname.h +pathname.o: $(hdrdir)/ruby/internal/encoding/re.h +pathname.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +pathname.o: $(hdrdir)/ruby/internal/encoding/string.h +pathname.o: $(hdrdir)/ruby/internal/encoding/symbol.h +pathname.o: $(hdrdir)/ruby/internal/encoding/transcode.h +pathname.o: $(hdrdir)/ruby/internal/error.h +pathname.o: $(hdrdir)/ruby/internal/eval.h +pathname.o: $(hdrdir)/ruby/internal/event.h +pathname.o: $(hdrdir)/ruby/internal/fl_type.h +pathname.o: $(hdrdir)/ruby/internal/gc.h +pathname.o: $(hdrdir)/ruby/internal/glob.h +pathname.o: $(hdrdir)/ruby/internal/globals.h +pathname.o: $(hdrdir)/ruby/internal/has/attribute.h +pathname.o: $(hdrdir)/ruby/internal/has/builtin.h +pathname.o: $(hdrdir)/ruby/internal/has/c_attribute.h +pathname.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +pathname.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +pathname.o: $(hdrdir)/ruby/internal/has/extension.h +pathname.o: $(hdrdir)/ruby/internal/has/feature.h +pathname.o: $(hdrdir)/ruby/internal/has/warning.h +pathname.o: $(hdrdir)/ruby/internal/intern/array.h +pathname.o: $(hdrdir)/ruby/internal/intern/bignum.h +pathname.o: $(hdrdir)/ruby/internal/intern/class.h +pathname.o: $(hdrdir)/ruby/internal/intern/compar.h +pathname.o: $(hdrdir)/ruby/internal/intern/complex.h +pathname.o: $(hdrdir)/ruby/internal/intern/cont.h +pathname.o: $(hdrdir)/ruby/internal/intern/dir.h +pathname.o: $(hdrdir)/ruby/internal/intern/enum.h +pathname.o: $(hdrdir)/ruby/internal/intern/enumerator.h +pathname.o: $(hdrdir)/ruby/internal/intern/error.h +pathname.o: $(hdrdir)/ruby/internal/intern/eval.h +pathname.o: $(hdrdir)/ruby/internal/intern/file.h +pathname.o: $(hdrdir)/ruby/internal/intern/gc.h +pathname.o: $(hdrdir)/ruby/internal/intern/hash.h +pathname.o: $(hdrdir)/ruby/internal/intern/io.h +pathname.o: $(hdrdir)/ruby/internal/intern/load.h +pathname.o: $(hdrdir)/ruby/internal/intern/marshal.h +pathname.o: $(hdrdir)/ruby/internal/intern/numeric.h +pathname.o: $(hdrdir)/ruby/internal/intern/object.h +pathname.o: $(hdrdir)/ruby/internal/intern/parse.h +pathname.o: $(hdrdir)/ruby/internal/intern/proc.h +pathname.o: $(hdrdir)/ruby/internal/intern/process.h +pathname.o: $(hdrdir)/ruby/internal/intern/random.h +pathname.o: $(hdrdir)/ruby/internal/intern/range.h +pathname.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +pathname.o: $(hdrdir)/ruby/internal/intern/sprintf.h +pathname.o: $(hdrdir)/ruby/internal/intern/string.h +pathname.o: $(hdrdir)/ruby/internal/intern/struct.h +pathname.o: $(hdrdir)/ruby/internal/intern/thread.h +pathname.o: $(hdrdir)/ruby/internal/intern/time.h +pathname.o: $(hdrdir)/ruby/internal/intern/variable.h +pathname.o: $(hdrdir)/ruby/internal/intern/vm.h +pathname.o: $(hdrdir)/ruby/internal/interpreter.h +pathname.o: $(hdrdir)/ruby/internal/iterator.h +pathname.o: $(hdrdir)/ruby/internal/memory.h +pathname.o: $(hdrdir)/ruby/internal/method.h +pathname.o: $(hdrdir)/ruby/internal/module.h +pathname.o: $(hdrdir)/ruby/internal/newobj.h +pathname.o: $(hdrdir)/ruby/internal/rgengc.h +pathname.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +pathname.o: $(hdrdir)/ruby/internal/value.h +pathname.o: $(hdrdir)/ruby/internal/value_type.h +pathname.o: $(hdrdir)/ruby/internal/variable.h +pathname.o: $(hdrdir)/ruby/internal/warning_push.h +pathname.o: $(hdrdir)/ruby/internal/xmalloc.h pathname.o: $(hdrdir)/ruby/missing.h pathname.o: $(hdrdir)/ruby/onigmo.h pathname.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/pathname/lib/pathname.rb b/ruby/ext/pathname/lib/pathname.rb index dc4a7c022..3799d589d 100644 --- a/ruby/ext/pathname/lib/pathname.rb +++ b/ruby/ext/pathname/lib/pathname.rb @@ -35,6 +35,13 @@ class Pathname SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/ end + if File.dirname('A:') == 'A:.' # DOSish drive letter + ABSOLUTE_PATH = /\A(?:[A-Za-z]:|#{SEPARATOR_PAT})/o + else + ABSOLUTE_PATH = /\A#{SEPARATOR_PAT}/o + end + private_constant :ABSOLUTE_PATH + # :startdoc: # chop_basename(path) -> [pre-basename, basename] or nil @@ -222,7 +229,7 @@ def root? # p.absolute? # #=> false def absolute? - !relative? + ABSOLUTE_PATH.match? @path end # The opposite of Pathname#absolute? @@ -237,11 +244,7 @@ def absolute? # p.relative? # #=> true def relative? - path = @path - while r = chop_basename(path) - path, = r - end - path == '' + !absolute? end # @@ -502,6 +505,9 @@ def each_child(with_directory=true, &b) # # ArgumentError is raised when it cannot find a relative path. # + # Note that this method does not handle situations where the case sensitivity + # of the filesystem in use differs from the operating system default. + # def relative_path_from(base_directory) base_directory = Pathname.new(base_directory) unless base_directory.is_a? Pathname dest_directory = self.cleanpath.to_s @@ -569,13 +575,14 @@ def find(ignore_error: true) # :yield: pathname class Pathname # * FileUtils * + autoload(:FileUtils, 'fileutils') + # Creates a full path, including any intermediate directories that don't yet # exist. # # See FileUtils.mkpath and FileUtils.mkdir_p - def mkpath - require 'fileutils' - FileUtils.mkpath(@path) + def mkpath(mode: nil) + FileUtils.mkpath(@path, mode: mode) nil end @@ -585,7 +592,6 @@ def mkpath def rmtree # The name "rmtree" is borrowed from File::Path of Perl. # File::Path provides "mkpath" and "rmtree". - require 'fileutils' FileUtils.rm_r(@path) nil end diff --git a/ruby/ext/pathname/pathname.c b/ruby/ext/pathname/pathname.c index 15f80d487..1d4ed2814 100644 --- a/ruby/ext/pathname/pathname.c +++ b/ruby/ext/pathname/pathname.c @@ -138,7 +138,7 @@ path_freeze(VALUE self) static VALUE path_taint(VALUE self) { - rb_warning("Pathname#taint is deprecated and will be removed in Ruby 3.2."); + rb_warn("Pathname#taint is deprecated and will be removed in Ruby 3.2."); return self; } @@ -151,7 +151,7 @@ path_taint(VALUE self) static VALUE path_untaint(VALUE self) { - rb_warning("Pathname#untaint is deprecated and will be removed in Ruby 3.2."); + rb_warn("Pathname#untaint is deprecated and will be removed in Ruby 3.2."); return self; } @@ -360,10 +360,10 @@ path_each_line(int argc, VALUE *argv, VALUE self) args[0] = get_strpath(self); n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]); if (rb_block_given_p()) { - return rb_block_call(rb_cFile, id_foreach, 1+n, args, 0, 0); + return rb_block_call_kw(rb_cFile, id_foreach, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS); } else { - return rb_funcallv(rb_cFile, id_foreach, 1+n, args); + return rb_funcallv_kw(rb_cFile, id_foreach, 1+n, args, RB_PASS_CALLED_KEYWORDS); } } @@ -554,7 +554,7 @@ path_mtime(VALUE self) /* * call-seq: - * pathname.chmod -> integer + * pathname.chmod(mode_int) -> integer * * Changes file permissions. * @@ -568,7 +568,7 @@ path_chmod(VALUE self, VALUE mode) /* * call-seq: - * pathname.lchmod -> integer + * pathname.lchmod(mode_int) -> integer * * Same as Pathname.chmod, but does not follow symbolic links. * @@ -582,7 +582,7 @@ path_lchmod(VALUE self, VALUE mode) /* * call-seq: - * pathname.chown -> integer + * pathname.chown(owner_int, group_int) -> integer * * Change owner and group of the file. * @@ -596,7 +596,7 @@ path_chown(VALUE self, VALUE owner, VALUE group) /* * call-seq: - * pathname.lchown -> integer + * pathname.lchown(owner_int, group_int) -> integer * * Same as Pathname.chown, but does not follow symbolic links. * @@ -610,8 +610,8 @@ path_lchown(VALUE self, VALUE owner, VALUE group) /* * call-seq: - * pathname.fnmatch(pattern, [flags]) -> string - * pathname.fnmatch?(pattern, [flags]) -> string + * pathname.fnmatch(pattern, [flags]) -> true or false + * pathname.fnmatch?(pattern, [flags]) -> true or false * * Return +true+ if the receiver matches the given pattern. * @@ -657,6 +657,13 @@ path_make_link(VALUE self, VALUE old) } /* + * call-seq: + * pathname.open() + * pathname.open(mode="r" [, opt]) -> file + * pathname.open([mode [, perm]] [, opt]) -> file + * pathname.open(mode="r" [, opt]) {|file| block } -> obj + * pathname.open([mode [, perm]] [, opt]) {|file| block } -> obj + * * Opens the file for reading or writing. * * See File.open. @@ -827,7 +834,7 @@ path_split(VALUE self) VALUE str = get_strpath(self); VALUE ary, dirname, basename; ary = rb_funcall(rb_cFile, id_split, 1, str); - ary = rb_check_array_type(ary); + Check_Type(ary, T_ARRAY); dirname = rb_ary_entry(ary, 0); basename = rb_ary_entry(ary, 1); dirname = rb_class_new_instance(1, &dirname, rb_obj_class(self)); @@ -1482,6 +1489,8 @@ path_f_pathname(VALUE self, VALUE str) * - #binread(*args) * - #readlines(*args) * - #sysopen(*args) + * - #write(*args) + * - #binwrite(*args) * * === Utilities * @@ -1503,6 +1512,10 @@ path_f_pathname(VALUE self, VALUE str) void Init_pathname(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + InitVM(pathname); rb_cPathname = rb_define_class("Pathname", rb_cObject); diff --git a/ruby/ext/pathname/pathname.gemspec b/ruby/ext/pathname/pathname.gemspec new file mode 100644 index 000000000..5aaa8f8dd --- /dev/null +++ b/ruby/ext/pathname/pathname.gemspec @@ -0,0 +1,25 @@ +Gem::Specification.new do |spec| + spec.name = "pathname" + spec.version = "0.2.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Representation of the name of a file or directory on the filesystem} + spec.description = %q{Representation of the name of a file or directory on the filesystem} + spec.homepage = "https://github.com/ruby/pathname" + 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.require_paths = ["lib"] + spec.extensions = %w[ext/pathname/extconf.rb] +end diff --git a/ruby/ext/psych/depend b/ruby/ext/psych/depend index dc358eaed..444866353 100644 --- a/ruby/ext/psych/depend +++ b/ruby/ext/psych/depend @@ -6,9 +6,165 @@ psych.o: $(arch_hdrdir)/ruby/config.h psych.o: $(hdrdir)/ruby.h psych.o: $(hdrdir)/ruby/assert.h psych.o: $(hdrdir)/ruby/backward.h +psych.o: $(hdrdir)/ruby/backward/2/assume.h +psych.o: $(hdrdir)/ruby/backward/2/attributes.h +psych.o: $(hdrdir)/ruby/backward/2/bool.h +psych.o: $(hdrdir)/ruby/backward/2/inttypes.h +psych.o: $(hdrdir)/ruby/backward/2/limits.h +psych.o: $(hdrdir)/ruby/backward/2/long_long.h +psych.o: $(hdrdir)/ruby/backward/2/stdalign.h +psych.o: $(hdrdir)/ruby/backward/2/stdarg.h psych.o: $(hdrdir)/ruby/defines.h psych.o: $(hdrdir)/ruby/encoding.h psych.o: $(hdrdir)/ruby/intern.h +psych.o: $(hdrdir)/ruby/internal/anyargs.h +psych.o: $(hdrdir)/ruby/internal/arithmetic.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/char.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/double.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/int.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/long.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/short.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +psych.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +psych.o: $(hdrdir)/ruby/internal/assume.h +psych.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +psych.o: $(hdrdir)/ruby/internal/attr/artificial.h +psych.o: $(hdrdir)/ruby/internal/attr/cold.h +psych.o: $(hdrdir)/ruby/internal/attr/const.h +psych.o: $(hdrdir)/ruby/internal/attr/constexpr.h +psych.o: $(hdrdir)/ruby/internal/attr/deprecated.h +psych.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +psych.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +psych.o: $(hdrdir)/ruby/internal/attr/error.h +psych.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +psych.o: $(hdrdir)/ruby/internal/attr/forceinline.h +psych.o: $(hdrdir)/ruby/internal/attr/format.h +psych.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +psych.o: $(hdrdir)/ruby/internal/attr/noalias.h +psych.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +psych.o: $(hdrdir)/ruby/internal/attr/noexcept.h +psych.o: $(hdrdir)/ruby/internal/attr/noinline.h +psych.o: $(hdrdir)/ruby/internal/attr/nonnull.h +psych.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych.o: $(hdrdir)/ruby/internal/attr/pure.h +psych.o: $(hdrdir)/ruby/internal/attr/restrict.h +psych.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +psych.o: $(hdrdir)/ruby/internal/attr/warning.h +psych.o: $(hdrdir)/ruby/internal/attr/weakref.h +psych.o: $(hdrdir)/ruby/internal/cast.h +psych.o: $(hdrdir)/ruby/internal/compiler_is.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +psych.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +psych.o: $(hdrdir)/ruby/internal/compiler_since.h +psych.o: $(hdrdir)/ruby/internal/config.h +psych.o: $(hdrdir)/ruby/internal/constant_p.h +psych.o: $(hdrdir)/ruby/internal/core.h +psych.o: $(hdrdir)/ruby/internal/core/rarray.h +psych.o: $(hdrdir)/ruby/internal/core/rbasic.h +psych.o: $(hdrdir)/ruby/internal/core/rbignum.h +psych.o: $(hdrdir)/ruby/internal/core/rclass.h +psych.o: $(hdrdir)/ruby/internal/core/rdata.h +psych.o: $(hdrdir)/ruby/internal/core/rfile.h +psych.o: $(hdrdir)/ruby/internal/core/rhash.h +psych.o: $(hdrdir)/ruby/internal/core/robject.h +psych.o: $(hdrdir)/ruby/internal/core/rregexp.h +psych.o: $(hdrdir)/ruby/internal/core/rstring.h +psych.o: $(hdrdir)/ruby/internal/core/rstruct.h +psych.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +psych.o: $(hdrdir)/ruby/internal/ctype.h +psych.o: $(hdrdir)/ruby/internal/dllexport.h +psych.o: $(hdrdir)/ruby/internal/dosish.h +psych.o: $(hdrdir)/ruby/internal/encoding/coderange.h +psych.o: $(hdrdir)/ruby/internal/encoding/ctype.h +psych.o: $(hdrdir)/ruby/internal/encoding/encoding.h +psych.o: $(hdrdir)/ruby/internal/encoding/pathname.h +psych.o: $(hdrdir)/ruby/internal/encoding/re.h +psych.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +psych.o: $(hdrdir)/ruby/internal/encoding/string.h +psych.o: $(hdrdir)/ruby/internal/encoding/symbol.h +psych.o: $(hdrdir)/ruby/internal/encoding/transcode.h +psych.o: $(hdrdir)/ruby/internal/error.h +psych.o: $(hdrdir)/ruby/internal/eval.h +psych.o: $(hdrdir)/ruby/internal/event.h +psych.o: $(hdrdir)/ruby/internal/fl_type.h +psych.o: $(hdrdir)/ruby/internal/gc.h +psych.o: $(hdrdir)/ruby/internal/glob.h +psych.o: $(hdrdir)/ruby/internal/globals.h +psych.o: $(hdrdir)/ruby/internal/has/attribute.h +psych.o: $(hdrdir)/ruby/internal/has/builtin.h +psych.o: $(hdrdir)/ruby/internal/has/c_attribute.h +psych.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +psych.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +psych.o: $(hdrdir)/ruby/internal/has/extension.h +psych.o: $(hdrdir)/ruby/internal/has/feature.h +psych.o: $(hdrdir)/ruby/internal/has/warning.h +psych.o: $(hdrdir)/ruby/internal/intern/array.h +psych.o: $(hdrdir)/ruby/internal/intern/bignum.h +psych.o: $(hdrdir)/ruby/internal/intern/class.h +psych.o: $(hdrdir)/ruby/internal/intern/compar.h +psych.o: $(hdrdir)/ruby/internal/intern/complex.h +psych.o: $(hdrdir)/ruby/internal/intern/cont.h +psych.o: $(hdrdir)/ruby/internal/intern/dir.h +psych.o: $(hdrdir)/ruby/internal/intern/enum.h +psych.o: $(hdrdir)/ruby/internal/intern/enumerator.h +psych.o: $(hdrdir)/ruby/internal/intern/error.h +psych.o: $(hdrdir)/ruby/internal/intern/eval.h +psych.o: $(hdrdir)/ruby/internal/intern/file.h +psych.o: $(hdrdir)/ruby/internal/intern/gc.h +psych.o: $(hdrdir)/ruby/internal/intern/hash.h +psych.o: $(hdrdir)/ruby/internal/intern/io.h +psych.o: $(hdrdir)/ruby/internal/intern/load.h +psych.o: $(hdrdir)/ruby/internal/intern/marshal.h +psych.o: $(hdrdir)/ruby/internal/intern/numeric.h +psych.o: $(hdrdir)/ruby/internal/intern/object.h +psych.o: $(hdrdir)/ruby/internal/intern/parse.h +psych.o: $(hdrdir)/ruby/internal/intern/proc.h +psych.o: $(hdrdir)/ruby/internal/intern/process.h +psych.o: $(hdrdir)/ruby/internal/intern/random.h +psych.o: $(hdrdir)/ruby/internal/intern/range.h +psych.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h +psych.o: $(hdrdir)/ruby/internal/intern/string.h +psych.o: $(hdrdir)/ruby/internal/intern/struct.h +psych.o: $(hdrdir)/ruby/internal/intern/thread.h +psych.o: $(hdrdir)/ruby/internal/intern/time.h +psych.o: $(hdrdir)/ruby/internal/intern/variable.h +psych.o: $(hdrdir)/ruby/internal/intern/vm.h +psych.o: $(hdrdir)/ruby/internal/interpreter.h +psych.o: $(hdrdir)/ruby/internal/iterator.h +psych.o: $(hdrdir)/ruby/internal/memory.h +psych.o: $(hdrdir)/ruby/internal/method.h +psych.o: $(hdrdir)/ruby/internal/module.h +psych.o: $(hdrdir)/ruby/internal/newobj.h +psych.o: $(hdrdir)/ruby/internal/rgengc.h +psych.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +psych.o: $(hdrdir)/ruby/internal/value.h +psych.o: $(hdrdir)/ruby/internal/value_type.h +psych.o: $(hdrdir)/ruby/internal/variable.h +psych.o: $(hdrdir)/ruby/internal/warning_push.h +psych.o: $(hdrdir)/ruby/internal/xmalloc.h psych.o: $(hdrdir)/ruby/missing.h psych.o: $(hdrdir)/ruby/onigmo.h psych.o: $(hdrdir)/ruby/oniguruma.h @@ -26,9 +182,165 @@ psych_emitter.o: $(arch_hdrdir)/ruby/config.h psych_emitter.o: $(hdrdir)/ruby.h psych_emitter.o: $(hdrdir)/ruby/assert.h psych_emitter.o: $(hdrdir)/ruby/backward.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/assume.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/attributes.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/bool.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/inttypes.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/limits.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/long_long.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/stdalign.h +psych_emitter.o: $(hdrdir)/ruby/backward/2/stdarg.h psych_emitter.o: $(hdrdir)/ruby/defines.h psych_emitter.o: $(hdrdir)/ruby/encoding.h psych_emitter.o: $(hdrdir)/ruby/intern.h +psych_emitter.o: $(hdrdir)/ruby/internal/anyargs.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/char.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/double.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/int.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/short.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +psych_emitter.o: $(hdrdir)/ruby/internal/assume.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/artificial.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/cold.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/const.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/constexpr.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/deprecated.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/error.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/forceinline.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/format.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/noalias.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/noexcept.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/noinline.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/nonnull.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/pure.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/restrict.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/warning.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/weakref.h +psych_emitter.o: $(hdrdir)/ruby/internal/cast.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +psych_emitter.o: $(hdrdir)/ruby/internal/compiler_since.h +psych_emitter.o: $(hdrdir)/ruby/internal/config.h +psych_emitter.o: $(hdrdir)/ruby/internal/constant_p.h +psych_emitter.o: $(hdrdir)/ruby/internal/core.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rarray.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rbasic.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rbignum.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rclass.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rdata.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rfile.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rhash.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/robject.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rregexp.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rstring.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rstruct.h +psych_emitter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +psych_emitter.o: $(hdrdir)/ruby/internal/ctype.h +psych_emitter.o: $(hdrdir)/ruby/internal/dllexport.h +psych_emitter.o: $(hdrdir)/ruby/internal/dosish.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/coderange.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/ctype.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/encoding.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/pathname.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/re.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/string.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/symbol.h +psych_emitter.o: $(hdrdir)/ruby/internal/encoding/transcode.h +psych_emitter.o: $(hdrdir)/ruby/internal/error.h +psych_emitter.o: $(hdrdir)/ruby/internal/eval.h +psych_emitter.o: $(hdrdir)/ruby/internal/event.h +psych_emitter.o: $(hdrdir)/ruby/internal/fl_type.h +psych_emitter.o: $(hdrdir)/ruby/internal/gc.h +psych_emitter.o: $(hdrdir)/ruby/internal/glob.h +psych_emitter.o: $(hdrdir)/ruby/internal/globals.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/attribute.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/builtin.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/c_attribute.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/extension.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/feature.h +psych_emitter.o: $(hdrdir)/ruby/internal/has/warning.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/array.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/bignum.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/class.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/compar.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/complex.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/cont.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/dir.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/enum.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/enumerator.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/error.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/eval.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/file.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/gc.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/hash.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/io.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/load.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/marshal.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/numeric.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/object.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/parse.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/proc.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/process.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/random.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/range.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/struct.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/thread.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/time.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/variable.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/vm.h +psych_emitter.o: $(hdrdir)/ruby/internal/interpreter.h +psych_emitter.o: $(hdrdir)/ruby/internal/iterator.h +psych_emitter.o: $(hdrdir)/ruby/internal/memory.h +psych_emitter.o: $(hdrdir)/ruby/internal/method.h +psych_emitter.o: $(hdrdir)/ruby/internal/module.h +psych_emitter.o: $(hdrdir)/ruby/internal/newobj.h +psych_emitter.o: $(hdrdir)/ruby/internal/rgengc.h +psych_emitter.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +psych_emitter.o: $(hdrdir)/ruby/internal/value.h +psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h +psych_emitter.o: $(hdrdir)/ruby/internal/variable.h +psych_emitter.o: $(hdrdir)/ruby/internal/warning_push.h +psych_emitter.o: $(hdrdir)/ruby/internal/xmalloc.h psych_emitter.o: $(hdrdir)/ruby/missing.h psych_emitter.o: $(hdrdir)/ruby/onigmo.h psych_emitter.o: $(hdrdir)/ruby/oniguruma.h @@ -46,9 +358,165 @@ psych_parser.o: $(arch_hdrdir)/ruby/config.h psych_parser.o: $(hdrdir)/ruby.h psych_parser.o: $(hdrdir)/ruby/assert.h psych_parser.o: $(hdrdir)/ruby/backward.h +psych_parser.o: $(hdrdir)/ruby/backward/2/assume.h +psych_parser.o: $(hdrdir)/ruby/backward/2/attributes.h +psych_parser.o: $(hdrdir)/ruby/backward/2/bool.h +psych_parser.o: $(hdrdir)/ruby/backward/2/inttypes.h +psych_parser.o: $(hdrdir)/ruby/backward/2/limits.h +psych_parser.o: $(hdrdir)/ruby/backward/2/long_long.h +psych_parser.o: $(hdrdir)/ruby/backward/2/stdalign.h +psych_parser.o: $(hdrdir)/ruby/backward/2/stdarg.h psych_parser.o: $(hdrdir)/ruby/defines.h psych_parser.o: $(hdrdir)/ruby/encoding.h psych_parser.o: $(hdrdir)/ruby/intern.h +psych_parser.o: $(hdrdir)/ruby/internal/anyargs.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +psych_parser.o: $(hdrdir)/ruby/internal/assume.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/artificial.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/cold.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/const.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/error.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/format.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/noalias.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/noinline.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/pure.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/restrict.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/warning.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/weakref.h +psych_parser.o: $(hdrdir)/ruby/internal/cast.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +psych_parser.o: $(hdrdir)/ruby/internal/compiler_since.h +psych_parser.o: $(hdrdir)/ruby/internal/config.h +psych_parser.o: $(hdrdir)/ruby/internal/constant_p.h +psych_parser.o: $(hdrdir)/ruby/internal/core.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rarray.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rbasic.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rbignum.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rclass.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rdata.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rfile.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rhash.h +psych_parser.o: $(hdrdir)/ruby/internal/core/robject.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rregexp.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rstring.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rstruct.h +psych_parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +psych_parser.o: $(hdrdir)/ruby/internal/ctype.h +psych_parser.o: $(hdrdir)/ruby/internal/dllexport.h +psych_parser.o: $(hdrdir)/ruby/internal/dosish.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/re.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/string.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h +psych_parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h +psych_parser.o: $(hdrdir)/ruby/internal/error.h +psych_parser.o: $(hdrdir)/ruby/internal/eval.h +psych_parser.o: $(hdrdir)/ruby/internal/event.h +psych_parser.o: $(hdrdir)/ruby/internal/fl_type.h +psych_parser.o: $(hdrdir)/ruby/internal/gc.h +psych_parser.o: $(hdrdir)/ruby/internal/glob.h +psych_parser.o: $(hdrdir)/ruby/internal/globals.h +psych_parser.o: $(hdrdir)/ruby/internal/has/attribute.h +psych_parser.o: $(hdrdir)/ruby/internal/has/builtin.h +psych_parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h +psych_parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +psych_parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +psych_parser.o: $(hdrdir)/ruby/internal/has/extension.h +psych_parser.o: $(hdrdir)/ruby/internal/has/feature.h +psych_parser.o: $(hdrdir)/ruby/internal/has/warning.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/array.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/bignum.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/class.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/compar.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/complex.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/cont.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/dir.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/enum.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/error.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/eval.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/file.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/gc.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/hash.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/io.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/load.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/marshal.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/numeric.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/object.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/parse.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/proc.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/process.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/random.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/range.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/struct.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/thread.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/time.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/variable.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/vm.h +psych_parser.o: $(hdrdir)/ruby/internal/interpreter.h +psych_parser.o: $(hdrdir)/ruby/internal/iterator.h +psych_parser.o: $(hdrdir)/ruby/internal/memory.h +psych_parser.o: $(hdrdir)/ruby/internal/method.h +psych_parser.o: $(hdrdir)/ruby/internal/module.h +psych_parser.o: $(hdrdir)/ruby/internal/newobj.h +psych_parser.o: $(hdrdir)/ruby/internal/rgengc.h +psych_parser.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +psych_parser.o: $(hdrdir)/ruby/internal/value.h +psych_parser.o: $(hdrdir)/ruby/internal/value_type.h +psych_parser.o: $(hdrdir)/ruby/internal/variable.h +psych_parser.o: $(hdrdir)/ruby/internal/warning_push.h +psych_parser.o: $(hdrdir)/ruby/internal/xmalloc.h psych_parser.o: $(hdrdir)/ruby/missing.h psych_parser.o: $(hdrdir)/ruby/onigmo.h psych_parser.o: $(hdrdir)/ruby/oniguruma.h @@ -66,9 +534,165 @@ psych_to_ruby.o: $(arch_hdrdir)/ruby/config.h psych_to_ruby.o: $(hdrdir)/ruby.h psych_to_ruby.o: $(hdrdir)/ruby/assert.h psych_to_ruby.o: $(hdrdir)/ruby/backward.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/assume.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/attributes.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/bool.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/inttypes.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/limits.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/long_long.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdalign.h +psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdarg.h psych_to_ruby.o: $(hdrdir)/ruby/defines.h psych_to_ruby.o: $(hdrdir)/ruby/encoding.h psych_to_ruby.o: $(hdrdir)/ruby/intern.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/anyargs.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/char.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/double.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/int.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/short.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/assume.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/artificial.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/cold.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/const.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/constexpr.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/deprecated.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/error.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/forceinline.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/format.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noalias.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noexcept.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noinline.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nonnull.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/pure.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/restrict.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/warning.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/weakref.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/cast.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_since.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/config.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/constant_p.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rarray.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbasic.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbignum.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rclass.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rdata.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rfile.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rhash.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/robject.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rregexp.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstring.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstruct.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/ctype.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/dllexport.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/dosish.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/coderange.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/ctype.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/encoding.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/pathname.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/re.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/string.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/symbol.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/transcode.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/error.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/eval.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/event.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/fl_type.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/gc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/glob.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/globals.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/attribute.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/builtin.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/c_attribute.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/extension.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/feature.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/has/warning.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/array.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/bignum.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/class.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/compar.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/complex.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/cont.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/dir.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enum.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enumerator.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/error.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/eval.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/file.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/gc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/hash.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/io.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/load.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/marshal.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/numeric.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/object.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/parse.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/proc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/process.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/random.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/range.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/struct.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/thread.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/time.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/variable.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/vm.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/interpreter.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/iterator.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/memory.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/method.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/module.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/newobj.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/rgengc.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/variable.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/warning_push.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/xmalloc.h psych_to_ruby.o: $(hdrdir)/ruby/missing.h psych_to_ruby.o: $(hdrdir)/ruby/onigmo.h psych_to_ruby.o: $(hdrdir)/ruby/oniguruma.h @@ -86,9 +710,165 @@ psych_yaml_tree.o: $(arch_hdrdir)/ruby/config.h psych_yaml_tree.o: $(hdrdir)/ruby.h psych_yaml_tree.o: $(hdrdir)/ruby/assert.h psych_yaml_tree.o: $(hdrdir)/ruby/backward.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/assume.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/attributes.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/bool.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/inttypes.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/limits.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/long_long.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdalign.h +psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdarg.h psych_yaml_tree.o: $(hdrdir)/ruby/defines.h psych_yaml_tree.o: $(hdrdir)/ruby/encoding.h psych_yaml_tree.o: $(hdrdir)/ruby/intern.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/anyargs.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/char.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/double.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/int.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/short.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/assume.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/artificial.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/cold.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/const.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/constexpr.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/deprecated.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/error.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/forceinline.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/format.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noalias.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noexcept.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noinline.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nonnull.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/pure.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/restrict.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/warning.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/weakref.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/cast.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_since.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/config.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/constant_p.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rarray.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbasic.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbignum.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rclass.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rdata.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rfile.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rhash.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/robject.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rregexp.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstring.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstruct.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/ctype.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/dllexport.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/dosish.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/coderange.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/ctype.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/encoding.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/pathname.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/re.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/string.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/symbol.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/transcode.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/error.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/eval.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/event.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/fl_type.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/gc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/glob.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/globals.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/attribute.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/builtin.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/c_attribute.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/extension.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/feature.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/warning.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/array.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/bignum.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/class.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/compar.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/complex.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/cont.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/dir.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enum.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enumerator.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/error.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/eval.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/file.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/gc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/hash.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/io.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/load.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/marshal.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/numeric.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/object.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/parse.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/proc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/process.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/random.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/range.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/struct.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/thread.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/time.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/variable.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/vm.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/interpreter.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/iterator.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/memory.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/method.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/module.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/newobj.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/rgengc.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/variable.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/warning_push.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/xmalloc.h psych_yaml_tree.o: $(hdrdir)/ruby/missing.h psych_yaml_tree.o: $(hdrdir)/ruby/onigmo.h psych_yaml_tree.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/psych/lib/psych.rb b/ruby/ext/psych/lib/psych.rb index c719b036d..383078788 100644 --- a/ruby/ext/psych/lib/psych.rb +++ b/ruby/ext/psych/lib/psych.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'psych/versions' +require_relative 'psych/versions' case RUBY_ENGINE when 'jruby' - require 'psych_jars' + require_relative 'psych_jars' if JRuby::Util.respond_to?(:load_ext) JRuby::Util.load_ext('org.jruby.ext.psych.PsychLibrary') else @@ -12,28 +12,28 @@ else require 'psych.so' end -require 'psych/nodes' -require 'psych/streaming' -require 'psych/visitors' -require 'psych/handler' -require 'psych/tree_builder' -require 'psych/parser' -require 'psych/omap' -require 'psych/set' -require 'psych/coder' -require 'psych/core_ext' -require 'psych/stream' -require 'psych/json/tree_builder' -require 'psych/json/stream' -require 'psych/handlers/document_stream' -require 'psych/class_loader' +require_relative 'psych/nodes' +require_relative 'psych/streaming' +require_relative 'psych/visitors' +require_relative 'psych/handler' +require_relative 'psych/tree_builder' +require_relative 'psych/parser' +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' +require_relative 'psych/handlers/document_stream' +require_relative 'psych/class_loader' ### # = Overview # # Psych is a YAML parser and emitter. # Psych leverages libyaml [Home page: https://pyyaml.org/wiki/LibYAML] -# or [HG repo: https://bitbucket.org/xi/libyaml] for its YAML parsing +# or [git repo: https://github.com/yaml/libyaml] for its YAML parsing # and emitting capabilities. In addition to wrapping libyaml, Psych also # knows how to serialize and de-serialize most Ruby objects to and from # the YAML format. @@ -74,12 +74,15 @@ # # ==== Reading from a string # -# Psych.load("--- a") # => 'a' -# Psych.load("---\n - a\n - b") # => ['a', 'b'] +# Psych.safe_load("--- a") # => 'a' +# Psych.safe_load("---\n - a\n - b") # => ['a', 'b'] +# # From a trusted string: +# Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42 # # ==== Reading from a file # -# Psych.load_file("database.yml") +# Psych.safe_load_file("data.yml", permitted_classes: [Date]) +# Psych.load_file("trusted_database.yml") # # ==== Exception handling # @@ -230,10 +233,7 @@ module Psych # The version of libyaml Psych is using - LIBYAML_VERSION = Psych.libyaml_version.join '.' - # Deprecation guard - NOT_GIVEN = Object.new - private_constant :NOT_GIVEN + LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze ### # Load +yaml+ in to a Ruby data structure. If multiple documents are @@ -246,11 +246,11 @@ module Psych # # Example: # - # Psych.load("--- a") # => 'a' - # Psych.load("---\n - a\n - b") # => ['a', 'b'] + # Psych.unsafe_load("--- a") # => 'a' + # Psych.unsafe_load("---\n - a\n - b") # => ['a', 'b'] # # begin - # Psych.load("--- `", filename: "file.txt") + # Psych.unsafe_load("--- `", filename: "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" @@ -259,27 +259,21 @@ module Psych # When the optional +symbolize_names+ keyword argument is set to a # true value, returns symbols for keys in Hash objects (default: strings). # - # Psych.load("---\n foo: bar") # => {"foo"=>"bar"} - # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"} + # Psych.unsafe_load("---\n foo: bar") # => {"foo"=>"bar"} + # Psych.unsafe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"} # # Raises a TypeError when `yaml` parameter is NilClass # # NOTE: This method *should not* be used to parse untrusted documents, such as # YAML documents that are supplied via user input. Instead, please use the - # safe_load method. + # load method or the safe_load method. # - def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false - if legacy_filename != NOT_GIVEN - warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE - filename = legacy_filename - end - + def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false result = parse(yaml, filename: filename) return fallback unless result - result = result.to_ruby if result - symbolize_names!(result) if symbolize_names - result + result.to_ruby(symbolize_names: symbolize_names, freeze: freeze) end + class << self; alias :load :unsafe_load; end ### # Safely load the yaml string in +yaml+. By default, only the following @@ -288,7 +282,8 @@ def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, # * TrueClass # * FalseClass # * NilClass - # * Numeric + # * Integer + # * Float # * String # * Array # * Hash @@ -325,27 +320,7 @@ def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"} # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"} # - def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false - if legacy_permitted_classes != NOT_GIVEN - warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE - permitted_classes = legacy_permitted_classes - end - - if legacy_permitted_symbols != NOT_GIVEN - warn_with_uplevel 'Passing permitted_symbols with the 3rd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_symbols: ...) instead.', uplevel: 1 if $VERBOSE - permitted_symbols = legacy_permitted_symbols - end - - if legacy_aliases != NOT_GIVEN - warn_with_uplevel 'Passing aliases with the 4th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, aliases: ...) instead.', uplevel: 1 if $VERBOSE - aliases = legacy_aliases - end - - if legacy_filename != NOT_GIVEN - warn_with_uplevel 'Passing filename with the 5th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE - filename = legacy_filename - end - + def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false result = parse(yaml, filename: filename) return fallback unless result @@ -353,15 +328,54 @@ def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_ permitted_symbols.map(&:to_s)) scanner = ScalarScanner.new class_loader visitor = if aliases - Visitors::ToRuby.new scanner, class_loader + Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze else - Visitors::NoAliasRuby.new scanner, class_loader + Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze end result = visitor.accept result - symbolize_names!(result) if symbolize_names result end + ### + # Load +yaml+ in to a Ruby data structure. If multiple documents are + # 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+. + # + # Raises a Psych::SyntaxError when a YAML syntax error is detected. + # + # Example: + # + # Psych.load("--- a") # => 'a' + # Psych.load("---\n - a\n - b") # => ['a', 'b'] + # + # begin + # Psych.load("--- `", filename: "file.txt") + # rescue Psych::SyntaxError => ex + # ex.file # => 'file.txt' + # ex.message # => "(file.txt): found character that cannot start any token" + # end + # + # When the optional +symbolize_names+ keyword argument is set to a + # true value, returns symbols for keys in Hash objects (default: strings). + # + # Psych.load("---\n foo: bar") # => {"foo"=>"bar"} + # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"} + # + # Raises a TypeError when `yaml` parameter is NilClass. This method is + # similar to `safe_load` except that `Symbol` objects are allowed by default. + # + def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false + safe_load yaml, permitted_classes: permitted_classes, + permitted_symbols: permitted_symbols, + aliases: aliases, + filename: filename, + fallback: fallback, + symbolize_names: symbolize_names, + freeze: freeze + end + ### # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document. # +filename+ is used in the exception message if a Psych::SyntaxError is @@ -381,22 +395,12 @@ def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_ # end # # See Psych::Nodes for more information about YAML AST. - def self.parse yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: NOT_GIVEN - if legacy_filename != NOT_GIVEN - warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse is deprecated. Use keyword argument like Psych.parse(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE - filename = legacy_filename - end - + def self.parse yaml, filename: nil parse_stream(yaml, filename: filename) do |node| return node end - if fallback != NOT_GIVEN - warn_with_uplevel 'Passing the `fallback` keyword argument of Psych.parse is deprecated.', uplevel: 1 if $VERBOSE - fallback - else - false - end + false end ### @@ -445,12 +449,7 @@ def self.parser # Raises a TypeError when NilClass is passed. # # See Psych::Nodes for more information about YAML AST. - def self.parse_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, &block - if legacy_filename != NOT_GIVEN - warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse_stream is deprecated. Use keyword argument like Psych.parse_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE - filename = legacy_filename - end - + def self.parse_stream yaml, filename: nil, &block if block_given? parser = Psych::Parser.new(Handlers::DocumentStream.new(&block)) parser.parse yaml, filename @@ -514,6 +513,79 @@ def self.dump o, io = nil, options = {} visitor.tree.yaml io, options end + ### + # call-seq: + # Psych.safe_dump(o) -> string of yaml + # Psych.safe_dump(o, options) -> string of yaml + # Psych.safe_dump(o, io) -> io object passed in + # Psych.safe_dump(o, io, options) -> io object passed in + # + # Safely dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in + # to control the output format. If an IO object is passed in, the YAML will + # be dumped to that IO object. By default, only the following + # classes are allowed to be serialized: + # + # * TrueClass + # * FalseClass + # * NilClass + # * Integer + # * Float + # * String + # * Array + # * Hash + # + # Arbitrary classes can be allowed by adding those classes to the +permitted_classes+ + # keyword argument. They are additive. For example, to allow Date serialization: + # + # Psych.safe_dump(yaml, permitted_classes: [Date]) + # + # Now the Date class can be dumped in addition to the classes listed above. + # + # A Psych::DisallowedClass exception will be raised if the object contains a + # class that isn't in the +permitted_classes+ list. + # + # Currently supported options are: + # + # [:indentation] Number of space characters used to indent. + # Acceptable value should be in 0..9 range, + # otherwise option is ignored. + # + # Default: 2. + # [:line_width] Max character to wrap line at. + # + # Default: 0 (meaning "wrap at 81"). + # [:canonical] Write "canonical" YAML form (very verbose, yet + # strictly formal). + # + # Default: false. + # [:header] Write %YAML [version] at the beginning of document. + # + # Default: false. + # + # Example: + # + # # Dump an array, get back a YAML string + # Psych.safe_dump(['a', 'b']) # => "---\n- a\n- b\n" + # + # # Dump an array to an IO object + # Psych.safe_dump(['a', 'b'], StringIO.new) # => # + # + # # Dump an array with indentation set + # Psych.safe_dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n" + # + # # Dump an array to an IO with indentation set + # Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3) + def self.safe_dump o, io = nil, options = {} + if Hash === io + options = io + io = nil + end + + visitor = Psych::Visitors::RestrictedYAMLTree.create options + visitor << o + visitor.tree.yaml io, options + end + ### # Dump a list of objects as separate documents to a document stream. # @@ -551,18 +623,13 @@ def self.to_json object # end # list # => ['foo', 'bar'] # - def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [] - if legacy_filename != NOT_GIVEN - warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE - filename = legacy_filename - end - + def self.load_stream yaml, filename: nil, fallback: [], **kwargs result = if block_given? parse_stream(yaml, filename: filename) do |node| - yield node.to_ruby + yield node.to_ruby(**kwargs) end else - parse_stream(yaml, filename: filename).children.map(&:to_ruby) + parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) } end return fallback if result.is_a?(Array) && result.empty? @@ -573,49 +640,59 @@ def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: # Load 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+. - def self.load_file filename, fallback: false + # + # NOTE: This method *should not* be used to parse untrusted documents, such as + # YAML documents that are supplied via user input. Instead, please use the + # safe_load_file method. + def self.unsafe_load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| - self.load f, filename: filename, fallback: fallback + self.unsafe_load f, filename: filename, **kwargs + } + end + + ### + # 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+. + # See safe_load for options. + def self.safe_load_file filename, **kwargs + File.open(filename, 'r:bom|utf-8') { |f| + self.safe_load f, filename: filename, **kwargs + } + end + + ### + # 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+. + # See load for options. + def self.load_file filename, **kwargs + File.open(filename, 'r:bom|utf-8') { |f| + self.load f, filename: filename, **kwargs } end # :stopdoc: - @domain_types = {} def self.add_domain_type domain, type_tag, &block key = ['tag', domain, type_tag].join ':' - @domain_types[key] = [key, block] - @domain_types["tag:#{type_tag}"] = [key, block] + domain_types[key] = [key, block] + domain_types["tag:#{type_tag}"] = [key, block] end def self.add_builtin_type type_tag, &block domain = 'yaml.org,2002' key = ['tag', domain, type_tag].join ':' - @domain_types[key] = [key, block] + domain_types[key] = [key, block] end def self.remove_type type_tag - @domain_types.delete type_tag + domain_types.delete type_tag end - @load_tags = {} - @dump_tags = {} def self.add_tag tag, klass - @load_tags[tag] = klass.name - @dump_tags[klass] = tag - end - - def self.symbolize_names!(result) - case result - when Hash - result.keys.each do |key| - result[key.to_sym] = symbolize_names!(result.delete(key)) - end - when Array - result.map! { |r| symbolize_names!(r) } - end - result + load_tags[tag] = klass.name + dump_tags[klass] = tag end - private_class_method :symbolize_names! # Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower. def self.warn_with_uplevel(message, uplevel: 1) @@ -633,9 +710,32 @@ def self.parse_caller(at) private_class_method :warn_with_uplevel, :parse_caller class << self - attr_accessor :load_tags - attr_accessor :dump_tags - attr_accessor :domain_types + if defined?(Ractor) + require 'forwardable' + extend Forwardable + + class Config + attr_accessor :load_tags, :dump_tags, :domain_types + def initialize + @load_tags = {} + @dump_tags = {} + @domain_types = {} + end + end + + def config + Ractor.current[:PsychConfig] ||= Config.new + end + + def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types= + else + attr_accessor :load_tags + attr_accessor :dump_tags + attr_accessor :domain_types + end end + self.load_tags = {} + self.dump_tags = {} + self.domain_types = {} # :startdoc: end diff --git a/ruby/ext/psych/lib/psych/class_loader.rb b/ruby/ext/psych/lib/psych/class_loader.rb index cfca86845..c2e4ea4c9 100644 --- a/ruby/ext/psych/lib/psych/class_loader.rb +++ b/ruby/ext/psych/lib/psych/class_loader.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'psych/omap' -require 'psych/set' +require_relative 'omap' +require_relative 'set' module Psych class ClassLoader # :nodoc: @@ -35,9 +35,11 @@ def symbolize sym constants.each do |const| konst = const_get const - define_method(const.to_s.downcase) do - load konst - end + class_eval <<~RUBY + def #{const.to_s.downcase} + load #{konst.inspect} + end + RUBY end private @@ -69,7 +71,7 @@ def resolve klassname rescue nil end - }.compact] + }.compact].freeze class Restricted < ClassLoader def initialize classes, symbols @@ -84,7 +86,7 @@ def symbolize sym if @symbols.include? sym super else - raise DisallowedClass, 'Symbol' + raise DisallowedClass.new('load', 'Symbol') end end @@ -94,7 +96,7 @@ def find klassname if @classes.include? klassname super else - raise DisallowedClass, klassname + raise DisallowedClass.new('load', klassname) end end end diff --git a/ruby/ext/psych/lib/psych/core_ext.rb b/ruby/ext/psych/lib/psych/core_ext.rb index 81055cc50..0721a133c 100644 --- a/ruby/ext/psych/lib/psych/core_ext.rb +++ b/ruby/ext/psych/lib/psych/core_ext.rb @@ -15,5 +15,5 @@ def to_yaml options = {} end if defined?(::IRB) - require 'psych/y' + require_relative 'y' end diff --git a/ruby/ext/psych/lib/psych/exception.rb b/ruby/ext/psych/lib/psych/exception.rb index fac0c42b9..f473b95a3 100644 --- a/ruby/ext/psych/lib/psych/exception.rb +++ b/ruby/ext/psych/lib/psych/exception.rb @@ -7,8 +7,8 @@ class BadAlias < Exception end class DisallowedClass < Exception - def initialize klass_name - super "Tried to load unspecified class: #{klass_name}" + def initialize action, klass_name + super "Tried to #{action} unspecified class: #{klass_name}" end end end diff --git a/ruby/ext/psych/lib/psych/handler.rb b/ruby/ext/psych/lib/psych/handler.rb index 8f23e366f..ad7249ff7 100644 --- a/ruby/ext/psych/lib/psych/handler.rb +++ b/ruby/ext/psych/lib/psych/handler.rb @@ -119,7 +119,7 @@ def alias anchor # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value - # +style+ is an integer idicating the string style + # +style+ is an integer indicating the string style # # See the constants in Psych::Nodes::Scalar for the possible values of # +style+ diff --git a/ruby/ext/psych/lib/psych/handlers/document_stream.rb b/ruby/ext/psych/lib/psych/handlers/document_stream.rb index 67da79409..b77115d07 100644 --- a/ruby/ext/psych/lib/psych/handlers/document_stream.rb +++ b/ruby/ext/psych/lib/psych/handlers/document_stream.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/tree_builder' +require_relative '../tree_builder' module Psych module Handlers diff --git a/ruby/ext/psych/lib/psych/handlers/recorder.rb b/ruby/ext/psych/lib/psych/handlers/recorder.rb index a8fc7b114..c98724cb7 100644 --- a/ruby/ext/psych/lib/psych/handlers/recorder.rb +++ b/ruby/ext/psych/lib/psych/handlers/recorder.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/handler' +require_relative '../handler' module Psych module Handlers diff --git a/ruby/ext/psych/lib/psych/json/stream.rb b/ruby/ext/psych/lib/psych/json/stream.rb index 2ebd3d7a6..24dd4b9ba 100644 --- a/ruby/ext/psych/lib/psych/json/stream.rb +++ b/ruby/ext/psych/lib/psych/json/stream.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'psych/json/ruby_events' -require 'psych/json/yaml_events' +require_relative 'ruby_events' +require_relative 'yaml_events' module Psych module JSON diff --git a/ruby/ext/psych/lib/psych/json/tree_builder.rb b/ruby/ext/psych/lib/psych/json/tree_builder.rb index 5c2ee8ca2..9a45f6b94 100644 --- a/ruby/ext/psych/lib/psych/json/tree_builder.rb +++ b/ruby/ext/psych/lib/psych/json/tree_builder.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/json/yaml_events' +require_relative 'yaml_events' module Psych module JSON diff --git a/ruby/ext/psych/lib/psych/nodes.rb b/ruby/ext/psych/lib/psych/nodes.rb index 5842c2e3e..2fa52e005 100644 --- a/ruby/ext/psych/lib/psych/nodes.rb +++ b/ruby/ext/psych/lib/psych/nodes.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'psych/nodes/node' -require 'psych/nodes/stream' -require 'psych/nodes/document' -require 'psych/nodes/sequence' -require 'psych/nodes/scalar' -require 'psych/nodes/mapping' -require 'psych/nodes/alias' +require_relative 'nodes/node' +require_relative 'nodes/stream' +require_relative 'nodes/document' +require_relative 'nodes/sequence' +require_relative 'nodes/scalar' +require_relative 'nodes/mapping' +require_relative 'nodes/alias' module Psych ### diff --git a/ruby/ext/psych/lib/psych/nodes/node.rb b/ruby/ext/psych/lib/psych/nodes/node.rb index f59fb8916..1f841625c 100644 --- a/ruby/ext/psych/lib/psych/nodes/node.rb +++ b/ruby/ext/psych/lib/psych/nodes/node.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'stringio' -require 'psych/class_loader' -require 'psych/scalar_scanner' +require_relative '../class_loader' +require_relative '../scalar_scanner' module Psych module Nodes @@ -46,8 +46,8 @@ def each &block # Convert this node to Ruby. # # See also Psych::Visitors::ToRuby - def to_ruby - Visitors::ToRuby.create.accept(self) + def to_ruby(symbolize_names: false, freeze: false) + Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self) end alias :transform :to_ruby diff --git a/ruby/ext/psych/lib/psych/nodes/scalar.rb b/ruby/ext/psych/lib/psych/nodes/scalar.rb index e2616b6a8..5550b616a 100644 --- a/ruby/ext/psych/lib/psych/nodes/scalar.rb +++ b/ruby/ext/psych/lib/psych/nodes/scalar.rb @@ -50,7 +50,7 @@ class Scalar < Psych::Nodes::Node # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value - # +style+ is an integer idicating the string style + # +style+ is an integer indicating the string style # # == See Also # diff --git a/ruby/ext/psych/lib/psych/scalar_scanner.rb b/ruby/ext/psych/lib/psych/scalar_scanner.rb index cea2a453d..b66ff9938 100644 --- a/ruby/ext/psych/lib/psych/scalar_scanner.rb +++ b/ruby/ext/psych/lib/psych/scalar_scanner.rb @@ -9,15 +9,14 @@ class ScalarScanner TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/ # Taken from http://yaml.org/type/float.html - FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10) - |[-+]?\.(inf|Inf|INF)(?# infinity) - |\.(nan|NaN|NAN)(?# not a number))$/x + # 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 = /^(?:[-+]?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 + INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2) + |[-+]?0[0-7_,]+ (?# base 8) + |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10) + |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x attr_reader :class_loader @@ -34,7 +33,7 @@ def tokenize string # Check for a String type, being careful not to get caught by hash keys, hex values, and # special floats (e.g., -.inf). - if string.match?(/^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/) || string.match?(/\n/) + if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/) return string if string.length > 5 if string.match?(/^[^ytonf~]/i) @@ -61,7 +60,7 @@ def tokenize string rescue ArgumentError string end - elsif string.match?(/^\.inf$/i) + elsif string.match?(/^\+?\.inf$/i) Float::INFINITY elsif string.match?(/^-\.inf$/i) -Float::INFINITY @@ -101,7 +100,7 @@ def tokenize string ### # Parse and return an int from +string+ def parse_int string - Integer(string.gsub(/[,]/, '')) + Integer(string.gsub(/[,_]/, '')) end ### diff --git a/ruby/ext/psych/lib/psych/syntax_error.rb b/ruby/ext/psych/lib/psych/syntax_error.rb index 1598e6ff3..a4c9c4a37 100644 --- a/ruby/ext/psych/lib/psych/syntax_error.rb +++ b/ruby/ext/psych/lib/psych/syntax_error.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/exception' +require_relative 'exception' module Psych class SyntaxError < Psych::Exception diff --git a/ruby/ext/psych/lib/psych/tree_builder.rb b/ruby/ext/psych/lib/psych/tree_builder.rb index 47a169564..414ca02bf 100644 --- a/ruby/ext/psych/lib/psych/tree_builder.rb +++ b/ruby/ext/psych/lib/psych/tree_builder.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/handler' +require_relative 'handler' module Psych ### diff --git a/ruby/ext/psych/lib/psych/versions.rb b/ruby/ext/psych/lib/psych/versions.rb index 731ba9545..3cfd59e75 100644 --- a/ruby/ext/psych/lib/psych/versions.rb +++ b/ruby/ext/psych/lib/psych/versions.rb @@ -1,10 +1,10 @@ - # frozen_string_literal: true + module Psych # The version of Psych you are using - VERSION = '3.1.0' unless defined?(::Psych::VERSION) + VERSION = '4.0.3' if RUBY_ENGINE == 'jruby' - DEFAULT_SNAKEYAML_VERSION = '1.23'.freeze + DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze end end diff --git a/ruby/ext/psych/lib/psych/visitors.rb b/ruby/ext/psych/lib/psych/visitors.rb index e2b084dae..508290d86 100644 --- a/ruby/ext/psych/lib/psych/visitors.rb +++ b/ruby/ext/psych/lib/psych/visitors.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'psych/visitors/visitor' -require 'psych/visitors/to_ruby' -require 'psych/visitors/emitter' -require 'psych/visitors/yaml_tree' -require 'psych/visitors/json_tree' -require 'psych/visitors/depth_first' +require_relative 'visitors/visitor' +require_relative 'visitors/to_ruby' +require_relative 'visitors/emitter' +require_relative 'visitors/yaml_tree' +require_relative 'visitors/json_tree' +require_relative 'visitors/depth_first' diff --git a/ruby/ext/psych/lib/psych/visitors/json_tree.rb b/ruby/ext/psych/lib/psych/visitors/json_tree.rb index 9912cb136..979fc100b 100644 --- a/ruby/ext/psych/lib/psych/visitors/json_tree.rb +++ b/ruby/ext/psych/lib/psych/visitors/json_tree.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'psych/json/ruby_events' +require_relative '../json/ruby_events' module Psych module Visitors diff --git a/ruby/ext/psych/lib/psych/visitors/to_ruby.rb b/ruby/ext/psych/lib/psych/visitors/to_ruby.rb index b72fb4a1d..4c1f56107 100644 --- a/ruby/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ruby/ext/psych/lib/psych/visitors/to_ruby.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'psych/scalar_scanner' -require 'psych/class_loader' -require 'psych/exception' +require_relative '../scalar_scanner' +require_relative '../class_loader' +require_relative '../exception' unless defined?(Regexp::NOENCODING) Regexp::NOENCODING = 32 @@ -12,39 +12,44 @@ module Visitors ### # This class walks a YAML AST, converting each node to Ruby class ToRuby < Psych::Visitors::Visitor - def self.create + def self.create(symbolize_names: false, freeze: false) class_loader = ClassLoader.new scanner = ScalarScanner.new class_loader - new(scanner, class_loader) + new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze) end attr_reader :class_loader - def initialize ss, class_loader + def initialize ss, class_loader, symbolize_names: false, freeze: false super() @st = {} @ss = ss + @load_tags = Psych.load_tags @domain_types = Psych.domain_types @class_loader = class_loader + @symbolize_names = symbolize_names + @freeze = freeze end def accept target result = super - return result if @domain_types.empty? || !target.tag - key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') - key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/ + unless @domain_types.empty? || !target.tag + key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') + key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/ - if @domain_types.key? key - value, block = @domain_types[key] - return block.call value, result + if @domain_types.key? key + value, block = @domain_types[key] + result = block.call value, result + end end + result = deduplicate(result).freeze if @freeze result end def deserialize o - if klass = resolve_class(Psych.load_tags[o.tag]) + if klass = resolve_class(@load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) @@ -124,7 +129,7 @@ def visit_Psych_Nodes_Scalar o end def visit_Psych_Nodes_Sequence o - if klass = resolve_class(Psych.load_tags[o.tag]) + if klass = resolve_class(@load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) @@ -156,8 +161,8 @@ def visit_Psych_Nodes_Sequence o end def visit_Psych_Nodes_Mapping o - if Psych.load_tags[o.tag] - return revive(resolve_class(Psych.load_tags[o.tag]), o) + if @load_tags[o.tag] + return revive(resolve_class(@load_tags[o.tag]), o) end return revive_hash(register(o, {}), o) unless o.tag @@ -322,6 +327,7 @@ def visit_Psych_Nodes_Alias o end private + def register node, object @st[node.anchor] = object if node.anchor object @@ -333,13 +339,12 @@ def register_empty object list end - SHOVEL = '<<' - def revive_hash hash, o + def revive_hash hash, o, tagged= false o.children.each_slice(2) { |k,v| - key = deduplicate(accept(k)) + key = accept(k) val = accept(v) - if key == SHOVEL && k.tag != "tag:yaml.org,2002:str" + if key == '<<' && k.tag != "tag:yaml.org,2002:str" case v when Nodes::Alias, Nodes::Mapping begin @@ -361,6 +366,12 @@ def revive_hash hash, o hash[key] = val end else + if !tagged && @symbolize_names && key.is_a?(String) + key = key.to_sym + elsif !@freeze + key = deduplicate(key) + end + hash[key] = val end @@ -371,6 +382,8 @@ def revive_hash hash, o if RUBY_VERSION < '2.7' def deduplicate key if key.is_a?(String) + # It is important to untaint the string, otherwise it won't + # be deduplicated into an fstring, but simply frozen. -(key.untaint) else key @@ -391,7 +404,7 @@ def merge_key hash, key, val def revive klass, node s = register(node, klass.allocate) - init_with(s, revive_hash({}, node), node) + init_with(s, revive_hash({}, node, true), node) end def init_with o, h, node diff --git a/ruby/ext/psych/lib/psych/visitors/visitor.rb b/ruby/ext/psych/lib/psych/visitors/visitor.rb index 3f4ba64e5..21052aa66 100644 --- a/ruby/ext/psych/lib/psych/visitors/visitor.rb +++ b/ruby/ext/psych/lib/psych/visitors/visitor.rb @@ -8,12 +8,26 @@ def accept target private - DISPATCH = Hash.new do |hash, klass| - hash[klass] = "visit_#{klass.name.gsub('::', '_')}" + # @api private + def self.dispatch_cache + Hash.new do |hash, klass| + hash[klass] = :"visit_#{klass.name.gsub('::', '_')}" + end.compare_by_identity + end + + if defined?(Ractor) + def dispatch + @dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache) + end + else + DISPATCH = dispatch_cache + def dispatch + DISPATCH + end end def visit target - send DISPATCH[target.class], target + send dispatch[target.class], target end end end diff --git a/ruby/ext/psych/lib/psych/visitors/yaml_tree.rb b/ruby/ext/psych/lib/psych/visitors/yaml_tree.rb index 79ca129b8..316a3a949 100644 --- a/ruby/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ruby/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'psych/tree_builder' -require 'psych/scalar_scanner' -require 'psych/class_loader' +require_relative '../tree_builder' +require_relative '../scalar_scanner' +require_relative '../class_loader' module Psych module Visitors @@ -80,7 +80,7 @@ def initialize emitter, ss, options raise(TypeError, "Can't dump #{target.class}") unless method h[klass] = method - end + end.compare_by_identity end def start encoding = Nodes::Stream::UTF8 @@ -181,7 +181,7 @@ def visit_Struct o end def visit_Exception o - dump_exception o, private_iv_get(o, 'mesg') + dump_exception o, o.message.to_s end def visit_NameError o @@ -272,6 +272,8 @@ def visit_String o tag = 'tag:yaml.org,2002:str' plain = false quote = false + elsif o == 'y' || o == 'n' + style = Nodes::Scalar::DOUBLE_QUOTED elsif @line_width && o.length > @line_width style = Nodes::Scalar::FOLDED elsif o =~ /^[^[:word:]][^"]*$/ @@ -509,9 +511,9 @@ def dump_coder o def emit_coder c, o case c.type when :scalar - @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY + @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style when :seq - @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK + @emitter.start_sequence nil, c.tag, c.tag.nil?, c.style c.seq.each do |thing| accept thing end @@ -535,5 +537,51 @@ def dump_ivars target end end end + + class RestrictedYAMLTree < YAMLTree + DEFAULT_PERMITTED_CLASSES = { + TrueClass => true, + FalseClass => true, + NilClass => true, + Integer => true, + Float => true, + String => true, + Array => true, + Hash => true, + }.compare_by_identity.freeze + + def initialize emitter, ss, options + super + @permitted_classes = DEFAULT_PERMITTED_CLASSES.dup + Array(options[:permitted_classes]).each do |klass| + @permitted_classes[klass] = true + end + @permitted_symbols = {}.compare_by_identity + Array(options[:permitted_symbols]).each do |symbol| + @permitted_symbols[symbol] = true + end + @aliases = options.fetch(:aliases, false) + end + + def accept target + if !@aliases && @st.key?(target) + raise BadAlias, "Tried to dump an aliased object" + end + + unless @permitted_classes[target.class] + raise DisallowedClass.new('dump', target.class.name || target.class.inspect) + end + + super + end + + def visit_Symbol sym + unless @permitted_symbols[sym] + raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})") + end + + super + end + end end end diff --git a/ruby/ext/psych/psych.c b/ruby/ext/psych/psych.c index 3bb59bfc1..8af0bb6a5 100644 --- a/ruby/ext/psych/psych.c +++ b/ruby/ext/psych/psych.c @@ -11,9 +11,9 @@ static VALUE libyaml_version(VALUE module) yaml_get_version(&major, &minor, &patch); - list[0] = INT2NUM((long)major); - list[1] = INT2NUM((long)minor); - list[2] = INT2NUM((long)patch); + list[0] = INT2NUM(major); + list[1] = INT2NUM(minor); + list[2] = INT2NUM(patch); return rb_ary_new4((long)3, list); } @@ -22,6 +22,9 @@ VALUE mPsych; void Init_psych(void) { + #ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); + #endif mPsych = rb_define_module("Psych"); rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0); diff --git a/ruby/ext/psych/psych.gemspec b/ruby/ext/psych/psych.gemspec index e0168af7d..65dd7156c 100644 --- a/ruby/ext/psych/psych.gemspec +++ b/ruby/ext/psych/psych.gemspec @@ -1,16 +1,14 @@ # -*- encoding: utf-8 -*- # frozen_string_literal: true -begin - require_relative 'lib/psych/versions' -rescue LoadError - # for Ruby core repository - require_relative 'versions' +version_module = Module.new do + version_rb = File.join(__dir__, "lib/psych/versions.rb") + module_eval(File.read(version_rb), version_rb) end Gem::Specification.new do |s| s.name = "psych" - s.version = Psych::VERSION + s.version = version_module::Psych::VERSION s.authors = ["Aaron Patterson", "SHIBATA Hiroshi", "Charles Oliver Nutter"] s.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org", "headius@headius.com"] s.summary = "Psych is a YAML parser and emitter" @@ -25,7 +23,7 @@ DESCRIPTION # for ruby core repository. It was generated by `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } s.files = [ - ".gitignore", ".travis.yml", "Gemfile", "Mavenfile", "README.md", "Rakefile", "bin/console", + ".gitignore", "Gemfile", "LICENSE", "Mavenfile", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/psych/depend", "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h", "ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h", "ext/psych/psych_parser.c", "ext/psych/psych_parser.h", "ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h", "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h", @@ -48,7 +46,6 @@ DESCRIPTION s.extra_rdoc_files = ["README.md"] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0") - s.rubygems_version = "2.5.1" s.required_rubygems_version = Gem::Requirement.new(">= 0") if RUBY_ENGINE == 'jruby' @@ -62,9 +59,11 @@ DESCRIPTION "lib/psych_jars.rb", "lib/psych.jar" ] - s.requirements = "jar org.yaml:snakeyaml, #{Psych::DEFAULT_SNAKEYAML_VERSION}" + s.requirements = "jar org.yaml:snakeyaml, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}" s.add_dependency 'jar-dependencies', '>= 0.1.7' else s.extensions = ["ext/psych/extconf.rb"] + s.add_dependency 'stringio' end + end diff --git a/ruby/ext/psych/psych_parser.c b/ruby/ext/psych/psych_parser.c index fb1a917bb..fd550b671 100644 --- a/ruby/ext/psych/psych_parser.c +++ b/ruby/ext/psych/psych_parser.c @@ -27,7 +27,7 @@ static ID id_event_location; static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read) { VALUE io = (VALUE)data; - VALUE string = rb_funcall(io, id_read, 1, INT2NUM(size)); + VALUE string = rb_funcall(io, id_read, 1, SIZET2NUM(size)); *read = 0; @@ -89,9 +89,9 @@ static VALUE make_exception(yaml_parser_t * parser, VALUE path) return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6, path, - INT2NUM(line), - INT2NUM(column), - INT2NUM(parser->problem_offset), + 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); } @@ -303,10 +303,10 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) rb_exc_raise(exception); } - start_line = INT2NUM((long)event.start_mark.line); - start_column = INT2NUM((long)event.start_mark.column); - end_line = INT2NUM((long)event.end_mark.line); - end_column = INT2NUM((long)event.end_mark.column); + 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; @@ -321,7 +321,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) VALUE args[2]; args[0] = handler; - args[1] = INT2NUM((long)event.data.stream_start.encoding); + args[1] = INT2NUM(event.data.stream_start.encoding); rb_protect(protected_start_stream, (VALUE)args, &state); } break; @@ -334,8 +334,8 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) VALUE version = event.data.document_start.version_directive ? rb_ary_new3( (long)2, - INT2NUM((long)event.data.document_start.version_directive->major), - INT2NUM((long)event.data.document_start.version_directive->minor) + 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) { @@ -418,7 +418,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) quoted_implicit = event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; - style = INT2NUM((long)event.data.scalar.style); + style = INT2NUM(event.data.scalar.style); args[0] = handler; args[1] = val; @@ -450,7 +450,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) implicit = event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; - style = INT2NUM((long)event.data.sequence_start.style); + style = INT2NUM(event.data.sequence_start.style); args[0] = handler; args[1] = anchor; @@ -483,7 +483,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self) implicit = event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; - style = INT2NUM((long)event.data.mapping_start.style); + style = INT2NUM(event.data.mapping_start.style); args[0] = handler; args[1] = anchor; @@ -527,9 +527,9 @@ static VALUE mark(VALUE self) TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser); mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark")); - args[0] = INT2NUM(parser->mark.index); - args[1] = INT2NUM(parser->mark.line); - args[2] = INT2NUM(parser->mark.column); + args[0] = SIZET2NUM(parser->mark.index); + args[1] = SIZET2NUM(parser->mark.line); + args[2] = SIZET2NUM(parser->mark.column); return rb_class_new_instance(3, args, mark_klass); } diff --git a/ruby/ext/psych/psych_yaml_tree.c b/ruby/ext/psych/psych_yaml_tree.c index 7aca9114c..225655d12 100644 --- a/ruby/ext/psych/psych_yaml_tree.c +++ b/ruby/ext/psych/psych_yaml_tree.c @@ -2,23 +2,11 @@ VALUE cPsychVisitorsYamlTree; -/* - * call-seq: private_iv_get(target, prop) - * - * Get the private instance variable +prop+ from +target+ - */ -static VALUE private_iv_get(VALUE self, VALUE target, VALUE prop) -{ - return rb_attr_get(target, rb_intern(StringValueCStr(prop))); -} - void Init_psych_yaml_tree(void) { VALUE psych = rb_define_module("Psych"); VALUE visitors = rb_define_module_under(psych, "Visitors"); VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject); cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor); - - rb_define_private_method(cPsychVisitorsYamlTree, "private_iv_get", private_iv_get, 2); } /* vim: set noet sws=4 sw=4: */ diff --git a/ruby/ext/psych/yaml/api.c b/ruby/ext/psych/yaml/api.c index 95dc6b4de..6add8b266 100644 --- a/ruby/ext/psych/yaml/api.c +++ b/ruby/ext/psych/yaml/api.c @@ -118,7 +118,12 @@ yaml_string_join( YAML_DECLARE(int) yaml_stack_extend(void **start, void **top, void **end) { - void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2); + void *new_start; + + if ((char *)*end - (char *)*start >= INT_MAX / 2) + return 0; + + new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2); if (!new_start) return 0; @@ -618,10 +623,10 @@ yaml_token_delete(yaml_token_t *token) */ static int -yaml_check_utf8(yaml_char_t *start, size_t length) +yaml_check_utf8(const yaml_char_t *start, size_t length) { - yaml_char_t *end = start+length; - yaml_char_t *pointer = start; + const yaml_char_t *end = start+length; + const yaml_char_t *pointer = start; while (pointer < end) { unsigned char octet; @@ -789,7 +794,7 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit) */ YAML_DECLARE(int) -yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) +yaml_alias_event_initialize(yaml_event_t *event, const yaml_char_t *anchor) { yaml_mark_t mark = { 0, 0, 0 }; yaml_char_t *anchor_copy = NULL; @@ -814,8 +819,8 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) YAML_DECLARE(int) yaml_scalar_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, - yaml_char_t *value, int length, + const yaml_char_t *anchor, const yaml_char_t *tag, + const yaml_char_t *value, int length, int plain_implicit, int quoted_implicit, yaml_scalar_style_t style) { @@ -868,7 +873,7 @@ yaml_scalar_event_initialize(yaml_event_t *event, YAML_DECLARE(int) yaml_sequence_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, + const yaml_char_t *anchor, const yaml_char_t *tag, int implicit, yaml_sequence_style_t style) { yaml_mark_t mark = { 0, 0, 0 }; @@ -923,7 +928,7 @@ yaml_sequence_end_event_initialize(yaml_event_t *event) YAML_DECLARE(int) yaml_mapping_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, + const yaml_char_t *anchor, const yaml_char_t *tag, int implicit, yaml_mapping_style_t style) { yaml_mark_t mark = { 0, 0, 0 }; @@ -1117,15 +1122,8 @@ yaml_document_initialize(yaml_document_t *document, YAML_DECLARE(void) yaml_document_delete(yaml_document_t *document) { - struct { - yaml_error_type_t error; - } context; yaml_tag_directive_t *tag_directive; - /* Eliminate a compliler warning. */ - context.error = YAML_NO_ERROR; - (void)context.error; - assert(document); /* Non-NULL document object is expected. */ while (!STACK_EMPTY(&context, document->nodes)) { @@ -1195,7 +1193,7 @@ yaml_document_get_root_node(yaml_document_t *document) YAML_DECLARE(int) yaml_document_add_scalar(yaml_document_t *document, - yaml_char_t *tag, yaml_char_t *value, int length, + const yaml_char_t *tag, const yaml_char_t *value, int length, yaml_scalar_style_t style) { struct { @@ -1245,7 +1243,7 @@ yaml_document_add_scalar(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_sequence(yaml_document_t *document, - yaml_char_t *tag, yaml_sequence_style_t style) + const yaml_char_t *tag, yaml_sequence_style_t style) { struct { yaml_error_type_t error; @@ -1290,7 +1288,7 @@ yaml_document_add_sequence(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_mapping(yaml_document_t *document, - yaml_char_t *tag, yaml_mapping_style_t style) + const yaml_char_t *tag, yaml_mapping_style_t style) { struct { yaml_error_type_t error; diff --git a/ruby/ext/psych/yaml/config.h b/ruby/ext/psych/yaml/config.h index da905133f..4b1150f5e 100644 --- a/ruby/ext/psych/yaml/config.h +++ b/ruby/ext/psych/yaml/config.h @@ -1,10 +1,80 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "yaml" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "https://github.com/yaml/libyaml/issues/new" + +/* Define to the full name of this package. */ #define PACKAGE_NAME "yaml" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yaml 0.2.5" + +/* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "yaml" -#define PACKAGE_VERSION "0.2.1" -#define PACKAGE_STRING "yaml 0.2.1" -#define PACKAGE_BUGREPORT "https://github.com/yaml/libyaml/issues" -#define PACKAGE_URL "https://github.com/yaml/libyaml" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.2.5" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.2.5" + +/* Define the major version number. */ #define YAML_VERSION_MAJOR 0 + +/* Define the minor version number. */ #define YAML_VERSION_MINOR 2 -#define YAML_VERSION_PATCH 1 -#define YAML_VERSION_STRING "0.2.1" + +/* Define the patch version number. */ +#define YAML_VERSION_PATCH 5 + +/* Define the version string. */ +#define YAML_VERSION_STRING "0.2.5" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/ruby/ext/psych/yaml/dumper.c b/ruby/ext/psych/yaml/dumper.c index 29fb9c078..1fe940b67 100644 --- a/ruby/ext/psych/yaml/dumper.c +++ b/ruby/ext/psych/yaml/dumper.c @@ -131,7 +131,7 @@ yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document) assert(emitter->opened); /* Emitter should be opened. */ - emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors)) + emitter->anchors = (yaml_anchors_t*)yaml_malloc(sizeof(*(emitter->anchors)) * (document->nodes.top - document->nodes.start)); if (!emitter->anchors) goto error; memset(emitter->anchors, 0, sizeof(*(emitter->anchors)) diff --git a/ruby/ext/psych/yaml/emitter.c b/ruby/ext/psych/yaml/emitter.c index 92e21cdb7..796294ccd 100644 --- a/ruby/ext/psych/yaml/emitter.c +++ b/ruby/ext/psych/yaml/emitter.c @@ -16,7 +16,7 @@ #define PUT(emitter,value) \ (FLUSH(emitter) \ && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \ - emitter->column ++, \ + emitter->column++, \ 1)) /* @@ -495,6 +495,7 @@ static int yaml_emitter_emit_stream_start(yaml_emitter_t *emitter, yaml_event_t *event) { + emitter->open_ended = 0; if (event->type == YAML_STREAM_START_EVENT) { if (!emitter->encoding) { @@ -597,13 +598,20 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, if (!yaml_emitter_write_indent(emitter)) return 0; } + emitter->open_ended = 0; if (event->data.document_start.version_directive) { implicit = 0; if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0)) return 0; - if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0)) - return 0; + if (event->data.document_start.version_directive->minor == 1) { + if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0)) + return 0; + } + else { + if (!yaml_emitter_write_indicator(emitter, "1.2", 1, 0, 0)) + return 0; + } if (!yaml_emitter_write_indent(emitter)) return 0; } @@ -644,19 +652,25 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter, emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE; + emitter->open_ended = 0; return 1; } else if (event->type == YAML_STREAM_END_EVENT) { - if (emitter->open_ended) + + /** + * This can happen if a block scalar with trailing empty lines + * is at the end of the stream + */ + if (emitter->open_ended == 2) { if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) return 0; + emitter->open_ended = 0; if (!yaml_emitter_write_indent(emitter)) return 0; } - if (!yaml_emitter_flush(emitter)) return 0; @@ -698,9 +712,12 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter, if (!event->data.document_end.implicit) { if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) return 0; + emitter->open_ended = 0; if (!yaml_emitter_write_indent(emitter)) return 0; } + else if (!emitter->open_ended) + emitter->open_ended = 1; if (!yaml_emitter_flush(emitter)) return 0; @@ -1006,6 +1023,8 @@ yaml_emitter_emit_alias(yaml_emitter_t *emitter, SHIM(yaml_event_t *event)) { if (!yaml_emitter_process_anchor(emitter)) return 0; + if (emitter->simple_key_context) + if (!PUT(emitter, ' ')) return 0; emitter->state = POP(emitter, emitter->states); return 1; @@ -1333,7 +1352,10 @@ static int yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter, yaml_version_directive_t version_directive) { - if (version_directive.major != 1 || version_directive.minor != 1) { + if (version_directive.major != 1 || ( + version_directive.minor != 1 + && version_directive.minor != 2 + )) { return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive"); } @@ -1803,7 +1825,6 @@ yaml_emitter_write_indicator(yaml_emitter_t *emitter, emitter->whitespace = is_whitespace; emitter->indention = (emitter->indention && is_indention); - emitter->open_ended = 0; return 1; } @@ -1904,7 +1925,17 @@ yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter, STRING_ASSIGN(string, value, length); - if (!emitter->whitespace) { + /** + * Avoid trailing spaces for empty values in block mode. + * In flow mode, we still want the space to prevent ambiguous things + * like {a:}. + * Currently, the emitter forbids any plain empty scalar in flow mode + * (e.g. it outputs {a: ''} instead), so emitter->flow_level will + * never be true here. + * But if the emitter is ever changed to allow emitting empty values, + * the check for flow_level is already here. + */ + if (!emitter->whitespace && (length || emitter->flow_level)) { if (!PUT(emitter, ' ')) return 0; } @@ -2004,6 +2035,9 @@ yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter, } } + if (breaks) + if (!yaml_emitter_write_indent(emitter)) return 0; + if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0)) return 0; @@ -2203,7 +2237,7 @@ yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter, else if (string.start == string.pointer) { chomp_hint = "+"; - emitter->open_ended = 1; + emitter->open_ended = 2; } else { @@ -2213,7 +2247,7 @@ yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter, if (IS_BREAK(string)) { chomp_hint = "+"; - emitter->open_ended = 1; + emitter->open_ended = 2; } } } diff --git a/ruby/ext/psych/yaml/loader.c b/ruby/ext/psych/yaml/loader.c index e5d90be9b..bcf3aee8c 100644 --- a/ruby/ext/psych/yaml/loader.c +++ b/ruby/ext/psych/yaml/loader.c @@ -37,27 +37,47 @@ yaml_parser_register_anchor(yaml_parser_t *parser, static void yaml_parser_delete_aliases(yaml_parser_t *parser); +/* + * Document loading context. + */ +struct loader_ctx { + int *start; + int *end; + int *top; +}; + /* * Composer functions. */ +static int +yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx); + +static int +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event); static int -yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int -yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int -yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int -yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int -yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); static int -yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event); +yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx); /* * Load the next document of the stream. @@ -162,59 +182,78 @@ yaml_parser_delete_aliases(yaml_parser_t *parser) */ static int -yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event) { - yaml_event_t event; + struct loader_ctx ctx = { NULL, NULL, NULL }; - assert(first_event->type == YAML_DOCUMENT_START_EVENT); + assert(event->type == YAML_DOCUMENT_START_EVENT); /* DOCUMENT-START is expected. */ parser->document->version_directive - = first_event->data.document_start.version_directive; + = event->data.document_start.version_directive; parser->document->tag_directives.start - = first_event->data.document_start.tag_directives.start; + = event->data.document_start.tag_directives.start; parser->document->tag_directives.end - = first_event->data.document_start.tag_directives.end; + = event->data.document_start.tag_directives.end; parser->document->start_implicit - = first_event->data.document_start.implicit; - parser->document->start_mark = first_event->start_mark; - - if (!yaml_parser_parse(parser, &event)) return 0; - - if (!yaml_parser_load_node(parser, &event)) return 0; - - if (!yaml_parser_parse(parser, &event)) return 0; - assert(event.type == YAML_DOCUMENT_END_EVENT); - /* DOCUMENT-END is expected. */ + = event->data.document_start.implicit; + parser->document->start_mark = event->start_mark; - parser->document->end_implicit = event.data.document_end.implicit; - parser->document->end_mark = event.end_mark; + if (!STACK_INIT(parser, ctx, int*)) return 0; + if (!yaml_parser_load_nodes(parser, &ctx)) { + STACK_DEL(parser, ctx); + return 0; + } + STACK_DEL(parser, ctx); return 1; } /* - * Compose a node. + * Compose a node tree. */ static int -yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx) { - switch (first_event->type) { - case YAML_ALIAS_EVENT: - return yaml_parser_load_alias(parser, first_event); - case YAML_SCALAR_EVENT: - return yaml_parser_load_scalar(parser, first_event); - case YAML_SEQUENCE_START_EVENT: - return yaml_parser_load_sequence(parser, first_event); - case YAML_MAPPING_START_EVENT: - return yaml_parser_load_mapping(parser, first_event); - default: - assert(0); /* Could not happen. */ - return 0; - } + yaml_event_t event; - return 0; + do { + if (!yaml_parser_parse(parser, &event)) return 0; + + switch (event.type) { + case YAML_ALIAS_EVENT: + if (!yaml_parser_load_alias(parser, &event, ctx)) return 0; + break; + case YAML_SCALAR_EVENT: + if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0; + break; + case YAML_SEQUENCE_START_EVENT: + if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0; + break; + case YAML_SEQUENCE_END_EVENT: + if (!yaml_parser_load_sequence_end(parser, &event, ctx)) + return 0; + break; + case YAML_MAPPING_START_EVENT: + if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0; + break; + case YAML_MAPPING_END_EVENT: + if (!yaml_parser_load_mapping_end(parser, &event, ctx)) + return 0; + break; + default: + assert(0); /* Could not happen. */ + return 0; + case YAML_DOCUMENT_END_EVENT: + break; + } + } while (event.type != YAML_DOCUMENT_END_EVENT); + + parser->document->end_implicit = event.data.document_end.implicit; + parser->document->end_mark = event.end_mark; + + return 1; } /* @@ -252,27 +291,80 @@ yaml_parser_register_anchor(yaml_parser_t *parser, return 1; } +/* + * Compose node into its parent in the stree. + */ + +static int +yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx, + int index) +{ + struct yaml_node_s *parent; + int parent_index; + + if (STACK_EMPTY(parser, *ctx)) { + /* This is the root node, there's no tree to add it to. */ + return 1; + } + + parent_index = *((*ctx).top - 1); + parent = &parser->document->nodes.start[parent_index-1]; + + switch (parent->type) { + case YAML_SEQUENCE_NODE: + if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1)) + return 0; + if (!PUSH(parser, parent->data.sequence.items, index)) + return 0; + break; + case YAML_MAPPING_NODE: { + yaml_node_pair_t pair; + if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) { + yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1; + if (p->key != 0 && p->value == 0) { + p->value = index; + break; + } + } + + pair.key = index; + pair.value = 0; + if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1)) + return 0; + if (!PUSH(parser, parent->data.mapping.pairs, pair)) + return 0; + + break; + } + default: + assert(0); /* Could not happen. */ + return 0; + } + return 1; +} + /* * Compose a node corresponding to an alias. */ static int -yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { - yaml_char_t *anchor = first_event->data.alias.anchor; + yaml_char_t *anchor = event->data.alias.anchor; yaml_alias_data_t *alias_data; for (alias_data = parser->aliases.start; alias_data != parser->aliases.top; alias_data ++) { if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { yaml_free(anchor); - return alias_data->index; + return yaml_parser_load_node_add(parser, ctx, alias_data->index); } } yaml_free(anchor); return yaml_parser_set_composer_error(parser, "found undefined alias", - first_event->start_mark); + event->start_mark); } /* @@ -280,11 +372,12 @@ yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event) */ static int -yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { yaml_node_t node; int index; - yaml_char_t *tag = first_event->data.scalar.tag; + yaml_char_t *tag = event->data.scalar.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -294,23 +387,23 @@ yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) if (!tag) goto error; } - SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value, - first_event->data.scalar.length, first_event->data.scalar.style, - first_event->start_mark, first_event->end_mark); + SCALAR_NODE_INIT(node, tag, event->data.scalar.value, + event->data.scalar.length, event->data.scalar.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = (int)(parser->document->nodes.top - parser->document->nodes.start); if (!yaml_parser_register_anchor(parser, index, - first_event->data.scalar.anchor)) return 0; + event->data.scalar.anchor)) return 0; - return index; + return yaml_parser_load_node_add(parser, ctx, index); error: yaml_free(tag); - yaml_free(first_event->data.scalar.anchor); - yaml_free(first_event->data.scalar.value); + yaml_free(event->data.scalar.anchor); + yaml_free(event->data.scalar.value); return 0; } @@ -319,17 +412,17 @@ yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) */ static int -yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { - yaml_event_t event; yaml_node_t node; struct { yaml_node_item_t *start; yaml_node_item_t *end; yaml_node_item_t *top; } items = { NULL, NULL, NULL }; - int index, item_index; - yaml_char_t *tag = first_event->data.sequence_start.tag; + int index; + yaml_char_t *tag = event->data.sequence_start.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -342,48 +435,54 @@ yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error; SEQUENCE_NODE_INIT(node, tag, items.start, items.end, - first_event->data.sequence_start.style, - first_event->start_mark, first_event->end_mark); + event->data.sequence_start.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = (int)(parser->document->nodes.top - parser->document->nodes.start); if (!yaml_parser_register_anchor(parser, index, - first_event->data.sequence_start.anchor)) return 0; - - if (!yaml_parser_parse(parser, &event)) return 0; - - while (event.type != YAML_SEQUENCE_END_EVENT) { - if (!STACK_LIMIT(parser, - parser->document->nodes.start[index-1].data.sequence.items, - INT_MAX-1)) return 0; - item_index = yaml_parser_load_node(parser, &event); - if (!item_index) return 0; - if (!PUSH(parser, - parser->document->nodes.start[index-1].data.sequence.items, - item_index)) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - } + event->data.sequence_start.anchor)) return 0; - parser->document->nodes.start[index-1].end_mark = event.end_mark; + if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; - return index; + if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; + if (!PUSH(parser, *ctx, index)) return 0; + + return 1; error: yaml_free(tag); - yaml_free(first_event->data.sequence_start.anchor); + yaml_free(event->data.sequence_start.anchor); return 0; } +static int +yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) +{ + int index; + + assert(((*ctx).top - (*ctx).start) > 0); + + index = *((*ctx).top - 1); + assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE); + parser->document->nodes.start[index-1].end_mark = event->end_mark; + + (void)POP(parser, *ctx); + + return 1; +} + /* * Compose a mapping node. */ static int -yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) { - yaml_event_t event; yaml_node_t node; struct { yaml_node_pair_t *start; @@ -391,8 +490,7 @@ yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) yaml_node_pair_t *top; } pairs = { NULL, NULL, NULL }; int index; - yaml_node_pair_t pair; - yaml_char_t *tag = first_event->data.mapping_start.tag; + yaml_char_t *tag = event->data.mapping_start.tag; if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error; @@ -405,40 +503,42 @@ yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error; MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, - first_event->data.mapping_start.style, - first_event->start_mark, first_event->end_mark); + event->data.mapping_start.style, + event->start_mark, event->end_mark); if (!PUSH(parser, parser->document->nodes, node)) goto error; index = (int)(parser->document->nodes.top - parser->document->nodes.start); if (!yaml_parser_register_anchor(parser, index, - first_event->data.mapping_start.anchor)) return 0; + event->data.mapping_start.anchor)) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; + if (!yaml_parser_load_node_add(parser, ctx, index)) return 0; - while (event.type != YAML_MAPPING_END_EVENT) { - if (!STACK_LIMIT(parser, - parser->document->nodes.start[index-1].data.mapping.pairs, - INT_MAX-1)) return 0; - pair.key = yaml_parser_load_node(parser, &event); - if (!pair.key) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - pair.value = yaml_parser_load_node(parser, &event); - if (!pair.value) return 0; - if (!PUSH(parser, - parser->document->nodes.start[index-1].data.mapping.pairs, - pair)) return 0; - if (!yaml_parser_parse(parser, &event)) return 0; - } + if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0; + if (!PUSH(parser, *ctx, index)) return 0; - parser->document->nodes.start[index-1].end_mark = event.end_mark; - - return index; + return 1; error: yaml_free(tag); - yaml_free(first_event->data.mapping_start.anchor); + yaml_free(event->data.mapping_start.anchor); return 0; } +static int +yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event, + struct loader_ctx *ctx) +{ + int index; + + assert(((*ctx).top - (*ctx).start) > 0); + + index = *((*ctx).top - 1); + assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE); + parser->document->nodes.start[index-1].end_mark = event->end_mark; + + (void)POP(parser, *ctx); + + return 1; +} diff --git a/ruby/ext/psych/yaml/parser.c b/ruby/ext/psych/yaml/parser.c index 621f676bf..ec2f8d3e0 100644 --- a/ruby/ext/psych/yaml/parser.c +++ b/ruby/ext/psych/yaml/parser.c @@ -1261,7 +1261,10 @@ yaml_parser_process_directives(yaml_parser_t *parser, goto error; } if (token->data.version_directive.major != 1 - || token->data.version_directive.minor != 1) { + || ( + token->data.version_directive.minor != 1 + && token->data.version_directive.minor != 2 + )) { yaml_parser_set_parser_error(parser, "found incompatible YAML document", token->start_mark); goto error; @@ -1316,6 +1319,8 @@ yaml_parser_process_directives(yaml_parser_t *parser, STACK_DEL(parser, tag_directives); } + if (!version_directive_ref) + yaml_free(version_directive); return 1; error: diff --git a/ruby/ext/psych/yaml/scanner.c b/ruby/ext/psych/yaml/scanner.c index 204593d91..bb5d20127 100644 --- a/ruby/ext/psych/yaml/scanner.c +++ b/ruby/ext/psych/yaml/scanner.c @@ -38,8 +38,8 @@ * BLOCK-END # Indentation decrease. * FLOW-SEQUENCE-START # '[' * FLOW-SEQUENCE-END # ']' - * BLOCK-SEQUENCE-START # '{' - * BLOCK-SEQUENCE-END # '}' + * FLOW-MAPPING-START # '{' + * FLOW-MAPPING-END # '}' * BLOCK-ENTRY # '-' * FLOW-ENTRY # ',' * KEY # '?' or nothing (simple keys). @@ -273,7 +273,7 @@ * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation * increase that precedes a block collection (cf. the INDENT token in Python). * The token BLOCK-END denote indentation decrease that ends a block collection - * (cf. the DEDENT token in Python). However YAML has some syntax pecularities + * (cf. the DEDENT token in Python). However YAML has some syntax peculiarities * that makes detections of these tokens more complex. * * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators @@ -348,6 +348,7 @@ * SCALAR("another value",plain) * KEY * SCALAR("a mapping",plain) + * VALUE * BLOCK-MAPPING-START * KEY * SCALAR("key 1",plain) @@ -711,7 +712,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, yaml_mark_t start_mark, yaml_char_t **handle); static int -yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, +yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive, yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri); static int @@ -2292,7 +2293,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Scan a prefix. */ - if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value)) + if (!yaml_parser_scan_tag_uri(parser, 1, 1, NULL, start_mark, &prefix_value)) goto error; /* Expect a whitespace or line break. */ @@ -2410,7 +2411,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) /* Consume the tag value. */ - if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix)) + if (!yaml_parser_scan_tag_uri(parser, 1, 0, NULL, start_mark, &suffix)) goto error; /* Check for '>' and eat it. */ @@ -2438,14 +2439,14 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) { /* Scan the suffix now. */ - if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix)) + if (!yaml_parser_scan_tag_uri(parser, 0, 0, NULL, start_mark, &suffix)) goto error; } else { /* It wasn't a handle after all. Scan the rest of the tag. */ - if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix)) + if (!yaml_parser_scan_tag_uri(parser, 0, 0, handle, start_mark, &suffix)) goto error; /* Set the handle to '!'. */ @@ -2474,9 +2475,11 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) if (!CACHE(parser, 1)) goto error; if (!IS_BLANKZ(parser->buffer)) { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find expected whitespace or line break"); - goto error; + if (!parser->flow_level || !CHECK(parser->buffer, ',') ) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break"); + goto error; + } } end_mark = parser->mark; @@ -2565,7 +2568,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, */ static int -yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, +yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive, yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri) { size_t length = head ? strlen((char *)head) : 0; @@ -2601,8 +2604,11 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, * The set of characters that may appear in URI is as follows: * * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', - * '%'. + * '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%'. + * + * If we are inside a verbatim tag <...> (parameter uri_char is true) + * then also the following flow indicators are allowed: + * ',', '[', ']' */ while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';') @@ -2610,12 +2616,15 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=') || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$') - || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.') + || CHECK(parser->buffer, '.') || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~') || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'') || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')') - || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') - || CHECK(parser->buffer, '%')) + || (uri_char && ( + CHECK(parser->buffer, ',') + || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') + ) + )) { /* Check if it is a URI-escape sequence. */ @@ -2860,7 +2869,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, if (!CACHE(parser, 1)) goto error; - while ((int)parser->mark.column == indent && !IS_Z(parser->buffer)) + while ((int)parser->mark.column == indent && !(IS_Z(parser->buffer))) { /* * We are at the beginning of a non-empty line. @@ -3278,7 +3287,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, /* Check if we are at the end of the scalar. */ - /* Fix for crash unitialized value crash + /* Fix for crash uninitialized value crash * Credit for the bug and input is to OSS Fuzz * Credit for the fix to Alex Gaynor */ @@ -3430,11 +3439,22 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) while (!IS_BLANKZ(parser->buffer)) { - /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */ + /* Check for "x:" + one of ',?[]{}' in the flow context. TODO: Fix the test "spec-08-13". + * This is not completely according to the spec + * See http://yaml.org/spec/1.1/#id907281 9.1.3. Plain + */ if (parser->flow_level && CHECK(parser->buffer, ':') - && !IS_BLANKZ_AT(parser->buffer, 1)) { + && ( + CHECK_AT(parser->buffer, ',', 1) + || CHECK_AT(parser->buffer, '?', 1) + || CHECK_AT(parser->buffer, '[', 1) + || CHECK_AT(parser->buffer, ']', 1) + || CHECK_AT(parser->buffer, '{', 1) + || CHECK_AT(parser->buffer, '}', 1) + ) + ) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found unexpected ':'"); goto error; @@ -3444,8 +3464,8 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1)) || (parser->flow_level && - (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':') - || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[') + (CHECK(parser->buffer, ',') + || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') || CHECK(parser->buffer, '}')))) break; @@ -3512,7 +3532,7 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) if (leading_blanks && (int)parser->mark.column < indent && IS_TAB(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violate indentation"); + start_mark, "found a tab character that violates indentation"); goto error; } diff --git a/ruby/ext/psych/yaml/yaml.h b/ruby/ext/psych/yaml/yaml.h index f33a15259..f1b7bfde2 100644 --- a/ruby/ext/psych/yaml/yaml.h +++ b/ruby/ext/psych/yaml/yaml.h @@ -26,7 +26,9 @@ extern "C" { /** The public API declaration. */ -#ifdef _WIN32 +#if defined(__MINGW32__) +# define YAML_DECLARE(type) type +#elif defined(_WIN32) # if defined(YAML_DECLARE_STATIC) # define YAML_DECLARE(type) type # elif defined(YAML_DECLARE_EXPORT) @@ -230,7 +232,7 @@ typedef enum yaml_token_type_e { /** A BLOCK-SEQUENCE-START token. */ YAML_BLOCK_SEQUENCE_START_TOKEN, - /** A BLOCK-SEQUENCE-END token. */ + /** A BLOCK-MAPPING-START token. */ YAML_BLOCK_MAPPING_START_TOKEN, /** A BLOCK-END token. */ YAML_BLOCK_END_TOKEN, @@ -550,7 +552,7 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit); */ YAML_DECLARE(int) -yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor); +yaml_alias_event_initialize(yaml_event_t *event, const yaml_char_t *anchor); /** * Create a SCALAR event. @@ -576,8 +578,8 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor); YAML_DECLARE(int) yaml_scalar_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, - yaml_char_t *value, int length, + const yaml_char_t *anchor, const yaml_char_t *tag, + const yaml_char_t *value, int length, int plain_implicit, int quoted_implicit, yaml_scalar_style_t style); @@ -599,7 +601,7 @@ yaml_scalar_event_initialize(yaml_event_t *event, YAML_DECLARE(int) yaml_sequence_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, + const yaml_char_t *anchor, const yaml_char_t *tag, int implicit, yaml_sequence_style_t style); /** @@ -631,7 +633,7 @@ yaml_sequence_end_event_initialize(yaml_event_t *event); YAML_DECLARE(int) yaml_mapping_start_event_initialize(yaml_event_t *event, - yaml_char_t *anchor, yaml_char_t *tag, int implicit, + const yaml_char_t *anchor, const yaml_char_t *tag, int implicit, yaml_mapping_style_t style); /** @@ -663,7 +665,7 @@ yaml_event_delete(yaml_event_t *event); /** The tag @c !!null with the only possible value: @c null. */ #define YAML_NULL_TAG "tag:yaml.org,2002:null" -/** The tag @c !!bool with the values: @c true and @c falce. */ +/** The tag @c !!bool with the values: @c true and @c false. */ #define YAML_BOOL_TAG "tag:yaml.org,2002:bool" /** The tag @c !!str for string values. */ #define YAML_STR_TAG "tag:yaml.org,2002:str" @@ -894,7 +896,7 @@ yaml_document_get_root_node(yaml_document_t *document); YAML_DECLARE(int) yaml_document_add_scalar(yaml_document_t *document, - yaml_char_t *tag, yaml_char_t *value, int length, + const yaml_char_t *tag, const yaml_char_t *value, int length, yaml_scalar_style_t style); /** @@ -911,7 +913,7 @@ yaml_document_add_scalar(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_sequence(yaml_document_t *document, - yaml_char_t *tag, yaml_sequence_style_t style); + const yaml_char_t *tag, yaml_sequence_style_t style); /** * Create a MAPPING node and attach it to the document. @@ -927,7 +929,7 @@ yaml_document_add_sequence(yaml_document_t *document, YAML_DECLARE(int) yaml_document_add_mapping(yaml_document_t *document, - yaml_char_t *tag, yaml_mapping_style_t style); + const yaml_char_t *tag, yaml_mapping_style_t style); /** * Add an item to a SEQUENCE node. @@ -935,7 +937,7 @@ yaml_document_add_mapping(yaml_document_t *document, * @param[in,out] document A document object. * @param[in] sequence The sequence node id. * @param[in] item The item node id. -* + * * @returns @c 1 if the function succeeded, @c 0 on error. */ @@ -950,7 +952,7 @@ yaml_document_append_sequence_item(yaml_document_t *document, * @param[in] mapping The mapping node id. * @param[in] key The key node id. * @param[in] value The value node id. -* + * * @returns @c 1 if the function succeeded, @c 0 on error. */ @@ -1018,6 +1020,7 @@ typedef enum yaml_parser_state_e { YAML_PARSE_DOCUMENT_CONTENT_STATE, /** Expect DOCUMENT-END. */ YAML_PARSE_DOCUMENT_END_STATE, + /** Expect a block node. */ YAML_PARSE_BLOCK_NODE_STATE, /** Expect a block node or indentless sequence. */ @@ -1028,6 +1031,7 @@ typedef enum yaml_parser_state_e { YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, /** Expect an entry of a block sequence. */ YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, + /** Expect an entry of an indentless sequence. */ YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, /** Expect the first key of a block mapping. */ @@ -1038,6 +1042,7 @@ typedef enum yaml_parser_state_e { YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, /** Expect the first entry of a flow sequence. */ YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, + /** Expect an entry of a flow sequence. */ YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, /** Expect a key of an ordered mapping. */ @@ -1049,6 +1054,7 @@ typedef enum yaml_parser_state_e { /** Expect the first key of a flow mapping. */ YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, /** Expect a key of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_KEY_STATE, /** Expect a value of a flow mapping. */ YAML_PARSE_FLOW_MAPPING_VALUE_STATE, @@ -1203,7 +1209,7 @@ typedef struct yaml_parser_s { /** The number of tokens fetched from the queue. */ size_t tokens_parsed; - /* Does the tokens queue contain a token ready for dequeueing. */ + /** Does the tokens queue contain a token ready for dequeueing. */ int token_available; /** The indentation levels stack. */ @@ -1329,7 +1335,7 @@ yaml_parser_delete(yaml_parser_t *parser); * Set a string input. * * Note that the @a input pointer must be valid while the @a parser object - * exists. The application is responsible for destroing @a input after + * exists. The application is responsible for destroying @a input after * destroying the @a parser. * * @param[in,out] parser A parser object. @@ -1444,7 +1450,7 @@ yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); * @param[in,out] parser A parser object. * @param[out] document An empty document object. * - * @return @c 1 if the function succeeded, @c 0 on error. + * @returns @c 1 if the function succeeded, @c 0 on error. */ YAML_DECLARE(int) @@ -1487,6 +1493,7 @@ typedef enum yaml_emitter_state_e { YAML_EMIT_DOCUMENT_CONTENT_STATE, /** Expect DOCUMENT-END. */ YAML_EMIT_DOCUMENT_END_STATE, + /** Expect the first item of a flow sequence. */ YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, /** Expect an item of a flow sequence. */ @@ -1497,6 +1504,7 @@ typedef enum yaml_emitter_state_e { YAML_EMIT_FLOW_MAPPING_KEY_STATE, /** Expect a value for a simple key of a flow mapping. */ YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, + /** Expect a value of a flow mapping. */ YAML_EMIT_FLOW_MAPPING_VALUE_STATE, /** Expect the first item of a block sequence. */ @@ -1507,6 +1515,7 @@ typedef enum yaml_emitter_state_e { YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, /** Expect the key of a block mapping. */ YAML_EMIT_BLOCK_MAPPING_KEY_STATE, + /** Expect a value for a simple key of a block mapping. */ YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, /** Expect a value of a block mapping. */ @@ -1515,6 +1524,18 @@ typedef enum yaml_emitter_state_e { YAML_EMIT_END_STATE } yaml_emitter_state_t; + +/* This is needed for C++ */ + +typedef struct yaml_anchors_s { + /** The number of references. */ + int references; + /** The anchor id. */ + int anchor; + /** If the node has been emitted? */ + int serialized; +} yaml_anchors_t; + /** * The emitter structure. * @@ -1546,7 +1567,7 @@ typedef struct yaml_emitter_s { /** Write handler. */ yaml_write_handler_t *write_handler; - /** A pointer for passing to the white handler. */ + /** A pointer for passing to the write handler. */ void *write_handler_data; /** Standard (string or file) output data. */ @@ -1713,7 +1734,7 @@ typedef struct yaml_emitter_s { size_t length; /** Does the scalar contain line breaks? */ int multiline; - /** Can the scalar be expessed in the flow plain style? */ + /** Can the scalar be expressed in the flow plain style? */ int flow_plain_allowed; /** Can the scalar be expressed in the block plain style? */ int block_plain_allowed; @@ -1740,14 +1761,7 @@ typedef struct yaml_emitter_s { int closed; /** The information associated with the document nodes. */ - struct { - /** The number of references. */ - int references; - /** The anchor id. */ - int anchor; - /** If the node has been emitted? */ - int serialized; - } *anchors; + yaml_anchors_t *anchors; /** The last assigned anchor id. */ int last_anchor_id; @@ -1936,10 +1950,10 @@ yaml_emitter_close(yaml_emitter_t *emitter); /** * Emit a YAML document. * - * The documen object may be generated using the yaml_parser_load() function + * The document object may be generated using the yaml_parser_load() function * or the yaml_document_initialize() function. The emitter takes the - * responsibility for the document object and destoys its content after - * it is emitted. The document object is destroyedeven if the function fails. + * responsibility for the document object and destroys its content after + * it is emitted. The document object is destroyed even if the function fails. * * @param[in,out] emitter An emitter object. * @param[in,out] document A document object. diff --git a/ruby/ext/psych/yaml/yaml_private.h b/ruby/ext/psych/yaml/yaml_private.h index f4f244cbc..266a6bd3a 100644 --- a/ruby/ext/psych/yaml/yaml_private.h +++ b/ruby/ext/psych/yaml/yaml_private.h @@ -2,8 +2,8 @@ #include RUBY_EXTCONF_H #endif -#if HAVE_CONFIG_H -#include +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include @@ -175,14 +175,14 @@ yaml_string_join( * Check the octet at the specified position. */ -#define CHECK_AT(string,octet,offset) \ +#define CHECK_AT(string,octet,offset) \ ((string).pointer[offset] == (yaml_char_t)(octet)) /* * Check the current octet in the buffer. */ -#define CHECK(string,octet) CHECK_AT((string),(octet),0) +#define CHECK(string,octet) (CHECK_AT((string),(octet),0)) /* * Check if the character at the specified position is an alphabetical diff --git a/ruby/ext/pty/depend b/ruby/ext/pty/depend index 1e89dc824..7baded100 100644 --- a/ruby/ext/pty/depend +++ b/ruby/ext/pty/depend @@ -1,12 +1,168 @@ # AUTOGENERATED DEPENDENCIES START pty.o: $(RUBY_EXTCONF_H) pty.o: $(arch_hdrdir)/ruby/config.h -pty.o: $(hdrdir)/ruby.h pty.o: $(hdrdir)/ruby/assert.h pty.o: $(hdrdir)/ruby/backward.h +pty.o: $(hdrdir)/ruby/backward/2/assume.h +pty.o: $(hdrdir)/ruby/backward/2/attributes.h +pty.o: $(hdrdir)/ruby/backward/2/bool.h +pty.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +pty.o: $(hdrdir)/ruby/backward/2/inttypes.h +pty.o: $(hdrdir)/ruby/backward/2/limits.h +pty.o: $(hdrdir)/ruby/backward/2/long_long.h +pty.o: $(hdrdir)/ruby/backward/2/stdalign.h +pty.o: $(hdrdir)/ruby/backward/2/stdarg.h pty.o: $(hdrdir)/ruby/defines.h pty.o: $(hdrdir)/ruby/encoding.h pty.o: $(hdrdir)/ruby/intern.h +pty.o: $(hdrdir)/ruby/internal/anyargs.h +pty.o: $(hdrdir)/ruby/internal/arithmetic.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/char.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/double.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/int.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/long.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/short.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +pty.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +pty.o: $(hdrdir)/ruby/internal/assume.h +pty.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +pty.o: $(hdrdir)/ruby/internal/attr/artificial.h +pty.o: $(hdrdir)/ruby/internal/attr/cold.h +pty.o: $(hdrdir)/ruby/internal/attr/const.h +pty.o: $(hdrdir)/ruby/internal/attr/constexpr.h +pty.o: $(hdrdir)/ruby/internal/attr/deprecated.h +pty.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +pty.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +pty.o: $(hdrdir)/ruby/internal/attr/error.h +pty.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +pty.o: $(hdrdir)/ruby/internal/attr/forceinline.h +pty.o: $(hdrdir)/ruby/internal/attr/format.h +pty.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +pty.o: $(hdrdir)/ruby/internal/attr/noalias.h +pty.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +pty.o: $(hdrdir)/ruby/internal/attr/noexcept.h +pty.o: $(hdrdir)/ruby/internal/attr/noinline.h +pty.o: $(hdrdir)/ruby/internal/attr/nonnull.h +pty.o: $(hdrdir)/ruby/internal/attr/noreturn.h +pty.o: $(hdrdir)/ruby/internal/attr/pure.h +pty.o: $(hdrdir)/ruby/internal/attr/restrict.h +pty.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +pty.o: $(hdrdir)/ruby/internal/attr/warning.h +pty.o: $(hdrdir)/ruby/internal/attr/weakref.h +pty.o: $(hdrdir)/ruby/internal/cast.h +pty.o: $(hdrdir)/ruby/internal/compiler_is.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +pty.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +pty.o: $(hdrdir)/ruby/internal/compiler_since.h +pty.o: $(hdrdir)/ruby/internal/config.h +pty.o: $(hdrdir)/ruby/internal/constant_p.h +pty.o: $(hdrdir)/ruby/internal/core.h +pty.o: $(hdrdir)/ruby/internal/core/rarray.h +pty.o: $(hdrdir)/ruby/internal/core/rbasic.h +pty.o: $(hdrdir)/ruby/internal/core/rbignum.h +pty.o: $(hdrdir)/ruby/internal/core/rclass.h +pty.o: $(hdrdir)/ruby/internal/core/rdata.h +pty.o: $(hdrdir)/ruby/internal/core/rfile.h +pty.o: $(hdrdir)/ruby/internal/core/rhash.h +pty.o: $(hdrdir)/ruby/internal/core/robject.h +pty.o: $(hdrdir)/ruby/internal/core/rregexp.h +pty.o: $(hdrdir)/ruby/internal/core/rstring.h +pty.o: $(hdrdir)/ruby/internal/core/rstruct.h +pty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +pty.o: $(hdrdir)/ruby/internal/ctype.h +pty.o: $(hdrdir)/ruby/internal/dllexport.h +pty.o: $(hdrdir)/ruby/internal/dosish.h +pty.o: $(hdrdir)/ruby/internal/encoding/coderange.h +pty.o: $(hdrdir)/ruby/internal/encoding/ctype.h +pty.o: $(hdrdir)/ruby/internal/encoding/encoding.h +pty.o: $(hdrdir)/ruby/internal/encoding/pathname.h +pty.o: $(hdrdir)/ruby/internal/encoding/re.h +pty.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +pty.o: $(hdrdir)/ruby/internal/encoding/string.h +pty.o: $(hdrdir)/ruby/internal/encoding/symbol.h +pty.o: $(hdrdir)/ruby/internal/encoding/transcode.h +pty.o: $(hdrdir)/ruby/internal/error.h +pty.o: $(hdrdir)/ruby/internal/eval.h +pty.o: $(hdrdir)/ruby/internal/event.h +pty.o: $(hdrdir)/ruby/internal/fl_type.h +pty.o: $(hdrdir)/ruby/internal/gc.h +pty.o: $(hdrdir)/ruby/internal/glob.h +pty.o: $(hdrdir)/ruby/internal/globals.h +pty.o: $(hdrdir)/ruby/internal/has/attribute.h +pty.o: $(hdrdir)/ruby/internal/has/builtin.h +pty.o: $(hdrdir)/ruby/internal/has/c_attribute.h +pty.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +pty.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +pty.o: $(hdrdir)/ruby/internal/has/extension.h +pty.o: $(hdrdir)/ruby/internal/has/feature.h +pty.o: $(hdrdir)/ruby/internal/has/warning.h +pty.o: $(hdrdir)/ruby/internal/intern/array.h +pty.o: $(hdrdir)/ruby/internal/intern/bignum.h +pty.o: $(hdrdir)/ruby/internal/intern/class.h +pty.o: $(hdrdir)/ruby/internal/intern/compar.h +pty.o: $(hdrdir)/ruby/internal/intern/complex.h +pty.o: $(hdrdir)/ruby/internal/intern/cont.h +pty.o: $(hdrdir)/ruby/internal/intern/dir.h +pty.o: $(hdrdir)/ruby/internal/intern/enum.h +pty.o: $(hdrdir)/ruby/internal/intern/enumerator.h +pty.o: $(hdrdir)/ruby/internal/intern/error.h +pty.o: $(hdrdir)/ruby/internal/intern/eval.h +pty.o: $(hdrdir)/ruby/internal/intern/file.h +pty.o: $(hdrdir)/ruby/internal/intern/gc.h +pty.o: $(hdrdir)/ruby/internal/intern/hash.h +pty.o: $(hdrdir)/ruby/internal/intern/io.h +pty.o: $(hdrdir)/ruby/internal/intern/load.h +pty.o: $(hdrdir)/ruby/internal/intern/marshal.h +pty.o: $(hdrdir)/ruby/internal/intern/numeric.h +pty.o: $(hdrdir)/ruby/internal/intern/object.h +pty.o: $(hdrdir)/ruby/internal/intern/parse.h +pty.o: $(hdrdir)/ruby/internal/intern/proc.h +pty.o: $(hdrdir)/ruby/internal/intern/process.h +pty.o: $(hdrdir)/ruby/internal/intern/random.h +pty.o: $(hdrdir)/ruby/internal/intern/range.h +pty.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h +pty.o: $(hdrdir)/ruby/internal/intern/string.h +pty.o: $(hdrdir)/ruby/internal/intern/struct.h +pty.o: $(hdrdir)/ruby/internal/intern/thread.h +pty.o: $(hdrdir)/ruby/internal/intern/time.h +pty.o: $(hdrdir)/ruby/internal/intern/variable.h +pty.o: $(hdrdir)/ruby/internal/intern/vm.h +pty.o: $(hdrdir)/ruby/internal/interpreter.h +pty.o: $(hdrdir)/ruby/internal/iterator.h +pty.o: $(hdrdir)/ruby/internal/memory.h +pty.o: $(hdrdir)/ruby/internal/method.h +pty.o: $(hdrdir)/ruby/internal/module.h +pty.o: $(hdrdir)/ruby/internal/newobj.h +pty.o: $(hdrdir)/ruby/internal/rgengc.h +pty.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +pty.o: $(hdrdir)/ruby/internal/value.h +pty.o: $(hdrdir)/ruby/internal/value_type.h +pty.o: $(hdrdir)/ruby/internal/variable.h +pty.o: $(hdrdir)/ruby/internal/warning_push.h +pty.o: $(hdrdir)/ruby/internal/xmalloc.h pty.o: $(hdrdir)/ruby/io.h pty.o: $(hdrdir)/ruby/missing.h pty.o: $(hdrdir)/ruby/onigmo.h @@ -16,5 +172,13 @@ pty.o: $(hdrdir)/ruby/st.h pty.o: $(hdrdir)/ruby/subst.h pty.o: $(hdrdir)/ruby/util.h pty.o: $(top_srcdir)/internal.h +pty.o: $(top_srcdir)/internal/array.h +pty.o: $(top_srcdir)/internal/compilers.h +pty.o: $(top_srcdir)/internal/gc.h +pty.o: $(top_srcdir)/internal/imemo.h +pty.o: $(top_srcdir)/internal/process.h +pty.o: $(top_srcdir)/internal/signal.h +pty.o: $(top_srcdir)/internal/static_assert.h +pty.o: $(top_srcdir)/internal/warnings.h pty.o: pty.c # AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/pty/extconf.rb b/ruby/ext/pty/extconf.rb index 7721a744c..038bdf4d2 100644 --- a/ruby/ext/pty/extconf.rb +++ b/ruby/ext/pty/extconf.rb @@ -10,9 +10,9 @@ have_header("util.h") # OpenBSD openpty have_header("pty.h") have_header("pwd.h") - have_library("util", "openpty") + util = have_library("util", "openpty") if have_func("posix_openpt") or - have_func("openpty") or + (util or have_func("openpty")) or have_func("_getpty") or have_func("ptsname") or have_func("ioctl") diff --git a/ruby/ext/pty/pty.c b/ruby/ext/pty/pty.c index 4c6ae2612..72074f742 100644 --- a/ruby/ext/pty/pty.c +++ b/ruby/ext/pty/pty.c @@ -1,45 +1,51 @@ -#include "ruby/config.h" +#include "ruby/config.h" + #ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H +# include RUBY_EXTCONF_H #endif -#include -#include -#include -#include -#include -#include -#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + #ifdef HAVE_PWD_H -#include +# include #endif + #ifdef HAVE_SYS_IOCTL_H -#include +# include #endif + #ifdef HAVE_LIBUTIL_H -#include +# include #endif + #ifdef HAVE_UTIL_H -#include +# include #endif + #ifdef HAVE_PTY_H -#include +# include #endif + #if defined(HAVE_SYS_PARAM_H) - /* for __FreeBSD_version */ + /* for __FreeBSD_version */ # include #endif + #ifdef HAVE_SYS_WAIT_H -#include +# include #else -#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +# define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) #endif -#include - -#include "ruby/io.h" -#include "internal.h" -#include "ruby/util.h" -#include #ifdef HAVE_SYS_STROPTS_H #include #endif @@ -48,6 +54,12 @@ #include #endif +#include "internal.h" +#include "internal/process.h" +#include "internal/signal.h" +#include "ruby/io.h" +#include "ruby/util.h" + #define DEVICELEN 16 #ifndef HAVE_SETEUID @@ -259,7 +271,7 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, int flags = O_RDWR|O_NOCTTY; # if defined(O_CLOEXEC) /* glibc posix_openpt() in GNU/Linux calls open("/dev/ptmx", flags) internally. - * So version dependency on GNU/Linux is same as O_CLOEXEC with open(). + * So version dependency on GNU/Linux is the same as O_CLOEXEC with open(). * O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */ flags |= O_CLOEXEC; # endif @@ -452,11 +464,11 @@ pty_close_pty(VALUE assoc) /* * call-seq: * PTY.open => [master_io, slave_file] - * PTY.open {|master_io, slave_file| ... } => block value + * PTY.open {|(master_io, slave_file)| ... } => block value * * Allocates a pty (pseudo-terminal). * - * In the block form, yields two arguments master_io, slave_file + * In the block form, yields an array of two elements (master_io, slave_file) * and the value of the block is returned from +open+. * * The IO and File are both closed after the block completes if they haven't @@ -485,7 +497,7 @@ pty_close_pty(VALUE assoc) * require 'io/console' * PTY.open {|m, s| * s.raw! - * ... + * # ... * } * */ @@ -682,7 +694,7 @@ static VALUE cPTY; * Document-class: PTY * * Creates and manages pseudo terminals (PTYs). See also - * http://en.wikipedia.org/wiki/Pseudo_terminal + * https://en.wikipedia.org/wiki/Pseudo_terminal * * PTY allows you to allocate new terminals using ::open or ::spawn a new * terminal with a specific command. @@ -725,16 +737,16 @@ static VALUE cPTY; * * == License * - * C) Copyright 1998 by Akinori Ito. + * (c) Copyright 1998 by Akinori Ito. * - * This software may be redistributed freely for this purpose, in full - * or in part, provided that this entire copyright notice is included - * on any copies of this software and applications and derivations thereof. + * This software may be redistributed freely for this purpose, in full + * or in part, provided that this entire copyright notice is included + * on any copies of this software and applications and derivations thereof. * - * This software is provided on an "as is" basis, without warranty of any - * kind, either expressed or implied, as to any matter including, but not - * limited to warranty of fitness of purpose, or merchantability, or - * results obtained from use of this software. + * This software is provided on an "as is" basis, without warranty of any + * kind, either expressed or implied, as to any matter including, but not + * limited to warranty of fitness of purpose, or merchantability, or + * results obtained from use of this software. */ void diff --git a/ruby/ext/racc/cparse/cparse.c b/ruby/ext/racc/cparse/cparse.c index ca74b8000..f71ed2bba 100644 --- a/ruby/ext/racc/cparse/cparse.c +++ b/ruby/ext/racc/cparse/cparse.c @@ -605,7 +605,7 @@ parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume) user_yyerror: if (v->errstatus == 3) { if (v->t == vFINAL_TOKEN) { - v->retval = Qfalse; + v->retval = Qnil; v->fin = CP_FIN_EOT; return; } @@ -819,14 +819,16 @@ reduce0(RB_BLOCK_CALL_FUNC_ARGLIST(_, data)) void Init_cparse(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + VALUE Racc, Parser; - ID id_racc = rb_intern("Racc"); + ID id_racc = rb_intern_const("Racc"); if (rb_const_defined(rb_cObject, id_racc)) { Racc = rb_const_get(rb_cObject, id_racc); - Parser = rb_const_get_at(Racc, rb_intern("Parser")); + Parser = rb_const_get_at(Racc, rb_intern_const("Parser")); } else { Racc = rb_define_module("Racc"); @@ -846,16 +848,16 @@ Init_cparse(void) RaccBug = rb_eRuntimeError; - id_yydebug = rb_intern("@yydebug"); - id_nexttoken = rb_intern("next_token"); - id_onerror = rb_intern("on_error"); - id_noreduce = rb_intern("_reduce_none"); - id_errstatus = rb_intern("@racc_error_status"); - - id_d_shift = rb_intern("racc_shift"); - id_d_reduce = rb_intern("racc_reduce"); - id_d_accept = rb_intern("racc_accept"); - id_d_read_token = rb_intern("racc_read_token"); - id_d_next_state = rb_intern("racc_next_state"); - id_d_e_pop = rb_intern("racc_e_pop"); + id_yydebug = rb_intern_const("@yydebug"); + id_nexttoken = rb_intern_const("next_token"); + id_onerror = rb_intern_const("on_error"); + id_noreduce = rb_intern_const("_reduce_none"); + id_errstatus = rb_intern_const("@racc_error_status"); + + id_d_shift = rb_intern_const("racc_shift"); + id_d_reduce = rb_intern_const("racc_reduce"); + id_d_accept = rb_intern_const("racc_accept"); + id_d_read_token = rb_intern_const("racc_read_token"); + id_d_next_state = rb_intern_const("racc_next_state"); + id_d_e_pop = rb_intern_const("racc_e_pop"); } diff --git a/ruby/ext/racc/cparse/depend b/ruby/ext/racc/cparse/depend index a156b3234..cb2a1b6bd 100644 --- a/ruby/ext/racc/cparse/depend +++ b/ruby/ext/racc/cparse/depend @@ -4,8 +4,155 @@ cparse.o: $(arch_hdrdir)/ruby/config.h cparse.o: $(hdrdir)/ruby.h cparse.o: $(hdrdir)/ruby/assert.h cparse.o: $(hdrdir)/ruby/backward.h +cparse.o: $(hdrdir)/ruby/backward/2/assume.h +cparse.o: $(hdrdir)/ruby/backward/2/attributes.h +cparse.o: $(hdrdir)/ruby/backward/2/bool.h +cparse.o: $(hdrdir)/ruby/backward/2/inttypes.h +cparse.o: $(hdrdir)/ruby/backward/2/limits.h +cparse.o: $(hdrdir)/ruby/backward/2/long_long.h +cparse.o: $(hdrdir)/ruby/backward/2/stdalign.h +cparse.o: $(hdrdir)/ruby/backward/2/stdarg.h cparse.o: $(hdrdir)/ruby/defines.h cparse.o: $(hdrdir)/ruby/intern.h +cparse.o: $(hdrdir)/ruby/internal/anyargs.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/char.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/double.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/int.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/long.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/short.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +cparse.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +cparse.o: $(hdrdir)/ruby/internal/assume.h +cparse.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +cparse.o: $(hdrdir)/ruby/internal/attr/artificial.h +cparse.o: $(hdrdir)/ruby/internal/attr/cold.h +cparse.o: $(hdrdir)/ruby/internal/attr/const.h +cparse.o: $(hdrdir)/ruby/internal/attr/constexpr.h +cparse.o: $(hdrdir)/ruby/internal/attr/deprecated.h +cparse.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +cparse.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +cparse.o: $(hdrdir)/ruby/internal/attr/error.h +cparse.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +cparse.o: $(hdrdir)/ruby/internal/attr/forceinline.h +cparse.o: $(hdrdir)/ruby/internal/attr/format.h +cparse.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +cparse.o: $(hdrdir)/ruby/internal/attr/noalias.h +cparse.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +cparse.o: $(hdrdir)/ruby/internal/attr/noexcept.h +cparse.o: $(hdrdir)/ruby/internal/attr/noinline.h +cparse.o: $(hdrdir)/ruby/internal/attr/nonnull.h +cparse.o: $(hdrdir)/ruby/internal/attr/noreturn.h +cparse.o: $(hdrdir)/ruby/internal/attr/pure.h +cparse.o: $(hdrdir)/ruby/internal/attr/restrict.h +cparse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +cparse.o: $(hdrdir)/ruby/internal/attr/warning.h +cparse.o: $(hdrdir)/ruby/internal/attr/weakref.h +cparse.o: $(hdrdir)/ruby/internal/cast.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +cparse.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +cparse.o: $(hdrdir)/ruby/internal/compiler_since.h +cparse.o: $(hdrdir)/ruby/internal/config.h +cparse.o: $(hdrdir)/ruby/internal/constant_p.h +cparse.o: $(hdrdir)/ruby/internal/core.h +cparse.o: $(hdrdir)/ruby/internal/core/rarray.h +cparse.o: $(hdrdir)/ruby/internal/core/rbasic.h +cparse.o: $(hdrdir)/ruby/internal/core/rbignum.h +cparse.o: $(hdrdir)/ruby/internal/core/rclass.h +cparse.o: $(hdrdir)/ruby/internal/core/rdata.h +cparse.o: $(hdrdir)/ruby/internal/core/rfile.h +cparse.o: $(hdrdir)/ruby/internal/core/rhash.h +cparse.o: $(hdrdir)/ruby/internal/core/robject.h +cparse.o: $(hdrdir)/ruby/internal/core/rregexp.h +cparse.o: $(hdrdir)/ruby/internal/core/rstring.h +cparse.o: $(hdrdir)/ruby/internal/core/rstruct.h +cparse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +cparse.o: $(hdrdir)/ruby/internal/ctype.h +cparse.o: $(hdrdir)/ruby/internal/dllexport.h +cparse.o: $(hdrdir)/ruby/internal/dosish.h +cparse.o: $(hdrdir)/ruby/internal/error.h +cparse.o: $(hdrdir)/ruby/internal/eval.h +cparse.o: $(hdrdir)/ruby/internal/event.h +cparse.o: $(hdrdir)/ruby/internal/fl_type.h +cparse.o: $(hdrdir)/ruby/internal/gc.h +cparse.o: $(hdrdir)/ruby/internal/glob.h +cparse.o: $(hdrdir)/ruby/internal/globals.h +cparse.o: $(hdrdir)/ruby/internal/has/attribute.h +cparse.o: $(hdrdir)/ruby/internal/has/builtin.h +cparse.o: $(hdrdir)/ruby/internal/has/c_attribute.h +cparse.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +cparse.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +cparse.o: $(hdrdir)/ruby/internal/has/extension.h +cparse.o: $(hdrdir)/ruby/internal/has/feature.h +cparse.o: $(hdrdir)/ruby/internal/has/warning.h +cparse.o: $(hdrdir)/ruby/internal/intern/array.h +cparse.o: $(hdrdir)/ruby/internal/intern/bignum.h +cparse.o: $(hdrdir)/ruby/internal/intern/class.h +cparse.o: $(hdrdir)/ruby/internal/intern/compar.h +cparse.o: $(hdrdir)/ruby/internal/intern/complex.h +cparse.o: $(hdrdir)/ruby/internal/intern/cont.h +cparse.o: $(hdrdir)/ruby/internal/intern/dir.h +cparse.o: $(hdrdir)/ruby/internal/intern/enum.h +cparse.o: $(hdrdir)/ruby/internal/intern/enumerator.h +cparse.o: $(hdrdir)/ruby/internal/intern/error.h +cparse.o: $(hdrdir)/ruby/internal/intern/eval.h +cparse.o: $(hdrdir)/ruby/internal/intern/file.h +cparse.o: $(hdrdir)/ruby/internal/intern/gc.h +cparse.o: $(hdrdir)/ruby/internal/intern/hash.h +cparse.o: $(hdrdir)/ruby/internal/intern/io.h +cparse.o: $(hdrdir)/ruby/internal/intern/load.h +cparse.o: $(hdrdir)/ruby/internal/intern/marshal.h +cparse.o: $(hdrdir)/ruby/internal/intern/numeric.h +cparse.o: $(hdrdir)/ruby/internal/intern/object.h +cparse.o: $(hdrdir)/ruby/internal/intern/parse.h +cparse.o: $(hdrdir)/ruby/internal/intern/proc.h +cparse.o: $(hdrdir)/ruby/internal/intern/process.h +cparse.o: $(hdrdir)/ruby/internal/intern/random.h +cparse.o: $(hdrdir)/ruby/internal/intern/range.h +cparse.o: $(hdrdir)/ruby/internal/intern/rational.h +cparse.o: $(hdrdir)/ruby/internal/intern/re.h +cparse.o: $(hdrdir)/ruby/internal/intern/ruby.h +cparse.o: $(hdrdir)/ruby/internal/intern/select.h +cparse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +cparse.o: $(hdrdir)/ruby/internal/intern/signal.h +cparse.o: $(hdrdir)/ruby/internal/intern/sprintf.h +cparse.o: $(hdrdir)/ruby/internal/intern/string.h +cparse.o: $(hdrdir)/ruby/internal/intern/struct.h +cparse.o: $(hdrdir)/ruby/internal/intern/thread.h +cparse.o: $(hdrdir)/ruby/internal/intern/time.h +cparse.o: $(hdrdir)/ruby/internal/intern/variable.h +cparse.o: $(hdrdir)/ruby/internal/intern/vm.h +cparse.o: $(hdrdir)/ruby/internal/interpreter.h +cparse.o: $(hdrdir)/ruby/internal/iterator.h +cparse.o: $(hdrdir)/ruby/internal/memory.h +cparse.o: $(hdrdir)/ruby/internal/method.h +cparse.o: $(hdrdir)/ruby/internal/module.h +cparse.o: $(hdrdir)/ruby/internal/newobj.h +cparse.o: $(hdrdir)/ruby/internal/rgengc.h +cparse.o: $(hdrdir)/ruby/internal/scan_args.h +cparse.o: $(hdrdir)/ruby/internal/special_consts.h +cparse.o: $(hdrdir)/ruby/internal/static_assert.h +cparse.o: $(hdrdir)/ruby/internal/stdalign.h +cparse.o: $(hdrdir)/ruby/internal/stdbool.h +cparse.o: $(hdrdir)/ruby/internal/symbol.h +cparse.o: $(hdrdir)/ruby/internal/value.h +cparse.o: $(hdrdir)/ruby/internal/value_type.h +cparse.o: $(hdrdir)/ruby/internal/variable.h +cparse.o: $(hdrdir)/ruby/internal/warning_push.h +cparse.o: $(hdrdir)/ruby/internal/xmalloc.h cparse.o: $(hdrdir)/ruby/missing.h cparse.o: $(hdrdir)/ruby/ruby.h cparse.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/racc/cparse/extconf.rb b/ruby/ext/racc/cparse/extconf.rb index 47b455d99..18c5689ad 100644 --- a/ruby/ext/racc/cparse/extconf.rb +++ b/ruby/ext/racc/cparse/extconf.rb @@ -1,8 +1,9 @@ # frozen_string_literal: false -# $Id: a9187b5bc40e6adf05e7b6ee5b370b39a3429ecd $ +# require 'mkmf' +have_func('rb_block_call') have_func('rb_ary_subseq') create_makefile 'racc/cparse' diff --git a/ruby/ext/rbconfig/sizeof/depend b/ruby/ext/rbconfig/sizeof/depend index 9433dd415..c4100266f 100644 --- a/ruby/ext/rbconfig/sizeof/depend +++ b/ruby/ext/rbconfig/sizeof/depend @@ -18,8 +18,155 @@ limits.o: $(RUBY_EXTCONF_H) limits.o: $(arch_hdrdir)/ruby/config.h limits.o: $(hdrdir)/ruby/assert.h limits.o: $(hdrdir)/ruby/backward.h +limits.o: $(hdrdir)/ruby/backward/2/assume.h +limits.o: $(hdrdir)/ruby/backward/2/attributes.h +limits.o: $(hdrdir)/ruby/backward/2/bool.h +limits.o: $(hdrdir)/ruby/backward/2/inttypes.h +limits.o: $(hdrdir)/ruby/backward/2/limits.h +limits.o: $(hdrdir)/ruby/backward/2/long_long.h +limits.o: $(hdrdir)/ruby/backward/2/stdalign.h +limits.o: $(hdrdir)/ruby/backward/2/stdarg.h limits.o: $(hdrdir)/ruby/defines.h limits.o: $(hdrdir)/ruby/intern.h +limits.o: $(hdrdir)/ruby/internal/anyargs.h +limits.o: $(hdrdir)/ruby/internal/arithmetic.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/char.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/double.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/int.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/long.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/short.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +limits.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +limits.o: $(hdrdir)/ruby/internal/assume.h +limits.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +limits.o: $(hdrdir)/ruby/internal/attr/artificial.h +limits.o: $(hdrdir)/ruby/internal/attr/cold.h +limits.o: $(hdrdir)/ruby/internal/attr/const.h +limits.o: $(hdrdir)/ruby/internal/attr/constexpr.h +limits.o: $(hdrdir)/ruby/internal/attr/deprecated.h +limits.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +limits.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +limits.o: $(hdrdir)/ruby/internal/attr/error.h +limits.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +limits.o: $(hdrdir)/ruby/internal/attr/forceinline.h +limits.o: $(hdrdir)/ruby/internal/attr/format.h +limits.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +limits.o: $(hdrdir)/ruby/internal/attr/noalias.h +limits.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +limits.o: $(hdrdir)/ruby/internal/attr/noexcept.h +limits.o: $(hdrdir)/ruby/internal/attr/noinline.h +limits.o: $(hdrdir)/ruby/internal/attr/nonnull.h +limits.o: $(hdrdir)/ruby/internal/attr/noreturn.h +limits.o: $(hdrdir)/ruby/internal/attr/pure.h +limits.o: $(hdrdir)/ruby/internal/attr/restrict.h +limits.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +limits.o: $(hdrdir)/ruby/internal/attr/warning.h +limits.o: $(hdrdir)/ruby/internal/attr/weakref.h +limits.o: $(hdrdir)/ruby/internal/cast.h +limits.o: $(hdrdir)/ruby/internal/compiler_is.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +limits.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +limits.o: $(hdrdir)/ruby/internal/compiler_since.h +limits.o: $(hdrdir)/ruby/internal/config.h +limits.o: $(hdrdir)/ruby/internal/constant_p.h +limits.o: $(hdrdir)/ruby/internal/core.h +limits.o: $(hdrdir)/ruby/internal/core/rarray.h +limits.o: $(hdrdir)/ruby/internal/core/rbasic.h +limits.o: $(hdrdir)/ruby/internal/core/rbignum.h +limits.o: $(hdrdir)/ruby/internal/core/rclass.h +limits.o: $(hdrdir)/ruby/internal/core/rdata.h +limits.o: $(hdrdir)/ruby/internal/core/rfile.h +limits.o: $(hdrdir)/ruby/internal/core/rhash.h +limits.o: $(hdrdir)/ruby/internal/core/robject.h +limits.o: $(hdrdir)/ruby/internal/core/rregexp.h +limits.o: $(hdrdir)/ruby/internal/core/rstring.h +limits.o: $(hdrdir)/ruby/internal/core/rstruct.h +limits.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +limits.o: $(hdrdir)/ruby/internal/ctype.h +limits.o: $(hdrdir)/ruby/internal/dllexport.h +limits.o: $(hdrdir)/ruby/internal/dosish.h +limits.o: $(hdrdir)/ruby/internal/error.h +limits.o: $(hdrdir)/ruby/internal/eval.h +limits.o: $(hdrdir)/ruby/internal/event.h +limits.o: $(hdrdir)/ruby/internal/fl_type.h +limits.o: $(hdrdir)/ruby/internal/gc.h +limits.o: $(hdrdir)/ruby/internal/glob.h +limits.o: $(hdrdir)/ruby/internal/globals.h +limits.o: $(hdrdir)/ruby/internal/has/attribute.h +limits.o: $(hdrdir)/ruby/internal/has/builtin.h +limits.o: $(hdrdir)/ruby/internal/has/c_attribute.h +limits.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +limits.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +limits.o: $(hdrdir)/ruby/internal/has/extension.h +limits.o: $(hdrdir)/ruby/internal/has/feature.h +limits.o: $(hdrdir)/ruby/internal/has/warning.h +limits.o: $(hdrdir)/ruby/internal/intern/array.h +limits.o: $(hdrdir)/ruby/internal/intern/bignum.h +limits.o: $(hdrdir)/ruby/internal/intern/class.h +limits.o: $(hdrdir)/ruby/internal/intern/compar.h +limits.o: $(hdrdir)/ruby/internal/intern/complex.h +limits.o: $(hdrdir)/ruby/internal/intern/cont.h +limits.o: $(hdrdir)/ruby/internal/intern/dir.h +limits.o: $(hdrdir)/ruby/internal/intern/enum.h +limits.o: $(hdrdir)/ruby/internal/intern/enumerator.h +limits.o: $(hdrdir)/ruby/internal/intern/error.h +limits.o: $(hdrdir)/ruby/internal/intern/eval.h +limits.o: $(hdrdir)/ruby/internal/intern/file.h +limits.o: $(hdrdir)/ruby/internal/intern/gc.h +limits.o: $(hdrdir)/ruby/internal/intern/hash.h +limits.o: $(hdrdir)/ruby/internal/intern/io.h +limits.o: $(hdrdir)/ruby/internal/intern/load.h +limits.o: $(hdrdir)/ruby/internal/intern/marshal.h +limits.o: $(hdrdir)/ruby/internal/intern/numeric.h +limits.o: $(hdrdir)/ruby/internal/intern/object.h +limits.o: $(hdrdir)/ruby/internal/intern/parse.h +limits.o: $(hdrdir)/ruby/internal/intern/proc.h +limits.o: $(hdrdir)/ruby/internal/intern/process.h +limits.o: $(hdrdir)/ruby/internal/intern/random.h +limits.o: $(hdrdir)/ruby/internal/intern/range.h +limits.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +limits.o: $(hdrdir)/ruby/internal/intern/sprintf.h +limits.o: $(hdrdir)/ruby/internal/intern/string.h +limits.o: $(hdrdir)/ruby/internal/intern/struct.h +limits.o: $(hdrdir)/ruby/internal/intern/thread.h +limits.o: $(hdrdir)/ruby/internal/intern/time.h +limits.o: $(hdrdir)/ruby/internal/intern/variable.h +limits.o: $(hdrdir)/ruby/internal/intern/vm.h +limits.o: $(hdrdir)/ruby/internal/interpreter.h +limits.o: $(hdrdir)/ruby/internal/iterator.h +limits.o: $(hdrdir)/ruby/internal/memory.h +limits.o: $(hdrdir)/ruby/internal/method.h +limits.o: $(hdrdir)/ruby/internal/module.h +limits.o: $(hdrdir)/ruby/internal/newobj.h +limits.o: $(hdrdir)/ruby/internal/rgengc.h +limits.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +limits.o: $(hdrdir)/ruby/internal/value.h +limits.o: $(hdrdir)/ruby/internal/value_type.h +limits.o: $(hdrdir)/ruby/internal/variable.h +limits.o: $(hdrdir)/ruby/internal/warning_push.h +limits.o: $(hdrdir)/ruby/internal/xmalloc.h limits.o: $(hdrdir)/ruby/missing.h limits.o: $(hdrdir)/ruby/ruby.h limits.o: $(hdrdir)/ruby/st.h @@ -29,8 +176,155 @@ sizes.o: $(RUBY_EXTCONF_H) sizes.o: $(arch_hdrdir)/ruby/config.h sizes.o: $(hdrdir)/ruby/assert.h sizes.o: $(hdrdir)/ruby/backward.h +sizes.o: $(hdrdir)/ruby/backward/2/assume.h +sizes.o: $(hdrdir)/ruby/backward/2/attributes.h +sizes.o: $(hdrdir)/ruby/backward/2/bool.h +sizes.o: $(hdrdir)/ruby/backward/2/inttypes.h +sizes.o: $(hdrdir)/ruby/backward/2/limits.h +sizes.o: $(hdrdir)/ruby/backward/2/long_long.h +sizes.o: $(hdrdir)/ruby/backward/2/stdalign.h +sizes.o: $(hdrdir)/ruby/backward/2/stdarg.h sizes.o: $(hdrdir)/ruby/defines.h sizes.o: $(hdrdir)/ruby/intern.h +sizes.o: $(hdrdir)/ruby/internal/anyargs.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sizes.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sizes.o: $(hdrdir)/ruby/internal/assume.h +sizes.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sizes.o: $(hdrdir)/ruby/internal/attr/artificial.h +sizes.o: $(hdrdir)/ruby/internal/attr/cold.h +sizes.o: $(hdrdir)/ruby/internal/attr/const.h +sizes.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sizes.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sizes.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sizes.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sizes.o: $(hdrdir)/ruby/internal/attr/error.h +sizes.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sizes.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sizes.o: $(hdrdir)/ruby/internal/attr/format.h +sizes.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sizes.o: $(hdrdir)/ruby/internal/attr/noalias.h +sizes.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sizes.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sizes.o: $(hdrdir)/ruby/internal/attr/noinline.h +sizes.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sizes.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sizes.o: $(hdrdir)/ruby/internal/attr/pure.h +sizes.o: $(hdrdir)/ruby/internal/attr/restrict.h +sizes.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sizes.o: $(hdrdir)/ruby/internal/attr/warning.h +sizes.o: $(hdrdir)/ruby/internal/attr/weakref.h +sizes.o: $(hdrdir)/ruby/internal/cast.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sizes.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sizes.o: $(hdrdir)/ruby/internal/compiler_since.h +sizes.o: $(hdrdir)/ruby/internal/config.h +sizes.o: $(hdrdir)/ruby/internal/constant_p.h +sizes.o: $(hdrdir)/ruby/internal/core.h +sizes.o: $(hdrdir)/ruby/internal/core/rarray.h +sizes.o: $(hdrdir)/ruby/internal/core/rbasic.h +sizes.o: $(hdrdir)/ruby/internal/core/rbignum.h +sizes.o: $(hdrdir)/ruby/internal/core/rclass.h +sizes.o: $(hdrdir)/ruby/internal/core/rdata.h +sizes.o: $(hdrdir)/ruby/internal/core/rfile.h +sizes.o: $(hdrdir)/ruby/internal/core/rhash.h +sizes.o: $(hdrdir)/ruby/internal/core/robject.h +sizes.o: $(hdrdir)/ruby/internal/core/rregexp.h +sizes.o: $(hdrdir)/ruby/internal/core/rstring.h +sizes.o: $(hdrdir)/ruby/internal/core/rstruct.h +sizes.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sizes.o: $(hdrdir)/ruby/internal/ctype.h +sizes.o: $(hdrdir)/ruby/internal/dllexport.h +sizes.o: $(hdrdir)/ruby/internal/dosish.h +sizes.o: $(hdrdir)/ruby/internal/error.h +sizes.o: $(hdrdir)/ruby/internal/eval.h +sizes.o: $(hdrdir)/ruby/internal/event.h +sizes.o: $(hdrdir)/ruby/internal/fl_type.h +sizes.o: $(hdrdir)/ruby/internal/gc.h +sizes.o: $(hdrdir)/ruby/internal/glob.h +sizes.o: $(hdrdir)/ruby/internal/globals.h +sizes.o: $(hdrdir)/ruby/internal/has/attribute.h +sizes.o: $(hdrdir)/ruby/internal/has/builtin.h +sizes.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sizes.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sizes.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sizes.o: $(hdrdir)/ruby/internal/has/extension.h +sizes.o: $(hdrdir)/ruby/internal/has/feature.h +sizes.o: $(hdrdir)/ruby/internal/has/warning.h +sizes.o: $(hdrdir)/ruby/internal/intern/array.h +sizes.o: $(hdrdir)/ruby/internal/intern/bignum.h +sizes.o: $(hdrdir)/ruby/internal/intern/class.h +sizes.o: $(hdrdir)/ruby/internal/intern/compar.h +sizes.o: $(hdrdir)/ruby/internal/intern/complex.h +sizes.o: $(hdrdir)/ruby/internal/intern/cont.h +sizes.o: $(hdrdir)/ruby/internal/intern/dir.h +sizes.o: $(hdrdir)/ruby/internal/intern/enum.h +sizes.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sizes.o: $(hdrdir)/ruby/internal/intern/error.h +sizes.o: $(hdrdir)/ruby/internal/intern/eval.h +sizes.o: $(hdrdir)/ruby/internal/intern/file.h +sizes.o: $(hdrdir)/ruby/internal/intern/gc.h +sizes.o: $(hdrdir)/ruby/internal/intern/hash.h +sizes.o: $(hdrdir)/ruby/internal/intern/io.h +sizes.o: $(hdrdir)/ruby/internal/intern/load.h +sizes.o: $(hdrdir)/ruby/internal/intern/marshal.h +sizes.o: $(hdrdir)/ruby/internal/intern/numeric.h +sizes.o: $(hdrdir)/ruby/internal/intern/object.h +sizes.o: $(hdrdir)/ruby/internal/intern/parse.h +sizes.o: $(hdrdir)/ruby/internal/intern/proc.h +sizes.o: $(hdrdir)/ruby/internal/intern/process.h +sizes.o: $(hdrdir)/ruby/internal/intern/random.h +sizes.o: $(hdrdir)/ruby/internal/intern/range.h +sizes.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +sizes.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sizes.o: $(hdrdir)/ruby/internal/intern/string.h +sizes.o: $(hdrdir)/ruby/internal/intern/struct.h +sizes.o: $(hdrdir)/ruby/internal/intern/thread.h +sizes.o: $(hdrdir)/ruby/internal/intern/time.h +sizes.o: $(hdrdir)/ruby/internal/intern/variable.h +sizes.o: $(hdrdir)/ruby/internal/intern/vm.h +sizes.o: $(hdrdir)/ruby/internal/interpreter.h +sizes.o: $(hdrdir)/ruby/internal/iterator.h +sizes.o: $(hdrdir)/ruby/internal/memory.h +sizes.o: $(hdrdir)/ruby/internal/method.h +sizes.o: $(hdrdir)/ruby/internal/module.h +sizes.o: $(hdrdir)/ruby/internal/newobj.h +sizes.o: $(hdrdir)/ruby/internal/rgengc.h +sizes.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +sizes.o: $(hdrdir)/ruby/internal/value.h +sizes.o: $(hdrdir)/ruby/internal/value_type.h +sizes.o: $(hdrdir)/ruby/internal/variable.h +sizes.o: $(hdrdir)/ruby/internal/warning_push.h +sizes.o: $(hdrdir)/ruby/internal/xmalloc.h sizes.o: $(hdrdir)/ruby/missing.h sizes.o: $(hdrdir)/ruby/ruby.h sizes.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/readline/depend b/ruby/ext/readline/depend index 2dde7fca5..818770b80 100644 --- a/ruby/ext/readline/depend +++ b/ruby/ext/readline/depend @@ -3,9 +3,165 @@ readline.o: $(RUBY_EXTCONF_H) readline.o: $(arch_hdrdir)/ruby/config.h readline.o: $(hdrdir)/ruby/assert.h readline.o: $(hdrdir)/ruby/backward.h +readline.o: $(hdrdir)/ruby/backward/2/assume.h +readline.o: $(hdrdir)/ruby/backward/2/attributes.h +readline.o: $(hdrdir)/ruby/backward/2/bool.h +readline.o: $(hdrdir)/ruby/backward/2/inttypes.h +readline.o: $(hdrdir)/ruby/backward/2/limits.h +readline.o: $(hdrdir)/ruby/backward/2/long_long.h +readline.o: $(hdrdir)/ruby/backward/2/stdalign.h +readline.o: $(hdrdir)/ruby/backward/2/stdarg.h readline.o: $(hdrdir)/ruby/defines.h readline.o: $(hdrdir)/ruby/encoding.h readline.o: $(hdrdir)/ruby/intern.h +readline.o: $(hdrdir)/ruby/internal/anyargs.h +readline.o: $(hdrdir)/ruby/internal/arithmetic.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/char.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/double.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/int.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/long.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/short.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +readline.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +readline.o: $(hdrdir)/ruby/internal/assume.h +readline.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +readline.o: $(hdrdir)/ruby/internal/attr/artificial.h +readline.o: $(hdrdir)/ruby/internal/attr/cold.h +readline.o: $(hdrdir)/ruby/internal/attr/const.h +readline.o: $(hdrdir)/ruby/internal/attr/constexpr.h +readline.o: $(hdrdir)/ruby/internal/attr/deprecated.h +readline.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +readline.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +readline.o: $(hdrdir)/ruby/internal/attr/error.h +readline.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +readline.o: $(hdrdir)/ruby/internal/attr/forceinline.h +readline.o: $(hdrdir)/ruby/internal/attr/format.h +readline.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +readline.o: $(hdrdir)/ruby/internal/attr/noalias.h +readline.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +readline.o: $(hdrdir)/ruby/internal/attr/noexcept.h +readline.o: $(hdrdir)/ruby/internal/attr/noinline.h +readline.o: $(hdrdir)/ruby/internal/attr/nonnull.h +readline.o: $(hdrdir)/ruby/internal/attr/noreturn.h +readline.o: $(hdrdir)/ruby/internal/attr/pure.h +readline.o: $(hdrdir)/ruby/internal/attr/restrict.h +readline.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +readline.o: $(hdrdir)/ruby/internal/attr/warning.h +readline.o: $(hdrdir)/ruby/internal/attr/weakref.h +readline.o: $(hdrdir)/ruby/internal/cast.h +readline.o: $(hdrdir)/ruby/internal/compiler_is.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +readline.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +readline.o: $(hdrdir)/ruby/internal/compiler_since.h +readline.o: $(hdrdir)/ruby/internal/config.h +readline.o: $(hdrdir)/ruby/internal/constant_p.h +readline.o: $(hdrdir)/ruby/internal/core.h +readline.o: $(hdrdir)/ruby/internal/core/rarray.h +readline.o: $(hdrdir)/ruby/internal/core/rbasic.h +readline.o: $(hdrdir)/ruby/internal/core/rbignum.h +readline.o: $(hdrdir)/ruby/internal/core/rclass.h +readline.o: $(hdrdir)/ruby/internal/core/rdata.h +readline.o: $(hdrdir)/ruby/internal/core/rfile.h +readline.o: $(hdrdir)/ruby/internal/core/rhash.h +readline.o: $(hdrdir)/ruby/internal/core/robject.h +readline.o: $(hdrdir)/ruby/internal/core/rregexp.h +readline.o: $(hdrdir)/ruby/internal/core/rstring.h +readline.o: $(hdrdir)/ruby/internal/core/rstruct.h +readline.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +readline.o: $(hdrdir)/ruby/internal/ctype.h +readline.o: $(hdrdir)/ruby/internal/dllexport.h +readline.o: $(hdrdir)/ruby/internal/dosish.h +readline.o: $(hdrdir)/ruby/internal/encoding/coderange.h +readline.o: $(hdrdir)/ruby/internal/encoding/ctype.h +readline.o: $(hdrdir)/ruby/internal/encoding/encoding.h +readline.o: $(hdrdir)/ruby/internal/encoding/pathname.h +readline.o: $(hdrdir)/ruby/internal/encoding/re.h +readline.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +readline.o: $(hdrdir)/ruby/internal/encoding/string.h +readline.o: $(hdrdir)/ruby/internal/encoding/symbol.h +readline.o: $(hdrdir)/ruby/internal/encoding/transcode.h +readline.o: $(hdrdir)/ruby/internal/error.h +readline.o: $(hdrdir)/ruby/internal/eval.h +readline.o: $(hdrdir)/ruby/internal/event.h +readline.o: $(hdrdir)/ruby/internal/fl_type.h +readline.o: $(hdrdir)/ruby/internal/gc.h +readline.o: $(hdrdir)/ruby/internal/glob.h +readline.o: $(hdrdir)/ruby/internal/globals.h +readline.o: $(hdrdir)/ruby/internal/has/attribute.h +readline.o: $(hdrdir)/ruby/internal/has/builtin.h +readline.o: $(hdrdir)/ruby/internal/has/c_attribute.h +readline.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +readline.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +readline.o: $(hdrdir)/ruby/internal/has/extension.h +readline.o: $(hdrdir)/ruby/internal/has/feature.h +readline.o: $(hdrdir)/ruby/internal/has/warning.h +readline.o: $(hdrdir)/ruby/internal/intern/array.h +readline.o: $(hdrdir)/ruby/internal/intern/bignum.h +readline.o: $(hdrdir)/ruby/internal/intern/class.h +readline.o: $(hdrdir)/ruby/internal/intern/compar.h +readline.o: $(hdrdir)/ruby/internal/intern/complex.h +readline.o: $(hdrdir)/ruby/internal/intern/cont.h +readline.o: $(hdrdir)/ruby/internal/intern/dir.h +readline.o: $(hdrdir)/ruby/internal/intern/enum.h +readline.o: $(hdrdir)/ruby/internal/intern/enumerator.h +readline.o: $(hdrdir)/ruby/internal/intern/error.h +readline.o: $(hdrdir)/ruby/internal/intern/eval.h +readline.o: $(hdrdir)/ruby/internal/intern/file.h +readline.o: $(hdrdir)/ruby/internal/intern/gc.h +readline.o: $(hdrdir)/ruby/internal/intern/hash.h +readline.o: $(hdrdir)/ruby/internal/intern/io.h +readline.o: $(hdrdir)/ruby/internal/intern/load.h +readline.o: $(hdrdir)/ruby/internal/intern/marshal.h +readline.o: $(hdrdir)/ruby/internal/intern/numeric.h +readline.o: $(hdrdir)/ruby/internal/intern/object.h +readline.o: $(hdrdir)/ruby/internal/intern/parse.h +readline.o: $(hdrdir)/ruby/internal/intern/proc.h +readline.o: $(hdrdir)/ruby/internal/intern/process.h +readline.o: $(hdrdir)/ruby/internal/intern/random.h +readline.o: $(hdrdir)/ruby/internal/intern/range.h +readline.o: $(hdrdir)/ruby/internal/intern/rational.h +readline.o: $(hdrdir)/ruby/internal/intern/re.h +readline.o: $(hdrdir)/ruby/internal/intern/ruby.h +readline.o: $(hdrdir)/ruby/internal/intern/select.h +readline.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +readline.o: $(hdrdir)/ruby/internal/intern/signal.h +readline.o: $(hdrdir)/ruby/internal/intern/sprintf.h +readline.o: $(hdrdir)/ruby/internal/intern/string.h +readline.o: $(hdrdir)/ruby/internal/intern/struct.h +readline.o: $(hdrdir)/ruby/internal/intern/thread.h +readline.o: $(hdrdir)/ruby/internal/intern/time.h +readline.o: $(hdrdir)/ruby/internal/intern/variable.h +readline.o: $(hdrdir)/ruby/internal/intern/vm.h +readline.o: $(hdrdir)/ruby/internal/interpreter.h +readline.o: $(hdrdir)/ruby/internal/iterator.h +readline.o: $(hdrdir)/ruby/internal/memory.h +readline.o: $(hdrdir)/ruby/internal/method.h +readline.o: $(hdrdir)/ruby/internal/module.h +readline.o: $(hdrdir)/ruby/internal/newobj.h +readline.o: $(hdrdir)/ruby/internal/rgengc.h +readline.o: $(hdrdir)/ruby/internal/scan_args.h +readline.o: $(hdrdir)/ruby/internal/special_consts.h +readline.o: $(hdrdir)/ruby/internal/static_assert.h +readline.o: $(hdrdir)/ruby/internal/stdalign.h +readline.o: $(hdrdir)/ruby/internal/stdbool.h +readline.o: $(hdrdir)/ruby/internal/symbol.h +readline.o: $(hdrdir)/ruby/internal/value.h +readline.o: $(hdrdir)/ruby/internal/value_type.h +readline.o: $(hdrdir)/ruby/internal/variable.h +readline.o: $(hdrdir)/ruby/internal/warning_push.h +readline.o: $(hdrdir)/ruby/internal/xmalloc.h readline.o: $(hdrdir)/ruby/io.h readline.o: $(hdrdir)/ruby/missing.h readline.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/readline/depend-gem b/ruby/ext/readline/depend-gem new file mode 100644 index 000000000..df01bd2a8 --- /dev/null +++ b/ruby/ext/readline/depend-gem @@ -0,0 +1,4 @@ +# AUTOGENERATED DEPENDENCIES START +readline.o: $(RUBY_EXTCONF_H) +readline.o: readline.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/readline/readline-ext.gemspec b/ruby/ext/readline/readline-ext.gemspec index b85e07dd9..177ee2152 100644 --- a/ruby/ext/readline/readline-ext.gemspec +++ b/ruby/ext/readline/readline-ext.gemspec @@ -1,13 +1,13 @@ Gem::Specification.new do |spec| spec.name = "readline-ext" - spec.version = "0.1.0" + spec.version = "0.1.4" spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{Provides an interface for GNU Readline and Edit Line (libedit).} spec.description = %q{Provides an interface for GNU Readline and Edit Line (libedit).} spec.homepage = "https://github.com/ruby/readline-ext" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.extensions = %w[ext/readline/extconf.rb] spec.metadata["homepage_uri"] = spec.homepage diff --git a/ruby/ext/readline/readline.c b/ruby/ext/readline/readline.c index 646be2b19..5ae037dd4 100644 --- a/ruby/ext/readline/readline.c +++ b/ruby/ext/readline/readline.c @@ -78,7 +78,7 @@ static ID id_special_prefixes; #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION # define rl_username_completion_function username_completion_function #else -char *rl_username_completion_function(const char *, int); +RUBY_EXTERN char *rl_username_completion_function(const char *, int); #endif #ifndef HAVE_RL_COMPLETION_MATCHES # define rl_completion_matches completion_matches @@ -689,14 +689,13 @@ readline_s_insert_text(VALUE self, VALUE str) #endif #if defined(HAVE_RL_DELETE_TEXT) -int rl_delete_text(int, int); +RUBY_EXTERN int rl_delete_text(int, int); static const char * str_subpos(const char *ptr, const char *end, long beg, long *sublen, rb_encoding *enc) { VALUE str = rb_enc_str_new_static(ptr, end-ptr, enc); OBJ_FREEZE(str); ptr = rb_str_subpos(str, beg, sublen); - rb_gc_force_recycle(str); return ptr; } @@ -1148,7 +1147,7 @@ readline_s_get_screen_size(VALUE self) #endif #ifdef HAVE_RL_VI_EDITING_MODE -int rl_vi_editing_mode(int, int); +RUBY_EXTERN int rl_vi_editing_mode(int, int); /* * call-seq: * Readline.vi_editing_mode -> nil @@ -1187,7 +1186,7 @@ readline_s_vi_editing_mode_p(VALUE self) #endif #ifdef HAVE_RL_EMACS_EDITING_MODE -int rl_emacs_editing_mode(int, int); +RUBY_EXTERN int rl_emacs_editing_mode(int, int); /* * call-seq: * Readline.emacs_editing_mode -> nil @@ -1672,7 +1671,7 @@ readline_s_get_filename_quote_characters(VALUE self) #endif #ifdef HAVE_RL_REFRESH_LINE -int rl_refresh_line(int, int); +RUBY_EXTERN int rl_refresh_line(int, int); /* * call-seq: * Readline.refresh_line -> nil @@ -1918,8 +1917,11 @@ username_completion_proc_call(VALUE self, VALUE str) return result; } +#ifdef HAVE_RL_CATCH_SIGNALS +RUBY_EXTERN int rl_catch_signals; +#endif #ifdef HAVE_RL_CLEAR_SIGNALS -int rl_clear_signals(void); +RUBY_EXTERN int rl_clear_signals(void); #endif #undef rb_intern @@ -2060,7 +2062,7 @@ Init_readline(void) * The history buffer. It extends Enumerable module, so it behaves * just like an array. * For example, gets the fifth content that the user input by - * HISTORY[4]. + * HISTORY[4]. */ rb_define_const(mReadline, "HISTORY", history); @@ -2088,6 +2090,7 @@ Init_readline(void) #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION, strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) { + prepare_readline(); add_history("1"); if (history_get(history_get_offset_func(0)) == NULL) { history_get_offset_func = history_get_offset_0; diff --git a/ruby/ext/ripper/depend b/ruby/ext/ripper/depend index 69759ec71..9f4b1b53b 100644 --- a/ruby/ext/ripper/depend +++ b/ruby/ext/ripper/depend @@ -22,6 +22,7 @@ ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse. $(Q) $(RUBY) $(top_srcdir)/tool/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ \ --vpath=$(VPATH)$(PATH_SEPARATOR)$(top_srcdir) id.h $(top_srcdir)/parse.y > ripper.tmp.y $(Q) $(RUBY) $(top_srcdir)/tool/pure_parser.rb ripper.tmp.y $(BISON) + $(Q) $(RM) ripper.tmp.y.bak $(Q) $(RUBY) $(srcdir)/tools/preproc.rb ripper.tmp.y --output=$@ $(Q) $(RM) ripper.tmp.y @@ -50,23 +51,208 @@ ripper.E: ripper.c # AUTOGENERATED DEPENDENCIES START ripper.o: $(RUBY_EXTCONF_H) ripper.o: $(arch_hdrdir)/ruby/config.h -ripper.o: $(hdrdir)/ruby.h ripper.o: $(hdrdir)/ruby/assert.h ripper.o: $(hdrdir)/ruby/backward.h +ripper.o: $(hdrdir)/ruby/backward/2/assume.h +ripper.o: $(hdrdir)/ruby/backward/2/attributes.h +ripper.o: $(hdrdir)/ruby/backward/2/bool.h +ripper.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ripper.o: $(hdrdir)/ruby/backward/2/inttypes.h +ripper.o: $(hdrdir)/ruby/backward/2/limits.h +ripper.o: $(hdrdir)/ruby/backward/2/long_long.h +ripper.o: $(hdrdir)/ruby/backward/2/stdalign.h +ripper.o: $(hdrdir)/ruby/backward/2/stdarg.h ripper.o: $(hdrdir)/ruby/defines.h ripper.o: $(hdrdir)/ruby/encoding.h ripper.o: $(hdrdir)/ruby/intern.h +ripper.o: $(hdrdir)/ruby/internal/anyargs.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ripper.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ripper.o: $(hdrdir)/ruby/internal/assume.h +ripper.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ripper.o: $(hdrdir)/ruby/internal/attr/artificial.h +ripper.o: $(hdrdir)/ruby/internal/attr/cold.h +ripper.o: $(hdrdir)/ruby/internal/attr/const.h +ripper.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ripper.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ripper.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ripper.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ripper.o: $(hdrdir)/ruby/internal/attr/error.h +ripper.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ripper.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ripper.o: $(hdrdir)/ruby/internal/attr/format.h +ripper.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ripper.o: $(hdrdir)/ruby/internal/attr/noalias.h +ripper.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ripper.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ripper.o: $(hdrdir)/ruby/internal/attr/noinline.h +ripper.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ripper.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ripper.o: $(hdrdir)/ruby/internal/attr/pure.h +ripper.o: $(hdrdir)/ruby/internal/attr/restrict.h +ripper.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ripper.o: $(hdrdir)/ruby/internal/attr/warning.h +ripper.o: $(hdrdir)/ruby/internal/attr/weakref.h +ripper.o: $(hdrdir)/ruby/internal/cast.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ripper.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ripper.o: $(hdrdir)/ruby/internal/compiler_since.h +ripper.o: $(hdrdir)/ruby/internal/config.h +ripper.o: $(hdrdir)/ruby/internal/constant_p.h +ripper.o: $(hdrdir)/ruby/internal/core.h +ripper.o: $(hdrdir)/ruby/internal/core/rarray.h +ripper.o: $(hdrdir)/ruby/internal/core/rbasic.h +ripper.o: $(hdrdir)/ruby/internal/core/rbignum.h +ripper.o: $(hdrdir)/ruby/internal/core/rclass.h +ripper.o: $(hdrdir)/ruby/internal/core/rdata.h +ripper.o: $(hdrdir)/ruby/internal/core/rfile.h +ripper.o: $(hdrdir)/ruby/internal/core/rhash.h +ripper.o: $(hdrdir)/ruby/internal/core/robject.h +ripper.o: $(hdrdir)/ruby/internal/core/rregexp.h +ripper.o: $(hdrdir)/ruby/internal/core/rstring.h +ripper.o: $(hdrdir)/ruby/internal/core/rstruct.h +ripper.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ripper.o: $(hdrdir)/ruby/internal/ctype.h +ripper.o: $(hdrdir)/ruby/internal/dllexport.h +ripper.o: $(hdrdir)/ruby/internal/dosish.h +ripper.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ripper.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ripper.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ripper.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ripper.o: $(hdrdir)/ruby/internal/encoding/re.h +ripper.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ripper.o: $(hdrdir)/ruby/internal/encoding/string.h +ripper.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ripper.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ripper.o: $(hdrdir)/ruby/internal/error.h +ripper.o: $(hdrdir)/ruby/internal/eval.h +ripper.o: $(hdrdir)/ruby/internal/event.h +ripper.o: $(hdrdir)/ruby/internal/fl_type.h +ripper.o: $(hdrdir)/ruby/internal/gc.h +ripper.o: $(hdrdir)/ruby/internal/glob.h +ripper.o: $(hdrdir)/ruby/internal/globals.h +ripper.o: $(hdrdir)/ruby/internal/has/attribute.h +ripper.o: $(hdrdir)/ruby/internal/has/builtin.h +ripper.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ripper.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ripper.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ripper.o: $(hdrdir)/ruby/internal/has/extension.h +ripper.o: $(hdrdir)/ruby/internal/has/feature.h +ripper.o: $(hdrdir)/ruby/internal/has/warning.h +ripper.o: $(hdrdir)/ruby/internal/intern/array.h +ripper.o: $(hdrdir)/ruby/internal/intern/bignum.h +ripper.o: $(hdrdir)/ruby/internal/intern/class.h +ripper.o: $(hdrdir)/ruby/internal/intern/compar.h +ripper.o: $(hdrdir)/ruby/internal/intern/complex.h +ripper.o: $(hdrdir)/ruby/internal/intern/cont.h +ripper.o: $(hdrdir)/ruby/internal/intern/dir.h +ripper.o: $(hdrdir)/ruby/internal/intern/enum.h +ripper.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ripper.o: $(hdrdir)/ruby/internal/intern/error.h +ripper.o: $(hdrdir)/ruby/internal/intern/eval.h +ripper.o: $(hdrdir)/ruby/internal/intern/file.h +ripper.o: $(hdrdir)/ruby/internal/intern/gc.h +ripper.o: $(hdrdir)/ruby/internal/intern/hash.h +ripper.o: $(hdrdir)/ruby/internal/intern/io.h +ripper.o: $(hdrdir)/ruby/internal/intern/load.h +ripper.o: $(hdrdir)/ruby/internal/intern/marshal.h +ripper.o: $(hdrdir)/ruby/internal/intern/numeric.h +ripper.o: $(hdrdir)/ruby/internal/intern/object.h +ripper.o: $(hdrdir)/ruby/internal/intern/parse.h +ripper.o: $(hdrdir)/ruby/internal/intern/proc.h +ripper.o: $(hdrdir)/ruby/internal/intern/process.h +ripper.o: $(hdrdir)/ruby/internal/intern/random.h +ripper.o: $(hdrdir)/ruby/internal/intern/range.h +ripper.o: $(hdrdir)/ruby/internal/intern/rational.h +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/signal.h +ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ripper.o: $(hdrdir)/ruby/internal/intern/string.h +ripper.o: $(hdrdir)/ruby/internal/intern/struct.h +ripper.o: $(hdrdir)/ruby/internal/intern/thread.h +ripper.o: $(hdrdir)/ruby/internal/intern/time.h +ripper.o: $(hdrdir)/ruby/internal/intern/variable.h +ripper.o: $(hdrdir)/ruby/internal/intern/vm.h +ripper.o: $(hdrdir)/ruby/internal/interpreter.h +ripper.o: $(hdrdir)/ruby/internal/iterator.h +ripper.o: $(hdrdir)/ruby/internal/memory.h +ripper.o: $(hdrdir)/ruby/internal/method.h +ripper.o: $(hdrdir)/ruby/internal/module.h +ripper.o: $(hdrdir)/ruby/internal/newobj.h +ripper.o: $(hdrdir)/ruby/internal/rgengc.h +ripper.o: $(hdrdir)/ruby/internal/scan_args.h +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/symbol.h +ripper.o: $(hdrdir)/ruby/internal/value.h +ripper.o: $(hdrdir)/ruby/internal/value_type.h +ripper.o: $(hdrdir)/ruby/internal/variable.h +ripper.o: $(hdrdir)/ruby/internal/warning_push.h +ripper.o: $(hdrdir)/ruby/internal/xmalloc.h +ripper.o: $(hdrdir)/ruby/io.h ripper.o: $(hdrdir)/ruby/missing.h ripper.o: $(hdrdir)/ruby/onigmo.h ripper.o: $(hdrdir)/ruby/oniguruma.h +ripper.o: $(hdrdir)/ruby/ractor.h ripper.o: $(hdrdir)/ruby/regex.h ripper.o: $(hdrdir)/ruby/ruby.h ripper.o: $(hdrdir)/ruby/st.h ripper.o: $(hdrdir)/ruby/subst.h ripper.o: $(hdrdir)/ruby/util.h +ripper.o: $(top_srcdir)/constant.h +ripper.o: $(top_srcdir)/id_table.h ripper.o: $(top_srcdir)/internal.h +ripper.o: $(top_srcdir)/internal/array.h +ripper.o: $(top_srcdir)/internal/bignum.h +ripper.o: $(top_srcdir)/internal/bits.h +ripper.o: $(top_srcdir)/internal/compile.h +ripper.o: $(top_srcdir)/internal/compilers.h +ripper.o: $(top_srcdir)/internal/complex.h +ripper.o: $(top_srcdir)/internal/error.h +ripper.o: $(top_srcdir)/internal/fixnum.h +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/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/serial.h +ripper.o: $(top_srcdir)/internal/static_assert.h +ripper.o: $(top_srcdir)/internal/string.h +ripper.o: $(top_srcdir)/internal/symbol.h +ripper.o: $(top_srcdir)/internal/thread.h +ripper.o: $(top_srcdir)/internal/variable.h +ripper.o: $(top_srcdir)/internal/vm.h +ripper.o: $(top_srcdir)/internal/warnings.h ripper.o: $(top_srcdir)/node.h ripper.o: $(top_srcdir)/regenc.h +ripper.o: $(top_srcdir)/ruby_assert.h ripper.o: $(top_srcdir)/symbol.h ripper.o: ../../probes.h ripper.o: eventids2.c diff --git a/ruby/ext/ripper/eventids2.c b/ruby/ext/ripper/eventids2.c index cdac2081e..ac38663f2 100644 --- a/ruby/ext/ripper/eventids2.c +++ b/ruby/ext/ripper/eventids2.c @@ -1,12 +1,20 @@ enum { tIGNORED_NL = tLAST_TOKEN + 1, +# define tIGNORED_NL ((enum yytokentype)tIGNORED_NL) tCOMMENT, +# define tCOMMENT ((enum yytokentype)tCOMMENT) tEMBDOC_BEG, +# define tEMBDOC_BEG ((enum yytokentype)tEMBDOC_BEG) tEMBDOC, +# define tEMBDOC ((enum yytokentype)tEMBDOC) tEMBDOC_END, +# define tEMBDOC_END ((enum yytokentype)tEMBDOC_END) tHEREDOC_BEG, +# define tHEREDOC_BEG ((enum yytokentype)tHEREDOC_BEG) tHEREDOC_END, - k__END__ +# define tHEREDOC_END ((enum yytokentype)tHEREDOC_END) + k__END__, +# define k__END__ ((enum yytokentype)k__END__) }; typedef struct { diff --git a/ruby/ext/ripper/extconf.rb b/ruby/ext/ripper/extconf.rb index 2dde565bd..65cb5030d 100644 --- a/ruby/ext/ripper/extconf.rb +++ b/ruby/ext/ripper/extconf.rb @@ -13,7 +13,8 @@ def main end end $objs = %w(ripper.o) - $cleanfiles.concat %w(ripper.y ripper.c ripper.E ripper.output y.output eventids1.c eventids2table.c .eventids2-check) + $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids2table.c) + $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check) $defs << '-DRIPPER' $defs << '-DRIPPER_DEBUG' if $debug $VPATH << '$(topdir)' << '$(top_srcdir)' diff --git a/ruby/ext/ripper/lib/ripper/lexer.rb b/ruby/ext/ripper/lib/ripper/lexer.rb index 9f613c347..19c59e2cc 100644 --- a/ruby/ext/ripper/lib/ripper/lexer.rb +++ b/ruby/ext/ripper/lib/ripper/lexer.rb @@ -14,17 +14,24 @@ class Ripper # Tokenizes the Ruby program and returns an array of strings. + # The +filename+ and +lineno+ arguments are mostly ignored, since the + # return value is just the tokenized input. + # 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+. # # p Ripper.tokenize("def m(a) nil end") # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"] # - def Ripper.tokenize(src, filename = '-', lineno = 1) - Lexer.new(src, filename, lineno).tokenize + def Ripper.tokenize(src, filename = '-', lineno = 1, **kw) + Lexer.new(src, filename, lineno).tokenize(**kw) 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' @@ -41,15 +48,32 @@ def Ripper.tokenize(src, filename = '-', lineno = 1) # [[1, 12], :on_sp, " ", END ], # [[1, 13], :on_kw, "end", END ]] # - def Ripper.lex(src, filename = '-', lineno = 1) - Lexer.new(src, filename, lineno).lex + def Ripper.lex(src, filename = '-', lineno = 1, **kw) + Lexer.new(src, filename, lineno).lex(**kw) end class Lexer < ::Ripper #:nodoc: internal use only - State = Struct.new(:to_int, :to_s) do + class State + attr_reader :to_int, :to_s + + def initialize(i) + @to_int = i + @to_s = Ripper.lex_state_name(i) + freeze + end + + def [](index) + case index + when 0, :to_int + @to_int + when 1, :to_s + @event + else + nil + end + end + alias to_i to_int - def initialize(i) super(i, Ripper.lex_state_name(i)).freeze end - # def inspect; "#<#{self.class}: #{self}>" end alias inspect to_s def pretty_print(q) q.text(to_s) end def ==(i) super or to_int == i end @@ -60,21 +84,46 @@ def anybits?(i) to_int.anybits?(i) end def nobits?(i) to_int.nobits?(i) end end - Elem = Struct.new(:pos, :event, :tok, :state, :message) do + class Elem + attr_accessor :pos, :event, :tok, :state, :message + def initialize(pos, event, tok, state, message = nil) - super(pos, event, tok, State.new(state), message) + @pos = pos + @event = event + @tok = tok + @state = State.new(state) + @message = message + end + + def [](index) + case index + when 0, :pos + @pos + when 1, :event + @event + when 2, :tok + @tok + when 3, :state + @state + when 4, :message + @message + else + nil + end end def inspect "#<#{self.class}: #{event}@#{pos[0]}:#{pos[1]}:#{state}: #{tok.inspect}#{": " if message}#{message}>" end + alias to_s inspect + def pretty_print(q) q.group(2, "#<#{self.class}:", ">") { q.breakable q.text("#{event}@#{pos[0]}:#{pos[1]}") q.breakable - q.text(state) + state.pretty_print(q) q.breakable q.text("token: ") tok.pretty_print(q) @@ -87,25 +136,27 @@ def pretty_print(q) end def to_a - a = super - a.pop unless a.last - a + if @message + [@pos, @event, @tok, @state, @message] + else + [@pos, @event, @tok, @state] + end end end attr_reader :errors - def tokenize - parse().sort_by(&:pos).map(&:tok) + def tokenize(**kw) + parse(**kw).sort_by(&:pos).map(&:tok) end - def lex - parse().sort_by(&:pos).map(&:to_a) + def lex(**kw) + parse(**kw).sort_by(&:pos).map(&:to_a) end # parse the code and returns elements including errors. - def scan - result = (parse() + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]} + def scan(**kw) + result = (parse(**kw) + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]} result.each_with_index do |e, i| if e.event == :on_parse_error and e.tok.empty? and (pre = result[i-1]) and pre.pos[0] == e.pos[0] and (pre.pos[1] + pre.tok.size) == e.pos[1] @@ -118,13 +169,20 @@ def scan result end - def parse + def parse(raise_errors: false) @errors = [] @buf = [] @stack = [] - super + super() + @buf = @stack.pop unless @stack.empty? + if raise_errors and !@errors.empty? + raise SyntaxError, @errors.map(&:message).join(' ;') + end @buf.flatten! - @buf + unless (result = @buf).empty? + result.concat(@buf) until (@buf = []; super(); @buf.flatten!; @buf.empty?) + end + result end private @@ -138,17 +196,19 @@ def parse def on_heredoc_dedent(v, w) ignored_sp = [] heredoc = @buf.last - heredoc.each_with_index do |e, i| - if Elem === e and e.event == :on_tstring_content and e.pos[1].zero? - tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok - if (n = dedent_string(e.tok, w)) > 0 - if e.tok.empty? - e.tok = tok[0, n] - e.event = :on_ignored_sp - next + if Array === heredoc + heredoc.each_with_index do |e, i| + if Elem === e and e.event == :on_tstring_content and e.pos[1].zero? + tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok + if (n = dedent_string(e.tok, w)) > 0 + if e.tok.empty? + e.tok = tok[0, n] + e.event = :on_ignored_sp + next + end + ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)] + e.pos[1] += n end - ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)] - e.pos[1] += n end end end @@ -172,14 +232,23 @@ def on_heredoc_end(tok) end def _push_token(tok) - @buf.push Elem.new([lineno(), column()], __callee__, tok, state()) + e = Elem.new([lineno(), column()], __callee__, tok, state()) + @buf.push(e) + e end - def on_error(mesg) + def on_error1(mesg) @errors.push Elem.new([lineno(), column()], __callee__, token(), state(), mesg) end - alias on_parse_error on_error - alias compile_error on_error + + def on_error2(mesg, elem) + @errors.push Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg) + end + PARSER_EVENTS.grep(/_error\z/) do |e| + arity = PARSER_EVENT_TABLE.fetch(e) + alias_method "on_#{e}", "on_error#{arity}" + end + alias compile_error on_error1 (SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event| alias_method event, :_push_token diff --git a/ruby/ext/ripper/lib/ripper/sexp.rb b/ruby/ext/ripper/lib/ripper/sexp.rb index e71d52cd4..b1d553b1d 100644 --- a/ruby/ext/ripper/lib/ripper/sexp.rb +++ b/ruby/ext/ripper/lib/ripper/sexp.rb @@ -17,6 +17,10 @@ class Ripper # 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' @@ -28,15 +32,25 @@ class Ripper # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]], # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]] # - def Ripper.sexp(src, filename = '-', lineno = 1) + def Ripper.sexp(src, filename = '-', lineno = 1, raise_errors: false) builder = SexpBuilderPP.new(src, filename, lineno) sexp = builder.parse - sexp unless builder.error? + if builder.error? + if raise_errors + raise SyntaxError, builder.error + end + else + sexp + end end # [EXPERIMENTAL] # 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' @@ -54,13 +68,21 @@ def Ripper.sexp(src, filename = '-', lineno = 1) # nil, # nil]]]] # - def Ripper.sexp_raw(src, filename = '-', lineno = 1) + def Ripper.sexp_raw(src, filename = '-', lineno = 1, raise_errors: false) builder = SexpBuilder.new(src, filename, lineno) sexp = builder.parse - sexp unless builder.error? + if builder.error? + if raise_errors + raise SyntaxError, builder.error + end + else + sexp + end end class SexpBuilder < ::Ripper #:nodoc: + attr_reader :error + private def dedent_element(e, width) @@ -107,6 +129,13 @@ def on_#{event}(tok) 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 end class SexpBuilderPP < SexpBuilder #:nodoc: diff --git a/ruby/ext/ripper/ripper.c b/ruby/ext/ripper/ripper.c index d10b1396f..0d6230a5f 100644 --- a/ruby/ext/ripper/ripper.c +++ b/ruby/ext/ripper/ripper.c @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -61,8 +65,8 @@ -/* Copy the first part of user declarations. */ -#line 12 "ripper.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 12 "ripper.y" #if !YYPURE @@ -74,18 +78,37 @@ #define YYLTYPE rb_code_location_t #define YYLTYPE_IS_DECLARED 1 -#include "ruby/ruby.h" -#include "ruby/st.h" -#include "ruby/encoding.h" +#include "ruby/config.h" + +#include +#include +#include + #include "internal.h" +#include "internal/compile.h" +#include "internal/complex.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/parse.h" +#include "internal/rational.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/util.h" +#include "internal/variable.h" #include "node.h" #include "parse.h" -#include "symbol.h" -#include "regenc.h" -#include -#include -#include #include "probes.h" +#include "regenc.h" +#include "ruby/encoding.h" +#include "ruby/regex.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "symbol.h" #ifndef WARN_PAST_SCOPE # define WARN_PAST_SCOPE 0 @@ -350,7 +373,6 @@ struct parser_params { unsigned int do_loop: 1; unsigned int do_chomp: 1; unsigned int do_split: 1; - unsigned int warn_location: 1; NODE *eval_tree_begin; NODE *eval_tree; @@ -1019,13 +1041,26 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in (void)0) static int looking_at_eol_p(struct parser_params *p); -#line 1023 "ripper.c" /* yacc.c:339 */ +#line 1045 "ripper.c" +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -1178,10 +1213,9 @@ extern int yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 978 "ripper.y" /* yacc.c:355 */ +#line 996 "ripper.y" VALUE val; NODE *node; @@ -1191,9 +1225,9 @@ union YYSTYPE const struct vtable *vars; struct rb_strterm_struct *strterm; -#line 1193 "ripper.c" /* yacc.c:355 */ -}; +#line 1227 "ripper.c" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 @@ -1219,36 +1253,81 @@ int yyparse (struct parser_params *p); -/* Copy the second part of user declarations. */ -#line 1223 "ripper.c" /* yacc.c:358 */ #ifdef short # undef short #endif -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif #endif -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; #else typedef signed char yytype_int8; #endif -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; #else -typedef unsigned short int yytype_uint16; +typedef short yytype_uint8; #endif -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; #else -typedef short int yytype_int16; +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif #endif #ifndef YYSIZE_T @@ -1256,15 +1335,27 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS @@ -1278,30 +1369,19 @@ typedef short int yytype_int16; # endif #endif -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) # else -# define YY_ATTRIBUTE(Spec) /* empty */ +# define YY_ATTRIBUTE_PURE # endif #endif -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - #ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) # else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# define YY_ATTRIBUTE_UNUSED # endif #endif @@ -1312,13 +1392,13 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value @@ -1331,6 +1411,20 @@ typedef short int yytype_int16; # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) #if ! defined yyoverflow || YYERROR_VERBOSE @@ -1408,18 +1502,19 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; + yy_state_t yyss_alloc; YYSTYPE yyvs_alloc; YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ + + YYSIZEOF (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 @@ -1432,11 +1527,11 @@ union yyalloc # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ - YYSIZE_T yynewbytes; \ + YYPTRDIFF_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ } \ while (0) @@ -1448,12 +1543,12 @@ union yyalloc # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ - YYSIZE_T yyi; \ + YYPTRDIFF_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ @@ -1465,27 +1560,28 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 13766 +#define YYLAST 13832 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 154 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 266 +#define YYNNTS 265 /* YYNRULES -- Number of rules. */ -#define YYNRULES 759 +#define YYNRULES 757 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 1243 +#define YYNSTATES 1241 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 353 + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 71, @@ -1528,84 +1624,84 @@ static const yytype_uint8 yytranslate[] = #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 1176, 1176, 1176, 1202, 1208, 1215, 1222, 1229, 1235, - 1236, 1242, 1255, 1253, 1264, 1275, 1281, 1288, 1295, 1302, - 1308, 1313, 1312, 1322, 1322, 1329, 1336, 1346, 1354, 1361, - 1369, 1377, 1389, 1401, 1411, 1425, 1426, 1434, 1442, 1451, - 1458, 1461, 1468, 1475, 1483, 1490, 1497, 1505, 1512, 1522, - 1527, 1536, 1539, 1540, 1544, 1548, 1552, 1557, 1564, 1566, - 1556, 1574, 1577, 1584, 1584, 1584, 1590, 1591, 1594, 1595, - 1604, 1614, 1624, 1633, 1644, 1651, 1658, 1665, 1672, 1680, - 1688, 1695, 1702, 1711, 1712, 1721, 1722, 1731, 1738, 1745, - 1752, 1759, 1766, 1773, 1780, 1787, 1794, 1803, 1804, 1813, - 1820, 1829, 1836, 1845, 1852, 1859, 1866, 1876, 1883, 1893, - 1900, 1907, 1917, 1924, 1931, 1938, 1945, 1952, 1959, 1966, - 1973, 1983, 1990, 1993, 2000, 2007, 2016, 2017, 2018, 2019, - 2024, 2031, 2038, 2041, 2048, 2048, 2058, 2059, 2060, 2061, - 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, - 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, - 2082, 2083, 2084, 2085, 2086, 2087, 2090, 2090, 2090, 2091, - 2091, 2092, 2092, 2092, 2093, 2093, 2093, 2093, 2094, 2094, - 2094, 2094, 2095, 2095, 2095, 2096, 2096, 2096, 2096, 2097, - 2097, 2097, 2097, 2098, 2098, 2098, 2098, 2099, 2099, 2099, - 2099, 2100, 2100, 2100, 2100, 2101, 2101, 2104, 2111, 2118, - 2126, 2134, 2142, 2150, 2158, 2165, 2173, 2182, 2191, 2203, - 2215, 2227, 2239, 2243, 2247, 2251, 2255, 2259, 2263, 2267, - 2271, 2275, 2279, 2283, 2287, 2291, 2292, 2296, 2300, 2304, - 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2336, 2341, - 2350, 2356, 2357, 2358, 2359, 2362, 2366, 2373, 2380, 2381, - 2385, 2392, 2401, 2406, 2417, 2424, 2453, 2454, 2457, 2458, - 2459, 2463, 2470, 2479, 2487, 2494, 2502, 2510, 2514, 2514, - 2551, 2560, 2564, 2570, 2577, 2584, 2591, 2600, 2601, 2604, - 2611, 2618, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, - 2635, 2636, 2637, 2645, 2644, 2659, 2659, 2666, 2666, 2674, - 2682, 2689, 2696, 2703, 2711, 2718, 2725, 2732, 2739, 2739, - 2744, 2748, 2752, 2759, 2760, 2769, 2768, 2779, 2790, 2801, - 2811, 2822, 2821, 2838, 2837, 2852, 2861, 2909, 2908, 2932, - 2931, 2954, 2953, 2977, 2983, 2976, 3003, 3004, 3003, 3029, - 3036, 3043, 3050, 3059, 3066, 3072, 3089, 3095, 3101, 3107, - 3113, 3119, 3125, 3131, 3137, 3143, 3149, 3155, 3161, 3167, - 3182, 3189, 3195, 3202, 3203, 3204, 3207, 3208, 3211, 3212, - 3224, 3225, 3234, 3235, 3238, 3246, 3255, 3262, 3271, 3278, - 3285, 3292, 3299, 3308, 3316, 3325, 3329, 3333, 3337, 3341, - 3347, 3352, 3357, 3361, 3365, 3369, 3373, 3377, 3385, 3389, - 3393, 3397, 3401, 3405, 3409, 3413, 3417, 3423, 3424, 3430, - 3439, 3451, 3455, 3464, 3466, 3470, 3475, 3481, 3484, 3488, - 3492, 3496, 3481, 3520, 3528, 3538, 3543, 3549, 3559, 3573, - 3580, 3587, 3596, 3605, 3613, 3621, 3628, 3636, 3644, 3651, - 3658, 3671, 3679, 3689, 3690, 3694, 3689, 3711, 3712, 3716, - 3711, 3735, 3743, 3750, 3758, 3767, 3779, 3780, 3784, 3790, - 3791, 3793, 3794, 3795, 3783, 3808, 3809, 3812, 3813, 3821, - 3831, 3832, 3837, 3845, 3849, 3855, 3858, 3867, 3870, 3877, - 3880, 3881, 3883, 3884, 3893, 3902, 3907, 3916, 3925, 3930, - 3930, 3935, 3941, 3940, 3952, 3957, 3957, 3964, 3973, 3977, - 3986, 3990, 3994, 3998, 4002, 4005, 4009, 4018, 4022, 4026, - 4030, 4036, 4037, 4046, 4055, 4059, 4063, 4067, 4071, 4075, - 4081, 4083, 4092, 4100, 4114, 4115, 4138, 4142, 4148, 4154, - 4155, 4164, 4173, 4185, 4197, 4198, 4199, 4200, 4212, 4226, - 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4242, 4241, - 4254, 4264, 4277, 4284, 4291, 4300, 4312, 4315, 4322, 4329, - 4332, 4336, 4339, 4346, 4349, 4350, 4353, 4370, 4371, 4372, - 4381, 4391, 4400, 4406, 4416, 4422, 4431, 4433, 4442, 4452, - 4458, 4467, 4476, 4486, 4492, 4502, 4508, 4518, 4528, 4547, - 4553, 4563, 4573, 4614, 4617, 4616, 4633, 4637, 4642, 4646, - 4650, 4632, 4671, 4678, 4685, 4692, 4695, 4696, 4699, 4709, - 4710, 4711, 4712, 4715, 4725, 4726, 4736, 4737, 4738, 4739, - 4742, 4743, 4744, 4745, 4746, 4749, 4750, 4751, 4752, 4753, - 4754, 4755, 4758, 4771, 4780, 4787, 4796, 4797, 4801, 4800, - 4810, 4818, 4827, 4842, 4842, 4856, 4860, 4864, 4868, 4872, - 4878, 4883, 4888, 4892, 4896, 4900, 4904, 4908, 4912, 4916, - 4920, 4924, 4928, 4932, 4936, 4940, 4945, 4951, 4960, 4968, - 4976, 4984, 4994, 4995, 5003, 5012, 5020, 5041, 5043, 5056, - 5066, 5074, 5084, 5091, 5100, 5107, 5117, 5124, 5133, 5134, - 5137, 5145, 5153, 5163, 5173, 5183, 5190, 5199, 5206, 5215, - 5216, 5219, 5227, 5237, 5238, 5241, 5251, 5255, 5261, 5266, - 5266, 5290, 5291, 5300, 5302, 5325, 5336, 5343, 5351, 5370, - 5371, 5372, 5375, 5376, 5377, 5378, 5381, 5382, 5383, 5386, - 5387, 5390, 5391, 5394, 5395, 5398, 5399, 5402, 5403, 5406, - 5409, 5412, 5415, 5416, 5417, 5420, 5421, 5424, 5425, 5429 +static const yytype_int16 yyrline[] = +{ + 0, 1194, 1194, 1194, 1220, 1226, 1233, 1240, 1247, 1253, + 1254, 1260, 1273, 1271, 1282, 1293, 1299, 1306, 1313, 1320, + 1326, 1331, 1330, 1340, 1340, 1347, 1354, 1364, 1372, 1379, + 1387, 1395, 1407, 1419, 1429, 1443, 1444, 1452, 1460, 1469, + 1476, 1479, 1487, 1495, 1504, 1512, 1520, 1528, 1536, 1546, + 1551, 1560, 1563, 1564, 1568, 1572, 1576, 1581, 1588, 1590, + 1580, 1598, 1601, 1608, 1608, 1608, 1614, 1615, 1618, 1619, + 1628, 1638, 1648, 1657, 1668, 1675, 1682, 1689, 1696, 1704, + 1712, 1719, 1726, 1735, 1736, 1745, 1746, 1755, 1762, 1769, + 1776, 1783, 1790, 1797, 1804, 1811, 1818, 1827, 1828, 1837, + 1844, 1853, 1860, 1869, 1876, 1883, 1890, 1900, 1907, 1917, + 1924, 1931, 1941, 1948, 1955, 1962, 1969, 1976, 1983, 1990, + 1997, 2007, 2014, 2017, 2024, 2031, 2040, 2041, 2042, 2043, + 2048, 2055, 2062, 2065, 2072, 2072, 2082, 2083, 2084, 2085, + 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, + 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, + 2106, 2107, 2108, 2109, 2110, 2111, 2114, 2114, 2114, 2115, + 2115, 2116, 2116, 2116, 2117, 2117, 2117, 2117, 2118, 2118, + 2118, 2118, 2119, 2119, 2119, 2120, 2120, 2120, 2120, 2121, + 2121, 2121, 2121, 2122, 2122, 2122, 2122, 2123, 2123, 2123, + 2123, 2124, 2124, 2124, 2124, 2125, 2125, 2128, 2135, 2142, + 2150, 2158, 2166, 2174, 2182, 2189, 2197, 2206, 2215, 2227, + 2239, 2251, 2263, 2267, 2271, 2275, 2279, 2283, 2287, 2291, + 2295, 2299, 2303, 2307, 2311, 2315, 2316, 2320, 2324, 2328, + 2332, 2336, 2340, 2344, 2348, 2352, 2356, 2360, 2360, 2365, + 2374, 2380, 2381, 2382, 2383, 2386, 2390, 2397, 2404, 2405, + 2409, 2416, 2425, 2430, 2441, 2448, 2477, 2478, 2481, 2482, + 2483, 2487, 2494, 2503, 2511, 2518, 2526, 2534, 2538, 2538, + 2575, 2584, 2588, 2594, 2601, 2608, 2615, 2624, 2625, 2628, + 2635, 2642, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, + 2659, 2660, 2661, 2669, 2668, 2683, 2683, 2690, 2690, 2698, + 2706, 2713, 2720, 2727, 2735, 2742, 2749, 2756, 2763, 2763, + 2768, 2772, 2776, 2783, 2784, 2793, 2792, 2803, 2814, 2825, + 2835, 2846, 2845, 2862, 2861, 2876, 2885, 2933, 2932, 2956, + 2955, 2978, 2977, 3001, 3007, 3000, 3027, 3028, 3027, 3053, + 3060, 3067, 3074, 3083, 3090, 3096, 3113, 3119, 3125, 3131, + 3137, 3143, 3149, 3155, 3161, 3167, 3173, 3179, 3185, 3191, + 3206, 3213, 3219, 3226, 3227, 3228, 3231, 3232, 3235, 3236, + 3248, 3249, 3258, 3259, 3262, 3270, 3279, 3286, 3295, 3302, + 3309, 3316, 3323, 3332, 3340, 3349, 3353, 3357, 3361, 3365, + 3371, 3376, 3381, 3385, 3389, 3393, 3397, 3401, 3409, 3413, + 3417, 3421, 3425, 3429, 3433, 3437, 3441, 3447, 3448, 3454, + 3463, 3475, 3479, 3488, 3490, 3494, 3499, 3505, 3508, 3512, + 3516, 3520, 3505, 3544, 3552, 3562, 3567, 3573, 3583, 3597, + 3604, 3611, 3620, 3629, 3637, 3645, 3652, 3660, 3668, 3675, + 3682, 3695, 3703, 3713, 3714, 3718, 3713, 3735, 3736, 3740, + 3735, 3759, 3767, 3774, 3782, 3791, 3803, 3804, 3808, 3814, + 3815, 3817, 3818, 3819, 3807, 3832, 3833, 3836, 3837, 3845, + 3855, 3856, 3861, 3869, 3873, 3879, 3882, 3891, 3894, 3901, + 3904, 3905, 3907, 3908, 3917, 3926, 3931, 3940, 3949, 3954, + 3954, 3959, 3964, 3964, 3969, 3974, 3974, 3981, 3990, 3994, + 4003, 4007, 4011, 4015, 4019, 4022, 4026, 4035, 4039, 4043, + 4047, 4053, 4054, 4063, 4072, 4076, 4080, 4084, 4088, 4094, + 4096, 4105, 4113, 4127, 4128, 4151, 4155, 4161, 4167, 4168, + 4177, 4186, 4198, 4210, 4211, 4212, 4213, 4225, 4239, 4240, + 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4255, 4254, 4267, + 4277, 4290, 4297, 4304, 4313, 4325, 4328, 4335, 4342, 4345, + 4349, 4352, 4359, 4362, 4363, 4366, 4383, 4384, 4385, 4394, + 4404, 4413, 4419, 4429, 4435, 4444, 4446, 4455, 4465, 4471, + 4480, 4489, 4499, 4505, 4515, 4521, 4531, 4541, 4560, 4566, + 4576, 4586, 4627, 4630, 4629, 4646, 4650, 4655, 4659, 4663, + 4645, 4684, 4691, 4698, 4705, 4708, 4709, 4712, 4722, 4723, + 4724, 4725, 4728, 4738, 4739, 4749, 4750, 4751, 4752, 4755, + 4756, 4757, 4758, 4759, 4762, 4763, 4764, 4765, 4766, 4767, + 4768, 4771, 4784, 4793, 4800, 4809, 4810, 4814, 4813, 4823, + 4831, 4840, 4855, 4855, 4869, 4873, 4877, 4881, 4885, 4891, + 4896, 4901, 4905, 4909, 4913, 4917, 4921, 4925, 4929, 4933, + 4937, 4941, 4945, 4949, 4953, 4958, 4964, 4973, 4981, 4989, + 4997, 5007, 5008, 5016, 5025, 5033, 5054, 5056, 5069, 5079, + 5087, 5097, 5104, 5113, 5120, 5130, 5137, 5146, 5147, 5150, + 5158, 5166, 5176, 5186, 5196, 5203, 5212, 5219, 5228, 5229, + 5232, 5240, 5250, 5251, 5254, 5264, 5268, 5274, 5279, 5279, + 5303, 5304, 5313, 5315, 5338, 5349, 5356, 5364, 5383, 5384, + 5385, 5388, 5389, 5390, 5391, 5394, 5395, 5396, 5399, 5400, + 5403, 5404, 5407, 5408, 5411, 5412, 5415, 5416, 5419, 5422, + 5425, 5426, 5427, 5430, 5431, 5434, 5435, 5439 }; #endif @@ -1692,14 +1788,14 @@ static const char *const yytname[] = "blkarg_mark", "f_block_arg", "opt_f_block_arg", "singleton", "$@56", "assoc_list", "assocs", "assoc", "operation", "operation2", "operation3", "dot_or_colon", "call_op", "call_op2", "opt_terms", "opt_nl", "rparen", - "rbracket", "rbrace", "trailer", "term", "terms", "none", YY_NULLPTR + "rbracket", "trailer", "term", "terms", "none", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = +static const yytype_int16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -1720,164 +1816,164 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -1028 +#define YYPACT_NINF (-1056) -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-1028))) +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) -#define YYTABLE_NINF -760 +#define YYTABLE_NINF (-758) -#define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-760))) +#define yytable_value_is_error(Yyn) \ + ((Yyn) == YYTABLE_NINF) /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { - -1028, 133, 3772, -1028, 9176, -1028, -1028, -1028, 8634, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, 9302, 9302, -1028, -1028, - -1028, 5241, 4800, -1028, -1028, -1028, -1028, 533, 8489, 1, - 100, 124, -1028, -1028, -1028, 4065, 4947, -1028, -1028, 4212, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 10940, 10940, - 10940, 10940, 200, 6689, 9428, 9806, 10184, 8918, -1028, 8344, - -1028, -1028, -1028, 155, 181, 247, 265, 1275, 11066, 10940, - -1028, 232, -1028, 1140, -1028, 319, -1028, -1028, 14, 411, - 330, -1028, 332, 11318, -1028, 380, 2654, 644, 46, 425, - -1028, 11192, 11192, -1028, -1028, 7671, 11440, 11562, 11684, 8198, - 9302, 819, 108, -1028, -1028, 456, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 717, 729, - -1028, 420, 783, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, 432, -1028, -1028, -1028, 479, 10940, 524, 6840, - 10940, 10940, 10940, -1028, 10940, -1028, 503, 4337, 542, -1028, - -1028, 513, 515, 267, 365, 614, 366, 545, -1028, -1028, - 7545, -1028, 9302, 9554, -1028, -1028, 7797, -1028, 11192, 858, - -1028, 574, 6991, -1028, 7142, -1028, -1028, 598, 605, 14, - -1028, 522, -1028, 718, 3380, 3380, 791, 9428, -1028, 6689, - 657, 232, -1028, 1140, 1, 682, -1028, 1140, 1, 665, - 371, 519, -1028, 542, 673, 519, -1028, 1, 763, 1275, - 11806, 677, -1028, 690, 708, 716, 724, -1028, -1028, -1028, - -1028, -1028, 481, -1028, 580, 678, 953, -1028, -1028, -1028, - -1028, 748, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 7923, - 11192, 11192, 11192, 11192, 9428, 11192, 11192, -1028, -1028, -1028, - 721, -1028, -1028, -1028, -1028, -1028, 10310, -1028, 6689, 9047, - 684, 10310, -1028, 10940, 10940, 10940, 10940, 10940, -1028, -1028, - 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, -1028, - -1028, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, - 10940, -1028, -1028, 12269, 9302, 12359, 5833, 319, 86, 86, - 7293, 11192, 7293, 232, -1028, 691, 777, -1028, -1028, 741, - 822, 53, 68, 69, 681, 956, 11192, 733, -1028, 714, - 891, -1028, -1028, -1028, -1028, 130, 291, 527, 572, 582, - 586, 608, 653, 663, -1028, -1028, -1028, 666, -1028, -1028, - -1028, 13619, -1028, -1028, 11066, 11066, -1028, -1028, 374, -1028, - -1028, -1028, 618, 10940, 10940, 9680, -1028, -1028, 12449, 9302, - 12539, 10940, 10940, 9932, -1028, 1, 710, -1028, -1028, 10940, - 1, -1028, 711, 1, 722, -1028, 107, -1028, -1028, -1028, - -1028, -1028, 8634, -1028, 10940, 726, 728, 12449, 12539, 10940, - 1140, 100, 1, -1028, -1028, 8049, 732, 1, -1028, -1028, - 10058, -1028, -1028, 10184, -1028, -1028, -1028, 574, 893, -1028, - -1028, 734, 11806, 12629, 9302, 12719, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 786, 101, - 988, 102, 10940, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, 757, -1028, -1028, -1028, 882, -1028, 882, 10940, - -1028, 760, 767, 874, -1028, 1, 11806, 774, -1028, -1028, - -1028, 880, 806, 4043, -1028, -1028, -1028, 963, 400, -1028, - 718, 3896, 3896, 3896, 3896, 4484, 3134, 3896, 3896, 3380, - 3380, 759, 759, 3267, 1222, 1222, 1464, 406, 406, 718, - 718, 718, 1115, 1115, 3482, 4359, 5535, 4506, -1028, 605, - -1028, 1, 850, -1028, 1016, -1028, -1028, 5094, 882, 925, - -1028, 5984, 922, 6437, 882, 60, 882, 914, 927, 76, - 12809, 9302, 12899, -1028, 319, -1028, 893, -1028, -1028, -1028, - 12989, 9302, 13079, 5833, 11192, -1028, -1028, -1028, -1028, -1028, - -1028, 2683, -1028, 4190, -1028, -1028, -1028, 8634, 10940, -1028, - 10940, 542, -1028, 545, 3918, 4653, 1, 453, 458, -1028, - -1028, -1028, -1028, 9680, -1028, 9932, -1028, -1028, 11192, 4337, - -1028, -1028, 605, 605, -1028, -1028, -9, -1028, -1028, 519, - 11806, 734, 381, 686, 1, 362, 407, -1028, -1028, 1249, - -1028, 566, -1028, 794, -1028, -1028, 568, 795, -1028, 718, - -1028, -1028, 804, -1028, -1028, -1028, -1028, 812, 10436, 9428, - -1028, 734, 11806, 9428, 11066, 10940, 13169, 9302, 13259, 12202, - 832, 11066, 11066, -1028, 721, 816, 1020, 11066, 11066, -1028, - -1028, 721, -1028, -1028, -1028, 10562, 755, -1028, 825, -1028, - 950, -1028, -1028, -1028, -1028, -1028, -1028, 927, 882, -1028, - 10688, 882, 33, 278, 1, 77, 83, 7293, 232, 11192, - 5833, 995, 686, -1028, 1, 882, 107, 820, 8779, 108, - 411, -1028, -1028, -1028, -1028, 10940, 10940, 462, 10940, 10940, - 824, 107, -1028, -1028, 626, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, 843, -1028, 843, - 10940, 833, -1028, 734, -1028, 4337, 5388, 5682, 1, 466, - 470, -1028, -1028, 3091, 3091, 751, -1028, 616, 345, -1028, - 940, 899, -1028, 871, -1028, -1028, 815, -1028, -1028, 336, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 10940, - -1028, -1028, -1028, -1028, -1028, -1028, 11066, -1028, -1028, -1028, - -1028, -1028, 760, -1028, 904, -1028, -1028, -1028, 7293, -1028, - -1028, -1028, -1028, 7293, 11192, 882, -1028, -1028, 882, -1028, - -1028, 882, -1028, 10940, -1028, 54, -1028, 113, 882, 5833, - 232, 882, -1028, -1028, -1028, 1877, 5833, 1686, -1028, -1028, - -1028, 10940, 9932, -1028, 1519, -1028, 1385, 7142, -1028, -1028, - 5833, 862, 538, -1028, -1028, -1028, -1028, 12202, 12083, -1028, - 257, 866, -1028, -1028, -1028, 964, -1028, 12202, 3091, 3091, - 751, 616, 547, 3621, 3621, 4337, -1028, -1028, 11928, 86, - -1028, -1028, 6563, -1028, 86, -1028, -1028, -1028, -1028, -1028, - 10814, 6135, -1028, 882, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, 1537, -1028, -1028, -1028, -1028, -1028, - -1028, 1, 1, -1028, -1028, 896, -1028, 877, 10940, -1028, - 883, 106, 887, 887, -1028, 894, 980, 895, 987, -1028, - 882, 232, 820, 1686, -1028, -1028, -1028, -1028, 1, 912, - 920, 901, 12050, -1028, 911, 887, 887, -1028, 916, 918, - -1028, 929, -1028, -1028, 276, 27, 3, 1, 12169, -1028, - 919, -1028, -1028, 1, 932, -1028, 12202, -1028, -1028, 348, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - 1, 1, 1, 1, 994, -1028, 1025, 118, 135, 179, - 5833, 1078, 5984, 3621, 10940, -1028, 92, -1028, 1537, 1208, - -1028, 949, 1, 954, -1028, -1028, -1028, 10940, 1686, -1028, - -1028, 1060, -1028, -1028, -1028, -1028, 216, -1028, -1028, 1686, - -1028, -1028, 1096, -1028, -1028, -1028, -1028, 5833, 1, 63, - 7419, 972, -1028, 12050, 1686, -1028, 1049, 1030, 1060, -1028, - -1028, -1028, 1686, -1028, 1096, -1028, 1424, -1028, 978, 12202, - -1028, 43, 899, 982, -1028, 288, -1028, 257, 899, -1028, - -1028, 1079, -1028, -1028, -1028, -1028, 222, 13349, 9302, 13439, - 925, -1028, 825, 86, 886, 255, -1028, -1028, -1028, -1028, - -1028, -1028, 1, -1028, 1537, -1028, 1560, -1028, -1028, -1028, - 983, 986, -1028, 1082, 887, -1028, 989, -1028, 990, -1028, - 989, 882, 992, 5833, 7142, -1028, 1019, -1028, 1030, -1028, - 998, 1001, -1028, 13529, -1028, 887, 1003, -1028, 1011, 1003, - -1028, 592, -1028, -1028, 12202, 1012, -1028, 1015, 12202, -1028, - -1028, -1028, -1028, -1028, 134, 158, 1, 315, 318, -1028, - -1028, -1028, 11192, 11192, 12083, -1028, -1028, 1017, 1021, 1686, - -1028, 1096, -1028, -1028, 1096, -1028, 1096, -1028, -1028, -1028, - -1028, 882, 1027, -1028, 1686, -1028, 1096, -1028, 1024, 1029, - -1028, 1096, -1028, 1096, -1028, -1028, 1424, -1028, 1012, 12202, - 12202, 1012, 457, -1028, -1028, -1028, -1028, 1560, 1560, 989, - 1041, 989, 989, -1028, -1028, 1003, 1043, 1003, 1003, -1028, - -1028, 1012, -1028, 1021, -1028, 1096, -1028, -1028, -1028, -1028, - 1096, -1028, -1028, -1028, 6286, 989, 1003, 150, -1028, -1028, - -1028, -1028, -1028 + -1056, 97, 3943, -1056, 9202, -1056, -1056, -1056, 8660, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, 9328, 9328, -1056, -1056, + -1056, 5267, 4826, -1056, -1056, -1056, -1056, -41, 8515, 18, + -33, 124, -1056, -1056, -1056, 3778, 4973, -1056, -1056, 4238, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 10966, 10966, + 10966, 10966, 90, 6715, 9454, 9832, 10210, 8944, -1056, 8370, + -1056, -1056, -1056, 72, 143, 146, 197, 1315, 11092, 10966, + -1056, 6, -1056, 1265, -1056, 411, -1056, -1056, 249, 152, + 253, -1056, 239, 11344, -1056, 279, 1752, 377, 542, 624, + -1056, 11218, 11218, -1056, -1056, 7697, 11466, 11588, 11710, 8224, + 9328, 48, 21, -1056, -1056, 281, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 394, 461, + -1056, 355, 498, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, 343, -1056, -1056, -1056, 346, 10966, 453, 6866, + 10966, 10966, 10966, -1056, 10966, -1056, 399, 4510, 448, -1056, + -1056, 357, 723, 9, 300, 438, 547, 423, -1056, -1056, + 7571, -1056, 9328, 9580, -1056, -1056, 7823, -1056, 11218, 336, + -1056, 430, 7017, -1056, 7168, -1056, -1056, 464, 483, 249, + -1056, 740, -1056, 565, 3504, 3504, 581, 9454, -1056, 6715, + 549, 6, -1056, 1265, 18, 586, -1056, 1265, 18, 568, + 588, 640, -1056, 448, 578, 640, -1056, 18, 690, 1315, + 11832, 617, -1056, 790, 858, 885, 923, -1056, -1056, -1056, + -1056, -1056, 362, -1056, 446, 562, 683, -1056, -1056, -1056, + -1056, 694, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 7949, + 11218, 11218, 11218, 11218, 9454, 11218, 11218, -1056, -1056, -1056, + 668, -1056, -1056, -1056, -1056, -1056, 10336, -1056, 6715, 9073, + 663, 10336, -1056, 10966, 10966, 10966, 10966, 10966, -1056, -1056, + 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, -1056, + -1056, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, + 10966, -1056, -1056, 12335, 9328, 12425, 5859, 411, 108, 108, + 7319, 11218, 7319, 6, -1056, 674, 758, -1056, -1056, 936, + 819, 53, 77, 126, 732, 827, 11218, 274, -1056, 727, + 940, -1056, -1056, -1056, -1056, 403, 437, 475, 517, 533, + 540, 543, 554, 558, -1056, -1056, -1056, 566, -1056, -1056, + -1056, 13685, -1056, -1056, 11092, 11092, -1056, -1056, 629, -1056, + -1056, -1056, 407, 10966, 10966, 9706, -1056, -1056, 12515, 9328, + 12605, 10966, 10966, 9958, -1056, 18, 718, -1056, -1056, 10966, + 18, -1056, 750, 18, 752, -1056, 96, -1056, -1056, -1056, + -1056, -1056, 8660, -1056, 10966, 729, 757, 12515, 12605, 10966, + 1265, -33, 18, -1056, -1056, 8075, 754, 18, -1056, -1056, + 10084, -1056, -1056, 10210, -1056, -1056, -1056, 430, 963, -1056, + -1056, 771, 11832, 12695, 9328, 12785, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 824, 101, + 992, 141, 10966, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, 759, -1056, -1056, -1056, 866, -1056, 866, 10966, + -1056, 773, 779, 860, -1056, 18, 11832, 781, -1056, -1056, + -1056, 884, 806, 4216, -1056, -1056, -1056, 1006, 644, -1056, + 565, 2696, 2696, 2696, 2696, 4071, 2908, 2696, 2696, 3504, + 3504, 814, 814, 3389, 1310, 1310, 1335, 24, 24, 565, + 565, 565, 1921, 1921, 3606, 4385, 5561, 4532, -1056, 483, + -1056, 18, 832, -1056, 870, -1056, -1056, 5120, 866, 922, + -1056, 6010, 921, 6463, 866, 37, 866, 935, 947, 153, + 12875, 9328, 12965, -1056, 411, -1056, 963, -1056, -1056, -1056, + 13055, 9328, 13145, 5859, 11218, -1056, -1056, -1056, -1056, -1056, + -1056, 3199, -1056, 4363, -1056, -1056, -1056, 8660, 10966, -1056, + 10966, 448, -1056, 423, 4091, 4679, 18, 655, 707, -1056, + -1056, -1056, -1056, 9706, -1056, 9958, -1056, -1056, 11218, 4510, + -1056, -1056, 483, 483, -1056, -1056, -6, -1056, -1056, 640, + 11832, 771, 57, 749, 18, 447, 519, -1056, -1056, 1173, + -1056, 538, -1056, 831, -1056, -1056, 553, 843, -1056, 565, + -1056, -1056, 822, -1056, -1056, -1056, -1056, 830, 10462, 9454, + -1056, 771, 11832, 9454, 11092, 10966, 13235, 9328, 13325, 12268, + 856, 11092, 11092, -1056, 668, 848, 875, 11092, 11092, -1056, + -1056, 668, -1056, -1056, -1056, 10588, 167, -1056, 817, -1056, + 991, -1056, -1056, -1056, -1056, -1056, -1056, 947, 866, -1056, + 10714, 866, 81, 177, 18, 288, 307, 7319, 6, 11218, + 5859, 1030, 749, -1056, 18, 866, 96, 862, 8805, 21, + 152, -1056, -1056, -1056, -1056, 10966, 10966, 714, 10966, 10966, + 868, 96, -1056, -1056, 607, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, 887, -1056, 887, + 10966, 876, -1056, 771, -1056, 4510, 5414, 5708, 18, 744, + 748, -1056, -1056, 2641, 2641, 534, -1056, 400, 881, -1056, + 975, 934, -1056, 904, -1056, -1056, 804, -1056, -1056, 267, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 10966, + -1056, -1056, -1056, -1056, -1056, -1056, 11092, -1056, -1056, -1056, + -1056, -1056, 773, -1056, 938, -1056, -1056, -1056, 7319, -1056, + -1056, -1056, -1056, 7319, 11218, 866, -1056, -1056, 866, -1056, + -1056, 866, -1056, 10966, -1056, 63, -1056, 330, 866, 5859, + 6, 866, -1056, -1056, -1056, 1233, 5859, 1709, -1056, -1056, + -1056, 10966, 9958, -1056, 1648, -1056, 1383, 7168, -1056, -1056, + 5859, 895, 756, -1056, -1056, -1056, -1056, 12268, 2069, -1056, + -1056, 687, -1056, -1056, 1000, -1056, 12268, 2641, 2641, 534, + 400, 501, 12149, 12149, 4510, -1056, -1056, 11954, 108, -1056, + -1056, 6589, -1056, 108, -1056, -1056, -1056, -1056, -1056, 10840, + 6161, -1056, 866, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, 1218, -1056, -1056, -1056, -1056, -1056, -1056, + 18, 18, -1056, -1056, 917, -1056, 907, 10966, -1056, 911, + 595, 916, 916, -1056, 919, 1015, 924, 1020, -1056, 866, + 6, 862, 1709, -1056, -1056, -1056, -1056, 18, 942, 949, + 932, 12076, -1056, 933, 916, 916, -1056, 943, 945, -1056, + 931, -1056, -1056, 206, 38, 117, 18, 12235, -1056, 948, + -1056, -1056, 952, 954, -1056, 12268, -1056, -1056, 679, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 18, 18, + 18, 18, 1060, -1056, 1049, 183, 292, 324, 5859, 1110, + 6010, 12149, 10966, -1056, 649, -1056, 1218, 1276, -1056, 974, + 18, 976, -1056, -1056, -1056, 10966, 1709, -1056, -1056, 1099, + -1056, -1056, -1056, -1056, 359, -1056, -1056, 1709, -1056, -1056, + 1860, -1056, -1056, -1056, -1056, 5859, 18, 123, 7445, 994, + -1056, 12076, 1709, -1056, 1074, 1070, 1099, -1056, -1056, -1056, + 1709, -1056, 1860, -1056, 1293, -1056, 988, 12268, -1056, 163, + 934, 990, -1056, 717, -1056, 687, 934, -1056, -1056, 730, + -1056, -1056, -1056, -1056, 360, 13415, 9328, 13505, 922, -1056, + 817, 108, 838, 295, -1056, -1056, -1056, -1056, -1056, -1056, + 18, -1056, 1218, -1056, 855, -1056, -1056, -1056, 993, 996, + -1056, 1091, 916, -1056, 998, -1056, 1001, -1056, 998, 866, + 999, 5859, 7168, -1056, 1032, -1056, 1070, -1056, 1009, 1014, + -1056, 13595, -1056, 916, 1017, -1056, 1019, 1017, -1056, 710, + -1056, -1056, 12268, 1023, -1056, 1026, 12268, -1056, -1056, -1056, + -1056, -1056, 105, 187, 18, 371, 396, -1056, -1056, -1056, + 11218, 11218, 2069, -1056, -1056, 1037, 1038, 1709, -1056, 1860, + -1056, -1056, 1860, -1056, 1860, -1056, -1056, -1056, -1056, 866, + 1042, -1056, 1709, -1056, 1860, -1056, 1013, 1040, -1056, 1860, + -1056, 1860, -1056, -1056, 1293, -1056, 1023, 12268, 12268, 1023, + 406, -1056, -1056, -1056, -1056, 855, 855, 998, 1052, 998, + 998, -1056, -1056, 1017, 1053, 1017, 1017, -1056, -1056, 1023, + -1056, 1038, -1056, 1860, -1056, -1056, -1056, -1056, 1860, -1056, + -1056, -1056, 6312, 998, 1017, 80, -1056, -1056, -1056, -1056, + -1056 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ -static const yytype_uint16 yydefact[] = +static const yytype_int16 yydefact[] = { 2, 0, 0, 1, 0, 361, 362, 363, 0, 354, 355, 356, 359, 357, 358, 360, 349, 350, 351, 352, - 372, 278, 278, 636, 635, 637, 638, 747, 0, 747, - 0, 0, 640, 639, 641, 729, 731, 632, 631, 730, - 634, 626, 627, 628, 629, 577, 646, 647, 0, 0, - 0, 0, 0, 0, 305, 759, 759, 95, 325, 597, - 597, 599, 601, 0, 0, 0, 0, 0, 0, 0, - 3, 745, 6, 9, 35, 40, 52, 67, 278, 66, + 372, 278, 278, 635, 634, 636, 637, 746, 0, 746, + 0, 0, 639, 638, 640, 728, 730, 631, 630, 729, + 633, 625, 626, 627, 628, 576, 645, 646, 0, 0, + 0, 0, 0, 0, 305, 757, 757, 95, 325, 596, + 596, 598, 600, 0, 0, 0, 0, 0, 0, 0, + 3, 744, 6, 9, 35, 40, 52, 67, 278, 66, 0, 83, 0, 87, 97, 0, 61, 235, 250, 0, - 303, 0, 0, 63, 63, 745, 0, 0, 0, 0, - 314, 68, 323, 292, 293, 576, 578, 294, 295, 296, - 298, 297, 299, 575, 616, 617, 574, 624, 642, 643, + 303, 0, 0, 63, 63, 744, 0, 0, 0, 0, + 314, 68, 323, 292, 293, 575, 577, 294, 295, 296, + 298, 297, 299, 574, 615, 616, 573, 623, 641, 642, 300, 0, 301, 71, 5, 8, 176, 187, 177, 200, 173, 193, 183, 182, 203, 204, 198, 181, 180, 175, 201, 205, 206, 185, 174, 188, 192, 194, 186, 179, @@ -1887,174 +1983,174 @@ static const yytype_uint16 yydefact[] = 143, 163, 164, 149, 150, 154, 158, 144, 146, 136, 137, 138, 151, 152, 153, 155, 156, 159, 160, 165, 131, 133, 28, 129, 130, 132, 0, 0, 0, 0, - 0, 0, 0, 597, 0, 273, 0, 257, 283, 81, - 277, 759, 0, 642, 643, 0, 301, 759, 723, 82, - 747, 79, 0, 759, 448, 78, 747, 748, 0, 0, + 0, 0, 0, 596, 0, 273, 0, 257, 283, 81, + 277, 757, 0, 641, 642, 0, 301, 757, 722, 82, + 746, 79, 0, 757, 448, 78, 746, 747, 0, 0, 23, 247, 0, 10, 0, 349, 350, 317, 449, 0, 229, 0, 314, 230, 220, 221, 311, 0, 21, 0, - 0, 745, 17, 20, 747, 85, 16, 307, 747, 0, - 752, 752, 258, 0, 0, 752, 721, 747, 0, 0, - 0, 93, 353, 0, 103, 104, 111, 427, 621, 620, - 622, 619, 0, 618, 0, 0, 0, 584, 593, 589, - 595, 625, 56, 241, 242, 755, 756, 4, 757, 746, + 0, 744, 17, 20, 746, 85, 16, 307, 746, 0, + 750, 750, 258, 0, 0, 750, 720, 746, 0, 0, + 0, 93, 353, 0, 103, 104, 111, 427, 620, 619, + 621, 618, 0, 617, 0, 0, 0, 583, 592, 588, + 594, 624, 56, 241, 242, 753, 754, 4, 755, 745, 0, 0, 0, 0, 0, 0, 0, 364, 453, 442, 72, 457, 322, 365, 457, 438, 0, 99, 0, 91, 88, 0, 57, 0, 0, 0, 0, 0, 253, 254, 0, 0, 0, 0, 218, 219, 0, 0, 0, 251, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 741, 742, 0, 759, 0, 0, 62, 0, 0, - 0, 0, 0, 745, 333, 746, 0, 383, 382, 0, - 0, 642, 643, 301, 121, 122, 0, 0, 124, 650, - 0, 642, 643, 301, 341, 196, 189, 199, 184, 166, - 167, 168, 126, 127, 719, 343, 718, 0, 80, 744, - 743, 0, 324, 579, 0, 0, 134, 726, 311, 284, - 728, 280, 0, 0, 0, 0, 274, 282, 0, 759, - 0, 0, 0, 0, 275, 747, 0, 316, 279, 677, - 747, 269, 759, 747, 759, 268, 747, 321, 55, 25, + 0, 740, 741, 0, 757, 0, 0, 62, 0, 0, + 0, 0, 0, 744, 333, 745, 0, 383, 382, 0, + 0, 641, 642, 301, 121, 122, 0, 0, 124, 649, + 0, 641, 642, 301, 341, 196, 189, 199, 184, 166, + 167, 168, 126, 127, 718, 343, 717, 0, 80, 743, + 742, 0, 324, 578, 0, 0, 134, 725, 311, 284, + 727, 280, 0, 0, 0, 0, 274, 282, 0, 757, + 0, 0, 0, 0, 275, 746, 0, 316, 279, 676, + 746, 269, 757, 746, 757, 268, 746, 321, 55, 25, 27, 26, 0, 318, 0, 0, 0, 0, 0, 0, - 19, 0, 747, 309, 15, 746, 84, 747, 306, 312, - 754, 753, 259, 754, 261, 313, 722, 0, 110, 625, - 101, 96, 0, 0, 759, 0, 326, 428, 603, 623, - 606, 604, 598, 580, 581, 600, 582, 602, 0, 0, - 0, 0, 0, 758, 7, 29, 30, 31, 32, 33, + 19, 0, 746, 309, 15, 745, 84, 746, 306, 312, + 752, 751, 259, 752, 261, 313, 721, 0, 110, 624, + 101, 96, 0, 0, 757, 0, 326, 428, 602, 622, + 605, 603, 597, 579, 580, 599, 581, 601, 0, 0, + 0, 0, 0, 756, 7, 29, 30, 31, 32, 33, 53, 54, 0, 454, 453, 73, 0, 458, 0, 0, - 36, 288, 0, 39, 287, 747, 0, 89, 100, 51, + 36, 288, 0, 39, 287, 746, 0, 89, 100, 51, 41, 49, 0, 262, 283, 207, 37, 0, 301, 58, 227, 234, 236, 237, 238, 245, 246, 239, 240, 216, - 217, 243, 244, 747, 231, 232, 233, 222, 223, 224, - 225, 226, 255, 256, 732, 734, 733, 735, 447, 278, - 445, 747, 732, 734, 733, 735, 446, 278, 0, 759, + 217, 243, 244, 746, 231, 232, 233, 222, 223, 224, + 225, 226, 255, 256, 731, 733, 732, 734, 447, 278, + 445, 746, 731, 733, 732, 734, 446, 278, 0, 757, 374, 0, 373, 0, 0, 0, 0, 331, 0, 311, - 0, 759, 0, 63, 339, 121, 122, 123, 648, 337, - 0, 759, 0, 0, 0, 344, 739, 740, 346, 732, - 733, 278, 42, 262, 208, 48, 215, 0, 0, 725, - 0, 285, 281, 759, 732, 733, 747, 732, 733, 724, - 315, 749, 264, 270, 265, 272, 320, 24, 0, 248, - 11, 34, 0, 759, 214, 22, 86, 18, 308, 752, - 0, 94, 736, 109, 747, 732, 733, 429, 607, 0, - 583, 0, 586, 0, 591, 588, 0, 0, 592, 228, + 0, 757, 0, 63, 339, 121, 122, 123, 647, 337, + 0, 757, 0, 0, 0, 344, 738, 739, 346, 731, + 732, 278, 42, 262, 208, 48, 215, 0, 0, 724, + 0, 285, 281, 757, 731, 732, 746, 731, 732, 723, + 315, 748, 264, 270, 265, 272, 320, 24, 0, 248, + 11, 34, 0, 757, 214, 22, 86, 18, 308, 750, + 0, 94, 735, 109, 746, 731, 732, 429, 606, 0, + 582, 0, 585, 0, 590, 587, 0, 0, 591, 228, 451, 455, 0, 371, 452, 459, 437, 291, 0, 0, - 98, 92, 0, 0, 0, 0, 0, 759, 0, 0, + 98, 92, 0, 0, 0, 0, 0, 757, 0, 0, 0, 0, 0, 444, 76, 0, 450, 0, 0, 267, - 443, 74, 266, 304, 366, 759, 759, 566, 759, 375, - 759, 329, 377, 64, 376, 330, 468, 0, 0, 368, - 0, 0, 736, 310, 747, 732, 733, 0, 0, 0, - 0, 121, 122, 125, 747, 0, 747, 653, 0, 439, - 69, 135, 727, 286, 276, 0, 0, 450, 0, 0, - 759, 747, 260, 102, 450, 430, 608, 612, 613, 614, - 605, 615, 585, 587, 594, 590, 596, 759, 70, 759, - 0, 289, 38, 90, 50, 263, 732, 733, 747, 732, - 733, 560, 564, 0, 0, 0, 505, 499, 502, 558, - 0, 59, 485, 487, 489, 492, 539, 544, 545, 546, - 549, 550, 551, 552, 553, 555, 554, 556, 557, 0, - 47, 212, 46, 213, 77, 750, 0, 44, 210, 45, - 211, 75, 567, 568, 759, 569, 367, 369, 0, 12, - 14, 573, 370, 0, 0, 0, 378, 380, 0, 65, + 443, 74, 266, 304, 366, 757, 757, 565, 757, 375, + 757, 329, 377, 64, 376, 330, 468, 0, 0, 368, + 0, 0, 735, 310, 746, 731, 732, 0, 0, 0, + 0, 121, 122, 125, 746, 0, 746, 652, 0, 439, + 69, 135, 726, 286, 276, 0, 0, 450, 0, 0, + 757, 746, 260, 102, 450, 430, 607, 611, 612, 613, + 604, 614, 584, 586, 593, 589, 595, 757, 70, 757, + 0, 289, 38, 90, 50, 263, 731, 732, 746, 731, + 732, 559, 563, 0, 0, 0, 505, 499, 502, 557, + 0, 59, 485, 487, 489, 492, 538, 543, 544, 545, + 548, 549, 550, 551, 552, 554, 553, 555, 556, 0, + 47, 212, 46, 213, 77, 749, 0, 44, 210, 45, + 211, 75, 566, 567, 757, 568, 367, 369, 0, 12, + 14, 572, 370, 0, 0, 0, 378, 380, 0, 65, 469, 0, 335, 0, 461, 0, 334, 450, 0, 0, - 0, 0, 450, 342, 720, 676, 0, 676, 347, 440, - 441, 0, 271, 319, 676, 609, 747, 0, 418, 417, - 0, 290, 450, 547, 548, 122, 562, 0, 0, 501, - 0, 0, 504, 427, 561, 0, 60, 0, 542, 543, - 0, 491, 490, 0, 0, 249, 43, 209, 0, 0, - 571, 572, 0, 381, 0, 327, 328, 470, 332, 462, - 0, 0, 336, 0, 649, 338, 683, 680, 679, 678, - 681, 689, 698, 677, 0, 710, 699, 714, 713, 709, - 675, 747, 747, 682, 684, 685, 687, 661, 691, 696, - 759, 702, 759, 759, 707, 661, 712, 661, 0, 659, - 0, 0, 653, 676, 431, 434, 610, 416, 747, 0, - 685, 401, 693, 694, 759, 759, 759, 705, 401, 401, - 399, 421, 456, 460, 747, 519, 507, 747, 508, 514, - 0, 534, 597, 747, 525, 530, 533, 527, 529, 537, - 751, 559, 486, 488, 540, 541, 563, 498, 495, 597, - 747, 747, 747, 747, 0, 570, 0, 642, 643, 301, - 0, 759, 0, 0, 0, 463, 759, 340, 0, 394, - 386, 388, 747, 391, 384, 651, 652, 0, 0, 668, - 690, 0, 656, 717, 700, 701, 0, 658, 657, 0, - 671, 711, 0, 673, 715, 345, 654, 0, 747, 0, - 0, 0, 419, 0, 407, 409, 0, 692, 0, 396, - 398, 397, 0, 412, 0, 414, 0, 506, 517, 0, - 500, 512, 523, 509, 515, 0, 503, 526, 532, 538, - 536, 0, 493, 494, 496, 497, 311, 0, 759, 0, - 759, 13, 759, 0, 477, 480, 483, 484, 464, 466, - 467, 465, 747, 393, 0, 686, 0, 703, 660, 688, - 661, 661, 697, 702, 759, 716, 661, 708, 661, 685, - 661, 0, 0, 0, 0, 432, 0, 420, 704, 400, - 401, 401, 311, 0, 695, 759, 401, 706, 401, 401, - 425, 747, 423, 426, 0, 520, 521, 510, 0, 516, - 535, 531, 524, 528, 736, 310, 747, 732, 733, 565, - 379, 471, 0, 0, 481, 385, 387, 389, 392, 0, - 664, 0, 666, 655, 0, 672, 0, 669, 674, 348, - 433, 0, 0, 611, 0, 404, 0, 406, 736, 310, - 395, 0, 413, 0, 410, 415, 0, 422, 518, 0, - 0, 513, 450, 472, 478, 479, 482, 0, 0, 661, - 661, 661, 661, 436, 435, 401, 401, 401, 401, 424, - 522, 511, 473, 390, 665, 0, 662, 667, 670, 405, - 0, 402, 408, 411, 0, 661, 401, 759, 663, 403, - 475, 476, 474 + 0, 0, 450, 342, 719, 675, 0, 675, 347, 440, + 441, 0, 271, 319, 675, 608, 746, 0, 418, 417, + 0, 290, 450, 546, 547, 122, 561, 0, 0, 501, + 504, 0, 427, 560, 0, 60, 0, 541, 542, 0, + 491, 490, 0, 0, 249, 43, 209, 0, 0, 570, + 571, 0, 381, 0, 327, 328, 470, 332, 462, 0, + 0, 336, 0, 648, 338, 682, 679, 678, 677, 680, + 688, 697, 676, 0, 709, 698, 713, 712, 708, 674, + 746, 746, 681, 683, 684, 686, 660, 690, 695, 757, + 701, 757, 757, 706, 660, 711, 660, 0, 658, 0, + 0, 652, 675, 431, 434, 609, 416, 746, 0, 684, + 401, 692, 693, 757, 757, 757, 704, 401, 401, 399, + 421, 456, 460, 746, 519, 507, 746, 508, 514, 0, + 533, 596, 0, 525, 529, 532, 526, 528, 536, 558, + 486, 488, 539, 540, 562, 498, 495, 596, 746, 746, + 746, 746, 0, 569, 0, 641, 642, 301, 0, 757, + 0, 0, 0, 463, 757, 340, 0, 394, 386, 388, + 746, 391, 384, 650, 651, 0, 0, 667, 689, 0, + 655, 716, 699, 700, 0, 657, 656, 0, 670, 710, + 0, 672, 714, 345, 653, 0, 746, 0, 0, 0, + 419, 0, 407, 409, 0, 691, 0, 396, 398, 397, + 0, 412, 0, 414, 0, 506, 517, 0, 500, 512, + 523, 509, 515, 0, 503, 0, 531, 537, 535, 0, + 493, 494, 496, 497, 311, 0, 757, 0, 757, 13, + 757, 0, 477, 480, 483, 484, 464, 466, 467, 465, + 746, 393, 0, 685, 0, 702, 659, 687, 660, 660, + 696, 701, 757, 715, 660, 707, 660, 684, 660, 0, + 0, 0, 0, 432, 0, 420, 703, 400, 401, 401, + 311, 0, 694, 757, 401, 705, 401, 401, 425, 746, + 423, 426, 0, 520, 521, 510, 0, 516, 534, 530, + 524, 527, 735, 310, 746, 731, 732, 564, 379, 471, + 0, 0, 481, 385, 387, 389, 392, 0, 663, 0, + 665, 654, 0, 671, 0, 668, 673, 348, 433, 0, + 0, 610, 0, 404, 0, 406, 735, 310, 395, 0, + 413, 0, 410, 415, 0, 422, 518, 0, 0, 513, + 450, 472, 478, 479, 482, 0, 0, 660, 660, 660, + 660, 436, 435, 401, 401, 401, 401, 424, 522, 511, + 473, 390, 664, 0, 661, 666, 669, 405, 0, 402, + 408, 411, 0, 660, 401, 757, 662, 403, 475, 476, + 474 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1028, -1028, -1028, 923, -1028, 62, 730, -552, -1028, -35, - -1028, 731, -1028, 72, -1028, -212, -254, -66, -1028, -1028, - -1028, -32, -88, -1028, -1028, -36, -1028, -260, 641, 25, - 1106, -141, -6, -68, -1028, -410, -19, 2212, -370, 1108, - -40, -24, -1028, -1028, 5, -1028, 2954, -1028, 1121, -1028, - 1541, -1028, 652, 426, 601, -307, 94, -10, -1028, -360, - -218, 66, -1028, -310, -52, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 32, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, 509, -1028, 210, 981, -368, - -1028, 126, -700, -1028, -1024, -1001, 198, 116, 355, 317, - -1028, 461, -1028, -860, -1028, 30, 350, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, 494, -1028, -1028, -95, 723, -1028, - -1028, -1028, 915, -1028, -1028, -1028, -1028, -680, -1028, -1, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -526, - -1028, -1028, -1028, -1028, 354, -1028, -1028, -1028, -824, -1028, - 230, -609, -594, -781, -1028, 177, -1028, 178, 190, -1028, - -376, -1028, 373, -1028, -1028, 166, -1028, -1028, 263, 485, - 499, -1028, 1171, 747, 1110, 1394, -1028, 780, 1448, -1028, - 1612, 1744, -1028, -1028, -57, -1028, -1028, -199, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, 0, -1028, -1028, -1028, -1028, - -37, 2020, 1174, 1178, 2236, 1512, -1028, -1028, 329, -1028, - -705, 314, -773, 429, -1027, -785, -603, -908, 236, -200, - 258, 243, -1028, -1028, -503, -690, -213, -984, -987, 234, - 274, -1028, -846, -1028, -513, -379, -1028, -1028, -1028, 6, - -417, -1028, -275, -1028, -1028, -87, -1028, -71, 23, 185, - -583, 322, -194, -60, -44, -2 + -1056, -1056, -1056, 953, -1056, 22, 743, -541, -1056, -51, + -1056, 736, -1056, 115, -1056, -228, -321, -68, -1056, -1056, + -1056, -32, -72, -1056, -1056, 2, -1056, -5, 735, 4, + 1113, -175, 26, -76, -1056, -452, -19, 2254, -362, 1108, + -43, -14, -1056, -1056, 0, -1056, 3078, -1056, 1123, -1056, + 778, -1056, 709, 133, 601, -307, 121, -13, -1056, -283, + -209, -4, -1056, -314, -25, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 32, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, 507, -1056, -296, 1267, -365, + -1056, 127, -700, -1056, -1027, -1024, 200, 119, 363, 165, + -1056, 454, -1056, -874, -1056, 40, 349, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, 495, -1056, -1056, -96, 722, -1056, + -1056, -1056, 915, -1056, -1056, -1056, -1056, -698, -1056, 5, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -591, + -1056, -1056, -1056, -1056, 361, -1056, -1056, -1056, -851, -1056, + 230, -1055, -711, -779, -1056, 168, -1056, 170, 171, -1056, + -409, -1056, 366, -1056, -1056, 166, -1056, -1056, 246, 28, + 375, -1056, 1151, 666, 777, 842, -1056, 760, 1516, -1056, + 2119, 2191, -1056, -1056, -59, -1056, -1056, -229, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, 3, -1056, -1056, -1056, -1056, + -27, 2015, 1563, 1159, 2490, 1953, -1056, -1056, 314, -1056, + -390, 71, -701, 421, -1019, -433, 145, -971, 75, -404, + 248, 226, -1056, -1056, -214, -674, -320, -969, -991, 234, + 266, -1056, -616, -1056, 162, -816, -1056, -1056, -1056, 157, + -396, -1056, -319, -1056, -1056, -86, -1056, -7, 23, 56, + -593, -236, -66, -28, -2 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 70, 71, 72, 243, 578, 902, 579, + -1, 1, 2, 70, 71, 72, 243, 578, 901, 579, 261, 262, 461, 263, 452, 74, 530, 75, 539, 689, - 886, 368, 370, 371, 839, 76, 77, 515, 249, 79, + 885, 368, 370, 371, 839, 76, 77, 515, 249, 79, 80, 264, 81, 82, 83, 481, 84, 216, 388, 389, 200, 201, 202, 617, 567, 204, 86, 454, 359, 87, 218, 269, 535, 568, 700, 440, 441, 231, 232, 220, 426, 442, 523, 524, 88, 366, 268, 467, 638, 287, - 717, 588, 730, 728, 603, 605, 737, 738, 952, 251, + 717, 588, 730, 728, 603, 605, 737, 738, 951, 251, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 321, 324, 705, 828, 720, 833, 834, 674, 252, 581, - 713, 835, 836, 380, 1020, 1021, 1022, 1023, 1129, 1055, - 958, 867, 868, 959, 1141, 1142, 486, 487, 657, 755, - 864, 1049, 954, 1125, 325, 101, 102, 322, 512, 513, - 671, 767, 516, 517, 675, 769, 845, 721, 1101, 718, - 840, 907, 1013, 1203, 1222, 1234, 1242, 1093, 1094, 1072, - 792, 793, 893, 894, 794, 878, 880, 877, 977, 978, - 979, 1145, 980, 983, 984, 985, 986, 987, 988, 795, - 796, 883, 797, 798, 799, 706, 824, 899, 830, 103, + 713, 835, 836, 380, 1018, 1019, 1020, 1021, 1127, 1053, + 957, 867, 868, 958, 1139, 1140, 486, 487, 657, 755, + 864, 1047, 953, 1123, 325, 101, 102, 322, 512, 513, + 671, 767, 516, 517, 675, 769, 845, 721, 1099, 718, + 840, 906, 1011, 1201, 1220, 1232, 1240, 1091, 1092, 1070, + 792, 793, 892, 893, 794, 878, 881, 877, 976, 977, + 978, 1143, 979, 982, 983, 984, 985, 986, 987, 795, + 796, 882, 797, 798, 799, 706, 824, 898, 830, 103, 104, 105, 106, 107, 108, 109, 498, 661, 110, 500, 111, 112, 499, 501, 292, 295, 296, 492, 659, 658, - 756, 865, 956, 1050, 760, 113, 114, 293, 115, 116, + 756, 865, 955, 1048, 760, 113, 114, 293, 115, 116, 117, 223, 224, 120, 225, 226, 599, 729, 856, 857, - 1108, 1029, 931, 443, 933, 934, 1119, 936, 937, 938, - 939, 963, 964, 940, 941, 942, 943, 944, 967, 968, - 945, 946, 947, 948, 949, 1032, 407, 604, 274, 444, + 1106, 1027, 930, 443, 932, 933, 1117, 935, 936, 937, + 938, 962, 963, 939, 940, 941, 942, 943, 966, 967, + 944, 945, 946, 947, 948, 1030, 407, 604, 274, 444, 228, 123, 642, 570, 608, 602, 411, 307, 436, 437, - 696, 882, 472, 582, 375, 266 + 696, 472, 582, 375, 266 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -2062,678 +2158,595 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 124, 583, 365, 294, 240, 282, 372, 412, 205, 434, - 838, 308, 235, 203, 410, 330, 629, 597, 260, 291, - 969, 536, 227, 227, 374, 367, 367, 309, 205, 367, - 301, 282, 302, 203, 89, 308, 89, 841, 281, 1143, - 317, 215, 215, 747, 282, 282, 282, 265, 222, 222, - 238, 735, 241, 272, 276, 1117, 629, 571, -116, 405, - 369, 271, 275, 373, 203, 622, 125, 580, 320, 1000, - 1002, 754, 651, 622, 73, 1137, 73, 474, -112, 1068, - 1166, 476, 221, 221, 951, 89, 89, 712, 569, 283, - 577, 955, 1123, -113, -120, 1147, 495, 497, 1051, 580, - 222, -119, -115, 885, 203, 1168, 227, 827, -117, 719, - 219, 229, 1001, 1003, -353, 283, 681, -84, 462, 529, - 1109, 270, 626, 222, 222, 215, 267, 222, 379, 390, - 390, -112, 222, 3, 317, 430, 611, -98, -114, 1024, - 1034, 847, -353, -353, 315, 316, 1109, -116, -113, -523, - 930, 852, 930, 569, 237, 577, 422, 318, 1035, 930, - 612, 615, 233, 791, 458, 827, 221, 663, 667, 1143, - 446, -118, 448, 1069, 260, 716, 965, 654, 851, -107, - 1048, -732, 1111, 643, 1166, 1117, 1124, 525, 1122, 1148, - 464, -353, -120, 1118, 408, 872, 485, 1137, -636, -103, - 910, 308, 529, 529, 879, 305, 1223, 306, 1131, 456, - 643, 305, 480, 306, -104, -111, 1138, 465, 629, 427, - 664, 668, -110, -106, 260, 427, 434, -636, 282, -108, - 733, 445, 1097, 1024, 1103, -119, 227, 305, 227, 306, - 124, 89, 479, 242, 367, 367, 367, 367, 930, 510, - 511, 318, 935, 265, 935, 215, 256, 215, 215, -105, - 237, 935, 222, 960, 222, 222, 1109, 244, 222, -112, - 222, -112, 773, 622, 89, 622, 89, 282, 505, 506, - 507, 508, -732, 1109, 724, -116, -113, -116, -113, 89, - 520, 89, 592, 260, 734, 531, 221, 913, 221, 662, - 477, 662, 587, -118, 950, 367, -733, 297, 997, -118, - 527, -118, 283, 308, 73, 981, 1099, 643, 973, 1024, - 594, 1024, 265, 1210, 435, 927, 438, 643, -115, 460, - -120, -117, -120, 298, 922, 584, 1100, 586, 1216, 585, - 1206, 89, 222, 222, 222, 222, 89, 222, 222, 928, - 935, 974, 976, 970, 488, 885, 315, 316, 222, -635, - 89, 283, 445, 537, 965, 926, -644, 976, 976, 982, - 575, 504, 965, -119, 965, -119, 885, 989, 531, 531, - 778, 73, 1079, 305, 1073, 306, 509, -106, -635, 215, - 989, 989, 522, -112, 1070, 823, 222, 522, 89, 299, - 1080, 1164, 89, 222, 89, 744, -107, 873, 874, 490, - 491, 569, 1150, 577, 480, 876, 575, 300, 222, 1084, - 1085, 447, 1024, 1024, -109, 935, -733, 445, 637, 237, - 282, 623, -108, 890, 814, 575, 935, 810, 812, 323, - 427, 821, 427, 817, 819, 629, 537, 537, 234, 466, - 688, 960, 205, 468, 215, 752, 326, 203, 480, 960, - 1078, 222, 763, 575, -645, 432, -115, 763, -115, -117, - -114, -117, 529, 459, 282, 1146, 649, 911, 327, 529, - 529, 891, 445, 333, 892, 529, 529, 1095, -106, -747, - 575, -113, -120, 361, 965, 1121, 965, 89, 237, 415, - -119, 965, 622, 965, 319, 727, 331, -107, -106, 215, - 989, -106, 994, 995, 283, -106, 222, 470, 1115, 414, - 996, 362, 363, 1115, 471, 714, -120, -107, 1113, -732, - -107, 1010, 744, -108, -107, 1198, 1012, 1240, 736, 1201, - 965, 970, 356, 357, 358, 1115, 708, 488, 710, 970, - 1146, 970, 748, -108, 1146, 1113, -108, 749, 283, 694, - -108, 861, 896, 1037, 1038, 697, 935, 701, 60, 698, - 364, 1181, 751, 1202, 989, 702, 690, 707, 416, -115, - 418, 960, 753, 361, -117, 1059, 1060, 1061, -114, 445, - 361, 1221, -115, 741, 695, -637, -117, 575, 282, 445, - 489, 740, 490, 491, 529, 1220, 1146, 575, -114, 702, - -114, 362, 428, 89, 480, 89, 215, 205, 362, 457, - 630, 427, 203, 222, -637, 632, 215, 236, 634, 423, - 282, 636, 488, 222, 488, 89, 222, 816, 976, 750, - -638, 702, 424, 78, 859, 78, 488, 646, 531, 695, - -640, -105, 648, 966, -639, 531, 531, 78, 78, 425, - 429, 531, 531, 367, -114, 473, 962, 429, 849, -638, - 222, 970, 471, 970, 234, 319, -641, 695, 970, -640, - 970, 236, 283, -639, 488, 445, 237, 490, 491, 490, - 491, 433, 848, 575, 78, 78, -747, 850, 858, 493, - 237, 490, 491, 825, 831, -641, 837, -729, 837, 78, - 680, 89, 215, 431, 283, 89, 537, 970, 762, 222, - 765, -630, 453, 537, 537, 1161, 338, 339, 676, 537, - 537, -633, 78, 78, 606, 1173, 78, 493, 1196, 490, - 491, 78, 618, 203, 488, 237, 230, 695, 427, -630, - -630, 772, -105, 233, -310, 774, 1190, 695, 361, 89, - -633, 222, 89, 607, 826, 869, -747, 869, 367, 237, - 827, 522, -105, 349, 350, -105, -642, -630, -630, -105, - 531, 1156, -310, -310, -643, 595, 362, 483, 703, 596, - 914, 576, -301, 901, 711, 333, 715, 494, 903, 490, - 491, 695, 904, 595, -642, -642, 463, 875, -83, 361, - 695, 881, -643, -643, 643, 469, -644, 475, 1114, 478, - -301, -301, 900, 482, -729, 502, -630, 514, -645, -729, - 528, -310, 972, 589, -733, 484, 333, 362, 590, 832, - 827, 966, 503, -112, 598, 1135, 282, 593, 537, 966, - 78, 966, 488, -642, 962, -113, 576, 633, 962, 631, - 89, -643, 962, -103, 962, 89, 222, 1011, 635, -301, - 640, 78, 641, 78, 78, -104, 1016, 78, -98, 78, - 650, 89, 415, 78, 576, 78, 591, 361, 89, 971, - 459, 1046, 673, 354, 355, 356, 357, 358, 78, 89, - 78, 670, 89, 888, 889, 660, -283, 490, 491, -120, - 282, 576, 449, 678, 695, 362, 409, -119, 679, 1089, - 682, 854, 450, 451, 683, 1075, 1162, 1163, 842, -111, - 1006, 846, 684, 704, 89, 709, 863, -110, 1033, 716, - 1033, 1033, 1081, 89, 719, 853, 764, 766, 768, 697, - 78, 78, 78, 78, 78, 78, 78, 78, -284, 361, - 809, -311, 1033, 1033, 1033, 827, 815, 78, 855, 78, - 862, 966, 78, 966, 866, 1090, -115, 1092, 966, -285, - 966, 971, -730, 100, 962, 100, 962, 362, 600, -311, - -311, 962, 884, 962, 1057, 693, -106, 100, 100, 885, - 695, 282, 887, 699, 898, 78, 881, 78, -286, 831, - 990, 78, 78, 78, 837, 1126, 781, 966, 576, 488, - 496, -736, 1027, 1028, -633, 695, 695, 78, 576, 1031, - 962, 361, 1041, 1036, 100, 100, 601, 699, -311, 1044, - 1039, 1042, 89, 1052, 89, 905, 1053, 1054, 906, 100, - 1086, 908, -633, -633, 488, 78, 78, 1058, 912, 362, - 686, 915, 1062, -736, 1064, 1074, 614, 616, 693, 699, - 78, 971, 100, 100, 490, 491, 100, 998, 1077, 89, - 1066, 100, 89, 614, 616, 1128, 445, 826, 707, 1182, - 837, -736, -736, 361, 575, 1104, 367, 367, 361, -730, - 1106, -633, 961, 1127, -730, 1132, 78, 665, 687, 490, - 491, 644, 1033, 215, 576, 698, 1025, 1026, 921, 816, - 222, 362, 1087, 1017, 1144, 78, 362, 1133, 1149, 1169, - 1204, 1205, 1171, 1033, 1035, 1174, 1176, 922, -736, 1183, - -736, 1180, -117, -732, 1184, 488, -114, 1186, 916, 1191, - 917, 918, 919, 920, 921, 89, 89, 1193, 1199, 1067, - 1045, 1200, -108, 1207, 1197, 455, -105, 1208, 926, 927, - 1088, 1214, -732, 922, 800, 601, 119, -733, 119, 695, - 310, 311, 312, 313, 314, 1082, 1083, 1225, 801, 1230, - 100, 645, 333, 928, 222, 222, 647, 924, 493, 1237, - 490, 491, 377, 1150, 926, 927, 394, 1105, 360, 346, - 347, 100, 739, 100, 100, 829, 1102, 100, 1160, 100, - 1167, 957, 78, 100, 78, 100, 1219, 119, 119, 928, - 870, 285, 78, 991, 860, 837, 1241, 672, 100, 518, - 100, 993, 78, 1096, 78, 78, 351, 352, 353, 354, - 355, 356, 357, 358, 1151, 1152, 1159, 285, 992, 1040, - 916, 1043, 917, 918, 919, 920, 89, 1153, 800, 800, - 382, 392, 392, 392, 1091, 1116, 413, 406, 1120, 78, - 666, 1047, 801, 801, 932, 1063, 1065, 1165, 1130, 1112, - 100, 100, 100, 100, 100, 100, 100, 100, 1136, 333, - 1139, 1134, 1110, 757, 758, 1076, 759, 100, 0, 100, - 0, 0, 100, 46, 47, 0, 346, 347, 0, 0, - 78, 0, 0, 0, 78, 78, 0, 0, 78, 0, - 0, 1179, 78, 78, 41, 42, 43, 44, 78, 78, - 0, 0, 0, 811, 813, 100, 0, 100, 0, 818, - 820, 100, 100, 100, 0, 353, 354, 355, 356, 357, - 358, 0, 800, 800, 0, 0, 0, 100, 78, 0, - 78, 78, 800, 800, 800, 0, 801, 801, 800, 800, - 0, 0, 0, 119, 0, 0, 801, 801, 801, 0, - 0, 1213, 801, 801, 0, 100, 100, 811, 813, 0, - 818, 820, 0, 0, 0, 1209, 0, 1211, 0, 0, - 100, 0, 1212, 0, 0, 0, 119, 0, 119, 0, - 1215, 0, 1217, 0, 1170, 1172, 0, 0, 0, 1218, - 1175, 119, 1177, 119, 1178, 0, 802, 916, 0, 917, - 918, 919, 920, 921, 0, 0, 100, 1185, 1187, 0, - 0, 0, 0, 1192, 285, 1194, 1195, 78, 0, 0, - 0, 1235, 922, 800, 0, 100, 1236, 0, 897, 78, - 0, 800, 0, 0, 78, 78, 1140, 801, 917, 918, - 919, 920, 0, 119, 0, 801, 924, 0, 119, 0, - 78, 0, 925, 926, 927, 0, 0, 78, 800, 0, - 0, 0, 119, 285, 0, 0, 0, 0, 78, 0, - 0, 78, 801, 897, 122, 576, 122, 0, 928, 0, - 0, 929, 0, 1224, 1226, 1227, 1228, 0, 0, 0, - 802, 802, 1229, 1231, 1232, 1233, 0, 0, 237, 0, - 119, 333, 0, 78, 119, 0, 119, 0, 0, 1238, - 0, 0, 78, 1239, 800, 0, 0, 0, 346, 347, - 0, 0, 100, 0, 100, 122, 122, 0, 801, 286, - 0, 916, 100, 917, 918, 919, 920, 921, 0, 0, - 0, 0, 100, 0, 100, 100, 0, 0, 0, 916, - 0, 917, 918, 919, 920, 286, 922, 273, 354, 355, - 356, 357, 358, 0, 0, 0, 0, 0, 383, 393, - 393, 0, 916, 0, 917, 918, 919, 920, 0, 100, - 924, 0, 0, 0, 802, 802, 925, 926, 927, 800, - 0, 0, 0, 800, 802, 802, 802, 0, 1018, 119, - 802, 802, 0, 801, 1019, 0, 0, 801, 0, 800, - 0, 78, 928, 78, 0, 929, 285, 0, 0, 0, - 100, 1018, 0, 801, 100, 100, 0, 953, 100, 0, - 0, 0, 100, 100, 0, 0, 0, 0, 100, 100, - 0, 0, 0, 0, 800, 800, 0, 0, 78, 0, - 0, 78, 0, 0, 0, 0, 0, 0, 801, 801, - 285, 0, 0, 0, 0, 0, 0, 0, 100, 0, - 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 122, 0, 0, 0, 802, 0, 0, 0, 78, - 0, 0, 0, 802, 0, 0, 0, 0, 916, 0, - 917, 918, 919, 920, 921, 0, 0, 0, 417, 0, - 0, 419, 420, 421, 122, 119, 122, 119, 0, 0, - 802, 0, 0, 922, 78, 78, 0, 0, 0, 122, - 0, 122, 0, 0, 0, 0, 0, 119, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 924, 0, 0, - 0, 0, 286, 925, 926, 927, 0, 100, 0, 803, - 0, 0, 0, 78, 78, 0, 0, 0, 0, 100, - 0, 0, 0, 0, 100, 100, 802, 0, 0, 928, - 0, 122, 929, 0, 285, 0, 122, 0, 0, 0, - 100, 0, 0, 0, 0, 0, 0, 100, 0, 0, - 122, 286, 0, 538, 0, 0, 0, 0, 100, 0, - 0, 100, 0, 119, 0, 0, 285, 119, 0, 0, - 0, 0, 0, 808, 0, 0, 0, 521, 0, 0, - 0, 0, 534, 0, 0, 78, 0, 0, 122, 0, - 0, 0, 122, 100, 122, 0, 0, 0, 0, 0, - 0, 802, 100, 803, 803, 802, 0, 0, 0, 0, - 0, 119, 0, 0, 119, 0, 0, 0, 0, 0, - 0, 802, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 538, 538, 0, 916, - 0, 917, 918, 919, 920, 921, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 802, 802, 0, 0, - 0, 0, 0, 0, 922, 0, 0, 808, 808, 0, - 0, 0, 0, 0, 0, 619, 621, 0, 923, 0, - 0, 0, 0, 0, 273, 0, 0, 122, 924, 0, - 0, 0, 0, 0, 925, 926, 927, 803, 803, 0, - 0, 100, 0, 100, 286, 0, 0, 803, 803, 803, - 0, 0, 119, 803, 803, 0, 0, 119, 0, 0, - 928, 621, 0, 929, 273, 0, 0, 0, 0, 0, - 0, 0, 118, 119, 118, 0, 0, 0, 100, 0, - 119, 100, 0, 0, 0, 0, 0, 0, 286, 0, - 0, 119, 0, 0, 119, 0, 0, 0, 0, 0, - 0, 808, 808, 0, 0, 0, 0, 0, 0, 0, - 677, 808, 808, 808, 0, 0, 0, 808, 808, 100, - 0, 0, 1008, 118, 118, 0, 119, 284, 0, 0, - 0, 0, 0, 804, 0, 119, 0, 0, 803, 0, - 0, 0, 0, 122, 0, 122, 803, 0, 0, 0, - 0, 0, 0, 284, 100, 100, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 122, 381, 391, 391, 391, - 0, 0, 0, 803, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 392, 805, 0, 0, - 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, - 0, 0, 808, 0, 0, 0, 0, 0, 0, 742, - 808, 743, 286, 0, 0, 0, 0, 0, 0, 0, - 0, 761, 0, 0, 621, 0, 273, 804, 804, 803, - 0, 0, 0, 0, 119, 0, 119, 808, 0, 0, - 0, 122, 0, 0, 286, 122, 538, 0, 0, 0, - 0, 0, 0, 538, 538, 0, 0, 0, 0, 538, - 538, 0, 0, 0, 85, 100, 85, 0, 0, 771, - 0, 119, 0, 0, 119, 0, 0, 392, 0, 118, - 0, 805, 805, 0, 0, 0, 0, 0, 121, 122, - 121, 0, 122, 808, 0, 0, 822, 0, 0, 0, - 0, 0, 0, 0, 803, 0, 0, 0, 803, 0, - 0, 844, 118, 0, 118, 85, 85, 0, 0, 0, - 0, 804, 804, 0, 803, 0, 0, 118, 0, 118, - 0, 804, 804, 804, 0, 0, 0, 804, 804, 121, - 121, 0, 0, 0, 0, 0, 0, 119, 119, 0, - 284, 806, 0, 0, 0, 0, 0, 0, 378, 803, - 803, 871, 0, 0, 0, 0, 0, 0, 808, 0, - 0, 0, 808, 0, 0, 805, 805, 0, 538, 118, - 0, 0, 0, 0, 118, 805, 805, 805, 808, 0, - 122, 805, 805, 0, 0, 122, 0, 0, 118, 284, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 122, 0, 0, 0, 0, 0, 0, 122, 0, - 0, 0, 804, 808, 808, 0, 0, 0, 0, 122, - 804, 0, 122, 0, 909, 0, 118, 0, 0, 0, - 118, 0, 118, 0, 0, 806, 806, 0, 0, 0, - 0, 0, 0, 273, 0, 0, 0, 804, 119, 0, - 1009, 0, 0, 0, 122, 0, 0, 0, 0, 0, - 0, 85, 0, 122, 0, 0, 805, 0, 0, 0, - 0, 0, 0, 807, 805, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 121, 0, 0, 0, 0, - 0, 1015, 0, 0, 85, 0, 85, 0, 0, 0, - 0, 805, 0, 804, 0, 0, 0, 0, 0, 85, - 0, 85, 0, 0, 393, 0, 0, 0, 121, 1030, - 121, 0, 0, 0, 0, 118, 0, 0, 0, 806, - 806, 0, 0, 121, 0, 121, 0, 0, 0, 806, - 806, 806, 284, 0, 0, 806, 806, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 805, 0, 0, - 0, 85, 122, 0, 122, 0, 85, 807, 807, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 804, 0, - 85, 0, 804, 532, 0, 121, 284, 0, 0, 0, - 121, 0, 0, 0, 0, 1098, 0, 0, 804, 122, - 0, 0, 122, 0, 121, 393, 0, 121, 1107, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, - 0, 0, 85, 0, 85, 0, 0, 0, 0, 0, - 806, 0, 805, 804, 804, 0, 805, 0, 806, 0, - 0, 118, 121, 118, 0, 0, 121, 0, 121, 0, - 0, 0, 805, 0, 0, 0, 0, 0, 0, 0, - 0, 807, 807, 118, 0, 806, 532, 532, 0, 0, - 0, 807, 807, 807, 0, 122, 122, 807, 807, 0, - 0, 0, 0, 0, 0, 0, 0, 805, 805, 0, - 121, 121, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 284, 0, 0, 0, 0, 0, 0, 85, 0, 332, - 0, 806, 0, -759, 0, 0, 0, 0, 0, 0, - 0, -759, -759, -759, 0, 0, -759, -759, -759, 118, - -759, 121, 284, 118, 0, 0, 0, 0, -759, -759, - -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -759, -759, 807, -759, -759, -759, -759, -759, 0, 0, - 807, 333, 334, 335, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 0, 0, 122, 118, 346, 347, - 118, -759, 0, 0, 0, 0, 806, 807, 0, 0, - 806, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 806, 0, 0, -759, - -759, 348, 0, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 85, 0, 85, 0, 0, 0, 0, - 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, - 0, 806, 806, 807, 0, 85, 0, 121, 0, 121, - 0, 0, 0, 0, 0, 0, -759, -759, 0, 0, - 0, 233, -759, 0, -759, 0, -759, 0, 0, 121, - 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, - 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, - 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 118, 807, 0, - 118, 85, 807, 0, 0, 85, 532, 0, 0, 0, - 0, 0, 0, 532, 532, 0, 0, 0, 807, 532, - 532, 0, 0, 0, 0, 121, 0, 0, 1007, 121, - 121, 0, 118, 0, 0, 0, 0, 121, 121, 0, - 0, 118, 0, 121, 121, 0, 0, 0, 0, 85, - 0, 0, 85, 807, 807, 0, 0, 0, 0, 0, + 124, 294, 260, 365, 583, 308, 412, 330, 203, 235, + 838, 205, 221, 221, 240, 410, 291, 536, 434, 841, + 215, 215, 372, 367, 367, 597, 125, 367, 203, 308, + 651, 205, 282, 747, 89, 474, 89, 629, 281, 476, + 301, 998, 1000, 309, 569, 1141, 577, 317, 222, 222, + 238, 270, 241, 272, 276, 1107, 405, 571, 282, 203, + 369, 754, 735, 373, 712, 320, 495, 497, 1115, 1135, + 302, 282, 282, 282, 681, 1164, 580, 629, -112, 265, + 1166, 1107, -107, 1049, 462, 89, 89, 1196, 374, 283, + 1066, 1199, 611, 612, 615, 827, 221, 3, 791, 203, + 222, 333, -113, 529, 215, 716, -116, 236, -643, 569, + 242, 577, 237, 999, 1001, 283, 361, 73, -116, 73, + -84, 580, 626, 222, 222, 1035, 1036, 222, 379, 390, + 390, 847, 222, 315, 316, -112, 430, 219, 229, 643, + -98, 852, 622, 1219, 362, 409, 256, 1057, 1058, 1059, + 622, -120, 1121, 525, 422, 234, 950, 305, 260, 306, + 356, 357, 358, 954, 318, 458, 643, 663, 446, 267, + 448, 237, 1120, 227, 227, 1141, 826, 654, -119, 1164, + 323, 1221, 827, -107, 1067, 872, 529, 529, 305, 851, + 306, 1135, 964, 456, 879, 308, -112, 485, 1115, -103, + -118, 1107, -118, -107, 480, -731, -107, 667, 260, 909, + -107, 319, 271, 275, 305, 1145, 306, 884, 1107, 427, + 664, 408, 676, -104, 297, 427, 221, -107, 221, -731, + 773, 445, 1095, 465, 215, 434, 215, 215, 733, 629, + 124, 89, 367, 367, 367, 367, 1122, 510, 511, 237, + 968, 1046, 479, -731, 464, 282, -116, 227, -116, 305, + 668, 306, 222, -523, 222, 222, 1071, 244, 222, 662, + 222, 662, -111, 643, 89, 317, 89, 260, 505, 506, + 507, 508, 703, 643, 724, 265, 973, 975, 711, 89, + 715, 89, 447, 592, 734, 298, 1171, 995, 299, -110, + 477, 975, 975, 367, 282, -113, 884, 308, 912, 1146, + 527, 1204, 283, -115, 1097, 949, 1098, 1188, 594, 584, + 466, 586, 522, -109, 468, -732, 595, 522, 520, 972, + 596, 504, -117, 531, -112, -732, -112, -120, -118, 585, + -118, 89, 222, 222, 222, 222, 89, 222, 222, 300, + 622, 435, 622, 438, 265, -114, 1144, 73, 222, 237, + 89, 283, 445, 537, 889, 575, 587, 569, 215, 577, + 810, 812, 460, -119, 873, 874, 817, 819, 964, 326, + 778, 234, 319, 1068, -115, 327, 964, 227, 964, 227, + 449, 823, 318, 60, 1076, 884, 222, 233, 89, -644, + 450, 451, 89, 222, 89, 331, 480, 1082, 1083, -117, + 1109, 575, 890, 752, 744, 891, 531, 531, 222, -114, + 1093, 1116, 842, 876, 73, 846, -113, 445, 488, 509, + 575, 1144, 763, 215, -106, 1144, 1129, 763, 637, 853, + 427, 1162, 427, -113, 1136, -113, 537, 537, 315, 316, + 480, 688, 203, -108, 414, 205, 529, 282, 575, 338, + 339, 222, 961, 529, 529, 929, 629, 929, 926, 529, + 529, -635, -106, 488, 929, -120, -105, -120, 992, 993, + 910, 489, 445, 490, 491, 575, 1218, 1144, 215, 416, + 1022, 630, 927, -643, 236, 895, 632, 89, 576, 634, + -635, 282, 636, 425, 1119, -634, 349, 350, 964, 418, + 964, -119, 488, -119, 283, 964, 222, 964, 646, 714, + -112, 727, -115, 648, -115, 423, 493, 994, 490, 491, + 708, 618, 710, 1008, -634, 1238, 736, 431, 1010, 904, + -103, 744, 905, -636, -108, 907, 965, -117, 424, -117, + -746, 1208, 911, 237, 964, 914, 694, -114, 283, -114, + -644, 1200, 929, 576, 701, 493, 1214, 490, 491, 433, + 751, 975, -636, -106, 753, 702, 690, 707, 453, 622, + 1179, 680, 623, 1022, 1101, -637, 595, -113, 529, 445, + 875, 576, 575, -106, 695, 215, -106, 415, 740, 445, + -106, -639, 575, 741, 488, 215, 480, -104, -638, 702, + -353, -640, 230, 89, -637, 89, 1015, 203, 576, 488, + 205, 427, -629, 222, -120, 282, -632, 649, 488, 1032, + -639, 233, -105, 222, 606, 89, 222, -638, -353, -353, + -640, 702, 333, 859, -111, -108, 432, 1033, 961, 695, + -746, -629, 961, 1043, 237, -632, 961, 282, 961, 490, + 491, 367, 849, 607, 827, -108, 719, 988, -108, 1022, + 222, 1022, -108, -120, 490, 491, 848, 695, 988, 988, + 459, 494, 283, 490, 491, 445, 531, -353, 575, 814, + 762, 215, 361, 531, 531, 858, 821, 850, 463, 531, + 531, 522, 693, 825, 831, 765, 837, -119, 837, 1112, + 699, 89, -83, 1077, 283, 89, 537, 800, 469, 222, + 362, 363, 475, 537, 537, 576, 1159, -110, 459, 537, + 537, 1078, 965, -105, 470, 576, 1133, 78, 203, 78, + 965, 471, 965, 415, 699, 980, 478, 695, 427, 488, + 496, 78, 78, -105, 748, -119, -105, 695, -728, 89, + -105, 222, 89, 482, 921, 869, 367, 869, 643, 364, + -120, 502, 1022, 1022, 514, 693, 699, 900, 961, 1154, + 961, -115, 902, 488, 913, 961, 473, 961, 78, 78, + 750, 361, 854, 471, 772, 925, 488, 988, 774, 981, + -629, 695, 903, 78, 490, 491, 749, 863, 361, 528, + 695, 800, 800, 861, 589, 1111, 971, -310, 531, 362, + 428, 576, 899, 1177, 961, 503, 78, 78, -629, -629, + 78, 832, 827, -117, 273, 78, 362, 457, 490, 491, + -114, 1148, 1111, 697, 593, -310, -310, 698, 537, 493, + 1009, 490, 491, -729, 1148, 816, 1194, 598, 361, 1014, + 89, 988, 965, 237, 965, 89, 222, 631, 429, 965, + -115, 965, 282, 640, -117, -728, 673, -629, 1160, 1161, + -728, 89, -114, 1211, 1044, 429, 362, 483, 89, 970, + 488, 333, 887, 888, -310, -632, 633, -732, 635, 89, + -98, 641, 89, 670, 679, 800, 800, 915, 965, 916, + 917, 918, 919, 695, 800, 800, 800, 650, 1087, -283, + 800, 800, 1073, -632, -632, 678, -641, 682, 683, 1004, + 704, 697, 684, 89, 709, 484, 282, 1031, 1079, 1031, + 1031, 960, 89, 660, 78, 490, 491, 996, 354, 355, + 356, 357, 358, -642, -641, -641, 1016, 1088, -115, 1090, + 716, 1031, 1031, 1031, 719, 78, 768, 78, 78, 698, + -729, 78, -632, 78, 816, -729, -284, 78, -106, 78, + 970, -642, -642, 764, 809, 417, 1023, 1024, 419, 420, + 421, -301, 78, 1055, 78, 766, -117, 1124, 815, 695, + 934, -114, 934, -641, 361, 800, 827, 831, 361, 934, + 855, 959, 837, 800, 862, 1038, -108, 1041, 866, -301, + -301, -105, -285, 695, 695, 880, 282, 883, 969, 1065, + -642, -311, 362, 590, 884, 886, 362, 600, 897, 800, + 89, -286, 89, 1025, 78, 78, 78, 78, 78, 78, + 78, 78, 781, 1026, 1080, 1081, -735, 1029, 488, -311, + -311, 78, 1034, 78, 801, 1037, 78, 1039, -301, 970, + 1040, 1180, 1042, 1050, 361, 1051, 1103, 89, 1052, 1056, + 89, 591, 1064, 1126, 445, 601, 707, 575, 837, 1060, + 215, 1062, 367, 367, 1072, 800, 1074, 934, -735, 78, + 1075, 78, 362, 686, 521, 78, 78, 78, -311, 534, + 1031, 665, 1114, 490, 491, 1118, 1084, 361, 222, 826, + 1102, 78, 1104, 614, 616, 1125, -735, -735, 1202, 1203, + 1130, 1031, 1061, 1063, 1142, 1134, 1147, 1137, 361, 1167, + 614, 616, 1169, 1033, 1172, 362, 1085, 1174, 1178, 78, + 78, 687, 1181, 89, 89, 1182, 1163, 920, 801, 801, + 1184, -731, 1195, 1189, 78, 1191, 362, 1131, 644, 1197, + 800, 934, 1198, -735, 800, -735, 921, 695, -731, 1168, + 1170, 1235, 934, 1205, 1206, 1173, 1212, 1175, -732, 1176, + 800, 1113, 222, 222, 1086, 455, 1113, 959, 1223, 1228, + 78, 647, 619, 621, 645, 959, 394, 925, 926, 377, + 360, 273, 739, 829, 969, 601, 1100, 1158, 1113, 78, + 576, 1165, 969, 870, 969, 800, 800, 757, 758, 956, + 759, 989, 927, 837, 1217, 860, 672, 46, 47, 518, + 1239, 1094, 1207, 1149, 1209, 1150, 1151, 991, 621, 1210, + 990, 273, 801, 801, 1157, 1089, 413, 1213, 406, 1215, + 666, 801, 801, 801, 89, 1045, 1216, 801, 801, 100, + 915, 100, 916, 917, 918, 919, 931, 1110, 1222, 1224, + 1225, 1226, 1132, 100, 100, 915, 1128, 916, 917, 918, + 919, 920, 1108, 1183, 1185, 0, 0, 677, 1233, 1190, + 0, 1192, 1193, 1234, 1236, 310, 311, 312, 313, 314, + 921, 0, 934, 0, 0, 0, 78, 0, 78, 1016, + 100, 100, 0, 0, 922, 1017, 78, 959, 915, 0, + 916, 917, 918, 919, 923, 100, 78, 0, 78, 78, + 924, 925, 926, 0, 969, 1138, 969, 916, 917, 918, + 919, 969, 801, 969, 0, 802, 0, 0, 100, 100, + 801, 0, 100, 0, 0, 0, 927, 100, 0, 928, + 0, 0, 0, 78, 41, 42, 43, 44, 1227, 1229, + 1230, 1231, 0, 0, 0, 0, 801, 333, 0, 0, + 969, 0, 0, 0, 0, 0, 742, 0, 743, 1237, + 811, 813, 0, 0, 346, 347, 818, 820, 0, 0, + 0, 621, 333, 273, 78, 0, 0, 0, 78, 78, + 0, 0, 78, 0, 0, 0, 78, 78, 0, 346, + 347, 0, 78, 78, 0, 915, 0, 916, 917, 918, + 919, 920, 801, 353, 354, 355, 356, 357, 358, 802, + 802, 0, 0, 0, 811, 813, 771, 818, 820, 0, + 921, 0, 78, 0, 78, 78, 803, 0, 0, 354, + 355, 356, 357, 358, 0, 0, 100, 0, 0, 0, + 0, 0, 0, 822, 923, 0, 0, 0, 0, 0, + 924, 925, 926, 0, 0, 0, 0, 100, 844, 100, + 100, 0, 0, 100, 0, 100, 0, 0, 0, 100, + 0, 100, 0, 0, 0, 0, 927, 801, 0, 928, + 0, 801, 0, 0, 100, 896, 100, 0, 0, 0, + 0, 804, 0, 0, 0, 0, 237, 801, 0, 0, + 0, 0, 0, 802, 802, 0, 0, 0, 871, 0, + 0, 78, 802, 802, 802, 0, 0, 0, 802, 802, + 803, 803, 0, 78, 0, 119, 0, 119, 78, 78, + 896, 0, 801, 801, 0, 0, 100, 100, 100, 100, + 100, 100, 100, 100, 78, 0, 0, 0, 0, 0, + 0, 78, 0, 100, 0, 100, 0, 0, 100, 0, + 0, 0, 78, 0, 0, 78, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 119, 0, 0, + 285, 908, 0, 0, 0, 804, 804, 0, 0, 0, + 0, 100, 0, 100, 0, 0, 78, 100, 100, 100, + 273, 0, 0, 802, 0, 78, 285, 0, 0, 0, + 0, 802, 0, 100, 803, 803, 0, 0, 0, 382, + 392, 392, 392, 803, 803, 803, 0, 0, 0, 803, + 803, 0, 0, 0, 0, 0, 0, 802, 0, 0, + 0, 100, 100, 0, 0, 0, 0, 1013, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, + 915, 0, 916, 917, 918, 919, 920, 0, 0, 0, + 0, 0, 0, 0, 0, 1028, 0, 0, 0, 804, + 804, 0, 0, 0, 0, 921, 0, 0, 804, 804, + 804, 0, 100, 802, 804, 804, 0, 0, 0, 0, + 0, 0, 0, 78, 0, 78, 0, 0, 0, 923, + 0, 100, 0, 0, 803, 924, 925, 926, 0, 0, + 0, 915, 803, 916, 917, 918, 919, 920, 0, 0, + 0, 0, 119, 0, 0, 0, 0, 332, 0, 0, + 78, 927, 0, 78, 928, 0, 921, 0, 803, 0, + 1096, 0, 0, 0, 0, 0, 952, 0, 0, 0, + 0, 0, 0, 1105, 0, 119, 0, 119, 802, 0, + 923, 0, 802, 0, 0, 0, 924, 925, 926, 804, + 119, 78, 119, 0, 0, 0, 0, 804, 802, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 927, 285, 803, 928, 346, 347, 100, 0, + 100, 0, 0, 804, 0, 0, 78, 78, 100, 0, + 0, 0, 0, 802, 802, 0, 0, 0, 100, 0, + 100, 100, 119, 0, 0, 0, 0, 119, 0, 348, + 0, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 119, 285, 0, 0, 78, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 0, 0, 804, + 0, 0, 915, 0, 916, 917, 918, 919, 920, 803, + 0, 0, 0, 803, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 119, 0, 119, 0, 921, 0, 803, + 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, + 100, 100, 0, 0, 100, 122, 0, 122, 100, 100, + 0, 923, 0, 0, 100, 100, 0, 78, 925, 926, + 0, 0, 0, 0, 803, 803, 0, 0, 0, 0, + 0, 0, 0, 0, 804, 0, 0, 0, 804, 0, + 0, 0, 0, 927, 100, 0, 100, 100, 333, 0, + 0, 0, 0, 0, 804, 0, 122, 122, 0, 0, + 286, 0, 0, 0, 0, 346, 347, 118, 0, 118, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, 286, 0, 0, 804, + 804, 0, 0, 0, 0, 285, 0, 0, 0, 383, + 393, 393, 351, 352, 353, 354, 355, 356, 357, 358, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, + 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 0, 0, 0, 0, 0, 285, + 0, 0, 0, 0, 0, 100, 0, 0, 284, 0, + 100, 100, 23, 24, 25, 26, 0, 0, 0, 0, + 0, 381, 391, 391, 391, 0, 100, 0, 32, 33, + 34, 781, 0, 100, 0, 782, 0, 0, 41, 42, + 43, 44, 45, 0, 100, 0, 0, 100, 0, 0, + 0, 0, 0, 0, 119, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 783, + 784, 0, 122, 0, 0, 0, 119, 785, 100, 0, + 786, 0, 0, 787, 788, 0, 974, 100, 0, 789, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 122, 0, 122, 0, 0, + 0, 790, 0, 0, 0, 805, 0, 0, 279, 0, + 122, 0, 122, 285, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, + 0, 0, 0, 286, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 285, 119, 0, 0, 0, + 0, 0, 808, 0, 0, 0, 85, 118, 85, 118, + 0, 0, 122, 0, 0, 0, 0, 122, 0, 0, + 0, 0, 118, 0, 118, 100, 0, 100, 0, 0, + 0, 122, 286, 0, 538, 0, 0, 0, 0, 0, + 119, 0, 0, 119, 0, 284, 0, 0, 0, 805, + 805, 0, 0, 0, 0, 0, 0, 85, 85, 0, + 0, 0, 100, 0, 0, 100, 0, 0, 0, 122, + 0, 0, 0, 122, 118, 122, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 121, 0, 0, 121, 0, 0, 0, - 217, 217, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 391, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 118, 284, 0, 808, 808, 0, 0, + 378, 0, 0, 100, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 538, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 250, 253, 254, 255, 0, 0, 0, 217, - 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 303, 304, 0, 0, 0, 0, 532, 0, - 118, 0, 118, 0, 0, 0, 0, 0, 0, 0, - 85, 0, 0, 0, 0, 85, 0, 0, 0, 0, - 0, 0, 121, 0, 217, 0, 0, 0, 0, 0, - 0, 85, 0, 0, 121, 0, 0, 118, 85, 121, - 118, 0, 0, 391, 0, 0, 0, 0, 0, 85, - 0, 0, 85, 0, 0, 121, 0, 0, 0, 0, - 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 121, 0, 0, 121, 0, 0, 0, - 1005, 0, 0, 0, 85, 0, 0, 0, 0, 0, - 0, 0, 0, 85, 23, 24, 25, 26, 0, 0, + 0, 118, 0, 0, 0, 118, 0, 118, 100, 100, + 0, 119, 0, 805, 805, 0, 119, 0, 0, 0, + 0, 0, 805, 805, 805, 0, 0, 0, 805, 805, + 0, 0, 119, 0, 0, 0, 0, 0, 122, 119, + 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, + 119, 0, 0, 119, 0, 286, 0, 0, 0, 0, + 808, 808, 0, 0, 0, 0, 0, 0, 0, 808, + 808, 808, 0, 0, 0, 808, 808, 0, 0, 0, + 1006, 0, 0, 85, 119, 0, 0, 0, 0, 0, + 0, 0, 0, 119, 0, 0, 0, 0, 0, 286, + 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 121, 805, 121, 0, 85, 284, 85, 100, + 0, 805, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 85, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 392, 0, 0, 805, 0, 0, + 0, 0, 0, 0, 122, 0, 122, 0, 0, 0, + 808, 284, 0, 121, 121, 0, 0, 0, 808, 0, + 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 85, 0, + 0, 119, 0, 119, 808, 0, 0, 0, 0, 0, + 0, 0, 85, 805, 0, 532, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 0, 118, 0, + 0, 0, 0, 286, 0, 0, 0, 0, 119, 0, + 0, 119, 761, 0, 392, 0, 0, 0, 118, 0, + 85, 0, 0, 0, 85, 0, 85, 0, 0, 0, + 808, 0, 122, 0, 0, 286, 122, 538, 0, 0, + 0, 0, 0, 0, 538, 538, 0, 0, 0, 0, + 538, 538, 0, 0, 0, 0, 0, 0, 805, 0, + 0, 0, 805, 0, 0, 284, 0, 0, 532, 532, + 0, 0, 0, 0, 23, 24, 25, 26, 805, 0, + 122, 0, 0, 122, 119, 119, 0, 0, 0, 0, + 32, 33, 34, 0, 118, 0, 0, 284, 118, 121, + 41, 42, 43, 44, 45, 808, 0, 0, 0, 808, + 0, 0, 0, 805, 805, 0, 0, 0, 0, 85, + 0, 0, 0, 0, 0, 808, 0, 0, 0, 0, + 0, 0, 121, 0, 121, 0, 0, 0, 0, 0, + 0, 0, 118, 0, 0, 118, 0, 121, 0, 121, + 0, 789, 59, 60, 61, 62, 63, 64, 65, 66, + 808, 808, 0, 0, 0, 0, 0, 0, 0, 538, + 0, 0, 0, 333, -758, -758, -758, -758, 338, 339, + 279, 122, -758, -758, 0, 0, 122, 0, 0, 0, + 346, 347, 0, 0, 0, 119, 0, 0, 0, 121, + 0, 0, 122, 0, 121, 0, 0, 0, 806, 122, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, - 32, 33, 34, 118, 118, 0, 0, 121, 0, 0, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 217, 0, 0, 217, 217, 217, 0, 303, 0, + 122, 121, 0, 122, 0, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 85, 0, 85, 0, 0, + 0, 0, 0, 118, 0, 0, 0, 0, 118, 0, + 1007, 0, 0, 0, 122, 0, 121, 85, 0, 0, + 121, 0, 121, 122, 118, 0, 0, 0, 0, 0, + 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, + 807, 0, 118, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 217, 0, 217, 217, 0, 0, + 0, 0, 806, 806, 121, 121, 0, 0, 0, 0, + 0, 0, 1005, 0, 393, 0, 118, 0, 0, 0, + 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 85, 532, 0, + 0, 0, 0, 0, 0, 532, 532, 0, 0, 0, + 0, 532, 532, 0, 0, 121, 0, 0, 0, 0, + 0, 122, 0, 122, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 807, 807, 391, 0, 0, 0, + 0, 85, 0, 0, 85, 333, 334, 335, 336, 337, + 338, 339, 340, 0, 342, 343, 806, 806, 122, 0, + 0, 122, 346, 347, 393, 806, 806, 806, 0, 0, + 0, 806, 806, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 118, 0, 118, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 789, 59, 60, 61, 62, 63, 64, 65, 66, - 0, 333, 334, 335, 336, 337, 338, 339, 340, 0, - 342, 343, 85, 0, 85, 0, 0, 0, 346, 347, - 279, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 121, 0, 121, 0, - 0, 0, 0, 0, 118, 0, 0, 0, 0, 85, - 0, 0, 85, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 0, 0, 0, 0, 0, 0, 0, - 217, 0, 0, 121, 0, 533, 121, 540, 541, 542, - 543, 544, 0, 0, 545, 546, 547, 548, 549, 550, - 551, 552, 553, 0, 0, 554, 555, 556, 557, 558, - 559, 560, 561, 562, 563, 0, 0, 0, 217, 0, + 118, 0, 0, 118, 0, 0, 391, 0, 807, 807, + 532, 121, 0, 121, 122, 122, 0, 807, 807, 807, + 0, 0, 85, 807, 807, 0, 0, 85, 0, 0, + 0, 0, 0, 121, 217, 217, 806, 0, 0, 0, + 0, 0, 0, 85, 806, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 0, 85, 0, 250, 253, 254, 255, + 806, 0, 0, 217, 217, 0, 118, 118, 0, 0, + 0, 0, 0, 0, 0, 0, 303, 304, 0, 0, + 0, 1003, 0, 0, 0, 85, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, 0, 0, 807, 121, + 0, 0, 0, 121, 121, 0, 807, 0, 217, 0, + 0, 121, 121, 0, 0, 122, 806, 121, 121, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, + 0, 0, 807, 0, 0, 0, 0, -757, -757, -757, + 0, 0, -757, -757, -757, 0, -757, 121, 0, 0, + 121, 0, 0, 0, -757, -757, -757, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -757, -757, 0, -757, + -757, -757, -757, -757, 0, 0, 0, 118, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 807, 0, + 0, 806, 85, 0, 85, 806, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 806, 0, 0, 0, 217, 0, 0, 217, 217, + 217, 0, 303, 0, 0, -757, -757, 0, 0, 85, + 0, 0, 85, 0, 0, 0, 121, 0, 217, 0, + 217, 217, 0, 0, 0, 0, 806, 806, 121, -757, + 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 807, 0, 0, 0, 807, 0, 121, + 0, 0, -757, -757, 0, 0, 121, 233, -757, 0, + -757, 0, -757, 807, 0, 0, 0, 121, 0, 0, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 0, 0, 0, - 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 0, 0, 121, - 121, 346, 347, 0, 0, 0, 0, 0, 613, 613, - 0, 0, 0, 0, 0, 0, 0, 613, 217, 217, - 0, 0, 0, 217, 0, 613, 613, 217, 0, 0, - 0, 0, 0, 255, 348, 0, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 0, 0, 639, 0, - 0, 0, 0, 613, 0, 0, 0, 0, 0, 0, - 237, 0, 0, 0, 217, 0, 0, 217, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, - 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 669, 333, 334, 335, - 336, 337, 338, 339, 340, 341, 342, 343, -760, -760, - 121, 0, 0, 217, 346, 347, 0, 0, 0, 0, - 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, - -736, -736, -736, 0, 0, 0, -736, -736, 0, -736, - 0, 0, 0, 0, 0, 0, 0, -736, -736, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, -736, - -736, 0, -736, -736, -736, -736, -736, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, - -736, 0, 0, 0, 0, 217, 0, 0, 0, -736, - -736, -736, -736, -736, -736, -736, -736, -736, -736, -736, - -736, -736, 217, 0, 217, 0, -736, -736, -736, -736, - 0, 691, 0, 0, 0, 0, 0, 217, 0, 217, + 0, 0, 0, 0, 0, 0, 0, 0, 807, 807, + 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 0, 0, 0, 217, 0, 0, 0, 0, 533, + 0, 540, 541, 542, 543, 544, 0, 0, 545, 546, + 547, 548, 549, 550, 551, 552, 553, 0, 0, 554, + 555, 556, 557, 558, 559, 560, 561, 562, 563, 0, + 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -736, 0, 0, 0, 0, 0, -116, -736, - 0, -736, -736, -736, -736, -736, -736, -736, -736, -736, - -736, 0, 0, 0, 0, -736, -736, -736, -107, 0, - 0, -736, 217, -736, 0, -736, 0, 0, 613, 775, - 0, 217, 0, 0, 0, 613, 613, 0, 0, 0, - 0, 613, 613, 0, 23, 24, 25, 26, 0, 217, + 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 0, + 0, 0, 0, 346, 347, 0, 85, 0, 0, 0, + 0, 0, 613, 613, 0, 0, 0, 0, 121, 0, + 121, 613, 217, 217, 0, 0, 0, 217, 0, 613, + 613, 217, 0, 0, 0, 0, 348, 255, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 0, 0, + 0, 0, 639, 0, 0, 121, 0, 613, 121, 0, + 0, 0, 237, 0, 0, 0, 0, 0, 217, 0, + 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 33, 34, 781, 217, 0, 0, 782, 0, 981, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 922, 613, - 613, 0, 613, 613, 0, 0, 0, 0, 0, 0, - 0, 783, 784, 0, 0, 0, 0, 0, 0, 785, - 0, 0, 786, 0, 217, 787, 788, 0, 975, 926, - 0, 789, 59, 999, 61, 62, 63, 64, 65, 66, + 669, 333, 334, 335, 336, 337, 338, 339, 340, 341, + 342, 343, -758, -758, 0, 0, 0, 217, 346, 347, + 0, 0, 0, 0, 0, 0, -735, 0, 0, 0, + 0, 121, 121, 0, -735, -735, -735, 0, 0, 0, + -735, -735, 0, -735, 0, 0, 0, 0, 0, 0, + 0, -735, -735, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, -735, -735, 0, -735, -735, -735, -735, + -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, + 0, 0, 0, 0, -735, 0, 0, 0, 0, 217, + 0, 0, 0, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, -735, -735, -735, 217, 0, 217, 0, + -735, -735, -735, -735, 0, 691, 0, 0, 0, 0, + 0, 217, 0, 217, 0, 0, 0, 0, 0, 0, + 0, 0, 121, 0, 0, 0, -735, 0, 0, 0, + 0, 0, -116, -735, 0, -735, -735, -735, -735, -735, + -735, -735, -735, -735, -735, 0, 0, 0, 0, -735, + -735, -735, -107, 0, 0, -735, 217, -735, 0, -735, + 0, 0, 613, 775, 0, 217, 0, 0, 0, 613, + 613, 0, 0, 0, 0, 613, 613, 0, -629, 0, + 0, 0, 0, 217, 0, 0, -629, -629, -629, 0, + 0, -629, -629, -629, 0, -629, 0, 0, 217, 0, + 0, 0, 0, -629, 0, -629, -629, -629, 0, 0, + 0, 0, 0, 0, 0, -629, -629, 0, -629, -629, + -629, -629, -629, 613, 613, 0, 613, 613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 790, 0, 0, 0, 0, 0, 0, - 279, 0, 0, 895, 0, 0, 0, 0, 0, 0, - 613, 0, -759, 4, 0, 5, 6, 7, 8, 9, - 0, 0, 0, 10, 11, 0, 0, 0, 12, 0, - 13, 14, 15, 16, 17, 18, 19, 217, 0, 0, - 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 27, 0, 0, 0, 613, 217, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, + 0, 0, 0, 0, 0, 0, -629, 0, 217, 0, + 0, 0, 0, 0, 0, -629, -629, -629, -629, -629, + -629, -629, -629, -629, -629, -629, -629, -629, 0, 0, + 0, 0, -629, -629, -629, -629, 0, -629, -629, 0, + 0, 0, 0, 0, -629, 0, 0, 894, 0, 0, + 0, 0, 0, 0, 613, 0, 0, 0, -629, 0, + 0, -629, 0, 0, -629, -629, -629, -629, -629, -629, + -629, -629, -629, -629, -629, -629, -629, 0, 0, 0, + 0, 217, -629, -629, -629, 0, 0, -629, -629, -629, + 0, -629, 0, 0, 0, 0, 0, 0, 0, 613, + 217, 0, 0, -757, 4, 0, 5, 6, 7, 8, + 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, + 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, + 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, + 0, 0, 27, 0, 0, 0, 0, 217, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 0, 217, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 51, 217, 0, 0, 0, 0, 0, - 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, - 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 0, 217, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, + 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, + 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 67, 68, 69, 0, 0, 0, 0, -736, 0, - 0, 0, 0, -759, 0, -759, -736, -736, -736, 0, - 0, -736, -736, -736, 0, -736, 0, 0, 0, 0, - 0, 0, 0, -736, -736, -736, -736, -736, 0, 0, - 0, 0, 0, 0, 0, -736, -736, 0, -736, -736, - -736, -736, -736, 0, 0, 0, 0, 0, 217, 0, - 0, 0, 0, 333, -760, -760, -760, -760, 338, 339, - 0, 217, -760, -760, 0, 0, -736, 0, 0, 0, - 346, 347, 0, 0, 0, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, -736, 0, 0, - 0, 0, -736, -736, -736, -736, 0, 745, -736, 0, - 0, 0, 0, 0, -736, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 0, 0, 0, -736, 0, - 0, -736, 217, 0, -116, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, 0, 0, 0, - 0, -736, -736, -736, -736, -630, 0, -736, -736, -736, - 0, -736, 0, -630, -630, -630, 0, 0, -630, -630, - -630, 0, -630, 0, 0, 0, 0, 685, 0, 0, - -630, 0, -630, -630, -630, 0, 0, 0, 0, 0, - 0, 0, -630, -630, 0, -630, -630, -630, -630, -630, + 0, 0, 67, 68, 69, 0, 0, 0, 0, 0, + 217, -735, 0, 0, -757, 0, -757, 0, 0, -735, + -735, -735, 0, 217, -735, -735, -735, 0, -735, 0, + 0, 0, 0, 0, 0, 0, -735, -735, -735, -735, + -735, 0, 0, 0, 0, 0, 0, 0, -735, -735, + 0, -735, -735, -735, -735, -735, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, + 335, 336, 337, 338, 339, 0, 0, 342, 343, -735, + 0, 0, 0, 0, 217, 346, 347, 0, -735, -735, + -735, -735, -735, -735, -735, -735, -735, -735, -735, -735, + -735, 0, 0, 0, 0, -735, -735, -735, -735, 0, + 745, -735, 0, 0, 0, 0, 0, -735, 0, 0, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 0, -735, 0, 0, -735, 0, 0, -116, -735, -735, + -735, -735, -735, -735, -735, -735, -735, -735, -735, -735, + 0, 0, 0, 0, -735, -735, -735, -735, -632, 0, + -735, -735, -735, 0, -735, 0, -632, -632, -632, 0, + 0, -632, -632, -632, 0, -632, 0, 0, 0, 0, + 685, 0, 0, -632, 0, -632, -632, -632, 0, 0, + 0, 0, 0, 0, 0, -632, -632, 0, -632, -632, + -632, -632, -632, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, -632, 0, 0, 0, + 346, 347, 0, 0, 0, -632, -632, -632, -632, -632, + -632, -632, -632, -632, -632, -632, -632, -632, 0, 0, + 0, 0, -632, -632, -632, -632, 0, -632, -632, 0, + 0, 0, 0, 348, -632, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 0, 0, 0, -632, 0, + 0, -632, -257, 0, -632, -632, -632, -632, -632, -632, + -632, -632, -632, -632, -632, -632, -632, 0, 0, 0, + 0, 0, -632, -632, -632, -736, 0, -632, -632, -632, + 0, -632, 0, -736, -736, -736, 0, 0, -736, -736, + -736, 0, -736, 0, 0, 0, 0, 685, 0, 0, + -736, -736, -736, -736, -736, 0, 0, 0, 0, 0, + 0, 0, -736, -736, 0, -736, -736, -736, -736, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, -630, 0, 0, 0, 346, 347, 0, - 0, 0, -630, -630, -630, -630, -630, -630, -630, -630, - -630, -630, -630, -630, -630, 0, 0, 0, 0, -630, - -630, -630, -630, 0, -630, -630, 0, 0, 0, 0, - 348, -630, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 0, 0, 0, -630, 0, 0, -630, -257, - 0, -630, -630, -630, -630, -630, -630, -630, -630, -630, - -630, -630, -630, -630, 0, 0, 0, 0, 0, -630, - -630, -630, -633, 0, -630, -630, -630, 0, -630, 0, - -633, -633, -633, 0, 0, -633, -633, -633, 0, -633, - 0, 0, 0, 0, 685, 0, 0, -633, 0, -633, - -633, -633, 0, 0, 0, 0, 0, 0, 0, -633, - -633, 0, -633, -633, -633, -633, -633, 0, 0, 0, + 343, 344, 345, -736, 0, 0, 0, 346, 347, 0, + 0, 0, -736, -736, -736, -736, -736, -736, -736, -736, + -736, -736, -736, -736, -736, 0, 0, 0, 0, -736, + -736, -736, -736, 0, 0, -736, 0, 0, 0, 0, + 348, -736, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 0, 0, 0, -736, 0, 0, -736, 0, + 0, 0, -736, -736, -736, -736, -736, -736, -736, -736, + -736, -736, -736, -736, 0, 0, 0, 0, -736, -736, + -736, -736, -737, 0, -736, -736, -736, 0, -736, 0, + -737, -737, -737, 0, 0, -737, -737, -737, 0, -737, + 0, 0, 0, 0, 0, 0, 0, -737, -737, -737, + -737, -737, 0, 0, 0, 0, 0, 0, 0, -737, + -737, 0, -737, -737, -737, -737, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - -633, 0, 0, 0, 346, 347, 0, 0, 0, -633, - -633, -633, -633, -633, -633, -633, -633, -633, -633, -633, - -633, -633, 0, 0, 0, 0, -633, -633, -633, -633, - 0, -633, -633, 0, 0, 0, 0, 348, -633, 349, + -737, 0, 0, 0, 346, 347, 0, 0, 0, -737, + -737, -737, -737, -737, -737, -737, -737, -737, -737, -737, + -737, -737, 0, 0, 0, 0, -737, -737, -737, -737, + 0, 0, -737, 0, 0, 0, 0, 348, -737, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 0, - 0, 0, -633, 0, 0, -633, 0, 0, -633, -633, - -633, -633, -633, -633, -633, -633, -633, -633, -633, -633, - -633, 0, 0, 0, 0, 0, -633, -633, -633, -737, - 0, -633, -633, -633, 0, -633, 0, -737, -737, -737, - 0, 0, -737, -737, -737, 0, -737, 0, 0, 0, - 0, 0, 0, 0, -737, -737, -737, -737, -737, 0, - 0, 0, 0, 0, 0, 0, -737, -737, 0, -737, - -737, -737, -737, -737, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, -737, 0, 0, - 0, 346, 347, 0, 0, 0, -737, -737, -737, -737, - -737, -737, -737, -737, -737, -737, -737, -737, -737, 0, - 0, 0, 0, -737, -737, -737, -737, 0, 0, -737, - 0, 0, 0, 0, 348, -737, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 0, 0, 0, -737, - 0, 0, -737, 0, 0, 0, -737, -737, -737, -737, - -737, -737, -737, -737, -737, -737, -737, -737, 0, 0, - 0, 0, -737, -737, -737, -737, -738, 0, -737, -737, - -737, 0, -737, 0, -738, -738, -738, 0, 0, -738, - -738, -738, 0, -738, 0, 0, 0, 0, 0, 0, - 0, -738, -738, -738, -738, -738, 0, 0, 0, 0, - 0, 0, 0, -738, -738, 0, -738, -738, -738, -738, - -738, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 337, 338, 339, 0, 0, - 342, 343, 0, 0, -738, 0, 0, 0, 346, 347, - 0, 0, 0, -738, -738, -738, -738, -738, -738, -738, - -738, -738, -738, -738, -738, -738, 0, 0, 0, 0, - -738, -738, -738, -738, 0, 0, -738, 0, 0, 0, - 0, 0, -738, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 0, 0, 0, -738, 0, 0, -738, - 0, 0, 0, -738, -738, -738, -738, -738, -738, -738, - -738, -738, -738, -738, -738, 0, 0, 0, 0, -738, - -738, -738, -738, -310, 0, -738, -738, -738, 0, -738, - 0, -310, -310, -310, 0, 0, -310, -310, -310, 0, - -310, 0, 0, 0, 0, 0, 0, 0, -310, 0, - -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, - -310, -310, 0, -310, -310, -310, -310, -310, 0, 0, + 0, 0, -737, 0, 0, -737, 0, 0, 0, -737, + -737, -737, -737, -737, -737, -737, -737, -737, -737, -737, + -737, 0, 0, 0, 0, -737, -737, -737, -737, -310, + 0, -737, -737, -737, 0, -737, 0, -310, -310, -310, + 0, 0, -310, -310, -310, 0, -310, 0, 0, 0, + 0, 0, 0, 0, -310, 0, -310, -310, -310, 0, + 0, 0, 0, 0, 0, 0, -310, -310, 0, -310, + -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, + 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, -310, 0, + 0, 0, 0, -310, -310, -310, -310, 0, 746, -310, + 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, + 0, 0, -310, 0, 0, -118, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, 0, 0, + 0, 0, 0, -310, -310, -310, -449, 0, -310, -310, + -310, 0, -310, 0, -449, -449, -449, 0, 0, -449, + -449, -449, 0, -449, 0, 0, 0, 0, 0, 0, + 0, -449, -449, -449, -449, 0, 0, 0, 0, 0, + 0, 0, 0, -449, -449, 0, -449, -449, -449, -449, + -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, - -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, -310, 0, 0, 0, 0, -310, -310, -310, - -310, 0, 746, -310, 0, 0, 0, 0, 0, -310, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -310, 0, 0, -310, 0, 0, -118, - -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, 0, 0, 0, 0, 0, -310, -310, -310, - -449, 0, -310, -310, -310, 0, -310, 0, -449, -449, - -449, 0, 0, -449, -449, -449, 0, -449, 0, 0, - 0, 0, 0, 0, 0, -449, -449, -449, -449, 0, - 0, 0, 0, 0, 0, 0, 0, -449, -449, 0, - -449, -449, -449, -449, -449, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -449, 0, - 0, 0, 0, 0, 0, 0, 0, -449, -449, -449, - -449, -449, -449, -449, -449, -449, -449, -449, -449, -449, - 0, 0, 0, 0, -449, -449, -449, -449, 0, 0, - -449, 0, 0, 0, 0, 0, -449, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -449, 0, 0, 0, 0, 0, 0, -449, 0, -449, - -449, -449, -449, -449, -449, -449, -449, -449, -449, 0, - 0, 0, 0, -449, -449, -449, -449, -302, 233, -449, - -449, -449, 0, -449, 0, -302, -302, -302, 0, 0, - -302, -302, -302, 0, -302, 0, 0, 0, 0, 0, - 0, 0, -302, 0, -302, -302, -302, 0, 0, 0, - 0, 0, 0, 0, -302, -302, 0, -302, -302, -302, - -302, -302, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -449, 0, 0, 0, 0, 0, + 0, 0, 0, -449, -449, -449, -449, -449, -449, -449, + -449, -449, -449, -449, -449, -449, 0, 0, 0, 0, + -449, -449, -449, -449, 0, 0, -449, 0, 0, 0, + 0, 0, -449, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -449, 0, 0, 0, + 0, 0, 0, -449, 0, -449, -449, -449, -449, -449, + -449, -449, -449, -449, -449, 0, 0, 0, 0, -449, + -449, -449, -449, -302, 233, -449, -449, -449, 0, -449, + 0, -302, -302, -302, 0, 0, -302, -302, -302, 0, + -302, 0, 0, 0, 0, 0, 0, 0, -302, 0, + -302, -302, -302, 0, 0, 0, 0, 0, 0, 0, + -302, -302, 0, -302, -302, -302, -302, -302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -302, 0, 0, 0, 0, - 0, 0, 0, 0, -302, -302, -302, -302, -302, -302, - -302, -302, -302, -302, -302, -302, -302, 0, 0, 0, - 0, -302, -302, -302, -302, 0, 0, -302, 0, 0, - 0, 0, 0, -302, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -302, 0, 0, - -302, 0, 0, 0, -302, -302, -302, -302, -302, -302, - -302, -302, -302, -302, -302, -302, 0, 0, 0, 0, - 0, -302, -302, -302, -759, 0, -302, -302, -302, 0, - -302, 0, -759, -759, -759, 0, 0, -759, -759, -759, - 0, -759, 0, 0, 0, 0, 0, 0, 0, -759, - -759, -759, -759, 0, 0, 0, 0, 0, 0, 0, - 0, -759, -759, 0, -759, -759, -759, -759, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -302, 0, 0, 0, 0, 0, 0, 0, 0, + -302, -302, -302, -302, -302, -302, -302, -302, -302, -302, + -302, -302, -302, 0, 0, 0, 0, -302, -302, -302, + -302, 0, 0, -302, 0, 0, 0, 0, 0, -302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, - 0, -759, -759, -759, -759, -759, -759, -759, -759, -759, - -759, -759, -759, -759, 0, 0, 0, 0, -759, -759, - -759, -759, 0, 0, -759, 0, 0, 0, 0, 0, - -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, - 0, -759, 0, -759, -759, -759, -759, -759, -759, -759, - -759, -759, -759, 0, 0, 0, 0, -759, -759, -759, - -759, -317, 233, -759, -759, -759, 0, -759, 0, -317, - -317, -317, 0, 0, -317, -317, -317, 0, -317, 0, - 0, 0, 0, 0, 0, 0, -317, 0, -317, -317, - 0, 0, 0, 0, 0, 0, 0, 0, -317, -317, - 0, -317, -317, -317, -317, -317, 0, 0, 0, 0, + 0, 0, 0, -302, 0, 0, -302, 0, 0, 0, + -302, -302, -302, -302, -302, -302, -302, -302, -302, -302, + -302, -302, 0, 0, 0, 0, 0, -302, -302, -302, + -757, 0, -302, -302, -302, 0, -302, 0, -757, -757, + -757, 0, 0, -757, -757, -757, 0, -757, 0, 0, + 0, 0, 0, 0, 0, -757, -757, -757, -757, 0, + 0, 0, 0, 0, 0, 0, 0, -757, -757, 0, + -757, -757, -757, -757, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, - 0, 0, 0, 0, 0, 0, 0, 0, -317, -317, - -317, -317, -317, -317, -317, -317, -317, -317, -317, -317, - -317, 0, 0, 0, 0, -317, -317, -317, -317, 0, - 0, -317, 0, 0, 0, 0, 0, -317, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, + 0, 0, 0, 0, 0, 0, 0, -757, -757, -757, + -757, -757, -757, -757, -757, -757, -757, -757, -757, -757, + 0, 0, 0, 0, -757, -757, -757, -757, 0, 0, + -757, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -317, 0, 0, 0, 0, 0, 0, -317, 0, - -317, -317, -317, -317, -317, -317, -317, -317, -317, -317, - 0, 0, 0, 0, 0, -317, -317, -317, -736, 230, - -317, -317, -317, 0, -317, 0, -736, -736, -736, 0, - 0, 0, -736, -736, 0, -736, 0, 0, 0, 0, - 0, 0, 0, -736, -736, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -736, -736, 0, -736, -736, - -736, -736, -736, 0, 0, 0, 0, 0, 0, 0, + -757, 0, 0, 0, 0, 0, 0, -757, 0, -757, + -757, -757, -757, -757, -757, -757, -757, -757, -757, 0, + 0, 0, 0, -757, -757, -757, -757, -317, 233, -757, + -757, -757, 0, -757, 0, -317, -317, -317, 0, 0, + -317, -317, -317, 0, -317, 0, 0, 0, 0, 0, + 0, 0, -317, 0, -317, -317, 0, 0, 0, 0, + 0, 0, 0, 0, -317, -317, 0, -317, -317, -317, + -317, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, - 0, 0, 0, 0, 0, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, -736, 0, 0, - 0, 0, -736, -736, -736, -736, 0, 691, 0, 0, + 0, 0, 0, 0, 0, -317, 0, 0, 0, 0, + 0, 0, 0, 0, -317, -317, -317, -317, -317, -317, + -317, -317, -317, -317, -317, -317, -317, 0, 0, 0, + 0, -317, -317, -317, -317, 0, 0, -317, 0, 0, + 0, 0, 0, -317, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -317, 0, 0, + 0, 0, 0, 0, -317, 0, -317, -317, -317, -317, + -317, -317, -317, -317, -317, -317, 0, 0, 0, 0, + 0, -317, -317, -317, -735, 230, -317, -317, -317, 0, + -317, 0, -735, -735, -735, 0, 0, 0, -735, -735, + 0, -735, 0, 0, 0, 0, 0, 0, 0, -735, + -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -735, -735, 0, -735, -735, -735, -735, -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, - 0, 0, 0, 0, -116, -736, 0, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, 0, 0, 0, - 0, -736, -736, -736, -736, -310, 0, -736, 0, -736, - 0, -736, 0, -310, -310, -310, 0, 0, 0, -310, - -310, 0, -310, 0, 0, 0, 0, 0, 0, 0, - -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -310, -310, 0, -310, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -735, 0, 0, 0, 0, 0, 0, 0, + 0, -735, -735, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, -735, 0, 0, 0, 0, -735, -735, + -735, -735, 0, 691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, - 0, 0, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, -310, -310, -310, 0, 0, 0, 0, -310, - -310, -310, -310, 0, 692, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -735, 0, 0, 0, 0, 0, + -116, -735, 0, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, 0, 0, 0, 0, -735, -735, -735, + -735, -310, 0, -735, 0, -735, 0, -735, 0, -310, + -310, -310, 0, 0, 0, -310, -310, 0, -310, 0, + 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, + 0, -310, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, - 0, -118, -310, 0, -310, -310, -310, -310, -310, -310, - -310, -310, -310, -310, 0, 0, 0, 0, 0, -310, - -310, -109, -310, 0, -310, 0, -310, 0, -310, 0, - -310, -310, -310, 0, 0, 0, -310, -310, 0, -310, - 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, - -310, 0, -310, -310, -310, -310, -310, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -310, 0, 0, 0, 0, 0, 0, 0, 0, -310, + 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, 0, 0, 0, 0, -310, -310, -310, -310, - 0, 692, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -310, 0, 0, 0, 0, 0, -118, -310, - 0, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, 0, 0, 0, 0, 0, -310, -310, -310, 0, - 0, -310, 0, -310, 257, -310, 5, 6, 7, 8, - 9, -759, -759, -759, 10, 11, 0, 0, -759, 12, - 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 68, 69, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -759, 257, -759, 5, 6, 7, - 8, 9, 0, 0, -759, 10, 11, 0, -759, -759, - 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, - 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, - 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, - 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, - 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, - 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 67, 68, 69, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -759, 257, -759, 5, 6, - 7, 8, 9, 0, 0, -759, 10, 11, 0, 0, - -759, 12, -759, 13, 14, 15, 16, 17, 18, 19, - 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, - 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, - 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, - 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, - 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, - 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, + -310, 0, 0, 0, 0, -310, -310, -310, -310, 0, + 692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -759, 257, -759, 5, - 6, 7, 8, 9, 0, 0, -759, 10, 11, 0, - 0, -759, 12, 0, 13, 14, 15, 16, 17, 18, - 19, -759, 0, 0, 0, 0, 20, 21, 22, 23, - 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, - 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, - 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, - 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, - 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, -310, 0, 0, 0, 0, 0, -118, -310, 0, + -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, + 0, 0, 0, 0, 0, -310, -310, -109, -310, 0, + -310, 0, -310, 0, -310, 0, -310, -310, -310, 0, + 0, 0, -310, -310, 0, -310, 0, 0, 0, 0, + 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -310, -310, 0, -310, -310, + -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 67, 68, 69, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -759, 257, -759, - 5, 6, 7, 8, 9, 0, 0, -759, 10, 11, - 0, 0, -759, 12, 0, 13, 14, 15, 16, 17, - 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, - 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, - 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, - 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, - 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, - 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 257, 0, 5, 6, 7, 8, - 9, 0, -759, -759, 10, 11, 67, 68, 69, 12, - 0, 13, 14, 15, 16, 17, 18, 19, -759, 0, - -759, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, + 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, + 0, 0, 0, 0, 0, -310, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, 0, 0, + 0, 0, -310, -310, -310, -310, 0, 692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 257, 0, 5, 6, 7, 8, 9, 0, 0, 0, - 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, -759, 0, -759, 0, 0, 20, + 0, 0, 0, 0, 0, 0, 0, 0, -310, 0, + 0, 0, 0, 0, -118, -310, 0, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, 0, 0, 0, + 0, 0, -310, -310, -310, 0, 0, -310, 0, -310, + 257, -310, 5, 6, 7, 8, 9, -757, -757, -757, + 10, 11, 0, 0, -757, 12, 0, 13, 14, 15, + 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, @@ -2741,13 +2754,13 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, - 259, 54, 0, 55, 56, 0, 57, 0, 0, 58, + 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, - 69, 0, 0, 0, 0, 0, 0, 0, -759, 0, - -759, 257, -759, 5, 6, 7, 8, 9, 0, 0, - 0, 10, 11, 0, 0, 0, 12, 0, 13, 14, + 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -757, 257, -757, 5, 6, 7, 8, 9, 0, 0, + -757, 10, 11, 0, -757, -757, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, @@ -2760,12 +2773,12 @@ static const yytype_int16 yytable[] = 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, - 68, 69, 0, 0, 0, 0, 0, 0, 0, -759, - 0, -759, 4, -759, 5, 6, 7, 8, 9, 0, - 0, 0, 10, 11, 0, 0, 0, 12, 0, 13, + 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -757, 257, -757, 5, 6, 7, 8, 9, 0, + 0, -757, 10, 11, 0, 0, -757, 12, -757, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 27, 0, 0, 0, 0, 0, 28, 29, 30, 31, + 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, @@ -2775,10 +2788,10 @@ static const yytype_int16 yytable[] = 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 67, 68, 69, 0, 0, -759, 0, 0, 0, 0, - 0, 0, -759, 257, -759, 5, 6, 7, 8, 9, - 0, 0, 0, 10, 11, 0, 0, 0, 12, 0, - 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, + 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -757, 257, -757, 5, 6, 7, 8, 9, + 0, 0, -757, 10, 11, 0, 0, -757, 12, 0, + 13, 14, 15, 16, 17, 18, 19, -757, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, @@ -2790,9 +2803,9 @@ static const yytype_int16 yytable[] = 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 67, 68, 69, 0, 0, -759, 0, 0, 0, - 0, 0, 0, -759, 257, -759, 5, 6, 7, 8, - 9, 0, 0, -759, 10, 11, 0, 0, 0, 12, + 0, 67, 68, 69, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -757, 257, -757, 5, 6, 7, 8, + 9, 0, 0, -757, 10, 11, 0, 0, -757, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, @@ -2804,9 +2817,9 @@ static const yytype_int16 yytable[] = 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 257, 0, 5, 6, 7, 8, 9, 0, 0, 0, + 257, 0, 5, 6, 7, 8, 9, 0, -757, -757, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, -759, 0, -759, 0, 0, 20, + 16, 17, 18, 19, -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, @@ -2815,36 +2828,109 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 0, -759, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, - 7, 0, 9, 0, 0, 0, 10, 11, 67, 68, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 257, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, - -759, 0, -759, 0, 0, 20, 21, 22, 23, 24, - 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, - 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, + -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, - 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, - 56, 0, 210, 211, 212, 58, 59, 213, 61, 62, + 0, 0, 0, 52, 0, 0, 259, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, + 0, 0, 0, 0, -757, 0, -757, 257, -757, 5, + 6, 7, 8, 9, 0, 0, 0, 10, 11, 0, + 0, 0, 12, 0, 13, 14, 15, 16, 17, 18, + 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, + 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, + 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, + 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, + 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, + 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 67, 68, 69, 0, 0, + 0, 0, 0, 0, 0, -757, 0, -757, 4, -757, + 5, 6, 7, 8, 9, 0, 0, 0, 10, 11, + 0, 0, 0, 12, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, + 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, + 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, + 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, + 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, + 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 67, 68, 69, 0, + 0, -757, 0, 0, 0, 0, 0, 0, -757, 257, + -757, 5, 6, 7, 8, 9, 0, 0, 0, 10, + 11, 0, 0, 0, 12, 0, 13, 14, 15, 16, + 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, + 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, + 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, + 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 67, 68, 69, + 0, 0, -757, 0, 0, 0, 0, 0, 0, -757, + 257, -757, 5, 6, 7, 8, 9, 0, 0, -757, + 10, 11, 0, 0, 0, 12, 0, 13, 14, 15, + 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, + 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, + 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, + 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, + 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 257, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, + 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, + -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, - 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, - 14, 15, 16, 17, 18, 19, 0, 0, 237, 0, + 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, + 14, 15, 16, 17, 18, 19, -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 27, 0, 0, 0, 0, 0, 0, 29, 0, 0, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, + 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, - 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, - 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 0, 0, 209, 54, 0, 55, 56, 0, 210, 211, + 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, - 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, - 18, 19, 305, 0, 306, 0, 0, 20, 21, 22, + 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 0, 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, @@ -2854,24 +2940,24 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, - 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 0, 13, 14, 15, 16, 17, 18, 19, 305, 0, + 306, 0, 0, 20, 21, 22, 23, 24, 25, 26, + 0, 0, 27, 0, 0, 0, 0, 0, 0, 29, + 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 0, 208, 0, 0, 209, 54, 0, 55, 56, 0, + 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, 503, 0, 0, 0, 0, 20, + 16, 17, 18, 19, 0, 0, 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, - 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, + 0, 0, 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, @@ -2879,30 +2965,28 @@ static const yytype_int16 yytable[] = 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, + 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, + 503, 0, 0, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, - 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 503, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 0, 0, 0, 150, 151, - 152, 395, 396, 397, 398, 157, 158, 159, 0, 0, - 0, 0, 0, 160, 161, 162, 163, 399, 400, 401, - 402, 168, 37, 38, 403, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, - 181, 182, 183, 184, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 185, 186, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 0, 197, 198, - 0, 0, 0, 0, 0, 199, 404, 126, 127, 128, + 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 503, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 0, 0, 0, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 0, 0, 0, 0, 0, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 288, 289, - 169, 290, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 0, 0, 0, 150, 151, 152, 395, 396, 397, + 398, 157, 158, 159, 0, 0, 0, 0, 0, 160, + 161, 162, 163, 399, 400, 401, 402, 168, 37, 38, + 403, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, 184, @@ -2911,136 +2995,138 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, 0, - 0, 199, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 0, 0, 0, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, - 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 239, 0, 169, 0, 0, 0, 0, + 0, 199, 404, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 0, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 288, 289, 169, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, - 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 0, 0, 0, 0, 0, 199, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 0, 0, 0, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 0, 0, 0, 0, 0, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 0, 0, - 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 0, 0, 0, 0, 181, 182, 183, 184, + 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, + 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 185, 186, 0, 0, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, + 197, 198, 0, 0, 0, 0, 0, 199, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 0, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 0, 0, 0, 0, 0, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 239, + 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 0, 197, 198, 0, 0, 0, 0, - 0, 199, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 0, 0, 0, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, - 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 0, 0, 169, 0, 0, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, + 0, 0, 199, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 0, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 5, 6, 7, 0, 9, 199, 0, 0, 10, - 11, 0, 0, 0, 12, 0, 13, 14, 15, 245, - 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, - 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, - 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, + 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 185, 186, 0, + 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, + 197, 198, 0, 0, 0, 0, 0, 199, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 0, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 0, 0, 0, 0, 0, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 0, + 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 278, 0, 0, 209, - 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 5, 6, 7, + 0, 9, 199, 0, 0, 10, 11, 0, 0, 0, + 12, 0, 13, 14, 15, 245, 246, 18, 19, 0, + 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, + 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 7, 0, 9, 0, 0, 279, 10, 11, - 0, 0, 0, 12, 280, 13, 14, 15, 245, 246, - 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, - 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, - 0, 0, 0, 277, 0, 0, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, - 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 278, 0, 0, 209, 54, - 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, - 6, 7, 8, 9, 0, 0, 279, 10, 11, 0, - 0, 0, 12, 526, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, - 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, - 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, - 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, - 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, - 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, - 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, + 0, 0, 278, 0, 0, 209, 54, 0, 55, 56, + 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, + 9, 0, 0, 279, 10, 11, 0, 0, 0, 12, + 280, 13, 14, 15, 245, 246, 18, 19, 0, 0, + 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, + 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, + 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 278, 0, 0, 209, 54, 0, 55, 56, 0, + 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, + 0, 0, 279, 10, 11, 0, 0, 0, 12, 526, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, - 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, + 0, 27, 0, 0, 0, 0, 0, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 210, - 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, + 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, + 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 6, 7, 8, 9, 0, 0, 0, 10, - 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, + 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, + 11, 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, - 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, - 0, 0, 0, 28, 29, 0, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, + 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, - 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, - 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, + 54, 0, 55, 56, 0, 210, 211, 212, 58, 59, + 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, - 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, + 8, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, - 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, - 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, + 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, + 29, 0, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 439, 0, 0, 0, 0, - 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 210, 211, 212, 58, 59, 213, 61, 62, 63, + 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, + 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, - 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, - 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, - 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, + 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, + 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, + 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 620, 211, 212, + 50, 439, 0, 0, 0, 0, 0, 0, 208, 0, + 0, 209, 54, 0, 55, 56, 0, 210, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, @@ -3053,7 +3139,7 @@ static const yytype_int16 yytable[] = 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, - 55, 56, 0, 210, 211, 0, 58, 59, 213, 61, + 55, 56, 0, 620, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, @@ -3065,8 +3151,8 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 0, - 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, + 208, 0, 0, 209, 54, 0, 55, 56, 0, 210, + 211, 0, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 245, @@ -3078,7 +3164,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, - 54, 0, 55, 56, 0, 620, 211, 0, 58, 59, + 54, 0, 55, 56, 0, 0, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, @@ -3091,24 +3177,24 @@ static const yytype_int16 yytable[] = 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 0, 211, 0, 58, 59, 213, 61, 62, 63, + 0, 620, 211, 0, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, - 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, - 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, + 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, + 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, + 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 519, 0, 0, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, + 0, 209, 54, 0, 55, 56, 0, 0, 211, 0, + 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, - 214, 69, 12, 0, 13, 14, 15, 245, 246, 18, - 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, + 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, + 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, @@ -3116,7 +3202,7 @@ static const yytype_int16 yytable[] = 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, - 55, 56, 0, 770, 0, 0, 58, 59, 60, 61, + 55, 56, 0, 519, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, @@ -3128,7 +3214,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 519, + 208, 0, 0, 209, 54, 0, 55, 56, 0, 770, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, @@ -3141,7 +3227,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, - 54, 0, 55, 56, 0, 843, 0, 0, 58, 59, + 54, 0, 55, 56, 0, 519, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, @@ -3154,7 +3240,7 @@ static const yytype_int16 yytable[] = 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 1014, 0, 0, 58, 59, 60, 61, 62, 63, + 0, 843, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, @@ -3166,12 +3252,12 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, + 0, 209, 54, 0, 55, 56, 0, 1012, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, - 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, + 214, 69, 12, 0, 13, 14, 15, 245, 246, 18, + 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, @@ -3185,7 +3271,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 27, 0, 0, 0, 0, 0, 0, 29, 0, + 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, @@ -3195,52 +3281,89 @@ static const yytype_int16 yytable[] = 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, - 11, 67, 68, 69, 12, 0, 13, 14, 15, 245, + 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, + 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, + 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, + 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, + 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, + 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, + 12, 0, 13, 14, 15, 245, 246, 18, 19, 0, + 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, + 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 278, 0, 0, 328, 54, 0, 55, 56, + 0, 329, 0, 0, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, + 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, + 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, + 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, + 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, + 0, 0, 277, 0, 0, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, + 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 376, 0, 0, 53, 54, 0, + 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, + 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 384, 36, 37, 38, 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 278, 0, 0, 328, - 54, 0, 55, 56, 0, 329, 0, 0, 58, 59, + 0, 0, 386, 0, 0, 0, 387, 0, 0, 209, + 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, + 33, 34, 384, 36, 37, 38, 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 376, 0, - 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 387, 0, + 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, - 0, 32, 33, 34, 384, 36, 37, 38, 385, 40, + 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 386, 0, 0, 0, - 387, 0, 0, 209, 54, 0, 55, 56, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 278, 0, 0, 328, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, - 277, 0, 0, 32, 33, 34, 384, 36, 37, 38, - 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 387, 0, 0, 209, 54, 0, 55, 56, + 0, 0, 1002, 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, @@ -3252,621 +3375,633 @@ static const yytype_int16 yytable[] = 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 278, 0, 0, 328, 54, 0, - 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, - 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, - 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, - 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, - 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, - 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1004, 0, 0, 209, - 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, - 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, - 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, - 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, - 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, - 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, - 42, 43, 44, 45, 46, 47, 23, 24, 25, 26, + 0, 0, 0, 0, 1054, 0, 0, 209, 54, 0, + 55, 56, 23, 24, 25, 26, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 32, 33, + 34, 781, 0, 0, 0, 782, 0, 980, 41, 42, + 43, 44, 45, 0, 0, 279, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 921, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 783, + 784, 0, 0, 0, 0, 0, 0, 785, 0, 0, + 786, 0, 0, 787, 788, 0, 974, 925, 0, 789, + 59, 997, 61, 62, 63, 64, 65, 66, 23, 24, + 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 790, 0, 0, 32, 33, 34, 781, 279, 0, + 0, 782, 0, 0, 41, 42, 43, 44, 45, 0, + 0, 23, 24, 25, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, + 781, 0, 0, 0, 782, 783, 784, 41, 42, 43, + 44, 45, 0, 785, 0, 0, 786, 0, 0, 787, + 788, 0, 1069, 0, 0, 789, 59, 60, 61, 62, + 63, 64, 65, 66, 0, 0, 0, 0, 783, 784, + 0, 0, 0, 0, 0, 0, 785, 790, 0, 786, + 0, 0, 787, 788, 279, 0, 0, 0, 789, 59, + 60, 61, 62, 63, 64, 65, 66, 564, 565, 0, + 0, 566, 0, 0, 0, 0, 0, 0, 0, 0, + 790, 0, 0, 0, 0, 0, 0, 279, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 33, 34, 781, 0, 0, 0, 782, - 0, 0, 41, 42, 43, 44, 45, 0, 1056, 0, - 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, - 0, 0, 0, 783, 784, 0, 0, 0, 0, 0, - 0, 785, 0, 0, 786, 0, 0, 787, 788, 279, - 975, 0, 0, 789, 59, 60, 61, 62, 63, 64, - 65, 66, 23, 24, 25, 26, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 790, 0, 0, 32, 33, - 34, 781, 279, 0, 0, 782, 0, 0, 41, 42, - 43, 44, 45, 0, 0, 23, 24, 25, 26, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 33, 34, 781, 0, 0, 0, 782, 783, - 784, 41, 42, 43, 44, 45, 0, 785, 0, 0, - 786, 0, 0, 787, 788, 0, 1071, 0, 0, 789, - 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, - 0, 0, 783, 784, 0, 0, 0, 0, 0, 0, - 785, 790, 0, 786, 0, 0, 787, 788, 279, 0, - 0, 0, 789, 59, 60, 61, 62, 63, 64, 65, - 66, 564, 565, 0, 0, 566, 0, 0, 0, 0, - 0, 0, 0, 0, 790, 0, 0, 0, 0, 0, - 0, 279, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 572, 573, 0, + 0, 574, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 572, 573, 0, 0, 574, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 624, 565, 0, + 0, 625, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 624, 565, 0, 0, 625, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 627, 573, 0, + 0, 628, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 627, 573, 0, 0, 628, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 652, 565, 0, + 0, 653, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 652, 565, 0, 0, 653, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 655, 573, 0, + 0, 656, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 655, 573, 0, 0, 656, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 722, 565, 0, + 0, 723, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 722, 565, 0, 0, 723, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 725, 573, 0, + 0, 726, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 725, 573, 0, 0, 726, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 731, 565, 0, + 0, 732, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 731, 565, 0, 0, 732, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 609, 573, 0, + 0, 610, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 609, 573, 0, 0, 610, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 776, 565, 0, + 0, 777, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 776, 565, 0, 0, 777, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 779, 573, 0, + 0, 780, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 779, 573, 0, 0, 780, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1152, 565, 0, + 0, 1153, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1154, 565, 0, 0, 1155, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1155, 573, 0, + 0, 1156, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1157, 573, 0, 0, 1158, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1186, 565, 0, + 0, 1187, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1188, 565, 0, 0, 1189, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 609, 573, 0, + 0, 610, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 609, 573, 0, 0, 610, 199, 233, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 0, 0, 0, 0, 0, 199 + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, + 0, 0, 199 }; static const yytype_int16 yycheck[] = { - 2, 369, 89, 60, 28, 57, 94, 102, 8, 227, - 710, 71, 22, 8, 101, 83, 433, 387, 53, 59, - 866, 331, 16, 17, 95, 91, 92, 71, 28, 95, - 67, 83, 68, 28, 2, 95, 4, 717, 57, 1066, - 26, 16, 17, 626, 96, 97, 98, 53, 16, 17, - 27, 603, 29, 55, 56, 1039, 473, 364, 25, 99, - 92, 55, 56, 95, 59, 425, 4, 13, 78, 893, - 894, 654, 482, 433, 2, 1062, 4, 271, 25, 52, - 1104, 275, 16, 17, 857, 53, 54, 27, 363, 57, - 365, 864, 29, 25, 25, 52, 295, 296, 958, 13, - 68, 25, 25, 100, 99, 1106, 100, 15, 25, 17, - 16, 17, 893, 894, 68, 83, 526, 126, 259, 331, - 1028, 55, 429, 91, 92, 100, 54, 95, 96, 97, - 98, 13, 100, 0, 26, 222, 411, 146, 25, 924, - 34, 724, 96, 97, 37, 38, 1054, 13, 13, 146, - 855, 734, 857, 428, 153, 430, 213, 143, 52, 864, - 414, 415, 148, 689, 251, 15, 100, 66, 66, 1196, - 236, 13, 238, 146, 209, 25, 866, 484, 730, 146, - 953, 148, 1028, 458, 1208, 1169, 123, 328, 1048, 146, - 261, 145, 13, 1039, 100, 778, 283, 1184, 68, 146, - 146, 261, 414, 415, 787, 151, 1207, 153, 1054, 244, - 485, 151, 280, 153, 146, 146, 1062, 261, 635, 221, - 119, 119, 146, 146, 259, 227, 444, 97, 280, 146, - 600, 233, 1013, 1018, 1019, 13, 230, 151, 232, 153, - 242, 209, 279, 143, 310, 311, 312, 313, 953, 315, - 316, 143, 855, 259, 857, 230, 56, 232, 233, 146, - 153, 864, 230, 866, 232, 233, 1174, 143, 236, 151, - 238, 153, 682, 633, 242, 635, 244, 329, 310, 311, - 312, 313, 148, 1191, 591, 151, 151, 153, 153, 257, - 326, 259, 379, 328, 601, 331, 230, 849, 232, 498, - 277, 500, 373, 25, 856, 371, 148, 152, 891, 151, - 329, 153, 280, 373, 242, 58, 1016, 592, 870, 1104, - 386, 1106, 328, 1169, 230, 109, 232, 602, 13, 257, - 151, 13, 153, 152, 77, 370, 1016, 372, 1184, 371, - 1164, 309, 310, 311, 312, 313, 314, 315, 316, 133, - 953, 877, 878, 866, 66, 100, 37, 38, 326, 68, - 328, 329, 364, 331, 1054, 108, 99, 893, 894, 112, - 365, 309, 1062, 151, 1064, 153, 100, 880, 414, 415, - 687, 309, 34, 151, 978, 153, 314, 25, 97, 364, - 893, 894, 326, 126, 977, 705, 364, 331, 366, 152, - 52, 146, 370, 371, 372, 623, 25, 783, 784, 121, - 122, 686, 124, 688, 482, 785, 411, 152, 386, 1002, - 1003, 236, 1207, 1208, 146, 1028, 148, 429, 452, 153, - 482, 425, 25, 97, 694, 430, 1039, 691, 692, 28, - 442, 701, 444, 697, 698, 862, 414, 415, 22, 264, - 537, 1054, 452, 268, 429, 649, 126, 452, 526, 1062, - 986, 429, 661, 458, 99, 99, 151, 666, 153, 151, - 13, 153, 684, 99, 526, 1069, 470, 845, 146, 691, - 692, 145, 484, 77, 148, 697, 698, 1013, 126, 144, - 485, 126, 126, 68, 1184, 1047, 1186, 465, 153, 99, - 126, 1191, 862, 1193, 78, 593, 126, 126, 146, 484, - 1013, 149, 888, 889, 482, 153, 484, 146, 1031, 99, - 890, 96, 97, 1036, 153, 585, 126, 146, 1031, 148, - 149, 899, 750, 126, 153, 1144, 904, 1237, 604, 1148, - 1230, 1054, 136, 137, 138, 1058, 581, 66, 583, 1062, - 1144, 1064, 99, 146, 1148, 1058, 149, 99, 526, 569, - 153, 99, 816, 942, 943, 99, 1169, 577, 112, 99, - 145, 1123, 638, 1156, 1077, 577, 553, 579, 146, 126, - 56, 1184, 650, 68, 126, 964, 965, 966, 126, 591, - 68, 1200, 126, 617, 571, 68, 126, 592, 650, 601, - 119, 611, 121, 122, 816, 1199, 1200, 602, 151, 611, - 153, 96, 97, 581, 682, 583, 591, 617, 96, 97, - 435, 623, 617, 591, 97, 440, 601, 148, 443, 126, - 682, 446, 66, 601, 66, 603, 604, 99, 1164, 633, - 68, 643, 100, 2, 739, 4, 66, 462, 684, 626, - 68, 25, 467, 866, 68, 691, 692, 16, 17, 146, - 145, 697, 698, 729, 126, 146, 866, 145, 728, 97, - 638, 1184, 153, 1186, 248, 249, 68, 654, 1191, 97, - 1193, 148, 650, 97, 66, 687, 153, 121, 122, 121, - 122, 146, 727, 688, 53, 54, 149, 729, 738, 119, - 153, 121, 122, 705, 706, 97, 708, 26, 710, 68, - 525, 679, 687, 99, 682, 683, 684, 1230, 152, 687, - 152, 68, 148, 691, 692, 1093, 82, 83, 518, 697, - 698, 68, 91, 92, 68, 1114, 95, 119, 146, 121, - 122, 100, 124, 738, 66, 153, 148, 724, 750, 68, - 97, 679, 126, 148, 68, 683, 1135, 734, 68, 727, - 97, 729, 730, 97, 9, 767, 150, 769, 834, 153, - 15, 705, 146, 129, 130, 149, 68, 96, 97, 153, - 816, 1088, 96, 97, 68, 52, 96, 97, 578, 56, - 850, 365, 68, 828, 584, 77, 586, 119, 833, 121, - 122, 778, 834, 52, 96, 97, 149, 56, 126, 68, - 787, 788, 96, 97, 1089, 150, 99, 144, 1031, 56, - 96, 97, 824, 146, 143, 77, 145, 106, 99, 148, - 146, 145, 867, 56, 148, 145, 77, 96, 97, 14, - 15, 1054, 151, 126, 130, 1058, 898, 25, 816, 1062, - 209, 1064, 66, 145, 1054, 126, 430, 146, 1058, 149, - 828, 145, 1062, 146, 1064, 833, 834, 902, 146, 145, - 144, 230, 144, 232, 233, 146, 911, 236, 146, 238, - 146, 849, 99, 242, 458, 244, 145, 68, 856, 866, - 99, 951, 10, 134, 135, 136, 137, 138, 257, 867, - 259, 144, 870, 88, 89, 119, 146, 121, 122, 126, - 962, 485, 54, 146, 891, 96, 97, 126, 44, 1006, - 146, 736, 64, 65, 44, 982, 40, 41, 718, 146, - 898, 721, 126, 8, 902, 13, 751, 146, 940, 25, - 942, 943, 999, 911, 17, 735, 152, 152, 144, 99, - 309, 310, 311, 312, 313, 314, 315, 316, 146, 68, - 128, 68, 964, 965, 966, 15, 150, 326, 148, 328, - 146, 1184, 331, 1186, 131, 1010, 126, 1012, 1191, 146, - 1193, 958, 26, 2, 1184, 4, 1186, 96, 97, 96, - 97, 1191, 52, 1193, 962, 569, 146, 16, 17, 100, - 977, 1053, 131, 577, 100, 364, 983, 366, 146, 1011, - 144, 370, 371, 372, 1016, 1050, 52, 1230, 592, 66, - 67, 26, 126, 146, 68, 1002, 1003, 386, 602, 146, - 1230, 68, 52, 146, 53, 54, 145, 611, 145, 52, - 146, 146, 1010, 131, 1012, 835, 126, 146, 838, 68, - 56, 841, 96, 97, 66, 414, 415, 146, 848, 96, - 97, 851, 146, 68, 146, 146, 414, 415, 642, 643, - 429, 1048, 91, 92, 121, 122, 95, 892, 146, 1047, - 151, 100, 1050, 431, 432, 1053, 1088, 9, 1090, 1124, - 1092, 96, 97, 68, 1089, 146, 1162, 1163, 68, 143, - 146, 145, 866, 131, 148, 56, 465, 119, 145, 121, - 122, 459, 1114, 1088, 688, 99, 931, 932, 58, 99, - 1088, 96, 97, 913, 146, 484, 96, 97, 146, 146, - 1162, 1163, 146, 1135, 52, 146, 146, 77, 143, 120, - 145, 149, 126, 148, 146, 66, 126, 146, 52, 146, - 54, 55, 56, 57, 58, 1123, 1124, 146, 146, 974, - 950, 146, 146, 146, 1141, 242, 146, 146, 108, 109, - 145, 144, 148, 77, 689, 145, 2, 148, 4, 1156, - 40, 41, 42, 43, 44, 1000, 1001, 146, 689, 146, - 209, 461, 77, 133, 1162, 1163, 465, 101, 119, 1234, - 121, 122, 96, 124, 108, 109, 98, 1022, 87, 94, - 95, 230, 611, 232, 233, 706, 1018, 236, 1092, 238, - 1104, 866, 581, 242, 583, 244, 1196, 53, 54, 133, - 769, 57, 591, 883, 740, 1237, 1237, 514, 257, 324, - 259, 887, 601, 1013, 603, 604, 131, 132, 133, 134, - 135, 136, 137, 138, 1077, 1077, 1090, 83, 885, 945, - 52, 947, 54, 55, 56, 57, 1234, 1077, 783, 784, - 96, 97, 98, 99, 1011, 1039, 105, 99, 1042, 638, - 500, 952, 783, 784, 855, 968, 969, 1102, 1054, 1031, - 309, 310, 311, 312, 313, 314, 315, 316, 1062, 77, - 1064, 1058, 1028, 54, 55, 983, 57, 326, -1, 328, - -1, -1, 331, 64, 65, -1, 94, 95, -1, -1, - 679, -1, -1, -1, 683, 684, -1, -1, 687, -1, - -1, 1121, 691, 692, 59, 60, 61, 62, 697, 698, - -1, -1, -1, 691, 692, 364, -1, 366, -1, 697, - 698, 370, 371, 372, -1, 133, 134, 135, 136, 137, - 138, -1, 877, 878, -1, -1, -1, 386, 727, -1, - 729, 730, 887, 888, 889, -1, 877, 878, 893, 894, - -1, -1, -1, 209, -1, -1, 887, 888, 889, -1, - -1, 1181, 893, 894, -1, 414, 415, 745, 746, -1, - 748, 749, -1, -1, -1, 1169, -1, 1171, -1, -1, - 429, -1, 1176, -1, -1, -1, 242, -1, 244, -1, - 1184, -1, 1186, -1, 1110, 1111, -1, -1, -1, 1193, - 1116, 257, 1118, 259, 1120, -1, 689, 52, -1, 54, - 55, 56, 57, 58, -1, -1, 465, 1130, 1131, -1, - -1, -1, -1, 1136, 280, 1138, 1139, 816, -1, -1, - -1, 1225, 77, 978, -1, 484, 1230, -1, 816, 828, - -1, 986, -1, -1, 833, 834, 52, 978, 54, 55, - 56, 57, -1, 309, -1, 986, 101, -1, 314, -1, - 849, -1, 107, 108, 109, -1, -1, 856, 1013, -1, - -1, -1, 328, 329, -1, -1, -1, -1, 867, -1, - -1, 870, 1013, 861, 2, 1089, 4, -1, 133, -1, - -1, 136, -1, 1209, 1210, 1211, 1212, -1, -1, -1, - 783, 784, 1215, 1216, 1217, 1218, -1, -1, 153, -1, - 366, 77, -1, 902, 370, -1, 372, -1, -1, 1235, - -1, -1, 911, 1236, 1069, -1, -1, -1, 94, 95, - -1, -1, 581, -1, 583, 53, 54, -1, 1069, 57, - -1, 52, 591, 54, 55, 56, 57, 58, -1, -1, - -1, -1, 601, -1, 603, 604, -1, -1, -1, 52, - -1, 54, 55, 56, 57, 83, 77, 56, 134, 135, - 136, 137, 138, -1, -1, -1, -1, -1, 96, 97, - 98, -1, 52, -1, 54, 55, 56, 57, -1, 638, - 101, -1, -1, -1, 877, 878, 107, 108, 109, 1144, - -1, -1, -1, 1148, 887, 888, 889, -1, 101, 465, - 893, 894, -1, 1144, 107, -1, -1, 1148, -1, 1164, - -1, 1010, 133, 1012, -1, 136, 482, -1, -1, -1, - 679, 101, -1, 1164, 683, 684, -1, 148, 687, -1, - -1, -1, 691, 692, -1, -1, -1, -1, 697, 698, - -1, -1, -1, -1, 1199, 1200, -1, -1, 1047, -1, - -1, 1050, -1, -1, -1, -1, -1, -1, 1199, 1200, - 526, -1, -1, -1, -1, -1, -1, -1, 727, -1, - 729, 730, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 209, -1, -1, -1, 978, -1, -1, -1, 1088, - -1, -1, -1, 986, -1, -1, -1, -1, 52, -1, - 54, 55, 56, 57, 58, -1, -1, -1, 207, -1, - -1, 210, 211, 212, 242, 581, 244, 583, -1, -1, - 1013, -1, -1, 77, 1123, 1124, -1, -1, -1, 257, - -1, 259, -1, -1, -1, -1, -1, 603, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, - -1, -1, 280, 107, 108, 109, -1, 816, -1, 689, - -1, -1, -1, 1162, 1163, -1, -1, -1, -1, 828, - -1, -1, -1, -1, 833, 834, 1069, -1, -1, 133, - -1, 309, 136, -1, 650, -1, 314, -1, -1, -1, - 849, -1, -1, -1, -1, -1, -1, 856, -1, -1, - 328, 329, -1, 331, -1, -1, -1, -1, 867, -1, - -1, 870, -1, 679, -1, -1, 682, 683, -1, -1, - -1, -1, -1, 689, -1, -1, -1, 326, -1, -1, - -1, -1, 331, -1, -1, 1234, -1, -1, 366, -1, - -1, -1, 370, 902, 372, -1, -1, -1, -1, -1, - -1, 1144, 911, 783, 784, 1148, -1, -1, -1, -1, - -1, 727, -1, -1, 730, -1, -1, -1, -1, -1, - -1, 1164, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 414, 415, -1, 52, - -1, 54, 55, 56, 57, 58, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1199, 1200, -1, -1, - -1, -1, -1, -1, 77, -1, -1, 783, 784, -1, - -1, -1, -1, -1, -1, 424, 425, -1, 91, -1, - -1, -1, -1, -1, 433, -1, -1, 465, 101, -1, - -1, -1, -1, -1, 107, 108, 109, 877, 878, -1, - -1, 1010, -1, 1012, 482, -1, -1, 887, 888, 889, - -1, -1, 828, 893, 894, -1, -1, 833, -1, -1, - 133, 470, -1, 136, 473, -1, -1, -1, -1, -1, - -1, -1, 2, 849, 4, -1, -1, -1, 1047, -1, - 856, 1050, -1, -1, -1, -1, -1, -1, 526, -1, - -1, 867, -1, -1, 870, -1, -1, -1, -1, -1, - -1, 877, 878, -1, -1, -1, -1, -1, -1, -1, - 519, 887, 888, 889, -1, -1, -1, 893, 894, 1088, - -1, -1, 898, 53, 54, -1, 902, 57, -1, -1, - -1, -1, -1, 689, -1, 911, -1, -1, 978, -1, - -1, -1, -1, 581, -1, 583, 986, -1, -1, -1, - -1, -1, -1, 83, 1123, 1124, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 603, 96, 97, 98, 99, - -1, -1, -1, 1013, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 962, 689, -1, -1, - -1, -1, -1, 1162, 1163, -1, -1, -1, -1, -1, - -1, -1, 978, -1, -1, -1, -1, -1, -1, 618, - 986, 620, 650, -1, -1, -1, -1, -1, -1, -1, - -1, 659, -1, -1, 633, -1, 635, 783, 784, 1069, - -1, -1, -1, -1, 1010, -1, 1012, 1013, -1, -1, - -1, 679, -1, -1, 682, 683, 684, -1, -1, -1, - -1, -1, -1, 691, 692, -1, -1, -1, -1, 697, - 698, -1, -1, -1, 2, 1234, 4, -1, -1, 678, - -1, 1047, -1, -1, 1050, -1, -1, 1053, -1, 209, - -1, 783, 784, -1, -1, -1, -1, -1, 2, 727, - 4, -1, 730, 1069, -1, -1, 705, -1, -1, -1, - -1, -1, -1, -1, 1144, -1, -1, -1, 1148, -1, - -1, 720, 242, -1, 244, 53, 54, -1, -1, -1, - -1, 877, 878, -1, 1164, -1, -1, 257, -1, 259, - -1, 887, 888, 889, -1, -1, -1, 893, 894, 53, - 54, -1, -1, -1, -1, -1, -1, 1123, 1124, -1, - 280, 689, -1, -1, -1, -1, -1, -1, 96, 1199, - 1200, 770, -1, -1, -1, -1, -1, -1, 1144, -1, - -1, -1, 1148, -1, -1, 877, 878, -1, 816, 309, - -1, -1, -1, -1, 314, 887, 888, 889, 1164, -1, - 828, 893, 894, -1, -1, 833, -1, -1, 328, 329, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 849, -1, -1, -1, -1, -1, -1, 856, -1, - -1, -1, 978, 1199, 1200, -1, -1, -1, -1, 867, - 986, -1, 870, -1, 843, -1, 366, -1, -1, -1, - 370, -1, 372, -1, -1, 783, 784, -1, -1, -1, - -1, -1, -1, 862, -1, -1, -1, 1013, 1234, -1, - 898, -1, -1, -1, 902, -1, -1, -1, -1, -1, - -1, 209, -1, 911, -1, -1, 978, -1, -1, -1, - -1, -1, -1, 689, 986, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 209, -1, -1, -1, -1, - -1, 910, -1, -1, 242, -1, 244, -1, -1, -1, - -1, 1013, -1, 1069, -1, -1, -1, -1, -1, 257, - -1, 259, -1, -1, 962, -1, -1, -1, 242, 938, - 244, -1, -1, -1, -1, 465, -1, -1, -1, 877, - 878, -1, -1, 257, -1, 259, -1, -1, -1, 887, - 888, 889, 482, -1, -1, 893, 894, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1069, -1, -1, - -1, 309, 1010, -1, 1012, -1, 314, 783, 784, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1144, -1, - 328, -1, 1148, 331, -1, 309, 526, -1, -1, -1, - 314, -1, -1, -1, -1, 1014, -1, -1, 1164, 1047, - -1, -1, 1050, -1, 328, 1053, -1, 331, 1027, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 366, -1, - -1, -1, 370, -1, 372, -1, -1, -1, -1, -1, - 978, -1, 1144, 1199, 1200, -1, 1148, -1, 986, -1, - -1, 581, 366, 583, -1, -1, 370, -1, 372, -1, - -1, -1, 1164, -1, -1, -1, -1, -1, -1, -1, - -1, 877, 878, 603, -1, 1013, 414, 415, -1, -1, - -1, 887, 888, 889, -1, 1123, 1124, 893, 894, -1, - -1, -1, -1, -1, -1, -1, -1, 1199, 1200, -1, - 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 650, -1, -1, -1, -1, -1, -1, 465, -1, 25, - -1, 1069, -1, 0, -1, -1, -1, -1, -1, -1, - -1, 8, 9, 10, -1, -1, 13, 14, 15, 679, - 17, 465, 682, 683, -1, -1, -1, -1, 25, 26, - 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 37, 38, 978, 40, 41, 42, 43, 44, -1, -1, - 986, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, -1, -1, 1234, 727, 94, 95, - 730, 68, -1, -1, -1, -1, 1144, 1013, -1, -1, - 1148, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1164, -1, -1, 96, - 97, 127, -1, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 581, -1, 583, -1, -1, -1, -1, - -1, -1, -1, 120, -1, -1, -1, -1, -1, -1, - -1, 1199, 1200, 1069, -1, 603, -1, 581, -1, 583, - -1, -1, -1, -1, -1, -1, 143, 144, -1, -1, - -1, 148, 149, -1, 151, -1, 153, -1, -1, 603, - -1, -1, -1, -1, -1, -1, -1, -1, 828, -1, - -1, -1, -1, 833, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 849, - -1, -1, -1, -1, -1, -1, 856, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 867, 1144, -1, - 870, 679, 1148, -1, -1, 683, 684, -1, -1, -1, - -1, -1, -1, 691, 692, -1, -1, -1, 1164, 697, - 698, -1, -1, -1, -1, 679, -1, -1, 898, 683, - 684, -1, 902, -1, -1, -1, -1, 691, 692, -1, - -1, 911, -1, 697, 698, -1, -1, -1, -1, 727, - -1, -1, 730, 1199, 1200, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 727, -1, -1, 730, -1, -1, -1, - 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 962, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 48, 49, 50, 51, -1, -1, -1, 55, - 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 68, 69, -1, -1, -1, -1, 816, -1, - 1010, -1, 1012, -1, -1, -1, -1, -1, -1, -1, - 828, -1, -1, -1, -1, 833, -1, -1, -1, -1, - -1, -1, 816, -1, 100, -1, -1, -1, -1, -1, - -1, 849, -1, -1, 828, -1, -1, 1047, 856, 833, - 1050, -1, -1, 1053, -1, -1, -1, -1, -1, 867, - -1, -1, 870, -1, -1, 849, -1, -1, -1, -1, - -1, -1, 856, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 867, -1, -1, 870, -1, -1, -1, - 898, -1, -1, -1, 902, -1, -1, -1, -1, -1, - -1, -1, -1, 911, 33, 34, 35, 36, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 902, -1, - 49, 50, 51, 1123, 1124, -1, -1, 911, -1, -1, - 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, - -1, 207, -1, -1, 210, 211, 212, -1, 214, -1, + 2, 60, 53, 89, 369, 71, 102, 83, 8, 22, + 710, 8, 16, 17, 28, 101, 59, 331, 227, 717, + 16, 17, 94, 91, 92, 387, 4, 95, 28, 95, + 482, 28, 57, 626, 2, 271, 4, 433, 57, 275, + 67, 892, 893, 71, 363, 1064, 365, 26, 16, 17, + 27, 55, 29, 55, 56, 1026, 99, 364, 83, 59, + 92, 654, 603, 95, 27, 78, 295, 296, 1037, 1060, + 68, 96, 97, 98, 526, 1102, 13, 473, 25, 53, + 1104, 1052, 25, 957, 259, 53, 54, 1142, 95, 57, + 52, 1146, 411, 414, 415, 15, 100, 0, 689, 99, + 68, 77, 25, 331, 100, 25, 25, 148, 99, 428, + 143, 430, 153, 892, 893, 83, 68, 2, 13, 4, + 126, 13, 429, 91, 92, 941, 942, 95, 96, 97, + 98, 724, 100, 37, 38, 126, 222, 16, 17, 458, + 146, 734, 425, 1198, 96, 97, 56, 963, 964, 965, + 433, 25, 29, 328, 213, 22, 857, 151, 209, 153, + 136, 137, 138, 864, 143, 251, 485, 66, 236, 54, + 238, 153, 1046, 16, 17, 1194, 9, 484, 25, 1206, + 28, 1205, 15, 126, 146, 778, 414, 415, 151, 730, + 153, 1182, 866, 244, 787, 261, 13, 283, 1167, 146, + 13, 1172, 25, 146, 280, 148, 149, 66, 259, 146, + 153, 78, 55, 56, 151, 52, 153, 100, 1189, 221, + 119, 100, 518, 146, 152, 227, 230, 146, 232, 148, + 682, 233, 1011, 261, 230, 444, 232, 233, 600, 635, + 242, 209, 310, 311, 312, 313, 123, 315, 316, 153, + 866, 952, 279, 148, 261, 280, 151, 100, 153, 151, + 119, 153, 230, 146, 232, 233, 977, 143, 236, 498, + 238, 500, 146, 592, 242, 26, 244, 328, 310, 311, + 312, 313, 578, 602, 591, 259, 877, 878, 584, 257, + 586, 259, 236, 379, 601, 152, 1112, 890, 152, 146, + 277, 892, 893, 371, 329, 13, 100, 373, 849, 146, + 329, 1162, 280, 25, 1014, 856, 1014, 1133, 386, 370, + 264, 372, 326, 146, 268, 148, 52, 331, 326, 870, + 56, 309, 25, 331, 151, 148, 153, 13, 151, 371, + 153, 309, 310, 311, 312, 313, 314, 315, 316, 152, + 633, 230, 635, 232, 328, 25, 1067, 242, 326, 153, + 328, 329, 364, 331, 97, 365, 373, 686, 364, 688, + 691, 692, 257, 13, 783, 784, 697, 698, 1052, 126, + 687, 248, 249, 976, 13, 146, 1060, 230, 1062, 232, + 54, 705, 143, 112, 985, 100, 364, 148, 366, 99, + 64, 65, 370, 371, 372, 126, 482, 1000, 1001, 13, + 1026, 411, 145, 649, 623, 148, 414, 415, 386, 13, + 1011, 1037, 718, 785, 309, 721, 126, 429, 66, 314, + 430, 1142, 661, 429, 146, 1146, 1052, 666, 452, 735, + 442, 146, 444, 151, 1060, 153, 414, 415, 37, 38, + 526, 537, 452, 146, 99, 452, 684, 482, 458, 82, + 83, 429, 866, 691, 692, 855, 862, 857, 109, 697, + 698, 68, 25, 66, 864, 151, 146, 153, 887, 888, + 845, 119, 484, 121, 122, 485, 1197, 1198, 484, 146, + 923, 435, 133, 99, 148, 816, 440, 465, 365, 443, + 97, 526, 446, 146, 1045, 68, 129, 130, 1182, 56, + 1184, 151, 66, 153, 482, 1189, 484, 1191, 462, 585, + 126, 593, 151, 467, 153, 126, 119, 889, 121, 122, + 581, 124, 583, 898, 97, 1235, 604, 99, 903, 835, + 146, 750, 838, 68, 25, 841, 866, 151, 100, 153, + 150, 1167, 848, 153, 1228, 851, 569, 151, 526, 153, + 99, 1154, 952, 430, 577, 119, 1182, 121, 122, 146, + 638, 1162, 97, 126, 650, 577, 553, 579, 148, 862, + 1121, 525, 425, 1016, 1017, 68, 52, 126, 816, 591, + 56, 458, 592, 146, 571, 591, 149, 99, 611, 601, + 153, 68, 602, 617, 66, 601, 682, 146, 68, 611, + 68, 68, 148, 581, 97, 583, 912, 617, 485, 66, + 617, 623, 68, 591, 126, 650, 68, 470, 66, 34, + 97, 148, 25, 601, 68, 603, 604, 97, 96, 97, + 97, 643, 77, 739, 146, 126, 99, 52, 1052, 626, + 149, 97, 1056, 949, 153, 97, 1060, 682, 1062, 121, + 122, 729, 728, 97, 15, 146, 17, 881, 149, 1102, + 638, 1104, 153, 126, 121, 122, 727, 654, 892, 893, + 99, 119, 650, 121, 122, 687, 684, 145, 688, 694, + 152, 687, 68, 691, 692, 738, 701, 729, 149, 697, + 698, 705, 569, 705, 706, 152, 708, 126, 710, 1029, + 577, 679, 126, 34, 682, 683, 684, 689, 150, 687, + 96, 97, 144, 691, 692, 592, 1091, 146, 99, 697, + 698, 52, 1052, 126, 146, 602, 1056, 2, 738, 4, + 1060, 153, 1062, 99, 611, 58, 56, 724, 750, 66, + 67, 16, 17, 146, 99, 126, 149, 734, 26, 727, + 153, 729, 730, 146, 77, 767, 834, 769, 1087, 145, + 126, 77, 1205, 1206, 106, 642, 643, 828, 1182, 1086, + 1184, 126, 833, 66, 850, 1189, 146, 1191, 53, 54, + 633, 68, 736, 153, 679, 108, 66, 1011, 683, 112, + 68, 778, 834, 68, 121, 122, 99, 751, 68, 146, + 787, 783, 784, 99, 56, 1029, 867, 68, 816, 96, + 97, 688, 824, 1119, 1228, 151, 91, 92, 96, 97, + 95, 14, 15, 126, 56, 100, 96, 97, 121, 122, + 126, 124, 1056, 99, 25, 96, 97, 99, 816, 119, + 901, 121, 122, 26, 124, 99, 146, 130, 68, 910, + 828, 1075, 1182, 153, 1184, 833, 834, 149, 145, 1189, + 126, 1191, 897, 144, 126, 143, 10, 145, 40, 41, + 148, 849, 126, 1179, 950, 145, 96, 97, 856, 866, + 66, 77, 88, 89, 145, 68, 146, 148, 146, 867, + 146, 144, 870, 144, 44, 877, 878, 52, 1228, 54, + 55, 56, 57, 890, 886, 887, 888, 146, 1004, 146, + 892, 893, 981, 96, 97, 146, 68, 146, 44, 897, + 8, 99, 126, 901, 13, 145, 961, 939, 997, 941, + 942, 866, 910, 119, 209, 121, 122, 891, 134, 135, + 136, 137, 138, 68, 96, 97, 101, 1008, 126, 1010, + 25, 963, 964, 965, 17, 230, 144, 232, 233, 99, + 143, 236, 145, 238, 99, 148, 146, 242, 146, 244, + 957, 96, 97, 152, 128, 207, 930, 931, 210, 211, + 212, 68, 257, 961, 259, 152, 126, 1048, 150, 976, + 855, 126, 857, 145, 68, 977, 15, 1009, 68, 864, + 148, 866, 1014, 985, 146, 944, 146, 946, 131, 96, + 97, 146, 146, 1000, 1001, 144, 1051, 52, 866, 973, + 145, 68, 96, 97, 100, 131, 96, 97, 100, 1011, + 1008, 146, 1010, 126, 309, 310, 311, 312, 313, 314, + 315, 316, 52, 146, 998, 999, 26, 146, 66, 96, + 97, 326, 146, 328, 689, 146, 331, 52, 145, 1046, + 146, 1122, 52, 131, 68, 126, 1020, 1045, 146, 146, + 1048, 145, 151, 1051, 1086, 145, 1088, 1087, 1090, 146, + 1086, 146, 1160, 1161, 146, 1067, 144, 952, 68, 364, + 146, 366, 96, 97, 326, 370, 371, 372, 145, 331, + 1112, 119, 1037, 121, 122, 1040, 56, 68, 1086, 9, + 146, 386, 146, 414, 415, 131, 96, 97, 1160, 1161, + 56, 1133, 967, 968, 146, 1060, 146, 1062, 68, 146, + 431, 432, 146, 52, 146, 96, 97, 146, 149, 414, + 415, 145, 120, 1121, 1122, 146, 1100, 58, 783, 784, + 146, 148, 1139, 146, 429, 146, 96, 97, 459, 146, + 1142, 1026, 146, 143, 1146, 145, 77, 1154, 148, 1108, + 1109, 1232, 1037, 146, 146, 1114, 144, 1116, 148, 1118, + 1162, 1029, 1160, 1161, 145, 242, 1034, 1052, 146, 146, + 465, 465, 424, 425, 461, 1060, 98, 108, 109, 96, + 87, 433, 611, 706, 1052, 145, 1016, 1090, 1056, 484, + 1087, 1102, 1060, 769, 1062, 1197, 1198, 54, 55, 866, + 57, 882, 133, 1235, 1194, 740, 514, 64, 65, 324, + 1235, 1011, 1167, 1075, 1169, 1075, 1075, 886, 470, 1174, + 884, 473, 877, 878, 1088, 1009, 105, 1182, 99, 1184, + 500, 886, 887, 888, 1232, 951, 1191, 892, 893, 2, + 52, 4, 54, 55, 56, 57, 855, 1029, 1207, 1208, + 1209, 1210, 1056, 16, 17, 52, 1052, 54, 55, 56, + 57, 58, 1026, 1128, 1129, -1, -1, 519, 1223, 1134, + -1, 1136, 1137, 1228, 1233, 40, 41, 42, 43, 44, + 77, -1, 1167, -1, -1, -1, 581, -1, 583, 101, + 53, 54, -1, -1, 91, 107, 591, 1182, 52, -1, + 54, 55, 56, 57, 101, 68, 601, -1, 603, 604, + 107, 108, 109, -1, 1182, 52, 1184, 54, 55, 56, + 57, 1189, 977, 1191, -1, 689, -1, -1, 91, 92, + 985, -1, 95, -1, -1, -1, 133, 100, -1, 136, + -1, -1, -1, 638, 59, 60, 61, 62, 1213, 1214, + 1215, 1216, -1, -1, -1, -1, 1011, 77, -1, -1, + 1228, -1, -1, -1, -1, -1, 618, -1, 620, 1234, + 691, 692, -1, -1, 94, 95, 697, 698, -1, -1, + -1, 633, 77, 635, 679, -1, -1, -1, 683, 684, + -1, -1, 687, -1, -1, -1, 691, 692, -1, 94, + 95, -1, 697, 698, -1, 52, -1, 54, 55, 56, + 57, 58, 1067, 133, 134, 135, 136, 137, 138, 783, + 784, -1, -1, -1, 745, 746, 678, 748, 749, -1, + 77, -1, 727, -1, 729, 730, 689, -1, -1, 134, + 135, 136, 137, 138, -1, -1, 209, -1, -1, -1, + -1, -1, -1, 705, 101, -1, -1, -1, -1, -1, + 107, 108, 109, -1, -1, -1, -1, 230, 720, 232, + 233, -1, -1, 236, -1, 238, -1, -1, -1, 242, + -1, 244, -1, -1, -1, -1, 133, 1142, -1, 136, + -1, 1146, -1, -1, 257, 816, 259, -1, -1, -1, + -1, 689, -1, -1, -1, -1, 153, 1162, -1, -1, + -1, -1, -1, 877, 878, -1, -1, -1, 770, -1, + -1, 816, 886, 887, 888, -1, -1, -1, 892, 893, + 783, 784, -1, 828, -1, 2, -1, 4, 833, 834, + 861, -1, 1197, 1198, -1, -1, 309, 310, 311, 312, + 313, 314, 315, 316, 849, -1, -1, -1, -1, -1, + -1, 856, -1, 326, -1, 328, -1, -1, 331, -1, + -1, -1, 867, -1, -1, 870, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 53, 54, -1, -1, + 57, 843, -1, -1, -1, 783, 784, -1, -1, -1, + -1, 364, -1, 366, -1, -1, 901, 370, 371, 372, + 862, -1, -1, 977, -1, 910, 83, -1, -1, -1, + -1, 985, -1, 386, 877, 878, -1, -1, -1, 96, + 97, 98, 99, 886, 887, 888, -1, -1, -1, 892, + 893, -1, -1, -1, -1, -1, -1, 1011, -1, -1, + -1, 414, 415, -1, -1, -1, -1, 909, -1, -1, + -1, -1, -1, -1, -1, -1, 429, -1, -1, -1, + 52, -1, 54, 55, 56, 57, 58, -1, -1, -1, + -1, -1, -1, -1, -1, 937, -1, -1, -1, 877, + 878, -1, -1, -1, -1, 77, -1, -1, 886, 887, + 888, -1, 465, 1067, 892, 893, -1, -1, -1, -1, + -1, -1, -1, 1008, -1, 1010, -1, -1, -1, 101, + -1, 484, -1, -1, 977, 107, 108, 109, -1, -1, + -1, 52, 985, 54, 55, 56, 57, 58, -1, -1, + -1, -1, 209, -1, -1, -1, -1, 25, -1, -1, + 1045, 133, -1, 1048, 136, -1, 77, -1, 1011, -1, + 1012, -1, -1, -1, -1, -1, 148, -1, -1, -1, + -1, -1, -1, 1025, -1, 242, -1, 244, 1142, -1, + 101, -1, 1146, -1, -1, -1, 107, 108, 109, 977, + 257, 1086, 259, -1, -1, -1, -1, 985, 1162, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 133, 280, 1067, 136, 94, 95, 581, -1, + 583, -1, -1, 1011, -1, -1, 1121, 1122, 591, -1, + -1, -1, -1, 1197, 1198, -1, -1, -1, 601, -1, + 603, 604, 309, -1, -1, -1, -1, 314, -1, 127, + -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 328, 329, -1, -1, 1160, 1161, -1, -1, -1, + -1, -1, -1, -1, -1, 638, -1, -1, -1, 1067, + -1, -1, 52, -1, 54, 55, 56, 57, 58, 1142, + -1, -1, -1, 1146, -1, -1, -1, -1, -1, 366, + -1, -1, -1, 370, -1, 372, -1, 77, -1, 1162, + -1, -1, -1, -1, -1, -1, 679, -1, -1, -1, + 683, 684, -1, -1, 687, 2, -1, 4, 691, 692, + -1, 101, -1, -1, 697, 698, -1, 1232, 108, 109, + -1, -1, -1, -1, 1197, 1198, -1, -1, -1, -1, + -1, -1, -1, -1, 1142, -1, -1, -1, 1146, -1, + -1, -1, -1, 133, 727, -1, 729, 730, 77, -1, + -1, -1, -1, -1, 1162, -1, 53, 54, -1, -1, + 57, -1, -1, -1, -1, 94, 95, 2, -1, 4, + -1, -1, -1, -1, -1, -1, -1, -1, 465, -1, + -1, -1, -1, -1, -1, -1, 83, -1, -1, 1197, + 1198, -1, -1, -1, -1, 482, -1, -1, -1, 96, + 97, 98, 131, 132, 133, 134, 135, 136, 137, 138, + -1, -1, -1, -1, -1, -1, -1, -1, 53, 54, + -1, -1, 57, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 816, -1, -1, -1, -1, -1, 526, + -1, -1, -1, -1, -1, 828, -1, -1, 83, -1, + 833, 834, 33, 34, 35, 36, -1, -1, -1, -1, + -1, 96, 97, 98, 99, -1, 849, -1, 49, 50, + 51, 52, -1, 856, -1, 56, -1, -1, 59, 60, + 61, 62, 63, -1, 867, -1, -1, 870, -1, -1, + -1, -1, -1, -1, 581, -1, 583, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, 209, -1, -1, -1, 603, 98, 901, -1, + 101, -1, -1, 104, 105, -1, 107, 910, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, 242, -1, 244, -1, -1, + -1, 132, -1, -1, -1, 689, -1, -1, 139, -1, + 257, -1, 259, 650, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 209, -1, -1, -1, -1, -1, + -1, -1, -1, 280, -1, -1, -1, -1, -1, -1, + -1, -1, 679, -1, -1, 682, 683, -1, -1, -1, + -1, -1, 689, -1, -1, -1, 2, 242, 4, 244, + -1, -1, 309, -1, -1, -1, -1, 314, -1, -1, + -1, -1, 257, -1, 259, 1008, -1, 1010, -1, -1, + -1, 328, 329, -1, 331, -1, -1, -1, -1, -1, + 727, -1, -1, 730, -1, 280, -1, -1, -1, 783, + 784, -1, -1, -1, -1, -1, -1, 53, 54, -1, + -1, -1, 1045, -1, -1, 1048, -1, -1, -1, 366, + -1, -1, -1, 370, 309, 372, -1, -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 230, -1, 232, 233, -1, -1, + -1, -1, -1, 328, 329, -1, 783, 784, -1, -1, + 96, -1, -1, 1086, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 366, -1, -1, -1, 370, -1, 372, 1121, 1122, + -1, 828, -1, 877, 878, -1, 833, -1, -1, -1, + -1, -1, 886, 887, 888, -1, -1, -1, 892, 893, + -1, -1, 849, -1, -1, -1, -1, -1, 465, 856, + -1, -1, -1, -1, -1, -1, -1, 1160, 1161, -1, + 867, -1, -1, 870, -1, 482, -1, -1, -1, -1, + 877, 878, -1, -1, -1, -1, -1, -1, -1, 886, + 887, 888, -1, -1, -1, 892, 893, -1, -1, -1, + 897, -1, -1, 209, 901, -1, -1, -1, -1, -1, + -1, -1, -1, 910, -1, -1, -1, -1, -1, 526, + 465, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2, 977, 4, -1, 242, 482, 244, 1232, + -1, 985, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, -1, 259, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 961, -1, -1, 1011, -1, -1, + -1, -1, -1, -1, 581, -1, 583, -1, -1, -1, + 977, 526, -1, 53, 54, -1, -1, -1, 985, -1, + -1, -1, -1, -1, -1, -1, 603, -1, -1, -1, + -1, -1, -1, 309, -1, -1, -1, -1, 314, -1, + -1, 1008, -1, 1010, 1011, -1, -1, -1, -1, -1, + -1, -1, 328, 1067, -1, 331, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 581, -1, 583, -1, + -1, -1, -1, 650, -1, -1, -1, -1, 1045, -1, + -1, 1048, 659, -1, 1051, -1, -1, -1, 603, -1, + 366, -1, -1, -1, 370, -1, 372, -1, -1, -1, + 1067, -1, 679, -1, -1, 682, 683, 684, -1, -1, + -1, -1, -1, -1, 691, 692, -1, -1, -1, -1, + 697, 698, -1, -1, -1, -1, -1, -1, 1142, -1, + -1, -1, 1146, -1, -1, 650, -1, -1, 414, 415, + -1, -1, -1, -1, 33, 34, 35, 36, 1162, -1, + 727, -1, -1, 730, 1121, 1122, -1, -1, -1, -1, + 49, 50, 51, -1, 679, -1, -1, 682, 683, 209, + 59, 60, 61, 62, 63, 1142, -1, -1, -1, 1146, + -1, -1, -1, 1197, 1198, -1, -1, -1, -1, 465, + -1, -1, -1, -1, -1, 1162, -1, -1, -1, -1, + -1, -1, 242, -1, 244, -1, -1, -1, -1, -1, + -1, -1, 727, -1, -1, 730, -1, 257, -1, 259, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, - -1, 77, 78, 79, 80, 81, 82, 83, 84, -1, - 86, 87, 1010, -1, 1012, -1, -1, -1, 94, 95, - 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1010, -1, 1012, -1, - -1, -1, -1, -1, 1234, -1, -1, -1, -1, 1047, - -1, -1, 1050, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, -1, -1, -1, -1, -1, -1, - 326, -1, -1, 1047, -1, 331, 1050, 333, 334, 335, - 336, 337, -1, -1, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, -1, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, -1, -1, -1, 364, -1, + 1197, 1198, -1, -1, -1, -1, -1, -1, -1, 816, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 139, 828, 86, 87, -1, -1, 833, -1, -1, -1, + 94, 95, -1, -1, -1, 1232, -1, -1, -1, 309, + -1, -1, 849, -1, 314, -1, -1, -1, 689, 856, + -1, -1, -1, -1, -1, -1, -1, -1, 328, -1, + 867, 331, -1, 870, -1, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 581, -1, 583, -1, -1, + -1, -1, -1, 828, -1, -1, -1, -1, 833, -1, + 897, -1, -1, -1, 901, -1, 366, 603, -1, -1, + 370, -1, 372, 910, 849, -1, -1, -1, -1, -1, + -1, 856, -1, -1, -1, -1, -1, -1, -1, -1, + 689, -1, 867, -1, -1, 870, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1123, 1124, -1, -1, -1, - -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, -1, -1, 1123, - 1124, 94, 95, -1, -1, -1, -1, -1, 414, 415, - -1, -1, -1, -1, -1, -1, -1, 423, 424, 425, - -1, -1, -1, 429, -1, 431, 432, 433, -1, -1, - -1, -1, -1, 439, 127, -1, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, -1, -1, 454, -1, - -1, -1, -1, 459, -1, -1, -1, -1, -1, -1, - 153, -1, -1, -1, 470, -1, -1, 473, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 484, -1, - -1, -1, -1, -1, -1, -1, 1234, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 502, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 1234, -1, -1, 519, 94, 95, -1, -1, -1, -1, - -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, - 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, - -1, -1, -1, -1, -1, -1, -1, 25, 26, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 37, - 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, + -1, -1, 783, 784, 414, 415, -1, -1, -1, -1, + -1, -1, 897, -1, 961, -1, 901, -1, -1, -1, + -1, -1, -1, -1, -1, 910, -1, -1, -1, -1, + -1, -1, -1, 679, -1, -1, -1, 683, 684, -1, + -1, -1, -1, -1, -1, 691, 692, -1, -1, -1, + -1, 697, 698, -1, -1, 465, -1, -1, -1, -1, + -1, 1008, -1, 1010, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 783, 784, 961, -1, -1, -1, + -1, 727, -1, -1, 730, 77, 78, 79, 80, 81, + 82, 83, 84, -1, 86, 87, 877, 878, 1045, -1, + -1, 1048, 94, 95, 1051, 886, 887, 888, -1, -1, + -1, 892, 893, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1008, -1, 1010, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 591, -1, -1, -1, -1, - 68, -1, -1, -1, -1, 601, -1, -1, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 618, -1, 620, -1, 94, 95, 96, 97, - -1, 99, -1, -1, -1, -1, -1, 633, -1, 635, + 1045, -1, -1, 1048, -1, -1, 1051, -1, 877, 878, + 816, 581, -1, 583, 1121, 1122, -1, 886, 887, 888, + -1, -1, 828, 892, 893, -1, -1, 833, -1, -1, + -1, -1, -1, 603, 16, 17, 977, -1, -1, -1, + -1, -1, -1, 849, 985, -1, -1, -1, -1, -1, + 856, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 867, -1, -1, 870, -1, 48, 49, 50, 51, + 1011, -1, -1, 55, 56, -1, 1121, 1122, -1, -1, + -1, -1, -1, -1, -1, -1, 68, 69, -1, -1, + -1, 897, -1, -1, -1, 901, -1, -1, -1, -1, + -1, -1, -1, -1, 910, -1, -1, -1, 977, 679, + -1, -1, -1, 683, 684, -1, 985, -1, 100, -1, + -1, 691, 692, -1, -1, 1232, 1067, 697, 698, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, 1011, -1, -1, -1, -1, 8, 9, 10, + -1, -1, 13, 14, 15, -1, 17, 727, -1, -1, + 730, -1, -1, -1, 25, 26, 27, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, + 41, 42, 43, 44, -1, -1, -1, 1232, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1067, -1, + -1, 1142, 1008, -1, 1010, 1146, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, - -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, 143, 144, 145, 146, -1, - -1, 149, 678, 151, -1, 153, -1, -1, 684, 685, - -1, 687, -1, -1, -1, 691, 692, -1, -1, -1, - -1, 697, 698, -1, 33, 34, 35, 36, -1, 705, + -1, 1162, -1, -1, -1, 207, -1, -1, 210, 211, + 212, -1, 214, -1, -1, 96, 97, -1, -1, 1045, + -1, -1, 1048, -1, -1, -1, 816, -1, 230, -1, + 232, 233, -1, -1, -1, -1, 1197, 1198, 828, 120, + -1, -1, -1, 833, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1142, -1, -1, -1, 1146, -1, 849, + -1, -1, 143, 144, -1, -1, 856, 148, 149, -1, + 151, -1, 153, 1162, -1, -1, -1, 867, -1, -1, + 870, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1121, 1122, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1197, 1198, + -1, 901, -1, -1, -1, -1, -1, -1, -1, -1, + 910, -1, -1, -1, 326, -1, -1, -1, -1, 331, + -1, 333, 334, 335, 336, 337, -1, -1, 340, 341, + 342, 343, 344, 345, 346, 347, 348, -1, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 49, 50, 51, 52, 720, -1, -1, 56, -1, 58, - 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 77, 745, - 746, -1, 748, 749, -1, -1, -1, -1, -1, -1, - -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, - -1, -1, 101, -1, 770, 104, 105, -1, 107, 108, - -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, + -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, + -1, -1, -1, 94, 95, -1, 1232, -1, -1, -1, + -1, -1, 414, 415, -1, -1, -1, -1, 1008, -1, + 1010, 423, 424, 425, -1, -1, -1, 429, -1, 431, + 432, 433, -1, -1, -1, -1, 127, 439, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, + -1, -1, 454, -1, -1, 1045, -1, 459, 1048, -1, + -1, -1, 153, -1, -1, -1, -1, -1, 470, -1, + -1, 473, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 484, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 132, -1, -1, -1, -1, -1, -1, - 139, -1, -1, 809, -1, -1, -1, -1, -1, -1, - 816, -1, 0, 1, -1, 3, 4, 5, 6, 7, - -1, -1, -1, 11, 12, -1, -1, -1, 16, -1, - 18, 19, 20, 21, 22, 23, 24, 843, -1, -1, - -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, - -1, 39, -1, -1, -1, 861, 862, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, + 502, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, -1, -1, -1, 519, 94, 95, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, 1121, 1122, -1, 8, 9, 10, -1, -1, -1, + 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, + -1, 25, 26, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 37, 38, -1, 40, 41, 42, 43, + 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 591, + -1, -1, -1, -1, 68, -1, -1, -1, -1, 601, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 618, -1, 620, -1, + 94, 95, 96, 97, -1, 99, -1, -1, -1, -1, + -1, 633, -1, 635, -1, -1, -1, -1, -1, -1, + -1, -1, 1232, -1, -1, -1, 120, -1, -1, -1, + -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, + 144, 145, 146, -1, -1, 149, 678, 151, -1, 153, + -1, -1, 684, 685, -1, 687, -1, -1, -1, 691, + 692, -1, -1, -1, -1, 697, 698, -1, 0, -1, + -1, -1, -1, 705, -1, -1, 8, 9, 10, -1, + -1, 13, 14, 15, -1, 17, -1, -1, 720, -1, + -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, + -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, + 42, 43, 44, 745, 746, -1, 748, 749, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 90, 91, 910, -1, -1, -1, -1, -1, - 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, - -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, - 118, -1, 938, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 68, -1, 770, -1, + -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, + -1, -1, 94, 95, 96, 97, -1, 99, 100, -1, + -1, -1, -1, -1, 106, -1, -1, 809, -1, -1, + -1, -1, -1, -1, 816, -1, -1, -1, 120, -1, + -1, 123, -1, -1, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, + -1, 843, 144, 145, 146, -1, -1, 149, 150, 151, + -1, 153, -1, -1, -1, -1, -1, -1, -1, 861, + 862, -1, -1, 0, 1, -1, 3, 4, 5, 6, + 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, + -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, + -1, -1, 39, -1, -1, -1, -1, 909, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, + -1, -1, -1, -1, -1, 937, -1, -1, 75, 76, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, + -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, + 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, -1, 0, -1, - -1, -1, -1, 151, -1, 153, 8, 9, 10, -1, + -1, -1, 139, 140, 141, -1, -1, -1, -1, -1, + 1012, 0, -1, -1, 151, -1, 153, -1, -1, 8, + 9, 10, -1, 1025, 13, 14, 15, -1, 17, -1, + -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, + 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, + -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, -1, -1, 86, 87, 68, + -1, -1, -1, -1, 1086, 94, 95, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, + 99, 100, -1, -1, -1, -1, -1, 106, -1, -1, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + -1, 120, -1, -1, 123, -1, -1, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, + 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, - -1, -1, -1, 25, 26, 27, 28, 29, -1, -1, + 44, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, - 42, 43, 44, -1, -1, -1, -1, -1, 1014, -1, + 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, - -1, 1027, 86, 87, -1, -1, 68, -1, -1, -1, + 84, 85, 86, 87, 88, 89, 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, 99, 100, -1, - -1, -1, -1, -1, 106, 129, 130, 131, 132, 133, + -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, 120, -1, - -1, 123, 1088, -1, 126, 127, 128, 129, 130, 131, + -1, 123, 146, -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, - -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, + -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, 44, -1, -1, - 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, + 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, - 95, 96, 97, -1, 99, 100, -1, -1, -1, -1, + 95, 96, 97, -1, -1, 100, -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, -1, -1, -1, 120, -1, -1, 123, 146, - -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, + 137, 138, -1, -1, -1, 120, -1, -1, 123, -1, + -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, - -1, -1, -1, -1, 44, -1, -1, 25, -1, 27, + -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, @@ -3874,41 +4009,41 @@ static const yytype_int16 yycheck[] = 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, - -1, 99, 100, -1, -1, -1, -1, 127, 106, 129, + -1, -1, 100, -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, - -1, -1, 120, -1, -1, 123, -1, -1, 126, 127, + -1, -1, 120, -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, -1, 144, 145, 146, 0, + 138, -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, - -1, -1, -1, -1, 25, 26, 27, 28, 29, -1, + -1, -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 68, -1, -1, - -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, + -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, - -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, - -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, -1, -1, -1, 120, - -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, + -1, -1, -1, 94, 95, 96, 97, -1, 99, 100, + -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, + -1, -1, 123, -1, -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, - -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, + -1, -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, - -1, 25, 26, 27, 28, 29, -1, -1, -1, -1, + -1, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 77, 78, 79, 80, 81, 82, 83, -1, -1, - 86, 87, -1, -1, 68, -1, -1, -1, 94, 95, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, -1, -1, -1, - -1, -1, 106, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, -1, -1, 120, -1, -1, 123, - -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, + -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, + -1, -1, -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, - 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, + 144, 145, 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, @@ -3918,9 +4053,9 @@ static const yytype_int16 yycheck[] = -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, - 97, -1, 99, 100, -1, -1, -1, -1, -1, 106, + 97, -1, -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 120, -1, -1, 123, -1, -1, 126, + -1, -1, -1, 120, -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, @@ -3940,7 +4075,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, 143, 144, 145, 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, - -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, + -1, -1, 25, -1, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3950,26 +4085,26 @@ static const yytype_int16 yycheck[] = -1, 94, 95, 96, 97, -1, -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, - 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, + -1, -1, -1, -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, - -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, - 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, + -1, 144, 145, 146, 0, 148, 149, 150, 151, -1, + 153, -1, 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, 25, - 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, + 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, - 96, 97, -1, -1, 100, -1, -1, -1, -1, -1, - 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, 97, -1, 99, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, - -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, + 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, 144, 145, - 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, - 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, - -1, -1, -1, -1, -1, -1, 25, -1, 27, 28, + 146, 0, -1, 149, -1, 151, -1, 153, -1, 8, + 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, + -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3977,14 +4112,14 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, - -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, + 99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 120, -1, -1, -1, -1, -1, -1, 127, -1, + -1, 120, -1, -1, -1, -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - -1, -1, -1, -1, -1, 144, 145, 146, 0, 148, - 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, + -1, -1, -1, -1, -1, 144, 145, 146, 0, -1, + 149, -1, 151, -1, 153, -1, 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, -1, -1, -1, - -1, -1, -1, 25, 26, -1, -1, -1, -1, -1, + -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3996,125 +4131,10 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, - -1, 143, 144, 145, 146, 0, -1, 149, -1, 151, - -1, 153, -1, 8, 9, 10, -1, -1, -1, 14, - 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, - 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, - -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, - 95, 96, 97, -1, 99, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, - -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, - 145, 146, 0, -1, 149, -1, 151, -1, 153, -1, - 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, - -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, - 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, - -1, 99, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, - -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, -1, 144, 145, 146, -1, - -1, 149, -1, 151, 1, 153, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, -1, 15, 16, - -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 139, 140, 141, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, - 6, 7, -1, -1, 10, 11, 12, -1, 14, 15, - 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, - 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, - -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, - 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 139, 140, 141, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, - 5, 6, 7, -1, -1, 10, 11, 12, -1, -1, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, - 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, - -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, - 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, - 4, 5, 6, 7, -1, -1, 10, 11, 12, -1, - -1, 15, 16, -1, 18, 19, 20, 21, 22, 23, - 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, - 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, - -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, - -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 139, 140, 141, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, - 3, 4, 5, 6, 7, -1, -1, 10, 11, 12, - -1, -1, 15, 16, -1, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, - 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, - -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, - -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, - -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, 1, -1, 3, 4, 5, 6, - 7, -1, 9, 10, 11, 12, 139, 140, 141, 16, - -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, - 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - 1, -1, 3, 4, 5, 6, 7, -1, -1, -1, - 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, - 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, + -1, -1, 144, 145, 146, -1, -1, 149, -1, 151, + 1, 153, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, -1, -1, 15, 16, -1, 18, 19, 20, + 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, @@ -4126,9 +4146,9 @@ static const yytype_int16 yycheck[] = 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, -1, -1, -1, -1, 149, -1, + 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, -1, -1, - -1, 11, 12, -1, -1, -1, 16, -1, 18, 19, + 10, 11, 12, -1, 14, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, @@ -4141,9 +4161,9 @@ static const yytype_int16 yycheck[] = 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, -1, -1, -1, -1, 149, + 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, -1, - -1, -1, 11, 12, -1, -1, -1, 16, -1, 18, + -1, 10, 11, 12, -1, -1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, @@ -4156,10 +4176,10 @@ static const yytype_int16 yycheck[] = -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 139, 140, 141, -1, -1, 144, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, - -1, -1, -1, 11, 12, -1, -1, -1, 16, -1, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, + -1, -1, 10, 11, 12, -1, -1, 15, 16, -1, + 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, @@ -4171,9 +4191,9 @@ static const yytype_int16 yycheck[] = -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 139, 140, 141, -1, -1, 144, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, - 7, -1, -1, 10, 11, 12, -1, -1, -1, 16, + 7, -1, -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, @@ -4185,7 +4205,7 @@ static const yytype_int16 yycheck[] = -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - 1, -1, 3, 4, 5, 6, 7, -1, -1, -1, + 1, -1, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, @@ -4196,36 +4216,109 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, - -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, + -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, + -1, -1, -1, -1, 149, -1, 151, 1, 153, 3, + 4, 5, 6, 7, -1, -1, -1, 11, 12, -1, + -1, -1, 16, -1, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, + 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, + -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, + -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, + 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 139, 140, 141, -1, -1, + -1, -1, -1, -1, -1, 149, -1, 151, 1, 153, + 3, 4, 5, 6, 7, -1, -1, -1, 11, 12, + -1, -1, -1, 16, -1, 18, 19, 20, 21, 22, + 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, + 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, + -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, + 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, + -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, + -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, + 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 139, 140, 141, -1, + -1, 144, -1, -1, -1, -1, -1, -1, 151, 1, + 153, 3, 4, 5, 6, 7, -1, -1, -1, 11, + 12, -1, -1, -1, 16, -1, 18, 19, 20, 21, + 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, + 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, + -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 139, 140, 141, + -1, -1, 144, -1, -1, -1, -1, -1, -1, 151, + 1, 153, 3, 4, 5, 6, 7, -1, -1, 10, + 11, 12, -1, -1, -1, 16, -1, 18, 19, 20, + 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, + 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, + -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, + 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, + 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, + 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, + 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, + 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, - 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, 120, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, - 19, 20, 21, 22, 23, 24, -1, -1, 153, -1, + 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, - -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, - -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, + -1, -1, 101, 102, -1, 104, 105, -1, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, - 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, + 23, 24, -1, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, @@ -4235,22 +4328,22 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, - -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, + -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, + -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, - 21, 22, 23, 24, 151, -1, -1, -1, -1, 30, + 21, 22, 23, 24, -1, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, @@ -4260,24 +4353,22 @@ static const yytype_int16 yycheck[] = 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, + 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, + 151, -1, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, + -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 151, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 75, 76, 77, 78, 79, 80, 81, - 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, - 92, 93, 94, 95, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 107, 108, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, -1, 140, 141, - -1, -1, -1, -1, -1, 147, 148, 3, 4, 5, + -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 151, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, 35, @@ -4292,124 +4383,126 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, -1, - -1, 147, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, -1, 56, -1, -1, -1, -1, + -1, 147, 148, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, - 111, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, -1, -1, -1, -1, -1, 147, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, - 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, - 86, 87, -1, -1, -1, -1, 92, 93, 94, 95, + -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, + -1, -1, 92, 93, 94, 95, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 107, 108, -1, -1, 111, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, + 140, 141, -1, -1, -1, -1, -1, 147, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, 140, 141, -1, -1, -1, -1, - -1, 147, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, - 51, 52, 53, -1, -1, 56, -1, -1, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, 111, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, + -1, -1, 147, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, + 50, 51, 52, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 3, 4, 5, -1, 7, 147, -1, -1, 11, - 12, -1, -1, -1, 16, -1, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, + -1, -1, 92, 93, 94, 95, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 107, 108, -1, + -1, 111, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, + 140, 141, -1, -1, -1, -1, -1, 147, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 3, 4, 5, + -1, 7, 147, -1, -1, 11, 12, -1, -1, -1, + 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, + 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, + 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, 5, -1, 7, -1, -1, 139, 11, 12, - -1, -1, -1, 16, 146, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, - 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, - -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 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, - -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, - -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, - 4, 5, 6, 7, -1, -1, 139, 11, 12, -1, - -1, -1, 16, 146, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, - 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, - -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, - -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, - -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, + -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, + -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, + 7, -1, -1, 139, 11, 12, -1, -1, -1, 16, + 146, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, + -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, + -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, + 57, -1, 59, 60, 61, 62, 63, 64, 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, -1, -1, -1, -1, + -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, + -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, + -1, -1, 139, 11, 12, -1, -1, -1, 16, 146, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, - -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, - -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, + -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, 5, 6, 7, -1, -1, -1, 11, + -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, 45, 46, -1, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + 102, -1, 104, 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, + 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, - 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, + 46, -1, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, @@ -4434,7 +4527,7 @@ static const yytype_int16 yycheck[] = -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, 108, -1, 110, 111, 112, 113, + 104, 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, @@ -4446,8 +4539,8 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, - 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, + 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, @@ -4459,7 +4552,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, 108, -1, 110, 111, + 102, -1, 104, 105, -1, -1, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, @@ -4472,19 +4565,19 @@ static const yytype_int16 yycheck[] = 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, -1, 108, -1, 110, 111, 112, 113, 114, 115, + -1, 107, 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, + -1, 101, 102, -1, 104, 105, -1, -1, 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, @@ -4547,7 +4640,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, + -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, @@ -4582,10 +4675,47 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, + -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, + 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, + 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, + 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 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, -1, -1, -1, + -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, + -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, + 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, + -1, -1, 16, 139, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, + 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, + -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 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, -1, + -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, + 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, + -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, + 12, -1, -1, -1, 16, 139, 18, 19, 20, 21, + 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, + 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, + -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 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, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + -1, -1, 94, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, 139, 18, 19, @@ -4597,7 +4727,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, + -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, 139, @@ -4608,7 +4738,7 @@ static const yytype_int16 yycheck[] = -1, 59, 60, 61, 62, 63, 64, 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, -1, 94, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, @@ -4634,197 +4764,177 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, - 12, -1, -1, -1, 16, 139, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 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, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, - -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, - -1, 11, 12, -1, -1, -1, 16, 139, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, - 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, - -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, 65, 33, 34, 35, 36, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 49, 50, 51, 52, -1, -1, -1, 56, - -1, -1, 59, 60, 61, 62, 63, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, - 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, -1, -1, 104, 105, 139, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 33, 34, 35, 36, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 132, -1, -1, 49, 50, - 51, 52, 139, -1, -1, 56, -1, -1, 59, 60, - 61, 62, 63, -1, -1, 33, 34, 35, 36, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 49, 50, 51, 52, -1, -1, -1, 56, 90, - 91, 59, 60, 61, 62, 63, -1, 98, -1, -1, - 101, -1, -1, 104, 105, -1, 107, -1, -1, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, - -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, - 98, 132, -1, 101, -1, -1, 104, 105, 139, -1, - -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 52, 53, -1, -1, 56, -1, -1, -1, -1, - -1, -1, -1, -1, 132, -1, -1, -1, -1, -1, - -1, 139, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 104, 105, 33, 34, 35, 36, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, 49, 50, + 51, 52, -1, -1, -1, 56, -1, 58, 59, 60, + 61, 62, 63, -1, -1, 139, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 77, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, + 101, -1, -1, 104, 105, -1, 107, 108, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 33, 34, + 35, 36, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 132, -1, -1, 49, 50, 51, 52, 139, -1, + -1, 56, -1, -1, 59, 60, 61, 62, 63, -1, + -1, 33, 34, 35, 36, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 49, 50, 51, + 52, -1, -1, -1, 56, 90, 91, 59, 60, 61, + 62, 63, -1, 98, -1, -1, 101, -1, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, 132, -1, 101, + -1, -1, 104, 105, 139, -1, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 52, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + 132, -1, -1, -1, -1, -1, -1, 139, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, -1, -1, -1, -1, -1, 147 + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, + -1, -1, 147 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = +static const yytype_int16 yystos[] = { 0, 155, 156, 0, 1, 3, 4, 5, 6, 7, 11, 12, 16, 18, 19, 20, 21, 22, 23, 24, @@ -4838,7 +4948,7 @@ static const yytype_uint16 yystos[] = 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 252, 279, 280, 333, 334, 335, 336, 337, 338, 339, 342, 344, 345, 359, 360, 362, 363, 364, 365, 366, - 367, 368, 369, 405, 419, 159, 3, 4, 5, 6, + 367, 368, 369, 405, 418, 159, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, @@ -4852,28 +4962,28 @@ static const yytype_uint16 yystos[] = 148, 211, 212, 148, 207, 211, 148, 153, 412, 54, 195, 412, 143, 160, 143, 21, 22, 31, 32, 182, 200, 233, 252, 200, 200, 200, 56, 1, 47, 101, - 163, 164, 165, 167, 185, 186, 419, 167, 220, 205, - 215, 403, 419, 204, 402, 403, 419, 46, 98, 139, + 163, 164, 165, 167, 185, 186, 418, 167, 220, 205, + 215, 403, 418, 204, 402, 403, 418, 46, 98, 139, 146, 190, 218, 233, 365, 366, 369, 223, 54, 55, 57, 194, 348, 361, 348, 349, 350, 152, 152, 152, - 152, 364, 179, 200, 200, 151, 153, 411, 417, 418, + 152, 364, 179, 200, 200, 151, 153, 411, 416, 417, 40, 41, 42, 43, 44, 37, 38, 26, 143, 207, 211, 244, 281, 28, 245, 278, 126, 146, 101, 107, 187, 126, 25, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 94, 95, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 202, 202, 68, 96, 97, 145, 409, 219, 171, 175, 175, - 176, 177, 176, 175, 411, 418, 98, 184, 191, 233, + 176, 177, 176, 175, 411, 417, 98, 184, 191, 233, 257, 365, 366, 369, 52, 56, 94, 98, 192, 193, 233, 365, 366, 369, 193, 33, 34, 35, 36, 49, 50, 51, 52, 56, 148, 194, 367, 400, 210, 97, 409, 410, 281, 336, 99, 99, 146, 204, 56, 204, - 204, 204, 348, 126, 100, 146, 214, 419, 97, 145, + 204, 204, 348, 126, 100, 146, 214, 418, 97, 145, 409, 99, 99, 146, 214, 210, 412, 413, 210, 91, - 209, 210, 215, 377, 403, 419, 171, 413, 171, 54, + 209, 210, 215, 377, 403, 418, 171, 413, 171, 54, 64, 65, 168, 148, 201, 157, 163, 97, 409, 99, - 167, 166, 185, 149, 411, 418, 413, 221, 413, 150, - 146, 153, 416, 146, 416, 144, 416, 412, 56, 364, + 167, 166, 185, 149, 411, 417, 413, 221, 413, 150, + 146, 153, 415, 146, 415, 144, 415, 412, 56, 364, 187, 189, 146, 97, 145, 409, 270, 271, 66, 119, 121, 122, 351, 119, 119, 351, 67, 351, 340, 346, 343, 347, 77, 151, 159, 175, 175, 175, 175, 167, @@ -4884,7 +4994,7 @@ static const yytype_uint16 yystos[] = 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 52, 53, 56, 198, 207, 406, 407, 209, 52, 53, 56, 198, 207, 406, 161, 163, - 13, 253, 417, 253, 163, 175, 163, 411, 225, 56, + 13, 253, 416, 253, 163, 175, 163, 411, 225, 56, 97, 145, 409, 25, 171, 52, 56, 192, 130, 370, 97, 145, 409, 228, 401, 229, 68, 97, 408, 52, 56, 406, 170, 200, 206, 170, 206, 197, 124, 204, @@ -4896,65 +5006,65 @@ static const yytype_uint16 yystos[] = 144, 284, 282, 10, 251, 288, 251, 204, 146, 44, 413, 189, 146, 44, 126, 44, 97, 145, 409, 173, 412, 99, 99, 207, 211, 412, 414, 99, 99, 207, - 208, 211, 419, 251, 8, 246, 329, 419, 163, 13, - 163, 251, 27, 254, 417, 251, 25, 224, 293, 17, + 208, 211, 418, 251, 8, 246, 329, 418, 163, 13, + 163, 251, 27, 254, 416, 251, 25, 224, 293, 17, 248, 291, 52, 56, 209, 52, 56, 176, 227, 371, 226, 52, 56, 192, 209, 161, 171, 230, 231, 208, 211, 195, 204, 204, 214, 99, 99, 414, 99, 99, - 403, 171, 416, 187, 414, 273, 354, 54, 55, 57, + 403, 171, 415, 187, 414, 273, 354, 54, 55, 57, 358, 369, 152, 351, 152, 152, 152, 285, 144, 289, 107, 204, 167, 189, 167, 200, 52, 56, 209, 52, 56, 52, 56, 90, 91, 98, 101, 104, 105, 110, 132, 303, 304, 305, 308, 323, 324, 326, 327, 328, 333, 334, 337, 338, 339, 342, 344, 345, 366, 128, 170, 206, 170, 206, 181, 150, 99, 170, 206, 170, - 206, 181, 204, 217, 330, 419, 9, 15, 247, 249, - 332, 419, 14, 249, 250, 255, 256, 419, 256, 178, - 294, 291, 251, 107, 204, 290, 251, 414, 163, 417, + 206, 181, 204, 217, 330, 418, 9, 15, 247, 249, + 332, 418, 14, 249, 250, 255, 256, 418, 256, 178, + 294, 291, 251, 107, 204, 290, 251, 414, 163, 416, 175, 161, 414, 251, 413, 148, 372, 373, 194, 281, - 278, 99, 146, 413, 274, 355, 131, 265, 266, 419, + 278, 99, 146, 413, 274, 355, 131, 265, 266, 418, 265, 204, 414, 324, 324, 56, 192, 311, 309, 414, - 310, 412, 415, 325, 52, 100, 174, 131, 88, 89, - 97, 145, 148, 306, 307, 200, 170, 206, 100, 331, - 419, 163, 162, 163, 175, 251, 251, 295, 251, 204, - 146, 253, 251, 161, 417, 251, 52, 54, 55, 56, - 57, 58, 77, 91, 101, 107, 108, 109, 133, 136, - 374, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 387, 388, 389, 390, 391, 394, 395, 396, 397, 398, - 161, 376, 232, 148, 276, 376, 356, 262, 264, 267, - 380, 382, 383, 385, 386, 389, 390, 392, 393, 396, - 398, 412, 163, 161, 303, 107, 303, 312, 313, 314, - 316, 58, 112, 317, 318, 319, 320, 321, 322, 388, - 144, 270, 326, 308, 324, 324, 192, 414, 413, 112, - 312, 317, 312, 317, 98, 191, 233, 365, 366, 369, - 253, 163, 253, 296, 107, 204, 163, 251, 101, 107, - 258, 259, 260, 261, 379, 413, 413, 126, 146, 375, - 204, 146, 399, 419, 34, 52, 146, 399, 399, 146, - 375, 52, 146, 375, 52, 251, 417, 372, 376, 275, - 357, 267, 131, 126, 146, 263, 98, 233, 146, 399, - 399, 399, 146, 263, 146, 263, 151, 413, 52, 146, - 414, 107, 303, 316, 146, 348, 415, 146, 303, 34, - 52, 348, 413, 413, 414, 414, 56, 97, 145, 409, - 163, 332, 163, 301, 302, 303, 314, 317, 204, 256, - 291, 292, 260, 379, 146, 413, 146, 204, 374, 381, - 394, 396, 384, 388, 390, 398, 382, 391, 396, 380, - 382, 161, 267, 29, 123, 277, 163, 131, 233, 262, - 393, 396, 56, 97, 385, 390, 382, 392, 396, 382, - 52, 268, 269, 378, 146, 315, 316, 52, 146, 146, - 124, 319, 321, 322, 52, 56, 209, 52, 56, 329, - 255, 253, 40, 41, 146, 413, 258, 261, 259, 146, - 375, 146, 375, 399, 146, 375, 146, 375, 375, 251, - 149, 161, 163, 120, 146, 263, 146, 263, 52, 56, - 399, 146, 263, 146, 263, 263, 146, 412, 315, 146, - 146, 315, 414, 297, 175, 175, 312, 146, 146, 382, - 396, 382, 382, 251, 144, 382, 396, 382, 382, 269, - 316, 315, 298, 259, 375, 146, 375, 375, 375, 263, - 146, 263, 263, 263, 299, 382, 382, 163, 375, 263, - 256, 293, 300 + 144, 310, 325, 52, 100, 174, 131, 88, 89, 97, + 145, 148, 306, 307, 200, 170, 206, 100, 331, 418, + 163, 162, 163, 175, 251, 251, 295, 251, 204, 146, + 253, 251, 161, 416, 251, 52, 54, 55, 56, 57, + 58, 77, 91, 101, 107, 108, 109, 133, 136, 374, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 387, + 388, 389, 390, 391, 394, 395, 396, 397, 398, 161, + 376, 232, 148, 276, 376, 356, 262, 264, 267, 380, + 382, 383, 385, 386, 389, 390, 392, 393, 396, 398, + 412, 163, 161, 303, 107, 303, 312, 313, 314, 316, + 58, 112, 317, 318, 319, 320, 321, 322, 388, 270, + 326, 308, 324, 324, 192, 414, 413, 112, 312, 317, + 312, 317, 98, 191, 233, 365, 366, 369, 253, 163, + 253, 296, 107, 204, 163, 251, 101, 107, 258, 259, + 260, 261, 379, 413, 413, 126, 146, 375, 204, 146, + 399, 418, 34, 52, 146, 399, 399, 146, 375, 52, + 146, 375, 52, 251, 416, 372, 376, 275, 357, 267, + 131, 126, 146, 263, 98, 233, 146, 399, 399, 399, + 146, 263, 146, 263, 151, 413, 52, 146, 414, 107, + 303, 316, 146, 348, 144, 146, 303, 34, 52, 348, + 413, 413, 414, 414, 56, 97, 145, 409, 163, 332, + 163, 301, 302, 303, 314, 317, 204, 256, 291, 292, + 260, 379, 146, 413, 146, 204, 374, 381, 394, 396, + 384, 388, 390, 398, 382, 391, 396, 380, 382, 161, + 267, 29, 123, 277, 163, 131, 233, 262, 393, 396, + 56, 97, 385, 390, 382, 392, 396, 382, 52, 268, + 269, 378, 146, 315, 316, 52, 146, 146, 124, 319, + 321, 322, 52, 56, 209, 52, 56, 329, 255, 253, + 40, 41, 146, 413, 258, 261, 259, 146, 375, 146, + 375, 399, 146, 375, 146, 375, 375, 251, 149, 161, + 163, 120, 146, 263, 146, 263, 52, 56, 399, 146, + 263, 146, 263, 263, 146, 412, 315, 146, 146, 315, + 414, 297, 175, 175, 312, 146, 146, 382, 396, 382, + 382, 251, 144, 382, 396, 382, 382, 269, 316, 315, + 298, 259, 375, 146, 375, 375, 375, 263, 146, 263, + 263, 263, 299, 382, 382, 163, 375, 263, 256, 293, + 300 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = +static const yytype_int16 yyr1[] = { 0, 154, 156, 155, 157, 158, 158, 158, 158, 159, 159, 160, 162, 161, 161, 163, 164, 164, 164, 164, @@ -5008,34 +5118,34 @@ static const yytype_uint16 yyr1[] = 306, 307, 308, 308, 308, 308, 308, 308, 308, 309, 308, 308, 310, 308, 308, 311, 308, 312, 312, 312, 312, 312, 312, 312, 312, 313, 313, 314, 314, 314, - 314, 315, 315, 316, 317, 317, 317, 317, 317, 317, - 318, 318, 319, 319, 320, 320, 321, 321, 322, 323, - 323, 323, 323, 323, 323, 323, 323, 323, 323, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 325, 324, - 326, 327, 328, 328, 328, 329, 329, 330, 330, 330, - 331, 331, 332, 332, 333, 333, 334, 335, 335, 335, - 336, 337, 338, 339, 340, 340, 341, 341, 342, 343, - 343, 344, 345, 346, 346, 347, 347, 348, 348, 349, - 349, 350, 350, 351, 352, 351, 353, 354, 355, 356, - 357, 351, 358, 358, 358, 358, 359, 359, 360, 361, - 361, 361, 361, 362, 363, 363, 364, 364, 364, 364, - 365, 365, 365, 365, 365, 366, 366, 366, 366, 366, - 366, 366, 367, 367, 368, 368, 369, 369, 371, 370, - 370, 372, 372, 373, 372, 374, 374, 374, 374, 374, - 375, 375, 376, 376, 376, 376, 376, 376, 376, 376, - 376, 376, 376, 376, 376, 376, 376, 377, 378, 378, - 378, 378, 379, 379, 380, 381, 381, 382, 382, 383, - 384, 384, 385, 385, 386, 386, 387, 387, 388, 388, - 389, 390, 390, 391, 392, 393, 393, 394, 394, 395, - 395, 396, 396, 397, 397, 398, 399, 399, 400, 401, - 400, 402, 402, 403, 403, 404, 404, 404, 404, 405, - 405, 405, 406, 406, 406, 406, 407, 407, 407, 408, - 408, 409, 409, 410, 410, 411, 411, 412, 412, 413, - 414, 415, 416, 416, 416, 417, 417, 418, 418, 419 + 314, 315, 315, 316, 317, 317, 317, 317, 317, 318, + 318, 319, 319, 320, 320, 321, 321, 322, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 325, 324, 326, + 327, 328, 328, 328, 329, 329, 330, 330, 330, 331, + 331, 332, 332, 333, 333, 334, 335, 335, 335, 336, + 337, 338, 339, 340, 340, 341, 341, 342, 343, 343, + 344, 345, 346, 346, 347, 347, 348, 348, 349, 349, + 350, 350, 351, 352, 351, 353, 354, 355, 356, 357, + 351, 358, 358, 358, 358, 359, 359, 360, 361, 361, + 361, 361, 362, 363, 363, 364, 364, 364, 364, 365, + 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, + 366, 367, 367, 368, 368, 369, 369, 371, 370, 370, + 372, 372, 373, 372, 374, 374, 374, 374, 374, 375, + 375, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 376, 376, 376, 376, 376, 376, 377, 378, 378, 378, + 378, 379, 379, 380, 381, 381, 382, 382, 383, 384, + 384, 385, 385, 386, 386, 387, 387, 388, 388, 389, + 390, 390, 391, 392, 393, 393, 394, 394, 395, 395, + 396, 396, 397, 397, 398, 399, 399, 400, 401, 400, + 402, 402, 403, 403, 404, 404, 404, 404, 405, 405, + 405, 406, 406, 406, 406, 407, 407, 407, 408, 408, + 409, 409, 410, 410, 411, 411, 412, 412, 413, 414, + 415, 415, 415, 416, 416, 417, 417, 418 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +static const yytype_int8 yyr2[] = { 0, 2, 0, 2, 2, 1, 1, 3, 2, 1, 2, 3, 0, 6, 3, 2, 1, 1, 3, 2, @@ -5089,30 +5199,30 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 4, 4, 3, 4, 4, 3, 0, 4, 2, 0, 4, 2, 0, 4, 1, 1, 2, 3, 5, 2, 4, 1, 2, 3, 2, 4, 1, - 3, 1, 3, 1, 3, 1, 2, 1, 3, 1, - 1, 3, 2, 1, 1, 3, 2, 1, 2, 1, - 3, 3, 2, 2, 1, 1, 1, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, - 1, 2, 2, 3, 1, 6, 1, 1, 1, 1, - 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, - 3, 3, 3, 4, 0, 3, 1, 2, 4, 0, - 3, 4, 4, 0, 3, 0, 3, 0, 2, 0, - 2, 0, 2, 1, 0, 3, 0, 0, 0, 0, - 0, 8, 1, 1, 1, 1, 1, 1, 2, 1, - 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, + 3, 1, 3, 1, 3, 1, 1, 3, 1, 1, + 3, 2, 1, 1, 3, 2, 1, 2, 1, 3, + 3, 2, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, + 2, 2, 3, 1, 6, 1, 1, 1, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, + 3, 3, 4, 0, 3, 1, 2, 4, 0, 3, + 4, 4, 0, 3, 0, 3, 0, 2, 0, 2, + 0, 2, 1, 0, 3, 0, 0, 0, 0, 0, + 8, 1, 1, 1, 1, 1, 1, 2, 1, 1, + 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, - 0, 3, 3, 0, 3, 4, 2, 2, 2, 1, - 2, 0, 6, 8, 4, 6, 4, 6, 2, 4, - 6, 2, 4, 2, 4, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, - 2, 1, 2, 1, 1, 3, 1, 3, 1, 1, - 2, 2, 1, 3, 3, 1, 3, 1, 3, 1, - 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, - 4, 1, 2, 1, 3, 3, 2, 4, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, + 3, 3, 0, 3, 4, 2, 2, 2, 1, 2, + 0, 6, 8, 4, 6, 4, 6, 2, 4, 6, + 2, 4, 2, 4, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 3, 1, 2, + 1, 2, 1, 1, 3, 1, 3, 1, 1, 2, + 2, 1, 3, 3, 1, 3, 1, 3, 1, 1, + 2, 1, 1, 1, 2, 2, 1, 1, 0, 4, + 1, 2, 1, 3, 3, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 0, 1, 2, - 2, 2, 0, 1, 1, 1, 1, 1, 2, 0 + 1, 1, 1, 1, 0, 1, 0, 1, 2, 2, + 0, 1, 1, 1, 1, 1, 2, 0 }; @@ -5128,22 +5238,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, p, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, p, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -5202,10 +5312,10 @@ do { \ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED -static unsigned +static int yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { - unsigned res = 0; + int res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { @@ -5248,40 +5358,42 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yylocationp); YYUSE (p); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) { YYFPRINTF (p, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - YY_LOCATION_PRINT (yyoutput, *yylocationp); + YY_LOCATION_PRINT (yyo, *yylocationp); YYFPRINTF (p, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, p); + yy_symbol_value_print (yyo, yytype, yyvaluep, yylocationp, p); YYFPRINTF (p, ")"); } @@ -5291,7 +5403,7 @@ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYL `------------------------------------------------------------------*/ static void -ruby_parser_yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop, struct parser_params *p) +ruby_parser_yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop, struct parser_params *p) #define yy_stack_print(b, t) ruby_parser_yy_stack_print(b, t, p) { YYFPRINTF (p, "Stack now"); @@ -5315,12 +5427,12 @@ do { \ `------------------------------------------------*/ static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct parser_params *p) +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct parser_params *p) { - unsigned long int yylno = yyrline[yyrule]; + int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - YYFPRINTF (p, "Reducing stack by rule %d (line %lu):\n", + YYFPRINTF (p, "Reducing stack by rule %d (line %d):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) @@ -5328,7 +5440,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule YYFPRINTF (p, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , &(yylsp[(yyi + 1) - (yynrhs)]) , p); YYFPRINTF (p, "\n"); } @@ -5374,13 +5486,13 @@ int yydebug; # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen +# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) # else /* Return the length of YYSTR. */ -static YYSIZE_T +static YYPTRDIFF_T yystrlen (const char *yystr) { - YYSIZE_T yylen; + YYPTRDIFF_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; @@ -5416,12 +5528,12 @@ yystpcpy (char *yydest, const char *yysrc) backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ -static YYSIZE_T +static YYPTRDIFF_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { - YYSIZE_T yyn = 0; + YYPTRDIFF_T yyn = 0; char const *yyp = yystr; for (;;) @@ -5434,7 +5546,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -5449,10 +5564,10 @@ yytnamerr (char *yyres, const char *yystr) do_not_strip_quotes: ; } - if (! yyres) + if (yyres) + return yystpcpy (yyres, yystr) - yyres; + else return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; } # endif @@ -5465,19 +5580,19 @@ yytnamerr (char *yyres, const char *yystr) *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int -yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +yysyntax_error (struct parser_params *p, YYPTRDIFF_T *yymsg_alloc, char **yymsg, + yy_state_t *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ + /* Arguments of yyformat: reported tokens (one for the "unexpected", + one per "expected"). */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ + /* Actual size of YYARG. */ int yycount = 0; + /* Cumulated lengths of YYARG. */ + YYPTRDIFF_T yysize = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then @@ -5505,6 +5620,8 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; + YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + yysize = yysize0; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { @@ -5529,11 +5646,12 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } yyarg[yycount++] = yytname[yyx]; { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + YYPTRDIFF_T yysize1 + = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -5545,6 +5663,7 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -5555,10 +5674,13 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + /* Don't count the "%s"s in the final size, but reserve room for + the terminator. */ + YYPTRDIFF_T yysize1 = yysize + (yystrlen (yyformat) - 2 * yycount) + 1; + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -5584,8 +5706,8 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } else { - yyp++; - yyformat++; + ++yyp; + ++yyformat; } } return 0; @@ -5642,7 +5764,7 @@ YYLTYPE yylloc = yyloc_default; /* Number of syntax errors so far. */ int yynerrs; - int yystate; + yy_state_fast_t yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -5655,9 +5777,9 @@ YYLTYPE yylloc = yyloc_default; to reallocate them elsewhere. */ /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss; + yy_state_t *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -5672,7 +5794,7 @@ YYLTYPE yylloc = yyloc_default; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; - YYSIZE_T yystacksize; + YYPTRDIFF_T yystacksize; int yyn; int yyresult; @@ -5687,7 +5809,7 @@ YYLTYPE yylloc = yyloc_default; /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; + YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) @@ -5709,38 +5831,51 @@ YYLTYPE yylloc = yyloc_default; yychar = YYEMPTY; /* Cause a token to be read. */ /* User initialization code. */ -#line 974 "ripper.y" /* yacc.c:1429 */ +#line 992 "ripper.y" { RUBY_SET_YYLLOC_OF_NONE(yylloc); } -#line 5713 "ripper.c" /* yacc.c:1429 */ +#line 5835 "ripper.c" + yylsp[0] = yylloc; goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((p, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYPTRDIFF_T yysize = yyssp - yyss + 1; -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ + yy_state_t *yyss1 = yyss; YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the @@ -5748,19 +5883,15 @@ YYLTYPE yylloc = yyloc_default; conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yyls1, yysize * YYSIZEOF (*yylsp), &yystacksize); - - yyls = yyls1; yyss = yyss1; yyvs = yyvs1; + yyls = yyls1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -5769,44 +5900,45 @@ YYLTYPE yylloc = yyloc_default; yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; + yy_state_t *yyss1 = yyss; union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; - YYDPRINTF ((p, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((p, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) YYABORT; } - - YYDPRINTF ((p, "Entering state %d\n", yystate)); +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ if (yystate == YYFINAL) YYACCEPT; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -5856,15 +5988,14 @@ YYLTYPE yylloc = yyloc_default; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; + + /* Discard the shifted token. */ + yychar = YYEMPTY; goto yynewstate; @@ -5879,7 +6010,7 @@ YYLTYPE yylloc = yyloc_default; /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -5895,23 +6026,24 @@ YYLTYPE yylloc = yyloc_default; GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ + /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 1176 "ripper.y" /* yacc.c:1646 */ - { + case 2: +#line 1194 "ripper.y" + { SET_LEX_STATE(EXPR_BEG); local_push(p, ifndef_ripper(1)+0); } -#line 5905 "ripper.c" /* yacc.c:1646 */ +#line 6037 "ripper.c" break; case 3: -#line 1181 "ripper.y" /* yacc.c:1646 */ - { +#line 1199 "ripper.y" + { #if 0 if ((yyvsp[0].val) && !compile_for_eval) { NODE *node = (yyvsp[0].val); @@ -5930,69 +6062,69 @@ YYLTYPE yylloc = yyloc_default; {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(program,v1);p->result=v2;} local_pop(p); } -#line 5929 "ripper.c" /* yacc.c:1646 */ +#line 6061 "ripper.c" break; case 4: -#line 1203 "ripper.y" /* yacc.c:1646 */ - { +#line 1221 "ripper.y" + { (yyval.val) = void_stmts(p, (yyvsp[-1].val)); } -#line 5937 "ripper.c" /* yacc.c:1646 */ +#line 6069 "ripper.c" break; case 5: -#line 1209 "ripper.y" /* yacc.c:1646 */ - { +#line 1227 "ripper.y" + { #if 0 (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=dispatch0(stmts_new);v2=dispatch0(void_stmt);v3=v1;v4=v2;v5=dispatch2(stmts_add,v3,v4);(yyval.val)=v5;} } -#line 5948 "ripper.c" /* yacc.c:1646 */ +#line 6080 "ripper.c" break; case 6: -#line 1216 "ripper.y" /* yacc.c:1646 */ - { +#line 1234 "ripper.y" + { #if 0 (yyval.val) = newline_node((yyvsp[0].val)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(stmts_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(stmts_add,v2,v3);(yyval.val)=v4;} } -#line 5959 "ripper.c" /* yacc.c:1646 */ +#line 6091 "ripper.c" break; case 7: -#line 1223 "ripper.y" /* yacc.c:1646 */ - { +#line 1241 "ripper.y" + { #if 0 (yyval.val) = block_append(p, (yyvsp[-2].val), newline_node((yyvsp[0].val))); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(stmts_add,v1,v2);(yyval.val)=v3;} } -#line 5970 "ripper.c" /* yacc.c:1646 */ +#line 6102 "ripper.c" break; case 8: -#line 1230 "ripper.y" /* yacc.c:1646 */ - { +#line 1248 "ripper.y" + { (yyval.val) = remove_begin((yyvsp[0].val)); } -#line 5978 "ripper.c" /* yacc.c:1646 */ +#line 6110 "ripper.c" break; case 10: -#line 1237 "ripper.y" /* yacc.c:1646 */ - { +#line 1255 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 5986 "ripper.c" /* yacc.c:1646 */ +#line 6118 "ripper.c" break; case 11: -#line 1243 "ripper.y" /* yacc.c:1646 */ - { +#line 1261 "ripper.y" + { #if 0 p->eval_tree_begin = block_append(p, p->eval_tree_begin, NEW_BEGIN((yyvsp[-1].val), &(yyloc))); @@ -6000,141 +6132,141 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(BEGIN,v1);(yyval.val)=v2;} } -#line 5999 "ripper.c" /* yacc.c:1646 */ +#line 6131 "ripper.c" break; case 12: -#line 1255 "ripper.y" /* yacc.c:1646 */ - {if (!(yyvsp[-1].val)) {yyerror1(&(yylsp[0]), "else without rescue is useless");}} -#line 6005 "ripper.c" /* yacc.c:1646 */ +#line 1273 "ripper.y" + {if (!(yyvsp[-1].val)) {yyerror1(&(yylsp[0]), "else without rescue is useless");}} +#line 6137 "ripper.c" break; case 13: -#line 1258 "ripper.y" /* yacc.c:1646 */ - { +#line 1276 "ripper.y" + { #if 0 (yyval.val) = new_bodystmt(p, (yyvsp[-5].val), (yyvsp[-4].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=escape_Qundef((yyvsp[-5].val));v2=escape_Qundef((yyvsp[-4].val));v3=escape_Qundef((yyvsp[-1].val));v4=escape_Qundef((yyvsp[0].val));v5=dispatch4(bodystmt,v1,v2,v3,v4);(yyval.val)=v5;} } -#line 6016 "ripper.c" /* yacc.c:1646 */ +#line 6148 "ripper.c" break; case 14: -#line 1267 "ripper.y" /* yacc.c:1646 */ - { +#line 1285 "ripper.y" + { #if 0 (yyval.val) = new_bodystmt(p, (yyvsp[-2].val), (yyvsp[-1].val), 0, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=escape_Qundef((yyvsp[-2].val));v2=escape_Qundef((yyvsp[-1].val));v3=Qnil;v4=escape_Qundef((yyvsp[0].val));v5=dispatch4(bodystmt,v1,v2,v3,v4);(yyval.val)=v5;} } -#line 6027 "ripper.c" /* yacc.c:1646 */ +#line 6159 "ripper.c" break; case 15: -#line 1276 "ripper.y" /* yacc.c:1646 */ - { +#line 1294 "ripper.y" + { (yyval.val) = void_stmts(p, (yyvsp[-1].val)); } -#line 6035 "ripper.c" /* yacc.c:1646 */ +#line 6167 "ripper.c" break; case 16: -#line 1282 "ripper.y" /* yacc.c:1646 */ - { +#line 1300 "ripper.y" + { #if 0 (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=dispatch0(stmts_new);v2=dispatch0(void_stmt);v3=v1;v4=v2;v5=dispatch2(stmts_add,v3,v4);(yyval.val)=v5;} } -#line 6046 "ripper.c" /* yacc.c:1646 */ +#line 6178 "ripper.c" break; case 17: -#line 1289 "ripper.y" /* yacc.c:1646 */ - { +#line 1307 "ripper.y" + { #if 0 (yyval.val) = newline_node((yyvsp[0].val)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(stmts_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(stmts_add,v2,v3);(yyval.val)=v4;} } -#line 6057 "ripper.c" /* yacc.c:1646 */ +#line 6189 "ripper.c" break; case 18: -#line 1296 "ripper.y" /* yacc.c:1646 */ - { +#line 1314 "ripper.y" + { #if 0 (yyval.val) = block_append(p, (yyvsp[-2].val), newline_node((yyvsp[0].val))); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(stmts_add,v1,v2);(yyval.val)=v3;} } -#line 6068 "ripper.c" /* yacc.c:1646 */ +#line 6200 "ripper.c" break; case 19: -#line 1303 "ripper.y" /* yacc.c:1646 */ - { +#line 1321 "ripper.y" + { (yyval.val) = remove_begin((yyvsp[0].val)); } -#line 6076 "ripper.c" /* yacc.c:1646 */ +#line 6208 "ripper.c" break; case 20: -#line 1309 "ripper.y" /* yacc.c:1646 */ - { +#line 1327 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 6084 "ripper.c" /* yacc.c:1646 */ +#line 6216 "ripper.c" break; case 21: -#line 1313 "ripper.y" /* yacc.c:1646 */ - { +#line 1331 "ripper.y" + { yyerror1(&(yylsp[0]), "BEGIN is permitted only at toplevel"); } -#line 6092 "ripper.c" /* yacc.c:1646 */ +#line 6224 "ripper.c" break; case 22: -#line 1317 "ripper.y" /* yacc.c:1646 */ - { +#line 1335 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 6100 "ripper.c" /* yacc.c:1646 */ +#line 6232 "ripper.c" break; case 23: -#line 1322 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} -#line 6106 "ripper.c" /* yacc.c:1646 */ +#line 1340 "ripper.y" + {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} +#line 6238 "ripper.c" break; case 24: -#line 1323 "ripper.y" /* yacc.c:1646 */ - { +#line 1341 "ripper.y" + { #if 0 (yyval.val) = NEW_ALIAS((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(alias,v1,v2);(yyval.val)=v3;} } -#line 6117 "ripper.c" /* yacc.c:1646 */ +#line 6249 "ripper.c" break; case 25: -#line 1330 "ripper.y" /* yacc.c:1646 */ - { +#line 1348 "ripper.y" + { #if 0 (yyval.val) = NEW_VALIAS((yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(var_alias,v1,v2);(yyval.val)=v3;} } -#line 6128 "ripper.c" /* yacc.c:1646 */ +#line 6260 "ripper.c" break; case 26: -#line 1337 "ripper.y" /* yacc.c:1646 */ - { +#line 1355 "ripper.y" + { #if 0 char buf[2]; buf[0] = '$'; @@ -6143,59 +6275,59 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(var_alias,v1,v2);(yyval.val)=v3;} } -#line 6142 "ripper.c" /* yacc.c:1646 */ +#line 6274 "ripper.c" break; case 27: -#line 1347 "ripper.y" /* yacc.c:1646 */ - { +#line 1365 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "can't make alias for the number variables"); (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(var_alias,v1,v2);v4=v3;v5=dispatch1(alias_error,v4);(yyval.val)=v5;}ripper_error(p); } -#line 6154 "ripper.c" /* yacc.c:1646 */ +#line 6286 "ripper.c" break; case 28: -#line 1355 "ripper.y" /* yacc.c:1646 */ - { +#line 1373 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(undef,v1);(yyval.val)=v2;} } -#line 6165 "ripper.c" /* yacc.c:1646 */ +#line 6297 "ripper.c" break; case 29: -#line 1362 "ripper.y" /* yacc.c:1646 */ - { +#line 1380 "ripper.y" + { #if 0 (yyval.val) = new_if(p, (yyvsp[0].val), remove_begin((yyvsp[-2].val)), 0, &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(if_mod,v1,v2);(yyval.val)=v3;} } -#line 6177 "ripper.c" /* yacc.c:1646 */ +#line 6309 "ripper.c" break; case 30: -#line 1370 "ripper.y" /* yacc.c:1646 */ - { +#line 1388 "ripper.y" + { #if 0 (yyval.val) = new_unless(p, (yyvsp[0].val), remove_begin((yyvsp[-2].val)), 0, &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(unless_mod,v1,v2);(yyval.val)=v3;} } -#line 6189 "ripper.c" /* yacc.c:1646 */ +#line 6321 "ripper.c" break; case 31: -#line 1378 "ripper.y" /* yacc.c:1646 */ - { +#line 1396 "ripper.y" + { #if 0 if ((yyvsp[-2].val) && nd_type((yyvsp[-2].val)) == NODE_BEGIN) { (yyval.val) = NEW_WHILE(cond(p, (yyvsp[0].val), &(yylsp[0])), (yyvsp[-2].val)->nd_body, 0, &(yyloc)); @@ -6206,12 +6338,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(while_mod,v1,v2);(yyval.val)=v3;} } -#line 6205 "ripper.c" /* yacc.c:1646 */ +#line 6337 "ripper.c" break; case 32: -#line 1390 "ripper.y" /* yacc.c:1646 */ - { +#line 1408 "ripper.y" + { #if 0 if ((yyvsp[-2].val) && nd_type((yyvsp[-2].val)) == NODE_BEGIN) { (yyval.val) = NEW_UNTIL(cond(p, (yyvsp[0].val), &(yylsp[0])), (yyvsp[-2].val)->nd_body, 0, &(yyloc)); @@ -6222,12 +6354,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(until_mod,v1,v2);(yyval.val)=v3;} } -#line 6221 "ripper.c" /* yacc.c:1646 */ +#line 6353 "ripper.c" break; case 33: -#line 1402 "ripper.y" /* yacc.c:1646 */ - { +#line 1420 "ripper.y" + { #if 0 NODE *resq; YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); @@ -6236,12 +6368,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(rescue_mod,v1,v2);(yyval.val)=v3;} } -#line 6235 "ripper.c" /* yacc.c:1646 */ +#line 6367 "ripper.c" break; case 34: -#line 1412 "ripper.y" /* yacc.c:1646 */ - { +#line 1430 "ripper.y" + { if (p->in_def) { rb_warn0("END in method; use at_exit"); } @@ -6254,36 +6386,36 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(END,v1);(yyval.val)=v2;} } -#line 6253 "ripper.c" /* yacc.c:1646 */ +#line 6385 "ripper.c" break; case 36: -#line 1427 "ripper.y" /* yacc.c:1646 */ - { +#line 1445 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = node_assign(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(massign,v1,v2);(yyval.val)=v3;} } -#line 6265 "ripper.c" /* yacc.c:1646 */ +#line 6397 "ripper.c" break; case 37: -#line 1435 "ripper.y" /* yacc.c:1646 */ - { +#line 1453 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = node_assign(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(assign,v1,v2);(yyval.val)=v3;} } -#line 6277 "ripper.c" /* yacc.c:1646 */ +#line 6409 "ripper.c" break; case 38: -#line 1443 "ripper.y" /* yacc.c:1646 */ - { +#line 1461 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].val)); @@ -6291,123 +6423,129 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(rescue_mod,v1,v2);v4=(yyvsp[-4].val);v5=v3;v6=dispatch2(massign,v4,v5);(yyval.val)=v6;} } -#line 6290 "ripper.c" /* yacc.c:1646 */ +#line 6422 "ripper.c" break; case 39: -#line 1452 "ripper.y" /* yacc.c:1646 */ - { +#line 1470 "ripper.y" + { #if 0 (yyval.val) = node_assign(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(massign,v1,v2);(yyval.val)=v3;} } -#line 6301 "ripper.c" /* yacc.c:1646 */ +#line 6433 "ripper.c" break; case 41: -#line 1462 "ripper.y" /* yacc.c:1646 */ - { +#line 1480 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = node_assign(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(assign,v1,v2);(yyval.val)=v3;} } -#line 6312 "ripper.c" /* yacc.c:1646 */ +#line 6445 "ripper.c" break; case 42: -#line 1469 "ripper.y" /* yacc.c:1646 */ - { +#line 1488 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = new_op_assign(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(opassign,v1,v2,v3);(yyval.val)=v4;} } -#line 6323 "ripper.c" /* yacc.c:1646 */ +#line 6457 "ripper.c" break; case 43: -#line 1476 "ripper.y" /* yacc.c:1646 */ - { +#line 1496 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = new_ary_op_assign(p, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-3]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-5].val);v2=escape_Qundef((yyvsp[-3].val));v3=dispatch2(aref_field,v1,v2);v4=v3;v5=(yyvsp[-1].val);v6=(yyvsp[0].val);v7=dispatch3(opassign,v4,v5,v6);(yyval.val)=v7;} } -#line 6335 "ripper.c" /* yacc.c:1646 */ +#line 6470 "ripper.c" break; case 44: -#line 1484 "ripper.y" /* yacc.c:1646 */ - { +#line 1505 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), (yyvsp[-3].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 6346 "ripper.c" /* yacc.c:1646 */ +#line 6482 "ripper.c" break; case 45: -#line 1491 "ripper.y" /* yacc.c:1646 */ - { +#line 1513 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), (yyvsp[-3].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 6357 "ripper.c" /* yacc.c:1646 */ +#line 6494 "ripper.c" break; case 46: -#line 1498 "ripper.y" /* yacc.c:1646 */ - { +#line 1521 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-4]), &(yylsp[-2])); (yyval.val) = new_const_op_assign(p, NEW_COLON2((yyvsp[-4].val), (yyvsp[-2].val), &loc), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=dispatch2(const_path_field,v1,v2);v4=v3;v5=(yyvsp[-1].val);v6=(yyvsp[0].val);v7=dispatch3(opassign,v4,v5,v6);(yyval.val)=v7;} } -#line 6369 "ripper.c" /* yacc.c:1646 */ +#line 6506 "ripper.c" break; case 47: -#line 1506 "ripper.y" /* yacc.c:1646 */ - { +#line 1529 "ripper.y" + { #if 0 + value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), ID2VAL(idCOLON2), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 6380 "ripper.c" /* yacc.c:1646 */ +#line 6518 "ripper.c" break; case 48: -#line 1513 "ripper.y" /* yacc.c:1646 */ - { +#line 1537 "ripper.y" + { #if 0 rb_backref_error(p, (yyvsp[-2].val)); (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=var_field(p, (yyvsp[-2].val));v2=(yyvsp[0].val);v3=dispatch2(assign,v1,v2);v4=v3;v5=dispatch1(assign_error,v4);(yyval.val)=v5;}ripper_error(p); } -#line 6392 "ripper.c" /* yacc.c:1646 */ +#line 6530 "ripper.c" break; case 49: -#line 1523 "ripper.y" /* yacc.c:1646 */ - { +#line 1547 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 6401 "ripper.c" /* yacc.c:1646 */ +#line 6539 "ripper.c" break; case 50: -#line 1528 "ripper.y" /* yacc.c:1646 */ - { +#line 1552 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].val)); @@ -6415,144 +6553,144 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(rescue_mod,v1,v2);(yyval.val)=v3;} } -#line 6414 "ripper.c" /* yacc.c:1646 */ +#line 6552 "ripper.c" break; case 53: -#line 1541 "ripper.y" /* yacc.c:1646 */ - { +#line 1565 "ripper.y" + { (yyval.val) = logop(p, idAND, (yyvsp[-2].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 6422 "ripper.c" /* yacc.c:1646 */ +#line 6560 "ripper.c" break; case 54: -#line 1545 "ripper.y" /* yacc.c:1646 */ - { +#line 1569 "ripper.y" + { (yyval.val) = logop(p, idOR, (yyvsp[-2].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 6430 "ripper.c" /* yacc.c:1646 */ +#line 6568 "ripper.c" break; case 55: -#line 1549 "ripper.y" /* yacc.c:1646 */ - { +#line 1573 "ripper.y" + { (yyval.val) = call_uni_op(p, method_cond(p, (yyvsp[0].val), &(yylsp[0])), METHOD_NOT, &(yylsp[-2]), &(yyloc)); } -#line 6438 "ripper.c" /* yacc.c:1646 */ +#line 6576 "ripper.c" break; case 56: -#line 1553 "ripper.y" /* yacc.c:1646 */ - { +#line 1577 "ripper.y" + { (yyval.val) = call_uni_op(p, method_cond(p, (yyvsp[0].val), &(yylsp[0])), '!', &(yylsp[-1]), &(yyloc)); } -#line 6446 "ripper.c" /* yacc.c:1646 */ +#line 6584 "ripper.c" break; case 57: -#line 1557 "ripper.y" /* yacc.c:1646 */ - { +#line 1581 "ripper.y" + { value_expr((yyvsp[-1].val)); SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; (yyval.num) = p->in_kwarg; p->in_kwarg = 1; } -#line 6458 "ripper.c" /* yacc.c:1646 */ +#line 6596 "ripper.c" break; case 58: -#line 1564 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pvtbl(p);} -#line 6464 "ripper.c" /* yacc.c:1646 */ +#line 1588 "ripper.y" + {(yyval.tbl) = push_pvtbl(p);} +#line 6602 "ripper.c" break; case 59: -#line 1566 "ripper.y" /* yacc.c:1646 */ - {pop_pvtbl(p, (yyvsp[-1].tbl));} -#line 6470 "ripper.c" /* yacc.c:1646 */ +#line 1590 "ripper.y" + {pop_pvtbl(p, (yyvsp[-1].tbl));} +#line 6608 "ripper.c" break; case 60: -#line 1567 "ripper.y" /* yacc.c:1646 */ - { +#line 1591 "ripper.y" + { p->in_kwarg = !!(yyvsp[-3].num); #if 0 (yyval.val) = new_case3(p, (yyvsp[-5].val), NEW_IN((yyvsp[-1].val), 0, 0, &(yylsp[-1])), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-1].val);v2=Qnil;v3=Qnil;v4=dispatch3(in,v1,v2,v3);v5=(yyvsp[-5].val);v6=v4;v7=dispatch2(case,v5,v6);(yyval.val)=v7;} } -#line 6482 "ripper.c" /* yacc.c:1646 */ +#line 6620 "ripper.c" break; case 62: -#line 1578 "ripper.y" /* yacc.c:1646 */ - { +#line 1602 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 6491 "ripper.c" /* yacc.c:1646 */ +#line 6629 "ripper.c" break; case 63: -#line 1584 "ripper.y" /* yacc.c:1646 */ - {COND_PUSH(1);} -#line 6497 "ripper.c" /* yacc.c:1646 */ +#line 1608 "ripper.y" + {COND_PUSH(1);} +#line 6635 "ripper.c" break; case 64: -#line 1584 "ripper.y" /* yacc.c:1646 */ - {COND_POP();} -#line 6503 "ripper.c" /* yacc.c:1646 */ +#line 1608 "ripper.y" + {COND_POP();} +#line 6641 "ripper.c" break; case 65: -#line 1585 "ripper.y" /* yacc.c:1646 */ - { +#line 1609 "ripper.y" + { (yyval.val) = (yyvsp[-2].val); } -#line 6511 "ripper.c" /* yacc.c:1646 */ +#line 6649 "ripper.c" break; case 69: -#line 1596 "ripper.y" /* yacc.c:1646 */ - { +#line 1620 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, (yyvsp[-2].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-3].val);v2=(yyvsp[-2].val);v3=(yyvsp[-1].val);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 6522 "ripper.c" /* yacc.c:1646 */ +#line 6660 "ripper.c" break; case 70: -#line 1605 "ripper.y" /* yacc.c:1646 */ - { +#line 1629 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); #if 0 (yyval.val)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.val), (yylsp[-2]).end_pos.lineno); #endif } -#line 6534 "ripper.c" /* yacc.c:1646 */ +#line 6672 "ripper.c" break; case 71: -#line 1615 "ripper.y" /* yacc.c:1646 */ - { +#line 1639 "ripper.y" + { #if 0 (yyval.val) = NEW_FCALL((yyvsp[0].val), 0, &(yyloc)); nd_set_line((yyval.val), p->tokline); #endif (yyval.val)=(yyvsp[0].val); } -#line 6546 "ripper.c" /* yacc.c:1646 */ +#line 6684 "ripper.c" break; case 72: -#line 1625 "ripper.y" /* yacc.c:1646 */ - { +#line 1649 "ripper.y" + { #if 0 (yyvsp[-1].val)->nd_args = (yyvsp[0].val); nd_set_last_loc((yyvsp[-1].val), (yylsp[0]).end_pos); @@ -6560,12 +6698,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(command,v1,v2);(yyval.val)=v3;} } -#line 6559 "ripper.c" /* yacc.c:1646 */ +#line 6697 "ripper.c" break; case 73: -#line 1634 "ripper.y" /* yacc.c:1646 */ - { +#line 1658 "ripper.y" + { #if 0 block_dup_check(p, (yyvsp[-1].val), (yyvsp[0].val)); (yyvsp[-2].val)->nd_args = (yyvsp[-1].val); @@ -6575,333 +6713,333 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(command,v1,v2);v4=v3;v5=(yyvsp[0].val);v6=dispatch2(method_add_block,v4,v5);(yyval.val)=v6;} } -#line 6574 "ripper.c" /* yacc.c:1646 */ +#line 6712 "ripper.c" break; case 74: -#line 1645 "ripper.y" /* yacc.c:1646 */ - { +#line 1669 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, (yyvsp[-2].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), Qnull, &(yylsp[-1]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-3].val);v2=(yyvsp[-2].val);v3=(yyvsp[-1].val);v4=(yyvsp[0].val);v5=dispatch4(command_call,v1,v2,v3,v4);(yyval.val)=v5;} } -#line 6585 "ripper.c" /* yacc.c:1646 */ +#line 6723 "ripper.c" break; case 75: -#line 1652 "ripper.y" /* yacc.c:1646 */ - { +#line 1676 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, (yyvsp[-3].val), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-2]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=(yyvsp[-1].val);v5=dispatch4(command_call,v1,v2,v3,v4);v6=v5;v7=(yyvsp[0].val);v8=dispatch2(method_add_block,v6,v7);(yyval.val)=v8;} } -#line 6596 "ripper.c" /* yacc.c:1646 */ +#line 6734 "ripper.c" break; case 76: -#line 1659 "ripper.y" /* yacc.c:1646 */ - { +#line 1683 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, ID2VAL(idCOLON2), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), Qnull, &(yylsp[-1]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-3].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[-1].val);v4=(yyvsp[0].val);v5=dispatch4(command_call,v1,v2,v3,v4);(yyval.val)=v5;} } -#line 6607 "ripper.c" /* yacc.c:1646 */ +#line 6745 "ripper.c" break; case 77: -#line 1666 "ripper.y" /* yacc.c:1646 */ - { +#line 1690 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, ID2VAL(idCOLON2), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-2]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[-2].val);v4=(yyvsp[-1].val);v5=dispatch4(command_call,v1,v2,v3,v4);v6=v5;v7=(yyvsp[0].val);v8=dispatch2(method_add_block,v6,v7);(yyval.val)=v8;} } -#line 6618 "ripper.c" /* yacc.c:1646 */ +#line 6756 "ripper.c" break; case 78: -#line 1673 "ripper.y" /* yacc.c:1646 */ - { +#line 1697 "ripper.y" + { #if 0 (yyval.val) = NEW_SUPER((yyvsp[0].val), &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(super,v1);(yyval.val)=v2;} } -#line 6630 "ripper.c" /* yacc.c:1646 */ +#line 6768 "ripper.c" break; case 79: -#line 1681 "ripper.y" /* yacc.c:1646 */ - { +#line 1705 "ripper.y" + { #if 0 (yyval.val) = new_yield(p, (yyvsp[0].val), &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(yield,v1);(yyval.val)=v2;} } -#line 6642 "ripper.c" /* yacc.c:1646 */ +#line 6780 "ripper.c" break; case 80: -#line 1689 "ripper.y" /* yacc.c:1646 */ - { +#line 1713 "ripper.y" + { #if 0 (yyval.val) = NEW_RETURN(ret_args(p, (yyvsp[0].val)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(return,v1);(yyval.val)=v2;} } -#line 6653 "ripper.c" /* yacc.c:1646 */ +#line 6791 "ripper.c" break; case 81: -#line 1696 "ripper.y" /* yacc.c:1646 */ - { +#line 1720 "ripper.y" + { #if 0 (yyval.val) = NEW_BREAK(ret_args(p, (yyvsp[0].val)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(break,v1);(yyval.val)=v2;} } -#line 6664 "ripper.c" /* yacc.c:1646 */ +#line 6802 "ripper.c" break; case 82: -#line 1703 "ripper.y" /* yacc.c:1646 */ - { +#line 1727 "ripper.y" + { #if 0 (yyval.val) = NEW_NEXT(ret_args(p, (yyvsp[0].val)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(next,v1);(yyval.val)=v2;} } -#line 6675 "ripper.c" /* yacc.c:1646 */ +#line 6813 "ripper.c" break; case 84: -#line 1713 "ripper.y" /* yacc.c:1646 */ - { +#line 1737 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(mlhs_paren,v1);(yyval.val)=v2;} } -#line 6686 "ripper.c" /* yacc.c:1646 */ +#line 6824 "ripper.c" break; case 86: -#line 1723 "ripper.y" /* yacc.c:1646 */ - { +#line 1747 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(NEW_LIST((yyvsp[-1].val), &(yyloc)), 0, &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(mlhs_paren,v1);(yyval.val)=v2;} } -#line 6697 "ripper.c" /* yacc.c:1646 */ +#line 6835 "ripper.c" break; case 87: -#line 1732 "ripper.y" /* yacc.c:1646 */ - { +#line 1756 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=(yyvsp[0].val); } -#line 6708 "ripper.c" /* yacc.c:1646 */ +#line 6846 "ripper.c" break; case 88: -#line 1739 "ripper.y" /* yacc.c:1646 */ - { +#line 1763 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(list_append(p, (yyvsp[-1].val),(yyvsp[0].val)), 0, &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(mlhs_add,v1,v2);(yyval.val)=v3;} } -#line 6719 "ripper.c" /* yacc.c:1646 */ +#line 6857 "ripper.c" break; case 89: -#line 1746 "ripper.y" /* yacc.c:1646 */ - { +#line 1770 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(mlhs_add_star,v1,v2);(yyval.val)=v3;} } -#line 6730 "ripper.c" /* yacc.c:1646 */ +#line 6868 "ripper.c" break; case 90: -#line 1753 "ripper.y" /* yacc.c:1646 */ - { +#line 1777 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-4].val), NEW_POSTARG((yyvsp[-2].val),(yyvsp[0].val),&(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=dispatch2(mlhs_add_star,v1,v2);v4=v3;v5=(yyvsp[0].val);v6=dispatch2(mlhs_add_post,v4,v5);(yyval.val)=v6;} } -#line 6741 "ripper.c" /* yacc.c:1646 */ +#line 6879 "ripper.c" break; case 91: -#line 1760 "ripper.y" /* yacc.c:1646 */ - { +#line 1784 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-1].val), NODE_SPECIAL_NO_NAME_REST, &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=Qnil;v3=dispatch2(mlhs_add_star,v1,v2);(yyval.val)=v3;} } -#line 6752 "ripper.c" /* yacc.c:1646 */ +#line 6890 "ripper.c" break; case 92: -#line 1767 "ripper.y" /* yacc.c:1646 */ - { +#line 1791 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-3].val), NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-3].val);v2=Qnil;v3=dispatch2(mlhs_add_star,v1,v2);v4=v3;v5=(yyvsp[0].val);v6=dispatch2(mlhs_add_post,v4,v5);(yyval.val)=v6;} } -#line 6763 "ripper.c" /* yacc.c:1646 */ +#line 6901 "ripper.c" break; case 93: -#line 1774 "ripper.y" /* yacc.c:1646 */ - { +#line 1798 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(mlhs_add_star,v2,v3);(yyval.val)=v4;} } -#line 6774 "ripper.c" /* yacc.c:1646 */ +#line 6912 "ripper.c" break; case 94: -#line 1781 "ripper.y" /* yacc.c:1646 */ - { +#line 1805 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, NEW_POSTARG((yyvsp[-2].val),(yyvsp[0].val),&(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[-2].val);v4=dispatch2(mlhs_add_star,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(mlhs_add_post,v5,v6);(yyval.val)=v7;} } -#line 6785 "ripper.c" /* yacc.c:1646 */ +#line 6923 "ripper.c" break; case 95: -#line 1788 "ripper.y" /* yacc.c:1646 */ - { +#line 1812 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, NODE_SPECIAL_NO_NAME_REST, &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=Qnil;v4=dispatch2(mlhs_add_star,v2,v3);(yyval.val)=v4;} } -#line 6796 "ripper.c" /* yacc.c:1646 */ +#line 6934 "ripper.c" break; case 96: -#line 1795 "ripper.y" /* yacc.c:1646 */ - { +#line 1819 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=dispatch0(mlhs_new);v2=v1;v3=Qnil;v4=dispatch2(mlhs_add_star,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(mlhs_add_post,v5,v6);(yyval.val)=v7;} } -#line 6807 "ripper.c" /* yacc.c:1646 */ +#line 6945 "ripper.c" break; case 98: -#line 1805 "ripper.y" /* yacc.c:1646 */ - { +#line 1829 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(mlhs_paren,v1);(yyval.val)=v2;} } -#line 6818 "ripper.c" /* yacc.c:1646 */ +#line 6956 "ripper.c" break; case 99: -#line 1814 "ripper.y" /* yacc.c:1646 */ - { +#line 1838 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[-1].val), &(yylsp[-1])); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[-1].val);v4=dispatch2(mlhs_add,v2,v3);(yyval.val)=v4;} } -#line 6829 "ripper.c" /* yacc.c:1646 */ +#line 6967 "ripper.c" break; case 100: -#line 1821 "ripper.y" /* yacc.c:1646 */ - { +#line 1845 "ripper.y" + { #if 0 (yyval.val) = list_append(p, (yyvsp[-2].val), (yyvsp[-1].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(mlhs_add,v1,v2);(yyval.val)=v3;} } -#line 6840 "ripper.c" /* yacc.c:1646 */ +#line 6978 "ripper.c" break; case 101: -#line 1830 "ripper.y" /* yacc.c:1646 */ - { +#line 1854 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(mlhs_add,v2,v3);(yyval.val)=v4;} } -#line 6851 "ripper.c" /* yacc.c:1646 */ +#line 6989 "ripper.c" break; case 102: -#line 1837 "ripper.y" /* yacc.c:1646 */ - { +#line 1861 "ripper.y" + { #if 0 (yyval.val) = list_append(p, (yyvsp[-2].val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(mlhs_add,v1,v2);(yyval.val)=v3;} } -#line 6862 "ripper.c" /* yacc.c:1646 */ +#line 7000 "ripper.c" break; case 103: -#line 1846 "ripper.y" /* yacc.c:1646 */ - { +#line 1870 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 6873 "ripper.c" /* yacc.c:1646 */ +#line 7011 "ripper.c" break; case 104: -#line 1853 "ripper.y" /* yacc.c:1646 */ - { +#line 1877 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 6884 "ripper.c" /* yacc.c:1646 */ +#line 7022 "ripper.c" break; case 105: -#line 1860 "ripper.y" /* yacc.c:1646 */ - { +#line 1884 "ripper.y" + { #if 0 (yyval.val) = aryset(p, (yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=escape_Qundef((yyvsp[-1].val));v3=dispatch2(aref_field,v1,v2);(yyval.val)=v3;} } -#line 6895 "ripper.c" /* yacc.c:1646 */ +#line 7033 "ripper.c" break; case 106: -#line 1867 "ripper.y" /* yacc.c:1646 */ - { +#line 1891 "ripper.y" + { if ((yyvsp[-1].val) == tANDDOT) { yyerror1(&(yylsp[-1]), "&. inside multiple assignment destination"); } @@ -6910,23 +7048,23 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(field,v1,v2,v3);(yyval.val)=v4;} } -#line 6909 "ripper.c" /* yacc.c:1646 */ +#line 7047 "ripper.c" break; case 107: -#line 1877 "ripper.y" /* yacc.c:1646 */ - { +#line 1901 "ripper.y" + { #if 0 (yyval.val) = attrset(p, (yyvsp[-2].val), idCOLON2, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_field,v1,v2);(yyval.val)=v3;} } -#line 6920 "ripper.c" /* yacc.c:1646 */ +#line 7058 "ripper.c" break; case 108: -#line 1884 "ripper.y" /* yacc.c:1646 */ - { +#line 1908 "ripper.y" + { if ((yyvsp[-1].val) == tANDDOT) { yyerror1(&(yylsp[-1]), "&. inside multiple assignment destination"); } @@ -6935,533 +7073,533 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(field,v1,v2,v3);(yyval.val)=v4;} } -#line 6934 "ripper.c" /* yacc.c:1646 */ +#line 7072 "ripper.c" break; case 109: -#line 1894 "ripper.y" /* yacc.c:1646 */ - { +#line 1918 "ripper.y" + { #if 0 (yyval.val) = const_decl(p, NEW_COLON2((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_field,v1,v2);(yyval.val)=const_decl(p, v3);} } -#line 6945 "ripper.c" /* yacc.c:1646 */ +#line 7083 "ripper.c" break; case 110: -#line 1901 "ripper.y" /* yacc.c:1646 */ - { +#line 1925 "ripper.y" + { #if 0 (yyval.val) = const_decl(p, NEW_COLON3((yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(top_const_field,v1);(yyval.val)=const_decl(p, v2);} } -#line 6956 "ripper.c" /* yacc.c:1646 */ +#line 7094 "ripper.c" break; case 111: -#line 1908 "ripper.y" /* yacc.c:1646 */ - { +#line 1932 "ripper.y" + { #if 0 rb_backref_error(p, (yyvsp[0].val)); (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2;v1=var_field(p, (yyvsp[0].val));v2=dispatch1(assign_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 6968 "ripper.c" /* yacc.c:1646 */ +#line 7106 "ripper.c" break; case 112: -#line 1918 "ripper.y" /* yacc.c:1646 */ - { +#line 1942 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 6979 "ripper.c" /* yacc.c:1646 */ +#line 7117 "ripper.c" break; case 113: -#line 1925 "ripper.y" /* yacc.c:1646 */ - { +#line 1949 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 6990 "ripper.c" /* yacc.c:1646 */ +#line 7128 "ripper.c" break; case 114: -#line 1932 "ripper.y" /* yacc.c:1646 */ - { +#line 1956 "ripper.y" + { #if 0 (yyval.val) = aryset(p, (yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=escape_Qundef((yyvsp[-1].val));v3=dispatch2(aref_field,v1,v2);(yyval.val)=v3;} } -#line 7001 "ripper.c" /* yacc.c:1646 */ +#line 7139 "ripper.c" break; case 115: -#line 1939 "ripper.y" /* yacc.c:1646 */ - { +#line 1963 "ripper.y" + { #if 0 (yyval.val) = attrset(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(field,v1,v2,v3);(yyval.val)=v4;} } -#line 7012 "ripper.c" /* yacc.c:1646 */ +#line 7150 "ripper.c" break; case 116: -#line 1946 "ripper.y" /* yacc.c:1646 */ - { +#line 1970 "ripper.y" + { #if 0 (yyval.val) = attrset(p, (yyvsp[-2].val), idCOLON2, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[0].val);v4=dispatch3(field,v1,v2,v3);(yyval.val)=v4;} } -#line 7023 "ripper.c" /* yacc.c:1646 */ +#line 7161 "ripper.c" break; case 117: -#line 1953 "ripper.y" /* yacc.c:1646 */ - { +#line 1977 "ripper.y" + { #if 0 (yyval.val) = attrset(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(field,v1,v2,v3);(yyval.val)=v4;} } -#line 7034 "ripper.c" /* yacc.c:1646 */ +#line 7172 "ripper.c" break; case 118: -#line 1960 "ripper.y" /* yacc.c:1646 */ - { +#line 1984 "ripper.y" + { #if 0 (yyval.val) = const_decl(p, NEW_COLON2((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_field,v1,v2);(yyval.val)=const_decl(p, v3);} } -#line 7045 "ripper.c" /* yacc.c:1646 */ +#line 7183 "ripper.c" break; case 119: -#line 1967 "ripper.y" /* yacc.c:1646 */ - { +#line 1991 "ripper.y" + { #if 0 (yyval.val) = const_decl(p, NEW_COLON3((yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(top_const_field,v1);(yyval.val)=const_decl(p, v2);} } -#line 7056 "ripper.c" /* yacc.c:1646 */ +#line 7194 "ripper.c" break; case 120: -#line 1974 "ripper.y" /* yacc.c:1646 */ - { +#line 1998 "ripper.y" + { #if 0 rb_backref_error(p, (yyvsp[0].val)); (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2;v1=var_field(p, (yyvsp[0].val));v2=dispatch1(assign_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 7068 "ripper.c" /* yacc.c:1646 */ +#line 7206 "ripper.c" break; case 121: -#line 1984 "ripper.y" /* yacc.c:1646 */ - { +#line 2008 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "class/module name must be CONSTANT"); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(class_name_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 7079 "ripper.c" /* yacc.c:1646 */ +#line 7217 "ripper.c" break; case 123: -#line 1994 "ripper.y" /* yacc.c:1646 */ - { +#line 2018 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON3((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(top_const_ref,v1);(yyval.val)=v2;} } -#line 7090 "ripper.c" /* yacc.c:1646 */ +#line 7228 "ripper.c" break; case 124: -#line 2001 "ripper.y" /* yacc.c:1646 */ - { +#line 2025 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON2(0, (yyval.val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(const_ref,v1);(yyval.val)=v2;} } -#line 7101 "ripper.c" /* yacc.c:1646 */ +#line 7239 "ripper.c" break; case 125: -#line 2008 "ripper.y" /* yacc.c:1646 */ - { +#line 2032 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON2((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_ref,v1,v2);(yyval.val)=v3;} } -#line 7112 "ripper.c" /* yacc.c:1646 */ +#line 7250 "ripper.c" break; case 129: -#line 2020 "ripper.y" /* yacc.c:1646 */ - { +#line 2044 "ripper.y" + { SET_LEX_STATE(EXPR_ENDFN); (yyval.val) = (yyvsp[0].val); } -#line 7121 "ripper.c" /* yacc.c:1646 */ +#line 7259 "ripper.c" break; case 130: -#line 2025 "ripper.y" /* yacc.c:1646 */ - { +#line 2049 "ripper.y" + { SET_LEX_STATE(EXPR_ENDFN); (yyval.val) = (yyvsp[0].val); } -#line 7130 "ripper.c" /* yacc.c:1646 */ +#line 7268 "ripper.c" break; case 131: -#line 2032 "ripper.y" /* yacc.c:1646 */ - { +#line 2056 "ripper.y" + { #if 0 (yyval.val) = NEW_LIT(ID2SYM((yyvsp[0].val)), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(symbol_literal,v1);(yyval.val)=v2;} } -#line 7141 "ripper.c" /* yacc.c:1646 */ +#line 7279 "ripper.c" break; case 133: -#line 2042 "ripper.y" /* yacc.c:1646 */ - { +#line 2066 "ripper.y" + { #if 0 (yyval.val) = NEW_UNDEF((yyvsp[0].val), &(yyloc)); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 7152 "ripper.c" /* yacc.c:1646 */ +#line 7290 "ripper.c" break; case 134: -#line 2048 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} -#line 7158 "ripper.c" /* yacc.c:1646 */ +#line 2072 "ripper.y" + {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} +#line 7296 "ripper.c" break; case 135: -#line 2049 "ripper.y" /* yacc.c:1646 */ - { +#line 2073 "ripper.y" + { #if 0 NODE *undef = NEW_UNDEF((yyvsp[0].val), &(yylsp[0])); (yyval.val) = block_append(p, (yyvsp[-3].val), undef); #endif (yyval.val)=rb_ary_push((yyvsp[-3].val), get_value((yyvsp[0].val))); } -#line 7170 "ripper.c" /* yacc.c:1646 */ +#line 7308 "ripper.c" break; case 136: -#line 2058 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '|'); } -#line 7176 "ripper.c" /* yacc.c:1646 */ +#line 2082 "ripper.y" + { ifndef_ripper((yyval.val) = '|'); } +#line 7314 "ripper.c" break; case 137: -#line 2059 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '^'); } -#line 7182 "ripper.c" /* yacc.c:1646 */ +#line 2083 "ripper.y" + { ifndef_ripper((yyval.val) = '^'); } +#line 7320 "ripper.c" break; case 138: -#line 2060 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '&'); } -#line 7188 "ripper.c" /* yacc.c:1646 */ +#line 2084 "ripper.y" + { ifndef_ripper((yyval.val) = '&'); } +#line 7326 "ripper.c" break; case 139: -#line 2061 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tCMP); } -#line 7194 "ripper.c" /* yacc.c:1646 */ +#line 2085 "ripper.y" + { ifndef_ripper((yyval.val) = tCMP); } +#line 7332 "ripper.c" break; case 140: -#line 2062 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tEQ); } -#line 7200 "ripper.c" /* yacc.c:1646 */ +#line 2086 "ripper.y" + { ifndef_ripper((yyval.val) = tEQ); } +#line 7338 "ripper.c" break; case 141: -#line 2063 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tEQQ); } -#line 7206 "ripper.c" /* yacc.c:1646 */ +#line 2087 "ripper.y" + { ifndef_ripper((yyval.val) = tEQQ); } +#line 7344 "ripper.c" break; case 142: -#line 2064 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tMATCH); } -#line 7212 "ripper.c" /* yacc.c:1646 */ +#line 2088 "ripper.y" + { ifndef_ripper((yyval.val) = tMATCH); } +#line 7350 "ripper.c" break; case 143: -#line 2065 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tNMATCH); } -#line 7218 "ripper.c" /* yacc.c:1646 */ +#line 2089 "ripper.y" + { ifndef_ripper((yyval.val) = tNMATCH); } +#line 7356 "ripper.c" break; case 144: -#line 2066 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '>'); } -#line 7224 "ripper.c" /* yacc.c:1646 */ +#line 2090 "ripper.y" + { ifndef_ripper((yyval.val) = '>'); } +#line 7362 "ripper.c" break; case 145: -#line 2067 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tGEQ); } -#line 7230 "ripper.c" /* yacc.c:1646 */ +#line 2091 "ripper.y" + { ifndef_ripper((yyval.val) = tGEQ); } +#line 7368 "ripper.c" break; case 146: -#line 2068 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '<'); } -#line 7236 "ripper.c" /* yacc.c:1646 */ +#line 2092 "ripper.y" + { ifndef_ripper((yyval.val) = '<'); } +#line 7374 "ripper.c" break; case 147: -#line 2069 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tLEQ); } -#line 7242 "ripper.c" /* yacc.c:1646 */ +#line 2093 "ripper.y" + { ifndef_ripper((yyval.val) = tLEQ); } +#line 7380 "ripper.c" break; case 148: -#line 2070 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tNEQ); } -#line 7248 "ripper.c" /* yacc.c:1646 */ +#line 2094 "ripper.y" + { ifndef_ripper((yyval.val) = tNEQ); } +#line 7386 "ripper.c" break; case 149: -#line 2071 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tLSHFT); } -#line 7254 "ripper.c" /* yacc.c:1646 */ +#line 2095 "ripper.y" + { ifndef_ripper((yyval.val) = tLSHFT); } +#line 7392 "ripper.c" break; case 150: -#line 2072 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tRSHFT); } -#line 7260 "ripper.c" /* yacc.c:1646 */ +#line 2096 "ripper.y" + { ifndef_ripper((yyval.val) = tRSHFT); } +#line 7398 "ripper.c" break; case 151: -#line 2073 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '+'); } -#line 7266 "ripper.c" /* yacc.c:1646 */ +#line 2097 "ripper.y" + { ifndef_ripper((yyval.val) = '+'); } +#line 7404 "ripper.c" break; case 152: -#line 2074 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '-'); } -#line 7272 "ripper.c" /* yacc.c:1646 */ +#line 2098 "ripper.y" + { ifndef_ripper((yyval.val) = '-'); } +#line 7410 "ripper.c" break; case 153: -#line 2075 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '*'); } -#line 7278 "ripper.c" /* yacc.c:1646 */ +#line 2099 "ripper.y" + { ifndef_ripper((yyval.val) = '*'); } +#line 7416 "ripper.c" break; case 154: -#line 2076 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '*'); } -#line 7284 "ripper.c" /* yacc.c:1646 */ +#line 2100 "ripper.y" + { ifndef_ripper((yyval.val) = '*'); } +#line 7422 "ripper.c" break; case 155: -#line 2077 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '/'); } -#line 7290 "ripper.c" /* yacc.c:1646 */ +#line 2101 "ripper.y" + { ifndef_ripper((yyval.val) = '/'); } +#line 7428 "ripper.c" break; case 156: -#line 2078 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '%'); } -#line 7296 "ripper.c" /* yacc.c:1646 */ +#line 2102 "ripper.y" + { ifndef_ripper((yyval.val) = '%'); } +#line 7434 "ripper.c" break; case 157: -#line 2079 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tPOW); } -#line 7302 "ripper.c" /* yacc.c:1646 */ +#line 2103 "ripper.y" + { ifndef_ripper((yyval.val) = tPOW); } +#line 7440 "ripper.c" break; case 158: -#line 2080 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tDSTAR); } -#line 7308 "ripper.c" /* yacc.c:1646 */ +#line 2104 "ripper.y" + { ifndef_ripper((yyval.val) = tDSTAR); } +#line 7446 "ripper.c" break; case 159: -#line 2081 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '!'); } -#line 7314 "ripper.c" /* yacc.c:1646 */ +#line 2105 "ripper.y" + { ifndef_ripper((yyval.val) = '!'); } +#line 7452 "ripper.c" break; case 160: -#line 2082 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '~'); } -#line 7320 "ripper.c" /* yacc.c:1646 */ +#line 2106 "ripper.y" + { ifndef_ripper((yyval.val) = '~'); } +#line 7458 "ripper.c" break; case 161: -#line 2083 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tUPLUS); } -#line 7326 "ripper.c" /* yacc.c:1646 */ +#line 2107 "ripper.y" + { ifndef_ripper((yyval.val) = tUPLUS); } +#line 7464 "ripper.c" break; case 162: -#line 2084 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tUMINUS); } -#line 7332 "ripper.c" /* yacc.c:1646 */ +#line 2108 "ripper.y" + { ifndef_ripper((yyval.val) = tUMINUS); } +#line 7470 "ripper.c" break; case 163: -#line 2085 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tAREF); } -#line 7338 "ripper.c" /* yacc.c:1646 */ +#line 2109 "ripper.y" + { ifndef_ripper((yyval.val) = tAREF); } +#line 7476 "ripper.c" break; case 164: -#line 2086 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = tASET); } -#line 7344 "ripper.c" /* yacc.c:1646 */ +#line 2110 "ripper.y" + { ifndef_ripper((yyval.val) = tASET); } +#line 7482 "ripper.c" break; case 165: -#line 2087 "ripper.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.val) = '`'); } -#line 7350 "ripper.c" /* yacc.c:1646 */ +#line 2111 "ripper.y" + { ifndef_ripper((yyval.val) = '`'); } +#line 7488 "ripper.c" break; case 207: -#line 2105 "ripper.y" /* yacc.c:1646 */ - { +#line 2129 "ripper.y" + { #if 0 (yyval.val) = node_assign(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(assign,v1,v2);(yyval.val)=v3;} } -#line 7361 "ripper.c" /* yacc.c:1646 */ +#line 7499 "ripper.c" break; case 208: -#line 2112 "ripper.y" /* yacc.c:1646 */ - { +#line 2136 "ripper.y" + { #if 0 (yyval.val) = new_op_assign(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(opassign,v1,v2,v3);(yyval.val)=v4;} } -#line 7372 "ripper.c" /* yacc.c:1646 */ +#line 7510 "ripper.c" break; case 209: -#line 2119 "ripper.y" /* yacc.c:1646 */ - { +#line 2143 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = new_ary_op_assign(p, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-3]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-5].val);v2=escape_Qundef((yyvsp[-3].val));v3=dispatch2(aref_field,v1,v2);v4=v3;v5=(yyvsp[-1].val);v6=(yyvsp[0].val);v7=dispatch3(opassign,v4,v5,v6);(yyval.val)=v7;} } -#line 7384 "ripper.c" /* yacc.c:1646 */ +#line 7522 "ripper.c" break; case 210: -#line 2127 "ripper.y" /* yacc.c:1646 */ - { +#line 2151 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), (yyvsp[-3].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 7396 "ripper.c" /* yacc.c:1646 */ +#line 7534 "ripper.c" break; case 211: -#line 2135 "ripper.y" /* yacc.c:1646 */ - { +#line 2159 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), (yyvsp[-3].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 7408 "ripper.c" /* yacc.c:1646 */ +#line 7546 "ripper.c" break; case 212: -#line 2143 "ripper.y" /* yacc.c:1646 */ - { +#line 2167 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = new_attr_op_assign(p, (yyvsp[-4].val), ID2VAL(idCOLON2), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[-2].val);v4=dispatch3(field,v1,v2,v3);v5=v4;v6=(yyvsp[-1].val);v7=(yyvsp[0].val);v8=dispatch3(opassign,v5,v6,v7);(yyval.val)=v8;} } -#line 7420 "ripper.c" /* yacc.c:1646 */ +#line 7558 "ripper.c" break; case 213: -#line 2151 "ripper.y" /* yacc.c:1646 */ - { +#line 2175 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-4]), &(yylsp[-2])); (yyval.val) = new_const_op_assign(p, NEW_COLON2((yyvsp[-4].val), (yyvsp[-2].val), &loc), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=dispatch2(const_path_field,v1,v2);v4=v3;v5=(yyvsp[-1].val);v6=(yyvsp[0].val);v7=dispatch3(opassign,v4,v5,v6);(yyval.val)=v7;} } -#line 7432 "ripper.c" /* yacc.c:1646 */ +#line 7570 "ripper.c" break; case 214: -#line 2159 "ripper.y" /* yacc.c:1646 */ - { +#line 2183 "ripper.y" + { #if 0 (yyval.val) = new_const_op_assign(p, NEW_COLON3((yyvsp[-2].val), &(yyloc)), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-2].val);v2=dispatch1(top_const_field,v1);v3=v2;v4=(yyvsp[-1].val);v5=(yyvsp[0].val);v6=dispatch3(opassign,v3,v4,v5);(yyval.val)=v6;} } -#line 7443 "ripper.c" /* yacc.c:1646 */ +#line 7581 "ripper.c" break; case 215: -#line 2166 "ripper.y" /* yacc.c:1646 */ - { +#line 2190 "ripper.y" + { #if 0 rb_backref_error(p, (yyvsp[-2].val)); (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=var_field(p, (yyvsp[-2].val));v2=(yyvsp[-1].val);v3=(yyvsp[0].val);v4=dispatch3(opassign,v1,v2,v3);v5=v4;v6=dispatch1(assign_error,v5);(yyval.val)=v6;}ripper_error(p); } -#line 7455 "ripper.c" /* yacc.c:1646 */ +#line 7593 "ripper.c" break; case 216: -#line 2174 "ripper.y" /* yacc.c:1646 */ - { +#line 2198 "ripper.y" + { #if 0 value_expr((yyvsp[-2].val)); value_expr((yyvsp[0].val)); @@ -7469,12 +7607,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 7468 "ripper.c" /* yacc.c:1646 */ +#line 7606 "ripper.c" break; case 217: -#line 2183 "ripper.y" /* yacc.c:1646 */ - { +#line 2207 "ripper.y" + { #if 0 value_expr((yyvsp[-2].val)); value_expr((yyvsp[0].val)); @@ -7482,12 +7620,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 7481 "ripper.c" /* yacc.c:1646 */ +#line 7619 "ripper.c" break; case 218: -#line 2192 "ripper.y" /* yacc.c:1646 */ - { +#line 2216 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -7498,12 +7636,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=Qnil;v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 7497 "ripper.c" /* yacc.c:1646 */ +#line 7635 "ripper.c" break; case 219: -#line 2204 "ripper.y" /* yacc.c:1646 */ - { +#line 2228 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -7514,12 +7652,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=Qnil;v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 7513 "ripper.c" /* yacc.c:1646 */ +#line 7651 "ripper.c" break; case 220: -#line 2216 "ripper.y" /* yacc.c:1646 */ - { +#line 2240 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -7530,12 +7668,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=Qnil;v2=(yyvsp[0].val);v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 7529 "ripper.c" /* yacc.c:1646 */ +#line 7667 "ripper.c" break; case 221: -#line 2228 "ripper.y" /* yacc.c:1646 */ - { +#line 2252 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -7546,219 +7684,219 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=Qnil;v2=(yyvsp[0].val);v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 7545 "ripper.c" /* yacc.c:1646 */ +#line 7683 "ripper.c" break; case 222: -#line 2240 "ripper.y" /* yacc.c:1646 */ - { +#line 2264 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '+', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7553 "ripper.c" /* yacc.c:1646 */ +#line 7691 "ripper.c" break; case 223: -#line 2244 "ripper.y" /* yacc.c:1646 */ - { +#line 2268 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '-', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7561 "ripper.c" /* yacc.c:1646 */ +#line 7699 "ripper.c" break; case 224: -#line 2248 "ripper.y" /* yacc.c:1646 */ - { +#line 2272 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '*', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7569 "ripper.c" /* yacc.c:1646 */ +#line 7707 "ripper.c" break; case 225: -#line 2252 "ripper.y" /* yacc.c:1646 */ - { +#line 2276 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '/', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7577 "ripper.c" /* yacc.c:1646 */ +#line 7715 "ripper.c" break; case 226: -#line 2256 "ripper.y" /* yacc.c:1646 */ - { +#line 2280 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '%', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7585 "ripper.c" /* yacc.c:1646 */ +#line 7723 "ripper.c" break; case 227: -#line 2260 "ripper.y" /* yacc.c:1646 */ - { +#line 2284 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idPow, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7593 "ripper.c" /* yacc.c:1646 */ +#line 7731 "ripper.c" break; case 228: -#line 2264 "ripper.y" /* yacc.c:1646 */ - { +#line 2288 "ripper.y" + { (yyval.val) = call_uni_op(p, call_bin_op(p, (yyvsp[-2].val), idPow, (yyvsp[0].val), &(yylsp[-2]), &(yyloc)), idUMinus, &(yylsp[-3]), &(yyloc)); } -#line 7601 "ripper.c" /* yacc.c:1646 */ +#line 7739 "ripper.c" break; case 229: -#line 2268 "ripper.y" /* yacc.c:1646 */ - { +#line 2292 "ripper.y" + { (yyval.val) = call_uni_op(p, (yyvsp[0].val), idUPlus, &(yylsp[-1]), &(yyloc)); } -#line 7609 "ripper.c" /* yacc.c:1646 */ +#line 7747 "ripper.c" break; case 230: -#line 2272 "ripper.y" /* yacc.c:1646 */ - { +#line 2296 "ripper.y" + { (yyval.val) = call_uni_op(p, (yyvsp[0].val), idUMinus, &(yylsp[-1]), &(yyloc)); } -#line 7617 "ripper.c" /* yacc.c:1646 */ +#line 7755 "ripper.c" break; case 231: -#line 2276 "ripper.y" /* yacc.c:1646 */ - { +#line 2300 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '|', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7625 "ripper.c" /* yacc.c:1646 */ +#line 7763 "ripper.c" break; case 232: -#line 2280 "ripper.y" /* yacc.c:1646 */ - { +#line 2304 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '^', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7633 "ripper.c" /* yacc.c:1646 */ +#line 7771 "ripper.c" break; case 233: -#line 2284 "ripper.y" /* yacc.c:1646 */ - { +#line 2308 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), '&', (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7641 "ripper.c" /* yacc.c:1646 */ +#line 7779 "ripper.c" break; case 234: -#line 2288 "ripper.y" /* yacc.c:1646 */ - { +#line 2312 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idCmp, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7649 "ripper.c" /* yacc.c:1646 */ +#line 7787 "ripper.c" break; case 236: -#line 2293 "ripper.y" /* yacc.c:1646 */ - { +#line 2317 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idEq, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7657 "ripper.c" /* yacc.c:1646 */ +#line 7795 "ripper.c" break; case 237: -#line 2297 "ripper.y" /* yacc.c:1646 */ - { +#line 2321 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idEqq, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7665 "ripper.c" /* yacc.c:1646 */ +#line 7803 "ripper.c" break; case 238: -#line 2301 "ripper.y" /* yacc.c:1646 */ - { +#line 2325 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idNeq, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7673 "ripper.c" /* yacc.c:1646 */ +#line 7811 "ripper.c" break; case 239: -#line 2305 "ripper.y" /* yacc.c:1646 */ - { +#line 2329 "ripper.y" + { (yyval.val) = match_op(p, (yyvsp[-2].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7681 "ripper.c" /* yacc.c:1646 */ +#line 7819 "ripper.c" break; case 240: -#line 2309 "ripper.y" /* yacc.c:1646 */ - { +#line 2333 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idNeqTilde, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7689 "ripper.c" /* yacc.c:1646 */ +#line 7827 "ripper.c" break; case 241: -#line 2313 "ripper.y" /* yacc.c:1646 */ - { +#line 2337 "ripper.y" + { (yyval.val) = call_uni_op(p, method_cond(p, (yyvsp[0].val), &(yylsp[0])), '!', &(yylsp[-1]), &(yyloc)); } -#line 7697 "ripper.c" /* yacc.c:1646 */ +#line 7835 "ripper.c" break; case 242: -#line 2317 "ripper.y" /* yacc.c:1646 */ - { +#line 2341 "ripper.y" + { (yyval.val) = call_uni_op(p, (yyvsp[0].val), '~', &(yylsp[-1]), &(yyloc)); } -#line 7705 "ripper.c" /* yacc.c:1646 */ +#line 7843 "ripper.c" break; case 243: -#line 2321 "ripper.y" /* yacc.c:1646 */ - { +#line 2345 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idLTLT, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7713 "ripper.c" /* yacc.c:1646 */ +#line 7851 "ripper.c" break; case 244: -#line 2325 "ripper.y" /* yacc.c:1646 */ - { +#line 2349 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), idGTGT, (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7721 "ripper.c" /* yacc.c:1646 */ +#line 7859 "ripper.c" break; case 245: -#line 2329 "ripper.y" /* yacc.c:1646 */ - { +#line 2353 "ripper.y" + { (yyval.val) = logop(p, idANDOP, (yyvsp[-2].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7729 "ripper.c" /* yacc.c:1646 */ +#line 7867 "ripper.c" break; case 246: -#line 2333 "ripper.y" /* yacc.c:1646 */ - { +#line 2357 "ripper.y" + { (yyval.val) = logop(p, idOROP, (yyvsp[-2].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7737 "ripper.c" /* yacc.c:1646 */ +#line 7875 "ripper.c" break; case 247: -#line 2336 "ripper.y" /* yacc.c:1646 */ - {p->in_defined = 1;} -#line 7743 "ripper.c" /* yacc.c:1646 */ +#line 2360 "ripper.y" + {p->in_defined = 1;} +#line 7881 "ripper.c" break; case 248: -#line 2337 "ripper.y" /* yacc.c:1646 */ - { +#line 2361 "ripper.y" + { p->in_defined = 0; (yyval.val) = new_defined(p, (yyvsp[0].val), &(yyloc)); } -#line 7752 "ripper.c" /* yacc.c:1646 */ +#line 7890 "ripper.c" break; case 249: -#line 2342 "ripper.y" /* yacc.c:1646 */ - { +#line 2366 "ripper.y" + { #if 0 value_expr((yyvsp[-5].val)); (yyval.val) = new_if(p, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[0].val), &(yyloc)); @@ -7766,109 +7904,109 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-5].val);v2=(yyvsp[-3].val);v3=(yyvsp[0].val);v4=dispatch3(ifop,v1,v2,v3);(yyval.val)=v4;} } -#line 7765 "ripper.c" /* yacc.c:1646 */ +#line 7903 "ripper.c" break; case 250: -#line 2351 "ripper.y" /* yacc.c:1646 */ - { +#line 2375 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 7773 "ripper.c" /* yacc.c:1646 */ +#line 7911 "ripper.c" break; case 251: -#line 2356 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = '>';} -#line 7779 "ripper.c" /* yacc.c:1646 */ +#line 2380 "ripper.y" + {(yyval.val) = '>';} +#line 7917 "ripper.c" break; case 252: -#line 2357 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = '<';} -#line 7785 "ripper.c" /* yacc.c:1646 */ +#line 2381 "ripper.y" + {(yyval.val) = '<';} +#line 7923 "ripper.c" break; case 253: -#line 2358 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = idGE;} -#line 7791 "ripper.c" /* yacc.c:1646 */ +#line 2382 "ripper.y" + {(yyval.val) = idGE;} +#line 7929 "ripper.c" break; case 254: -#line 2359 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = idLE;} -#line 7797 "ripper.c" /* yacc.c:1646 */ +#line 2383 "ripper.y" + {(yyval.val) = idLE;} +#line 7935 "ripper.c" break; case 255: -#line 2363 "ripper.y" /* yacc.c:1646 */ - { +#line 2387 "ripper.y" + { (yyval.val) = call_bin_op(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7805 "ripper.c" /* yacc.c:1646 */ +#line 7943 "ripper.c" break; case 256: -#line 2367 "ripper.y" /* yacc.c:1646 */ - { +#line 2391 "ripper.y" + { rb_warning1("comparison '%s' after comparison", WARN_ID((yyvsp[-1].val))); (yyval.val) = call_bin_op(p, (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); } -#line 7814 "ripper.c" /* yacc.c:1646 */ +#line 7952 "ripper.c" break; case 257: -#line 2374 "ripper.y" /* yacc.c:1646 */ - { +#line 2398 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 7823 "ripper.c" /* yacc.c:1646 */ +#line 7961 "ripper.c" break; case 259: -#line 2382 "ripper.y" /* yacc.c:1646 */ - { +#line 2406 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); } -#line 7831 "ripper.c" /* yacc.c:1646 */ +#line 7969 "ripper.c" break; case 260: -#line 2386 "ripper.y" /* yacc.c:1646 */ - { +#line 2410 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? arg_append(p, (yyvsp[-3].val), new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].val); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-1].val);v2=dispatch1(bare_assoc_hash,v1);v3=(yyvsp[-3].val);v4=v2;v5=dispatch2(args_add,v3,v4);(yyval.val)=v5;} } -#line 7842 "ripper.c" /* yacc.c:1646 */ +#line 7980 "ripper.c" break; case 261: -#line 2393 "ripper.y" /* yacc.c:1646 */ - { +#line 2417 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? NEW_LIST(new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yyloc)) : 0; #endif {VALUE v1,v2,v3,v4,v5,v6;v1=dispatch0(args_new);v2=(yyvsp[-1].val);v3=dispatch1(bare_assoc_hash,v2);v4=v1;v5=v3;v6=dispatch2(args_add,v4,v5);(yyval.val)=v6;} } -#line 7853 "ripper.c" /* yacc.c:1646 */ +#line 7991 "ripper.c" break; case 262: -#line 2402 "ripper.y" /* yacc.c:1646 */ - { +#line 2426 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 7862 "ripper.c" /* yacc.c:1646 */ +#line 8000 "ripper.c" break; case 263: -#line 2407 "ripper.y" /* yacc.c:1646 */ - { +#line 2431 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].val)); @@ -7876,23 +8014,23 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(rescue_mod,v1,v2);(yyval.val)=v3;} } -#line 7875 "ripper.c" /* yacc.c:1646 */ +#line 8013 "ripper.c" break; case 264: -#line 2418 "ripper.y" /* yacc.c:1646 */ - { +#line 2442 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=escape_Qundef((yyvsp[-1].val));v2=dispatch1(arg_paren,v1);(yyval.val)=v2;} } -#line 7886 "ripper.c" /* yacc.c:1646 */ +#line 8024 "ripper.c" break; case 265: -#line 2425 "ripper.y" /* yacc.c:1646 */ - { +#line 2449 "ripper.y" + { if (!local_id(p, idFWD_REST) || #if idFWD_KWREST !local_id(p, idFWD_KWREST) || @@ -7918,95 +8056,95 @@ YYLTYPE yylloc = yyloc_default; {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(arg_paren,v1);(yyval.val)=v2;} } } -#line 7917 "ripper.c" /* yacc.c:1646 */ +#line 8055 "ripper.c" break; case 270: -#line 2460 "ripper.y" /* yacc.c:1646 */ - { +#line 2484 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); } -#line 7925 "ripper.c" /* yacc.c:1646 */ +#line 8063 "ripper.c" break; case 271: -#line 2464 "ripper.y" /* yacc.c:1646 */ - { +#line 2488 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? arg_append(p, (yyvsp[-3].val), new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].val); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-1].val);v2=dispatch1(bare_assoc_hash,v1);v3=(yyvsp[-3].val);v4=v2;v5=dispatch2(args_add,v3,v4);(yyval.val)=v5;} } -#line 7936 "ripper.c" /* yacc.c:1646 */ +#line 8074 "ripper.c" break; case 272: -#line 2471 "ripper.y" /* yacc.c:1646 */ - { +#line 2495 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? NEW_LIST(new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yylsp[-1])) : 0; #endif {VALUE v1,v2,v3,v4,v5,v6;v1=dispatch0(args_new);v2=(yyvsp[-1].val);v3=dispatch1(bare_assoc_hash,v2);v4=v1;v5=v3;v6=dispatch2(args_add,v4,v5);(yyval.val)=v6;} } -#line 7947 "ripper.c" /* yacc.c:1646 */ +#line 8085 "ripper.c" break; case 273: -#line 2480 "ripper.y" /* yacc.c:1646 */ - { +#line 2504 "ripper.y" + { #if 0 value_expr((yyvsp[0].val)); (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add,v2,v3);(yyval.val)=v4;} } -#line 7959 "ripper.c" /* yacc.c:1646 */ +#line 8097 "ripper.c" break; case 274: -#line 2488 "ripper.y" /* yacc.c:1646 */ - { +#line 2512 "ripper.y" + { #if 0 (yyval.val) = arg_blk_pass((yyvsp[-1].val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(args_add_block,v1,v2);(yyval.val)=v3;} } -#line 7970 "ripper.c" /* yacc.c:1646 */ +#line 8108 "ripper.c" break; case 275: -#line 2495 "ripper.y" /* yacc.c:1646 */ - { +#line 2519 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? NEW_LIST(new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yylsp[-1])) : 0; (yyval.val) = arg_blk_pass((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8,v9;v1=dispatch0(args_new);v2=(yyvsp[-1].val);v3=dispatch1(bare_assoc_hash,v2);v4=v1;v5=v3;v6=dispatch2(args_add,v4,v5);v7=v6;v8=(yyvsp[0].val);v9=dispatch2(args_add_block,v7,v8);(yyval.val)=v9;} } -#line 7982 "ripper.c" /* yacc.c:1646 */ +#line 8120 "ripper.c" break; case 276: -#line 2503 "ripper.y" /* yacc.c:1646 */ - { +#line 2527 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val) ? arg_append(p, (yyvsp[-3].val), new_hash(p, (yyvsp[-1].val), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].val); (yyval.val) = arg_blk_pass((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-1].val);v2=dispatch1(bare_assoc_hash,v1);v3=(yyvsp[-3].val);v4=v2;v5=dispatch2(args_add,v3,v4);v6=v5;v7=(yyvsp[0].val);v8=dispatch2(args_add_block,v6,v7);(yyval.val)=v8;} } -#line 7994 "ripper.c" /* yacc.c:1646 */ +#line 8132 "ripper.c" break; case 277: -#line 2511 "ripper.y" /* yacc.c:1646 */ - {{VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add_block,v2,v3);(yyval.val)=v4;}} -#line 8000 "ripper.c" /* yacc.c:1646 */ +#line 2535 "ripper.y" + {{VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add_block,v2,v3);(yyval.val)=v4;}} +#line 8138 "ripper.c" break; case 278: -#line 2514 "ripper.y" /* yacc.c:1646 */ - { +#line 2538 "ripper.y" + { /* If call_args starts with a open paren '(' or '[', * look-ahead reading of the letters calls CMDARG_PUSH(0), * but the push must be done after CMDARG_PUSH(1). @@ -8023,12 +8161,12 @@ YYLTYPE yylloc = yyloc_default; CMDARG_PUSH(1); if (lookahead) CMDARG_PUSH(0); } -#line 8022 "ripper.c" /* yacc.c:1646 */ +#line 8160 "ripper.c" break; case 279: -#line 2532 "ripper.y" /* yacc.c:1646 */ - { +#line 2556 "ripper.y" + { /* call_args can be followed by tLBRACE_ARG (that does CMDARG_PUSH(0) in the lexer) * but the push must be done after CMDARG_POP() in the parser. * So this code does CMDARG_POP() to pop 0 pushed by tLBRACE_ARG, @@ -8045,135 +8183,135 @@ YYLTYPE yylloc = yyloc_default; if (lookahead) CMDARG_PUSH(0); (yyval.val) = (yyvsp[0].val); } -#line 8044 "ripper.c" /* yacc.c:1646 */ +#line 8182 "ripper.c" break; case 280: -#line 2552 "ripper.y" /* yacc.c:1646 */ - { +#line 2576 "ripper.y" + { #if 0 (yyval.val) = NEW_BLOCK_PASS((yyvsp[0].val), &(yyloc)); #endif (yyval.val)=(yyvsp[0].val); } -#line 8055 "ripper.c" /* yacc.c:1646 */ +#line 8193 "ripper.c" break; case 281: -#line 2561 "ripper.y" /* yacc.c:1646 */ - { +#line 2585 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 8063 "ripper.c" /* yacc.c:1646 */ +#line 8201 "ripper.c" break; case 282: -#line 2565 "ripper.y" /* yacc.c:1646 */ - { +#line 2589 "ripper.y" + { (yyval.val) = 0; } -#line 8071 "ripper.c" /* yacc.c:1646 */ +#line 8209 "ripper.c" break; case 283: -#line 2571 "ripper.y" /* yacc.c:1646 */ - { +#line 2595 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add,v2,v3);(yyval.val)=v4;} } -#line 8082 "ripper.c" /* yacc.c:1646 */ +#line 8220 "ripper.c" break; case 284: -#line 2578 "ripper.y" /* yacc.c:1646 */ - { +#line 2602 "ripper.y" + { #if 0 (yyval.val) = NEW_SPLAT((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add_star,v2,v3);(yyval.val)=v4;} } -#line 8093 "ripper.c" /* yacc.c:1646 */ +#line 8231 "ripper.c" break; case 285: -#line 2585 "ripper.y" /* yacc.c:1646 */ - { +#line 2609 "ripper.y" + { #if 0 (yyval.val) = last_arg_append(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(args_add,v1,v2);(yyval.val)=v3;} } -#line 8104 "ripper.c" /* yacc.c:1646 */ +#line 8242 "ripper.c" break; case 286: -#line 2592 "ripper.y" /* yacc.c:1646 */ - { +#line 2616 "ripper.y" + { #if 0 (yyval.val) = rest_arg_append(p, (yyvsp[-3].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=(yyvsp[0].val);v3=dispatch2(args_add_star,v1,v2);(yyval.val)=v3;} } -#line 8115 "ripper.c" /* yacc.c:1646 */ +#line 8253 "ripper.c" break; case 289: -#line 2605 "ripper.y" /* yacc.c:1646 */ - { +#line 2629 "ripper.y" + { #if 0 (yyval.val) = last_arg_append(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-2].val);v2=dispatch1(mrhs_new_from_args,v1);v3=v2;v4=(yyvsp[0].val);v5=dispatch2(mrhs_add,v3,v4);(yyval.val)=v5;} } -#line 8126 "ripper.c" /* yacc.c:1646 */ +#line 8264 "ripper.c" break; case 290: -#line 2612 "ripper.y" /* yacc.c:1646 */ - { +#line 2636 "ripper.y" + { #if 0 (yyval.val) = rest_arg_append(p, (yyvsp[-3].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-3].val);v2=dispatch1(mrhs_new_from_args,v1);v3=v2;v4=(yyvsp[0].val);v5=dispatch2(mrhs_add_star,v3,v4);(yyval.val)=v5;} } -#line 8137 "ripper.c" /* yacc.c:1646 */ +#line 8275 "ripper.c" break; case 291: -#line 2619 "ripper.y" /* yacc.c:1646 */ - { +#line 2643 "ripper.y" + { #if 0 (yyval.val) = NEW_SPLAT((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mrhs_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(mrhs_add_star,v2,v3);(yyval.val)=v4;} } -#line 8148 "ripper.c" /* yacc.c:1646 */ +#line 8286 "ripper.c" break; case 302: -#line 2638 "ripper.y" /* yacc.c:1646 */ - { +#line 2662 "ripper.y" + { #if 0 (yyval.val) = NEW_FCALL((yyvsp[0].val), 0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[0].val);v2=dispatch1(fcall,v1);v3=dispatch0(args_new);v4=v2;v5=v3;v6=dispatch2(method_add_arg,v4,v5);(yyval.val)=v6;} } -#line 8159 "ripper.c" /* yacc.c:1646 */ +#line 8297 "ripper.c" break; case 303: -#line 2645 "ripper.y" /* yacc.c:1646 */ - { +#line 2669 "ripper.y" + { CMDARG_PUSH(0); } -#line 8167 "ripper.c" /* yacc.c:1646 */ +#line 8305 "ripper.c" break; case 304: -#line 2650 "ripper.y" /* yacc.c:1646 */ - { +#line 2674 "ripper.y" + { CMDARG_POP(); #if 0 set_line_body((yyvsp[-1].val), (yylsp[-3]).end_pos.lineno); @@ -8182,278 +8320,278 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(begin,v1);(yyval.val)=v2;} } -#line 8181 "ripper.c" /* yacc.c:1646 */ +#line 8319 "ripper.c" break; case 305: -#line 2659 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_ENDARG);} -#line 8187 "ripper.c" /* yacc.c:1646 */ +#line 2683 "ripper.y" + {SET_LEX_STATE(EXPR_ENDARG);} +#line 8325 "ripper.c" break; case 306: -#line 2660 "ripper.y" /* yacc.c:1646 */ - { +#line 2684 "ripper.y" + { #if 0 (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2;v1=0;v2=dispatch1(paren,v1);(yyval.val)=v2;} } -#line 8198 "ripper.c" /* yacc.c:1646 */ +#line 8336 "ripper.c" break; case 307: -#line 2666 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_ENDARG);} -#line 8204 "ripper.c" /* yacc.c:1646 */ +#line 2690 "ripper.y" + {SET_LEX_STATE(EXPR_ENDARG);} +#line 8342 "ripper.c" break; case 308: -#line 2667 "ripper.y" /* yacc.c:1646 */ - { +#line 2691 "ripper.y" + { #if 0 if (nd_type((yyvsp[-2].val)) == NODE_SELF) (yyvsp[-2].val)->nd_state = 0; (yyval.val) = (yyvsp[-2].val); #endif {VALUE v1,v2;v1=(yyvsp[-2].val);v2=dispatch1(paren,v1);(yyval.val)=v2;} } -#line 8216 "ripper.c" /* yacc.c:1646 */ +#line 8354 "ripper.c" break; case 309: -#line 2675 "ripper.y" /* yacc.c:1646 */ - { +#line 2699 "ripper.y" + { #if 0 if (nd_type((yyvsp[-1].val)) == NODE_SELF) (yyvsp[-1].val)->nd_state = 0; (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(paren,v1);(yyval.val)=v2;} } -#line 8228 "ripper.c" /* yacc.c:1646 */ +#line 8366 "ripper.c" break; case 310: -#line 2683 "ripper.y" /* yacc.c:1646 */ - { +#line 2707 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON2((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_ref,v1,v2);(yyval.val)=v3;} } -#line 8239 "ripper.c" /* yacc.c:1646 */ +#line 8377 "ripper.c" break; case 311: -#line 2690 "ripper.y" /* yacc.c:1646 */ - { +#line 2714 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON3((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(top_const_ref,v1);(yyval.val)=v2;} } -#line 8250 "ripper.c" /* yacc.c:1646 */ +#line 8388 "ripper.c" break; case 312: -#line 2697 "ripper.y" /* yacc.c:1646 */ - { +#line 2721 "ripper.y" + { #if 0 (yyval.val) = make_list((yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=escape_Qundef((yyvsp[-1].val));v2=dispatch1(array,v1);(yyval.val)=v2;} } -#line 8261 "ripper.c" /* yacc.c:1646 */ +#line 8399 "ripper.c" break; case 313: -#line 2704 "ripper.y" /* yacc.c:1646 */ - { +#line 2728 "ripper.y" + { #if 0 (yyval.val) = new_hash(p, (yyvsp[-1].val), &(yyloc)); (yyval.val)->nd_brace = TRUE; #endif {VALUE v1,v2;v1=escape_Qundef((yyvsp[-1].val));v2=dispatch1(hash,v1);(yyval.val)=v2;} } -#line 8273 "ripper.c" /* yacc.c:1646 */ +#line 8411 "ripper.c" break; case 314: -#line 2712 "ripper.y" /* yacc.c:1646 */ - { +#line 2736 "ripper.y" + { #if 0 (yyval.val) = NEW_RETURN(0, &(yyloc)); #endif {VALUE v1;v1=dispatch0(return0);(yyval.val)=v1;} } -#line 8284 "ripper.c" /* yacc.c:1646 */ +#line 8422 "ripper.c" break; case 315: -#line 2719 "ripper.y" /* yacc.c:1646 */ - { +#line 2743 "ripper.y" + { #if 0 (yyval.val) = new_yield(p, (yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-1].val);v2=dispatch1(paren,v1);v3=v2;v4=dispatch1(yield,v3);(yyval.val)=v4;} } -#line 8295 "ripper.c" /* yacc.c:1646 */ +#line 8433 "ripper.c" break; case 316: -#line 2726 "ripper.y" /* yacc.c:1646 */ - { +#line 2750 "ripper.y" + { #if 0 (yyval.val) = NEW_YIELD(0, &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5;v1=dispatch0(args_new);v2=v1;v3=dispatch1(paren,v2);v4=v3;v5=dispatch1(yield,v4);(yyval.val)=v5;} } -#line 8306 "ripper.c" /* yacc.c:1646 */ +#line 8444 "ripper.c" break; case 317: -#line 2733 "ripper.y" /* yacc.c:1646 */ - { +#line 2757 "ripper.y" + { #if 0 (yyval.val) = NEW_YIELD(0, &(yyloc)); #endif {VALUE v1;v1=dispatch0(yield0);(yyval.val)=v1;} } -#line 8317 "ripper.c" /* yacc.c:1646 */ +#line 8455 "ripper.c" break; case 318: -#line 2739 "ripper.y" /* yacc.c:1646 */ - {p->in_defined = 1;} -#line 8323 "ripper.c" /* yacc.c:1646 */ +#line 2763 "ripper.y" + {p->in_defined = 1;} +#line 8461 "ripper.c" break; case 319: -#line 2740 "ripper.y" /* yacc.c:1646 */ - { +#line 2764 "ripper.y" + { p->in_defined = 0; (yyval.val) = new_defined(p, (yyvsp[-1].val), &(yyloc)); } -#line 8332 "ripper.c" /* yacc.c:1646 */ +#line 8470 "ripper.c" break; case 320: -#line 2745 "ripper.y" /* yacc.c:1646 */ - { +#line 2769 "ripper.y" + { (yyval.val) = call_uni_op(p, method_cond(p, (yyvsp[-1].val), &(yylsp[-1])), METHOD_NOT, &(yylsp[-3]), &(yyloc)); } -#line 8340 "ripper.c" /* yacc.c:1646 */ +#line 8478 "ripper.c" break; case 321: -#line 2749 "ripper.y" /* yacc.c:1646 */ - { +#line 2773 "ripper.y" + { (yyval.val) = call_uni_op(p, method_cond(p, new_nil(&(yylsp[-1])), &(yylsp[-1])), METHOD_NOT, &(yylsp[-2]), &(yyloc)); } -#line 8348 "ripper.c" /* yacc.c:1646 */ +#line 8486 "ripper.c" break; case 322: -#line 2753 "ripper.y" /* yacc.c:1646 */ - { +#line 2777 "ripper.y" + { #if 0 (yyval.val) = method_add_block(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8,v9;v1=(yyvsp[-1].val);v2=dispatch1(fcall,v1);v3=dispatch0(args_new);v4=v2;v5=v3;v6=dispatch2(method_add_arg,v4,v5);v7=v6;v8=(yyvsp[0].val);v9=dispatch2(method_add_block,v7,v8);(yyval.val)=v9;} } -#line 8359 "ripper.c" /* yacc.c:1646 */ +#line 8497 "ripper.c" break; case 324: -#line 2761 "ripper.y" /* yacc.c:1646 */ - { +#line 2785 "ripper.y" + { #if 0 block_dup_check(p, (yyvsp[-1].val)->nd_args, (yyvsp[0].val)); (yyval.val) = method_add_block(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(method_add_block,v1,v2);(yyval.val)=v3;} } -#line 8371 "ripper.c" /* yacc.c:1646 */ +#line 8509 "ripper.c" break; case 325: -#line 2769 "ripper.y" /* yacc.c:1646 */ - { +#line 2793 "ripper.y" + { token_info_push(p, "->", &(yylsp[0])); } -#line 8379 "ripper.c" /* yacc.c:1646 */ +#line 8517 "ripper.c" break; case 326: -#line 2773 "ripper.y" /* yacc.c:1646 */ - { +#line 2797 "ripper.y" + { (yyval.val) = (yyvsp[0].val); #if 0 nd_set_first_loc((yyval.val), (yylsp[-2]).beg_pos); #endif } -#line 8390 "ripper.c" /* yacc.c:1646 */ +#line 8528 "ripper.c" break; case 327: -#line 2783 "ripper.y" /* yacc.c:1646 */ - { +#line 2807 "ripper.y" + { #if 0 (yyval.val) = new_if(p, (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), &(yyloc)); fixpos((yyval.val), (yyvsp[-4].val)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=escape_Qundef((yyvsp[-1].val));v4=dispatch3(if,v1,v2,v3);(yyval.val)=v4;} } -#line 8402 "ripper.c" /* yacc.c:1646 */ +#line 8540 "ripper.c" break; case 328: -#line 2794 "ripper.y" /* yacc.c:1646 */ - { +#line 2818 "ripper.y" + { #if 0 (yyval.val) = new_unless(p, (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), &(yyloc)); fixpos((yyval.val), (yyvsp[-4].val)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=escape_Qundef((yyvsp[-1].val));v4=dispatch3(unless,v1,v2,v3);(yyval.val)=v4;} } -#line 8414 "ripper.c" /* yacc.c:1646 */ +#line 8552 "ripper.c" break; case 329: -#line 2804 "ripper.y" /* yacc.c:1646 */ - { +#line 2828 "ripper.y" + { #if 0 (yyval.val) = NEW_WHILE(cond(p, (yyvsp[-2].val), &(yylsp[-2])), (yyvsp[-1].val), 1, &(yyloc)); fixpos((yyval.val), (yyvsp[-2].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(while,v1,v2);(yyval.val)=v3;} } -#line 8426 "ripper.c" /* yacc.c:1646 */ +#line 8564 "ripper.c" break; case 330: -#line 2814 "ripper.y" /* yacc.c:1646 */ - { +#line 2838 "ripper.y" + { #if 0 (yyval.val) = NEW_UNTIL(cond(p, (yyvsp[-2].val), &(yylsp[-2])), (yyvsp[-1].val), 1, &(yyloc)); fixpos((yyval.val), (yyvsp[-2].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(until,v1,v2);(yyval.val)=v3;} } -#line 8438 "ripper.c" /* yacc.c:1646 */ +#line 8576 "ripper.c" break; case 331: -#line 2822 "ripper.y" /* yacc.c:1646 */ - { +#line 2846 "ripper.y" + { (yyval.val) = p->case_labels; p->case_labels = Qnil; } -#line 8447 "ripper.c" /* yacc.c:1646 */ +#line 8585 "ripper.c" break; case 332: -#line 2828 "ripper.y" /* yacc.c:1646 */ - { +#line 2852 "ripper.y" + { if (RTEST(p->case_labels)) rb_hash_clear(p->case_labels); p->case_labels = (yyvsp[-2].val); #if 0 @@ -8462,21 +8600,21 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-4].val);v2=(yyvsp[-1].val);v3=dispatch2(case,v1,v2);(yyval.val)=v3;} } -#line 8461 "ripper.c" /* yacc.c:1646 */ +#line 8599 "ripper.c" break; case 333: -#line 2838 "ripper.y" /* yacc.c:1646 */ - { +#line 2862 "ripper.y" + { (yyval.val) = p->case_labels; p->case_labels = 0; } -#line 8470 "ripper.c" /* yacc.c:1646 */ +#line 8608 "ripper.c" break; case 334: -#line 2844 "ripper.y" /* yacc.c:1646 */ - { +#line 2868 "ripper.y" + { if (RTEST(p->case_labels)) rb_hash_clear(p->case_labels); p->case_labels = (yyvsp[-2].val); #if 0 @@ -8484,23 +8622,23 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=Qnil;v2=(yyvsp[-1].val);v3=dispatch2(case,v1,v2);(yyval.val)=v3;} } -#line 8483 "ripper.c" /* yacc.c:1646 */ +#line 8621 "ripper.c" break; case 335: -#line 2855 "ripper.y" /* yacc.c:1646 */ - { +#line 2879 "ripper.y" + { #if 0 (yyval.val) = new_case3(p, (yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=(yyvsp[-1].val);v3=dispatch2(case,v1,v2);(yyval.val)=v3;} } -#line 8494 "ripper.c" /* yacc.c:1646 */ +#line 8632 "ripper.c" break; case 336: -#line 2864 "ripper.y" /* yacc.c:1646 */ - { +#line 2888 "ripper.y" + { #if 0 /* * for a, b, c in e @@ -8544,12 +8682,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=(yyvsp[-1].val);v4=dispatch3(for,v1,v2,v3);(yyval.val)=v4;} } -#line 8543 "ripper.c" /* yacc.c:1646 */ +#line 8681 "ripper.c" break; case 337: -#line 2909 "ripper.y" /* yacc.c:1646 */ - { +#line 2933 "ripper.y" + { if (p->in_def) { YYLTYPE loc = code_loc_gen(&(yylsp[-2]), &(yylsp[-1])); yyerror1(&loc, "class definition in method body"); @@ -8558,12 +8696,12 @@ YYLTYPE yylloc = yyloc_default; p->in_class = 1; local_push(p, 0); } -#line 8557 "ripper.c" /* yacc.c:1646 */ +#line 8695 "ripper.c" break; case 338: -#line 2920 "ripper.y" /* yacc.c:1646 */ - { +#line 2944 "ripper.y" + { #if 0 (yyval.val) = NEW_CLASS((yyvsp[-4].val), (yyvsp[-1].val), (yyvsp[-3].val), &(yyloc)); nd_set_line((yyval.val)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8574,23 +8712,23 @@ YYLTYPE yylloc = yyloc_default; local_pop(p); p->in_class = (yyvsp[-5].num) & 1; } -#line 8573 "ripper.c" /* yacc.c:1646 */ +#line 8711 "ripper.c" break; case 339: -#line 2932 "ripper.y" /* yacc.c:1646 */ - { +#line 2956 "ripper.y" + { (yyval.num) = (p->in_class << 1) | p->in_def; p->in_def = 0; p->in_class = 0; local_push(p, 0); } -#line 8584 "ripper.c" /* yacc.c:1646 */ +#line 8722 "ripper.c" break; case 340: -#line 2941 "ripper.y" /* yacc.c:1646 */ - { +#line 2965 "ripper.y" + { #if 0 (yyval.val) = NEW_SCLASS((yyvsp[-4].val), (yyvsp[-1].val), &(yyloc)); nd_set_line((yyval.val)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8602,12 +8740,12 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-3].num) & 1; p->in_class = ((yyvsp[-3].num) >> 1) & 1; } -#line 8601 "ripper.c" /* yacc.c:1646 */ +#line 8739 "ripper.c" break; case 341: -#line 2954 "ripper.y" /* yacc.c:1646 */ - { +#line 2978 "ripper.y" + { if (p->in_def) { YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); yyerror1(&loc, "module definition in method body"); @@ -8616,12 +8754,12 @@ YYLTYPE yylloc = yyloc_default; p->in_class = 1; local_push(p, 0); } -#line 8615 "ripper.c" /* yacc.c:1646 */ +#line 8753 "ripper.c" break; case 342: -#line 2965 "ripper.y" /* yacc.c:1646 */ - { +#line 2989 "ripper.y" + { #if 0 (yyval.val) = NEW_MODULE((yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); nd_set_line((yyval.val)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8632,32 +8770,32 @@ YYLTYPE yylloc = yyloc_default; local_pop(p); p->in_class = (yyvsp[-4].num) & 1; } -#line 8631 "ripper.c" /* yacc.c:1646 */ +#line 8769 "ripper.c" break; case 343: -#line 2977 "ripper.y" /* yacc.c:1646 */ - { +#line 3001 "ripper.y" + { numparam_name(p, get_id((yyvsp[0].val))); local_push(p, 0); (yyval.id) = p->cur_arg; p->cur_arg = 0; } -#line 8642 "ripper.c" /* yacc.c:1646 */ +#line 8780 "ripper.c" break; case 344: -#line 2983 "ripper.y" /* yacc.c:1646 */ - { +#line 3007 "ripper.y" + { (yyval.num) = p->in_def; p->in_def = 1; } -#line 8651 "ripper.c" /* yacc.c:1646 */ +#line 8789 "ripper.c" break; case 345: -#line 2990 "ripper.y" /* yacc.c:1646 */ - { +#line 3014 "ripper.y" + { #if 0 NODE *body = remove_begin((yyvsp[-1].val)); reduce_nodes(p, &body); @@ -8670,18 +8808,18 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-3].num) & 1; p->cur_arg = (yyvsp[-4].id); } -#line 8669 "ripper.c" /* yacc.c:1646 */ +#line 8807 "ripper.c" break; case 346: -#line 3003 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME);} -#line 8675 "ripper.c" /* yacc.c:1646 */ +#line 3027 "ripper.y" + {SET_LEX_STATE(EXPR_FNAME);} +#line 8813 "ripper.c" break; case 347: -#line 3004 "ripper.y" /* yacc.c:1646 */ - { +#line 3028 "ripper.y" + { numparam_name(p, get_id((yyvsp[0].val))); (yyvsp[-1].num) = p->in_def; p->in_def = 1; @@ -8690,12 +8828,12 @@ YYLTYPE yylloc = yyloc_default; (yyval.id) = p->cur_arg; p->cur_arg = 0; } -#line 8689 "ripper.c" /* yacc.c:1646 */ +#line 8827 "ripper.c" break; case 348: -#line 3016 "ripper.y" /* yacc.c:1646 */ - { +#line 3040 "ripper.y" + { #if 0 NODE *body = remove_begin((yyvsp[-1].val)); reduce_nodes(p, &body); @@ -8708,73 +8846,73 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-5].num) & 1; p->cur_arg = (yyvsp[-3].id); } -#line 8707 "ripper.c" /* yacc.c:1646 */ +#line 8845 "ripper.c" break; case 349: -#line 3030 "ripper.y" /* yacc.c:1646 */ - { +#line 3054 "ripper.y" + { #if 0 (yyval.val) = NEW_BREAK(0, &(yyloc)); #endif {VALUE v1,v2,v3;v1=dispatch0(args_new);v2=v1;v3=dispatch1(break,v2);(yyval.val)=v3;} } -#line 8718 "ripper.c" /* yacc.c:1646 */ +#line 8856 "ripper.c" break; case 350: -#line 3037 "ripper.y" /* yacc.c:1646 */ - { +#line 3061 "ripper.y" + { #if 0 (yyval.val) = NEW_NEXT(0, &(yyloc)); #endif {VALUE v1,v2,v3;v1=dispatch0(args_new);v2=v1;v3=dispatch1(next,v2);(yyval.val)=v3;} } -#line 8729 "ripper.c" /* yacc.c:1646 */ +#line 8867 "ripper.c" break; case 351: -#line 3044 "ripper.y" /* yacc.c:1646 */ - { +#line 3068 "ripper.y" + { #if 0 (yyval.val) = NEW_REDO(&(yyloc)); #endif {VALUE v1;v1=dispatch0(redo);(yyval.val)=v1;} } -#line 8740 "ripper.c" /* yacc.c:1646 */ +#line 8878 "ripper.c" break; case 352: -#line 3051 "ripper.y" /* yacc.c:1646 */ - { +#line 3075 "ripper.y" + { #if 0 (yyval.val) = NEW_RETRY(&(yyloc)); #endif {VALUE v1;v1=dispatch0(retry);(yyval.val)=v1;} } -#line 8751 "ripper.c" /* yacc.c:1646 */ +#line 8889 "ripper.c" break; case 353: -#line 3060 "ripper.y" /* yacc.c:1646 */ - { +#line 3084 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 8760 "ripper.c" /* yacc.c:1646 */ +#line 8898 "ripper.c" break; case 354: -#line 3067 "ripper.y" /* yacc.c:1646 */ - { +#line 3091 "ripper.y" + { token_info_push(p, "begin", &(yyloc)); } -#line 8768 "ripper.c" /* yacc.c:1646 */ +#line 8906 "ripper.c" break; case 355: -#line 3073 "ripper.y" /* yacc.c:1646 */ - { +#line 3097 "ripper.y" + { WARN_EOL("if"); token_info_push(p, "if", &(yyloc)); if (p->token_info && p->token_info->nonspc && @@ -8788,116 +8926,116 @@ YYLTYPE yylloc = yyloc_default; } } } -#line 8787 "ripper.c" /* yacc.c:1646 */ +#line 8925 "ripper.c" break; case 356: -#line 3090 "ripper.y" /* yacc.c:1646 */ - { +#line 3114 "ripper.y" + { token_info_push(p, "unless", &(yyloc)); } -#line 8795 "ripper.c" /* yacc.c:1646 */ +#line 8933 "ripper.c" break; case 357: -#line 3096 "ripper.y" /* yacc.c:1646 */ - { +#line 3120 "ripper.y" + { token_info_push(p, "while", &(yyloc)); } -#line 8803 "ripper.c" /* yacc.c:1646 */ +#line 8941 "ripper.c" break; case 358: -#line 3102 "ripper.y" /* yacc.c:1646 */ - { +#line 3126 "ripper.y" + { token_info_push(p, "until", &(yyloc)); } -#line 8811 "ripper.c" /* yacc.c:1646 */ +#line 8949 "ripper.c" break; case 359: -#line 3108 "ripper.y" /* yacc.c:1646 */ - { +#line 3132 "ripper.y" + { token_info_push(p, "case", &(yyloc)); } -#line 8819 "ripper.c" /* yacc.c:1646 */ +#line 8957 "ripper.c" break; case 360: -#line 3114 "ripper.y" /* yacc.c:1646 */ - { +#line 3138 "ripper.y" + { token_info_push(p, "for", &(yyloc)); } -#line 8827 "ripper.c" /* yacc.c:1646 */ +#line 8965 "ripper.c" break; case 361: -#line 3120 "ripper.y" /* yacc.c:1646 */ - { +#line 3144 "ripper.y" + { token_info_push(p, "class", &(yyloc)); } -#line 8835 "ripper.c" /* yacc.c:1646 */ +#line 8973 "ripper.c" break; case 362: -#line 3126 "ripper.y" /* yacc.c:1646 */ - { +#line 3150 "ripper.y" + { token_info_push(p, "module", &(yyloc)); } -#line 8843 "ripper.c" /* yacc.c:1646 */ +#line 8981 "ripper.c" break; case 363: -#line 3132 "ripper.y" /* yacc.c:1646 */ - { +#line 3156 "ripper.y" + { token_info_push(p, "def", &(yyloc)); } -#line 8851 "ripper.c" /* yacc.c:1646 */ +#line 8989 "ripper.c" break; case 364: -#line 3138 "ripper.y" /* yacc.c:1646 */ - { +#line 3162 "ripper.y" + { token_info_push(p, "do", &(yyloc)); } -#line 8859 "ripper.c" /* yacc.c:1646 */ +#line 8997 "ripper.c" break; case 365: -#line 3144 "ripper.y" /* yacc.c:1646 */ - { +#line 3168 "ripper.y" + { token_info_push(p, "do", &(yyloc)); } -#line 8867 "ripper.c" /* yacc.c:1646 */ +#line 9005 "ripper.c" break; case 366: -#line 3150 "ripper.y" /* yacc.c:1646 */ - { +#line 3174 "ripper.y" + { token_info_warn(p, "rescue", p->token_info, 1, &(yyloc)); } -#line 8875 "ripper.c" /* yacc.c:1646 */ +#line 9013 "ripper.c" break; case 367: -#line 3156 "ripper.y" /* yacc.c:1646 */ - { +#line 3180 "ripper.y" + { token_info_warn(p, "ensure", p->token_info, 1, &(yyloc)); } -#line 8883 "ripper.c" /* yacc.c:1646 */ +#line 9021 "ripper.c" break; case 368: -#line 3162 "ripper.y" /* yacc.c:1646 */ - { +#line 3186 "ripper.y" + { token_info_warn(p, "when", p->token_info, 0, &(yyloc)); } -#line 8891 "ripper.c" /* yacc.c:1646 */ +#line 9029 "ripper.c" break; case 369: -#line 3168 "ripper.y" /* yacc.c:1646 */ - { +#line 3192 "ripper.y" + { token_info *ptinfo_beg = p->token_info; int same = ptinfo_beg && strcmp(ptinfo_beg->token, "case") != 0; token_info_warn(p, "else", p->token_info, same, &(yyloc)); @@ -8909,372 +9047,372 @@ YYLTYPE yylloc = yyloc_default; if (!e.nonspc) *ptinfo_beg = e; } } -#line 8908 "ripper.c" /* yacc.c:1646 */ +#line 9046 "ripper.c" break; case 370: -#line 3183 "ripper.y" /* yacc.c:1646 */ - { +#line 3207 "ripper.y" + { WARN_EOL("elsif"); token_info_warn(p, "elsif", p->token_info, 1, &(yyloc)); } -#line 8917 "ripper.c" /* yacc.c:1646 */ +#line 9055 "ripper.c" break; case 371: -#line 3190 "ripper.y" /* yacc.c:1646 */ - { +#line 3214 "ripper.y" + { token_info_pop(p, "end", &(yyloc)); } -#line 8925 "ripper.c" /* yacc.c:1646 */ +#line 9063 "ripper.c" break; case 372: -#line 3196 "ripper.y" /* yacc.c:1646 */ - { +#line 3220 "ripper.y" + { if (p->in_class && !p->in_def && !dyna_in_block(p)) yyerror1(&(yylsp[0]), "Invalid return in class/module body"); } -#line 8934 "ripper.c" /* yacc.c:1646 */ +#line 9072 "ripper.c" break; case 379: -#line 3215 "ripper.y" /* yacc.c:1646 */ - { +#line 3239 "ripper.y" + { #if 0 (yyval.val) = new_if(p, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); fixpos((yyval.val), (yyvsp[-3].val)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-3].val);v2=(yyvsp[-1].val);v3=escape_Qundef((yyvsp[0].val));v4=dispatch3(elsif,v1,v2,v3);(yyval.val)=v4;} } -#line 8946 "ripper.c" /* yacc.c:1646 */ +#line 9084 "ripper.c" break; case 381: -#line 3226 "ripper.y" /* yacc.c:1646 */ - { +#line 3250 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(else,v1);(yyval.val)=v2;} } -#line 8957 "ripper.c" /* yacc.c:1646 */ +#line 9095 "ripper.c" break; case 384: -#line 3239 "ripper.y" /* yacc.c:1646 */ - { +#line 3263 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); mark_lvar_used(p, (yyval.val)); #endif (yyval.val)=assignable(p, (yyvsp[0].val)); } -#line 8969 "ripper.c" /* yacc.c:1646 */ +#line 9107 "ripper.c" break; case 385: -#line 3247 "ripper.y" /* yacc.c:1646 */ - { +#line 3271 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(mlhs_paren,v1);(yyval.val)=v2;} } -#line 8980 "ripper.c" /* yacc.c:1646 */ +#line 9118 "ripper.c" break; case 386: -#line 3256 "ripper.y" /* yacc.c:1646 */ - { +#line 3280 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(mlhs_add,v2,v3);(yyval.val)=v4;} } -#line 8991 "ripper.c" /* yacc.c:1646 */ +#line 9129 "ripper.c" break; case 387: -#line 3263 "ripper.y" /* yacc.c:1646 */ - { +#line 3287 "ripper.y" + { #if 0 (yyval.val) = list_append(p, (yyvsp[-2].val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(mlhs_add,v1,v2);(yyval.val)=v3;} } -#line 9002 "ripper.c" /* yacc.c:1646 */ +#line 9140 "ripper.c" break; case 388: -#line 3272 "ripper.y" /* yacc.c:1646 */ - { +#line 3296 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=(yyvsp[0].val); } -#line 9013 "ripper.c" /* yacc.c:1646 */ +#line 9151 "ripper.c" break; case 389: -#line 3279 "ripper.y" /* yacc.c:1646 */ - { +#line 3303 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(mlhs_add_star,v1,v2);(yyval.val)=v3;} } -#line 9024 "ripper.c" /* yacc.c:1646 */ +#line 9162 "ripper.c" break; case 390: -#line 3286 "ripper.y" /* yacc.c:1646 */ - { +#line 3310 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN((yyvsp[-4].val), NEW_POSTARG((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6;v1=(yyvsp[-4].val);v2=(yyvsp[-2].val);v3=dispatch2(mlhs_add_star,v1,v2);v4=v3;v5=(yyvsp[0].val);v6=dispatch2(mlhs_add_post,v4,v5);(yyval.val)=v6;} } -#line 9035 "ripper.c" /* yacc.c:1646 */ +#line 9173 "ripper.c" break; case 391: -#line 3293 "ripper.y" /* yacc.c:1646 */ - { +#line 3317 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(mlhs_add_star,v2,v3);(yyval.val)=v4;} } -#line 9046 "ripper.c" /* yacc.c:1646 */ +#line 9184 "ripper.c" break; case 392: -#line 3300 "ripper.y" /* yacc.c:1646 */ - { +#line 3324 "ripper.y" + { #if 0 (yyval.val) = NEW_MASGN(0, NEW_POSTARG((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=dispatch0(mlhs_new);v2=v1;v3=(yyvsp[-2].val);v4=dispatch2(mlhs_add_star,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(mlhs_add_post,v5,v6);(yyval.val)=v7;} } -#line 9057 "ripper.c" /* yacc.c:1646 */ +#line 9195 "ripper.c" break; case 393: -#line 3309 "ripper.y" /* yacc.c:1646 */ - { +#line 3333 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); mark_lvar_used(p, (yyval.val)); #endif (yyval.val)=assignable(p, (yyvsp[0].val)); } -#line 9069 "ripper.c" /* yacc.c:1646 */ +#line 9207 "ripper.c" break; case 394: -#line 3317 "ripper.y" /* yacc.c:1646 */ - { +#line 3341 "ripper.y" + { #if 0 (yyval.val) = NODE_SPECIAL_NO_NAME_REST; #endif (yyval.val)=Qnil; } -#line 9080 "ripper.c" /* yacc.c:1646 */ +#line 9218 "ripper.c" break; case 395: -#line 3326 "ripper.y" /* yacc.c:1646 */ - { +#line 3350 "ripper.y" + { (yyval.val) = new_args_tail(p, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1])); } -#line 9088 "ripper.c" /* yacc.c:1646 */ +#line 9226 "ripper.c" break; case 396: -#line 3330 "ripper.y" /* yacc.c:1646 */ - { +#line 3354 "ripper.y" + { (yyval.val) = new_args_tail(p, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yylsp[-1])); } -#line 9096 "ripper.c" /* yacc.c:1646 */ +#line 9234 "ripper.c" break; case 397: -#line 3334 "ripper.y" /* yacc.c:1646 */ - { +#line 3358 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1])); } -#line 9104 "ripper.c" /* yacc.c:1646 */ +#line 9242 "ripper.c" break; case 398: -#line 3338 "ripper.y" /* yacc.c:1646 */ - { +#line 3362 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, ID2VAL(idNil), (yyvsp[0].val), &(yylsp[-1])); } -#line 9112 "ripper.c" /* yacc.c:1646 */ +#line 9250 "ripper.c" break; case 399: -#line 3342 "ripper.y" /* yacc.c:1646 */ - { +#line 3366 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, Qnone, (yyvsp[0].val), &(yylsp[0])); } -#line 9120 "ripper.c" /* yacc.c:1646 */ +#line 9258 "ripper.c" break; case 400: -#line 3348 "ripper.y" /* yacc.c:1646 */ - { +#line 3372 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 9128 "ripper.c" /* yacc.c:1646 */ +#line 9266 "ripper.c" break; case 401: -#line 3352 "ripper.y" /* yacc.c:1646 */ - { +#line 3376 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); } -#line 9136 "ripper.c" /* yacc.c:1646 */ +#line 9274 "ripper.c" break; case 402: -#line 3358 "ripper.y" /* yacc.c:1646 */ - { +#line 3382 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9144 "ripper.c" /* yacc.c:1646 */ +#line 9282 "ripper.c" break; case 403: -#line 3362 "ripper.y" /* yacc.c:1646 */ - { +#line 3386 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-7].val), (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9152 "ripper.c" /* yacc.c:1646 */ +#line 9290 "ripper.c" break; case 404: -#line 3366 "ripper.y" /* yacc.c:1646 */ - { +#line 3390 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-3].val), (yyvsp[-1].val), Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9160 "ripper.c" /* yacc.c:1646 */ +#line 9298 "ripper.c" break; case 405: -#line 3370 "ripper.y" /* yacc.c:1646 */ - { +#line 3394 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), (yyvsp[-3].val), Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9168 "ripper.c" /* yacc.c:1646 */ +#line 9306 "ripper.c" break; case 406: -#line 3374 "ripper.y" /* yacc.c:1646 */ - { +#line 3398 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9176 "ripper.c" /* yacc.c:1646 */ +#line 9314 "ripper.c" break; case 407: -#line 3378 "ripper.y" /* yacc.c:1646 */ - { +#line 3402 "ripper.y" + { #if 0 /* magic number for rest_id in iseq_set_arguments() */ (yyval.val) = new_args(p, (yyvsp[-1].val), Qnone, NODE_SPECIAL_EXCESSIVE_COMMA, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[-1])), &(yyloc)); #endif {VALUE v1;v1=dispatch0(excessed_comma);(yyval.val)=new_args(p, (yyvsp[-1].val), Qnone, v1, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, NULL), NULL);} } -#line 9188 "ripper.c" /* yacc.c:1646 */ +#line 9326 "ripper.c" break; case 408: -#line 3386 "ripper.y" /* yacc.c:1646 */ - { +#line 3410 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), Qnone, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9196 "ripper.c" /* yacc.c:1646 */ +#line 9334 "ripper.c" break; case 409: -#line 3390 "ripper.y" /* yacc.c:1646 */ - { +#line 3414 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-1].val), Qnone, Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9204 "ripper.c" /* yacc.c:1646 */ +#line 9342 "ripper.c" break; case 410: -#line 3394 "ripper.y" /* yacc.c:1646 */ - { +#line 3418 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-3].val), (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9212 "ripper.c" /* yacc.c:1646 */ +#line 9350 "ripper.c" break; case 411: -#line 3398 "ripper.y" /* yacc.c:1646 */ - { +#line 3422 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9220 "ripper.c" /* yacc.c:1646 */ +#line 9358 "ripper.c" break; case 412: -#line 3402 "ripper.y" /* yacc.c:1646 */ - { +#line 3426 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-1].val), Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9228 "ripper.c" /* yacc.c:1646 */ +#line 9366 "ripper.c" break; case 413: -#line 3406 "ripper.y" /* yacc.c:1646 */ - { +#line 3430 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9236 "ripper.c" /* yacc.c:1646 */ +#line 9374 "ripper.c" break; case 414: -#line 3410 "ripper.y" /* yacc.c:1646 */ - { +#line 3434 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9244 "ripper.c" /* yacc.c:1646 */ +#line 9382 "ripper.c" break; case 415: -#line 3414 "ripper.y" /* yacc.c:1646 */ - { +#line 3438 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 9252 "ripper.c" /* yacc.c:1646 */ +#line 9390 "ripper.c" break; case 416: -#line 3418 "ripper.y" /* yacc.c:1646 */ - { +#line 3442 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9260 "ripper.c" /* yacc.c:1646 */ +#line 9398 "ripper.c" break; case 418: -#line 3425 "ripper.y" /* yacc.c:1646 */ - { +#line 3449 "ripper.y" + { p->command_start = TRUE; } -#line 9268 "ripper.c" /* yacc.c:1646 */ +#line 9406 "ripper.c" break; case 419: -#line 3431 "ripper.y" /* yacc.c:1646 */ - { +#line 3455 "ripper.y" + { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; #if 0 @@ -9282,12 +9420,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11;v1=Qnil;v2=Qnil;v3=Qnil;v4=Qnil;v5=Qnil;v6=Qnil;v7=Qnil;v8=dispatch7(params,v1,v2,v3,v4,v5,v6,v7);v9=v8;v10=escape_Qundef((yyvsp[-1].val));v11=dispatch2(block_var,v9,v10);(yyval.val)=v11;} } -#line 9281 "ripper.c" /* yacc.c:1646 */ +#line 9419 "ripper.c" break; case 420: -#line 3440 "ripper.y" /* yacc.c:1646 */ - { +#line 3464 "ripper.y" + { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; #if 0 @@ -9295,102 +9433,102 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=escape_Qundef((yyvsp[-2].val));v2=escape_Qundef((yyvsp[-1].val));v3=dispatch2(block_var,v1,v2);(yyval.val)=v3;} } -#line 9294 "ripper.c" /* yacc.c:1646 */ +#line 9432 "ripper.c" break; case 421: -#line 3452 "ripper.y" /* yacc.c:1646 */ - { +#line 3476 "ripper.y" + { (yyval.val) = 0; } -#line 9302 "ripper.c" /* yacc.c:1646 */ +#line 9440 "ripper.c" break; case 422: -#line 3456 "ripper.y" /* yacc.c:1646 */ - { +#line 3480 "ripper.y" + { #if 0 (yyval.val) = 0; #endif (yyval.val)=(yyvsp[-1].val); } -#line 9313 "ripper.c" /* yacc.c:1646 */ +#line 9451 "ripper.c" break; case 423: -#line 3465 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} -#line 9319 "ripper.c" /* yacc.c:1646 */ +#line 3489 "ripper.y" + {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} +#line 9457 "ripper.c" break; case 424: -#line 3467 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val)));} -#line 9325 "ripper.c" /* yacc.c:1646 */ +#line 3491 "ripper.y" + {(yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val)));} +#line 9463 "ripper.c" break; case 425: -#line 3471 "ripper.y" /* yacc.c:1646 */ - { +#line 3495 "ripper.y" + { new_bv(p, get_id((yyvsp[0].val))); (yyval.val)=get_value((yyvsp[0].val)); } -#line 9334 "ripper.c" /* yacc.c:1646 */ +#line 9472 "ripper.c" break; case 426: -#line 3476 "ripper.y" /* yacc.c:1646 */ - { +#line 3500 "ripper.y" + { (yyval.val) = 0; } -#line 9342 "ripper.c" /* yacc.c:1646 */ +#line 9480 "ripper.c" break; case 427: -#line 3481 "ripper.y" /* yacc.c:1646 */ - { +#line 3505 "ripper.y" + { (yyval.vars) = dyna_push(p); } -#line 9350 "ripper.c" /* yacc.c:1646 */ +#line 9488 "ripper.c" break; case 428: -#line 3484 "ripper.y" /* yacc.c:1646 */ - { +#line 3508 "ripper.y" + { (yyval.num) = p->lex.lpar_beg; p->lex.lpar_beg = p->lex.paren_nest; } -#line 9359 "ripper.c" /* yacc.c:1646 */ +#line 9497 "ripper.c" break; case 429: -#line 3488 "ripper.y" /* yacc.c:1646 */ - { +#line 3512 "ripper.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9368 "ripper.c" /* yacc.c:1646 */ +#line 9506 "ripper.c" break; case 430: -#line 3492 "ripper.y" /* yacc.c:1646 */ - { +#line 3516 "ripper.y" + { (yyval.node) = numparam_push(p); } -#line 9376 "ripper.c" /* yacc.c:1646 */ +#line 9514 "ripper.c" break; case 431: -#line 3496 "ripper.y" /* yacc.c:1646 */ - { +#line 3520 "ripper.y" + { CMDARG_PUSH(0); } -#line 9384 "ripper.c" /* yacc.c:1646 */ +#line 9522 "ripper.c" break; case 432: -#line 3500 "ripper.y" /* yacc.c:1646 */ - { +#line 3524 "ripper.y" + { int max_numparam = p->max_numparam; p->lex.lpar_beg = (yyvsp[-5].num); p->max_numparam = (yyvsp[-4].num); @@ -9408,65 +9546,65 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-3].node)); dyna_pop(p, (yyvsp[-6].vars)); } -#line 9407 "ripper.c" /* yacc.c:1646 */ +#line 9545 "ripper.c" break; case 433: -#line 3521 "ripper.y" /* yacc.c:1646 */ - { +#line 3545 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-2].val); p->max_numparam = ORDINAL_PARAM; #endif {VALUE v1,v2;v1=(yyvsp[-2].val);v2=dispatch1(paren,v1);(yyval.val)=v2;} } -#line 9419 "ripper.c" /* yacc.c:1646 */ +#line 9557 "ripper.c" break; case 434: -#line 3529 "ripper.y" /* yacc.c:1646 */ - { +#line 3553 "ripper.y" + { #if 0 if (!args_info_empty_p((yyvsp[0].val)->nd_ainfo)) p->max_numparam = ORDINAL_PARAM; #endif (yyval.val) = (yyvsp[0].val); } -#line 9431 "ripper.c" /* yacc.c:1646 */ +#line 9569 "ripper.c" break; case 435: -#line 3539 "ripper.y" /* yacc.c:1646 */ - { +#line 3563 "ripper.y" + { token_info_pop(p, "}", &(yylsp[0])); (yyval.val) = (yyvsp[-1].val); } -#line 9440 "ripper.c" /* yacc.c:1646 */ +#line 9578 "ripper.c" break; case 436: -#line 3544 "ripper.y" /* yacc.c:1646 */ - { +#line 3568 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); } -#line 9448 "ripper.c" /* yacc.c:1646 */ +#line 9586 "ripper.c" break; case 437: -#line 3550 "ripper.y" /* yacc.c:1646 */ - { +#line 3574 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); #if 0 (yyval.val)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.val), (yylsp[-2]).end_pos.lineno); #endif } -#line 9460 "ripper.c" /* yacc.c:1646 */ +#line 9598 "ripper.c" break; case 438: -#line 3560 "ripper.y" /* yacc.c:1646 */ - { +#line 3584 "ripper.y" + { #if 0 if (nd_type((yyvsp[-1].val)) == NODE_YIELD) { compile_error(p, "block given to yield"); @@ -9479,45 +9617,45 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(method_add_block,v1,v2);(yyval.val)=v3;} } -#line 9478 "ripper.c" /* yacc.c:1646 */ +#line 9616 "ripper.c" break; case 439: -#line 3574 "ripper.y" /* yacc.c:1646 */ - { +#line 3598 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, (yyvsp[-2].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-3].val);v2=(yyvsp[-2].val);v3=(yyvsp[-1].val);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=v6==Qundef ? v5 : dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 9489 "ripper.c" /* yacc.c:1646 */ +#line 9627 "ripper.c" break; case 440: -#line 3581 "ripper.y" /* yacc.c:1646 */ - { +#line 3605 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, (yyvsp[-3].val), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-2]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=(yyvsp[-1].val);v5=dispatch4(command_call,v1,v2,v3,v4);v6=v5;v7=(yyvsp[0].val);v8=v7==Qundef ? v6 : dispatch2(method_add_block,v6,v7);(yyval.val)=v8;} } -#line 9500 "ripper.c" /* yacc.c:1646 */ +#line 9638 "ripper.c" break; case 441: -#line 3588 "ripper.y" /* yacc.c:1646 */ - { +#line 3612 "ripper.y" + { #if 0 (yyval.val) = new_command_qcall(p, (yyvsp[-3].val), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-2]), &(yyloc)); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=(yyvsp[-4].val);v2=(yyvsp[-3].val);v3=(yyvsp[-2].val);v4=(yyvsp[-1].val);v5=dispatch4(command_call,v1,v2,v3,v4);v6=v5;v7=(yyvsp[0].val);v8=dispatch2(method_add_block,v6,v7);(yyval.val)=v8;} } -#line 9511 "ripper.c" /* yacc.c:1646 */ +#line 9649 "ripper.c" break; case 442: -#line 3597 "ripper.y" /* yacc.c:1646 */ - { +#line 3621 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); (yyval.val)->nd_args = (yyvsp[0].val); @@ -9525,93 +9663,93 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-1].val);v2=dispatch1(fcall,v1);v3=v2;v4=(yyvsp[0].val);v5=dispatch2(method_add_arg,v3,v4);(yyval.val)=v5;} } -#line 9524 "ripper.c" /* yacc.c:1646 */ +#line 9662 "ripper.c" break; case 443: -#line 3606 "ripper.y" /* yacc.c:1646 */ - { +#line 3630 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, (yyvsp[-2].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.val), (yylsp[-1]).end_pos.lineno); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-3].val);v2=(yyvsp[-2].val);v3=(yyvsp[-1].val);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=v6==Qundef ? v5 : dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 9536 "ripper.c" /* yacc.c:1646 */ +#line 9674 "ripper.c" break; case 444: -#line 3614 "ripper.y" /* yacc.c:1646 */ - { +#line 3638 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.val), (yylsp[-1]).end_pos.lineno); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-3].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[-1].val);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 9548 "ripper.c" /* yacc.c:1646 */ +#line 9686 "ripper.c" break; case 445: -#line 3622 "ripper.y" /* yacc.c:1646 */ - { +#line 3646 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-2].val), (yyvsp[0].val), Qnull, &(yylsp[0]), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=ID2VAL(idCOLON2);v3=(yyvsp[0].val);v4=dispatch3(call,v1,v2,v3);(yyval.val)=v4;} } -#line 9559 "ripper.c" /* yacc.c:1646 */ +#line 9697 "ripper.c" break; case 446: -#line 3629 "ripper.y" /* yacc.c:1646 */ - { +#line 3653 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, (yyvsp[-1].val), (yyvsp[-2].val), ID2VAL(idCall), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.val), (yylsp[-1]).end_pos.lineno); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=ID2VAL(idCall);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 9571 "ripper.c" /* yacc.c:1646 */ +#line 9709 "ripper.c" break; case 447: -#line 3637 "ripper.y" /* yacc.c:1646 */ - { +#line 3661 "ripper.y" + { #if 0 (yyval.val) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-2].val), ID2VAL(idCall), (yyvsp[0].val), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.val), (yylsp[-1]).end_pos.lineno); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=(yyvsp[-2].val);v2=ID2VAL(idCOLON2);v3=ID2VAL(idCall);v4=dispatch3(call,v1,v2,v3);v5=v4;v6=(yyvsp[0].val);v7=dispatch2(method_add_arg,v5,v6);(yyval.val)=v7;} } -#line 9583 "ripper.c" /* yacc.c:1646 */ +#line 9721 "ripper.c" break; case 448: -#line 3645 "ripper.y" /* yacc.c:1646 */ - { +#line 3669 "ripper.y" + { #if 0 (yyval.val) = NEW_SUPER((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(super,v1);(yyval.val)=v2;} } -#line 9594 "ripper.c" /* yacc.c:1646 */ +#line 9732 "ripper.c" break; case 449: -#line 3652 "ripper.y" /* yacc.c:1646 */ - { +#line 3676 "ripper.y" + { #if 0 (yyval.val) = NEW_ZSUPER(&(yyloc)); #endif {VALUE v1;v1=dispatch0(zsuper);(yyval.val)=v1;} } -#line 9605 "ripper.c" /* yacc.c:1646 */ +#line 9743 "ripper.c" break; case 450: -#line 3659 "ripper.y" /* yacc.c:1646 */ - { +#line 3683 "ripper.y" + { #if 0 if ((yyvsp[-3].val) && nd_type((yyvsp[-3].val)) == NODE_SELF) (yyval.val) = NEW_FCALL(tAREF, (yyvsp[-1].val), &(yyloc)); @@ -9621,59 +9759,59 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=escape_Qundef((yyvsp[-1].val));v3=dispatch2(aref,v1,v2);(yyval.val)=v3;} } -#line 9620 "ripper.c" /* yacc.c:1646 */ +#line 9758 "ripper.c" break; case 451: -#line 3672 "ripper.y" /* yacc.c:1646 */ - { +#line 3696 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); #if 0 (yyval.val)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.val), (yylsp[-2]).end_pos.lineno); #endif } -#line 9632 "ripper.c" /* yacc.c:1646 */ +#line 9770 "ripper.c" break; case 452: -#line 3680 "ripper.y" /* yacc.c:1646 */ - { +#line 3704 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); #if 0 (yyval.val)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.val), (yylsp[-2]).end_pos.lineno); #endif } -#line 9644 "ripper.c" /* yacc.c:1646 */ +#line 9782 "ripper.c" break; case 453: -#line 3689 "ripper.y" /* yacc.c:1646 */ - {(yyval.vars) = dyna_push(p);} -#line 9650 "ripper.c" /* yacc.c:1646 */ +#line 3713 "ripper.y" + {(yyval.vars) = dyna_push(p);} +#line 9788 "ripper.c" break; case 454: -#line 3690 "ripper.y" /* yacc.c:1646 */ - { +#line 3714 "ripper.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9659 "ripper.c" /* yacc.c:1646 */ +#line 9797 "ripper.c" break; case 455: -#line 3694 "ripper.y" /* yacc.c:1646 */ - { +#line 3718 "ripper.y" + { (yyval.node) = numparam_push(p); } -#line 9667 "ripper.c" /* yacc.c:1646 */ +#line 9805 "ripper.c" break; case 456: -#line 3698 "ripper.y" /* yacc.c:1646 */ - { +#line 3722 "ripper.y" + { int max_numparam = p->max_numparam; p->max_numparam = (yyvsp[-3].num); (yyvsp[-1].val) = args_with_numbered(p, (yyvsp[-1].val), max_numparam); @@ -9684,36 +9822,36 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-2].node)); dyna_pop(p, (yyvsp[-4].vars)); } -#line 9683 "ripper.c" /* yacc.c:1646 */ +#line 9821 "ripper.c" break; case 457: -#line 3711 "ripper.y" /* yacc.c:1646 */ - {(yyval.vars) = dyna_push(p);} -#line 9689 "ripper.c" /* yacc.c:1646 */ +#line 3735 "ripper.y" + {(yyval.vars) = dyna_push(p);} +#line 9827 "ripper.c" break; case 458: -#line 3712 "ripper.y" /* yacc.c:1646 */ - { +#line 3736 "ripper.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9698 "ripper.c" /* yacc.c:1646 */ +#line 9836 "ripper.c" break; case 459: -#line 3716 "ripper.y" /* yacc.c:1646 */ - { +#line 3740 "ripper.y" + { (yyval.node) = numparam_push(p); CMDARG_PUSH(0); } -#line 9707 "ripper.c" /* yacc.c:1646 */ +#line 9845 "ripper.c" break; case 460: -#line 3721 "ripper.y" /* yacc.c:1646 */ - { +#line 3745 "ripper.y" + { int max_numparam = p->max_numparam; p->max_numparam = (yyvsp[-3].num); (yyvsp[-1].val) = args_with_numbered(p, (yyvsp[-1].val), max_numparam); @@ -9725,185 +9863,185 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-2].node)); dyna_pop(p, (yyvsp[-4].vars)); } -#line 9724 "ripper.c" /* yacc.c:1646 */ +#line 9862 "ripper.c" break; case 461: -#line 3736 "ripper.y" /* yacc.c:1646 */ - { +#line 3760 "ripper.y" + { #if 0 check_literal_when(p, (yyvsp[0].val), &(yylsp[0])); (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add,v2,v3);(yyval.val)=v4;} } -#line 9736 "ripper.c" /* yacc.c:1646 */ +#line 9874 "ripper.c" break; case 462: -#line 3744 "ripper.y" /* yacc.c:1646 */ - { +#line 3768 "ripper.y" + { #if 0 (yyval.val) = NEW_SPLAT((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=dispatch0(args_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(args_add_star,v2,v3);(yyval.val)=v4;} } -#line 9747 "ripper.c" /* yacc.c:1646 */ +#line 9885 "ripper.c" break; case 463: -#line 3751 "ripper.y" /* yacc.c:1646 */ - { +#line 3775 "ripper.y" + { #if 0 check_literal_when(p, (yyvsp[0].val), &(yylsp[0])); (yyval.val) = last_arg_append(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(args_add,v1,v2);(yyval.val)=v3;} } -#line 9759 "ripper.c" /* yacc.c:1646 */ +#line 9897 "ripper.c" break; case 464: -#line 3759 "ripper.y" /* yacc.c:1646 */ - { +#line 3783 "ripper.y" + { #if 0 (yyval.val) = rest_arg_append(p, (yyvsp[-3].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-3].val);v2=(yyvsp[0].val);v3=dispatch2(args_add_star,v1,v2);(yyval.val)=v3;} } -#line 9770 "ripper.c" /* yacc.c:1646 */ +#line 9908 "ripper.c" break; case 465: -#line 3770 "ripper.y" /* yacc.c:1646 */ - { +#line 3794 "ripper.y" + { #if 0 (yyval.val) = NEW_WHEN((yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); fixpos((yyval.val), (yyvsp[-3].val)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-3].val);v2=(yyvsp[-1].val);v3=escape_Qundef((yyvsp[0].val));v4=dispatch3(when,v1,v2,v3);(yyval.val)=v4;} } -#line 9782 "ripper.c" /* yacc.c:1646 */ +#line 9920 "ripper.c" break; case 468: -#line 3784 "ripper.y" /* yacc.c:1646 */ - { +#line 3808 "ripper.y" + { SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; (yyval.num) = p->in_kwarg; p->in_kwarg = 1; } -#line 9793 "ripper.c" /* yacc.c:1646 */ +#line 9931 "ripper.c" break; case 469: -#line 3790 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pvtbl(p);} -#line 9799 "ripper.c" /* yacc.c:1646 */ +#line 3814 "ripper.y" + {(yyval.tbl) = push_pvtbl(p);} +#line 9937 "ripper.c" break; case 470: -#line 3791 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9805 "ripper.c" /* yacc.c:1646 */ +#line 3815 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 9943 "ripper.c" break; case 471: -#line 3793 "ripper.y" /* yacc.c:1646 */ - {pop_pktbl(p, (yyvsp[-2].tbl));} -#line 9811 "ripper.c" /* yacc.c:1646 */ +#line 3817 "ripper.y" + {pop_pktbl(p, (yyvsp[-2].tbl));} +#line 9949 "ripper.c" break; case 472: -#line 3794 "ripper.y" /* yacc.c:1646 */ - {pop_pvtbl(p, (yyvsp[-4].tbl));} -#line 9817 "ripper.c" /* yacc.c:1646 */ +#line 3818 "ripper.y" + {pop_pvtbl(p, (yyvsp[-4].tbl));} +#line 9955 "ripper.c" break; case 473: -#line 3795 "ripper.y" /* yacc.c:1646 */ - { +#line 3819 "ripper.y" + { p->in_kwarg = !!(yyvsp[-6].num); } -#line 9825 "ripper.c" /* yacc.c:1646 */ +#line 9963 "ripper.c" break; case 474: -#line 3800 "ripper.y" /* yacc.c:1646 */ - { +#line 3824 "ripper.y" + { #if 0 (yyval.val) = NEW_IN((yyvsp[-6].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-6].val);v2=(yyvsp[-1].val);v3=escape_Qundef((yyvsp[0].val));v4=dispatch3(in,v1,v2,v3);(yyval.val)=v4;} } -#line 9836 "ripper.c" /* yacc.c:1646 */ +#line 9974 "ripper.c" break; case 478: -#line 3814 "ripper.y" /* yacc.c:1646 */ - { +#line 3838 "ripper.y" + { #if 0 (yyval.val) = new_if(p, (yyvsp[0].val), remove_begin((yyvsp[-2].val)), 0, &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(if_mod,v1,v2);(yyval.val)=v3;} } -#line 9848 "ripper.c" /* yacc.c:1646 */ +#line 9986 "ripper.c" break; case 479: -#line 3822 "ripper.y" /* yacc.c:1646 */ - { +#line 3846 "ripper.y" + { #if 0 (yyval.val) = new_unless(p, (yyvsp[0].val), remove_begin((yyvsp[-2].val)), 0, &(yyloc)); fixpos((yyval.val), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[0].val);v2=(yyvsp[-2].val);v3=dispatch2(unless_mod,v1,v2);(yyval.val)=v3;} } -#line 9860 "ripper.c" /* yacc.c:1646 */ +#line 9998 "ripper.c" break; case 481: -#line 3833 "ripper.y" /* yacc.c:1646 */ - { +#line 3857 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &(yyloc)); (yyval.val) = new_array_pattern(p, Qnone, get_value((yyvsp[-1].val)), (yyval.val), &(yyloc)); } -#line 9869 "ripper.c" /* yacc.c:1646 */ +#line 10007 "ripper.c" break; case 482: -#line 3838 "ripper.y" /* yacc.c:1646 */ - { +#line 3862 "ripper.y" + { (yyval.val) = new_array_pattern(p, Qnone, get_value((yyvsp[-2].val)), (yyvsp[0].val), &(yyloc)); #if 0 nd_set_first_loc((yyval.val), (yylsp[-2]).beg_pos); #endif } -#line 9881 "ripper.c" /* yacc.c:1646 */ +#line 10019 "ripper.c" break; case 483: -#line 3846 "ripper.y" /* yacc.c:1646 */ - { +#line 3870 "ripper.y" + { (yyval.val) = new_array_pattern(p, Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9889 "ripper.c" /* yacc.c:1646 */ +#line 10027 "ripper.c" break; case 484: -#line 3850 "ripper.y" /* yacc.c:1646 */ - { +#line 3874 "ripper.y" + { (yyval.val) = new_hash_pattern(p, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 9897 "ripper.c" /* yacc.c:1646 */ +#line 10035 "ripper.c" break; case 486: -#line 3859 "ripper.y" /* yacc.c:1646 */ - { +#line 3883 "ripper.y" + { #if 0 NODE *n = NEW_LIST((yyvsp[-2].val), &(yyloc)); n = list_append(p, n, (yyvsp[0].val)); @@ -9911,35 +10049,35 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=STATIC_ID2SYM(id_assoc);v3=(yyvsp[0].val);v4=dispatch3(binary,v1,v2,v3);(yyval.val)=v4;} } -#line 9910 "ripper.c" /* yacc.c:1646 */ +#line 10048 "ripper.c" break; case 488: -#line 3871 "ripper.y" /* yacc.c:1646 */ - { +#line 3895 "ripper.y" + { #if 0 (yyval.val) = NEW_NODE(NODE_OR, (yyvsp[-2].val), (yyvsp[0].val), 0, &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[-2].val);v2=STATIC_ID2SYM(idOr);v3=(yyvsp[0].val);v4=dispatch3(binary,v1,v2,v3);(yyval.val)=v4;} } -#line 9921 "ripper.c" /* yacc.c:1646 */ +#line 10059 "ripper.c" break; case 490: -#line 3880 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9927 "ripper.c" /* yacc.c:1646 */ +#line 3904 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10065 "ripper.c" break; case 491: -#line 3881 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9933 "ripper.c" /* yacc.c:1646 */ +#line 3905 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10071 "ripper.c" break; case 493: -#line 3885 "ripper.y" /* yacc.c:1646 */ - { +#line 3909 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = new_array_pattern(p, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), &(yyloc)); #if 0 @@ -9947,12 +10085,12 @@ YYLTYPE yylloc = yyloc_default; #endif } -#line 9946 "ripper.c" /* yacc.c:1646 */ +#line 10084 "ripper.c" break; case 494: -#line 3894 "ripper.y" /* yacc.c:1646 */ - { +#line 3918 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = new_hash_pattern(p, (yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); #if 0 @@ -9960,21 +10098,21 @@ YYLTYPE yylloc = yyloc_default; #endif } -#line 9959 "ripper.c" /* yacc.c:1646 */ +#line 10097 "ripper.c" break; case 495: -#line 3903 "ripper.y" /* yacc.c:1646 */ - { +#line 3927 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.val) = new_array_pattern(p, (yyvsp[-2].val), Qnone, (yyval.val), &(yyloc)); } -#line 9968 "ripper.c" /* yacc.c:1646 */ +#line 10106 "ripper.c" break; case 496: -#line 3908 "ripper.y" /* yacc.c:1646 */ - { +#line 3932 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = new_array_pattern(p, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), &(yyloc)); #if 0 @@ -9982,12 +10120,12 @@ YYLTYPE yylloc = yyloc_default; #endif } -#line 9981 "ripper.c" /* yacc.c:1646 */ +#line 10119 "ripper.c" break; case 497: -#line 3917 "ripper.y" /* yacc.c:1646 */ - { +#line 3941 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = new_hash_pattern(p, (yyvsp[-3].val), (yyvsp[-1].val), &(yyloc)); #if 0 @@ -9995,89 +10133,84 @@ YYLTYPE yylloc = yyloc_default; #endif } -#line 9994 "ripper.c" /* yacc.c:1646 */ +#line 10132 "ripper.c" break; case 498: -#line 3926 "ripper.y" /* yacc.c:1646 */ - { +#line 3950 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.val) = new_array_pattern(p, (yyvsp[-2].val), Qnone, (yyval.val), &(yyloc)); } -#line 10003 "ripper.c" /* yacc.c:1646 */ +#line 10141 "ripper.c" break; case 499: -#line 3930 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 10009 "ripper.c" /* yacc.c:1646 */ +#line 3954 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10147 "ripper.c" break; case 500: -#line 3931 "ripper.y" /* yacc.c:1646 */ - { +#line 3955 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = new_array_pattern(p, Qnone, Qnone, (yyvsp[-1].val), &(yyloc)); } -#line 10018 "ripper.c" /* yacc.c:1646 */ +#line 10156 "ripper.c" break; case 501: -#line 3936 "ripper.y" /* yacc.c:1646 */ - { +#line 3960 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.val) = new_array_pattern(p, Qnone, Qnone, (yyval.val), &(yyloc)); } -#line 10027 "ripper.c" /* yacc.c:1646 */ +#line 10165 "ripper.c" break; case 502: -#line 3941 "ripper.y" /* yacc.c:1646 */ - { - (yyval.tbl) = push_pktbl(p); - (yyvsp[0].num) = p->in_kwarg; - p->in_kwarg = 0; - } -#line 10037 "ripper.c" /* yacc.c:1646 */ +#line 3964 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10171 "ripper.c" break; case 503: -#line 3947 "ripper.y" /* yacc.c:1646 */ - { +#line 3965 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); - p->in_kwarg = (yyvsp[-3].num); (yyval.val) = new_hash_pattern(p, Qnone, (yyvsp[-1].val), &(yyloc)); } -#line 10047 "ripper.c" /* yacc.c:1646 */ +#line 10180 "ripper.c" break; case 504: -#line 3953 "ripper.y" /* yacc.c:1646 */ - { +#line 3970 "ripper.y" + { (yyval.val) = new_hash_pattern_tail(p, Qnone, 0, &(yyloc)); (yyval.val) = new_hash_pattern(p, Qnone, (yyval.val), &(yyloc)); } -#line 10056 "ripper.c" /* yacc.c:1646 */ +#line 10189 "ripper.c" break; case 505: -#line 3957 "ripper.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 10062 "ripper.c" /* yacc.c:1646 */ +#line 3974 "ripper.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10195 "ripper.c" break; case 506: -#line 3958 "ripper.y" /* yacc.c:1646 */ - { +#line 3975 "ripper.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.val) = (yyvsp[-1].val); } -#line 10071 "ripper.c" /* yacc.c:1646 */ +#line 10204 "ripper.c" break; case 507: -#line 3965 "ripper.y" /* yacc.c:1646 */ - { +#line 3982 "ripper.y" + { #if 0 NODE *pre_args = NEW_LIST((yyvsp[0].val), &(yyloc)); (yyval.val) = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &(yyloc)); @@ -10085,20 +10218,20 @@ YYLTYPE yylloc = yyloc_default; (yyval.val) = new_array_pattern_tail(p, rb_ary_new_from_args(1, get_value((yyvsp[0].val))), 0, 0, Qnone, &(yyloc)); } -#line 10084 "ripper.c" /* yacc.c:1646 */ +#line 10217 "ripper.c" break; case 508: -#line 3974 "ripper.y" /* yacc.c:1646 */ - { +#line 3991 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, (yyvsp[0].val), 1, 0, Qnone, &(yyloc)); } -#line 10092 "ripper.c" /* yacc.c:1646 */ +#line 10225 "ripper.c" break; case 509: -#line 3978 "ripper.y" /* yacc.c:1646 */ - { +#line 3995 "ripper.y" + { #if 0 (yyval.val) = new_array_pattern_tail(p, list_concat((yyvsp[-1].val), (yyvsp[0].val)), 0, 0, Qnone, &(yyloc)); #endif @@ -10106,194 +10239,186 @@ YYLTYPE yylloc = yyloc_default; (yyval.val) = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &(yyloc)); } -#line 10105 "ripper.c" /* yacc.c:1646 */ +#line 10238 "ripper.c" break; case 510: -#line 3987 "ripper.y" /* yacc.c:1646 */ - { +#line 4004 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, (yyvsp[-2].val), 1, (yyvsp[0].val), Qnone, &(yyloc)); } -#line 10113 "ripper.c" /* yacc.c:1646 */ +#line 10246 "ripper.c" break; case 511: -#line 3991 "ripper.y" /* yacc.c:1646 */ - { +#line 4008 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, (yyvsp[-4].val), 1, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); } -#line 10121 "ripper.c" /* yacc.c:1646 */ +#line 10254 "ripper.c" break; case 512: -#line 3995 "ripper.y" /* yacc.c:1646 */ - { +#line 4012 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, (yyvsp[-1].val), 1, 0, Qnone, &(yyloc)); } -#line 10129 "ripper.c" /* yacc.c:1646 */ +#line 10262 "ripper.c" break; case 513: -#line 3999 "ripper.y" /* yacc.c:1646 */ - { +#line 4016 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, (yyvsp[-3].val), 1, 0, (yyvsp[0].val), &(yyloc)); } -#line 10137 "ripper.c" /* yacc.c:1646 */ +#line 10270 "ripper.c" break; case 515: -#line 4006 "ripper.y" /* yacc.c:1646 */ - { +#line 4023 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); } -#line 10145 "ripper.c" /* yacc.c:1646 */ +#line 10278 "ripper.c" break; case 516: -#line 4010 "ripper.y" /* yacc.c:1646 */ - { +#line 4027 "ripper.y" + { #if 0 (yyval.val) = list_concat((yyvsp[-2].val), (yyvsp[-1].val)); #endif (yyval.val)=rb_ary_concat((yyvsp[-2].val), get_value((yyvsp[-1].val))); } -#line 10156 "ripper.c" /* yacc.c:1646 */ +#line 10289 "ripper.c" break; case 517: -#line 4019 "ripper.y" /* yacc.c:1646 */ - { +#line 4036 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 1, (yyvsp[0].val), Qnone, &(yyloc)); } -#line 10164 "ripper.c" /* yacc.c:1646 */ +#line 10297 "ripper.c" break; case 518: -#line 4023 "ripper.y" /* yacc.c:1646 */ - { +#line 4040 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 1, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); } -#line 10172 "ripper.c" /* yacc.c:1646 */ +#line 10305 "ripper.c" break; case 519: -#line 4027 "ripper.y" /* yacc.c:1646 */ - { +#line 4044 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &(yyloc)); } -#line 10180 "ripper.c" /* yacc.c:1646 */ +#line 10313 "ripper.c" break; case 520: -#line 4031 "ripper.y" /* yacc.c:1646 */ - { +#line 4048 "ripper.y" + { (yyval.val) = new_array_pattern_tail(p, Qnone, 1, 0, (yyvsp[0].val), &(yyloc)); } -#line 10188 "ripper.c" /* yacc.c:1646 */ +#line 10321 "ripper.c" break; case 522: -#line 4038 "ripper.y" /* yacc.c:1646 */ - { +#line 4055 "ripper.y" + { #if 0 (yyval.val) = list_concat((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_concat((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 10199 "ripper.c" /* yacc.c:1646 */ +#line 10332 "ripper.c" break; case 523: -#line 4047 "ripper.y" /* yacc.c:1646 */ - { +#line 4064 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif (yyval.val)=rb_ary_new_from_args(1, get_value((yyvsp[0].val))); } -#line 10210 "ripper.c" /* yacc.c:1646 */ +#line 10343 "ripper.c" break; case 524: -#line 4056 "ripper.y" /* yacc.c:1646 */ - { +#line 4073 "ripper.y" + { (yyval.val) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-2].val), &(yyloc)), (yyvsp[0].val), &(yyloc)); } -#line 10218 "ripper.c" /* yacc.c:1646 */ +#line 10351 "ripper.c" break; case 525: -#line 4060 "ripper.y" /* yacc.c:1646 */ - { +#line 4077 "ripper.y" + { (yyval.val) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[0].val), &(yyloc)), 0, &(yyloc)); } -#line 10226 "ripper.c" /* yacc.c:1646 */ +#line 10359 "ripper.c" break; case 526: -#line 4064 "ripper.y" /* yacc.c:1646 */ - { - (yyval.val) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-1].val), &(yyloc)), 0, &(yyloc)); +#line 4081 "ripper.y" + { + (yyval.val) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), (yyvsp[0].val), &(yyloc)); } -#line 10234 "ripper.c" /* yacc.c:1646 */ +#line 10367 "ripper.c" break; case 527: -#line 4068 "ripper.y" /* yacc.c:1646 */ - { - (yyval.val) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), (yyvsp[0].val), &(yyloc)); +#line 4085 "ripper.y" + { + (yyval.val) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-2].val), &(yyloc)), ID2VAL(idNil), &(yyloc)); } -#line 10242 "ripper.c" /* yacc.c:1646 */ +#line 10375 "ripper.c" break; case 528: -#line 4072 "ripper.y" /* yacc.c:1646 */ - { - (yyval.val) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-2].val), &(yyloc)), ID2VAL(idNil), &(yyloc)); +#line 4089 "ripper.y" + { + (yyval.val) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), ID2VAL(idNil), &(yyloc)); } -#line 10250 "ripper.c" /* yacc.c:1646 */ +#line 10383 "ripper.c" break; case 529: -#line 4076 "ripper.y" /* yacc.c:1646 */ - { - (yyval.val) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), ID2VAL(idNil), &(yyloc)); - } -#line 10258 "ripper.c" /* yacc.c:1646 */ +#line 4095 "ripper.y" + {(yyval.val)=rb_ary_new_from_args(1, (yyvsp[0].val));} +#line 10389 "ripper.c" break; case 530: -#line 4082 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=rb_ary_new_from_args(1, (yyvsp[0].val));} -#line 10264 "ripper.c" /* yacc.c:1646 */ - break; - - case 531: -#line 4084 "ripper.y" /* yacc.c:1646 */ - { +#line 4097 "ripper.y" + { #if 0 (yyval.val) = list_concat((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), (yyvsp[0].val)); } -#line 10275 "ripper.c" /* yacc.c:1646 */ +#line 10400 "ripper.c" break; - case 532: -#line 4093 "ripper.y" /* yacc.c:1646 */ - { + case 531: +#line 4106 "ripper.y" + { error_duplicate_pattern_key(p, get_id((yyvsp[-1].val)), &(yylsp[-1])); #if 0 (yyval.val) = list_append(p, NEW_LIST(NEW_LIT(ID2SYM((yyvsp[-1].val)), &(yyloc)), &(yyloc)), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_new_from_args(2, get_value((yyvsp[-1].val)), get_value((yyvsp[0].val))); } -#line 10287 "ripper.c" /* yacc.c:1646 */ +#line 10412 "ripper.c" break; - case 533: -#line 4101 "ripper.y" /* yacc.c:1646 */ - { + case 532: +#line 4114 "ripper.y" + { error_duplicate_pattern_key(p, get_id((yyvsp[0].val)), &(yylsp[0])); if ((yyvsp[0].val) && !is_local_id(get_id((yyvsp[0].val)))) { yyerror1(&(yylsp[0]), "key must be valid as local variables"); @@ -10304,12 +10429,12 @@ YYLTYPE yylloc = yyloc_default; #endif (yyval.val)=rb_ary_new_from_args(2, get_value((yyvsp[0].val)), Qnil); } -#line 10303 "ripper.c" /* yacc.c:1646 */ +#line 10428 "ripper.c" break; - case 535: -#line 4116 "ripper.y" /* yacc.c:1646 */ - { + case 534: +#line 4129 "ripper.y" + { YYLTYPE loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); #if 0 if (!(yyvsp[-1].val) || nd_type((yyvsp[-1].val)) == NODE_STR) { @@ -10329,36 +10454,36 @@ YYLTYPE yylloc = yyloc_default; (yyval.val) = 0; } } -#line 10328 "ripper.c" /* yacc.c:1646 */ +#line 10453 "ripper.c" break; - case 536: -#line 4139 "ripper.y" /* yacc.c:1646 */ - { + case 535: +#line 4152 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 10336 "ripper.c" /* yacc.c:1646 */ +#line 10461 "ripper.c" break; - case 537: -#line 4143 "ripper.y" /* yacc.c:1646 */ - { + case 536: +#line 4156 "ripper.y" + { (yyval.val) = 0; } -#line 10344 "ripper.c" /* yacc.c:1646 */ +#line 10469 "ripper.c" break; - case 538: -#line 4149 "ripper.y" /* yacc.c:1646 */ - { + case 537: +#line 4162 "ripper.y" + { (yyval.val) = 0; } -#line 10352 "ripper.c" /* yacc.c:1646 */ +#line 10477 "ripper.c" break; - case 540: -#line 4156 "ripper.y" /* yacc.c:1646 */ - { + case 539: +#line 4169 "ripper.y" + { #if 0 value_expr((yyvsp[-2].val)); value_expr((yyvsp[0].val)); @@ -10366,12 +10491,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 10365 "ripper.c" /* yacc.c:1646 */ +#line 10490 "ripper.c" break; - case 541: -#line 4165 "ripper.y" /* yacc.c:1646 */ - { + case 540: +#line 4178 "ripper.y" + { #if 0 value_expr((yyvsp[-2].val)); value_expr((yyvsp[0].val)); @@ -10379,12 +10504,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 10378 "ripper.c" /* yacc.c:1646 */ +#line 10503 "ripper.c" break; - case 542: -#line 4174 "ripper.y" /* yacc.c:1646 */ - { + case 541: +#line 4187 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -10395,12 +10520,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=Qnil;v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 10394 "ripper.c" /* yacc.c:1646 */ +#line 10519 "ripper.c" break; - case 543: -#line 4186 "ripper.y" /* yacc.c:1646 */ - { + case 542: +#line 4199 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -10411,12 +10536,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=Qnil;v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 10410 "ripper.c" /* yacc.c:1646 */ +#line 10535 "ripper.c" break; - case 547: -#line 4201 "ripper.y" /* yacc.c:1646 */ - { + case 546: +#line 4214 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -10427,12 +10552,12 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=Qnil;v2=(yyvsp[0].val);v3=dispatch2(dot2,v1,v2);(yyval.val)=v3;} } -#line 10426 "ripper.c" /* yacc.c:1646 */ +#line 10551 "ripper.c" break; - case 548: -#line 4213 "ripper.y" /* yacc.c:1646 */ - { + case 547: +#line 4226 "ripper.y" + { #if 0 YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -10443,54 +10568,54 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=Qnil;v2=(yyvsp[0].val);v3=dispatch2(dot3,v1,v2);(yyval.val)=v3;} } -#line 10442 "ripper.c" /* yacc.c:1646 */ +#line 10567 "ripper.c" break; - case 557: -#line 4235 "ripper.y" /* yacc.c:1646 */ - { + case 556: +#line 4248 "ripper.y" + { #if 0 if (!((yyval.val) = gettable(p, (yyvsp[0].val), &(yyloc)))) (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 10453 "ripper.c" /* yacc.c:1646 */ +#line 10578 "ripper.c" break; - case 558: -#line 4242 "ripper.y" /* yacc.c:1646 */ - { + case 557: +#line 4255 "ripper.y" + { token_info_push(p, "->", &(yylsp[0])); } -#line 10461 "ripper.c" /* yacc.c:1646 */ +#line 10586 "ripper.c" break; - case 559: -#line 4246 "ripper.y" /* yacc.c:1646 */ - { + case 558: +#line 4259 "ripper.y" + { (yyval.val) = (yyvsp[0].val); #if 0 nd_set_first_loc((yyval.val), (yylsp[-2]).beg_pos); #endif } -#line 10472 "ripper.c" /* yacc.c:1646 */ +#line 10597 "ripper.c" break; - case 560: -#line 4255 "ripper.y" /* yacc.c:1646 */ - { + case 559: +#line 4268 "ripper.y" + { #if 0 error_duplicate_pattern_variable(p, (yyvsp[0].val), &(yylsp[0])); (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 10484 "ripper.c" /* yacc.c:1646 */ +#line 10609 "ripper.c" break; - case 561: -#line 4265 "ripper.y" /* yacc.c:1646 */ - { + case 560: +#line 4278 "ripper.y" + { #if 0 NODE *n = gettable(p, (yyvsp[0].val), &(yyloc)); if (!(nd_type(n) == NODE_LVAR || nd_type(n) == NODE_DVAR)) { @@ -10500,45 +10625,45 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 10499 "ripper.c" /* yacc.c:1646 */ +#line 10624 "ripper.c" break; - case 562: -#line 4278 "ripper.y" /* yacc.c:1646 */ - { + case 561: +#line 4291 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON3((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(top_const_ref,v1);(yyval.val)=v2;} } -#line 10510 "ripper.c" /* yacc.c:1646 */ +#line 10635 "ripper.c" break; - case 563: -#line 4285 "ripper.y" /* yacc.c:1646 */ - { + case 562: +#line 4298 "ripper.y" + { #if 0 (yyval.val) = NEW_COLON2((yyvsp[-2].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(const_path_ref,v1,v2);(yyval.val)=v3;} } -#line 10521 "ripper.c" /* yacc.c:1646 */ +#line 10646 "ripper.c" break; - case 564: -#line 4292 "ripper.y" /* yacc.c:1646 */ - { + case 563: +#line 4305 "ripper.y" + { #if 0 (yyval.val) = gettable(p, (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 10532 "ripper.c" /* yacc.c:1646 */ +#line 10657 "ripper.c" break; - case 565: -#line 4303 "ripper.y" /* yacc.c:1646 */ - { + case 564: +#line 4316 "ripper.y" + { #if 0 (yyval.val) = NEW_RESBODY((yyvsp[-4].val), (yyvsp[-3].val) ? block_append(p, node_assign(p, (yyvsp[-3].val), NEW_ERRINFO(&(yylsp[-3])), &(yylsp[-3])), (yyvsp[-1].val)) : (yyvsp[-1].val), @@ -10547,53 +10672,53 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3,v4,v5;v1=escape_Qundef((yyvsp[-4].val));v2=escape_Qundef((yyvsp[-3].val));v3=escape_Qundef((yyvsp[-1].val));v4=escape_Qundef((yyvsp[0].val));v5=dispatch4(rescue,v1,v2,v3,v4);(yyval.val)=v5;} } -#line 10546 "ripper.c" /* yacc.c:1646 */ +#line 10671 "ripper.c" break; - case 567: -#line 4316 "ripper.y" /* yacc.c:1646 */ - { + case 566: +#line 4329 "ripper.y" + { #if 0 (yyval.val) = NEW_LIST((yyvsp[0].val), &(yyloc)); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 10557 "ripper.c" /* yacc.c:1646 */ +#line 10682 "ripper.c" break; - case 568: -#line 4323 "ripper.y" /* yacc.c:1646 */ - { + case 567: +#line 4336 "ripper.y" + { #if 0 if (!((yyval.val) = splat_array((yyvsp[0].val)))) (yyval.val) = (yyvsp[0].val); #endif (yyval.val)=(yyvsp[0].val); } -#line 10568 "ripper.c" /* yacc.c:1646 */ +#line 10693 "ripper.c" break; - case 570: -#line 4333 "ripper.y" /* yacc.c:1646 */ - { + case 569: +#line 4346 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 10576 "ripper.c" /* yacc.c:1646 */ +#line 10701 "ripper.c" break; - case 572: -#line 4340 "ripper.y" /* yacc.c:1646 */ - { + case 571: +#line 4353 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(ensure,v1);(yyval.val)=v2;} } -#line 10587 "ripper.c" /* yacc.c:1646 */ +#line 10712 "ripper.c" break; - case 576: -#line 4354 "ripper.y" /* yacc.c:1646 */ - { + case 575: +#line 4367 "ripper.y" + { #if 0 NODE *node = (yyvsp[0].val); if (!node) { @@ -10607,203 +10732,203 @@ YYLTYPE yylloc = yyloc_default; #endif (yyval.val)=(yyvsp[0].val); } -#line 10606 "ripper.c" /* yacc.c:1646 */ +#line 10731 "ripper.c" break; - case 579: -#line 4373 "ripper.y" /* yacc.c:1646 */ - { + case 578: +#line 4386 "ripper.y" + { #if 0 (yyval.val) = literal_concat(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(string_concat,v1,v2);(yyval.val)=v3;} } -#line 10617 "ripper.c" /* yacc.c:1646 */ +#line 10742 "ripper.c" break; - case 580: -#line 4382 "ripper.y" /* yacc.c:1646 */ - { + case 579: +#line 4395 "ripper.y" + { #if 0 (yyval.val) = heredoc_dedent(p, (yyvsp[-1].val)); if ((yyval.val)) nd_set_loc((yyval.val), &(yyloc)); #endif {VALUE v1,v2;v1=heredoc_dedent(p, (yyvsp[-1].val));v2=dispatch1(string_literal,v1);(yyval.val)=v2;} } -#line 10629 "ripper.c" /* yacc.c:1646 */ +#line 10754 "ripper.c" break; - case 581: -#line 4392 "ripper.y" /* yacc.c:1646 */ - { + case 580: +#line 4405 "ripper.y" + { #if 0 (yyval.val) = new_xstring(p, heredoc_dedent(p, (yyvsp[-1].val)), &(yyloc)); #endif {VALUE v1,v2;v1=heredoc_dedent(p, (yyvsp[-1].val));v2=dispatch1(xstring_literal,v1);(yyval.val)=v2;} } -#line 10640 "ripper.c" /* yacc.c:1646 */ +#line 10765 "ripper.c" break; - case 582: -#line 4401 "ripper.y" /* yacc.c:1646 */ - { + case 581: +#line 4414 "ripper.y" + { (yyval.val) = new_regexp(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 10648 "ripper.c" /* yacc.c:1646 */ +#line 10773 "ripper.c" break; - case 583: -#line 4407 "ripper.y" /* yacc.c:1646 */ - { + case 582: +#line 4420 "ripper.y" + { #if 0 (yyval.val) = make_list((yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(array,v1);(yyval.val)=v2;} } -#line 10659 "ripper.c" /* yacc.c:1646 */ +#line 10784 "ripper.c" break; - case 584: -#line 4416 "ripper.y" /* yacc.c:1646 */ - { + case 583: +#line 4429 "ripper.y" + { #if 0 (yyval.val) = 0; #endif {VALUE v1;v1=dispatch0(words_new);(yyval.val)=v1;} } -#line 10670 "ripper.c" /* yacc.c:1646 */ +#line 10795 "ripper.c" break; - case 585: -#line 4423 "ripper.y" /* yacc.c:1646 */ - { + case 584: +#line 4436 "ripper.y" + { #if 0 (yyval.val) = list_append(p, (yyvsp[-2].val), evstr2dstr(p, (yyvsp[-1].val))); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(words_add,v1,v2);(yyval.val)=v3;} } -#line 10681 "ripper.c" /* yacc.c:1646 */ +#line 10806 "ripper.c" break; - case 586: -#line 4432 "ripper.y" /* yacc.c:1646 */ - {{VALUE v1,v2,v3,v4;v1=dispatch0(word_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(word_add,v2,v3);(yyval.val)=v4;}} -#line 10687 "ripper.c" /* yacc.c:1646 */ + case 585: +#line 4445 "ripper.y" + {{VALUE v1,v2,v3,v4;v1=dispatch0(word_new);v2=v1;v3=(yyvsp[0].val);v4=dispatch2(word_add,v2,v3);(yyval.val)=v4;}} +#line 10812 "ripper.c" break; - case 587: -#line 4434 "ripper.y" /* yacc.c:1646 */ - { + case 586: +#line 4447 "ripper.y" + { #if 0 (yyval.val) = literal_concat(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(word_add,v1,v2);(yyval.val)=v3;} } -#line 10698 "ripper.c" /* yacc.c:1646 */ +#line 10823 "ripper.c" break; - case 588: -#line 4443 "ripper.y" /* yacc.c:1646 */ - { + case 587: +#line 4456 "ripper.y" + { #if 0 (yyval.val) = make_list((yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(array,v1);(yyval.val)=v2;} } -#line 10709 "ripper.c" /* yacc.c:1646 */ +#line 10834 "ripper.c" break; - case 589: -#line 4452 "ripper.y" /* yacc.c:1646 */ - { + case 588: +#line 4465 "ripper.y" + { #if 0 (yyval.val) = 0; #endif {VALUE v1;v1=dispatch0(symbols_new);(yyval.val)=v1;} } -#line 10720 "ripper.c" /* yacc.c:1646 */ +#line 10845 "ripper.c" break; - case 590: -#line 4459 "ripper.y" /* yacc.c:1646 */ - { + case 589: +#line 4472 "ripper.y" + { #if 0 (yyval.val) = symbol_append(p, (yyvsp[-2].val), evstr2dstr(p, (yyvsp[-1].val))); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(symbols_add,v1,v2);(yyval.val)=v3;} } -#line 10731 "ripper.c" /* yacc.c:1646 */ +#line 10856 "ripper.c" break; - case 591: -#line 4468 "ripper.y" /* yacc.c:1646 */ - { + case 590: +#line 4481 "ripper.y" + { #if 0 (yyval.val) = make_list((yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(array,v1);(yyval.val)=v2;} } -#line 10742 "ripper.c" /* yacc.c:1646 */ +#line 10867 "ripper.c" break; - case 592: -#line 4477 "ripper.y" /* yacc.c:1646 */ - { + case 591: +#line 4490 "ripper.y" + { #if 0 (yyval.val) = make_list((yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(array,v1);(yyval.val)=v2;} } -#line 10753 "ripper.c" /* yacc.c:1646 */ +#line 10878 "ripper.c" break; - case 593: -#line 4486 "ripper.y" /* yacc.c:1646 */ - { + case 592: +#line 4499 "ripper.y" + { #if 0 (yyval.val) = 0; #endif {VALUE v1;v1=dispatch0(qwords_new);(yyval.val)=v1;} } -#line 10764 "ripper.c" /* yacc.c:1646 */ +#line 10889 "ripper.c" break; - case 594: -#line 4493 "ripper.y" /* yacc.c:1646 */ - { + case 593: +#line 4506 "ripper.y" + { #if 0 (yyval.val) = list_append(p, (yyvsp[-2].val), (yyvsp[-1].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(qwords_add,v1,v2);(yyval.val)=v3;} } -#line 10775 "ripper.c" /* yacc.c:1646 */ +#line 10900 "ripper.c" break; - case 595: -#line 4502 "ripper.y" /* yacc.c:1646 */ - { + case 594: +#line 4515 "ripper.y" + { #if 0 (yyval.val) = 0; #endif {VALUE v1;v1=dispatch0(qsymbols_new);(yyval.val)=v1;} } -#line 10786 "ripper.c" /* yacc.c:1646 */ +#line 10911 "ripper.c" break; - case 596: -#line 4509 "ripper.y" /* yacc.c:1646 */ - { + case 595: +#line 4522 "ripper.y" + { #if 0 (yyval.val) = symbol_append(p, (yyvsp[-2].val), (yyvsp[-1].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[-1].val);v3=dispatch2(qsymbols_add,v1,v2);(yyval.val)=v3;} } -#line 10797 "ripper.c" /* yacc.c:1646 */ +#line 10922 "ripper.c" break; - case 597: -#line 4518 "ripper.y" /* yacc.c:1646 */ - { + case 596: +#line 4531 "ripper.y" + { #if 0 (yyval.val) = 0; #endif @@ -10813,12 +10938,12 @@ YYLTYPE yylloc = yyloc_default; (yyval.val) = ripper_new_yylval(p, 0, (yyval.val), 0); } -#line 10812 "ripper.c" /* yacc.c:1646 */ +#line 10937 "ripper.c" break; - case 598: -#line 4529 "ripper.y" /* yacc.c:1646 */ - { + case 597: +#line 4542 "ripper.y" + { #if 0 (yyval.val) = literal_concat(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif @@ -10833,34 +10958,34 @@ YYLTYPE yylloc = yyloc_default; } } -#line 10832 "ripper.c" /* yacc.c:1646 */ +#line 10957 "ripper.c" break; - case 599: -#line 4547 "ripper.y" /* yacc.c:1646 */ - { + case 598: +#line 4560 "ripper.y" + { #if 0 (yyval.val) = 0; #endif {VALUE v1;v1=dispatch0(xstring_new);(yyval.val)=v1;} } -#line 10843 "ripper.c" /* yacc.c:1646 */ +#line 10968 "ripper.c" break; - case 600: -#line 4554 "ripper.y" /* yacc.c:1646 */ - { + case 599: +#line 4567 "ripper.y" + { #if 0 (yyval.val) = literal_concat(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(xstring_add,v1,v2);(yyval.val)=v3;} } -#line 10854 "ripper.c" /* yacc.c:1646 */ +#line 10979 "ripper.c" break; - case 601: -#line 4563 "ripper.y" /* yacc.c:1646 */ - { + case 600: +#line 4576 "ripper.y" + { #if 0 (yyval.val) = 0; #endif @@ -10870,12 +10995,12 @@ YYLTYPE yylloc = yyloc_default; (yyval.val) = ripper_new_yylval(p, 0, (yyval.val), 0); } -#line 10869 "ripper.c" /* yacc.c:1646 */ +#line 10994 "ripper.c" break; - case 602: -#line 4574 "ripper.y" /* yacc.c:1646 */ - { + case 601: +#line 4587 "ripper.y" + { #if 0 NODE *head = (yyvsp[-1].val), *tail = (yyvsp[0].val); if (!head) { @@ -10913,29 +11038,29 @@ YYLTYPE yylloc = yyloc_default; } } -#line 10912 "ripper.c" /* yacc.c:1646 */ +#line 11037 "ripper.c" break; - case 603: -#line 4615 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=ripper_new_yylval(p, 0, get_value((yyvsp[0].val)), (yyvsp[0].val));} -#line 10918 "ripper.c" /* yacc.c:1646 */ + case 602: +#line 4628 "ripper.y" + {(yyval.val)=ripper_new_yylval(p, 0, get_value((yyvsp[0].val)), (yyvsp[0].val));} +#line 11043 "ripper.c" break; - case 604: -#line 4617 "ripper.y" /* yacc.c:1646 */ - { + case 603: +#line 4630 "ripper.y" + { /* need to backup p->lex.strterm so that a string literal `%&foo,#$&,bar&` can be parsed */ (yyval.strterm) = p->lex.strterm; p->lex.strterm = 0; SET_LEX_STATE(EXPR_BEG); } -#line 10929 "ripper.c" /* yacc.c:1646 */ +#line 11054 "ripper.c" break; - case 605: -#line 4624 "ripper.y" /* yacc.c:1646 */ - { + case 604: +#line 4637 "ripper.y" + { p->lex.strterm = (yyvsp[-1].strterm); #if 0 (yyval.val) = NEW_EVSTR((yyvsp[0].val), &(yyloc)); @@ -10943,58 +11068,58 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(string_dvar,v1);(yyval.val)=v2;} } -#line 10942 "ripper.c" /* yacc.c:1646 */ +#line 11067 "ripper.c" break; - case 606: -#line 4633 "ripper.y" /* yacc.c:1646 */ - { + case 605: +#line 4646 "ripper.y" + { CMDARG_PUSH(0); COND_PUSH(0); } -#line 10951 "ripper.c" /* yacc.c:1646 */ +#line 11076 "ripper.c" break; - case 607: -#line 4637 "ripper.y" /* yacc.c:1646 */ - { + case 606: +#line 4650 "ripper.y" + { /* need to backup p->lex.strterm so that a string literal `%!foo,#{ !0 },bar!` can be parsed */ (yyval.strterm) = p->lex.strterm; p->lex.strterm = 0; } -#line 10961 "ripper.c" /* yacc.c:1646 */ +#line 11086 "ripper.c" break; - case 608: -#line 4642 "ripper.y" /* yacc.c:1646 */ - { + case 607: +#line 4655 "ripper.y" + { (yyval.num) = p->lex.state; SET_LEX_STATE(EXPR_BEG); } -#line 10970 "ripper.c" /* yacc.c:1646 */ +#line 11095 "ripper.c" break; - case 609: -#line 4646 "ripper.y" /* yacc.c:1646 */ - { + case 608: +#line 4659 "ripper.y" + { (yyval.num) = p->lex.brace_nest; p->lex.brace_nest = 0; } -#line 10979 "ripper.c" /* yacc.c:1646 */ +#line 11104 "ripper.c" break; - case 610: -#line 4650 "ripper.y" /* yacc.c:1646 */ - { + case 609: +#line 4663 "ripper.y" + { (yyval.num) = p->heredoc_indent; p->heredoc_indent = 0; } -#line 10988 "ripper.c" /* yacc.c:1646 */ +#line 11113 "ripper.c" break; - case 611: -#line 4655 "ripper.y" /* yacc.c:1646 */ - { + case 610: +#line 4668 "ripper.y" + { COND_POP(); CMDARG_POP(); p->lex.strterm = (yyvsp[-5].strterm); @@ -11008,123 +11133,123 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(string_embexpr,v1);(yyval.val)=v2;} } -#line 11007 "ripper.c" /* yacc.c:1646 */ +#line 11132 "ripper.c" break; - case 612: -#line 4672 "ripper.y" /* yacc.c:1646 */ - { + case 611: +#line 4685 "ripper.y" + { #if 0 (yyval.val) = NEW_GVAR((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 11018 "ripper.c" /* yacc.c:1646 */ +#line 11143 "ripper.c" break; - case 613: -#line 4679 "ripper.y" /* yacc.c:1646 */ - { + case 612: +#line 4692 "ripper.y" + { #if 0 (yyval.val) = NEW_IVAR((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 11029 "ripper.c" /* yacc.c:1646 */ +#line 11154 "ripper.c" break; - case 614: -#line 4686 "ripper.y" /* yacc.c:1646 */ - { + case 613: +#line 4699 "ripper.y" + { #if 0 (yyval.val) = NEW_CVAR((yyvsp[0].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 11040 "ripper.c" /* yacc.c:1646 */ +#line 11165 "ripper.c" break; - case 618: -#line 4700 "ripper.y" /* yacc.c:1646 */ - { + case 617: +#line 4713 "ripper.y" + { SET_LEX_STATE(EXPR_END); #if 0 (yyval.val) = NEW_LIT(ID2SYM((yyvsp[0].val)), &(yyloc)); #endif {VALUE v1,v2,v3,v4;v1=(yyvsp[0].val);v2=dispatch1(symbol,v1);v3=v2;v4=dispatch1(symbol_literal,v3);(yyval.val)=v4;} } -#line 11052 "ripper.c" /* yacc.c:1646 */ +#line 11177 "ripper.c" break; - case 623: -#line 4716 "ripper.y" /* yacc.c:1646 */ - { + case 622: +#line 4729 "ripper.y" + { SET_LEX_STATE(EXPR_END); #if 0 (yyval.val) = dsym_node(p, (yyvsp[-1].val), &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(dyna_symbol,v1);(yyval.val)=v2;} } -#line 11064 "ripper.c" /* yacc.c:1646 */ +#line 11189 "ripper.c" break; - case 625: -#line 4727 "ripper.y" /* yacc.c:1646 */ - { + case 624: +#line 4740 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); RB_OBJ_WRITE(p->ast, &(yyval.val)->nd_lit, negate_lit(p, (yyval.val)->nd_lit)); #endif {VALUE v1,v2,v3;v1=ID2VAL(idUMinus);v2=(yyvsp[0].val);v3=dispatch2(unary,v1,v2);(yyval.val)=v3;} } -#line 11076 "ripper.c" /* yacc.c:1646 */ +#line 11201 "ripper.c" + break; + + case 634: +#line 4762 "ripper.y" + {(yyval.val) = KWD2EID(nil, (yyvsp[0].val));} +#line 11207 "ripper.c" break; case 635: -#line 4749 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(nil, (yyvsp[0].val));} -#line 11082 "ripper.c" /* yacc.c:1646 */ +#line 4763 "ripper.y" + {(yyval.val) = KWD2EID(self, (yyvsp[0].val));} +#line 11213 "ripper.c" break; case 636: -#line 4750 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(self, (yyvsp[0].val));} -#line 11088 "ripper.c" /* yacc.c:1646 */ +#line 4764 "ripper.y" + {(yyval.val) = KWD2EID(true, (yyvsp[0].val));} +#line 11219 "ripper.c" break; case 637: -#line 4751 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(true, (yyvsp[0].val));} -#line 11094 "ripper.c" /* yacc.c:1646 */ +#line 4765 "ripper.y" + {(yyval.val) = KWD2EID(false, (yyvsp[0].val));} +#line 11225 "ripper.c" break; case 638: -#line 4752 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(false, (yyvsp[0].val));} -#line 11100 "ripper.c" /* yacc.c:1646 */ +#line 4766 "ripper.y" + {(yyval.val) = KWD2EID(_FILE__, (yyvsp[0].val));} +#line 11231 "ripper.c" break; case 639: -#line 4753 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(_FILE__, (yyvsp[0].val));} -#line 11106 "ripper.c" /* yacc.c:1646 */ +#line 4767 "ripper.y" + {(yyval.val) = KWD2EID(_LINE__, (yyvsp[0].val));} +#line 11237 "ripper.c" break; case 640: -#line 4754 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(_LINE__, (yyvsp[0].val));} -#line 11112 "ripper.c" /* yacc.c:1646 */ +#line 4768 "ripper.y" + {(yyval.val) = KWD2EID(_ENCODING__, (yyvsp[0].val));} +#line 11243 "ripper.c" break; case 641: -#line 4755 "ripper.y" /* yacc.c:1646 */ - {(yyval.val) = KWD2EID(_ENCODING__, (yyvsp[0].val));} -#line 11118 "ripper.c" /* yacc.c:1646 */ - break; - - case 642: -#line 4759 "ripper.y" /* yacc.c:1646 */ - { +#line 4772 "ripper.y" + { #if 0 if (!((yyval.val) = gettable(p, (yyvsp[0].val), &(yyloc)))) (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif @@ -11136,73 +11261,73 @@ YYLTYPE yylloc = yyloc_default; } } -#line 11135 "ripper.c" /* yacc.c:1646 */ +#line 11260 "ripper.c" break; - case 643: -#line 4772 "ripper.y" /* yacc.c:1646 */ - { + case 642: +#line 4785 "ripper.y" + { #if 0 if (!((yyval.val) = gettable(p, (yyvsp[0].val), &(yyloc)))) (yyval.val) = NEW_BEGIN(0, &(yyloc)); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(var_ref,v1);(yyval.val)=v2;} } -#line 11146 "ripper.c" /* yacc.c:1646 */ +#line 11271 "ripper.c" break; - case 644: -#line 4781 "ripper.y" /* yacc.c:1646 */ - { + case 643: +#line 4794 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 11157 "ripper.c" /* yacc.c:1646 */ +#line 11282 "ripper.c" break; - case 645: -#line 4788 "ripper.y" /* yacc.c:1646 */ - { + case 644: +#line 4801 "ripper.y" + { #if 0 (yyval.val) = assignable(p, (yyvsp[0].val), 0, &(yyloc)); #endif (yyval.val)=assignable(p, var_field(p, (yyvsp[0].val))); } -#line 11168 "ripper.c" /* yacc.c:1646 */ +#line 11293 "ripper.c" break; - case 648: -#line 4801 "ripper.y" /* yacc.c:1646 */ - { + case 647: +#line 4814 "ripper.y" + { SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11177 "ripper.c" /* yacc.c:1646 */ +#line 11302 "ripper.c" break; - case 649: -#line 4806 "ripper.y" /* yacc.c:1646 */ - { + case 648: +#line 4819 "ripper.y" + { (yyval.val) = (yyvsp[-1].val); } -#line 11185 "ripper.c" /* yacc.c:1646 */ +#line 11310 "ripper.c" break; - case 650: -#line 4810 "ripper.y" /* yacc.c:1646 */ - { + case 649: +#line 4823 "ripper.y" + { #if 0 (yyval.val) = 0; #endif (yyval.val)=Qnil; } -#line 11196 "ripper.c" /* yacc.c:1646 */ +#line 11321 "ripper.c" break; - case 651: -#line 4819 "ripper.y" /* yacc.c:1646 */ - { + case 650: +#line 4832 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif @@ -11210,12 +11335,12 @@ YYLTYPE yylloc = yyloc_default; SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11209 "ripper.c" /* yacc.c:1646 */ +#line 11334 "ripper.c" break; - case 652: -#line 4828 "ripper.y" /* yacc.c:1646 */ - { + case 651: +#line 4841 "ripper.y" + { arg_var(p, idFWD_REST); #if idFWD_KWREST arg_var(p, idFWD_KWREST); @@ -11229,302 +11354,302 @@ YYLTYPE yylloc = yyloc_default; SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11228 "ripper.c" /* yacc.c:1646 */ +#line 11353 "ripper.c" break; - case 653: -#line 4842 "ripper.y" /* yacc.c:1646 */ - { + case 652: +#line 4855 "ripper.y" + { (yyval.num) = p->in_kwarg; p->in_kwarg = 1; SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */ } -#line 11238 "ripper.c" /* yacc.c:1646 */ +#line 11363 "ripper.c" break; - case 654: -#line 4848 "ripper.y" /* yacc.c:1646 */ - { + case 653: +#line 4861 "ripper.y" + { p->in_kwarg = !!(yyvsp[-2].num); (yyval.val) = (yyvsp[-1].val); SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11249 "ripper.c" /* yacc.c:1646 */ +#line 11374 "ripper.c" break; - case 655: -#line 4857 "ripper.y" /* yacc.c:1646 */ - { + case 654: +#line 4870 "ripper.y" + { (yyval.val) = new_args_tail(p, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1])); } -#line 11257 "ripper.c" /* yacc.c:1646 */ +#line 11382 "ripper.c" break; - case 656: -#line 4861 "ripper.y" /* yacc.c:1646 */ - { + case 655: +#line 4874 "ripper.y" + { (yyval.val) = new_args_tail(p, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yylsp[-1])); } -#line 11265 "ripper.c" /* yacc.c:1646 */ +#line 11390 "ripper.c" break; - case 657: -#line 4865 "ripper.y" /* yacc.c:1646 */ - { + case 656: +#line 4878 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yylsp[-1])); } -#line 11273 "ripper.c" /* yacc.c:1646 */ +#line 11398 "ripper.c" break; - case 658: -#line 4869 "ripper.y" /* yacc.c:1646 */ - { + case 657: +#line 4882 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, ID2VAL(idNil), (yyvsp[0].val), &(yylsp[-1])); } -#line 11281 "ripper.c" /* yacc.c:1646 */ +#line 11406 "ripper.c" break; - case 659: -#line 4873 "ripper.y" /* yacc.c:1646 */ - { + case 658: +#line 4886 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, Qnone, (yyvsp[0].val), &(yylsp[0])); } -#line 11289 "ripper.c" /* yacc.c:1646 */ +#line 11414 "ripper.c" break; - case 660: -#line 4879 "ripper.y" /* yacc.c:1646 */ - { + case 659: +#line 4892 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 11297 "ripper.c" /* yacc.c:1646 */ +#line 11422 "ripper.c" break; - case 661: -#line 4883 "ripper.y" /* yacc.c:1646 */ - { + case 660: +#line 4896 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); } -#line 11305 "ripper.c" /* yacc.c:1646 */ +#line 11430 "ripper.c" break; - case 662: -#line 4889 "ripper.y" /* yacc.c:1646 */ - { + case 661: +#line 4902 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11313 "ripper.c" /* yacc.c:1646 */ +#line 11438 "ripper.c" break; - case 663: -#line 4893 "ripper.y" /* yacc.c:1646 */ - { + case 662: +#line 4906 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-7].val), (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11321 "ripper.c" /* yacc.c:1646 */ +#line 11446 "ripper.c" break; - case 664: -#line 4897 "ripper.y" /* yacc.c:1646 */ - { + case 663: +#line 4910 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-3].val), (yyvsp[-1].val), Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11329 "ripper.c" /* yacc.c:1646 */ +#line 11454 "ripper.c" break; - case 665: -#line 4901 "ripper.y" /* yacc.c:1646 */ - { + case 664: +#line 4914 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), (yyvsp[-3].val), Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11337 "ripper.c" /* yacc.c:1646 */ +#line 11462 "ripper.c" break; - case 666: -#line 4905 "ripper.y" /* yacc.c:1646 */ - { + case 665: +#line 4918 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11345 "ripper.c" /* yacc.c:1646 */ +#line 11470 "ripper.c" break; - case 667: -#line 4909 "ripper.y" /* yacc.c:1646 */ - { + case 666: +#line 4922 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-5].val), Qnone, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11353 "ripper.c" /* yacc.c:1646 */ +#line 11478 "ripper.c" break; - case 668: -#line 4913 "ripper.y" /* yacc.c:1646 */ - { + case 667: +#line 4926 "ripper.y" + { (yyval.val) = new_args(p, (yyvsp[-1].val), Qnone, Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11361 "ripper.c" /* yacc.c:1646 */ +#line 11486 "ripper.c" break; - case 669: -#line 4917 "ripper.y" /* yacc.c:1646 */ - { + case 668: +#line 4930 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-3].val), (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11369 "ripper.c" /* yacc.c:1646 */ +#line 11494 "ripper.c" break; - case 670: -#line 4921 "ripper.y" /* yacc.c:1646 */ - { + case 669: +#line 4934 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-5].val), (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11377 "ripper.c" /* yacc.c:1646 */ +#line 11502 "ripper.c" break; - case 671: -#line 4925 "ripper.y" /* yacc.c:1646 */ - { + case 670: +#line 4938 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-1].val), Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11385 "ripper.c" /* yacc.c:1646 */ +#line 11510 "ripper.c" break; - case 672: -#line 4929 "ripper.y" /* yacc.c:1646 */ - { + case 671: +#line 4942 "ripper.y" + { (yyval.val) = new_args(p, Qnone, (yyvsp[-3].val), Qnone, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11393 "ripper.c" /* yacc.c:1646 */ +#line 11518 "ripper.c" break; - case 673: -#line 4933 "ripper.y" /* yacc.c:1646 */ - { + case 672: +#line 4946 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, (yyvsp[-1].val), Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11401 "ripper.c" /* yacc.c:1646 */ +#line 11526 "ripper.c" break; - case 674: -#line 4937 "ripper.y" /* yacc.c:1646 */ - { + case 673: +#line 4950 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, (yyvsp[-3].val), (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)); } -#line 11409 "ripper.c" /* yacc.c:1646 */ +#line 11534 "ripper.c" break; - case 675: -#line 4941 "ripper.y" /* yacc.c:1646 */ - { + case 674: +#line 4954 "ripper.y" + { (yyval.val) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyvsp[0].val), &(yyloc)); } -#line 11417 "ripper.c" /* yacc.c:1646 */ +#line 11542 "ripper.c" break; - case 676: -#line 4945 "ripper.y" /* yacc.c:1646 */ - { + case 675: +#line 4958 "ripper.y" + { (yyval.val) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); (yyval.val) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyval.val), &(yylsp[0])); } -#line 11426 "ripper.c" /* yacc.c:1646 */ +#line 11551 "ripper.c" break; - case 677: -#line 4952 "ripper.y" /* yacc.c:1646 */ - { + case 676: +#line 4965 "ripper.y" + { #if 0 (yyval.val) = idDot3; #endif {VALUE v1;v1=dispatch0(args_forward);(yyval.val)=v1;} } -#line 11437 "ripper.c" /* yacc.c:1646 */ +#line 11562 "ripper.c" break; - case 678: -#line 4961 "ripper.y" /* yacc.c:1646 */ - { + case 677: +#line 4974 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "formal argument cannot be a constant"); (yyval.val) = 0; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(param_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 11449 "ripper.c" /* yacc.c:1646 */ +#line 11574 "ripper.c" break; - case 679: -#line 4969 "ripper.y" /* yacc.c:1646 */ - { + case 678: +#line 4982 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "formal argument cannot be an instance variable"); (yyval.val) = 0; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(param_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 11461 "ripper.c" /* yacc.c:1646 */ +#line 11586 "ripper.c" break; - case 680: -#line 4977 "ripper.y" /* yacc.c:1646 */ - { + case 679: +#line 4990 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "formal argument cannot be a global variable"); (yyval.val) = 0; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(param_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 11473 "ripper.c" /* yacc.c:1646 */ +#line 11598 "ripper.c" break; - case 681: -#line 4985 "ripper.y" /* yacc.c:1646 */ - { + case 680: +#line 4998 "ripper.y" + { #if 0 yyerror1(&(yylsp[0]), "formal argument cannot be a class variable"); (yyval.val) = 0; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(param_error,v1);(yyval.val)=v2;}ripper_error(p); } -#line 11485 "ripper.c" /* yacc.c:1646 */ +#line 11610 "ripper.c" break; - case 683: -#line 4996 "ripper.y" /* yacc.c:1646 */ - { + case 682: +#line 5009 "ripper.y" + { formal_argument(p, get_id((yyvsp[0].val))); p->max_numparam = ORDINAL_PARAM; (yyval.val) = (yyvsp[0].val); } -#line 11495 "ripper.c" /* yacc.c:1646 */ +#line 11620 "ripper.c" break; - case 684: -#line 5004 "ripper.y" /* yacc.c:1646 */ - { + case 683: +#line 5017 "ripper.y" + { ID id = get_id((yyvsp[0].val)); arg_var(p, id); p->cur_arg = id; (yyval.val) = (yyvsp[0].val); } -#line 11506 "ripper.c" /* yacc.c:1646 */ +#line 11631 "ripper.c" break; - case 685: -#line 5013 "ripper.y" /* yacc.c:1646 */ - { + case 684: +#line 5026 "ripper.y" + { p->cur_arg = 0; #if 0 (yyval.val) = NEW_ARGS_AUX((yyvsp[0].val), 1, &NULL_LOC); #endif (yyval.val)=get_value((yyvsp[0].val)); } -#line 11518 "ripper.c" /* yacc.c:1646 */ +#line 11643 "ripper.c" break; - case 686: -#line 5021 "ripper.y" /* yacc.c:1646 */ - { + case 685: +#line 5034 "ripper.y" + { #if 0 ID tid = internal_id(p); YYLTYPE loc; @@ -11542,18 +11667,18 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(mlhs_paren,v1);(yyval.val)=v2;} } -#line 11541 "ripper.c" /* yacc.c:1646 */ +#line 11666 "ripper.c" break; - case 687: -#line 5042 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} -#line 11547 "ripper.c" /* yacc.c:1646 */ + case 686: +#line 5055 "ripper.y" + {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} +#line 11672 "ripper.c" break; - case 688: -#line 5044 "ripper.y" /* yacc.c:1646 */ - { + case 687: +#line 5057 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-2].val); (yyval.val)->nd_plen++; @@ -11562,283 +11687,283 @@ YYLTYPE yylloc = yyloc_default; #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11561 "ripper.c" /* yacc.c:1646 */ +#line 11686 "ripper.c" break; - case 689: -#line 5057 "ripper.y" /* yacc.c:1646 */ - { + case 688: +#line 5070 "ripper.y" + { ID id = get_id((yyvsp[0].val)); arg_var(p, formal_argument(p, id)); p->cur_arg = id; p->max_numparam = ORDINAL_PARAM; (yyval.val) = (yyvsp[0].val); } -#line 11573 "ripper.c" /* yacc.c:1646 */ +#line 11698 "ripper.c" break; - case 690: -#line 5067 "ripper.y" /* yacc.c:1646 */ - { + case 689: +#line 5080 "ripper.y" + { p->cur_arg = 0; #if 0 (yyval.val) = new_kw_arg(p, assignable(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[-1].val))), get_value((yyvsp[0].val))); } -#line 11585 "ripper.c" /* yacc.c:1646 */ +#line 11710 "ripper.c" break; - case 691: -#line 5075 "ripper.y" /* yacc.c:1646 */ - { + case 690: +#line 5088 "ripper.y" + { p->cur_arg = 0; #if 0 (yyval.val) = new_kw_arg(p, assignable(p, (yyvsp[0].val), NODE_SPECIAL_REQUIRED_KEYWORD, &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[0].val))), 0); } -#line 11597 "ripper.c" /* yacc.c:1646 */ +#line 11722 "ripper.c" break; - case 692: -#line 5085 "ripper.y" /* yacc.c:1646 */ - { + case 691: +#line 5098 "ripper.y" + { #if 0 (yyval.val) = new_kw_arg(p, assignable(p, (yyvsp[-1].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[-1].val))), get_value((yyvsp[0].val))); } -#line 11608 "ripper.c" /* yacc.c:1646 */ +#line 11733 "ripper.c" break; - case 693: -#line 5092 "ripper.y" /* yacc.c:1646 */ - { + case 692: +#line 5105 "ripper.y" + { #if 0 (yyval.val) = new_kw_arg(p, assignable(p, (yyvsp[0].val), NODE_SPECIAL_REQUIRED_KEYWORD, &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[0].val))), 0); } -#line 11619 "ripper.c" /* yacc.c:1646 */ +#line 11744 "ripper.c" break; - case 694: -#line 5101 "ripper.y" /* yacc.c:1646 */ - { + case 693: +#line 5114 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 11630 "ripper.c" /* yacc.c:1646 */ +#line 11755 "ripper.c" break; - case 695: -#line 5108 "ripper.y" /* yacc.c:1646 */ - { + case 694: +#line 5121 "ripper.y" + { #if 0 (yyval.val) = kwd_append((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11641 "ripper.c" /* yacc.c:1646 */ +#line 11766 "ripper.c" break; - case 696: -#line 5118 "ripper.y" /* yacc.c:1646 */ - { + case 695: +#line 5131 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 11652 "ripper.c" /* yacc.c:1646 */ +#line 11777 "ripper.c" break; - case 697: -#line 5125 "ripper.y" /* yacc.c:1646 */ - { + case 696: +#line 5138 "ripper.y" + { #if 0 (yyval.val) = kwd_append((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11663 "ripper.c" /* yacc.c:1646 */ +#line 11788 "ripper.c" break; - case 700: -#line 5138 "ripper.y" /* yacc.c:1646 */ - { + case 699: +#line 5151 "ripper.y" + { #if 0 #endif {VALUE v1,v2;v1=Qnil;v2=dispatch1(nokw_param,v1);(yyval.val)=v2;} } -#line 11673 "ripper.c" /* yacc.c:1646 */ +#line 11798 "ripper.c" break; - case 701: -#line 5146 "ripper.y" /* yacc.c:1646 */ - { + case 700: +#line 5159 "ripper.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].val)))); #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(kwrest_param,v1);(yyval.val)=v2;} } -#line 11685 "ripper.c" /* yacc.c:1646 */ +#line 11810 "ripper.c" break; - case 702: -#line 5154 "ripper.y" /* yacc.c:1646 */ - { + case 701: +#line 5167 "ripper.y" + { #if 0 (yyval.val) = internal_id(p); arg_var(p, (yyval.val)); #endif {VALUE v1,v2;v1=Qnil;v2=dispatch1(kwrest_param,v1);(yyval.val)=v2;} } -#line 11697 "ripper.c" /* yacc.c:1646 */ +#line 11822 "ripper.c" break; - case 703: -#line 5164 "ripper.y" /* yacc.c:1646 */ - { + case 702: +#line 5177 "ripper.y" + { p->cur_arg = 0; #if 0 (yyval.val) = NEW_OPT_ARG(0, assignable(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[-2].val))), get_value((yyvsp[0].val))); } -#line 11709 "ripper.c" /* yacc.c:1646 */ +#line 11834 "ripper.c" break; - case 704: -#line 5174 "ripper.y" /* yacc.c:1646 */ - { + case 703: +#line 5187 "ripper.y" + { p->cur_arg = 0; #if 0 (yyval.val) = NEW_OPT_ARG(0, assignable(p, (yyvsp[-2].val), (yyvsp[0].val), &(yyloc)), &(yyloc)); #endif (yyval.val)=rb_assoc_new(get_value(assignable(p, (yyvsp[-2].val))), get_value((yyvsp[0].val))); } -#line 11721 "ripper.c" /* yacc.c:1646 */ +#line 11846 "ripper.c" break; - case 705: -#line 5184 "ripper.y" /* yacc.c:1646 */ - { + case 704: +#line 5197 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 11732 "ripper.c" /* yacc.c:1646 */ +#line 11857 "ripper.c" break; - case 706: -#line 5191 "ripper.y" /* yacc.c:1646 */ - { + case 705: +#line 5204 "ripper.y" + { #if 0 (yyval.val) = opt_arg_append((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11743 "ripper.c" /* yacc.c:1646 */ +#line 11868 "ripper.c" break; - case 707: -#line 5200 "ripper.y" /* yacc.c:1646 */ - { + case 706: +#line 5213 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[0].val); #endif (yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val))); } -#line 11754 "ripper.c" /* yacc.c:1646 */ +#line 11879 "ripper.c" break; - case 708: -#line 5207 "ripper.y" /* yacc.c:1646 */ - { + case 707: +#line 5220 "ripper.y" + { #if 0 (yyval.val) = opt_arg_append((yyvsp[-2].val), (yyvsp[0].val)); #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11765 "ripper.c" /* yacc.c:1646 */ +#line 11890 "ripper.c" break; - case 711: -#line 5220 "ripper.y" /* yacc.c:1646 */ - { + case 710: +#line 5233 "ripper.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].val)))); #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(rest_param,v1);(yyval.val)=v2;} } -#line 11777 "ripper.c" /* yacc.c:1646 */ +#line 11902 "ripper.c" break; - case 712: -#line 5228 "ripper.y" /* yacc.c:1646 */ - { + case 711: +#line 5241 "ripper.y" + { #if 0 (yyval.val) = internal_id(p); arg_var(p, (yyval.val)); #endif {VALUE v1,v2;v1=Qnil;v2=dispatch1(rest_param,v1);(yyval.val)=v2;} } -#line 11789 "ripper.c" /* yacc.c:1646 */ +#line 11914 "ripper.c" break; - case 715: -#line 5242 "ripper.y" /* yacc.c:1646 */ - { + case 714: +#line 5255 "ripper.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].val)))); #if 0 (yyval.val) = (yyvsp[0].val); #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(blockarg,v1);(yyval.val)=v2;} } -#line 11801 "ripper.c" /* yacc.c:1646 */ +#line 11926 "ripper.c" break; - case 716: -#line 5252 "ripper.y" /* yacc.c:1646 */ - { + case 715: +#line 5265 "ripper.y" + { (yyval.val) = (yyvsp[0].val); } -#line 11809 "ripper.c" /* yacc.c:1646 */ +#line 11934 "ripper.c" break; - case 717: -#line 5256 "ripper.y" /* yacc.c:1646 */ - { + case 716: +#line 5269 "ripper.y" + { (yyval.val) = Qnull; } -#line 11817 "ripper.c" /* yacc.c:1646 */ +#line 11942 "ripper.c" break; - case 718: -#line 5262 "ripper.y" /* yacc.c:1646 */ - { + case 717: +#line 5275 "ripper.y" + { value_expr((yyvsp[0].val)); (yyval.val) = (yyvsp[0].val); } -#line 11826 "ripper.c" /* yacc.c:1646 */ +#line 11951 "ripper.c" break; - case 719: -#line 5266 "ripper.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_BEG);} -#line 11832 "ripper.c" /* yacc.c:1646 */ + case 718: +#line 5279 "ripper.y" + {SET_LEX_STATE(EXPR_BEG);} +#line 11957 "ripper.c" break; - case 720: -#line 5267 "ripper.y" /* yacc.c:1646 */ - { + case 719: +#line 5280 "ripper.y" + { #if 0 switch (nd_type((yyvsp[-1].val))) { case NODE_STR: @@ -11859,29 +11984,29 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(paren,v1);(yyval.val)=v2;} } -#line 11858 "ripper.c" /* yacc.c:1646 */ +#line 11983 "ripper.c" break; - case 722: -#line 5292 "ripper.y" /* yacc.c:1646 */ - { + case 721: +#line 5305 "ripper.y" + { #if 0 (yyval.val) = (yyvsp[-1].val); #endif {VALUE v1,v2;v1=(yyvsp[-1].val);v2=dispatch1(assoclist_from_args,v1);(yyval.val)=v2;} } -#line 11869 "ripper.c" /* yacc.c:1646 */ +#line 11994 "ripper.c" break; - case 723: -#line 5301 "ripper.y" /* yacc.c:1646 */ - {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} -#line 11875 "ripper.c" /* yacc.c:1646 */ + case 722: +#line 5314 "ripper.y" + {(yyval.val)=rb_ary_new3(1, get_value((yyvsp[0].val)));} +#line 12000 "ripper.c" break; - case 724: -#line 5303 "ripper.y" /* yacc.c:1646 */ - { + case 723: +#line 5316 "ripper.y" + { #if 0 NODE *assocs = (yyvsp[-2].val); NODE *tail = (yyvsp[0].val); @@ -11901,12 +12026,12 @@ YYLTYPE yylloc = yyloc_default; #endif (yyval.val)=rb_ary_push((yyvsp[-2].val), get_value((yyvsp[0].val))); } -#line 11900 "ripper.c" /* yacc.c:1646 */ +#line 12025 "ripper.c" break; - case 725: -#line 5326 "ripper.y" /* yacc.c:1646 */ - { + case 724: +#line 5339 "ripper.y" + { #if 0 if (nd_type((yyvsp[-2].val)) == NODE_STR) { nd_set_type((yyvsp[-2].val), NODE_LIT); @@ -11916,35 +12041,35 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2,v3;v1=(yyvsp[-2].val);v2=(yyvsp[0].val);v3=dispatch2(assoc_new,v1,v2);(yyval.val)=v3;} } -#line 11915 "ripper.c" /* yacc.c:1646 */ +#line 12040 "ripper.c" break; - case 726: -#line 5337 "ripper.y" /* yacc.c:1646 */ - { + case 725: +#line 5350 "ripper.y" + { #if 0 (yyval.val) = list_append(p, NEW_LIST(NEW_LIT(ID2SYM((yyvsp[-1].val)), &(yylsp[-1])), &(yyloc)), (yyvsp[0].val)); #endif {VALUE v1,v2,v3;v1=(yyvsp[-1].val);v2=(yyvsp[0].val);v3=dispatch2(assoc_new,v1,v2);(yyval.val)=v3;} } -#line 11926 "ripper.c" /* yacc.c:1646 */ +#line 12051 "ripper.c" break; - case 727: -#line 5344 "ripper.y" /* yacc.c:1646 */ - { + case 726: +#line 5357 "ripper.y" + { #if 0 YYLTYPE loc = code_loc_gen(&(yylsp[-3]), &(yylsp[-1])); (yyval.val) = list_append(p, NEW_LIST(dsym_node(p, (yyvsp[-2].val), &loc), &loc), (yyvsp[0].val)); #endif {VALUE v1,v2,v3,v4,v5;v1=(yyvsp[-2].val);v2=dispatch1(dyna_symbol,v1);v3=v2;v4=(yyvsp[0].val);v5=dispatch2(assoc_new,v3,v4);(yyval.val)=v5;} } -#line 11938 "ripper.c" /* yacc.c:1646 */ +#line 12063 "ripper.c" break; - case 728: -#line 5352 "ripper.y" /* yacc.c:1646 */ - { + case 727: +#line 5365 "ripper.y" + { #if 0 if (nd_type((yyvsp[0].val)) == NODE_HASH && !((yyvsp[0].val)->nd_head && (yyvsp[0].val)->nd_head->nd_alen)) { @@ -11960,37 +12085,38 @@ YYLTYPE yylloc = yyloc_default; #endif {VALUE v1,v2;v1=(yyvsp[0].val);v2=dispatch1(assoc_splat,v1);(yyval.val)=v2;} } -#line 11959 "ripper.c" /* yacc.c:1646 */ +#line 12084 "ripper.c" break; - case 755: -#line 5420 "ripper.y" /* yacc.c:1646 */ - {yyerrok;token_flush(p);} -#line 11965 "ripper.c" /* yacc.c:1646 */ + case 753: +#line 5430 "ripper.y" + {yyerrok;token_flush(p);} +#line 12090 "ripper.c" break; - case 756: -#line 5421 "ripper.y" /* yacc.c:1646 */ - {token_flush(p);} -#line 11971 "ripper.c" /* yacc.c:1646 */ + case 754: +#line 5431 "ripper.y" + {token_flush(p);} +#line 12096 "ripper.c" break; - case 758: -#line 5425 "ripper.y" /* yacc.c:1646 */ - {yyerrok;} -#line 11977 "ripper.c" /* yacc.c:1646 */ + case 756: +#line 5435 "ripper.y" + {yyerrok;} +#line 12102 "ripper.c" break; - case 759: -#line 5429 "ripper.y" /* yacc.c:1646 */ - { + case 757: +#line 5439 "ripper.y" + { (yyval.val) = Qnull; } -#line 11985 "ripper.c" /* yacc.c:1646 */ +#line 12110 "ripper.c" break; -#line 11989 "ripper.c" /* yacc.c:1646 */ +#line 12114 "ripper.c" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -12016,14 +12142,13 @@ YYLTYPE yylloc = yyloc_default; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -12055,7 +12180,7 @@ YYLTYPE yylloc = yyloc_default; { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + yymsg = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); if (!yymsg) { yymsg = yymsgbuf; @@ -12106,14 +12231,11 @@ YYLTYPE yylloc = yyloc_default; | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -12179,6 +12301,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -12186,6 +12309,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -12196,6 +12320,10 @@ YYLTYPE yylloc = yyloc_default; /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -12225,7 +12353,7 @@ YYLTYPE yylloc = yyloc_default; #endif return yyresult; } -#line 5433 "ripper.y" /* yacc.c:1906 */ +#line 5443 "ripper.y" # undef p # undef yylex @@ -12335,9 +12463,6 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t) #define has_delayed_token(p) (!NIL_P(p->delayed.token)) #endif /* RIPPER */ -#include "ruby/regex.h" -#include "ruby/util.h" - static inline int is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc) { @@ -12643,7 +12768,7 @@ vtable_free_gen(struct parser_params *p, int line, const char *name, if (tbl->tbl) { ruby_sized_xfree(tbl->tbl, tbl->capa * sizeof(ID)); } - ruby_sized_xfree(tbl, sizeof(tbl)); + ruby_sized_xfree(tbl, sizeof(*tbl)); } } #define vtable_free(tbl) vtable_free_gen(p, __LINE__, #tbl, tbl) @@ -16705,19 +16830,6 @@ past_dvar_p(struct parser_params *p, ID id) } # endif -/* As Ripper#warn does not have arguments for the location, so the - * following messages cannot be separated */ -#define WARN_LOCATION(type) do { \ - if (p->warn_location) { \ - int line; \ - VALUE file = rb_source_location(&line); \ - rb_warn3(type" in eval may not return location in binding;" \ - " use Binding#source_location instead\n" \ - "%"PRIsWARN":%d: warning: in `%"PRIsWARN"'", \ - file, WARN_I(line), rb_id2str(rb_frame_this_func())); \ - } \ -} while (0) - static int numparam_nested_p(struct parser_params *p) { @@ -16751,7 +16863,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case keyword_false: return NEW_FALSE(loc); case keyword__FILE__: - WARN_LOCATION("__FILE__"); { VALUE file = p->ruby_sourcefile_string; if (NIL_P(file)) @@ -16763,7 +16874,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) } return node; case keyword__LINE__: - WARN_LOCATION("__LINE__"); return NEW_LIT(INT2FIX(p->tokline), loc); case keyword__ENCODING__: node = NEW_LIT(rb_enc_from_encoding(p->enc), loc); @@ -18044,7 +18154,7 @@ negate_lit(struct parser_params *p, VALUE lit) lit = rb_big_norm(lit); break; case T_RATIONAL: - RRATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); + RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); break; case T_COMPLEX: RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real)); @@ -18845,7 +18955,7 @@ dvar_defined_ref(struct parser_params *p, ID id, ID **vidrefp) if (used) used = used->prev; } - if (vars == DVARS_INHERIT) { + if (vars == DVARS_INHERIT && !NUMPARAM_ID_P(id)) { return rb_dvar_defined(id, p->parent_iseq); } @@ -19040,14 +19150,6 @@ rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split) p->do_split = split; } -void -rb_parser_warn_location(VALUE vparser, int warn) -{ - struct parser_params *p; - TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - p->warn_location = warn; -} - static NODE * parser_append_options(struct parser_params *p, NODE *node) { diff --git a/ruby/ext/ripper/ripper.y b/ruby/ext/ripper/ripper.y index 7e1d1feac..5d98d45a5 100644 --- a/ruby/ext/ripper/ripper.y +++ b/ruby/ext/ripper/ripper.y @@ -20,18 +20,37 @@ #define YYLTYPE rb_code_location_t #define YYLTYPE_IS_DECLARED 1 -#include "ruby/ruby.h" -#include "ruby/st.h" -#include "ruby/encoding.h" +#include "ruby/config.h" + +#include +#include +#include + #include "internal.h" +#include "internal/compile.h" +#include "internal/complex.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/parse.h" +#include "internal/rational.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/util.h" +#include "internal/variable.h" #include "node.h" #include "parse.h" -#include "symbol.h" -#include "regenc.h" -#include -#include -#include #include "probes.h" +#include "regenc.h" +#include "ruby/encoding.h" +#include "ruby/regex.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "symbol.h" #ifndef WARN_PAST_SCOPE # define WARN_PAST_SCOPE 0 @@ -296,7 +315,6 @@ struct parser_params { unsigned int do_loop: 1; unsigned int do_chomp: 1; unsigned int do_split: 1; - unsigned int warn_location: 1; NODE *eval_tree_begin; NODE *eval_tree; @@ -1461,6 +1479,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem command_asgn : lhs '=' command_rhs { #if 0 + value_expr($3); $$ = node_assign(p, $1, $3, &@$); #endif {VALUE v1,v2,v3;v1=$1;v2=$3;v3=dispatch2(assign,v1,v2);$$=v3;} @@ -1468,6 +1487,7 @@ command_asgn : lhs '=' command_rhs | var_lhs tOP_ASGN command_rhs { #if 0 + value_expr($3); $$ = new_op_assign(p, $1, $2, $3, &@$); #endif {VALUE v1,v2,v3,v4;v1=$1;v2=$2;v3=$3;v4=dispatch3(opassign,v1,v2,v3);$$=v4;} @@ -1475,6 +1495,7 @@ command_asgn : lhs '=' command_rhs | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs { #if 0 + value_expr($6); $$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$); #endif {VALUE v1,v2,v3,v4,v5,v6,v7;v1=$1;v2=escape_Qundef($3);v3=dispatch2(aref_field,v1,v2);v4=v3;v5=$5;v6=$6;v7=dispatch3(opassign,v4,v5,v6);$$=v7;} @@ -1483,6 +1504,7 @@ command_asgn : lhs '=' command_rhs | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs { #if 0 + value_expr($5); $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=$1;v2=$2;v3=$3;v4=dispatch3(field,v1,v2,v3);v5=v4;v6=$4;v7=$5;v8=dispatch3(opassign,v5,v6,v7);$$=v8;} @@ -1490,6 +1512,7 @@ command_asgn : lhs '=' command_rhs | primary_value call_op tCONSTANT tOP_ASGN command_rhs { #if 0 + value_expr($5); $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=$1;v2=$2;v3=$3;v4=dispatch3(field,v1,v2,v3);v5=v4;v6=$4;v7=$5;v8=dispatch3(opassign,v5,v6,v7);$$=v8;} @@ -1505,6 +1528,7 @@ command_asgn : lhs '=' command_rhs | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs { #if 0 + value_expr($5); $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$); #endif {VALUE v1,v2,v3,v4,v5,v6,v7,v8;v1=$1;v2=ID2VAL(idCOLON2);v3=$3;v4=dispatch3(field,v1,v2,v3);v5=v4;v6=$4;v7=$5;v8=dispatch3(opassign,v5,v6,v7);$$=v8;} @@ -3937,19 +3961,12 @@ p_expr_basic : p_value $$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$); $$ = new_array_pattern(p, Qnone, Qnone, $$, &@$); } - | tLBRACE - { - $$ = push_pktbl(p); - $1 = p->in_kwarg; - p->in_kwarg = 0; - } - p_kwargs rbrace + | tLBRACE {$$ = push_pktbl(p);} p_kwargs '}' { pop_pktbl(p, $2); - p->in_kwarg = $1; $$ = new_hash_pattern(p, Qnone, $3, &@$); } - | tLBRACE rbrace + | tLBRACE '}' { $$ = new_hash_pattern_tail(p, Qnone, 0, &@$); $$ = new_hash_pattern(p, Qnone, $$, &@$); @@ -4060,10 +4077,6 @@ p_kwargs : p_kwarg ',' p_kwrest { $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), 0, &@$); } - | p_kwarg ',' - { - $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), 0, &@$); - } | p_kwrest { $$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), $1, &@$); @@ -5409,9 +5422,6 @@ rparen : opt_nl ')' rbracket : opt_nl ']' ; -rbrace : opt_nl '}' - ; - trailer : /* none */ | '\n' | ',' @@ -5539,9 +5549,6 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t) #define has_delayed_token(p) (!NIL_P(p->delayed.token)) #endif /* RIPPER */ -#include "ruby/regex.h" -#include "ruby/util.h" - static inline int is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc) { @@ -5847,7 +5854,7 @@ vtable_free_gen(struct parser_params *p, int line, const char *name, if (tbl->tbl) { ruby_sized_xfree(tbl->tbl, tbl->capa * sizeof(ID)); } - ruby_sized_xfree(tbl, sizeof(tbl)); + ruby_sized_xfree(tbl, sizeof(*tbl)); } } #define vtable_free(tbl) vtable_free_gen(p, __LINE__, #tbl, tbl) @@ -9909,19 +9916,6 @@ past_dvar_p(struct parser_params *p, ID id) } # endif -/* As Ripper#warn does not have arguments for the location, so the - * following messages cannot be separated */ -#define WARN_LOCATION(type) do { \ - if (p->warn_location) { \ - int line; \ - VALUE file = rb_source_location(&line); \ - rb_warn3(type" in eval may not return location in binding;" \ - " use Binding#source_location instead\n" \ - "%"PRIsWARN":%d: warning: in `%"PRIsWARN"'", \ - file, WARN_I(line), rb_id2str(rb_frame_this_func())); \ - } \ -} while (0) - static int numparam_nested_p(struct parser_params *p) { @@ -9955,7 +9949,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case keyword_false: return NEW_FALSE(loc); case keyword__FILE__: - WARN_LOCATION("__FILE__"); { VALUE file = p->ruby_sourcefile_string; if (NIL_P(file)) @@ -9967,7 +9960,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) } return node; case keyword__LINE__: - WARN_LOCATION("__LINE__"); return NEW_LIT(INT2FIX(p->tokline), loc); case keyword__ENCODING__: node = NEW_LIT(rb_enc_from_encoding(p->enc), loc); @@ -11248,7 +11240,7 @@ negate_lit(struct parser_params *p, VALUE lit) lit = rb_big_norm(lit); break; case T_RATIONAL: - RRATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); + RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); break; case T_COMPLEX: RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real)); @@ -12049,7 +12041,7 @@ dvar_defined_ref(struct parser_params *p, ID id, ID **vidrefp) if (used) used = used->prev; } - if (vars == DVARS_INHERIT) { + if (vars == DVARS_INHERIT && !NUMPARAM_ID_P(id)) { return rb_dvar_defined(id, p->parent_iseq); } @@ -12244,14 +12236,6 @@ rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split) p->do_split = split; } -void -rb_parser_warn_location(VALUE vparser, int warn) -{ - struct parser_params *p; - TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - p->warn_location = warn; -} - static NODE * parser_append_options(struct parser_params *p, NODE *node) { diff --git a/ruby/ext/ripper/tools/dsl.rb b/ruby/ext/ripper/tools/dsl.rb index d2b9715a7..49ff51711 100644 --- a/ruby/ext/ripper/tools/dsl.rb +++ b/ruby/ext/ripper/tools/dsl.rb @@ -7,6 +7,9 @@ # v2 = dispatch0(void_stmt); # $$ = dispatch2(stmts_add, v1, v2); +$dollar = "$$" +alias $$ $dollar + class DSL def initialize(code, options) @events = {} diff --git a/ruby/ext/ripper/tools/preproc.rb b/ruby/ext/ripper/tools/preproc.rb index 7639a901d..b838a78db 100644 --- a/ruby/ext/ripper/tools/preproc.rb +++ b/ruby/ext/ripper/tools/preproc.rb @@ -45,7 +45,7 @@ def prelude(f, out) while line = f.gets case line when /\A%%/ - out << '%%' << $/ + out << "%%\n" return when /\A%token/ out << line.sub(/<\w+>/, '') @@ -79,15 +79,15 @@ def grammar(f, out) while line = f.gets case line when %r - out << DSL.new($2, ($1 || "").split(",")).generate << $/ + out << DSL.new($2, ($1 || "").split(",")).generate << "\n" when %r - out << '#if 0' << $/ + out << "#if 0\n" when %r - out << '#endif' << $/ + out << "#endif\n" when %r<%\*/> - out << $/ + out << "\n" when /\A%%/ - out << '%%' << $/ + out << "%%\n" return else out << line diff --git a/ruby/ext/sdbm/_sdbm.c b/ruby/ext/sdbm/_sdbm.c deleted file mode 100644 index 3a42b0e56..000000000 --- a/ruby/ext/sdbm/_sdbm.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * sdbm - ndbm work-alike hashed database library - * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). - * author: oz@nexus.yorku.ca - * status: public domain. - * - * core routines - */ - -#include "ruby/ruby.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "sdbm.h" - -/* - * sdbm - ndbm work-alike hashed database library - * tuning and portability constructs [not nearly enough] - * author: oz@nexus.yorku.ca - */ - -#define BYTESIZ 8 - -#ifdef BSD42 -#define SEEK_SET L_SET -#define memset(s,c,n) bzero((s), (n)) /* only when c is zero */ -#define memcpy(s1,s2,n) bcopy((s2), (s1), (n)) -#define memcmp(s1,s2,n) bcmp((s1),(s2),(n)) -#endif - -/* - * important tuning parms (hah) - */ - -#ifndef SEEDUPS -#define SEEDUPS 1 /* always detect duplicates */ -#endif -#ifndef BADMESS -#define BADMESS 1 /* generate a message for worst case: - cannot make room after SPLTMAX splits */ -#endif - -/* - * misc - */ -#ifdef DEBUG -#define debug(x) printf x -#else -#define debug(x) -#endif - -#ifdef BIG_E -#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1])) -#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s)) -#else -#define GET_SHORT(p, i) ((p)[(i)]) -#define PUT_SHORT(p, i, s) ((p)[(i)] = (s)) -#endif - -/*#include "pair.h"*/ -static int fitpair proto((char *, int)); -static void putpair proto((char *, datum, datum)); -static datum getpair proto((char *, datum)); -static int delpair proto((char *, datum)); -static int chkpage proto((char *)); -static datum getnkey proto((char *, int)); -static void splpage proto((char *, char *, long)); -#if SEEDUPS -static int duppair proto((char *, datum)); -#endif - -#include -#include -#ifdef DOSISH -#include -#endif -#include -#include -#ifdef BSD42 -#include -#else -#include -/*#include */ -#endif -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#include -#ifndef EPERM -#define EPERM EACCES -#endif -#include - -#ifdef __STDC__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* - * externals - */ -#if !defined(__sun) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(errno) -extern int errno; -#endif - -/* - * forward - */ -static int getdbit proto((DBM *, long)); -static int setdbit proto((DBM *, long)); -static int getpage proto((DBM *, long)); -static datum getnext proto((DBM *)); -static int makroom proto((DBM *, long, int)); - -/* - * useful macros - */ -#define bad(x) ((x).dptr == NULL || (x).dsize < 0) -#define exhash(item) sdbm_hash((item).dptr, (item).dsize) -#define ioerr(db) ((db)->flags |= DBM_IOERR) - -#define OFF_PAG(off) (long) (off) * PBLKSIZ -#define OFF_DIR(off) (long) (off) * DBLKSIZ - -static long masks[] = { - 000000000000L, 000000000001L, 000000000003L, - 000000000007L, 000000000017L, 000000000037L, - 000000000077L, 000000000177L, 000000000377L, - 000000000777L, 000000001777L, 000000003777L, - 000000007777L, 000000017777L, 000000037777L, - 000000077777L, 000000177777L, 000000377777L, - 000000777777L, 000001777777L, 000003777777L, - 000007777777L, 000017777777L, 000037777777L, - 000077777777L, 000177777777L, 000377777777L, - 000777777777L, 001777777777L, 003777777777L, - 007777777777L, 017777777777L -}; - -datum nullitem = {NULL, 0}; - -DBM * -sdbm_open(register char *file, register int flags, register int mode) -{ - register DBM *db; - register char *dirname; - register char *pagname; - register size_t n; - - if (file == NULL || !*file) - return errno = EINVAL, (DBM *) NULL; -/* - * need space for two separate filenames - */ - n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2; - - if ((dirname = malloc(n)) == NULL) - return errno = ENOMEM, (DBM *) NULL; -/* - * build the file names - */ - dirname = strcat(strcpy(dirname, file), DIRFEXT); - pagname = strcpy(dirname + strlen(dirname) + 1, file); - pagname = strcat(pagname, PAGFEXT); - - db = sdbm_prep(dirname, pagname, flags, mode); - free((char *) dirname); - return db; -} - -static int -fd_set_cloexec(int fd) -{ - /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */ -#ifdef F_GETFD - int flags, ret; - flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */ - if (flags == -1) { - return -1; - } - if (2 < fd) { - if (!(flags & FD_CLOEXEC)) { - flags |= FD_CLOEXEC; - ret = fcntl(fd, F_SETFD, flags); - if (ret == -1) { - return -1; - } - } - } -#endif - return 0; -} - -DBM * -sdbm_prep(char *dirname, char *pagname, int flags, int mode) -{ - register DBM *db; - struct stat dstat; - - if ((db = (DBM *) malloc(sizeof(DBM))) == NULL) - return errno = ENOMEM, (DBM *) NULL; - - db->pagf = -1; - db->dirf = -1; - db->flags = 0; - db->hmask = 0; - db->blkptr = 0; - db->keyptr = 0; -/* - * adjust user flags so that WRONLY becomes RDWR, - * as required by this package. Also set our internal - * flag for RDONLY. - */ - if (flags & O_WRONLY) - flags = (flags & ~O_WRONLY) | O_RDWR; - if (flags & O_RDONLY) - db->flags = DBM_RDONLY; -/* - * open the files in sequence, and stat the dirfile. - * If we fail anywhere, undo everything, return NULL. - */ - flags |= O_BINARY; -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - - if ((db->pagf = open(pagname, flags, mode)) == -1) goto err; - if (fd_set_cloexec(db->pagf) == -1) goto err; - if ((db->dirf = open(dirname, flags, mode)) == -1) goto err; - if (fd_set_cloexec(db->dirf) == -1) goto err; -/* - * need the dirfile size to establish max bit number. - */ - if (fstat(db->dirf, &dstat) == -1) goto err; -/* - * zero size: either a fresh database, or one with a single, - * unsplit data page: dirpage is all zeros. - */ - db->dirbno = (!dstat.st_size) ? 0 : -1; - db->pagbno = -1; - db->maxbno = dstat.st_size * (long) BYTESIZ; - - (void) memset(db->pagbuf, 0, PBLKSIZ); - (void) memset(db->dirbuf, 0, DBLKSIZ); -/* - * success - */ - return db; - - err: - if (db->pagf != -1) - (void) close(db->pagf); - if (db->dirf != -1) - (void) close(db->dirf); - free((char *) db); - return (DBM *) NULL; -} - -void -sdbm_close(register DBM *db) -{ - if (db == NULL) - errno = EINVAL; - else { - (void) close(db->dirf); - (void) close(db->pagf); - free((char *) db); - } -} - -datum -sdbm_fetch(register DBM *db, datum key) -{ - if (db == NULL || bad(key)) - return errno = EINVAL, nullitem; - - if (getpage(db, exhash(key))) - return getpair(db->pagbuf, key); - - return ioerr(db), nullitem; -} - -int -sdbm_delete(register DBM *db, datum key) -{ - if (db == NULL || bad(key)) - return errno = EINVAL, -1; - if (sdbm_rdonly(db)) - return errno = EPERM, -1; - - if (getpage(db, exhash(key))) { - if (!delpair(db->pagbuf, key)) - return -1; -/* - * update the page file - */ - if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0 - || write(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return ioerr(db), -1; - - return 0; - } - - return ioerr(db), -1; -} - -int -sdbm_store(register DBM *db, datum key, datum val, int flags) -{ - int need; - register long hash; - - if (db == NULL || bad(key)) - return errno = EINVAL, -1; - if (sdbm_rdonly(db)) - return errno = EPERM, -1; - - need = key.dsize + val.dsize; -/* - * is the pair too big (or too small) for this database ?? - */ - if (need < 0 || need > PAIRMAX) - return errno = EINVAL, -1; - - if (getpage(db, (hash = exhash(key)))) { -/* - * if we need to replace, delete the key/data pair - * first. If it is not there, ignore. - */ - if (flags == DBM_REPLACE) - (void) delpair(db->pagbuf, key); -#if SEEDUPS - else if (duppair(db->pagbuf, key)) - return 1; -#endif -/* - * if we do not have enough room, we have to split. - */ - if (!fitpair(db->pagbuf, need)) - if (!makroom(db, hash, need)) - return ioerr(db), -1; -/* - * we have enough room or split is successful. insert the key, - * and update the page file. - */ - (void) putpair(db->pagbuf, key, val); - - if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0 - || write(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return ioerr(db), -1; - /* - * success - */ - return 0; - } - - return ioerr(db), -1; -} - -/* - * makroom - make room by splitting the overfull page - * this routine will attempt to make room for SPLTMAX times before - * giving up. - */ -static int -makroom(register DBM *db, long int hash, int need) -{ - long newp; - char twin[PBLKSIZ]; -#if defined _WIN32 - char zer[PBLKSIZ]; - long oldtail; -#endif - char *pag = db->pagbuf; - char *new = twin; - register int smax = SPLTMAX; - - do { -/* - * split the current page - */ - (void) splpage(pag, new, db->hmask + 1); -/* - * address of the new page - */ - newp = (hash & db->hmask) | (db->hmask + 1); - debug(("newp: %ld\n", newp)); -/* - * write delay, read avoidance/cache shuffle: - * select the page for incoming pair: if key is to go to the new page, - * write out the previous one, and copy the new one over, thus making - * it the current page. If not, simply write the new page, and we are - * still looking at the page of interest. current page is not updated - * here, as sdbm_store will do so, after it inserts the incoming pair. - */ - -#if defined _WIN32 - /* - * Fill hole with 0 if made it. - * (hole is NOT read as 0) - */ - oldtail = lseek(db->pagf, 0L, SEEK_END); - memset(zer, 0, PBLKSIZ); - while (OFF_PAG(newp) > oldtail) { - if (lseek(db->pagf, 0L, SEEK_END) < 0 || - write(db->pagf, zer, PBLKSIZ) < 0) { - - return 0; - } - oldtail += PBLKSIZ; - } -#endif - - if (hash & (db->hmask + 1)) { - if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0 - || write(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return 0; - db->pagbno = newp; - (void) memcpy(pag, new, PBLKSIZ); - } - else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0 - || write(db->pagf, new, PBLKSIZ) < 0) - return 0; - - if (!setdbit(db, db->curbit)) - return 0; -/* - * see if we have enough room now - */ - if (fitpair(pag, need)) - return 1; -/* - * try again... update curbit and hmask as getpage would have - * done. because of our update of the current page, we do not - * need to read in anything. BUT we have to write the current - * [deferred] page out, as the window of failure is too great. - */ - db->curbit = 2 * db->curbit + - ((hash & (db->hmask + 1)) ? 2 : 1); - db->hmask |= (db->hmask + 1); - - if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0 - || write(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return 0; - - } while (--smax); -/* - * if we are here, this is real bad news. After SPLTMAX splits, - * we still cannot fit the key. say goodnight. - */ -#if BADMESS - (void) (write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44) < 0); -#endif - return 0; - -} - -/* - * the following two routines will break if - * deletions aren't taken into account. (ndbm bug) - */ -datum -sdbm_firstkey(register DBM *db) -{ - if (db == NULL) - return errno = EINVAL, nullitem; -/* - * start at page 0 - */ - (void) memset(db->pagbuf, 0, PBLKSIZ); - if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0 - || read(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return ioerr(db), nullitem; - db->pagbno = 0; - db->blkptr = 0; - db->keyptr = 0; - - return getnext(db); -} - -datum -sdbm_nextkey(register DBM *db) -{ - if (db == NULL) - return errno = EINVAL, nullitem; - return getnext(db); -} - -/* - * all important binary trie traversal - */ -static int -getpage(register DBM *db, register long int hash) -{ - register int hbit; - register long dbit; - register long pagb; - - dbit = 0; - hbit = 0; - while (dbit < db->maxbno && getdbit(db, dbit)) - dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1); - - debug(("dbit: %ld...", dbit)); - - db->curbit = dbit; - db->hmask = masks[hbit]; - - pagb = hash & db->hmask; -/* - * see if the block we need is already in memory. - * note: this lookaside cache has about 10% hit rate. - */ - if (pagb != db->pagbno) { -/* - * note: here, we assume a "hole" is read as 0s. - * if not, must zero pagbuf first. - */ - (void) memset(db->pagbuf, 0, PBLKSIZ); - - if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0 - || read(db->pagf, db->pagbuf, PBLKSIZ) < 0) - return 0; - if (!chkpage(db->pagbuf)) { - return 0; - } - db->pagbno = pagb; - - debug(("pag read: %ld\n", pagb)); - } - return 1; -} - -static int -getdbit(register DBM *db, register long int dbit) -{ - register long c; - register long dirb; - - c = dbit / BYTESIZ; - dirb = c / DBLKSIZ; - - if (dirb != db->dirbno) { - if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 - || read(db->dirf, db->dirbuf, DBLKSIZ) < 0) - return 0; - db->dirbno = dirb; - - debug(("dir read: %ld\n", dirb)); - } - - return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ)); -} - -static int -setdbit(register DBM *db, register long int dbit) -{ - register long c; - register long dirb; - - c = dbit / BYTESIZ; - dirb = c / DBLKSIZ; - - if (dirb != db->dirbno) { - if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 - || read(db->dirf, db->dirbuf, DBLKSIZ) < 0) - return 0; - db->dirbno = dirb; - - debug(("dir read: %ld\n", dirb)); - } - - db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ)); - - if (dbit >= db->maxbno) - db->maxbno += (long) DBLKSIZ * BYTESIZ; - - if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 - || write(db->dirf, db->dirbuf, DBLKSIZ) < 0) - return 0; - - return 1; -} - -/* - * getnext - get the next key in the page, and if done with - * the page, try the next page in sequence - */ -static datum -getnext(register DBM *db) -{ - datum key; - - for (;;) { - db->keyptr++; - key = getnkey(db->pagbuf, db->keyptr); - if (key.dptr != NULL) - return key; -/* - * we either run out, or there is nothing on this page.. - * try the next one... If we lost our position on the - * file, we will have to seek. - */ - db->keyptr = 0; - if (db->pagbno != db->blkptr++) - if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0) - break; - db->pagbno = db->blkptr; - if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0) - break; - if (!chkpage(db->pagbuf)) { - break; - } - } - - return ioerr(db), nullitem; -} - -/* pair.c */ -/* - * sdbm - ndbm work-alike hashed database library - * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). - * author: oz@nexus.yorku.ca - * status: public domain. - * - * page-level routines - */ - -#ifndef BSD42 -/*#include */ -#endif - -#define exhash(item) sdbm_hash((item).dptr, (item).dsize) - -/* - * forward - */ -static int seepair proto((char *, int, char *, int)); - -/* - * page format: - * +------------------------------+ - * ino | n | keyoff | datoff | keyoff | - * +------------+--------+--------+ - * | datoff | - - - ----> | - * +--------+---------------------+ - * | F R E E A R E A | - * +--------------+---------------+ - * | <---- - - - | data | - * +--------+-----+----+----------+ - * | key | data | key | - * +--------+----------+----------+ - * - * calculating the offsets for free area: if the number - * of entries (ino[0]) is zero, the offset to the END of - * the free area is the block size. Otherwise, it is the - * nth (ino[ino[0]]) entry's offset. - */ - -static int -fitpair(char *pag, int need) -{ - register int n; - register int off; - register int free; - register short *ino = (short *) pag; - - off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ; - free = off - (n + 1) * (int)sizeof(short); - need += 2 * (int)sizeof(short); - - debug(("free %d need %d\n", free, need)); - - return need <= free; -} - -static void -putpair(char *pag, datum key, datum val) -{ - register int n; - register int off; - register short *ino = (short *) pag; - - off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ; -/* - * enter the key first - */ - off -= key.dsize; - if (key.dsize) - (void) memcpy(pag + off, key.dptr, key.dsize); - PUT_SHORT(ino,n + 1,off); -/* - * now the data - */ - off -= val.dsize; - if (val.dsize) - (void) memcpy(pag + off, val.dptr, val.dsize); - PUT_SHORT(ino,n + 2,off); -/* - * adjust item count - */ - PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2); -} - -static datum -getpair(char *pag, datum key) -{ - register int i; - register int n; - datum val; - register short *ino = (short *) pag; - - if ((n = GET_SHORT(ino,0)) == 0) - return nullitem; - - if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0) - return nullitem; - - val.dptr = pag + GET_SHORT(ino,i + 1); - val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1); - return val; -} - -#if SEEDUPS -static int -duppair(char *pag, datum key) -{ - register short *ino = (short *) pag; - return GET_SHORT(ino,0) > 0 && - seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0; -} -#endif - -static datum -getnkey(char *pag, int num) -{ - datum key; - register int off; - register short *ino = (short *) pag; - - num = num * 2 - 1; - if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0)) - return nullitem; - - off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ; - - key.dptr = pag + GET_SHORT(ino,num); - key.dsize = off - GET_SHORT(ino,num); - - return key; -} - -static int -delpair(char *pag, datum key) -{ - register int n; - register int i; - register short *ino = (short *) pag; - - if ((n = GET_SHORT(ino,0)) == 0) - return 0; - - if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0) - return 0; -/* - * found the key. if it is the last entry - * [i.e. i == n - 1] we just adjust the entry count. - * hard case: move all data down onto the deleted pair, - * shift offsets onto deleted offsets, and adjust them. - * [note: 0 < i < n] - */ - if (i < n - 1) { - register int m; - register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1)); - register char *src = pag + GET_SHORT(ino,i + 1); - register ptrdiff_t zoo = dst - src; - - debug(("free-up %"PRIdPTRDIFF" ", zoo)); -/* - * shift data/keys down - */ - m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n); -#ifdef DUFF -#define MOVB *--dst = *--src - - if (m > 0) { - register int loop = (m + 8 - 1) >> 3; - - switch (m & (8 - 1)) { - case 0: do { - MOVB; case 7: MOVB; - case 6: MOVB; case 5: MOVB; - case 4: MOVB; case 3: MOVB; - case 2: MOVB; case 1: MOVB; - } while (--loop); - } - } -#else -#ifdef MEMMOVE - memmove(dst-m, src-m, m); -#else - while (m--) - *--dst = *--src; -#endif -#endif -/* - * adjust offset index up - */ - while (i < n - 1) { - PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo); - i++; - } - } - PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2); - return 1; -} - -/* - * search for the key in the page. - * return offset index in the range 0 < i < n. - * return 0 if not found. - */ -static int -seepair(char *pag, register int n, register char *key, register int siz) -{ - register int i; - register int off = PBLKSIZ; - register short *ino = (short *) pag; - - for (i = 1; i < n; i += 2) { - if (siz == off - GET_SHORT(ino,i) && - memcmp(key, pag + GET_SHORT(ino,i), siz) == 0) - return i; - off = GET_SHORT(ino,i + 1); - } - return 0; -} - -static void -splpage(char *pag, char *new, long int sbit) -{ - datum key; - datum val; - - register int n; - register int off = PBLKSIZ; - char cur[PBLKSIZ]; - register short *ino = (short *) cur; - - (void) memcpy(cur, pag, PBLKSIZ); - (void) memset(pag, 0, PBLKSIZ); - (void) memset(new, 0, PBLKSIZ); - - n = GET_SHORT(ino,0); - for (ino++; n > 0; ino += 2) { - key.dptr = cur + GET_SHORT(ino,0); - key.dsize = off - GET_SHORT(ino,0); - val.dptr = cur + GET_SHORT(ino,1); - val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1); -/* - * select the page pointer (by looking at sbit) and insert - */ - (void) putpair((exhash(key) & sbit) ? new : pag, key, val); - - off = GET_SHORT(ino,1); - n -= 2; - } - - debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, - ((short *) new)[0] / 2, - ((short *) pag)[0] / 2)); -} - -/* - * check page sanity: - * number of entries should be something - * reasonable, and all offsets in the index should be in order. - * this could be made more rigorous. - */ -static int -chkpage(char *pag) -{ - register int n; - register int off; - register short *ino = (short *) pag; - - if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / (int)sizeof(short)) - return 0; - - if (n > 0) { - off = PBLKSIZ; - for (ino++; n > 0; ino += 2) { - if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off || - GET_SHORT(ino,1) > GET_SHORT(ino,0)) - return 0; - off = GET_SHORT(ino,1); - n -= 2; - } - } - return 1; -} - -/* hash.c */ -/* - * sdbm - ndbm work-alike hashed database library - * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). - * author: oz@nexus.yorku.ca - * status: public domain. keep it that way. - * - * hashing routine - */ - -/* - * polynomial conversion ignoring overflows - * [this seems to work remarkably well, in fact better - * then the ndbm hash function. Replace at your own risk] - * use: 65599 nice. - * 65587 even better. - */ -long -sdbm_hash(register char *str, register int len) -{ - register unsigned long n = 0; - -#ifdef DUFF - -#define HASHC n = *str++ + 65599 * n - - if (len > 0) { - register int loop = (len + 8 - 1) >> 3; - - switch(len & (8 - 1)) { - case 0: do { - HASHC; case 7: HASHC; - case 6: HASHC; case 5: HASHC; - case 4: HASHC; case 3: HASHC; - case 2: HASHC; case 1: HASHC; - } while (--loop); - } - - } -#else - while (len--) - n = ((*str++) & 255) + 65587L * n; -#endif - return n; -} diff --git a/ruby/ext/sdbm/depend b/ruby/ext/sdbm/depend deleted file mode 100644 index d475eccce..000000000 --- a/ruby/ext/sdbm/depend +++ /dev/null @@ -1,27 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -_sdbm.o: $(RUBY_EXTCONF_H) -_sdbm.o: $(arch_hdrdir)/ruby/config.h -_sdbm.o: $(hdrdir)/ruby/assert.h -_sdbm.o: $(hdrdir)/ruby/backward.h -_sdbm.o: $(hdrdir)/ruby/defines.h -_sdbm.o: $(hdrdir)/ruby/intern.h -_sdbm.o: $(hdrdir)/ruby/missing.h -_sdbm.o: $(hdrdir)/ruby/ruby.h -_sdbm.o: $(hdrdir)/ruby/st.h -_sdbm.o: $(hdrdir)/ruby/subst.h -_sdbm.o: _sdbm.c -_sdbm.o: sdbm.h -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/defines.h -init.o: $(hdrdir)/ruby/intern.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 -init.o: sdbm.h -# AUTOGENERATED DEPENDENCIES END diff --git a/ruby/ext/sdbm/extconf.rb b/ruby/ext/sdbm/extconf.rb deleted file mode 100644 index bdf3e299e..000000000 --- a/ruby/ext/sdbm/extconf.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' - -$defs << "-D""BADMESS=0" -create_makefile("sdbm") diff --git a/ruby/ext/sdbm/init.c b/ruby/ext/sdbm/init.c deleted file mode 100644 index 42292b99c..000000000 --- a/ruby/ext/sdbm/init.c +++ /dev/null @@ -1,1067 +0,0 @@ -/************************************************ - - sdbminit.c - - - $Author$ - created at: Fri May 7 08:34:24 JST 1999 - - Copyright (C) 1995-2001 Yukihiro Matsumoto - -************************************************/ - -#include "ruby.h" - -#include "sdbm.h" -#include -#include - -/* - * Document-class: SDBM - * - * SDBM provides a simple file-based key-value store, which can only store - * String keys and values. - * - * Note that Ruby comes with the source code for SDBM, while the DBM and GDBM - * standard libraries rely on external libraries and headers. - * - * === Examples - * - * Insert values: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db['apple'] = 'fruit' - * db['pear'] = 'fruit' - * db['carrot'] = 'vegetable' - * db['tomato'] = 'vegetable' - * end - * - * Bulk update: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db.update('peach' => 'fruit', 'tomato' => 'fruit') - * end - * - * Retrieve values: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db.each do |key, value| - * puts "Key: #{key}, Value: #{value}" - * end - * end - * - * Outputs: - * - * Key: apple, Value: fruit - * Key: pear, Value: fruit - * Key: carrot, Value: vegetable - * Key: peach, Value: fruit - * Key: tomato, Value: fruit - */ - -static VALUE rb_cDBM, rb_eDBMError; - -struct dbmdata { - int di_size; - DBM *di_dbm; -}; - -NORETURN(static void closed_sdbm(void)); - -static void -closed_sdbm(void) -{ - rb_raise(rb_eDBMError, "closed SDBM file"); -} - -#define GetDBM(obj, dbmp) do {\ - TypedData_Get_Struct((obj), struct dbmdata, &sdbm_type, (dbmp));\ - if ((dbmp)->di_dbm == 0) closed_sdbm();\ -} while (0) - -#define GetDBM2(obj, dbmp, dbm) do {\ - GetDBM((obj), (dbmp));\ - (dbm) = (dbmp)->di_dbm;\ -} while (0) - -static void -free_sdbm(void *ptr) -{ - struct dbmdata *dbmp = ptr; - - if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm); - ruby_xfree(dbmp); -} - -static size_t -memsize_dbm(const void *ptr) -{ - const struct dbmdata *dbmp = ptr; - size_t size = sizeof(*dbmp); - if (dbmp->di_dbm) - size += sizeof(DBM); - return size; -} - -static const rb_data_type_t sdbm_type = { - "sdbm", - {0, free_sdbm, memsize_dbm,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, -}; - -/* - * call-seq: - * sdbm.close -> nil - * - * Closes the database file. - * - * Raises SDBMError if the database is already closed. - */ -static VALUE -fsdbm_close(VALUE obj) -{ - struct dbmdata *dbmp; - - GetDBM(obj, dbmp); - sdbm_close(dbmp->di_dbm); - dbmp->di_dbm = 0; - - return Qnil; -} - -/* - * call-seq: - * sdbm.closed? -> true or false - * - * Returns +true+ if the database is closed. - */ -static VALUE -fsdbm_closed(VALUE obj) -{ - struct dbmdata *dbmp; - - TypedData_Get_Struct(obj, struct dbmdata, &sdbm_type, dbmp); - if (dbmp->di_dbm == 0) - return Qtrue; - - return Qfalse; -} - -static VALUE -fsdbm_alloc(VALUE klass) -{ - struct dbmdata *dbmp; - - return TypedData_Make_Struct(klass, struct dbmdata, &sdbm_type, dbmp); -} -/* - * call-seq: - * SDBM.new(filename, mode = 0666) - * - * Creates a new database handle by opening the given +filename+. SDBM actually - * uses two physical files, with extensions '.dir' and '.pag'. These extensions - * will automatically be appended to the +filename+. - * - * If the file does not exist, a new file will be created using the given - * +mode+, unless +mode+ is explicitly set to nil. In the latter case, no - * database will be created. - * - * If the file exists, it will be opened in read/write mode. If this fails, it - * will be opened in read-only mode. - */ -static VALUE -fsdbm_initialize(int argc, VALUE *argv, VALUE obj) -{ - VALUE file, vmode; - DBM *dbm; - struct dbmdata *dbmp; - int mode; - - TypedData_Get_Struct(obj, struct dbmdata, &sdbm_type, dbmp); - if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { - mode = 0666; /* default value */ - } - else if (NIL_P(vmode)) { - mode = -1; /* return nil if DB not exist */ - } - else { - mode = NUM2INT(vmode); - } - FilePathValue(file); - - dbm = 0; - if (mode >= 0) - dbm = sdbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode); - if (!dbm) - dbm = sdbm_open(RSTRING_PTR(file), O_RDWR, 0); - if (!dbm) - dbm = sdbm_open(RSTRING_PTR(file), O_RDONLY, 0); - - if (!dbm) { - if (mode == -1) return Qnil; - rb_sys_fail_str(file); - } - - if (dbmp->di_dbm) - sdbm_close(dbmp->di_dbm); - dbmp->di_dbm = dbm; - dbmp->di_size = -1; - - return obj; -} - -/* - * call-seq: - * SDBM.open(filename, mode = 0666) - * SDBM.open(filename, mode = 0666) { |sdbm| ... } - * - * If called without a block, this is the same as SDBM.new. - * - * If a block is given, the new database will be passed to the block and - * will be safely closed after the block has executed. - * - * Example: - * - * require 'sdbm' - * - * SDBM.open('my_database') do |db| - * db['hello'] = 'world' - * end - */ -static VALUE -fsdbm_s_open(int argc, VALUE *argv, VALUE klass) -{ - VALUE obj = fsdbm_alloc(klass); - - if (NIL_P(fsdbm_initialize(argc, argv, obj))) { - return Qnil; - } - - if (rb_block_given_p()) { - return rb_ensure(rb_yield, obj, fsdbm_close, obj); - } - - return obj; -} - -static VALUE -fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) -{ - datum key, value; - struct dbmdata *dbmp; - DBM *dbm; - - ExportStringValue(keystr); - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - - GetDBM2(obj, dbmp, dbm); - value = sdbm_fetch(dbm, key); - if (value.dptr == 0) { - if (ifnone == Qnil && rb_block_given_p()) - return rb_yield(rb_external_str_new(key.dptr, key.dsize)); - return ifnone; - } - return rb_external_str_new(value.dptr, value.dsize); -} - -/* - * call-seq: - * sdbm[key] -> value or nil - * - * Returns the +value+ in the database associated with the given +key+ string. - * - * If no value is found, returns +nil+. - */ -static VALUE -fsdbm_aref(VALUE obj, VALUE keystr) -{ - return fsdbm_fetch(obj, keystr, Qnil); -} - -/* - * call-seq: - * sdbm.fetch(key) -> value or nil - * sdbm.fetch(key) { |key| ... } - * - * Returns the +value+ in the database associated with the given +key+ string. - * - * If a block is provided, the block will be called when there is no - * +value+ associated with the given +key+. The +key+ will be passed in as an - * argument to the block. - * - * If no block is provided and no value is associated with the given +key+, - * then an IndexError will be raised. - */ -static VALUE -fsdbm_fetch_m(int argc, VALUE *argv, VALUE obj) -{ - VALUE keystr, valstr, ifnone; - - rb_scan_args(argc, argv, "11", &keystr, &ifnone); - valstr = fsdbm_fetch(obj, keystr, ifnone); - if (argc == 1 && !rb_block_given_p() && NIL_P(valstr)) - rb_raise(rb_eIndexError, "key not found"); - - return valstr; -} - -/* - * call-seq: - * sdbm.key(value) -> key - * - * Returns the +key+ associated with the given +value+. If more than one - * +key+ corresponds to the given +value+, then the first key to be found - * will be returned. If no keys are found, +nil+ will be returned. - */ -static VALUE -fsdbm_key(VALUE obj, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - ExportStringValue(valstr); - val.dptr = RSTRING_PTR(valstr); - val.dsize = RSTRING_LENINT(valstr); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - if (val.dsize == RSTRING_LEN(valstr) && - memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) - return rb_external_str_new(key.dptr, key.dsize); - } - return Qnil; -} - -/* - * :nodoc: - */ -static VALUE -fsdbm_index(VALUE hash, VALUE value) -{ - rb_warn("SDBM#index is deprecated; use SDBM#key"); - return fsdbm_key(hash, value); -} - -/* call-seq: - * sdbm.select { |key, value| ... } -> Array - * - * Returns a new Array of key-value pairs for which the block returns +true+. - * - * Example: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db['apple'] = 'fruit' - * db['pear'] = 'fruit' - * db['spinach'] = 'vegetable' - * - * veggies = db.select do |key, value| - * value == 'vegetable' - * end #=> [["apple", "fruit"], ["pear", "fruit"]] - * end - */ -static VALUE -fsdbm_select(VALUE obj) -{ - VALUE new = rb_ary_new(); - datum key, val; - DBM *dbm; - struct dbmdata *dbmp; - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - VALUE assoc, v; - val = sdbm_fetch(dbm, key); - assoc = rb_assoc_new(rb_external_str_new(key.dptr, key.dsize), - rb_external_str_new(val.dptr, val.dsize)); - v = rb_yield(assoc); - if (RTEST(v)) { - rb_ary_push(new, assoc); - } - GetDBM2(obj, dbmp, dbm); - } - - return new; -} - -/* call-seq: - * sdbm.values_at(key, ...) -> Array - * - * Returns an Array of values corresponding to the given keys. - */ -static VALUE -fsdbm_values_at(int argc, VALUE *argv, VALUE obj) -{ - VALUE new = rb_ary_new2(argc); - int i; - - for (i=0; i value or nil - * sdbm.delete(key) { |key, value| ... } - * - * Deletes the key-value pair corresponding to the given +key+. If the - * +key+ exists, the deleted value will be returned, otherwise +nil+. - * - * If a block is provided, the deleted +key+ and +value+ will be passed to - * the block as arguments. If the +key+ does not exist in the database, the - * value will be +nil+. - */ -static VALUE -fsdbm_delete(VALUE obj, VALUE keystr) -{ - datum key, value; - struct dbmdata *dbmp; - DBM *dbm; - VALUE valstr; - - fdbm_modify(obj); - ExportStringValue(keystr); - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - - value = sdbm_fetch(dbm, key); - if (value.dptr == 0) { - if (rb_block_given_p()) return rb_yield(keystr); - return Qnil; - } - - /* need to save value before sdbm_delete() */ - valstr = rb_external_str_new(value.dptr, value.dsize); - - if (sdbm_delete(dbm, key)) { - dbmp->di_size = -1; - rb_raise(rb_eDBMError, "dbm_delete failed"); - } - else if (dbmp->di_size >= 0) { - dbmp->di_size--; - } - return valstr; -} - -/* - * call-seq: - * sdbm.shift -> Array or nil - * - * Removes a key-value pair from the database and returns them as an - * Array. If the database is empty, returns +nil+. - */ -static VALUE -fsdbm_shift(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - key = sdbm_firstkey(dbm); - if (!key.dptr) return Qnil; - val = sdbm_fetch(dbm, key); - keystr = rb_external_str_new(key.dptr, key.dsize); - valstr = rb_external_str_new(val.dptr, val.dsize); - sdbm_delete(dbm, key); - if (dbmp->di_size >= 0) { - dbmp->di_size--; - } - - return rb_assoc_new(keystr, valstr); -} - -/* - * call-seq: - * sdbm.delete_if { |key, value| ... } -> self - * sdbm.reject! { |key, value| ... } -> self - * - * Iterates over the key-value pairs in the database, deleting those for - * which the block returns +true+. - */ -static VALUE -fsdbm_delete_if(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - VALUE ret, ary = rb_ary_new(); - long i; - int status = 0, n; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - n = dbmp->di_size; - dbmp->di_size = -1; - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - keystr = rb_external_str_new(key.dptr, key.dsize); - valstr = rb_external_str_new(val.dptr, val.dsize); - ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status); - if (status != 0) break; - if (RTEST(ret)) rb_ary_push(ary, keystr); - GetDBM2(obj, dbmp, dbm); - } - - for (i = 0; i < RARRAY_LEN(ary); i++) { - keystr = RARRAY_AREF(ary, i); - ExportStringValue(keystr); - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - if (sdbm_delete(dbm, key)) { - rb_raise(rb_eDBMError, "sdbm_delete failed"); - } - } - if (status) rb_jump_tag(status); - if (n > 0) dbmp->di_size = n - RARRAY_LENINT(ary); - - return obj; -} - -/* - * call-seq: - * sdbm.clear -> self - * - * Deletes all data from the database. - */ -static VALUE -fsdbm_clear(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - fdbm_modify(obj); - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - while (key = sdbm_firstkey(dbm), key.dptr) { - if (sdbm_delete(dbm, key)) { - rb_raise(rb_eDBMError, "sdbm_delete failed"); - } - } - dbmp->di_size = 0; - - return obj; -} - -/* - * call-seq: - * sdbm.invert -> Hash - * - * Returns a Hash in which the key-value pairs have been inverted. - * - * Example: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db.update('apple' => 'fruit', 'spinach' => 'vegetable') - * - * db.invert #=> {"fruit" => "apple", "vegetable" => "spinach"} - * end - */ -static VALUE -fsdbm_invert(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE keystr, valstr; - VALUE hash = rb_hash_new(); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - keystr = rb_external_str_new(key.dptr, key.dsize); - valstr = rb_external_str_new(val.dptr, val.dsize); - rb_hash_aset(hash, valstr, keystr); - } - return hash; -} - -/* - * call-seq: - * sdbm[key] = value -> value - * sdbm.store(key, value) -> value - * - * Stores a new +value+ in the database with the given +key+ as an index. - * - * If the +key+ already exists, this will update the +value+ associated with - * the +key+. - * - * Returns the given +value+. - */ -static VALUE -fsdbm_store(VALUE obj, VALUE keystr, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - if (valstr == Qnil) { - fsdbm_delete(obj, keystr); - return Qnil; - } - - fdbm_modify(obj); - ExportStringValue(keystr); - ExportStringValue(valstr); - - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - - val.dptr = RSTRING_PTR(valstr); - val.dsize = RSTRING_LENINT(valstr); - - GetDBM2(obj, dbmp, dbm); - dbmp->di_size = -1; - if (sdbm_store(dbm, key, val, DBM_REPLACE)) { -#ifdef HAVE_DBM_CLAERERR - sdbm_clearerr(dbm); -#endif - if (errno == EPERM) rb_sys_fail(0); - rb_raise(rb_eDBMError, "sdbm_store failed"); - } - - return valstr; -} - -static VALUE -update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm)) -{ - const VALUE *ptr; - Check_Type(pair, T_ARRAY); - if (RARRAY_LEN(pair) < 2) { - rb_raise(rb_eArgError, "pair must be [key, value]"); - } - ptr = RARRAY_CONST_PTR(pair); - fsdbm_store(dbm, ptr[0], ptr[1]); - return Qnil; -} - -/* - * call-seq: - * sdbm.update(pairs) -> self - * - * Insert or update key-value pairs. - * - * This method will work with any object which implements an each_pair - * method, such as a Hash. - */ -static VALUE -fsdbm_update(VALUE obj, VALUE other) -{ - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * sdbm.replace(pairs) -> self - * - * Empties the database, then inserts the given key-value pairs. - * - * This method will work with any object which implements an each_pair - * method, such as a Hash. - */ -static VALUE -fsdbm_replace(VALUE obj, VALUE other) -{ - fsdbm_clear(obj); - rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj); - return obj; -} - -/* - * call-seq: - * sdbm.length -> integer - * sdbm.size -> integer - * - * Returns the number of keys in the database. - */ -static VALUE -fsdbm_length(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - int i = 0; - - GetDBM2(obj, dbmp, dbm); - if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); - - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - i++; - } - dbmp->di_size = i; - - return INT2FIX(i); -} - -/* - * call-seq: - * sdbm.empty? -> true or false - * - * Returns +true+ if the database is empty. - */ -static VALUE -fsdbm_empty_p(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - GetDBM(obj, dbmp); - if (dbmp->di_size < 0) { - dbm = dbmp->di_dbm; - - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - return Qfalse; - } - } - else { - if (dbmp->di_size) - return Qfalse; - } - return Qtrue; -} - -/* - * call-seq: - * sdbm.each_value - * sdbm.each_value { |value| ... } - * - * Iterates over each +value+ in the database. - * - * If no block is given, returns an Enumerator. - */ -static VALUE -fsdbm_each_value(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - rb_yield(rb_external_str_new(val.dptr, val.dsize)); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * sdbm.each_key - * sdbm.each_key { |key| ... } - * - * Iterates over each +key+ in the database. - * - * If no block is given, returns an Enumerator. - */ -static VALUE -fsdbm_each_key(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - rb_yield(rb_external_str_new(key.dptr, key.dsize)); - GetDBM2(obj, dbmp, dbm); - } - return obj; -} - -/* - * call-seq: - * sdbm.each - * sdbm.each { |key, value| ... } - * sdbm.each_pair - * sdbm.each_pair { |key, value| ... } - * - * Iterates over each key-value pair in the database. - * - * If no block is given, returns an Enumerator. - */ -static VALUE -fsdbm_each_pair(VALUE obj) -{ - datum key, val; - DBM *dbm; - struct dbmdata *dbmp; - VALUE keystr, valstr; - - RETURN_ENUMERATOR(obj, 0, 0); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - keystr = rb_external_str_new(key.dptr, key.dsize); - valstr = rb_external_str_new(val.dptr, val.dsize); - rb_yield(rb_assoc_new(keystr, valstr)); - GetDBM2(obj, dbmp, dbm); - } - - return obj; -} - -/* - * call-seq: - * sdbm.keys -> Array - * - * Returns a new Array containing the keys in the database. - */ -static VALUE -fsdbm_keys(VALUE obj) -{ - datum key; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - rb_ary_push(ary, rb_external_str_new(key.dptr, key.dsize)); - } - - return ary; -} - -/* - * call-seq: - * sdbm.values -> Array - * - * Returns a new Array containing the values in the database. - */ -static VALUE -fsdbm_values(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - rb_ary_push(ary, rb_external_str_new(val.dptr, val.dsize)); - } - - return ary; -} - -/* - * call-seq: - * sdbm.include?(key) -> true or false - * sdbm.key?(key) -> true or false - * sdbm.member?(key) -> true or false - * sdbm.has_key?(key) -> true or false - * - * Returns +true+ if the database contains the given +key+. - */ -static VALUE -fsdbm_has_key(VALUE obj, VALUE keystr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - ExportStringValue(keystr); - key.dptr = RSTRING_PTR(keystr); - key.dsize = RSTRING_LENINT(keystr); - - GetDBM2(obj, dbmp, dbm); - val = sdbm_fetch(dbm, key); - if (val.dptr) return Qtrue; - return Qfalse; -} - -/* - * call-seq: - * sdbm.value?(key) -> true or false - * sdbm.has_value?(key) -> true or false - * - * Returns +true+ if the database contains the given +value+. - */ -static VALUE -fsdbm_has_value(VALUE obj, VALUE valstr) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - - ExportStringValue(valstr); - val.dptr = RSTRING_PTR(valstr); - val.dsize = RSTRING_LENINT(valstr); - - GetDBM2(obj, dbmp, dbm); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - if (val.dsize == RSTRING_LENINT(valstr) && - memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) - return Qtrue; - } - return Qfalse; -} - -/* - * call-seq: - * sdbm.to_a -> Array - * - * Returns a new Array containing each key-value pair in the database. - * - * Example: - * - * require 'sdbm' - * - * SDBM.open 'my_database' do |db| - * db.update('apple' => 'fruit', 'spinach' => 'vegetable') - * - * db.to_a #=> [["apple", "fruit"], ["spinach", "vegetable"]] - * end - */ -static VALUE -fsdbm_to_a(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE ary; - - GetDBM2(obj, dbmp, dbm); - ary = rb_ary_new(); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - rb_ary_push(ary, rb_assoc_new(rb_external_str_new(key.dptr, key.dsize), - rb_external_str_new(val.dptr, val.dsize))); - } - - return ary; -} - -/* - * call-seq: - * sdbm.to_hash -> Hash - * - * Returns a new Hash containing each key-value pair in the database. - */ -static VALUE -fsdbm_to_hash(VALUE obj) -{ - datum key, val; - struct dbmdata *dbmp; - DBM *dbm; - VALUE hash; - - GetDBM2(obj, dbmp, dbm); - hash = rb_hash_new(); - for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { - val = sdbm_fetch(dbm, key); - rb_hash_aset(hash, rb_external_str_new(key.dptr, key.dsize), - rb_external_str_new(val.dptr, val.dsize)); - } - - return hash; -} - -/* - * call-seq: - * sdbm.reject { |key, value| ... } -> Hash - * - * Creates a new Hash using the key-value pairs from the database, then - * calls Hash#reject with the given block, which returns a Hash with - * only the key-value pairs for which the block returns +false+. - */ -static VALUE -fsdbm_reject(VALUE obj) -{ - return rb_hash_delete_if(fsdbm_to_hash(obj)); -} - -void -Init_sdbm(void) -{ - rb_cDBM = rb_define_class("SDBM", rb_cObject); - rb_eDBMError = rb_define_class("SDBMError", rb_eStandardError); - /* Document-class: SDBMError - * Exception class used to return errors from the sdbm library. - */ - rb_include_module(rb_cDBM, rb_mEnumerable); - - rb_define_alloc_func(rb_cDBM, fsdbm_alloc); - rb_define_singleton_method(rb_cDBM, "open", fsdbm_s_open, -1); - - rb_define_method(rb_cDBM, "initialize", fsdbm_initialize, -1); - rb_define_method(rb_cDBM, "close", fsdbm_close, 0); - rb_define_method(rb_cDBM, "closed?", fsdbm_closed, 0); - rb_define_method(rb_cDBM, "[]", fsdbm_aref, 1); - rb_define_method(rb_cDBM, "fetch", fsdbm_fetch_m, -1); - rb_define_method(rb_cDBM, "[]=", fsdbm_store, 2); - rb_define_method(rb_cDBM, "store", fsdbm_store, 2); - rb_define_method(rb_cDBM, "index", fsdbm_index, 1); - rb_define_method(rb_cDBM, "key", fsdbm_key, 1); - rb_define_method(rb_cDBM, "select", fsdbm_select, 0); - rb_define_method(rb_cDBM, "values_at", fsdbm_values_at, -1); - rb_define_method(rb_cDBM, "length", fsdbm_length, 0); - rb_define_method(rb_cDBM, "size", fsdbm_length, 0); - rb_define_method(rb_cDBM, "empty?", fsdbm_empty_p, 0); - rb_define_method(rb_cDBM, "each", fsdbm_each_pair, 0); - rb_define_method(rb_cDBM, "each_value", fsdbm_each_value, 0); - rb_define_method(rb_cDBM, "each_key", fsdbm_each_key, 0); - rb_define_method(rb_cDBM, "each_pair", fsdbm_each_pair, 0); - rb_define_method(rb_cDBM, "keys", fsdbm_keys, 0); - rb_define_method(rb_cDBM, "values", fsdbm_values, 0); - rb_define_method(rb_cDBM, "shift", fsdbm_shift, 0); - rb_define_method(rb_cDBM, "delete", fsdbm_delete, 1); - rb_define_method(rb_cDBM, "delete_if", fsdbm_delete_if, 0); - rb_define_method(rb_cDBM, "reject!", fsdbm_delete_if, 0); - rb_define_method(rb_cDBM, "reject", fsdbm_reject, 0); - rb_define_method(rb_cDBM, "clear", fsdbm_clear, 0); - rb_define_method(rb_cDBM,"invert", fsdbm_invert, 0); - rb_define_method(rb_cDBM,"update", fsdbm_update, 1); - rb_define_method(rb_cDBM,"replace", fsdbm_replace, 1); - - rb_define_method(rb_cDBM, "has_key?", fsdbm_has_key, 1); - rb_define_method(rb_cDBM, "include?", fsdbm_has_key, 1); - rb_define_method(rb_cDBM, "key?", fsdbm_has_key, 1); - rb_define_method(rb_cDBM, "member?", fsdbm_has_key, 1); - rb_define_method(rb_cDBM, "has_value?", fsdbm_has_value, 1); - rb_define_method(rb_cDBM, "value?", fsdbm_has_value, 1); - - rb_define_method(rb_cDBM, "to_a", fsdbm_to_a, 0); - rb_define_method(rb_cDBM, "to_hash", fsdbm_to_hash, 0); -} diff --git a/ruby/ext/sdbm/sdbm.gemspec b/ruby/ext/sdbm/sdbm.gemspec deleted file mode 100644 index 6cf000b45..000000000 --- a/ruby/ext/sdbm/sdbm.gemspec +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -Gem::Specification.new do |s| - s.name = "sdbm" - s.version = '1.0.0' - s.summary = "Provides a simple file-based key-value store with String keys and values." - s.description = "Provides a simple file-based key-value store with String keys and values." - - s.require_path = %w{lib} - s.files = %w{ext/sdbm/_sdbm.c ext/sdbm/extconf.rb ext/sdbm/init.c ext/sdbm/sdbm.h} - s.extensions = ["ext/sdbm/extconf.rb"] - s.required_ruby_version = ">= 2.3.0" - - s.authors = ["Yukihiro Matsumoto"] - s.email = ["matz@ruby-lang.org"] - s.homepage = "https://github.com/ruby/sdbm" - s.license = "BSD-2-Clause" - - s.add_development_dependency "test-unit" - s.add_development_dependency "rake-compiler" -end diff --git a/ruby/ext/sdbm/sdbm.h b/ruby/ext/sdbm/sdbm.h deleted file mode 100644 index c3b53c4a8..000000000 --- a/ruby/ext/sdbm/sdbm.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * sdbm - ndbm work-alike hashed database library - * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978). - * author: oz@nexus.yorku.ca - * status: public domain. - */ -#ifndef _SDBM_H_ -#define _SDBM_H_ - -#include - -#define DBLKSIZ 4096 -#define PBLKSIZ 1024 -#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */ -#define SPLTMAX 10 /* maximum allowed splits */ - /* for a single insertion */ -#define DIRFEXT ".dir" -#define PAGFEXT ".pag" - -typedef struct { - int dirf; /* directory file descriptor */ - int pagf; /* page file descriptor */ - int flags; /* status/error flags, see below */ - int keyptr; /* current key for nextkey */ - off_t maxbno; /* size of dirfile in bits */ - long curbit; /* current bit number */ - long hmask; /* current hash mask */ - long blkptr; /* current block for nextkey */ - long blkno; /* current page to read/write */ - long pagbno; /* current page in pagbuf */ - char pagbuf[PBLKSIZ]; /* page file block buffer */ - long dirbno; /* current block in dirbuf */ - char dirbuf[DBLKSIZ]; /* directory file block buffer */ -} DBM; - -#define DBM_RDONLY 0x1 /* data base open read-only */ -#define DBM_IOERR 0x2 /* data base I/O error */ - -/* - * utility macros - */ -#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY) -#define sdbm_error(db) ((db)->flags & DBM_IOERR) - -#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */ - -#define sdbm_dirfno(db) ((db)->dirf) -#define sdbm_pagfno(db) ((db)->pagf) - -typedef struct { - char *dptr; - int dsize; -} datum; - -extern datum nullitem; - -#if defined(__STDC__) -#define proto(p) p -#else -#define proto(p) () -#endif - -/* - * flags to sdbm_store - */ -#define DBM_INSERT 0 -#define DBM_REPLACE 1 - -/* - * ndbm interface - */ -extern DBM *sdbm_open proto((char *, int, int)); -extern void sdbm_close proto((DBM *)); -extern datum sdbm_fetch proto((DBM *, datum)); -extern int sdbm_delete proto((DBM *, datum)); -extern int sdbm_store proto((DBM *, datum, datum, int)); -extern datum sdbm_firstkey proto((DBM *)); -extern datum sdbm_nextkey proto((DBM *)); - -/* - * other - */ -extern DBM *sdbm_prep proto((char *, char *, int, int)); -extern long sdbm_hash proto((char *, int)); - -#endif /* _SDBM_H_ */ diff --git a/ruby/ext/socket/ancdata.c b/ruby/ext/socket/ancdata.c index 84463af06..aa62cab0e 100644 --- a/ruby/ext/socket/ancdata.c +++ b/ruby/ext/socket/ancdata.c @@ -2,7 +2,6 @@ #include -int rsock_cmsg_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ static VALUE sym_wait_readable, sym_wait_writable; #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) @@ -89,9 +88,9 @@ ancillary_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE static VALUE ancdata_new(int family, int level, int type, VALUE data) { - NEWOBJ_OF(obj, struct RObject, rb_cAncillaryData, T_OBJECT); + VALUE obj = rb_obj_alloc(rb_cAncillaryData); StringValue(data); - ancillary_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data); + ancillary_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data); return (VALUE)obj; } @@ -852,6 +851,12 @@ anc_inspect_ipv6_pktinfo(int level, int type, VALUE data, VALUE ret) } #endif +#ifdef HAVE_GMTIME_R +# define LOCALTIME(time, tm) localtime_r(&(time), &(tm)) +#else +# define LOCALTIME(time, tm) ((tm) = *localtime(&(time))) +#endif + #if defined(SCM_TIMESTAMP) /* GNU/Linux, FreeBSD, NetBSD, OpenBSD, MacOS X, Solaris */ static int inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret) @@ -863,7 +868,7 @@ inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret) char buf[32]; memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv)); time = tv.tv_sec; - tm = *localtime(&time); + LOCALTIME(time, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); rb_str_catf(ret, " %s.%06ld", buf, (long)tv.tv_usec); return 1; @@ -883,7 +888,7 @@ inspect_timespec_as_abstime(int level, int optname, VALUE data, VALUE ret) struct tm tm; char buf[32]; memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts)); - tm = *localtime(&ts.tv_sec); + LOCALTIME(ts.tv_sec, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); rb_str_catf(ret, " %s.%09ld", buf, (long)ts.tv_nsec); return 1; @@ -907,7 +912,7 @@ inspect_bintime_as_abstime(int level, int optname, VALUE data, VALUE ret) uint64_t res_h, res_l; char buf[32]; memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt)); - tm = *localtime(&bt.sec); + LOCALTIME(bt.sec, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); /* res_h = frac * 10**19 / 2**64 */ @@ -1280,7 +1285,7 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, if (ss == -1) { int e; - if (!nonblock && rb_io_wait_writable(fptr->fd)) { + if (!nonblock && rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) { rb_io_check_closed(fptr); goto retry; } @@ -1429,10 +1434,7 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end) if (fstat(fd, &stbuf) == -1) rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS"); rb_update_max_fd(fd); - if (rsock_cmsg_cloexec_state < 0) - rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd); - if (rsock_cmsg_cloexec_state == 0 || fd <= 2) - rb_maygvl_fd_fix_cloexec(fd); + rb_maygvl_fd_fix_cloexec(fd); if (S_ISSOCK(stbuf.st_mode)) io = rsock_init_sock(rb_obj_alloc(rb_cSocket), fd); else @@ -1555,7 +1557,7 @@ bsock_recvmsg_internal(VALUE sock, if (ss == -1) { int e; - if (!nonblock && rb_io_wait_readable(fptr->fd)) { + if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, Qnil)) { rb_io_check_closed(fptr); goto retry; } diff --git a/ruby/ext/socket/basicsocket.c b/ruby/ext/socket/basicsocket.c index fb5beed81..44fb7a4eb 100644 --- a/ruby/ext/socket/basicsocket.c +++ b/ruby/ext/socket/basicsocket.c @@ -10,6 +10,28 @@ #include "rubysocket.h" +#ifdef _WIN32 +#define is_socket(fd) rb_w32_is_socket(fd) +#else +static int +is_socket(int fd) +{ + struct stat sbuf; + + if (fstat(fd, &sbuf) < 0) + rb_sys_fail("fstat(2)"); + return S_ISSOCK(sbuf.st_mode); +} +#endif + +static void +rsock_validate_descriptor(int descriptor) +{ + if (!is_socket(descriptor) || rb_reserved_fd_p(descriptor)) { + rb_syserr_fail(EBADF, "not a socket file descriptor"); + } +} + /* * call-seq: * BasicSocket.for_fd(fd) => basicsocket @@ -22,10 +44,14 @@ * */ static VALUE -bsock_s_for_fd(VALUE klass, VALUE fd) +bsock_s_for_fd(VALUE klass, VALUE _descriptor) { rb_io_t *fptr; - VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd)); + + int descriptor = RB_NUM2INT(_descriptor); + rsock_validate_descriptor(descriptor); + + VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor); GetOpenFile(sock, fptr); @@ -280,7 +306,7 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock) * ipttl = sock.getsockopt(:IP, :TTL).int * * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) - * ipttl = optval.unpack("i")[0] + * ipttl = optval.unpack1("i") * * Option values may be structs. Decoding them can be complex as it involves * examining your system headers to determine the correct definition. An @@ -537,12 +563,11 @@ bsock_remote_address(VALUE sock) * } */ VALUE -rsock_bsock_send(int argc, VALUE *argv, VALUE sock) +rsock_bsock_send(int argc, VALUE *argv, VALUE socket) { struct rsock_send_arg arg; VALUE flags, to; rb_io_t *fptr; - ssize_t n; rb_blocking_function_t *func; const char *funcname; @@ -550,28 +575,38 @@ rsock_bsock_send(int argc, VALUE *argv, VALUE sock) StringValue(arg.mesg); if (!NIL_P(to)) { - SockAddrStringValue(to); - to = rb_str_new4(to); - arg.to = (struct sockaddr *)RSTRING_PTR(to); - arg.tolen = RSTRING_SOCKLEN(to); - func = rsock_sendto_blocking; - funcname = "sendto(2)"; + SockAddrStringValue(to); + to = rb_str_new4(to); + arg.to = (struct sockaddr *)RSTRING_PTR(to); + arg.tolen = RSTRING_SOCKLEN(to); + func = rsock_sendto_blocking; + funcname = "sendto(2)"; } else { - func = rsock_send_blocking; - funcname = "send(2)"; + func = rsock_send_blocking; + funcname = "send(2)"; } - GetOpenFile(sock, fptr); + + RB_IO_POINTER(socket, fptr); + arg.fd = fptr->fd; arg.flags = NUM2INT(flags); - while (rsock_maybe_fd_writable(arg.fd), - (n = (ssize_t)BLOCKING_REGION_FD(func, &arg)) < 0) { - if (rb_io_wait_writable(arg.fd)) { - continue; - } - rb_sys_fail(funcname); + + while (true) { +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil); +#endif + + ssize_t n = (ssize_t)BLOCKING_REGION_FD(func, &arg); + + if (n >= 0) return SSIZET2NUM(n); + + if (rb_io_maybe_wait_writable(errno, socket, Qnil)) { + continue; + } + + rb_sys_fail(funcname); } - return SSIZET2NUM(n); } /* diff --git a/ruby/ext/socket/depend b/ruby/ext/socket/depend index e958b3dc5..99617e253 100644 --- a/ruby/ext/socket/depend +++ b/ruby/ext/socket/depend @@ -12,12 +12,169 @@ constdefs.c: constdefs.h # AUTOGENERATED DEPENDENCIES START ancdata.o: $(RUBY_EXTCONF_H) ancdata.o: $(arch_hdrdir)/ruby/config.h -ancdata.o: $(hdrdir)/ruby.h ancdata.o: $(hdrdir)/ruby/assert.h ancdata.o: $(hdrdir)/ruby/backward.h +ancdata.o: $(hdrdir)/ruby/backward/2/assume.h +ancdata.o: $(hdrdir)/ruby/backward/2/attributes.h +ancdata.o: $(hdrdir)/ruby/backward/2/bool.h +ancdata.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ancdata.o: $(hdrdir)/ruby/backward/2/inttypes.h +ancdata.o: $(hdrdir)/ruby/backward/2/limits.h +ancdata.o: $(hdrdir)/ruby/backward/2/long_long.h +ancdata.o: $(hdrdir)/ruby/backward/2/stdalign.h +ancdata.o: $(hdrdir)/ruby/backward/2/stdarg.h ancdata.o: $(hdrdir)/ruby/defines.h ancdata.o: $(hdrdir)/ruby/encoding.h +ancdata.o: $(hdrdir)/ruby/fiber/scheduler.h ancdata.o: $(hdrdir)/ruby/intern.h +ancdata.o: $(hdrdir)/ruby/internal/anyargs.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ancdata.o: $(hdrdir)/ruby/internal/assume.h +ancdata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ancdata.o: $(hdrdir)/ruby/internal/attr/artificial.h +ancdata.o: $(hdrdir)/ruby/internal/attr/cold.h +ancdata.o: $(hdrdir)/ruby/internal/attr/const.h +ancdata.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ancdata.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ancdata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ancdata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ancdata.o: $(hdrdir)/ruby/internal/attr/error.h +ancdata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ancdata.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ancdata.o: $(hdrdir)/ruby/internal/attr/format.h +ancdata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noalias.h +ancdata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noinline.h +ancdata.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ancdata.o: $(hdrdir)/ruby/internal/attr/pure.h +ancdata.o: $(hdrdir)/ruby/internal/attr/restrict.h +ancdata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ancdata.o: $(hdrdir)/ruby/internal/attr/warning.h +ancdata.o: $(hdrdir)/ruby/internal/attr/weakref.h +ancdata.o: $(hdrdir)/ruby/internal/cast.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_since.h +ancdata.o: $(hdrdir)/ruby/internal/config.h +ancdata.o: $(hdrdir)/ruby/internal/constant_p.h +ancdata.o: $(hdrdir)/ruby/internal/core.h +ancdata.o: $(hdrdir)/ruby/internal/core/rarray.h +ancdata.o: $(hdrdir)/ruby/internal/core/rbasic.h +ancdata.o: $(hdrdir)/ruby/internal/core/rbignum.h +ancdata.o: $(hdrdir)/ruby/internal/core/rclass.h +ancdata.o: $(hdrdir)/ruby/internal/core/rdata.h +ancdata.o: $(hdrdir)/ruby/internal/core/rfile.h +ancdata.o: $(hdrdir)/ruby/internal/core/rhash.h +ancdata.o: $(hdrdir)/ruby/internal/core/robject.h +ancdata.o: $(hdrdir)/ruby/internal/core/rregexp.h +ancdata.o: $(hdrdir)/ruby/internal/core/rstring.h +ancdata.o: $(hdrdir)/ruby/internal/core/rstruct.h +ancdata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ancdata.o: $(hdrdir)/ruby/internal/ctype.h +ancdata.o: $(hdrdir)/ruby/internal/dllexport.h +ancdata.o: $(hdrdir)/ruby/internal/dosish.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/re.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/string.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ancdata.o: $(hdrdir)/ruby/internal/error.h +ancdata.o: $(hdrdir)/ruby/internal/eval.h +ancdata.o: $(hdrdir)/ruby/internal/event.h +ancdata.o: $(hdrdir)/ruby/internal/fl_type.h +ancdata.o: $(hdrdir)/ruby/internal/gc.h +ancdata.o: $(hdrdir)/ruby/internal/glob.h +ancdata.o: $(hdrdir)/ruby/internal/globals.h +ancdata.o: $(hdrdir)/ruby/internal/has/attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/builtin.h +ancdata.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/extension.h +ancdata.o: $(hdrdir)/ruby/internal/has/feature.h +ancdata.o: $(hdrdir)/ruby/internal/has/warning.h +ancdata.o: $(hdrdir)/ruby/internal/intern/array.h +ancdata.o: $(hdrdir)/ruby/internal/intern/bignum.h +ancdata.o: $(hdrdir)/ruby/internal/intern/class.h +ancdata.o: $(hdrdir)/ruby/internal/intern/compar.h +ancdata.o: $(hdrdir)/ruby/internal/intern/complex.h +ancdata.o: $(hdrdir)/ruby/internal/intern/cont.h +ancdata.o: $(hdrdir)/ruby/internal/intern/dir.h +ancdata.o: $(hdrdir)/ruby/internal/intern/enum.h +ancdata.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ancdata.o: $(hdrdir)/ruby/internal/intern/error.h +ancdata.o: $(hdrdir)/ruby/internal/intern/eval.h +ancdata.o: $(hdrdir)/ruby/internal/intern/file.h +ancdata.o: $(hdrdir)/ruby/internal/intern/gc.h +ancdata.o: $(hdrdir)/ruby/internal/intern/hash.h +ancdata.o: $(hdrdir)/ruby/internal/intern/io.h +ancdata.o: $(hdrdir)/ruby/internal/intern/load.h +ancdata.o: $(hdrdir)/ruby/internal/intern/marshal.h +ancdata.o: $(hdrdir)/ruby/internal/intern/numeric.h +ancdata.o: $(hdrdir)/ruby/internal/intern/object.h +ancdata.o: $(hdrdir)/ruby/internal/intern/parse.h +ancdata.o: $(hdrdir)/ruby/internal/intern/proc.h +ancdata.o: $(hdrdir)/ruby/internal/intern/process.h +ancdata.o: $(hdrdir)/ruby/internal/intern/random.h +ancdata.o: $(hdrdir)/ruby/internal/intern/range.h +ancdata.o: $(hdrdir)/ruby/internal/intern/rational.h +ancdata.o: $(hdrdir)/ruby/internal/intern/re.h +ancdata.o: $(hdrdir)/ruby/internal/intern/ruby.h +ancdata.o: $(hdrdir)/ruby/internal/intern/select.h +ancdata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ancdata.o: $(hdrdir)/ruby/internal/intern/signal.h +ancdata.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ancdata.o: $(hdrdir)/ruby/internal/intern/string.h +ancdata.o: $(hdrdir)/ruby/internal/intern/struct.h +ancdata.o: $(hdrdir)/ruby/internal/intern/thread.h +ancdata.o: $(hdrdir)/ruby/internal/intern/time.h +ancdata.o: $(hdrdir)/ruby/internal/intern/variable.h +ancdata.o: $(hdrdir)/ruby/internal/intern/vm.h +ancdata.o: $(hdrdir)/ruby/internal/interpreter.h +ancdata.o: $(hdrdir)/ruby/internal/iterator.h +ancdata.o: $(hdrdir)/ruby/internal/memory.h +ancdata.o: $(hdrdir)/ruby/internal/method.h +ancdata.o: $(hdrdir)/ruby/internal/module.h +ancdata.o: $(hdrdir)/ruby/internal/newobj.h +ancdata.o: $(hdrdir)/ruby/internal/rgengc.h +ancdata.o: $(hdrdir)/ruby/internal/scan_args.h +ancdata.o: $(hdrdir)/ruby/internal/special_consts.h +ancdata.o: $(hdrdir)/ruby/internal/static_assert.h +ancdata.o: $(hdrdir)/ruby/internal/stdalign.h +ancdata.o: $(hdrdir)/ruby/internal/stdbool.h +ancdata.o: $(hdrdir)/ruby/internal/symbol.h +ancdata.o: $(hdrdir)/ruby/internal/value.h +ancdata.o: $(hdrdir)/ruby/internal/value_type.h +ancdata.o: $(hdrdir)/ruby/internal/variable.h +ancdata.o: $(hdrdir)/ruby/internal/warning_push.h +ancdata.o: $(hdrdir)/ruby/internal/xmalloc.h ancdata.o: $(hdrdir)/ruby/io.h ancdata.o: $(hdrdir)/ruby/missing.h ancdata.o: $(hdrdir)/ruby/onigmo.h @@ -28,18 +185,186 @@ ancdata.o: $(hdrdir)/ruby/subst.h ancdata.o: $(hdrdir)/ruby/thread.h ancdata.o: $(hdrdir)/ruby/util.h ancdata.o: $(top_srcdir)/internal.h +ancdata.o: $(top_srcdir)/internal/array.h +ancdata.o: $(top_srcdir)/internal/compilers.h +ancdata.o: $(top_srcdir)/internal/error.h +ancdata.o: $(top_srcdir)/internal/gc.h +ancdata.o: $(top_srcdir)/internal/io.h +ancdata.o: $(top_srcdir)/internal/serial.h +ancdata.o: $(top_srcdir)/internal/static_assert.h +ancdata.o: $(top_srcdir)/internal/string.h +ancdata.o: $(top_srcdir)/internal/thread.h +ancdata.o: $(top_srcdir)/internal/vm.h +ancdata.o: $(top_srcdir)/internal/warnings.h ancdata.o: ancdata.c ancdata.o: constdefs.h ancdata.o: rubysocket.h ancdata.o: sockport.h basicsocket.o: $(RUBY_EXTCONF_H) basicsocket.o: $(arch_hdrdir)/ruby/config.h -basicsocket.o: $(hdrdir)/ruby.h basicsocket.o: $(hdrdir)/ruby/assert.h basicsocket.o: $(hdrdir)/ruby/backward.h +basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h +basicsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +basicsocket.o: $(hdrdir)/ruby/backward/2/bool.h +basicsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +basicsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +basicsocket.o: $(hdrdir)/ruby/backward/2/limits.h +basicsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +basicsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +basicsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h basicsocket.o: $(hdrdir)/ruby/defines.h basicsocket.o: $(hdrdir)/ruby/encoding.h +basicsocket.o: $(hdrdir)/ruby/fiber/scheduler.h basicsocket.o: $(hdrdir)/ruby/intern.h +basicsocket.o: $(hdrdir)/ruby/internal/anyargs.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/assume.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/const.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/error.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/format.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +basicsocket.o: $(hdrdir)/ruby/internal/cast.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +basicsocket.o: $(hdrdir)/ruby/internal/config.h +basicsocket.o: $(hdrdir)/ruby/internal/constant_p.h +basicsocket.o: $(hdrdir)/ruby/internal/core.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +basicsocket.o: $(hdrdir)/ruby/internal/core/robject.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +basicsocket.o: $(hdrdir)/ruby/internal/ctype.h +basicsocket.o: $(hdrdir)/ruby/internal/dllexport.h +basicsocket.o: $(hdrdir)/ruby/internal/dosish.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +basicsocket.o: $(hdrdir)/ruby/internal/error.h +basicsocket.o: $(hdrdir)/ruby/internal/eval.h +basicsocket.o: $(hdrdir)/ruby/internal/event.h +basicsocket.o: $(hdrdir)/ruby/internal/fl_type.h +basicsocket.o: $(hdrdir)/ruby/internal/gc.h +basicsocket.o: $(hdrdir)/ruby/internal/glob.h +basicsocket.o: $(hdrdir)/ruby/internal/globals.h +basicsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +basicsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/extension.h +basicsocket.o: $(hdrdir)/ruby/internal/has/feature.h +basicsocket.o: $(hdrdir)/ruby/internal/has/warning.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/array.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/class.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/error.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/file.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/gc.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/io.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/load.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/object.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/process.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/random.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/range.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/re.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/select.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/string.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/time.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +basicsocket.o: $(hdrdir)/ruby/internal/interpreter.h +basicsocket.o: $(hdrdir)/ruby/internal/iterator.h +basicsocket.o: $(hdrdir)/ruby/internal/memory.h +basicsocket.o: $(hdrdir)/ruby/internal/method.h +basicsocket.o: $(hdrdir)/ruby/internal/module.h +basicsocket.o: $(hdrdir)/ruby/internal/newobj.h +basicsocket.o: $(hdrdir)/ruby/internal/rgengc.h +basicsocket.o: $(hdrdir)/ruby/internal/scan_args.h +basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h +basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h +basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h +basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h +basicsocket.o: $(hdrdir)/ruby/internal/symbol.h +basicsocket.o: $(hdrdir)/ruby/internal/value.h +basicsocket.o: $(hdrdir)/ruby/internal/value_type.h +basicsocket.o: $(hdrdir)/ruby/internal/variable.h +basicsocket.o: $(hdrdir)/ruby/internal/warning_push.h +basicsocket.o: $(hdrdir)/ruby/internal/xmalloc.h basicsocket.o: $(hdrdir)/ruby/io.h basicsocket.o: $(hdrdir)/ruby/missing.h basicsocket.o: $(hdrdir)/ruby/onigmo.h @@ -50,18 +375,186 @@ basicsocket.o: $(hdrdir)/ruby/subst.h basicsocket.o: $(hdrdir)/ruby/thread.h basicsocket.o: $(hdrdir)/ruby/util.h basicsocket.o: $(top_srcdir)/internal.h +basicsocket.o: $(top_srcdir)/internal/array.h +basicsocket.o: $(top_srcdir)/internal/compilers.h +basicsocket.o: $(top_srcdir)/internal/error.h +basicsocket.o: $(top_srcdir)/internal/gc.h +basicsocket.o: $(top_srcdir)/internal/io.h +basicsocket.o: $(top_srcdir)/internal/serial.h +basicsocket.o: $(top_srcdir)/internal/static_assert.h +basicsocket.o: $(top_srcdir)/internal/string.h +basicsocket.o: $(top_srcdir)/internal/thread.h +basicsocket.o: $(top_srcdir)/internal/vm.h +basicsocket.o: $(top_srcdir)/internal/warnings.h basicsocket.o: basicsocket.c basicsocket.o: constdefs.h basicsocket.o: rubysocket.h basicsocket.o: sockport.h constants.o: $(RUBY_EXTCONF_H) constants.o: $(arch_hdrdir)/ruby/config.h -constants.o: $(hdrdir)/ruby.h constants.o: $(hdrdir)/ruby/assert.h constants.o: $(hdrdir)/ruby/backward.h +constants.o: $(hdrdir)/ruby/backward/2/assume.h +constants.o: $(hdrdir)/ruby/backward/2/attributes.h +constants.o: $(hdrdir)/ruby/backward/2/bool.h +constants.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +constants.o: $(hdrdir)/ruby/backward/2/inttypes.h +constants.o: $(hdrdir)/ruby/backward/2/limits.h +constants.o: $(hdrdir)/ruby/backward/2/long_long.h +constants.o: $(hdrdir)/ruby/backward/2/stdalign.h +constants.o: $(hdrdir)/ruby/backward/2/stdarg.h constants.o: $(hdrdir)/ruby/defines.h constants.o: $(hdrdir)/ruby/encoding.h +constants.o: $(hdrdir)/ruby/fiber/scheduler.h constants.o: $(hdrdir)/ruby/intern.h +constants.o: $(hdrdir)/ruby/internal/anyargs.h +constants.o: $(hdrdir)/ruby/internal/arithmetic.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/char.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/double.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/int.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/long.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/short.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +constants.o: $(hdrdir)/ruby/internal/assume.h +constants.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +constants.o: $(hdrdir)/ruby/internal/attr/artificial.h +constants.o: $(hdrdir)/ruby/internal/attr/cold.h +constants.o: $(hdrdir)/ruby/internal/attr/const.h +constants.o: $(hdrdir)/ruby/internal/attr/constexpr.h +constants.o: $(hdrdir)/ruby/internal/attr/deprecated.h +constants.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +constants.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +constants.o: $(hdrdir)/ruby/internal/attr/error.h +constants.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +constants.o: $(hdrdir)/ruby/internal/attr/forceinline.h +constants.o: $(hdrdir)/ruby/internal/attr/format.h +constants.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +constants.o: $(hdrdir)/ruby/internal/attr/noalias.h +constants.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +constants.o: $(hdrdir)/ruby/internal/attr/noexcept.h +constants.o: $(hdrdir)/ruby/internal/attr/noinline.h +constants.o: $(hdrdir)/ruby/internal/attr/nonnull.h +constants.o: $(hdrdir)/ruby/internal/attr/noreturn.h +constants.o: $(hdrdir)/ruby/internal/attr/pure.h +constants.o: $(hdrdir)/ruby/internal/attr/restrict.h +constants.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +constants.o: $(hdrdir)/ruby/internal/attr/warning.h +constants.o: $(hdrdir)/ruby/internal/attr/weakref.h +constants.o: $(hdrdir)/ruby/internal/cast.h +constants.o: $(hdrdir)/ruby/internal/compiler_is.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +constants.o: $(hdrdir)/ruby/internal/compiler_since.h +constants.o: $(hdrdir)/ruby/internal/config.h +constants.o: $(hdrdir)/ruby/internal/constant_p.h +constants.o: $(hdrdir)/ruby/internal/core.h +constants.o: $(hdrdir)/ruby/internal/core/rarray.h +constants.o: $(hdrdir)/ruby/internal/core/rbasic.h +constants.o: $(hdrdir)/ruby/internal/core/rbignum.h +constants.o: $(hdrdir)/ruby/internal/core/rclass.h +constants.o: $(hdrdir)/ruby/internal/core/rdata.h +constants.o: $(hdrdir)/ruby/internal/core/rfile.h +constants.o: $(hdrdir)/ruby/internal/core/rhash.h +constants.o: $(hdrdir)/ruby/internal/core/robject.h +constants.o: $(hdrdir)/ruby/internal/core/rregexp.h +constants.o: $(hdrdir)/ruby/internal/core/rstring.h +constants.o: $(hdrdir)/ruby/internal/core/rstruct.h +constants.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +constants.o: $(hdrdir)/ruby/internal/ctype.h +constants.o: $(hdrdir)/ruby/internal/dllexport.h +constants.o: $(hdrdir)/ruby/internal/dosish.h +constants.o: $(hdrdir)/ruby/internal/encoding/coderange.h +constants.o: $(hdrdir)/ruby/internal/encoding/ctype.h +constants.o: $(hdrdir)/ruby/internal/encoding/encoding.h +constants.o: $(hdrdir)/ruby/internal/encoding/pathname.h +constants.o: $(hdrdir)/ruby/internal/encoding/re.h +constants.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +constants.o: $(hdrdir)/ruby/internal/encoding/string.h +constants.o: $(hdrdir)/ruby/internal/encoding/symbol.h +constants.o: $(hdrdir)/ruby/internal/encoding/transcode.h +constants.o: $(hdrdir)/ruby/internal/error.h +constants.o: $(hdrdir)/ruby/internal/eval.h +constants.o: $(hdrdir)/ruby/internal/event.h +constants.o: $(hdrdir)/ruby/internal/fl_type.h +constants.o: $(hdrdir)/ruby/internal/gc.h +constants.o: $(hdrdir)/ruby/internal/glob.h +constants.o: $(hdrdir)/ruby/internal/globals.h +constants.o: $(hdrdir)/ruby/internal/has/attribute.h +constants.o: $(hdrdir)/ruby/internal/has/builtin.h +constants.o: $(hdrdir)/ruby/internal/has/c_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/extension.h +constants.o: $(hdrdir)/ruby/internal/has/feature.h +constants.o: $(hdrdir)/ruby/internal/has/warning.h +constants.o: $(hdrdir)/ruby/internal/intern/array.h +constants.o: $(hdrdir)/ruby/internal/intern/bignum.h +constants.o: $(hdrdir)/ruby/internal/intern/class.h +constants.o: $(hdrdir)/ruby/internal/intern/compar.h +constants.o: $(hdrdir)/ruby/internal/intern/complex.h +constants.o: $(hdrdir)/ruby/internal/intern/cont.h +constants.o: $(hdrdir)/ruby/internal/intern/dir.h +constants.o: $(hdrdir)/ruby/internal/intern/enum.h +constants.o: $(hdrdir)/ruby/internal/intern/enumerator.h +constants.o: $(hdrdir)/ruby/internal/intern/error.h +constants.o: $(hdrdir)/ruby/internal/intern/eval.h +constants.o: $(hdrdir)/ruby/internal/intern/file.h +constants.o: $(hdrdir)/ruby/internal/intern/gc.h +constants.o: $(hdrdir)/ruby/internal/intern/hash.h +constants.o: $(hdrdir)/ruby/internal/intern/io.h +constants.o: $(hdrdir)/ruby/internal/intern/load.h +constants.o: $(hdrdir)/ruby/internal/intern/marshal.h +constants.o: $(hdrdir)/ruby/internal/intern/numeric.h +constants.o: $(hdrdir)/ruby/internal/intern/object.h +constants.o: $(hdrdir)/ruby/internal/intern/parse.h +constants.o: $(hdrdir)/ruby/internal/intern/proc.h +constants.o: $(hdrdir)/ruby/internal/intern/process.h +constants.o: $(hdrdir)/ruby/internal/intern/random.h +constants.o: $(hdrdir)/ruby/internal/intern/range.h +constants.o: $(hdrdir)/ruby/internal/intern/rational.h +constants.o: $(hdrdir)/ruby/internal/intern/re.h +constants.o: $(hdrdir)/ruby/internal/intern/ruby.h +constants.o: $(hdrdir)/ruby/internal/intern/select.h +constants.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +constants.o: $(hdrdir)/ruby/internal/intern/signal.h +constants.o: $(hdrdir)/ruby/internal/intern/sprintf.h +constants.o: $(hdrdir)/ruby/internal/intern/string.h +constants.o: $(hdrdir)/ruby/internal/intern/struct.h +constants.o: $(hdrdir)/ruby/internal/intern/thread.h +constants.o: $(hdrdir)/ruby/internal/intern/time.h +constants.o: $(hdrdir)/ruby/internal/intern/variable.h +constants.o: $(hdrdir)/ruby/internal/intern/vm.h +constants.o: $(hdrdir)/ruby/internal/interpreter.h +constants.o: $(hdrdir)/ruby/internal/iterator.h +constants.o: $(hdrdir)/ruby/internal/memory.h +constants.o: $(hdrdir)/ruby/internal/method.h +constants.o: $(hdrdir)/ruby/internal/module.h +constants.o: $(hdrdir)/ruby/internal/newobj.h +constants.o: $(hdrdir)/ruby/internal/rgengc.h +constants.o: $(hdrdir)/ruby/internal/scan_args.h +constants.o: $(hdrdir)/ruby/internal/special_consts.h +constants.o: $(hdrdir)/ruby/internal/static_assert.h +constants.o: $(hdrdir)/ruby/internal/stdalign.h +constants.o: $(hdrdir)/ruby/internal/stdbool.h +constants.o: $(hdrdir)/ruby/internal/symbol.h +constants.o: $(hdrdir)/ruby/internal/value.h +constants.o: $(hdrdir)/ruby/internal/value_type.h +constants.o: $(hdrdir)/ruby/internal/variable.h +constants.o: $(hdrdir)/ruby/internal/warning_push.h +constants.o: $(hdrdir)/ruby/internal/xmalloc.h constants.o: $(hdrdir)/ruby/io.h constants.o: $(hdrdir)/ruby/missing.h constants.o: $(hdrdir)/ruby/onigmo.h @@ -72,6 +565,17 @@ constants.o: $(hdrdir)/ruby/subst.h constants.o: $(hdrdir)/ruby/thread.h constants.o: $(hdrdir)/ruby/util.h constants.o: $(top_srcdir)/internal.h +constants.o: $(top_srcdir)/internal/array.h +constants.o: $(top_srcdir)/internal/compilers.h +constants.o: $(top_srcdir)/internal/error.h +constants.o: $(top_srcdir)/internal/gc.h +constants.o: $(top_srcdir)/internal/io.h +constants.o: $(top_srcdir)/internal/serial.h +constants.o: $(top_srcdir)/internal/static_assert.h +constants.o: $(top_srcdir)/internal/string.h +constants.o: $(top_srcdir)/internal/thread.h +constants.o: $(top_srcdir)/internal/vm.h +constants.o: $(top_srcdir)/internal/warnings.h constants.o: constants.c constants.o: constdefs.c constants.o: constdefs.h @@ -79,12 +583,169 @@ constants.o: rubysocket.h constants.o: sockport.h ifaddr.o: $(RUBY_EXTCONF_H) ifaddr.o: $(arch_hdrdir)/ruby/config.h -ifaddr.o: $(hdrdir)/ruby.h ifaddr.o: $(hdrdir)/ruby/assert.h ifaddr.o: $(hdrdir)/ruby/backward.h +ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h +ifaddr.o: $(hdrdir)/ruby/backward/2/attributes.h +ifaddr.o: $(hdrdir)/ruby/backward/2/bool.h +ifaddr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ifaddr.o: $(hdrdir)/ruby/backward/2/inttypes.h +ifaddr.o: $(hdrdir)/ruby/backward/2/limits.h +ifaddr.o: $(hdrdir)/ruby/backward/2/long_long.h +ifaddr.o: $(hdrdir)/ruby/backward/2/stdalign.h +ifaddr.o: $(hdrdir)/ruby/backward/2/stdarg.h ifaddr.o: $(hdrdir)/ruby/defines.h ifaddr.o: $(hdrdir)/ruby/encoding.h +ifaddr.o: $(hdrdir)/ruby/fiber/scheduler.h ifaddr.o: $(hdrdir)/ruby/intern.h +ifaddr.o: $(hdrdir)/ruby/internal/anyargs.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/assume.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/artificial.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/cold.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/const.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/error.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/format.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noalias.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noinline.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/pure.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/restrict.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/warning.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/weakref.h +ifaddr.o: $(hdrdir)/ruby/internal/cast.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_since.h +ifaddr.o: $(hdrdir)/ruby/internal/config.h +ifaddr.o: $(hdrdir)/ruby/internal/constant_p.h +ifaddr.o: $(hdrdir)/ruby/internal/core.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rarray.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rbasic.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rbignum.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rclass.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rdata.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rfile.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rhash.h +ifaddr.o: $(hdrdir)/ruby/internal/core/robject.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rregexp.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rstring.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rstruct.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ifaddr.o: $(hdrdir)/ruby/internal/ctype.h +ifaddr.o: $(hdrdir)/ruby/internal/dllexport.h +ifaddr.o: $(hdrdir)/ruby/internal/dosish.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/re.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/string.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ifaddr.o: $(hdrdir)/ruby/internal/error.h +ifaddr.o: $(hdrdir)/ruby/internal/eval.h +ifaddr.o: $(hdrdir)/ruby/internal/event.h +ifaddr.o: $(hdrdir)/ruby/internal/fl_type.h +ifaddr.o: $(hdrdir)/ruby/internal/gc.h +ifaddr.o: $(hdrdir)/ruby/internal/glob.h +ifaddr.o: $(hdrdir)/ruby/internal/globals.h +ifaddr.o: $(hdrdir)/ruby/internal/has/attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/builtin.h +ifaddr.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/extension.h +ifaddr.o: $(hdrdir)/ruby/internal/has/feature.h +ifaddr.o: $(hdrdir)/ruby/internal/has/warning.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/array.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/bignum.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/class.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/compar.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/complex.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/cont.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/dir.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/enum.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/error.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/eval.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/file.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/gc.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/hash.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/io.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/load.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/marshal.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/numeric.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/object.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/parse.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/proc.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/process.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/random.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/range.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/rational.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/re.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/ruby.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/select.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/signal.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/string.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/struct.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/thread.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/time.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/variable.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/vm.h +ifaddr.o: $(hdrdir)/ruby/internal/interpreter.h +ifaddr.o: $(hdrdir)/ruby/internal/iterator.h +ifaddr.o: $(hdrdir)/ruby/internal/memory.h +ifaddr.o: $(hdrdir)/ruby/internal/method.h +ifaddr.o: $(hdrdir)/ruby/internal/module.h +ifaddr.o: $(hdrdir)/ruby/internal/newobj.h +ifaddr.o: $(hdrdir)/ruby/internal/rgengc.h +ifaddr.o: $(hdrdir)/ruby/internal/scan_args.h +ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h +ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h +ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h +ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h +ifaddr.o: $(hdrdir)/ruby/internal/symbol.h +ifaddr.o: $(hdrdir)/ruby/internal/value.h +ifaddr.o: $(hdrdir)/ruby/internal/value_type.h +ifaddr.o: $(hdrdir)/ruby/internal/variable.h +ifaddr.o: $(hdrdir)/ruby/internal/warning_push.h +ifaddr.o: $(hdrdir)/ruby/internal/xmalloc.h ifaddr.o: $(hdrdir)/ruby/io.h ifaddr.o: $(hdrdir)/ruby/missing.h ifaddr.o: $(hdrdir)/ruby/onigmo.h @@ -95,18 +756,186 @@ ifaddr.o: $(hdrdir)/ruby/subst.h ifaddr.o: $(hdrdir)/ruby/thread.h ifaddr.o: $(hdrdir)/ruby/util.h ifaddr.o: $(top_srcdir)/internal.h +ifaddr.o: $(top_srcdir)/internal/array.h +ifaddr.o: $(top_srcdir)/internal/compilers.h +ifaddr.o: $(top_srcdir)/internal/error.h +ifaddr.o: $(top_srcdir)/internal/gc.h +ifaddr.o: $(top_srcdir)/internal/io.h +ifaddr.o: $(top_srcdir)/internal/serial.h +ifaddr.o: $(top_srcdir)/internal/static_assert.h +ifaddr.o: $(top_srcdir)/internal/string.h +ifaddr.o: $(top_srcdir)/internal/thread.h +ifaddr.o: $(top_srcdir)/internal/vm.h +ifaddr.o: $(top_srcdir)/internal/warnings.h ifaddr.o: constdefs.h ifaddr.o: ifaddr.c ifaddr.o: rubysocket.h ifaddr.o: sockport.h 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/gcc_version_since.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/encoding.h +init.o: $(hdrdir)/ruby/fiber/scheduler.h init.o: $(hdrdir)/ruby/intern.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/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/encoding/coderange.h +init.o: $(hdrdir)/ruby/internal/encoding/ctype.h +init.o: $(hdrdir)/ruby/internal/encoding/encoding.h +init.o: $(hdrdir)/ruby/internal/encoding/pathname.h +init.o: $(hdrdir)/ruby/internal/encoding/re.h +init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +init.o: $(hdrdir)/ruby/internal/encoding/string.h +init.o: $(hdrdir)/ruby/internal/encoding/symbol.h +init.o: $(hdrdir)/ruby/internal/encoding/transcode.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/gc.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/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/rgengc.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/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/io.h init.o: $(hdrdir)/ruby/missing.h init.o: $(hdrdir)/ruby/onigmo.h @@ -117,18 +946,186 @@ init.o: $(hdrdir)/ruby/subst.h init.o: $(hdrdir)/ruby/thread.h init.o: $(hdrdir)/ruby/util.h init.o: $(top_srcdir)/internal.h +init.o: $(top_srcdir)/internal/array.h +init.o: $(top_srcdir)/internal/compilers.h +init.o: $(top_srcdir)/internal/error.h +init.o: $(top_srcdir)/internal/gc.h +init.o: $(top_srcdir)/internal/io.h +init.o: $(top_srcdir)/internal/serial.h +init.o: $(top_srcdir)/internal/static_assert.h +init.o: $(top_srcdir)/internal/string.h +init.o: $(top_srcdir)/internal/thread.h +init.o: $(top_srcdir)/internal/vm.h +init.o: $(top_srcdir)/internal/warnings.h init.o: constdefs.h init.o: init.c init.o: rubysocket.h init.o: sockport.h ipsocket.o: $(RUBY_EXTCONF_H) ipsocket.o: $(arch_hdrdir)/ruby/config.h -ipsocket.o: $(hdrdir)/ruby.h ipsocket.o: $(hdrdir)/ruby/assert.h ipsocket.o: $(hdrdir)/ruby/backward.h +ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h +ipsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +ipsocket.o: $(hdrdir)/ruby/backward/2/bool.h +ipsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ipsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +ipsocket.o: $(hdrdir)/ruby/backward/2/limits.h +ipsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +ipsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +ipsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h ipsocket.o: $(hdrdir)/ruby/defines.h ipsocket.o: $(hdrdir)/ruby/encoding.h +ipsocket.o: $(hdrdir)/ruby/fiber/scheduler.h ipsocket.o: $(hdrdir)/ruby/intern.h +ipsocket.o: $(hdrdir)/ruby/internal/anyargs.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/assume.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/const.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/error.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/format.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +ipsocket.o: $(hdrdir)/ruby/internal/cast.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +ipsocket.o: $(hdrdir)/ruby/internal/config.h +ipsocket.o: $(hdrdir)/ruby/internal/constant_p.h +ipsocket.o: $(hdrdir)/ruby/internal/core.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +ipsocket.o: $(hdrdir)/ruby/internal/core/robject.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ipsocket.o: $(hdrdir)/ruby/internal/ctype.h +ipsocket.o: $(hdrdir)/ruby/internal/dllexport.h +ipsocket.o: $(hdrdir)/ruby/internal/dosish.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ipsocket.o: $(hdrdir)/ruby/internal/error.h +ipsocket.o: $(hdrdir)/ruby/internal/eval.h +ipsocket.o: $(hdrdir)/ruby/internal/event.h +ipsocket.o: $(hdrdir)/ruby/internal/fl_type.h +ipsocket.o: $(hdrdir)/ruby/internal/gc.h +ipsocket.o: $(hdrdir)/ruby/internal/glob.h +ipsocket.o: $(hdrdir)/ruby/internal/globals.h +ipsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +ipsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/extension.h +ipsocket.o: $(hdrdir)/ruby/internal/has/feature.h +ipsocket.o: $(hdrdir)/ruby/internal/has/warning.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/array.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/class.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/error.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/file.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/gc.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/io.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/load.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/object.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/process.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/random.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/range.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/re.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/select.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/string.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/time.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +ipsocket.o: $(hdrdir)/ruby/internal/interpreter.h +ipsocket.o: $(hdrdir)/ruby/internal/iterator.h +ipsocket.o: $(hdrdir)/ruby/internal/memory.h +ipsocket.o: $(hdrdir)/ruby/internal/method.h +ipsocket.o: $(hdrdir)/ruby/internal/module.h +ipsocket.o: $(hdrdir)/ruby/internal/newobj.h +ipsocket.o: $(hdrdir)/ruby/internal/rgengc.h +ipsocket.o: $(hdrdir)/ruby/internal/scan_args.h +ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h +ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h +ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h +ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h +ipsocket.o: $(hdrdir)/ruby/internal/symbol.h +ipsocket.o: $(hdrdir)/ruby/internal/value.h +ipsocket.o: $(hdrdir)/ruby/internal/value_type.h +ipsocket.o: $(hdrdir)/ruby/internal/variable.h +ipsocket.o: $(hdrdir)/ruby/internal/warning_push.h +ipsocket.o: $(hdrdir)/ruby/internal/xmalloc.h ipsocket.o: $(hdrdir)/ruby/io.h ipsocket.o: $(hdrdir)/ruby/missing.h ipsocket.o: $(hdrdir)/ruby/onigmo.h @@ -139,18 +1136,186 @@ ipsocket.o: $(hdrdir)/ruby/subst.h ipsocket.o: $(hdrdir)/ruby/thread.h ipsocket.o: $(hdrdir)/ruby/util.h ipsocket.o: $(top_srcdir)/internal.h +ipsocket.o: $(top_srcdir)/internal/array.h +ipsocket.o: $(top_srcdir)/internal/compilers.h +ipsocket.o: $(top_srcdir)/internal/error.h +ipsocket.o: $(top_srcdir)/internal/gc.h +ipsocket.o: $(top_srcdir)/internal/io.h +ipsocket.o: $(top_srcdir)/internal/serial.h +ipsocket.o: $(top_srcdir)/internal/static_assert.h +ipsocket.o: $(top_srcdir)/internal/string.h +ipsocket.o: $(top_srcdir)/internal/thread.h +ipsocket.o: $(top_srcdir)/internal/vm.h +ipsocket.o: $(top_srcdir)/internal/warnings.h ipsocket.o: constdefs.h ipsocket.o: ipsocket.c ipsocket.o: rubysocket.h ipsocket.o: sockport.h option.o: $(RUBY_EXTCONF_H) option.o: $(arch_hdrdir)/ruby/config.h -option.o: $(hdrdir)/ruby.h option.o: $(hdrdir)/ruby/assert.h option.o: $(hdrdir)/ruby/backward.h +option.o: $(hdrdir)/ruby/backward/2/assume.h +option.o: $(hdrdir)/ruby/backward/2/attributes.h +option.o: $(hdrdir)/ruby/backward/2/bool.h +option.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +option.o: $(hdrdir)/ruby/backward/2/inttypes.h +option.o: $(hdrdir)/ruby/backward/2/limits.h +option.o: $(hdrdir)/ruby/backward/2/long_long.h +option.o: $(hdrdir)/ruby/backward/2/stdalign.h +option.o: $(hdrdir)/ruby/backward/2/stdarg.h option.o: $(hdrdir)/ruby/defines.h option.o: $(hdrdir)/ruby/encoding.h +option.o: $(hdrdir)/ruby/fiber/scheduler.h option.o: $(hdrdir)/ruby/intern.h +option.o: $(hdrdir)/ruby/internal/anyargs.h +option.o: $(hdrdir)/ruby/internal/arithmetic.h +option.o: $(hdrdir)/ruby/internal/arithmetic/char.h +option.o: $(hdrdir)/ruby/internal/arithmetic/double.h +option.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +option.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/int.h +option.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/long.h +option.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +option.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/short.h +option.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +option.o: $(hdrdir)/ruby/internal/assume.h +option.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +option.o: $(hdrdir)/ruby/internal/attr/artificial.h +option.o: $(hdrdir)/ruby/internal/attr/cold.h +option.o: $(hdrdir)/ruby/internal/attr/const.h +option.o: $(hdrdir)/ruby/internal/attr/constexpr.h +option.o: $(hdrdir)/ruby/internal/attr/deprecated.h +option.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +option.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +option.o: $(hdrdir)/ruby/internal/attr/error.h +option.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +option.o: $(hdrdir)/ruby/internal/attr/forceinline.h +option.o: $(hdrdir)/ruby/internal/attr/format.h +option.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +option.o: $(hdrdir)/ruby/internal/attr/noalias.h +option.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +option.o: $(hdrdir)/ruby/internal/attr/noexcept.h +option.o: $(hdrdir)/ruby/internal/attr/noinline.h +option.o: $(hdrdir)/ruby/internal/attr/nonnull.h +option.o: $(hdrdir)/ruby/internal/attr/noreturn.h +option.o: $(hdrdir)/ruby/internal/attr/pure.h +option.o: $(hdrdir)/ruby/internal/attr/restrict.h +option.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +option.o: $(hdrdir)/ruby/internal/attr/warning.h +option.o: $(hdrdir)/ruby/internal/attr/weakref.h +option.o: $(hdrdir)/ruby/internal/cast.h +option.o: $(hdrdir)/ruby/internal/compiler_is.h +option.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +option.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +option.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +option.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +option.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +option.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +option.o: $(hdrdir)/ruby/internal/compiler_since.h +option.o: $(hdrdir)/ruby/internal/config.h +option.o: $(hdrdir)/ruby/internal/constant_p.h +option.o: $(hdrdir)/ruby/internal/core.h +option.o: $(hdrdir)/ruby/internal/core/rarray.h +option.o: $(hdrdir)/ruby/internal/core/rbasic.h +option.o: $(hdrdir)/ruby/internal/core/rbignum.h +option.o: $(hdrdir)/ruby/internal/core/rclass.h +option.o: $(hdrdir)/ruby/internal/core/rdata.h +option.o: $(hdrdir)/ruby/internal/core/rfile.h +option.o: $(hdrdir)/ruby/internal/core/rhash.h +option.o: $(hdrdir)/ruby/internal/core/robject.h +option.o: $(hdrdir)/ruby/internal/core/rregexp.h +option.o: $(hdrdir)/ruby/internal/core/rstring.h +option.o: $(hdrdir)/ruby/internal/core/rstruct.h +option.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +option.o: $(hdrdir)/ruby/internal/ctype.h +option.o: $(hdrdir)/ruby/internal/dllexport.h +option.o: $(hdrdir)/ruby/internal/dosish.h +option.o: $(hdrdir)/ruby/internal/encoding/coderange.h +option.o: $(hdrdir)/ruby/internal/encoding/ctype.h +option.o: $(hdrdir)/ruby/internal/encoding/encoding.h +option.o: $(hdrdir)/ruby/internal/encoding/pathname.h +option.o: $(hdrdir)/ruby/internal/encoding/re.h +option.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +option.o: $(hdrdir)/ruby/internal/encoding/string.h +option.o: $(hdrdir)/ruby/internal/encoding/symbol.h +option.o: $(hdrdir)/ruby/internal/encoding/transcode.h +option.o: $(hdrdir)/ruby/internal/error.h +option.o: $(hdrdir)/ruby/internal/eval.h +option.o: $(hdrdir)/ruby/internal/event.h +option.o: $(hdrdir)/ruby/internal/fl_type.h +option.o: $(hdrdir)/ruby/internal/gc.h +option.o: $(hdrdir)/ruby/internal/glob.h +option.o: $(hdrdir)/ruby/internal/globals.h +option.o: $(hdrdir)/ruby/internal/has/attribute.h +option.o: $(hdrdir)/ruby/internal/has/builtin.h +option.o: $(hdrdir)/ruby/internal/has/c_attribute.h +option.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +option.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +option.o: $(hdrdir)/ruby/internal/has/extension.h +option.o: $(hdrdir)/ruby/internal/has/feature.h +option.o: $(hdrdir)/ruby/internal/has/warning.h +option.o: $(hdrdir)/ruby/internal/intern/array.h +option.o: $(hdrdir)/ruby/internal/intern/bignum.h +option.o: $(hdrdir)/ruby/internal/intern/class.h +option.o: $(hdrdir)/ruby/internal/intern/compar.h +option.o: $(hdrdir)/ruby/internal/intern/complex.h +option.o: $(hdrdir)/ruby/internal/intern/cont.h +option.o: $(hdrdir)/ruby/internal/intern/dir.h +option.o: $(hdrdir)/ruby/internal/intern/enum.h +option.o: $(hdrdir)/ruby/internal/intern/enumerator.h +option.o: $(hdrdir)/ruby/internal/intern/error.h +option.o: $(hdrdir)/ruby/internal/intern/eval.h +option.o: $(hdrdir)/ruby/internal/intern/file.h +option.o: $(hdrdir)/ruby/internal/intern/gc.h +option.o: $(hdrdir)/ruby/internal/intern/hash.h +option.o: $(hdrdir)/ruby/internal/intern/io.h +option.o: $(hdrdir)/ruby/internal/intern/load.h +option.o: $(hdrdir)/ruby/internal/intern/marshal.h +option.o: $(hdrdir)/ruby/internal/intern/numeric.h +option.o: $(hdrdir)/ruby/internal/intern/object.h +option.o: $(hdrdir)/ruby/internal/intern/parse.h +option.o: $(hdrdir)/ruby/internal/intern/proc.h +option.o: $(hdrdir)/ruby/internal/intern/process.h +option.o: $(hdrdir)/ruby/internal/intern/random.h +option.o: $(hdrdir)/ruby/internal/intern/range.h +option.o: $(hdrdir)/ruby/internal/intern/rational.h +option.o: $(hdrdir)/ruby/internal/intern/re.h +option.o: $(hdrdir)/ruby/internal/intern/ruby.h +option.o: $(hdrdir)/ruby/internal/intern/select.h +option.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +option.o: $(hdrdir)/ruby/internal/intern/signal.h +option.o: $(hdrdir)/ruby/internal/intern/sprintf.h +option.o: $(hdrdir)/ruby/internal/intern/string.h +option.o: $(hdrdir)/ruby/internal/intern/struct.h +option.o: $(hdrdir)/ruby/internal/intern/thread.h +option.o: $(hdrdir)/ruby/internal/intern/time.h +option.o: $(hdrdir)/ruby/internal/intern/variable.h +option.o: $(hdrdir)/ruby/internal/intern/vm.h +option.o: $(hdrdir)/ruby/internal/interpreter.h +option.o: $(hdrdir)/ruby/internal/iterator.h +option.o: $(hdrdir)/ruby/internal/memory.h +option.o: $(hdrdir)/ruby/internal/method.h +option.o: $(hdrdir)/ruby/internal/module.h +option.o: $(hdrdir)/ruby/internal/newobj.h +option.o: $(hdrdir)/ruby/internal/rgengc.h +option.o: $(hdrdir)/ruby/internal/scan_args.h +option.o: $(hdrdir)/ruby/internal/special_consts.h +option.o: $(hdrdir)/ruby/internal/static_assert.h +option.o: $(hdrdir)/ruby/internal/stdalign.h +option.o: $(hdrdir)/ruby/internal/stdbool.h +option.o: $(hdrdir)/ruby/internal/symbol.h +option.o: $(hdrdir)/ruby/internal/value.h +option.o: $(hdrdir)/ruby/internal/value_type.h +option.o: $(hdrdir)/ruby/internal/variable.h +option.o: $(hdrdir)/ruby/internal/warning_push.h +option.o: $(hdrdir)/ruby/internal/xmalloc.h option.o: $(hdrdir)/ruby/io.h option.o: $(hdrdir)/ruby/missing.h option.o: $(hdrdir)/ruby/onigmo.h @@ -161,18 +1326,186 @@ option.o: $(hdrdir)/ruby/subst.h option.o: $(hdrdir)/ruby/thread.h option.o: $(hdrdir)/ruby/util.h option.o: $(top_srcdir)/internal.h +option.o: $(top_srcdir)/internal/array.h +option.o: $(top_srcdir)/internal/compilers.h +option.o: $(top_srcdir)/internal/error.h +option.o: $(top_srcdir)/internal/gc.h +option.o: $(top_srcdir)/internal/io.h +option.o: $(top_srcdir)/internal/serial.h +option.o: $(top_srcdir)/internal/static_assert.h +option.o: $(top_srcdir)/internal/string.h +option.o: $(top_srcdir)/internal/thread.h +option.o: $(top_srcdir)/internal/vm.h +option.o: $(top_srcdir)/internal/warnings.h option.o: constdefs.h option.o: option.c option.o: rubysocket.h option.o: sockport.h raddrinfo.o: $(RUBY_EXTCONF_H) raddrinfo.o: $(arch_hdrdir)/ruby/config.h -raddrinfo.o: $(hdrdir)/ruby.h raddrinfo.o: $(hdrdir)/ruby/assert.h raddrinfo.o: $(hdrdir)/ruby/backward.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/attributes.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/bool.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/inttypes.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/limits.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/long_long.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/stdalign.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/stdarg.h raddrinfo.o: $(hdrdir)/ruby/defines.h raddrinfo.o: $(hdrdir)/ruby/encoding.h +raddrinfo.o: $(hdrdir)/ruby/fiber/scheduler.h raddrinfo.o: $(hdrdir)/ruby/intern.h +raddrinfo.o: $(hdrdir)/ruby/internal/anyargs.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/char.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/double.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/int.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/short.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/assume.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/artificial.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/cold.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/const.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/constexpr.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/deprecated.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/forceinline.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/format.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noalias.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noexcept.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noinline.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/nonnull.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noreturn.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/pure.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/restrict.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/warning.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/weakref.h +raddrinfo.o: $(hdrdir)/ruby/internal/cast.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_since.h +raddrinfo.o: $(hdrdir)/ruby/internal/config.h +raddrinfo.o: $(hdrdir)/ruby/internal/constant_p.h +raddrinfo.o: $(hdrdir)/ruby/internal/core.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rarray.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rbasic.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rbignum.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rclass.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rdata.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rfile.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rhash.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/robject.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rregexp.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rstring.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rstruct.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +raddrinfo.o: $(hdrdir)/ruby/internal/ctype.h +raddrinfo.o: $(hdrdir)/ruby/internal/dllexport.h +raddrinfo.o: $(hdrdir)/ruby/internal/dosish.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/coderange.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/ctype.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/encoding.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/pathname.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/re.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/string.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/symbol.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/transcode.h +raddrinfo.o: $(hdrdir)/ruby/internal/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/eval.h +raddrinfo.o: $(hdrdir)/ruby/internal/event.h +raddrinfo.o: $(hdrdir)/ruby/internal/fl_type.h +raddrinfo.o: $(hdrdir)/ruby/internal/gc.h +raddrinfo.o: $(hdrdir)/ruby/internal/glob.h +raddrinfo.o: $(hdrdir)/ruby/internal/globals.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/builtin.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/c_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/extension.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/feature.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/warning.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/array.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/bignum.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/class.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/compar.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/complex.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/cont.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/dir.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/enum.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/enumerator.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/eval.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/file.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/gc.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/hash.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/io.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/load.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/marshal.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/numeric.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/object.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/parse.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/proc.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/process.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/random.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/range.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/rational.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/re.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/ruby.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/select.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/signal.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/sprintf.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/string.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/struct.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/thread.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/time.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/variable.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/vm.h +raddrinfo.o: $(hdrdir)/ruby/internal/interpreter.h +raddrinfo.o: $(hdrdir)/ruby/internal/iterator.h +raddrinfo.o: $(hdrdir)/ruby/internal/memory.h +raddrinfo.o: $(hdrdir)/ruby/internal/method.h +raddrinfo.o: $(hdrdir)/ruby/internal/module.h +raddrinfo.o: $(hdrdir)/ruby/internal/newobj.h +raddrinfo.o: $(hdrdir)/ruby/internal/rgengc.h +raddrinfo.o: $(hdrdir)/ruby/internal/scan_args.h +raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h +raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h +raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h +raddrinfo.o: $(hdrdir)/ruby/internal/value.h +raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h +raddrinfo.o: $(hdrdir)/ruby/internal/variable.h +raddrinfo.o: $(hdrdir)/ruby/internal/warning_push.h +raddrinfo.o: $(hdrdir)/ruby/internal/xmalloc.h raddrinfo.o: $(hdrdir)/ruby/io.h raddrinfo.o: $(hdrdir)/ruby/missing.h raddrinfo.o: $(hdrdir)/ruby/onigmo.h @@ -183,18 +1516,186 @@ raddrinfo.o: $(hdrdir)/ruby/subst.h raddrinfo.o: $(hdrdir)/ruby/thread.h raddrinfo.o: $(hdrdir)/ruby/util.h raddrinfo.o: $(top_srcdir)/internal.h +raddrinfo.o: $(top_srcdir)/internal/array.h +raddrinfo.o: $(top_srcdir)/internal/compilers.h +raddrinfo.o: $(top_srcdir)/internal/error.h +raddrinfo.o: $(top_srcdir)/internal/gc.h +raddrinfo.o: $(top_srcdir)/internal/io.h +raddrinfo.o: $(top_srcdir)/internal/serial.h +raddrinfo.o: $(top_srcdir)/internal/static_assert.h +raddrinfo.o: $(top_srcdir)/internal/string.h +raddrinfo.o: $(top_srcdir)/internal/thread.h +raddrinfo.o: $(top_srcdir)/internal/vm.h +raddrinfo.o: $(top_srcdir)/internal/warnings.h raddrinfo.o: constdefs.h raddrinfo.o: raddrinfo.c raddrinfo.o: rubysocket.h raddrinfo.o: sockport.h socket.o: $(RUBY_EXTCONF_H) socket.o: $(arch_hdrdir)/ruby/config.h -socket.o: $(hdrdir)/ruby.h socket.o: $(hdrdir)/ruby/assert.h socket.o: $(hdrdir)/ruby/backward.h +socket.o: $(hdrdir)/ruby/backward/2/assume.h +socket.o: $(hdrdir)/ruby/backward/2/attributes.h +socket.o: $(hdrdir)/ruby/backward/2/bool.h +socket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +socket.o: $(hdrdir)/ruby/backward/2/inttypes.h +socket.o: $(hdrdir)/ruby/backward/2/limits.h +socket.o: $(hdrdir)/ruby/backward/2/long_long.h +socket.o: $(hdrdir)/ruby/backward/2/stdalign.h +socket.o: $(hdrdir)/ruby/backward/2/stdarg.h socket.o: $(hdrdir)/ruby/defines.h socket.o: $(hdrdir)/ruby/encoding.h +socket.o: $(hdrdir)/ruby/fiber/scheduler.h socket.o: $(hdrdir)/ruby/intern.h +socket.o: $(hdrdir)/ruby/internal/anyargs.h +socket.o: $(hdrdir)/ruby/internal/arithmetic.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +socket.o: $(hdrdir)/ruby/internal/assume.h +socket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +socket.o: $(hdrdir)/ruby/internal/attr/artificial.h +socket.o: $(hdrdir)/ruby/internal/attr/cold.h +socket.o: $(hdrdir)/ruby/internal/attr/const.h +socket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +socket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +socket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +socket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +socket.o: $(hdrdir)/ruby/internal/attr/error.h +socket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +socket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +socket.o: $(hdrdir)/ruby/internal/attr/format.h +socket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +socket.o: $(hdrdir)/ruby/internal/attr/noalias.h +socket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +socket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +socket.o: $(hdrdir)/ruby/internal/attr/noinline.h +socket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +socket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +socket.o: $(hdrdir)/ruby/internal/attr/pure.h +socket.o: $(hdrdir)/ruby/internal/attr/restrict.h +socket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +socket.o: $(hdrdir)/ruby/internal/attr/warning.h +socket.o: $(hdrdir)/ruby/internal/attr/weakref.h +socket.o: $(hdrdir)/ruby/internal/cast.h +socket.o: $(hdrdir)/ruby/internal/compiler_is.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +socket.o: $(hdrdir)/ruby/internal/compiler_since.h +socket.o: $(hdrdir)/ruby/internal/config.h +socket.o: $(hdrdir)/ruby/internal/constant_p.h +socket.o: $(hdrdir)/ruby/internal/core.h +socket.o: $(hdrdir)/ruby/internal/core/rarray.h +socket.o: $(hdrdir)/ruby/internal/core/rbasic.h +socket.o: $(hdrdir)/ruby/internal/core/rbignum.h +socket.o: $(hdrdir)/ruby/internal/core/rclass.h +socket.o: $(hdrdir)/ruby/internal/core/rdata.h +socket.o: $(hdrdir)/ruby/internal/core/rfile.h +socket.o: $(hdrdir)/ruby/internal/core/rhash.h +socket.o: $(hdrdir)/ruby/internal/core/robject.h +socket.o: $(hdrdir)/ruby/internal/core/rregexp.h +socket.o: $(hdrdir)/ruby/internal/core/rstring.h +socket.o: $(hdrdir)/ruby/internal/core/rstruct.h +socket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +socket.o: $(hdrdir)/ruby/internal/ctype.h +socket.o: $(hdrdir)/ruby/internal/dllexport.h +socket.o: $(hdrdir)/ruby/internal/dosish.h +socket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +socket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +socket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +socket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +socket.o: $(hdrdir)/ruby/internal/encoding/re.h +socket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +socket.o: $(hdrdir)/ruby/internal/encoding/string.h +socket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +socket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +socket.o: $(hdrdir)/ruby/internal/error.h +socket.o: $(hdrdir)/ruby/internal/eval.h +socket.o: $(hdrdir)/ruby/internal/event.h +socket.o: $(hdrdir)/ruby/internal/fl_type.h +socket.o: $(hdrdir)/ruby/internal/gc.h +socket.o: $(hdrdir)/ruby/internal/glob.h +socket.o: $(hdrdir)/ruby/internal/globals.h +socket.o: $(hdrdir)/ruby/internal/has/attribute.h +socket.o: $(hdrdir)/ruby/internal/has/builtin.h +socket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/extension.h +socket.o: $(hdrdir)/ruby/internal/has/feature.h +socket.o: $(hdrdir)/ruby/internal/has/warning.h +socket.o: $(hdrdir)/ruby/internal/intern/array.h +socket.o: $(hdrdir)/ruby/internal/intern/bignum.h +socket.o: $(hdrdir)/ruby/internal/intern/class.h +socket.o: $(hdrdir)/ruby/internal/intern/compar.h +socket.o: $(hdrdir)/ruby/internal/intern/complex.h +socket.o: $(hdrdir)/ruby/internal/intern/cont.h +socket.o: $(hdrdir)/ruby/internal/intern/dir.h +socket.o: $(hdrdir)/ruby/internal/intern/enum.h +socket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +socket.o: $(hdrdir)/ruby/internal/intern/error.h +socket.o: $(hdrdir)/ruby/internal/intern/eval.h +socket.o: $(hdrdir)/ruby/internal/intern/file.h +socket.o: $(hdrdir)/ruby/internal/intern/gc.h +socket.o: $(hdrdir)/ruby/internal/intern/hash.h +socket.o: $(hdrdir)/ruby/internal/intern/io.h +socket.o: $(hdrdir)/ruby/internal/intern/load.h +socket.o: $(hdrdir)/ruby/internal/intern/marshal.h +socket.o: $(hdrdir)/ruby/internal/intern/numeric.h +socket.o: $(hdrdir)/ruby/internal/intern/object.h +socket.o: $(hdrdir)/ruby/internal/intern/parse.h +socket.o: $(hdrdir)/ruby/internal/intern/proc.h +socket.o: $(hdrdir)/ruby/internal/intern/process.h +socket.o: $(hdrdir)/ruby/internal/intern/random.h +socket.o: $(hdrdir)/ruby/internal/intern/range.h +socket.o: $(hdrdir)/ruby/internal/intern/rational.h +socket.o: $(hdrdir)/ruby/internal/intern/re.h +socket.o: $(hdrdir)/ruby/internal/intern/ruby.h +socket.o: $(hdrdir)/ruby/internal/intern/select.h +socket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +socket.o: $(hdrdir)/ruby/internal/intern/signal.h +socket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +socket.o: $(hdrdir)/ruby/internal/intern/string.h +socket.o: $(hdrdir)/ruby/internal/intern/struct.h +socket.o: $(hdrdir)/ruby/internal/intern/thread.h +socket.o: $(hdrdir)/ruby/internal/intern/time.h +socket.o: $(hdrdir)/ruby/internal/intern/variable.h +socket.o: $(hdrdir)/ruby/internal/intern/vm.h +socket.o: $(hdrdir)/ruby/internal/interpreter.h +socket.o: $(hdrdir)/ruby/internal/iterator.h +socket.o: $(hdrdir)/ruby/internal/memory.h +socket.o: $(hdrdir)/ruby/internal/method.h +socket.o: $(hdrdir)/ruby/internal/module.h +socket.o: $(hdrdir)/ruby/internal/newobj.h +socket.o: $(hdrdir)/ruby/internal/rgengc.h +socket.o: $(hdrdir)/ruby/internal/scan_args.h +socket.o: $(hdrdir)/ruby/internal/special_consts.h +socket.o: $(hdrdir)/ruby/internal/static_assert.h +socket.o: $(hdrdir)/ruby/internal/stdalign.h +socket.o: $(hdrdir)/ruby/internal/stdbool.h +socket.o: $(hdrdir)/ruby/internal/symbol.h +socket.o: $(hdrdir)/ruby/internal/value.h +socket.o: $(hdrdir)/ruby/internal/value_type.h +socket.o: $(hdrdir)/ruby/internal/variable.h +socket.o: $(hdrdir)/ruby/internal/warning_push.h +socket.o: $(hdrdir)/ruby/internal/xmalloc.h socket.o: $(hdrdir)/ruby/io.h socket.o: $(hdrdir)/ruby/missing.h socket.o: $(hdrdir)/ruby/onigmo.h @@ -205,18 +1706,186 @@ socket.o: $(hdrdir)/ruby/subst.h socket.o: $(hdrdir)/ruby/thread.h socket.o: $(hdrdir)/ruby/util.h socket.o: $(top_srcdir)/internal.h +socket.o: $(top_srcdir)/internal/array.h +socket.o: $(top_srcdir)/internal/compilers.h +socket.o: $(top_srcdir)/internal/error.h +socket.o: $(top_srcdir)/internal/gc.h +socket.o: $(top_srcdir)/internal/io.h +socket.o: $(top_srcdir)/internal/serial.h +socket.o: $(top_srcdir)/internal/static_assert.h +socket.o: $(top_srcdir)/internal/string.h +socket.o: $(top_srcdir)/internal/thread.h +socket.o: $(top_srcdir)/internal/vm.h +socket.o: $(top_srcdir)/internal/warnings.h socket.o: constdefs.h socket.o: rubysocket.h socket.o: socket.c socket.o: sockport.h sockssocket.o: $(RUBY_EXTCONF_H) sockssocket.o: $(arch_hdrdir)/ruby/config.h -sockssocket.o: $(hdrdir)/ruby.h sockssocket.o: $(hdrdir)/ruby/assert.h sockssocket.o: $(hdrdir)/ruby/backward.h +sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h +sockssocket.o: $(hdrdir)/ruby/backward/2/attributes.h +sockssocket.o: $(hdrdir)/ruby/backward/2/bool.h +sockssocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +sockssocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +sockssocket.o: $(hdrdir)/ruby/backward/2/limits.h +sockssocket.o: $(hdrdir)/ruby/backward/2/long_long.h +sockssocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +sockssocket.o: $(hdrdir)/ruby/backward/2/stdarg.h sockssocket.o: $(hdrdir)/ruby/defines.h sockssocket.o: $(hdrdir)/ruby/encoding.h +sockssocket.o: $(hdrdir)/ruby/fiber/scheduler.h sockssocket.o: $(hdrdir)/ruby/intern.h +sockssocket.o: $(hdrdir)/ruby/internal/anyargs.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/assume.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/cold.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/const.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/error.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/format.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/pure.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/warning.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +sockssocket.o: $(hdrdir)/ruby/internal/cast.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_since.h +sockssocket.o: $(hdrdir)/ruby/internal/config.h +sockssocket.o: $(hdrdir)/ruby/internal/constant_p.h +sockssocket.o: $(hdrdir)/ruby/internal/core.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rarray.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rclass.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rdata.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rfile.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rhash.h +sockssocket.o: $(hdrdir)/ruby/internal/core/robject.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rstring.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sockssocket.o: $(hdrdir)/ruby/internal/ctype.h +sockssocket.o: $(hdrdir)/ruby/internal/dllexport.h +sockssocket.o: $(hdrdir)/ruby/internal/dosish.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/re.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/string.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +sockssocket.o: $(hdrdir)/ruby/internal/error.h +sockssocket.o: $(hdrdir)/ruby/internal/eval.h +sockssocket.o: $(hdrdir)/ruby/internal/event.h +sockssocket.o: $(hdrdir)/ruby/internal/fl_type.h +sockssocket.o: $(hdrdir)/ruby/internal/gc.h +sockssocket.o: $(hdrdir)/ruby/internal/glob.h +sockssocket.o: $(hdrdir)/ruby/internal/globals.h +sockssocket.o: $(hdrdir)/ruby/internal/has/attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/builtin.h +sockssocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/extension.h +sockssocket.o: $(hdrdir)/ruby/internal/has/feature.h +sockssocket.o: $(hdrdir)/ruby/internal/has/warning.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/array.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/class.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/compar.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/complex.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/cont.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/dir.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/enum.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/error.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/eval.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/file.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/gc.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/hash.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/io.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/load.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/object.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/parse.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/proc.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/process.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/random.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/range.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/rational.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/re.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/select.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/signal.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/string.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/struct.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/thread.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/time.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/variable.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/vm.h +sockssocket.o: $(hdrdir)/ruby/internal/interpreter.h +sockssocket.o: $(hdrdir)/ruby/internal/iterator.h +sockssocket.o: $(hdrdir)/ruby/internal/memory.h +sockssocket.o: $(hdrdir)/ruby/internal/method.h +sockssocket.o: $(hdrdir)/ruby/internal/module.h +sockssocket.o: $(hdrdir)/ruby/internal/newobj.h +sockssocket.o: $(hdrdir)/ruby/internal/rgengc.h +sockssocket.o: $(hdrdir)/ruby/internal/scan_args.h +sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h +sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h +sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h +sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h +sockssocket.o: $(hdrdir)/ruby/internal/symbol.h +sockssocket.o: $(hdrdir)/ruby/internal/value.h +sockssocket.o: $(hdrdir)/ruby/internal/value_type.h +sockssocket.o: $(hdrdir)/ruby/internal/variable.h +sockssocket.o: $(hdrdir)/ruby/internal/warning_push.h +sockssocket.o: $(hdrdir)/ruby/internal/xmalloc.h sockssocket.o: $(hdrdir)/ruby/io.h sockssocket.o: $(hdrdir)/ruby/missing.h sockssocket.o: $(hdrdir)/ruby/onigmo.h @@ -227,18 +1896,186 @@ sockssocket.o: $(hdrdir)/ruby/subst.h sockssocket.o: $(hdrdir)/ruby/thread.h sockssocket.o: $(hdrdir)/ruby/util.h sockssocket.o: $(top_srcdir)/internal.h +sockssocket.o: $(top_srcdir)/internal/array.h +sockssocket.o: $(top_srcdir)/internal/compilers.h +sockssocket.o: $(top_srcdir)/internal/error.h +sockssocket.o: $(top_srcdir)/internal/gc.h +sockssocket.o: $(top_srcdir)/internal/io.h +sockssocket.o: $(top_srcdir)/internal/serial.h +sockssocket.o: $(top_srcdir)/internal/static_assert.h +sockssocket.o: $(top_srcdir)/internal/string.h +sockssocket.o: $(top_srcdir)/internal/thread.h +sockssocket.o: $(top_srcdir)/internal/vm.h +sockssocket.o: $(top_srcdir)/internal/warnings.h sockssocket.o: constdefs.h sockssocket.o: rubysocket.h sockssocket.o: sockport.h sockssocket.o: sockssocket.c tcpserver.o: $(RUBY_EXTCONF_H) tcpserver.o: $(arch_hdrdir)/ruby/config.h -tcpserver.o: $(hdrdir)/ruby.h tcpserver.o: $(hdrdir)/ruby/assert.h tcpserver.o: $(hdrdir)/ruby/backward.h +tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h +tcpserver.o: $(hdrdir)/ruby/backward/2/attributes.h +tcpserver.o: $(hdrdir)/ruby/backward/2/bool.h +tcpserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +tcpserver.o: $(hdrdir)/ruby/backward/2/inttypes.h +tcpserver.o: $(hdrdir)/ruby/backward/2/limits.h +tcpserver.o: $(hdrdir)/ruby/backward/2/long_long.h +tcpserver.o: $(hdrdir)/ruby/backward/2/stdalign.h +tcpserver.o: $(hdrdir)/ruby/backward/2/stdarg.h tcpserver.o: $(hdrdir)/ruby/defines.h tcpserver.o: $(hdrdir)/ruby/encoding.h +tcpserver.o: $(hdrdir)/ruby/fiber/scheduler.h tcpserver.o: $(hdrdir)/ruby/intern.h +tcpserver.o: $(hdrdir)/ruby/internal/anyargs.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/assume.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/artificial.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/cold.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/const.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/error.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/format.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noalias.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noinline.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/pure.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/restrict.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/warning.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/weakref.h +tcpserver.o: $(hdrdir)/ruby/internal/cast.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_since.h +tcpserver.o: $(hdrdir)/ruby/internal/config.h +tcpserver.o: $(hdrdir)/ruby/internal/constant_p.h +tcpserver.o: $(hdrdir)/ruby/internal/core.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rarray.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rbasic.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rbignum.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rclass.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rdata.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rfile.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rhash.h +tcpserver.o: $(hdrdir)/ruby/internal/core/robject.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rregexp.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rstring.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rstruct.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +tcpserver.o: $(hdrdir)/ruby/internal/ctype.h +tcpserver.o: $(hdrdir)/ruby/internal/dllexport.h +tcpserver.o: $(hdrdir)/ruby/internal/dosish.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/re.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/string.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h +tcpserver.o: $(hdrdir)/ruby/internal/error.h +tcpserver.o: $(hdrdir)/ruby/internal/eval.h +tcpserver.o: $(hdrdir)/ruby/internal/event.h +tcpserver.o: $(hdrdir)/ruby/internal/fl_type.h +tcpserver.o: $(hdrdir)/ruby/internal/gc.h +tcpserver.o: $(hdrdir)/ruby/internal/glob.h +tcpserver.o: $(hdrdir)/ruby/internal/globals.h +tcpserver.o: $(hdrdir)/ruby/internal/has/attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/builtin.h +tcpserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/extension.h +tcpserver.o: $(hdrdir)/ruby/internal/has/feature.h +tcpserver.o: $(hdrdir)/ruby/internal/has/warning.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/array.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/bignum.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/class.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/compar.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/complex.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/cont.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/dir.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/enum.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/error.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/eval.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/file.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/gc.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/hash.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/io.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/load.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/marshal.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/numeric.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/object.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/parse.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/proc.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/process.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/random.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/range.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/rational.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/re.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/ruby.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/select.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/signal.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/string.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/struct.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/thread.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/time.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/variable.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/vm.h +tcpserver.o: $(hdrdir)/ruby/internal/interpreter.h +tcpserver.o: $(hdrdir)/ruby/internal/iterator.h +tcpserver.o: $(hdrdir)/ruby/internal/memory.h +tcpserver.o: $(hdrdir)/ruby/internal/method.h +tcpserver.o: $(hdrdir)/ruby/internal/module.h +tcpserver.o: $(hdrdir)/ruby/internal/newobj.h +tcpserver.o: $(hdrdir)/ruby/internal/rgengc.h +tcpserver.o: $(hdrdir)/ruby/internal/scan_args.h +tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h +tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h +tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h +tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h +tcpserver.o: $(hdrdir)/ruby/internal/symbol.h +tcpserver.o: $(hdrdir)/ruby/internal/value.h +tcpserver.o: $(hdrdir)/ruby/internal/value_type.h +tcpserver.o: $(hdrdir)/ruby/internal/variable.h +tcpserver.o: $(hdrdir)/ruby/internal/warning_push.h +tcpserver.o: $(hdrdir)/ruby/internal/xmalloc.h tcpserver.o: $(hdrdir)/ruby/io.h tcpserver.o: $(hdrdir)/ruby/missing.h tcpserver.o: $(hdrdir)/ruby/onigmo.h @@ -249,18 +2086,186 @@ tcpserver.o: $(hdrdir)/ruby/subst.h tcpserver.o: $(hdrdir)/ruby/thread.h tcpserver.o: $(hdrdir)/ruby/util.h tcpserver.o: $(top_srcdir)/internal.h +tcpserver.o: $(top_srcdir)/internal/array.h +tcpserver.o: $(top_srcdir)/internal/compilers.h +tcpserver.o: $(top_srcdir)/internal/error.h +tcpserver.o: $(top_srcdir)/internal/gc.h +tcpserver.o: $(top_srcdir)/internal/io.h +tcpserver.o: $(top_srcdir)/internal/serial.h +tcpserver.o: $(top_srcdir)/internal/static_assert.h +tcpserver.o: $(top_srcdir)/internal/string.h +tcpserver.o: $(top_srcdir)/internal/thread.h +tcpserver.o: $(top_srcdir)/internal/vm.h +tcpserver.o: $(top_srcdir)/internal/warnings.h tcpserver.o: constdefs.h tcpserver.o: rubysocket.h tcpserver.o: sockport.h tcpserver.o: tcpserver.c tcpsocket.o: $(RUBY_EXTCONF_H) tcpsocket.o: $(arch_hdrdir)/ruby/config.h -tcpsocket.o: $(hdrdir)/ruby.h tcpsocket.o: $(hdrdir)/ruby/assert.h tcpsocket.o: $(hdrdir)/ruby/backward.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/bool.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/limits.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h tcpsocket.o: $(hdrdir)/ruby/defines.h tcpsocket.o: $(hdrdir)/ruby/encoding.h +tcpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h tcpsocket.o: $(hdrdir)/ruby/intern.h +tcpsocket.o: $(hdrdir)/ruby/internal/anyargs.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/assume.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/const.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/format.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +tcpsocket.o: $(hdrdir)/ruby/internal/cast.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +tcpsocket.o: $(hdrdir)/ruby/internal/config.h +tcpsocket.o: $(hdrdir)/ruby/internal/constant_p.h +tcpsocket.o: $(hdrdir)/ruby/internal/core.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/robject.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +tcpsocket.o: $(hdrdir)/ruby/internal/ctype.h +tcpsocket.o: $(hdrdir)/ruby/internal/dllexport.h +tcpsocket.o: $(hdrdir)/ruby/internal/dosish.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +tcpsocket.o: $(hdrdir)/ruby/internal/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/eval.h +tcpsocket.o: $(hdrdir)/ruby/internal/event.h +tcpsocket.o: $(hdrdir)/ruby/internal/fl_type.h +tcpsocket.o: $(hdrdir)/ruby/internal/gc.h +tcpsocket.o: $(hdrdir)/ruby/internal/glob.h +tcpsocket.o: $(hdrdir)/ruby/internal/globals.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/extension.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/feature.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/warning.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/array.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/class.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/file.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/io.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/load.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/object.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/process.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/random.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/range.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/re.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/select.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/string.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/time.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +tcpsocket.o: $(hdrdir)/ruby/internal/interpreter.h +tcpsocket.o: $(hdrdir)/ruby/internal/iterator.h +tcpsocket.o: $(hdrdir)/ruby/internal/memory.h +tcpsocket.o: $(hdrdir)/ruby/internal/method.h +tcpsocket.o: $(hdrdir)/ruby/internal/module.h +tcpsocket.o: $(hdrdir)/ruby/internal/newobj.h +tcpsocket.o: $(hdrdir)/ruby/internal/rgengc.h +tcpsocket.o: $(hdrdir)/ruby/internal/scan_args.h +tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h +tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h +tcpsocket.o: $(hdrdir)/ruby/internal/value.h +tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h +tcpsocket.o: $(hdrdir)/ruby/internal/variable.h +tcpsocket.o: $(hdrdir)/ruby/internal/warning_push.h +tcpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h tcpsocket.o: $(hdrdir)/ruby/io.h tcpsocket.o: $(hdrdir)/ruby/missing.h tcpsocket.o: $(hdrdir)/ruby/onigmo.h @@ -271,18 +2276,186 @@ tcpsocket.o: $(hdrdir)/ruby/subst.h tcpsocket.o: $(hdrdir)/ruby/thread.h tcpsocket.o: $(hdrdir)/ruby/util.h tcpsocket.o: $(top_srcdir)/internal.h +tcpsocket.o: $(top_srcdir)/internal/array.h +tcpsocket.o: $(top_srcdir)/internal/compilers.h +tcpsocket.o: $(top_srcdir)/internal/error.h +tcpsocket.o: $(top_srcdir)/internal/gc.h +tcpsocket.o: $(top_srcdir)/internal/io.h +tcpsocket.o: $(top_srcdir)/internal/serial.h +tcpsocket.o: $(top_srcdir)/internal/static_assert.h +tcpsocket.o: $(top_srcdir)/internal/string.h +tcpsocket.o: $(top_srcdir)/internal/thread.h +tcpsocket.o: $(top_srcdir)/internal/vm.h +tcpsocket.o: $(top_srcdir)/internal/warnings.h tcpsocket.o: constdefs.h tcpsocket.o: rubysocket.h tcpsocket.o: sockport.h tcpsocket.o: tcpsocket.c udpsocket.o: $(RUBY_EXTCONF_H) udpsocket.o: $(arch_hdrdir)/ruby/config.h -udpsocket.o: $(hdrdir)/ruby.h udpsocket.o: $(hdrdir)/ruby/assert.h udpsocket.o: $(hdrdir)/ruby/backward.h +udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h +udpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +udpsocket.o: $(hdrdir)/ruby/backward/2/bool.h +udpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +udpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +udpsocket.o: $(hdrdir)/ruby/backward/2/limits.h +udpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +udpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +udpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h udpsocket.o: $(hdrdir)/ruby/defines.h udpsocket.o: $(hdrdir)/ruby/encoding.h +udpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h udpsocket.o: $(hdrdir)/ruby/intern.h +udpsocket.o: $(hdrdir)/ruby/internal/anyargs.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/assume.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/const.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/error.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/format.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +udpsocket.o: $(hdrdir)/ruby/internal/cast.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +udpsocket.o: $(hdrdir)/ruby/internal/config.h +udpsocket.o: $(hdrdir)/ruby/internal/constant_p.h +udpsocket.o: $(hdrdir)/ruby/internal/core.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +udpsocket.o: $(hdrdir)/ruby/internal/core/robject.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +udpsocket.o: $(hdrdir)/ruby/internal/ctype.h +udpsocket.o: $(hdrdir)/ruby/internal/dllexport.h +udpsocket.o: $(hdrdir)/ruby/internal/dosish.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +udpsocket.o: $(hdrdir)/ruby/internal/error.h +udpsocket.o: $(hdrdir)/ruby/internal/eval.h +udpsocket.o: $(hdrdir)/ruby/internal/event.h +udpsocket.o: $(hdrdir)/ruby/internal/fl_type.h +udpsocket.o: $(hdrdir)/ruby/internal/gc.h +udpsocket.o: $(hdrdir)/ruby/internal/glob.h +udpsocket.o: $(hdrdir)/ruby/internal/globals.h +udpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +udpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/extension.h +udpsocket.o: $(hdrdir)/ruby/internal/has/feature.h +udpsocket.o: $(hdrdir)/ruby/internal/has/warning.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/array.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/class.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/error.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/file.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/io.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/load.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/object.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/process.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/random.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/range.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/re.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/select.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/string.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/time.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +udpsocket.o: $(hdrdir)/ruby/internal/interpreter.h +udpsocket.o: $(hdrdir)/ruby/internal/iterator.h +udpsocket.o: $(hdrdir)/ruby/internal/memory.h +udpsocket.o: $(hdrdir)/ruby/internal/method.h +udpsocket.o: $(hdrdir)/ruby/internal/module.h +udpsocket.o: $(hdrdir)/ruby/internal/newobj.h +udpsocket.o: $(hdrdir)/ruby/internal/rgengc.h +udpsocket.o: $(hdrdir)/ruby/internal/scan_args.h +udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h +udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h +udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h +udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +udpsocket.o: $(hdrdir)/ruby/internal/symbol.h +udpsocket.o: $(hdrdir)/ruby/internal/value.h +udpsocket.o: $(hdrdir)/ruby/internal/value_type.h +udpsocket.o: $(hdrdir)/ruby/internal/variable.h +udpsocket.o: $(hdrdir)/ruby/internal/warning_push.h +udpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h udpsocket.o: $(hdrdir)/ruby/io.h udpsocket.o: $(hdrdir)/ruby/missing.h udpsocket.o: $(hdrdir)/ruby/onigmo.h @@ -293,18 +2466,186 @@ udpsocket.o: $(hdrdir)/ruby/subst.h udpsocket.o: $(hdrdir)/ruby/thread.h udpsocket.o: $(hdrdir)/ruby/util.h udpsocket.o: $(top_srcdir)/internal.h +udpsocket.o: $(top_srcdir)/internal/array.h +udpsocket.o: $(top_srcdir)/internal/compilers.h +udpsocket.o: $(top_srcdir)/internal/error.h +udpsocket.o: $(top_srcdir)/internal/gc.h +udpsocket.o: $(top_srcdir)/internal/io.h +udpsocket.o: $(top_srcdir)/internal/serial.h +udpsocket.o: $(top_srcdir)/internal/static_assert.h +udpsocket.o: $(top_srcdir)/internal/string.h +udpsocket.o: $(top_srcdir)/internal/thread.h +udpsocket.o: $(top_srcdir)/internal/vm.h +udpsocket.o: $(top_srcdir)/internal/warnings.h udpsocket.o: constdefs.h udpsocket.o: rubysocket.h udpsocket.o: sockport.h udpsocket.o: udpsocket.c unixserver.o: $(RUBY_EXTCONF_H) unixserver.o: $(arch_hdrdir)/ruby/config.h -unixserver.o: $(hdrdir)/ruby.h unixserver.o: $(hdrdir)/ruby/assert.h unixserver.o: $(hdrdir)/ruby/backward.h +unixserver.o: $(hdrdir)/ruby/backward/2/assume.h +unixserver.o: $(hdrdir)/ruby/backward/2/attributes.h +unixserver.o: $(hdrdir)/ruby/backward/2/bool.h +unixserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +unixserver.o: $(hdrdir)/ruby/backward/2/inttypes.h +unixserver.o: $(hdrdir)/ruby/backward/2/limits.h +unixserver.o: $(hdrdir)/ruby/backward/2/long_long.h +unixserver.o: $(hdrdir)/ruby/backward/2/stdalign.h +unixserver.o: $(hdrdir)/ruby/backward/2/stdarg.h unixserver.o: $(hdrdir)/ruby/defines.h unixserver.o: $(hdrdir)/ruby/encoding.h +unixserver.o: $(hdrdir)/ruby/fiber/scheduler.h unixserver.o: $(hdrdir)/ruby/intern.h +unixserver.o: $(hdrdir)/ruby/internal/anyargs.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +unixserver.o: $(hdrdir)/ruby/internal/assume.h +unixserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +unixserver.o: $(hdrdir)/ruby/internal/attr/artificial.h +unixserver.o: $(hdrdir)/ruby/internal/attr/cold.h +unixserver.o: $(hdrdir)/ruby/internal/attr/const.h +unixserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +unixserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +unixserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +unixserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +unixserver.o: $(hdrdir)/ruby/internal/attr/error.h +unixserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +unixserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +unixserver.o: $(hdrdir)/ruby/internal/attr/format.h +unixserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noalias.h +unixserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noinline.h +unixserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixserver.o: $(hdrdir)/ruby/internal/attr/pure.h +unixserver.o: $(hdrdir)/ruby/internal/attr/restrict.h +unixserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +unixserver.o: $(hdrdir)/ruby/internal/attr/warning.h +unixserver.o: $(hdrdir)/ruby/internal/attr/weakref.h +unixserver.o: $(hdrdir)/ruby/internal/cast.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_since.h +unixserver.o: $(hdrdir)/ruby/internal/config.h +unixserver.o: $(hdrdir)/ruby/internal/constant_p.h +unixserver.o: $(hdrdir)/ruby/internal/core.h +unixserver.o: $(hdrdir)/ruby/internal/core/rarray.h +unixserver.o: $(hdrdir)/ruby/internal/core/rbasic.h +unixserver.o: $(hdrdir)/ruby/internal/core/rbignum.h +unixserver.o: $(hdrdir)/ruby/internal/core/rclass.h +unixserver.o: $(hdrdir)/ruby/internal/core/rdata.h +unixserver.o: $(hdrdir)/ruby/internal/core/rfile.h +unixserver.o: $(hdrdir)/ruby/internal/core/rhash.h +unixserver.o: $(hdrdir)/ruby/internal/core/robject.h +unixserver.o: $(hdrdir)/ruby/internal/core/rregexp.h +unixserver.o: $(hdrdir)/ruby/internal/core/rstring.h +unixserver.o: $(hdrdir)/ruby/internal/core/rstruct.h +unixserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +unixserver.o: $(hdrdir)/ruby/internal/ctype.h +unixserver.o: $(hdrdir)/ruby/internal/dllexport.h +unixserver.o: $(hdrdir)/ruby/internal/dosish.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/re.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/string.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h +unixserver.o: $(hdrdir)/ruby/internal/error.h +unixserver.o: $(hdrdir)/ruby/internal/eval.h +unixserver.o: $(hdrdir)/ruby/internal/event.h +unixserver.o: $(hdrdir)/ruby/internal/fl_type.h +unixserver.o: $(hdrdir)/ruby/internal/gc.h +unixserver.o: $(hdrdir)/ruby/internal/glob.h +unixserver.o: $(hdrdir)/ruby/internal/globals.h +unixserver.o: $(hdrdir)/ruby/internal/has/attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/builtin.h +unixserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/extension.h +unixserver.o: $(hdrdir)/ruby/internal/has/feature.h +unixserver.o: $(hdrdir)/ruby/internal/has/warning.h +unixserver.o: $(hdrdir)/ruby/internal/intern/array.h +unixserver.o: $(hdrdir)/ruby/internal/intern/bignum.h +unixserver.o: $(hdrdir)/ruby/internal/intern/class.h +unixserver.o: $(hdrdir)/ruby/internal/intern/compar.h +unixserver.o: $(hdrdir)/ruby/internal/intern/complex.h +unixserver.o: $(hdrdir)/ruby/internal/intern/cont.h +unixserver.o: $(hdrdir)/ruby/internal/intern/dir.h +unixserver.o: $(hdrdir)/ruby/internal/intern/enum.h +unixserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +unixserver.o: $(hdrdir)/ruby/internal/intern/error.h +unixserver.o: $(hdrdir)/ruby/internal/intern/eval.h +unixserver.o: $(hdrdir)/ruby/internal/intern/file.h +unixserver.o: $(hdrdir)/ruby/internal/intern/gc.h +unixserver.o: $(hdrdir)/ruby/internal/intern/hash.h +unixserver.o: $(hdrdir)/ruby/internal/intern/io.h +unixserver.o: $(hdrdir)/ruby/internal/intern/load.h +unixserver.o: $(hdrdir)/ruby/internal/intern/marshal.h +unixserver.o: $(hdrdir)/ruby/internal/intern/numeric.h +unixserver.o: $(hdrdir)/ruby/internal/intern/object.h +unixserver.o: $(hdrdir)/ruby/internal/intern/parse.h +unixserver.o: $(hdrdir)/ruby/internal/intern/proc.h +unixserver.o: $(hdrdir)/ruby/internal/intern/process.h +unixserver.o: $(hdrdir)/ruby/internal/intern/random.h +unixserver.o: $(hdrdir)/ruby/internal/intern/range.h +unixserver.o: $(hdrdir)/ruby/internal/intern/rational.h +unixserver.o: $(hdrdir)/ruby/internal/intern/re.h +unixserver.o: $(hdrdir)/ruby/internal/intern/ruby.h +unixserver.o: $(hdrdir)/ruby/internal/intern/select.h +unixserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +unixserver.o: $(hdrdir)/ruby/internal/intern/signal.h +unixserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +unixserver.o: $(hdrdir)/ruby/internal/intern/string.h +unixserver.o: $(hdrdir)/ruby/internal/intern/struct.h +unixserver.o: $(hdrdir)/ruby/internal/intern/thread.h +unixserver.o: $(hdrdir)/ruby/internal/intern/time.h +unixserver.o: $(hdrdir)/ruby/internal/intern/variable.h +unixserver.o: $(hdrdir)/ruby/internal/intern/vm.h +unixserver.o: $(hdrdir)/ruby/internal/interpreter.h +unixserver.o: $(hdrdir)/ruby/internal/iterator.h +unixserver.o: $(hdrdir)/ruby/internal/memory.h +unixserver.o: $(hdrdir)/ruby/internal/method.h +unixserver.o: $(hdrdir)/ruby/internal/module.h +unixserver.o: $(hdrdir)/ruby/internal/newobj.h +unixserver.o: $(hdrdir)/ruby/internal/rgengc.h +unixserver.o: $(hdrdir)/ruby/internal/scan_args.h +unixserver.o: $(hdrdir)/ruby/internal/special_consts.h +unixserver.o: $(hdrdir)/ruby/internal/static_assert.h +unixserver.o: $(hdrdir)/ruby/internal/stdalign.h +unixserver.o: $(hdrdir)/ruby/internal/stdbool.h +unixserver.o: $(hdrdir)/ruby/internal/symbol.h +unixserver.o: $(hdrdir)/ruby/internal/value.h +unixserver.o: $(hdrdir)/ruby/internal/value_type.h +unixserver.o: $(hdrdir)/ruby/internal/variable.h +unixserver.o: $(hdrdir)/ruby/internal/warning_push.h +unixserver.o: $(hdrdir)/ruby/internal/xmalloc.h unixserver.o: $(hdrdir)/ruby/io.h unixserver.o: $(hdrdir)/ruby/missing.h unixserver.o: $(hdrdir)/ruby/onigmo.h @@ -315,18 +2656,186 @@ unixserver.o: $(hdrdir)/ruby/subst.h unixserver.o: $(hdrdir)/ruby/thread.h unixserver.o: $(hdrdir)/ruby/util.h unixserver.o: $(top_srcdir)/internal.h +unixserver.o: $(top_srcdir)/internal/array.h +unixserver.o: $(top_srcdir)/internal/compilers.h +unixserver.o: $(top_srcdir)/internal/error.h +unixserver.o: $(top_srcdir)/internal/gc.h +unixserver.o: $(top_srcdir)/internal/io.h +unixserver.o: $(top_srcdir)/internal/serial.h +unixserver.o: $(top_srcdir)/internal/static_assert.h +unixserver.o: $(top_srcdir)/internal/string.h +unixserver.o: $(top_srcdir)/internal/thread.h +unixserver.o: $(top_srcdir)/internal/vm.h +unixserver.o: $(top_srcdir)/internal/warnings.h unixserver.o: constdefs.h unixserver.o: rubysocket.h unixserver.o: sockport.h unixserver.o: unixserver.c unixsocket.o: $(RUBY_EXTCONF_H) unixsocket.o: $(arch_hdrdir)/ruby/config.h -unixsocket.o: $(hdrdir)/ruby.h unixsocket.o: $(hdrdir)/ruby/assert.h unixsocket.o: $(hdrdir)/ruby/backward.h +unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h +unixsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +unixsocket.o: $(hdrdir)/ruby/backward/2/bool.h +unixsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +unixsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +unixsocket.o: $(hdrdir)/ruby/backward/2/limits.h +unixsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +unixsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +unixsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h unixsocket.o: $(hdrdir)/ruby/defines.h unixsocket.o: $(hdrdir)/ruby/encoding.h +unixsocket.o: $(hdrdir)/ruby/fiber/scheduler.h unixsocket.o: $(hdrdir)/ruby/intern.h +unixsocket.o: $(hdrdir)/ruby/internal/anyargs.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/assume.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/const.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/error.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/format.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +unixsocket.o: $(hdrdir)/ruby/internal/cast.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +unixsocket.o: $(hdrdir)/ruby/internal/config.h +unixsocket.o: $(hdrdir)/ruby/internal/constant_p.h +unixsocket.o: $(hdrdir)/ruby/internal/core.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +unixsocket.o: $(hdrdir)/ruby/internal/core/robject.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +unixsocket.o: $(hdrdir)/ruby/internal/ctype.h +unixsocket.o: $(hdrdir)/ruby/internal/dllexport.h +unixsocket.o: $(hdrdir)/ruby/internal/dosish.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +unixsocket.o: $(hdrdir)/ruby/internal/error.h +unixsocket.o: $(hdrdir)/ruby/internal/eval.h +unixsocket.o: $(hdrdir)/ruby/internal/event.h +unixsocket.o: $(hdrdir)/ruby/internal/fl_type.h +unixsocket.o: $(hdrdir)/ruby/internal/gc.h +unixsocket.o: $(hdrdir)/ruby/internal/glob.h +unixsocket.o: $(hdrdir)/ruby/internal/globals.h +unixsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +unixsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/extension.h +unixsocket.o: $(hdrdir)/ruby/internal/has/feature.h +unixsocket.o: $(hdrdir)/ruby/internal/has/warning.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/array.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/class.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/error.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/file.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/gc.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/io.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/load.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/object.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/process.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/random.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/range.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/re.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/select.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/string.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/time.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +unixsocket.o: $(hdrdir)/ruby/internal/interpreter.h +unixsocket.o: $(hdrdir)/ruby/internal/iterator.h +unixsocket.o: $(hdrdir)/ruby/internal/memory.h +unixsocket.o: $(hdrdir)/ruby/internal/method.h +unixsocket.o: $(hdrdir)/ruby/internal/module.h +unixsocket.o: $(hdrdir)/ruby/internal/newobj.h +unixsocket.o: $(hdrdir)/ruby/internal/rgengc.h +unixsocket.o: $(hdrdir)/ruby/internal/scan_args.h +unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h +unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h +unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h +unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h +unixsocket.o: $(hdrdir)/ruby/internal/symbol.h +unixsocket.o: $(hdrdir)/ruby/internal/value.h +unixsocket.o: $(hdrdir)/ruby/internal/value_type.h +unixsocket.o: $(hdrdir)/ruby/internal/variable.h +unixsocket.o: $(hdrdir)/ruby/internal/warning_push.h +unixsocket.o: $(hdrdir)/ruby/internal/xmalloc.h unixsocket.o: $(hdrdir)/ruby/io.h unixsocket.o: $(hdrdir)/ruby/missing.h unixsocket.o: $(hdrdir)/ruby/onigmo.h @@ -337,6 +2846,17 @@ unixsocket.o: $(hdrdir)/ruby/subst.h unixsocket.o: $(hdrdir)/ruby/thread.h unixsocket.o: $(hdrdir)/ruby/util.h unixsocket.o: $(top_srcdir)/internal.h +unixsocket.o: $(top_srcdir)/internal/array.h +unixsocket.o: $(top_srcdir)/internal/compilers.h +unixsocket.o: $(top_srcdir)/internal/error.h +unixsocket.o: $(top_srcdir)/internal/gc.h +unixsocket.o: $(top_srcdir)/internal/io.h +unixsocket.o: $(top_srcdir)/internal/serial.h +unixsocket.o: $(top_srcdir)/internal/static_assert.h +unixsocket.o: $(top_srcdir)/internal/string.h +unixsocket.o: $(top_srcdir)/internal/thread.h +unixsocket.o: $(top_srcdir)/internal/vm.h +unixsocket.o: $(top_srcdir)/internal/warnings.h unixsocket.o: constdefs.h unixsocket.o: rubysocket.h unixsocket.o: sockport.h diff --git a/ruby/ext/socket/extconf.rb b/ruby/ext/socket/extconf.rb index 1a67e0013..b70a86241 100644 --- a/ruby/ext/socket/extconf.rb +++ b/ruby/ext/socket/extconf.rb @@ -444,7 +444,6 @@ def test_recvmsg_with_msg_peek_creates_fds(headers) test_func = "socket(0,0,0)" have_library("nsl", 't_open("", 0, (struct t_info *)NULL)', headers) # SunOS have_library("socket", "socket(0,0,0)", headers) # SunOS - have_library("anl", 'getaddrinfo_a', headers) end if have_func(test_func, headers) @@ -485,6 +484,9 @@ def test_recvmsg_with_msg_peek_creates_fds(headers) have_func("getpeerucred(0, (ucred_t **)NULL)", headers) # SunOS have_func_decl = proc do |name, headers| + # check if there is a declaration of by trying to declare + # both "int (void)" and "void (void)" + # (at least one attempt should fail if there is a declaration) if !checking_for("declaration of #{name}()") {!%w[int void].all? {|ret| try_compile(<fd = fd; @@ -166,7 +148,7 @@ recvfrom_locktmp(VALUE v) } VALUE -rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) +rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from) { rb_io_t *fptr; VALUE str; @@ -177,27 +159,38 @@ rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) rb_scan_args(argc, argv, "12", &len, &flg, &str); - if (flg == Qnil) arg.flags = 0; - else arg.flags = NUM2INT(flg); + if (flg == Qnil) + arg.flags = 0; + else + arg.flags = NUM2INT(flg); + buflen = NUM2INT(len); str = rsock_strbuf(str, buflen); - GetOpenFile(sock, fptr); + RB_IO_POINTER(socket, fptr); + if (rb_io_read_pending(fptr)) { - rb_raise(rb_eIOError, "recv for buffered IO"); + rb_raise(rb_eIOError, "recv for buffered IO"); } + arg.fd = fptr->fd; arg.alen = (socklen_t)sizeof(arg.buf); arg.str = str; arg.length = buflen; - while (rb_io_check_closed(fptr), - rsock_maybe_wait_fd(arg.fd), - (slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, - (VALUE)&arg)) < 0) { - if (!rb_io_wait_readable(fptr->fd)) { + while (true) { + rb_io_check_closed(fptr); + +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); +#endif + + slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, (VALUE)&arg); + + if (slen >= 0) break; + + if (!rb_io_maybe_wait_readable(errno, socket, Qnil)) rb_sys_fail("recvfrom(2)"); - } } /* Resize the string to the amount of data received */ @@ -221,7 +214,7 @@ rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen)); #endif case RECV_SOCKET: - return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, &arg.buf.addr, arg.alen)); + return rb_assoc_new(str, rsock_io_socket_addrinfo(socket, &arg.buf.addr, arg.alen)); default: rb_bug("rsock_s_recvfrom called with bad value"); } @@ -408,84 +401,30 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex) } #endif /* MSG_DONTWAIT_RELIABLE */ -/* returns true if SOCK_CLOEXEC is supported */ -int rsock_detect_cloexec(int fd) +static int +rsock_socket0(int domain, int type, int proto) { #ifdef SOCK_CLOEXEC - int flags = fcntl(fd, F_GETFD); - - if (flags == -1) - rb_bug("rsock_detect_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno)); + type |= SOCK_CLOEXEC; +#endif - if (flags & FD_CLOEXEC) - return 1; +#ifdef SOCK_NONBLOCK + type |= SOCK_NONBLOCK; #endif - return 0; -} -#ifdef SOCK_CLOEXEC -static int -rsock_socket0(int domain, int type, int proto) -{ - int ret; - static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ - - if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */ - ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto); - if (ret >= 0) { - if (ret <= 2) - goto fix_cloexec; - goto update_max_fd; - } - } - else if (cloexec_state < 0) { /* usually runs once only for detection */ - ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto); - if (ret >= 0) { - cloexec_state = rsock_detect_cloexec(ret); - if (cloexec_state == 0 || ret <= 2) - goto fix_cloexec; - goto update_max_fd; - } - else if (ret == -1 && errno == EINVAL) { - /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ - ret = socket(domain, type, proto); - if (ret != -1) { - cloexec_state = 0; - /* fall through to fix_cloexec */ - } - } - } - else { /* cloexec_state == 0 */ - ret = socket(domain, type, proto); - } - if (ret == -1) + int result = socket(domain, type, proto); + + if (result == -1) return -1; -fix_cloexec: - rb_maygvl_fd_fix_cloexec(ret); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(ret); - } -update_max_fd: - rb_update_max_fd(ret); - return ret; -} -#else /* !SOCK_CLOEXEC */ -static int -rsock_socket0(int domain, int type, int proto) -{ - int ret = socket(domain, type, proto); + rb_fd_fix_cloexec(result); - if (ret == -1) - return -1; - rb_fd_fix_cloexec(ret); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(ret); - } +#ifndef SOCK_NONBLOCK + rsock_make_fd_nonblock(result); +#endif - return ret; + return result; } -#endif /* !SOCK_CLOEXEC */ int rsock_socket(int domain, int type, int proto) @@ -505,7 +444,7 @@ rsock_socket(int domain, int type, int proto) /* emulate blocking connect behavior on EINTR or non-blocking socket */ static int -wait_connectable(int fd) +wait_connectable(int fd, struct timeval *timeout) { int sockerr, revents; socklen_t sockerrlen; @@ -542,7 +481,7 @@ wait_connectable(int fd) * * Note: rb_wait_for_single_fd already retries on EINTR/ERESTART */ - revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL); + revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, timeout); if (revents < 0) return -1; @@ -557,6 +496,12 @@ wait_connectable(int fd) * be defensive in case some platforms set SO_ERROR on the original, * interrupted connect() */ + + /* when the connection timed out, no errno is set and revents is 0. */ + if (timeout && revents == 0) { + errno = ETIMEDOUT; + return -1; + } case EINTR: #ifdef ERESTART case ERESTART: @@ -604,7 +549,7 @@ socks_connect_blocking(void *data) #endif int -rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) +rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout) { int status; rb_blocking_function_t *func = connect_blocking; @@ -628,7 +573,7 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) #ifdef EINPROGRESS case EINPROGRESS: #endif - return wait_connectable(fd); + return wait_connectable(fd, timeout); } } return status; @@ -637,6 +582,10 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) void rsock_make_fd_nonblock(int fd) { +#ifdef _WIN32 + return; +#endif + int flags; #ifdef F_GETFL flags = fcntl(fd, F_GETFL); @@ -653,56 +602,34 @@ rsock_make_fd_nonblock(int fd) } static int -cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len, - int nonblock) +cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len) { - int ret; socklen_t len0 = 0; -#ifdef HAVE_ACCEPT4 - static int try_accept4 = 1; -#endif - if (RSOCK_NONBLOCK_DEFAULT) { - nonblock = 1; - } if (address_len) len0 = *address_len; + #ifdef HAVE_ACCEPT4 - if (try_accept4) { - int flags = 0; -#ifdef SOCK_CLOEXEC - flags |= SOCK_CLOEXEC; -#endif + int flags = SOCK_CLOEXEC; + #ifdef SOCK_NONBLOCK - if (nonblock) { - flags |= SOCK_NONBLOCK; - } + flags |= SOCK_NONBLOCK; #endif - ret = accept4(socket, address, address_len, flags); - /* accept4 is available since Linux 2.6.28, glibc 2.10. */ - if (ret != -1) { - if (ret <= 2) - rb_maygvl_fd_fix_cloexec(ret); + + int result = accept4(socket, address, address_len, flags); + if (result == -1) return -1; + #ifndef SOCK_NONBLOCK - if (nonblock) { - rsock_make_fd_nonblock(ret); - } + rsock_make_fd_nonblock(result); #endif - if (address_len && len0 < *address_len) *address_len = len0; - return ret; - } - if (errno != ENOSYS) { - return -1; - } - try_accept4 = 0; - } +#else + int result = accept(socket, address, address_len); + if (result == -1) return -1; + + rb_maygvl_fd_fix_cloexec(result); + rsock_make_fd_nonblock(result); #endif - ret = accept(socket, address, address_len); - if (ret == -1) return -1; + if (address_len && len0 < *address_len) *address_len = len0; - rb_maygvl_fd_fix_cloexec(ret); - if (nonblock) { - rsock_make_fd_nonblock(ret); - } - return ret; + return result; } VALUE @@ -712,7 +639,7 @@ rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, int fd2; rb_io_set_nonblock(fptr); - fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1); + fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len); if (fd2 < 0) { int e = errno; switch (e) { @@ -744,42 +671,53 @@ static VALUE accept_blocking(void *data) { struct accept_arg *arg = data; - return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len, 0); + return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len); } VALUE -rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) +rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len) { - int fd2; - int retry = 0; - struct accept_arg arg; + rb_io_t *fptr = NULL; + RB_IO_POINTER(io, fptr); + + struct accept_arg accept_arg = { + .fd = fptr->fd, + .sockaddr = sockaddr, + .len = len + }; + + int retry = 0, peer; - arg.fd = fd; - arg.sockaddr = sockaddr; - arg.len = len; retry: - rsock_maybe_wait_fd(fd); - fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg); - if (fd2 < 0) { - int e = errno; - switch (e) { - case EMFILE: - case ENFILE: - case ENOMEM: - if (retry) break; - rb_gc(); - retry = 1; - goto retry; - default: - if (!rb_io_wait_readable(fd)) break; - retry = 0; - goto retry; - } - rb_syserr_fail(e, "accept(2)"); +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); +#endif + peer = (int)BLOCKING_REGION_FD(accept_blocking, &accept_arg); + if (peer < 0) { + int error = errno; + + switch (error) { + case EMFILE: + case ENFILE: + case ENOMEM: + if (retry) break; + rb_gc(); + retry = 1; + goto retry; + default: + if (!rb_io_maybe_wait_readable(error, io, Qnil)) break; + retry = 0; + goto retry; + } + + rb_syserr_fail(error, "accept(2)"); } - rb_update_max_fd(fd2); - if (!klass) return INT2NUM(fd2); - return rsock_init_sock(rb_obj_alloc(klass), fd2); + + rb_update_max_fd(peer); + + if (!klass) return INT2NUM(peer); + + return rsock_init_sock(rb_obj_alloc(klass), peer); } int diff --git a/ruby/ext/socket/ipsocket.c b/ruby/ext/socket/ipsocket.c index a2cb6e0e1..b5cdc6008 100644 --- a/ruby/ext/socket/ipsocket.c +++ b/ruby/ext/socket/ipsocket.c @@ -19,6 +19,8 @@ struct inetsock_arg } remote, local; int type; int fd; + VALUE resolv_timeout; + VALUE connect_timeout; }; static VALUE @@ -49,10 +51,20 @@ init_inetsock_internal(VALUE v) int fd, status = 0, local = 0; int family = AF_UNSPEC; const char *syscall = 0; + VALUE connect_timeout = arg->connect_timeout; + struct timeval tv_storage; + struct timeval *tv = NULL; + + if (!NIL_P(connect_timeout)) { + tv_storage = rb_time_interval(connect_timeout); + tv = &tv_storage; + } arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, family, SOCK_STREAM, (type == INET_SERVER) ? AI_PASSIVE : 0); + + /* * Maybe also accept a local address */ @@ -113,7 +125,7 @@ init_inetsock_internal(VALUE v) if (status >= 0) { status = rsock_connect(fd, res->ai_addr, res->ai_addrlen, - (type == INET_SOCKS)); + (type == INET_SOCKS), tv); syscall = "connect(2)"; } } @@ -157,7 +169,8 @@ init_inetsock_internal(VALUE v) VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, - VALUE local_host, VALUE local_serv, int type) + VALUE local_host, VALUE local_serv, int type, + VALUE resolv_timeout, VALUE connect_timeout) { struct inetsock_arg arg; arg.sock = sock; @@ -169,6 +182,8 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, arg.local.res = 0; arg.type = type; arg.fd = -1; + arg.resolv_timeout = resolv_timeout; + arg.connect_timeout = connect_timeout; return rb_ensure(init_inetsock_internal, (VALUE)&arg, inetsock_cleanup, (VALUE)&arg); } @@ -243,7 +258,7 @@ ip_inspect(VALUE sock) * If +reverse_lookup+ is +true+ or +:hostname+, * hostname is obtained from numeric_address using reverse lookup. * Or if it is +false+, or +:numeric+, - * hostname is same as numeric_address. + * hostname is the same as numeric_address. * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+. * See +Socket.getaddrinfo+ also. * @@ -284,7 +299,7 @@ ip_addr(int argc, VALUE *argv, VALUE sock) * If +reverse_lookup+ is +true+ or +:hostname+, * hostname is obtained from numeric_address using reverse lookup. * Or if it is +false+, or +:numeric+, - * hostname is same as numeric_address. + * hostname is the same as numeric_address. * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+. * See +Socket.getaddrinfo+ also. * @@ -326,7 +341,7 @@ ip_peeraddr(int argc, VALUE *argv, VALUE sock) * * _flags_ should be a bitwise OR of Socket::MSG_* constants. * - * ipaddr is same as IPSocket#{peeraddr,addr}. + * ipaddr is the same as IPSocket#{peeraddr,addr}. * * u1 = UDPSocket.new * u1.bind("127.0.0.1", 4913) diff --git a/ruby/ext/socket/mkconstants.rb b/ruby/ext/socket/mkconstants.rb index 620a5f60f..577958a35 100644 --- a/ruby/ext/socket/mkconstants.rb +++ b/ruby/ext/socket/mkconstants.rb @@ -358,6 +358,8 @@ def def_intern(func_name, pat, prefix_optional=nil) SOCK_RDM nil A reliable datagram socket provides reliable delivery of messages SOCK_SEQPACKET nil A sequential packet socket provides sequenced, reliable two-way connection for datagrams SOCK_PACKET nil Device-level packet access +SOCK_NONBLOCK nil Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor. +SOCK_CLOEXEC nil Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. AF_UNSPEC nil Unspecified protocol, any supported address family PF_UNSPEC nil Unspecified protocol, any supported address family @@ -397,6 +399,8 @@ def def_intern(func_name, pat, prefix_optional=nil) PF_SNA nil IBM SNA protocol AF_DEC nil DECnet protocol PF_DEC nil DECnet protocol +AF_DECnet nil DECnet protocol +PF_DECnet nil DECnet protocol AF_DLI nil DEC Direct Data Link Interface protocol PF_DLI nil DEC Direct Data Link Interface protocol AF_LAT nil Local Area Transport protocol @@ -438,7 +442,34 @@ def def_intern(func_name, pat, prefix_optional=nil) PF_XTP nil eXpress Transfer Protocol PF_RTIP PF_PIP -PF_KEY +AF_KEY nil Key management protocol, originally developed for usage with IPsec +PF_KEY nil Key management protocol, originally developed for usage with IPsec +AF_NETLINK nil Kernel user interface device +PF_NETLINK nil Kernel user interface device +AF_RDS nil Reliable Datagram Sockets (RDS) protocol +PF_RDS nil Reliable Datagram Sockets (RDS) protocol +AF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) +PF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) +AF_LLC nil Logical link control (IEEE 802.2 LLC) protocol +PF_LLC nil Logical link control (IEEE 802.2 LLC) protocol +AF_IB nil InfiniBand native addressing +PF_IB nil InfiniBand native addressing +AF_MPLS nil Multiprotocol Label Switching +PF_MPLS nil Multiprotocol Label Switching +AF_CAN nil Controller Area Network automotive bus protocol +PF_CAN nil Controller Area Network automotive bus protocol +AF_TIPC nil TIPC, "cluster domain sockets" protocol +PF_TIPC nil TIPC, "cluster domain sockets" protocol +AF_BLUETOOTH nil Bluetooth low-level socket protocol +PF_BLUETOOTH nil Bluetooth low-level socket protocol +AF_ALG nil Interface to kernel crypto API +PF_ALG nil Interface to kernel crypto API +AF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication +PF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication +AF_KCM nil KCM (kernel connection multiplexor) interface +PF_KCM nil KCM (kernel connection multiplexor) interface +AF_XDP nil XDP (express data path) interface +PF_XDP nil XDP (express data path) interface MSG_OOB nil Process out-of-band data MSG_PEEK nil Peek at incoming message diff --git a/ruby/ext/socket/option.c b/ruby/ext/socket/option.c index 5ad44cdcd..4b33b3f1d 100644 --- a/ruby/ext/socket/option.c +++ b/ruby/ext/socket/option.c @@ -106,9 +106,9 @@ sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALU VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data) { - NEWOBJ_OF(obj, struct RObject, rb_cSockOpt, T_OBJECT); + VALUE obj = rb_obj_alloc(rb_cSockOpt); StringValue(data); - sockopt_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); + sockopt_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); return (VALUE)obj; } diff --git a/ruby/ext/socket/raddrinfo.c b/ruby/ext/socket/raddrinfo.c index 9ec2fdc32..d94e96a2b 100644 --- a/ruby/ext/socket/raddrinfo.c +++ b/ruby/ext/socket/raddrinfo.c @@ -199,27 +199,6 @@ nogvl_getaddrinfo(void *arg) } #endif -#ifdef HAVE_GETADDRINFO_A -struct gai_suspend_arg -{ - struct gaicb *req; - struct timespec *timeout; -}; - -static void * -nogvl_gai_suspend(void *arg) -{ - int ret; - struct gai_suspend_arg *ptr = arg; - struct gaicb const *wait_reqs[1]; - - wait_reqs[0] = ptr->req; - ret = gai_suspend(wait_reqs, 1, ptr->timeout); - - return (void *)(VALUE)ret; -} -#endif - static int numeric_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, @@ -305,93 +284,6 @@ numeric_getaddrinfo(const char *node, const char *service, return EAI_FAIL; } -int -rb_getaddrinfo(const char *node, const char *service, - const struct addrinfo *hints, - struct rb_addrinfo **res) -{ - struct addrinfo *ai; - int ret; - int allocated_by_malloc = 0; - - ret = numeric_getaddrinfo(node, service, hints, &ai); - if (ret == 0) - allocated_by_malloc = 1; - else { -#ifdef GETADDRINFO_EMU - ret = getaddrinfo(node, service, hints, &ai); -#else - struct getaddrinfo_arg arg; - MEMZERO(&arg, struct getaddrinfo_arg, 1); - arg.node = node; - arg.service = service; - arg.hints = hints; - arg.res = &ai; - ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); -#endif - } - - if (ret == 0) { - *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); - (*res)->allocated_by_malloc = allocated_by_malloc; - (*res)->ai = ai; - } - return ret; -} - -#ifdef HAVE_GETADDRINFO_A -int -rb_getaddrinfo_a(const char *node, const char *service, - const struct addrinfo *hints, - struct rb_addrinfo **res, struct timespec *timeout) -{ - struct addrinfo *ai; - int ret; - int allocated_by_malloc = 0; - - ret = numeric_getaddrinfo(node, service, hints, &ai); - if (ret == 0) - allocated_by_malloc = 1; - else { - struct gai_suspend_arg arg; - struct gaicb *reqs[1]; - struct gaicb req; - - req.ar_name = node; - req.ar_service = service; - req.ar_request = hints; - - reqs[0] = &req; - ret = getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL); - if (ret) return ret; - - arg.req = &req; - arg.timeout = timeout; - - ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_gai_suspend, &arg, RUBY_UBF_IO, 0); - - if (ret) { - /* on Ubuntu 18.04 (or other systems), gai_suspend(3) returns EAI_SYSTEM/ENOENT on timeout */ - if (ret == EAI_SYSTEM && errno == ENOENT) { - return EAI_AGAIN; - } else { - return ret; - } - } - - ret = gai_error(reqs[0]); - ai = reqs[0]->ar_result; - } - - if (ret == 0) { - *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); - (*res)->allocated_by_malloc = allocated_by_malloc; - (*res)->ai = ai; - } - return ret; -} -#endif - void rb_freeaddrinfo(struct rb_addrinfo *ai) { @@ -572,41 +464,63 @@ port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr) } } -struct rb_addrinfo* -rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack) -{ - struct rb_addrinfo* res = NULL; - char *hostp, *portp; - int error; - char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; - int additional_flags = 0; - - hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags); - portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); - - if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { - hints->ai_socktype = SOCK_DGRAM; - } - hints->ai_flags |= additional_flags; - - error = rb_getaddrinfo(hostp, portp, hints, &res); - if (error) { - if (hostp && hostp[strlen(hostp)-1] == '\n') { - rb_raise(rb_eSocket, "newline at the end of hostname"); +static int +rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service, + const struct addrinfo *hints, struct rb_addrinfo **res) +{ + int error, res_allocated = 0, _additional_flags = 0; + long i, len; + struct addrinfo *ai, *ai_tail = NULL; + char *hostp; + char _hbuf[NI_MAXHOST]; + VALUE ip_addresses_array, ip_address; + + ip_addresses_array = rb_fiber_scheduler_address_resolve(scheduler, host); + + if (ip_addresses_array == Qundef) { + // Returns EAI_FAIL if the scheduler hook is not implemented: + return EAI_FAIL; + } else if (ip_addresses_array == Qnil) { + len = 0; + } else { + len = RARRAY_LEN(ip_addresses_array); + } + + for(i=0; iallocated_by_malloc = 1; + (*res)->ai = ai; + ai_tail = ai; + } else { + while (ai_tail->ai_next) { + ai_tail = ai_tail->ai_next; + } + ai_tail->ai_next = ai; + ai_tail = ai; + } } - rsock_raise_socket_error("getaddrinfo", error); } - return res; + if (res_allocated) { // At least one valid result. + return 0; + } else { + return EAI_NONAME; + } } -#ifdef HAVE_GETADDRINFO_A -static struct rb_addrinfo* -rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout) +struct rb_addrinfo* +rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack) { struct rb_addrinfo* res = NULL; + struct addrinfo *ai; char *hostp, *portp; - int error; + int error = 0; char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; int additional_flags = 0; @@ -614,27 +528,56 @@ rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { - hints->ai_socktype = SOCK_DGRAM; + hints->ai_socktype = SOCK_DGRAM; } hints->ai_flags |= additional_flags; - if (NIL_P(timeout)) { - error = rb_getaddrinfo(hostp, portp, hints, &res); + error = numeric_getaddrinfo(hostp, portp, hints, &ai); + if (error == 0) { + res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + res->allocated_by_malloc = 1; + res->ai = ai; } else { - struct timespec _timeout = rb_time_timespec_interval(timeout); - error = rb_getaddrinfo_a(hostp, portp, hints, &res, &_timeout); + VALUE scheduler = rb_fiber_scheduler_current(); + int resolved = 0; + + if (scheduler != Qnil && hostp && !(hints->ai_flags & AI_NUMERICHOST)) { + error = rb_scheduler_getaddrinfo(scheduler, host, portp, hints, &res); + + if (error != EAI_FAIL) { + resolved = 1; + } + } + + if (!resolved) { +#ifdef GETADDRINFO_EMU + error = getaddrinfo(hostp, portp, hints, &ai); +#else + struct getaddrinfo_arg arg; + MEMZERO(&arg, struct getaddrinfo_arg, 1); + arg.node = hostp; + arg.service = portp; + arg.hints = hints; + arg.res = &ai; + error = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); +#endif + if (error == 0) { + res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + res->allocated_by_malloc = 0; + res->ai = ai; + } + } } if (error) { if (hostp && hostp[strlen(hostp)-1] == '\n') { rb_raise(rb_eSocket, "newline at the end of hostname"); } - rsock_raise_socket_error("getaddrinfo_a", error); + rsock_raise_socket_error("getaddrinfo", error); } return res; } -#endif int rsock_fd_family(int fd) @@ -941,15 +884,7 @@ call_getaddrinfo(VALUE node, VALUE service, hints.ai_flags = NUM2INT(flags); } -#ifdef HAVE_GETADDRINFO_A - if (NIL_P(timeout)) { - res = rsock_getaddrinfo(node, service, &hints, socktype_hack); - } else { - res = rsock_getaddrinfo_a(node, service, &hints, socktype_hack, timeout); - } -#else res = rsock_getaddrinfo(node, service, &hints, socktype_hack); -#endif if (res == NULL) rb_raise(rb_eSocket, "host not found"); @@ -1913,7 +1848,7 @@ addrinfo_to_sockaddr(VALUE self) * call-seq: * addrinfo.canonname => string or nil * - * returns the canonical name as an string. + * returns the canonical name as a string. * * nil is returned if no canonical name. * @@ -2686,7 +2621,7 @@ rsock_init_addrinfo(void) */ id_timeout = rb_intern("timeout"); - rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); + rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject); rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); diff --git a/ruby/ext/socket/rubysocket.h b/ruby/ext/socket/rubysocket.h index 0ce77a5f6..c0d40addc 100644 --- a/ruby/ext/socket/rubysocket.h +++ b/ruby/ext/socket/rubysocket.h @@ -1,12 +1,22 @@ #ifndef RUBY_SOCKET_H #define RUBY_SOCKET_H 1 -#include "ruby/ruby.h" -#include "ruby/io.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "internal.h" +#include "ruby/config.h" +#include RUBY_EXTCONF_H + +#if defined(__sun) || defined(_AIX) +/* (Recent?) Solaris' have conflicting definition of T_DATA. Let + * us honour system definition by undefining ours. + * + * See also [ruby-core:4261] + */ +# include "ruby/ruby.h" +# undef T_DATA +#endif + +#include #include + #include #include @@ -26,13 +36,7 @@ # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL # endif -/* - * FIXME: failures if we make nonblocking the default - * [ruby-core:89973] [ruby-core:89976] [ruby-core:89977] [Bug #14968] - */ -# define RSOCK_NONBLOCK_DEFAULT (0) #else -# define RSOCK_NONBLOCK_DEFAULT (0) # include # include # ifdef HAVE_NETINET_IN_SYSTM_H @@ -56,12 +60,11 @@ #ifdef HAVE_NETPACKET_PACKET_H # include #endif + #ifdef HAVE_NET_ETHERNET_H # include #endif -#include - #ifdef HAVE_SYS_UN_H # include #endif @@ -87,12 +90,15 @@ # endif # include #endif + #ifdef HAVE_SYS_IOCTL_H # include #endif + #ifdef HAVE_SYS_SOCKIO_H # include #endif + #ifdef HAVE_NET_IF_H # include #endif @@ -100,16 +106,41 @@ #ifdef HAVE_SYS_PARAM_H # include #endif + #ifdef HAVE_SYS_UCRED_H # include #endif + #ifdef HAVE_UCRED_H # include #endif + #ifdef HAVE_NET_IF_DL_H # include #endif +#ifdef SOCKS5 +# include +#endif + +#ifndef HAVE_GETADDRINFO +# include "addrinfo.h" +#endif + +#include "internal.h" +#include "internal/array.h" +#include "internal/error.h" +#include "internal/gc.h" +#include "internal/io.h" +#include "internal/thread.h" +#include "internal/vm.h" +#include "ruby/io.h" +#include "ruby/ruby.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "sockport.h" +#include "ruby/fiber/scheduler.h" + #ifndef HAVE_TYPE_SOCKLEN_T typedef int socklen_t; #endif @@ -143,11 +174,6 @@ unsigned int if_nametoindex(const char *); */ #define pseudo_AF_FTIP pseudo_AF_RTIP -#ifndef HAVE_GETADDRINFO -# include "addrinfo.h" -#endif - -#include "sockport.h" #ifndef NI_MAXHOST # define NI_MAXHOST 1025 @@ -229,7 +255,6 @@ typedef union { #define INET_SOCKS 2 extern int rsock_do_not_reverse_lookup; -extern int rsock_cmsg_cloexec_state; #define FMODE_NOREVLOOKUP 0x100 /* common socket families only */ @@ -255,9 +280,7 @@ extern VALUE rb_eSocket; #ifdef SOCKS extern VALUE rb_cSOCKSSocket; -# ifdef SOCKS5 -# include -# else +# ifndef SOCKS5 void SOCKSinit(); int Rconnect(); # endif @@ -291,13 +314,13 @@ struct rb_addrinfo { struct addrinfo *ai; int allocated_by_malloc; }; -int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res); void rb_freeaddrinfo(struct rb_addrinfo *ai); VALUE rsock_freeaddrinfo(VALUE arg); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); int rsock_fd_family(int fd); struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags); struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack); + VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len); VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len); @@ -323,7 +346,7 @@ int rsock_socket(int domain, int type, int proto); int rsock_detect_cloexec(int fd); VALUE rsock_init_sock(VALUE sock, int fd); VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass); -VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type); +VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout); VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server); struct rsock_send_arg { @@ -348,9 +371,9 @@ VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex, enum sock_recv_type from); VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from); -int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks); +int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout); -VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len); +VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len); VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len); VALUE rsock_sock_listen(VALUE sock, VALUE log); @@ -409,30 +432,17 @@ NORETURN(void rsock_sys_fail_sockaddr(const char *, struct sockaddr *addr, sockl NORETURN(void rsock_sys_fail_raddrinfo(const char *, VALUE rai)); NORETURN(void rsock_sys_fail_raddrinfo_or_sockaddr(const char *, VALUE addr, VALUE rai)); -/* - * It is safe on Linux to attempt using a socket without waiting on it in - * all cases. For some syscalls (e.g. accept/accept4), blocking on the - * syscall instead of relying on select/poll allows the kernel to use - * "wake-one" behavior and avoid the thundering herd problem. - * This is likely safe on all other *nix-like systems, so this safe list - * can be expanded by interested parties. - */ -#if defined(__linux__) -static inline int rsock_maybe_fd_writable(int fd) { return 1; } -static inline void rsock_maybe_wait_fd(int fd) { } -# ifdef MSG_DONTWAIT -# define MSG_DONTWAIT_RELIABLE 1 -# endif -#else /* some systems (mswin/mingw) need these. ref: r36946 */ -# define rsock_maybe_fd_writable(fd) rb_thread_fd_writable((fd)) -# define rsock_maybe_wait_fd(fd) rb_thread_wait_fd((fd)) +#if defined(__MINGW32__) || defined(_WIN32) +#define RSOCK_WAIT_BEFORE_BLOCKING #endif /* * some OSes may support MSG_DONTWAIT inconsistently depending on socket * type, we only expect Linux to support it consistently for all socket types. */ -#ifndef MSG_DONTWAIT_RELIABLE +#if defined(MSG_DONTWAIT) && defined(__linux__) +# define MSG_DONTWAIT_RELIABLE 1 +#else # define MSG_DONTWAIT_RELIABLE 0 #endif diff --git a/ruby/ext/socket/socket.c b/ruby/ext/socket/socket.c index bfeb30340..ccf990d11 100644 --- a/ruby/ext/socket/socket.c +++ b/ruby/ext/socket/socket.c @@ -168,93 +168,47 @@ pair_yield(VALUE pair) #endif #if defined HAVE_SOCKETPAIR - -#ifdef SOCK_CLOEXEC static int -rsock_socketpair0(int domain, int type, int protocol, int sv[2]) +rsock_socketpair0(int domain, int type, int protocol, int descriptors[2]) { - int ret; - static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ - static const int default_flags = SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT; +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif - if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */ - ret = socketpair(domain, type|default_flags, protocol, sv); - if (ret == 0 && (sv[0] <= 2 || sv[1] <= 2)) { - goto fix_cloexec; /* highly unlikely */ - } - goto update_max_fd; - } - else if (cloexec_state < 0) { /* usually runs once only for detection */ - ret = socketpair(domain, type|default_flags, protocol, sv); - if (ret == 0) { - cloexec_state = rsock_detect_cloexec(sv[0]); - if ((cloexec_state == 0) || (sv[0] <= 2 || sv[1] <= 2)) - goto fix_cloexec; - goto update_max_fd; - } - else if (ret == -1 && errno == EINVAL) { - /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ - ret = socketpair(domain, type, protocol, sv); - if (ret != -1) { - /* The reason of EINVAL may be other than SOCK_CLOEXEC. - * So disable SOCK_CLOEXEC only if socketpair() succeeds without SOCK_CLOEXEC. - * Ex. Socket.pair(:UNIX, 0xff) fails with EINVAL. - */ - cloexec_state = 0; - } - } - } - else { /* cloexec_state == 0 */ - ret = socketpair(domain, type, protocol, sv); - } - if (ret == -1) { - return -1; - } +#ifdef SOCK_NONBLOCK + type |= SOCK_NONBLOCK; +#endif -fix_cloexec: - rb_maygvl_fd_fix_cloexec(sv[0]); - rb_maygvl_fd_fix_cloexec(sv[1]); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(sv[0]); - rsock_make_fd_nonblock(sv[1]); - } + int result = socketpair(domain, type, protocol, descriptors); -update_max_fd: - rb_update_max_fd(sv[0]); - rb_update_max_fd(sv[1]); + if (result == -1) + return -1; - return ret; -} -#else /* !SOCK_CLOEXEC */ -static int -rsock_socketpair0(int domain, int type, int protocol, int sv[2]) -{ - int ret = socketpair(domain, type, protocol, sv); +#ifndef SOCK_CLOEXEC + rb_fd_fix_cloexec(descriptors[0]); + rb_fd_fix_cloexec(descriptors[1]); +#endif - if (ret == -1) - return -1; +#ifndef SOCK_NONBLOCK + rsock_make_fd_nonblock(descriptors[0]); + rsock_make_fd_nonblock(descriptors[1]); +#endif - rb_fd_fix_cloexec(sv[0]); - rb_fd_fix_cloexec(sv[1]); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(sv[0]); - rsock_make_fd_nonblock(sv[1]); - } - return ret; + return result; } -#endif /* !SOCK_CLOEXEC */ static int -rsock_socketpair(int domain, int type, int protocol, int sv[2]) +rsock_socketpair(int domain, int type, int protocol, int descriptors[2]) { - int ret; + int result; + + result = rsock_socketpair0(domain, type, protocol, descriptors); - ret = rsock_socketpair0(domain, type, protocol, sv); - if (ret < 0 && rb_gc_for_fd(errno)) { - ret = rsock_socketpair0(domain, type, protocol, sv); + if (result < 0 && rb_gc_for_fd(errno)) { + result = rsock_socketpair0(domain, type, protocol, descriptors); } - return ret; + return result; } /* @@ -376,7 +330,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket * bound to the specified peer address - * * Errno::ETIMEDOUT - the attempt to connect time out before a connection + * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection * was made. * * On unix-based systems if the address family of the calling +socket+ is @@ -417,7 +371,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) * * Errno::EHOSTUNREACH - no route to the network is present * * Errno::ENOBUFS - no buffer space is available * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket - * * Errno::ETIMEDOUT - the attempt to connect time out before a connection + * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection * was made. * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the * connection cannot be completed immediately @@ -439,7 +393,7 @@ sock_connect(VALUE sock, VALUE addr) addr = rb_str_new4(addr); GetOpenFile(sock, fptr); fd = fptr->fd; - n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0); + n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, NULL); if (n < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai); } @@ -796,17 +750,14 @@ sock_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex) * */ static VALUE -sock_accept(VALUE sock) +sock_accept(VALUE server) { - rb_io_t *fptr; - VALUE sock2; - union_sockaddr buf; - socklen_t len = (socklen_t)sizeof buf; + union_sockaddr buffer; + socklen_t length = (socklen_t)sizeof(buffer); - GetOpenFile(sock, fptr); - sock2 = rsock_s_accept(rb_cSocket,fptr->fd,&buf.addr,&len); + VALUE peer = rsock_s_accept(rb_cSocket, server, &buffer.addr, &length); - return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); + return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length)); } /* :nodoc: */ @@ -866,17 +817,14 @@ sock_accept_nonblock(VALUE sock, VALUE ex) * * Socket#accept */ static VALUE -sock_sysaccept(VALUE sock) +sock_sysaccept(VALUE server) { - rb_io_t *fptr; - VALUE sock2; - union_sockaddr buf; - socklen_t len = (socklen_t)sizeof buf; + union_sockaddr buffer; + socklen_t length = (socklen_t)sizeof(buffer); - GetOpenFile(sock, fptr); - sock2 = rsock_s_accept(0,fptr->fd,&buf.addr,&len); + VALUE peer = rsock_s_accept(0, server, &buffer.addr, &length); - return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); + return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length)); } #ifdef HAVE_GETHOSTNAME @@ -1011,6 +959,7 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE sock_s_gethostbyname(VALUE obj, VALUE host) { + rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); return rsock_make_hostent(host, res, sock_sockaddr); @@ -1050,6 +999,8 @@ sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _) VALUE ary, names; int t = AF_INET; + rb_warn("Socket.gethostbyaddr is deprecated; use Addrinfo#getnameinfo instead."); + rb_scan_args(argc, argv, "11", &addr, &family); StringValue(addr); if (!NIL_P(family)) { @@ -1197,7 +1148,7 @@ sock_s_getservbyport(int argc, VALUE *argv, VALUE _) * be one of below. If _reverse_lookup_ is omitted, the default value is +nil+. * * +true+, +:hostname+: hostname is obtained from numeric address using reverse lookup, which may take a time. - * +false+, +:numeric+: hostname is same as numeric address. + * +false+, +:numeric+: hostname is the same as numeric address. * +nil+: obey to the current +do_not_reverse_lookup+ flag. * * If Addrinfo object is preferred, use Addrinfo.getaddrinfo. @@ -1227,6 +1178,7 @@ sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _) if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) { norevlookup = rsock_do_not_reverse_lookup; } + res = rsock_getaddrinfo(host, port, &hints, 0); ret = make_addrinfo(res, norevlookup); @@ -1260,7 +1212,6 @@ static VALUE sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) { VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp; - char *hptr, *pptr; char hbuf[1024], pbuf[1024]; int fl; struct rb_addrinfo *res = NULL; @@ -1321,34 +1272,10 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given", RARRAY_LEN(sa)); } - /* host */ - if (NIL_P(host)) { - hptr = NULL; - } - else { - strncpy(hbuf, StringValueCStr(host), sizeof(hbuf)); - hbuf[sizeof(hbuf) - 1] = '\0'; - hptr = hbuf; - } - /* port */ - if (NIL_P(port)) { - strcpy(pbuf, "0"); - pptr = NULL; - } - else if (FIXNUM_P(port)) { - snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port)); - pptr = pbuf; - } - else { - strncpy(pbuf, StringValueCStr(port), sizeof(pbuf)); - pbuf[sizeof(pbuf) - 1] = '\0'; - pptr = pbuf; - } hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; /* af */ hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af); - error = rb_getaddrinfo(hptr, pptr, &hints, &res); - if (error) goto error_exit_addr; + res = rsock_getaddrinfo(host, port, &hints, 0); sap = res->ai->ai_addr; salen = res->ai->ai_addrlen; } @@ -1378,12 +1305,6 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) } return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); - error_exit_addr: - saved_errno = errno; - if (res) rb_freeaddrinfo(res); - errno = saved_errno; - rsock_raise_socket_error("getaddrinfo", error); - error_exit_name: saved_errno = errno; if (res) rb_freeaddrinfo(res); @@ -1936,6 +1857,8 @@ socket_s_ip_address_list(VALUE self) void Init_socket(void) { + rb_ext_ractor_safe(true); + rsock_init_basicsocket(); /* diff --git a/ruby/ext/socket/sockssocket.c b/ruby/ext/socket/sockssocket.c index 82789eeaa..b8b7e1299 100644 --- a/ruby/ext/socket/sockssocket.c +++ b/ruby/ext/socket/sockssocket.c @@ -34,7 +34,7 @@ socks_init(VALUE sock, VALUE host, VALUE port) init = 1; } - return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS); + return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil); } #ifdef SOCKS5 diff --git a/ruby/ext/socket/tcpserver.c b/ruby/ext/socket/tcpserver.c index 1bbb31adc..675733c6f 100644 --- a/ruby/ext/socket/tcpserver.c +++ b/ruby/ext/socket/tcpserver.c @@ -36,7 +36,7 @@ tcp_svr_init(int argc, VALUE *argv, VALUE sock) VALUE hostname, port; rb_scan_args(argc, argv, "011", &hostname, &port); - return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER); + return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil); } /* @@ -53,15 +53,12 @@ tcp_svr_init(int argc, VALUE *argv, VALUE sock) * */ static VALUE -tcp_accept(VALUE sock) +tcp_accept(VALUE server) { - rb_io_t *fptr; - union_sockaddr from; - socklen_t fromlen; + union_sockaddr buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(from); - return rsock_s_accept(rb_cTCPSocket, fptr->fd, &from.addr, &fromlen); + return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length); } /* :nodoc: */ @@ -91,15 +88,12 @@ tcp_accept_nonblock(VALUE sock, VALUE ex) * */ static VALUE -tcp_sysaccept(VALUE sock) +tcp_sysaccept(VALUE server) { - rb_io_t *fptr; - union_sockaddr from; - socklen_t fromlen; + union_sockaddr buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(from); - return rsock_s_accept(0, fptr->fd, &from.addr, &fromlen); + return rsock_s_accept(0, server, &buffer.addr, &length); } void diff --git a/ruby/ext/socket/tcpsocket.c b/ruby/ext/socket/tcpsocket.c index 29a3eda45..51e77a0de 100644 --- a/ruby/ext/socket/tcpsocket.c +++ b/ruby/ext/socket/tcpsocket.c @@ -12,23 +12,42 @@ /* * call-seq: - * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil) + * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, connect_timeout: nil) * * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+ * and +local_port+ are specified, then those parameters are used on the local * end to establish the connection. + * + * [:connect_timeout] specify the timeout in seconds. */ static VALUE tcp_init(int argc, VALUE *argv, VALUE sock) { VALUE remote_host, remote_serv; VALUE local_host, local_serv; + VALUE opt; + static ID keyword_ids[2]; + VALUE kwargs[2]; + VALUE resolv_timeout = Qnil; + VALUE connect_timeout = Qnil; + + if (!keyword_ids[0]) { + CONST_ID(keyword_ids[0], "resolv_timeout"); + CONST_ID(keyword_ids[1], "connect_timeout"); + } + + rb_scan_args(argc, argv, "22:", &remote_host, &remote_serv, + &local_host, &local_serv, &opt); - rb_scan_args(argc, argv, "22", &remote_host, &remote_serv, - &local_host, &local_serv); + if (!NIL_P(opt)) { + rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs); + if (kwargs[0] != Qundef) { resolv_timeout = kwargs[0]; } + if (kwargs[1] != Qundef) { connect_timeout = kwargs[1]; } + } return rsock_init_inetsock(sock, remote_host, remote_serv, - local_host, local_serv, INET_CLIENT); + local_host, local_serv, INET_CLIENT, + resolv_timeout, connect_timeout); } static VALUE @@ -59,6 +78,7 @@ tcp_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE tcp_s_gethostbyname(VALUE obj, VALUE host) { + rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); return rsock_make_hostent(host, res, tcp_sockaddr); diff --git a/ruby/ext/socket/udpsocket.c b/ruby/ext/socket/udpsocket.c index 6ef8242a1..2bfd7c856 100644 --- a/ruby/ext/socket/udpsocket.c +++ b/ruby/ext/socket/udpsocket.c @@ -60,7 +60,7 @@ udp_connect_internal(VALUE v) rb_io_check_closed(fptr = arg->fptr); fd = fptr->fd; for (res = arg->res->ai; res; res = res->ai_next) { - if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) { + if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0, NULL) >= 0) { return Qtrue; } } @@ -153,23 +153,26 @@ udp_send_internal(VALUE v) { struct udp_send_arg *arg = (void *)v; rb_io_t *fptr; - int n; struct addrinfo *res; rb_io_check_closed(fptr = arg->fptr); for (res = arg->res->ai; res; res = res->ai_next) { retry: - arg->sarg.fd = fptr->fd; - arg->sarg.to = res->ai_addr; - arg->sarg.tolen = res->ai_addrlen; - rsock_maybe_fd_writable(arg->sarg.fd); - n = (int)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg->sarg); - if (n >= 0) { - return INT2FIX(n); - } - if (rb_io_wait_writable(fptr->fd)) { - goto retry; - } + arg->sarg.fd = fptr->fd; + arg->sarg.to = res->ai_addr; + arg->sarg.tolen = res->ai_addrlen; + +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil); +#endif + + ssize_t n = (ssize_t)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg->sarg); + + if (n >= 0) return RB_SSIZE2NUM(n); + + if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) { + goto retry; + } } return Qfalse; } diff --git a/ruby/ext/socket/unixserver.c b/ruby/ext/socket/unixserver.c index b1f2a3854..890f9d3fa 100644 --- a/ruby/ext/socket/unixserver.c +++ b/ruby/ext/socket/unixserver.c @@ -47,16 +47,12 @@ unix_svr_init(VALUE sock, VALUE path) * */ static VALUE -unix_accept(VALUE sock) +unix_accept(VALUE server) { - rb_io_t *fptr; - struct sockaddr_un from; - socklen_t fromlen; + struct sockaddr_un buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(struct sockaddr_un); - return rsock_s_accept(rb_cUNIXSocket, fptr->fd, - (struct sockaddr*)&from, &fromlen); + return rsock_s_accept(rb_cUNIXSocket, server, (struct sockaddr*)&buffer, &length); } /* :nodoc: */ @@ -92,15 +88,12 @@ unix_accept_nonblock(VALUE sock, VALUE ex) * */ static VALUE -unix_sysaccept(VALUE sock) +unix_sysaccept(VALUE server) { - rb_io_t *fptr; - struct sockaddr_un from; - socklen_t fromlen; + struct sockaddr_un buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(struct sockaddr_un); - return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); + return rsock_s_accept(0, server, (struct sockaddr*)&buffer, &length); } #endif diff --git a/ruby/ext/socket/unixsocket.c b/ruby/ext/socket/unixsocket.c index 0c3a01d21..857cfa600 100644 --- a/ruby/ext/socket/unixsocket.c +++ b/ruby/ext/socket/unixsocket.c @@ -22,7 +22,7 @@ unixsock_connect_internal(VALUE a) { struct unixsock_arg *arg = (struct unixsock_arg *)a; return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr, - arg->sockaddrlen, 0); + arg->sockaddrlen, 0, NULL); } static VALUE @@ -455,11 +455,7 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock) #endif rb_update_max_fd(fd); - - if (rsock_cmsg_cloexec_state < 0) - rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd); - if (rsock_cmsg_cloexec_state == 0 || fd <= 2) - rb_maygvl_fd_fix_cloexec(fd); + rb_maygvl_fd_fix_cloexec(fd); if (klass == Qnil) return INT2FIX(fd); diff --git a/ruby/ext/stringio/depend b/ruby/ext/stringio/depend index 02d468b30..7b70a77d2 100644 --- a/ruby/ext/stringio/depend +++ b/ruby/ext/stringio/depend @@ -4,9 +4,165 @@ stringio.o: $(arch_hdrdir)/ruby/config.h stringio.o: $(hdrdir)/ruby.h stringio.o: $(hdrdir)/ruby/assert.h stringio.o: $(hdrdir)/ruby/backward.h +stringio.o: $(hdrdir)/ruby/backward/2/assume.h +stringio.o: $(hdrdir)/ruby/backward/2/attributes.h +stringio.o: $(hdrdir)/ruby/backward/2/bool.h +stringio.o: $(hdrdir)/ruby/backward/2/inttypes.h +stringio.o: $(hdrdir)/ruby/backward/2/limits.h +stringio.o: $(hdrdir)/ruby/backward/2/long_long.h +stringio.o: $(hdrdir)/ruby/backward/2/stdalign.h +stringio.o: $(hdrdir)/ruby/backward/2/stdarg.h stringio.o: $(hdrdir)/ruby/defines.h stringio.o: $(hdrdir)/ruby/encoding.h stringio.o: $(hdrdir)/ruby/intern.h +stringio.o: $(hdrdir)/ruby/internal/anyargs.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/char.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/double.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/int.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/long.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/short.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +stringio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +stringio.o: $(hdrdir)/ruby/internal/assume.h +stringio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +stringio.o: $(hdrdir)/ruby/internal/attr/artificial.h +stringio.o: $(hdrdir)/ruby/internal/attr/cold.h +stringio.o: $(hdrdir)/ruby/internal/attr/const.h +stringio.o: $(hdrdir)/ruby/internal/attr/constexpr.h +stringio.o: $(hdrdir)/ruby/internal/attr/deprecated.h +stringio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +stringio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +stringio.o: $(hdrdir)/ruby/internal/attr/error.h +stringio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +stringio.o: $(hdrdir)/ruby/internal/attr/forceinline.h +stringio.o: $(hdrdir)/ruby/internal/attr/format.h +stringio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +stringio.o: $(hdrdir)/ruby/internal/attr/noalias.h +stringio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +stringio.o: $(hdrdir)/ruby/internal/attr/noexcept.h +stringio.o: $(hdrdir)/ruby/internal/attr/noinline.h +stringio.o: $(hdrdir)/ruby/internal/attr/nonnull.h +stringio.o: $(hdrdir)/ruby/internal/attr/noreturn.h +stringio.o: $(hdrdir)/ruby/internal/attr/pure.h +stringio.o: $(hdrdir)/ruby/internal/attr/restrict.h +stringio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +stringio.o: $(hdrdir)/ruby/internal/attr/warning.h +stringio.o: $(hdrdir)/ruby/internal/attr/weakref.h +stringio.o: $(hdrdir)/ruby/internal/cast.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +stringio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +stringio.o: $(hdrdir)/ruby/internal/compiler_since.h +stringio.o: $(hdrdir)/ruby/internal/config.h +stringio.o: $(hdrdir)/ruby/internal/constant_p.h +stringio.o: $(hdrdir)/ruby/internal/core.h +stringio.o: $(hdrdir)/ruby/internal/core/rarray.h +stringio.o: $(hdrdir)/ruby/internal/core/rbasic.h +stringio.o: $(hdrdir)/ruby/internal/core/rbignum.h +stringio.o: $(hdrdir)/ruby/internal/core/rclass.h +stringio.o: $(hdrdir)/ruby/internal/core/rdata.h +stringio.o: $(hdrdir)/ruby/internal/core/rfile.h +stringio.o: $(hdrdir)/ruby/internal/core/rhash.h +stringio.o: $(hdrdir)/ruby/internal/core/robject.h +stringio.o: $(hdrdir)/ruby/internal/core/rregexp.h +stringio.o: $(hdrdir)/ruby/internal/core/rstring.h +stringio.o: $(hdrdir)/ruby/internal/core/rstruct.h +stringio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +stringio.o: $(hdrdir)/ruby/internal/ctype.h +stringio.o: $(hdrdir)/ruby/internal/dllexport.h +stringio.o: $(hdrdir)/ruby/internal/dosish.h +stringio.o: $(hdrdir)/ruby/internal/encoding/coderange.h +stringio.o: $(hdrdir)/ruby/internal/encoding/ctype.h +stringio.o: $(hdrdir)/ruby/internal/encoding/encoding.h +stringio.o: $(hdrdir)/ruby/internal/encoding/pathname.h +stringio.o: $(hdrdir)/ruby/internal/encoding/re.h +stringio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +stringio.o: $(hdrdir)/ruby/internal/encoding/string.h +stringio.o: $(hdrdir)/ruby/internal/encoding/symbol.h +stringio.o: $(hdrdir)/ruby/internal/encoding/transcode.h +stringio.o: $(hdrdir)/ruby/internal/error.h +stringio.o: $(hdrdir)/ruby/internal/eval.h +stringio.o: $(hdrdir)/ruby/internal/event.h +stringio.o: $(hdrdir)/ruby/internal/fl_type.h +stringio.o: $(hdrdir)/ruby/internal/gc.h +stringio.o: $(hdrdir)/ruby/internal/glob.h +stringio.o: $(hdrdir)/ruby/internal/globals.h +stringio.o: $(hdrdir)/ruby/internal/has/attribute.h +stringio.o: $(hdrdir)/ruby/internal/has/builtin.h +stringio.o: $(hdrdir)/ruby/internal/has/c_attribute.h +stringio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +stringio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +stringio.o: $(hdrdir)/ruby/internal/has/extension.h +stringio.o: $(hdrdir)/ruby/internal/has/feature.h +stringio.o: $(hdrdir)/ruby/internal/has/warning.h +stringio.o: $(hdrdir)/ruby/internal/intern/array.h +stringio.o: $(hdrdir)/ruby/internal/intern/bignum.h +stringio.o: $(hdrdir)/ruby/internal/intern/class.h +stringio.o: $(hdrdir)/ruby/internal/intern/compar.h +stringio.o: $(hdrdir)/ruby/internal/intern/complex.h +stringio.o: $(hdrdir)/ruby/internal/intern/cont.h +stringio.o: $(hdrdir)/ruby/internal/intern/dir.h +stringio.o: $(hdrdir)/ruby/internal/intern/enum.h +stringio.o: $(hdrdir)/ruby/internal/intern/enumerator.h +stringio.o: $(hdrdir)/ruby/internal/intern/error.h +stringio.o: $(hdrdir)/ruby/internal/intern/eval.h +stringio.o: $(hdrdir)/ruby/internal/intern/file.h +stringio.o: $(hdrdir)/ruby/internal/intern/gc.h +stringio.o: $(hdrdir)/ruby/internal/intern/hash.h +stringio.o: $(hdrdir)/ruby/internal/intern/io.h +stringio.o: $(hdrdir)/ruby/internal/intern/load.h +stringio.o: $(hdrdir)/ruby/internal/intern/marshal.h +stringio.o: $(hdrdir)/ruby/internal/intern/numeric.h +stringio.o: $(hdrdir)/ruby/internal/intern/object.h +stringio.o: $(hdrdir)/ruby/internal/intern/parse.h +stringio.o: $(hdrdir)/ruby/internal/intern/proc.h +stringio.o: $(hdrdir)/ruby/internal/intern/process.h +stringio.o: $(hdrdir)/ruby/internal/intern/random.h +stringio.o: $(hdrdir)/ruby/internal/intern/range.h +stringio.o: $(hdrdir)/ruby/internal/intern/rational.h +stringio.o: $(hdrdir)/ruby/internal/intern/re.h +stringio.o: $(hdrdir)/ruby/internal/intern/ruby.h +stringio.o: $(hdrdir)/ruby/internal/intern/select.h +stringio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +stringio.o: $(hdrdir)/ruby/internal/intern/signal.h +stringio.o: $(hdrdir)/ruby/internal/intern/sprintf.h +stringio.o: $(hdrdir)/ruby/internal/intern/string.h +stringio.o: $(hdrdir)/ruby/internal/intern/struct.h +stringio.o: $(hdrdir)/ruby/internal/intern/thread.h +stringio.o: $(hdrdir)/ruby/internal/intern/time.h +stringio.o: $(hdrdir)/ruby/internal/intern/variable.h +stringio.o: $(hdrdir)/ruby/internal/intern/vm.h +stringio.o: $(hdrdir)/ruby/internal/interpreter.h +stringio.o: $(hdrdir)/ruby/internal/iterator.h +stringio.o: $(hdrdir)/ruby/internal/memory.h +stringio.o: $(hdrdir)/ruby/internal/method.h +stringio.o: $(hdrdir)/ruby/internal/module.h +stringio.o: $(hdrdir)/ruby/internal/newobj.h +stringio.o: $(hdrdir)/ruby/internal/rgengc.h +stringio.o: $(hdrdir)/ruby/internal/scan_args.h +stringio.o: $(hdrdir)/ruby/internal/special_consts.h +stringio.o: $(hdrdir)/ruby/internal/static_assert.h +stringio.o: $(hdrdir)/ruby/internal/stdalign.h +stringio.o: $(hdrdir)/ruby/internal/stdbool.h +stringio.o: $(hdrdir)/ruby/internal/symbol.h +stringio.o: $(hdrdir)/ruby/internal/value.h +stringio.o: $(hdrdir)/ruby/internal/value_type.h +stringio.o: $(hdrdir)/ruby/internal/variable.h +stringio.o: $(hdrdir)/ruby/internal/warning_push.h +stringio.o: $(hdrdir)/ruby/internal/xmalloc.h stringio.o: $(hdrdir)/ruby/io.h stringio.o: $(hdrdir)/ruby/missing.h stringio.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/stringio/stringio.c b/ruby/ext/stringio/stringio.c index b31e801b2..8df07e80f 100644 --- a/ruby/ext/stringio/stringio.c +++ b/ruby/ext/stringio/stringio.c @@ -1,3 +1,4 @@ +/* -*- mode: c; indent-tabs-mode: t -*- */ /********************************************************************** stringio.c - @@ -11,7 +12,7 @@ **********************************************************************/ -#define STRINGIO_VERSION "0.1.0" +#define STRINGIO_VERSION "3.0.1" #include "ruby.h" #include "ruby/io.h" @@ -64,7 +65,7 @@ strio_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, n = strchr(n, '|'); } e = strchr(++n, ':'); - len = e ? e - n : strlen(n); + len = e ? e - n : (long)strlen(n); if (len > 0 && len <= ENCODING_MAXNAMELEN) { if (e) { memcpy(encname, n, len); @@ -599,6 +600,14 @@ strio_closed_write(VALUE self) return Qtrue; } +static struct StringIO * +strio_to_read(VALUE self) +{ + struct StringIO *ptr = readable(self); + if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr; + return NULL; +} + /* * call-seq: * strio.eof -> true or false @@ -610,8 +619,7 @@ strio_closed_write(VALUE self) static VALUE strio_eof(VALUE self) { - struct StringIO *ptr = readable(self); - if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse; + if (strio_to_read(self)) return Qfalse; return Qtrue; } @@ -821,29 +829,17 @@ strio_get_sync(VALUE self) static VALUE strio_each_byte(VALUE self) { - struct StringIO *ptr = readable(self); + struct StringIO *ptr; RETURN_ENUMERATOR(self, 0, 0); - while (ptr->pos < RSTRING_LEN(ptr->string)) { + while ((ptr = strio_to_read(self)) != NULL) { char c = RSTRING_PTR(ptr->string)[ptr->pos++]; rb_yield(CHR2FIX(c)); } return self; } -/* - * This is a deprecated alias for #each_byte. - */ -static VALUE -strio_bytes(VALUE self) -{ - rb_warn("StringIO#bytes is deprecated; use #each_byte instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0); - return strio_each_byte(self); -} - /* * call-seq: * strio.getc -> string or nil @@ -1057,18 +1053,6 @@ strio_each_char(VALUE self) return self; } -/* - * This is a deprecated alias for #each_char. - */ -static VALUE -strio_chars(VALUE self) -{ - rb_warn("StringIO#chars is deprecated; use #each_char instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0); - return strio_each_char(self); -} - /* * call-seq: * strio.each_codepoint {|c| block } -> strio @@ -1088,31 +1072,15 @@ strio_each_codepoint(VALUE self) ptr = readable(self); enc = get_enc(ptr); - for (;;) { - if (ptr->pos >= RSTRING_LEN(ptr->string)) { - return self; - } - + while ((ptr = strio_to_read(self)) != NULL) { c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_END(ptr->string), &n, enc); - rb_yield(UINT2NUM(c)); ptr->pos += n; + rb_yield(UINT2NUM(c)); } return self; } -/* - * This is a deprecated alias for #each_codepoint. - */ -static VALUE -strio_codepoints(VALUE self) -{ - rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0); - return strio_each_codepoint(self); -} - /* Boyer-Moore search: copied from regex.c */ static void bm_init_skip(long *skip, const char *pat, long m) @@ -1363,18 +1331,6 @@ strio_each(int argc, VALUE *argv, VALUE self) return self; } -/* - * This is a deprecated alias for #each_line. - */ -static VALUE -strio_lines(int argc, VALUE *argv, VALUE self) -{ - rb_warn("StringIO#lines is deprecated; use #each_line instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv); - return strio_each(argc, argv, self); -} - /* * call-seq: * strio.readlines(sep=$/, chomp: false) -> array @@ -1429,13 +1385,18 @@ strio_write(VALUE self, VALUE str) long len, olen; rb_encoding *enc, *enc2; rb_encoding *const ascii8bit = rb_ascii8bit_encoding(); + rb_encoding *usascii = 0; if (!RB_TYPE_P(str, T_STRING)) str = rb_obj_as_string(str); enc = get_enc(ptr); enc2 = rb_enc_get(str); - if (enc != enc2 && enc != ascii8bit) { - str = rb_str_conv_enc(str, enc2, enc); + if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) { + VALUE converted = rb_str_conv_enc(str, enc2, enc); + if (converted == str && enc2 != ascii8bit && enc2 != usascii) { /* conversion failed */ + rb_enc_check(rb_enc_from_encoding(enc), str); + } + str = converted; } len = RSTRING_LEN(str); if (len == 0) return 0; @@ -1532,7 +1493,6 @@ strio_read(int argc, VALUE *argv, VALUE self) long len; int binary = 0; - rb_check_arity(argc, 0, 2); switch (argc) { case 2: str = argv[1]; @@ -1572,6 +1532,8 @@ strio_read(int argc, VALUE *argv, VALUE self) len -= ptr->pos; } break; + default: + rb_error_arity(argc, 0, 2); } if (NIL_P(str)) { rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr); @@ -1792,7 +1754,12 @@ void Init_stringio(void) { #undef rb_intern - VALUE StringIO = rb_define_class("StringIO", rb_cData); + +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + + VALUE StringIO = rb_define_class("StringIO", rb_cObject); rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION)); @@ -1837,13 +1804,9 @@ Init_stringio(void) rb_define_method(StringIO, "each", strio_each, -1); rb_define_method(StringIO, "each_line", strio_each, -1); - rb_define_method(StringIO, "lines", strio_lines, -1); rb_define_method(StringIO, "each_byte", strio_each_byte, 0); - rb_define_method(StringIO, "bytes", strio_bytes, 0); rb_define_method(StringIO, "each_char", strio_each_char, 0); - rb_define_method(StringIO, "chars", strio_chars, 0); rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0); - rb_define_method(StringIO, "codepoints", strio_codepoints, 0); rb_define_method(StringIO, "getc", strio_getc, 0); rb_define_method(StringIO, "ungetc", strio_ungetc, 1); rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1); diff --git a/ruby/ext/stringio/stringio.gemspec b/ruby/ext/stringio/stringio.gemspec index a16c75753..524d976cf 100644 --- a/ruby/ext/stringio/stringio.gemspec +++ b/ruby/ext/stringio/stringio.gemspec @@ -22,13 +22,10 @@ Gem::Specification.new do |s| s.extensions = ["ext/stringio/extconf.rb"] s.files = ["README.md", "ext/stringio/extconf.rb", "ext/stringio/stringio.c"] s.homepage = "https://github.com/ruby/stringio" - s.licenses = ["BSD-2-Clause"] + s.licenses = ["Ruby", "BSD-2-Clause"] s.required_ruby_version = ">= 2.5" - s.rubygems_version = "2.6.11" s.summary = "Pseudo IO on String" # s.cert_chain = %w[certs/nobu.pem] # s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/ - - s.add_development_dependency 'rake-compiler' end diff --git a/ruby/ext/strscan/depend b/ruby/ext/strscan/depend index 212d386f8..7024f8bfa 100644 --- a/ruby/ext/strscan/depend +++ b/ruby/ext/strscan/depend @@ -3,9 +3,166 @@ strscan.o: $(RUBY_EXTCONF_H) strscan.o: $(arch_hdrdir)/ruby/config.h strscan.o: $(hdrdir)/ruby/assert.h strscan.o: $(hdrdir)/ruby/backward.h +strscan.o: $(hdrdir)/ruby/backward/2/assume.h +strscan.o: $(hdrdir)/ruby/backward/2/attributes.h +strscan.o: $(hdrdir)/ruby/backward/2/bool.h +strscan.o: $(hdrdir)/ruby/backward/2/inttypes.h +strscan.o: $(hdrdir)/ruby/backward/2/limits.h +strscan.o: $(hdrdir)/ruby/backward/2/long_long.h +strscan.o: $(hdrdir)/ruby/backward/2/stdalign.h +strscan.o: $(hdrdir)/ruby/backward/2/stdarg.h strscan.o: $(hdrdir)/ruby/defines.h strscan.o: $(hdrdir)/ruby/encoding.h strscan.o: $(hdrdir)/ruby/intern.h +strscan.o: $(hdrdir)/ruby/internal/anyargs.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/char.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/double.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/int.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/long.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/short.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +strscan.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +strscan.o: $(hdrdir)/ruby/internal/assume.h +strscan.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +strscan.o: $(hdrdir)/ruby/internal/attr/artificial.h +strscan.o: $(hdrdir)/ruby/internal/attr/cold.h +strscan.o: $(hdrdir)/ruby/internal/attr/const.h +strscan.o: $(hdrdir)/ruby/internal/attr/constexpr.h +strscan.o: $(hdrdir)/ruby/internal/attr/deprecated.h +strscan.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +strscan.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +strscan.o: $(hdrdir)/ruby/internal/attr/error.h +strscan.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +strscan.o: $(hdrdir)/ruby/internal/attr/forceinline.h +strscan.o: $(hdrdir)/ruby/internal/attr/format.h +strscan.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +strscan.o: $(hdrdir)/ruby/internal/attr/noalias.h +strscan.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +strscan.o: $(hdrdir)/ruby/internal/attr/noexcept.h +strscan.o: $(hdrdir)/ruby/internal/attr/noinline.h +strscan.o: $(hdrdir)/ruby/internal/attr/nonnull.h +strscan.o: $(hdrdir)/ruby/internal/attr/noreturn.h +strscan.o: $(hdrdir)/ruby/internal/attr/pure.h +strscan.o: $(hdrdir)/ruby/internal/attr/restrict.h +strscan.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +strscan.o: $(hdrdir)/ruby/internal/attr/warning.h +strscan.o: $(hdrdir)/ruby/internal/attr/weakref.h +strscan.o: $(hdrdir)/ruby/internal/cast.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +strscan.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +strscan.o: $(hdrdir)/ruby/internal/compiler_since.h +strscan.o: $(hdrdir)/ruby/internal/config.h +strscan.o: $(hdrdir)/ruby/internal/constant_p.h +strscan.o: $(hdrdir)/ruby/internal/core.h +strscan.o: $(hdrdir)/ruby/internal/core/rarray.h +strscan.o: $(hdrdir)/ruby/internal/core/rbasic.h +strscan.o: $(hdrdir)/ruby/internal/core/rbignum.h +strscan.o: $(hdrdir)/ruby/internal/core/rclass.h +strscan.o: $(hdrdir)/ruby/internal/core/rdata.h +strscan.o: $(hdrdir)/ruby/internal/core/rfile.h +strscan.o: $(hdrdir)/ruby/internal/core/rhash.h +strscan.o: $(hdrdir)/ruby/internal/core/rmatch.h +strscan.o: $(hdrdir)/ruby/internal/core/robject.h +strscan.o: $(hdrdir)/ruby/internal/core/rregexp.h +strscan.o: $(hdrdir)/ruby/internal/core/rstring.h +strscan.o: $(hdrdir)/ruby/internal/core/rstruct.h +strscan.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +strscan.o: $(hdrdir)/ruby/internal/ctype.h +strscan.o: $(hdrdir)/ruby/internal/dllexport.h +strscan.o: $(hdrdir)/ruby/internal/dosish.h +strscan.o: $(hdrdir)/ruby/internal/encoding/coderange.h +strscan.o: $(hdrdir)/ruby/internal/encoding/ctype.h +strscan.o: $(hdrdir)/ruby/internal/encoding/encoding.h +strscan.o: $(hdrdir)/ruby/internal/encoding/pathname.h +strscan.o: $(hdrdir)/ruby/internal/encoding/re.h +strscan.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +strscan.o: $(hdrdir)/ruby/internal/encoding/string.h +strscan.o: $(hdrdir)/ruby/internal/encoding/symbol.h +strscan.o: $(hdrdir)/ruby/internal/encoding/transcode.h +strscan.o: $(hdrdir)/ruby/internal/error.h +strscan.o: $(hdrdir)/ruby/internal/eval.h +strscan.o: $(hdrdir)/ruby/internal/event.h +strscan.o: $(hdrdir)/ruby/internal/fl_type.h +strscan.o: $(hdrdir)/ruby/internal/gc.h +strscan.o: $(hdrdir)/ruby/internal/glob.h +strscan.o: $(hdrdir)/ruby/internal/globals.h +strscan.o: $(hdrdir)/ruby/internal/has/attribute.h +strscan.o: $(hdrdir)/ruby/internal/has/builtin.h +strscan.o: $(hdrdir)/ruby/internal/has/c_attribute.h +strscan.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +strscan.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +strscan.o: $(hdrdir)/ruby/internal/has/extension.h +strscan.o: $(hdrdir)/ruby/internal/has/feature.h +strscan.o: $(hdrdir)/ruby/internal/has/warning.h +strscan.o: $(hdrdir)/ruby/internal/intern/array.h +strscan.o: $(hdrdir)/ruby/internal/intern/bignum.h +strscan.o: $(hdrdir)/ruby/internal/intern/class.h +strscan.o: $(hdrdir)/ruby/internal/intern/compar.h +strscan.o: $(hdrdir)/ruby/internal/intern/complex.h +strscan.o: $(hdrdir)/ruby/internal/intern/cont.h +strscan.o: $(hdrdir)/ruby/internal/intern/dir.h +strscan.o: $(hdrdir)/ruby/internal/intern/enum.h +strscan.o: $(hdrdir)/ruby/internal/intern/enumerator.h +strscan.o: $(hdrdir)/ruby/internal/intern/error.h +strscan.o: $(hdrdir)/ruby/internal/intern/eval.h +strscan.o: $(hdrdir)/ruby/internal/intern/file.h +strscan.o: $(hdrdir)/ruby/internal/intern/gc.h +strscan.o: $(hdrdir)/ruby/internal/intern/hash.h +strscan.o: $(hdrdir)/ruby/internal/intern/io.h +strscan.o: $(hdrdir)/ruby/internal/intern/load.h +strscan.o: $(hdrdir)/ruby/internal/intern/marshal.h +strscan.o: $(hdrdir)/ruby/internal/intern/numeric.h +strscan.o: $(hdrdir)/ruby/internal/intern/object.h +strscan.o: $(hdrdir)/ruby/internal/intern/parse.h +strscan.o: $(hdrdir)/ruby/internal/intern/proc.h +strscan.o: $(hdrdir)/ruby/internal/intern/process.h +strscan.o: $(hdrdir)/ruby/internal/intern/random.h +strscan.o: $(hdrdir)/ruby/internal/intern/range.h +strscan.o: $(hdrdir)/ruby/internal/intern/rational.h +strscan.o: $(hdrdir)/ruby/internal/intern/re.h +strscan.o: $(hdrdir)/ruby/internal/intern/ruby.h +strscan.o: $(hdrdir)/ruby/internal/intern/select.h +strscan.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +strscan.o: $(hdrdir)/ruby/internal/intern/signal.h +strscan.o: $(hdrdir)/ruby/internal/intern/sprintf.h +strscan.o: $(hdrdir)/ruby/internal/intern/string.h +strscan.o: $(hdrdir)/ruby/internal/intern/struct.h +strscan.o: $(hdrdir)/ruby/internal/intern/thread.h +strscan.o: $(hdrdir)/ruby/internal/intern/time.h +strscan.o: $(hdrdir)/ruby/internal/intern/variable.h +strscan.o: $(hdrdir)/ruby/internal/intern/vm.h +strscan.o: $(hdrdir)/ruby/internal/interpreter.h +strscan.o: $(hdrdir)/ruby/internal/iterator.h +strscan.o: $(hdrdir)/ruby/internal/memory.h +strscan.o: $(hdrdir)/ruby/internal/method.h +strscan.o: $(hdrdir)/ruby/internal/module.h +strscan.o: $(hdrdir)/ruby/internal/newobj.h +strscan.o: $(hdrdir)/ruby/internal/rgengc.h +strscan.o: $(hdrdir)/ruby/internal/scan_args.h +strscan.o: $(hdrdir)/ruby/internal/special_consts.h +strscan.o: $(hdrdir)/ruby/internal/static_assert.h +strscan.o: $(hdrdir)/ruby/internal/stdalign.h +strscan.o: $(hdrdir)/ruby/internal/stdbool.h +strscan.o: $(hdrdir)/ruby/internal/symbol.h +strscan.o: $(hdrdir)/ruby/internal/value.h +strscan.o: $(hdrdir)/ruby/internal/value_type.h +strscan.o: $(hdrdir)/ruby/internal/variable.h +strscan.o: $(hdrdir)/ruby/internal/warning_push.h +strscan.o: $(hdrdir)/ruby/internal/xmalloc.h strscan.o: $(hdrdir)/ruby/missing.h strscan.o: $(hdrdir)/ruby/onigmo.h strscan.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ruby/ext/strscan/strscan.c b/ruby/ext/strscan/strscan.c index b6d17992c..e1426380b 100644 --- a/ruby/ext/strscan/strscan.c +++ b/ruby/ext/strscan/strscan.c @@ -4,8 +4,8 @@ Copyright (c) 1999-2006 Minero Aoki This program is free software. - You can distribute/modify this program under the terms of - the Ruby License. For details, see the file COPYING. + You can redistribute this program under the terms of the Ruby's or 2-clause + BSD License. For details, see the COPYING and LICENSE.txt files. */ #include "ruby/ruby.h" @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs); #include -#define STRSCAN_VERSION "1.0.3" +#define STRSCAN_VERSION "3.0.1" /* ======================================================================= Data Type Definitions @@ -176,6 +176,7 @@ strscan_mark(void *ptr) { struct strscanner *p = ptr; rb_gc_mark(p->str); + rb_gc_mark(p->regex); } static void @@ -212,6 +213,7 @@ strscan_s_allocate(VALUE klass) CLEAR_MATCH_STATUS(p); onig_region_init(&(p->regs)); p->str = Qnil; + p->regex = Qnil; return obj; } @@ -443,13 +445,10 @@ static VALUE strscan_get_charpos(VALUE self) { struct strscanner *p; - VALUE substr; GET_SCANNER(self, p); - substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), INT2NUM(p->curr)); - - return rb_str_length(substr); + return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str))); } /* @@ -473,7 +472,7 @@ strscan_set_pos(VALUE self, VALUE v) if (i < 0) rb_raise(rb_eRangeError, "index out of range"); if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range"); p->curr = i; - return INT2NUM(i); + return LONG2NUM(i); } static inline UChar * @@ -848,9 +847,8 @@ adjust_registers_to_matched(struct strscanner *p) * s.getch # => "b" * s.getch # => nil * - * $KCODE = 'EUC' - * s = StringScanner.new("\244\242") - * s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP + * s = StringScanner.new("\244\242".force_encoding("euc-jp")) + * s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP * s.getch # => nil */ static VALUE @@ -885,10 +883,9 @@ strscan_getch(VALUE self) * s.get_byte # => "b" * s.get_byte # => nil * - * $KCODE = 'EUC' - * s = StringScanner.new("\244\242") - * s.get_byte # => "\244" - * s.get_byte # => "\242" + * s = StringScanner.new("\244\242".force_encoding("euc-jp")) + * s.get_byte # => "\xA4" + * s.get_byte # => "\xA2" * s.get_byte # => nil */ static VALUE @@ -984,7 +981,7 @@ strscan_unscan(VALUE self) } /* - * Returns +true+ iff the scan pointer is at the beginning of the line. + * Returns +true+ if and only if the scan pointer is at the beginning of the line. * * s = StringScanner.new("test\ntest\n") * s.bol? # => true @@ -1037,7 +1034,7 @@ strscan_empty_p(VALUE self) } /* - * Returns true iff there is more data in the string. See #eos?. + * Returns true if and only if there is more data in the string. See #eos?. * This method is obsolete; use #eos? instead. * * s = StringScanner.new('test string') @@ -1054,7 +1051,7 @@ strscan_rest_p(VALUE self) } /* - * Returns +true+ iff the last match was successful. + * Returns +true+ if and only if the last match was successful. * * s = StringScanner.new('test string') * s.match?(/\w+/) # => 4 @@ -1091,8 +1088,9 @@ strscan_matched(VALUE self) } /* - * Returns the size of the most recent match (see #matched), or +nil+ if there - * was no recent match. + * Returns the size of the most recent match in bytes, or +nil+ if there + * was no recent match. This is different than matched.size, + * which will return the size in characters. * * s = StringScanner.new('test string') * s.check /\w+/ # -> "test" @@ -1107,7 +1105,7 @@ strscan_matched_size(VALUE self) GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; - return INT2NUM(p->regs.end[0] - p->regs.beg[0]); + return LONG2NUM(p->regs.end[0] - p->regs.beg[0]); } static int @@ -1169,7 +1167,7 @@ strscan_aref(VALUE self, VALUE idx) idx = rb_sym2str(idx); /* fall through */ case T_STRING: - if (!p->regex) return Qnil; + if (!RTEST(p->regex)) return Qnil; RSTRING_GETMEM(idx, name, i); i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx)); break; @@ -1536,7 +1534,7 @@ strscan_fixed_anchor_p(VALUE self) * * === Finding Where we Are * - * - #beginning_of_line? (#bol?) + * - #beginning_of_line? (#bol?) * - #eos? * - #rest? * - #rest_size @@ -1553,13 +1551,13 @@ strscan_fixed_anchor_p(VALUE self) * - #matched * - #matched? * - #matched_size - * - [] + * - #[] * - #pre_match * - #post_match * * === Miscellaneous * - * - << + * - << * - #concat * - #string * - #string= @@ -1570,6 +1568,10 @@ strscan_fixed_anchor_p(VALUE self) void Init_strscan(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + #undef rb_intern ID id_scanerr = rb_intern("ScanError"); VALUE tmp; diff --git a/ruby/ext/strscan/strscan.gemspec b/ruby/ext/strscan/strscan.gemspec index 4759c6c86..5d8119ea4 100644 --- a/ruby/ext/strscan/strscan.gemspec +++ b/ruby/ext/strscan/strscan.gemspec @@ -1,7 +1,18 @@ # frozen_string_literal: true +# +source_version = ["", "ext/strscan/"].find do |dir| + begin + break File.open(File.join(__dir__, "#{dir}strscan.c")) {|f| + f.gets("\n#define STRSCAN_VERSION ") + f.gets[/\s*"(.+)"/, 1] + } + rescue Errno::ENOENT + end +end + Gem::Specification.new do |s| s.name = "strscan" - s.version = '1.0.3' + s.version = source_version s.summary = "Provides lexical scanning operations on a String." s.description = "Provides lexical scanning operations on a String." @@ -13,8 +24,5 @@ Gem::Specification.new do |s| s.authors = ["Minero Aoki", "Sutou Kouhei"] s.email = [nil, "kou@cozmixng.org"] s.homepage = "https://github.com/ruby/strscan" - s.license = "BSD-2-Clause" - - s.add_development_dependency "rake-compiler" - s.add_development_dependency "benchmark-driver" + s.licenses = ["Ruby", "BSD-2-Clause"] end diff --git a/ruby/ext/syslog/depend b/ruby/ext/syslog/depend index a3f7db837..0752bed04 100644 --- a/ruby/ext/syslog/depend +++ b/ruby/ext/syslog/depend @@ -3,8 +3,155 @@ syslog.o: $(RUBY_EXTCONF_H) syslog.o: $(arch_hdrdir)/ruby/config.h syslog.o: $(hdrdir)/ruby/assert.h syslog.o: $(hdrdir)/ruby/backward.h +syslog.o: $(hdrdir)/ruby/backward/2/assume.h +syslog.o: $(hdrdir)/ruby/backward/2/attributes.h +syslog.o: $(hdrdir)/ruby/backward/2/bool.h +syslog.o: $(hdrdir)/ruby/backward/2/inttypes.h +syslog.o: $(hdrdir)/ruby/backward/2/limits.h +syslog.o: $(hdrdir)/ruby/backward/2/long_long.h +syslog.o: $(hdrdir)/ruby/backward/2/stdalign.h +syslog.o: $(hdrdir)/ruby/backward/2/stdarg.h syslog.o: $(hdrdir)/ruby/defines.h syslog.o: $(hdrdir)/ruby/intern.h +syslog.o: $(hdrdir)/ruby/internal/anyargs.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/char.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/double.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/int.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/long.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/short.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +syslog.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +syslog.o: $(hdrdir)/ruby/internal/assume.h +syslog.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +syslog.o: $(hdrdir)/ruby/internal/attr/artificial.h +syslog.o: $(hdrdir)/ruby/internal/attr/cold.h +syslog.o: $(hdrdir)/ruby/internal/attr/const.h +syslog.o: $(hdrdir)/ruby/internal/attr/constexpr.h +syslog.o: $(hdrdir)/ruby/internal/attr/deprecated.h +syslog.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +syslog.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +syslog.o: $(hdrdir)/ruby/internal/attr/error.h +syslog.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +syslog.o: $(hdrdir)/ruby/internal/attr/forceinline.h +syslog.o: $(hdrdir)/ruby/internal/attr/format.h +syslog.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +syslog.o: $(hdrdir)/ruby/internal/attr/noalias.h +syslog.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +syslog.o: $(hdrdir)/ruby/internal/attr/noexcept.h +syslog.o: $(hdrdir)/ruby/internal/attr/noinline.h +syslog.o: $(hdrdir)/ruby/internal/attr/nonnull.h +syslog.o: $(hdrdir)/ruby/internal/attr/noreturn.h +syslog.o: $(hdrdir)/ruby/internal/attr/pure.h +syslog.o: $(hdrdir)/ruby/internal/attr/restrict.h +syslog.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +syslog.o: $(hdrdir)/ruby/internal/attr/warning.h +syslog.o: $(hdrdir)/ruby/internal/attr/weakref.h +syslog.o: $(hdrdir)/ruby/internal/cast.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +syslog.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +syslog.o: $(hdrdir)/ruby/internal/compiler_since.h +syslog.o: $(hdrdir)/ruby/internal/config.h +syslog.o: $(hdrdir)/ruby/internal/constant_p.h +syslog.o: $(hdrdir)/ruby/internal/core.h +syslog.o: $(hdrdir)/ruby/internal/core/rarray.h +syslog.o: $(hdrdir)/ruby/internal/core/rbasic.h +syslog.o: $(hdrdir)/ruby/internal/core/rbignum.h +syslog.o: $(hdrdir)/ruby/internal/core/rclass.h +syslog.o: $(hdrdir)/ruby/internal/core/rdata.h +syslog.o: $(hdrdir)/ruby/internal/core/rfile.h +syslog.o: $(hdrdir)/ruby/internal/core/rhash.h +syslog.o: $(hdrdir)/ruby/internal/core/robject.h +syslog.o: $(hdrdir)/ruby/internal/core/rregexp.h +syslog.o: $(hdrdir)/ruby/internal/core/rstring.h +syslog.o: $(hdrdir)/ruby/internal/core/rstruct.h +syslog.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +syslog.o: $(hdrdir)/ruby/internal/ctype.h +syslog.o: $(hdrdir)/ruby/internal/dllexport.h +syslog.o: $(hdrdir)/ruby/internal/dosish.h +syslog.o: $(hdrdir)/ruby/internal/error.h +syslog.o: $(hdrdir)/ruby/internal/eval.h +syslog.o: $(hdrdir)/ruby/internal/event.h +syslog.o: $(hdrdir)/ruby/internal/fl_type.h +syslog.o: $(hdrdir)/ruby/internal/gc.h +syslog.o: $(hdrdir)/ruby/internal/glob.h +syslog.o: $(hdrdir)/ruby/internal/globals.h +syslog.o: $(hdrdir)/ruby/internal/has/attribute.h +syslog.o: $(hdrdir)/ruby/internal/has/builtin.h +syslog.o: $(hdrdir)/ruby/internal/has/c_attribute.h +syslog.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +syslog.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +syslog.o: $(hdrdir)/ruby/internal/has/extension.h +syslog.o: $(hdrdir)/ruby/internal/has/feature.h +syslog.o: $(hdrdir)/ruby/internal/has/warning.h +syslog.o: $(hdrdir)/ruby/internal/intern/array.h +syslog.o: $(hdrdir)/ruby/internal/intern/bignum.h +syslog.o: $(hdrdir)/ruby/internal/intern/class.h +syslog.o: $(hdrdir)/ruby/internal/intern/compar.h +syslog.o: $(hdrdir)/ruby/internal/intern/complex.h +syslog.o: $(hdrdir)/ruby/internal/intern/cont.h +syslog.o: $(hdrdir)/ruby/internal/intern/dir.h +syslog.o: $(hdrdir)/ruby/internal/intern/enum.h +syslog.o: $(hdrdir)/ruby/internal/intern/enumerator.h +syslog.o: $(hdrdir)/ruby/internal/intern/error.h +syslog.o: $(hdrdir)/ruby/internal/intern/eval.h +syslog.o: $(hdrdir)/ruby/internal/intern/file.h +syslog.o: $(hdrdir)/ruby/internal/intern/gc.h +syslog.o: $(hdrdir)/ruby/internal/intern/hash.h +syslog.o: $(hdrdir)/ruby/internal/intern/io.h +syslog.o: $(hdrdir)/ruby/internal/intern/load.h +syslog.o: $(hdrdir)/ruby/internal/intern/marshal.h +syslog.o: $(hdrdir)/ruby/internal/intern/numeric.h +syslog.o: $(hdrdir)/ruby/internal/intern/object.h +syslog.o: $(hdrdir)/ruby/internal/intern/parse.h +syslog.o: $(hdrdir)/ruby/internal/intern/proc.h +syslog.o: $(hdrdir)/ruby/internal/intern/process.h +syslog.o: $(hdrdir)/ruby/internal/intern/random.h +syslog.o: $(hdrdir)/ruby/internal/intern/range.h +syslog.o: $(hdrdir)/ruby/internal/intern/rational.h +syslog.o: $(hdrdir)/ruby/internal/intern/re.h +syslog.o: $(hdrdir)/ruby/internal/intern/ruby.h +syslog.o: $(hdrdir)/ruby/internal/intern/select.h +syslog.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +syslog.o: $(hdrdir)/ruby/internal/intern/signal.h +syslog.o: $(hdrdir)/ruby/internal/intern/sprintf.h +syslog.o: $(hdrdir)/ruby/internal/intern/string.h +syslog.o: $(hdrdir)/ruby/internal/intern/struct.h +syslog.o: $(hdrdir)/ruby/internal/intern/thread.h +syslog.o: $(hdrdir)/ruby/internal/intern/time.h +syslog.o: $(hdrdir)/ruby/internal/intern/variable.h +syslog.o: $(hdrdir)/ruby/internal/intern/vm.h +syslog.o: $(hdrdir)/ruby/internal/interpreter.h +syslog.o: $(hdrdir)/ruby/internal/iterator.h +syslog.o: $(hdrdir)/ruby/internal/memory.h +syslog.o: $(hdrdir)/ruby/internal/method.h +syslog.o: $(hdrdir)/ruby/internal/module.h +syslog.o: $(hdrdir)/ruby/internal/newobj.h +syslog.o: $(hdrdir)/ruby/internal/rgengc.h +syslog.o: $(hdrdir)/ruby/internal/scan_args.h +syslog.o: $(hdrdir)/ruby/internal/special_consts.h +syslog.o: $(hdrdir)/ruby/internal/static_assert.h +syslog.o: $(hdrdir)/ruby/internal/stdalign.h +syslog.o: $(hdrdir)/ruby/internal/stdbool.h +syslog.o: $(hdrdir)/ruby/internal/symbol.h +syslog.o: $(hdrdir)/ruby/internal/value.h +syslog.o: $(hdrdir)/ruby/internal/value_type.h +syslog.o: $(hdrdir)/ruby/internal/variable.h +syslog.o: $(hdrdir)/ruby/internal/warning_push.h +syslog.o: $(hdrdir)/ruby/internal/xmalloc.h syslog.o: $(hdrdir)/ruby/missing.h syslog.o: $(hdrdir)/ruby/ruby.h syslog.o: $(hdrdir)/ruby/st.h diff --git a/ruby/ext/syslog/syslog.gemspec b/ruby/ext/syslog/syslog.gemspec new file mode 100644 index 000000000..8f73f5ad0 --- /dev/null +++ b/ruby/ext/syslog/syslog.gemspec @@ -0,0 +1,23 @@ +Gem::Specification.new do |spec| + spec.name = "syslog" + spec.version = "0.1.0" + spec.authors = ["Akinori MUSHA"] + spec.email = ["knu@idaemons.org"] + + spec.summary = %q{Ruby interface for the POSIX system logging facility.} + spec.description = %q{Ruby interface for the POSIX system logging facility.} + spec.homepage = "https://github.com/ruby/syslog" + 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 + + 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.extensions = ["ext/syslog/extconf.rb"] + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] +end diff --git a/ruby/ext/win32/lib/Win32API.rb b/ruby/ext/win32/lib/Win32API.rb deleted file mode 100644 index 97b29fbf7..000000000 --- a/ruby/ext/win32/lib/Win32API.rb +++ /dev/null @@ -1,47 +0,0 @@ -# -*- ruby -*- -# frozen_string_literal: true - -# for backward compatibility -warn "Win32API is deprecated after Ruby 1.9.1; use fiddle directly instead", uplevel: 2 - -require 'fiddle/import' - -class Win32API - DLL = {} - TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG} - POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*' - - WIN32_TYPES = "VPpNnLlIi" - DL_TYPES = "0SSI" - - def initialize(dllname, func, import, export = "0", calltype = :stdcall) - @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1') - import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]} - export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)] - calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype] - - handle = DLL[dllname] ||= - begin - Fiddle.dlopen(dllname) - rescue Fiddle::DLError - raise unless File.extname(dllname).empty? - Fiddle.dlopen(dllname + ".dll") - end - - @func = Fiddle::Function.new(handle[func], import, export, calltype) - rescue Fiddle::DLError => e - raise LoadError, e.message, e.backtrace - end - - def call(*args) - import = @proto.split("") - args.each_with_index do |x, i| - args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S" - args[i], = [x].pack("I").unpack("i") if import[i] == "I" - end - ret, = @func.call(*args) - return ret || 0 - end - - alias Call call -end diff --git a/ruby/ext/win32/lib/win32/importer.rb b/ruby/ext/win32/lib/win32/importer.rb deleted file mode 100644 index 2bef016c2..000000000 --- a/ruby/ext/win32/lib/win32/importer.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false -require 'fiddle/import' - -module Win32 -end - -Win32.module_eval do - Importer = Fiddle::Importer -end diff --git a/ruby/ext/win32/lib/win32/registry.rb b/ruby/ext/win32/lib/win32/registry.rb index 451499b16..b5b99ff68 100644 --- a/ruby/ext/win32/lib/win32/registry.rb +++ b/ruby/ext/win32/lib/win32/registry.rb @@ -1,5 +1,5 @@ # frozen_string_literal: false -require 'win32/importer' +require 'fiddle/import' module Win32 @@ -169,7 +169,7 @@ module Constants # class Error < ::StandardError module Kernel32 - extend Importer + extend Fiddle::Importer dlload "kernel32.dll" end FormatMessageW = Kernel32.extern "int FormatMessageW(int, void *, int, int, void *, int, void *)", :stdcall @@ -225,7 +225,7 @@ def class # module API include Constants - extend Importer + extend Fiddle::Importer dlload "advapi32.dll" [ "long RegOpenKeyExW(void *, void *, long, long, void *)", @@ -667,14 +667,14 @@ def read(name, *rtype) # # Read a registry value named name and return its value data. - # The class of value is same as #read method returns. + # The class of the value is the same as the #read method returns. # # If the value type is REG_EXPAND_SZ, returns value data whose environment # variables are replaced. # If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD, # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised. # - # The meaning of rtype is same as #read method. + # The meaning of rtype is the same as for the #read method. # def [](name, *rtype) type, data = read(name, *rtype) diff --git a/ruby/ext/win32/lib/win32/resolv.rb b/ruby/ext/win32/lib/win32/resolv.rb index 1eb70d5dc..d06658f0a 100644 --- a/ruby/ext/win32/lib/win32/resolv.rb +++ b/ruby/ext/win32/lib/win32/resolv.rb @@ -42,19 +42,6 @@ def self.get_resolv_info rescue LoadError end -if [nil].pack("p").size <= 4 # 32bit env - begin - f = Fiddle - osid = f::Handle.new["rb_w32_osid"] - rescue f::DLError # not ix86, cannot be Windows 9x - else - if f::Function.new(osid, [], f::TYPE_INT).call < 2 # VER_PLATFORM_WIN32_NT - require_relative 'resolv9x' - return - end - end -end - module Win32 #==================================================================== # Windows NT diff --git a/ruby/ext/win32/lib/win32/resolv9x.rb b/ruby/ext/win32/lib/win32/resolv9x.rb deleted file mode 100644 index a409d59c0..000000000 --- a/ruby/ext/win32/lib/win32/resolv9x.rb +++ /dev/null @@ -1,253 +0,0 @@ -#==================================================================== -# Windows 9x -#==================================================================== -module Win32 - module Resolv - TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP' - DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP' - WINDOWS = 'Software\Microsoft\Windows\CurrentVersion' - - class << self - # private - - def get_hosts_dir - Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg| - reg.read_s_expand('SystemRoot') - end - end - - def get_info - search = [] - nameserver = [] - begin - Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg| - if reg.read_s("EnableDNS") == "1" - domain = reg.read_s("Domain") - ns = reg.read_s("NameServer") - slist = reg.read_s("SearchList") - search << domain unless domain.empty? - search.concat(slist.split(/,\s*/)) - nameserver.concat(ns.split(/[,\s]\s*/)) - end - end - rescue Registry::Error - end - - dhcpinfo = get_dhcpinfo - search.concat(dhcpinfo[0]) - nameserver.concat(dhcpinfo[1]) - [ search, nameserver ] - end - - def get_dhcpinfo - macaddrs = {} - ipaddrs = {} - WsControl.get_iflist.each do |index, macaddr, *ipaddr| - macaddrs[macaddr] = 1 - ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 } - end - iflist = [ macaddrs, ipaddrs ] - - search = [] - nameserver = [] - version = -1 - Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg| - begin - version = API.unpackdw(reg.read_bin("Version")) - rescue Registry::Error - end - - reg.each_key do |key, | - catch(:not_used) do - reg.open(key) do |regdi| - dom, ns = get_dhcpinfo_key(version, regdi, iflist) - search << dom if dom - nameserver.concat(ns) if ns - end - end - end - end - [ search, nameserver ] - end - - def get_dhcpinfo_95(reg) - dhcp = reg.read_bin("DhcpInfo") - [ - API.unpackdw(dhcp[4..7]), - API.unpackdw(dhcp[8..11]), - 1, - dhcp[45..50], - reg.read_bin("OptionInfo"), - ] - end - - def get_dhcpinfo_98(reg) - [ - API.unpackdw(reg.read_bin("DhcpIPAddress")), - API.unpackdw(reg.read_bin("DhcpSubnetMask")), - API.unpackdw(reg.read_bin("HardwareType")), - reg.read_bin("HardwareAddress"), - reg.read_bin("OptionInfo"), - ] - end - - def get_dhcpinfo_key(version, reg, iflist) - info = case version - when 1 - get_dhcpinfo_95(reg) - when 2 - get_dhcpinfo_98(reg) - else - begin - get_dhcpinfo_98(reg) - rescue Registry::Error - get_dhcpinfo_95(reg) - end - end - ipaddr, netmask, hwtype, macaddr, opt = info - throw :not_used unless - ipaddr and ipaddr != 0 and - netmask and netmask != 0 and - macaddr and macaddr.size == 6 and - hwtype == 1 and - iflist[0][macaddr] and iflist[1][ipaddr] - - size = opt.size - idx = 0 - while idx <= size - opttype = opt[idx] - optsize = opt[idx + 1] - optval = opt[idx + 2, optsize] - case opttype - when 0xFF ## term - break - when 0x0F ## domain - domain = optval.chomp("\0") - when 0x06 ## dns - nameserver = optval.scan(/..../).collect { |addr| - "%d.%d.%d.%d" % addr.unpack('C4') - } - end - idx += optsize + 2 - end - [ domain, nameserver ] - rescue Registry::Error - throw :not_used - end - end - - module WsControl - module WSock32 - extend Importer - dlload "wsock32.dll" - end - WsControl = WSock32.extern "int WsControl(int, int, void *, void *, void *, void *)", :stdcall - WSAGetLastError = WSock32.extern "int WSAGetLastError(void)", :stdcall - - MAX_TDI_ENTITIES = 512 - IPPROTO_TCP = 6 - WSCTL_TCP_QUERY_INFORMATION = 0 - INFO_CLASS_GENERIC = 0x100 - INFO_CLASS_PROTOCOL = 0x200 - INFO_TYPE_PROVIDER = 0x100 - ENTITY_LIST_ID = 0 - GENERIC_ENTITY = 0 - CL_NL_ENTITY = 0x301 - IF_ENTITY = 0x200 - ENTITY_TYPE_ID = 1 - CL_NL_IP = 0x303 - IF_MIB = 0x202 - IF_MIB_STATS_ID = 1 - IP_MIB_ADDRTABLE_ENTRY_ID = 0x102 - - def self.wsctl(tei_entity, tei_instance, - toi_class, toi_type, toi_id, - buffsize) - reqinfo = [ - ## TDIEntityID - tei_entity, tei_instance, - ## TDIObjectID - toi_class, toi_type, toi_id, - ## TCP_REQUEST_INFORMATION_EX - "" - ].pack('VVVVVa16') - reqsize = API.packdw(reqinfo.size) - buff = "\0" * buffsize - buffsize = API.packdw(buffsize) - result = WsControl.call( - IPPROTO_TCP, - WSCTL_TCP_QUERY_INFORMATION, - reqinfo, reqsize, - buff, buffsize) - if result != 0 - raise RuntimeError, "WsControl failed.(#{result})" - end - [ buff, API.unpackdw(buffsize) ] - end - private_class_method :wsctl - - def self.get_iflist - # Get TDI Entity List - entities, size = - wsctl(GENERIC_ENTITY, 0, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_LIST_ID, - MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID) - entities = entities[0, size]. - scan(/.{8}/). - collect { |e| e.unpack('VV') } - - # Get MIB Interface List - iflist = [] - ifcount = 0 - entities.each do |entity, instance| - if( (entity & IF_ENTITY)>0 ) - ifcount += 1 - etype, = wsctl(entity, instance, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_TYPE_ID, - 4) - if( (API.unpackdw(etype) & IF_MIB)==IF_MIB ) - ifentry, = wsctl(entity, instance, - INFO_CLASS_PROTOCOL, - INFO_TYPE_PROVIDER, - IF_MIB_STATS_ID, - 21 * 4 + 8 + 130) # sizeof(IFEntry) - iflist << [ - API.unpackdw(ifentry[0,4]), - ifentry[20, 6] - ] - end - end - end - - # Get IP Addresses - entities.each do |entity, instance| - if entity == CL_NL_ENTITY - etype, = wsctl(entity, instance, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_TYPE_ID, - 4) - if API.unpackdw(etype) == CL_NL_IP - ipentries, = wsctl(entity, instance, - INFO_CLASS_PROTOCOL, - INFO_TYPE_PROVIDER, - IP_MIB_ADDRTABLE_ENTRY_ID, - 24 * (ifcount+1)) # sizeof(IPAddrEntry) - ipentries.scan(/.{24}/) do |ipentry| - ipaddr, index = ipentry.unpack('VV') - if ifitem = iflist.assoc(index) - ifitem << ipaddr - end - end - end - end - end - iflist - end - end - end -end diff --git a/ruby/ext/win32/lib/win32/sspi.rb b/ruby/ext/win32/lib/win32/sspi.rb index 8103893d7..20205fd4d 100644 --- a/ruby/ext/win32/lib/win32/sspi.rb +++ b/ruby/ext/win32/lib/win32/sspi.rb @@ -11,321 +11,328 @@ # Ruby Distribution License or GNU General Public License. # -require 'Win32API' +require 'fiddle/import' # Implements bindings to Win32 SSPI functions, focused on authentication to a proxy server over HTTP. module Win32 - module SSPI - # Specifies how credential structure requested will be used. Only SECPKG_CRED_OUTBOUND is used - # here. - SECPKG_CRED_INBOUND = 0x00000001 - SECPKG_CRED_OUTBOUND = 0x00000002 - SECPKG_CRED_BOTH = 0x00000003 - - # Format of token. NETWORK format is used here. - SECURITY_NATIVE_DREP = 0x00000010 - SECURITY_NETWORK_DREP = 0x00000000 - - # InitializeSecurityContext Requirement flags - ISC_REQ_REPLAY_DETECT = 0x00000004 - ISC_REQ_SEQUENCE_DETECT = 0x00000008 - ISC_REQ_CONFIDENTIALITY = 0x00000010 - ISC_REQ_USE_SESSION_KEY = 0x00000020 - ISC_REQ_PROMPT_FOR_CREDS = 0x00000040 - ISC_REQ_CONNECTION = 0x00000800 - - # Win32 API Functions. Uses Win32API to bind methods to constants contained in class. - module API - # Can be called with AcquireCredentialsHandle.call() - AcquireCredentialsHandle = Win32API.new("secur32", "AcquireCredentialsHandle", 'ppLpppppp', 'L') - # Can be called with InitializeSecurityContext.call() - InitializeSecurityContext = Win32API.new("secur32", "InitializeSecurityContext", 'pppLLLpLpppp', 'L') - # Can be called with DeleteSecurityContext.call() - DeleteSecurityContext = Win32API.new("secur32", "DeleteSecurityContext", 'P', 'L') - # Can be called with FreeCredentialsHandle.call() - FreeCredentialsHandle = Win32API.new("secur32", "FreeCredentialsHandle", 'P', 'L') - end - - # SecHandle struct - class SecurityHandle - def upper - @struct.unpack("LL")[1] - end - - def lower - @struct.unpack("LL")[0] - end - - def to_p - @struct ||= "\0" * 8 - end - end - - # Some familiar aliases for the SecHandle structure - CredHandle = CtxtHandle = SecurityHandle - - # TimeStamp struct - class TimeStamp - attr_reader :struct - - def to_p - @struct ||= "\0" * 8 - end - end - - # Creates binary representations of a SecBufferDesc structure, - # including the SecBuffer contained inside. - class SecurityBuffer - - SECBUFFER_TOKEN = 2 # Security token - - TOKENBUFSIZE = 12288 - SECBUFFER_VERSION = 0 - - def initialize(buffer = nil) - @buffer = buffer || "\0" * TOKENBUFSIZE - @bufferSize = @buffer.length - @type = SECBUFFER_TOKEN - end - - def bufferSize - unpack - @bufferSize - end - - def bufferType - unpack - @type - end - - def token - unpack - @buffer - end - - def to_p - # Assumption is that when to_p is called we are going to get a packed structure. Therefore, - # set @unpacked back to nil so we know to unpack when accessors are next accessed. - @unpacked = nil - # Assignment of inner structure to variable is very important here. Without it, - # will not be able to unpack changes to the structure. Alternative, nested unpacks, - # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer") - @sec_buffer ||= [@bufferSize, @type, @buffer].pack("LLP") - @struct ||= [SECBUFFER_VERSION, 1, @sec_buffer].pack("LLP") - end - - private - - # Unpacks the SecurityBufferDesc structure into member variables. We - # only want to do this once per struct, so the struct is deleted - # after unpacking. - def unpack - if ! @unpacked && @sec_buffer && @struct - @bufferSize, @type = @sec_buffer.unpack("LL") - @buffer = @sec_buffer.unpack("LLP#{@bufferSize}")[2] - @struct = nil - @sec_buffer = nil - @unpacked = true - end - end - end - - # SEC_WINNT_AUTH_IDENTITY structure - class Identity - SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1 - - attr_accessor :user, :domain, :password - - def initialize(user = nil, domain = nil, password = nil) - @user = user - @domain = domain - @password = password - @flags = SEC_WINNT_AUTH_IDENTITY_ANSI - end - - def to_p - [@user, @user ? @user.length : 0, - @domain, @domain ? @domain.length : 0, - @password, @password ? @password.length : 0, - @flags].pack("PLPLPLL") - end - end - - # Takes a return result from an SSPI function and interprets the value. - class SSPIResult - # Good results - SEC_E_OK = 0x00000000 - SEC_I_CONTINUE_NEEDED = 0x00090312 - - # These are generally returned by InitializeSecurityContext - SEC_E_INSUFFICIENT_MEMORY = 0x80090300 - SEC_E_INTERNAL_ERROR = 0x80090304 - SEC_E_INVALID_HANDLE = 0x80090301 - SEC_E_INVALID_TOKEN = 0x80090308 - SEC_E_LOGON_DENIED = 0x8009030C - SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311 - SEC_E_NO_CREDENTIALS = 0x8009030E - SEC_E_TARGET_UNKNOWN = 0x80090303 - SEC_E_UNSUPPORTED_FUNCTION = 0x80090302 - SEC_E_WRONG_PRINCIPAL = 0x80090322 - - # These are generally returned by AcquireCredentialsHandle - SEC_E_NOT_OWNER = 0x80090306 - SEC_E_SECPKG_NOT_FOUND = 0x80090305 - SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D - - @@map = {} - constants.each { |v| @@map[self.const_get(v.to_s)] = v } - - attr_reader :value - - def initialize(value) - # convert to unsigned long - value = [value].pack("L").unpack("L").first - raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value - @value = value - end - - def to_s - @@map[@value].to_s - end - - def ok? - @value == SEC_I_CONTINUE_NEEDED || @value == SEC_E_OK - end - - def ==(other) - if other.is_a?(SSPIResult) - @value == other.value - elsif other.is_a?(Fixnum) - @value == @@map[other] - else - false - end - end - end - - # Handles "Negotiate" type authentication. Geared towards authenticating with a proxy server over HTTP - class NegotiateAuth - attr_accessor :credentials, :context, :contextAttributes, :user, :domain - - # Default request flags for SSPI functions - REQUEST_FLAGS = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION - - # NTLM tokens start with this header always. Encoding alone adds "==" and newline, so remove those + module SSPI + # Specifies how credential structure requested will be used. Only SECPKG_CRED_OUTBOUND is used + # here. + SECPKG_CRED_INBOUND = 0x00000001 + SECPKG_CRED_OUTBOUND = 0x00000002 + SECPKG_CRED_BOTH = 0x00000003 + + # Format of token. NETWORK format is used here. + SECURITY_NATIVE_DREP = 0x00000010 + SECURITY_NETWORK_DREP = 0x00000000 + + # InitializeSecurityContext Requirement flags + ISC_REQ_REPLAY_DETECT = 0x00000004 + ISC_REQ_SEQUENCE_DETECT = 0x00000008 + ISC_REQ_CONFIDENTIALITY = 0x00000010 + ISC_REQ_USE_SESSION_KEY = 0x00000020 + ISC_REQ_PROMPT_FOR_CREDS = 0x00000040 + ISC_REQ_CONNECTION = 0x00000800 + + # Win32 API Functions. Uses Win32API to bind methods to constants contained in class. + module API + extend Fiddle::Importer + dlload "secur32.dll" + [ + # Can be called with AcquireCredentialsHandleA.call() + "unsigned long AcquireCredentialsHandleA(void *, void *, unsigned long, void *, void *, void *, void *, void *, void *)", + # Can be called with InitializeSecurityContextA.call() + "unsigned long InitializeSecurityContextA(void *, void *, void *, unsigned long, unsigned long, unsigned long, void *, unsigned long, void *, void *, void *, void *)", + # Can be called with DeleteSecurityContext.call() + "unsigned long DeleteSecurityContext(void *)", + # Can be called with FreeCredentialsHandle.call() + "unsigned long FreeCredentialsHandle(void *)" + ].each do |fn| + cfunc = extern fn, :stdcall + const_set cfunc.name.intern, cfunc + end + end + + # SecHandle struct + class SecurityHandle + def upper + @struct.unpack("LL")[1] + end + + def lower + @struct.unpack("LL")[0] + end + + def to_p + @struct ||= "\0" * 8 + end + end + + # Some familiar aliases for the SecHandle structure + CredHandle = CtxtHandle = SecurityHandle + + # TimeStamp struct + class TimeStamp + attr_reader :struct + + def to_p + @struct ||= "\0" * 8 + end + end + + # Creates binary representations of a SecBufferDesc structure, + # including the SecBuffer contained inside. + class SecurityBuffer + + SECBUFFER_TOKEN = 2 # Security token + + TOKENBUFSIZE = 12288 + SECBUFFER_VERSION = 0 + + def initialize(buffer = nil) + @buffer = buffer || "\0" * TOKENBUFSIZE + @bufferSize = @buffer.length + @type = SECBUFFER_TOKEN + end + + def bufferSize + unpack + @bufferSize + end + + def bufferType + unpack + @type + end + + def token + unpack + @buffer + end + + def to_p + # Assumption is that when to_p is called we are going to get a packed structure. Therefore, + # set @unpacked back to nil so we know to unpack when accessors are next accessed. + @unpacked = nil + # Assignment of inner structure to variable is very important here. Without it, + # will not be able to unpack changes to the structure. Alternative, nested unpacks, + # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer") + @sec_buffer ||= [@bufferSize, @type, @buffer].pack("LLP") + @struct ||= [SECBUFFER_VERSION, 1, @sec_buffer].pack("LLP") + end + + private + + # Unpacks the SecurityBufferDesc structure into member variables. We + # only want to do this once per struct, so the struct is deleted + # after unpacking. + def unpack + if ! @unpacked && @sec_buffer && @struct + @bufferSize, @type = @sec_buffer.unpack("LL") + @buffer = @sec_buffer.unpack("LLP#{@bufferSize}")[2] + @struct = nil + @sec_buffer = nil + @unpacked = true + end + end + end + + # SEC_WINNT_AUTH_IDENTITY structure + class Identity + SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1 + + attr_accessor :user, :domain, :password + + def initialize(user = nil, domain = nil, password = nil) + @user = user + @domain = domain + @password = password + @flags = SEC_WINNT_AUTH_IDENTITY_ANSI + end + + def to_p + [@user, @user ? @user.length : 0, + @domain, @domain ? @domain.length : 0, + @password, @password ? @password.length : 0, + @flags].pack("PLPLPLL") + end + end + + # Takes a return result from an SSPI function and interprets the value. + class SSPIResult + # Good results + SEC_E_OK = 0x00000000 + SEC_I_CONTINUE_NEEDED = 0x00090312 + + # These are generally returned by InitializeSecurityContext + SEC_E_INSUFFICIENT_MEMORY = 0x80090300 + SEC_E_INTERNAL_ERROR = 0x80090304 + SEC_E_INVALID_HANDLE = 0x80090301 + SEC_E_INVALID_TOKEN = 0x80090308 + SEC_E_LOGON_DENIED = 0x8009030C + SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311 + SEC_E_NO_CREDENTIALS = 0x8009030E + SEC_E_TARGET_UNKNOWN = 0x80090303 + SEC_E_UNSUPPORTED_FUNCTION = 0x80090302 + SEC_E_WRONG_PRINCIPAL = 0x80090322 + + # These are generally returned by AcquireCredentialsHandle + SEC_E_NOT_OWNER = 0x80090306 + SEC_E_SECPKG_NOT_FOUND = 0x80090305 + SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D + + @@map = {} + constants.each { |v| @@map[self.const_get(v.to_s)] = v } + + attr_reader :value + + def initialize(value) + # convert to unsigned long + value = [value].pack("L").unpack("L").first + raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value + @value = value + end + + def to_s + @@map[@value].to_s + end + + def ok? + @value == SEC_I_CONTINUE_NEEDED || @value == SEC_E_OK + end + + def ==(other) + if other.is_a?(SSPIResult) + @value == other.value + elsif other.is_a?(Fixnum) + @value == @@map[other] + else + false + end + end + end + + # Handles "Negotiate" type authentication. Geared towards authenticating with a proxy server over HTTP + class NegotiateAuth + attr_accessor :credentials, :context, :contextAttributes, :user, :domain + + # Default request flags for SSPI functions + REQUEST_FLAGS = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION + + # NTLM tokens start with this header always. Encoding alone adds "==" and newline, so remove those B64_TOKEN_PREFIX = ["NTLMSSP"].pack("m").delete("=\n") - # Given a connection and a request path, performs authentication as the current user and returns - # the response from a GET request. The connnection should be a Net::HTTP object, and it should - # have been constructed using the Net::HTTP.Proxy method, but anything that responds to "get" will work. - # If a user and domain are given, will authenticate as the given user. - # Returns the response received from the get method (usually Net::HTTPResponse) - def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil) - raise "http must respond to :get" unless http.respond_to?(:get) - nego_auth = self.new user, domain - - resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token } - if resp["Proxy-Authenticate"] - resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) } - end - - resp - end - - # Creates a new instance ready for authentication as the given user in the given domain. - # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if - # no arguments are supplied. - def initialize(user = nil, domain = nil) - if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil? - raise "A username or domain must be supplied since they cannot be retrieved from the environment" - end - - @user = user || ENV["USERNAME"] - @domain = domain || ENV["USERDOMAIN"] - end - - # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can - # be easily decoded, however. - def get_initial_token - raise "This object is no longer usable because its resources have been freed." if @cleaned_up - get_credentials - - outputBuffer = SecurityBuffer.new - @context = CtxtHandle.new - @contextAttributes = "\0" * 4 - - result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, nil, nil, - REQUEST_FLAGS,0, SECURITY_NETWORK_DREP, nil, 0, @context.to_p, outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p)) - - if result.ok? then - return encode_token(outputBuffer.token) - else - raise "Error: #{result.to_s}" - end - end - - # Takes a token and gets the next token in the Negotiate authentication chain. Token can be Base64 encoded or not. - # The token can include the "Negotiate" header and it will be stripped. - # Does not indicate if SEC_I_CONTINUE or SEC_E_OK was returned. - # Token returned is Base64 encoded w/ all new lines removed. - def complete_authentication(token) - raise "This object is no longer usable because its resources have been freed." if @cleaned_up - - # Nil token OK, just set it to empty string - token = "" if token.nil? - - if token.include? "Negotiate" - # If the Negotiate prefix is passed in, assume we are seeing "Negotiate " and get the token. - token = token.split(" ").last - end - - if token.include? B64_TOKEN_PREFIX - # indicates base64 encoded token + # Given a connection and a request path, performs authentication as the current user and returns + # the response from a GET request. The connection should be a Net::HTTP object, and it should + # have been constructed using the Net::HTTP.Proxy method, but anything that responds to "get" will work. + # If a user and domain are given, will authenticate as the given user. + # Returns the response received from the get method (usually Net::HTTPResponse) + def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil) + raise "http must respond to :get" unless http.respond_to?(:get) + nego_auth = self.new user, domain + + resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token } + if resp["Proxy-Authenticate"] + resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) } + end + + resp + end + + # Creates a new instance ready for authentication as the given user in the given domain. + # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if + # no arguments are supplied. + def initialize(user = nil, domain = nil) + if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil? + raise "A username or domain must be supplied since they cannot be retrieved from the environment" + end + + @user = user || ENV["USERNAME"] + @domain = domain || ENV["USERDOMAIN"] + end + + # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can + # be easily decoded, however. + def get_initial_token + raise "This object is no longer usable because its resources have been freed." if @cleaned_up + get_credentials + + outputBuffer = SecurityBuffer.new + @context = CtxtHandle.new + @contextAttributes = "\0" * 4 + + result = SSPIResult.new(API::InitializeSecurityContextA.call(@credentials.to_p, nil, nil, + REQUEST_FLAGS,0, SECURITY_NETWORK_DREP, nil, 0, @context.to_p, outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p)) + + if result.ok? then + return encode_token(outputBuffer.token) + else + raise "Error: #{result.to_s}" + end + end + + # Takes a token and gets the next token in the Negotiate authentication chain. Token can be Base64 encoded or not. + # The token can include the "Negotiate" header and it will be stripped. + # Does not indicate if SEC_I_CONTINUE or SEC_E_OK was returned. + # Token returned is Base64 encoded w/ all new lines removed. + def complete_authentication(token) + raise "This object is no longer usable because its resources have been freed." if @cleaned_up + + # Nil token OK, just set it to empty string + token = "" if token.nil? + + if token.include? "Negotiate" + # If the Negotiate prefix is passed in, assume we are seeing "Negotiate " and get the token. + token = token.split(" ").last + end + + if token.include? B64_TOKEN_PREFIX + # indicates base64 encoded token token = token.strip.unpack("m")[0] - end - - outputBuffer = SecurityBuffer.new - result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil, - REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0, - @context.to_p, - outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p)) - - if result.ok? then - return encode_token(outputBuffer.token) - else - raise "Error: #{result.to_s}" - end - ensure - # need to make sure we don't clean up if we've already cleaned up. - clean_up unless @cleaned_up - end - - private - - def clean_up - # free structures allocated - @cleaned_up = true - API::FreeCredentialsHandle.call(@credentials.to_p) - API::DeleteSecurityContext.call(@context.to_p) - @context = nil - @credentials = nil - @contextAttributes = nil - end - - # Gets credentials based on user, domain or both. If both are nil, an error occurs - def get_credentials - @credentials = CredHandle.new - ts = TimeStamp.new - @identity = Identity.new @user, @domain - result = SSPIResult.new(API::AcquireCredentialsHandle.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p, - nil, nil, @credentials.to_p, ts.to_p)) - raise "Error acquire credentials: #{result}" unless result.ok? - end - - def encode_token(t) - # encode64 will add newlines every 60 characters so we need to remove those. + end + + outputBuffer = SecurityBuffer.new + result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil, + REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0, + @context.to_p, + outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p)) + + if result.ok? then + return encode_token(outputBuffer.token) + else + raise "Error: #{result.to_s}" + end + ensure + # need to make sure we don't clean up if we've already cleaned up. + clean_up unless @cleaned_up + end + + private + + def clean_up + # free structures allocated + @cleaned_up = true + API::FreeCredentialsHandle.call(@credentials.to_p) + API::DeleteSecurityContext.call(@context.to_p) + @context = nil + @credentials = nil + @contextAttributes = nil + end + + # Gets credentials based on user, domain or both. If both are nil, an error occurs + def get_credentials + @credentials = CredHandle.new + ts = TimeStamp.new + @identity = Identity.new @user, @domain + result = SSPIResult.new(API::AcquireCredentialsHandleA.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p, + nil, nil, @credentials.to_p, ts.to_p)) + raise "Error acquire credentials: #{result}" unless result.ok? + end + + def encode_token(t) + # encode64 will add newlines every 60 characters so we need to remove those. [t].pack("m").delete("\n") - end - end - end + end + end + end end diff --git a/ruby/ext/win32ole/sample/xml.rb b/ruby/ext/win32ole/sample/xml.rb index 36c3db32e..5a239c933 100644 --- a/ruby/ext/win32ole/sample/xml.rb +++ b/ruby/ext/win32ole/sample/xml.rb @@ -1032,8 +1032,8 @@ def loadXML(arg0) end # VOID save - # save the document to a specified desination - # VARIANT arg0 --- desination [IN] + # save the document to a specified destination + # VARIANT arg0 --- destination [IN] def save(arg0) ret = _invoke(64, [arg0], [VT_VARIANT]) @lastargs = WIN32OLE::ARGV @@ -6224,8 +6224,8 @@ def loadXML(arg0) end # VOID save - # save the document to a specified desination - # VARIANT arg0 --- desination [IN] + # save the document to a specified destination + # VARIANT arg0 --- destination [IN] def save(arg0) ret = @dispatch._invoke(64, [arg0], [VT_VARIANT]) @lastargs = WIN32OLE::ARGV @@ -6831,8 +6831,8 @@ def loadXML(arg0) end # VOID save - # save the document to a specified desination - # VARIANT arg0 --- desination [IN] + # save the document to a specified destination + # VARIANT arg0 --- destination [IN] def save(arg0) ret = @dispatch._invoke(64, [arg0], [VT_VARIANT]) @lastargs = WIN32OLE::ARGV diff --git a/ruby/ext/win32ole/win32ole.c b/ruby/ext/win32ole/win32ole.c index f20bfc84f..5ad6a80eb 100644 --- a/ruby/ext/win32ole/win32ole.c +++ b/ruby/ext/win32ole/win32ole.c @@ -507,6 +507,7 @@ static UINT ole_encoding2cp(rb_encoding *enc) ENC_MACHING_CP(enc, "GB2312", 20936); ENC_MACHING_CP(enc, "GBK", 936); ENC_MACHING_CP(enc, "IBM437", 437); + ENC_MACHING_CP(enc, "IBM720", 720); ENC_MACHING_CP(enc, "IBM737", 737); ENC_MACHING_CP(enc, "IBM775", 775); ENC_MACHING_CP(enc, "IBM852", 852); @@ -994,7 +995,7 @@ ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt) } return; } -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) switch(vt & ~VT_BYREF) { case VT_I8: V_VT(var) = VT_I8; @@ -1008,7 +1009,7 @@ ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt) ole_val2variant2(val, var); break; } -#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ +#else /* (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) */ ole_val2variant2(val, var); #endif } @@ -1062,7 +1063,7 @@ get_ptr_of_variant(VARIANT *pvar) case VT_R8: return &V_R8(pvar); break; -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) case VT_I8: return &V_I8(pvar); break; @@ -1549,10 +1550,10 @@ ole_variant2val(VARIANT *pvar) obj = RB_INT2NUM((long)V_UINT(pvar)); break; -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) case VT_I8: if(V_ISBYREF(pvar)) -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) #ifdef V_I8REF obj = I8_2_NUM(*V_I8REF(pvar)); #endif @@ -1564,7 +1565,7 @@ ole_variant2val(VARIANT *pvar) break; case VT_UI8: if(V_ISBYREF(pvar)) -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) #ifdef V_UI8REF obj = UI8_2_NUM(*V_UI8REF(pvar)); #endif @@ -1574,7 +1575,7 @@ ole_variant2val(VARIANT *pvar) else obj = UI8_2_NUM(V_UI8(pvar)); break; -#endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ +#endif /* (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) */ case VT_R4: if(V_ISBYREF(pvar)) @@ -2651,7 +2652,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) /*------------------------------------------ hash object ==> named dispatch parameters --------------------------------------------*/ - cNamedArgs = rb_long2int(RHASH_SIZE(param)); + cNamedArgs = rb_long2int((long)RHASH_SIZE(param)); op.dp.cArgs = cNamedArgs + argc - 2; op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); @@ -3752,7 +3753,7 @@ ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) case VT_UI4: typestr = rb_str_new2("UI4"); break; -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) case VT_I8: typestr = rb_str_new2("I8"); break; @@ -3962,6 +3963,7 @@ check_nano_server(void) } } +LCID cWIN32OLE_lcid; void Init_win32ole(void) diff --git a/ruby/ext/win32ole/win32ole.gemspec b/ruby/ext/win32ole/win32ole.gemspec new file mode 100644 index 000000000..977555c98 --- /dev/null +++ b/ruby/ext/win32ole/win32ole.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "win32ole" + spec.version = "1.8.8" + spec.authors = ["Masaki Suketa"] + spec.email = ["suke@ruby-lang.org"] + + spec.summary = %q{Provides an interface for OLE Automation in Ruby} + spec.description = spec.summary + spec.homepage = "https://github.com/ruby/win32ole" + 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 + + 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/ruby/ext/win32ole/win32ole.h b/ruby/ext/win32ole/win32ole.h index c01993039..cd627ef76 100644 --- a/ruby/ext/win32ole/win32ole.h +++ b/ruby/ext/win32ole/win32ole.h @@ -112,8 +112,8 @@ struct oledata { IDispatch *pDispatch; }; -VALUE cWIN32OLE; -LCID cWIN32OLE_lcid; +extern VALUE cWIN32OLE; +extern LCID cWIN32OLE_lcid; struct oledata *oledata_get_struct(VALUE obj); LPWSTR ole_vstr2wc(VALUE vstr); diff --git a/ruby/ext/win32ole/win32ole_error.c b/ruby/ext/win32ole/win32ole_error.c index 022527617..2bb515626 100644 --- a/ruby/ext/win32ole/win32ole_error.c +++ b/ruby/ext/win32ole/win32ole_error.c @@ -60,6 +60,9 @@ ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...) rb_exc_raise(rb_exc_new_str(ecs, msg)); } +VALUE eWIN32OLERuntimeError; +VALUE eWIN32OLEQueryInterfaceError; + void Init_win32ole_error(void) { diff --git a/ruby/ext/win32ole/win32ole_error.h b/ruby/ext/win32ole/win32ole_error.h index 296eb101a..a2f329856 100644 --- a/ruby/ext/win32ole/win32ole_error.h +++ b/ruby/ext/win32ole/win32ole_error.h @@ -1,8 +1,8 @@ #ifndef WIN32OLE_ERROR_H #define WIN32OLE_ERROR_H 1 -VALUE eWIN32OLERuntimeError; -VALUE eWIN32OLEQueryInterfaceError; +extern VALUE eWIN32OLERuntimeError; +extern VALUE eWIN32OLEQueryInterfaceError; NORETURN(PRINTF_ARGS(void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...), 3, 4)); void Init_win32ole_error(void); diff --git a/ruby/ext/win32ole/win32ole_method.c b/ruby/ext/win32ole/win32ole_method.c index ffa932465..6ed5def6d 100644 --- a/ruby/ext/win32ole/win32ole_method.c +++ b/ruby/ext/win32ole/win32ole_method.c @@ -437,7 +437,7 @@ ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_MTHOD#invkind + * WIN32OLE_METHOD#invkind * * Returns the method invoke kind. * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') @@ -923,6 +923,8 @@ folemethod_inspect(VALUE self) return default_inspect(self, "WIN32OLE_METHOD"); } +VALUE cWIN32OLE_METHOD; + void Init_win32ole_method(void) { cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); diff --git a/ruby/ext/win32ole/win32ole_method.h b/ruby/ext/win32ole/win32ole_method.h index ff2898ebe..ef907d2fa 100644 --- a/ruby/ext/win32ole/win32ole_method.h +++ b/ruby/ext/win32ole/win32ole_method.h @@ -7,7 +7,7 @@ struct olemethoddata { UINT index; }; -VALUE cWIN32OLE_METHOD; +extern VALUE cWIN32OLE_METHOD; VALUE folemethod_s_allocate(VALUE klass); VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); VALUE create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name); diff --git a/ruby/ext/win32ole/win32ole_record.c b/ruby/ext/win32ole/win32ole_record.c index e8838832a..03523bc47 100644 --- a/ruby/ext/win32ole/win32ole_record.c +++ b/ruby/ext/win32ole/win32ole_record.c @@ -589,6 +589,8 @@ folerecord_inspect(VALUE self) field); } +VALUE cWIN32OLE_RECORD; + void Init_win32ole_record(void) { diff --git a/ruby/ext/win32ole/win32ole_record.h b/ruby/ext/win32ole/win32ole_record.h index ea431e91f..ab1df0ee7 100644 --- a/ruby/ext/win32ole/win32ole_record.h +++ b/ruby/ext/win32ole/win32ole_record.h @@ -1,7 +1,7 @@ #ifndef WIN32OLE_RECORD_H #define WIN32OLE_RECORD_H 1 -VALUE cWIN32OLE_RECORD; +extern VALUE cWIN32OLE_RECORD; void ole_rec2variant(VALUE rec, VARIANT *var); void olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec); VALUE create_win32ole_record(IRecordInfo *pri, void *prec); diff --git a/ruby/ext/win32ole/win32ole_type.c b/ruby/ext/win32ole/win32ole_type.c index e6ac402ec..48dbc9dbd 100644 --- a/ruby/ext/win32ole/win32ole_type.c +++ b/ruby/ext/win32ole/win32ole_type.c @@ -56,7 +56,7 @@ static const rb_data_type_t oletype_datatype = { /* * Document-class: WIN32OLE_TYPE * - * WIN32OLE_TYPE objects represent OLE type libarary information. + * WIN32OLE_TYPE objects represent OLE type library information. */ static void @@ -883,6 +883,8 @@ foletype_inspect(VALUE self) return default_inspect(self, "WIN32OLE_TYPE"); } +VALUE cWIN32OLE_TYPE; + void Init_win32ole_type(void) { cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject); diff --git a/ruby/ext/win32ole/win32ole_type.h b/ruby/ext/win32ole/win32ole_type.h index a26bf3e04..87b551e50 100644 --- a/ruby/ext/win32ole/win32ole_type.h +++ b/ruby/ext/win32ole/win32ole_type.h @@ -1,6 +1,6 @@ #ifndef WIN32OLE_TYPE_H #define WIN32OLE_TYPE_H 1 -VALUE cWIN32OLE_TYPE; +extern VALUE cWIN32OLE_TYPE; VALUE create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name); ITypeInfo *itypeinfo(VALUE self); VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo); diff --git a/ruby/ext/win32ole/win32ole_typelib.c b/ruby/ext/win32ole/win32ole_typelib.c index 35376c644..d89f181e0 100644 --- a/ruby/ext/win32ole/win32ole_typelib.c +++ b/ruby/ext/win32ole/win32ole_typelib.c @@ -822,6 +822,8 @@ foletypelib_inspect(VALUE self) return default_inspect(self, "WIN32OLE_TYPELIB"); } +VALUE cWIN32OLE_TYPELIB; + void Init_win32ole_typelib(void) { diff --git a/ruby/ext/win32ole/win32ole_typelib.h b/ruby/ext/win32ole/win32ole_typelib.h index 9fc117fcb..2c2730bb5 100644 --- a/ruby/ext/win32ole/win32ole_typelib.h +++ b/ruby/ext/win32ole/win32ole_typelib.h @@ -1,7 +1,7 @@ #ifndef WIN32OLE_TYPELIB_H #define WIN32OLE_TYPELIB_H 1 -VALUE cWIN32OLE_TYPELIB; +extern VALUE cWIN32OLE_TYPELIB; void Init_win32ole_typelib(void); ITypeLib * itypelib(VALUE self); diff --git a/ruby/ext/win32ole/win32ole_variable.c b/ruby/ext/win32ole/win32ole_variable.c index 3dc9972ee..803083156 100644 --- a/ruby/ext/win32ole/win32ole_variable.c +++ b/ruby/ext/win32ole/win32ole_variable.c @@ -365,6 +365,8 @@ folevariable_inspect(VALUE self) return make_inspect("WIN32OLE_VARIABLE", detail); } +VALUE cWIN32OLE_VARIABLE; + void Init_win32ole_variable(void) { cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject); diff --git a/ruby/ext/win32ole/win32ole_variable.h b/ruby/ext/win32ole/win32ole_variable.h index 704dc1350..209613fd4 100644 --- a/ruby/ext/win32ole/win32ole_variable.h +++ b/ruby/ext/win32ole/win32ole_variable.h @@ -1,7 +1,7 @@ #ifndef WIN32OLE_VARIABLE_H #define WIN32OLE_VARIABLE_H 1 -VALUE cWIN32OLE_VARIABLE; +extern VALUE cWIN32OLE_VARIABLE; VALUE create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name); void Init_win32ole_variable(void); diff --git a/ruby/ext/win32ole/win32ole_variant.c b/ruby/ext/win32ole/win32ole_variant.c index 3ff8f4ffb..0953fc324 100644 --- a/ruby/ext/win32ole/win32ole_variant.c +++ b/ruby/ext/win32ole/win32ole_variant.c @@ -94,7 +94,7 @@ ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) } } } -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); @@ -202,7 +202,7 @@ ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt) V_R8REF(var) = &V_R8(realvar); break; -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) #ifdef V_I8REF case VT_I8: V_I8REF(var) = &V_I8(realvar); @@ -371,7 +371,7 @@ check_type_val2variant(VALUE val) * Win32OLE converts Ruby object into OLE variant automatically when * invoking OLE methods. If OLE method requires the argument which is * different from the variant by automatic conversion of Win32OLE, you - * can convert the specfied variant type by using WIN32OLE_VARIANT class. + * can convert the specified variant type by using WIN32OLE_VARIANT class. * * param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4) * oleobj.method(param) @@ -689,6 +689,8 @@ ole_variant2variant(VALUE val, VARIANT *var) VariantCopy(var, &(pvar->var)); } +VALUE cWIN32OLE_VARIANT; + void Init_win32ole_variant(void) { diff --git a/ruby/ext/win32ole/win32ole_variant.h b/ruby/ext/win32ole/win32ole_variant.h index efe7ea8be..4bd3b0aee 100644 --- a/ruby/ext/win32ole/win32ole_variant.h +++ b/ruby/ext/win32ole/win32ole_variant.h @@ -1,7 +1,7 @@ #ifndef WIN32OLE_VARIANT_H #define WIN32OLE_VARIANT_H 1 -VALUE cWIN32OLE_VARIANT; +extern VALUE cWIN32OLE_VARIANT; void ole_variant2variant(VALUE val, VARIANT *var); void Init_win32ole_variant(void); diff --git a/ruby/ext/win32ole/win32ole_variant_m.c b/ruby/ext/win32ole/win32ole_variant_m.c index 4d76fdc79..c285a0017 100644 --- a/ruby/ext/win32ole/win32ole_variant_m.c +++ b/ruby/ext/win32ole/win32ole_variant_m.c @@ -1,5 +1,7 @@ #include "win32ole.h" +VALUE mWIN32OLE_VARIANT; + void Init_win32ole_variant_m(void) { /* @@ -114,7 +116,7 @@ void Init_win32ole_variant_m(void) */ rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", RB_INT2FIX(VT_UI4)); -#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) /* * represents VT_I8 type constant. */ diff --git a/ruby/ext/win32ole/win32ole_variant_m.h b/ruby/ext/win32ole/win32ole_variant_m.h index afbef3021..6272a6578 100644 --- a/ruby/ext/win32ole/win32ole_variant_m.h +++ b/ruby/ext/win32ole/win32ole_variant_m.h @@ -1,7 +1,7 @@ #ifndef WIN32OLE_VARIANT_M_H #define WIN32OLE_VARIANT_M_H 1 -VALUE mWIN32OLE_VARIANT; +extern VALUE mWIN32OLE_VARIANT; void Init_win32ole_variant_m(void); #endif diff --git a/ruby/ext/zlib/depend b/ruby/ext/zlib/depend index 5ab5684fb..68c1efde0 100644 --- a/ruby/ext/zlib/depend +++ b/ruby/ext/zlib/depend @@ -4,9 +4,165 @@ zlib.o: $(arch_hdrdir)/ruby/config.h zlib.o: $(hdrdir)/ruby.h zlib.o: $(hdrdir)/ruby/assert.h zlib.o: $(hdrdir)/ruby/backward.h +zlib.o: $(hdrdir)/ruby/backward/2/assume.h +zlib.o: $(hdrdir)/ruby/backward/2/attributes.h +zlib.o: $(hdrdir)/ruby/backward/2/bool.h +zlib.o: $(hdrdir)/ruby/backward/2/inttypes.h +zlib.o: $(hdrdir)/ruby/backward/2/limits.h +zlib.o: $(hdrdir)/ruby/backward/2/long_long.h +zlib.o: $(hdrdir)/ruby/backward/2/stdalign.h +zlib.o: $(hdrdir)/ruby/backward/2/stdarg.h zlib.o: $(hdrdir)/ruby/defines.h zlib.o: $(hdrdir)/ruby/encoding.h zlib.o: $(hdrdir)/ruby/intern.h +zlib.o: $(hdrdir)/ruby/internal/anyargs.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/char.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/double.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/int.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/long.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/short.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +zlib.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +zlib.o: $(hdrdir)/ruby/internal/assume.h +zlib.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +zlib.o: $(hdrdir)/ruby/internal/attr/artificial.h +zlib.o: $(hdrdir)/ruby/internal/attr/cold.h +zlib.o: $(hdrdir)/ruby/internal/attr/const.h +zlib.o: $(hdrdir)/ruby/internal/attr/constexpr.h +zlib.o: $(hdrdir)/ruby/internal/attr/deprecated.h +zlib.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +zlib.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +zlib.o: $(hdrdir)/ruby/internal/attr/error.h +zlib.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +zlib.o: $(hdrdir)/ruby/internal/attr/forceinline.h +zlib.o: $(hdrdir)/ruby/internal/attr/format.h +zlib.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +zlib.o: $(hdrdir)/ruby/internal/attr/noalias.h +zlib.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +zlib.o: $(hdrdir)/ruby/internal/attr/noexcept.h +zlib.o: $(hdrdir)/ruby/internal/attr/noinline.h +zlib.o: $(hdrdir)/ruby/internal/attr/nonnull.h +zlib.o: $(hdrdir)/ruby/internal/attr/noreturn.h +zlib.o: $(hdrdir)/ruby/internal/attr/pure.h +zlib.o: $(hdrdir)/ruby/internal/attr/restrict.h +zlib.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +zlib.o: $(hdrdir)/ruby/internal/attr/warning.h +zlib.o: $(hdrdir)/ruby/internal/attr/weakref.h +zlib.o: $(hdrdir)/ruby/internal/cast.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +zlib.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +zlib.o: $(hdrdir)/ruby/internal/compiler_since.h +zlib.o: $(hdrdir)/ruby/internal/config.h +zlib.o: $(hdrdir)/ruby/internal/constant_p.h +zlib.o: $(hdrdir)/ruby/internal/core.h +zlib.o: $(hdrdir)/ruby/internal/core/rarray.h +zlib.o: $(hdrdir)/ruby/internal/core/rbasic.h +zlib.o: $(hdrdir)/ruby/internal/core/rbignum.h +zlib.o: $(hdrdir)/ruby/internal/core/rclass.h +zlib.o: $(hdrdir)/ruby/internal/core/rdata.h +zlib.o: $(hdrdir)/ruby/internal/core/rfile.h +zlib.o: $(hdrdir)/ruby/internal/core/rhash.h +zlib.o: $(hdrdir)/ruby/internal/core/robject.h +zlib.o: $(hdrdir)/ruby/internal/core/rregexp.h +zlib.o: $(hdrdir)/ruby/internal/core/rstring.h +zlib.o: $(hdrdir)/ruby/internal/core/rstruct.h +zlib.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +zlib.o: $(hdrdir)/ruby/internal/ctype.h +zlib.o: $(hdrdir)/ruby/internal/dllexport.h +zlib.o: $(hdrdir)/ruby/internal/dosish.h +zlib.o: $(hdrdir)/ruby/internal/encoding/coderange.h +zlib.o: $(hdrdir)/ruby/internal/encoding/ctype.h +zlib.o: $(hdrdir)/ruby/internal/encoding/encoding.h +zlib.o: $(hdrdir)/ruby/internal/encoding/pathname.h +zlib.o: $(hdrdir)/ruby/internal/encoding/re.h +zlib.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +zlib.o: $(hdrdir)/ruby/internal/encoding/string.h +zlib.o: $(hdrdir)/ruby/internal/encoding/symbol.h +zlib.o: $(hdrdir)/ruby/internal/encoding/transcode.h +zlib.o: $(hdrdir)/ruby/internal/error.h +zlib.o: $(hdrdir)/ruby/internal/eval.h +zlib.o: $(hdrdir)/ruby/internal/event.h +zlib.o: $(hdrdir)/ruby/internal/fl_type.h +zlib.o: $(hdrdir)/ruby/internal/gc.h +zlib.o: $(hdrdir)/ruby/internal/glob.h +zlib.o: $(hdrdir)/ruby/internal/globals.h +zlib.o: $(hdrdir)/ruby/internal/has/attribute.h +zlib.o: $(hdrdir)/ruby/internal/has/builtin.h +zlib.o: $(hdrdir)/ruby/internal/has/c_attribute.h +zlib.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +zlib.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +zlib.o: $(hdrdir)/ruby/internal/has/extension.h +zlib.o: $(hdrdir)/ruby/internal/has/feature.h +zlib.o: $(hdrdir)/ruby/internal/has/warning.h +zlib.o: $(hdrdir)/ruby/internal/intern/array.h +zlib.o: $(hdrdir)/ruby/internal/intern/bignum.h +zlib.o: $(hdrdir)/ruby/internal/intern/class.h +zlib.o: $(hdrdir)/ruby/internal/intern/compar.h +zlib.o: $(hdrdir)/ruby/internal/intern/complex.h +zlib.o: $(hdrdir)/ruby/internal/intern/cont.h +zlib.o: $(hdrdir)/ruby/internal/intern/dir.h +zlib.o: $(hdrdir)/ruby/internal/intern/enum.h +zlib.o: $(hdrdir)/ruby/internal/intern/enumerator.h +zlib.o: $(hdrdir)/ruby/internal/intern/error.h +zlib.o: $(hdrdir)/ruby/internal/intern/eval.h +zlib.o: $(hdrdir)/ruby/internal/intern/file.h +zlib.o: $(hdrdir)/ruby/internal/intern/gc.h +zlib.o: $(hdrdir)/ruby/internal/intern/hash.h +zlib.o: $(hdrdir)/ruby/internal/intern/io.h +zlib.o: $(hdrdir)/ruby/internal/intern/load.h +zlib.o: $(hdrdir)/ruby/internal/intern/marshal.h +zlib.o: $(hdrdir)/ruby/internal/intern/numeric.h +zlib.o: $(hdrdir)/ruby/internal/intern/object.h +zlib.o: $(hdrdir)/ruby/internal/intern/parse.h +zlib.o: $(hdrdir)/ruby/internal/intern/proc.h +zlib.o: $(hdrdir)/ruby/internal/intern/process.h +zlib.o: $(hdrdir)/ruby/internal/intern/random.h +zlib.o: $(hdrdir)/ruby/internal/intern/range.h +zlib.o: $(hdrdir)/ruby/internal/intern/rational.h +zlib.o: $(hdrdir)/ruby/internal/intern/re.h +zlib.o: $(hdrdir)/ruby/internal/intern/ruby.h +zlib.o: $(hdrdir)/ruby/internal/intern/select.h +zlib.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +zlib.o: $(hdrdir)/ruby/internal/intern/signal.h +zlib.o: $(hdrdir)/ruby/internal/intern/sprintf.h +zlib.o: $(hdrdir)/ruby/internal/intern/string.h +zlib.o: $(hdrdir)/ruby/internal/intern/struct.h +zlib.o: $(hdrdir)/ruby/internal/intern/thread.h +zlib.o: $(hdrdir)/ruby/internal/intern/time.h +zlib.o: $(hdrdir)/ruby/internal/intern/variable.h +zlib.o: $(hdrdir)/ruby/internal/intern/vm.h +zlib.o: $(hdrdir)/ruby/internal/interpreter.h +zlib.o: $(hdrdir)/ruby/internal/iterator.h +zlib.o: $(hdrdir)/ruby/internal/memory.h +zlib.o: $(hdrdir)/ruby/internal/method.h +zlib.o: $(hdrdir)/ruby/internal/module.h +zlib.o: $(hdrdir)/ruby/internal/newobj.h +zlib.o: $(hdrdir)/ruby/internal/rgengc.h +zlib.o: $(hdrdir)/ruby/internal/scan_args.h +zlib.o: $(hdrdir)/ruby/internal/special_consts.h +zlib.o: $(hdrdir)/ruby/internal/static_assert.h +zlib.o: $(hdrdir)/ruby/internal/stdalign.h +zlib.o: $(hdrdir)/ruby/internal/stdbool.h +zlib.o: $(hdrdir)/ruby/internal/symbol.h +zlib.o: $(hdrdir)/ruby/internal/value.h +zlib.o: $(hdrdir)/ruby/internal/value_type.h +zlib.o: $(hdrdir)/ruby/internal/variable.h +zlib.o: $(hdrdir)/ruby/internal/warning_push.h +zlib.o: $(hdrdir)/ruby/internal/xmalloc.h zlib.o: $(hdrdir)/ruby/io.h zlib.o: $(hdrdir)/ruby/missing.h zlib.o: $(hdrdir)/ruby/onigmo.h diff --git a/ruby/ext/zlib/extconf.rb b/ruby/ext/zlib/extconf.rb index fd2f16852..d674544f2 100644 --- a/ruby/ext/zlib/extconf.rb +++ b/ruby/ext/zlib/extconf.rb @@ -10,11 +10,12 @@ dir_config 'zlib' - +libs = $libs if %w'z libz zlib1 zlib zdll zlibwapi'.find {|z| have_library(z, 'deflateReset')} and have_header('zlib.h') then have_zlib = true else + $libs = libs unless File.directory?(zsrc = "#{$srcdir}/zlib") dirs = Dir.open($srcdir) {|z| z.grep(/\Azlib-\d+[.\d]*\z/) {|x|"#{$srcdir}/#{x}"}} dirs.delete_if {|x| !File.directory?(x)} @@ -31,9 +32,12 @@ $extso << dll $cleanfiles << "$(topdir)/#{dll}" << "$(ZIMPLIB)" zmk = "\t$(MAKE) -f $(ZMKFILE) TOP=$(ZSRC)" + zopts = [] if $nmake zmkfile = "$(ZSRC)/win32/Makefile.msc" m = "#{zsrc}/win32/Makefile.msc" + # zopts << "USE_ASM=1" + zopts << "ARCH=#{RbConfig::CONFIG['target_cpu']}" else zmkfile = "$(ZSRC)/win32/Makefile.gcc" m = "#{zsrc}/win32/Makefile.gcc" @@ -43,7 +47,7 @@ end m = File.read(m) zimplib = m[/^IMPLIB[ \t]*=[ \t]*(\S+)/, 1] - $LOCAL_LIBS << " " << zimplib + ($LOCAL_LIBS << " ./" << zimplib).strip! unless $nmake or /^TOP[ \t]/ =~ m m.gsub!(/win32\/zlib\.def/, '$(TOP)/\&') m.gsub!(/^(\t.*[ \t])(\S+\.rc)/, '\1-I$( len) +- n = len; ++ n = (unsigned)len; + + /* first just try copying data from the output buffer */ + if (state->x.have) { +@@ -397,7 +397,7 @@ + } + + /* read len or fewer bytes to buf */ +- len = gz_read(state, buf, len); ++ len = (unsigned)gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) +@@ -469,7 +469,7 @@ + } + + /* nothing there -- try gz_read() */ +- ret = gz_read(state, buf, 1); ++ ret = (int)gz_read(state, buf, 1); + return ret < 1 ? -1 : buf[0]; + } + +diff -ru zlib-1.2.11/gzwrite.c zlib-1.2.11/gzwrite.c +--- zlib-1.2.11/gzwrite.c 2017-01-15 09:29:40.000000000 +0900 ++++ zlib-1.2.11/gzwrite.c 2020-11-23 19:35:41.530494030 +0900 +@@ -209,7 +209,7 @@ + state->in); + copy = state->size - have; + if (copy > len) +- copy = len; ++ copy = (unsigned)len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; +@@ -229,7 +229,7 @@ + do { + unsigned n = (unsigned)-1; + if (n > len) +- n = len; ++ n = (unsigned)len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) +@@ -368,7 +368,7 @@ + + /* write string */ + len = strlen(str); +- ret = gz_write(state, str, len); ++ ret = (int)gz_write(state, str, len); + return ret == 0 && len != 0 ? -1 : ret; + } + +diff -ru zlib-1.2.11/win32/Makefile.msc zlib-1.2.11/win32/Makefile.msc +--- zlib-1.2.11/win32/Makefile.msc 2017-01-15 09:07:08.000000000 +0900 ++++ zlib-1.2.11/win32/Makefile.msc 2020-11-23 22:37:19.746500208 +0900 +@@ -37,6 +37,22 @@ + gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj + OBJA = + ++!ifdef USE_ASM ++LOC = -DASMV -DASMINF ++!if "$(ARCH)" == "i386" ++OBJA = inffas32.obj match686.obj ++!else if "$(ARCH)" == "x64" ++AS = ml64 ++LOC = $(LOC) -I. ++OBJA = inffasx64.obj gvmat64.obj inffas8664.obj ++!endif ++!endif ++ ++!if "$(ARCH)" == "x64" ++ZBASE = 0x5A4C000000 ++!else ++ZBASE = 0x5A4C0000 ++!endif + + # targets + all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ +@@ -49,7 +65,7 @@ + + $(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res + $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \ +- -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res ++ -out:$@ -base:$(ZBASE) $(OBJS) $(OBJA) zlib1.res + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;2 + diff --git a/ruby/ext/zlib/zlib.c b/ruby/ext/zlib/zlib.c index 5c8aab24a..be5f148bc 100644 --- a/ruby/ext/zlib/zlib.c +++ b/ruby/ext/zlib/zlib.c @@ -25,7 +25,7 @@ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 #endif -#define RUBY_ZLIB_VERSION "1.1.0" +#define RUBY_ZLIB_VERSION "2.1.1" #ifndef RB_PASS_CALLED_KEYWORDS # define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass) @@ -56,7 +56,10 @@ max_uint(long n) #define MAX_UINT(n) (uInt)(n) #endif -static ID id_dictionaries; +#define OPTHASH_GIVEN_P(opts) \ + (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1)) + +static ID id_dictionaries, id_read, id_buffer; /*--------- Prototypes --------*/ @@ -130,7 +133,7 @@ static VALUE rb_inflate_s_allocate(VALUE); static VALUE rb_inflate_initialize(int, VALUE*, VALUE); static VALUE rb_inflate_s_inflate(VALUE, VALUE); static void do_inflate(struct zstream*, VALUE); -static VALUE rb_inflate_inflate(VALUE, VALUE); +static VALUE rb_inflate_inflate(int, VALUE*, VALUE); static VALUE rb_inflate_addstr(VALUE, VALUE); static VALUE rb_inflate_sync(VALUE, VALUE); static VALUE rb_inflate_sync_point_p(VALUE); @@ -285,6 +288,7 @@ static VALUE rb_gzreader_readlines(int, VALUE*, VALUE); * - Zlib::MemError * - Zlib::BufError * - Zlib::VersionError + * - Zlib::InProgressError * * (if you have GZIP_SUPPORT) * - Zlib::GzipReader @@ -301,7 +305,7 @@ void Init_zlib(void); /*--------- Exceptions --------*/ static VALUE cZError, cStreamEnd, cNeedDict; -static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError; +static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError, cInProgressError; static void raise_zlib_error(int err, const char *msg) @@ -351,7 +355,9 @@ raise_zlib_error(int err, const char *msg) static void finalizer_warn(const char *msg) { +#if 0 fprintf(stderr, "zlib(finalizer): %s\n", msg); +#endif } @@ -407,6 +413,15 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt)) if (NIL_P(str)) { sum = func(sum, Z_NULL, 0); } + else if (rb_obj_is_kind_of(str, rb_cIO)) { + VALUE buf; + VALUE buflen = INT2NUM(8192); + + while (!NIL_P(buf = rb_funcall(str, id_read, 1, buflen))) { + StringValue(buf); + sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(buf), RSTRING_LEN(buf)); + } + } else { StringValue(str); sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str)); @@ -422,6 +437,8 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt)) * Calculates Adler-32 checksum for +string+, and returns updated value of * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If * +adler+ is omitted, it assumes that the initial value is given to +adler+. + * If +string+ is an IO instance, reads from the IO until the IO returns nil + * and returns Adler-32 of all read data. * * Example usage: * @@ -466,7 +483,9 @@ rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2) * * Calculates CRC checksum for +string+, and returns updated value of +crc+. If * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it - * assumes that the initial value is given to +crc+. + * assumes that the initial value is given to +crc+. If +string+ is an IO instance, + * reads from the IO until the IO returns nil and returns CRC checksum of all read + * data. * * FIXME: expression. */ @@ -530,6 +549,7 @@ struct zstream { unsigned long flags; VALUE buf; VALUE input; + VALUE mutex; z_stream stream; const struct zstream_funcs { int (*reset)(z_streamp); @@ -538,13 +558,15 @@ struct zstream { } *func; }; -#define ZSTREAM_FLAG_READY 0x1 -#define ZSTREAM_FLAG_IN_STREAM 0x2 -#define ZSTREAM_FLAG_FINISHED 0x4 -#define ZSTREAM_FLAG_CLOSING 0x8 -#define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for +#define ZSTREAM_FLAG_READY (1 << 0) +#define ZSTREAM_FLAG_IN_STREAM (1 << 1) +#define ZSTREAM_FLAG_FINISHED (1 << 2) +#define ZSTREAM_FLAG_CLOSING (1 << 3) +#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for gzip*/ -#define ZSTREAM_FLAG_UNUSED 0x20 +#define ZSTREAM_REUSE_BUFFER (1 << 5) +#define ZSTREAM_IN_PROGRESS (1 << 6) +#define ZSTREAM_FLAG_UNUSED (1 << 7) #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY) #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY) @@ -553,6 +575,8 @@ struct zstream { #define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE) #define ZSTREAM_BUF_FILLED(z) (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf)) +#define ZSTREAM_REUSE_BUFFER_P(z) ((z)->flags & ZSTREAM_REUSE_BUFFER) + #define ZSTREAM_EXPAND_BUFFER_OK 0 /* I think that more better value should be found, @@ -571,7 +595,9 @@ static const struct zstream_funcs inflate_funcs = { }; struct zstream_run_args { - struct zstream * z; + struct zstream *const z; + Bytef *src; + long len; int flush; /* stream flush value for inflate() or deflate() */ int interrupt; /* stop processing the stream and return to ruby */ int jump_state; /* for buffer expansion block break or exception */ @@ -602,6 +628,7 @@ zstream_init(struct zstream *z, const struct zstream_funcs *func) z->flags = 0; z->buf = Qnil; z->input = Qnil; + z->mutex = rb_mutex_new(); z->stream.zalloc = zlib_mem_alloc; z->stream.zfree = zlib_mem_free; z->stream.opaque = Z_NULL; @@ -629,11 +656,21 @@ zstream_expand_buffer(struct zstream *z) if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) { int state = 0; - rb_obj_reveal(z->buf, rb_cString); + if (!ZSTREAM_REUSE_BUFFER_P(z)) { + rb_obj_reveal(z->buf, rb_cString); + } + rb_mutex_unlock(z->mutex); rb_protect(rb_yield, z->buf, &state); - - z->buf = Qnil; + rb_mutex_lock(z->mutex); + + if (ZSTREAM_REUSE_BUFFER_P(z)) { + rb_str_modify(z->buf); + rb_str_set_len(z->buf, 0); + } + else { + z->buf = Qnil; + } zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX); if (state) @@ -751,7 +788,9 @@ zstream_detach_buffer(struct zstream *z) } else { dst = z->buf; - rb_obj_reveal(dst, rb_cString); + if (!ZSTREAM_REUSE_BUFFER_P(z)) { + rb_obj_reveal(dst, rb_cString); + } } z->buf = Qnil; @@ -859,7 +898,6 @@ zstream_discard_input(struct zstream *z, long len) } rb_str_resize(z->input, newlen); if (newlen == 0) { - rb_gc_force_recycle(z->input); z->input = Qnil; } else { @@ -1024,19 +1062,18 @@ zstream_unblock_func(void *ptr) args->interrupt = 1; } -static void -zstream_run(struct zstream *z, Bytef *src, long len, int flush) +static VALUE +zstream_run_try(VALUE value_arg) { - struct zstream_run_args args; + struct zstream_run_args *args = (struct zstream_run_args *)value_arg; + struct zstream *z = args->z; + Bytef *src = args->src; + long len = args->len; + int flush = args->flush; + int err; VALUE old_input = Qnil; - args.z = z; - args.flush = flush; - args.interrupt = 0; - args.jump_state = 0; - args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(); - if (NIL_P(z->input) && len == 0) { z->stream.next_in = (Bytef*)""; z->stream.avail_in = 0; @@ -1058,14 +1095,20 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush) loop: #ifndef RB_NOGVL_UBF_ASYNC_SAFE - err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args, - zstream_unblock_func, (void *)&args); + err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args, + zstream_unblock_func, (void *)args); #else - err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args, - zstream_unblock_func, (void *)&args, + err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args, + zstream_unblock_func, (void *)args, RB_NOGVL_UBF_ASYNC_SAFE); #endif + /* retry if no exception is thrown */ + if (err == Z_OK && args->interrupt) { + args->interrupt = 0; + goto loop; + } + if (flush != Z_FINISH && err == Z_BUF_ERROR && z->stream.avail_out > 0) { z->flags |= ZSTREAM_FLAG_IN_STREAM; @@ -1096,11 +1139,54 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush) } if (!NIL_P(old_input)) { rb_str_resize(old_input, 0); - rb_gc_force_recycle(old_input); } - if (args.jump_state) - rb_jump_tag(args.jump_state); + if (args->jump_state) + rb_jump_tag(args->jump_state); + + return Qnil; +} + +static VALUE +zstream_run_ensure(VALUE value_arg) +{ + struct zstream_run_args *args = (struct zstream_run_args *)value_arg; + + /* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */ + args->z->flags &= ~ZSTREAM_IN_PROGRESS; + + return Qnil; +} + +static VALUE +zstream_run_synchronized(VALUE value_arg) +{ + struct zstream_run_args *args = (struct zstream_run_args *)value_arg; + + /* Cannot start zstream while it is in progress. */ + if (args->z->flags & ZSTREAM_IN_PROGRESS) { + rb_raise(cInProgressError, "zlib stream is in progress"); + } + args->z->flags |= ZSTREAM_IN_PROGRESS; + + rb_ensure(zstream_run_try, value_arg, zstream_run_ensure, value_arg); + + return Qnil; +} + +static void +zstream_run(struct zstream *z, Bytef *src, long len, int flush) +{ + struct zstream_run_args args = { + .z = z, + .src = src, + .len = len, + .flush = flush, + .interrupt = 0, + .jump_state = 0, + .stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(), + }; + rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args); } static VALUE @@ -1148,6 +1234,7 @@ zstream_mark(void *p) struct zstream *z = p; rb_gc_mark(z->buf); rb_gc_mark(z->input); + rb_gc_mark(z->mutex); } static void @@ -2000,8 +2087,8 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) * Document-method: Zlib::Inflate#inflate * * call-seq: - * inflate(deflate_string) -> String - * inflate(deflate_string) { |chunk| ... } -> nil + * inflate(deflate_string, buffer: nil) -> String + * inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil * * Inputs +deflate_string+ into the inflate stream and returns the output from * the stream. Calling this method, both the input and the output buffer of @@ -2011,6 +2098,15 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) * If a block is given consecutive inflated chunks from the +deflate_string+ * are yielded to the block and +nil+ is returned. * + * If a :buffer keyword argument is given and not nil: + * + * * The :buffer keyword should be a String, and will used as the output buffer. + * Using this option can reuse the memory required during inflation. + * * When not passing a block, the return value will be the same object as the + * :buffer keyword argument. + * * When passing a block, the yielded chunks will be the same value as the + * :buffer keyword argument. + * * Raises a Zlib::NeedDict exception if a preset dictionary is needed to * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then * call this method again with an empty string to flush the stream: @@ -2034,10 +2130,37 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) * See also Zlib::Inflate.new */ static VALUE -rb_inflate_inflate(VALUE obj, VALUE src) +rb_inflate_inflate(int argc, VALUE* argv, VALUE obj) { struct zstream *z = get_zstream(obj); - VALUE dst; + VALUE dst, src, opts, buffer = Qnil; + + if (OPTHASH_GIVEN_P(opts)) { + VALUE buf; + rb_get_kwargs(opts, &id_buffer, 0, 1, &buf); + if (buf != Qundef && buf != Qnil) { + buffer = StringValue(buf); + } + } + if (buffer != Qnil) { + if (!(ZSTREAM_REUSE_BUFFER_P(z) && z->buf == buffer)) { + long len = RSTRING_LEN(buffer); + if (len >= ZSTREAM_AVAIL_OUT_STEP_MAX) { + rb_str_modify(buffer); + } + else { + len = ZSTREAM_AVAIL_OUT_STEP_MAX - len; + rb_str_modify_expand(buffer, len); + } + rb_str_set_len(buffer, 0); + z->flags |= ZSTREAM_REUSE_BUFFER; + z->buf = buffer; + } + } else if (ZSTREAM_REUSE_BUFFER_P(z)) { + z->flags &= ~ZSTREAM_REUSE_BUFFER; + z->buf = Qnil; + } + rb_scan_args(argc, argv, "10", &src); if (ZSTREAM_IS_FINISHED(z)) { if (NIL_P(src)) { @@ -2046,7 +2169,11 @@ rb_inflate_inflate(VALUE obj, VALUE src) else { StringValue(src); zstream_append_buffer2(z, src); - dst = rb_str_new(0, 0); + if (ZSTREAM_REUSE_BUFFER_P(z)) { + dst = rb_str_resize(buffer, 0); + } else { + dst = rb_str_new(0, 0); + } } } else { @@ -2198,7 +2325,7 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic) #define OS_CODE OS_UNIX #endif -static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input; +static ID id_write, id_readpartial, id_flush, id_seek, id_close, id_path, id_input; static VALUE cGzError, cNoFooter, cCRCError, cLengthError; @@ -2798,8 +2925,6 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) if (!NIL_P(outbuf)) { rb_str_resize(outbuf, RSTRING_LEN(dst)); memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst)); - rb_str_resize(dst, 0); - rb_gc_force_recycle(dst); dst = outbuf; } return dst; @@ -3445,6 +3570,16 @@ rb_gzfile_path(VALUE obj) return gz->path; } +static VALUE +gzfile_initialize_path_partial(VALUE obj) +{ + struct gzfile* gz; + TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz); + gz->path = rb_funcall(gz->io, id_path, 0); + rb_define_singleton_method(obj, "path", rb_gzfile_path, 0); + return Qnil; +} + static void rb_gzfile_ecopts(struct gzfile *gz, VALUE opts) { @@ -3553,8 +3688,8 @@ rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj) rb_gzfile_ecopts(gz, opt); if (rb_respond_to(io, id_path)) { - gz->path = rb_funcall(gz->io, id_path, 0); - rb_define_singleton_method(obj, "path", rb_gzfile_path, 0); + /* File#path may raise IOError in case when a path is unavailable */ + rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0); } return obj; @@ -3723,6 +3858,60 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass) return gzfile_s_open(argc, argv, klass, "rb"); } +/* + * Document-method: Zlib::GzipReader.zcat + * + * call-seq: + * Zlib::GzipReader.zcat(io, options = {}, &block) => nil + * Zlib::GzipReader.zcat(io, options = {}) => string + * + * Decompresses all gzip data in the +io+, handling multiple gzip + * streams until the end of the +io+. There should not be any non-gzip + * data after the gzip streams. + * + * If a block is given, it is yielded strings of uncompressed data, + * and the method returns +nil+. + * If a block is not given, the method returns the concatenation of + * all uncompressed data in all gzip streams. + */ +static VALUE +rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass) +{ + VALUE io, unused, obj, buf=0, tmpbuf; + long pos; + + rb_check_arity(argc, 1, 2); + io = argv[0]; + + do { + obj = rb_funcallv(klass, rb_intern("new"), argc, argv); + if (rb_block_given_p()) { + rb_gzreader_each(0, 0, obj); + } + else { + if (!buf) { + buf = rb_str_new(0, 0); + } + tmpbuf = gzfile_read_all(get_gzfile(obj)); + rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf)); + } + + rb_gzreader_read(0, 0, obj); + pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0)); + unused = rb_gzreader_unused(obj); + rb_gzfile_finish(obj); + if (!NIL_P(unused)) { + pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0)); + rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos)); + } + } while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0))); + + if (rb_block_given_p()) { + return Qnil; + } + return buf; +} + /* * Document-method: Zlib::GzipReader.new * @@ -3761,8 +3950,8 @@ rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj) rb_gzfile_ecopts(gz, opt); if (rb_respond_to(io, id_path)) { - gz->path = rb_funcall(gz->io, id_path, 0); - rb_define_singleton_method(obj, "path", rb_gzfile_path, 0); + /* File#path may raise IOError in case when a path is unavailable */ + rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0); } return obj; @@ -3949,20 +4138,6 @@ rb_gzreader_each_byte(VALUE obj) return Qnil; } -/* - * Document-method: Zlib::GzipReader#bytes - * - * This is a deprecated alias for each_byte. - */ -static VALUE -rb_gzreader_bytes(VALUE obj) -{ - rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0); - return rb_gzreader_each_byte(obj); -} - /* * Document-method: Zlib::GzipReader#ungetc * @@ -4041,17 +4216,17 @@ gzreader_charboundary(struct gzfile *gz, long n) { char *s = RSTRING_PTR(gz->z.buf); char *e = s + ZSTREAM_BUF_FILLED(&gz->z); - char *p = rb_enc_left_char_head(s, s + n, e, gz->enc); + char *p = rb_enc_left_char_head(s, s + n - 1, e, gz->enc); long l = p - s; if (l < n) { - n = rb_enc_precise_mbclen(p, e, gz->enc); - if (MBCLEN_NEEDMORE_P(n)) { - if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) { + int n_bytes = rb_enc_precise_mbclen(p, e, gz->enc); + if (MBCLEN_NEEDMORE_P(n_bytes)) { + if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes))) > 0) { return l; } } - else if (MBCLEN_CHARFOUND_P(n)) { - return l + MBCLEN_CHARFOUND_LEN(n); + else if (MBCLEN_CHARFOUND_P(n_bytes)) { + return l + MBCLEN_CHARFOUND_LEN(n_bytes); } } return n; @@ -4189,6 +4364,8 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) * Document-method: Zlib::GzipReader#gets * * See Zlib::GzipReader documentation for a description. + * However, note that this method can return +nil+ even if + * #eof? returns false, unlike the behavior of File#gets. */ static VALUE rb_gzreader_gets(int argc, VALUE *argv, VALUE obj) @@ -4235,20 +4412,6 @@ rb_gzreader_each(int argc, VALUE *argv, VALUE obj) return obj; } -/* - * Document-method: Zlib::GzipReader#lines - * - * This is a deprecated alias for each_line. - */ -static VALUE -rb_gzreader_lines(int argc, VALUE *argv, VALUE obj) -{ - rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead"); - if (!rb_block_given_p()) - return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv); - return rb_gzreader_each(argc, argv, obj); -} - /* * Document-method: Zlib::GzipReader#readlines * @@ -4299,8 +4462,6 @@ zlib_gzip_end(struct gzfile *gz) zstream_end(&gz->z); } -#define OPTHASH_GIVEN_P(opts) \ - (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1)) static ID id_level, id_strategy; static VALUE zlib_gzip_run(VALUE arg); @@ -4453,6 +4614,10 @@ zlib_gunzip_run(VALUE arg) void Init_zlib(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + #undef rb_intern VALUE mZlib, cZStream, cDeflate, cInflate; #if GZIP_SUPPORT @@ -4471,6 +4636,7 @@ Init_zlib(void) cMemError = rb_define_class_under(mZlib, "MemError", cZError); cBufError = rb_define_class_under(mZlib, "BufError", cZError); cVersionError = rb_define_class_under(mZlib, "VersionError", cZError); + cInProgressError = rb_define_class_under(mZlib, "InProgressError", cZError); rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0); rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1); @@ -4547,7 +4713,7 @@ Init_zlib(void) rb_define_alloc_func(cInflate, rb_inflate_s_allocate); rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1); rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1); - rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1); + rb_define_method(cInflate, "inflate", rb_inflate_inflate, -1); rb_define_method(cInflate, "<<", rb_inflate_addstr, 1); rb_define_method(cInflate, "sync", rb_inflate_sync, 1); rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0); @@ -4696,6 +4862,7 @@ Init_zlib(void) rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1); rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1); + rb_define_singleton_method(cGzipReader, "zcat", rb_gzreader_s_zcat, -1); rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate); rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1); rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0); @@ -4708,14 +4875,12 @@ Init_zlib(void) rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0); rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0); rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0); - rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0); rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1); rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1); rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1); rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1); rb_define_method(cGzipReader, "each", rb_gzreader_each, -1); rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1); - rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1); rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1); rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0); @@ -4757,6 +4922,7 @@ Init_zlib(void) id_level = rb_intern("level"); id_strategy = rb_intern("strategy"); + id_buffer = rb_intern("buffer"); #endif /* GZIP_SUPPORT */ } @@ -4778,6 +4944,7 @@ Init_zlib(void) * - Zlib::MemError * - Zlib::BufError * - Zlib::VersionError + * - Zlib::InProgressError * */ @@ -4852,6 +5019,20 @@ Init_zlib(void) * */ +/* + * Document-class: Zlib::InProgressError + * + * Subclass of Zlib::Error. This error is raised when the zlib + * stream is currently in progress. + * + * For example: + * + * inflater = Zlib::Inflate.new + * inflater.inflate(compressed) do + * inflater.inflate(compressed) # Raises Zlib::InProgressError + * end + */ + /* * Document-class: Zlib::GzipFile::Error * diff --git a/ruby/ext/zlib/zlib.gemspec b/ruby/ext/zlib/zlib.gemspec index 4a77ae325..4a5f8f2ee 100644 --- a/ruby/ext/zlib/zlib.gemspec +++ b/ruby/ext/zlib/zlib.gemspec @@ -20,16 +20,12 @@ Gem::Specification.new do |spec| spec.summary = %q{Ruby interface for the zlib compression/decompression library} spec.description = %q{Ruby interface for the zlib compression/decompression library} spec.homepage = "https://github.com/ruby/zlib" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"] + spec.files = ["LICENSE.txt", "README.md", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"] spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.executables = [] spec.require_paths = ["lib"] spec.extensions = "ext/zlib/extconf.rb" spec.required_ruby_version = ">= 2.3.0" - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "rake-compiler" end diff --git a/ruby/file.c b/ruby/file.c index 94a22ac72..2d0f32340 100644 --- a/ruby/file.c +++ b/ruby/file.c @@ -11,14 +11,22 @@ **********************************************************************/ +#include "ruby/internal/config.h" + #ifdef _WIN32 -#include "missing/file.h" +# include "missing/file.h" +# include "ruby.h" #endif + +#include +#include + #ifdef __CYGWIN__ -#include -#include -#include +# include +# include +# include #endif + #ifdef __APPLE__ # if !(defined(__has_feature) && defined(__has_attribute)) /* Maybe a bug in SDK of Xcode 10.2.1 */ @@ -28,21 +36,13 @@ # define API_AVAILABLE(...) # define API_DEPRECATED(...) # endif -#include +# include #endif -#include "id.h" -#include "ruby/encoding.h" -#include "ruby/io.h" -#include "ruby/util.h" -#include "ruby/thread.h" -#include "internal.h" -#include "dln.h" -#include "encindex.h" - #ifdef HAVE_UNISTD_H -#include +# include #endif + #ifdef HAVE_SYS_TIME_H # include #endif @@ -60,81 +60,73 @@ int flock(int, int); # define MAXPATHLEN 1024 #endif -#include - -#include - #ifdef HAVE_UTIME_H -#include +# include #elif defined HAVE_SYS_UTIME_H -#include +# include #endif #ifdef HAVE_PWD_H -#include +# include #endif #ifdef HAVE_SYS_SYSMACROS_H -#include +# include #endif #include #include #ifdef HAVE_SYS_MKDEV_H -#include +# include #endif #if defined(HAVE_FCNTL_H) -#include +# include #endif #if defined(HAVE_SYS_TIME_H) -#include +# include #endif #if !defined HAVE_LSTAT && !defined lstat -#define lstat stat +# define lstat stat #endif -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - /* define system APIs */ #ifdef _WIN32 -#include "win32/file.h" -#define STAT(p, s) rb_w32_ustati128((p), (s)) -#undef lstat -#define lstat(p, s) rb_w32_ulstati128((p), (s)) -#undef access -#define access(p, m) rb_w32_uaccess((p), (m)) -#undef truncate -#define truncate(p, n) rb_w32_utruncate((p), (n)) -#undef chmod -#define chmod(p, m) rb_w32_uchmod((p), (m)) -#undef chown -#define chown(p, o, g) rb_w32_uchown((p), (o), (g)) -#undef lchown -#define lchown(p, o, g) rb_w32_ulchown((p), (o), (g)) -#undef utimensat -#define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f)) -#undef link -#define link(f, t) rb_w32_ulink((f), (t)) -#undef unlink -#define unlink(p) rb_w32_uunlink(p) -#undef rename -#define rename(f, t) rb_w32_urename((f), (t)) -#undef symlink -#define symlink(s, l) rb_w32_usymlink((s), (l)) - -#ifdef HAVE_REALPATH +# include "win32/file.h" +# define STAT(p, s) rb_w32_ustati128((p), (s)) +# undef lstat +# define lstat(p, s) rb_w32_ulstati128((p), (s)) +# undef access +# define access(p, m) rb_w32_uaccess((p), (m)) +# undef truncate +# define truncate(p, n) rb_w32_utruncate((p), (n)) +# undef chmod +# define chmod(p, m) rb_w32_uchmod((p), (m)) +# undef chown +# define chown(p, o, g) rb_w32_uchown((p), (o), (g)) +# undef lchown +# define lchown(p, o, g) rb_w32_ulchown((p), (o), (g)) +# undef utimensat +# define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f)) +# undef link +# define link(f, t) rb_w32_ulink((f), (t)) +# undef unlink +# define unlink(p) rb_w32_uunlink(p) +# undef rename +# define rename(f, t) rb_w32_urename((f), (t)) +# undef symlink +# define symlink(s, l) rb_w32_usymlink((s), (l)) + +# ifdef HAVE_REALPATH /* Don't use native realpath(3) on Windows, as the check for absolute paths does not work for drive letters. */ -#undef HAVE_REALPATH -#endif +# undef HAVE_REALPATH +# endif #else -#define STAT(p, s) stat((p), (s)) +# define STAT(p, s) stat((p), (s)) #endif #if defined _WIN32 || defined __APPLE__ @@ -147,7 +139,7 @@ int flock(int, int); /* utime may fail if time is out-of-range for the FS [ruby-dev:38277] */ #if defined DOSISH || defined __CYGWIN__ -# define UTIME_EINVAL +# define UTIME_EINVAL #endif /* Solaris 10 realpath(3) doesn't support File.realpath */ @@ -156,10 +148,29 @@ int flock(int, int); #endif #ifdef HAVE_REALPATH -#include -#include +# include +# include #endif +#include "dln.h" +#include "encindex.h" +#include "id.h" +#include "internal.h" +#include "internal/compilers.h" +#include "internal/dir.h" +#include "internal/error.h" +#include "internal/file.h" +#include "internal/io.h" +#include "internal/load.h" +#include "internal/object.h" +#include "internal/process.h" +#include "internal/thread.h" +#include "internal/vm.h" +#include "ruby/encoding.h" +#include "ruby/io.h" +#include "ruby/thread.h" +#include "ruby/util.h" + VALUE rb_cFile; VALUE rb_mFileTest; VALUE rb_cStat; @@ -566,7 +577,13 @@ rb_stat_cmp(VALUE self, VALUE other) static VALUE rb_stat_dev(VALUE self) { +#if SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_DEV_T return DEVT2NUM(get_stat(self)->st_dev); +#elif SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_LONG + return ULONG2NUM(get_stat(self)->st_dev); +#else + return ULL2NUM(get_stat(self)->st_dev); +#endif } /* @@ -671,7 +688,21 @@ rb_stat_mode(VALUE self) static VALUE rb_stat_nlink(VALUE self) { - return UINT2NUM(get_stat(self)->st_nlink); + /* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */ + const struct stat *ptr = get_stat(self); + + if (sizeof(ptr->st_nlink) <= sizeof(int)) { + return UINT2NUM((unsigned)ptr->st_nlink); + } + else if (sizeof(ptr->st_nlink) == sizeof(long)) { + return ULONG2NUM((unsigned long)ptr->st_nlink); + } + else if (sizeof(ptr->st_nlink) == sizeof(LONG_LONG)) { + return ULL2NUM((unsigned LONG_LONG)ptr->st_nlink); + } + else { + rb_bug(":FIXME: don't know what to do"); + } } /* @@ -722,7 +753,13 @@ static VALUE rb_stat_rdev(VALUE self) { #ifdef HAVE_STRUCT_STAT_ST_RDEV +# if SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_DEV_T return DEVT2NUM(get_stat(self)->st_rdev); +# elif SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_LONG + return ULONG2NUM(get_stat(self)->st_rdev); +# else + return ULL2NUM(get_stat(self)->st_rdev); +# endif #else return Qnil; #endif @@ -849,12 +886,17 @@ stat_atimespec(const struct stat *st) } static VALUE -stat_atime(const struct stat *st) +stat_time(const struct timespec ts) { - struct timespec ts = stat_atimespec(st); return rb_time_nano_new(ts.tv_sec, ts.tv_nsec); } +static VALUE +stat_atime(const struct stat *st) +{ + return stat_time(stat_atimespec(st)); +} + static struct timespec stat_mtimespec(const struct stat *st) { @@ -875,8 +917,7 @@ stat_mtimespec(const struct stat *st) static VALUE stat_mtime(const struct stat *st) { - struct timespec ts = stat_mtimespec(st); - return rb_time_nano_new(ts.tv_sec, ts.tv_nsec); + return stat_time(stat_mtimespec(st)); } static struct timespec @@ -899,8 +940,7 @@ stat_ctimespec(const struct stat *st) static VALUE stat_ctime(const struct stat *st) { - struct timespec ts = stat_ctimespec(st); - return rb_time_nano_new(ts.tv_sec, ts.tv_nsec); + return stat_time(stat_ctimespec(st)); } #define HAVE_STAT_BIRTHTIME @@ -1228,7 +1268,7 @@ statx_birthtime(const struct statx *stx, VALUE fname) /* birthtime is not supported on the filesystem */ statx_notimplement("birthtime"); } - return rb_time_nano_new(stx->stx_btime.tv_sec, stx->stx_btime.tv_nsec); + return rb_time_nano_new((time_t)stx->stx_btime.tv_sec, stx->stx_btime.tv_nsec); } typedef struct statx statx_data; @@ -1411,7 +1451,7 @@ rb_group_member(GETGROUPS_T gid) return FALSE; #else int rv = FALSE; - int groups = 16; + int groups; VALUE v = 0; GETGROUPS_T *gary; int anum = -1; @@ -1419,25 +1459,9 @@ rb_group_member(GETGROUPS_T gid) if (getgid() == gid || getegid() == gid) return TRUE; - /* - * On Mac OS X (Mountain Lion), NGROUPS is 16. But libc and kernel - * accept more larger value. - * So we don't trunk NGROUPS anymore. - */ - while (groups <= RB_MAX_GROUPS) { - gary = ALLOCV_N(GETGROUPS_T, v, groups); - anum = getgroups(groups, gary); - if (anum != -1 && anum != groups) - break; - groups *= 2; - if (v) { - ALLOCV_END(v); - v = 0; - } - } - if (anum == -1) - return FALSE; - + groups = getgroups(0, NULL); + gary = ALLOCV_N(GETGROUPS_T, v, groups); + anum = getgroups(groups, gary); while (--anum >= 0) { if (gary[anum] == gid) { rv = TRUE; @@ -1762,25 +1786,20 @@ rb_file_exist_p(VALUE obj, VALUE fname) return Qtrue; } -/* - * call-seq: - * File.exists?(file_name) -> true or false - * - * Deprecated method. Don't use. - */ +/* :nodoc: */ static VALUE rb_file_exists_p(VALUE obj, VALUE fname) { - const char *s = "FileTest#"; + const char *s = "FileTest#exist?"; if (obj == rb_mFileTest) { - s = "FileTest."; + s = "FileTest.exist?"; } else if (obj == rb_cFile || (RB_TYPE_P(obj, T_CLASS) && RTEST(rb_class_inherited_p(obj, rb_cFile)))) { - s = "File."; + s = "File.exist?"; } - rb_warning("%sexists? is a deprecated name, use %sexist? instead", s, s); + rb_warn_deprecated("%.*ss?", s, (int)(strlen(s)-1), s); return rb_file_exist_p(obj, fname); } @@ -1798,8 +1817,7 @@ rb_file_exists_p(VALUE obj, VALUE fname) static VALUE rb_file_readable_p(VALUE obj, VALUE fname) { - if (rb_eaccess(fname, R_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_eaccess(fname, R_OK) >= 0); } /* @@ -1816,8 +1834,7 @@ rb_file_readable_p(VALUE obj, VALUE fname) static VALUE rb_file_readable_real_p(VALUE obj, VALUE fname) { - if (rb_access(fname, R_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_access(fname, R_OK) >= 0); } #ifndef S_IRUGO @@ -1872,8 +1889,7 @@ rb_file_world_readable_p(VALUE obj, VALUE fname) static VALUE rb_file_writable_p(VALUE obj, VALUE fname) { - if (rb_eaccess(fname, W_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_eaccess(fname, W_OK) >= 0); } /* @@ -1890,8 +1906,7 @@ rb_file_writable_p(VALUE obj, VALUE fname) static VALUE rb_file_writable_real_p(VALUE obj, VALUE fname) { - if (rb_access(fname, W_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_access(fname, W_OK) >= 0); } /* @@ -1942,8 +1957,7 @@ rb_file_world_writable_p(VALUE obj, VALUE fname) static VALUE rb_file_executable_p(VALUE obj, VALUE fname) { - if (rb_eaccess(fname, X_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_eaccess(fname, X_OK) >= 0); } /* @@ -1964,8 +1978,7 @@ rb_file_executable_p(VALUE obj, VALUE fname) static VALUE rb_file_executable_real_p(VALUE obj, VALUE fname) { - if (rb_access(fname, X_OK) < 0) return Qfalse; - return Qtrue; + return RBOOL(rb_access(fname, X_OK) >= 0); } #ifndef S_ISREG @@ -1990,8 +2003,7 @@ rb_file_file_p(VALUE obj, VALUE fname) struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (S_ISREG(st.st_mode)) return Qtrue; - return Qfalse; + return RBOOL(S_ISREG(st.st_mode)); } /* @@ -2010,8 +2022,7 @@ rb_file_zero_p(VALUE obj, VALUE fname) struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (st.st_size == 0) return Qtrue; - return Qfalse; + return RBOOL(st.st_size == 0); } /* @@ -2051,8 +2062,7 @@ rb_file_owned_p(VALUE obj, VALUE fname) struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (st.st_uid == geteuid()) return Qtrue; - return Qfalse; + return RBOOL(st.st_uid == geteuid()); } static VALUE @@ -2061,8 +2071,7 @@ rb_file_rowned_p(VALUE obj, VALUE fname) struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (st.st_uid == getuid()) return Qtrue; - return Qfalse; + return RBOOL(st.st_uid == getuid()); } /* @@ -2095,8 +2104,7 @@ check3rdbyte(VALUE fname, int mode) struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (st.st_mode & mode) return Qtrue; - return Qfalse; + return RBOOL(st.st_mode & mode); } #endif @@ -2507,20 +2515,33 @@ rb_file_birthtime(VALUE obj) * */ -static VALUE -rb_file_size(VALUE obj) +off_t +rb_file_size(VALUE file) { - rb_io_t *fptr; - struct stat st; + if (RB_TYPE_P(file, T_FILE)) { + rb_io_t *fptr; + struct stat st; - GetOpenFile(obj, fptr); - if (fptr->mode & FMODE_WRITABLE) { - rb_io_flush_raw(obj, 0); + RB_IO_POINTER(file, fptr); + if (fptr->mode & FMODE_WRITABLE) { + rb_io_flush_raw(file, 0); + } + + if (fstat(fptr->fd, &st) == -1) { + rb_sys_fail_path(fptr->pathv); + } + + return st.st_size; } - if (fstat(fptr->fd, &st) == -1) { - rb_sys_fail_path(fptr->pathv); + else { + return NUM2OFFT(rb_funcall(file, idSize, 0)); } - return OFFT2NUM(st.st_size); +} + +static VALUE +file_size(VALUE self) +{ + return OFFT2NUM(rb_file_size(self)); } static int @@ -3331,7 +3352,6 @@ getcwdofdrv(int drv) } return drvcwd; } -#endif static inline int not_same_drive(VALUE path, int drive) @@ -3346,6 +3366,7 @@ not_same_drive(VALUE path, int drive) } } #endif +#endif static inline char * skiproot(const char *path, const char *end, rb_encoding *enc) @@ -3447,6 +3468,20 @@ rb_enc_path_end(const char *path, const char *end, rb_encoding *enc) return chompdirsep(path, end, enc); } +static rb_encoding * +fs_enc_check(VALUE path1, VALUE path2) +{ + rb_encoding *enc = rb_enc_check(path1, path2); + int encidx = rb_enc_to_index(enc); + if (encidx == ENCINDEX_US_ASCII) { + encidx = rb_enc_get_index(path1); + if (encidx == ENCINDEX_US_ASCII) + encidx = rb_enc_get_index(path2); + enc = rb_enc_from_index(encidx); + } + return enc; +} + #if USE_NTFS static char * ntfs_tail(const char *path, const char *end, rb_encoding *enc) @@ -3583,21 +3618,42 @@ rb_default_home_dir(VALUE result) #if defined HAVE_PWD_H if (!dir) { - const char *login = getlogin(); - if (login) { - struct passwd *pw = getpwnam(login); - if (pw) { - copy_home_path(result, pw->pw_dir); - endpwent(); - return result; - } - endpwent(); - rb_raise(rb_eArgError, "couldn't find HOME for login `%s' -- expanding `~'", - login); - } - else { - rb_raise(rb_eArgError, "couldn't find login name -- expanding `~'"); - } + /* We'll look up the user's default home dir in the password db by + * login name, if possible, and failing that will fall back to looking + * the information up by uid (as would be needed for processes that + * are not a descendant of login(1) or a work-alike). + * + * While the lookup by uid is more likely to succeed (since we always + * have a uid, but may or may not have a login name), we prefer first + * looking up by name to accommodate the possibility of multiple login + * names (each with its own record in the password database, so each + * with a potentially different home directory) being mapped to the + * same uid (as explicitly allowed for by POSIX; see getlogin(3posix)). + */ + VALUE login_name = rb_getlogin(); + +# if !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID) + /* This is a corner case, but for backward compatibility reasons we + * want to emit this error if neither the lookup by login name nor + * lookup by getuid() has a chance of succeeding. + */ + if (NIL_P(login_name)) { + rb_raise(rb_eArgError, "couldn't find login name -- expanding `~'"); + } +# endif + + VALUE pw_dir = rb_getpwdirnam_for_login(login_name); + if (NIL_P(pw_dir)) { + pw_dir = rb_getpwdiruid(); + if (NIL_P(pw_dir)) { + rb_raise(rb_eArgError, "couldn't find home for uid `%ld'", (long)getuid()); + } + } + + /* found it */ + copy_home_path(result, RSTRING_PTR(pw_dir)); + rb_str_resize(pw_dir, 0); + return result; } #endif if (!dir) { @@ -3626,7 +3682,7 @@ append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encodi size_t dirlen = strlen(dir), buflen = rb_str_capacity(result); if (NORMALIZE_UTF8PATH || *enc != fsenc) { - rb_encoding *direnc = rb_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc)); + rb_encoding *direnc = fs_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc)); if (direnc != fsenc) { dirname = rb_str_conv_enc(dirname, fsenc, direnc); RSTRING_GETMEM(dirname, cwdp, dirlen); @@ -3722,7 +3778,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na p = e; } else { - rb_enc_associate(result, enc = rb_enc_check(result, fname)); + rb_enc_associate(result, enc = fs_enc_check(result, fname)); p = pend; } p = chompdirsep(skiproot(buf, p, enc), p, enc); @@ -3733,7 +3789,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na else if (!rb_is_absolute_path(s)) { if (!NIL_P(dname)) { rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result); - rb_enc_associate(result, rb_enc_check(result, fname)); + rb_enc_associate(result, fs_enc_check(result, fname)); BUFINIT(); p = pend; } @@ -3761,7 +3817,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na BUFCHECK(bdiff >= buflen); memset(buf, '/', len); rb_str_set_len(result, len); - rb_enc_associate(result, rb_enc_check(result, fname)); + rb_enc_associate(result, fs_enc_check(result, fname)); } if (p > buf && p[-1] == '/') --p; @@ -4222,7 +4278,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE f rb_encoding *tmpenc, *linkenc = rb_enc_get(link); link_orig = link; link = rb_str_subseq(link, 0, link_prefixlen); - tmpenc = rb_enc_check(*resolvedp, link); + tmpenc = fs_enc_check(*resolvedp, link); if (tmpenc != linkenc) link = rb_str_conv_enc(link, linkenc, tmpenc); *resolvedp = link; *prefixlenp = link_prefixlen; @@ -4341,6 +4397,21 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum static VALUE rb_file_join(VALUE ary); +#ifndef HAVE_REALPATH +static VALUE +rb_check_realpath_emulate_try(VALUE arg) +{ + VALUE *args = (VALUE *)arg; + return rb_check_realpath_emulate(args[0], args[1], (rb_encoding *)args[2], RB_REALPATH_CHECK); +} + +static VALUE +rb_check_realpath_emulate_rescue(VALUE arg, VALUE exc) +{ + return Qnil; +} +#endif /* HAVE_REALPATH */ + static VALUE rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode) { @@ -4348,7 +4419,6 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum VALUE unresolved_path; char *resolved_ptr = NULL; VALUE resolved; - struct stat st; if (mode == RB_REALPATH_DIR) { return rb_check_realpath_emulate(basedir, path, origenc, mode); @@ -4379,14 +4449,17 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding()); free(resolved_ptr); +# if !defined(__LINUX__) && !defined(__APPLE__) /* As `resolved` is a String in the filesystem encoding, no * conversion is needed */ + struct stat st; if (stat_without_gvl(RSTRING_PTR(resolved), &st) < 0) { if (mode == RB_REALPATH_CHECK) { return Qnil; } rb_sys_fail_path(unresolved_path); } +# endif if (origenc && origenc != rb_enc_get(resolved)) { if (!rb_enc_str_asciionly_p(resolved)) { @@ -4405,7 +4478,18 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum RB_GC_GUARD(unresolved_path); return resolved; #else - return rb_check_realpath_emulate(basedir, path, origenc, mode); + if (mode == RB_REALPATH_CHECK) { + VALUE arg[3]; + arg[0] = basedir; + arg[1] = path; + arg[2] = (VALUE)origenc; + + return rb_rescue(rb_check_realpath_emulate_try, (VALUE)arg, + rb_check_realpath_emulate_rescue, Qnil); + } + else { + return rb_check_realpath_emulate(basedir, path, origenc, mode); + } #endif /* HAVE_REALPATH */ } @@ -4626,9 +4710,11 @@ rb_file_s_basename(int argc, VALUE *argv, VALUE _) return basename; } +static VALUE rb_file_dirname_n(VALUE fname, int n); + /* * call-seq: - * File.dirname(file_name) -> dir_name + * File.dirname(file_name, level = 1) -> dir_name * * Returns all components of the filename given in file_name * except the last one (after first stripping trailing separators). @@ -4637,21 +4723,40 @@ rb_file_s_basename(int argc, VALUE *argv, VALUE _) * not nil. * * File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work" + * + * If +level+ is given, removes the last +level+ components, not only + * one. + * + * File.dirname("/home/gumby/work/ruby.rb", 2) #=> "/home/gumby" + * File.dirname("/home/gumby/work/ruby.rb", 4) #=> "/" */ static VALUE -rb_file_s_dirname(VALUE klass, VALUE fname) +rb_file_s_dirname(int argc, VALUE *argv, VALUE klass) { - return rb_file_dirname(fname); + int n = 1; + if ((argc = rb_check_arity(argc, 1, 2)) > 1) { + n = NUM2INT(argv[1]); + } + return rb_file_dirname_n(argv[0], n); } VALUE rb_file_dirname(VALUE fname) +{ + return rb_file_dirname_n(fname, 1); +} + +static VALUE +rb_file_dirname_n(VALUE fname, int n) { const char *name, *root, *p, *end; VALUE dirname; rb_encoding *enc; + VALUE sepsv = 0; + const char **seps; + if (n < 0) rb_raise(rb_eArgError, "negative level: %d", n); FilePathStringValue(fname); name = StringValueCStr(fname); end = name + RSTRING_LEN(fname); @@ -4664,10 +4769,39 @@ rb_file_dirname(VALUE fname) if (root > name + 1) name = root - 1; #endif - p = strrdirsep(root, end, enc); - if (!p) { + if (n > (end - root + 1) / 2) { p = root; } + else { + int i; + switch (n) { + case 0: + p = end; + break; + case 1: + if (!(p = strrdirsep(root, end, enc))) p = root; + break; + default: + seps = ALLOCV_N(const char *, sepsv, n); + for (i = 0; i < n; ++i) seps[i] = root; + i = 0; + for (p = root; p < end; ) { + if (isdirsep(*p)) { + const char *tmp = p++; + while (p < end && isdirsep(*p)) p++; + if (p >= end) break; + seps[i++] = tmp; + if (i == n) i = 0; + } + else { + Inc(p, end, enc); + } + } + p = seps[i]; + ALLOCV_END(sepsv); + break; + } + } if (p == name) return rb_usascii_str_new2("."); #ifdef DOSISH_DRIVE_LETTER @@ -4894,7 +5028,7 @@ rb_file_join(VALUE ary) rb_str_cat(result, "/", 1); } } - enc = rb_enc_check(result, tmp); + enc = fs_enc_check(result, tmp); rb_str_buf_append(result, tmp); rb_enc_associate(result, enc); } @@ -5258,14 +5392,7 @@ rb_f_test(int argc, VALUE *argv, VALUE _) if (argc == 0) rb_check_arity(argc, 2, 3); cmd = NUM2CHR(argv[0]); if (cmd == 0) { - unknown: - /* unknown command */ - if (ISPRINT(cmd)) { - rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd); - } - else { - rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd); - } + goto unknown; } if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) { CHECK(1); @@ -5391,7 +5518,15 @@ rb_f_test(int argc, VALUE *argv, VALUE _) return Qfalse; } } - goto unknown; + unknown: + /* unknown command */ + if (ISPRINT(cmd)) { + rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd); + } + else { + rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd); + } + UNREACHABLE_RETURN(Qundef); } @@ -5677,11 +5812,11 @@ rb_stat_r(VALUE obj) #endif #ifdef S_IRUSR if (rb_stat_owned(obj)) - return st->st_mode & S_IRUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IRUSR); #endif #ifdef S_IRGRP if (rb_stat_grpowned(obj)) - return st->st_mode & S_IRGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IRGRP); #endif #ifdef S_IROTH if (!(st->st_mode & S_IROTH)) return Qfalse; @@ -5710,11 +5845,11 @@ rb_stat_R(VALUE obj) #endif #ifdef S_IRUSR if (rb_stat_rowned(obj)) - return st->st_mode & S_IRUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IRUSR); #endif #ifdef S_IRGRP if (rb_group_member(get_stat(obj)->st_gid)) - return st->st_mode & S_IRGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IRGRP); #endif #ifdef S_IROTH if (!(st->st_mode & S_IROTH)) return Qfalse; @@ -5770,11 +5905,11 @@ rb_stat_w(VALUE obj) #endif #ifdef S_IWUSR if (rb_stat_owned(obj)) - return st->st_mode & S_IWUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IWUSR); #endif #ifdef S_IWGRP if (rb_stat_grpowned(obj)) - return st->st_mode & S_IWGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IWGRP); #endif #ifdef S_IWOTH if (!(st->st_mode & S_IWOTH)) return Qfalse; @@ -5803,11 +5938,11 @@ rb_stat_W(VALUE obj) #endif #ifdef S_IWUSR if (rb_stat_rowned(obj)) - return st->st_mode & S_IWUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IWUSR); #endif #ifdef S_IWGRP if (rb_group_member(get_stat(obj)->st_gid)) - return st->st_mode & S_IWGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IWGRP); #endif #ifdef S_IWOTH if (!(st->st_mode & S_IWOTH)) return Qfalse; @@ -5862,16 +5997,16 @@ rb_stat_x(VALUE obj) #ifdef USE_GETEUID if (geteuid() == 0) { - return st->st_mode & S_IXUGO ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXUGO); } #endif #ifdef S_IXUSR if (rb_stat_owned(obj)) - return st->st_mode & S_IXUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXUSR); #endif #ifdef S_IXGRP if (rb_stat_grpowned(obj)) - return st->st_mode & S_IXGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXGRP); #endif #ifdef S_IXOTH if (!(st->st_mode & S_IXOTH)) return Qfalse; @@ -5894,16 +6029,16 @@ rb_stat_X(VALUE obj) #ifdef USE_GETEUID if (getuid() == 0) { - return st->st_mode & S_IXUGO ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXUGO); } #endif #ifdef S_IXUSR if (rb_stat_rowned(obj)) - return st->st_mode & S_IXUSR ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXUSR); #endif #ifdef S_IXGRP if (rb_group_member(get_stat(obj)->st_gid)) - return st->st_mode & S_IXGRP ? Qtrue : Qfalse; + return RBOOL(st->st_mode & S_IXGRP); #endif #ifdef S_IXOTH if (!(st->st_mode & S_IXOTH)) return Qfalse; @@ -5949,11 +6084,13 @@ rb_stat_z(VALUE obj) /* * call-seq: - * state.size -> integer + * stat.size? -> Integer or nil * - * Returns the size of stat in bytes. + * Returns +nil+ if stat is a zero-length file, the size of + * the file otherwise. * - * File.stat("testfile").size #=> 66 + * File.stat("testfile").size? #=> 66 + * File.stat("/dev/null").size? #=> nil * */ @@ -6114,7 +6251,7 @@ rb_is_absolute_path(const char *path) #if ENABLE_PATH_CHECK static int -path_check_0(VALUE path, int execpath) +path_check_0(VALUE path) { struct stat st; const char *p0 = StringValueCStr(path); @@ -6142,12 +6279,16 @@ path_check_0(VALUE path, int execpath) #endif if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH) #ifdef S_ISVTX - && !(p && execpath && (st.st_mode & S_ISVTX)) + && !(p && (st.st_mode & S_ISVTX)) #endif && !access(p0, W_OK)) { - rb_enc_warn(enc, "Insecure world writable dir %s in %sPATH, mode 0%" + rb_enc_warn(enc, "Insecure world writable dir %s in PATH, mode 0%" +#if SIZEOF_DEV_T > SIZEOF_INT PRI_MODET_PREFIX"o", - p0, (execpath ? "" : "LOAD_"), st.st_mode); +#else + "o", +#endif + p0, st.st_mode); if (p) *p = '/'; RB_GC_GUARD(path); return 0; @@ -6162,12 +6303,6 @@ path_check_0(VALUE path, int execpath) } #endif -#if ENABLE_PATH_CHECK -#define fpath_check(path) path_check_0((path), FALSE) -#else -#define fpath_check(path) 1 -#endif - int rb_path_check(const char *path) { @@ -6183,7 +6318,7 @@ rb_path_check(const char *path) if (!p) p = pend; for (;;) { - if (!path_check_0(rb_str_new(p0, p - p0), TRUE)) { + if (!path_check_0(rb_str_new(p0, p - p0))) { return 0; /* not safe */ } p0 = p + 1; @@ -6257,19 +6392,16 @@ is_explicit_relative(const char *path) static VALUE copy_path_class(VALUE path, VALUE orig) { + int encidx = rb_enc_get_index(orig); + if (encidx == ENCINDEX_ASCII || encidx == ENCINDEX_US_ASCII) + encidx = rb_filesystem_encindex(); + rb_enc_associate_index(path, encidx); str_shrink(path); RBASIC_SET_CLASS(path, rb_obj_class(orig)); OBJ_FREEZE(path); return path; } -int -rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int _level) -{ - rb_warn("rb_find_file_ext_safe will be removed in Ruby 3.0"); - return rb_find_file_ext(filep, ext); -} - int rb_find_file_ext(VALUE *filep, const char *const *ext) { @@ -6329,13 +6461,6 @@ rb_find_file_ext(VALUE *filep, const char *const *ext) return 0; } -VALUE -rb_find_file_safe(VALUE path, int _level) -{ - rb_warn("rb_find_file_safe will be removed in Ruby 3.0"); - return rb_find_file(path); -} - VALUE rb_find_file(VALUE path) { @@ -6433,6 +6558,139 @@ const char ruby_null_device[] = * read-only, which is reported as 0444. * * Various constants for the methods in File can be found in File::Constants. + * + * == What's Here + * + * First, what's elsewhere. \Class \File: + * + * - Inherits from {class IO}[IO.html#class-IO-label-What-27s+Here], + * in particular, methods for creating, reading, and writing files + * - Includes {module FileTest}[FileTest.html#module-FileTest-label-What-27s+Here]. + * which provides dozens of additional methods. + * + * Here, class \File provides methods that are useful for: + * + * - {Creating}[#class-File-label-Creating] + * - {Querying}[#class-File-label-Querying] + * - {Settings}[#class-File-label-Settings] + * - {Other}[#class-File-label-Other] + * + * === Creating + * + * - ::new:: Opens the file at the given path; returns the file. + * - ::open:: Same as ::new, but when given a block will yield the file to the block, + * and close the file upon exiting the block. + * - ::link:: Creates a new name for an existing file using a hard link. + * - ::mkfifo:: Returns the FIFO file created at the given path. + * - ::symlink:: Creates a symbolic link for the given file path. + * + * === Querying + * + * _Paths_ + * + * - ::absolute_path:: Returns the absolute file path for the given path. + * - ::absolute_path?:: Returns whether the given path is the absolute file path. + * - ::basename:: Returns the last component of the given file path. + * - ::dirname:: Returns all but the last component of the given file path. + * - ::expand_path:: Returns the absolute file path for the given path, + * expanding ~ for a home directory. + * - ::extname:: Returns the file extension for the given file path. + * - ::fnmatch? (aliased as ::fnmatch):: Returns whether the given file path + * matches the given pattern. + * - ::join:: Joins path components into a single path string. + * - ::path:: Returns the string representation of the given path. + * - ::readlink:: Returns the path to the file at the given symbolic link. + * - ::realdirpath:: Returns the real path for the given file path, + * where the last component need not exist. + * - ::realpath:: Returns the real path for the given file path, + * where all components must exist. + * - ::split:: Returns an array of two strings: the directory name and basename + * of the file at the given path. + * - #path (aliased as #to_path):: Returns the string representation of the given path. + * + * _Times_ + * + * - ::atime:: Returns a \Time for the most recent access to the given file. + * - ::birthtime:: Returns a \Time for the creation of the given file. + * - ::ctime:: Returns a \Time for the metadata change of the given file. + * - ::mtime:: Returns a \Time for the most recent data modification to + * the content of the given file. + * - #atime:: Returns a \Time for the most recent access to +self+. + * - #birthtime:: Returns a \Time the creation for +self+. + * - #ctime:: Returns a \Time for the metadata change of +self+. + * - #mtime:: Returns a \Time for the most recent data modification + * to the content of +self+. + * + * _Types_ + * + * - ::blockdev?:: Returns whether the file at the given path is a block device. + * - ::chardev?:: Returns whether the file at the given path is a character device. + * - ::directory?:: Returns whether the file at the given path is a diretory. + * - ::executable?:: Returns whether the file at the given path is executable + * by the effective user and group of the current process. + * - ::executable_real?:: Returns whether the file at the given path is executable + * by the real user and group of the current process. + * - ::exist?:: Returns whether the file at the given path exists. + * - ::file?:: Returns whether the file at the given path is a regular file. + * - ::ftype:: Returns a string giving the type of the file at the given path. + * - ::grpowned?:: Returns whether the effective group of the current process + * owns the file at the given path. + * - ::identical?:: Returns whether the files at two given paths are identical. + * - ::lstat:: Returns the File::Stat object for the last symbolic link + * in the given path. + * - ::owned?:: Returns whether the effective user of the current process + * owns the file at the given path. + * - ::pipe?:: Returns whether the file at the given path is a pipe. + * - ::readable?:: Returns whether the file at the given path is readable + * by the effective user and group of the current process. + * - ::readable_real?:: Returns whether the file at the given path is readable + * by the real user and group of the current process. + * - ::setgid?:: Returns whether the setgid bit is set for the file at the given path. + * - ::setuid?:: Returns whether the setuid bit is set for the file at the given path. + * - ::socket?:: Returns whether the file at the given path is a socket. + * - ::stat:: Returns the File::Stat object for the file at the given path. + * - ::sticky?:: Returns whether the file at the given path has its sticky bit set. + * - ::symlink?:: Returns whether the file at the given path is a symbolic link. + * - ::umask:: Returns the umask value for the current process. + * - ::world_readable?:: Returns whether the file at the given path is readable + * by others. + * - ::world_writable?:: Returns whether the file at the given path is writable + * by others. + * - ::writable?:: Returns whether the file at the given path is writable + * by the effective user and group of the current process. + * - ::writable_real?:: Returns whether the file at the given path is writable + * by the real user and group of the current process. + * - #lstat:: Returns the File::Stat object for the last symbolic link + * in the path for +self+. + * + * _Contents_ + * + * - ::empty? (aliased as ::zero?):: Returns whether the file at the given path + * exists and is empty. + * - ::size:: Returns the size (bytes) of the file at the given path. + * - ::size?:: Returns +nil+ if there is no file at the given path, + * or if that file is empty; otherwise returns the file size (bytes). + * - #size:: Returns the size (bytes) of +self+. + * + * === Settings + * + * - ::chmod:: Changes permissions of the file at the given path. + * - ::chown:: Change ownership of the file at the given path. + * - ::lchmod:: Changes permissions of the last symbolic link in the given path. + * - ::lchown:: Change ownership of the last symbolic in the given path. + * - ::lutime:: For each given file path, sets the access time and modification time + * of the last symbolic link in the path. + * - ::rename:: Moves the file at one given path to another given path. + * - ::utime:: Sets the access time and modification time of each file + * at the given paths. + * - #flock:: Locks or unlocks +self+. + * + * === Other + * + * - ::truncate:: Truncates the file at the given file path to the given size. + * - ::unlink (aliased as ::delete):: Deletes the file for each given file path. + * - #truncate:: Truncates +self+ to the given size. + * */ void @@ -6507,7 +6765,7 @@ Init_File(void) rb_define_singleton_method(rb_cFile, "realpath", rb_file_s_realpath, -1); rb_define_singleton_method(rb_cFile, "realdirpath", rb_file_s_realdirpath, -1); rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1); - rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, 1); + rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, -1); rb_define_singleton_method(rb_cFile, "extname", rb_file_s_extname, 1); rb_define_singleton_method(rb_cFile, "path", rb_file_s_path, 1); @@ -6535,7 +6793,7 @@ Init_File(void) rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0); rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0); rb_define_method(rb_cFile, "birthtime", rb_file_birthtime, 0); - rb_define_method(rb_cFile, "size", rb_file_size, 0); + rb_define_method(rb_cFile, "size", file_size, 0); rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1); rb_define_method(rb_cFile, "chown", rb_file_chown, 2); diff --git a/ruby/gc.c b/ruby/gc.c index 0c007dffe..ef9327df1 100644 --- a/ruby/gc.c +++ b/ruby/gc.c @@ -14,47 +14,39 @@ #define rb_data_object_alloc rb_data_object_alloc #define rb_data_typed_object_alloc rb_data_typed_object_alloc -#include "ruby/encoding.h" -#include "ruby/io.h" -#include "ruby/st.h" -#include "ruby/re.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "ruby/debug.h" -#include "internal.h" -#include "eval_intern.h" -#include "vm_core.h" -#include "builtin.h" -#include "gc.h" -#include "constant.h" -#include "ruby_atomic.h" -#include "probes.h" -#include "id_table.h" -#include "symbol.h" -#include -#include -#include -#include -#include "ruby_assert.h" -#include "debug_counter.h" -#include "transient_heap.h" -#include "mjit.h" +#include "ruby/internal/config.h" +#ifdef _WIN32 +# include "ruby/ruby.h" +#endif -#undef rb_data_object_wrap +#include + +#define sighandler_t ruby_sighandler_t + +#ifndef _WIN32 +#include +#include +#endif + +#include +#include +#include +/* MALLOC_HEADERS_BEGIN */ #ifndef HAVE_MALLOC_USABLE_SIZE # ifdef _WIN32 -# define HAVE_MALLOC_USABLE_SIZE -# define malloc_usable_size(a) _msize(a) +# define HAVE_MALLOC_USABLE_SIZE +# define malloc_usable_size(a) _msize(a) # elif defined HAVE_MALLOC_SIZE -# define HAVE_MALLOC_USABLE_SIZE -# define malloc_usable_size(a) malloc_size(a) +# define HAVE_MALLOC_USABLE_SIZE +# define malloc_usable_size(a) malloc_size(a) # endif #endif + #ifdef HAVE_MALLOC_USABLE_SIZE # ifdef RUBY_ALTERNATIVE_MALLOC_HEADER -# include RUBY_ALTERNATIVE_MALLOC_HEADER -# elif HAVE_MALLOC_H +/* Alternative malloc header is included in ruby/missing.h */ +# elif defined(HAVE_MALLOC_H) # include # elif defined(HAVE_MALLOC_NP_H) # include @@ -63,75 +55,96 @@ # endif #endif +#if !defined(PAGE_SIZE) && defined(HAVE_SYS_USER_H) +/* LIST_HEAD conflicts with sys/queue.h on macOS */ +# include +#endif +/* MALLOC_HEADERS_END */ + #ifdef HAVE_SYS_TIME_H -#include +# include #endif #ifdef HAVE_SYS_RESOURCE_H -#include +# include #endif #if defined _WIN32 || defined __CYGWIN__ -#include +# include #elif defined(HAVE_POSIX_MEMALIGN) #elif defined(HAVE_MEMALIGN) -#include +# include #endif -#define rb_setjmp(env) RUBY_SETJMP(env) -#define rb_jmp_buf rb_jmpbuf_t +#include -#if defined(_MSC_VER) && defined(_WIN64) -#include -#pragma intrinsic(_umul128) +#ifdef __EMSCRIPTEN__ +#include #endif -/* Expecting this struct to be eliminated by function inlinings */ -struct optional { - bool left; - size_t right; -}; - -static inline struct optional -size_mul_overflow(size_t x, size_t y) -{ - bool p; - size_t z; -#if 0 - -#elif defined(HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW) - p = __builtin_mul_overflow(x, y, &z); +#undef LIST_HEAD /* ccan/list conflicts with BSD-origin sys/queue.h. */ -#elif defined(DSIZE_T) - RB_GNUC_EXTENSION DSIZE_T dx = x; - RB_GNUC_EXTENSION DSIZE_T dy = y; - RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; - p = dz > SIZE_MAX; - z = (size_t)dz; +#include "constant.h" +#include "debug_counter.h" +#include "eval_intern.h" +#include "gc.h" +#include "id_table.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/complex.h" +#include "internal/cont.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/gc.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/rational.h" +#include "internal/sanitizers.h" +#include "internal/struct.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "internal/warnings.h" +#include "mjit.h" +#include "probes.h" +#include "regint.h" +#include "ruby/debug.h" +#include "ruby/io.h" +#include "ruby/re.h" +#include "ruby/st.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "ruby_assert.h" +#include "ruby_atomic.h" +#include "symbol.h" +#include "transient_heap.h" +#include "vm_core.h" +#include "vm_sync.h" +#include "vm_callinfo.h" +#include "ractor_core.h" -#elif defined(_MSC_VER) && defined(_WIN64) - unsigned __int64 dp; - unsigned __int64 dz = _umul128(x, y, &dp); - p = (bool)dp; - z = (size_t)dz; +#include "builtin.h" -#else - /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ - p = (y != 0) && (x > SIZE_MAX / y); - z = x * y; +#define rb_setjmp(env) RUBY_SETJMP(env) +#define rb_jmp_buf rb_jmpbuf_t +#undef rb_data_object_wrap +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON #endif - return (struct optional) { p, z, }; -} -static inline struct optional +static inline struct rbimpl_size_mul_overflow_tag size_add_overflow(size_t x, size_t y) { size_t z; bool p; #if 0 -#elif defined(HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW) +#elif __has_builtin(__builtin_add_overflow) p = __builtin_add_overflow(x, y, &z); #elif defined(DSIZE_T) @@ -146,24 +159,24 @@ size_add_overflow(size_t x, size_t y) p = z < y; #endif - return (struct optional) { p, z, }; + return (struct rbimpl_size_mul_overflow_tag) { p, z, }; } -static inline struct optional +static inline struct rbimpl_size_mul_overflow_tag size_mul_add_overflow(size_t x, size_t y, size_t z) /* x * y + z */ { - struct optional t = size_mul_overflow(x, y); - struct optional u = size_add_overflow(t.right, z); - return (struct optional) { t.left || u.left, u.right }; + struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y); + struct rbimpl_size_mul_overflow_tag u = size_add_overflow(t.right, z); + return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left, u.right }; } -static inline struct optional +static inline struct rbimpl_size_mul_overflow_tag size_mul_add_mul_overflow(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */ { - struct optional t = size_mul_overflow(x, y); - struct optional u = size_mul_overflow(z, w); - struct optional v = size_add_overflow(t.right, u.right); - return (struct optional) { t.left || u.left || v.left, v.right }; + struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y); + struct rbimpl_size_mul_overflow_tag u = rbimpl_size_mul_overflow(z, w); + struct rbimpl_size_mul_overflow_tag v = size_add_overflow(t.right, u.right); + return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left || v.left, v.right }; } PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3); @@ -171,7 +184,7 @@ PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3); static inline size_t size_mul_or_raise(size_t x, size_t y, VALUE exc) { - struct optional t = size_mul_overflow(x, y); + struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y); if (LIKELY(!t.left)) { return t.right; } @@ -184,7 +197,7 @@ size_mul_or_raise(size_t x, size_t y, VALUE exc) "integer overflow: %"PRIuSIZE " * %"PRIuSIZE " > %"PRIuSIZE, - x, y, SIZE_MAX); + x, y, (size_t)SIZE_MAX); } } @@ -197,7 +210,7 @@ rb_size_mul_or_raise(size_t x, size_t y, VALUE exc) static inline size_t size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc) { - struct optional t = size_mul_add_overflow(x, y, z); + struct rbimpl_size_mul_overflow_tag t = size_mul_add_overflow(x, y, z); if (LIKELY(!t.left)) { return t.right; } @@ -211,7 +224,7 @@ size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc) " * %"PRIuSIZE " + %"PRIuSIZE " > %"PRIuSIZE, - x, y, z, SIZE_MAX); + x, y, z, (size_t)SIZE_MAX); } } @@ -224,7 +237,7 @@ rb_size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc) static inline size_t size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc) { - struct optional t = size_mul_add_mul_overflow(x, y, z, w); + struct rbimpl_size_mul_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w); if (LIKELY(!t.left)) { return t.right; } @@ -239,7 +252,7 @@ size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc) " + %"PRIdSIZE " * %"PRIdSIZE " > %"PRIdSIZE, - x, y, z, w, SIZE_MAX); + x, y, z, w, (size_t)SIZE_MAX); } } @@ -365,7 +378,6 @@ static ruby_gc_params_t gc_params = { #define GC_DEBUG 0 #endif -#if USE_RGENGC /* RGENGC_DEBUG: * 1: basic information * 2: remember set operation @@ -382,8 +394,10 @@ static ruby_gc_params_t gc_params = { #endif #if RGENGC_DEBUG < 0 && !defined(_MSC_VER) # define RGENGC_DEBUG_ENABLED(level) (-(RGENGC_DEBUG) >= (level) && ruby_rgengc_debug >= (level)) -#else +#elif defined(HAVE_VA_ARGS_MACRO) # define RGENGC_DEBUG_ENABLED(level) ((RGENGC_DEBUG) >= (level)) +#else +# define RGENGC_DEBUG_ENABLED(level) 0 #endif int ruby_rgengc_debug; @@ -438,22 +452,6 @@ int ruby_rgengc_debug; #define RGENGC_FORCE_MAJOR_GC 0 #endif -#else /* USE_RGENGC */ - -#ifdef RGENGC_DEBUG -#undef RGENGC_DEBUG -#endif -#define RGENGC_DEBUG 0 -#ifdef RGENGC_CHECK_MODE -#undef RGENGC_CHECK_MODE -#endif -#define RGENGC_CHECK_MODE 0 -#define RGENGC_PROFILE 0 -#define RGENGC_ESTIMATE_OLDMALLOC 0 -#define RGENGC_FORCE_MAJOR_GC 0 - -#endif /* USE_RGENGC */ - #ifndef GC_PROFILE_MORE_DETAIL #define GC_PROFILE_MORE_DETAIL 0 #endif @@ -512,6 +510,7 @@ typedef enum { GPR_FLAG_HAVE_FINALIZE = 0x4000, GPR_FLAG_IMMEDIATE_MARK = 0x8000, GPR_FLAG_FULL_MARK = 0x10000, + GPR_FLAG_COMPACT = 0x20000, GPR_DEFAULT_REASON = (GPR_FLAG_FULL_MARK | GPR_FLAG_IMMEDIATE_MARK | @@ -519,7 +518,7 @@ typedef enum { } gc_profile_record_flag; typedef struct gc_profile_record { - int flags; + unsigned int flags; double gc_time; double gc_invoke_time; @@ -527,6 +526,7 @@ typedef struct gc_profile_record { size_t heap_total_objects; size_t heap_use_size; size_t heap_total_size; + size_t moved_objects; #if GC_PROFILE_MORE_DETAIL double gc_mark_time; @@ -559,9 +559,15 @@ typedef struct gc_profile_record { #endif } gc_profile_record; -#if defined(_MSC_VER) || defined(__CYGWIN__) -#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ -#endif +#define FL_FROM_FREELIST FL_USER0 + +struct RMoved { + VALUE flags; + VALUE dummy; + VALUE destination; +}; + +#define RMOVED(obj) ((struct RMoved *)(obj)) typedef struct RVALUE { union { @@ -586,6 +592,7 @@ typedef struct RVALUE { struct RMatch match; struct RRational rational; struct RComplex complex; + struct RSymbol symbol; union { rb_cref_t cref; struct vm_svar svar; @@ -611,9 +618,12 @@ typedef struct RVALUE { #endif } RVALUE; -#if defined(_MSC_VER) || defined(__CYGWIN__) -#pragma pack(pop) +#if GC_DEBUG +STATIC_ASSERT(sizeof_rvalue, offsetof(RVALUE, file) == SIZEOF_VALUE * 5); +#else +STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == SIZEOF_VALUE * 5); #endif +STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE); typedef uintptr_t bits_t; enum { @@ -653,13 +663,15 @@ typedef struct mark_stack { size_t unused_cache_size; } mark_stack_t; -typedef struct rb_heap_struct { - RVALUE *freelist; +#define SIZE_POOL_EDEN_HEAP(size_pool) (&(size_pool)->eden_heap) +#define SIZE_POOL_TOMB_HEAP(size_pool) (&(size_pool)->tomb_heap) +typedef struct rb_heap_struct { struct heap_page *free_pages; - struct heap_page *using_page; struct list_head pages; struct heap_page *sweeping_page; /* iterator for .pages */ + struct heap_page *compact_cursor; + RVALUE * compact_cursor_index; #if GC_ENABLE_INCREMENTAL_MARK struct heap_page *pooled_pages; #endif @@ -667,6 +679,24 @@ typedef struct rb_heap_struct { size_t total_slots; /* total slot count (about total_pages * HEAP_PAGE_OBJ_LIMIT) */ } rb_heap_t; +typedef struct rb_size_pool_struct { + short slot_size; + + size_t allocatable_pages; + +#if USE_RVARGC + /* Sweeping statistics */ + size_t freed_slots; + size_t empty_slots; + + /* Global statistics */ + size_t force_major_gc_count; +#endif + + rb_heap_t eden_heap; + rb_heap_t tomb_heap; +} rb_size_pool_t; + enum gc_mode { gc_mode_none, gc_mode_marking, @@ -692,30 +722,23 @@ typedef struct rb_objspace { unsigned int during_compacting : 1; unsigned int gc_stressful: 1; unsigned int has_hook: 1; -#if USE_RGENGC unsigned int during_minor_gc : 1; -#endif #if GC_ENABLE_INCREMENTAL_MARK unsigned int during_incremental_marking : 1; #endif + unsigned int measure_gc : 1; } flags; rb_event_flag_t hook_events; size_t total_allocated_objects; VALUE next_object_id; - rb_heap_t eden_heap; - rb_heap_t tomb_heap; /* heap for zombies and ghosts */ + rb_size_pool_t size_pools[SIZE_POOL_COUNT]; struct { rb_atomic_t finalizing; } atomic_flags; - struct mark_func_data_struct { - void *data; - void (*mark_func)(VALUE v, void *data); - } *mark_func_data; - mark_stack_t mark_stack; size_t marked_slots; @@ -736,7 +759,7 @@ typedef struct rb_objspace { struct { int run; - int latest_gc_info; + unsigned int latest_gc_info; gc_profile_record *records; gc_profile_record *current_record; size_t next_index; @@ -747,10 +770,10 @@ typedef struct rb_objspace { #endif double invoke_time; -#if USE_RGENGC size_t minor_gc_count; size_t major_gc_count; size_t compact_count; + size_t read_barrier_faults; #if RGENGC_PROFILE > 0 size_t total_generated_normal_object_count; size_t total_generated_shady_object_count; @@ -768,7 +791,6 @@ typedef struct rb_objspace { size_t remembered_shady_object_count_types[RUBY_T_MASK]; #endif #endif /* RGENGC_PROFILE */ -#endif /* USE_RGENGC */ /* temporary profiling space */ double gc_sweep_start_time; @@ -780,12 +802,13 @@ typedef struct rb_objspace { size_t total_freed_objects; size_t total_allocated_pages; size_t total_freed_pages; + uint64_t total_time_ns; + struct timespec start_time; } profile; struct gc_list *global_list; VALUE gc_stress_mode; -#if USE_RGENGC struct { VALUE parent_object; int need_major_gc; @@ -809,6 +832,7 @@ typedef struct rb_objspace { struct { size_t considered_count_table[T_MASK]; size_t moved_count_table[T_MASK]; + size_t total_moved; } rcompactor; #if GC_ENABLE_INCREMENTAL_MARK @@ -817,7 +841,6 @@ typedef struct rb_objspace { size_t step_slots; } rincgc; #endif -#endif /* USE_RGENGC */ st_table *id_to_obj_tbl; st_table *obj_to_id_tbl; @@ -834,15 +857,33 @@ typedef struct rb_objspace { enum { HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG), HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)), - REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5), - HEAP_PAGE_SIZE = (HEAP_PAGE_ALIGN - REQUIRED_SIZE_BY_MALLOC), + HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN, HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header))/sizeof(struct RVALUE)), HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, sizeof(struct RVALUE)), BITS_BITLENGTH), HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT), - HEAP_PAGE_BITMAP_PLANES = USE_RGENGC ? 4 : 1 /* RGENGC: mark, unprotected, uncollectible, marking */ }; +#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG) +#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN + +#ifdef HAVE_MMAP +# if HAVE_CONST_PAGE_SIZE +/* If we have the HEAP_PAGE and it is a constant, then we can directly use it. */ +static const bool USE_MMAP_ALIGNED_ALLOC = (PAGE_SIZE <= HEAP_PAGE_SIZE); +# elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE) +/* PAGE_SIZE <= HEAP_PAGE_SIZE */ +static const bool USE_MMAP_ALIGNED_ALLOC = true; +# else +/* Otherwise, fall back to determining if we can use mmap during runtime. */ +# define USE_MMAP_ALIGNED_ALLOC (use_mmap_aligned_alloc != false) + +static bool use_mmap_aligned_alloc; +# endif +#elif !defined(__MINGW32__) && !defined(_WIN32) +static const bool USE_MMAP_ALIGNED_ALLOC = false; +#endif struct heap_page { + short slot_size; short total_slots; short free_slots; short pinned_slots; @@ -854,20 +895,18 @@ struct heap_page { unsigned int in_tomb : 1; } flags; + rb_size_pool_t *size_pool; + struct heap_page *free_next; RVALUE *start; RVALUE *freelist; struct list_node page_node; -#if USE_RGENGC bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT]; -#endif /* the following three bitmaps are cleared at the beginning of full GC */ bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT]; -#if USE_RGENGC bits_t uncollectible_bits[HEAP_PAGE_BITMAP_LIMIT]; bits_t marking_bits[HEAP_PAGE_BITMAP_LIMIT]; -#endif /* If set, the object is not movable */ bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT]; @@ -890,11 +929,9 @@ struct heap_page { /* getting bitmap */ #define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0]) #define GET_HEAP_PINNED_BITS(x) (&GET_HEAP_PAGE(x)->pinned_bits[0]) -#if USE_RGENGC #define GET_HEAP_UNCOLLECTIBLE_BITS(x) (&GET_HEAP_PAGE(x)->uncollectible_bits[0]) #define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0]) #define GET_HEAP_MARKING_BITS(x) (&GET_HEAP_PAGE(x)->marking_bits[0]) -#endif /* Aliases */ #define rb_objspace (*rb_objspace_of(GET_VM())) @@ -912,13 +949,10 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; #define heap_pages_sorted_length objspace->heap_pages.sorted_length #define heap_pages_lomem objspace->heap_pages.range[0] #define heap_pages_himem objspace->heap_pages.range[1] -#define heap_allocatable_pages objspace->heap_pages.allocatable_pages #define heap_pages_freeable_pages objspace->heap_pages.freeable_pages #define heap_pages_final_slots objspace->heap_pages.final_slots #define heap_pages_deferred_final objspace->heap_pages.deferred_final -#define heap_eden (&objspace->eden_heap) -#define heap_tomb (&objspace->tomb_heap) -#define dont_gc objspace->flags.dont_gc +#define size_pools objspace->size_pools #define during_gc objspace->flags.during_gc #define finalizing objspace->atomic_flags.finalizing #define finalizer_table objspace->finalizer_table @@ -931,6 +965,18 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; #define stress_to_class 0 #endif +#if 0 +#define dont_gc_on() (fprintf(stderr, "dont_gc_on@%s:%d\n", __FILE__, __LINE__), objspace->flags.dont_gc = 1) +#define dont_gc_off() (fprintf(stderr, "dont_gc_off@%s:%d\n", __FILE__, __LINE__), objspace->flags.dont_gc = 0) +#define dont_gc_set(b) (fprintf(stderr, "dont_gc_set(%d)@%s:%d\n", __FILE__, __LINE__), (int)b), objspace->flags.dont_gc = (b)) +#define dont_gc_val() (objspace->flags.dont_gc) +#else +#define dont_gc_on() (objspace->flags.dont_gc = 1) +#define dont_gc_off() (objspace->flags.dont_gc = 0) +#define dont_gc_set(b) (((int)b), objspace->flags.dont_gc = (b)) +#define dont_gc_val() (objspace->flags.dont_gc) +#endif + static inline enum gc_mode gc_mode_verify(enum gc_mode mode) { @@ -947,16 +993,75 @@ gc_mode_verify(enum gc_mode mode) return mode; } +static inline bool +has_sweeping_pages(rb_objspace_t *objspace) +{ + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + if (SIZE_POOL_EDEN_HEAP(&size_pools[i])->sweeping_page) { + return TRUE; + } + } + return FALSE; +} + +static inline size_t +heap_eden_total_pages(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + count += SIZE_POOL_EDEN_HEAP(&size_pools[i])->total_pages; + } + return count; +} + +static inline size_t +heap_eden_total_slots(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + count += SIZE_POOL_EDEN_HEAP(&size_pools[i])->total_slots; + } + return count; +} + +static inline size_t +heap_tomb_total_pages(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + count += SIZE_POOL_TOMB_HEAP(&size_pools[i])->total_pages; + } + return count; +} + +static inline size_t +heap_allocatable_pages(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + count += size_pools[i].allocatable_pages; + } + return count; +} + +static inline size_t +heap_allocatable_slots(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + int slot_size_multiple = size_pool->slot_size / sizeof(RVALUE); + count += size_pool->allocatable_pages * HEAP_PAGE_OBJ_LIMIT / slot_size_multiple; + } + return count; +} + #define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode) #define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode)) #define is_marking(objspace) (gc_mode(objspace) == gc_mode_marking) #define is_sweeping(objspace) (gc_mode(objspace) == gc_mode_sweeping) -#if USE_RGENGC #define is_full_marking(objspace) ((objspace)->flags.during_minor_gc == FALSE) -#else -#define is_full_marking(objspace) TRUE -#endif #if GC_ENABLE_INCREMENTAL_MARK #define is_incremental_marking(objspace) ((objspace)->flags.during_incremental_marking != FALSE) #else @@ -967,8 +1072,7 @@ gc_mode_verify(enum gc_mode mode) #else #define will_be_incremental_marking(objspace) FALSE #endif -#define has_sweeping_pages(heap) ((heap)->sweeping_page != 0) -#define is_lazy_sweeping(heap) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(heap)) +#define is_lazy_sweeping(objspace) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(objspace)) #if SIZEOF_LONG == SIZEOF_VOIDP # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG) @@ -999,6 +1103,7 @@ int ruby_gc_debug_indent = 0; #endif VALUE rb_mGC; int ruby_disable_gc = 0; +int ruby_enable_autocompact = 0; void rb_iseq_mark(const rb_iseq_t *iseq); void rb_iseq_update_references(rb_iseq_t *iseq); @@ -1010,32 +1115,43 @@ void rb_gcdebug_print_obj_condition(VALUE obj); static VALUE define_final0(VALUE obj, VALUE block); +NORETURN(static void *gc_vraise(void *ptr)); +NORETURN(static void gc_raise(VALUE exc, const char *fmt, ...)); NORETURN(static void negative_size_allocation_error(const char *)); static void init_mark_stack(mark_stack_t *stack); static int ready_to_gc(rb_objspace_t *objspace); -static int garbage_collect(rb_objspace_t *, int reason); +static int garbage_collect(rb_objspace_t *, unsigned int reason); -static int gc_start(rb_objspace_t *objspace, int reason); +static int gc_start(rb_objspace_t *objspace, unsigned int reason); static void gc_rest(rb_objspace_t *objspace); -static inline void gc_enter(rb_objspace_t *objspace, const char *event); -static inline void gc_exit(rb_objspace_t *objspace, const char *event); + +enum gc_enter_event { + gc_enter_event_start, + gc_enter_event_mark_continue, + gc_enter_event_sweep_continue, + gc_enter_event_rest, + gc_enter_event_finalizer, + gc_enter_event_rb_memerror, +}; + +static inline void gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev); +static inline void gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev); static void gc_marks(rb_objspace_t *objspace, int full_mark); static void gc_marks_start(rb_objspace_t *objspace, int full); static int gc_marks_finish(rb_objspace_t *objspace); static void gc_marks_rest(rb_objspace_t *objspace); -static void gc_marks_step(rb_objspace_t *objspace, int slots); -static void gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap); +static void gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); static void gc_sweep(rb_objspace_t *objspace); static void gc_sweep_start(rb_objspace_t *objspace); static void gc_sweep_finish(rb_objspace_t *objspace); -static int gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap); +static int gc_sweep_step(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); static void gc_sweep_rest(rb_objspace_t *objspace); -static void gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap); +static void gc_sweep_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); static inline void gc_mark(rb_objspace_t *objspace, VALUE ptr); static inline void gc_pin(rb_objspace_t *objspace, VALUE ptr); @@ -1065,7 +1181,7 @@ static void gc_stress_set(rb_objspace_t *objspace, VALUE flag); static VALUE gc_disable_no_rest(rb_objspace_t *); static double getrusage_time(void); -static inline void gc_prof_setup_new_record(rb_objspace_t *objspace, int reason); +static inline void gc_prof_setup_new_record(rb_objspace_t *objspace, unsigned int reason); static inline void gc_prof_timer_start(rb_objspace_t *); static inline void gc_prof_timer_stop(rb_objspace_t *); static inline void gc_prof_mark_timer_start(rb_objspace_t *); @@ -1094,12 +1210,7 @@ static inline void gc_prof_set_heap_info(rb_objspace_t *); #endif PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4); static const char *obj_info(VALUE obj); - -#define PUSH_MARK_FUNC_DATA(v) do { \ - struct mark_func_data_struct *prev_mark_func_data = objspace->mark_func_data; \ - objspace->mark_func_data = (v); - -#define POP_MARK_FUNC_DATA() objspace->mark_func_data = prev_mark_func_data;} while (0) +static const char *obj_type_name(VALUE obj); /* * 1 - TSC (H/W Time Stamp Counter) @@ -1153,6 +1264,19 @@ tick(void) return val; } +#elif defined(__aarch64__) && defined(__GNUC__) +typedef unsigned long tick_t; +#define PRItick "lu" + +static __inline__ tick_t +tick(void) +{ + unsigned long val; + __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (val)); + return val; +} + + #elif defined(_WIN32) && defined(_MSC_VER) #include typedef unsigned __int64 tick_t; @@ -1200,6 +1324,14 @@ tick(void) #define MEASURE_LINE(expr) expr #endif /* USE_TICK_T */ +static inline void * +asan_unpoison_object_temporary(VALUE obj) +{ + void *ptr = asan_poisoned_object_p(obj); + asan_unpoison_object(obj, false); + return ptr; +} + #define FL_CHECK2(name, x, pred) \ ((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? \ (rb_bug(name": SPECIAL_CONST (%p)", (void *)(x)), 0) : (pred)) @@ -1211,7 +1343,6 @@ tick(void) #define RVALUE_PIN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), (obj)) #define RVALUE_PAGE_MARKED(page, obj) MARKED_IN_BITMAP((page)->mark_bits, (obj)) -#if USE_RGENGC #define RVALUE_WB_UNPROTECTED_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), (obj)) #define RVALUE_UNCOLLECTIBLE_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), (obj)) #define RVALUE_MARKING_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), (obj)) @@ -1235,103 +1366,108 @@ RVALUE_FLAGS_AGE(VALUE flags) return (int)((flags & (FL_PROMOTED0 | FL_PROMOTED1)) >> RVALUE_AGE_SHIFT); } -#endif /* USE_RGENGC */ - static int check_rvalue_consistency_force(const VALUE obj, int terminate) { - rb_objspace_t *objspace = &rb_objspace; int err = 0; + rb_objspace_t *objspace = &rb_objspace; - if (SPECIAL_CONST_P(obj)) { - fprintf(stderr, "check_rvalue_consistency: %p is a special const.\n", (void *)obj); - err++; - } - else if (!is_pointer_to_heap(objspace, (void *)obj)) { - /* check if it is in tomb_pages */ - struct heap_page *page = NULL; - list_for_each(&heap_tomb->pages, page, page_node) { - if (&page->start[0] <= (RVALUE *)obj && - (RVALUE *)obj < &page->start[page->total_slots]) { - fprintf(stderr, "check_rvalue_consistency: %p is in a tomb_heap (%p).\n", - (void *)obj, (void *)page); - err++; - goto skip; - } - } - fprintf(stderr, "check_rvalue_consistency: %p is not a Ruby object.\n", (void *)obj); - err++; - skip: - ; - } - else { - const int wb_unprotected_bit = RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0; - const int uncollectible_bit = RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0; - const int mark_bit = RVALUE_MARK_BITMAP(obj) != 0; - const int marking_bit = RVALUE_MARKING_BITMAP(obj) != 0, remembered_bit = marking_bit; - const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags); - - if (GET_HEAP_PAGE(obj)->flags.in_tomb) { - fprintf(stderr, "check_rvalue_consistency: %s is in tomb page.\n", obj_info(obj)); - err++; - } - if (BUILTIN_TYPE(obj) == T_NONE) { - fprintf(stderr, "check_rvalue_consistency: %s is T_NONE.\n", obj_info(obj)); - err++; - } - if (BUILTIN_TYPE(obj) == T_ZOMBIE) { - fprintf(stderr, "check_rvalue_consistency: %s is T_ZOMBIE.\n", obj_info(obj)); + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + if (SPECIAL_CONST_P(obj)) { + fprintf(stderr, "check_rvalue_consistency: %p is a special const.\n", (void *)obj); err++; } - - obj_memsize_of((VALUE)obj, FALSE); - - /* check generation - * - * OLD == age == 3 && old-bitmap && mark-bit (except incremental marking) - */ - if (age > 0 && wb_unprotected_bit) { - fprintf(stderr, "check_rvalue_consistency: %s is not WB protected, but age is %d > 0.\n", obj_info(obj), age); + else if (!is_pointer_to_heap(objspace, (void *)obj)) { + /* check if it is in tomb_pages */ + struct heap_page *page = NULL; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + list_for_each(&size_pool->tomb_heap.pages, page, page_node) { + if (&page->start[0] <= (RVALUE *)obj && + (uintptr_t)obj < ((uintptr_t)page->start + (page->total_slots * size_pool->slot_size))) { + fprintf(stderr, "check_rvalue_consistency: %p is in a tomb_heap (%p).\n", + (void *)obj, (void *)page); + err++; + goto skip; + } + } + } + bp(); + fprintf(stderr, "check_rvalue_consistency: %p is not a Ruby object.\n", (void *)obj); err++; + skip: + ; } + else { + const int wb_unprotected_bit = RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0; + const int uncollectible_bit = RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0; + const int mark_bit = RVALUE_MARK_BITMAP(obj) != 0; + const int marking_bit = RVALUE_MARKING_BITMAP(obj) != 0, remembered_bit = marking_bit; + const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags); + + if (GET_HEAP_PAGE(obj)->flags.in_tomb) { + fprintf(stderr, "check_rvalue_consistency: %s is in tomb page.\n", obj_info(obj)); + err++; + } + if (BUILTIN_TYPE(obj) == T_NONE) { + fprintf(stderr, "check_rvalue_consistency: %s is T_NONE.\n", obj_info(obj)); + err++; + } + if (BUILTIN_TYPE(obj) == T_ZOMBIE) { + fprintf(stderr, "check_rvalue_consistency: %s is T_ZOMBIE.\n", obj_info(obj)); + err++; + } - if (!is_marking(objspace) && uncollectible_bit && !mark_bit) { - fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but is not marked while !gc.\n", obj_info(obj)); - err++; - } + obj_memsize_of((VALUE)obj, FALSE); - if (!is_full_marking(objspace)) { - if (uncollectible_bit && age != RVALUE_OLD_AGE && !wb_unprotected_bit) { - fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but not old (age: %d) and not WB unprotected.\n", - obj_info(obj), age); + /* check generation + * + * OLD == age == 3 && old-bitmap && mark-bit (except incremental marking) + */ + if (age > 0 && wb_unprotected_bit) { + fprintf(stderr, "check_rvalue_consistency: %s is not WB protected, but age is %d > 0.\n", obj_info(obj), age); err++; } - if (remembered_bit && age != RVALUE_OLD_AGE) { - fprintf(stderr, "check_rvalue_consistency: %s is remembered, but not old (age: %d).\n", - obj_info(obj), age); + + if (!is_marking(objspace) && uncollectible_bit && !mark_bit) { + fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but is not marked while !gc.\n", obj_info(obj)); err++; } - } - /* - * check coloring - * - * marking:false marking:true - * marked:false white *invalid* - * marked:true black grey - */ - if (is_incremental_marking(objspace) && marking_bit) { - if (!is_marking(objspace) && !mark_bit) { - fprintf(stderr, "check_rvalue_consistency: %s is marking, but not marked.\n", obj_info(obj)); - err++; + if (!is_full_marking(objspace)) { + if (uncollectible_bit && age != RVALUE_OLD_AGE && !wb_unprotected_bit) { + fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but not old (age: %d) and not WB unprotected.\n", + obj_info(obj), age); + err++; + } + if (remembered_bit && age != RVALUE_OLD_AGE) { + fprintf(stderr, "check_rvalue_consistency: %s is remembered, but not old (age: %d).\n", + obj_info(obj), age); + err++; + } + } + + /* + * check coloring + * + * marking:false marking:true + * marked:false white *invalid* + * marked:true black grey + */ + if (is_incremental_marking(objspace) && marking_bit) { + if (!is_marking(objspace) && !mark_bit) { + fprintf(stderr, "check_rvalue_consistency: %s is marking, but not marked.\n", obj_info(obj)); + err++; + } } } } + RB_VM_LOCK_LEAVE_NO_BARRIER(); if (err > 0 && terminate) { rb_bug("check_rvalue_consistency_force: there is %d errors.", err); } - return err; } @@ -1384,7 +1520,6 @@ RVALUE_PINNED(VALUE obj) return RVALUE_PIN_BITMAP(obj) != 0; } -#if USE_RGENGC static inline int RVALUE_WB_UNPROTECTED(VALUE obj) { @@ -1571,8 +1706,6 @@ RVALUE_WHITE_P(VALUE obj) return RVALUE_MARKED(obj) == FALSE; } -#endif /* USE_RGENGC */ - /* --------------------------- ObjectSpace ----------------------------- */ @@ -1587,10 +1720,19 @@ rb_objspace_t * rb_objspace_alloc(void) { rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t)); + objspace->flags.measure_gc = 1; malloc_limit = gc_params.malloc_limit_min; - list_head_init(&objspace->eden_heap.pages); - list_head_init(&objspace->tomb_heap.pages); - dont_gc = TRUE; + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + + size_pool->slot_size = sizeof(RVALUE) * (1 << i); + + list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages); + list_head_init(&SIZE_POOL_TOMB_HEAP(size_pool)->pages); + } + + dont_gc_on(); return objspace; } @@ -1601,7 +1743,7 @@ static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page); void rb_objspace_free(rb_objspace_t *objspace) { - if (is_lazy_sweeping(heap_eden)) + if (is_lazy_sweeping(objspace)) rb_bug("lazy sweeping underway when freeing object space"); if (objspace->profile.records) { @@ -1627,8 +1769,11 @@ rb_objspace_free(rb_objspace_t *objspace) heap_pages_lomem = 0; heap_pages_himem = 0; - objspace->eden_heap.total_pages = 0; - objspace->eden_heap.total_slots = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + SIZE_POOL_EDEN_HEAP(size_pool)->total_pages = 0; + SIZE_POOL_EDEN_HEAP(size_pool)->total_slots = 0; + } } st_free_table(objspace->id_to_obj_tbl); st_free_table(objspace->obj_to_id_tbl); @@ -1642,7 +1787,8 @@ heap_pages_expand_sorted_to(rb_objspace_t *objspace, size_t next_length) struct heap_page **sorted; size_t size = size_mul_or_raise(next_length, sizeof(struct heap_page *), rb_eRuntimeError); - gc_report(3, objspace, "heap_pages_expand_sorted: next_length: %d, size: %d\n", (int)next_length, (int)size); + gc_report(3, objspace, "heap_pages_expand_sorted: next_length: %"PRIdSIZE", size: %"PRIdSIZE"\n", + next_length, size); if (heap_pages_sorted_length > 0) { sorted = (struct heap_page **)realloc(heap_pages_sorted, size); @@ -1667,30 +1813,37 @@ heap_pages_expand_sorted(rb_objspace_t *objspace) * however, if there are pages which do not have empty slots, then try to create new pages * so that the additional allocatable_pages counts (heap_tomb->total_pages) are added. */ - size_t next_length = heap_allocatable_pages; - next_length += heap_eden->total_pages; - next_length += heap_tomb->total_pages; + size_t next_length = heap_allocatable_pages(objspace); + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + next_length += SIZE_POOL_EDEN_HEAP(size_pool)->total_pages; + next_length += SIZE_POOL_TOMB_HEAP(size_pool)->total_pages; + } if (next_length > heap_pages_sorted_length) { heap_pages_expand_sorted_to(objspace, next_length); } - GC_ASSERT(heap_allocatable_pages + heap_eden->total_pages <= heap_pages_sorted_length); + GC_ASSERT(heap_allocatable_pages(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length); GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length); } static void -heap_allocatable_pages_set(rb_objspace_t *objspace, size_t s) +size_pool_allocatable_pages_set(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t s) { - heap_allocatable_pages = s; + size_pool->allocatable_pages = s; heap_pages_expand_sorted(objspace); } - static inline void heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj) { + ASSERT_vm_locking(); + RVALUE *p = (RVALUE *)obj; + + asan_unpoison_object(obj, false); + asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); p->as.free.flags = 0; @@ -1701,13 +1854,12 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj if (RGENGC_CHECK_MODE && /* obj should belong to page */ !(&page->start[0] <= (RVALUE *)obj && - (RVALUE *)obj < &page->start[page->total_slots] && + (uintptr_t)obj < ((uintptr_t)page->start + (page->total_slots * page->slot_size)) && obj % sizeof(RVALUE) == 0)) { rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p); } asan_poison_object(obj); - gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj); } @@ -1716,31 +1868,29 @@ heap_add_freepage(rb_heap_t *heap, struct heap_page *page) { asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); GC_ASSERT(page->free_slots != 0); - if (page->freelist) { - page->free_next = heap->free_pages; - heap->free_pages = page; - } + GC_ASSERT(page->freelist != NULL); + + page->free_next = heap->free_pages; + heap->free_pages = page; + + RUBY_DEBUG_LOG("page:%p freelist:%p", (void *)page, (void *)page->freelist); + asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); } #if GC_ENABLE_INCREMENTAL_MARK -static inline int +static inline void heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page) { asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - if (page->freelist) { - page->free_next = heap->pooled_pages; - heap->pooled_pages = page; - objspace->rincgc.pooled_slots += page->free_slots; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + GC_ASSERT(page->free_slots != 0); + GC_ASSERT(page->freelist != NULL); - return TRUE; - } - else { - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + page->free_next = heap->pooled_pages; + heap->pooled_pages = page; + objspace->rincgc.pooled_slots += page->free_slots; - return FALSE; - } + asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); } #endif @@ -1752,14 +1902,14 @@ heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pag heap->total_slots -= page->total_slots; } -static void rb_aligned_free(void *ptr); +static void rb_aligned_free(void *ptr, size_t size); static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page) { heap_allocated_pages--; objspace->profile.total_freed_pages++; - rb_aligned_free(GET_PAGE_BODY(page->start)); + rb_aligned_free(GET_PAGE_BODY(page->start), HEAP_PAGE_SIZE); free(page); } @@ -1768,33 +1918,48 @@ heap_pages_free_unused_pages(rb_objspace_t *objspace) { size_t i, j; - if (!list_empty(&heap_tomb->pages)) { - for (i = j = 1; j < heap_allocated_pages; i++) { - struct heap_page *page = heap_pages_sorted[i]; + bool has_pages_in_tomb_heap = FALSE; + for (i = 0; i < SIZE_POOL_COUNT; i++) { + if (!list_empty(&SIZE_POOL_TOMB_HEAP(&size_pools[i])->pages)) { + has_pages_in_tomb_heap = TRUE; + break; + } + } + + if (has_pages_in_tomb_heap) { + for (i = j = 1; j < heap_allocated_pages; i++) { + struct heap_page *page = heap_pages_sorted[i]; + + if (page->flags.in_tomb && page->free_slots == page->total_slots) { + heap_unlink_page(objspace, SIZE_POOL_TOMB_HEAP(page->size_pool), page); + heap_page_free(objspace, page); + } + else { + if (i != j) { + heap_pages_sorted[j] = page; + } + j++; + } + } + + struct heap_page *hipage = heap_pages_sorted[heap_allocated_pages - 1]; + uintptr_t himem = (uintptr_t)hipage->start + (hipage->total_slots * hipage->slot_size); + GC_ASSERT(himem <= (uintptr_t)heap_pages_himem); + heap_pages_himem = (RVALUE *)himem; - if (page->flags.in_tomb && page->free_slots == page->total_slots) { - heap_unlink_page(objspace, heap_tomb, page); - heap_page_free(objspace, page); - } - else { - if (i != j) { - heap_pages_sorted[j] = page; - } - j++; - } - } GC_ASSERT(j == heap_allocated_pages); } } static struct heap_page * -heap_page_allocate(rb_objspace_t *objspace) +heap_page_allocate(rb_objspace_t *objspace, rb_size_pool_t *size_pool) { - RVALUE *start, *end, *p; + uintptr_t start, end, p; struct heap_page *page; struct heap_page_body *page_body = 0; - size_t hi, lo, mid; - int limit = HEAP_PAGE_OBJ_LIMIT; + uintptr_t hi, lo, mid; + size_t stride = size_pool->slot_size; + unsigned int limit = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)))/(int)stride; /* assign heap_page body (contains heap_page_header and RVALUEs) */ page_body = (struct heap_page_body *)rb_aligned_malloc(HEAP_PAGE_ALIGN, HEAP_PAGE_SIZE); @@ -1805,31 +1970,44 @@ heap_page_allocate(rb_objspace_t *objspace) /* assign heap_page entry */ page = calloc1(sizeof(struct heap_page)); if (page == 0) { - rb_aligned_free(page_body); + rb_aligned_free(page_body, HEAP_PAGE_SIZE); rb_memerror(); } /* adjust obj_limit (object number available in this page) */ - start = (RVALUE*)((VALUE)page_body + sizeof(struct heap_page_header)); + start = (uintptr_t)((VALUE)page_body + sizeof(struct heap_page_header)); + if ((VALUE)start % sizeof(RVALUE) != 0) { - int delta = (int)(sizeof(RVALUE) - ((VALUE)start % sizeof(RVALUE))); - start = (RVALUE*)((VALUE)start + delta); - limit = (HEAP_PAGE_SIZE - (int)((VALUE)start - (VALUE)page_body))/(int)sizeof(RVALUE); + int delta = (int)sizeof(RVALUE) - (start % (int)sizeof(RVALUE)); + start = start + delta; + GC_ASSERT(NUM_IN_PAGE(start) == 0 || NUM_IN_PAGE(start) == 1); + + /* Find a num in page that is evenly divisible by `stride`. + * This is to ensure that objects are aligned with bit planes. + * In other words, ensure there are an even number of objects + * per bit plane. */ + if (NUM_IN_PAGE(start) == 1) { + start += stride - sizeof(RVALUE); + } + + GC_ASSERT(NUM_IN_PAGE(start) * sizeof(RVALUE) % stride == 0); + + limit = (HEAP_PAGE_SIZE - (int)(start - (uintptr_t)page_body))/(int)stride; } - end = start + limit; + end = start + (limit * (int)stride); /* setup heap_pages_sorted */ lo = 0; - hi = heap_allocated_pages; + hi = (uintptr_t)heap_allocated_pages; while (lo < hi) { struct heap_page *mid_page; mid = (lo + hi) / 2; mid_page = heap_pages_sorted[mid]; - if (mid_page->start < start) { + if ((uintptr_t)mid_page->start < start) { lo = mid + 1; } - else if (mid_page->start > start) { + else if ((uintptr_t)mid_page->start > start) { hi = mid; } else { @@ -1837,7 +2015,7 @@ heap_page_allocate(rb_objspace_t *objspace) } } - if (hi < heap_allocated_pages) { + if (hi < (uintptr_t)heap_allocated_pages) { MEMMOVE(&heap_pages_sorted[hi+1], &heap_pages_sorted[hi], struct heap_page_header*, heap_allocated_pages - hi); } @@ -1845,8 +2023,8 @@ heap_page_allocate(rb_objspace_t *objspace) heap_allocated_pages++; - GC_ASSERT(heap_eden->total_pages + heap_allocatable_pages <= heap_pages_sorted_length); - GC_ASSERT(heap_eden->total_pages + heap_tomb->total_pages == heap_allocated_pages - 1); + GC_ASSERT(heap_eden_total_pages(objspace) + heap_allocatable_pages(objspace) <= heap_pages_sorted_length); + GC_ASSERT(heap_eden_total_pages(objspace) + heap_tomb_total_pages(objspace) == heap_allocated_pages - 1); GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length); objspace->profile.total_allocated_pages++; @@ -1856,14 +2034,16 @@ heap_page_allocate(rb_objspace_t *objspace) heap_allocated_pages, heap_pages_sorted_length); } - if (heap_pages_lomem == 0 || heap_pages_lomem > start) heap_pages_lomem = start; - if (heap_pages_himem < end) heap_pages_himem = end; + if (heap_pages_lomem == 0 || (uintptr_t)heap_pages_lomem > start) heap_pages_lomem = (RVALUE *)start; + if ((uintptr_t)heap_pages_himem < end) heap_pages_himem = (RVALUE *)end; - page->start = start; + page->start = (RVALUE *)start; page->total_slots = limit; + page->slot_size = size_pool->slot_size; + page->size_pool = size_pool; page_body->header.page = page; - for (p = start; p != end; p++) { + for (p = start; p != end; p += stride) { gc_report(3, objspace, "assign_heap_page: %p is added to freelist\n", (void *)p); heap_page_add_freeobj(objspace, page, (VALUE)p); } @@ -1874,14 +2054,14 @@ heap_page_allocate(rb_objspace_t *objspace) } static struct heap_page * -heap_page_resurrect(rb_objspace_t *objspace) +heap_page_resurrect(rb_objspace_t *objspace, rb_size_pool_t *size_pool) { struct heap_page *page = 0, *next; - list_for_each_safe(&heap_tomb->pages, page, next, page_node) { + list_for_each_safe(&SIZE_POOL_TOMB_HEAP(size_pool)->pages, page, next, page_node) { asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); if (page->freelist != NULL) { - heap_unlink_page(objspace, heap_tomb, page); + heap_unlink_page(objspace, &size_pool->tomb_heap, page); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); return page; } @@ -1891,60 +2071,64 @@ heap_page_resurrect(rb_objspace_t *objspace) } static struct heap_page * -heap_page_create(rb_objspace_t *objspace) +heap_page_create(rb_objspace_t *objspace, rb_size_pool_t *size_pool) { struct heap_page *page; const char *method = "recycle"; - heap_allocatable_pages--; + size_pool->allocatable_pages--; - page = heap_page_resurrect(objspace); + page = heap_page_resurrect(objspace, size_pool); if (page == NULL) { - page = heap_page_allocate(objspace); + page = heap_page_allocate(objspace, size_pool); method = "allocate"; } - if (0) fprintf(stderr, "heap_page_create: %s - %p, heap_allocated_pages: %d, heap_allocated_pages: %d, tomb->total_pages: %d\n", - method, (void *)page, (int)heap_pages_sorted_length, (int)heap_allocated_pages, (int)heap_tomb->total_pages); + if (0) fprintf(stderr, "heap_page_create: %s - %p, " + "heap_allocated_pages: %"PRIdSIZE", " + "heap_allocated_pages: %"PRIdSIZE", " + "tomb->total_pages: %"PRIdSIZE"\n", + method, (void *)page, heap_pages_sorted_length, heap_allocated_pages, SIZE_POOL_TOMB_HEAP(size_pool)->total_pages); return page; } static void -heap_add_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page) +heap_add_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, struct heap_page *page) { - page->flags.in_tomb = (heap == heap_tomb); - list_add(&heap->pages, &page->page_node); + /* Adding to eden heap during incremental sweeping is forbidden */ + GC_ASSERT(!(heap == SIZE_POOL_EDEN_HEAP(size_pool) && heap->sweeping_page)); + page->flags.in_tomb = (heap == SIZE_POOL_TOMB_HEAP(size_pool)); + list_add_tail(&heap->pages, &page->page_node); heap->total_pages++; heap->total_slots += page->total_slots; } static void -heap_assign_page(rb_objspace_t *objspace, rb_heap_t *heap) +heap_assign_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { - struct heap_page *page = heap_page_create(objspace); - heap_add_page(objspace, heap, page); + struct heap_page *page = heap_page_create(objspace, size_pool); + heap_add_page(objspace, size_pool, heap, page); heap_add_freepage(heap, page); } static void -heap_add_pages(rb_objspace_t *objspace, rb_heap_t *heap, size_t add) +heap_add_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, size_t add) { size_t i; - heap_allocatable_pages_set(objspace, add); + size_pool_allocatable_pages_set(objspace, size_pool, add); for (i = 0; i < add; i++) { - heap_assign_page(objspace, heap); + heap_assign_page(objspace, size_pool, heap); } - GC_ASSERT(heap_allocatable_pages == 0); + GC_ASSERT(size_pool->allocatable_pages == 0); } static size_t -heap_extend_pages(rb_objspace_t *objspace, size_t free_slots, size_t total_slots) +heap_extend_pages(rb_objspace_t *objspace, size_t free_slots, size_t total_slots, size_t used) { double goal_ratio = gc_params.heap_free_slots_goal_ratio; - size_t used = heap_allocated_pages + heap_allocatable_pages; size_t next_used; if (goal_ratio == 0.0) { @@ -1976,108 +2160,49 @@ heap_extend_pages(rb_objspace_t *objspace, size_t free_slots, size_t total_slots if (next_used > max_used) next_used = max_used; } - return next_used - used; -} - -static void -heap_set_increment(rb_objspace_t *objspace, size_t additional_pages) -{ - size_t used = heap_eden->total_pages; - size_t next_used_limit = used + additional_pages; - - if (next_used_limit == heap_allocated_pages) next_used_limit++; - - heap_allocatable_pages_set(objspace, next_used_limit - used); + size_t extend_page_count = next_used - used; + /* Extend by at least 1 page. */ + if (extend_page_count == 0) extend_page_count = 1; - gc_report(1, objspace, "heap_set_increment: heap_allocatable_pages is %d\n", (int)heap_allocatable_pages); + return extend_page_count; } static int -heap_increment(rb_objspace_t *objspace, rb_heap_t *heap) +heap_increment(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { - if (heap_allocatable_pages > 0) { - gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %d, heap_pages_inc: %d, heap->total_pages: %d\n", - (int)heap_pages_sorted_length, (int)heap_allocatable_pages, (int)heap->total_pages); + if (size_pool->allocatable_pages > 0) { + gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %"PRIdSIZE", " + "heap_pages_inc: %"PRIdSIZE", heap->total_pages: %"PRIdSIZE"\n", + heap_pages_sorted_length, size_pool->allocatable_pages, heap->total_pages); - GC_ASSERT(heap_allocatable_pages + heap_eden->total_pages <= heap_pages_sorted_length); + GC_ASSERT(heap_allocatable_pages(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length); GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length); - heap_assign_page(objspace, heap); + heap_assign_page(objspace, size_pool, heap); return TRUE; } return FALSE; } static void -heap_prepare(rb_objspace_t *objspace, rb_heap_t *heap) +heap_prepare(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { GC_ASSERT(heap->free_pages == NULL); - if (is_lazy_sweeping(heap)) { - gc_sweep_continue(objspace, heap); + if (is_lazy_sweeping(objspace)) { + gc_sweep_continue(objspace, size_pool, heap); } else if (is_incremental_marking(objspace)) { - gc_marks_continue(objspace, heap); + gc_marks_continue(objspace, size_pool, heap); } if (heap->free_pages == NULL && - (will_be_incremental_marking(objspace) || heap_increment(objspace, heap) == FALSE) && + (will_be_incremental_marking(objspace) || heap_increment(objspace, size_pool, heap) == FALSE) && gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) { rb_memerror(); } } -static RVALUE * -heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap) -{ - struct heap_page *page; - RVALUE *p; - - while (heap->free_pages == NULL) { - heap_prepare(objspace, heap); - } - page = heap->free_pages; - heap->free_pages = page->free_next; - heap->using_page = page; - - GC_ASSERT(page->free_slots != 0); - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - p = page->freelist; - page->freelist = NULL; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); - page->free_slots = 0; - asan_unpoison_object((VALUE)p, true); - return p; -} - -static inline VALUE -heap_get_freeobj_head(rb_objspace_t *objspace, rb_heap_t *heap) -{ - RVALUE *p = heap->freelist; - if (LIKELY(p != NULL)) { - heap->freelist = p->as.free.next; - } - asan_unpoison_object((VALUE)p, true); - return (VALUE)p; -} - -static inline VALUE -heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap) -{ - RVALUE *p = heap->freelist; - - while (1) { - if (LIKELY(p != NULL)) { - asan_unpoison_object((VALUE)p, true); - heap->freelist = p->as.free.next; - return (VALUE)p; - } - else { - p = heap_get_freeobj_from_next_freepage(objspace, heap); - } - } -} - void rb_objspace_set_event_hook(const rb_event_flag_t event) { @@ -2101,68 +2226,72 @@ gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb #define gc_event_hook_available_p(objspace) ((objspace)->flags.has_hook) #define gc_event_hook_needed_p(objspace, event) ((objspace)->hook_events & (event)) -#define gc_event_hook(objspace, event, data) do { \ +#define gc_event_hook_prep(objspace, event, data, prep) do { \ if (UNLIKELY(gc_event_hook_needed_p(objspace, event))) { \ + prep; \ gc_event_hook_body(GET_EC(), (objspace), (event), (data)); \ } \ } while (0) +#define gc_event_hook(objspace, event, data) gc_event_hook_prep(objspace, event, data, (void)0) + static inline VALUE -newobj_init(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, rb_objspace_t *objspace, VALUE obj) +newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, VALUE obj) { #if !__has_feature(memory_sanitizer) GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); GC_ASSERT((flags & FL_WB_PROTECTED) == 0); #endif + RVALUE *p = RANY(obj); + p->as.basic.flags = flags; + *((VALUE *)&p->as.basic.klass) = klass; - /* OBJSETUP */ - struct RVALUE buf = { - .as = { - .values = { - .basic = { - .flags = flags, - .klass = klass, - }, - .v1 = v1, - .v2 = v2, - .v3 = v3, - }, - }, - }; - MEMCPY(RANY(obj), &buf, RVALUE, 1); +#if RACTOR_CHECK_MODE + rb_ractor_setup_belonging(obj); +#endif #if RGENGC_CHECK_MODE - GC_ASSERT(RVALUE_MARKED(obj) == FALSE); - GC_ASSERT(RVALUE_MARKING(obj) == FALSE); - GC_ASSERT(RVALUE_OLD_P(obj) == FALSE); - GC_ASSERT(RVALUE_WB_UNPROTECTED(obj) == FALSE); + p->as.values.v1 = p->as.values.v2 = p->as.values.v3 = 0; - if (flags & FL_PROMOTED1) { - if (RVALUE_AGE(obj) != 2) rb_bug("newobj: %s of age (%d) != 2.", obj_info(obj), RVALUE_AGE(obj)); - } - else { - if (RVALUE_AGE(obj) > 0) rb_bug("newobj: %s of age (%d) > 0.", obj_info(obj), RVALUE_AGE(obj)); + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + check_rvalue_consistency(obj); + + GC_ASSERT(RVALUE_MARKED(obj) == FALSE); + GC_ASSERT(RVALUE_MARKING(obj) == FALSE); + GC_ASSERT(RVALUE_OLD_P(obj) == FALSE); + GC_ASSERT(RVALUE_WB_UNPROTECTED(obj) == FALSE); + + if (flags & FL_PROMOTED1) { + if (RVALUE_AGE(obj) != 2) rb_bug("newobj: %s of age (%d) != 2.", obj_info(obj), RVALUE_AGE(obj)); + } + else { + if (RVALUE_AGE(obj) > 0) rb_bug("newobj: %s of age (%d) > 0.", obj_info(obj), RVALUE_AGE(obj)); + } + if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj)); } - if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj)); + RB_VM_LOCK_LEAVE_NO_BARRIER(); #endif -#if USE_RGENGC if (UNLIKELY(wb_protected == FALSE)) { - MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); + ASSERT_vm_locking(); + MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); } -#endif + + // TODO: make it atomic, or ractor local + objspace->total_allocated_objects++; #if RGENGC_PROFILE if (wb_protected) { - objspace->profile.total_generated_normal_object_count++; + objspace->profile.total_generated_normal_object_count++; #if RGENGC_PROFILE >= 2 - objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++; + objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++; #endif } else { - objspace->profile.total_generated_shady_object_count++; + objspace->profile.total_generated_shady_object_count++; #if RGENGC_PROFILE >= 2 - objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++; + objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++; #endif } #endif @@ -2172,77 +2301,220 @@ newobj_init(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_prote GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */ #endif - objspace->total_allocated_objects++; - gc_report(5, objspace, "newobj: %s\n", obj_info(obj)); #if RGENGC_OLD_NEWOBJ_CHECK > 0 { - static int newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK; + static int newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK; - if (!is_incremental_marking(objspace) && - flags & FL_WB_PROTECTED && /* do not promote WB unprotected objects */ - ! RB_TYPE_P(obj, T_ARRAY)) { /* array.c assumes that allocated objects are new */ - if (--newobj_cnt == 0) { - newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK; + if (!is_incremental_marking(objspace) && + flags & FL_WB_PROTECTED && /* do not promote WB unprotected objects */ + ! RB_TYPE_P(obj, T_ARRAY)) { /* array.c assumes that allocated objects are new */ + if (--newobj_cnt == 0) { + newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK; - gc_mark_set(objspace, obj); - RVALUE_AGE_SET_OLD(objspace, obj); + gc_mark_set(objspace, obj); + RVALUE_AGE_SET_OLD(objspace, obj); - rb_gc_writebarrier_remember(obj); - } - } + rb_gc_writebarrier_remember(obj); + } + } } #endif - check_rvalue_consistency(obj); + // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj)); return obj; } +static inline void heap_add_freepage(rb_heap_t *heap, struct heap_page *page); +static struct heap_page *heap_next_freepage(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap); +static inline void ractor_set_cache(rb_ractor_t *cr, struct heap_page *page, size_t size_pool_idx); + +size_t +rb_gc_obj_slot_size(VALUE obj) +{ + return GET_HEAP_PAGE(obj)->slot_size; +} + +static inline size_t +size_pool_slot_size(unsigned char pool_id) +{ + GC_ASSERT(pool_id < SIZE_POOL_COUNT); + + size_t slot_size = (1 << pool_id) * sizeof(RVALUE); + +#if RGENGC_CHECK_MODE + rb_objspace_t *objspace = &rb_objspace; + GC_ASSERT(size_pools[pool_id].slot_size == (short)slot_size); +#endif + + return slot_size; +} + +bool +rb_gc_size_allocatable_p(size_t size) +{ + return size <= size_pool_slot_size(SIZE_POOL_COUNT - 1); +} + static inline VALUE -newobj_slowpath(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace, int wb_protected) +ractor_cached_free_region(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx) +{ + rb_ractor_newobj_size_pool_cache_t *cache = &cr->newobj_cache.size_pool_caches[size_pool_idx]; + RVALUE *p = cache->freelist; + + if (p) { + VALUE obj = (VALUE)p; + cache->freelist = p->as.free.next; + asan_unpoison_object(obj, true); +#if RGENGC_CHECK_MODE + // zero clear + MEMZERO((char *)obj, char, size_pool_slot_size(size_pool_idx)); +#endif + return obj; + } + else { + return Qfalse; + } +} + +static struct heap_page * +heap_next_freepage(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) +{ + ASSERT_vm_locking(); + + struct heap_page *page; + + while (heap->free_pages == NULL) { + heap_prepare(objspace, size_pool, heap); + } + page = heap->free_pages; + heap->free_pages = page->free_next; + + GC_ASSERT(page->free_slots != 0); + RUBY_DEBUG_LOG("page:%p freelist:%p cnt:%d", (void *)page, (void *)page->freelist, page->free_slots); + + asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + + return page; +} + +static inline void +ractor_set_cache(rb_ractor_t *cr, struct heap_page *page, size_t size_pool_idx) +{ + gc_report(3, &rb_objspace, "ractor_set_cache: Using page %p\n", (void *)GET_PAGE_BODY(page->start)); + + rb_ractor_newobj_size_pool_cache_t *cache = &cr->newobj_cache.size_pool_caches[size_pool_idx]; + + cache->using_page = page; + cache->freelist = page->freelist; + page->free_slots = 0; + page->freelist = NULL; + + asan_unpoison_object((VALUE)cache->freelist, false); + GC_ASSERT(RB_TYPE_P((VALUE)cache->freelist, T_NONE)); + asan_poison_object((VALUE)cache->freelist); +} + +static inline void +ractor_cache_slots(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx) +{ + ASSERT_vm_locking(); + + rb_size_pool_t *size_pool = &size_pools[size_pool_idx]; + struct heap_page *page = heap_next_freepage(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); + + ractor_set_cache(cr, page, size_pool_idx); +} + +static inline VALUE +newobj_fill(VALUE obj, VALUE v1, VALUE v2, VALUE v3) +{ + RVALUE *p = (RVALUE *)obj; + p->as.values.v1 = v1; + p->as.values.v2 = v2; + p->as.values.v3 = v3; + return obj; +} + +static inline size_t +size_pool_idx_for_size(size_t size) +{ +#if USE_RVARGC + size_t slot_count = CEILDIV(size, sizeof(RVALUE)); + + /* size_pool_idx is ceil(log2(slot_count)) */ + size_t size_pool_idx = 64 - nlz_int64(slot_count - 1); + if (size_pool_idx >= SIZE_POOL_COUNT) { + rb_bug("size_pool_idx_for_size: allocation size too large"); + } + + return size_pool_idx; +#else + GC_ASSERT(size <= sizeof(RVALUE)); + return 0; +#endif +} + +ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx)); + +static inline VALUE +newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx) { VALUE obj; + unsigned int lev; - if (UNLIKELY(during_gc || ruby_gc_stressful)) { - if (during_gc) { - dont_gc = 1; - during_gc = 0; - rb_bug("object allocation during garbage collection phase"); - } + RB_VM_LOCK_ENTER_CR_LEV(cr, &lev); + { + if (UNLIKELY(during_gc || ruby_gc_stressful)) { + if (during_gc) { + dont_gc_on(); + during_gc = 0; + rb_bug("object allocation during garbage collection phase"); + } - if (ruby_gc_stressful) { - if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) { - rb_memerror(); - } - } + if (ruby_gc_stressful) { + if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) { + rb_memerror(); + } + } + } + + // allocate new slot + while ((obj = ractor_cached_free_region(objspace, cr, size_pool_idx)) == Qfalse) { + ractor_cache_slots(objspace, cr, size_pool_idx); + } + GC_ASSERT(obj != 0); + newobj_init(klass, flags, wb_protected, objspace, obj); + + gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_fill(obj, 0, 0, 0)); } + RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev); - obj = heap_get_freeobj(objspace, heap_eden); - newobj_init(klass, flags, v1, v2, v3, wb_protected, objspace, obj); - gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj); return obj; } -NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace)); -NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace)); +NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags, + rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)); +NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, + rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)); static VALUE -newobj_slowpath_wb_protected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace) +newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx) { - return newobj_slowpath(klass, flags, v1, v2, v3, objspace, TRUE); + return newobj_slowpath(klass, flags, objspace, cr, TRUE, size_pool_idx); } static VALUE -newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace) +newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx) { - return newobj_slowpath(klass, flags, v1, v2, v3, objspace, FALSE); + return newobj_slowpath(klass, flags, objspace, cr, FALSE, size_pool_idx); } static inline VALUE -newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected) +newobj_of0(VALUE klass, VALUE flags, int wb_protected, rb_ractor_t *cr, size_t alloc_size) { - rb_objspace_t *objspace = &rb_objspace; VALUE obj; + rb_objspace_t *objspace = &rb_objspace; RB_DEBUG_COUNTER_INC(obj_newobj); (void)RB_DEBUG_COUNTER_INC_IF(obj_newobj_wb_unprotected, !wb_protected); @@ -2255,33 +2527,61 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protect } } #endif - if (!(during_gc || - ruby_gc_stressful || - gc_event_hook_available_p(objspace)) && - (obj = heap_get_freeobj_head(objspace, heap_eden)) != Qfalse) { - return newobj_init(klass, flags, v1, v2, v3, wb_protected, objspace, obj); + + size_t size_pool_idx = size_pool_idx_for_size(alloc_size); + + if ((!UNLIKELY(during_gc || + ruby_gc_stressful || + gc_event_hook_available_p(objspace)) && + wb_protected && + (obj = ractor_cached_free_region(objspace, cr, size_pool_idx)) != Qfalse)) { + + newobj_init(klass, flags, wb_protected, objspace, obj); } else { RB_DEBUG_COUNTER_INC(obj_newobj_slowpath); - return wb_protected ? - newobj_slowpath_wb_protected(klass, flags, v1, v2, v3, objspace) : - newobj_slowpath_wb_unprotected(klass, flags, v1, v2, v3, objspace); + obj = wb_protected ? + newobj_slowpath_wb_protected(klass, flags, objspace, cr, size_pool_idx) : + newobj_slowpath_wb_unprotected(klass, flags, objspace, cr, size_pool_idx); } + + return obj; +} + +static inline VALUE +newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, size_t alloc_size) +{ + VALUE obj = newobj_of0(klass, flags, wb_protected, GET_RACTOR(), alloc_size); + return newobj_fill(obj, v1, v2, v3); +} + +static inline VALUE +newobj_of_cr(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, size_t alloc_size) +{ + VALUE obj = newobj_of0(klass, flags, wb_protected, cr, alloc_size); + return newobj_fill(obj, v1, v2, v3); +} + +VALUE +rb_wb_unprotected_newobj_of(VALUE klass, VALUE flags, size_t size) +{ + GC_ASSERT((flags & FL_WB_PROTECTED) == 0); + return newobj_of(klass, flags, 0, 0, 0, FALSE, size); } VALUE -rb_wb_unprotected_newobj_of(VALUE klass, VALUE flags) +rb_wb_protected_newobj_of(VALUE klass, VALUE flags, size_t size) { GC_ASSERT((flags & FL_WB_PROTECTED) == 0); - return newobj_of(klass, flags, 0, 0, 0, FALSE); + return newobj_of(klass, flags, 0, 0, 0, TRUE, size); } VALUE -rb_wb_protected_newobj_of(VALUE klass, VALUE flags) +rb_ec_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags, size_t size) { GC_ASSERT((flags & FL_WB_PROTECTED) == 0); - return newobj_of(klass, flags, 0, 0, 0, TRUE); + return newobj_of_cr(rb_ec_ractor_ptr(ec), klass, flags, 0, 0, 0, TRUE, size); } /* for compatibility */ @@ -2289,33 +2589,72 @@ rb_wb_protected_newobj_of(VALUE klass, VALUE flags) VALUE rb_newobj(void) { - return newobj_of(0, T_NONE, 0, 0, 0, FALSE); + return newobj_of(0, T_NONE, 0, 0, 0, FALSE, sizeof(RVALUE)); } VALUE rb_newobj_of(VALUE klass, VALUE flags) { - return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED); + if ((flags & RUBY_T_MASK) == T_OBJECT) { + st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass); + + VALUE obj = newobj_of(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED , Qundef, Qundef, Qundef, flags & FL_WB_PROTECTED, sizeof(RVALUE)); + + if (index_tbl && index_tbl->num_entries > ROBJECT_EMBED_LEN_MAX) { + rb_init_iv_list(obj); + } + return obj; + } + else { + return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, sizeof(RVALUE)); + } } #define UNEXPECTED_NODE(func) \ rb_bug(#func"(): GC does not handle T_NODE 0x%x(%p) 0x%"PRIxVALUE, \ BUILTIN_TYPE(obj), (void*)(obj), RBASIC(obj)->flags) +const char * +rb_imemo_name(enum imemo_type type) +{ + // put no default case to get a warning if an imemo type is missing + switch (type) { +#define IMEMO_NAME(x) case imemo_##x: return #x; + IMEMO_NAME(env); + IMEMO_NAME(cref); + IMEMO_NAME(svar); + IMEMO_NAME(throw_data); + IMEMO_NAME(ifunc); + IMEMO_NAME(memo); + IMEMO_NAME(ment); + IMEMO_NAME(iseq); + IMEMO_NAME(tmpbuf); + IMEMO_NAME(ast); + IMEMO_NAME(parser_strterm); + IMEMO_NAME(callinfo); + IMEMO_NAME(callcache); + IMEMO_NAME(constcache); +#undef IMEMO_NAME + } + return "unknown"; +} + #undef rb_imemo_new VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0) { + size_t size = sizeof(RVALUE); VALUE flags = T_IMEMO | (type << FL_USHIFT); - return newobj_of(v0, flags, v1, v2, v3, TRUE); + return newobj_of(v0, flags, v1, v2, v3, TRUE, size); } static VALUE rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0) { + size_t size = sizeof(RVALUE); VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT); - return newobj_of(v0, flags, v1, v2, v3, FALSE); + return newobj_of(v0, flags, v1, v2, v3, FALSE, size); } static VALUE @@ -2375,17 +2714,40 @@ rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, #endif VALUE -rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) +rb_class_allocate_instance(VALUE klass) { - if (klass) Check_Type(klass, T_CLASS); - return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE); + st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass); + + VALUE flags = T_OBJECT | ROBJECT_EMBED; + + VALUE obj = newobj_of(klass, flags, Qundef, Qundef, Qundef, RGENGC_WB_PROTECTED_OBJECT, sizeof(RVALUE)); + + if (index_tbl && index_tbl->num_entries > ROBJECT_EMBED_LEN_MAX) { + rb_init_iv_list(obj); + } + + return obj; } -#undef rb_data_object_alloc -RUBY_ALIAS_FUNCTION(rb_data_object_alloc(VALUE klass, void *datap, - RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree), - rb_data_object_wrap, (klass, datap, dmark, dfree)) +static inline void +rb_data_object_check(VALUE klass) +{ + if (klass != rb_cObject && (rb_get_alloc_func(klass) == rb_class_allocate_instance)) { + rb_undef_alloc_func(klass); +#if RUBY_VERSION_SINCE(3, 2) + RBIMPL_TODO("enable the warning at this release"); + rb_warn("undefining the allocator of T_DATA class %"PRIsVALUE, klass); +#endif + } +} +VALUE +rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) +{ + RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1); + if (klass) rb_data_object_check(klass); + return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE, sizeof(RVALUE)); +} VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) @@ -2398,15 +2760,11 @@ rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type) { - if (klass) Check_Type(klass, T_CLASS); - return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED); + RBIMPL_NONNULL_ARG(type); + if (klass) rb_data_object_check(klass); + return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED, sizeof(RVALUE)); } -#undef rb_data_typed_object_alloc -RUBY_ALIAS_FUNCTION(rb_data_typed_object_alloc(VALUE klass, void *datap, - const rb_data_type_t *type), - rb_data_typed_object_wrap, (klass, datap, type)) - VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type) { @@ -2462,13 +2820,15 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr) mid = (lo + hi) / 2; page = heap_pages_sorted[mid]; if (page->start <= p) { - if (p < page->start + page->total_slots) { + if ((uintptr_t)p < ((uintptr_t)page->start + (page->total_slots * page->slot_size))) { RB_DEBUG_COUNTER_INC(gc_isptr_maybe); if (page->flags.in_tomb) { return FALSE; } else { + if ((NUM_IN_PAGE(p) * sizeof(RVALUE)) % page->slot_size != 0) return FALSE; + return TRUE; } } @@ -2496,6 +2856,145 @@ rb_free_const_table(struct rb_id_table *tbl) rb_id_table_free(tbl); } +static int +free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data) +{ + xfree((void *)value); + return ST_CONTINUE; +} + +static void +iv_index_tbl_free(struct st_table *tbl) +{ + st_foreach(tbl, free_iv_index_tbl_free_i, 0); + st_free_table(tbl); +} + +// alive: if false, target pointers can be freed already. +// To check it, we need objspace parameter. +static void +vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, rb_objspace_t *objspace, VALUE klass) +{ + if (ccs->entries) { + for (int i=0; ilen; i++) { + const struct rb_callcache *cc = ccs->entries[i].cc; + if (!alive) { + void *ptr = asan_poisoned_object_p((VALUE)cc); + asan_unpoison_object((VALUE)cc, false); + // ccs can be free'ed. + if (is_pointer_to_heap(objspace, (void *)cc) && + IMEMO_TYPE_P(cc, imemo_callcache) && + cc->klass == klass) { + // OK. maybe target cc. + } + else { + if (ptr) { + asan_poison_object((VALUE)cc); + } + continue; + } + if (ptr) { + asan_poison_object((VALUE)cc); + } + } + vm_cc_invalidate(cc); + } + ruby_xfree(ccs->entries); + } + ruby_xfree(ccs); +} + +void +rb_vm_ccs_free(struct rb_class_cc_entries *ccs) +{ + RB_DEBUG_COUNTER_INC(ccs_free); + vm_ccs_free(ccs, TRUE, NULL, Qundef); +} + +struct cc_tbl_i_data { + rb_objspace_t *objspace; + VALUE klass; + bool alive; +}; + +static enum rb_id_table_iterator_result +cc_table_mark_i(ID id, VALUE ccs_ptr, void *data_ptr) +{ + struct cc_tbl_i_data *data = data_ptr; + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr; + VM_ASSERT(vm_ccs_p(ccs)); + VM_ASSERT(id == ccs->cme->called_id); + + if (METHOD_ENTRY_INVALIDATED(ccs->cme)) { + rb_vm_ccs_free(ccs); + return ID_TABLE_DELETE; + } + else { + gc_mark(data->objspace, (VALUE)ccs->cme); + + for (int i=0; ilen; i++) { + VM_ASSERT(data->klass == ccs->entries[i].cc->klass); + VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme)); + + gc_mark(data->objspace, (VALUE)ccs->entries[i].ci); + gc_mark(data->objspace, (VALUE)ccs->entries[i].cc); + } + return ID_TABLE_CONTINUE; + } +} + +static void +cc_table_mark(rb_objspace_t *objspace, VALUE klass) +{ + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + if (cc_tbl) { + struct cc_tbl_i_data data = { + .objspace = objspace, + .klass = klass, + }; + rb_id_table_foreach(cc_tbl, cc_table_mark_i, &data); + } +} + +static enum rb_id_table_iterator_result +cc_table_free_i(VALUE ccs_ptr, void *data_ptr) +{ + struct cc_tbl_i_data *data = data_ptr; + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr; + VM_ASSERT(vm_ccs_p(ccs)); + vm_ccs_free(ccs, data->alive, data->objspace, data->klass); + return ID_TABLE_CONTINUE; +} + +static void +cc_table_free(rb_objspace_t *objspace, VALUE klass, bool alive) +{ + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + + if (cc_tbl) { + struct cc_tbl_i_data data = { + .objspace = objspace, + .klass = klass, + .alive = alive, + }; + rb_id_table_foreach_values(cc_tbl, cc_table_free_i, &data); + rb_id_table_free(cc_tbl); + } +} + +static enum rb_id_table_iterator_result +cvar_table_free_i(VALUE value, void * ctx) +{ + xfree((void *) value); + return ID_TABLE_CONTINUE; +} + +void +rb_cc_table_free(VALUE klass) +{ + cc_table_free(&rb_objspace, klass, TRUE); +} + static inline void make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data) { @@ -2505,26 +3004,31 @@ make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *dat zombie->data = data; zombie->next = heap_pages_deferred_final; heap_pages_deferred_final = (VALUE)zombie; + + struct heap_page *page = GET_HEAP_PAGE(obj); + page->final_slots++; + heap_pages_final_slots++; } static inline void make_io_zombie(rb_objspace_t *objspace, VALUE obj) { rb_io_t *fptr = RANY(obj)->as.file.fptr; - make_zombie(objspace, obj, (void (*)(void*))rb_io_fptr_finalize, fptr); + make_zombie(objspace, obj, rb_io_fptr_finalize_internal, fptr); } static void obj_free_object_id(rb_objspace_t *objspace, VALUE obj) { - VALUE id; + ASSERT_vm_locking(); + st_data_t o = (st_data_t)obj, id; GC_ASSERT(FL_TEST(obj, FL_SEEN_OBJ_ID)); FL_UNSET(obj, FL_SEEN_OBJ_ID); - if (st_delete(objspace->obj_to_id_tbl, (st_data_t *)&obj, &id)) { + if (st_delete(objspace->obj_to_id_tbl, &o, &id)) { GC_ASSERT(id); - st_delete(objspace->id_to_obj_tbl, (st_data_t *)&id, NULL); + st_delete(objspace->id_to_obj_tbl, &id, NULL); } else { rb_bug("Object ID seen, but not in mapping table: %s\n", obj_info(obj)); @@ -2535,6 +3039,7 @@ static int obj_free(rb_objspace_t *objspace, VALUE obj) { RB_DEBUG_COUNTER_INC(obj_free); + // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj)); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_FREEOBJ, obj); @@ -2545,6 +3050,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case T_FALSE: rb_bug("obj_free() called for broken object"); break; + default: + break; } if (FL_TEST(obj, FL_EXIVAR)) { @@ -2556,7 +3063,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) obj_free_object_id(objspace, obj); } -#if USE_RGENGC if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); #if RGENGC_CHECK_MODE @@ -2566,13 +3072,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj) CHECK(RVALUE_MARKING); CHECK(RVALUE_UNCOLLECTIBLE); #undef CHECK -#endif #endif switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - if ((RANY(obj)->as.basic.flags & ROBJECT_EMBED) || - RANY(obj)->as.object.as.heap.ivptr == NULL) { + if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) { RB_DEBUG_COUNTER_INC(obj_obj_embed); } else if (ROBJ_TRANSIENT_P(obj)) { @@ -2585,8 +3089,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_MODULE: case T_CLASS: - mjit_remove_class_serial(RCLASS_SERIAL(obj)); rb_id_table_free(RCLASS_M_TBL(obj)); + cc_table_free(objspace, obj, FALSE); if (RCLASS_IV_TBL(obj)) { st_free_table(RCLASS_IV_TBL(obj)); } @@ -2594,22 +3098,19 @@ obj_free(rb_objspace_t *objspace, VALUE obj) rb_free_const_table(RCLASS_CONST_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { - st_free_table(RCLASS_IV_INDEX_TBL(obj)); + iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj)); } - if (RCLASS_EXT(obj)->subclasses) { - if (BUILTIN_TYPE(obj) == T_MODULE) { - rb_class_detach_module_subclasses(obj); - } - else { - rb_class_detach_subclasses(obj); - } - RCLASS_EXT(obj)->subclasses = NULL; + if (RCLASS_CVC_TBL(obj)) { + rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL); + rb_id_table_free(RCLASS_CVC_TBL(obj)); } + rb_class_remove_subclass_head(obj); rb_class_remove_from_module_subclasses(obj); rb_class_remove_from_super_subclasses(obj); - if (RANY(obj)->as.klass.ptr) - xfree(RANY(obj)->as.klass.ptr); - RANY(obj)->as.klass.ptr = NULL; +#if !USE_RVARGC + if (RCLASS_EXT(obj)) + xfree(RCLASS_EXT(obj)); +#endif (void)RB_DEBUG_COUNTER_INC_IF(obj_module_ptr, BUILTIN_TYPE(obj) == T_MODULE); (void)RB_DEBUG_COUNTER_INC_IF(obj_class_ptr, BUILTIN_TYPE(obj) == T_CLASS); @@ -2622,7 +3123,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_HASH: #if USE_DEBUG_COUNTER - switch RHASH_SIZE(obj) { + switch (RHASH_SIZE(obj)) { case 0: RB_DEBUG_COUNTER_INC(obj_hash_empty); break; @@ -2714,7 +3215,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) else { make_zombie(objspace, obj, dfree, data); RB_DEBUG_COUNTER_INC(obj_data_zombie); - return 1; + return FALSE; } } else { @@ -2748,7 +3249,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) if (RANY(obj)->as.file.fptr) { make_io_zombie(objspace, obj); RB_DEBUG_COUNTER_INC(obj_file_ptr); - return 1; + return FALSE; } break; case T_RATIONAL: @@ -2761,20 +3262,20 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_ICLASS: /* Basically , T_ICLASS shares table with the module */ - if (FL_TEST(obj, RICLASS_IS_ORIGIN)) { - rb_id_table_free(RCLASS_M_TBL(obj)); - } + if (RICLASS_OWNS_M_TBL_P(obj)) { + /* Method table is not shared for origin iclasses of classes */ + rb_id_table_free(RCLASS_M_TBL(obj)); + } if (RCLASS_CALLABLE_M_TBL(obj) != NULL) { rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj)); } - if (RCLASS_EXT(obj)->subclasses) { - rb_class_detach_subclasses(obj); - RCLASS_EXT(obj)->subclasses = NULL; - } + rb_class_remove_subclass_head(obj); + cc_table_free(objspace, obj, FALSE); rb_class_remove_from_module_subclasses(obj); rb_class_remove_from_super_subclasses(obj); - xfree(RANY(obj)->as.klass.ptr); - RANY(obj)->as.klass.ptr = NULL; +#if !USE_RVARGC + xfree(RCLASS_EXT(obj)); +#endif RB_DEBUG_COUNTER_INC(obj_iclass_ptr); break; @@ -2784,7 +3285,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_BIGNUM: - if (!(RBASIC(obj)->flags & BIGNUM_EMBED_FLAG) && BIGNUM_DIGITS(obj)) { + if (!BIGNUM_EMBED_P(obj) && BIGNUM_DIGITS(obj)) { xfree(BIGNUM_DIGITS(obj)); RB_DEBUG_COUNTER_INC(obj_bignum_ptr); } @@ -2859,11 +3360,17 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case imemo_parser_strterm: RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm); break; - default: - /* unreachable */ - break; + case imemo_callinfo: + RB_DEBUG_COUNTER_INC(obj_imemo_callinfo); + break; + case imemo_callcache: + RB_DEBUG_COUNTER_INC(obj_imemo_callcache); + break; + case imemo_constcache: + RB_DEBUG_COUNTER_INC(obj_imemo_constcache); + break; } - return 0; + return TRUE; default: rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE, @@ -2872,10 +3379,10 @@ obj_free(rb_objspace_t *objspace, VALUE obj) if (FL_TEST(obj, FL_FINALIZE)) { make_zombie(objspace, obj, 0, 0); - return 1; + return FALSE; } else { - return 0; + return TRUE; } } @@ -2886,9 +3393,10 @@ obj_free(rb_objspace_t *objspace, VALUE obj) static int object_id_cmp(st_data_t x, st_data_t y) { - if (RB_TYPE_P(x, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(x)) { return !rb_big_eql(x, y); - } else { + } + else { return x != y; } } @@ -2896,9 +3404,10 @@ object_id_cmp(st_data_t x, st_data_t y) static st_index_t object_id_hash(st_data_t n) { - if (RB_TYPE_P(n, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(n)) { return FIX2LONG(rb_big_hash(n)); - } else { + } + else { return st_numhash(n); } } @@ -2912,6 +3421,20 @@ Init_heap(void) { rb_objspace_t *objspace = &rb_objspace; +#if defined(HAVE_MMAP) && !HAVE_CONST_PAGE_SIZE && !defined(PAGE_MAX_SIZE) + /* Need to determine if we can use mmap at runtime. */ +# ifdef PAGE_SIZE + /* If the PAGE_SIZE macro can be used. */ + use_mmap_aligned_alloc = PAGE_SIZE <= HEAP_PAGE_SIZE; +# elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) + /* If we can use sysconf to determine the page size. */ + use_mmap_aligned_alloc = sysconf(_SC_PAGE_SIZE) <= HEAP_PAGE_SIZE; +# else + /* Otherwise we can't determine the system page size, so don't use mmap. */ + use_mmap_aligned_alloc = FALSE; +# endif +#endif + objspace->next_object_id = INT2FIX(OBJ_ID_INITIAL); objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type); objspace->obj_to_id_tbl = st_init_numtable(); @@ -2920,7 +3443,16 @@ Init_heap(void) objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min; #endif - heap_add_pages(objspace, heap_eden, gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT); + heap_add_pages(objspace, &size_pools[0], SIZE_POOL_EDEN_HEAP(&size_pools[0]), gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT); + + /* Give other size pools allocatable pages. */ + for (int i = 1; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + int multiple = size_pool->slot_size / sizeof(RVALUE); + size_pool->allocatable_pages = gc_params.heap_init_slots * multiple / HEAP_PAGE_OBJ_LIMIT; + } + heap_pages_expand_sorted(objspace); + init_mark_stack(&objspace->mark_stack); objspace->profile.invoke_time = getrusage_time(); @@ -2937,53 +3469,99 @@ Init_gc_stress(void) typedef int each_obj_callback(void *, void *, size_t, void *); -static void objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data); +static void objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected); static void objspace_reachable_objects_from_root(rb_objspace_t *, void (func)(const char *, VALUE, void *), void *); -struct each_obj_args { +struct each_obj_data { rb_objspace_t *objspace; + bool reenable_incremental; + each_obj_callback *callback; void *data; + + struct heap_page **pages[SIZE_POOL_COUNT]; + size_t pages_counts[SIZE_POOL_COUNT]; }; -static void -objspace_each_objects_without_setup(rb_objspace_t *objspace, each_obj_callback *callback, void *data) +static VALUE +objspace_each_objects_ensure(VALUE arg) { - size_t i; - struct heap_page *page; - RVALUE *pstart = NULL, *pend; - - i = 0; - while (i < heap_allocated_pages) { - while (0 < i && pstart < heap_pages_sorted[i-1]->start) i--; - while (i < heap_allocated_pages && heap_pages_sorted[i]->start <= pstart) i++; - if (heap_allocated_pages <= i) break; - - page = heap_pages_sorted[i]; + struct each_obj_data *data = (struct each_obj_data *)arg; + rb_objspace_t *objspace = data->objspace; - pstart = page->start; - pend = pstart + page->total_slots; + /* Reenable incremental GC */ + if (data->reenable_incremental) { + objspace->flags.dont_incremental = FALSE; + } - if ((*callback)(pstart, pend, sizeof(RVALUE), data)) { - break; - } + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + struct heap_page **pages = data->pages[i]; + /* pages could be NULL if an error was raised during setup (e.g. + * malloc failed due to out of memory). */ + if (pages) { + free(pages); + } } -} -static VALUE -objspace_each_objects_protected(VALUE arg) -{ - struct each_obj_args *args = (struct each_obj_args *)arg; - objspace_each_objects_without_setup(args->objspace, args->callback, args->data); return Qnil; } static VALUE -incremental_enable(VALUE _) +objspace_each_objects_try(VALUE arg) { - rb_objspace_t *objspace = &rb_objspace; + struct each_obj_data *data = (struct each_obj_data *)arg; + rb_objspace_t *objspace = data->objspace; + + /* Copy pages from all size_pools to their respective buffers. */ + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + size_t size = size_mul_or_raise(SIZE_POOL_EDEN_HEAP(size_pool)->total_pages, sizeof(struct heap_page *), rb_eRuntimeError); + + struct heap_page **pages = malloc(size); + if (!pages) rb_memerror(); + + /* Set up pages buffer by iterating over all pages in the current eden + * heap. This will be a snapshot of the state of the heap before we + * call the callback over each page that exists in this buffer. Thus it + * is safe for the callback to allocate objects without possibly entering + * an infinite loop. */ + struct heap_page *page = 0; + size_t pages_count = 0; + list_for_each(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node) { + pages[pages_count] = page; + pages_count++; + } + data->pages[i] = pages; + data->pages_counts[i] = pages_count; + GC_ASSERT(pages_count == SIZE_POOL_EDEN_HEAP(size_pool)->total_pages); + } + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + size_t pages_count = data->pages_counts[i]; + struct heap_page **pages = data->pages[i]; + + struct heap_page *page = list_top(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, struct heap_page, page_node); + for (size_t i = 0; i < pages_count; i++) { + /* If we have reached the end of the linked list then there are no + * more pages, so break. */ + if (page == NULL) break; + + /* If this page does not match the one in the buffer, then move to + * the next page in the buffer. */ + if (pages[i] != page) continue; + + uintptr_t pstart = (uintptr_t)page->start; + uintptr_t pend = pstart + (page->total_slots * size_pool->slot_size); + + if ((*data->callback)((void *)pstart, (void *)pend, size_pool->slot_size, data->data)) { + break; + } + + page = list_next(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node); + } + } - objspace->flags.dont_incremental = FALSE; return Qnil; } @@ -3018,7 +3596,7 @@ incremental_enable(VALUE _) * This means that you can not walk through all Ruby object page * including freed object page. * - * Note: On this implementation, 'stride' is same as sizeof(RVALUE). + * Note: On this implementation, 'stride' is the same as sizeof(RVALUE). * However, there are possibilities to pass variable values with * 'stride' with some reasons. You must use stride instead of * use some constant value in the iteration. @@ -3026,30 +3604,39 @@ incremental_enable(VALUE _) void rb_objspace_each_objects(each_obj_callback *callback, void *data) { - objspace_each_objects(&rb_objspace, callback, data); + objspace_each_objects(&rb_objspace, callback, data, TRUE); } static void -objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data) +objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected) { - int prev_dont_incremental = objspace->flags.dont_incremental; - - gc_rest(objspace); - objspace->flags.dont_incremental = TRUE; + /* Disable incremental GC */ + bool reenable_incremental = FALSE; + if (protected) { + reenable_incremental = !objspace->flags.dont_incremental; - if (prev_dont_incremental) { - objspace_each_objects_without_setup(objspace, callback, data); - } - else { - struct each_obj_args args = {objspace, callback, data}; - rb_ensure(objspace_each_objects_protected, (VALUE)&args, incremental_enable, Qnil); + gc_rest(objspace); + objspace->flags.dont_incremental = TRUE; } + + struct each_obj_data each_obj_data = { + .objspace = objspace, + .reenable_incremental = reenable_incremental, + + .callback = callback, + .data = data, + + .pages = {NULL}, + .pages_counts = {0}, + }; + rb_ensure(objspace_each_objects_try, (VALUE)&each_obj_data, + objspace_each_objects_ensure, (VALUE)&each_obj_data); } void rb_objspace_each_objects_without_setup(each_obj_callback *callback, void *data) { - objspace_each_objects_without_setup(&rb_objspace, callback, data); + objspace_each_objects(&rb_objspace, callback, data, FALSE); } struct os_each_struct { @@ -3066,7 +3653,7 @@ internal_object_p(VALUE obj) bool used_p = p->as.basic.flags; if (used_p) { - switch (BUILTIN_TYPE(p)) { + switch (BUILTIN_TYPE(obj)) { case T_NODE: UNEXPECTED_NODE(internal_object_p); break; @@ -3103,14 +3690,15 @@ static int os_obj_of_i(void *vstart, void *vend, size_t stride, void *data) { struct os_each_struct *oes = (struct os_each_struct *)data; - RVALUE *p = (RVALUE *)vstart, *pend = (RVALUE *)vend; - for (; p != pend; p++) { - volatile VALUE v = (VALUE)p; + VALUE v = (VALUE)vstart; + for (; v != (VALUE)vend; v += stride) { if (!internal_object_p(v)) { if (!oes->of || rb_obj_is_kind_of(v, oes->of)) { - rb_yield(v); - oes->num++; + if (!rb_multi_ractor_p() || rb_ractor_shareable_p(v)) { + rb_yield(v); + oes->num++; + } } } } @@ -3228,6 +3816,57 @@ should_be_finalizable(VALUE obj) * as an argument to aProc. If aProc is a lambda or * method, make sure it can be called with a single argument. * + * The return value is an array [0, aProc]. + * + * The two recommended patterns are to either create the finaliser proc + * in a non-instance method where it can safely capture the needed state, + * or to use a custom callable object that stores the needed state + * explicitly as instance variables. + * + * class Foo + * def initialize(data_needed_for_finalization) + * ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization)) + * end + * + * def self.create_finalizer(data_needed_for_finalization) + * proc { + * puts "finalizing #{data_needed_for_finalization}" + * } + * end + * end + * + * class Bar + * class Remover + * def initialize(data_needed_for_finalization) + * @data_needed_for_finalization = data_needed_for_finalization + * end + * + * def call(id) + * puts "finalizing #{@data_needed_for_finalization}" + * end + * end + * + * def initialize(data_needed_for_finalization) + * ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization)) + * end + * end + * + * Note that if your finalizer references the object to be + * finalized it will never be run on GC, although it will still be + * run at exit. You will get a warning if you capture the object + * to be finalized as the receiver of the finalizer. + * + * class CapturesSelf + * def initialize(name) + * ObjectSpace.define_finalizer(self, proc { + * # this finalizer will only be run on exit + * puts "finalizing #{name}" + * }) + * end + * end + * + * Also note that finalization can be unpredictable and is never guaranteed + * to be run except on exit. */ static VALUE @@ -3244,6 +3883,10 @@ define_final(int argc, VALUE *argv, VALUE os) should_be_callable(block); } + if (rb_callable_receiver(block) == obj) { + rb_warn("finalizer references object to be finalized"); + } + return define_final0(obj, block); } @@ -3256,9 +3899,6 @@ define_final0(VALUE obj, VALUE block) RBASIC(obj)->flags |= FL_FINALIZE; - block = rb_ary_new3(2, INT2FIX(0), block); - OBJ_FREEZE(block); - if (st_lookup(finalizer_table, obj, &data)) { table = (VALUE)data; @@ -3269,8 +3909,9 @@ define_final0(VALUE obj, VALUE block) for (i = 0; i < len; i++) { VALUE recv = RARRAY_AREF(table, i); - if (rb_funcall(recv, idEq, 1, block)) { - return recv; + if (rb_equal(recv, block)) { + block = recv; + goto end; } } } @@ -3282,6 +3923,9 @@ define_final0(VALUE obj, VALUE block) RBASIC_CLEAR_CLASS(table); st_add_direct(finalizer_table, obj, table); } + end: + block = rb_ary_new3(2, INT2FIX(0), block); + OBJ_FREEZE(block); return block; } @@ -3309,12 +3953,21 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj) } static VALUE -run_single_final(VALUE final, VALUE objid) +run_single_final(VALUE cmd, VALUE objid) { - const VALUE cmd = RARRAY_AREF(final, 1); return rb_check_funcall(cmd, idCall, 1, &objid); } +static void +warn_exception_in_finalizer(rb_execution_context_t *ec, VALUE final) +{ + if (final != Qundef && !NIL_P(ruby_verbose)) { + VALUE errinfo = ec->errinfo; + rb_warn("Exception in finalizer %+"PRIsVALUE, final); + rb_ec_error_print(ec, errinfo); + } +} + static void run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) { @@ -3323,28 +3976,31 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) volatile struct { VALUE errinfo; VALUE objid; + VALUE final; rb_control_frame_t *cfp; long finished; } saved; rb_execution_context_t * volatile ec = GET_EC(); #define RESTORE_FINALIZER() (\ ec->cfp = saved.cfp, \ - rb_set_errinfo(saved.errinfo)) + ec->errinfo = saved.errinfo) - saved.errinfo = rb_errinfo(); + saved.errinfo = ec->errinfo; saved.objid = rb_obj_id(obj); saved.cfp = ec->cfp; saved.finished = 0; + saved.final = Qundef; EC_PUSH_TAG(ec); state = EC_EXEC_TAG(); if (state != TAG_NONE) { ++saved.finished; /* skip failed finalizer */ + warn_exception_in_finalizer(ec, ATOMIC_VALUE_EXCHANGE(saved.final, Qundef)); } for (i = saved.finished; RESTORE_FINALIZER(), ibasic.flags = 0; - if (LIKELY(heap_pages_final_slots)) heap_pages_final_slots--; - page->final_slots--; - page->free_slots++; - heap_page_add_freeobj(objspace, GET_HEAP_PAGE(zombie), zombie); + GC_ASSERT(heap_pages_final_slots > 0); + GC_ASSERT(page->final_slots > 0); - objspace->profile.total_freed_objects++; + heap_pages_final_slots--; + page->final_slots--; + page->free_slots++; + heap_page_add_freeobj(objspace, page, zombie); + objspace->profile.total_freed_objects++; + } + RB_VM_LOCK_LEAVE(); - zombie = next_zombie; + zombie = next_zombie; } } @@ -3398,10 +4059,14 @@ static void finalize_deferred(rb_objspace_t *objspace) { VALUE zombie; + rb_execution_context_t *ec = GET_EC(); + ec->interrupt_mask |= PENDING_INTERRUPT_MASK; while ((zombie = ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) { finalize_list(objspace, zombie); } + + ec->interrupt_mask &= ~PENDING_INTERRUPT_MASK; } static void @@ -3409,6 +4074,7 @@ gc_finalize_deferred(void *dmy) { rb_objspace_t *objspace = dmy; if (ATOMIC_EXCHANGE(finalizing, 1)) return; + finalize_deferred(objspace); ATOMIC_SET(finalizing, 0); } @@ -3439,10 +4105,11 @@ force_chain_object(st_data_t key, st_data_t val, st_data_t arg) return ST_CONTINUE; } +bool rb_obj_is_main_ractor(VALUE gv); + void rb_objspace_call_finalizer(rb_objspace_t *objspace) { - RVALUE *p, *pend; size_t i; #if RGENGC_CHECK_MODE >= 2 @@ -3475,49 +4142,57 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) } /* prohibit GC because force T_DATA finalizers can break an object graph consistency */ - dont_gc = 1; + dont_gc_on(); /* running data/file finalizers are part of garbage collection */ - gc_enter(objspace, "rb_objspace_call_finalizer"); + unsigned int lock_lev; + gc_enter(objspace, gc_enter_event_finalizer, &lock_lev); /* run data/file object's finalizers */ for (i = 0; i < heap_allocated_pages; i++) { - p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->total_slots; - while (p < pend) { - void *poisoned = asan_poisoned_object_p((VALUE)p); - asan_unpoison_object((VALUE)p, false); - switch (BUILTIN_TYPE(p)) { + struct heap_page *page = heap_pages_sorted[i]; + short stride = page->slot_size; + + uintptr_t p = (uintptr_t)page->start; + uintptr_t pend = p + page->total_slots * stride; + for (; p < pend; p += stride) { + VALUE vp = (VALUE)p; + void *poisoned = asan_poisoned_object_p(vp); + asan_unpoison_object(vp, false); + switch (BUILTIN_TYPE(vp)) { case T_DATA: if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break; - if (rb_obj_is_thread((VALUE)p)) break; - if (rb_obj_is_mutex((VALUE)p)) break; - if (rb_obj_is_fiber((VALUE)p)) break; - p->as.free.flags = 0; - if (RTYPEDDATA_P(p)) { + if (rb_obj_is_thread(vp)) break; + if (rb_obj_is_mutex(vp)) break; + if (rb_obj_is_fiber(vp)) break; + if (rb_obj_is_main_ractor(vp)) break; + if (RTYPEDDATA_P(vp)) { RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree; } + RANY(p)->as.free.flags = 0; if (RANY(p)->as.data.dfree == RUBY_DEFAULT_FREE) { xfree(DATA_PTR(p)); } else if (RANY(p)->as.data.dfree) { - make_zombie(objspace, (VALUE)p, RANY(p)->as.data.dfree, RANY(p)->as.data.data); + make_zombie(objspace, vp, RANY(p)->as.data.dfree, RANY(p)->as.data.data); } break; case T_FILE: if (RANY(p)->as.file.fptr) { - make_io_zombie(objspace, (VALUE)p); + make_io_zombie(objspace, vp); } break; + default: + break; } if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(p) == T_NONE); - asan_poison_object((VALUE)p); + GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE); + asan_poison_object(vp); } - p++; } } - gc_exit(objspace, "rb_objspace_call_finalizer"); + gc_exit(objspace, gc_enter_event_finalizer, &lock_lev); if (heap_pages_deferred_final) { finalize_list(objspace, heap_pages_deferred_final); @@ -3528,39 +4203,18 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) ATOMIC_SET(finalizing, 0); } -PUREFUNC(static inline int is_id_value(rb_objspace_t *objspace, VALUE ptr)); -static inline int -is_id_value(rb_objspace_t *objspace, VALUE ptr) -{ - if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE; - if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE; - if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE; - return TRUE; -} - static inline int -heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr) +is_swept_object(rb_objspace_t *objspace, VALUE ptr) { struct heap_page *page = GET_HEAP_PAGE(ptr); return page->flags.before_sweep ? FALSE : TRUE; } -static inline int -is_swept_object(rb_objspace_t *objspace, VALUE ptr) -{ - if (heap_is_swept_object(objspace, heap_eden, ptr)) { - return TRUE; - } - else { - return FALSE; - } -} - /* garbage objects will be collected soon. */ static inline int is_garbage_object(rb_objspace_t *objspace, VALUE ptr) { - if (!is_lazy_sweeping(heap_eden) || + if (!is_lazy_sweeping(objspace) || is_swept_object(objspace, ptr) || MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) { @@ -3576,8 +4230,11 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr) { switch (BUILTIN_TYPE(ptr)) { case T_NONE: + case T_MOVED: case T_ZOMBIE: return FALSE; + default: + break; } if (!is_garbage_object(objspace, ptr)) { @@ -3633,6 +4290,8 @@ id2ref_obj_tbl(rb_objspace_t *objspace, VALUE objid) * r = ObjectSpace._id2ref(s.object_id) #=> "I am a string" * r == s #=> true * + * On multi-ractor mode, if the object is not shareable, it raises + * RangeError. */ static VALUE @@ -3648,11 +4307,12 @@ id2ref(VALUE objid) VALUE orig; void *p0; + objid = rb_to_int(objid); if (FIXNUM_P(objid) || rb_big_size(objid) <= SIZEOF_VOIDP) { ptr = NUM2PTR(objid); if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; + if (NIL_P(ptr)) return Qnil; if (FIXNUM_P(ptr)) return (VALUE)ptr; if (FLONUM_P(ptr)) return (VALUE)ptr; @@ -3668,12 +4328,19 @@ id2ref(VALUE objid) if ((orig = id2ref_obj_tbl(objspace, objid)) != Qundef && is_live_object(objspace, orig)) { - return orig; + + if (!rb_multi_ractor_p() || rb_ractor_shareable_p(orig)) { + return orig; + } + else { + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is id of the unshareable object on multi-ractor", rb_int2str(objid, 10)); + } } if (rb_int_ge(objid, objspace->next_object_id)) { rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10)); - } else { + } + else { rb_raise(rb_eRangeError, "%+"PRIsVALUE" is recycled object", rb_int2str(objid, 10)); } } @@ -3710,9 +4377,9 @@ cached_object_id(VALUE obj) VALUE id; rb_objspace_t *objspace = &rb_objspace; + RB_VM_LOCK_ENTER(); if (st_lookup(objspace->obj_to_id_tbl, (st_data_t)obj, &id)) { GC_ASSERT(FL_TEST(obj, FL_SEEN_OBJ_ID)); - return id; } else { GC_ASSERT(!FL_TEST(obj, FL_SEEN_OBJ_ID)); @@ -3720,12 +4387,15 @@ cached_object_id(VALUE obj) id = objspace->next_object_id; objspace->next_object_id = rb_int_plus(id, INT2FIX(OBJ_ID_INCREMENT)); + VALUE already_disabled = rb_gc_disable_no_rest(); st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id); st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj); + if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace); FL_SET(obj, FL_SEEN_OBJ_ID); - - return id; } + RB_VM_LOCK_LEAVE(); + + return id; } static VALUE @@ -3803,7 +4473,23 @@ rb_obj_id(VALUE obj) return rb_find_object_id(obj, cached_object_id); } -#include "regint.h" +static enum rb_id_table_iterator_result +cc_table_memsize_i(VALUE ccs_ptr, void *data_ptr) +{ + size_t *total_size = data_ptr; + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr; + *total_size += sizeof(*ccs); + *total_size += sizeof(ccs->entries[0]) * ccs->capa; + return ID_TABLE_CONTINUE; +} + +static size_t +cc_table_memsize(struct rb_id_table *cc_table) +{ + size_t total = rb_id_table_memsize(cc_table); + rb_id_table_foreach_values(cc_table, cc_table_memsize_i, &total); + return total; +} static size_t obj_memsize_of(VALUE obj, int use_all_types) @@ -3820,9 +4506,8 @@ obj_memsize_of(VALUE obj, int use_all_types) switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - if (!(RBASIC(obj)->flags & ROBJECT_EMBED) && - ROBJECT(obj)->as.heap.ivptr) { - size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE); + if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) { + size += ROBJECT_NUMIV(obj) * sizeof(VALUE); } break; case T_MODULE: @@ -3834,24 +4519,36 @@ obj_memsize_of(VALUE obj, int use_all_types) if (RCLASS_IV_TBL(obj)) { size += st_memsize(RCLASS_IV_TBL(obj)); } + if (RCLASS_CVC_TBL(obj)) { + size += rb_id_table_memsize(RCLASS_CVC_TBL(obj)); + } if (RCLASS_IV_INDEX_TBL(obj)) { + // TODO: more correct value size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); } - if (RCLASS(obj)->ptr->iv_tbl) { - size += st_memsize(RCLASS(obj)->ptr->iv_tbl); + if (RCLASS_EXT(obj)->iv_tbl) { + size += st_memsize(RCLASS_EXT(obj)->iv_tbl); } - if (RCLASS(obj)->ptr->const_tbl) { - size += rb_id_table_memsize(RCLASS(obj)->ptr->const_tbl); + if (RCLASS_EXT(obj)->const_tbl) { + size += rb_id_table_memsize(RCLASS_EXT(obj)->const_tbl); } + if (RCLASS_CC_TBL(obj)) { + size += cc_table_memsize(RCLASS_CC_TBL(obj)); + } +#if !USE_RVARGC size += sizeof(rb_classext_t); +#endif } break; case T_ICLASS: - if (FL_TEST(obj, RICLASS_IS_ORIGIN)) { + if (RICLASS_OWNS_M_TBL_P(obj)) { if (RCLASS_M_TBL(obj)) { size += rb_id_table_memsize(RCLASS_M_TBL(obj)); } } + if (RCLASS_EXT(obj) && RCLASS_CC_TBL(obj)) { + size += cc_table_memsize(RCLASS_CC_TBL(obj)); + } break; case T_STRING: size += rb_str_memsize(obj); @@ -3862,7 +4559,7 @@ obj_memsize_of(VALUE obj, int use_all_types) case T_HASH: if (RHASH_AR_TABLE_P(obj)) { if (RHASH_AR_TABLE(obj) != NULL) { - size_t rb_hash_ar_table_size(); + size_t rb_hash_ar_table_size(void); size += rb_hash_ar_table_size(); } } @@ -3929,7 +4626,7 @@ obj_memsize_of(VALUE obj, int use_all_types) BUILTIN_TYPE(obj), (void*)obj); } - return size + sizeof(RVALUE); + return size + GET_HEAP_PAGE(obj)->slot_size; } size_t @@ -3980,7 +4677,7 @@ type_sym(size_t type) COUNT_TYPE(T_ZOMBIE); COUNT_TYPE(T_MOVED); #undef COUNT_TYPE - default: return INT2NUM(type); break; + default: return SIZET2NUM(type); break; } } @@ -4041,27 +4738,31 @@ count_objects(int argc, VALUE *argv, VALUE os) for (i = 0; i < heap_allocated_pages; i++) { struct heap_page *page = heap_pages_sorted[i]; - RVALUE *p, *pend; - - p = page->start; pend = p + page->total_slots; - for (;p < pend; p++) { - void *poisoned = asan_poisoned_object_p((VALUE)p); - asan_unpoison_object((VALUE)p, false); - if (p->as.basic.flags) { - counts[BUILTIN_TYPE(p)]++; + short stride = page->slot_size; + + uintptr_t p = (uintptr_t)page->start; + uintptr_t pend = p + page->total_slots * stride; + for (;p < pend; p += stride) { + VALUE vp = (VALUE)p; + GC_ASSERT((NUM_IN_PAGE(vp) * sizeof(RVALUE)) % page->slot_size == 0); + + void *poisoned = asan_poisoned_object_p(vp); + asan_unpoison_object(vp, false); + if (RANY(p)->as.basic.flags) { + counts[BUILTIN_TYPE(vp)]++; } else { freed++; } if (poisoned) { - GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE); - asan_poison_object((VALUE)p); + GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE); + asan_poison_object(vp); } } total += page->total_slots; } - if (hash == Qnil) { + if (NIL_P(hash)) { hash = rb_hash_new(); } else if (!RHASH_EMPTY_P(hash)) { @@ -4079,124 +4780,641 @@ count_objects(int argc, VALUE *argv, VALUE os) return hash; } -/* - ------------------------ Garbage Collection ------------------------ -*/ +/* + ------------------------ Garbage Collection ------------------------ +*/ + +/* Sweeping */ + +static size_t +objspace_available_slots(rb_objspace_t *objspace) +{ + size_t total_slots = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + total_slots += SIZE_POOL_EDEN_HEAP(size_pool)->total_slots; + total_slots += SIZE_POOL_TOMB_HEAP(size_pool)->total_slots; + } + return total_slots; +} + +static size_t +objspace_live_slots(rb_objspace_t *objspace) +{ + return (objspace->total_allocated_objects - objspace->profile.total_freed_objects) - heap_pages_final_slots; +} + +static size_t +objspace_free_slots(rb_objspace_t *objspace) +{ + return objspace_available_slots(objspace) - objspace_live_slots(objspace) - heap_pages_final_slots; +} + +static void +gc_setup_mark_bits(struct heap_page *page) +{ + /* copy oldgen bitmap to mark bitmap */ + memcpy(&page->mark_bits[0], &page->uncollectible_bits[0], HEAP_PAGE_BITMAP_SIZE); +} + +static int gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj); +static VALUE gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t slot_size); + +static void +lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body) +{ +#if defined(_WIN32) + DWORD old_protect; + + if (!VirtualProtect(body, HEAP_PAGE_SIZE, PAGE_NOACCESS, &old_protect)) { +#else + if (mprotect(body, HEAP_PAGE_SIZE, PROT_NONE)) { +#endif + rb_bug("Couldn't protect page %p, errno: %s", (void *)body, strerror(errno)); + } + else { + gc_report(5, objspace, "Protecting page in move %p\n", (void *)body); + } +} + +static void +unlock_page_body(rb_objspace_t *objspace, struct heap_page_body *body) +{ +#if defined(_WIN32) + DWORD old_protect; + + if (!VirtualProtect(body, HEAP_PAGE_SIZE, PAGE_READWRITE, &old_protect)) { +#else + if (mprotect(body, HEAP_PAGE_SIZE, PROT_READ | PROT_WRITE)) { +#endif + rb_bug("Couldn't unprotect page %p, errno: %s", (void *)body, strerror(errno)); + } + else { + gc_report(5, objspace, "Unprotecting page in move %p\n", (void *)body); + } +} + +static inline bool +try_move_plane(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page, uintptr_t p, bits_t bits, VALUE dest) +{ + if (bits) { + do { + if (bits & 1) { + /* We're trying to move "p" */ + objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)p)]++; + + if (gc_is_moveable_obj(objspace, (VALUE)p)) { + /* We were able to move "p" */ + objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)p)]++; + objspace->rcompactor.total_moved++; + + bool from_freelist = false; + + if (BUILTIN_TYPE(dest) == T_NONE) { + from_freelist = true; + } + + gc_move(objspace, (VALUE)p, dest, page->slot_size); + gc_pin(objspace, (VALUE)p); + heap->compact_cursor_index = (RVALUE *)p; + if (from_freelist) { + FL_SET((VALUE)p, FL_FROM_FREELIST); + } + + return true; + } + } + p += sizeof(RVALUE); + bits >>= 1; + } while (bits); + } + + return false; +} + +static short +try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, VALUE dest) +{ + struct heap_page * cursor = heap->compact_cursor; + + GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest)); + + /* T_NONE objects came from the free list. If the object is *not* a + * T_NONE, it is an object that just got freed but hasn't been + * added to the freelist yet */ + + while (1) { + size_t index; + + bits_t *mark_bits = cursor->mark_bits; + bits_t *pin_bits = cursor->pinned_bits; + RVALUE * p; + + if (heap->compact_cursor_index) { + index = BITMAP_INDEX(heap->compact_cursor_index); + p = heap->compact_cursor_index; + GC_ASSERT(cursor == GET_HEAP_PAGE(p)); + } + else { + index = 0; + p = cursor->start; + } + + bits_t bits = mark_bits[index] & ~pin_bits[index]; + + bits >>= NUM_IN_PAGE(p); + if (try_move_plane(objspace, heap, sweep_page, (uintptr_t)p, bits, dest)) return 1; + + if (index == 0) { + p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start)); + } + else { + p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start)) + (BITS_BITLENGTH * index); + } + + /* Find an object to move and move it. Movable objects must be + * marked, so we iterate using the marking bitmap */ + for (size_t i = index + 1; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + bits_t bits = mark_bits[i] & ~pin_bits[i]; + if (try_move_plane(objspace, heap, sweep_page, (uintptr_t)p, bits, dest)) return 1; + p += BITS_BITLENGTH; + } + + /* We couldn't find a movable object on the compact cursor, so lets + * move to the next page (previous page since we are traveling in the + * opposite direction of the sweep cursor) and look there. */ + + struct heap_page * next; + + next = list_prev(&heap->pages, cursor, page_node); + + /* Protect the current cursor since it probably has T_MOVED slots. */ + lock_page_body(objspace, GET_PAGE_BODY(cursor->start)); + + heap->compact_cursor = next; + heap->compact_cursor_index = 0; + cursor = next; + + // Cursors have met, lets quit. We set `heap->compact_cursor` equal + // to `heap->sweeping_page` so we know how far to iterate through + // the heap when unprotecting pages. + if (next == sweep_page) { + break; + } + } + + return 0; +} + +static void +gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap) +{ + struct heap_page *cursor = heap->compact_cursor; + + while (cursor) { + unlock_page_body(objspace, GET_PAGE_BODY(cursor->start)); + cursor = list_next(&heap->pages, cursor, page_node); + } +} + +static void gc_update_references(rb_objspace_t * objspace); +static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page); + +static void +read_barrier_handler(uintptr_t address) +{ + VALUE obj; + rb_objspace_t * objspace = &rb_objspace; + + address -= address % sizeof(RVALUE); + + obj = (VALUE)address; + + RB_VM_LOCK_ENTER(); + { + unlock_page_body(objspace, GET_PAGE_BODY(obj)); + + objspace->profile.read_barrier_faults++; + + invalidate_moved_page(objspace, GET_HEAP_PAGE(obj)); + } + RB_VM_LOCK_LEAVE(); +} + +#if defined(_WIN32) +static LPTOP_LEVEL_EXCEPTION_FILTER old_handler; +typedef void (*signal_handler)(int); +static signal_handler old_sigsegv_handler; + +static LONG WINAPI +read_barrier_signal(EXCEPTION_POINTERS * info) +{ + /* EXCEPTION_ACCESS_VIOLATION is what's raised by access to protected pages */ + if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + /* > The second array element specifies the virtual address of the inaccessible data. + * https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record + * + * Use this address to invalidate the page */ + read_barrier_handler((uintptr_t)info->ExceptionRecord->ExceptionInformation[1]); + return EXCEPTION_CONTINUE_EXECUTION; + } + else { + return EXCEPTION_CONTINUE_SEARCH; + } +} + +static void +uninstall_handlers(void) +{ + signal(SIGSEGV, old_sigsegv_handler); + SetUnhandledExceptionFilter(old_handler); +} + +static void +install_handlers(void) +{ + /* Remove SEGV handler so that the Unhandled Exception Filter handles it */ + old_sigsegv_handler = signal(SIGSEGV, NULL); + /* Unhandled Exception Filter has access to the violation address similar + * to si_addr from sigaction */ + old_handler = SetUnhandledExceptionFilter(read_barrier_signal); +} +#else +static struct sigaction old_sigbus_handler; +static struct sigaction old_sigsegv_handler; + +static void +read_barrier_signal(int sig, siginfo_t * info, void * data) +{ + // setup SEGV/BUS handlers for errors + struct sigaction prev_sigbus, prev_sigsegv; + sigaction(SIGBUS, &old_sigbus_handler, &prev_sigbus); + sigaction(SIGSEGV, &old_sigsegv_handler, &prev_sigsegv); + + // enable SIGBUS/SEGV + sigset_t set, prev_set; + sigemptyset(&set); + sigaddset(&set, SIGBUS); + sigaddset(&set, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &set, &prev_set); + + // run handler + read_barrier_handler((uintptr_t)info->si_addr); + + // reset SEGV/BUS handlers + sigaction(SIGBUS, &prev_sigbus, NULL); + sigaction(SIGSEGV, &prev_sigsegv, NULL); + sigprocmask(SIG_SETMASK, &prev_set, NULL); +} + +static void +uninstall_handlers(void) +{ + sigaction(SIGBUS, &old_sigbus_handler, NULL); + sigaction(SIGSEGV, &old_sigsegv_handler, NULL); +} + +static void +install_handlers(void) +{ + struct sigaction action; + memset(&action, 0, sizeof(struct sigaction)); + sigemptyset(&action.sa_mask); + action.sa_sigaction = read_barrier_signal; + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + + sigaction(SIGBUS, &action, &old_sigbus_handler); + sigaction(SIGSEGV, &action, &old_sigsegv_handler); +} +#endif + +static void +revert_stack_objects(VALUE stack_obj, void *ctx) +{ + rb_objspace_t * objspace = (rb_objspace_t*)ctx; + + if (BUILTIN_TYPE(stack_obj) == T_MOVED) { + /* For now we'll revert the whole page if the object made it to the + * stack. I think we can change this to move just the one object + * back though */ + invalidate_moved_page(objspace, GET_HEAP_PAGE(stack_obj)); + } +} + +static void +revert_machine_stack_references(rb_objspace_t *objspace, VALUE v) +{ + if (is_pointer_to_heap(objspace, (void *)v)) { + if (BUILTIN_TYPE(v) == T_MOVED) { + /* For now we'll revert the whole page if the object made it to the + * stack. I think we can change this to move just the one object + * back though */ + invalidate_moved_page(objspace, GET_HEAP_PAGE(v)); + } + } +} + +static void each_machine_stack_value(const rb_execution_context_t *ec, void (*cb)(rb_objspace_t *, VALUE)); + +static void +check_stack_for_moved(rb_objspace_t *objspace) +{ + rb_execution_context_t *ec = GET_EC(); + rb_vm_t *vm = rb_ec_vm_ptr(ec); + rb_vm_each_stack_value(vm, revert_stack_objects, (void*)objspace); + each_machine_stack_value(ec, revert_machine_stack_references); +} + +static void +gc_compact_finish(rb_objspace_t *objspace, rb_size_pool_t *pool, rb_heap_t *heap) +{ + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + gc_unprotect_pages(objspace, heap); + } + + uninstall_handlers(); + + /* The mutator is allowed to run during incremental sweeping. T_MOVED + * objects can get pushed on the stack and when the compaction process + * finishes up, it may remove the read barrier before anything has a + * chance to read from the T_MOVED address. To fix this, we scan the stack + * then revert any moved objects that made it to the stack. */ + check_stack_for_moved(objspace); + + gc_update_references(objspace); + objspace->profile.compact_count++; + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + heap->compact_cursor = NULL; + heap->compact_cursor_index = 0; + } + + if (gc_prof_enabled(objspace)) { + gc_profile_record *record = gc_prof_record(objspace); + record->moved_objects = objspace->rcompactor.total_moved - record->moved_objects; + } + objspace->flags.during_compacting = FALSE; +} + +struct gc_sweep_context { + struct heap_page *page; + int final_slots; + int freed_slots; + int empty_slots; +}; + +static inline void +gc_fill_swept_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, bool *finished_compacting, struct gc_sweep_context *ctx) +{ + struct heap_page * sweep_page = ctx->page; + + if (bitset) { + short slot_size = sweep_page->slot_size; + short slot_bits = slot_size / sizeof(RVALUE); + + do { + if (bitset & 1) { + VALUE dest = (VALUE)p; + + GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest)); + GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest)); + + CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest); + + if (*finished_compacting) { + if (BUILTIN_TYPE(dest) == T_NONE) { + ctx->empty_slots++; + } + else { + ctx->freed_slots++; + } + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)dest, sizeof(RVALUE)); + heap_page_add_freeobj(objspace, sweep_page, dest); + } + else { + /* Zombie slots don't get marked, but we can't reuse + * their memory until they have their finalizers run.*/ + if (BUILTIN_TYPE(dest) != T_ZOMBIE) { + if (!try_move(objspace, heap, sweep_page, dest)) { + *finished_compacting = true; + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); + gc_report(5, objspace, "Quit compacting, couldn't find an object to move\n"); + if (BUILTIN_TYPE(dest) == T_NONE) { + ctx->empty_slots++; + } + else { + ctx->freed_slots++; + } + heap_page_add_freeobj(objspace, sweep_page, dest); + gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(dest)); + } + else { + //moved_slots++; + } + } + } + } + p += slot_size; + bitset >>= slot_bits; + } while (bitset); + } +} + +static bool +gc_fill_swept_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, struct gc_sweep_context *ctx) +{ + /* Find any pinned but not marked objects and try to fill those slots */ + bool finished_compacting = false; + bits_t *mark_bits, *pin_bits; + bits_t bitset; + uintptr_t p; + + mark_bits = sweep_page->mark_bits; + pin_bits = sweep_page->pinned_bits; + + p = (uintptr_t)sweep_page->start; + + struct heap_page * cursor = heap->compact_cursor; + + unlock_page_body(objspace, GET_PAGE_BODY(cursor->start)); + + /* *Want to move* objects are pinned but not marked. */ + bitset = pin_bits[0] & ~mark_bits[0]; + bitset >>= NUM_IN_PAGE(p); // Skip header / dead space bits + gc_fill_swept_plane(objspace, heap, (uintptr_t)p, bitset, &finished_compacting, ctx); + p += ((BITS_BITLENGTH - NUM_IN_PAGE(p)) * sizeof(RVALUE)); + + for (int i = 1; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + /* *Want to move* objects are pinned but not marked. */ + bitset = pin_bits[i] & ~mark_bits[i]; + gc_fill_swept_plane(objspace, heap, (uintptr_t)p, bitset, &finished_compacting, ctx); + p += ((BITS_BITLENGTH) * sizeof(RVALUE)); + } -/* Sweeping */ + lock_page_body(objspace, GET_PAGE_BODY(heap->compact_cursor->start)); -static size_t -objspace_available_slots(rb_objspace_t *objspace) -{ - return heap_eden->total_slots + heap_tomb->total_slots; + return finished_compacting; } -static size_t -objspace_live_slots(rb_objspace_t *objspace) +static inline void +gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct gc_sweep_context *ctx) { - return (objspace->total_allocated_objects - objspace->profile.total_freed_objects) - heap_pages_final_slots; -} + struct heap_page * sweep_page = ctx->page; + short slot_size = sweep_page->slot_size; + short slot_bits = slot_size / sizeof(RVALUE); + GC_ASSERT(slot_bits > 0); -static size_t -objspace_free_slots(rb_objspace_t *objspace) -{ - return objspace_available_slots(objspace) - objspace_live_slots(objspace) - heap_pages_final_slots; + do { + VALUE vp = (VALUE)p; + GC_ASSERT(vp % sizeof(RVALUE) == 0); + + asan_unpoison_object(vp, false); + if (bitset & 1) { + switch (BUILTIN_TYPE(vp)) { + default: /* majority case */ + gc_report(2, objspace, "page_sweep: free %p\n", (void *)p); +#if RGENGC_CHECK_MODE + if (!is_full_marking(objspace)) { + if (RVALUE_OLD_P(vp)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p); + if (rgengc_remembered_sweep(objspace, vp)) rb_bug("page_sweep: %p - remembered.", (void *)p); + } +#endif + if (obj_free(objspace, vp)) { + if (heap->compact_cursor) { + /* We *want* to fill this slot */ + MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp); + } + else { + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); + heap_page_add_freeobj(objspace, sweep_page, vp); + gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp)); + ctx->freed_slots++; + } + } + else { + ctx->final_slots++; + } + break; + + case T_MOVED: + if (objspace->flags.during_compacting) { + /* The sweep cursor shouldn't have made it to any + * T_MOVED slots while the compact flag is enabled. + * The sweep cursor and compact cursor move in + * opposite directions, and when they meet references will + * get updated and "during_compacting" should get disabled */ + rb_bug("T_MOVED shouldn't be seen until compaction is finished\n"); + } + gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp)); + if (FL_TEST(vp, FL_FROM_FREELIST)) { + ctx->empty_slots++; + } + else { + ctx->freed_slots++; + } + heap_page_add_freeobj(objspace, sweep_page, vp); + break; + case T_ZOMBIE: + /* already counted */ + break; + case T_NONE: + if (heap->compact_cursor) { + /* We *want* to fill this slot */ + MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp); + } + else { + ctx->empty_slots++; /* already freed */ + } + break; + } + } + p += slot_size; + bitset >>= slot_bits; + } while (bitset); } -static void -gc_setup_mark_bits(struct heap_page *page) +static inline void +gc_sweep_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, struct gc_sweep_context *ctx) { -#if USE_RGENGC - /* copy oldgen bitmap to mark bitmap */ - memcpy(&page->mark_bits[0], &page->uncollectible_bits[0], HEAP_PAGE_BITMAP_SIZE); -#else - /* clear mark bitmap */ - memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); -#endif -} + struct heap_page *sweep_page = ctx->page; -static inline int -gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page) -{ int i; - int empty_slots = 0, freed_slots = 0, final_slots = 0; - RVALUE *p, *pend,*offset; + + RVALUE *p; bits_t *bits, bitset; gc_report(2, objspace, "page_sweep: start.\n"); + if (heap->compact_cursor) { + if (sweep_page == heap->compact_cursor) { + /* The compaction cursor and sweep page met, so we need to quit compacting */ + gc_report(5, objspace, "Quit compacting, mark and compact cursor met\n"); + gc_compact_finish(objspace, size_pool, heap); + } + else { + /* We anticipate filling the page, so NULL out the freelist. */ + asan_unpoison_memory_region(&sweep_page->freelist, sizeof(RVALUE*), false); + sweep_page->freelist = NULL; + asan_poison_memory_region(&sweep_page->freelist, sizeof(RVALUE*)); + } + } + sweep_page->flags.before_sweep = FALSE; + sweep_page->free_slots = 0; - p = sweep_page->start; pend = p + sweep_page->total_slots; - offset = p - NUM_IN_PAGE(p); + p = sweep_page->start; bits = sweep_page->mark_bits; - /* create guard : fill 1 out-of-range */ - bits[BITMAP_INDEX(p)] |= BITMAP_BIT(p)-1; - bits[BITMAP_INDEX(pend)] |= ~(BITMAP_BIT(pend) - 1); + int page_rvalue_count = sweep_page->total_slots * (size_pool->slot_size / sizeof(RVALUE)); + int out_of_range_bits = (NUM_IN_PAGE(p) + page_rvalue_count) % BITS_BITLENGTH; + if (out_of_range_bits != 0) { // sizeof(RVALUE) == 64 + bits[BITMAP_INDEX(p) + page_rvalue_count / BITS_BITLENGTH] |= ~(((bits_t)1 << out_of_range_bits) - 1); + } - for (i=0; i < HEAP_PAGE_BITMAP_LIMIT; i++) { - bitset = ~bits[i]; - if (bitset) { - p = offset + i * BITS_BITLENGTH; - do { - asan_unpoison_object((VALUE)p, false); - if (bitset & 1) { - switch (BUILTIN_TYPE(p)) { - default: { /* majority case */ - gc_report(2, objspace, "page_sweep: free %p\n", (void *)p); -#if USE_RGENGC && RGENGC_CHECK_MODE - if (!is_full_marking(objspace)) { - if (RVALUE_OLD_P((VALUE)p)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p); - if (rgengc_remembered_sweep(objspace, (VALUE)p)) rb_bug("page_sweep: %p - remembered.", (void *)p); - } -#endif - if (obj_free(objspace, (VALUE)p)) { - final_slots++; - } - else { - (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - heap_page_add_freeobj(objspace, sweep_page, (VALUE)p); - gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info((VALUE)p)); - freed_slots++; - asan_poison_object((VALUE)p); - } - break; - } - - /* minor cases */ - case T_ZOMBIE: - /* already counted */ - break; - case T_NONE: - empty_slots++; /* already freed */ - break; - } - } - p++; - bitset >>= 1; - } while (bitset); - } + // Skip out of range slots at the head of the page + bitset = ~bits[0]; + bitset >>= NUM_IN_PAGE(p); + if (bitset) { + gc_sweep_plane(objspace, heap, (uintptr_t)p, bitset, ctx); + } + p += (BITS_BITLENGTH - NUM_IN_PAGE(p)); + + for (i=1; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + bitset = ~bits[i]; + if (bitset) { + gc_sweep_plane(objspace, heap, (uintptr_t)p, bitset, ctx); + } + p += BITS_BITLENGTH; + } + + if (heap->compact_cursor) { + if (gc_fill_swept_page(objspace, heap, sweep_page, ctx)) { + gc_compact_finish(objspace, size_pool, heap); + } } - gc_setup_mark_bits(sweep_page); + if (!heap->compact_cursor) { + gc_setup_mark_bits(sweep_page); + } #if GC_PROFILE_MORE_DETAIL if (gc_prof_enabled(objspace)) { gc_profile_record *record = gc_prof_record(objspace); - record->removing_objects += final_slots + freed_slots; - record->empty_objects += empty_slots; + record->removing_objects += ctx->final_slots + ctx->freed_slots; + record->empty_objects += ctx->empty_slots; } #endif - if (0) fprintf(stderr, "gc_page_sweep(%d): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n", - (int)rb_gc_count(), - (int)sweep_page->total_slots, - freed_slots, empty_slots, final_slots); + if (0) fprintf(stderr, "gc_sweep_page(%"PRIdSIZE"): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n", + rb_gc_count(), + sweep_page->total_slots, + ctx->freed_slots, ctx->empty_slots, ctx->final_slots); - sweep_page->free_slots = freed_slots + empty_slots; - objspace->profile.total_freed_objects += freed_slots; - heap_pages_final_slots += final_slots; - sweep_page->final_slots += final_slots; + sweep_page->free_slots += ctx->freed_slots + ctx->empty_slots; + objspace->profile.total_freed_objects += ctx->freed_slots; if (heap_pages_deferred_final && !finalizing) { rb_thread_t *th = GET_THREAD(); @@ -4205,23 +5423,37 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_ } } - gc_report(2, objspace, "page_sweep: end.\n"); +#if RGENGC_CHECK_MODE + short freelist_len = 0; + RVALUE *ptr = sweep_page->freelist; + while (ptr) { + freelist_len++; + ptr = ptr->as.free.next; + } + if (freelist_len != sweep_page->free_slots) { + rb_bug("inconsistent freelist length: expected %d but was %d", sweep_page->free_slots, freelist_len); + } +#endif - return freed_slots + empty_slots; + gc_report(2, objspace, "page_sweep: end.\n"); } +#if !USE_RVARGC /* allocate additional minimum page to work */ static void -gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_heap_t *heap) +gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { - if (!heap->free_pages && heap_increment(objspace, heap) == FALSE) { - /* there is no free after page_sweep() */ - heap_set_increment(objspace, 1); - if (!heap_increment(objspace, heap)) { /* can't allocate additional free objects */ - rb_memerror(); - } + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + if (!heap->free_pages && heap_increment(objspace, size_pool, heap) == FALSE) { + /* there is no free after page_sweep() */ + size_pool_allocatable_pages_set(objspace, size_pool, 1); + if (!heap_increment(objspace, size_pool, heap)) { /* can't allocate additional free objects */ + rb_memerror(); + } + } } } +#endif static const char * gc_mode_name(enum gc_mode mode) @@ -4249,6 +5481,30 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode) gc_mode_set(objspace, mode); } +static void +heap_page_freelist_append(struct heap_page *page, RVALUE *freelist) +{ + if (freelist) { + asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + if (page->freelist) { + RVALUE *p = page->freelist; + asan_unpoison_object((VALUE)p, false); + while (p->as.free.next) { + RVALUE *prev = p; + p = p->as.free.next; + asan_poison_object((VALUE)prev); + asan_unpoison_object((VALUE)p, false); + } + p->as.free.next = freelist; + asan_poison_object((VALUE)p); + } + else { + page->freelist = freelist; + } + asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + } +} + static void gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap) { @@ -4256,21 +5512,7 @@ gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap) heap->free_pages = NULL; #if GC_ENABLE_INCREMENTAL_MARK heap->pooled_pages = NULL; - objspace->rincgc.pooled_slots = 0; #endif - if (heap->using_page) { - struct heap_page *page = heap->using_page; - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - - RVALUE **p = &page->freelist; - while (*p) { - p = &(*p)->as.free.next; - } - *p = heap->freelist; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); - heap->using_page = NULL; - } - heap->freelist = NULL; } #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 @@ -4280,8 +5522,63 @@ static void gc_sweep_start(rb_objspace_t *objspace) { gc_mode_transition(objspace, gc_mode_sweeping); - gc_sweep_start_heap(objspace, heap_eden); + +#if GC_ENABLE_INCREMENTAL_MARK + objspace->rincgc.pooled_slots = 0; +#endif + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + + gc_sweep_start_heap(objspace, SIZE_POOL_EDEN_HEAP(size_pool)); + } + + rb_ractor_t *r = NULL; + list_for_each(&GET_VM()->ractor.set, r, vmlr_node) { + rb_gc_ractor_newobj_cache_clear(&r->newobj_cache); + } +} + +#if USE_RVARGC +static void +gc_sweep_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool) +{ + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + size_t total_slots = heap->total_slots + SIZE_POOL_TOMB_HEAP(size_pool)->total_slots; + size_t total_pages = heap->total_pages + SIZE_POOL_TOMB_HEAP(size_pool)->total_pages; + size_t swept_slots = size_pool->freed_slots + size_pool->empty_slots; + + size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio); + + if (swept_slots < min_free_slots) { + bool grow_heap = is_full_marking(objspace); + + if (!is_full_marking(objspace)) { + /* The heap is a growth heap if it freed more slots than had empty slots. */ + bool is_growth_heap = size_pool->empty_slots == 0 || + size_pool->freed_slots > size_pool->empty_slots; + + if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) { + grow_heap = TRUE; + } + else if (is_growth_heap) { /* Only growth heaps are allowed to start a major GC. */ + objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE; + size_pool->force_major_gc_count++; + } + } + + if (grow_heap) { + size_t extend_page_count = heap_extend_pages(objspace, swept_slots, total_slots, total_pages); + + if (extend_page_count > size_pool->allocatable_pages) { + size_pool_allocatable_pages_set(objspace, size_pool, extend_page_count); + } + + heap_increment(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); + } + } } +#endif static void gc_sweep_finish(rb_objspace_t *objspace) @@ -4291,10 +5588,37 @@ gc_sweep_finish(rb_objspace_t *objspace) gc_prof_set_heap_info(objspace); heap_pages_free_unused_pages(objspace); - /* if heap_pages has unused pages, then assign them to increment */ - if (heap_allocatable_pages < heap_tomb->total_pages) { - heap_allocatable_pages_set(objspace, heap_tomb->total_pages); + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + + /* if heap_pages has unused pages, then assign them to increment */ + size_t tomb_pages = SIZE_POOL_TOMB_HEAP(size_pool)->total_pages; + if (size_pool->allocatable_pages < tomb_pages) { + size_pool->allocatable_pages = tomb_pages; + } + +#if USE_RVARGC + size_pool->freed_slots = 0; + size_pool->empty_slots = 0; + +#if GC_ENABLE_INCREMENTAL_MARK + if (!will_be_incremental_marking(objspace)) { + rb_heap_t *eden_heap = SIZE_POOL_EDEN_HEAP(size_pool); + struct heap_page *end_page = eden_heap->free_pages; + if (end_page) { + while (end_page->free_next) end_page = end_page->free_next; + end_page->free_next = eden_heap->pooled_pages; + } + else { + eden_heap->free_pages = eden_heap->pooled_pages; + } + eden_heap->pooled_pages = NULL; + objspace->rincgc.pooled_slots = 0; + } +#endif +#endif } + heap_pages_expand_sorted(objspace); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_SWEEP, 0); gc_mode_transition(objspace, gc_mode_none); @@ -4305,12 +5629,18 @@ gc_sweep_finish(rb_objspace_t *objspace) } static int -gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) +gc_sweep_step(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { struct heap_page *sweep_page = heap->sweeping_page; int unlink_limit = 3; + #if GC_ENABLE_INCREMENTAL_MARK + int swept_slots = 0; +#if USE_RVARGC + bool need_pool = TRUE; +#else int need_pool = will_be_incremental_marking(objspace) ? TRUE : FALSE; +#endif gc_report(2, objspace, "gc_sweep_step (need_pool: %d)\n", need_pool); #else @@ -4324,8 +5654,18 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) #endif do { - int free_slots = gc_page_sweep(objspace, heap, sweep_page); - heap->sweeping_page = list_next(&heap->pages, sweep_page, page_node); + RUBY_DEBUG_LOG("sweep_page:%p", (void *)sweep_page); + + struct gc_sweep_context ctx = { + .page = sweep_page, + .final_slots = 0, + .freed_slots = 0, + .empty_slots = 0, + }; + gc_sweep_page(objspace, size_pool, heap, &ctx); + int free_slots = ctx.freed_slots + ctx.empty_slots; + + heap->sweeping_page = list_next(&heap->pages, sweep_page, page_node); if (sweep_page->final_slots + free_slots == sweep_page->total_slots && heap_pages_freeable_pages > 0 && @@ -4334,22 +5674,29 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) unlink_limit--; /* there are no living objects -> move this page to tomb heap */ heap_unlink_page(objspace, heap, sweep_page); - heap_add_page(objspace, heap_tomb, sweep_page); + heap_add_page(objspace, size_pool, SIZE_POOL_TOMB_HEAP(size_pool), sweep_page); } else if (free_slots > 0) { +#if USE_RVARGC + size_pool->freed_slots += ctx.freed_slots; + size_pool->empty_slots += ctx.empty_slots; +#endif + #if GC_ENABLE_INCREMENTAL_MARK if (need_pool) { - if (heap_add_poolpage(objspace, heap, sweep_page)) { - need_pool = FALSE; - } + heap_add_poolpage(objspace, heap, sweep_page); + need_pool = FALSE; } else { - heap_add_freepage(heap, sweep_page); - break; + heap_add_freepage(heap, sweep_page); + swept_slots += free_slots; + if (swept_slots > 2048) { + break; + } } #else - heap_add_freepage(heap, sweep_page); - break; + heap_add_freepage(heap, sweep_page); + break; #endif } else { @@ -4358,7 +5705,13 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) } while ((sweep_page = heap->sweeping_page)); if (!heap->sweeping_page) { - gc_sweep_finish(objspace); +#if USE_RVARGC + gc_sweep_finish_size_pool(objspace, size_pool); +#endif + + if (!has_sweeping_pages(objspace)) { + gc_sweep_finish(objspace); + } } #if GC_ENABLE_LAZY_SWEEP @@ -4371,27 +5724,139 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) static void gc_sweep_rest(rb_objspace_t *objspace) { - rb_heap_t *heap = heap_eden; /* lazy sweep only for eden */ + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; - while (has_sweeping_pages(heap)) { - gc_sweep_step(objspace, heap); + while (SIZE_POOL_EDEN_HEAP(size_pool)->sweeping_page) { + gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); + } } } static void -gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap) +gc_sweep_continue(rb_objspace_t *objspace, rb_size_pool_t *sweep_size_pool, rb_heap_t *heap) { - GC_ASSERT(dont_gc == FALSE); + GC_ASSERT(dont_gc_val() == FALSE); if (!GC_ENABLE_LAZY_SWEEP) return; - gc_enter(objspace, "sweep_continue"); -#if USE_RGENGC - if (objspace->rgengc.need_major_gc == GPR_FLAG_NONE && heap_increment(objspace, heap)) { - gc_report(3, objspace, "gc_sweep_continue: success heap_increment().\n"); - } + unsigned int lock_lev; + gc_enter(objspace, gc_enter_event_sweep_continue, &lock_lev); + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + if (!gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool))) { +#if USE_RVARGC + /* sweep_size_pool requires a free slot but sweeping did not yield any. */ + if (size_pool == sweep_size_pool) { + if (size_pool->allocatable_pages > 0) { + heap_increment(objspace, size_pool, heap); + } + else { + /* Not allowed to create a new page so finish sweeping. */ + gc_sweep_rest(objspace); + break; + } + } #endif - gc_sweep_step(objspace, heap); - gc_exit(objspace, "sweep_continue"); + } + } + + gc_exit(objspace, gc_enter_event_sweep_continue, &lock_lev); +} + +static void +invalidate_moved_plane(rb_objspace_t *objspace, struct heap_page *page, uintptr_t p, bits_t bitset) +{ + if (bitset) { + do { + if (bitset & 1) { + VALUE forwarding_object = (VALUE)p; + VALUE object; + + if (BUILTIN_TYPE(forwarding_object) == T_MOVED) { + GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(forwarding_object), forwarding_object)); + GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(forwarding_object), forwarding_object)); + + CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(forwarding_object), forwarding_object); + + bool from_freelist = FL_TEST_RAW(forwarding_object, FL_FROM_FREELIST); + object = rb_gc_location(forwarding_object); + + gc_move(objspace, object, forwarding_object, page->slot_size); + /* forwarding_object is now our actual object, and "object" + * is the free slot for the original page */ + struct heap_page *orig_page = GET_HEAP_PAGE(object); + orig_page->free_slots++; + if (!from_freelist) { + objspace->profile.total_freed_objects++; + } + heap_page_add_freeobj(objspace, orig_page, object); + + GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(forwarding_object), forwarding_object)); + GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_MOVED); + GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_NONE); + } + } + p += sizeof(RVALUE); + bitset >>= 1; + } while (bitset); + } +} + +static void +invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page) +{ + int i; + bits_t *mark_bits, *pin_bits; + bits_t bitset; + RVALUE *p; + + mark_bits = page->mark_bits; + pin_bits = page->pinned_bits; + + p = page->start; + + // Skip out of range slots at the head of the page + bitset = pin_bits[0] & ~mark_bits[0]; + bitset >>= NUM_IN_PAGE(p); + invalidate_moved_plane(objspace, page, (uintptr_t)p, bitset); + p += (BITS_BITLENGTH - NUM_IN_PAGE(p)); + + for (i=1; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + /* Moved objects are pinned but never marked. We reuse the pin bits + * to indicate there is a moved object in this slot. */ + bitset = pin_bits[i] & ~mark_bits[i]; + + invalidate_moved_plane(objspace, page, (uintptr_t)p, bitset); + p += BITS_BITLENGTH; + } +} + +static void +gc_compact_start(rb_objspace_t *objspace) +{ + struct heap_page *page = NULL; + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(&size_pools[i]); + list_for_each(&heap->pages, page, page_node) { + page->flags.before_sweep = TRUE; + } + + heap->compact_cursor = list_tail(&heap->pages, struct heap_page, page_node); + heap->compact_cursor_index = 0; + } + + if (gc_prof_enabled(objspace)) { + gc_profile_record *record = gc_prof_record(objspace); + record->moved_objects = objspace->rcompactor.total_moved; + } + + memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t)); + memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t)); + + /* Set up read barrier for pages containing MOVED objects */ + install_handlers(); } static void @@ -4406,6 +5871,10 @@ gc_sweep(rb_objspace_t *objspace) gc_prof_sweep_timer_start(objspace); #endif gc_sweep_start(objspace); + if (objspace->flags.during_compacting) { + gc_compact_start(objspace); + } + gc_sweep_rest(objspace); #if !GC_ENABLE_LAZY_SWEEP gc_prof_sweep_timer_stop(objspace); @@ -4415,13 +5884,27 @@ gc_sweep(rb_objspace_t *objspace) struct heap_page *page = NULL; gc_sweep_start(objspace); - list_for_each(&heap_eden->pages, page, page_node) { - page->flags.before_sweep = TRUE; + if (ruby_enable_autocompact && is_full_marking(objspace)) { + gc_compact_start(objspace); + } + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + list_for_each(&(SIZE_POOL_EDEN_HEAP(&size_pools[i])->pages), page, page_node) { + page->flags.before_sweep = TRUE; + } + } + + /* Sweep every size pool. */ + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); } - gc_sweep_step(objspace, heap_eden); } - gc_heap_prepare_minimum_pages(objspace, heap_eden); +#if !USE_RVARGC + rb_size_pool_t *size_pool = &size_pools[0]; + gc_heap_prepare_minimum_pages(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); +#endif } /* Marking - Marking stack */ @@ -4529,10 +6012,52 @@ free_stack_chunks(mark_stack_t *stack) static void push_mark_stack(mark_stack_t *stack, VALUE data) { - if (stack->index == stack->limit) { - push_mark_stack_chunk(stack); + VALUE obj = data; + switch (BUILTIN_TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + case T_FLOAT: + case T_STRING: + case T_REGEXP: + case T_ARRAY: + case T_HASH: + case T_STRUCT: + case T_BIGNUM: + case T_FILE: + case T_DATA: + case T_MATCH: + case T_COMPLEX: + case T_RATIONAL: + case T_TRUE: + case T_FALSE: + case T_SYMBOL: + case T_IMEMO: + case T_ICLASS: + if (stack->index == stack->limit) { + push_mark_stack_chunk(stack); + } + stack->chunk->data[stack->index++] = data; + return; + + case T_NONE: + case T_NIL: + case T_FIXNUM: + case T_MOVED: + case T_ZOMBIE: + case T_UNDEF: + case T_MASK: + rb_bug("push_mark_stack() called for broken object"); + break; + + case T_NODE: + UNEXPECTED_NODE(push_mark_stack); + break; } - stack->chunk->data[stack->index++] = data; + + rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s", + BUILTIN_TYPE(obj), (void *)data, + is_pointer_to_heap(&rb_objspace, (void *)data) ? "corrupted object" : "non object"); } static int @@ -4551,35 +6076,6 @@ pop_mark_stack(mark_stack_t *stack, VALUE *data) return TRUE; } -#if GC_ENABLE_INCREMENTAL_MARK -static int -invalidate_mark_stack_chunk(stack_chunk_t *chunk, int limit, VALUE obj) -{ - int i; - for (i=0; idata[i] == obj) { - chunk->data[i] = Qundef; - return TRUE; - } - } - return FALSE; -} - -static void -invalidate_mark_stack(mark_stack_t *stack, VALUE obj) -{ - stack_chunk_t *chunk = stack->chunk; - int limit = stack->index; - - while (chunk) { - if (invalidate_mark_stack_chunk(chunk, limit, obj)) return; - chunk = chunk->next; - limit = stack->limit; - } - rb_bug("invalid_mark_stack: unreachable"); -} -#endif - static void init_mark_stack(mark_stack_t *stack) { @@ -4587,7 +6083,6 @@ init_mark_stack(mark_stack_t *stack) MEMZERO(stack, mark_stack_t, 1); stack->index = stack->limit = STACK_CHUNK_SIZE; - stack->cache_size = 0; for (i=0; i < 4; i++) { add_stack_chunk_cache(stack, stack_chunk_alloc()); @@ -4603,11 +6098,6 @@ init_mark_stack(mark_stack_t *stack) #define STACK_END (ec->machine.stack_end) #define STACK_LEVEL_MAX (ec->machine.stack_maxsize/sizeof(VALUE)) -#ifdef __EMSCRIPTEN__ -#undef STACK_GROW_DIRECTION -#define STACK_GROW_DIRECTION 1 -#endif - #if STACK_GROW_DIRECTION < 0 # define STACK_LENGTH (size_t)(STACK_START - STACK_END) #elif STACK_GROW_DIRECTION > 0 @@ -4646,7 +6136,7 @@ ruby_stack_length(VALUE **p) # define PREVENT_STACK_OVERFLOW 0 #endif #endif -#if PREVENT_STACK_OVERFLOW +#if PREVENT_STACK_OVERFLOW && !defined(__EMSCRIPTEN__) static int stack_check(rb_execution_context_t *ec, int water_mark) { @@ -4675,32 +6165,32 @@ ruby_stack_check(void) return stack_check(GET_EC(), STACKFRAME_FOR_CALL_CFUNC); } -ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void mark_locations_array(rb_objspace_t *objspace, register const VALUE *x, register long n)); +ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE))); static void -mark_locations_array(rb_objspace_t *objspace, register const VALUE *x, register long n) +each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE)) { VALUE v; while (n--) { v = *x; - gc_mark_maybe(objspace, v); + cb(objspace, v); x++; } } static void -gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end) +gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void (*cb)(rb_objspace_t *, VALUE)) { long n; if (end <= start) return; n = end - start; - mark_locations_array(objspace, start, n); + each_location(objspace, start, n, cb); } void rb_gc_mark_locations(const VALUE *start, const VALUE *end) { - gc_mark_locations(&rb_objspace, start, end); + gc_mark_locations(&rb_objspace, start, end, gc_mark_maybe); } static void @@ -4725,13 +6215,12 @@ rb_gc_mark_values(long n, const VALUE *values) } static void -gc_mark_and_pin_stack_values(rb_objspace_t *objspace, long n, const VALUE *values) +gc_mark_stack_values(rb_objspace_t *objspace, long n, const VALUE *values) { long i; for (i=0; imark_func_data == NULL && RHASH_TRANSIENT_P(hash)) { + if (LIKELY(during_gc) && RHASH_TRANSIENT_P(hash)) { rb_transient_heap_mark(hash, RHASH_AR_TABLE(hash)); } } @@ -4876,10 +6373,16 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me) if (def) { switch (def->type) { - case VM_METHOD_TYPE_ISEQ: - if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr); - gc_mark(objspace, (VALUE)def->body.iseq.cref); - break; + case VM_METHOD_TYPE_ISEQ: + if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr); + gc_mark(objspace, (VALUE)def->body.iseq.cref); + + if (def->iseq_overload && me->defined_class) { + // it can be a key of "overloaded_cme" table + // so it should be pinned. + gc_mark_and_pin(objspace, (VALUE)me); + } + break; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: gc_mark(objspace, def->body.attr.location); @@ -4951,15 +6454,16 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) ((start) = STACK_END, (end) = STACK_START) : ((start) = STACK_START, (end) = STACK_END+(appendix))) #endif -static void mark_stack_locations(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end); +static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, + const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)); +#ifndef __EMSCRIPTEN__ static void mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { union { rb_jmp_buf j; - VALUE v[sizeof(rb_jmp_buf) / sizeof(VALUE)]; + VALUE v[sizeof(rb_jmp_buf) / (sizeof(VALUE))]; } save_regs_gc_mark; VALUE *stack_start, *stack_end; @@ -4974,32 +6478,59 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - mark_locations_array(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v)); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe); - mark_stack_locations(objspace, ec, stack_start, stack_end); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); } +#else -void -rb_gc_mark_machine_stack(const rb_execution_context_t *ec) +static VALUE *rb_emscripten_stack_range_tmp[2]; + +static void +rb_emscripten_mark_locations(void *begin, void *end) +{ + rb_emscripten_stack_range_tmp[0] = begin; + rb_emscripten_stack_range_tmp[1] = end; +} + +static void +mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) +{ + emscripten_scan_stack(rb_emscripten_mark_locations); + each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe); + + emscripten_scan_registers(rb_emscripten_mark_locations); + each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe); +} +#endif + +static void +each_machine_stack_value(const rb_execution_context_t *ec, void (*cb)(rb_objspace_t *, VALUE)) { rb_objspace_t *objspace = &rb_objspace; VALUE *stack_start, *stack_end; GET_STACK_BOUNDS(stack_start, stack_end, 0); - mark_stack_locations(objspace, ec, stack_start, stack_end); + each_stack_location(objspace, ec, stack_start, stack_end, cb); +} + +void +rb_gc_mark_machine_stack(const rb_execution_context_t *ec) +{ + each_machine_stack_value(ec, gc_mark_maybe); } static void -mark_stack_locations(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end) +each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, + const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)) { - gc_mark_locations(objspace, stack_start, stack_end); + gc_mark_locations(objspace, stack_start, stack_end, cb); #if defined(__mc68000__) gc_mark_locations(objspace, (VALUE*)((char*)stack_start + 2), - (VALUE*)((char*)stack_end - 2)); + (VALUE*)((char*)stack_end - 2), cb); #endif } @@ -5026,7 +6557,6 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) /* Garbage can live on the stack, so do not mark or pin */ switch (BUILTIN_TYPE(obj)) { - case T_MOVED: case T_ZOMBIE: case T_NONE: break; @@ -5051,12 +6581,12 @@ rb_gc_mark_maybe(VALUE obj) static inline int gc_mark_set(rb_objspace_t *objspace, VALUE obj) { + ASSERT_vm_locking(); if (RVALUE_MARKED(obj)) return 0; MARK_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj); return 1; } -#if USE_RGENGC static int gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj) { @@ -5080,12 +6610,10 @@ gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj) return FALSE; } } -#endif static void rgengc_check_relation(rb_objspace_t *objspace, VALUE obj) { -#if USE_RGENGC const VALUE old_parent = objspace->rgengc.parent_object; if (old_parent) { /* parent object is old */ @@ -5118,7 +6646,6 @@ rgengc_check_relation(rb_objspace_t *objspace, VALUE obj) } GC_ASSERT(old_parent == objspace->rgengc.parent_object); -#endif } static void @@ -5141,7 +6668,6 @@ gc_grey(rb_objspace_t *objspace, VALUE obj) static void gc_aging(rb_objspace_t *objspace, VALUE obj) { -#if USE_RGENGC struct heap_page *page = GET_HEAP_PAGE(obj); GC_ASSERT(RVALUE_MARKING(obj) == FALSE); @@ -5158,25 +6684,40 @@ gc_aging(rb_objspace_t *objspace, VALUE obj) } } check_rvalue_consistency(obj); -#endif /* USE_RGENGC */ objspace->marked_slots++; } NOINLINE(static void gc_mark_ptr(rb_objspace_t *objspace, VALUE obj)); +static void reachable_objects_from_callback(VALUE obj); static void gc_mark_ptr(rb_objspace_t *objspace, VALUE obj) { - if (LIKELY(objspace->mark_func_data == NULL)) { + if (LIKELY(during_gc)) { rgengc_check_relation(objspace, obj); if (!gc_mark_set(objspace, obj)) return; /* already marked */ - if (RB_TYPE_P(obj, T_NONE)) rb_bug("try to mark T_NONE object"); /* check here will help debugging */ + + if (0) { // for debug GC marking miss + if (objspace->rgengc.parent_object) { + RUBY_DEBUG_LOG("%p (%s) parent:%p (%s)", + (void *)obj, obj_type_name(obj), + (void *)objspace->rgengc.parent_object, obj_type_name(objspace->rgengc.parent_object)); + } + else { + RUBY_DEBUG_LOG("%p (%s)", (void *)obj, obj_type_name(obj)); + } + } + + if (UNLIKELY(RB_TYPE_P(obj, T_NONE))) { + rp(obj); + rb_bug("try to mark T_NONE object"); /* check here will help debugging */ + } gc_aging(objspace, obj); gc_grey(objspace, obj); } else { - objspace->mark_func_data->mark_func(obj, objspace->mark_func_data->data); + reachable_objects_from_callback(obj); } } @@ -5185,7 +6726,9 @@ gc_pin(rb_objspace_t *objspace, VALUE obj) { GC_ASSERT(is_markable_object(objspace, obj)); if (UNLIKELY(objspace->flags.during_compacting)) { - MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj); + if (LIKELY(during_gc)) { + MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj); + } } } @@ -5229,14 +6772,12 @@ rb_objspace_marked_object_p(VALUE obj) static inline void gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) { -#if USE_RGENGC if (RVALUE_OLD_P(obj)) { objspace->rgengc.parent_object = obj; } else { objspace->rgengc.parent_object = Qfalse; } -#endif } static void @@ -5246,15 +6787,20 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_env: { const rb_env_t *env = (const rb_env_t *)obj; - GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); - gc_mark_values(objspace, (long)env->env_size, env->env); - VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); - gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); - gc_mark(objspace, (VALUE)env->iseq); + + if (LIKELY(env->ep)) { + // just after newobj() can be NULL here. + GC_ASSERT(env->ep[VM_ENV_DATA_INDEX_ENV] == obj); + GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); + gc_mark_values(objspace, (long)env->env_size, env->env); + VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); + gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); + gc_mark(objspace, (VALUE)env->iseq); + } } return; case imemo_cref: - gc_mark(objspace, RANY(obj)->as.imemo.cref.klass); + gc_mark(objspace, RANY(obj)->as.imemo.cref.klass_or_self); gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next); gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements); return; @@ -5295,6 +6841,21 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_parser_strterm: rb_strterm_mark(obj); return; + case imemo_callinfo: + return; + case imemo_callcache: + { + const struct rb_callcache *cc = (const struct rb_callcache *)obj; + // should not mark klass here + gc_mark(objspace, (VALUE)vm_cc_cme(cc)); + } + return; + case imemo_constcache: + { + const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj; + gc_mark(objspace, ice->value); + } + return; #if VM_CHECK_MODE > 0 default: VM_UNREACHABLE(gc_mark_imemo); @@ -5332,6 +6893,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) case T_IMEMO: gc_mark_imemo(objspace, obj); return; + + default: + break; } gc_mark(objspace, any->as.basic.klass); @@ -5343,13 +6907,15 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) gc_mark(objspace, RCLASS_SUPER(obj)); } if (!RCLASS_EXT(obj)) break; + mark_m_tbl(objspace, RCLASS_M_TBL(obj)); + cc_table_mark(objspace, obj); mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj)); mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); break; case T_ICLASS: - if (FL_TEST(obj, RICLASS_IS_ORIGIN)) { + if (RICLASS_OWNS_M_TBL_P(obj)) { mark_m_tbl(objspace, RCLASS_M_TBL(obj)); } if (RCLASS_SUPER(obj)) { @@ -5357,6 +6923,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) } if (!RCLASS_EXT(obj)) break; mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj)); + cc_table_mark(objspace, obj); break; case T_ARRAY: @@ -5371,7 +6938,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) gc_mark(objspace, ptr[i]); } - if (objspace->mark_func_data == NULL) { + if (LIKELY(during_gc)) { if (!FL_TEST_RAW(obj, RARRAY_EMBED_FLAG) && RARRAY_TRANSIENT_P(obj)) { rb_transient_heap_mark(obj, ptr); @@ -5406,22 +6973,21 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) { const VALUE * const ptr = ROBJECT_IVPTR(obj); - if (ptr) { - uint32_t i, len = ROBJECT_NUMIV(obj); - for (i = 0; i < len; i++) { - gc_mark(objspace, ptr[i]); - } + uint32_t i, len = ROBJECT_NUMIV(obj); + for (i = 0; i < len; i++) { + gc_mark(objspace, ptr[i]); + } - if (objspace->mark_func_data == NULL && + if (LIKELY(during_gc) && ROBJ_TRANSIENT_P(obj)) { - rb_transient_heap_mark(obj, ptr); - } + rb_transient_heap_mark(obj, ptr); } } break; case T_FILE: if (any->as.file.fptr) { + gc_mark(objspace, any->as.file.fptr->self); gc_mark(objspace, any->as.file.fptr->pathv); gc_mark(objspace, any->as.file.fptr->tied_io_for_writing); gc_mark(objspace, any->as.file.fptr->writeconv_asciicompat); @@ -5462,7 +7028,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) gc_mark(objspace, ptr[i]); } - if (objspace->mark_func_data == NULL && + if (LIKELY(during_gc) && RSTRUCT_TRANSIENT_P(obj)) { rb_transient_heap_mark(obj, ptr); } @@ -5587,9 +7153,7 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp) if (categoryp) *categoryp = "xxx"; -#if USE_RGENGC objspace->rgengc.parent_object = Qfalse; -#endif #if PRINT_ROOT_TICKS #define MARK_CHECKPOINT_PRINT_TICK(category) do { \ @@ -5731,8 +7295,10 @@ static int allrefs_add(struct allrefs *data, VALUE obj) { struct reflist *refs; + st_data_t r; - if (st_lookup(data->references, obj, (st_data_t *)&refs)) { + if (st_lookup(data->references, obj, &r)) { + refs = (struct reflist *)r; reflist_add(refs, data->root_obj); return 0; } @@ -5764,15 +7330,20 @@ allrefs_roots_i(VALUE obj, void *ptr) push_mark_stack(&data->mark_stack, obj); } } +#define PUSH_MARK_FUNC_DATA(v) do { \ + struct gc_mark_func_data_struct *prev_mark_func_data = GET_RACTOR()->mfd; \ + GET_RACTOR()->mfd = (v); + +#define POP_MARK_FUNC_DATA() GET_RACTOR()->mfd = prev_mark_func_data;} while (0) static st_table * objspace_allrefs(rb_objspace_t *objspace) { struct allrefs data; - struct mark_func_data_struct mfd; + struct gc_mark_func_data_struct mfd; VALUE obj; - int prev_dont_gc = dont_gc; - dont_gc = TRUE; + int prev_dont_gc = dont_gc_val(); + dont_gc_on(); data.objspace = objspace; data.references = st_init_numtable(); @@ -5783,7 +7354,7 @@ objspace_allrefs(rb_objspace_t *objspace) /* traverse root objects */ PUSH_MARK_FUNC_DATA(&mfd); - objspace->mark_func_data = &mfd; + GET_RACTOR()->mfd = &mfd; gc_mark_roots(objspace, &data.category); POP_MARK_FUNC_DATA(); @@ -5793,12 +7364,12 @@ objspace_allrefs(rb_objspace_t *objspace) } free_stack_chunks(&data.mark_stack); - dont_gc = prev_dont_gc; + dont_gc_set(prev_dont_gc); return data.references; } static int -objspace_allrefs_destruct_i(st_data_t key, st_data_t value, void *ptr) +objspace_allrefs_destruct_i(st_data_t key, st_data_t value, st_data_t ptr) { struct reflist *refs = (struct reflist *)value; reflist_destruct(refs); @@ -5827,13 +7398,14 @@ allrefs_dump_i(st_data_t k, st_data_t v, st_data_t ptr) static void allrefs_dump(rb_objspace_t *objspace) { - fprintf(stderr, "[all refs] (size: %d)\n", (int)objspace->rgengc.allrefs_table->num_entries); + VALUE size = objspace->rgengc.allrefs_table->num_entries; + fprintf(stderr, "[all refs] (size: %"PRIuVALUE")\n", size); st_foreach(objspace->rgengc.allrefs_table, allrefs_dump_i, 0); } #endif static int -gc_check_after_marks_i(st_data_t k, st_data_t v, void *ptr) +gc_check_after_marks_i(st_data_t k, st_data_t v, st_data_t ptr) { VALUE obj = k; struct reflist *refs = (struct reflist *)v; @@ -5896,14 +7468,11 @@ struct verify_internal_consistency_struct { size_t live_object_count; size_t zombie_object_count; -#if USE_RGENGC VALUE parent; size_t old_object_count; size_t remembered_shady_count; -#endif }; -#if USE_RGENGC static void check_generation_i(const VALUE child, void *ptr) { @@ -5934,7 +7503,6 @@ check_color_i(const VALUE child, void *ptr) data->err_count++; } } -#endif static void check_children_i(const VALUE child, void *ptr) @@ -5950,9 +7518,9 @@ check_children_i(const VALUE child, void *ptr) } static int -verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, void *ptr) +verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, + struct verify_internal_consistency_struct *data) { - struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr; VALUE obj; rb_objspace_t *objspace = data->objspace; @@ -5972,7 +7540,6 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data); } -#if USE_RGENGC /* check health of children */ if (RVALUE_OLD_P(obj)) data->old_object_count++; if (RVALUE_WB_UNPROTECTED(obj) && RVALUE_UNCOLLECTIBLE(obj)) data->remembered_shady_count++; @@ -5990,7 +7557,6 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data); } } -#endif } else { if (BUILTIN_TYPE(obj) == T_ZOMBIE) { @@ -6010,15 +7576,15 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v static int gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj) { -#if USE_RGENGC int i; unsigned int has_remembered_shady = FALSE; unsigned int has_remembered_old = FALSE; int remembered_old_objects = 0; int free_objects = 0; int zombie_objects = 0; + int stride = page->slot_size / sizeof(RVALUE); - for (i=0; itotal_slots; i++) { + for (i=0; itotal_slots; i+=stride) { VALUE val = (VALUE)&page->start[i]; void *poisoned = asan_poisoned_object_p(val); asan_unpoison_object(val, false); @@ -6060,17 +7626,14 @@ gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj) if (0) { /* free_slots may not equal to free_objects */ if (page->free_slots != free_objects) { - rb_bug("page %p's free_slots should be %d, but %d\n", (void *)page, (int)page->free_slots, free_objects); + rb_bug("page %p's free_slots should be %d, but %d\n", (void *)page, page->free_slots, free_objects); } } if (page->final_slots != zombie_objects) { - rb_bug("page %p's final_slots should be %d, but %d\n", (void *)page, (int)page->final_slots, zombie_objects); + rb_bug("page %p's final_slots should be %d, but %d\n", (void *)page, page->final_slots, zombie_objects); } return remembered_old_objects; -#else - return 0; -#endif } static int @@ -6083,13 +7646,14 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head) asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); RVALUE *p = page->freelist; while (p) { - RVALUE *prev = p; - asan_unpoison_object((VALUE)p, false); - if (BUILTIN_TYPE(p) != T_NONE) { - fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info((VALUE)p)); + VALUE vp = (VALUE)p; + VALUE prev = vp; + asan_unpoison_object(vp, false); + if (BUILTIN_TYPE(vp) != T_NONE) { + fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info(vp)); } p = p->as.free.next; - asan_poison_object((VALUE)prev); + asan_poison_object(prev); } asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); @@ -6105,8 +7669,10 @@ static int gc_verify_heap_pages(rb_objspace_t *objspace) { int remembered_old_objects = 0; - remembered_old_objects += gc_verify_heap_pages_(objspace, &heap_eden->pages); - remembered_old_objects += gc_verify_heap_pages_(objspace, &heap_tomb->pages); + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + remembered_old_objects += gc_verify_heap_pages_(objspace, &(SIZE_POOL_EDEN_HEAP(&size_pools[i])->pages)); + remembered_old_objects += gc_verify_heap_pages_(objspace, &(SIZE_POOL_TOMB_HEAP(&size_pools[i])->pages)); + } return remembered_old_objects; } @@ -6124,12 +7690,11 @@ static VALUE gc_verify_internal_consistency_m(VALUE dummy) { gc_verify_internal_consistency(&rb_objspace); - return Qnil; } static void -gc_verify_internal_consistency(rb_objspace_t *objspace) +gc_verify_internal_consistency_(rb_objspace_t *objspace) { struct verify_internal_consistency_struct data = {0}; @@ -6137,8 +7702,15 @@ gc_verify_internal_consistency(rb_objspace_t *objspace) gc_report(5, objspace, "gc_verify_internal_consistency: start\n"); /* check relations */ + for (size_t i = 0; i < heap_allocated_pages; i++) { + struct heap_page *page = heap_pages_sorted[i]; + short slot_size = page->slot_size; - objspace_each_objects_without_setup(objspace, verify_internal_consistency_i, &data); + uintptr_t start = (uintptr_t)page->start; + uintptr_t end = start + page->total_slots * slot_size; + + verify_internal_consistency_i((void *)start, (void *)end, slot_size, &data); + } if (data.err_count != 0) { #if RGENGC_CHECK_MODE >= 5 @@ -6154,24 +7726,28 @@ gc_verify_internal_consistency(rb_objspace_t *objspace) /* check counters */ - if (!is_lazy_sweeping(heap_eden) && !finalizing) { + if (!is_lazy_sweeping(objspace) && + !finalizing && + ruby_single_main_ractor != NULL) { if (objspace_live_slots(objspace) != data.live_object_count) { - fprintf(stderr, "heap_pages_final_slots: %d, objspace->profile.total_freed_objects: %d\n", - (int)heap_pages_final_slots, (int)objspace->profile.total_freed_objects); - rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace_live_slots(objspace), data.live_object_count); + fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", " + "objspace->profile.total_freed_objects: %"PRIdSIZE"\n", + heap_pages_final_slots, objspace->profile.total_freed_objects); + rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", + objspace_live_slots(objspace), data.live_object_count); } } -#if USE_RGENGC if (!is_marking(objspace)) { if (objspace->rgengc.old_objects != data.old_object_count) { - rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.old_objects, data.old_object_count); + rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", + objspace->rgengc.old_objects, data.old_object_count); } if (objspace->rgengc.uncollectible_wb_unprotected_objects != data.remembered_shady_count) { - rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.uncollectible_wb_unprotected_objects, data.remembered_shady_count); + rb_bug("inconsistent number of wb unprotected objects: expect %"PRIuSIZE", but %"PRIuSIZE".", + objspace->rgengc.uncollectible_wb_unprotected_objects, data.remembered_shady_count); } } -#endif if (!finalizing) { size_t list_count = 0; @@ -6187,19 +7763,36 @@ gc_verify_internal_consistency(rb_objspace_t *objspace) if (heap_pages_final_slots != data.zombie_object_count || heap_pages_final_slots != list_count) { - rb_bug("inconsistent finalizing object count:\n" - " expect %"PRIuSIZE"\n" - " but %"PRIuSIZE" zombies\n" - " heap_pages_deferred_final list has %"PRIuSIZE" items.", - heap_pages_final_slots, - data.zombie_object_count, - list_count); + rb_bug("inconsistent finalizing object count:\n" + " expect %"PRIuSIZE"\n" + " but %"PRIuSIZE" zombies\n" + " heap_pages_deferred_final list has %"PRIuSIZE" items.", + heap_pages_final_slots, + data.zombie_object_count, + list_count); } } gc_report(5, objspace, "gc_verify_internal_consistency: OK\n"); } +static void +gc_verify_internal_consistency(rb_objspace_t *objspace) +{ + RB_VM_LOCK_ENTER(); + { + rb_vm_barrier(); // stop other ractors + + unsigned int prev_during_gc = during_gc; + during_gc = FALSE; // stop gc here + { + gc_verify_internal_consistency_(objspace); + } + during_gc = prev_during_gc; + } + RB_VM_LOCK_LEAVE(); +} + void rb_gc_verify_internal_consistency(void) { @@ -6222,66 +7815,85 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark) gc_report(1, objspace, "gc_marks_start: (%s)\n", full_mark ? "full" : "minor"); gc_mode_transition(objspace, gc_mode_marking); -#if USE_RGENGC if (full_mark) { #if GC_ENABLE_INCREMENTAL_MARK objspace->rincgc.step_slots = (objspace->marked_slots * 2) / ((objspace->rincgc.pooled_slots / HEAP_PAGE_OBJ_LIMIT) + 1); - if (0) fprintf(stderr, "objspace->marked_slots: %d, objspace->rincgc.pooled_page_num: %d, objspace->rincgc.step_slots: %d, \n", - (int)objspace->marked_slots, (int)objspace->rincgc.pooled_slots, (int)objspace->rincgc.step_slots); + if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE", " + "objspace->rincgc.pooled_page_num: %"PRIdSIZE", " + "objspace->rincgc.step_slots: %"PRIdSIZE", \n", + objspace->marked_slots, objspace->rincgc.pooled_slots, objspace->rincgc.step_slots); #endif objspace->flags.during_minor_gc = FALSE; + if (ruby_enable_autocompact) { + objspace->flags.during_compacting |= TRUE; + } objspace->profile.major_gc_count++; objspace->rgengc.uncollectible_wb_unprotected_objects = 0; objspace->rgengc.old_objects = 0; objspace->rgengc.last_major_gc = objspace->profile.count; objspace->marked_slots = 0; - rgengc_mark_and_rememberset_clear(objspace, heap_eden); + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rgengc_mark_and_rememberset_clear(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i])); + } } else { objspace->flags.during_minor_gc = TRUE; objspace->marked_slots = objspace->rgengc.old_objects + objspace->rgengc.uncollectible_wb_unprotected_objects; /* uncollectible objects are marked already */ objspace->profile.minor_gc_count++; - rgengc_rememberset_mark(objspace, heap_eden); + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rgengc_rememberset_mark(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i])); + } } -#endif gc_mark_roots(objspace, NULL); - gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %d\n", full_mark ? "full" : "minor", (int)mark_stack_size(&objspace->mark_stack)); + gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %"PRIdSIZE"\n", + full_mark ? "full" : "minor", mark_stack_size(&objspace->mark_stack)); } #if GC_ENABLE_INCREMENTAL_MARK +static inline void +gc_marks_wb_unprotected_objects_plane(rb_objspace_t *objspace, uintptr_t p, bits_t bits) +{ + if (bits) { + do { + if (bits & 1) { + gc_report(2, objspace, "gc_marks_wb_unprotected_objects: marked shady: %s\n", obj_info((VALUE)p)); + GC_ASSERT(RVALUE_WB_UNPROTECTED((VALUE)p)); + GC_ASSERT(RVALUE_MARKED((VALUE)p)); + gc_mark_children(objspace, (VALUE)p); + } + p += sizeof(RVALUE); + bits >>= 1; + } while (bits); + } +} + static void -gc_marks_wb_unprotected_objects(rb_objspace_t *objspace) +gc_marks_wb_unprotected_objects(rb_objspace_t *objspace, rb_heap_t *heap) { struct heap_page *page = 0; - list_for_each(&heap_eden->pages, page, page_node) { + list_for_each(&heap->pages, page, page_node) { bits_t *mark_bits = page->mark_bits; bits_t *wbun_bits = page->wb_unprotected_bits; RVALUE *p = page->start; - RVALUE *offset = p - NUM_IN_PAGE(p); size_t j; - for (j=0; j>= NUM_IN_PAGE(p); + gc_marks_wb_unprotected_objects_plane(objspace, (uintptr_t)p, bits); + p += (BITS_BITLENGTH - NUM_IN_PAGE(p)); - if (bits) { - p = offset + j * BITS_BITLENGTH; + for (j=1; j>= 1; - } while (bits); - } + gc_marks_wb_unprotected_objects_plane(objspace, (uintptr_t)p, bits); + p += BITS_BITLENGTH; } } @@ -6308,20 +7920,25 @@ gc_marks_finish(rb_objspace_t *objspace) #if GC_ENABLE_INCREMENTAL_MARK /* finish incremental GC */ if (is_incremental_marking(objspace)) { - if (heap_eden->pooled_pages) { - heap_move_pooled_pages_to_free_pages(heap_eden); - gc_report(1, objspace, "gc_marks_finish: pooled pages are exists. retry.\n"); - return FALSE; /* continue marking phase */ - } + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(&size_pools[i]); + if (heap->pooled_pages) { + heap_move_pooled_pages_to_free_pages(heap); + gc_report(1, objspace, "gc_marks_finish: pooled pages are exists. retry.\n"); + return FALSE; /* continue marking phase */ + } + } if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) { - rb_bug("gc_marks_finish: mark stack is not empty (%d).", (int)mark_stack_size(&objspace->mark_stack)); + rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").", + mark_stack_size(&objspace->mark_stack)); } gc_mark_roots(objspace, 0); if (is_mark_stack_empty(&objspace->mark_stack) == FALSE) { - gc_report(1, objspace, "gc_marks_finish: not empty (%d). retry.\n", (int)mark_stack_size(&objspace->mark_stack)); + gc_report(1, objspace, "gc_marks_finish: not empty (%"PRIdSIZE"). retry.\n", + mark_stack_size(&objspace->mark_stack)); return FALSE; } @@ -6333,7 +7950,9 @@ gc_marks_finish(rb_objspace_t *objspace) objspace->flags.during_incremental_marking = FALSE; /* check children of all marked wb-unprotected objects */ - gc_marks_wb_unprotected_objects(objspace); + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + gc_marks_wb_unprotected_objects(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i])); + } } #endif /* GC_ENABLE_INCREMENTAL_MARK */ @@ -6341,32 +7960,35 @@ gc_marks_finish(rb_objspace_t *objspace) gc_verify_internal_consistency(objspace); #endif -#if USE_RGENGC if (is_full_marking(objspace)) { /* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */ const double r = gc_params.oldobject_limit_factor; objspace->rgengc.uncollectible_wb_unprotected_objects_limit = (size_t)(objspace->rgengc.uncollectible_wb_unprotected_objects * r); objspace->rgengc.old_objects_limit = (size_t)(objspace->rgengc.old_objects * r); } -#endif #if RGENGC_CHECK_MODE >= 4 + during_gc = FALSE; gc_marks_check(objspace, gc_check_after_marks_i, "after_marks"); + during_gc = TRUE; #endif { /* decide full GC is needed or not */ - rb_heap_t *heap = heap_eden; - size_t total_slots = heap_allocatable_pages * HEAP_PAGE_OBJ_LIMIT + heap->total_slots; + size_t total_slots = heap_allocatable_slots(objspace) + heap_eden_total_slots(objspace); size_t sweep_slots = total_slots - objspace->marked_slots; /* will be swept slots */ size_t max_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_max_ratio); size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio); int full_marking = is_full_marking(objspace); + const int r_cnt = GET_VM()->ractor.cnt; + const int r_mul = r_cnt > 8 ? 8 : r_cnt; // upto 8 - GC_ASSERT(heap->total_slots >= objspace->marked_slots); + GC_ASSERT(heap_eden_total_slots(objspace) >= objspace->marked_slots); /* setup free-able page counts */ - if (max_free_slots < gc_params.heap_init_slots) max_free_slots = gc_params.heap_init_slots; + if (max_free_slots < gc_params.heap_init_slots * r_mul) { + max_free_slots = gc_params.heap_init_slots * r_mul; + } if (sweep_slots > max_free_slots) { heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT; @@ -6375,28 +7997,34 @@ gc_marks_finish(rb_objspace_t *objspace) heap_pages_freeable_pages = 0; } - /* check free_min */ - if (min_free_slots < gc_params.heap_free_slots) min_free_slots = gc_params.heap_free_slots; + /* check free_min */ + if (min_free_slots < gc_params.heap_free_slots * r_mul) { + min_free_slots = gc_params.heap_free_slots * r_mul; + } -#if USE_RGENGC if (sweep_slots < min_free_slots) { if (!full_marking) { if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) { full_marking = TRUE; /* do not update last_major_gc, because full marking is not done. */ - goto increment; + /* goto increment; */ } else { gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n"); objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE; } } - else { - increment: + +#if !USE_RVARGC + if (full_marking) { + /* increment: */ gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n"); - heap_set_increment(objspace, heap_extend_pages(objspace, sweep_slots, total_slots)); - heap_increment(objspace, heap); + rb_size_pool_t *size_pool = &size_pools[0]; + size_pool_allocatable_pages_set(objspace, size_pool, heap_extend_pages(objspace, sweep_slots, total_slots, heap_allocated_pages + heap_allocatable_pages(objspace))); + + heap_increment(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); } +#endif } if (full_marking) { @@ -6416,29 +8044,25 @@ gc_marks_finish(rb_objspace_t *objspace) objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_FORCE; } - gc_report(1, objspace, "gc_marks_finish (marks %d objects, old %d objects, total %d slots, sweep %d slots, increment: %d, next GC: %s)\n", - (int)objspace->marked_slots, (int)objspace->rgengc.old_objects, (int)heap->total_slots, (int)sweep_slots, (int)heap_allocatable_pages, + gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, " + "old %"PRIdSIZE" objects, total %"PRIdSIZE" slots, " + "sweep %"PRIdSIZE" slots, increment: %"PRIdSIZE", next GC: %s)\n", + objspace->marked_slots, objspace->rgengc.old_objects, heap_eden_total_slots(objspace), sweep_slots, heap_allocatable_pages(objspace), objspace->rgengc.need_major_gc ? "major" : "minor"); -#else /* USE_RGENGC */ - if (sweep_slots < min_free_slots) { - gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n"); - heap_set_increment(objspace, heap_extend_pages(objspace, sweep_slot, total_slot)); - heap_increment(objspace, heap); - } -#endif } rb_transient_heap_finish_marking(); + rb_ractor_finish_marking(); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_MARK, 0); return TRUE; } +#if GC_ENABLE_INCREMENTAL_MARK static void -gc_marks_step(rb_objspace_t *objspace, int slots) +gc_marks_step(rb_objspace_t *objspace, size_t slots) { -#if GC_ENABLE_INCREMENTAL_MARK GC_ASSERT(is_marking(objspace)); if (gc_mark_stacked_objects_incremental(objspace, slots)) { @@ -6447,9 +8071,9 @@ gc_marks_step(rb_objspace_t *objspace, int slots) gc_sweep(objspace); } } - if (0) fprintf(stderr, "objspace->marked_slots: %d\n", (int)objspace->marked_slots); -#endif + if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE"\n", objspace->marked_slots); } +#endif static void gc_marks_rest(rb_objspace_t *objspace) @@ -6457,7 +8081,9 @@ gc_marks_rest(rb_objspace_t *objspace) gc_report(1, objspace, "gc_marks_rest\n"); #if GC_ENABLE_INCREMENTAL_MARK - heap_eden->pooled_pages = NULL; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + SIZE_POOL_EDEN_HEAP(&size_pools[i])->pooled_pages = NULL; + } #endif if (is_incremental_marking(objspace)) { @@ -6475,42 +8101,41 @@ gc_marks_rest(rb_objspace_t *objspace) } static void -gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap) +gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap) { - GC_ASSERT(dont_gc == FALSE); + GC_ASSERT(dont_gc_val() == FALSE); #if GC_ENABLE_INCREMENTAL_MARK - gc_enter(objspace, "marks_continue"); + unsigned int lock_lev; + gc_enter(objspace, gc_enter_event_mark_continue, &lock_lev); - PUSH_MARK_FUNC_DATA(NULL); - { - int slots = 0; - const char *from; + int slots = 0; + const char *from; - if (heap->pooled_pages) { - while (heap->pooled_pages && slots < HEAP_PAGE_OBJ_LIMIT) { - struct heap_page *page = heap_move_pooled_pages_to_free_pages(heap); - slots += page->free_slots; - } - from = "pooled-pages"; - } - else if (heap_increment(objspace, heap)) { - slots = heap->free_pages->free_slots; - from = "incremented-pages"; - } + if (heap->pooled_pages) { + while (heap->pooled_pages && slots < HEAP_PAGE_OBJ_LIMIT) { + struct heap_page *page = heap_move_pooled_pages_to_free_pages(heap); + slots += page->free_slots; + } + from = "pooled-pages"; + } + else if (heap_increment(objspace, size_pool, heap)) { + slots = heap->free_pages->free_slots; + from = "incremented-pages"; + } - if (slots > 0) { - gc_report(2, objspace, "gc_marks_continue: provide %d slots from %s.\n", slots, from); - gc_marks_step(objspace, (int)objspace->rincgc.step_slots); - } - else { - gc_report(2, objspace, "gc_marks_continue: no more pooled pages (stack depth: %d).\n", (int)mark_stack_size(&objspace->mark_stack)); - gc_marks_rest(objspace); - } + if (slots > 0) { + gc_report(2, objspace, "gc_marks_continue: provide %d slots from %s.\n", + slots, from); + gc_marks_step(objspace, objspace->rincgc.step_slots); + } + else { + gc_report(2, objspace, "gc_marks_continue: no more pooled pages (stack depth: %"PRIdSIZE").\n", + mark_stack_size(&objspace->mark_stack)); + gc_marks_rest(objspace); } - POP_MARK_FUNC_DATA(); - gc_exit(objspace, "marks_continue"); + gc_exit(objspace, gc_enter_event_mark_continue, &lock_lev); #endif } @@ -6519,29 +8144,19 @@ gc_marks(rb_objspace_t *objspace, int full_mark) { gc_prof_mark_timer_start(objspace); - PUSH_MARK_FUNC_DATA(NULL); - { - /* setup marking */ + /* setup marking */ -#if USE_RGENGC - gc_marks_start(objspace, full_mark); - if (!is_incremental_marking(objspace)) { - gc_marks_rest(objspace); - } + gc_marks_start(objspace, full_mark); + if (!is_incremental_marking(objspace)) { + gc_marks_rest(objspace); + } #if RGENGC_PROFILE > 0 - if (gc_prof_record(objspace)) { - gc_profile_record *record = gc_prof_record(objspace); - record->old_objects = objspace->rgengc.old_objects; - } -#endif - -#else /* USE_RGENGC */ - gc_marks_start(objspace, TRUE); - gc_marks_rest(objspace); -#endif + if (gc_prof_record(objspace)) { + gc_profile_record *record = gc_prof_record(objspace); + record->old_objects = objspace->rgengc.old_objects; } - POP_MARK_FUNC_DATA(); +#endif gc_prof_mark_timer_stop(objspace); } @@ -6556,19 +8171,17 @@ gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...) va_list args; const char *status = " "; -#if USE_RGENGC if (during_gc) { status = is_full_marking(objspace) ? "+" : "-"; } else { - if (is_lazy_sweeping(heap_eden)) { + if (is_lazy_sweeping(objspace)) { status = "S"; } if (is_incremental_marking(objspace)) { status = "M"; } } -#endif va_start(args, fmt); vsnprintf(buf, 1024, fmt, args); @@ -6579,8 +8192,6 @@ gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...) } } -#if USE_RGENGC - /* bit operations */ static int @@ -6655,6 +8266,25 @@ rgengc_remembered(rb_objspace_t *objspace, VALUE obj) #define PROFILE_REMEMBERSET_MARK 0 #endif +static inline void +rgengc_rememberset_mark_plane(rb_objspace_t *objspace, uintptr_t p, bits_t bitset) +{ + if (bitset) { + do { + if (bitset & 1) { + VALUE obj = (VALUE)p; + gc_report(2, objspace, "rgengc_rememberset_mark: mark %s\n", obj_info(obj)); + GC_ASSERT(RVALUE_UNCOLLECTIBLE(obj)); + GC_ASSERT(RVALUE_OLD_P(obj) || RVALUE_WB_UNPROTECTED(obj)); + + gc_mark_children(objspace, obj); + } + p += sizeof(RVALUE); + bitset >>= 1; + } while (bitset); + } +} + static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap) { @@ -6668,7 +8298,6 @@ rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap) list_for_each(&heap->pages, page, page_node) { if (page->flags.has_remembered_objects | page->flags.has_uncollectible_shady_objects) { RVALUE *p = page->start; - RVALUE *offset = p - NUM_IN_PAGE(p); bits_t bitset, bits[HEAP_PAGE_BITMAP_LIMIT]; bits_t *marking_bits = page->marking_bits; bits_t *uncollectible_bits = page->uncollectible_bits; @@ -6684,25 +8313,15 @@ rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap) } page->flags.has_remembered_objects = FALSE; - for (j=0; j < HEAP_PAGE_BITMAP_LIMIT; j++) { - bitset = bits[j]; - - if (bitset) { - p = offset + j * BITS_BITLENGTH; - - do { - if (bitset & 1) { - VALUE obj = (VALUE)p; - gc_report(2, objspace, "rgengc_rememberset_mark: mark %s\n", obj_info(obj)); - GC_ASSERT(RVALUE_UNCOLLECTIBLE(obj)); - GC_ASSERT(RVALUE_OLD_P(obj) || RVALUE_WB_UNPROTECTED(obj)); + bitset = bits[0]; + bitset >>= NUM_IN_PAGE(p); + rgengc_rememberset_mark_plane(objspace, (uintptr_t)p, bitset); + p += (BITS_BITLENGTH - NUM_IN_PAGE(p)); - gc_mark_children(objspace, obj); - } - p++; - bitset >>= 1; - } while (bitset); - } + for (j=1; j < HEAP_PAGE_BITMAP_LIMIT; j++) { + bitset = bits[j]; + rgengc_rememberset_mark_plane(objspace, (uintptr_t)p, bitset); + p += BITS_BITLENGTH; } } #if PROFILE_REMEMBERSET_MARK @@ -6749,7 +8368,11 @@ gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace) #if 1 /* mark `a' and remember (default behavior) */ if (!rgengc_remembered(objspace, a)) { - rgengc_remember(objspace, a); + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + rgengc_remember(objspace, a); + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); gc_report(1, objspace, "gc_writebarrier_generational: %s (remembered) -> %s\n", obj_info(a), obj_info(b)); } #else @@ -6809,6 +8432,10 @@ gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace) gc_remember_unprotected(objspace, b); } } + + if (UNLIKELY(objspace->flags.during_compacting)) { + MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(b), b); + } } } #else @@ -6823,17 +8450,32 @@ rb_gc_writebarrier(VALUE a, VALUE b) if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const"); if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const"); + retry: if (!is_incremental_marking(objspace)) { - if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) { - return; - } - else { - gc_writebarrier_generational(a, b, objspace); - } + if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) { + // do nothing + } + else { + gc_writebarrier_generational(a, b, objspace); + } } - else { /* slow path */ - gc_writebarrier_incremental(a, b, objspace); + else { + bool retry = false; + /* slow path */ + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + if (is_incremental_marking(objspace)) { + gc_writebarrier_incremental(a, b, objspace); + } + else { + retry = true; + } + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); + + if (retry) goto retry; } + return; } void @@ -6897,7 +8539,7 @@ static st_table *rgengc_unprotect_logging_table; static int rgengc_unprotect_logging_exit_func_i(st_data_t key, st_data_t val, st_data_t arg) { - fprintf(stderr, "%s\t%d\n", (char *)key, (int)val); + fprintf(stderr, "%s\t%"PRIuVALUE"\n", (char *)key, (VALUE)val); return ST_CONTINUE; } @@ -6934,12 +8576,10 @@ rb_gc_unprotect_logging(void *objptr, const char *filename, int line) st_insert(rgengc_unprotect_logging_table, (st_data_t)ptr, cnt); } } -#endif /* USE_RGENGC */ void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj) { -#if USE_RGENGC rb_objspace_t *objspace = &rb_objspace; if (RVALUE_WB_UNPROTECTED(obj) && !RVALUE_WB_UNPROTECTED(dest)) { @@ -6953,7 +8593,6 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj) } check_rvalue_consistency(dest); -#endif } /* RGENGC analysis information */ @@ -6961,17 +8600,13 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj) VALUE rb_obj_rgengc_writebarrier_protected_p(VALUE obj) { -#if USE_RGENGC return RVALUE_WB_UNPROTECTED(obj) ? Qfalse : Qtrue; -#else - return Qfalse; -#endif } VALUE rb_obj_rgengc_promoted_p(VALUE obj) { - return OBJ_PROMOTED(obj) ? Qtrue : Qfalse; + return RBOOL(OBJ_PROMOTED(obj)); } size_t @@ -6979,29 +8614,23 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) { size_t n = 0; static ID ID_marked; -#if USE_RGENGC static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible, ID_pinned; -#endif if (!ID_marked) { #define I(s) ID_##s = rb_intern(#s); I(marked); -#if USE_RGENGC I(wb_protected); I(old); I(marking); I(uncollectible); I(pinned); -#endif #undef I } -#if USE_RGENGC if (RVALUE_WB_UNPROTECTED(obj) == 0 && nsize_pool_caches[size_pool_idx]; - gc_report(2, objspace, "rb_gc_force_recycle: %s\n", obj_info(obj)); + struct heap_page *page = cache->using_page; + RVALUE *freelist = cache->freelist; + RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", (void *)page, (void *)freelist); - if (is_old) { - if (RVALUE_MARKED(obj)) { - objspace->rgengc.old_objects--; - } - } - CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), obj); - CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); + heap_page_freelist_append(page, freelist); -#if GC_ENABLE_INCREMENTAL_MARK - if (is_incremental_marking(objspace)) { - if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj)) { - invalidate_mark_stack(&objspace->mark_stack, obj); - CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj); - } - CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj); - } - else { -#endif - if (is_old || !GET_HEAP_PAGE(obj)->flags.before_sweep) { - CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj); - } - CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj); -#if GC_ENABLE_INCREMENTAL_MARK + cache->using_page = NULL; + cache->freelist = NULL; } -#endif -#endif - - objspace->profile.total_freed_objects++; - - heap_page_add_freeobj(objspace, GET_HEAP_PAGE(obj), obj); +} - /* Disable counting swept_slots because there are no meaning. - * if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) { - * objspace->heap.swept_slots++; - * } - */ +void +rb_gc_force_recycle(VALUE obj) +{ + /* no-op */ } #ifndef MARK_OBJECT_ARY_BUCKET_SIZE @@ -7064,15 +8668,22 @@ rb_gc_force_recycle(VALUE obj) void rb_gc_register_mark_object(VALUE obj) { - VALUE ary_ary = GET_VM()->mark_object_ary; - VALUE ary = rb_ary_last(0, 0, ary_ary); + if (!is_pointer_to_heap(&rb_objspace, (void *)obj)) + return; - if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) { - ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE); - rb_ary_push(ary_ary, ary); - } + RB_VM_LOCK_ENTER(); + { + VALUE ary_ary = GET_VM()->mark_object_ary; + VALUE ary = rb_ary_last(0, 0, ary_ary); + + if (NIL_P(ary) || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) { + ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE); + rb_ary_push(ary_ary, ary); + } - rb_ary_push(ary, obj); + rb_ary_push(ary, obj); + } + RB_VM_LOCK_LEAVE(); } void @@ -7129,22 +8740,25 @@ enum { (FIXNUM_P(ruby_gc_stress_mode) && (FIX2LONG(ruby_gc_stress_mode) & (1<freelist && !heap->free_pages) { - if (!heap_increment(objspace, heap)) { - heap_set_increment(objspace, 1); - heap_increment(objspace, heap); - } + if (!heap->free_pages) { + if (!heap_increment(objspace, size_pool, heap)) { + size_pool_allocatable_pages_set(objspace, size_pool, 1); + heap_increment(objspace, size_pool, heap); + } } } static int ready_to_gc(rb_objspace_t *objspace) { - if (dont_gc || during_gc || ruby_disable_gc) { - heap_ready_to_gc(objspace, heap_eden); - return FALSE; + if (dont_gc_val() || during_gc || ruby_disable_gc) { + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + heap_ready_to_gc(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool)); + } + return FALSE; } else { return TRUE; @@ -7152,7 +8766,7 @@ ready_to_gc(rb_objspace_t *objspace) } static void -gc_reset_malloc_info(rb_objspace_t *objspace) +gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark) { gc_prof_set_malloc_info(objspace); { @@ -7186,7 +8800,7 @@ gc_reset_malloc_info(rb_objspace_t *objspace) /* reset oldmalloc info */ #if RGENGC_ESTIMATE_OLDMALLOC - if (!is_full_marking(objspace)) { + if (!full_mark) { if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) { objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDMALLOC; objspace->rgengc.oldmalloc_increase_limit = @@ -7197,12 +8811,12 @@ gc_reset_malloc_info(rb_objspace_t *objspace) } } - if (0) fprintf(stderr, "%d\t%d\t%u\t%u\t%d\n", - (int)rb_gc_count(), - (int)objspace->rgengc.need_major_gc, - (unsigned int)objspace->rgengc.oldmalloc_increase, - (unsigned int)objspace->rgengc.oldmalloc_increase_limit, - (unsigned int)gc_params.oldmalloc_limit_max); + if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n", + rb_gc_count(), + objspace->rgengc.need_major_gc, + objspace->rgengc.oldmalloc_increase, + objspace->rgengc.oldmalloc_increase_limit, + gc_params.oldmalloc_limit_max); } else { /* major GC */ @@ -7220,42 +8834,57 @@ gc_reset_malloc_info(rb_objspace_t *objspace) } static int -garbage_collect(rb_objspace_t *objspace, int reason) +garbage_collect(rb_objspace_t *objspace, unsigned int reason) { + int ret; + + RB_VM_LOCK_ENTER(); + { #if GC_PROFILE_MORE_DETAIL - objspace->profile.prepare_time = getrusage_time(); + objspace->profile.prepare_time = getrusage_time(); #endif - gc_rest(objspace); + gc_rest(objspace); #if GC_PROFILE_MORE_DETAIL - objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time; + objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time; #endif - return gc_start(objspace, reason); + ret = gc_start(objspace, reason); + } + RB_VM_LOCK_LEAVE(); + + return ret; } static int -gc_start(rb_objspace_t *objspace, int reason) +gc_start(rb_objspace_t *objspace, unsigned int reason) { - unsigned int do_full_mark = !!((unsigned)reason & GPR_FLAG_FULL_MARK); - unsigned int immediate_mark = (unsigned)reason & GPR_FLAG_IMMEDIATE_MARK; + unsigned int do_full_mark = !!(reason & GPR_FLAG_FULL_MARK); +#if GC_ENABLE_INCREMENTAL_MARK + unsigned int immediate_mark = reason & GPR_FLAG_IMMEDIATE_MARK; +#endif /* reason may be clobbered, later, so keep set immediate_sweep here */ - objspace->flags.immediate_sweep = !!((unsigned)reason & GPR_FLAG_IMMEDIATE_SWEEP); + objspace->flags.immediate_sweep = !!(reason & GPR_FLAG_IMMEDIATE_SWEEP); + + /* Explicitly enable compaction (GC.compact) */ + objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT); if (!heap_allocated_pages) return FALSE; /* heap is not ready */ if (!(reason & GPR_FLAG_METHOD) && !ready_to_gc(objspace)) return TRUE; /* GC is not allowed */ GC_ASSERT(gc_mode(objspace) == gc_mode_none); - GC_ASSERT(!is_lazy_sweeping(heap_eden)); + GC_ASSERT(!is_lazy_sweeping(objspace)); GC_ASSERT(!is_incremental_marking(objspace)); + + unsigned int lock_lev; + gc_enter(objspace, gc_enter_event_start, &lock_lev); + #if RGENGC_CHECK_MODE >= 2 gc_verify_internal_consistency(objspace); #endif - gc_enter(objspace, "gc_start"); - if (ruby_gc_stressful) { int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0; @@ -7266,7 +8895,6 @@ gc_start(rb_objspace_t *objspace, int reason) objspace->flags.immediate_sweep = !(flag & (1<rgengc.need_major_gc) { reason |= objspace->rgengc.need_major_gc; do_full_mark = TRUE; @@ -7277,7 +8905,6 @@ gc_start(rb_objspace_t *objspace, int reason) } objspace->rgengc.need_major_gc = GPR_FLAG_NONE; -#endif } if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) { @@ -7299,7 +8926,7 @@ gc_start(rb_objspace_t *objspace, int reason) if (objspace->flags.immediate_sweep) reason |= GPR_FLAG_IMMEDIATE_SWEEP; - gc_report(1, objspace, "gc_start(reason: %d) => %u, %d, %d\n", + gc_report(1, objspace, "gc_start(reason: %x) => %u, %d, %d\n", reason, do_full_mark, !is_incremental_marking(objspace), objspace->flags.immediate_sweep); @@ -7329,7 +8956,7 @@ gc_start(rb_objspace_t *objspace, int reason) objspace->profile.total_allocated_objects_at_gc_start = objspace->total_allocated_objects; objspace->profile.heap_used_at_gc_start = heap_allocated_pages; gc_prof_setup_new_record(objspace, reason); - gc_reset_malloc_info(objspace); + gc_reset_malloc_info(objspace, do_full_mark); rb_transient_heap_start_marking(do_full_mark); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_START, 0 /* TODO: pass minor/immediate flag? */); @@ -7341,7 +8968,7 @@ gc_start(rb_objspace_t *objspace, int reason) } gc_prof_timer_stop(objspace); - gc_exit(objspace, "gc_start"); + gc_exit(objspace, gc_enter_event_start, &lock_lev); return TRUE; } @@ -7349,28 +8976,27 @@ static void gc_rest(rb_objspace_t *objspace) { int marking = is_incremental_marking(objspace); - int sweeping = is_lazy_sweeping(heap_eden); + int sweeping = is_lazy_sweeping(objspace); if (marking || sweeping) { - gc_enter(objspace, "gc_rest"); + unsigned int lock_lev; + gc_enter(objspace, gc_enter_event_rest, &lock_lev); if (RGENGC_CHECK_MODE >= 2) gc_verify_internal_consistency(objspace); if (is_incremental_marking(objspace)) { - PUSH_MARK_FUNC_DATA(NULL); - gc_marks_rest(objspace); - POP_MARK_FUNC_DATA(); - } - if (is_lazy_sweeping(heap_eden)) { + gc_marks_rest(objspace); + } + if (is_lazy_sweeping(objspace)) { gc_sweep_rest(objspace); } - gc_exit(objspace, "gc_rest"); + gc_exit(objspace, gc_enter_event_rest, &lock_lev); } } struct objspace_and_reason { rb_objspace_t *objspace; - int reason; + unsigned int reason; }; static void @@ -7379,16 +9005,14 @@ gc_current_status_fill(rb_objspace_t *objspace, char *buff) int i = 0; if (is_marking(objspace)) { buff[i++] = 'M'; -#if USE_RGENGC if (is_full_marking(objspace)) buff[i++] = 'F'; #if GC_ENABLE_INCREMENTAL_MARK if (is_incremental_marking(objspace)) buff[i++] = 'I'; -#endif #endif } else if (is_sweeping(objspace)) { buff[i++] = 'S'; - if (is_lazy_sweeping(heap_eden)) buff[i++] = 'L'; + if (is_lazy_sweeping(objspace)) buff[i++] = 'L'; } else { buff[i++] = 'N'; @@ -7443,39 +9067,147 @@ gc_record(rb_objspace_t *objspace, int direction, const char *event) #endif } } -#else /* PRINT_ENTER_EXIT_TICK */ -static inline void -gc_record(rb_objspace_t *objspace, int direction, const char *event) +#else /* PRINT_ENTER_EXIT_TICK */ +static inline void +gc_record(rb_objspace_t *objspace, int direction, const char *event) +{ + /* null */ +} +#endif /* PRINT_ENTER_EXIT_TICK */ + +static const char * +gc_enter_event_cstr(enum gc_enter_event event) +{ + switch (event) { + case gc_enter_event_start: return "start"; + case gc_enter_event_mark_continue: return "mark_continue"; + case gc_enter_event_sweep_continue: return "sweep_continue"; + case gc_enter_event_rest: return "rest"; + case gc_enter_event_finalizer: return "finalizer"; + case gc_enter_event_rb_memerror: return "rb_memerror"; + } + return NULL; +} + +static void +gc_enter_count(enum gc_enter_event event) +{ + switch (event) { + case gc_enter_event_start: RB_DEBUG_COUNTER_INC(gc_enter_start); break; + case gc_enter_event_mark_continue: RB_DEBUG_COUNTER_INC(gc_enter_mark_continue); break; + case gc_enter_event_sweep_continue: RB_DEBUG_COUNTER_INC(gc_enter_sweep_continue); break; + case gc_enter_event_rest: RB_DEBUG_COUNTER_INC(gc_enter_rest); break; + case gc_enter_event_finalizer: RB_DEBUG_COUNTER_INC(gc_enter_finalizer); break; + case gc_enter_event_rb_memerror: /* nothing */ break; + } +} + +#ifndef MEASURE_GC +#define MEASURE_GC (objspace->flags.measure_gc) +#endif + +static bool +gc_enter_event_measure_p(rb_objspace_t *objspace, enum gc_enter_event event) +{ + if (!MEASURE_GC) return false; + + switch (event) { + case gc_enter_event_start: + case gc_enter_event_mark_continue: + case gc_enter_event_sweep_continue: + case gc_enter_event_rest: + return true; + + default: + // case gc_enter_event_finalizer: + // case gc_enter_event_rb_memerror: + return false; + } +} + +static bool current_process_time(struct timespec *ts); + +static void +gc_enter_clock(rb_objspace_t *objspace, enum gc_enter_event event) { - /* null */ + if (gc_enter_event_measure_p(objspace, event)) { + if (!current_process_time(&objspace->profile.start_time)) { + objspace->profile.start_time.tv_sec = 0; + objspace->profile.start_time.tv_nsec = 0; + } + } +} + +static void +gc_exit_clock(rb_objspace_t *objspace, enum gc_enter_event event) +{ + if (gc_enter_event_measure_p(objspace, event)) { + struct timespec end_time; + + if ((objspace->profile.start_time.tv_sec > 0 || + objspace->profile.start_time.tv_nsec > 0) && + current_process_time(&end_time)) { + + if (end_time.tv_sec < objspace->profile.start_time.tv_sec) { + return; // ignore + } + else { + uint64_t ns = + (uint64_t)(end_time.tv_sec - objspace->profile.start_time.tv_sec) * (1000 * 1000 * 1000) + + (end_time.tv_nsec - objspace->profile.start_time.tv_nsec); + objspace->profile.total_time_ns += ns; + } + } + } } -#endif /* PRINT_ENTER_EXIT_TICK */ static inline void -gc_enter(rb_objspace_t *objspace, const char *event) +gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev) { - GC_ASSERT(during_gc == 0); + RB_VM_LOCK_ENTER_LEV(lock_lev); + + gc_enter_clock(objspace, event); + + switch (event) { + case gc_enter_event_rest: + if (!is_marking(objspace)) break; + // fall through + case gc_enter_event_start: + case gc_enter_event_mark_continue: + // stop other ractors + rb_vm_barrier(); + break; + default: + break; + } + + gc_enter_count(event); + if (UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0"); if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace); mjit_gc_start_hook(); during_gc = TRUE; - gc_report(1, objspace, "gc_enter: %s [%s]\n", event, gc_current_status(objspace)); - gc_record(objspace, 0, event); + RUBY_DEBUG_LOG("%s (%s)",gc_enter_event_cstr(event), gc_current_status(objspace)); + gc_report(1, objspace, "gc_enter: %s [%s]\n", gc_enter_event_cstr(event), gc_current_status(objspace)); + gc_record(objspace, 0, gc_enter_event_cstr(event)); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_ENTER, 0); /* TODO: which parameter should be passed? */ } static inline void -gc_exit(rb_objspace_t *objspace, const char *event) +gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev) { GC_ASSERT(during_gc != 0); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_EXIT, 0); /* TODO: which parameter should be passsed? */ - gc_record(objspace, 1, event); - gc_report(1, objspace, "gc_exit: %s [%s]\n", event, gc_current_status(objspace)); + gc_record(objspace, 1, gc_enter_event_cstr(event)); + RUBY_DEBUG_LOG("%s (%s)", gc_enter_event_cstr(event), gc_current_status(objspace)); + gc_report(1, objspace, "gc_exit: %s [%s]\n", gc_enter_event_cstr(event), gc_current_status(objspace)); during_gc = FALSE; mjit_gc_exit_hook(); + gc_exit_clock(objspace, event); + RB_VM_LOCK_LEAVE_LEV(lock_lev); } static void * @@ -7486,9 +9218,9 @@ gc_with_gvl(void *ptr) } static int -garbage_collect_with_gvl(rb_objspace_t *objspace, int reason) +garbage_collect_with_gvl(rb_objspace_t *objspace, unsigned int reason) { - if (dont_gc) return TRUE; + if (dont_gc_val()) return TRUE; if (ruby_thread_has_gvl_p()) { return garbage_collect(objspace, reason); } @@ -7508,17 +9240,31 @@ garbage_collect_with_gvl(rb_objspace_t *objspace, int reason) } static VALUE -gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep) +gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep, VALUE compact) { rb_objspace_t *objspace = &rb_objspace; - int reason = GPR_FLAG_FULL_MARK | - GPR_FLAG_IMMEDIATE_MARK | - GPR_FLAG_IMMEDIATE_SWEEP | - GPR_FLAG_METHOD; + unsigned int reason = (GPR_FLAG_FULL_MARK | + GPR_FLAG_IMMEDIATE_MARK | + GPR_FLAG_IMMEDIATE_SWEEP | + GPR_FLAG_METHOD); + + /* For now, compact implies full mark / sweep, so ignore other flags */ + if (RTEST(compact)) { + /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for + * the read barrier, so we must disable compaction. */ +#if !defined(__MINGW32__) && !defined(_WIN32) + if (!USE_MMAP_ALIGNED_ALLOC) { + rb_raise(rb_eNotImpError, "Compaction isn't available on this platform"); + } +#endif - if (!RTEST(full_mark)) reason &= ~GPR_FLAG_FULL_MARK; - if (!RTEST(immediate_mark)) reason &= ~GPR_FLAG_IMMEDIATE_MARK; - if (!RTEST(immediate_sweep)) reason &= ~GPR_FLAG_IMMEDIATE_SWEEP; + reason |= GPR_FLAG_COMPACT; + } + else { + if (!RTEST(full_mark)) reason &= ~GPR_FLAG_FULL_MARK; + if (!RTEST(immediate_mark)) reason &= ~GPR_FLAG_IMMEDIATE_MARK; + if (!RTEST(immediate_sweep)) reason &= ~GPR_FLAG_IMMEDIATE_SWEEP; + } garbage_collect(objspace, reason); gc_finalize_deferred(objspace); @@ -7529,9 +9275,7 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE static int gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) { - if (SPECIAL_CONST_P(obj)) { - return FALSE; - } + GC_ASSERT(!SPECIAL_CONST_P(obj)); switch (BUILTIN_TYPE(obj)) { case T_NONE: @@ -7539,7 +9283,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) case T_MOVED: case T_ZOMBIE: return FALSE; - break; case T_SYMBOL: if (DYNAMIC_SYM_P(obj) && (RSYMBOL(obj)->id & ~ID_SCOPE_MASK)) { return FALSE; @@ -7564,12 +9307,19 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) case T_NODE: case T_CLASS: if (FL_TEST(obj, FL_FINALIZE)) { + /* The finalizer table is a numtable. It looks up objects by address. + * We can't mark the keys in the finalizer table because that would + * prevent the objects from being collected. This check prevents + * objects that are keys in the finalizer table from being moved + * without directly pinning them. */ if (st_is_member(finalizer_table, obj)) { return FALSE; } } - return !RVALUE_PINNED(obj); - break; + GC_ASSERT(RVALUE_MARKED(obj)); + GC_ASSERT(!RVALUE_PINNED(obj)); + + return TRUE; default: rb_bug("gc_is_moveable_obj: unreachable (%d)", (int)BUILTIN_TYPE(obj)); @@ -7580,7 +9330,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) } static VALUE -gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list) +gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t slot_size) { int marked; int wb_unprotected; @@ -7592,7 +9342,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list) gc_report(4, objspace, "Moving object: %p -> %p\n", (void*)scan, (void *)free); GC_ASSERT(BUILTIN_TYPE(scan) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(free) == T_NONE); + GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(free), free)); /* Save off bits for current object. */ marked = rb_objspace_marked_object_p((VALUE)src); @@ -7600,31 +9350,38 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list) uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src); marking = RVALUE_MARKING((VALUE)src); - objspace->total_allocated_objects++; - /* Clear bits for eventual T_MOVED */ CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)src), (VALUE)src); CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)src), (VALUE)src); CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)src), (VALUE)src); CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)src), (VALUE)src); - if (FL_TEST(src, FL_EXIVAR)) { + if (FL_TEST((VALUE)src, FL_EXIVAR)) { + /* Same deal as below. Generic ivars are held in st tables. + * Resizing the table could cause a GC to happen and we can't allow it */ + VALUE already_disabled = rb_gc_disable_no_rest(); rb_mv_generic_ivar((VALUE)src, (VALUE)dest); + if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace); } - VALUE id; + st_data_t srcid = (st_data_t)src, id; /* If the source object's object_id has been seen, we need to update * the object to object id mapping. */ - if (st_lookup(objspace->obj_to_id_tbl, (VALUE)src, &id)) { + if (st_lookup(objspace->obj_to_id_tbl, srcid, &id)) { gc_report(4, objspace, "Moving object with seen id: %p -> %p\n", (void *)src, (void *)dest); - st_delete(objspace->obj_to_id_tbl, (st_data_t *)&src, 0); - st_insert(objspace->obj_to_id_tbl, (VALUE)dest, id); + /* inserting in the st table can cause the GC to run. We need to + * prevent re-entry in to the GC since `gc_move` is running in the GC, + * so temporarily disable the GC around the st table mutation */ + VALUE already_disabled = rb_gc_disable_no_rest(); + st_delete(objspace->obj_to_id_tbl, &srcid, 0); + st_insert(objspace->obj_to_id_tbl, (st_data_t)dest, id); + if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace); } /* Move the object */ - memcpy(dest, src, sizeof(RVALUE)); - memset(src, 0, sizeof(RVALUE)); + memcpy(dest, src, slot_size); + memset(src, 0, slot_size); /* Set bits for object in new location */ if (marking) { @@ -7657,102 +9414,13 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list) /* Assign forwarding address */ src->as.moved.flags = T_MOVED; + src->as.moved.dummy = Qundef; src->as.moved.destination = (VALUE)dest; - src->as.moved.next = moved_list; GC_ASSERT(BUILTIN_TYPE((VALUE)dest) != T_NONE); return (VALUE)src; } -struct heap_cursor { - RVALUE *slot; - size_t index; - struct heap_page *page; - rb_objspace_t * objspace; -}; - -static void -advance_cursor(struct heap_cursor *free, struct heap_page **page_list) -{ - if (free->slot == free->page->start + free->page->total_slots - 1) { - free->index++; - free->page = page_list[free->index]; - free->slot = free->page->start; - } - else { - free->slot++; - } -} - -static void -retreat_cursor(struct heap_cursor *scan, struct heap_page **page_list) -{ - if (scan->slot == scan->page->start) { - scan->index--; - scan->page = page_list[scan->index]; - scan->slot = scan->page->start + scan->page->total_slots - 1; - } - else { - scan->slot--; - } -} - -static int -not_met(struct heap_cursor *free, struct heap_cursor *scan) -{ - if (free->index < scan->index) - return 1; - - if (free->index > scan->index) - return 0; - - return free->slot < scan->slot; -} - -static void -init_cursors(rb_objspace_t *objspace, struct heap_cursor *free, struct heap_cursor *scan, struct heap_page **page_list) -{ - struct heap_page *page; - size_t total_pages = heap_eden->total_pages; - page = page_list[0]; - - free->index = 0; - free->page = page; - free->slot = page->start; - free->objspace = objspace; - - page = page_list[total_pages - 1]; - scan->index = total_pages - 1; - scan->page = page; - scan->slot = page->start + page->total_slots - 1; - scan->objspace = objspace; -} - -static int -count_pinned(struct heap_page *page) -{ - int pinned = 0; - int i; - - for (i = 0; i < HEAP_PAGE_BITMAP_LIMIT; i++) { - pinned += popcount_bits(page->pinned_bits[i]); - } - - return pinned; -} - -static int -compare_pinned(const void *left, const void *right, void *dummy) -{ - struct heap_page *left_page; - struct heap_page *right_page; - - left_page = *(struct heap_page * const *)left; - right_page = *(struct heap_page * const *)right; - - return right_page->pinned_slots - left_page->pinned_slots; -} - static int compare_free_slots(const void *left, const void *right, void *dummy) { @@ -7762,114 +9430,43 @@ compare_free_slots(const void *left, const void *right, void *dummy) left_page = *(struct heap_page * const *)left; right_page = *(struct heap_page * const *)right; - return right_page->free_slots - left_page->free_slots; -} - -typedef int page_compare_func_t(const void *, const void *, void *); - -static struct heap_page ** -allocate_page_list(rb_objspace_t *objspace, page_compare_func_t *comparator) -{ - size_t total_pages = heap_eden->total_pages; - size_t size = size_mul_or_raise(total_pages, sizeof(struct heap_page *), rb_eRuntimeError); - struct heap_page *page = 0, **page_list = malloc(size); - int i = 0; - - list_for_each(&heap_eden->pages, page, page_node) { - page_list[i++] = page; - page->pinned_slots = count_pinned(page); - GC_ASSERT(page != NULL); - } - GC_ASSERT(total_pages > 0); - GC_ASSERT((size_t)i == total_pages); - - ruby_qsort(page_list, total_pages, sizeof(struct heap_page *), comparator, NULL); - - return page_list; + return left_page->free_slots - right_page->free_slots; } -static VALUE -gc_compact_heap(rb_objspace_t *objspace, page_compare_func_t *comparator) +static void +gc_sort_heap_by_empty_slots(rb_objspace_t *objspace) { - struct heap_cursor free_cursor; - struct heap_cursor scan_cursor; - struct heap_page **page_list; - VALUE moved_list; + for (int j = 0; j < SIZE_POOL_COUNT; j++) { + rb_size_pool_t *size_pool = &size_pools[j]; - moved_list = Qfalse; - memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t)); - memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t)); - - page_list = allocate_page_list(objspace, comparator); - - init_cursors(objspace, &free_cursor, &scan_cursor, page_list); - - /* Two finger algorithm */ - while (not_met(&free_cursor, &scan_cursor)) { - /* Free cursor movement */ - - /* Unpoison free_cursor slot */ - void *free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot); - asan_unpoison_object((VALUE)free_cursor.slot, false); - - while (BUILTIN_TYPE(free_cursor.slot) != T_NONE && not_met(&free_cursor, &scan_cursor)) { - /* Re-poison slot if it's not the one we want */ - if (free_slot_poison) { - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE); - asan_poison_object((VALUE)free_cursor.slot); - } + size_t total_pages = SIZE_POOL_EDEN_HEAP(size_pool)->total_pages; + size_t size = size_mul_or_raise(total_pages, sizeof(struct heap_page *), rb_eRuntimeError); + struct heap_page *page = 0, **page_list = malloc(size); + size_t i = 0; - advance_cursor(&free_cursor, page_list); - - /* Unpoison free_cursor slot */ - free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot); - asan_unpoison_object((VALUE)free_cursor.slot, false); + list_for_each(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node) { + page_list[i++] = page; + GC_ASSERT(page); } - /* Unpoison scan_cursor slot */ - void *scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot); - asan_unpoison_object((VALUE)scan_cursor.slot, false); + GC_ASSERT((size_t)i == total_pages); - /* Scan cursor movement */ - objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; + /* Sort the heap so "filled pages" are first. `heap_add_page` adds to the + * head of the list, so empty pages will end up at the start of the heap */ + ruby_qsort(page_list, total_pages, sizeof(struct heap_page *), compare_free_slots, NULL); - while (!gc_is_moveable_obj(objspace, (VALUE)scan_cursor.slot) && not_met(&free_cursor, &scan_cursor)) { + /* Reset the eden heap */ + list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages); - /* Re-poison slot if it's not the one we want */ - if (scan_slot_poison) { - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_NONE); - asan_poison_object((VALUE)scan_cursor.slot); + for (i = 0; i < total_pages; i++) { + list_add(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, &page_list[i]->page_node); + if (page_list[i]->free_slots != 0) { + heap_add_freepage(SIZE_POOL_EDEN_HEAP(size_pool), page_list[i]); } - - retreat_cursor(&scan_cursor, page_list); - - /* Unpoison scan_cursor slot */ - scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot); - asan_unpoison_object((VALUE)scan_cursor.slot, false); - - objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; } - if (not_met(&free_cursor, &scan_cursor)) { - objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; - - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_MOVED); - - moved_list = gc_move(objspace, (VALUE)scan_cursor.slot, (VALUE)free_cursor.slot, moved_list); - - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_MOVED); - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_MOVED); - - advance_cursor(&free_cursor, page_list); - retreat_cursor(&scan_cursor, page_list); - } + free(page_list); } - free(page_list); - - return moved_list; } static void @@ -7894,11 +9491,9 @@ gc_ref_update_object(rb_objspace_t * objspace, VALUE v) { VALUE *ptr = ROBJECT_IVPTR(v); - if (ptr) { - uint32_t i, len = ROBJECT_NUMIV(v); - for (i = 0; i < len; i++) { - UPDATE_IF_MOVED(objspace, ptr[i]); - } + uint32_t i, len = ROBJECT_NUMIV(v); + for (i = 0; i < len; i++) { + UPDATE_IF_MOVED(objspace, ptr[i]); } } @@ -8052,13 +9647,16 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_env: { rb_env_t *env = (rb_env_t *)obj; - TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, env->iseq); - UPDATE_IF_MOVED(objspace, env->ep[VM_ENV_DATA_INDEX_ENV]); - gc_update_values(objspace, (long)env->env_size, (VALUE *)env->env); + if (LIKELY(env->ep)) { + // just after newobj() can be NULL here. + TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, env->iseq); + UPDATE_IF_MOVED(objspace, env->ep[VM_ENV_DATA_INDEX_ENV]); + gc_update_values(objspace, (long)env->env_size, (VALUE *)env->env); + } } break; case imemo_cref: - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass); + UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass_or_self); TYPED_UPDATE_IF_MOVED(objspace, struct rb_cref_struct *, RANY(obj)->as.imemo.cref.next); UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.refinements); break; @@ -8086,8 +9684,33 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_ast: rb_ast_update_references((rb_ast_t *)obj); break; + case imemo_callcache: + { + const struct rb_callcache *cc = (const struct rb_callcache *)obj; + if (cc->klass) { + UPDATE_IF_MOVED(objspace, cc->klass); + if (!is_live_object(objspace, cc->klass)) { + *((VALUE *)(&cc->klass)) = (VALUE)0; + } + } + + if (cc->cme_) { + TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_); + if (!is_live_object(objspace, (VALUE)cc->cme_)) { + *((struct rb_callable_method_entry_struct **)(&cc->cme_)) = (struct rb_callable_method_entry_struct *)0; + } + } + } + break; + case imemo_constcache: + { + const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj; + UPDATE_IF_MOVED(objspace, ice->value); + } + break; case imemo_parser_strterm: case imemo_tmpbuf: + case imemo_callinfo: break; default: rb_bug("not reachable %d", imemo_type(obj)); @@ -8115,7 +9738,7 @@ rb_gc_location(VALUE value) VALUE destination; - if (!SPECIAL_CONST_P((void *)value)) { + if (!SPECIAL_CONST_P(value)) { void *poisoned = asan_poisoned_object_p(value); asan_unpoison_object(value, false); @@ -8160,6 +9783,60 @@ update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) } } +static enum rb_id_table_iterator_result +update_cc_tbl_i(ID id, VALUE ccs_ptr, void *data) +{ + rb_objspace_t *objspace = (rb_objspace_t *)data; + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr; + VM_ASSERT(vm_ccs_p(ccs)); + + if (gc_object_moved_p(objspace, (VALUE)ccs->cme)) { + ccs->cme = (const rb_callable_method_entry_t *)rb_gc_location((VALUE)ccs->cme); + } + + for (int i=0; ilen; i++) { + if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].ci)) { + ccs->entries[i].ci = (struct rb_callinfo *)rb_gc_location((VALUE)ccs->entries[i].ci); + } + if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].cc)) { + ccs->entries[i].cc = (struct rb_callcache *)rb_gc_location((VALUE)ccs->entries[i].cc); + } + } + + // do not replace + return ID_TABLE_CONTINUE; +} + +static void +update_cc_tbl(rb_objspace_t *objspace, VALUE klass) +{ + struct rb_id_table *tbl = RCLASS_CC_TBL(klass); + if (tbl) { + rb_id_table_foreach_with_replace(tbl, update_cc_tbl_i, 0, objspace); + } +} + +static enum rb_id_table_iterator_result +update_cvc_tbl_i(ID id, VALUE cvc_entry, void *data) +{ + struct rb_cvar_class_tbl_entry *entry; + + entry = (struct rb_cvar_class_tbl_entry *)cvc_entry; + + entry->class_value = rb_gc_location(entry->class_value); + + return ID_TABLE_CONTINUE; +} + +static void +update_cvc_tbl(rb_objspace_t *objspace, VALUE klass) +{ + struct rb_id_table *tbl = RCLASS_CVC_TBL(klass); + if (tbl) { + rb_id_table_foreach_with_replace(tbl, update_cvc_tbl_i, 0, objspace); + } +} + static enum rb_id_table_iterator_result update_const_table(VALUE value, void *data) { @@ -8193,12 +9870,26 @@ update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry) } } +static int +update_iv_index_tbl_i(st_data_t key, st_data_t value, st_data_t arg) +{ + rb_objspace_t *objspace = (rb_objspace_t *)arg; + struct rb_iv_index_tbl_entry *ent = (struct rb_iv_index_tbl_entry *)value; + UPDATE_IF_MOVED(objspace, ent->class_value); + return ST_CONTINUE; +} + static void update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext) { UPDATE_IF_MOVED(objspace, ext->origin_); UPDATE_IF_MOVED(objspace, ext->refined_class); update_subclass_entries(objspace, ext->subclasses); + + // ext->iv_index_tbl + if (ext->iv_index_tbl) { + st_foreach(ext->iv_index_tbl, update_iv_index_tbl_i, (st_data_t)objspace); + } } static void @@ -8206,7 +9897,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) { RVALUE *any = RANY(obj); - gc_report(4, objspace, "update-refs: %p ->", (void *)obj); + gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj); switch (BUILTIN_TYPE(obj)) { case T_CLASS: @@ -8216,13 +9907,18 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) } if (!RCLASS_EXT(obj)) break; update_m_tbl(objspace, RCLASS_M_TBL(obj)); + update_cc_tbl(objspace, obj); + update_cvc_tbl(objspace, obj); + gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj)); + update_class_ext(objspace, RCLASS_EXT(obj)); update_const_tbl(objspace, RCLASS_CONST_TBL(obj)); break; case T_ICLASS: - if (FL_TEST(obj, RICLASS_IS_ORIGIN)) { + if (FL_TEST(obj, RICLASS_IS_ORIGIN) && + !FL_TEST(obj, RICLASS_ORIGIN_SHARED_MTBL)) { update_m_tbl(objspace, RCLASS_M_TBL(obj)); } if (RCLASS_SUPER((VALUE)obj)) { @@ -8234,6 +9930,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) } update_class_ext(objspace, RCLASS_EXT(obj)); update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj)); + update_cc_tbl(objspace, obj); break; case T_IMEMO: @@ -8264,7 +9961,19 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) case T_STRING: if (STR_SHARED_P(obj)) { +#if USE_RVARGC + VALUE orig_shared = any->as.string.as.heap.aux.shared; +#endif UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared); +#if USE_RVARGC + VALUE shared = any->as.string.as.heap.aux.shared; + if (STR_EMBED_P(shared)) { + size_t offset = (size_t)any->as.string.as.heap.ptr - (size_t)RSTRING(orig_shared)->as.embed.ary; + GC_ASSERT(any->as.string.as.heap.ptr >= RSTRING(orig_shared)->as.embed.ary); + GC_ASSERT(offset <= (size_t)RSTRING(shared)->as.embed.len); + any->as.string.as.heap.ptr = RSTRING(shared)->as.embed.ary + offset; + } +#endif } break; @@ -8287,6 +9996,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) case T_FILE: if (any->as.file.fptr) { + UPDATE_IF_MOVED(objspace, any->as.file.fptr->self); UPDATE_IF_MOVED(objspace, any->as.file.fptr->pathv); UPDATE_IF_MOVED(objspace, any->as.file.fptr->tied_io_for_writing); UPDATE_IF_MOVED(objspace, any->as.file.fptr->writeconv_asciicompat); @@ -8350,58 +10060,50 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) UPDATE_IF_MOVED(objspace, RBASIC(obj)->klass); - gc_report(4, objspace, "update-refs: %p <-", (void *)obj); + gc_report(4, objspace, "update-refs: %p <-\n", (void *)obj); } static int -gc_ref_update(void *vstart, void *vend, size_t stride, void * data) +gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace, struct heap_page *page) { - rb_objspace_t * objspace; - struct heap_page *page; - short free_slots = 0; - VALUE v = (VALUE)vstart; - objspace = (rb_objspace_t *)data; - page = GET_HEAP_PAGE(v); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - page->freelist = NULL; asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); page->flags.has_uncollectible_shady_objects = FALSE; page->flags.has_remembered_objects = FALSE; /* For each object on the page */ for (; v != (VALUE)vend; v += stride) { - if (!SPECIAL_CONST_P(v)) { - void *poisoned = asan_poisoned_object_p(v); - asan_unpoison_object(v, false); + void *poisoned = asan_poisoned_object_p(v); + asan_unpoison_object(v, false); - switch (BUILTIN_TYPE(v)) { - case T_NONE: - heap_page_add_freeobj(objspace, page, v); - free_slots++; - break; - case T_MOVED: - break; - case T_ZOMBIE: - break; - default: - if (RVALUE_WB_UNPROTECTED(v)) { - page->flags.has_uncollectible_shady_objects = TRUE; - } - if (RVALUE_PAGE_MARKING(page, v)) { - page->flags.has_remembered_objects = TRUE; + switch (BUILTIN_TYPE(v)) { + case T_NONE: + case T_MOVED: + case T_ZOMBIE: + break; + default: + if (RVALUE_WB_UNPROTECTED(v)) { + page->flags.has_uncollectible_shady_objects = TRUE; + } + if (RVALUE_PAGE_MARKING(page, v)) { + page->flags.has_remembered_objects = TRUE; + } + if (page->flags.before_sweep) { + if (RVALUE_MARKED(v)) { + gc_update_object_references(objspace, v); } + } + else { gc_update_object_references(objspace, v); } + } - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); - asan_poison_object(v); - } + if (poisoned) { + asan_poison_object(v); } } - page->free_slots = free_slots; return 0; } @@ -8409,14 +10111,34 @@ extern rb_symbols_t ruby_global_symbols; #define global_symbols ruby_global_symbols static void -gc_update_references(rb_objspace_t * objspace) +gc_update_references(rb_objspace_t *objspace) { rb_execution_context_t *ec = GET_EC(); rb_vm_t *vm = rb_ec_vm_ptr(ec); - objspace_each_objects_without_setup(objspace, gc_ref_update, objspace); + struct heap_page *page = NULL; + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + bool should_set_mark_bits = TRUE; + rb_size_pool_t *size_pool = &size_pools[i]; + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + + list_for_each(&heap->pages, page, page_node) { + uintptr_t start = (uintptr_t)page->start; + uintptr_t end = start + (page->total_slots * size_pool->slot_size); + + gc_ref_update((void *)start, (void *)end, size_pool->slot_size, objspace, page); + if (page == heap->sweeping_page) { + should_set_mark_bits = FALSE; + } + if (should_set_mark_bits) { + gc_setup_mark_bits(page); + } + } + } rb_vm_update_references(vm); rb_transient_heap_update_references(); + rb_gc_update_global_tbl(); global_symbols.ids = rb_gc_location(global_symbols.ids); global_symbols.dsymbol_fstr_hash = rb_gc_location(global_symbols.dsymbol_fstr_hash); gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl); @@ -8425,54 +10147,29 @@ gc_update_references(rb_objspace_t * objspace) gc_update_table_refs(objspace, finalizer_table); } -static VALUE type_sym(size_t type); - -static VALUE -gc_compact_stats(rb_objspace_t *objspace) -{ - size_t i; - VALUE h = rb_hash_new(); - VALUE considered = rb_hash_new(); - VALUE moved = rb_hash_new(); - - for (i=0; ircompactor.considered_count_table[i])); - } - - for (i=0; ircompactor.moved_count_table[i])); - } - - rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered); - rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved); - - return h; -} - -static void gc_compact_after_gc(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier); - -static void -gc_compact(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier) -{ - - objspace->flags.during_compacting = TRUE; - { - /* pin objects referenced by maybe pointers */ - garbage_collect(objspace, GPR_DEFAULT_REASON); - /* compact */ - gc_compact_after_gc(objspace, use_toward_empty, use_double_pages, use_verifier); - } - objspace->flags.during_compacting = FALSE; -} - static VALUE -rb_gc_compact(rb_execution_context_t *ec, VALUE self) +gc_compact_stats(rb_execution_context_t *ec, VALUE self) { + size_t i; rb_objspace_t *objspace = &rb_objspace; - if (dont_gc) return Qnil; + VALUE h = rb_hash_new(); + VALUE considered = rb_hash_new(); + VALUE moved = rb_hash_new(); + + for (i=0; ircompactor.considered_count_table[i]) { + rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i])); + } + + if (objspace->rcompactor.moved_count_table[i]) { + rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i])); + } + } + + rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered); + rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved); - gc_compact(objspace, FALSE, FALSE, FALSE); - return gc_compact_stats(objspace); + return h; } static void @@ -8509,7 +10206,9 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data) case T_ZOMBIE: break; default: - rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v); + if (!rb_objspace_garbage_object_p(v)) { + rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v); + } } if (poisoned) { @@ -8523,151 +10222,46 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data) } static VALUE -gc_check_references_for_moved(rb_objspace_t *objspace) -{ - objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL); - objspace_each_objects(objspace, heap_check_moved_i, NULL); - return Qnil; -} - -static void -gc_compact_after_gc(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier) +gc_compact(rb_execution_context_t *ec, VALUE self) { - if (0) fprintf(stderr, "gc_compact_after_gc: %d,%d,%d\n", use_toward_empty, use_double_pages, use_verifier); - - mjit_gc_start_hook(); // prevent MJIT from running while moving pointers related to ISeq - - objspace->profile.compact_count++; - - if (use_verifier) { - gc_verify_internal_consistency(objspace); - } - - if (use_double_pages) { - /* Double heap size */ - heap_add_pages(objspace, heap_eden, heap_allocated_pages); - } - - VALUE moved_list_head; - VALUE disabled = rb_objspace_gc_disable(objspace); - - if (use_toward_empty) { - moved_list_head = gc_compact_heap(objspace, compare_free_slots); - } - else { - moved_list_head = gc_compact_heap(objspace, compare_pinned); - } - heap_eden->freelist = NULL; - - gc_update_references(objspace); - if (!RTEST(disabled)) rb_objspace_gc_enable(objspace); - - if (use_verifier) { - gc_check_references_for_moved(objspace); - } - - rb_clear_method_cache_by_class(rb_cObject); - rb_clear_constant_cache(); - heap_eden->free_pages = NULL; - heap_eden->using_page = NULL; - - /* For each moved slot */ - while (moved_list_head) { - VALUE next_moved; - struct heap_page *page; - - page = GET_HEAP_PAGE(moved_list_head); - next_moved = RMOVED(moved_list_head)->next; - - /* clear the memory for that moved slot */ - RMOVED(moved_list_head)->flags = 0; - RMOVED(moved_list_head)->destination = 0; - RMOVED(moved_list_head)->next = 0; - page->free_slots++; - heap_page_add_freeobj(objspace, page, moved_list_head); - - if (page->free_slots == page->total_slots && heap_pages_freeable_pages > 0) { - heap_pages_freeable_pages--; - heap_unlink_page(objspace, heap_eden, page); - heap_add_page(objspace, heap_tomb, page); - } - objspace->profile.total_freed_objects++; - moved_list_head = next_moved; - } - - /* Add any eden pages with free slots back to the free pages list */ - struct heap_page *page = NULL; - list_for_each(&heap_eden->pages, page, page_node) { - if (page->free_slots > 0) { - heap_add_freepage(heap_eden, page); - } else { - page->free_next = NULL; - } - } - - /* Set up "using_page" if we have any pages with free slots */ - if (heap_eden->free_pages) { - heap_eden->using_page = heap_eden->free_pages; - heap_eden->free_pages = heap_eden->free_pages->free_next; - } - - if (use_verifier) { - gc_verify_internal_consistency(objspace); - } + /* Run GC with compaction enabled */ + gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue); - mjit_gc_exit_hook(); // unlock MJIT here, because `rb_gc()` calls `mjit_gc_start_hook()` again. + return gc_compact_stats(ec, self); } -/* - * call-seq: - * GC.verify_compaction_references(toward: nil, double_heap: nil) -> nil - * - * Verify compaction reference consistency. - * - * This method is implementation specific. During compaction, objects that - * were moved are replaced with T_MOVED objects. No object should have a - * reference to a T_MOVED object after compaction. - * - * This function doubles the heap to ensure room to move all objects, - * compacts the heap to make sure everything moves, updates all references, - * then performs a full GC. If any object contains a reference to a T_MOVED - * object, that object should be pushed on the mark stack, and will - * make a SEGV. - */ static VALUE -gc_verify_compaction_references(int argc, VALUE *argv, VALUE mod) +gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE toward_empty) { rb_objspace_t *objspace = &rb_objspace; - int use_toward_empty = FALSE; - int use_double_pages = FALSE; - - if (dont_gc) return Qnil; - VALUE opt = Qnil; - static ID keyword_ids[2]; - VALUE kwvals[2]; + /* Clear the heap. */ + gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qfalse); - kwvals[1] = Qtrue; - - rb_scan_args(argc, argv, "0:", &opt); + RB_VM_LOCK_ENTER(); + { + gc_rest(objspace); - if (!NIL_P(opt)) { - if (!keyword_ids[0]) { - keyword_ids[0] = rb_intern("toward"); - keyword_ids[1] = rb_intern("double_heap"); + if (RTEST(double_heap)) { + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + heap_add_pages(objspace, size_pool, heap, heap->total_pages); + } } - rb_get_kwargs(opt, keyword_ids, 0, 2, kwvals); - if (kwvals[0] != Qundef && rb_intern("empty") == rb_sym2id(kwvals[0])) { - use_toward_empty = TRUE; - } - if (kwvals[1] != Qundef && RTEST(kwvals[1])) { - use_double_pages = TRUE; + if (RTEST(toward_empty)) { + gc_sort_heap_by_empty_slots(objspace); } } + RB_VM_LOCK_LEAVE(); - gc_compact(objspace, use_toward_empty, use_double_pages, TRUE); - return gc_compact_stats(objspace); + gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue); + + objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL); + objspace_each_objects(objspace, heap_check_moved_i, NULL, TRUE); + + return gc_compact_stats(ec, self); } VALUE @@ -8681,7 +10275,7 @@ void rb_gc(void) { rb_objspace_t *objspace = &rb_objspace; - int reason = GPR_DEFAULT_REASON; + unsigned int reason = GPR_DEFAULT_REASON; garbage_collect(objspace, reason); } @@ -8722,7 +10316,7 @@ gc_count(rb_execution_context_t *ec, VALUE self) } static VALUE -gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_flags) +gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned int orig_flags) { static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state; static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress; @@ -8733,7 +10327,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ static VALUE sym_none, sym_marking, sym_sweeping; VALUE hash = Qnil, key = Qnil; VALUE major_by; - VALUE flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info; + unsigned int flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info; if (SYMBOL_P(hash_or_key)) { key = hash_or_key; @@ -8745,7 +10339,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ rb_raise(rb_eTypeError, "non-hash or symbol given"); } - if (sym_major_by == Qnil) { + if (NIL_P(sym_major_by)) { #define S(s) sym_##s = ID2SYM(rb_intern_const(#s)) S(major_by); S(gc_by); @@ -8798,8 +10392,8 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ Qnil ); - SET(have_finalizer, (flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse); - SET(immediate_sweep, (flags & GPR_FLAG_IMMEDIATE_SWEEP) ? Qtrue : Qfalse); + SET(have_finalizer, RBOOL(flags & GPR_FLAG_HAVE_FINALIZE)); + SET(immediate_sweep, RBOOL(flags & GPR_FLAG_IMMEDIATE_SWEEP)); if (orig_flags == 0) { SET(state, gc_mode(objspace) == gc_mode_none ? sym_none : @@ -8838,6 +10432,7 @@ gc_latest_gc_info(rb_execution_context_t *ec, VALUE self, VALUE arg) enum gc_stat_sym { gc_stat_sym_count, + gc_stat_sym_time, gc_stat_sym_heap_allocated_pages, gc_stat_sym_heap_sorted_length, gc_stat_sym_heap_allocatable_pages, @@ -8854,10 +10449,11 @@ enum gc_stat_sym { gc_stat_sym_total_freed_objects, gc_stat_sym_malloc_increase_bytes, gc_stat_sym_malloc_increase_bytes_limit, -#if USE_RGENGC gc_stat_sym_minor_gc_count, gc_stat_sym_major_gc_count, gc_stat_sym_compact_count, + gc_stat_sym_read_barrier_faults, + gc_stat_sym_total_moved_objects, gc_stat_sym_remembered_wb_unprotected_objects, gc_stat_sym_remembered_wb_unprotected_objects_limit, gc_stat_sym_old_objects, @@ -8873,41 +10469,11 @@ enum gc_stat_sym { gc_stat_sym_total_promoted_count, gc_stat_sym_total_remembered_normal_object_count, gc_stat_sym_total_remembered_shady_object_count, -#endif #endif gc_stat_sym_last }; -enum gc_stat_compat_sym { - gc_stat_compat_sym_gc_stat_heap_used, - gc_stat_compat_sym_heap_eden_page_length, - gc_stat_compat_sym_heap_tomb_page_length, - gc_stat_compat_sym_heap_increment, - gc_stat_compat_sym_heap_length, - gc_stat_compat_sym_heap_live_slot, - gc_stat_compat_sym_heap_free_slot, - gc_stat_compat_sym_heap_final_slot, - gc_stat_compat_sym_heap_swept_slot, -#if USE_RGENGC - gc_stat_compat_sym_remembered_shady_object, - gc_stat_compat_sym_remembered_shady_object_limit, - gc_stat_compat_sym_old_object, - gc_stat_compat_sym_old_object_limit, -#endif - gc_stat_compat_sym_total_allocated_object, - gc_stat_compat_sym_total_freed_object, - gc_stat_compat_sym_malloc_increase, - gc_stat_compat_sym_malloc_limit, -#if RGENGC_ESTIMATE_OLDMALLOC - gc_stat_compat_sym_oldmalloc_increase, - gc_stat_compat_sym_oldmalloc_limit, -#endif - gc_stat_compat_sym_last -}; - static VALUE gc_stat_symbols[gc_stat_sym_last]; -static VALUE gc_stat_compat_symbols[gc_stat_compat_sym_last]; -static VALUE gc_stat_compat_table; static void setup_gc_stat_symbols(void) @@ -8915,6 +10481,7 @@ setup_gc_stat_symbols(void) if (gc_stat_symbols[0] == 0) { #define S(s) gc_stat_symbols[gc_stat_sym_##s] = ID2SYM(rb_intern_const(#s)) S(count); + S(time); S(heap_allocated_pages); S(heap_sorted_length); S(heap_allocatable_pages); @@ -8931,10 +10498,11 @@ setup_gc_stat_symbols(void) S(total_freed_objects); S(malloc_increase_bytes); S(malloc_increase_bytes_limit); -#if USE_RGENGC S(minor_gc_count); S(major_gc_count); S(compact_count); + S(read_barrier_faults); + S(total_moved_objects); S(remembered_wb_unprotected_objects); S(remembered_wb_unprotected_objects_limit); S(old_objects); @@ -8951,106 +10519,10 @@ setup_gc_stat_symbols(void) S(total_remembered_normal_object_count); S(total_remembered_shady_object_count); #endif /* RGENGC_PROFILE */ -#endif /* USE_RGENGC */ #undef S -#define S(s) gc_stat_compat_symbols[gc_stat_compat_sym_##s] = ID2SYM(rb_intern_const(#s)) - S(gc_stat_heap_used); - S(heap_eden_page_length); - S(heap_tomb_page_length); - S(heap_increment); - S(heap_length); - S(heap_live_slot); - S(heap_free_slot); - S(heap_final_slot); - S(heap_swept_slot); -#if USE_RGEGC - S(remembered_shady_object); - S(remembered_shady_object_limit); - S(old_object); - S(old_object_limit); -#endif - S(total_allocated_object); - S(total_freed_object); - S(malloc_increase); - S(malloc_limit); -#if RGENGC_ESTIMATE_OLDMALLOC - S(oldmalloc_increase); - S(oldmalloc_limit); -#endif -#undef S - - { - VALUE table = gc_stat_compat_table = rb_hash_new(); - rb_obj_hide(table); - rb_gc_register_mark_object(table); - - /* compatibility layer for Ruby 2.1 */ -#define OLD_SYM(s) gc_stat_compat_symbols[gc_stat_compat_sym_##s] -#define NEW_SYM(s) gc_stat_symbols[gc_stat_sym_##s] - rb_hash_aset(table, OLD_SYM(gc_stat_heap_used), NEW_SYM(heap_allocated_pages)); - rb_hash_aset(table, OLD_SYM(heap_eden_page_length), NEW_SYM(heap_eden_pages)); - rb_hash_aset(table, OLD_SYM(heap_tomb_page_length), NEW_SYM(heap_tomb_pages)); - rb_hash_aset(table, OLD_SYM(heap_increment), NEW_SYM(heap_allocatable_pages)); - rb_hash_aset(table, OLD_SYM(heap_length), NEW_SYM(heap_sorted_length)); - rb_hash_aset(table, OLD_SYM(heap_live_slot), NEW_SYM(heap_live_slots)); - rb_hash_aset(table, OLD_SYM(heap_free_slot), NEW_SYM(heap_free_slots)); - rb_hash_aset(table, OLD_SYM(heap_final_slot), NEW_SYM(heap_final_slots)); -#if USE_RGEGC - rb_hash_aset(table, OLD_SYM(remembered_shady_object), NEW_SYM(remembered_wb_unprotected_objects)); - rb_hash_aset(table, OLD_SYM(remembered_shady_object_limit), NEW_SYM(remembered_wb_unprotected_objects_limit)); - rb_hash_aset(table, OLD_SYM(old_object), NEW_SYM(old_objects)); - rb_hash_aset(table, OLD_SYM(old_object_limit), NEW_SYM(old_objects_limit)); -#endif - rb_hash_aset(table, OLD_SYM(total_allocated_object), NEW_SYM(total_allocated_objects)); - rb_hash_aset(table, OLD_SYM(total_freed_object), NEW_SYM(total_freed_objects)); - rb_hash_aset(table, OLD_SYM(malloc_increase), NEW_SYM(malloc_increase_bytes)); - rb_hash_aset(table, OLD_SYM(malloc_limit), NEW_SYM(malloc_increase_bytes_limit)); -#if RGENGC_ESTIMATE_OLDMALLOC - rb_hash_aset(table, OLD_SYM(oldmalloc_increase), NEW_SYM(oldmalloc_increase_bytes)); - rb_hash_aset(table, OLD_SYM(oldmalloc_limit), NEW_SYM(oldmalloc_increase_bytes_limit)); -#endif -#undef OLD_SYM -#undef NEW_SYM - rb_obj_freeze(table); - } } } -static VALUE -compat_key(VALUE key) -{ - VALUE new_key = rb_hash_lookup(gc_stat_compat_table, key); - - if (!NIL_P(new_key)) { - static int warned = 0; - if (warned == 0) { - rb_warn("GC.stat keys were changed from Ruby 2.1. " - "In this case, you refer to obsolete `%"PRIsVALUE"' (new key is `%"PRIsVALUE"'). " - "Please check for more information.", - key, new_key); - warned = 1; - } - } - - return new_key; -} - -static VALUE -default_proc_for_compat_func(RB_BLOCK_CALL_FUNC_ARGLIST(hash, _)) -{ - VALUE key, new_key; - - Check_Type(hash, T_HASH); - rb_check_arity(argc, 2, 2); - key = argv[1]; - - if ((new_key = compat_key(key)) != Qnil) { - return rb_hash_lookup(hash, new_key); - } - - return Qnil; -} - static size_t gc_stat_internal(VALUE hash_or_sym) { @@ -9061,15 +10533,6 @@ gc_stat_internal(VALUE hash_or_sym) if (RB_TYPE_P(hash_or_sym, T_HASH)) { hash = hash_or_sym; - - if (NIL_P(RHASH_IFNONE(hash))) { - static VALUE default_proc_for_compat = 0; - if (default_proc_for_compat == 0) { /* TODO: it should be */ - default_proc_for_compat = rb_proc_new(default_proc_for_compat_func, Qnil); - rb_gc_register_mark_object(default_proc_for_compat); - } - rb_hash_set_default_proc(hash, default_proc_for_compat); - } } else if (SYMBOL_P(hash_or_sym)) { key = hash_or_sym; @@ -9084,30 +10547,31 @@ gc_stat_internal(VALUE hash_or_sym) else if (hash != Qnil) \ rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr)); - again: SET(count, objspace->profile.count); + SET(time, (size_t) (objspace->profile.total_time_ns / (1000 * 1000) /* ns -> ms */)); // TODO: UINT64T2NUM /* implementation dependent counters */ SET(heap_allocated_pages, heap_allocated_pages); SET(heap_sorted_length, heap_pages_sorted_length); - SET(heap_allocatable_pages, heap_allocatable_pages); + SET(heap_allocatable_pages, heap_allocatable_pages(objspace)); SET(heap_available_slots, objspace_available_slots(objspace)); SET(heap_live_slots, objspace_live_slots(objspace)); SET(heap_free_slots, objspace_free_slots(objspace)); SET(heap_final_slots, heap_pages_final_slots); SET(heap_marked_slots, objspace->marked_slots); - SET(heap_eden_pages, heap_eden->total_pages); - SET(heap_tomb_pages, heap_tomb->total_pages); + SET(heap_eden_pages, heap_eden_total_pages(objspace)); + SET(heap_tomb_pages, heap_tomb_total_pages(objspace)); SET(total_allocated_pages, objspace->profile.total_allocated_pages); SET(total_freed_pages, objspace->profile.total_freed_pages); SET(total_allocated_objects, objspace->total_allocated_objects); SET(total_freed_objects, objspace->profile.total_freed_objects); SET(malloc_increase_bytes, malloc_increase); SET(malloc_increase_bytes_limit, malloc_limit); -#if USE_RGENGC SET(minor_gc_count, objspace->profile.minor_gc_count); SET(major_gc_count, objspace->profile.major_gc_count); SET(compact_count, objspace->profile.compact_count); + SET(read_barrier_faults, objspace->profile.read_barrier_faults); + SET(total_moved_objects, objspace->rcompactor.total_moved); SET(remembered_wb_unprotected_objects, objspace->rgengc.uncollectible_wb_unprotected_objects); SET(remembered_wb_unprotected_objects_limit, objspace->rgengc.uncollectible_wb_unprotected_objects_limit); SET(old_objects, objspace->rgengc.old_objects); @@ -9125,15 +10589,9 @@ gc_stat_internal(VALUE hash_or_sym) SET(total_remembered_normal_object_count, objspace->profile.total_remembered_normal_object_count); SET(total_remembered_shady_object_count, objspace->profile.total_remembered_shady_object_count); #endif /* RGENGC_PROFILE */ -#endif /* USE_RGENGC */ #undef SET if (!NIL_P(key)) { /* matched key should return above */ - VALUE new_key; - if ((new_key = compat_key(key)) != Qnil) { - key = new_key; - goto again; - } rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key)); } @@ -9217,10 +10675,10 @@ rb_gc_enable(void) VALUE rb_objspace_gc_enable(rb_objspace_t *objspace) { - int old = dont_gc; + int old = dont_gc_val(); - dont_gc = FALSE; - return old ? Qtrue : Qfalse; + dont_gc_off(); + return RBOOL(old); } static VALUE @@ -9239,9 +10697,9 @@ rb_gc_disable_no_rest(void) static VALUE gc_disable_no_rest(rb_objspace_t *objspace) { - int old = dont_gc; - dont_gc = TRUE; - return old ? Qtrue : Qfalse; + int old = dont_gc_val(); + dont_gc_on(); + return RBOOL(old); } VALUE @@ -9264,10 +10722,31 @@ gc_disable(rb_execution_context_t *ec, VALUE _) return rb_gc_disable(); } +static VALUE +gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v) +{ + /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for + * the read barrier, so we must disable automatic compaction. */ +#if !defined(__MINGW32__) && !defined(_WIN32) + if (!USE_MMAP_ALIGNED_ALLOC) { + rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform"); + } +#endif + + ruby_enable_autocompact = RTEST(v); + return v; +} + +static VALUE +gc_get_auto_compact(rb_execution_context_t *ec, VALUE _) +{ + return RBOOL(ruby_enable_autocompact); +} + static int get_envparam_size(const char *name, size_t *default_value, size_t lower_bound) { - char *ptr = getenv(name); + const char *ptr = getenv(name); ssize_t val; if (ptr != NULL && *ptr) { @@ -9325,7 +10804,7 @@ get_envparam_size(const char *name, size_t *default_value, size_t lower_bound) static int get_envparam_double(const char *name, double *default_value, double lower_bound, double upper_bound, int accept_zero) { - char *ptr = getenv(name); + const char *ptr = getenv(name); double val; if (ptr != NULL && *ptr) { @@ -9353,13 +10832,15 @@ get_envparam_double(const char *name, double *default_value, double lower_bound, } } else { - accept: - if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (default value: %f)\n", name, val, *default_value); - *default_value = val; - return 1; + goto accept; } } return 0; + + accept: + if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (default value: %f)\n", name, val, *default_value); + *default_value = val; + return 1; } static void @@ -9368,10 +10849,19 @@ gc_set_initial_pages(void) size_t min_pages; rb_objspace_t *objspace = &rb_objspace; + gc_rest(objspace); + min_pages = gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT; - if (min_pages > heap_eden->total_pages) { - heap_add_pages(objspace, heap_eden, min_pages - heap_eden->total_pages); + + size_t pages_per_class = (min_pages - heap_eden_total_pages(objspace)) / SIZE_POOL_COUNT; + + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + + heap_add_pages(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool), pages_per_class); } + + heap_add_pages(objspace, &size_pools[0], SIZE_POOL_EDEN_HEAP(&size_pools[0]), min_pages - heap_eden_total_pages(objspace)); } /* @@ -9423,18 +10913,11 @@ ruby_gc_set_params(void) if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) { /* ok */ } - else if (get_envparam_size("RUBY_FREE_MIN", &gc_params.heap_free_slots, 0)) { - rb_warn("RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead."); - } /* RUBY_GC_HEAP_INIT_SLOTS */ if (get_envparam_size("RUBY_GC_HEAP_INIT_SLOTS", &gc_params.heap_init_slots, 0)) { gc_set_initial_pages(); } - else if (get_envparam_size("RUBY_HEAP_MIN_SLOTS", &gc_params.heap_init_slots, 0)) { - rb_warn("RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead."); - gc_set_initial_pages(); - } get_envparam_double("RUBY_GC_HEAP_GROWTH_FACTOR", &gc_params.growth_factor, 1.0, 0.0, FALSE); get_envparam_size ("RUBY_GC_HEAP_GROWTH_MAX_SLOTS", &gc_params.growth_max_slots, 0); @@ -9463,18 +10946,30 @@ ruby_gc_set_params(void) #endif } +static void +reachable_objects_from_callback(VALUE obj) +{ + rb_ractor_t *cr = GET_RACTOR(); + cr->mfd->mark_func(obj, cr->mfd->data); +} + void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data) { rb_objspace_t *objspace = &rb_objspace; + if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true"); + if (is_markable_object(objspace, obj)) { - struct mark_func_data_struct mfd; - mfd.mark_func = func; - mfd.data = data; - PUSH_MARK_FUNC_DATA(&mfd); + rb_ractor_t *cr = GET_RACTOR(); + struct gc_mark_func_data_struct mfd = { + .mark_func = func, + .data = data, + }, *prev_mfd = cr->mfd; + + cr->mfd = &mfd; gc_mark_children(objspace, obj); - POP_MARK_FUNC_DATA(); + cr->mfd = prev_mfd; } } @@ -9501,18 +10996,21 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, static void objspace_reachable_objects_from_root(rb_objspace_t *objspace, void (func)(const char *category, VALUE, void *), void *passing_data) { - struct root_objects_data data; - struct mark_func_data_struct mfd; + if (during_gc) rb_bug("objspace_reachable_objects_from_root() is not supported while during_gc == true"); - data.func = func; - data.data = passing_data; - - mfd.mark_func = root_objects_from; - mfd.data = &data; + rb_ractor_t *cr = GET_RACTOR(); + struct root_objects_data data = { + .func = func, + .data = passing_data, + }; + struct gc_mark_func_data_struct mfd = { + .mark_func = root_objects_from, + .data = &data, + }, *prev_mfd = cr->mfd; - PUSH_MARK_FUNC_DATA(&mfd); + cr->mfd = &mfd; gc_mark_roots(objspace, &data.category); - POP_MARK_FUNC_DATA(); + cr->mfd = prev_mfd; } /* @@ -9554,10 +11052,10 @@ gc_raise(VALUE exc, const char *fmt, ...) /* Not in a ruby thread */ fprintf(stderr, "%s", "[FATAL] "); vfprintf(stderr, fmt, ap); - abort(); } va_end(ap); + abort(); } static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size); @@ -9575,6 +11073,8 @@ ruby_memerror_body(void *dummy) return 0; } +NORETURN(static void ruby_memerror(void)); +RBIMPL_ATTR_MAYBE_UNUSED() static void ruby_memerror(void) { @@ -9588,9 +11088,9 @@ ruby_memerror(void) else { /* no ruby thread */ fprintf(stderr, "[FATAL] failed to allocate memory\n"); - exit(EXIT_FAILURE); } } + exit(EXIT_FAILURE); } void @@ -9606,7 +11106,10 @@ rb_memerror(void) sleep(60); } - if (during_gc) gc_exit(objspace, "rb_memerror"); + if (during_gc) { + // TODO: OMG!! How to implement it? + gc_exit(objspace, gc_enter_event_rb_memerror, NULL); + } exc = nomem_error; if (!exc || @@ -9635,22 +11138,54 @@ rb_aligned_malloc(size_t alignment, size_t size) #elif defined _WIN32 void *_aligned_malloc(size_t, size_t); res = _aligned_malloc(size, alignment); -#elif defined(HAVE_POSIX_MEMALIGN) - if (posix_memalign(&res, alignment, size) == 0) { - return res; +#else + if (USE_MMAP_ALIGNED_ALLOC) { + GC_ASSERT(alignment % sysconf(_SC_PAGE_SIZE) == 0); + + char *ptr = mmap(NULL, alignment + size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ptr == MAP_FAILED) { + return NULL; + } + + char *aligned = ptr + alignment; + aligned -= ((VALUE)aligned & (alignment - 1)); + GC_ASSERT(aligned > ptr); + GC_ASSERT(aligned <= ptr + alignment); + + size_t start_out_of_range_size = aligned - ptr; + GC_ASSERT(start_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); + if (start_out_of_range_size > 0) { + if (munmap(ptr, start_out_of_range_size)) { + rb_bug("rb_aligned_malloc: munmap failed for start"); + } + } + + size_t end_out_of_range_size = alignment - start_out_of_range_size; + GC_ASSERT(end_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0); + if (end_out_of_range_size > 0) { + if (munmap(aligned + size, end_out_of_range_size)) { + rb_bug("rb_aligned_malloc: munmap failed for end"); + } + } + + res = (void *)aligned; } else { - return NULL; +# if defined(HAVE_POSIX_MEMALIGN) + if (posix_memalign(&res, alignment, size) != 0) { + return NULL; + } +# elif defined(HAVE_MEMALIGN) + res = memalign(alignment, size); +# else + char* aligned; + res = malloc(alignment + size + sizeof(void*)); + aligned = (char*)res + alignment + sizeof(void*); + aligned -= ((VALUE)aligned & (alignment - 1)); + ((void**)aligned)[-1] = res; + res = (void*)aligned; +# endif } -#elif defined(HAVE_MEMALIGN) - res = memalign(alignment, size); -#else - char* aligned; - res = malloc(alignment + size + sizeof(void*)); - aligned = (char*)res + alignment + sizeof(void*); - aligned -= ((VALUE)aligned & (alignment - 1)); - ((void**)aligned)[-1] = res; - res = (void*)aligned; #endif /* alignment must be a power of 2 */ @@ -9660,16 +11195,26 @@ rb_aligned_malloc(size_t alignment, size_t size) } static void -rb_aligned_free(void *ptr) +rb_aligned_free(void *ptr, size_t size) { #if defined __MINGW32__ __mingw_aligned_free(ptr); #elif defined _WIN32 _aligned_free(ptr); -#elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN) - free(ptr); #else - free(((void**)ptr)[-1]); + if (USE_MMAP_ALIGNED_ALLOC) { + GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0); + if (munmap(ptr, size)) { + rb_bug("rb_aligned_free: munmap failed"); + } + } + else { +# if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) + free(ptr); +# else + free(((void**)ptr)[-1]); +# endif + } #endif } @@ -9705,8 +11250,8 @@ static void objspace_malloc_gc_stress(rb_objspace_t *objspace) { if (ruby_gc_stressful && ruby_native_thread_p()) { - int reason = GPR_FLAG_IMMEDIATE_MARK | GPR_FLAG_IMMEDIATE_SWEEP | - GPR_FLAG_STRESS | GPR_FLAG_MALLOC; + unsigned int reason = (GPR_FLAG_IMMEDIATE_MARK | GPR_FLAG_IMMEDIATE_SWEEP | + GPR_FLAG_STRESS | GPR_FLAG_MALLOC); if (gc_stress_full_mark_after_malloc_p()) { reason |= GPR_FLAG_FULL_MARK; @@ -9715,8 +11260,20 @@ objspace_malloc_gc_stress(rb_objspace_t *objspace) } } -static void -objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type) +static inline bool +objspace_malloc_increase_report(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type) +{ + if (0) fprintf(stderr, "increase - ptr: %p, type: %s, new_size: %"PRIdSIZE", old_size: %"PRIdSIZE"\n", + mem, + type == MEMOP_TYPE_MALLOC ? "malloc" : + type == MEMOP_TYPE_FREE ? "free " : + type == MEMOP_TYPE_REALLOC ? "realloc": "error", + new_size, old_size); + return false; +} + +static bool +objspace_malloc_increase_body(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type) { if (new_size > old_size) { ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size); @@ -9733,8 +11290,8 @@ objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, si if (type == MEMOP_TYPE_MALLOC) { retry: - if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc) { - if (ruby_thread_has_gvl_p() && is_lazy_sweeping(heap_eden)) { + if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc_val()) { + if (ruby_thread_has_gvl_p() && is_lazy_sweeping(objspace)) { gc_rest(objspace); /* gc_rest can reduce malloc_increase */ goto retry; } @@ -9758,13 +11315,6 @@ objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, si atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size); } - if (0) fprintf(stderr, "increase - ptr: %p, type: %s, new_size: %d, old_size: %d\n", - mem, - type == MEMOP_TYPE_MALLOC ? "malloc" : - type == MEMOP_TYPE_FREE ? "free " : - type == MEMOP_TYPE_REALLOC ? "realloc": "error", - (int)new_size, (int)old_size); - switch (type) { case MEMOP_TYPE_MALLOC: ATOMIC_SIZE_INC(objspace->malloc_params.allocations); @@ -9785,8 +11335,14 @@ objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, si case MEMOP_TYPE_REALLOC: /* ignore */ break; } #endif + return true; } +#define objspace_malloc_increase(...) \ + for (bool malloc_increase_done = objspace_malloc_increase_report(__VA_ARGS__); \ + !malloc_increase_done; \ + malloc_increase_done = objspace_malloc_increase_body(__VA_ARGS__)) + struct malloc_obj_info { /* 4 words */ size_t size; #if USE_GC_MALLOC_OBJ_INFO_DETAILS @@ -9827,8 +11383,6 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) info->gen = objspace->profile.count; info->file = ruby_malloc_info_file; info->line = info->file ? ruby_malloc_info_line : 0; -#else - info->file = NULL; #endif mem = info + 1; } @@ -9837,7 +11391,37 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) return mem; } -#define TRY_WITH_GC(alloc) do { \ +#if defined(__GNUC__) && RUBY_DEBUG +#define RB_BUG_INSTEAD_OF_RB_MEMERROR +#endif + +#ifdef RB_BUG_INSTEAD_OF_RB_MEMERROR +#define TRY_WITH_GC(siz, expr) do { \ + const gc_profile_record_flag gpr = \ + GPR_FLAG_FULL_MARK | \ + GPR_FLAG_IMMEDIATE_MARK | \ + GPR_FLAG_IMMEDIATE_SWEEP | \ + GPR_FLAG_MALLOC; \ + objspace_malloc_gc_stress(objspace); \ + \ + if (LIKELY((expr))) { \ + /* Success on 1st try */ \ + } \ + else if (!garbage_collect_with_gvl(objspace, gpr)) { \ + /* @shyouhei thinks this doesn't happen */ \ + rb_bug("TRY_WITH_GC: could not GC"); \ + } \ + else if ((expr)) { \ + /* Success on 2nd try */ \ + } \ + else { \ + rb_bug("TRY_WITH_GC: could not allocate:" \ + "%"PRIdSIZE" bytes for %s", \ + siz, # expr); \ + } \ + } while (0) +#else +#define TRY_WITH_GC(siz, alloc) do { \ objspace_malloc_gc_stress(objspace); \ if (!(alloc) && \ (!garbage_collect_with_gvl(objspace, GPR_FLAG_FULL_MARK | \ @@ -9847,9 +11431,10 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) ruby_memerror(); \ } \ } while (0) +#endif /* these shouldn't be called directly. - * objspace_* functinos do not check allocation size. + * objspace_* functions do not check allocation size. */ static void * objspace_xmalloc0(rb_objspace_t *objspace, size_t size) @@ -9857,7 +11442,7 @@ objspace_xmalloc0(rb_objspace_t *objspace, size_t size) void *mem; size = objspace_malloc_prepare(objspace, size); - TRY_WITH_GC(mem = malloc(size)); + TRY_WITH_GC(size, mem = malloc(size)); RB_DEBUG_COUNTER_INC(heap_xmalloc); return objspace_malloc_fixup(objspace, mem, size); } @@ -9928,7 +11513,7 @@ objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t ol #endif old_size = objspace_malloc_size(objspace, ptr, old_size); - TRY_WITH_GC(mem = realloc(ptr, new_size)); + TRY_WITH_GC(new_size, mem = realloc(ptr, new_size)); new_size = objspace_malloc_size(objspace, mem, new_size); #if CALC_EXACT_MALLOC_SIZE @@ -9960,7 +11545,7 @@ mmalloc_info_file_i(st_data_t key, st_data_t val, st_data_t dmy) const char *file = (void *)key; const size_t *data = (void *)val; - fprintf(stderr, "%s\t%d\t%d\n", file, (int)data[0], (int)data[1]); + fprintf(stderr, "%s\t%"PRIdSIZE"\t%"PRIdSIZE"\n", file, data[0], data[1]); return ST_CONTINUE; } @@ -9974,19 +11559,19 @@ rb_malloc_info_show_results(void) fprintf(stderr, "* malloc_info gen statistics\n"); for (i=0; ifile; + st_data_t key = (st_data_t)info->file, d; size_t *data; if (malloc_info_file_table == NULL) { malloc_info_file_table = st_init_numtable_with_size(1024); } - if (st_lookup(malloc_info_file_table, key, (st_data_t *)&data)) { + if (st_lookup(malloc_info_file_table, key, &d)) { /* hit */ + data = (size_t *)d; } else { data = malloc(xmalloc2_size(2, sizeof(size_t))); @@ -10053,25 +11639,25 @@ objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size) data[0] ++; data[1] += info->size; }; -#if 0 /* verbose output */ - if (gen >= 2) { + if (0 && gen >= 2) { /* verbose output */ if (info->file) { - fprintf(stderr, "free - size:%d, gen:%d, pos: %s:%d\n", (int)info->size, gen, info->file, (int)info->line); + fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d, pos: %s:%"PRIdSIZE"\n", + info->size, gen, info->file, info->line); } else { - fprintf(stderr, "free - size:%d, gen:%d\n", (int)info->size, gen); + fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d\n", + info->size, gen); } } -#endif } #endif #endif old_size = objspace_malloc_size(objspace, ptr, old_size); - free(ptr); - RB_DEBUG_COUNTER_INC(heap_xfree); - - objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE); + objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE) { + free(ptr); + RB_DEBUG_COUNTER_INC(heap_xfree); + } } static void * @@ -10109,7 +11695,7 @@ objspace_xcalloc(rb_objspace_t *objspace, size_t size) void *mem; size = objspace_malloc_prepare(objspace, size); - TRY_WITH_GC(mem = calloc1(size)); + TRY_WITH_GC(size, mem = calloc1(size)); return objspace_malloc_fixup(objspace, mem, size); } @@ -10223,8 +11809,6 @@ ruby_mimmalloc(size_t size) info->gen = 0; info->file = NULL; info->line = 0; -#else - info->file = NULL; #endif mem = info + 1; } @@ -10417,7 +12001,6 @@ static const rb_data_type_t weakmap_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; -extern const struct st_hash_type rb_hashtype_ident; static VALUE wmap_finalize(RB_BLOCK_CALL_FUNC_ARGLIST(objid, self)); static VALUE @@ -10425,8 +12008,8 @@ wmap_allocate(VALUE klass) { struct weakmap *w; VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &weakmap_type, w); - w->obj2wmap = st_init_table(&rb_hashtype_ident); - w->wmap2obj = st_init_table(&rb_hashtype_ident); + w->obj2wmap = rb_init_identtable(); + w->wmap2obj = rb_init_identtable(); w->final = rb_func_lambda_new(wmap_finalize, obj, 1, 1); return obj; } @@ -10434,9 +12017,20 @@ wmap_allocate(VALUE klass) static int wmap_live_p(rb_objspace_t *objspace, VALUE obj) { - if (!FL_ABLE(obj)) return TRUE; - if (!is_id_value(objspace, obj)) return FALSE; - if (!is_live_object(objspace, obj)) return FALSE; + if (SPECIAL_CONST_P(obj)) return TRUE; + if (is_pointer_to_heap(objspace, (void *)obj)) { + void *poisoned = asan_unpoison_object_temporary(obj); + + enum ruby_value_type t = BUILTIN_TYPE(obj); + int ret = (!(t == T_NONE || t >= T_FIXNUM || t == T_ICLASS) && + is_live_object(objspace, obj)); + + if (poisoned) { + asan_poison_object(obj); + } + + return ret; + } return TRUE; } @@ -10502,10 +12096,26 @@ struct wmap_iter_arg { VALUE value; }; +static VALUE +wmap_inspect_append(rb_objspace_t *objspace, VALUE str, VALUE obj) +{ + if (SPECIAL_CONST_P(obj)) { + return rb_str_append(str, rb_inspect(obj)); + } + else if (wmap_live_p(objspace, obj)) { + return rb_str_append(str, rb_any_to_s(obj)); + } + else { + return rb_str_catf(str, "#", (void*)obj); + } +} + static int wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg) { - VALUE str = (VALUE)arg; + struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg; + rb_objspace_t *objspace = argp->objspace; + VALUE str = argp->value; VALUE k = (VALUE)key, v = (VALUE)val; if (RSTRING_PTR(str)[0] == '#') { @@ -10515,11 +12125,9 @@ wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg) rb_str_cat2(str, ": "); RSTRING_PTR(str)[0] = '#'; } - k = SPECIAL_CONST_P(k) ? rb_inspect(k) : rb_any_to_s(k); - rb_str_append(str, k); + wmap_inspect_append(objspace, str, k); rb_str_cat2(str, " => "); - v = SPECIAL_CONST_P(v) ? rb_inspect(v) : rb_any_to_s(v); - rb_str_append(str, v); + wmap_inspect_append(objspace, str, v); return ST_CONTINUE; } @@ -10530,11 +12138,14 @@ wmap_inspect(VALUE self) VALUE str; VALUE c = rb_class_name(CLASS_OF(self)); struct weakmap *w; + struct wmap_iter_arg args; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self); if (w->wmap2obj) { - st_foreach(w->wmap2obj, wmap_inspect_i, str); + args.objspace = &rb_objspace; + args.value = str; + st_foreach(w->wmap2obj, wmap_inspect_i, (st_data_t)&args); } RSTRING_PTR(str)[0] = '#'; rb_str_cat2(str, ">"); @@ -10687,26 +12298,26 @@ wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing) /* Creates a weak reference from the given key to the given value */ static VALUE -wmap_aset(VALUE self, VALUE wmap, VALUE orig) +wmap_aset(VALUE self, VALUE key, VALUE value) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); - if (FL_ABLE(orig)) { - define_final0(orig, w->final); + if (FL_ABLE(value)) { + define_final0(value, w->final); } - if (FL_ABLE(wmap)) { - define_final0(wmap, w->final); + if (FL_ABLE(key)) { + define_final0(key, w->final); } - st_update(w->obj2wmap, (st_data_t)orig, wmap_aset_update, wmap); - st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig); - return nonspecial_obj_id(orig); + st_update(w->obj2wmap, (st_data_t)value, wmap_aset_update, key); + st_insert(w->wmap2obj, (st_data_t)key, (st_data_t)value); + return nonspecial_obj_id(value); } /* Retrieves a weakly referenced object with the given key */ static VALUE -wmap_aref(VALUE self, VALUE wmap) +wmap_lookup(VALUE self, VALUE key) { st_data_t data; VALUE obj; @@ -10714,17 +12325,25 @@ wmap_aref(VALUE self, VALUE wmap) rb_objspace_t *objspace = &rb_objspace; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); - if (!st_lookup(w->wmap2obj, (st_data_t)wmap, &data)) return Qnil; + if (!st_lookup(w->wmap2obj, (st_data_t)key, &data)) return Qundef; obj = (VALUE)data; - if (!wmap_live_p(objspace, obj)) return Qnil; + if (!wmap_live_p(objspace, obj)) return Qundef; return obj; } +/* Retrieves a weakly referenced object with the given key */ +static VALUE +wmap_aref(VALUE self, VALUE key) +{ + VALUE obj = wmap_lookup(self, key); + return obj != Qundef ? obj : Qnil; +} + /* Returns +true+ if +key+ is registered */ static VALUE wmap_has_key(VALUE self, VALUE key) { - return NIL_P(wmap_aref(self, key)) ? Qfalse : Qtrue; + return wmap_lookup(self, key) == Qundef ? Qfalse : Qtrue; } /* Returns the number of referenced objects */ @@ -10749,16 +12368,14 @@ wmap_size(VALUE self) #define GC_PROFILE_RECORD_DEFAULT_SIZE 100 -/* return sec in user time */ -static double -getrusage_time(void) +static bool +current_process_time(struct timespec *ts) { #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) { static int try_clock_gettime = 1; - struct timespec ts; - if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) { - return ts.tv_sec + ts.tv_nsec * 1e-9; + if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ts) == 0) { + return true; } else { try_clock_gettime = 0; @@ -10772,7 +12389,9 @@ getrusage_time(void) struct timeval time; if (getrusage(RUSAGE_SELF, &usage) == 0) { time = usage.ru_utime; - return time.tv_sec + time.tv_usec * 1e-6; + ts->tv_sec = time.tv_sec; + ts->tv_nsec = (int32_t)time.tv_usec * 1000; + return true; } } #endif @@ -10780,32 +12399,37 @@ getrusage_time(void) #ifdef _WIN32 { FILETIME creation_time, exit_time, kernel_time, user_time; - ULARGE_INTEGER ui; - LONG_LONG q; - double t; + ULARGE_INTEGER ui; - if (GetProcessTimes(GetCurrentProcess(), + if (GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time, &kernel_time, &user_time) != 0) { - memcpy(&ui, &user_time, sizeof(FILETIME)); - q = ui.QuadPart / 10L; - t = (DWORD)(q % 1000000L) * 1e-6; - q /= 1000000L; -#ifdef __GNUC__ - t += q; -#else - t += (double)(DWORD)(q >> 16) * (1 << 16); - t += (DWORD)q & ~(~0 << 16); -#endif - return t; + memcpy(&ui, &user_time, sizeof(FILETIME)); +#define PER100NSEC (uint64_t)(1000 * 1000 * 10) + ts->tv_nsec = (long)(ui.QuadPart % PER100NSEC); + ts->tv_sec = (time_t)(ui.QuadPart / PER100NSEC); + return true; } } #endif - return 0.0; + return false; +} + +static double +getrusage_time(void) +{ + struct timespec ts; + if (current_process_time(&ts)) { + return ts.tv_sec + ts.tv_nsec * 1e-9; + } + else { + return 0.0; + } } + static inline void -gc_prof_setup_new_record(rb_objspace_t *objspace, int reason) +gc_prof_setup_new_record(rb_objspace_t *objspace, unsigned int reason) { if (objspace->profile.run) { size_t index = objspace->profile.next_index; @@ -11077,6 +12701,7 @@ gc_profile_record_get(VALUE _) rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(record->heap_use_size)); rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), SIZET2NUM(record->heap_total_size)); rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), SIZET2NUM(record->heap_total_objects)); + rb_hash_aset(prof, ID2SYM(rb_intern("MOVED_OBJECTS")), SIZET2NUM(record->moved_objects)); rb_hash_aset(prof, ID2SYM(rb_intern("GC_IS_MARKED")), Qtrue); #if GC_PROFILE_MORE_DETAIL rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(record->gc_mark_time)); @@ -11090,7 +12715,7 @@ gc_profile_record_get(VALUE _) rb_hash_aset(prof, ID2SYM(rb_intern("REMOVING_OBJECTS")), SIZET2NUM(record->removing_objects)); rb_hash_aset(prof, ID2SYM(rb_intern("EMPTY_OBJECTS")), SIZET2NUM(record->empty_objects)); - rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), (record->flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse); + rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), RBOOL(record->flags & GPR_FLAG_HAVE_FINALIZE)); #endif #if RGENGC_PROFILE > 0 @@ -11108,9 +12733,9 @@ gc_profile_record_get(VALUE _) #define MAJOR_REASON_MAX 0x10 static char * -gc_profile_dump_major_reason(int flags, char *buff) +gc_profile_dump_major_reason(unsigned int flags, char *buff) { - int reason = flags & GPR_FLAG_MAJOR_MASK; + unsigned int reason = flags & GPR_FLAG_MAJOR_MASK; int i = 0; if (reason == GPR_FLAG_NONE) { @@ -11160,7 +12785,7 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE)) } #if GC_PROFILE_MORE_DETAIL - append(out, rb_str_new_cstr("\n\n" \ + const char *str = "\n\n" \ "More detail.\n" \ "Prepare Time = Previously GC's rest sweep time\n" "Index Flags Allocate Inc. Allocate Limit" @@ -11174,7 +12799,8 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE)) #if GC_PROFILE_DETAIL_MEMORY " MaxRSS(KB) MinorFLT MajorFLT" #endif - "\n")); + "\n"; + append(out, rb_str_new_cstr(str)); for (i = 0; i < count; i++) { record = &objspace->profile.records[i]; @@ -11305,7 +12931,7 @@ static VALUE gc_profile_enable_get(VALUE self) { rb_objspace_t *objspace = &rb_objspace; - return objspace->profile.run ? Qtrue : Qfalse; + return RBOOL(objspace->profile.run); } /* @@ -11434,10 +13060,21 @@ rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq) } } +static int +str_len_no_raise(VALUE str) +{ + long len = RSTRING_LEN(str); + if (len < 0) return 0; + if (len > INT_MAX) return INT_MAX; + return (int)len; +} + const char * rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) { int pos = 0; + void *poisoned = asan_poisoned_object_p(obj); + asan_unpoison_object(obj, false); #define BUFF_ARGS buff + pos, buff_size - pos #define APPENDF(f) if ((pos += snprintf f) >= buff_size) goto end @@ -11455,17 +13092,17 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) #define TF(c) ((c) != 0 ? "true" : "false") #define C(c, s) ((c) != 0 ? (s) : " ") const int type = BUILTIN_TYPE(obj); -#if USE_RGENGC const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags); if (is_pointer_to_heap(&rb_objspace, (void *)obj)) { - APPENDF((BUFF_ARGS, "%p [%d%s%s%s%s%s] %s ", + APPENDF((BUFF_ARGS, "%p [%d%s%s%s%s%s%s] %s ", (void *)obj, age, C(RVALUE_UNCOLLECTIBLE_BITMAP(obj), "L"), C(RVALUE_MARK_BITMAP(obj), "M"), C(RVALUE_PIN_BITMAP(obj), "P"), C(RVALUE_MARKING_BITMAP(obj), "R"), C(RVALUE_WB_UNPROTECTED_BITMAP(obj), "U"), + C(rb_objspace_garbage_object_p(obj), "G"), obj_type_name(obj))); } else { @@ -11474,12 +13111,6 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) (void *)obj, age, obj_type_name(obj))); } -#else - APPENDF((BUFF_ARGS, "%p [%s] %s", - (void *)obj, - C(RVALUE_MARK_BITMAP(obj), "M"), - obj_type_name(obj))); -#endif if (internal_object_p(obj)) { /* ignore */ @@ -11510,34 +13141,46 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) rb_obj_info(RARRAY(obj)->as.heap.aux.shared_root))); } else if (FL_TEST(obj, RARRAY_EMBED_FLAG)) { - APPENDF((BUFF_ARGS, "[%s%s] len: %d (embed)", + APPENDF((BUFF_ARGS, "[%s%s] len: %ld (embed)", C(ARY_EMBED_P(obj), "E"), C(ARY_SHARED_P(obj), "S"), - (int)RARRAY_LEN(obj))); + RARRAY_LEN(obj))); } else { - APPENDF((BUFF_ARGS, "[%s%s%s] len: %d, capa:%d ptr:%p", + APPENDF((BUFF_ARGS, "[%s%s%s] len: %ld, capa:%ld ptr:%p", C(ARY_EMBED_P(obj), "E"), C(ARY_SHARED_P(obj), "S"), C(RARRAY_TRANSIENT_P(obj), "T"), - (int)RARRAY_LEN(obj), - ARY_EMBED_P(obj) ? -1 : (int)RARRAY(obj)->as.heap.aux.capa, + RARRAY_LEN(obj), + ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa, (void *)RARRAY_CONST_PTR_TRANSIENT(obj))); } break; case T_STRING: { - APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(obj))); + if (STR_SHARED_P(obj)) APPENDF((BUFF_ARGS, " [shared] ")); + APPENDF((BUFF_ARGS, "%.*s", str_len_no_raise(obj), RSTRING_PTR(obj))); break; } + case T_SYMBOL: { + VALUE fstr = RSYMBOL(obj)->fstr; + ID id = RSYMBOL(obj)->id; + if (RB_TYPE_P(fstr, T_STRING)) { + APPENDF((BUFF_ARGS, ":%s id:%d", RSTRING_PTR(fstr), (unsigned int)id)); + } + else { + APPENDF((BUFF_ARGS, "(%p) id:%d", (void *)fstr, (unsigned int)id)); + } + break; + } case T_MOVED: { APPENDF((BUFF_ARGS, "-> %p", (void*)rb_gc_location(obj))); break; } case T_HASH: { - APPENDF((BUFF_ARGS, "[%c%c] %d", + APPENDF((BUFF_ARGS, "[%c%c] %"PRIdSIZE, RHASH_AR_TABLE_P(obj) ? 'A' : 'S', RHASH_TRANSIENT_P(obj) ? 'T' : ' ', - (int)RHASH_SIZE(obj))); + RHASH_SIZE(obj))); break; } case T_CLASS: @@ -11547,6 +13190,9 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) if (!NIL_P(class_path)) { APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(class_path))); } + else { + APPENDF((BUFF_ARGS, "(annon)")); + } break; } case T_ICLASS: @@ -11579,6 +13225,12 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) (iseq = vm_block_iseq(block)) != NULL) { rb_raw_iseq_info(BUFF_ARGS, iseq); } + else if (rb_ractor_p(obj)) { + rb_ractor_t *r = (void *)DATA_PTR(obj); + if (r) { + APPENDF((BUFF_ARGS, "r:%d", r->pub.id)); + } + } else { const char * const type_name = rb_objspace_data_type_name(obj); if (type_name) { @@ -11588,46 +13240,66 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) break; } case T_IMEMO: { - const char *imemo_name = "\0"; - switch (imemo_type(obj)) { -#define IMEMO_NAME(x) case imemo_##x: imemo_name = #x; break; - IMEMO_NAME(env); - IMEMO_NAME(cref); - IMEMO_NAME(svar); - IMEMO_NAME(throw_data); - IMEMO_NAME(ifunc); - IMEMO_NAME(memo); - IMEMO_NAME(ment); - IMEMO_NAME(iseq); - IMEMO_NAME(tmpbuf); - IMEMO_NAME(ast); - IMEMO_NAME(parser_strterm); -#undef IMEMO_NAME - default: UNREACHABLE; - } - APPENDF((BUFF_ARGS, "/%s", imemo_name)); + APPENDF((BUFF_ARGS, "<%s> ", rb_imemo_name(imemo_type(obj)))); switch (imemo_type(obj)) { - case imemo_ment: { - const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment; - if (me->def) { - APPENDF((BUFF_ARGS, "(called_id: %s, type: %s, alias: %d, owner: %s, defined_class: %s)", - rb_id2name(me->called_id), - rb_method_type_name(me->def->type), - me->def->alias_count, - obj_info(me->owner), - obj_info(me->defined_class))); - } - else { - APPENDF((BUFF_ARGS, "%s", rb_id2name(me->called_id))); - } - break; - } + case imemo_ment: + { + const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment; + + APPENDF((BUFF_ARGS, ":%s (%s%s%s%s) type:%s alias:%d owner:%p defined_class:%p", + rb_id2name(me->called_id), + METHOD_ENTRY_VISI(me) == METHOD_VISI_PUBLIC ? "pub" : + METHOD_ENTRY_VISI(me) == METHOD_VISI_PRIVATE ? "pri" : "pro", + METHOD_ENTRY_COMPLEMENTED(me) ? ",cmp" : "", + METHOD_ENTRY_CACHED(me) ? ",cc" : "", + METHOD_ENTRY_INVALIDATED(me) ? ",inv" : "", + me->def ? rb_method_type_name(me->def->type) : "NULL", + me->def ? me->def->alias_count : -1, + (void *)me->owner, // obj_info(me->owner), + (void *)me->defined_class)); //obj_info(me->defined_class))); + + if (me->def) { + switch (me->def->type) { + case VM_METHOD_TYPE_ISEQ: + APPENDF((BUFF_ARGS, " (iseq:%s)", obj_info((VALUE)me->def->body.iseq.iseqptr))); + break; + default: + break; + } + } + + break; + } case imemo_iseq: { const rb_iseq_t *iseq = (const rb_iseq_t *)obj; rb_raw_iseq_info(BUFF_ARGS, iseq); break; } + case imemo_callinfo: + { + const struct rb_callinfo *ci = (const struct rb_callinfo *)obj; + APPENDF((BUFF_ARGS, "(mid:%s, flag:%x argc:%d, kwarg:%s)", + rb_id2name(vm_ci_mid(ci)), + vm_ci_flag(ci), + vm_ci_argc(ci), + vm_ci_kwarg(ci) ? "available" : "NULL")); + break; + } + case imemo_callcache: + { + const struct rb_callcache *cc = (const struct rb_callcache *)obj; + VALUE class_path = cc->klass ? rb_class_path_cached(cc->klass) : Qnil; + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + + APPENDF((BUFF_ARGS, "(klass:%s cme:%s%s (%p) call:%p", + NIL_P(class_path) ? (cc->klass ? "??" : "") : RSTRING_PTR(class_path), + cme ? rb_id2name(cme->called_id) : "", + cme ? (METHOD_ENTRY_INVALIDATED(cme) ? " [inv]" : "") : "", + (void *)cme, + (void *)vm_cc_call(cc))); + break; + } default: break; } @@ -11639,6 +13311,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) #undef C } end: + if (poisoned) { + asan_poison_object(obj); + } + return buff; #undef APPENDF #undef BUFF_ARGS @@ -11683,7 +13359,7 @@ rb_obj_info_dump(VALUE obj) fprintf(stderr, "rb_obj_info_dump: %s\n", rb_raw_obj_info(buff, 0x100, obj)); } -void +MJIT_FUNC_EXPORTED void rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func) { char buff[0x100]; @@ -11715,14 +13391,12 @@ rb_gcdebug_print_obj_condition(VALUE obj) fprintf(stderr, "marked? : %s\n", MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) ? "true" : "false"); fprintf(stderr, "pinned? : %s\n", MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj) ? "true" : "false"); -#if USE_RGENGC fprintf(stderr, "age? : %d\n", RVALUE_AGE(obj)); fprintf(stderr, "old? : %s\n", RVALUE_OLD_P(obj) ? "true" : "false"); fprintf(stderr, "WB-protected?: %s\n", RVALUE_WB_UNPROTECTED(obj) ? "false" : "true"); fprintf(stderr, "remembered? : %s\n", RVALUE_REMEMBERED(obj) ? "true" : "false"); -#endif - if (is_lazy_sweeping(heap_eden)) { + if (is_lazy_sweeping(objspace)) { fprintf(stderr, "lazy sweeping?: true\n"); fprintf(stderr, "swept?: %s\n", is_swept_object(objspace, obj) ? "done" : "not yet"); } @@ -11801,9 +13475,9 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self) * * ObjectSpace also provides support for object finalizers, procs that will be * called when a specific object is about to be destroyed by garbage - * collection. - * - * require 'objspace' + * collection. See the documentation for + * ObjectSpace.define_finalizer for important information on + * how to use this method correctly. * * a = "A" * b = "B" @@ -11811,6 +13485,9 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self) * ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" }) * ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" }) * + * a = nil + * b = nil + * * _produces:_ * * Finalizer two on 537763470 @@ -11856,13 +13533,15 @@ Init_GC(void) VALUE gc_constants; rb_mGC = rb_define_module("GC"); - load_gc(); gc_constants = rb_hash_new(); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("DEBUG")), RBOOL(GC_DEBUG)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE))); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE)); - rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_PLANES")), SIZET2NUM(HEAP_PAGE_BITMAP_PLANES)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("SIZE_POOL_COUNT")), LONG2FIX(SIZE_POOL_COUNT)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(size_pool_slot_size(SIZE_POOL_COUNT - 1))); OBJ_FREEZE(gc_constants); /* internal constants */ rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants); @@ -11915,7 +13594,6 @@ Init_GC(void) /* internal methods */ rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency_m, 0); - rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1); rb_define_singleton_method(rb_mGC, "verify_transient_heap_internal_consistency", gc_verify_transient_heap_internal_consistency, 0); #if MALLOC_ALLOCATED_SIZE rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0); diff --git a/ruby/gc.h b/ruby/gc.h index cf794fa51..91d6e5787 100644 --- a/ruby/gc.h +++ b/ruby/gc.h @@ -1,19 +1,30 @@ - #ifndef RUBY_GC_H #define RUBY_GC_H 1 +#include "ruby/ruby.h" #if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__) #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p))) #elif defined(__i386) && defined(__GNUC__) #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p))) -#elif defined(__powerpc64__) && defined(__GNUC__) +#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && !defined(_AIX) #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr\t%0, %%r1" : "=r" (*(p))) +#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && defined(_AIX) +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr %0,1" : "=r" (*(p))) +#elif defined(__aarch64__) && defined(__GNUC__) +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mov\t%0, sp" : "=r" (*(p))) #else NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p)); #define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p) #define USE_CONSERVATIVE_STACK_END #endif +#define RB_GC_SAVE_MACHINE_CONTEXT(th) \ + do { \ + FLUSH_REGISTER_WINDOWS; \ + setjmp((th)->ec->machine.regs); \ + SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \ + } while (0) + /* for GC debug */ #ifndef RUBY_MARK_FREE_DEBUG @@ -26,7 +37,7 @@ extern int ruby_gc_debug_indent; static inline void rb_gc_debug_indent(void) { - printf("%*s", ruby_gc_debug_indent, ""); + ruby_debug_printf("%*s", ruby_gc_debug_indent, ""); } static inline void @@ -36,7 +47,7 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) ruby_gc_debug_indent--; } rb_gc_debug_indent(); - printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr); + ruby_debug_printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr); if (st) { ruby_gc_debug_indent++; @@ -49,7 +60,7 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) #define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", (msg), 0, ptr) #define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", (msg), 1, ptr) #define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", (msg), 0, ptr) -#define RUBY_GC_INFO rb_gc_debug_indent(); printf +#define RUBY_GC_INFO rb_gc_debug_indent(), ruby_debug_printf #else #define RUBY_MARK_ENTER(msg) @@ -59,7 +70,7 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) #define RUBY_GC_INFO if(0)printf #endif -#define RUBY_MARK_NO_PIN_UNLESS_NULL(ptr) do { \ +#define RUBY_MARK_MOVABLE_UNLESS_NULL(ptr) do { \ VALUE markobj = (ptr); \ if (RTEST(markobj)) {rb_gc_mark_movable(markobj);} \ } while (0) @@ -116,7 +127,6 @@ void rb_objspace_reachable_objects_from_root(void (func)(const char *category, V int rb_objspace_markable_object_p(VALUE obj); int rb_objspace_internal_object_p(VALUE obj); int rb_objspace_marked_object_p(VALUE obj); -int rb_objspace_garbage_object_p(VALUE obj); void rb_objspace_each_objects( int (*callback)(void *start, void *end, size_t stride, void *data), diff --git a/ruby/gc.rb b/ruby/gc.rb index fcfa48fbe..72637f379 100644 --- a/ruby/gc.rb +++ b/ruby/gc.rb @@ -31,11 +31,32 @@ module GC # are not guaranteed to be future-compatible, and may be ignored if the # underlying implementation does not support them. def self.start full_mark: true, immediate_mark: true, immediate_sweep: true - __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep + Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true - __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep + Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false + end + + # call-seq: + # GC.auto_compact -> true or false + # + # Returns whether or not automatic compaction has been enabled. + # + def self.auto_compact + Primitive.gc_get_auto_compact + end + + # call-seq: + # GC.auto_compact = flag + # + # Updates automatic compaction mode. + # + # When enabled, the compactor will execute on every major collection. + # + # Enabling compaction will degrade performance on major collections. + def self.auto_compact=(flag) + Primitive.gc_set_auto_compact(flag) end # call-seq: @@ -49,7 +70,7 @@ def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true # GC.enable #=> false # def self.enable - __builtin_gc_enable + Primitive.gc_enable end # call-seq: @@ -61,7 +82,7 @@ def self.enable # GC.disable #=> false # GC.disable #=> true def self.disable - __builtin_gc_disable + Primitive.gc_disable end # call-seq: @@ -69,7 +90,7 @@ def self.disable # # Returns current status of GC stress mode. def self.stress - __builtin_gc_stress_get + Primitive.gc_stress_get end # call-seq: @@ -87,7 +108,7 @@ def self.stress # 0x02:: no immediate sweep # 0x04:: full mark after malloc/calloc/realloc def self.stress=(flag) - __builtin_gc_stress_set_m flag + Primitive.gc_stress_set_m flag end # call-seq: @@ -97,52 +118,82 @@ def self.stress=(flag) # # It returns the number of times GC occurred since the process started. def self.count - __builtin_gc_count + Primitive.gc_count end # call-seq: # GC.stat -> Hash - # GC.stat(hash) -> hash + # GC.stat(hash) -> Hash # GC.stat(:key) -> Numeric # # Returns a Hash containing information about the GC. # + # The contents of the hash are implementation specific and may change in + # the future without notice. + # # The hash includes information about internal statistics about GC such as: # - # { - # :count=>0, - # :heap_allocated_pages=>24, - # :heap_sorted_length=>24, - # :heap_allocatable_pages=>0, - # :heap_available_slots=>9783, - # :heap_live_slots=>7713, - # :heap_free_slots=>2070, - # :heap_final_slots=>0, - # :heap_marked_slots=>0, - # :heap_eden_pages=>24, - # :heap_tomb_pages=>0, - # :total_allocated_pages=>24, - # :total_freed_pages=>0, - # :total_allocated_objects=>7796, - # :total_freed_objects=>83, - # :malloc_increase_bytes=>2389312, - # :malloc_increase_bytes_limit=>16777216, - # :minor_gc_count=>0, - # :major_gc_count=>0, - # :remembered_wb_unprotected_objects=>0, - # :remembered_wb_unprotected_objects_limit=>0, - # :old_objects=>0, - # :old_objects_limit=>0, - # :oldmalloc_increase_bytes=>2389760, - # :oldmalloc_increase_bytes_limit=>16777216 - # } - # - # The contents of the hash are implementation specific and may be changed in - # the future. - # - # This method is only expected to work on C Ruby. + # [count] + # The total number of garbage collections ran since application start + # (count includes both minor and major garbage collections) + # [heap_allocated_pages] + # The total number of `:heap_eden_pages` + `:heap_tomb_pages` + # [heap_sorted_length] + # The number of pages that can fit into the buffer that holds references to + # all pages + # [heap_allocatable_pages] + # The total number of pages the application could allocate without additional GC + # [heap_available_slots] + # The total number of slots in all `:heap_allocated_pages` + # [heap_live_slots] + # The total number of slots which contain live objects + # [heap_free_slots] + # The total number of slots which do not contain live objects + # [heap_final_slots] + # The total number of slots with pending finalizers to be run + # [heap_marked_slots] + # The total number of objects marked in the last GC + # [heap_eden_pages] + # The total number of pages which contain at least one live slot + # [heap_tomb_pages] + # The total number of pages which do not contain any live slots + # [total_allocated_pages] + # The cumulative number of pages allocated since application start + # [total_freed_pages] + # The cumulative number of pages freed since application start + # [total_allocated_objects] + # The cumulative number of objects allocated since application start + # [total_freed_objects] + # The cumulative number of objects freed since application start + # [malloc_increase_bytes] + # Amount of memory allocated on the heap for objects. Decreased by any GC + # [malloc_increase_bytes_limit] + # When `:malloc_increase_bytes` crosses this limit, GC is triggered + # [minor_gc_count] + # The total number of minor garbage collections run since process start + # [major_gc_count] + # The total number of major garbage collections run since process start + # [remembered_wb_unprotected_objects] + # The total number of objects without write barriers + # [remembered_wb_unprotected_objects_limit] + # When `:remembered_wb_unprotected_objects` crosses this limit, + # major GC is triggered + # [old_objects] + # Number of live, old objects which have survived at least 3 garbage collections + # [old_objects_limit] + # When `:old_objects` crosses this limit, major GC is triggered + # [oldmalloc_increase_bytes] + # Amount of memory allocated on the heap for objects. Decreased by major GC + # [oldmalloc_increase_bytes_limit] + # When `:old_malloc_increase_bytes` crosses this limit, major GC is triggered + # + # If the optional argument, hash, is given, + # it is overwritten and returned. + # This is intended to avoid probe effect. + # + # This method is only expected to work on CRuby. def self.stat hash_or_key = nil - __builtin_gc_stat hash_or_key + Primitive.gc_stat hash_or_key end # call-seq: @@ -151,18 +202,109 @@ def self.stat hash_or_key = nil # GC.latest_gc_info(:major_by) -> :malloc # # Returns information about the most recent garbage collection. + # + # If the optional argument, hash, is given, + # it is overwritten and returned. + # This is intended to avoid probe effect. def self.latest_gc_info hash_or_key = nil - __builtin_gc_latest_gc_info hash_or_key + Primitive.gc_latest_gc_info hash_or_key + end + + # call-seq: + # GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}} + # + # Returns information about object moved in the most recent GC compaction. + # + # The returned hash has two keys :considered and :moved. The hash for + # :considered lists the number of objects that were considered for movement + # by the compactor, and the :moved hash lists the number of objects that + # were actually moved. Some objects can't be moved (maybe they were pinned) + # so these numbers can be used to calculate compaction efficiency. + def self.latest_compact_info + Primitive.gc_compact_stats end + # call-seq: + # GC.compact + # + # This function compacts objects together in Ruby's heap. It eliminates + # unused space (or fragmentation) in the heap by moving objects in to that + # unused space. This function returns a hash which contains statistics about + # which objects were moved. See `GC.latest_gc_info` for details about + # compaction statistics. + # + # This method is implementation specific and not expected to be implemented + # in any implementation besides MRI. def self.compact - __builtin_rb_gc_compact + Primitive.gc_compact + end + + # call-seq: + # GC.verify_compaction_references(toward: nil, double_heap: false) -> hash + # + # Verify compaction reference consistency. + # + # This method is implementation specific. During compaction, objects that + # were moved are replaced with T_MOVED objects. No object should have a + # reference to a T_MOVED object after compaction. + # + # This function doubles the heap to ensure room to move all objects, + # compacts the heap to make sure everything moves, updates all references, + # then performs a full GC. If any object contains a reference to a T_MOVED + # object, that object should be pushed on the mark stack, and will + # make a SEGV. + def self.verify_compaction_references(toward: nil, double_heap: false) + Primitive.gc_verify_compaction_references(double_heap, toward == :empty) + end + + # call-seq: + # GC.using_rvargc? -> true or false + # + # Returns true if using experimental feature Variable Width Allocation, false + # otherwise. + def self.using_rvargc? # :nodoc: + GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] > 1 + end + + + # call-seq: + # GC.measure_total_time = true/false + # + # Enable to measure GC time. + # You can get the result with GC.stat(:time). + # Note that GC time measurement can cause some performance overhead. + def self.measure_total_time=(flag) + Primitive.cstmt! %{ + rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE; + return flag; + } + end + + # call-seq: + # GC.measure_total_time -> true/false + # + # Return measure_total_time flag (default: +true+). + # Note that measurement can affect the application performance. + def self.measure_total_time + Primitive.cexpr! %{ + RBOOL(rb_objspace.flags.measure_gc) + } + end + + # call-seq: + # GC.total_time -> int + # + # Return measured GC total time in nano seconds. + def self.total_time + Primitive.cexpr! %{ + ULL2NUM(rb_objspace.profile.total_time_ns) + } end end module ObjectSpace def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true - __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep + Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end module_function :garbage_collect diff --git a/ruby/gc.rbinc b/ruby/gc.rbinc index d893a077c..03df06db4 100644 --- a/ruby/gc.rbinc +++ b/ruby/gc.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with gc.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_gc(void) +void Init_builtin_gc(void) { // table definition static const struct rb_builtin_function gc_table[] = { diff --git a/ruby/gem_prelude.rb b/ruby/gem_prelude.rb index 1d0158d00..94ada316a 100644 --- a/ruby/gem_prelude.rb +++ b/ruby/gem_prelude.rb @@ -1,2 +1,19 @@ -require 'rubygems.rb' if defined?(Gem) -require 'did_you_mean' if defined?(DidYouMean) +begin + require 'rubygems' +rescue LoadError => e + raise unless e.path == 'rubygems' + + warn "`RubyGems' were not loaded." +end if defined?(Gem) + +begin + require 'error_highlight' +rescue LoadError + warn "`error_highlight' was not loaded." +end if defined?(ErrorHighlight) + +begin + require 'did_you_mean' +rescue LoadError + warn "`did_you_mean' was not loaded." +end if defined?(DidYouMean) diff --git a/ruby/gem_prelude.rbinc b/ruby/gem_prelude.rbinc deleted file mode 100644 index 20723847e..000000000 --- a/ruby/gem_prelude.rbinc +++ /dev/null @@ -1,23 +0,0 @@ -// -*- c -*- -// DO NOT MODIFY THIS FILE DIRECTLY. -// auto-generated file -// by ./tool/mk_builtin_loader.rb -// with gem_prelude.rb - -static void load_gem_prelude(void) -{ - // table definition - static const struct rb_builtin_function gem_prelude_table[] = { - RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0), - }; - - // arity_check -COMPILER_WARNING_PUSH -#if GCC_VERSION_SINCE(5, 1, 0) || __clang__ -COMPILER_WARNING_ERROR(-Wincompatible-pointer-types) -#endif -COMPILER_WARNING_POP - - // load - rb_load_with_builtin_functions("gem_prelude", gem_prelude_table); -} diff --git a/ruby/gems/bundled_gems b/ruby/gems/bundled_gems index ce2dd1bdb..9e37598e9 100644 --- a/ruby/gems/bundled_gems +++ b/ruby/gems/bundled_gems @@ -1,6 +1,16 @@ -minitest 5.13.0 https://github.com/seattlerb/minitest -net-telnet 0.2.0 https://github.com/ruby/net-telnet -power_assert 1.1.7 https://github.com/k-tsj/power_assert -rake 13.0.1 https://github.com/ruby/rake -test-unit 3.3.4 https://github.com/test-unit/test-unit -xmlrpc 0.3.0 https://github.com/ruby/xmlrpc +# gem-name version-to-bundle repository-url [optional-commit-hash-to-test-or-defaults-to-v-version] +minitest 5.15.0 https://github.com/seattlerb/minitest +power_assert 2.0.1 https://github.com/ruby/power_assert +rake 13.0.6 https://github.com/ruby/rake +test-unit 3.5.3 https://github.com/test-unit/test-unit 3.5.3 +rexml 3.2.5 https://github.com/ruby/rexml +rss 0.2.9 https://github.com/ruby/rss 0.2.9 +net-ftp 0.1.3 https://github.com/ruby/net-ftp +net-imap 0.2.3 https://github.com/ruby/net-imap +net-pop 0.1.1 https://github.com/ruby/net-pop +net-smtp 0.3.1 https://github.com/ruby/net-smtp +matrix 0.4.2 https://github.com/ruby/matrix +prime 0.1.2 https://github.com/ruby/prime +rbs 2.1.0 https://github.com/ruby/rbs +typeprof 0.21.2 https://github.com/ruby/typeprof +debug 1.4.0 https://github.com/ruby/debug diff --git a/ruby/gems/minitest-5.13.0.gem b/ruby/gems/minitest-5.13.0.gem deleted file mode 100644 index eaf1c8b74..000000000 Binary files a/ruby/gems/minitest-5.13.0.gem and /dev/null differ diff --git a/ruby/gems/minitest-5.13.0/.autotest b/ruby/gems/minitest-5.13.0/.autotest deleted file mode 100644 index b6fbce536..000000000 --- a/ruby/gems/minitest-5.13.0/.autotest +++ /dev/null @@ -1,34 +0,0 @@ -# -*- ruby -*- - -require 'autotest/restart' -require 'autotest/rcov' if ENV['RCOV'] - -Autotest.add_hook :initialize do |at| - at.testlib = 'minitest/autorun' - - bench_tests = %w(TestMinitestBenchmark) - mock_tests = %w(TestMinitestMock TestMinitestStub) - spec_tests = %w(TestMinitestReporter TestMetaStatic TestMeta - TestSpecInTestCase) - unit_tests = %w(TestMinitestGuard TestMinitestRunnable - TestMinitestRunner TestMinitestTest TestMinitestUnit - TestMinitestUnitInherited TestMinitestUnitOrder - TestMinitestUnitRecording TestMinitestUnitTestCase) - - { - bench_tests => "test/minitest/test_minitest_benchmark.rb", - mock_tests => "test/minitest/test_minitest_mock.rb", - spec_tests => "test/minitest/test_minitest_reporter.rb", - unit_tests => "test/minitest/test_minitest_unit.rb", - }.each do |klasses, file| - klasses.each do |klass| - at.extra_class_map[klass] = file - end - end - - at.add_exception 'coverage.info' - at.add_exception 'coverage' -end - -# require 'autotest/rcov' -# Autotest::RCov.command = 'rcov_info' diff --git a/ruby/gems/minitest-5.13.0/History.rdoc b/ruby/gems/minitest-5.13.0/History.rdoc deleted file mode 100644 index e11ed907e..000000000 --- a/ruby/gems/minitest-5.13.0/History.rdoc +++ /dev/null @@ -1,1367 +0,0 @@ -=== 5.13.0 / 2019-10-29 - -* 9 minor enhancements: - - * Added Minitest::Guard#osx? - * Added examples to documentation for assert_raises. (lxxxvi) - * Added expectations #path_must_exist and #path_wont_exist. Not thrilled with the names. - * Added fail_after(year, month, day, msg) to allow time-bombing after a deadline. - * Added skip_until(year, month, day, msg) to allow deferring until a deadline. - * Deprecated Minitest::Guard#maglev? - * Deprecated Minitest::Guard#rubinius? - * Finally added assert_path_exists and refute_path_exists. (deivid-rodriguez) - * Refactored and pulled Assertions#things_to_diff out of #diff. (BurdetteLamar) - -* 3 bug fixes: - - * Fix autorun bug that affects fork exit status in tests. (dylanahsmith/jhawthorn) - * Improved documentation for _/value/expect, especially for blocks. (svoop) - * Support new Proc#to_s format. (ko1) - -=== 5.12.2 / 2019-09-28 - -* 1 bug fix: - - * After chatting w/ @y-yagi and others, decided to lower support to include ruby 2.2. - -=== 5.12.1 / 2019-09-28 - -* 1 minor enhancement: - - * Added documentation for Reporter classes. (sshaw) - -* 3 bug fixes: - - * Avoid using 'match?' to support older ruby versions. (y-yagi) - * Fixed broken link to reference on goodness-of-fit testing. (havenwood) - * Update requirements in readme and Rakefile/hoe spec. - -=== 5.12.0 / 2019-09-22 - -* 8 minor enhancements: - - * Added a descriptive error if assert_output or assert_raises called without a block. (okuramasafumi) - * Changed mu_pp_for_diff to make having both \n and \\n easier to debug. - * Deprecated $N for specifying number of parallel test runners. Use MT_CPU. - * Deprecated use of global expectations. To be removed from MT6. - * Extended Assertions#mu_pp to encoding validity output for strings to improve diffs. - * Extended Assertions#mu_pp to output encoding and validity if invalid to improve diffs. - * Extended Assertions#mu_pp_for_diff to make escaped newlines more obvious in diffs. - * Fail gracefully when expectation used outside of `it`. - -* 3 bug fixes: - - * Check `option[:filter]` klass before match. Fixes 2.6 warning. (y-yagi) - * Fixed Assertions#diff from recalculating if set to nil - * Fixed spec section of readme to not use deprecated global expectations. (CheezItMan) - -=== 5.11.3 / 2018-01-26 - -* 1 bug fix: - - * Pushed #error? up to Reportable module. (composerinteralia) - -=== 5.11.2 / 2018-01-25 - -* 1 minor enhancement: - - * Reversed Test < Result. Back to < Runnable and using Reportable for shared code. - -* 2 bug fixes: - - * Fixed Result#location for instances of Test. (alexisbernard) - * Fixed deprecation message for Runnable#marshal_dump. (y-yagi) - -=== 5.11.1 / 2018-01-02 - -* 1 bug fix: - - * Fixed Result (a superclass of Test) overriding Runnable's name accessors. (y-yagi, MSP-Greg) - -=== 5.11.0 / 2018-01-01 - -* 2 major enhancements: - - * Added Minitest::Result and Minitest::Result.from(runnable). - * Changed Minitest::Test to subclass Result and refactored methods up. - -* 7 minor enhancements: - - * Added --no-plugins and MT_NO_PLUGINS to bypass MT plugin autoloading. Helps with bad actors installed globally. - * Added bench_performance_{logarithmic,power} for spec-style benchmarks. (rickhull) - * Added deprecation warning for Runnable#marshal_dump. - * Minitest.run_one_method now checks for instance of Result, not exact same class. - * Minitest::Test.run returns a Result version of self, not self. - * ProgressReporter#prerecord now explicitly prints klass.name. Allows for fakers. - -* 4 bug fixes: - - * Object.stub no longer calls the passed block if stubbed with a callable. - * Object.stub now passes blocks down to the callable result. - * Pushed Minitest::Test#time & #time_it up to Runnable. - * Test nil equality directly in assert_equal. Fixes #679. (voxik) - -=== 5.11.0b1 / 2017-12-20 - -* 2 major enhancements: - - * Added Minitest::Result and Minitest::Result.from(runnable). - * Changed Minitest::Test to subclass Result and refactored methods up. - -* 6 minor enhancements: - - * Added --no-plugins and MT_NO_PLUGINS to bypass MT plugin autoloading. Helps with bad actors installed globally. - * Added bench_performance_{logarithmic,power} for spec-style benchmarks. (rickhull) - * Minitest.run_one_method now checks for instance of Result, not exact same class. - * Minitest::Test.run returns a Result version of self, not self. - * ProgressReporter#prerecord now explicitly prints klass.name. Allows for fakers. - * Removed Runnable.marshal_dump/load. - -* 4 bug fixes: - - * Object.stub no longer calls the passed block if stubbed with a callable. - * Object.stub now passes blocks down to the callable result. - * Pushed Minitest::Test#time & #time_it up to Runnable. - * Test nil equality directly in assert_equal. Fixes #679. (voxik) - -=== 5.10.3 / 2017-07-21 - -* 1 minor enhancement: - - * Extended documentation for Mock#expect for multiple calls to mock object. (insti) - -* 2 bug fixes: - - * Finished off missing doco. - * Fixed verbose output on parallelize_me! classes. (chanks) - -=== 5.10.2 / 2017-05-09 - -* 1 minor enhancement: - - * Added suggestion in minitest/hell to install minitest/proveit. - -* 7 bug fixes: - - * Expand MT6 to Minitest 6. (xaviershay) - * Fixed location of assert_send deprecation. (rab) - * Fixed location of nil assert_equal deprecation to work with expectations. (jeremyevans) - * Fixed minitest/hell to use parallelize_me! (azul) - * Made deprecation use warn so -W0 will silence it. - * Workaround for rdoc nodoc generation bug that totally f'd up minitest doco. (Paxa) - * Write aggregated_results directly to the IO object to avoid mixed encoding errors. (tenderlove) - -=== 5.10.1 / 2016-12-01 - -* 1 bug fix: - - * Added a hack/kludge to deal with missing #prerecord on reporters that aren't properly subclassing AbstractReporter (I'm looking at you minitest-reporters) - -=== 5.10.0 / 2016-11-30 - -* 1 major enhancement: - - * Deprecated ruby 1.8, 1.9, possibly 2.0, assert_send, & old MiniTest namespace. - -* 3 minor enhancements: - - * Warn if assert_equal expects a nil. This will fail in minitest 6+. (tenderlove) - * Added AbstractReporter#prerecord and extended ProgressReporter and CompositeReporter to use it. - * Minor optimization: remove runnables with no runnable methods before run. - -* 3 bug fixes: - - * Fix assert_throw rescuing any NameError and ArgumentError. (waldyr) - * Clean up (most of the) last remaining vestiges of minitest/unit. - * 2.4: removed deprecation warnings when referring to Fixnum. - -=== 5.9.1 / 2016-09-25 - -* 2 bug fixes: - - * Re-release to refresh gem certificate signing. ugh. - * Fixed hoe/minitest to not augment load path if we're actually testing minitest. - -=== 5.9.0 / 2016-05-16 - -* 8 minor enhancements: - - * Added Minitest.info_signal accessors to customize signal for test run info. (nate) - * Added assert_mock to make it more clear that you're testing w/ them. - * Added negative filter by test name. (utilum) - * Added warning to README that 1.8 and 1.9 support will be dropped in minitest 6. - * Automatically activate minitest/hell if $MT_HELL is defined. - * Improved default error messages for assert and refute. (bhenderson) - * minitest/hell now tries to require minitest/proveit - * mu_pp for strings prints out non-standard encodings to improve assert_equal diffs. - -* 1 bug fix: - - * Removed Interrupt from PASSTHROUGH_EXCEPTIONS (already handled). (waldyr) - -=== 5.8.5 / 2016-09-25 - -* 2 bug fixes: - - * Re-release to refresh gem certificate signing. ugh. - * Fixed hoe/minitest to not augment load path if we're actually testing minitest. - -=== 5.8.4 / 2016-01-21 - -* 1 bug fix: - - * Allow Minitest::Assertion to pass through assert_raises so inner failures are dealt with first. - -=== 5.8.3 / 2015-11-17 - -* 1 minor enhancement: - - * Added extra note about mocks and threads to readme. (zamith) - -* 1 bug fix: - - * Fixed bug in Mock#verify. (pithub/zamith) - -=== 5.8.2 / 2015-10-26 - -* 1 bug fix: - - * Fixed using parallelize_me! and capture_io (or any locking io). (arlt/tenderlove) - -=== 5.8.1 / 2015-09-23 - -* 1 minor enhancement: - - * Refactor assert_raises to be cleaner and to pass SystemExit and SignalException. (bhenderson) - -=== 5.8.0 / 2015-08-06 - -* 2 minor enhancements: - - * Add optional delegation mechanism to extend object with a mock. (zamith) - * Return early if there are no filtered methods. (jeremyevans) - -* 1 bug fix: - - * Don't extend io with pride if io is not a tty. (toy) - -=== 5.7.0 / 2015-05-27 - -* 1 major enhancement: - - * assert_raises now matches subclasses of the expected exception types. (jeremyevans) - -* 3 minor enhancements: - - * Added :block type for minitest/spec's #infect_an_assertion. (jeremyevans) - * Inline verification error messages in minitest/mock for GC performance. (zamith) - * assert_raises defaults to RuntimeError if not specified. (jeremyevans) - -* 4 bug fixes: - - * Added 'class' to minitest/mock's overridden_methods list. (zamith) - * Added file/line to infect_an_assertion's class_eval call. (jeremyevans) - * Cleared UnexpectedError's mesg w/ generic string. - * Fixed non-proc-oriented expectations when used on proc target. (jeremyevans) - -=== 5.6.1 / 2015-04-27 - -* 2 bug fixes: - - * Added Minitest.clock_time and switched all Time.now to it. (tenderlove) - * Moved Minitest::Expectations#_ into Minitest::Spec::DSL. - -=== 5.6.0 / 2015-04-13 - -* 4 major enhancements: - - * Added Minitest::Expectation value monad. - * Added Minitest::Expectations#_ that returns an Expectation. Aliased to value. - * All expectations are added to Minitest::Expectation. - * At some point, the methods on Object will be deprecated and then removed. - -* 4 minor enhancements: - - * Added a note about bundle exec pitfall in ruby 2.2+. (searls) - * Lazily start the parallel executor. (tenderlove) - * Make mocks more debugger-friendly (edward) - * Print out the current test run on interrupt. (riffraff) - -* 3 bug fixes: - - * Fix failing test under Windows. (kimhmadsen) - * Record mocked calls before they happen so mocks can raise exceptions easier (tho I'm not a fan). (corecode) - * Tried to clarify mocks vs stubs terminology better. (kkirsche) - -=== 5.5.1 / 2015-01-09 - -* 1 bug fix: - - * Fixed doco problems. (zzak) - -=== 5.5.0 / 2014-12-12 // mri 2.2.0 (as a real gem) - -* 1 minor enhancement: - - * Allow seed to be given via ENV for rake test loader sadness: eg rake SEED=42. - -=== 5.4.3 / 2014-11-11 - -* 2 bug fixes: - - * Clarified requirements for ruby are now 1.8.7 or better. - * Force encode error output in case mal-encoded exception is raised. (jasonrclark) - -=== 5.4.2 / 2014-09-26 - -* 2 minor enhancements: - - * Extract teardown method list. - * Thanks to minitest-gcstats got a 5-10% speedup via reduced GC! - -=== 5.4.1 / 2014-08-28 - -* 1 bug fix: - - * Fixed specs hidden by nesting/ordering bug (blowmage/apotonick) - -=== 5.4.0 / 2014-07-07 - -* 2 minor enhancements: - - * Kernel#describe extended to splat additional_desc. - * Spec#spec_type extended to take a splat of additional items, passed to matcher procs. - -* 1 bug fix: - - * minitest/spec should require minitest/test, not minitest/unit. (doudou) - -=== 5.3.5 / 2014-06-17 - -* 1 minor enhancement: - - * Spit and polish (mostly spit). - -=== 5.3.4 / 2014-05-15 - -* 1 minor enhancement: - - * Test classes are randomized before running. (judofyr) - -=== 5.3.3 / 2014-04-14 - -* 1 bug fix: - - * Fixed using expectations w/ DSL in Test class w/o describe. (blowmage+others) - -=== 5.3.2 / 2014-04-02 - -* 1 bug fix: - - * Fixed doco on Assertions.assertions. (xaviershay) - -=== 5.3.1 / 2014-03-14 - -* 1 minor enhancement: - - * Modified verbage on bad 'let' names to be more helpful. (Archytaus) - -* 1 bug fix: - - * Fixed 2 cases still using MiniTest. (mikesea) - -=== 5.3.0 / 2014-02-25 - -* 1 minor enhancement: - - * Mocked methods can take a block to verify state. Seattle.rb 12 bday present from ernie! Thanks!! - -=== 5.2.3 / 2014-02-10 - -* 1 bug fix: - - * Fixed Spec#let check to allow overriding of other lets. (mvz) - -=== 5.2.2 / 2014-01-22 - -* 1 minor enhancement: - - * Spec#let raises ArgumentError if you override _any_ instance method (except subject). (rynr) - -* 1 bug fix: - - * Fixed up benchmark spec doco and added a test to demonstrate. (bhenderson) - -=== 5.2.1 / 2014-01-07 - -* 1 bug fix: - - * Properly deal with horrible mix of runtime load errors + other at_exit handlers. (dougo/chqr) - -=== 5.2.0 / 2013-12-13 - -* 1 minor enhancement: - - * Change expectations to allow calling most on procs (but not calling the proc). (bhenderson+others) - -=== 5.1.0 / 2013-12-05 - -* 1 minor enhancement: - - * Use a Queue for scheduling parallel tests. (tenderlove) - -* 1 bug fix: - - * Fixed misspelling in doco. (amatsuda) - -=== 5.0.8 / 2013-09-20 - -* 1 bug fix: - - * Fixed siginfo handler by rearranging reporters and fixing to_s. (tenderlove) - -=== 5.0.7 / 2013-09-05 - -* 2 minor enhancements: - - * Added clarification about the use of thread local variables in expectations. (jemc) - * Added extra message about skipped tests, if any. Disable globally with $MT_NO_SKIP_MSG. - -* 2 bug fixes: - - * Only require minitest, not minitest/autorun in pride_plugin. (judofyr) - * Require rubygems in load_plugins in case you're not using minitest/autorun. - -=== 5.0.6 / 2013-06-28 - -* 3 minor enhancements: - - * Allow stub to pass args to blocks. (swindsor) - * Improved warning message about minitest/autorun to address 1.9's minitest/autorun. - * Made minitest/test require minitest as needed. For lib writers. (erikh) - -* 1 bug fix: - - * Fixed missing require in minitest/test. (erikh) - -=== 4.7.5 / 2013-06-21 // mri 2.1.1 - -* 2 bug fixes: - - * Fix Spec#describe_stack to be thread local. - * Fix multithreaded test failures by defining Time local to mock test namespace - -=== 5.0.5 / 2013-06-20 - -* 6 bug fixes: - - * DOH! Fixed the rest of the new casing on Minitest. (splattael) - * Fixed typo on minitest/mock rdoc. (mrgilman/guiceolin) - * Make Spec::DSL.describe_stack thread local to avoid failing on my own tests. - * Make a fake Time.now local to the tests so they won't interfere with real reporter timings. - * Make everything mockable by wrapping all 'special' methods in a smarter wrapper. (bestie) - * Raise ArgumentError if let name starts with 'test'. (johnmaxwell) - -=== 5.0.4 / 2013-06-07 - -* 5 minor enhancements: - - * Added AbstractReporter, defining required Reporter API to quack properly. - * Added doco for writing reporters. - * Refactored Reporter into ProgressReporter and SummaryReporter. (idea: phiggins, code:me+scotch) - * Refactored SummaryReporter pushing up to StatisticsReporter. (phiggins) - * Removed Reporter#run_and_report... cleaner, but doesn't "fit" in the API. - -=== 5.0.3 / 2013-05-29 - -* 4 minor enhancements: - - * Added Runnable.with_info_handler and Runnable.on_signal. - * Moved io.sync restore to Reporter#run_and_report. - * Refactored inner loop of Reporter#report to #to_s. Callable for status updates. - * Restored MT4's mid-run report (^t). (tenderlove). - -=== 5.0.2 / 2013-05-20 - -* 3 bug fixes: - - * Gem.find_files is smarter than I remember... cause I wrote it that way. *sigh* I'm getting old. - * Pride wasn't doing puts through its #io. (tmiller/tenderlove) - * Replaced Runnable#dup and Test#dup with marshal_dump/load. Too many problems cropping up on untested rails code. (tenderlove/rubys) - -=== 5.0.1 / 2013-05-14 - -* 2 bug fixes: - - * Documented Assertions' need for @assertions to be defined by the includer. - * Only load one plugin version per name. Tries for latest. - -=== 5.0.0 / 2013-05-10 - -Oh god... here we go... - -Minitest 5: - -* 4 deaths in the family: - - * MiniTest.runner is dead. No more manager objects. - * MiniTest::Unit#record is dead. Use a Reporter instance instead. - * MiniTest::Unit._run_* is dead. Runnable things are responsible for their own runs. - * MiniTest::Unit.output is dead. No more centralized IO. - -* 12 major (oft incompatible) changes: - - * Renamed MiniTest to Minitest. Your pinkies will thank me. (aliased to MiniTest) - * Removed MiniTest::Unit entirely. No more manager objects. - * Added Minitest::Runnable. Everything minitest can run subclasses this. - * Renamed MiniTest::Unit::TestCase to Minitest::Test (subclassing Runnable). - * Added Minitest::Benchmark. - * Your benchmarks need to move to their own subclass. - * Benchmarks using the spec DSL have to have "Bench" somewhere in their describe. - * MiniTest::Unit.after_tests moved to Minitest.after_tests - * MiniTest::Unit.autorun is now Minitest.autorun. Just require minitest/autorun pls. - * Removed ParallelEach#grep since it isn't used anywhere. - * Renamed Runnable#__name__ to Runnable#name (but uses @NAME internally). - * Runnable#run needs to return self. Allows for swapping of results as needed. - -* 8 minor moves: - - * Moved Assertions module to minitest/assertions.rb - * Moved Expectations module to minitest/expectations.rb - * Moved Test to minitest/test.rb - * Moved everything else in minitest/unit.rb to minitest.rb - * minitest/unit.rb is now just a small (user-test only) compatibility layer. - * Moved most of minitest/pride into minitest/pride_plugin. - * minitest/pride now just activates pride. - * Moved ParallelEach under Minitest. - -* 9 additions: - - * Added a plugin system that can extend command-line options. - * Added Minitest.extensions. - * Added Minitest.reporter (only available during startup). - * Added Minitest.run(args). This is the very top of any Minitest run. - * Added Minitest::Reporter. Everything minitest can report goes through here. - * Minitest.reporter is a composite so you can add your own. - * Added Minitest::CompositeReporter. Much easier to extend with your own reporters. - * Added UnexpectedError, an Assertion subclass, to wrap up errors. - * Minitest::Test#run is now freakin' beautiful. 47 -> 17 loc - -* 11 other: - - * Removed Object.infect_with_assertions (it was already dead code). - * Runnables are responsible for knowing their result_code (eg "." or "F"). - * Minitest.autorun now returns boolean, not exit code. - * Added FAQ entry for extending via modules. (phiggins) - * Implement Runnable#dup to cleanse state back to test results. Helps with serialization. pair:tenderlove - * Moved ParallelEach under Minitest. - * Runnable#run needs to return self. Allows for swapping of results as needed. - * Minitest.init_plugins passes down options. - * Minitest.load_plugins only loads once. - * Fixed minitest/pride to work with rake test loader again. (tmiller) - * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb) - -* 5 voodoo: - - * Removed mutex from minitest.rb (phiggins) - * Removed mutex from test.rb (phiggins) - * Removed Minitest::Reporter.synchronize (phiggins) - * Removed Minitest::Test.synchronize (phiggins) - * Upon loading minitest/parallel_each, record, capture_io and capture_subprocess_io are doped with synchronization code. (phiggins) - -=== 4.7.4 / 2013-05-01 - -This is probably the last release of the 4.x series. It will be merged -to ruby and will be put into maintenance mode there. - -I'm not set in stone on this, but at this point further development of -minitest (5+) will be gem-only. It is just too hard to work w/in -ruby-core w/ test-unit compatibility holding minitest development -back. - -* 2 minor enhancements: - - * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb) - * Allow disabling of info_signal handler in runner. (erikh) - -=== 4.7.3 / 2013-04-20 - -* 1 bug fix: - - * Reverted stubbing of module methods change. Stub the user, not the impl. (ab9/tyabe) - -=== 4.7.2 / 2013-04-18 - -* 2 bug fixes: - - * Fixed inconsistency in refute_in_delta/epsilon. I double negatived my logic. (nettsundere) - * Fixed stubbing of module methods (eg Kernel#sleep). (steveklabnik) - -=== 4.7.1 / 2013-04-09 - -* 1 minor enhancement: - - * Added FAQ section to README - -* 1 bug fix: - - * Fixed bug where guard runs tests bypassing minitest/autorun and an ivar isn't set right. (darrencauthon) - -=== 4.7.0 / 2013-03-18 - -* 1 major enhancement: - - * Refactored MiniTest::Spec into MiniTest::Spec::DSL. - -* 1 bug fix: - - * Removed $DEBUG handler that detected when test/unit and minitest were both loaded. (tenderlove) - -=== 4.6.2 / 2013-02-27 - -* 1 minor enhancement: - - * Change error output to match Class#method, making it easier to use -n filter. - -=== 4.6.1 / 2013-02-14 - -* 1 bug fix: - - * Fixed an option processing bug caused by test/unit's irresponsibly convoluted code. (floehopper) - -=== 4.6.0 / 2013-02-07 - -* 3 major enhancements: - - * Removed ::reset_setup_teardown_hooks - * Removed the long deprecated assert_block - * Removed the long deprecated lifecycle hooks: add_(setup|teardown)_hook - -* 1 minor enhancement: - - * Allow filtering tests by suite name as well as test name. (lazyatom) - -* 2 bug fixes: - - * Made hex handling (eg object_ids) in mu_pp_for_diff more specific. (maxim) - * nodoc top-level module. (zzak) - -=== 4.5.0 / 2013-01-22 - -* 1 major enhancement: - - * Rearranged minitest/unit.rb so NO parallelization code is loaded/used until you opt-in. - -* 4 minor enhancements: - - * Added TestCase#skipped? for teardown guards - * Added maglev? guard - * Document that record can be sent twice if teardown fails or errors (randycoulman) - * Errors in teardown are now recorded. (randycoulman) - -* 3 bug fixes: - - * Added hacks and skips to get clean test runs on maglev - * Modified float tests for maglev float output differences. Not sure this is right. Not sure I care. - * Test for existance of diff.exe instead of assuming they have devkit. (blowmage/Cumbayah) - -=== 4.4.0 / 2013-01-07 - -* 3 minor enhancements: - - * Added fit_logarithic and assert_performance_logarithmic. (ktheory) - * Merge processed options so others can mess with defaults. (tenderlove) - * TestCase#message can now take another proc to defer custom message cost. (ordinaryzelig/bhenderson) - -* 1 bug fix: - - * TestCase#passed? now true if test is skipped. (qanhd) - -=== 4.3.3 / 2012-12-06 - -* 1 bug fix: - - * Updated information about stubbing. (daviddavis) - -=== 4.3.2 / 2012-11-27 // mri 2.0.0 - -* 1 minor enhancement: - - * Improved assert_equals error message to point you at #== of member objects. (kcurtin) - -=== 4.3.1 / 2012-11-23 - -* 1 bug fix: - - * Moved test_children to serial testcase to prevent random failures. - -=== 4.3.0 / 2012-11-17 - -* 4 minor enhancements: - - * Allow #autorun to run even if loaded with other test libs that call exit. (sunaku) - * Do not include Expectations in Object if $MT_NO_EXPECTATIONS is set (experimental?) - * Gave some much needed love to assert_raises. - * Mock#expect can take a block to custom-validate args. (gmoothart) - -=== 4.2.0 / 2012-11-02 - -* 4 major enhancements: - - * Added minitest/hell - run all your tests through the ringer! - * Added support for :parallel test_order to run test cases in parallel. - * Removed last_error and refactored runner code to be threadsafe. - * _run_suites now runs suites in parallel if they opt-in. - -* 4 minor enhancements: - - * Added TestCase#synchronize - * Added TestCase.make_my_diffs_pretty! - * Added TestCase.parallelize_me! - * Lock on capture_io for thread safety (tenderlove) - -=== 4.1.0 / 2012-10-05 - -* 2 minor enhancements: - - * Added skip example to readme. (dissolved) - * Extracted backtrace filter to object. (tenderlove) - -* 1 bug fix: - - * OMG I'm so dumb. Fixed access to deprecated hook class methods. I hate ruby modules. (route) - -=== 4.0.0 / 2012-09-28 - -* 1 major enhancement: - - * The names of a privately-used undocumented constants are Super Importantâ„¢. - -* 1 minor enhancement: - - * Support stubbing methods that would be handled via method_missing. (jhsu) - -* 3 bug fixes: - - * Add include_private param to MiniTest::Mock#respond_to? (rf-) - * Fixed use of minitest/pride with --help. (zw963) - * Made 'No visible difference.' message more clear. (ckrailo) - -=== 3.5.0 / 2012-09-21 - -* 1 minor enhancement: - - * Added #capture_subprocess_io. (route) - -=== 3.4.0 / 2012-09-05 - -* 2 minor enhancements: - - * assert_output can now take regexps for expected values. (suggested by stomar) - * Clarified that ruby 1.9/2.0's phony gems cause serious confusion for rubygems. - -=== 3.3.0 / 2012-07-26 - -* 1 major enhancement: - - * Deprecated add_(setup|teardown)_hook in favor of (before|after)_(setup|teardown) [2013-01-01] - -* 4 minor enhancements: - - * Refactored deprecated hook system into a module. - * Refactored lifecycle hooks into a module. - * Removed after_setup/before_teardown + run_X_hooks from Spec. - * Spec#before/after now do a simple define_method and call super. DUR. - -* 2 bug fixes: - - * Fixed #passed? when used against a test that called flunk. (floehopper) - * Fixed rdoc bug preventing doco for some expectations. (stomar). - -=== 3.2.0 / 2012-06-26 - -* 1 minor enhancement: - - * Stubs now yield self. (peterhellberg) - -* 1 bug fix: - - * Fixed verbose test that only fails when run in verbose mode. mmmm irony. - -=== 3.1.0 / 2012-06-13 - -* 2 minor enhancements: - - * Removed LONG deprecated Unit.out accessor - * Removed generated method name munging from minitest/spec. (ordinaryzelig/tenderlove) - -=== 3.0.1 / 2012-05-24 - -* 1 bug fix: - - * I'm a dumbass and refactored into Mock#call. Renamed to #__call so you can mock #call. (mschuerig) - -=== 3.0.0 / 2012-05-08 - -* 3 major enhancements: - - * Added Object#stub (in minitest/mock.rb). - * Mock#expect mocks are used in the order they're given. - * Mock#verify now strictly compares against expect calls. - -* 3 minor enhancements: - - * Added caller to deprecation message. - * Mock error messages are much prettier. - * Removed String check for RHS of assert/refute_match. This lets #to_str work properly. - -* 1 bug fix: - - * Support drive letter on Windows. Patch provided from MRI by Usaku NAKAMURA. (ayumin) - -=== 2.12.1 / 2012-04-10 - -* 1 minor enhancement: - - * Added ruby releases to History.txt to make it easier to see what you're missing - -* 1 bug fix: - - * Rolled my own deprecate msg to allow MT to work with rubygems < 1.7 - -=== 2.12.0 / 2012-04-03 - -* 4 minor enhancements: - - * ::it returns test method name (wojtekmach) - * Added #record method to runner so runner subclasses can cleanly gather data. - * Added Minitest alias for MiniTest because even I forget. - * Deprecated assert_block!! Yay!!! - -* 1 bug fix: - - * Fixed warning in i_suck_and_my_tests_are_order_dependent! (phiggins) - -=== 2.11.4 / 2012-03-20 - -* 2 minor enhancements: - - * Updated known extensions - * You got your unicode in my tests! You got your tests in my unicode! (fl00r) - -* 1 bug fix: - - * Fixed MiniTest::Mock example in the readme. (conradwt) - -=== 2.11.3 / 2012-02-29 - -* 2 bug fixes: - - * Clarified that assert_raises returns the exception for further testing - * Fixed assert_in_epsilon when both args are negative. (tamc) - -=== 2.11.2 / 2012-02-14 - -* 1 minor enhancement: - - * Display failures/errors on SIGINFO. (tenderlove) - -* 1 bug fix: - - * Fixed MiniTest::Unit.after_tests for Ruby 1.9.3. (ysbaddaden) - -=== 2.11.1 / 2012-02-01 - -* 3 bug fixes: - - * Improved description for --name argument. (drd) - * Ensure Mock#expect's expected args is an Array. (mperham) - * Ensure Mock#verify verifies multiple expects of the same method. (chastell) - -=== 2.11.0 / 2012-01-25 - -* 2 minor enhancements: - - * Added before / after hooks for setup and teardown. (tenderlove) - * Pushed run_setup_hooks down to Spec. (tenderlove) - -=== 2.10.1 / 2012-01-17 - -* 1 bug fix: - - * Fixed stupid 1.9 path handling grumble grumble. (graaff) - -=== 2.10.0 / 2011-12-20 - -* 3 minor enhancements: - - * Added specs for must/wont be_empty/respond_to/be_kind_of and others. - * Added tests for assert/refute predicate. - * Split minitest/excludes.rb out to its own gem. - -* 1 bug fix: - - * Fixed must_be_empty and wont_be_empty argument handling. (mrsimo) - -=== 2.9.1 / 2011-12-13 - -* 4 minor enhancements: - - * Added a ton of tests on spec error message output. - * Cleaned up consistency of msg handling on unary expectations. - * Improved error messages on assert/refute_in_delta. - * infect_an_assertion no longer checks arity and better handles args. - -* 1 bug fix: - - * Fixed error message on specs when 2+ args and custom message provided. (chastell) - -=== 2.9.0 / 2011-12-07 - -* 4 minor enhancements: - - * Added TestCase.exclude and load_excludes for programmatic filtering of tests. - * Added guard methods so you can cleanly skip based on platform/impl - * Holy crap! 100% doco! `rdoc -C` ftw - * Switch assert_output to test stderr before stdout to possibly improve debugging - -=== 2.8.1 / 2011-11-17 - -* 1 bug fix: - - * Ugh. 1.9's test/unit violates my internals. Added const_missing. - -=== 2.8.0 / 2011-11-08 - -* 2 minor enhancements: - - * Add a method so that code can be run around a particular test case (tenderlove) - * Turn off backtrace filtering if we're running inside a ruby checkout. (drbrain) - -* 2 bug fixes: - - * Fixed 2 typos and 2 doc glitches. (splattael) - * Remove unused block arguments to avoid creating Proc objects. (k-tsj) - -=== 2.7.0 / 2011-10-25 - -* 2 minor enhancements: - - * Include failed values in the expected arg output in MockExpectationError. (nono) - * Make minitest/pride work with other 256 color capable terms. (sunaku) - -* 2 bug fixes: - - * Clarified the documentation of minitest/benchmark (eregon) - * Fixed using expectations in regular unit tests. (sunaku) - -=== 2.6.2 / 2011-10-19 - -* 1 minor enhancement: - - * Added link to vim bundle. (sunaku) - -* 2 bug fixes: - - * Force gem activation in hoe minitest plugin - * Support RUBY_VERSION='2.0.0' (nagachika) - -=== 2.6.1 / 2011-09-27 - -* 2 bug fixes: - - * Alias Spec.name from Spec.to_s so it works when @name is nil (nathany) - * Fixed assert and refute_operator where second object has a bad == method. - -=== 2.6.0 / 2011-09-13 - -* 2 minor enhancements: - - * Added specify alias for it and made desc optional. - * Spec#must_be and #wont_be can be used with predicates (metaskills) - -* 1 bug fix: - - * Fixed Mock.respond_to?(var) to work with strings. (holli) - -=== 2.5.1 / 2011-08-27 // ruby 1.9.3: p0, p125, p34579 - -* 2 minor enhancements: - - * Added gem activation for minitest in minitest/autoload to help out 1.9 users - * Extended Spec.register_spec_type to allow for procs instead of just regexps. - -=== 2.5.0 / 2011-08-18 - -* 4 minor enhancements: - - * Added 2 more arguments against rspec: let & subject in 9 loc! (emmanuel/luis) - * Added TestCase.i_suck_and_my_tests_are_order_dependent! - * Extended describe to take an optional method name (2 line change!). (emmanuel) - * Refactored and extended minitest/pride to do full 256 color support. (lolcat) - -* 1 bug fix: - - * Doc fixes. (chastell) - -=== 2.4.0 / 2011-08-09 - -* 4 minor enhancements: - - * Added simple examples for all expectations. - * Improved Mock error output when args mismatch. - * Moved all expectations from Object to MiniTest::Expectations. - * infect_with_assertions has been removed due to excessive clever - -* 4 bug fixes: - - * Fix Assertions#mu_pp to deal with immutable encoded strings. (ferrous26) - * Fix minitest/pride for MacRuby (ferrous26) - * Made error output less fancy so it is more readable - * Mock shouldn't undef === and inspect. (dgraham) - -=== 2.3.1 / 2011-06-22 - -* 1 bug fix: - - * Fixed minitest hoe plugin to be a spermy dep and not depend on itself. - -=== 2.3.0 / 2011-06-15 - -* 5 minor enhancements: - - * Add setup and teardown hooks to MiniTest::TestCase. (phiggins) - * Added nicer error messages for MiniTest::Mock. (phiggins) - * Allow for less specific expected arguments in Mock. (bhenderson/phiggins) - * Made MiniTest::Mock a blank slate. (phiggins) - * Refactored minitest/spec to use the hooks instead of define_inheritable_method. (phiggins) - -* 2 bug fixes: - - * Fixed TestCase's inherited hook. (dchelimsky/phiggins/jamis, the 'good' neighbor) - * MiniTest::Assertions#refute_empty should use mu_pp in the default message. (whatthejeff) - -=== 2.2.2 / 2011-06-01 - -* 2 bug fixes: - - * Got rid of the trailing period in message for assert_equal. (tenderlove) - * Windows needs more flushing. (Akio Tajima) - -=== 2.2.1 / 2011-05-31 - -* 1 bug fix: - - * My _ONE_ non-rubygems-using minitest user goes to Seattle.rb! - -=== 2.2.0 / 2011-05-29 - -* 6 minor enhancements: - - * assert_equal (and must_equal) now tries to diff output where it makes sense. - * Added Assertions#diff(exp, act) to be used by assert_equal. - * Added Assertions#mu_pp_for_diff - * Added Assertions.diff and diff= - * Moved minitest hoe-plugin from hoe-seattlerb. (erikh) - * Skipped tests only output details in verbose mode. (tenderlove+zenspider=xoxo) - -=== 2.1.0 / 2011-04-11 - -* 5 minor enhancements: - - * Added MiniTest::Spec.register_spec_type(matcher, klass) and spec_type(desc) - * Added ability for specs to share code via subclassing of Spec. (metaskills) - * Clarified (or tried to) bench_performance_linear's use of threshold. - * MiniTest::Unit.runner=(runner) provides an easy way of creating custom test runners for specialized needs. (justinweiss) - * Reverse order of inheritance in teardowns of specs. (deepfryed) - -* 3 bug fixes: - - * FINALLY fixed problems of inheriting specs in describe/it/describe scenario. (MGPalmer) - * Fixed a new warning in 1.9.3. - * Fixed assert_block's message handling. (nobu) - -=== 2.0.2 / 2010-12-24 - -* 1 minor enhancement: - - * Completed doco on minitest/benchmark for specs. - -* 1 bug fix: - - * Benchmarks in specs that didn't call bench_range would die. (zzak). - -=== 2.0.1 / 2010-12-15 - -* 4 minor enhancements: - - * Do not filter backtrace if $DEBUG - * Exit autorun via nested at_exit handler, in case other libs call exit - * Make options accesor lazy. - * Split printing of test name and its time. (nurse) - -* 1 bug fix: - - * Fix bug when ^T is hit before runner start - -=== 2.0.0 / 2010-11-11 - -* 3 major enhancements: - - * Added minitest/benchmark! Assert your performance! YAY! - * Refactored runner to allow for more extensibility. See minitest/benchmark. - * This makes the runner backwards incompatible in some ways! - -* 9 minor enhancements: - - * Added MiniTest::Unit.after_tests { ... } - * Improved output by adding test rates and a more sortable verbose format - * Improved readme based on feedback from others - * Added io method to TestCase. If used, it'll supplant '.EF' output. - * Refactored IO in MiniTest::Unit. - * Refactored _run_anything to _run_suite to make it easier to wrap (ngauthier) - * Spec class names are now the unmunged descriptions (btakita) - * YAY for not having redundant rdoc/readmes! - * Help output is now generated from the flags you passed straight up. - -* 4 bug fixes: - - * Fixed scoping issue on minitest/mock (srbaker/prosperity) - * Fixed some of the assertion default messages - * Fixes autorun when on windows with ruby install on different drive (larsch) - * Fixed rdoc output bug in spec.rb - -=== 1.7.2 / 2010-09-23 - -* 3 bug fixes: - - * Fixed doco for expectations and Spec. - * Fixed test_capture_io on 1.9.3+ (sora_h) - * assert_raises now lets MiniTest::Skip through. (shyouhei) - -=== 1.7.1 / 2010-09-01 - -* 1 bug fix: - - * 1.9.2 fixes for spec tests - -=== 1.7.0 / 2010-07-15 - -* 5 minor enhancements: - - * Added assert_output (mapped to must_output). - * Added assert_silent (mapped to must_be_silent). - * Added examples to readme (Mike Dalessio) - * Added options output at the top of the run, for fatal run debugging (tenderlove) - * Spec's describe method returns created class - -=== 1.6.0 / 2010-03-27 // ruby 1.9.2-p290 - -* 10 minor enhancements: - - * Added --seed argument so you can reproduce a random order for debugging. - * Added documentation for assertions - * Added more rdoc and tons of :nodoc: - * Added output to give you all the options you need to reproduce that run. - * Added proper argument parsing to minitest. - * Added unique serial # to spec names so order can be preserved (needs tests). (phrogz) - * Empty 'it' fails with default msg. (phrogz) - * Remove previous method on expect to remove 1.9 warnings - * Spec#it is now order-proof wrt subclasses/nested describes. - * assert_same error message now reports in decimal, eg: oid=123. (mattkent) - -* 2 bug fixes: - - * Fixed message on refute_same to be consistent with assert_same. - * Fixed method randomization to be stable for testing. - -=== 1.5.0 / 2010-01-06 - -* 4 minor enhancements: - - * Added ability to specify what assertions should have their args flipped. - * Don't flip arguments on *include and *respond_to assertions. - * Refactored Module.infect_an_assertion from Module.infect_with_assertions. - * before/after :all now bitches and acts like :each - -* 3 bug fixes: - - * Nested describes now map to nested test classes to avoid namespace collision. - * Using undef_method instead of remove_method to clean out inherited specs. - * assert_raises was ignoring passed in message. - -=== 1.4.2 / 2009-06-25 - -* 1 bug fix: - - * Fixed info handler for systems that don't have siginfo. - -=== 1.4.1 / 2009-06-23 - -* 1 major enhancement: - - * Handle ^C and other fatal exceptions by failing - -* 1 minor enhancement: - - * Added something to catch mixed use of test/unit and minitest if $DEBUG - -* 1 bug fix: - - * Added SIGINFO handler for finding slow tests without verbose - -=== 1.4.0 / 2009-06-18 - -* 5 minor enhancement: - - * Added clarification doco. - * Added specs and mocks to autorun. - * Changed spec test class creation to be non-destructive. - * Updated rakefile for new hoe capabilities. - * describes are nestable (via subclass). before/after/def inherits, specs don't. - -* 3 bug fixes: - - * Fixed location on must/wont. - * Switched to __name__ to avoid common ivar name. - * Fixed indentation in test file (1.9). - -=== 1.3.1 / 2009-01-20 // ruby 1.9.1-p431 - -* 1 minor enhancement: - - * Added miniunit/autorun.rb as replacement for test/unit.rb's autorun. - -* 16 bug fixes: - - * 1.9 test fixes. - * Bug fixes from nobu and akira for really odd scenarios. They run ruby funny. - * Fixed (assert|refute)_match's argument order. - * Fixed LocalJumpError in autorun if exception thrown before at_exit. - * Fixed assert_in_delta (should be >=, not >). - * Fixed assert_raises to match Modules. - * Fixed capture_io to not dup IOs. - * Fixed indentation of capture_io for ruby 1.9 warning. - * Fixed location to deal better with custom assertions and load paths. (Yuki) - * Fixed order of (must|wont)_include in MiniTest::Spec. - * Fixed skip's backtrace. - * Got arg order wrong in *_match in tests, message wrong as a result. - * Made describe private. For some reason I thought that an attribute of Kernel. - * Removed disable_autorun method, added autorun.rb instead. - * assert_match escapes if passed string for pattern. - * instance_of? is different from ===, use instance_of. - -=== 1.3.0 / 2008-10-09 - -* 2 major enhancements: - - * renamed to minitest and pulled out test/unit compatibility. - * mini/test.rb is now minitest/unit.rb, everything else maps directly. - -* 12 minor enhancements: - - * assert_match now checks that act can call =~ and converts exp to a - regexp only if needed. - * Added assert_send... seems useless to me tho. - * message now forces to string... ruby-core likes to pass classes and arrays :( - * Added -v handling and switched to @verbose from $DEBUG. - * Verbose output now includes test class name and adds a sortable running time! - * Switched message generation into procs for message deferment. - * Added skip and renamed fail to flunk. - * Improved output failure messages for assert_instance_of, assert_kind_of - * Improved output for assert_respond_to, assert_same. - * at_exit now exits false instead of errors+failures. - * Made the tests happier and more readable imhfo. - * Switched index(s) == 0 to rindex(s, 0) on nobu's suggestion. Faster. - -* 5 bug fixes: - - * 1.9: Added encoding normalization in mu_pp. - * 1.9: Fixed backtrace filtering (BTs are expanded now) - * Added back exception_details to assert_raises. DOH. - * Fixed shadowed variable in mock.rb - * Fixed stupid muscle memory message bug in assert_send. - -=== 1.2.1 / 2008-06-10 - -* 7 minor enhancements: - - * Added deprecations everywhere in test/unit. - * Added test_order to TestCase. :random on mini, :sorted on test/unit (for now). - * Big cleanup in test/unit for rails. Thanks Jeremy Kemper! - * Minor readability cleanup. - * Pushed setup/run/teardown down to testcase allowing specialized testcases. - * Removed pp. Tests run 2x faster. :/ - * Renamed deprecation methods and moved to test/unit/deprecate.rb. - -=== 1.2.0 / 2008-06-09 - -* 2 major enhancements: - - * Added Mini::Spec. - * Added Mini::Mock. Thanks Steven Baker!! - -* 23 minor enhancements: - - * Added bin/use_miniunit to make it easy to test out miniunit. - * Added -n filtering, thanks to Phil Hagelberg! - * Added args argument to #run, takes ARGV from at_exit. - * Added test name output if $DEBUG. - * Added a refute (was deny) for every assert. - * Added capture_io and a bunch of nice assertions from zentest. - * Added deprecation mechanism for assert_no/not methods to test/unit/assertions. - * Added pp output when available. - * Added tests for all assertions. Pretty much maxed out coverage. - * Added tests to verify consistency and good naming. - * Aliased and deprecated all ugly assertions. - * Cleaned out test/unit. Moved autorun there. - * Code cleanup to make extensions easier. Thanks Chad! - * Got spec args reversed in all but a couple assertions. Much more readable. - * Improved error messages across the board. Adds your message to the default. - * Moved into Mini namespace, renamed to Mini::Test and Mini::Spec. - * Pulled the assertions into their own module... - * Removed as much code as I could while still maintaining full functionality. - * Moved filter_backtrace into MiniTest. - * Removed MiniTest::Unit::run. Unnecessary. - * Removed location_of_failure. Unnecessary. - * Rewrote test/unit's filter_backtrace. Flog from 37.0 to 18.1 - * Removed assert_send. Google says it is never used. - * Renamed MiniTest::Unit.autotest to #run. - * Renamed deny to refute. - * Rewrote some ugly/confusing default assertion messages. - * assert_in_delta now defaults to 0.001 precision. Makes specs prettier. - -* 9 bug fixes: - - * Fixed assert_raises to raise outside of the inner-begin/rescue. - * Fixed for ruby 1.9 and rubinius. - * No longer exits 0 if exception in code PRE-test run causes early exit. - * Removed implementors method list from mini/test.rb - too stale. - * assert_nothing_raised takes a class as an arg. wtf? STUPID - * ".EF" output is now unbuffered. - * Bunch of changes to get working with rails... UGH. - * Added stupid hacks to deal with rails not requiring their dependencies. - * Now bitch loudly if someone defines one of my classes instead of requiring. - * Fixed infect method to work better on 1.9. - * Fixed all shadowed variable warnings in 1.9. - -=== 1.1.0 / 2007-11-08 - -* 4 major enhancements: - - * Finished writing all missing assertions. - * Output matches original test/unit. - * Documented every method needed by language implementor. - * Fully switched over to self-testing setup. - -* 2 minor enhancements: - - * Added deny (assert ! test), our favorite extension to test/unit. - * Added .autotest and fairly complete unit tests. (thanks Chad for help here) - -=== 1.0.0 / 2006-10-30 - -* 1 major enhancement - - * Birthday! - diff --git a/ruby/gems/minitest-5.13.0/Manifest.txt b/ruby/gems/minitest-5.13.0/Manifest.txt deleted file mode 100644 index 8e096ff4d..000000000 --- a/ruby/gems/minitest-5.13.0/Manifest.txt +++ /dev/null @@ -1,27 +0,0 @@ -.autotest -History.rdoc -Manifest.txt -README.rdoc -Rakefile -design_rationale.rb -lib/hoe/minitest.rb -lib/minitest.rb -lib/minitest/assertions.rb -lib/minitest/autorun.rb -lib/minitest/benchmark.rb -lib/minitest/expectations.rb -lib/minitest/hell.rb -lib/minitest/mock.rb -lib/minitest/parallel.rb -lib/minitest/pride.rb -lib/minitest/pride_plugin.rb -lib/minitest/spec.rb -lib/minitest/test.rb -lib/minitest/unit.rb -test/minitest/metametameta.rb -test/minitest/test_minitest_assertions.rb -test/minitest/test_minitest_benchmark.rb -test/minitest/test_minitest_mock.rb -test/minitest/test_minitest_reporter.rb -test/minitest/test_minitest_spec.rb -test/minitest/test_minitest_test.rb diff --git a/ruby/gems/minitest-5.13.0/README.rdoc b/ruby/gems/minitest-5.13.0/README.rdoc deleted file mode 100644 index 07feac0ee..000000000 --- a/ruby/gems/minitest-5.13.0/README.rdoc +++ /dev/null @@ -1,763 +0,0 @@ -= minitest/{test,spec,mock,benchmark} - -home :: https://github.com/seattlerb/minitest -bugs :: https://github.com/seattlerb/minitest/issues -rdoc :: http://docs.seattlerb.org/minitest -vim :: https://github.com/sunaku/vim-ruby-minitest -emacs:: https://github.com/arthurnn/minitest-emacs - -== DESCRIPTION: - -minitest provides a complete suite of testing facilities supporting -TDD, BDD, mocking, and benchmarking. - - "I had a class with Jim Weirich on testing last week and we were - allowed to choose our testing frameworks. Kirk Haines and I were - paired up and we cracked open the code for a few test - frameworks... - - I MUST say that minitest is *very* readable / understandable - compared to the 'other two' options we looked at. Nicely done and - thank you for helping us keep our mental sanity." - - -- Wayne E. Seguin - -minitest/test is a small and incredibly fast unit testing framework. -It provides a rich set of assertions to make your tests clean and -readable. - -minitest/spec is a functionally complete spec engine. It hooks onto -minitest/test and seamlessly bridges test assertions over to spec -expectations. - -minitest/benchmark is an awesome way to assert the performance of your -algorithms in a repeatable manner. Now you can assert that your newb -co-worker doesn't replace your linear algorithm with an exponential -one! - -minitest/mock by Steven Baker, is a beautifully tiny mock (and stub) -object framework. - -minitest/pride shows pride in testing and adds coloring to your test -output. I guess it is an example of how to write IO pipes too. :P - -minitest/test is meant to have a clean implementation for language -implementors that need a minimal set of methods to bootstrap a working -test suite. For example, there is no magic involved for test-case -discovery. - - "Again, I can't praise enough the idea of a testing/specing - framework that I can actually read in full in one sitting!" - - -- Piotr Szotkowski - -Comparing to rspec: - - rspec is a testing DSL. minitest is ruby. - - -- Adam Hawkins, "Bow Before MiniTest" - -minitest doesn't reinvent anything that ruby already provides, like: -classes, modules, inheritance, methods. This means you only have to -learn ruby to use minitest and all of your regular OO practices like -extract-method refactorings still apply. - -== FEATURES/PROBLEMS: - -* minitest/autorun - the easy and explicit way to run all your tests. -* minitest/test - a very fast, simple, and clean test system. -* minitest/spec - a very fast, simple, and clean spec system. -* minitest/mock - a simple and clean mock/stub system. -* minitest/benchmark - an awesome way to assert your algorithm's performance. -* minitest/pride - show your pride in testing! -* Incredibly small and fast runner, but no bells and whistles. -* Written by squishy human beings. Software can never be perfect. We will all eventually die. - -== RATIONALE: - -See design_rationale.rb to see how specs and tests work in minitest. - -== SYNOPSIS: - -Given that you'd like to test the following class: - - class Meme - def i_can_has_cheezburger? - "OHAI!" - end - - def will_it_blend? - "YES!" - end - end - -=== Unit tests - -Define your tests as methods beginning with +test_+. - - require "minitest/autorun" - - class TestMeme < Minitest::Test - def setup - @meme = Meme.new - end - - def test_that_kitty_can_eat - assert_equal "OHAI!", @meme.i_can_has_cheezburger? - end - - def test_that_it_will_not_blend - refute_match /^no/i, @meme.will_it_blend? - end - - def test_that_will_be_skipped - skip "test this later" - end - end - -=== Specs - - require "minitest/autorun" - - describe Meme do - before do - @meme = Meme.new - end - - describe "when asked about cheeseburgers" do - it "must respond positively" do - _(@meme.i_can_has_cheezburger?).must_equal "OHAI!" - end - end - - describe "when asked about blending possibilities" do - it "won't say no" do - _(@meme.will_it_blend?).wont_match /^no/i - end - end - end - -For matchers support check out: - -* https://github.com/wojtekmach/minitest-matchers -* https://github.com/rmm5t/minitest-matchers_vaccine - -=== Benchmarks - -Add benchmarks to your tests. - - # optionally run benchmarks, good for CI-only work! - require "minitest/benchmark" if ENV["BENCH"] - - class TestMeme < Minitest::Benchmark - # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000] - def bench_my_algorithm - assert_performance_linear 0.9999 do |n| # n is a range value - @obj.my_algorithm(n) - end - end - end - -Or add them to your specs. If you make benchmarks optional, you'll -need to wrap your benchmarks in a conditional since the methods won't -be defined. In minitest 5, the describe name needs to match -/Bench(mark)?$/. - - describe "Meme Benchmark" do - if ENV["BENCH"] then - bench_performance_linear "my_algorithm", 0.9999 do |n| - 100.times do - @obj.my_algorithm(n) - end - end - end - end - -outputs something like: - - # Running benchmarks: - - TestBlah 100 1000 10000 - bench_my_algorithm 0.006167 0.079279 0.786993 - bench_other_algorithm 0.061679 0.792797 7.869932 - -Output is tab-delimited to make it easy to paste into a spreadsheet. - -=== Mocks - -Mocks and stubs defined using terminology by Fowler & Meszaros at -http://www.martinfowler.com/bliki/TestDouble.html: - -"Mocks are pre-programmed with expectations which form a specification -of the calls they are expected to receive. They can throw an exception -if they receive a call they don't expect and are checked during -verification to ensure they got all the calls they were expecting." - - class MemeAsker - def initialize(meme) - @meme = meme - end - - def ask(question) - method = question.tr(" ", "_") + "?" - @meme.__send__(method) - end - end - - require "minitest/autorun" - - describe MemeAsker, :ask do - describe "when passed an unpunctuated question" do - it "should invoke the appropriate predicate method on the meme" do - @meme = Minitest::Mock.new - @meme_asker = MemeAsker.new @meme - @meme.expect :will_it_blend?, :return_value - - @meme_asker.ask "will it blend" - - @meme.verify - end - end - end - -==== Multi-threading and Mocks - -Minitest mocks do not support multi-threading. If it works, fine, if it doesn't -you can use regular ruby patterns and facilities like local variables. Here's -an example of asserting that code inside a thread is run: - - def test_called_inside_thread - called = false - pr = Proc.new { called = true } - thread = Thread.new(&pr) - thread.join - assert called, "proc not called" - end - -=== Stubs - -Mocks and stubs are defined using terminology by Fowler & Meszaros at -http://www.martinfowler.com/bliki/TestDouble.html: - -"Stubs provide canned answers to calls made during the test". - -Minitest's stub method overrides a single method for the duration of -the block. - - def test_stale_eh - obj_under_test = Something.new - - refute obj_under_test.stale? - - Time.stub :now, Time.at(0) do # stub goes away once the block is done - assert obj_under_test.stale? - end - end - -A note on stubbing: In order to stub a method, the method must -actually exist prior to stubbing. Use a singleton method to create a -new non-existing method: - - def obj_under_test.fake_method - ... - end - -=== Running Your Tests - -Ideally, you'll use a rake task to run your tests, either piecemeal or -all at once. Both rake and rails ship with rake tasks for running your -tests. BUT! You don't have to: - - % ruby -Ilib:test test/minitest/test_minitest_test.rb - Run options: --seed 37685 - - # Running: - - ...................................................................... (etc) - - Finished in 0.107130s, 1446.8403 runs/s, 2959.0217 assertions/s. - - 155 runs, 317 assertions, 0 failures, 0 errors, 0 skips - -There are runtime options available, both from minitest itself, and also -provided via plugins. To see them, simply run with +--help+: - - % ruby -Ilib:test test/minitest/test_minitest_test.rb --help - minitest options: - -h, --help Display this help. - -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake - -v, --verbose Verbose. Show progress processing files. - -n, --name PATTERN Filter run on /regexp/ or string. - -e, --exclude PATTERN Exclude /regexp/ or string from run. - - Known extensions: pride, autotest - -p, --pride Pride. Show your testing pride! - -a, --autotest Connect to autotest server. - -You can set up a rake task to run all your tests by adding this to your Rakefile: - - require "rake/testtask" - - Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.libs << "lib" - t.test_files = FileList["test/**/test_*.rb"] - end - - task :default => :test - -== Writing Extensions - -To define a plugin, add a file named minitest/XXX_plugin.rb to your -project/gem. That file must be discoverable via ruby's LOAD_PATH (via -rubygems or otherwise). Minitest will find and require that file using -Gem.find_files. It will then try to call +plugin_XXX_init+ during -startup. The option processor will also try to call +plugin_XXX_options+ -passing the OptionParser instance and the current options hash. This -lets you register your own command-line options. Here's a totally -bogus example: - - # minitest/bogus_plugin.rb: - - module Minitest - def self.plugin_bogus_options(opts, options) - opts.on "--myci", "Report results to my CI" do - options[:myci] = true - options[:myci_addr] = get_myci_addr - options[:myci_port] = get_myci_port - end - end - - def self.plugin_bogus_init(options) - self.reporter << MyCI.new(options) if options[:myci] - end - end - -=== Adding custom reporters - -Minitest uses composite reporter to output test results using multiple -reporter instances. You can add new reporters to the composite during -the init_plugins phase. As we saw in +plugin_bogus_init+ above, you -simply add your reporter instance to the composite via <<. - -+AbstractReporter+ defines the API for reporters. You may subclass it -and override any method you want to achieve your desired behavior. - -start :: Called when the run has started. -record :: Called for each result, passed or otherwise. -report :: Called at the end of the run. -passed? :: Called to see if you detected any problems. - -Using our example above, here is how we might implement MyCI: - - # minitest/bogus_plugin.rb - - module Minitest - class MyCI < AbstractReporter - attr_accessor :results, :addr, :port - - def initialize options - self.results = [] - self.addr = options[:myci_addr] - self.port = options[:myci_port] - end - - def record result - self.results << result - end - - def report - CI.connect(addr, port).send_results self.results - end - end - - # code from above... - end - -== FAQ - -=== How to test SimpleDelegates? - -The following implementation and test: - - class Worker < SimpleDelegator - def work - end - end - - describe Worker do - before do - @worker = Worker.new(Object.new) - end - - it "must respond to work" do - _(@worker).must_respond_to :work - end - end - -outputs a failure: - - 1) Failure: - Worker#test_0001_must respond to work [bug11.rb:16]: - Expected # (Object) to respond to #work. - -Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. -Expectations are put on Object (one level down) so the Worker -(SimpleDelegate) hits +method_missing+ and delegates down to the -+Object.new+ instance. That object doesn't respond to work so the test -fails. - -You can bypass SimpleDelegate#method_missing by extending the worker -with Minitest::Expectations. You can either do that in your setup at -the instance level, like: - - before do - @worker = Worker.new(Object.new) - @worker.extend Minitest::Expectations - end - -or you can extend the Worker class (within the test file!), like: - - class Worker - include ::Minitest::Expectations - end - -=== How to share code across test classes? - -Use a module. That's exactly what they're for: - - module UsefulStuff - def useful_method - # ... - end - end - - describe Blah do - include UsefulStuff - - def test_whatever - # useful_method available here - end - end - -Remember, +describe+ simply creates test classes. It's just ruby at -the end of the day and all your normal Good Ruby Rules (tm) apply. If -you want to extend your test using setup/teardown via a module, just -make sure you ALWAYS call super. before/after automatically call super -for you, so make sure you don't do it twice. - -=== How to run code before a group of tests? - -Use a constant with begin...end like this: - - describe Blah do - SETUP = begin - # ... this runs once when describe Blah starts - end - # ... - end - -This can be useful for expensive initializations or sharing state. -Remember, this is just ruby code, so you need to make sure this -technique and sharing state doesn't interfere with your tests. - -=== Why am I seeing uninitialized constant MiniTest::Test (NameError)? - -Are you running the test with Bundler (e.g. via bundle exec )? If so, -in order to require minitest, you must first add the gem 'minitest' -to your Gemfile and run +bundle+. Once it's installed, you should be -able to require minitest and run your tests. - -== Prominent Projects using Minitest: - -* arel -* journey -* mime-types -* nokogiri -* rails (active_support et al) -* rake -* rdoc -* ...and of course, everything from seattle.rb... - -== Developing Minitest: - -Minitest requires {Hoe}[https://rubygems.org/gems/hoe]. - -=== Minitest's own tests require UTF-8 external encoding. - -This is a common problem in Windows, where the default external Encoding is -often CP850, but can affect any platform. -Minitest can run test suites using any Encoding, but to run Minitest's -own tests you must have a default external Encoding of UTF-8. - -If your encoding is wrong, you'll see errors like: - - --- expected - +++ actual - @@ -1,2 +1,3 @@ - # encoding: UTF-8 - -"Expected /\\w+/ to not match \"blah blah blah\"." - +"Expected /\\w+/ to not match # encoding: UTF-8 - +\"blah blah blah\"." - -To check your current encoding, run: - - ruby -e 'puts Encoding.default_external' - -If your output is something other than UTF-8, you can set the RUBYOPTS -env variable to a value of '-Eutf-8'. Something like: - - RUBYOPT='-Eutf-8' ruby -e 'puts Encoding.default_external' - -Check your OS/shell documentation for the precise syntax (the above -will not work on a basic Windows CMD prompt, look for the SET command). -Once you've got it successfully outputing UTF-8, use the same setting -when running rake in Minitest. - -=== Minitest's own tests require GNU (or similar) diff. - -This is also a problem primarily affecting Windows developers. PowerShell -has a command called diff, but it is not suitable for use with Minitest. - -If you see failures like either of these, you are probably missing diff tool: - - 4) Failure: - TestMinitestUnitTestCase#test_assert_equal_different_long [D:/ruby/seattlerb/minitest/test/minitest/test_minitest_test.rb:936]: - Expected: "--- expected\n+++ actual\n@@ -1 +1 @@\n-\"hahahahahahahahahahahahahahahahahahahaha\"\n+\"blahblahblahblahblahblahblahblahblahblah\"\n" - Actual: "Expected: \"hahahahahahahahahahahahahahahahahahahaha\"\n Actual: \"blahblahblahblahblahblahblahblahblahblah\"" - - - 5) Failure: - TestMinitestUnitTestCase#test_assert_equal_different_collection_hash_hex_invisible [D:/ruby/seattlerb/minitest/test/minitest/test_minitest_test.rb:845]: - Expected: "No visible difference in the Hash#inspect output.\nYou should look at the implementation of #== on Hash or its members.\n - {1=>#}" - Actual: "Expected: {1=>#}\n Actual: {1=>#}" - - -If you use Cygwin or MSYS2 or similar there are packages that include a -GNU diff for Windows. If you don't, you can download GNU diffutils from -http://gnuwin32.sourceforge.net/packages/diffutils.htm -(make sure to add it to your PATH). - -You can make sure it's installed and path is configured properly with: - - diff.exe -v - -There are multiple lines of output, the first should be something like: - - diff (GNU diffutils) 2.8.1 - -If you are using PowerShell make sure you run diff.exe, not just diff, -which will invoke the PowerShell built in function. - -== Known Extensions: - -capybara_minitest_spec :: Bridge between Capybara RSpec matchers and - Minitest::Spec expectations (e.g. - page.must_have_content("Title")). -color_pound_spec_reporter :: Test names print Ruby Object types in color with - your Minitest Spec style tests. -minispec-metadata :: Metadata for describe/it blocks & CLI tag filter. - E.g. it "requires JS driver", js: true do & - ruby test.rb --tag js runs tests tagged :js. -minispec-rails :: Minimal support to use Spec style in Rails 5+. -mini-apivore :: for swagger based automated API testing. -minitest-around :: Around block for minitest. An alternative to - setup/teardown dance. -minitest-assert_errors :: Adds Minitest assertions to test for errors raised - or not raised by Minitest itself. -minitest-autotest :: autotest is a continuous testing facility meant to - be used during development. -minitest-bacon :: minitest-bacon extends minitest with bacon-like - functionality. -minitest-bang :: Adds support for RSpec-style let! to immediately - invoke let statements before each test. -minitest-bisect :: Helps you isolate and debug random test failures. -minitest-blink1_reporter :: Display test results with a Blink1. -minitest-capistrano :: Assertions and expectations for testing - Capistrano recipes. -minitest-capybara :: Capybara matchers support for minitest unit and - spec. -minitest-chef-handler :: Run Minitest suites as Chef report handlers -minitest-ci :: CI reporter plugin for Minitest. -minitest-context :: Defines contexts for code reuse in Minitest - specs that share common expectations. -minitest-debugger :: Wraps assert so failed assertions drop into - the ruby debugger. -minitest-display :: Patches Minitest to allow for an easily - configurable output. -minitest-documentation :: Minimal documentation format inspired by rspec's. -minitest-doc_reporter :: Detailed output inspired by rspec's documentation - format. -minitest-emoji :: Print out emoji for your test passes, fails, and - skips. -minitest-english :: Semantically symmetric aliases for assertions and - expectations. -minitest-excludes :: Clean API for excluding certain tests you - don't want to run under certain conditions. -minitest-fail-fast :: Reimplements RSpec's "fail fast" feature -minitest-filecontent :: Support unit tests with expectation results in files. - Differing results will be stored again in files. -minitest-filesystem :: Adds assertion and expectation to help testing - filesystem contents. -minitest-firemock :: Makes your Minitest mocks more resilient. -minitest-focus :: Focus on one test at a time. -minitest-gcstats :: A minitest plugin that adds a report of the top - tests by number of objects allocated. -minitest-global_expectations:: Support minitest expectation methods for all objects -minitest-great_expectations :: Generally useful additions to minitest's - assertions and expectations. -minitest-growl :: Test notifier for minitest via growl. -minitest-happy :: GLOBALLY ACTIVATE MINITEST PRIDE! RAWR! -minitest-have_tag :: Adds Minitest assertions to test for the existence of - HTML tags, including contents, within a provided string. -minitest-hooks :: Around and before_all/after_all/around_all hooks -minitest-hyper :: Pretty, single-page HTML reports for your Minitest runs -minitest-implicit-subject :: Implicit declaration of the test subject. -minitest-instrument :: Instrument ActiveSupport::Notifications when - test method is executed. -minitest-instrument-db :: Store information about speed of test execution - provided by minitest-instrument in database. -minitest-junit :: JUnit-style XML reporter for minitest. -minitest-keyword :: Use Minitest assertions with keyword arguments. -minitest-libnotify :: Test notifier for minitest via libnotify. -minitest-line :: Run test at line number. -minitest-logger :: Define assert_log and enable minitest to test log messages. - Supports Logger and Log4r::Logger. -minitest-macruby :: Provides extensions to minitest for macruby UI - testing. -minitest-matchers :: Adds support for RSpec-style matchers to - minitest. -minitest-matchers_vaccine :: Adds assertions that adhere to the matcher spec, - but without any expectation infections. -minitest-metadata :: Annotate tests with metadata (key-value). -minitest-mock_expectations :: Provides method call assertions for minitest. -minitest-mongoid :: Mongoid assertion matchers for Minitest. -minitest-must_not :: Provides must_not as an alias for wont in - Minitest. -minitest-optional_retry :: Automatically retry failed test to help with flakiness. -minitest-osx :: Reporter for the Mac OS X notification center. -minitest-parallel_fork :: Fork-based parallelization -minitest-parallel-db :: Run tests in parallel with a single database. -minitest-power_assert :: PowerAssert for Minitest. -minitest-predicates :: Adds support for .predicate? methods. -minitest-profile :: List the 10 slowest tests in your suite. -minitest-rails :: Minitest integration for Rails 3.x. -minitest-rails-capybara :: Capybara integration for Minitest::Rails. -minitest-reporters :: Create customizable Minitest output formats. -minitest-rg :: Colored red/green output for Minitest. -minitest-rspec_mocks :: Use RSpec Mocks with Minitest. -minitest-server :: minitest-server provides a client/server setup - with your minitest process, allowing your test - run to send its results directly to a handler. -minitest-sequel :: Minitest assertions to speed-up development and - testing of Ruby Sequel database setups. -minitest-shared_description :: Support for shared specs and shared spec - subclasses -minitest-should_syntax :: RSpec-style x.should == y assertions for - Minitest. -minitest-shouldify :: Adding all manner of shoulds to Minitest (bad - idea) -minitest-snail :: Print a list of tests that take too long -minitest-spec-context :: Provides rspec-ish context method to - Minitest::Spec. -minitest-spec-expect :: Expect syntax for Minitest::Spec (e.g. - expect(sequences).to_include :celery_man). -minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond. -minitest-spec-rails :: Drop in Minitest::Spec superclass for - ActiveSupport::TestCase. -minitest-sprint :: Runs (Get it? It's fast!) your tests and makes - it easier to rerun individual failures. -minitest-stately :: Find leaking state between tests -minitest-stub_any_instance :: Stub any instance of a method on the given class - for the duration of a block. -minitest-stub-const :: Stub constants for the duration of a block. -minitest-tags :: Add tags for minitest. -minitest-unordered :: Adds a new assertion to minitest for checking the - contents of a collection, ignoring element order. -minitest-vcr :: Automatic cassette managment with Minitest::Spec - and VCR. -minitest_owrapper :: Get tests results as a TestResult object. -minitest_should :: Shoulda style syntax for minitest test::unit. -minitest_tu_shim :: Bridges between test/unit and minitest. -mongoid-minitest :: Minitest matchers for Mongoid. -mutant-minitest :: Minitest integration for mutant. -pry-rescue :: A pry plugin w/ minitest support. See - pry-rescue/minitest.rb. -rspec2minitest :: Easily translate any RSpec matchers to Minitest - assertions and expectations. - -== Unknown Extensions: - -Authors... Please send me a pull request with a description of your minitest extension. - -* assay-minitest -* detroit-minitest -* em-minitest-spec -* flexmock-minitest -* guard-minitest -* guard-minitest-decisiv -* minitest-activemodel -* minitest-ar-assertions -* minitest-capybara-unit -* minitest-colorer -* minitest-deluxe -* minitest-extra-assertions -* minitest-rails-shoulda -* minitest-spec -* minitest-spec-should -* minitest-sugar -* spork-minitest - -== Minitest related goods - -* minitest/pride fabric: http://www.spoonflower.com/fabric/3928730-again-by-katie_allen - -== REQUIREMENTS: - -* Ruby 2.3+. No magic is involved. I hope. - -== INSTALL: - - sudo gem install minitest - -On 1.9, you already have it. To get newer candy you can still install -the gem, and then requiring "minitest/autorun" should automatically -pull it in. If not, you'll need to do it yourself: - - gem "minitest" # ensures you"re using the gem, and not the built-in MT - require "minitest/autorun" - - # ... usual testing stuffs ... - -DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 -packages their own gems. They install a gem specification file, but -don't install the gem contents in the gem path. This messes up -Gem.find_files and many other things (gem which, gem contents, etc). - -Just install minitest as a gem for real and you'll be happier. - -== LICENSE: - -(The MIT License) - -Copyright (c) Ryan Davis, seattle.rb - -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. diff --git a/ruby/gems/minitest-5.13.0/Rakefile b/ruby/gems/minitest-5.13.0/Rakefile deleted file mode 100644 index 4971f9cb5..000000000 --- a/ruby/gems/minitest-5.13.0/Rakefile +++ /dev/null @@ -1,72 +0,0 @@ -# -*- ruby -*- - -require "rubygems" -require "hoe" - -Hoe.plugin :seattlerb -Hoe.plugin :rdoc - -Hoe.spec "minitest" do - developer "Ryan Davis", "ryand-ruby@zenspider.com" - - license "MIT" - - require_ruby_version "~> 2.2" -end - -desc "Find missing expectations" -task :specs do - $:.unshift "lib" - require "minitest/test" - require "minitest/spec" - - pos_prefix, neg_prefix = "must", "wont" - skip_re = /^(must|wont)$|wont_(throw)|must_(block|not?_|nothing|raise$)/x - dont_flip_re = /(must|wont)_(include|respond_to)/ - - map = { - /(must_throw)s/ => '\1', - /(?!not)_same/ => "_be_same_as", - /_in_/ => "_be_within_", - /_operator/ => "_be", - /_includes/ => "_include", - /(must|wont)_(.*_of|nil|silent|empty)/ => '\1_be_\2', - /must_raises/ => "must_raise", - } - - expectations = Minitest::Expectations.public_instance_methods.map(&:to_s) - assertions = Minitest::Assertions.public_instance_methods.map(&:to_s) - - assertions.sort.each do |assertion| - expectation = case assertion - when /^assert/ then - assertion.sub(/^assert/, pos_prefix.to_s) - when /^refute/ then - assertion.sub(/^refute/, neg_prefix.to_s) - end - - next unless expectation - next if expectation =~ skip_re - - regexp, replacement = map.find { |re, _| expectation =~ re } - expectation.sub! regexp, replacement if replacement - - next if expectations.include? expectation - - args = [assertion, expectation].map(&:to_sym).map(&:inspect) - args << :reverse if expectation =~ dont_flip_re - - puts - puts "##" - puts "# :method: #{expectation}" - puts "# See Minitest::Assertions##{assertion}" - puts - puts "infect_an_assertion #{args.join ", "}" - end -end - -task :bugs do - sh "for f in bug*.rb ; do echo $f; echo; #{Gem.ruby} -Ilib $f && rm $f ; done" -end - -# vim: syntax=Ruby diff --git a/ruby/gems/minitest-5.13.0/design_rationale.rb b/ruby/gems/minitest-5.13.0/design_rationale.rb deleted file mode 100644 index a3fcc378c..000000000 --- a/ruby/gems/minitest-5.13.0/design_rationale.rb +++ /dev/null @@ -1,52 +0,0 @@ -# Specs: # Equivalent Unit Tests: -############################################################################### -describe Thingy do # class TestThingy < Minitest::Test - before do # def setup - do_some_setup # super - end # do_some_setup - # end - it "should do the first thing" do # - 1.must_equal 1 # def test_first_thing - end # assert_equal 1, 1 - # end - describe SubThingy do # end - before do # - do_more_setup # class TestSubThingy < TestThingy - end # def setup - # super - it "should do the second thing" do # do_more_setup - 2.must_equal 2 # end - end # - end # def test_second_thing -end # assert_equal 2, 2 - # end - # end -############################################################################### -# runs 2 specs # runs 3 tests -############################################################################### -# The specs generate: - -class ThingySpec < Minitest::Spec - def setup - super - do_some_setup - end - - def test_should_do_the_first_thing - assert_equal 1, 1 - end -end - -class SubThingySpec < ThingySpec - def setup - super - do_more_setup - end - - # because only setup/teardown is inherited, not specs - remove_method :test_should_do_the_first_thing - - def test_should_do_the_second_thing - assert_equal 2, 2 - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/hoe/minitest.rb b/ruby/gems/minitest-5.13.0/lib/hoe/minitest.rb deleted file mode 100644 index 6c045a5f4..000000000 --- a/ruby/gems/minitest-5.13.0/lib/hoe/minitest.rb +++ /dev/null @@ -1,32 +0,0 @@ -# :stopdoc: - -class Hoe -end - -module Hoe::Minitest - def minitest? - self.name == "minitest" - end - - def initialize_minitest - unless minitest? then - dir = "../../minitest/dev/lib" - Hoe.add_include_dirs dir if File.directory? dir - end - - gem "minitest" - require "minitest" - version = Minitest::VERSION.split(/\./).first(2).join(".") - - dependency "minitest", "~> #{version}", :development unless - minitest? or ENV["MT_NO_ISOLATE"] - end - - def define_minitest_tasks - self.testlib = :minitest - - # make sure we use the gemmed minitest on 1.9 - self.test_prelude = 'gem "minitest"' unless - minitest? or ENV["MT_NO_ISOLATE"] - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest.rb b/ruby/gems/minitest-5.13.0/lib/minitest.rb deleted file mode 100644 index 8e71f0993..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest.rb +++ /dev/null @@ -1,1056 +0,0 @@ -require "optparse" -require "thread" -require "mutex_m" -require "minitest/parallel" -require "stringio" - -## -# :include: README.rdoc - -module Minitest - VERSION = "5.13.0" # :nodoc: - ENCS = "".respond_to? :encoding # :nodoc: - - @@installed_at_exit ||= false - @@after_run = [] - @extensions = [] - - mc = (class << self; self; end) - - ## - # Parallel test executor - - mc.send :attr_accessor, :parallel_executor - - warn "DEPRECATED: use MT_CPU instead of N for parallel test runs" if ENV["N"] - n_threads = (ENV["MT_CPU"] || ENV["N"] || 2).to_i - self.parallel_executor = Parallel::Executor.new n_threads - - ## - # Filter object for backtraces. - - mc.send :attr_accessor, :backtrace_filter - - ## - # Reporter object to be used for all runs. - # - # NOTE: This accessor is only available during setup, not during runs. - - mc.send :attr_accessor, :reporter - - ## - # Names of known extension plugins. - - mc.send :attr_accessor, :extensions - - ## - # The signal to use for dumping information to STDERR. Defaults to "INFO". - - mc.send :attr_accessor, :info_signal - self.info_signal = "INFO" - - ## - # Registers Minitest to run at process exit - - def self.autorun - at_exit { - next if $! and not ($!.kind_of? SystemExit and $!.success?) - - exit_code = nil - - pid = Process.pid - at_exit { - next if Process.pid != pid - @@after_run.reverse_each(&:call) - exit exit_code || false - } - - exit_code = Minitest.run ARGV - } unless @@installed_at_exit - @@installed_at_exit = true - end - - ## - # A simple hook allowing you to run a block of code after everything - # is done running. Eg: - # - # Minitest.after_run { p $debugging_info } - - def self.after_run &block - @@after_run << block - end - - def self.init_plugins options # :nodoc: - self.extensions.each do |name| - msg = "plugin_#{name}_init" - send msg, options if self.respond_to? msg - end - end - - def self.load_plugins # :nodoc: - return unless self.extensions.empty? - - seen = {} - - require "rubygems" unless defined? Gem - - Gem.find_files("minitest/*_plugin.rb").each do |plugin_path| - name = File.basename plugin_path, "_plugin.rb" - - next if seen[name] - seen[name] = true - - require plugin_path - self.extensions << name - end - end - - ## - # This is the top-level run method. Everything starts from here. It - # tells each Runnable sub-class to run, and each of those are - # responsible for doing whatever they do. - # - # The overall structure of a run looks like this: - # - # Minitest.autorun - # Minitest.run(args) - # Minitest.__run(reporter, options) - # Runnable.runnables.each - # runnable.run(reporter, options) - # self.runnable_methods.each - # self.run_one_method(self, runnable_method, reporter) - # Minitest.run_one_method(klass, runnable_method) - # klass.new(runnable_method).run - - def self.run args = [] - self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"] - - options = process_args args - - reporter = CompositeReporter.new - reporter << SummaryReporter.new(options[:io], options) - reporter << ProgressReporter.new(options[:io], options) - - self.reporter = reporter # this makes it available to plugins - self.init_plugins options - self.reporter = nil # runnables shouldn't depend on the reporter, ever - - self.parallel_executor.start if parallel_executor.respond_to?(:start) - reporter.start - begin - __run reporter, options - rescue Interrupt - warn "Interrupted. Exiting..." - end - self.parallel_executor.shutdown - reporter.report - - reporter.passed? - end - - ## - # Internal run method. Responsible for telling all Runnable - # sub-classes to run. - - def self.__run reporter, options - suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle - parallel, serial = suites.partition { |s| s.test_order == :parallel } - - # If we run the parallel tests before the serial tests, the parallel tests - # could run in parallel with the serial tests. This would be bad because - # the serial tests won't lock around Reporter#record. Run the serial tests - # first, so that after they complete, the parallel tests will lock when - # recording results. - serial.map { |suite| suite.run reporter, options } + - parallel.map { |suite| suite.run reporter, options } - end - - def self.process_args args = [] # :nodoc: - options = { - :io => $stdout, - } - orig_args = args.dup - - OptionParser.new do |opts| - opts.banner = "minitest options:" - opts.version = Minitest::VERSION - - opts.on "-h", "--help", "Display this help." do - puts opts - exit - end - - opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS)." - - desc = "Sets random seed. Also via env. Eg: SEED=n rake" - opts.on "-s", "--seed SEED", Integer, desc do |m| - options[:seed] = m.to_i - end - - opts.on "-v", "--verbose", "Verbose. Show progress processing files." do - options[:verbose] = true - end - - opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a| - options[:filter] = a - end - - opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a| - options[:exclude] = a - end - - unless extensions.empty? - opts.separator "" - opts.separator "Known extensions: #{extensions.join(", ")}" - - extensions.each do |meth| - msg = "plugin_#{meth}_options" - send msg, opts, options if self.respond_to?(msg) - end - end - - begin - opts.parse! args - rescue OptionParser::InvalidOption => e - puts - puts e - puts - puts opts - exit 1 - end - - orig_args -= args - end - - unless options[:seed] then - srand - options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF - orig_args << "--seed" << options[:seed].to_s - end - - srand options[:seed] - - options[:args] = orig_args.map { |s| - s =~ /[\s|&<>$()]/ ? s.inspect : s - }.join " " - - options - end - - def self.filter_backtrace bt # :nodoc: - backtrace_filter.filter bt - end - - ## - # Represents anything "runnable", like Test, Spec, Benchmark, or - # whatever you can dream up. - # - # Subclasses of this are automatically registered and available in - # Runnable.runnables. - - class Runnable - ## - # Number of assertions executed in this run. - - attr_accessor :assertions - - ## - # An assertion raised during the run, if any. - - attr_accessor :failures - - ## - # The time it took to run. - - attr_accessor :time - - def time_it # :nodoc: - t0 = Minitest.clock_time - - yield - ensure - self.time = Minitest.clock_time - t0 - end - - ## - # Name of the run. - - def name - @NAME - end - - ## - # Set the name of the run. - - def name= o - @NAME = o - end - - ## - # Returns all instance methods matching the pattern +re+. - - def self.methods_matching re - public_instance_methods(true).grep(re).map(&:to_s) - end - - def self.reset # :nodoc: - @@runnables = [] - end - - reset - - ## - # Responsible for running all runnable methods in a given class, - # each in its own instance. Each instance is passed to the - # reporter to record. - - def self.run reporter, options = {} - filter = options[:filter] || "/./" - filter = Regexp.new $1 if filter.is_a?(String) && filter =~ %r%/(.*)/% - - filtered_methods = self.runnable_methods.find_all { |m| - filter === m || filter === "#{self}##{m}" - } - - exclude = options[:exclude] - exclude = Regexp.new $1 if exclude =~ %r%/(.*)/% - - filtered_methods.delete_if { |m| - exclude === m || exclude === "#{self}##{m}" - } - - return if filtered_methods.empty? - - with_info_handler reporter do - filtered_methods.each do |method_name| - run_one_method self, method_name, reporter - end - end - end - - ## - # Runs a single method and has the reporter record the result. - # This was considered internal API but is factored out of run so - # that subclasses can specialize the running of an individual - # test. See Minitest::ParallelTest::ClassMethods for an example. - - def self.run_one_method klass, method_name, reporter - reporter.prerecord klass, method_name - reporter.record Minitest.run_one_method(klass, method_name) - end - - def self.with_info_handler reporter, &block # :nodoc: - handler = lambda do - unless reporter.passed? then - warn "Current results:" - warn "" - warn reporter.reporters.first - warn "" - end - end - - on_signal ::Minitest.info_signal, handler, &block - end - - SIGNALS = Signal.list # :nodoc: - - def self.on_signal name, action # :nodoc: - supported = SIGNALS[name] - - old_trap = trap name do - old_trap.call if old_trap.respond_to? :call - action.call - end if supported - - yield - ensure - trap name, old_trap if supported - end - - ## - # Each subclass of Runnable is responsible for overriding this - # method to return all runnable methods. See #methods_matching. - - def self.runnable_methods - raise NotImplementedError, "subclass responsibility" - end - - ## - # Returns all subclasses of Runnable. - - def self.runnables - @@runnables - end - - @@marshal_dump_warned = false - - def marshal_dump # :nodoc: - unless @@marshal_dump_warned then - warn ["Minitest::Runnable#marshal_dump is deprecated.", - "You might be violating internals. From", caller.first].join " " - @@marshal_dump_warned = true - end - - [self.name, self.failures, self.assertions, self.time] - end - - def marshal_load ary # :nodoc: - self.name, self.failures, self.assertions, self.time = ary - end - - def failure # :nodoc: - self.failures.first - end - - def initialize name # :nodoc: - self.name = name - self.failures = [] - self.assertions = 0 - end - - ## - # Runs a single method. Needs to return self. - - def run - raise NotImplementedError, "subclass responsibility" - end - - ## - # Did this run pass? - # - # Note: skipped runs are not considered passing, but they don't - # cause the process to exit non-zero. - - def passed? - raise NotImplementedError, "subclass responsibility" - end - - ## - # Returns a single character string to print based on the result - # of the run. One of ".", "F", - # "E" or "S". - - def result_code - raise NotImplementedError, "subclass responsibility" - end - - ## - # Was this run skipped? See #passed? for more information. - - def skipped? - raise NotImplementedError, "subclass responsibility" - end - end - - ## - # Shared code for anything that can get passed to a Reporter. See - # Minitest::Test & Minitest::Result. - - module Reportable - ## - # Did this run pass? - # - # Note: skipped runs are not considered passing, but they don't - # cause the process to exit non-zero. - - def passed? - not self.failure - end - - ## - # The location identifier of this test. Depends on a method - # existing called class_name. - - def location - loc = " [#{self.failure.location}]" unless passed? or error? - "#{self.class_name}##{self.name}#{loc}" - end - - def class_name # :nodoc: - raise NotImplementedError, "subclass responsibility" - end - - ## - # Returns ".", "F", or "E" based on the result of the run. - - def result_code - self.failure and self.failure.result_code or "." - end - - ## - # Was this run skipped? - - def skipped? - self.failure and Skip === self.failure - end - - ## - # Did this run error? - - def error? - self.failures.any? { |f| UnexpectedError === f } - end - end - - ## - # This represents a test result in a clean way that can be - # marshalled over a wire. Tests can do anything they want to the - # test instance and can create conditions that cause Marshal.dump to - # blow up. By using Result.from(a_test) you can be reasonably sure - # that the test result can be marshalled. - - class Result < Runnable - include Minitest::Reportable - - undef_method :marshal_dump - undef_method :marshal_load - - ## - # The class name of the test result. - - attr_accessor :klass - - ## - # The location of the test method. - - attr_accessor :source_location - - ## - # Create a new test result from a Runnable instance. - - def self.from runnable - o = runnable - - r = self.new o.name - r.klass = o.class.name - r.assertions = o.assertions - r.failures = o.failures.dup - r.time = o.time - - r.source_location = o.method(o.name).source_location rescue ["unknown", -1] - - r - end - - def class_name # :nodoc: - self.klass # for Minitest::Reportable - end - - def to_s # :nodoc: - return location if passed? and not skipped? - - failures.map { |failure| - "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n" - }.join "\n" - end - end - - ## - # Defines the API for Reporters. Subclass this and override whatever - # you want. Go nuts. - - class AbstractReporter - include Mutex_m - - ## - # Starts reporting on the run. - - def start - end - - ## - # About to start running a test. This allows a reporter to show - # that it is starting or that we are in the middle of a test run. - - def prerecord klass, name - end - - ## - # Output and record the result of the test. Call - # {result#result_code}[rdoc-ref:Runnable#result_code] to get the - # result character string. Stores the result of the run if the run - # did not pass. - - def record result - end - - ## - # Outputs the summary of the run. - - def report - end - - ## - # Did this run pass? - - def passed? - true - end - end - - class Reporter < AbstractReporter # :nodoc: - ## - # The IO used to report. - - attr_accessor :io - - ## - # Command-line options for this run. - - attr_accessor :options - - def initialize io = $stdout, options = {} # :nodoc: - super() - self.io = io - self.options = options - end - end - - ## - # A very simple reporter that prints the "dots" during the run. - # - # This is added to the top-level CompositeReporter at the start of - # the run. If you want to change the output of minitest via a - # plugin, pull this out of the composite and replace it with your - # own. - - class ProgressReporter < Reporter - def prerecord klass, name #:nodoc: - if options[:verbose] then - io.print "%s#%s = " % [klass.name, name] - io.flush - end - end - - def record result # :nodoc: - io.print "%.2f s = " % [result.time] if options[:verbose] - io.print result.result_code - io.puts if options[:verbose] - end - end - - ## - # A reporter that gathers statistics about a test run. Does not do - # any IO because meant to be used as a parent class for a reporter - # that does. - # - # If you want to create an entirely different type of output (eg, - # CI, HTML, etc), this is the place to start. - # - # Example: - # - # class JenkinsCIReporter < StatisticsReporter - # def report - # super # Needed to calculate some statistics - # - # print " 30 characters. - # 3. or: Strings are equal to each other (but maybe different encodings?). - # 4. and: we found a diff executable. - - def things_to_diff exp, act - expect = mu_pp_for_diff exp - butwas = mu_pp_for_diff act - - e1, e2 = expect.include?("\n"), expect.include?("\\n") - b1, b2 = butwas.include?("\n"), butwas.include?("\\n") - - need_to_diff = - (e1 ^ e2 || - b1 ^ b2 || - expect.size > 30 || - butwas.size > 30 || - expect == butwas) && - Minitest::Assertions.diff - - need_to_diff && [expect, butwas] - end - - ## - # This returns a human-readable version of +obj+. By default - # #inspect is called. You can override this to use #pretty_inspect - # if you want. - # - # See Minitest::Test.make_my_diffs_pretty! - - def mu_pp obj - s = obj.inspect - - if defined? Encoding then - s = s.encode Encoding.default_external - - if String === obj && (obj.encoding != Encoding.default_external || - !obj.valid_encoding?) then - enc = "# encoding: #{obj.encoding}" - val = "# valid: #{obj.valid_encoding?}" - s = "#{enc}\n#{val}\n#{s}" - end - end - - s - end - - ## - # This returns a diff-able more human-readable version of +obj+. - # This differs from the regular mu_pp because it expands escaped - # newlines and makes hex-values (like object_ids) generic. This - # uses mu_pp to do the first pass and then cleans it up. - - def mu_pp_for_diff obj - str = mu_pp obj - - # both '\n' & '\\n' (_after_ mu_pp (aka inspect)) - single = !!str.match(/(?exp == act printing the difference between - # the two, if possible. - # - # If there is no visible difference but the assertion fails, you - # should suspect that your #== is buggy, or your inspect output is - # missing crucial details. For nicer structural diffing, set - # Minitest::Test.make_my_diffs_pretty! - # - # For floats use assert_in_delta. - # - # See also: Minitest::Assertions.diff - - def assert_equal exp, act, msg = nil - msg = message(msg, E) { diff exp, act } - result = assert exp == act, msg - - if nil == exp then - if Minitest::VERSION =~ /^6/ then - refute_nil exp, "Use assert_nil if expecting nil." - else - where = Minitest.filter_backtrace(caller).first - where = where.split(/:in /, 2).first # clean up noise - - warn "DEPRECATED: Use assert_nil if expecting nil from #{where}. This will fail in Minitest 6." - end - end - - result - end - - ## - # For comparing Floats. Fails unless +exp+ and +act+ are within +delta+ - # of each other. - # - # assert_in_delta Math::PI, (22.0 / 7.0), 0.01 - - def assert_in_delta exp, act, delta = 0.001, msg = nil - n = (exp - act).abs - msg = message(msg) { - "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}" - } - assert delta >= n, msg - end - - ## - # For comparing Floats. Fails unless +exp+ and +act+ have a relative - # error less than +epsilon+. - - def assert_in_epsilon exp, act, epsilon = 0.001, msg = nil - assert_in_delta exp, act, [exp.abs, act.abs].min * epsilon, msg - end - - ## - # Fails unless +collection+ includes +obj+. - - def assert_includes collection, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" - } - assert_respond_to collection, :include? - assert collection.include?(obj), msg - end - - ## - # Fails unless +obj+ is an instance of +cls+. - - def assert_instance_of cls, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" - } - - assert obj.instance_of?(cls), msg - end - - ## - # Fails unless +obj+ is a kind of +cls+. - - def assert_kind_of cls, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" } - - assert obj.kind_of?(cls), msg - end - - ## - # Fails unless +matcher+ =~ +obj+. - - def assert_match matcher, obj, msg = nil - msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } - assert_respond_to matcher, :"=~" - matcher = Regexp.new Regexp.escape matcher if String === matcher - assert matcher =~ obj, msg - end - - ## - # Fails unless +obj+ is nil - - def assert_nil obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" } - assert obj.nil?, msg - end - - ## - # For testing with binary operators. Eg: - # - # assert_operator 5, :<=, 4 - - def assert_operator o1, op, o2 = UNDEFINED, msg = nil - return assert_predicate o1, op, msg if UNDEFINED == o2 - msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" } - assert o1.__send__(op, o2), msg - end - - ## - # Fails if stdout or stderr do not output the expected results. - # Pass in nil if you don't care about that streams output. Pass in - # "" if you require it to be silent. Pass in a regexp if you want - # to pattern match. - # - # assert_output(/hey/) { method_with_output } - # - # NOTE: this uses #capture_io, not #capture_subprocess_io. - # - # See also: #assert_silent - - def assert_output stdout = nil, stderr = nil - flunk "assert_output requires a block to capture output." unless - block_given? - - out, err = capture_io do - yield - end - - err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr - out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout - - y = send err_msg, stderr, err, "In stderr" if err_msg - x = send out_msg, stdout, out, "In stdout" if out_msg - - (!stdout || x) && (!stderr || y) - end - - ## - # Fails unless +path+ exists. - - def assert_path_exists path, msg = nil - msg = message(msg) { "Expected path '#{path}' to exist" } - assert File.exist?(path), msg - end - - ## - # For testing with predicates. Eg: - # - # assert_predicate str, :empty? - # - # This is really meant for specs and is front-ended by assert_operator: - # - # str.must_be :empty? - - def assert_predicate o1, op, msg = nil - msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" } - assert o1.__send__(op), msg - end - - ## - # Fails unless the block raises one of +exp+. Returns the - # exception matched so you can check the message, attributes, etc. - # - # +exp+ takes an optional message on the end to help explain - # failures and defaults to StandardError if no exception class is - # passed. Eg: - # - # assert_raises(CustomError) { method_with_custom_error } - # - # With custom error message: - # - # assert_raises(CustomError, 'This should have raised CustomError') { method_with_custom_error } - # - # Using the returned object: - # - # error = assert_raises(CustomError) do - # raise CustomError, 'This is really bad' - # end - # - # assert_equal 'This is really bad', error.message - - def assert_raises *exp - flunk "assert_raises requires a block to capture errors." unless - block_given? - - msg = "#{exp.pop}.\n" if String === exp.last - exp << StandardError if exp.empty? - - begin - yield - rescue *exp => e - pass # count assertion - return e - rescue Minitest::Skip, Minitest::Assertion - # don't count assertion - raise - rescue SignalException, SystemExit - raise - rescue Exception => e - flunk proc { - exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not") - } - end - - exp = exp.first if exp.size == 1 - - flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." - end - - ## - # Fails unless +obj+ responds to +meth+. - - def assert_respond_to obj, meth, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" - } - assert obj.respond_to?(meth), msg - end - - ## - # Fails unless +exp+ and +act+ are #equal? - - def assert_same exp, act, msg = nil - msg = message(msg) { - data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] - "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data - } - assert exp.equal?(act), msg - end - - ## - # +send_ary+ is a receiver, message and arguments. - # - # Fails unless the call returns a true value - - def assert_send send_ary, m = nil - where = Minitest.filter_backtrace(caller).first - where = where.split(/:in /, 2).first # clean up noise - warn "DEPRECATED: assert_send. From #{where}" - - recv, msg, *args = send_ary - m = message(m) { - "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" } - assert recv.__send__(msg, *args), m - end - - ## - # Fails if the block outputs anything to stderr or stdout. - # - # See also: #assert_output - - def assert_silent - assert_output "", "" do - yield - end - end - - ## - # Fails unless the block throws +sym+ - - def assert_throws sym, msg = nil - default = "Expected #{mu_pp(sym)} to have been thrown" - caught = true - catch(sym) do - begin - yield - rescue ThreadError => e # wtf?!? 1.8 + threads == suck - default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" - rescue ArgumentError => e # 1.9 exception - raise e unless e.message.include?("uncaught throw") - default += ", not #{e.message.split(/ /).last}" - rescue NameError => e # 1.8 exception - raise e unless e.name == sym - default += ", not #{e.name.inspect}" - end - caught = false - end - - assert caught, message(msg) { default } - end - - ## - # Captures $stdout and $stderr into strings: - # - # out, err = capture_io do - # puts "Some info" - # warn "You did a bad thing" - # end - # - # assert_match %r%info%, out - # assert_match %r%bad%, err - # - # NOTE: For efficiency, this method uses StringIO and does not - # capture IO for subprocesses. Use #capture_subprocess_io for - # that. - - def capture_io - _synchronize do - begin - captured_stdout, captured_stderr = StringIO.new, StringIO.new - - orig_stdout, orig_stderr = $stdout, $stderr - $stdout, $stderr = captured_stdout, captured_stderr - - yield - - return captured_stdout.string, captured_stderr.string - ensure - $stdout = orig_stdout - $stderr = orig_stderr - end - end - end - - ## - # Captures $stdout and $stderr into strings, using Tempfile to - # ensure that subprocess IO is captured as well. - # - # out, err = capture_subprocess_io do - # system "echo Some info" - # system "echo You did a bad thing 1>&2" - # end - # - # assert_match %r%info%, out - # assert_match %r%bad%, err - # - # NOTE: This method is approximately 10x slower than #capture_io so - # only use it when you need to test the output of a subprocess. - - def capture_subprocess_io - _synchronize do - begin - require "tempfile" - - captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") - - orig_stdout, orig_stderr = $stdout.dup, $stderr.dup - $stdout.reopen captured_stdout - $stderr.reopen captured_stderr - - yield - - $stdout.rewind - $stderr.rewind - - return captured_stdout.read, captured_stderr.read - ensure - captured_stdout.unlink - captured_stderr.unlink - $stdout.reopen orig_stdout - $stderr.reopen orig_stderr - end - end - end - - ## - # Returns details for exception +e+ - - def exception_details e, msg - [ - "#{msg}", - "Class: <#{e.class}>", - "Message: <#{e.message.inspect}>", - "---Backtrace---", - "#{Minitest.filter_backtrace(e.backtrace).join("\n")}", - "---------------", - ].join "\n" - end - - ## - # Fails after a given date (in the local time zone). This allows - # you to put time-bombs in your tests if you need to keep - # something around until a later date lest you forget about it. - - def fail_after y,m,d,msg - flunk msg if Time.now > Time.local(y, m, d) - end - - ## - # Fails with +msg+. - - def flunk msg = nil - msg ||= "Epic Fail!" - assert false, msg - end - - ## - # Returns a proc that will output +msg+ along with the default message. - - def message msg = nil, ending = nil, &default - proc { - msg = msg.call.chomp(".") if Proc === msg - custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? - "#{custom_message}#{default.call}#{ending || "."}" - } - end - - ## - # used for counting assertions - - def pass _msg = nil - assert true - end - - ## - # Fails if +test+ is truthy. - - def refute test, msg = nil - msg ||= message { "Expected #{mu_pp(test)} to not be truthy" } - not assert !test, msg - end - - ## - # Fails if +obj+ is empty. - - def refute_empty obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" } - assert_respond_to obj, :empty? - refute obj.empty?, msg - end - - ## - # Fails if exp == act. - # - # For floats use refute_in_delta. - - def refute_equal exp, act, msg = nil - msg = message(msg) { - "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" - } - refute exp == act, msg - end - - ## - # For comparing Floats. Fails if +exp+ is within +delta+ of +act+. - # - # refute_in_delta Math::PI, (22.0 / 7.0) - - def refute_in_delta exp, act, delta = 0.001, msg = nil - n = (exp - act).abs - msg = message(msg) { - "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}" - } - refute delta >= n, msg - end - - ## - # For comparing Floats. Fails if +exp+ and +act+ have a relative error - # less than +epsilon+. - - def refute_in_epsilon a, b, epsilon = 0.001, msg = nil - refute_in_delta a, b, a * epsilon, msg - end - - ## - # Fails if +collection+ includes +obj+. - - def refute_includes collection, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" - } - assert_respond_to collection, :include? - refute collection.include?(obj), msg - end - - ## - # Fails if +obj+ is an instance of +cls+. - - def refute_instance_of cls, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} to not be an instance of #{cls}" - } - refute obj.instance_of?(cls), msg - end - - ## - # Fails if +obj+ is a kind of +cls+. - - def refute_kind_of cls, obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } - refute obj.kind_of?(cls), msg - end - - ## - # Fails if +matcher+ =~ +obj+. - - def refute_match matcher, obj, msg = nil - msg = message(msg) { "Expected #{mu_pp matcher} to not match #{mu_pp obj}" } - assert_respond_to matcher, :"=~" - matcher = Regexp.new Regexp.escape matcher if String === matcher - refute matcher =~ obj, msg - end - - ## - # Fails if +obj+ is nil. - - def refute_nil obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" } - refute obj.nil?, msg - end - - ## - # Fails if +o1+ is not +op+ +o2+. Eg: - # - # refute_operator 1, :>, 2 #=> pass - # refute_operator 1, :<, 2 #=> fail - - def refute_operator o1, op, o2 = UNDEFINED, msg = nil - return refute_predicate o1, op, msg if UNDEFINED == o2 - msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" } - refute o1.__send__(op, o2), msg - end - - ## - # Fails if +path+ exists. - - def refute_path_exists path, msg = nil - msg = message(msg) { "Expected path '#{path}' to not exist" } - refute File.exist?(path), msg - end - - ## - # For testing with predicates. - # - # refute_predicate str, :empty? - # - # This is really meant for specs and is front-ended by refute_operator: - # - # str.wont_be :empty? - - def refute_predicate o1, op, msg = nil - msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" } - refute o1.__send__(op), msg - end - - ## - # Fails if +obj+ responds to the message +meth+. - - def refute_respond_to obj, meth, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" } - - refute obj.respond_to?(meth), msg - end - - ## - # Fails if +exp+ is the same (by object identity) as +act+. - - def refute_same exp, act, msg = nil - msg = message(msg) { - data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] - "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data - } - refute exp.equal?(act), msg - end - - ## - # Skips the current run. If run in verbose-mode, the skipped run - # gets listed at the end of the run but doesn't cause a failure - # exit code. - - def skip msg = nil, bt = caller - msg ||= "Skipped, no message given" - @skip = true - raise Minitest::Skip, msg, bt - end - - ## - # Skips the current run until a given date (in the local time - # zone). This allows you to put some fixes on hold until a later - # date, but still holds you accountable and prevents you from - # forgetting it. - - def skip_until y,m,d,msg - skip msg if Time.now < Time.local(y, m, d) - where = caller.first.split(/:/, 3).first(2).join ":" - warn "Stale skip_until %p at %s" % [msg, where] - end - - ## - # Was this testcase skipped? Meant for #teardown. - - def skipped? - defined?(@skip) and @skip - end - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/autorun.rb b/ruby/gems/minitest-5.13.0/lib/minitest/autorun.rb deleted file mode 100644 index 9409b04b2..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/autorun.rb +++ /dev/null @@ -1,13 +0,0 @@ -begin - require "rubygems" - gem "minitest" -rescue Gem::LoadError - # do nothing -end - -require "minitest" -require "minitest/spec" -require "minitest/mock" -require "minitest/hell" if ENV["MT_HELL"] - -Minitest.autorun diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/benchmark.rb b/ruby/gems/minitest-5.13.0/lib/minitest/benchmark.rb deleted file mode 100644 index f2b2465eb..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/benchmark.rb +++ /dev/null @@ -1,455 +0,0 @@ -require "minitest/test" -require "minitest/spec" - -module Minitest - ## - # Subclass Benchmark to create your own benchmark runs. Methods - # starting with "bench_" get executed on a per-class. - # - # See Minitest::Assertions - - class Benchmark < Test - def self.io # :nodoc: - @io - end - - def io # :nodoc: - self.class.io - end - - def self.run reporter, options = {} # :nodoc: - @io = reporter.io - super - end - - def self.runnable_methods # :nodoc: - methods_matching(/^bench_/) - end - - ## - # Returns a set of ranges stepped exponentially from +min+ to - # +max+ by powers of +base+. Eg: - # - # bench_exp(2, 16, 2) # => [2, 4, 8, 16] - - def self.bench_exp min, max, base = 10 - min = (Math.log10(min) / Math.log10(base)).to_i - max = (Math.log10(max) / Math.log10(base)).to_i - - (min..max).map { |m| base ** m }.to_a - end - - ## - # Returns a set of ranges stepped linearly from +min+ to +max+ by - # +step+. Eg: - # - # bench_linear(20, 40, 10) # => [20, 30, 40] - - def self.bench_linear min, max, step = 10 - (min..max).step(step).to_a - rescue LocalJumpError # 1.8.6 - r = []; (min..max).step(step) { |n| r << n }; r - end - - ## - # Specifies the ranges used for benchmarking for that class. - # Defaults to exponential growth from 1 to 10k by powers of 10. - # Override if you need different ranges for your benchmarks. - # - # See also: ::bench_exp and ::bench_linear. - - def self.bench_range - bench_exp 1, 10_000 - end - - ## - # Runs the given +work+, gathering the times of each run. Range - # and times are then passed to a given +validation+ proc. Outputs - # the benchmark name and times in tab-separated format, making it - # easy to paste into a spreadsheet for graphing or further - # analysis. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # validation = proc { |x, y| ... } - # assert_performance validation do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance validation, &work - range = self.class.bench_range - - io.print "#{self.name}" - - times = [] - - range.each do |x| - GC.start - t0 = Minitest.clock_time - instance_exec(x, &work) - t = Minitest.clock_time - t0 - - io.print "\t%9.6f" % t - times << t - end - io.puts - - validation[range, times] - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a constant rate (eg, linear slope == 0) within a given - # +threshold+. Note: because we're testing for a slope of 0, R^2 - # is not a good determining factor for the fit, so the threshold - # is applied against the slope itself. As such, you probably want - # to tighten it from the default. - # - # See https://www.graphpad.com/guides/prism/8/curve-fitting/reg_intepretingnonlinr2.htm - # for more details. - # - # Fit is calculated by #fit_linear. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_constant 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_constant threshold = 0.99, &work - validation = proc do |range, times| - a, b, rr = fit_linear range, times - assert_in_delta 0, b, 1 - threshold - [a, b, rr] - end - - assert_performance validation, &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a exponential curve within a given error +threshold+. - # - # Fit is calculated by #fit_exponential. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_exponential 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_exponential threshold = 0.99, &work - assert_performance validation_for_fit(:exponential, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a logarithmic curve within a given error +threshold+. - # - # Fit is calculated by #fit_logarithmic. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_logarithmic 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_logarithmic threshold = 0.99, &work - assert_performance validation_for_fit(:logarithmic, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a straight line within a given error +threshold+. - # - # Fit is calculated by #fit_linear. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_linear 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_linear threshold = 0.99, &work - assert_performance validation_for_fit(:linear, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered curve - # fit to match a power curve within a given error +threshold+. - # - # Fit is calculated by #fit_power. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_power 0.9999 do |x| - # @obj.algorithm - # end - # end - - def assert_performance_power threshold = 0.99, &work - assert_performance validation_for_fit(:power, threshold), &work - end - - ## - # Takes an array of x/y pairs and calculates the general R^2 value. - # - # See: http://en.wikipedia.org/wiki/Coefficient_of_determination - - def fit_error xys - y_bar = sigma(xys) { |_, y| y } / xys.size.to_f - ss_tot = sigma(xys) { |_, y| (y - y_bar) ** 2 } - ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } - - 1 - (ss_err / ss_tot) - end - - ## - # To fit a functional form: y = ae^(bx). - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html - - def fit_exponential xs, ys - n = xs.size - xys = xs.zip(ys) - sxlny = sigma(xys) { |x, y| x * Math.log(y) } - slny = sigma(xys) { |_, y| Math.log(y) } - sx2 = sigma(xys) { |x, _| x * x } - sx = sigma xs - - c = n * sx2 - sx ** 2 - a = (slny * sx2 - sx * sxlny) / c - b = ( n * sxlny - sx * slny ) / c - - return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } - end - - ## - # To fit a functional form: y = a + b*ln(x). - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html - - def fit_logarithmic xs, ys - n = xs.size - xys = xs.zip(ys) - slnx2 = sigma(xys) { |x, _| Math.log(x) ** 2 } - slnx = sigma(xys) { |x, _| Math.log(x) } - sylnx = sigma(xys) { |x, y| y * Math.log(x) } - sy = sigma(xys) { |_, y| y } - - c = n * slnx2 - slnx ** 2 - b = ( n * sylnx - sy * slnx ) / c - a = (sy - b * slnx) / n - - return a, b, fit_error(xys) { |x| a + b * Math.log(x) } - end - - ## - # Fits the functional form: a + bx. - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFitting.html - - def fit_linear xs, ys - n = xs.size - xys = xs.zip(ys) - sx = sigma xs - sy = sigma ys - sx2 = sigma(xs) { |x| x ** 2 } - sxy = sigma(xys) { |x, y| x * y } - - c = n * sx2 - sx**2 - a = (sy * sx2 - sx * sxy) / c - b = ( n * sxy - sx * sy ) / c - - return a, b, fit_error(xys) { |x| a + b * x } - end - - ## - # To fit a functional form: y = ax^b. - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html - - def fit_power xs, ys - n = xs.size - xys = xs.zip(ys) - slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } - slnx = sigma(xs) { |x | Math.log(x) } - slny = sigma(ys) { | y| Math.log(y) } - slnx2 = sigma(xs) { |x | Math.log(x) ** 2 } - - b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2) - a = (slny - b * slnx) / n - - return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } - end - - ## - # Enumerates over +enum+ mapping +block+ if given, returning the - # sum of the result. Eg: - # - # sigma([1, 2, 3]) # => 1 + 2 + 3 => 6 - # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14 - - def sigma enum, &block - enum = enum.map(&block) if block - enum.inject { |sum, n| sum + n } - end - - ## - # Returns a proc that calls the specified fit method and asserts - # that the error is within a tolerable threshold. - - def validation_for_fit msg, threshold - proc do |range, times| - a, b, rr = send "fit_#{msg}", range, times - assert_operator rr, :>=, threshold - [a, b, rr] - end - end - end -end - -module Minitest - ## - # The spec version of Minitest::Benchmark. - - class BenchSpec < Benchmark - extend Minitest::Spec::DSL - - ## - # This is used to define a new benchmark method. You usually don't - # use this directly and is intended for those needing to write new - # performance curve fits (eg: you need a specific polynomial fit). - # - # See ::bench_performance_linear for an example of how to use this. - - def self.bench name, &block - define_method "bench_#{name.gsub(/\W+/, "_")}", &block - end - - ## - # Specifies the ranges used for benchmarking for that class. - # - # bench_range do - # bench_exp(2, 16, 2) - # end - # - # See Minitest::Benchmark#bench_range for more details. - - def self.bench_range &block - return super unless block - - meta = (class << self; self; end) - meta.send :define_method, "bench_range", &block - end - - ## - # Create a benchmark that verifies that the performance is linear. - # - # describe "my class Bench" do - # bench_performance_linear "fast_algorithm", 0.9999 do |n| - # @obj.fast_algorithm(n) - # end - # end - - def self.bench_performance_linear name, threshold = 0.99, &work - bench name do - assert_performance_linear threshold, &work - end - end - - ## - # Create a benchmark that verifies that the performance is constant. - # - # describe "my class Bench" do - # bench_performance_constant "zoom_algorithm!" do |n| - # @obj.zoom_algorithm!(n) - # end - # end - - def self.bench_performance_constant name, threshold = 0.99, &work - bench name do - assert_performance_constant threshold, &work - end - end - - ## - # Create a benchmark that verifies that the performance is exponential. - # - # describe "my class Bench" do - # bench_performance_exponential "algorithm" do |n| - # @obj.algorithm(n) - # end - # end - - def self.bench_performance_exponential name, threshold = 0.99, &work - bench name do - assert_performance_exponential threshold, &work - end - end - - - ## - # Create a benchmark that verifies that the performance is logarithmic. - # - # describe "my class Bench" do - # bench_performance_logarithmic "algorithm" do |n| - # @obj.algorithm(n) - # end - # end - - def self.bench_performance_logarithmic name, threshold = 0.99, &work - bench name do - assert_performance_logarithmic threshold, &work - end - end - - ## - # Create a benchmark that verifies that the performance is power. - # - # describe "my class Bench" do - # bench_performance_power "algorithm" do |n| - # @obj.algorithm(n) - # end - # end - - def self.bench_performance_power name, threshold = 0.99, &work - bench name do - assert_performance_power threshold, &work - end - end - end - - Minitest::Spec.register_spec_type(/Bench(mark)?$/, Minitest::BenchSpec) -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/expectations.rb b/ruby/gems/minitest-5.13.0/lib/minitest/expectations.rb deleted file mode 100644 index ede40ee81..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/expectations.rb +++ /dev/null @@ -1,302 +0,0 @@ -## -# It's where you hide your "assertions". -# -# Please note, because of the way that expectations are implemented, -# all expectations (eg must_equal) are dependent upon a thread local -# variable +:current_spec+. If your specs rely on mixing threads into -# the specs themselves, you're better off using assertions or the new -# _(value) wrapper. For example: -# -# it "should still work in threads" do -# my_threaded_thingy do -# (1+1).must_equal 2 # bad -# assert_equal 2, 1+1 # good -# _(1 + 1).must_equal 2 # good -# value(1 + 1).must_equal 2 # good, also #expect -# end -# end - -module Minitest::Expectations - - ## - # See Minitest::Assertions#assert_empty. - # - # collection.must_be_empty - # - # :method: must_be_empty - - infect_an_assertion :assert_empty, :must_be_empty, :unary - - ## - # See Minitest::Assertions#assert_equal - # - # a.must_equal b - # - # :method: must_equal - - infect_an_assertion :assert_equal, :must_equal - - ## - # See Minitest::Assertions#assert_in_delta - # - # n.must_be_close_to m [, delta] - # - # :method: must_be_close_to - - infect_an_assertion :assert_in_delta, :must_be_close_to - - alias :must_be_within_delta :must_be_close_to # :nodoc: - - ## - # See Minitest::Assertions#assert_in_epsilon - # - # n.must_be_within_epsilon m [, epsilon] - # - # :method: must_be_within_epsilon - - infect_an_assertion :assert_in_epsilon, :must_be_within_epsilon - - ## - # See Minitest::Assertions#assert_includes - # - # collection.must_include obj - # - # :method: must_include - - infect_an_assertion :assert_includes, :must_include, :reverse - - ## - # See Minitest::Assertions#assert_instance_of - # - # obj.must_be_instance_of klass - # - # :method: must_be_instance_of - - infect_an_assertion :assert_instance_of, :must_be_instance_of - - ## - # See Minitest::Assertions#assert_kind_of - # - # obj.must_be_kind_of mod - # - # :method: must_be_kind_of - - infect_an_assertion :assert_kind_of, :must_be_kind_of - - ## - # See Minitest::Assertions#assert_match - # - # a.must_match b - # - # :method: must_match - - infect_an_assertion :assert_match, :must_match - - ## - # See Minitest::Assertions#assert_nil - # - # obj.must_be_nil - # - # :method: must_be_nil - - infect_an_assertion :assert_nil, :must_be_nil, :unary - - ## - # See Minitest::Assertions#assert_operator - # - # n.must_be :<=, 42 - # - # This can also do predicates: - # - # str.must_be :empty? - # - # :method: must_be - - infect_an_assertion :assert_operator, :must_be, :reverse - - ## - # See Minitest::Assertions#assert_output - # - # proc { ... }.must_output out_or_nil [, err] - # - # :method: must_output - - infect_an_assertion :assert_output, :must_output, :block - - ## - # See Minitest::Assertions#assert_raises - # - # proc { ... }.must_raise exception - # - # :method: must_raise - - infect_an_assertion :assert_raises, :must_raise, :block - - ## - # See Minitest::Assertions#assert_respond_to - # - # obj.must_respond_to msg - # - # :method: must_respond_to - - infect_an_assertion :assert_respond_to, :must_respond_to, :reverse - - ## - # See Minitest::Assertions#assert_same - # - # a.must_be_same_as b - # - # :method: must_be_same_as - - infect_an_assertion :assert_same, :must_be_same_as - - ## - # See Minitest::Assertions#assert_silent - # - # proc { ... }.must_be_silent - # - # :method: must_be_silent - - infect_an_assertion :assert_silent, :must_be_silent, :block - - ## - # See Minitest::Assertions#assert_throws - # - # proc { ... }.must_throw sym - # - # :method: must_throw - - infect_an_assertion :assert_throws, :must_throw, :block - - ## - # See Minitest::Assertions#assert_path_exists - # - # _(some_path).path_must_exist - # - # :method: path_must_exist - - infect_an_assertion :assert_path_exists, :path_must_exist, :unary - - ## - # See Minitest::Assertions#refute_path_exists - # - # _(some_path).path_wont_exist - # - # :method: path_wont_exist - - infect_an_assertion :refute_path_exists, :path_wont_exist, :unary - - ## - # See Minitest::Assertions#refute_empty - # - # collection.wont_be_empty - # - # :method: wont_be_empty - - infect_an_assertion :refute_empty, :wont_be_empty, :unary - - ## - # See Minitest::Assertions#refute_equal - # - # a.wont_equal b - # - # :method: wont_equal - - infect_an_assertion :refute_equal, :wont_equal - - ## - # See Minitest::Assertions#refute_in_delta - # - # n.wont_be_close_to m [, delta] - # - # :method: wont_be_close_to - - infect_an_assertion :refute_in_delta, :wont_be_close_to - - alias :wont_be_within_delta :wont_be_close_to # :nodoc: - - ## - # See Minitest::Assertions#refute_in_epsilon - # - # n.wont_be_within_epsilon m [, epsilon] - # - # :method: wont_be_within_epsilon - - infect_an_assertion :refute_in_epsilon, :wont_be_within_epsilon - - ## - # See Minitest::Assertions#refute_includes - # - # collection.wont_include obj - # - # :method: wont_include - - infect_an_assertion :refute_includes, :wont_include, :reverse - - ## - # See Minitest::Assertions#refute_instance_of - # - # obj.wont_be_instance_of klass - # - # :method: wont_be_instance_of - - infect_an_assertion :refute_instance_of, :wont_be_instance_of - - ## - # See Minitest::Assertions#refute_kind_of - # - # obj.wont_be_kind_of mod - # - # :method: wont_be_kind_of - - infect_an_assertion :refute_kind_of, :wont_be_kind_of - - ## - # See Minitest::Assertions#refute_match - # - # a.wont_match b - # - # :method: wont_match - - infect_an_assertion :refute_match, :wont_match - - ## - # See Minitest::Assertions#refute_nil - # - # obj.wont_be_nil - # - # :method: wont_be_nil - - infect_an_assertion :refute_nil, :wont_be_nil, :unary - - ## - # See Minitest::Assertions#refute_operator - # - # n.wont_be :<=, 42 - # - # This can also do predicates: - # - # str.wont_be :empty? - # - # :method: wont_be - - infect_an_assertion :refute_operator, :wont_be, :reverse - - ## - # See Minitest::Assertions#refute_respond_to - # - # obj.wont_respond_to msg - # - # :method: wont_respond_to - - infect_an_assertion :refute_respond_to, :wont_respond_to, :reverse - - ## - # See Minitest::Assertions#refute_same - # - # a.wont_be_same_as b - # - # :method: wont_be_same_as - - infect_an_assertion :refute_same, :wont_be_same_as -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/hell.rb b/ruby/gems/minitest-5.13.0/lib/minitest/hell.rb deleted file mode 100644 index 73c88acd7..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/hell.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "minitest/parallel" - -class Minitest::Test - parallelize_me! -end - -begin - require "minitest/proveit" -rescue LoadError - warn "NOTE: `gem install minitest-proveit` for even more hellish tests" -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/mock.rb b/ruby/gems/minitest-5.13.0/lib/minitest/mock.rb deleted file mode 100644 index 39cfc24e4..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/mock.rb +++ /dev/null @@ -1,240 +0,0 @@ -class MockExpectationError < StandardError; end # :nodoc: - -module Minitest # :nodoc: - - ## - # A simple and clean mock object framework. - # - # All mock objects are an instance of Mock - - class Mock - alias :__respond_to? :respond_to? - - overridden_methods = %w[ - === - class - inspect - instance_eval - instance_variables - object_id - public_send - respond_to_missing? - send - to_s - ] - - instance_methods.each do |m| - undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/ - end - - overridden_methods.map(&:to_sym).each do |method_id| - define_method method_id do |*args, &b| - if @expected_calls.key? method_id then - method_missing(method_id, *args, &b) - else - super(*args, &b) - end - end - end - - def initialize delegator = nil # :nodoc: - @delegator = delegator - @expected_calls = Hash.new { |calls, name| calls[name] = [] } - @actual_calls = Hash.new { |calls, name| calls[name] = [] } - end - - ## - # Expect that method +name+ is called, optionally with +args+ or a - # +blk+, and returns +retval+. - # - # @mock.expect(:meaning_of_life, 42) - # @mock.meaning_of_life # => 42 - # - # @mock.expect(:do_something_with, true, [some_obj, true]) - # @mock.do_something_with(some_obj, true) # => true - # - # @mock.expect(:do_something_else, true) do |a1, a2| - # a1 == "buggs" && a2 == :bunny - # end - # - # +args+ is compared to the expected args using case equality (ie, the - # '===' operator), allowing for less specific expectations. - # - # @mock.expect(:uses_any_string, true, [String]) - # @mock.uses_any_string("foo") # => true - # @mock.verify # => true - # - # @mock.expect(:uses_one_string, true, ["foo"]) - # @mock.uses_one_string("bar") # => raises MockExpectationError - # - # If a method will be called multiple times, specify a new expect for each one. - # They will be used in the order you define them. - # - # @mock.expect(:ordinal_increment, 'first') - # @mock.expect(:ordinal_increment, 'second') - # - # @mock.ordinal_increment # => 'first' - # @mock.ordinal_increment # => 'second' - # @mock.ordinal_increment # => raises MockExpectationError "No more expects available for :ordinal_increment" - # - - def expect name, retval, args = [], &blk - name = name.to_sym - - if block_given? - raise ArgumentError, "args ignored when block given" unless args.empty? - @expected_calls[name] << { :retval => retval, :block => blk } - else - raise ArgumentError, "args must be an array" unless Array === args - @expected_calls[name] << { :retval => retval, :args => args } - end - self - end - - def __call name, data # :nodoc: - case data - when Hash then - "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}" - else - data.map { |d| __call name, d }.join ", " - end - end - - ## - # Verify that all methods were called as expected. Raises - # +MockExpectationError+ if the mock object was not called as - # expected. - - def verify - @expected_calls.each do |name, expected| - actual = @actual_calls.fetch(name, nil) - raise MockExpectationError, "expected #{__call name, expected[0]}" unless actual - raise MockExpectationError, "expected #{__call name, expected[actual.size]}, got [#{__call name, actual}]" if - actual.size < expected.size - end - true - end - - def method_missing sym, *args, &block # :nodoc: - unless @expected_calls.key?(sym) then - if @delegator && @delegator.respond_to?(sym) - return @delegator.public_send(sym, *args, &block) - else - raise NoMethodError, "unmocked method %p, expected one of %p" % - [sym, @expected_calls.keys.sort_by(&:to_s)] - end - end - - index = @actual_calls[sym].length - expected_call = @expected_calls[sym][index] - - unless expected_call then - raise MockExpectationError, "No more expects available for %p: %p" % - [sym, args] - end - - expected_args, retval, val_block = - expected_call.values_at(:args, :retval, :block) - - if val_block then - # keep "verify" happy - @actual_calls[sym] << expected_call - - raise MockExpectationError, "mocked method %p failed block w/ %p" % - [sym, args] unless val_block.call(*args, &block) - - return retval - end - - if expected_args.size != args.size then - raise ArgumentError, "mocked method %p expects %d arguments, got %d" % - [sym, expected_args.size, args.size] - end - - zipped_args = expected_args.zip(args) - fully_matched = zipped_args.all? { |mod, a| - mod === a or mod == a - } - - unless fully_matched then - raise MockExpectationError, "mocked method %p called with unexpected arguments %p" % - [sym, args] - end - - @actual_calls[sym] << { - :retval => retval, - :args => zipped_args.map! { |mod, a| mod === a ? mod : a }, - } - - retval - end - - def respond_to? sym, include_private = false # :nodoc: - return true if @expected_calls.key? sym.to_sym - return true if @delegator && @delegator.respond_to?(sym, include_private) - __respond_to?(sym, include_private) - end - end -end - -module Minitest::Assertions - ## - # Assert that the mock verifies correctly. - - def assert_mock mock - assert mock.verify - end -end - -## -# Object extensions for Minitest::Mock. - -class Object - - ## - # Add a temporary stubbed method replacing +name+ for the duration - # of the +block+. If +val_or_callable+ responds to #call, then it - # returns the result of calling it, otherwise returns the value - # as-is. If stubbed method yields a block, +block_args+ will be - # passed along. Cleans up the stub at the end of the +block+. The - # method +name+ must exist before stubbing. - # - # def test_stale_eh - # obj_under_test = Something.new - # refute obj_under_test.stale? - # - # Time.stub :now, Time.at(0) do - # assert obj_under_test.stale? - # end - # end - # - - def stub name, val_or_callable, *block_args - new_name = "__minitest_stub__#{name}" - - metaclass = class << self; self; end - - if respond_to? name and not methods.map(&:to_s).include? name.to_s then - metaclass.send :define_method, name do |*args| - super(*args) - end - end - - metaclass.send :alias_method, new_name, name - - metaclass.send :define_method, name do |*args, &blk| - if val_or_callable.respond_to? :call then - val_or_callable.call(*args, &blk) - else - blk.call(*block_args) if blk - val_or_callable - end - end - - yield self - ensure - metaclass.send :undef_method, name - metaclass.send :alias_method, name, new_name - metaclass.send :undef_method, new_name - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/parallel.rb b/ruby/gems/minitest-5.13.0/lib/minitest/parallel.rb deleted file mode 100644 index 40ac709a3..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/parallel.rb +++ /dev/null @@ -1,70 +0,0 @@ -module Minitest - module Parallel #:nodoc: - - ## - # The engine used to run multiple tests in parallel. - - class Executor - - ## - # The size of the pool of workers. - - attr_reader :size - - ## - # Create a parallel test executor of with +size+ workers. - - def initialize size - @size = size - @queue = Queue.new - @pool = nil - end - - ## - # Start the executor - - def start - @pool = size.times.map { - Thread.new(@queue) do |queue| - Thread.current.abort_on_exception = true - while (job = queue.pop) - klass, method, reporter = job - reporter.synchronize { reporter.prerecord klass, method } - result = Minitest.run_one_method klass, method - reporter.synchronize { reporter.record result } - end - end - } - end - - ## - # Add a job to the queue - - def << work; @queue << work; end - - ## - # Shuts down the pool of workers by signalling them to quit and - # waiting for them all to finish what they're currently working - # on. - - def shutdown - size.times { @queue << nil } - @pool.each(&:join) - end - end - - module Test # :nodoc: - def _synchronize; Minitest::Test.io_lock.synchronize { yield }; end # :nodoc: - - module ClassMethods # :nodoc: - def run_one_method klass, method_name, reporter - Minitest.parallel_executor << [klass, method_name, reporter] - end - - def test_order - :parallel - end - end - end - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/pride.rb b/ruby/gems/minitest-5.13.0/lib/minitest/pride.rb deleted file mode 100644 index f3b8e474f..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/pride.rb +++ /dev/null @@ -1,4 +0,0 @@ -require "minitest" - -Minitest.load_plugins -Minitest::PrideIO.pride! diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/pride_plugin.rb b/ruby/gems/minitest-5.13.0/lib/minitest/pride_plugin.rb deleted file mode 100644 index aeef2b9c8..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/pride_plugin.rb +++ /dev/null @@ -1,142 +0,0 @@ -require "minitest" - -module Minitest - def self.plugin_pride_options opts, _options # :nodoc: - opts.on "-p", "--pride", "Pride. Show your testing pride!" do - PrideIO.pride! - end - end - - def self.plugin_pride_init options # :nodoc: - if PrideIO.pride? then - klass = ENV["TERM"] =~ /^xterm|-256color$/ ? PrideLOL : PrideIO - io = klass.new options[:io] - - self.reporter.reporters.grep(Minitest::Reporter).each do |rep| - rep.io = io if rep.io.tty? - end - end - end - - ## - # Show your testing pride! - - class PrideIO - ## - # Activate the pride plugin. Called from both -p option and minitest/pride - - def self.pride! - @pride = true - end - - ## - # Are we showing our testing pride? - - def self.pride? - @pride ||= false - end - - # Start an escape sequence - ESC = "\e[" - - # End the escape sequence - NND = "#{ESC}0m" - - # The IO we're going to pipe through. - attr_reader :io - - def initialize io # :nodoc: - @io = io - # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm - # also reference http://en.wikipedia.org/wiki/ANSI_escape_code - @colors ||= (31..36).to_a - @size = @colors.size - @index = 0 - end - - ## - # Wrap print to colorize the output. - - def print o - case o - when "." then - io.print pride o - when "E", "F" then - io.print "#{ESC}41m#{ESC}37m#{o}#{NND}" - when "S" then - io.print pride o - else - io.print o - end - end - - def puts *o # :nodoc: - o.map! { |s| - s.to_s.sub(/Finished/) { - @index = 0 - "Fabulous run".split(//).map { |c| - pride(c) - }.join - } - } - - io.puts(*o) - end - - ## - # Color a string. - - def pride string - string = "*" if string == "." - c = @colors[@index % @size] - @index += 1 - "#{ESC}#{c}m#{string}#{NND}" - end - - def method_missing msg, *args # :nodoc: - io.send(msg, *args) - end - end - - ## - # If you thought the PrideIO was colorful... - # - # (Inspired by lolcat, but with clean math) - - class PrideLOL < PrideIO - PI_3 = Math::PI / 3 # :nodoc: - - def initialize io # :nodoc: - # walk red, green, and blue around a circle separated by equal thirds. - # - # To visualize, type this into wolfram-alpha: - # - # plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3) - - # 6 has wide pretty gradients. 3 == lolcat, about half the width - @colors = (0...(6 * 7)).map { |n| - n *= 1.0 / 6 - r = (3 * Math.sin(n ) + 3).to_i - g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i - b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i - - # Then we take rgb and encode them in a single number using base 6. - # For some mysterious reason, we add 16... to clear the bottom 4 bits? - # Yes... they're ugly. - - 36 * r + 6 * g + b + 16 - } - - super - end - - ## - # Make the string even more colorful. Damnit. - - def pride string - c = @colors[@index % @size] - @index += 1 - "#{ESC}38;5;#{c}m#{string}#{NND}" - end - end -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/spec.rb b/ruby/gems/minitest-5.13.0/lib/minitest/spec.rb deleted file mode 100644 index 12f1975cf..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/spec.rb +++ /dev/null @@ -1,342 +0,0 @@ -require "minitest/test" - -class Module # :nodoc: - def infect_an_assertion meth, new_name, dont_flip = false # :nodoc: - block = dont_flip == :block - dont_flip = false if block - - # warn "%-22p -> %p %p" % [meth, new_name, dont_flip] - self.class_eval <<-EOM, __FILE__, __LINE__ + 1 - def #{new_name} *args - where = Minitest.filter_backtrace(caller).first - where = where.split(/:in /, 2).first # clean up noise - warn "DEPRECATED: global use of #{new_name} from #\{where}. Use _(obj).#{new_name} instead. This will fail in Minitest 6." - Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args) - end - EOM - - Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1 - def #{new_name} *args - raise "Calling ##{new_name} outside of test." unless ctx - case - when #{!!dont_flip} then - ctx.#{meth}(target, *args) - when #{block} && Proc === target then - ctx.#{meth}(*args, &target) - else - ctx.#{meth}(args.first, target, *args[1..-1]) - end - end - EOM - end -end - -Minitest::Expectation = Struct.new :target, :ctx # :nodoc: - -## -# Kernel extensions for minitest - -module Kernel - ## - # Describe a series of expectations for a given target +desc+. - # - # Defines a test class subclassing from either Minitest::Spec or - # from the surrounding describe's class. The surrounding class may - # subclass Minitest::Spec manually in order to easily share code: - # - # class MySpec < Minitest::Spec - # # ... shared code ... - # end - # - # class TestStuff < MySpec - # it "does stuff" do - # # shared code available here - # end - # describe "inner stuff" do - # it "still does stuff" do - # # ...and here - # end - # end - # end - # - # For more information on getting started with writing specs, see: - # - # http://www.rubyinside.com/a-minitestspec-tutorial-elegant-spec-style-testing-that-comes-with-ruby-5354.html - # - # For some suggestions on how to improve your specs, try: - # - # http://betterspecs.org - # - # but do note that several items there are debatable or specific to - # rspec. - # - # For more information about expectations, see Minitest::Expectations. - - def describe desc, *additional_desc, &block # :doc: - stack = Minitest::Spec.describe_stack - name = [stack.last, desc, *additional_desc].compact.join("::") - sclas = stack.last || if Class === self && kind_of?(Minitest::Spec::DSL) then - self - else - Minitest::Spec.spec_type desc, *additional_desc - end - - cls = sclas.create name, desc - - stack.push cls - cls.class_eval(&block) - stack.pop - cls - end - private :describe -end - -## -# Minitest::Spec -- The faster, better, less-magical spec framework! -# -# For a list of expectations, see Minitest::Expectations. - -class Minitest::Spec < Minitest::Test - - def self.current # :nodoc: - Thread.current[:current_spec] - end - - def initialize name # :nodoc: - super - Thread.current[:current_spec] = self - end - - ## - # Oh look! A Minitest::Spec::DSL module! Eat your heart out DHH. - - module DSL - ## - # Contains pairs of matchers and Spec classes to be used to - # calculate the superclass of a top-level describe. This allows for - # automatically customizable spec types. - # - # See: register_spec_type and spec_type - - TYPES = [[//, Minitest::Spec]] - - ## - # Register a new type of spec that matches the spec's description. - # This method can take either a Regexp and a spec class or a spec - # class and a block that takes the description and returns true if - # it matches. - # - # Eg: - # - # register_spec_type(/Controller$/, Minitest::Spec::Rails) - # - # or: - # - # register_spec_type(Minitest::Spec::RailsModel) do |desc| - # desc.superclass == ActiveRecord::Base - # end - - def register_spec_type *args, &block - if block then - matcher, klass = block, args.first - else - matcher, klass = *args - end - TYPES.unshift [matcher, klass] - end - - ## - # Figure out the spec class to use based on a spec's description. Eg: - # - # spec_type("BlahController") # => Minitest::Spec::Rails - - def spec_type desc, *additional - TYPES.find { |matcher, _klass| - if matcher.respond_to? :call then - matcher.call desc, *additional - else - matcher === desc.to_s - end - }.last - end - - def describe_stack # :nodoc: - Thread.current[:describe_stack] ||= [] - end - - def children # :nodoc: - @children ||= [] - end - - def nuke_test_methods! # :nodoc: - self.public_instance_methods.grep(/^test_/).each do |name| - self.send :undef_method, name - end - end - - ## - # Define a 'before' action. Inherits the way normal methods should. - # - # NOTE: +type+ is ignored and is only there to make porting easier. - # - # Equivalent to Minitest::Test#setup. - - def before _type = nil, &block - define_method :setup do - super() - self.instance_eval(&block) - end - end - - ## - # Define an 'after' action. Inherits the way normal methods should. - # - # NOTE: +type+ is ignored and is only there to make porting easier. - # - # Equivalent to Minitest::Test#teardown. - - def after _type = nil, &block - define_method :teardown do - self.instance_eval(&block) - super() - end - end - - ## - # Define an expectation with name +desc+. Name gets morphed to a - # proper test method name. For some freakish reason, people who - # write specs don't like class inheritance, so this goes way out of - # its way to make sure that expectations aren't inherited. - # - # This is also aliased to #specify and doesn't require a +desc+ arg. - # - # Hint: If you _do_ want inheritance, use minitest/test. You can mix - # and match between assertions and expectations as much as you want. - - def it desc = "anonymous", &block - block ||= proc { skip "(no tests defined)" } - - @specs ||= 0 - @specs += 1 - - name = "test_%04d_%s" % [ @specs, desc ] - - undef_klasses = self.children.reject { |c| c.public_method_defined? name } - - define_method name, &block - - undef_klasses.each do |undef_klass| - undef_klass.send :undef_method, name - end - - name - end - - ## - # Essentially, define an accessor for +name+ with +block+. - # - # Why use let instead of def? I honestly don't know. - - def let name, &block - name = name.to_s - pre, post = "let '#{name}' cannot ", ". Please use another name." - methods = Minitest::Spec.instance_methods.map(&:to_s) - %w[subject] - raise ArgumentError, "#{pre}begin with 'test'#{post}" if - name =~ /\Atest/ - raise ArgumentError, "#{pre}override a method in Minitest::Spec#{post}" if - methods.include? name - - define_method name do - @_memoized ||= {} - @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) } - end - end - - ## - # Another lazy man's accessor generator. Made even more lazy by - # setting the name for you to +subject+. - - def subject &block - let :subject, &block - end - - def create name, desc # :nodoc: - cls = Class.new(self) do - @name = name - @desc = desc - - nuke_test_methods! - end - - children << cls - - cls - end - - def name # :nodoc: - defined?(@name) ? @name : super - end - - def to_s # :nodoc: - name # Can't alias due to 1.8.7, not sure why - end - - attr_reader :desc # :nodoc: - alias :specify :it - - ## - # Rdoc... why are you so dumb? - - module InstanceMethods - ## - # Takes a value or a block and returns a value monad that has - # all of Expectations methods available to it. - # - # _(1 + 1).must_equal 2 - # - # And for blocks: - # - # _ { 1 + "1" }.must_raise TypeError - # - # This method of expectation-based testing is preferable to - # straight-expectation methods (on Object) because it stores its - # test context, bypassing our hacky use of thread-local variables. - # - # NOTE: At some point, the methods on Object will be deprecated - # and then removed. - # - # It is also aliased to #value and #expect for your aesthetic - # pleasure: - # - # _(1 + 1).must_equal 2 - # value(1 + 1).must_equal 2 - # expect(1 + 1).must_equal 2 - - def _ value = nil, &block - Minitest::Expectation.new block || value, self - end - - alias value _ - alias expect _ - - def before_setup # :nodoc: - super - Thread.current[:current_spec] = self - end - end - - def self.extended obj # :nodoc: - obj.send :include, InstanceMethods - end - end - - extend DSL - - TYPES = DSL::TYPES # :nodoc: -end - -require "minitest/expectations" - -class Object # :nodoc: - include Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"] -end diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/test.rb b/ruby/gems/minitest-5.13.0/lib/minitest/test.rb deleted file mode 100644 index 0993bc491..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/test.rb +++ /dev/null @@ -1,220 +0,0 @@ -require "minitest" unless defined? Minitest::Runnable - -module Minitest - ## - # Subclass Test to create your own tests. Typically you'll want a - # Test subclass per implementation class. - # - # See Minitest::Assertions - - class Test < Runnable - require "minitest/assertions" - include Minitest::Assertions - include Minitest::Reportable - - def class_name # :nodoc: - self.class.name # for Minitest::Reportable - end - - PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc: - - # :stopdoc: - class << self; attr_accessor :io_lock; end - self.io_lock = Mutex.new - # :startdoc: - - ## - # Call this at the top of your tests when you absolutely - # positively need to have ordered tests. In doing so, you're - # admitting that you suck and your tests are weak. - - def self.i_suck_and_my_tests_are_order_dependent! - class << self - undef_method :test_order if method_defined? :test_order - define_method :test_order do :alpha end - end - end - - ## - # Make diffs for this Test use #pretty_inspect so that diff - # in assert_equal can have more details. NOTE: this is much slower - # than the regular inspect but much more usable for complex - # objects. - - def self.make_my_diffs_pretty! - require "pp" - - define_method :mu_pp, &:pretty_inspect - end - - ## - # Call this at the top of your tests when you want to run your - # tests in parallel. In doing so, you're admitting that you rule - # and your tests are awesome. - - def self.parallelize_me! - include Minitest::Parallel::Test - extend Minitest::Parallel::Test::ClassMethods - end - - ## - # Returns all instance methods starting with "test_". Based on - # #test_order, the methods are either sorted, randomized - # (default), or run in parallel. - - def self.runnable_methods - methods = methods_matching(/^test_/) - - case self.test_order - when :random, :parallel then - max = methods.size - methods.sort.sort_by { rand max } - when :alpha, :sorted then - methods.sort - else - raise "Unknown test_order: #{self.test_order.inspect}" - end - end - - ## - # Defines the order to run tests (:random by default). Override - # this or use a convenience method to change it for your tests. - - def self.test_order - :random - end - - TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc: - - ## - # Runs a single test with setup/teardown hooks. - - def run - with_info_handler do - time_it do - capture_exceptions do - before_setup; setup; after_setup - - self.send self.name - end - - TEARDOWN_METHODS.each do |hook| - capture_exceptions do - self.send hook - end - end - end - end - - Result.from self # per contract - end - - ## - # Provides before/after hooks for setup and teardown. These are - # meant for library writers, NOT for regular test authors. See - # #before_setup for an example. - - module LifecycleHooks - - ## - # Runs before every test, before setup. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # As a simplistic example: - # - # module MyMinitestPlugin - # def before_setup - # super - # # ... stuff to do before setup is run - # end - # - # def after_setup - # # ... stuff to do after setup is run - # super - # end - # - # def before_teardown - # super - # # ... stuff to do before teardown is run - # end - # - # def after_teardown - # # ... stuff to do after teardown is run - # super - # end - # end - # - # class MiniTest::Test - # include MyMinitestPlugin - # end - - def before_setup; end - - ## - # Runs before every test. Use this to set up before each test - # run. - - def setup; end - - ## - # Runs before every test, after setup. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def after_setup; end - - ## - # Runs after every test, before teardown. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def before_teardown; end - - ## - # Runs after every test. Use this to clean up after each test - # run. - - def teardown; end - - ## - # Runs after every test, after teardown. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def after_teardown; end - end # LifecycleHooks - - def capture_exceptions # :nodoc: - yield - rescue *PASSTHROUGH_EXCEPTIONS - raise - rescue Assertion => e - self.failures << e - rescue Exception => e - self.failures << UnexpectedError.new(e) - end - - def with_info_handler &block # :nodoc: - t0 = Minitest.clock_time - - handler = lambda do - warn "\nCurrent: %s#%s %.2fs" % [self.class, self.name, Minitest.clock_time - t0] - end - - self.class.on_signal ::Minitest.info_signal, handler, &block - end - - include LifecycleHooks - include Guard - extend Guard - end # Test -end - -require "minitest/unit" unless defined?(MiniTest) # compatibility layer only diff --git a/ruby/gems/minitest-5.13.0/lib/minitest/unit.rb b/ruby/gems/minitest-5.13.0/lib/minitest/unit.rb deleted file mode 100644 index 9a4eadff1..000000000 --- a/ruby/gems/minitest-5.13.0/lib/minitest/unit.rb +++ /dev/null @@ -1,45 +0,0 @@ -# :stopdoc: - -unless defined?(Minitest) then - # all of this crap is just to avoid circular requires and is only - # needed if a user requires "minitest/unit" directly instead of - # "minitest/autorun", so we also warn - - from = caller.reject { |s| s =~ /rubygems/ }.join("\n ") - warn "Warning: you should require 'minitest/autorun' instead." - warn %(Warning: or add 'gem "minitest"' before 'require "minitest/autorun"') - warn "From:\n #{from}" - - module Minitest; end - MiniTest = Minitest # prevents minitest.rb from requiring back to us - require "minitest" -end - -MiniTest = Minitest unless defined?(MiniTest) - -module Minitest - class Unit - VERSION = Minitest::VERSION - class TestCase < Minitest::Test - def self.inherited klass # :nodoc: - from = caller.first - warn "MiniTest::Unit::TestCase is now Minitest::Test. From #{from}" - super - end - end - - def self.autorun # :nodoc: - from = caller.first - warn "MiniTest::Unit.autorun is now Minitest.autorun. From #{from}" - Minitest.autorun - end - - def self.after_tests &b # :nodoc: - from = caller.first - warn "MiniTest::Unit.after_tests is now Minitest.after_run. From #{from}" - Minitest.after_run(&b) - end - end -end - -# :startdoc: diff --git a/ruby/gems/minitest-5.13.0/minitest.gemspec b/ruby/gems/minitest-5.13.0/minitest.gemspec deleted file mode 100644 index 627b96062..000000000 --- a/ruby/gems/minitest-5.13.0/minitest.gemspec +++ /dev/null @@ -1,35 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: minitest 5.13.0 ruby lib - -Gem::Specification.new do |s| - s.name = "minitest".freeze - s.version = "5.13.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib".freeze] - s.authors = ["Ryan Davis".freeze] - s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDPjCCAiagAwIBAgIBAzANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu\nZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB\nGRYDY29tMB4XDTE4MTIwNDIxMzAxNFoXDTE5MTIwNDIxMzAxNFowRTETMBEGA1UE\nAwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS\nJomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda\nb9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx\ntaCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT\noOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh\nGiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt\nqhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV\ngBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw\nHQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBCwUAA4IB\nAQCbJwLmpJR2PomLU+Zzw3KRzH/hbyUWc/ftru71AopZ1fy4iY9J/BW5QYKVYwbP\nV0FSBWtvfI/RdwfKGtuGhPKECZgmLieGuZ3XCc09qPu1bdg7i/tu1p0t0c6163ku\nnDMDIC/t/DAFK0TY9I3HswuyZGbLW7rgF0DmiuZdN/RPhHq2pOLMLXJmFclCb/im\n9yToml/06TJdUJ5p64mkBs0TzaK66DIB1Smd3PdtfZqoRV+EwaXMdx0Hb3zdR1JR\nEm82dBUFsipwMLCYj39kcyHWAxyl6Ae1Cn9r/ItVBCxoeFdrHjfavnrIEoXUt4bU\nUfBugfLD19bu3nvL+zTAGx/U\n-----END CERTIFICATE-----\n".freeze] - s.date = "2019-10-30" - s.description = "minitest provides a complete suite of testing facilities supporting\nTDD, BDD, mocking, and benchmarking.\n\n \"I had a class with Jim Weirich on testing last week and we were\n allowed to choose our testing frameworks. Kirk Haines and I were\n paired up and we cracked open the code for a few test\n frameworks...\n\n I MUST say that minitest is *very* readable / understandable\n compared to the 'other two' options we looked at. Nicely done and\n thank you for helping us keep our mental sanity.\"\n\n -- Wayne E. Seguin\n\nminitest/test is a small and incredibly fast unit testing framework.\nIt provides a rich set of assertions to make your tests clean and\nreadable.\n\nminitest/spec is a functionally complete spec engine. It hooks onto\nminitest/test and seamlessly bridges test assertions over to spec\nexpectations.\n\nminitest/benchmark is an awesome way to assert the performance of your\nalgorithms in a repeatable manner. Now you can assert that your newb\nco-worker doesn't replace your linear algorithm with an exponential\none!\n\nminitest/mock by Steven Baker, is a beautifully tiny mock (and stub)\nobject framework.\n\nminitest/pride shows pride in testing and adds coloring to your test\noutput. I guess it is an example of how to write IO pipes too. :P\n\nminitest/test is meant to have a clean implementation for language\nimplementors that need a minimal set of methods to bootstrap a working\ntest suite. For example, there is no magic involved for test-case\ndiscovery.\n\n \"Again, I can't praise enough the idea of a testing/specing\n framework that I can actually read in full in one sitting!\"\n\n -- Piotr Szotkowski\n\nComparing to rspec:\n\n rspec is a testing DSL. minitest is ruby.\n\n -- Adam Hawkins, \"Bow Before MiniTest\"\n\nminitest doesn't reinvent anything that ruby already provides, like:\nclasses, modules, inheritance, methods. This means you only have to\nlearn ruby to use minitest and all of your regular OO practices like\nextract-method refactorings still apply.".freeze - s.email = ["ryand-ruby@zenspider.com".freeze] - s.extra_rdoc_files = ["History.rdoc".freeze, "Manifest.txt".freeze, "README.rdoc".freeze] - s.files = [".autotest".freeze, "History.rdoc".freeze, "Manifest.txt".freeze, "README.rdoc".freeze, "Rakefile".freeze, "design_rationale.rb".freeze, "lib/hoe/minitest.rb".freeze, "lib/minitest.rb".freeze, "lib/minitest/assertions.rb".freeze, "lib/minitest/autorun.rb".freeze, "lib/minitest/benchmark.rb".freeze, "lib/minitest/expectations.rb".freeze, "lib/minitest/hell.rb".freeze, "lib/minitest/mock.rb".freeze, "lib/minitest/parallel.rb".freeze, "lib/minitest/pride.rb".freeze, "lib/minitest/pride_plugin.rb".freeze, "lib/minitest/spec.rb".freeze, "lib/minitest/test.rb".freeze, "lib/minitest/unit.rb".freeze, "test/minitest/metametameta.rb".freeze, "test/minitest/test_minitest_assertions.rb".freeze, "test/minitest/test_minitest_benchmark.rb".freeze, "test/minitest/test_minitest_mock.rb".freeze, "test/minitest/test_minitest_reporter.rb".freeze, "test/minitest/test_minitest_spec.rb".freeze, "test/minitest/test_minitest_test.rb".freeze] - s.homepage = "https://github.com/seattlerb/minitest".freeze - s.licenses = ["MIT".freeze] - s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] - s.required_ruby_version = Gem::Requirement.new("~> 2.2".freeze) - s.rubygems_version = "3.1.2".freeze - s.summary = "minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking".freeze - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_development_dependency(%q.freeze, [">= 4.0", "< 7"]) - s.add_development_dependency(%q.freeze, ["~> 3.18"]) - else - s.add_dependency(%q.freeze, [">= 4.0", "< 7"]) - s.add_dependency(%q.freeze, ["~> 3.18"]) - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/metametameta.rb b/ruby/gems/minitest-5.13.0/test/minitest/metametameta.rb deleted file mode 100644 index 02418d59c..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/metametameta.rb +++ /dev/null @@ -1,117 +0,0 @@ -require "tempfile" -require "stringio" -require "minitest/autorun" - -class Minitest::Test - def clean s - s.gsub(/^ {6}/, "") - end -end - -class FakeNamedTest < Minitest::Test - @@count = 0 - - def self.name - @fake_name ||= begin - @@count += 1 - "FakeNamedTest%02d" % @@count - end - end -end - -module MyModule; end -class AnError < StandardError; include MyModule; end - -class MetaMetaMetaTestCase < Minitest::Test - attr_accessor :reporter, :output, :tu - - def with_stderr err - old = $stderr - $stderr = err - yield - ensure - $stderr = old - end - - def run_tu_with_fresh_reporter flags = %w[--seed 42] - options = Minitest.process_args flags - - @output = StringIO.new("".encode('UTF-8')) - - self.reporter = Minitest::CompositeReporter.new - reporter << Minitest::SummaryReporter.new(@output, options) - reporter << Minitest::ProgressReporter.new(@output, options) - - with_stderr @output do - reporter.start - - yield(reporter) if block_given? - - @tus ||= [@tu] - @tus.each do |tu| - Minitest::Runnable.runnables.delete tu - - tu.run reporter, options - end - - reporter.report - end - end - - def first_reporter - reporter.reporters.first - end - - def assert_report expected, flags = %w[--seed 42], &block - header = clean <<-EOM - Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "} - - # Running: - - EOM - - run_tu_with_fresh_reporter flags, &block - - output = normalize_output @output.string.dup - - assert_equal header + expected, output - end - - def normalize_output output - output.sub!(/Finished in .*/, "Finished in 0.00") - output.sub!(/Loaded suite .*/, "Loaded suite blah") - - output.gsub!(/FakeNamedTest\d+/, "FakeNamedTestXX") - output.gsub!(/ = \d+.\d\d s = /, " = 0.00 s = ") - output.gsub!(/0x[A-Fa-f0-9]+/, "0xXXX") - output.gsub!(/ +$/, "") - - if windows? then - output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, "[FILE:LINE]") - output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in') - else - output.gsub!(/\[[^\]:]+:\d+\]/, "[FILE:LINE]") - output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in') - end - - output.gsub!(/( at )[^:]+:\d+/, '\1[FILE:LINE]') - - output - end - - def restore_env - old_value = ENV["MT_NO_SKIP_MSG"] - ENV.delete "MT_NO_SKIP_MSG" - - yield - ensure - ENV["MT_NO_SKIP_MSG"] = old_value - end - - def setup - super - srand 42 - Minitest::Test.reset - @tu = nil - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_assertions.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_assertions.rb deleted file mode 100644 index 0d9e03926..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_assertions.rb +++ /dev/null @@ -1,1437 +0,0 @@ -# encoding: UTF-8 - -require "minitest/autorun" - -if defined? Encoding then - e = Encoding.default_external - if e != Encoding::UTF_8 then - warn "" - warn "" - warn "NOTE: External encoding #{e} is not UTF-8. Tests WILL fail." - warn " Run tests with `RUBYOPT=-Eutf-8 rake` to avoid errors." - warn "" - warn "" - end -end - -SomeError = Class.new Exception - -unless defined? MyModule then - module MyModule; end - class AnError < StandardError; include MyModule; end -end - -class TestMinitestAssertions < Minitest::Test - # do not call parallelize_me! - teardown accesses @tc._assertions - # which is not threadsafe. Nearly every method in here is an - # assertion test so it isn't worth splitting it out further. - - RUBY18 = !defined? Encoding - - class DummyTest - include Minitest::Assertions - # include Minitest::Reportable # TODO: why do I really need this? - - attr_accessor :assertions, :failure - - def initialize - self.assertions = 0 - self.failure = nil - end - end - - def setup - super - - Minitest::Test.reset - - @tc = DummyTest.new - @zomg = "zomg ponies!" # TODO: const - @assertion_count = 1 - end - - def teardown - assert_equal(@assertion_count, @tc.assertions, - "expected #{@assertion_count} assertions to be fired during the test, not #{@tc.assertions}") - end - - def assert_deprecated name - dep = /DEPRECATED: #{name}. From #{__FILE__}:\d+(?::.*)?/ - dep = "" if $-w.nil? - - assert_output nil, dep do - yield - end - end - - def assert_triggered expected, klass = Minitest::Assertion - e = assert_raises klass do - yield - end - - msg = e.message.sub(/(---Backtrace---).*/m, '\1') - msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") - msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform - - assert_msg = Regexp === expected ? :assert_match : :assert_equal - self.send assert_msg, expected, msg - end - - def clean s - s.gsub(/^ {6,10}/, "") - end - - def non_verbose - orig_verbose = $VERBOSE - $VERBOSE = false - - yield - ensure - $VERBOSE = orig_verbose - end - - def test_assert - @assertion_count = 2 - - @tc.assert_equal true, @tc.assert(true), "returns true on success" - end - - def test_assert__triggered - assert_triggered "Expected false to be truthy." do - @tc.assert false - end - end - - def test_assert__triggered_message - assert_triggered @zomg do - @tc.assert false, @zomg - end - end - - def test_assert__triggered_lambda - assert_triggered "whoops" do - @tc.assert false, lambda { "whoops" } - end - end - - def test_assert_empty - @assertion_count = 2 - - @tc.assert_empty [] - end - - def test_assert_empty_triggered - @assertion_count = 2 - - assert_triggered "Expected [1] to be empty." do - @tc.assert_empty [1] - end - end - - def test_assert_equal - @tc.assert_equal 1, 1 - end - - def test_assert_equal_different_collection_array_hex_invisible - object1 = Object.new - object2 = Object.new - msg = "No visible difference in the Array#inspect output. - You should look at the implementation of #== on Array or its members. - [#]".gsub(/^ +/, "") - assert_triggered msg do - @tc.assert_equal [object1], [object2] - end - end - - def test_assert_equal_different_collection_hash_hex_invisible - h1, h2 = {}, {} - h1[1] = Object.new - h2[1] = Object.new - msg = "No visible difference in the Hash#inspect output. - You should look at the implementation of #== on Hash or its members. - {1=>#}".gsub(/^ +/, "") - - assert_triggered msg do - @tc.assert_equal h1, h2 - end - end - - def test_assert_equal_different_diff_deactivated - without_diff do - assert_triggered util_msg("haha" * 10, "blah" * 10) do - o1 = "haha" * 10 - o2 = "blah" * 10 - - @tc.assert_equal o1, o2 - end - end - end - - def test_assert_equal_different_message - assert_triggered "whoops.\nExpected: 1\n Actual: 2" do - @tc.assert_equal 1, 2, message { "whoops" } - end - end - - def test_assert_equal_different_lambda - assert_triggered "whoops.\nExpected: 1\n Actual: 2" do - @tc.assert_equal 1, 2, lambda { "whoops" } - end - end - - def test_assert_equal_different_hex - c = Class.new do - def initialize s; @name = s; end - end - - o1 = c.new "a" - o2 = c.new "b" - msg = clean <<-EOS - --- expected - +++ actual - @@ -1 +1 @@ - -#<#:0xXXXXXX @name=\"a\"> - +#<#:0xXXXXXX @name=\"b\"> - EOS - - assert_triggered msg do - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_hex_invisible - o1 = Object.new - o2 = Object.new - - msg = "No visible difference in the Object#inspect output. - You should look at the implementation of #== on Object or its members. - #".gsub(/^ +/, "") - - assert_triggered msg do - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long - msg = "--- expected - +++ actual - @@ -1 +1 @@ - -\"hahahahahahahahahahahahahahahahahahahaha\" - +\"blahblahblahblahblahblahblahblahblahblah\" - ".gsub(/^ +/, "") - - assert_triggered msg do - o1 = "haha" * 10 - o2 = "blah" * 10 - - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long_invisible - msg = "No visible difference in the String#inspect output. - You should look at the implementation of #== on String or its members. - \"blahblahblahblahblahblahblahblahblahblah\"".gsub(/^ +/, "") - - assert_triggered msg do - o1 = "blah" * 10 - o2 = "blah" * 10 - def o1.== _ - false - end - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long_msg - msg = "message. - --- expected - +++ actual - @@ -1 +1 @@ - -\"hahahahahahahahahahahahahahahahahahahaha\" - +\"blahblahblahblahblahblahblahblahblahblah\" - ".gsub(/^ +/, "") - - assert_triggered msg do - o1 = "haha" * 10 - o2 = "blah" * 10 - @tc.assert_equal o1, o2, "message" - end - end - - def test_assert_equal_different_short - assert_triggered util_msg(1, 2) do - @tc.assert_equal 1, 2 - end - end - - def test_assert_equal_different_short_msg - assert_triggered util_msg(1, 2, "message") do - @tc.assert_equal 1, 2, "message" - end - end - - def test_assert_equal_different_short_multiline - msg = "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n \"a\n-b\"\n+c\"\n" - assert_triggered msg do - @tc.assert_equal "a\nb", "a\nc" - end - end - - def test_assert_equal_does_not_allow_lhs_nil - if Minitest::VERSION =~ /^6/ then - warn "Time to strip the MT5 test" - - @assertion_count += 1 - assert_triggered(/Use assert_nil if expecting nil/) do - @tc.assert_equal nil, nil - end - else - err_re = /Use assert_nil if expecting nil from .*test_minitest_\w+.rb/ - err_re = "" if $-w.nil? - - assert_output "", err_re do - @tc.assert_equal nil, nil - end - end - end - - def test_assert_equal_does_not_allow_lhs_nil_triggered - assert_triggered "Expected: nil\n Actual: false" do - @tc.assert_equal nil, false - end - end - - def test_assert_equal_string_bug791 - exp = <<-'EOF'.gsub(/^ {10}/, "") # note single quotes - --- expected - +++ actual - @@ -1,2 +1 @@ - -"\\n - -" - +"\\\" - EOF - - exp = "Expected: \"\\\\n\"\n Actual: \"\\\\\"" - assert_triggered exp do - @tc.assert_equal "\\n", "\\" - end - end - - def test_assert_equal_string_both_escaped_unescaped_newlines - msg = <<-EOM.gsub(/^ {10}/, "") - --- expected - +++ actual - @@ -1,2 +1 @@ - -\"A\\n - -B\" - +\"A\\n\\\\nB\" - EOM - - assert_triggered msg do - exp = "A\\nB" - act = "A\n\\nB" - - @tc.assert_equal exp, act - end - end - - def test_assert_equal_string_encodings - msg = <<-EOM.gsub(/^ {10}/, "") - --- expected - +++ actual - @@ -1,3 +1,3 @@ - -# encoding: UTF-8 - -# valid: false - +# encoding: ASCII-8BIT - +# valid: true - "bad-utf8-\\xF1.txt" - EOM - - assert_triggered msg do - x = "bad-utf8-\xF1.txt" - y = x.dup.force_encoding "binary" # TODO: switch to .b when 1.9 dropped - @tc.assert_equal x, y - end - end unless RUBY18 - - def test_assert_equal_string_encodings_both_different - msg = <<-EOM.gsub(/^ {10}/, "") - --- expected - +++ actual - @@ -1,3 +1,3 @@ - -# encoding: US-ASCII - -# valid: false - +# encoding: ASCII-8BIT - +# valid: true - "bad-utf8-\\xF1.txt" - EOM - - assert_triggered msg do - x = "bad-utf8-\xF1.txt".force_encoding "ASCII" - y = x.dup.force_encoding "binary" # TODO: switch to .b when 1.9 dropped - @tc.assert_equal x, y - end - end unless RUBY18 - - def test_assert_equal_unescape_newlines - msg = <<-'EOM'.gsub(/^ {10}/, "") # NOTE single quotes on heredoc - --- expected - +++ actual - @@ -1,2 +1,2 @@ - -"hello - +"hello\n - world" - EOM - - assert_triggered msg do - exp = "hello\nworld" - act = 'hello\nworld' # notice single quotes - - @tc.assert_equal exp, act - end - end - - def test_assert_in_delta - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 - end - - def test_assert_in_delta_triggered - x = "1.0e-06" - assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 - end - end - - def test_assert_in_epsilon - @assertion_count = 10 - - @tc.assert_in_epsilon 10_000, 9991 - @tc.assert_in_epsilon 9991, 10_000 - @tc.assert_in_epsilon 1.0, 1.001 - @tc.assert_in_epsilon 1.001, 1.0 - - @tc.assert_in_epsilon 10_000, 9999.1, 0.0001 - @tc.assert_in_epsilon 9999.1, 10_000, 0.0001 - @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 - @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 - - @tc.assert_in_epsilon(-1, -1) - @tc.assert_in_epsilon(-10_000, -9991) - end - - def test_assert_in_epsilon_triggered - assert_triggered "Expected |10000 - 9990| (10) to be <= 9.99." do - @tc.assert_in_epsilon 10_000, 9990 - end - end - - def test_assert_in_epsilon_triggered_negative_case - x = (RUBY18 and not maglev?) ? "0.1" : "0.100000xxx" - y = "0.1" - assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do - @tc.assert_in_epsilon(-1.1, -1, 0.1) - end - end - - def test_assert_includes - @assertion_count = 2 - - @tc.assert_includes [true], true - end - - def test_assert_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises Minitest::Assertion do - @tc.assert_includes [true], false - end - - expected = "Expected [true] to include false." - assert_equal expected, e.message - end - - def test_assert_instance_of - @tc.assert_instance_of String, "blah" - end - - def test_assert_instance_of_triggered - assert_triggered 'Expected "blah" to be an instance of Array, not String.' do - @tc.assert_instance_of Array, "blah" - end - end - - def test_assert_kind_of - @tc.assert_kind_of String, "blah" - end - - def test_assert_kind_of_triggered - assert_triggered 'Expected "blah" to be a kind of Array, not String.' do - @tc.assert_kind_of Array, "blah" - end - end - - def test_assert_match - @assertion_count = 2 - @tc.assert_match(/\w+/, "blah blah blah") - end - - def test_assert_match_matchee_to_str - @assertion_count = 2 - - obj = Object.new - def obj.to_str; "blah" end - - @tc.assert_match "blah", obj - end - - def test_assert_match_matcher_object - @assertion_count = 2 - - pattern = Object.new - def pattern.=~ _; true end - - @tc.assert_match pattern, 5 - end - - def test_assert_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~ _; false end - def pattern.inspect; "[Object]" end - - assert_triggered "Expected [Object] to match 5." do - @tc.assert_match pattern, 5 - end - end - - def test_assert_match_triggered - @assertion_count = 2 - assert_triggered 'Expected /\d+/ to match "blah blah blah".' do - @tc.assert_match(/\d+/, "blah blah blah") - end - end - - def test_assert_nil - @tc.assert_nil nil - end - - def test_assert_nil_triggered - assert_triggered "Expected 42 to be nil." do - @tc.assert_nil 42 - end - end - - def test_assert_operator - @tc.assert_operator 2, :>, 1 - end - - def test_assert_operator_bad_object - bad = Object.new - def bad.== _; true end - - @tc.assert_operator bad, :equal?, bad - end - - def test_assert_operator_triggered - assert_triggered "Expected 2 to be < 1." do - @tc.assert_operator 2, :<, 1 - end - end - - def test_assert_output_both - @assertion_count = 2 - - @tc.assert_output "yay", "blah" do - print "yay" - $stderr.print "blah" - end - end - - def test_assert_output_both_regexps - @assertion_count = 4 - - @tc.assert_output(/y.y/, /bl.h/) do - print "yay" - $stderr.print "blah" - end - end - - def test_assert_output_err - @tc.assert_output nil, "blah" do - $stderr.print "blah" - end - end - - def test_assert_output_neither - @assertion_count = 0 - - @tc.assert_output do - # do nothing - end - end - - def test_assert_output_out - @tc.assert_output "blah" do - print "blah" - end - end - - def test_assert_output_triggered_both - assert_triggered util_msg("blah", "blah blah", "In stderr") do - @tc.assert_output "yay", "blah" do - print "boo" - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_err - assert_triggered util_msg("blah", "blah blah", "In stderr") do - @tc.assert_output nil, "blah" do - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_out - assert_triggered util_msg("blah", "blah blah", "In stdout") do - @tc.assert_output "blah" do - print "blah blah" - end - end - end - - def test_assert_output_without_block - assert_triggered "assert_output requires a block to capture output." do - @tc.assert_output "blah" - end - end - - def test_assert_predicate - @tc.assert_predicate "", :empty? - end - - def test_assert_predicate_triggered - assert_triggered 'Expected "blah" to be empty?.' do - @tc.assert_predicate "blah", :empty? - end - end - - def test_assert_raises - @tc.assert_raises RuntimeError do - raise "blah" - end - end - - def test_assert_raises_default - @tc.assert_raises do - raise StandardError, "blah" - end - end - - def test_assert_raises_default_triggered - e = assert_raises Minitest::Assertion do - @tc.assert_raises do - raise SomeError, "blah" - end - end - - expected = clean <<-EOM.chomp - [StandardError] exception expected, not - Class: - Message: <\"blah\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_default_triggered\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") - actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" - - assert_equal expected, actual - end - - def test_assert_raises_exit - @tc.assert_raises SystemExit do - exit 1 - end - end - - def test_assert_raises_module - @tc.assert_raises MyModule do - raise AnError - end - end - - def test_assert_raises_signals - @tc.assert_raises SignalException do - raise SignalException, :INT - end - end - - ## - # *sigh* This is quite an odd scenario, but it is from real (albeit - # ugly) test code in ruby-core: - - # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29259 - - def test_assert_raises_skip - @assertion_count = 0 - - assert_triggered "skipped", Minitest::Skip do - @tc.assert_raises ArgumentError do - begin - raise "blah" - rescue - skip "skipped" - end - end - end - end - - def test_assert_raises_subclass - @tc.assert_raises StandardError do - raise AnError - end - end - - def test_assert_raises_subclass_triggered - e = assert_raises Minitest::Assertion do - @tc.assert_raises SomeError do - raise AnError, "some message" - end - end - - expected = clean <<-EOM - [SomeError] exception expected, not - Class: - Message: <\"some message\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_subclass_triggered\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") - actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" - - assert_equal expected.chomp, actual - end - - def test_assert_raises_triggered_different - e = assert_raises Minitest::Assertion do - @tc.assert_raises RuntimeError do - raise SyntaxError, "icky" - end - end - - expected = clean <<-EOM.chomp - [RuntimeError] exception expected, not - Class: - Message: <\"icky\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_triggered_different\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") - actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" - - assert_equal expected, actual - end - - def test_assert_raises_triggered_different_msg - e = assert_raises Minitest::Assertion do - @tc.assert_raises RuntimeError, "XXX" do - raise SyntaxError, "icky" - end - end - - expected = clean <<-EOM - XXX. - [RuntimeError] exception expected, not - Class: - Message: <\"icky\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_triggered_different_msg\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") - actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" - - assert_equal expected.chomp, actual - end - - def test_assert_raises_triggered_none - e = assert_raises Minitest::Assertion do - @tc.assert_raises Minitest::Assertion do - # do nothing - end - end - - expected = "Minitest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_triggered_none_msg - e = assert_raises Minitest::Assertion do - @tc.assert_raises Minitest::Assertion, "XXX" do - # do nothing - end - end - - expected = "XXX.\nMinitest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_without_block - assert_triggered "assert_raises requires a block to capture errors." do - @tc.assert_raises StandardError - end - end - - def test_assert_respond_to - @tc.assert_respond_to "blah", :empty? - end - - def test_assert_respond_to_triggered - assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do - @tc.assert_respond_to "blah", :rawr! - end - end - - def test_assert_same - @assertion_count = 3 - - o = "blah" - @tc.assert_same 1, 1 - @tc.assert_same :blah, :blah - @tc.assert_same o, o - end - - def test_assert_same_triggered - @assertion_count = 2 - - assert_triggered "Expected 2 (oid=N) to be the same as 1 (oid=N)." do - @tc.assert_same 1, 2 - end - - s1 = "blah" - s2 = "blah" - - assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do - @tc.assert_same s1, s2 - end - end - - def test_assert_send - assert_deprecated :assert_send do - @tc.assert_send [1, :<, 2] - end - end - - def test_assert_send_bad - assert_deprecated :assert_send do - assert_triggered "Expected 1.>(*[2]) to return true." do - @tc.assert_send [1, :>, 2] - end - end - end - - def test_assert_silent - @assertion_count = 2 - - @tc.assert_silent do - # do nothing - end - end - - def test_assert_silent_triggered_err - assert_triggered util_msg("", "blah blah", "In stderr") do - @tc.assert_silent do - $stderr.print "blah blah" - end - end - end - - def test_assert_silent_triggered_out - @assertion_count = 2 - - assert_triggered util_msg("", "blah blah", "In stdout") do - @tc.assert_silent do - print "blah blah" - end - end - end - - def test_assert_throws - @tc.assert_throws :blah do - throw :blah - end - end - - def test_assert_throws_argument_exception - @tc.assert_raises ArgumentError do - @tc.assert_throws :blah do - raise ArgumentError - end - end - end - - def test_assert_throws_different - assert_triggered "Expected :blah to have been thrown, not :not_blah." do - @tc.assert_throws :blah do - throw :not_blah - end - end - end - - def test_assert_throws_name_error - @tc.assert_raises NameError do - @tc.assert_throws :blah do - raise NameError - end - end - end - - def test_assert_throws_unthrown - assert_triggered "Expected :blah to have been thrown." do - @tc.assert_throws :blah do - # do nothing - end - end - end - - def test_assert_path_exists - @tc.assert_path_exists __FILE__ - end - - def test_assert_path_exists_triggered - assert_triggered "Expected path 'blah' to exist." do - @tc.assert_path_exists "blah" - end - end - - def test_capture_io - @assertion_count = 0 - - non_verbose do - out, err = capture_io do - puts "hi" - $stderr.puts "bye!" - end - - assert_equal "hi\n", out - assert_equal "bye!\n", err - end - end - - def test_capture_subprocess_io - @assertion_count = 0 - - non_verbose do - out, err = capture_subprocess_io do - system("echo hi") - system("echo bye! 1>&2") - end - - assert_equal "hi\n", out - assert_equal "bye!", err.strip - end - end - - def test_class_asserts_match_refutes - @assertion_count = 0 - - methods = Minitest::Assertions.public_instance_methods - methods.map!(&:to_s) if Symbol === methods.first - - # These don't have corresponding refutes _on purpose_. They're - # useless and will never be added, so don't bother. - ignores = %w[assert_output assert_raises assert_send - assert_silent assert_throws assert_mock] - - # These are test/unit methods. I'm not actually sure why they're still here - ignores += %w[assert_no_match assert_not_equal assert_not_nil - assert_not_same assert_nothing_raised - assert_nothing_thrown assert_raise] - - asserts = methods.grep(/^assert/).sort - ignores - refutes = methods.grep(/^refute/).sort - ignores - - assert_empty refutes.map { |n| n.sub(/^refute/, "assert") } - asserts - assert_empty asserts.map { |n| n.sub(/^assert/, "refute") } - refutes - end - - def test_delta_consistency - @assertion_count = 2 - - @tc.assert_in_delta 0, 1, 1 - - assert_triggered "Expected |0 - 1| (1) to not be <= 1." do - @tc.refute_in_delta 0, 1, 1 - end - end - - def test_epsilon_consistency - @assertion_count = 2 - - @tc.assert_in_epsilon 1.0, 1.001 - - msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001." - assert_triggered msg do - @tc.refute_in_epsilon 1.0, 1.001 - end - end - - def test_fail_after - t = Time.now - y, m, d = t.year, t.month, t.day - - assert_silent do - @tc.fail_after y, m, d+1, "remove the deprecations" - end - - assert_triggered "remove the deprecations" do - @tc.fail_after y, m, d, "remove the deprecations" - end - end - - def test_flunk - assert_triggered "Epic Fail!" do - @tc.flunk - end - end - - def test_flunk_message - assert_triggered @zomg do - @tc.flunk @zomg - end - end - - def test_pass - @tc.pass - end - - def test_refute - @assertion_count = 2 - - @tc.assert_equal false, @tc.refute(false), "returns false on success" - end - - def test_refute_empty - @assertion_count = 2 - - @tc.refute_empty [1] - end - - def test_refute_empty_triggered - @assertion_count = 2 - - assert_triggered "Expected [] to not be empty." do - @tc.refute_empty [] - end - end - - def test_refute_equal - @tc.refute_equal "blah", "yay" - end - - def test_refute_equal_triggered - assert_triggered 'Expected "blah" to not be equal to "blah".' do - @tc.refute_equal "blah", "blah" - end - end - - def test_refute_in_delta - @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 - end - - def test_refute_in_delta_triggered - x = "0.1" - assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do - @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1 - end - end - - def test_refute_in_epsilon - @tc.refute_in_epsilon 10_000, 9990-1 - end - - def test_refute_in_epsilon_triggered - assert_triggered "Expected |10000 - 9990| (10) to not be <= 10.0." do - @tc.refute_in_epsilon 10_000, 9990 - flunk - end - end - - def test_refute_includes - @assertion_count = 2 - - @tc.refute_includes [true], false - end - - def test_refute_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises Minitest::Assertion do - @tc.refute_includes [true], true - end - - expected = "Expected [true] to not include true." - assert_equal expected, e.message - end - - def test_refute_instance_of - @tc.refute_instance_of Array, "blah" - end - - def test_refute_instance_of_triggered - assert_triggered 'Expected "blah" to not be an instance of String.' do - @tc.refute_instance_of String, "blah" - end - end - - def test_refute_kind_of - @tc.refute_kind_of Array, "blah" - end - - def test_refute_kind_of_triggered - assert_triggered 'Expected "blah" to not be a kind of String.' do - @tc.refute_kind_of String, "blah" - end - end - - def test_refute_match - @assertion_count = 2 - @tc.refute_match(/\d+/, "blah blah blah") - end - - def test_refute_match_matcher_object - @assertion_count = 2 - pattern = Object.new - def pattern.=~ _; false end - @tc.refute_match pattern, 5 - end - - def test_refute_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~ _; true end - def pattern.inspect; "[Object]" end - - assert_triggered "Expected [Object] to not match 5." do - @tc.refute_match pattern, 5 - end - end - - def test_refute_match_triggered - @assertion_count = 2 - assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do - @tc.refute_match(/\w+/, "blah blah blah") - end - end - - def test_refute_nil - @tc.refute_nil 42 - end - - def test_refute_nil_triggered - assert_triggered "Expected nil to not be nil." do - @tc.refute_nil nil - end - end - - def test_refute_operator - @tc.refute_operator 2, :<, 1 - end - - def test_refute_operator_bad_object - bad = Object.new - def bad.== _; true end - - @tc.refute_operator true, :equal?, bad - end - - def test_refute_operator_triggered - assert_triggered "Expected 2 to not be > 1." do - @tc.refute_operator 2, :>, 1 - end - end - - def test_refute_predicate - @tc.refute_predicate "42", :empty? - end - - def test_refute_predicate_triggered - assert_triggered 'Expected "" to not be empty?.' do - @tc.refute_predicate "", :empty? - end - end - - def test_refute_respond_to - @tc.refute_respond_to "blah", :rawr! - end - - def test_refute_respond_to_triggered - assert_triggered 'Expected "blah" to not respond to empty?.' do - @tc.refute_respond_to "blah", :empty? - end - end - - def test_refute_same - @tc.refute_same 1, 2 - end - - def test_refute_same_triggered - assert_triggered "Expected 1 (oid=N) to not be the same as 1 (oid=N)." do - @tc.refute_same 1, 1 - end - end - - def test_refute_path_exists - @tc.refute_path_exists "blah" - end - - def test_refute_path_exists_triggered - assert_triggered "Expected path '#{__FILE__}' to not exist." do - @tc.refute_path_exists __FILE__ - end - end - - def test_skip - @assertion_count = 0 - - assert_triggered "haha!", Minitest::Skip do - @tc.skip "haha!" - end - end - - def test_skip_until - @assertion_count = 0 - - t = Time.now - y, m, d = t.year, t.month, t.day - - assert_output "", /Stale skip_until \"not yet\" at .*?:\d+$/ do - @tc.skip_until y, m, d, "not yet" - end - - assert_triggered "not ready yet", Minitest::Skip do - @tc.skip_until y, m, d+1, "not ready yet" - end - end - - def util_msg exp, act, msg = nil - s = "Expected: #{exp.inspect}\n Actual: #{act.inspect}" - s = "#{msg}.\n#{s}" if msg - s - end - - def without_diff - old_diff = Minitest::Assertions.diff - Minitest::Assertions.diff = nil - - yield - ensure - Minitest::Assertions.diff = old_diff - end -end - -class TestMinitestAssertionHelpers < Minitest::Test - def assert_mu_pp exp, input, raw = false - act = mu_pp input - - if String === input && !raw then - assert_equal "\"#{exp}\"", act - else - assert_equal exp, act - end - end - - def assert_mu_pp_for_diff exp, input, raw = false - act = mu_pp_for_diff input - - if String === input && !raw then - assert_equal "\"#{exp}\"", act - else - assert_equal exp, act - end - end - - def test_diff_equal - msg = "No visible difference in the String#inspect output. - You should look at the implementation of #== on String or its members. - \"blahblahblahblahblahblahblahblahblahblah\"".gsub(/^ +/, "") - - o1 = "blah" * 10 - o2 = "blah" * 10 - def o1.== _ - false - end - - assert_equal msg, diff(o1, o2) - end - - def test_diff_str_mixed - msg = <<-'EOM'.gsub(/^ {10}/, "") # NOTE single quotes on heredoc - --- expected - +++ actual - @@ -1 +1 @@ - -"A\\n\nB" - +"A\n\\nB" - EOM - - exp = "A\\n\nB" - act = "A\n\\nB" - - assert_equal msg, diff(exp, act) - end - - def test_diff_str_multiline - msg = <<-'EOM'.gsub(/^ {10}/, "") # NOTE single quotes on heredoc - --- expected - +++ actual - @@ -1,2 +1,2 @@ - "A - -B" - +C" - EOM - - exp = "A\nB" - act = "A\nC" - - assert_equal msg, diff(exp, act) - end - - def test_diff_str_simple - msg = <<-'EOM'.gsub(/^ {10}/, "").chomp # NOTE single quotes on heredoc - Expected: "A" - Actual: "B" - EOM - - exp = "A" - act = "B" - - assert_equal msg, diff(exp, act) - end - - def test_message - assert_equal "blah2.", message { "blah2" }.call - assert_equal "blah2.", message("") { "blah2" }.call - assert_equal "blah1.\nblah2.", message(:blah1) { "blah2" }.call - assert_equal "blah1.\nblah2.", message("blah1") { "blah2" }.call - - message = proc { "blah1" } - assert_equal "blah1.\nblah2.", message(message) { "blah2" }.call - - message = message { "blah1" } - assert_equal "blah1.\nblah2.", message(message) { "blah2" }.call - end - - def test_message_deferred - var = nil - - msg = message { var = "blah" } - - assert_nil var - - msg.call - - assert_equal "blah", var - end - - def test_mu_pp - assert_mu_pp 42.inspect, 42 - assert_mu_pp %w[a b c].inspect, %w[a b c] - assert_mu_pp "A B", "A B" - assert_mu_pp "A\\nB", "A\nB" - assert_mu_pp "A\\\\nB", 'A\nB' # notice single quotes - end - - def test_mu_pp_for_diff - assert_mu_pp_for_diff "#", Object.new - assert_mu_pp_for_diff "A B", "A B" - assert_mu_pp_for_diff [1, 2, 3].inspect, [1, 2, 3] - assert_mu_pp_for_diff "A\nB", "A\nB" - end - - def test_mu_pp_for_diff_str_bad_encoding - str = "\666".force_encoding Encoding::UTF_8 - exp = "# encoding: UTF-8\n# valid: false\n\"\\xB6\"" - - assert_mu_pp_for_diff exp, str, :raw - end - - def test_mu_pp_for_diff_str_bad_encoding_both - str = "\666A\\n\nB".force_encoding Encoding::UTF_8 - exp = "# encoding: UTF-8\n# valid: false\n\"\\xB6A\\\\n\\nB\"" - - assert_mu_pp_for_diff exp, str, :raw - end - - def test_mu_pp_for_diff_str_encoding - str = "A\nB".b - exp = "# encoding: ASCII-8BIT\n# valid: true\n\"A\nB\"" - - assert_mu_pp_for_diff exp, str, :raw - end - - def test_mu_pp_for_diff_str_encoding_both - str = "A\\n\nB".b - exp = "# encoding: ASCII-8BIT\n# valid: true\n\"A\\\\n\\nB\"" - - assert_mu_pp_for_diff exp, str, :raw - end - - def test_mu_pp_for_diff_str_nerd - assert_mu_pp_for_diff "A\\nB\\\\nC", "A\nB\\nC" - assert_mu_pp_for_diff "\\nB\\\\nC", "\nB\\nC" - assert_mu_pp_for_diff "\\nB\\\\n", "\nB\\n" - assert_mu_pp_for_diff "\\n\\\\n", "\n\\n" - assert_mu_pp_for_diff "\\\\n\\n", "\\n\n" - assert_mu_pp_for_diff "\\\\nB\\n", "\\nB\n" - assert_mu_pp_for_diff "\\\\nB\\nC", "\\nB\nC" - assert_mu_pp_for_diff "A\\\\n\\nB", "A\\n\nB" - assert_mu_pp_for_diff "A\\n\\\\nB", "A\n\\nB" - assert_mu_pp_for_diff "\\\\n\\n", "\\n\n" - assert_mu_pp_for_diff "\\n\\\\n", "\n\\n" - end - - def test_mu_pp_for_diff_str_normal - assert_mu_pp_for_diff "", "" - assert_mu_pp_for_diff "A\\n\n", "A\\n" - assert_mu_pp_for_diff "A\\n\nB", "A\\nB" - assert_mu_pp_for_diff "A\n", "A\n" - assert_mu_pp_for_diff "A\nB", "A\nB" - assert_mu_pp_for_diff "\\n\n", "\\n" - assert_mu_pp_for_diff "\n", "\n" - assert_mu_pp_for_diff "\\n\nA", "\\nA" - assert_mu_pp_for_diff "\nA", "\nA" - end - - def test_mu_pp_str_bad_encoding - str = "\666".force_encoding Encoding::UTF_8 - exp = "# encoding: UTF-8\n# valid: false\n\"\\xB6\"" - - assert_mu_pp exp, str, :raw - end - - def test_mu_pp_str_encoding - str = "A\nB".b - exp = "# encoding: ASCII-8BIT\n# valid: true\n\"A\\nB\"" - - assert_mu_pp exp, str, :raw - end - - def test_mu_pp_str_immutable - printer = Class.new { extend Minitest::Assertions } - str = "test".freeze - assert_equal '"test"', printer.mu_pp(str) - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_benchmark.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_benchmark.rb deleted file mode 100644 index 88abf77c1..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_benchmark.rb +++ /dev/null @@ -1,137 +0,0 @@ -require "minitest/autorun" -require "minitest/benchmark" - -## -# Used to verify data: -# http://www.wolframalpha.com/examples/RegressionAnalysis.html - -class TestMinitestBenchmark < Minitest::Test - def test_cls_bench_exp - assert_equal [2, 4, 8, 16, 32], Minitest::Benchmark.bench_exp(2, 32, 2) - end - - def test_cls_bench_linear - assert_equal [2, 4, 6, 8, 10], Minitest::Benchmark.bench_linear(2, 10, 2) - end - - def test_cls_runnable_methods - assert_equal [], Minitest::Benchmark.runnable_methods - - c = Class.new(Minitest::Benchmark) do - def bench_blah - end - end - - assert_equal ["bench_blah"], c.runnable_methods - end - - def test_cls_bench_range - assert_equal [1, 10, 100, 1_000, 10_000], Minitest::Benchmark.bench_range - end - - def test_fit_exponential_clean - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = x.map { |n| 1.1 * Math.exp(2.1 * n) } - - assert_fit :exponential, x, y, 1.0, 1.1, 2.1 - end - - def test_fit_exponential_noisy - x = [1.0, 1.9, 2.6, 3.4, 5.0] - y = [12, 10, 8.2, 6.9, 5.9] - - # verified with Numbers and R - assert_fit :exponential, x, y, 0.95, 13.81148, -0.1820 - end - - def test_fit_logarithmic_clean - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = x.map { |n| 1.1 + 2.1 * Math.log(n) } - - assert_fit :logarithmic, x, y, 1.0, 1.1, 2.1 - end - - def test_fit_logarithmic_noisy - x = [1.0, 2.0, 3.0, 4.0, 5.0] - # Generated with - # y = x.map { |n| jitter = 0.999 + 0.002 * rand; (Math.log(n) ) * jitter } - y = [0.0, 0.6935, 1.0995, 1.3873, 1.6097] - - assert_fit :logarithmic, x, y, 0.95, 0, 1 - end - - def test_fit_constant_clean - x = (1..5).to_a - y = [5.0, 5.0, 5.0, 5.0, 5.0] - - assert_fit :linear, x, y, nil, 5.0, 0 - end - - def test_fit_constant_noisy - x = (1..5).to_a - y = [1.0, 1.2, 1.0, 0.8, 1.0] - - # verified in numbers and R - assert_fit :linear, x, y, nil, 1.12, -0.04 - end - - def test_fit_linear_clean - # y = m * x + b where m = 2.2, b = 3.1 - x = (1..5).to_a - y = x.map { |n| 2.2 * n + 3.1 } - - assert_fit :linear, x, y, 1.0, 3.1, 2.2 - end - - def test_fit_linear_noisy - x = [ 60, 61, 62, 63, 65] - y = [3.1, 3.6, 3.8, 4.0, 4.1] - - # verified in numbers and R - assert_fit :linear, x, y, 0.8315, -7.9635, 0.1878 - end - - def test_fit_power_clean - # y = A x ** B, where B = b and A = e ** a - # if, A = 1, B = 2, then - - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = [1.0, 4.0, 9.0, 16.0, 25.0] - - assert_fit :power, x, y, 1.0, 1.0, 2.0 - end - - def test_fit_power_noisy - # from www.engr.uidaho.edu/thompson/courses/ME330/lecture/least_squares.html - x = [10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35] - y = [95, 105, 125, 141, 173, 200, 253, 298, 385, 459, 602] - - # verified in numbers - assert_fit :power, x, y, 0.90, 2.6217, 1.4556 - - # income to % of households below income amount - # http://library.wolfram.com/infocenter/Conferences/6461/PowerLaws.nb - x = [15_000, 25_000, 35_000, 50_000, 75_000, 100_000] - y = [0.154, 0.283, 0.402, 0.55, 0.733, 0.843] - - # verified in numbers - assert_fit :power, x, y, 0.96, 3.119e-5, 0.8959 - end - - def assert_fit msg, x, y, fit, exp_a, exp_b - bench = Minitest::Benchmark.new :blah - - a, b, rr = bench.send "fit_#{msg}", x, y - - assert_operator rr, :>=, fit if fit - assert_in_delta exp_a, a - assert_in_delta exp_b, b - end -end - -describe "my class Bench" do - klass = self - it "should provide bench methods" do - klass.must_respond_to :bench - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_mock.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_mock.rb deleted file mode 100644 index 7128d5bf1..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_mock.rb +++ /dev/null @@ -1,872 +0,0 @@ -require "minitest/autorun" - -class TestMinitestMock < Minitest::Test - parallelize_me! - - def setup - @mock = Minitest::Mock.new.expect(:foo, nil) - @mock.expect(:meaning_of_life, 42) - end - - def test_create_stub_method - assert_nil @mock.foo - end - - def test_allow_return_value_specification - assert_equal 42, @mock.meaning_of_life - end - - def test_blow_up_if_not_called - @mock.foo - - util_verify_bad "expected meaning_of_life() => 42" - end - - def test_not_blow_up_if_everything_called - @mock.foo - @mock.meaning_of_life - - assert_mock @mock - end - - def test_allow_expectations_to_be_added_after_creation - @mock.expect(:bar, true) - assert @mock.bar - end - - def test_not_verify_if_new_expected_method_is_not_called - @mock.foo - @mock.meaning_of_life - @mock.expect(:bar, true) - - util_verify_bad "expected bar() => true" - end - - def test_blow_up_on_wrong_number_of_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - e = assert_raises ArgumentError do - @mock.sum - end - - assert_equal "mocked method :sum expects 2 arguments, got 0", e.message - end - - def test_return_mock_does_not_raise - retval = Minitest::Mock.new - mock = Minitest::Mock.new - mock.expect(:foo, retval) - mock.foo - - assert_mock mock - end - - def test_mock_args_does_not_raise - arg = Minitest::Mock.new - mock = Minitest::Mock.new - mock.expect(:foo, nil, [arg]) - mock.foo(arg) - - assert_mock mock - end - - def test_set_expectation_on_special_methods - mock = Minitest::Mock.new - - mock.expect :object_id, "received object_id" - assert_equal "received object_id", mock.object_id - - mock.expect :respond_to_missing?, "received respond_to_missing?" - assert_equal "received respond_to_missing?", mock.respond_to_missing? - - mock.expect :===, "received ===" - assert_equal "received ===", mock.=== - - mock.expect :inspect, "received inspect" - assert_equal "received inspect", mock.inspect - - mock.expect :to_s, "received to_s" - assert_equal "received to_s", mock.to_s - - mock.expect :public_send, "received public_send" - assert_equal "received public_send", mock.public_send - - mock.expect :send, "received send" - assert_equal "received send", mock.send - - assert_mock mock - end - - def test_expectations_can_be_satisfied_via_send - @mock.send :foo - @mock.send :meaning_of_life - - assert_mock @mock - end - - def test_expectations_can_be_satisfied_via_public_send - skip "Doesn't run on 1.8" if RUBY_VERSION < "1.9" - - @mock.public_send :foo - @mock.public_send :meaning_of_life - - assert_mock @mock - end - - def test_blow_up_on_wrong_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - e = assert_raises MockExpectationError do - @mock.sum(2, 4) - end - - exp = "mocked method :sum called with unexpected arguments [2, 4]" - assert_equal exp, e.message - end - - def test_expect_with_non_array_args - e = assert_raises ArgumentError do - @mock.expect :blah, 3, false - end - - assert_equal "args must be an array", e.message - end - - def test_respond_appropriately - assert @mock.respond_to?(:foo) - assert @mock.respond_to?(:foo, true) - assert @mock.respond_to?("foo") - assert !@mock.respond_to?(:bar) - end - - def test_no_method_error_on_unexpected_methods - e = assert_raises NoMethodError do - @mock.bar - end - - expected = "unmocked method :bar, expected one of [:foo, :meaning_of_life]" - - assert_equal expected, e.message - end - - def test_assign_per_mock_return_values - a = Minitest::Mock.new - b = Minitest::Mock.new - - a.expect(:foo, :a) - b.expect(:foo, :b) - - assert_equal :a, a.foo - assert_equal :b, b.foo - end - - def test_do_not_create_stub_method_on_new_mocks - a = Minitest::Mock.new - a.expect(:foo, :a) - - assert !Minitest::Mock.new.respond_to?(:foo) - end - - def test_mock_is_a_blank_slate - @mock.expect :kind_of?, true, [String] - @mock.expect :==, true, [1] - - assert @mock.kind_of?(String), "didn't mock :kind_of\?" - assert @mock == 1, "didn't mock :==" - end - - def test_verify_allows_called_args_to_be_loosely_specified - mock = Minitest::Mock.new - mock.expect :loose_expectation, true, [Integer] - mock.loose_expectation 1 - - assert_mock mock - end - - def test_verify_raises_with_strict_args - mock = Minitest::Mock.new - mock.expect :strict_expectation, true, [2] - - e = assert_raises MockExpectationError do - mock.strict_expectation 1 - end - - exp = "mocked method :strict_expectation called with unexpected arguments [1]" - assert_equal exp, e.message - end - - def test_method_missing_empty - mock = Minitest::Mock.new - - mock.expect :a, nil - - mock.a - - e = assert_raises MockExpectationError do - mock.a - end - - assert_equal "No more expects available for :a: []", e.message - end - - def test_same_method_expects_are_verified_when_all_called - mock = Minitest::Mock.new - mock.expect :foo, nil, [:bar] - mock.expect :foo, nil, [:baz] - - mock.foo :bar - mock.foo :baz - - assert_mock mock - end - - def test_same_method_expects_blow_up_when_not_all_called - mock = Minitest::Mock.new - mock.expect :foo, nil, [:bar] - mock.expect :foo, nil, [:baz] - - mock.foo :bar - - e = assert_raises(MockExpectationError) { mock.verify } - - exp = "expected foo(:baz) => nil, got [foo(:bar) => nil]" - - assert_equal exp, e.message - end - - def test_same_method_expects_with_same_args_blow_up_when_not_all_called - mock = Minitest::Mock.new - mock.expect :foo, nil, [:bar] - mock.expect :foo, nil, [:bar] - - mock.foo :bar - - e = assert_raises(MockExpectationError) { mock.verify } - - exp = "expected foo(:bar) => nil, got [foo(:bar) => nil]" - - assert_equal exp, e.message - end - - def test_verify_passes_when_mock_block_returns_true - mock = Minitest::Mock.new - mock.expect :foo, nil do - true - end - - mock.foo - - assert_mock mock - end - - def test_mock_block_is_passed_function_params - arg1, arg2, arg3 = :bar, [1, 2, 3], { :a => "a" } - mock = Minitest::Mock.new - mock.expect :foo, nil do |a1, a2, a3| - a1 == arg1 && a2 == arg2 && a3 == arg3 - end - - mock.foo arg1, arg2, arg3 - - assert_mock mock - end - - def test_mock_block_is_passed_function_block - mock = Minitest::Mock.new - block = proc { "bar" } - mock.expect :foo, nil do |arg, &blk| - arg == "foo" && - blk == block - end - mock.foo "foo", &block - assert_mock mock - end - - def test_verify_fails_when_mock_block_returns_false - mock = Minitest::Mock.new - mock.expect :foo, nil do - false - end - - e = assert_raises(MockExpectationError) { mock.foo } - exp = "mocked method :foo failed block w/ []" - - assert_equal exp, e.message - end - - def test_mock_block_throws_if_args_passed - mock = Minitest::Mock.new - - e = assert_raises(ArgumentError) do - mock.expect :foo, nil, [:a, :b, :c] do - true - end - end - - exp = "args ignored when block given" - - assert_equal exp, e.message - end - - def test_mock_returns_retval_when_called_with_block - mock = Minitest::Mock.new - mock.expect(:foo, 32) do - true - end - - rs = mock.foo - - assert_equal rs, 32 - end - - def util_verify_bad exp - e = assert_raises MockExpectationError do - @mock.verify - end - - assert_equal exp, e.message - end - - def test_mock_called_via_send - mock = Minitest::Mock.new - mock.expect(:foo, true) - - mock.send :foo - assert_mock mock - end - - def test_mock_called_via___send__ - mock = Minitest::Mock.new - mock.expect(:foo, true) - - mock.__send__ :foo - assert_mock mock - end - - def test_mock_called_via_send_with_args - mock = Minitest::Mock.new - mock.expect(:foo, true, [1, 2, 3]) - - mock.send(:foo, 1, 2, 3) - assert_mock mock - end - -end - -require "minitest/metametameta" - -class TestMinitestStub < Minitest::Test - # Do not parallelize since we're calling stub on class methods - - def setup - super - Minitest::Test.reset - - @tc = Minitest::Test.new "fake tc" - @assertion_count = 1 - end - - def teardown - super - assert_equal @assertion_count, @tc.assertions if self.passed? - end - - class Time - def self.now - 24 - end - end - - def assert_stub val_or_callable - @assertion_count += 1 - - t = Time.now.to_i - - Time.stub :now, val_or_callable do - @tc.assert_equal 42, Time.now - end - - @tc.assert_operator Time.now.to_i, :>=, t - end - - def test_stub_private_module_method - @assertion_count += 1 - - t0 = Time.now - - self.stub :sleep, nil do - @tc.assert_nil sleep(10) - end - - @tc.assert_operator Time.now - t0, :<=, 1 - end - - def test_stub_private_module_method_indirect - @assertion_count += 1 - - fail_clapper = Class.new do - def fail_clap - raise - :clap - end - end.new - - fail_clapper.stub :raise, nil do |safe_clapper| - @tc.assert_equal :clap, safe_clapper.fail_clap # either form works - @tc.assert_equal :clap, fail_clapper.fail_clap # yay closures - end - end - - def test_stub_public_module_method - Math.stub :log10, :stubbed do - @tc.assert_equal :stubbed, Math.log10(1000) - end - end - - def test_stub_value - assert_stub 42 - end - - def test_stub_block - assert_stub lambda { 42 } - end - - def test_stub_block_args - @assertion_count += 1 - - t = Time.now.to_i - - Time.stub :now, lambda { |n| n * 2 } do - @tc.assert_equal 42, Time.now(21) - end - - @tc.assert_operator Time.now.to_i, :>=, t - end - - def test_stub_callable - obj = Object.new - - def obj.call - 42 - end - - assert_stub obj - end - - def test_stub_yield_self - obj = "foo" - - val = obj.stub :to_s, "bar" do |s| - s.to_s - end - - @tc.assert_equal "bar", val - end - - def test_dynamic_method - @assertion_count = 2 - - dynamic = Class.new do - def self.respond_to? meth - meth == :found - end - - def self.method_missing meth, *args, &block - if meth == :found - false - else - super - end - end - end - - val = dynamic.stub(:found, true) do |s| - s.found - end - - @tc.assert_equal true, val - @tc.assert_equal false, dynamic.found - end - - def test_stub_NameError - e = @tc.assert_raises NameError do - Time.stub :nope_nope_nope, 42 do - # do nothing - end - end - - exp = /undefined method `nope_nope_nope' for( class)? `#{self.class}::Time'/ - assert_match exp, e.message - end - - def test_mock_with_yield - mock = Minitest::Mock.new - mock.expect(:write, true) do - true - end - rs = nil - - File.stub :open, true, mock do - File.open "foo.txt", "r" do |f| - rs = f.write - end - end - @tc.assert_equal true, rs - end - - alias test_stub_value__old test_stub_value # TODO: remove/rename - - ## Permutation Sets: - - # [:value, :lambda] - # [:*, :block, :block_call] - # [:**, :block_args] - # - # Where: - # - # :value = a normal value - # :lambda = callable or lambda - # :* = no block - # :block = normal block - # :block_call = :lambda invokes the block (N/A for :value) - # :** = no args - # :args = args passed to stub - - ## Permutations - - # [:call, :*, :**] =>5 callable+block FIX: CALL BOTH (bug) - # [:call, :*, :**] =>6 callable - - # [:lambda, :*, :**] => lambda result - - # [:lambda, :*, :args] => lambda result NO ARGS - - # [:lambda, :block, :**] =>5 lambda result FIX: CALL BOTH (bug) - # [:lambda, :block, :**] =>6 lambda result - - # [:lambda, :block, :args] =>5 lambda result FIX: CALL BOTH (bug) - # [:lambda, :block, :args] =>6 lambda result - # [:lambda, :block, :args] =>7 raise ArgumentError - - # [:lambda, :block_call, :**] =>5 lambda FIX: BUG!-not passed block to lambda - # [:lambda, :block_call, :**] =>6 lambda+block result - - # [:lambda, :block_call, :args] =>5 lambda FIX: BUG!-not passed block to lambda - # [:lambda, :block_call, :args] =>6 lambda+block result - - # [:value, :*, :**] => value - - # [:value, :*, :args] => value, ignore args - - # [:value, :block, :**] =>5 value, call block - # [:value, :block, :**] =>6 value - - # [:value, :block, :args] =>5 value, call block w/ args - # [:value, :block, :args] =>6 value, call block w/ args, deprecated - # [:value, :block, :args] =>7 raise ArgumentError - - # [:value, :block_call, :**] => N/A - - # [:value, :block_call, :args] => N/A - - class Bar - def call - puts "hi" - end - end - - class Foo - def self.blocking - yield - end - end - - class Thingy - def self.identity arg - arg - end - end - - def test_stub_callable_block_5 # from tenderlove - @assertion_count += 1 - Foo.stub5 :blocking, Bar.new do - @tc.assert_output "hi\n", "" do - Foo.blocking do - @tc.flunk "shouldn't ever hit this" - end - end - end - end - - def test_stub_callable_block_6 # from tenderlove - skip_stub6 - - @assertion_count += 1 - Foo.stub6 :blocking, Bar.new do - @tc.assert_output "hi\n", "" do - Foo.blocking do - @tc.flunk "shouldn't ever hit this" - end - end - end - end - - def test_stub_lambda - Thread.stub :new, lambda { 21+21 } do - @tc.assert_equal 42, Thread.new - end - end - - def test_stub_lambda_args - Thread.stub :new, lambda { 21+21 }, :wtf do - @tc.assert_equal 42, Thread.new - end - end - - def test_stub_lambda_block_5 - Thread.stub5 :new, lambda { 21+21 } do - result = Thread.new do - @tc.flunk "shouldn't ever hit this" - end - @tc.assert_equal 42, result - end - end - - def test_stub_lambda_block_6 - skip_stub6 - - Thread.stub6 :new, lambda { 21+21 } do - result = Thread.new do - @tc.flunk "shouldn't ever hit this" - end - @tc.assert_equal 42, result - end - end - - def test_stub_lambda_block_args_5 - @assertion_count += 1 - Thingy.stub5 :identity, lambda { |y| @tc.assert_equal :nope, y; 21+21 }, :WTF? do - result = Thingy.identity :nope do |x| - @tc.flunk "shouldn't reach this" - end - @tc.assert_equal 42, result - end - end - - def test_stub_lambda_block_args_6 - skip_stub6 - - @assertion_count += 1 - Thingy.stub6 :identity, lambda { |y| @tc.assert_equal :nope, y; 21+21 }, :WTF? do - result = Thingy.identity :nope do |x| - @tc.flunk "shouldn't reach this" - end - @tc.assert_equal 42, result - end - end - - def test_stub_lambda_block_args_6_2 - skip_stub6 - - @tc.assert_raises ArgumentError do - Thingy.stub6_2 :identity, lambda { |y| :__not_run__ }, :WTF? do - # doesn't matter - end - end - end - - def test_stub_lambda_block_call_5 - @assertion_count += 1 - rs = nil - io = StringIO.new "", "w" - File.stub5 :open, lambda { |p, m, &blk| blk and blk.call io } do - File.open "foo.txt", "r" do |f| - rs = f && f.write("woot") - end - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_lambda_block_call_6 - skip_stub6 - - @assertion_count += 1 - rs = nil - io = StringIO.new "", "w" - File.stub6 :open, lambda { |p, m, &blk| blk.call io } do - File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_lambda_block_call_args_5 - @assertion_count += 1 - rs = nil - io = StringIO.new "", "w" - File.stub5(:open, lambda { |p, m, &blk| blk and blk.call io }, :WTF?) do - File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_lambda_block_call_args_6 - skip_stub6 - - @assertion_count += 1 - rs = nil - io = StringIO.new "", "w" - File.stub6(:open, lambda { |p, m, &blk| blk.call io }, :WTF?) do - File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_lambda_block_call_args_6_2 - skip_stub6 - - @assertion_count += 2 - rs = nil - io = StringIO.new "", "w" - @tc.assert_raises ArgumentError do - File.stub6_2(:open, lambda { |p, m, &blk| blk.call io }, :WTF?) do - File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - end - end - @tc.assert_nil rs - @tc.assert_equal "", io.string - end - - def test_stub_value - Thread.stub :new, 42 do - result = Thread.new - @tc.assert_equal 42, result - end - end - - def test_stub_value_args - Thread.stub :new, 42, :WTF? do - result = Thread.new - @tc.assert_equal 42, result - end - end - - def test_stub_value_block_5 - @assertion_count += 1 - Thread.stub5 :new, 42 do - result = Thread.new do - @tc.assert true - end - @tc.assert_equal 42, result - end - end - - def test_stub_value_block_6 - skip_stub6 - - Thread.stub6 :new, 42 do - result = Thread.new do - @tc.flunk "shouldn't hit this" - end - @tc.assert_equal 42, result - end - end - - def test_stub_value_block_args_5 - @assertion_count += 2 - rs = nil - io = StringIO.new "", "w" - File.stub5 :open, :value, io do - result = File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - @tc.assert_equal :value, result - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_value_block_args_5__break_if_not_passed - e = @tc.assert_raises NoMethodError do - File.stub5 :open, :return_value do # intentionally bad setup w/ no args - File.open "foo.txt", "r" do |f| - f.write "woot" - end - end - end - exp = "undefined method `write' for nil:NilClass" - assert_equal exp, e.message - end - - def test_stub_value_block_args_6 - skip_stub6 - - @assertion_count += 2 - rs = nil - io = StringIO.new "", "w" - assert_deprecated do - File.stub6 :open, :value, io do - result = File.open "foo.txt", "r" do |f| - rs = f.write("woot") - end - @tc.assert_equal :value, result - end - end - @tc.assert_equal 4, rs - @tc.assert_equal "woot", io.string - end - - def test_stub_value_block_args_6_2 - skip_stub6 - - @assertion_count += 2 - rs = nil - io = StringIO.new "", "w" - @tc.assert_raises ArgumentError do - File.stub6_2 :open, :value, io do - result = File.open "foo.txt", "r" do |f| - @tc.flunk "shouldn't hit this" - end - @tc.assert_equal :value, result - end - end - @tc.assert_nil rs - @tc.assert_equal "", io.string - end - - def assert_deprecated re = /deprecated/ - assert_output "", re do - yield - end - end - - def skip_stub6 - skip "not yet" unless STUB6 - end -end - -STUB6 = ENV["STUB6"] - -if STUB6 then - require "minitest/mock6" if STUB6 -else - class Object - alias stub5 stub - alias stub6 stub - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_reporter.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_reporter.rb deleted file mode 100644 index 6619d03d4..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_reporter.rb +++ /dev/null @@ -1,299 +0,0 @@ -require "minitest/autorun" -require "minitest/metametameta" - -class Runnable - def woot - assert true - end -end - -class TestMinitestReporter < MetaMetaMetaTestCase - - attr_accessor :r, :io - - def new_composite_reporter - reporter = Minitest::CompositeReporter.new - reporter << Minitest::SummaryReporter.new(self.io) - reporter << Minitest::ProgressReporter.new(self.io) - - def reporter.first - reporters.first - end - - def reporter.results - first.results - end - - def reporter.count - first.count - end - - def reporter.assertions - first.assertions - end - - reporter - end - - def setup - self.io = StringIO.new("") - self.r = new_composite_reporter - end - - def error_test - unless defined? @et then - @et = Minitest::Test.new(:woot) - @et.failures << Minitest::UnexpectedError.new(begin - raise "no" - rescue => e - e - end) - @et = Minitest::Result.from @et - end - @et - end - - def fail_test - unless defined? @ft then - @ft = Minitest::Test.new(:woot) - @ft.failures << begin - raise Minitest::Assertion, "boo" - rescue Minitest::Assertion => e - e - end - @ft = Minitest::Result.from @ft - end - @ft - end - - def passing_test - @pt ||= Minitest::Result.from Minitest::Test.new(:woot) - end - - def skip_test - unless defined? @st then - @st = Minitest::Test.new(:woot) - @st.failures << begin - raise Minitest::Skip - rescue Minitest::Assertion => e - e - end - @st = Minitest::Result.from @st - end - @st - end - - def test_to_s - r.record passing_test - r.record fail_test - assert_match "woot", r.first.to_s - end - - def test_passed_eh_empty - assert_predicate r, :passed? - end - - def test_passed_eh_failure - r.results << fail_test - - refute_predicate r, :passed? - end - - SKIP_MSG = "\n\nYou have skipped tests. Run with --verbose for details." - - def test_passed_eh_error - r.start - - r.results << error_test - - refute_predicate r, :passed? - - r.report - - refute_match SKIP_MSG, io.string - end - - def test_passed_eh_skipped - r.start - r.results << skip_test - assert r.passed? - - restore_env do - r.report - end - - assert_match SKIP_MSG, io.string - end - - def test_passed_eh_skipped_verbose - r.first.options[:verbose] = true - - r.start - r.results << skip_test - assert r.passed? - r.report - - refute_match SKIP_MSG, io.string - end - - def test_start - r.start - - exp = "Run options: \n\n# Running:\n\n" - - assert_equal exp, io.string - end - - def test_record_pass - r.record passing_test - - assert_equal ".", io.string - assert_empty r.results - assert_equal 1, r.count - assert_equal 0, r.assertions - end - - def test_record_fail - fail_test = self.fail_test - r.record fail_test - - assert_equal "F", io.string - assert_equal [fail_test], r.results - assert_equal 1, r.count - assert_equal 0, r.assertions - end - - def test_record_error - error_test = self.error_test - r.record error_test - - assert_equal "E", io.string - assert_equal [error_test], r.results - assert_equal 1, r.count - assert_equal 0, r.assertions - end - - def test_record_skip - skip_test = self.skip_test - r.record skip_test - - assert_equal "S", io.string - assert_equal [skip_test], r.results - assert_equal 1, r.count - assert_equal 0, r.assertions - end - - def test_report_empty - r.start - r.report - - exp = clean <<-EOM - Run options: - - # Running: - - - - Finished in 0.00 - - 0 runs, 0 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_equal exp, normalize_output(io.string) - end - - def test_report_passing - r.start - r.record passing_test - r.report - - exp = clean <<-EOM - Run options: - - # Running: - - . - - Finished in 0.00 - - 1 runs, 0 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_equal exp, normalize_output(io.string) - end - - def test_report_failure - r.start - r.record fail_test - r.report - - exp = clean <<-EOM - Run options: - - # Running: - - F - - Finished in 0.00 - - 1) Failure: - Minitest::Test#woot [FILE:LINE]: - boo - - 1 runs, 0 assertions, 1 failures, 0 errors, 0 skips - EOM - - assert_equal exp, normalize_output(io.string) - end - - def test_report_error - r.start - r.record error_test - r.report - - exp = clean <<-EOM - Run options: - - # Running: - - E - - Finished in 0.00 - - 1) Error: - Minitest::Test#woot: - RuntimeError: no - FILE:LINE:in `error_test' - FILE:LINE:in `test_report_error' - - 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips - EOM - - assert_equal exp, normalize_output(io.string) - end - - def test_report_skipped - r.start - r.record skip_test - - restore_env do - r.report - end - - exp = clean <<-EOM - Run options: - - # Running: - - S - - Finished in 0.00 - - 1 runs, 0 assertions, 0 failures, 0 errors, 1 skips - - You have skipped tests. Run with --verbose for details. - EOM - - assert_equal exp, normalize_output(io.string) - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_spec.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_spec.rb deleted file mode 100644 index 5af4deef2..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_spec.rb +++ /dev/null @@ -1,1041 +0,0 @@ -# encoding: utf-8 -require "minitest/metametameta" -require "stringio" - -class MiniSpecA < Minitest::Spec; end -class MiniSpecB < Minitest::Test; extend Minitest::Spec::DSL; end -class MiniSpecC < MiniSpecB; end -class NamedExampleA < MiniSpecA; end -class NamedExampleB < MiniSpecB; end -class NamedExampleC < MiniSpecC; end -class ExampleA; end -class ExampleB < ExampleA; end - -describe Minitest::Spec do - # helps to deal with 2.4 deprecation of Fixnum for Integer - Int = 1.class - - # do not parallelize this suite... it just can"t handle it. - - def assert_triggered expected = "blah", klass = Minitest::Assertion - @assertion_count += 1 - - e = assert_raises(klass) do - yield - end - - msg = e.message.sub(/(---Backtrace---).*/m, '\1') - msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") - msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform - msg.gsub!(/:0x[Xa-fA-F0-9]{4,}[ @].+?>/, ":0xXXXXXX@PATH>") - - if expected - @assertion_count += 1 - case expected - when String then - assert_equal expected, msg - when Regexp then - @assertion_count += 1 - assert_match expected, msg - else - flunk "Unknown: #{expected.inspect}" - end - end - end - - before do - @assertion_count = 4 - end - - after do - _(self.assertions).must_equal @assertion_count if passed? and not skipped? - end - - it "needs to be able to catch a Minitest::Assertion exception" do - @assertion_count = 1 - - assert_triggered "Expected 1 to not be equal to 1." do - _(1).wont_equal 1 - end - end - - it "needs to check for file existence" do - @assertion_count = 3 - - _(_(__FILE__).path_must_exist).must_equal true - - assert_triggered "Expected path 'blah' to exist." do - _("blah").path_must_exist - end - end - - it "needs to check for file non-existence" do - @assertion_count = 3 - - _(_("blah").path_wont_exist).must_equal false - - assert_triggered "Expected path '#{__FILE__}' to not exist." do - _(__FILE__).path_wont_exist - end - end - - it "needs to be sensible about must_include order" do - @assertion_count += 3 # must_include is 2 assertions - - _(_([1, 2, 3]).must_include(2)).must_equal true - - assert_triggered "Expected [1, 2, 3] to include 5." do - _([1, 2, 3]).must_include 5 - end - - assert_triggered "msg.\nExpected [1, 2, 3] to include 5." do - _([1, 2, 3]).must_include 5, "msg" - end - end - - it "needs to be sensible about wont_include order" do - @assertion_count += 3 # wont_include is 2 assertions - - _(_([1, 2, 3]).wont_include(5)).must_equal false - - assert_triggered "Expected [1, 2, 3] to not include 2." do - _([1, 2, 3]).wont_include 2 - end - - assert_triggered "msg.\nExpected [1, 2, 3] to not include 2." do - _([1, 2, 3]).wont_include 2, "msg" - end - end - - it "needs to catch an expected exception" do - @assertion_count = 2 - - expect { raise "blah" }.must_raise RuntimeError - expect { raise Minitest::Assertion }.must_raise Minitest::Assertion - end - - it "needs to catch an unexpected exception" do - @assertion_count -= 2 # no positive - - msg = <<-EOM.gsub(/^ {6}/, "").chomp - [RuntimeError] exception expected, not - Class: - Message: <"woot"> - ---Backtrace--- - EOM - - assert_triggered msg do - expect { raise StandardError, "woot" }.must_raise RuntimeError - end - - assert_triggered "msg.\n#{msg}" do - expect { raise StandardError, "woot" }.must_raise RuntimeError, "msg" - end - end - - it "needs to ensure silence" do - @assertion_count -= 1 # no msg - @assertion_count += 2 # assert_output is 2 assertions - - _(expect {}.must_be_silent).must_equal true - - assert_triggered "In stdout.\nExpected: \"\"\n Actual: \"xxx\"" do - expect { print "xxx" }.must_be_silent - end - end - - it "needs to have all methods named well" do - skip "N/A" if ENV["MT_NO_EXPECTATIONS"] - - @assertion_count = 2 - - methods = Minitest::Expectations.public_instance_methods.grep(/must|wont/) - methods.map!(&:to_s) if Symbol === methods.first - - musts, wonts = methods.sort.partition { |m| m =~ /must/ } - - expected_musts = %w[must_be - must_be_close_to - must_be_empty - must_be_instance_of - must_be_kind_of - must_be_nil - must_be_same_as - must_be_silent - must_be_within_delta - must_be_within_epsilon - must_equal - must_include - must_match - must_output - must_raise - must_respond_to - must_throw - path_must_exist] - - bad = %w[not raise throw send output be_silent] - - expected_wonts = expected_musts.map { |m| m.sub(/must/, "wont") }.sort - expected_wonts.reject! { |m| m =~ /wont_#{Regexp.union(*bad)}/ } - - _(musts).must_equal expected_musts - _(wonts).must_equal expected_wonts - end - - it "needs to raise if an expected exception is not raised" do - @assertion_count -= 2 # no positive test - - assert_triggered "RuntimeError expected but nothing was raised." do - expect { 42 }.must_raise RuntimeError - end - - assert_triggered "msg.\nRuntimeError expected but nothing was raised." do - expect { 42 }.must_raise RuntimeError, "msg" - end - end - - it "needs to verify binary messages" do - _(_(42).wont_be(:<, 24)).must_equal false - - assert_triggered "Expected 24 to not be < 42." do - _(24).wont_be :<, 42 - end - - assert_triggered "msg.\nExpected 24 to not be < 42." do - _(24).wont_be :<, 42, "msg" - end - end - - it "needs to verify emptyness" do - @assertion_count += 3 # empty is 2 assertions - - _(_([]).must_be_empty).must_equal true - - assert_triggered "Expected [42] to be empty." do - _([42]).must_be_empty - end - - assert_triggered "msg.\nExpected [42] to be empty." do - _([42]).must_be_empty "msg" - end - end - - it "needs to verify equality" do - @assertion_count += 1 - - _(_(6 * 7).must_equal(42)).must_equal true - - assert_triggered "Expected: 42\n Actual: 54" do - _(6 * 9).must_equal 42 - end - - assert_triggered "msg.\nExpected: 42\n Actual: 54" do - _(6 * 9).must_equal 42, "msg" - end - - assert_triggered(/^-42\n\+#\n/) do - _(proc { 42 }).must_equal 42 # proc isn't called, so expectation fails - end - end - - it "needs to warn on equality with nil" do - @assertion_count += 1 # extra test - - out, err = capture_io do - _(_(nil).must_equal(nil)).must_equal true - end - - exp = "DEPRECATED: Use assert_nil if expecting nil from #{__FILE__}:#{__LINE__-3}. " \ - "This will fail in Minitest 6.\n" - exp = "" if $-w.nil? - - assert_empty out - assert_equal exp, err - end - - it "needs to verify floats outside a delta" do - @assertion_count += 1 # extra test - - _(_(24).wont_be_close_to(42)).must_equal false - - assert_triggered "Expected |42 - 42.0| (0.0) to not be <= 0.001." do - _(6 * 7.0).wont_be_close_to 42 - end - - x = "1.0e-05" - assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do - _(6 * 7.0).wont_be_close_to 42, 0.00001 - end - - assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do - _(6 * 7.0).wont_be_close_to 42, 0.00001, "msg" - end - end - - it "needs to verify floats outside an epsilon" do - @assertion_count += 1 # extra test - - _(_(24).wont_be_within_epsilon(42)).must_equal false - - x = "0.042" - assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do - _(6 * 7.0).wont_be_within_epsilon 42 - end - - x = "0.00042" - assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do - _(6 * 7.0).wont_be_within_epsilon 42, 0.00001 - end - - assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do - _(6 * 7.0).wont_be_within_epsilon 42, 0.00001, "msg" - end - end - - it "needs to verify floats within a delta" do - @assertion_count += 1 # extra test - - _(_(6.0 * 7).must_be_close_to(42.0)).must_equal true - - assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.001." do - _(1.0 / 100).must_be_close_to 0.0 - end - - x = "1.0e-06" - assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do - _(1.0 / 1000).must_be_close_to 0.0, 0.000001 - end - - assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= #{x}." do - _(1.0 / 1000).must_be_close_to 0.0, 0.000001, "msg" - end - end - - it "needs to verify floats within an epsilon" do - @assertion_count += 1 # extra test - - _(_(6.0 * 7).must_be_within_epsilon(42.0)).must_equal true - - assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.0." do - _(1.0 / 100).must_be_within_epsilon 0.0 - end - - assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= 0.0." do - _(1.0 / 1000).must_be_within_epsilon 0.0, 0.000001 - end - - assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= 0.0." do - _(1.0 / 1000).must_be_within_epsilon 0.0, 0.000001, "msg" - end - end - - it "needs to verify identity" do - _(_(1).must_be_same_as(1)).must_equal true - - assert_triggered "Expected 1 (oid=N) to be the same as 2 (oid=N)." do - _(1).must_be_same_as 2 - end - - assert_triggered "msg.\nExpected 1 (oid=N) to be the same as 2 (oid=N)." do - _(1).must_be_same_as 2, "msg" - end - end - - it "needs to verify inequality" do - @assertion_count += 2 - _(_(42).wont_equal(6 * 9)).must_equal false - _(_(proc {}).wont_equal(42)).must_equal false - - assert_triggered "Expected 1 to not be equal to 1." do - _(1).wont_equal 1 - end - - assert_triggered "msg.\nExpected 1 to not be equal to 1." do - _(1).wont_equal 1, "msg" - end - end - - it "needs to verify instances of a class" do - _(_(42).wont_be_instance_of(String)).must_equal false - - assert_triggered "Expected 42 to not be a kind of #{Int.name}." do - _(42).wont_be_kind_of Int - end - - assert_triggered "msg.\nExpected 42 to not be an instance of #{Int.name}." do - _(42).wont_be_instance_of Int, "msg" - end - end - - it "needs to verify kinds of a class" do - @assertion_count += 2 - - _(_(42).wont_be_kind_of(String)).must_equal false - _(_(proc {}).wont_be_kind_of(String)).must_equal false - - assert_triggered "Expected 42 to not be a kind of #{Int.name}." do - _(42).wont_be_kind_of Int - end - - assert_triggered "msg.\nExpected 42 to not be a kind of #{Int.name}." do - _(42).wont_be_kind_of Int, "msg" - end - end - - it "needs to verify kinds of objects" do - @assertion_count += 3 # extra test - - _(_(6 * 7).must_be_kind_of(Int)).must_equal true - _(_(6 * 7).must_be_kind_of(Numeric)).must_equal true - - assert_triggered "Expected 42 to be a kind of String, not #{Int.name}." do - _(6 * 7).must_be_kind_of String - end - - assert_triggered "msg.\nExpected 42 to be a kind of String, not #{Int.name}." do - _(6 * 7).must_be_kind_of String, "msg" - end - - exp = "Expected # to be a kind of String, not Proc." - assert_triggered exp do - _(proc {}).must_be_kind_of String - end - end - - it "needs to verify mismatch" do - @assertion_count += 3 # match is 2 - - _(_("blah").wont_match(/\d+/)).must_equal false - - assert_triggered "Expected /\\w+/ to not match \"blah\"." do - _("blah").wont_match(/\w+/) - end - - assert_triggered "msg.\nExpected /\\w+/ to not match \"blah\"." do - _("blah").wont_match(/\w+/, "msg") - end - end - - it "needs to verify nil" do - _(_(nil).must_be_nil).must_equal true - - assert_triggered "Expected 42 to be nil." do - _(42).must_be_nil - end - - assert_triggered "msg.\nExpected 42 to be nil." do - _(42).must_be_nil "msg" - end - end - - it "needs to verify non-emptyness" do - @assertion_count += 3 # empty is 2 assertions - - _(_(["some item"]).wont_be_empty).must_equal false - - assert_triggered "Expected [] to not be empty." do - _([]).wont_be_empty - end - - assert_triggered "msg.\nExpected [] to not be empty." do - _([]).wont_be_empty "msg" - end - end - - it "needs to verify non-identity" do - _(_(1).wont_be_same_as(2)).must_equal false - - assert_triggered "Expected 1 (oid=N) to not be the same as 1 (oid=N)." do - _(1).wont_be_same_as 1 - end - - assert_triggered "msg.\nExpected 1 (oid=N) to not be the same as 1 (oid=N)." do - _(1).wont_be_same_as 1, "msg" - end - end - - it "needs to verify non-nil" do - _(_(42).wont_be_nil).must_equal false - - assert_triggered "Expected nil to not be nil." do - _(nil).wont_be_nil - end - - assert_triggered "msg.\nExpected nil to not be nil." do - _(nil).wont_be_nil "msg" - end - end - - it "needs to verify objects not responding to a message" do - _(_("").wont_respond_to(:woot!)).must_equal false - - assert_triggered "Expected \"\" to not respond to to_s." do - _("").wont_respond_to :to_s - end - - assert_triggered "msg.\nExpected \"\" to not respond to to_s." do - _("").wont_respond_to :to_s, "msg" - end - end - - it "needs to verify output in stderr" do - @assertion_count -= 1 # no msg - - _(expect { $stderr.print "blah" }.must_output(nil, "blah")).must_equal true - - assert_triggered "In stderr.\nExpected: \"blah\"\n Actual: \"xxx\"" do - expect { $stderr.print "xxx" }.must_output(nil, "blah") - end - end - - it "needs to verify output in stdout" do - @assertion_count -= 1 # no msg - - _(expect { print "blah" }.must_output("blah")).must_equal true - - assert_triggered "In stdout.\nExpected: \"blah\"\n Actual: \"xxx\"" do - expect { print "xxx" }.must_output("blah") - end - end - - it "needs to verify regexp matches" do - @assertion_count += 3 # must_match is 2 assertions - - _(_("blah").must_match(/\w+/)).must_equal true - - assert_triggered "Expected /\\d+/ to match \"blah\"." do - _("blah").must_match(/\d+/) - end - - assert_triggered "msg.\nExpected /\\d+/ to match \"blah\"." do - _("blah").must_match(/\d+/, "msg") - end - end - - describe "expect" do - before do - @assertion_count -= 3 - end - - it "can use expect" do - _(1 + 1).must_equal 2 - end - - it "can use expect with a lambda" do - _ { raise "blah" }.must_raise RuntimeError - end - - it "can use expect in a thread" do - Thread.new { _(1 + 1).must_equal 2 }.join - end - - it "can NOT use must_equal in a thread. It must use expect in a thread" do - skip "N/A" if ENV["MT_NO_EXPECTATIONS"] - assert_raises RuntimeError do - capture_io do - Thread.new { (1 + 1).must_equal 2 }.join - end - end - end - - it "fails gracefully when expectation used outside of `it`" do - skip "N/A" if ENV["MT_NO_EXPECTATIONS"] - - @assertion_count += 1 - - e = assert_raises RuntimeError do - capture_io do - Thread.new { # forces ctx to be nil - describe("woot") do - (1 + 1).must_equal 2 - end - }.join - end - end - - assert_equal "Calling #must_equal outside of test.", e.message - end - - it "deprecates expectation used without _" do - skip "N/A" if ENV["MT_NO_EXPECTATIONS"] - - @assertion_count += 3 - - exp = /DEPRECATED: global use of must_equal from/ - - assert_output "", exp do - (1 + 1).must_equal 2 - end - end - end - - it "needs to verify throw" do - @assertion_count += 2 # 2 extra tests - - _(expect { throw :blah }.must_throw(:blah)).must_equal true - - assert_triggered "Expected :blah to have been thrown." do - expect {}.must_throw :blah - end - - assert_triggered "Expected :blah to have been thrown, not :xxx." do - expect { throw :xxx }.must_throw :blah - end - - assert_triggered "msg.\nExpected :blah to have been thrown." do - expect {}.must_throw :blah, "msg" - end - - assert_triggered "msg.\nExpected :blah to have been thrown, not :xxx." do - expect { throw :xxx }.must_throw :blah, "msg" - end - end - - it "needs to verify types of objects" do - _(_(6 * 7).must_be_instance_of(Int)).must_equal true - - exp = "Expected 42 to be an instance of String, not #{Int.name}." - - assert_triggered exp do - _(6 * 7).must_be_instance_of String - end - - assert_triggered "msg.\n#{exp}" do - _(6 * 7).must_be_instance_of String, "msg" - end - end - - it "needs to verify using any (negative) predicate" do - @assertion_count -= 1 # doesn"t take a message - - _(_("blah").wont_be(:empty?)).must_equal false - - assert_triggered "Expected \"\" to not be empty?." do - _("").wont_be :empty? - end - end - - it "needs to verify using any binary operator" do - @assertion_count -= 1 # no msg - - _(_(41).must_be(:<, 42)).must_equal true - - assert_triggered "Expected 42 to be < 41." do - _(42).must_be(:<, 41) - end - end - - it "needs to verify using any predicate" do - @assertion_count -= 1 # no msg - - _(_("").must_be(:empty?)).must_equal true - - assert_triggered "Expected \"blah\" to be empty?." do - _("blah").must_be :empty? - end - end - - it "needs to verify using respond_to" do - _(_(42).must_respond_to(:+)).must_equal true - - assert_triggered "Expected 42 (#{Int.name}) to respond to #clear." do - _(42).must_respond_to :clear - end - - assert_triggered "msg.\nExpected 42 (#{Int.name}) to respond to #clear." do - _(42).must_respond_to :clear, "msg" - end - end -end - -describe Minitest::Spec, :let do - i_suck_and_my_tests_are_order_dependent! - - def _count - $let_count ||= 0 - end - - let :count do - $let_count += 1 - $let_count - end - - it "is evaluated once per example" do - _(_count).must_equal 0 - - _(count).must_equal 1 - _(count).must_equal 1 - - _(_count).must_equal 1 - end - - it "is REALLY evaluated once per example" do - _(_count).must_equal 1 - - _(count).must_equal 2 - _(count).must_equal 2 - - _(_count).must_equal 2 - end - - it 'raises an error if the name begins with "test"' do - expect { self.class.let(:test_value) { true } }.must_raise ArgumentError - end - - it "raises an error if the name shadows a normal instance method" do - expect { self.class.let(:message) { true } }.must_raise ArgumentError - end - - it "doesn't raise an error if it is just another let" do - v = proc do - describe :outer do - let(:bar) - describe :inner do - let(:bar) - end - end - :good - end.call - _(v).must_equal :good - end - - it "procs come after dont_flip" do - p = proc {} - assert_respond_to p, :call - _(p).must_respond_to :call - end -end - -describe Minitest::Spec, :subject do - attr_reader :subject_evaluation_count - - subject do - @subject_evaluation_count ||= 0 - @subject_evaluation_count += 1 - @subject_evaluation_count - end - - it "is evaluated once per example" do - _(subject).must_equal 1 - _(subject).must_equal 1 - _(subject_evaluation_count).must_equal 1 - end -end - -class TestMetaStatic < Minitest::Test - def test_children - Minitest::Spec.children.clear # prevents parallel run - - y = z = nil - x = describe "top-level thingy" do - y = describe "first thingy" do end - - it "top-level-it" do end - - z = describe "second thingy" do end - end - - assert_equal [x], Minitest::Spec.children - assert_equal [y, z], x.children - assert_equal [], y.children - assert_equal [], z.children - end - - def test_it_wont_remove_existing_child_test_methods - Minitest::Spec.children.clear # prevents parallel run - - inner = nil - outer = describe "outer" do - inner = describe "inner" do - it do - assert true - end - end - it do - assert true - end - end - - assert_equal 1, outer.public_instance_methods.grep(/^test_/).count - assert_equal 1, inner.public_instance_methods.grep(/^test_/).count - end - - def test_it_wont_add_test_methods_to_children - Minitest::Spec.children.clear # prevents parallel run - - inner = nil - outer = describe "outer" do - inner = describe "inner" do end - it do - assert true - end - end - - assert_equal 1, outer.public_instance_methods.grep(/^test_/).count - assert_equal 0, inner.public_instance_methods.grep(/^test_/).count - end -end - -class TestMeta < MetaMetaMetaTestCase - # do not call parallelize_me! here because specs use register_spec_type globally - - def util_structure - y = z = nil - before_list = [] - after_list = [] - x = describe "top-level thingy" do - before { before_list << 1 } - after { after_list << 1 } - - it "top-level-it" do end - - y = describe "inner thingy" do - before { before_list << 2 } - after { after_list << 2 } - it "inner-it" do end - - z = describe "very inner thingy" do - before { before_list << 3 } - after { after_list << 3 } - it "inner-it" do end - - it { } # ignore me - specify { } # anonymous it - end - end - end - - return x, y, z, before_list, after_list - end - - def test_register_spec_type - original_types = Minitest::Spec::TYPES.dup - - assert_includes Minitest::Spec::TYPES, [//, Minitest::Spec] - - Minitest::Spec.register_spec_type(/woot/, TestMeta) - - p = lambda do |_| true end - Minitest::Spec.register_spec_type TestMeta, &p - - keys = Minitest::Spec::TYPES.map(&:first) - - assert_includes keys, /woot/ - assert_includes keys, p - ensure - Minitest::Spec::TYPES.replace original_types - end - - def test_spec_type - original_types = Minitest::Spec::TYPES.dup - - Minitest::Spec.register_spec_type(/A$/, MiniSpecA) - Minitest::Spec.register_spec_type MiniSpecB do |desc| - desc.superclass == ExampleA - end - Minitest::Spec.register_spec_type MiniSpecC do |_desc, *addl| - addl.include? :woot - end - - assert_equal MiniSpecA, Minitest::Spec.spec_type(ExampleA) - assert_equal MiniSpecB, Minitest::Spec.spec_type(ExampleB) - assert_equal MiniSpecC, Minitest::Spec.spec_type(ExampleB, :woot) - ensure - Minitest::Spec::TYPES.replace original_types - end - - def test_bug_dsl_expectations - spec_class = Class.new MiniSpecB do - it "should work" do - _(0).must_equal 0 - end - end - - test_name = spec_class.instance_methods.sort.grep(/test/).first - - spec = spec_class.new test_name - - result = spec.run - - assert spec.passed? - assert result.passed? - assert_equal 1, result.assertions - end - - def test_name - spec_a = describe ExampleA do; end - spec_b = describe ExampleB, :random_method do; end - spec_c = describe ExampleB, :random_method, :addl_context do; end - - assert_equal "ExampleA", spec_a.name - assert_equal "ExampleB::random_method", spec_b.name - assert_equal "ExampleB::random_method::addl_context", spec_c.name - end - - def test_name2 - assert_equal "NamedExampleA", NamedExampleA.name - assert_equal "NamedExampleB", NamedExampleB.name - assert_equal "NamedExampleC", NamedExampleC.name - - spec_a = describe ExampleA do; end - spec_b = describe ExampleB, :random_method do; end - - assert_equal "ExampleA", spec_a.name - assert_equal "ExampleB::random_method", spec_b.name - end - - def test_structure - x, y, z, * = util_structure - - assert_equal "top-level thingy", x.to_s - assert_equal "top-level thingy::inner thingy", y.to_s - assert_equal "top-level thingy::inner thingy::very inner thingy", z.to_s - - assert_equal "top-level thingy", x.desc - assert_equal "inner thingy", y.desc - assert_equal "very inner thingy", z.desc - - top_methods = %w[setup teardown test_0001_top-level-it] - inner_methods1 = %w[setup teardown test_0001_inner-it] - inner_methods2 = inner_methods1 + - %w[test_0002_anonymous test_0003_anonymous] - - assert_equal top_methods, x.instance_methods(false).sort.map(&:to_s) - assert_equal inner_methods1, y.instance_methods(false).sort.map(&:to_s) - assert_equal inner_methods2, z.instance_methods(false).sort.map(&:to_s) - end - - def test_structure_postfix_it - z = nil - y = describe "outer" do - # NOT here, below the inner-describe! - # it "inner-it" do end - - z = describe "inner" do - it "inner-it" do end - end - - # defined AFTER inner describe means we'll try to wipe out the inner-it - it "inner-it" do end - end - - assert_equal %w[test_0001_inner-it], y.instance_methods(false).map(&:to_s) - assert_equal %w[test_0001_inner-it], z.instance_methods(false).map(&:to_s) - end - - def test_setup_teardown_behavior - _, _, z, before_list, after_list = util_structure - - @tu = z - - run_tu_with_fresh_reporter - - size = z.runnable_methods.size - assert_equal [1, 2, 3] * size, before_list - assert_equal [3, 2, 1] * size, after_list - end - - def test_describe_first_structure - x1 = x2 = y = z = nil - x = describe "top-level thingy" do - y = describe "first thingy" do end - - x1 = it "top level it" do end - x2 = it "не латинÑкие &ã„ã£ãŸ α, β, γ, δ, ε hello!!! world" do end - - z = describe "second thingy" do end - end - - test_methods = ["test_0001_top level it", - "test_0002_не латинÑкие &ã„ã£ãŸ α, β, γ, δ, ε hello!!! world", - ].sort - - assert_equal test_methods, [x1, x2] - assert_equal test_methods, x.instance_methods.grep(/^test/).map(&:to_s).sort - assert_equal [], y.instance_methods.grep(/^test/) - assert_equal [], z.instance_methods.grep(/^test/) - end - - def test_structure_subclasses - z = nil - x = Class.new Minitest::Spec do - def xyz; end - end - y = Class.new x do - z = describe("inner") { } - end - - assert_respond_to x.new(nil), "xyz" - assert_respond_to y.new(nil), "xyz" - assert_respond_to z.new(nil), "xyz" - end -end - -class TestSpecInTestCase < MetaMetaMetaTestCase - def setup - super - - Thread.current[:current_spec] = self - @tc = self - @assertion_count = 2 - end - - def assert_triggered expected, klass = Minitest::Assertion - @assertion_count += 1 - - e = assert_raises klass do - yield - end - - msg = e.message.sub(/(---Backtrace---).*/m, "\1") - msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") - - assert_equal expected, msg - end - - def teardown - msg = "expected #{@assertion_count} assertions, not #{@tc.assertions}" - assert_equal @assertion_count, @tc.assertions, msg - end - - def test_expectation - @tc.assert_equal true, _(1).must_equal(1) - end - - def test_expectation_triggered - assert_triggered "Expected: 2\n Actual: 1" do - _(1).must_equal 2 - end - end - - include Minitest::Spec::DSL::InstanceMethods - - def test_expectation_with_a_message - assert_triggered "woot.\nExpected: 2\n Actual: 1" do - _(1).must_equal 2, "woot" - end - end -end - -class ValueMonadTest < Minitest::Test - attr_accessor :struct - - def setup - @struct = { :_ => "a", :value => "b", :expect => "c" } - def @struct.method_missing k # think openstruct - self[k] - end - end - - def test_value_monad_method - assert_equal "a", struct._ - end - - def test_value_monad_value_alias - assert_equal "b", struct.value - end - - def test_value_monad_expect_alias - assert_equal "c", struct.expect - end -end diff --git a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_test.rb b/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_test.rb deleted file mode 100644 index abce54e2f..000000000 --- a/ruby/gems/minitest-5.13.0/test/minitest/test_minitest_test.rb +++ /dev/null @@ -1,1080 +0,0 @@ -# encoding: UTF-8 - -require "pathname" -require "minitest/metametameta" - -if defined? Encoding then - e = Encoding.default_external - if e != Encoding::UTF_8 then - warn "" - warn "" - warn "NOTE: External encoding #{e} is not UTF-8. Tests WILL fail." - warn " Run tests with `RUBYOPT=-Eutf-8 rake` to avoid errors." - warn "" - warn "" - end -end - -class Minitest::Runnable - def whatever # faked for testing - assert true - end -end - -class TestMinitestUnit < MetaMetaMetaTestCase - parallelize_me! - - pwd = Pathname.new File.expand_path Dir.pwd - basedir = Pathname.new(File.expand_path "lib/minitest") + "mini" - basedir = basedir.relative_path_from(pwd).to_s - MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" - BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", - "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] - - def test_filter_backtrace - # this is a semi-lame mix of relative paths. - # I cheated by making the autotest parts not have ./ - bt = (["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29", - "test/test_autotest.rb:422"]) - bt = util_expand_bt bt - - ex = ["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'"] - ex = util_expand_bt ex - - fu = Minitest.filter_backtrace(bt) - - assert_equal ex, fu - end - - def test_filter_backtrace_all_unit - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - ex = bt.clone - fu = Minitest.filter_backtrace(bt) - assert_equal ex, fu - end - - def test_filter_backtrace_unit_starts - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/mini/test.rb:29", - "-e:1"]) - - bt = util_expand_bt bt - - ex = ["-e:1"] - fu = Minitest.filter_backtrace bt - assert_equal ex, fu - end - - # def test_default_runner_is_minitest_unit - # assert_instance_of Minitest::Unit, Minitest::Unit.runner - # end - - def test_infectious_binary_encoding - @tu = Class.new FakeNamedTest do - def test_this_is_not_ascii_assertion - assert_equal "ÐÐÐ", "ёёё" - end - - def test_this_is_non_ascii_failure_message - fail 'ÐÐÐ'.force_encoding('ASCII-8BIT') - end - end - - expected = clean <<-EOM - EF - - Finished in 0.00 - - 1) Error: - FakeNamedTestXX#test_this_is_non_ascii_failure_message: - RuntimeError: ÐÐÐ - FILE:LINE:in `test_this_is_non_ascii_failure_message' - - 2) Failure: - FakeNamedTestXX#test_this_is_not_ascii_assertion [FILE:LINE]: - Expected: \"ÐÐÐ\" - Actual: \"ёёё\" - - 2 runs, 1 assertions, 1 failures, 1 errors, 0 skips - EOM - - assert_report expected - end - - def test_passed_eh_teardown_good - test_class = Class.new FakeNamedTest do - def teardown; assert true; end - def test_omg; assert true; end - end - - test = test_class.new :test_omg - test.run - - refute_predicate test, :error? - assert_predicate test, :passed? - refute_predicate test, :skipped? - end - - def test_passed_eh_teardown_skipped - test_class = Class.new FakeNamedTest do - def teardown; assert true; end - def test_omg; skip "bork"; end - end - - test = test_class.new :test_omg - test.run - - refute_predicate test, :error? - refute_predicate test, :passed? - assert_predicate test, :skipped? - end - - def test_passed_eh_teardown_flunked - test_class = Class.new FakeNamedTest do - def teardown; flunk; end - def test_omg; assert true; end - end - - test = test_class.new :test_omg - test.run - - refute_predicate test, :error? - refute_predicate test, :passed? - refute_predicate test, :skipped? - end - - def util_expand_bt bt - if RUBY_VERSION >= "1.9.0" then - bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } - else - bt - end - end -end - -class TestMinitestUnitInherited < MetaMetaMetaTestCase - def with_overridden_include - Class.class_eval do - def inherited_with_hacks _klass - throw :inherited_hook - end - - alias inherited_without_hacks inherited - alias inherited inherited_with_hacks - alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros - end - - yield - ensure - Class.class_eval do - alias inherited inherited_without_hacks - - undef_method :inherited_with_hacks - undef_method :inherited_without_hacks - end - - refute_respond_to Class, :inherited_with_hacks - refute_respond_to Class, :inherited_without_hacks - end - - def test_inherited_hook_plays_nice_with_others - with_overridden_include do - assert_throws :inherited_hook do - Class.new FakeNamedTest - end - end - end -end - -class TestMinitestRunner < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def test_class_runnables - @assertion_count = 0 - - tc = Class.new(Minitest::Test) - - assert_equal 1, Minitest::Test.runnables.size - assert_equal [tc], Minitest::Test.runnables - end - - def test_run_test - @tu = - Class.new FakeNamedTest do - attr_reader :foo - - def run - @foo = "hi mom!" - r = super - @foo = "okay" - - r - end - - def test_something - assert_equal "hi mom!", foo - end - end - - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_error - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - - def test_error - raise "unhandled exception" - end - end - - expected = clean <<-EOM - E. - - Finished in 0.00 - - 1) Error: - FakeNamedTestXX#test_error: - RuntimeError: unhandled exception - FILE:LINE:in \`test_error\' - - 2 runs, 1 assertions, 0 failures, 1 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_error_teardown - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - - def teardown - raise "unhandled exception" - end - end - - expected = clean <<-EOM - E - - Finished in 0.00 - - 1) Error: - FakeNamedTestXX#test_something: - RuntimeError: unhandled exception - FILE:LINE:in \`teardown\' - - 1 runs, 1 assertions, 0 failures, 1 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_failing - setup_basic_tu - - expected = clean <<-EOM - F. - - Finished in 0.00 - - 1) Failure: - FakeNamedTestXX#test_failure [FILE:LINE]: - Expected false to be truthy. - - 2 runs, 2 assertions, 1 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def setup_basic_tu - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - - def test_failure - assert false - end - end - end - - def test_run_failing_filtered - setup_basic_tu - - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected, %w[--name /some|thing/ --seed 42] - end - - def assert_filtering filter, name, expected, a = false - args = %W[--#{filter} #{name} --seed 42] - - alpha = Class.new FakeNamedTest do - define_method :test_something do - assert a - end - end - Object.const_set(:Alpha, alpha) - - beta = Class.new FakeNamedTest do - define_method :test_something do - assert true - end - end - Object.const_set(:Beta, beta) - - @tus = [alpha, beta] - - assert_report expected, args - ensure - Object.send :remove_const, :Alpha - Object.send :remove_const, :Beta - end - - def test_run_filtered_including_suite_name - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "name", "/Beta#test_something/", expected - end - - def test_run_filtered_including_suite_name_string - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "name", "Beta#test_something", expected - end - - def test_run_filtered_string_method_only - expected = clean <<-EOM - .. - - Finished in 0.00 - - 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "name", "test_something", expected, :pass - end - - def test_run_failing_excluded - setup_basic_tu - - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected, %w[--exclude /failure/ --seed 42] - end - - def test_run_filtered_excluding_suite_name - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "exclude", "/Alpha#test_something/", expected - end - - def test_run_filtered_excluding_suite_name_string - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "exclude", "Alpha#test_something", expected - end - - def test_run_filtered_excluding_string_method_only - expected = clean <<-EOM - - - Finished in 0.00 - - 0 runs, 0 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "exclude", "test_something", expected, :pass - end - - def test_run_passing - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - end - - expected = clean <<-EOM - . - - Finished in 0.00 - - 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_skip - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - - def test_skip - skip "not yet" - end - end - - expected = clean <<-EOM - S. - - Finished in 0.00 - - 2 runs, 1 assertions, 0 failures, 0 errors, 1 skips - - You have skipped tests. Run with --verbose for details. - EOM - - restore_env do - assert_report expected - end - end - - def test_run_skip_verbose - @tu = - Class.new FakeNamedTest do - def test_something - assert true - end - - def test_skip - skip "not yet" - end - end - - expected = clean <<-EOM - FakeNamedTestXX#test_skip = 0.00 s = S - FakeNamedTestXX#test_something = 0.00 s = . - - Finished in 0.00 - - 1) Skipped: - FakeNamedTestXX#test_skip [FILE:LINE]: - not yet - - 2 runs, 1 assertions, 0 failures, 0 errors, 1 skips - EOM - - assert_report expected, %w[--seed 42 --verbose] - end - - def test_run_with_other_runner - @tu = - Class.new FakeNamedTest do - def self.run reporter, options = {} - @reporter = reporter - before_my_suite - super - end - - def self.name; "wacky!" end - - def self.before_my_suite - @reporter.io.puts "Running #{self.name} tests" - @@foo = 1 - end - - def test_something - assert_equal 1, @@foo - end - - def test_something_else - assert_equal 1, @@foo - end - end - - expected = clean <<-EOM - Running wacky! tests - .. - - Finished in 0.00 - - 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - require "monitor" - - class Latch - def initialize count = 1 - @count = count - @lock = Monitor.new - @cv = @lock.new_cond - end - - def release - @lock.synchronize do - @count -= 1 if @count > 0 - @cv.broadcast if @count == 0 - end - end - - def await - @lock.synchronize { @cv.wait_while { @count > 0 } } - end - end - - def test_run_parallel - test_count = 2 - test_latch = Latch.new test_count - wait_latch = Latch.new test_count - main_latch = Latch.new - - thread = Thread.new { - Thread.current.abort_on_exception = true - - # This latch waits until both test latches have been released. Both - # latches can't be released unless done in separate threads because - # `main_latch` keeps the test method from finishing. - test_latch.await - main_latch.release - } - - @tu = - Class.new FakeNamedTest do - parallelize_me! - - test_count.times do |i| - define_method :"test_wait_on_main_thread_#{i}" do - test_latch.release - - # This latch blocks until the "main thread" releases it. The main - # thread can't release this latch until both test latches have - # been released. This forces the latches to be released in separate - # threads. - main_latch.await - assert true - end - end - end - - expected = clean <<-EOM - .. - - Finished in 0.00 - - 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report(expected) do |reporter| - reporter.extend(Module.new { - define_method("record") do |result| - super(result) - wait_latch.release - end - - define_method("report") do - wait_latch.await - super() - end - }) - end - assert thread.join - end -end - -class TestMinitestUnitOrder < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def test_before_setup - call_order = [] - @tu = - Class.new FakeNamedTest do - define_method :setup do - super() - call_order << :setup - end - - define_method :before_setup do - call_order << :before_setup - end - - def test_omg; assert true; end - end - - run_tu_with_fresh_reporter - - expected = [:before_setup, :setup] - assert_equal expected, call_order - end - - def test_after_teardown - call_order = [] - @tu = - Class.new FakeNamedTest do - define_method :teardown do - super() - call_order << :teardown - end - - define_method :after_teardown do - call_order << :after_teardown - end - - def test_omg; assert true; end - end - - run_tu_with_fresh_reporter - - expected = [:teardown, :after_teardown] - assert_equal expected, call_order - end - - def test_all_teardowns_are_guaranteed_to_run - call_order = [] - @tu = - Class.new FakeNamedTest do - define_method :after_teardown do - super() - call_order << :after_teardown - raise - end - - define_method :teardown do - super() - call_order << :teardown - raise - end - - define_method :before_teardown do - super() - call_order << :before_teardown - raise - end - - def test_omg; assert true; end - end - - run_tu_with_fresh_reporter - - expected = [:before_teardown, :teardown, :after_teardown] - assert_equal expected, call_order - end - - def test_setup_and_teardown_survive_inheritance - call_order = [] - - @tu = Class.new FakeNamedTest do - define_method :setup do - call_order << :setup_method - end - - define_method :teardown do - call_order << :teardown_method - end - - define_method :test_something do - call_order << :test - end - end - - run_tu_with_fresh_reporter - - @tu = Class.new @tu - run_tu_with_fresh_reporter - - # Once for the parent class, once for the child - expected = [:setup_method, :test, :teardown_method] * 2 - - assert_equal expected, call_order - end -end - -class TestMinitestRunnable < Minitest::Test - def setup_marshal klass - tc = klass.new "whatever" - tc.assertions = 42 - tc.failures << "a failure" - - yield tc if block_given? - - def tc.setup - @blah = "blah" - end - tc.setup - - @tc = Minitest::Result.from tc - end - - def assert_marshal expected_ivars - new_tc = Marshal.load Marshal.dump @tc - - ivars = new_tc.instance_variables.map(&:to_s).sort - assert_equal expected_ivars, ivars - assert_equal "whatever", new_tc.name - assert_equal 42, new_tc.assertions - assert_equal ["a failure"], new_tc.failures - - yield new_tc if block_given? - end - - def test_marshal - setup_marshal Minitest::Runnable - - assert_marshal %w[@NAME @assertions @failures @klass @source_location @time] - end - - def test_spec_marshal - klass = describe("whatever") { it("passes") { assert true } } - rm = klass.runnable_methods.first - - # Run the test - @tc = klass.new(rm).run - - assert_kind_of Minitest::Result, @tc - - # Pass it over the wire - over_the_wire = Marshal.load Marshal.dump @tc - - assert_equal @tc.time, over_the_wire.time - assert_equal @tc.name, over_the_wire.name - assert_equal @tc.assertions, over_the_wire.assertions - assert_equal @tc.failures, over_the_wire.failures - assert_equal @tc.klass, over_the_wire.klass - end -end - -class TestMinitestTest < TestMinitestRunnable - def test_dup - setup_marshal Minitest::Test do |tc| - tc.time = 3.14 - end - - assert_marshal %w[@NAME @assertions @failures @klass @source_location @time] do |new_tc| - assert_in_epsilon 3.14, new_tc.time - end - end -end - -class TestMinitestUnitTestCase < Minitest::Test - # do not call parallelize_me! - teardown accesses @tc._assertions - # which is not threadsafe. Nearly every method in here is an - # assertion test so it isn't worth splitting it out further. - - RUBY18 = !defined? Encoding - - def setup - super - - Minitest::Test.reset - - @tc = Minitest::Test.new "fake tc" - @zomg = "zomg ponies!" - @assertion_count = 1 - end - - def teardown - assert_equal(@assertion_count, @tc.assertions, - "expected #{@assertion_count} assertions to be fired during the test, not #{@tc.assertions}") if @tc.passed? - end - - def non_verbose - orig_verbose = $VERBOSE - $VERBOSE = false - - yield - ensure - $VERBOSE = orig_verbose - end - - def test_runnable_methods_random - @assertion_count = 0 - - sample_test_case = Class.new FakeNamedTest do - def self.test_order; :random; end - def test_test1; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test3; assert "does not matter" end - end - - srand 42 - expected = %w[test_test2 test_test1 test_test3] - assert_equal expected, sample_test_case.runnable_methods - end - - def test_runnable_methods_sorted - @assertion_count = 0 - - sample_test_case = Class.new FakeNamedTest do - def self.test_order; :sorted end - def test_test3; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test1; assert "does not matter" end - end - - expected = %w[test_test1 test_test2 test_test3] - assert_equal expected, sample_test_case.runnable_methods - end - - def test_i_suck_and_my_tests_are_order_dependent_bang_sets_test_order_alpha - @assertion_count = 0 - - shitty_test_case = Class.new FakeNamedTest - - shitty_test_case.i_suck_and_my_tests_are_order_dependent! - - assert_equal :alpha, shitty_test_case.test_order - end - - def test_i_suck_and_my_tests_are_order_dependent_bang_does_not_warn - @assertion_count = 0 - - shitty_test_case = Class.new FakeNamedTest - - def shitty_test_case.test_order; :lol end - - assert_silent do - shitty_test_case.i_suck_and_my_tests_are_order_dependent! - end - end - - def test_autorun_does_not_affect_fork_success_status - @assertion_count = 0 - skip "windows doesn't have skip" unless Process.respond_to?(:fork) - Process.waitpid(fork {}) - assert_equal true, $?.success? - end - - def test_autorun_does_not_affect_fork_exit_status - @assertion_count = 0 - skip "windows doesn't have skip" unless Process.respond_to?(:fork) - Process.waitpid(fork { exit 42 }) - assert_equal 42, $?.exitstatus - end -end - -class TestMinitestGuard < Minitest::Test - parallelize_me! - - def test_mri_eh - assert self.class.mri? "ruby blah" - assert self.mri? "ruby blah" - end - - def test_jruby_eh - assert self.class.jruby? "java" - assert self.jruby? "java" - end - - def test_rubinius_eh - assert_output "", /DEPRECATED/ do - assert self.class.rubinius? "rbx" - end - assert_output "", /DEPRECATED/ do - assert self.rubinius? "rbx" - end - end - - def test_maglev_eh - assert_output "", /DEPRECATED/ do - assert self.class.maglev? "maglev" - end - assert_output "", /DEPRECATED/ do - assert self.maglev? "maglev" - end - end - - def test_osx_eh - assert self.class.osx? "darwin" - assert self.osx? "darwin" - end - - def test_windows_eh - assert self.class.windows? "mswin" - assert self.windows? "mswin" - end -end - -class TestMinitestUnitRecording < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def assert_run_record *expected, &block - @tu = Class.new FakeNamedTest, &block - - run_tu_with_fresh_reporter - - recorded = first_reporter.results.map(&:failures).flatten.map { |f| f.error.class } - - assert_equal expected, recorded - end - - def test_run_with_bogus_reporter - # https://github.com/seattlerb/minitest/issues/659 - # TODO: remove test for minitest 6 - @tu = Class.new FakeNamedTest do - def test_method - assert true - end - end - - bogus_reporter = Class.new do # doesn't subclass AbstractReporter - def start; @success = false; end - # def prerecord klass, name; end # doesn't define full API - def record result; @success = true; end - def report; end - def passed?; end - def results; end - def success?; @success; end - end.new - - self.reporter = Minitest::CompositeReporter.new - reporter << bogus_reporter - - Minitest::Runnable.runnables.delete @tu - - @tu.run reporter, {} - - assert_predicate bogus_reporter, :success? - end - - def test_record_passing - assert_run_record do - def test_method - assert true - end - end - end - - def test_record_failing - assert_run_record Minitest::Assertion do - def test_method - assert false - end - end - end - - def test_record_error - assert_run_record RuntimeError do - def test_method - raise "unhandled exception" - end - end - end - - def test_record_error_teardown - assert_run_record RuntimeError do - def test_method - assert true - end - - def teardown - raise "unhandled exception" - end - end - end - - def test_record_error_in_test_and_teardown - assert_run_record AnError, RuntimeError do - def test_method - raise AnError - end - - def teardown - raise "unhandled exception" - end - end - end - - def test_to_s_error_in_test_and_teardown - @tu = Class.new FakeNamedTest do - def test_method - raise AnError - end - - def teardown - raise "unhandled exception" - end - end - - run_tu_with_fresh_reporter - - exp = clean " - Error: - FakeNamedTestXX#test_method: - AnError: AnError - FILE:LINE:in `test_method' - - Error: - FakeNamedTestXX#test_method: - RuntimeError: unhandled exception - FILE:LINE:in `teardown' - " - - assert_equal exp.strip, normalize_output(first_reporter.results.first.to_s).strip - end - - def test_record_skip - assert_run_record Minitest::Skip do - def test_method - skip "not yet" - end - end - end -end diff --git a/ruby/gems/net-telnet-0.2.0.gem b/ruby/gems/net-telnet-0.2.0.gem deleted file mode 100644 index 2230468d0..000000000 Binary files a/ruby/gems/net-telnet-0.2.0.gem and /dev/null differ diff --git a/ruby/gems/net-telnet-0.2.0/.gitignore b/ruby/gems/net-telnet-0.2.0/.gitignore deleted file mode 100644 index 0cb6eeb06..000000000 --- a/ruby/gems/net-telnet-0.2.0/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/.bundle/ -/.yardoc -/Gemfile.lock -/_yardoc/ -/coverage/ -/doc/ -/pkg/ -/spec/reports/ -/tmp/ diff --git a/ruby/gems/net-telnet-0.2.0/.travis.yml b/ruby/gems/net-telnet-0.2.0/.travis.yml deleted file mode 100644 index 7fe63c52e..000000000 --- a/ruby/gems/net-telnet-0.2.0/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: ruby -rvm: - - 2.3.6 - - 2.4.3 - - 2.5.0 - - ruby-head - -script: - - rake test - - mspec diff --git a/ruby/gems/net-telnet-0.2.0/Gemfile b/ruby/gems/net-telnet-0.2.0/Gemfile deleted file mode 100644 index 7ad7e3431..000000000 --- a/ruby/gems/net-telnet-0.2.0/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'https://rubygems.org' - -# Specify your gem's dependencies in net-telnet.gemspec -gemspec diff --git a/ruby/gems/net-telnet-0.2.0/LICENSE.txt b/ruby/gems/net-telnet-0.2.0/LICENSE.txt deleted file mode 100644 index a1f19ff99..000000000 --- a/ruby/gems/net-telnet-0.2.0/LICENSE.txt +++ /dev/null @@ -1,56 +0,0 @@ -Ruby is copyrighted free software by Yukihiro Matsumoto . -You can redistribute it and/or modify it under either the terms of the -2-clause BSDL (see the file BSDL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. diff --git a/ruby/gems/net-telnet-0.2.0/README.md b/ruby/gems/net-telnet-0.2.0/README.md deleted file mode 100644 index 9e11229da..000000000 --- a/ruby/gems/net-telnet-0.2.0/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Net::Telnet - -[![Build Status](https://travis-ci.org/ruby/net-telnet.svg?branch=master)](https://travis-ci.org/ruby/net-telnet) - -Provides telnet client functionality. - -This class also has, through delegation, all the methods of a socket object (by default, a **TCPSocket**, but can be set by the **Proxy** option to ```new()```). This provides methods such as ```close()``` to end the session and ```sysread()``` to read data directly from the host, instead of via the ```waitfor()``` mechanism. Note that if you do use ```sysread()``` directly when in telnet mode, you should probably pass the output through ```preprocess()``` to extract telnet command sequences. - -## Installation - -Add this line to your application's Gemfile: - -```ruby -gem 'net-telnet' -``` - -And then execute: - - $ bundle - -Or install it yourself as: - - $ gem install net-telnet - -## Usage - -### Log in and send a command, echoing all output to stdout - -```ruby -localhost = Net::Telnet::new("Host" => "localhost", - "Timeout" => 10, - "Prompt" => /[$%#>] \z/n) -localhost.login("username", "password") { |c| print c } -localhost.cmd("command") { |c| print c } -localhost.close -``` - -### Check a POP server to see if you have mail - -```ruby -pop = Net::Telnet::new("Host" => "your_destination_host_here", - "Port" => 110, - "Telnetmode" => false, - "Prompt" => /^\+OK/n) -pop.cmd("user " + "your_username_here") { |c| print c } -pop.cmd("pass " + "your_password_here") { |c| print c } -pop.cmd("list") { |c| print c } -``` - -## Development - -After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. - -To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). - -## Contributing - -1. Fork it ( https://github.com/ruby/net-telnet/fork ) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create a new Pull Request diff --git a/ruby/gems/net-telnet-0.2.0/Rakefile b/ruby/gems/net-telnet-0.2.0/Rakefile deleted file mode 100644 index 4bd5f69be..000000000 --- a/ruby/gems/net-telnet-0.2.0/Rakefile +++ /dev/null @@ -1,9 +0,0 @@ -require "bundler/gem_tasks" -require 'rake/testtask' - -Rake::TestTask.new do |t| - t.libs << "test" - t.test_files = FileList['test/test_*.rb'] -end - -task(default: :test) diff --git a/ruby/gems/net-telnet-0.2.0/bin/console b/ruby/gems/net-telnet-0.2.0/bin/console deleted file mode 100755 index 83f6eec91..000000000 --- a/ruby/gems/net-telnet-0.2.0/bin/console +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby - -require "bundler/setup" -require "net/telnet" - -# You can add fixtures and/or initialization code here to make experimenting -# with your gem easier. You can also use a different console, if you like. - -# (If you use this, don't forget to add pry to your Gemfile!) -# require "pry" -# Pry.start - -require "irb" -IRB.start diff --git a/ruby/gems/net-telnet-0.2.0/bin/setup b/ruby/gems/net-telnet-0.2.0/bin/setup deleted file mode 100755 index b65ed50ff..000000000 --- a/ruby/gems/net-telnet-0.2.0/bin/setup +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -euo pipefail -IFS=$'\n\t' - -bundle install - -# Do any other automated setup that you need to do here diff --git a/ruby/gems/net-telnet-0.2.0/lib/net-telnet.rb b/ruby/gems/net-telnet-0.2.0/lib/net-telnet.rb deleted file mode 100644 index 3546d5327..000000000 --- a/ruby/gems/net-telnet-0.2.0/lib/net-telnet.rb +++ /dev/null @@ -1 +0,0 @@ -require 'net/telnet' diff --git a/ruby/gems/net-telnet-0.2.0/lib/net/telnet.rb b/ruby/gems/net-telnet-0.2.0/lib/net/telnet.rb deleted file mode 100644 index 43764f27e..000000000 --- a/ruby/gems/net-telnet-0.2.0/lib/net/telnet.rb +++ /dev/null @@ -1,763 +0,0 @@ -# = net/telnet.rb - Simple Telnet Client Library -# -# Author:: Wakou Aoyama -# Documentation:: William Webber and Wakou Aoyama -# -# This file holds the class Net::Telnet, which provides client-side -# telnet functionality. -# -# For documentation, see Net::Telnet. -# - -require "net/protocol" -require "English" - -module Net - - # - # == Net::Telnet - # - # Provides telnet client functionality. - # - # This class also has, through delegation, all the methods of a - # socket object (by default, a +TCPSocket+, but can be set by the - # +Proxy+ option to new()). This provides methods such as - # close() to end the session and sysread() to read - # data directly from the host, instead of via the waitfor() - # mechanism. Note that if you do use sysread() directly - # when in telnet mode, you should probably pass the output through - # preprocess() to extract telnet command sequences. - # - # == Overview - # - # The telnet protocol allows a client to login remotely to a user - # account on a server and execute commands via a shell. The equivalent - # is done by creating a Net::Telnet class with the +Host+ option - # set to your host, calling #login() with your user and password, - # issuing one or more #cmd() calls, and then calling #close() - # to end the session. The #waitfor(), #print(), #puts(), and - # #write() methods, which #cmd() is implemented on top of, are - # only needed if you are doing something more complicated. - # - # A Net::Telnet object can also be used to connect to non-telnet - # services, such as SMTP or HTTP. In this case, you normally - # want to provide the +Port+ option to specify the port to - # connect to, and set the +Telnetmode+ option to false to prevent - # the client from attempting to interpret telnet command sequences. - # Generally, #login() will not work with other protocols, and you - # have to handle authentication yourself. - # - # For some protocols, it will be possible to specify the +Prompt+ - # option once when you create the Telnet object and use #cmd() calls; - # for others, you will have to specify the response sequence to - # look for as the Match option to every #cmd() call, or call - # #puts() and #waitfor() directly; for yet others, you will have - # to use #sysread() instead of #waitfor() and parse server - # responses yourself. - # - # It is worth noting that when you create a new Net::Telnet object, - # you can supply a proxy IO channel via the Proxy option. This - # can be used to attach the Telnet object to other Telnet objects, - # to already open sockets, or to any read-write IO object. This - # can be useful, for instance, for setting up a test fixture for - # unit testing. - # - # == Examples - # - # === Log in and send a command, echoing all output to stdout - # - # localhost = Net::Telnet::new("Host" => "localhost", - # "Timeout" => 10, - # "Prompt" => /[$%#>] \z/n) - # localhost.login("username", "password") { |c| print c } - # localhost.cmd("command") { |c| print c } - # localhost.close - # - # - # === Check a POP server to see if you have mail - # - # pop = Net::Telnet::new("Host" => "your_destination_host_here", - # "Port" => 110, - # "Telnetmode" => false, - # "Prompt" => /^\+OK/n) - # pop.cmd("user " + "your_username_here") { |c| print c } - # pop.cmd("pass " + "your_password_here") { |c| print c } - # pop.cmd("list") { |c| print c } - # - # == References - # - # There are a large number of RFCs relevant to the Telnet protocol. - # RFCs 854-861 define the base protocol. For a complete listing - # of relevant RFCs, see - # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html - # - class Telnet - - # :stopdoc: - IAC = 255.chr # "\377" # "\xff" # interpret as command - DONT = 254.chr # "\376" # "\xfe" # you are not to use option - DO = 253.chr # "\375" # "\xfd" # please, you use option - WONT = 252.chr # "\374" # "\xfc" # I won't use option - WILL = 251.chr # "\373" # "\xfb" # I will use option - SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation - GA = 249.chr # "\371" # "\xf9" # you may reverse the line - EL = 248.chr # "\370" # "\xf8" # erase the current line - EC = 247.chr # "\367" # "\xf7" # erase the current character - AYT = 246.chr # "\366" # "\xf6" # are you there - AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish - IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently - BREAK = 243.chr # "\363" # "\xf3" # break - DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning - NOP = 241.chr # "\361" # "\xf1" # nop - SE = 240.chr # "\360" # "\xf0" # end sub negotiation - EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode) - ABORT = 238.chr # "\356" # "\xee" # Abort process - SUSP = 237.chr # "\355" # "\xed" # Suspend process - EOF = 236.chr # "\354" # "\xec" # End of file - SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls - - OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission - OPT_ECHO = 1.chr # "\001" # "\x01" # Echo - OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection - OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead - OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation - OPT_STATUS = 5.chr # "\005" # "\x05" # Status - OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark - OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo - OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width - OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size - OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition - OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops - OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition - OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition - OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops - OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition - OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition - OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII - OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout - OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro - OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal - OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP - OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output - OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location - OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type - OPT_EOR = 25.chr # "\031" # "\x19" # End of Record - OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification - OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking - OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number - OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime - OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD - OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size - OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed - OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control - OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode - OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location - OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option - OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option - OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option - OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option - OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List - - NULL = "\000" - CR = "\015" - LF = "\012" - EOL = CR + LF - REVISION = '$Id$' - # :startdoc: - - # - # Creates a new Net::Telnet object. - # - # Attempts to connect to the host (unless the Proxy option is - # provided: see below). If a block is provided, it is yielded - # status messages on the attempt to connect to the server, of - # the form: - # - # Trying localhost... - # Connected to localhost. - # - # +options+ is a hash of options. The following example lists - # all options and their default values. - # - # host = Net::Telnet::new( - # "Host" => "localhost", # default: "localhost" - # "Port" => 23, # default: 23 - # "Binmode" => false, # default: false - # "Output_log" => "output_log", # default: nil (no output) - # "Dump_log" => "dump_log", # default: nil (no output) - # "Prompt" => /[$%#>] \z/n, # default: /[$%#>] \z/n - # "Telnetmode" => true, # default: true - # "Timeout" => 10, # default: 10 - # # if ignore timeout then set "Timeout" to false. - # "Waittime" => 0, # default: 0 - # "Proxy" => proxy # default: nil - # # proxy is Net::Telnet or IO object - # ) - # - # The options have the following meanings: - # - # Host:: the hostname or IP address of the host to connect to, as a String. - # Defaults to "localhost". - # - # Port:: the port to connect to. Defaults to 23. - # - # Binmode:: if false (the default), newline substitution is performed. - # Outgoing LF is - # converted to CRLF, and incoming CRLF is converted to LF. If - # true, this substitution is not performed. This value can - # also be set with the #binmode() method. The - # outgoing conversion only applies to the #puts() and #print() - # methods, not the #write() method. The precise nature of - # the newline conversion is also affected by the telnet options - # SGA and BIN. - # - # Output_log:: the name of the file to write connection status messages - # and all received traffic to. In the case of a proper - # Telnet session, this will include the client input as - # echoed by the host; otherwise, it only includes server - # responses. Output is appended verbatim to this file. - # By default, no output log is kept. - # - # Dump_log:: as for Output_log, except that output is written in hexdump - # format (16 bytes per line as hex pairs, followed by their - # printable equivalent), with connection status messages - # preceded by '#', sent traffic preceded by '>', and - # received traffic preceded by '<'. By default, not dump log - # is kept. - # - # Prompt:: a regular expression matching the host's command-line prompt - # sequence. This is needed by the Telnet class to determine - # when the output from a command has finished and the host is - # ready to receive a new command. By default, this regular - # expression is /[$%#>] \z/n. - # - # Telnetmode:: a boolean value, true by default. In telnet mode, - # traffic received from the host is parsed for special - # command sequences, and these sequences are escaped - # in outgoing traffic sent using #puts() or #print() - # (but not #write()). If you are using the Net::Telnet - # object to connect to a non-telnet service (such as - # SMTP or POP), this should be set to "false" to prevent - # undesired data corruption. This value can also be set - # by the #telnetmode() method. - # - # Timeout:: the number of seconds to wait before timing out both the - # initial attempt to connect to host (in this constructor), - # which raises a Net::OpenTimeout, and all attempts to read data - # from the host, which raises a Net::ReadTimeout (in #waitfor(), - # #cmd(), and #login()). The default value is 10 seconds. - # You can disable the timeout by setting this value to false. - # In this case, the connect attempt will eventually timeout - # on the underlying connect(2) socket call with an - # Errno::ETIMEDOUT error (but generally only after a few - # minutes), but other attempts to read data from the host - # will hang indefinitely if no data is forthcoming. - # - # Waittime:: the amount of time to wait after seeing what looks like a - # prompt (that is, received data that matches the Prompt - # option regular expression) to see if more data arrives. - # If more data does arrive in this time, Net::Telnet assumes - # that what it saw was not really a prompt. This is to try to - # avoid false matches, but it can also lead to missing real - # prompts (if, for instance, a background process writes to - # the terminal soon after the prompt is displayed). By - # default, set to 0, meaning not to wait for more data. - # - # Proxy:: a proxy object to used instead of opening a direct connection - # to the host. Must be either another Net::Telnet object or - # an IO object. If it is another Net::Telnet object, this - # instance will use that one's socket for communication. If an - # IO object, it is used directly for communication. Any other - # kind of object will cause an error to be raised. - # - def initialize(options) # :yield: mesg - @options = options - @options["Host"] = "localhost" unless @options.has_key?("Host") - @options["Port"] = 23 unless @options.has_key?("Port") - @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt") - @options["Timeout"] = 10 unless @options.has_key?("Timeout") - @options["Waittime"] = 0 unless @options.has_key?("Waittime") - unless @options.has_key?("Binmode") - @options["Binmode"] = false - else - unless (true == @options["Binmode"] or false == @options["Binmode"]) - raise ArgumentError, "Binmode option must be true or false" - end - end - - unless @options.has_key?("Telnetmode") - @options["Telnetmode"] = true - else - unless (true == @options["Telnetmode"] or false == @options["Telnetmode"]) - raise ArgumentError, "Telnetmode option must be true or false" - end - end - - @telnet_option = { "SGA" => false, "BINARY" => false } - - if @options.has_key?("Output_log") - @log = File.open(@options["Output_log"], 'a+') - @log.sync = true - @log.binmode - end - - if @options.has_key?("Dump_log") - @dumplog = File.open(@options["Dump_log"], 'a+') - @dumplog.sync = true - @dumplog.binmode - def @dumplog.log_dump(dir, x) # :nodoc: - len = x.length - addr = 0 - offset = 0 - while 0 < len - if len < 16 - line = x[offset, len] - else - line = x[offset, 16] - end - hexvals = line.unpack('H*')[0] - hexvals += ' ' * (32 - hexvals.length) - hexvals = format("%s %s %s %s " * 4, *hexvals.unpack('a2' * 16)) - line = line.gsub(/[\000-\037\177-\377]/n, '.') - printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line - addr += 16 - offset += 16 - len -= 16 - end - print "\n" - end - end - - if @options.has_key?("Proxy") - if @options["Proxy"].kind_of?(Net::Telnet) - @sock = @options["Proxy"].sock - elsif @options["Proxy"].kind_of?(IO) - @sock = @options["Proxy"] - else - raise "Error: Proxy must be an instance of Net::Telnet or IO." - end - else - message = "Trying " + @options["Host"] + "...\n" - yield(message) if block_given? - @log.write(message) if @options.has_key?("Output_log") - @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") - - begin - if @options["Timeout"] == false - @sock = TCPSocket.open(@options["Host"], @options["Port"]) - else - Timeout.timeout(@options["Timeout"], Net::OpenTimeout) do - @sock = TCPSocket.open(@options["Host"], @options["Port"]) - end - end - rescue Net::OpenTimeout - raise Net::OpenTimeout, "timed out while opening a connection to the host" - rescue - @log.write($ERROR_INFO.to_s + "\n") if @options.has_key?("Output_log") - @dumplog.log_dump('#', $ERROR_INFO.to_s + "\n") if @options.has_key?("Dump_log") - raise - end - @sock.sync = true - @sock.binmode - - message = "Connected to " + @options["Host"] + ".\n" - yield(message) if block_given? - @log.write(message) if @options.has_key?("Output_log") - @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") - end - - end # initialize - - # The socket the Telnet object is using. Note that this object becomes - # a delegate of the Telnet object, so normally you invoke its methods - # directly on the Telnet object. - attr_reader :sock - - # Set telnet command interpretation on (+mode+ == true) or off - # (+mode+ == false), or return the current value (+mode+ not - # provided). It should be on for true telnet sessions, off if - # using Net::Telnet to connect to a non-telnet service such - # as SMTP. - def telnetmode(mode = nil) - case mode - when nil - @options["Telnetmode"] - when true, false - @options["Telnetmode"] = mode - else - raise ArgumentError, "argument must be true or false, or missing" - end - end - - # Turn telnet command interpretation on (true) or off (false). It - # should be on for true telnet sessions, off if using Net::Telnet - # to connect to a non-telnet service such as SMTP. - def telnetmode=(mode) - if (true == mode or false == mode) - @options["Telnetmode"] = mode - else - raise ArgumentError, "argument must be true or false" - end - end - - # Turn newline conversion on (+mode+ == false) or off (+mode+ == true), - # or return the current value (+mode+ is not specified). - def binmode(mode = nil) - case mode - when nil - @options["Binmode"] - when true, false - @options["Binmode"] = mode - else - raise ArgumentError, "argument must be true or false" - end - end - - # Turn newline conversion on (false) or off (true). - def binmode=(mode) - if (true == mode or false == mode) - @options["Binmode"] = mode - else - raise ArgumentError, "argument must be true or false" - end - end - - # Preprocess received data from the host. - # - # Performs newline conversion and detects telnet command sequences. - # Called automatically by #waitfor(). You should only use this - # method yourself if you have read input directly using sysread() - # or similar, and even then only if in telnet mode. - def preprocess(string) - # combine CR+NULL into CR - string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"] - - # combine EOL into "\n" - string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"] - - # remove NULL - string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"] - - string.gsub(/#{IAC}( - [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| - [#{DO}#{DONT}#{WILL}#{WONT}] - [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| - #{SB}[^#{IAC}]*#{IAC}#{SE} - )/xno) do - if IAC == $1 # handle escaped IAC characters - IAC - elsif AYT == $1 # respond to "IAC AYT" (are you there) - self.write("nobody here but us pigeons" + EOL) - '' - elsif DO[0] == $1[0] # respond to "IAC DO x" - if OPT_BINARY[0] == $1[1] - @telnet_option["BINARY"] = true - self.write(IAC + WILL + OPT_BINARY) - else - self.write(IAC + WONT + $1[1..1]) - end - '' - elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x" - self.write(IAC + WONT + $1[1..1]) - '' - elsif WILL[0] == $1[0] # respond to "IAC WILL x" - if OPT_BINARY[0] == $1[1] - self.write(IAC + DO + OPT_BINARY) - elsif OPT_ECHO[0] == $1[1] - self.write(IAC + DO + OPT_ECHO) - elsif OPT_SGA[0] == $1[1] - @telnet_option["SGA"] = true - self.write(IAC + DO + OPT_SGA) - else - self.write(IAC + DONT + $1[1..1]) - end - '' - elsif WONT[0] == $1[0] # respond to "IAC WON'T x" - if OPT_ECHO[0] == $1[1] - self.write(IAC + DONT + OPT_ECHO) - elsif OPT_SGA[0] == $1[1] - @telnet_option["SGA"] = false - self.write(IAC + DONT + OPT_SGA) - else - self.write(IAC + DONT + $1[1..1]) - end - '' - else - '' - end - end - end # preprocess - - # Read data from the host until a certain sequence is matched. - # - # If a block is given, the received data will be yielded as it - # is read in (not necessarily all in one go), or nil if EOF - # occurs before any data is received. Whether a block is given - # or not, all data read will be returned in a single string, or again - # nil if EOF occurs before any data is received. Note that - # received data includes the matched sequence we were looking for. - # - # +options+ can be either a regular expression or a hash of options. - # If a regular expression, this specifies the data to wait for. - # If a hash, this can specify the following options: - # - # Match:: a regular expression, specifying the data to wait for. - # Prompt:: as for Match; used only if Match is not specified. - # String:: as for Match, except a string that will be converted - # into a regular expression. Used only if Match and - # Prompt are not specified. - # Timeout:: the number of seconds to wait for data from the host - # before raising a Timeout::Error. If set to false, - # no timeout will occur. If not specified, the - # Timeout option value specified when this instance - # was created will be used, or, failing that, the - # default value of 10 seconds. - # Waittime:: the number of seconds to wait after matching against - # the input data to see if more data arrives. If more - # data arrives within this time, we will judge ourselves - # not to have matched successfully, and will continue - # trying to match. If not specified, the Waittime option - # value specified when this instance was created will be - # used, or, failing that, the default value of 0 seconds, - # which means not to wait for more input. - # FailEOF:: if true, when the remote end closes the connection then an - # EOFError will be raised. Otherwise, defaults to the old - # behaviour that the function will return whatever data - # has been received already, or nil if nothing was received. - # - def waitfor(options) # :yield: recvdata - time_out = @options["Timeout"] - waittime = @options["Waittime"] - fail_eof = @options["FailEOF"] - - if options.kind_of?(Hash) - prompt = if options.has_key?("Match") - options["Match"] - elsif options.has_key?("Prompt") - options["Prompt"] - elsif options.has_key?("String") - Regexp.new( Regexp.quote(options["String"]) ) - end - time_out = options["Timeout"] if options.has_key?("Timeout") - waittime = options["Waittime"] if options.has_key?("Waittime") - fail_eof = options["FailEOF"] if options.has_key?("FailEOF") - else - prompt = options - end - - if time_out == false - time_out = nil - end - - line = '' - buf = '' - rest = '' - until(prompt === line and not @sock.wait_readable(waittime)) - unless @sock.wait_readable(time_out) - raise Net::ReadTimeout, "timed out while waiting for more data" - end - begin - c = @sock.readpartial(1024 * 1024) - @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") - if @options["Telnetmode"] - c = rest + c - if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) < - Integer(c.rindex(/#{IAC}#{SB}/no) || 0) - buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)]) - rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1] - elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) || - c.rindex(/\r\z/no) - buf = preprocess(c[0 ... pt]) - rest = c[pt .. -1] - else - buf = preprocess(c) - rest = '' - end - else - # Not Telnetmode. - # - # We cannot use preprocess() on this data, because that - # method makes some Telnetmode-specific assumptions. - buf = rest + c - rest = '' - unless @options["Binmode"] - if pt = buf.rindex(/\r\z/no) - buf = buf[0 ... pt] - rest = buf[pt .. -1] - end - buf.gsub!(/#{EOL}/no, "\n") - end - end - @log.print(buf) if @options.has_key?("Output_log") - line += buf - yield buf if block_given? - rescue EOFError # End of file reached - raise if fail_eof - if line == '' - line = nil - yield nil if block_given? - end - break - end - end - line - end - - # Write +string+ to the host. - # - # Does not perform any conversions on +string+. Will log +string+ to the - # dumplog, if the Dump_log option is set. - def write(string) - length = string.length - while 0 < length - @sock.wait_writable - @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log") - length -= @sock.syswrite(string[-length..-1]) - end - end - - # Sends a string to the host. - # - # This does _not_ automatically append a newline to the string. Embedded - # newlines may be converted and telnet command sequences escaped - # depending upon the values of telnetmode, binmode, and telnet options - # set by the host. - def print(string) - string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"] - - if @options["Binmode"] - self.write(string) - else - if @telnet_option["BINARY"] and @telnet_option["SGA"] - # IAC WILL SGA IAC DO BIN send EOL --> CR - self.write(string.gsub(/\n/n, CR)) - elsif @telnet_option["SGA"] - # IAC WILL SGA send EOL --> CR+NULL - self.write(string.gsub(/\n/n, CR + NULL)) - else - # NONE send EOL --> CR+LF - self.write(string.gsub(/\n/n, EOL)) - end - end - end - - # Sends a string to the host. - # - # Same as #print(), but appends a newline to the string. - def puts(string) - self.print(string + "\n") - end - - # Send a command to the host. - # - # More exactly, sends a string to the host, and reads in all received - # data until is sees the prompt or other matched sequence. - # - # If a block is given, the received data will be yielded to it as - # it is read in. Whether a block is given or not, the received data - # will be return as a string. Note that the received data includes - # the prompt and in most cases the host's echo of our command. - # - # +options+ is either a String, specified the string or command to - # send to the host; or it is a hash of options. If a hash, the - # following options can be specified: - # - # String:: the command or other string to send to the host. - # Match:: a regular expression, the sequence to look for in - # the received data before returning. If not specified, - # the Prompt option value specified when this instance - # was created will be used, or, failing that, the default - # prompt of /[$%#>] \z/n. - # Timeout:: the seconds to wait for data from the host before raising - # a Timeout error. If not specified, the Timeout option - # value specified when this instance was created will be - # used, or, failing that, the default value of 10 seconds. - # - # The command or other string will have the newline sequence appended - # to it. - def cmd(options) # :yield: recvdata - match = @options["Prompt"] - time_out = @options["Timeout"] - fail_eof = @options["FailEOF"] - - if options.kind_of?(Hash) - string = options["String"] - match = options["Match"] if options.has_key?("Match") - time_out = options["Timeout"] if options.has_key?("Timeout") - fail_eof = options["FailEOF"] if options.has_key?("FailEOF") - else - string = options - end - - self.puts(string) - if block_given? - waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c } - else - waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}) - end - end - - # Login to the host with a given username and password. - # - # The username and password can either be provided as two string - # arguments in that order, or as a hash with keys "Name" and - # "Password". - # - # This method looks for the strings "login" and "Password" from the - # host to determine when to send the username and password. If the - # login sequence does not follow this pattern (for instance, you - # are connecting to a service other than telnet), you will need - # to handle login yourself. - # - # The password can be omitted, either by only - # provided one String argument, which will be used as the username, - # or by providing a has that has no "Password" key. In this case, - # the method will not look for the "Password:" prompt; if it is - # sent, it will have to be dealt with by later calls. - # - # The method returns all data received during the login process from - # the host, including the echoed username but not the password (which - # the host should not echo). If a block is passed in, this received - # data is also yielded to the block as it is received. - def login(options, password = nil) # :yield: recvdata - login_prompt = /[Ll]ogin[: ]*\z/n - password_prompt = /[Pp]ass(?:word|phrase)[: ]*\z/n - if options.kind_of?(Hash) - username = options["Name"] - password = options["Password"] - login_prompt = options["LoginPrompt"] if options["LoginPrompt"] - password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"] - else - username = options - end - - if block_given? - line = waitfor(login_prompt){|c| yield c } - if password - line += cmd({"String" => username, - "Match" => password_prompt}){|c| yield c } - line += cmd(password){|c| yield c } - else - line += cmd(username){|c| yield c } - end - else - line = waitfor(login_prompt) - if password - line += cmd({"String" => username, - "Match" => password_prompt}) - line += cmd(password) - else - line += cmd(username) - end - end - line - end - - # Closes the connection - def close - @sock.close - end - - end # class Telnet -end # module Net - diff --git a/ruby/gems/net-telnet-0.2.0/lib/net/telnet/version.rb b/ruby/gems/net-telnet-0.2.0/lib/net/telnet/version.rb deleted file mode 100644 index 9f98d4418..000000000 --- a/ruby/gems/net-telnet-0.2.0/lib/net/telnet/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Net - class Telnet - VERSION = "0.2.0" - end -end diff --git a/ruby/gems/net-telnet-0.2.0/net-telnet.gemspec b/ruby/gems/net-telnet-0.2.0/net-telnet.gemspec deleted file mode 100644 index 1666c9e6d..000000000 --- a/ruby/gems/net-telnet-0.2.0/net-telnet.gemspec +++ /dev/null @@ -1,37 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: net-telnet 0.2.0 ruby lib - -Gem::Specification.new do |s| - s.name = "net-telnet".freeze - s.version = "0.2.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib".freeze] - s.authors = ["SHIBATA Hiroshi".freeze] - s.bindir = "exe".freeze - s.date = "2018-07-25" - s.description = "Provides telnet client functionality.".freeze - s.email = ["hsbt@ruby-lang.org".freeze] - s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/net-telnet.rb".freeze, "lib/net/telnet.rb".freeze, "lib/net/telnet/version.rb".freeze, "net-telnet.gemspec".freeze] - s.homepage = "https://github.com/ruby/net-telnet".freeze - s.licenses = ["ruby".freeze] - s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) - s.rubygems_version = "3.1.2".freeze - s.summary = "Provides telnet client functionality.".freeze - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - else - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - end -end diff --git a/ruby/gems/power_assert-1.1.7.gem b/ruby/gems/power_assert-1.1.7.gem deleted file mode 100644 index 55ce5fe20..000000000 Binary files a/ruby/gems/power_assert-1.1.7.gem and /dev/null differ diff --git a/ruby/gems/power_assert-1.1.7/.gitignore b/ruby/gems/power_assert-1.1.7/.gitignore deleted file mode 100644 index 7e8259bc1..000000000 --- a/ruby/gems/power_assert-1.1.7/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/.bundle/ -/coverage/ -/Gemfile.local -/Gemfile.lock -/GPATH -/GRTAGS -/GTAGS -/pkg/ -/vendor/ diff --git a/ruby/gems/power_assert-1.1.7/.travis.yml b/ruby/gems/power_assert-1.1.7/.travis.yml deleted file mode 100644 index e53077d26..000000000 --- a/ruby/gems/power_assert-1.1.7/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -sudo: false -language: ruby -rvm: - - 2.0.0-p648 - - 2.1.10 - - 2.2.10 - - 2.3.8 - - 2.4.9 - - 2.5.7 - - 2.6.5 - - 2.7.0 - - ruby-head -env: - - TEST_SYMLINK="no" - - TEST_SYMLINK="yes" -matrix: - allow_failures: - - rvm: ruby-head -before_script: - - bundle exec rake before_script -after_script: - - bundle exec rake after_script diff --git a/ruby/gems/power_assert-1.1.7/BSDL b/ruby/gems/power_assert-1.1.7/BSDL deleted file mode 100644 index a5031274c..000000000 --- a/ruby/gems/power_assert-1.1.7/BSDL +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (C) 2014 Kazuki Tsujimoto - -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. diff --git a/ruby/gems/power_assert-1.1.7/COPYING b/ruby/gems/power_assert-1.1.7/COPYING deleted file mode 100644 index 0dd3c9756..000000000 --- a/ruby/gems/power_assert-1.1.7/COPYING +++ /dev/null @@ -1,57 +0,0 @@ -Copyright (C) 2014 Kazuki Tsujimoto - -You can redistribute it and/or modify it under either the terms of the -2-clause BSDL (see the file BSDL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. diff --git a/ruby/gems/power_assert-1.1.7/Gemfile b/ruby/gems/power_assert-1.1.7/Gemfile deleted file mode 100644 index 7b1328fd1..000000000 --- a/ruby/gems/power_assert-1.1.7/Gemfile +++ /dev/null @@ -1,9 +0,0 @@ -source "http://rubygems.org" - -gemspec - -# https://github.com/redmine/redmine/blob/3.0.4/Gemfile#L101 -local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") -if File.exist?(local_gemfile) - eval_gemfile local_gemfile -end diff --git a/ruby/gems/power_assert-1.1.7/LEGAL b/ruby/gems/power_assert-1.1.7/LEGAL deleted file mode 100644 index d6854ea17..000000000 --- a/ruby/gems/power_assert-1.1.7/LEGAL +++ /dev/null @@ -1,4 +0,0 @@ -LEGAL NOTICE INFORMATION ------------------------- - -All the files in this distribution are written by the author. diff --git a/ruby/gems/power_assert-1.1.7/README.rdoc b/ruby/gems/power_assert-1.1.7/README.rdoc deleted file mode 100644 index 1bb77d0be..000000000 --- a/ruby/gems/power_assert-1.1.7/README.rdoc +++ /dev/null @@ -1,81 +0,0 @@ -= power_assert -== About -Power Assert for Ruby. - -Power Assert shows each value of variables and method calls in the expression. -It is useful for testing, providing which value wasn't correct when the condition is not satisfied. - - Failure: - assert { 3.times.to_a.include?(3) } - | | | - | | false - | [0, 1, 2] - # - -== Related Projects -In general, you don't need to use this library directly. -Use following test frameworks or extensions instead. - -* {test-unit}[https://github.com/test-unit/test-unit](>= 3.0.0) - * {Document}[http://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html#assert-instance_method] -* {minitest-power_assert}[https://github.com/hsbt/minitest-power_assert] -* {rspec-power_assert}[https://github.com/joker1007/rspec-power_assert] -* {pry-power_assert}[https://github.com/yui-knk/pry-power_assert] -* {pry-byebug-power_assert}[https://github.com/k-tsj/pry-byebug-power_assert] -* {power_p}[https://github.com/k-tsj/power_p] - -== Requirement -* CRuby 2.0.0 or later - -== Reference -* {Power Assert in Ruby (at RubyKaigi 2014) // Speaker Deck}[https://speakerdeck.com/k_tsj/power-assert-in-ruby] - -== Known Limitations -* Expressions must be put in one line. Expressions with folded long lines produce nothing report, e.g.: - assert do - # reported - func(foo: 0123456789, bar: "abcdefg") - end - - assert do - # won't be reported - func(foo: 0123456789, - bar: "abcdefg") - end -* Expressions must have one or more method call. Expressions with no method call produce nothing report, e.g.: - val = false - assert do - # reported - val == true - end - - assert do - # won't be reported - val - end -* Returned values from accessor methods, method missing, or "super" produce nothing report, e.g: - class Foo - attr_accessor :val - end - foo = Foo.new - foo.val = false - - assert do - # reported (only the value of "foo" and the literal "true") - foo.val == true - end - - assert do - # won't be reported - foo.val - end -* Expressions should not have conditional branches. Expressions with such conditional codes may produce nothing report, e.g.: - condition = true - expected = false - actual = true - assert do - # this will fail but nothing reported - condition ? expected == actual : expected == actual - end - -== Travis Build Status {}[http://travis-ci.org/k-tsj/power_assert] diff --git a/ruby/gems/power_assert-1.1.7/Rakefile b/ruby/gems/power_assert-1.1.7/Rakefile deleted file mode 100644 index e82d34c1c..000000000 --- a/ruby/gems/power_assert-1.1.7/Rakefile +++ /dev/null @@ -1,59 +0,0 @@ -require "bundler/gem_tasks" -require "rake/testtask" - -task :default => :test -Rake::TestTask.new(:test) do |t| - # helper(simplecov) must be required before loading power_assert - helper_path = File.realpath("test/test_helper.rb") - t.ruby_opts = ["-w", "-r#{helper_path}"] - t.test_files = FileList["test/**/*_test.rb"].exclude do |i| - begin - next false unless defined?(RubyVM) - RubyVM::InstructionSequence.compile(File.read(i)) - false - rescue SyntaxError - true - end - end -end - -# ruby/ruby:test/pathname/test_pathname.rb -def has_symlink? - begin - File.symlink("", "") - rescue NotImplementedError, Errno::EACCES - return false - rescue Errno::ENOENT - end - return true -end - -SYMLINK_DIRS = ["lib", "test"] - -task :before_script do - if ENV["TEST_SYMLINK"] == "yes" and has_symlink? - SYMLINK_DIRS.each do |d| - File.rename(d, ".#{d}") - File.symlink(".#{d}", d) - end - end -end - -task :after_script do - SYMLINK_DIRS.each do |d| - if File.symlink?(d) and File.directory?(".#{d}") - File.unlink(d) - File.rename(".#{d}", d) - end - unless File.directory?(d) - raise "#{d} should be directory" - end - end -end - -desc "Run the benchmark suite" -task :benchmark do - Dir.glob("benchmark/bm_*.rb").each do |f| - load(f) - end -end diff --git a/ruby/gems/power_assert-1.1.7/bin/console b/ruby/gems/power_assert-1.1.7/bin/console deleted file mode 100755 index 30eaef0d6..000000000 --- a/ruby/gems/power_assert-1.1.7/bin/console +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby - -require 'bundler/setup' -require 'power_assert' - -begin - require 'pry' - Pry -rescue LoadError - require 'irb' - IRB -end.start diff --git a/ruby/gems/power_assert-1.1.7/bin/setup b/ruby/gems/power_assert-1.1.7/bin/setup deleted file mode 100755 index cf4ad25e1..000000000 --- a/ruby/gems/power_assert-1.1.7/bin/setup +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -IFS=$'\n\t' -set -vx - -bundle install diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert.rb deleted file mode 100644 index 7eaa5f923..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert.rb +++ /dev/null @@ -1,98 +0,0 @@ -# power_assert.rb -# -# Copyright (C) 2014 Kazuki Tsujimoto - -begin - unless defined?(Byebug) - captured = false - TracePoint.new(:return, :c_return) do |tp| - captured = true - unless tp.binding and tp.return_value - raise '' - end - end.enable { __id__ } - raise '' unless captured - end -rescue - raise LoadError, 'Fully compatible TracePoint API required' -end - -require 'power_assert/version' -require 'power_assert/configuration' -require 'power_assert/context' - -module PowerAssert - POWER_ASSERT_LIB_DIR = File.dirname(caller_locations(1, 1).first.path) - INTERNAL_LIB_DIRS = {PowerAssert => POWER_ASSERT_LIB_DIR} - private_constant :POWER_ASSERT_LIB_DIR, :INTERNAL_LIB_DIRS - - # For backward compatibility - IGNORED_LIB_DIRS = INTERNAL_LIB_DIRS - private_constant :IGNORED_LIB_DIRS - if respond_to?(:deprecate_constant) - deprecate_constant :IGNORED_LIB_DIRS - end - - class << self - def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLEVEL_BINDING) - if respond_to?(:clear_global_method_cache, true) - clear_global_method_cache - end - yield BlockContext.new(assertion_proc_or_source, assertion_method, source_binding) - end - - def trace(frame) - begin - raise 'Byebug is not started yet' unless Byebug.started? - rescue NameError - raise "PowerAssert.#{__method__} requires Byebug" - end - ctx = TraceContext.new(frame._binding) - ctx.enable - ctx - end - - def app_caller_locations - caller_locations.drop_while {|i| internal_file?(i.path) }.take_while {|i| ! internal_file?(i.path) } - end - - def app_context? - top_frame = caller_locations.drop_while {|i| i.path.start_with?(POWER_ASSERT_LIB_DIR) }.first - top_frame and ! internal_file?(top_frame.path) - end - - private - - def internal_file?(file) - setup_internal_lib_dir(Byebug, :attach, 2) if defined?(Byebug) - setup_internal_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug) - INTERNAL_LIB_DIRS.find do |_, dir| - file.start_with?(dir) - end - end - - def setup_internal_lib_dir(lib, mid, depth, lib_obj = lib) - unless INTERNAL_LIB_DIRS.key?(lib) - INTERNAL_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth) - end - rescue NameError - end - - def lib_dir(obj, mid, depth) - File.expand_path('../' * depth, obj.method(mid).source_location[0]) - end - - if defined?(RubyVM) - CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)') - private_constant :CLEAR_CACHE_ISEQ - - def clear_global_method_cache - CLEAR_CACHE_ISEQ.eval - end - end - end - - module Empty - end - private_constant :Empty -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/colorize.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/colorize.rb deleted file mode 100644 index 4c7487a97..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/colorize.rb +++ /dev/null @@ -1,9 +0,0 @@ -warn 'power_assert/colorize is experimental' - -require 'power_assert/configuration' - -PowerAssert.configure do |c| - c.lazy_inspection = true - c._colorize_message = true - c._use_pp = true -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/configuration.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/configuration.rb deleted file mode 100644 index ee101362d..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/configuration.rb +++ /dev/null @@ -1,46 +0,0 @@ -module PowerAssert - class << self - def configuration - @configuration ||= Configuration[false, false, true, false, false] - end - - def configure - yield configuration - end - end - - SUPPORT_ALIAS_METHOD = TracePoint.public_method_defined?(:callee_id) - private_constant :SUPPORT_ALIAS_METHOD - - class Configuration < Struct.new(:lazy_inspection, :_trace_alias_method, :_redefinition, :_colorize_message, :_use_pp) - def _trace_alias_method=(bool) - super - if SUPPORT_ALIAS_METHOD - warn 'power_assert: _trace_alias_method option is obsolete. You no longer have to set it.' - end - end - - def _colorize_message=(bool) - if bool - require 'pry' - end - super - end - - def lazy_inspection=(bool) - unless bool - raise 'lazy_inspection option must be enabled when using pp' if _use_pp - end - super - end - - def _use_pp=(bool) - if bool - raise 'lazy_inspection option must be enabled when using pp' unless lazy_inspection - require 'pp' - end - super - end - end - private_constant :Configuration -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/context.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/context.rb deleted file mode 100644 index 279295e55..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/context.rb +++ /dev/null @@ -1,238 +0,0 @@ -require 'power_assert/configuration' -require 'power_assert/enable_tracepoint_events' -require 'power_assert/inspector' -require 'power_assert/parser' - -module PowerAssert - class Context - Value = Struct.new(:name, :value, :lineno, :column, :display_offset) - - def initialize(base_caller_length) - @fired = false - @target_thread = Thread.current - method_id_set = nil - @return_values = [] - trace_alias_method = PowerAssert.configuration._trace_alias_method - @trace_return = TracePoint.new(:return, :c_return) do |tp| - begin - unless method_id_set - next unless Thread.current == @target_thread - method_id_set = @parser.method_id_set - end - method_id = SUPPORT_ALIAS_METHOD ? tp.callee_id : - trace_alias_method && tp.event == :return ? tp.binding.eval('::Kernel.__callee__') : - tp.method_id - next if ! method_id_set[method_id] - next if tp.event == :c_return and - not (@parser.lineno == tp.lineno and @parser.path == tp.path) - locs = PowerAssert.app_caller_locations - diff = locs.length - base_caller_length - if (tp.event == :c_return && diff == 1 || tp.event == :return && diff <= 2) and Thread.current == @target_thread - idx = -(base_caller_length + 1) - if @parser.path == locs[idx].path and @parser.lineno == locs[idx].lineno - val = PowerAssert.configuration.lazy_inspection ? - tp.return_value : - InspectedValue.new(SafeInspectable.new(tp.return_value).inspect) - @return_values << Value[method_id.to_s, val, locs[idx].lineno, nil] - end - end - rescue Exception => e - warn "power_assert: [BUG] Failed to trace: #{e.class}: #{e.message}" - if e.respond_to?(:full_message) - warn e.full_message.gsub(/^/, 'power_assert: ') - end - end - end - end - - def message - raise 'call #yield or #enable at first' unless fired? - @message ||= build_assertion_message(@parser, @return_values).freeze - end - - def message_proc - -> { message } - end - - private - - def fired? - @fired - end - - def build_assertion_message(parser, return_values) - if PowerAssert.configuration._colorize_message - line = Pry::Code.new(parser.line).highlighted - else - line = parser.line - end - - path = detect_path(parser, return_values) - return line unless path - - c2d = column2display_offset(parser.line) - return_values, methods_in_path = find_all_identified_calls(return_values, path) - return_values.zip(methods_in_path) do |i, j| - unless i.name == j.name - warn "power_assert: [BUG] Failed to get column: #{i.name}" - return line - end - i.display_offset = c2d[j.column] - end - refs_in_path = path.find_all {|i| i.type == :ref } - ref_values = refs_in_path.map {|i| Value[i.name, parser.binding.eval(i.name), parser.lineno, i.column, c2d[i.column]] } - vals = (return_values + ref_values).find_all(&:display_offset).sort_by(&:display_offset).reverse - return line if vals.empty? - - fmt = (0..vals[0].display_offset).map do |i| - if vals.find {|v| v.display_offset == i } - "%<#{i}>s" - else - line[i] == "\t" ? "\t" : ' ' - end - end.join - lines = [] - lines << line.chomp - lines << sprintf(fmt, vals.each_with_object({}) {|v, h| h[v.display_offset.to_s.to_sym] = '|' }).chomp - vals.each do |i| - inspected_val = SafeInspectable.new(Formatter.new(i.value, i.display_offset)).inspect - inspected_val.each_line do |l| - map_to = vals.each_with_object({}) do |j, h| - h[j.display_offset.to_s.to_sym] = [l, '|', ' '][i.display_offset <=> j.display_offset] - end - lines << encoding_safe_rstrip(sprintf(fmt, map_to)) - end - end - lines.join("\n") - end - - def detect_path(parser, return_values) - return parser.call_paths.flatten.uniq if parser.method_id_set.empty? - all_paths = parser.call_paths - return_value_names = return_values.map(&:name) - uniq_calls = uniq_calls(all_paths) - uniq_call = return_value_names.find {|i| uniq_calls.include?(i) } - detected_paths = all_paths.find_all do |path| - method_names = path.find_all {|ident| ident.type == :method }.map(&:name) - break [path] if uniq_call and method_names.include?(uniq_call) - return_value_names == method_names - end - return nil unless detected_paths.length == 1 - detected_paths[0] - end - - def uniq_calls(paths) - all_calls = enum_count_by(paths.map {|path| path.find_all {|ident| ident.type == :method }.map(&:name).uniq }.flatten) {|i| i } - all_calls.find_all {|_, call_count| call_count == 1 }.map {|name, _| name } - end - - def find_all_identified_calls(return_values, path) - return_value_num_of_calls = enum_count_by(return_values, &:name) - path_num_of_calls = enum_count_by(path.find_all {|ident| ident.type == :method }, &:name) - identified_calls = return_value_num_of_calls.find_all {|name, num| path_num_of_calls[name] == num }.map(&:first) - [ - return_values.find_all {|val| identified_calls.include?(val.name) }, - path.find_all {|ident| ident.type == :method and identified_calls.include?(ident.name) } - ] - end - - def enum_count_by(enum, &blk) - Hash[enum.group_by(&blk).map{|k, v| [k, v.length] }] - end - - def encoding_safe_rstrip(str) - str.rstrip - rescue ArgumentError, Encoding::CompatibilityError - enc = str.encoding - if enc.ascii_compatible? - str.b.rstrip.force_encoding(enc) - else - str - end - end - - def column2display_offset(str) - display_offset = 0 - str.each_char.with_object([]) do |c, r| - c.bytesize.times do - r << display_offset - end - display_offset += c.ascii_only? ? 1 : 2 # FIXME - end - end - end - private_constant :Context - - class BlockContext < Context - def initialize(assertion_proc_or_source, assertion_method, source_binding) - super(0) - if assertion_proc_or_source.respond_to?(:to_proc) - @assertion_proc = assertion_proc_or_source.to_proc - line = nil - else - @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}" - line = assertion_proc_or_source - end - @parser = Parser::DUMMY - @trace_call = TracePoint.new(:call, :c_call) do - if PowerAssert.app_context? and Thread.current == @target_thread - @trace_call.disable - locs = PowerAssert.app_caller_locations - path = locs.last.path - lineno = locs.last.lineno - if File.exist?(path) - line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } - end - if line - @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc) - end - end - end - end - - def yield - @fired = true - invoke_yield(&@assertion_proc) - end - - private - - def invoke_yield - @trace_return.enable do - @trace_call.enable do - yield - end - end - end - end - private_constant :BlockContext - - class TraceContext < Context - def initialize(binding) - target_frame, *base = PowerAssert.app_caller_locations - super(base.length) - path = target_frame.path - lineno = target_frame.lineno - if File.exist?(path) - line = File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } - @parser = Parser.new(line, path, lineno, binding) - else - @parser = Parser::DUMMY - end - end - - def enable - @fired = true - @trace_return.enable - end - - def disable - @trace_return.disable - end - - def enabled? - @trace_return.enabled? - end - end - private_constant :TraceContext -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/enable_tracepoint_events.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/enable_tracepoint_events.rb deleted file mode 100644 index 5380e4d39..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/enable_tracepoint_events.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'power_assert/configuration' - -if defined?(RubyVM) - if PowerAssert.configuration._redefinition - if RUBY_VERSION == '2.3.2' - warn 'power_assert: It is strongly recommended that you use Ruby 2.3.3 or later which fixes regression on 2.3.2.' - warn 'power_assert: See https://www.ruby-lang.org/en/news/2016/11/21/ruby-2-3-3-released/ for more details.' - end - - verbose = $VERBOSE - begin - $VERBOSE = nil - module PowerAssert - # set redefined flag - basic_classes = [ - Fixnum, Float, String, Array, Hash, Bignum, Symbol, Time, Regexp, NilClass, TrueClass, FalseClass - ] - - basic_operators = [ - :+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=, - :length, :size, :empty?, :succ, :>, :>=, :!, :!=, :=~, :freeze, :-@, :max, :min, :nil? - ] - - bug11182 = Class.new do - def fixed? - true - end - end - - refine bug11182 do - def fixed? - end - end - - _ = Class.new(bug11182) do - alias _fixed? fixed? - protected :_fixed? - end - - if (bug11182.new.fixed? rescue false) - basic_classes.each do |klass| - basic_operators.each do |bop| - if klass.public_method_defined?(bop) - refine(klass) do - define_method(bop) {} - end - end - end - end - else - # workaround for https://bugs.ruby-lang.org/issues/11182 - basic_classes.each do |klass| - basic_operators.each do |bop| - if klass.public_method_defined?(bop) - klass.ancestors.find {|i| i.instance_methods(false).index(bop) }.module_eval do - public bop - end - end - end - end - - refine Symbol do - def == - end - end - end - - # bypass check_cfunc - refine BasicObject do - def ! - end - - def == - end - end - - refine Module do - def == - end - end - end - ensure - $VERBOSE = verbose - end - end - - # disable optimization - RubyVM::InstructionSequence.compile_option = { - specialized_instruction: false - } -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/inspector.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/inspector.rb deleted file mode 100644 index 6aca38937..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/inspector.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'power_assert/configuration' - -module PowerAssert - class InspectedValue - def initialize(value) - @value = value - end - - def inspect - @value - end - end - private_constant :InspectedValue - - class SafeInspectable - def initialize(value) - @value = value - end - - def inspect - inspected = @value.inspect - if Encoding.compatible?(Encoding.default_external, inspected) - inspected - else - begin - "#{inspected.encode(Encoding.default_external)}(#{inspected.encoding})" - rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError - inspected.force_encoding(Encoding.default_external) - end - end - rescue => e - "InspectionFailure: #{e.class}: #{e.message.each_line.first}" - end - end - private_constant :SafeInspectable - - class Formatter - def initialize(value, indent) - @value = value - @indent = indent - end - - def inspect - if PowerAssert.configuration._colorize_message - if PowerAssert.configuration._use_pp - width = [(defined?(Pry::Terminal) ? Pry::Terminal.width! : Pry.new(output: StringIO.new).output.width) - 1 - @indent, 10].max - Pry::ColorPrinter.pp(@value, '', width) - else - Pry::Code.new(@value.inspect).highlighted - end - else - if PowerAssert.configuration._use_pp - PP.pp(@value, '') - else - @value.inspect - end - end - end - end - private_constant :Formatter -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/parser.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/parser.rb deleted file mode 100644 index ff67200fe..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/parser.rb +++ /dev/null @@ -1,251 +0,0 @@ -require 'ripper' - -module PowerAssert - class Parser - Ident = Struct.new(:type, :name, :column) - - attr_reader :line, :path, :lineno, :binding - - def initialize(line, path, lineno, binding, assertion_method_name = nil, assertion_proc = nil) - @line = line - @line_for_parsing = (valid_syntax?(line) ? line : slice_expression(line)).b - @path = path - @lineno = lineno - @binding = binding - @proc_local_variables = binding.eval('local_variables').map(&:to_s) - @assertion_method_name = assertion_method_name - @assertion_proc = assertion_proc - end - - def idents - @idents ||= extract_idents(Ripper.sexp(@line_for_parsing)) - end - - def call_paths - collect_paths(idents).uniq - end - - def method_id_set - methods = idents.flatten.find_all {|i| i.type == :method } - @method_id_set ||= methods.map(&:name).map(&:to_sym).each_with_object({}) {|i, h| h[i] = true } - end - - private - - def valid_syntax?(str) - return true unless defined?(RubyVM) - begin - verbose, $VERBOSE = $VERBOSE, nil - RubyVM::InstructionSequence.compile(str) - true - rescue SyntaxError - false - ensure - $VERBOSE = verbose - end - end - - def slice_expression(str) - str = str.chomp - str.sub!(/\A\s*(?:if|unless|elsif|case|while|until) /) {|i| ' ' * i.length } - str.sub!(/\A\s*(?:\}|\]|end)?\./) {|i| ' ' * i.length } - str.sub!(/[\{\.\\]\z/, '') - str.sub!(/(?:&&|\|\|)\z/, '') - str.sub!(/ (?:do|and|or)\z/, '') - str - end - - class Branch < Array - end - - AND_OR_OPS = %i(and or && ||) - - # - # Returns idents as graph structure. - # - # +--c--b--+ - # extract_idents(Ripper.sexp('a&.b(c).d')) #=> a--+ +--d - # +--------+ - # - def extract_idents(sexp) - tag, * = sexp - case tag - when :arg_paren, :assoc_splat, :fcall, :hash, :method_add_block, :string_literal, :return - extract_idents(sexp[1]) - when :assign, :massign - extract_idents(sexp[2]) - when :opassign - _, _, (_, op_name, (_, op_column)), s0 = sexp - extract_idents(s0) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]] - when :dyna_symbol - if sexp[1][0].kind_of?(Symbol) - # sexp[1] can be [:string_content, [..]] while parsing { "a": 1 } - extract_idents(sexp[1]) - else - sexp[1].flat_map {|s| extract_idents(s) } - end - when :assoclist_from_args, :bare_assoc_hash, :paren, :string_embexpr, - :regexp_literal, :xstring_literal - sexp[1].flat_map {|s| extract_idents(s) } - when :command - [sexp[2], sexp[1]].flat_map {|s| extract_idents(s) } - when :assoc_new, :dot2, :dot3, :string_content - sexp[1..-1].flat_map {|s| extract_idents(s) } - when :unary - handle_columnless_ident([], sexp[1], extract_idents(sexp[2])) - when :binary - op = sexp[2] - if AND_OR_OPS.include?(op) - extract_idents(sexp[1]) + [Branch[extract_idents(sexp[3]), []]] - else - handle_columnless_ident(extract_idents(sexp[1]), op, extract_idents(sexp[3])) - end - when :call - _, recv, (op_sym, op_name, _), method = sexp - with_safe_op = ((op_sym == :@op and op_name == '&.') or op_sym == :"&.") - if method == :call - handle_columnless_ident(extract_idents(recv), :call, [], with_safe_op) - else - extract_idents(recv) + (with_safe_op ? [Branch[extract_idents(method), []]] : extract_idents(method)) - end - when :array - sexp[1] ? sexp[1].flat_map {|s| extract_idents(s) } : [] - when :command_call - [sexp[1], sexp[4], sexp[3]].flat_map {|s| extract_idents(s) } - when :aref - handle_columnless_ident(extract_idents(sexp[1]), :[], extract_idents(sexp[2])) - when :method_add_arg - idents = extract_idents(sexp[1]) - if idents.empty? - # idents may be empty(e.g. ->{}.()) - extract_idents(sexp[2]) - else - if idents[-1].kind_of?(Branch) and idents[-1][1].empty? - # Safe navigation operator is used. See :call clause also. - idents[0..-2] + [Branch[extract_idents(sexp[2]) + idents[-1][0], []]] - else - idents[0..-2] + extract_idents(sexp[2]) + [idents[-1]] - end - end - when :args_add_block - _, (tag, ss0, *ss1), _ = sexp - if tag == :args_add_star - (ss0 + ss1).flat_map {|s| extract_idents(s) } - else - sexp[1].flat_map {|s| extract_idents(s) } - end - when :vcall - _, (tag, name, (_, column)) = sexp - if tag == :@ident - [Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]] - else - [] - end - when :program - _, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp - if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and - (tag3 == :@ident or tag3 == :@const) and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block) - ss.flat_map {|s| extract_idents(s) } - else - _, (s0, *) = sexp - extract_idents(s0) - end - when :ifop - _, s0, s1, s2 = sexp - [*extract_idents(s0), Branch[extract_idents(s1), extract_idents(s2)]] - when :if, :unless - _, s0, ss0, (_, ss1) = sexp - [*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1 ? ss1.flat_map {|s| extract_idents(s) } : []]] - when :if_mod, :unless_mod - _, s0, s1 = sexp - [*extract_idents(s0), Branch[extract_idents(s1), []]] - when :var_ref, :var_field - _, (tag, ref_name, (_, column)) = sexp - case tag - when :@kw - if ref_name == 'self' - [Ident[:ref, 'self', column]] - else - [] - end - when :@ident, :@const, :@cvar, :@ivar, :@gvar - [Ident[:ref, ref_name, column]] - else - [] - end - when :@ident, :@const, :@op - _, method_name, (_, column) = sexp - [Ident[:method, method_name, column]] - else - [] - end - end - - def str_indices(str, re, offset, limit) - idx = str.index(re, offset) - if idx and idx <= limit - [idx, *str_indices(str, re, idx + 1, limit)] - else - [] - end - end - - MID2SRCTXT = { - :[] => '[', - :+@ => '+', - :-@ => '-', - :call => '(' - } - - def handle_columnless_ident(left_idents, mid, right_idents, with_safe_op = false) - left_max = left_idents.flatten.max_by(&:column) - right_min = right_idents.flatten.min_by(&:column) - bg = left_max ? left_max.column + left_max.name.length : 0 - ed = right_min ? right_min.column - 1 : @line_for_parsing.length - 1 - mname = mid.to_s - srctxt = MID2SRCTXT[mid] || mname - re = / - #{'\b' if /\A\w/ =~ srctxt} - #{Regexp.escape(srctxt)} - #{'\b' if /\w\z/ =~ srctxt} - /x - indices = str_indices(@line_for_parsing, re, bg, ed) - if indices.length == 1 or !(right_idents.empty? and left_idents.empty?) - ident = Ident[:method, mname, right_idents.empty? ? indices.first : indices.last] - left_idents + right_idents + (with_safe_op ? [Branch[[ident], []]] : [ident]) - else - left_idents + right_idents - end - end - - def collect_paths(idents, prefixes = [[]], index = 0) - if index < idents.length - node = idents[index] - if node.kind_of?(Branch) - prefixes = node.flat_map {|n| collect_paths(n, prefixes, 0) } - else - prefixes = prefixes.map {|prefix| prefix + [node] } - end - collect_paths(idents, prefixes, index + 1) - else - prefixes - end - end - - class DummyParser < Parser - def initialize - super('', nil, nil, TOPLEVEL_BINDING) - end - - def idents - [] - end - - def call_paths - [] - end - end - DUMMY = DummyParser.new - end - private_constant :Parser -end diff --git a/ruby/gems/power_assert-1.1.7/lib/power_assert/version.rb b/ruby/gems/power_assert-1.1.7/lib/power_assert/version.rb deleted file mode 100644 index 700e7d445..000000000 --- a/ruby/gems/power_assert-1.1.7/lib/power_assert/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module PowerAssert - VERSION = "1.1.7" -end diff --git a/ruby/gems/power_assert-1.1.7/power_assert.gemspec b/ruby/gems/power_assert-1.1.7/power_assert.gemspec deleted file mode 100644 index 0243673f5..000000000 --- a/ruby/gems/power_assert-1.1.7/power_assert.gemspec +++ /dev/null @@ -1,44 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: power_assert 1.1.7 ruby lib - -Gem::Specification.new do |s| - s.name = "power_assert".freeze - s.version = "1.1.7" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib".freeze] - s.authors = ["Kazuki Tsujimoto".freeze] - s.bindir = "exe".freeze - s.date = "2020-03-22" - s.description = "Power Assert for Ruby. Power Assert shows each value of variables and method calls in the expression. It is useful for testing, providing which value wasn't correct when the condition is not satisfied.".freeze - s.email = ["kazuki@callcc.net".freeze] - s.extra_rdoc_files = ["README.rdoc".freeze] - s.files = [".gitignore".freeze, ".travis.yml".freeze, "BSDL".freeze, "COPYING".freeze, "Gemfile".freeze, "LEGAL".freeze, "README.rdoc".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/power_assert.rb".freeze, "lib/power_assert/colorize.rb".freeze, "lib/power_assert/configuration.rb".freeze, "lib/power_assert/context.rb".freeze, "lib/power_assert/enable_tracepoint_events.rb".freeze, "lib/power_assert/inspector.rb".freeze, "lib/power_assert/parser.rb".freeze, "lib/power_assert/version.rb".freeze, "power_assert.gemspec".freeze] - s.homepage = "https://github.com/k-tsj/power_assert".freeze - s.licenses = ["2-clause BSDL".freeze, "Ruby's".freeze] - s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] - s.rubygems_version = "3.1.2".freeze - s.summary = "Power Assert for Ruby".freeze - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - else - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - end -end diff --git a/ruby/gems/rake-13.0.1.gem b/ruby/gems/rake-13.0.1.gem deleted file mode 100644 index 8753712d9..000000000 Binary files a/ruby/gems/rake-13.0.1.gem and /dev/null differ diff --git a/ruby/gems/rake-13.0.1/.github/workflows/macos.yml b/ruby/gems/rake-13.0.1/.github/workflows/macos.yml deleted file mode 100644 index 2dbc56a36..000000000 --- a/ruby/gems/rake-13.0.1/.github/workflows/macos.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: macos - -on: [push] - -jobs: - build: - runs-on: macos-latest - strategy: - matrix: - ruby: [ '2.6.x', '2.5.x', '2.4.x' ] - steps: - - uses: actions/checkout@master - - name: Set up Ruby - uses: actions/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - - name: Install dependencies - run: gem install minitest - - name: Run test - env: - COVERALLS: "yes" - run: ruby -Ilib exe/rake diff --git a/ruby/gems/rake-13.0.1/.github/workflows/ubuntu-rvm.yml b/ruby/gems/rake-13.0.1/.github/workflows/ubuntu-rvm.yml deleted file mode 100644 index cf3d1d05b..000000000 --- a/ruby/gems/rake-13.0.1/.github/workflows/ubuntu-rvm.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: ubuntu-rvm - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - ruby: [ 'jruby-head', 'jruby-9.2.9.0', 'ruby-head', '2.3.8', '2.2.10' ] - steps: - - uses: actions/checkout@master - - name: Set up RVM - run: | - curl -sSL https://get.rvm.io | bash - - name: Set up Ruby - run: | - source $HOME/.rvm/scripts/rvm - rvm install ${{ matrix.ruby }} --binary - rvm --default use ${{ matrix.ruby }} - - name: Install dependencies - run: | - source $HOME/.rvm/scripts/rvm - gem install minitest - - name: Run test - run: | - source $HOME/.rvm/scripts/rvm - ruby -Ilib exe/rake diff --git a/ruby/gems/rake-13.0.1/.github/workflows/ubuntu.yml b/ruby/gems/rake-13.0.1/.github/workflows/ubuntu.yml deleted file mode 100644 index b67130ad8..000000000 --- a/ruby/gems/rake-13.0.1/.github/workflows/ubuntu.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: ubuntu - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - ruby: [ '2.6.x', '2.5.x', '2.4.x' ] - steps: - - uses: actions/checkout@master - - name: Set up Ruby - uses: actions/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - - name: Install dependencies - run: gem install minitest - - name: Run test - run: ruby -Ilib exe/rake diff --git a/ruby/gems/rake-13.0.1/.github/workflows/windows.yml b/ruby/gems/rake-13.0.1/.github/workflows/windows.yml deleted file mode 100644 index 5ced11c45..000000000 --- a/ruby/gems/rake-13.0.1/.github/workflows/windows.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: windows - -on: [push] - -jobs: - build: - runs-on: windows-latest - strategy: - matrix: - ruby: [ '2.6.x', '2.5.x', '2.4.x' ] - steps: - - uses: actions/checkout@master - - name: Set up Ruby - uses: actions/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - - name: Install dependencies - run: gem install minitest - - name: Run test - run: ruby -Ilib exe/rake diff --git a/ruby/gems/rake-13.0.1/CONTRIBUTING.rdoc b/ruby/gems/rake-13.0.1/CONTRIBUTING.rdoc deleted file mode 100644 index e8430ddb4..000000000 --- a/ruby/gems/rake-13.0.1/CONTRIBUTING.rdoc +++ /dev/null @@ -1,43 +0,0 @@ -= Source Repository - -Rake is currently hosted at github. The github web page is -https://github.com/ruby/rake . The public git clone URL is - - https://github.com/ruby/rake.git - -= Running the Rake Test Suite - -If you wish to run the unit and functional tests that come with Rake: - -* +cd+ into the top project directory of rake. -* Install gem dependency using bundler: - - $ bundle install # Install bundler, minitest and rdoc - -* Run the test suite - - $ rake - -= Rubocop - -Rake uses Rubocop to enforce a consistent style on new changes being -proposed. You can check your code with Rubocop using: - - $ ./bin/rubocop - -= Issues and Bug Reports - -Feel free to submit commits or feature requests. If you send a patch, -remember to update the corresponding unit tests. In fact, I prefer -new feature to be submitted in the form of new unit tests. - -For other information, feel free to ask on the ruby-talk mailing list. - -If you have found a bug in rake please try with the latest version of rake -before filing an issue. Also check History.rdoc for bug fixes that may have -addressed your issue. - -When submitting pull requests please check the rake Travis-CI page for test -failures: - - https://travis-ci.org/ruby/rake diff --git a/ruby/gems/rake-13.0.1/Gemfile b/ruby/gems/rake-13.0.1/Gemfile deleted file mode 100644 index 8bcbf50a7..000000000 --- a/ruby/gems/rake-13.0.1/Gemfile +++ /dev/null @@ -1,10 +0,0 @@ -source "https://rubygems.org" - -gemspec - -group :development do - gem "bundler" - gem "minitest" - gem "coveralls" - gem "rubocop" -end diff --git a/ruby/gems/rake-13.0.1/History.rdoc b/ruby/gems/rake-13.0.1/History.rdoc deleted file mode 100644 index 119747c66..000000000 --- a/ruby/gems/rake-13.0.1/History.rdoc +++ /dev/null @@ -1,2368 +0,0 @@ -=== 13.0.1 - -==== Bug fixes - -* Fixed bug: Reenabled task raises previous exception on second invokation - Pull Request #271 by thorsteneckel -* Fix an incorrectly resolved arg pattern - Pull Request #327 by mjbellantoni - -=== 13.0.0 - -==== Enhancements - -* Follows recent changes on keyword arguments in ruby 2.7. - Pull Request #326 by nobu -* Make `PackageTask` be able to omit parent directory while packing files - Pull Request #310 by tonytonyjan -* Add order only dependency - Pull Request #269 by take-cheeze - -==== Compatibility changes - -* Drop old ruby versions(< 2.2) - -=== 12.3.3 - -==== Bug fixes - -* Use the application's name in error message if a task is not found. - Pull Request #303 by tmatilai - -==== Enhancements: - -* Use File.open explicitly. - -=== 12.3.2 - -==== Bug fixes - -* Fixed test fails caused by 2.6 warnings. - Pull Request #297 by hsbt - -==== Enhancements: - -* Rdoc improvements. - Pull Request #293 by colby-swandale -* Improve multitask performance. - Pull Request #273 by jsm -* Add alias `prereqs`. - Pull Request #268 by take-cheeze - -=== 12.3.1 - -==== Bug fixes - -* Support did_you_mean >= v1.2.0 which has a breaking change on formatters. - Pull request #262 by FUJI Goro. - -==== Enhancements: - -* Don't run task if it depends on already invoked but failed task. - Pull request #252 by Gonzalo Rodriguez. -* Make space trimming consistent for all task arguments. - Pull request #259 by Gonzalo Rodriguez. -* Removes duplicated inclusion of Rake::DSL in tests. - Pull request #254 by Gonzalo Rodriguez. -* Re-raise a LoadError that didn't come from require in the test loader. - Pull request #250 by Dylan Thacker-Smith. - -=== 12.3.0 - -==== Compatibility Changes - -* Bump `required_ruby_version` to Ruby 2.0.0. Rake has already - removed support for Ruby 1.9.x. - -==== Enhancements: - -* Support `test-bundled-gems` task on ruby core. - -=== 12.2.1 - -==== Bug fixes - -* Fixed to break Capistrano::Application on capistrano3. - -=== 12.2.0 - -==== Enhancements: - -* Make rake easier to use as a library - Pull request #211 by @drbrain -* Fix quadratic performance in FileTask#out_of_date? - Pull request #224 by @doudou -* Clarify output when printing nested exception traces - Pull request #232 by @urbanautomaton - -==== Bug fixes - -* Account for a file that match 2 or more patterns. - Pull request #231 by @styd - -=== 12.1.0 - -==== Enhancements: - -* Added did_you_mean feature for invalid rake task. - Pull request #221 by @xtina-starr -* Enabled to dependency chained by extensions. Pull request #39 by Petr Skocik. -* Make all of string literals to frozen objects on Ruby 2.4 or later. - -==== Bug fixes - -* Typo fixes in rakefile.rdoc. Pull request #180 by Yuta Kurotaki. -* Fix unexpected behavior of file task with dryrun option. - Pull request #183 by @aycabta. -* Make LoadError from running tests more obvious. Pull request #195 - by Eric Hodel. -* Fix unexpected TypeError with hash style option. Pull request #202 - by Kuniaki IGARASHI. - -=== 12.0.0 - -==== Compatibility Changes - -* Removed arguments on clear #157 by Jesse Bowes -* Removed `rake/contrib` packages. These are extracted to `rake-contrib` gem. -* Removed deprecated method named `last\_comment`. - -==== Enhancements: - -* Re-use trace option on `cleanup` task. #164 by Brian Henderson -* Actions adore keyword arguments #174 by Josh Cheek -* Rake::TaskArguments#key? alias of #has_key? #175 by Paul Annesley - -=== 11.3.0 / 2016-09-20 - -==== Enhancements: - -* Remove to reference `Fixnum` constant. Pull request #160 by nobu - -=== 11.2.2 / 2016-06-12 - -==== Bug fixes - -* Fix unexpected behavior with multiple dependencies on Rake::TestTask - -=== 11.2.1 / 2016-06-12 - -==== Bug fixes - -* Fix regression of dependencies handling on Rake::TestTask. Report #139 - -=== 11.2.0 / 2016-06-11 - -==== Bug fixes - -* Fix unexpected cut-out behavior on task description using triple dots - and exclamation. Report #106 from Stephan Kämper and Pull request #134 by Lee -* Fix empty argument assignment with `with_defaults` option. Pull request #135 - by bakunyo -* Ignore to use `hwprefs` on Darwin platform. Use sysctl now. Report #128 - -==== Enhancements - -* Spawn options for sh Pull equest #138 by Eric Hodel. -* Allow to specify dependencies(prerequisites) for Rake::TestTask - Pull request #117 by Tim Maslyuchenko -* Use Bundler task instead of hoe for gem release. -* Remove explicitly load to rubygems for Ruby 1.8. -* Unify to declare `Rake::VERSION`. -* Support xz format for PackageTask. - -=== 11.1.2 / 2016-03-28 - -==== Bug fixes - -* Remove `-W` option when Rake::TestTask#verbose enabled. It's misunderstanding - specification change with Rake 11. Partly revert #67 - -=== 11.1.1 / 2016-03-14 - -==== Bug fixes - -* Use `-W` instead of `--verbose` when Rake::TestTask#verbose enabled. - JRuby doesn't have `--verbose` option. - -=== 11.1.0 / 2016-03-11 - -==== Compatibility Changes - -* Revert to remove `last\_comment`. It will remove Rake 12. - -=== 11.0.1 / 2016-03-09 - -==== Bug fixes - -* Fixed packaging manifest. - -=== 11.0.0 / 2016-03-09 - -==== Bug fixes - -* Correctly handle bad encoding in exception messages. Pull request #113 - by Tomer Brisker -* Fix verbose option at TestTask. Pull request #67 by Mike Blumtritt - -==== Enhancements - -* Make FileList#exclude more analogous to FileList#include. -* Use IO.open instead of Open3.popen3 for CPU counter. -* Make Rake::Task#already_invoked publicly accessible. - Pull request #93 by Joe Rafaniello -* Lookup prerequisites with same name outside of scope instead of - matching self. Pull request #96 by Sandy Vanderbleek -* Make FileList#pathmap behave like String#pathmap. - Pull request #61 by Daniel Tamai -* Add fetch method to task arguments. - Pull request #12 by Chris Keathley -* Use ruby warnings by default. Pull request #97 by Harold Giménez - -==== Compatibility Changes - -* Removed to support Ruby 1.8.x -* Removed constant named `RAKEVERSION` -* Removed Rake::AltSystem -* Removed Rake::RubyForgePublisher -* Removed Rake::TaskManager#last\_comment. Use last\_description. -* Removed Rake::TaskLib#paste -* Removed Top-level SshDirPublisher, SshFreshDirPublisher, SshFilePublisher - and CompositePublisher from lib/rake/contrib/publisher.rb -* Removed "rake/runtest.rb" - -=== 10.5.0 / 2016-01-13 - -==== Enhancements - -* Removed monkey patching for Ruby 1.8. Pull request #46 by Pablo Herrero. -* Inheritance class of Rake::FileList returns always self class. - Pull request #74 by Thomas Scholz - -=== 10.4.2 / 2014-12-02 - -==== Bug fixes - -* Rake no longer edits ARGV. This allows you to re-exec rake from a rake - task. Pull requset #9 by Matt Palmer. -* Documented how Rake::DSL#desc handles sentences in task descriptions. - Issue #7 by Raza Sayed. -* Fixed test error on 1.9.3 with legacy RubyGems. Issue #8 by Matt Palmer. -* Deleted duplicated History entry. Pull request #10 by Yuji Yamamoto. - -=== 10.4.1 / 2014-12-01 - -==== Bug fixes - -* Reverted fix for #277 as it caused numerous issues for rake users. - rails/spring issue #366 by Gustavo Dutra. - -=== 10.4.0 / 2014-11-22 - -==== Enhancements - -* Upgraded to minitest 5. Pull request #292 by Teo Ljungberg. -* Added support for Pathname in rake tasks. Pull request #271 by Randy - Coulman. -* Rake now ignores falsy dependencies which allows for easier programmatic - creation of tasks. Pull request #273 by Manav. -* Rake no longer edits ARGV. This allows you to re-exec rake from a rake - task. Issue #277 by Matt Palmer. -* Etc.nprocessors is used for counting the number of CPUs. - -==== Bug fixes - -* Updated rake manpage. Issue #283 by Nathan Long, pull request #291 by - skittleys. -* Add Rake::LATE to allow rebuilding of files that depend on deleted files. - Bug #286, pull request #287 by David Grayson. -* Fix relinking of files when repackaging. Bug #276 by Muenze. -* Fixed some typos. Pull request #280 by Jed Northridge. -* Try counting CPUs via cpuinfo if host_os was not matched. Pull request - #282 by Edouard B. - -=== 10.3.2 / 2014-05-15 - -==== Bug fixes - -* Rake no longer infinitely loops when showing exception causes that refer to - each other. Bug #272 by Chris Bandy. -* Fixed documentation typos. Bug #275 by Jake Worth. - -=== 10.3.1 / 2014-04-17 - -==== Bug fixes - -* Really stop reporting an error when cleaning already-deleted files. Pull - request #269 by Randy Coulman -* Fixed infinite loop when cleaning already-deleted files on windows. - -=== 10.3 / 2014-04-15 - -==== Enhancements - -* Added --build-all option to rake which treats all file prerequisites as - out-of-date. Pull request #254 by Andrew Gilbert. -* Added Rake::NameSpace#scope. Issue #263 by Jon San Miguel. - -==== Bug fixes - -* Suppress org.jruby package files in rake error messages for JRuby users. - Issue #213 by Charles Nutter. -* Fixed typo, removed extra "h". Pull request #267 by Hsing-Hui Hsu. -* Rake no longer reports an error when cleaning already-deleted files. Pull - request #266 by Randy Coulman. -* Consume stderr while determining CPU count to avoid hang. Issue #268 by - Albert Sun. - -=== 10.2.2 / 2014-03-27 - -==== Bug fixes - -* Restored Ruby 1.8.7 compatibility - -=== 10.2.1 / 2014-03-25 - -==== Bug fixes - -* File tasks including a ':' are now top-level tasks again. Issue #262 by - Josh Holtrop. -* Use sysctl for CPU count for all BSDs. Pull request #261 by Joshua Stein. -* Fixed CPU detection for unknown platforms. - -=== 10.2.0 / 2014-03-24 - -==== Enhancements - -* Rake now requires Ruby 1.9 or newer. For me, this is a breaking change, but - it seems that Jim planned to release it with Rake 10.2. See also pull - request #247 by Philip Arndt. -* Rake now allows you to declare tasks under a namespace like: - - task 'a:b' do ... end - - Pull request #232 by Judson Lester. -* Task#source defaults to the first prerequisite in non-rule tasks. Pull - request #215 by Avdi Grimm. -* Rake now automatically rebuilds and reloads imported files. Pull request - #209 by Randy Coulman. -* The rake task arguments can contain escaped commas. Pull request #214 by - Filip Hrbek. -* Rake now prints the exception class on errors. Patch #251 by David Cornu. - -==== Bug fixes - -* Fixed typos. Pull request #256 by Valera Rozuvan, #250 via Jake Worth, #260 - by Zachary Scott. -* Fixed documentation for calling tasks with arguments. Pull request #235 by - John Varghese. -* Clarified `rake -f` usage message. Pull request #252 by Marco Pfatschbacher. -* Fixed a test failure on windows. Pull request #231 by Hiroshi Shirosaki. -* Fixed corrupted rake.1.gz. Pull request #225 by Michel Boaventura. -* Fixed bug in can\_detect\_signals? in test. Patch from #243 by Alexey - Borzenkov. - -=== 10.1.1 - -* Use http://github.com/jimweirich/rake instead of http://rake.rubyforge.org for - canonical project url. - -=== 10.1.0 - -==== Changes - -===== New Features - -* Add support for variable length task argument lists. If more actual - arguments are supplied than named arguments, then the extra - arguments values will be in args.extras. - -* Application name is not displayed in the help banner. (Previously - "rake" was hardcoded, now rake-based applications can display their - own names). - -===== Bug Fixes - -Bug fixes include: - -* Fix backtrace suppression issues. - -* Rules now explicit get task arguments passed to them. - -* Rename FileList#exclude? to FileList#exclude\_from\_list? to avoid - conflict with new Rails method. - -* Clean / Clobber tasks now report failure to remove files. - -* Plus heaps of internal code cleanup. - -==== Thanks - -As usual, it was input from users that drove a lot of these changes. -The following people contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Michael Nikitochkin (general code cleanup) -* Vipul A M (general code cleanup) -* Dennis Bell (variable length task argument lists) -* Jacob Swanner (rules arguments) -* Rafael Rosa Fu (documentation typo) -* Stuart Nelson (install.rb fixes) -* Lee Hambley (application name in help banner) - --- Jim Weirich - -=== 10.0.3 - - "Jim, when will Rake reach version 1.0?" - -Over the past several years I've been asked that question at -conferences, panels and over twitter. Due to historical reasons (or -maybe just plain laziness) Rake has (incorrectly) been treating the -second digit of the version as the major release number. So in my head -Rake was already at version 9. - -Well, it's time to fix things. This next version of Rake drops old, -crufty, backwards compatibility hacks such as top level constants, DSL -methods defined in Object and numerous other features that are just no -longer desired. It's also time to drop the leading zero from the -version number as well and call this new version of rake what it -really is: Version 10. - -So, welcome to Rake 10.0! - -Rake 10 is actually feature identical to the latest version of Rake 9 -(that would be the version spelled 0.9.3), *except* that Rake 10 drops -all the sundry deprecated features that have accumulated over the years. - -If your Rakefile is up to date and current with all the new features -of Rake 10, you are ready to go. If your Rakefile still uses a few -deprecated feeatures, feel free to use Rake 9 (0.9.3) with the same -feature set. Just be aware that future features will be in Rake 10 -family line. - -==== Changes - -As mentioned above, there are no new features in Rake 10. However, -there are a number of features missing: - -* Classic namespaces are now gone. Rake is no longer able to reflect - the options settings in the global variables ($rakefile, $show\_tasks, - $show\_prereqs, $trace, $dryrun and $silent). The - --classic-namespace option is no longer supported. - -* Global constants are no longer supported. This includes - Task, FileTask, FileCreationTask and - RakeApp). The constant missing hook to warn about using - global rake constants has been removed. - -* The Rake DSL methods (task, file, directory, etc) are in their own - module (Rake::DSL). The stub versions of these methods (that printed - warnings) in Object have been removed. However, the DSL methods are - added to the top-level main object. Since main is - not in the inheritance tree, the presence of the DSL methods in main - should be low impact on other libraries. - - If you want to use the Rake DSL commands from your own code, just - include Rake::DSL into your own classes and modules. - -* The deprecated syntax for task arguments (the one using - :needs) has been removed. - -* The --reduce-compat flag has been removed (it's not needed - anymore). - -* The deprecated rake/sys.rb library has been removed. - -* The deprecated rake/rdoctask.rb library has been removed. - RDoc supplies its own rake task now. - -* The deprecated rake/gempackagetask.rb library has been - removed. Gem supplies its own package task now. - -There is one small behavioral change: - -* Non-file tasks now always report the current time as their time - stamp. This is different from the previous behavior where non-file - tasks reported current time only if there were no prerequisites, and - the max prerequisite timestamp otherwise. This lead to inconsistent - and surprising behavior when adding prerequisites to tasks that in - turn were prequisites to file tasks. The new behavior is more - consistent and predictable. - -==== Changes (from 0.9.3, 0.9.4, 0.9.5) - -Since Rake 10 includes the changes from the last version of Rake 9, -we'll repeat the changes for versions 0.9.3 through 0.9.5 here. - -===== New Features (in 0.9.3) - -* Multitask tasks now use a thread pool. Use -j to limit the number of - available threads. - -* Use -m to turn regular tasks into multitasks (use at your own risk). - -* You can now do "Rake.add_rakelib 'dir'" in your Rakefile to - programatically add rake task libraries. - -* You can specific backtrace suppression patterns (see - --suppress-backtrace) - -* Directory tasks can now take prerequisites and actions - -* Use --backtrace to request a full backtrace without the task trace. - -* You can say "--backtrace=stdout" and "--trace=stdout" to route trace - output to standard output rather than standard error. - -* Optional 'phony' target (enable with 'require 'rake/phony'") for - special purpose builds. - -* Task#clear now clears task comments as well as actions and - prerequisites. Task#clear_comment will specifically target comments. - -* The --all option will force -T and -D to consider all the tasks, - with and without descriptions. - -===== Bug Fixes (in 0.9.3) - -* Semi-colons in windows rakefile paths now work. - -* Improved Control-C support when invoking multiple test suites. - -* egrep method now reads files in text mode (better support for - Windows) - -* Better deprecation line number reporting. - -* The -W option now works with all tasks, whether they have a - description or not. - -* File globs in rake should not be sorted alphabetically, independent - of file system and platform. - -* Numerous internal improvements. - -* Documentation typos and fixes. - -===== Bug Fixes (in 0.9.4) - -* Exit status with failing tests is not correctly set to non-zero. - -* Simplified syntax for phony task (for older versions of RDoc). - -* Stand alone FileList usage gets glob function (without loading in - extra dependencies) - -===== Bug Fixes (in 0.9.5) - -* --trace and --backtrace no longer swallow following task names. - -==== Thanks - -As usual, it was input from users that drove a lot of these changes. The -following people contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 10.0.2 - -==== Changes - -===== Bug Fixes - -* --trace and --backtrace no longer swallow following task names. - -==== Thanks - -As usual, it was input from users that drove a lot of these changes. The -following people contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 10.0.1 - -==== Changes - -===== Bug Fixes - -* Exit status with failing tests is not correctly set to non-zero. - -* Simplified syntax for phony task (for older versions of RDoc). - -* Stand alone FileList usage gets glob function (without loading in - extra dependencies) - -==== Thanks - -As usual, it was input from users that drove a lot of these changes. The -following people contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 10.0.0 - - "Jim, when will Rake reach version 1.0?" - -Over the past several years I've been asked that question at -conferences, panels and over twitter. Due to historical reasons (or -maybe just plain laziness) Rake has (incorrectly) been treating the -second digit of the version as the major release number. So in my head -Rake was already at version 9. - -Well, it's time to fix things. This next version of Rake drops old, -crufty, backwards compatibility hacks such as top level constants, DSL -methods defined in Object and numerous other features that are just no -longer desired. It's also time to drop the leading zero from the -version number as well and call this new version of rake what it -really is: Version 10. - -So, welcome to Rake 10.0! - -Rake 10 is actually feature identical to the latest version of Rake 9 -(that would be the version spelled 0.9.3), *except* that Rake 10 drops -all the sundry deprecated features that have accumulated over the years. - -If your Rakefile is up to date and current with all the new features -of Rake 10, you are ready to go. If your Rakefile still uses a few -deprecated feeatures, feel free to use Rake 9 (0.9.3) with the same -feature set. Just be aware that future features will be in Rake 10 -family line. - -==== Changes in 10.0 - -As mentioned above, there are no new features in Rake 10. However, -there are a number of features missing: - -* Classic namespaces are now gone. Rake is no longer able to reflect - the options settings in the global variables ($rakefile, $show\_tasks, - $show\_prereqs, $trace, $dryrun and $silent). The - --classic-namespace option is no longer supported. - -* Global constants are no longer supported. This includes - Task, FileTask, FileCreationTask and - RakeApp). The constant missing hook to warn about using - global rake constants has been removed. - -* The Rake DSL methods (task, file, directory, etc) are in their own - module (Rake::DSL). The stub versions of these methods (that printed - warnings) in Object have been removed. However, the DSL methods are - added to the top-level main object. Since main is - not in the inheritance tree, the presence of the DSL methods in main - should be low impact on other libraries. - - If you want to use the Rake DSL commands from your own code, just - include Rake::DSL into your own classes and modules. - -* The deprecated syntax for task arguments (the one using - :needs) has been removed. - -* The --reduce-compat flag has been removed (it's not needed - anymore). - -* The deprecated rake/sys.rb library has been removed. - -* The deprecated rake/rdoctask.rb library has been removed. - RDoc supplies its own rake task now. - -* The deprecated rake/gempackagetask.rb library has been - removed. Gem supplies its own package task now. - -There is one small behavioral change: - -* Non-file tasks now always report the current time as their time - stamp. This is different from the previous behavior where non-file - tasks reported current time only if there were no prerequisites, and - the max prerequisite timestamp otherwise. This lead to inconsistent - and surprising behavior when adding prerequisites to tasks that in - turn were prequisites to file tasks. The new behavior is more - consistent and predictable. - -==== Changes (from 0.9.3) - -Since Rake 10 includes the changes from the last version of Rake 9, -we'll repeat the changes for version 0.9.3 here. - -===== New Features - -* Multitask tasks now use a thread pool. Use -j to limit the number of - available threads. - -* Use -m to turn regular tasks into multitasks (use at your own risk). - -* You can now do "Rake.add_rakelib 'dir'" in your Rakefile to - programatically add rake task libraries. - -* You can specific backtrace suppression patterns (see - --suppress-backtrace) - -* Directory tasks can now take prerequisites and actions - -* Use --backtrace to request a full backtrace without the task trace. - -* You can say "--backtrace=stdout" and "--trace=stdout" to route trace - output to standard output rather than standard error. - -* Optional 'phony' target (enable with 'require 'rake/phony'") for - special purpose builds. - -* Task#clear now clears task comments as well as actions and - prerequisites. Task#clear_comment will specifically target comments. - -* The --all option will force -T and -D to consider all the tasks, - with and without descriptions. - -===== Bug Fixes - -* Semi-colons in windows rakefile paths now work. - -* Improved Control-C support when invoking multiple test suites. - -* egrep method now reads files in text mode (better support for - Windows) - -* Better deprecation line number reporting. - -* The -W option now works with all tasks, whether they have a - description or not. - -* File globs in rake should not be sorted alphabetically, independent - of file system and platform. - -* Numerous internal improvements. - -* Documentation typos and fixes. - - -==== Thanks - -As usual, it was input from users that drove a lot of these changes. The -following people contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 0.9.6 - -Rake version 0.9.6 contains a number of fixes mainly for merging -Rake into the Ruby source tree and fixing tests. - -==== Changes - -===== Bug Fixes (0.9.6) - -* Better trace output when using a multi-threaded Rakefile. -* Arg parsing is now consistent for tasks and multitasks. -* Skip exit code test in versions of Ruby that don't support it well. - -Changes for better integration with the Ruby source tree: - -* Fix version literal for Ruby source tree build. -* Better loading of libraries for testing in Ruby build. -* Use the ruby version provided by Ruby's tests. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 0.9.5 - -Rake version 0.9.5 contains a number of bug fixes. - -==== Changes - -===== Bug Fixes (0.9.5) - -* --trace and --backtrace no longer swallow following task names. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 0.9.4 - -Rake version 0.9.4 contains a number of bug fixes. - -==== Changes - -===== Bug Fixes (0.9.4) - -* Exit status with failing tests is not correctly set to non-zero. - -* Simplified syntax for phony task (for older versions of RDoc). - -* Stand alone FileList usage gets glob function (without loading in - extra dependencies) - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== 0.9.3 - -Rake version 0.9.3 contains some new, backwards compatible features and -a number of bug fixes. - -==== Changes - -===== New Features - -* Multitask tasks now use a thread pool. Use -j to limit the number of - available threads. - -* Use -m to turn regular tasks into multitasks (use at your own risk). - -* You can now do "Rake.add_rakelib 'dir'" in your Rakefile to - programatically add rake task libraries. - -* You can specific backtrace suppression patterns (see - --suppress-backtrace) - -* Directory tasks can now take prerequisites and actions - -* Use --backtrace to request a full backtrace without the task trace. - -* You can say "--backtrace=stdout" and "--trace=stdout" to route trace - output to standard output rather than standard error. - -* Optional 'phony' target (enable with 'require 'rake/phony'") for - special purpose builds. - -* Task#clear now clears task comments as well as actions and - prerequisites. Task#clear_comment will specifically target comments. - -* The --all option will force -T and -D to consider all the tasks, - with and without descriptions. - -===== Bug Fixes - -* Semi-colons in windows rakefile paths now work. - -* Improved Control-C support when invoking multiple test suites. - -* egrep method now reads files in text mode (better support for - Windows) - -* Better deprecation line number reporting. - -* The -W option now works with all tasks, whether they have a - description or not. - -* File globs in rake should not be sorted alphabetically, independent - of file system and platform. - -* Numerous internal improvements. - -* Documentation typos and fixes. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Aaron Patterson -* Dylan Smith -* Jo Liss -* Jonas Pfenniger -* Kazuki Tsujimoto -* Michael Bishop -* Michael Elufimov -* NAKAMURA Usaku -* Ryan Davis -* Sam Grönblom -* Sam Phippen -* Sergio Wong -* Tay Ray Chuan -* grosser -* quix - -Also, many thanks to Eric Hodel for assisting with getting this release -out the door. - --- Jim Weirich - -=== Rake 0.9.2.2 - -Rake version 0.9.2.2 is mainly bug fixes. - -==== Changes - -* The rake test loader now removes arguments it has processed. Issue #51 -* Rake::TaskArguments now responds to #values\_at -* RakeFileUtils.verbose_flag = nil silences output the same as 0.8.7 -* Rake tests are now directory-independent -* Rake tests are no longer require flexmock -* Commands constant is no longer polluting top level namespace. -* Show only the interesting portion of the backtrace by default (James M. Lawrence). -* Added --reduce-compat option to remove backward compatible DSL hacks (James M. Lawrence). - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence (quix) -* Roger Pack -* Cezary Baginski -* Sean Scot August Moon -* R.T. Lechow -* Alex Chaffee -* James Tucker -* Matthias Lüdtke -* Santiago Pastorino - -Also, bit thanks to Eric Hodel for assisting with getting this release -out the door (where "assisting" includes, but is not by any means -limited to, "pushing" me to get it done). - --- Jim Weirich - -=== 0.9.2 - -Rake version 0.9.2 has a few small fixes. See below for details. - -==== Changes - -* Support for Ruby 1.8.6 was fixed. -* Global DSL warnings now honor --no-deprecate - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence (quix) -* Roger Pack -* Cezary Baginski -* Sean Scot August Moon -* R.T. Lechow -* Alex Chaffee -* James Tucker -* Matthias Lüdtke -* Santiago Pastorino - -Also, bit thanks to Eric Hodel for assisting with getting this release -out the door (where "assisting" includes, but is not by any means -limited to, "pushing" me to get it done). - --- Jim Weirich - -=== 0.9.1 - -Rake version 0.9.1 has a number of bug fixes and enhancments (see -below for more details). Additionally, the internals have be slightly -restructured and improved. - -==== Changes - -Rake 0.9.1 adds back the global DSL methods, but with deprecation -messages. This allows Rake 0.9.1 to be used with older rakefiles with -warning messages. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence (quix) -* Roger Pack -* Cezary Baginski -* Sean Scot August Moon -* R.T. Lechow -* Alex Chaffee -* James Tucker -* Matthias Lüdtke -* Santiago Pastorino - -Also, bit thanks to Eric Hodel for assisting with getting this release -out the door (where "assisting" includes, but is not by any means -limited to, "pushing" me to get it done). - --- Jim Weirich - -=== 0.9.0 - -Rake version 0.9.0 has a number of bug fixes and enhancments (see -below for more details). Additionally, the internals have be slightly -restructured and improved. - -==== Changes - -===== New Features / Enhancements / Bug Fixes in Version 0.9.0 - -* Rake now warns when the deprecated :needs syntax used (and suggests - the proper syntax in the warning). - -* Moved Rake DSL commands to top level ruby object 'main'. Rake DSL - commands are no longer private methods in Object. (Suggested by - James M. Lawrence/quix) - -* Rake now uses case-insensitive comparisons to find the Rakefile on Windows. - Based on patch by Roger Pack. - -* Rake now requires (instead of loads) files in the test task. Patch by Cezary - Baginski. - -* Fixed typos. Patches by Sean Scot August Moon and R.T. Lechow. - -* Rake now prints the Rakefile directory only when it's different from the - current directory. Patch by Alex Chaffee. - -* Improved rakefile_location discovery on Windows. Patch by James Tucker. - -* Rake now recognizes "Windows Server" as a windows system. Patch by Matthias - Lüdtke - -* Rake::RDocTask is deprecated. Use RDoc::Task from RDoc 2.4.2+ (require - 'rdoc/task') - -* Rake::GemPackageTask is deprecated. Use Gem::PackageTask (require - 'rubygems/package\_task') - -* Rake now outputs various messages to $stderr instead of $stdout. - -* Rake no longer emits warnings for Config. Patch by Santiago Pastorino. - -* Removed Rake's DSL methods from the top level scope. If you need to - call 'task :xzy' in your code, include Rake::DSL into your class, or - put the code in a Rake::DSL.environment do ... end block. - -* Split rake.rb into individual files. - -* Support for the --where (-W) flag for showing where a task is defined. - -* Fixed quoting in test task. - (http://onestepback.org/redmine/issues/show/44, - http://www.pivotaltracker.com/story/show/1223138) - -* Fixed the silent option parsing problem. - (http://onestepback.org/redmine/issues/show/47) - -* Fixed :verbose=>false flag on sh and ruby commands. - -* Rake command line options may be given by default in a RAKEOPT - environment variable. - -* Errors in Rake will now display the task invocation chain in effect - at the time of the error. - -* Accepted change by warnickr to not expand test patterns in shell - (allowing more files in the test suite). - -* Fixed that file tasks did not perform prereq lookups in scope - (Redmine #57). - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence (quix) -* Roger Pack -* Cezary Baginski -* Sean Scot August Moon -* R.T. Lechow -* Alex Chaffee -* James Tucker -* Matthias Lüdtke -* Santiago Pastorino - -Also, bit thanks to Eric Hodel for assisting with getting this release -out the door (where "assisting" includes, but is not by any means -limited to, "pushing" me to get it done). - --- Jim Weirich - - -=== 0.8.7 - -Rake version 0.8.5 introduced greatly improved support for executing -commands on Windows. The "sh" command now has the same semantics on -Windows that it has on Unix based platforms. - -Rake version 0.8.6 includes minor fixes the the RDoc generation. -Rake version 0.8.7 includes a minor fix for JRuby running on windows. - -==== Changes - -===== New Features / Enhancements in Version 0.8.5 - -* Improved implementation of the Rake system command for Windows. - (patch from James M. Lawrence/quix) - -* Support for Ruby 1.9's improved system command. (patch from James - M. Lawrence/quix) - -* Rake now includes the configured extension when invoking an - executable (Config::CONFIG['EXEEXT]) - -===== Bug Fixes in Version 0.8.5 - -* Environment variable keys are now correctly cased (it matters in - some implementations). - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Charles Nutter - --- Jim Weirich - -=== 0.8.6 - -Rake version 0.8.5 introduced greatly improved support for executing -commands on Windows. The "sh" command now has the same semantics on -Windows that it has on Unix based platforms. - -Rake version 0.8.5 includes minor fixes the the RDoc generation. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence/quix -* Luis Lavena - --- Jim Weirich - -=== 0.8.5 - -Rake version 0.8.5 is a new release of Rake with greatly improved -support for executing commands on Windows. The "sh" command now has -the same semantics on Windows that it has on Unix based platforms. - -==== Changes - -===== New Features / Enhancements in Version 0.8.5 - -* Improved implementation of the Rake system command for Windows. - (patch from James M. Lawrence/quix) - -* Support for Ruby 1.9's improved system command. (patch from James - M. Lawrence/quix) - -* Rake now includes the configured extension when invoking an - executable (Config::CONFIG['EXEEXT]) - -===== Bug Fixes in Version 0.8.5 - -* Environment variable keys are now correctly cased (it matters in - some implementations). - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence/quix -* Luis Lavena - --- Jim Weirich - -=== 0.8.4 - -Rake version 0.8.4 is a bug-fix release of rake. - -NOTE: The version of Rake that comes with Ruby 1.9 has diverged - slightly from the core Rake code base. Rake 0.8.4 will work - with Ruby 1.9, but is not a strict upgrade for the Rake that - comes with Ruby 1.9. A (near) future release of Rake will unify - those two codebases. - -==== Letter Writing Campaign - -Thanks to Aaron Patterson (@tenderlove) and Eric Hodel (@drbrain) for -their encouraging support in organizing a letter writing campaign to -lobby for the "Warning Free" release of rake 0.8.4. A special callout -goes to Jonathan D. Lord, Sr (Dr. Wingnut) whose postcard was the -first to actually reach me. (see -http://tenderlovemaking.com/2009/02/26/we-need-a-new-version-of-rake/ -for details) - -==== Changes - -===== New Features / Enhancements in Version 0.8.4 - -* Case is preserved on rakefile names. (patch from James - M. Lawrence/quix) - -* Improved Rakefile case insensitivity testing (patch from Luis - Lavena). - -* Windows system dir search order is now: HOME, HOMEDRIVE + HOMEPATH, - APPDATA, USERPROFILE (patch from Luis Lavena) - -* MingGW is now recognized as a windows platform. (patch from Luis - Lavena) - -===== Bug Fixes in Version 0.8.4 - -* Removed reference to manage_gem to fix the warning produced by the - gem package task. - -* Fixed stray ARGV option problem that was interfering with - Test::Unit::Runner. (patch from Pivotal Labs) - -===== Infrastructure Improvements in Version 0.8.4 - -* Numerous fixes to the windows test suite (patch from Luis Lavena). - -* Improved Rakefile case insensitivity testing (patch from Luis - Lavena). - -* Better support for windows paths in the test task (patch from Simon - Chiang/bahuvrihi) - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* James M. Lawrence/quix -* Luis Lavena -* Pivotal Labs -* Simon Chiang/bahuvrihi - --- Jim Weirich - -=== 0.8.3 - -Rake version 0.8.3 is a bug-fix release of rake. - -==== Changes - -===== Bug Fixes in Version 0.8.3 - -* Enhanced the system directory detection in windows. We now check - HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch - supplied by James Tucker). Rake no long aborts if it can't find the - directory. - -* Added fix to handle ruby installations in directories with spaces in - their name. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Edwin Pratomo -* Gavin Stark -* Adam Q. Salter -* Adam Majer -* Emanuel Indermühle -* Ittay Dror -* Bheeshmar Redheendran (for spending an afternoon with me debugging - windows issues) - --- Jim Weirich - - -=== 0.8.2 - -Rake version 0.8.2 is a new release of rake that includes a number of -new features and numerous bug fixes. - -==== Changes - -===== New Features in Version 0.8.2 - -* Switched from getoptlong to optparse (patches supplied by Edwin - Pratomo). - -* The -T option will now attempt to dynamically sense the size of the - terminal. The -T output will only self-truncate if the output is a - tty. However, if RAKE_COLUMNS is explicitly set, it will be honored - in any case. (Patch provided by Gavin Stark). - -* The following public methods have been added to rake task objects: - - * task.clear -- Clear both the prerequisites and actions of the - target rake task. - * task.clear_prerequisites -- Clear all the existing prerequisites - from the target rake task. - * task.clear_actions -- Clear all the existing actions from the - target rake task. - * task.reenable -- Re-enable a task, allowing its actions to be - executed again if the task is invoked. - -* Changed RDoc test task to have no default template. This makes it - easier for the tempate to pick up the template from the environment. - -* Default values for task arguments can easily be specified with the - :with_defaults method. (Idea for default argument merging supplied - by (Adam Q. Salter) - -===== Bug Fixes in Version 0.8.2 - -* Fixed bug in package task so that it will include the subdir - directory in the package for testing. (Bug found by Adam Majer) - -* Fixed filename dependency order bug in test\_inspect\_pending and - test\_to\_s\_pending. (Bug found by Adam Majer) - -* Fixed check for file utils options to make them immune to the - symbol/string differences. (Patch supplied by Edwin Pratomo) - -* Fixed bug with rules involving multiple source, where only the first - dependency of a rule has any effect (Patch supplied by Emanuel - Indermühle) - -* FileList#clone and FileList#dup have better sematics w.r.t. taint - and freeze. - -* Changed from using Mutex to Monitor. Evidently Mutex causes thread - join errors when Ruby is compiled with -disable-pthreads. (Patch - supplied by Ittay Dror) - -* Fixed bug in makefile parser that had problems with extra spaces in - file task names. (Patch supplied by Ittay Dror) - -==== Other changes in Version 0.8.2 - -* Added ENV var to rake's own Rakefile to prevent OS X from including - extended attribute junk in the rake package tar file. (Bug found by - Adam Majer) - -* Added a performance patch for reading large makefile dependency - files. (Patch supplied by Ittay Dror) - -==== Task Argument Examples - -Prior to version 0.8.0, rake was only able to handle command line -arguments of the form NAME=VALUE that were passed into Rake via the -ENV hash. Many folks had asked for some kind of simple command line -arguments, perhaps using "--" to separate regular task names from -argument values on the command line. The problem is that there was no -easy way to associate positional arguments on the command line with -different tasks. Suppose both tasks :a and :b expect a command line -argument: does the first value go with :a? What if :b is run first? -Should it then get the first command line argument. - -Rake 0.8.0 solves this problem by explicitly passing values directly -to the tasks that need them. For example, if I had a release task -that required a version number, I could say: - - rake release[0.8.2] - -And the string "0.8.2" will be passed to the :release task. Multiple -arguments can be passed by separating them with a comma, for example: - - rake name[john,doe] - -Just a few words of caution. The rake task name and its arguments -need to be a single command line argument to rake. This generally -means no spaces. If spaces are needed, then the entire rake + -argument string should be quoted. Something like this: - - rake "name[billy bob, smith]" - -(Quoting rules vary between operating systems and shells, so make sure -you consult the proper docs for your OS/shell). - -===== Tasks that Expect Parameters - -Parameters are only given to tasks that are setup to expect them. In -order to handle named parameters, the task declaration syntax for -tasks has been extended slightly. - -For example, a task that needs a first name and last name might be -declared as: - - task :name, :first_name, :last_name - -The first argument is still the name of the task (:name in this case). -The next to argumements are the names of the parameters expected by -:name (:first_name and :last_name in the example). - -To access the values of the parameters, the block defining the task -behaviour can now accept a second parameter: - - task :name, :first_name, :last_name do |t, args| - puts "First name is #{args.first_name}" - puts "Last name is #{args.last_name}" - end - -The first argument of the block "t" is always bound to the current -task object. The second argument "args" is an open-struct like object -that allows access to the task arguments. Extra command line -arguments to a task are ignored. Missing command line arguments are -given the nil value. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Edwin Pratomo -* Gavin Stark -* Adam Q. Salter -* Adam Majer -* Emanuel Indermühle -* Ittay Dror -* Bheeshmar Redheendran (for spending an afternoon with me debugging - windows issues) - --- Jim Weirich - -=== 0.8.0/0.8.1 - -Rake version 0.8.0 is a new release of rake that includes serveral new -features. - -==== Changes - -===== New Features in Version 0.8.0 - -* Tasks can now receive command line parameters. See the examples - below for more details. - -* Comments are limited to 80 columns on output, but full comments can - be seen by using the -D parameter. (feature suggested by Jamis - Buck). - -* Explicit exit(n) calls will now set the exit status to n. (patch - provided by Stephen Touset). - -* Rake is now compatible with Ruby 1.9. - -Version 0.8.1 is a minor update that includes additional Ruby 1.9 -compatibility fixes. - -==== Task Argument Examples - -Prior to version 0.8.0, rake was only able to handle command line -arguments of the form NAME=VALUE that were passed into Rake via the -ENV hash. Many folks had asked for some kind of simple command line -arguments, perhaps using "--" to separate regular task names from -argument values on the command line. The problem is that there was no -easy way to associate positional arguments on the command line with -different tasks. Suppose both tasks :a and :b expect a command line -argument: does the first value go with :a? What if :b is run first? -Should it then get the first command line argument. - -Rake 0.8.0 solves this problem by explicitly passing values directly -to the tasks that need them. For example, if I had a release task -that required a version number, I could say: - - rake release[0.8.0] - -And the string "0.8.0" will be passed to the :release task. Multiple -arguments can be passed by separating them with a comma, for example: - - rake name[john,doe] - -Just a few words of caution. The rake task name and its arguments -need to be a single command line argument to rake. This generally -means no spaces. If spaces are needed, then the entire rake + -argument string should be quoted. Something like this: - - rake "name[billy bob, smith]" - -(Quoting rules vary between operating systems and shells, so make sure -you consult the proper docs for your OS/shell). - -===== Tasks that Expect Parameters - -Parameters are only given to tasks that are setup to expect them. In -order to handle named parameters, the task declaration syntax for -tasks has been extended slightly. - -For example, a task that needs a first name and last name might be -declared as: - - task :name, :first_name, :last_name - -The first argument is still the name of the task (:name in this case). -The next to argumements are the names of the parameters expected by -:name (:first_name and :last_name in the example). - -To access the values of the parameters, the block defining the task -behaviour can now accept a second parameter: - - task :name, :first_name, :last_name do |t, args| - puts "First name is #{args.first_name}" - puts "Last name is #{args.last_name}" - end - -The first argument of the block "t" is always bound to the current -task object. The second argument "args" is an open-struct like object -that allows access to the task arguments. Extra command line -arguments to a task are ignored. Missing command line arguments are -given the nil value. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - -* Jamis Buck (for comment formatting suggestions) -* Stephen Touset (for exit status patch). - --- Jim Weirich - - -=== 0.7.3 - -Rake version 0.7.3 is a minor release that includes some refactoring to better -support custom Rake applications. - -==== Changes - -===== New Features in Version 0.7.3 - -* Added the +init+ and +top_level+ methods to make the creation of custom Rake applications a bit easier. E.g. - - gem 'rake', ">= 0.7.3" - require 'rake' - - Rake.application.init('myrake') - - task :default do - something_interesting - end - - Rake.application.top_level - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. The -following people either contributed patches, made suggestions or made -otherwise helpful comments. Thanks to ... - --- Jim Weirich - - -=== 0.7.2 - - -Version 0.7.2 supplies a bug fix and a few minor enhancements. In -particular, the new version fixes an incompatibility with the soon to -be released Ruby 1.8.6. We strongly recommend upgrading to Rake 0.7.2 -in order to be compatible with the new version of Ruby. - -==== Changes - -===== Bug Fixes in 0.7.2 - -There are quite a number of bug fixes in the new 0.7.2 version of -Rake: - -* Removed dependency on internal fu_xxx functions from FileUtils. - -* Error messages are now send to stderr rather than stdout (from - Payton Quackenbush). - -* Better error handling on invalid command line arguments (from Payton - Quackenbush). - -* Fixed some bugs where the application object was going to the global - appliation instead of using its own data. - -* Fixed the method name leak from FileUtils (bug found by Glenn - Vanderburg). - -* Added test for noop, bad_option and verbose flags to sh command. - -* Added a description to the gem task in GemPackageTask. - -* Fixed a bug when rules have multiple prerequisites (patch by Joel - VanderWerf) - -* Added the handful of RakeFileUtils to the private method as well. - -===== New Features in 0.7.2 - -The following new features are available in Rake version 0.7.2: - -* Added square and curly bracket patterns to FileList#include (Tilman - Sauerbeck). - -* FileLists can now pass a block to FileList#exclude to exclude files - based on calculated values. - -* Added plain filename support to rule dependents (suggested by Nobu - Nakada). - -* Added pathmap support to rule dependents. In other words, if a - pathmap format (beginning with a '%') is given as a Rake rule - dependent, then the name of the depend will be the name of the - target with the pathmap format applied. - -* Added a 'tasks' method to a namespace to get a list of tasks - associated with the namespace. - -* Added tar_command and zip_command options to the Package task. - -* The clean task will no longer delete 'core' if it is a directory. - -===== Internal Rake Improvements - -The following changes will are mainly internal improvements and -refactorings and have little effect on the end user. But they may be -of interest to the general public. - -* Added rcov task and updated unit testing for better code coverage. - -* Added a 'shame' task to the Rakefile. - -* Added rake_extension to handle detection of extension collisions. - -* Added a protected 'require "rubygems"' to test/test_application to - unbreak cruisecontrol.rb. - -* Removed rake\_dup. Now we just simply rescue a bad dup. - -* Refactored the FileList reject logic to remove duplication. - -* Removed if \_\_FILE\_\_ at the end of the rake.rb file. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. -The following people either contributed patches, made suggestions or -made otherwise helpful comments. Thanks to ... - -* Payton Quackenbush -- For several error handling improvements. - -* Glenn Vanderburg -- For finding and fixing the method name leak from - FileUtils. - -* Joel VanderWerf -- for finding and fixing a bug in the handling of - multiple prerequisites. - -* Tilman Sauerbeck -- For some enhancing FileList to support more - advanced file globbing. - -* Nobu Nakada -- For suggesting plain file name support to rule dependents. - --- Jim Weirich - -=== 0.7.1 - -Version 0.7.1 supplies a bug fix and a few minor enhancements. - -==== Changes - -===== Bug Fixes in 0.7.1 - -* Changes in the exception reported for the FileUtils.ln caused - safe_ln to fail with a NotImplementedError. Rake 0.7.1 will now - catch that error or any StandardError and properly fall back to - using +cp+. - -===== New Features in 0.7.1 - -* You can filter the results of the --task option by supplying an - optional regular expression. This allows the user to easily find a - particular task name in a long list of possible names. - -* Transforming procs in a rule may now return a list of prerequisites. - This allows more flexible rule formation. - -* FileList and String now support a +pathmap+ melthod that makes the - transforming paths a bit easier. See the API docs for +pathmap+ for - details. - -* The -f option without a value will disable the search for a - Rakefile. This allows the Rakefile to be defined entirely in a - library (and loaded with the -r option). The current working - directory is not changed when this is done. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. -The following people either contributed patches, made suggestions or -made otherwise helpful comments. Thanks to ... - -* James Britt and Assaph Mehr for reporting and helping to debug the - safe_ln issue. - --- Jim Weirich - - -=== 0.7.0 - -These changes for Rake have been brewing for a long time. Here they -are, I hope you enjoy them. - -==== Changes - -===== New Features - -* Name space support for task names (see below). -* Prerequisites can be executed in parallel (see below). -* Added safe_ln support for openAFS (via Ludvig Omholt). -* RDoc defaults to internal (in-process) invocation. The old behavior - is still available by setting the +external+ flag to true. -* Rakefiles are now loaded with the expanded path to prevent - accidental pollution from the Ruby load path. -* Task objects my now be used in prerequisite lists directly. -* Task objects (in addition to task names) may now be included in the - prerequisite list of a task. -* Internals cleanup and refactoring. - -===== Bug Fixes - -* Compatibility fixes for Ruby 1.8.4 FileUtils changes. - -===== Namespaces - -Tasks can now be nested inside their own namespaces. Tasks within one -namespace will not accidentally interfer with tasks named in a different -namespace. - -For example: - - namespace "main" do - task :build do - # Build the main program - end - end - - namespace "samples" do - task :build do - # Build the sample programs - end - end - - task :build_all => ["main:build", "samples:build"] - -Even though both tasks are named :build, they are separate tasks in -their own namespaces. The :build_all task (defined in the toplevel -namespace) references both build tasks in its prerequisites. - -You may invoke each of the individual build tasks with the following -commands: - - rake main:build - rake samples:build - -Or invoke both via the :build_all command: - - rake build_all - -Namespaces may be nested arbitrarily. Since the name of file tasks -correspond to the name of a file in the external file system, -FileTasks are not affected by the namespaces. - -See the Rakefile format documentation (in the Rake API documents) for -more information. - -===== Parallel Tasks - -Sometimes you have several tasks that can be executed in parallel. By -specifying these tasks as prerequisites to a +multitask+ task. - -In the following example the tasks copy\_src, copy\_doc and copy\_bin -will all execute in parallel in their own thread. - - multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do - puts "All Copies Complete" - end - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. -The following people either contributed patches, made suggestions or -made otherwise helpful comments. Thanks to ... - -* Doug Young (inspiration for the parallel task) -* David Heinemeier Hansson (for --trace message enhancement and for - pushing for namespace support). -* Ludvig Omholt (for the openAFS fix) - --- Jim Weirich - -=== 0.6.1 - -* Rebuilt 0.6.0 gem without signing. - -=== 0.6.0 - -Its time for some long requested enhancements and lots of bug fixes -... And a whole new web page. - -==== New Web Page - -The primary documentation for rake has moved from the RubyForge based -wiki to its own Hieraki based web site. Constant spam on the wiki -made it a difficult to keep clean. The new site will be easier to -update and organize. - -Check out the new documentation at: http://docs.rubyrake.org - -We will be adding new documentation to the site as time goes on. - -In addition to the new docs page, make sure you check out Martin -Fowlers article on rake at http://martinfowler.com/articles/rake.html - -==== Changes - -===== New Features - -* Multiple prerequisites on Rake rules now allowed. However, keep the - following in mind: - - 1. All the prerequisites of a rule must be available before a rule - is triggered, where "enabled" means (a) an existing file, (b) a - defined rule, or (c) another rule which also must be - trigger-able. - 2. Rules are checked in order of definition, so it is important to - order your rules properly. If a file can be created by two - different rules, put the more specific rule first (otherwise the - more general rule will trigger first and the specific one will - never be triggered). - 3. The source method now returns the name of the first - prerequisite listed in the rule. sources returns the - names of all the rule prerequisites, ordered as they are defined - in the rule. If the task has other prerequisites not defined in - the rule (but defined in an explicit task definition), then they - will _not_ be included in the sources list. - -* FileLists may now use the egrep command. This popular enhancement - is now a core part of the FileList object. If you want to get a - list of all your to-dos, fixmes and TBD comments, add the following - to your Rakefile. - - desc "Look for TODO and FIXME tags in the code" - task :todo do - FileList['**/*.rb'].egrep /#.*(FIXME|TODO|TBD)/ - end - -* The investigation method was added to task object to dump - out some important values. This makes it a bit easier to debug Rake - tasks. - - For example, if you are having problems with a particular task, just - print it out: - - task :huh do - puts Rake::Task['huh'].investigation - end - -* The Rake::TestTask class now supports a "ruby\_opts" option to pass - arbitrary ruby options to a test subprocess. - -===== Some Incompatibilities - -* When using the ruby command to start a Ruby subprocess, the - Ruby interpreter that is currently running rake is used by default. - This makes it easier to use rake in an environment with multiple - ruby installation. (Previously, the first ruby command found in the - PATH was used). - - If you wish to chose a different Ruby interpreter, you can - explicitly choose the interpreter via the sh command. - -* The major rake classes (Task, FileTask, FileCreationTask, RakeApp) - have been moved out of the toplevel scope and are now accessible as - Rake::Task, Rake::FileTask, Rake::FileCreationTask and - Rake::Application. If your Rakefile - directly references any one of these tasks, you may: - - 1. Update your Rakefile to use the new classnames - 2. Use the --classic-namespace option on the rake command to get the - old behavior, - 3. Add require 'rake/classic_namespace' to the - Rakefile to get the old behavior. - - rake will print a rather annoying warning whenever a - deprecated class name is referenced without enabling classic - namespace. - -===== Bug Fixes - -* Several unit tests and functional tests were fixed to run better - under windows. - -* Directory tasks are now a specialized version of a File task. A - directory task will only be triggered if it doesn't exist. It will - not be triggered if it is out of date w.r.t. any of its - prerequisites. - -* Fixed a bug in the Rake::GemPackageTask class so that the gem now - properly contains the platform name. - -* Fixed a bug where a prerequisite on a file task would cause - an exception if the prerequisite did not exist. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. -The following people either contributed patches, made suggestions or -made otherwise helpful comments. Thanks to ... - -* Greg Fast (better ruby_opt test options) -* Kelly Felkins (requested by better namespace support) -* Martin Fowler (suggested Task.investigation) -* Stuart Jansen (send initial patch for multiple prerequisites). -* Masao Mutch (better support for non-ruby Gem platforms) -* Philipp Neubeck (patch for file task exception fix) - --- Jim Weirich - -=== 0.5.4 - -Time for some minor bug fixes and small enhancements - -==== Changes - -Here are the changes for version 0.5.4 ... - -* Added double quotes to the test runner. This allows the location of - the tests (and runner) to be in a directory path that contains - spaces (e.g. "C:/Program Files/ruby/bin"). -* Added .svn to default ignore list. Now subversion project metadata - is automatically ignored by Rake's FileList. -* Updated FileList#include to support nested arrays and filelists. - FileLists are flat lists of file names. Using a FileList in an - include will flatten out the nested file names. - -== Thanks - -As usual, it was input from users that drove a alot of these changes. -Thanks to ... - -* Tilman Sauerbeck for the nested FileList suggestion. -* Josh Knowles for pointing out the spaces in directory name problem. - --- Jim Weirich - -=== 0.5.3 - -Although it has only been two weeks since the last release, we have -enough updates to the Rake program to make it time for another -release. - -==== Changes - -Here are the changes for version 0.5.3 ... - -* FileLists have been extensively changed so that they mimic the - behavior of real arrays even more closely. In particular, - operations on FileLists that return a new collection (e.g. collect, - reject) will now return a FileList rather than an array. In - addition, several places where FileLists were not properly expanded - before use have been fixed. -* A method (+ext+) to simplify the handling of file extensions was - added to String and to Array. -* The 'testrb' script in test/unit tends to silently swallow syntax - errors in test suites. Because of that, the default test loader is - now a rake-provided script. You can still use 'testrb' by setting - the loader flag in the test task to :testrb. (See the API documents - for TestTask for all the loader flag values). -* FileUtil methods (e.g. cp, mv, install) are now declared to be - private. This will cut down on the interference with user defined - methods of the same name. -* Fixed the verbose flag in the TestTask so that the test code is - controlled by the flag. Also shortened up some failure messages. - (Thanks to Tobias Luetke for the suggestion). -* Rules will now properly detect a task that can generate a source - file. Previously rules would only consider source files that were - already present. -* Added an +import+ command that allows Rake to dynamically import - dependendencies into a running Rake session. The +import+ command - can run tasks to update the dependency file before loading them. - Dependency files can be in rake or make format, allowing rake to - work with tools designed to generate dependencies for make. - -==== Thanks - -As usual, it was input from users that drove a alot of these changes. -Thanks to ... - -* Brian Gernhardt for the rules fix (especially for the patience to - explain the problem to me until I got what he was talking about). -* Stefan Lang for pointing out problems in the dark corners of the - FileList implementation. -* Alexey Verkhovsky pointing out the silently swallows syntax errors - in tests. -* Tobias Luetke for beautifying the test task output. -* Sam Roberts for some of the ideas behind dependency loading. - --- Jim Weirich - - -=== 0.5.0 - -It has been a long time in coming, but we finally have a new version -of Rake available. - -==== Changes - -* Fixed documentation that was lacking the Rake module name (Tilman - Sauerbeck). -* Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck). -* Recursive rules are now supported (Tilman Sauerbeck). -* Added warning option for the Test Task (requested by Eric Hodel). -* The jamis rdoc template is only used if it exists. -* Added fix for Ruby 1.8.2 test/unit and rails problem. -* Added contributed rake man file (Jani Monoses). -* Added Brian Candler's fix for problems in --trace and --dry-run - mode. - -==== Thanks - -Lots of people provided input to this release. Thanks to Tilman -Sauerbeck for numerous patches, documentation fixes and suggestions. -And for also pushing me to get this release out. Also, thanks to -Brian Candler for the finding and fixing --trace/dry-run fix. That -was an obscure bug. Also to Eric Hodel for some good suggestions. - --- Jim Weirich - -=== 0.4.15 - -==== Changes - -Version 0.4.15 is a bug fix update for the Ruby 1.8.2 compatibility -changes. This release includes: - -* Fixed a bug that prevented the TESTOPTS flag from working with the - revised for 1.8.2 test task. -* Updated the docs on --trace to indicate that it also enables a full - backtrace on errors. -* Several fixes for new warnings generated. - -==== Mini-Roadmap - -I will continue to issue Rake updates in the 0.4.xx series as new -Ruby-1.8.2 issues become manifest. Once the codebase stabilizes, I -will release a 0.5.0 version incorporating all the changes. If you -are not using Ruby-1.8.2 and wish to avoid version churn, I recommend -staying with a release prior to Rake-0.4.14. - -=== 0.4.14 - -Version 0.4.14 is a compatibility fix to allow Rake's test task to -work under Ruby 1.8.2. A change in the Test::Unit autorun feature -prevented Rake from running any tests. This release fixes the -problem. - -Rake 0.4.14 is the recommended release for anyone using Ruby 1.8.2. - -=== 0.4.13 - -* Fixed the dry-run flag so it is operating again. -* Multiple arguments to sh and ruby commands will not be interpreted - by the shell (patch provided by Jonathan Paisley). - -=== 0.4.12 - -* Added --silent (-s) to suppress the (in directory) rake message. - -=== 0.4.11 - -* Changed the "don't know how to rake" message (finally) -* Changes references to a literal "Rakefile" to reference the global - variable $rakefile (which contains the actual name of the rakefile). - -=== 0.4.10 - -* Added block support to the "sh" command, allowing users to take - special actions on the result of the system call. E.g. - - sh "shell_command" do |ok, res| - puts "Program returned #{res.exitstatus}" if ! ok - end - -=== 0.4.9 - -* Switched to Jamis Buck's RDoc template. -* Removed autorequire from Rake's gem spec. This prevents the Rake - libraries from loading while using rails. - -=== 0.4.8 - -* Added support for .rb versions of Rakefile. -* Removed \\\n's from test task. -* Fixed Ruby 1.9 compatibility issue with FileList. - -=== 0.4.7 - -* Fixed problem in FileList that caused Ruby 1.9 to go into infinite - recursion. Since to_a was removed from Object, it does not need to - added back into the list of methods to rewrite in FileList. (Thanks - to Kent Sibilev for pointing this out). - -=== 0.4.6 -* Removed test version of ln in FileUtils that prevented safe_ln from - using ln. - -=== 0.4.5 -* Upgraded comments in TestTask. -* FileList to_s and inspect now automatically resolve pending changes. -* FileList#exclude properly returns the FileList. - -=== 0.4.4 -* Fixed initialization problem with @comment. -* Now using multi -r technique in TestTask. Switch Rakefile back to - using the built-in test task macros because the rake runtime is no - longer needed. -* Added 'TEST=filename' and 'TESTOPTS=options' to the Test Task - macros. -* Allow a +test_files+ attribute in test tasks. This allows more - flexibility in specifying test files. - -=== 0.4.3 -* Fixed Comment leakage. - -=== 0.4.2 -* Added safe_ln that falls back to a copy if a file link is not supported. -* Package builder now uses safe\_ln. - -=== 0.4.1 -* Task comments are now additive, combined with "/". -* Works with (soon to be released) rubygems 0.6.2 (or 0.7.0) - -=== 0.4.0 -* FileList now uses deferred loading. The file system is not searched - until the first call that needs the file names. -* VAR=VALUE options are now accepted on the command line and are - treated like environment variables. The values may be tested in a - Rakefile by referencing ENV['VAR']. -* File.mtime is now used (instead of File.new().mtime). - -=== 0.3.2.x - -* Removed some hidden dependencies on rubygems. Tests now will test - gems only if they are installed. -* Removed Sys from some example files. I believe that is that last - reference to Sys outside of the contrib area. -* Updated all copyright notices to include 2004. - -=== 0.3.2 - -* GEM Installation now works with the application stub. - -=== 0.3.1 - -* FileLists now automatically ignore CVS, .bak, ! -* GEM Installation now works. - -=== 0.3.0 - -Promoted 0.2.10. - -=== 0.2.10 -General - -* Added title to Rake's rdocs -* Contrib packages are no longer included in the documentation. - -RDoc Issues - -* Removed default for the '--main' option -* Fixed rendering of the rdoc options -* Fixed clean/clobber confusion with rerdoc -* 'title' attribute added - -Package Task Library Issues - -* Version (or explicit :noversion) is required. -* +package_file+ attribute is now writable - -FileList Issues - -* Dropped bang version of exclude. Now using ant-like include/exclude semantics. -* Enabled the "yield self" idiom in FileList#initialize. - -=== 0.2.9 - -This version contains numerous changes as the RubyConf.new(2003) -presentation was being prepared. The changes include: - -* The monolithic rubyapp task library is in the process of being - dropped in favor of lighter weight task libraries. - -=== 0.2.7 - -* Added "desc" for task descriptions. -* -T will now display tasks with descriptions. -* -P will display tasks and prerequisites. -* Dropped the Sys module in favor of the 1.8.x FileUtils module. Sys - is still supported in the contrib area. - -=== 0.2.6 - -* Moved to RubyForge - -=== 0.2.5 - -* Switched to standard ruby app builder. -* Added no_match option to file matcher. - -=== 0.2.4 - -* Fixed indir, which neglected to actually change directories. - -=== 0.2.3 - -* Added rake module for a help target -* Added 'for\_files' to Sys -* Added a $rakefile constant -* Added test for selecting proper rule with multiple targets. diff --git a/ruby/gems/rake-13.0.1/MIT-LICENSE b/ruby/gems/rake-13.0.1/MIT-LICENSE deleted file mode 100644 index 4292f3b3c..000000000 --- a/ruby/gems/rake-13.0.1/MIT-LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) Jim Weirich - -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. - diff --git a/ruby/gems/rake-13.0.1/README.rdoc b/ruby/gems/rake-13.0.1/README.rdoc deleted file mode 100644 index 5f0278d8e..000000000 --- a/ruby/gems/rake-13.0.1/README.rdoc +++ /dev/null @@ -1,155 +0,0 @@ -= RAKE -- Ruby Make - -home :: https://github.com/ruby/rake -bugs :: https://github.com/ruby/rake/issues -docs :: https://ruby.github.io/rake - -== Description - -Rake is a Make-like program implemented in Ruby. Tasks and dependencies are -specified in standard Ruby syntax. - -Rake has the following features: - -* Rakefiles (rake's version of Makefiles) are completely defined in - standard Ruby syntax. No XML files to edit. No quirky Makefile - syntax to worry about (is that a tab or a space?) - -* Users can specify tasks with prerequisites. - -* Rake supports rule patterns to synthesize implicit tasks. - -* Flexible FileLists that act like arrays but know about manipulating - file names and paths. - -* A library of prepackaged tasks to make building rakefiles easier. For example, - tasks for building tarballs. (Formerly - tasks for building RDoc, Gems, and publishing to FTP were included in rake but they're now - available in RDoc, RubyGems, and rake-contrib respectively.) - -* Supports parallel execution of tasks. - -== Installation - -=== Gem Installation - -Download and install rake with the following. - - gem install rake - -== Usage - -=== Simple Example - -First, you must write a "Rakefile" file which contains the build rules. Here's -a simple example: - - task default: %w[test] - - task :test do - ruby "test/unittest.rb" - end - -This Rakefile has two tasks: - -* A task named "test", which -- upon invocation -- will run a unit test file - in Ruby. -* A task named "default". This task does nothing by itself, but it has exactly - one dependency, namely the "test" task. Invoking the "default" task will - cause Rake to invoke the "test" task as well. - -Running the "rake" command without any options will cause it to run the -"default" task in the Rakefile: - - % ls - Rakefile test/ - % rake - (in /home/some_user/Projects/rake) - ruby test/unittest.rb - ....unit test output here... - -Type "rake --help" for all available options. - -== Resources - -=== Rake Information - -* {Rake command-line}[link:doc/command_line_usage.rdoc] -* {Writing Rakefiles}[link:doc/rakefile.rdoc] -* The original {Rake announcement}[link:doc/rational.rdoc] -* Rake {glossary}[link:doc/glossary.rdoc] - -=== Presentations and Articles about Rake - -* Avdi Grimm's rake series: - 1. {Rake Basics}[http://devblog.avdi.org/2014/04/21/rake-part-1-basics/] - 2. {Rake File Lists}[http://devblog.avdi.org/2014/04/22/rake-part-2-file-lists/] - 3. {Rake Rules}[http://devblog.avdi.org/2014/04/23/rake-part-3-rules/] - 4. {Rake Pathmap}[http://devblog.avdi.org/2014/04/24/rake-part-4-pathmap/] - 5. {File Operations}[http://devblog.avdi.org/2014/04/25/rake-part-5-file-operations/] - 6. {Clean and Clobber}[http://devblog.avdi.org/2014/04/28/rake-part-6-clean-and-clobber/] - 7. {MultiTask}[http://devblog.avdi.org/2014/04/29/rake-part-7-multitask/] -* {Jim Weirich's 2003 RubyConf presentation}[http://web.archive.org/web/20140221123354/http://onestepback.org/articles/buildingwithrake/] -* Martin Fowler's article on Rake: http://martinfowler.com/articles/rake.html - -== Other Make Re-envisionings ... - -Rake is a late entry in the make replacement field. Here are links to -other projects with similar (and not so similar) goals. - -* http://directory.fsf.org/wiki/Bras -- Bras, one of earliest - implementations of "make in a scripting language". -* http://www.a-a-p.org -- Make in Python -* http://ant.apache.org -- The Ant project -* http://search.cpan.org/search?query=PerlBuildSystem -- The Perl Build System -* http://www.rubydoc.info/gems/rant/0.5.7/frames -- Rant, another Ruby make tool. - -== Credits - -[Jim Weirich] Who originally created Rake. - -[Ryan Dlugosz] For the initial conversation that sparked Rake. - -[Nobuyoshi Nakada ] For the initial patch for rule support. - -[Tilman Sauerbeck ] For the recursive rule patch. - -[Eric Hodel] For aid in maintaining rake. - -[Hiroshi SHIBATA] Maintainer of Rake 10.X and Rake 11.X - -== License - -Rake is available under an MIT-style license. - -:include: MIT-LICENSE - ---- - -= Other stuff - -Author:: Jim Weirich -Requires:: Ruby 2.0.0 or later -License:: Copyright Jim Weirich. - Released under an MIT-style license. See the MIT-LICENSE - file included in the distribution. - -== Warranty - -This software is provided "as is" and without any express or implied -warranties, including, without limitation, the implied warranties of -merchantability and fitness for a particular purpose. - -== Historical - -Rake was originally created by Jim Weirich, who unfortunately passed away in -February 2014. This repository was originally hosted at -{github.com/jimweirich/rake}[https://github.com/jimweirich/rake/], however -with his passing, has been moved to {ruby/rake}[https://github.com/ruby/rake]. - -You can view Jim's last commit here: -https://github.com/jimweirich/rake/tree/336559f28f55bce418e2ebcc0a57548dcbac4025 - -You can {read more about Jim}[https://en.wikipedia.org/wiki/Jim_Weirich] at Wikipedia. - -Thank you for this great tool, Jim. We'll remember you. diff --git a/ruby/gems/rake-13.0.1/Rakefile b/ruby/gems/rake-13.0.1/Rakefile deleted file mode 100644 index e03dc6feb..000000000 --- a/ruby/gems/rake-13.0.1/Rakefile +++ /dev/null @@ -1,41 +0,0 @@ -# Rakefile for rake -*- ruby -*- - -# Copyright 2003, 2004, 2005 by Jim Weirich (jim@weirichhouse.org) -# All rights reserved. - -# This file may be distributed under an MIT style license. See -# MIT-LICENSE for details. - -lib = File.expand_path("../lib", __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) - -begin - require "bundler/gem_tasks" -rescue LoadError -end - -require "rake/testtask" -Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.verbose = true - t.test_files = FileList["test/**/test_*.rb"] -end - -require "rdoc/task" -RDoc::Task.new do |doc| - doc.main = "README.rdoc" - doc.title = "Rake -- Ruby Make" - doc.rdoc_files = FileList.new %w[lib MIT-LICENSE doc/**/*.rdoc *.rdoc] - doc.rdoc_dir = "html" -end - -task ghpages: :rdoc do - %x[git checkout gh-pages] - require "fileutils" - FileUtils.rm_rf "/tmp/html" - FileUtils.mv "html", "/tmp" - FileUtils.rm_rf "*" - FileUtils.cp_r Dir.glob("/tmp/html/*"), "." -end - -task default: :test diff --git a/ruby/gems/rake-13.0.1/bin/bundle b/ruby/gems/rake-13.0.1/bin/bundle deleted file mode 100755 index 524dfd3f2..000000000 --- a/ruby/gems/rake-13.0.1/bin/bundle +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# -# This file was generated by Bundler. -# -# The application 'bundle' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "rubygems" - -m = Module.new do - module_function - - def invoked_as_script? - File.expand_path($0) == File.expand_path(__FILE__) - end - - def env_var_version - ENV["BUNDLER_VERSION"] - end - - def cli_arg_version - return unless invoked_as_script? # don't want to hijack other binstubs - return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` - bundler_version = nil - update_index = nil - ARGV.each_with_index do |a, i| - if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN - bundler_version = a - end - next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ - bundler_version = $1 || ">= 0.a" - update_index = i - end - bundler_version - end - - def gemfile - gemfile = ENV["BUNDLE_GEMFILE"] - return gemfile if gemfile && !gemfile.empty? - - File.expand_path("../../Gemfile", __FILE__) - end - - def lockfile - lockfile = - case File.basename(gemfile) - when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) - else "#{gemfile}.lock" - end - File.expand_path(lockfile) - end - - def lockfile_version - return unless File.file?(lockfile) - lockfile_contents = File.read(lockfile) - return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ - Regexp.last_match(1) - end - - def bundler_version - @bundler_version ||= begin - env_var_version || cli_arg_version || - lockfile_version || "#{Gem::Requirement.default}.a" - end - end - - def load_bundler! - ENV["BUNDLE_GEMFILE"] ||= gemfile - - # must dup string for RG < 1.8 compatibility - activate_bundler(bundler_version.dup) - end - - def activate_bundler(bundler_version) - if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") - bundler_version = "< 2" - end - gem_error = activation_error_handling do - gem "bundler", bundler_version - end - return if gem_error.nil? - require_error = activation_error_handling do - require "bundler/version" - end - return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) - warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" - exit 42 - end - - def activation_error_handling - yield - nil - rescue StandardError, LoadError => e - e - end -end - -m.load_bundler! - -if m.invoked_as_script? - load Gem.bin_path("bundler", "bundle") -end diff --git a/ruby/gems/rake-13.0.1/bin/console b/ruby/gems/rake-13.0.1/bin/console deleted file mode 100755 index b8342352c..000000000 --- a/ruby/gems/rake-13.0.1/bin/console +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby - -require "bundler/setup" -require "rake" - -require "irb" -IRB.start diff --git a/ruby/gems/rake-13.0.1/bin/rake b/ruby/gems/rake-13.0.1/bin/rake deleted file mode 100755 index 9275675e8..000000000 --- a/ruby/gems/rake-13.0.1/bin/rake +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# -# This file was generated by Bundler. -# -# The application 'rake' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -bundle_binstub = File.expand_path("../bundle", __FILE__) - -if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ - load(bundle_binstub) - else - abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. -Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") - end -end - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("rake", "rake") diff --git a/ruby/gems/rake-13.0.1/bin/rdoc b/ruby/gems/rake-13.0.1/bin/rdoc deleted file mode 100755 index a952e7988..000000000 --- a/ruby/gems/rake-13.0.1/bin/rdoc +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# -# This file was generated by Bundler. -# -# The application 'rdoc' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -bundle_binstub = File.expand_path("../bundle", __FILE__) - -if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ - load(bundle_binstub) - else - abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. -Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") - end -end - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("rdoc", "rdoc") diff --git a/ruby/gems/rake-13.0.1/bin/rubocop b/ruby/gems/rake-13.0.1/bin/rubocop deleted file mode 100755 index d0c488293..000000000 --- a/ruby/gems/rake-13.0.1/bin/rubocop +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# -# This file was generated by Bundler. -# -# The application 'rubocop' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -bundle_binstub = File.expand_path("../bundle", __FILE__) - -if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ - load(bundle_binstub) - else - abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. -Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") - end -end - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("rubocop", "rubocop") diff --git a/ruby/gems/rake-13.0.1/bin/setup b/ruby/gems/rake-13.0.1/bin/setup deleted file mode 100755 index cf4ad25e1..000000000 --- a/ruby/gems/rake-13.0.1/bin/setup +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -IFS=$'\n\t' -set -vx - -bundle install diff --git a/ruby/gems/rake-13.0.1/doc/command_line_usage.rdoc b/ruby/gems/rake-13.0.1/doc/command_line_usage.rdoc deleted file mode 100644 index 105d6c8e9..000000000 --- a/ruby/gems/rake-13.0.1/doc/command_line_usage.rdoc +++ /dev/null @@ -1,158 +0,0 @@ -= Rake Command Line Usage - -Rake is invoked from the command line using: - - % rake [options ...] [VAR=VALUE ...] [targets ...] - -Options are: - -[name=value] - Set the environment variable name to value - during the execution of the rake command. You can access - the value by using ENV['name']. - -[--all (-A)] - Used in combination with the -T and -D options, will force - those options to show all the tasks, even the ones without comments. - -[--backtrace{=_output_} (-n)] - Enable a full backtrace (i.e. like --trace, but without the task - tracing details). The _output_ parameter is optional, but if - specified it controls where the backtrace output is sent. If - _output_ is stdout, then backtrace output is directed to - standard output. If _output_ is stderr, or if it is - missing, then the backtrace output is sent to standard error. - -[--comments] - Used in combination with the -W options to force the output to - contain commented options only. This is the reverse of - --all. - -[--describe _pattern_ (-D)] - Describe the tasks (matching optional PATTERN), then exit. - -[--dry-run (-n)] - Do a dry run. Print the tasks invoked and executed, but do not - actually execute any of the actions. - -[--execute _code_ (-e)] - Execute some Ruby code and exit. - -[--execute-print _code_ (-p)] - Execute some Ruby code, print the result, and exit. - -[--execute-continue _code_ (-E)] - Execute some Ruby code, then continue with normal task processing. - -[--help (-H)] - Display some help text and exit. - -[--jobs _number_ (-j)] - - Specifies the maximum number of concurrent threads allowed. Rake - will allocate threads as needed up to this maximum number. - - If omitted, Rake will attempt to estimate the number of CPUs on - the system and add 4 to that number. - - The concurrent threads are used to execute the multitask - prerequisites. Also see the -m option which turns all - tasks into multitasks. - - Sample values: - (no -j) : Allow up to (# of CPUs + 4) number of threads - --jobs : Allow unlimited number of threads - --jobs=1 : Allow only one thread (the main thread) - --jobs=16 : Allow up to 16 concurrent threads - -[--job-stats _level_] - - Display job statistics at the completion of the run. By default, - this will display the requested number of active threads (from the - -j options) and the maximum number of threads in play at any given - time. - - If the optional _level_ is history, then a complete trace - of task history will be displayed on standard output. - -[--libdir _directory_ (-I)] - Add _directory_ to the list of directories searched for require. - -[--multitask (-m)] - Treat all tasks as multitasks. ('make/drake' semantics) - -[--nosearch (-N)] - Do not search for a Rakefile in parent directories. - -[--prereqs (-P)] - Display a list of all tasks and their immediate prerequisites. - -[--quiet (-q)] - Do not echo commands from FileUtils. - -[--rakefile _filename_ (-f)] - Use _filename_ as the name of the rakefile. The default rakefile - names are +rakefile+ and +Rakefile+ (with +rakefile+ taking - precedence). If the rakefile is not found in the current - directory, +rake+ will search parent directories for a match. The - directory where the Rakefile is found will become the current - directory for the actions executed in the Rakefile. - -[--rakelibdir _rakelibdir_ (-R)] - Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib') - -[--require _name_ (-r)] - Require _name_ before executing the Rakefile. - -[--rules] - Trace the rules resolution. - -[--silent (-s)] - Like --quiet, but also suppresses the 'in directory' announcement. - -[--suppress-backtrace _pattern_ ] - Line matching the regular expression _pattern_ will be removed - from the backtrace output. Note that the --backtrace option is the - full backtrace without these lines suppressed. - -[--system (-g)] - Use the system wide (global) rakefiles. The project Rakefile is - ignored. By default, the system wide rakefiles are used only if no - project Rakefile is found. On Unix-like system, the system wide - rake files are located in $HOME/.rake. On a windows system they - are stored in $APPDATA/Rake. - -[--no-system (-G)] - Use the project level Rakefile, ignoring the system-wide (global) - rakefiles. - -[--tasks pattern (-T)] - Display a list of the major tasks and their comments. Comments - are defined using the "desc" command. If a pattern is given, then - only tasks matching the pattern are displayed. - -[--trace{=_output_} (-t)] - Turn on invoke/execute tracing. Also enable full backtrace on - errors. The _output_ parameter is optional, but if specified it - controls where the trace output is sent. If _output_ is - stdout, then trace output is directed to standard output. - If _output_ is stderr, or if it is missing, then trace - output is sent to standard error. - -[--verbose (-v)] - Echo the Sys commands to standard output. - -[--version (-V)] - Display the program version and exit. - -[--where pattern (-W)] - Display tasks that match pattern and the file and line - number where the task is defined. By default this option will - display all tasks, not just the tasks that have descriptions. - -[--no-deprecation-warnings (-X)] - Do not display the deprecation warnings. - -In addition, any command line option of the form -VAR=VALUE will be added to the environment hash -ENV and may be tested in the Rakefile. diff --git a/ruby/gems/rake-13.0.1/doc/example/Rakefile1 b/ruby/gems/rake-13.0.1/doc/example/Rakefile1 deleted file mode 100644 index 39f8bcceb..000000000 --- a/ruby/gems/rake-13.0.1/doc/example/Rakefile1 +++ /dev/null @@ -1,38 +0,0 @@ -# Example Rakefile -*- ruby -*- - -task :default => [:main] - -file "a.o" => ["a.c"] do |t| - src = t.name.sub(/\.o$/, '.c') - sh "gcc #{src} -c -o #{t.name}" -end - -file "b.o" => ["b.c"] do |t| - src = t.name.sub(/\.o$/, '.c') - sh "gcc #{src} -c -o #{t.name}" -end - -file "main.o" => ["main.c"] do |t| - src = t.name.sub(/\.o$/, '.c') - sh "gcc #{src} -c -o #{t.name}" -end - -OBJFILES = ["a.o", "b.o", "main.o"] -task :obj => OBJFILES - -file "main" => OBJFILES do |t| - sh "gcc -o #{t.name} main.o a.o b.o" -end - -task :clean do - rm_f FileList['*.o'] - Dir['*~'].each { |fn| rm_f fn } -end - -task :clobber => [:clean] do - rm_f "main" -end - -task :run => ["main"] do - sh "./main" -end diff --git a/ruby/gems/rake-13.0.1/doc/example/Rakefile2 b/ruby/gems/rake-13.0.1/doc/example/Rakefile2 deleted file mode 100644 index 35310eceb..000000000 --- a/ruby/gems/rake-13.0.1/doc/example/Rakefile2 +++ /dev/null @@ -1,35 +0,0 @@ -# Example Rakefile -*- ruby -*- -# Using the power of Ruby - -task :default => [:main] - -def ext(fn, newext) - fn.sub(/\.[^.]+$/, newext) -end - -SRCFILES = Dir['*.c'] -OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") } - -OBJFILES.each do |objfile| - srcfile = ext(objfile, ".c") - file objfile => [srcfile] do |t| - sh "gcc #{srcfile} -c -o #{t.name}" - end -end - -file "main" => OBJFILES do |t| - sh "gcc -o #{t.name} main.o a.o b.o" -end - -task :clean do - rm_f FileList['*.o'] - Dir['*~'].each { |fn| rm_f fn } -end - -task :clobber => [:clean] do - rm_f "main" -end - -task :run => ["main"] do - sh "./main" -end diff --git a/ruby/gems/rake-13.0.1/doc/example/a.c b/ruby/gems/rake-13.0.1/doc/example/a.c deleted file mode 100644 index 620e6f800..000000000 --- a/ruby/gems/rake-13.0.1/doc/example/a.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -void a() -{ - printf ("In function a\n"); -} diff --git a/ruby/gems/rake-13.0.1/doc/example/b.c b/ruby/gems/rake-13.0.1/doc/example/b.c deleted file mode 100644 index 9b24aa127..000000000 --- a/ruby/gems/rake-13.0.1/doc/example/b.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -void b() -{ - printf ("In function b\n"); -} diff --git a/ruby/gems/rake-13.0.1/doc/example/main.c b/ruby/gems/rake-13.0.1/doc/example/main.c deleted file mode 100644 index a04558a25..000000000 --- a/ruby/gems/rake-13.0.1/doc/example/main.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -extern void a(); -extern void b(); - -int main () -{ - a(); - b(); - return 0; -} diff --git a/ruby/gems/rake-13.0.1/doc/glossary.rdoc b/ruby/gems/rake-13.0.1/doc/glossary.rdoc deleted file mode 100644 index 9d592b02c..000000000 --- a/ruby/gems/rake-13.0.1/doc/glossary.rdoc +++ /dev/null @@ -1,42 +0,0 @@ -= Glossary - -action :: - Code to be executed in order to perform a task. Actions in a Rakefile are - specified in a code block. (Usually delimited by +do+/+end+ pairs.) - -execute :: - When a task is executed, all of its actions are performed in the order they - were defined. Note that, unlike invoke, execute always - executes the actions (without invoking or executing the prerequisites). - -file task (Rake::FileTask) :: - A file task is a task whose purpose is to create a file (which has the same - name as the task). When invoked, a file task will only execute if one or - more of the following conditions are true. - - 1. The associated file does not exist. - 2. A prerequisite has a later time stamp than the existing file. - - Because normal Tasks always have the current time as timestamp, a FileTask - that has a normal Task prerequisite will always execute. - -invoke :: - When a task is invoked, first we check to see if it has been invoked before. - If it has been, then nothing else is done. If this is the first time it has - been invoked, then we invoke each of its prerequisites. Finally, we check - to see if we need to execute the actions of this task by calling - Rake::Task#needed?. If the task is needed, we execute its actions. - - NOTE: Prerequisites are still invoked even if the task is not needed. - -prerequisites :: - Every task has a (possibly empty) set of prerequisites. A prerequisite P to - Task T is itself a task that must be invoked before Task T. - -rule :: - A rule is a recipe for synthesizing a task when no task is explicitly - defined. Rules generally synthesize file tasks. - -task (Rake::Task) :: - The basic unit of work in a Rakefile. A task has a name, a set of - prerequisites, and a list of actions to be performed. diff --git a/ruby/gems/rake-13.0.1/doc/jamis.rb b/ruby/gems/rake-13.0.1/doc/jamis.rb deleted file mode 100644 index 531aa7573..000000000 --- a/ruby/gems/rake-13.0.1/doc/jamis.rb +++ /dev/null @@ -1,592 +0,0 @@ -# frozen_string_literal: true -module RDoc -module Page - -FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif" - -STYLE = < pre { - padding: 0.5em; - border: 1px dotted black; - background: #FFE; -} - -CSS - -XHTML_PREAMBLE = %{ - -} - -HEADER = XHTML_PREAMBLE + < - - %title% - - - - - - - -ENDHEADER - -FILE_PAGE = < - - - - -
File
%short_name%
- - - - - - - - - -
Path:%full_path% -IF:cvsurl -  (CVS) -ENDIF:cvsurl -
Modified:%dtm_modified%
-
- -
-HTML - -################################################################### - -CLASS_PAGE = < - %classmod%
%full_name% - - - - - - -IF:parent - - - - -ENDIF:parent -
In: -START:infiles -HREF:full_path_url:full_path: -IF:cvsurl - (CVS) -ENDIF:cvsurl -END:infiles -
Parent: -IF:par_url - -ENDIF:par_url -%parent% -IF:par_url - -ENDIF:par_url -
- - - -HTML - -################################################################### - -METHOD_LIST = < -IF:diagram -
- %diagram% -
-ENDIF:diagram - -IF:description -
%description%
-ENDIF:description - -IF:requires -
Required Files
-
    -START:requires -
  • HREF:aref:name:
  • -END:requires -
-ENDIF:requires - -IF:toc -
Contents
- -ENDIF:toc - -IF:methods -
Methods
-
    -START:methods -
  • HREF:aref:name:
  • -END:methods -
-ENDIF:methods - -IF:includes -
Included Modules
-
    -START:includes -
  • HREF:aref:name:
  • -END:includes -
-ENDIF:includes - -START:sections -IF:sectitle - -IF:seccomment -
-%seccomment% -
-ENDIF:seccomment -ENDIF:sectitle - -IF:classlist -
Classes and Modules
- %classlist% -ENDIF:classlist - -IF:constants -
Constants
- -START:constants - - - - - -IF:desc - - - - -ENDIF:desc -END:constants -
%name%=%value%
 %desc%
-ENDIF:constants - -IF:attributes -
Attributes
- -START:attributes - - - - - -END:attributes -
-IF:rw -[%rw%] -ENDIF:rw - %name%%a_desc%
-ENDIF:attributes - -IF:method_list -START:method_list -IF:methods -
%type% %category% methods
-START:methods -
-
-IF:callseq - %callseq% -ENDIF:callseq -IFNOT:callseq - %name%%params% -ENDIF:callseq -IF:codeurl -[ source ] -ENDIF:codeurl -
-IF:m_desc -
- %m_desc% -
-ENDIF:m_desc -IF:aka -
- This method is also aliased as -START:aka - %name% -END:aka -
-ENDIF:aka -IF:sourcecode -
- -
-
-%sourcecode%
-
-
-
-ENDIF:sourcecode -
-END:methods -ENDIF:methods -END:method_list -ENDIF:method_list -END:sections - -HTML - -FOOTER = < - -ENDFOOTER - -BODY = HEADER + < - -
- #{METHOD_LIST} -
- - #{FOOTER} -ENDBODY - -########################## Source code ########################## - -SRC_PAGE = XHTML_PREAMBLE + < -%title% - - - - -
%code%
- - -HTML - -########################## Index ################################ - -FR_INDEX_BODY = < - - - - - - - -
-START:entries -%name%
-END:entries -
- -HTML - -CLASS_INDEX = FILE_INDEX -METHOD_INDEX = FILE_INDEX - -INDEX = XHTML_PREAMBLE + < - - %title% - - - - - - - - - -IF:inline_source - -ENDIF:inline_source -IFNOT:inline_source - - - - -ENDIF:inline_source - - <body bgcolor="white"> - Click <a href="html/index.html">here</a> for a non-frames - version of this page. - </body> - - - - -HTML - -end -end - - diff --git a/ruby/gems/rake-13.0.1/doc/proto_rake.rdoc b/ruby/gems/rake-13.0.1/doc/proto_rake.rdoc deleted file mode 100644 index a9e33d11d..000000000 --- a/ruby/gems/rake-13.0.1/doc/proto_rake.rdoc +++ /dev/null @@ -1,127 +0,0 @@ -= Original Prototype Rake - -This is the original 100 line prototype rake program. - ---- - #!/usr/bin/env ruby - - require 'ftools' - - class Task - TASKS = Hash.new - - attr_reader :prerequisites - - def initialize(task_name) - @name = task_name - @prerequisites = [] - @actions = [] - end - - def enhance(deps=nil, &block) - @prerequisites |= deps if deps - @actions << block if block_given? - self - end - - def name - @name.to_s - end - - def invoke - @prerequisites.each { |n| Task[n].invoke } - execute if needed? - end - - def execute - return if @triggered - @triggered = true - @actions.collect { |act| result = act.call(self) }.last - end - - def needed? - true - end - - def timestamp - Time.now - end - - class << self - def [](task_name) - TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}" - end - - def define_task(args, &block) - case args - when Hash - fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1 - fail "No Task Name Given" if args.size < 1 - task_name = args.keys[0] - deps = args[task_name] - else - task_name = args - deps = [] - end - deps = deps.collect {|d| intern(d) } - get(task_name).enhance(deps, &block) - end - - def get(task_name) - name = intern(task_name) - TASKS[name] ||= self.new(name) - end - - def intern(task_name) - (Symbol === task_name) ? task_name : task_name.intern - end - end - end - - class FileTask < Task - def needed? - return true unless File.exist?(name) - latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max - return false if latest_prereq.nil? - timestamp < latest_prereq - end - - def timestamp - File.new(name.to_s).mtime - end - end - - def task(args, &block) - Task.define_task(args, &block) - end - - def file(args, &block) - FileTask.define_task(args, &block) - end - - def sys(cmd) - puts cmd - system(cmd) or fail "Command Failed: [#{cmd}]" - end - - def rake - begin - here = Dir.pwd - while ! File.exist?("Rakefile") - Dir.chdir("..") - fail "No Rakefile found" if Dir.pwd == here - here = Dir.pwd - end - puts "(in #{Dir.pwd})" - load "./Rakefile" - ARGV.push("default") if ARGV.size == 0 - ARGV.each { |task_name| Task[task_name].invoke } - rescue Exception => ex - puts "rake aborted ... #{ex.message}" - puts ex.backtrace.find {|str| str =~ /Rakefile/ } || "" - end - end - - if __FILE__ == $0 then - rake - end diff --git a/ruby/gems/rake-13.0.1/doc/rake.1 b/ruby/gems/rake-13.0.1/doc/rake.1 deleted file mode 100644 index c6bfa25c0..000000000 --- a/ruby/gems/rake-13.0.1/doc/rake.1 +++ /dev/null @@ -1,156 +0,0 @@ -.Dd June 12, 2016 -.Dt RAKE 1 -.Os rake 11.2.2 -.Sh NAME -.Nm rake -.Nd make-like build utility for Ruby -.Sh SYNOPSIS -.Nm -.Op Fl f Ar rakefile -.Op Ar options -.Ar targets ... -.Sh DESCRIPTION -.Nm -is a -.Xr make 1 Ns -like -build utility for Ruby. -Tasks and dependencies are specified in standard Ruby syntax. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl m , Fl -multitask -Treat all tasks as multitasks. -.It Fl B , Fl -build-all -Build all prerequisites, including those which are up\-to\-date. -.It Fl j , Fl -jobs Ar num_jobs -Specifies the maximum number of tasks to execute in parallel (default is number of CPU cores + 4). -.El -.Ss Modules -.Bl -tag -width Ds -.It Fl I , Fl -libdir Ar libdir -Include -.Ar libdir -in the search path for required modules. -.It Fl r , Fl -require Ar module -Require -.Ar module -before executing -.Pa rakefile . -.El -.Ss Rakefile location -.Bl -tag -width Ds -.It Fl f , Fl -rakefile Ar filename -Use -.Ar filename -as the rakefile to search for. -.It Fl N , Fl -no-search , Fl -nosearch -Do not search parent directories for the Rakefile. -.It Fl G , Fl -no-system , Fl -nosystem -Use standard project Rakefile search paths, ignore system wide rakefiles. -.It Fl R , Fl -rakelib Ar rakelibdir , Fl -rakelibdir Ar rakelibdir -Auto-import any .rake files in -.Ar rakelibdir -(default is -.Sq rakelib ) -.It Fl g , Fl -system -Use system-wide (global) rakefiles (usually -.Pa ~/.rake/*.rake ) . -.El -.Ss Debugging -.Bl -tag -width Ds -.It Fl -backtrace Ns = Ns Ar out -Enable full backtrace. -.Ar out -can be -.Dv stderr -(default) or -.Dv stdout . -.It Fl t , Fl -trace Ns = Ns Ar out -Turn on invoke/execute tracing, enable full backtrace. -.Ar out -can be -.Dv stderr -(default) or -.Dv stdout . -.It Fl -suppress-backtrace Ar pattern -Suppress backtrace lines matching regexp -.Ar pattern . -Ignored if -.Fl -trace -is on. -.It Fl -rules -Trace the rules resolution. -.It Fl n , Fl -dry-run -Do a dry run without executing actions. -.It Fl T , Fl -tasks Op Ar pattern -Display the tasks (matching optional -.Ar pattern ) -with descriptions, then exit. -.It Fl D , Fl -describe Op Ar pattern -Describe the tasks (matching optional -.Ar pattern ) , -then exit. -.It Fl W , Fl -where Op Ar pattern -Describe the tasks (matching optional -.Ar pattern ) , -then exit. -.It Fl P , Fl -prereqs -Display the tasks and dependencies, then exit. -.It Fl e , Fl -execute Ar code -Execute some Ruby code and exit. -.It Fl p , Fl -execute-print Ar code -Execute some Ruby code, print the result, then exit. -.It Fl E , Fl -execute-continue Ar code -Execute some Ruby code, then continue with normal task processing. -.El -.Ss Information -.Bl -tag -width Ds -.It Fl v , Fl -verbose -Log message to standard output. -.It Fl q , Fl -quiet -Do not log messages to standard output. -.It Fl s , Fl -silent -Like -.Fl -quiet , -but also suppresses the -.Sq in directory -announcement. -.It Fl X , Fl -no-deprecation-warnings -Disable the deprecation warnings. -.It Fl -comments -Show commented tasks only -.It Fl A , Fl -all -Show all tasks, even uncommented ones (in combination with -.Fl T -or -.Fl D ) -.It Fl -job-stats Op Ar level -Display job statistics. -If -.Ar level -is -.Sq history , -displays a complete job list. -.It Fl V , Fl -version -Display the program version. -.It Fl h , Fl H , Fl -help -Display a help message. -.El -.Sh SEE ALSO -The complete documentation for -.Nm rake -has been installed at -.Pa /usr/share/doc/rake-doc/html/index.html . -It is also available online at -.Lk https://ruby.github.io/rake . -.Sh AUTHORS -.An -nosplit -.Nm -was written by -.An Jim Weirich Aq Mt jim@weirichhouse.org . -.Pp -This manual was created by -.An Caitlin Matos Aq Mt caitlin.matos@zoho.com -for the Debian project (but may be used by others). -It was inspired by the manual by -.An Jani Monoses Aq Mt jani@iv.ro -for the Ubuntu project. diff --git a/ruby/gems/rake-13.0.1/doc/rakefile.rdoc b/ruby/gems/rake-13.0.1/doc/rakefile.rdoc deleted file mode 100644 index 4014306a1..000000000 --- a/ruby/gems/rake-13.0.1/doc/rakefile.rdoc +++ /dev/null @@ -1,622 +0,0 @@ -= Rakefile Format - -First of all, there is no special format for a Rakefile. A Rakefile -contains executable Ruby code. Anything legal in a ruby script is -allowed in a Rakefile. - -Now that we understand there is no special syntax in a Rakefile, there -are some conventions that are used in a Rakefile that are a little -unusual in a typical Ruby program. Since a Rakefile is tailored to -specifying tasks and actions, the idioms used in a Rakefile are -designed to support that. - -So, what goes into a Rakefile? - -== Tasks - -Tasks are the main unit of work in a Rakefile. Tasks have a name -(usually given as a symbol or a string), a list of prerequisites (more -symbols or strings) and a list of actions (given as a block). - -=== Simple Tasks - -A task is declared by using the +task+ method. +task+ takes a single -parameter that is the name of the task. - - task :name - -=== Tasks with Prerequisites - -Any prerequisites are given as a list (enclosed in square brackets) -following the name and an arrow (=>). - - task name: [:prereq1, :prereq2] - -*NOTE:* Although this syntax looks a little funky, it is legal -Ruby. We are constructing a hash where the key is :name and the value -for that key is the list of prerequisites. It is equivalent to the -following ... - - hash = Hash.new - hash[:name] = [:prereq1, :prereq2] - task(hash) - -You can also use strings for task names and prerequisites, rake doesn't care. -This is the same task definition: - - task 'name' => %w[prereq1 prereq2] - -As is this: - - task name: %w[prereq1 prereq2] - -We'll prefer this style for regular tasks with prerequisites throughout the -rest of the document. Using an array of strings for the prerequisites means -you will need to make fewer changes if you need to move tasks into namespaces -or perform other refactorings. - -=== Tasks with Actions - -Actions are defined by passing a block to the +task+ method. Any Ruby -code can be placed in the block. The block may reference the task -object via the block parameter. - - task name: [:prereq1, :prereq2] do |t| - # actions (may reference t) - end - -=== Multiple Definitions - -A task may be specified more than once. Each specification adds its -prerequisites and actions to the existing definition. This allows one -part of a rakefile to specify the actions and a different rakefile -(perhaps separately generated) to specify the dependencies. - -For example, the following is equivalent to the single task -specification given above. - - task :name - task name: :prereq1 - task name: %w[prereq2] - task :name do |t| - # actions - end - -== File Tasks - -Some tasks are designed to create a file from one or more other files. -Tasks that generate these files may be skipped if the file already -exists. File tasks are used to specify file creation tasks. - -File tasks are declared using the +file+ method (instead of the +task+ -method). In addition, file tasks are usually named with a string -rather than a symbol. - -The following file task creates a executable program (named +prog+) -given two object files named +a.o+ and +b.o+. The tasks -for creating +a.o+ and +b.o+ are not shown. - - file "prog" => ["a.o", "b.o"] do |t| - sh "cc -o #{t.name} #{t.prerequisites.join(' ')}" - end - -== Directory Tasks - -It is common to need to create directories upon demand. The -+directory+ convenience method is a short-hand for creating a FileTask -that creates the directory. For example, the following declaration -... - - directory "testdata/examples/doc" - -is equivalent to ... - - file "testdata" do |t| mkdir t.name end - file "testdata/examples" => ["testdata"] do |t| mkdir t.name end - file "testdata/examples/doc" => ["testdata/examples"] do |t| mkdir t.name end - -The +directory+ method does not accept prerequisites or actions, but -both prerequisites and actions can be added later. For example ... - - directory "testdata" - file "testdata" => ["otherdata"] - file "testdata" do - cp Dir["standard_data/*.data"], "testdata" - end - -== Tasks with Parallel Prerequisites - -Rake allows parallel execution of prerequisites using the following syntax: - - multitask copy_files: %w[copy_src copy_doc copy_bin] do - puts "All Copies Complete" - end - -In this example, +copy_files+ is a normal rake task. Its actions are -executed whenever all of its prerequisites are done. The big -difference is that the prerequisites (+copy_src+, +copy_bin+ and -+copy_doc+) are executed in parallel. Each of the prerequisites are -run in their own Ruby thread, possibly allowing faster overall runtime. - -=== Secondary Prerequisites - -If any of the primary prerequisites of a multitask have common secondary -prerequisites, all of the primary/parallel prerequisites will wait -until the common prerequisites have been run. - -For example, if the copy_xxx tasks have the -following prerequisites: - - task copy_src: :prep_for_copy - task copy_bin: :prep_for_copy - task copy_doc: :prep_for_copy - -Then the +prep_for_copy+ task is run before starting all the copies in -parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+, -and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is -run only once, even though it is referenced in multiple threads. - -=== Thread Safety - -The Rake internal data structures are thread-safe with respect -to the multitask parallel execution, so there is no need for the user -to do extra synchronization for Rake's benefit. However, if there are -user data structures shared between the parallel prerequisites, the -user must do whatever is necessary to prevent race conditions. - -== Tasks with Arguments - -Prior to version 0.8.0, rake was only able to handle command line -arguments of the form NAME=VALUE that were passed into Rake via the -ENV hash. Many folks had asked for some kind of simple command line -arguments, perhaps using "--" to separate regular task names from -argument values on the command line. The problem is that there was no -easy way to associate positional arguments on the command line with -different tasks. Suppose both tasks :a and :b expect a command line -argument: does the first value go with :a? What if :b is run first? -Should it then get the first command line argument. - -Rake 0.8.0 solves this problem by explicitly passing values directly -to the tasks that need them. For example, if I had a release task -that required a version number, I could say: - - rake release[0.8.2] - -And the string "0.8.2" will be passed to the :release task. Multiple -arguments can be passed by separating them with a comma, for example: - - rake name[john,doe] - -Just a few words of caution. The rake task name and its arguments -need to be a single command line argument to rake. This generally -means no spaces. If spaces are needed, then the entire name + -argument string should be quoted. Something like this: - - rake "name[billy bob, smith]" - -(Quoting rules vary between operating systems and shells, so make sure -you consult the proper docs for your OS/shell). - -=== Tasks that Expect Parameters - -Parameters are only given to tasks that are setup to expect them. In -order to handle named parameters, the task declaration syntax for -tasks has been extended slightly. - -For example, a task that needs a first name and last name might be -declared as: - - task :name, [:first_name, :last_name] - -The first argument is still the name of the task (:name in this case). -The next two arguments are the names of the parameters expected by -:name in an array (:first_name and :last_name in the example). - -To access the values of the parameters, the block defining the task -behaviour can now accept a second parameter: - - task :name, [:first_name, :last_name] do |t, args| - puts "First name is #{args.first_name}" - puts "Last name is #{args.last_name}" - end - -The first argument of the block "t" is always bound to the current -task object. The second argument "args" is an open-struct like object -that allows access to the task arguments. Extra command line -arguments to a task are ignored. - -If you wish to specify default values for the arguments, you can use -the with_defaults method in the task body. Here is the above example -where we specify default values for the first and last names: - - task :name, [:first_name, :last_name] do |t, args| - args.with_defaults(:first_name => "John", :last_name => "Dough") - puts "First name is #{args.first_name}" - puts "Last name is #{args.last_name}" - end - -=== Tasks that Expect Parameters and Have Prerequisites - -Tasks that use parameters have a slightly different format for -prerequisites. Use the arrow notation to indicate the prerequisites -for tasks with arguments. For example: - - task :name, [:first_name, :last_name] => [:pre_name] do |t, args| - args.with_defaults(:first_name => "John", :last_name => "Dough") - puts "First name is #{args.first_name}" - puts "Last name is #{args.last_name}" - end - -=== Tasks that take Variable-length Parameters - -Tasks that need to handle a list of values as a parameter can use the -extras method of the args variable. This allows for tasks that can -loop over a variable number of values, and its compatible with named -parameters as well: - - task :email, [:message] do |t, args| - mail = Mail.new(args.message) - recipients = args.extras - recipients.each do |target| - mail.send_to(target) - end - end - -There is also the convenience method to_a that returns all parameters -in the sequential order they were given, including those associated -with named parameters. - -=== Deprecated Task Parameters Format - -There is an older format for declaring task parameters that omitted -the task argument array and used the :needs keyword to introduce the -dependencies. That format is still supported for compatibility, but -is not recommended for use. The older format may be dropped in future -versions of rake. - -== Accessing Task Programmatically - -Sometimes it is useful to manipulate tasks programmatically in a -Rakefile. To find a task object use Rake::Task.[]. - -=== Programmatic Task Example - -For example, the following Rakefile defines two tasks. The :doit task -simply prints a simple "DONE" message. The :dont class will lookup -the doit class and remove (clear) all of its prerequisites and -actions. - - task :doit do - puts "DONE" - end - - task :dont do - Rake::Task[:doit].clear - end - -Running this example: - - $ rake doit - (in /Users/jim/working/git/rake/x) - DONE - $ rake dont doit - (in /Users/jim/working/git/rake/x) - $ - -The ability to programmatically manipulate tasks gives rake very -powerful meta-programming capabilities w.r.t. task execution, but -should be used with caution. - -== Rules - -When a file is named as a prerequisite, but does not have a file task -defined for it, Rake will attempt to synthesize a task by looking at a -list of rules supplied in the Rakefile. - -Suppose we were trying to invoke task "mycode.o", but no task is -defined for it. But the rakefile has a rule that look like this ... - - rule '.o' => ['.c'] do |t| - sh "cc #{t.source} -c -o #{t.name}" - end - -This rule will synthesize any task that ends in ".o". It has a -prerequisite a source file with an extension of ".c" must exist. If -Rake is able to find a file named "mycode.c", it will automatically -create a task that builds "mycode.o" from "mycode.c". - -If the file "mycode.c" does not exist, rake will attempt -to recursively synthesize a rule for it. - -When a task is synthesized from a rule, the +source+ attribute of the -task is set to the matching source file. This allows us to write -rules with actions that reference the source file. - -=== Advanced Rules - -Any regular expression may be used as the rule pattern. Additionally, -a proc may be used to calculate the name of the source file. This -allows for complex patterns and sources. - -The following rule is equivalent to the example above. - - rule( /\.o$/ => [ - proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') } - ]) do |t| - sh "cc #{t.source} -c -o #{t.name}" - end - -*NOTE:* Because of a _quirk_ in Ruby syntax, parenthesis are -required on *rule* when the first argument is a regular expression. - -The following rule might be used for Java files ... - - rule '.class' => [ - proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') } - ] do |t| - java_compile(t.source, t.name) - end - -*NOTE:* +java_compile+ is a hypothetical method that invokes the -java compiler. - -== Importing Dependencies - -Any ruby file (including other rakefiles) can be included with a -standard Ruby +require+ command. The rules and declarations in the -required file are just added to the definitions already accumulated. - -Because the files are loaded _before_ the rake targets are evaluated, -the loaded files must be "ready to go" when the rake command is -invoked. This makes generated dependency files difficult to use. By -the time rake gets around to updating the dependencies file, it is too -late to load it. - -The +import+ command addresses this by specifying a file to be loaded -_after_ the main rakefile is loaded, but _before_ any targets on the -command line are invoked. In addition, if the file name matches an -explicit task, that task is invoked before loading the file. This -allows dependency files to be generated and used in a single rake -command invocation. - -Example: - - require 'rake/loaders/makefile' - - file ".depends.mf" => [SRC_LIST] do |t| - sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" - end - - import ".depends.mf" - -If ".depends" does not exist, or is out of date w.r.t. the source -files, a new ".depends" file is generated using +makedepend+ before -loading. - -== Comments - -Standard Ruby comments (beginning with "#") can be used anywhere it is -legal in Ruby source code, including comments for tasks and rules. -However, if you wish a task to be described using the "-T" switch, -then you need to use the +desc+ command to describe the task. - -Example: - - desc "Create a distribution package" - task package: %w[ ... ] do ... end - -The "-T" switch (or "--tasks" if you like to spell things out) will -display a list of tasks that have a description. If you use +desc+ to -describe your major tasks, you have a semi-automatic way of generating -a summary of your Rake file. - - $ rake -T - (in /home/.../rake) - rake clean # Remove any temporary products. - rake clobber # Remove any generated file. - rake clobber_rdoc # Remove rdoc products - rake contrib_test # Run tests for contrib_test - rake default # Default Task - rake install # Install the application - rake lines # Count lines in the main rake file - rake rdoc # Build the rdoc HTML Files - rake rerdoc # Force a rebuild of the RDOC files - rake test # Run tests - rake testall # Run all test targets - -Only tasks with descriptions will be displayed with the "-T" switch. -Use "-P" (or "--prereqs") to get a list of all tasks and their -prerequisites. - -== Namespaces - -As projects grow (and along with it, the number of tasks), it is -common for task names to begin to clash. For example, if you might -have a main program and a set of sample programs built by a single -Rakefile. By placing the tasks related to the main program in one -namespace, and the tasks for building the sample programs in a -different namespace, the task names will not interfere with each other. - -For example: - - namespace "main" do - task :build do - # Build the main program - end - end - - namespace "samples" do - task :build do - # Build the sample programs - end - end - - task build: %w[main:build samples:build] - -Referencing a task in a separate namespace can be achieved by -prefixing the task name with the namespace and a colon -(e.g. "main:build" refers to the :build task in the +main+ namespace). -Nested namespaces are supported. - -Note that the name given in the +task+ command is always the unadorned -task name without any namespace prefixes. The +task+ command always -defines a task in the current namespace. - -=== FileTasks - -File task names are not scoped by the namespace command. Since the -name of a file task is the name of an actual file in the file system, -it makes little sense to include file task names in name space. -Directory tasks (created by the +directory+ command) are a type of -file task and are also not affected by namespaces. - -=== Name Resolution - -When looking up a task name, rake will start with the current -namespace and attempt to find the name there. If it fails to find a -name in the current namespace, it will search the parent namespaces -until a match is found (or an error occurs if there is no match). - -The "rake" namespace is a special implicit namespace that refers to -the toplevel names. - -If a task name begins with a "^" character, the name resolution will -start in the parent namespace. Multiple "^" characters are allowed. - -Here is an example file with multiple :run tasks and how various names -resolve in different locations. - - task :run - - namespace "one" do - task :run - - namespace "two" do - task :run - - # :run => "one:two:run" - # "two:run" => "one:two:run" - # "one:two:run" => "one:two:run" - # "one:run" => "one:run" - # "^run" => "one:run" - # "^^run" => "rake:run" (the top level task) - # "rake:run" => "rake:run" (the top level task) - end - - # :run => "one:run" - # "two:run" => "one:two:run" - # "^run" => "rake:run" - end - - # :run => "rake:run" - # "one:run" => "one:run" - # "one:two:run" => "one:two:run" - -== FileLists - -FileLists are the way Rake manages lists of files. You can treat a -FileList as an array of strings for the most part, but FileLists -support some additional operations. - -=== Creating a FileList - -Creating a file list is easy. Just give it the list of file names: - - fl = FileList['file1.rb', file2.rb'] - -Or give it a glob pattern: - - fl = FileList['*.rb'] - -== Odds and Ends - -=== do/end versus { } - -Blocks may be specified with either a +do+/+end+ pair, or with curly -braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the -actions for tasks and rules. Because the rakefile idiom tends to -leave off parentheses on the task/file/rule methods, unusual -ambiguities can arise when using curly braces. - -For example, suppose that the method +object_files+ returns a list of -object files in a project. Now we use +object_files+ as the -prerequisites in a rule specified with actions in curly braces. - - # DON'T DO THIS! - file "prog" => object_files { - # Actions are expected here (but it doesn't work)! - } - -Because curly braces have a higher precedence than +do+/+end+, the -block is associated with the +object_files+ method rather than the -+file+ method. - -This is the proper way to specify the task ... - - # THIS IS FINE - file "prog" => object_files do - # Actions go here - end - -== Rakefile Path - -When issuing the +rake+ command in a terminal, Rake will look -for a Rakefile in the current directory. If a Rakefile is not found, -it will search parent directories until one is found. - -For example, if a Rakefile resides in the +project/+ directory, -moving deeper into the project's directory tree will not have an adverse -effect on rake tasks: - - $ pwd - /home/user/project - - $ cd lib/foo/bar - $ pwd - /home/user/project/lib/foo/bar - - $ rake run_pwd - /home/user/project - -As far as rake is concerned, all tasks are run from the directory in -which the Rakefile resides. - -=== Multiple Rake Files - -Not all tasks need to be included in a single Rakefile. Additional -rake files (with the file extension "+.rake+") may be placed in -+rakelib+ directory located at the top level of a project (i.e. -the same directory that contains the main +Rakefile+). - -Also, rails projects may include additional rake files in the -+lib/tasks+ directory. - -=== Clean and Clobber Tasks - -Through require 'rake/clean' Rake provides +clean+ and +clobber+ -tasks: - -+clean+ :: - Clean up the project by deleting scratch files and backup files. Add files - to the +CLEAN+ FileList to have the +clean+ target handle them. - -+clobber+ :: - Clobber all generated and non-source files in a project. The task depends - on +clean+, so all the +CLEAN+ files will be deleted as well as files in the - +CLOBBER+ FileList. The intent of this task is to return a project to its - pristine, just unpacked state. - -You can add file names or glob patterns to both the +CLEAN+ and +CLOBBER+ -lists. - -=== Phony Task - -The phony task can be used as a dependency to allow file-based tasks to use -non-file-based-tasks as prerequisites without forcing them to rebuild. You -can require 'rake/phony' to add the +phony+ task. - ----- - -== See - -* README.rdoc -- Main documentation for Rake. diff --git a/ruby/gems/rake-13.0.1/doc/rational.rdoc b/ruby/gems/rake-13.0.1/doc/rational.rdoc deleted file mode 100644 index 0e1c33873..000000000 --- a/ruby/gems/rake-13.0.1/doc/rational.rdoc +++ /dev/null @@ -1,151 +0,0 @@ -= Why rake? - -Ok, let me state from the beginning that I never intended to write this -code. I'm not convinced it is useful, and I'm not convinced anyone -would even be interested in it. All I can say is that Why's onion truck -must by been passing through the Ohio valley. - -What am I talking about? ... A Ruby version of Make. - -See, I can sense you cringing already, and I agree. The world certainly -doesn't need yet another reworking of the "make" program. I mean, we -already have "ant". Isn't that enough? - -It started yesterday. I was helping a coworker fix a problem in one of -the Makefiles we use in our project. Not a particularly tough problem, -but during the course of the conversation I began lamenting some of the -shortcomings of make. In particular, in one of my makefiles I wanted to -determine the name of a file dynamically and had to resort to some -simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you -could just use Ruby inside a Makefile" I said. - -My coworker (a recent convert to Ruby) agreed, but wondered what it -would look like. So I sketched the following on the whiteboard... - - "What if you could specify the make tasks in Ruby, like this ..." - - task "build" do - java_compile(...args, etc ...) - end - - "The task function would register "build" as a target to be made, - and the block would be the action executed whenever the build - system determined that it was time to do the build target." - -We agreed that would be cool, but writing make from scratch would be WAY -too much work. And that was the end of that! - -... Except I couldn't get the thought out of my head. What exactly -would be needed to make the about syntax work as a make file? Hmmm, you -would need to register the tasks, you need some way of specifying -dependencies between tasks, and some way of kicking off the process. -Hey! What if we did ... and fifteen minutes later I had a working -prototype of Ruby make, complete with dependencies and actions. - -I showed the code to my coworker and we had a good laugh. It was just -about a page worth of code that reproduced an amazing amount of the -functionality of make. We were both truly stunned with the power of -Ruby. - -But it didn't do everything make did. In particular, it didn't have -timestamp based file dependencies (where a file is rebuilt if any of its -prerequisite files have a later timestamp). Obviously THAT would be a -pain to add and so Ruby Make would remain an interesting experiment. - -... Except as I walked back to my desk, I started thinking about what -file based dependencies would really need. Rats! I was hooked again, -and by adding a new class and two new methods, file/timestamp -dependencies were implemented. - -Ok, now I was really hooked. Last night (during CSI!) I massaged the -code and cleaned it up a bit. The result is a bare-bones replacement -for make in exactly 100 lines of code. - -For the curious, you can see it at ... -* doc/proto_rake.rdoc - -Oh, about the name. When I wrote the example Ruby Make task on my -whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ... -Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves -and Rake would clean them up ... or something like that. Anyways, the -name stuck. - -Some quick examples ... - -A simple task to delete backup files ... - - task :clean do - Dir['*~'].each {|fn| rm fn rescue nil} - end - -Note that task names are symbols (they are slightly easier to type -than quoted strings ... but you may use quoted string if you would -rather). Rake makes the methods of the FileUtils module directly -available, so we take advantage of the rm command. Also note -the use of "rescue nil" to trap and ignore errors in the rm -command. - -To run it, just type "rake clean". Rake will automatically find a -Rakefile in the current directory (or above!) and will invoke the -targets named on the command line. If there are no targets explicitly -named, rake will invoke the task "default". - -Here's another task with dependencies ... - - task :clobber => [:clean] do - rm_r "tempdir" - end - -Task :clobber depends upon task :clean, so :clean will be run before -:clobber is executed. - -Files are specified by using the "file" command. It is similar to the -task command, except that the task name represents a file, and the task -will be run only if the file doesn't exist, or if its modification time -is earlier than any of its prerequisites. - -Here is a file based dependency that will compile "hello.cc" to -"hello.o". - - file "hello.cc" - file "hello.o" => ["hello.cc"] do |t| - srcfile = t.name.sub(/\.o$/, ".cc") - sh %{g++ #{srcfile} -c -o #{t.name}} - end - -I normally specify file tasks with string (rather than symbols). Some -file names can't be represented by symbols. Plus it makes the -distinction between them more clear to the casual reader. - -Currently writing a task for each and every file in the project would be -tedious at best. I envision a set of libraries to make this job -easier. For instance, perhaps something like this ... - - require 'rake/ctools' - Dir['*.c'].each do |fn| - c_source_file(fn) - end - -where "c_source_file" will create all the tasks need to compile all the -C source files in a directory. Any number of useful libraries could be -created for rake. - -That's it. There's no documentation (other than whats in this -message). Does this sound interesting to anyone? If so, I'll continue -to clean it up and write it up and publish it on RAA. Otherwise, I'll -leave it as an interesting exercise and a tribute to the power of Ruby. - -Why /might/ rake be interesting to Ruby programmers. I don't know, -perhaps ... - -* No weird make syntax (only weird Ruby syntax :-) -* No need to edit or read XML (a la ant) -* Platform independent build scripts. -* Will run anywhere Ruby exists, so no need to have "make" installed. - If you stay away from the "sys" command and use things like - 'ftools', you can have a perfectly platform independent - build script. Also rake is only 100 lines of code, so it can - easily be packaged along with the rest of your code. - -So ... Sorry for the long rambling message. Like I said, I never -intended to write this code at all. diff --git a/ruby/gems/rake-13.0.1/exe/rake b/ruby/gems/rake-13.0.1/exe/rake deleted file mode 100755 index a00975f30..000000000 --- a/ruby/gems/rake-13.0.1/exe/rake +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich -# -# 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. -#++ - -require "rake" - -Rake.application.run diff --git a/ruby/gems/rake-13.0.1/lib/rake.rb b/ruby/gems/rake-13.0.1/lib/rake.rb deleted file mode 100644 index 0dfd05315..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true -#-- -# Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com) -# -# 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. -#++ - -module Rake; end - -require "rake/version" - -require "rbconfig" -require "fileutils" -require "singleton" -require "monitor" -require "optparse" -require "ostruct" - -require "rake/ext/string" - -require "rake/win32" - -require "rake/linked_list" -require "rake/cpu_counter" -require "rake/scope" -require "rake/task_argument_error" -require "rake/rule_recursion_overflow_error" -require "rake/rake_module" -require "rake/trace_output" -require "rake/pseudo_status" -require "rake/task_arguments" -require "rake/invocation_chain" -require "rake/task" -require "rake/file_task" -require "rake/file_creation_task" -require "rake/multi_task" -require "rake/dsl_definition" -require "rake/file_utils_ext" -require "rake/file_list" -require "rake/default_loader" -require "rake/early_time" -require "rake/late_time" -require "rake/name_space" -require "rake/task_manager" -require "rake/application" -require "rake/backtrace" - -$trace = false - -# :stopdoc: -# -# Some top level Constants. - -FileList = Rake::FileList -RakeFileUtils = Rake::FileUtilsExt diff --git a/ruby/gems/rake-13.0.1/lib/rake/application.rb b/ruby/gems/rake-13.0.1/lib/rake/application.rb deleted file mode 100644 index 9ac9b2130..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/application.rb +++ /dev/null @@ -1,824 +0,0 @@ -# frozen_string_literal: true -require "optparse" - -require "rake/task_manager" -require "rake/file_list" -require "rake/thread_pool" -require "rake/thread_history_display" -require "rake/trace_output" -require "rake/win32" - -module Rake - - CommandLineOptionError = Class.new(StandardError) - - ## - # Rake main application object. When invoking +rake+ from the - # command line, a Rake::Application object is created and run. - - class Application - include TaskManager - include TraceOutput - - # The name of the application (typically 'rake') - attr_reader :name - - # The original directory where rake was invoked. - attr_reader :original_dir - - # Name of the actual rakefile used. - attr_reader :rakefile - - # Number of columns on the terminal - attr_accessor :terminal_columns - - # List of the top level task names (task names from the command line). - attr_reader :top_level_tasks - - # Override the detected TTY output state (mostly for testing) - attr_writer :tty_output - - DEFAULT_RAKEFILES = [ - "rakefile", - "Rakefile", - "rakefile.rb", - "Rakefile.rb" - ].freeze - - # Initialize a Rake::Application object. - def initialize - super - @name = "rake" - @rakefiles = DEFAULT_RAKEFILES.dup - @rakefile = nil - @pending_imports = [] - @imported = [] - @loaders = {} - @default_loader = Rake::DefaultLoader.new - @original_dir = Dir.pwd - @top_level_tasks = [] - add_loader("rb", DefaultLoader.new) - add_loader("rf", DefaultLoader.new) - add_loader("rake", DefaultLoader.new) - @tty_output = STDOUT.tty? - @terminal_columns = ENV["RAKE_COLUMNS"].to_i - - set_default_options - end - - # Run the Rake application. The run method performs the following - # three steps: - # - # * Initialize the command line options (+init+). - # * Define the tasks (+load_rakefile+). - # * Run the top level tasks (+top_level+). - # - # If you wish to build a custom rake command, you should call - # +init+ on your application. Then define any tasks. Finally, - # call +top_level+ to run your top level tasks. - def run(argv = ARGV) - standard_exception_handling do - init "rake", argv - load_rakefile - top_level - end - end - - # Initialize the command line parameters and app name. - def init(app_name="rake", argv = ARGV) - standard_exception_handling do - @name = app_name - begin - args = handle_options argv - rescue ArgumentError - # Backward compatibility for capistrano - args = handle_options - end - collect_command_line_tasks(args) - end - end - - # Find the rakefile and then load it and any pending imports. - def load_rakefile - standard_exception_handling do - raw_load_rakefile - end - end - - # Run the top level tasks of a Rake application. - def top_level - run_with_threads do - if options.show_tasks - display_tasks_and_comments - elsif options.show_prereqs - display_prerequisites - else - top_level_tasks.each { |task_name| invoke_task(task_name) } - end - end - end - - # Run the given block with the thread startup and shutdown. - def run_with_threads - thread_pool.gather_history if options.job_stats == :history - - yield - - thread_pool.join - if options.job_stats - stats = thread_pool.statistics - puts "Maximum active threads: #{stats[:max_active_threads]} + main" - puts "Total threads in play: #{stats[:total_threads_in_play]} + main" - end - ThreadHistoryDisplay.new(thread_pool.history).show if - options.job_stats == :history - end - - # Add a loader to handle imported files ending in the extension - # +ext+. - def add_loader(ext, loader) - ext = ".#{ext}" unless ext =~ /^\./ - @loaders[ext] = loader - end - - # Application options from the command line - def options - @options ||= OpenStruct.new - end - - # Return the thread pool used for multithreaded processing. - def thread_pool # :nodoc: - @thread_pool ||= ThreadPool.new(options.thread_pool_size || Rake.suggested_thread_count-1) - end - - # internal ---------------------------------------------------------------- - - # Invokes a task with arguments that are extracted from +task_string+ - def invoke_task(task_string) # :nodoc: - name, args = parse_task_string(task_string) - t = self[name] - t.invoke(*args) - end - - def parse_task_string(string) # :nodoc: - /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s - - name = $1 - remaining_args = $2 - - return string, [] unless name - return name, [] if remaining_args.empty? - - args = [] - - begin - /\s*((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args - - remaining_args = $2 - args << $1.gsub(/\\(.)/, '\1') - end while remaining_args - - return name, args - end - - # Provide standard exception handling for the given block. - def standard_exception_handling # :nodoc: - yield - rescue SystemExit - # Exit silently with current status - raise - rescue OptionParser::InvalidOption => ex - $stderr.puts ex.message - exit(false) - rescue Exception => ex - # Exit with error message - display_error_message(ex) - exit_because_of_exception(ex) - end - - # Exit the program because of an unhandled exception. - # (may be overridden by subclasses) - def exit_because_of_exception(ex) # :nodoc: - exit(false) - end - - # Display the error message that caused the exception. - def display_error_message(ex) # :nodoc: - trace "#{name} aborted!" - display_exception_details(ex) - trace "Tasks: #{ex.chain}" if has_chain?(ex) - trace "(See full trace by running task with --trace)" unless - options.backtrace - end - - def display_exception_details(ex) # :nodoc: - display_exception_details_seen << ex - - display_exception_message_details(ex) - display_exception_backtrace(ex) - display_cause_details(ex.cause) if has_cause?(ex) - end - - def display_cause_details(ex) # :nodoc: - return if display_exception_details_seen.include? ex - - trace "\nCaused by:" - display_exception_details(ex) - end - - def display_exception_details_seen # :nodoc: - Thread.current[:rake_display_exception_details_seen] ||= [] - end - - def has_cause?(ex) # :nodoc: - ex.respond_to?(:cause) && ex.cause - end - - def display_exception_message_details(ex) # :nodoc: - if ex.instance_of?(RuntimeError) - trace ex.message - else - trace "#{ex.class.name}: #{ex.message}" - end - end - - def display_exception_backtrace(ex) # :nodoc: - if options.backtrace - trace ex.backtrace.join("\n") - else - trace Backtrace.collapse(ex.backtrace).join("\n") - end - end - - # Warn about deprecated usage. - # - # Example: - # Rake.application.deprecate("import", "Rake.import", caller.first) - # - def deprecate(old_usage, new_usage, call_site) # :nodoc: - unless options.ignore_deprecate - $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + - "Please use '#{new_usage}' instead.\n" + - " at #{call_site}" - end - end - - # Does the exception have a task invocation chain? - def has_chain?(exception) # :nodoc: - exception.respond_to?(:chain) && exception.chain - end - private :has_chain? - - # True if one of the files in RAKEFILES is in the current directory. - # If a match is found, it is copied into @rakefile. - def have_rakefile # :nodoc: - @rakefiles.each do |fn| - if File.exist?(fn) - others = FileList.glob(fn, File::FNM_CASEFOLD) - return others.size == 1 ? others.first : fn - elsif fn == "" - return fn - end - end - return nil - end - - # True if we are outputting to TTY, false otherwise - def tty_output? # :nodoc: - @tty_output - end - - # We will truncate output if we are outputting to a TTY or if we've been - # given an explicit column width to honor - def truncate_output? # :nodoc: - tty_output? || @terminal_columns.nonzero? - end - - # Display the tasks and comments. - def display_tasks_and_comments # :nodoc: - displayable_tasks = tasks.select { |t| - (options.show_all_tasks || t.comment) && - t.name =~ options.show_task_pattern - } - case options.show_tasks - when :tasks - width = displayable_tasks.map { |t| t.name_with_args.length }.max || 10 - if truncate_output? - max_column = terminal_width - name.size - width - 7 - else - max_column = nil - end - - displayable_tasks.each do |t| - printf("#{name} %-#{width}s # %s\n", - t.name_with_args, - max_column ? truncate(t.comment, max_column) : t.comment) - end - when :describe - displayable_tasks.each do |t| - puts "#{name} #{t.name_with_args}" - comment = t.full_comment || "" - comment.split("\n").each do |line| - puts " #{line}" - end - puts - end - when :lines - displayable_tasks.each do |t| - t.locations.each do |loc| - printf "#{name} %-30s %s\n", t.name_with_args, loc - end - end - else - fail "Unknown show task mode: '#{options.show_tasks}'" - end - end - - def terminal_width # :nodoc: - if @terminal_columns.nonzero? - result = @terminal_columns - else - result = unix? ? dynamic_width : 80 - end - (result < 10) ? 80 : result - rescue - 80 - end - - # Calculate the dynamic width of the - def dynamic_width # :nodoc: - @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) - end - - def dynamic_width_stty # :nodoc: - %x{stty size 2>/dev/null}.split[1].to_i - end - - def dynamic_width_tput # :nodoc: - %x{tput cols 2>/dev/null}.to_i - end - - def unix? # :nodoc: - RbConfig::CONFIG["host_os"] =~ - /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i - end - - def windows? # :nodoc: - Win32.windows? - end - - def truncate(string, width) # :nodoc: - if string.nil? - "" - elsif string.length <= width - string - else - (string[0, width - 3] || "") + "..." - end - end - - # Display the tasks and prerequisites - def display_prerequisites # :nodoc: - tasks.each do |t| - puts "#{name} #{t.name}" - t.prerequisites.each { |pre| puts " #{pre}" } - end - end - - def trace(*strings) # :nodoc: - options.trace_output ||= $stderr - trace_on(options.trace_output, *strings) - end - - def sort_options(options) # :nodoc: - options.sort_by { |opt| - opt.select { |o| o.is_a?(String) && o =~ /^-/ }.map(&:downcase).sort.reverse - } - end - private :sort_options - - # A list of all the standard options used in rake, suitable for - # passing to OptionParser. - def standard_rake_options # :nodoc: - sort_options( - [ - ["--all", "-A", - "Show all tasks, even uncommented ones (in combination with -T or -D)", - lambda { |value| - options.show_all_tasks = value - } - ], - ["--backtrace=[OUT]", - "Enable full backtrace. OUT can be stderr (default) or stdout.", - lambda { |value| - options.backtrace = true - select_trace_output(options, "backtrace", value) - } - ], - ["--build-all", "-B", - "Build all prerequisites, including those which are up-to-date.", - lambda { |value| - options.build_all = true - } - ], - ["--comments", - "Show commented tasks only", - lambda { |value| - options.show_all_tasks = !value - } - ], - ["--describe", "-D [PATTERN]", - "Describe the tasks (matching optional PATTERN), then exit.", - lambda { |value| - select_tasks_to_show(options, :describe, value) - } - ], - ["--dry-run", "-n", - "Do a dry run without executing actions.", - lambda { |value| - Rake.verbose(true) - Rake.nowrite(true) - options.dryrun = true - options.trace = true - } - ], - ["--execute", "-e CODE", - "Execute some Ruby code and exit.", - lambda { |value| - eval(value) - exit - } - ], - ["--execute-print", "-p CODE", - "Execute some Ruby code, print the result, then exit.", - lambda { |value| - puts eval(value) - exit - } - ], - ["--execute-continue", "-E CODE", - "Execute some Ruby code, " + - "then continue with normal task processing.", - lambda { |value| eval(value) } - ], - ["--jobs", "-j [NUMBER]", - "Specifies the maximum number of tasks to execute in parallel. " + - "(default is number of CPU cores + 4)", - lambda { |value| - if value.nil? || value == "" - value = Float::INFINITY - elsif value =~ /^\d+$/ - value = value.to_i - else - value = Rake.suggested_thread_count - end - value = 1 if value < 1 - options.thread_pool_size = value - 1 - } - ], - ["--job-stats [LEVEL]", - "Display job statistics. " + - "LEVEL=history displays a complete job list", - lambda { |value| - if value =~ /^history/i - options.job_stats = :history - else - options.job_stats = true - end - } - ], - ["--libdir", "-I LIBDIR", - "Include LIBDIR in the search path for required modules.", - lambda { |value| $:.push(value) } - ], - ["--multitask", "-m", - "Treat all tasks as multitasks.", - lambda { |value| options.always_multitask = true } - ], - ["--no-search", "--nosearch", - "-N", "Do not search parent directories for the Rakefile.", - lambda { |value| options.nosearch = true } - ], - ["--prereqs", "-P", - "Display the tasks and dependencies, then exit.", - lambda { |value| options.show_prereqs = true } - ], - ["--quiet", "-q", - "Do not log messages to standard output.", - lambda { |value| Rake.verbose(false) } - ], - ["--rakefile", "-f [FILENAME]", - "Use FILENAME as the rakefile to search for.", - lambda { |value| - value ||= "" - @rakefiles.clear - @rakefiles << value - } - ], - ["--rakelibdir", "--rakelib", "-R RAKELIBDIR", - "Auto-import any .rake files in RAKELIBDIR. " + - "(default is 'rakelib')", - lambda { |value| - options.rakelib = value.split(File::PATH_SEPARATOR) - } - ], - ["--require", "-r MODULE", - "Require MODULE before executing rakefile.", - lambda { |value| - begin - require value - rescue LoadError => ex - begin - rake_require value - rescue LoadError - raise ex - end - end - } - ], - ["--rules", - "Trace the rules resolution.", - lambda { |value| options.trace_rules = true } - ], - ["--silent", "-s", - "Like --quiet, but also suppresses the " + - "'in directory' announcement.", - lambda { |value| - Rake.verbose(false) - options.silent = true - } - ], - ["--suppress-backtrace PATTERN", - "Suppress backtrace lines matching regexp PATTERN. " + - "Ignored if --trace is on.", - lambda { |value| - options.suppress_backtrace_pattern = Regexp.new(value) - } - ], - ["--system", "-g", - "Using system wide (global) rakefiles " + - "(usually '~/.rake/*.rake').", - lambda { |value| options.load_system = true } - ], - ["--no-system", "--nosystem", "-G", - "Use standard project Rakefile search paths, " + - "ignore system wide rakefiles.", - lambda { |value| options.ignore_system = true } - ], - ["--tasks", "-T [PATTERN]", - "Display the tasks (matching optional PATTERN) " + - "with descriptions, then exit. " + - "-AT combination displays all of tasks contained no description.", - lambda { |value| - select_tasks_to_show(options, :tasks, value) - } - ], - ["--trace=[OUT]", "-t", - "Turn on invoke/execute tracing, enable full backtrace. " + - "OUT can be stderr (default) or stdout.", - lambda { |value| - options.trace = true - options.backtrace = true - select_trace_output(options, "trace", value) - Rake.verbose(true) - } - ], - ["--verbose", "-v", - "Log message to standard output.", - lambda { |value| Rake.verbose(true) } - ], - ["--version", "-V", - "Display the program version.", - lambda { |value| - puts "rake, version #{Rake::VERSION}" - exit - } - ], - ["--where", "-W [PATTERN]", - "Describe the tasks (matching optional PATTERN), then exit.", - lambda { |value| - select_tasks_to_show(options, :lines, value) - options.show_all_tasks = true - } - ], - ["--no-deprecation-warnings", "-X", - "Disable the deprecation warnings.", - lambda { |value| - options.ignore_deprecate = true - } - ], - ]) - end - - def select_tasks_to_show(options, show_tasks, value) # :nodoc: - options.show_tasks = show_tasks - options.show_task_pattern = Regexp.new(value || "") - Rake::TaskManager.record_task_metadata = true - end - private :select_tasks_to_show - - def select_trace_output(options, trace_option, value) # :nodoc: - value = value.strip unless value.nil? - case value - when "stdout" - options.trace_output = $stdout - when "stderr", nil - options.trace_output = $stderr - else - fail CommandLineOptionError, - "Unrecognized --#{trace_option} option '#{value}'" - end - end - private :select_trace_output - - # Read and handle the command line options. Returns the command line - # arguments that we didn't understand, which should (in theory) be just - # task names and env vars. - def handle_options(argv) # :nodoc: - set_default_options - - OptionParser.new do |opts| - opts.banner = "#{Rake.application.name} [-f rakefile] {options} targets..." - opts.separator "" - opts.separator "Options are ..." - - opts.on_tail("-h", "--help", "-H", "Display this help message.") do - puts opts - exit - end - - standard_rake_options.each { |args| opts.on(*args) } - opts.environment("RAKEOPT") - end.parse(argv) - end - - # Similar to the regular Ruby +require+ command, but will check - # for *.rake files in addition to *.rb files. - def rake_require(file_name, paths=$LOAD_PATH, loaded=$") # :nodoc: - fn = file_name + ".rake" - return false if loaded.include?(fn) - paths.each do |path| - full_path = File.join(path, fn) - if File.exist?(full_path) - Rake.load_rakefile(full_path) - loaded << fn - return true - end - end - fail LoadError, "Can't find #{file_name}" - end - - def find_rakefile_location # :nodoc: - here = Dir.pwd - until (fn = have_rakefile) - Dir.chdir("..") - return nil if Dir.pwd == here || options.nosearch - here = Dir.pwd - end - [fn, here] - ensure - Dir.chdir(Rake.original_dir) - end - - def print_rakefile_directory(location) # :nodoc: - $stderr.puts "(in #{Dir.pwd})" unless - options.silent or original_dir == location - end - - def raw_load_rakefile # :nodoc: - rakefile, location = find_rakefile_location - if (!options.ignore_system) && - (options.load_system || rakefile.nil?) && - system_dir && File.directory?(system_dir) - print_rakefile_directory(location) - glob("#{system_dir}/*.rake") do |name| - add_import name - end - else - fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if - rakefile.nil? - @rakefile = rakefile - Dir.chdir(location) - print_rakefile_directory(location) - Rake.load_rakefile(File.expand_path(@rakefile)) if - @rakefile && @rakefile != "" - options.rakelib.each do |rlib| - glob("#{rlib}/*.rake") do |name| - add_import name - end - end - end - load_imports - end - - def glob(path, &block) # :nodoc: - FileList.glob(path.tr("\\", "/")).each(&block) - end - private :glob - - # The directory path containing the system wide rakefiles. - def system_dir # :nodoc: - @system_dir ||= - begin - if ENV["RAKE_SYSTEM"] - ENV["RAKE_SYSTEM"] - else - standard_system_dir - end - end - end - - # The standard directory containing system wide rake files. - if Win32.windows? - def standard_system_dir #:nodoc: - Win32.win32_system_dir - end - else - def standard_system_dir #:nodoc: - File.join(File.expand_path("~"), ".rake") - end - end - private :standard_system_dir - - # Collect the list of tasks on the command line. If no tasks are - # given, return a list containing only the default task. - # Environmental assignments are processed at this time as well. - # - # `args` is the list of arguments to peruse to get the list of tasks. - # It should be the command line that was given to rake, less any - # recognised command-line options, which OptionParser.parse will - # have taken care of already. - def collect_command_line_tasks(args) # :nodoc: - @top_level_tasks = [] - args.each do |arg| - if arg =~ /^(\w+)=(.*)$/m - ENV[$1] = $2 - else - @top_level_tasks << arg unless arg =~ /^-/ - end - end - @top_level_tasks.push(default_task_name) if @top_level_tasks.empty? - end - - # Default task name ("default"). - # (May be overridden by subclasses) - def default_task_name # :nodoc: - "default" - end - - # Add a file to the list of files to be imported. - def add_import(fn) # :nodoc: - @pending_imports << fn - end - - # Load the pending list of imported files. - def load_imports # :nodoc: - while fn = @pending_imports.shift - next if @imported.member?(fn) - fn_task = lookup(fn) and fn_task.invoke - ext = File.extname(fn) - loader = @loaders[ext] || @default_loader - loader.load(fn) - if fn_task = lookup(fn) and fn_task.needed? - fn_task.reenable - fn_task.invoke - loader.load(fn) - end - @imported << fn - end - end - - def rakefile_location(backtrace=caller) # :nodoc: - backtrace.map { |t| t[/([^:]+):/, 1] } - - re = /^#{@rakefile}$/ - re = /#{re.source}/i if windows? - - backtrace.find { |str| str =~ re } || "" - end - - def set_default_options # :nodoc: - options.always_multitask = false - options.backtrace = false - options.build_all = false - options.dryrun = false - options.ignore_deprecate = false - options.ignore_system = false - options.job_stats = false - options.load_system = false - options.nosearch = false - options.rakelib = %w[rakelib] - options.show_all_tasks = false - options.show_prereqs = false - options.show_task_pattern = nil - options.show_tasks = nil - options.silent = false - options.suppress_backtrace_pattern = nil - options.thread_pool_size = Rake.suggested_thread_count - options.trace = false - options.trace_output = $stderr - options.trace_rules = false - end - - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/backtrace.rb b/ruby/gems/rake-13.0.1/lib/rake/backtrace.rb deleted file mode 100644 index 31ff05450..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/backtrace.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true -module Rake - module Backtrace # :nodoc: all - SYS_KEYS = RbConfig::CONFIG.keys.grep(/(?:[a-z]prefix|libdir)\z/) - SYS_PATHS = RbConfig::CONFIG.values_at(*SYS_KEYS).uniq + - [ File.join(File.dirname(__FILE__), "..") ] - - SUPPRESSED_PATHS = SYS_PATHS. - map { |s| s.tr("\\", "/") }. - map { |f| File.expand_path(f) }. - reject { |s| s.nil? || s =~ /^ *$/ } - SUPPRESSED_PATHS_RE = SUPPRESSED_PATHS.map { |f| Regexp.quote(f) }.join("|") - SUPPRESSED_PATHS_RE << "|^org\\/jruby\\/\\w+\\.java" if - Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == "jruby" - - SUPPRESS_PATTERN = %r!(\A(#{SUPPRESSED_PATHS_RE})|bin/rake:\d+)!i - - def self.collapse(backtrace) - pattern = Rake.application.options.suppress_backtrace_pattern || - SUPPRESS_PATTERN - backtrace.reject { |elem| elem =~ pattern } - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/clean.rb b/ruby/gems/rake-13.0.1/lib/rake/clean.rb deleted file mode 100644 index b52e832a9..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/clean.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true -# The 'rake/clean' file defines two file lists (CLEAN and CLOBBER) and -# two rake tasks (:clean and :clobber). -# -# [:clean] Clean up the project by deleting scratch files and backup -# files. Add files to the CLEAN file list to have the :clean -# target handle them. -# -# [:clobber] Clobber all generated and non-source files in a project. -# The task depends on :clean, so all the clean files will -# be deleted as well as files in the CLOBBER file list. -# The intent of this task is to return a project to its -# pristine, just unpacked state. - -require "rake" - -# :stopdoc: - -module Rake - module Cleaner - extend FileUtils - - module_function - - def cleanup_files(file_names) - file_names.each do |file_name| - cleanup(file_name) - end - end - - def cleanup(file_name, **opts) - begin - opts = { verbose: Rake.application.options.trace }.merge(opts) - rm_r file_name, **opts - rescue StandardError => ex - puts "Failed to remove #{file_name}: #{ex}" unless file_already_gone?(file_name) - end - end - - def file_already_gone?(file_name) - return false if File.exist?(file_name) - - path = file_name - prev = nil - - while path = File.dirname(path) - return false if cant_be_deleted?(path) - break if [prev, "."].include?(path) - prev = path - end - true - end - private_class_method :file_already_gone? - - def cant_be_deleted?(path_name) - File.exist?(path_name) && - (!File.readable?(path_name) || !File.executable?(path_name)) - end - private_class_method :cant_be_deleted? - end -end - -CLEAN = ::Rake::FileList["**/*~", "**/*.bak", "**/core"] -CLEAN.clear_exclude.exclude { |fn| - fn.pathmap("%f").downcase == "core" && File.directory?(fn) -} - -desc "Remove any temporary products." -task :clean do - Rake::Cleaner.cleanup_files(CLEAN) -end - -CLOBBER = ::Rake::FileList.new - -desc "Remove any generated files." -task clobber: [:clean] do - Rake::Cleaner.cleanup_files(CLOBBER) -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/cloneable.rb b/ruby/gems/rake-13.0.1/lib/rake/cloneable.rb deleted file mode 100644 index eddb77e2f..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/cloneable.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true -module Rake - ## - # Mixin for creating easily cloned objects. - - module Cloneable # :nodoc: - # The hook that is invoked by 'clone' and 'dup' methods. - def initialize_copy(source) - super - source.instance_variables.each do |var| - src_value = source.instance_variable_get(var) - value = src_value.clone rescue src_value - instance_variable_set(var, value) - end - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/cpu_counter.rb b/ruby/gems/rake-13.0.1/lib/rake/cpu_counter.rb deleted file mode 100644 index 564a62859..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/cpu_counter.rb +++ /dev/null @@ -1,107 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Based on a script at: - # http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed - class CpuCounter # :nodoc: all - def self.count - new.count_with_default - end - - def count_with_default(default=4) - count || default - rescue StandardError - default - end - - begin - require "etc" - rescue LoadError - else - if Etc.respond_to?(:nprocessors) - def count - return Etc.nprocessors - end - end - end - end -end - -unless Rake::CpuCounter.method_defined?(:count) - Rake::CpuCounter.class_eval <<-'end;', __FILE__, __LINE__+1 - require 'rbconfig' - - def count - if RUBY_PLATFORM == 'java' - count_via_java_runtime - else - case RbConfig::CONFIG['host_os'] - when /linux/ - count_via_cpuinfo - when /darwin|bsd/ - count_via_sysctl - when /mswin|mingw/ - count_via_win32 - else - # Try everything - count_via_win32 || - count_via_sysctl || - count_via_cpuinfo - end - end - end - - def count_via_java_runtime - Java::Java.lang.Runtime.getRuntime.availableProcessors - rescue StandardError - nil - end - - def count_via_win32 - require 'win32ole' - wmi = WIN32OLE.connect("winmgmts://") - cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this - cpu.to_enum.first.NumberOfCores - rescue StandardError, LoadError - nil - end - - def count_via_cpuinfo - open('/proc/cpuinfo') { |f| f.readlines }.grep(/processor/).size - rescue StandardError - nil - end - - def count_via_sysctl - run 'sysctl', '-n', 'hw.ncpu' - end - - def run(command, *args) - cmd = resolve_command(command) - if cmd - IO.popen [cmd, *args] do |io| - io.read.to_i - end - else - nil - end - end - - def resolve_command(command) - look_for_command("/usr/sbin", command) || - look_for_command("/sbin", command) || - in_path_command(command) - end - - def look_for_command(dir, command) - path = File.join(dir, command) - File.exist?(path) ? path : nil - end - - def in_path_command(command) - IO.popen ['which', command] do |io| - io.eof? ? nil : command - end - end - end; -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/default_loader.rb b/ruby/gems/rake-13.0.1/lib/rake/default_loader.rb deleted file mode 100644 index d3b4650d3..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/default_loader.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Default Rakefile loader used by +import+. - class DefaultLoader - - ## - # Loads a rakefile into the current application from +fn+ - - def load(fn) - Rake.load_rakefile(File.expand_path(fn)) - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/dsl_definition.rb b/ruby/gems/rake-13.0.1/lib/rake/dsl_definition.rb deleted file mode 100644 index c80464020..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/dsl_definition.rb +++ /dev/null @@ -1,195 +0,0 @@ -# frozen_string_literal: true -# Rake DSL functions. -require "rake/file_utils_ext" - -module Rake - - ## - # DSL is a module that provides #task, #desc, #namespace, etc. Use this - # when you'd like to use rake outside the top level scope. - # - # For a Rakefile you run from the command line this module is automatically - # included. - - module DSL - - #-- - # Include the FileUtils file manipulation functions in the top - # level module, but mark them private so that they don't - # unintentionally define methods on other objects. - #++ - - include FileUtilsExt - private(*FileUtils.instance_methods(false)) - private(*FileUtilsExt.instance_methods(false)) - - private - - # :call-seq: - # task(task_name) - # task(task_name: dependencies) - # task(task_name, arguments => dependencies) - # - # Declare a basic task. The +task_name+ is always the first argument. If - # the task name contains a ":" it is defined in that namespace. - # - # The +dependencies+ may be a single task name or an Array of task names. - # The +argument+ (a single name) or +arguments+ (an Array of names) define - # the arguments provided to the task. - # - # The task, argument and dependency names may be either symbols or - # strings. - # - # A task with a single dependency: - # - # task clobber: %w[clean] do - # rm_rf "html" - # end - # - # A task with an argument and a dependency: - # - # task :package, [:version] => :test do |t, args| - # # ... - # end - # - # To invoke this task from the command line: - # - # $ rake package[1.2.3] - # - def task(*args, &block) # :doc: - Rake::Task.define_task(*args, &block) - end - - # Declare a file task. - # - # Example: - # file "config.cfg" => ["config.template"] do - # open("config.cfg", "w") do |outfile| - # open("config.template") do |infile| - # while line = infile.gets - # outfile.puts line - # end - # end - # end - # end - # - def file(*args, &block) # :doc: - Rake::FileTask.define_task(*args, &block) - end - - # Declare a file creation task. - # (Mainly used for the directory command). - def file_create(*args, &block) - Rake::FileCreationTask.define_task(*args, &block) - end - - # Declare a set of files tasks to create the given directories on - # demand. - # - # Example: - # directory "testdata/doc" - # - def directory(*args, &block) # :doc: - result = file_create(*args, &block) - dir, _ = *Rake.application.resolve_args(args) - dir = Rake.from_pathname(dir) - Rake.each_dir_parent(dir) do |d| - file_create d do |t| - mkdir_p t.name unless File.exist?(t.name) - end - end - result - end - - # Declare a task that performs its prerequisites in - # parallel. Multitasks does *not* guarantee that its prerequisites - # will execute in any given order (which is obvious when you think - # about it) - # - # Example: - # multitask deploy: %w[deploy_gem deploy_rdoc] - # - def multitask(*args, &block) # :doc: - Rake::MultiTask.define_task(*args, &block) - end - - # Create a new rake namespace and use it for evaluating the given - # block. Returns a NameSpace object that can be used to lookup - # tasks defined in the namespace. - # - # Example: - # - # ns = namespace "nested" do - # # the "nested:run" task - # task :run - # end - # task_run = ns[:run] # find :run in the given namespace. - # - # Tasks can also be defined in a namespace by using a ":" in the task - # name: - # - # task "nested:test" do - # # ... - # end - # - def namespace(name=nil, &block) # :doc: - name = name.to_s if name.kind_of?(Symbol) - name = name.to_str if name.respond_to?(:to_str) - unless name.kind_of?(String) || name.nil? - raise ArgumentError, "Expected a String or Symbol for a namespace name" - end - Rake.application.in_namespace(name, &block) - end - - # Declare a rule for auto-tasks. - # - # Example: - # rule '.o' => '.c' do |t| - # sh 'cc', '-o', t.name, t.source - # end - # - def rule(*args, &block) # :doc: - Rake::Task.create_rule(*args, &block) - end - - # Describes the next rake task. Duplicate descriptions are discarded. - # Descriptions are shown with rake -T (up to the first - # sentence) and rake -D (the entire description). - # - # Example: - # desc "Run the Unit Tests" - # task test: [:build] - # # ... run tests - # end - # - def desc(description) # :doc: - Rake.application.last_description = description - end - - # Import the partial Rakefiles +fn+. Imported files are loaded - # _after_ the current file is completely loaded. This allows the - # import statement to appear anywhere in the importing file, and yet - # allowing the imported files to depend on objects defined in the - # importing file. - # - # A common use of the import statement is to include files - # containing dependency declarations. - # - # See also the --rakelibdir command line option. - # - # Example: - # import ".depend", "my_rules" - # - def import(*fns) # :doc: - fns.each do |fn| - Rake.application.add_import(fn) - end - end - end - extend FileUtilsExt -end - -# Extend the main object with the DSL commands. This allows top-level -# calls to task, etc. to work from a Rakefile without polluting the -# object inheritance tree. -self.extend Rake::DSL diff --git a/ruby/gems/rake-13.0.1/lib/rake/early_time.rb b/ruby/gems/rake-13.0.1/lib/rake/early_time.rb deleted file mode 100644 index 80cc6bfad..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/early_time.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true -module Rake - - # EarlyTime is a fake timestamp that occurs _before_ any other time value. - class EarlyTime - include Comparable - include Singleton - - ## - # The EarlyTime always comes before +other+! - - def <=>(other) - -1 - end - - def to_s # :nodoc: - "" - end - end - - EARLY = EarlyTime.instance -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/ext/core.rb b/ruby/gems/rake-13.0.1/lib/rake/ext/core.rb deleted file mode 100644 index 226f2125b..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/ext/core.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true -class Module - # Check for an existing method in the current class before extending. If - # the method already exists, then a warning is printed and the extension is - # not added. Otherwise the block is yielded and any definitions in the - # block will take effect. - # - # Usage: - # - # class String - # rake_extension("xyz") do - # def xyz - # ... - # end - # end - # end - # - def rake_extension(method) # :nodoc: - if method_defined?(method) - $stderr.puts "WARNING: Possible conflict with Rake extension: " + - "#{self}##{method} already exists" - else - yield - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/ext/string.rb b/ruby/gems/rake-13.0.1/lib/rake/ext/string.rb deleted file mode 100644 index c70236ae9..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/ext/string.rb +++ /dev/null @@ -1,176 +0,0 @@ -# frozen_string_literal: true -require "rake/ext/core" - -class String - - rake_extension("ext") do - # Replace the file extension with +newext+. If there is no extension on - # the string, append the new extension to the end. If the new extension - # is not given, or is the empty string, remove any existing extension. - # - # +ext+ is a user added method for the String class. - # - # This String extension comes from Rake - def ext(newext="") - return self.dup if [".", ".."].include? self - if newext != "" - newext = "." + newext unless newext =~ /^\./ - end - self.chomp(File.extname(self)) << newext - end - end - - rake_extension("pathmap") do - # Explode a path into individual components. Used by +pathmap+. - # - # This String extension comes from Rake - def pathmap_explode - head, tail = File.split(self) - return [self] if head == self - return [tail] if head == "." || tail == "/" - return [head, tail] if head == "/" - return head.pathmap_explode + [tail] - end - protected :pathmap_explode - - # Extract a partial path from the path. Include +n+ directories from the - # front end (left hand side) if +n+ is positive. Include |+n+| - # directories from the back end (right hand side) if +n+ is negative. - # - # This String extension comes from Rake - def pathmap_partial(n) - dirs = File.dirname(self).pathmap_explode - partial_dirs = - if n > 0 - dirs[0...n] - elsif n < 0 - dirs.reverse[0...-n].reverse - else - "." - end - File.join(partial_dirs) - end - protected :pathmap_partial - - # Perform the pathmap replacement operations on the given path. The - # patterns take the form 'pat1,rep1;pat2,rep2...'. - # - # This String extension comes from Rake - def pathmap_replace(patterns, &block) - result = self - patterns.split(";").each do |pair| - pattern, replacement = pair.split(",") - pattern = Regexp.new(pattern) - if replacement == "*" && block_given? - result = result.sub(pattern, &block) - elsif replacement - result = result.sub(pattern, replacement) - else - result = result.sub(pattern, "") - end - end - result - end - protected :pathmap_replace - - # Map the path according to the given specification. The specification - # controls the details of the mapping. The following special patterns are - # recognized: - # - # %p :: The complete path. - # %f :: The base file name of the path, with its file extension, - # but without any directories. - # %n :: The file name of the path without its file extension. - # %d :: The directory list of the path. - # %x :: The file extension of the path. An empty string if there - # is no extension. - # %X :: Everything *but* the file extension. - # %s :: The alternate file separator if defined, otherwise use # - # the standard file separator. - # %% :: A percent sign. - # - # The %d specifier can also have a numeric prefix (e.g. '%2d'). - # If the number is positive, only return (up to) +n+ directories in the - # path, starting from the left hand side. If +n+ is negative, return (up - # to) +n+ directories from the right hand side of the path. - # - # Examples: - # - # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b' - # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d' - # - # Also the %d, %p, %f, %n, - # %x, and %X operators can take a pattern/replacement - # argument to perform simple string substitutions on a particular part of - # the path. The pattern and replacement are separated by a comma and are - # enclosed by curly braces. The replacement spec comes after the % - # character but before the operator letter. (e.g. "%{old,new}d"). - # Multiple replacement specs should be separated by semi-colons (e.g. - # "%{old,new;src,bin}d"). - # - # Regular expressions may be used for the pattern, and back refs may be - # used in the replacement text. Curly braces, commas and semi-colons are - # excluded from both the pattern and replacement text (let's keep parsing - # reasonable). - # - # For example: - # - # "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class") - # - # returns: - # - # "class/org/onestepback/proj/A.class" - # - # If the replacement text is '*', then a block may be provided to perform - # some arbitrary calculation for the replacement. - # - # For example: - # - # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext| - # ext.downcase - # } - # - # Returns: - # - # "/path/to/file.txt" - # - # This String extension comes from Rake - def pathmap(spec=nil, &block) - return self if spec.nil? - result = "".dup - spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag| - case frag - when "%f" - result << File.basename(self) - when "%n" - result << File.basename(self).ext - when "%d" - result << File.dirname(self) - when "%x" - result << File.extname(self) - when "%X" - result << self.ext - when "%p" - result << self - when "%s" - result << (File::ALT_SEPARATOR || File::SEPARATOR) - when "%-" - # do nothing - when "%%" - result << "%" - when /%(-?\d+)d/ - result << pathmap_partial($1.to_i) - when /^%\{([^}]*)\}(\d*[dpfnxX])/ - patterns, operator = $1, $2 - result << pathmap("%" + operator).pathmap_replace(patterns, &block) - when /^%/ - fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'" - else - result << frag - end - end - result - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/file_creation_task.rb b/ruby/gems/rake-13.0.1/lib/rake/file_creation_task.rb deleted file mode 100644 index 5a4c68492..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/file_creation_task.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true -require "rake/file_task" -require "rake/early_time" - -module Rake - - # A FileCreationTask is a file task that when used as a dependency will be - # needed if and only if the file has not been created. Once created, it is - # not re-triggered if any of its dependencies are newer, nor does trigger - # any rebuilds of tasks that depend on it whenever it is updated. - # - class FileCreationTask < FileTask - # Is this file task needed? Yes if it doesn't exist. - def needed? - !File.exist?(name) - end - - # Time stamp for file creation task. This time stamp is earlier - # than any other time stamp. - def timestamp - Rake::EARLY - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/file_list.rb b/ruby/gems/rake-13.0.1/lib/rake/file_list.rb deleted file mode 100644 index 22c339f24..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/file_list.rb +++ /dev/null @@ -1,435 +0,0 @@ -# frozen_string_literal: true -require "rake/cloneable" -require "rake/file_utils_ext" -require "rake/ext/string" - -module Rake - - ## - # A FileList is essentially an array with a few helper methods defined to - # make file manipulation a bit easier. - # - # FileLists are lazy. When given a list of glob patterns for possible files - # to be included in the file list, instead of searching the file structures - # to find the files, a FileList holds the pattern for latter use. - # - # This allows us to define a number of FileList to match any number of - # files, but only search out the actual files when then FileList itself is - # actually used. The key is that the first time an element of the - # FileList/Array is requested, the pending patterns are resolved into a real - # list of file names. - # - class FileList - - include Cloneable - - # == Method Delegation - # - # The lazy evaluation magic of FileLists happens by implementing all the - # array specific methods to call +resolve+ before delegating the heavy - # lifting to an embedded array object (@items). - # - # In addition, there are two kinds of delegation calls. The regular kind - # delegates to the @items array and returns the result directly. Well, - # almost directly. It checks if the returned value is the @items object - # itself, and if so will return the FileList object instead. - # - # The second kind of delegation call is used in methods that normally - # return a new Array object. We want to capture the return value of these - # methods and wrap them in a new FileList object. We enumerate these - # methods in the +SPECIAL_RETURN+ list below. - - # List of array methods (that are not in +Object+) that need to be - # delegated. - ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map(&:to_s) - - # List of additional methods that must be delegated. - MUST_DEFINE = %w[inspect <=>] - - # List of methods that should not be delegated here (we define special - # versions of them explicitly below). - MUST_NOT_DEFINE = %w[to_a to_ary partition * <<] - - # List of delegated methods that return new array values which need - # wrapping. - SPECIAL_RETURN = %w[ - map collect sort sort_by select find_all reject grep - compact flatten uniq values_at - + - & | - ] - - DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).map(&:to_s).sort.uniq - - # Now do the delegation. - DELEGATING_METHODS.each do |sym| - if SPECIAL_RETURN.include?(sym) - ln = __LINE__ + 1 - class_eval %{ - def #{sym}(*args, &block) - resolve - result = @items.send(:#{sym}, *args, &block) - self.class.new.import(result) - end - }, __FILE__, ln - else - ln = __LINE__ + 1 - class_eval %{ - def #{sym}(*args, &block) - resolve - result = @items.send(:#{sym}, *args, &block) - result.object_id == @items.object_id ? self : result - end - }, __FILE__, ln - end - end - - GLOB_PATTERN = %r{[*?\[\{]} - - # Create a file list from the globbable patterns given. If you wish to - # perform multiple includes or excludes at object build time, use the - # "yield self" pattern. - # - # Example: - # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb') - # - # pkg_files = FileList.new('lib/**/*') do |fl| - # fl.exclude(/\bCVS\b/) - # end - # - def initialize(*patterns) - @pending_add = [] - @pending = false - @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup - @exclude_procs = DEFAULT_IGNORE_PROCS.dup - @items = [] - patterns.each { |pattern| include(pattern) } - yield self if block_given? - end - - # Add file names defined by glob patterns to the file list. If an array - # is given, add each element of the array. - # - # Example: - # file_list.include("*.java", "*.cfg") - # file_list.include %w( math.c lib.h *.o ) - # - def include(*filenames) - # TODO: check for pending - filenames.each do |fn| - if fn.respond_to? :to_ary - include(*fn.to_ary) - else - @pending_add << Rake.from_pathname(fn) - end - end - @pending = true - self - end - alias :add :include - - # Register a list of file name patterns that should be excluded from the - # list. Patterns may be regular expressions, glob patterns or regular - # strings. In addition, a block given to exclude will remove entries that - # return true when given to the block. - # - # Note that glob patterns are expanded against the file system. If a file - # is explicitly added to a file list, but does not exist in the file - # system, then an glob pattern in the exclude list will not exclude the - # file. - # - # Examples: - # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c'] - # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c'] - # - # If "a.c" is a file, then ... - # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c'] - # - # If "a.c" is not a file, then ... - # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c'] - # - def exclude(*patterns, &block) - patterns.each do |pat| - if pat.respond_to? :to_ary - exclude(*pat.to_ary) - else - @exclude_patterns << Rake.from_pathname(pat) - end - end - @exclude_procs << block if block_given? - resolve_exclude unless @pending - self - end - - # Clear all the exclude patterns so that we exclude nothing. - def clear_exclude - @exclude_patterns = [] - @exclude_procs = [] - self - end - - # A FileList is equal through array equality. - def ==(array) - to_ary == array - end - - # Return the internal array object. - def to_a - resolve - @items - end - - # Return the internal array object. - def to_ary - to_a - end - - # Lie about our class. - def is_a?(klass) - klass == Array || super(klass) - end - alias kind_of? is_a? - - # Redefine * to return either a string or a new file list. - def *(other) - result = @items * other - case result - when Array - self.class.new.import(result) - else - result - end - end - - def <<(obj) - resolve - @items << Rake.from_pathname(obj) - self - end - - # Resolve all the pending adds now. - def resolve - if @pending - @pending = false - @pending_add.each do |fn| resolve_add(fn) end - @pending_add = [] - resolve_exclude - end - self - end - - def resolve_add(fn) # :nodoc: - case fn - when GLOB_PATTERN - add_matching(fn) - else - self << fn - end - end - private :resolve_add - - def resolve_exclude # :nodoc: - reject! { |fn| excluded_from_list?(fn) } - self - end - private :resolve_exclude - - # Return a new FileList with the results of running +sub+ against each - # element of the original list. - # - # Example: - # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o'] - # - def sub(pat, rep) - inject(self.class.new) { |res, fn| res << fn.sub(pat, rep) } - end - - # Return a new FileList with the results of running +gsub+ against each - # element of the original list. - # - # Example: - # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\") - # => ['lib\\test\\file', 'x\\y'] - # - def gsub(pat, rep) - inject(self.class.new) { |res, fn| res << fn.gsub(pat, rep) } - end - - # Same as +sub+ except that the original file list is modified. - def sub!(pat, rep) - each_with_index { |fn, i| self[i] = fn.sub(pat, rep) } - self - end - - # Same as +gsub+ except that the original file list is modified. - def gsub!(pat, rep) - each_with_index { |fn, i| self[i] = fn.gsub(pat, rep) } - self - end - - # Apply the pathmap spec to each of the included file names, returning a - # new file list with the modified paths. (See String#pathmap for - # details.) - def pathmap(spec=nil, &block) - collect { |fn| fn.pathmap(spec, &block) } - end - - # Return a new FileList with String#ext method applied to - # each member of the array. - # - # This method is a shortcut for: - # - # array.collect { |item| item.ext(newext) } - # - # +ext+ is a user added method for the Array class. - def ext(newext="") - collect { |fn| fn.ext(newext) } - end - - # Grep each of the files in the filelist using the given pattern. If a - # block is given, call the block on each matching line, passing the file - # name, line number, and the matching line of text. If no block is given, - # a standard emacs style file:linenumber:line message will be printed to - # standard out. Returns the number of matched items. - def egrep(pattern, *options) - matched = 0 - each do |fn| - begin - File.open(fn, "r", *options) do |inf| - count = 0 - inf.each do |line| - count += 1 - if pattern.match(line) - matched += 1 - if block_given? - yield fn, count, line - else - puts "#{fn}:#{count}:#{line}" - end - end - end - end - rescue StandardError => ex - $stderr.puts "Error while processing '#{fn}': #{ex}" - end - end - matched - end - - # Return a new file list that only contains file names from the current - # file list that exist on the file system. - def existing - select { |fn| File.exist?(fn) }.uniq - end - - # Modify the current file list so that it contains only file name that - # exist on the file system. - def existing! - resolve - @items = @items.select { |fn| File.exist?(fn) }.uniq - self - end - - # FileList version of partition. Needed because the nested arrays should - # be FileLists in this version. - def partition(&block) # :nodoc: - resolve - result = @items.partition(&block) - [ - self.class.new.import(result[0]), - self.class.new.import(result[1]), - ] - end - - # Convert a FileList to a string by joining all elements with a space. - def to_s - resolve - self.join(" ") - end - - # Add matching glob patterns. - def add_matching(pattern) - self.class.glob(pattern).each do |fn| - self << fn unless excluded_from_list?(fn) - end - end - private :add_matching - - # Should the given file name be excluded from the list? - # - # NOTE: This method was formerly named "exclude?", but Rails - # introduced an exclude? method as an array method and setup a - # conflict with file list. We renamed the method to avoid - # confusion. If you were using "FileList#exclude?" in your user - # code, you will need to update. - def excluded_from_list?(fn) - return true if @exclude_patterns.any? do |pat| - case pat - when Regexp - fn =~ pat - when GLOB_PATTERN - flags = File::FNM_PATHNAME - # Ruby <= 1.9.3 does not support File::FNM_EXTGLOB - flags |= File::FNM_EXTGLOB if defined? File::FNM_EXTGLOB - File.fnmatch?(pat, fn, flags) - else - fn == pat - end - end - @exclude_procs.any? { |p| p.call(fn) } - end - - DEFAULT_IGNORE_PATTERNS = [ - /(^|[\/\\])CVS([\/\\]|$)/, - /(^|[\/\\])\.svn([\/\\]|$)/, - /\.bak$/, - /~$/ - ] - DEFAULT_IGNORE_PROCS = [ - proc { |fn| fn =~ /(^|[\/\\])core$/ && !File.directory?(fn) } - ] - - def import(array) # :nodoc: - @items = array - self - end - - class << self - # Create a new file list including the files listed. Similar to: - # - # FileList.new(*args) - def [](*args) - new(*args) - end - - # Get a sorted list of files matching the pattern. This method - # should be preferred to Dir[pattern] and Dir.glob(pattern) because - # the files returned are guaranteed to be sorted. - def glob(pattern, *args) - Dir.glob(pattern, *args).sort - end - end - end -end - -module Rake - class << self - - # Yield each file or directory component. - def each_dir_parent(dir) # :nodoc: - old_length = nil - while dir != "." && dir.length != old_length - yield(dir) - old_length = dir.length - dir = File.dirname(dir) - end - end - - # Convert Pathname and Pathname-like objects to strings; - # leave everything else alone - def from_pathname(path) # :nodoc: - path = path.to_path if path.respond_to?(:to_path) - path = path.to_str if path.respond_to?(:to_str) - path - end - end -end # module Rake diff --git a/ruby/gems/rake-13.0.1/lib/rake/file_task.rb b/ruby/gems/rake-13.0.1/lib/rake/file_task.rb deleted file mode 100644 index db790e39f..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/file_task.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true -require "rake/task" -require "rake/early_time" - -module Rake - - # A FileTask is a task that includes time based dependencies. If any of a - # FileTask's prerequisites have a timestamp that is later than the file - # represented by this task, then the file must be rebuilt (using the - # supplied actions). - # - class FileTask < Task - - # Is this file task needed? Yes if it doesn't exist, or if its time stamp - # is out of date. - def needed? - !File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all - end - - # Time stamp for file task. - def timestamp - if File.exist?(name) - File.mtime(name.to_s) - else - Rake::LATE - end - end - - private - - # Are there any prerequisites with a later time than the given time stamp? - def out_of_date?(stamp) - all_prerequisite_tasks.any? { |prereq| - prereq_task = application[prereq, @scope] - if prereq_task.instance_of?(Rake::FileTask) - prereq_task.timestamp > stamp || @application.options.build_all - else - prereq_task.timestamp > stamp - end - } - end - - # ---------------------------------------------------------------- - # Task class methods. - # - class << self - # Apply the scope to the task name according to the rules for this kind - # of task. File based tasks ignore the scope when creating the name. - def scope_name(scope, task_name) - Rake.from_pathname(task_name) - end - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/file_utils.rb b/ruby/gems/rake-13.0.1/lib/rake/file_utils.rb deleted file mode 100644 index e979eedb2..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/file_utils.rb +++ /dev/null @@ -1,134 +0,0 @@ -# frozen_string_literal: true -require "rbconfig" -require "fileutils" - -#-- -# This a FileUtils extension that defines several additional commands to be -# added to the FileUtils utility functions. -module FileUtils - # Path to the currently running Ruby program - RUBY = ENV["RUBY"] || File.join( - RbConfig::CONFIG["bindir"], - RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]). - sub(/.*\s.*/m, '"\&"') - - # Run the system command +cmd+. If multiple arguments are given the command - # is run directly (without the shell, same semantics as Kernel::exec and - # Kernel::system). - # - # It is recommended you use the multiple argument form over interpolating - # user input for both usability and security reasons. With the multiple - # argument form you can easily process files with spaces or other shell - # reserved characters in them. With the multiple argument form your rake - # tasks are not vulnerable to users providing an argument like - # ; rm # -rf /. - # - # If a block is given, upon command completion the block is called with an - # OK flag (true on a zero exit status) and a Process::Status object. - # Without a block a RuntimeError is raised when the command exits non-zero. - # - # Examples: - # - # sh 'ls -ltr' - # - # sh 'ls', 'file with spaces' - # - # # check exit status after command runs - # sh %{grep pattern file} do |ok, res| - # if !ok - # puts "pattern not found (status = #{res.exitstatus})" - # end - # end - # - def sh(*cmd, &block) - options = (Hash === cmd.last) ? cmd.pop : {} - shell_runner = block_given? ? block : create_shell_runner(cmd) - - set_verbose_option(options) - verbose = options.delete :verbose - noop = options.delete(:noop) || Rake::FileUtilsExt.nowrite_flag - - Rake.rake_output_message sh_show_command cmd if verbose - - unless noop - res = (Hash === cmd.last) ? system(*cmd) : system(*cmd, options) - status = $? - status = Rake::PseudoStatus.new(1) if !res && status.nil? - shell_runner.call(res, status) - end - end - - def create_shell_runner(cmd) # :nodoc: - show_command = sh_show_command cmd - show_command = show_command[0, 42] + "..." unless $trace - - lambda do |ok, status| - ok or - fail "Command failed with status (#{status.exitstatus}): " + - "[#{show_command}]" - end - end - private :create_shell_runner - - def sh_show_command(cmd) # :nodoc: - cmd = cmd.dup - - if Hash === cmd.first - env = cmd.first - env = env.map { |name, value| "#{name}=#{value}" }.join " " - cmd[0] = env - end - - cmd.join " " - end - private :sh_show_command - - def set_verbose_option(options) # :nodoc: - unless options.key? :verbose - options[:verbose] = - (Rake::FileUtilsExt.verbose_flag == Rake::FileUtilsExt::DEFAULT) || - Rake::FileUtilsExt.verbose_flag - end - end - private :set_verbose_option - - # Run a Ruby interpreter with the given arguments. - # - # Example: - # ruby %{-pe '$_.upcase!' 1 - sh(RUBY, *args, **options, &block) - else - sh("#{RUBY} #{args.first}", **options, &block) - end - end - - LN_SUPPORTED = [true] - - # Attempt to do a normal file link, but fall back to a copy if the link - # fails. - def safe_ln(*args, **options) - if LN_SUPPORTED[0] - begin - return options.empty? ? ln(*args) : ln(*args, **options) - rescue StandardError, NotImplementedError - LN_SUPPORTED[0] = false - end - end - options.empty? ? cp(*args) : cp(*args, **options) - end - - # Split a file path into individual directory names. - # - # Example: - # split_all("a/b/c") => ['a', 'b', 'c'] - # - def split_all(path) - head, tail = File.split(path) - return [tail] if head == "." || tail == "/" - return [head, tail] if head == "/" - return split_all(head) + [tail] - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/file_utils_ext.rb b/ruby/gems/rake-13.0.1/lib/rake/file_utils_ext.rb deleted file mode 100644 index e91ad595f..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/file_utils_ext.rb +++ /dev/null @@ -1,134 +0,0 @@ -# frozen_string_literal: true -require "rake/file_utils" - -module Rake - # - # FileUtilsExt provides a custom version of the FileUtils methods - # that respond to the verbose and nowrite - # commands. - # - module FileUtilsExt - include FileUtils - - class << self - attr_accessor :verbose_flag, :nowrite_flag - end - - DEFAULT = Object.new - - FileUtilsExt.verbose_flag = DEFAULT - FileUtilsExt.nowrite_flag = false - - FileUtils.commands.each do |name| - opts = FileUtils.options_of name - default_options = [] - if opts.include?("verbose") - default_options << "verbose: FileUtilsExt.verbose_flag" - end - if opts.include?("noop") - default_options << "noop: FileUtilsExt.nowrite_flag" - end - - next if default_options.empty? - module_eval(<<-EOS, __FILE__, __LINE__ + 1) - def #{name}(*args, **options, &block) - super(*args, - #{default_options.join(', ')}, - **options, &block) - end - EOS - end - - # Get/set the verbose flag controlling output from the FileUtils - # utilities. If verbose is true, then the utility method is - # echoed to standard output. - # - # Examples: - # verbose # return the current value of the - # # verbose flag - # verbose(v) # set the verbose flag to _v_. - # verbose(v) { code } # Execute code with the verbose flag set - # # temporarily to _v_. Return to the - # # original value when code is done. - def verbose(value=nil) - oldvalue = FileUtilsExt.verbose_flag - FileUtilsExt.verbose_flag = value unless value.nil? - if block_given? - begin - yield - ensure - FileUtilsExt.verbose_flag = oldvalue - end - end - FileUtilsExt.verbose_flag - end - - # Get/set the nowrite flag controlling output from the FileUtils - # utilities. If verbose is true, then the utility method is - # echoed to standard output. - # - # Examples: - # nowrite # return the current value of the - # # nowrite flag - # nowrite(v) # set the nowrite flag to _v_. - # nowrite(v) { code } # Execute code with the nowrite flag set - # # temporarily to _v_. Return to the - # # original value when code is done. - def nowrite(value=nil) - oldvalue = FileUtilsExt.nowrite_flag - FileUtilsExt.nowrite_flag = value unless value.nil? - if block_given? - begin - yield - ensure - FileUtilsExt.nowrite_flag = oldvalue - end - end - oldvalue - end - - # Use this function to prevent potentially destructive ruby code - # from running when the :nowrite flag is set. - # - # Example: - # - # when_writing("Building Project") do - # project.build - # end - # - # The following code will build the project under normal - # conditions. If the nowrite(true) flag is set, then the example - # will print: - # - # DRYRUN: Building Project - # - # instead of actually building the project. - # - def when_writing(msg=nil) - if FileUtilsExt.nowrite_flag - $stderr.puts "DRYRUN: #{msg}" if msg - else - yield - end - end - - # Send the message to the default rake output (which is $stderr). - def rake_output_message(message) - $stderr.puts(message) - end - - # Check that the options do not contain options not listed in - # +optdecl+. An ArgumentError exception is thrown if non-declared - # options are found. - def rake_check_options(options, *optdecl) - h = options.dup - optdecl.each do |name| - h.delete name - end - raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless - h.empty? - end - - extend self - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/invocation_chain.rb b/ruby/gems/rake-13.0.1/lib/rake/invocation_chain.rb deleted file mode 100644 index 44a995496..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/invocation_chain.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true -module Rake - - # InvocationChain tracks the chain of task invocations to detect - # circular dependencies. - class InvocationChain < LinkedList - - # Is the invocation already in the chain? - def member?(invocation) - head == invocation || tail.member?(invocation) - end - - # Append an invocation to the chain of invocations. It is an error - # if the invocation already listed. - def append(invocation) - if member?(invocation) - fail RuntimeError, "Circular dependency detected: #{to_s} => #{invocation}" - end - conj(invocation) - end - - # Convert to string, ie: TOP => invocation => invocation - def to_s - "#{prefix}#{head}" - end - - # Class level append. - def self.append(invocation, chain) - chain.append(invocation) - end - - private - - def prefix - "#{tail} => " - end - - # Null object for an empty chain. - class EmptyInvocationChain < LinkedList::EmptyLinkedList - @parent = InvocationChain - - def member?(obj) - false - end - - def append(invocation) - conj(invocation) - end - - def to_s - "TOP" - end - end - - EMPTY = EmptyInvocationChain.new - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/invocation_exception_mixin.rb b/ruby/gems/rake-13.0.1/lib/rake/invocation_exception_mixin.rb deleted file mode 100644 index b0d307a48..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/invocation_exception_mixin.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true -module Rake - module InvocationExceptionMixin - # Return the invocation chain (list of Rake tasks) that were in - # effect when this exception was detected by rake. May be null if - # no tasks were active. - def chain - @rake_invocation_chain ||= nil - end - - # Set the invocation chain in effect when this exception was - # detected. - def chain=(value) - @rake_invocation_chain = value - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/late_time.rb b/ruby/gems/rake-13.0.1/lib/rake/late_time.rb deleted file mode 100644 index 8fe024943..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/late_time.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true -module Rake - # LateTime is a fake timestamp that occurs _after_ any other time value. - class LateTime - include Comparable - include Singleton - - def <=>(other) - 1 - end - - def to_s - "" - end - end - - LATE = LateTime.instance -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/linked_list.rb b/ruby/gems/rake-13.0.1/lib/rake/linked_list.rb deleted file mode 100644 index 11fa46f0d..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/linked_list.rb +++ /dev/null @@ -1,112 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Polylithic linked list structure used to implement several data - # structures in Rake. - class LinkedList - include Enumerable - attr_reader :head, :tail - - # Polymorphically add a new element to the head of a list. The - # type of head node will be the same list type as the tail. - def conj(item) - self.class.cons(item, self) - end - - # Is the list empty? - # .make guards against a list being empty making any instantiated LinkedList - # object not empty by default - # You should consider overriding this method if you implement your own .make method - def empty? - false - end - - # Lists are structurally equivalent. - def ==(other) - current = self - while !current.empty? && !other.empty? - return false if current.head != other.head - current = current.tail - other = other.tail - end - current.empty? && other.empty? - end - - # Convert to string: LL(item, item...) - def to_s - items = map(&:to_s).join(", ") - "LL(#{items})" - end - - # Same as +to_s+, but with inspected items. - def inspect - items = map(&:inspect).join(", ") - "LL(#{items})" - end - - # For each item in the list. - def each - current = self - while !current.empty? - yield(current.head) - current = current.tail - end - self - end - - # Make a list out of the given arguments. This method is - # polymorphic - def self.make(*args) - # return an EmptyLinkedList if there are no arguments - return empty if !args || args.empty? - - # build a LinkedList by starting at the tail and iterating - # through each argument - # inject takes an EmptyLinkedList to start - args.reverse.inject(empty) do |list, item| - list = cons(item, list) - list # return the newly created list for each item in the block - end - end - - # Cons a new head onto the tail list. - def self.cons(head, tail) - new(head, tail) - end - - # The standard empty list class for the given LinkedList class. - def self.empty - self::EMPTY - end - - protected - - def initialize(head, tail=EMPTY) - @head = head - @tail = tail - end - - # Represent an empty list, using the Null Object Pattern. - # - # When inheriting from the LinkedList class, you should implement - # a type specific Empty class as well. Make sure you set the class - # instance variable @parent to the associated list class (this - # allows conj, cons and make to work polymorphically). - class EmptyLinkedList < LinkedList - @parent = LinkedList - - def initialize - end - - def empty? - true - end - - def self.cons(head, tail) - @parent.cons(head, tail) - end - end - - EMPTY = EmptyLinkedList.new - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/loaders/makefile.rb b/ruby/gems/rake-13.0.1/lib/rake/loaders/makefile.rb deleted file mode 100644 index 46f4beaad..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/loaders/makefile.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Makefile loader to be used with the import file loader. Use this to - # import dependencies from make dependency tools: - # - # require 'rake/loaders/makefile' - # - # file ".depends.mf" => [SRC_LIST] do |t| - # sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" - # end - # - # import ".depends.mf" - # - # See {Importing Dependencies}[link:doc/rakefile_rdoc.html#label-Importing+Dependencies] - # for further details. - - class MakefileLoader - include Rake::DSL - - SPACE_MARK = "\0" # :nodoc: - - # Load the makefile dependencies in +fn+. - def load(fn) # :nodoc: - lines = File.read fn - lines.gsub!(/\\ /, SPACE_MARK) - lines.gsub!(/#[^\n]*\n/m, "") - lines.gsub!(/\\\n/, " ") - lines.each_line do |line| - process_line(line) - end - end - - private - - # Process one logical line of makefile data. - def process_line(line) # :nodoc: - file_tasks, args = line.split(":", 2) - return if args.nil? - dependents = args.split.map { |d| respace(d) } - file_tasks.scan(/\S+/) do |file_task| - file_task = respace(file_task) - file file_task => dependents - end - end - - def respace(str) # :nodoc: - str.tr SPACE_MARK, " " - end - end - - # Install the handler - Rake.application.add_loader("mf", MakefileLoader.new) -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/multi_task.rb b/ruby/gems/rake-13.0.1/lib/rake/multi_task.rb deleted file mode 100644 index 3ae363cbe..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/multi_task.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Same as a regular task, but the immediate prerequisites are done in - # parallel using Ruby threads. - # - class MultiTask < Task - private - - def invoke_prerequisites(task_args, invocation_chain) # :nodoc: - invoke_prerequisites_concurrently(task_args, invocation_chain) - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/name_space.rb b/ruby/gems/rake-13.0.1/lib/rake/name_space.rb deleted file mode 100644 index 32f8139fc..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/name_space.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true -## -# The NameSpace class will lookup task names in the scope defined by a -# +namespace+ command. - -class Rake::NameSpace - - ## - # Create a namespace lookup object using the given task manager - # and the list of scopes. - - def initialize(task_manager, scope_list) - @task_manager = task_manager - @scope = scope_list.dup - end - - ## - # Lookup a task named +name+ in the namespace. - - def [](name) - @task_manager.lookup(name, @scope) - end - - ## - # The scope of the namespace (a LinkedList) - - def scope - @scope.dup - end - - ## - # Return the list of tasks defined in this and nested namespaces. - - def tasks - @task_manager.tasks_in_scope(@scope) - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/packagetask.rb b/ruby/gems/rake-13.0.1/lib/rake/packagetask.rb deleted file mode 100644 index aeff81c29..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/packagetask.rb +++ /dev/null @@ -1,222 +0,0 @@ -# frozen_string_literal: true -# Define a package task library to aid in the definition of -# redistributable package files. - -require "rake" -require "rake/tasklib" - -module Rake - - # Create a packaging task that will package the project into - # distributable files (e.g zip archive or tar files). - # - # The PackageTask will create the following targets: - # - # +:package+ :: - # Create all the requested package files. - # - # +:clobber_package+ :: - # Delete all the package files. This target is automatically - # added to the main clobber target. - # - # +:repackage+ :: - # Rebuild the package files from scratch, even if they are not out - # of date. - # - # "package_dir/name-version.tgz" :: - # Create a gzipped tar package (if need_tar is true). - # - # "package_dir/name-version.tar.gz" :: - # Create a gzipped tar package (if need_tar_gz is true). - # - # "package_dir/name-version.tar.bz2" :: - # Create a bzip2'd tar package (if need_tar_bz2 is true). - # - # "package_dir/name-version.zip" :: - # Create a zip package archive (if need_zip is true). - # - # Example: - # - # Rake::PackageTask.new("rake", "1.2.3") do |p| - # p.need_tar = true - # p.package_files.include("lib/**/*.rb") - # end - # - class PackageTask < TaskLib - # Name of the package (from the GEM Spec). - attr_accessor :name - - # Version of the package (e.g. '1.3.2'). - attr_accessor :version - - # Directory used to store the package files (default is 'pkg'). - attr_accessor :package_dir - - # True if a gzipped tar file (tgz) should be produced (default is - # false). - attr_accessor :need_tar - - # True if a gzipped tar file (tar.gz) should be produced (default - # is false). - attr_accessor :need_tar_gz - - # True if a bzip2'd tar file (tar.bz2) should be produced (default - # is false). - attr_accessor :need_tar_bz2 - - # True if a xz'd tar file (tar.xz) should be produced (default is false) - attr_accessor :need_tar_xz - - # True if a zip file should be produced (default is false) - attr_accessor :need_zip - - # List of files to be included in the package. - attr_accessor :package_files - - # Tar command for gzipped or bzip2ed archives. The default is 'tar'. - attr_accessor :tar_command - - # Zip command for zipped archives. The default is 'zip'. - attr_accessor :zip_command - - # True if parent directory should be omited (default is false) - attr_accessor :without_parent_dir - - # Create a Package Task with the given name and version. Use +:noversion+ - # as the version to build a package without a version or to provide a - # fully-versioned package name. - - def initialize(name=nil, version=nil) - init(name, version) - yield self if block_given? - define unless name.nil? - end - - # Initialization that bypasses the "yield self" and "define" step. - def init(name, version) - @name = name - @version = version - @package_files = Rake::FileList.new - @package_dir = "pkg" - @need_tar = false - @need_tar_gz = false - @need_tar_bz2 = false - @need_tar_xz = false - @need_zip = false - @tar_command = "tar" - @zip_command = "zip" - @without_parent_dir = false - end - - # Create the tasks defined by this task library. - def define - fail "Version required (or :noversion)" if @version.nil? - @version = nil if :noversion == @version - - desc "Build all the packages" - task :package - - desc "Force a rebuild of the package files" - task repackage: [:clobber_package, :package] - - desc "Remove package products" - task :clobber_package do - rm_r package_dir rescue nil - end - - task clobber: [:clobber_package] - - [ - [need_tar, tgz_file, "z"], - [need_tar_gz, tar_gz_file, "z"], - [need_tar_bz2, tar_bz2_file, "j"], - [need_tar_xz, tar_xz_file, "J"] - ].each do |need, file, flag| - if need - task package: ["#{package_dir}/#{file}"] - file "#{package_dir}/#{file}" => - [package_dir_path] + package_files do - chdir(working_dir) { sh @tar_command, "#{flag}cvf", file, target_dir } - mv "#{package_dir_path}/#{target_dir}", package_dir if without_parent_dir - end - end - end - - if need_zip - task package: ["#{package_dir}/#{zip_file}"] - file "#{package_dir}/#{zip_file}" => - [package_dir_path] + package_files do - chdir(working_dir) { sh @zip_command, "-r", zip_file, target_dir } - mv "#{package_dir_path}/#{zip_file}", package_dir if without_parent_dir - end - end - - directory package_dir_path => @package_files do - @package_files.each do |fn| - f = File.join(package_dir_path, fn) - fdir = File.dirname(f) - mkdir_p(fdir) unless File.exist?(fdir) - if File.directory?(fn) - mkdir_p(f) - else - rm_f f - safe_ln(fn, f) - end - end - end - self - end - - # The name of this package - - def package_name - @version ? "#{@name}-#{@version}" : @name - end - - # The directory this package will be built in - - def package_dir_path - "#{package_dir}/#{package_name}" - end - - # The package name with .tgz added - - def tgz_file - "#{package_name}.tgz" - end - - # The package name with .tar.gz added - - def tar_gz_file - "#{package_name}.tar.gz" - end - - # The package name with .tar.bz2 added - - def tar_bz2_file - "#{package_name}.tar.bz2" - end - - # The package name with .tar.xz added - - def tar_xz_file - "#{package_name}.tar.xz" - end - - # The package name with .zip added - - def zip_file - "#{package_name}.zip" - end - - def working_dir - without_parent_dir ? package_dir_path : package_dir - end - - # target directory relative to working_dir - def target_dir - without_parent_dir ? "." : package_name - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/phony.rb b/ruby/gems/rake-13.0.1/lib/rake/phony.rb deleted file mode 100644 index 8caa5de17..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/phony.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true -# Defines a :phony task that you can use as a dependency. This allows -# file-based tasks to use non-file-based tasks as prerequisites -# without forcing them to rebuild. -# -# See FileTask#out_of_date? and Task#timestamp for more info. - -require "rake" - -task :phony - -Rake::Task[:phony].tap do |task| - def task.timestamp # :nodoc: - Time.at 0 - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/private_reader.rb b/ruby/gems/rake-13.0.1/lib/rake/private_reader.rb deleted file mode 100644 index 2815ce643..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/private_reader.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Include PrivateReader to use +private_reader+. - module PrivateReader # :nodoc: all - - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - - # Declare a list of private accessors - def private_reader(*names) - attr_reader(*names) - private(*names) - end - end - - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/promise.rb b/ruby/gems/rake-13.0.1/lib/rake/promise.rb deleted file mode 100644 index f45af4f3a..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/promise.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: true -module Rake - - # A Promise object represents a promise to do work (a chore) in the - # future. The promise is created with a block and a list of - # arguments for the block. Calling value will return the value of - # the promised chore. - # - # Used by ThreadPool. - # - class Promise # :nodoc: all - NOT_SET = Object.new.freeze # :nodoc: - - attr_accessor :recorder - - # Create a promise to do the chore specified by the block. - def initialize(args, &block) - @mutex = Mutex.new - @result = NOT_SET - @error = NOT_SET - @args = args - @block = block - end - - # Return the value of this promise. - # - # If the promised chore is not yet complete, then do the work - # synchronously. We will wait. - def value - unless complete? - stat :sleeping_on, item_id: object_id - @mutex.synchronize do - stat :has_lock_on, item_id: object_id - chore - stat :releasing_lock_on, item_id: object_id - end - end - error? ? raise(@error) : @result - end - - # If no one else is working this promise, go ahead and do the chore. - def work - stat :attempting_lock_on, item_id: object_id - if @mutex.try_lock - stat :has_lock_on, item_id: object_id - chore - stat :releasing_lock_on, item_id: object_id - @mutex.unlock - else - stat :bailed_on, item_id: object_id - end - end - - private - - # Perform the chore promised - def chore - if complete? - stat :found_completed, item_id: object_id - return - end - stat :will_execute, item_id: object_id - begin - @result = @block.call(*@args) - rescue Exception => e - @error = e - end - stat :did_execute, item_id: object_id - discard - end - - # Do we have a result for the promise - def result? - !@result.equal?(NOT_SET) - end - - # Did the promise throw an error - def error? - !@error.equal?(NOT_SET) - end - - # Are we done with the promise - def complete? - result? || error? - end - - # free up these items for the GC - def discard - @args = nil - @block = nil - end - - # Record execution statistics if there is a recorder - def stat(*args) - @recorder.call(*args) if @recorder - end - - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/pseudo_status.rb b/ruby/gems/rake-13.0.1/lib/rake/pseudo_status.rb deleted file mode 100644 index 8b3c98949..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/pseudo_status.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true -module Rake - - ## - # Exit status class for times the system just gives us a nil. - class PseudoStatus # :nodoc: all - attr_reader :exitstatus - - def initialize(code=0) - @exitstatus = code - end - - def to_i - @exitstatus << 8 - end - - def >>(n) - to_i >> n - end - - def stopped? - false - end - - def exited? - true - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/rake_module.rb b/ruby/gems/rake-13.0.1/lib/rake/rake_module.rb deleted file mode 100644 index 03c295624..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/rake_module.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true -require "rake/application" - -module Rake - - class << self - # Current Rake Application - def application - @application ||= Rake::Application.new - end - - # Set the current Rake application object. - def application=(app) - @application = app - end - - def suggested_thread_count # :nodoc: - @cpu_count ||= Rake::CpuCounter.count - @cpu_count + 4 - end - - # Return the original directory where the Rake application was started. - def original_dir - application.original_dir - end - - # Load a rakefile. - def load_rakefile(path) - load(path) - end - - # Add files to the rakelib list - def add_rakelib(*files) - application.options.rakelib ||= [] - application.options.rakelib.concat(files) - end - - # Make +block_application+ the default rake application inside a block so - # you can load rakefiles into a different application. - # - # This is useful when you want to run rake tasks inside a library without - # running rake in a sub-shell. - # - # Example: - # - # Dir.chdir 'other/directory' - # - # other_rake = Rake.with_application do |rake| - # rake.load_rakefile - # end - # - # puts other_rake.tasks - - def with_application(block_application = Rake::Application.new) - orig_application = Rake.application - - Rake.application = block_application - - yield block_application - - block_application - ensure - Rake.application = orig_application - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/rake_test_loader.rb b/ruby/gems/rake-13.0.1/lib/rake/rake_test_loader.rb deleted file mode 100644 index f0f7772ba..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/rake_test_loader.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true -require "rake" - -# Load the test files from the command line. -argv = ARGV.select do |argument| - begin - case argument - when /^-/ then - argument - when /\*/ then - FileList[argument].to_a.each do |file| - require File.expand_path file - end - - false - else - require File.expand_path argument - - false - end - rescue LoadError => e - raise unless e.path - abort "\nFile does not exist: #{e.path}\n\n" - end -end - -ARGV.replace argv diff --git a/ruby/gems/rake-13.0.1/lib/rake/rule_recursion_overflow_error.rb b/ruby/gems/rake-13.0.1/lib/rake/rule_recursion_overflow_error.rb deleted file mode 100644 index a51e77489..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/rule_recursion_overflow_error.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Error indicating a recursion overflow error in task selection. - class RuleRecursionOverflowError < StandardError - def initialize(*args) - super - @targets = [] - end - - def add_target(target) - @targets << target - end - - def message - super + ": [" + @targets.reverse.join(" => ") + "]" - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/scope.rb b/ruby/gems/rake-13.0.1/lib/rake/scope.rb deleted file mode 100644 index fc1eb6c3a..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/scope.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true -module Rake - class Scope < LinkedList # :nodoc: all - - # Path for the scope. - def path - map(&:to_s).reverse.join(":") - end - - # Path for the scope + the named path. - def path_with_task_name(task_name) - "#{path}:#{task_name}" - end - - # Trim +n+ innermost scope levels from the scope. In no case will - # this trim beyond the toplevel scope. - def trim(n) - result = self - while n > 0 && !result.empty? - result = result.tail - n -= 1 - end - result - end - - # Scope lists always end with an EmptyScope object. See Null - # Object Pattern) - class EmptyScope < EmptyLinkedList - @parent = Scope - - def path - "" - end - - def path_with_task_name(task_name) - task_name - end - end - - # Singleton null object for an empty scope. - EMPTY = EmptyScope.new - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/task.rb b/ruby/gems/rake-13.0.1/lib/rake/task.rb deleted file mode 100644 index ec2c756e0..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/task.rb +++ /dev/null @@ -1,434 +0,0 @@ -# frozen_string_literal: true -require "rake/invocation_exception_mixin" - -module Rake - - ## - # A Task is the basic unit of work in a Rakefile. Tasks have associated - # actions (possibly more than one) and a list of prerequisites. When - # invoked, a task will first ensure that all of its prerequisites have an - # opportunity to run and then it will execute its own actions. - # - # Tasks are not usually created directly using the new method, but rather - # use the +file+ and +task+ convenience methods. - # - class Task - # List of prerequisites for a task. - attr_reader :prerequisites - alias prereqs prerequisites - - # List of order only prerequisites for a task. - attr_reader :order_only_prerequisites - - # List of actions attached to a task. - attr_reader :actions - - # Application owning this task. - attr_accessor :application - - # Array of nested namespaces names used for task lookup by this task. - attr_reader :scope - - # File/Line locations of each of the task definitions for this - # task (only valid if the task was defined with the detect - # location option set). - attr_reader :locations - - # Has this task already been invoked? Already invoked tasks - # will be skipped unless you reenable them. - attr_reader :already_invoked - - # Return task name - def to_s - name - end - - def inspect # :nodoc: - "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>" - end - - # List of sources for task. - attr_writer :sources - def sources - if defined?(@sources) - @sources - else - prerequisites - end - end - - # List of prerequisite tasks - def prerequisite_tasks - (prerequisites + order_only_prerequisites).map { |pre| lookup_prerequisite(pre) } - end - - def lookup_prerequisite(prerequisite_name) # :nodoc: - scoped_prerequisite_task = application[prerequisite_name, @scope] - if scoped_prerequisite_task == self - unscoped_prerequisite_task = application[prerequisite_name] - end - unscoped_prerequisite_task || scoped_prerequisite_task - end - private :lookup_prerequisite - - # List of all unique prerequisite tasks including prerequisite tasks' - # prerequisites. - # Includes self when cyclic dependencies are found. - def all_prerequisite_tasks - seen = {} - collect_prerequisites(seen) - seen.values - end - - def collect_prerequisites(seen) # :nodoc: - prerequisite_tasks.each do |pre| - next if seen[pre.name] - seen[pre.name] = pre - pre.collect_prerequisites(seen) - end - end - protected :collect_prerequisites - - # First source from a rule (nil if no sources) - def source - sources.first - end - - # Create a task named +task_name+ with no actions or prerequisites. Use - # +enhance+ to add actions and prerequisites. - def initialize(task_name, app) - @name = task_name.to_s - @prerequisites = [] - @actions = [] - @already_invoked = false - @comments = [] - @lock = Monitor.new - @application = app - @scope = app.current_scope - @arg_names = nil - @locations = [] - @invocation_exception = nil - @order_only_prerequisites = [] - end - - # Enhance a task with prerequisites or actions. Returns self. - def enhance(deps=nil, &block) - @prerequisites |= deps if deps - @actions << block if block_given? - self - end - - # Name of the task, including any namespace qualifiers. - def name - @name.to_s - end - - # Name of task with argument list description. - def name_with_args # :nodoc: - if arg_description - "#{name}#{arg_description}" - else - name - end - end - - # Argument description (nil if none). - def arg_description # :nodoc: - @arg_names ? "[#{arg_names.join(',')}]" : nil - end - - # Name of arguments for this task. - def arg_names - @arg_names || [] - end - - # Reenable the task, allowing its tasks to be executed if the task - # is invoked again. - def reenable - @already_invoked = false - @invocation_exception = nil - end - - # Clear the existing prerequisites, actions, comments, and arguments of a rake task. - def clear - clear_prerequisites - clear_actions - clear_comments - clear_args - self - end - - # Clear the existing prerequisites of a rake task. - def clear_prerequisites - prerequisites.clear - self - end - - # Clear the existing actions on a rake task. - def clear_actions - actions.clear - self - end - - # Clear the existing comments on a rake task. - def clear_comments - @comments = [] - self - end - - # Clear the existing arguments on a rake task. - def clear_args - @arg_names = nil - self - end - - # Invoke the task if it is needed. Prerequisites are invoked first. - def invoke(*args) - task_args = TaskArguments.new(arg_names, args) - invoke_with_call_chain(task_args, InvocationChain::EMPTY) - end - - # Same as invoke, but explicitly pass a call chain to detect - # circular dependencies. - # - # If multiple tasks depend on this - # one in parallel, they will all fail if the first execution of - # this task fails. - def invoke_with_call_chain(task_args, invocation_chain) - new_chain = Rake::InvocationChain.append(self, invocation_chain) - @lock.synchronize do - begin - if application.options.trace - application.trace "** Invoke #{name} #{format_trace_flags}" - end - - if @already_invoked - if @invocation_exception - if application.options.trace - application.trace "** Previous invocation of #{name} failed #{format_trace_flags}" - end - raise @invocation_exception - else - return - end - end - - @already_invoked = true - - invoke_prerequisites(task_args, new_chain) - execute(task_args) if needed? - rescue Exception => ex - add_chain_to(ex, new_chain) - @invocation_exception = ex - raise ex - end - end - end - protected :invoke_with_call_chain - - def add_chain_to(exception, new_chain) # :nodoc: - exception.extend(InvocationExceptionMixin) unless - exception.respond_to?(:chain) - exception.chain = new_chain if exception.chain.nil? - end - private :add_chain_to - - # Invoke all the prerequisites of a task. - def invoke_prerequisites(task_args, invocation_chain) # :nodoc: - if application.options.always_multitask - invoke_prerequisites_concurrently(task_args, invocation_chain) - else - prerequisite_tasks.each { |p| - prereq_args = task_args.new_scope(p.arg_names) - p.invoke_with_call_chain(prereq_args, invocation_chain) - } - end - end - - # Invoke all the prerequisites of a task in parallel. - def invoke_prerequisites_concurrently(task_args, invocation_chain)# :nodoc: - futures = prerequisite_tasks.map do |p| - prereq_args = task_args.new_scope(p.arg_names) - application.thread_pool.future(p) do |r| - r.invoke_with_call_chain(prereq_args, invocation_chain) - end - end - # Iterate in reverse to improve performance related to thread waiting and switching - futures.reverse_each(&:value) - end - - # Format the trace flags for display. - def format_trace_flags - flags = [] - flags << "first_time" unless @already_invoked - flags << "not_needed" unless needed? - flags.empty? ? "" : "(" + flags.join(", ") + ")" - end - private :format_trace_flags - - # Execute the actions associated with this task. - def execute(args=nil) - args ||= EMPTY_TASK_ARGS - if application.options.dryrun - application.trace "** Execute (dry run) #{name}" - return - end - application.trace "** Execute #{name}" if application.options.trace - application.enhance_with_matching_rule(name) if @actions.empty? - if opts = Hash.try_convert(args) and !opts.empty? - @actions.each { |act| act.call(self, args, **opts)} - else - @actions.each { |act| act.call(self, args)} - end - end - - # Is this task needed? - def needed? - true - end - - # Timestamp for this task. Basic tasks return the current time for their - # time stamp. Other tasks can be more sophisticated. - def timestamp - Time.now - end - - # Add a description to the task. The description can consist of an option - # argument list (enclosed brackets) and an optional comment. - def add_description(description) - return unless description - comment = description.strip - add_comment(comment) if comment && !comment.empty? - end - - def comment=(comment) # :nodoc: - add_comment(comment) - end - - def add_comment(comment) # :nodoc: - return if comment.nil? - @comments << comment unless @comments.include?(comment) - end - private :add_comment - - # Full collection of comments. Multiple comments are separated by - # newlines. - def full_comment - transform_comments("\n") - end - - # First line (or sentence) of all comments. Multiple comments are - # separated by a "/". - def comment - transform_comments(" / ") { |c| first_sentence(c) } - end - - # Transform the list of comments as specified by the block and - # join with the separator. - def transform_comments(separator, &block) - if @comments.empty? - nil - else - block ||= lambda { |c| c } - @comments.map(&block).join(separator) - end - end - private :transform_comments - - # Get the first sentence in a string. The sentence is terminated - # by the first period, exclamation mark, or the end of the line. - # Decimal points do not count as periods. - def first_sentence(string) - string.split(/(?<=\w)(\.|!)[ \t]|(\.$|!)|\n/).first - end - private :first_sentence - - # Set the names of the arguments for this task. +args+ should be - # an array of symbols, one for each argument name. - def set_arg_names(args) - @arg_names = args.map(&:to_sym) - end - - # Return a string describing the internal state of a task. Useful for - # debugging. - def investigation - result = "------------------------------\n".dup - result << "Investigating #{name}\n" - result << "class: #{self.class}\n" - result << "task needed: #{needed?}\n" - result << "timestamp: #{timestamp}\n" - result << "pre-requisites: \n" - prereqs = prerequisite_tasks - prereqs.sort! { |a, b| a.timestamp <=> b.timestamp } - prereqs.each do |p| - result << "--#{p.name} (#{p.timestamp})\n" - end - latest_prereq = prerequisite_tasks.map(&:timestamp).max - result << "latest-prerequisite time: #{latest_prereq}\n" - result << "................................\n\n" - return result - end - - # Format dependencies parameter to pass to task. - def self.format_deps(deps) - deps = [deps] unless deps.respond_to?(:to_ary) - deps.map { |d| Rake.from_pathname(d).to_s } - end - - # Add order only dependencies. - def |(deps) - @order_only_prerequisites |= Task.format_deps(deps) - @prerequisites - self - end - - # ---------------------------------------------------------------- - # Rake Module Methods - # - class << self - - # Clear the task list. This cause rake to immediately forget all the - # tasks that have been assigned. (Normally used in the unit tests.) - def clear - Rake.application.clear - end - - # List of all defined tasks. - def tasks - Rake.application.tasks - end - - # Return a task with the given name. If the task is not currently - # known, try to synthesize one from the defined rules. If no rules are - # found, but an existing file matches the task name, assume it is a file - # task with no dependencies or actions. - def [](task_name) - Rake.application[task_name] - end - - # TRUE if the task name is already defined. - def task_defined?(task_name) - Rake.application.lookup(task_name) != nil - end - - # Define a task given +args+ and an option block. If a rule with the - # given name already exists, the prerequisites and actions are added to - # the existing task. Returns the defined task. - def define_task(*args, &block) - Rake.application.define_task(self, *args, &block) - end - - # Define a rule for synthesizing tasks. - def create_rule(*args, &block) - Rake.application.create_rule(*args, &block) - end - - # Apply the scope to the task name according to the rules for - # this kind of task. Generic tasks will accept the scope as - # part of the name. - def scope_name(scope, task_name) - scope.path_with_task_name(task_name) - end - - end # class << Rake::Task - end # class Rake::Task -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/task_argument_error.rb b/ruby/gems/rake-13.0.1/lib/rake/task_argument_error.rb deleted file mode 100644 index ef20076c6..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/task_argument_error.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -module Rake - - # Error indicating an ill-formed task declaration. - class TaskArgumentError < ArgumentError - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/task_arguments.rb b/ruby/gems/rake-13.0.1/lib/rake/task_arguments.rb deleted file mode 100644 index 0d3001afd..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/task_arguments.rb +++ /dev/null @@ -1,109 +0,0 @@ -# frozen_string_literal: true -module Rake - - ## - # TaskArguments manage the arguments passed to a task. - # - class TaskArguments - include Enumerable - - # Argument names - attr_reader :names - - # Create a TaskArgument object with a list of argument +names+ and a set - # of associated +values+. +parent+ is the parent argument object. - def initialize(names, values, parent=nil) - @names = names - @parent = parent - @hash = {} - @values = values - names.each_with_index { |name, i| - next if values[i].nil? || values[i] == "" - @hash[name.to_sym] = values[i] - } - end - - # Retrieve the complete array of sequential values - def to_a - @values.dup - end - - # Retrieve the list of values not associated with named arguments - def extras - @values[@names.length..-1] || [] - end - - # Create a new argument scope using the prerequisite argument - # names. - def new_scope(names) - values = names.map { |n| self[n] } - self.class.new(names, values + extras, self) - end - - # Find an argument value by name or index. - def [](index) - lookup(index.to_sym) - end - - # Specify a hash of default values for task arguments. Use the - # defaults only if there is no specific value for the given - # argument. - def with_defaults(defaults) - @hash = defaults.merge(@hash) - end - - # Enumerates the arguments and their values - def each(&block) - @hash.each(&block) - end - - # Extracts the argument values at +keys+ - def values_at(*keys) - keys.map { |k| lookup(k) } - end - - # Returns the value of the given argument via method_missing - def method_missing(sym, *args) - lookup(sym.to_sym) - end - - # Returns a Hash of arguments and their values - def to_hash - @hash.dup - end - - def to_s # :nodoc: - inspect - end - - def inspect # :nodoc: - inspection = @hash.map do |k,v| - "#{k.to_s}: #{v.to_s}" - end.join(", ") - - "#<#{self.class} #{inspection}>" - end - - # Returns true if +key+ is one of the arguments - def has_key?(key) - @hash.has_key?(key) - end - alias key? has_key? - - def fetch(*args, &block) - @hash.fetch(*args, &block) - end - - protected - - def lookup(name) # :nodoc: - if @hash.has_key?(name) - @hash[name] - elsif @parent - @parent.lookup(name) - end - end - end - - EMPTY_TASK_ARGS = TaskArguments.new([], []) # :nodoc: -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/task_manager.rb b/ruby/gems/rake-13.0.1/lib/rake/task_manager.rb deleted file mode 100644 index 97e3b9459..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/task_manager.rb +++ /dev/null @@ -1,331 +0,0 @@ -# frozen_string_literal: true -module Rake - - # The TaskManager module is a mixin for managing tasks. - module TaskManager - # Track the last comment made in the Rakefile. - attr_accessor :last_description - - def initialize # :nodoc: - super - @tasks = Hash.new - @rules = Array.new - @scope = Scope.make - @last_description = nil - end - - def create_rule(*args, &block) # :nodoc: - pattern, args, deps, order_only = resolve_args(args) - pattern = Regexp.new(Regexp.quote(pattern) + "$") if String === pattern - @rules << [pattern, args, deps, order_only, block] - end - - def define_task(task_class, *args, &block) # :nodoc: - task_name, arg_names, deps, order_only = resolve_args(args) - - original_scope = @scope - if String === task_name and - not task_class.ancestors.include? Rake::FileTask - task_name, *definition_scope = *(task_name.split(":").reverse) - @scope = Scope.make(*(definition_scope + @scope.to_a)) - end - - task_name = task_class.scope_name(@scope, task_name) - task = intern(task_class, task_name) - task.set_arg_names(arg_names) unless arg_names.empty? - if Rake::TaskManager.record_task_metadata - add_location(task) - task.add_description(get_description(task)) - end - task.enhance(Task.format_deps(deps), &block) - task | order_only unless order_only.nil? - task - ensure - @scope = original_scope - end - - # Lookup a task. Return an existing task if found, otherwise - # create a task of the current type. - def intern(task_class, task_name) - @tasks[task_name.to_s] ||= task_class.new(task_name, self) - end - - # Find a matching task for +task_name+. - def [](task_name, scopes=nil) - task_name = task_name.to_s - self.lookup(task_name, scopes) or - enhance_with_matching_rule(task_name) or - synthesize_file_task(task_name) or - fail generate_message_for_undefined_task(task_name) - end - - def generate_message_for_undefined_task(task_name) - message = "Don't know how to build task '#{task_name}' "\ - "(See the list of available tasks with `#{Rake.application.name} --tasks`)" - message + generate_did_you_mean_suggestions(task_name) - end - - def generate_did_you_mean_suggestions(task_name) - return "" unless defined?(::DidYouMean::SpellChecker) - - suggestions = ::DidYouMean::SpellChecker.new(dictionary: @tasks.keys).correct(task_name.to_s) - if ::DidYouMean.respond_to?(:formatter)# did_you_mean v1.2.0 or later - ::DidYouMean.formatter.message_for(suggestions) - elsif defined?(::DidYouMean::Formatter) # before did_you_mean v1.2.0 - ::DidYouMean::Formatter.new(suggestions).to_s - else - "" - end - end - - def synthesize_file_task(task_name) # :nodoc: - return nil unless File.exist?(task_name) - define_task(Rake::FileTask, task_name) - end - - # Resolve the arguments for a task/rule. Returns a tuple of - # [task_name, arg_name_list, prerequisites, order_only_prerequisites]. - def resolve_args(args) - if args.last.is_a?(Hash) - deps = args.pop - resolve_args_with_dependencies(args, deps) - else - resolve_args_without_dependencies(args) - end - end - - # Resolve task arguments for a task or rule when there are no - # dependencies declared. - # - # The patterns recognized by this argument resolving function are: - # - # task :t - # task :t, [:a] - # - def resolve_args_without_dependencies(args) - task_name = args.shift - if args.size == 1 && args.first.respond_to?(:to_ary) - arg_names = args.first.to_ary - else - arg_names = args - end - [task_name, arg_names, [], nil] - end - private :resolve_args_without_dependencies - - # Resolve task arguments for a task or rule when there are - # dependencies declared. - # - # The patterns recognized by this argument resolving function are: - # - # task :t, order_only: [:e] - # task :t => [:d] - # task :t => [:d], order_only: [:e] - # task :t, [a] => [:d] - # task :t, [a] => [:d], order_only: [:e] - # - def resolve_args_with_dependencies(args, hash) # :nodoc: - fail "Task Argument Error" if - hash.size != 1 && - (hash.size != 2 || !hash.key?(:order_only)) - order_only = hash.delete(:order_only) - key, value = hash.map { |k, v| [k, v] }.first - if args.empty? - task_name = key - arg_names = [] - deps = value || [] - else - task_name = args.shift - arg_names = key || args.shift|| [] - deps = value || [] - end - deps = [deps] unless deps.respond_to?(:to_ary) - [task_name, arg_names, deps, order_only] - end - private :resolve_args_with_dependencies - - # If a rule can be found that matches the task name, enhance the - # task with the prerequisites and actions from the rule. Set the - # source attribute of the task appropriately for the rule. Return - # the enhanced task or nil of no rule was found. - def enhance_with_matching_rule(task_name, level=0) - fail Rake::RuleRecursionOverflowError, - "Rule Recursion Too Deep" if level >= 16 - @rules.each do |pattern, args, extensions, order_only, block| - if pattern && pattern.match(task_name) - task = attempt_rule(task_name, pattern, args, extensions, block, level) - task | order_only unless order_only.nil? - return task if task - end - end - nil - rescue Rake::RuleRecursionOverflowError => ex - ex.add_target(task_name) - fail ex - end - - # List of all defined tasks in this application. - def tasks - @tasks.values.sort_by { |t| t.name } - end - - # List of all the tasks defined in the given scope (and its - # sub-scopes). - def tasks_in_scope(scope) - prefix = scope.path - tasks.select { |t| - /^#{prefix}:/ =~ t.name - } - end - - # Clear all tasks in this application. - def clear - @tasks.clear - @rules.clear - end - - # Lookup a task, using scope and the scope hints in the task name. - # This method performs straight lookups without trying to - # synthesize file tasks or rules. Special scope names (e.g. '^') - # are recognized. If no scope argument is supplied, use the - # current scope. Return nil if the task cannot be found. - def lookup(task_name, initial_scope=nil) - initial_scope ||= @scope - task_name = task_name.to_s - if task_name =~ /^rake:/ - scopes = Scope.make - task_name = task_name.sub(/^rake:/, "") - elsif task_name =~ /^(\^+)/ - scopes = initial_scope.trim($1.size) - task_name = task_name.sub(/^(\^+)/, "") - else - scopes = initial_scope - end - lookup_in_scope(task_name, scopes) - end - - # Lookup the task name - def lookup_in_scope(name, scope) - loop do - tn = scope.path_with_task_name(name) - task = @tasks[tn] - return task if task - break if scope.empty? - scope = scope.tail - end - nil - end - private :lookup_in_scope - - # Return the list of scope names currently active in the task - # manager. - def current_scope - @scope - end - - # Evaluate the block in a nested namespace named +name+. Create - # an anonymous namespace if +name+ is nil. - def in_namespace(name) - name ||= generate_name - @scope = Scope.new(name, @scope) - ns = NameSpace.new(self, @scope) - yield(ns) - ns - ensure - @scope = @scope.tail - end - - private - - # Add a location to the locations field of the given task. - def add_location(task) - loc = find_location - task.locations << loc if loc - task - end - - # Find the location that called into the dsl layer. - def find_location - locations = caller - i = 0 - while locations[i] - return locations[i + 1] if locations[i] =~ /rake\/dsl_definition.rb/ - i += 1 - end - nil - end - - # Generate an anonymous namespace name. - def generate_name - @seed ||= 0 - @seed += 1 - "_anon_#{@seed}" - end - - def trace_rule(level, message) # :nodoc: - options.trace_output.puts "#{" " * level}#{message}" if - Rake.application.options.trace_rules - end - - # Attempt to create a rule given the list of prerequisites. - def attempt_rule(task_name, task_pattern, args, extensions, block, level) - sources = make_sources(task_name, task_pattern, extensions) - prereqs = sources.map { |source| - trace_rule level, "Attempting Rule #{task_name} => #{source}" - if File.exist?(source) || Rake::Task.task_defined?(source) - trace_rule level, "(#{task_name} => #{source} ... EXIST)" - source - elsif parent = enhance_with_matching_rule(source, level + 1) - trace_rule level, "(#{task_name} => #{source} ... ENHANCE)" - parent.name - else - trace_rule level, "(#{task_name} => #{source} ... FAIL)" - return nil - end - } - task = FileTask.define_task(task_name, { args => prereqs }, &block) - task.sources = prereqs - task - end - - # Make a list of sources from the list of file name extensions / - # translation procs. - def make_sources(task_name, task_pattern, extensions) - result = extensions.map { |ext| - case ext - when /%/ - task_name.pathmap(ext) - when %r{/} - ext - when /^\./ - source = task_name.sub(task_pattern, ext) - source == ext ? task_name.ext(ext) : source - when String - ext - when Proc, Method - if ext.arity == 1 - ext.call(task_name) - else - ext.call - end - else - fail "Don't know how to handle rule dependent: #{ext.inspect}" - end - } - result.flatten - end - - # Return the current description, clearing it in the process. - def get_description(task) - desc = @last_description - @last_description = nil - desc - end - - class << self - attr_accessor :record_task_metadata # :nodoc: - TaskManager.record_task_metadata = false - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/tasklib.rb b/ruby/gems/rake-13.0.1/lib/rake/tasklib.rb deleted file mode 100644 index 5354b4f94..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/tasklib.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true -require "rake" - -module Rake - - # Base class for Task Libraries. - class TaskLib - include Cloneable - include Rake::DSL - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/testtask.rb b/ruby/gems/rake-13.0.1/lib/rake/testtask.rb deleted file mode 100644 index 537627567..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/testtask.rb +++ /dev/null @@ -1,224 +0,0 @@ -# frozen_string_literal: true -require "rake" -require "rake/tasklib" - -module Rake - - # Create a task that runs a set of tests. - # - # Example: - # require "rake/testtask" - # - # Rake::TestTask.new do |t| - # t.libs << "test" - # t.test_files = FileList['test/test*.rb'] - # t.verbose = true - # end - # - # If rake is invoked with a "TEST=filename" command line option, - # then the list of test files will be overridden to include only the - # filename specified on the command line. This provides an easy way - # to run just one test. - # - # If rake is invoked with a "TESTOPTS=options" command line option, - # then the given options are passed to the test process after a - # '--'. This allows Test::Unit options to be passed to the test - # suite. - # - # Examples: - # - # rake test # run tests normally - # rake test TEST=just_one_file.rb # run just one test file. - # rake test TESTOPTS="-v" # run in verbose mode - # rake test TESTOPTS="--runner=fox" # use the fox test runner - # - class TestTask < TaskLib - - # Name of test task. (default is :test) - attr_accessor :name - - # List of directories added to $LOAD_PATH before running the - # tests. (default is 'lib') - attr_accessor :libs - - # True if verbose test output desired. (default is false) - attr_accessor :verbose - - # Test options passed to the test suite. An explicit - # TESTOPTS=opts on the command line will override this. (default - # is NONE) - attr_accessor :options - - # Request that the tests be run with the warning flag set. - # E.g. warning=true implies "ruby -w" used to run the tests. - # (default is true) - attr_accessor :warning - - # Glob pattern to match test files. (default is 'test/test*.rb') - attr_accessor :pattern - - # Style of test loader to use. Options are: - # - # * :rake -- Rake provided test loading script (default). - # * :testrb -- Ruby provided test loading script. - # * :direct -- Load tests using command line loader. - # - attr_accessor :loader - - # Array of command line options to pass to ruby when running test loader. - attr_accessor :ruby_opts - - # Description of the test task. (default is 'Run tests') - attr_accessor :description - - # Task prerequisites. - attr_accessor :deps - - # Explicitly define the list of test files to be included in a - # test. +list+ is expected to be an array of file names (a - # FileList is acceptable). If both +pattern+ and +test_files+ are - # used, then the list of test files is the union of the two. - def test_files=(list) - @test_files = list - end - - # Create a testing task. - def initialize(name=:test) - @name = name - @libs = ["lib"] - @pattern = nil - @options = nil - @test_files = nil - @verbose = false - @warning = true - @loader = :rake - @ruby_opts = [] - @description = "Run tests" + (@name == :test ? "" : " for #{@name}") - @deps = [] - if @name.is_a?(Hash) - @deps = @name.values.first - @name = @name.keys.first - end - yield self if block_given? - @pattern = "test/test*.rb" if @pattern.nil? && @test_files.nil? - define - end - - # Create the tasks defined by this task lib. - def define - desc @description - task @name => Array(deps) do - FileUtilsExt.verbose(@verbose) do - puts "Use TESTOPTS=\"--verbose\" to pass --verbose" \ - ", etc. to runners." if ARGV.include? "--verbose" - args = - "#{ruby_opts_string} #{run_code} " + - "#{file_list_string} #{option_list}" - ruby args do |ok, status| - if !ok && status.respond_to?(:signaled?) && status.signaled? - raise SignalException.new(status.termsig) - elsif !ok - status = "Command failed with status (#{status.exitstatus})" - details = ": [ruby #{args}]" - message = - if Rake.application.options.trace or @verbose - status + details - else - status - end - - fail message - end - end - end - end - self - end - - def option_list # :nodoc: - (ENV["TESTOPTS"] || - ENV["TESTOPT"] || - ENV["TEST_OPTS"] || - ENV["TEST_OPT"] || - @options || - "") - end - - def ruby_opts_string # :nodoc: - opts = @ruby_opts.dup - opts.unshift("-I\"#{lib_path}\"") unless @libs.empty? - opts.unshift("-w") if @warning - opts.join(" ") - end - - def lib_path # :nodoc: - @libs.join(File::PATH_SEPARATOR) - end - - def file_list_string # :nodoc: - file_list.map { |fn| "\"#{fn}\"" }.join(" ") - end - - def file_list # :nodoc: - if ENV["TEST"] - FileList[ENV["TEST"]] - else - result = [] - result += @test_files.to_a if @test_files - result += FileList[@pattern].to_a if @pattern - result - end - end - - def ruby_version # :nodoc: - RUBY_VERSION - end - - def run_code # :nodoc: - case @loader - when :direct - "-e \"ARGV.each{|f| require f}\"" - when :testrb - "-S testrb" - when :rake - "#{rake_include_arg} \"#{rake_loader}\"" - end - end - - def rake_loader # :nodoc: - find_file("rake/rake_test_loader") or - fail "unable to find rake test loader" - end - - def find_file(fn) # :nodoc: - $LOAD_PATH.each do |path| - file_path = File.join(path, "#{fn}.rb") - return file_path if File.exist? file_path - end - nil - end - - def rake_include_arg # :nodoc: - spec = Gem.loaded_specs["rake"] - if spec.respond_to?(:default_gem?) && spec.default_gem? - "" - else - "-I\"#{rake_lib_dir}\"" - end - end - - def rake_lib_dir # :nodoc: - find_dir("rake") or - fail "unable to find rake lib" - end - - def find_dir(fn) # :nodoc: - $LOAD_PATH.each do |path| - file_path = File.join(path, "#{fn}.rb") - return path if File.exist? file_path - end - nil - end - - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/thread_history_display.rb b/ruby/gems/rake-13.0.1/lib/rake/thread_history_display.rb deleted file mode 100644 index 412ea37be..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/thread_history_display.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true -require "rake/private_reader" - -module Rake - - class ThreadHistoryDisplay # :nodoc: all - include Rake::PrivateReader - - private_reader :stats, :items, :threads - - def initialize(stats) - @stats = stats - @items = { _seq_: 1 } - @threads = { _seq_: "A" } - end - - def show - puts "Job History:" - stats.each do |stat| - stat[:data] ||= {} - rename(stat, :thread, threads) - rename(stat[:data], :item_id, items) - rename(stat[:data], :new_thread, threads) - rename(stat[:data], :deleted_thread, threads) - printf("%8d %2s %-20s %s\n", - (stat[:time] * 1_000_000).round, - stat[:thread], - stat[:event], - stat[:data].map do |k, v| "#{k}:#{v}" end.join(" ")) - end - end - - private - - def rename(hash, key, renames) - if hash && hash[key] - original = hash[key] - value = renames[original] - unless value - value = renames[:_seq_] - renames[:_seq_] = renames[:_seq_].succ - renames[original] = value - end - hash[key] = value - end - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/thread_pool.rb b/ruby/gems/rake-13.0.1/lib/rake/thread_pool.rb deleted file mode 100644 index b01a5efe0..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/thread_pool.rb +++ /dev/null @@ -1,163 +0,0 @@ -# frozen_string_literal: true -require "set" - -require "rake/promise" - -module Rake - - class ThreadPool # :nodoc: all - - # Creates a ThreadPool object. The +thread_count+ parameter is the size - # of the pool. - def initialize(thread_count) - @max_active_threads = [thread_count, 0].max - @threads = Set.new - @threads_mon = Monitor.new - @queue = Queue.new - @join_cond = @threads_mon.new_cond - - @history_start_time = nil - @history = [] - @history_mon = Monitor.new - @total_threads_in_play = 0 - end - - # Creates a future executed by the +ThreadPool+. - # - # The args are passed to the block when executing (similarly to - # Thread#new) The return value is an object representing - # a future which has been created and added to the queue in the - # pool. Sending #value to the object will sleep the - # current thread until the future is finished and will return the - # result (or raise an exception thrown from the future) - def future(*args, &block) - promise = Promise.new(args, &block) - promise.recorder = lambda { |*stats| stat(*stats) } - - @queue.enq promise - stat :queued, item_id: promise.object_id - start_thread - promise - end - - # Waits until the queue of futures is empty and all threads have exited. - def join - @threads_mon.synchronize do - begin - stat :joining - @join_cond.wait unless @threads.empty? - stat :joined - rescue Exception => e - stat :joined - $stderr.puts e - $stderr.print "Queue contains #{@queue.size} items. " + - "Thread pool contains #{@threads.count} threads\n" - $stderr.print "Current Thread #{Thread.current} status = " + - "#{Thread.current.status}\n" - $stderr.puts e.backtrace.join("\n") - @threads.each do |t| - $stderr.print "Thread #{t} status = #{t.status}\n" - $stderr.puts t.backtrace.join("\n") - end - raise e - end - end - end - - # Enable the gathering of history events. - def gather_history #:nodoc: - @history_start_time = Time.now if @history_start_time.nil? - end - - # Return a array of history events for the thread pool. - # - # History gathering must be enabled to be able to see the events - # (see #gather_history). Best to call this when the job is - # complete (i.e. after ThreadPool#join is called). - def history # :nodoc: - @history_mon.synchronize { @history.dup }. - sort_by { |i| i[:time] }. - each { |i| i[:time] -= @history_start_time } - end - - # Return a hash of always collected statistics for the thread pool. - def statistics # :nodoc: - { - total_threads_in_play: @total_threads_in_play, - max_active_threads: @max_active_threads, - } - end - - private - - # processes one item on the queue. Returns true if there was an - # item to process, false if there was no item - def process_queue_item #:nodoc: - return false if @queue.empty? - - # Even though we just asked if the queue was empty, it - # still could have had an item which by this statement - # is now gone. For this reason we pass true to Queue#deq - # because we will sleep indefinitely if it is empty. - promise = @queue.deq(true) - stat :dequeued, item_id: promise.object_id - promise.work - return true - - rescue ThreadError # this means the queue is empty - false - end - - def safe_thread_count - @threads_mon.synchronize do - @threads.count - end - end - - def start_thread # :nodoc: - @threads_mon.synchronize do - next unless @threads.count < @max_active_threads - - t = Thread.new do - begin - while safe_thread_count <= @max_active_threads - break unless process_queue_item - end - ensure - @threads_mon.synchronize do - @threads.delete Thread.current - stat :ended, thread_count: @threads.count - @join_cond.broadcast if @threads.empty? - end - end - end - - @threads << t - stat( - :spawned, - new_thread: t.object_id, - thread_count: @threads.count) - @total_threads_in_play = @threads.count if - @threads.count > @total_threads_in_play - end - end - - def stat(event, data=nil) # :nodoc: - return if @history_start_time.nil? - info = { - event: event, - data: data, - time: Time.now, - thread: Thread.current.object_id, - } - @history_mon.synchronize { @history << info } - end - - # for testing only - - def __queue__ # :nodoc: - @queue - end - end - -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/trace_output.rb b/ruby/gems/rake-13.0.1/lib/rake/trace_output.rb deleted file mode 100644 index d713a0926..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/trace_output.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true -module Rake - module TraceOutput # :nodoc: all - - # Write trace output to output stream +out+. - # - # The write is done as a single IO call (to print) to lessen the - # chance that the trace output is interrupted by other tasks also - # producing output. - def trace_on(out, *strings) - sep = $\ || "\n" - if strings.empty? - output = sep - else - output = strings.map { |s| - next if s.nil? - s.end_with?(sep) ? s : s + sep - }.join - end - out.print(output) - end - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/version.rb b/ruby/gems/rake-13.0.1/lib/rake/version.rb deleted file mode 100644 index b5486ba79..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/version.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true -module Rake - VERSION = "13.0.1" - - module Version # :nodoc: all - MAJOR, MINOR, BUILD, *OTHER = Rake::VERSION.split "." - - NUMBERS = [MAJOR, MINOR, BUILD, *OTHER] - end -end diff --git a/ruby/gems/rake-13.0.1/lib/rake/win32.rb b/ruby/gems/rake-13.0.1/lib/rake/win32.rb deleted file mode 100644 index 6e6203181..000000000 --- a/ruby/gems/rake-13.0.1/lib/rake/win32.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true -require "rbconfig" - -module Rake - # Win 32 interface methods for Rake. Windows specific functionality - # will be placed here to collect that knowledge in one spot. - module Win32 # :nodoc: all - - # Error indicating a problem in locating the home directory on a - # Win32 system. - class Win32HomeError < RuntimeError - end - - class << self - # True if running on a windows system. - def windows? - RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw|[Ww]indows)! - end - - # The standard directory containing system wide rake files on - # Win 32 systems. Try the following environment variables (in - # order): - # - # * HOME - # * HOMEDRIVE + HOMEPATH - # * APPDATA - # * USERPROFILE - # - # If the above are not defined, the return nil. - def win32_system_dir #:nodoc: - win32_shared_path = ENV["HOME"] - if win32_shared_path.nil? && ENV["HOMEDRIVE"] && ENV["HOMEPATH"] - win32_shared_path = ENV["HOMEDRIVE"] + ENV["HOMEPATH"] - end - - win32_shared_path ||= ENV["APPDATA"] - win32_shared_path ||= ENV["USERPROFILE"] - raise Win32HomeError, - "Unable to determine home path environment variable." if - win32_shared_path.nil? or win32_shared_path.empty? - normalize(File.join(win32_shared_path, "Rake")) - end - - # Normalize a win32 path so that the slashes are all forward slashes. - def normalize(path) - path.gsub(/\\/, "/") - end - - end - end -end diff --git a/ruby/gems/rake-13.0.1/rake.gemspec b/ruby/gems/rake-13.0.1/rake.gemspec deleted file mode 100644 index 969e2eda1..000000000 --- a/ruby/gems/rake-13.0.1/rake.gemspec +++ /dev/null @@ -1,24 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: rake 13.0.1 ruby lib - -Gem::Specification.new do |s| - s.name = "rake".freeze - s.version = "13.0.1" - - s.required_rubygems_version = Gem::Requirement.new(">= 1.3.2".freeze) if s.respond_to? :required_rubygems_version= - s.metadata = { "bug_tracker_uri" => "https://github.com/ruby/rake/issues", "changelog_uri" => "https://github.com/ruby/rake/blob/v13.0.1/History.rdoc", "documentation_uri" => "https://ruby.github.io/rake", "source_code_uri" => "https://github.com/ruby/rake/tree/v13.0.1" } if s.respond_to? :metadata= - s.require_paths = ["lib".freeze] - s.authors = ["Hiroshi SHIBATA".freeze, "Eric Hodel".freeze, "Jim Weirich".freeze] - s.bindir = "exe".freeze - s.date = "2019-11-12" - s.description = "Rake is a Make-like program implemented in Ruby. Tasks and dependencies are\nspecified in standard Ruby syntax.\nRake has the following features:\n * Rakefiles (rake's version of Makefiles) are completely defined in standard Ruby syntax.\n No XML files to edit. No quirky Makefile syntax to worry about (is that a tab or a space?)\n * Users can specify tasks with prerequisites.\n * Rake supports rule patterns to synthesize implicit tasks.\n * Flexible FileLists that act like arrays but know about manipulating file names and paths.\n * Supports parallel execution of tasks.\n".freeze - s.email = ["hsbt@ruby-lang.org".freeze, "drbrain@segment7.net".freeze, "".freeze] - s.executables = ["rake".freeze] - s.files = [".github/workflows/macos.yml".freeze, ".github/workflows/ubuntu-rvm.yml".freeze, ".github/workflows/ubuntu.yml".freeze, ".github/workflows/windows.yml".freeze, "CONTRIBUTING.rdoc".freeze, "Gemfile".freeze, "History.rdoc".freeze, "MIT-LICENSE".freeze, "README.rdoc".freeze, "Rakefile".freeze, "bin/bundle".freeze, "bin/console".freeze, "bin/rake".freeze, "bin/rdoc".freeze, "bin/rubocop".freeze, "bin/setup".freeze, "doc/command_line_usage.rdoc".freeze, "doc/example/Rakefile1".freeze, "doc/example/Rakefile2".freeze, "doc/example/a.c".freeze, "doc/example/b.c".freeze, "doc/example/main.c".freeze, "doc/glossary.rdoc".freeze, "doc/jamis.rb".freeze, "doc/proto_rake.rdoc".freeze, "doc/rake.1".freeze, "doc/rakefile.rdoc".freeze, "doc/rational.rdoc".freeze, "exe/rake".freeze, "lib/rake.rb".freeze, "lib/rake/application.rb".freeze, "lib/rake/backtrace.rb".freeze, "lib/rake/clean.rb".freeze, "lib/rake/cloneable.rb".freeze, "lib/rake/cpu_counter.rb".freeze, "lib/rake/default_loader.rb".freeze, "lib/rake/dsl_definition.rb".freeze, "lib/rake/early_time.rb".freeze, "lib/rake/ext/core.rb".freeze, "lib/rake/ext/string.rb".freeze, "lib/rake/file_creation_task.rb".freeze, "lib/rake/file_list.rb".freeze, "lib/rake/file_task.rb".freeze, "lib/rake/file_utils.rb".freeze, "lib/rake/file_utils_ext.rb".freeze, "lib/rake/invocation_chain.rb".freeze, "lib/rake/invocation_exception_mixin.rb".freeze, "lib/rake/late_time.rb".freeze, "lib/rake/linked_list.rb".freeze, "lib/rake/loaders/makefile.rb".freeze, "lib/rake/multi_task.rb".freeze, "lib/rake/name_space.rb".freeze, "lib/rake/packagetask.rb".freeze, "lib/rake/phony.rb".freeze, "lib/rake/private_reader.rb".freeze, "lib/rake/promise.rb".freeze, "lib/rake/pseudo_status.rb".freeze, "lib/rake/rake_module.rb".freeze, "lib/rake/rake_test_loader.rb".freeze, "lib/rake/rule_recursion_overflow_error.rb".freeze, "lib/rake/scope.rb".freeze, "lib/rake/task.rb".freeze, "lib/rake/task_argument_error.rb".freeze, "lib/rake/task_arguments.rb".freeze, "lib/rake/task_manager.rb".freeze, "lib/rake/tasklib.rb".freeze, "lib/rake/testtask.rb".freeze, "lib/rake/thread_history_display.rb".freeze, "lib/rake/thread_pool.rb".freeze, "lib/rake/trace_output.rb".freeze, "lib/rake/version.rb".freeze, "lib/rake/win32.rb".freeze, "rake.gemspec".freeze] - s.homepage = "https://github.com/ruby/rake".freeze - s.licenses = ["MIT".freeze] - s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] - s.required_ruby_version = Gem::Requirement.new(">= 2.2".freeze) - s.rubygems_version = "3.1.2".freeze - s.summary = "Rake is a Make-like program implemented in Ruby".freeze -end diff --git a/ruby/gems/test-unit-3.3.4.gem b/ruby/gems/test-unit-3.3.4.gem deleted file mode 100644 index ee78ae5e8..000000000 Binary files a/ruby/gems/test-unit-3.3.4.gem and /dev/null differ diff --git a/ruby/gems/test-unit-3.3.4/COPYING b/ruby/gems/test-unit-3.3.4/COPYING deleted file mode 100644 index 1aa77daf1..000000000 --- a/ruby/gems/test-unit-3.3.4/COPYING +++ /dev/null @@ -1,67 +0,0 @@ -test-unit is copyrighted free software by Kouhei Sutou -, Ryan Davis -and Nathaniel Talbott . - -You can redistribute it and/or modify it under either the terms of the GPL -version 2 (see the file GPL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. - -Exceptions ----------- - - * lib/test/unit/diff.rb: This license, PSF license and/or LGPLv2.1 - or later - - * lib/test-unit.rb: This license and/or LGPLv2.1 or later diff --git a/ruby/gems/test-unit-3.3.4/GPL b/ruby/gems/test-unit-3.3.4/GPL deleted file mode 100644 index d159169d1..000000000 --- a/ruby/gems/test-unit-3.3.4/GPL +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/ruby/gems/test-unit-3.3.4/LGPL b/ruby/gems/test-unit-3.3.4/LGPL deleted file mode 100644 index 4362b4915..000000000 --- a/ruby/gems/test-unit-3.3.4/LGPL +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/ruby/gems/test-unit-3.3.4/PSFL b/ruby/gems/test-unit-3.3.4/PSFL deleted file mode 100644 index 544000b5d..000000000 --- a/ruby/gems/test-unit-3.3.4/PSFL +++ /dev/null @@ -1,271 +0,0 @@ -This is the official license for the Python 2.5 release: - -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations (now Zope -Corporation, see http://www.zope.com). In 2001, the Python Software -Foundation (PSF, see http://www.python.org/psf/) was formed, a -non-profit organization created specifically to own Python-related -Intellectual Property. Zope Corporation is a sponsoring member of -the PSF. - -All Python releases are Open Source (see http://www.opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.2 2.1.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2.1 2.2 2002 PSF yes - 2.2.2 2.2.1 2002 PSF yes - 2.2.3 2.2.2 2003 PSF yes - 2.3 2.2.2 2002-2003 PSF yes - 2.3.1 2.3 2002-2003 PSF yes - 2.3.2 2.3.1 2002-2003 PSF yes - 2.3.3 2.3.2 2002-2003 PSF yes - 2.3.4 2.3.3 2004 PSF yes - 2.3.5 2.3.4 2005 PSF yes - 2.4 2.3 2004 PSF yes - 2.4.1 2.4 2005 PSF yes - 2.4.2 2.4.1 2005 PSF yes - 2.4.3 2.4.2 2006 PSF yes - 2.5 2.4 2006 PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python -alone or in any derivative version, provided, however, that PSF's -License Agreement and PSF's notice of copyright, i.e., "Copyright (c) -2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights -Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the Internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the Internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/ruby/gems/test-unit-3.3.4/README.md b/ruby/gems/test-unit-3.3.4/README.md deleted file mode 100644 index 77a863d58..000000000 --- a/ruby/gems/test-unit-3.3.4/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# test-unit - -[![](https://badge.fury.io/rb/test-unit.svg)](http://badge.fury.io/rb/test-unit) -[![](https://travis-ci.org/test-unit/test-unit.svg?branch=master)](https://travis-ci.org/test-unit/test-unit) - -* http://test-unit.github.io/ -* https://github.com/test-unit/test-unit - -## Description - -An xUnit family unit testing framework for Ruby. - -test-unit (Test::Unit) is unit testing framework for Ruby, based on xUnit -principles. These were originally designed by Kent Beck, creator of extreme -programming software development methodology, for Smalltalk's SUnit. It allows -writing tests, checking results and automated testing in Ruby. - -## Features - -* test-unit 1.2.3 is the original test-unit, taken - straight from the ruby distribution. It is being - distributed as a gem to allow tool builders to use it as a - stand-alone package. (The test framework in ruby is going - to radically change very soon). - -* test-unit will be improved actively and may break - compatiblity with test-unit 1.2.3. (We will not hope it - if it isn't needed.) - -* Some features exist as separated gems like GUI test - runner. (Tk, GTK+ and Fox) test-unit-full gem package - provides for installing all test-unit related gems - easily. - -## How To - -* [How To](https://github.com/test-unit/test-unit/blob/master/doc/text/how-to.md) (link for GitHub) -* {file:doc/text/how-to.md How To} (link for YARD) - -## Install - -
-% sudo gem install test-unit
-
- -If you want to use full test-unit features: - -
-% sudo gem install test-unit-full
-
- -## License - -(The Ruby License) - -This software is distributed under the same terms as ruby. - -Exception: - - * lib/test/unit/diff.rb is a triple license of the Ruby license, - PSF license and LGPLv2.1 or later. - - * lib/test-unit.rb is a dual license of the Ruby license and LGPLv2.1 - or later. - -## Authors - -### Active - -* Kouhei Sutou: The current maintainer -* Haruka Yoshihara: Data driven test supports. - -### Inactive - -* Nathaniel Talbott: The original author -* Ryan Davis: The second maintainer - -### Images - -* Mayu & Co.: kinotan icons - -## Thanks - -* Daniel Berger: Suggestions and bug reports. -* Designing Patterns: Suggestions. -* Erik Hollensbe: Suggestions and bug reports. -* Bill Lear: A suggestion. -* Diego Pettenò: A bug report. -* Angelo Lakra: A bug report. -* Mike Pomraning: A bug report. -* David MARCHALAND: Suggestions and bug reports. -* Andrew Grimm: A bug report. -* Champak Ch: A bug report. -* Florian Frank: A bug report. -* grafi-tt: Bug fixes and reports. -* Jeremy Stephens: A bug report. -* Hans de Graaff: Bug reports. -* James Mead: A bug report. -* Marc Seeger (Acquia): A bug report. -* boutil: A bug report. -* Vladislav Rassokhin: A bug report. diff --git a/ruby/gems/test-unit-3.3.4/Rakefile b/ruby/gems/test-unit-3.3.4/Rakefile deleted file mode 100644 index 1e045a948..000000000 --- a/ruby/gems/test-unit-3.3.4/Rakefile +++ /dev/null @@ -1,80 +0,0 @@ -# -*- ruby -*- -# -# Copyright (C) 2008-2017 Kouhei Sutou -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Encoding.default_internal = "UTF-8" if defined?(Encoding.default_internal) - -# TODO: Remove me when we drop Ruby 1.9 support. -unless "".respond_to?(:b) - class String - def b - dup.force_encoding("ASCII-8BIT") - end - end -end - -require "erb" -require "yaml" -require "rubygems" -require "rake/clean" -require "yard" -require "bundler/gem_helper" -require "packnga" - -task :default => :test - -base_dir = File.dirname(__FILE__) -html_base_dir = File.join(base_dir, "doc", "html") - -helper = Bundler::GemHelper.new(base_dir) -def helper.version_tag - version -end - -helper.install -spec = helper.gemspec - -document_task = Packnga::DocumentTask.new(spec) do |task| - task.original_language = "en" - task.translate_languages = ["ja"] -end - -Packnga::ReleaseTask.new(spec) do |task| - test_unit_github_io_dir_candidates = [ - "../../www/test-unit.github.io", - ] - test_unit_github_io_dir = test_unit_github_io_dir_candidates.find do |dir| - File.directory?(dir) - end - task.index_html_dir = test_unit_github_io_dir -end - -def rake(*arguments) - ruby($0, *arguments) -end - -namespace :html do - desc "Publish HTML to Web site." - task :publish do - # FIXME Do nothing for now - #rsync_to_rubyforge(spec, "#{html_base_dir}/", "") - end -end - -task :test do - ruby("test/run-test.rb") -end diff --git a/ruby/gems/test-unit-3.3.4/doc/text/getting-started.md b/ruby/gems/test-unit-3.3.4/doc/text/getting-started.md deleted file mode 100644 index f49bd657e..000000000 --- a/ruby/gems/test-unit-3.3.4/doc/text/getting-started.md +++ /dev/null @@ -1,246 +0,0 @@ -## 1. First step of the `test-unit` - -Let's getting start `test-unit`. - -This document creates an example gem package called `sample` with the `test-unit` testing framework. - -## 2. Install bundler and test-unit. - -* First, install the `bundler` gem for generating gem template. -* Second, install the `test-unit` itself. - -~~~ -!!!plain -gem install bundler -gem install test-unit -~~~ - -The `gem list` command output installed packages. -You will find the following lines. - -~~~ -!!!plain -gem list -... -bundler (1.14.6) -... -test-unit (3.2.3) -~~~ - -## 3. Create gem template. - -Next, create a gem template using `bundler` command. -This command generates package skeleton with a testing framework. -However, this command can't generate test templates for `test-unit`. - -So, First create gem template with the `minitest` testing framework. -(It's similar to `unit-test`). -After that, replace some files for `test-unit`. - -The `bundle gem -t minitest sample` command will generate the following files. - -~~~ -!!!plain -. -|-- Gemfile -|-- README.md -|-- Rakefile -|-- bin -| |-- console -| `-- setup -|-- lib -| |-- sample -| | `-- version.rb -| `-- sample.rb -|-- sample.gemspec # <- Modify -`-- test - |-- sample_test.rb # <- Modify - `-- test_helper.rb # <- Modify -~~~ - -## 4. Edit files for `test-unit` - -### 4.1. Edit gemspec - -Edit `sample.gemspec` like the below. -Replace `minitest` line to `test-unit`. - -Before - -~~~ -!!!ruby - spec.add_development_dependency "minitest", "~> 5.0" -~~~ - -After - -~~~ -!!!ruby - spec.add_development_dependency "test-unit", "~> 3.2.3" -~~~ - -### 4.2. Edit `test/test_helper.rb` - -Next, edit the `test/test_helper.rb` file. - -Before - -~~~ -!!!ruby -$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) -require 'sample' - -require 'minitest/autorun' # <-- Modify this line. -~~~ - -After - -~~~ -!!!ruby -$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) -require 'sample' - -require 'test/unit' # <-- After modification. -~~~ - -### 4.3 Rakefile (No edit) - -This file doesn't need to modify. -The output is the below. - -~~~ -!!!ruby -require "bundler/gem_tasks" -require "rake/testtask" - -Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.libs << "lib" - t.test_files = FileList['test/**/*_test.rb'] -end - -task :default => :test -~~~ - -### 4.4 Edit `test/sample_test.rb` - -The bundler generate the file `test/sample_test.rb`. -This file originally templates for `minitest`. - -Let's modify this file for `test-unit` - -before - -~~~ -!!!ruby -require 'test_helper' - -class SampleTest < Minitest::Test # <- Modify here - def test_that_it_has_a_version_number - refute_nil ::Sample::VERSION - end - - def test_it_does_something_useful - assert false - end -end -~~~ - -After - -~~~ -!!!ruby -require 'test_helper' - -class SampleTest < Test::Unit::TestCase # <- After modification - def test_that_it_has_a_version_number - refute_nil ::Sample::VERSION - end - - def test_it_does_something_useful - assert false - end -end -~~~ - -## 5. Execute test. - -The `rake test` command execute test scenarios in the `test` directory. -Now it tries to two tests. One will success the other one fails. - -~~~ -!!!plain -rake test -Loaded suite -/path/to/ruby/lib/ruby/gems/2.3.0/gems/rake-12.0.0/lib/rake/rake_test_loader -Started -F -================================================================================ -Failure: is not true. -test_it_does_something_useful(SampleTest) -/path/to/sample/test/sample_test.rb:9:in `test_it_does_something_useful' - 6: end - 7: - 8: def test_it_does_something_useful - => 9: assert false - 10: end - 11: end -================================================================================ -. - -Finished in 0.011521 seconds. --------------------------------------------------------------------------------- -2 tests, 2 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications -50% passed --------------------------------------------------------------------------------- -173.60 tests/s, 173.60 assertions/s -rake aborted! -Command failed with status (1) - -Tasks: TOP => test -(See full trace by running task with --trace) -~~~ - -## 6. Create original tests. - -Let's create your original tests with the following rules. - -* Create a test file in the `test` directory. -* The file needs suffix `xxx_test.rb`. -* You can put test file into the subdirectory like `test/sub`. - -Example directory layout. - -~~~ -!!!plain -test -|-- sample_test.rb -|-- sub -| `-- sample2_test.rb -`-- test_helper.rb -~~~ - -Example test file in the sub directory. - -~~~ -!!!ruby -require 'test_helper' - -module Sub - class Sample2Test < Test::Unit::TestCase - def test_that_it_has_a_version_number - refute_nil ::Sample::VERSION - end - - def test_it_does_something_useful - assert false - end - end -end -~~~ - -## 7. For more inforomation - -Let's read the official document. - -* [test-unit](http://test-unit.github.io/index.html) diff --git a/ruby/gems/test-unit-3.3.4/doc/text/how-to.md b/ruby/gems/test-unit-3.3.4/doc/text/how-to.md deleted file mode 100644 index 11bf236d1..000000000 --- a/ruby/gems/test-unit-3.3.4/doc/text/how-to.md +++ /dev/null @@ -1,90 +0,0 @@ -# How To - -## Run all tests - -To make it easy to run all your tests, you can add a `run_test.rb` script -to your `test` directory. A simple example might look like: - - base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..")) - lib_dir = File.join(base_dir, "lib") - test_dir = File.join(base_dir, "test") - - $LOAD_PATH.unshift(lib_dir) - - require 'test/unit' - - exit Test::Unit::AutoRunner.run(true, test_dir) - -Then it's easy to run tests via the command line with, - - $ ruby test/run_test.rb - -## Change test runner via the command line - -The output format can be changed via the command line with -the `--runner` option. Simply tack it to the end: - - ruby test/run_test.rb --runner tap - - -## Configure test-unit per-project - -Test::Unit reads `test-unit.yml` or `.test-unit.yml` in the current working -directory as Test::Unit's configuration file. It can contain the following -settings: - -* color scheme definitions -* test runner to be used -* test runner options -* test collector to be used - -Except color scheme definitions, all of them can be specified by command -line option. - -Here are sample color scheme definitions: - - color_schemes: - inverted: - success: - name: red - bold: true - failure: - name: green - bold: true - other_scheme: - ... - -Here are the syntax of color scheme definitions: - - color_schemes: - SCHEME_NAME: - EVENT_NAME: - name: COLOR_NAME - intensity: BOOLEAN - bold: BOOLEAN - italic: BOOLEAN - underline: BOOLEAN - ... - ... - -| Definition | Description | -|-------------|------------------------------| -| SCHEME_NAME | the name of the color scheme | -| EVENT_NAME | success, failure, pending, omission, notification, error | -| COLOR_NAME | black, red, green, yellow, blue, magenta, cyan, white | -| BOOLEAN | true or false | - -You can use the above 'inverted' color scheme with the following configuration: - - runner: console - console_options: - color_scheme: inverted - color_schemes: - inverted: - success: - name: red - bold: true - failure: - name: green - bold: true - diff --git a/ruby/gems/test-unit-3.3.4/doc/text/news.md b/ruby/gems/test-unit-3.3.4/doc/text/news.md deleted file mode 100644 index 97607c6d4..000000000 --- a/ruby/gems/test-unit-3.3.4/doc/text/news.md +++ /dev/null @@ -1,1453 +0,0 @@ -# News - -## 3.3.4 - 2019-09-30 {#version-3-3-4} - -### Improvements - - * Converted markup format to Markdown from RDoc. - [GitHub#164][Patch by OGAWA KenIchi] - - * test: Stopped to depend on `Time#inspect` format. - [GitHub#165][Reported by Benoit Daloze] - -### Thanks - - * OGAWA KenIchi - - * Benoit Daloze - -## 3.3.3 - 2019-05-10 {#version-3-3-3} - -### Fixed - - * Fixed a bug that priority mode with test case name that uses - special characters such as `?` can't be used on Windows. - -## 3.3.2 - 2019-04-11 {#version-3-3-2} - -### Fixes - - * Fixed a bug that `Test::Unit::Collector::Load` doesn't load test - files under sub directories when these files have the same base - name as test files in upper directories. - [Reported by Kenta Murata] - -### Thanks - - * Kenta Murata - -## 3.3.1 - 2019-03-27 {#version-3-3-1} - -### Improvements - - * Added support for `Test::Unit::AssertionFailedError#user_message` - for not only `assert_equal` and `assert_raise` but also all - assertions. - [GitHub#162][Reported by xgraffm] - -### Thanks - - * xgraffm - -## 3.3.0 - 2019-01-23 {#version-3-3-0} - -### Improvements - - * Added support for auto test run when all tests are defined in - modules. - - * Added support for defining methods to test case class in multiple - threads. - [GitHub#159][Reported by Charles Oliver Nutter] - - * Suppressed warnings on Ruby 2.5. - [GitHub#160][Reported by Daniel Berger] - - * Suppressed warnings on Ruby 2.7. - -### Fixes - - * Fixed a code snippet fetch failure when source code isn't UTF-8 - and the default external encoding is set to not UTF-8. - [GitHub#161][Reported by masa kunikata] - -### Thanks - - * Charles Oliver Nutter - - * Daniel Berger - - * masa kunikata - -## 3.2.9 - 2018-12-01 {#version-3-2-9} - -### Improvements - - * Added support for data generation by method. `data_#{test_name}` - is called to generate data for `test_name` test. - - * Added support for data matrix generation. - - Example: - - ```ruby - data(:a, [0, 1, 2]) - data(:b, [:x, :y]) - def test_data(data) - end - ``` - - This example generates the following data matrix: - - * label: `"a: 0, b: :x"`, data: `{a: 0, b: :x}` - * label: `"a: 0, b: :y"`, data: `{a: 0, b: :y}` - * label: `"a: 1, b: :x"`, data: `{a: 1, b: :x}` - * label: `"a: 1, b: :y"`, data: `{a: 1, b: :y}` - * label: `"a: 2, b: :x"`, data: `{a: 2, b: :x}` - * label: `"a: 2, b: :y"`, data: `{a: 2, b: :y}` - - * Added `Test::Unit::TestCase#data` that returns the current data. - - * Added support for using test method that doesn't have no - parameters as data driven test. - - Example: - - ```ruby - data("label", :value) - def test_data # Available since this release - p data # :value - end - ``` - - * Added support for `:keep` option to `Test::Unit::TestCase.data`. - - * Added support for `:group` option to - `Test::Unit::TestCase.data`. It's useful to generate multiple data - matrix groups. - - ```ruby - # Group1 - data(:a, [0, 1, 2], group: :g1) - data(:b, [:x, :y], group: :g1) - # Group2 - data(:a, [:x, :y], group: :g2) - data(:c, [-1, -2], group: :g2) - def test_data(data) - end - ``` - - This example generates the following data matrix: - - * label: `"group: :g1, a: 0, b: :x"`, data: `{a: 0, b: :x}` - * label: `"group: :g1, a: 0, b: :y"`, data: `{a: 0, b: :y}` - * label: `"group: :g1, a: 1, b: :x"`, data: `{a: 1, b: :x}` - * label: `"group: :g1, a: 1, b: :y"`, data: `{a: 1, b: :y}` - * label: `"group: :g1, a: 2, b: :x"`, data: `{a: 2, b: :x}` - * label: `"group: :g1, a: 2, b: :y"`, data: `{a: 2, b: :y}` - * label: `"group: :g2, a: :x, b: -1"`, data: `{a: :x, b: -1}` - * label: `"group: :g2, a: :x, b: -2"`, data: `{a: :x, b: -2}` - * label: `"group: :g2, a: :y, b: -1"`, data: `{a: :y, b: -1}` - * label: `"group: :g2, a: :y, b: -2"`, data: `{a: :y, b: -2}` - -## 3.2.8 - 2018-05-13 {#version-3-2-8} - -### Improvements - - * [UI][console]: Changed to put code snippet before backtrace on - reverse mode. - -## 3.2.7 - 2017-12-12 {#version-3-2-7} - -### Improvements - - * Added source code link to gemspec. - [GitHub#157][Patch by Grey Baker] - - * Changed to use SVG image for badges in README. - [GitHub#158][Patch by Olle Jonsson] - - * [UI][console]: Added `--reverse-output` option to output fault - details in reverse like Ruby 2.5. It's enabled by default only for - tty output. - -### Fixes - - * Fixed a typo. - [GitHub#156][Patch by masa kunikata] - - * [UI][console]: Fixed a bug that broken align in verbose mode. - -### Thanks - - * masa kunikata - - * Grey Baker - - * Olle Jonsson - -## 3.2.6 - 2017-09-21 {#version-3-2-6} - -### Improvements - - * Changed test file require failure to error from omission. - [GitHub#154][Patch by naofumi-fujii] - -### Thanks - - * naofumi-fujii - -## 3.2.5 - 2017-06-24 {#version-3-2-5} - -### Improvements - - * Supported `--enable-frozen-string-literal` `ruby` option. - [GitHub#149][Reported by Pat Allan] - -### Thanks - - * Pat Allan - -## 3.2.4 - 2017-05-23 {#version-3-2-4} - -### Improvements - - * Updated tests for Ruby 2.4. [GitHUb#136][Patch by Kazuki Tsujimoto] - - * Supported power\_assert 1.0.0. [GitHub#137][Patch by Kazuki Tsujimoto] - - * Added the getting started document. - [GitHub#139][GitHub#141][Patch by Hiroyuki Sato] - - * Added the document for `attribute`. - [GitHub#143][Patch by Fumiaki MATSUSHIMA] - - * Improved a link for GitHub. [GitHub#144][Patch by rochefort] - - * Updated `.travis.yml`. [GitHub#145][Patch by Jun Aruga] - -### Fixes - - * Fixed a contributor name. [GitHub#131][Patch by Akira Matsuda] - - * Fixed typos in document. [GitHub#132][Patch by Akira Matsuda] - - * Fixed typos in document. [GitHub#134][Patch by Yuji Yaginuma] - - * Fixed a bug that data label with "(" isn't supported. - [GitHub#135][Reported by Kazuki Tsujimoto] - - * Fixed assertion message in English. - [GitHub#133][Reported by Khalil Fazal] - - * Fixed a typo in typo fix. [GitHub#138][Patch by kami] - - * Fixed a bug that target location finder may return wrong - location. [GitHub#146][Patch by Yuki Ito] - - * Fixed a bug that `--no-show-detail-immediately` raises an error. - [GitHub#147][Reported by MSP-Greg] - -### Thanks - - * Akira Matsuda - - * Yuji Yaginuma - - * Kazuki Tsujimoto - - * Khalil Fazal - - * kami - - * Hiroyuki Sato - - * Fumiaki MATSUSHIMA - - * rochefort - - * Jun Aruga - - * Yuki Ito - - * MSP-Greg - -## 3.2.3 - 2016-11-25 {#version-3-2-3} - -### Fixes - - * Fixed a bug that `--order` isn't applied. - [GitHub#129][Reported by Vít Ondruch] - -### Thanks - - * Vít Ondruch - -## 3.2.2 - 2016-11-02 {#version-3-2-2} - -### Improvements - - * Improved Travis CI configuration. - [GitHub#123][Patch by Ryunosuke Sato] - - * Supported Java native exception. - [GitHub#126][Reported by Bob Saveland] - -### Fixes - - * doc: Fixed markup. [GitHub#127][Patch by Tomohiro Hashidate] - - * Fixed a bug that `--location=LINE` may not detect a test when - fixtures are defined before any tests: - - 1 class MyTestCase < Test::Unit::TestCase - 2 setup do - 3 end - 4 - 5 test "xxx" do - 6 end - 7 end - - `--location=5` couldn't find the `xxx` test. - - [Reported by Ryota Sasabe] - -### Thanks - - * Ryunosuke Sato - - * Tomohiro Hashidate - - * Bob Saveland - - * Ryota Sasabe - -## 3.2.1 - 2016-07-19 {#version-3-2-1} - -### Improvements - - * Clarified lib/test/unit/diff.rb license. It's a triple license of - the Ruby license, PSF license and LGPLv2.1 or later. - [Reported by Luisa Pace] - - * Reported norification when data driven test doesn't have - parameter. - [GitHub#122][Reported by Satoshi "Moris" Tagomori] - -### Thanks - - * Luisa Pace - - * Satoshi "Moris" Tagomori - -## 3.2.0 - 2016-06-12 {#version-3-2-0} - -### Improvements - - * Supported rxvt family terminals as color available terminals. - [GitHub#121][Reported by Ippei Kishida] - -### Thanks - - * Ippei Kishida - -## 3.1.9 - 2016-05-20 {#version-3-1-9} - -### Fixes - - * Fixed conflict with test-unit-power_assert. - [GitHub#120][Patch by Kazuki Tsujimoto] - - * Fixed a bug that path in `$LOAD_PATH` may be removed. - -### Thanks - - * Kazuki Tsujimoto - -## 3.1.8 - 2016-03-19 {#version-3-1-8} - -### Improvements - - * Added `--stop-on-failure` command line option. With this option, - running test suite is stopped immediately when one test is failed - or an error is raised in one test. - -## 3.1.7 - 2016-01-17 {#version-3-1-7} - -### Fixes - - * Added a missing require. - -## 3.1.6 - 2016-01-17 {#version-3-1-6} - -It's a Ruby on Rails integration improvement release. - -### Improvements - - * Filtered backtrace of power\_assert. - [GitHub#114] - * Improved performance to retrieve test defined location. - * Improved performance to run fixtures in a test. - * Supported running a test by `yield` in `setup`: - - Before: - - def setup - @file = File.open("x") - end - - def teardown - @file.close - end - - After: - - def setup - File.open("x") do |file| - @file = file - yield - end - end - - * Added `--default-test-path` option that specifies the default path - that has tests. - * Made auto runner registration more lazily. Auto runner isn't - registered automatically until user defines a test. In the - previous releases, auto runner is registered automatically when - user defines a test case. - * Supported specifying a test by location in command line. For - example, the following command line runs a test that is defined in - /tmp/test_a.rb at line 10: - - % ruby -r test-unit -e run_test /tmp/test_a.rb:10 - -### Fixes - - * Fixed a bug that test isn't ran. The test has the same name as - data driven test that is defined in parent test case. - [GitHub#115] - -## 3.1.5 - 2015-10-09 {#version-3-1-5} - -It's a Rack integration improvement release. - -### Improvements - - * Renamed experimental top-level `run` method to `run_test` method - because `run` is conflicted with Rack. - [GitHub#32][GitHub:basecamp/pow#303] [Reported by Yevhen Viktorov] - -### Thanks - - * Yevhen Viktorov - -## 3.1.4 - 2015-09-26 {#version-3-1-4} - -It's a minor improvement release. - -### Improvements - - * Updated sample code. [GitHub#109][Patch by takiy33] - * Updated .travis.yml. [GitHub#110][Patch by takiy33] - * document: Added table header in how to document. - [GitHub#111][Patch by takiy33] - * Removed duplicated code. - [GitHub#112][Patch by takiy33] - * Removed needless encoding conversion in fetching code snippet. - [GitHub#113][Patch by NARUSE, Yui] - -### Thanks - - * takiy33 - * NARUSE, Yui - -## 3.1.3 - 2015-07-26 {#version-3-1-3} - -It's a bug fix release. - -### Improvements - - * Removed unused `TODO` file. [GitHub#108][Patch by takiy33] - -### Fixes - - * `--location`: Fixed a bug that `--location LINE` doesn't work when - test script is specified as relative path. [Reported by TOMITA Masahiro] - - The following doesn't work: - - % ruby ./test.rb --location 10 - - The following works: - - % ruby test.rb --location 10 - -### Thanks - - * takiy33 - * TOMITA Masahiro - -## 3.1.2 - 2015-06-09 {#version-3-1-2} - -It's command line option improvements fix release. - -### Improvements - - * `--location`: Made path match rule more strict. - [Suggested by kimura wataru] - * Before: - * If test defined path ends with the specified path, the test is - matched. - * After: - * If base name of test defined path equals to the specified - path, the test is matched. - * If relative path of test defined path equals to the specified - path, the test is matched. - * If the specified path is absolute path and test defined path - equals to the specified path, the test is matched. - * `--pattern`: If the option is specified, the default patterns - aren't used. In the earlier versions, both the default patterns - and the specified patterns are used. - [Suggested by kimura wataru] - -### Thanks - - * kimura wataru - -## 3.1.1 - 2015-05-29 {#version-3-1-1} - -It's a bug fix release. - -### Fixes - - * Fixed a bug that `--location` detects tests not only in sub test - case but also parent test case. - [GitHub#105][Reported by wanabe] - -### Thanks - - * wanabe - -## 3.1.0 - 2015-05-28 {#version-3-1-0} - -It's a bug fix release. - -### Improvements - - * [ui][console] Removed needless new line. - -### Fixes - - * Fixed a bug that priority mode can't be used on Windows. - [GitHub#95][Reported by Daniel Berger] - * Fixed a homepage URL RubyGems spec. - [GitHub#96][Patch by Masayoshi Takahashi] - supported.) [GitHub#89][Patch by Aaron Stone] - * Fixed a bug that shutdown hook isn't called when pass throw - exception such as `Interrupt` is raised. - [GitHub#98][Reported by jeremiahishere.] - * Fixed typos in documents. - [GitHub#100][Reported by scivola] - [GitHub#102][GitHub#103][Patch by Masafumi Yokoyama] - * Fixed a bug that the same name test isn't executed in sub test case. - [GitHub#104][Reported by wanabe] - -### Thanks - - * Daniel Berger - * Masayoshi Takahashi - * jeremiahishere - * scivola - * Masafumi Yokoyama - * wanabe - -## 3.0.9 - 2014-12-31 {#version-3-0-9} - -It's a release that improves colors. - -### Improvements - - * Added a work around for Ruby 1.8. (Note: Ruby 1.8 isn't - supported.) [GitHub#89][Patch by Aaron Stone] - * Supported colorized output on Windows. - [GitHub#90][Patch by usa] - * Improved colorized output. - http://www.a-k-r.org/d/2014-12.html#a2014_12_27_1 - [Suggested by Tanaka Akira] - -### Thanks - - * Aaron Stone - * usa - * Tanaka Akira - -## 3.0.8 - 2014-12-12 {#version-3-0-8} - -It's a release that supports Ruby 2.2.0 preview2. - -### Improvements - - * Added a link for YARD in README. - [GitHub:test-unit.github.io#2][Reported by sunnyone] - * Added description about "/PATTERN/" style value in auto runner usage. - [GitHub#86][Suggested by sunnyone] - * Supported Ruby 2.2.0 preview2 in `assert_throw` and - `assert_nothing_thrown`. - -### Fixes - - * Fixed a bug that error report is failed when source encoding and - locale encoding are different. - [GitHub#87][Reported by scivola] - -### Thanks - - * sunnyone - * scivola - -## 3.0.7 - 2014-11-14 {#version-3-0-7} - -It's a minor update release. - -### Fixes - - * Fixed a bug that teardown blocks aren't called with sub class to - parent class order. - [GitHub#85][Reported by TOMITA Masahiro] - -### Thanks - - * TOMITA Masahiro - -## 3.0.6 - 2014-11-09 {#version-3-0-6} - -It's a minor update release. - -### Improvements - - * Improved code snippet location. - [GitHub#84][Patch by Yuki Kurihara] - -### Thanks - - * Yuki Kurihara - -## 3.0.5 - 2014-11-08 {#version-3-0-5} - -It's a minor update release. - -### Fixes - - * Fixed a bug that startup/shutdown of parent test case isn't called - when the test case includes one or more modules. - [GitHub#83][Reported by Chadderton Odwazny] - -### Thanks - - * Chadderton Odwazny - -## 3.0.4 - 2014-11-01 {#version-3-0-4} - -It's a minor update release. - -### Improvements - - * Stopped to remove JRuby and Rubinius internal backtrace entries from - backtrace on failure/error. - [GitHub#82][Patch by Charles Oliver Nutter] - -### Thanks - - * Charles Oliver Nutter - -## 3.0.3 - 2014-10-29 {#version-3-0-3} - -It's a minor update release. - -### Improvements - - * Improved `Test::Unit::TestCase.test` performance. - 100 times faster. - * Supported `Proc` for user message. - [Sugested by Nobuyoshi Nakada] - -### Fixes - - * Fixed markup in document. - [GitHub#81][Patch by Masafumi Yokoyama] - -### Thanks - - * Masafumi Yokoyama - * Nobuyoshi Nakada - -## 3.0.2 - 2014-10-15 {#version-3-0-2} - -It's a minor update release. - -### Improvements - - * Supported broken `==` implementation. - `==` implementation should be fixed but it's not work of test-unit. :< - [GitHub#71][Reported by Emily] - * [UI][console]: Accepted no message failure. - [GitHub#66][Reported by Brian Tatnall] - * Updated gem description. - [GitHub#74][Patch by Vít Ondruch] - * Updated GPL text. - [GitHub#78][Patch by Vít Ondruch] - -### Fixes - - * Removed needless executable bit from README file. - [GitHub#79][Patch by Vít Ondruch] - -### Thanks - - * Emily - * Brian Tatnall - * Vít Ondruch - -## 3.0.1 - 2014-08-05 {#version-3-0-1} - -It's a minor update release. - -### Improvements - - * Improved Ruby 1.8.7 support. Note that we don't support Ruby 1.8.7 - actively. We just support if its support is painless. - [GitHub#71][Patch by estolfo] - -### Thanks - - * estolfo - -## 3.0.0 - 2014-08-03 {#version-3-0-0} - -It's Power Assert supported release! - -### Improvements - - * Improved Rubinius support. [Ryo Onodera] - * Updated RR repository link. [GitHub#56][Patch by Kenichi Kamiya] - * Added some minitest compatible assertions. We don't recommend - using these assertions. They are just for migrating from minitest. - [GitHub#57][Patch by Karol Bucek] - * {Test::Unit::Assertions#refute} - * {Test::Unit::Assertions#refute_predicate} - * {Test::Unit::Assertions#refute_empty} - * {Test::Unit::Assertions#assert_not_includes} - * {Test::Unit::Assertions#refute_includes} - * {Test::Unit::Assertions#assert_not_instance_of} - * {Test::Unit::Assertions#refute_instance_of} - * {Test::Unit::Assertions#assert_not_kind_of} - * {Test::Unit::Assertions#refute_kind_of} - * {Test::Unit::Assertions#assert_not_operator} - * {Test::Unit::Assertions#refute_operator} - * Improved code readability. [Suggested by Kenichi Kamiya] - * Made license field in RubyGems parseable. - [GitHub#60][Patch by Michael Grosser] - * Improved test case match feature by `--testcase` and `--ignore-testcase` - options. They also checks parent class names. - * Made inspected representation of Numeric objects especially - BigDecimal more readable. [GitHub#64][Reported by Byron Appelt] - * Added badges for Traivs CI and RubyGems. - [GitHub#65][Patch by Byron Appelt] - * Supported Power Assert. You can use Power Assert with - {Test::Unit::Assertions#assert} with block. See method document - for details. We recommend using Power Assert for predicate method - checks. For example, we recommend Power Assert rather than - {Test::Unit::Assertions#assert_true}, - {Test::Unit::Assertions#assert_predicate} and so on. We don't - recommend using Power Assert for equality check assertion. - {Test::Unit::Assertions#assert_equal} should be used for the case. - [Kazuki Tsujimoto] - -### Fixes - - * Fixed a bug that test case defined by block has wrong location. - [GitHub#58][Patch by Narihiro Nakamura] - * Fixed a bug that test methods defined in included modules in - super-class are also collected. - [GitHub#62][GitHub#63][Patch by Karol Bucek] - -### Thanks - - * Ryo Onodera - * Kenichi Kamiya - * Karol Bucek - * Narihiro Nakamura - * Michael Grosser - * Byron Appelt - * Kazuki Tsujimoto - -## 2.5.5 - 2013-05-18 {#version-2-5-5} - -It's Ruby 2.0.0 supported release! - -### Improvements - - * Supported Ruby 2.0.0. [GitHub#54] [Reported by mtasaka] - * Accepted screen-256color TERM as 256 colors available environment. - [GitHub#55] [Reported by Tom Miller] - -### Fixes - - * Fixed a typo in document. - [GitHub#53] [Patch by Baptiste Fontaine] - * Fixed a bug in {Test::Unit::Assertions#assert_in_epsilon}. It doesn't work - as expected if expected value is negative value. - [Ruby Bug #8317] [Reported by Nobuhiro IMAI] - -### Thanks - - * Baptiste Fontaine - * mtasaka - * Tom Miller - * Nobuhiro IMAI - -## 2.5.4 - 2013-01-23 {#version-2-5-4} - -It's a bug fix release. - -### Improvements - - * Added documents for data driven test functionality. - * Added TSV support for data driven test functionality. - * Support tag inspection on JRuby. - -### Fixes - - * Fixed a bug. It is too slow to filter tests when there are many - tests. [GitHub#46] - * Accept anonymous test suite. - [GitHub:#49] [Reported by Matthew Rudy Jacobs] - -### Thanks - - * Matthew Rudy Jacobs - -## 2.5.3 - 2012-11-28 {#version-2-5-3} - -It's a release for minitest compatibility and bug fix. - -### Improvements - - * Supported diff in invalid encoding. - * Added some assersion methods just for minitest compatibility. - Added methods are assert_includes(), refute_*() and refute(). - If you are test-unit user, please don't use them. - [GitHub#40] [Suggested by Michael Grosser] - * Added --attribute option to select target tests by attribute. - [test-unit-users-en:00098] [Suggested by Piotr Nestorow] - -### Fixes - - * Allowed use of test for inheritance in ActionController::TestCase. - [GitHub#42] [Patch by David Rasch] - * Ensured evaluating at_exit block in top level. - In IRB context, exit() specifies irb_exit(). - [test-unit-users-en:00089] [Reported by Daniel Berger] - * Fixed a bug that decoration style description is ignored. - "decoration style description" are using description method - above "def test_name" or with Symbol specifying test_name. - [GitHub#45] [Reported by Piotr Nestorow] - -### Thanks - - * Michael Grosser - * David Rasch - * Daniel Berger - * Piotr Nestorow - -## 2.5.2 - 2012-08-29 {#version-2-5-2} - -It's an improvement release for tmtms. `--location` is a similar -feature to `--line_number` in RSpec. `sub_test_case` is a similar -feature to `context` in shoulda-context and RSpec. - -### Improvements - - * Cleaned up tests. - [GitHub#34] [Patch by Michael Grosser] - * Added missing background color for 8 color environment. - * Added workaround for NetBeans. - [GitHub#38] [Reported by Marc Cooper] - * Added `--location` command line option that selects target tests - by test defined location. - * Created sub test suite for each subclassed test case. - * [ui][console] Supported nested test suites. - * Added {Test::Unit.at_start} and {Test::Unit.at_exit} hooks that - are run before/after all tests are run. - [Good hook name is suggested by kdmsnr] - * Improved code snippet target on failure. Test method is always used - for code snippet target. - [GitHub#39] [Suggested by Michael Grosser] - * Added {Test::Unit::TestCase.sub_test_case} that creates sub test case. - The sub test case name isn't limited Ruby's constant name rule. You can - specify the sub test case name in free form. - -### Thanks - - * Michael Grosser - * Marc Cooper - * kdmsnr - -## 2.5.1 - 2012-07-05 {#version-2-5-1} - -It's a bug fix release. - -### Improvements - - * Supported installing from GitHub. - [GitHub#29] [Suggested by Michael Grosser] - * Supported ActiveSupport::TestCase. - [GitHub#30] [Reported by Michael Grosser] - * [ui][console] Improved multiline falut message display. - -### Fixes - - * [ui][console] Fixed a bug that expected and actual values are - empty. - [GitHub#31][GitHub#33] - [Reported by Kendall Buchanan][Reported by Mathieu Martin] - [Hinted by Michael Grosser] - * Fixed a bug that .gemspec can't be loaded on LANG=C. - [RubyForge#29595] [Reported by Jean-Denis Koeck] - -### Thanks - - * Michael Grosser - * Kendall Buchanan - * Mathieu Martin - * Jean-Denis Koeck - -## 2.5.0 - 2012-06-06 {#version-2-5-0} - -It's a bug fix release. - -### Fixes - - * Fixed a backward incompatibility of `TestUnitMediator#run_suite` - introduced in 2.4.9. - [GitHub#28] [Reported by Vladislav Rassokhin] - -### Thanks - - * Vladislav Rassokhin - -## 2.4.9 - 2012-06-03 {#version-2-4-9} - -It's a bug fix release. - -### Improvements - - * `Test::Unit.run?` -> - `Test::Unit::AutoRunner.need_auto_run?`. `Test::Unit.run?` is marked - as deprecated but it is still available. - * [experimental] Added top level "run" method for `"ruby -rtest-unit -e - run test/test_*.rb"`. Is this API OK or dirty? - * Made failure output more readable on no color mode. - * Supported showing ASCII-8BIT diff in failure message. - * [ui][console] Supported `ENV["TERM"] == "xterm-256color"` as color - available terminal. - [GitHub#26] [Reported by Michael Grosser] - * [ui][console] Supported "-256color" suffix `ENV["TERM"]` terminal - as 256 color supported terminal. - -### Fixes - - * Fixed a bug that `--workdir` doesn't work. - * Consumed processed command line parameters in `ARGV` as `--help` - says. - [RubyForge#29554] [Reported by Bob Saveland] - * Added missing `require "test/unit/diff"`. - [GitHub#25] [Reported by Stephan Kulow] - -### Thanks - - * Bob Saveland - * Stephan Kulow - * Michael Grosser - -## 2.4.8 - 2012-3-6 {#version-2-4-8} - -It's a bug fix release. - -### Improvements - - * Delayed at_exit registration until Test::Unit is used. - [GitHub:#21] [Reported by Jason Lunn] - * Added workaround for test-spec. - [GitHub:#22] [Reported by Cédric Boutillier] - -### Fixes - - * Fixed an error on code snippet display on JRuby. - [GitHub:#19][GitHub:#20] - [Reported by Jørgen P. Tjernø][Patch by Junegunn Choi] - -### Thanks - - * Jørgen P. Tjernø - * Junegunn Choi - * Jason Lunn - -## 2.4.7 - 2012-2-10 {#version-2-4-7} - -It's a code snippet improvement release. - -### Improvements - - * Supported code snippet display on all faults. - -## 2.4.6 - 2012-2-9 {#version-2-4-6} - -It's a TAP runner separated release. - -### Improvements - - * Moved TAP runner to test-unit-runner-tap gem from test-unit gem. - * Supported code snippet display on failure. - -## 2.4.5 - 2012-1-16 {#version-2-4-5} - -It's a failure message readability improvement release. - -### Improvements - - * Removed needless information from exception inspected - text on failure. It's for easy to read. - * Supported custom inspector. - -## 2.4.4 - 2012-1-2 {#version-2-4-4} - -It's a Rails integration improved release. - -### Improvements - - * [ui][console] Don't break progress display when a test is failed. - * [ui][console] Added markers betwen a failure detail - message in progress to improve visibility. - * [travis] Dropped Ruby 1.8.6 as a test target. [GitHub:#13] - [Patch by Josh Kalderimis] - * Supported expected value == 0 case in assert_in_epsilon. [RubyForge#29485] - [Reported by Syver Enstad] - * Supported a block style setup/teardown/cleanup. - -### Thanks - - * Josh Kalderimis - * Syver Enstad - -## 2.4.3 - 2011-12-11 {#version-2-4-3} - -### Improvements - - * Improved SimpleCov integration by stopping to modify - `ARGV` in auto runner. [GitHub:#12] - [Reported by Nikos Dimitrakopoulos] - * Improved JRuby integration by removing JRuby internal backtrace. - -### Thanks - - * Nikos Dimitrakopoulos - -## 2.4.2 - 2011-11-26 {#version-2-4-2} - -### Improvements - - * `--name` supported data label. - -## 2.4.1 - 2011-11-09 - -### Improvements - - * Accepted AssertionMessage as assertion's user message. - It is used in assert_select in actionpack. - [Reported by David Heath] - -### Fixes - - * Fixed test failure on LANG=C. #11 [Reported by boutil] - * Suppress warnings on Ruby 1.9.2. - -### Thanks - - * boutil - * David Heath - -## 2.4.0 - 2011-09-18 - -### Improvements - - * Supported Travis CI. #5 [Suggested by James Mead] - * Added Gemfile. #6 [Suggested by James Mead] - * [ui][console] Supported notification in show-detail-immediately. - * [ui][console] enable --show-detail-immediately by default. - * [ui] Added --max-diff-target-string-size option. - * [ui][console] Supported 256 colors. - -### Fixes - - * Added missing fixture file. #7 [Reported by grafi-tt] - * [ui][console] Added missing the last newline for progress level. - * Supported correct backtrace for redefined notification. - * Don't handle Timeout::Error as pass through exception on Ruby 1.8. #8 - [Reported by Marc Seeger (Acquia)] - -### Thanks - - * James Mead - * grafi-tt - * Marc Seeger (Acquia) - -## 2.3.2 - 2011-08-15 - -A bug fix release. - -### Improvements - - * [ui][console] Added some newlines to improve readability. - -### Fixes - - * [ui][console] Worked --verbose again. - * Re-supported Ruby 1.8.6. [Reported by James Mead] - -### Thanks - - * James Mead - -## 2.3.1 - 2011-08-06 {#version-2-3-1} - -Output improvement release! - -### Improvements - - * [ui][console] Outputs omissions and notifications in short. - * [ui][console] Added "important-only" verbose level. - * Intelligence diff supports recursive references. - * [rubyforge #29325] Supported Ruby Enterprise Edition. - [Reported by Hans de Graaff] - * [rubyforge #29326] Supported JRuby. - [Reported by Hans de Graaff] - * Added --show-detail-immediately option that shows - fault details when a fault is occurred. - -### Fixes - - * [pull request #1] Fixed a problem that load collector - can't load a test file on Ruby 1.9. [Patch by grafi-tt] - * [issue #3] Fixed a problem that implicit method name - override by declarative style test definition. - [Reported by Jeremy Stephens] - -### Thanks - - * grafi-tt - * Jeremy Stephens - * Hans de Graaff - -## 2.3.0 / 2011-04-17 - -* 13 enhancements - * improve Hash key sorting for diff. - * [#28928] support any characters in declarative style description. - [Daniel Berger] - * add Error#location and make #backtrace deprecated. - * make TestCase#passed? public. - * add result finished and pass assertion notifications. - * add TestSuite#passed? public. - * add XML test runner. - * add --output-file-descriptor option. - * measure elapsed time for each test. - * add --collector option. - * support test driven test. - [Haruka Yoshihara] - * add cleanup hook it runs between after test and before teardown. - * support recursive collection sort for diff. - -* Thanks - * Daniel Berger - * Haruka Yoshihara - -## 2.2.0 / 2011-02-14 - -* 22 enhancements - * [#28808] accept String as delta for assert_in_delta. - [Daniel Berger] - * [test-unit-users-en:00035] make GC-able finished tests. - [Daniel Berger] - * use also COLUMNS environment variable to guess terminal width. - * make delta for assert_in_delta optional. - [Nobuyoshi Nakada] - * add assert_not_respond_to. - [Nobuyoshi Nakada] - * add assert_not_match. assert_no_match is deprecated. - [Nobuyoshi Nakada] - * add assert_not_in_delta. - [Nobuyoshi Nakada] - * add assert_in_epsilon. - [Nobuyoshi Nakada] - * add assert_not_in_epsilon. - [Nobuyoshi Nakada] - * add assert_include. - [Nobuyoshi Nakada] - * add assert_not_include. - [Nobuyoshi Nakada] - * add assert_empty. - [Nobuyoshi Nakada] - * add assert_not_empty. - [Nobuyoshi Nakada] - * notify require failed paths. - * validate message value for assert. - * show throughputs at the last. - * support not ASCII compatible string diff. - * support colorized diff on encoding different string. - * normalize entry order of Hash for readable diff. - * add --ignore-name option. - * add --ignore-testcase option. - * add assert_not_send. - -* Thanks - * Daniel Berger - * Nobuyoshi Nakada - -## 2.1.2 / 2010-11-25 - -* 1 enhancement - * support auto runner prepare hook. - -## 2.1.1 / 2010-07-29 - -* 1 bug fix - * [test-unit-users-en:00026] re-work tap runner. - [Daniel Berger] - -* Thanks - * Daniel Berger - -=== 2.1.0 / 2010-07-17 - -* 1 bug fix - * [#28267] global config file ignored - [Daniel Berger] - -* Thanks - * Daniel Berger - -## 2.0.8 / 2010-06-02 - -* 5 major enchancements - * collect *_test.rb and *-test.rb files as test files. - * [#28181] improve assert_in_delta message. - [Suggested by David MARCHALAND] - * show string encoding in assert_equal failure message if - they are different. - * change default color scheme: - * success: green back + white - * failure: red back + white - * add capture_output. - -* 2 bug fixes - * fix a bug that console runner on verbose mode causes an - error for long test name (>= 61). - * [#28093] Autorunner ignores all files in a directory named test by default - [Reported by Florian Frank] - -* Thanks - * Florian Frank - * David MARCHALAND - -## 2.0.7 / 2010-03-09 - -* 4 major enhancements - * detect redefined test methods. - * [INTERFACE IMCOMPATIBLE] multiple --name and --testcase - options narrow down targets instead of adding targets. - * [#27764] accept custom test_order for each test case. - [Suggested by David MARCHALAND] - * [#27790] ignore omitted tests from 'n% passed' report. - [Suggested by Daniel Berger] - -* 2 minor enchancements - * [#27832] ignore .git directory. [Suggested by Daniel Berger] - * [#27792] require 'fileutils' and 'tmpdir' lazily for non-priority - mode users. [Suggested by David MARCHALAND] - -* 2 bug fixes - * [#27892] modify processed arguments array destructively. - [Reported by Bob Saveland] - * work without HOME environment variable. - [Reported by Champak Ch] - -* Thanks - * David MARCHALAND - * Daniel Berger - * Bob Saveland - * Champak Ch - -## 2.0.6 / 2010-01-09 - -* 3 major enhancements - * [#27380] Declarative syntax? [Daniel Berger] - support declarative syntax: - - test "test description in natural language" do - ... - end - * support test description: - description "test description in natural language" - def test_my_test - ... - end - * make max diff target string size customizable by - TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE environment variable. - -* 2 bug fixes - * [#27374] omit_if unexpected behavior [David MARCHALAND] - * fix a bug that tests in sub directories aren't load with --basedir. - [Daniel Berger] - -* Thanks - * David MARCHALAND - * Daniel Berger - -## 2.0.5 / 2009-10-18 - -* 1 bug fixes - * [#27314] fix diff may raise an exception. [Erik Hollensbe] - -* Thanks - * Erik Hollensbe - -## 2.0.4 / 2009-10-17 - -* 4 major enhancements - * use ~/.test-unit.yml as global configuration file. - * add TAP runner. (--runner tap) - * support colorized diff: - http://test-unit.github.io/color-diff.png - * add Test::Unit::AutoRunner.default_runner= to specify default test runner. - -* 4 minor enhancements - * improve verbose mode output format. (use indent) - * support `NOT_PASS_THROUGH_EXCEPTIONS`. - * support arguments option in `#{runner}_options`. - * TC_ -> Test in sample test case name. - -* 1 bug fixes - * [#27195] test-unit-2.0.3 + ruby-1.9.1 cannot properly test - DelegateClass subclasses [Mike Pomraning] - -* Thanks - * Mike Pomraning - -## 2.0.3 / 2009-07-19 - -* 6 major enhancements - * add assert_predicate. - * add assert_not_predicate. - * [#24210] assert_kind_of supports an array of classes or modules. - [Daniel Berger] - * assert_instance_of supports an array of classes or modules. - * add --default-priority option. - * [#26627] add --order option. [Daniel Berger] - -* 4 minor enhancements - * use yellow foreground + black background for error. - * don't show diff for long string. - * accept "*term-color" TERM environment as colorizable terminal. - (e.g. Apple's Terminal) - * [#26268] add a workaround for test-spec's after_all. [Angelo Lakra] - -* 1 bug fix - * [#23586] re-support ruby 1.9.1. [Diego Pettenò] - -* Thanks - * Diego Pettenò - * Daniel Berger - * Angelo Lakra - -## 2.0.2 / 2008-12-21 - -* 2 major enhancements - - * re-support ruby 1.8.5. - * improve exception object comparison. - -* 3 bug fixes - - * [#22723]: collector fails on anonymous classes - * [#22986]: Test names with '?' blow up on Windows - * [#22988]: don't create .test-result on non-priority mode. - -* Thanks - - * Erik Hollensbe - * Daniel Berger - * Bill Lear - -## 2.0.1 / 2008-11-09 - -* 19 major enhancements - - * support ruby 1.9.1. - * add run_test method to be extensible. - * improve priority-mode auto off. - * improve startup/shutdown RDoc. [Daniel Berger] - * add assert_compare. [#20851] [Designing Patterns] - * add assert_fail_assertion. [#20851] [Designing Patterns] - * add assert_raise_message. [#20851] [Designing Patterns] - * support folded diff. - * add assert_raise_kind_of. [Daniel Berger] - * ingore inherited test for nested test case. - * add assert_const_defined. - * add assert_not_const_defined. - * support assert_raise with an exception object. - * support assert_raise with no arguments that asserts any - exception is raised. [#22602] [Daniel Berger] - * support folded dot progress. - * add --progress-row-max option. - * support color scheme customize. - * support configuration file. (YAML) - * recognize test-XXX.rb files as test files not only test_XXX.rb - -* Thanks - - * Daniel Berger - * Designing Patterns - -## 2.0.0 / 2008-06-18 - -* 15 major enhancements - - * support startup/shutdown. (test case level setup/teardown) - * support multiple setup/teardown. - * support pending. - * support omission. - * support notification. - * support colorize. - * support diff. - * support test attribute. - * add assert_boolean. - * add assert_true. - * add assert_false. - * add --priority-mode option. - * don't use ObjectSpace to collect test cases. - * make more customizable. (additional options, exception handling and so on) - * improve Emacs integration. - -* 4 major changes - - * remove GTK+1 support. - * split GTK+ runner as another gem. - * split FOX runner as another gem. - * split Tk runner as another gem. - -## 1.2.3 / 2008-02-25 - -* 1 major enhancement - - * Birthday (as a gem)! diff --git a/ruby/gems/test-unit-3.3.4/lib/test-unit.rb b/ruby/gems/test-unit-3.3.4/lib/test-unit.rb deleted file mode 100644 index 25abbdc33..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test-unit.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2012-2015 Kouhei Sutou -# -# License: Ruby's or LGPLv2.1 or later -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -module Test - module Unit - autoload :TestCase, "test/unit/testcase" - autoload :AutoRunner, "test/unit/autorunner" - end -end - -unless respond_to?(:run_test, true) - # experimental. It is for "ruby -rtest-unit -e run_test test/test_*.rb". - # Is this API OK or dirty? - def run_test - self.class.send(:undef_method, :run_test) - require "test/unit" - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit.rb deleted file mode 100644 index 1e962e869..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit.rb +++ /dev/null @@ -1,514 +0,0 @@ -require 'test/unit/testcase' -require 'test/unit/autorunner' - -module Test # :nodoc: - # - # # Test::Unit - Ruby Unit Testing Framework - # - # ## Introduction - # - # Unit testing is making waves all over the place, largely due to the - # fact that it is a core practice of XP. While XP is great, unit testing - # has been around for a long time and has always been a good idea. One - # of the keys to good unit testing, though, is not just writing tests, - # but having tests. What's the difference? Well, if you just _write_ a - # test and throw it away, you have no guarantee that something won't - # change later which breaks your code. If, on the other hand, you _have_ - # tests (obviously you have to write them first), and run them as often - # as possible, you slowly build up a wall of things that cannot break - # without you immediately knowing about it. This is when unit testing - # hits its peak usefulness. - # - # Enter Test::Unit, a framework for unit testing in Ruby, helping you to - # design, debug and evaluate your code by making it easy to write and - # have tests for it. - # - # - # ## Notes - # - # Test::Unit has grown out of and superceded Lapidary. - # - # - # ## Feedback - # - # I like (and do my best to practice) XP, so I value early releases, - # user feedback, and clean, simple, expressive code. There is always - # room for improvement in everything I do, and Test::Unit is no - # exception. Please, let me know what you think of Test::Unit as it - # stands, and what you'd like to see expanded/changed/improved/etc. If - # you find a bug, let me know ASAP; one good way to let me know what the - # bug is is to submit a new test that catches it :-) Also, I'd love to - # hear about any successes you have with Test::Unit, and any - # documentation you might add will be greatly appreciated. My contact - # info is below. - # - # - # ## Contact Information - # - # A lot of discussion happens about Ruby in general on the ruby-talk - # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask - # any questions you might have there. I monitor the list, as do many - # other helpful Rubyists, and you're sure to get a quick answer. Of - # course, you're also welcome to email me (Nathaniel Talbott) directly - # at mailto:testunit@talbott.ws, and I'll do my best to help you out. - # - # - # ## Credits - # - # I'd like to thank... - # - # Matz, for a great language! - # - # Masaki Suketa, for his work on RubyUnit, which filled a vital need in - # the Ruby world for a very long time. I'm also grateful for his help in - # polishing Test::Unit and getting the RubyUnit compatibility layer - # right. His graciousness in allowing Test::Unit to supercede RubyUnit - # continues to be a challenge to me to be more willing to defer my own - # rights. - # - # Ken McKinlay, for his interest and work on unit testing, and for his - # willingness to dialog about it. He was also a great help in pointing - # out some of the holes in the RubyUnit compatibility layer. - # - # Dave Thomas, for the original idea that led to the extremely simple - # "require 'test/unit'", plus his code to improve it even more by - # allowing the selection of tests from the command-line. Also, without - # RDoc, the documentation for Test::Unit would stink a lot more than it - # does now. - # - # Everyone who's helped out with bug reports, feature ideas, - # encouragement to continue, etc. It's a real privilege to be a part of - # the Ruby community. - # - # The guys at RoleModel Software, for putting up with me repeating, "But - # this would be so much easier in Ruby!" whenever we're coding in Java. - # - # My Creator, for giving me life, and giving it more abundantly. - # - # - # ## License - # - # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free - # software, and is distributed under the Ruby license. See the COPYING - # file. - # - # Exception: lib/test/unit/diff.rb is copyright (c) - # 2008-2010 Kouhei Sutou and 2001-2008 Python Software - # Foundation. It is free software, and is distributed - # under the Ruby license and/or the PSF license. See the - # COPYING file and PSFL file. - # - # ## Warranty - # - # This software is provided "as is" and without any express or - # implied warranties, including, without limitation, the implied - # warranties of merchantibility and fitness for a particular - # purpose. - # - # - # ## Author - # - # Nathaniel Talbott. - # Copyright (c) 2000-2003, Nathaniel Talbott - # - # ---- - # - # # Usage - # - # The general idea behind unit testing is that you write a _test_ - # _method_ that makes certain _assertions_ about your code, working - # against a _test_ _fixture_. A bunch of these _test_ _methods_ are - # bundled up into a _test_ _suite_ and can be run any time the - # developer wants. The results of a run are gathered in a _test_ - # _result_ and displayed to the user through some UI. So, lets break - # this down and see how Test::Unit provides each of these necessary - # pieces. - # - # - # ## Assertions - # - # These are the heart of the framework. Think of an assertion as a - # statement of expected outcome, i.e. "I assert that x should be equal - # to y". If, when the assertion is executed, it turns out to be - # correct, nothing happens, and life is good. If, on the other hand, - # your assertion turns out to be false, an error is propagated with - # pertinent information so that you can go back and make your - # assertion succeed, and, once again, life is good. For an explanation - # of the current assertions, see Test::Unit::Assertions. - # - # - # ## Test Method & Test Fixture - # - # Obviously, these assertions have to be called within a context that - # knows about them and can do something meaningful with their - # pass/fail value. Also, it's handy to collect a bunch of related - # tests, each test represented by a method, into a common test class - # that knows how to run them. The tests will be in a separate class - # from the code they're testing for a couple of reasons. First of all, - # it allows your code to stay uncluttered with test code, making it - # easier to maintain. Second, it allows the tests to be stripped out - # for deployment, since they're really there for you, the developer, - # and your users don't need them. Third, and most importantly, it - # allows you to set up a common test fixture for your tests to run - # against. - # - # What's a test fixture? Well, tests do not live in a vacuum; rather, - # they're run against the code they are testing. Often, a collection - # of tests will run against a common set of data, also called a - # fixture. If they're all bundled into the same test class, they can - # all share the setting up and tearing down of that data, eliminating - # unnecessary duplication and making it much easier to add related - # tests. - # - # Test::Unit::TestCase wraps up a collection of test methods together - # and allows you to easily set up and tear down the same test fixture - # for each test. This is done by overriding #setup and/or #teardown, - # which will be called before and after each test method that is - # run. The TestCase also knows how to collect the results of your - # assertions into a Test::Unit::TestResult, which can then be reported - # back to you... but I'm getting ahead of myself. To write a test, - # follow these steps: - # - # * Make sure Test::Unit is in your library path. - # * require 'test/unit' in your test script. - # * Create a class that subclasses Test::Unit::TestCase. - # * Add a method that begins with "test" to your class. - # * Make assertions in your test method. - # * Optionally define #setup and/or #teardown to set up and/or tear - # down your common test fixture. - # * You can now run your test as you would any other Ruby - # script... try it and see! - # - # A really simple test might look like this (#setup and #teardown are - # commented out to indicate that they are completely optional): - # - # require 'test/unit' - # - # class MyTest < Test::Unit::TestCase - # # def setup - # # end - # - # # def teardown - # # end - # - # def test_fail - # assert(false, 'Assertion was false.') - # end - # end - # - # - # ## Test Runners - # - # So, now you have this great test class, but you still - # need a way to run it and view any failures that occur - # during the run. There are some test runner; console test - # runner, GTK+ test runner and so on. The console test - # runner is automatically invoked for you if you require - # 'test/unit' and simply run the file. To use another - # runner simply set default test runner ID to - # Test::Unit::AutoRunner: - # - # require 'test/unit' - # Test::Unit::AutoRunner.default_runner = "gtk2" - # - # ## Test Suite - # - # As more and more unit tests accumulate for a given project, it - # becomes a real drag running them one at a time, and it also - # introduces the potential to overlook a failing test because you - # forget to run it. Suddenly it becomes very handy that the - # TestRunners can take any object that returns a Test::Unit::TestSuite - # in response to a suite method. The TestSuite can, in turn, contain - # other TestSuites or individual tests (typically created by a - # TestCase). In other words, you can easily wrap up a group of - # TestCases and TestSuites. - # - # Test::Unit does a little bit more for you, by wrapping - # these up automatically when you require - # 'test/unit'. What does this mean? It means you could - # write the above test case like this instead: - # - # require 'test/unit' - # require 'test_myfirsttests' - # require 'test_moretestsbyme' - # require 'test_anothersetoftests' - # - # Test::Unit is smart enough to find all the test cases existing in - # the ObjectSpace and wrap them up into a suite for you. It then runs - # the dynamic suite using the console TestRunner. - # - # - # ## Configuration file - # - # Test::Unit reads 'test-unit.yml' in the current working - # directory as Test::Unit's configuration file. It can - # contain the following configurations: - # - # * color scheme definitions - # * test runner to be used - # * test runner options - # * test collector to be used - # - # Except color scheme definitions, all of them are - # specified by command line option. - # - # Here are sample color scheme definitions: - # - # color_schemes: - # inverted: - # success: - # name: red - # bold: true - # failure: - # name: green - # bold: true - # other_scheme: - # ... - # - # Here are the syntax of color scheme definitions: - # - # color_schemes: - # SCHEME_NAME: - # EVENT_NAME: - # name: COLOR_NAME - # intensity: BOOLEAN - # bold: BOOLEAN - # italic: BOOLEAN - # underline: BOOLEAN - # ... - # ... - # - # SCHEME_NAME - # : the name of the color scheme - # - # EVENT_NAME - # : one of [success, failure, pending, omission, notification, error] - # - # COLOR_NAME - # : one of [black, red, green, yellow, blue, magenta, cyan, white] - # - # BOOLEAN - # : true or false - # - # You can use the above 'inverted' color scheme with the - # following configuration: - # - # runner: console - # console_options: - # color_scheme: inverted - # color_schemes: - # inverted: - # success: - # name: red - # bold: true - # failure: - # name: green - # bold: true - # - # ## Questions? - # - # I'd really like to get feedback from all levels of Ruby - # practitioners about typos, grammatical errors, unclear statements, - # missing points, etc., in this document (or any other). - # - - module Unit - class << self - # Set true when Test::Unit has run. If set to true Test::Unit - # will not automatically run at exit. - # - # @deprecated Use Test::Unit::AutoRunner.need_auto_run= instead. - def run=(have_run) - AutoRunner.need_auto_run = (not have_run) - end - - # Already tests have run? - # - # @deprecated Use Test::Unit::AutoRunner.need_auto_run? instead. - def run? - not AutoRunner.need_auto_run? - end - - # @api private - @@at_start_hooks = [] - - # Regsiter a hook that is run before running tests. - # To register multiple hooks, call this method multiple times. - # - # Here is an example test case: - # - # Test::Unit.at_start do - # # ... - # end - # - # class TestMyClass1 < Test::Unit::TestCase - # class << self - # def startup - # # ... - # end - # end - # - # def setup - # # ... - # end - # - # def test_my_class1 - # # ... - # end - # - # def test_my_class2 - # # ... - # end - # end - # - # class TestMyClass2 < Test::Unit::TestCase - # class << self - # def startup - # # ... - # end - # end - # - # def setup - # # ... - # end - # - # def test_my_class1 - # # ... - # end - # - # def test_my_class2 - # # ... - # end - # end - # - # Here is a call order: - # - # * at_start - # * TestMyClass1.startup - # * TestMyClass1#setup - # * TestMyClass1#test_my_class1 - # * TestMyClass1#setup - # * TestMyClass1#test_my_class2 - # * TestMyClass2#setup - # * TestMyClass2#test_my_class1 - # * TestMyClass2#setup - # * TestMyClass2#test_my_class2 - # - # @example - # Test::Unit.at_start do - # puts "Start!" - # end - # - # @yield A block that is run before running tests. - # @yieldreturn [void] - # @return [void] - # - # @since 2.5.2 - def at_start(&hook) - @@at_start_hooks << hook - end - - # @api private - def run_at_start_hooks - @@at_start_hooks.each do |hook| - hook.call - end - end - - # @api private - @@at_exit_hooks = [] - - # Regsiter a hook that is run after running tests. - # To register multiple hooks, call this method multiple times. - # - # Here is an example test case: - # - # Test::Unit.at_exit do - # # ... - # end - # - # class TestMyClass1 < Test::Unit::TestCase - # class << self - # def shutdown - # # ... - # end - # end - # - # def teardown - # # ... - # end - # - # def test_my_class1 - # # ... - # end - # - # def test_my_class2 - # # ... - # end - # end - # - # class TestMyClass2 < Test::Unit::TestCase - # class << self - # def shutdown - # # ... - # end - # end - # - # def teardown - # # ... - # end - # - # def test_my_class1 - # # ... - # end - # - # def test_my_class2 - # # ... - # end - # end - # - # Here is a call order: - # - # * TestMyClass1#test_my_class1 - # * TestMyClass1#teardown - # * TestMyClass1#test_my_class2 - # * TestMyClass1#teardown - # * TestMyClass1.shutdown - # * TestMyClass2#test_my_class1 - # * TestMyClass2#teardown - # * TestMyClass2#test_my_class2 - # * TestMyClass2#teardown - # * TestMyClass2.shutdown - # * at_exit - # - # @example - # Test::Unit.at_exit do - # puts "Exit!" - # end - # - # @yield A block that is run after running tests. - # @yieldreturn [void] - # @return [void] - # - # @since 2.5.2 - def at_exit(&hook) - @@at_exit_hooks << hook - end - - # @api private - def run_at_exit_hooks - @@at_exit_hooks.each do |hook| - hook.call - end - end - end - end -end - -Module.new do - at_exit do - if $!.nil? and Test::Unit::AutoRunner.need_auto_run? - exit Test::Unit::AutoRunner.run - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/assertion-failed-error.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/assertion-failed-error.rb deleted file mode 100644 index 474cfa291..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/assertion-failed-error.rb +++ /dev/null @@ -1,25 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -module Test - module Unit - - # Thrown by Test::Unit::Assertions when an assertion fails. - class AssertionFailedError < StandardError - attr_accessor :expected, :actual, :user_message - attr_accessor :inspected_expected, :inspected_actual - def initialize(message=nil, options=nil) - options ||= {} - @expected = options[:expected] - @actual = options[:actual] - @inspected_expected = options[:inspected_expected] - @inspected_actual = options[:inspected_actual] - @user_message = options[:user_message] - super(message) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/assertions.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/assertions.rb deleted file mode 100644 index 57aa1360e..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/assertions.rb +++ /dev/null @@ -1,2256 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# Copyright (c) 2009-2013 Kouhei Sutou. All rights reserved. -# License:: Ruby license. - -require 'test/unit/assertion-failed-error' -require 'test/unit/util/backtracefilter' -require 'test/unit/util/method-owner-finder' -require 'test/unit/diff' - -begin - require 'power_assert' -rescue LoadError, SyntaxError -end - -module Test - module Unit - - ## - # Test::Unit::Assertions contains the standard Test::Unit assertions. - # Assertions is included in Test::Unit::TestCase. - # - # To include it in your own code and use its functionality, you simply - # need to rescue Test::Unit::AssertionFailedError. Additionally you may - # override add_assertion to get notified whenever an assertion is made. - # - # Notes: - # - # * The message to each assertion, if given, will be propagated with the - # failure. - # * It is easy to add your own assertions based on assert_block(). - # - # @example Example Custom Assertion - # - # def deny(boolean, message=nil) - # message = build_message(message, ' is not false or nil.', boolean) - # assert_block(message) do - # not boolean - # end - # end - - module Assertions - - ## - # The assertion upon which all other assertions are based. Passes if the - # block yields true. - # - # @example - # assert_block "Couldn't do the thing" do - # do_the_thing - # end - def assert_block(message="assert_block failed.") - _wrap_assertion do - if (! yield) - options = {} - if message.respond_to?(:user_message) - options[:user_message] = message.user_message - end - raise AssertionFailedError.new(message.to_s, options) - end - end - end - - # @private - NOT_SPECIFIED = Object.new - - # @overload assert(object, message=nil) - # - # Asserts that `object` is not false nor nil. - # - # Normally, you don't need to use this assertion. Use more - # specific assertions such as #assert_equal and - # #assert_include. - # - # @example Pass patterns - # assert(true) # => pass - # assert([1, 2].include?(1)) # => pass - # - # @example Failure patterns - # assert(nil) # => failure - # assert(false) # => failure - # assert([1, 2].include?(5)) # => failure - # - # @param [Object] object The check target. - # @param [String] message The additional user message. It is - # showed when the assertion is failed. - # @return [void] - # - # @overload assert(message=nil) {} - # - # Asserts that the givens block returns not false nor nil. - # - # This style uses Power Assert. It means that you can see each - # object values in method chains on failure. See the following - # example about Power Assert. - # - # @example Power Assert - # coins = [1, 5, 50] - # target_coin = 10 - # assert do - # coins.include?(target_coin) - # end - # # => - # # coins.include?(target_coin) - # # | | | - # # | | 10 - # # | false - # # [1, 5, 50] - # - # We recommend you to use Power Assert for predicate method - # checks rather than existing assertions such as - # #assert_include and #assert_predicate. Power Assert shows - # useful message for debugging. - # - # We don't recommend you use Power Assert for equality - # check. You should use #assert_equal for the case. Because - # #assert_equal shows more useful message for debugging. - # - # @example Pass patterns - # assert {true} # => pass - # assert {[1, 2].include?(1)} # => pass - # - # @example Failure patterns - # assert {nil} # => failure - # assert {false} # => failure - # assert {[1, 2].include?(5)} # => failure - # - # @param [String] message The additional user message. It is - # showed when the assertion is failed. - # @yield [] Given no parameters to the block. - # @yieldreturn [Object] The checked object. - # @return [void] - def assert(object=NOT_SPECIFIED, message=nil, &block) - _wrap_assertion do - have_object = !NOT_SPECIFIED.equal?(object) - if block - message = object if have_object - if defined?(PowerAssert) - PowerAssert.start(block, :assertion_method => __callee__) do |pa| - pa_message = AssertionMessage.delayed_literal(&pa.message_proc) - assertion_message = build_message(message, "?", pa_message) - assert_block(assertion_message) do - pa.yield - end - end - else - assert(yield, message) - end - else - unless have_object - raise ArgumentError, "wrong number of arguments (0 for 1..2)" - end - assertion_message = nil - case message - when nil, String, Proc - when AssertionMessage - assertion_message = message - else - error_message = "assertion message must be String, Proc or " - error_message += "#{AssertionMessage}: " - error_message += "<#{message.inspect}>(<#{message.class}>)" - raise ArgumentError, error_message, filter_backtrace(caller) - end - assertion_message ||= build_message(message, - " is not true.", - object) - assert_block(assertion_message) do - object - end - end - end - end - - # Asserts that `object` is false or nil. - # - # @note Just for minitest compatibility. :< - # - # @param [Object] object The object to be asserted. - # @return [void] - # - # @example Pass patterns - # refute(false) # => pass - # refute(nil) # => pass - # - # @example Failure patterns - # refute(true) # => failure - # refute("string") # => failure - # - # @since 2.5.3 - def refute(object, message=nil) - _wrap_assertion do - assertion_message = nil - case message - when nil, String, Proc - when AssertionMessage - assertion_message = message - else - error_message = "assertion message must be String, Proc or " - error_message += "#{AssertionMessage}: " - error_message += "<#{message.inspect}>(<#{message.class}>)" - raise ArgumentError, error_message, filter_backtrace(caller) - end - assert_block("refute should not be called with a block.") do - !block_given? - end - assertion_message ||= build_message(message, - " is neither nil or false.", - object) - assert_block(assertion_message) do - not object - end - end - end - - ## - # Passes if `expected` == `actual`. - # - # Note that the ordering of arguments is important, since a helpful - # error message is generated when this one fails that tells you the - # values of expected and actual. - # - # @example - # assert_equal 'MY STRING', 'my string'.upcase - def assert_equal(expected, actual, message=nil) - diff = AssertionMessage.delayed_diff(expected, actual) - if expected.respond_to?(:encoding) and - actual.respond_to?(:encoding) and - expected.encoding != actual.encoding - format = <(?) expected but was -(?).? -EOT - full_message = build_message(message, format, - expected, expected.encoding.name, - actual, actual.encoding.name, - diff) - else - full_message = build_message(message, < expected but was -.? -EOT - end - begin - assert_block(full_message) { expected == actual } - rescue AssertionFailedError => failure - _set_failed_information(failure, expected, actual) - raise failure # For JRuby. :< - end - end - - ## - # Passes if the block raises one of the expected - # exceptions. When an expected exception is an Exception - # object, passes if expected_exception == actual_exception. - # - # @example - # assert_raise(RuntimeError, LoadError) do - # raise 'Boom!!!' - # end # -> pass - # - # assert_raise do - # raise Exception, 'Any exception should be raised!!!' - # end # -> pass - # - # assert_raise(RuntimeError.new("XXX")) {raise "XXX"} # -> pass - # assert_raise(MyError.new("XXX")) {raise "XXX"} # -> fail - # assert_raise(RuntimeError.new("ZZZ")) {raise "XXX"} # -> fail - def assert_raise(*args, &block) - assert_expected_exception = Proc.new do |*_args| - message, assert_exception_helper, actual_exception = _args - expected = assert_exception_helper.expected_exceptions - diff = AssertionMessage.delayed_diff(expected, actual_exception) - full_message = build_message(message, - " exception expected but was\n.?", - expected, actual_exception, diff) - begin - assert_block(full_message) do - expected == [] or - assert_exception_helper.expected?(actual_exception) - end - rescue AssertionFailedError => failure - _set_failed_information(failure, expected, actual_exception) - raise failure # For JRuby. :< - end - end - _assert_raise(assert_expected_exception, *args, &block) - end - - # Just for minitest compatibility. :< - alias_method :assert_raises, :assert_raise - - ## - # Passes if the block raises one of the given - # exceptions or sub exceptions of the given exceptions. - # - # @example - # assert_raise_kind_of(SystemCallError) do - # raise Errno::EACCES - # end - def assert_raise_kind_of(*args, &block) - assert_expected_exception = Proc.new do |*_args| - message, assert_exception_helper, actual_exception = _args - expected = assert_exception_helper.expected_exceptions - full_message = build_message(message, - " family exception expected " + - "but was\n.", - expected, actual_exception) - assert_block(full_message) do - assert_exception_helper.expected?(actual_exception, :kind_of?) - end - end - _assert_raise(assert_expected_exception, *args, &block) - end - - - ## - # Passes if `object`.instance_of?(`klass`). When `klass` is - # an array of classes, it passes if any class - # satisfies +object.instance_of?(class). - # - # @example - # assert_instance_of(String, 'foo') # -> pass - # assert_instance_of([Fixnum, NilClass], 100) # -> pass - # assert_instance_of([Numeric, NilClass], 100) # -> fail - def assert_instance_of(klass, object, message=nil) - _wrap_assertion do - if klass.is_a?(Array) - klasses = klass - else - klasses = [klass] - end - assert_block("The first parameter to assert_instance_of should be " + - "a Class or an Array of Class.") do - klasses.all? {|k| k.is_a?(Class)} - end - klass_message = AssertionMessage.maybe_container(klass) do |value| - "<#{value}>" - end - full_message = build_message(message, < was expected to be instance_of\\? -? but was -. -EOT - assert_block(full_message) do - klasses.any? {|k| object.instance_of?(k)} - end - end - end - - ## - # Passes if `object`.instance_of?(`klass`) does not hold. - # When `klass` is an array of classes, it passes if no class - # satisfies +object.instance_of?(class). - # - # @example - # assert_not_instance_of(String, 100) # -> pass - # assert_not_instance_of([Fixnum, NilClass], '100') # -> pass - # assert_not_instance_of([Numeric, NilClass], 100) # -> fail - # - # @since 3.0.0 - def assert_not_instance_of(klass, object, message=nil) - _wrap_assertion do - if klass.is_a?(Array) - klasses = klass - else - klasses = [klass] - end - assert_block("The first parameter to assert_not_instance_of should be " + - "a Class or an Array of Class.") do - klasses.all? {|k| k.is_a?(Class)} - end - klass_message = AssertionMessage.maybe_container(klass) do |value| - "<#{value}>" - end - full_message = build_message(message, - " was expected to not be instance_of\\?\n" + - "? but was.", - object, - klass_message) - assert_block(full_message) do - klasses.none? {|k| object.instance_of?(k)} - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_instance_of, :assert_not_instance_of - - ## - # Passes if `object` is nil. - # - # @example - # assert_nil [1, 2].uniq! - def assert_nil(object, message=nil) - full_message = build_message(message, < was expected to be nil. -EOT - assert_block(full_message) { object.nil? } - end - - ## - # Passes if `object`.kind_of?(`klass`). When `klass` is - # an array of classes or modules, it passes if any - # class or module satisfies +object.kind_of?(class_or_module). - # - # @example - # assert_kind_of(Object, 'foo') # -> pass - # assert_kind_of([Fixnum, NilClass], 100) # -> pass - # assert_kind_of([Fixnum, NilClass], "string") # -> fail - def assert_kind_of(klass, object, message=nil) - _wrap_assertion do - if klass.is_a?(Array) - klasses = klass - else - klasses = [klass] - end - assert_block("The first parameter to assert_kind_of should be " + - "a kind_of Module or an Array of a kind_of Module.") do - klasses.all? {|k| k.kind_of?(Module)} - end - klass_message = AssertionMessage.maybe_container(klass) do |value| - "<#{value}>" - end - full_message = build_message(message, - " was expected to be kind_of\\?\n" + - "? but was\n" + - ".", - object, - klass_message, - object.class) - assert_block(full_message) do - klasses.any? {|k| object.kind_of?(k)} - end - end - end - - ## - # Passes if `object`.kind_of?(`klass`) does not hold. - # When `klass` is an array of classes or modules, it passes only if all - # classes (and modules) do not satisfy +object.kind_of?(class_or_module). - # - # @example - # assert_not_kind_of(Fixnum, 'foo') # -> pass - # assert_not_kind_of([Fixnum, NilClass], '0') # -> pass - # assert_not_kind_of([Fixnum, NilClass], 100) # -> fail - # - # @since 3.0.0 - def assert_not_kind_of(klass, object, message=nil) - _wrap_assertion do - if klass.is_a?(Array) - klasses = klass - else - klasses = [klass] - end - assert_block("The first parameter to assert_not_kind_of should be " + - "a kind_of Module or an Array of a kind_of Module.") do - klasses.all? {|k| k.kind_of?(Module)} - end - klass_message = AssertionMessage.maybe_container(klass) do |value| - "<#{value}>" - end - full_message = build_message(message, - " was expected to not be kind_of\\?\n" + - "? but was.", - object, - klass_message) - assert_block(full_message) do - klasses.none? {|k| object.kind_of?(k)} - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_kind_of, :assert_not_kind_of - - ## - # Passes if `object` .respond_to? `method` - # - # @example - # assert_respond_to 'bugbear', :slice - def assert_respond_to(object, method, message=nil) - _wrap_assertion do - full_message = build_message(message, - ".kind_of\\?(Symbol) or\n" + - ".respond_to\\?(:to_str) expected", - method, method) - assert_block(full_message) do - method.kind_of?(Symbol) or method.respond_to?(:to_str) - end - full_message = build_message(message, - ".respond_to\\?(?) expected\n" + - "(Class: )", - object, method, object.class) - assert_block(full_message) {object.respond_to?(method)} - end - end - - ## - # Passes if `object` does not .respond_to? `method`. - # - # @example - # assert_not_respond_to('bugbear', :nonexistence) # -> pass - # assert_not_respond_to('bugbear', :size) # -> fail - def assert_not_respond_to(object, method, message=nil) - _wrap_assertion do - full_message = build_message(message, - ".kind_of\\?(Symbol) or\n" + - ".respond_to\\?(:to_str) expected", - method, method) - assert_block(full_message) do - method.kind_of?(Symbol) or method.respond_to?(:to_str) - end - full_message = build_message(message, - "!.respond_to\\?(?) expected\n" + - "(Class: )", - object, method, object.class) - assert_block(full_message) {!object.respond_to?(method)} - end - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_respond_to, :assert_not_respond_to - - ## - # Passes if `pattern` =~ `string`. - # - # @example - # assert_match(/\d+/, 'five, 6, seven') - def assert_match(pattern, string, message=nil) - _wrap_assertion do - pattern = case(pattern) - when String - Regexp.new(Regexp.escape(pattern)) - else - pattern - end - full_message = build_message(message, - " was expected to be =~\n.", - pattern, string) - assert_block(full_message) { pattern =~ string } - end - end - - ## - # Passes if `actual` .equal? `expected` (i.e. they are the same - # instance). - # - # @example - # o = Object.new - # assert_same o, o - def assert_same(expected, actual, message=nil) - full_message = build_message(message, < -with id was expected to be equal\\? to - -with id . -EOT - assert_block(full_message) { actual.equal?(expected) } - end - - ## - # Compares the `object1` with `object2` using `operator`. - # - # Passes if object1.__send__(operator, object2) is true. - # - # @example - # assert_operator 5, :>=, 4 - def assert_operator(object1, operator, object2, message=nil) - _wrap_assertion do - full_message = build_message(nil, "\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator) - assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)} - full_message = build_message(message, < was expected to be -? -. -EOT - assert_block(full_message) { object1.__send__(operator, object2) } - end - end - - ## - # Compares the `object1` with `object2` using `operator`. - # - # Passes if object1.__send__(operator, object2) is not true. - # - # @example - # assert_not_operator(5, :<, 4) # => pass - # assert_not_operator(5, :>, 4) # => fail - # - # @since 3.0.0 - def assert_not_operator(object1, operator, object2, message=nil) - _wrap_assertion do - full_message = build_message(nil, "\ngiven as the operator for #assert_not_operator must be a Symbol or #respond_to\\?(:to_str).", operator) - assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)} - full_message = build_message(message, < was expected to not be -? -. -EOT - assert_block(full_message) { ! object1.__send__(operator, object2) } - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_operator, :assert_not_operator - - ## - # Passes if block does not raise an exception. - # - # @example - # assert_nothing_raised do - # [1, 2].uniq - # end - def assert_nothing_raised(*args) - _wrap_assertion do - if args.last.is_a?(String) - message = args.pop - else - message = "" - end - - assert_exception_helper = AssertExceptionHelper.new(self, args) - begin - yield - rescue Exception => e - if ((args.empty? && !e.instance_of?(AssertionFailedError)) || - assert_exception_helper.expected?(e)) - failure_message = build_message(message, "Exception raised:\n?", e) - assert_block(failure_message) {false} - else - raise - end - end - end - end - - ## - # Flunk always fails. - # - # @example - # flunk 'Not done testing yet.' - def flunk(message="Flunked") - assert_block(build_message(message)){false} - end - - ## - # Passes if ! `actual` .equal? `expected` - # - # @example - # assert_not_same Object.new, Object.new - def assert_not_same(expected, actual, message=nil) - full_message = build_message(message, < -with id was expected to not be equal\\? to - -with id . -EOT - assert_block(full_message) { !actual.equal?(expected) } - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_same, :assert_not_same - - ## - # Passes if `expected` != `actual` - # - # @example - # assert_not_equal 'some string', 5 - def assert_not_equal(expected, actual, message=nil) - full_message = build_message(message, - " was expected to be != to\n.", - expected, actual) - assert_block(full_message) { expected != actual } - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_equal, :assert_not_equal - - ## - # Passes if ! `object` .nil? - # - # @example - # assert_not_nil '1 two 3'.sub!(/two/, '2') - def assert_not_nil(object, message=nil) - full_message = build_message(message, - " was expected to not be nil.", - object) - assert_block(full_message){!object.nil?} - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_nil, :assert_not_nil - - ## - # Passes if `regexp` !~ `string` - # - # @example - # assert_not_match(/two/, 'one 2 three') # -> pass - # assert_not_match(/three/, 'one 2 three') # -> fail - def assert_not_match(regexp, string, message=nil) - _wrap_assertion do - assert_instance_of(Regexp, regexp, - " in assert_not_match(, ...) " + - "should be a Regexp.") - full_message = build_message(message, - " was expected to not match\n.", - regexp, string) - assert_block(full_message) { regexp !~ string } - end - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_match, :assert_not_match - - ## - # Deprecated. Use #assert_not_match instead. - # - # Passes if `regexp` !~ `string` - # - # @example - # assert_no_match(/two/, 'one 2 three') # -> pass - # assert_no_match(/three/, 'one 2 three') # -> fail - def assert_no_match(regexp, string, message="") - _wrap_assertion do - assert_instance_of(Regexp, regexp, - "The first argument to assert_no_match " + - "should be a Regexp.") - assert_not_match(regexp, string, message) - end - end - - # @private - class ThrowTagExtractor - @@have_uncaught_throw_error = const_defined?(:UncaughtThrowError) - - UncaughtThrowPatterns = { - NameError => /^uncaught throw `(.+)'$/, - ArgumentError => /^uncaught throw (`.+'|.+)$/, - ThreadError => /^uncaught throw `(.+)' in thread /, - } - - def initialize(error) - @error = error - end - - def extract_tag - tag = nil - if @@have_uncaught_throw_error - return nil unless @error.is_a?(UncaughtThrowError) - tag = @error.tag - else - pattern = UncaughtThrowPatterns[@error.class] - return nil if pattern.nil? - return nil unless pattern =~ @error.message - tag = $1 - end - normalize_tag(tag) - end - - private - def normalize_tag(tag) - case tag - when /\A:/ - tag[1..-1].intern - when /\A`(.+)'\z/ - $1.intern - when String - tag.intern - else - tag - end - end - end - - ## - # Passes if the block throws `expected_object` - # - # @example - # assert_throw(:done) do - # throw(:done) - # end - def assert_throw(expected_object, message=nil, &proc) - _wrap_assertion do - begin - catch([]) {} - rescue TypeError - assert_instance_of(Symbol, expected_object, - "assert_throws expects the symbol that should be thrown for its first argument") - end - assert_block("Should have passed a block to assert_throw.") do - block_given? - end - caught = true - begin - catch(expected_object) do - proc.call - caught = false - end - full_message = build_message(message, - " should have been thrown.", - expected_object) - assert_block(full_message) {caught} - rescue => error - extractor = ThrowTagExtractor.new(error) - tag = extractor.extract_tag - raise if tag.nil? - full_message = build_message(message, - " was expected to be thrown but\n" + - " was thrown.", - expected_object, tag) - flunk(full_message) - end - end - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :assert_throws, :assert_throw - - ## - # Passes if block does not throw anything. - # - # @example - # assert_nothing_thrown do - # [1, 2].uniq - # end - def assert_nothing_thrown(message=nil, &proc) - _wrap_assertion do - assert(block_given?, "Should have passed a block to assert_nothing_thrown") - begin - proc.call - rescue => error - extractor = ThrowTagExtractor.new(error) - tag = extractor.extract_tag - raise if tag.nil? - full_message = build_message(message, - " was thrown when nothing was expected", - tag) - flunk(full_message) - end - assert(true, "Expected nothing to be thrown") - end - end - - ## - # Passes if `expected_float` and `actual_float` are equal - # within `delta` tolerance. - # - # @example - # assert_in_delta 0.05, (50000.0 / 10**6), 0.00001 - def assert_in_delta(expected_float, actual_float, delta=0.001, message="") - _wrap_assertion do - _assert_in_delta_validate_arguments(expected_float, - actual_float, - delta) - full_message = _assert_in_delta_message(expected_float, - actual_float, - delta, - message) - assert_block(full_message) do - (expected_float.to_f - actual_float.to_f).abs <= delta.to_f - end - end - end - - ## - # Passes if `expected_float` and `actual_float` are - # not equal within `delta` tolerance. - # - # @example - # assert_not_in_delta(0.05, (50000.0 / 10**6), 0.00002) # -> pass - # assert_not_in_delta(0.05, (50000.0 / 10**6), 0.00001) # -> fail - def assert_not_in_delta(expected_float, actual_float, delta=0.001, message="") - _wrap_assertion do - _assert_in_delta_validate_arguments(expected_float, - actual_float, - delta) - full_message = _assert_in_delta_message(expected_float, - actual_float, - delta, - message, - :negative_assertion => true) - assert_block(full_message) do - (expected_float.to_f - actual_float.to_f).abs > delta.to_f - end - end - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :refute_in_delta, :assert_not_in_delta - - private - def _assert_in_delta_validate_arguments(expected_float, - actual_float, - delta) - { - expected_float => "first float", - actual_float => "second float", - delta => "delta" - }.each do |float, name| - assert_respond_to(float, :to_f, - "The arguments must respond to to_f; " + - "the #{name} did not") - end - delta = delta.to_f - assert_operator(delta, :>=, 0.0, "The delta should not be negative") - end - - def _assert_in_delta_message(expected_float, actual_float, delta, - message, options={}) - if options[:negative_assertion] - format = <<-EOT - -/+ was expected to not include -. -EOT - else - format = <<-EOT - -/+ was expected to include -. -EOT - end - arguments = [expected_float, delta, actual_float] - normalized_expected = expected_float.to_f - normalized_actual = actual_float.to_f - normalized_delta = delta.to_f - relation_format = nil - relation_arguments = nil - if normalized_actual < normalized_expected - normalized_delta - relation_format = "< < -[?] <= +[?]>" - relation_arguments = [actual_float, - expected_float, delta, - normalized_expected - normalized_delta, - expected_float, delta, - normalized_expected + normalized_delta] - elsif normalized_actual <= normalized_expected + normalized_delta - relation_format = "<-[?] <= <= +[?]>" - relation_arguments = [expected_float, delta, - normalized_expected - normalized_delta, - actual_float, - expected_float, delta, - normalized_expected + normalized_delta] - else - relation_format = "<-[?] <= +[?] < >" - relation_arguments = [expected_float, delta, - normalized_expected - normalized_delta, - expected_float, delta, - normalized_expected + normalized_delta, - actual_float] - end - - if relation_format - format += <<-EOT - -Relation: -#{relation_format} -EOT - arguments.concat(relation_arguments) - end - - build_message(message, format, *arguments) - end - - public - ## - # Passes if `expected_float` and `actual_float` are equal - # within `epsilon` relative error of `expected_float`. - # - # @example - # assert_in_epsilon(10000.0, 9900.0, 0.1) # -> pass - # assert_in_epsilon(10000.0, 9899.0, 0.1) # -> fail - def assert_in_epsilon(expected_float, actual_float, epsilon=0.001, - message="") - _wrap_assertion do - _assert_in_epsilon_validate_arguments(expected_float, - actual_float, - epsilon) - full_message = _assert_in_epsilon_message(expected_float, - actual_float, - epsilon, - message) - assert_block(full_message) do - normalized_expected_float = expected_float.to_f - if normalized_expected_float.zero? - delta = epsilon.to_f ** 2 - else - delta = normalized_expected_float * epsilon.to_f - end - delta = delta.abs - (normalized_expected_float - actual_float.to_f).abs <= delta - end - end - end - - ## - # Passes if `expected_float` and `actual_float` are - # not equal within `epsilon` relative error of - # `expected_float`. - # - # @example - # assert_not_in_epsilon(10000.0, 9900.0, 0.1) # -> fail - # assert_not_in_epsilon(10000.0, 9899.0, 0.1) # -> pass - def assert_not_in_epsilon(expected_float, actual_float, epsilon=0.001, - message="") - _wrap_assertion do - _assert_in_epsilon_validate_arguments(expected_float, - actual_float, - epsilon) - full_message = _assert_in_epsilon_message(expected_float, - actual_float, - epsilon, - message, - :negative_assertion => true) - assert_block(full_message) do - normalized_expected_float = expected_float.to_f - delta = normalized_expected_float * epsilon.to_f - (normalized_expected_float - actual_float.to_f).abs > delta - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_in_epsilon, :assert_not_in_epsilon - - private - def _assert_in_epsilon_validate_arguments(expected_float, - actual_float, - epsilon) - { - expected_float => "first float", - actual_float => "second float", - epsilon => "epsilon" - }.each do |float, name| - assert_respond_to(float, :to_f, - "The arguments must respond to to_f; " + - "the #{name} did not") - end - epsilon = epsilon.to_f - assert_operator(epsilon, :>=, 0.0, "The epsilon should not be negative") - end - - def _assert_in_epsilon_message(expected_float, actual_float, epsilon, - message, options={}) - normalized_expected = expected_float.to_f - normalized_actual = actual_float.to_f - normalized_epsilon = epsilon.to_f - delta = normalized_expected * normalized_epsilon - - if options[:negative_assertion] - format = <<-EOT - -/+ ( * )[?] was expected to not include -. -EOT - else - format = <<-EOT - -/+ ( * )[?] was expected to include -. -EOT - end - arguments = [expected_float, expected_float, epsilon, delta, - actual_float] - - relation_format = nil - relation_arguments = nil - if normalized_actual < normalized_expected - delta - relation_format = "< < -(*)[?] <= +(*)[?]>" - relation_arguments = [actual_float, - expected_float, expected_float, epsilon, - normalized_expected - delta, - expected_float, expected_float, epsilon, - normalized_expected + delta] - elsif normalized_actual <= normalized_expected + delta - relation_format = "<-(*)[?] <= <= +(*)[?]>" - relation_arguments = [expected_float, expected_float, epsilon, - normalized_expected - delta, - actual_float, - expected_float, expected_float, epsilon, - normalized_expected + delta] - else - relation_format = "<-(*)[?] <= +(*)[?] < >" - relation_arguments = [expected_float, expected_float, epsilon, - normalized_expected - delta, - expected_float, expected_float, epsilon, - normalized_expected + delta, - actual_float] - end - - if relation_format - format += <<-EOT - -Relation: -#{relation_format} -EOT - arguments.concat(relation_arguments) - end - - build_message(message, format, *arguments) - end - - public - ## - # Passes if the method send returns a true value. - # - # `send_array` is composed of: - # * A receiver - # * A method - # * Arguments to the method - # - # @example - # assert_send([[1, 2], :member?, 1]) # -> pass - # assert_send([[1, 2], :member?, 4]) # -> fail - def assert_send(send_array, message=nil) - _wrap_assertion do - assert_instance_of(Array, send_array, - "assert_send requires an array " + - "of send information") - assert_operator(send_array.size, :>=, 2, - "assert_send requires at least a receiver " + - "and a message name") - format = < was expected to respond to - with a true value but was -. -EOT - receiver, message_name, *arguments = send_array - result = nil - full_message = - build_message(message, - format, - receiver, - AssertionMessage.literal(message_name.to_s), - arguments, - AssertionMessage.delayed_literal {result}) - assert_block(full_message) do - result = receiver.__send__(message_name, *arguments) - result - end - end - end - - ## - # Passes if the method send doesn't return a true value. - # - # `send_array` is composed of: - # * A receiver - # * A method - # * Arguments to the method - # - # @example - # assert_not_send([[1, 2], :member?, 1]) # -> fail - # assert_not_send([[1, 2], :member?, 4]) # -> pass - def assert_not_send(send_array, message=nil) - _wrap_assertion do - assert_instance_of(Array, send_array, - "assert_not_send requires an array " + - "of send information") - assert_operator(send_array.size, :>=, 2, - "assert_not_send requires at least a receiver " + - "and a message name") - format = < was expected to respond to - with not a true value but was -. -EOT - receiver, message_name, *arguments = send_array - result = nil - full_message = - build_message(message, - format, - receiver, - AssertionMessage.literal(message_name.to_s), - arguments, - AssertionMessage.delayed_literal {result}) - assert_block(full_message) do - result = receiver.__send__(message_name, *arguments) - not result - end - end - end - - ## - # Passes if `actual` is a boolean value. - # - # @example - # assert_boolean(true) # -> pass - # assert_boolean(nil) # -> fail - def assert_boolean(actual, message=nil) - _wrap_assertion do - assert_block(build_message(message, - " or expected but was\n", - actual)) do - [true, false].include?(actual) - end - end - end - - ## - # Passes if `actual` is true. - # - # @example - # assert_true(true) # -> pass - # assert_true(:true) # -> fail - def assert_true(actual, message=nil) - _wrap_assertion do - assert_block(build_message(message, - " expected but was\n", - actual)) do - actual == true - end - end - end - - ## - # Passes if `actual` is false. - # - # @example - # assert_false(false) # -> pass - # assert_false(nil) # -> fail - def assert_false(actual, message=nil) - _wrap_assertion do - assert_block(build_message(message, - " expected but was\n", - actual)) do - actual == false - end - end - end - - ## - # Passes if expression "`expected` `operator` - # `actual`" is true. - # - # @example - # assert_compare(1, "<", 10) # -> pass - # assert_compare(1, ">=", 10) # -> fail - def assert_compare(expected, operator, actual, message=nil) - _wrap_assertion do - assert_send([["<", "<=", ">", ">="], :include?, operator.to_s]) - case operator.to_s - when "<" - operator_description = "less than" - when "<=" - operator_description = "less than or equal to" - when ">" - operator_description = "greater than" - when ">=" - operator_description = "greater than or equal to" - end - template = <<-EOT - #{operator} should be true - was expected to be #{operator_description} -. -EOT - full_message = build_message(message, template, - expected, actual, - expected, actual) - assert_block(full_message) do - expected.__send__(operator, actual) - end - end - end - - ## - # Passes if assertion is failed in block. - # - # @example - # assert_fail_assertion {assert_equal("A", "B")} # -> pass - # assert_fail_assertion {assert_equal("A", "A")} # -> fail - def assert_fail_assertion(message=nil) - _wrap_assertion do - full_message = build_message(message, - "Failed assertion was expected.") - assert_block(full_message) do - begin - yield - false - rescue AssertionFailedError - true - end - end - end - end - - ## - # Passes if an exception is raised in block and its - # message is `expected`. - # - # @example - # assert_raise_message("exception") {raise "exception"} # -> pass - # assert_raise_message(/exc/i) {raise "exception"} # -> pass - # assert_raise_message("exception") {raise "EXCEPTION"} # -> fail - # assert_raise_message("exception") {} # -> fail - def assert_raise_message(expected, message=nil) - _wrap_assertion do - full_message = build_message(message, - " exception message was expected " + - "but none was thrown.", - expected) - exception = nil - assert_block(full_message) do - begin - yield - false - rescue Exception => exception - true - end - end - - actual = exception.message - diff = AssertionMessage.delayed_diff(expected, actual) - full_message = - build_message(message, - " exception message expected but was\n" + - ".?", expected, actual, diff) - assert_block(full_message) do - if expected.is_a?(Regexp) - expected =~ actual - else - expected == actual - end - end - end - end - - ## - # Passes if `object`.const_defined?(`constant_name`) - # - # @example - # assert_const_defined(Test, :Unit) # -> pass - # assert_const_defined(Object, :Nonexistent) # -> fail - def assert_const_defined(object, constant_name, message=nil) - _wrap_assertion do - full_message = build_message(message, - ".const_defined\\?() expected.", - object, constant_name) - assert_block(full_message) do - object.const_defined?(constant_name) - end - end - end - - ## - # Passes if !`object`.const_defined?(`constant_name`) - # - # @example - # assert_not_const_defined(Object, :Nonexistent) # -> pass - # assert_not_const_defined(Test, :Unit) # -> fail - def assert_not_const_defined(object, constant_name, message=nil) - _wrap_assertion do - full_message = build_message(message, - "!.const_defined\\?() expected.", - object, constant_name) - assert_block(full_message) do - !object.const_defined?(constant_name) - end - end - end - - ## - # Passes if `object`.`predicate` is _true_. - # - # @example - # assert_predicate([], :empty?) # -> pass - # assert_predicate([1], :empty?) # -> fail - def assert_predicate(object, predicate, message=nil) - _wrap_assertion do - assert_respond_to(object, predicate, message) - actual = object.__send__(predicate) - full_message = build_message(message, - ".? is true value expected but was\n" + - "", - object, - AssertionMessage.literal(predicate), - actual) - assert_block(full_message) do - actual - end - end - end - - ## - # Passes if `object`.`predicate` is not _true_. - # - # @example - # assert_not_predicate([1], :empty?) # -> pass - # assert_not_predicate([], :empty?) # -> fail - def assert_not_predicate(object, predicate, message=nil) - _wrap_assertion do - assert_respond_to(object, predicate, message) - actual = object.__send__(predicate) - full_message = build_message(message, - ".? is false value expected but was\n" + - "", - object, - AssertionMessage.literal(predicate), - actual) - assert_block(full_message) do - not actual - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_predicate, :assert_not_predicate - - ## - # Passes if `object`#`alias_name` is an alias method of - # `object`#`original_name`. - # - # @example - # assert_alias_method([], :length, :size) # -> pass - # assert_alias_method([], :size, :length) # -> pass - # assert_alias_method([], :each, :size) # -> fail - def assert_alias_method(object, alias_name, original_name, message=nil) - _wrap_assertion do - find_method_failure_message = Proc.new do |method_name| - build_message(message, - ".? doesn't exist\n" + - "(Class: )", - object, - AssertionMessage.literal(method_name), - object.class) - end - - alias_method = original_method = nil - assert_block(find_method_failure_message.call(alias_name)) do - begin - alias_method = object.method(alias_name) - true - rescue NameError - false - end - end - assert_block(find_method_failure_message.call(original_name)) do - begin - original_method = object.method(original_name) - true - rescue NameError - false - end - end - - full_message = build_message(message, - " is alias of\n" + - " expected", - alias_method, - original_method) - assert_block(full_message) do - alias_method == original_method - end - end - end - - ## - # Passes if `path` exists. - # - # @example - # assert_path_exist("/tmp") # -> pass - # assert_path_exist("/bin/sh") # -> pass - # assert_path_exist("/nonexistent") # -> fail - def assert_path_exist(path, message=nil) - _wrap_assertion do - failure_message = build_message(message, - " was expected to exist", - path) - assert_block(failure_message) do - File.exist?(path) - end - end - end - - ## - # Passes if `path` doesn't exist. - # - # @example - # assert_path_not_exist("/nonexistent") # -> pass - # assert_path_not_exist("/tmp") # -> fail - # assert_path_not_exist("/bin/sh") # -> fail - def assert_path_not_exist(path, message=nil) - _wrap_assertion do - failure_message = build_message(message, - " was expected to not exist", - path) - assert_block(failure_message) do - not File.exist?(path) - end - end - end - - ## - # Passes if `collection` includes `object`. - # - # @example - # assert_include([1, 10], 1) # -> pass - # assert_include(1..10, 5) # -> pass - # assert_include([1, 10], 5) # -> fail - # assert_include(1..10, 20) # -> fail - def assert_include(collection, object, message=nil) - _wrap_assertion do - assert_respond_to(collection, :include?, - "The collection must respond to :include?.") - full_message = build_message(message, - " was expected to include\n.", - collection, - object) - assert_block(full_message) do - collection.include?(object) - end - end - end - - # Just for minitest compatibility. :< - # - # @since 2.5.3 - alias_method :assert_includes, :assert_include - - ## - # Passes if `collection` doesn't include `object`. - # - # @example - # assert_not_include([1, 10], 5) # -> pass - # assert_not_include(1..10, 20) # -> pass - # assert_not_include([1, 10], 1) # -> fail - # assert_not_include(1..10, 5) # -> fail - def assert_not_include(collection, object, message=nil) - _wrap_assertion do - assert_respond_to(collection, :include?, - "The collection must respond to :include?.") - full_message = build_message(message, - " was expected to not include\n.", - collection, - object) - assert_block(full_message) do - not collection.include?(object) - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :assert_not_includes, :assert_not_include - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_includes, :assert_not_include - - ## - # Passes if `object` is empty. - # - # @example - # assert_empty("") # -> pass - # assert_empty([]) # -> pass - # assert_empty({}) # -> pass - # assert_empty(" ") # -> fail - # assert_empty([nil]) # -> fail - # assert_empty({1 => 2}) # -> fail - def assert_empty(object, message=nil) - _wrap_assertion do - assert_respond_to(object, :empty?, - "The object must respond to :empty?.") - full_message = build_message(message, - " was expected to be empty.", - object) - assert_block(full_message) do - object.empty? - end - end - end - - ## - # Passes if `object` is not empty. - # - # @example - # assert_not_empty(" ") # -> pass - # assert_not_empty([nil]) # -> pass - # assert_not_empty({1 => 2}) # -> pass - # assert_not_empty("") # -> fail - # assert_not_empty([]) # -> fail - # assert_not_empty({}) # -> fail - def assert_not_empty(object, message=nil) - _wrap_assertion do - assert_respond_to(object, :empty?, - "The object must respond to :empty?.") - full_message = build_message(message, - " was expected to not be empty.", - object) - assert_block(full_message) do - not object.empty? - end - end - end - - # Just for minitest compatibility. :< - # - # @since 3.0.0 - alias_method :refute_empty, :assert_not_empty - - ## - # Builds a failure message. `user_message` is added before the - # `template` and `arguments` replaces the '?'s positionally in - # the template. - def build_message(user_message, template=nil, *arguments) - template &&= template.chomp - return AssertionMessage.new(user_message, template, arguments) - end - - private - def _wrap_assertion(&block) - @_assertion_wrapped ||= false - if @_assertion_wrapped - block.call - else - @_assertion_wrapped = true - begin - add_assertion - block.call - ensure - @_assertion_wrapped = false - end - end - end - - public - # Called whenever an assertion is made. Define this in classes - # that include Test::Unit::Assertions to record assertion - # counts. - # - # This is a public API for developers who extend test-unit. - # - # @return [void] - def add_assertion - end - - ## - # Select whether or not to use the pretty-printer. If this option is set - # to false before any assertions are made, pp.rb will not be required. - def self.use_pp=(value) - AssertionMessage.use_pp = value - end - - private - def _assert_raise(assert_expected_exception, *args, &block) - _wrap_assertion do - if args.last.is_a?(String) - message = args.pop - else - message = "" - end - - assert_exception_helper = AssertExceptionHelper.new(self, args) - expected = assert_exception_helper.expected_exceptions - actual_exception = nil - full_message = build_message(message, - " exception was expected " + - "but none was thrown.", - expected) - assert_block(full_message) do - begin - yield - false - rescue Exception => actual_exception - true - end - end - assert_expected_exception.call(message, assert_exception_helper, - actual_exception) - actual_exception - end - end - - def _set_failed_information(failure, expected, actual) - failure.expected = expected - failure.actual = actual - failure.inspected_expected = AssertionMessage.convert(expected) - failure.inspected_actual = AssertionMessage.convert(actual) - end - - class AssertionMessage - @use_pp = true - class << self - attr_accessor :use_pp - - def literal(value) - Literal.new(value) - end - - def delayed_literal(&block) - DelayedLiteral.new(block) - end - - def maybe_container(value, &formatter) - MaybeContainer.new(value, &formatter) - end - - MAX_DIFF_TARGET_STRING_SIZE = 1000 - def max_diff_target_string_size - return @@max_diff_target_string_size if @@max_diff_target_string_size - - size = ENV["TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE"] - if size - begin - size = Integer(size) - rescue ArgumentError - size = nil - end - end - size || MAX_DIFF_TARGET_STRING_SIZE - end - - @@max_diff_target_string_size = nil - def max_diff_target_string_size=(size) - @@max_diff_target_string_size = size - end - - def diff_target_string?(string) - if string.respond_to?(:bytesize) - string.bytesize < max_diff_target_string_size - else - string.size < max_diff_target_string_size - end - end - - def ensure_diffable_string(string) - if string.respond_to?(:encoding) and - !string.encoding.ascii_compatible? - string = string.dup.force_encoding("ASCII-8BIT") - end - string - end - - def prepare_for_diff(from, to) - if !from.is_a?(String) or !to.is_a?(String) - from = convert(from) - to = convert(to) - end - - if diff_target_string?(from) and diff_target_string?(to) - from = ensure_diffable_string(from) - to = ensure_diffable_string(to) - [from, to] - else - [nil, nil] - end - end - - def delayed_diff(from, to) - delayed_literal do - from, to = prepare_for_diff(from, to) - - diff = "" if from.nil? or to.nil? - diff ||= Diff.readable(from, to) - if /^[-+]/ !~ diff - diff = "" - elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff - diff = "\n\ndiff:\n#{diff}" - else - diff = "" - end - - if Diff.need_fold?(diff) - folded_diff = Diff.folded_readable(from, to) - diff += "\n\nfolded diff:\n#{folded_diff}" - end - - diff - end - end - - def convert(object) - if object.is_a?(Exception) - object = AssertExceptionHelper::WrappedException.new(object) - end - inspector = Inspector.new(object) - if use_pp - begin - require "pp" unless defined?(PP) - begin - return PP.pp(inspector, String.new).chomp - rescue NameError - end - rescue LoadError - self.use_pp = false - end - end - inspector.inspect - end - end - - class Inspector - include Comparable - - class << self - def cached_new(object, inspected_objects) - inspected_objects[object.object_id] ||= - new(object, inspected_objects) - end - - @@inspector_classes = [] - def inspector_classes - @@inspector_classes - end - - def register_inspector_class(inspector_class) - @@inspector_classes << inspector_class - end - - def unregister_inspector_class(inspector_class) - @@inspector_classes.delete(inspector_class) - end - end - - attr_reader :object - def initialize(object, inspected_objects={}) - @inspected_objects = inspected_objects - @object = object - @inspected_objects[@object.object_id] = self - @inspect_target = inspect_target - end - - alias_method :native_inspect, :inspect - def inspect - @inspect_target.inspect - end - - def pretty_print(q) - @inspect_target.pretty_print(q) - end - - def pretty_print_cycle(q) - @inspect_target.pretty_print_cycle(q) - end - - def <=>(other) - if other.is_a?(self.class) - @object <=> other.object - else - @object <=> other - end - end - - private - def inspect_target - self.class.inspector_classes.each do |inspector_class| - if inspector_class.target?(@object) - return inspector_class.new(@object, @inspected_objects) - end - end - @object - end - end - - class NumericInspector - Inspector.register_inspector_class(self) - - class << self - def target?(object) - object.is_a?(Numeric) - end - end - - def initialize(numeric, inspected_objects) - @inspected_objects = inspected_objects - @numeric = numeric - end - - def inspect - @numeric.to_s - end - - def pretty_print(q) - q.text(@numeric.to_s) - end - - def pretty_print_cycle(q) - q.text(@numeric.to_s) - end - end - - class HashInspector - Inspector.register_inspector_class(self) - - class << self - def target?(object) - object.is_a?(Hash) or ENV.equal?(object) - end - end - - def initialize(hash, inspected_objects) - @inspected_objects = inspected_objects - @hash = {} - hash.each do |key, value| - key = Inspector.cached_new(key, @inspected_objects) - value = Inspector.cached_new(value, @inspected_objects) - @hash[key] = value - end - end - - def inspect - @hash.inspect - end - - def pretty_print(q) - q.group(1, '{', '}') do - q.seplist(self, nil, :each_pair) do |k, v| - q.group do - q.pp(k) - q.text('=>') - q.group(1) do - q.breakable('') - q.pp(v) - end - end - end - end - end - - def pretty_print_cycle(q) - @hash.pretty_print_cycle(q) - end - - def each_pair - keys = @hash.keys - begin - keys = keys.sort # FIXME: more cleverly - rescue ArgumentError - end - keys.each do |key| - yield(key, @hash[key]) - end - end - end - - class ArrayInspector - Inspector.register_inspector_class(self) - - class << self - def target?(object) - object.is_a?(Array) - end - end - - def initialize(array, inspected_objects) - @inspected_objects = inspected_objects - @array = array.collect do |element| - Inspector.cached_new(element, @inspected_objects) - end - end - - def inspect - @array.inspect - end - - def pretty_print(q) - q.group(1, '[', ']') do - q.seplist(self) do |v| - q.pp(v) - end - end - end - - def pretty_print_cycle(q) - @array.pretty_print_cycle(q) - end - - def each(&block) - @array.each(&block) - end - end - - class Literal - def initialize(value) - @value = value - end - - def inspect - @value.to_s - end - end - - class DelayedLiteral - def initialize(value) - @value = value - end - - def inspect - @value.call.to_s - end - end - - class MaybeContainer - def initialize(value, &formatter) - @value = value - @formatter = formatter - end - - def inspect - if @value.is_a?(Array) - values = @value.collect do |value| - @formatter.call(AssertionMessage.convert(value)) - end - "[#{values.join(', ')}]" - else - @formatter.call(AssertionMessage.convert(@value)) - end - end - end - - class Template - def self.create(string) - parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : []) - self.new(parts) - end - - attr_reader :count - - def initialize(parts) - @parts = parts - @count = parts.find_all{|e| e == '?'}.size - end - - def result(parameters) - raise "The number of parameters does not match the number of substitutions." if(parameters.size != count) - params = parameters.dup - expanded_template = "" - @parts.each do |part| - if part == '?' - param = params.shift - if Object.const_defined?(:Encoding) - expanded_template += concatenatable(param, - expanded_template.encoding) - else - expanded_template += param - end - else - expanded_template += part.gsub(/\\\?/m, '?') - end - end - expanded_template - end - - private - def concatenatable(text, encoding) - if Encoding.compatible?(text, encoding) - text - else - text.dup.force_encoding(encoding) - end - end - end - - include Util::BacktraceFilter - - def initialize(user_message, template_string, parameters) - @user_message = user_message - @template_string = template_string - @parameters = parameters - end - - def convert(object) - self.class.convert(object) - end - - def template - @template ||= Template.create(@template_string) - end - - def user_message - return nil unless @user_message - message = @user_message - message = message.call if message.respond_to?(:call) - message.to_s - end - - def to_s - message_parts = [] - head = user_message - if head and not head.empty? - message_parts << add_period(head) - end - tail = template.result(@parameters.collect{|e| convert(e)}) - message_parts << tail unless(tail.empty?) - message_parts.join("\n") - end - - private - def add_period(string) - (string =~ /\.\Z/ ? string : string + '.') - end - end - - class AssertExceptionHelper - class WrappedException - attr_reader :exception - def initialize(exception) - @exception = exception - end - - def inspect - if default_inspect? - "#{@exception.class.inspect}(<#{@exception.message}>)" - else - @exception.inspect - end - end - - def method_missing(name, *args, &block) - @exception.__send__(name, *args, &block) - end - - private - def default_inspect? - inspect_method = @exception.method(:inspect) - if inspect_method.respond_to?(:owner) and - inspect_method.owner == Exception - true - else - default_inspect_method = Exception.instance_method(:inspect) - default_inspect_method.bind(@exception).call == @exception.inspect - end - end - end - - def initialize(test_case, expected_exceptions) - @test_case = test_case - @expected_exceptions = expected_exceptions - @expected_classes, @expected_modules, @expected_objects = - split_expected_exceptions(expected_exceptions) - end - - def expected_exceptions - exceptions = @expected_exceptions.collect do |exception| - if exception.is_a?(Exception) - WrappedException.new(exception) - else - exception - end - end - if exceptions.size == 1 - exceptions[0] - else - exceptions - end - end - - def expected?(actual_exception, equality=nil) - equality ||= :instance_of? - expected_class?(actual_exception, equality) or - expected_module?(actual_exception) or - expected_object?(actual_exception) - end - - private - def split_expected_exceptions(expected_exceptions) - exception_modules = [] - exception_objects = [] - exception_classes = [] - expected_exceptions.each do |exception_type| - if exception_type.instance_of?(Module) - exception_modules << exception_type - elsif exception_object?(exception_type) - exception_objects << exception_type - elsif exception_class?(exception_type) - exception_classes << exception_type - else - full_message = - @test_case.__send__(:build_message, - nil, - " must be " + - "a subclass of Exception, " + - "an object of Exception subclasses " + - "or a Module", - exception_type) - @test_case.flunk(full_message) - end - end - [exception_classes, exception_modules, exception_objects] - end - - def exception_object?(exception_type) - return true if exception_type.is_a?(Exception) - - if Object.const_defined?(:Java) - return true if exception_type.is_a?(Java::JavaLang::Throwable) - end - - false - end - - def exception_class?(exception_type) - return true if exception_type <= Exception - - if Object.const_defined?(:Java) - return true if exception_type <= Java::JavaLang::Throwable - end - - false - end - - def expected_class?(actual_exception, equality) - @expected_classes.any? do |expected_class| - actual_exception.__send__(equality, expected_class) - end - end - - def expected_module?(actual_exception) - @expected_modules.any? do |expected_module| - actual_exception.is_a?(expected_module) - end - end - - def expected_object?(actual_exception) - @expected_objects.any? do |expected_object| - expected_object == actual_exception or - fallback_exception_object_equal(expected_object, actual_exception) - end - end - - def fallback_exception_object_equal(expected_object, actual_exception) - owner = Util::MethodOwnerFinder.find(expected_object, :==) - if owner == Kernel or owner == Exception - expected_object.class == actual_exception.class and - expected_object.message == actual_exception.message - else - false - end - end - end - - # :startdoc: - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute-matcher.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute-matcher.rb deleted file mode 100644 index 5b5597560..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute-matcher.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Test - module Unit - class AttributeMatcher - def initialize(test) - @test = test - end - - def match?(expression) - matched = instance_eval(expression) - if matched.nil? - false - else - matched - end - end - - def method_missing(name, *args) - if args.empty? - @test[name] - else - super - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute.rb deleted file mode 100644 index ea66c8d69..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/attribute.rb +++ /dev/null @@ -1,227 +0,0 @@ -module Test - module Unit - module Attribute - class StringifyKeyHash < Hash - class << self - def stringify(object) - object.to_s - end - end - - def key?(key) - super(self.class.stringify(key)) - end - - def [](key) - super(self.class.stringify(key)) - end - - def []=(key, value) - super(self.class.stringify(key), value) - end - end - - class << self - def included(base) - base.extend(BaseClassMethods) - base.extend(ClassMethods) - end - end - - module BaseClassMethods - def attributes_table - {} - end - end - - module ClassMethods - def method_added(name) - super - return unless defined?(@current_attributes) - - attributes = {} - kept_attributes = StringifyKeyHash.new - @current_attributes.each do |attribute_name, attribute| - attributes[attribute_name] = attribute[:value] - if attribute[:keep] - keep_hook = attribute[:keep_hook] - attribute = keep_hook.call(attribute) if keep_hook - kept_attributes[attribute_name] = attribute - end - end - set_attributes(name, attributes) - @current_attributes = kept_attributes - end - - # Set an attribute to test methods. - # - # @overload attribute(name, value) - # @example - # attribute :speed, :slow - # def test_my_slow_method - # self[:speed] # => :slow - # end - # - # @param [Object] name the attribute name - # @param [Object] value the attribute value - # @return [void] - # - # @overload attribute(name, value, *method_names) - # @example - # def test_my_slow_method1 - # self[:speed] # => :slow - # end - # - # attribute :speed, :slow, :test_my_slow_method1, :test_my_slow_method2 - # - # def test_my_slow_method2 - # self[:speed] # => :slow - # end - # - # @param [Object] name the attribute name - # @param [Object] value the attribute value - # @param [Array] method_names the test method names set the attribute - # @return [void] - # - # @overload attribute(name, value, options) - # @example - # attribute :speed, :slow, keep: true - # def test_my_slow_method1 - # self[:speed] # => :slow - # end - # - # def test_my_slow_method2 - # self[:speed] # => :slow - # end - # - # @param [Object] name the attribute name - # @param [Object] value the attribute value - # @option options [Boolean] :keep whether or not to set attribute to following test methods - # @return [void] - # - # @overload attribute(name, value, options, *method_names) - # @example - # def test_my_slow_method1 - # self[:speed] # => :slow - # end - # - # # There are no valid options for now. - # attribute :speed, :slow, {}, :test_my_slow_method1 - # - # def test_my_slow_method2 - # self[:speed] # => nil - # end - # - # @param [Object] name the attribute name - # @param [Object] value the attribute value - # @param [Hash] options ignored - # @param [Array] method_names the test method names set the attribute - # @return [void] - def attribute(name, value, options={}, *method_names) - unless options.is_a?(Hash) - method_names << options - options = {} - end - if method_names.empty? - current_attributes[name] = options.merge(:value => value) - else - method_names.each do |method_name| - set_attributes(method_name, {name => value}) - end - end - end - - def current_attributes - @current_attributes ||= StringifyKeyHash.new - end - - def current_attribute(name) - current_attributes[name] || StringifyKeyHash.new - end - - def attributes_table - @attributes_table ||= StringifyKeyHash.new - super.merge(@attributes_table) - end - - def set_attributes(method_name, new_attributes) - return if new_attributes.empty? - @attributes_table ||= StringifyKeyHash.new - @attributes_table[method_name] ||= StringifyKeyHash.new - current_attributes = @attributes_table[method_name] - new_attributes.each do |key, value| - observers = attribute_observers(key) || [] - observers.each do |observer| - observer.call(self, - StringifyKeyHash.stringify(key), - (attributes(method_name) || {})[key], - value, - method_name) - end - current_attributes[key] = value - end - end - - def attributes(method_name) - attributes = attributes_table[method_name] - ancestors.each do |ancestor| - next if ancestor == self - if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute - parent_attributes = ancestor.attributes(method_name) - if attributes - attributes = (parent_attributes || {}).merge(attributes) - else - attributes = parent_attributes - end - break - end - end - attributes || StringifyKeyHash.new - end - - def find_attribute(method_name, name, options={}) - recursive_p = options[:recursive] - recursive_p = true if recursive_p.nil? - - @attributes_table ||= StringifyKeyHash.new - if @attributes_table.key?(method_name) - attributes = @attributes_table[method_name] - if attributes.key?(name) - return attributes[name] - end - end - - return nil unless recursive_p - return nil if self == TestCase - - @cached_parent_test_case ||= ancestors.find do |ancestor| - ancestor != self and - ancestor.is_a?(Class) and - ancestor < Test::Unit::Attribute - end - - @cached_parent_test_case.find_attribute(method_name, name, options) - end - - @@attribute_observers = StringifyKeyHash.new - def register_attribute_observer(attribute_name, observer=nil, &block) - observer ||= Proc.new(&block) - @@attribute_observers[attribute_name] ||= [] - @@attribute_observers[attribute_name] << observer - end - - def attribute_observers(attribute_name) - @@attribute_observers[attribute_name] - end - end - - def attributes - self.class.attributes(@method_name) || StringifyKeyHash.new - end - - def [](name) - self.class.find_attribute(@method_name, name) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/auto-runner-loader.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/auto-runner-loader.rb deleted file mode 100644 index 21f70edb2..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/auto-runner-loader.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "test/unit/test-suite-creator" - -module Test - module Unit - module AutoRunnerLoader - @loaded = false - class << self - def check(test_case, method_name) - return if @loaded - return unless TestSuiteCreator.test_method?(test_case, method_name) - require "test/unit" - @loaded = true - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/autorunner.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/autorunner.rb deleted file mode 100644 index d45463cf0..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/autorunner.rb +++ /dev/null @@ -1,537 +0,0 @@ -require "English" - -require "test/unit/color-scheme" -require "test/unit/priority" -require "test/unit/attribute-matcher" -require "test/unit/testcase" -require "optparse" - -module Test - module Unit - class AutoRunner - RUNNERS = {} - COLLECTORS = {} - ADDITIONAL_OPTIONS = [] - PREPARE_HOOKS = [] - - class << self - def register_runner(id, runner_builder=nil, &block) - runner_builder ||= Proc.new(&block) - RUNNERS[id] = runner_builder - RUNNERS[id.to_s] = runner_builder - end - - def runner(id) - RUNNERS[id.to_s] - end - - @@default_runner = nil - def default_runner - runner(@@default_runner) - end - - def default_runner=(id) - @@default_runner = id - end - - def register_collector(id, collector_builder=nil, &block) - collector_builder ||= Proc.new(&block) - COLLECTORS[id] = collector_builder - COLLECTORS[id.to_s] = collector_builder - end - - def collector(id) - COLLECTORS[id.to_s] - end - - def register_color_scheme(id, scheme) - ColorScheme[id] = scheme - end - - def setup_option(option_builder=nil, &block) - option_builder ||= Proc.new(&block) - ADDITIONAL_OPTIONS << option_builder - end - - def prepare(hook=nil, &block) - hook ||= Proc.new(&block) - PREPARE_HOOKS << hook - end - - def run(force_standalone=false, default_dir=nil, argv=ARGV, &block) - r = new(force_standalone || standalone?, &block) - r.base = default_dir - r.prepare - r.process_args(argv) - r.run - end - - def standalone? - return false unless("-e" == $0) - ObjectSpace.each_object(Class) do |klass| - return false if(klass < TestCase) - end - true - end - - @@need_auto_run = true - def need_auto_run? - @@need_auto_run - end - - def need_auto_run=(need) - @@need_auto_run = need - end - end - - register_collector(:descendant) do |auto_runner| - require "test/unit/collector/descendant" - collector = Collector::Descendant.new - collector.filter = auto_runner.filters - collector.collect($0.sub(/\.rb\Z/, "")) - end - - register_collector(:load) do |auto_runner| - require "test/unit/collector/load" - collector = Collector::Load.new - unless auto_runner.pattern.empty? - collector.patterns.replace(auto_runner.pattern) - end - unless auto_runner.exclude.empty? - collector.excludes.replace(auto_runner.exclude) - end - collector.base = auto_runner.base - collector.default_test_paths = auto_runner.default_test_paths - collector.filter = auto_runner.filters - collector.collect(*auto_runner.to_run) - end - - # JUST TEST! - # register_collector(:xml) do |auto_runner| - # require "test/unit/collector/xml" - # collector = Collector::XML.new - # collector.filter = auto_runner.filters - # collector.collect(auto_runner.to_run[0]) - # end - - # deprecated - register_collector(:object_space) do |auto_runner| - require "test/unit/collector/objectspace" - c = Collector::ObjectSpace.new - c.filter = auto_runner.filters - c.collect($0.sub(/\.rb\Z/, "")) - end - - # deprecated - register_collector(:dir) do |auto_runner| - require "test/unit/collector/dir" - c = Collector::Dir.new - c.filter = auto_runner.filters - unless auto_runner.pattern.empty? - c.pattern.replace(auto_runner.pattern) - end - unless auto_runner.exclude.empty? - c.exclude.replace(auto_runner.exclude) - end - c.base = auto_runner.base - $:.push(auto_runner.base) if auto_runner.base - c.collect(*(auto_runner.to_run.empty? ? ["."] : auto_runner.to_run)) - end - - attr_reader :suite, :runner_options - attr_accessor :filters, :to_run - attr_accessor :default_test_paths - attr_accessor :pattern, :exclude, :base, :workdir - attr_accessor :color_scheme, :listeners - attr_writer :stop_on_failure - attr_writer :runner, :collector - - def initialize(standalone) - @standalone = standalone - @runner = default_runner - @collector = default_collector - @filters = [] - @to_run = [] - @default_test_paths = [] - @color_scheme = ColorScheme.default - @runner_options = {} - @default_arguments = [] - @workdir = nil - @listeners = [] - @stop_on_failure = false - config_file = "test-unit.yml" - if File.exist?(config_file) - load_config(config_file) - else - load_global_config - end - yield(self) if block_given? - end - - def stop_on_failure? - @stop_on_failure - end - - def prepare - PREPARE_HOOKS.each do |handler| - handler.call(self) - end - end - - def process_args(args=ARGV) - begin - args.unshift(*@default_arguments) - options.order!(args) {|arg| add_test_path(arg)} - rescue OptionParser::ParseError => e - puts e - puts options - exit(false) - end - not @to_run.empty? - end - - def options - @options ||= OptionParser.new do |o| - o.banner = "Test::Unit automatic runner." - o.banner += "\nUsage: #{$0} [options] [-- untouched arguments]" - - o.on("-r", "--runner=RUNNER", RUNNERS, - "Use the given RUNNER.", - "(" + keyword_display(RUNNERS) + ")") do |r| - @runner = r - end - - o.on("--collector=COLLECTOR", COLLECTORS, - "Use the given COLLECTOR.", - "(" + keyword_display(COLLECTORS) + ")") do |collector| - @collector = collector - end - - if (@standalone) - o.on("-b", "--basedir=DIR", "Base directory of test suites.") do |b| - @base = b - end - - o.on("-w", "--workdir=DIR", "Working directory to run tests.") do |w| - @workdir = w - end - - o.on("--default-test-path=PATH", - "Add PATH to the default test paths.", - "The PATH is used when user doesn't specify any test path.", - "You can specify this option multiple times.") do |path| - @default_test_paths << path - end - - o.on("-a", "--add=TORUN", Array, - "Add TORUN to the list of things to run;", - "can be a file or a directory.") do |paths| - paths.each do |path| - add_test_path(path) - end - end - - @pattern = [] - o.on("-p", "--pattern=PATTERN", Regexp, - "Match files to collect against PATTERN.") do |e| - @pattern << e - end - - @exclude = [] - o.on("-x", "--exclude=PATTERN", Regexp, - "Ignore files to collect against PATTERN.") do |e| - @exclude << e - end - end - - o.on("-n", "--name=NAME", String, - "Runs tests matching NAME.", - "Use '/PATTERN/' for NAME to use regular expression.") do |name| - name = (%r{\A/(.*)/\Z} =~ name ? Regexp.new($1) : name) - @filters << lambda do |test| - return true if name === test.method_name - return true if name === test.local_name - false - end - end - - o.on("--ignore-name=NAME", String, - "Ignores tests matching NAME.", - "Use '/PATTERN/' for NAME to use regular expression.") do |n| - n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) - case n - when Regexp - @filters << proc {|t| n =~ t.method_name ? false : true} - else - @filters << proc {|t| n != t.method_name} - end - end - - o.on("-t", "--testcase=TESTCASE", String, - "Runs tests in TestCases matching TESTCASE.", - "Use '/PATTERN/' for TESTCASE to use regular expression.") do |n| - n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) - @filters << lambda do |test| - match_test_case_name(test, n) - end - end - - o.on("--ignore-testcase=TESTCASE", String, - "Ignores tests in TestCases matching TESTCASE.", - "Use '/PATTERN/' for TESTCASE to use regular expression.") do |n| - n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) - @filters << lambda do |test| - not match_test_case_name(test, n) - end - end - - o.on("--location=LOCATION", String, - "Runs tests that defined in LOCATION.", - "LOCATION is one of PATH:LINE, PATH or LINE") do |location| - if /\A\d+\z/ =~ location - path = nil - line = location.to_i - else - path, line, = location.split(/:(\d+)/, 2) - line = line.to_i unless line.nil? - end - add_location_filter(path, line) - end - - o.on("--attribute=EXPRESSION", String, - "Runs tests that matches EXPRESSION.", - "EXPRESSION is evaluated as Ruby's expression.", - "Test attribute name can be used with no receiver in EXPRESSION.", - "EXPRESSION examples:", - " !slow", - " tag == 'important' and !slow") do |expression| - @filters << lambda do |test| - matcher = AttributeMatcher.new(test) - matcher.match?(expression) - end - end - - priority_filter = Proc.new do |test| - if @filters == [priority_filter] - Priority::Checker.new(test).need_to_run? - else - nil - end - end - o.on("--[no-]priority-mode", - "Runs some tests based on their priority.") do |priority_mode| - if priority_mode - Priority.enable - @filters |= [priority_filter] - else - Priority.disable - @filters -= [priority_filter] - end - end - - o.on("--default-priority=PRIORITY", - Priority.available_values, - "Uses PRIORITY as default priority", - "(#{keyword_display(Priority.available_values)})") do |priority| - Priority.default = priority - end - - o.on("-I", "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]", - "Appends directory list to $LOAD_PATH.") do |dirs| - $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR)) - end - - color_schemes = ColorScheme.all - o.on("--color-scheme=SCHEME", color_schemes, - "Use SCHEME as color scheme.", - "(#{keyword_display(color_schemes)})") do |scheme| - @color_scheme = scheme - end - - o.on("--config=FILE", - "Use YAML fomat FILE content as configuration file.") do |file| - load_config(file) - end - - o.on("--order=ORDER", TestCase::AVAILABLE_ORDERS, - "Run tests in a test case in ORDER order.", - "(#{keyword_display(TestCase::AVAILABLE_ORDERS)})") do |order| - TestCase.test_order = order - end - - assertion_message_class = Test::Unit::Assertions::AssertionMessage - o.on("--max-diff-target-string-size=SIZE", Integer, - "Shows diff if both expected result string size and " + - "actual result string size are " + - "less than or equal SIZE in bytes.", - "(#{assertion_message_class.max_diff_target_string_size})") do |size| - assertion_message_class.max_diff_target_string_size = size - end - - o.on("--[no-]stop-on-failure", - "Stops immediately on the first non success test", - "(#{@stop_on_failure})") do |boolean| - @stop_on_failure = boolean - end - - ADDITIONAL_OPTIONS.each do |option_builder| - option_builder.call(self, o) - end - - o.on("--", - "Stop processing options so that the", - "remaining options will be passed to the", - "test."){o.terminate} - - o.on("-h", "--help", "Display this help."){puts o; exit} - - o.on_tail - o.on_tail("Deprecated options:") - - o.on_tail("--console", "Console runner (use --runner).") do - warn("Deprecated option (--console).") - @runner = self.class.runner(:console) - end - - if RUNNERS[:fox] - o.on_tail("--fox", "Fox runner (use --runner).") do - warn("Deprecated option (--fox).") - @runner = self.class.runner(:fox) - end - end - - o.on_tail - end - end - - def keyword_display(keywords) - keywords = keywords.collect do |keyword, _| - keyword.to_s - end.uniq.sort - - i = 0 - keywords.collect do |keyword| - if (i > 0 and keyword[0] == keywords[i - 1][0]) or - ((i < keywords.size - 1) and (keyword[0] == keywords[i + 1][0])) - n = 2 - else - n = 1 - end - i += 1 - keyword.sub(/^(.{#{n}})([A-Za-z]+)(?=\w*$)/, '\\1[\\2]') - end.join(", ") - end - - def run - self.class.need_auto_run = false - suite = @collector[self] - return false if suite.nil? - return true if suite.empty? - runner = @runner[self] - return false if runner.nil? - @runner_options[:color_scheme] ||= @color_scheme - @runner_options[:listeners] ||= [] - @runner_options[:listeners].concat(@listeners) - if @stop_on_failure - @runner_options[:listeners] << StopOnFailureListener.new - end - change_work_directory do - runner.run(suite, @runner_options).passed? - end - end - - def load_config(file) - require "yaml" - config = YAML.load(File.read(file)) - runner_name = config["runner"] - @runner = self.class.runner(runner_name) || @runner - @collector = self.class.collector(config["collector"]) || @collector - (config["color_schemes"] || {}).each do |name, options| - ColorScheme[name] = options - end - runner_options = {} - (config["#{runner_name}_options"] || {}).each do |key, value| - key = key.to_sym - value = ColorScheme[value] if key == :color_scheme - if key == :arguments - @default_arguments.concat(value.split) - else - runner_options[key.to_sym] = value - end - end - @runner_options = @runner_options.merge(runner_options) - end - - private - def default_runner - runner = self.class.default_runner - if ENV["EMACS"] == "t" - runner ||= self.class.runner(:emacs) - else - runner ||= self.class.runner(:console) - end - runner - end - - def default_collector - self.class.collector(@standalone ? :load : :descendant) - end - - def global_config_file - File.expand_path("~/.test-unit.yml") - rescue ArgumentError - nil - end - - def load_global_config - file = global_config_file - load_config(file) if file and File.exist?(file) - end - - def change_work_directory(&block) - if @workdir - Dir.chdir(@workdir, &block) - else - yield - end - end - - def match_test_case_name(test, pattern) - test.class.ancestors.each do |test_class| - break if test_class == TestCase - return true if pattern === test_class.name - end - false - end - - def add_test_path(path) - if /:(\d+)\z/ =~ path - line = $1.to_i - path = $PREMATCH - add_location_filter(path, line) - end - @to_run << path - end - - def add_location_filter(path, line) - @filters << lambda do |test| - test.class.test_defined?(:path => path, - :line => line, - :method_name => test.method_name) - end - end - - class StopOnFailureListener - def attach_to_mediator(mediator) - mediator.add_listener(TestResult::FINISHED) do |result| - result.stop unless result.passed? - end - end - end - end - end -end - -require "test/unit/runner/console" -require "test/unit/runner/emacs" -require "test/unit/runner/xml" diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/code-snippet-fetcher.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/code-snippet-fetcher.rb deleted file mode 100644 index 81f946d14..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/code-snippet-fetcher.rb +++ /dev/null @@ -1,56 +0,0 @@ -module Test - module Unit - class CodeSnippetFetcher - def initialize - @sources = {} - end - - def fetch(path, line, options={}) - n_context_line = options[:n_context_line] || 3 - lines = source(path) - return [] if lines.nil? - min_line = [line - n_context_line, 1].max - max_line = [line + n_context_line, lines.length].min - window = min_line..max_line - window.collect do |n| - attributes = {:target_line? => (n == line)} - [n, lines[n - 1].chomp, attributes] - end - end - - def source(path) - @sources[path] ||= read_source(path) - end - - private - def read_source(path) - return nil unless File.exist?(path) - lines = [] - File.open(path, "rb") do |file| - first_line = file.gets - break if first_line.nil? - encoding = detect_encoding(first_line) || Encoding::UTF_8 - first_line.force_encoding(encoding) - file.set_encoding(encoding) - lines << first_line - lines.concat(file.readlines) - end - lines - end - - def detect_encoding(first_line) - return nil unless first_line.respond_to?(:ascii_only?) - return nil unless first_line.ascii_only? - if /\b(?:en)?coding[:=]\s*([a-z\d_-]+)/i =~ first_line - begin - Encoding.find($1) - rescue ArgumentError - nil - end - else - nil - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector.rb deleted file mode 100644 index 022cedf79..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector.rb +++ /dev/null @@ -1,73 +0,0 @@ -module Test - module Unit - module Collector - def initialize - @filters = [] - end - - def filter=(filters) - @filters = case(filters) - when Proc - [filters] - when Array - filters - end - end - - def add_suite(destination, suite) - to_delete = suite.tests.find_all do |test| - test.is_a?(TestCase) and !include?(test) - end - suite.delete_tests(to_delete) - destination << suite unless suite.empty? - end - - def add_test_cases(suite, test_cases) - children_map = {} - test_cases.each do |test_case| - ancestor_classes = test_case.ancestors.find_all do |ancestor| - ancestor.is_a?(Class) - end - parent = ancestor_classes[1] - children_map[parent] ||= [] - children_map[parent] << test_case - end - - root_test_cases = children_map.keys - test_cases - root_test_cases.each do |root_test_case| - add_test_case(suite, root_test_case, children_map) - end - end - - def include?(test) - return true if(@filters.empty?) - @filters.each do |filter| - return false if filter[test] == false - end - true - end - - def sort(suites) - suites.sort_by do |suite| - [suite.priority, suite.name || suite.to_s] - end - end - - private - def add_test_case(suite, test_case, children_map) - children = children_map[test_case] - return if children.nil? - - sub_suites = [] - children.each do |child| - sub_suite = child.suite - add_test_case(sub_suite, child, children_map) - add_suite(sub_suites, sub_suite) - end - sort(sub_suites).each do |sub_suite| - suite << sub_suite - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/descendant.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/descendant.rb deleted file mode 100644 index b2de52863..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/descendant.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'test/unit/collector' - -module Test - module Unit - module Collector - class Descendant - include Collector - - NAME = 'collected from the subclasses of TestCase' - - def collect(name=NAME) - suite = TestSuite.new(name) - add_test_cases(suite, TestCase::DESCENDANTS) - suite - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/dir.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/dir.rb deleted file mode 100644 index f84273abb..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/dir.rb +++ /dev/null @@ -1,108 +0,0 @@ -require 'test/unit/testsuite' -require 'test/unit/collector' - -module Test - module Unit - module Collector - class Dir - include Collector - - attr_reader :pattern, :exclude - attr_accessor :base - - def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil) - super() - @dir = dir - @file = file - @object_space = object_space - @req = req - @pattern = [/\btest_.*\.rb\Z/m] - @exclude = [] - @base = nil - end - - def collect(*from) - basedir = @base - $:.push(basedir) if basedir - if(from.empty?) - recursive_collect('.', find_test_cases) - elsif(from.size == 1) - recursive_collect(from.first, find_test_cases) - else - suites = [] - from.each do |f| - suite = recursive_collect(f, find_test_cases) - suites << suite unless(suite.tests.empty?) - end - suite = TestSuite.new("[#{from.join(', ')}]") - sort(suites).each{|s| suite << s} - suite - end - ensure - $:.delete_at($:.rindex(basedir)) if basedir - end - - def find_test_cases(ignore=[]) - cases = [] - @object_space.each_object(Class) do |c| - cases << c if(c < TestCase && !ignore.include?(c)) - end - ignore.concat(cases) - cases - end - - def recursive_collect(name, already_gathered) - sub_suites = [] - path = realdir(name) - if @file.directory?(path) - dir_name = name unless name == '.' - @dir.entries(path).each do |e| - next if(e == '.' || e == '..') - e_name = dir_name ? @file.join(dir_name, e) : e - if @file.directory?(realdir(e_name)) - next if /\A(?:CVS|\.svn|\.git)\z/ =~ e - sub_suite = recursive_collect(e_name, already_gathered) - sub_suites << sub_suite unless(sub_suite.empty?) - else - next if /~\z/ =~ e_name or /\A\.\#/ =~ e - if @pattern and !@pattern.empty? - next unless @pattern.any? {|pat| pat =~ e_name} - end - if @exclude and !@exclude.empty? - next if @exclude.any? {|pat| pat =~ e_name} - end - collect_file(e_name, sub_suites, already_gathered) - end - end - else - collect_file(name, sub_suites, already_gathered) - end - suite = TestSuite.new(@file.basename(name)) - sort(sub_suites).each{|s| suite << s} - suite - end - - def collect_file(name, suites, already_gathered) - dir = @file.dirname(@file.expand_path(name, @base)) - $:.unshift(dir) - if(@req) - @req.require(name) - else - require(name) - end - find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)} - ensure - $:.delete_at($:.rindex(dir)) if(dir) - end - - def realdir(path) - if @base - @file.join(@base, path) - else - path - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/load.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/load.rb deleted file mode 100644 index 28a379b7e..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/load.rb +++ /dev/null @@ -1,197 +0,0 @@ -require 'pathname' - -require 'test/unit/testsuite' -require 'test/unit/collector' - -module Test - module Unit - module Collector - class Load - include Collector - - attr_reader :patterns, :excludes, :base - attr_reader :default_test_paths - - def initialize - super - @system_excludes = [/~\z/, /\A\.\#/] - @system_directory_excludes = [/\A(?:CVS|\.svn|\.git)\z/] - @patterns = [/\Atest[_\-].+\.rb\z/m, /[_\-]test\.rb\z/] - @excludes = [] - @base = nil - @default_test_paths = [] - @require_failed_infos = [] - end - - def base=(base) - base = Pathname(base) unless base.nil? - @base = base - end - - def default_test_paths=(paths) - @default_test_paths = paths.collect do |path| - Pathname(path) - end - end - - def collect(*froms) - add_load_path(@base) do - froms = @default_test_paths if froms.empty? - froms = ["."] if froms.empty? - test_suites = [] - already_gathered = find_test_cases - froms.each do |from| - from = resolve_path(from) - if from.directory? - test_suite = collect_recursive(from, already_gathered) - test_suites << test_suite unless test_suite.tests.empty? - else - collect_file(from, test_suites, already_gathered) - end - end - add_require_failed_test_suite(test_suites) - - if test_suites.size > 1 - test_suite = TestSuite.new("[#{froms.join(', ')}]") - sort(test_suites).each do |sub_test_suite| - test_suite << sub_test_suite - end - else - test_suite = test_suites.first - end - - test_suite - end - end - - def find_test_cases(ignore=[]) - test_cases = [] - TestCase::DESCENDANTS.each do |test_case| - test_cases << test_case unless ignore.include?(test_case) - end - ignore.concat(test_cases) - test_cases - end - - private - def collect_recursive(path, already_gathered) - sub_test_suites = [] - - if path.directory? - directories, files = path.children.partition do |child| - child.directory? - end - - files.each do |child| - next if excluded_file?(child.basename.to_s) - collect_file(child, sub_test_suites, already_gathered) - end - - directories.each do |child| - next if excluded_directory?(child.basename.to_s) - sub_test_suite = collect_recursive(child, already_gathered) - sub_test_suites << sub_test_suite unless sub_test_suite.empty? - end - else - unless excluded_file?(path.basename.to_s) - collect_file(path, sub_test_suites, already_gathered) - end - end - - test_suite = TestSuite.new(path.basename.to_s) - sort(sub_test_suites).each do |sub_test_suite| - test_suite << sub_test_suite - end - test_suite - end - - def collect_file(path, test_suites, already_gathered) - @program_file ||= File.expand_path($0) - expanded_path = path.expand_path - return if @program_file == expanded_path.to_s - add_load_path(expanded_path.dirname) do - begin - require(expanded_path.to_s) - rescue LoadError - @require_failed_infos << {:path => expanded_path, :exception => $!} - end - add_test_cases(test_suites, find_test_cases(already_gathered)) - end - end - - def resolve_path(path) - if @base - @base + path - else - Pathname(path) - end - end - - def add_load_path(path) - return yield if path.nil? - - path = path.to_s - begin - $LOAD_PATH.unshift(path) - yield - ensure - index = $LOAD_PATH.index(path) - $LOAD_PATH.delete_at(index) if index - end - end - - def excluded_directory?(base) - @system_directory_excludes.any? {|pattern| pattern =~ base} - end - - def excluded_file?(base) - return true if @system_excludes.any? {|pattern| pattern =~ base} - - patterns = @patterns || [] - unless patterns.empty? - return true unless patterns.any? {|pattern| pattern =~ base} - end - - excludes = @excludes || [] - unless excludes.empty? - return true if excludes.any? {|pattern| pattern =~ base} - end - - false - end - - def add_require_failed_test_suite(test_suites) - return if @require_failed_infos.empty? - - require_failed_infos = @require_failed_infos - require_failed_errors = Class.new(Test::Unit::TestCase) - require_failed_errors.class_eval do - class << self - def name - "RequireFailedErrors" - end - end - - require_failed_infos.each do |info| - path = info[:path] - normalized_path = path.to_s.gsub(/[^a-z0-9\_]+/i, '_') - normalized_path = normalized_path.gsub(/\A_+/, '') - exception = info[:exception] - define_method("test_require_#{normalized_path}") do - raise(exception.class, - "failed to load <#{path}>: #{exception.message}", - exception.backtrace) - end - end - - def priority - 100 - end - end - - add_suite(test_suites, require_failed_errors.suite) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/objectspace.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/objectspace.rb deleted file mode 100644 index eab313779..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/objectspace.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/collector' - -module Test - module Unit - module Collector - class ObjectSpace - include Collector - - NAME = 'collected from the ObjectSpace' - - def initialize(source=::ObjectSpace) - super() - @source = source - end - - def collect(name=NAME) - suite = TestSuite.new(name) - sub_suites = [] - @source.each_object(Class) do |klass| - if(Test::Unit::TestCase > klass) - add_suite(sub_suites, klass.suite) - end - end - sort(sub_suites).each{|s| suite << s} - suite - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/xml.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/xml.rb deleted file mode 100644 index cde452805..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/collector/xml.rb +++ /dev/null @@ -1,249 +0,0 @@ -#-- -# -# Author:: Kouhei Sutou -# Copyright:: -# * Copyright (c) 2011 Kouhei Sutou -# License:: Ruby license. - -# just test!!! don't use it yet!!! - -require 'test/unit/collector' - -require 'rexml/document' -require 'rexml/streamlistener' - -module Test - module Unit - module Collector - class XML - include Collector - - def collect(xml_log_path) - listener = Listener.new - File.open(xml_log_path) do |xml_log| - parser = REXML::Parsers::StreamParser.new(xml_log, listener) - parser.parse - end - suite = TestSuite.new("tests in #{xml_log_path}") - suites = listener.test_suites - sort(suites).each {|s| add_suite(suite, s)} - suite - end - - class Listener - include REXML::StreamListener - - attr_reader :test_suites - def initialize - @ns_stack = [{"xml" => :xml}] - @tag_stack = [["", :root]] - @text_stack = [''] - @state_stack = [:root] - @values = {} - @test_suites = [] - end - - def tag_start(name, attributes) - @text_stack.push('') - - ns = @ns_stack.last.dup - attrs = {} - attributes.each do |n, v| - if /\Axmlns(?:\z|:)/ =~ n - ns[$POSTMATCH] = v - else - attrs[n] = v - end - end - @ns_stack.push(ns) - - _parent_tag = parent_tag - prefix, local = split_name(name) - uri = _ns(ns, prefix) - @tag_stack.push([uri, local]) - - state = next_state(@state_stack.last, uri, local) - @state_stack.push(state) - @values = {} - case state - when :test_suite, :test_case - # do nothing - when :test - @n_pass_assertions = 0 if _parent_tag == "start-test" - when :backtrace - @backtrace = [] - @values_backup = @values - end - end - - def tag_end(name) - state = @state_stack.pop - text = @text_stack.pop - uri, local = @tag_stack.pop - no_action_states = [:root, :stream] - case state - when *no_action_states - # do nothing - when :test_suite - test_suite_end - when :complete_test_case - @test_suites.last << @test_case.suite - when :test_case - test_case_end - when :result - @result = @values - when :test - test_end - when :pass_assertion - @n_pass_assertions += 1 - when :backtrace - @values = @values_backup - @values["backtrace"] = @backtrace - when :entry - file = @values['file'] - line = @values['line'] - info = @values['info'] - @backtrace << "#{file}:#{line}: #{info}" - @values = {} - else - local = normalize_local(local) - @values[local] = text - end - @ns_stack.pop - end - - def text(data) - @text_stack.last << data - end - - private - def _ns(ns, prefix) - ns.fetch(prefix, "") - end - - NAME_SPLIT = /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/ - def split_name(name) - name =~ NAME_SPLIT - [$1 || '', $2] - end - - STATE_TABLE = { - :root => [:stream], - :stream => [:ready_test_suite, - :start_test_suite, - :ready_test_case, - :start_test_case, - :start_test, - :pass_assertion, - :test_result, - :complete_test, - :complete_test_case, - :complete_test_suite, - :success], - :ready_test_suite => [:n_tests], - :start_test_suite => [:test_suite], - :ready_test_case => [:test_case, - :n_tests], - :start_test_case => [:test_case], - :start_test => [:test], - :pass_assertion => [:test], - :complete_test => [:test, :success], - :complete_test_case => [:test_case, - :elapsed, - :success], - :complete_test_suite => [:test_suite, - :success], - :test_suite => [:start_time, - :elapsed], - :test_case => [:name, - :start_time, - :elapsed], - :test => [:name, - :start_time, - :elapsed], - :test_result => [:test, - :result], - :result => [:test_case, - :test, - :status, - :backtrace, - :detail], - :backtrace => [:entry], - :entry => [:file, - :line, - :info], - } - def next_state(current_state, uri, local) - local = normalize_local(local) - valid_elements = STATE_TABLE[current_state] - if valid_elements.nil? - raise "unexpected element: #{current_path}" - end - next_state = local.to_sym - unless valid_elements.include?(next_state) - raise "unexpected element: #{current_path}" - end - next_state - end - - def current_path - locals = @tag_stack.collect do |uri, local| - local - end - ["", *locals].join("/") - end - - def normalize_local(local) - local.gsub(/-/, "_") - end - - def parent_tag - @tag_stack.last[1] - end - - def test_suite_end - return unless parent_tag == "start-test-suite" - suite = TestSuite.new - ["start_time", "elapsed_time", "n_tests"].each do |key| - if @values.has_key?(key) - suite.instance_variable_set("@#{key}", @values[key]) - end - end - @test_suites << suite - end - - def test_case_end - return unless parent_tag == "start-test-case" - name = @values["name"] - @test_case = Class.new(TestCase) do - define_method(:name) do - name - end - end - end - - def test_end - return unless parent_tag == "complete-test" - name = @values["name"] - n_pass_assertions = @n_pass_assertions - result = @result - @test_case.module_eval do - test - define_method(name) do - n_pass_assertions.times do - add_assertion - end - case result["status"] - when "omission" - add_omission(Omission.new(name, - result["backtrace"], - result["detail"])) - end - end - end - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/color-scheme.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/color-scheme.rb deleted file mode 100644 index a898f9d68..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/color-scheme.rb +++ /dev/null @@ -1,198 +0,0 @@ -require 'test/unit/color' - -module Test - module Unit - class ColorScheme - include Enumerable - - class << self - def default - if available_colors == 256 - default_for_256_colors - else - default_for_8_colors - end - end - - @@default_for_8_colors = nil - def default_for_8_colors - @@default_for_8_colors ||= - new("pass" => Color.new("green", :background => true) + - Color.new("white", :bold => true), - "pass-marker" => Color.new("green", :bold => true), - "failure" => Color.new("red", :background => true) + - Color.new("white", :bold => true), - "failure-marker" => Color.new("red"), - "pending" => Color.new("magenta", :background => true) + - Color.new("white", :bold => true), - "pending-marker" => Color.new("magenta"), - "omission" => Color.new("blue", :background => true) + - Color.new("white", :bold => true), - "omission-marker" => Color.new("blue"), - "notification" => Color.new("cyan", :background => true) + - Color.new("white", :bold => true), - "notification-marker" => Color.new("cyan"), - "error" => Color.new("black", :background => true) + - Color.new("yellow", :bold => true), - "error-marker" => Color.new("yellow"), - "case" => Color.new("blue", :background => true) + - Color.new("white", :bold => true), - "suite" => Color.new("green", :background => true) + - Color.new("white", :bold => true), - "diff-inserted-tag" => Color.new("red", :background => true) + - Color.new("black", :bold => true), - "diff-deleted-tag" => Color.new("green", :background => true) + - Color.new("black", :bold => true), - "diff-difference-tag" => Color.new("cyan", :background => true) + - Color.new("white", :bold => true), - "diff-inserted" => Color.new("red", :background => true) + - Color.new("white", :bold => true), - "diff-deleted" => Color.new("green", :background => true) + - Color.new("white", :bold => true)) - end - - @@default_for_256_colors = nil - def default_for_256_colors - @@default_for_256_colors ||= - new("pass" => Color.new("030", :background => true) + - Color.new("555", :bold => true), - "pass-marker" => Color.new("050", :bold => true), - "failure" => Color.new("300", :background => true) + - Color.new("555", :bold => true), - "failure-marker" => Color.new("500"), - "pending" => Color.new("303", :background => true) + - Color.new("555", :bold => true), - "pending-marker" => Color.new("303"), - "omission" => Color.new("001", :background => true) + - Color.new("555", :bold => true), - "omission-marker" => Color.new("001"), - "notification" => Color.new("011", :background => true) + - Color.new("555", :bold => true), - "notification-marker" => Color.new("011"), - "error" => Color.new("000", :background => true) + - Color.new("550", :bold => true), - "error-marker" => Color.new("550"), - "case" => Color.new("220", :background => true) + - Color.new("555", :bold => true), - "suite" => Color.new("110", :background => true) + - Color.new("555", :bold => true), - "diff-inserted-tag" => Color.new("500", :background => true) + - Color.new("000", :bold => true), - "diff-deleted-tag" => Color.new("050", :background => true) + - Color.new("000", :bold => true), - "diff-difference-tag" => Color.new("005", :background => true) + - Color.new("555", :bold => true), - "diff-inserted" => Color.new("300", :background => true) + - Color.new("555", :bold => true), - "diff-deleted" => Color.new("030", :background => true) + - Color.new("555", :bold => true)) - end - - @@schemes = {} - def all - @@schemes.merge("default" => default) - end - - def [](id) - @@schemes[id.to_s] - end - - def []=(id, scheme_or_spec) - if scheme_or_spec.is_a?(self) - scheme = scheme_or_spec - else - scheme = new(scheme_or_spec) - end - @@schemes[id.to_s] = scheme - end - - def available_colors - guess_available_colors_from_vte_version_env || - guess_available_colors_from_colorterm_env || - guess_available_colors_from_term_env || - 8 - end - - private - def guess_available_colors_from_vte_version_env - vte_version = ENV["VTE_VERSION"] - return nil if vte_version.nil? - - major = 0 - minor = 13 - micro = 0 - packed_version = major * 10000 + minor * 100 + micro - if vte_version.to_i >= packed_version - 256 - else - 8 - end - end - - def guess_available_colors_from_colorterm_env - case ENV["COLORTERM"] - when "gnome-terminal", "xfce4-terminal" - 256 - else - nil - end - end - - def guess_available_colors_from_term_env - case ENV["TERM"] - when /-256color\z/ - 256 - else - nil - end - end - end - - def initialize(scheme_spec) - @scheme = {} - scheme_spec.each do |key, color_spec| - self[key] = color_spec - end - end - - def [](name) - @scheme[name.to_s] - end - - def []=(name, color_spec) - @scheme[name.to_s] = make_color(color_spec) - end - - def each(&block) - @scheme.each(&block) - end - - def to_hash - hash = {} - @scheme.each do |key, color| - hash[key] = color - end - hash - end - - private - def make_color(color_spec) - if color_spec.is_a?(Color) or color_spec.is_a?(MixColor) - color_spec - else - color_name = nil - normalized_color_spec = {} - color_spec.each do |key, value| - key = key.to_sym - if key == :name - color_name = value - else - normalized_color_spec[key] = value - end - end - Color.new(color_name, normalized_color_spec) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/color.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/color.rb deleted file mode 100644 index 86972fc45..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/color.rb +++ /dev/null @@ -1,134 +0,0 @@ -module Test - module Unit - class Color - class Error < StandardError - end - - class ParseError < Error - end - - class << self - def parse_256_color(string) - case string - when /\A([0-5])([0-5])([0-5])\z/ - red, green, blue = $1, $2, $3 - red.to_i * 36 + green.to_i * 6 + blue.to_i + 16 - else - message = "must be 'RGB' format and R, G and B " + - "are in 0-5: #{string.inspect}" - raise ParseError, message - end - end - end - - NAMES = ["black", "red", "green", "yellow", - "blue", "magenta", "cyan", "white"] - - attr_reader :name - def initialize(name, options={}) - @name = name - if options.has_key?(:foreground) - if options[:foreground].nil? - @background = false - else - @background = !options[:foreground] - end - else - @background = options[:background] - end - @intensity = options[:intensity] - @bold = options[:bold] - @italic = options[:italic] - @underline = options[:underline] - end - - def foreground? - not background? - end - - def background? - @background - end - - def intensity? - @intensity - end - - def bold? - @bold - end - - def italic? - @italic - end - - def underline? - @underline - end - - def ==(other) - self.class === other and - [name, background?, intensity?, - bold?, italic?, underline?] == - [other.name, other.background?, other.intensity?, - other.bold?, other.italic?, other.underline?] - end - - def sequence - sequence = [] - if @name == "none" - elsif @name == "reset" - sequence << "0" - else - if NAMES.include?(@name) - color_parameter = foreground? ? 3 : 4 - color_parameter += 6 if intensity? - color = NAMES.index(@name) - sequence << "#{color_parameter}#{color}" - else - sequence << (foreground? ? "38" : "48") - sequence << "5" - sequence << self.class.parse_256_color(@name).to_s - end - end - sequence << "1" if bold? - sequence << "3" if italic? - sequence << "4" if underline? - sequence - end - - def escape_sequence - "\e[#{sequence.join(';')}m" - end - - def +(other) - MixColor.new([self, other]) - end - end - - class MixColor - attr_reader :colors - def initialize(colors) - @colors = colors - end - - def sequence - @colors.inject([]) do |result, color| - result + color.sequence - end - end - - def escape_sequence - "\e[#{sequence.join(';')}m" - end - - def +(other) - self.class.new([self, other]) - end - - def ==(other) - self.class === other and colors == other.colors - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/data-sets.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/data-sets.rb deleted file mode 100644 index d617aea48..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/data-sets.rb +++ /dev/null @@ -1,116 +0,0 @@ -module Test - module Unit - class DataSets - def initialize - @variables = [] - @procs = [] - @value_sets = [] - end - - def add(data_set, options=nil) - options ||= {} - if data_set.respond_to?(:call) - @procs << [data_set, options] - elsif data_set.is_a?(Array) - @variables << [data_set, options] - else - @value_sets << [data_set, options] - end - end - - def <<(data_set) - add(data_set) - end - - def keep - new_data_sets = self.class.new - all_data_sets = Enumerator.new do |yielder| - block = lambda do |(data_set, options)| - yielder << [data_set, options] - end - @procs.each(&block) - @variables.each(&block) - @value_sets.each(&block) - end - all_data_sets.each do |data_set, options| - next if options.nil? - next unless options[:keep] - new_data_sets.add(data_set, options) - end - new_data_sets - end - - def each - variables = @variables - value_sets = @value_sets - @procs.each do |proc, options| - data_set = proc.call - case data_set - when Array - variables += [[data_set, options]] - else - value_sets += [[data_set, options]] - end - end - - value_sets.each do |values, _options| - values.each do |label, data| - yield(label, data) - end - end - - each_pattern(variables) do |label, data| - yield(label, data) - end - end - - def ==(other) - @variables == other.instance_variable_get(:@variables) and - @procs == other.instance_variable_get(:@procs) and - @value_sets == other.instance_variable_get(:@value_sets) - end - - def eql?(other) - self == other - end - - def hash - [@variables, @procs, @value_sets].hash - end - - private - def each_pattern(variables) - grouped_variables = variables.group_by do |_, options| - options[:group] - end - grouped_variables.each do |group, group_variables| - each_raw_pattern(group_variables) do |cell| - label = String.new - label << "group: #{group.inspect}" unless group.nil? - data = {} - cell.each do |variable, pattern| - label << ", " unless label.empty? - label << "#{variable}: #{pattern.inspect}" - data[variable] = pattern - end - yield(label, data) - end - end - end - - def each_raw_pattern(variables, &block) - return if variables.empty? - - sorted_variables = variables.sort_by do |(variable, _), _| - variable - end - all_patterns = sorted_variables.collect do |(variable, patterns), _| - patterns.collect do |pattern| - [variable, pattern] - end - end - all_patterns[0].product(*all_patterns[1..-1], &block) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/data.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/data.rb deleted file mode 100644 index bc9c9ffbe..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/data.rb +++ /dev/null @@ -1,371 +0,0 @@ -require "test/unit/data-sets" - -module Test - module Unit - module Data - class << self - def included(base) - base.extend(ClassMethods) - end - end - - module ClassMethods - # This method provides Data-Driven-Test functionality. - # - # Define test data in the test code. - # - # @overload data(label, data, options={}) - # @param [String] label specify test case name. - # @param data specify test data. - # @param [Hash] options specify options. - # @option options [Boolean] :keep whether or not to use - # this data in the following test methods - # - # @example data(label, data) - # data("empty string", [true, ""]) - # data("plain string", [false, "hello"]) - # def test_empty?(data) - # expected, target = data - # assert_equal(expected, target.empty?) - # end - # - # @overload data(variable, patterns, options={}) - # @param [Symbol] variable specify test pattern variable name. - # @param [Array] patterns specify test patterns for the variable. - # @param [Hash] options specify options. - # @option options [Boolean] :keep whether or not to use - # this data in the following test methods - # @option options [Object] :group the test pattern group. - # Test matrix is generated for each test pattern group separately. - # - # @example data(variable, patterns) - # data(:x, [1, 2, 3]) - # data(:y, ["a", "b"]) - # def test_patterns(data) - # # 3 * 2 times executed - # # 3: the number of patterns of :x - # # 2: the number of patterns of :y - # p data - # # => {:x => 1, :y => "a"} - # # => {:x => 1, :y => "b"} - # # => {:x => 2, :y => "a"} - # # => {:x => 2, :y => "b"} - # # => {:x => 3, :y => "a"} - # # => {:x => 3, :y => "b"} - # end - # - # Generates test matrix from variable and patterns pairs. - # - # @overload data(data_set, options={}) - # @param [Hash] data_set specify test data as a Hash that - # key is test label and value is test data. - # @param [Hash] options specify options. - # @option options [Boolean] :keep whether or not to use - # this data in the following test methods - # - # @example data(data_set) - # data("empty string" => [true, ""], - # "plain string" => [false, "hello"]) - # def test_empty?(data) - # expected, target = data - # assert_equal(expected, target.empty?) - # end - # - # @overload data(options={}, &block) - # @param [Hash] options specify options. - # @option options [Boolean] :keep whether or not to use - # this data in the following test methods - # @yieldreturn [Hash] return test data set - # as a Hash that key is test label and value is test data. - # - # @example data(&block) - # data do - # data_set = {} - # data_set["empty string"] = [true, ""] - # data_set["plain string"] = [false, "hello"] - # data_set - # end - # def test_empty?(data) - # expected, target = data - # assert_equal(expected, target.empty?) - # end - # - # @overload data(options={}, &block) - # @param [Hash] options specify options. - # @option options [Boolean] :keep whether or not to use - # this data in the following test methods - # @yieldreturn [Array] return test data set - # as an Array of variable and patterns. - # - # @example data(&block) - # data do - # patterns = 3.times.to_a - # [:x, patterns] - # end - # data do - # patterns = [] - # character = "a" - # 2.times.each do - # patterns << character - # character = character.succ - # end - # [:y, patterns] - # end - # def test_patterns(data) - # # 3 * 2 times executed - # # 3: the number of patterns of :x - # # 2: the number of patterns of :y - # p data - # # => {:x => 0, :y => "a"} - # # => {:x => 0, :y => "b"} - # # => {:x => 1, :y => "a"} - # # => {:x => 1, :y => "b"} - # # => {:x => 2, :y => "a"} - # # => {:x => 2, :y => "b"} - # end - # - # Generates test matrix from variable and patterns pairs. - # - def data(*arguments, &block) - options = nil - n_arguments = arguments.size - case n_arguments - when 0 - raise ArgumentError, "no block is given" unless block_given? - data_set = block - when 1 - if block_given? - data_set = block - options = arguments[1] - else - data_set = arguments[0] - end - when 2 - case arguments[0] - when String - data_set = {arguments[0] => arguments[1]} - when Hash - data_set = arguments[0] - options = arguments[1] - else - variable = arguments[0] - patterns = arguments[1] - data_set = [variable, patterns] - end - when 3 - case arguments[0] - when String - data_set = {arguments[0] => arguments[1]} - options = arguments[2] - else - variable = arguments[0] - patterns = arguments[1] - data_set = [variable, patterns] - options = arguments[2] - end - else - message = "wrong number arguments(#{n_arguments} for 0..3)" - raise ArgumentError, message - end - options ||= {} - data_sets = current_attribute(:data)[:value] || DataSets.new - data_sets.add(data_set, options) - if options[:keep] - keep_hook = lambda do |attr| - attr.merge(value: attr[:value].keep) - end - options = options.merge(keep_hook: keep_hook) - end - attribute(:data, data_sets, options) - end - - # This method provides Data-Driven-Test functionality. - # - # Load test data from the file. This is shorthand to load - # test data from file. If you want to load complex file, you - # can use {#data} with block. - # - # @param [String] file_name full path to test data file. - # File format is automatically detected from filename extension. - # @raise [ArgumentError] if `file_name` is not supported file format. - # @see Loader#load - # - # @example Load data from CSV file - # load_data("/path/to/test-data.csv") - # def test_empty?(data) - # assert_equal(data["expected"], data["target"].empty?) - # end - # - def load_data(file_name) - loader = Loader.new(self) - loader.load(file_name) - end - - class Loader - # @api private - def initialize(test_case) - @test_case = test_case - end - - # Load data from file. - # - # @param [String] file_name full path to test data file. - # File format is automatically detected from filename extension. - # @raise [ArgumentError] if `file_name` is not supported file format. - # @see #load_csv - # @see #load_tsv - # @api private - def load(file_name) - case File.extname(file_name).downcase - when ".csv" - load_csv(file_name) - when ".tsv" - load_tsv(file_name) - else - raise ArgumentError, "unsupported file format: <#{file_name}>" - end - end - - # Load data from CSV file. - # - # There are 2 types of CSV file as following examples. - # First, there is a header on first row and it's first column is "label". - # Another, there is no header in the file. - # - # @example Load data from CSV file with header - # # test-data.csv: - # # label,expected,target - # # empty string,true,"" - # # plain string,false,hello - # # - # load_data("/path/to/test-data.csv") - # def test_empty?(data) - # assert_equal(data["expected"], data["target"].empty?) - # end - # - # @example Load data from CSV file without header - # # test-data-without-header.csv: - # # empty string,true,"" - # # plain string,false,hello - # # - # load_data("/path/to/test-data-without-header.csv") - # def test_empty?(data) - # expected, target = data - # assert_equal(expected, target.empty?) - # end - # - # @api private - def load_csv(file_name) - require 'csv' - first_row = true - header = nil - CSV.foreach(file_name) do |row| - if first_row - first_row = false - if row.first == "label" - header = row[1..-1] - next - end - end - - set_test_data(header, row) - end - end - - # Load data from TSV file. - # - # There are 2 types of TSV file as following examples. - # First, there is a header on first row and it's first column is "label". - # Another, there is no header in the file. - # - # @example Load data from TSV file with header - # # test-data.tsv: - # # label expected target - # # empty string true "" - # # plain string false hello - # # - # load_data("/path/to/test-data.tsv") - # def test_empty?(data) - # assert_equal(data["expected"], data["target"].empty?) - # end - # - # @example Load data from TSV file without header - # # test-data-without-header.tsv: - # # empty string true "" - # # plain string false hello - # # - # load_data("/path/to/test-data-without-header.tsv") - # def test_empty?(data) - # expected, target = data - # assert_equal(expected, target.empty?) - # end - # - # @api private - def load_tsv(file_name) - require "csv" - if CSV.const_defined?(:VERSION) - first_row = true - header = nil - CSV.foreach(file_name, :col_sep => "\t") do |row| - if first_row - first_row = false - if row.first == "label" - header = row[1..-1] - next - end - end - - set_test_data(header, row) - end - else - # for old CSV library - first_row = true - header = nil - CSV.open(file_name, "r", "\t") do |row| - if first_row - first_row = false - if row.first == "label" - header = row[1..-1] - next - end - end - - set_test_data(header, row) - end - end - end - - private - def normalize_value(value) - return true if value == "true" - return false if value == "false" - begin - Integer(value) - rescue ArgumentError - begin - Float(value) - rescue ArgumentError - value - end - end - end - - def set_test_data(header, row) - label = row.shift - if header - data = {} - header.each_with_index do |key, i| - data[key] = normalize_value(row[i]) - end - else - data = row.collect do |cell| - normalize_value(cell) - end - end - @test_case.data(label, data) - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/diff.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/diff.rb deleted file mode 100644 index ce2348e32..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/diff.rb +++ /dev/null @@ -1,746 +0,0 @@ -# port of Python's difflib. -# -# Copyright (c) 2001-2008 Python Software Foundation; All Rights Reserved -# Copyright (c) 2008-2011 Kouhei Sutou; All Rights Reserved -# -# It is free software, and is distributed under the Ruby license, the -# PSF license and/or LGPLv2.1 or later. See the COPYING file, the PSFL -# file and the LGPL file. - -module Test - module Unit - module Diff - class SequenceMatcher - def initialize(from, to, &junk_predicate) - @from = from - @to = to - @junk_predicate = junk_predicate - update_to_indexes - end - - def longest_match(from_start, from_end, to_start, to_end) - best_info = find_best_match_position(from_start, from_end, - to_start, to_end) - unless @junks.empty? - args = [from_start, from_end, to_start, to_end] - best_info = adjust_best_info_with_junk_predicate(false, best_info, - *args) - best_info = adjust_best_info_with_junk_predicate(true, best_info, - *args) - end - - best_info - end - - def blocks - @blocks ||= compute_blocks - end - - def operations - @operations ||= compute_operations - end - - def grouped_operations(context_size=nil) - context_size ||= 3 - _operations = operations.dup - _operations = [[:equal, 0, 0, 0, 0]] if _operations.empty? - expand_edge_equal_operations!(_operations, context_size) - - group_window = context_size * 2 - groups = [] - group = [] - _operations.each do |tag, from_start, from_end, to_start, to_end| - if tag == :equal and from_end - from_start > group_window - group << [tag, - from_start, - [from_end, from_start + context_size].min, - to_start, - [to_end, to_start + context_size].min] - groups << group - group = [] - from_start = [from_start, from_end - context_size].max - to_start = [to_start, to_end - context_size].max - end - group << [tag, from_start, from_end, to_start, to_end] - end - groups << group unless group.empty? - groups - end - - def ratio - @ratio ||= compute_ratio - end - - private - def update_to_indexes - @to_indexes = {} - @junks = {} - if @to.is_a?(String) - each = " "[0].is_a?(Integer) ? :each_byte : :each_char - else - each = :each - end - i = 0 - @to.__send__(each) do |item| - @to_indexes[item] ||= [] - @to_indexes[item] << i - i += 1 - end - - return if @junk_predicate.nil? - @to_indexes = @to_indexes.reject do |key, value| - junk = @junk_predicate.call(key) - @junks[key] = true if junk - junk - end - end - - def find_best_match_position(from_start, from_end, to_start, to_end) - best_from, best_to, best_size = from_start, to_start, 0 - sizes = {} - from_start.upto(from_end) do |from_index| - _sizes = {} - (@to_indexes[@from[from_index]] || []).each do |to_index| - next if to_index < to_start - break if to_index > to_end - size = _sizes[to_index] = (sizes[to_index - 1] || 0) + 1 - if size > best_size - best_from = from_index - size + 1 - best_to = to_index - size + 1 - best_size = size - end - end - sizes = _sizes - end - [best_from, best_to, best_size] - end - - def adjust_best_info_with_junk_predicate(should_junk, best_info, - from_start, from_end, - to_start, to_end) - best_from, best_to, best_size = best_info - while best_from > from_start and best_to > to_start and - (should_junk ? - @junks.has_key?(@to[best_to - 1]) : - !@junks.has_key?(@to[best_to - 1])) and - @from[best_from - 1] == @to[best_to - 1] - best_from -= 1 - best_to -= 1 - best_size += 1 - end - - while best_from + best_size < from_end and - best_to + best_size < to_end and - (should_junk ? - @junks.has_key?(@to[best_to + best_size]) : - !@junks.has_key?(@to[best_to + best_size])) and - @from[best_from + best_size] == @to[best_to + best_size] - best_size += 1 - end - - [best_from, best_to, best_size] - end - - def matches - @matches ||= compute_matches - end - - def compute_matches - matches = [] - queue = [[0, @from.size, 0, @to.size]] - until queue.empty? - from_start, from_end, to_start, to_end = queue.pop - match = longest_match(from_start, from_end - 1, to_start, to_end - 1) - match_from_index, match_to_index, size = match - unless size.zero? - if from_start < match_from_index and - to_start < match_to_index - queue.push([from_start, match_from_index, - to_start, match_to_index]) - end - matches << match - if match_from_index + size < from_end and - match_to_index + size < to_end - queue.push([match_from_index + size, from_end, - match_to_index + size, to_end]) - end - end - end - matches.sort_by do |(from_index, _, _)| - from_index - end - end - - def compute_blocks - blocks = [] - current_from_index = current_to_index = current_size = 0 - matches.each do |from_index, to_index, size| - if current_from_index + current_size == from_index and - current_to_index + current_size == to_index - current_size += size - else - unless current_size.zero? - blocks << [current_from_index, current_to_index, current_size] - end - current_from_index = from_index - current_to_index = to_index - current_size = size - end - end - unless current_size.zero? - blocks << [current_from_index, current_to_index, current_size] - end - - blocks << [@from.size, @to.size, 0] - blocks - end - - def compute_operations - from_index = to_index = 0 - operations = [] - blocks.each do |match_from_index, match_to_index, size| - tag = determine_tag(from_index, to_index, - match_from_index, match_to_index) - if tag != :equal - operations << [tag, - from_index, match_from_index, - to_index, match_to_index] - end - - from_index, to_index = match_from_index + size, match_to_index + size - if size > 0 - operations << [:equal, - match_from_index, from_index, - match_to_index, to_index] - end - end - operations - end - - def compute_ratio - matches = blocks.inject(0) {|result, block| result + block[-1]} - length = @from.length + @to.length - if length.zero? - 1.0 - else - 2.0 * matches / length - end - end - - def determine_tag(from_index, to_index, - match_from_index, match_to_index) - if from_index < match_from_index and to_index < match_to_index - :replace - elsif from_index < match_from_index - :delete - elsif to_index < match_to_index - :insert - else - :equal - end - end - - def expand_edge_equal_operations!(_operations, context_size) - tag, from_start, from_end, to_start, to_end = _operations[0] - if tag == :equal - _operations[0] = [tag, - [from_start, from_end - context_size].max, - from_end, - [to_start, to_end - context_size].max, - to_end] - end - - tag, from_start, from_end, to_start, to_end = _operations[-1] - if tag == :equal - _operations[-1] = [tag, - from_start, - [from_end, from_start + context_size].min, - to_start, - [to_end, to_start + context_size].min] - end - end - end - - class Differ - def initialize(from, to) - @from = from - @to = to - end - - private - def tag(mark, contents) - contents.collect {|content| mark + content} - end - end - - class UTF8Line - class << self - # from http://unicode.org/reports/tr11/ - WIDE_CHARACTERS = - [0x1100..0x1159, 0x115F..0x115F, 0x2329..0x232A, - 0x2E80..0x2E99, 0x2E9B..0x2EF3, 0x2F00..0x2FD5, - 0x2FF0..0x2FFB, 0x3000..0x303E, 0x3041..0x3096, - 0x3099..0x30FF, 0x3105..0x312D, 0x3131..0x318E, - 0x3190..0x31B7, 0x31C0..0x31E3, 0x31F0..0x321E, - 0x3220..0x3243, 0x3250..0x32FE, 0x3300..0x4DB5, - 0x4E00..0x9FC3, 0xA000..0xA48C, 0xA490..0xA4C6, - 0xAC00..0xD7A3, 0xF900..0xFA2D, 0xFA30..0xFA6A, - 0xFA70..0xFAD9, 0xFE10..0xFE19, 0xFE30..0xFE52, - 0xFE54..0xFE66, 0xFE68..0xFE6B, 0xFF01..0xFF60, - 0xFFE0..0xFFE6, 0x20000..0x2FFFD, 0x30000..0x3FFFD, - ] - - AMBIGUOUS = - [0x00A1..0x00A1, 0x00A4..0x00A4, 0x00A7..0x00A8, - 0x00AA..0x00AA, 0x00AD..0x00AE, 0x00B0..0x00B4, - 0x00B6..0x00BA, 0x00BC..0x00BF, 0x00C6..0x00C6, - 0x00D0..0x00D0, 0x00D7..0x00D8, 0x00DE..0x00E1, - 0x00E6..0x00E6, 0x00E8..0x00EA, 0x00EC..0x00ED, - 0x00F0..0x00F0, 0x00F2..0x00F3, 0x00F7..0x00FA, - 0x00FC..0x00FC, 0x00FE..0x00FE, 0x0101..0x0101, - 0x0111..0x0111, 0x0113..0x0113, 0x011B..0x011B, - 0x0126..0x0127, 0x012B..0x012B, 0x0131..0x0133, - 0x0138..0x0138, 0x013F..0x0142, 0x0144..0x0144, - 0x0148..0x014B, 0x014D..0x014D, 0x0152..0x0153, - 0x0166..0x0167, 0x016B..0x016B, 0x01CE..0x01CE, - 0x01D0..0x01D0, 0x01D2..0x01D2, 0x01D4..0x01D4, - 0x01D6..0x01D6, 0x01D8..0x01D8, 0x01DA..0x01DA, - 0x01DC..0x01DC, 0x0251..0x0251, 0x0261..0x0261, - 0x02C4..0x02C4, 0x02C7..0x02C7, 0x02C9..0x02CB, - 0x02CD..0x02CD, 0x02D0..0x02D0, 0x02D8..0x02DB, - 0x02DD..0x02DD, 0x02DF..0x02DF, 0x0300..0x036F, - 0x0391..0x03A1, 0x03A3..0x03A9, 0x03B1..0x03C1, - 0x03C3..0x03C9, 0x0401..0x0401, 0x0410..0x044F, - 0x0451..0x0451, 0x2010..0x2010, 0x2013..0x2016, - 0x2018..0x2019, 0x201C..0x201D, 0x2020..0x2022, - 0x2024..0x2027, 0x2030..0x2030, 0x2032..0x2033, - 0x2035..0x2035, 0x203B..0x203B, 0x203E..0x203E, - 0x2074..0x2074, 0x207F..0x207F, 0x2081..0x2084, - 0x20AC..0x20AC, 0x2103..0x2103, 0x2105..0x2105, - 0x2109..0x2109, 0x2113..0x2113, 0x2116..0x2116, - 0x2121..0x2122, 0x2126..0x2126, 0x212B..0x212B, - 0x2153..0x2154, 0x215B..0x215E, 0x2160..0x216B, - 0x2170..0x2179, 0x2190..0x2199, 0x21B8..0x21B9, - 0x21D2..0x21D2, 0x21D4..0x21D4, 0x21E7..0x21E7, - 0x2200..0x2200, 0x2202..0x2203, 0x2207..0x2208, - 0x220B..0x220B, 0x220F..0x220F, 0x2211..0x2211, - 0x2215..0x2215, 0x221A..0x221A, 0x221D..0x2220, - 0x2223..0x2223, 0x2225..0x2225, 0x2227..0x222C, - 0x222E..0x222E, 0x2234..0x2237, 0x223C..0x223D, - 0x2248..0x2248, 0x224C..0x224C, 0x2252..0x2252, - 0x2260..0x2261, 0x2264..0x2267, 0x226A..0x226B, - 0x226E..0x226F, 0x2282..0x2283, 0x2286..0x2287, - 0x2295..0x2295, 0x2299..0x2299, 0x22A5..0x22A5, - 0x22BF..0x22BF, 0x2312..0x2312, 0x2460..0x24E9, - 0x24EB..0x254B, 0x2550..0x2573, 0x2580..0x258F, - 0x2592..0x2595, 0x25A0..0x25A1, 0x25A3..0x25A9, - 0x25B2..0x25B3, 0x25B6..0x25B7, 0x25BC..0x25BD, - 0x25C0..0x25C1, 0x25C6..0x25C8, 0x25CB..0x25CB, - 0x25CE..0x25D1, 0x25E2..0x25E5, 0x25EF..0x25EF, - 0x2605..0x2606, 0x2609..0x2609, 0x260E..0x260F, - 0x2614..0x2615, 0x261C..0x261C, 0x261E..0x261E, - 0x2640..0x2640, 0x2642..0x2642, 0x2660..0x2661, - 0x2663..0x2665, 0x2667..0x266A, 0x266C..0x266D, - 0x266F..0x266F, 0x273D..0x273D, 0x2776..0x277F, - 0xE000..0xF8FF, 0xFE00..0xFE0F, 0xFFFD..0xFFFD, - 0xE0100..0xE01EF, 0xF0000..0xFFFFD, 0x100000..0x10FFFD, - ] - - def wide_character?(character) - binary_search_ranges(character, WIDE_CHARACTERS) or - binary_search_ranges(character, AMBIGUOUS) - end - - private - def binary_search_ranges(character, ranges) - if ranges.size.zero? - false - elsif ranges.size == 1 - ranges[0].include?(character) - else - half = ranges.size / 2 - range = ranges[half] - if range.include?(character) - true - elsif character < range.begin - binary_search_ranges(character, ranges[0...half]) - else - binary_search_ranges(character, ranges[(half + 1)..-1]) - end - end - end - end - - def initialize(line) - @line = line - @characters = @line.unpack("U*") - end - - def [](*args) - result = @characters[*args] - if result.respond_to?(:pack) - result.pack("U*") - else - result - end - end - - def each(&block) - @characters.each(&block) - end - - def size - @characters.size - end - - def to_s - @line - end - - def compute_width(start, _end) - width = 0 - start.upto(_end - 1) do |i| - if self.class.wide_character?(@characters[i]) - width += 2 - else - width += 1 - end - end - width - end - end - - class ReadableDiffer < Differ - def diff(options={}) - @result = [] - operations.each do |tag, from_start, from_end, to_start, to_end| - case tag - when :replace - diff_lines(from_start, from_end, to_start, to_end) - when :delete - tag_deleted(@from[from_start...from_end]) - when :insert - tag_inserted(@to[to_start...to_end]) - when :equal - tag_equal(@from[from_start...from_end]) - else - raise "unknown tag: #{tag}" - end - end - @result - end - - private - def operations - @operations ||= nil - if @operations.nil? - matcher = SequenceMatcher.new(@from, @to) - @operations = matcher.operations - end - @operations - end - - def default_ratio - 0.74 - end - - def cut_off_ratio - 0.75 - end - - def tag(mark, contents) - contents.each do |content| - @result << (mark + content) - end - end - - def tag_deleted(contents) - tag("- ", contents) - end - - def tag_inserted(contents) - tag("+ ", contents) - end - - def tag_equal(contents) - tag(" ", contents) - end - - def tag_difference(contents) - tag("? ", contents) - end - - def find_diff_line_info(from_start, from_end, to_start, to_end) - best_ratio = default_ratio - from_equal_index = to_equal_index = nil - from_best_index = to_best_index = nil - - to_start.upto(to_end - 1) do |to_index| - from_start.upto(from_end - 1) do |from_index| - if @from[from_index] == @to[to_index] - from_equal_index ||= from_index - to_equal_index ||= to_index - next - end - - matcher = SequenceMatcher.new(@from[from_index], @to[to_index], - &method(:space_character?)) - if matcher.ratio > best_ratio - best_ratio = matcher.ratio - from_best_index = from_index - to_best_index = to_index - end - end - end - - [best_ratio, - from_equal_index, to_equal_index, - from_best_index, to_best_index] - end - - def diff_lines(from_start, from_end, to_start, to_end) - info = find_diff_line_info(from_start, from_end, to_start, to_end) - best_ratio, from_equal_index, to_equal_index, *info = info - from_best_index, to_best_index = info - from_best_index ||= from_start - to_best_index ||= to_start - - if best_ratio < cut_off_ratio - if from_equal_index.nil? - if to_end - to_start < from_end - from_start - tag_inserted(@to[to_start...to_end]) - tag_deleted(@from[from_start...from_end]) - else - tag_deleted(@from[from_start...from_end]) - tag_inserted(@to[to_start...to_end]) - end - return - end - from_best_index = from_equal_index - to_best_index = to_equal_index - best_ratio = 1.0 - end - - _diff_lines(from_start, from_best_index, to_start, to_best_index) - diff_line(@from[from_best_index], @to[to_best_index]) - _diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end) - end - - def _diff_lines(from_start, from_end, to_start, to_end) - if from_start < from_end - if to_start < to_end - diff_lines(from_start, from_end, to_start, to_end) - else - tag_deleted(@from[from_start...from_end]) - end - else - tag_inserted(@to[to_start...to_end]) - end - end - - def line_operations(from_line, to_line) - if !from_line.respond_to?(:force_encoding) and $KCODE == "UTF8" - from_line = UTF8Line.new(from_line) - to_line = UTF8Line.new(to_line) - end - matcher = SequenceMatcher.new(from_line, to_line, - &method(:space_character?)) - [from_line, to_line, matcher.operations] - end - - def compute_width(line, start, _end) - if line.respond_to?(:encoding) and - Encoding.compatible?(Encoding::UTF_8, line.encoding) - utf8_line = line[start..._end].encode(Encoding::UTF_8) - width = 0 - utf8_line.each_codepoint do |unicode_codepoint| - if UTF8Line.wide_character?(unicode_codepoint) - width += 2 - else - width += 1 - end - end - width - elsif line.is_a?(UTF8Line) - line.compute_width(start, _end) - else - _end - start - end - end - - def diff_line(from_line, to_line) - from_tags = "" - to_tags = "" - from_line, to_line, _operations = line_operations(from_line, to_line) - _operations.each do |tag, from_start, from_end, to_start, to_end| - from_width = compute_width(from_line, from_start, from_end) - to_width = compute_width(to_line, to_start, to_end) - case tag - when :replace - from_tags += "^" * from_width - to_tags += "^" * to_width - when :delete - from_tags += "-" * from_width - when :insert - to_tags += "+" * to_width - when :equal - from_tags += " " * from_width - to_tags += " " * to_width - else - raise "unknown tag: #{tag}" - end - end - format_diff_point(from_line, to_line, from_tags, to_tags) - end - - def format_diff_point(from_line, to_line, from_tags, to_tags) - common = [n_leading_characters(from_line, ?\t), - n_leading_characters(to_line, ?\t)].min - common = [common, - n_leading_characters(from_tags[0, common], " "[0])].min - from_tags = from_tags[common..-1].rstrip - to_tags = to_tags[common..-1].rstrip - - tag_deleted([from_line]) - unless from_tags.empty? - tag_difference(["#{"\t" * common}#{from_tags}"]) - end - tag_inserted([to_line]) - unless to_tags.empty? - tag_difference(["#{"\t" * common}#{to_tags}"]) - end - end - - def n_leading_characters(string, character) - n = 0 - while string[n] == character - n += 1 - end - n - end - - def space_character?(character) - [" "[0], "\t"[0]].include?(character) - end - end - - class UnifiedDiffer < Differ - def diff(options={}) - groups = SequenceMatcher.new(@from, @to).grouped_operations - return [] if groups.empty? - return [] if same_content?(groups) - - show_context = options[:show_context] - show_context = true if show_context.nil? - result = ["--- #{options[:from_label]}".rstrip, - "+++ #{options[:to_label]}".rstrip] - groups.each do |operations| - result << format_summary(operations, show_context) - operations.each do |args| - operation_tag, from_start, from_end, to_start, to_end = args - case operation_tag - when :replace - result.concat(tag("-", @from[from_start...from_end])) - result.concat(tag("+", @to[to_start...to_end])) - when :delete - result.concat(tag("-", @from[from_start...from_end])) - when :insert - result.concat(tag("+", @to[to_start...to_end])) - when :equal - result.concat(tag(" ", @from[from_start...from_end])) - end - end - end - result - end - - private - def same_content?(groups) - return false if groups.size != 1 - group = groups[0] - return false if group.size != 1 - tag, from_start, from_end, to_start, to_end = group[0] - - tag == :equal and [from_start, from_end] == [to_start, to_end] - end - - def format_summary(operations, show_context) - _, first_from_start, _, first_to_start, _ = operations[0] - _, _, last_from_end, _, last_to_end = operations[-1] - summary = "@@ -%d,%d +%d,%d @@" % [first_from_start + 1, - last_from_end - first_from_start, - first_to_start + 1, - last_to_end - first_to_start,] - if show_context - interesting_line = find_interesting_line(first_from_start, - first_to_start, - :define_line?) - summary << " #{interesting_line}" if interesting_line - end - summary - end - - def find_interesting_line(from_start, to_start, predicate) - from_index = from_start - to_index = to_start - while from_index >= 0 or to_index >= 0 - [@from[from_index], @to[to_index]].each do |line| - return line if line and __send__(predicate, line) - end - - from_index -= 1 - to_index -= 1 - end - nil - end - - def define_line?(line) - /\A(?:[_a-zA-Z$]|\s*(?:class|module|def)\b)/ =~ line - end - end - - module_function - def need_fold?(diff) - /^[-+].{79}/ =~ diff - end - - def fold(string) - string.split(/\r?\n/).collect do |line| - line.gsub(/(.{78})/, "\\1\n") - end.join("\n") - end - - def folded_readable(from, to, options={}) - readable(fold(from), fold(to), options) - end - - def readable(from, to, options={}) - diff(ReadableDiffer, from, to, options) - end - - def unified(from, to, options={}) - diff(UnifiedDiffer, from, to, options) - end - - def diff(differ_class, from, to, options={}) - if from.respond_to?(:valid_encoding?) and not from.valid_encoding? - from = from.dup.force_encoding("ASCII-8BIT") - end - if to.respond_to?(:valid_encoding?) and not to.valid_encoding? - to = to.dup.force_encoding("ASCII-8BIT") - end - differ = differ_class.new(from.split(/\r?\n/), to.split(/\r?\n/)) - lines = differ.diff(options) - if Object.const_defined?(:EncodingError) - begin - lines.join("\n") - rescue EncodingError - lines.collect {|line| line.force_encoding("ASCII-8BIT")}.join("\n") - end - else - lines.join("\n") - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/error.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/error.rb deleted file mode 100644 index 1b5652472..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/error.rb +++ /dev/null @@ -1,158 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/util/backtracefilter' - -module Test - module Unit - - # Encapsulates an error in a test. Created by - # Test::Unit::TestCase when it rescues an exception thrown - # during the processing of a test. - class Error - include Util::BacktraceFilter - - attr_reader :test_name, :exception - attr_reader :method_name - - SINGLE_CHARACTER = 'E' - LABEL = "Error" - - # Creates a new Error with the given test_name and - # exception. - def initialize(test_name, exception, options={}) - @test_name = test_name - @exception = exception - @method_name = options[:method_name] - end - - # Returns a single character representation of an error. - def single_character_display - SINGLE_CHARACTER - end - - def label - LABEL - end - - # Returns the message associated with the error. - def message - "#{@exception.class.name}: #{@exception.message}" - end - - # Returns a brief version of the error description. - def short_display - "#@test_name: #{message.split("\n")[0]}" - end - - # Returns a verbose version of the error description. - def long_display - backtrace_display = location.join("\n ") - "#{label}:\n#@test_name:\n#{message}\n #{backtrace_display}" - end - - def location - @location ||= filter_backtrace(@exception.backtrace) - end - alias_method :backtrace, :location # Deprecated - - # Overridden to return long_display. - def to_s - long_display - end - - def critical? - true - end - end - - module ErrorHandler - class << self - def included(base) - base.exception_handler(:handle_all_exception) - end - end - - NOT_PASS_THROUGH_EXCEPTIONS = [] - NOT_PASS_THROUGH_EXCEPTION_NAMES = ["Timeout::Error"] - PASS_THROUGH_EXCEPTIONS = [ - NoMemoryError, - SignalException, - Interrupt, - SystemExit, - ] - PASS_THROUGH_EXCEPTION_NAMES = [] - private - def handle_all_exception(exception) - return false if pass_through_exception?(exception) - - problem_occurred - add_error(exception) - true - end - - def pass_through_exception?(exception) - case exception - when *NOT_PASS_THROUGH_EXCEPTIONS - return false - end - case exception.class.name - when *NOT_PASS_THROUGH_EXCEPTION_NAMES - return false - end - - case exception - when *PASS_THROUGH_EXCEPTIONS - return true - end - case exception.class.name - when *PASS_THROUGH_EXCEPTION_NAMES - return true - end - - false - end - - def add_error(exception) - error = Error.new(name, exception, :method_name => @method_name) - current_result.add_error(error) - end - end - - module TestResultErrorSupport - attr_reader :errors - - # Records a Test::Unit::Error. - def add_error(error) - @errors << error - notify_fault(error) - notify_changed - end - - # Returns the number of errors this TestResult has - # recorded. - def error_count - @errors.size - end - - def error_occurred? - not @errors.empty? - end - - private - def initialize_containers - super - @errors = [] - @summary_generators << :error_summary - @problem_checkers << :error_occurred? - end - - def error_summary - "#{error_count} errors" - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/exception-handler.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/exception-handler.rb deleted file mode 100644 index 9a5f1a2c4..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/exception-handler.rb +++ /dev/null @@ -1,82 +0,0 @@ -module Test - module Unit - module ExceptionHandler - @@exception_handlers = [] - class << self - def exception_handlers - @@exception_handlers - end - - def included(base) - base.extend(ClassMethods) - - observer = Proc.new do |test_case, _, _, value, method_name| - if value - @@exception_handlers.unshift(method_name) - else - @@exception_handlers.delete(method_name) - end - end - base.register_attribute_observer(:exception_handler, &observer) - end - end - - module ClassMethods - def exception_handlers - ExceptionHandler.exception_handlers - end - - # @overload exception_handler(method_name) - # Add an exception handler method. - # - # @param method_name [Symbol] - # The method name that handles exception raised in tests. - # @return [void] - # - # @overload exception_handler(&callback) - # Add an exception handler. - # - # @yield [test, exception] - # Gives the test and the exception. - # @yieldparam test [Test::Unit::TestCase] - # The test where the exception is raised. - # @yieldparam exception [Exception] - # The exception that is raised in running the test. - # @yieldreturn [Boolean] - # Whether the handler handles the exception or not. - # The handler must return _true_ if the handler handles - # test exception, _false_ otherwise. - # @return [void] - # - # This is a public API for developers who extend test-unit. - def exception_handler(*method_name_or_handlers, &block) - if block_given? - exception_handlers.unshift(block) - else - method_name_or_handlers.each do |method_name_or_handler| - if method_name_or_handler.respond_to?(:call) - handler = method_name_or_handler - exception_handlers.unshift(handler) - else - method_name = method_name_or_handler - attribute(:exception_handler, true, {}, method_name) - end - end - end - end - - def unregister_exception_handler(*method_name_or_handlers) - method_name_or_handlers.each do |method_name_or_handler| - if method_name_or_handler.respond_to?(:call) - handler = method_name_or_handler - exception_handlers.delete(handler) - else - method_name = method_name_or_handler - attribute(:exception_handler, false, {}, method_name) - end - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/failure.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/failure.rb deleted file mode 100644 index 2e386cfc3..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/failure.rb +++ /dev/null @@ -1,169 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -module Test - module Unit - - # Encapsulates a test failure. Created by Test::Unit::TestCase - # when an assertion fails. - class Failure - attr_reader :test_name, :location, :message - attr_reader :method_name, :source_location - attr_reader :expected, :actual, :user_message - attr_reader :inspected_expected, :inspected_actual - - SINGLE_CHARACTER = 'F' - LABEL = "Failure" - - # Creates a new Failure with the given location and - # message. - def initialize(test_name, location, message, options={}) - @test_name = test_name - @location = location - @message = message - @method_name = options[:method_name] - @source_location = options[:source_location] - @expected = options[:expected] - @actual = options[:actual] - @inspected_expected = options[:inspected_expected] - @inspected_actual = options[:inspected_actual] - @user_message = options[:user_message] - end - - # Returns a single character representation of a failure. - def single_character_display - SINGLE_CHARACTER - end - - def label - LABEL - end - - # Returns a brief version of the error description. - def short_display - "#@test_name: #{@message.split("\n")[0]}" - end - - # Returns a verbose version of the error description. - def long_display - if location.size == 1 - location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]') - else - location_display = "\n [#{location.join("\n ")}]" - end - "#{label}:\n#@test_name#{location_display}:\n#@message" - end - - # Overridden to return long_display. - def to_s - long_display - end - - def critical? - true - end - - def diff - @diff ||= compute_diff - end - - private - def compute_diff - Assertions::AssertionMessage.delayed_diff(@expected, @actual).inspect - end - end - - module FailureHandler - class << self - def included(base) - base.exception_handler(:handle_assertion_failed_error) - end - end - - # Report a failure. - # - # This is a public API for developers who extend test-unit. - # - # @param message [String] The description about the failure. - # @param backtrace [Array] The backtrace for the failure. - # @option options [Object] :expected - # The expected value of the assertion. - # @option options [Object] :actual - # The actual value of the assertion. - # @option options [String] :inspected_expected - # The inspected expected value of the assertion. - # It is used for diff between expected and actual of the failure. - # @option options [String] :inspected_actual - # The inspected actual value of the assertion. - # It is used for diff between expected and actual of the failure. - # @option options [String] :user_message - # The message of the assertion from user. - # @option options [String] :method_name (@method_name) - # The method name of the test. - # @option options [Array] :source_location - # The location where the test is defined. It is the same - # format as Proc#source_location. That is, it's an array of - # path and and line number where the test definition is - # started. - # @return [void] - def add_failure(message, backtrace, options={}) - default_options = { - :method_name => @method_name, - :source_location => self[:source_location], - } - failure = Failure.new(name, filter_backtrace(backtrace), message, - default_options.merge(options)) - current_result.add_failure(failure) - end - - private - def handle_assertion_failed_error(exception) - return false unless exception.is_a?(AssertionFailedError) - problem_occurred - add_failure(exception.message, exception.backtrace, - :expected => exception.expected, - :actual => exception.actual, - :inspected_expected => exception.inspected_expected, - :inspected_actual => exception.inspected_actual, - :user_message => exception.user_message) - true - end - end - - module TestResultFailureSupport - attr_reader :failures - - # Records a Test::Unit::Failure. - def add_failure(failure) - @failures << failure - notify_fault(failure) - notify_changed - end - - # Returns the number of failures this TestResult has - # recorded. - def failure_count - @failures.size - end - - def failure_occurred? - not @failures.empty? - end - - private - def initialize_containers - super - @failures = [] - @summary_generators << :failure_summary - @problem_checkers << :failure_occurred? - end - - def failure_summary - "#{failure_count} failures" - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/fault-location-detector.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/fault-location-detector.rb deleted file mode 100644 index b783be17a..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/fault-location-detector.rb +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (C) 2012 Kouhei Sutou -# -# License: Ruby's - -require "English" - -module Test - module Unit - class FaultLocationDetector - def initialize(fault, code_snippet_fetcher) - @fault = fault - @code_snippet_fetcher = code_snippet_fetcher - extract_fault_information - end - - def split_backtrace_entry(entry) - match_data = /\A(.+):(\d+)(?::(.*))?\z/.match(entry) - return nil if match_data.nil? - file, line_number, context = match_data.to_a[1..-1] - line_number = line_number.to_i - if /\Ain `(.+?)'/ =~ context - method_name = $1 - if /\Ablock (?:\(.+?\) )?in / =~ method_name - method_name = $POSTMATCH - end - else - method_name = nil - end - [file, line_number, context, method_name] - end - - def target?(backtrace_entry) - file, line_number, context, method_name = - split_backtrace_entry(backtrace_entry) - _ = context - return false if file.nil? - - if @fault_source_location - target_source_location?(file, line_number, method_name) - elsif @fault_method_name - target_method?(method_name) - else - true - end - end - - private - def target_source_location?(file, line_number, method_name) - fault_file, fault_line_number = @fault_source_location - return false unless file.end_with?(fault_file) - - return false if line_number < fault_line_number - - lines = @code_snippet_fetcher.source(file) - return false if lines.nil? - - base_indent_level = nil - fault_line_number.step(lines.size) do |current_line_number| - line = lines[current_line_number - 1] - current_indent_level = guess_indent_level(line) - base_indent_level ||= current_indent_level - return true if current_line_number == line_number - - if current_line_number == fault_line_number - break if /(?:\send|\})\s*$/ =~ line - else - break if current_indent_level == base_indent_level - end - end - false - end - - def target_method?(method_name) - @fault_method_name == method_name - end - - def guess_indent_level(line) - if /\A(\s*)/ =~ line - $1.sub(/\t/, " " * 8).count(" ") - else - 0 - end - end - - def extract_fault_information - if @fault.respond_to?(:source_location) - @fault_source_location = @fault.source_location - else - @fault_source_location = nil - end - - if @fault.respond_to?(:method_name) - @fault_method_name = @fault.method_name - else - @fault_method_name = nil - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/fixture.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/fixture.rb deleted file mode 100644 index d41f25d2e..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/fixture.rb +++ /dev/null @@ -1,298 +0,0 @@ -module Test - module Unit - module Fixture - class << self - def included(base) - base.extend(ClassMethods) - - [:setup, :cleanup, :teardown].each do |type| - observer = lambda do |test_case, _, _, value, callback| - if value.nil? - test_case.fixture[type].unregister(callback) - else - test_case.fixture[type].register(callback, value) - end - end - base.register_attribute_observer(type, &observer) - end - end - end - - class Fixture - attr_reader :setup - attr_reader :cleanup - attr_reader :teardown - def initialize(test_case) - @test_case = test_case - @setup = HookPoint.new(@test_case, :setup, :after => :append) - @cleanup = HookPoint.new(@test_case, :cleanup, :before => :prepend) - @teardown = HookPoint.new(@test_case, :teardown, :before => :prepend) - @cached_before_callbacks = {} - @cached_after_callbacks = {} - end - - def [](type) - case type - when :setup - @setup - when :cleanup - @cleanup - when :teardown - @teardown - end - end - - def before_callbacks(type) - @cached_before_callbacks[type] ||= collect_before_callbacks(type) - end - - def after_callbacks(type) - @cached_after_callbacks[type] ||= collect_after_callbacks(type) - end - - private - def target_test_cases - @cached_target_test_cases ||= collect_target_test_cases - end - - def collect_before_callbacks(type) - prepend_callbacks = [] - append_callbacks = [] - target_test_cases.each do |ancestor| - prepend_callbacks << ancestor.fixture[type].before_prepend_callbacks - append_callbacks << ancestor.fixture[type].before_append_callbacks - end - - merge_callbacks(prepend_callbacks, append_callbacks) - end - - def collect_after_callbacks(type) - prepend_callbacks = [] - append_callbacks = [] - target_test_cases.each do |ancestor| - prepend_callbacks << ancestor.fixture[type].after_prepend_callbacks - append_callbacks << ancestor.fixture[type].after_append_callbacks - end - - merge_callbacks(prepend_callbacks, append_callbacks) - end - - def collect_target_test_cases - ancestors = @test_case.ancestors - base_index = ancestors.index(::Test::Unit::Fixture) - interested_ancestors = ancestors[0, base_index].find_all do |ancestor| - ancestor.is_a?(Class) - end - interested_ancestors.reverse - end - - def merge_callbacks(prepend_callbacks, append_callbacks) - all_callbacks = [] - prepend_callbacks.reverse_each do |callbacks| - all_callbacks.concat(callbacks) - end - append_callbacks.each do |callbacks| - all_callbacks.concat(callbacks) - end - all_callbacks - end - end - - class HookPoint - def initialize(test_case, type, default_options) - @test_case = test_case - @type = type - @default_options = default_options - @before_prepend_callbacks = [] - @before_append_callbacks = [] - @after_prepend_callbacks = [] - @after_append_callbacks = [] - @unregistered_callbacks = [] - end - - def register(method_name_or_callback, options=nil) - options ||= {} - unless valid_register_options?(options) - message = "must be {:before => :prepend}, " + - "{:before => :append}, {:after => :prepend} or " + - "{:after => :append}: #{options.inspect}" - raise ArgumentError, message - end - - if options.empty? - options = @default_options - end - before_how = options[:before] - after_how = options[:after] - if method_name_or_callback.respond_to?(:call) - callback = method_name_or_callback - method_name = callback_method_name(callback) - @test_case.attribute(:source_location, - callback.source_location, - method_name) - @test_case.__send__(:define_method, method_name, &callback) - else - method_name = method_name_or_callback - end - add_callback(method_name, before_how, after_how) - end - - def unregister(method_name_or_callback) - if method_name_or_callback.respond_to?(:call) - callback = method_name_or_callback - method_name = callback_method_name(callback) - else - method_name = method_name_or_callback - end - @unregistered_callbacks << method_name - end - - def before_prepend_callbacks - @before_prepend_callbacks - @unregistered_callbacks - end - - def before_append_callbacks - @before_append_callbacks - @unregistered_callbacks - end - - def after_prepend_callbacks - @after_prepend_callbacks - @unregistered_callbacks - end - - def after_append_callbacks - @after_append_callbacks - @unregistered_callbacks - end - - private - def valid_register_options?(options) - return true if options.empty? - return false if options.size > 1 - - key = options.keys.first - [:before, :after].include?(key) and - [:prepend, :append].include?(options[key]) - end - - def callback_method_name(callback) - "#{@type}_#{callback.object_id}" - end - - def add_callback(method_name_or_callback, before_how, after_how) - case before_how - when :prepend - @before_prepend_callbacks = - [method_name_or_callback] | @before_prepend_callbacks - when :append - @before_append_callbacks |= [method_name_or_callback] - else - case after_how - when :prepend - @after_prepend_callbacks = - [method_name_or_callback] | @after_prepend_callbacks - when :append - @after_append_callbacks |= [method_name_or_callback] - end - end - end - end - - module ClassMethods - def fixture - @fixture ||= Fixture.new(self) - end - - def setup(*method_names, &callback) - register_fixture(:setup, *method_names, &callback) - end - - def unregister_setup(*method_names_or_callbacks) - unregister_fixture(:setup, *method_names_or_callbacks) - end - - def cleanup(*method_names, &callback) - register_fixture(:cleanup, *method_names, &callback) - end - - def unregister_cleanup(*method_names_or_callbacks) - unregister_fixture(:cleanup, *method_names_or_callbacks) - end - - def teardown(*method_names, &callback) - register_fixture(:teardown, *method_names, &callback) - end - - def unregister_teardown(*method_names_or_callbacks) - unregister_fixture(:teardown, *method_names_or_callbacks) - end - - private - def register_fixture(fixture, *method_names, &callback) - options = {} - options = method_names.pop if method_names.last.is_a?(Hash) - callbacks = method_names - callbacks << callback if callback - attribute(fixture, options, *callbacks) - end - - def unregister_fixture(fixture, *method_names_or_callbacks) - attribute(fixture, nil, *method_names_or_callbacks) - end - end - - private - def run_fixture(type, options={}, &block) - fixtures = [ - self.class.fixture.before_callbacks(type), - type, - self.class.fixture.after_callbacks(type), - ].flatten - if block - runner = create_fixtures_runner(fixtures, options, &block) - runner.call - else - fixtures.each do |method_name| - run_fixture_callback(method_name, options) - end - end - end - - def create_fixtures_runner(fixtures, options, &block) - if fixtures.empty? - block - else - last_fixture = fixtures.pop - create_fixtures_runner(fixtures, options) do - block_is_called = false - run_fixture_callback(last_fixture, options) do - block_is_called = true - block.call - end - block.call unless block_is_called - end - end - end - - def run_fixture_callback(method_name, options, &block) - return unless respond_to?(method_name, true) - begin - __send__(method_name, &block) - rescue Exception - raise unless options[:handle_exception] - raise unless handle_exception($!) - end - end - - def run_setup(&block) - run_fixture(:setup, &block) - end - - def run_cleanup - run_fixture(:cleanup) - end - - def run_teardown - run_fixture(:teardown, :handle_exception => true) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/notification.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/notification.rb deleted file mode 100644 index adc412dec..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/notification.rb +++ /dev/null @@ -1,138 +0,0 @@ -require 'test/unit/util/backtracefilter' - -module Test - module Unit - class Notification - include Util::BacktraceFilter - attr_reader :test_name, :location, :message - attr_reader :method_name - - SINGLE_CHARACTER = 'N' - LABEL = "Notification" - - # Creates a new Notification with the given location and - # message. - def initialize(test_name, location, message, options={}) - @test_name = test_name - @location = location - @message = message - @method_name = options[:method_name] - end - - # Returns a single character representation of a notification. - def single_character_display - SINGLE_CHARACTER - end - - def label - LABEL - end - - # Returns a brief version of the error description. - def short_display - "#{@test_name}: #{@message.split("\n")[0]}" - end - - # Returns a verbose version of the error description. - def long_display - backtrace = filter_backtrace(location).join("\n") - "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" - end - - # Overridden to return long_display. - def to_s - long_display - end - - def critical? - false - end - end - - class NotifiedError < StandardError - end - - - module TestCaseNotificationSupport - class << self - def included(base) - base.class_eval do - include NotificationHandler - end - end - end - - # Notify some information. - # - # Example: - # - # def test_notification - # notify("I'm here!") - # # Reached here - # notify("Special!") if special_case? - # # Reached here too - # end - # - # options: - # - # :backtrace override backtrace. - def notify(message, options={}, &block) - backtrace = filter_backtrace(options[:backtrace] || caller) - notification = Notification.new(name, backtrace, message, - :method_name => @method_name) - add_notification(notification) - end - - private - def add_notification(notification) - current_result.add_notification(notification) - end - end - - module NotificationHandler - class << self - def included(base) - base.exception_handler(:handle_notified_error) - end - end - - private - def handle_notified_error(exception) - return false unless exception.is_a?(NotifiedError) - notification = Notification.new(name, - filter_backtrace(exception.backtrace), - exception.message) - add_notification(notification) - true - end - end - - module TestResultNotificationSupport - attr_reader :notifications - - # Records a Test::Unit::Notification. - def add_notification(notification) - @notifications << notification - notify_fault(notification) - notify_changed - end - - # Returns the number of notifications this TestResult has - # recorded. - def notification_count - @notifications.size - end - - private - def initialize_containers - super - @notifications = [] - @summary_generators << :notification_summary - end - - def notification_summary - "#{notification_count} notifications" - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/omission.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/omission.rb deleted file mode 100644 index e608048ff..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/omission.rb +++ /dev/null @@ -1,198 +0,0 @@ -require 'test/unit/util/backtracefilter' - -module Test - module Unit - class Omission - include Util::BacktraceFilter - attr_reader :test_name, :location, :message - attr_reader :method_name - - SINGLE_CHARACTER = 'O' - LABEL = "Omission" - - # Creates a new Omission with the given location and - # message. - def initialize(test_name, location, message, options={}) - @test_name = test_name - @location = location - @message = message - @method_name = options[:method_name] - end - - # Returns a single character representation of a omission. - def single_character_display - SINGLE_CHARACTER - end - - def label - LABEL - end - - # Returns a brief version of the error description. - def short_display - "#{@test_name}: #{@message.split("\n")[0]}" - end - - # Returns a verbose version of the error description. - def long_display - backtrace = filter_backtrace(location).join("\n") - "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" - end - - # Overridden to return long_display. - def to_s - long_display - end - - def critical? - true - end - end - - class OmittedError < StandardError - end - - - module TestCaseOmissionSupport - class << self - def included(base) - base.class_eval do - include OmissionHandler - end - end - end - - # Omit the test or part of the test. - # - # Example: - # - # def test_omission - # omit - # # Not reached here - # end - # - # def test_omission_with_here - # omit do - # # Not ran here - # end - # # Reached here - # end - def omit(message=nil, &block) - message ||= "omitted." - if block_given? - omission = Omission.new(name, filter_backtrace(caller), message, - :method_name => @method_name) - add_omission(omission) - else - raise OmittedError.new(message) - end - end - - # Omit the test or part of the test if _condition_ is - # true. - # - # Example: - # - # def test_omission - # omit_if("".empty?) - # # Not reached here - # end - # - # def test_omission_with_here - # omit_if(true) do - # # Not ran here - # end - # omit_if(false) do - # # Reached here - # end - # # Reached here too - # end - def omit_if(condition, *args, &block) - if condition - omit(*args, &block) - else - block.call if block - end - end - - # Omit the test or part of the test if _condition_ is - # not true. - # - # Example: - # - # def test_omission - # omit_unless("string".empty?) - # # Not reached here - # end - # - # def test_omission_with_here - # omit_unless(true) do - # # Reached here - # end - # omit_unless(false) do - # # Not ran here - # end - # # Reached here too - # end - def omit_unless(condition, *args, &block) - if condition - block.call if block - else - omit(*args, &block) - end - end - - private - def add_omission(omission) - current_result.add_omission(omission) - end - end - - module OmissionHandler - class << self - def included(base) - base.exception_handler(:handle_omitted_error) - end - end - - private - def handle_omitted_error(exception) - return false unless exception.is_a?(OmittedError) - omission = Omission.new(name, - filter_backtrace(exception.backtrace), - exception.message, - :method_name => @method_name) - add_omission(omission) - true - end - end - - module TestResultOmissionSupport - attr_reader :omissions - - # Records a Test::Unit::Omission. - def add_omission(omission) - @omissions << omission - notify_fault(omission) - notify_changed - end - - # Returns the number of omissions this TestResult has - # recorded. - def omission_count - @omissions.size - end - - private - def initialize_containers - super - @omissions = [] - @summary_generators << :omission_summary - end - - def omission_summary - "#{omission_count} omissions" - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/pending.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/pending.rb deleted file mode 100644 index f03dd9a21..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/pending.rb +++ /dev/null @@ -1,155 +0,0 @@ -require 'test/unit/util/backtracefilter' - -module Test - module Unit - class Pending - include Util::BacktraceFilter - attr_reader :test_name, :location, :message - attr_reader :method_name - - SINGLE_CHARACTER = 'P' - LABEL = "Pending" - - # Creates a new Pending with the given location and - # message. - def initialize(test_name, location, message, options={}) - @test_name = test_name - @location = location - @message = message - @method_name = options[:method_name] - end - - # Returns a single character representation of a pending. - def single_character_display - SINGLE_CHARACTER - end - - def label - LABEL - end - - # Returns a brief version of the error description. - def short_display - "#{@test_name}: #{@message.split("\n")[0]}" - end - - # Returns a verbose version of the error description. - def long_display - backtrace = filter_backtrace(location).join("\n") - "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" - end - - # Overridden to return long_display. - def to_s - long_display - end - - def critical? - true - end - end - - class PendedError < StandardError - end - - - module TestCasePendingSupport - class << self - def included(base) - base.class_eval do - include PendingHandler - end - end - end - - # Marks the test or part of the test is pending. - # - # Example: - # - # def test_pending - # pend - # # Not reached here - # end - # - # def test_pending_with_here - # pend do - # # Ran here - # # Fails if the block doesn't raise any error. - # # Because it means the block is passed unexpectedly. - # end - # # Reached here - # end - def pend(message=nil, &block) - message ||= "pended." - if block_given? - pending = nil - begin - yield - rescue Exception - pending = Pending.new(name, filter_backtrace(caller), message, - :method_name => @method_name) - add_pending(pending) - end - unless pending - flunk("Pending block should not be passed: #{message}") - end - else - raise PendedError.new(message) - end - end - - private - def add_pending(pending) - problem_occurred - current_result.add_pending(pending) - end - end - - module PendingHandler - class << self - def included(base) - base.exception_handler(:handle_pended_error) - end - end - - private - def handle_pended_error(exception) - return false unless exception.is_a?(PendedError) - pending = Pending.new(name, - filter_backtrace(exception.backtrace), - exception.message, - :method_name => @method_name) - add_pending(pending) - true - end - end - - module TestResultPendingSupport - attr_reader :pendings - - # Records a Test::Unit::Pending. - def add_pending(pending) - @pendings << pending - notify_fault(pending) - notify_changed - end - - # Returns the number of pendings this TestResult has - # recorded. - def pending_count - @pendings.size - end - - private - def initialize_containers - super - @pendings = [] - @summary_generators << :pending_summary - end - - def pending_summary - "#{pending_count} pendings" - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/priority.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/priority.rb deleted file mode 100644 index 1858007d2..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/priority.rb +++ /dev/null @@ -1,196 +0,0 @@ -require "fileutils" - -module Test - module Unit - module Priority - class << self - def included(base) - base.extend(ClassMethods) - - base.class_eval do - setup :priority_setup, :before => :prepend - teardown :priority_teardown, :after => :append - end - end - - @@enabled = false - def enabled? - @@enabled - end - - def enable - require "fileutils" - require "tmpdir" - @@enabled = true - end - - def disable - @@enabled = false - end - - @@default = :normal - def default - @@default || :normal - end - - def default=(default) - @@default = default - end - - def available_values - Checker.available_priorities - end - end - - class Checker - class << self - def have_priority?(name) - singleton_class = (class << self; self; end) - singleton_class.method_defined?(priority_check_method_name(name)) - end - - def need_to_run?(test) - priority = test[:priority] || Priority.default - if have_priority?(priority) - __send__(priority_check_method_name(priority), test) - else - true - end - end - - def available_priorities - methods(false).collect do |name| - /\Arun_priority_(.+)\?\z/ =~ name.to_s - $1 - end.compact - end - - def run_priority_must?(test) - true - end - - def run_priority_important?(test) - rand > 0.1 - end - - def run_priority_high?(test) - rand > 0.3 - end - - def run_priority_normal?(test) - rand > 0.5 - end - - def run_priority_low?(test) - rand > 0.75 - end - - def run_priority_never?(test) - false - end - - private - def priority_check_method_name(priority_name) - "run_priority_#{priority_name}?" - end - end - - attr_reader :test - def initialize(test) - @test = test - end - - def setup - FileUtils.rm_f(passed_file) - end - - def teardown - if @test.__send__(:passed?) - FileUtils.touch(passed_file) - else - FileUtils.rm_f(passed_file) - end - end - - def need_to_run? - !previous_test_success? or self.class.need_to_run?(@test) - end - - private - def previous_test_success? - File.exist?(passed_file) - end - - def result_dir - components = [ - ".test-result", - escape_class_name(@test.class.name || "AnonymousTestCase"), - escaped_method_name, - ] - parent_directories = [File.dirname($0), Dir.pwd] - if Process.respond_to?(:uid) - parent_directories << File.join(Dir.tmpdir, Process.uid.to_s) - end - parent_directories.each do |parent_directory| - dir = File.expand_path(File.join(parent_directory, *components)) - begin - FileUtils.mkdir_p(dir) - return dir - rescue Errno::EACCES - end - end - - raise Errno::EACCES, parent_directories.join(", ") - end - - def passed_file - File.join(result_dir, "passed") - end - - def escape_class_name(class_name) - escape_name(class_name) - end - - def escaped_method_name - escape_name(@test.method_name.to_s) - end - - def escape_name(name) - name.gsub(/(?:[: \/!?=])/) do |matched| - case matched - when ":" - "_colon_" - when " ", "/" - "_" - when "!" - ".destructive" - when "?" - ".predicate" - when "=" - ".equal" - end - end - end - end - - module ClassMethods - def priority(name, *tests) - unless Checker.have_priority?(name) - raise ArgumentError, "unknown priority: #{name}" - end - attribute(:priority, name, {:keep => true}, *tests) - end - end - - def priority_setup - return unless Priority.enabled? - Checker.new(self).setup - end - - def priority_teardown - return unless Priority.enabled? - Checker.new(self).teardown - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/console.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/console.rb deleted file mode 100644 index 20139e767..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/console.rb +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2008-2017 Kouhei Sutou -# -# License: Ruby OR LGPL-2.1+ -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -module Test - module Unit - AutoRunner.register_runner(:console) do |auto_runner| - require 'test/unit/ui/console/testrunner' - Test::Unit::UI::Console::TestRunner - end - - AutoRunner.setup_option do |auto_runner, opts| - require 'test/unit/ui/console/outputlevel' - - output_levels = [ - ["silent", UI::Console::OutputLevel::SILENT], - ["progress", UI::Console::OutputLevel::PROGRESS_ONLY], - ["important-only", UI::Console::OutputLevel::IMPORTANT_FAULTS_ONLY], - ["normal", UI::Console::OutputLevel::NORMAL], - ["verbose", UI::Console::OutputLevel::VERBOSE], - ] - opts.on('-v', '--verbose=[LEVEL]', output_levels, - "Set the output level (default is verbose).", - "(#{auto_runner.keyword_display(output_levels)})") do |level| - level ||= output_levels.assoc("verbose")[1] - auto_runner.runner_options[:output_level] = level - end - - use_color_options = [ - [:auto, :auto], - ["-", false], - ["no", false], - ["false", false], - ["+", true], - ["yes", true], - ["true", true], - ] - opts.on("--[no-]use-color=[auto]", use_color_options, - "Uses color output", - "(default is auto)") do |use_color| - case use_color - when nil - use_color = true - when :auto - use_color = nil - end - auto_runner.runner_options[:use_color] = use_color - end - - opts.on("--progress-row-max=MAX", Integer, - "Uses MAX as max terminal width for progress mark", - "(default is auto)") do |max| - auto_runner.runner_options[:progress_row_max] = max - end - - opts.on("--no-show-detail-immediately", - "Shows not passed test details immediately.", - "(default is yes)") do |boolean| - auto_runner.runner_options[:show_detail_immediately] = boolean - end - - opts.on("--[no-]reverse-output", - "Shows fault details in reverse.", - "(default is yes for tty output, no otherwise)") do |boolean| - auto_runner.runner_options[:reverse_output] = boolean - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/emacs.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/emacs.rb deleted file mode 100644 index c2546576d..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/emacs.rb +++ /dev/null @@ -1,8 +0,0 @@ -module Test - module Unit - AutoRunner.register_runner(:emacs) do |auto_runner| - require 'test/unit/ui/emacs/testrunner' - Test::Unit::UI::Emacs::TestRunner - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/xml.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/xml.rb deleted file mode 100644 index aea03760c..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/runner/xml.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Test - module Unit - AutoRunner.register_runner(:xml) do |auto_runner| - require 'test/unit/ui/xml/testrunner' - Test::Unit::UI::XML::TestRunner - end - - AutoRunner.setup_option do |auto_runner, opts| - opts.on("--output-file-descriptor=FD", Integer, - "Outputs to file descriptor FD") do |fd| - auto_runner.runner_options[:output_file_descriptor] = fd - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/test-suite-creator.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/test-suite-creator.rb deleted file mode 100644 index f625a886f..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/test-suite-creator.rb +++ /dev/null @@ -1,103 +0,0 @@ -#-- -# -# Author:: Kouhei Sutou -# Copyright:: -# * Copyright (c) 2011 Kouhei Sutou -# License:: Ruby license. - -require "test/unit/data-sets" - -module Test - module Unit - class TestSuiteCreator # :nodoc: - class << self - def test_method?(test_case, method_name) - /\Atest./ =~ method_name.to_s or - test_case.find_attribute(method_name, :test) - end - end - - def initialize(test_case) - @test_case = test_case - end - - def create - suite = TestSuite.new(@test_case.name, @test_case) - collect_test_names.each do |test_name| - data_sets = extract_data_sets(test_name) - if data_sets - data_sets.each do |label, data| - append_test(suite, test_name) do |test| - test.assign_test_data(label, data) - end - end - else - append_test(suite, test_name) - end - end - append_test(suite, "default_test") if suite.empty? - suite - end - - private - def extract_data_sets(test_name) - data_sets = @test_case.find_attribute(test_name, - :data, - :recursive => false) - data_method_name = "data_#{test_name}" - test = @test_case.new(test_name) - if test.respond_to?(data_method_name) - data_method = test.method(data_method_name) - if data_method.arity <= 0 - data_sets ||= DataSets.new - data_sets << data_method - end - end - data_sets - end - - def append_test(suite, test_name) - test = @test_case.new(test_name) - yield(test) if block_given? - suite << test if test.valid? - end - - def collect_test_names - methods = @test_case.public_instance_methods(true) - super_test_case = @test_case.superclass - methods -= super_test_case.public_instance_methods(true) - methods |= @test_case.public_instance_methods(false) - method_names = methods.collect(&:to_s) - test_names = method_names.find_all do |method_name| - self.class.test_method?(@test_case, method_name) - end - __send__("sort_test_names_in_#{@test_case.test_order}_order", test_names) - end - - def sort_test_names_in_alphabetic_order(test_names) - test_names.sort - end - - def sort_test_names_in_random_order(test_names) - test_names.sort_by {rand(test_names.size)} - end - - def sort_test_names_in_defined_order(test_names) - added_method_names = @test_case.added_method_names - test_names.sort do |test1, test2| - test1_defined_order = added_method_names.index(test1) - test2_defined_order = added_method_names.index(test2) - if test1_defined_order and test2_defined_order - test1_defined_order <=> test2_defined_order - elsif test1_defined_order - 1 - elsif test2_defined_order - -1 - else - test1 <=> test2 - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/testcase.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/testcase.rb deleted file mode 100644 index 2755f121d..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/testcase.rb +++ /dev/null @@ -1,899 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: -# * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# * Copyright (c) 2008-2012 Kouhei Sutou -# License:: Ruby license. - -require 'test/unit/attribute' -require 'test/unit/fixture' -require 'test/unit/exception-handler' -require 'test/unit/assertions' -require 'test/unit/failure' -require 'test/unit/error' -require 'test/unit/pending' -require 'test/unit/omission' -require 'test/unit/notification' -require 'test/unit/priority' -require 'test/unit/data' -require 'test/unit/testsuite' -require 'test/unit/test-suite-creator' -require 'test/unit/assertion-failed-error' -require 'test/unit/auto-runner-loader' -require 'test/unit/util/backtracefilter' -require 'test/unit/util/output' -require 'test/unit/util/method-owner-finder' - -module Test - module Unit - - # Ties everything together. If you subclass and add your own - # test methods, it takes care of making them into tests and - # wrapping those tests into a suite. It also does the - # nitty-gritty of actually running an individual test and - # collecting its results into a Test::Unit::TestResult object. - # - # You can run two hooks before/after a TestCase run. - # - # Example: - # - # class TestMyClass < Test::Unit::TestCase - # class << self - # def startup - # ... - # end - # - # def shutdown - # ... - # end - # end - # - # def setup - # ... - # end - # - # def cleanup - # ... - # end - # - # def teardown - # ... - # end - # - # def test_my_method1 - # ... - # end - # - # def test_my_method2 - # ... - # end - # end - # - # Here is a call order: - # - # 1. startup - # 1. setup - # 1. test_my_method1 - # 1. cleanup - # 1. teardown - # 1. setup - # 1. test_my_method2 - # 1. cleanup - # 1. teardown - # 1. shutdown - # - # You can set an attribute to each test. - # - # Example: - # - # class TestMyClass < Test::Unit::TestCase - # attribute :speed, :fast - # def test_my_fast_method - # # You can get the attribute via `self[]` - # self[:speed] # => :fast - # ... - # end - # - # attribute :speed, :slow - # def test_my_slow_method - # self[:speed] # => :slow - # ... - # end - # end - class TestCase - include Attribute - include Fixture - include ExceptionHandler - include ErrorHandler - include FailureHandler - include TestCasePendingSupport - include TestCaseOmissionSupport - include TestCaseNotificationSupport - include Priority - include Data - include Assertions - include Util::BacktraceFilter - include Util::Output - - STARTED = name + "::STARTED" # :nodoc: - FINISHED = name + "::FINISHED" # :nodoc: - STARTED_OBJECT = name + "::STARTED::OBJECT" # :nodoc: - FINISHED_OBJECT = name + "::FINISHED::OBJECT" # :nodoc: - - DESCENDANTS = [] # :nodoc: - AVAILABLE_ORDERS = [:alphabetic, :random, :defined] # :nodoc: - - class << self - def inherited(sub_class) # :nodoc: - DESCENDANTS << sub_class - super - end - - def include(*modules, &block) # :nodoc: - super - modules.each do |mod| - mod.public_instance_methods(false).each do |method_name| - AutoRunnerLoader.check(self, method_name.to_s) - end - end - end - - @@added_method_names = {} - def method_added(name) # :nodoc: - super - added_method_names = (@@added_method_names[self] ||= {}) - stringified_name = name.to_s - if added_method_names.key?(stringified_name) - attribute(:redefined, {:backtrace => caller}, {}, stringified_name) - end - source_location = find_attribute(stringified_name, :source_location) - if source_location - path, line = source_location - elsif respond_to?(:caller_locations, true) - location = caller_locations(1, 1)[0] - path = location.absolute_path || location.path - line = location.lineno - else - # TODO: Remove me when Ruby 1.9 support is dropped - path, line, = caller[0].split(/:(\d+)/, 2) - line = line.to_i if line - end - location = { - :method_name => stringified_name, - :path => File.expand_path(path), - :line => line, - } - add_method_location(location) - added_method_names[stringified_name] = true - AutoRunnerLoader.check(self, stringified_name) - end - - def added_method_names # :nodoc: - (@@added_method_names[self] ||= {}).keys - end - - # Rolls up all of the test* methods in the fixture into - # one suite, creating a new instance of the fixture for - # each method. - def suite - suite_creator = TestSuiteCreator.new(self) - suite_creator.create - end - - # Called before every test case runs. Can be used - # to set up fixture information used in test case - # scope. - # - # Here is an example test case: - # - # class TestMyClass < Test::Unit::TestCase - # class << self - # def startup - # ... - # end - # end - # - # def setup - # ... - # end - # - # def test_my_class1 - # ... - # end - # - # def test_my_class2 - # ... - # end - # end - # - # Here is a call order: - # - # * startup - # * setup - # * test_my_class1 (or test_my_class2) - # * setup - # * test_my_class2 (or test_my_class1) - # - # Note that you should not assume test order. Tests - # should be worked in any order. - def startup - end - - # Called after every test case runs. Can be used to tear - # down fixture information used in test case scope. - # - # Here is an example test case: - # - # class TestMyClass < Test::Unit::TestCase - # class << self - # def shutdown - # ... - # end - # end - # - # def teardown - # ... - # end - # - # def test_my_class1 - # ... - # end - # - # def test_my_class2 - # ... - # end - # end - # - # Here is a call order: - # - # * test_my_class1 (or test_my_class2) - # * teardown - # * test_my_class2 (or test_my_class1) - # * teardown - # * shutdown - # - # Note that you should not assume test order. Tests - # should be worked in any order. - def shutdown - end - - @@test_orders = {} - - # Returns the current test order. This returns - # `:alphabetic` by default. - def test_order - ancestors.each do |ancestor| - order = @@test_orders[ancestor] - return order if order - end - AVAILABLE_ORDERS.first - end - - # Sets the current test order. - # - # Here are the available _order_: - # - # :alphabetic - # : Default. Tests are sorted in alphabetic order. - # - # :random - # : Tests are sorted in random order. - # - # :defined - # : Tests are sorted in defined order. - def test_order=(order) - @@test_orders[self] = order - end - - # Defines a test in declarative syntax or marks - # following method as a test method. - # - # In declarative syntax usage, the following two - # test definitions are the almost same: - # - # description "register user" - # def test_register_user - # ... - # end - # - # test "register user" do - # ... - # end - # - # In test method mark usage, the "my_test_method" is - # treated as a test method: - # - # test - # def my_test_method - # assert_equal("call me", ...) - # end - def test(*test_description_or_targets, &block) - if block_given? - test_description = test_description_or_targets.first - if test_description.nil? - raise ArgumentError, "test description is missing" - end - n_arguments = test_description_or_targets.size - if n_arguments > 1 - message = "wrong number of arguments (#{n_arguments} for 1)" - raise ArgumentError, message - end - method_name = "test: #{test_description}" - description(test_description, method_name) - attribute(:test, true, {}, method_name) - if block.respond_to?(:source_location) - attribute(:source_location, block.source_location, {}, method_name) - end - define_method(method_name, &block) - else - targets = test_description_or_targets - attribute(:test, true, {}, *targets) - targets.each do |target| - AutoRunnerLoader.check(self, target) - end - end - end - - # Describes a test. - # - # The following example associates "register a - # normal user" description with "test_register" - # test. - # - # description "register a normal user" - # def test_register - # ... - # end - def description(value, target=nil) - targets = [target].compact - attribute(:description, value, {}, *targets) - end - - # Defines a sub test case. - # - # This is a syntax sugar. The both of the following codes are - # the same in meaning: - # - # Standard: - # - # class TestParent < Test::Unit::TestCase - # class TestChild < self - # def test_in_child - # end - # end - # end - # - # Syntax sugar: - # - # class TestParent < Test::Unit::TestCase - # sub_test_case("TestChild") do - # def test_in_child - # end - # end - # end - # - # The difference of them are the following: - # - # * Test case created by {sub_test_case} is an anonymous class. - # So you can't refer the test case by name. - # * The class name of class style must follow - # constant naming rule in Ruby. But the name of test case - # created by {sub_test_case} doesn't need to follow the rule. - # For example, you can use a space in name such as "child test". - # - # @param name [String] The name of newly created sub test case. - # @yield - # The block is evaluated under the newly created sub test - # case class context. - # @return [Test::Unit::TestCase] Created sub test case class. - def sub_test_case(name, &block) - parent_test_case = self - sub_test_case = Class.new(self) do - singleton_class = class << self; self; end - singleton_class.__send__(:define_method, :name) do - [parent_test_case.name, name].compact.join("::") - end - end - sub_test_case.class_eval(&block) - sub_test_case - end - - # Checks whether a test that is matched the query is - # defined. - # - # @option query [String] :path (nil) - # the path where a test is defined in. - # @option query [Numeric] :line (nil) - # the line number where a test is defined at. - # @option query [String] :method_name (nil) - # the method name for a test. - def test_defined?(query) - locations = find_locations(query) - not locations.empty? - end - - def find_locations(query) - query_path = query[:path] - query_line = query[:line] - query_method_name = query[:method_name] - - available_locations = target_method_locations(query_path) - if query_line - available_locations = available_locations.sort_by do |location| - -location[:line] - end - available_location = available_locations.find do |location| - query_line >= location[:line] - end - return [] if available_location.nil? - return [] if available_location[:test_case] != self - available_locations = [available_location] - end - if query_method_name - available_location = available_locations.find do |location| - location[:test_case] == self and - query_method_name == location[:method_name] - end - return [] if available_location.nil? - available_locations = [available_location] - end - - available_locations - end - - private - # @private - @@method_locations = {} - # @private - @@method_location_mutex = Mutex.new - - # @private - def method_locations - @@method_locations[self] ||= [] - end - - # @private - def add_method_location(location) - @@method_location_mutex.synchronize do - method_locations << location - end - end - - # @private - def target_method_locations(path) - @@method_location_mutex.synchronize do - if path.nil? - self_location = method_locations.first - path = self_location[:path] if self_location - end - return [] if path.nil? - - target_locations = [] - @@method_locations.each do |test_case, locations| - locations.each do |location| - absolete_path = File.expand_path(path) - location_path = location[:path] - location_basename = File.basename(location_path) - if location_path == absolete_path or location_basename == path - target_locations << location.merge(:test_case => test_case) - end - end - end - target_locations - end - end - end - - attr_reader :method_name - - # Creates a new instance of the fixture for running the - # test represented by test_method_name. - def initialize(test_method_name) - @method_name = test_method_name - @internal_data = InternalData.new - end - - # Assigns test data to the test. It is used in internal. - def assign_test_data(label, data) # :nodoc: - @internal_data.assign_test_data(label, data) - end - - # Returns the test is valid test. It is used in internal. - def valid? # :nodoc: - return false unless respond_to?(@method_name) - test_method = method(@method_name) - unless @internal_data.have_test_data? - return false unless test_method.arity <= 0 - end - owner = Util::MethodOwnerFinder.find(self, @method_name) - if owner.class != Module and self.class != owner - return false - end - true - end - - # Runs the individual test method represented by this - # instance of the fixture, collecting statistics, failures - # and errors in result. - def run(result) - begin - @_result = result - @internal_data.test_started - yield(STARTED, name) - yield(STARTED_OBJECT, self) - processed_exception_in_setup = false - begin - catch do |tag| - run_setup do - begin - run_test - run_cleanup - add_pass - rescue Exception - @internal_data.interrupted - unless handle_exception($!) - processed_exception_in_setup = true - raise - end - throw(tag) - end - end - end - rescue Exception - if processed_exception_in_setup - raise - else - @internal_data.interrupted - raise unless handle_exception($!) - end - ensure - begin - run_teardown - rescue Exception - raise unless handle_exception($!) - end - end - @internal_data.test_finished - result.add_run - yield(FINISHED, name) - yield(FINISHED_OBJECT, self) - ensure - # @_result = nil # For test-spec's after_all :< - end - end - - # Called before every test method runs. Can be used - # to set up fixture information. - # - # You can add additional setup tasks by the following - # code: - # - # class TestMyClass < Test::Unit::TestCase - # def setup - # ... - # end - # - # setup - # def my_setup1 - # ... - # end - # - # setup do - # ... # setup callback1 - # end - # - # setup - # def my_setup2 - # ... - # end - # - # setup do - # ... # setup callback2 - # end - # - # def test_my_class - # ... - # end - # end - # - # Here is a call order: - # - # * setup - # * my_setup1 - # * setup callback1 - # * my_setup2 - # * setup callback2 - # * test_my_class - def setup - end - - # Called after every test method runs but the test - # method isn't marked as 'passed'. Can be used to - # clean up and/or verify tested condition. - # e.g. Can be used to verify mock. - # - # You can add additional cleanup tasks by the following - # code: - # - # class TestMyClass < Test::Unit::TestCase - # def cleanup - # ... - # end - # - # cleanup - # def my_cleanup1 - # ... - # end - # - # cleanup do - # ... # cleanup callback1 - # end - # - # cleanup - # def my_cleanup2 - # ... - # end - # - # cleanup do - # ... # cleanup callback2 - # end - # - # def test_my_class - # ... - # end - # end - # - # Here is a call order: - # - # * test_my_class - # * cleanup callback2 - # * my_cleanup2 - # * cleanup callback1 - # * my_cleanup1 - # * cleanup - def cleanup - end - - # Called after every test method runs. Can be used to tear - # down fixture information. - # - # You can add additional teardown tasks by the following - # code: - # - # class TestMyClass < Test::Unit::TestCase - # def teardown - # ... - # end - # - # teardown - # def my_teardown1 - # ... - # end - # - # teardown do - # ... # teardown callback1 - # end - # - # teardown - # def my_teardown2 - # ... - # end - # - # teardown do - # ... # teardown callback2 - # end - # - # def test_my_class - # ... - # end - # end - # - # Here is a call order: - # - # * test_my_class - # * teardown callback2 - # * my_teardown2 - # * teardown callback1 - # * my_teardown1 - # * teardown - def teardown - end - - def default_test - flunk("No tests were specified") - end - - def size - 1 - end - - # Returns a label of test data for the test. If the - # test isn't associated with any test data, it returns - # `nil`. - def data_label - @internal_data.test_data_label - end - - # Returns test data for the test. If the test isn't associated - # with any test data, it returns `nil`. - def data - @internal_data.test_data - end - - # Returns a human-readable name for the specific test that - # this instance of TestCase represents. - def name - "#{local_name}(#{self.class.name})" - end - - # Returns a human-readable name for the specific test that this - # instance of TestCase represents. - # - # `#local_name` doesn't include class name. `#name` includes - # class name. - def local_name - if @internal_data.have_test_data? - "#{@method_name}[#{data_label}]" - else - @method_name.to_s - end - end - - # Returns a description for the test. A description - # will be associated by Test::Unit::TestCase.test or - # Test::Unit::TestCase.description. - # - # Returns a name for the test for no description test. - def description - self[:description] || name - end - - # Overridden to return #name. - def to_s - name - end - - # It's handy to be able to compare TestCase instances. - def ==(other) - return false unless other.kind_of?(self.class) - return false unless @method_name == other.method_name - return false unless data_label == other.data_label - self.class == other.class - end - - # Returns a Time at the test was started. - def start_time - @internal_data.start_time - end - - # Returns elapsed time for the test was ran. - def elapsed_time - @internal_data.elapsed_time - end - - # Returns whether the test is interrupted. - def interrupted? - @internal_data.interrupted? - end - - # Returns whether this individual test passed or - # not. Primarily for use in teardown so that artifacts - # can be left behind if the test fails. - def passed? - @internal_data.passed? - end - - # Notify that a problem is occurred in the test. It means that - # the test is a failed test. If any failed tests exist in test - # suites, the test process exits with failure exit status. - # - # This is a public API for developers who extend test-unit. - # - # @return [void] - def problem_occurred - @internal_data.problem_occurred - end - - # Notify that the test is passed. Normally, it is not needed - # because #run calls it automatically. If you want to override - # #run, it is not a good idea. Please contact test-unit - # developers. We will help you without your custom #run. For - # example, we may add a new hook in #run. - # - # This is a public API for developers who extend test-unit. - # - # @return [void] - def add_pass - current_result.add_pass - end - - private - def current_result - @_result - end - - def run_test - signature = "#{self.class}\##{@method_name}" - redefined_info = self[:redefined] - if redefined_info - notify("<#{signature}> was redefined", - :backtrace => redefined_info[:backtrace]) - end - if @internal_data.have_test_data? - test_method = method(@method_name) - arity = test_method.arity - if arity.zero? - __send__(@method_name) - else - __send__(@method_name, @internal_data.test_data) - end - else - __send__(@method_name) - end - end - - def handle_exception(exception) - self.class.exception_handlers.each do |handler| - if handler.respond_to?(:call) - handled = handler.call(self, exception) - else - handled = __send__(handler, exception) - end - return true if handled - end - false - end - - def add_assertion - current_result.add_assertion - end - - class InternalData - attr_reader :start_time, :elapsed_time - attr_reader :test_data_label, :test_data - def initialize - @start_time = nil - @elapsed_time = nil - @passed = true - @interrupted = false - @test_data_label = nil - @test_data = nil - end - - def passed? - @passed - end - - def interrupted? - @interrupted - end - - def assign_test_data(label, data) - @test_data_label = label - @test_data = data - end - - def have_test_data? - not @test_data_label.nil? - end - - def test_started - @start_time = Time.now - end - - def test_finished - @elapsed_time = Time.now - @start_time - end - - def problem_occurred - @passed = false - end - - def interrupted - @interrupted = true - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/testresult.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/testresult.rb deleted file mode 100644 index 5afb3be51..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/testresult.rb +++ /dev/null @@ -1,132 +0,0 @@ -#-- -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/util/observable' -require 'test/unit/failure' -require 'test/unit/error' -require 'test/unit/omission' -require 'test/unit/pending' -require 'test/unit/notification' - -module Test - module Unit - module NullResultContainerInitializer - private - def initialize_containers - end - end - - # Collects Test::Unit::Failure and Test::Unit::Error so that - # they can be displayed to the user. To this end, observers - # can be added to it, allowing the dynamic updating of, say, a - # UI. - class TestResult - include Util::Observable - include NullResultContainerInitializer - include TestResultFailureSupport - include TestResultErrorSupport - include TestResultPendingSupport - include TestResultOmissionSupport - include TestResultNotificationSupport - - FINISHED = name + "::FINISHED" - CHANGED = name + "::CHANGED" - PASS_ASSERTION = name + "::PASS_ASSERTION" - FAULT = name + "::FAULT" - - attr_reader :run_count, :pass_count, :assertion_count, :faults - - attr_accessor :stop_tag - - # Constructs a new, empty TestResult. - def initialize - @run_count, @pass_count, @assertion_count = 0, 0, 0 - @summary_generators = [] - @problem_checkers = [] - @faults = [] - @stop_tag = nil - initialize_containers - end - - # Records a test run. - def add_run - @run_count += 1 - notify_listeners(FINISHED, self) - notify_changed - end - - def add_pass - @pass_count += 1 - end - - # Records an individual assertion. - def add_assertion - @assertion_count += 1 - notify_listeners(PASS_ASSERTION, self) - notify_changed - end - - # Returns a string contain the recorded runs, assertions, - # failures and errors in this TestResult. - def summary - ["#{run_count} tests", - "#{assertion_count} assertions", - *@summary_generators.collect {|generator| __send__(generator)}].join(", ") - end - - # Returnes a string that shows result status. - def status - if passed? - if pending_count > 0 - "pending" - elsif omission_count > 0 - "omission" - elsif notification_count > 0 - "notification" - else - "pass" - end - elsif error_count > 0 - "error" - elsif failure_count > 0 - "failure" - end - end - - def stop - throw @stop_tag - end - - def to_s - summary - end - - # Returns whether or not this TestResult represents - # successful completion. - def passed? - @problem_checkers.all? {|checker| not __send__(checker)} - end - - def pass_percentage - n_tests = @run_count - omission_count - if n_tests.zero? - 0 - else - 100.0 * (@pass_count / n_tests.to_f) - end - end - - private - def notify_changed - notify_listeners(CHANGED, self) - end - - def notify_fault(fault) - @faults << fault - notify_listeners(FAULT, fault) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/testsuite.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/testsuite.rb deleted file mode 100644 index 495fc341c..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/testsuite.rb +++ /dev/null @@ -1,175 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# Copyright:: Copyright (c) 2008-2011 Kouhei Sutou. All rights reserved. -# License:: Ruby license. - -require 'test/unit/error' - -module Test - module Unit - - # A collection of tests which can be #run. - # - # Note: It is easy to confuse a TestSuite instance with - # something that has a static suite method; I know because _I_ - # have trouble keeping them straight. Think of something that - # has a suite method as simply providing a way to get a - # meaningful TestSuite instance. - class TestSuite - attr_reader :name, :tests, :test_case, :start_time, :elapsed_time - - # Test suite that has higher priority is ran prior to - # test suites that have lower priority. - attr_accessor :priority - - STARTED = name + "::STARTED" - STARTED_OBJECT = name + "::STARTED::OBJECT" - FINISHED = name + "::FINISHED" - FINISHED_OBJECT = name + "::FINISHED::OBJECT" - - # Creates a new TestSuite with the given name. - def initialize(name="Unnamed TestSuite", test_case=nil) - @name = name - @tests = [] - @test_case = test_case - @n_tests = 0 - @priority = 0 - @start_time = nil - @elapsed_time = nil - @passed = true - end - - # Runs the tests and/or suites contained in this - # TestSuite. - def run(result, &progress_block) - @start_time = Time.now - yield(STARTED, name) - yield(STARTED_OBJECT, self) - run_startup(result) - while test = @tests.shift - @n_tests += test.size - run_test(test, result, &progress_block) - @passed = false unless test.passed? - end - ensure - begin - run_shutdown(result) - ensure - @elapsed_time = Time.now - @start_time - yield(FINISHED, name) - yield(FINISHED_OBJECT, self) - end - end - - # Adds the test to the suite. - def <<(test) - @tests << test - self - end - - def delete(test) - @tests.delete(test) - end - - def delete_tests(tests) - @tests -= tests - end - - # Retuns the rolled up number of tests in this suite; - # i.e. if the suite contains other suites, it counts the - # tests within those suites, not the suites themselves. - def size - total_size = @n_tests - @tests.each { |test| total_size += test.size } - total_size - end - - def empty? - size.zero? - end - - # Overridden to return the name given the suite at - # creation. - def to_s - @name - end - - # It's handy to be able to compare TestSuite instances. - def ==(other) - return false unless(other.kind_of?(self.class)) - return false unless(@name == other.name) - @tests == other.tests - end - - def passed? - @passed - end - - private - def run_startup(result) - return if @test_case.nil? or !@test_case.respond_to?(:startup) - begin - @test_case.startup - rescue Exception - raise unless handle_exception($!, result) - end - end - - def run_test(test, result) - finished_is_yielded = false - finished_object_is_yielded = false - previous_event_name = nil - test.run(result) do |event_name, *args| - case previous_event_name - when Test::Unit::TestCase::STARTED - if event_name != Test::Unit::TestCase::STARTED_OBJECT - yield(Test::Unit::TestCase::STARTED_OBJECT, test) - end - when Test::Unit::TestCase::FINISHED - if event_name != Test::Unit::TestCase::FINISHED_OBJECT - yield(Test::Unit::TestCase::FINISHED_OBJECT, test) - end - finished_object_is_yielded = true - end - - case event_name - when Test::Unit::TestCase::STARTED - finished_is_yielded = false - finished_object_is_yielded = false - when Test::Unit::TestCase::FINISHED - finished_is_yielded = true - end - - previous_event_name = event_name - yield(event_name, *args) - end - - if finished_is_yielded and not finished_object_is_yielded - yield(Test::Unit::TestCase::FINISHED_OBJECT, test) - end - end - - def run_shutdown(result) - return if @test_case.nil? or !@test_case.respond_to?(:shutdown) - begin - @test_case.shutdown - rescue Exception - raise unless handle_exception($!, result) - end - end - - def handle_exception(exception, result) - case exception - when *ErrorHandler::PASS_THROUGH_EXCEPTIONS - false - else - result.add_error(Error.new(@test_case.name, exception)) - @passed = false - true - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/outputlevel.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/outputlevel.rb deleted file mode 100644 index de3ccfd83..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/outputlevel.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Test - module Unit - module UI - module Console - module OutputLevel - SILENT = 0 - PROGRESS_ONLY = 1 - IMPORTANT_FAULTS_ONLY = 2 - NORMAL = 3 - VERBOSE = 4 - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/testrunner.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/testrunner.rb deleted file mode 100644 index 78bb330c0..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/console/testrunner.rb +++ /dev/null @@ -1,750 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: -# * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# * Copyright (c) 2008-2017 Kouhei Sutou -# License:: Ruby license. - -begin - require 'io/console' -rescue LoadError -end - -require 'test/unit/color-scheme' -require 'test/unit/code-snippet-fetcher' -require 'test/unit/fault-location-detector' -require 'test/unit/diff' -require 'test/unit/ui/testrunner' -require 'test/unit/ui/testrunnermediator' -require 'test/unit/ui/console/outputlevel' - -module Test - module Unit - module UI - module Console - - # Runs a Test::Unit::TestSuite on the console. - class TestRunner < UI::TestRunner - include OutputLevel - - # Creates a new TestRunner for running the passed - # suite. If quiet_mode is true, the output while - # running is limited to progress dots, errors and - # failures, and the final result. io specifies - # where runner output should go to; defaults to - # STDOUT. - def initialize(suite, options={}) - super - @output_level = @options[:output_level] || NORMAL - @output = @options[:output] || STDOUT - @use_color = @options[:use_color] - @use_color = guess_color_availability if @use_color.nil? - @color_scheme = @options[:color_scheme] || ColorScheme.default - @reset_color = Color.new("reset") - @progress_row = 0 - @progress_row_max = @options[:progress_row_max] - @progress_row_max ||= guess_progress_row_max - @show_detail_immediately = @options[:show_detail_immediately] - @show_detail_immediately = true if @show_detail_immediately.nil? - @reverse_output = @options[:reverse_output] - @reverse_output = @output.tty? if @reverse_output.nil? - @already_outputted = false - @indent = 0 - @top_level = true - @current_output_level = NORMAL - @faults = [] - @code_snippet_fetcher = CodeSnippetFetcher.new - @test_suites = [] - end - - private - def change_output_level(level) - old_output_level = @current_output_level - @current_output_level = level - yield - @current_output_level = old_output_level - end - - def setup_mediator - super - output_setup_end - end - - def output_setup_end - suite_name = @suite.to_s - suite_name = @suite.name if @suite.kind_of?(Module) - output("Loaded suite #{suite_name}") - end - - def attach_to_mediator - @mediator.add_listener(TestResult::FAULT, - &method(:add_fault)) - @mediator.add_listener(TestRunnerMediator::STARTED, - &method(:started)) - @mediator.add_listener(TestRunnerMediator::FINISHED, - &method(:finished)) - @mediator.add_listener(TestCase::STARTED_OBJECT, - &method(:test_started)) - @mediator.add_listener(TestCase::FINISHED_OBJECT, - &method(:test_finished)) - @mediator.add_listener(TestSuite::STARTED_OBJECT, - &method(:test_suite_started)) - @mediator.add_listener(TestSuite::FINISHED_OBJECT, - &method(:test_suite_finished)) - end - - def add_fault(fault) - @faults << fault - output_progress(fault.single_character_display, - fault_marker_color(fault)) - output_progress_in_detail(fault) if @show_detail_immediately - @already_outputted = true if fault.critical? - end - - def started(result) - @result = result - output_started - end - - def output_started - output("Started") - end - - def finished(elapsed_time) - unless @show_detail_immediately - nl if output?(NORMAL) and !output?(VERBOSE) - output_faults - end - nl(PROGRESS_ONLY) - change_output_level(IMPORTANT_FAULTS_ONLY) do - output_statistics(elapsed_time) - end - end - - def output_faults - categorized_faults = categorize_faults - change_output_level(IMPORTANT_FAULTS_ONLY) do - output_faults_in_detail(categorized_faults[:need_detail_faults]) - end - output_faults_in_short("Omissions", Omission, - categorized_faults[:omissions]) - output_faults_in_short("Notifications", Notification, - categorized_faults[:notifications]) - end - - def max_digit(max_number) - (Math.log10(max_number) + 1).truncate - end - - def output_faults_in_detail(faults) - return if faults.nil? - digit = max_digit(faults.size) - faults.each_with_index do |fault, index| - nl - output_single("%#{digit}d) " % (index + 1)) - output_fault_in_detail(fault) - end - end - - def output_faults_in_short(label, fault_class, faults) - return if faults.nil? - digit = max_digit(faults.size) - nl - output_single(label, fault_class_color(fault_class)) - output(":") - faults.each_with_index do |fault, index| - output_single("%#{digit}d) " % (index + 1)) - output_fault_in_short(fault) - end - end - - def categorize_faults - faults = {} - @faults.each do |fault| - category = categorize_fault(fault) - faults[category] ||= [] - faults[category] << fault - end - faults - end - - def categorize_fault(fault) - case fault - when Omission - :omissions - when Notification - :notifications - else - :need_detail_faults - end - end - - def output_fault_in_detail(fault) - if fault.is_a?(Failure) and - fault.inspected_expected and - fault.inspected_actual - if @reverse_output - output_fault_backtrace(fault) - output_failure_message(fault) - output_single("#{fault.label}: ") - output(fault.test_name, fault_color(fault)) - else - output_single("#{fault.label}: ") - output(fault.test_name, fault_color(fault)) - output_fault_backtrace(fault) - output_failure_message(fault) - end - else - if @reverse_output - output_fault_backtrace(fault) - output_single("#{fault.label}: ") - output_single(fault.test_name, fault_color(fault)) - output_fault_message(fault) - else - output_single("#{fault.label}: ") - output_single(fault.test_name, fault_color(fault)) - output_fault_message(fault) - output_fault_backtrace(fault) - end - end - end - - def output_fault_message(fault) - message = fault.message - return if message.nil? - - if message.include?("\n") - output(":") - message.each_line do |line| - output(" #{line.chomp}") - end - else - output(": #{message}") - end - end - - def output_fault_backtrace(fault) - detector = FaultLocationDetector.new(fault, @code_snippet_fetcher) - backtrace = fault.location - # workaround for test-spec. :< - # see also GitHub:#22 - backtrace ||= [] - - code_snippet_backtrace_index = nil - code_snippet_lines = nil - backtrace.each_with_index do |entry, i| - next unless detector.target?(entry) - file, line_number, = detector.split_backtrace_entry(entry) - lines = fetch_code_snippet(file, line_number) - unless lines.empty? - code_snippet_backtrace_index = i - code_snippet_lines = lines - break - end - end - - if @reverse_output - backtrace.each_with_index.reverse_each do |entry, i| - if i == code_snippet_backtrace_index - output_code_snippet(code_snippet_lines, fault_color(fault)) - end - output(entry) - end - else - backtrace.each_with_index do |entry, i| - output(entry) - if i == code_snippet_backtrace_index - output_code_snippet(code_snippet_lines, fault_color(fault)) - end - end - end - end - - def fetch_code_snippet(file, line_number) - @code_snippet_fetcher.fetch(file, line_number) - end - - def output_code_snippet(lines, target_line_color=nil) - max_n = lines.collect {|n, line, attributes| n}.max - digits = (Math.log10(max_n) + 1).truncate - lines.each do |n, line, attributes| - if attributes[:target_line?] - line_color = target_line_color - current_line_mark = "=>" - else - line_color = nil - current_line_mark = "" - end - output(" %2s %*d: %s" % [current_line_mark, digits, n, line], - line_color) - end - end - - def output_failure_message(failure) - if failure.expected.respond_to?(:encoding) and - failure.actual.respond_to?(:encoding) and - failure.expected.encoding != failure.actual.encoding - need_encoding = true - else - need_encoding = false - end - output(failure.user_message) if failure.user_message - output_single("<") - output_single(failure.inspected_expected, color("pass")) - output_single(">") - if need_encoding - output_single("(") - output_single(failure.expected.encoding.name, color("pass")) - output_single(")") - end - output(" expected but was") - output_single("<") - output_single(failure.inspected_actual, color("failure")) - output_single(">") - if need_encoding - output_single("(") - output_single(failure.actual.encoding.name, color("failure")) - output_single(")") - end - output("") - from, to = prepare_for_diff(failure.expected, failure.actual) - if from and to - if need_encoding - unless from.valid_encoding? - from = from.dup.force_encoding("ASCII-8BIT") - end - unless to.valid_encoding? - to = to.dup.force_encoding("ASCII-8BIT") - end - end - from_lines = from.split(/\r?\n/) - to_lines = to.split(/\r?\n/) - if need_encoding - from_lines << "" - to_lines << "" - from_lines << "Encoding: #{failure.expected.encoding.name}" - to_lines << "Encoding: #{failure.actual.encoding.name}" - end - differ = ColorizedReadableDiffer.new(from_lines, to_lines, self) - if differ.need_diff? - output("") - output("diff:") - differ.diff - end - end - end - - def output_fault_in_short(fault) - if @reverse_output - output(fault.location.first) - output_single("#{fault.label}: ") - output_single(fault.message, fault_color(fault)) - output(" [#{fault.test_name}]") - else - output_single("#{fault.label}: ") - output_single(fault.message, fault_color(fault)) - output(" [#{fault.test_name}]") - output(fault.location.first) - end - end - - def format_fault(fault) - fault.long_display - end - - def output_statistics(elapsed_time) - output("Finished in #{elapsed_time} seconds.") - output_summary_marker - output(@result) - output("%g%% passed" % @result.pass_percentage) - unless elapsed_time.zero? - output_summary_marker - test_throughput = @result.run_count / elapsed_time - assertion_throughput = @result.assertion_count / elapsed_time - throughput = [ - "%.2f tests/s" % test_throughput, - "%.2f assertions/s" % assertion_throughput, - ] - output(throughput.join(", ")) - end - end - - def output_summary_marker - if @progress_row_max > 0 - output("-" * @progress_row_max, summary_marker_color) - else - nl - end - end - - def test_started(test) - return unless output?(VERBOSE) - - tab_width = 8 - name = test.local_name - separator = ":" - left_used = indent.size + name.size + separator.size - right_space = tab_width * 2 - left_space = @progress_row_max - right_space - if (left_used % tab_width).zero? - left_space -= left_used - n_tabs = 0 - else - left_space -= ((left_used / tab_width) + 1) * tab_width - n_tabs = 1 - end - n_tabs += [left_space, 0].max / tab_width - tab_stop = "\t" * n_tabs - output_single("#{indent}#{name}#{separator}#{tab_stop}", - nil, - VERBOSE) - @test_start = Time.now - end - - def test_finished(test) - unless @already_outputted - output_progress(".", color("pass-marker")) - end - @already_outputted = false - - return unless output?(VERBOSE) - - output(": (%f)" % (Time.now - @test_start), nil, VERBOSE) - end - - def suite_name(prefix, suite) - name = suite.name - if name.nil? - "(anonymous)" - else - name.sub(/\A#{Regexp.escape(prefix)}/, "") - end - end - - def test_suite_started(suite) - last_test_suite = @test_suites.last - @test_suites << suite - if @top_level - @top_level = false - return - end - - output_single(indent, nil, VERBOSE) - if suite.test_case.nil? - _color = color("suite") - else - _color = color("case") - end - prefix = "#{last_test_suite.name}::" - output_single(suite_name(prefix, suite), _color, VERBOSE) - output(": ", nil, VERBOSE) - @indent += 2 - end - - def test_suite_finished(suite) - @indent -= 2 - @test_suites.pop - end - - def indent - if output?(VERBOSE) - " " * @indent - else - "" - end - end - - def nl(level=nil) - output("", nil, level) - end - - def output(something, color=nil, level=nil) - return unless output?(level) - output_single(something, color, level) - @output.puts - end - - def output_single(something, color=nil, level=nil) - return false unless output?(level) - if @use_color and color - something = "%s%s%s" % [color.escape_sequence, - something, - @reset_color.escape_sequence] - end - @output.write(something) - @output.flush - true - end - - def output_progress(mark, color=nil) - if output_single(mark, color, PROGRESS_ONLY) - return unless @progress_row_max > 0 - @progress_row += mark.size - if @progress_row >= @progress_row_max - nl unless @output_level == VERBOSE - @progress_row = 0 - end - end - end - - def output_progress_in_detail_marker(fault) - if @progress_row_max > 0 - output("=" * @progress_row_max) - else - nl - end - end - - def output_progress_in_detail(fault) - return if @output_level == SILENT - nl - output_progress_in_detail_marker(fault) - if categorize_fault(fault) == :need_detail_faults - output_fault_in_detail(fault) - else - output_fault_in_short(fault) - end - output_progress_in_detail_marker(fault) - @progress_row = 0 - end - - def output?(level) - (level || @current_output_level) <= @output_level - end - - def color(name) - _color = @color_scheme[name] - _color ||= @color_scheme["success"] if name == "pass" - _color ||= ColorScheme.default[name] - _color - end - - def fault_class_color_name(fault_class) - fault_class.name.split(/::/).last.downcase - end - - def fault_class_color(fault_class) - color(fault_class_color_name(fault_class)) - end - - def fault_color(fault) - fault_class_color(fault.class) - end - - def fault_marker_color(fault) - color("#{fault_class_color_name(fault.class)}-marker") - end - - def summary_marker_color - color("#{@result.status}-marker") - end - - def guess_color_availability - return false unless @output.tty? - return true if windows? and ruby_2_0_or_later? - case ENV["TERM"] - when /(?:term|screen)(?:-(?:256)?color)?\z/ - true - when /\Arxvt/ - true - else - return true if ENV["EMACS"] == "t" - false - end - end - - def windows? - /mswin|mingw/ === RUBY_PLATFORM - end - - def ruby_2_0_or_later? - RUBY_VERSION >= "2.0.0" - end - - def guess_progress_row_max - term_width = guess_term_width - if term_width.zero? - if ENV["EMACS"] == "t" - -1 - else - 79 - end - else - term_width - end - end - - def guess_term_width - guess_term_width_from_io || guess_term_width_from_env || 0 - end - - def guess_term_width_from_io - if @output.respond_to?(:winsize) - begin - @output.winsize[1] - rescue SystemCallError - nil - end - else - nil - end - end - - def guess_term_width_from_env - env = ENV["COLUMNS"] || ENV["TERM_WIDTH"] - return nil if env.nil? - - begin - Integer(env) - rescue ArgumentError - nil - end - end - end - - class ColorizedReadableDiffer < Diff::ReadableDiffer - def initialize(from, to, runner) - @runner = runner - super(from, to) - end - - def need_diff?(options={}) - return false if one_line_all_change? - operations.each do |tag,| - return true if [:replace, :equal].include?(tag) - end - false - end - - private - def one_line_all_change? - return false if operations.size != 1 - - tag, from_start, from_end, to_start, to_end = operations.first - return false if tag != :replace - return false if [from_start, from_end] != [0, 1] - return false if [from_start, from_end] != [to_start, to_end] - - _, _, _line_operations = line_operations(@from.first, @to.first) - _line_operations.size == 1 - end - - def output_single(something, color=nil) - @runner.__send__(:output_single, something, color) - end - - def output(something, color=nil) - @runner.__send__(:output, something, color) - end - - def color(name) - @runner.__send__(:color, name) - end - - def cut_off_ratio - 0 - end - - def default_ratio - 0 - end - - def tag(mark, color_name, contents) - _color = color(color_name) - contents.each do |content| - output_single(mark, _color) - output_single(" ") - output(content) - end - end - - def tag_deleted(contents) - tag("-", "diff-deleted-tag", contents) - end - - def tag_inserted(contents) - tag("+", "diff-inserted-tag", contents) - end - - def tag_equal(contents) - tag(" ", "normal", contents) - end - - def tag_difference(contents) - tag("?", "diff-difference-tag", contents) - end - - def diff_line(from_line, to_line) - to_operations = [] - from_line, to_line, _operations = line_operations(from_line, to_line) - - no_replace = true - _operations.each do |tag,| - if tag == :replace - no_replace = false - break - end - end - - output_single("?", color("diff-difference-tag")) - output_single(" ") - _operations.each do |tag, from_start, from_end, to_start, to_end| - from_width = compute_width(from_line, from_start, from_end) - to_width = compute_width(to_line, to_start, to_end) - case tag - when :replace - output_single(from_line[from_start...from_end], - color("diff-deleted")) - if (from_width < to_width) - output_single(" " * (to_width - from_width)) - end - to_operations << Proc.new do - output_single(to_line[to_start...to_end], - color("diff-inserted")) - if (to_width < from_width) - output_single(" " * (from_width - to_width)) - end - end - when :delete - output_single(from_line[from_start...from_end], - color("diff-deleted")) - unless no_replace - to_operations << Proc.new {output_single(" " * from_width)} - end - when :insert - if no_replace - output_single(to_line[to_start...to_end], - color("diff-inserted")) - else - output_single(" " * to_width) - to_operations << Proc.new do - output_single(to_line[to_start...to_end], - color("diff-inserted")) - end - end - when :equal - output_single(from_line[from_start...from_end]) - unless no_replace - to_operations << Proc.new {output_single(" " * to_width)} - end - else - raise "unknown tag: #{tag}" - end - end - output("") - - unless to_operations.empty? - output_single("?", color("diff-difference-tag")) - output_single(" ") - to_operations.each do |operation| - operation.call - end - output("") - end - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/emacs/testrunner.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/emacs/testrunner.rb deleted file mode 100644 index c3aad4295..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/emacs/testrunner.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'test/unit/ui/console/testrunner' - -module Test - module Unit - module UI - module Emacs - class TestRunner < Console::TestRunner - private - def output_setup_end - end - - def output_started - end - - def format_fault(fault) - return super unless fault.respond_to?(:label) - format_method_name = "format_fault_#{fault.label.downcase}" - if respond_to?(format_method_name, true) - __send__(format_method_name, fault) - else - super - end - end - - def format_fault_failure(failure) - if failure.location.size == 1 - location = failure.location[0] - location_display = location.sub(/\A(.+:\d+).*/, ' [\\1]') - else - location_display = "\n" + failure.location.join("\n") - end - result = "#{failure.label}:\n" - result += "#{failure.test_name}#{location_display}:\n" - result += failure.message - result - end - - def format_fault_error(error) - result = "#{error.label}:\n" - result += "#{error.test_name}:\n" - result += "#{error.message}\n" - result += error.backtrace.join("\n") - result - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunner.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunner.rb deleted file mode 100644 index 975cad9a2..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunner.rb +++ /dev/null @@ -1,53 +0,0 @@ -require 'test/unit/ui/testrunnerutilities' - -module Test - module Unit - module UI - class TestRunner - extend TestRunnerUtilities - - attr_reader :listeners - def initialize(suite, options={}) - if suite.respond_to?(:suite) - @suite = suite.suite - else - @suite = suite - end - @options = options - @listeners = @options[:listeners] || [] - end - - # Begins the test run. - def start - setup_mediator - attach_to_mediator - attach_listeners - start_mediator - end - - private - def setup_mediator - @mediator = TestRunnerMediator.new(@suite) - end - - def attach_listeners - @listeners.each do |listener| - listener.attach_to_mediator(@mediator) - end - end - - def start_mediator - @mediator.run - end - - def diff_target_string?(string) - Assertions::AssertionMessage.diff_target_string?(string) - end - - def prepare_for_diff(from, to) - Assertions::AssertionMessage.prepare_for_diff(from, to) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnermediator.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnermediator.rb deleted file mode 100644 index 21a1d7ea5..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnermediator.rb +++ /dev/null @@ -1,114 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/util/observable' -require 'test/unit/testresult' - -module Test - module Unit - module UI - - # Provides an interface to write any given UI against, - # hopefully making it easy to write new UIs. - class TestRunnerMediator - RESET = name + "::RESET" - STARTED = name + "::STARTED" - FINISHED = name + "::FINISHED" - - include Util::Observable - - # Creates a new TestRunnerMediator initialized to run - # the passed suite. - def initialize(suite) - @suite = suite - end - - # Runs the suite the TestRunnerMediator was created - # with. - def run - AutoRunner.need_auto_run = false - - result = create_result - - Test::Unit.run_at_start_hooks - start_time = Time.now - begin - catch do |stop_tag| - result.stop_tag = stop_tag - with_listener(result) do - notify_listeners(RESET, @suite.size) - notify_listeners(STARTED, result) - - run_suite(result) - end - end - ensure - elapsed_time = Time.now - start_time - notify_listeners(FINISHED, elapsed_time) - end - Test::Unit.run_at_exit_hooks - - result - end - - # Just for backward compatibility for NetBeans. - # NetBeans should not use monkey patching. NetBeans - # should use runner change public API. - # - # See GitHub#38 - # https://github.com/test-unit/test-unit/issues/38 - def run_suite(result=nil) - if result.nil? - run - else - @suite.run(result) do |channel, value| - notify_listeners(channel, value) - end - end - end - - private - # A factory method to create the result the mediator - # should run with. Can be overridden by subclasses if - # one wants to use a different result. - def create_result - TestResult.new - end - - def measure_time - begin_time = Time.now - yield - Time.now - begin_time - end - - def with_listener(result) - finished_listener = result.add_listener(TestResult::FINISHED) do |*args| - notify_listeners(TestResult::FINISHED, *args) - end - changed_listener = result.add_listener(TestResult::CHANGED) do |*args| - notify_listeners(TestResult::CHANGED, *args) - end - pass_assertion_listener = result.add_listener(TestResult::PASS_ASSERTION) do |*args| - notify_listeners(TestResult::PASS_ASSERTION, *args) - end - fault_listener = result.add_listener(TestResult::FAULT) do |*args| - notify_listeners(TestResult::FAULT, *args) - end - - begin - yield - ensure - result.remove_listener(TestResult::FAULT, fault_listener) - result.remove_listener(TestResult::CHANGED, changed_listener) - result.remove_listener(TestResult::FINISHED, finished_listener) - result.remove_listener(TestResult::PASS_ASSERTION, - pass_assertion_listener) - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnerutilities.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnerutilities.rb deleted file mode 100644 index 33d80fb10..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/testrunnerutilities.rb +++ /dev/null @@ -1,41 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -module Test - module Unit - module UI - - # Provides some utilities common to most, if not all, - # TestRunners. - # - #-- - # - # Perhaps there ought to be a TestRunner superclass? There - # seems to be a decent amount of shared code between test - # runners. - - module TestRunnerUtilities - - # Creates a new TestRunner and runs the suite. - def run(suite, options={}) - return new(suite, options).start - end - - # Takes care of the ARGV parsing and suite - # determination necessary for running one of the - # TestRunners from the command line. - def start_command_line_test - if ARGV.empty? - puts "You should supply the name of a test suite file to the runner" - exit - end - require ARGV[0].gsub(/.+::/, '') - new(eval(ARGV[0])).start - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/xml/testrunner.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/xml/testrunner.rb deleted file mode 100644 index ce8acc042..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/ui/xml/testrunner.rb +++ /dev/null @@ -1,224 +0,0 @@ -#-- -# -# Author:: Kouhei Sutou -# Copyright:: -# * Copyright (c) 2011 Kouhei Sutou -# License:: Ruby license. - -require 'erb' -require 'time' -require 'test/unit/ui/testrunner' -require 'test/unit/ui/testrunnermediator' - -module Test - module Unit - module UI - module XML - - # Runs a Test::Unit::TestSuite and outputs XML. - class TestRunner < UI::TestRunner - include ERB::Util - - # Creates a new TestRunner for running the passed - # suite. :output option specifies where runner - # output should go to; defaults to STDOUT. - def initialize(suite, options={}) - super - @output = @options[:output] || STDOUT - if @options[:output_file_descriptor] - @output = IO.new(@options[:output_file_descriptor], "w") - end - @already_outputted = false - @indent = 0 - @top_level = true - @current_test = nil - @current_test_suite = nil - @already_outputted = false - end - - private - def attach_to_mediator - @mediator.add_listener(TestResult::PASS_ASSERTION, - &method(:result_pass_assertion)) - @mediator.add_listener(TestResult::FAULT, - &method(:result_fault)) - @mediator.add_listener(TestRunnerMediator::STARTED, - &method(:started)) - @mediator.add_listener(TestRunnerMediator::FINISHED, - &method(:finished)) - @mediator.add_listener(TestCase::STARTED_OBJECT, - &method(:test_started)) - @mediator.add_listener(TestCase::FINISHED_OBJECT, - &method(:test_finished)) - @mediator.add_listener(TestSuite::STARTED_OBJECT, - &method(:test_suite_started)) - @mediator.add_listener(TestSuite::FINISHED_OBJECT, - &method(:test_suite_finished)) - end - - def result_pass_assertion(result) - open_tag("pass-assertion") do - output_test(@current_test) - end - end - - def result_fault(fault) - open_tag("test-result") do - open_tag("result") do - output_test_suite(@current_test_suite) - output_test(@current_test) - open_tag("backtrace") do - fault.location.each do |entry| - file, line, info = entry.split(/:/, 3) - open_tag("entry") do - add_content("file", file) - add_content("line", line) - add_content("info", info) - end - end - end - if fault.respond_to?(:expected) - add_content("expected", fault.expected) - end - if fault.respond_to?(:actual) - add_content("actual", fault.actual) - end - add_content("detail", fault.message) - add_content("status", fault.label.downcase) - end - end - @already_outputted = true if fault.critical? - end - - def started(result) - @result = result - output_started - end - - def output_started - open_tag("stream") - end - - def finished(elapsed_time) - add_content("success", @result.passed?) - close_tag("stream") - end - - def test_started(test) - @already_outputted = false - @current_test = test - open_tag("start-test") do - output_test(test) - end - end - - def test_finished(test) - unless @already_outputted - open_tag("test-result") do - output_test(test) - open_tag("result") do - output_test_suite(@current_test_suite) - output_test(test) - add_content("status", "success") - end - end - end - - open_tag("complete-test") do - output_test(test) - add_content("success", test.passed?) - end - @current_test = nil - end - - def test_suite_started(suite) - @current_test_suite = suite - if suite.test_case.nil? - open_tag("ready-test-suite") do - add_content("n-tests", suite.size) - end - open_tag("start-test-suite") do - output_test_suite(suite) - end - else - open_tag("ready-test-case") do - output_test_suite(suite) - add_content("n-tests", suite.size) - end - open_tag("start-test-case") do - output_test_suite(suite) - end - end - end - - def test_suite_finished(suite) - if suite.test_case.nil? - open_tag("complete-test-suite") do - output_test_suite(suite) - add_content("success", suite.passed?) - end - else - open_tag("complete-test-case") do - output_test_suite(suite) - add_content("success", suite.passed?) - end - end - @current_test_suite = nil - end - - def indent - " " * @indent - end - - def open_tag(name) - @output.puts("#{indent}<#{name}>") - @indent += 2 - if block_given? - yield - close_tag(name) - end - end - - def add_content(name, content) - return if content.nil? - case content - when Time - content = content.iso8601 - end - @output.puts("#{indent}<#{name}>#{h(content)}") - end - - def close_tag(name) - @indent -= 2 - @output.puts("#{indent}") - end - - def output_test(test) - open_tag("test") do - add_content("name", test.method_name) - add_content("start-time", test.start_time) - add_content("elapsed", test.elapsed_time) - end - end - - def output_test_suite(test_suite) - test_case = test_suite.test_case - if test_case.nil? - open_tag("test-suite") do - add_content("name", test_suite.name) - add_content("start-time", test_suite.start_time) - add_content("elapsed", test_suite.elapsed_time) - end - else - open_tag("test-case") do - add_content("name", test_suite.name) - add_content("start-time", test_suite.start_time) - add_content("elapsed", test_suite.elapsed_time) - end - end - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/backtracefilter.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/util/backtracefilter.rb deleted file mode 100644 index 15db727a7..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/backtracefilter.rb +++ /dev/null @@ -1,59 +0,0 @@ -begin - require 'power_assert' -rescue LoadError, SyntaxError -end - -module Test - module Unit - module Util - module BacktraceFilter - TESTUNIT_FILE_SEPARATORS = %r{[\\/:]} - TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3] - TESTUNIT_RB_FILE = /\.rb\Z/ - - POWERASSERT_PREFIX = - defined?(::PowerAssert) ? - ::PowerAssert.method(:start).source_location[0].split(TESTUNIT_FILE_SEPARATORS)[0..-2] : - nil - - module_function - def filter_backtrace(backtrace, prefix=nil) - return ["No backtrace"] unless backtrace - return backtrace if ENV["TEST_UNIT_ALL_BACKTRACE"] - - if prefix - split_prefixes = [prefix.split(TESTUNIT_FILE_SEPARATORS)] - else - split_prefixes = [TESTUNIT_PREFIX, POWERASSERT_PREFIX].compact - end - test_unit_internal_p = lambda do |entry| - components = entry.split(TESTUNIT_FILE_SEPARATORS) - split_prefixes.any? do |split_prefix| - split_entry = components[0, split_prefix.size] - next false unless split_entry[0..-2] == split_prefix[0..-2] - split_entry[-1].sub(TESTUNIT_RB_FILE, '') == split_prefix[-1] - end - end - - in_user_code = false - new_backtrace = backtrace.reverse.reject do |entry| - if test_unit_internal_p.call(entry) - in_user_code = true - true - else - not in_user_code - end - end.reverse - - if new_backtrace.empty? - new_backtrace = backtrace.reject do |entry| - test_unit_internal_p.call(entry) - end - new_backtrace = backtrace if new_backtrace.empty? - end - new_backtrace - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/method-owner-finder.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/util/method-owner-finder.rb deleted file mode 100644 index 46a5b0cf9..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/method-owner-finder.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Test - module Unit - module Util - module MethodOwnerFinder - module_function - def find(object, method_name) - method = object.method(method_name) - return method.owner if method.respond_to?(:owner) - - if /\((.+?)\)\#/ =~ method.to_s - owner_name = $1 - if /\A# ["stdout\n", "stderr\n"] - def capture_output - require 'stringio' - - output = StringIO.new - error = StringIO.new - stdout_save, stderr_save = $stdout, $stderr - $stdout, $stderr = output, error - begin - yield - [output.string, error.string] - ensure - $stdout, $stderr = stdout_save, stderr_save - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/procwrapper.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/util/procwrapper.rb deleted file mode 100644 index b82d76b8f..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/util/procwrapper.rb +++ /dev/null @@ -1,48 +0,0 @@ -#-- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -module Test - module Unit - module Util - - # Allows the storage of a Proc passed through '&' in a - # hash. - # - # Note: this may be inefficient, since the hash being - # used is not necessarily very good. In Observable, - # efficiency is not too important, since the hash is - # only accessed when adding and removing listeners, - # not when notifying. - - class ProcWrapper - - # Creates a new wrapper for a_proc. - def initialize(a_proc) - @a_proc = a_proc - @hash = a_proc.inspect.sub(/^(#<#{a_proc.class}:)/){''}.sub(/(>)$/){''}.hex - end - - def hash - return @hash - end - - def ==(other) - case(other) - when ProcWrapper - return @a_proc == other.to_proc - else - return super - end - end - alias :eql? :== - - def to_proc - return @a_proc - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/lib/test/unit/version.rb b/ruby/gems/test-unit-3.3.4/lib/test/unit/version.rb deleted file mode 100644 index 2d3e97f6d..000000000 --- a/ruby/gems/test-unit-3.3.4/lib/test/unit/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Test - module Unit - VERSION = "3.3.4" - end -end diff --git a/ruby/gems/test-unit-3.3.4/sample/adder.rb b/ruby/gems/test-unit-3.3.4/sample/adder.rb deleted file mode 100644 index ca1b0f5bd..000000000 --- a/ruby/gems/test-unit-3.3.4/sample/adder.rb +++ /dev/null @@ -1,13 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -class Adder - def initialize(number) - @number = number - end - def add(number) - @number + number - end -end - diff --git a/ruby/gems/test-unit-3.3.4/sample/subtracter.rb b/ruby/gems/test-unit-3.3.4/sample/subtracter.rb deleted file mode 100644 index b7d3ab885..000000000 --- a/ruby/gems/test-unit-3.3.4/sample/subtracter.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -class Subtracter - def initialize(number) - @number = number - end - def subtract(number) - @number - number - end -end diff --git a/ruby/gems/test-unit-3.3.4/sample/test_adder.rb b/ruby/gems/test-unit-3.3.4/sample/test_adder.rb deleted file mode 100644 index 92c7f4d7d..000000000 --- a/ruby/gems/test-unit-3.3.4/sample/test_adder.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require_relative 'adder' - -class TestAdder < Test::Unit::TestCase - def setup - @adder = Adder.new(5) - end - - def test_add - assert_equal(7, @adder.add(2), "Should have added correctly") - end - - def teardown - @adder = nil - end -end diff --git a/ruby/gems/test-unit-3.3.4/sample/test_subtracter.rb b/ruby/gems/test-unit-3.3.4/sample/test_subtracter.rb deleted file mode 100644 index 9c85faee9..000000000 --- a/ruby/gems/test-unit-3.3.4/sample/test_subtracter.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require_relative 'subtracter' - -class TestSubtracter < Test::Unit::TestCase - def setup - @subtracter = Subtracter.new(5) - end - - def test_subtract - assert_equal(3, @subtracter.subtract(2), "Should have subtracted correctly") - end - - def teardown - @subtracter = nil - end -end diff --git a/ruby/gems/test-unit-3.3.4/sample/test_user.rb b/ruby/gems/test-unit-3.3.4/sample/test_user.rb deleted file mode 100644 index 181cf1453..000000000 --- a/ruby/gems/test-unit-3.3.4/sample/test_user.rb +++ /dev/null @@ -1,23 +0,0 @@ -# nested test case example. -require 'test/unit' - -class UserTest < Test::Unit::TestCase - def setup - @user = "me" - end - - def test_full_name - assert_equal("me", @user) - end - - class ProfileTest < UserTest - setup - def setup_profile - @user += ": profile" - end - - def test_has_profile - assert_match(/: profile/, @user) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test-unit.gemspec b/ruby/gems/test-unit-3.3.4/test-unit.gemspec deleted file mode 100644 index 1908c1bb1..000000000 --- a/ruby/gems/test-unit-3.3.4/test-unit.gemspec +++ /dev/null @@ -1,41 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: test-unit 3.3.4 ruby lib - -Gem::Specification.new do |s| - s.name = "test-unit".freeze - s.version = "3.3.4" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.metadata = { "source_code_uri" => "https://github.com/test-unit/test-unit" } if s.respond_to? :metadata= - s.require_paths = ["lib".freeze] - s.authors = ["Kouhei Sutou".freeze, "Haruka Yoshihara".freeze] - s.date = "2019-09-29" - s.description = "test-unit (Test::Unit) is unit testing framework for Ruby, based on xUnit\nprinciples. These were originally designed by Kent Beck, creator of extreme\nprogramming software development methodology, for Smalltalk's SUnit. It allows\nwriting tests, checking results and automated testing in Ruby.\n".freeze - s.email = ["kou@cozmixng.org".freeze, "yoshihara@clear-code.com".freeze] - s.files = ["COPYING".freeze, "GPL".freeze, "LGPL".freeze, "PSFL".freeze, "README.md".freeze, "Rakefile".freeze, "doc/text/getting-started.md".freeze, "doc/text/how-to.md".freeze, "doc/text/news.md".freeze, "lib/test-unit.rb".freeze, "lib/test/unit.rb".freeze, "lib/test/unit/assertion-failed-error.rb".freeze, "lib/test/unit/assertions.rb".freeze, "lib/test/unit/attribute-matcher.rb".freeze, "lib/test/unit/attribute.rb".freeze, "lib/test/unit/auto-runner-loader.rb".freeze, "lib/test/unit/autorunner.rb".freeze, "lib/test/unit/code-snippet-fetcher.rb".freeze, "lib/test/unit/collector.rb".freeze, "lib/test/unit/collector/descendant.rb".freeze, "lib/test/unit/collector/dir.rb".freeze, "lib/test/unit/collector/load.rb".freeze, "lib/test/unit/collector/objectspace.rb".freeze, "lib/test/unit/collector/xml.rb".freeze, "lib/test/unit/color-scheme.rb".freeze, "lib/test/unit/color.rb".freeze, "lib/test/unit/data-sets.rb".freeze, "lib/test/unit/data.rb".freeze, "lib/test/unit/diff.rb".freeze, "lib/test/unit/error.rb".freeze, "lib/test/unit/exception-handler.rb".freeze, "lib/test/unit/failure.rb".freeze, "lib/test/unit/fault-location-detector.rb".freeze, "lib/test/unit/fixture.rb".freeze, "lib/test/unit/notification.rb".freeze, "lib/test/unit/omission.rb".freeze, "lib/test/unit/pending.rb".freeze, "lib/test/unit/priority.rb".freeze, "lib/test/unit/runner/console.rb".freeze, "lib/test/unit/runner/emacs.rb".freeze, "lib/test/unit/runner/xml.rb".freeze, "lib/test/unit/test-suite-creator.rb".freeze, "lib/test/unit/testcase.rb".freeze, "lib/test/unit/testresult.rb".freeze, "lib/test/unit/testsuite.rb".freeze, "lib/test/unit/ui/console/outputlevel.rb".freeze, "lib/test/unit/ui/console/testrunner.rb".freeze, "lib/test/unit/ui/emacs/testrunner.rb".freeze, "lib/test/unit/ui/testrunner.rb".freeze, "lib/test/unit/ui/testrunnermediator.rb".freeze, "lib/test/unit/ui/testrunnerutilities.rb".freeze, "lib/test/unit/ui/xml/testrunner.rb".freeze, "lib/test/unit/util/backtracefilter.rb".freeze, "lib/test/unit/util/method-owner-finder.rb".freeze, "lib/test/unit/util/observable.rb".freeze, "lib/test/unit/util/output.rb".freeze, "lib/test/unit/util/procwrapper.rb".freeze, "lib/test/unit/version.rb".freeze, "sample/adder.rb".freeze, "sample/subtracter.rb".freeze, "sample/test_adder.rb".freeze, "sample/test_subtracter.rb".freeze, "sample/test_user.rb".freeze, "test/collector/test-descendant.rb".freeze, "test/collector/test-load.rb".freeze, "test/collector/test_dir.rb".freeze, "test/collector/test_objectspace.rb".freeze, "test/fixtures/header-label.csv".freeze, "test/fixtures/header-label.tsv".freeze, "test/fixtures/header.csv".freeze, "test/fixtures/header.tsv".freeze, "test/fixtures/no-header.csv".freeze, "test/fixtures/no-header.tsv".freeze, "test/fixtures/plus.csv".freeze, "test/run-test.rb".freeze, "test/test-assertions.rb".freeze, "test/test-attribute-matcher.rb".freeze, "test/test-attribute.rb".freeze, "test/test-code-snippet.rb".freeze, "test/test-color-scheme.rb".freeze, "test/test-color.rb".freeze, "test/test-data.rb".freeze, "test/test-diff.rb".freeze, "test/test-emacs-runner.rb".freeze, "test/test-error.rb".freeze, "test/test-failure.rb".freeze, "test/test-fault-location-detector.rb".freeze, "test/test-fixture.rb".freeze, "test/test-notification.rb".freeze, "test/test-omission.rb".freeze, "test/test-pending.rb".freeze, "test/test-priority.rb".freeze, "test/test-test-case.rb".freeze, "test/test-test-result.rb".freeze, "test/test-test-suite-creator.rb".freeze, "test/test-test-suite.rb".freeze, "test/testunit-test-util.rb".freeze, "test/ui/test_testrunmediator.rb".freeze, "test/util/test-method-owner-finder.rb".freeze, "test/util/test-output.rb".freeze, "test/util/test_backtracefilter.rb".freeze, "test/util/test_observable.rb".freeze, "test/util/test_procwrapper.rb".freeze] - s.homepage = "http://test-unit.github.io/".freeze - s.licenses = ["Ruby".freeze, "PSFL".freeze] - s.rubygems_version = "3.1.2".freeze - s.summary = "An xUnit family unit testing framework for Ruby.".freeze - s.test_files = ["test/util/test_procwrapper.rb".freeze, "test/util/test_observable.rb".freeze, "test/util/test-output.rb".freeze, "test/util/test-method-owner-finder.rb".freeze, "test/util/test_backtracefilter.rb".freeze, "test/test-diff.rb".freeze, "test/test-assertions.rb".freeze, "test/testunit-test-util.rb".freeze, "test/run-test.rb".freeze, "test/test-emacs-runner.rb".freeze, "test/test-color.rb".freeze, "test/test-pending.rb".freeze, "test/test-omission.rb".freeze, "test/test-color-scheme.rb".freeze, "test/test-test-result.rb".freeze, "test/test-test-suite.rb".freeze, "test/test-code-snippet.rb".freeze, "test/test-test-case.rb".freeze, "test/test-failure.rb".freeze, "test/fixtures/no-header.csv".freeze, "test/fixtures/header-label.tsv".freeze, "test/fixtures/no-header.tsv".freeze, "test/fixtures/header.csv".freeze, "test/fixtures/header-label.csv".freeze, "test/fixtures/plus.csv".freeze, "test/fixtures/header.tsv".freeze, "test/ui/test_testrunmediator.rb".freeze, "test/test-fixture.rb".freeze, "test/test-priority.rb".freeze, "test/test-test-suite-creator.rb".freeze, "test/test-attribute.rb".freeze, "test/test-notification.rb".freeze, "test/test-attribute-matcher.rb".freeze, "test/test-fault-location-detector.rb".freeze, "test/collector/test-descendant.rb".freeze, "test/collector/test_objectspace.rb".freeze, "test/collector/test-load.rb".freeze, "test/collector/test_dir.rb".freeze, "test/test-error.rb".freeze, "test/test-data.rb".freeze] - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_runtime_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - else - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/collector/test-descendant.rb b/ruby/gems/test-unit-3.3.4/test/collector/test-descendant.rb deleted file mode 100644 index 3f72e0b16..000000000 --- a/ruby/gems/test-unit-3.3.4/test/collector/test-descendant.rb +++ /dev/null @@ -1,182 +0,0 @@ -require 'test/unit' -require 'test/unit/collector/descendant' - -class TestUnitCollectorDescendant < Test::Unit::TestCase - def setup - @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup - Test::Unit::TestCase::DESCENDANTS.clear - end - - def teardown - Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants) - end - - private - def assert_collect(expected, *collect_args) - collector = Test::Unit::Collector::Descendant.new - yield(collector) if block_given? - assert_equal(expected, collector.send(:collect, *collect_args)) - end - - def default_name - Test::Unit::Collector::Descendant::NAME - end - - def empty_suite(name=nil) - Test::Unit::TestSuite.new(name || default_name) - end - - class TestCollect < self - def setup - super - - @test_case1 = Class.new(Test::Unit::TestCase) do - self.test_order = :alphabetic - - def self.name - "test-case1" - end - - def test_1 - end - - def test_2 - end - end - - @test_case2 = Class.new(Test::Unit::TestCase) do - self.test_order = :alphabetic - - def self.name - "test-case2" - end - - def test_0 - end - end - - @no_test_case = Class.new do - def self.name - "no-test-case" - end - - def test_4 - end - end - end - - def test_basic - assert_collect(full_suite("name"), "name") - - assert_collect(full_suite("name"), "name") do |collector| - collector.filter = [] - end - end - - def test_filtered - assert_collect(empty_suite) do |collector| - collector.filter = Proc.new {false} - end - - assert_collect(full_suite) do |collector| - collector.filter = Proc.new {true} - end - - assert_collect(full_suite) do |collector| - collector.filter = Proc.new {nil} - end - - assert_collect(empty_suite) do |collector| - collector.filter = [Proc.new {false}, Proc.new {true}] - end - - assert_collect(empty_suite) do |collector| - collector.filter = [Proc.new {true}, Proc.new {false}] - end - - assert_collect(empty_suite) do |collector| - collector.filter = [Proc.new {nil}, Proc.new {false}] - end - - assert_collect(full_suite) do |collector| - collector.filter = [Proc.new {nil}, Proc.new {true}] - end - - expected = empty_suite - suite1 = Test::Unit::TestSuite.new(@test_case1.name) - suite1 << @test_case1.new("test_1") - suite2 = Test::Unit::TestSuite.new(@test_case2.name) - suite2 << @test_case2.new("test_0") - expected << suite1 << suite2 - assert_collect(expected) do |collector| - collector.filter = Proc.new do |test| - ['test_1', 'test_0'].include?(test.method_name) - end - end - - suite1 = Test::Unit::TestSuite.new(@test_case1.name) - suite1 << @test_case1.new("test_1") - suite2 = Test::Unit::TestSuite.new(@test_case2.name) - suite2 << @test_case2.new("test_0") - assert_collect(empty_suite) do |collector| - filters = [Proc.new {|test| test.method_name == 'test_1' ? true : nil}, - Proc.new {|test| test.method_name == 'test_0' ? true : nil}, - Proc.new {false}] - collector.filter = filters - end - end - - private - def full_suite(name=nil) - sub_suite1 = Test::Unit::TestSuite.new(@test_case1.name) - sub_suite1 << @test_case1.new('test_1') - sub_suite1 << @test_case1.new('test_2') - - sub_suite2 = Test::Unit::TestSuite.new(@test_case2.name) - sub_suite2 << @test_case2.new('test_0') - - suite = empty_suite(name) - suite << sub_suite1 - suite << sub_suite2 - suite - end - end - - class TestModule < self - def test_included_in_child - tests = Module.new do - def test_in_module - end - end - - parent_test_case = Class.new(Test::Unit::TestCase) do - class << self - def name - "Parent" - end - end - end - - child_test_case = Class.new(parent_test_case) do - include tests - - class << self - def name - "Child" - end - end - end - - child_suite = Test::Unit::TestSuite.new(child_test_case.name) - child_suite << child_test_case.new("test_in_module") - - parent_suite = Test::Unit::TestSuite.new(parent_test_case.name) - parent_suite << child_suite - - suite = empty_suite("all") - suite << parent_suite - - assert_collect(suite, "all") - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/collector/test-load.rb b/ruby/gems/test-unit-3.3.4/test/collector/test-load.rb deleted file mode 100644 index 967836db5..000000000 --- a/ruby/gems/test-unit-3.3.4/test/collector/test-load.rb +++ /dev/null @@ -1,475 +0,0 @@ -require 'tmpdir' -require 'pathname' - -require 'test/unit' -require 'test/unit/collector/load' - -class TestUnitCollectorLoad < Test::Unit::TestCase - def setup - @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup - Test::Unit::TestCase::DESCENDANTS.clear - - @temporary_test_cases_module_name = "TempTestCases" - ::Object.const_set(@temporary_test_cases_module_name, Module.new) - - @test_dir = Pathname(Dir.tmpdir) + "test-unit" - @extra_test_dir = Pathname(Dir.tmpdir) + "test-unit-extra" - ensure_clean_directory(@test_dir) - ensure_clean_directory(@extra_test_dir) - end - - setup - def setup_top_level_test_cases - @test_case1_base_name = "test_case1.rb" - - @test_case1 = @test_dir + @test_case1_base_name - @test_case2 = @test_dir + "test_case2.rb" - @no_load_test_case3 = @test_dir + "case3.rb" - - @test_case1.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class TestCase1 < Test::Unit::TestCase - def test1_1 - end - - def test1_2 - end - end -end -EOT - end - - @test_case2.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class TestCase2 < Test::Unit::TestCase - def test2 - end - end -end -EOT - end - - @no_load_test_case3.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class NoLoadTestCase3 < Test::Unit::TestCase - def test3 - end - end -end -EOT - end - end - - setup - def setup_sub_level_test_cases - @sub_test_dir = @test_dir + "sub" - @sub_test_dir.mkpath - - @sub_test_case1 = @sub_test_dir + @test_case1_base_name - @sub_test_case4 = @sub_test_dir + "test_case4.rb" - @no_load_sub_test_case5 = @sub_test_dir + "case5.rb" - @sub_test_case6 = @sub_test_dir + "test_case6.rb" - - @sub_test_case1.open("w") do |test_case| - test_case.puts(<<-TEST_CASE) -module #{@temporary_test_cases_module_name} - class SubTestCase1 < Test::Unit::TestCase - def test1_1 - end - - def test1_2 - end - end -end - TEST_CASE - end - - @sub_test_case4.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SubTestCase4 < Test::Unit::TestCase - def test4_1 - end - - def test4_2 - end - end -end -EOT - end - - @no_load_sub_test_case5.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class NoLoadSubTestCase5 < Test::Unit::TestCase - def test5_1 - end - - def test5_2 - end - end -end -EOT - end - - @sub_test_case6.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SubTestCase6 < Test::Unit::TestCase - def test6 - end - end -end -EOT - end - end - - setup - def setup_sub_level_test_cases2 - @sub2_test_dir = @test_dir + "sub2" - @sub2_test_dir.mkpath - - @no_load_sub2_test_case7 = @sub2_test_dir + "case7.rb" - @sub2_test_case8 = @sub2_test_dir + "test_case8.rb" - @sub2_test_case9 = @sub2_test_dir + "test_case9.rb" - - @no_load_sub2_test_case7.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class NoLoadSub2TestCase7 < Test::Unit::TestCase - def test7_1 - end - - def test7_2 - end - end -end -EOT - end - - @sub2_test_case8.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class Sub2TestCase8 < Test::Unit::TestCase - def test8_1 - end - - def test8_2 - end - end -end -EOT - end - - @sub2_test_case9.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class Sub2TestCase9 < Test::Unit::TestCase - def test9 - end - end -end -EOT - end - end - - setup - def setup_svn_test_cases - @svn_test_dir = @test_dir + ".svn" - @svn_test_dir.mkpath - - @svn_test_case10 = @svn_test_dir + "test_case10.rb" - - @svn_test_case10.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SvnTestCase10 < Test::Unit::TestCase - def test7 - end - end -end -EOT - end - end - - setup - def setup_sub_cvs_test_cases - @sub_cvs_test_dir = @sub_test_dir + "CVS" - @sub_cvs_test_dir.mkpath - - @sub_cvs_test_case11 = @sub_cvs_test_dir + "test_case11.rb" - - @sub_cvs_test_case11.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SubCVSTestCase11 < Test::Unit::TestCase - def test11 - end - end -end -EOT - end - end - - setup - def setup_sub_git_test_cases - @sub_git_test_dir = @sub_test_dir + ".git" - @sub_git_test_dir.mkpath - - @sub_git_test_case11 = @sub_git_test_dir + "test_case11.rb" - - @sub_git_test_case11.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SubGitTestCase11 < Test::Unit::TestCase - def test11 - end - end -end -EOT - end - end - - setup - def setup_extra_top_level_test_cases - @test_cases12 = @extra_test_dir + "test_cases12.rb" - @test_cases12.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class TestCase121 < Test::Unit::TestCase - def test121_1 - end - - def test121_2 - end - end - - class TestCase122 < Test::Unit::TestCase - def test122_1 - end - - def test122_2 - end - end -end -EOT - end - end - - setup - def setup_sub_level_extra_test_cases - @sub_extra_test_dir = @extra_test_dir + "sub" - @sub_extra_test_dir.mkpath - - @cases13_test = @sub_extra_test_dir + "13cases_test.rb" - @cases13_test.open("w") do |test_case| - test_case.puts(<<-EOT) -module #{@temporary_test_cases_module_name} - class SubTestCase13 < Test::Unit::TestCase - def test13_1 - end - - def test13_2 - end - end -end -EOT - end - end - - def teardown - @test_dir.rmtree if @test_dir.exist? - ::Object.send(:remove_const, @temporary_test_cases_module_name) - Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants) - end - - def test_simple_collect - assert_collect([:suite, {:name => @sub_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("SubTestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("SubTestCase4")}, - [:test, {:name => "test4_1"}], - [:test, {:name => "test4_2"}]], - [:suite, {:name => _test_case_name("SubTestCase6")}, - [:test, {:name => "test6"}]]], - @sub_test_dir.to_s) - end - - def test_simple_collect_test_suffix - assert_collect([:suite, {:name => @extra_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("TestCase121")}, - [:test, {:name => "test121_1"}], - [:test, {:name => "test121_2"}]], - [:suite, {:name => _test_case_name("TestCase122")}, - [:test, {:name => "test122_1"}], - [:test, {:name => "test122_2"}]], - [:suite, {:name => @sub_extra_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("SubTestCase13")}, - [:test, {:name => "test13_1"}], - [:test, {:name => "test13_2"}]]]], - @extra_test_dir.to_s) - end - - def test_multilevel_collect - assert_collect([:suite, {:name => "."}, - [:suite, {:name => _test_case_name("TestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("TestCase2")}, - [:test, {:name => "test2"}]], - [:suite, {:name => @sub_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("SubTestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("SubTestCase4")}, - [:test, {:name => "test4_1"}], - [:test, {:name => "test4_2"}]], - [:suite, {:name => _test_case_name("SubTestCase6")}, - [:test, {:name => "test6"}]]], - [:suite, {:name => @sub2_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("Sub2TestCase8")}, - [:test, {:name => "test8_1"}], - [:test, {:name => "test8_2"}]], - [:suite, {:name => _test_case_name("Sub2TestCase9")}, - [:test, {:name => "test9"}]]]]) - end - - def test_collect_file - assert_collect([:suite, {:name => _test_case_name("TestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - @test_case1.to_s) - end - - def test_collect_file_no_pattern_match_file_name - assert_collect([:suite, {:name => _test_case_name("NoLoadSubTestCase5")}, - [:test, {:name => "test5_1"}], - [:test, {:name => "test5_2"}]], - @no_load_sub_test_case5.to_s) - end - - def test_collect_file_test_cases - assert_collect([:suite, {:name => "[#{@test_cases12}]"}, - [:suite, {:name => _test_case_name("TestCase121")}, - [:test, {:name => "test121_1"}], - [:test, {:name => "test121_2"}]], - [:suite, {:name => _test_case_name("TestCase122")}, - [:test, {:name => "test122_1"}], - [:test, {:name => "test122_2"}]]], - @test_cases12.to_s) - end - - def test_collect_files - assert_collect([:suite, - {:name => "[#{@test_case1}, #{@test_case2}]"}, - [:suite, {:name => _test_case_name("TestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("TestCase2")}, - [:test, {:name => "test2"}]]], - @test_case1.to_s, @test_case2.to_s) - end - - def test_nil_pattern - assert_collect([:suite, {:name => @sub_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("NoLoadSubTestCase5")}, - [:test, {:name => "test5_1"}], - [:test, {:name => "test5_2"}]], - [:suite, {:name => _test_case_name("SubTestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("SubTestCase4")}, - [:test, {:name => "test4_1"}], - [:test, {:name => "test4_2"}]], - [:suite, {:name => _test_case_name("SubTestCase6")}, - [:test, {:name => "test6"}]]], - @sub_test_dir.to_s) do |collector| - collector.patterns.clear - end - end - - def test_filtering - assert_collect([:suite, {:name => "."}, - [:suite, {:name => _test_case_name("TestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => @sub_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("SubTestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]]]]) do |collector| - collector.filter = Proc.new do |test| - !/\Atest1/.match(test.method_name).nil? - end - end - end - - def test_collect_multi - test_dirs = [@sub_test_dir.to_s, @sub2_test_dir.to_s] - assert_collect([:suite, {:name => "[#{test_dirs.join(', ')}]"}, - [:suite, {:name => @sub_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("SubTestCase1")}, - [:test, {:name => "test1_1"}], - [:test, {:name => "test1_2"}]], - [:suite, {:name => _test_case_name("SubTestCase4")}, - [:test, {:name => "test4_1"}], - [:test, {:name => "test4_2"}]], - [:suite, {:name => _test_case_name("SubTestCase6")}, - [:test, {:name => "test6"}]]], - [:suite, {:name => @sub2_test_dir.basename.to_s}, - [:suite, {:name => _test_case_name("Sub2TestCase8")}, - [:test, {:name => "test8_1"}], - [:test, {:name => "test8_2"}]], - [:suite, {:name => _test_case_name("Sub2TestCase9")}, - [:test, {:name => "test9"}]]]], - *test_dirs) - end - - private - def assert_collect(expected, *collect_args) - keep_required_files do - Dir.chdir(@test_dir.to_s) do - collector = Test::Unit::Collector::Load.new - yield(collector) if block_given? - actual = inspect_test_object(collector.send(:collect, *collect_args)) - assert_equal(expected, actual) - end - end - end - - def ensure_clean_directory(directory) - directory.rmtree if directory.exist? - directory.mkpath - end - - def keep_required_files - required_files = $".dup - yield - ensure - $".replace(required_files) - end - - def _test_case_name(test_case_class_name) - "#{@temporary_test_cases_module_name}::#{test_case_class_name}" - end - - def inspect_test_object(test_object) - return nil if test_object.nil? - case test_object - when Test::Unit::TestSuite - sub_tests = test_object.tests.collect do |test| - inspect_test_object(test) - end.sort_by do |type, attributes, *children| - attributes[:name] - end - [:suite, {:name => test_object.name}, *sub_tests] - when Test::Unit::TestCase - [:test, {:name => test_object.method_name}] - else - raise "unexpected test object: #{test_object.inspect}" - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/collector/test_dir.rb b/ruby/gems/test-unit-3.3.4/test/collector/test_dir.rb deleted file mode 100644 index c25793813..000000000 --- a/ruby/gems/test-unit-3.3.4/test/collector/test_dir.rb +++ /dev/null @@ -1,407 +0,0 @@ -require 'test/unit' -require 'test/unit/collector/dir' -require 'pp' - -module Test - module Unit - module Collector - class TestDir < TestCase - class FileSystem - class Directory - def initialize(name, fs, parent=self, &block) - @name = name - @fs = fs - @parent = parent - @contents = {'.' => self, '..' => parent} - instance_eval(&block) if(block) - end - - def file(name, contents) - @contents[name] = contents - end - - def dir(name, &block) - @contents[name] = self.class.new(name, @fs, self, &block) - end - - def entries - @contents.keys - end - - def directory?(name) - return true if(name.nil? || name.empty?) - return false unless(@contents.include?(name)) - @contents[name].kind_of?(self.class) - end - - def file?(name) - return false unless(@contents.include?(name)) - !directory?(name) - end - - def exist?(name) - @contents.include?(name) - end - - def [](name) - raise Errno::ENOENT, name unless(@contents.include?(name)) - @contents[name] - end - - def path_to(name=nil) - if(!name) - @parent.path_to(@name) - elsif(@parent == self) - @fs.join('/', name) - else - @fs.join(@parent.path_to(@name), name) - end - end - end - - class ObjectSpace - def initialize - @objects = [] - end - - def each_object(klass, &block) - @objects.find_all{|o| o.kind_of?(klass)}.each(&block) - end - - def <<(object) - @objects << object - end - end - - attr_reader :object_space - - def initialize(&block) - @root = Directory.new('/', self, &block) - @pwd = @root - @object_space = ObjectSpace.new - @required = [] - end - - def entries(dir) - e = find(dir) - require_directory(dir) - e.entries - end - - def directory?(name) - return true if (base = basename(name)) == '/' - e = find(dirname(name)) - return false unless(e) - e.directory?(base) - end - - def find(path) - if(/\A\// =~ path) - thing = @root - else - thing = @pwd - end - path.scan(/[^\/]+/) do |e| - break thing = false unless(thing.kind_of?(Directory)) - thing = thing[e] - end - thing - end - - def dirname(name) - if (name = name.tr_s('/', '/')) == '/' - name - else - name[%r"\A.+(?=/[^/]+/?\z)|\A/"] || "." - end - end - - def basename(name) - name[%r"(\A/|[^/]+)/*\z", 1] - end - - def split(name) - [dirname(name), basename(name)] - end - - def join(*parts) - parts.join('/').gsub(%r{/+}, '/') - end - - def file?(name) - e = find(dirname(name)) - return false unless(e) - e.file?(basename(name)) - end - - def pwd - @pwd.path_to - end - - def chdir(to) - e = find(to) - require_directory(to) - @pwd = e - end - - def expand_path(path, base = nil) - until /\A\// =~ path - base ||= pwd - path = join(base, path) - base = nil - end - path.gsub!(%r"(?:/\.)+(?=/)", '') - nil while path.sub!(%r"/(?!\.\./)[^/]+/\.\.(?=/)", '') - path.sub!(%r"\A(?:/\.\.)+(?=/)", '') - path.sub!(%r"(?:\A(/)|/)\.\.?\z", '\1') - path - end - - def require_directory(path) - raise Errno::ENOTDIR, path unless(directory?(path)) - end - - def require(file) - return false if(@required.include?(file)) - begin - e = find(file) - rescue Errno::ENOENT => e - if(/\.rb\Z/ =~ file) - raise LoadError, file - end - e = find(file + '.rb') - end - @required << file - @object_space << e - true - rescue Errno::ENOENT - raise LoadError, file - end - end - - def test_dir - inner_dir = nil - dirs = FileSystem::Directory.new('/', nil) do - file 'a', nil - inner_dir = dir 'b' - end - assert_equal(inner_dir, dirs['b']) - end - - def test_fs - fs = FileSystem.new do - file 'a', nil - dir 'b' - end - assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort) - assert(fs.directory?('/')) - assert(!fs.directory?('/a')) - assert(!fs.directory?('/bogus')) - assert(fs.file?('/a')) - assert(!fs.file?('/')) - assert(!fs.file?('/bogus')) - assert(fs.directory?('/b')) - assert(fs.file?('a')) - assert(fs.directory?('b')) - end - - def test_fs_sub - fs = FileSystem.new do - dir 'a' do - file 'b', nil - dir 'c' do - file 'd', nil - end - end - end - assert(fs.file?('/a/b')) - assert(!fs.file?('/a/b/c/d')) - assert(fs.file?('/a/c/d')) - end - - def test_fs_pwd - fs = FileSystem.new do - file 'a', nil - dir 'b' do - file 'c', nil - dir 'd' do - file 'e', nil - end - end - end - assert_equal('/', fs.pwd) - assert_raises(Errno::ENOENT) do - fs.chdir('bogus') - end - assert_raises(Errno::ENOTDIR) do - fs.chdir('a') - end - fs.chdir('b') - assert_equal('/b', fs.pwd) - fs.chdir('d') - assert_equal('/b/d', fs.pwd) - fs.chdir('..') - assert_equal('/b', fs.pwd) - fs.chdir('..') - assert_equal('/', fs.pwd) - end - - def test_fs_entries - fs = FileSystem.new do - file 'a', nil - dir 'b' do - file 'c', nil - file 'd', nil - end - file 'e', nil - dir 'f' do - file 'g', nil - dir 'h' do - file 'i', nil - end - end - end - assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort) - assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort) - assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort) - assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort) - assert_raises(Errno::ENOENT) do - fs.entries('z') - end - assert_raises(Errno::ENOTDIR) do - fs.entries('a') - end - fs.chdir('f') - assert_equal(['.', '..', 'i'], fs.entries('h').sort) - end - - class TestClass1 - end - class TestClass2 - end - def test_fs_require - fs = FileSystem.new do - file 'test_class1.rb', TestClass1 - dir 'dir' do - file 'test_class2.rb', TestClass2 - end - end - c = [] - fs.object_space.each_object(Class) do |o| - c << o - end - assert_equal([], c) - - assert_raises(LoadError) do - fs.require('bogus') - end - - assert(fs.require('test_class1.rb')) - assert(!fs.require('test_class1.rb')) - c = [] - fs.object_space.each_object(Class) do |o| - c << o - end - assert_equal([TestClass1], c) - - fs.require('dir/test_class2') - c = [] - fs.object_space.each_object(Class) do |o| - c << o - end - assert_equal([TestClass1, TestClass2], c) - - c = [] - fs.object_space.each_object(Time) do |o| - c << o - end - assert_equal([], c) - end - - def setup - @t1 = t1 = create_test(1) - @t2 = t2 = create_test(2) - @t3 = t3 = create_test(3) - @t4 = t4 = create_test(4) - @t5 = t5 = create_test(5) - @t6 = t6 = create_test(6) - fs = FileSystem.new do - file 'test_1.rb', t1 - file 'test_2.rb', t2 - dir 'd1' do - file 'test_3.rb', t3 - end - file 't4.rb', t4 - dir 'd2' do - file 'test_5', t5 - file 'test_6.rb', Time - end - file 't6.rb', t6 - end - fs.require('t6') - @c = Dir.new(fs, fs, fs.object_space, fs) - end - - def create_test(name) - t = Class.new(TestCase) - t.class_eval <<-EOC - self.test_order = :alphabetic - def self.name - "T\#{#{name}}" - end - def test_#{name}a - end - def test_#{name}b - end - EOC - t - end - - def test_simple_collect - expected = TestSuite.new('d1') - expected << (@t3.suite) - assert_equal(expected, @c.collect('d1')) - end - - def test_multilevel_collect - expected = TestSuite.new('.') - expected << @t1.suite << @t2.suite - expected << (TestSuite.new('d1') << @t3.suite) - assert_equal(expected, @c.collect) - end - - def test_collect_file - expected = TestSuite.new('test_1.rb') - expected << @t1.suite - assert_equal(expected, @c.collect('test_1.rb')) - - expected = TestSuite.new('t4.rb') - expected << @t4.suite - assert_equal(expected, @c.collect('t4.rb')) - end - - def test_nil_pattern - expected = TestSuite.new('d2') - expected << @t5.suite - @c.pattern.clear - assert_equal(expected, @c.collect('d2')) - end - - def test_filtering - expected = TestSuite.new('.') - expected << @t1.suite - @c.filter = proc{|t| t.method_name == 'test_1a' || t.method_name == 'test_1b'} - assert_equal(expected, @c.collect) - end - - def test_collect_multi - expected = TestSuite.new('[d1, d2]') - expected << (TestSuite.new('d1') << @t3.suite) - expected << (TestSuite.new('d2') << @t5.suite) - @c.pattern.replace([/\btest_/]) - assert_equal(expected, @c.collect('d1', 'd2')) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/collector/test_objectspace.rb b/ruby/gems/test-unit-3.3.4/test/collector/test_objectspace.rb deleted file mode 100644 index b63b5a3e8..000000000 --- a/ruby/gems/test-unit-3.3.4/test/collector/test_objectspace.rb +++ /dev/null @@ -1,102 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require 'test/unit/collector/objectspace' - -module Test - module Unit - module Collector - class TC_ObjectSpace < TestCase - def setup - @tc1 = Class.new(TestCase) do - self.test_order = :alphabetic - def self.name - "tc_1" - end - def test_1 - end - def test_2 - end - end - - @tc2 = Class.new(TestCase) do - self.test_order = :alphabetic - def self.name - "tc_2" - end - def test_0 - end - end - - @no_tc = Class.new do - def test_4 - end - end - - @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']} - def @object_space.each_object(type) - self[type].each{|item| yield(item) } - end - - @c = ObjectSpace.new(@object_space) - end - - def full_suite(name=ObjectSpace::NAME) - expected = TestSuite.new(name) - expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1') << @tc1.new('test_2')) - expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0')) - end - - def empty_suite - TestSuite.new(ObjectSpace::NAME) - end - - def test_basic_collection - assert_equal(full_suite("name"), @c.collect("name")) - - @c.filter = [] - assert_equal(full_suite("name"), @c.collect("name")) - end - - def test_filtered_collection - @c.filter = proc{false} - assert_equal(empty_suite, @c.collect) - - @c.filter = proc{true} - assert_equal(full_suite, @c.collect) - - @c.filter = proc{nil} - assert_equal(full_suite, @c.collect) - - @c.filter = [proc{false}, proc{true}] - assert_equal(empty_suite, @c.collect) - - @c.filter = [proc{true}, proc{false}] - assert_equal(empty_suite, @c.collect) - - @c.filter = [proc{nil}, proc{false}] - assert_equal(empty_suite, @c.collect) - - @c.filter = [proc{nil}, proc{true}] - assert_equal(full_suite, @c.collect) - - expected = TestSuite.new(ObjectSpace::NAME) - expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1')) - expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0')) - @c.filter = proc{|test| ['test_1', 'test_0'].include?(test.method_name)} - assert_equal(expected, @c.collect) - - expected = TestSuite.new(ObjectSpace::NAME) - TestSuite.new(@tc1.name) << @tc1.new('test_1') - TestSuite.new(@tc2.name) << @tc2.new('test_0') - @c.filter = [proc{|t| t.method_name == 'test_1' ? true : nil}, - proc{|t| t.method_name == 'test_0' ? true : nil}, - proc{false}] - assert_equal(empty_suite, @c.collect) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.csv b/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.csv deleted file mode 100644 index 42cffe4e6..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.csv +++ /dev/null @@ -1,3 +0,0 @@ -label,expected,label -upper case,HELLO,HELLO -lower case,Hello,hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.tsv b/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.tsv deleted file mode 100644 index 25f84bd6a..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/header-label.tsv +++ /dev/null @@ -1,3 +0,0 @@ -label expected label -upper case HELLO HELLO -lower case Hello hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/header.csv b/ruby/gems/test-unit-3.3.4/test/fixtures/header.csv deleted file mode 100644 index 5173e49ce..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/header.csv +++ /dev/null @@ -1,3 +0,0 @@ -label,expected,target -empty string,true,"" -plain string,false,hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/header.tsv b/ruby/gems/test-unit-3.3.4/test/fixtures/header.tsv deleted file mode 100644 index 5e01a6f06..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/header.tsv +++ /dev/null @@ -1,3 +0,0 @@ -label expected target -empty string true "" -plain string false hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.csv b/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.csv deleted file mode 100644 index a6d47d538..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.csv +++ /dev/null @@ -1,2 +0,0 @@ -empty string,true,"" -plain string,false,hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.tsv b/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.tsv deleted file mode 100644 index 775930964..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/no-header.tsv +++ /dev/null @@ -1,2 +0,0 @@ -empty string true "" -plain string false hello diff --git a/ruby/gems/test-unit-3.3.4/test/fixtures/plus.csv b/ruby/gems/test-unit-3.3.4/test/fixtures/plus.csv deleted file mode 100644 index 218d971da..000000000 --- a/ruby/gems/test-unit-3.3.4/test/fixtures/plus.csv +++ /dev/null @@ -1,3 +0,0 @@ -label,expected,augend,addend -positive positive,4,3,1 -positive negative,-1,1,-2 diff --git a/ruby/gems/test-unit-3.3.4/test/run-test.rb b/ruby/gems/test-unit-3.3.4/test/run-test.rb deleted file mode 100755 index 409a810b6..000000000 --- a/ruby/gems/test-unit-3.3.4/test/run-test.rb +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$KCODE = "utf8" unless "".respond_to?(:encoding) - -base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..")) -lib_dir = File.join(base_dir, "lib") -test_dir = File.join(base_dir, "test") - -$LOAD_PATH.unshift(lib_dir) - -require 'test/unit' - -test_unit_notify_base_dir = File.join(base_dir, "..", "test-unit-notify") -test_unit_notify_base_dir = File.expand_path(test_unit_notify_base_dir) -if File.exist?(test_unit_notify_base_dir) - $LOAD_PATH.unshift(File.join(test_unit_notify_base_dir, "lib")) - require 'test/unit/notify' -end - -exit Test::Unit::AutoRunner.run(true, test_dir) diff --git a/ruby/gems/test-unit-3.3.4/test/test-assertions.rb b/ruby/gems/test-unit-3.3.4/test/test-assertions.rb deleted file mode 100644 index e454cc263..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-assertions.rb +++ /dev/null @@ -1,2187 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# Copyright (c) 2009-2014 Kouhei Sutou. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require "testunit-test-util" - -module Test - module Unit - module AssertionCheckable - include TestUnitTestUtil - - private - def check(value, message="") - add_assertion - raise AssertionFailedError.new(message) unless value - end - - def check_assertions(expect_fail, options={}) - expected_message = options[:expected_message] - actual_message_normalizer = options[:actual_message_normalizer] - return_value_expected = options[:return_value_expected] - @actual_assertion_count = 0 - failed = true - actual_message = nil - @catch_assertions = true - return_value = nil - begin - return_value = yield - failed = false - rescue AssertionFailedError => error - return_value = error - actual_message = error.message - end - @catch_assertions = false - - if expect_fail - message = "Should have failed, but didn't" - else - message = "Should not have failed, but did with message\n" + - "<#{actual_message}>" - end - check(expect_fail == failed, message) - - message = "Should have made one assertion but made\n" + - "<#{@actual_assertion_count}>" - check(1 == @actual_assertion_count, message) - - if expect_fail - if actual_message_normalizer - actual_message = actual_message_normalizer.call(actual_message) - end - case expected_message - when String - check(expected_message == actual_message, - "Should have the correct message.\n" + - "<#{expected_message.inspect}> expected but was\n" + - "<#{actual_message.inspect}>") - when Regexp - check(expected_message =~ actual_message, - "The message should match correctly.\n" + - " expected to match\n" + - "<#{actual_message.inspect}>") - else - check(false, - "Incorrect expected message type in assert_nothing_failed") - end - else - case return_value_expected - when :dont_care - # do nothing - when true - check(!return_value.nil?, "Should return a value") - else - check(return_value.nil?, - "Should not return a value but returned <#{return_value}>") - end - end - - return_value - end - - def check_nothing_fails(return_value_expected=false, &proc) - check_assertions(false, - {:expected_message => nil, - :return_value_expected => return_value_expected}, - &proc) - end - - def check_fail(expected_message, options={}, &proc) - check_assertions(true, - options.merge(:expected_message => expected_message), - &proc) - end - - def check_fail_exception(expected_message, options={}, &proc) - normalizer = lambda do |actual_message| - actual_message.gsub(/(^[^:\n]+:\d+:.+\n?)+\z/, "") - end - check_assertions(true, - options.merge(:expected_message => expected_message, - :actual_message_normalizer => normalizer), - &proc) - end - - def inspect_tag(tag) - tag.inspect - end - - def add_failure(message, location=caller, options=nil) - unless @catch_assertions - super - end - end - - def add_assertion - if @catch_assertions - @actual_assertion_count += 1 - else - super - end - end - end - - class TestAssertions < TestCase - include AssertionCheckable - - class TestAssertBlock < self - def test_pass_without_message - check_nothing_fails { - assert_block {true} - } - end - - def test_pass_with_message - check_nothing_fails { - assert_block("successful assert_block") {true} - } - end - - def test_failure_without_message - check_fail("assert_block failed.") { - assert_block {false} - } - end - - def test_failure_with_message - check_fail("failed assert_block") { - assert_block("failed assert_block") {false} - } - end - end - - class TestAssertEqual < self - class TestSuccess < self - def test_without_message - check_nothing_fails { - assert_equal("string1", "string1") - } - end - - def test_with_message - check_nothing_fails { - assert_equal("string1", "string1", "successful assert_equal") - } - end - end - - class TestFailure < self - def test_without_message - message = <<-EOM.chomp -<"string1"> expected but was -<"string2">. - -diff: -- string1 -? ^ -+ string2 -? ^ -EOM - check_fail(message) { - assert_equal("string1", "string2") - } - end - - def test_with_message - message = <<-EOM.chomp -failed assert_equal. -<"string1"> expected but was -<"string2">. - -diff: -- string1 -? ^ -+ string2 -? ^ -EOM - check_fail(message) { - assert_equal("string1", "string2", "failed assert_equal") - } - end - - def test_with_message_proc - message = <<-EOM.chomp -failed assert_equal. -<"string1"> expected but was -<"string2">. - -diff: -- string1 -? ^ -+ string2 -? ^ -EOM - check_fail(message) do - assert_equal("string1", "string2", lambda {"failed assert_equal"}) - end - end - end - - class TestSystemMessage < self - def test_different_type - message = <<-EOM.chomp -<"111111"> expected but was -<111111>. - -diff: -- "111111" -? - - -+ 111111 -EOM - check_fail(message) do - assert_equal("111111", 111111) - end - end - - def test_long_line - expected = ["0123456789", - "1123456789", - "2123456789", - "3123456789", - "4123456789", - "5123456789", - "6123456789", - "7123456789", - "8123456789"].join - actual = ["0000000000", - "1123456789", - "2123456789", - "3123456789", - "4123456789", - "5123456789", - "6123456789", - "7123456789", - "8123456789"].join - message = <<-EOM.chomp -<"#{expected}"> expected but was -<"#{actual}">. - -diff: -- #{expected} -? ^^^^^^^^^ -+ #{actual} -? ^^^^^^^^^ - -folded diff: -- 012345678911234567892123456789312345678941234567895123456789612345678971234567 -? ^^^^^^^^^ -+ 000000000011234567892123456789312345678941234567895123456789612345678971234567 -? ^^^^^^^^^ - 898123456789 -EOM - check_fail(message) do - assert_equal(expected, actual) - end - end - - def test_too_small_difference - message = <<-EOM.chomp -<1> expected but was -<2>. -EOM - check_fail(message) do - assert_equal(1, 2) - end - end - - def test_same_inspected_objects - same_inspected_class = Class.new do - def inspect - "inspected" - end - end - object1 = same_inspected_class.new - object2 = same_inspected_class.new - message = <<-EOM.chomp - expected but was -. -EOM - check_fail(message) do - assert_equal(object1, object2) - end - end - - def test_multi_lines_result - message = <<-EOM.chomp -<#{AssertionMessage.convert("a\nb")}> expected but was -<#{AssertionMessage.convert("x")}>. - -diff: -+ x -- a -- b -EOM - check_fail(message) do - assert_equal("a\nb", "x") - end - end - - def test_large_string - message = <<-EOM.chomp -<#{AssertionMessage.convert("a\n" + "x" * 997)}> expected but was -<#{AssertionMessage.convert("x")}>. - -diff: -+ x -- a -- #{"x" * 997} - -folded diff: -+ x -- a -#{(["- " + ("x" * 78)] * 12).join("\n")} -- #{"x" * 61} -EOM - check_fail(message) do - assert_equal("a\n" + "x" * 997, "x") - end - - message = <<-EOM.chomp -<#{AssertionMessage.convert("a\n" + "x" * 998)}> expected but was -<#{AssertionMessage.convert("x")}>. -EOM - check_fail(message) do - assert_equal("a\n" + "x" * 998, "x") - end - end - - def test_max_diff_target_string_size - key = "TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE" - before_value = ENV[key] - ENV[key] = "100" - begin - message = <<-EOM.chomp -<#{AssertionMessage.convert("a\n" + "x" * 97)}> expected but was -<#{AssertionMessage.convert("x")}>. - -diff: -+ x -- a -- #{"x" * 97} - -folded diff: -+ x -- a -#{(["- " + ("x" * 78)]).join("\n")} -- #{"x" * 19} -EOM - check_fail(message) do - assert_equal("a\n" + "x" * 97, "x") - end - - message = <<-EOM.chomp -<#{AssertionMessage.convert("a\n" + "x" * 98)}> expected but was -<#{AssertionMessage.convert("x")}>. -EOM - check_fail(message) do - assert_equal("a\n" + "x" * 98, "x") - end - ensure - ENV[key] = before_value - end - end - - def test_different_encoding - utf8_string = "ã“ã‚“ã«ã¡ã¯" - unless utf8_string.respond_to?(:force_encoding) - omit("encoding test is for Ruby >= 1.9") - end - ascii_8bit_string = utf8_string.dup.force_encoding("ascii-8bit") - message = <<-EOM.chomp -<#{utf8_string.inspect}>("UTF-8") expected but was -<#{ascii_8bit_string.inspect}>("ASCII-8BIT"). -EOM - check_fail(message) do - assert_equal(utf8_string, ascii_8bit_string) - end - end - - def test_different_hash - designers = { - "Ruby" => "Matz", - "Lisp" => "John McCarthy", - } - categories = { - "LL" => ["Ruby", "Python"], - "Heavy" => ["C", "C++"], - } - message = <<-EOM.chomp -<{"Lisp"=>"John McCarthy", "Ruby"=>"Matz"}> expected but was -<{"Heavy"=>["C", "C++"], "LL"=>["Ruby", "Python"]}>. -EOM - check_fail(message) do - assert_equal(designers, categories) - end - end - - def test_recursive_hash - alice = {"name" => "Alice"} - bob = {"name" => "Bob"} - alice["followers"] = [bob] - bob["followers"] = [alice] - message = <<-EOM.chomp -<{"followers"=>[{"followers"=>[{...}], "name"=>"Bob"}], "name"=>"Alice"}> expected but was -<{"followers"=>[{"followers"=>[{...}], "name"=>"Alice"}], "name"=>"Bob"}>. - -diff: -- {"followers"=>[{"followers"=>[{...}], "name"=>"Bob"}], "name"=>"Alice"} -? ----------------- -+ {"followers"=>[{"followers"=>[{...}], "name"=>"Alice"}], "name"=>"Bob"} -? +++++++++++++++++ -EOM - check_fail(message) do - assert_equal(alice, bob) - end - end - - def test_numeric - numeric_family_class = Class.new(Numeric) do - def inspect - "inspect is called" - end - - def to_s - "to_s is called" - end - end - numeric = numeric_family_class.new - - message = <<-MESSAGE.chomp - expected but was -<"must be failed">. - MESSAGE - check_fail(message) do - assert_equal(numeric, "must be failed") - end - end - end - end - - def test_assert_raise_success - return_value = nil - check_nothing_fails(true) do - return_value = assert_raise(RuntimeError) do - raise "Error" - end - end - check(return_value.kind_of?(Exception), - "Should have returned the exception " + - "from a successful assert_raise") - check(return_value.message == "Error", - "Should have returned the correct exception " + - "from a successful assert_raise") - - check_nothing_fails(true) do - assert_raise(ArgumentError, "successful assert_raise") do - raise ArgumentError.new("Error") - end - end - - check_nothing_fails(true) do - assert_raise(RuntimeError) do - raise "Error" - end - end - - check_nothing_fails(true) do - assert_raise(RuntimeError, "successful assert_raise") do - raise "Error" - end - end - - check_nothing_fails(true) do - assert_raise do - raise Exception, "Any exception" - end - end - end - - def test_assert_raise_fail - check_fail(" exception was expected but none was thrown.") do - assert_raise(RuntimeError) do - 1 + 1 - end - end - - message = <<-EOM.chomp -failed assert_raise. - exception expected but was -)>. -EOM - check_fail_exception(message) do - assert_raise(ArgumentError, "failed assert_raise") do - raise "Error" - end - end - - message = <<-EOM - must be a subclass of Exception, an object of Exception subclasses or a Module. -EOM - check_fail(message.chomp) do - assert_nothing_raised(Object) do - 1 + 1 - end - end - end - - def test_assert_raise_module - exceptions = [ArgumentError, TypeError] - modules = [Math, Comparable] - rescues = exceptions + modules - - exceptions.each do |exc| - return_value = nil - check_nothing_fails(true) do - return_value = assert_raise(*rescues) do - raise exc, "Error" - end - end - check(return_value.instance_of?(exc), - "Should have returned #{exc} but was #{return_value.class}") - check(return_value.message == "Error", - "Should have returned the correct exception " + - "from a successful assert_raise") - end - - modules.each do |mod| - return_value = nil - check_nothing_fails(true) do - return_value = assert_raise(*rescues) do - raise Exception.new("Error").extend(mod) - end - end - check(mod === return_value, - "Should have returned #{mod}") - check(return_value.message == "Error", - "Should have returned the correct exception " + - "from a successful assert_raise") - end - - check_fail("<[ArgumentError, TypeError, Math, Comparable]> exception " + - "was expected but none was thrown.") do - assert_raise(*rescues) do - 1 + 1 - end - end - - message = <<-EOM.chomp -failed assert_raise. -<[ArgumentError, TypeError]> exception expected but was -)>. -EOM - check_fail_exception(message) do - assert_raise(ArgumentError, TypeError, "failed assert_raise") do - raise "Error" - end - end - end - - def test_assert_raise_instance - return_value = nil - check_nothing_fails(true) do - return_value = assert_raise(RuntimeError.new("Error")) do - raise "Error" - end - end - check(return_value.kind_of?(Exception), - "Should have returned the exception " + - "from a successful assert_raise") - check(return_value.message == "Error", - "Should have returned the correct exception " + - "from a successful assert_raise") - - message = <<-EOM.chomp -)> exception expected but was -)>. - -diff: -- RuntimeError() -? ^^^ -+ RuntimeError() -? ^^^^^ -EOM - check_fail_exception(message) do - return_value = assert_raise(RuntimeError.new("XXX")) do - raise "Error" - end - end - - different_error_class = Class.new(StandardError) - message = <<-EOM.chomp -<#{different_error_class.inspect}()> exception expected but was -)>. -EOM - check_fail_exception(message) do - assert_raise(different_error_class.new("Error")) do - raise "Error" - end - end - - different_error = different_error_class.new("Error") - def different_error.inspect - "DifferentError: \"Error\"" - end - message = <<-EOM.chomp - exception expected but was -)>. -EOM - check_fail_exception(message) do - assert_raise(different_error) do - raise "Error" - end - end - - check_nothing_fails(true) do - assert_raise(different_error_class.new("Error"), - RuntimeError.new("Error"), - RuntimeError.new("XXX")) do - raise "Error" - end - end - end - - def test_assert_raise_jruby - omit("For JRuby") unless Object.const_defined?(:Java) - - exception = Java::JavaLang::StringIndexOutOfBoundsException - - return_value = nil - check_nothing_fails(true) do - return_value = assert_raise(exception) do - Java::JavaLang::String.new("abc").char_at(4) - end - end - check(return_value.instance_of?(exception), - "Should have returned #{exception} but was #{return_value.class}") - end - - def test_assert_instance_of - check_nothing_fails { - assert_instance_of(String, "string") - } - check_nothing_fails { - assert_instance_of(String, "string", "successful assert_instance_of") - } - check_nothing_fails { - assert_instance_of(String, "string", "successful assert_instance_of") - } - check_fail(%Q{<"string"> was expected to be instance_of?\n but was\n.}) { - assert_instance_of(Hash, "string") - } - check_fail(%Q{failed assert_instance_of.\n<"string"> was expected to be instance_of?\n but was\n.}) { - assert_instance_of(Hash, "string", "failed assert_instance_of") - } - - check_nothing_fails do - assert_instance_of([Class, NilClass], Array) - end - check_fail(%Q{<"string"> was expected to be instance_of?\n[, ] but was\n.}) do - assert_instance_of([Class, NilClass], "string") - end - check_fail(%Q{ was expected to be instance_of?\n[, ] but was\n.}) do - assert_instance_of([Module, NilClass], Array) - end - end - - def test_assert_not_instance_of - check_nothing_fails { - assert_not_instance_of(NilClass, "string") - } - check_nothing_fails { - assert_not_instance_of(NilClass, "string", "successful assert_instance_of") - } - check_fail(%Q{<"string"> was expected to not be instance_of?\n but was.}) { - assert_not_instance_of(String, "string") - } - check_fail(%Q{failed assert.\n<"string"> was expected to not be instance_of?\n but was.}) { - assert_not_instance_of(String, "string", "failed assert") - } - - check_nothing_fails do - assert_not_instance_of([Module, NilClass], Array) - end - check_fail(%Q{ was expected to not be instance_of?\n[, ] but was.}) do - assert_not_instance_of([Class, NilClass], Array) - end - check_fail(%Q{<"str"> was expected to not be instance_of?\n[, ] but was.}) do - assert_not_instance_of([Numeric, String], 'str') - end - end - - def test_assert_nil - check_nothing_fails { - assert_nil(nil) - } - check_nothing_fails { - assert_nil(nil, "successful assert_nil") - } - check_nothing_fails { - assert_nil(nil, "successful assert_nil") - } - check_fail(%Q{<"string"> was expected to be nil.}) { - assert_nil("string") - } - check_fail(%Q{failed assert_nil.\n<"string"> was expected to be nil.}) { - assert_nil("string", "failed assert_nil") - } - end - - def test_assert_not_nil - check_nothing_fails{assert_not_nil(false)} - check_nothing_fails{assert_not_nil(false, "message")} - check_fail(" was expected to not be nil."){assert_not_nil(nil)} - check_fail("message.\n was expected to not be nil.") {assert_not_nil(nil, "message")} - end - - def test_assert_kind_of - check_nothing_fails { - assert_kind_of(Module, Array) - } - check_nothing_fails { - assert_kind_of(Object, "string", "successful assert_kind_of") - } - check_nothing_fails { - assert_kind_of(String, "string", "successful assert_kind_of") - } - check_nothing_fails { - assert_kind_of(Comparable, 1) - } - check_fail(%Q{<"string"> was expected to be kind_of?\n but was\n.}) { - assert_kind_of(Class, "string") - } - check_fail(%Q{failed assert_kind_of.\n<"string"> was expected to be kind_of?\n but was\n.}) { - assert_kind_of(Class, "string", "failed assert_kind_of") - } - - check_nothing_fails do - assert_kind_of([Class, NilClass], Array) - end - check_fail(%Q{<"string"> was expected to be kind_of?\n[, ] but was\n.}) do - assert_kind_of([Class, NilClass], "string") - end - end - - def test_assert_not_kind_of - check_nothing_fails { - assert_not_kind_of(Class, 42) - } - check_nothing_fails { - assert_not_kind_of(Symbol, "string", "successful assert_not_kind_of") - } - check_nothing_fails { - assert_not_kind_of(Integer, 1.1) - } - check_fail(%Q{<1> was expected to not be kind_of?\n but was.}) { - assert_not_kind_of(Integer, 1) - } - check_fail(%Q{failed assert_not_kind_of.\n<"string"> was expected to not be kind_of?\n but was.}) { - assert_not_kind_of(String, "string", "failed assert_not_kind_of") - } - - check_nothing_fails do - assert_not_kind_of([String, NilClass], 100) - end - check_fail(%Q{ was expected to not be kind_of?\n[, ] but was.}) do - assert_not_kind_of([Class, NilClass], Array) - end - end - - def test_assert_match - check_nothing_fails { - assert_match(/strin./, "string") - } - check_nothing_fails { - assert_match("strin", "string") - } - check_nothing_fails { - assert_match(/strin./, "string", "successful assert_match") - } - check_nothing_fails { - assert_match(/strin./, "string", "successful assert_match") - } - check_fail(%Q{ was expected to be =~\n<"string">.}) { - assert_match(/slin./, "string") - } - check_fail(%Q{ was expected to be =~\n<"string">.}) { - assert_match("strin.", "string") - } - check_fail(%Q{failed assert_match.\n was expected to be =~\n<"string">.}) { - assert_match(/slin./, "string", "failed assert_match") - } - end - - def test_assert_same - thing = "thing" - check_nothing_fails { - assert_same(thing, thing) - } - check_nothing_fails { - assert_same(thing, thing, "successful assert_same") - } - check_nothing_fails { - assert_same(thing, thing, "successful assert_same") - } - thing2 = thing.dup - check_fail(%Q{<"thing">\nwith id <#{thing.__id__}> was expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) { - assert_same(thing, thing2) - } - check_fail(%Q{failed assert_same.\n<"thing">\nwith id <#{thing.__id__}> was expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) { - assert_same(thing, thing2, "failed assert_same") - } - end - - def test_assert_nothing_raised - check_nothing_fails(:dont_care) { - assert_nothing_raised { - 1 + 1 - } - } - check_nothing_fails(:dont_care) { - assert_nothing_raised("successful assert_nothing_raised") { - 1 + 1 - } - } - check_nothing_fails(:dont_care) { - assert_nothing_raised("successful assert_nothing_raised") { - 1 + 1 - } - } - check_nothing_fails(:dont_care) { - begin - assert_nothing_raised(RuntimeError, StandardError, Comparable, "successful assert_nothing_raised") { - raise ZeroDivisionError.new("ArgumentError") - } - rescue ZeroDivisionError - end - } - expected_message = - " must be a subclass of Exception, " + - "an object of Exception subclasses or a Module." - check_fail(expected_message) { - assert_nothing_raised(Object) { - 1 + 1 - } - } - expected_message = <<-EOM.chomp -Exception raised: -RuntimeError() -EOM - check_fail_exception(expected_message) { - assert_nothing_raised { - raise "Error" - } - } - expected_message = <<-EOM.chomp -failed assert_nothing_raised. -Exception raised: -RuntimeError() -EOM - check_fail_exception(expected_message) { - assert_nothing_raised("failed assert_nothing_raised") { - raise "Error" - } - } - expected_message = <<-EOM.chomp -Exception raised: -RuntimeError() -EOM - check_fail_exception(expected_message) { - assert_nothing_raised(StandardError, RuntimeError) { - raise "Error" - } - } - check_fail("Failure.") do - assert_nothing_raised do - flunk("Failure") - end - end - end - - def test_flunk - check_fail("Flunked.") { - flunk - } - check_fail("flunk message.") { - flunk("flunk message") - } - end - - def test_assert_not_same - thing = "thing" - thing2 = thing.dup - check_nothing_fails { - assert_not_same(thing, thing2) - } - check_nothing_fails { - assert_not_same(thing, thing2, "message") - } - check_fail(%Q{<"thing">\nwith id <#{thing.__id__}> was expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) { - assert_not_same(thing, thing) - } - check_fail(%Q{message.\n<"thing">\nwith id <#{thing.__id__}> was expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) { - assert_not_same(thing, thing, "message") - } - end - - def test_assert_not_equal - check_nothing_fails { - assert_not_equal("string1", "string2") - } - check_nothing_fails { - assert_not_equal("string1", "string2", "message") - } - check_fail(%Q{<"string"> was expected to be != to\n<"string">.}) { - assert_not_equal("string", "string") - } - check_fail(%Q{message.\n<"string"> was expected to be != to\n<"string">.}) { - assert_not_equal("string", "string", "message") - } - end - - def test_assert_not_match_pass - check_nothing_fails do - assert_not_match(/sling/, "string") - end - end - - def test_assert_not_match_pass_with_message - check_nothing_fails do - assert_not_match(/sling/, "string", "message") - end - end - - def test_assert_not_match_fail_not_regexp - check_fail(" in assert_not_match(, ...) " + - "should be a Regexp.\n" + - "<\"asdf\"> was expected to be instance_of?\n" + - " but was\n" + - ".") do - assert_not_match("asdf", "asdf") - end - end - - def test_assert_not_match_fail_match - check_fail(" was expected to not match\n" + - "<\"string\">.") do - assert_not_match(/string/, "string") - end - end - - def test_assert_not_match_fail_match_with_message - check_fail("message.\n" + - " was expected to not match\n" + - "<\"string\">.") do - assert_not_match(/string/, "string", "message") - end - end - - def test_assert_no_match - check_nothing_fails{assert_no_match(/sling/, "string")} - check_nothing_fails{assert_no_match(/sling/, "string", "message")} - check_fail(%Q{The first argument to assert_no_match should be a Regexp.\n<"asdf"> was expected to be instance_of?\n but was\n.}) do - assert_no_match("asdf", "asdf") - end - check_fail(%Q{ was expected to not match\n<"string">.}) do - assert_no_match(/string/, "string") - end - check_fail(%Q{message.\n was expected to not match\n<"string">.}) do - assert_no_match(/string/, "string", "message") - end - end - - def test_assert_throw - check_nothing_fails do - assert_throw(:thing, "message") do - throw :thing - end - end - - tag = :thing2 - check_fail("message.\n" + - "<:thing> was expected to be thrown but\n" + - "<#{inspect_tag(tag)}> was thrown.") do - assert_throw(:thing, "message") do - throw :thing2 - end - end - check_fail("message.\n" + - "<:thing> should have been thrown.") do - assert_throw(:thing, "message") do - 1 + 1 - end - end - end - - def test_assert_nothing_thrown - check_nothing_fails do - assert_nothing_thrown("message") do - 1 + 1 - end - end - - tag = :thing - inspected = inspect_tag(tag) - check_fail("message.\n" + - "<#{inspected}> was thrown when nothing was expected.") do - assert_nothing_thrown("message") do - throw tag - end - end - end - - def test_assert_operator - check_nothing_fails { - assert_operator("thing", :==, "thing", "message") - } - check_fail(%Q{<0.15>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to?(:to_str).}) do - assert_operator("thing", 0.15, "thing") - end - check_fail(%Q{message.\n<"thing1"> was expected to be\n==\n<"thing2">.}) { - assert_operator("thing1", :==, "thing2", "message") - } - end - - def test_assert_not_operator - check_nothing_fails { - assert_not_operator("thing", :==, "Thing", "message") - } - check_fail(%Q{<42>\ngiven as the operator for #assert_not_operator must be a Symbol or #respond_to?(:to_str).}) do - assert_not_operator("thing", 42, "message") - end - check_fail(%Q{message.\n<0> was expected to not be\n==\n<0.0>.}) { - assert_not_operator(0, :==, 0.0, "message") - } - end - - def test_assert_respond_to - check_nothing_fails { - assert_respond_to("thing", :to_s, "message") - } - check_nothing_fails { - assert_respond_to("thing", "to_s", "message") - } - check_fail("<0.15>.kind_of?(Symbol) or\n" + - "<0.15>.respond_to?(:to_str) expected") { - assert_respond_to("thing", 0.15) - } - check_fail("message.\n" + - "<:symbol>.respond_to?(:nonexistence) expected\n" + - "(Class: )") { - assert_respond_to(:symbol, :nonexistence, "message") - } - end - - def test_assert_not_respond_to_pass_symbol - check_nothing_fails do - assert_not_respond_to("thing", :nonexistent, "message") - end - end - - def test_assert_not_respond_to_pass_string - check_nothing_fails do - assert_not_respond_to("thing", :nonexistent, "message") - end - end - - def test_assert_not_respond_to_fail_number - check_fail("<0.15>.kind_of?(Symbol) or\n" + - "<0.15>.respond_to?(:to_str) expected") do - assert_respond_to("thing", 0.15) - end - end - - def tset_assert_not_respond_to_fail_existence - check_fail("message.\n" + - "!<:symbol>.respond_to?(:to_s) expected\n" + - "(Class: )") do - assert_respond_to(:symbol, :to_s, "message") - end - end - - def test_assert_send - object = Object.new - class << object - private - def return_argument(argument, bogus) - return argument - end - end - check_nothing_fails do - assert_send([object, :return_argument, true, "bogus"], "message") - end - - inspected_object = AssertionMessage.convert(object) - expected_message = <<-EOM -message. -<#{inspected_object}> was expected to respond to - with a true value but was -. -EOM - check_fail(expected_message.chomp) do - assert_send([object, :return_argument, false, "bogus"], "message") - end - end - - def test_condition_invariant - object = Object.new - def object.inspect - @changed = true - end - def object.==(other) - @changed ||= false - return (!@changed) - end - check_nothing_fails do - assert_equal(object, object, "message") - end - end - - def test_assert_boolean - check_nothing_fails do - assert_boolean(true) - end - check_nothing_fails do - assert_boolean(false) - end - - check_fail(" or expected but was\n<1>") do - assert_boolean(1) - end - - check_fail(" or expected but was\n") do - assert_boolean(nil) - end - - check_fail("message.\n or expected but was\n<\"XXX\">") do - assert_boolean("XXX", "message") - end - end - - def test_assert_true - check_nothing_fails do - assert_true(true) - end - - check_fail(" expected but was\n") do - assert_true(false) - end - - check_fail(" expected but was\n<1>") do - assert_true(1) - end - - exception = check_fail("message.\n expected but was\n") do - assert_true(nil, "message") - end - assert_equal("message", exception.user_message) - end - - def test_assert_false - check_nothing_fails do - assert_false(false) - end - - check_fail(" expected but was\n") do - assert_false(true) - end - - check_fail(" expected but was\n") do - assert_false(nil) - end - - check_fail("message.\n expected but was\n<:false>") do - assert_false(:false, "message") - end - end - - def test_assert_compare - check_nothing_fails do - assert_compare(1.4, "<", 10.0) - end - - check_nothing_fails do - assert_compare(2, "<=", 2) - end - - check_nothing_fails do - assert_compare(14, ">=", 10.0) - end - - check_nothing_fails do - assert_compare(14, ">", 13.9) - end - - expected_message = <<-EOM -<15> < <10> should be true -<15> was expected to be less than -<10>. -EOM - check_fail(expected_message.chomp) do - assert_compare(15, "<", 10) - end - - expected_message = <<-EOM -<15> <= <10> should be true -<15> was expected to be less than or equal to -<10>. -EOM - check_fail(expected_message.chomp) do - assert_compare(15, "<=", 10) - end - - expected_message = <<-EOM -<10> > <15> should be true -<10> was expected to be greater than -<15>. -EOM - check_fail(expected_message.chomp) do - assert_compare(10, ">", 15) - end - - expected_message = <<-EOM -<10> >= <15> should be true -<10> was expected to be greater than or equal to -<15>. -EOM - check_fail(expected_message.chomp) do - assert_compare(10, ">=", 15) - end - end - - def test_assert_fail_assertion - check_nothing_fails do - assert_fail_assertion do - flunk - end - end - - check_fail("Failed assertion was expected.") do - assert_fail_assertion do - end - end - end - - def test_assert_raise_message - check_nothing_fails do - assert_raise_message("Raise!") do - raise "Raise!" - end - end - - check_nothing_fails do - assert_raise_message("Raise!") do - raise Exception, "Raise!" - end - end - - check_nothing_fails do - assert_raise_message(/raise/i) do - raise "Raise!" - end - end - - expected_message = <<-EOM -<"Expected message"> exception message expected but was -<"Actual message">. -EOM - check_fail(expected_message.chomp) do - assert_raise_message("Expected message") do - raise "Actual message" - end - end - - expected_message = <<-EOM -<"Expected message"> exception message was expected but none was thrown. -EOM - check_fail(expected_message.chomp) do - assert_raise_message("Expected message") do - end - end - end - - def test_assert_raise_kind_of - check_nothing_fails(true) do - assert_raise_kind_of(SystemCallError) do - raise Errno::EACCES - end - end - - expected_message = <<-EOM.chomp - family exception expected but was -)>. -EOM - check_fail_exception(expected_message) do - assert_raise_kind_of(SystemCallError) do - raise RuntimeError, "XXX" - end - end - end - - def test_assert_const_defined - check_nothing_fails do - assert_const_defined(Test, :Unit) - end - - check_nothing_fails do - assert_const_defined(Test, "Unit") - end - - check_fail(".const_defined?(<:Nonexistence>) expected.") do - assert_const_defined(Test, :Nonexistence) - end - end - - def test_assert_not_const_defined - check_nothing_fails do - assert_not_const_defined(Test, :Nonexistence) - end - - check_fail("!.const_defined?(<:Unit>) expected.") do - assert_not_const_defined(Test, :Unit) - end - - check_fail("!.const_defined?(<\"Unit\">) expected.") do - assert_not_const_defined(Test, "Unit") - end - end - - def test_assert_predicate - check_nothing_fails do - assert_predicate([], :empty?) - end - - check_fail("<[1]>.empty? is true value expected but was\n") do - assert_predicate([1], :empty?) - end - - check_fail("<[1]>.respond_to?(:nonexistent?) expected\n" + - "(Class: )") do - assert_predicate([1], :nonexistent?) - end - end - - def test_assert_not_predicate - check_nothing_fails do - assert_not_predicate([1], :empty?) - end - - check_fail("<[]>.empty? is false value expected but was\n") do - assert_not_predicate([], :empty?) - end - - check_fail("<[]>.respond_to?(:nonexistent?) expected\n" + - "(Class: )") do - assert_not_predicate([], :nonexistent?) - end - end - - def test_assert_alias_method - object = Object.new - class << object - def original_method - end - alias_method :alias_method, :original_method - - def other - end - end - - check_nothing_fails do - assert_alias_method(object, :alias_method, :original_method) - end - - check_nothing_fails do - assert_alias_method(object, :original_method, :alias_method) - end - - check_fail("<#{object.method(:other).inspect}> is alias of\n" + - "<#{object.method(:original_method).inspect}> expected") do - assert_alias_method(object, :other, :original_method) - end - - inspected_object = AssertionMessage.convert(object) - check_fail("<#{inspected_object}>.nonexistent doesn't exist\n" + - "(Class: )") do - assert_alias_method(object, :nonexistent, :original_method) - end - - check_fail("<#{inspected_object}>.nonexistent doesn't exist\n" + - "(Class: )") do - assert_alias_method(object, :alias_method, :nonexistent) - end - end - - def test_assert_path_exist - check_nothing_fails do - assert_path_exist(__FILE__) - end - - nonexistent_file = __FILE__ + ".nonexistent" - check_fail("<#{nonexistent_file.inspect}> was expected to exist") do - assert_path_exist(nonexistent_file) - end - end - - def test_assert_path_not_exist - nonexistent_file = __FILE__ + ".nonexistent" - check_nothing_fails do - assert_path_not_exist(nonexistent_file) - end - - check_fail("<#{__FILE__.inspect}> was expected to not exist") do - assert_path_not_exist(__FILE__) - end - end - end - - class TestAssert < TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert(true) - end - end - - def test_pass_neither_false_or_nil - check_nothing_fails do - assert("a") - end - end - - def test_pass_with_message - check_nothing_fails do - assert(true, "successful assert") - end - end - - def test_pass_block - check_nothing_fails do - assert do - true - end - end - end - - def test_fail_nil - check_fail(" is not true.") do - assert(nil) - end - end - - def test_fail_false - check_fail(" is not true.") do - assert(false) - end - end - - def test_fail_false_with_message - check_fail("failed assert.\n" + - " is not true.") do - assert(false, "failed assert") - end - end - - def test_fail_with_assertion_message - check_fail("user message.\n" + - "placeholder <:in> message") do - assert(false, build_message("user message", - "placeholder message", - :in)) - end - end - - def test_fail_block - check_fail(//) do - assert do - 0.odd? - end - end - end - - def test_error_invalid_message_true - check_fail("assertion message must be String, Proc or " + - "Test::Unit::Assertions::AssertionMessage: " + - "()") do - begin - assert(true, true) - rescue ArgumentError - raise AssertionFailedError, $!.message - end - end - end - - def test_error_wrong_number_of_arguments - check_fail("wrong number of arguments (0 for 1..2)") do - begin - assert - rescue ArgumentError - raise AssertionFailedError, $!.message - end - end - end - - class TestBlock < self - def test_with_message - if defined?(PowerAssert) - system_message = <<-MESSAGE.chomp - 1.to_s == "2" - | | - | false - "1" -MESSAGE - else - system_message = " is not true." - end - check_fail("user message.\n#{system_message}") do - assert("user message") do - 1.to_s == "2" - end - end - end - end - end - - class TestRefute < TestCase - include AssertionCheckable - - class TestPass < self - def test_nil - check_nothing_fails do - refute(nil) - end - end - - def test_false - check_nothing_fails do - refute(false) - end - end - - def test_with_message - check_nothing_fails do - refute(nil, "successful refute") - end - end - end - - class TestFailure < self - def test_true - check_fail(" is neither nil or false.") do - refute(true) - end - end - - def test_with_message - check_fail("failed refute.\n" + - " is neither nil or false.") do - refute(true, "failed refute") - end - end - - def test_fail_with_assertion_message - check_fail("user message.\n" + - "placeholder <:in> message") do - refute(true, build_message("user message", - "placeholder message", - :in)) - end - end - - def test_error_invalid_message_true - check_fail("assertion message must be String, Proc or " + - "Test::Unit::Assertions::AssertionMessage: " + - "()") do - begin - refute(true, false) - rescue ArgumentError - raise AssertionFailedError, $!.message - end - end - end - end - end - - class TestAssertInDelta < TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_in_delta(1.4, 1.4, 0) - end - end - - def test_pass_without_delta - check_nothing_fails do - assert_in_delta(1.401, 1.402) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_in_delta(0.5, 0.4, 0.1, "message") - end - end - - def test_pass_float_like_object - check_nothing_fails do - float_thing = Object.new - def float_thing.to_f - 0.2 - end - assert_in_delta(0.1, float_thing, 0.1) - end - end - - def test_pass_string_expected - check_nothing_fails do - assert_in_delta("0.5", 0.4, 0.1) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<0.5> -/+ <0.05> was expected to include\n" + - "<0.4>.\n" + - "\n" + - "Relation:\n" + - "<<0.4> < <0.5>-<0.05>[0.45] <= <0.5>+<0.05>[0.55]>") do - assert_in_delta(0.5, 0.4, 0.05, "message") - end - end - - def test_fail_because_not_float_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The arguments must respond to to_f; " + - "the first float did not.\n" + - "<#{inspected_object}>.respond_to?(:to_f) expected\n" + - "(Class: )") do - assert_in_delta(object, 0.4, 0.1) - end - end - - def test_fail_because_negaitve_delta - check_fail("The delta should not be negative.\n" + - "<-0.1> was expected to be\n>=\n<0.0>.") do - assert_in_delta(0.5, 0.4, -0.1, "message") - end - end - - def test_fail_without_delta - check_fail("<1.402> -/+ <0.001> was expected to include\n" + - "<1.404>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<1.402>-<0.001>[#{1.402 - 0.001}] <= " + - "<1.402>+<0.001>[#{1.402 + 0.001}] < " + - "<1.404>" + - ">") do - assert_in_delta(1.402, 1.404) - end - end - end - - class TestAssertNotInDelta < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_not_in_delta(1.42, 1.44, 0.01) - end - end - - def test_pass_without_delta - check_nothing_fails do - assert_not_in_delta(1.402, 1.404) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_not_in_delta(0.5, 0.4, 0.09, "message") - end - end - - def test_pass_float_like_object - check_nothing_fails do - float_thing = Object.new - def float_thing.to_f - 0.2 - end - assert_not_in_delta(0.1, float_thing, 0.09) - end - end - - def test_pass_string_epxected - check_nothing_fails do - assert_not_in_delta("0.5", 0.4, 0.09) - end - end - - def test_fail - check_fail("<1.4> -/+ <0.11> was expected to not include\n" + - "<1.5>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<1.4>-<0.11>[#{1.4 - 0.11}] <= " + - "<1.5> <= " + - "<1.4>+<0.11>[#{1.4 + 0.11}]" + - ">") do - assert_not_in_delta(1.4, 1.5, 0.11) - end - end - - def test_fail_without_delta - check_fail("<1.402> -/+ <0.001> was expected to not include\n" + - "<1.4021>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<1.402>-<0.001>[#{1.402 - 0.001}] <= " + - "<1.4021> <= " + - "<1.402>+<0.001>[#{1.402 + 0.001}]" + - ">") do - assert_not_in_delta(1.402, 1.4021) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<0.5> -/+ <0.11> was expected to not include\n" + - "<0.4>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<0.5>-<0.11>[0.39] <= " + - "<0.4> <= " + - "<0.5>+<0.11>[0.61]" + - ">") do - assert_not_in_delta(0.5, 0.4, 0.11, "message") - end - end - - def test_fail_because_not_float_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The arguments must respond to to_f; " + - "the first float did not.\n" + - "<#{inspected_object}>.respond_to?(:to_f) expected\n" + - "(Class: )") do - assert_not_in_delta(object, 0.4, 0.1) - end - end - - def test_fail_because_negaitve_delta - check_fail("The delta should not be negative.\n" + - "<-0.11> was expected to be\n>=\n<0.0>.") do - assert_not_in_delta(0.5, 0.4, -0.11, "message") - end - end - end - - class TestAssertInEpsilon < TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_in_epsilon(10000, 9000, 0.1) - end - end - - def test_pass_without_epsilon - check_nothing_fails do - assert_in_epsilon(10000, 9991) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_in_epsilon(10000, 9000, 0.1, "message") - end - end - - def test_pass_float_like_object - check_nothing_fails do - float_thing = Object.new - def float_thing.to_f - 9000.0 - end - assert_in_epsilon(10000, float_thing, 0.1) - end - end - - def test_pass_string_expected - check_nothing_fails do - assert_in_epsilon("10000", 9000, 0.1) - end - end - - def test_pass_zero_expected - check_nothing_fails do - assert_in_epsilon(0, 0.00000001) - end - end - - def test_pass_minus_expected - check_nothing_fails do - assert_in_epsilon(-1, -1) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<10000> -/+ (<10000> * <0.1>)[1000.0] " + - "was expected to include\n" + - "<8999>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<8999> < " + - "<10000>-(<10000>*<0.1>)[9000.0] <= " + - "<10000>+(<10000>*<0.1>)[11000.0]" + - ">") do - assert_in_epsilon(10000, 8999, 0.1, "message") - end - end - - def test_fail_because_not_float_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The arguments must respond to to_f; " + - "the first float did not.\n" + - "<#{inspected_object}>.respond_to?(:to_f) expected\n" + - "(Class: )") do - assert_in_epsilon(object, 9000, 0.1) - end - end - - def test_fail_because_negaitve_epsilon - check_fail("The epsilon should not be negative.\n" + - "<-0.1> was expected to be\n>=\n<0.0>.") do - assert_in_epsilon(10000, 9000, -0.1, "message") - end - end - - def test_fail_without_epsilon - check_fail("<10000> -/+ (<10000> * <0.001>)[10.0] " + - "was expected to include\n" + - "<10011>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<10000>-(<10000>*<0.001>)[9990.0] <= " + - "<10000>+(<10000>*<0.001>)[10010.0] < " + - "<10011>" + - ">") do - assert_in_epsilon(10000, 10011) - end - end - end - - class TestAssertNotInEpsilon < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_not_in_epsilon(10000, 8999, 0.1) - end - end - - def test_pass_without_epsilon - check_nothing_fails do - assert_not_in_epsilon(10000, 9989) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_not_in_epsilon(10000, 8999, 0.1, "message") - end - end - - def test_pass_float_like_object - check_nothing_fails do - float_thing = Object.new - def float_thing.to_f - 8999.0 - end - assert_not_in_epsilon(10000, float_thing, 0.1) - end - end - - def test_pass_string_epxected - check_nothing_fails do - assert_not_in_epsilon("10000", 8999, 0.1) - end - end - - def test_fail - check_fail("<10000> -/+ (<10000> * <0.1>)[1000.0] " + - "was expected to not include\n" + - "<9000>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<10000>-(<10000>*<0.1>)[9000.0] <= " + - "<9000> <= " + - "<10000>+(<10000>*<0.1>)[11000.0]" + - ">") do - assert_not_in_epsilon(10000, 9000, 0.1) - end - end - - def test_fail_without_epsilon - check_fail("<10000> -/+ (<10000> * <0.001>)[10.0] " + - "was expected to not include\n" + - "<9990>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<10000>-(<10000>*<0.001>)[9990.0] <= " + - "<9990> <= " + - "<10000>+(<10000>*<0.001>)[10010.0]" + - ">") do - assert_not_in_epsilon(10000, 9990) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<10000> -/+ (<10000> * <0.1>)[1000.0] " + - "was expected to not include\n" + - "<9000>.\n" + - "\n" + - "Relation:\n" + - "<" + - "<10000>-(<10000>*<0.1>)[9000.0] <= " + - "<9000> <= " + - "<10000>+(<10000>*<0.1>)[11000.0]" + - ">") do - assert_not_in_epsilon(10000, 9000, 0.1, "message") - end - end - - def test_fail_because_not_float_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The arguments must respond to to_f; " + - "the first float did not.\n" + - "<#{inspected_object}>.respond_to?(:to_f) expected\n" + - "(Class: )") do - assert_not_in_epsilon(object, 9000, 0.1) - end - end - - def test_fail_because_negaitve_epsilon - check_fail("The epsilon should not be negative.\n" + - "<-0.1> was expected to be\n>=\n<0.0>.") do - assert_not_in_epsilon(10000, 9000, -0.1, "message") - end - end - end - - class TestAssertInclude < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_include([1, 2, 3], 1) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_include([1, 2, 3], 1, "message") - end - end - - def test_fail - check_fail("<[1, 2, 3]> was expected to include\n" + - "<4>.") do - assert_include([1, 2, 3], 4) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<[1, 2, 3]> was expected to include\n" + - "<4>.") do - assert_include([1, 2, 3], 4, "message") - end - end - - def test_fail_because_not_collection_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The collection must respond to :include?.\n" + - "<#{inspected_object}>.respond_to?(:include?) expected\n" + - "(Class: )") do - assert_include(object, 1) - end - end - end - - class TestAssertNotInclude < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_not_include([1, 2, 3], 5) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_not_include([1, 2, 3], 5, "message") - end - end - - def test_fail - check_fail("<[1, 2, 3]> was expected to not include\n" + - "<2>.") do - assert_not_include([1, 2, 3], 2) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<[1, 2, 3]> was expected to not include\n" + - "<2>.") do - assert_not_include([1, 2, 3], 2, "message") - end - end - - def test_fail_because_not_collection_like_object - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The collection must respond to :include?.\n" + - "<#{inspected_object}>.respond_to?(:include?) expected\n" + - "(Class: )") do - assert_not_include(object, 1) - end - end - end - - class TestAssertEmpty < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_empty([]) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_empty([], "message") - end - end - - def test_fail - check_fail("<[1]> was expected to be empty.") do - assert_empty([1]) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<[1]> was expected to be empty.") do - assert_empty([1], "message") - end - end - - def test_fail_because_no_empty_method - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The object must respond to :empty?.\n" + - "<#{inspected_object}>.respond_to?(:empty?) expected\n" + - "(Class: )") do - assert_empty(object) - end - end - end - - class TestAssertNotEmpty < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_not_empty([1]) - end - end - - def test_pass_with_message - check_nothing_fails do - assert_not_empty([1], "message") - end - end - - def test_fail - check_fail("<[]> was expected to not be empty.") do - assert_not_empty([]) - end - end - - def test_fail_with_message - check_fail("message.\n" + - "<[]> was expected to not be empty.") do - assert_not_empty([], "message") - end - end - - def test_fail_because_no_empty_method - object = Object.new - inspected_object = AssertionMessage.convert(object) - check_fail("The object must respond to :empty?.\n" + - "<#{inspected_object}>.respond_to?(:empty?) expected\n" + - "(Class: )") do - assert_not_empty(object) - end - end - end - - class TestAssertNotSend < Test::Unit::TestCase - include AssertionCheckable - - def test_pass - check_nothing_fails do - assert_not_send([[1, 2], :member?, 4], "message") - end - end - - def test_fail - expected_message = <<-EOM -message. -<[1, 2]> was expected to respond to - with not a true value but was -. -EOM - check_fail(expected_message.chomp) do - assert_not_send([[1, 2], :member?, 2], "message") - end - end - end - - class TestTemplate < Test::Unit::TestCase - def test_incompatible_encoding_by_diff - need_encoding - assert_raise(AssertionFailedError) do - assert_equal("UTF-8ã®æ—¥æœ¬èªž\n" * 3, - ("Shift_JISã®æ—¥æœ¬èªž\n" * 3).force_encoding("ASCII-8BIT")) - end - end - - private - def need_encoding - omit("need Encoding") unless Object.const_defined?(:Encoding) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-attribute-matcher.rb b/ruby/gems/test-unit-3.3.4/test/test-attribute-matcher.rb deleted file mode 100644 index 26b9e5d7e..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-attribute-matcher.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'test/unit' -require 'testunit-test-util' - -class TestAttributeMatcher < Test::Unit::TestCase - include TestUnitTestUtil - - def setup - @test = {} - @matcher = Test::Unit::AttributeMatcher.new(@test) - end - - def test_nonexistent - assert_false(@matcher.match?("nonexistent")) - end - - def test_existent - @test[:existent] = true - assert_true(@matcher.match?("existent")) - end - - def test_and - @test[:slow] = true - @test[:important] = true - assert_true(@matcher.match?("important and slow")) - end - - def test_complex - @test[:tags] = [:slow, :web] - @test[:bug] = "2929" - assert_true(@matcher.match?("tags.include?(:web) or bug == '29'")) - end - - def test_exception - assert_raise(NoMethodError) do - @matcher.match?("nonexistent > 100") - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-attribute.rb b/ruby/gems/test-unit-3.3.4/test/test-attribute.rb deleted file mode 100644 index 280be9e6e..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-attribute.rb +++ /dev/null @@ -1,123 +0,0 @@ -class TestUnitAttribute < Test::Unit::TestCase - class TestStack < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - class Stack - def initialize - @data = [] - end - - def push(data) - @data.push(data) - end - - def peek - @data[-2] - end - - def empty? - @data.empty? - end - - def size - @data.size + 11 - end - end - - def setup - @stack = Stack.new - end - - attribute :category, :accessor - def test_peek - @stack.push(1) - @stack.push(2) - assert_equal(2, @stack.peek) - end - - attribute :bug, 1234 - def test_bug_1234 - assert_equal(0, @stack.size) - end - - def test_no_attributes - assert(@stack.empty?) - @stack.push(1) - assert(!@stack.empty?) - assert_equal(1, @stack.size) - end - end - - def test_set_attributes - test_for_accessor_category = TestStack.new("test_peek") - assert_equal({"category" => :accessor}, - test_for_accessor_category.attributes) - - test_for_bug_1234 = TestStack.new("test_bug_1234") - assert_equal({"bug" => 1234}, test_for_bug_1234.attributes) - - test_no_attributes = TestStack.new("test_no_attributes") - assert_equal({}, test_no_attributes.attributes) - end - - def test_callback - changed_attributes = [] - observer = Proc.new do |test_case, key, old_value, value, method_name| - changed_attributes << [test_case, key, old_value, value, method_name] - end - - test_case = Class.new(TestStack) do - register_attribute_observer(:bug, &observer) - attribute("bug", 9876, "test_bug_1234") - attribute(:description, "Test for peek", "test_peek") - attribute(:bug, 29, "test_peek") - end - - assert_equal([ - [test_case, "bug", 1234, 9876, "test_bug_1234"], - [test_case, "bug", nil, 29, "test_peek"], - ], - changed_attributes) - end - - def test_attributes_with_prepended_module - omit("Module#prepend is needed") unless Module.respond_to?(:prepend, true) - test_case = Class.new(TestStack) do - prepend Module.new - end - assert_equal({ - "category" => :accessor, - }, - test_case.attributes("test_peek")) - end - - class TestDescription < self - def test_decoration_style - test_case = Class.new(TestStack) do - description "Test for push" - def test_push - end - end - - test_push = test_case.new("test_push") - assert_equal({"description" => "Test for push"}, - test_push.attributes) - end - - def test_explicit_test_name_style - test_case = Class.new(TestStack) do - def test_push - end - description "Test for push", :test_push - end - - test_push = test_case.new("test_push") - assert_equal({"description" => "Test for push"}, - test_push.attributes) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-code-snippet.rb b/ruby/gems/test-unit-3.3.4/test/test-code-snippet.rb deleted file mode 100644 index c42b9fa41..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-code-snippet.rb +++ /dev/null @@ -1,79 +0,0 @@ -# coding: utf-8 - -require "test-unit" -require "testunit-test-util" - -class TestCodeSnippet < Test::Unit::TestCase - include TestUnitTestUtil - - class TestJRuby < self - def test_error_inside_jruby - jruby_only_test - - backtrace = backtrace_from_jruby - no_rb_entries = backtrace.find_all do |(file, _, _)| - File.extname(file) != ".rb" - end - - fetcher = Test::Unit::CodeSnippetFetcher.new - snippets = no_rb_entries.collect do |(file, line, _)| - fetcher.fetch(file, line) - end - assert_equal([[]] * no_rb_entries.size, - snippets) - end - - private - def backtrace_from_jruby - begin - java.util.Vector.new(-1) - rescue Exception - $@.collect do |entry| - entry.split(/:/, 3) - end - else - flunk("failed to raise an exception from JRuby.") - end - end - end - - class TestDefaultExternal < self - def suppress_warning - verbose = $VERBOSE - begin - $VERBOSE = false - yield - ensure - $VERBOSE = verbose - end - end - - def setup - suppress_warning do - @default_external = Encoding.default_external - end - @fetcher = Test::Unit::CodeSnippetFetcher.new - end - - def teardown - suppress_warning do - Encoding.default_external = @default_external - end - end - - def test_windows_31j - source = Tempfile.new(["test-code-snippet", ".rb"]) - source.puts(<<-SOURCE) -puts("ã‚ã„ã†ãˆãŠ") - SOURCE - source.flush - suppress_warning do - Encoding.default_external = "Windows-31J" - end - assert_equal([ - [1, "puts(\"ã‚ã„ã†ãˆãŠ\")", {:target_line? => false}], - ], - @fetcher.fetch(source.path, 0)) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-color-scheme.rb b/ruby/gems/test-unit-3.3.4/test/test-color-scheme.rb deleted file mode 100644 index ee0700997..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-color-scheme.rb +++ /dev/null @@ -1,82 +0,0 @@ -class TestUnitColorScheme < Test::Unit::TestCase - def test_register - inverted_scheme_spec = { - "success" => {:name => "red"}, - "failure" => {:name => "green"}, - } - Test::Unit::ColorScheme["inverted"] = inverted_scheme_spec - assert_equal({ - "success" => color("red"), - "failure" => color("green"), - }, - Test::Unit::ColorScheme["inverted"].to_hash) - end - - def test_new_with_colors - scheme = Test::Unit::ColorScheme.new(:success => color("blue"), - "failure" => color("green", - :underline => true)) - assert_equal({ - "success" => color("blue"), - "failure" => color("green", :underline => true), - }, - scheme.to_hash) - end - - def test_new_with_spec - scheme = Test::Unit::ColorScheme.new(:success => { - :name => "blue", - :bold => true - }, - "failure" => {:name => "green"}) - assert_equal({ - "success" => color("blue", :bold => true), - "failure" => color("green"), - }, - scheme.to_hash) - end - - private - def color(name, options={}) - Test::Unit::Color.new(name, options) - end - - class TestFor8Colors < self - def setup - @original_term, ENV["TERM"] = ENV["TERM"], nil - @original_color_term, ENV["COLORTERM"] = ENV["COLORTERM"], nil - ENV["TERM"] = "xterm" - end - - def teardown - ENV["TERM"] = @original_term - ENV["COLORTERM"] = @original_color_term - end - - def test_default - expected_schema_keys = [ - "pass", - "pass-marker", - "failure", - "failure-marker", - "pending", - "pending-marker", - "omission", - "omission-marker", - "notification", - "notification-marker", - "error", - "error-marker", - "case", - "suite", - "diff-inserted-tag", - "diff-deleted-tag", - "diff-difference-tag", - "diff-inserted", - "diff-deleted", - ] - assert_equal(expected_schema_keys.sort, - Test::Unit::ColorScheme.default.to_hash.keys.sort) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-color.rb b/ruby/gems/test-unit-3.3.4/test/test-color.rb deleted file mode 100644 index 63698bfbc..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-color.rb +++ /dev/null @@ -1,47 +0,0 @@ -class TestUnitColor < Test::Unit::TestCase - def test_color_escape_sequence - assert_escape_sequence(["31"], color("red")) - assert_escape_sequence(["32", "1"], color("green", :bold => true)) - assert_escape_sequence(["0"], color("reset")) - assert_escape_sequence(["45"], color("magenta", :background => true)) - end - - def test_mix_color_escape_sequence - assert_escape_sequence(["34", "1"], - mix_color([color("blue"), - color("none", :bold => true)])) - assert_escape_sequence(["34", "1", "4"], - mix_color([color("blue"), - color("none", :bold => true)]) + - color("none", :underline => true)) - assert_escape_sequence(["34", "1", "4"], - color("blue") + - color("none", :bold => true) + - color("none", :underline => true)) - end - - def test_equal - red = color("red") - red_bold = color("red", :bold => true) - - assert_operator(red, :==, red) - assert_not_equal(red, nil) - assert_equal(red, color("red")) - assert_not_equal(red, red_bold) - end - - private - def color(name, options={}) - Test::Unit::Color.new(name, options) - end - - def mix_color(colors) - Test::Unit::MixColor.new(colors) - end - - def assert_escape_sequence(expected, color) - assert_equal(expected, color.sequence) - assert_match(/\e\[(?:\d+;)*\d+m/, color.escape_sequence) - assert_equal(expected, color.escape_sequence[2..-2].split(";")) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-data.rb b/ruby/gems/test-unit-3.3.4/test/test-data.rb deleted file mode 100644 index 7a129b05a..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-data.rb +++ /dev/null @@ -1,419 +0,0 @@ -require "testunit-test-util" - -class TestData < Test::Unit::TestCase - class Calc - def initialize - end - - def plus(augend, addend) - augend + addend - end - end - - class TestCalc < Test::Unit::TestCase - @@testing = false - - class << self - def testing=(testing) - @@testing = testing - end - end - - def valid? - @@testing - end - - def setup - @calc = Calc.new - end - - class TestDataSet < TestCalc - data("positive positive" => {:expected => 4, :augend => 3, :addend => 1}, - "positive negative" => {:expected => -1, :augend => 1, :addend => -2}) - def test_plus(data) - assert_equal(data[:expected], - @calc.plus(data[:augend], data[:addend])) - end - end - - class TestNData < TestCalc - data("positive positive", {:expected => 4, :augend => 3, :addend => 1}) - data("positive negative", {:expected => -1, :augend => 1, :addend => -2}) - def test_plus(data) - assert_equal(data[:expected], - @calc.plus(data[:augend], data[:addend])) - end - end - - class TestDynamicDataSet < TestCalc - DATA_PROC = lambda do - data_set = {} - data_set["positive positive"] = { - :expected => 3, - :augend => 1, - :addend => 2 - } - data_set["positive negative"] = { - :expected => -1, - :augend => 1, - :addend => -2 - } - data_set - end - - data(&DATA_PROC) - def test_plus(data) - assert_equal(data[:expected], - @calc.plus(data[:augend], data[:addend])) - end - end - - class TestLoadDataSet < TestCalc - extend TestUnitTestUtil - load_data(fixture_file_path("plus.csv")) - def test_plus(data) - assert_equal(data["expected"], - @calc.plus(data["augend"], data["addend"])) - end - end - - class TestSuperclass < TestCalc - data("positive positive" => {:expected => 4, :augend => 3, :addend => 1}, - "positive negative" => {:expected => -1, :augend => 1, :addend => -2}) - def test_plus(data) - assert_equal(data[:expected], - @calc.plus(data[:augend], data[:addend])) - end - - class TestNormalTestInSubclass < self - def test_plus - assert_equal(2, @calc.plus(1, 1)) - end - end - end - - class TestMethod < TestCalc - def data_test_plus - { - "positive positive" => {:expected => 4, :augend => 3, :addend => 1}, - "positive negative" => {:expected => -1, :augend => 1, :addend => -2}, - } - end - - def test_plus(data) - assert_equal(data[:expected], - @calc.plus(data[:augend], data[:addend])) - end - end - - class TestPatterns < TestCalc - data(:x, [-1, 1, 0]) - data(:y, [-100, 100]) - data(:z, ["a", "b", "c"]) - def test_use_data(data) - end - end - - class TestPatternsKeep < TestCalc - data(:x, [-1, 1, 0], keep: true) - data(:y, [-100, 100]) - data(:z, ["a", "b", "c"], keep: true) - def test_use_data(data) - end - - def test_use_data_keep(data) - end - end - - class TestPatternsGroup < TestCalc - data(:a, [-1, 1, 0], group: 1) - data(:b, [:a, :b], group: 1) - data(:x, [2, 9], group: :z) - data(:y, ["a", "b", "c"], group: :z) - def test_use_data(data) - end - end - end - - def setup - TestCalc.testing = true - end - - def teardown - TestCalc.testing = false - end - - def test_data_no_arguments_without_block - assert_raise(ArgumentError) do - self.class.data - end - end - - data("data set", - { - :test_case => TestCalc::TestDataSet, - :data_sets => [ - { - "positive positive" => { - :expected => 4, - :augend => 3, - :addend => 1, - }, - "positive negative" => { - :expected => -1, - :augend => 1, - :addend => -2, - }, - }, - ], - }) - data("n-data", - { - :test_case => TestCalc::TestNData, - :data_sets => [ - { - "positive positive" => { - :expected => 4, - :augend => 3, - :addend => 1, - }, - }, - { - "positive negative" => { - :expected => -1, - :augend => 1, - :addend => -2, - }, - }, - ], - }) - data("dynamic-data-set", - { - :test_case => TestCalc::TestDynamicDataSet, - :data_sets => [TestCalc::TestDynamicDataSet::DATA_PROC], - }) - data("load-data-set", - { - :test_case => TestCalc::TestLoadDataSet, - :data_sets => [ - { - "positive positive" => { - "expected" => 4, - "augend" => 3, - "addend" => 1, - }, - }, - { - "positive negative" => { - "expected" => -1, - "augend" => 1, - "addend" => -2, - }, - }, - ], - }) - def test_data(data) - test_plus = data[:test_case].new("test_plus") - data_sets = Test::Unit::DataSets.new - data[:data_sets].each do |data_set| - data_sets.add(data_set) - end - assert_equal(data_sets, test_plus[:data]) - end - - def test_data_patterns - test = TestCalc::TestPatterns.new("test_use_data") - data_sets = Test::Unit::DataSets.new - data_sets << [:x, [-1, 1, 0]] - data_sets << [:y, [-100, 100]] - data_sets << [:z, ["a", "b", "c"]] - assert_equal(data_sets, test[:data]) - end - - def test_data_patterns_keep - test = TestCalc::TestPatternsKeep.new("test_use_data_keep") - data_sets = Test::Unit::DataSets.new - data_sets.add([:x, [-1, 1, 0]], {keep: true}) - data_sets.add([:z, ["a", "b", "c"]], {keep: true}) - assert_equal(data_sets, test[:data]) - end - - data("data set" => TestCalc::TestDataSet, - "n-data" => TestCalc::TestNData, - "dynamic-data-set" => TestCalc::TestDynamicDataSet, - "load-data-set" => TestCalc::TestLoadDataSet) - def test_suite(test_case) - suite = test_case.suite - assert_equal(["test_plus[positive negative](#{test_case.name})", - "test_plus[positive positive](#{test_case.name})"], - suite.tests.collect {|test| test.name}.sort) - end - - def test_suite_patterns - test_case = TestCalc::TestPatterns - suite = test_case.suite - assert_equal([ - "test_use_data[x: -1, y: -100, z: \"a\"](#{test_case.name})", - "test_use_data[x: -1, y: -100, z: \"b\"](#{test_case.name})", - "test_use_data[x: -1, y: -100, z: \"c\"](#{test_case.name})", - "test_use_data[x: -1, y: 100, z: \"a\"](#{test_case.name})", - "test_use_data[x: -1, y: 100, z: \"b\"](#{test_case.name})", - "test_use_data[x: -1, y: 100, z: \"c\"](#{test_case.name})", - "test_use_data[x: 0, y: -100, z: \"a\"](#{test_case.name})", - "test_use_data[x: 0, y: -100, z: \"b\"](#{test_case.name})", - "test_use_data[x: 0, y: -100, z: \"c\"](#{test_case.name})", - "test_use_data[x: 0, y: 100, z: \"a\"](#{test_case.name})", - "test_use_data[x: 0, y: 100, z: \"b\"](#{test_case.name})", - "test_use_data[x: 0, y: 100, z: \"c\"](#{test_case.name})", - "test_use_data[x: 1, y: -100, z: \"a\"](#{test_case.name})", - "test_use_data[x: 1, y: -100, z: \"b\"](#{test_case.name})", - "test_use_data[x: 1, y: -100, z: \"c\"](#{test_case.name})", - "test_use_data[x: 1, y: 100, z: \"a\"](#{test_case.name})", - "test_use_data[x: 1, y: 100, z: \"b\"](#{test_case.name})", - "test_use_data[x: 1, y: 100, z: \"c\"](#{test_case.name})", - ], - suite.tests.collect {|test| test.name}.sort) - end - - def test_suite_patterns_group - test_case = TestCalc::TestPatternsGroup - suite = test_case.suite - assert_equal([ - "test_use_data[group: 1, a: -1, b: :a](#{test_case.name})", - "test_use_data[group: 1, a: -1, b: :b](#{test_case.name})", - "test_use_data[group: 1, a: 0, b: :a](#{test_case.name})", - "test_use_data[group: 1, a: 0, b: :b](#{test_case.name})", - "test_use_data[group: 1, a: 1, b: :a](#{test_case.name})", - "test_use_data[group: 1, a: 1, b: :b](#{test_case.name})", - "test_use_data[group: :z, x: 2, y: \"a\"](#{test_case.name})", - "test_use_data[group: :z, x: 2, y: \"b\"](#{test_case.name})", - "test_use_data[group: :z, x: 2, y: \"c\"](#{test_case.name})", - "test_use_data[group: :z, x: 9, y: \"a\"](#{test_case.name})", - "test_use_data[group: :z, x: 9, y: \"b\"](#{test_case.name})", - "test_use_data[group: :z, x: 9, y: \"c\"](#{test_case.name})", - ], - suite.tests.collect {|test| test.name}.sort) - end - - data("data set" => TestCalc::TestDataSet, - "n-data" => TestCalc::TestNData, - "dynamic-data-set" => TestCalc::TestDynamicDataSet, - "load-data-set" => TestCalc::TestLoadDataSet, - "superclass" => TestCalc::TestSuperclass, - "method" => TestCalc::TestMethod) - def test_run(test_case) - result = _run_test(test_case) - assert_equal("2 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, " \ - "0 omissions, 0 notifications", result.to_s) - end - - def test_run_normal_test_in_subclass - result = _run_test(TestCalc::TestSuperclass::TestNormalTestInSubclass) - assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \ - "0 omissions, 0 notifications", result.to_s) - end - - data("data set" => TestCalc::TestDataSet, - "n-data" => TestCalc::TestNData, - "dynamic-data-set" => TestCalc::TestDynamicDataSet, - "load-data-set" => TestCalc::TestLoadDataSet) - def test_equal(test_case) - suite = test_case.suite - positive_positive_test = suite.tests.find do |test| - test.data_label == "positive positive" - end - suite.tests.delete(positive_positive_test) - assert_equal(["test_plus[positive negative](#{test_case.name})"], - suite.tests.collect {|test| test.name}.sort) - end - - data("true" => {:expected => true, :target => "true"}, - "false" => {:expected => false, :target => "false"}, - "integer" => {:expected => 1, :target => "1"}, - "float" => {:expected => 1.5, :target => "1.5"}, - "string" => {:expected => "hello", :target => "hello"}) - def test_normalize_value(data) - loader = Test::Unit::Data::ClassMethods::Loader.new(self) - assert_equal(data[:expected], loader.__send__(:normalize_value, data[:target])) - end - - def _run_test(test_case) - result = Test::Unit::TestResult.new - test = test_case.suite - yield(test) if block_given? - test.run(result) {} - result - end - - class TestLoadData < Test::Unit::TestCase - include TestUnitTestUtil - def test_invalid_csv_file_name - garbage = "X" - file_name = "data.csv#{garbage}" - assert_raise(ArgumentError, "unsupported file format: <#{file_name}>") do - self.class.load_data(file_name) - end - end - - class TestFileFormat < self - def setup - self.class.current_attribute(:data).clear - end - - class TestHeader < self - data("csv" => "header.csv", - "tsv" => "header.tsv") - def test_normal(file_name) - self.class.load_data(fixture_file_path(file_name)) - data_sets = Test::Unit::DataSets.new - data_sets << { - "empty string" => { - "expected" => true, - "target" => "" - } - } - data_sets << { - "plain string" => { - "expected" => false, - "target" => "hello" - } - } - assert_equal(data_sets, - self.class.current_attribute(:data)[:value]) - end - - data("csv" => "header-label.csv", - "tsv" => "header-label.tsv") - def test_label(file_name) - self.class.load_data(fixture_file_path(file_name)) - data_sets = Test::Unit::DataSets.new - data_sets << { - "upper case" => { - "expected" => "HELLO", - "label" => "HELLO" - } - } - data_sets << { - "lower case" => { - "expected" => "Hello", - "label" => "hello" - } - } - assert_equal(data_sets, - self.class.current_attribute(:data)[:value]) - end - end - - data("csv" => "no-header.csv", - "tsv" => "no-header.tsv") - def test_without_header(file_name) - self.class.load_data(fixture_file_path(file_name)) - data_sets = Test::Unit::DataSets.new - data_sets << {"empty string" => [true, ""]} - data_sets << {"plain string" => [false, "hello"]} - assert_equal(data_sets, - self.class.current_attribute(:data)[:value]) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-diff.rb b/ruby/gems/test-unit-3.3.4/test/test-diff.rb deleted file mode 100644 index d74ad77bc..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-diff.rb +++ /dev/null @@ -1,518 +0,0 @@ -class TestUnitDiff < Test::Unit::TestCase - def test_binary_search_ranges - assert_found_binary_search_ranges(5, [1..2, 4..5, 7..9]) - assert_not_found_binary_search_ranges(3, [1..2, 4..5, 7..9]) - end - - def test_to_indexes - assert_to_indexes({"abc def" => [0, 2], "abc" => [1]}, - ["abc def", "abc", "abc def"]) - - assert_to_indexes({?a => [0, 3], ?b => [1], ?c => [2], ?d => [4]}, - "abcad") - - assert_to_indexes({ - ?1 => [0, 35], - ?t => [2, 5, 16], - ?e => [3, 14, 31, 38], - ?s => [4, 6, 12, 13, 20, 32, 44], - ?, => [7, 21, 33], - ?0 => [9, 23], - ?a => [11, 26], - ?r => [15, 30], - ?i => [17, 27, 41], - ?o => [18], - ?n => [19, 39, 42], - ?f => [25], - ?l => [28], - ?u => [29], - ?p => [37], - ?d => [40], - ?g => [43], - }, - "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| - x == " "[0] - end - end - - def test_longest_match - assert_longest_match([0, 1, 3], - %w(b c d), %w(a b c d x y z), - 0, 2, 0, 7) - assert_longest_match([1, 2, 2], - %w(b c d), %w(a b c d x y z), - 1, 2, 0, 6) - assert_longest_match([0, 0, 0], - %w(a b), %w(c), - 0, 1, 0, 0) - assert_longest_match([1, 0, 2], - %w(q a b x c d), %w(a b y c d f), - 0, 5, 0, 5) - assert_longest_match([4, 3, 2], - %w(q a b x c d), %w(a b y c d f), - 3, 5, 2, 5) - - assert_longest_match([1, 0, 2], "qabxcd", "abycdf", 0, 5, 0, 5) - assert_longest_match([0, 0, 1], "efg", "eg", 0, 2, 0, 1) - assert_longest_match([2, 1, 1], "efg", "eg", 1, 2, 1, 1) - end - - def test_longest_match_with_junk_predicate - assert_longest_match([0, 4, 5], " abcd", "abcd abcd", 0, 4, 0, 8) - assert_longest_match([1, 0, 4], " abcd", "abcd abcd", 0, 4, 0, 8) do |x| - x == ' '[0] - end - end - - def test_matches - assert_matches([[0, 0, 2], - [3, 2, 2]], - %w(a b x c d), %w(a b c d)) - assert_matches([[1, 0, 2], - [4, 3, 2]], - %w(q a b x c d), %w(a b y c d f)) - - assert_matches([[1, 0, 2], - [4, 3, 2]], - "qabxcd", "abycdf") - assert_matches([[0, 0, 1], - [2, 1, 1]], - "efg", "eg") - end - - def test_matches_with_junk_predicate - assert_matches([[0, 0, 23], - [24, 24, 11], - [36, 36, 9]], - "1 tests, 0 assertions, 1 failures, 0 pendings", - "1 tests, 0 assertions, 0 failures, 1 pendings") - - assert_matches([[0, 0, 1], - [1, 1, 8], - [9, 9, 1], - [10, 10, 13], - [24, 24, 11], - [36, 36, 9]], - "1 tests, 0 assertions, 1 failures, 0 pendings", - "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| - x == " "[0] - end - end - - def test_blocks - assert_blocks([[0, 0, 2], - [3, 2, 2], - [5, 4, 0]], - %w(a b x c d), %w(a b c d)) - assert_blocks([[1, 0, 2], - [4, 3, 2], - [6, 6, 0]], - %w(q a b x c d), %w(a b y c d f)) - - assert_blocks([[1, 0, 2], - [4, 3, 2], - [6, 6, 0]], - "qabxcd", "abycdf") - assert_blocks([[0, 0, 1], - [2, 1, 1], - [3, 2, 0]], - "efg", "eg") - end - - def test_blocks_with_junk_predicate - assert_blocks([[0, 0, 23], - [24, 24, 11], - [36, 36, 9], - [45, 45, 0]], - "1 tests, 0 assertions, 1 failures, 0 pendings", - "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| - x == " "[0] - end - end - - def test_operations - assert_operations([], %w(), %w()) - - assert_operations([[:delete, 0, 1, 0, 0], - [:equal, 1, 3, 0, 2], - [:replace, 3, 4, 2, 3], - [:equal, 4, 6, 3, 5], - [:insert, 6, 6, 5, 6]], - %w(q a b x c d), %w(a b y c d f)) - - assert_operations([[:delete, 0, 1, 0, 0], - [:equal, 1, 3, 0, 2], - [:replace, 3, 4, 2, 3], - [:equal, 4, 6, 3, 5], - [:insert, 6, 6, 5, 6]], - "qabxcd", "abycdf") - - assert_operations([[:equal, 0, 23, 0, 23], - [:replace, 23, 24, 23, 24], - [:equal, 24, 35, 24, 35], - [:replace, 35, 36, 35, 36], - [:equal, 36, 45, 36, 45]], - "1 tests, 0 assertions, 1 failures, 0 pendings", - "1 tests, 0 assertions, 0 failures, 1 pendings") - - assert_operations([[:equal, 0, 23, 0, 23], - [:replace, 23, 24, 23, 24], - [:equal, 24, 35, 24, 35], - [:replace, 35, 36, 35, 36], - [:equal, 36, 45, 36, 45]], - "1 tests, 0 assertions, 1 failures, 0 pendings", - "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| - x == " "[0] - end - end - - def test_grouped_operations - assert_grouped_operations([[[:equal, 0, 0, 0, 0]]], - %w(), - %w()) - - assert_grouped_operations([[[:equal, 0, 3, 0, 3]]], - %w(a b c), - %w(a b c)) - - assert_grouped_operations([[[:equal, 0, 1, 0, 1], - [:replace, 1, 2, 1, 2], - [:equal, 2, 5, 2, 5]], - [[:equal, 8, 11, 8, 11], - [:replace, 11, 12, 11, 12], - [:equal, 12, 13, 12, 13], - [:delete, 13, 16, 13, 13], - [:equal, 16, 17, 13, 14], - [:replace, 17, 18, 14, 15], - [:equal, 18, 20, 15, 17]]], - %w(1 2 3 4 5 6 7 8 9 a b c d e f g h i j k), - %w(1 i 3 4 5 6 7 8 9 a b cX d h iX j k)) - end - - def test_ratio - assert_ratio(0.75, "abcd", "bcde") - assert_ratio(0.80, "efg", "eg") - end - - def test_1_length_readable_diff - differ = Test::Unit::Diff::ReadableDiffer.new(["0"], ["1"]) - def differ.cut_off_ratio - 0 - end - def differ.default_ratio - 0 - end - assert_equal("- 0\n" + - "? ^\n" + - "+ 1\n" + - "? ^", - differ.diff.join("\n")) - end - - def test_same_contents_readable_diff - assert_readable_diff(" aaa", ["aaa"], ["aaa"]) - assert_readable_diff(" aaa\n" \ - " bbb", - ["aaa", "bbb"], ["aaa", "bbb"]) - end - - def test_deleted_readable_diff - assert_readable_diff(" aaa\n" \ - "- bbb", - ["aaa", "bbb"], ["aaa"]) - assert_readable_diff(" aaa\n" \ - "- bbb\n" \ - "- ccc\n" \ - "- ddd", - ["aaa", "bbb", "ccc", "ddd"], ["aaa"]) - end - - def test_inserted_readable_diff - assert_readable_diff(" aaa\n" \ - "+ bbb\n" \ - "+ ccc\n" \ - "+ ddd", - ["aaa"], ["aaa", "bbb", "ccc", "ddd"]) - end - - def test_replace_readable_diff - assert_readable_diff(" aaa\n" \ - "- bbb\n" \ - "+ BbB\n" \ - " ccc\n" \ - "- ddd\n" \ - "- efg\n" \ - "? -\n" \ - "+ eg", - ["aaa", "bbb", "ccc", "ddd", "efg"], - ["aaa", "BbB", "ccc", "eg"]) - - assert_readable_diff("- abcd xyz abc\n" \ - "? -\n" \ - "+ abcd abcd xyz abc\n" \ - "? +++++", - [" abcd xyz abc"], - ["abcd abcd xyz abc"]) - end - - def test_difference_readable_diff - assert_readable_diff("- 1 tests, 0 assertions, 1 failures, 0 pendings\n" \ - "? ^ ^\n" \ - "+ 1 tests, 0 assertions, 0 failures, 1 pendings\n" \ - "? ^ ^", - ["1 tests, 0 assertions, 1 failures, 0 pendings"], - ["1 tests, 0 assertions, 0 failures, 1 pendings"]) - end - - def test_complex_readable_diff - assert_readable_diff(" aaa\n" \ - "- bbb\n" \ - "- ccc\n" \ - "+ \n" \ - "+ # \n" \ - " ddd", - ["aaa", "bbb", "ccc", "ddd"], - ["aaa", "", " # ", "ddd"]) - - assert_readable_diff("- one1\n" \ - "? ^\n" \ - "+ ore1\n" \ - "? ^\n" \ - "- two2\n" \ - "- three3\n" \ - "? - -\n" \ - "+ tree\n" \ - "+ emu", - ["one1", "two2", "three3"], - ["ore1", "tree", "emu"]) - end - - def test_empty_readable_diff - assert_readable_diff("", [""], [""]) - end - - def test_unified_diff - assert_unified_diff("", - ["one", "two", "three"], - ["one", "two", "three"], - "content 1", - "content 2") - - assert_unified_diff("--- Original Sat Jan 26 23:30:50 1991\n" \ - "+++ Current Fri Jun 06 10:20:52 2003\n" \ - "@@ -1,4 +1,4 @@\n" \ - "+zero\n" \ - " one\n" \ - "-two\n" \ - "-three\n" \ - "+tree\n" \ - " four", - ["one", "two", "three", "four"], - ["zero", "one", "tree", "four"], - "Original Sat Jan 26 23:30:50 1991", - "Current Fri Jun 06 10:20:52 2003", - :show_context => false) - - from = File.read(__FILE__).split(/\n/) - to = from.dup - target_line = __LINE__ - to[target_line - 1, 1] = [] - context = " def test_unified_diff" - summary = "@@ -#{target_line - 3},7 +#{target_line - 3},6 @@ #{context}" - assert_unified_diff((["--- revision 10", - "+++ revision 11", - summary] + - from[target_line - 4, 3].collect {|line| " #{line}"} + - ["-#{from[target_line - 1]}"] + - from[target_line, 3].collect {|line| " #{line}"} - ).join("\n"), - from, to, - "revision 10", - "revision 11") - end - - def test_empty_unified_diff - assert_unified_diff("", [""], [""], "From", "To") - assert_unified_diff("", [], [], "From", "To") - end - - def test_diff_lines - assert_diff_lines(["- ddd", - "- efg", - "? -", - "+ eg"], - ["aaa", "bbb", "ccc", "ddd", "efg"], - ["aaa", "BbB", "ccc", "eg"], - 3, 5, 3, 4) - end - - def test_diff_line - assert_diff_line(["- abcDefghiJkl", - "? ^ ^ ^", - "+ abcdefGhijkl", - "? ^ ^ ^"], - "abcDefghiJkl", - "abcdefGhijkl") - - assert_diff_line(["- bcDefghiJklx", - "? ^ ^ ^ -", - "+ abcdefGhijkl", - "? + ^ ^ ^"], - "bcDefghiJklx", - "abcdefGhijkl") - end - - def test_empty_diff_line - assert_diff_line(["- ", - "+ "], - "", "") - end - - def test_format_diff_point - assert_format_diff_point(["- \tabcDefghiJkl", - "? \t ^ ^ ^", - "+ \t\tabcdefGhijkl", - "? \t ^ ^ ^"], - "\tabcDefghiJkl", - "\t\tabcdefGhijkl", - " ^ ^ ^ ", - "+ ^ ^ ^ ") - assert_format_diff_point(["- efg", - "? ^", - "+ eg"], - "efg", - "eg", - " ^", - "") - end - - def test_interesting_line - from = ["class X", - " def find(x=0)", - " body", - " end", - "end"] - to = ["def xxx", - " raise 'not call me'", - "end"] - assert_interesting_line(" def find(x=0)", - from, to, - 2, 1) - assert_interesting_line("def xxx", - from, to, - 2, 0) - assert_interesting_line("class X", - from, to, - 0, 0) - end - - private - def assert_found_binary_search_ranges(numeric, ranges) - assert_true(Test::Unit::Diff::UTF8Line.send(:binary_search_ranges, - numeric, - ranges)) - end - - def assert_not_found_binary_search_ranges(numeric, ranges) - assert_false(Test::Unit::Diff::UTF8Line.send(:binary_search_ranges, - numeric, - ranges)) - end - - def assert_to_indexes(expected, to, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new([""], to, &junk_predicate) - assert_equal(expected, matcher.instance_variable_get("@to_indexes")) - end - - def assert_find_best_match_position(expected, from, to, - from_start, from_end, - to_start, to_end, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) - assert_equal(expected, matcher.send(:find_best_match_position, - from_start, from_end, - to_start, to_end)) - end - - def assert_longest_match(expected, from, to, - from_start, from_end, - to_start, to_end, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) - assert_equal(expected, matcher.longest_match(from_start, from_end, - to_start, to_end)) - end - - def assert_matches(expected, from, to, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) - assert_equal(expected, matcher.send(:matches)) - end - - def assert_blocks(expected, from, to, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) - assert_equal(expected, matcher.blocks) - end - - def assert_operations(expected, from, to, &junk_predicate) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) - assert_equal(expected, matcher.operations) - end - - def assert_grouped_operations(expected, from, to) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to) - assert_equal(expected, matcher.grouped_operations) - end - - def assert_ratio(expected, from, to) - matcher = Test::Unit::Diff::SequenceMatcher.new(from, to) - assert_in_delta(expected, 0.001, matcher.ratio) - end - - def assert_readable_diff(expected, from, to) - assert_equal(expected, - Test::Unit::Diff.readable(from.join("\n"), to.join("\n"))) - end - - def assert_unified_diff(expected, from, to, from_label, to_label, options={}) - options = options.merge(:from_label => from_label, - :to_label => to_label) - assert_equal(expected, - Test::Unit::Diff.unified(from.join("\n"), to.join("\n"), - options)) - end - - def assert_diff_lines(expected, from, to, - from_start, from_end, - to_start, to_end) - differ = Test::Unit::Diff::ReadableDiffer.new(from, to) - result = [] - differ.instance_variable_set("@result", result) - differ.send(:diff_lines, - from_start, from_end, - to_start, to_end) - assert_equal(expected, result) - end - - def assert_diff_line(expected, from_line, to_line) - differ = Test::Unit::Diff::ReadableDiffer.new([""], [""]) - result = [] - differ.instance_variable_set("@result", result) - differ.send(:diff_line, from_line, to_line) - assert_equal(expected, result) - end - - def assert_format_diff_point(expected, from_line, to_line, from_tags, to_tags) - differ = Test::Unit::Diff::ReadableDiffer.new([""], [""]) - result = [] - differ.instance_variable_set("@result", result) - differ.send(:format_diff_point, - from_line, to_line, - from_tags, to_tags) - assert_equal(expected, result) - end - - def assert_interesting_line(expected, from, to, from_start, to_start) - differ = Test::Unit::Diff::UnifiedDiffer.new(from, to) - assert_equal(expected, differ.send(:find_interesting_line, - from_start, to_start, - :define_line?)) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-emacs-runner.rb b/ruby/gems/test-unit-3.3.4/test/test-emacs-runner.rb deleted file mode 100644 index 412c8cc44..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-emacs-runner.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'test/unit' -require 'test/unit/ui/emacs/testrunner' - -class TestUnitEmacsRunner < Test::Unit::TestCase - def test_format_failure_with_a_location - runner = create_runner - test_name = "test_failure" - file = "/home/user/test_xxx.rb" - line = "3" - info = "in `xxx'" - location = "#{file}:#{line}: #{info}" - message = "FAIL!!!" - failure = Test::Unit::Failure.new(test_name, [location], message) - assert_equal(<<-EOM.chomp, runner.send(:format_fault, failure)) -Failure: -#{test_name} [#{file}:#{line}]: -#{message} -EOM - end - - def test_format_failure_with_locations - runner = create_runner - test_name = "test_failure" - locations = ["/home/user/test_xxx.rb:3: in `xxx'", - "/home/user/yyy/test_yyy.rb:999: in `yyy'", - "/home/user/xyz/zzz.rb:29: in `zzz'"] - message = "Many backtrace!!!" - failure = Test::Unit::Failure.new(test_name, locations, message) - assert_equal(<<-EOM.chomp, runner.send(:format_fault, failure)) -Failure: -#{test_name} -#{locations.join("\n")}: -#{message} -EOM - end - - def test_format_error - runner = create_runner - test_name = "test_error" - message = "Error Message!!!" - backtrace = ["/home/user/test_xxx.rb:3: in `xxx'", - "/home/user/yyy/test_yyy.rb:999: in `yyy'", - "/home/user/xyz/zzz.rb:29: in `zzz'"] - exception = RuntimeError.new(message) - exception.set_backtrace(backtrace) - error = Test::Unit::Error.new(test_name, exception) - assert_equal(<<-EOM.chomp, runner.send(:format_fault, error)) -Error: -#{test_name}: -#{exception.class.name}: #{message} -#{backtrace.join("\n")} -EOM - end - - private - def create_runner(suite=nil) - suite ||= Test::Unit::TestSuite.new - Test::Unit::UI::Emacs::TestRunner.new(suite) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-error.rb b/ruby/gems/test-unit-3.3.4/test/test-error.rb deleted file mode 100644 index 56b275b36..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-error.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' - -module Test - module Unit - class TC_Error < TestCase - TF_Exception = Struct.new('TF_Exception', :message, :backtrace) - def test_display - ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2']) - e = Error.new("name", ex) - assert_equal("name: #{TF_Exception.name}: message1", e.short_display) - assert_equal(< -# -# License: Ruby's - -require "test-unit" -require "test/unit/fault-location-detector" -require "testunit-test-util" - -class TestFaultLocationDetector < Test::Unit::TestCase - include TestUnitTestUtil - - def setup - @fetcher = Test::Unit::CodeSnippetFetcher.new - end - - private - def run_test_case(test_case) - suite = test_case.suite - result = Test::Unit::TestResult.new - suite.run(result) {} - result.faults[0] - end - - def assert_detect(fault, target_line_number) - detector = Test::Unit::FaultLocationDetector.new(fault, @fetcher) - - expected_backtrace_entries_until_detected = [] - fault.location.each do |backtrace_entry| - expected_backtrace_entries_until_detected << backtrace_entry - _, line_number, = detector.split_backtrace_entry(backtrace_entry) - break if target_line_number == line_number - end - - actual_backtrace_entries_until_detected = [] - fault.location.each do |backtrace_entry| - actual_backtrace_entries_until_detected << backtrace_entry - break if detector.target?(backtrace_entry) - end - - assert_equal(expected_backtrace_entries_until_detected, - actual_backtrace_entries_until_detected) - end - - module AlwaysFailAssertion - private - def assert_always_failed - assert_true(false) - end - end - - class TestSourceLocation < self - setup - def setup_check_source_location - unless lambda {}.respond_to?(:source_location) - omit("Need Proc#source_location") - end - end - - def test_detected - target_line_number = nil - test_case = Class.new(Test::Unit::TestCase) do - include AlwaysFailAssertion - - test "failed" do - target_line_number = __LINE__; assert_always_failed - end - end - - fault = run_test_case(test_case) - assert_detect(fault, target_line_number) - end - - class TestOneLine < self - def test_brace - target_line_number = nil - test_case = Class.new(Test::Unit::TestCase) do - include AlwaysFailAssertion - - test("failed") {target_line_number = __LINE__; assert_always_failed} - - def other_method - # body - end - end - - fault = run_test_case(test_case) - assert_detect(fault, target_line_number) - end - - def test_do_end - target_line_number = nil - test_case = Class.new(Test::Unit::TestCase) do - include AlwaysFailAssertion - - test "failed" do target_line_number = __LINE__; assert_always_failed; end - - def other_method - # body - end - end - - fault = run_test_case(test_case) - assert_detect(fault, target_line_number) - end - end - end - - class TestMethodName < self - def test_detected - test_case = Class.new(Test::Unit::TestCase) do - include AlwaysFailAssertion - - class << self - def target_line_number - @@target_line_number - end - - def target_line_number=(line_number) - @@target_line_number = line_number - end - end - - def test_failed - self.class.target_line_number = __LINE__; assert_always_failed - end - end - - fault = run_test_case(test_case) - assert_detect(fault, test_case.target_line_number) - end - end - - class TestInBlock < self - def test_in_block - test_case = Class.new(Test::Unit::TestCase) do - include AlwaysFailAssertion - - class << self - def target_line_number - @@target_line_number - end - - def target_line_number=(line_number) - @@target_line_number = line_number - end - end - - def run_yield - yield - end - - def test_failed - run_yield do - self.class.target_line_number = __LINE__; assert_always_failed - end - end - end - - fault = run_test_case(test_case) - assert_detect(fault, test_case.target_line_number) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-fixture.rb b/ruby/gems/test-unit-3.3.4/test/test-fixture.rb deleted file mode 100644 index 8ccc4e844..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-fixture.rb +++ /dev/null @@ -1,713 +0,0 @@ -class TestUnitFixture < Test::Unit::TestCase - module EmptyModule - end - - class TestSetup < self - def test_without_option - expected_setup_calls = [:setup, - :custom_setup_method0, - :custom_setup_callback0, - :custom_setup_method1, - :custom_setup_callback1, - :custom_setup_method3, - :custom_setup_callback3] - test_case = assert_setup(expected_setup_calls, []) - assert_inherited_setup(expected_setup_calls, test_case) - - assert_inherited_setup([:setup], nil) - assert_called_fixtures(expected_setup_calls, test_case) - end - - def test_with_before_option - expected_setup_calls = [:custom_setup_callback3, - :custom_setup_method3, - :custom_setup_method0, - :custom_setup_callback0, - :custom_setup_method1, - :custom_setup_callback1, - :setup] - test_case = assert_setup(expected_setup_calls, - [[{:before => :append}], - [{:before => :append}], - [{:before => :prepend}], - [{:before => :prepend}]]) - assert_inherited_setup(expected_setup_calls, test_case) - - assert_inherited_setup([:setup], nil) - assert_called_fixtures(expected_setup_calls, test_case) - end - - def test_with_after_option - expected_setup_calls = [:setup, - :custom_setup_callback3, - :custom_setup_method3, - :custom_setup_method0, - :custom_setup_callback0, - :custom_setup_method1, - :custom_setup_callback1] - test_case = assert_setup(expected_setup_calls, - [[{:after => :append}], - [{:after => :append}], - [{:after => :prepend}], - [{:after => :prepend}]]) - assert_inherited_setup(expected_setup_calls, test_case) - - assert_inherited_setup([:setup], nil) - assert_called_fixtures(expected_setup_calls, test_case) - end - - def test_with_invalid_option - assert_invalid_setup_option(:unknown => true) - assert_invalid_setup_option(:before => :unknown) - assert_invalid_setup_option(:after => :unknown) - end - - def test_with_option_to_inherited - expected_setup_calls = [:setup] - test_case = assert_setup(expected_setup_calls, nil) - assert_inherited_setup([:setup, - :custom_setup_method0, - :custom_setup_callback0, - :custom_setup_method1, - :custom_setup_callback1, - :custom_setup_method3, - :custom_setup_callback3], - test_case, - []) - - assert_inherited_setup([:setup], nil) - assert_called_fixtures(expected_setup_calls, test_case) - end - - private - def assert_setup_customizable(expected, parent, options) - test_case = Class.new(parent || Test::Unit::TestCase) do - yield(self, :before) if block_given? - - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - def setup - called(:setup) - end - - setup(*(options[0] || [])) if options - def custom_setup_method0 - called(:custom_setup_method0) - end - - if options - setup(*(options[0] || [])) do - called(:custom_setup_callback0) - end - end - - def custom_setup_method1 - called(:custom_setup_method1) - end - setup(*[:custom_setup_method1, *(options[1] || [])]) if options - - if options - setup(*(options[1] || [])) do - called(:custom_setup_callback1) - end - end - - setup(*(options[2] || [])) if options - def custom_setup_method2 - called(:custom_setup_method2) - end - unregister_setup(:custom_setup_method2) if options - - if options - callback = lambda do - called(:custom_setup_callback2) - end - setup(*(options[2] || []), &callback) - unregister_setup(callback) - end - - setup(*(options[3] || [])) if options - def custom_setup_method3 - called(:custom_setup_method3) - end - - if options - setup(*(options[3] || [])) do - called(:custom_setup_callback3) - end - end - - def test_nothing - end - - yield(self, :after) if block_given? - end - - assert_called_fixtures(expected, test_case) - test_case - end - - def assert_setup(expected, options) - _test_case = assert_setup_customizable(expected, nil, options) - assert_setup_customizable(expected, nil, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - _test_case - end - - def assert_inherited_setup(expected, parent, options=nil) - _test_case = assert_setup_customizable(expected, parent, options) - assert_setup_customizable(expected, parent, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - _test_case - end - - def assert_invalid_setup_option(option) - assert_invalid_option(:setup, option) - end - end - - class TestCleanup < self - def test_without_option - expected_cleanup_calls = [:custom_cleanup_callback3, - :custom_cleanup_method3, - :custom_cleanup_callback1, - :custom_cleanup_method1, - :custom_cleanup_callback0, - :custom_cleanup_method0, - :cleanup] - test_case = assert_cleanup(expected_cleanup_calls, []) - assert_inherited_cleanup(expected_cleanup_calls, test_case) - - assert_inherited_cleanup([:cleanup], nil) - assert_called_fixtures(expected_cleanup_calls, test_case) - end - - def test_with_before_option - expected_cleanup_calls = [:custom_cleanup_callback3, - :custom_cleanup_method3, - :custom_cleanup_method0, - :custom_cleanup_callback0, - :custom_cleanup_method1, - :custom_cleanup_callback1, - :cleanup] - test_case = assert_cleanup(expected_cleanup_calls, - [[{:before => :append}], - [{:before => :append}], - [{:before => :prepend}], - [{:before => :prepend}]]) - assert_inherited_cleanup(expected_cleanup_calls, test_case) - - assert_inherited_cleanup([:cleanup], nil) - assert_called_fixtures(expected_cleanup_calls, test_case) - end - - def test_with_after_option - expected_cleanup_calls = [:cleanup, - :custom_cleanup_callback3, - :custom_cleanup_method3, - :custom_cleanup_method0, - :custom_cleanup_callback0, - :custom_cleanup_method1, - :custom_cleanup_callback1] - test_case = assert_cleanup(expected_cleanup_calls, - [[{:after => :append}], - [{:after => :append}], - [{:after => :prepend}], - [{:after => :prepend}]]) - assert_inherited_cleanup(expected_cleanup_calls, test_case) - - assert_inherited_cleanup([:cleanup], nil) - assert_called_fixtures(expected_cleanup_calls, test_case) - end - - def test_with_invalid_option - assert_invalid_cleanup_option(:unknown => true) - assert_invalid_cleanup_option(:before => :unknown) - assert_invalid_cleanup_option(:after => :unknown) - end - - def test_with_option_to_inherited - expected_cleanup_calls = [:cleanup] - test_case = assert_cleanup(expected_cleanup_calls, nil) - assert_inherited_cleanup([:custom_cleanup_callback3, - :custom_cleanup_method3, - :custom_cleanup_callback1, - :custom_cleanup_method1, - :custom_cleanup_callback0, - :custom_cleanup_method0, - :cleanup], - test_case, []) - - assert_inherited_cleanup([:cleanup], nil) - assert_called_fixtures(expected_cleanup_calls, test_case) - end - - def test_with_exception - test_case = Class.new(Test::Unit::TestCase) do - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - def cleanup - called(:cleanup) - raise "cleanup" - end - - cleanup - def custom_cleanup_method0 - called(:custom_cleanup_method0) - raise "custom_cleanup_method0" - end - - cleanup do - called(:custom_cleanup_callback0) - raise "custom_cleanup_callback0" - end - - cleanup - def custom_cleanup_method1 - called(:custom_cleanup_method1) - raise "custom_cleanup_method1" - end - - cleanup do - called(:custom_cleanup_callback1) - raise "custom_cleanup_callback1" - end - - def test_nothing - end - end - - assert_called_fixtures([:custom_cleanup_callback1], - test_case) - end - - private - def assert_cleanup_customizable(expected, parent, options) - test_case = Class.new(parent || Test::Unit::TestCase) do - yield(self, :before) if block_given? - - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - def cleanup - called(:cleanup) - end - - cleanup(*(options[0] || [])) if options - def custom_cleanup_method0 - called(:custom_cleanup_method0) - end - - if options - cleanup(*(options[0] || [])) do - called(:custom_cleanup_callback0) - end - end - - def custom_cleanup_method1 - called(:custom_cleanup_method1) - end - cleanup(*[:custom_cleanup_method1, *(options[1] || [])]) if options - - if options - cleanup(*(options[1] || [])) do - called(:custom_cleanup_callback1) - end - end - - cleanup(*(options[2] || [])) if options - def custom_cleanup_method2 - called(:custom_cleanup_method2) - end - unregister_cleanup(:custom_cleanup_method2) if options - - if options - callback = lambda do - called(:custom_cleanup_callback2) - end - cleanup(*(options[2] || []), &callback) - unregister_cleanup(callback) - end - - cleanup(*(options[3] || [])) if options - def custom_cleanup_method3 - called(:custom_cleanup_method3) - end - - if options - cleanup(*(options[3] || [])) do - called(:custom_cleanup_callback3) - end - end - - def test_nothing - end - - yield(self, :after) if block_given? - end - - assert_called_fixtures(expected, test_case) - test_case - end - - def assert_cleanup(expected, options) - assert_cleanup_customizable(expected, nil, options) - assert_cleanup_customizable(expected, nil, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - end - - def assert_inherited_cleanup(expected, parent, options=nil) - assert_cleanup_customizable(expected, parent, options) - assert_cleanup_customizable(expected, parent, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - end - - def assert_invalid_cleanup_option(option) - assert_invalid_option(:cleanup, option) - end - end - - class TestTeardown < self - def test_without_option - expected_teardown_calls = [:custom_teardown_callback3, - :custom_teardown_method3, - :custom_teardown_callback1, - :custom_teardown_method1, - :custom_teardown_callback0, - :custom_teardown_method0, - :teardown] - test_case = assert_teardown(expected_teardown_calls, []) - assert_inherited_teardown(expected_teardown_calls, test_case) - - assert_inherited_teardown([:teardown], nil) - assert_called_fixtures(expected_teardown_calls, test_case) - end - - def test_with_before_option - expected_teardown_calls = [:custom_teardown_callback3, - :custom_teardown_method3, - :custom_teardown_method0, - :custom_teardown_callback0, - :custom_teardown_method1, - :custom_teardown_callback1, - :teardown] - test_case = assert_teardown(expected_teardown_calls, - [[{:before => :append}], - [{:before => :append}], - [{:before => :prepend}], - [{:before => :prepend}]]) - assert_inherited_teardown(expected_teardown_calls, test_case) - - assert_inherited_teardown([:teardown], nil) - assert_called_fixtures(expected_teardown_calls, test_case) - end - - def test_with_after_option - expected_teardown_calls = [:teardown, - :custom_teardown_callback3, - :custom_teardown_method3, - :custom_teardown_method0, - :custom_teardown_callback0, - :custom_teardown_method1, - :custom_teardown_callback1] - test_case = assert_teardown(expected_teardown_calls, - [[{:after => :append}], - [{:after => :append}], - [{:after => :prepend}], - [{:after => :prepend}]]) - assert_inherited_teardown(expected_teardown_calls, test_case) - - assert_inherited_teardown([:teardown], nil) - assert_called_fixtures(expected_teardown_calls, test_case) - end - - def test_with_invalid_option - assert_invalid_teardown_option(:unknown => true) - assert_invalid_teardown_option(:before => :unknown) - assert_invalid_teardown_option(:after => :unknown) - end - - def test_with_option_to_inherited - expected_teardown_calls = [:teardown] - test_case = assert_teardown(expected_teardown_calls, nil) - assert_inherited_teardown([:custom_teardown_callback3, - :custom_teardown_method3, - :custom_teardown_callback1, - :custom_teardown_method1, - :custom_teardown_callback0, - :custom_teardown_method0, - :teardown], - test_case, []) - - assert_inherited_teardown([:teardown], nil) - assert_called_fixtures(expected_teardown_calls, test_case) - end - - def test_with_exception - test_case = Class.new(Test::Unit::TestCase) do - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - def teardown - called(:teardown) - raise "teardown" - end - - teardown - def custom_teardown_method0 - called(:custom_teardown_method0) - raise "custom_teardown_method0" - end - - teardown do - called(:custom_teardown_callback0) - raise "custom_teardown_callback0" - end - - teardown - def custom_teardown_method1 - called(:custom_teardown_method1) - raise "custom_teardown_method1" - end - - teardown do - called(:custom_teardown_callback1) - raise "custom_teardown_callback1" - end - - def test_nothing - end - end - - assert_called_fixtures([:custom_teardown_callback1, - :custom_teardown_method1, - :custom_teardown_callback0, - :custom_teardown_method0, - :teardown], - test_case) - end - - def test_nested - called = [] - parent_test_case = Class.new(Test::Unit::TestCase) do - teardown do - called << :parent - end - end - - child_test_case = Class.new(parent_test_case) do - teardown do - called << :child - end - - def test_nothing - end - end - - run_test_nothing(child_test_case) - assert_equal([:child, :parent], - called) - end - - def test_setup_with_block - test_case = Class.new(Test::Unit::TestCase) do - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - setup - def setup1 - called(:setup1) - begin - yield - called(:setup1_after_yield) - ensure - called(:setup1_teardown) - end - end - - setup - def setup2 - called(:setup2) - begin - yield - called(:setup2_after_yield) - ensure - called(:setup2_teardown) - end - end - - def teardown - called(:teardown) - end - - def test_nothing - called(:test) - flunk - called(:test_after_failure) - end - end - - assert_called_fixtures([ - :setup1, - :setup2, - :test, - :setup2_teardown, - :setup1_teardown, - :teardown, - ], - test_case) - end - - private - def assert_teardown_customizable(expected, parent, options) - test_case = Class.new(parent || Test::Unit::TestCase) do - yield(self, :before) if block_given? - - def called_ids - @called_ids ||= [] - end - - def called(id) - called_ids << id - end - - def teardown - called(:teardown) - end - - teardown(*(options[0] || [])) if options - def custom_teardown_method0 - called(:custom_teardown_method0) - end - - if options - teardown(*(options[0] || [])) do - called(:custom_teardown_callback0) - end - end - - def custom_teardown_method1 - called(:custom_teardown_method1) - end - teardown(*[:custom_teardown_method1, *(options[1] || [])]) if options - - if options - teardown(*(options[1] || [])) do - called(:custom_teardown_callback1) - end - end - - teardown(*(options[2] || [])) if options - def custom_teardown_method2 - called(:custom_teardown_method2) - end - unregister_teardown(:custom_teardown_method2) if options - - if options - callback = lambda do - called(:custom_teardown_callback2) - end - teardown(*(options[2] || []), &callback) - unregister_teardown(callback) - end - - teardown(*(options[3] || [])) if options - def custom_teardown_method3 - called(:custom_teardown_method3) - end - - if options - teardown(*(options[3] || [])) do - called(:custom_teardown_callback3) - end - end - - def test_nothing - end - - yield(self, :after) if block_given? - end - - assert_called_fixtures(expected, test_case) - test_case - end - - def assert_teardown(expected, options) - assert_teardown_customizable(expected, nil, options) - assert_teardown_customizable(expected, nil, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - end - - def assert_inherited_teardown(expected, parent, options=nil) - assert_teardown_customizable(expected, parent, options) - assert_teardown_customizable(expected, parent, options) do |test_case, tag| - test_case.send(:include, EmptyModule) if tag == :before - end - end - - def assert_invalid_teardown_option(option) - assert_invalid_option(:teardown, option) - end - end - - private - def run_test_nothing(test_case) - test = test_case.new("test_nothing") - test.run(Test::Unit::TestResult.new) {} - test - end - - def assert_called_fixtures(expected, test_case) - test = run_test_nothing(test_case) - assert_equal(expected, test.called_ids) - end - - def assert_invalid_option(fixture_type, option) - exception = assert_raise(ArgumentError) do - Class.new(Test::Unit::TestCase) do - def test_nothing - end - - send(fixture_type, option) - def fixture - end - end - end - assert_equal("must be {:before => :prepend}, {:before => :append}, " + - "{:after => :prepend} or {:after => :append}" + - ": #{option.inspect}", - exception.message) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-notification.rb b/ruby/gems/test-unit-3.3.4/test/test-notification.rb deleted file mode 100644 index e4931f3d6..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-notification.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'test/unit' -require 'testunit-test-util' - -class TestUnitNotification < Test::Unit::TestCase - include TestUnitTestUtil - - class TestCase < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - def test_notify - notify("1st notify") - notify("2nd notify. Reach here.") - end - end - - def test_notify - result = _run_test("test_notify") - assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ - "0 omissions, 2 notifications", - result.to_s) - assert_fault_messages(["1st notify", "2nd notify. Reach here."], - result.notifications) - end - - private - def _run_test(name) - super(TestCase, name) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-omission.rb b/ruby/gems/test-unit-3.3.4/test/test-omission.rb deleted file mode 100644 index 183216058..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-omission.rb +++ /dev/null @@ -1,81 +0,0 @@ -require 'test/unit' -require 'testunit-test-util' - -class TestUnitOmission < Test::Unit::TestCase - include TestUnitTestUtil - - class TestCase < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - def test_omit - omit("1st omit") - omit("2nd omit. Should not be reached here.") - assert(true, "Should not be reached here too.") - end - - def test_omit_with_condition - omit_if(false, "Never omit.") - omit_unless(true, "Never omit too.") - omit_if(true, "Should omit.") - omit("The last omit. Should not be reached here.") - end - - def test_omit_with_block - omit("Omit block") do - flunk("Should not be reached here.") - end - assert(true, "Should be reached here.") - end - - def test_omit_with_block_and_condition - omit_if(false, "Never omit.") do - assert(true, "Should be reached here.") - end - omit_if(true, "Should omit.") do - flunk("Never reached here.") - end - assert(true, "Should be reached here too.") - end - end - - def test_omit - result = _run_test("test_omit") - assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ - "1 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["1st omit"], result.omissions) - end - - def test_omit_with_condition - result = _run_test("test_omit_with_condition") - assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ - "1 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["Should omit."], result.omissions) - end - - def test_omit_with_block - result = _run_test("test_omit_with_block") - assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \ - "1 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["Omit block"], result.omissions) - end - - def test_omit_with_condition_and_block - result = _run_test("test_omit_with_block_and_condition") - assert_equal("1 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, " \ - "1 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["Should omit."], result.omissions) - end - - private - def _run_test(name) - super(TestCase, name) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-pending.rb b/ruby/gems/test-unit-3.3.4/test/test-pending.rb deleted file mode 100644 index aa322de3b..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-pending.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'test/unit' -require 'testunit-test-util' - -class TestUnitPending < Test::Unit::TestCase - include TestUnitTestUtil - - class TestCase < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - def test_pend - pend("1st pend") - pend("2nd pend. Should not be reached here.") - assert(true, "Should not be reached here too.") - end - - def test_pend_with_failure_in_block - pend("Wait a minute") do - raise "Not implemented yet" - end - assert(true, "Reached here.") - end - - def test_pend_with_no_failure_in_block - pend("Wait a minute") do - "Nothing raised" - end - assert(true, "Not reached here.") - end - end - - def test_pend - test = nil - result = _run_test("test_pend") {|t| test = t} - assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 1 pendings, " \ - "0 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["1st pend"], result.pendings) - assert_true(test.interrupted?) - end - - def test_pend_with_failure_in_block - test = nil - result = _run_test("test_pend_with_failure_in_block") {|t| test = t} - assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 1 pendings, " \ - "0 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["Wait a minute"], result.pendings) - assert_false(test.interrupted?) - end - - def test_pend_with_no_failure_in_block - test = nil - result = _run_test("test_pend_with_no_failure_in_block") {|t| test = t} - assert_equal("1 tests, 1 assertions, 1 failures, 0 errors, 0 pendings, " \ - "0 omissions, 0 notifications", - result.to_s) - assert_fault_messages(["Pending block should not be passed: Wait a minute."], - result.failures) - assert_true(test.interrupted?) - end - - private - def _run_test(name, &block) - super(TestCase, name, &block) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-priority.rb b/ruby/gems/test-unit-3.3.4/test/test-priority.rb deleted file mode 100644 index d1bbd16e7..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-priority.rb +++ /dev/null @@ -1,184 +0,0 @@ -require 'test/unit' - -class TestUnitPriority < Test::Unit::TestCase - class TestCase < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - priority :must - def test_must - assert(true) - end - - def test_must_inherited - assert(true) - end - - priority :important - def test_important - assert(true) - end - - def test_important_inherited - assert(true) - end - - priority :high - def test_high - assert(true) - end - - def test_high_inherited - assert(true) - end - - priority :normal - def test_normal - assert(true) - end - - def test_normal_inherited - assert(true) - end - - priority :low - def test_low - assert(true) - end - - def test_low_inherited - assert(true) - end - - priority :never - def test_never - assert(true) - end - - def test_never_inherited - assert(true) - end - end - - def test_priority_must - assert_priority("must", 1.0, 0.0001) - end - - def test_priority_important - assert_priority("important", 0.9, 0.09) - end - - def test_priority_high - assert_priority("high", 0.70, 0.1) - end - - def test_priority_normal - assert_priority("normal", 0.5, 0.1) - end - - def test_priority_low - assert_priority("low", 0.25, 0.1) - end - - def test_priority_never - assert_priority("never", 0.0, 0.0001) - end - - def assert_priority(priority, expected, delta) - assert_need_to_run("test_#{priority}", expected, delta) - assert_need_to_run("test_#{priority}_inherited", expected, delta) - end - - def assert_need_to_run(test_name, expected, delta) - test = TestCase.new(test_name) - n = 1000 - n_need_to_run = 0 - n.times do |i| - n_need_to_run += 1 if Test::Unit::Priority::Checker.need_to_run?(test) - end - assert_in_delta(expected, n_need_to_run.to_f / n, delta) - end - - class TestClassName < self - def test_colon - assert_escaped_name("Test_colon__colon_Priority", "Test::Priority") - end - - def test_space - assert_escaped_name("test_priority", "test priority") - end - - def test_slash - assert_escaped_name("test_priority", "test/priority") - end - - def test_back_slash - assert_escaped_name("test_priority", "test\/priority") - end - - def test_question - assert_escaped_name("#question.predicate", "#question?") - end - - def test_exclamation - assert_escaped_name("#exclamation.destructive", "#exclamation!") - end - - def test_equal - assert_escaped_name("#equal.equal", "#equal=") - end - - def assert_escaped_name(expected, class_name) - checker = Checker.new(nil) - escaped_class_name = checker.send(:escape_class_name, class_name) - assert_equal(expected, escaped_class_name) - end - end - - class TestFileName < self - class SpecialNameTestCase < Test::Unit::TestCase - class << self - def suite - Test::Unit::TestSuite.new(name) - end - end - - def test_question? - end - - def test_exclamation! - end - - def test_equal= - end - - test "have space" do - end - end - - def test_question - assert_escaped_name("test_colon__#question.predicate_case", - "test: #question? case") - end - - def test_exclamation - assert_escaped_name("test_colon__#exclamation.destructive_case", - "test: #exclamation! case") - end - - def test_equal - assert_escaped_name("test_colon__#equal.equal_case", - "test: #equal= case") - end - - def assert_escaped_name(expected, test_method_name) - checker = Checker.new(SpecialNameTestCase.new(test_method_name)) - passed_file = checker.send(:passed_file) - method_name_component = File.basename(File.dirname(passed_file)) - assert_equal(expected, method_name_component) - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-test-case.rb b/ruby/gems/test-unit-3.3.4/test/test-test-case.rb deleted file mode 100644 index 1735b028b..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-test-case.rb +++ /dev/null @@ -1,1279 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2008-2014 Kouhei Sutou -# Copyright:: Copyright (c) 2011 Haruka Yoshihara -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott -# License:: Ruby license. - -require 'test/unit' - -module Test - module Unit - class TestTestCase < TestCase - self.test_order = :random - def test_creation - test_case = Class.new(TestCase) do - def test_with_arguments(arg1, arg2) - end - end - - test = test_case.new(:test_with_arguments) - check("Should have caught an invalid test when there are arguments", - !test.valid?) - - test = test_case.new(:non_existent_test) - check("Should have caught an invalid test when the method does not exist", - !test.valid?) - end - - def setup - @tc_failure_error = Class.new(TestCase) do - def test_failure - assert_block("failure") do - false - end - end - def test_error - 1 / 0 - end - def test_nested_failure - nested - end - def nested - assert_block("nested") do - false - end - end - def return_passed? - return passed? - end - end - - def @tc_failure_error.name - "TC_FailureError" - end - end - - def jruby_backtrace_entry?(entry) - entry.start_with?("org/jruby/") - end - - def rubinius_backtrace_entry?(entry) - entry.start_with?("kernel/") - end - - def normalize_location(location) - filtered_location = location.reject do |entry| - jruby_backtrace_entry?(entry) or - rubinius_backtrace_entry?(entry) - end - filtered_location.collect do |entry| - entry.sub(/:\d+:/, ":0:") - end - end - - def test_add_failed_assertion - test_case = @tc_failure_error.new(:test_failure) - assert do - test_case.passed? - end - - result = TestResult.new - faults = [] - result.add_listener(TestResult::FAULT) do |fault| - faults << fault - end - progress = [] - test_case.run(result) do |*arguments| - progress << arguments - end - fault_details = faults.collect do |fault| - { - :class => fault.class, - :message => fault.message, - :test_name => fault.test_name, - :location => normalize_location(fault.location), - } - end - assert_equal([ - { - :class => Failure, - :message => "failure", - :test_name => "test_failure(TC_FailureError)", - :location => [ - "#{__FILE__}:0:in `test_failure'", - "#{__FILE__}:0:in `#{__method__}'", - ], - }, - ], - fault_details) - - assert do - not test_case.passed? - end - assert_equal([ - [TestCase::STARTED, test_case.name], - [TestCase::STARTED_OBJECT, test_case], - [TestCase::FINISHED, test_case.name], - [TestCase::FINISHED_OBJECT, test_case], - ], - progress) - end - - def test_add_failure_nested - test_case = @tc_failure_error.new(:test_nested_failure) - assert do - test_case.passed? - end - - result = TestResult.new - faults = [] - result.add_listener(TestResult::FAULT) do |fault| - faults << fault - end - test_case.run(result) do - end - fault_details = faults.collect do |fault| - { - :class => fault.class, - :message => fault.message, - :test_name => fault.test_name, - :location => normalize_location(fault.location), - } - end - assert_equal([ - { - :class => Failure, - :message => "nested", - :test_name => "test_nested_failure(TC_FailureError)", - :location => [ - "#{__FILE__}:0:in `nested'", - "#{__FILE__}:0:in `test_nested_failure'", - "#{__FILE__}:0:in `#{__method__}'", - ], - }, - ], - fault_details) - - assert do - not test_case.passed? - end - end - - def jruby? - defined?(JRUBY_VERSION) - end - - def rubinius? - false # TODO - end - - def cruby? - (not jruby?) and (not rubinius?) - end - - def test_add_error - test_case = @tc_failure_error.new(:test_error) - assert do - test_case.passed? - end - - result = TestResult.new - faults = [] - result.add_listener(TestResult::FAULT) do |fault| - faults << fault - end - test_case.run(result) do - end - fault_details = faults.collect do |fault| - { - :class => fault.class, - :message => fault.message, - :test_name => fault.test_name, - :location => normalize_location(fault.location), - } - end - location = [] - location << "#{__FILE__}:0:in `/'" if cruby? - location << "#{__FILE__}:0:in `test_error'" - location << "#{__FILE__}:0:in `#{__method__}'" - assert_equal([ - { - :class => Error, - :message => "ZeroDivisionError: divided by 0", - :test_name => "test_error(TC_FailureError)", - :location => location, - }, - ], - fault_details) - - assert do - not test_case.passed? - end - end - - def test_no_tests - suite = TestCase.suite - check("Should have a test suite", suite.instance_of?(TestSuite)) - check("Should have one test", suite.size == 1) - check("Should have the default test", suite.tests.first.name == "default_test(Test::Unit::TestCase)") - - result = TestResult.new - suite.run(result) {} - check("Should have had one test run", result.run_count == 1) - check("Should have had one test failure", result.failure_count == 1) - check("Should have had no errors", result.error_count == 0) - end - - def test_suite - tc = Class.new(TestCase) do - def test_succeed - assert_block {true} - end - def test_fail - assert_block {false} - end - def test_error - 1/0 - end - def dont_run - assert_block {true} - end - def test_dont_run(argument) - assert_block {true} - end - def test - assert_block {true} - end - end - - suite = tc.suite - check("Should have a test suite", suite.instance_of?(TestSuite)) - check("Should have three tests", suite.size == 3) - - result = TestResult.new - suite.run(result) {} - check("Should have had three test runs", result.run_count == 3) - check("Should have had one test failure", result.failure_count == 1) - check("Should have had one test error", result.error_count == 1) - end - - def test_setup_teardown - tc = Class.new(TestCase) do - attr_reader(:setup_called, :teardown_called) - def initialize(test) - super(test) - @setup_called = false - @teardown_called = false - end - def setup - @setup_called = true - end - def teardown - @teardown_called = true - end - def test_succeed - assert_block {true} - end - def test_fail - assert_block {false} - end - def test_error - raise "Error!" - end - end - result = TestResult.new - - test = tc.new(:test_succeed) - test.run(result) {} - check("Should have called setup the correct number of times", test.setup_called) - check("Should have called teardown the correct number of times", test.teardown_called) - - test = tc.new(:test_fail) - test.run(result) {} - check("Should have called setup the correct number of times", test.setup_called) - check("Should have called teardown the correct number of times", test.teardown_called) - - test = tc.new(:test_error) - test.run(result) {} - check("Should have called setup the correct number of times", test.setup_called) - check("Should have called teardown the correct number of times", test.teardown_called) - - check("Should have had two test runs", result.run_count == 3) - check("Should have had a test failure", result.failure_count == 1) - check("Should have had a test error", result.error_count == 1) - end - - def test_assertion_failed_not_called - tc = Class.new(TestCase) do - def test_thing - raise AssertionFailedError.new - end - end - - suite = tc.suite - check("Should have one test", suite.size == 1) - result = TestResult.new - suite.run(result) {} - check("Should have had one test run", result.run_count == 1) - check("Should have had one assertion failure", result.failure_count == 1) - check("Should not have any assertion errors but had #{result.error_count}", result.error_count == 0) - end - - def test_equality - tc1 = Class.new(TestCase) do - def test_1 - end - def test_2 - end - end - - tc2 = Class.new(TestCase) do - def test_1 - end - end - - test1 = tc1.new('test_1') - test2 = tc1.new('test_1') - check("Should be equal", test1 == test2) - check("Should be equal", test2 == test1) - - test1 = tc1.new('test_2') - check("Should not be equal", test1 != test2) - check("Should not be equal", test2 != test1) - - test2 = tc1.new('test_2') - check("Should be equal", test1 == test2) - check("Should be equal", test2 == test1) - - test1 = tc1.new('test_1') - test2 = tc2.new('test_1') - check("Should not be equal", test1 != test2) - check("Should not be equal", test2 != test1) - - check("Should not be equal", test1 != Object.new) - check("Should not be equal", Object.new != test1) - end - - def test_re_raise_exception - test_case = Class.new(TestCase) do - def test_raise_interrupt - raise Interrupt, "from test" - end - end - - test = test_case.new("test_raise_interrupt") - begin - test.run(TestResult.new) {} - check("Should not be reached", false) - rescue Exception - check("Interrupt exception should be re-raised", $!.class == Interrupt) - end - end - - def test_timeout_error - test_case = Class.new(TestCase) do - def test_raise_timeout_error - require "timeout" - raise Timeout::Error - end - end - - test_suite = test_case.suite - result = TestResult.new - begin - test_suite.run(result) {} - check("Timeout::Error should be handled as error", - result.error_count == 1) - rescue Exception - check("Timeout::Error should not be passed through: #{$!}", false) - end - end - - def test_interrupted - test_case = Class.new(TestCase) do - def test_fail - flunk - end - - def test_nothing - end - end - - failed_test = test_case.new(:test_fail) - failed_test.run(TestResult.new) {} - check("Should be interrupted", failed_test.interrupted?) - - success_test = test_case.new(:test_nothing) - success_test.run(TestResult.new) {} - check("Should not be interrupted", !success_test.interrupted?) - end - - def test_inherited_test_should_be_ignored - test_case = Class.new(TestCase) do - def test_nothing - end - end - - sub_test_case = Class.new(test_case) do - def test_fail - flunk - end - end - - test = test_case.new("test_nothing") - assert_predicate(test, :valid?) - - test = sub_test_case.new("test_fail") - assert_predicate(test, :valid?) - - test = sub_test_case.new("test_nothing") - assert_not_predicate(test, :valid?) - end - - def test_mixin_test_should_not_be_ignored - test_module = Module.new do - def test_nothing - end - end - - test_case = Class.new(Test::Unit::TestCase) do - include test_module - - def test_fail - flunk - end - end - - assert_nothing_thrown do - test_case.new("test_nothing") - end - - assert_nothing_thrown do - test_case.new("test_fail") - end - end - - def test_defined_order - test_case = Class.new(Test::Unit::TestCase) do - def test_z - end - - def test_1 - end - - def test_a - end - end - - test_case.test_order = :defined - assert_equal(["test_z", "test_1", "test_a"], - test_case.suite.tests.collect {|test| test.method_name}) - end - - def test_declarative_style - test_case = Class.new(Test::Unit::TestCase) do - test "declarative style test definition" do - end - - test "include parenthesis" do - end - - test "1 + 2 = 3" do - end - end - - test_case.test_order = :defined - - assert_equal(["test: declarative style test definition", - "test: include parenthesis", - "test: 1 + 2 = 3"], - test_case.suite.tests.collect {|test| test.method_name}) - - assert_equal(["declarative style test definition", - "include parenthesis", - "1 + 2 = 3"], - test_case.suite.tests.collect {|test| test.description}) - end - - def test_test_mark - test_case = Class.new(Test::Unit::TestCase) do - test - def my_test_method - end - end - - test_case.test_order = :defined - - assert_equal(["my_test_method"], - test_case.suite.tests.collect {|test| test.method_name}) - end - - def test_redefine_method - test_case = Class.new(Test::Unit::TestCase) do - self.test_order = :alphabetic - - def test_name - end - alias_method :test_name2, :test_name - - def test_name - end - end - - suite = test_case.suite - assert_equal(["test_name", "test_name2"], - suite.tests.collect {|test| test.method_name}) - result = TestResult.new - suite.run(result) {} - assert_equal("2 tests, 0 assertions, 0 failures, " + - "0 errors, 0 pendings, 0 omissions, 1 notifications", - result.summary) - end - - def test_data_driven_test - test_case = Class.new(TestCase) do - def test_with_data(data) - end - end - - test = test_case.new("test_with_data") - assert_not_predicate(test, :valid?) - test.assign_test_data("label1", :test_data1) - assert_predicate(test, :valid?) - end - - def test_data_driven_test_without_parameter - test_case = Class.new(TestCase) do - data("label" => "value") - def test_without_parameter - assert_equal("value", data) - end - end - - suite = test_case.suite - assert_equal(["test_without_parameter"], - suite.tests.collect {|test| test.method_name}) - result = TestResult.new - suite.run(result) {} - assert_equal("1 tests, 1 assertions, 0 failures, " + - "0 errors, 0 pendings, 0 omissions, 0 notifications", - result.summary) - end - - private - def check(message, passed) - add_assertion - raise AssertionFailedError.new(message) unless passed - end - - class TestTestDefined < self - class TestNoQuery < self - def test_no_test - test_case = Class.new(TestCase) do - end - assert_false(test_case.test_defined?({})) - end - - def test_have_def_style_test - test_case = Class.new(TestCase) do - def test_nothing - end - end - assert_true(test_case.test_defined?({})) - end - - def test_have_method_style_test - test_case = Class.new(TestCase) do - test "nothing" do - end - end - assert_true(test_case.test_defined?({})) - end - end - - class TestPath < self - class TestDefStyle < self - def test_base_name - test_case = Class.new(TestCase) do - def test_nothing - end - end - base_name = File.basename(__FILE__) - assert_true(test_case.test_defined?(:path => base_name)) - end - - def test_absolute_path - test_case = Class.new(TestCase) do - def test_nothing - end - end - assert_true(test_case.test_defined?(:path => __FILE__)) - end - - def test_not_match - test_case = Class.new(TestCase) do - def test_nothing - end - end - assert_false(test_case.test_defined?(:path => "nonexistent.rb")) - end - end - - class TestMethodStyle < self - def test_base_name - test_case = Class.new(TestCase) do - test "nothing" do - end - end - base_name = File.basename(__FILE__) - assert_true(test_case.test_defined?(:path => base_name)) - end - - def test_absolute_path - test_case = Class.new(TestCase) do - test "nothing" do - end - end - assert_true(test_case.test_defined?(:path => __FILE__)) - end - - def test_not_match - test_case = Class.new(TestCase) do - test "nothing" do - end - end - assert_false(test_case.test_defined?(:path => "nonexistent.rb")) - end - end - end - - class TestLine < self - class TestDefStyle < self - def test_before - line_before = nil - test_case = Class.new(TestCase) do - line_before = __LINE__ - def test_nothing - end - end - assert_false(test_case.test_defined?(:line => line_before)) - end - - def test_def - line_def = nil - test_case = Class.new(TestCase) do - line_def = __LINE__; def test_nothing - end - end - assert_true(test_case.test_defined?(:line => line_def)) - end - - def test_after - line_after = nil - test_case = Class.new(TestCase) do - def test_nothing - end - line_after = __LINE__ - end - assert_true(test_case.test_defined?(:line => line_after)) - end - - def test_child - child_test_case = nil - line_child = nil - parent_test_case = Class.new(TestCase) do - test "parent" do - end - - child_test_case = Class.new(self) do - line_child = __LINE__; test "child" do - end - end - end - assert_equal([ - false, - true, - ], - [ - parent_test_case.test_defined?(:line => line_child), - child_test_case.test_defined?(:line => line_child), - ]) - end - end - - class TestMethodStyle < self - def test_before - line_before = nil - test_case = Class.new(TestCase) do - line_before = __LINE__ - test "nothing" do - end - end - assert_false(test_case.test_defined?(:line => line_before)) - end - - def test_method - line_method = nil - test_case = Class.new(TestCase) do - line_method = __LINE__; test "nothing" do - end - end - assert_true(test_case.test_defined?(:line => line_method)) - end - - def test_after - line_after = nil - test_case = Class.new(TestCase) do - test "nothing" do - end - line_after = __LINE__ - end - assert_true(test_case.test_defined?(:line => line_after)) - end - - def test_child - child_test_case = nil - line_child = nil - parent_test_case = Class.new(TestCase) do - test "parent" do - end - - child_test_case = Class.new(self) do - line_child = __LINE__; test "child" do - end - end - end - assert_equal([ - false, - true, - ], - [ - parent_test_case.test_defined?(:line => line_child), - child_test_case.test_defined?(:line => line_child), - ]) - end - - def test_with_setup - line = nil - test_case = Class.new(TestCase) do - setup do - end - - line = __LINE__; test "with setup" do - end - end - assert do - test_case.test_defined?(:line => line, - :method_name => "test: with setup") - end - end - end - end - - class TestMethodName < self - class TestDefStyle < self - def test_match - test_case = Class.new(TestCase) do - def test_nothing - end - end - query = {:method_name => "test_nothing"} - assert_true(test_case.test_defined?(query)) - end - - def test_not_match - test_case = Class.new(TestCase) do - def test_nothing - end - end - query = {:method_name => "test_nonexistent"} - assert_false(test_case.test_defined?(query)) - end - end - - class TestMethodStyle < self - def test_match - test_case = Class.new(TestCase) do - test "nothing" do - end - end - query = {:method_name => "test: nothing"} - assert_true(test_case.test_defined?(query)) - end - - def test_not_match - test_case = Class.new(TestCase) do - test "nothing" do - end - end - query = {:method_name => "test: nonexistent"} - assert_false(test_case.test_defined?(query)) - end - end - end - - class TestCombine < self - class TestDefStyle < self - def test_line_middle - line_middle = nil - test_case = Class.new(TestCase) do - def test_before - end - line_middle = __LINE__ - def test_after - end - end - query = { - :path => __FILE__, - :line => line_middle, - :method_name => "test_before", - } - assert_true(test_case.test_defined?(query)) - end - - def test_line_after_def - line_after_def = nil - test_case = Class.new(TestCase) do - def test_before - end - - line_after_def = __LINE__; def test_after - end - end - query = { - :path => __FILE__, - :line => line_after_def, - :method_name => "test_before", - } - assert_false(test_case.test_defined?(query)) - end - end - - class TestMethodStyle < self - def test_line_middle - line_middle = nil - test_case = Class.new(TestCase) do - test "before" do - end - line_middle = __LINE__ - test "after" do - end - end - query = { - :path => __FILE__, - :line => line_middle, - :method_name => "test: before", - } - assert_true(test_case.test_defined?(query)) - end - - def test_line_after_method - line_after_method = nil - test_case = Class.new(TestCase) do - test "before" do - end - - line_after_method = __LINE__; test "after" do - end - end - query = { - :path => __FILE__, - :line => line_after_method, - :method_name => "test: before", - } - assert_false(test_case.test_defined?(query)) - end - end - end - end - - class TestSubTestCase < self - class TestName < self - def test_anonymous - test_case = Class.new(TestCase) - sub_test_case = test_case.sub_test_case("sub test case") do - end - assert_equal("sub test case", sub_test_case.name) - end - - def test_named - test_case = Class.new(TestCase) - def test_case.name - "ParentTestCase" - end - sub_test_case = test_case.sub_test_case("sub test case") do - end - assert_equal("ParentTestCase::sub test case", sub_test_case.name) - end - end - - def test_suite - test_case = Class.new(TestCase) - sub_test_case = test_case.sub_test_case("sub test case") do - def test_nothing - end - end - test_method_names = sub_test_case.suite.tests.collect do |test| - test.method_name - end - assert_equal(["test_nothing"], test_method_names) - end - - def test_duplicated_name - test_case = Class.new(TestCase) do - def test_nothing - end - end - sub_test_case = test_case.sub_test_case("sub test case") do - def test_nothing - end - end - - test_method_names = test_case.suite.tests.collect do |test| - test.method_name - end - sub_test_method_names = sub_test_case.suite.tests.collect do |test| - test.method_name - end - - assert_equal([ - ["test_nothing"], - ["test_nothing"], - ], - [ - test_method_names, - sub_test_method_names, - ]) - end - end - - class TestStartupShutdown < self - class TestOrder < self - module CallLogger - def called - @@called ||= [] - end - end - - def call_order(test_case) - test_case.called.clear - test_suite = test_case.suite - test_suite.run(TestResult.new) {} - test_case.called - end - - class TestNoInheritance < self - def setup - @test_case = Class.new(TestCase) do - extend CallLogger - - class << self - def startup - called << :startup - end - - def shutdown - called << :shutdown - end - end - - def setup - self.class.called << :setup - end - - def teardown - self.class.called << :teardown - end - - def test1 - end - - def test2 - end - end - end - - def test_call_order - assert_equal([ - :startup, - :setup, :teardown, - :setup, :teardown, - :shutdown, - ], - call_order(@test_case)) - end - end - - class TestInheritance < self - def setup - @original_descendants = TestCase::DESCENDANTS.dup - TestCase::DESCENDANTS.clear - - @parent_test_case = Class.new(TestCase) do - extend CallLogger - - self.test_order = :alphabetic - - class << self - def startup - called << :startup_parent - end - - def shutdown - called << :shutdown_parent - end - end - - def setup - self.class.called << :setup_parent - end - - def teardown - self.class.called << :teardown_parent - end - - def test1_parent - self.class.called << :test1_parent - end - - def test2_parent - self.class.called << :test2_parent - end - end - - @child_test_case = Class.new(@parent_test_case) do - class << self - def startup - called << :startup_child - end - - def shutdown - called << :shutdown_child - end - end - - def setup - self.class.called << :setup_child - end - - def teardown - self.class.called << :teardown_child - end - - def test1_child - self.class.called << :test1_child - end - - def test2_child - self.class.called << :test2_child - end - end - end - - def teardown - TestCase::DESCENDANTS.replace(@original_descendants) - end - - def test_call_order - collector = Collector::Descendant.new - test_suite = collector.collect - test_suite.run(TestResult.new) {} - called = @parent_test_case.called - assert_equal([ - :startup_parent, - :setup_parent, :test1_parent, :teardown_parent, - :setup_parent, :test2_parent, :teardown_parent, - :startup_child, - :setup_child, :test1_child, :teardown_child, - :setup_child, :test2_child, :teardown_child, - :shutdown_child, - :shutdown_parent, - ], - called) - end - end - end - - class TestError < self - def run_test_case(test_case) - test_suite = test_case.suite - result = TestResult.new - test_suite.run(result) {} - result - end - - def error_count(test_case) - run_test_case(test_case).error_count - end - - def test_on_startup - test_case = Class.new(TestCase) do - class << self - def startup - raise "from startup" - end - end - - def test_nothing - end - end - - assert_equal(1, error_count(test_case)) - end - - def test_pass_through_on_startup - test_case = Class.new(TestCase) do - class << self - def startup - raise Interrupt, "from startup" - end - end - - def test_nothing - end - end - - assert_raise(Interrupt) do - run_test_case(test_case) - end - end - - def test_on_shutdown - test_case = Class.new(TestCase) do - class << self - def shutdown - raise "from shutdown" - end - end - - def test_nothing - end - end - - assert_equal(1, error_count(test_case)) - end - - def test_pass_through_on_shutdown - test_case = Class.new(TestCase) do - class << self - def shutdown - raise Interrupt, "from shutdown" - end - end - - def test_nothing - end - end - - assert_raise(Interrupt) do - run_test_case(test_case) - end - end - - def test_pass_through_in_test - test_case = Class.new(TestCase) do - @called = [] - class << self - def called - @called - end - - def startup - @called << :startup - end - - def shutdown - @called << :shutdown - end - end - - def test_error - raise Interrupt, "from test" - end - end - - assert_raise(Interrupt) do - run_test_case(test_case) - end - assert_equal([:startup, :shutdown], - test_case.called) - end - - class TestName < self - def test_no_data - test_case = Class.new(TestCase) do - class << self - def name - "TestCase" - end - end - - def test_nothing - end - end - - test = test_case.new("test_nothing") - assert_equal("test_nothing(TestCase)", - test.name) - end - - def test_data - test_case = Class.new(TestCase) do - class << self - def name - "TestCase" - end - end - - def test_nothing - end - end - - test = test_case.new("test_nothing") - test.assign_test_data("(nil)", nil) - assert_equal("test_nothing[(nil)](TestCase)", - test.name) - end - end - - class TestLocalName < self - def test_no_data - test_case = Class.new(TestCase) do - class << self - def name - "TestCase" - end - end - - def test_nothing - end - end - - test = test_case.new("test_nothing") - assert_equal("test_nothing", - test.local_name) - end - - def test_data - test_case = Class.new(TestCase) do - class << self - def name - "TestCase" - end - end - - def test_nothing - end - end - - test = test_case.new("test_nothing") - test.assign_test_data("(nil)", nil) - assert_equal("test_nothing[(nil)]", - test.local_name) - end - end - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-test-result.rb b/ruby/gems/test-unit-3.3.4/test/test-test-result.rb deleted file mode 100644 index 889179e8e..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-test-result.rb +++ /dev/null @@ -1,113 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/testcase' -require 'test/unit/testresult' - -module Test - module Unit - class TC_TestResult < TestCase - def setup - @my_result = TestResult.new - @my_result.add_assertion() - @failure = "failure" - @my_result.add_failure(@failure) - @error = "error" - @my_result.add_error(@error) - end - - def test_result_changed_notification - called1 = false - @my_result.add_listener(TestResult::CHANGED) do |result| - assert_equal(@my_result, result) - called1 = true - end - @my_result.add_assertion - assert_true(called1) - - called1, called2 = false, false - @my_result.add_listener(TestResult::CHANGED) do |result| - assert_equal(@my_result, result) - called2 = true - end - @my_result.add_assertion - assert_equal([true, true], [called1, called2]) - - called1, called2 = false, false - @my_result.add_failure("") - assert_equal([true, true], [called1, called2]) - - called1, called2 = false, false - @my_result.add_error("") - assert_equal([true, true], [called1, called2]) - - called1, called2 = false, false - @my_result.add_run - assert_equal([true, true], [called1, called2]) - end - - def test_fault_notification - called1 = false - fault = "fault" - @my_result.add_listener(TestResult::FAULT) do |passed_fault| - assert_equal(fault, passed_fault) - called1 = true - end - - @my_result.add_assertion - assert_false(called1) - - @my_result.add_failure(fault) - assert_true(called1) - - called1, called2 = false, false - @my_result.add_listener(TestResult::FAULT) do |passed_fault| - assert_equal(fault, passed_fault) - called2 = true - end - - @my_result.add_assertion - assert_equal([false, false], [called1, called2]) - - called1, called2 = false, false - @my_result.add_failure(fault) - assert_equal([true, true], [called1, called2]) - - called1, called2 = false, false - @my_result.add_error(fault) - assert_equal([true, true], [called1, called2]) - - called1, called2 = false, false - @my_result.add_run - assert_equal([false, false], [called1, called2]) - end - - def test_passed? - result = TestResult.new - assert_true(result.passed?) - - result.add_assertion - assert_true(result.passed?) - - result.add_run - assert_true(result.passed?) - - result.add_failure("") - assert_false(result.passed?) - - result = TestResult.new - result.add_error("") - assert_false(result.passed?) - end - - def test_faults - assert_equal([@failure, @error], @my_result.faults) - - notification = "notification" - @my_result.add_notification(notification) - assert_equal([@failure, @error, notification], @my_result.faults) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-test-suite-creator.rb b/ruby/gems/test-unit-3.3.4/test/test-test-suite-creator.rb deleted file mode 100644 index b1a60746b..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-test-suite-creator.rb +++ /dev/null @@ -1,97 +0,0 @@ -require "test/unit" - -module Test - module Unit - class TestTestSuiteCreator < TestCase - def collect_test_names(test_case) - creator = TestSuiteCreator.new(test_case) - creator.send(:collect_test_names) - end - - class TestStandalone < self - def setup - @test_case = Class.new(TestCase) do - def test_in_test_case - end - end - end - - def test_collect_test_names - assert_equal(["test_in_test_case"], collect_test_names(@test_case)) - end - end - - class TestInherited < self - def setup - @parent_test_case = Class.new(TestCase) do - def test_in_parent - end - end - - @child_test_case = Class.new(@parent_test_case) do - def test_in_child - end - end - end - - def test_collect_test_names - assert_equal(["test_in_child"], collect_test_names(@child_test_case)) - end - end - - class TestModule < self - def setup - test_module = Module.new do - def test_in_module - end - end - - @test_case = Class.new(TestCase) do - include test_module - - def test_in_test_case - end - end - end - - def test_collect_test_names - assert_equal(["test_in_module", "test_in_test_case"].sort, - collect_test_names(@test_case).sort) - end - end - - class TestInheritedModule < self - def setup - parent_test_module = Module.new do - def test_in_module_in_parent - end - end - - child_test_module = Module.new do - def test_in_module_in_child - end - end - - @parent_test_case = Class.new(TestCase) do - include parent_test_module - - def test_in_parent - end - end - - @child_test_case = Class.new(@parent_test_case) do - include child_test_module - - def test_in_child - end - end - end - - def test_collect_test_names - assert_equal(["test_in_child", "test_in_module_in_child"].sort, - collect_test_names(@child_test_case).sort) - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/test-test-suite.rb b/ruby/gems/test-unit-3.3.4/test/test-test-suite.rb deleted file mode 100644 index 08bf04f65..000000000 --- a/ruby/gems/test-unit-3.3.4/test/test-test-suite.rb +++ /dev/null @@ -1,151 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' - -module Test - module Unit - class TestTestSuite < TestCase - def setup - @testcase1 = Class.new(TestCase) do - def test_succeed1 - assert_block { true } - end - def test_fail - assert_block { false } - end - end - - @testcase2 = Class.new(TestCase) do - def test_succeed2 - assert_block { true } - end - def test_error - raise - end - end - end - - def test_add - s = TestSuite.new - assert_equal(s, s << self.class.new("test_add")) - end - - def test_delete - s = TestSuite.new - t1 = self.class.new("test_delete") - s << t1 - t2 = self.class.new("test_add") - s << t2 - assert_equal(t1, s.delete(t1)) - assert_nil(s.delete(t1)) - assert_equal(TestSuite.new << t2, s) - end - - def test_delete_tests - suite = TestSuite.new - test1 = self.class.new("test_delete_1") - suite << test1 - test2 = self.class.new("test_delete_2") - suite << test2 - test3 = self.class.new("test_add") - suite << test3 - suite.delete_tests([test1, test2]) - assert_equal(1, suite.size) - assert_equal(TestSuite.new << test3, suite) - end - - def test_size - suite = TestSuite.new - suite2 = TestSuite.new - suite2 << self.class.new("test_size") - suite << suite2 - suite << self.class.new("test_size") - assert_equal(2, suite.size, "The count should be correct") - end - - def test_run - progress = [] - @testcase1.test_order = :alphabetic - suite = @testcase1.suite - tests = suite.tests.dup - result = TestResult.new - suite.run(result) { |*values| progress << values } - - assert_equal(2, result.run_count, "Should have had four test runs") - assert_equal(1, result.failure_count, "Should have had one test failure") - assert_equal(0, result.error_count, "Should have had one test error") - assert_equal([[TestSuite::STARTED, suite.name], - [TestSuite::STARTED_OBJECT, suite], - [TestCase::STARTED, "test_fail(#{suite.name})"], - [TestCase::STARTED_OBJECT, tests[0]], - [TestCase::FINISHED, "test_fail(#{suite.name})"], - [TestCase::FINISHED_OBJECT, tests[0]], - [TestCase::STARTED, "test_succeed1(#{suite.name})"], - [TestCase::STARTED_OBJECT, tests[1]], - [TestCase::FINISHED, "test_succeed1(#{suite.name})"], - [TestCase::FINISHED_OBJECT, tests[1]], - [TestSuite::FINISHED, suite.name], - [TestSuite::FINISHED_OBJECT, suite]], - progress, "Should have had the correct progress") - - suite = TestSuite.new - suite << @testcase1.suite - suite << @testcase2.suite - result = TestResult.new - progress = [] - suite.run(result) { |*values| progress << values } - - assert_equal(4, result.run_count, "Should have had four test runs") - assert_equal(1, result.failure_count, "Should have had one test failure") - assert_equal(1, result.error_count, "Should have had one test error") - assert_equal(28, progress.size, - "Should have had the correct number of progress calls") - end - - def test_empty? - assert(TestSuite.new.empty?, "A new test suite should be empty?") - assert(!@testcase2.suite.empty?, "A test suite with tests should not be empty") - end - - def test_equality - suite1 = TestSuite.new - suite2 = TestSuite.new - assert_equal(suite1, suite2) - assert_equal(suite2, suite1) - - suite1 = TestSuite.new('name') - assert_not_equal(suite1, suite2) - assert_not_equal(suite2, suite1) - - suite2 = TestSuite.new('name') - assert_equal(suite1, suite2) - assert_equal(suite2, suite1) - - suite1 << 'test' - assert_not_equal(suite1, suite2) - assert_not_equal(suite2, suite1) - - suite2 << 'test' - assert_equal(suite1, suite2) - assert_equal(suite2, suite1) - - suite2 = Object.new - class << suite2 - def name - 'name' - end - def tests - ['test'] - end - end - assert_not_equal(suite1, suite2) - assert_not_equal(suite2, suite1) - - assert_not_equal(suite1, Object.new) - assert_not_equal(Object.new, suite1) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/testunit-test-util.rb b/ruby/gems/test-unit-3.3.4/test/testunit-test-util.rb deleted file mode 100644 index 4cf83d07e..000000000 --- a/ruby/gems/test-unit-3.3.4/test/testunit-test-util.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "tempfile" - -module TestUnitTestUtil - private - def jruby? - RUBY_PLATFORM == "java" - end - - def jruby_only_test - if jruby? - require "java" - else - omit("test for JRuby") - end - end - - def assert_fault_messages(expected, faults) - assert_equal(expected, faults.collect {|fault| fault.message}) - end - - def _run_test(test_case, name) - result = Test::Unit::TestResult.new - test = test_case.new(name) - yield(test) if block_given? - test.run(result) {} - result - end - - def fixture_file_path(file_name) - base_dir = File.dirname(__FILE__) - File.join(base_dir, "fixtures", file_name) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/ui/test_testrunmediator.rb b/ruby/gems/test-unit-3.3.4/test/ui/test_testrunmediator.rb deleted file mode 100644 index 0942f8aa4..000000000 --- a/ruby/gems/test-unit-3.3.4/test/ui/test_testrunmediator.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'test/unit/ui/testrunnermediator' - -class TestUnitUIMediator < Test::Unit::TestCase - def test_run_suite_with_interrupt_exception - test_case = Class.new(Test::Unit::TestCase) do - def test_raise_interrupt - raise Interrupt, "from test" - end - end - mediator = Test::Unit::UI::TestRunnerMediator.new(test_case.suite) - finished = false - mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED) do - finished = true - end - assert_raise(Interrupt) do - mediator.run - end - assert(finished) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/util/test-method-owner-finder.rb b/ruby/gems/test-unit-3.3.4/test/util/test-method-owner-finder.rb deleted file mode 100644 index f0ec4b8d1..000000000 --- a/ruby/gems/test-unit-3.3.4/test/util/test-method-owner-finder.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'test/unit' - -require 'test/unit/util/method-owner-finder' - -class TestUnitMethodOwnerFinder < Test::Unit::TestCase - def test_find - assert_equal(Exception, find(RuntimeError.new, :inspect)) - assert_equal(Exception, find(Exception.new, :inspect)) - - anonymous_class = Class.new do - end - assert_equal(Kernel, find(anonymous_class.new, :inspect)) - - anonymous_parent_class = Class.new do - def inspect - super + " by anonymous parent class" - end - end - anonymous_sub_class = Class.new(anonymous_parent_class) do - end - assert_equal(anonymous_parent_class, find(anonymous_sub_class.new, :inspect)) - - anonymous_module = Module.new do - def inspect - super + " by anonymous module" - end - end - anonymous_include_class = Class.new do - include anonymous_module - end - assert_equal(anonymous_module, find(anonymous_include_class.new, :inspect)) - end - - private - def find(object, method_name) - Test::Unit::Util::MethodOwnerFinder.find(object, method_name) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/util/test-output.rb b/ruby/gems/test-unit-3.3.4/test/util/test-output.rb deleted file mode 100644 index 4607621c9..000000000 --- a/ruby/gems/test-unit-3.3.4/test/util/test-output.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'test/unit' - -class TestUnitOutput < Test::Unit::TestCase - def test_capture_output - assert_equal(["stdout\n", "stderr\n"], - capture_output do - puts("stdout") - warn("stderr") - end) - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/util/test_backtracefilter.rb b/ruby/gems/test-unit-3.3.4/test/util/test_backtracefilter.rb deleted file mode 100644 index c12d5dedf..000000000 --- a/ruby/gems/test-unit-3.3.4/test/util/test_backtracefilter.rb +++ /dev/null @@ -1,52 +0,0 @@ -require 'test/unit' - -require 'test/unit/util/backtracefilter' - -module Test::Unit::Util - class TestBacktraceFilter < Test::Unit::TestCase - include BacktraceFilter - - def test_filter_backtrace - backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, - %q{tc_thing.rb:4:in 'a'}, - %q{tc_thing.rb:4:in 'test_stuff'}, - %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, - %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, - %q{C:\some\old\path\test\unit.rb:44:in 'run'}, - %q{tc_thing.rb:3}] - assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") - - backtrace = [%q{tc_thing.rb:4:in 'a'}, - %q{tc_thing.rb:4:in 'test_stuff'}, - %q{tc_thing.rb:3}] - assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much") - - backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, - %q{tc_thing.rb:4:in 'a'}, - %q{tc_thing.rb:4:in 'test_stuff'}, - %q{tc_thing.rb:3}] - assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") - - backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, - %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, - %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, - %q{C:\some\old\path\test\unit.rb:44:in 'run'}] - assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") - end - - def test_nil_backtrace - assert_equal(["No backtrace"], filter_backtrace(nil)) - end - - def test_power_assert_backtrace - omit('test for power_assert') unless defined?(PowerAssert) - blk = Proc.new {caller.find {|i| /power_assert.*in \`start\'/ =~ i}} - PowerAssert.start(blk) do |pa| - backtrace = [pa.yield, - %q{tc_thing.rb:4:in 'a'}, - %q{tc_thing.rb:4:in 'test_stuff'}] - assert_equal(backtrace[1..2], filter_backtrace(backtrace)) - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/util/test_observable.rb b/ruby/gems/test-unit-3.3.4/test/util/test_observable.rb deleted file mode 100644 index 6cd10184f..000000000 --- a/ruby/gems/test-unit-3.3.4/test/util/test_observable.rb +++ /dev/null @@ -1,102 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit/util/observable' - -module Test - module Unit - module Util - class TC_Observable < TestCase - - class TF_Observable - include Observable - end - - def setup - @observable = TF_Observable.new - end - - def test_simple_observation - assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do - @observable.add_listener(:property, "a") - end - - heard = false - callback = proc { heard = true } - assert_equal("a", @observable.add_listener(:property, "a", &callback), "add_listener should return the listener that was added") - - count = 0 - @observable.instance_eval do - count = notify_listeners(:property) - end - assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified") - assert(heard, "Should have heard the property changed") - - heard = false - assert_equal(callback, @observable.remove_listener(:property, "a"), "remove_listener should return the callback") - - count = 1 - @observable.instance_eval do - count = notify_listeners(:property) - end - assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified") - assert(!heard, "Should not have heard the property change") - end - - def test_value_observation - value = nil - @observable.add_listener(:property, "a") do |passed_value| - value = passed_value - end - count = 0 - @observable.instance_eval do - count = notify_listeners(:property, "stuff") - end - assert_equal(1, count, "Should have update the correct number of listeners") - assert_equal("stuff", value, "Should have received the value as an argument to the listener") - end - - def test_multiple_value_observation - values = [] - @observable.add_listener(:property, "a") do |first_value, second_value| - values = [first_value, second_value] - end - count = 0 - @observable.instance_eval do - count = notify_listeners(:property, "stuff", "more stuff") - end - assert_equal(1, count, "Should have update the correct number of listeners") - assert_equal(["stuff", "more stuff"], values, "Should have received the value as an argument to the listener") - end - - def test_add_remove_with_default_listener - assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do - @observable.add_listener(:property) - end - - heard = false - callback = proc { heard = true } - assert_equal(callback, @observable.add_listener(:property, &callback), "add_listener should return the listener that was added") - - count = 0 - @observable.instance_eval do - count = notify_listeners(:property) - end - assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified") - assert(heard, "Should have heard the property changed") - - heard = false - assert_equal(callback, @observable.remove_listener(:property, callback), "remove_listener should return the callback") - - count = 1 - @observable.instance_eval do - count = notify_listeners(:property) - end - assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified") - assert(!heard, "Should not have heard the property change") - end - end - end - end -end diff --git a/ruby/gems/test-unit-3.3.4/test/util/test_procwrapper.rb b/ruby/gems/test-unit-3.3.4/test/util/test_procwrapper.rb deleted file mode 100644 index 3e552c771..000000000 --- a/ruby/gems/test-unit-3.3.4/test/util/test_procwrapper.rb +++ /dev/null @@ -1,36 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require 'test/unit/util/procwrapper' - -module Test - module Unit - module Util - class TC_ProcWrapper < TestCase - def munge_proc(&a_proc) - return a_proc - end - def setup - @original = proc {} - @munged = munge_proc(&@original) - @wrapped_original = ProcWrapper.new(@original) - @wrapped_munged = ProcWrapper.new(@munged) - end - def test_wrapping - assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped") - end - def test_hashing - - assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped") - assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent") - - a_hash = {@wrapped_original => @original} - assert(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash") - assert_equal(a_hash[@wrapped_original], @original, "Should be able to access the wrapper in the hash") - end - end - end - end -end diff --git a/ruby/gems/xmlrpc-0.3.0.gem b/ruby/gems/xmlrpc-0.3.0.gem deleted file mode 100644 index c63a38bfb..000000000 Binary files a/ruby/gems/xmlrpc-0.3.0.gem and /dev/null differ diff --git a/ruby/gems/xmlrpc-0.3.0/.gitignore b/ruby/gems/xmlrpc-0.3.0/.gitignore deleted file mode 100644 index 0cb6eeb06..000000000 --- a/ruby/gems/xmlrpc-0.3.0/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/.bundle/ -/.yardoc -/Gemfile.lock -/_yardoc/ -/coverage/ -/doc/ -/pkg/ -/spec/reports/ -/tmp/ diff --git a/ruby/gems/xmlrpc-0.3.0/.travis.yml b/ruby/gems/xmlrpc-0.3.0/.travis.yml deleted file mode 100644 index 8481012e3..000000000 --- a/ruby/gems/xmlrpc-0.3.0/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: ruby -rvm: - - 2.3.3 - - 2.4.0 - - ruby-head -before_install: gem update bundler diff --git a/ruby/gems/xmlrpc-0.3.0/Gemfile b/ruby/gems/xmlrpc-0.3.0/Gemfile deleted file mode 100644 index fa75df156..000000000 --- a/ruby/gems/xmlrpc-0.3.0/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' - -gemspec diff --git a/ruby/gems/xmlrpc-0.3.0/LICENSE.txt b/ruby/gems/xmlrpc-0.3.0/LICENSE.txt deleted file mode 100644 index a1f19ff99..000000000 --- a/ruby/gems/xmlrpc-0.3.0/LICENSE.txt +++ /dev/null @@ -1,56 +0,0 @@ -Ruby is copyrighted free software by Yukihiro Matsumoto . -You can redistribute it and/or modify it under either the terms of the -2-clause BSDL (see the file BSDL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. diff --git a/ruby/gems/xmlrpc-0.3.0/README.md b/ruby/gems/xmlrpc-0.3.0/README.md deleted file mode 100644 index 925ef0f20..000000000 --- a/ruby/gems/xmlrpc-0.3.0/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# XMLRPC - -[![Build Status](https://travis-ci.org/ruby/xmlrpc.svg?branch=master)](https://travis-ci.org/ruby/xmlrpc) - -## Overview - -XMLRPC is a lightweight protocol that enables remote procedure calls over -HTTP. It is defined at http://www.xmlrpc.com. - -XMLRPC allows you to create simple distributed computing solutions that span -computer languages. Its distinctive feature is its simplicity compared to -other approaches like SOAP and CORBA. - -The Ruby standard library package 'xmlrpc' enables you to create a server that -implements remote procedures and a client that calls them. Very little code -is required to achieve either of these. - -## Installation - -Add this line to your application's Gemfile: - -```ruby -gem 'xmlrpc' -``` - -And then execute: - - $ bundle - -Or install it yourself as: - - $ gem install xmlrpc - -## Example - -Try the following code. It calls a standard demonstration remote procedure. - -```ruby -require 'xmlrpc/client' -require 'pp' - -server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php") -result = server.call("sample.sumAndDifference", 5, 3) -pp result -``` - -## Development - -After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. - -To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). - -## Contributing - -Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/xmlrpc. - - -## License - -Released under the same term of license as Ruby. diff --git a/ruby/gems/xmlrpc-0.3.0/Rakefile b/ruby/gems/xmlrpc-0.3.0/Rakefile deleted file mode 100644 index 251574e60..000000000 --- a/ruby/gems/xmlrpc-0.3.0/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -require "bundler/gem_tasks" -require "rake/testtask" - -Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.libs << "lib" - t.test_files = FileList['test/**/test_*.rb'] -end - -task :default => :test diff --git a/ruby/gems/xmlrpc-0.3.0/bin/console b/ruby/gems/xmlrpc-0.3.0/bin/console deleted file mode 100755 index 1e4918856..000000000 --- a/ruby/gems/xmlrpc-0.3.0/bin/console +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby - -require "bundler/setup" -require "xmlrpc" - -# You can add fixtures and/or initialization code here to make experimenting -# with your gem easier. You can also use a different console, if you like. - -# (If you use this, don't forget to add pry to your Gemfile!) -# require "pry" -# Pry.start - -require "irb" -IRB.start diff --git a/ruby/gems/xmlrpc-0.3.0/bin/setup b/ruby/gems/xmlrpc-0.3.0/bin/setup deleted file mode 100755 index dce67d860..000000000 --- a/ruby/gems/xmlrpc-0.3.0/bin/setup +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -IFS=$'\n\t' -set -vx - -bundle install - -# Do any other automated setup that you need to do here diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc.rb deleted file mode 100644 index 1c65ed75f..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc.rb +++ /dev/null @@ -1,293 +0,0 @@ -# frozen_string_literal: false -# == Author and Copyright -# -# Copyright (C) 2001-2004 by Michael Neumann (mailto:mneumann@ntecs.de) -# -# Released under the same term of license as Ruby. -# -# == Overview -# -# XMLRPC is a lightweight protocol that enables remote procedure calls over -# HTTP. It is defined at http://www.xmlrpc.com. -# -# XMLRPC allows you to create simple distributed computing solutions that span -# computer languages. Its distinctive feature is its simplicity compared to -# other approaches like SOAP and CORBA. -# -# The Ruby standard library package 'xmlrpc' enables you to create a server that -# implements remote procedures and a client that calls them. Very little code -# is required to achieve either of these. -# -# == Example -# -# Try the following code. It calls a standard demonstration remote procedure. -# -# require 'xmlrpc/client' -# require 'pp' -# -# server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php") -# result = server.call("sample.sumAndDifference", 5, 3) -# pp result -# -# == Documentation -# -# See http://www.ntecs.de/ruby/xmlrpc4r/. There is plenty of detail there to -# use the client and implement a server. -# -# == Features of XMLRPC for Ruby -# -# * Extensions -# * Introspection -# * multiCall -# * optionally nil values and integers larger than 32 Bit -# -# * Server -# * Standalone XML-RPC server -# * CGI-based (works with FastCGI) -# * Apache mod_ruby server -# * WEBrick servlet -# -# * Client -# * synchronous/asynchronous calls -# * Basic HTTP-401 Authentication -# * HTTPS protocol (SSL) -# -# * Parsers -# * REXML (XMLParser::REXMLStreamParser) -# * Not compiled (pure ruby) -# * See ruby standard library -# * libxml (LibXMLStreamParser) -# * Compiled -# * See https://rubygems.org/gems/libxml-ruby/ -# -# * General -# * possible to choose between XMLParser module (Expat wrapper) and REXML (pure Ruby) parsers -# * Marshalling Ruby objects to Hashes and reconstruct them later from a Hash -# * SandStorm component architecture XMLRPC::Client interface -# -# == Howto -# -# === Client -# -# require "xmlrpc/client" -# -# # Make an object to represent the XML-RPC server. -# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") -# -# # Call the remote server and get our result -# result = server.call("sample.sumAndDifference", 5, 3) -# -# sum = result["sum"] -# difference = result["difference"] -# -# puts "Sum: #{sum}, Difference: #{difference}" -# -# === XMLRPC::Client with XML-RPC fault-structure handling -# -# There are two possible ways, of handling a fault-structure: -# -# ==== by catching a XMLRPC::FaultException exception -# -# require "xmlrpc/client" -# -# # Make an object to represent the XML-RPC server. -# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") -# -# begin -# # Call the remote server and get our result -# result = server.call("sample.sumAndDifference", 5, 3) -# -# sum = result["sum"] -# difference = result["difference"] -# -# puts "Sum: #{sum}, Difference: #{difference}" -# -# rescue XMLRPC::FaultException => e -# puts "Error: " -# puts e.faultCode -# puts e.faultString -# end -# -# ==== by calling "call2" which returns a boolean -# -# require "xmlrpc/client" -# -# # Make an object to represent the XML-RPC server. -# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") -# -# # Call the remote server and get our result -# ok, result = server.call2("sample.sumAndDifference", 5, 3) -# -# if ok -# sum = result["sum"] -# difference = result["difference"] -# -# puts "Sum: #{sum}, Difference: #{difference}" -# else -# puts "Error: " -# puts result.faultCode -# puts result.faultString -# end -# -# === Using XMLRPC::Client::Proxy -# -# You can create a Proxy object onto which you can call methods. This way it -# looks nicer. Both forms, _call_ and _call2_ are supported through _proxy_ and -# _proxy2_. You can additionally give arguments to the Proxy, which will be -# given to each XML-RPC call using that Proxy. -# -# require "xmlrpc/client" -# -# # Make an object to represent the XML-RPC server. -# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") -# -# # Create a Proxy object -# sample = server.proxy("sample") -# -# # Call the remote server and get our result -# result = sample.sumAndDifference(5,3) -# -# sum = result["sum"] -# difference = result["difference"] -# -# puts "Sum: #{sum}, Difference: #{difference}" -# -# === CGI-based server using XMLRPC::CGIServer -# -# There are also two ways to define handler, the first is -# like C/PHP, the second like Java, of course both ways -# can be mixed: -# -# ==== C/PHP-like (handler functions) -# -# require "xmlrpc/server" -# -# s = XMLRPC::CGIServer.new -# -# s.add_handler("sample.sumAndDifference") do |a,b| -# { "sum" => a + b, "difference" => a - b } -# end -# -# s.serve -# -# ==== Java-like (handler classes) -# -# require "xmlrpc/server" -# -# s = XMLRPC::CGIServer.new -# -# class MyHandler -# def sumAndDifference(a, b) -# { "sum" => a + b, "difference" => a - b } -# end -# end -# -# # NOTE: Security Hole (read below)!!! -# s.add_handler("sample", MyHandler.new) -# s.serve -# -# -# To return a fault-structure you have to raise an XMLRPC::FaultException e.g.: -# -# raise XMLRPC::FaultException.new(3, "division by Zero") -# -# ===== Security Note -# -# From Brian Candler: -# -# Above code sample has an extremely nasty security hole, in that you can now call -# any method of 'MyHandler' remotely, including methods inherited from Object -# and Kernel! For example, in the client code, you can use -# -# puts server.call("sample.send","`","ls") -# -# (backtick being the method name for running system processes). Needless to -# say, 'ls' can be replaced with something else. -# -# The version which binds proc objects (or the version presented below in the next section) -# doesn't have this problem, but people may be tempted to use the second version because it's -# so nice and 'Rubyesque'. I think it needs a big red disclaimer. -# -# -# From Michael: -# -# A solution is to undef insecure methods or to use -# XMLRPC::Service::PublicInstanceMethodsInterface as shown below: -# -# class MyHandler -# def sumAndDifference(a, b) -# { "sum" => a + b, "difference" => a - b } -# end -# end -# -# # ... server initialization ... -# -# s.add_handler(XMLRPC::iPIMethods("sample"), MyHandler.new) -# -# # ... -# -# This adds only public instance methods explicitly declared in class MyHandler -# (and not those inherited from any other class). -# -# ==== With interface declarations -# -# Code sample from the book Ruby Developer's Guide: -# -# require "xmlrpc/server" -# -# class Num -# INTERFACE = XMLRPC::interface("num") { -# meth 'int add(int, int)', 'Add two numbers', 'add' -# meth 'int div(int, int)', 'Divide two numbers' -# } -# -# def add(a, b) a + b end -# def div(a, b) a / b end -# end -# -# -# s = XMLRPC::CGIServer.new -# s.add_handler(Num::INTERFACE, Num.new) -# s.serve -# -# === Standalone XMLRPC::Server -# -# Same as CGI-based server, the only difference being -# -# server = XMLRPC::CGIServer.new -# -# must be changed to -# -# server = XMLRPC::Server.new(8080) -# -# if you want a server listening on port 8080. -# The rest is the same. -# -# === Choosing a different XMLParser or XMLWriter -# -# The examples above all use the default parser (which is now since 1.8 -# XMLParser::REXMLStreamParser) and a default XMLRPC::XMLWriter. -# If you want to use a different XMLParser, then you have to call the -# ParserWriterChooseMixin#set_parser method of XMLRPC::Client instances -# or instances of subclasses of XMLRPC::BasicServer or by editing -# xmlrpc/config.rb. -# -# XMLRPC::Client Example: -# -# # ... -# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") -# server.set_parser(XMLRPC::XMLParser::XMLParser.new) -# # ... -# -# XMLRPC::Server Example: -# -# # ... -# s = XMLRPC::CGIServer.new -# s.set_parser(XMLRPC::XMLParser::XMLParser.new) -# # ... -# -# -# You can change the XML-writer by calling method ParserWriterChooseMixin#set_writer. -module XMLRPC - VERSION = "0.3.0" -end diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/base64.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/base64.rb deleted file mode 100644 index 21f8c65ce..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/base64.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: false -# -# xmlrpc/base64.rb -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# Released under the same term of license as Ruby. - -module XMLRPC # :nodoc: - -# This class is necessary for 'xmlrpc4r' to determine that a string should -# be transmitted base64-encoded and not as a raw-string. -# -# You can use XMLRPC::Base64 on the client and server-side as a -# parameter and/or return-value. -class Base64 - - # Creates a new XMLRPC::Base64 instance with string +str+ as the - # internal string. When +state+ is +:dec+ it assumes that the - # string +str+ is not in base64 format (perhaps already decoded), - # otherwise if +state+ is +:enc+ it decodes +str+ - # and stores it as the internal string. - def initialize(str, state = :dec) - case state - when :enc - @str = Base64.decode(str) - when :dec - @str = str - else - raise ArgumentError, "wrong argument; either :enc or :dec" - end - end - - # Returns the decoded internal string. - def decoded - @str - end - - # Returns the base64 encoded internal string. - def encoded - Base64.encode(@str) - end - - - # Decodes string +str+ with base64 and returns that value. - def Base64.decode(str) - str.gsub(/\s+/, "").unpack("m")[0] - end - - # Encodes string +str+ with base64 and returns that value. - def Base64.encode(str) - [str].pack("m") - end - -end - - -end # module XMLRPC - - -=begin -= History - $Id$ -=end diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb deleted file mode 100644 index f3b70801e..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb +++ /dev/null @@ -1,629 +0,0 @@ -# frozen_string_literal: false -# xmlrpc/client.rb -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# Released under the same term of license as Ruby. -# -# History -# $Id$ -# -require "xmlrpc/parser" -require "xmlrpc/create" -require "xmlrpc/config" -require "xmlrpc/utils" # ParserWriterChooseMixin -require "net/http" -require "uri" - -module XMLRPC # :nodoc: - - # Provides remote procedure calls to a XML-RPC server. - # - # After setting the connection-parameters with XMLRPC::Client.new which - # creates a new XMLRPC::Client instance, you can execute a remote procedure - # by sending the XMLRPC::Client#call or XMLRPC::Client#call2 - # message to this new instance. - # - # The given parameters indicate which method to call on the remote-side and - # of course the parameters for the remote procedure. - # - # require "xmlrpc/client" - # - # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) - # begin - # param = server.call("michael.add", 4, 5) - # puts "4 + 5 = #{param}" - # rescue XMLRPC::FaultException => e - # puts "Error:" - # puts e.faultCode - # puts e.faultString - # end - # - # or - # - # require "xmlrpc/client" - # - # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) - # ok, param = server.call2("michael.add", 4, 5) - # if ok then - # puts "4 + 5 = #{param}" - # else - # puts "Error:" - # puts param.faultCode - # puts param.faultString - # end - class Client - - USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})" - - include ParserWriterChooseMixin - include ParseContentType - - - # Creates an object which represents the remote XML-RPC server on the - # given +host+. If the server is CGI-based, +path+ is the - # path to the CGI-script, which will be called, otherwise (in the - # case of a standalone server) +path+ should be "/RPC2". - # +port+ is the port on which the XML-RPC server listens. - # - # If +proxy_host+ is given, then a proxy server listening at - # +proxy_host+ is used. +proxy_port+ is the port of the - # proxy server. - # - # Default values for +host+, +path+ and +port+ are 'localhost', '/RPC2' and - # '80' respectively using SSL '443'. - # - # If +user+ and +password+ are given, each time a request is sent, - # an Authorization header is sent. Currently only Basic Authentication is - # implemented, no Digest. - # - # If +use_ssl+ is set to +true+, communication over SSL is enabled. - # - # Parameter +timeout+ is the time to wait for a XML-RPC response, defaults to 30. - def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, - user=nil, password=nil, use_ssl=nil, timeout=nil) - - @http_header_extra = nil - @http_last_response = nil - @cookie = nil - - @host = host || "localhost" - @path = path || "/RPC2" - @proxy_host = proxy_host - @proxy_port = proxy_port - @proxy_host ||= 'localhost' if @proxy_port != nil - @proxy_port ||= 8080 if @proxy_host != nil - @use_ssl = use_ssl || false - @timeout = timeout || 30 - - if use_ssl - require "net/https" - @port = port || 443 - else - @port = port || 80 - end - - @user, @password = user, password - - set_auth - - # convert ports to integers - @port = @port.to_i if @port != nil - @proxy_port = @proxy_port.to_i if @proxy_port != nil - - # HTTP object for synchronous calls - @http = net_http(@host, @port, @proxy_host, @proxy_port) - @http.use_ssl = @use_ssl if @use_ssl - @http.read_timeout = @timeout - @http.open_timeout = @timeout - - @parser = nil - @create = nil - end - - - class << self - - # Creates an object which represents the remote XML-RPC server at the - # given +uri+. The URI should have a host, port, path, user and password. - # Example: https://user:password@host:port/path - # - # Raises an ArgumentError if the +uri+ is invalid, - # or if the protocol isn't http or https. - # - # If a +proxy+ is given it should be in the form of "host:port". - # - # The optional +timeout+ defaults to 30 seconds. - def new2(uri, proxy=nil, timeout=nil) - begin - url = URI(uri) - rescue URI::InvalidURIError => e - raise ArgumentError, e.message, e.backtrace - end - - unless URI::HTTP === url - raise ArgumentError, "Wrong protocol specified. Only http or https allowed!" - end - - proto = url.scheme - user = url.user - passwd = url.password - host = url.host - port = url.port - path = url.path.empty? ? nil : url.request_uri - - proxy_host, proxy_port = (proxy || "").split(":") - proxy_port = proxy_port.to_i if proxy_port - - self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout) - end - - alias new_from_uri new2 - - # Receives a Hash and calls XMLRPC::Client.new - # with the corresponding values. - # - # The +hash+ parameter has following case-insensitive keys: - # * host - # * path - # * port - # * proxy_host - # * proxy_port - # * user - # * password - # * use_ssl - # * timeout - def new3(hash={}) - - # convert all keys into lowercase strings - h = {} - hash.each { |k,v| h[k.to_s.downcase] = v } - - self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'], - h['use_ssl'], h['timeout']) - end - - alias new_from_hash new3 - - end - - - # Returns the Net::HTTP object for the client. If you want to - # change HTTP client options except header, cookie, timeout, - # user and password, use Net::HTTP directly. - # - # Since 2.1.0. - attr_reader :http - - # Add additional HTTP headers to the request - attr_accessor :http_header_extra - - # Returns the Net::HTTPResponse object of the last RPC. - attr_reader :http_last_response - - # Get and set the HTTP Cookie header. - attr_accessor :cookie - - - # Return the corresponding attributes. - attr_reader :timeout, :user, :password - - # Sets the Net::HTTP#read_timeout and Net::HTTP#open_timeout to - # +new_timeout+ - def timeout=(new_timeout) - @timeout = new_timeout - @http.read_timeout = @timeout - @http.open_timeout = @timeout - end - - # Changes the user for the Basic Authentication header to +new_user+ - def user=(new_user) - @user = new_user - set_auth - end - - # Changes the password for the Basic Authentication header to - # +new_password+ - def password=(new_password) - @password = new_password - set_auth - end - - # Invokes the method named +method+ with the parameters given by - # +args+ on the XML-RPC server. - # - # The +method+ parameter is converted into a String and should - # be a valid XML-RPC method-name. - # - # Each parameter of +args+ must be of one of the following types, - # where Hash, Struct and Array can contain any of these listed _types_: - # - # * Integer - # * TrueClass, FalseClass, +true+, +false+ - # * String, Symbol - # * Float - # * Hash, Struct - # * Array - # * Date, Time, XMLRPC::DateTime - # * XMLRPC::Base64 - # * A Ruby object which class includes XMLRPC::Marshallable - # (only if Config::ENABLE_MARSHALLING is +true+). - # That object is converted into a hash, with one additional key/value - # pair ___class___ which contains the class name - # for restoring that object later. - # - # The method returns the return-value from the Remote Procedure Call. - # - # The type of the return-value is one of the types shown above. - # - # An Integer is only allowed when it fits in 32-bit. A XML-RPC - # +dateTime.iso8601+ type is always returned as a XMLRPC::DateTime object. - # Struct is never returned, only a Hash, the same for a Symbol, where as a - # String is always returned. XMLRPC::Base64 is returned as a String from - # xmlrpc4r version 1.6.1 on. - # - # If the remote procedure returned a fault-structure, then a - # XMLRPC::FaultException exception is raised, which has two accessor-methods - # +faultCode+ an Integer, and +faultString+ a String. - def call(method, *args) - ok, param = call2(method, *args) - if ok - param - else - raise param - end - end - - # The difference between this method and XMLRPC::Client#call is, that - # this method will NOT raise a XMLRPC::FaultException exception. - # - # The method returns an array of two values. The first value indicates if - # the second value is +true+ or an XMLRPC::FaultException. - # - # Both are explained in XMLRPC::Client#call. - # - # Simple to remember: The "2" in "call2" denotes the number of values it returns. - def call2(method, *args) - request = create().methodCall(method, *args) - data = do_rpc(request, false) - parser().parseMethodResponse(data) - end - - # Similar to XMLRPC::Client#call, however can be called concurrently and - # use a new connection for each request. In contrast to the corresponding - # method without the +_async+ suffix, which use connect-alive (one - # connection for all requests). - # - # Note, that you have to use Thread to call these methods concurrently. - # The following example calls two methods concurrently: - # - # Thread.new { - # p client.call_async("michael.add", 4, 5) - # } - # - # Thread.new { - # p client.call_async("michael.div", 7, 9) - # } - # - def call_async(method, *args) - ok, param = call2_async(method, *args) - if ok - param - else - raise param - end - end - - # Same as XMLRPC::Client#call2, but can be called concurrently. - # - # See also XMLRPC::Client#call_async - def call2_async(method, *args) - request = create().methodCall(method, *args) - data = do_rpc(request, true) - parser().parseMethodResponse(data) - end - - - # You can use this method to execute several methods on a XMLRPC server - # which support the multi-call extension. - # - # s.multicall( - # ['michael.add', 3, 4], - # ['michael.sub', 4, 5] - # ) - # # => [7, -1] - def multicall(*methods) - ok, params = multicall2(*methods) - if ok - params - else - raise params - end - end - - # Same as XMLRPC::Client#multicall, but returns two parameters instead of - # raising an XMLRPC::FaultException. - # - # See XMLRPC::Client#call2 - def multicall2(*methods) - gen_multicall(methods, false) - end - - # Similar to XMLRPC::Client#multicall, however can be called concurrently and - # use a new connection for each request. In contrast to the corresponding - # method without the +_async+ suffix, which use connect-alive (one - # connection for all requests). - # - # Note, that you have to use Thread to call these methods concurrently. - # The following example calls two methods concurrently: - # - # Thread.new { - # p client.multicall_async("michael.add", 4, 5) - # } - # - # Thread.new { - # p client.multicall_async("michael.div", 7, 9) - # } - # - def multicall_async(*methods) - ok, params = multicall2_async(*methods) - if ok - params - else - raise params - end - end - - # Same as XMLRPC::Client#multicall2, but can be called concurrently. - # - # See also XMLRPC::Client#multicall_async - def multicall2_async(*methods) - gen_multicall(methods, true) - end - - - # Returns an object of class XMLRPC::Client::Proxy, initialized with - # +prefix+ and +args+. - # - # A proxy object returned by this method behaves like XMLRPC::Client#call, - # i.e. a call on that object will raise a XMLRPC::FaultException when a - # fault-structure is returned by that call. - def proxy(prefix=nil, *args) - Proxy.new(self, prefix, args, :call) - end - - # Almost the same like XMLRPC::Client#proxy only that a call on the returned - # XMLRPC::Client::Proxy object will return two parameters. - # - # See XMLRPC::Client#call2 - def proxy2(prefix=nil, *args) - Proxy.new(self, prefix, args, :call2) - end - - # Similar to XMLRPC::Client#proxy, however can be called concurrently and - # use a new connection for each request. In contrast to the corresponding - # method without the +_async+ suffix, which use connect-alive (one - # connection for all requests). - # - # Note, that you have to use Thread to call these methods concurrently. - # The following example calls two methods concurrently: - # - # Thread.new { - # p client.proxy_async("michael.add", 4, 5) - # } - # - # Thread.new { - # p client.proxy_async("michael.div", 7, 9) - # } - # - def proxy_async(prefix=nil, *args) - Proxy.new(self, prefix, args, :call_async) - end - - # Same as XMLRPC::Client#proxy2, but can be called concurrently. - # - # See also XMLRPC::Client#proxy_async - def proxy2_async(prefix=nil, *args) - Proxy.new(self, prefix, args, :call2_async) - end - - - private - - def net_http(host, port, proxy_host, proxy_port) - Net::HTTP.new host, port, proxy_host, proxy_port - end - - def dup_net_http - http = net_http(@http.address, - @http.port, - @http.proxy_address, - @http.proxy_port) - http.proxy_user = @http.proxy_user - http.proxy_pass = @http.proxy_pass - if @http.use_ssl? - http.use_ssl = true - Net::HTTP::SSL_ATTRIBUTES.each do |attribute| - http.__send__("#{attribute}=", @http.__send__(attribute)) - end - end - http.read_timeout = @http.read_timeout - http.open_timeout = @http.open_timeout - http - end - - def set_auth - if @user.nil? - @auth = nil - else - a = "#@user" - a << ":#@password" if @password != nil - @auth = "Basic " + [a].pack("m0") - end - end - - def do_rpc(request, async=false) - header = { - "User-Agent" => USER_AGENT, - "Content-Type" => "text/xml; charset=utf-8", - "Content-Length" => request.bytesize.to_s, - "Connection" => (async ? "close" : "keep-alive") - } - - header["Cookie"] = @cookie if @cookie - header.update(@http_header_extra) if @http_header_extra - - if @auth != nil - # add authorization header - header["Authorization"] = @auth - end - - resp = nil - @http_last_response = nil - - if async - # use a new HTTP object for each call - http = dup_net_http - - # post request - http.start { - resp = http.request_post(@path, request, header) - } - else - # reuse the HTTP object for each call => connection alive is possible - # we must start connection explicitly first time so that http.request - # does not assume that we don't want keepalive - @http.start if not @http.started? - - # post request - resp = @http.request_post(@path, request, header) - end - - @http_last_response = resp - - data = resp.body - - if resp.code == "401" - # Authorization Required - raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}" - elsif resp.code[0,1] != "2" - raise "HTTP-Error: #{resp.code} #{resp.message}" - end - - # assume text/xml on instances where Content-Type header is not set - ct_expected = resp["Content-Type"] || 'text/xml' - ct = parse_content_type(ct_expected).first - if ct != "text/xml" - if ct == "text/html" - raise "Wrong content-type (received '#{ct}' but expected 'text/xml'): \n#{data}" - else - raise "Wrong content-type (received '#{ct}' but expected 'text/xml')" - end - end - - expected = resp["Content-Length"] || "" - if data.nil? or data.bytesize == 0 - raise "Wrong size. Was #{data.bytesize}, should be #{expected}" - end - - parse_set_cookies(resp.get_fields("Set-Cookie")) - - return data - end - - def parse_set_cookies(set_cookies) - return if set_cookies.nil? - return if set_cookies.empty? - require 'webrick/cookie' - pairs = {} - set_cookies.each do |set_cookie| - cookie = WEBrick::Cookie.parse_set_cookie(set_cookie) - pairs.delete(cookie.name) - pairs[cookie.name] = cookie.value - end - cookies = pairs.collect do |name, value| - WEBrick::Cookie.new(name, value).to_s - end - @cookie = cookies.join("; ") - end - - def gen_multicall(methods=[], async=false) - meth = :call2 - meth = :call2_async if async - - ok, params = self.send(meth, "system.multicall", - methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} } - ) - - if ok - params = params.collect do |param| - if param.is_a? Array - param[0] - elsif param.is_a? Hash - XMLRPC::FaultException.new(param["faultCode"], param["faultString"]) - else - raise "Wrong multicall return value" - end - end - end - - return ok, params - end - - - - # XML-RPC calls look nicer! - # - # You can call any method onto objects of that class - the object handles - # XMLRPC::Client::Proxy#method_missing and will forward the method call to - # a XML-RPC server. - # - # Don't use this class directly, instead use the public instance method - # XMLRPC::Client#proxy or XMLRPC::Client#proxy2. - # - # require "xmlrpc/client" - # - # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) - # - # michael = server.proxy("michael") - # michael2 = server.proxy("michael", 4) - # - # # both calls should return the same value '9'. - # p michael.add(4,5) - # p michael2.add(5) - class Proxy - - # Creates an object which provides XMLRPC::Client::Proxy#method_missing. - # - # The given +server+ must be an instance of XMLRPC::Client, which is the - # XML-RPC server to be used for a XML-RPC call. - # - # +prefix+ and +delim+ will be prepended to the method name called onto this object. - # - # An optional parameter +meth+ is the method to use for a RPC. - # It can be either, call, call2, call_async, call2_async - # - # +args+ are arguments which are automatically given to every XML-RPC - # call before being provided through +method_missing+. - def initialize(server, prefix, args=[], meth=:call, delim=".") - @server = server - @prefix = prefix ? prefix + delim : "" - @args = args - @meth = meth - end - - # Every method call is forwarded to the XML-RPC server defined in - # XMLRPC::Client::Proxy#new. - # - # Note: Inherited methods from class Object cannot be used as XML-RPC - # names, because they get around +method_missing+. - def method_missing(mid, *args) - pre = @prefix + mid.to_s - arg = @args + args - @server.send(@meth, pre, *arg) - end - - end # class Proxy - - end # class Client - -end # module XMLRPC diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/config.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/config.rb deleted file mode 100644 index b7ed7a9f7..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/config.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: false -# -# $Id$ -# Configuration file for XML-RPC for Ruby -# - -module XMLRPC # :nodoc: - - module Config - - # or XMLWriter::XMLParser - DEFAULT_WRITER = XMLWriter::Simple - - # === Available parsers - # - # * XMLParser::REXMLStreamParser - # * XMLParser::LibXMLStreamParser - DEFAULT_PARSER = XMLParser::REXMLStreamParser - - # enable tag - ENABLE_NIL_CREATE = false - ENABLE_NIL_PARSER = false - - # allows integers greater than 32-bit if +true+ - ENABLE_BIGINT = false - - # enable marshalling Ruby objects which include XMLRPC::Marshallable - ENABLE_MARSHALLING = true - - # enable multiCall extension by default - ENABLE_MULTICALL = false - - # enable Introspection extension by default - ENABLE_INTROSPECTION = false - - end - -end - diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/create.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/create.rb deleted file mode 100644 index 2e246df49..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/create.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: false -# -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# $Id$ -# - -require "date" -require "xmlrpc/base64" - -module XMLRPC # :nodoc: - - module XMLWriter - - class Abstract - def ele(name, *children) - element(name, nil, *children) - end - - def tag(name, txt) - element(name, nil, text(txt)) - end - end - - - class Simple < Abstract - - def document_to_str(doc) - doc - end - - def document(*params) - params.join("") - end - - def pi(name, *params) - "" - end - - def element(name, attrs, *children) - raise "attributes not yet implemented" unless attrs.nil? - if children.empty? - "<#{name}/>" - else - "<#{name}>" + children.join("") + "" - end - end - - def text(txt) - cleaned = txt.dup - cleaned.gsub!(/&/, '&') - cleaned.gsub!(//, '>') - cleaned - end - - end # class Simple - - - class XMLParser < Abstract - - def initialize - require "xmltreebuilder" - end - - def document_to_str(doc) - doc.to_s - end - - def document(*params) - XML::SimpleTree::Document.new(*params) - end - - def pi(name, *params) - XML::SimpleTree::ProcessingInstruction.new(name, *params) - end - - def element(name, attrs, *children) - XML::SimpleTree::Element.new(name, attrs, *children) - end - - def text(txt) - XML::SimpleTree::Text.new(txt) - end - - end # class XMLParser - - Classes = [Simple, XMLParser] - - # yields an instance of each installed XML writer - def self.each_installed_writer - XMLRPC::XMLWriter::Classes.each do |klass| - begin - yield klass.new - rescue LoadError - end - end - end - - end # module XMLWriter - - # Creates XML-RPC call/response documents - # - class Create - - def initialize(xml_writer = nil) - @writer = xml_writer || Config::DEFAULT_WRITER.new - end - - - def methodCall(name, *params) - name = name.to_s - - if name !~ /[a-zA-Z0-9_.:\/]+/ - raise ArgumentError, "Wrong XML-RPC method-name" - end - - parameter = params.collect do |param| - @writer.ele("param", conv2value(param)) - end - - tree = @writer.document( - @writer.pi("xml", 'version="1.0"'), - @writer.ele("methodCall", - @writer.tag("methodName", name), - @writer.ele("params", *parameter) - ) - ) - - @writer.document_to_str(tree) + "\n" - end - - - - # - # Generates a XML-RPC methodResponse document - # - # When +is_ret+ is +false+ then the +params+ array must - # contain only one element, which is a structure - # of a fault return-value. - # - # When +is_ret+ is +true+ then a normal - # return-value of all the given +params+ is created. - # - def methodResponse(is_ret, *params) - - if is_ret - resp = params.collect do |param| - @writer.ele("param", conv2value(param)) - end - - resp = [@writer.ele("params", *resp)] - else - if params.size != 1 or params[0] === XMLRPC::FaultException - raise ArgumentError, "no valid fault-structure given" - end - resp = @writer.ele("fault", conv2value(params[0].to_h)) - end - - - tree = @writer.document( - @writer.pi("xml", 'version="1.0"'), - @writer.ele("methodResponse", resp) - ) - - @writer.document_to_str(tree) + "\n" - end - - - - private - - # - # Converts a Ruby object into a XML-RPC tag - # - def conv2value(param) # :doc: - - val = case param - when Integer - # XML-RPC's int is 32bit int - if Config::ENABLE_BIGINT - @writer.tag("i4", param.to_s) - else - if param >= -(2**31) and param <= (2**31-1) - @writer.tag("i4", param.to_s) - else - raise "Integer is too big! Must be signed 32-bit integer!" - end - end - when TrueClass, FalseClass - @writer.tag("boolean", param ? "1" : "0") - - when Symbol - @writer.tag("string", param.to_s) - - when String - @writer.tag("string", param) - - when NilClass - if Config::ENABLE_NIL_CREATE - @writer.ele("nil") - else - raise "Wrong type NilClass. Not allowed!" - end - - when Float - raise "Wrong value #{param}. Not allowed!" unless param.finite? - @writer.tag("double", param.to_s) - - when Struct - h = param.members.collect do |key| - value = param[key] - @writer.ele("member", - @writer.tag("name", key.to_s), - conv2value(value) - ) - end - - @writer.ele("struct", *h) - - when Hash - # TODO: can a Hash be empty? - - h = param.collect do |key, value| - @writer.ele("member", - @writer.tag("name", key.to_s), - conv2value(value) - ) - end - - @writer.ele("struct", *h) - - when Array - # TODO: can an Array be empty? - a = param.collect {|v| conv2value(v) } - - @writer.ele("array", - @writer.ele("data", *a) - ) - - when Time, Date, ::DateTime - @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S")) - - when XMLRPC::DateTime - @writer.tag("dateTime.iso8601", - format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a)) - - when XMLRPC::Base64 - @writer.tag("base64", param.encoded) - - else - if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable - # convert Ruby object into Hash - ret = {"___class___" => param.class.name} - param.instance_variables.each {|v| - name = v[1..-1] - val = param.instance_variable_get(v) - - if val.nil? - ret[name] = val if Config::ENABLE_NIL_CREATE - else - ret[name] = val - end - } - return conv2value(ret) - else - ok, pa = wrong_type(param) - if ok - return conv2value(pa) - else - raise "Wrong type!" - end - end - end - - @writer.ele("value", val) - end - - def wrong_type(value) - false - end - - - end # class Create - -end # module XMLRPC - diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/datetime.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/datetime.rb deleted file mode 100644 index d34db8758..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/datetime.rb +++ /dev/null @@ -1,124 +0,0 @@ -# frozen_string_literal: false -# -# xmlrpc/datetime.rb -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# Released under the same term of license as Ruby. -# -require "date" - -module XMLRPC # :nodoc: - -# This class is important to handle XMLRPC +dateTime.iso8601+ values, -# correctly, because normal UNIX-dates, ie: Date, only handle dates -# from year 1970 on, and ruby's native Time class handles dates without the -# time component. -# -# XMLRPC::DateTime is able to store a XMLRPC +dateTime.iso8601+ value correctly. -class DateTime - - # Return the value of the specified date/time component. - attr_reader :year, :month, :day, :hour, :min, :sec - - # Set +value+ as the new date/time component. - # - # Raises ArgumentError if the given +value+ is out of range, or in the case - # of XMLRPC::DateTime#year= if +value+ is not of type Integer. - def year=(value) - raise ArgumentError, "date/time out of range" unless value.is_a? Integer - @year = value - end - - # Set +value+ as the new date/time component. - # - # Raises an ArgumentError if the given +value+ isn't between 1 and 12. - def month=(value) - raise ArgumentError, "date/time out of range" unless (1..12).include? value - @month = value - end - - # Set +value+ as the new date/time component. - # - # Raises an ArgumentError if the given +value+ isn't between 1 and 31. - def day=(value) - raise ArgumentError, "date/time out of range" unless (1..31).include? value - @day = value - end - - # Set +value+ as the new date/time component. - # - # Raises an ArgumentError if the given +value+ isn't between 0 and 24. - def hour=(value) - raise ArgumentError, "date/time out of range" unless (0..24).include? value - @hour = value - end - - # Set +value+ as the new date/time component. - # - # Raises an ArgumentError if the given +value+ isn't between 0 and 59. - def min=(value) - raise ArgumentError, "date/time out of range" unless (0..59).include? value - @min = value - end - - # Set +value+ as the new date/time component. - # - # Raises an ArgumentError if the given +value+ isn't between 0 and 59. - def sec=(value) - raise ArgumentError, "date/time out of range" unless (0..59).include? value - @sec = value - end - - # Alias for XMLRPC::DateTime#month. - alias mon month - # Alias for XMLRPC::DateTime#month=. - alias mon= month= - - - # Creates a new XMLRPC::DateTime instance with the - # parameters +year+, +month+, +day+ as date and - # +hour+, +min+, +sec+ as time. - # - # Raises an ArgumentError if a parameter is out of range, - # or if +year+ is not of the Integer type. - def initialize(year, month, day, hour, min, sec) - self.year, self.month, self.day = year, month, day - self.hour, self.min, self.sec = hour, min, sec - end - - # Return a Time object of the date/time which represents +self+. - # - # The timezone used is GMT. - def to_time - Time.gm(*to_a) - end - - # Return a Date object of the date which represents +self+. - # - # The Date object do _not_ contain the time component (only date). - def to_date - Date.new(*to_a[0,3]) - end - - # Returns all date/time components in an array. - # - # Returns +[year, month, day, hour, min, sec]+. - def to_a - [@year, @month, @day, @hour, @min, @sec] - end - - # Returns whether or not all date/time components are an array. - def ==(o) - self.to_a == Array(o) rescue false - end - -end - - -end # module XMLRPC - - -=begin -= History - $Id$ -=end diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/marshal.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/marshal.rb deleted file mode 100644 index 42b7b1e12..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/marshal.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: false -# -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# $Id$ -# - -require "xmlrpc/parser" -require "xmlrpc/create" -require "xmlrpc/config" -require "xmlrpc/utils" - -module XMLRPC # :nodoc: - - # Marshalling of XMLRPC::Create#methodCall and XMLRPC::Create#methodResponse - class Marshal - include ParserWriterChooseMixin - - class << self - - def dump_call( methodName, *params ) - new.dump_call( methodName, *params ) - end - - def dump_response( param ) - new.dump_response( param ) - end - - def load_call( stringOrReadable ) - new.load_call( stringOrReadable ) - end - - def load_response( stringOrReadable ) - new.load_response( stringOrReadable ) - end - - alias dump dump_response - alias load load_response - - end # class self - - def initialize( parser = nil, writer = nil ) - set_parser( parser ) - set_writer( writer ) - end - - def dump_call( methodName, *params ) - create.methodCall( methodName, *params ) - end - - def dump_response( param ) - create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param ) - end - - # Returns [ methodname, params ] - def load_call( stringOrReadable ) - parser.parseMethodCall( stringOrReadable ) - end - - # Returns +paramOrFault+ - def load_response( stringOrReadable ) - parser.parseMethodResponse( stringOrReadable )[1] - end - - end # class Marshal - -end diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/parser.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/parser.rb deleted file mode 100644 index a58da3372..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/parser.rb +++ /dev/null @@ -1,642 +0,0 @@ -# frozen_string_literal: false -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# $Id$ -# - - -require "date" -require "xmlrpc/base64" -require "xmlrpc/datetime" - - -module XMLRPC # :nodoc: - - # Raised when the remote procedure returns a fault-structure, which has two - # accessor-methods +faultCode+ an Integer, and +faultString+ a String. - class FaultException < StandardError - attr_reader :faultCode, :faultString - - # Creates a new XMLRPC::FaultException instance. - # - # +faultString+ is passed to StandardError as the +msg+ of the Exception. - def initialize(faultCode, faultString) - @faultCode = faultCode - @faultString = faultString - super(@faultString) - end - - # The +faultCode+ and +faultString+ of the exception in a Hash. - def to_h - {"faultCode" => @faultCode, "faultString" => @faultString} - end - end - - # Helper class used to convert types. - module Convert - - # Converts a String to an Integer - # - # See also String.to_i - def self.int(str) - str.to_i - end - - # Converts a String to +true+ or +false+ - # - # Raises an exception if +str+ is not +0+ or +1+ - def self.boolean(str) - case str - when "0" then false - when "1" then true - else - raise "RPC-value of type boolean is wrong" - end - end - - # Converts a String to a Float - # - # See also String.to_f - def self.double(str) - str.to_f - end - - # Converts a the given +str+ to a +dateTime.iso8601+ formatted date. - # - # Raises an exception if the String isn't in +dateTime.iso8601+ format. - # - # See also, XMLRPC::DateTime - def self.dateTime(str) - case str - when /^(-?\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(?:Z|([+-])(\d\d):?(\d\d))?$/ - a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} - if $7 - ofs = $8.to_i*3600 + $9.to_i*60 - ofs = -ofs if $7=='+' - utc = Time.utc(*a) + ofs - a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] - end - XMLRPC::DateTime.new(*a) - when /^(-?\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(Z|([+-]\d\d):(\d\d))?$/ - a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} - if a[0] < 70 - a[0] += 2000 - else - a[0] += 1900 - end - if $7 - ofs = $8.to_i*3600 + $9.to_i*60 - ofs = -ofs if $7=='+' - utc = Time.utc(*a) + ofs - a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] - end - XMLRPC::DateTime.new(*a) - else - raise "wrong dateTime.iso8601 format " + str - end - end - - # Decodes the given +str+ using XMLRPC::Base64.decode - def self.base64(str) - XMLRPC::Base64.decode(str) - end - - # Converts the given +hash+ to a marshalled object. - # - # Returns the given +hash+ if an exception occurs. - def self.struct(hash) - # convert to marshalled object - klass = hash["___class___"] - if klass.nil? or Config::ENABLE_MARSHALLING == false - hash - else - begin - mod = Module - klass.split("::").each {|const| mod = mod.const_get(const.strip)} - - obj = mod.allocate - - hash.delete "___class___" - hash.each {|key, value| - obj.instance_variable_set("@#{ key }", value) if key =~ /^([a-zA-Z_]\w*)$/ - } - obj - rescue - hash - end - end - end - - # Converts the given +hash+ to an XMLRPC::FaultException object by passing - # the +faultCode+ and +faultString+ attributes of the Hash to - # XMLRPC::FaultException.new - # - # Raises an Exception if the given +hash+ doesn't meet the requirements. - # Those requirements being: - # * 2 keys - # * 'faultCode' key is an Integer - # * 'faultString' key is a String - def self.fault(hash) - if hash.kind_of? Hash and hash.size == 2 and - hash.has_key? "faultCode" and hash.has_key? "faultString" and - hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String - - XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) - else - raise "wrong fault-structure: #{hash.inspect}" - end - end - - end # module Convert - - # Parser for XML-RPC call and response - module XMLParser - - class AbstractTreeParser - - def parseMethodResponse(str) - methodResponse_document(createCleanedTree(str)) - end - - def parseMethodCall(str) - methodCall_document(createCleanedTree(str)) - end - - private - - # Removes all whitespaces but in the tags i4, i8, int, boolean.... - # and all comments - def removeWhitespacesAndComments(node) - remove = [] - childs = node.childNodes.to_a - childs.each do |nd| - case _nodeType(nd) - when :TEXT - # TODO: add nil? - unless %w(i4 i8 int boolean string double dateTime.iso8601 base64).include? node.nodeName - - if node.nodeName == "value" - if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil? - remove << nd if nd.nodeValue.strip == "" - end - else - remove << nd if nd.nodeValue.strip == "" - end - end - when :COMMENT - remove << nd - else - removeWhitespacesAndComments(nd) - end - end - - remove.each { |i| node.removeChild(i) } - end - - - def nodeMustBe(node, name) - cmp = case name - when Array - name.include?(node.nodeName) - when String - name == node.nodeName - else - raise "error" - end - - if not cmp then - raise "wrong xml-rpc (name)" - end - - node - end - - # Returns, when successfully the only child-node - def hasOnlyOneChild(node, name=nil) - if node.childNodes.to_a.size != 1 - raise "wrong xml-rpc (size)" - end - if name != nil then - nodeMustBe(node.firstChild, name) - end - end - - - def assert(b) - if not b then - raise "assert-fail" - end - end - - # The node `node` has empty string or string - def text_zero_one(node) - nodes = node.childNodes.to_a.size - - if nodes == 1 - text(node.firstChild) - elsif nodes == 0 - "" - else - raise "wrong xml-rpc (size)" - end - end - - - def integer(node) - #TODO: check string for float because to_i returnsa - # 0 when wrong string - nodeMustBe(node, %w(i4 i8 int)) - hasOnlyOneChild(node) - - Convert.int(text(node.firstChild)) - end - - def boolean(node) - nodeMustBe(node, "boolean") - hasOnlyOneChild(node) - - Convert.boolean(text(node.firstChild)) - end - - def v_nil(node) - nodeMustBe(node, "nil") - assert( node.childNodes.to_a.size == 0 ) - nil - end - - def string(node) - nodeMustBe(node, "string") - text_zero_one(node) - end - - def double(node) - #TODO: check string for float because to_f returnsa - # 0.0 when wrong string - nodeMustBe(node, "double") - hasOnlyOneChild(node) - - Convert.double(text(node.firstChild)) - end - - def dateTime(node) - nodeMustBe(node, "dateTime.iso8601") - hasOnlyOneChild(node) - - Convert.dateTime( text(node.firstChild) ) - end - - def base64(node) - nodeMustBe(node, "base64") - #hasOnlyOneChild(node) - - Convert.base64(text_zero_one(node)) - end - - def member(node) - nodeMustBe(node, "member") - assert( node.childNodes.to_a.size == 2 ) - - [ name(node[0]), value(node[1]) ] - end - - def name(node) - nodeMustBe(node, "name") - #hasOnlyOneChild(node) - text_zero_one(node) - end - - def array(node) - nodeMustBe(node, "array") - hasOnlyOneChild(node, "data") - data(node.firstChild) - end - - def data(node) - nodeMustBe(node, "data") - - node.childNodes.to_a.collect do |val| - value(val) - end - end - - def param(node) - nodeMustBe(node, "param") - hasOnlyOneChild(node, "value") - value(node.firstChild) - end - - def methodResponse(node) - nodeMustBe(node, "methodResponse") - hasOnlyOneChild(node, %w(params fault)) - child = node.firstChild - - case child.nodeName - when "params" - [ true, params(child,false) ] - when "fault" - [ false, fault(child) ] - else - raise "unexpected error" - end - - end - - def methodName(node) - nodeMustBe(node, "methodName") - hasOnlyOneChild(node) - text(node.firstChild) - end - - def params(node, call=true) - nodeMustBe(node, "params") - - if call - node.childNodes.to_a.collect do |n| - param(n) - end - else # response (only one param) - hasOnlyOneChild(node) - param(node.firstChild) - end - end - - def fault(node) - nodeMustBe(node, "fault") - hasOnlyOneChild(node, "value") - f = value(node.firstChild) - Convert.fault(f) - end - - - - # _nodeType is defined in the subclass - def text(node) - assert( _nodeType(node) == :TEXT ) - assert( node.hasChildNodes == false ) - assert( node.nodeValue != nil ) - - node.nodeValue.to_s - end - - def struct(node) - nodeMustBe(node, "struct") - - hash = {} - node.childNodes.to_a.each do |me| - n, v = member(me) - hash[n] = v - end - - Convert.struct(hash) - end - - - def value(node) - nodeMustBe(node, "value") - nodes = node.childNodes.to_a.size - if nodes == 0 - return "" - elsif nodes > 1 - raise "wrong xml-rpc (size)" - end - - child = node.firstChild - - case _nodeType(child) - when :TEXT - text_zero_one(node) - when :ELEMENT - case child.nodeName - when "i4", "i8", "int" then integer(child) - when "boolean" then boolean(child) - when "string" then string(child) - when "double" then double(child) - when "dateTime.iso8601" then dateTime(child) - when "base64" then base64(child) - when "struct" then struct(child) - when "array" then array(child) - when "nil" - if Config::ENABLE_NIL_PARSER - v_nil(child) - else - raise "wrong/unknown XML-RPC type 'nil'" - end - else - raise "wrong/unknown XML-RPC type" - end - else - raise "wrong type of node" - end - - end - - def methodCall(node) - nodeMustBe(node, "methodCall") - assert( (1..2).include?( node.childNodes.to_a.size ) ) - name = methodName(node[0]) - - if node.childNodes.to_a.size == 2 then - pa = params(node[1]) - else # no parameters given - pa = [] - end - [name, pa] - end - - end # module TreeParserMixin - - class AbstractStreamParser - def parseMethodResponse(str) - parser = @parser_class.new - parser.parse(str) - raise "No valid method response!" if parser.method_name != nil - if parser.fault != nil - # is a fault structure - [false, parser.fault] - else - # is a normal return value - raise "Missing return value!" if parser.params.size == 0 - raise "Too many return values. Only one allowed!" if parser.params.size > 1 - [true, parser.params[0]] - end - end - - def parseMethodCall(str) - parser = @parser_class.new - parser.parse(str) - raise "No valid method call - missing method name!" if parser.method_name.nil? - [parser.method_name, parser.params] - end - end - - module StreamParserMixin - attr_reader :params - attr_reader :method_name - attr_reader :fault - - def initialize(*a) - super(*a) - @params = [] - @values = [] - @val_stack = [] - - @names = [] - @name = [] - - @structs = [] - @struct = {} - - @method_name = nil - @fault = nil - - @data = nil - end - - def startElement(name, attrs=[]) - @data = nil - case name - when "value" - @value = nil - when "nil" - raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER - @value = :nil - when "array" - @val_stack << @values - @values = [] - when "struct" - @names << @name - @name = [] - - @structs << @struct - @struct = {} - end - end - - def endElement(name) - @data ||= "" - case name - when "string" - @value = @data - when "i4", "i8", "int" - @value = Convert.int(@data) - when "boolean" - @value = Convert.boolean(@data) - when "double" - @value = Convert.double(@data) - when "dateTime.iso8601" - @value = Convert.dateTime(@data) - when "base64" - @value = Convert.base64(@data) - when "value" - @value = @data if @value.nil? - @values << (@value == :nil ? nil : @value) - when "array" - @value = @values - @values = @val_stack.pop - when "struct" - @value = Convert.struct(@struct) - - @name = @names.pop - @struct = @structs.pop - when "name" - @name[0] = @data - when "member" - @struct[@name[0]] = @values.pop - - when "param" - @params << @values[0] - @values = [] - - when "fault" - @fault = Convert.fault(@values[0]) - - when "methodName" - @method_name = @data - end - - @data = nil - end - - def character(data) - if @data - @data << data - else - @data = data - end - end - - end # module StreamParserMixin - - class REXMLStreamParser < AbstractStreamParser - def initialize - require "rexml/document" - @parser_class = StreamListener - end - - class StreamListener - include StreamParserMixin - - alias :tag_start :startElement - alias :tag_end :endElement - alias :text :character - alias :cdata :character - - def method_missing(*a) - # ignore - end - - def parse(str) - REXML::Document.parse_stream(str, self) - end - end - - end - - class LibXMLStreamParser < AbstractStreamParser - def initialize - require 'libxml' - @parser_class = LibXMLStreamListener - end - - class LibXMLStreamListener - include StreamParserMixin - - def on_start_element_ns(name, attributes, prefix, uri, namespaces) - startElement(name) - end - - def on_end_element_ns(name, prefix, uri) - endElement(name) - end - - alias :on_characters :character - alias :on_cdata_block :character - - def method_missing(*a) - end - - def parse(str) - parser = LibXML::XML::SaxParser.string(str) - parser.callbacks = self - parser.parse() - end - end - end - - Classes = [REXMLStreamParser, LibXMLStreamParser] - - # yields an instance of each installed parser - def self.each_installed_parser - XMLRPC::XMLParser::Classes.each do |klass| - begin - yield klass.new - rescue LoadError - end - end - end - - end # module XMLParser - - -end # module XMLRPC - diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/server.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/server.rb deleted file mode 100644 index cd0fdbad3..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/server.rb +++ /dev/null @@ -1,708 +0,0 @@ -# frozen_string_literal: false -# xmlrpc/server.rb -# Copyright (C) 2001, 2002, 2003, 2005 by Michael Neumann (mneumann@ntecs.de) -# -# Released under the same term of license as Ruby. - -require "xmlrpc/parser" -require "xmlrpc/create" -require "xmlrpc/config" -require "xmlrpc/utils" # ParserWriterChooseMixin - - - -module XMLRPC # :nodoc: - - -# This is the base class for all XML-RPC server-types (CGI, standalone). -# You can add handler and set a default handler. -# Do not use this server, as this is/should be an abstract class. -# -# === How the method to call is found -# The arity (number of accepted arguments) of a handler (method or Proc -# object) is compared to the given arguments submitted by the client for a -# RPC, or Remote Procedure Call. -# -# A handler is only called if it accepts the number of arguments, otherwise -# the search for another handler will go on. When at the end no handler was -# found, the default_handler, XMLRPC::BasicServer#set_default_handler will be -# called. -# -# With this technique it is possible to do overloading by number of parameters, but -# only for Proc handler, because you cannot define two methods of the same name in -# the same class. -class BasicServer - - include ParserWriterChooseMixin - include ParseContentType - - ERR_METHOD_MISSING = 1 - ERR_UNCAUGHT_EXCEPTION = 2 - ERR_MC_WRONG_PARAM = 3 - ERR_MC_MISSING_PARAMS = 4 - ERR_MC_MISSING_METHNAME = 5 - ERR_MC_RECURSIVE_CALL = 6 - ERR_MC_WRONG_PARAM_PARAMS = 7 - ERR_MC_EXPECTED_STRUCT = 8 - - - # Creates a new XMLRPC::BasicServer instance, which should not be - # done, because XMLRPC::BasicServer is an abstract class. This - # method should be called from a subclass indirectly by a +super+ call - # in the initialize method. - # - # The parameter +class_delim+ is used by add_handler, see - # XMLRPC::BasicServer#add_handler, when an object is added as a handler, to - # delimit the object-prefix and the method-name. - def initialize(class_delim=".") - @handler = [] - @default_handler = nil - @service_hook = nil - - @class_delim = class_delim - @create = nil - @parser = nil - - add_multicall if Config::ENABLE_MULTICALL - add_introspection if Config::ENABLE_INTROSPECTION - end - - # Adds +aBlock+ to the list of handlers, with +name+ as the name of - # the method. - # - # Parameters +signature+ and +help+ are used by the Introspection method if - # specified, where +signature+ is either an Array containing strings each - # representing a type of it's signature (the first is the return value) or - # an Array of Arrays if the method has multiple signatures. - # - # Value type-names are "int, boolean, double, string, dateTime.iso8601, - # base64, array, struct". - # - # Parameter +help+ is a String with information about how to call this method etc. - # - # When a method fails, it can tell the client by throwing an - # XMLRPC::FaultException like in this example: - # - # s.add_handler("michael.div") do |a,b| - # if b == 0 - # raise XMLRPC::FaultException.new(1, "division by zero") - # else - # a / b - # end - # end - # - # In the case of b==0 the client gets an object back of type - # XMLRPC::FaultException that has a +faultCode+ and +faultString+ field. - # - # This is the second form of (()). - # To add an object write: - # - # server.add_handler("michael", MyHandlerClass.new) - # - # All public methods of MyHandlerClass are accessible to - # the XML-RPC clients by michael."name of method". This is - # where the +class_delim+ in XMLRPC::BasicServer.new plays it's role, a - # XML-RPC method-name is defined by +prefix+ + +class_delim+ + "name - # of method". - # - # The third form of +add_handler is to use XMLRPC::Service::Interface to - # generate an object, which represents an interface (with signature and - # help text) for a handler class. - # - # The +interface+ parameter must be an instance of XMLRPC::Service::Interface. - # Adds all methods of +obj+ which are defined in the +interface+ to the server. - # - # This is the recommended way of adding services to a server! - def add_handler(prefix, obj_or_signature=nil, help=nil, &block) - if block_given? - # proc-handler - @handler << [prefix, block, obj_or_signature, help] - else - if prefix.kind_of? String - # class-handler - raise ArgumentError, "Expected non-nil value" if obj_or_signature.nil? - @handler << [prefix + @class_delim, obj_or_signature] - elsif prefix.kind_of? XMLRPC::Service::BasicInterface - # class-handler with interface - # add all methods - @handler += prefix.get_methods(obj_or_signature, @class_delim) - else - raise ArgumentError, "Wrong type for parameter 'prefix'" - end - end - self - end - - # Returns the service-hook, which is called on each service request (RPC) - # unless it's +nil+. - def get_service_hook - @service_hook - end - - # A service-hook is called for each service request (RPC). - # - # You can use a service-hook for example to wrap existing methods and catch - # exceptions of them or convert values to values recognized by XMLRPC. - # - # You can disable it by passing +nil+ as the +handler+ parameter. - # - # The service-hook is called with a Proc object along with any parameters. - # - # An example: - # - # server.set_service_hook {|obj, *args| - # begin - # ret = obj.call(*args) # call the original service-method - # # could convert the return value - # rescue - # # rescue exceptions - # end - # } - # - def set_service_hook(&handler) - @service_hook = handler - self - end - - # Returns the default-handler, which is called when no handler for - # a method-name is found. - # - # It is either a Proc object or +nil+. - def get_default_handler - @default_handler - end - - # Sets +handler+ as the default-handler, which is called when - # no handler for a method-name is found. - # - # +handler+ is a code-block. - # - # The default-handler is called with the (XML-RPC) method-name as first - # argument, and the other arguments are the parameters given by the - # client-call. - # - # If no block is specified the default of XMLRPC::BasicServer is - # used, which raises a XMLRPC::FaultException saying "method missing". - def set_default_handler(&handler) - @default_handler = handler - self - end - - # Adds the multi-call handler "system.multicall". - def add_multicall - add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs| - unless arrStructs.is_a? Array - raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array") - end - - arrStructs.collect {|call| - if call.is_a? Hash - methodName = call["methodName"] - params = call["params"] - - if params.nil? - multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params") - elsif methodName.nil? - multicall_fault(ERR_MC_MISSING_METHNAME, "Missing methodName") - else - if methodName == "system.multicall" - multicall_fault(ERR_MC_RECURSIVE_CALL, "Recursive system.multicall forbidden") - else - unless params.is_a? Array - multicall_fault(ERR_MC_WRONG_PARAM_PARAMS, "Parameter params have to be an Array") - else - ok, val = call_method(methodName, *params) - if ok - # correct return value - [val] - else - # exception - multicall_fault(val.faultCode, val.faultString) - end - end - end - end - - else - multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct") - end - } - end # end add_handler - self - end - - # Adds the introspection handlers "system.listMethods", - # "system.methodSignature" and - # "system.methodHelp", where only the first one works. - def add_introspection - add_handler("system.listMethods",%w(array), "List methods available on this XML-RPC server") do - methods = [] - @handler.each do |name, obj| - if obj.kind_of? Proc - methods << name - else - obj.class.public_instance_methods(false).each do |meth| - methods << "#{name}#{meth}" - end - end - end - methods - end - - add_handler("system.methodSignature", %w(array string), "Returns method signature") do |meth| - sigs = [] - @handler.each do |name, obj, sig| - if obj.kind_of? Proc and sig != nil and name == meth - if sig[0].kind_of? Array - # sig contains multiple signatures, e.g. [["array"], ["array", "string"]] - sig.each {|s| sigs << s} - else - # sig is a single signature, e.g. ["array"] - sigs << sig - end - end - end - sigs.uniq! || sigs # remove eventually duplicated signatures - end - - add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth| - help = nil - @handler.each do |name, obj, sig, hlp| - if obj.kind_of? Proc and name == meth - help = hlp - break - end - end - help || "" - end - - self - end - - - - def process(data) - method, params = parser().parseMethodCall(data) - handle(method, *params) - end - - private - - def multicall_fault(nr, str) - {"faultCode" => nr, "faultString" => str} - end - - def dispatch(methodname, *args) - for name, obj in @handler - if obj.kind_of? Proc - next unless methodname == name - else - next unless methodname =~ /^#{name}(.+)$/ - next unless obj.respond_to? $1 - obj = obj.method($1) - end - - if check_arity(obj, args.size) - if @service_hook.nil? - return obj.call(*args) - else - return @service_hook.call(obj, *args) - end - end - end - - if @default_handler.nil? - raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!") - else - @default_handler.call(methodname, *args) - end - end - - - # Returns +true+, if the arity of +obj+ matches +n_args+ - def check_arity(obj, n_args) - ary = obj.arity - - if ary >= 0 - n_args == ary - else - n_args >= (ary+1).abs - end - end - - - - def call_method(methodname, *args) - begin - [true, dispatch(methodname, *args)] - rescue XMLRPC::FaultException => e - [false, e] - rescue Exception => e - [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")] - end - end - - def handle(methodname, *args) - create().methodResponse(*call_method(methodname, *args)) - end - - -end - - -# Implements a CGI-based XML-RPC server. -# -# require "xmlrpc/server" -# -# s = XMLRPC::CGIServer.new -# -# s.add_handler("michael.add") do |a,b| -# a + b -# end -# -# s.add_handler("michael.div") do |a,b| -# if b == 0 -# raise XMLRPC::FaultException.new(1, "division by zero") -# else -# a / b -# end -# end -# -# s.set_default_handler do |name, *args| -# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + -# " or wrong number of parameters!") -# end -# -# s.serve -# -# -# Note: Make sure that you don't write to standard-output in a -# handler, or in any other part of your program, this would cause a CGI-based -# server to fail! -class CGIServer < BasicServer - @@obj = nil - - # Creates a new XMLRPC::CGIServer instance. - # - # All parameters given are by-passed to XMLRPC::BasicServer.new. - # - # You can only create one XMLRPC::CGIServer instance, because more - # than one makes no sense. - def CGIServer.new(*a) - @@obj = super(*a) if @@obj.nil? - @@obj - end - - def initialize(*a) - super(*a) - end - - # Call this after you have added all you handlers to the server. - # - # This method processes a XML-RPC method call and sends the answer - # back to the client. - def serve - catch(:exit_serve) { - length = ENV['CONTENT_LENGTH'].to_i - - http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST" - http_error(400, "Bad Request") unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml" - http_error(411, "Length Required") unless length > 0 - - # TODO: do we need a call to binmode? - $stdin.binmode if $stdin.respond_to? :binmode - data = $stdin.read(length) - - http_error(400, "Bad Request") if data.nil? or data.bytesize != length - - http_write(process(data), "Content-type" => "text/xml; charset=utf-8") - } - end - - - private - - def http_error(status, message) - err = "#{status} #{message}" - msg = <<-"MSGEND" - - - #{err} - - -

#{err}

-

Unexpected error occurred while processing XML-RPC request!

- - - MSGEND - - http_write(msg, "Status" => err, "Content-type" => "text/html") - throw :exit_serve # exit from the #serve method - end - - def http_write(body, header) - h = {} - header.each {|key, value| h[key.to_s.capitalize] = value} - h['Status'] ||= "200 OK" - h['Content-length'] ||= body.bytesize.to_s - - str = "" - h.each {|key, value| str << "#{key}: #{value}\r\n"} - str << "\r\n#{body}" - - print str - end - -end - - -# Implements a XML-RPC server, which works with Apache mod_ruby. -# -# Use it in the same way as XMLRPC::CGIServer! -class ModRubyServer < BasicServer - - # Creates a new XMLRPC::ModRubyServer instance. - # - # All parameters given are by-passed to XMLRPC::BasicServer.new. - def initialize(*a) - @ap = Apache::request - super(*a) - end - - # Call this after you have added all you handlers to the server. - # - # This method processes a XML-RPC method call and sends the answer - # back to the client. - def serve - catch(:exit_serve) { - header = {} - @ap.headers_in.each {|key, value| header[key.capitalize] = value} - - length = header['Content-length'].to_i - - http_error(405, "Method Not Allowed") unless @ap.request_method == "POST" - http_error(400, "Bad Request") unless parse_content_type(header['Content-type']).first == "text/xml" - http_error(411, "Length Required") unless length > 0 - - # TODO: do we need a call to binmode? - @ap.binmode - data = @ap.read(length) - - http_error(400, "Bad Request") if data.nil? or data.bytesize != length - - http_write(process(data), 200, "Content-type" => "text/xml; charset=utf-8") - } - end - - - private - - def http_error(status, message) - err = "#{status} #{message}" - msg = <<-"MSGEND" - - - #{err} - - -

#{err}

-

Unexpected error occurred while processing XML-RPC request!

- - - MSGEND - - http_write(msg, status, "Status" => err, "Content-type" => "text/html") - throw :exit_serve # exit from the #serve method - end - - def http_write(body, status, header) - h = {} - header.each {|key, value| h[key.to_s.capitalize] = value} - h['Status'] ||= "200 OK" - h['Content-length'] ||= body.bytesize.to_s - - h.each {|key, value| @ap.headers_out[key] = value } - @ap.content_type = h["Content-type"] - @ap.status = status.to_i - @ap.send_http_header - - @ap.print body - end - -end - - -class WEBrickServlet < BasicServer; end # forward declaration - -# Implements a standalone XML-RPC server. The method XMLRPC::Server#serve is -# left if a SIGHUP is sent to the program. -# -# require "xmlrpc/server" -# -# s = XMLRPC::Server.new(8080) -# -# s.add_handler("michael.add") do |a,b| -# a + b -# end -# -# s.add_handler("michael.div") do |a,b| -# if b == 0 -# raise XMLRPC::FaultException.new(1, "division by zero") -# else -# a / b -# end -# end -# -# s.set_default_handler do |name, *args| -# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + -# " or wrong number of parameters!") -# end -# -# s.serve -class Server < WEBrickServlet - - # Creates a new XMLRPC::Server instance, which is a XML-RPC server - # listening on the given +port+ and accepts requests for the given +host+, - # which is +localhost+ by default. - # - # The server is not started, to start it you have to call - # XMLRPC::Server#serve. - # - # The optional +audit+ and +debug+ parameters are obsolete! - # - # All additionally provided parameters in *a are by-passed to - # XMLRPC::BasicServer.new. - def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a) - super(*a) - require 'webrick' - @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections, - :Logger => WEBrick::Log.new(stdlog)) - @server.mount("/", self) - end - - # Call this after you have added all you handlers to the server. - # This method starts the server to listen for XML-RPC requests and answer them. - def serve - signals = %w[INT TERM HUP] & Signal.list.keys - signals.each { |signal| trap(signal) { @server.shutdown } } - - @server.start - end - - # Stops and shuts the server down. - def shutdown - @server.shutdown - end - -end - - -# Implements a servlet for use with WEBrick, a pure Ruby (HTTP) server -# framework. -# -# require "webrick" -# require "xmlrpc/server" -# -# s = XMLRPC::WEBrickServlet.new -# s.add_handler("michael.add") do |a,b| -# a + b -# end -# -# s.add_handler("michael.div") do |a,b| -# if b == 0 -# raise XMLRPC::FaultException.new(1, "division by zero") -# else -# a / b -# end -# end -# -# s.set_default_handler do |name, *args| -# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + -# " or wrong number of parameters!") -# end -# -# httpserver = WEBrick::HTTPServer.new(:Port => 8080) -# httpserver.mount("/RPC2", s) -# trap("HUP") { httpserver.shutdown } # use 1 instead of "HUP" on Windows -# httpserver.start -class WEBrickServlet < BasicServer - def initialize(*a) - super - require "webrick/httpstatus" - @valid_ip = nil - end - - # Deprecated from WEBrick/1.2.2, but does not break anything. - def require_path_info? - false - end - - def get_instance(config, *options) - # TODO: set config & options - self - end - - # Specifies the valid IP addresses that are allowed to connect to the server. - # - # Each IP is either a String or a Regexp. - def set_valid_ip(*ip_addr) - if ip_addr.size == 1 and ip_addr[0].nil? - @valid_ip = nil - else - @valid_ip = ip_addr - end - end - - # Return the valid IP addresses that are allowed to connect to the server. - # - # See also, XMLRPC::Server#set_valid_ip - def get_valid_ip - @valid_ip - end - - def service(request, response) - - if @valid_ip - raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip } - end - - if request.request_method != "POST" - raise WEBrick::HTTPStatus::MethodNotAllowed, - "unsupported method `#{request.request_method}'." - end - - if parse_content_type(request['Content-type']).first != "text/xml" - raise WEBrick::HTTPStatus::BadRequest - end - - length = (request['Content-length'] || 0).to_i - - raise WEBrick::HTTPStatus::LengthRequired unless length > 0 - - data = request.body - - if data.nil? or data.bytesize != length - raise WEBrick::HTTPStatus::BadRequest - end - - resp = process(data) - if resp.nil? or resp.bytesize <= 0 - raise WEBrick::HTTPStatus::InternalServerError - end - - response.status = 200 - response['Content-Length'] = resp.bytesize - response['Content-Type'] = "text/xml; charset=utf-8" - response.body = resp - end -end - - -end # module XMLRPC - - -=begin -= History - $Id$ -=end - diff --git a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/utils.rb b/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/utils.rb deleted file mode 100644 index cd2ab107d..000000000 --- a/ruby/gems/xmlrpc-0.3.0/lib/xmlrpc/utils.rb +++ /dev/null @@ -1,172 +0,0 @@ -# frozen_string_literal: false -# -# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) -# -# $Id$ -# -module XMLRPC # :nodoc: - - - # This module enables a user-class to be marshalled - # by XML-RPC for Ruby into a Hash, with one additional - # key/value pair ___class___ => ClassName - # - module Marshallable - end - - - # Defines ParserWriterChooseMixin, which makes it possible to choose a - # different XMLWriter and/or XMLParser then the default one. - # - # The Mixin is used in client.rb (class XMLRPC::Client) - # and server.rb (class XMLRPC::BasicServer) - module ParserWriterChooseMixin - - # Sets the XMLWriter to use for generating XML output. - # - # Should be an instance of a class from module XMLRPC::XMLWriter. - # - # If this method is not called, then XMLRPC::Config::DEFAULT_WRITER is used. - def set_writer(writer) - @create = Create.new(writer) - self - end - - # Sets the XMLParser to use for parsing XML documents. - # - # Should be an instance of a class from module XMLRPC::XMLParser. - # - # If this method is not called, then XMLRPC::Config::DEFAULT_PARSER is used. - def set_parser(parser) - @parser = parser - self - end - - private - - def create - # if set_writer was not already called then call it now - if @create.nil? then - set_writer(Config::DEFAULT_WRITER.new) - end - @create - end - - def parser - # if set_parser was not already called then call it now - if @parser.nil? then - set_parser(Config::DEFAULT_PARSER.new) - end - @parser - end - - end # module ParserWriterChooseMixin - - - module Service - - # Base class for XMLRPC::Service::Interface definitions, used - # by XMLRPC::BasicServer#add_handler - class BasicInterface - attr_reader :prefix, :methods - - def initialize(prefix) - @prefix = prefix - @methods = [] - end - - def add_method(sig, help=nil, meth_name=nil) - mname = nil - sig = [sig] if sig.kind_of? String - - sig = sig.collect do |s| - name, si = parse_sig(s) - raise "Wrong signatures!" if mname != nil and name != mname - mname = name - si - end - - @methods << [mname, meth_name || mname, sig, help] - end - - private - - def parse_sig(sig) - # sig is a String - if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/ - params = [$1] - name = $2.strip - $4.split(",").each {|i| params << i.strip} if $4 != nil - return name, params - else - raise "Syntax error in signature" - end - end - - end # class BasicInterface - - # - # Class which wraps a XMLRPC::Service::Interface definition, used - # by XMLRPC::BasicServer#add_handler - # - class Interface < BasicInterface - def initialize(prefix, &p) - raise "No interface specified" if p.nil? - super(prefix) - instance_eval(&p) - end - - def get_methods(obj, delim=".") - prefix = @prefix + delim - @methods.collect { |name, meth, sig, help| - [prefix + name.to_s, obj.method(meth).to_proc, sig, help] - } - end - - private - - def meth(*a) - add_method(*a) - end - - end # class Interface - - class PublicInstanceMethodsInterface < BasicInterface - def initialize(prefix) - super(prefix) - end - - def get_methods(obj, delim=".") - prefix = @prefix + delim - obj.class.public_instance_methods(false).collect { |name| - [prefix + name.to_s, obj.method(name).to_proc, nil, nil] - } - end - end - - - end # module Service - - - # - # Short-form to create a XMLRPC::Service::Interface - # - def self.interface(prefix, &p) - Service::Interface.new(prefix, &p) - end - - # Short-cut for creating a XMLRPC::Service::PublicInstanceMethodsInterface - def self.iPIMethods(prefix) - Service::PublicInstanceMethodsInterface.new(prefix) - end - - - module ParseContentType - def parse_content_type(str) - a, *b = str.split(";") - return a.strip.downcase, *b - end - end - -end # module XMLRPC - diff --git a/ruby/gems/xmlrpc-0.3.0/xmlrpc.gemspec b/ruby/gems/xmlrpc-0.3.0/xmlrpc.gemspec deleted file mode 100644 index 21bb3d304..000000000 --- a/ruby/gems/xmlrpc-0.3.0/xmlrpc.gemspec +++ /dev/null @@ -1,35 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: xmlrpc 0.3.0 ruby lib - -Gem::Specification.new do |s| - s.name = "xmlrpc".freeze - s.version = "0.3.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib".freeze] - s.authors = ["SHIBATA Hiroshi".freeze] - s.bindir = "exe".freeze - s.date = "2017-02-16" - s.description = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze - s.email = ["hsbt@ruby-lang.org".freeze] - s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/xmlrpc.rb".freeze, "lib/xmlrpc/base64.rb".freeze, "lib/xmlrpc/client.rb".freeze, "lib/xmlrpc/config.rb".freeze, "lib/xmlrpc/create.rb".freeze, "lib/xmlrpc/datetime.rb".freeze, "lib/xmlrpc/marshal.rb".freeze, "lib/xmlrpc/parser.rb".freeze, "lib/xmlrpc/server.rb".freeze, "lib/xmlrpc/utils.rb".freeze, "xmlrpc.gemspec".freeze] - s.homepage = "https://github.com/ruby/xmlrpc".freeze - s.licenses = ["Ruby".freeze] - s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze) - s.rubygems_version = "3.1.2".freeze - s.summary = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - s.add_development_dependency(%q.freeze, [">= 0"]) - else - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - s.add_dependency(%q.freeze, [">= 0"]) - end -end diff --git a/ruby/golf_prelude.c b/ruby/golf_prelude.c deleted file mode 100644 index 37cb9b3c8..000000000 --- a/ruby/golf_prelude.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -*-c-*- - THIS FILE WAS AUTOGENERATED BY template/prelude.c.tmpl. DO NOT EDIT. - - sources: golf_prelude -*/ -#include "ruby/ruby.h" -#include "internal.h" -#include "vm_core.h" -#include "iseq.h" - - -static const char prelude_name0[] = ""; -static const struct { - char L0[462]; /* 1..18 */ - char L18[485]; /* 19..34 */ - char L34[505]; /* 35..59 */ - char L59[487]; /* 60..96 */ - char L96[493]; /* 97..116 */ - char L116[222]; /* 117..131 */ -} prelude_code0 = { -#line 1 "golf_prelude.rb" -"class Object\n" -" @@golf_hash = {}\n" -"\n" -" verbose, $VERBOSE = $VERBOSE, nil\n" -" def method_missing m, *a, &b\n" -" t = @@golf_hash[ [m, self.class] ] ||= matching_methods(m)[0]\n" -" if t && b\n" -" __send__(t, *a) {|*args|\n" -" b.binding.eval(\"proc{|golf_matchdata| $~ = golf_matchdata }\").call($~) if $~\n" -" b.call(*args)\n" -" }\n" -" else\n" -" t ? __send__(t, *a, &b) : super\n" -" end\n" -" end\n" -" $VERBOSE = verbose\n" -"\n" -" def matching_methods(s = '', m = callable_methods)\n" -, -#line 19 "golf_prelude.rb" -" r = /^#{s.to_s.gsub(/./){\"(.*?)\" + Regexp.escape($&)}}/\n" -" m.grep(r).sort_by do |i|\n" -" i.to_s.match(r).captures.map(&:size) << i\n" -" end\n" -" end\n" -"\n" -" def self.const_missing c\n" -" t = @@golf_hash[ [c,self.class] ] ||= matching_methods(c, constants)[0]\n" -" t and return const_get(t)\n" -" raise NameError, \"uninitialized constant #{c}\", caller(1)\n" -" end\n" -"\n" -" def shortest_abbreviation(s = '', m = callable_methods)\n" -" s = s.to_s\n" -" our_case = (?A..?Z) === s[0]\n" -" if m.index(s.to_sym)\n" -, -#line 35 "golf_prelude.rb" -" 1.upto(s.size){|z| s.scan(/./).combination(z).map{|trial|\n" -" next unless ((?A..?Z) === trial[0]) == our_case\n" -" trial *= ''\n" -" return trial if matching_methods(trial, m)[0].to_s == s\n" -" }}\n" -" else\n" -" nil\n" -" end\n" -" end\n" -"\n" -" def callable_methods\n" -" self.class == Object ? methods + private_methods : methods\n" -" end\n" -"\n" -" private\n" -"\n" -" def h(a = 'H', b = 'w', c = '!')\n" -" puts \"#{a}ello, #{b}orld#{c}\"\n" -" end\n" -"\n" -" def f(m = 100)\n" -" 1.upto(m){|n|puts'FizzBuzz\n" -"'[i=n**4%-15,i+13]||n}\n" -" end\n" -"\n" -, -#line 60 "golf_prelude.rb" -" alias say puts\n" -"\n" -" def do_while\n" -" 0 while yield\n" -" end\n" -"\n" -" def do_until\n" -" 0 until yield\n" -" end\n" -"end\n" -"\n" -"class Array\n" -" alias old_to_s to_s\n" -" alias to_s join\n" -"end\n" -"\n" -"class FalseClass\n" -" alias old_to_s to_s\n" -" def to_s\n" -" \"\"\n" -" end\n" -"end\n" -"\n" -"class Integer\n" -" alias each times\n" -" include Enumerable\n" -"end\n" -"\n" -"class String\n" -" alias / split\n" -"\n" -" def to_a\n" -" split('')\n" -" end\n" -"\n" -" (Array.instance_methods - instance_methods - %i[to_ary transpose flatten flatten! compact compact! assoc rassoc]).each{|meth|\n" -" eval \"\n" -, -#line 97 "golf_prelude.rb" -" def #{meth}(*args, &block)\n" -" a = to_a\n" -" result = a.#{meth}(*args, &block)\n" -" replace(a.join)\n" -" if result.class == Array\n" -" Integer === result[0] ? result.pack('c*') : result.join\n" -" elsif result.class == Enumerator\n" -" result.map(&:join).to_enum\n" -" else\n" -" result\n" -" end\n" -" end\"\n" -" }\n" -"end\n" -"\n" -"class Enumerator\n" -" alias old_to_s to_s\n" -" (Array.instance_methods - instance_methods - [:replace] + [:to_s]).each{|meth|\n" -" eval \"\n" -" def #{meth}(*args, &block)\n" -, -#line 117 "golf_prelude.rb" -" to_a.#{meth}(*args, &block)\n" -" end\"\n" -" }\n" -" alias old_inspect inspect\n" -" alias inspect old_to_s\n" -"end\n" -"\n" -"class Symbol\n" -" def call(*args, &block)\n" -" proc do |recv|\n" -" recv.__send__(self, *args, &block)\n" -" end\n" -" end\n" -"end\n" -#line 163 "golf_prelude.c" -}; - -#define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1) -#define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n)) - -static rb_ast_t * -prelude_ast(VALUE name, VALUE code, int line) -{ - rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line); - if (!ast->body.root) { - rb_ast_dispose(ast); - rb_exc_raise(rb_errinfo()); - } - return ast; -} - -COMPILER_WARNING_PUSH -#if GCC_VERSION_SINCE(4, 2, 0) -COMPILER_WARNING_ERROR(-Wmissing-field-initializers) -#endif -static void -prelude_eval(VALUE code, VALUE name, int line) -{ - static const rb_compile_option_t optimization = { - TRUE, /* int inline_const_cache; */ - TRUE, /* int peephole_optimization; */ - FALSE,/* int tailcall_optimization; */ - TRUE, /* int specialized_instruction; */ - TRUE, /* int operands_unification; */ - TRUE, /* int instructions_unification; */ - TRUE, /* int stack_caching; */ - TRUE, /* int frozen_string_literal; */ - FALSE, /* int debug_frozen_string_literal; */ - FALSE, /* unsigned int coverage_enabled; */ - 0, /* int debug_level; */ - }; - - rb_ast_t *ast = prelude_ast(name, code, line); - rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line), - NULL, ISEQ_TYPE_TOP, &optimization)); - rb_ast_dispose(ast); -} -COMPILER_WARNING_POP - -void -Init_golf(void) -{ - prelude_eval(PRELUDE_CODE(0), PRELUDE_NAME(0), 1); - -#if 0 - printf("%.*s", (int)sizeof(prelude_code0), prelude_code0.L0); -#endif -} diff --git a/ruby/goruby.c b/ruby/goruby.c index ddb62562d..c90fc97b0 100644 --- a/ruby/goruby.c +++ b/ruby/goruby.c @@ -1,4 +1,6 @@ -void Init_golf(void); +static void Init_golf(void); +static void *goruby_options(int argc, char **argv); +static int goruby_run_node(void *arg); #define ruby_options goruby_options #define ruby_run_node goruby_run_node #include "main.c" @@ -17,6 +19,8 @@ RUBY_EXTERN void *ruby_options(int argc, char **argv); RUBY_EXTERN int ruby_run_node(void*); RUBY_EXTERN void ruby_init_ext(const char *name, void (*init)(void)); +#include "golf_prelude.c" + static VALUE init_golf(VALUE arg) { @@ -49,10 +53,8 @@ goruby_options(int argc, char **argv) close(infd); return ret; } - else { - no_irb: - return ruby_options(argc, argv); - } + no_irb: + return ruby_options(argc, argv); } int diff --git a/ruby/hash.c b/ruby/hash.c index b546f6246..85e84e087 100644 --- a/ruby/hash.c +++ b/ruby/hash.c @@ -11,17 +11,10 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/st.h" -#include "ruby/util.h" -#include "internal.h" +#include "ruby/internal/config.h" + #include -#include "probes.h" -#include "id.h" -#include "symbol.h" -#include "debug_counter.h" -#include "transient_heap.h" -#include "ruby_assert.h" + #ifdef __APPLE__ # ifdef HAVE_CRT_EXTERNS_H # include @@ -30,6 +23,30 @@ # endif #endif +#include "debug_counter.h" +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/bignum.h" +#include "internal/class.h" +#include "internal/cont.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/symbol.h" +#include "internal/time.h" +#include "internal/vm.h" +#include "probes.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "ruby_assert.h" +#include "symbol.h" +#include "transient_heap.h" +#include "ruby/thread_native.h" +#include "ruby/ractor.h" +#include "vm_sync.h" + #ifndef HASH_DEBUG #define HASH_DEBUG 0 #endif @@ -38,11 +55,6 @@ #include "gc.h" #endif -#define HAS_EXTRA_STATES(hash, klass) ( \ - ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \ - FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \ - !NIL_P(RHASH_IFNONE(hash))) - #define SET_DEFAULT(hash, ifnone) ( \ FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \ RHASH_SET_IFNONE(hash, ifnone)) @@ -56,19 +68,7 @@ copy_default(struct RHash *hash, const struct RHash *hash2) { hash->basic.flags &= ~RHASH_PROC_DEFAULT; hash->basic.flags |= hash2->basic.flags & RHASH_PROC_DEFAULT; - RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2)); -} - -static VALUE -has_extra_methods(VALUE klass) -{ - const VALUE base = rb_cHash; - VALUE c = klass; - while (c != base) { - if (rb_class_has_methods(c)) return klass; - c = RCLASS_SUPER(c); - } - return 0; + RHASH_SET_IFNONE(hash, RHASH_IFNONE((VALUE)hash2)); } static VALUE rb_hash_s_try_convert(VALUE, VALUE); @@ -92,7 +92,7 @@ rb_hash_freeze(VALUE hash) VALUE rb_cHash; static VALUE envtbl; -static ID id_hash, id_yield, id_default, id_flatten_bang; +static ID id_hash, id_default, id_flatten_bang; static ID id_hash_iter_lev; VALUE @@ -125,27 +125,6 @@ hash_recursive(VALUE obj, VALUE arg, int recurse) return rb_funcallv(obj, id_hash, 0, 0); } -VALUE -rb_hash(VALUE obj) -{ - VALUE hval = rb_exec_recursive_outer(hash_recursive, obj, 0); - - while (!FIXNUM_P(hval)) { - if (RB_TYPE_P(hval, T_BIGNUM)) { - int sign; - unsigned long ul; - sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0, - INTEGER_PACK_NATIVE_BYTE_ORDER); - ul &= (1UL << (sizeof(long)*CHAR_BIT-1)) - 1; - if (sign < 0) - return LONG2FIX(-(long)ul); - return LONG2FIX((long)ul); - } - hval = rb_to_int(hval); - } - return hval; -} - static long rb_objid_hash(st_index_t index); static st_index_t @@ -174,53 +153,68 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE)) VALUE hval; st_index_t hnum; - if (SPECIAL_CONST_P(a)) { + switch (TYPE(a)) { + case T_SYMBOL: if (STATIC_SYM_P(a)) { hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT); hnum = rb_hash_start(hnum); - goto out; } - else if (FLONUM_P(a)) { - /* prevent pathological behavior: [Bug #10761] */ - goto flt; - } + else { + hnum = RSYMBOL(a)->hashval; + } + break; + case T_FIXNUM: + case T_TRUE: + case T_FALSE: + case T_NIL: hnum = rb_objid_hash((st_index_t)a); - } - else if (BUILTIN_TYPE(a) == T_STRING) { + break; + case T_STRING: hnum = rb_str_hash(a); - } - else if (BUILTIN_TYPE(a) == T_SYMBOL) { - hnum = RSYMBOL(a)->hashval; - } - else if (BUILTIN_TYPE(a) == T_BIGNUM) { + break; + case T_BIGNUM: hval = rb_big_hash(a); hnum = FIX2LONG(hval); - } - else if (BUILTIN_TYPE(a) == T_FLOAT) { - flt: + break; + case T_FLOAT: /* prevent pathological behavior: [Bug #10761] */ hnum = rb_dbl_long_hash(rb_float_value(a)); - } - else { + break; + default: hnum = other_func(a); } - out: -#if SIZEOF_LONG < SIZEOF_ST_INDEX_T - if (hnum > 0) - hnum &= (unsigned long)-1 >> 2; + if ((SIGNED_VALUE)hnum > 0) + hnum &= FIXNUM_MAX; else - hnum |= ~((unsigned long)-1 >> 2); -#else - hnum <<= 1; - hnum = RSHIFT(hnum, 1); -#endif + hnum |= FIXNUM_MIN; return (long)hnum; } static st_index_t obj_any_hash(VALUE obj) { - obj = rb_hash(obj); - return FIX2LONG(obj); + VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0); + + if (hval == Qundef) { + hval = rb_exec_recursive_outer(hash_recursive, obj, 0); + } + + while (!FIXNUM_P(hval)) { + if (RB_TYPE_P(hval, T_BIGNUM)) { + int sign; + unsigned long ul; + sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0, + INTEGER_PACK_NATIVE_BYTE_ORDER); + if (sign < 0) { + hval = LONG2FIX(ul | FIXNUM_MIN); + } + else { + hval = LONG2FIX(ul & FIXNUM_MAX); + } + } + hval = rb_to_int(hval); + } + + return FIX2LONG(hval); } static st_index_t @@ -229,6 +223,13 @@ rb_any_hash(VALUE a) return any_hash(a, obj_any_hash); } +VALUE +rb_hash(VALUE obj) +{ + return LONG2FIX(any_hash(obj, obj_any_hash)); +} + + /* Here is a hash function for 64-bit key. It is about 5 times faster (2 times faster when uint128 type is absent) on Haswell than tailored Spooky or City hash function can be. */ @@ -299,6 +300,9 @@ objid_hash(VALUE obj) * implementations of Ruby. If you need a stable identifier across Ruby * invocations and implementations you will need to generate one with a custom * method. + * + * Certain core classes such as Integer use built-in hash calculations and + * do not call the #hash method when used as a hash key. *-- * \private *++ @@ -514,11 +518,13 @@ hash_verify_(VALUE hash, const char *file, int line) HASH_ASSERT(RHASH_AR_TABLE_BOUND_RAW(hash) == 0); } +#if USE_TRANSIENT_HEAP if (RHASH_TRANSIENT_P(hash)) { volatile st_data_t MAYBE_UNUSED(key) = RHASH_AR_TABLE_REF(hash, 0)->key; /* read */ HASH_ASSERT(RHASH_AR_TABLE(hash) != NULL); HASH_ASSERT(rb_transient_heap_managed_ptr_p(RHASH_AR_TABLE(hash))); } +#endif return hash; } @@ -781,7 +787,7 @@ ar_force_convert_table(VALUE hash, const char *file, int line) if (RHASH_AR_TABLE(hash)) { unsigned i, bound = RHASH_AR_TABLE_BOUND(hash); -#if RHASH_CONVERT_TABLE_DEBUG +#if defined(RHASH_CONVERT_TABLE_DEBUG) && RHASH_CONVERT_TABLE_DEBUG rb_obj_info_dump(hash); fprintf(stderr, "force_convert: %s:%d\n", file, line); RB_DEBUG_COUNTER_INC(obj_hash_force_convert); @@ -1264,19 +1270,17 @@ rb_hash_transient_heap_evacuate(VALUE hash, int promote) ar_table *old_tab = RHASH_AR_TABLE(hash); if (UNLIKELY(old_tab == NULL)) { - rb_gc_force_recycle(hash); return; } HASH_ASSERT(old_tab != NULL); + if (! promote) { + new_tab = rb_transient_heap_alloc(hash, sizeof(ar_table)); + if (new_tab == NULL) promote = true; + } if (promote) { - promote: new_tab = ruby_xmalloc(sizeof(ar_table)); RHASH_UNSET_TRANSIENT_FLAG(hash); } - else { - new_tab = rb_transient_heap_alloc(hash, sizeof(ar_table)); - if (new_tab == NULL) goto promote; - } *new_tab = *old_tab; hash_ar_table_set(hash, new_tab); } @@ -1418,7 +1422,7 @@ hash_iter_lev_inc(VALUE hash) } else { lev += 1; - RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | (lev << RHASH_LEV_SHIFT)); + RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT)); if (lev == RHASH_LEV_MAX) { iter_lev_in_ivar_set(hash, lev); } @@ -1502,11 +1506,16 @@ rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg) if (RHASH_TABLE_EMPTY_P(hash)) return; - hash_iter_lev_inc(hash); arg.hash = hash; arg.func = (rb_foreach_func *)func; arg.arg = farg; - rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash); + if (RB_OBJ_FROZEN(hash)) { + hash_foreach_call((VALUE)&arg); + } + else { + hash_iter_lev_inc(hash); + rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash); + } hash_verify(hash); } @@ -1541,6 +1550,15 @@ rb_hash_new(void) return hash_alloc(rb_cHash); } +static VALUE +copy_compare_by_id(VALUE hash, VALUE basis) +{ + if (rb_hash_compare_by_id_p(basis)) { + return rb_hash_compare_by_id(hash); + } + return hash; +} + MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size) { @@ -1558,10 +1576,8 @@ rb_hash_new_with_size(st_index_t size) } static VALUE -hash_dup(VALUE hash, VALUE klass, VALUE flags) +hash_copy(VALUE ret, VALUE hash) { - VALUE ret = hash_alloc_flags(klass, flags, - RHASH_IFNONE(hash)); if (!RHASH_EMPTY_P(hash)) { if (RHASH_AR_TABLE_P(hash)) ar_copy(ret, hash); @@ -1571,6 +1587,19 @@ hash_dup(VALUE hash, VALUE klass, VALUE flags) return ret; } +static VALUE +hash_dup_with_compare_by_id(VALUE hash) +{ + return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash); +} + +static VALUE +hash_dup(VALUE hash, VALUE klass, VALUE flags) +{ + return hash_copy(hash_alloc_flags(klass, flags, RHASH_IFNONE(hash)), + hash); +} + VALUE rb_hash_dup(VALUE hash) { @@ -1596,23 +1625,16 @@ rb_hash_modify_check(VALUE hash) } MJIT_FUNC_EXPORTED struct st_table * -#if RHASH_CONVERT_TABLE_DEBUG rb_hash_tbl_raw(VALUE hash, const char *file, int line) { return ar_force_convert_table(hash, file, line); } -#else -rb_hash_tbl_raw(VALUE hash) -{ - return ar_force_convert_table(hash, NULL, 0); -} -#endif struct st_table * rb_hash_tbl(VALUE hash, const char *file, int line) { OBJ_WB_UNPROTECT(hash); - return RHASH_TBL_RAW(hash); + return rb_hash_tbl_raw(hash, file, line); } static void @@ -1649,20 +1671,19 @@ func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \ struct update_arg { st_data_t arg; + st_update_callback_func *func; VALUE hash; - VALUE new_key; - VALUE old_key; - VALUE new_value; - VALUE old_value; + VALUE key; + VALUE value; }; typedef int (*tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int); int -rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg) +rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg) { if (RHASH_AR_TABLE_P(hash)) { - int result = ar_update(hash, (st_data_t)key, func, arg); + int result = ar_update(hash, key, func, arg); if (result == -1) { ar_try_convert_table(hash); } @@ -1671,29 +1692,54 @@ rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, s } } - return st_update(RHASH_ST_TABLE(hash), (st_data_t)key, func, arg); + return st_update(RHASH_ST_TABLE(hash), key, func, arg); +} + +static int +tbl_update_modify(st_data_t *key, st_data_t *val, st_data_t arg, int existing) +{ + struct update_arg *p = (struct update_arg *)arg; + st_data_t old_key = *key; + st_data_t old_value = *val; + VALUE hash = p->hash; + int ret = (p->func)(key, val, arg, existing); + switch (ret) { + default: + break; + case ST_CONTINUE: + if (!existing || *key != old_key || *val != old_value) { + rb_hash_modify(hash); + p->key = *key; + p->value = *val; + } + break; + case ST_DELETE: + if (existing) + rb_hash_modify(hash); + break; + } + + return ret; } static int tbl_update(VALUE hash, VALUE key, tbl_update_func func, st_data_t optional_arg) { - struct update_arg arg; - int result; - - arg.arg = optional_arg; - arg.hash = hash; - arg.new_key = 0; - arg.old_key = Qundef; - arg.new_value = 0; - arg.old_value = Qundef; + struct update_arg arg = { + .arg = optional_arg, + .func = func, + .hash = hash, + .key = key, + .value = (VALUE)optional_arg, + }; - result = rb_hash_stlike_update(hash, key, func, (st_data_t)&arg); + int ret = rb_hash_stlike_update(hash, key, tbl_update_modify, (st_data_t)&arg); /* write barrier */ - if (arg.new_key) RB_OBJ_WRITTEN(hash, arg.old_key, arg.new_key); - if (arg.new_value) RB_OBJ_WRITTEN(hash, arg.old_value, arg.new_value); + RB_OBJ_WRITTEN(hash, Qundef, arg.key); + RB_OBJ_WRITTEN(hash, Qundef, arg.value); - return result; + return ret; } #define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert) @@ -1723,37 +1769,33 @@ set_proc_default(VALUE hash, VALUE proc) /* * call-seq: - * Hash.new -> new_hash - * Hash.new(obj) -> new_hash - * Hash.new {|hash, key| block } -> new_hash - * - * Returns a new, empty hash. If this hash is subsequently accessed by - * a key that doesn't correspond to a hash entry, the value returned - * depends on the style of new used to create the hash. In - * the first form, the access returns nil. If - * obj is specified, this single object will be used for - * all default values. If a block is specified, it will be - * called with the hash object and the key, and should return the - * default value. It is the block's responsibility to store the value - * in the hash if required. - * - * h = Hash.new("Go Fish") - * h["a"] = 100 - * h["b"] = 200 - * h["a"] #=> 100 - * h["c"] #=> "Go Fish" - * # The following alters the single default object - * h["c"].upcase! #=> "GO FISH" - * h["d"] #=> "GO FISH" - * h.keys #=> ["a", "b"] - * - * # While this creates a new default object each time - * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } - * h["c"] #=> "Go Fish: c" - * h["c"].upcase! #=> "GO FISH: C" - * h["d"] #=> "Go Fish: d" - * h.keys #=> ["c", "d"] - * + * Hash.new(default_value = nil) -> new_hash + * Hash.new {|hash, key| ... } -> new_hash + * + * Returns a new empty \Hash object. + * + * The initial default value and initial default proc for the new hash + * depend on which form above was used. See {Default Values}[#class-Hash-label-Default+Values]. + * + * If neither an argument nor a block given, + * initializes both the default value and the default proc to nil: + * h = Hash.new + * h.default # => nil + * h.default_proc # => nil + * + * If argument default_value given but no block given, + * initializes the default value to the given default_value + * and the default proc to nil: + * h = Hash.new(false) + * h.default # => false + * h.default_proc # => nil + * + * If a block given but no argument, stores the block as the default proc + * and sets the default value to nil: + * h = Hash.new {|hash, key| "Default value for #{key}" } + * h.default # => nil + * h.default_proc.class # => Proc + * h[:nosuch] # => "Default value for nosuch" */ static VALUE @@ -1778,22 +1820,37 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash) /* * call-seq: - * Hash[ key, value, ... ] -> new_hash - * Hash[ [ [key, value], ... ] ] -> new_hash - * Hash[ object ] -> new_hash + * Hash[] -> new_empty_hash + * Hash[hash] -> new_hash + * Hash[ [*2_element_arrays] ] -> new_hash + * Hash[*objects] -> new_hash + * + * Returns a new \Hash object populated with the given objects, if any. + * See Hash::new. + * + * With no argument, returns a new empty \Hash. * - * Creates a new hash populated with the given objects. + * When the single given argument is a \Hash, returns a new \Hash + * populated with the entries from the given \Hash, excluding the + * default value or proc. * - * Similar to the literal { _key_ => _value_, ... }. In the first - * form, keys and values occur in pairs, so there must be an even number of - * arguments. + * h = {foo: 0, bar: 1, baz: 2} + * Hash[h] # => {:foo=>0, :bar=>1, :baz=>2} * - * The second and third form take a single argument which is either an array - * of key-value pairs or an object convertible to a hash. + * When the single given argument is an \Array of 2-element Arrays, + * returns a new \Hash object wherein each 2-element array forms a + * key-value entry: * - * Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200} - * Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200} - * Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200} + * Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {:foo=>0, :bar=>1} + * + * When the argument count is an even number; + * returns a new \Hash object wherein each successive pair of arguments + * has become a key-value entry: + * + * Hash[:foo, 0, :bar, 1] # => {:foo=>0, :bar=>1} + * + * Raises an exception if the argument list does not conform to any + * of the above. */ static VALUE @@ -1805,12 +1862,7 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass) tmp = rb_hash_s_try_convert(Qnil, argv[0]); if (!NIL_P(tmp)) { hash = hash_alloc(klass); - if (RHASH_AR_TABLE_P(tmp)) { - ar_copy(hash, tmp); - } - else { - RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(tmp))); - } + hash_copy(hash, tmp); return hash; } @@ -1852,7 +1904,7 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass) return hash; } -VALUE +MJIT_FUNC_EXPORTED VALUE rb_to_hash_type(VALUE hash) { return rb_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash); @@ -1867,14 +1919,16 @@ rb_check_hash_type(VALUE hash) /* * call-seq: - * Hash.try_convert(obj) -> hash or nil + * Hash.try_convert(obj) -> obj, new_hash, or nil * - * Try to convert obj into a hash, using to_hash method. - * Returns converted hash or nil if obj cannot be converted - * for any reason. + * If +obj+ is a \Hash object, returns +obj+. * - * Hash.try_convert({1=>2}) # => {1=>2} - * Hash.try_convert("1=>2") # => nil + * Otherwise if +obj+ responds to :to_hash, + * calls obj.to_hash and returns the result. + * + * Returns +nil+ if +obj+ does not respond to :to_hash + * + * Raises an exception unless obj.to_hash returns a \Hash object. */ static VALUE rb_hash_s_try_convert(VALUE dummy, VALUE hash) @@ -1901,7 +1955,7 @@ static VALUE rb_hash_s_ruby2_keywords_hash_p(VALUE dummy, VALUE hash) { Check_Type(hash, T_HASH); - return (RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS) ? Qtrue : Qfalse; + return RBOOL(RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS); } /* @@ -1947,22 +2001,14 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) /* * call-seq: - * hsh.rehash -> hsh - * - * Rebuilds the hash based on the current hash values for each key. If - * values of key objects have changed since they were inserted, this - * method will reindex hsh. If Hash#rehash is - * called while an iterator is traversing the hash, a - * RuntimeError will be raised in the iterator. - * - * a = [ "a", "b" ] - * c = [ "c", "d" ] - * h = { a => 100, c => 300 } - * h[a] #=> 100 - * a[0] = "z" - * h[a] #=> nil - * h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300} - * h[a] #=> 100 + * hash.rehash -> self + * + * Rebuilds the hash table by recomputing the hash index for each key; + * returns self. + * + * The hash table becomes invalid if the hash value of a key + * has changed after the entry was created. + * See {Modifying an Active Hash Key}[#class-Hash-label-Modifying+an+Active+Hash+Key]. */ VALUE @@ -1997,14 +2043,21 @@ rb_hash_rehash(VALUE hash) return hash; } +static VALUE +call_default_proc(VALUE proc, VALUE hash, VALUE key) +{ + VALUE args[2] = {hash, key}; + return rb_proc_call_with_block(proc, 2, args, Qnil); +} + VALUE rb_hash_default_value(VALUE hash, VALUE key) { - if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { + if (LIKELY(rb_method_basic_definition_p(CLASS_OF(hash), id_default))) { VALUE ifnone = RHASH_IFNONE(hash); if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone; if (key == Qundef) return Qnil; - return rb_funcall(ifnone, id_yield, 2, hash, key); + return call_default_proc(ifnone, hash, key); } else { return rb_funcall(hash, id_default, 1, key); @@ -2032,16 +2085,16 @@ rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval) /* * call-seq: - * hsh[key] -> value + * hash[key] -> value * - * Element Reference---Retrieves the value object corresponding - * to the key object. If not found, returns the default value (see - * Hash::new for details). - * - * h = { "a" => 100, "b" => 200 } - * h["a"] #=> 100 - * h["c"] #=> nil + * Returns the value associated with the given +key+, if found: + * h = {foo: 0, bar: 1, baz: 2} + * h[:foo] # => 0 * + * If +key+ is not found, returns a default value + * (see {Default Values}[#class-Hash-label-Default+Values]): + * h = {foo: 0, bar: 1, baz: 2} + * h[:nosuch] # => nil */ VALUE @@ -2078,31 +2131,25 @@ rb_hash_lookup(VALUE hash, VALUE key) /* * call-seq: - * hsh.fetch(key [, default] ) -> obj - * hsh.fetch(key) {| key | block } -> obj - * - * Returns a value from the hash for the given key. If the key can't be - * found, there are several options: With no other arguments, it will - * raise a KeyError exception; if default is given, - * then that will be returned; if the optional code block is specified, - * then that will be run and its result returned. + * hash.fetch(key) -> object + * hash.fetch(key, default_value) -> object + * hash.fetch(key) {|key| ... } -> object * - * h = { "a" => 100, "b" => 200 } - * h.fetch("a") #=> 100 - * h.fetch("z", "go fish") #=> "go fish" - * h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z" + * Returns the value for the given +key+, if found. + * h = {foo: 0, bar: 1, baz: 2} + * h.fetch(:bar) # => 1 * - * The following example shows that an exception is raised if the key - * is not found and a default value is not supplied. + * If +key+ is not found and no block was given, + * returns +default_value+: + * {}.fetch(:nosuch, :default) # => :default * - * h = { "a" => 100, "b" => 200 } - * h.fetch("z") + * If +key+ is not found and a block was given, + * yields +key+ to the block and returns the block's return value: + * {}.fetch(:nosuch) {|key| "No key #{key}"} # => "No key nosuch" * - * produces: - * - * prog.rb:2:in `fetch': key not found (KeyError) - * from prog.rb:2 + * Raises KeyError if neither +default_value+ nor a block was given. * + * Note that this method does not use the values of either #default or #default_proc. */ static VALUE @@ -2149,59 +2196,49 @@ rb_hash_fetch(VALUE hash, VALUE key) /* * call-seq: - * hsh.default(key=nil) -> obj - * - * Returns the default value, the value that would be returned by - * hsh[key] if key did not exist in hsh. - * See also Hash::new and Hash#default=. - * - * h = Hash.new #=> {} - * h.default #=> nil - * h.default(2) #=> nil - * - * h = Hash.new("cat") #=> {} - * h.default #=> "cat" - * h.default(2) #=> "cat" - * - * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {} - * h.default #=> nil - * h.default(2) #=> 20 + * hash.default -> object + * hash.default(key) -> object + * + * Returns the default value for the given +key+. + * The returned value will be determined either by the default proc or by the default value. + * See {Default Values}[#class-Hash-label-Default+Values]. + * + * With no argument, returns the current default value: + * h = {} + * h.default # => nil + * + * If +key+ is given, returns the default value for +key+, + * regardless of whether that key exists: + * h = Hash.new { |hash, key| hash[key] = "No key #{key}"} + * h[:foo] = "Hello" + * h.default(:foo) # => "No key foo" */ static VALUE rb_hash_default(int argc, VALUE *argv, VALUE hash) { - VALUE args[2], ifnone; + VALUE ifnone; rb_check_arity(argc, 0, 1); ifnone = RHASH_IFNONE(hash); if (FL_TEST(hash, RHASH_PROC_DEFAULT)) { if (argc == 0) return Qnil; - args[0] = hash; - args[1] = argv[0]; - return rb_funcallv(ifnone, id_yield, 2, args); + return call_default_proc(ifnone, hash, argv[0]); } return ifnone; } /* * call-seq: - * hsh.default = obj -> obj - * - * Sets the default value, the value returned for a key that does not - * exist in the hash. It is not possible to set the default to a - * Proc that will be executed on each key lookup. - * - * h = { "a" => 100, "b" => 200 } - * h.default = "Go fish" - * h["a"] #=> 100 - * h["z"] #=> "Go fish" - * # This doesn't do what you might hope... - * h.default = proc do |hash, key| - * hash[key] = key + key - * end - * h[2] #=> # - * h["cat"] #=> # + * hash.default = value -> object + * + * Sets the default value to +value+; returns +value+: + * h = {} + * h.default # => nil + * h.default = false # => false + * h.default # => false + * + * See {Default Values}[#class-Hash-label-Default+Values]. */ static VALUE @@ -2214,19 +2251,16 @@ rb_hash_set_default(VALUE hash, VALUE ifnone) /* * call-seq: - * hsh.default_proc -> anObject - * - * If Hash::new was invoked with a block, return that - * block, otherwise return nil. - * - * h = Hash.new {|h,k| h[k] = k*k } #=> {} - * p = h.default_proc #=> # - * a = [] #=> [] - * p.call(a, 2) - * a #=> [nil, nil, 4] + * hash.default_proc -> proc or nil + * + * Returns the default proc for +self+ + * (see {Default Values}[#class-Hash-label-Default+Values]): + * h = {} + * h.default_proc # => nil + * h.default_proc = proc {|hash, key| "Default value for #{key}" } + * h.default_proc.class # => Proc */ - static VALUE rb_hash_default_proc(VALUE hash) { @@ -2238,15 +2272,16 @@ rb_hash_default_proc(VALUE hash) /* * call-seq: - * hsh.default_proc = proc_obj or nil - * - * Sets the default proc to be executed on each failed key lookup. - * - * h.default_proc = proc do |hash, key| - * hash[key] = key + key - * end - * h[2] #=> 4 - * h["cat"] #=> "catcat" + * hash.default_proc = proc -> proc + * + * Sets the default proc for +self+ to +proc+: + * (see {Default Values}[#class-Hash-label-Default+Values]): + * h = {} + * h.default_proc # => nil + * h.default_proc = proc { |hash, key| "Default value for #{key}" } + * h.default_proc.class # => Proc + * h.default_proc = nil + * h.default_proc # => nil */ VALUE @@ -2284,16 +2319,15 @@ key_i(VALUE key, VALUE value, VALUE arg) /* * call-seq: - * hsh.key(value) -> key - * - * Returns the key of an occurrence of a given value. If the value is - * not found, returns nil. + * hash.key(value) -> key or nil * - * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 } - * h.key(200) #=> "b" - * h.key(300) #=> "c" - * h.key(999) #=> nil + * Returns the key for the first-found entry with the given +value+ + * (see {Entry Order}[#class-Hash-label-Entry+Order]): + * h = {foo: 0, bar: 2, baz: 2} + * h.key(0) # => :foo + * h.key(2) # => :bar * + * Returns +nil+ if so such value is found. */ static VALUE @@ -2309,14 +2343,6 @@ rb_hash_key(VALUE hash, VALUE value) return args[1]; } -/* :nodoc: */ -static VALUE -rb_hash_index(VALUE hash, VALUE value) -{ - rb_warn_deprecated("Hash#index", "Hash#key"); - return rb_hash_key(hash, value); -} - int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval) { @@ -2329,7 +2355,7 @@ rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval) } /* - * delete a specified entry a given key. + * delete a specified entry by a given key. * if there is the corresponding entry, return a value of the entry. * if there is no corresponding entry, return Qundef. */ @@ -2366,20 +2392,29 @@ rb_hash_delete(VALUE hash, VALUE key) /* * call-seq: - * hsh.delete(key) -> value - * hsh.delete(key) {| key | block } -> value + * hash.delete(key) -> value or nil + * hash.delete(key) {|key| ... } -> object + * + * Deletes the entry for the given +key+ and returns its associated value. * - * Deletes the key-value pair and returns the value from hsh whose - * key is equal to key. If the key is not found, it returns - * nil. If the optional code block is given and the - * key is not found, pass in the key and return the result of - * block. + * If no block is given and +key+ is found, deletes the entry and returns the associated value: + * h = {foo: 0, bar: 1, baz: 2} + * h.delete(:bar) # => 1 + * h # => {:foo=>0, :baz=>2} * - * h = { "a" => 100, "b" => 200 } - * h.delete("a") #=> 100 - * h.delete("z") #=> nil - * h.delete("z") { |el| "#{el} not found" } #=> "z not found" + * If no block given and +key+ is not found, returns +nil+. * + * If a block is given and +key+ is found, ignores the block, + * deletes the entry, and returns the associated value: + * h = {foo: 0, bar: 1, baz: 2} + * h.delete(:baz) { |key| raise 'Will never happen'} # => 2 + * h # => {:foo=>0, :bar=>1} + * + * If a block is given and +key+ is not found, + * calls the block and returns the block's return value: + * h = {foo: 0, bar: 1, baz: 2} + * h.delete(:nosuch) { |key| "Key #{key} not found" } # => "Key nosuch not found" + * h # => {:foo=>0, :bar=>1, :baz=>2} */ static VALUE @@ -2420,15 +2455,17 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) /* * call-seq: - * hsh.shift -> anArray or obj + * hash.shift -> [key, value] or default_value * - * Removes a key-value pair from hsh and returns it as the - * two-item array [ key, value ], or - * the hash's default value if the hash is empty. + * Removes the first hash entry + * (see {Entry Order}[#class-Hash-label-Entry+Order]); + * returns a 2-element \Array containing the removed key and value: + * h = {foo: 0, bar: 1, baz: 2} + * h.shift # => [:foo, 0] + * h # => {:bar=>1, :baz=>2} * - * h = { 1 => "a", 2 => "b", 3 => "c" } - * h.shift #=> [1, "a"] - * h #=> {2=>"b", 3=>"c"} + * Returns the default value if the hash is empty + * (see {Default Values}[#class-Hash-label-Default+Values]). */ static VALUE @@ -2474,6 +2511,7 @@ static int delete_if_i(VALUE key, VALUE value, VALUE hash) { if (RTEST(rb_yield_values(2, key, value))) { + rb_hash_modify(hash); return ST_DELETE; } return ST_CONTINUE; @@ -2487,17 +2525,19 @@ hash_enum_size(VALUE hash, VALUE args, VALUE eobj) /* * call-seq: - * hsh.delete_if {| key, value | block } -> hsh - * hsh.delete_if -> an_enumerator - * - * Deletes every key-value pair from hsh for which block - * evaluates to true. - * - * If no block is given, an enumerator is returned instead. - * - * h = { "a" => 100, "b" => 200, "c" => 300 } - * h.delete_if {|key, value| key >= "b" } #=> {"a"=>100} - * + * hash.delete_if {|key, value| ... } -> self + * hash.delete_if -> new_enumerator + * + * If a block given, calls the block with each key-value pair; + * deletes each entry for which the block returns a truthy value; + * returns +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.delete_if {|key, value| value > 0 } # => {:foo=>0} + * + * If no block given, returns a new \Enumerator: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.delete_if # => #0, :bar=>1, :baz=>2}:delete_if> + * e.each { |key, value| value > 0 } # => {:foo=>0} */ VALUE @@ -2513,14 +2553,23 @@ rb_hash_delete_if(VALUE hash) /* * call-seq: - * hsh.reject! {| key, value | block } -> hsh or nil - * hsh.reject! -> an_enumerator + * hash.reject! {|key, value| ... } -> self or nil + * hash.reject! -> new_enumerator + * + * Returns +self+, whose remaining entries are those + * for which the block returns +false+ or +nil+: + * h = {foo: 0, bar: 1, baz: 2} + * h.reject! {|key, value| value < 2 } # => {:baz=>2} * - * Equivalent to Hash#delete_if, but returns - * nil if no changes were made. + * Returns +nil+ if no entries are removed. + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.reject! # => #0, :bar=>1, :baz=>2}:reject!> + * e.each {|key, value| key.start_with?('b') } # => {:foo=>0} */ -VALUE +static VALUE rb_hash_reject_bang(VALUE hash) { st_index_t n; @@ -2534,57 +2583,46 @@ rb_hash_reject_bang(VALUE hash) return hash; } -static int -reject_i(VALUE key, VALUE value, VALUE result) -{ - if (!RTEST(rb_yield_values(2, key, value))) { - rb_hash_aset(result, key, value); - } - return ST_CONTINUE; -} - /* * call-seq: - * hsh.reject {|key, value| block} -> a_hash - * hsh.reject -> an_enumerator - * - * Returns a new hash consisting of entries for which the block returns false. - * - * If no block is given, an enumerator is returned instead. - * - * h = { "a" => 100, "b" => 200, "c" => 300 } - * h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300} - * h.reject {|k,v| v > 100} #=> {"a" => 100} + * hash.reject {|key, value| ... } -> new_hash + * hash.reject -> new_enumerator + * + * Returns a new \Hash object whose entries are all those + * from +self+ for which the block returns +false+ or +nil+: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.reject {|key, value| key.start_with?('b') } + * h1 # => {:foo=>0} + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.reject # => #0, :bar=>1, :baz=>2}:reject> + * h1 = e.each {|key, value| key.start_with?('b') } + * h1 # => {:foo=>0} */ -VALUE +static VALUE rb_hash_reject(VALUE hash) { VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - if (RTEST(ruby_verbose)) { - VALUE klass; - if (HAS_EXTRA_STATES(hash, klass)) { - rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash); - } - } - result = rb_hash_new(); + result = hash_dup_with_compare_by_id(hash); if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, reject_i, result); + rb_hash_foreach(result, delete_if_i, result); } return result; } /* * call-seq: - * hsh.slice(*keys) -> a_hash + * hash.slice(*keys) -> new_hash * - * Returns a hash containing only the given keys and their values. + * Returns a new \Hash object containing the entries for the given +keys+: + * h = {foo: 0, bar: 1, baz: 2} + * h.slice(:baz, :foo) # => {:baz=>2, :foo=>0} * - * h = { a: 100, b: 200, c: 300 } - * h.slice(:a) #=> {:a=>100} - * h.slice(:b, :c, :d) #=> {:b=>200, :c=>300} + * Any given +keys+ that are not found are ignored. */ static VALUE @@ -2594,9 +2632,9 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash) VALUE key, value, result; if (argc == 0 || RHASH_EMPTY_P(hash)) { - return rb_hash_new(); + return copy_compare_by_id(rb_hash_new(), hash); } - result = rb_hash_new_with_size(argc); + result = copy_compare_by_id(rb_hash_new_with_size(argc), hash); for (i = 0; i < argc; i++) { key = argv[i]; @@ -2609,17 +2647,46 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash) } /* - * call-seq: - * hsh.values_at(key, ...) -> array + * call-seq: + * hsh.except(*keys) -> a_hash * - * Return an array containing the values associated with the given keys. - * Also see Hash.select. + * Returns a new \Hash excluding entries for the given +keys+: + * h = { a: 100, b: 200, c: 300 } + * h.except(:a) #=> {:b=>200, :c=>300} * - * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } - * h.values_at("cow", "cat") #=> ["bovine", "feline"] + * Any given +keys+ that are not found are ignored. */ -VALUE +static VALUE +rb_hash_except(int argc, VALUE *argv, VALUE hash) +{ + int i; + VALUE key, result; + + result = hash_dup_with_compare_by_id(hash); + + for (i = 0; i < argc; i++) { + key = argv[i]; + rb_hash_delete(result, key); + } + + return result; +} + +/* + * call-seq: + * hash.values_at(*keys) -> new_array + * + * Returns a new \Array containing values for the given +keys+: + * h = {foo: 0, bar: 1, baz: 2} + * h.values_at(:baz, :foo) # => [2, 0] + * + * The {default values}[#class-Hash-label-Default+Values] are returned + * for any keys that are not found: + * h.values_at(:hello, :foo) # => [nil, 0] + */ + +static VALUE rb_hash_values_at(int argc, VALUE *argv, VALUE hash) { VALUE result = rb_ary_new2(argc); @@ -2632,22 +2699,26 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) } /* - * call-seq: - * hsh.fetch_values(key, ...) -> array - * hsh.fetch_values(key, ...) { |key| block } -> array + * call-seq: + * hash.fetch_values(*keys) -> new_array + * hash.fetch_values(*keys) {|key| ... } -> new_array + * + * Returns a new \Array containing the values associated with the given keys *keys: + * h = {foo: 0, bar: 1, baz: 2} + * h.fetch_values(:baz, :foo) # => [2, 0] * - * Returns an array containing the values associated with the given keys - * but also raises KeyError when one of keys can't be found. - * Also see Hash#values_at and Hash#fetch. + * Returns a new empty \Array if no arguments given. * - * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } + * When a block is given, calls the block with each missing key, + * treating the block's return value as the value for that key: + * h = {foo: 0, bar: 1, baz: 2} + * values = h.fetch_values(:bar, :foo, :bad, :bam) {|key| key.to_s} + * values # => [1, 0, "bad", "bam"] * - * h.fetch_values("cow", "cat") #=> ["bovine", "feline"] - * h.fetch_values("cow", "bird") # raises KeyError - * h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"] + * When no block is given, raises an exception if any given key is not found. */ -VALUE +static VALUE rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash) { VALUE result = rb_ary_new2(argc); @@ -2660,68 +2731,65 @@ rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash) } static int -select_i(VALUE key, VALUE value, VALUE result) +keep_if_i(VALUE key, VALUE value, VALUE hash) { - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_aset(result, key, value); + if (!RTEST(rb_yield_values(2, key, value))) { + rb_hash_modify(hash); + return ST_DELETE; } return ST_CONTINUE; } /* * call-seq: - * hsh.select {|key, value| block} -> a_hash - * hsh.select -> an_enumerator - * hsh.filter {|key, value| block} -> a_hash - * hsh.filter -> an_enumerator + * hash.select {|key, value| ... } -> new_hash + * hash.select -> new_enumerator * - * Returns a new hash consisting of entries for which the block returns true. - * - * If no block is given, an enumerator is returned instead. + * Hash#filter is an alias for Hash#select. * - * h = { "a" => 100, "b" => 200, "c" => 300 } - * h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300} - * h.select {|k,v| v < 200} #=> {"a" => 100} + * Returns a new \Hash object whose entries are those for which the block returns a truthy value: + * h = {foo: 0, bar: 1, baz: 2} + * h.select {|key, value| value < 2 } # => {:foo=>0, :bar=>1} * - * Hash#filter is an alias for Hash#select. + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.select # => #0, :bar=>1, :baz=>2}:select> + * e.each {|key, value| value < 2 } # => {:foo=>0, :bar=>1} */ -VALUE +static VALUE rb_hash_select(VALUE hash) { VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = rb_hash_new(); + result = hash_dup_with_compare_by_id(hash); if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, select_i, result); + rb_hash_foreach(result, keep_if_i, result); } return result; } -static int -keep_if_i(VALUE key, VALUE value, VALUE hash) -{ - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } - return ST_CONTINUE; -} - /* * call-seq: - * hsh.select! {| key, value | block } -> hsh or nil - * hsh.select! -> an_enumerator - * hsh.filter! {| key, value | block } -> hsh or nil - * hsh.filter! -> an_enumerator - * - * Equivalent to Hash#keep_if, but returns - * +nil+ if no changes were made. + * hash.select! {|key, value| ... } -> self or nil + * hash.select! -> new_enumerator * * Hash#filter! is an alias for Hash#select!. + * + * Returns +self+, whose entries are those for which the block returns a truthy value: + * h = {foo: 0, bar: 1, baz: 2} + * h.select! {|key, value| value < 2 } => {:foo=>0, :bar=>1} + * + * Returns +nil+ if no entries were removed. + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.select! # => #0, :bar=>1, :baz=>2}:select!> + * e.each { |key, value| value < 2 } # => {:foo=>0, :bar=>1} */ -VALUE +static VALUE rb_hash_select_bang(VALUE hash) { st_index_t n; @@ -2737,18 +2805,22 @@ rb_hash_select_bang(VALUE hash) /* * call-seq: - * hsh.keep_if {| key, value | block } -> hsh - * hsh.keep_if -> an_enumerator - * - * Deletes every key-value pair from hsh for which block - * evaluates to +false+. - * - * If no block is given, an enumerator is returned instead. - * - * See also Hash#select!. + * hash.keep_if {|key, value| ... } -> self + * hash.keep_if -> new_enumerator + * + * Calls the block for each key-value pair; + * retains the entry if the block returns a truthy value; + * otherwise deletes the entry; returns +self+. + * h = {foo: 0, bar: 1, baz: 2} + * h.keep_if { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2} + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.keep_if # => #0, :bar=>1, :baz=>2}:keep_if> + * e.each { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2} */ -VALUE +static VALUE rb_hash_keep_if(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); @@ -2767,13 +2839,9 @@ clear_i(VALUE key, VALUE value, VALUE dummy) /* * call-seq: - * hsh.clear -> hsh - * - * Removes all key-value pairs from hsh. - * - * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200} - * h.clear #=> {} + * hash.clear -> self * + * Removes all hash entries; returns +self+. */ VALUE @@ -2797,14 +2865,6 @@ rb_hash_clear(VALUE hash) static int hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing) { - if (existing) { - arg->new_value = arg->arg; - arg->old_value = *val; - } - else { - arg->new_key = *key; - arg->new_value = arg->arg; - } *val = arg->arg; return ST_CONTINUE; } @@ -2834,29 +2894,28 @@ NOINSERT_UPDATE_CALLBACK(hash_aset_str) /* * call-seq: - * hsh[key] = value -> value - * hsh.store(key, value) -> value - * - * == Element Assignment - * - * Associates the value given by +value+ with the key given by +key+. - * - * h = { "a" => 100, "b" => 200 } - * h["a"] = 9 - * h["c"] = 4 - * h #=> {"a"=>9, "b"=>200, "c"=>4} - * h.store("d", 42) #=> 42 - * h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42} - * - * +key+ should not have its value changed while it is in use as a key (an - * unfrozen String passed as a key will be duplicated and frozen). - * - * a = "a" - * b = "b".freeze - * h = { a => 100, b => 200 } - * h.key(100).equal? a #=> false - * h.key(200).equal? b #=> true - * + * hash[key] = value -> value + * hash.store(key, value) + * + * Hash#store is an alias for Hash#[]=. + + * Associates the given +value+ with the given +key+; returns +value+. + * + * If the given +key+ exists, replaces its value with the given +value+; + * the ordering is not affected + * (see {Entry Order}[#class-Hash-label-Entry+Order]): + * h = {foo: 0, bar: 1} + * h[:foo] = 2 # => 2 + * h.store(:bar, 3) # => 3 + * h # => {:foo=>2, :bar=>3} + * + * If +key+ does not exist, adds the +key+ and +value+; + * the new entry is last in the order + * (see {Entry Order}[#class-Hash-label-Entry+Order]): + * h = {foo: 0, bar: 1} + * h[:baz] = 2 # => 2 + * h.store(:bat, 3) # => 3 + * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3} */ VALUE @@ -2882,14 +2941,12 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) /* * call-seq: - * hsh.replace(other_hash) -> hsh - * - * Replaces the contents of hsh with the contents of - * other_hash. - * - * h = { "a" => 100, "b" => 200 } - * h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400} + * hash.replace(other_hash) -> self * + * Replaces the entire contents of +self+ with the contents of +other_hash+; + * returns +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4} */ static VALUE @@ -2905,25 +2962,17 @@ rb_hash_replace(VALUE hash, VALUE hash2) COPY_DEFAULT(hash, hash2); if (RHASH_AR_TABLE_P(hash)) { - if (RHASH_AR_TABLE_P(hash2)) { - ar_clear(hash); - } - else { - ar_free_and_clear_table(hash); - RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), RHASH_SIZE(hash2))); - } + ar_free_and_clear_table(hash); } else { - if (RHASH_AR_TABLE_P(hash2)) { - st_free_table(RHASH_ST_TABLE(hash)); - RHASH_ST_CLEAR(hash); - } - else { - st_clear(RHASH_ST_TABLE(hash)); - RHASH_TBL_RAW(hash)->type = RHASH_ST_TABLE(hash2)->type; - } + st_free_table(RHASH_ST_TABLE(hash)); + RHASH_ST_CLEAR(hash); + } + hash_copy(hash, hash2); + if (RHASH_EMPTY_P(hash2) && RHASH_ST_TABLE_P(hash2)) { + /* ident hash */ + RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), 0)); } - rb_hash_foreach(hash2, rb_hash_rehash_i, (VALUE)hash); rb_gc_writebarrier_remember(hash); @@ -2932,16 +2981,11 @@ rb_hash_replace(VALUE hash, VALUE hash2) /* * call-seq: - * hsh.length -> integer - * hsh.size -> integer + * hash.length -> integer + * hash.size -> integer * - * Returns the number of key-value pairs in the hash. - * - * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 } - * h.size #=> 4 - * h.delete("a") #=> 200 - * h.size #=> 3 - * h.length #=> 3 + * Returns the count of entries in +self+: + * {foo: 0, bar: 1, baz: 2}.length # => 3 * * Hash#length is an alias for Hash#size. */ @@ -2960,18 +3004,17 @@ rb_hash_size_num(VALUE hash) /* * call-seq: - * hsh.empty? -> true or false - * - * Returns true if hsh contains no key-value pairs. - * - * {}.empty? #=> true + * hash.empty? -> true or false * + * Returns +true+ if there are no hash entries, +false+ otherwise: + * {}.empty? # => true + * {foo: 0, bar: 1, baz: 2}.empty? # => false */ static VALUE rb_hash_empty_p(VALUE hash) { - return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse; + return RBOOL(RHASH_EMPTY_P(hash)); } static int @@ -2983,21 +3026,26 @@ each_value_i(VALUE key, VALUE value, VALUE _) /* * call-seq: - * hsh.each_value {| value | block } -> hsh - * hsh.each_value -> an_enumerator - * - * Calls block once for each key in hsh, passing the - * value as a parameter. - * - * If no block is given, an enumerator is returned instead. - * - * h = { "a" => 100, "b" => 200 } - * h.each_value {|value| puts value } - * - * produces: - * - * 100 - * 200 + * hash.each_value {|value| ... } -> self + * hash.each_value -> new_enumerator + * + * Calls the given block with each value; returns +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.each_value {|value| puts value } # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * 0 + * 1 + * 2 + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.each_value # => #0, :bar=>1, :baz=>2}:each_value> + * h1 = e.each {|value| puts value } + * h1 # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * 0 + * 1 + * 2 */ static VALUE @@ -3017,21 +3065,26 @@ each_key_i(VALUE key, VALUE value, VALUE _) /* * call-seq: - * hsh.each_key {| key | block } -> hsh - * hsh.each_key -> an_enumerator - * - * Calls block once for each key in hsh, passing the key - * as a parameter. - * - * If no block is given, an enumerator is returned instead. - * - * h = { "a" => 100, "b" => 200 } - * h.each_key {|key| puts key } - * - * produces: - * - * a - * b + * hash.each_key {|key| ... } -> self + * hash.each_key -> new_enumerator + * + * Calls the given block with each key; returns +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.each_key {|key| puts key } # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * foo + * bar + * baz + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.each_key # => #0, :bar=>1, :baz=>2}:each_key> + * h1 = e.each {|key| puts key } + * h1 # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * foo + * bar + * baz */ static VALUE rb_hash_each_key(VALUE hash) @@ -3060,37 +3113,65 @@ each_pair_i_fast(VALUE key, VALUE value, VALUE _) /* * call-seq: - * hsh.each {| key, value | block } -> hsh - * hsh.each_pair {| key, value | block } -> hsh - * hsh.each -> an_enumerator - * hsh.each_pair -> an_enumerator - * - * Calls block once for each key in hsh, passing the key-value - * pair as parameters. - * - * If no block is given, an enumerator is returned instead. - * - * h = { "a" => 100, "b" => 200 } - * h.each {|key, value| puts "#{key} is #{value}" } - * - * produces: - * - * a is 100 - * b is 200 - * + * hash.each {|key, value| ... } -> self + * hash.each_pair {|key, value| ... } -> self + * hash.each -> new_enumerator + * hash.each_pair -> new_enumerator + * + * Hash#each is an alias for Hash#each_pair. + + * Calls the given block with each key-value pair; returns +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.each_pair {|key, value| puts "#{key}: #{value}"} # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * foo: 0 + * bar: 1 + * baz: 2 + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.each_pair # => #0, :bar=>1, :baz=>2}:each_pair> + * h1 = e.each {|key, value| puts "#{key}: #{value}"} + * h1 # => {:foo=>0, :bar=>1, :baz=>2} + * Output: + * foo: 0 + * bar: 1 + * baz: 2 */ static VALUE rb_hash_each_pair(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - if (rb_block_arity() > 1) + if (rb_block_pair_yield_optimizable()) rb_hash_foreach(hash, each_pair_i_fast, 0); else rb_hash_foreach(hash, each_pair_i, 0); return hash; } +struct transform_keys_args{ + VALUE trans; + VALUE result; + int block_given; +}; + +static int +transform_keys_hash_i(VALUE key, VALUE value, VALUE transarg) +{ + struct transform_keys_args *p = (void *)transarg; + VALUE trans = p->trans, result = p->result; + VALUE new_key = rb_hash_lookup2(trans, key, Qundef); + if (new_key == Qundef) { + if (p->block_given) + new_key = rb_yield(key); + else + new_key = key; + } + rb_hash_aset(result, new_key, value); + return ST_CONTINUE; +} + static int transform_keys_i(VALUE key, VALUE value, VALUE result) { @@ -3101,68 +3182,125 @@ transform_keys_i(VALUE key, VALUE value, VALUE result) /* * call-seq: - * hsh.transform_keys {|key| block } -> new_hash - * hsh.transform_keys -> an_enumerator - * - * Returns a new hash with the results of running the block once for - * every key. - * This method does not change the values. - * - * h = { a: 1, b: 2, c: 3 } - * h.transform_keys {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 } - * h.transform_keys(&:to_s) #=> { "a" => 1, "b" => 2, "c" => 3 } - * h.transform_keys.with_index {|k, i| "#{k}.#{i}" } - * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 } - * - * If no block is given, an enumerator is returned instead. + * hash.transform_keys {|key| ... } -> new_hash + * hash.transform_keys(hash2) -> new_hash + * hash.transform_keys(hash2) {|other_key| ...} -> new_hash + * hash.transform_keys -> new_enumerator + * + * Returns a new \Hash object; each entry has: + * * A key provided by the block. + * * The value from +self+. + * + * An optional hash argument can be provided to map keys to new keys. + * Any key not given will be mapped using the provided block, + * or remain the same if no block is given. + * + * Transform keys: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.transform_keys {|key| key.to_s } + * h1 # => {"foo"=>0, "bar"=>1, "baz"=>2} + * + * h.transform_keys(foo: :bar, bar: :foo) + * #=> {bar: 0, foo: 1, baz: 2} + * + * h.transform_keys(foo: :hello, &:to_s) + * #=> {:hello=>0, "bar"=>1, "baz"=>2} + * + * Overwrites values for duplicate keys: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.transform_keys {|key| :bat } + * h1 # => {:bat=>2} + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.transform_keys # => #0, :bar=>1, :baz=>2}:transform_keys> + * h1 = e.each { |key| key.to_s } + * h1 # => {"foo"=>0, "bar"=>1, "baz"=>2} */ static VALUE -rb_hash_transform_keys(VALUE hash) +rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash) { VALUE result; + struct transform_keys_args transarg = {0}; - RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); + argc = rb_check_arity(argc, 0, 1); + if (argc > 0) { + transarg.trans = to_hash(argv[0]); + transarg.block_given = rb_block_given_p(); + } + else { + RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); + } result = rb_hash_new(); if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, transform_keys_i, result); + if (transarg.trans) { + transarg.result = result; + rb_hash_foreach(hash, transform_keys_hash_i, (VALUE)&transarg); + } + else { + rb_hash_foreach(hash, transform_keys_i, result); + } } return result; } -static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash); +static int flatten_i(VALUE key, VALUE val, VALUE ary); /* * call-seq: - * hsh.transform_keys! {|key| block } -> hsh - * hsh.transform_keys! -> an_enumerator + * hash.transform_keys! {|key| ... } -> self + * hash.transform_keys!(hash2) -> self + * hash.transform_keys!(hash2) {|other_key| ...} -> self + * hash.transform_keys! -> new_enumerator * - * Invokes the given block once for each key in hsh, replacing it - * with the new key returned by the block, and then returns hsh. - * This method does not change the values. - * - * h = { a: 1, b: 2, c: 3 } - * h.transform_keys! {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 } - * h.transform_keys!(&:to_sym) #=> { a: 1, b: 2, c: 3 } - * h.transform_keys!.with_index {|k, i| "#{k}.#{i}" } - * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 } - * - * If no block is given, an enumerator is returned instead. + * Same as Hash#transform_keys but modifies the receiver in place + * instead of returning a new hash. */ static VALUE -rb_hash_transform_keys_bang(VALUE hash) +rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash) { - RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); + VALUE trans = 0; + int block_given = 0; + + argc = rb_check_arity(argc, 0, 1); + if (argc > 0) { + trans = to_hash(argv[0]); + block_given = rb_block_given_p(); + } + else { + RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); + } rb_hash_modify_check(hash); if (!RHASH_TABLE_EMPTY_P(hash)) { long i; - VALUE pairs = rb_hash_flatten(0, NULL, hash); - rb_hash_clear(hash); + VALUE new_keys = hash_alloc(0); + VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2); + rb_hash_foreach(hash, flatten_i, pairs); for (i = 0; i < RARRAY_LEN(pairs); i += 2) { - VALUE key = RARRAY_AREF(pairs, i), new_key = rb_yield(key), - val = RARRAY_AREF(pairs, i+1); + VALUE key = RARRAY_AREF(pairs, i), new_key, val; + + if (!trans) { + new_key = rb_yield(key); + } + else if ((new_key = rb_hash_lookup2(trans, key, Qundef)) != Qundef) { + /* use the transformed key */ + } + else if (block_given) { + new_key = rb_yield(key); + } + else { + new_key = key; + } + val = RARRAY_AREF(pairs, i+1); + if (!hash_stlike_lookup(new_keys, key, NULL)) { + rb_hash_stlike_delete(hash, &key, NULL); + } rb_hash_aset(hash, new_key, val); + rb_hash_aset(new_keys, new_key, Qnil); } + rb_ary_clear(pairs); + rb_hash_clear(new_keys); } return hash; } @@ -3178,26 +3316,30 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg { VALUE new_value = rb_yield((VALUE)*value); VALUE hash = (VALUE)argp; + rb_hash_modify(hash); RB_OBJ_WRITE(hash, value, new_value); return ST_CONTINUE; } /* * call-seq: - * hsh.transform_values {|value| block } -> new_hash - * hsh.transform_values -> an_enumerator - * - * Returns a new hash with the results of running the block once for - * every value. - * This method does not change the keys. - * - * h = { a: 1, b: 2, c: 3 } - * h.transform_values {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 } - * h.transform_values(&:to_s) #=> { a: "1", b: "2", c: "3" } - * h.transform_values.with_index {|v, i| "#{v}.#{i}" } - * #=> { a: "1.0", b: "2.1", c: "3.2" } - * - * If no block is given, an enumerator is returned instead. + * hash.transform_values {|value| ... } -> new_hash + * hash.transform_values -> new_enumerator + * + * Returns a new \Hash object; each entry has: + * * A key from +self+. + * * A value provided by the block. + * + * Transform values: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.transform_values {|value| value * 100} + * h1 # => {:foo=>0, :bar=>100, :baz=>200} + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.transform_values # => #0, :bar=>1, :baz=>2}:transform_values> + * h1 = e.each { |value| value * 100} + * h1 # => {:foo=>0, :bar=>100, :baz=>200} */ static VALUE rb_hash_transform_values(VALUE hash) @@ -3205,7 +3347,8 @@ rb_hash_transform_values(VALUE hash) VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = hash_dup(hash, rb_cHash, 0); + result = hash_dup_with_compare_by_id(hash); + SET_DEFAULT(result, Qnil); if (!RHASH_EMPTY_P(hash)) { rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, result); @@ -3216,20 +3359,18 @@ rb_hash_transform_values(VALUE hash) /* * call-seq: - * hsh.transform_values! {|value| block } -> hsh - * hsh.transform_values! -> an_enumerator - * - * Invokes the given block once for each value in hsh, replacing it - * with the new value returned by the block, and then returns hsh. - * This method does not change the keys. - * - * h = { a: 1, b: 2, c: 3 } - * h.transform_values! {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 } - * h.transform_values!(&:to_s) #=> { a: "2", b: "5", c: "10" } - * h.transform_values!.with_index {|v, i| "#{v}.#{i}" } - * #=> { a: "2.0", b: "5.1", c: "10.2" } - * - * If no block is given, an enumerator is returned instead. + * hash.transform_values! {|value| ... } -> self + * hash.transform_values! -> new_enumerator + * + * Returns +self+, whose keys are unchanged, and whose values are determined by the given block. + * h = {foo: 0, bar: 1, baz: 2} + * h.transform_values! {|value| value * 100} # => {:foo=>0, :bar=>100, :baz=>200} + * + * Returns a new \Enumerator if no block given: + * h = {foo: 0, bar: 1, baz: 2} + * e = h.transform_values! # => #0, :bar=>100, :baz=>200}:transform_values!> + * h1 = e.each {|value| value * 100} + * h1 # => {:foo=>0, :bar=>100, :baz=>200} */ static VALUE rb_hash_transform_values_bang(VALUE hash) @@ -3253,13 +3394,12 @@ to_a_i(VALUE key, VALUE value, VALUE ary) /* * call-seq: - * hsh.to_a -> array + * hash.to_a -> new_array * - * Converts hsh to a nested array of [ key, - * value ] arrays. - * - * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } - * h.to_a #=> [["c", 300], ["a", 100], ["d", 400]] + * Returns a new \Array of 2-element \Array objects; + * each nested \Array contains a key-value pair from +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]] */ static VALUE @@ -3307,14 +3447,14 @@ inspect_hash(VALUE hash, VALUE dummy, int recur) } /* - * call-seq: - * hsh.to_s -> string - * hsh.inspect -> string + * call-seq: + * hash.inspect -> new_string * - * Return the contents of this hash as a string. + * Returns a new \String containing the hash entries: + * h = {foo: 0, bar: 1, baz: 2} + * h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}" * - * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } - * h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}" + * Hash#to_s is an alias for Hash#inspect. */ static VALUE @@ -3326,12 +3466,11 @@ rb_hash_inspect(VALUE hash) } /* - * call-seq: - * hsh.to_hash => hsh + * call-seq: + * hash.to_hash -> self * - * Returns +self+. + * Returns +self+. */ - static VALUE rb_hash_to_hash(VALUE hash) { @@ -3373,14 +3512,21 @@ rb_hash_to_h_block(VALUE hash) /* * call-seq: - * hsh.to_h -> hsh or new_hash - * hsh.to_h {|key, value| block } -> new_hash + * hash.to_h -> self or new_hash + * hash.to_h {|key, value| ... } -> new_hash * - * Returns +self+. If called on a subclass of Hash, converts - * the receiver to a Hash object. + * For an instance of \Hash, returns +self+. * - * If a block is given, the results of the block on each pair of - * the receiver will be used as pairs. + * For a subclass of \Hash, returns a new \Hash + * containing the content of +self+. + * + * When a block is given, returns a new \Hash object + * whose content is based on the block; + * the block should return a 2-element \Array object + * specifying the key-value pair to be included in the returned \Array: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.to_h {|key, value| [value, key] } + * h1 # => {0=>:foo, 1=>:bar, 2=>:baz} */ static VALUE @@ -3405,14 +3551,11 @@ keys_i(VALUE key, VALUE value, VALUE ary) /* * call-seq: - * hsh.keys -> array - * - * Returns a new array populated with the keys from this hash. See also - * Hash#values. - * - * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 } - * h.keys #=> ["a", "b", "c", "d"] + * hash.keys -> new_array * + * Returns a new \Array containing all keys in +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.keys # => [:foo, :bar, :baz] */ MJIT_FUNC_EXPORTED VALUE @@ -3452,14 +3595,11 @@ values_i(VALUE key, VALUE value, VALUE ary) /* * call-seq: - * hsh.values -> array - * - * Returns a new array populated with the values from hsh. See - * also Hash#keys. - * - * h = { "a" => 100, "b" => 200, "c" => 300 } - * h.values #=> [100, 200, 300] + * hash.values -> new_array * + * Returns a new \Array containing all values in +self+: + * h = {foo: 0, bar: 1, baz: 2} + * h.values # => [0, 1, 2] */ VALUE @@ -3487,6 +3627,7 @@ rb_hash_values(VALUE hash) } rb_ary_set_len(values, size); } + else { rb_hash_foreach(hash, values_i, values); } @@ -3496,32 +3637,20 @@ rb_hash_values(VALUE hash) /* * call-seq: - * hsh.has_key?(key) -> true or false - * hsh.include?(key) -> true or false - * hsh.key?(key) -> true or false - * hsh.member?(key) -> true or false - * - * Returns true if the given key is present in hsh. - * - * h = { "a" => 100, "b" => 200 } - * h.has_key?("a") #=> true - * h.has_key?("z") #=> false - * - * Note that #include? and #member? do not test member - * equality using == as do other Enumerables. + * hash.include?(key) -> true or false + * hash.has_key?(key) -> true or false + * hash.key?(key) -> true or false + * hash.member?(key) -> true or false + + * Methods #has_key?, #key?, and #member? are aliases for \#include?. * - * See also Enumerable#include? + * Returns +true+ if +key+ is a key in +self+, otherwise +false+. */ MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key) { - if (hash_stlike_lookup(hash, key, NULL)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(hash_stlike_lookup(hash, key, NULL)); } static int @@ -3538,15 +3667,12 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) /* * call-seq: - * hsh.has_value?(value) -> true or false - * hsh.value?(value) -> true or false + * hash.has_value?(value) -> true or false + * hash.value?(value) -> true or false * - * Returns true if the given value is present for some key - * in hsh. + * Method #value? is an alias for \#has_value?. * - * h = { "a" => 100, "b" => 200 } - * h.value?(100) #=> true - * h.value?(999) #=> false + * Returns +true+ if +value+ is a value in +self+, otherwise +false+. */ static VALUE @@ -3643,26 +3769,21 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) /* * call-seq: - * hsh == other_hash -> true or false - * - * Equality---Two hashes are equal if they each contain the same number - * of keys and if each key-value pair is equal to (according to - * Object#==) the corresponding elements in the other hash. + * hash == object -> true or false * - * h1 = { "a" => 1, "c" => 2 } - * h2 = { 7 => 35, "c" => 2, "a" => 1 } - * h3 = { "a" => 1, "c" => 2, 7 => 35 } - * h4 = { "a" => 1, "d" => 2, "f" => 35 } - * h1 == h2 #=> false - * h2 == h3 #=> true - * h3 == h4 #=> false + * Returns +true+ if all of the following are true: + * * +object+ is a \Hash object. + * * +hash+ and +object+ have the same keys (regardless of order). + * * For each key +key+, hash[key] == object[key]. * - * The orders of each hashes are not compared. - * - * h1 = { "a" => 1, "c" => 2 } - * h2 = { "c" => 2, "a" => 1 } - * h1 == h2 #=> true + * Otherwise, returns +false+. * + * Equal: + * h1 = {foo: 0, bar: 1, baz: 2} + * h2 = {foo: 0, bar: 1, baz: 2} + * h1 == h2 # => true + * h3 = {baz: 2, bar: 1, foo: 0} + * h1 == h3 # => true */ static VALUE @@ -3673,11 +3794,21 @@ rb_hash_equal(VALUE hash1, VALUE hash2) /* * call-seq: - * hash.eql?(other) -> true or false + * hash.eql? object -> true or false + * + * Returns +true+ if all of the following are true: + * * +object+ is a \Hash object. + * * +hash+ and +object+ have the same keys (regardless of order). + * * For each key +key+, h[key] eql? object[key]. * - * Returns true if hash and other are - * both hashes with the same content. - * The orders of each hashes are not compared. + * Otherwise, returns +false+. + * + * Equal: + * h1 = {foo: 0, bar: 1, baz: 2} + * h2 = {foo: 0, bar: 1, baz: 2} + * h1.eql? h2 # => true + * h3 = {baz: 2, bar: 1, foo: 0} + * h1.eql? h3 # => true */ static VALUE @@ -3700,12 +3831,16 @@ hash_i(VALUE key, VALUE val, VALUE arg) /* * call-seq: - * hsh.hash -> integer + * hash.hash -> an_integer * - * Compute a hash-code for this hash. Two hashes with the same content - * will have the same hash code (and will compare using eql?). + * Returns the \Integer hash-code for the hash. * - * See also Object#hash. + * Two \Hash objects have the same hash-code if their content is the same + * (regardless or order): + * h1 = {foo: 0, bar: 1, baz: 2} + * h2 = {baz: 2, bar: 1, foo: 0} + * h2.hash == h1.hash # => true + * h2.eql? h1 # => true */ static VALUE @@ -3730,32 +3865,17 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) /* * call-seq: - * hsh.invert -> new_hash - * - * Returns a new hash created by using hsh's values as keys, and - * the keys as values. - * If a key with the same value already exists in the hsh, then - * the last one defined will be used, the earlier value(s) will be discarded. - * - * h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 } - * h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"} - * - * If there is no key with the same value, Hash#invert is involutive. + * hash.invert -> new_hash * - * h = { a: 1, b: 3, c: 4 } - * h.invert.invert == h #=> true - * - * The condition, no key with the same value, can be tested by comparing - * the size of inverted hash. - * - * # no key with the same value - * h = { a: 1, b: 3, c: 4 } - * h.size == h.invert.size #=> true - * - * # two (or more) keys has the same value - * h = { a: 1, b: 3, c: 1 } - * h.size == h.invert.size #=> false + * Returns a new \Hash object with the each key-value pair inverted: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = h.invert + * h1 # => {0=>:foo, 1=>:bar, 2=>:baz} * + * Overwrites any repeated new keys: + * (see {Entry Order}[#class-Hash-label-Entry+Order]): + * h = {foo: 0, bar: 0, baz: 0} + * h.invert # => {0=>:baz} */ static VALUE @@ -3770,14 +3890,6 @@ rb_hash_invert(VALUE hash) static int rb_hash_update_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing) { - if (existing) { - arg->old_value = *value; - arg->new_value = arg->arg; - } - else { - arg->new_key = *key; - arg->new_value = arg->arg; - } *value = arg->arg; return ST_CONTINUE; } @@ -3794,16 +3906,11 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) static int rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing) { - VALUE newvalue = (VALUE)arg->arg; + st_data_t newvalue = arg->arg; if (existing) { - newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue); - arg->old_value = *value; - } - else { - arg->new_key = *key; + newvalue = (st_data_t)rb_yield_values(3, (VALUE)*key, (VALUE)*value, (VALUE)newvalue); } - arg->new_value = newvalue; *value = newvalue; return ST_CONTINUE; } @@ -3819,45 +3926,52 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) /* * call-seq: - * hsh.merge!(other_hash1, other_hash2, ...) -> hsh - * hsh.update(other_hash1, other_hash2, ...) -> hsh - * hsh.merge!(other_hash1, other_hash2, ...) {|key, oldval, newval| block} - * -> hsh - * hsh.update(other_hash1, other_hash2, ...) {|key, oldval, newval| block} - * -> hsh - * - * Adds the contents of the given hashes to the receiver. - * - * If no block is given, entries with duplicate keys are overwritten - * with the values from each +other_hash+ successively, - * otherwise the value for each duplicate key is determined by - * calling the block with the key, its value in the receiver and - * its value in each +other_hash+. - * - * h1 = { "a" => 100, "b" => 200 } - * h1.merge! #=> {"a"=>100, "b"=>200} - * h1 #=> {"a"=>100, "b"=>200} - * - * h1 = { "a" => 100, "b" => 200 } - * h2 = { "b" => 246, "c" => 300 } - * h1.merge!(h2) #=> {"a"=>100, "b"=>246, "c"=>300} - * h1 #=> {"a"=>100, "b"=>246, "c"=>300} - * - * h1 = { "a" => 100, "b" => 200 } - * h2 = { "b" => 246, "c" => 300 } - * h3 = { "b" => 357, "d" => 400 } - * h1.merge!(h2, h3) - * #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400} - * h1 #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400} - * - * h1 = { "a" => 100, "b" => 200 } - * h2 = { "b" => 246, "c" => 300 } - * h3 = { "b" => 357, "d" => 400 } - * h1.merge!(h2, h3) {|key, v1, v2| v1 } - * #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400} - * h1 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400} - * - * Hash#update is an alias for Hash#merge!. + * hash.merge! -> self + * hash.merge!(*other_hashes) -> self + * hash.merge!(*other_hashes) { |key, old_value, new_value| ... } -> self + * + * Merges each of +other_hashes+ into +self+; returns +self+. + * + * Each argument in +other_hashes+ must be a \Hash. + * + * \Method #update is an alias for \#merge!. + * + * With arguments and no block: + * * Returns +self+, after the given hashes are merged into it. + * * The given hashes are merged left to right. + * * Each new entry is added at the end. + * * Each duplicate-key entry's value overwrites the previous value. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = {bat: 3, bar: 4} + * h2 = {bam: 5, bat:6} + * h.merge!(h1, h2) # => {:foo=>0, :bar=>4, :baz=>2, :bat=>6, :bam=>5} + * + * With arguments and a block: + * * Returns +self+, after the given hashes are merged. + * * The given hashes are merged left to right. + * * Each new-key entry is added at the end. + * * For each duplicate key: + * * Calls the block with the key and the old and new values. + * * The block's return value becomes the new value for the entry. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = {bat: 3, bar: 4} + * h2 = {bam: 5, bat:6} + * h3 = h.merge!(h1, h2) { |key, old_value, new_value| old_value + new_value } + * h3 # => {:foo=>0, :bar=>5, :baz=>2, :bat=>9, :bam=>5} + * + * With no arguments: + * * Returns +self+, unmodified. + * * The block, if given, is ignored. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h.merge # => {:foo=>0, :bar=>1, :baz=>2} + * h1 = h.merge! { |key, old_value, new_value| raise 'Cannot happen' } + * h1 # => {:foo=>0, :bar=>1, :baz=>2} */ static VALUE @@ -3868,13 +3982,13 @@ rb_hash_update(int argc, VALUE *argv, VALUE self) rb_hash_modify(self); for (i = 0; i < argc; i++){ - VALUE hash = to_hash(argv[i]); - if (block_given) { - rb_hash_foreach(hash, rb_hash_update_block_i, self); - } - else { - rb_hash_foreach(hash, rb_hash_update_i, self); - } + VALUE hash = to_hash(argv[i]); + if (block_given) { + rb_hash_foreach(hash, rb_hash_update_block_i, self); + } + else { + rb_hash_foreach(hash, rb_hash_update_i, self); + } } return self; } @@ -3893,12 +4007,7 @@ rb_hash_update_func_callback(st_data_t *key, st_data_t *value, struct update_arg if (existing) { newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue); - arg->old_value = *value; - } - else { - arg->new_key = *key; } - arg->new_value = newvalue; *value = newvalue; return ST_CONTINUE; } @@ -3935,39 +4044,59 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func) /* * call-seq: - * hsh.merge(other_hash1, other_hash2, ...) -> new_hash - * hsh.merge(other_hash1, other_hash2, ...) {|key, oldval, newval| block} - * -> new_hash - * - * Returns a new hash that combines the contents of the receiver and - * the contents of the given hashes. - * - * If no block is given, entries with duplicate keys are overwritten - * with the values from each +other_hash+ successively, - * otherwise the value for each duplicate key is determined by - * calling the block with the key, its value in the receiver and - * its value in each +other_hash+. - * - * When called without any argument, returns a copy of the receiver. - * - * h1 = { "a" => 100, "b" => 200 } - * h2 = { "b" => 246, "c" => 300 } - * h3 = { "b" => 357, "d" => 400 } - * h1.merge #=> {"a"=>100, "b"=>200} - * h1.merge(h2) #=> {"a"=>100, "b"=>246, "c"=>300} - * h1.merge(h2, h3) #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400} - * h1.merge(h2) {|key, oldval, newval| newval - oldval} - * #=> {"a"=>100, "b"=>46, "c"=>300} - * h1.merge(h2, h3) {|key, oldval, newval| newval - oldval} - * #=> {"a"=>100, "b"=>311, "c"=>300, "d"=>400} - * h1 #=> {"a"=>100, "b"=>200} - * + * hash.merge -> copy_of_self + * hash.merge(*other_hashes) -> new_hash + * hash.merge(*other_hashes) { |key, old_value, new_value| ... } -> new_hash + * + * Returns the new \Hash formed by merging each of +other_hashes+ + * into a copy of +self+. + * + * Each argument in +other_hashes+ must be a \Hash. + * + * --- + * + * With arguments and no block: + * * Returns the new \Hash object formed by merging each successive + * \Hash in +other_hashes+ into +self+. + * * Each new-key entry is added at the end. + * * Each duplicate-key entry's value overwrites the previous value. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = {bat: 3, bar: 4} + * h2 = {bam: 5, bat:6} + * h.merge(h1, h2) # => {:foo=>0, :bar=>4, :baz=>2, :bat=>6, :bam=>5} + * + * With arguments and a block: + * * Returns a new \Hash object that is the merge of +self+ and each given hash. + * * The given hashes are merged left to right. + * * Each new-key entry is added at the end. + * * For each duplicate key: + * * Calls the block with the key and the old and new values. + * * The block's return value becomes the new value for the entry. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h1 = {bat: 3, bar: 4} + * h2 = {bam: 5, bat:6} + * h3 = h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value } + * h3 # => {:foo=>0, :bar=>5, :baz=>2, :bat=>9, :bam=>5} + * + * With no arguments: + * * Returns a copy of +self+. + * * The block, if given, is ignored. + * + * Example: + * h = {foo: 0, bar: 1, baz: 2} + * h.merge # => {:foo=>0, :bar=>1, :baz=>2} + * h1 = h.merge { |key, old_value, new_value| raise 'Cannot happen' } + * h1 # => {:foo=>0, :bar=>1, :baz=>2} */ static VALUE rb_hash_merge(int argc, VALUE *argv, VALUE self) { - return rb_hash_update(argc, argv, rb_hash_dup(self)); + return rb_hash_update(argc, argv, copy_compare_by_id(rb_hash_dup(self), self)); } static int @@ -4011,19 +4140,16 @@ assoc_i(VALUE key, VALUE val, VALUE arg) /* * call-seq: - * hash.assoc(obj) -> an_array or nil + * hash.assoc(key) -> new_array or nil * - * Searches through the hash comparing _obj_ with the key using ==. - * Returns the key-value pair (two elements array) or +nil+ - * if no match is found. See Array#assoc. + * If the given +key+ is found, returns a 2-element \Array containing that key and its value: + * h = {foo: 0, bar: 1, baz: 2} + * h.assoc(:bar) # => [:bar, 1] * - * h = {"colors" => ["red", "blue", "green"], - * "letters" => ["a", "b", "c" ]} - * h.assoc("letters") #=> ["letters", ["a", "b", "c"]] - * h.assoc("foo") #=> nil + * Returns +nil+ if key +key+ is not found. */ -VALUE +static VALUE rb_hash_assoc(VALUE hash, VALUE key) { st_table *table; @@ -4073,18 +4199,18 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) /* * call-seq: - * hash.rassoc(obj) -> an_array or nil + * hash.rassoc(value) -> new_array or nil * - * Searches through the hash comparing _obj_ with the value using ==. - * Returns the first key-value pair (two-element array) that matches. See - * also Array#rassoc. + * Returns a new 2-element \Array consisting of the key and value + * of the first-found entry whose value is == to value + * (see {Entry Order}[#class-Hash-label-Entry+Order]): + * h = {foo: 0, bar: 1, baz: 1} + * h.rassoc(1) # => [:bar, 1] * - * a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"} - * a.rassoc("two") #=> [2, "two"] - * a.rassoc("four") #=> nil + * Returns +nil+ if no such value found. */ -VALUE +static VALUE rb_hash_rassoc(VALUE hash, VALUE obj) { VALUE args[2]; @@ -4109,18 +4235,33 @@ flatten_i(VALUE key, VALUE val, VALUE ary) /* * call-seq: - * hash.flatten -> an_array - * hash.flatten(level) -> an_array - * - * Returns a new array that is a one-dimensional flattening of this - * hash. That is, for every key or value that is an array, extract - * its elements into the new array. Unlike Array#flatten, this - * method does not flatten recursively by default. The optional - * level argument determines the level of recursion to flatten. - * - * a = {1=> "one", 2 => [2,"two"], 3 => "three"} - * a.flatten # => [1, "one", 2, [2, "two"], 3, "three"] - * a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"] + * hash.flatten -> new_array + * hash.flatten(level) -> new_array + * + * Returns a new \Array object that is a 1-dimensional flattening of +self+. + * + * --- + * + * By default, nested Arrays are not flattened: + * h = {foo: 0, bar: [:bat, 3], baz: 2} + * h.flatten # => [:foo, 0, :bar, [:bat, 3], :baz, 2] + * + * Takes the depth of recursive flattening from \Integer argument +level+: + * h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]} + * h.flatten(1) # => [:foo, 0, :bar, [:bat, [:baz, [:bat]]]] + * h.flatten(2) # => [:foo, 0, :bar, :bat, [:baz, [:bat]]] + * h.flatten(3) # => [:foo, 0, :bar, :bat, :baz, [:bat]] + * h.flatten(4) # => [:foo, 0, :bar, :bat, :baz, :bat] + * + * When +level+ is negative, flattens all nested Arrays: + * h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]} + * h.flatten(-1) # => [:foo, 0, :bar, :bat, :baz, :bat] + * h.flatten(-2) # => [:foo, 0, :bar, :bat, :baz, :bat] + * + * When +level+ is zero, returns the equivalent of #to_a : + * h = {foo: 0, bar: [:bat, 3], baz: 2} + * h.flatten(0) # => [[:foo, 0], [:bar, [:bat, 3]], [:baz, 2]] + * h.flatten(0) == h.to_a # => true */ static VALUE @@ -4176,14 +4317,12 @@ set_if_not_nil(VALUE key, VALUE value, VALUE hash) /* * call-seq: - * hsh.compact -> new_hash - * - * Returns a new hash with the nil values/key pairs removed - * - * h = { a: 1, b: false, c: nil } - * h.compact #=> { a: 1, b: false } - * h #=> { a: 1, b: false, c: nil } + * hash.compact -> new_hash * + * Returns a copy of +self+ with all +nil+-valued entries removed: + * h = {foo: 0, bar: nil, baz: 2, bat: nil} + * h1 = h.compact + * h1 # => {:foo=>0, :baz=>2} */ static VALUE @@ -4198,14 +4337,13 @@ rb_hash_compact(VALUE hash) /* * call-seq: - * hsh.compact! -> hsh or nil + * hash.compact! -> self or nil * - * Removes all nil values from the hash. - * Returns nil if no changes were made, otherwise returns the hash. - * - * h = { a: 1, b: false, c: nil } - * h.compact! #=> { a: 1, b: false } + * Returns +self+ with all its +nil+-valued entries removed (in place): + * h = {foo: 0, bar: nil, baz: 2, bat: nil} + * h.compact! # => {:foo=>0, :baz=>2} * + * Returns +nil+ if no entries were removed. */ static VALUE @@ -4226,21 +4364,33 @@ static st_table *rb_init_identtable_with_size(st_index_t size); /* * call-seq: - * hsh.compare_by_identity -> hsh - * - * Makes hsh compare its keys by their identity, i.e. it - * will consider exact same objects as same keys. - * - * h1 = { "a" => 100, "b" => 200, :c => "c" } - * h1["a"] #=> 100 - * h1.compare_by_identity - * h1.compare_by_identity? #=> true - * h1["a".dup] #=> nil # different objects. - * h1[:c] #=> "c" # same symbols are all same. - * + * hash.compare_by_identity -> self + * + * Sets +self+ to consider only identity in comparing keys; + * two keys are considered the same only if they are the same object; + * returns +self+. + * + * By default, these two object are considered to be the same key, + * so +s1+ will overwrite +s0+: + * s0 = 'x' + * s1 = 'x' + * h = {} + * h.compare_by_identity? # => false + * h[s0] = 0 + * h[s1] = 1 + * h # => {"x"=>1} + * + * After calling \#compare_by_identity, the keys are considered to be different, + * and therefore do not overwrite each other: + * h = {} + * h.compare_by_identity # => {} + * h.compare_by_identity? # => true + * h[s0] = 0 + * h[s1] = 1 + * h # => {"x"=>0, "x"=>1} */ -static VALUE +VALUE rb_hash_compare_by_id(VALUE hash) { VALUE tmp; @@ -4259,29 +4409,21 @@ rb_hash_compare_by_id(VALUE hash) st_free_table(RHASH_ST_TABLE(hash)); RHASH_ST_TABLE_SET(hash, identtable); RHASH_ST_CLEAR(tmp); - rb_gc_force_recycle(tmp); return hash; } /* * call-seq: - * hsh.compare_by_identity? -> true or false - * - * Returns true if hsh will compare its keys by - * their identity. Also see Hash#compare_by_identity. + * hash.compare_by_identity? -> true or false * + * Returns +true+ if #compare_by_identity has been called, +false+ otherwise. */ MJIT_FUNC_EXPORTED VALUE rb_hash_compare_by_id_p(VALUE hash) { - if (RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash); } VALUE @@ -4292,6 +4434,14 @@ rb_ident_hash_new(void) return hash; } +VALUE +rb_ident_hash_new_with_size(st_index_t size) +{ + VALUE hash = rb_hash_new(); + RHASH_ST_TABLE_SET(hash, st_init_table_with_size(&identhash, size)); + return hash; +} + st_table * rb_init_identtable(void) { @@ -4339,10 +4489,31 @@ any_p_i_pattern(VALUE key, VALUE value, VALUE arg) /* * call-seq: - * hsh.any? [{ |(key, value)| block }] -> true or false - * hsh.any?(pattern) -> true or false - * - * See also Enumerable#any? + * hash.any? -> true or false + * hash.any?(object) -> true or false + * hash.any? {|key, value| ... } -> true or false + * + * Returns +true+ if any element satisfies a given criterion; + * +false+ otherwise. + * + * With no argument and no block, + * returns +true+ if +self+ is non-empty; +false+ if empty. + * + * With argument +object+ and no block, + * returns +true+ if for any key +key+ + * h.assoc(key) == object: + * h = {foo: 0, bar: 1, baz: 2} + * h.any?([:bar, 1]) # => true + * h.any?([:bar, 0]) # => false + * h.any?([:baz, 1]) # => false + * + * With no argument and a block, + * calls the block with each key-value pair; + * returns +true+ if the block returns any truthy value, + * +false+ otherwise: + * h = {foo: 0, bar: 1, baz: 2} + * h.any? {|key, value| value < 3 } # => true + * h.any? {|key, value| value > 3 } # => false */ static VALUE @@ -4366,7 +4537,7 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash) /* yields pairs, never false */ return Qtrue; } - if (rb_block_arity() > 1) + if (rb_block_pair_yield_optimizable()) rb_hash_foreach(hash, any_p_i_fast, (VALUE)args); else rb_hash_foreach(hash, any_p_i, (VALUE)args); @@ -4375,22 +4546,32 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash) } /* - * call-seq: - * hsh.dig(key, ...) -> object - * - * Extracts the nested value specified by the sequence of key - * objects by calling +dig+ at each step, returning +nil+ if any - * intermediate step is +nil+. - * - * h = { foo: {bar: {baz: 1}}} - * - * h.dig(:foo, :bar, :baz) #=> 1 - * h.dig(:foo, :zot, :xyz) #=> nil - * - * g = { foo: [10, 11, 12] } - * g.dig(:foo, 1) #=> 11 - * g.dig(:foo, 1, 0) #=> TypeError: Integer does not have #dig method - * g.dig(:foo, :bar) #=> TypeError: no implicit conversion of Symbol into Integer + * call-seq: + * hash.dig(key, *identifiers) -> object + * + * Finds and returns the object in nested objects + * that is specified by +key+ and +identifiers+. + * The nested objects may be instances of various classes. + * See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. + * + * Nested Hashes: + * h = {foo: {bar: {baz: 2}}} + * h.dig(:foo) # => {:bar=>{:baz=>2}} + * h.dig(:foo, :bar) # => {:baz=>2} + * h.dig(:foo, :bar, :baz) # => 2 + * h.dig(:foo, :bar, :BAZ) # => nil + * + * Nested Hashes and Arrays: + * h = {foo: {bar: [:a, :b, :c]}} + * h.dig(:foo, :bar, 2) # => :c + * + * This method will use the {default values}[#class-Hash-label-Default+Values] + * for keys that are not present: + * h = {foo: {bar: [:a, :b, :c]}} + * h.dig(:hello) # => nil + * h.default_proc = -> (hash, _key) { hash } + * h.dig(:hello, :world) # => h + * h.dig(:hello, :world, :foo, :bar, 2) # => :c */ static VALUE @@ -4424,17 +4605,15 @@ hash_le(VALUE hash1, VALUE hash2) } /* - * call-seq: - * hash <= other -> true or false - * - * Returns true if hash is subset of - * other or equals to other. - * - * h1 = {a:1, b:2} - * h2 = {a:1, b:2, c:3} - * h1 <= h2 #=> true - * h2 <= h1 #=> false - * h1 <= h1 #=> true + * call-seq: + * hash <= other_hash -> true or false + * + * Returns +true+ if +hash+ is a subset of +other_hash+, +false+ otherwise: + * h1 = {foo: 0, bar: 1} + * h2 = {foo: 0, bar: 1, baz: 2} + * h1 <= h2 # => true + * h2 <= h1 # => false + * h1 <= h1 # => true */ static VALUE rb_hash_le(VALUE hash, VALUE other) @@ -4445,17 +4624,15 @@ rb_hash_le(VALUE hash, VALUE other) } /* - * call-seq: - * hash < other -> true or false - * - * Returns true if hash is subset of - * other. - * - * h1 = {a:1, b:2} - * h2 = {a:1, b:2, c:3} - * h1 < h2 #=> true - * h2 < h1 #=> false - * h1 < h1 #=> false + * call-seq: + * hash < other_hash -> true or false + * + * Returns +true+ if +hash+ is a proper subset of +other_hash+, +false+ otherwise: + * h1 = {foo: 0, bar: 1} + * h2 = {foo: 0, bar: 1, baz: 2} + * h1 < h2 # => true + * h2 < h1 # => false + * h1 < h1 # => false */ static VALUE rb_hash_lt(VALUE hash, VALUE other) @@ -4466,17 +4643,15 @@ rb_hash_lt(VALUE hash, VALUE other) } /* - * call-seq: - * hash >= other -> true or false - * - * Returns true if other is subset of - * hash or equals to hash. - * - * h1 = {a:1, b:2} - * h2 = {a:1, b:2, c:3} - * h1 >= h2 #=> false - * h2 >= h1 #=> true - * h1 >= h1 #=> true + * call-seq: + * hash >= other_hash -> true or false + * + * Returns +true+ if +hash+ is a superset of +other_hash+, +false+ otherwise: + * h1 = {foo: 0, bar: 1, baz: 2} + * h2 = {foo: 0, bar: 1} + * h1 >= h2 # => true + * h2 >= h1 # => false + * h1 >= h1 # => true */ static VALUE rb_hash_ge(VALUE hash, VALUE other) @@ -4487,17 +4662,15 @@ rb_hash_ge(VALUE hash, VALUE other) } /* - * call-seq: - * hash > other -> true or false - * - * Returns true if other is subset of - * hash. - * - * h1 = {a:1, b:2} - * h2 = {a:1, b:2, c:3} - * h1 > h2 #=> false - * h2 > h1 #=> true - * h1 > h1 #=> false + * call-seq: + * hash > other_hash -> true or false + * + * Returns +true+ if +hash+ is a proper superset of +other_hash+, +false+ otherwise: + * h1 = {foo: 0, bar: 1, baz: 2} + * h2 = {foo: 0, bar: 1} + * h1 > h2 # => true + * h2 > h1 # => false + * h1 > h1 # => false */ static VALUE rb_hash_gt(VALUE hash, VALUE other) @@ -4515,22 +4688,21 @@ hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash)) } /* - * call-seq: - * hash.to_proc -> proc - * - * Returns a Proc which maps keys to values. - * - * h = {a:1, b:2} - * hp = h.to_proc - * hp.call(:a) #=> 1 - * hp.call(:b) #=> 2 - * hp.call(:c) #=> nil - * [:a, :b, :c].map(&h) #=> [1, 2, nil] + * call-seq: + * hash.to_proc -> proc + * + * Returns a \Proc object that maps a key to its value: + * h = {foo: 0, bar: 1, baz: 2} + * proc = h.to_proc + * proc.class # => Proc + * proc.call(:foo) # => 0 + * proc.call(:bar) # => 1 + * proc.call(:nosuch) # => nil */ static VALUE rb_hash_to_proc(VALUE hash) { - return rb_func_proc_new(hash_proc_call, hash); + return rb_func_lambda_new(hash_proc_call, hash, 1, 1); } static VALUE @@ -4630,22 +4802,7 @@ static char **my_environ; #undef environ #define environ my_environ #undef getenv -static char *(*w32_getenv)(const char*); -static char * -w32_getenv_unknown(const char *name) -{ - char *(*func)(const char*); - if (rb_locale_encindex() == rb_ascii8bit_encindex()) { - func = rb_w32_getenv; - } - else { - func = rb_w32_ugetenv; - } - /* atomic assignment in flat memory model */ - return (w32_getenv = func)(name); -} -static char *(*w32_getenv)(const char*) = w32_getenv_unknown; -#define getenv(n) w32_getenv(n) +#define getenv(n) rb_w32_ugetenv(n) #elif defined(__APPLE__) #undef environ #define environ (*_NSGetEnviron()) @@ -4664,35 +4821,32 @@ extern char **environ; #define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0) #endif -static VALUE -env_enc_str_new(const char *ptr, long len, rb_encoding *enc) +#define ENV_LOCK() RB_VM_LOCK_ENTER() +#define ENV_UNLOCK() RB_VM_LOCK_LEAVE() + +static inline rb_encoding * +env_encoding(void) { #ifdef _WIN32 - rb_encoding *internal = rb_default_internal_encoding(); - const int ecflags = ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE; - rb_encoding *utf8 = rb_utf8_encoding(); - VALUE str = rb_enc_str_new(NULL, 0, (internal ? internal : enc)); - if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, utf8, ecflags, Qnil))) { - rb_str_initialize(str, ptr, len, NULL); - } + return rb_utf8_encoding(); #else - VALUE str = rb_external_str_new_with_enc(ptr, len, enc); + return rb_locale_encoding(); #endif - - rb_obj_freeze(str); - return str; } static VALUE -env_enc_str_new_cstr(const char *ptr, rb_encoding *enc) +env_enc_str_new(const char *ptr, long len, rb_encoding *enc) { - return env_enc_str_new(ptr, strlen(ptr), enc); + VALUE str = rb_external_str_new_with_enc(ptr, len, enc); + + rb_obj_freeze(str); + return str; } static VALUE env_str_new(const char *ptr, long len) { - return env_enc_str_new(ptr, len, rb_locale_encoding()); + return env_enc_str_new(ptr, len, env_encoding()); } static VALUE @@ -4702,49 +4856,46 @@ env_str_new2(const char *ptr) return env_str_new(ptr, strlen(ptr)); } -static const char TZ_ENV[] = "TZ"; -extern bool ruby_tz_uptodate_p; - -static rb_encoding * -env_encoding_for(const char *name, const char *ptr) +static VALUE +getenv_with_lock(const char *name) { - if (ENVMATCH(name, PATH_ENV)) { - return rb_filesystem_encoding(); - } - else { - return rb_locale_encoding(); + VALUE ret; + ENV_LOCK(); + { + const char *val = getenv(name); + ret = env_str_new2(val); } + ENV_UNLOCK(); + return ret; } -static VALUE -env_name_new(const char *name, const char *ptr) +static bool +has_env_with_lock(const char *name) { - return env_enc_str_new_cstr(ptr, env_encoding_for(name, ptr)); + const char *val; + + ENV_LOCK(); + { + val = getenv(name); + } + ENV_UNLOCK(); + + return val ? true : false; } +static const char TZ_ENV[] = "TZ"; + static void * get_env_cstr( -#ifdef _WIN32 - volatile VALUE *pstr, -#else VALUE str, -#endif const char *name) { -#ifdef _WIN32 - VALUE str = *pstr; -#endif char *var; rb_encoding *enc = rb_enc_get(str); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s", name, rb_enc_name(enc)); } -#ifdef _WIN32 - if (!rb_enc_str_asciionly_p(str)) { - *pstr = str = rb_str_conv_enc(str, NULL, rb_utf8_encoding()); - } -#endif var = RSTRING_PTR(str); if (memchr(var, '\0', RSTRING_LEN(str))) { rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name); @@ -4752,13 +4903,8 @@ get_env_cstr( return rb_str_fill_terminator(str, 1); /* ASCII compatible */ } -#ifdef _WIN32 -#define get_env_ptr(var, val) \ - (var = get_env_cstr(&(val), #var)) -#else #define get_env_ptr(var, val) \ (var = get_env_cstr(val, #var)) -#endif static inline const char * env_name(volatile VALUE *s) @@ -4773,14 +4919,9 @@ env_name(volatile VALUE *s) static VALUE env_aset(VALUE nm, VALUE val); -static VALUE -env_delete(VALUE name) +static void +reset_by_modified_env(const char *nam) { - const char *nam, *val; - - nam = env_name(name); - val = getenv(nam); - /* * ENV['TZ'] = nil has a special meaning. * TZ is no longer considered up-to-date and ruby call tzset() as needed. @@ -4788,41 +4929,47 @@ env_delete(VALUE name) * This hack might works only on Linux glibc. */ if (ENVMATCH(nam, TZ_ENV)) { - ruby_tz_uptodate_p = FALSE; + ruby_reset_timezone(); } +} - if (val) { - VALUE value = env_str_new2(val); +static VALUE +env_delete(VALUE name) +{ + const char *nam = env_name(name); + reset_by_modified_env(nam); + VALUE val = getenv_with_lock(nam); - ruby_setenv(nam, 0); - if (ENVMATCH(nam, PATH_ENV)) { - RB_GC_GUARD(name); - } - return value; + if (!NIL_P(val)) { + ruby_setenv(nam, 0); } - return Qnil; + return val; } /* * call-seq: - * ENV.delete(name) -> value - * ENV.delete(name) { |name| block } -> value + * ENV.delete(name) -> value + * ENV.delete(name) { |name| block } -> value + * ENV.delete(missing_name) -> nil + * ENV.delete(missing_name) { |name| block } -> block_value * * Deletes the environment variable with +name+ if it exists and returns its value: * ENV['foo'] = '0' * ENV.delete('foo') # => '0' - * Returns +nil+ if the named environment variable does not exist: - * ENV.delete('foo') # => nil + * + * If a block is not given and the named environment variable does not exist, returns +nil+. + * * If a block given and the environment variable does not exist, - * yields +name+ to the block and returns +nil+: - * ENV.delete('foo') { |name| puts name } # => nil - * foo + * yields +name+ to the block and returns the value of the block: + * ENV.delete('foo') { |name| name * 2 } # => "foofoo" + * * If a block given and the environment variable exists, * deletes the environment variable and returns its value (ignoring the block): * ENV['foo'] = '0' - * ENV.delete('foo') { |name| fail 'ignored' } # => "0" + * ENV.delete('foo') { |name| raise 'ignored' } # => "0" + * * Raises an exception if +name+ is invalid. - * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values]. + * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]. */ static VALUE env_delete_m(VALUE obj, VALUE name) @@ -4830,7 +4977,7 @@ env_delete_m(VALUE obj, VALUE name) VALUE val; val = env_delete(name); - if (NIL_P(val) && rb_block_given_p()) rb_yield(name); + if (NIL_P(val) && rb_block_given_p()) val = rb_yield(name); return val; } @@ -4841,23 +4988,17 @@ env_delete_m(VALUE obj, VALUE name) * Returns the value for the environment variable +name+ if it exists: * ENV['foo'] = '0' * ENV['foo'] # => "0" - * Returns nil if the named variable does not exist: - * ENV.clear - * ENV['foo'] # => nil + * Returns +nil+ if the named variable does not exist. + * * Raises an exception if +name+ is invalid. - * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values]. + * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]. */ static VALUE rb_f_getenv(VALUE obj, VALUE name) { - const char *nam, *env; - - nam = env_name(name); - env = getenv(nam); - if (env) { - return env_name_new(nam, env); - } - return Qnil; + const char *nam = env_name(name); + VALUE env = getenv_with_lock(nam); + return env; } /* @@ -4883,14 +5024,15 @@ rb_f_getenv(VALUE obj, VALUE name) * and neither default value nor block is given: * ENV.fetch('foo') # Raises KeyError (key not found: "foo") * Raises an exception if +name+ is invalid. - * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values]. + * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]. */ static VALUE env_fetch(int argc, VALUE *argv, VALUE _) { VALUE key; long block_given; - const char *nam, *env; + const char *nam; + VALUE env; rb_check_arity(argc, 1, 2); key = argv[0]; @@ -4899,21 +5041,22 @@ env_fetch(int argc, VALUE *argv, VALUE _) rb_warn("block supersedes default value argument"); } nam = env_name(key); - env = getenv(nam); - if (!env) { + env = getenv_with_lock(nam); + + if (NIL_P(env)) { if (block_given) return rb_yield(key); if (argc == 1) { rb_key_err_raise(rb_sprintf("key not found: \"%"PRIsVALUE"\"", key), envtbl, key); } return argv[1]; } - return env_name_new(nam, env); + return env; } int rb_env_path_tainted(void) { - rb_warning("rb_env_path_tainted is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_env_path_tainted", NULL); return 0; } @@ -4932,6 +5075,8 @@ in_origenv(const char *str) static int envix(const char *nam) { + // should be locked + register int i, len = strlen(nam); char **env; @@ -5041,11 +5186,17 @@ ruby_setenv(const char *name, const char *value) wname[len-1] = L'='; #endif } + + ENV_LOCK(); + { #ifndef HAVE__WPUTENV_S - failed = _wputenv(wname); + failed = _wputenv(wname); #else - failed = _wputenv_s(wname, wvalue); + failed = _wputenv_s(wname, wvalue); #endif + } + ENV_UNLOCK(); + ALLOCV_END(buf); /* even if putenv() failed, clean up and try to delete the * variable from the system area. */ @@ -5060,15 +5211,31 @@ ruby_setenv(const char *name, const char *value) } #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV) if (value) { - if (setenv(name, value, 1)) - rb_sys_fail_str(rb_sprintf("setenv(%s)", name)); + int ret; + ENV_LOCK(); + { + ret = setenv(name, value, 1); + } + ENV_UNLOCK(); + + if (ret) rb_sys_fail_str(rb_sprintf("setenv(%s)", name)); } else { #ifdef VOID_UNSETENV - unsetenv(name); + ENV_LOCK(); + { + unsetenv(name); + } + ENV_UNLOCK(); #else - if (unsetenv(name)) - rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name)); + int ret; + ENV_LOCK(); + { + ret = unsetenv(name); + } + ENV_UNLOCK(); + + if (ret) rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name)); #endif } #elif defined __sun @@ -5082,64 +5249,85 @@ ruby_setenv(const char *name, const char *value) check_envname(name); len = strlen(name); if (value) { - mem_size = len + strlen(value) + 2; - mem_ptr = malloc(mem_size); - if (mem_ptr == NULL) - rb_sys_fail_str(rb_sprintf("malloc("PRIuSIZE")", mem_size)); - snprintf(mem_ptr, mem_size, "%s=%s", name, value); - } - for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) { - if (!strncmp(str, name, len) && str[len] == '=') { - if (!in_origenv(str)) free(str); - while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++; - break; - } + mem_size = len + strlen(value) + 2; + mem_ptr = malloc(mem_size); + if (mem_ptr == NULL) + rb_sys_fail_str(rb_sprintf("malloc(%"PRIuSIZE")", mem_size)); + snprintf(mem_ptr, mem_size, "%s=%s", name, value); + } + + ENV_LOCK(); + { + for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) { + if (!strncmp(str, name, len) && str[len] == '=') { + if (!in_origenv(str)) free(str); + while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++; + break; + } + } } + ENV_UNLOCK(); + if (value) { - if (putenv(mem_ptr)) { + int ret; + ENV_LOCK(); + { + ret = putenv(mem_ptr); + } + ENV_UNLOCK(); + + if (ret) { free(mem_ptr); - rb_sys_fail_str(rb_sprintf("putenv(%s)", name)); - } + rb_sys_fail_str(rb_sprintf("putenv(%s)", name)); + } } #else /* WIN32 */ size_t len; int i; - i=envix(name); /* where does it go? */ - - if (environ == origenviron) { /* need we copy environment? */ - int j; - int max; - char **tmpenv; - - for (max = i; environ[max]; max++) ; - tmpenv = ALLOC_N(char*, max+2); - for (j=0; j value + * ENV[name] = value -> value * ENV.store(name, value) -> value * * ENV.store is an alias for ENV.[]=. @@ -5216,37 +5404,39 @@ env_aset(VALUE nm, VALUE val) get_env_ptr(value, val); ruby_setenv(name, value); - if (ENVMATCH(name, PATH_ENV)) { - RB_GC_GUARD(nm); - } - else if (ENVMATCH(name, TZ_ENV)) { - ruby_tz_uptodate_p = FALSE; - } + reset_by_modified_env(name); return val; } static VALUE -env_keys(void) -{ - char **env; - VALUE ary; - - ary = rb_ary_new(); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s) { - rb_ary_push(ary, env_str_new(*env, s-*env)); - } - env++; +env_keys(int raw) +{ + rb_encoding *enc = raw ? 0 : rb_locale_encoding(); + VALUE ary = rb_ary_new(); + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); + if (s) { + const char *p = *env; + size_t l = s - p; + VALUE e = raw ? rb_utf8_str_new(p, l) : env_enc_str_new(p, l, enc); + rb_ary_push(ary, e); + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); + return ary; } /* * call-seq: - * ENV.keys -> Array + * ENV.keys -> array of names * * Returns all variable names in an Array: * ENV.replace('foo' => '0', 'bar' => '1') @@ -5254,15 +5444,13 @@ env_keys(void) * The order of the names is OS-dependent. * See {About Ordering}[#class-ENV-label-About+Ordering]. * - * Returns the empty Array if ENV is empty: - * ENV.clear - * ENV.keys # => [] + * Returns the empty Array if ENV is empty. */ static VALUE env_f_keys(VALUE _) { - return env_keys(); + return env_keys(FALSE); } static VALUE @@ -5271,20 +5459,25 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj) char **env; long cnt = 0; - env = GET_ENVIRON(environ); - for (; *env ; ++env) { - if (strchr(*env, '=')) { - cnt++; - } + ENV_LOCK(); + { + env = GET_ENVIRON(environ); + for (; *env ; ++env) { + if (strchr(*env, '=')) { + cnt++; + } + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); + return LONG2FIX(cnt); } /* * call-seq: * ENV.each_key { |name| block } -> ENV - * ENV.each_key -> Enumerator + * ENV.each_key -> an_enumerator * * Yields each environment variable name: * ENV.replace('foo' => '0', 'bar' => '1') # => ENV @@ -5305,7 +5498,7 @@ env_each_key(VALUE ehash) long i; RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); - keys = env_keys(); + keys = env_keys(FALSE); for (i=0; i Array + * ENV.values -> array of values * * Returns all environment variable values in an Array: * ENV.replace('foo' => '0', 'bar' => '1') @@ -5341,9 +5538,7 @@ env_values(void) * The order of the values is OS-dependent. * See {About Ordering}[#class-ENV-label-About+Ordering]. * - * Returns the empty Array if ENV is empty: - * ENV.clear - * ENV.values # => [] + * Returns the empty Array if ENV is empty. */ static VALUE env_f_values(VALUE _) @@ -5354,7 +5549,7 @@ env_f_values(VALUE _) /* * call-seq: * ENV.each_value { |value| block } -> ENV - * ENV.each_value -> Enumerator + * ENV.each_value -> an_enumerator * * Yields each environment variable value: * ENV.replace('foo' => '0', 'bar' => '1') # => ENV @@ -5385,11 +5580,11 @@ env_each_value(VALUE ehash) /* * call-seq: * ENV.each { |name, value| block } -> ENV - * ENV.each -> Enumerator + * ENV.each -> an_enumerator * ENV.each_pair { |name, value| block } -> ENV - * ENV.each_pair -> Enumerator + * ENV.each_pair -> an_enumerator * - * Yields each environment variable name and its value as a 2-element Array: + * Yields each environment variable name and its value as a 2-element \Array: * h = {} * ENV.each_pair { |name, value| h[name] = value } # => ENV * h # => {"bar"=>"1", "foo"=>"0"} @@ -5403,26 +5598,30 @@ env_each_value(VALUE ehash) static VALUE env_each_pair(VALUE ehash) { - char **env; - VALUE ary; long i; RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); - ary = rb_ary_new(); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s) { - rb_ary_push(ary, env_str_new(*env, s-*env)); - rb_ary_push(ary, env_str_new2(s+1)); - } - env++; + VALUE ary = rb_ary_new(); + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + + while (*env) { + char *s = strchr(*env, '='); + if (s) { + rb_ary_push(ary, env_str_new(*env, s-*env)); + rb_ary_push(ary, env_str_new2(s+1)); + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); - if (rb_block_arity() > 1) { - for (i=0; i ENV or nil - * ENV.reject! -> Enumerator + * ENV.reject! -> an_enumerator * * Similar to ENV.delete_if, but returns +nil+ if no changes were made. * - * Deletes each environment variable for which the block returns a truthy value, - * returning ENV (if any deletions) or +nil+ (if not): + * Yields each environment variable name and its value as a 2-element Array, + * deleting each environment variable for which the block returns a truthy value, + * and returning ENV (if any deletions) or +nil+ (if not): * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') * ENV.reject! { |name, value| name.start_with?('b') } # => ENV * ENV # => {"foo"=>"0"} @@ -5463,7 +5664,7 @@ env_reject_bang(VALUE ehash) int del = 0; RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); - keys = env_keys(); + keys = env_keys(FALSE); RBASIC_CLEAR_CLASS(keys); for (i=0; i ENV - * ENV.delete_if -> Enumerator + * ENV.delete_if -> an_enumerator * - * Deletes every environment variable for which the block evaluates to +true+. + * Yields each environment variable name and its value as a 2-element Array, + * deleting each environment variable for which the block returns a truthy value, + * and returning ENV (regardless of whether any deletions): + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"foo"=>"0"} + * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV * - * If no block is given an enumerator is returned instead. + * Returns an Enumerator if no block given: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * e = ENV.delete_if # => #"1", "baz"=>"2", "foo"=>"0"}:delete_if!> + * e.each { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"foo"=>"0"} + * e.each { |name, value| name.start_with?('b') } # => ENV */ static VALUE env_delete_if(VALUE ehash) @@ -5498,10 +5710,20 @@ env_delete_if(VALUE ehash) /* * call-seq: - * ENV.values_at(name, ...) -> Array + * ENV.values_at(*names) -> array of values * - * Returns an array containing the environment variable values associated with - * the given names. See also ENV.select. + * Returns an Array containing the environment variable values associated with + * the given names: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.values_at('foo', 'baz') # => ["0", "2"] + * + * Returns +nil+ in the Array for each name that is not an ENV name: + * ENV.values_at('foo', 'bat', 'bar', 'bam') # => ["0", nil, "1", nil] + * + * Returns an empty \Array if no names given. + * + * Raises an exception if any name is invalid. + * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]. */ static VALUE env_values_at(int argc, VALUE *argv, VALUE _) @@ -5518,16 +5740,24 @@ env_values_at(int argc, VALUE *argv, VALUE _) /* * call-seq: - * ENV.select { |name, value| block } -> Hash - * ENV.select -> Enumerator - * ENV.filter { |name, value| block } -> Hash - * ENV.filter -> Enumerator + * ENV.select { |name, value| block } -> hash of name/value pairs + * ENV.select -> an_enumerator + * ENV.filter { |name, value| block } -> hash of name/value pairs + * ENV.filter -> an_enumerator * - * Returns a copy of the environment for entries where the block returns true. + * ENV.filter is an alias for ENV.select. * - * Returns an Enumerator if no block was given. + * Yields each environment variable name and its value as a 2-element Array, + * returning a Hash of the names and values for which the block returns a truthy value: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.select { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"} + * ENV.filter { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"} * - * ENV.filter is an alias for ENV.select. + * Returns an Enumerator if no block given: + * e = ENV.select # => #"1", "baz"=>"2", "foo"=>"0"}:select> + * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"} + * e = ENV.filter # => #"1", "baz"=>"2", "foo"=>"0"}:filter> + * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"} */ static VALUE env_select(VALUE ehash) @@ -5538,7 +5768,7 @@ env_select(VALUE ehash) RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); result = rb_hash_new(); - keys = env_keys(); + keys = env_keys(FALSE); for (i = 0; i < RARRAY_LEN(keys); ++i) { VALUE key = RARRAY_AREF(keys, i); VALUE val = rb_f_getenv(Qnil, key); @@ -5556,13 +5786,39 @@ env_select(VALUE ehash) /* * call-seq: * ENV.select! { |name, value| block } -> ENV or nil - * ENV.select! -> Enumerator + * ENV.select! -> an_enumerator * ENV.filter! { |name, value| block } -> ENV or nil - * ENV.filter! -> Enumerator - * - * Equivalent to ENV.keep_if but returns +nil+ if no changes were made. + * ENV.filter! -> an_enumerator * * ENV.filter! is an alias for ENV.select!. + * + * Yields each environment variable name and its value as a 2-element Array, + * deleting each entry for which the block returns +false+ or +nil+, + * and returning ENV if any deletions made, or +nil+ otherwise: + * + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.select! { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} + * ENV.select! { |name, value| true } # => nil + * + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.filter! { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} + * ENV.filter! { |name, value| true } # => nil + * + * Returns an Enumerator if no block given: + * + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * e = ENV.select! # => #"1", "baz"=>"2"}:select!> + * e.each { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} + * e.each { |name, value| true } # => nil + * + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * e = ENV.filter! # => #"1", "baz"=>"2"}:filter!> + * e.each { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} + * e.each { |name, value| true } # => nil */ static VALUE env_select_bang(VALUE ehash) @@ -5572,7 +5828,7 @@ env_select_bang(VALUE ehash) int del = 0; RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); - keys = env_keys(); + keys = env_keys(FALSE); RBASIC_CLEAR_CLASS(keys); for (i=0; i ENV - * ENV.keep_if -> Enumerator + * ENV.keep_if -> an_enumerator * - * Deletes every environment variable where the block evaluates to +false+. + * Yields each environment variable name and its value as a 2-element Array, + * deleting each environment variable for which the block returns +false+ or +nil+, + * and returning ENV: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.keep_if { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} * - * Returns an enumerator if no block was given. + * Returns an Enumerator if no block given: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * e = ENV.keep_if # => #"1", "baz"=>"2", "foo"=>"0"}:keep_if> + * e.each { |name, value| name.start_with?('b') } # => ENV + * ENV # => {"bar"=>"1", "baz"=>"2"} */ static VALUE env_keep_if(VALUE ehash) @@ -5606,12 +5871,16 @@ env_keep_if(VALUE ehash) } /* - * call-seq: - * ENV.slice(*keys) -> a_hash - * - * Returns a hash containing only the given keys from ENV and their values. - * - * ENV.slice("TERM","HOME") #=> {"TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"} + * call-seq: + * ENV.slice(*names) -> hash of name/value pairs + * + * Returns a Hash of the given ENV names and their corresponding values: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2', 'bat' => '3') + * ENV.slice('foo', 'baz') # => {"foo"=>"0", "baz"=>"2"} + * ENV.slice('baz', 'foo') # => {"baz"=>"2", "foo"=>"0"} + * Raises an exception if any of the +names+ is invalid + * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]): + * ENV.slice('foo', 'bar', :bat) # Raises TypeError (no implicit conversion of Symbol into String) */ static VALUE env_slice(int argc, VALUE *argv, VALUE _) @@ -5640,12 +5909,11 @@ rb_env_clear(void) VALUE keys; long i; - keys = env_keys(); + keys = env_keys(TRUE); for (i=0; i "ENV" * - * Returns "ENV" + * Returns String 'ENV': + * ENV.to_s # => "ENV" */ static VALUE env_to_s(VALUE _) @@ -5681,34 +5950,40 @@ env_to_s(VALUE _) /* * call-seq: - * ENV.inspect -> string + * ENV.inspect -> a_string * - * Returns the contents of the environment as a String. + * Returns the contents of the environment as a String: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.inspect # => "{\"bar\"=>\"1\", \"foo\"=>\"0\"}" */ static VALUE env_inspect(VALUE _) { - char **env; - VALUE str, i; + VALUE i; + VALUE str = rb_str_buf_new2("{"); - str = rb_str_buf_new2("{"); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); - if (env != environ) { - rb_str_buf_cat2(str, ", "); - } - if (s) { - rb_str_buf_cat2(str, "\""); - rb_str_buf_cat(str, *env, s-*env); - rb_str_buf_cat2(str, "\"=>"); - i = rb_inspect(rb_str_new2(s+1)); - rb_str_buf_append(str, i); - } - env++; + if (env != environ) { + rb_str_buf_cat2(str, ", "); + } + if (s) { + rb_str_buf_cat2(str, "\""); + rb_str_buf_cat(str, *env, s-*env); + rb_str_buf_cat2(str, "\"=>"); + i = rb_inspect(rb_str_new2(s+1)); + rb_str_buf_append(str, i); + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); + rb_str_buf_cat2(str, "}"); return str; @@ -5716,39 +5991,43 @@ env_inspect(VALUE _) /* * call-seq: - * ENV.to_a -> Array - * - * Converts the environment variables into an array of names and value arrays. - * - * ENV.to_a # => [["TERM", "xterm-color"], ["SHELL", "/bin/bash"], ...] + * ENV.to_a -> array of 2-element arrays * + * Returns the contents of ENV as an Array of 2-element Arrays, + * each of which is a name/value pair: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.to_a # => [["bar", "1"], ["foo", "0"]] */ static VALUE env_to_a(VALUE _) { - char **env; - VALUE ary; + VALUE ary = rb_ary_new(); - ary = rb_ary_new(); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s) { - rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env), - env_str_new2(s+1))); - } - env++; + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); + if (s) { + rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env), + env_str_new2(s+1))); + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); + return ary; } /* * call-seq: - * ENV.rehash + * ENV.rehash -> nil + * + * (Provided for compatibility with Hash.) * - * Re-hashing the environment variables does nothing. It is provided for - * compatibility with Hash. + * Does not modify ENV; returns +nil+. */ static VALUE env_none(VALUE _) @@ -5756,44 +6035,64 @@ env_none(VALUE _) return Qnil; } +static int +env_size_with_lock(void) +{ + int i = 0; + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (env[i]) i++; + FREE_ENVIRON(environ); + } + ENV_UNLOCK(); + + return i; +} + /* * call-seq: - * ENV.length - * ENV.size + * ENV.length -> an_integer + * ENV.size -> an_integer * - * Returns the number of environment variables. + * Returns the count of environment variables: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.length # => 2 + * ENV.size # => 2 */ static VALUE env_size(VALUE _) { - int i; - char **env; - - env = GET_ENVIRON(environ); - for (i=0; env[i]; i++) - ; - FREE_ENVIRON(environ); - return INT2FIX(i); + return INT2FIX(env_size_with_lock()); } /* * call-seq: * ENV.empty? -> true or false * - * Returns true when there are no environment variables + * Returns +true+ when there are no environment variables, +false+ otherwise: + * ENV.clear + * ENV.empty? # => true + * ENV['foo'] = '0' + * ENV.empty? # => false */ static VALUE env_empty_p(VALUE _) { - char **env; + bool empty = true; - env = GET_ENVIRON(environ); - if (env[0] == 0) { + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + if (env[0] != 0) { + empty = false; + } FREE_ENVIRON(environ); - return Qtrue; } - FREE_ENVIRON(environ); - return Qfalse; + ENV_UNLOCK(); + + return RBOOL(empty); } /* @@ -5824,26 +6123,22 @@ env_empty_p(VALUE _) static VALUE env_has_key(VALUE env, VALUE key) { - const char *s; - - s = env_name(key); - if (getenv(s)) return Qtrue; - return Qfalse; + const char *s = env_name(key); + return RBOOL(has_env_with_lock(s)); } /* * call-seq: - * ENV.assoc(name) -> Array or nil + * ENV.assoc(name) -> [name, value] or nil * * Returns a 2-element Array containing the name and value of the environment variable * for +name+ if it exists: * ENV.replace('foo' => '0', 'bar' => '1') - * ENV.assoc('foo') # => ['foo' '0'] - * Returns +nil+ if +name+ is a valid String and there is no such environment variable: - * ENV.assoc('baz') # => false - * Returns +nil+ if +name+ is the empty String or is a String containing character '=': - * ENV.assoc('') # => false - * ENV.assoc('=') # => false + * ENV.assoc('foo') # => ['foo', '0'] + * Returns +nil+ if +name+ is a valid String and there is no such environment variable. + * + * Returns +nil+ if +name+ is the empty String or is a String containing character '='. + * * Raises an exception if +name+ is a String containing the NUL character "\0": * ENV.assoc("\0") # Raises ArgumentError (bad environment variable name: contains null byte) * Raises an exception if +name+ has an encoding that is not ASCII-compatible: @@ -5855,153 +6150,188 @@ env_has_key(VALUE env, VALUE key) static VALUE env_assoc(VALUE env, VALUE key) { - const char *s, *e; + const char *s = env_name(key); + VALUE e = getenv_with_lock(s); - s = env_name(key); - e = getenv(s); - if (e) return rb_assoc_new(key, env_str_new2(e)); - return Qnil; + if (!NIL_P(e)) { + return rb_assoc_new(key, e); + } + else { + return Qnil; + } } /* * call-seq: - * ENV.value?(value) -> true or false + * ENV.value?(value) -> true or false * ENV.has_value?(value) -> true or false * - * Returns +true+ if there is an environment variable with the given +value+. + * Returns +true+ if +value+ is the value for some environment variable name, +false+ otherwise: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.value?('0') # => true + * ENV.has_value?('0') # => true + * ENV.value?('2') # => false + * ENV.has_value?('2') # => false */ static VALUE env_has_value(VALUE dmy, VALUE obj) { - char **env; - obj = rb_check_string_type(obj); if (NIL_P(obj)) return Qnil; - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s++) { - long len = strlen(s); - if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { - FREE_ENVIRON(environ); - return Qtrue; - } - } - env++; + + VALUE ret = Qfalse; + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); + if (s++) { + long len = strlen(s); + if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { + ret = Qtrue; + break; + } + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); - return Qfalse; + ENV_UNLOCK(); + + return ret; } /* * call-seq: - * ENV.rassoc(value) + * ENV.rassoc(value) -> [name, value] or nil + * + * Returns a 2-element Array containing the name and value of the + * *first* *found* environment variable that has value +value+, if one + * exists: + * ENV.replace('foo' => '0', 'bar' => '0') + * ENV.rassoc('0') # => ["bar", "0"] + * The order in which environment variables are examined is OS-dependent. + * See {About Ordering}[#class-ENV-label-About+Ordering]. * - * Returns an Array of the name and value of the environment variable with - * +value+ or +nil+ if the value cannot be found. + * Returns +nil+ if there is no such environment variable. */ static VALUE env_rassoc(VALUE dmy, VALUE obj) { - char **env; - obj = rb_check_string_type(obj); if (NIL_P(obj)) return Qnil; - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s++) { - long len = strlen(s); - if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { - VALUE result = rb_assoc_new(rb_str_new(*env, s-*env-1), obj); - FREE_ENVIRON(environ); - return result; - } - } - env++; + + VALUE result = Qnil; + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + + while (*env) { + const char *p = *env; + char *s = strchr(p, '='); + if (s++) { + long len = strlen(s); + if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { + result = rb_assoc_new(rb_str_new(p, s-p-1), obj); + break; + } + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); - return Qnil; + ENV_UNLOCK(); + + return result; } /* * call-seq: * ENV.key(value) -> name or nil * - * Returns the name of the first environment variable with +value+ if it exists: - * ENV.replace('foo' => '0', 'bar' => '1') - * ENV.key('0') # =>'foo' + * Returns the name of the first environment variable with +value+, if it exists: + * ENV.replace('foo' => '0', 'bar' => '0') + * ENV.key('0') # => "foo" * The order in which environment variables are examined is OS-dependent. * See {About Ordering}[#class-ENV-label-About+Ordering]. * - * Returns +nil+ if there is no such value: - * ENV.key('2') # => nil - * Raises an exception if +value+ is not a String: + * Returns +nil+ if there is no such value. + * + * Raises an exception if +value+ is invalid: * ENV.key(Object.new) # raises TypeError (no implicit conversion of Object into String) + * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]. */ static VALUE env_key(VALUE dmy, VALUE value) { - char **env; - VALUE str; - SafeStringValue(value); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s++) { - long len = strlen(s); - if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) { - str = env_str_new(*env, s-*env-1); - FREE_ENVIRON(environ); - return str; - } - } - env++; + VALUE str = Qnil; + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); + if (s++) { + long len = strlen(s); + if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) { + str = env_str_new(*env, s-*env-1); + break; + } + } + env++; + } + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); - return Qnil; -} + ENV_UNLOCK(); -/* - * call-seq: - * ENV.index(value) -> key - * - * Deprecated method that is equivalent to ENV.key - */ -static VALUE -env_index(VALUE dmy, VALUE value) -{ - rb_warn_deprecated("ENV.index", "ENV.key"); - return env_key(dmy, value); + return str; } static VALUE env_to_hash(void) { - char **env; - VALUE hash; + VALUE hash = rb_hash_new(); - hash = rb_hash_new(); - env = GET_ENVIRON(environ); - while (*env) { - char *s = strchr(*env, '='); - if (s) { - rb_hash_aset(hash, env_str_new(*env, s-*env), - env_str_new2(s+1)); + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + while (*env) { + char *s = strchr(*env, '='); + if (s) { + rb_hash_aset(hash, env_str_new(*env, s-*env), + env_str_new2(s+1)); + } + env++; } - env++; + FREE_ENVIRON(environ); } - FREE_ENVIRON(environ); + ENV_UNLOCK(); + return hash; } +VALUE +rb_envtbl(void) +{ + return envtbl; +} + +VALUE +rb_env_to_hash(void) +{ + return env_to_hash(); +} + /* * call-seq: - * ENV.to_hash -> hash - * - * Creates a hash with a copy of the environment variables. + * ENV.to_hash -> hash of name/value pairs * + * Returns a Hash containing all name/value pairs from ENV: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"} */ static VALUE @@ -6012,11 +6342,21 @@ env_f_to_hash(VALUE _) /* * call-seq: - * ENV.to_h -> hash - * ENV.to_h {|name, value| block } -> hash - * - * Creates a hash with a copy of the environment variables. + * ENV.to_h -> hash of name/value pairs + * ENV.to_h {|name, value| block } -> hash of name/value pairs * + * With no block, returns a Hash containing all name/value pairs from ENV: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.to_h # => {"bar"=>"1", "foo"=>"0"} + * With a block, returns a Hash whose items are determined by the block. + * Each name/value pair in ENV is yielded to the block. + * The block must return a 2-element Array (name/value pair) + * that is added to the return Hash as a key and value: + * ENV.to_h { |name, value| [name.to_sym, value.to_i] } # => {:bar=>1, :foo=>0} + * Raises an exception if the block does not return an Array: + * ENV.to_h { |name, value| name } # Raises TypeError (wrong element type String (expected array)) + * Raises an exception if the block returns an Array of the wrong size: + * ENV.to_h { |name, value| [name] } # Raises ArgumentError (element has wrong array length (expected 2, was 1)) */ static VALUE env_to_h(VALUE _) @@ -6028,13 +6368,43 @@ env_to_h(VALUE _) return hash; } +/* + * call-seq: + * ENV.except(*keys) -> a_hash + * + * Returns a hash except the given keys from ENV and their values. + * + * ENV #=> {"LANG"=>"en_US.UTF-8", "TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"} + * ENV.except("TERM","HOME") #=> {"LANG"=>"en_US.UTF-8"} + */ +static VALUE +env_except(int argc, VALUE *argv, VALUE _) +{ + int i; + VALUE key, hash = env_to_hash(); + + for (i = 0; i < argc; i++) { + key = argv[i]; + rb_hash_delete(hash, key); + } + + return hash; +} + /* * call-seq: - * ENV.reject { |name, value| block } -> Hash - * ENV.reject -> Enumerator + * ENV.reject { |name, value| block } -> hash of name/value pairs + * ENV.reject -> an_enumerator * - * Same as ENV.delete_if, but works on (and returns) a copy of the - * environment. + * Yields each environment variable name and its value as a 2-element Array. + * Returns a Hash whose items are determined by the block. + * When the block returns a truthy value, the name/value pair is added to the return Hash; + * otherwise the pair is ignored: + * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2') + * ENV.reject { |name, value| name.start_with?('b') } # => {"foo"=>"0"} + * Returns an Enumerator if no block given: + * e = ENV.reject + * e.each { |name, value| name.start_with?('b') } # => {"foo"=>"0"} */ static VALUE env_reject(VALUE _) @@ -6042,18 +6412,19 @@ env_reject(VALUE _) return rb_hash_delete_if(env_to_hash()); } +NORETURN(static VALUE env_freeze(VALUE self)); /* * call-seq: - * ENV.freeze -> raises TypeError + * ENV.freeze * - * Ruby does not allow ENV to be frozen, so calling ENV.freeze - * raises TypeError. + * Raises an exception: + * ENV.freeze # Raises TypeError (cannot freeze ENV) */ static VALUE env_freeze(VALUE self) { rb_raise(rb_eTypeError, "cannot freeze ENV"); - return self; /* Not reached */ + UNREACHABLE_RETURN(self); } /* @@ -6069,36 +6440,51 @@ env_freeze(VALUE self) * Exactly which environment variable is "first" is OS-dependent. * See {About Ordering}[#class-ENV-label-About+Ordering]. * - * Returns +nil+ if the environment is empty: - * ENV.clear - * ENV.shift # => nil + * Returns +nil+ if the environment is empty. */ static VALUE env_shift(VALUE _) { - char **env; VALUE result = Qnil; + VALUE key = Qnil; + + ENV_LOCK(); + { + char **env = GET_ENVIRON(environ); + if (*env) { + const char *p = *env; + char *s = strchr(p, '='); + if (s) { + key = env_str_new(p, s-p); + VALUE val = env_str_new2(getenv(RSTRING_PTR(key))); + result = rb_assoc_new(key, val); + } + } + FREE_ENVIRON(environ); + } + ENV_UNLOCK(); - env = GET_ENVIRON(environ); - if (*env) { - char *s = strchr(*env, '='); - if (s) { - VALUE key = env_str_new(*env, s-*env); - VALUE val = env_str_new2(getenv(RSTRING_PTR(key))); - env_delete(key); - result = rb_assoc_new(key, val); - } + if (!NIL_P(key)) { + env_delete(key); } - FREE_ENVIRON(environ); + return result; } /* * call-seq: - * ENV.invert -> Hash + * ENV.invert -> hash of value/name pairs * - * Returns a new hash created by using environment variable names as values - * and values as names. + * Returns a Hash whose keys are the ENV values, + * and whose values are the corresponding ENV names: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.invert # => {"1"=>"bar", "0"=>"foo"} + * For a duplicate ENV value, overwrites the hash entry: + * ENV.replace('foo' => '0', 'bar' => '0') + * ENV.invert # => {"0"=>"foo"} + * Note that the order of the ENV processing is OS-dependent, + * which means that the order of overwriting is also OS-dependent. + * See {About Ordering}[#class-ENV-label-About+Ordering]. */ static VALUE env_invert(VALUE _) @@ -6106,13 +6492,32 @@ env_invert(VALUE _) return rb_hash_invert(env_to_hash()); } +static void +keylist_delete(VALUE keys, VALUE key) +{ + long keylen, elen; + const char *keyptr, *eptr; + RSTRING_GETMEM(key, keyptr, keylen); + /* Don't stop at first key, as it is possible to have + multiple environment values with the same key. + */ + for (long i=0; i '0', 'bar' => '1') # => ENV * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"} * - * Raises an exception if a name or value is invalid. - * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values]. + * Raises an exception if a name or value is invalid + * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]): + * ENV.replace('foo' => '0', :bar => '1') # Raises TypeError (no implicit conversion of Symbol into String) + * ENV.replace('foo' => '0', 'bar' => 1) # Raises TypeError (no implicit conversion of Integer into String) + * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"} */ static VALUE env_replace(VALUE env, VALUE hash) @@ -6137,7 +6545,7 @@ env_replace(VALUE env, VALUE hash) VALUE keys; long i; - keys = env_keys(); + keys = env_keys(TRUE); if (env == hash) return env; hash = to_hash(hash); rb_hash_foreach(hash, env_replace_i, keys); @@ -6169,15 +6577,39 @@ env_update_block_i(VALUE key, VALUE val, VALUE _) /* * call-seq: - * ENV.update(hash) -> ENV - * ENV.update(hash) { |name, old_value, new_value| block } -> ENV - * ENV.merge!(hash) -> ENV - * ENV.merge!(hash) { |name, old_value, new_value| block } -> ENV - * - * Adds the contents of +hash+ to the environment variables. If no block is - * specified entries with duplicate keys are overwritten, otherwise the value - * of each duplicate name is determined by calling the block with the key, its - * value from the environment and its value from the hash. + * ENV.update(hash) -> ENV + * ENV.update(hash) { |name, env_val, hash_val| block } -> ENV + * ENV.merge!(hash) -> ENV + * ENV.merge!(hash) { |name, env_val, hash_val| block } -> ENV + * + * ENV.update is an alias for ENV.merge!. + * + * Adds to ENV each key/value pair in the given +hash+; returns ENV: + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"} + * Deletes the ENV entry for a hash value that is +nil+: + * ENV.merge!('baz' => nil, 'bat' => nil) # => {"bar"=>"1", "foo"=>"0"} + * For an already-existing name, if no block given, overwrites the ENV value: + * ENV.merge!('foo' => '4') # => {"bar"=>"1", "foo"=>"4"} + * For an already-existing name, if block given, + * yields the name, its ENV value, and its hash value; + * the block's return value becomes the new name: + * ENV.merge!('foo' => '5') { |name, env_val, hash_val | env_val + hash_val } # => {"bar"=>"1", "foo"=>"45"} + * Raises an exception if a name or value is invalid + * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]); + * ENV.replace('foo' => '0', 'bar' => '1') + * ENV.merge!('foo' => '6', :bar => '7', 'baz' => '9') # Raises TypeError (no implicit conversion of Symbol into String) + * ENV # => {"bar"=>"1", "foo"=>"6"} + * ENV.merge!('foo' => '7', 'bar' => 8, 'baz' => '9') # Raises TypeError (no implicit conversion of Integer into String) + * ENV # => {"bar"=>"1", "foo"=>"7"} + * Raises an exception if the block returns an invalid name: + * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]): + * ENV.merge!('bat' => '8', 'foo' => '9') { |name, env_val, hash_val | 10 } # Raises TypeError (no implicit conversion of Integer into String) + * ENV # => {"bar"=>"1", "bat"=>"8", "foo"=>"7"} + * + * Note that for the exceptions above, + * hash pairs preceding an invalid name or value are processed normally; + * those following are ignored. */ static VALUE env_update(VALUE env, VALUE hash) @@ -6191,79 +6623,281 @@ env_update(VALUE env, VALUE hash) } /* - * A Hash is a dictionary-like collection of unique keys and their values. - * Also called associative arrays, they are similar to Arrays, but where an - * Array uses integers as its index, a Hash allows you to use any object - * type. - * - * Hashes enumerate their values in the order that the corresponding keys - * were inserted. + * call-seq: + * ENV.clone(freeze: nil) -> ENV * - * A Hash can be easily created by using its implicit form: + * Returns ENV itself, and warns because ENV is a wrapper for the + * process-wide environment variables and a clone is useless. + * If +freeze+ keyword is given and not +nil+ or +false+, raises ArgumentError. + * If +freeze+ keyword is given and +true+, raises TypeError, as ENV storage + * cannot be frozen. + */ +static VALUE +env_clone(int argc, VALUE *argv, VALUE obj) +{ + if (argc) { + VALUE opt, kwfreeze; + if (rb_scan_args(argc, argv, "0:", &opt) < argc) { + kwfreeze = rb_get_freeze_opt(1, &opt); + if (RTEST(kwfreeze)) { + rb_raise(rb_eTypeError, "cannot freeze ENV"); + } + } + } + + rb_warn_deprecated("ENV.clone", "ENV.to_h"); + return envtbl; +} + +NORETURN(static VALUE env_dup(VALUE)); +/* + * call-seq: + * ENV.dup # raises TypeError * - * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } + * Raises TypeError, because ENV is a singleton object. + * Use #to_h to get a copy of ENV data as a hash. + */ +static VALUE +env_dup(VALUE obj) +{ + rb_raise(rb_eTypeError, "Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash"); +} + +static const rb_data_type_t env_data_type = { + "ENV", + { + NULL, + NULL, + NULL, + NULL, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +/* + * A \Hash maps each of its unique keys to a specific value. * - * Hashes allow an alternate syntax for keys that are symbols. - * Instead of + * A \Hash has certain similarities to an \Array, but: + * - An \Array index is always an \Integer. + * - A \Hash key can be (almost) any object. * - * options = { :font_size => 10, :font_family => "Arial" } + * === \Hash \Data Syntax * - * You could write it as: + * The older syntax for \Hash data uses the "hash rocket," =>: * - * options = { font_size: 10, font_family: "Arial" } + * h = {:foo => 0, :bar => 1, :baz => 2} + * h # => {:foo=>0, :bar=>1, :baz=>2} * - * Each named key is a symbol you can access in hash: + * Alternatively, but only for a \Hash key that's a \Symbol, + * you can use a newer JSON-style syntax, + * where each bareword becomes a \Symbol: * - * options[:font_size] # => 10 + * h = {foo: 0, bar: 1, baz: 2} + * h # => {:foo=>0, :bar=>1, :baz=>2} * - * A Hash can also be created through its ::new method: + * You can also use a \String in place of a bareword: * - * grades = Hash.new - * grades["Dorothy Doe"] = 9 + * h = {'foo': 0, 'bar': 1, 'baz': 2} + * h # => {:foo=>0, :bar=>1, :baz=>2} * - * Hashes have a default value that is returned when accessing - * keys that do not exist in the hash. If no default is set +nil+ is used. - * You can set the default value by sending it as an argument to Hash.new: + * And you can mix the styles: * - * grades = Hash.new(0) + * h = {foo: 0, :bar => 1, 'baz': 2} + * h # => {:foo=>0, :bar=>1, :baz=>2} * - * Or by using the #default= method: + * But it's an error to try the JSON-style syntax + * for a key that's not a bareword or a String: * - * grades = {"Timmy Doe" => 8} - * grades.default = 0 + * # Raises SyntaxError (syntax error, unexpected ':', expecting =>): + * h = {0: 'zero'} * - * Accessing a value in a Hash requires using its key: + * Hash value can be omitted, meaning that value will be fetched from the context + * by the name of the key: * - * puts grades["Jane Doe"] # => 0 + * x = 0 + * y = 100 + * h = {x:, y:} + * h # => {:x=>0, :y=>100} * * === Common Uses * - * Hashes are an easy way to represent data structures, such as + * You can use a \Hash to give names to objects: + * + * person = {name: 'Matz', language: 'Ruby'} + * person # => {:name=>"Matz", :language=>"Ruby"} + * + * You can use a \Hash to give names to method arguments: + * + * def some_method(hash) + * p hash + * end + * some_method({foo: 0, bar: 1, baz: 2}) # => {:foo=>0, :bar=>1, :baz=>2} * - * books = {} - * books[:matz] = "The Ruby Programming Language" - * books[:black] = "The Well-Grounded Rubyist" + * Note: when the last argument in a method call is a \Hash, + * the curly braces may be omitted: * - * Hashes are also commonly used as a way to have named parameters in - * functions. Note that no brackets are used below. If a hash is the last - * argument on a method call, no braces are needed, thus creating a really - * clean interface: + * some_method(foo: 0, bar: 1, baz: 2) # => {:foo=>0, :bar=>1, :baz=>2} * - * Person.create(name: "John Doe", age: 27) + * You can use a \Hash to initialize an object: * - * def self.create(params) - * @name = params[:name] - * @age = params[:age] + * class Dev + * attr_accessor :name, :language + * def initialize(hash) + * self.name = hash[:name] + * self.language = hash[:language] + * end * end + * matz = Dev.new(name: 'Matz', language: 'Ruby') + * matz # => # + * + * === Creating a \Hash + * + * You can create a \Hash object explicitly with: + * + * - A {hash literal}[doc/syntax/literals_rdoc.html#label-Hash+Literals]. + * + * You can convert certain objects to Hashes with: + * + * - \Method {Hash}[Kernel.html#method-i-Hash]. * - * === Hash Keys + * You can create a \Hash by calling method Hash.new. * - * Two objects refer to the same hash key when their hash value + * Create an empty Hash: + * + * h = Hash.new + * h # => {} + * h.class # => Hash + * + * You can create a \Hash by calling method Hash.[]. + * + * Create an empty Hash: + * + * h = Hash[] + * h # => {} + * + * Create a \Hash with initial entries: + * + * h = Hash[foo: 0, bar: 1, baz: 2] + * h # => {:foo=>0, :bar=>1, :baz=>2} + * + * You can create a \Hash by using its literal form (curly braces). + * + * Create an empty \Hash: + * + * h = {} + * h # => {} + * + * Create a \Hash with initial entries: + * + * h = {foo: 0, bar: 1, baz: 2} + * h # => {:foo=>0, :bar=>1, :baz=>2} + * + * + * === \Hash Value Basics + * + * The simplest way to retrieve a \Hash value (instance method #[]): + * + * h = {foo: 0, bar: 1, baz: 2} + * h[:foo] # => 0 + * + * The simplest way to create or update a \Hash value (instance method #[]=): + * + * h = {foo: 0, bar: 1, baz: 2} + * h[:bat] = 3 # => 3 + * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3} + * h[:foo] = 4 # => 4 + * h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3} + * + * The simplest way to delete a \Hash entry (instance method #delete): + * + * h = {foo: 0, bar: 1, baz: 2} + * h.delete(:bar) # => 1 + * h # => {:foo=>0, :baz=>2} + * + * === Entry Order + * + * A \Hash object presents its entries in the order of their creation. This is seen in: + * + * - Iterative methods such as each, each_key, each_pair, each_value. + * - Other order-sensitive methods such as shift, keys, values. + * - The \String returned by method inspect. + * + * A new \Hash has its initial ordering per the given entries: + * + * h = Hash[foo: 0, bar: 1] + * h # => {:foo=>0, :bar=>1} + * + * New entries are added at the end: + * + * h[:baz] = 2 + * h # => {:foo=>0, :bar=>1, :baz=>2} + * + * Updating a value does not affect the order: + * + * h[:baz] = 3 + * h # => {:foo=>0, :bar=>1, :baz=>3} + * + * But re-creating a deleted entry can affect the order: + * + * h.delete(:foo) + * h[:foo] = 5 + * h # => {:bar=>1, :baz=>3, :foo=>5} + * + * === \Hash Keys + * + * ==== \Hash Key Equivalence + * + * Two objects are treated as the same \hash key when their hash value * is identical and the two objects are eql? to each other. * - * A user-defined class may be used as a hash key if the hash - * and eql? methods are overridden to provide meaningful - * behavior. By default, separate instances refer to separate hash keys. + * ==== Modifying an Active \Hash Key + * + * Modifying a \Hash key while it is in use damages the hash's index. + * + * This \Hash has keys that are Arrays: + * + * a0 = [ :foo, :bar ] + * a1 = [ :baz, :bat ] + * h = {a0 => 0, a1 => 1} + * h.include?(a0) # => true + * h[a0] # => 0 + * a0.hash # => 110002110 + * + * Modifying array element a0[0] changes its hash value: + * + * a0[0] = :bam + * a0.hash # => 1069447059 + * + * And damages the \Hash index: + * + * h.include?(a0) # => false + * h[a0] # => nil + * + * You can repair the hash index using method +rehash+: + * + * h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1} + * h.include?(a0) # => true + * h[a0] # => 0 + * + * A \String key is always safe. + * That's because an unfrozen \String + * passed as a key will be replaced by a duplicated and frozen \String: + * + * s = 'foo' + * s.frozen? # => false + * h = {s => 0} + * first_key = h.keys.first + * first_key.frozen? # => true + * + * ==== User-Defined \Hash Keys + * + * To be useable as a \Hash key, objects must implement the methods hash and eql?. + * Note: this requirement does not apply if the \Hash uses #compare_by_identity since comparison will then + * rely on the keys' object id instead of hash and eql?. + * + * \Object defines basic implementation for hash and eq? that makes each object + * a distinct key. Typically, user-defined classes will want to override these methods to provide meaningful + * behavior, or for example inherit \Struct that has useful definitions for these. * * A typical implementation of hash is based on the * object's data while eql? is usually aliased to the overridden @@ -6278,8 +6912,8 @@ env_update(VALUE env, VALUE hash) * end * * def ==(other) - * self.class === other and - * other.author == @author and + * self.class === other && + * other.author == @author && * other.title == @title * end * @@ -6300,18 +6934,226 @@ env_update(VALUE env, VALUE hash) * * reviews.length #=> 1 * - * See also Object#hash and Object#eql? + * === Default Values + * + * The methods #[], #values_at and #dig need to return the value associated to a certain key. + * When that key is not found, that value will be determined by its default proc (if any) + * or else its default (initially `nil`). + * + * You can retrieve the default value with method #default: + * + * h = Hash.new + * h.default # => nil + * + * You can set the default value by passing an argument to method Hash.new or + * with method #default= + * + * h = Hash.new(-1) + * h.default # => -1 + * h.default = 0 + * h.default # => 0 + * + * This default value is returned for #[], #values_at and #dig when a key is + * not found: + * + * counts = {foo: 42} + * counts.default # => nil (default) + * counts[:foo] = 42 + * counts[:bar] # => nil + * counts.default = 0 + * counts[:bar] # => 0 + * counts.values_at(:foo, :bar, :baz) # => [42, 0, 0] + * counts.dig(:bar) # => 0 + * + * Note that the default value is used without being duplicated. It is not advised to set + * the default value to a mutable object: + * + * synonyms = Hash.new([]) + * synonyms[:hello] # => [] + * synonyms[:hello] << :hi # => [:hi], but this mutates the default! + * synonyms.default # => [:hi] + * synonyms[:world] << :universe + * synonyms[:world] # => [:hi, :universe], oops + * synonyms.keys # => [], oops + * + * To use a mutable object as default, it is recommended to use a default proc + * + * ==== Default \Proc + * + * When the default proc for a \Hash is set (i.e., not +nil+), + * the default value returned by method #[] is determined by the default proc alone. + * + * You can retrieve the default proc with method #default_proc: + * + * h = Hash.new + * h.default_proc # => nil + * + * You can set the default proc by calling Hash.new with a block or + * calling the method #default_proc= + * + * h = Hash.new { |hash, key| "Default value for #{key}" } + * h.default_proc.class # => Proc + * h.default_proc = proc { |hash, key| "Default value for #{key.inspect}" } + * h.default_proc.class # => Proc + * + * When the default proc is set (i.e., not +nil+) + * and method #[] is called with with a non-existent key, + * #[] calls the default proc with both the \Hash object itself and the missing key, + * then returns the proc's return value: + * + * h = Hash.new { |hash, key| "Default value for #{key}" } + * h[:nosuch] # => "Default value for nosuch" + * + * Note that in the example above no entry for key +:nosuch+ is created: + * + * h.include?(:nosuch) # => false + * + * However, the proc itself can add a new entry: + * + * synonyms = Hash.new { |hash, key| hash[key] = [] } + * synonyms.include?(:hello) # => false + * synonyms[:hello] << :hi # => [:hi] + * synonyms[:world] << :universe # => [:universe] + * synonyms.keys # => [:hello, :world] + * + * Note that setting the default proc will clear the default value and vice versa. + * + * === What's Here + * + * First, what's elsewhere. \Class \Hash: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * which provides dozens of additional methods. + * + * Here, class \Hash provides methods that are useful for: + * + * - {Creating a Hash}[#class-Hash-label-Methods+for+Creating+a+Hash] + * - {Setting Hash State}[#class-Hash-label-Methods+for+Setting+Hash+State] + * - {Querying}[#class-Hash-label-Methods+for+Querying] + * - {Comparing}[#class-Hash-label-Methods+for+Comparing] + * - {Fetching}[#class-Hash-label-Methods+for+Fetching] + * - {Assigning}[#class-Hash-label-Methods+for+Assigning] + * - {Deleting}[#class-Hash-label-Methods+for+Deleting] + * - {Iterating}[#class-Hash-label-Methods+for+Iterating] + * - {Converting}[#class-Hash-label-Methods+for+Converting] + * - {Transforming Keys and Values}[#class-Hash-label-Methods+for+Transforming+Keys+and+Values] + * - {And more....}[#class-Hash-label-Other+Methods] + * + * \Class \Hash also includes methods from module Enumerable. + * + * ==== Methods for Creating a \Hash + * + * ::[]:: Returns a new hash populated with given objects. + * ::new:: Returns a new empty hash. + * ::try_convert:: Returns a new hash created from a given object. + * + * ==== Methods for Setting \Hash State + * + * #compare_by_identity:: Sets +self+ to consider only identity in comparing keys. + * #default=:: Sets the default to a given value. + * #default_proc=:: Sets the default proc to a given proc. + * #rehash:: Rebuilds the hash table by recomputing the hash index for each key. + * + * ==== Methods for Querying + * + * #any?:: Returns whether any element satisfies a given criterion. + * #compare_by_identity?:: Returns whether the hash considers only identity when comparing keys. + * #default:: Returns the default value, or the default value for a given key. + * #default_proc:: Returns the default proc. + * #empty?:: Returns whether there are no entries. + * #eql?:: Returns whether a given object is equal to +self+. + * #hash:: Returns the integer hash code. + * #has_value?:: Returns whether a given object is a value in +self+. + * #include?, #has_key?, #member?, #key?:: Returns whether a given object is a key in +self+. + * #length, #size:: Returns the count of entries. + * #value?:: Returns whether a given object is a value in +self+. + * + * ==== Methods for Comparing + * + * {#<}[#method-i-3C]:: Returns whether +self+ is a proper subset of a given object. + * {#<=}[#method-i-3C-3D]:: Returns whether +self+ is a subset of a given object. + * {#==}[#method-i-3D-3D]:: Returns whether a given object is equal to +self+. + * {#>}[#method-i-3E]:: Returns whether +self+ is a proper superset of a given object + * {#>=}[#method-i-3E-3D]:: Returns whether +self+ is a proper superset of a given object. + * + * ==== Methods for Fetching + * + * #[]:: Returns the value associated with a given key. + * #assoc:: Returns a 2-element array containing a given key and its value. + * #dig:: Returns the object in nested objects that is specified + * by a given key and additional arguments. + * #fetch:: Returns the value for a given key. + * #fetch_values:: Returns array containing the values associated with given keys. + * #key:: Returns the key for the first-found entry with a given value. + * #keys:: Returns an array containing all keys in +self+. + * #rassoc:: Returns a 2-element array consisting of the key and value + of the first-found entry having a given value. + * #values:: Returns an array containing all values in +self+/ + * #values_at:: Returns an array containing values for given keys. + * + * ==== Methods for Assigning + * + * #[]=, #store:: Associates a given key with a given value. + * #merge:: Returns the hash formed by merging each given hash into a copy of +self+. + * #merge!, #update:: Merges each given hash into +self+. + * #replace:: Replaces the entire contents of +self+ with the contents of a givan hash. + * + * ==== Methods for Deleting + * + * These methods remove entries from +self+: + * + * #clear:: Removes all entries from +self+. + * #compact!:: Removes all +nil+-valued entries from +self+. + * #delete:: Removes the entry for a given key. + * #delete_if:: Removes entries selected by a given block. + * #filter!, #select!:: Keep only those entries selected by a given block. + * #keep_if:: Keep only those entries selected by a given block. + * #reject!:: Removes entries selected by a given block. + * #shift:: Removes and returns the first entry. + * + * These methods return a copy of +self+ with some entries removed: + * + * #compact:: Returns a copy of +self+ with all +nil+-valued entries removed. + * #except:: Returns a copy of +self+ with entries removed for specified keys. + * #filter, #select:: Returns a copy of +self+ with only those entries selected by a given block. + * #reject:: Returns a copy of +self+ with entries removed as specified by a given block. + * #slice:: Returns a hash containing the entries for given keys. + * + * ==== Methods for Iterating + * #each, #each_pair:: Calls a given block with each key-value pair. + * #each_key:: Calls a given block with each key. + * #each_value:: Calls a given block with each value. + * + * ==== Methods for Converting + * + * #inspect, #to_s:: Returns a new String containing the hash entries. + * #to_a:: Returns a new array of 2-element arrays; + * each nested array contains a key-value pair from +self+. + * #to_h:: Returns +self+ if a \Hash; + * if a subclass of \Hash, returns a \Hash containing the entries from +self+. + * #to_hash:: Returns +self+. + * #to_proc:: Returns a proc that maps a given key to its value. + * + * ==== Methods for Transforming Keys and Values + * + * #transform_keys:: Returns a copy of +self+ with modified keys. + * #transform_keys!:: Modifies keys in +self+ + * #transform_values:: Returns a copy of +self+ with modified values. + * #transform_values!:: Modifies values in +self+. + * + * ==== Other Methods + * #flatten:: Returns an array that is a 1-dimensional flattening of +self+. + * #invert:: Returns a hash with the each key-value pair inverted. + * */ void Init_Hash(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - id_hash = rb_intern("hash"); - id_yield = rb_intern("yield"); - id_default = rb_intern("default"); - id_flatten_bang = rb_intern("flatten!"); + id_hash = rb_intern_const("hash"); + id_default = rb_intern_const("default"); + id_flatten_bang = rb_intern_const("flatten!"); id_hash_iter_lev = rb_make_internal_id(); rb_cHash = rb_define_class("Hash", rb_cObject); @@ -6344,7 +7186,6 @@ Init_Hash(void) rb_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0); rb_define_method(rb_cHash, "default_proc=", rb_hash_set_default_proc, 1); rb_define_method(rb_cHash, "key", rb_hash_key, 1); - rb_define_method(rb_cHash, "index", rb_hash_index, 1); rb_define_method(rb_cHash, "size", rb_hash_size, 0); rb_define_method(rb_cHash, "length", rb_hash_size, 0); rb_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0); @@ -6354,8 +7195,8 @@ Init_Hash(void) rb_define_method(rb_cHash, "each_pair", rb_hash_each_pair, 0); rb_define_method(rb_cHash, "each", rb_hash_each_pair, 0); - rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, 0); - rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, 0); + rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, -1); + rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, -1); rb_define_method(rb_cHash, "transform_values", rb_hash_transform_values, 0); rb_define_method(rb_cHash, "transform_values!", rb_hash_transform_values_bang, 0); @@ -6375,6 +7216,7 @@ Init_Hash(void) rb_define_method(rb_cHash, "reject", rb_hash_reject, 0); rb_define_method(rb_cHash, "reject!", rb_hash_reject_bang, 0); rb_define_method(rb_cHash, "slice", rb_hash_slice, -1); + rb_define_method(rb_cHash, "except", rb_hash_except, -1); rb_define_method(rb_cHash, "clear", rb_hash_clear, 0); rb_define_method(rb_cHash, "invert", rb_hash_invert, 0); rb_define_method(rb_cHash, "update", rb_hash_update, -1); @@ -6488,6 +7330,86 @@ Init_Hash(void) * so most example snippets begin by resetting the contents of ENV: * - ENV.replace replaces ENV with a new collection of entries. * - ENV.clear empties ENV. + * + * == What's Here + * + * First, what's elsewhere. \Class \ENV: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Extends {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * + * Here, class \ENV provides methods that are useful for: + * + * - {Querying}[#class-ENV-label-Methods+for+Querying] + * - {Assigning}[#class-ENV-label-Methods+for+Assigning] + * - {Deleting}[#class-ENV-label-Methods+for+Deleting] + * - {Iterating}[#class-ENV-label-Methods+for+Iterating] + * - {Converting}[#class-ENV-label-Methods+for+Converting] + * - {And more ....}[#class-ENV-label-More+Methods] + * + * === Methods for Querying + * + * - ::[]:: Returns the value for the given environment variable name if it exists: + * - ::empty?:: Returns whether \ENV is empty. + * - ::has_value?, ::value?:: Returns whether the given value is in \ENV. + * - ::include?, ::has_key?, ::key?, ::member?:: Returns whether the given name + is in \ENV. + * - ::key:: Returns the name of the first entry with the given value. + * - ::size, ::length:: Returns the number of entries. + * - ::value?:: Returns whether any entry has the given value. + * + * === Methods for Assigning + * + * - ::[]=, ::store:: Creates, updates, or deletes the named environment variable. + * - ::clear:: Removes every environment variable; returns \ENV: + * - ::update, ::merge!:: Adds to \ENV each key/value pair in the given hash. + * - ::replace:: Replaces the entire content of the \ENV + * with the name/value pairs in the given hash. + * + * === Methods for Deleting + * + * - ::delete:: Deletes the named environment variable name if it exists. + * - ::delete_if:: Deletes entries selected by the block. + * - ::keep_if:: Deletes entries not selected by the block. + * - ::reject!:: Similar to #delete_if, but returns +nil+ if no change was made. + * - ::select!, ::filter!:: Deletes entries selected by the block. + * - ::shift:: Removes and returns the first entry. + * + * === Methods for Iterating + * + * - ::each, ::each_pair:: Calls the block with each name/value pair. + * - ::each_key:: Calls the block with each name. + * - ::each_value:: Calls the block with each value. + * + * === Methods for Converting + * + * - ::assoc:: Returns a 2-element array containing the name and value + * of the named environment variable if it exists: + * - ::clone:: Returns \ENV (and issues a warning). + * - ::except:: Returns a hash of all name/value pairs except those given. + * - ::fetch:: Returns the value for the given name. + * - ::inspect:: Returns the contents of \ENV as a string. + * - ::invert:: Returns a hash whose keys are the ENV values, + and whose values are the corresponding ENV names. + * - ::keys:: Returns an array of all names. + * - ::rassoc:: Returns the name and value of the first found entry + * that has the given value. + * - ::reject:: Returns a hash of those entries not rejected by the block. + * - ::select, ::filter:: Returns a hash of name/value pairs selected by the block. + * - ::slice:: Returns a hash of the given names and their corresponding values. + * - ::to_a:: Returns the entries as an array of 2-element Arrays. + * - ::to_h:: Returns a hash of entries selected by the block. + * - ::to_hash:: Returns a hash of all entries. + * - ::to_s:: Returns the string 'ENV'. + * - ::values:: Returns all values as an array. + * - ::values_at:: Returns an array of the values for the given name. + * + * === More Methods + * + * - ::dup:: Raises an exception. + * - ::freeze:: Raises an exception. + * - ::rehash:: Returns +nil+, without modifying \ENV. + * */ /* @@ -6495,8 +7417,10 @@ Init_Hash(void) * envtbl = rb_define_class("ENV", rb_cObject); */ origenviron = environ; - envtbl = rb_obj_alloc(rb_cObject); + envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL); rb_extend_object(envtbl, rb_mEnumerable); + FL_SET_RAW(envtbl, RUBY_FL_SHAREABLE); + rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1); rb_define_singleton_method(envtbl, "fetch", env_fetch, -1); @@ -6510,6 +7434,7 @@ Init_Hash(void) rb_define_singleton_method(envtbl, "delete_if", env_delete_if, 0); rb_define_singleton_method(envtbl, "keep_if", env_keep_if, 0); rb_define_singleton_method(envtbl, "slice", env_slice, -1); + rb_define_singleton_method(envtbl, "except", env_except, -1); rb_define_singleton_method(envtbl, "clear", env_clear, 0); rb_define_singleton_method(envtbl, "reject", env_reject, 0); rb_define_singleton_method(envtbl, "reject!", env_reject_bang, 0); @@ -6528,7 +7453,6 @@ Init_Hash(void) rb_define_singleton_method(envtbl, "to_a", env_to_a, 0); rb_define_singleton_method(envtbl, "to_s", env_to_s, 0); rb_define_singleton_method(envtbl, "key", env_key, 1); - rb_define_singleton_method(envtbl, "index", env_index, 1); rb_define_singleton_method(envtbl, "size", env_size, 0); rb_define_singleton_method(envtbl, "length", env_size, 0); rb_define_singleton_method(envtbl, "empty?", env_empty_p, 0); @@ -6545,6 +7469,14 @@ Init_Hash(void) rb_define_singleton_method(envtbl, "to_h", env_to_h, 0); rb_define_singleton_method(envtbl, "assoc", env_assoc, 1); rb_define_singleton_method(envtbl, "rassoc", env_rassoc, 1); + rb_define_singleton_method(envtbl, "clone", env_clone, -1); + rb_define_singleton_method(envtbl, "dup", env_dup, 0); + + VALUE envtbl_class = rb_singleton_class(envtbl); + rb_undef_method(envtbl_class, "initialize"); + rb_undef_method(envtbl_class, "initialize_clone"); + rb_undef_method(envtbl_class, "initialize_copy"); + rb_undef_method(envtbl_class, "initialize_dup"); /* * ENV is a Hash-like accessor for environment variables. diff --git a/ruby/id_table.c b/ruby/id_table.c index f56658247..b2ba6fae8 100644 --- a/ruby/id_table.c +++ b/ruby/id_table.c @@ -7,6 +7,7 @@ #endif #if ID_TABLE_DEBUG == 0 +#undef NDEBUG #define NDEBUG #endif #include "ruby_assert.h" @@ -91,7 +92,7 @@ rb_id_table_init(struct rb_id_table *tbl, int capa) return tbl; } -struct rb_id_table * +MJIT_FUNC_EXPORTED struct rb_id_table * rb_id_table_create(size_t capa) { struct rb_id_table *tbl = ALLOC(struct rb_id_table); @@ -222,14 +223,14 @@ hash_table_show(struct rb_id_table *tbl) } #endif -int +MJIT_FUNC_EXPORTED int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp) { id_key_t key = id2key(id); int index = hash_table_index(tbl, key); if (index >= 0) { - *valp = tbl->items[index].val; + *valp = tbl->items[index].val; return TRUE; } else { @@ -252,7 +253,7 @@ rb_id_table_insert_key(struct rb_id_table *tbl, const id_key_t key, const VALUE return TRUE; } -int +MJIT_FUNC_EXPORTED int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val) { return rb_id_table_insert_key(tbl, id2key(id), val); @@ -273,9 +274,8 @@ rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_fu for (i=0; iitems[i].val, data); - assert(key != 0); + enum rb_id_table_iterator_result ret = (*func)((ID)0, tbl->items[i].val, data); + assert(ITEM_GET_KEY(tbl, i)); if (ret == ID_TABLE_REPLACE) { VALUE val = tbl->items[i].val; diff --git a/ruby/id_table.h b/ruby/id_table.h index abd9eb5f3..f3dc681d1 100644 --- a/ruby/id_table.h +++ b/ruby/id_table.h @@ -1,5 +1,7 @@ #ifndef RUBY_ID_TABLE_H #define RUBY_ID_TABLE_H 1 +#include "ruby/internal/config.h" +#include #include "ruby/ruby.h" struct rb_id_table; diff --git a/ruby/include/ruby.h b/ruby/include/ruby.h index 076b5ce25..789804b7b 100644 --- a/ruby/include/ruby.h +++ b/ruby/include/ruby.h @@ -1,28 +1,33 @@ -/********************************************************************** - - ruby.h - - - $Author$ - created at: Sun 10 12:06:15 Jun JST 2007 - - Copyright (C) 2007-2008 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_H +#ifndef RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_H 1 - +/** + * @author $Author$ + * @date Sun 10 12:06:15 Jun JST 2007 + * @copyright 2007-2008 Yukihiro Matsumoto + * @copyright 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. + */ +#define HAVE_RUBY_ATOMIC_H 1 +#define HAVE_RUBY_DEBUG_H 1 #define HAVE_RUBY_DEFINES_H 1 #define HAVE_RUBY_ENCODING_H 1 +#define HAVE_RUBY_FIBER_SCHEDULER_H 1 #define HAVE_RUBY_INTERN_H 1 #define HAVE_RUBY_IO_H 1 +#define HAVE_RUBY_MEMORY_VIEW_H 1 #define HAVE_RUBY_MISSING_H 1 +#define HAVE_RUBY_ONIGMO_H 1 #define HAVE_RUBY_ONIGURUMA_H 1 +#define HAVE_RUBY_RACTOR_H 1 +#define HAVE_RUBY_RANDOM_H 1 #define HAVE_RUBY_RE_H 1 #define HAVE_RUBY_REGEX_H 1 #define HAVE_RUBY_RUBY_H 1 #define HAVE_RUBY_ST_H 1 #define HAVE_RUBY_THREAD_H 1 +#define HAVE_RUBY_THREAD_NATIVE_H 1 #define HAVE_RUBY_UTIL_H 1 #define HAVE_RUBY_VERSION_H 1 #define HAVE_RUBY_VM_H 1 diff --git a/ruby/include/ruby/assert.h b/ruby/include/ruby/assert.h index d19d8e4e3..c9f2c3fbe 100644 --- a/ruby/include/ruby/assert.h +++ b/ruby/include/ruby/assert.h @@ -1,54 +1,234 @@ -#ifndef RUBY_ASSERT_H +#ifndef RUBY_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ASSERT_H +/** + * @file + * @author Ruby developers + * @date Wed May 18 00:21:44 JST 1994 + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + */ +#include "ruby/internal/assume.h" +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/dllexport.h" +#include "ruby/backward/2/assume.h" -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif +/* RUBY_NDEBUG is very simple: after everything described below are done, + * define it with either NDEBUG is undefined (=0) or defined (=1). It is truly + * subordinate. + * + * RUBY_DEBUG versus NDEBUG is complicated. Assertions shall be: + * + * | -UNDEBUG | -DNDEBUG + * ---------------+----------+--------- + * -URUBY_DEBUG | (*1) | disabled + * -DRUBY_DEBUG=0 | disabled | disabled + * -DRUBY_DEBUG=1 | enabled | (*2) + * -DRUBY_DEBUG | enabled | (*2) + * + * where: + * + * - (*1): Assertions shall be silently disabled, no warnings, in favour of + * commit 21991e6ca59274e41a472b5256bd3245f6596c90. + * + * - (*2): Compile-time warnings shall be issued. + */ -NORETURN(void rb_assert_failure(const char *, int, const char *, const char *)); -#ifdef RUBY_FUNCTION_NAME_STRING -# define RUBY_ASSERT_FAIL(expr) \ - rb_assert_failure(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, expr) +/** @cond INTERNAL_MACRO */ + +/* + * Pro tip: `!!RUBY_DEBUG-1` expands to... + * + * - `!!(-1)` (== `!0` == `1`) when RUBY_DEBUG is defined to be empty, + * - `(!!0)-1` (== `0-1` == `-1`) when RUBY_DEBUG is defined as 0, and + * - `(!!n)-1` (== `1-1` == `0`) when RUBY_DEBUG is defined as something else. + */ +#if ! defined(RUBY_DEBUG) +# define RBIMPL_RUBY_DEBUG 0 +#elif !!RUBY_DEBUG-1 < 0 +# define RBIMPL_RUBY_DEBUG 0 #else -# define RUBY_ASSERT_FAIL(expr) \ - rb_assert_failure(__FILE__, __LINE__, NULL, expr) +# define RBIMPL_RUBY_DEBUG 1 #endif -#define RUBY_ASSERT_MESG(expr, mesg) \ - ((expr) ? (void)0 : RUBY_ASSERT_FAIL(mesg)) -#ifdef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P -# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \ - ((RUBY_DEBUG+0) ? RUBY_ASSERT_MESG((expr), mesg) : \ - __builtin_choose_expr( \ - __builtin_constant_p(cond), \ - __builtin_choose_expr(cond, RUBY_ASSERT_MESG(expr, mesg), (void)0), \ - RUBY_ASSERT_MESG(!(cond) || (expr), mesg))) + +/* + * ISO/IEC 9899 (all past versions) says that "If NDEBUG is defined as a macro + * name at the point in the source file where is included, ..." + * which means we must not take its defined value into account. + */ +#if defined(NDEBUG) +# define RBIMPL_NDEBUG 1 #else -# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \ - RUBY_ASSERT_MESG(!((RUBY_DEBUG+0) || (cond)) || (expr), mesg) +# define RBIMPL_NDEBUG 0 #endif -#define RUBY_ASSERT(expr) RUBY_ASSERT_MESG_WHEN((!RUBY_NDEBUG+0), expr, #expr) -#define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN(cond, expr, #expr) -#define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG_WHEN(TRUE, expr, #expr) -#ifndef RUBY_DEBUG +/** @endcond */ + +/* Here we go... */ +#undef RUBY_DEBUG +#undef RUBY_NDEBUG +#undef NDEBUG +#if defined(__DOXYGEN__) +# /** Define this macro when you want assertions. */ # define RUBY_DEBUG 0 -#endif -#ifndef RUBY_NDEBUG -# ifdef NDEBUG -# define RUBY_NDEBUG 1 +# /** Define this macro when you don't want assertions. */ +# define NDEBUG +# /** This macro is basically the same as #NDEBUG */ +# define RUBY_NDEBUG 1 + +#elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 0) +# /* Assertions disabled as per request, no conflicts. */ +# define RUBY_DEBUG 0 +# define RUBY_NDEBUG 1 +# define NDEBUG + +#elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 1) +# /* Assertions enabled as per request, no conflicts. */ +# define RUBY_DEBUG 1 +# define RUBY_NDEBUG 0 +# /* keep NDEBUG undefined */ + +#elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0) +# /* The (*1) situation in avobe diagram. */ +# define RUBY_DEBUG 0 +# define RUBY_NDEBUG 1 +# define NDEBUG + +#elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 1) +# /* The (*2) situation in above diagram. */ +# define RUBY_DEBUG 1 +# define RUBY_NDEBUG 0 +# /* keep NDEBUG undefined */ + +# if defined(_MSC_VER) +# pragma message("NDEBUG is ignored because RUBY_DEBUG>0.") +# elif defined(__GNUC__) +# pragma GCC warning "NDEBUG is ignored because RUBY_DEBUG>0." # else -# define RUBY_NDEBUG 0 +# error NDEBUG is ignored because RUBY_DEBUG>0. # endif #endif +#undef RBIMPL_NDEBUG +#undef RBIMPL_RUBY_DEBUG + +/** @cond INTERNAL_MACRO */ +#define RBIMPL_ASSERT_NOTHING RBIMPL_CAST((void)0) + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_COLD() +void rb_assert_failure(const char *file, int line, const char *name, const char *expr); +RBIMPL_SYMBOL_EXPORT_END() + +#ifdef RUBY_FUNCTION_NAME_STRING +# define RBIMPL_ASSERT_FUNC RUBY_FUNCTION_NAME_STRING +#else +# define RBIMPL_ASSERT_FUNC RBIMPL_CAST((const char *)0) +#endif + +/** @endcond */ -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ +/** + * Prints the given message, and terminates the entire process abnormally. + * + * @param mesg The message to display. + */ +#define RUBY_ASSERT_FAIL(mesg) \ + rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg) + +/** + * Asserts that the expression is truthy. If not aborts with the message. + * + * @param expr What supposedly evaluates to true. + * @param mesg The message to display on failure. + */ +#define RUBY_ASSERT_MESG(expr, mesg) \ + (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg)) + +/** + * A variant of #RUBY_ASSERT that does not interface with #RUBY_DEBUG. + * + * @copydetails #RUBY_ASSERT + */ +#define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr) + +/** + * Asserts that the given expression is truthy if and only if #RUBY_DEBUG is truthy. + * + * @param expr What supposedly evaluates to true. + */ +#if RUBY_DEBUG +# define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr) +#else +# define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING #endif -} /* extern "C" { */ + +/** + * A variant of #RUBY_ASSERT that interfaces with #NDEBUG instead of + * #RUBY_DEBUG. This almost resembles `assert` C standard macro, except minor + * implementation details. + * + * @copydetails #RUBY_ASSERT + */ +/* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no + * difference any longer between this one and `RUBY_ASSERT`. */ +#if defined(NDEBUG) +# define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING +#else +# define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr) #endif +/** + * @copydoc #RUBY_ASSERT_WHEN + * @param mesg The message to display on failure. + */ +#if RUBY_DEBUG +# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg)) +#else +# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \ + ((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING) #endif + +/** + * A variant of #RUBY_ASSERT that asserts when either #RUBY_DEBUG or `cond` + * parameter is truthy. + * + * @param cond Extra condition that shall hold for assertion to take effect. + * @param expr What supposedly evaluates to true. + */ +#define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr) + +/** + * This is either #RUBY_ASSERT or #RBIMPL_ASSUME, depending on #RUBY_DEBUG. + * + * @copydetails #RUBY_ASSERT + */ +#if RUBY_DEBUG +# define RBIMPL_ASSERT_OR_ASSUME(expr) RUBY_ASSERT_ALWAYS(expr) +#elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0) +# /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */ +# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING +#elif defined(RUBY_ASSERT_NOASSUME) +# /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */ +# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING +#elif ! defined(RBIMPL_HAVE___ASSUME) +# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING +#else +# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr) +#endif + +#endif /* RUBY_ASSERT_H */ diff --git a/ruby/include/ruby/atomic.h b/ruby/include/ruby/atomic.h new file mode 100644 index 000000000..3eb80fbf7 --- /dev/null +++ b/ruby/include/ruby/atomic.h @@ -0,0 +1,890 @@ +#ifndef RUBY_ATOMIC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_ATOMIC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Atomic operations + * + * Basically, if we could assume either C11 or C++11, these macros are just + * redundant. Sadly we cannot. We have to do them ourselves. + */ + +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include /* size_t */ +#endif + +#ifdef HAVE_SYS_TYPES_H +# include /* ssize_t */ +#endif + +#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) +# pragma intrinsic(_InterlockedOr) +#elif defined(__sun) && defined(HAVE_ATOMIC_H) +# include +#endif + +#include "ruby/assert.h" +#include "ruby/backward/2/limits.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/value.h" +#include "ruby/internal/static_assert.h" +#include "ruby/internal/stdbool.h" + +/* + * Asserts that your environment supports more than one atomic types. These + * days systems tend to have such property (C11 was a standard of decades ago, + * right?) but we still support older ones. + */ +#if defined(__DOXYGEN__) || defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) +# define RUBY_ATOMIC_GENERIC_MACRO 1 +#endif + +/** + * Type that is eligible for atomic operations. Depending on your host + * platform you might have more than one such type, but we choose one of them + * anyways. + */ +#if defined(__DOXYGEN__) +using rb_atomic_t = std::atomic; +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) +typedef unsigned int rb_atomic_t; +#elif defined(HAVE_GCC_SYNC_BUILTINS) +typedef unsigned int rb_atomic_t; +#elif defined(_WIN32) +typedef LONG rb_atomic_t; +#elif defined(__sun) && defined(HAVE_ATOMIC_H) +typedef unsigned int rb_atomic_t; +#else +# error No atomic operation found +#endif + +/** + * Atomically replaces the value pointed by `var` with the result of addition + * of `val` to the old value of `var`. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to add. + * @return What was stored in `var` before the addition. + * @post `var` holds `var + val`. + */ +#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val)) + +/** + * Atomically replaces the value pointed by `var` with the result of + * subtraction of `val` to the old value of `var`. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to subtract. + * @return What was stored in `var` before the subtraction. + * @post `var` holds `var - val`. + */ +#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val)) + +/** + * Atomically replaces the value pointed by `var` with the result of + * bitwise OR between `val` and the old value of `var`. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to mix. + * @return void + * @post `var` holds `var | val`. + * @note For portability, this macro can return void. + */ +#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val)) + +/** + * Atomically replaces the value pointed by `var` with `val`. This is just an + * assignment, but you can additionally know the previous value. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to set. + * @return What was stored in `var` before the assignment. + * @post `var` holds `val`. + */ +#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val)) + +/** + * Atomic compare-and-swap. This stores `val` to `var` if and only if the + * assignment changes the value of `var` from `oldval` to `newval`. You can + * detect whether the assignment happened or not using the return value. + * + * @param var A variable of ::rb_atomic_t. + * @param oldval Expected value of `var` before the assignment. + * @param newval What you want to store at `var`. + * @retval oldval Successful assignment (`var` is now `newval`). + * @retval otherwise Something else is at `var`; not updated. + */ +#define RUBY_ATOMIC_CAS(var, oldval, newval) \ + rbimpl_atomic_cas(&(var), (oldval), (newval)) + +/** + * Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to set. + * @return void + * @post `var` holds `val`. + */ +#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to add. + * @return void + * @post `var` holds `var + val`. + */ +#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type. + * + * @param var A variable of ::rb_atomic_t. + * @param val Value to subtract. + * @return void + * @post `var` holds `var - val`. + */ +#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val)) + +/** + * Atomically increments the value pointed by `var`. + * + * @param var A variable of ::rb_atomic_t. + * @return void + * @post `var` holds `var + 1`. + */ +#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var)) + +/** + * Atomically decrements the value pointed by `var`. + * + * @param var A variable of ::rb_atomic_t. + * @return void + * @post `var` holds `var - 1`. + */ +#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var)) + +/** + * Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @return void + * @post `var` holds `var + 1`. + */ +#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var)) + +/** + * Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @return void + * @post `var` holds `var - 1`. + */ +#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var)) + +/** + * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are + * `size_t`. There are cases where ::rb_atomic_t is 32bit while `size_t` is + * 64bit. This should be used for size related operations to support such + * platforms. + * + * @param var A variable of `size_t`. + * @param val Value to set. + * @return What was stored in `var` before the assignment. + * @post `var` holds `val`. + */ +#define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \ + rbimpl_atomic_size_exchange(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @param oldval Expected value of `var` before the assignment. + * @param newval What you want to store at `var`. + * @retval oldval Successful assignment (`var` is now `newval`). + * @retval otherwise Something else is at `var`; not updated. + */ +#define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \ + rbimpl_atomic_size_cas(&(var), (oldval), (newval)) + +/** + * Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @param val Value to add. + * @return void + * @post `var` holds `var + val`. + */ +#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @param val Value to subtract. + * @return void + * @post `var` holds `var - val`. + */ +#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are + * `void*`. There are cases where ::rb_atomic_t is 32bit while `void*` is + * 64bit. This should be used for pointer related operations to support such + * platforms. + * + * @param var A variable of `void *`. + * @param val Value to set. + * @return What was stored in `var` before the assignment. + * @post `var` holds `val`. + * + * @internal + * + * :FIXME: this `(void*)` cast is evil! However `void*` is incompatible with + * some pointers, most notably function pointers. + */ +#define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \ + RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val)) + +/** + * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`. + * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `void*`. + * @param oldval Expected value of `var` before the assignment. + * @param newval What you want to store at `var`. + * @retval oldval Successful assignment (`var` is now `newval`). + * @retval otherwise Something else is at `var`; not updated. + */ +#define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \ + RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (oldval), (newval))) + +/** + * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are + * ::VALUE. There are cases where ::rb_atomic_t is 32bit while ::VALUE is + * 64bit. This should be used for pointer related operations to support such + * platforms. + * + * @param var A variable of ::VALUE. + * @param val Value to set. + * @return What was stored in `var` before the assignment. + * @post `var` holds `val`. + */ +#define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \ + rbimpl_atomic_value_exchange(&(var), (val)) + +/** + * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE. + * There are cases where ::rb_atomic_t is 32bit while ::VALUE is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `void*`. + * @param oldval Expected value of `var` before the assignment. + * @param newval What you want to store at `var`. + * @retval oldval Successful assignment (`var` is now `newval`). + * @retval otherwise Something else is at `var`; not updated. + */ +#define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \ + rbimpl_atomic_value_cas(&(var), (oldval), (newval)) + +/** @cond INTERNAL_MACRO */ +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline rb_atomic_t +rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_fetch_and_add(ptr, val); + +#elif defined(_WIN32) + return InterlockedExchangeAdd(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + /* + * `atomic_add_int_nv` takes its second argument as `int`! Meanwhile our + * `rb_atomic_t` is unsigned. We cannot pass `val` as-is. We have to + * manually check integer overflow. + */ + RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); + return atomic_add_int_nv(ptr, val) - val; + +#else +# error Unsupported platform. +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + /* + * GCC on amd64 is smart enough to detect this `__atomic_add_fetch`'s + * return value is not used, then compiles it into single `LOCK ADD` + * instruction. + */ + __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + __sync_add_and_fetch(ptr, val); + +#elif defined(_WIN32) + /* + * `InterlockedExchangeAdd` is `LOCK XADD`. It seems there also is + * `_InterlockedAdd` intrinsic in ARM Windows but not for x86? Sticking to + * `InterlockedExchangeAdd` for better portability. + */ + InterlockedExchangeAdd(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + /* Ditto for `atomic_add_int_nv`. */ + RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); + atomic_add_int(ptr, val); + +#else +# error Unsupported platform. +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_size_add(volatile size_t *ptr, size_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + __sync_add_and_fetch(ptr, val); + +#elif defined(_WIN32) && defined(_M_AMD64) + /* Ditto for `InterlockeExchangedAdd`. */ + InterlockedExchangeAdd64(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + /* Ditto for `atomic_add_int_nv`. */ + RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); + atomic_add_long(ptr, val); + +#else + RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); + + volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); + rbimpl_atomic_add(tmp, val); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_inc(volatile rb_atomic_t *ptr) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) + rbimpl_atomic_add(ptr, 1); + +#elif defined(_WIN32) + InterlockedIncrement(ptr); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + atomic_inc_uint(ptr); + +#else + rbimpl_atomic_add(ptr, 1); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_size_inc(volatile size_t *ptr) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) + rbimpl_atomic_size_add(ptr, 1); + +#elif defined(_WIN32) && defined(_M_AMD64) + InterlockedIncrement64(ptr); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + atomic_inc_ulong(ptr); + +#else + rbimpl_atomic_size_add(ptr, 1); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline rb_atomic_t +rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_fetch_and_sub(ptr, val); + +#elif defined(_WIN32) + /* rb_atomic_t is signed here! Safe to do `-val`. */ + return InterlockedExchangeAdd(ptr, -val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + /* Ditto for `rbimpl_atomic_fetch_add`. */ + const signed neg = -1; + RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); + return atomic_add_int_nv(ptr, neg * val) + val; + +#else +# error Unsupported platform. +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + __sync_sub_and_fetch(ptr, val); + +#elif defined(_WIN32) + InterlockedExchangeAdd(ptr, -val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + const signed neg = -1; + RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); + atomic_add_int(ptr, neg * val); + +#else +# error Unsupported platform. +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + __sync_sub_and_fetch(ptr, val); + +#elif defined(_WIN32) && defined(_M_AMD64) + const ssize_t neg = -1; + InterlockedExchangeAdd64(ptr, neg * val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + const signed neg = -1; + RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); + atomic_add_long(ptr, neg * val); + +#else + RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); + + volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); + rbimpl_atomic_sub(tmp, val); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_dec(volatile rb_atomic_t *ptr) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) + rbimpl_atomic_sub(ptr, 1); + +#elif defined(_WIN32) + InterlockedDecrement(ptr); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + atomic_dec_uint(ptr); + +#else + rbimpl_atomic_sub(ptr, 1); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_size_dec(volatile size_t *ptr) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) + rbimpl_atomic_size_sub(ptr, 1); + +#elif defined(_WIN32) && defined(_M_AMD64) + InterlockedDecrement64(ptr); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + atomic_dec_ulong(ptr); + +#else + rbimpl_atomic_size_sub(ptr, 1); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + __sync_or_and_fetch(ptr, val); + +#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) + _InterlockedOr(ptr, val); + +#elif defined(_WIN32) && defined(__GNUC__) + /* This was for old MinGW. Maybe not needed any longer? */ + __asm__( + "lock\n\t" + "orl\t%1, %0" + : "=m"(ptr) + : "Ir"(val)); + +#elif defined(_WIN32) && defined(_M_IX86) + __asm mov eax, ptr; + __asm mov ecx, val; + __asm lock or [eax], ecx; + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + atomic_or_uint(ptr, val); + +#else +# error Unsupported platform. +#endif +} + +/* Nobody uses this but for theoretical backwards compatibility... */ +#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) +static inline rb_atomic_t +rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val) +{ + return rbimpl_atomic_or(var, val); +} +#endif + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline rb_atomic_t +rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_lock_test_and_set(ptr, val); + +#elif defined(_WIN32) + return InterlockedExchange(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + return atomic_swap_uint(ptr, val); + +#else +# error Unsupported platform. +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline size_t +rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_lock_test_and_set(ptr, val); + +#elif defined(_WIN32) && defined(_M_AMD64) + return InterlockedExchange64(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + return atomic_swap_ulong(ptr, val); + +#else + RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); + + volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); + const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val); + return RBIMPL_CAST((size_t)ret); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void * +rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val) +{ +#if 0 + +#elif defined(InterlockedExchangePointer) + /* const_cast */ + PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); + PVOID pval = RBIMPL_CAST((PVOID)val); + return InterlockedExchangePointer(pptr, pval); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + return atomic_swap_ptr(ptr, RBIMPL_CAST((void *)val)); + +#else + RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t)); + + const size_t sval = RBIMPL_CAST((size_t)val); + volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); + const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); + return RBIMPL_CAST((void *)sret); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline VALUE +rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val) +{ + RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); + + const size_t sval = RBIMPL_CAST((size_t)val); + volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); + const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); + return RBIMPL_CAST((VALUE)sret); +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST); + +#else + /* Maybe std::atomic::store can be faster? */ + rbimpl_atomic_exchange(ptr, val); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline rb_atomic_t +rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_compare_exchange_n( + ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return oldval; + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_val_compare_and_swap(ptr, oldval, newval); + +#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) + return InterlockedCompareExchange(ptr, newval, oldval); + +#elif defined(_WIN32) + PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); + PVOID pold = RBIMPL_CAST((PVOID)oldval); + PVOID pnew = RBIMPL_CAST((PVOID)newval); + PVOID pret = InterlockedCompareExchange(pptr, pnew, pold); + return RBIMPL_CAST((rb_atomic_t)pret); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + return atomic_cas_uint(ptr, oldval, newval); + +#else +# error Unsupported platform. +#endif +} + +/* Nobody uses this but for theoretical backwards compatibility... */ +#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) +static inline rb_atomic_t +rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval) +{ + return rbimpl_atomic_cas(var, oldval, newval); +} +#endif + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline size_t +rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval) +{ +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + __atomic_compare_exchange_n( + ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return oldval; + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_val_compare_and_swap(ptr, oldval, newval); + +#elif defined(_WIN32) && defined(_M_AMD64) + return InterlockedCompareExchange64(ptr, newval, oldval); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + return atomic_cas_ulong(ptr, oldval, newval); + +#else + RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); + + volatile rb_atomic_t *tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); + return rbimpl_atomic_cas(tmp, oldval, newval); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline void * +rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval) +{ +#if 0 + +#elif defined(InterlockedExchangePointer) + /* ... Can we say that InterlockedCompareExchangePtr surly exists when + * InterlockedExchangePointer is defined? Seems so but...?*/ + PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); + PVOID pold = RBIMPL_CAST((PVOID)oldval); + PVOID pnew = RBIMPL_CAST((PVOID)newval); + return InterlockedCompareExchangePointer(pptr, pnew, pold); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + void *pold = RBIMPL_CAST((void *)oldval); + void *pnew = RBIMPL_CAST((void *)newval); + return atomic_cas_ptr(ptr, pold, pnew); + + +#else + RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t)); + + const size_t snew = RBIMPL_CAST((size_t)newval); + const size_t sold = RBIMPL_CAST((size_t)oldval); + volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); + const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); + return RBIMPL_CAST((void *)sret); + +#endif +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline VALUE +rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval) +{ + RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); + + const size_t snew = RBIMPL_CAST((size_t)newval); + const size_t sold = RBIMPL_CAST((size_t)oldval); + volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); + const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); + return RBIMPL_CAST((VALUE)sret); +} +/** @endcond */ +#endif /* RUBY_ATOMIC_H */ diff --git a/ruby/include/ruby/backward.h b/ruby/include/ruby/backward.h index 863edf0ed..e12f98ac4 100644 --- a/ruby/include/ruby/backward.h +++ b/ruby/include/ruby/backward.h @@ -1,71 +1,63 @@ -#ifndef RUBY_RUBY_BACKWARD_H +#ifndef RUBY_RUBY_BACKWARD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RUBY_BACKWARD_H 1 - -#define RClass RClassDeprecated -#ifndef __cplusplus -DEPRECATED_TYPE(("RClass is internal use only"), -struct RClass { - struct RBasic basic; -}); -#endif - -#define DECLARE_DEPRECATED_FEATURE(ver, func) \ - NORETURN(ERRORFUNC(("deprecated since "#ver), DEPRECATED(void func(void)))) +/** + * @author Ruby developers + * @copyright 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. + */ +#include "ruby/internal/value.h" +#include "ruby/internal/interpreter.h" +#include "ruby/backward/2/attributes.h" + +#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) RBIMPL_ATTR_DEPRECATED(("since " #ver)) +#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal")) /* eval.c */ -DECLARE_DEPRECATED_FEATURE(2.2, rb_disable_super); -DECLARE_DEPRECATED_FEATURE(2.2, rb_enable_super); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_disable_super(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_enable_super(); /* hash.c */ -DECLARE_DEPRECATED_FEATURE(2.2, rb_hash_iter_lev); -DECLARE_DEPRECATED_FEATURE(2.2, rb_hash_ifnone); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_iter_lev(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_ifnone(); /* string.c */ -DECLARE_DEPRECATED_FEATURE(2.2, rb_str_associate); -DECLARE_DEPRECATED_FEATURE(2.2, rb_str_associated); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associate(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associated(); /* variable.c */ -DEPRECATED(void rb_autoload(VALUE, ID, const char*)); - -/* vm.c */ -DECLARE_DEPRECATED_FEATURE(2.2, rb_clear_cache); -DECLARE_DEPRECATED_FEATURE(2.2, rb_frame_pop); - -#define DECLARE_DEPRECATED_INTERNAL_FEATURE(func) \ - NORETURN(ERRORFUNC(("deprecated internal function"), DEPRECATED(void func(void)))) +RBIMPL_ATTR_DEPRECATED_SINCE(2.5) void rb_autoload(); /* eval.c */ -NORETURN(ERRORFUNC(("internal function"), void rb_frozen_class_p(VALUE))); -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_exec_end_proc); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) void rb_frozen_class_p(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_exec_end_proc(); /* error.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error); -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error_with_enc); -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_compile_error_append); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_with_enc(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_append(); /* gc.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_gc_call_finalizer_at_exit); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_gc_call_finalizer_at_exit(); /* signal.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_trap_exit); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_trap_exit(); /* struct.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_struct_ptr); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.4) void rb_struct_ptr(); /* thread.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_clear_trace_func); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_clear_trace_func(); /* variable.c */ -DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_generic_ivar_table); -NORETURN(ERRORFUNC(("internal function"), VALUE rb_mod_const_missing(VALUE, VALUE))); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_generic_ivar_table(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) NORETURN(VALUE rb_mod_const_missing(VALUE, VALUE)); /* from version.c */ -#ifndef RUBY_SHOW_COPYRIGHT_TO_DIE -# define RUBY_SHOW_COPYRIGHT_TO_DIE 1 -#endif -#if RUBY_SHOW_COPYRIGHT_TO_DIE +#if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0) /* for source code backward compatibility */ -DEPRECATED(static inline int ruby_show_copyright_to_die(int)); +RBIMPL_ATTR_DEPRECATED_SINCE(2.4) static inline int ruby_show_copyright_to_die(int exitcode) { diff --git a/ruby/include/ruby/backward/2/assume.h b/ruby/include/ruby/backward/2/assume.h new file mode 100644 index 000000000..265421df7 --- /dev/null +++ b/ruby/include/ruby/backward/2/assume.h @@ -0,0 +1,58 @@ +#ifndef RUBY_BACKWARD2_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_ASSUME_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #ASSUME / #RB_LIKELY / #UNREACHABLE + */ +#include "ruby/internal/config.h" +#include "ruby/internal/assume.h" +#include "ruby/internal/has/builtin.h" + +#undef ASSUME /* Kill config.h definition */ +#undef UNREACHABLE /* Kill config.h definition */ +#define ASSUME RBIMPL_ASSUME /**< @old{RBIMPL_ASSUME} */ +#define UNREACHABLE RBIMPL_UNREACHABLE() /**< @old{RBIMPL_UNREACHABLE} */ +#define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN /**< @old{RBIMPL_UNREACHABLE_RETURN} */ + +/* likely */ +#if RBIMPL_HAS_BUILTIN(__builtin_expect) +/** + * Asserts that the given Boolean expression likely holds. + * + * @param x An expression that likely holds. + * + * @note Consider this macro carefully. It has been here since when CPUs were + * like babies, but contemporary processors are beasts. They are + * smarter than mare mortals like us today. Their branch predictions + * highly expectedly outperform your use of this macro. + */ +# define RB_LIKELY(x) (__builtin_expect(!!(x), 1)) + +/** + * Asserts that the given Boolean expression likely doesn't hold. + * + * @param x An expression that likely doesn't hold. + */ +# define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#else +# define RB_LIKELY(x) (x) +# define RB_UNLIKELY(x) (x) +#endif + +#endif /* RUBY_BACKWARD2_ASSUME_H */ diff --git a/ruby/include/ruby/backward/2/attributes.h b/ruby/include/ruby/backward/2/attributes.h new file mode 100644 index 000000000..73acfc9dc --- /dev/null +++ b/ruby/include/ruby/backward/2/attributes.h @@ -0,0 +1,165 @@ +#ifndef RUBY_BACKWARD2_ATTRIBUTES_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_ATTRIBUTES_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Various attribute-related macros. + * + * ### Q&A ### + * + * - Q: Why are the macros defined in this header file so inconsistent in + * style? + * + * - A: Don't know. Don't blame me. Backward compatibility is the key here. + * I'm just preserving what they have been. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/attr/alloc_size.h" +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/error.h" +#include "ruby/internal/attr/forceinline.h" +#include "ruby/internal/attr/format.h" +#include "ruby/internal/attr/maybe_unused.h" +#include "ruby/internal/attr/noinline.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/attr/restrict.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/attr/warning.h" +#include "ruby/internal/has/attribute.h" + +/* function attributes */ +#undef CONSTFUNC +#define CONSTFUNC(x) RBIMPL_ATTR_CONST() x + +#undef PUREFUNC +#define PUREFUNC(x) RBIMPL_ATTR_PURE() x + +#undef DEPRECATED +#define DEPRECATED(x) RBIMPL_ATTR_DEPRECATED(("")) x + +#undef DEPRECATED_BY +#define DEPRECATED_BY(n,x) RBIMPL_ATTR_DEPRECATED(("by: " # n)) x + +#undef DEPRECATED_TYPE +#if defined(__GNUC__) +# define DEPRECATED_TYPE(mesg, decl) \ + _Pragma("message \"DEPRECATED_TYPE is deprecated\""); \ + decl RBIMPL_ATTR_DEPRECATED(mseg) +#elif defined(_MSC_VER) +# pragma deprecated(DEPRECATED_TYPE) +# define DEPRECATED_TYPE(mesg, decl) \ + __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: " \ + "DEPRECATED_TYPE is deprecated")) \ + decl RBIMPL_ATTR_DEPRECATED(mseg) +#else +# define DEPRECATED_TYPE(mesg, decl) \ + <-<-"DEPRECATED_TYPE is deprecated"->-> +#endif + +#undef RUBY_CXX_DEPRECATED +#define RUBY_CXX_DEPRECATED(mseg) RBIMPL_ATTR_DEPRECATED((mseg)) + +#undef NOINLINE +#define NOINLINE(x) RBIMPL_ATTR_NOINLINE() x + +#ifndef MJIT_HEADER +# undef ALWAYS_INLINE +# define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x +#endif + +#undef ERRORFUNC +#define ERRORFUNC(mesg, x) RBIMPL_ATTR_ERROR(mesg) x +#if RBIMPL_HAS_ATTRIBUTE(error) +# define HAVE_ATTRIBUTE_ERRORFUNC 1 +#endif + +#undef WARNINGFUNC +#define WARNINGFUNC(mesg, x) RBIMPL_ATTR_WARNING(mesg) x +#if RBIMPL_HAS_ATTRIBUTE(warning) +# define HAVE_ATTRIBUTE_WARNINGFUNC 1 +#endif + +/* + cold attribute for code layout improvements + RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros + */ +#undef COLDFUNC +#define COLDFUNC RBIMPL_ATTR_COLD() + +#define PRINTF_ARGS(decl, string_index, first_to_check) \ + RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, (string_index), (first_to_check)) \ + decl + +#undef RUBY_ATTR_ALLOC_SIZE +#define RUBY_ATTR_ALLOC_SIZE RBIMPL_ATTR_ALLOC_SIZE + +#undef RUBY_ATTR_MALLOC +#define RUBY_ATTR_MALLOC RBIMPL_ATTR_RESTRICT() + +#undef RUBY_ATTR_RETURNS_NONNULL +#define RUBY_ATTR_RETURNS_NONNULL RBIMPL_ATTR_RETURNS_NONNULL() + +#ifndef FUNC_MINIMIZED +#define FUNC_MINIMIZED(x) x +#endif + +#ifndef FUNC_UNOPTIMIZED +#define FUNC_UNOPTIMIZED(x) x +#endif + +#ifndef RUBY_ALIAS_FUNCTION_TYPE +#define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \ + FUNC_MINIMIZED(type prot) {return (type)name args;} +#endif + +#ifndef RUBY_ALIAS_FUNCTION_VOID +#define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \ + FUNC_MINIMIZED(void prot) {name args;} +#endif + +#ifndef RUBY_ALIAS_FUNCTION +#define RUBY_ALIAS_FUNCTION(prot, name, args) \ + RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args) +#endif + +#undef RUBY_FUNC_NONNULL +#define RUBY_FUNC_NONNULL(n, x) RBIMPL_ATTR_NONNULL(n) x + +#undef NORETURN +#define NORETURN(x) RBIMPL_ATTR_NORETURN() x +#define NORETURN_STYLE_NEW + +#ifndef PACKED_STRUCT +# define PACKED_STRUCT(x) x +#endif + +#ifndef PACKED_STRUCT_UNALIGNED +# if UNALIGNED_WORD_ACCESS +# define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x) +# else +# define PACKED_STRUCT_UNALIGNED(x) x +# endif +#endif + +#undef RB_UNUSED_VAR +#define RB_UNUSED_VAR(x) x RBIMPL_ATTR_MAYBE_UNUSED() + +#endif /* RUBY_BACKWARD2_ATTRIBUTES_H */ diff --git a/ruby/include/ruby/backward/2/bool.h b/ruby/include/ruby/backward/2/bool.h new file mode 100644 index 000000000..f2fa390c8 --- /dev/null +++ b/ruby/include/ruby/backward/2/bool.h @@ -0,0 +1,36 @@ +#ifndef RUBY_BACKWARD2_BOOL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_BOOL_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines old TRUE / FALSE + */ +#include "ruby/internal/stdbool.h" + +#ifndef FALSE +# define FALSE false +#elif FALSE +# error FALSE must be false +#endif + +#ifndef TRUE +# define TRUE true +#elif ! TRUE +# error TRUE must be true +#endif + +#endif /* RUBY_BACKWARD2_BOOL_H */ diff --git a/ruby/include/ruby/backward/2/gcc_version_since.h b/ruby/include/ruby/backward/2/gcc_version_since.h new file mode 100644 index 000000000..00cc40ca5 --- /dev/null +++ b/ruby/include/ruby/backward/2/gcc_version_since.h @@ -0,0 +1,37 @@ +#ifndef RUBY_BACKWARD2_GCC_VERSION_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_GCC_VERSION_SINCE_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines old GCC_VERSION_SINCE + */ +#include "ruby/internal/compiler_since.h" + +#ifndef GCC_VERSION_SINCE +#define GCC_VERSION_SINCE(x, y, z) RBIMPL_COMPILER_SINCE(GCC, (x), (y), (z)) +#endif + +#ifndef GCC_VERSION_BEFORE +#define GCC_VERSION_BEFORE(x, y, z) \ + (RBIMPL_COMPILER_BEFORE(GCC, (x), (y), (z)) || \ + (RBIMPL_COMPILER_IS(GCC) && \ + ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ + ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ + (RBIMPL_COMPILER_VERSION_PATCH == (z)))))) +#endif + +#endif /* RUBY_BACKWARD2_GCC_VERSION_SINCE_H */ diff --git a/ruby/include/ruby/backward/2/inttypes.h b/ruby/include/ruby/backward/2/inttypes.h new file mode 100644 index 000000000..45460878b --- /dev/null +++ b/ruby/include/ruby/backward/2/inttypes.h @@ -0,0 +1,131 @@ +#ifndef RUBY_BACKWARD2_INTTYPES_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_INTTYPES_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief C99 shim for `` + */ +#include "ruby/internal/config.h" /* PRI_LL_PREFIX etc. are here */ + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "ruby/internal/value.h" /* PRI_VALUE_PREFIX is here. */ + +#ifndef PRI_INT_PREFIX +# define PRI_INT_PREFIX "" +#endif + +#ifndef PRI_LONG_PREFIX +# define PRI_LONG_PREFIX "l" +#endif + +#ifndef PRI_SHORT_PREFIX +# define PRI_SHORT_PREFIX "h" +#endif + +#ifdef PRI_64_PREFIX +# /* Take that. */ +#elif SIZEOF_LONG == 8 +# define PRI_64_PREFIX PRI_LONG_PREFIX +#elif SIZEOF_LONG_LONG == 8 +# define PRI_64_PREFIX PRI_LL_PREFIX +#endif + +#ifndef PRIdPTR +# define PRIdPTR PRI_PTR_PREFIX"d" +# define PRIiPTR PRI_PTR_PREFIX"i" +# define PRIoPTR PRI_PTR_PREFIX"o" +# define PRIuPTR PRI_PTR_PREFIX"u" +# define PRIxPTR PRI_PTR_PREFIX"x" +# define PRIXPTR PRI_PTR_PREFIX"X" +#endif + +#ifndef RUBY_PRI_VALUE_MARK +# define RUBY_PRI_VALUE_MARK "\v" +#endif + +#if defined PRIdPTR && !defined PRI_VALUE_PREFIX +# define PRIdVALUE PRIdPTR +# define PRIoVALUE PRIoPTR +# define PRIuVALUE PRIuPTR +# define PRIxVALUE PRIxPTR +# define PRIXVALUE PRIXPTR +# define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK +#else +# define PRIdVALUE PRI_VALUE_PREFIX"d" +# define PRIoVALUE PRI_VALUE_PREFIX"o" +# define PRIuVALUE PRI_VALUE_PREFIX"u" +# define PRIxVALUE PRI_VALUE_PREFIX"x" +# define PRIXVALUE PRI_VALUE_PREFIX"X" +# define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK +#endif + +#ifndef PRI_VALUE_PREFIX +# define PRI_VALUE_PREFIX "" +#endif + +#ifdef PRI_TIMET_PREFIX +# /* Take that. */ +#elif SIZEOF_TIME_T == SIZEOF_INT +# define PRI_TIMET_PREFIX +#elif SIZEOF_TIME_T == SIZEOF_LONG +# define PRI_TIMET_PREFIX "l" +#elif SIZEOF_TIME_T == SIZEOF_LONG_LONG +# define PRI_TIMET_PREFIX PRI_LL_PREFIX +#endif + +#ifdef PRI_PTRDIFF_PREFIX +# /* Take that. */ +#elif SIZEOF_PTRDIFF_T == SIZEOF_INT +# define PRI_PTRDIFF_PREFIX "" +#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG +# define PRI_PTRDIFF_PREFIX "l" +#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG +# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX +#endif + +#ifndef PRIdPTRDIFF +# define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d" +# define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i" +# define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o" +# define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u" +# define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x" +# define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X" +#endif + +#ifdef PRI_SIZE_PREFIX +# /* Take that. */ +#elif SIZEOF_SIZE_T == SIZEOF_INT +# define PRI_SIZE_PREFIX "" +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define PRI_SIZE_PREFIX "l" +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define PRI_SIZE_PREFIX PRI_LL_PREFIX +#endif + +#ifndef PRIdSIZE +# define PRIdSIZE PRI_SIZE_PREFIX"d" +# define PRIiSIZE PRI_SIZE_PREFIX"i" +# define PRIoSIZE PRI_SIZE_PREFIX"o" +# define PRIuSIZE PRI_SIZE_PREFIX"u" +# define PRIxSIZE PRI_SIZE_PREFIX"x" +# define PRIXSIZE PRI_SIZE_PREFIX"X" +#endif + +#endif /* RUBY_BACKWARD2_INTTYPES_H */ diff --git a/ruby/include/ruby/backward/2/limits.h b/ruby/include/ruby/backward/2/limits.h new file mode 100644 index 000000000..6f7021e5f --- /dev/null +++ b/ruby/include/ruby/backward/2/limits.h @@ -0,0 +1,99 @@ +#ifndef RUBY_BACKWARD2_LIMITS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_LIMITS_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Historical shim for ``. + * + * The macros in this header file are obsolescent. Does anyone really need our + * own definition of `CHAR_BIT` today? + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_LIMITS_H +# include +#endif + +#include "ruby/backward/2/long_long.h" + +#ifndef LONG_MAX +# /* assuming 32bit(2's complement) long */ +# define LONG_MAX 2147483647L +#endif + +#ifndef LONG_MIN +# define LONG_MIN (-LONG_MAX-1) +#endif + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +#ifdef LLONG_MAX +# /* Take that. */ +#elif defined(LONG_LONG_MAX) +# define LLONG_MAX LONG_LONG_MAX +#elif defined(_I64_MAX) +# define LLONG_MAX _I64_MAX +#else +# /* assuming 64bit(2's complement) long long */ +# define LLONG_MAX 9223372036854775807LL +#endif + +#ifdef LLONG_MIN +# /* Take that. */ +#elif defined(LONG_LONG_MIN) +# define LLONG_MIN LONG_LONG_MIN +#elif defined(_I64_MAX) +# define LLONG_MIN _I64_MIN +#else +# define LLONG_MIN (-LLONG_MAX-1) +#endif + +#ifdef SIZE_MAX +# /* Take that. */ +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define SIZE_MAX ULLONG_MAX +# define SIZE_MIN ULLONG_MIN +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define SIZE_MAX ULONG_MAX +# define SIZE_MIN ULONG_MIN +#elif SIZEOF_SIZE_T == SIZEOF_INT +# define SIZE_MAX UINT_MAX +# define SIZE_MIN UINT_MIN +#else +# define SIZE_MAX USHRT_MAX +# define SIZE_MIN USHRT_MIN +#endif + +#ifdef SSIZE_MAX +# /* Take that. */ +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define SSIZE_MAX LLONG_MAX +# define SSIZE_MIN LLONG_MIN +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define SSIZE_MAX LONG_MAX +# define SSIZE_MIN LONG_MIN +#elif SIZEOF_SIZE_T == SIZEOF_INT +# define SSIZE_MAX INT_MAX +# define SSIZE_MIN INT_MIN +#else +# define SSIZE_MAX SHRT_MAX +# define SSIZE_MIN SHRT_MIN +#endif + +#endif /* RUBY_BACKWARD2_LIMITS_H */ diff --git a/ruby/include/ruby/backward/2/long_long.h b/ruby/include/ruby/backward/2/long_long.h new file mode 100644 index 000000000..8e6b2743f --- /dev/null +++ b/ruby/include/ruby/backward/2/long_long.h @@ -0,0 +1,73 @@ +#ifndef RUBY_BACKWARD2_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_LONG_LONG_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines old #LONG_LONG + * + * No known compiler that can compile today's ruby lacks long long. + * Historically MSVC was one of such compiler, but it implemented long long a + * while ago (some time back in 2013). The macros are for backwards + * compatibility only. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/has/warning.h" +#include "ruby/internal/warning_push.h" + +#if defined(__DOXYGEN__) +# /** @cond INTERNAL_MACRO */ +# define HAVE_LONG_LONG 1 +# define HAVE_TRUE_LONG_LONG 1 +# /** @endcond */ +# /** @deprecated Just use `long long` directly. */ +# define LONG_LONG long long. + +#elif RBIMPL_HAS_WARNING("-Wc++11-long-long") +# define HAVE_TRUE_LONG_LONG 1 +# define LONG_LONG \ + RBIMPL_WARNING_PUSH() \ + RBIMPL_WARNING_IGNORED(-Wc++11-long-long) \ + long long \ + RBIMPL_WARNING_POP() + +#elif RBIMPL_HAS_WARNING("-Wlong-long") +# define HAVE_TRUE_LONG_LONG 1 +# define LONG_LONG \ + RBIMPL_WARNING_PUSH() \ + RBIMPL_WARNING_IGNORED(-Wlong-long) \ + long long \ + RBIMPL_WARNING_POP() + +#elif defined(HAVE_LONG_LONG) +# define HAVE_TRUE_LONG_LONG 1 +# define LONG_LONG long long + +#elif SIZEOF___INT64 > 0 +# define HAVE_LONG_LONG 1 +# define LONG_LONG __int64 +# undef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG SIZEOF___INT64 + +#else +# error Hello! Ruby developers believe this message must not happen. +# error If you encounter this message, can you file a bug report? +# error Remember to attach a detailed description of your environment. +# error Thank you! +#endif + +#endif /* RBIMPL_BACKWARD2_LONG_LONG_H */ diff --git a/ruby/include/ruby/backward/2/r_cast.h b/ruby/include/ruby/backward/2/r_cast.h new file mode 100644 index 000000000..3d0f40fd1 --- /dev/null +++ b/ruby/include/ruby/backward/2/r_cast.h @@ -0,0 +1,32 @@ +#ifndef RUBY_BACKWARD2_R_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_R_CAST_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines old R_CAST + * + * Nobody is actively using this macro. + */ +#define R_CAST(st) (struct st*) +#define RMOVED(obj) (R_CAST(RMoved)(obj)) + +#if defined(__GNUC__) +# warning R_CAST and RMOVED are deprecated +#elif defined(_MSC_VER) +# pragma message("warning: R_CAST and RMOVED are deprecated") +#endif +#endif /* RUBY_BACKWARD2_R_CAST_H */ diff --git a/ruby/include/ruby/backward/2/rmodule.h b/ruby/include/ruby/backward/2/rmodule.h new file mode 100644 index 000000000..53b37831c --- /dev/null +++ b/ruby/include/ruby/backward/2/rmodule.h @@ -0,0 +1,36 @@ +#ifndef RUBY_BACKWARD2_RMODULE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_RMODULE_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Orphan macros. + * + * These macros seems broken since at least 2011. Nobody (except ruby itself + * who is implementing the internals) could have used those macros for a while. + * Kept public as-is here to keep some theoretical backwards compatibility. + */ +#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) +#define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m) +#define RMODULE_M_TBL(m) RCLASS_M_TBL(m) +#define RMODULE_SUPER(m) RCLASS_SUPER(m) + +#if defined(__GNUC__) +# warning RMODULE_* macros are deprecated +#elif defined(_MSC_VER) +# pragma message("warning: RMODULE_* macros are deprecated") +#endif +#endif /* RUBY_BACKWARD2_RMODULE_H */ diff --git a/ruby/include/ruby/backward/2/stdalign.h b/ruby/include/ruby/backward/2/stdalign.h new file mode 100644 index 000000000..8b491bf56 --- /dev/null +++ b/ruby/include/ruby/backward/2/stdalign.h @@ -0,0 +1,30 @@ +#ifndef RUBY_BACKWARD2_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_STDALIGN_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RUBY_ALIGNAS / #RUBY_ALIGNOF + */ +#include "ruby/internal/stdalign.h" + +#undef RUBY_ALIGNAS +#undef RUBY_ALIGNOF +#define RUBY_ALIGNAS RBIMPL_ALIGNAS /**< @copydoc RBIMPL_ALIGNAS */ +#define RUBY_ALIGNOF RBIMPL_ALIGNOF /**< @copydoc RBIMPL_ALIGNOF */ + +#endif /* RUBY_BACKWARD2_STDALIGN_H */ diff --git a/ruby/include/ruby/backward/2/stdarg.h b/ruby/include/ruby/backward/2/stdarg.h new file mode 100644 index 000000000..08659fee4 --- /dev/null +++ b/ruby/include/ruby/backward/2/stdarg.h @@ -0,0 +1,69 @@ +#ifndef RUBY_BACKWARD2_STDARG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_BACKWARD2_STDARG_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines old #_ + * + * Nobody should ever use these macros any longer. No known compilers lack + * prototypes today. It's 21st century. Just forget them. + */ + +#undef _ +/** + * @deprecated Nobody practically needs this macro any longer. + * @brief This was a transition path from K&R to ANSI. + */ +#ifdef HAVE_PROTOTYPES +# define _(args) args +#else +# define _(args) () +#endif + +#undef __ +/** + * @deprecated Nobody practically needs this macro any longer. + * @brief This was a transition path from K&R to ANSI. + */ +#ifdef HAVE_STDARG_PROTOTYPES +# define __(args) args +#else +# define __(args) () +#endif + +/** + * Functions declared using this macro take arbitrary arguments, including + * void. + * + * ```CXX + * void func(ANYARGS); + * ``` + * + * This was a necessary evil when there was no such thing like function + * overloading. But it is the 21st century today. People generally need not + * use this. Just use a granular typed function. + * + * @see ruby::backward::cxxanyargs + */ +#ifdef __cplusplus +#define ANYARGS ... +#else +#define ANYARGS +#endif + +#endif /* RUBY_BACKWARD2_STDARG_H */ diff --git a/ruby/include/ruby/backward/classext.h b/ruby/include/ruby/backward/classext.h deleted file mode 100644 index 9d5747316..000000000 --- a/ruby/include/ruby/backward/classext.h +++ /dev/null @@ -1,18 +0,0 @@ -#if defined __GNUC__ -#warning use of RClass internals is deprecated -#elif defined _MSC_VER -#pragma message("warning: use of RClass internals is deprecated") -#endif - -#ifndef RUBY_BACKWARD_CLASSEXT_H -#define RUBY_BACKWARD_CLASSEXT_H 1 - -typedef struct rb_deprecated_classext_struct { - VALUE super; -} rb_deprecated_classext_t; - -#undef RCLASS_SUPER(c) -#define RCLASS_EXT(c) ((rb_deprecated_classext_t *)RCLASS(c)->ptr) -#define RCLASS_SUPER(c) (RCLASS(c)->super) - -#endif /* RUBY_BACKWARD_CLASSEXT_H */ diff --git a/ruby/include/ruby/backward/cxxanyargs.hpp b/ruby/include/ruby/backward/cxxanyargs.hpp index 3585f678b..2414b7ae6 100644 --- a/ruby/include/ruby/backward/cxxanyargs.hpp +++ b/ruby/include/ruby/backward/cxxanyargs.hpp @@ -1,48 +1,62 @@ -#ifndef RUBY_BACKWARD_CXXANYARGS_HPP // -*- C++ -*- +#ifndef RUBY_BACKWARD_CXXANYARGS_HPP //-*-C++-*-vi:ft=cpp #define RUBY_BACKWARD_CXXANYARGS_HPP /// @file -/// @brief Provides old prototypes for C++ programs. -/// @author \@shyouhei +/// @author @shyouhei /// @copyright 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. -/// @note DO NOT MODERNIZE THIS FILE! As the file name implies it is +/// @note DO NOT MODERNISE THIS FILE! As the file name implies it is /// meant to be a backwards compatibility shim. Please stick to /// C++ 98 and never use newer features, like `constexpr`. +/// @brief Provides old prototypes for C++ programs. +#include "ruby/internal/config.h" +#include "ruby/internal/intern/class.h" +#include "ruby/internal/intern/cont.h" +#include "ruby/internal/intern/hash.h" +#include "ruby/internal/intern/proc.h" +#include "ruby/internal/intern/thread.h" +#include "ruby/internal/intern/variable.h" +#include "ruby/internal/intern/vm.h" +#include "ruby/internal/iterator.h" +#include "ruby/internal/method.h" +#include "ruby/internal/value.h" +#include "ruby/internal/variable.h" +#include "ruby/backward/2/stdarg.h" +#include "ruby/st.h" + +extern "C++" { + +#ifdef HAVE_NULLPTR +#include +#endif /// @brief The main namespace. /// @note The name "ruby" might already be taken, but that must not be a /// problem because namespaces are allowed to reopen. namespace ruby { -/// @brief Backwards compatibility layer. +/// Backwards compatibility layer. namespace backward { -/// @brief Provides ANYARGS deprecation warnings. -/// -/// In C, ANYARGS means there is no function prototype. Literally anything, -/// even including nothing, can be a valid ANYARGS. So passing a correctly -/// prototyped function pointer to an ANYARGS-ed function parameter is valid, -/// at the same time passing an ANYARGS-ed function pointer to a granular typed -/// function parameter is also valid. However on the other hand in C++, -/// ANYARGS doesn't actually mean any number of arguments. C++'s ANYARGS means -/// _variadic_ number of arguments. This is incompatible with ordinal, correct -/// function prototypes. +/// Provides ANYARGS deprecation warnings. In C, ANYARGS means there is no +/// function prototype. Literally anything, even including nothing, can be a +/// valid ANYARGS. So passing a correctly prototyped function pointer to an +/// ANYARGS-ed function parameter is valid, at the same time passing an +/// ANYARGS-ed function pointer to a granular typed function parameter is also +/// valid. However on the other hand in C++, ANYARGS doesn't actually mean any +/// number of arguments. C++'s ANYARGS means _variadic_ number of arguments. +/// This is incompatible with ordinal, correct function prototypes. /// /// Luckily, function prototypes being distinct each other means they can be /// overloaded. We can provide a compatibility layer for older Ruby APIs which /// used to have ANYARGS. This namespace includes such attempts. namespace cxxanyargs { -/// @brief ANYARGS-ed function type. -typedef VALUE type(ANYARGS); - -/// @brief ANYARGS-ed function type, void variant. -typedef void void_type(ANYARGS); - -/// @brief ANYARGS-ed function type, int variant. -typedef int int_type(ANYARGS); +typedef VALUE type(ANYARGS); ///< ANYARGS-ed function type. +typedef void void_type(ANYARGS); ///< ANYARGS-ed function type, void variant. +typedef int int_type(ANYARGS); ///< ANYARGS-ed function type, int variant. +typedef VALUE onearg_type(VALUE); ///< Single-argumented function type. /// @name Hooking global variables /// @{ @@ -54,7 +68,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] e Setter function. /// @note Both functions can be nullptr. /// @see rb_define_hooked_variable() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline void rb_define_virtual_variable(const char *q, type *w, void_type *e) { @@ -64,13 +78,6 @@ rb_define_virtual_variable(const char *q, type *w, void_type *e) } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Define a function-backended global variable. -/// @param[in] q Name of the variable. -/// @param[in] w Getter function. -/// @param[in] e Setter function. -/// @note Both functions can be nullptr. -/// @see rb_define_hooked_variable() -/// @deprecated Use glanular typed overload instead. inline void rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e) { @@ -79,13 +86,6 @@ rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e) } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Define a function-backended global variable. -/// @param[in] q Name of the variable. -/// @param[in] w Getter function. -/// @param[in] e Setter function. -/// @note Both functions can be nullptr. -/// @see rb_define_hooked_variable() -/// @deprecated Use glanular typed overload instead. inline void rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e) { @@ -93,6 +93,36 @@ rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e) ::rb_define_virtual_variable(q, r, e); } +#ifdef HAVE_NULLPTR +inline void +rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, std::nullptr_t e) +{ + ::rb_define_virtual_variable(q, w, e); +} + +RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") +inline void +rb_define_virtual_variable(const char *q, type *w, std::nullptr_t e) +{ + rb_gvar_getter_t *r = reinterpret_cast(w); + ::rb_define_virtual_variable(q, r, e); +} + +inline void +rb_define_virtual_variable(const char *q, std::nullptr_t w, rb_gvar_setter_t *e) +{ + ::rb_define_virtual_variable(q, w, e); +} + +RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") +inline void +rb_define_virtual_variable(const char *q, std::nullptr_t w, void_type *e) +{ + rb_gvar_setter_t *r = reinterpret_cast(e); + ::rb_define_virtual_variable(q, w, r); +} +#endif + RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Define a function-backended global variable. /// @param[in] q Name of the variable. @@ -101,7 +131,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] r Setter function. /// @note Both functions can be nullptr. /// @see rb_define_virtual_variable() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r) { @@ -111,14 +141,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r) } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Define a function-backended global variable. -/// @param[in] q Name of the variable. -/// @param[in] w Variable storage. -/// @param[in] e Getter function. -/// @param[in] r Setter function. -/// @note Both functions can be nullptr. -/// @see rb_define_virtual_variable() -/// @deprecated Use glanular typed overload instead. inline void rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_type *r) { @@ -127,14 +149,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_typ } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Define a function-backended global variable. -/// @param[in] q Name of the variable. -/// @param[in] w Variable storage. -/// @param[in] e Getter function. -/// @param[in] r Setter function. -/// @note Both functions can be nullptr. -/// @see rb_define_virtual_variable() -/// @deprecated Use glanular typed overload instead. inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r) { @@ -142,10 +156,41 @@ rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r) ::rb_define_hooked_variable(q, w, t, r); } +#ifdef HAVE_NULLPTR +inline void +rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, std::nullptr_t r) +{ + ::rb_define_hooked_variable(q, w, e, r); +} + +RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") +inline void +rb_define_hooked_variable(const char *q, VALUE *w, type *e, std::nullptr_t r) +{ + rb_gvar_getter_t *y = reinterpret_cast(e); + ::rb_define_hooked_variable(q, w, y, r); +} + +inline void +rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, rb_gvar_setter_t *r) +{ + ::rb_define_hooked_variable(q, w, e, r); +} + +RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") +inline void +rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type *r) +{ + rb_gvar_setter_t *y = reinterpret_cast(r); + ::rb_define_hooked_variable(q, w, e, y); +} +#endif + /// @} /// @name Exceptions and tag jumps /// @{ +// RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Old way to implement iterators. /// @param[in] q A function that can yield. @@ -154,14 +199,23 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] r Passed to `e`. /// @return The return value of `q`. /// @note `e` can be nullptr. -/// @deprecated This function is obsolated since long before 2.x era. Do not +/// @deprecated This function is obsoleted since long before 2.x era. Do not /// use it any longer. rb_block_call() is provided instead. inline VALUE -rb_iterate(VALUE(*q)(VALUE), VALUE w, type *e, VALUE r) +rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r) { rb_block_call_func_t t = reinterpret_cast(e); - return ::rb_iterate(q, w, t, r); + return backward::rb_iterate_deprecated(q, w, t, r); +} + +#ifdef HAVE_NULLPTR +RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") +inline VALUE +rb_iterate(onearg_type *q, VALUE w, std::nullptr_t e, VALUE r) +{ + return backward::rb_iterate_deprecated(q, w, e, r); } +#endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Call a method with a block. @@ -173,7 +227,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] y Passed to `t` /// @return Return value of `q#w(*r,&t)` /// @note 't' can be nullptr. -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y) { @@ -181,6 +235,14 @@ rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y) return ::rb_block_call(q, w, e, r, u, y); } +#ifdef HAVE_NULLPTR +inline VALUE +rb_block_call(VALUE q, ID w, int e, const VALUE *r, std::nullptr_t t, VALUE y) +{ + return ::rb_block_call(q, w, e, r, t, y); +} +#endif + RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `rescue` clause. /// @param[in] q A function that can raise. @@ -193,7 +255,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @see rb_ensure() /// @see rb_rescue2() /// @see rb_protect() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_rescue(type *q, VALUE w, type *e, VALUE r) { @@ -217,7 +279,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @see rb_ensure() /// @see rb_rescue() /// @see rb_protect() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...) { @@ -243,7 +305,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @see rb_rescue() /// @see rb_rescue2() /// @see rb_protect() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r) { @@ -264,7 +326,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_catch(const char *q, type *w, VALUE e) { @@ -272,6 +334,14 @@ rb_catch(const char *q, type *w, VALUE e) return ::rb_catch(q, r, e); } +#ifdef HAVE_NULLPTR +inline VALUE +rb_catch(const char *q, std::nullptr_t w, VALUE e) +{ + return ::rb_catch(q, w, e); +} +#endif + RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `Kernel#catch`. /// @param[in] q The "tag" object. @@ -283,7 +353,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_catch_obj(VALUE q, type *w, VALUE e) { @@ -296,14 +366,14 @@ rb_catch_obj(VALUE q, type *w, VALUE e) /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Creates a @ref rb_cFiber instance. +/// @brief Creates a rb_cFiber instance. /// @param[in] q The fiber body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() -/// @see rb_thread_creatr() -/// @deprecated Use glanular typed overload instead. +/// @see rb_thread_create() +/// @deprecated Use granular typed overload instead. inline VALUE rb_fiber_new(type *q, VALUE w) { @@ -318,8 +388,8 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_fiber_new() -/// @see rb_thread_creatr() -/// @deprecated Use glanular typed overload instead. +/// @see rb_thread_create() +/// @deprecated Use granular typed overload instead. inline VALUE rb_proc_new(type *q, VALUE w) { @@ -335,7 +405,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() /// @see rb_fiber_new() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline VALUE rb_thread_create(type *q, void *w) { @@ -357,7 +427,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() /// @see rb_hash_foreach() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline int st_foreach(st_table *q, int_type *w, st_data_t e) { @@ -375,7 +445,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @retval 1 Element removed during traversing. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline int st_foreach_check(st_table *q, int_type *w, st_data_t e, st_data_t) { @@ -391,7 +461,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline void st_foreach_safe(st_table *q, int_type *w, st_data_t e) { @@ -407,7 +477,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline void rb_hash_foreach(VALUE q, int_type *w, VALUE e) { @@ -423,7 +493,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() -/// @deprecated Use glanular typed overload instead. +/// @deprecated Use granular typed overload instead. inline void rb_ivar_foreach(VALUE q, int_type *w, VALUE e) { @@ -433,7 +503,198 @@ rb_ivar_foreach(VALUE q, int_type *w, VALUE e) } /// @} -}}} + +/// Driver for *_define_method. ::rb_define_method function for instance takes +/// a pointer to ANYARGS-ed functions, which in fact varies 18 different +/// prototypes. We still need to preserve ANYARGS for storages but why not +/// check the consistencies if possible. In C++ a function has its own +/// prototype, which is a compile-time constant (static type) by nature. We +/// can list up all the possible input types and provide warnings for other +/// cases. This is such attempt. +namespace define_method { + +/// Type of ::rb_f_notimplement(). +typedef VALUE notimpl_type(int, const VALUE *, VALUE, VALUE); + +/// @brief Template metaprogramming to generate function prototypes. +/// @tparam T Type of method id (`ID` or `const char*` in practice). +/// @tparam F Definition driver e.g. ::rb_define_method. +template +struct driver { + + /// @brief Defines a method + /// @tparam N Arity of the function. + /// @tparam U The function in question + template + struct engine { + + /* :TODO: Following deprecation attribute renders tons of warnings (one + * per every method definitions), which is annoying. Of course + * annoyance is the core feature of deprecation warnings... But that + * could be too much, especially when the warnings happen inside of + * machine-generated programs. And SWIG is known to do such thing. + * The new (granular) API was introduced in API version 2.7. As of + * this writing the version is 2.8. Let's warn this later, some time + * during 3.x. Hopefully codes in old (ANYARGS-ed) format should be + * less than now. */ +#if (RUBY_API_VERSION_MAJOR * 100 + RUBY_API_VERSION_MINOR) >= 301 + RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") +#endif + /// @copydoc define(VALUE klass, T mid, U func) + /// @deprecated Pass correctly typed function instead. + static inline void + define(VALUE klass, T mid, type func) + { + F(klass, mid, func, N); + } + + /// @brief Defines klass#mid as func, whose arity is N. + /// @param[in] klass Where the method lives. + /// @param[in] mid Name of the method to define. + /// @param[in] func Function that implements klass#mid. + static inline void + define(VALUE klass, T mid, U func) + { + F(klass, mid, reinterpret_cast(func), N); + } + + /// @copydoc define(VALUE klass, T mid, U func) + static inline void + define(VALUE klass, T mid, notimpl_type func) + { + F(klass, mid, reinterpret_cast(func), N); + } + }; + + /// @cond INTERNAL_MACRO + template struct specific : public engine {}; + template struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; + template struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; + template struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; + template struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { + using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; + static inline void define(VALUE c, T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(c, m, reinterpret_cast(f), -1); } + }; + template struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; + /// @endcond +}; + +/* We could perhaps merge this struct into the one above using variadic + * template parameters if we could assume C++11, but sadly we cannot. */ +/// @copydoc ruby::backward::cxxanyargs::define_method::driver +template +struct driver0 { + + /// @brief Defines a method + /// @tparam N Arity of the function. + /// @tparam U The function in question + template + struct engine { + RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") + /// @copydoc define(T mid, U func) + /// @deprecated Pass correctly typed function instead. + static inline void + define(T mid, type func) + { + F(mid, func, N); + } + + /// @brief Defines Kernel#mid as func, whose arity is N. + /// @param[in] mid Name of the method to define. + /// @param[in] func Function that implements klass#mid. + static inline void + define(T mid, U func) + { + F(mid, reinterpret_cast(func), N); + } + + /// @copydoc define(T mid, U func) + /// @deprecated Pass correctly typed function instead. + static inline void + define(T mid, notimpl_type func) + { + F(mid, reinterpret_cast(func), N); + } + }; + + /// @cond INTERNAL_MACRO + template struct specific : public engine {}; + template struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; + template struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; + template struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; + template struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; + template struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { + using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; + static inline void define(T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(m, reinterpret_cast(f), -1); } + }; + template struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; + /// @endcond +}; + +struct rb_define_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_method. +struct rb_define_method_id : public driver {}; ///< Dispatches appropriate driver for ::rb_define_method_id. +struct rb_define_private_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_private_method. +struct rb_define_protected_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_protected_method. +struct rb_define_singleton_method : public driver {}; ///< Dispatches appropriate driver for ::rb_define_singleton_method. +struct rb_define_module_function : public driver {}; ///< Dispatches appropriate driver for ::rb_define_module_function. +struct rb_define_global_function : public driver0 {}; ///< Dispatches appropriate driver for ::rb_define_global_function. + +/// @brief Defines klass\#mid. +/// @param klass Where the method lives. +/// @copydetails #rb_define_global_function(mid, func, arity) +#define rb_define_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_method::specific::define(klass, mid, func) + +/// @copydoc #rb_define_method(klass, mid, func, arity) +#define rb_define_method_id(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_method_id::specific::define(klass, mid, func) + +/// @brief Defines klass\#mid and makes it private. +/// @copydetails #rb_define_method(klass, mid, func, arity) +#define rb_define_private_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_private_method::specific::define(klass, mid, func) + +/// @brief Defines klass\#mid and makes it protected. +/// @copydetails #rb_define_method +#define rb_define_protected_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method::specific::define(klass, mid, func) + +/// @brief Defines klass.mid.(klass, mid, func, arity) +/// @copydetails #rb_define_method +#define rb_define_singleton_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_singleton_method::specific::define(klass, mid, func) + +/// @brief Defines klass\#mid and makes it a module function. +/// @copydetails #rb_define_method(klass, mid, func, arity) +#define rb_define_module_function(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_module_function::specific::define(klass, mid, func) + +/// @brief Defines ::rb_mKernel \#mid. +/// @param mid Name of the defining method. +/// @param func Implementation of \#mid. +/// @param arity Arity of \#mid. +#define rb_define_global_function(mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_global_function::specific::define(mid, func) + +}}}}} using namespace ruby::backward::cxxanyargs; #endif // RUBY_BACKWARD_CXXANYARGS_HPP diff --git a/ruby/include/ruby/backward/rubyio.h b/ruby/include/ruby/backward/rubyio.h deleted file mode 100644 index a6e3a7c78..000000000 --- a/ruby/include/ruby/backward/rubyio.h +++ /dev/null @@ -1,6 +0,0 @@ -#if defined __GNUC__ -#warning use "ruby/io.h" instead of "rubyio.h" -#elif defined _MSC_VER -#pragma message("warning: use \"ruby/io.h\" instead of \"rubyio.h\"") -#endif -#include "ruby/io.h" diff --git a/ruby/include/ruby/backward/rubysig.h b/ruby/include/ruby/backward/rubysig.h deleted file mode 100644 index 58b13cab1..000000000 --- a/ruby/include/ruby/backward/rubysig.h +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** - - rubysig.h - - - $Author$ - $Date$ - created at: Wed Aug 16 01:15:38 JST 1995 - - Copyright (C) 1993-2008 Yukihiro Matsumoto - -**********************************************************************/ - -#if defined __GNUC__ -#warning rubysig.h is obsolete -#elif defined _MSC_VER -#pragma message("warning: rubysig.h is obsolete") -#endif - -#ifndef RUBYSIG_H -#define RUBYSIG_H -#include "ruby/ruby.h" - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -RUBY_SYMBOL_EXPORT_BEGIN - -#define RUBY_CRITICAL(statements) do {statements;} while (0) -#define DEFER_INTS (0) -#define ENABLE_INTS (1) -#define ALLOW_INTS do {CHECK_INTS;} while (0) -#define CHECK_INTS rb_thread_check_ints() - -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif - -#endif diff --git a/ruby/include/ruby/backward/st.h b/ruby/include/ruby/backward/st.h deleted file mode 100644 index 3e36d44cf..000000000 --- a/ruby/include/ruby/backward/st.h +++ /dev/null @@ -1,6 +0,0 @@ -#if defined __GNUC__ -#warning use "ruby/st.h" instead of bare "st.h" -#elif defined _MSC_VER -#pragma message("warning: use \"ruby/st.h\" instead of bare \"st.h\"") -#endif -#include "ruby/st.h" diff --git a/ruby/include/ruby/backward/util.h b/ruby/include/ruby/backward/util.h deleted file mode 100644 index 11d32a2da..000000000 --- a/ruby/include/ruby/backward/util.h +++ /dev/null @@ -1,6 +0,0 @@ -#if defined __GNUC__ -#warning use "ruby/util.h" instead of bare "util.h" -#elif defined _MSC_VER -#pragma message("warning: use \"ruby/util.h\" instead of bare \"util.h\"") -#endif -#include "ruby/util.h" diff --git a/ruby/include/ruby/debug.h b/ruby/include/ruby/debug.h index 8a831e61a..c88da9c43 100644 --- a/ruby/include/ruby/debug.h +++ b/ruby/include/ruby/debug.h @@ -1,97 +1,631 @@ -/********************************************************************** - - ruby/debug.h - - - $Author: ko1 $ - created at: Tue Nov 20 20:35:08 2012 - - Copyright (C) 2012 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RB_DEBUG_H +#ifndef RB_DEBUG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RB_DEBUG_H 1 +/** + * @file + * @author $Author: ko1 $ + * @date Tue Nov 20 20:35:08 2012 + * @copyright Copyright (C) 2012 Yukihiro Matsumoto + * @copyright 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. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/event.h" +#include "ruby/internal/value.h" -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -RUBY_SYMBOL_EXPORT_BEGIN +RBIMPL_SYMBOL_EXPORT_BEGIN() /* Note: This file contains experimental APIs. */ /* APIs can be replaced at Ruby 2.0.1 or later */ +/** + * @name Frame-profiling APIs + * + * @{ + */ -/* profile frames APIs */ +RBIMPL_ATTR_NONNULL((3)) +/** + * Queries mysterious "frame"s of the given range. + * + * The returned values are opaque backtrace pointers, which you are allowed to + * issue a very limited set of operations listed below. Don't call arbitrary + * ruby methods. + * + * @param[in] start Start position (0 means the topmost). + * @param[in] limit Number objects of `buff`. + * @param[out] buff Return buffer. + * @param[out] lines Return buffer. + * @return Number of objects filled into `buff`. + * @post `buff` is filled with backtrace pointers. + * @post `lines` is filled with `__LINE__` of each backtraces. + * + * @internal + * + * @shyouhei doesn't like this abuse of ::VALUE. It should have been + * `const struct rb_callable_method_entry_struct *`. + */ int rb_profile_frames(int start, int limit, VALUE *buff, int *lines); + +/** + * Queries the path of the passed backtrace. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil The frame is implemented in C etc. + * @retval otherwise Where `frame` is running. + */ VALUE rb_profile_frame_path(VALUE frame); + +/** + * Identical to rb_profile_frame_path(), except it tries to expand the + * returning path. In case the path is `require`-d from something else + * rb_profile_frame_path() can return relative paths. This one tries to avoid + * that. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval "" The frame is in C. + * @retval RUBY_Qnil Can't infer real path (inside of `eval` etc.). + * @retval otherwise Where `frame` is running. + */ VALUE rb_profile_frame_absolute_path(VALUE frame); + +/** + * Queries human-readable "label" string. This is `"
"` for the toplevel, + * `""` for evaluated ones, method name for methods, class name for + * classes. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil Can't infer the label (C etc.). + * @retval "
" The frame is global toplevel. + * @retval "" The frame is dynamic. + * @retval otherwise Label of the frame. + */ VALUE rb_profile_frame_label(VALUE frame); + +/** + * Identical to rb_profile_frame_label(), except it does not "qualify" the + * result. Consider the following backtrace: + * + * ```ruby + * def bar + * caller_locations + * end + * + * def foo + * [1].map { bar }.first + * end + * + * obj = foo.first + * obj.label # => "block in foo" + * obj.base_label # => "foo" + * ``` + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil Can't infer the label (C etc.). + * @retval "
" The frame is global toplevel. + * @retval "" The frame is dynamic. + * @retval otherwise Base label of the frame. + */ VALUE rb_profile_frame_base_label(VALUE frame); + +/** + * Identical to rb_profile_frame_label(), except it returns a qualified result. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil Can't infer the label (C etc.). + * @retval "
" The frame is global toplevel. + * @retval "" The frame is dynamic. + * @retval otherwise Qualified label of the frame. + * + * @internal + * + * As of writing there is no way to obtain this return value from a Ruby + * script. This may change in future (it took 8 years and still no progress, + * though). + */ VALUE rb_profile_frame_full_label(VALUE frame); + +/** + * Queries the first line of the method of the passed frame pointer. Can be + * handy when for instance a debugger want to display the frame in question. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil Can't infer the line (C etc.). + * @retval otherwise Line number of the method in question. + */ VALUE rb_profile_frame_first_lineno(VALUE frame); + +/** + * Queries the class path of the method that the passed frame represents. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil Can't infer the class (global toplevel etc.). + * @retval otherwise Class path as in rb_class_path(). + */ VALUE rb_profile_frame_classpath(VALUE frame); + +/** + * Queries if the method of the passed frame is a singleton class. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qtrue It is a singleton method. + * @retval RUBY_Qfalse Otherwise (normal method/non-method). + */ VALUE rb_profile_frame_singleton_method_p(VALUE frame); + +/** + * Queries the name of the method of the passed frame. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil The frame in question is not a method. + * @retval otherwise Name of the method of the frame. + */ VALUE rb_profile_frame_method_name(VALUE frame); + +/** + * Identical to rb_profile_frame_method_name(), except it "qualifies" the + * return value with its defining class. + * + * @param[in] frame What rb_profile_frames() returned. + * @retval RUBY_Qnil The frame in question is not a method. + * @retval otherwise Qualified name of the method of the frame. + */ VALUE rb_profile_frame_qualified_method_name(VALUE frame); -/* debug inspector APIs */ +/** @} */ + +/** + * @name Debug inspector APIs + * + * @{ + */ + +/** Opaque struct representing a debug inspector. */ typedef struct rb_debug_inspector_struct rb_debug_inspector_t; -typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *); +/** + * Type of the callback function passed to rb_debug_inspector_open(). + * Inspection shall happen only inside of them. The passed pointers gets + * invalidated once after the callback returns. + * + * @param[in] dc A debug context. + * @param[in,out] data What was passed to rb_debug_inspector_open(). + * @return What would be the return value of rb_debug_inspector_open(). + */ +typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void *data); + +/** + * Prepares, executes, then cleans up a debug session. + * + * @param[in] func A callback to run inside of a debug session. + * @param[in,out] data Passed as-is to `func`. + * @return What was returned from `func`. + */ VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data); + +/** + * Queries the current receiver of the passed context's upper frame. + * + * @param[in] dc A debug context. + * @param[in] index Index of the frame from top to bottom. + * @exception rb_eArgError `index` out of range. + * @return The current receiver at `index`-th frame. + */ VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index); + +/** + * Queries the current class of the passed context's upper frame. + * + * @param[in] dc A debug context. + * @param[in] index Index of the frame from top to bottom. + * @exception rb_eArgError `index` out of range. + * @return The current class at `index`-th frame. + */ VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index); + +/** + * Queries the binding of the passed context's upper frame. + * + * @param[in] dc A debug context. + * @param[in] index Index of the frame from top to bottom. + * @exception rb_eArgError `index` out of range. + * @return The binding at `index`-th frame. + */ VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index); + +/** + * Queries the instruction sequence of the passed context's upper frame. + * + * @param[in] dc A debug context. + * @param[in] index Index of the frame from top to bottom. + * @exception rb_eArgError `index` out of range. + * @retval RUBY_Qnil `index`-th frame is not in Ruby (C etc.). + * @retval otherwise An instance of `RubyVM::InstructionSequence` which + * represents the instruction sequence at `index`-th + * frame. + */ VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index); + +/** + * Queries the backtrace object of the context. This is as if you call + * `caller_locations` at the point of debugger. + * + * @param[in] dc A debug context. + * @return An array of `Thread::Backtrace::Location` which represents the + * current point of execution at `dc`. + + */ VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc); -/* Old style set_trace_func APIs */ +/** @} */ + +/** + * @name Old style set_trace_func APIs + * + * @{ + */ /* duplicated def of include/ruby/ruby.h */ -void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); -int rb_remove_event_hook(rb_event_hook_func_t func); +#include "ruby/internal/event.h" +/** + * Identical to rb_remove_event_hook(), except it additionally takes the data + * argument. This extra argument is the same as that of rb_add_event_hook(), + * and this function removes the hook which matches both arguments at once. + * + * @param[in] func A callback. + * @param[in] data What to be passed to `func`. + * @return Number of deleted event hooks. + * @note As multiple events can share the same `func` it is quite + * possible for the return value to become more than one. + */ int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data); + +/** + * Identical to rb_add_event_hook(), except its effect is limited to the passed + * thread. Other threads are not affected by this. + * + * @param[in] thval An instance of ::rb_cThread. + * @param[in] func A callback. + * @param[in] events A set of events that `func` should run. + * @param[in] data Passed as-is to `func`. + * @exception rb_eTypeError `thval` is not a thread. + */ void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); + +/** + * Identical to rb_remove_event_hook(), except it additionally takes a thread + * argument. This extra argument is the same as that of + * rb_thread_add_event_hook(), and this function removes the hook which matches + * both arguments at once. + * + * @param[in] thval An instance of ::rb_cThread. + * @param[in] func A callback. + * @exception rb_eTypeError `thval` is not a thread. + * @return Number of deleted event hooks. + * @note As multiple events can share the same `func` it is quite + * possible for the return value to become more than one. + */ int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func); + +/** + * Identical to rb_thread_remove_event_hook(), except it additionally takes the + * data argument. It can also be seen as a routine identical to + * rb_remove_event_hook_with_data(), except it additionally takes the thread. + * This function deletes hooks that satisfy all three criteria. + * + * @param[in] thval An instance of ::rb_cThread. + * @param[in] func A callback. + * @param[in] data What to be passed to `func`. + * @exception rb_eTypeError `thval` is not a thread. + * @return Number of deleted event hooks. + * @note As multiple events can share the same `func` it is quite + * possible for the return value to become more than one. + */ int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data); -/* TracePoint APIs */ +/** @} */ +/** + * @name TracePoint APIs + * + * @{ + */ + +/** + * Creates a tracepoint by registering a callback function for one or more + * tracepoint events. Once the tracepoint is created, you can use + * rb_tracepoint_enable to enable the tracepoint. + * + * @param[in] target_thread_not_supported_yet Meant for picking the + * thread in which the tracepoint is to be created. + * However, current implementation ignore this + * parameter, tracepoint is created for all threads. + * Simply specify Qnil. + * @param[in] events Event(s) to listen to. + * @param[in] func A callback function. + * @param[in,out] data Void pointer that will be passed to the callback + * function. + * + * When the callback function is called, it will be passed 2 parameters: + * 1. `VALUE tpval` - the TracePoint object from which trace args can be + * extracted. + * 1. `void *data` - A void pointer which helps to share scope with the + * callback function. + * + * It is important to note that you cannot register callbacks for normal events + * and internal events simultaneously because they are different purpose. You + * can use any Ruby APIs (calling methods and so on) on normal event hooks. + * However, in internal events, you can not use any Ruby APIs (even object + * creations). This is why we can't specify internal events by TracePoint + * directly. Limitations are MRI version specific. + * + * Example: + * + * ```CXX + * rb_tracepoint_new( + * Qnil, + * RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ, + * obj_event_i, + * data); + * ``` + * + * In this example, a callback function `obj_event_i` will be registered for + * internal events #RUBY_INTERNAL_EVENT_NEWOBJ and + * #RUBY_INTERNAL_EVENT_FREEOBJ. + */ VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void (*func)(VALUE, void *), void *data); + +/** + * Starts (enables) trace(s) defined by the passed object. A TracePoint object + * does not immediately take effect on creation. You have to explicitly call + * this API. + * + * @param[in] tpval An instance of TracePoint. + * @exception rb_eArgError A trace is already running. + * @return Undefined value. Forget this. It should have returned `void`. + * @post Trace(s) defined by `tpval` start. + */ VALUE rb_tracepoint_enable(VALUE tpval); + +/** + * Stops (disables) an already running instance of TracePoint. + * + * @param[in] tpval An instance of TracePoint. + * @return Undefined value. Forget this. It should have returned `void`. + * @post Trace(s) defined by `tpval` stop. + */ VALUE rb_tracepoint_disable(VALUE tpval); + +/** + * Queries if the passed TracePoint is up and running. + * + * @param[in] tpval An instance of TracePoint. + * @retval RUBY_Qtrue It is. + * @retval RUBY_Qfalse It isn't. + */ VALUE rb_tracepoint_enabled_p(VALUE tpval); +/** + * Type that represents a specific trace event. Roughly resembles the + * tracepoint object that is passed to the block of `TracePoint.new`: + * + * ```ruby + * TracePoint.new(*events) do |obj| + * ... # ^^^^^ Resembles this object. + * end + * ``` + */ typedef struct rb_trace_arg_struct rb_trace_arg_t; + +RBIMPL_ATTR_RETURNS_NONNULL() +/** + * Queries the current event of the passed tracepoint. + * + * @param[in] tpval An instance of TracePoint. + * @exception rb_eRuntimeError `tpval` is disabled. + * @return The current event. + * + * @internal + * + * `tpval` is a fake. There is only one instance of ::rb_trace_arg_t at one + * time. This function just returns that global variable. + */ rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval); +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the event of the passed trace. + * + * @param[in] trace_arg A trace instance. + * @return Its event. + */ rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_tracearg_event_flag(), except it returns the name of the + * event in Ruby's symbol. + * + * @param[in] trace_arg A trace instance. + * @return Its event, in Ruby level Symbol object. + */ VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the line of the point where the trace is at. + * + * @param[in] trace_arg A trace instance. + * @retval 0 The trace is not at Ruby frame. + * @return otherwise Its line number. + */ VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the file name of the point where the trace is at. + * + * @param[in] trace_arg A trace instance. + * @retval RUBY_Qnil The trace is not at Ruby frame. + * @retval otherwise Its path. + */ VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the method name of the point where the trace is at. + * + * @param[in] trace_arg A trace instance. + * @retval RUBY_Qnil There is no method. + * @retval otherwise Its method name, in Ruby level Symbol. + */ VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_tracearg_method_id(), except it returns callee id like + * rb_frame_callee(). + * + * @param[in] trace_arg A trace instance. + * @retval RUBY_Qnil There is no method. + * @retval otherwise Its method name, in Ruby level Symbol. + */ VALUE rb_tracearg_callee_id(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the class that defines the method that the passed trace is at. This + * can be different from the class of rb_tracearg_self()'s return value because + * of inheritance(s). + * + * @param[in] trace_arg A trace instance. + * @retval RUBY_Qnil There is no method. + * @retval otherwise Its method's class. + */ VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Creates a binding object of the point where the trace is at. + * + * @param[in] trace_arg A trace instance. + * @retval RUBY_Qnil The point has no binding. + * @retval otherwise Its binding. + * + * @internal + * + * @shyouhei has no idea on which situation shall this function return + * ::RUBY_Qnil. + */ VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the receiver of the point trace is at. + * + * @param[in] trace_arg A trace instance. + * @return Its receiver. + */ VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the return value that the trace represents. + * + * @param[in] trace_arg A trace instance. + * @exception rb_eRuntimeError The tracing event is not return-related. + * @return The return value. + */ VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the raised exception that the trace represents. + * + * @param[in] trace_arg A trace instance. + * @exception rb_eRuntimeError The tracing event is not exception-related. + * @return The raised exception. + */ VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries the allocated/deallocated object that the trace represents. + * + * @param[in] trace_arg A trace instance. + * @exception rb_eRuntimeError The tracing event is not GC-related. + * @return The allocated/deallocated object. + */ VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg); + +/** @} */ + +/** + * @name Postponed Job API + * + * @{ + */ + /* * Postponed Job API * rb_postponed_job_register and rb_postponed_job_register_one are * async-signal-safe and used via SIGPROF by the "stackprof" RubyGem */ + +/** + * Type of postponed jobs. + * + * @param[in,out] arg What was passed to rb_postponed_job_register(). + */ typedef void (*rb_postponed_job_func_t)(void *arg); + +/** + * Registers a postponed job. + * + * There are situations when running a ruby program is not possible. For + * instance when a program is in a signal handler; for another instance when + * the GC is busy. On such situations however, there might be needs to do + * something. We cannot but defer such operations until we are 100% sure it is + * safe to execute them. This mechanism is called postponed jobs. This + * function registers a new one. The registered job would eventually gets + * executed. + * + * @param[in] flags (Unused) reserved for future extensions. + * @param[in] func Job body. + * @param[in,out] data Passed as-is to `func`. + * @retval 0 Postponed job buffer is full. Failed. + * @retval otherwise Opaque return value. + * @post The passed job is postponed. + */ int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data); + +/** + * Identical to rb_postponed_job_register_one(), except it additionally checks + * for duplicated registration. In case the passed job is already in the + * postponed job buffer this function does nothing. + * + * @param[in] flags (Unused) reserved for future extensions. + * @param[in] func Job body. + * @param[in,out] data Passed as-is to `func`. + * @retval 0 Postponed job buffer is full. Failed. + * @retval otherwise Opaque return value. + */ int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data); +/** @} */ + +/** + * @cond INTERNAL_MACRO + * + * Anything after this are intentionally left undocumented, to honour the + * comment below. + */ + /* undocumented advanced tracing APIs */ typedef enum { @@ -103,13 +637,8 @@ typedef enum { void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); -RUBY_SYMBOL_EXPORT_END +/** @endcond */ -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_DEBUG_H */ diff --git a/ruby/include/ruby/defines.h b/ruby/include/ruby/defines.h index 5e03d4998..48184f8a1 100644 --- a/ruby/include/ruby/defines.h +++ b/ruby/include/ruby/defines.h @@ -1,135 +1,28 @@ -/************************************************ - - defines.h - - - $Author$ - created at: Wed May 18 00:21:44 JST 1994 - -************************************************/ - -#ifndef RUBY_DEFINES_H +#ifndef RUBY_DEFINES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_DEFINES_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#include "ruby/config.h" -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif - -/* function attributes */ -#ifndef CONSTFUNC -# define CONSTFUNC(x) x -#endif -#ifndef PUREFUNC -# define PUREFUNC(x) x -#endif -#ifndef DEPRECATED -# define DEPRECATED(x) x -#endif -#ifndef DEPRECATED_BY -# define DEPRECATED_BY(n,x) DEPRECATED(x) -#endif -#ifndef DEPRECATED_TYPE -# define DEPRECATED_TYPE(mesg, decl) decl -#endif -#ifndef RUBY_CXX_DEPRECATED -# define RUBY_CXX_DEPRECATED(mesg) /* nothing */ -#endif -#ifndef NOINLINE -# define NOINLINE(x) x -#endif -#ifndef ALWAYS_INLINE -# define ALWAYS_INLINE(x) x -#endif -#ifndef ERRORFUNC -# define HAVE_ATTRIBUTE_ERRORFUNC 0 -# define ERRORFUNC(mesg, x) x -#else -# define HAVE_ATTRIBUTE_ERRORFUNC 1 -#endif -#ifndef WARNINGFUNC -# define HAVE_ATTRIBUTE_WARNINGFUNC 0 -# define WARNINGFUNC(mesg, x) x -#else -# define HAVE_ATTRIBUTE_WARNINGFUNC 1 -#endif - -#ifndef GCC_VERSION_SINCE -# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) -# define GCC_VERSION_SINCE(major, minor, patchlevel) \ - ((__GNUC__ > (major)) || \ - ((__GNUC__ == (major) && \ - ((__GNUC_MINOR__ > (minor)) || \ - (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel)))))) -# else -# define GCC_VERSION_SINCE(major, minor, patchlevel) 0 -# endif -#endif -#ifndef GCC_VERSION_BEFORE -# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) -# define GCC_VERSION_BEFORE(major, minor, patchlevel) \ - ((__GNUC__ < (major)) || \ - ((__GNUC__ == (major) && \ - ((__GNUC_MINOR__ < (minor)) || \ - (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ <= (patchlevel)))))) -# else -# define GCC_VERSION_BEFORE(major, minor, patchlevel) 0 -# endif -#endif - -/* likely */ -#if __GNUC__ >= 3 -#define RB_LIKELY(x) (__builtin_expect(!!(x), 1)) -#define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0)) -#else /* __GNUC__ >= 3 */ -#define RB_LIKELY(x) (x) -#define RB_UNLIKELY(x) (x) -#endif /* __GNUC__ >= 3 */ - -/* - cold attribute for code layout improvements - RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros +/** + * @file + * @author $Author$ + * @date Wed May 18 00:21:44 JST 1994 + * @copyright 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. */ -#if defined(__clang__) || GCC_VERSION_SINCE(4, 3, 0) -#define COLDFUNC __attribute__((cold)) -#else -#define COLDFUNC -#endif -#ifdef __GNUC__ -#if defined __MINGW_PRINTF_FORMAT -#define PRINTF_ARGS(decl, string_index, first_to_check) \ - decl __attribute__((format(__MINGW_PRINTF_FORMAT, string_index, first_to_check))) -#else -#define PRINTF_ARGS(decl, string_index, first_to_check) \ - decl __attribute__((format(printf, string_index, first_to_check))) -#endif -#else -#define PRINTF_ARGS(decl, string_index, first_to_check) decl -#endif - -#ifdef __GNUC__ -#define RB_GNUC_EXTENSION __extension__ -#define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; }) -#else -#define RB_GNUC_EXTENSION -#define RB_GNUC_EXTENSION_BLOCK(x) (x) -#endif +#include "ruby/internal/config.h" /* AC_INCLUDES_DEFAULT */ #include + #ifdef HAVE_SYS_TYPES_H # include #endif + #ifdef HAVE_SYS_STAT_H # include #endif + #ifdef STDC_HEADERS # include # include @@ -138,24 +31,30 @@ extern "C" { # include # endif #endif + #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif + #ifdef HAVE_STRINGS_H # include #endif + #ifdef HAVE_INTTYPES_H # include #endif + #ifdef HAVE_STDINT_H # include #endif + #ifdef HAVE_STDALIGN_H # include #endif + #ifdef HAVE_UNISTD_H # include #endif @@ -165,376 +64,53 @@ extern "C" { #endif #ifdef RUBY_USE_SETJMPEX -#include -#endif - +# include +#endif + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/xmalloc.h" +#include "ruby/backward/2/assume.h" +#include "ruby/backward/2/attributes.h" +#include "ruby/backward/2/bool.h" +#include "ruby/backward/2/long_long.h" +#include "ruby/backward/2/stdalign.h" +#include "ruby/backward/2/stdarg.h" +#include "ruby/internal/dosish.h" #include "ruby/missing.h" +/** + * Asserts that the compilation unit includes Ruby's CAPI. This has been here + * since the very beginning (at least since version 0.49). + */ #define RUBY -#ifdef __cplusplus -# ifndef HAVE_PROTOTYPES -# define HAVE_PROTOTYPES 1 -# endif -# ifndef HAVE_STDARG_PROTOTYPES -# define HAVE_STDARG_PROTOTYPES 1 -# endif -#endif - -#undef _ -#ifdef HAVE_PROTOTYPES -# define _(args) args -#else -# define _(args) () -#endif - -#undef __ -#ifdef HAVE_STDARG_PROTOTYPES -# define __(args) args -#else -# define __(args) () -#endif - -#ifdef __cplusplus -#define ANYARGS ... +#ifdef __GNUC__ +# /** This is expanded to nothing for non-GCC compilers. */ +# define RB_GNUC_EXTENSION __extension__ +# /** This is expanded to the passed token for non-GCC compilers. */ +# define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; }) #else -#define ANYARGS -#endif - -#ifndef RUBY_SYMBOL_EXPORT_BEGIN -# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */ -# define RUBY_SYMBOL_EXPORT_END /* end */ -#endif - -RUBY_SYMBOL_EXPORT_BEGIN - -#define xmalloc ruby_xmalloc -#define xmalloc2 ruby_xmalloc2 -#define xcalloc ruby_xcalloc -#define xrealloc ruby_xrealloc -#define xrealloc2 ruby_xrealloc2 -#define xfree ruby_xfree - -#if GCC_VERSION_SINCE(4,3,0) -# define RUBY_ATTR_ALLOC_SIZE(params) __attribute__ ((alloc_size params)) -#elif defined(__has_attribute) -# if __has_attribute(alloc_size) -# define RUBY_ATTR_ALLOC_SIZE(params) __attribute__((__alloc_size__ params)) -# endif -#endif -#ifndef RUBY_ATTR_ALLOC_SIZE -# define RUBY_ATTR_ALLOC_SIZE(params) -#endif - -#ifdef __has_attribute -# if __has_attribute(malloc) -# define RUBY_ATTR_MALLOC __attribute__((__malloc__)) -# endif -#endif -#ifndef RUBY_ATTR_MALLOC -# define RUBY_ATTR_MALLOC -#endif - -#ifdef __has_attribute -# if __has_attribute(returns_nonnull) -# define RUBY_ATTR_RETURNS_NONNULL __attribute__((__returns_nonnull__)) -# endif -#endif -#ifndef RUBY_ATTR_RETURNS_NONNULL -# define RUBY_ATTR_RETURNS_NONNULL -#endif - -void *ruby_xmalloc(size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1)); -void *ruby_xmalloc2(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2)); -void *ruby_xcalloc(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2)); -void *ruby_xrealloc(void*,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); -void *ruby_xrealloc2(void*,size_t,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2,3)); -void ruby_xfree(void*); - -#ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS -#define USE_GC_MALLOC_OBJ_INFO_DETAILS 0 -#endif - -#if USE_GC_MALLOC_OBJ_INFO_DETAILS - -void *ruby_xmalloc_body(size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1)); -void *ruby_xmalloc2_body(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2)); -void *ruby_xcalloc_body(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2)); -void *ruby_xrealloc_body(void*,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); -void *ruby_xrealloc2_body(void*,size_t,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2,3)); - -#define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__) -#define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__) -#define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__) -#define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__) -#define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__) - -extern const char *ruby_malloc_info_file; -extern int ruby_malloc_info_line; - -static inline void * -ruby_xmalloc_with_location(size_t s, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xmalloc_body(s); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xmalloc2_body(s1, s2); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xcalloc_body(s1, s2); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line) -{ - void *rptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - rptr = ruby_xrealloc_body(ptr, s); - ruby_malloc_info_file = NULL; - return rptr; -} - -static inline void * -ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line) -{ - void *rptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - rptr = ruby_xrealloc2_body(ptr, s1, s2); - ruby_malloc_info_file = NULL; - return rptr; -} +# define RB_GNUC_EXTENSION +# define RB_GNUC_EXTENSION_BLOCK(x) (x) #endif -#define STRINGIZE(expr) STRINGIZE0(expr) -#ifndef STRINGIZE0 -#define STRINGIZE0(expr) #expr -#endif - -#ifdef HAVE_LONG_LONG -# define HAVE_TRUE_LONG_LONG 1 -#endif - -#if SIZEOF_LONG_LONG > 0 -# define LONG_LONG long long -#elif SIZEOF___INT64 > 0 -# define HAVE_LONG_LONG 1 -# define LONG_LONG __int64 -# undef SIZEOF_LONG_LONG -# define SIZEOF_LONG_LONG SIZEOF___INT64 -#endif - -#ifdef __CYGWIN__ -#undef _WIN32 -#endif - -#if defined(_WIN32) -/* - DOSISH mean MS-Windows style filesystem. - But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP, - ENV_IGNORECASE or CASEFOLD_FILESYSTEM. - */ -#define DOSISH 1 -# define DOSISH_DRIVE_LETTER -#endif - -#ifdef AC_APPLE_UNIVERSAL_BUILD -#undef WORDS_BIGENDIAN -#ifdef __BIG_ENDIAN__ -#define WORDS_BIGENDIAN -#endif -#endif - -#ifdef _WIN32 -#include "ruby/win32.h" -#endif - -#ifdef RUBY_EXPORT -#undef RUBY_EXTERN - -#ifndef FALSE -# define FALSE 0 -#elif FALSE -# error FALSE must be false -#endif -#ifndef TRUE -# define TRUE 1 -#elif !TRUE -# error TRUE must be true -#endif - -#endif - -#ifndef RUBY_FUNC_EXPORTED -#define RUBY_FUNC_EXPORTED -#endif - -/* These macros are used for functions which are exported only for MJIT - and NOT ensured to be exported in future versions. */ -#define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED -#define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN -#define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END - -#if defined(MJIT_HEADER) && defined(_MSC_VER) -# undef MJIT_FUNC_EXPORTED -# define MJIT_FUNC_EXPORTED static -#endif - -#ifndef RUBY_EXTERN -#define RUBY_EXTERN extern -#endif - -#ifndef EXTERN -# if defined __GNUC__ -# define EXTERN _Pragma("message \"EXTERN is deprecated, use RUBY_EXTERN instead\""); \ - RUBY_EXTERN -# elif defined _MSC_VER -# define EXTERN __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: "\ - "EXTERN is deprecated, use RUBY_EXTERN instead")); \ - RUBY_EXTERN -# else -# define EXTERN <-<-"EXTERN is deprecated, use RUBY_EXTERN instead"->-> -# endif -#endif +/** @cond INTERNAL_MACRO */ +/* :FIXME: Can someone tell us why is this macro defined here? @shyouhei + * thinks this is a truly internal macro but cannot move around because he + * doesn't understand the reason of this arrangement. */ #ifndef RUBY_MBCHAR_MAXSIZE -#define RUBY_MBCHAR_MAXSIZE INT_MAX - /* MB_CUR_MAX will not work well in C locale */ +# define RUBY_MBCHAR_MAXSIZE INT_MAX +# /* MB_CUR_MAX will not work well in C locale */ #endif #if defined(__sparc) +RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_sparc_flush_register_windows(void); -# define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows() -#else -# define FLUSH_REGISTER_WINDOWS ((void)0) -#endif - -#if defined(DOSISH) -#define PATH_SEP ";" -#else -#define PATH_SEP ":" -#endif -#define PATH_SEP_CHAR PATH_SEP[0] - -#define PATH_ENV "PATH" - -#if defined(DOSISH) -#define ENV_IGNORECASE -#endif - -#ifndef CASEFOLD_FILESYSTEM -# if defined DOSISH -# define CASEFOLD_FILESYSTEM 1 -# else -# define CASEFOLD_FILESYSTEM 0 -# endif -#endif - -#ifndef DLEXT_MAXLEN -#define DLEXT_MAXLEN 4 -#endif - -#ifndef RUBY_PLATFORM -#define RUBY_PLATFORM "unknown-unknown" -#endif - -#ifndef FUNC_MINIMIZED -#define FUNC_MINIMIZED(x) x -#endif -#ifndef FUNC_UNOPTIMIZED -#define FUNC_UNOPTIMIZED(x) x -#endif -#ifndef RUBY_ALIAS_FUNCTION_TYPE -#define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \ - FUNC_MINIMIZED(type prot) {return (type)name args;} -#endif -#ifndef RUBY_ALIAS_FUNCTION_VOID -#define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \ - FUNC_MINIMIZED(void prot) {name args;} -#endif -#ifndef RUBY_ALIAS_FUNCTION -#define RUBY_ALIAS_FUNCTION(prot, name, args) \ - RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args) -#endif -#ifndef RUBY_FUNC_NONNULL -#define RUBY_FUNC_NONNULL(n, x) x -#endif - -#ifndef UNALIGNED_WORD_ACCESS -# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(__powerpc64__) || \ - defined(__mc68020__) -# define UNALIGNED_WORD_ACCESS 1 -# else -# define UNALIGNED_WORD_ACCESS 0 -# endif -#endif -#ifndef PACKED_STRUCT -# define PACKED_STRUCT(x) x -#endif -#ifndef PACKED_STRUCT_UNALIGNED -# if UNALIGNED_WORD_ACCESS -# define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x) -# else -# define PACKED_STRUCT_UNALIGNED(x) x -# endif -#endif - -#ifndef RUBY_ALIGNAS -#define RUBY_ALIGNAS(x) /* x */ -#endif - -#ifdef RUBY_ALIGNOF -/* OK, take that definition */ -#elif defined(__cplusplus) && (__cplusplus >= 201103L) -#define RUBY_ALIGNOF alignof -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -#define RUBY_ALIGNOF _Alignof -#else -#define RUBY_ALIGNOF(type) ((size_t)offsetof(struct { char f1; type f2; }, f2)) -#endif - -#define NORETURN_STYLE_NEW 1 -#ifdef NORETURN -/* OK, take that definition */ -#elif defined(__cplusplus) && (__cplusplus >= 201103L) -#define NORETURN(x) [[ noreturn ]] x -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -#define NORETURN(x) _Noreturn x +RBIMPL_SYMBOL_EXPORT_END() +# define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows() #else -#define NORETURN(x) x +# define FLUSH_REGISTER_WINDOWS ((void)0) #endif - -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif - +/** @endcond */ #endif /* RUBY_DEFINES_H */ diff --git a/ruby/include/ruby/encoding.h b/ruby/include/ruby/encoding.h index 93939ee7d..125639370 100644 --- a/ruby/include/ruby/encoding.h +++ b/ruby/include/ruby/encoding.h @@ -1,429 +1,31 @@ -/********************************************************************** - - encoding.h - - - $Author: matz $ - created at: Thu May 24 11:49:41 JST 2007 - - Copyright (C) 2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_ENCODING_H +#ifndef RUBY_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ENCODING_H 1 - -#ifdef RUBY_INTERNAL_H -#error "Include this file before internal.h" -#endif - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#include +/** + * @file + * @author $Author: matz $ + * @date Thu May 24 11:49:41 JST 2007 + * @copyright Copyright (C) 2007 Yukihiro Matsumoto + * @copyright 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. + * @brief Encoding relates APIs. + * + * These APIs are mainly for implementing encodings themselves. Encodings are + * built on top of Ruby's core CAPIs. Though not prohibited, there can be + * relatively less rooms for things in this header file be useful when writing + * an extension library. + */ #include "ruby/ruby.h" -#include "ruby/oniguruma.h" - -RUBY_SYMBOL_EXPORT_BEGIN - -enum ruby_encoding_consts { - RUBY_ENCODING_INLINE_MAX = 127, - RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10), - RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<flags &= ~RUBY_ENCODING_MASK;\ - RBASIC(obj)->flags |= (VALUE)(i) << RUBY_ENCODING_SHIFT;\ -} while (0) -#define RB_ENCODING_SET(obj,i) rb_enc_set_index((obj), (i)) - -#define RB_ENCODING_GET_INLINED(obj) \ - (int)((RBASIC(obj)->flags & RUBY_ENCODING_MASK)>>RUBY_ENCODING_SHIFT) -#define RB_ENCODING_GET(obj) \ - (RB_ENCODING_GET_INLINED(obj) != RUBY_ENCODING_INLINE_MAX ? \ - RB_ENCODING_GET_INLINED(obj) : \ - rb_enc_get_index(obj)) - -#define RB_ENCODING_IS_ASCII8BIT(obj) (RB_ENCODING_GET_INLINED(obj) == 0) - -#define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) -#define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) -#define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) -#define ENCODING_GET(obj) RB_ENCODING_GET(obj) -#define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) -#define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN - -enum ruby_coderange_type { - RUBY_ENC_CODERANGE_UNKNOWN = 0, - RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8), - RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9), - RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)), - RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT| - RUBY_ENC_CODERANGE_VALID| - RUBY_ENC_CODERANGE_BROKEN) -}; - -static inline int -rb_enc_coderange_clean_p(int cr) -{ - return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT; -} -#define RB_ENC_CODERANGE_CLEAN_P(cr) rb_enc_coderange_clean_p(cr) -#define RB_ENC_CODERANGE(obj) ((int)RBASIC(obj)->flags & RUBY_ENC_CODERANGE_MASK) -#define RB_ENC_CODERANGE_ASCIIONLY(obj) (RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT) -#define RB_ENC_CODERANGE_SET(obj,cr) (\ - RBASIC(obj)->flags = \ - (RBASIC(obj)->flags & ~RUBY_ENC_CODERANGE_MASK) | (cr)) -#define RB_ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_SET((obj),0) - -/* assumed ASCII compatibility */ -#define RB_ENC_CODERANGE_AND(a, b) \ - ((a) == RUBY_ENC_CODERANGE_7BIT ? (b) : \ - (a) != RUBY_ENC_CODERANGE_VALID ? RUBY_ENC_CODERANGE_UNKNOWN : \ - (b) == RUBY_ENC_CODERANGE_7BIT ? RUBY_ENC_CODERANGE_VALID : (b)) - -#define RB_ENCODING_CODERANGE_SET(obj, encindex, cr) \ - do { \ - VALUE rb_encoding_coderange_obj = (obj); \ - RB_ENCODING_SET(rb_encoding_coderange_obj, (encindex)); \ - RB_ENC_CODERANGE_SET(rb_encoding_coderange_obj, (cr)); \ - } while (0) - -#define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK -#define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN -#define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT -#define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID -#define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN -#define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) -#define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) -#define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) -#define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) -#define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) -#define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) -#define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) - -typedef const OnigEncodingType rb_encoding; - -int rb_char_to_option_kcode(int c, int *option, int *kcode); - -int rb_enc_replicate(const char *, rb_encoding *); -int rb_define_dummy_encoding(const char *); -PUREFUNC(int rb_enc_dummy_p(rb_encoding *enc)); -PUREFUNC(int rb_enc_to_index(rb_encoding *enc)); -int rb_enc_get_index(VALUE obj); -void rb_enc_set_index(VALUE obj, int encindex); -int rb_enc_capable(VALUE obj); -int rb_enc_find_index(const char *name); -int rb_enc_alias(const char *alias, const char *orig); -int rb_to_encoding_index(VALUE); -rb_encoding *rb_to_encoding(VALUE); -rb_encoding *rb_find_encoding(VALUE); -rb_encoding *rb_enc_get(VALUE); -rb_encoding *rb_enc_compatible(VALUE,VALUE); -rb_encoding *rb_enc_check(VALUE,VALUE); -VALUE rb_enc_associate_index(VALUE, int); -VALUE rb_enc_associate(VALUE, rb_encoding*); -void rb_enc_copy(VALUE dst, VALUE src); - -VALUE rb_enc_str_new(const char*, long, rb_encoding*); -VALUE rb_enc_str_new_cstr(const char*, rb_encoding*); -VALUE rb_enc_str_new_static(const char*, long, rb_encoding*); -VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int); -PRINTF_ARGS(VALUE rb_enc_sprintf(rb_encoding *, const char*, ...), 2, 3); -VALUE rb_enc_vsprintf(rb_encoding *, const char*, va_list); -long rb_enc_strlen(const char*, const char*, rb_encoding*); -char* rb_enc_nth(const char*, const char*, long, rb_encoding*); -VALUE rb_obj_encoding(VALUE); -VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc); -VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc); - -VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *); -VALUE rb_str_export_to_enc(VALUE, rb_encoding *); -VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to); -VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); - -#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P -#define rb_enc_str_new(str, len, enc) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \ - rb_enc_str_new_static((str), (len), (enc)) : \ - rb_enc_str_new((str), (len), (enc)) \ -) -#define rb_enc_str_new_cstr(str, enc) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_enc_str_new_static((str), (long)strlen(str), (enc)) : \ - rb_enc_str_new_cstr((str), (enc)) \ -) -#endif - -PRINTF_ARGS(NORETURN(void rb_enc_raise(rb_encoding *, VALUE, const char*, ...)), 3, 4); - -/* index -> rb_encoding */ -rb_encoding *rb_enc_from_index(int idx); - -/* name -> rb_encoding */ -rb_encoding *rb_enc_find(const char *name); - -/* rb_encoding * -> name */ -#define rb_enc_name(enc) (enc)->name - -/* rb_encoding * -> minlen/maxlen */ -#define rb_enc_mbminlen(enc) (enc)->min_enc_len -#define rb_enc_mbmaxlen(enc) (enc)->max_enc_len - -/* -> mbclen (no error notification: 0 < ret <= e-p, no exception) */ -int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc); - -/* -> mbclen (only for valid encoding) */ -int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc); - -/* -> chlen, invalid or needmore */ -int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc); -#define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) -#define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) -#define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) -#define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) -#define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) - -/* -> 0x00..0x7f, -1 */ -int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc); - - -/* -> code (and len) or raise exception */ -unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc); - -/* prototype for obsolete function */ -unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc); -/* overriding macro */ -#define rb_enc_codepoint(p,e,enc) rb_enc_codepoint_len((p),(e),0,(enc)) -#define rb_enc_mbc_to_codepoint(p, e, enc) ONIGENC_MBC_TO_CODE((enc),(UChar*)(p),(UChar*)(e)) - -/* -> codelen>0 or raise exception */ -int rb_enc_codelen(int code, rb_encoding *enc); -/* -> 0 for invalid codepoint */ -int rb_enc_code_to_mbclen(int code, rb_encoding *enc); -#define rb_enc_code_to_mbclen(c, enc) ONIGENC_CODE_TO_MBCLEN((enc), (c)); - -/* code,ptr,encoding -> write buf */ -#define rb_enc_mbcput(c,buf,enc) ONIGENC_CODE_TO_MBC((enc),(c),(UChar*)(buf)) - -/* start, ptr, end, encoding -> prev_char */ -#define rb_enc_prev_char(s,p,e,enc) ((char *)onigenc_get_prev_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) -/* start, ptr, end, encoding -> next_char */ -#define rb_enc_left_char_head(s,p,e,enc) ((char *)onigenc_get_left_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) -#define rb_enc_right_char_head(s,p,e,enc) ((char *)onigenc_get_right_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e))) -#define rb_enc_step_back(s,p,e,n,enc) ((char *)onigenc_step_back((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e),(int)(n))) - -/* ptr, ptr, encoding -> newline_or_not */ -#define rb_enc_is_newline(p,end,enc) ONIGENC_IS_MBC_NEWLINE((enc),(UChar*)(p),(UChar*)(end)) - -#define rb_enc_isctype(c,t,enc) ONIGENC_IS_CODE_CTYPE((enc),(c),(t)) -#define rb_enc_isascii(c,enc) ONIGENC_IS_CODE_ASCII(c) -#define rb_enc_isalpha(c,enc) ONIGENC_IS_CODE_ALPHA((enc),(c)) -#define rb_enc_islower(c,enc) ONIGENC_IS_CODE_LOWER((enc),(c)) -#define rb_enc_isupper(c,enc) ONIGENC_IS_CODE_UPPER((enc),(c)) -#define rb_enc_ispunct(c,enc) ONIGENC_IS_CODE_PUNCT((enc),(c)) -#define rb_enc_isalnum(c,enc) ONIGENC_IS_CODE_ALNUM((enc),(c)) -#define rb_enc_isprint(c,enc) ONIGENC_IS_CODE_PRINT((enc),(c)) -#define rb_enc_isspace(c,enc) ONIGENC_IS_CODE_SPACE((enc),(c)) -#define rb_enc_isdigit(c,enc) ONIGENC_IS_CODE_DIGIT((enc),(c)) - -static inline int -rb_enc_asciicompat_inline(rb_encoding *enc) -{ - return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc); -} -#define rb_enc_asciicompat(enc) rb_enc_asciicompat_inline(enc) - -int rb_enc_casefold(char *to, const char *p, const char *e, rb_encoding *enc); -CONSTFUNC(int rb_enc_toupper(int c, rb_encoding *enc)); -CONSTFUNC(int rb_enc_tolower(int c, rb_encoding *enc)); -ID rb_intern3(const char*, long, rb_encoding*); -ID rb_interned_id_p(const char *, long, rb_encoding *); -int rb_enc_symname_p(const char*, rb_encoding*); -int rb_enc_symname2_p(const char*, long, rb_encoding*); -int rb_enc_str_coderange(VALUE); -long rb_str_coderange_scan_restartable(const char*, const char*, rb_encoding*, int*); -int rb_enc_str_asciionly_p(VALUE); -#define rb_enc_str_asciicompat_p(str) rb_enc_asciicompat(rb_enc_get(str)) -VALUE rb_enc_from_encoding(rb_encoding *enc); -PUREFUNC(int rb_enc_unicode_p(rb_encoding *enc)); -rb_encoding *rb_ascii8bit_encoding(void); -rb_encoding *rb_utf8_encoding(void); -rb_encoding *rb_usascii_encoding(void); -rb_encoding *rb_locale_encoding(void); -rb_encoding *rb_filesystem_encoding(void); -rb_encoding *rb_default_external_encoding(void); -rb_encoding *rb_default_internal_encoding(void); -#ifndef rb_ascii8bit_encindex -CONSTFUNC(int rb_ascii8bit_encindex(void)); -#endif -#ifndef rb_utf8_encindex -CONSTFUNC(int rb_utf8_encindex(void)); -#endif -#ifndef rb_usascii_encindex -CONSTFUNC(int rb_usascii_encindex(void)); -#endif -int rb_locale_encindex(void); -int rb_filesystem_encindex(void); -VALUE rb_enc_default_external(void); -VALUE rb_enc_default_internal(void); -void rb_enc_set_default_external(VALUE encoding); -void rb_enc_set_default_internal(VALUE encoding); -VALUE rb_locale_charmap(VALUE klass); -long rb_memsearch(const void*,long,const void*,long,rb_encoding*); -char *rb_enc_path_next(const char *,const char *,rb_encoding*); -char *rb_enc_path_skip_prefix(const char *,const char *,rb_encoding*); -char *rb_enc_path_last_separator(const char *,const char *,rb_encoding*); -char *rb_enc_path_end(const char *,const char *,rb_encoding*); -const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc); -const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc); -ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc); -VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc); - -RUBY_EXTERN VALUE rb_cEncoding; - -/* econv stuff */ - -typedef enum { - econv_invalid_byte_sequence, - econv_undefined_conversion, - econv_destination_buffer_full, - econv_source_buffer_empty, - econv_finished, - econv_after_output, - econv_incomplete_input -} rb_econv_result_t; - -typedef struct rb_econv_t rb_econv_t; - -VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts); -int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding); - -int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags); -int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts); - -rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags); -rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts); - -rb_econv_result_t rb_econv_convert(rb_econv_t *ec, - const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, - unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, - int flags); -void rb_econv_close(rb_econv_t *ec); - -/* result: 0:success -1:failure */ -int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname); - -/* result: 0:success -1:failure */ -int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name); -int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name); - -VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags); - -/* result: 0:success -1:failure */ -int rb_econv_insert_output(rb_econv_t *ec, - const unsigned char *str, size_t len, const char *str_encoding); - -/* encoding that rb_econv_insert_output doesn't need conversion */ -const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); - -/* raise an error if the last rb_econv_convert is error */ -void rb_econv_check_error(rb_econv_t *ec); - -/* returns an exception object or nil */ -VALUE rb_econv_make_exception(rb_econv_t *ec); - -int rb_econv_putbackable(rb_econv_t *ec); -void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); - -/* returns the corresponding ASCII compatible encoding for encname, - * or NULL if encname is not ASCII incompatible encoding. */ -const char *rb_econv_asciicompat_encoding(const char *encname); - -VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags); -VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags); -VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags); -VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags); -VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags); - -void rb_econv_binmode(rb_econv_t *ec); - -enum ruby_econv_flag_type { -/* flags for rb_econv_open */ - RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff, - - RUBY_ECONV_INVALID_MASK = 0x0000000f, - RUBY_ECONV_INVALID_REPLACE = 0x00000002, - - RUBY_ECONV_UNDEF_MASK = 0x000000f0, - RUBY_ECONV_UNDEF_REPLACE = 0x00000020, - RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, - - RUBY_ECONV_DECORATOR_MASK = 0x0000ff00, - RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00, - RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, - RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000, - - RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, - RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000, - RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, - RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000, - RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000, - - RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, - RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000, - - RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR = -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) - RUBY_ECONV_CRLF_NEWLINE_DECORATOR, -#else - 0, -#endif -#define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK -#define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK -#define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE -#define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK -#define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE -#define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF -#define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK -#define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK -#define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK -#define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK -#define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR -#define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR -#define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR -#define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR -#define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR -#define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK -#define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR -#define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR -/* end of flags for rb_econv_open */ - -/* flags for rb_econv_convert */ - RUBY_ECONV_PARTIAL_INPUT = 0x00010000, - RUBY_ECONV_AFTER_OUTPUT = 0x00020000, -#define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT -#define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT -/* end of flags for rb_econv_convert */ -RUBY_ECONV_FLAGS_PLACEHOLDER}; - -RUBY_SYMBOL_EXPORT_END -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +#include "ruby/internal/encoding/coderange.h" +#include "ruby/internal/encoding/ctype.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/encoding/pathname.h" +#include "ruby/internal/encoding/re.h" +#include "ruby/internal/encoding/sprintf.h" +#include "ruby/internal/encoding/string.h" +#include "ruby/internal/encoding/symbol.h" +#include "ruby/internal/encoding/transcode.h" #endif /* RUBY_ENCODING_H */ diff --git a/ruby/include/ruby/fiber/scheduler.h b/ruby/include/ruby/fiber/scheduler.h new file mode 100644 index 000000000..3ea52beb9 --- /dev/null +++ b/ruby/include/ruby/fiber/scheduler.h @@ -0,0 +1,336 @@ +#ifndef RUBY_FIBER_SCHEDULER_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_FIBER_SCHEDULER_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @brief Scheduler APIs. + */ +#include "ruby/internal/config.h" + +#include + +#ifdef STDC_HEADERS +#include /* size_t */ +#endif + +#include "ruby/ruby.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/arithmetic.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +struct timeval; + +/** + * Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should + * be used to safely capture results from system calls like `read` and `write`. + * + * You should use `rb_fiber_scheduler_io_result_apply` to unpack the result of + * this value and update `int errno`. + * + * You should not directly try to interpret the result value as it is considered + * an opaque representation. However, the general representation is an integer + * in the range of `[-int errno, size_t size]`. Linux generally restricts the + * result of system calls like `read` and `write` to `<= 2^31` which means this + * will typically fit within a single FIXNUM. + * + * @param[in] result The result of the system call. + * @param[in] error The value of `errno`. + * @return A `VALUE` which contains the result and/or errno. + */ +static inline VALUE +rb_fiber_scheduler_io_result(ssize_t result, int error) { + if (result == -1) { + return RB_INT2NUM(-error); + } else { + return RB_SIZE2NUM(result); + } +} + +/** + * Apply an io result to the local thread, returning the value of the original + * system call that created it and updating `int errno`. + * + * You should not directly try to interpret the result value as it is considered + * an opaque representation. + * + * @param[in] result The `VALUE` which contains an errno and/or result size. + * @post Updates `int errno` with the value if negative. + * @return The original result of the system call. + */ +static inline ssize_t +rb_fiber_scheduler_io_result_apply(VALUE result) { + if (RB_FIXNUM_P(result) && RB_NUM2INT(result) < 0) { + errno = -RB_NUM2INT(result); + return -1; + } else { + return RB_NUM2SIZE(result); + } +} + +/** + * Queries the current scheduler of the current thread that is calling this + * function. + * + * @retval RUBY_Qnil No scheduler has been set so far to this thread (which + * is the default). + * @retval otherwise The scheduler that was last set for the current thread + * with rb_fiber_scheduler_set(). + */ +VALUE rb_fiber_scheduler_get(void); + +/** + * Destructively assigns the passed scheduler to that of the current thread + * that is calling this function. If the scheduler is set, non-blocking fibers + * (created by `Fiber.new` with `blocking: false`, or by `Fiber.schedule`) call + * that scheduler's hook methods on potentially blocking operations, and the + * current thread will call scheduler's `#close` method on finalisation + * (allowing the scheduler to properly manage all non-finished fibers). + * `scheduler` can be an object of any class corresponding to + * `Fiber::SchedulerInterface`. Its implementation is up to the user. + * + * @param[in] scheduler The scheduler to set. + * @exception rb_eArgError `scheduler` does not conform the interface. + * @post Current thread's scheduler is `scheduler`. + */ +VALUE rb_fiber_scheduler_set(VALUE scheduler); + +/** + * Identical to rb_fiber_scheduler_get(), except it also returns ::RUBY_Qnil in + * case of a blocking fiber. As blocking fibers do not participate schedulers' + * scheduling this function can be handy. + * + * @retval RUBY_Qnil No scheduler is in effect. + * @retval otherwise The scheduler that is in effect, if any. + */ +VALUE rb_fiber_scheduler_current(void); + +/** + * Identical to rb_fiber_scheduler_current(), except it queries for that of the + * passed thread instead of the implicit current one. + * + * @param[in] thread Target thread. + * @exception rb_eTypeError `thread` is not a thread. + * @retval RUBY_Qnil No scheduler is in effect in `thread`. + * @retval otherwise The scheduler that is in effect in `thread`. + */ +VALUE rb_fiber_scheduler_current_for_thread(VALUE thread); + +/** + * Converts the passed timeout to an expression that rb_fiber_scheduler_block() + * etc. expects. + * + * @param[in] timeout A duration (can be `NULL`). + * @retval RUBY_Qnil No timeout (blocks indefinitely). + * @retval otherwise A timeout object. + */ +VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout); + +/** + * Closes the passed scheduler object. This expects the scheduler to wait for + * all fibers. Thus the scheduler's main loop tends to start here. + * + * @param[in] scheduler Target scheduler. + * @return What `scheduler.close` returns. + */ +VALUE rb_fiber_scheduler_close(VALUE scheduler); + +/** + * Nonblocking `sleep`. Depending on scheduler implementation, this for + * instance switches to another fiber etc. + * + * @param[in] scheduler Target scheduler. + * @param[in] duration Passed as-is to `scheduler.kernel_sleep`. + * @return What `scheduler.kernel_sleep` returns. + */ +VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration); + +/** + * Identical to rb_fiber_scheduler_kernel_sleep(), except it can pass multiple + * arguments. + * + * @param[in] scheduler Target scheduler. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed as-is to `scheduler.kernel_sleep` + * @return What `scheduler.kernel_sleep` returns. + */ +VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv); + +/* Description TBW */ +#if 0 +VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message); +VALUE rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv); +int rb_fiber_scheduler_supports_process_wait(VALUE scheduler); +#endif + +/** + * Nonblocking `waitpid`. Depending on scheduler implementation, this for + * instance switches to another fiber etc. + * + * @param[in] scheduler Target scheduler. + * @param[in] pid Process ID to wait. + * @param[in] flags Wait flags, e.g. `WUNTRACED`. + * @return What `scheduler.process_wait` returns. + */ +VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags); + +/** + * Nonblocking wait for the passed "blocker", which is for instance + * `Thread.join` or `Mutex.lock`. Depending on scheduler implementation, this + * for instance switches to another fiber etc. + * + * @param[in] scheduler Target scheduler. + * @param[in] blocker What blocks the current fiber. + * @param[in] timeout Numeric timeout. + * @return What `scheduler.block` returns. + */ +VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout); + +/** + * Wakes up a fiber previously blocked using rb_fiber_scheduler_block(). + * + * @param[in] scheduler Target scheduler. + * @param[in] blocker What was awaited for. + * @param[in] fiber What to unblock. + * @return What `scheduler.unblock` returns. + */ +VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber); + +/** + * Nonblocking version of rb_io_wait(). Depending on scheduler implementation, + * this for instance switches to another fiber etc. + * + * The "events" here is a Ruby level integer, which is an OR-ed value of + * `IO::READABLE`, `IO::WRITABLE`, and `IO::PRIORITY`. + * + * @param[in] scheduler Target scheduler. + * @param[in] io An io object to wait. + * @param[in] events An integer set of interests. + * @param[in] timeout Numeric timeout. + * @return What `scheduler.io_wait` returns. + */ +VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout); + +/** + * Nonblocking wait until the passed IO is ready for reading. This is a + * special case of rb_fiber_scheduler_io_wait(), where the interest is + * `IO::READABLE` and timeout is never. + * + * @param[in] scheduler Target scheduler. + * @param[in] io An io object to wait. + * @return What `scheduler.io_wait` returns. + */ +VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io); + +/** + * Nonblocking wait until the passed IO is ready for writing. This is a + * special case of rb_fiber_scheduler_io_wait(), where the interest is + * `IO::WRITABLE` and timeout is never. + * + * @param[in] scheduler Target scheduler. + * @param[in] io An io object to wait. + * @return What `scheduler.io_wait` returns. + */ +VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io); + +/** + * Nonblocking read from the passed IO. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. + * @return otherwise What `scheduler.io_read` returns `[-errno, size]`. + */ +VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length); + +/** + * Nonblocking write to the passed IO. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. + * @return otherwise What `scheduler.io_write` returns `[-errno, size]`. + */ +VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length); + +/** + * Nonblocking read from the passed IO at the specified offset. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. + * @param[in] offset The offset in the given IO to read the data from. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. + * @return otherwise What `scheduler.io_read` returns. + */ +VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); + +/** + * Nonblocking write to the passed IO at the specified offset. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. + * @param[in] offset The offset in the given IO to write the data to. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. + * @return otherwise What `scheduler.io_write` returns. + */ +VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); + +/** + * Nonblocking read from the passed IO using a native buffer. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. + * @return otherwise What `scheduler.io_read` returns. + */ +VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length); + +/** + * Nonblocking write to the passed IO using a native buffer. + * + * @param[in] scheduler Target scheduler. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. + * @return otherwise What `scheduler.io_write` returns. + */ +VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length); + +/** + * Nonblocking close the given IO. + * + * @param[in] scheduler Target scheduler. + * @param[in] io An io object to close. + * @retval RUBY_Qundef `scheduler` doesn't have `#io_close`. + * @return otherwise What `scheduler.io_close` returns. + */ +VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); + +/** + * Nonblocking DNS lookup. + * + * @param[in] scheduler Target scheduler. + * @param[in] hostname A host name to query. + * @retval RUBY_Qundef `scheduler` doesn't have `#address_resolve`. + * @return otherwise What `scheduler.address_resolve` returns. + */ +VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_FIBER_SCHEDULER_H */ diff --git a/ruby/include/ruby/intern.h b/ruby/include/ruby/intern.h index 2f60fb569..2480e2e70 100644 --- a/ruby/include/ruby/intern.h +++ b/ruby/include/ruby/intern.h @@ -1,1230 +1,64 @@ -/********************************************************************** - - intern.h - - - $Author$ - created at: Thu Jun 10 14:22:17 JST 1993 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -#ifndef RUBY_INTERN_H +#ifndef RUBY_INTERN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERN_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#if !defined(__has_attribute) -#define __has_attribute(x) 0 -#endif - +/** + * @file + * @author $Author$ + * @date Thu Jun 10 14:22:17 JST 1993 + * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto + * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. + * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan + * @copyright 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. + */ +#include "ruby/internal/config.h" #include "ruby/defines.h" -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif -#ifdef HAVE_STDARG_PROTOTYPES -# include -#else -# include -#endif +#include #include "ruby/st.h" -/* On mswin, MJIT header transformation can't be used since cl.exe can't output - preprocessed output preserving macros. So this `MJIT_STATIC` is needed - to force non-static function to static on MJIT header to avoid symbol conflict. */ -#ifdef MJIT_HEADER -# define MJIT_STATIC static -#else -# define MJIT_STATIC -#endif - -RUBY_SYMBOL_EXPORT_BEGIN - /* * Functions and variables that are used by more than one source file of * the kernel. */ -#define UNLIMITED_ARGUMENTS (-1) - -/* array.c */ -void rb_mem_clear(VALUE*, long); -VALUE rb_assoc_new(VALUE, VALUE); -VALUE rb_check_array_type(VALUE); -VALUE rb_ary_new(void); -VALUE rb_ary_new_capa(long capa); -VALUE rb_ary_new_from_args(long n, ...); -VALUE rb_ary_new_from_values(long n, const VALUE *elts); -VALUE rb_ary_tmp_new(long); -void rb_ary_free(VALUE); -void rb_ary_modify(VALUE); -VALUE rb_ary_freeze(VALUE); -VALUE rb_ary_shared_with_p(VALUE, VALUE); -VALUE rb_ary_aref(int, const VALUE*, VALUE); -VALUE rb_ary_subseq(VALUE, long, long); -void rb_ary_store(VALUE, long, VALUE); -VALUE rb_ary_dup(VALUE); -VALUE rb_ary_resurrect(VALUE ary); -VALUE rb_ary_to_ary(VALUE); -VALUE rb_ary_to_s(VALUE); -VALUE rb_ary_cat(VALUE, const VALUE *, long); -VALUE rb_ary_push(VALUE, VALUE); -VALUE rb_ary_pop(VALUE); -VALUE rb_ary_shift(VALUE); -VALUE rb_ary_unshift(VALUE, VALUE); -VALUE rb_ary_entry(VALUE, long); -VALUE rb_ary_each(VALUE); -VALUE rb_ary_join(VALUE, VALUE); -VALUE rb_ary_reverse(VALUE); -VALUE rb_ary_rotate(VALUE, long); -VALUE rb_ary_sort(VALUE); -VALUE rb_ary_sort_bang(VALUE); -VALUE rb_ary_delete(VALUE, VALUE); -VALUE rb_ary_delete_at(VALUE, long); -VALUE rb_ary_clear(VALUE); -VALUE rb_ary_plus(VALUE, VALUE); -VALUE rb_ary_concat(VALUE, VALUE); -VALUE rb_ary_assoc(VALUE, VALUE); -VALUE rb_ary_rassoc(VALUE, VALUE); -VALUE rb_ary_includes(VALUE, VALUE); -VALUE rb_ary_cmp(VALUE, VALUE); -VALUE rb_ary_replace(VALUE copy, VALUE orig); -VALUE rb_get_values_at(VALUE, long, int, const VALUE*, VALUE(*)(VALUE,long)); -VALUE rb_ary_resize(VALUE ary, long len); -#define rb_ary_new2 rb_ary_new_capa -#define rb_ary_new3 rb_ary_new_from_args -#define rb_ary_new4 rb_ary_new_from_values -/* bignum.c */ -VALUE rb_big_new(size_t, int); -int rb_bigzero_p(VALUE x); -VALUE rb_big_clone(VALUE); -void rb_big_2comp(VALUE); -VALUE rb_big_norm(VALUE); -void rb_big_resize(VALUE big, size_t len); -VALUE rb_cstr_to_inum(const char*, int, int); -VALUE rb_str_to_inum(VALUE, int, int); -VALUE rb_cstr2inum(const char*, int); -VALUE rb_str2inum(VALUE, int); -VALUE rb_big2str(VALUE, int); -long rb_big2long(VALUE); -#define rb_big2int(x) rb_big2long(x) -unsigned long rb_big2ulong(VALUE); -#define rb_big2uint(x) rb_big2ulong(x) -#if HAVE_LONG_LONG -LONG_LONG rb_big2ll(VALUE); -unsigned LONG_LONG rb_big2ull(VALUE); -#endif /* HAVE_LONG_LONG */ -void rb_big_pack(VALUE val, unsigned long *buf, long num_longs); -VALUE rb_big_unpack(unsigned long *buf, long num_longs); -int rb_uv_to_utf8(char[6],unsigned long); -VALUE rb_dbl2big(double); -double rb_big2dbl(VALUE); -VALUE rb_big_cmp(VALUE, VALUE); -VALUE rb_big_eq(VALUE, VALUE); -VALUE rb_big_eql(VALUE, VALUE); -VALUE rb_big_plus(VALUE, VALUE); -VALUE rb_big_minus(VALUE, VALUE); -VALUE rb_big_mul(VALUE, VALUE); -VALUE rb_big_div(VALUE, VALUE); -VALUE rb_big_idiv(VALUE, VALUE); -VALUE rb_big_modulo(VALUE, VALUE); -VALUE rb_big_divmod(VALUE, VALUE); -VALUE rb_big_pow(VALUE, VALUE); -VALUE rb_big_and(VALUE, VALUE); -VALUE rb_big_or(VALUE, VALUE); -VALUE rb_big_xor(VALUE, VALUE); -VALUE rb_big_lshift(VALUE, VALUE); -VALUE rb_big_rshift(VALUE, VALUE); - -/* For rb_integer_pack and rb_integer_unpack: */ -/* "MS" in MSWORD and MSBYTE means "most significant" */ -/* "LS" in LSWORD and LSBYTE means "least significant" */ -#define INTEGER_PACK_MSWORD_FIRST 0x01 -#define INTEGER_PACK_LSWORD_FIRST 0x02 -#define INTEGER_PACK_MSBYTE_FIRST 0x10 -#define INTEGER_PACK_LSBYTE_FIRST 0x20 -#define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40 -#define INTEGER_PACK_2COMP 0x80 -#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400 -/* For rb_integer_unpack: */ -#define INTEGER_PACK_FORCE_BIGNUM 0x100 -#define INTEGER_PACK_NEGATIVE 0x200 -/* Combinations: */ -#define INTEGER_PACK_LITTLE_ENDIAN \ - (INTEGER_PACK_LSWORD_FIRST | \ - INTEGER_PACK_LSBYTE_FIRST) -#define INTEGER_PACK_BIG_ENDIAN \ - (INTEGER_PACK_MSWORD_FIRST | \ - INTEGER_PACK_MSBYTE_FIRST) -int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); -VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); -size_t rb_absint_size(VALUE val, int *nlz_bits_ret); -size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); -int rb_absint_singlebit_p(VALUE val); - -/* rational.c */ -VALUE rb_rational_raw(VALUE, VALUE); -#define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1)) -#define rb_rational_raw2(x,y) rb_rational_raw((x), (y)) -VALUE rb_rational_new(VALUE, VALUE); -#define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1)) -#define rb_rational_new2(x,y) rb_rational_new((x), (y)) -VALUE rb_Rational(VALUE, VALUE); -#define rb_Rational1(x) rb_Rational((x), INT2FIX(1)) -#define rb_Rational2(x,y) rb_Rational((x), (y)) -VALUE rb_rational_num(VALUE rat); -VALUE rb_rational_den(VALUE rat); -VALUE rb_flt_rationalize_with_prec(VALUE, VALUE); -VALUE rb_flt_rationalize(VALUE); -/* complex.c */ -VALUE rb_complex_raw(VALUE, VALUE); -#define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0)) -#define rb_complex_raw2(x,y) rb_complex_raw((x), (y)) -VALUE rb_complex_new(VALUE, VALUE); -#define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0)) -#define rb_complex_new2(x,y) rb_complex_new((x), (y)) -VALUE rb_complex_new_polar(VALUE abs, VALUE arg); -DEPRECATED_BY(rb_complex_new_polar, VALUE rb_complex_polar(VALUE abs, VALUE arg)); -VALUE rb_complex_real(VALUE z); -VALUE rb_complex_imag(VALUE z); -VALUE rb_complex_plus(VALUE x, VALUE y); -VALUE rb_complex_minus(VALUE x, VALUE y); -VALUE rb_complex_mul(VALUE x, VALUE y); -VALUE rb_complex_div(VALUE x, VALUE y); -VALUE rb_complex_uminus(VALUE z); -VALUE rb_complex_conjugate(VALUE z); -VALUE rb_complex_abs(VALUE z); -VALUE rb_complex_arg(VALUE z); -VALUE rb_complex_pow(VALUE base, VALUE exp); -VALUE rb_dbl_complex_new(double real, double imag); -#define rb_complex_add rb_complex_plus -#define rb_complex_sub rb_complex_minus -#define rb_complex_nagate rb_complex_uminus - -VALUE rb_Complex(VALUE, VALUE); -#define rb_Complex1(x) rb_Complex((x), INT2FIX(0)) -#define rb_Complex2(x,y) rb_Complex((x), (y)) -/* class.c */ -VALUE rb_class_new(VALUE); -VALUE rb_mod_init_copy(VALUE, VALUE); -VALUE rb_singleton_class_clone(VALUE); -void rb_singleton_class_attached(VALUE,VALUE); -void rb_check_inheritable(VALUE); -VALUE rb_define_class_id(ID, VALUE); -VALUE rb_define_class_id_under(VALUE, ID, VALUE); -VALUE rb_module_new(void); -VALUE rb_define_module_id(ID); -VALUE rb_define_module_id_under(VALUE, ID); -VALUE rb_mod_included_modules(VALUE); -VALUE rb_mod_include_p(VALUE, VALUE); -VALUE rb_mod_ancestors(VALUE); -VALUE rb_class_instance_methods(int, const VALUE*, VALUE); -VALUE rb_class_public_instance_methods(int, const VALUE*, VALUE); -VALUE rb_class_protected_instance_methods(int, const VALUE*, VALUE); -VALUE rb_class_private_instance_methods(int, const VALUE*, VALUE); -VALUE rb_obj_singleton_methods(int, const VALUE*, VALUE); -void rb_define_method_id(VALUE, ID, VALUE (*)(ANYARGS), int); -void rb_undef(VALUE, ID); -void rb_define_protected_method(VALUE, const char*, VALUE (*)(ANYARGS), int); -void rb_define_private_method(VALUE, const char*, VALUE (*)(ANYARGS), int); -void rb_define_singleton_method(VALUE, const char*, VALUE(*)(ANYARGS), int); -VALUE rb_singleton_class(VALUE); -/* compar.c */ -int rb_cmpint(VALUE, VALUE, VALUE); -NORETURN(void rb_cmperr(VALUE, VALUE)); -/* cont.c */ -VALUE rb_fiber_new(rb_block_call_func_t, VALUE); -VALUE rb_fiber_resume(VALUE fib, int argc, const VALUE *argv); -VALUE rb_fiber_resume_kw(VALUE fib, int argc, const VALUE *argv, int kw_splat); -VALUE rb_fiber_yield(int argc, const VALUE *argv); -VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat); -VALUE rb_fiber_current(void); -VALUE rb_fiber_alive_p(VALUE); -/* enum.c */ -VALUE rb_enum_values_pack(int, const VALUE*); -/* enumerator.c */ -VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *); -typedef VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE); -VALUE rb_enumeratorize_with_size(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *); -VALUE rb_enumeratorize_with_size_kw(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *, int); -#ifndef RUBY_EXPORT -#define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \ - rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn)) -#define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \ - rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat) -#endif -#define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \ - rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \ - (argc), (argv), (size_fn)) -#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ - rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \ - (argc), (argv), (size_fn), (kw_splat)) -#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \ - if (!rb_block_given_p()) \ - return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ - } while (0) -#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ - if (!rb_block_given_p()) \ - return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \ - } while (0) -#define RETURN_ENUMERATOR(obj, argc, argv) RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0) -#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat) -typedef struct { - VALUE begin; - VALUE end; - VALUE step; - int exclude_end; -} rb_arithmetic_sequence_components_t; -int rb_arithmetic_sequence_extract(VALUE, rb_arithmetic_sequence_components_t *); -/* error.c */ -VALUE rb_exc_new(VALUE, const char*, long); -VALUE rb_exc_new_cstr(VALUE, const char*); -VALUE rb_exc_new_str(VALUE, VALUE); -#define rb_exc_new2 rb_exc_new_cstr -#define rb_exc_new3 rb_exc_new_str -PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2); -PRINTF_ARGS(NORETURN(void rb_loaderror_with_path(VALUE path, const char*, ...)), 2, 3); -PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3); -PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3); -PRINTF_ARGS(NORETURN(void rb_frozen_error_raise(VALUE, const char*, ...)), 2, 3); -NORETURN(void rb_invalid_str(const char*, const char*)); -NORETURN(void rb_error_frozen(const char*)); -NORETURN(void rb_error_frozen_object(VALUE)); -void rb_error_untrusted(VALUE); -void rb_check_frozen(VALUE); -void rb_check_trusted(VALUE); -#define rb_check_frozen_internal(obj) do { \ - VALUE frozen_obj = (obj); \ - if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \ - rb_error_frozen_object(frozen_obj); \ - } \ - } while (0) -#ifdef __GNUC__ -#define rb_check_frozen(obj) __extension__({rb_check_frozen_internal(obj);}) -#else -static inline void -rb_check_frozen_inline(VALUE obj) -{ - rb_check_frozen_internal(obj); -} -#define rb_check_frozen(obj) rb_check_frozen_inline(obj) -static inline void -rb_check_trusted_inline(VALUE obj) -{ - rb_check_trusted(obj); -} -#define rb_check_trusted(obj) rb_check_trusted_inline(obj) -#endif -void rb_check_copyable(VALUE obj, VALUE orig); - -#define RB_OBJ_INIT_COPY(obj, orig) \ - ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1)) -#define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig) - -/* eval.c */ -int rb_sourceline(void); -const char *rb_sourcefile(void); -VALUE rb_check_funcall(VALUE, ID, int, const VALUE*); -VALUE rb_check_funcall_kw(VALUE, ID, int, const VALUE*, int); - -NORETURN(MJIT_STATIC void rb_error_arity(int, int, int)); -static inline int -rb_check_arity(int argc, int min, int max) -{ - if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max)) - rb_error_arity(argc, min, max); - return argc; -} -#define rb_check_arity rb_check_arity /* for ifdef */ - -#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT) -typedef struct { - int maxfd; - fd_set *fdset; -} rb_fdset_t; - -void rb_fd_init(rb_fdset_t *); -void rb_fd_term(rb_fdset_t *); -void rb_fd_zero(rb_fdset_t *); -void rb_fd_set(int, rb_fdset_t *); -void rb_fd_clr(int, rb_fdset_t *); -int rb_fd_isset(int, const rb_fdset_t *); -void rb_fd_copy(rb_fdset_t *, const fd_set *, int); -void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); - -struct timeval; -int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *); - -#define rb_fd_ptr(f) ((f)->fdset) -#define rb_fd_max(f) ((f)->maxfd) - -#elif defined(_WIN32) - -typedef struct { - int capa; - fd_set *fdset; -} rb_fdset_t; - -void rb_fd_init(rb_fdset_t *); -void rb_fd_term(rb_fdset_t *); -#define rb_fd_zero(f) ((f)->fdset->fd_count = 0) -void rb_fd_set(int, rb_fdset_t *); -#define rb_fd_clr(n, f) rb_w32_fdclr((n), (f)->fdset) -#define rb_fd_isset(n, f) rb_w32_fdisset((n), (f)->fdset) -#define rb_fd_copy(d, s, n) rb_w32_fd_copy((d), (s), (n)) -void rb_w32_fd_copy(rb_fdset_t *, const fd_set *, int); -#define rb_fd_dup(d, s) rb_w32_fd_dup((d), (s)) -void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); -static inline int -rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout) -{ - return rb_w32_select(n, - rfds ? rfds->fdset : NULL, - wfds ? wfds->fdset : NULL, - efds ? efds->fdset : NULL, - timeout); -} -#define rb_fd_resize(n, f) ((void)(f)) - -#define rb_fd_ptr(f) ((f)->fdset) -#define rb_fd_max(f) ((f)->fdset->fd_count) - -#else - -typedef fd_set rb_fdset_t; -#define rb_fd_zero(f) FD_ZERO(f) -#define rb_fd_set(n, f) FD_SET((n), (f)) -#define rb_fd_clr(n, f) FD_CLR((n), (f)) -#define rb_fd_isset(n, f) FD_ISSET((n), (f)) -#define rb_fd_copy(d, s, n) (*(d) = *(s)) -#define rb_fd_dup(d, s) (*(d) = *(s)) -#define rb_fd_resize(n, f) ((void)(f)) -#define rb_fd_ptr(f) (f) -#define rb_fd_init(f) FD_ZERO(f) -#define rb_fd_init_copy(d, s) (*(d) = *(s)) -#define rb_fd_term(f) ((void)(f)) -#define rb_fd_max(f) FD_SETSIZE -#define rb_fd_select(n, rfds, wfds, efds, timeout) select((n), (rfds), (wfds), (efds), (timeout)) - -#endif - -NORETURN(void rb_exc_raise(VALUE)); -NORETURN(void rb_exc_fatal(VALUE)); -NORETURN(VALUE rb_f_exit(int, const VALUE*)); -NORETURN(VALUE rb_f_abort(int, const VALUE*)); -void rb_remove_method(VALUE, const char*); -void rb_remove_method_id(VALUE, ID); -#define HAVE_RB_DEFINE_ALLOC_FUNC 1 -typedef VALUE (*rb_alloc_func_t)(VALUE); -void rb_define_alloc_func(VALUE, rb_alloc_func_t); -void rb_undef_alloc_func(VALUE); -rb_alloc_func_t rb_get_alloc_func(VALUE); -void rb_clear_constant_cache(void); -void rb_clear_method_cache_by_class(VALUE); -void rb_alias(VALUE, ID, ID); -void rb_attr(VALUE,ID,int,int,int); -int rb_method_boundp(VALUE, ID, int); -int rb_method_basic_definition_p(VALUE, ID); -VALUE rb_eval_cmd(VALUE, VALUE, int); -VALUE rb_eval_cmd_kw(VALUE, VALUE, int); -int rb_obj_respond_to(VALUE, ID, int); -int rb_respond_to(VALUE, ID); -NORETURN(VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)); -#if !defined(RUBY_EXPORT) && defined(_WIN32) -RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker); -#define rb_f_notimplement (*rb_f_notimplement_) -#endif -NORETURN(void rb_interrupt(void)); -VALUE rb_apply(VALUE, ID, VALUE); -void rb_backtrace(void); -ID rb_frame_this_func(void); -VALUE rb_obj_instance_eval(int, const VALUE*, VALUE); -VALUE rb_obj_instance_exec(int, const VALUE*, VALUE); -VALUE rb_mod_module_eval(int, const VALUE*, VALUE); -VALUE rb_mod_module_exec(int, const VALUE*, VALUE); -void rb_load(VALUE, int); -void rb_load_protect(VALUE, int, int*); -NORETURN(void rb_jump_tag(int)); -int rb_provided(const char*); -int rb_feature_provided(const char *, const char **); -void rb_provide(const char*); -VALUE rb_f_require(VALUE, VALUE); -VALUE rb_require_safe(VALUE, int); /* Remove in 3.0 */ -VALUE rb_require_string(VALUE); -void rb_obj_call_init(VALUE, int, const VALUE*); -void rb_obj_call_init_kw(VALUE, int, const VALUE*, int); -VALUE rb_class_new_instance(int, const VALUE*, VALUE); -VALUE rb_class_new_instance_kw(int, const VALUE*, VALUE, int); -VALUE rb_block_proc(void); -VALUE rb_block_lambda(void); -VALUE rb_proc_new(rb_block_call_func_t, VALUE); -VALUE rb_obj_is_proc(VALUE); -VALUE rb_proc_call(VALUE, VALUE); -VALUE rb_proc_call_kw(VALUE, VALUE, int); -VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE); -VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int); -int rb_proc_arity(VALUE); -VALUE rb_proc_lambda_p(VALUE); -VALUE rb_binding_new(void); -VALUE rb_obj_method(VALUE, VALUE); -VALUE rb_obj_is_method(VALUE); -VALUE rb_method_call(int, const VALUE*, VALUE); -VALUE rb_method_call_kw(int, const VALUE*, VALUE, int); -VALUE rb_method_call_with_block(int, const VALUE *, VALUE, VALUE); -VALUE rb_method_call_with_block_kw(int, const VALUE *, VALUE, VALUE, int); -int rb_mod_method_arity(VALUE, ID); -int rb_obj_method_arity(VALUE, ID); -VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*); -void rb_set_end_proc(void (*)(VALUE), VALUE); -void rb_thread_schedule(void); -void rb_thread_wait_fd(int); -int rb_thread_fd_writable(int); -void rb_thread_fd_close(int); -int rb_thread_alone(void); -void rb_thread_sleep(int); -void rb_thread_sleep_forever(void); -void rb_thread_sleep_deadly(void); -VALUE rb_thread_stop(void); -VALUE rb_thread_wakeup(VALUE); -VALUE rb_thread_wakeup_alive(VALUE); -VALUE rb_thread_run(VALUE); -VALUE rb_thread_kill(VALUE); -VALUE rb_thread_create(VALUE (*)(void *), void*); -int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *); -void rb_thread_wait_for(struct timeval); -VALUE rb_thread_current(void); -VALUE rb_thread_main(void); -VALUE rb_thread_local_aref(VALUE, ID); -VALUE rb_thread_local_aset(VALUE, ID, VALUE); -void rb_thread_atfork(void); -void rb_thread_atfork_before_exec(void); -VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE); -VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE); -VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE); -VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE); -/* dir.c */ -VALUE rb_dir_getwd(void); -/* file.c */ -VALUE rb_file_s_expand_path(int, const VALUE *); -VALUE rb_file_expand_path(VALUE, VALUE); -VALUE rb_file_s_absolute_path(int, const VALUE *); -VALUE rb_file_absolute_path(VALUE, VALUE); -VALUE rb_file_dirname(VALUE fname); -int rb_find_file_ext_safe(VALUE*, const char* const*, int); /* Remove in 3.0 */ -VALUE rb_find_file_safe(VALUE, int); /* Remove in 3.0 */ -int rb_find_file_ext(VALUE*, const char* const*); -VALUE rb_find_file(VALUE); -VALUE rb_file_directory_p(VALUE,VALUE); -VALUE rb_str_encode_ospath(VALUE); -int rb_is_absolute_path(const char *); -/* gc.c */ -COLDFUNC NORETURN(void rb_memerror(void)); -PUREFUNC(int rb_during_gc(void)); -void rb_gc_mark_locations(const VALUE*, const VALUE*); -void rb_mark_tbl(struct st_table*); -void rb_mark_tbl_no_pin(struct st_table*); -void rb_mark_set(struct st_table*); -void rb_mark_hash(struct st_table*); -void rb_gc_update_tbl_refs(st_table *ptr); -void rb_gc_mark_maybe(VALUE); -void rb_gc_mark(VALUE); -void rb_gc_mark_movable(VALUE); -VALUE rb_gc_location(VALUE); -void rb_gc_force_recycle(VALUE); -void rb_gc(void); -void rb_gc_copy_finalizer(VALUE,VALUE); -VALUE rb_gc_enable(void); -VALUE rb_gc_disable(void); -VALUE rb_gc_start(void); -VALUE rb_define_finalizer(VALUE, VALUE); -VALUE rb_undefine_finalizer(VALUE); -size_t rb_gc_count(void); -size_t rb_gc_stat(VALUE); -VALUE rb_gc_latest_gc_info(VALUE); -void rb_gc_adjust_memory_usage(ssize_t); -/* hash.c */ -void rb_st_foreach_safe(struct st_table *, int (*)(st_data_t, st_data_t, st_data_t), st_data_t); -#define st_foreach_safe rb_st_foreach_safe -VALUE rb_check_hash_type(VALUE); -void rb_hash_foreach(VALUE, int (*)(VALUE, VALUE, VALUE), VALUE); -VALUE rb_hash(VALUE); -VALUE rb_hash_new(void); -VALUE rb_hash_dup(VALUE); -VALUE rb_hash_freeze(VALUE); -VALUE rb_hash_aref(VALUE, VALUE); -VALUE rb_hash_lookup(VALUE, VALUE); -VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); -VALUE rb_hash_fetch(VALUE, VALUE); -VALUE rb_hash_aset(VALUE, VALUE, VALUE); -VALUE rb_hash_clear(VALUE); -VALUE rb_hash_delete_if(VALUE); -VALUE rb_hash_delete(VALUE,VALUE); -VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone); -void rb_hash_bulk_insert(long, const VALUE *, VALUE); -typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func); -struct st_table *rb_hash_tbl(VALUE, const char *file, int line); -int rb_path_check(const char*); -int rb_env_path_tainted(void); -VALUE rb_env_clear(void); -VALUE rb_hash_size(VALUE); -void rb_hash_free(VALUE); -/* io.c */ -#define rb_defout rb_stdout -RUBY_EXTERN VALUE rb_fs; -RUBY_EXTERN VALUE rb_output_fs; -RUBY_EXTERN VALUE rb_rs; -RUBY_EXTERN VALUE rb_default_rs; -RUBY_EXTERN VALUE rb_output_rs; -VALUE rb_io_write(VALUE, VALUE); -VALUE rb_io_gets(VALUE); -VALUE rb_io_getbyte(VALUE); -VALUE rb_io_ungetc(VALUE, VALUE); -VALUE rb_io_ungetbyte(VALUE, VALUE); -VALUE rb_io_close(VALUE); -VALUE rb_io_flush(VALUE); -VALUE rb_io_eof(VALUE); -VALUE rb_io_binmode(VALUE); -VALUE rb_io_ascii8bit_binmode(VALUE); -VALUE rb_io_addstr(VALUE, VALUE); -VALUE rb_io_printf(int, const VALUE*, VALUE); -VALUE rb_io_print(int, const VALUE*, VALUE); -VALUE rb_io_puts(int, const VALUE*, VALUE); -VALUE rb_io_fdopen(int, int, const char*); -VALUE rb_io_get_io(VALUE); -VALUE rb_file_open(const char*, const char*); -VALUE rb_file_open_str(VALUE, const char*); -VALUE rb_gets(void); -void rb_write_error(const char*); -void rb_write_error2(const char*, long); -void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds); -int rb_pipe(int *pipes); -int rb_reserved_fd_p(int fd); -int rb_cloexec_open(const char *pathname, int flags, mode_t mode); -int rb_cloexec_dup(int oldfd); -int rb_cloexec_dup2(int oldfd, int newfd); -int rb_cloexec_pipe(int fildes[2]); -int rb_cloexec_fcntl_dupfd(int fd, int minfd); -#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd) -void rb_update_max_fd(int fd); -void rb_fd_fix_cloexec(int fd); -/* marshal.c */ -VALUE rb_marshal_dump(VALUE, VALUE); -VALUE rb_marshal_load(VALUE); -void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); -/* numeric.c */ -NORETURN(void rb_num_zerodiv(void)); -#define RB_NUM_COERCE_FUNCS_NEED_OPID 1 -VALUE rb_num_coerce_bin(VALUE, VALUE, ID); -VALUE rb_num_coerce_cmp(VALUE, VALUE, ID); -VALUE rb_num_coerce_relop(VALUE, VALUE, ID); -VALUE rb_num_coerce_bit(VALUE, VALUE, ID); -VALUE rb_num2fix(VALUE); -VALUE rb_fix2str(VALUE, int); -CONSTFUNC(VALUE rb_dbl_cmp(double, double)); -/* object.c */ -int rb_eql(VALUE, VALUE); -VALUE rb_any_to_s(VALUE); -VALUE rb_inspect(VALUE); -VALUE rb_obj_is_instance_of(VALUE, VALUE); -VALUE rb_obj_is_kind_of(VALUE, VALUE); -VALUE rb_obj_alloc(VALUE); -VALUE rb_obj_clone(VALUE); -VALUE rb_obj_dup(VALUE); -VALUE rb_obj_init_copy(VALUE,VALUE); -VALUE rb_obj_taint(VALUE); -PUREFUNC(VALUE rb_obj_tainted(VALUE)); -VALUE rb_obj_untaint(VALUE); -VALUE rb_obj_untrust(VALUE); -PUREFUNC(VALUE rb_obj_untrusted(VALUE)); -VALUE rb_obj_trust(VALUE); -VALUE rb_obj_freeze(VALUE); -PUREFUNC(VALUE rb_obj_frozen_p(VALUE)); -VALUE rb_obj_id(VALUE); -VALUE rb_memory_id(VALUE); -VALUE rb_obj_class(VALUE); -PUREFUNC(VALUE rb_class_real(VALUE)); -PUREFUNC(VALUE rb_class_inherited_p(VALUE, VALUE)); -VALUE rb_class_superclass(VALUE); -VALUE rb_class_get_superclass(VALUE); -VALUE rb_convert_type(VALUE,int,const char*,const char*); -VALUE rb_check_convert_type(VALUE,int,const char*,const char*); -VALUE rb_check_to_integer(VALUE, const char *); -VALUE rb_check_to_float(VALUE); -VALUE rb_to_int(VALUE); -VALUE rb_check_to_int(VALUE); -VALUE rb_Integer(VALUE); -VALUE rb_to_float(VALUE); -VALUE rb_Float(VALUE); -VALUE rb_String(VALUE); -VALUE rb_Array(VALUE); -VALUE rb_Hash(VALUE); -double rb_cstr_to_dbl(const char*, int); -double rb_str_to_dbl(VALUE, int); -/* parse.y */ -ID rb_id_attrset(ID); -CONSTFUNC(int rb_is_const_id(ID)); -CONSTFUNC(int rb_is_global_id(ID)); -CONSTFUNC(int rb_is_instance_id(ID)); -CONSTFUNC(int rb_is_attrset_id(ID)); -CONSTFUNC(int rb_is_class_id(ID)); -CONSTFUNC(int rb_is_local_id(ID)); -CONSTFUNC(int rb_is_junk_id(ID)); -int rb_symname_p(const char*); -int rb_sym_interned_p(VALUE); -VALUE rb_backref_get(void); -void rb_backref_set(VALUE); -VALUE rb_lastline_get(void); -void rb_lastline_set(VALUE); -/* process.c */ -void rb_last_status_set(int status, rb_pid_t pid); -VALUE rb_last_status_get(void); -int rb_proc_exec(const char*); -NORETURN(VALUE rb_f_exec(int, const VALUE*)); -rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags); -void rb_syswait(rb_pid_t pid); -rb_pid_t rb_spawn(int, const VALUE*); -rb_pid_t rb_spawn_err(int, const VALUE*, char*, size_t); -VALUE rb_proc_times(VALUE); -VALUE rb_detach_process(rb_pid_t pid); -/* range.c */ -VALUE rb_range_new(VALUE, VALUE, int); -VALUE rb_range_beg_len(VALUE, long*, long*, long, int); -int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp); -/* random.c */ -unsigned int rb_genrand_int32(void); -double rb_genrand_real(void); -void rb_reset_random_seed(void); -VALUE rb_random_bytes(VALUE rnd, long n); -VALUE rb_random_int(VALUE rnd, VALUE max); -unsigned int rb_random_int32(VALUE rnd); -double rb_random_real(VALUE rnd); -unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit); -unsigned long rb_genrand_ulong_limited(unsigned long i); -/* re.c */ -#define rb_memcmp memcmp -int rb_memcicmp(const void*,const void*,long); -void rb_match_busy(VALUE); -VALUE rb_reg_nth_defined(int, VALUE); -VALUE rb_reg_nth_match(int, VALUE); -int rb_reg_backref_number(VALUE match, VALUE backref); -VALUE rb_reg_last_match(VALUE); -VALUE rb_reg_match_pre(VALUE); -VALUE rb_reg_match_post(VALUE); -VALUE rb_reg_match_last(VALUE); -#define HAVE_RB_REG_NEW_STR 1 -VALUE rb_reg_new_str(VALUE, int); -VALUE rb_reg_new(const char *, long, int); -VALUE rb_reg_alloc(void); -VALUE rb_reg_init_str(VALUE re, VALUE s, int options); -VALUE rb_reg_match(VALUE, VALUE); -VALUE rb_reg_match2(VALUE); -int rb_reg_options(VALUE); -/* ruby.c */ -#define rb_argv rb_get_argv() -RUBY_EXTERN VALUE rb_argv0; -VALUE rb_get_argv(void); -void *rb_load_file(const char*); -void *rb_load_file_str(VALUE); -/* signal.c */ -VALUE rb_f_kill(int, const VALUE*); -#ifdef POSIX_SIGNAL -#define posix_signal ruby_posix_signal -RETSIGTYPE (*posix_signal(int, RETSIGTYPE (*)(int)))(int); -#endif -const char *ruby_signal_name(int); -void ruby_default_signal(int); -/* sprintf.c */ -VALUE rb_f_sprintf(int, const VALUE*); -PRINTF_ARGS(VALUE rb_sprintf(const char*, ...), 1, 2); -VALUE rb_vsprintf(const char*, va_list); -PRINTF_ARGS(VALUE rb_str_catf(VALUE, const char*, ...), 2, 3); -VALUE rb_str_vcatf(VALUE, const char*, va_list); -VALUE rb_str_format(int, const VALUE *, VALUE); -/* string.c */ -VALUE rb_str_new(const char*, long); -VALUE rb_str_new_cstr(const char*); -VALUE rb_str_new_shared(VALUE); -VALUE rb_str_new_frozen(VALUE); -VALUE rb_str_new_with_class(VALUE, const char*, long); -VALUE rb_tainted_str_new_cstr(const char*); -VALUE rb_tainted_str_new(const char*, long); -VALUE rb_external_str_new(const char*, long); -VALUE rb_external_str_new_cstr(const char*); -VALUE rb_locale_str_new(const char*, long); -VALUE rb_locale_str_new_cstr(const char*); -VALUE rb_filesystem_str_new(const char*, long); -VALUE rb_filesystem_str_new_cstr(const char*); -VALUE rb_str_buf_new(long); -VALUE rb_str_buf_new_cstr(const char*); -VALUE rb_str_buf_new2(const char*); -VALUE rb_str_tmp_new(long); -VALUE rb_usascii_str_new(const char*, long); -VALUE rb_usascii_str_new_cstr(const char*); -VALUE rb_utf8_str_new(const char*, long); -VALUE rb_utf8_str_new_cstr(const char*); -VALUE rb_str_new_static(const char *, long); -VALUE rb_usascii_str_new_static(const char *, long); -VALUE rb_utf8_str_new_static(const char *, long); -void rb_str_free(VALUE); -void rb_str_shared_replace(VALUE, VALUE); -VALUE rb_str_buf_append(VALUE, VALUE); -VALUE rb_str_buf_cat(VALUE, const char*, long); -VALUE rb_str_buf_cat2(VALUE, const char*); -VALUE rb_str_buf_cat_ascii(VALUE, const char*); -VALUE rb_obj_as_string(VALUE); -VALUE rb_check_string_type(VALUE); -void rb_must_asciicompat(VALUE); -VALUE rb_str_dup(VALUE); -VALUE rb_str_resurrect(VALUE str); -VALUE rb_str_locktmp(VALUE); -VALUE rb_str_unlocktmp(VALUE); -VALUE rb_str_dup_frozen(VALUE); -#define rb_str_dup_frozen rb_str_new_frozen -VALUE rb_str_plus(VALUE, VALUE); -VALUE rb_str_times(VALUE, VALUE); -long rb_str_sublen(VALUE, long); -VALUE rb_str_substr(VALUE, long, long); -VALUE rb_str_subseq(VALUE, long, long); -char *rb_str_subpos(VALUE, long, long*); -void rb_str_modify(VALUE); -void rb_str_modify_expand(VALUE, long); -VALUE rb_str_freeze(VALUE); -void rb_str_set_len(VALUE, long); -VALUE rb_str_resize(VALUE, long); -VALUE rb_str_cat(VALUE, const char*, long); -VALUE rb_str_cat_cstr(VALUE, const char*); -VALUE rb_str_cat2(VALUE, const char*); -VALUE rb_str_append(VALUE, VALUE); -VALUE rb_str_concat(VALUE, VALUE); -st_index_t rb_memhash(const void *ptr, long len); -st_index_t rb_hash_start(st_index_t); -st_index_t rb_hash_uint32(st_index_t, uint32_t); -st_index_t rb_hash_uint(st_index_t, st_index_t); -st_index_t rb_hash_end(st_index_t); -#define rb_hash_uint32(h, i) st_hash_uint32((h), (i)) -#define rb_hash_uint(h, i) st_hash_uint((h), (i)) -#define rb_hash_end(h) st_hash_end(h) -st_index_t rb_str_hash(VALUE); -int rb_str_hash_cmp(VALUE,VALUE); -int rb_str_comparable(VALUE, VALUE); -int rb_str_cmp(VALUE, VALUE); -VALUE rb_str_equal(VALUE str1, VALUE str2); -VALUE rb_str_drop_bytes(VALUE, long); -void rb_str_update(VALUE, long, long, VALUE); -VALUE rb_str_replace(VALUE, VALUE); -VALUE rb_str_inspect(VALUE); -VALUE rb_str_dump(VALUE); -VALUE rb_str_split(VALUE, const char*); -rb_gvar_setter_t rb_str_setter; -VALUE rb_str_intern(VALUE); -VALUE rb_sym_to_s(VALUE); -long rb_str_strlen(VALUE); -VALUE rb_str_length(VALUE); -long rb_str_offset(VALUE, long); -PUREFUNC(size_t rb_str_capacity(VALUE)); -VALUE rb_str_ellipsize(VALUE, long); -VALUE rb_str_scrub(VALUE, VALUE); -/* symbol.c */ -VALUE rb_sym_all_symbols(void); - -#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P -#define rb_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \ - rb_str_new_static((str), (len)) : \ - rb_str_new((str), (len)) \ -) -#define rb_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_str_new_static((str), (long)strlen(str)) : \ - rb_str_new_cstr(str) \ -) -#define rb_usascii_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \ - rb_usascii_str_new_static((str), (len)) : \ - rb_usascii_str_new((str), (len)) \ -) -#define rb_utf8_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \ - rb_utf8_str_new_static((str), (len)) : \ - rb_utf8_str_new((str), (len)) \ -) -#define rb_tainted_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_tainted_str_new((str), (long)strlen(str)) : \ - rb_tainted_str_new_cstr(str) \ -) -#define rb_usascii_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_usascii_str_new_static((str), (long)strlen(str)) : \ - rb_usascii_str_new_cstr(str) \ -) -#define rb_utf8_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_utf8_str_new_static((str), (long)strlen(str)) : \ - rb_utf8_str_new_cstr(str) \ -) -#define rb_external_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_external_str_new((str), (long)strlen(str)) : \ - rb_external_str_new_cstr(str) \ -) -#define rb_locale_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_locale_str_new((str), (long)strlen(str)) : \ - rb_locale_str_new_cstr(str) \ -) -#define rb_str_buf_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_str_buf_cat(rb_str_buf_new((long)strlen(str)), \ - (str), (long)strlen(str)) : \ - rb_str_buf_new_cstr(str) \ -) -#define rb_str_cat_cstr(str, ptr) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(ptr)) ? \ - rb_str_cat((str), (ptr), (long)strlen(ptr)) : \ - rb_str_cat_cstr((str), (ptr)) \ -) -#define rb_exc_new_cstr(klass, ptr) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(ptr)) ? \ - rb_exc_new((klass), (ptr), (long)strlen(ptr)) : \ - rb_exc_new_cstr((klass), (ptr)) \ -) -#endif -#define rb_str_new2 rb_str_new_cstr -#define rb_str_new3 rb_str_new_shared -#define rb_str_new4 rb_str_new_frozen -#define rb_str_new5 rb_str_new_with_class -#define rb_tainted_str_new2 rb_tainted_str_new_cstr -#define rb_str_buf_new2 rb_str_buf_new_cstr -#define rb_usascii_str_new2 rb_usascii_str_new_cstr -#define rb_str_buf_cat rb_str_cat -#define rb_str_buf_cat2 rb_str_cat_cstr -#define rb_str_cat2 rb_str_cat_cstr -#define rb_strlen_lit(str) (sizeof(str "") - 1) -#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str)) -#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str)) -#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str)) -#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc)) -#define rb_str_new_literal(str) rb_str_new_lit(str) -#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str) -#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str) -#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc) - -/* struct.c */ -VALUE rb_struct_new(VALUE, ...); -VALUE rb_struct_define(const char*, ...); -VALUE rb_struct_define_under(VALUE, const char*, ...); -VALUE rb_struct_alloc(VALUE, VALUE); -VALUE rb_struct_initialize(VALUE, VALUE); -VALUE rb_struct_aref(VALUE, VALUE); -VALUE rb_struct_aset(VALUE, VALUE, VALUE); -VALUE rb_struct_getmember(VALUE, ID); -VALUE rb_struct_s_members(VALUE); -VALUE rb_struct_members(VALUE); -VALUE rb_struct_size(VALUE s); -VALUE rb_struct_alloc_noinit(VALUE); -VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...); -VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); - -/* thread.c */ -typedef void rb_unblock_function_t(void *); -typedef VALUE rb_blocking_function_t(void *); -void rb_thread_check_ints(void); -int rb_thread_interrupted(VALUE thval); - -#define RUBY_UBF_IO ((rb_unblock_function_t *)-1) -#define RUBY_UBF_PROCESS ((rb_unblock_function_t *)-1) -VALUE rb_mutex_new(void); -VALUE rb_mutex_locked_p(VALUE mutex); -VALUE rb_mutex_trylock(VALUE mutex); -VALUE rb_mutex_lock(VALUE mutex); -VALUE rb_mutex_unlock(VALUE mutex); -VALUE rb_mutex_sleep(VALUE self, VALUE timeout); -VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg); -/* time.c */ -struct timespec; -void rb_timespec_now(struct timespec *); -VALUE rb_time_new(time_t, long); -VALUE rb_time_nano_new(time_t, long); -VALUE rb_time_timespec_new(const struct timespec *, int); -VALUE rb_time_num_new(VALUE, VALUE); -struct timeval rb_time_interval(VALUE num); -struct timeval rb_time_timeval(VALUE time); -struct timespec rb_time_timespec(VALUE time); -struct timespec rb_time_timespec_interval(VALUE num); -VALUE rb_time_utc_offset(VALUE time); -/* variable.c */ -VALUE rb_mod_name(VALUE); -VALUE rb_class_path(VALUE); -VALUE rb_class_path_cached(VALUE); -void rb_set_class_path(VALUE, VALUE, const char*); -void rb_set_class_path_string(VALUE, VALUE, VALUE); -VALUE rb_path_to_class(VALUE); -VALUE rb_path2class(const char*); -VALUE rb_class_name(VALUE); -VALUE rb_autoload_load(VALUE, ID); -VALUE rb_autoload_p(VALUE, ID); -VALUE rb_f_trace_var(int, const VALUE*); -VALUE rb_f_untrace_var(int, const VALUE*); -VALUE rb_f_global_variables(void); -void rb_alias_variable(ID, ID); -void rb_copy_generic_ivar(VALUE,VALUE); -void rb_free_generic_ivar(VALUE); -VALUE rb_ivar_get(VALUE, ID); -VALUE rb_ivar_set(VALUE, ID, VALUE); -VALUE rb_ivar_defined(VALUE, ID); -void rb_ivar_foreach(VALUE, int (*)(ID, VALUE, st_data_t), st_data_t); -st_index_t rb_ivar_count(VALUE); -VALUE rb_attr_get(VALUE, ID); -VALUE rb_obj_instance_variables(VALUE); -VALUE rb_obj_remove_instance_variable(VALUE, VALUE); -void *rb_mod_const_at(VALUE, void*); -void *rb_mod_const_of(VALUE, void*); -VALUE rb_const_list(void*); -VALUE rb_mod_constants(int, const VALUE *, VALUE); -VALUE rb_mod_remove_const(VALUE, VALUE); -int rb_const_defined(VALUE, ID); -int rb_const_defined_at(VALUE, ID); -int rb_const_defined_from(VALUE, ID); -VALUE rb_const_get(VALUE, ID); -VALUE rb_const_get_at(VALUE, ID); -VALUE rb_const_get_from(VALUE, ID); -void rb_const_set(VALUE, ID, VALUE); -VALUE rb_const_remove(VALUE, ID); -#if 0 /* EXPERIMENTAL: remove if no problem */ -NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE)); -#endif -VALUE rb_cvar_defined(VALUE, ID); -void rb_cvar_set(VALUE, ID, VALUE); -VALUE rb_cvar_get(VALUE, ID); -void rb_cv_set(VALUE, const char*, VALUE); -VALUE rb_cv_get(VALUE, const char*); -void rb_define_class_variable(VALUE, const char*, VALUE); -VALUE rb_mod_class_variables(int, const VALUE*, VALUE); -VALUE rb_mod_remove_cvar(VALUE, VALUE); - -ID rb_frame_callee(void); -int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); -VALUE rb_str_succ(VALUE); -VALUE rb_time_succ(VALUE); -VALUE rb_make_backtrace(void); -VALUE rb_make_exception(int, const VALUE*); - -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -extern "C++" { -#endif - -#if defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) -# define rb_f_notimplement_p(f) __builtin_types_compatible_p(__typeof__(f),__typeof__(rb_f_notimplement)) -#else -# define rb_f_notimplement_p(f) 0 -#endif - -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) && !defined(_WIN32) && !defined(__CYGWIN__) -#if defined(__has_attribute) && __has_attribute(transparent_union) && __has_attribute(unused) && __has_attribute(weakref) && __has_attribute(nonnull) -#define RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \ - __attribute__((__unused__,__weakref__(#def),__nonnull__ nonnull))static void defname(RB_UNWRAP_MACRO decl,VALUE(*func)funcargs,int arity); -#endif -#endif - -#if defined(RB_METHOD_DEFINITION_DECL_C) || defined(__cplusplus) -#ifndef RB_METHOD_DEFINITION_DECL_C -#define RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \ - static inline void defname(RB_UNWRAP_MACRO decl,VALUE(*func)funcargs,int arity) \ - { \ - def(RB_UNWRAP_MACRO vars,(VALUE(*)(ANYARGS))(func),arity); \ - } -#endif - -#define RB_UNWRAP_MACRO(...) __VA_ARGS__ - -#ifdef __cplusplus -#define RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) template struct def##_tmpl {}; -#define RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity) \ - template <> struct def##_tmpl { \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)funcargs) {::defname(RB_UNWRAP_MACRO vars, func, arity);} \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(...)) {::defname(RB_UNWRAP_MACRO vars, reinterpret_cast(func), arity);} \ - }; -#else -#define RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) /* nothing */ -#define RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity) /* nothing */ -#endif -#define RB_METHOD_DEFINITION_DECL_1(def,nonnull,defname,arity,decl,vars,funcargs) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \ - RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity) - -#define RB_METHOD_DEFINITION_DECL(def,nonnull,decl,vars) \ -RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##0 ,0 ,decl,vars,(VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##1 ,1 ,decl,vars,(VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##2 ,2 ,decl,vars,(VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##3 ,3 ,decl,vars,(VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##4 ,4 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##5 ,5 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##6 ,6 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##7 ,7 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##8 ,8 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##9 ,9 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##10,10,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##11,11,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##12,12,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##13,13,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##14,14,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##15,15,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_M3(def,nonnull,def##m3,decl,vars) \ -RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##m2,-2,decl,vars,(VALUE,VALUE)) \ -RB_METHOD_DEFINITION_DECL_M1(def,nonnull,def##m1,decl,vars) /* END */ -#ifdef __cplusplus -#define RB_METHOD_DEFINITION_DECL_M1(def,nonnull,defname,decl,vars) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,VALUE*,VALUE)) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,const VALUE*,VALUE)) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,const VALUE*,VALUE,VALUE)) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(...)) \ - template <> struct def##_tmpl<-1> { \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,VALUE*,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,const VALUE*,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,const VALUE*,VALUE,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \ - static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(...)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \ - }; -#define RB_METHOD_DEFINITION_DECL_M3(def,nonnull,defname,decl,vars) /* nothing */ -#else -#define RB_METHOD_DEFINITION_DECL_M1(def,nonnull,defname,decl,vars) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,union{VALUE*x;const VALUE*y;}__attribute__((__transparent_union__)),VALUE)) -#define RB_METHOD_DEFINITION_DECL_M3(def,nonnull,defname,decl,vars) \ - RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,()) -#endif - -#endif - -#ifdef RB_METHOD_DEFINITION_DECL - -RB_METHOD_DEFINITION_DECL(rb_define_method_id, (3), (VALUE klass, ID name), (klass, name)) -#ifdef __cplusplus -#define rb_define_method_id(m, n, f, a) rb_define_method_id_tmpl::define(m, n, f) -#else -#define rb_define_method_id_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_method_id15,rb_define_method_idm3) -#define rb_define_method_id_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_method_id14,rb_define_method_id_choose_prototype15(n)) -#define rb_define_method_id_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_method_id13,rb_define_method_id_choose_prototype14(n)) -#define rb_define_method_id_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_method_id12,rb_define_method_id_choose_prototype13(n)) -#define rb_define_method_id_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_method_id11,rb_define_method_id_choose_prototype12(n)) -#define rb_define_method_id_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_method_id10,rb_define_method_id_choose_prototype11(n)) -#define rb_define_method_id_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_method_id9, rb_define_method_id_choose_prototype10(n)) -#define rb_define_method_id_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_method_id8, rb_define_method_id_choose_prototype9(n)) -#define rb_define_method_id_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_method_id7, rb_define_method_id_choose_prototype8(n)) -#define rb_define_method_id_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_method_id6, rb_define_method_id_choose_prototype7(n)) -#define rb_define_method_id_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_method_id5, rb_define_method_id_choose_prototype6(n)) -#define rb_define_method_id_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_method_id4, rb_define_method_id_choose_prototype5(n)) -#define rb_define_method_id_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_method_id3, rb_define_method_id_choose_prototype4(n)) -#define rb_define_method_id_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_method_id2, rb_define_method_id_choose_prototype3(n)) -#define rb_define_method_id_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_method_id1, rb_define_method_id_choose_prototype2(n)) -#define rb_define_method_id_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_method_id0, rb_define_method_id_choose_prototype1(n)) -#define rb_define_method_id_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_method_idm1,rb_define_method_id_choose_prototype0(n)) -#define rb_define_method_id_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_method_idm2,rb_define_method_id_choose_prototypem1(n)) -#define rb_define_method_id_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_method_idm3,rb_define_method_id_choose_prototypem2(n)) -#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -RB_METHOD_DEFINITION_DECL(rb_define_protected_method, (2,3), (VALUE klass, const char *name), (klass, name)) -#ifdef __cplusplus -#define rb_define_protected_method(m, n, f, a) rb_define_protected_method_tmpl::define(m, n, f) -#else -#define rb_define_protected_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_protected_method15,rb_define_protected_methodm3) -#define rb_define_protected_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_protected_method14,rb_define_protected_method_choose_prototype15(n)) -#define rb_define_protected_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_protected_method13,rb_define_protected_method_choose_prototype14(n)) -#define rb_define_protected_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_protected_method12,rb_define_protected_method_choose_prototype13(n)) -#define rb_define_protected_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_protected_method11,rb_define_protected_method_choose_prototype12(n)) -#define rb_define_protected_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_protected_method10,rb_define_protected_method_choose_prototype11(n)) -#define rb_define_protected_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_protected_method9, rb_define_protected_method_choose_prototype10(n)) -#define rb_define_protected_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_protected_method8, rb_define_protected_method_choose_prototype9(n)) -#define rb_define_protected_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_protected_method7, rb_define_protected_method_choose_prototype8(n)) -#define rb_define_protected_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_protected_method6, rb_define_protected_method_choose_prototype7(n)) -#define rb_define_protected_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_protected_method5, rb_define_protected_method_choose_prototype6(n)) -#define rb_define_protected_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_protected_method4, rb_define_protected_method_choose_prototype5(n)) -#define rb_define_protected_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_protected_method3, rb_define_protected_method_choose_prototype4(n)) -#define rb_define_protected_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_protected_method2, rb_define_protected_method_choose_prototype3(n)) -#define rb_define_protected_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_protected_method1, rb_define_protected_method_choose_prototype2(n)) -#define rb_define_protected_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_protected_method0, rb_define_protected_method_choose_prototype1(n)) -#define rb_define_protected_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_protected_methodm1,rb_define_protected_method_choose_prototype0(n)) -#define rb_define_protected_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_protected_methodm2,rb_define_protected_method_choose_prototypem1(n)) -#define rb_define_protected_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_protected_methodm3,rb_define_protected_method_choose_prototypem2(n)) -#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -RB_METHOD_DEFINITION_DECL(rb_define_private_method, (2,3), (VALUE klass, const char *name), (klass, name)) -#ifdef __cplusplus -#define rb_define_private_method(m, n, f, a) rb_define_private_method_tmpl::define(m, n, f) -#else -#define rb_define_private_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_private_method15,rb_define_private_methodm3) -#define rb_define_private_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_private_method14,rb_define_private_method_choose_prototype15(n)) -#define rb_define_private_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_private_method13,rb_define_private_method_choose_prototype14(n)) -#define rb_define_private_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_private_method12,rb_define_private_method_choose_prototype13(n)) -#define rb_define_private_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_private_method11,rb_define_private_method_choose_prototype12(n)) -#define rb_define_private_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_private_method10,rb_define_private_method_choose_prototype11(n)) -#define rb_define_private_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_private_method9, rb_define_private_method_choose_prototype10(n)) -#define rb_define_private_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_private_method8, rb_define_private_method_choose_prototype9(n)) -#define rb_define_private_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_private_method7, rb_define_private_method_choose_prototype8(n)) -#define rb_define_private_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_private_method6, rb_define_private_method_choose_prototype7(n)) -#define rb_define_private_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_private_method5, rb_define_private_method_choose_prototype6(n)) -#define rb_define_private_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_private_method4, rb_define_private_method_choose_prototype5(n)) -#define rb_define_private_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_private_method3, rb_define_private_method_choose_prototype4(n)) -#define rb_define_private_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_private_method2, rb_define_private_method_choose_prototype3(n)) -#define rb_define_private_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_private_method1, rb_define_private_method_choose_prototype2(n)) -#define rb_define_private_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_private_method0, rb_define_private_method_choose_prototype1(n)) -#define rb_define_private_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_private_methodm1,rb_define_private_method_choose_prototype0(n)) -#define rb_define_private_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_private_methodm2,rb_define_private_method_choose_prototypem1(n)) -#define rb_define_private_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_private_methodm3,rb_define_private_method_choose_prototypem2(n)) -#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -RB_METHOD_DEFINITION_DECL(rb_define_singleton_method, (2,3), (VALUE klass, const char *name), (klass, name)) -#ifdef __cplusplus -#define rb_define_singleton_method(m, n, f, a) rb_define_singleton_method_tmpl::define(m, n, f) -#else -#define rb_define_singleton_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_singleton_method15,rb_define_singleton_methodm3) -#define rb_define_singleton_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_singleton_method14,rb_define_singleton_method_choose_prototype15(n)) -#define rb_define_singleton_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_singleton_method13,rb_define_singleton_method_choose_prototype14(n)) -#define rb_define_singleton_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_singleton_method12,rb_define_singleton_method_choose_prototype13(n)) -#define rb_define_singleton_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_singleton_method11,rb_define_singleton_method_choose_prototype12(n)) -#define rb_define_singleton_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_singleton_method10,rb_define_singleton_method_choose_prototype11(n)) -#define rb_define_singleton_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_singleton_method9, rb_define_singleton_method_choose_prototype10(n)) -#define rb_define_singleton_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_singleton_method8, rb_define_singleton_method_choose_prototype9(n)) -#define rb_define_singleton_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_singleton_method7, rb_define_singleton_method_choose_prototype8(n)) -#define rb_define_singleton_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_singleton_method6, rb_define_singleton_method_choose_prototype7(n)) -#define rb_define_singleton_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_singleton_method5, rb_define_singleton_method_choose_prototype6(n)) -#define rb_define_singleton_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_singleton_method4, rb_define_singleton_method_choose_prototype5(n)) -#define rb_define_singleton_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_singleton_method3, rb_define_singleton_method_choose_prototype4(n)) -#define rb_define_singleton_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_singleton_method2, rb_define_singleton_method_choose_prototype3(n)) -#define rb_define_singleton_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_singleton_method1, rb_define_singleton_method_choose_prototype2(n)) -#define rb_define_singleton_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_singleton_method0, rb_define_singleton_method_choose_prototype1(n)) -#define rb_define_singleton_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_singleton_methodm1,rb_define_singleton_method_choose_prototype0(n)) -#define rb_define_singleton_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_singleton_methodm2,rb_define_singleton_method_choose_prototypem1(n)) -#define rb_define_singleton_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_singleton_methodm3,rb_define_singleton_method_choose_prototypem2(n)) -#define rb_define_singleton_method(klass, mid, func, arity) rb_define_singleton_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -#endif - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C++" { */ -#endif +#include "ruby/internal/intern/array.h" +#include "ruby/internal/intern/bignum.h" +#include "ruby/internal/intern/class.h" +#include "ruby/internal/intern/compar.h" +#include "ruby/internal/intern/complex.h" +#include "ruby/internal/intern/cont.h" +#include "ruby/internal/intern/dir.h" +#include "ruby/internal/intern/enum.h" +#include "ruby/internal/intern/enumerator.h" +#include "ruby/internal/intern/error.h" +#include "ruby/internal/intern/eval.h" +#include "ruby/internal/intern/file.h" +#include "ruby/internal/intern/gc.h" +#include "ruby/internal/intern/hash.h" +#include "ruby/internal/intern/io.h" +#include "ruby/internal/intern/load.h" +#include "ruby/internal/intern/marshal.h" +#include "ruby/internal/intern/numeric.h" +#include "ruby/internal/intern/object.h" +#include "ruby/internal/intern/parse.h" +#include "ruby/internal/intern/proc.h" +#include "ruby/internal/intern/process.h" +#include "ruby/internal/intern/random.h" +#include "ruby/internal/intern/range.h" +#include "ruby/internal/intern/rational.h" +#include "ruby/internal/intern/re.h" +#include "ruby/internal/intern/ruby.h" +#include "ruby/internal/intern/select.h" +#include "ruby/internal/intern/signal.h" +#include "ruby/internal/intern/sprintf.h" +#include "ruby/internal/intern/string.h" +#include "ruby/internal/intern/struct.h" +#include "ruby/internal/intern/thread.h" +#include "ruby/internal/intern/time.h" +#include "ruby/internal/intern/variable.h" +#include "ruby/internal/intern/vm.h" #endif /* RUBY_INTERN_H */ diff --git a/ruby/include/ruby/internal/anyargs.h b/ruby/include/ruby/internal/anyargs.h new file mode 100644 index 000000000..9d8d16fda --- /dev/null +++ b/ruby/include/ruby/internal/anyargs.h @@ -0,0 +1,375 @@ +#ifndef RBIMPL_ANYARGS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ANYARGS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Function overloads to issue warnings around #ANYARGS. + * + * For instance ::rb_define_method takes a pointer to #ANYARGS -ed functions, + * which in fact varies 18 different prototypes. We still need to preserve + * #ANYARGS for storages but why not check the consistencies if possible. With + * those complex macro overlays defined in this header file, use of a function + * pointer gets checked against the corresponding arity argument. + * + * ### Q&A ### + * + * - Q: Where did the magic number "18" came from in the description above? + * + * - A: Count the case branch of `vm_method.c:call_cfunc_invoker_func()`. Note + * also that the 18 branches has lasted for at least 25 years. See also + * commit 200e0ee2fd3c1c006c528874a88f684447215524. + * + * - Q: What is this `__weakref__` thing? + * + * - A: That is a kind of function overloading mechanism that GCC provides. In + * this case for instance `rb_define_method_00` is an alias of + * ::rb_define_method, with a strong type. + * + * - Q: What is this `__transparent_union__` thing? + * + * A: That is another kind of function overloading mechanism that GCC + * provides. In this case the attributed function pointer is either + * `VALUE(*)(int,VALUE*,VALUE)` or `VALUE(*)(int,const VALUE*,VALUE)`. + * + * This is better than `void*` or #ANYARGS because we can reject all other + * possibilities than the two. + * + * - Q: What does this #rb_define_method macro mean? + * + * - A: It selects appropriate alias of the ::rb_define_method function, + * depending on the last (arity) argument. + * + * - Q: Why the special case for ::rb_f_notimplement ? + * + * - A: Function pointer to ::rb_f_notimplement is special cased in + * `vm_method.c:rb_add_method_cfunc()`. That should be handled by the + * `__builtin_choose_expr` chain inside of #rb_define_method macro + * expansion. In order to do so, comparison like + * `(func == rb_f_notimplement)` is inappropriate for + * `__builtin_choose_expr`'s expression (which must be a compile-time + * integer constant but the address of ::rb_f_notimplement is not fixed + * until the linker). Instead we are using + * `__builtin_types_compatible_p`, and in doing so we need to distinguish + * ::rb_f_notimplement from others, by type. + */ +#include "ruby/internal/attr/maybe_unused.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/weakref.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/config.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/intern/class.h" +#include "ruby/internal/intern/vm.h" +#include "ruby/internal/method.h" +#include "ruby/internal/value.h" +#include "ruby/backward/2/stdarg.h" + +#if defined(__cplusplus) +# include "ruby/backward/cxxanyargs.hpp" + +#elif defined(_WIN32) || defined(__CYGWIN__) +# /* Skip due to [Bug #16134] */ + +#elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union) +# /* :TODO: improve here, please find a way to support. */ + +#elif ! defined(HAVE_VA_ARGS_MACRO) +# /* :TODO: improve here, please find a way to support. */ + +#else +# /** @cond INTERNAL_MACRO */ +# if ! defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) +# define RBIMPL_CFUNC_IS_rb_f_notimplement(f) 0 +# else +# define RBIMPL_CFUNC_IS_rb_f_notimplement(f) \ + __builtin_types_compatible_p( \ + __typeof__(f), \ + __typeof__(rb_f_notimplement)) +# endif + +# if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) (falsy) +# else +# define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) \ + __builtin_choose_expr( \ + __builtin_choose_expr( \ + __builtin_constant_p(expr), \ + (expr), 0), \ + (truthy), (falsy)) +# endif + +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_singleton_method_m2, rb_define_singleton_method_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_singleton_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_singleton_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_singleton_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_singleton_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_singleton_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_singleton_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_singleton_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_singleton_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_singleton_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_singleton_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_singleton_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_singleton_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_singleton_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_singleton_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_singleton_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_singleton_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_singleton_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_protected_method_m2, rb_define_protected_method_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_protected_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_protected_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_protected_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_protected_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_protected_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_protected_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_protected_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_protected_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_protected_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_protected_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_protected_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_protected_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_protected_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_protected_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_protected_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_protected_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_protected_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_private_method_m2, rb_define_private_method_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_private_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_private_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_private_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_private_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_private_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_private_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_private_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_private_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_private_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_private_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_private_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_private_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_private_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_private_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_private_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_private_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_private_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_module_function_m2, rb_define_module_function_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_module_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_module_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_module_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_module_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_module_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_module_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_module_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_module_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_module_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_module_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_module_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_module_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_module_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_module_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_module_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_module_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_module_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_global_function_m2, rb_define_global_function_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_global_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_global_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_global_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_global_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_global_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_global_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_global_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_global_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_global_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_global_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_global_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_global_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_global_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_global_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_global_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_global_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_global_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_id_m2, rb_define_method_id_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_id_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_id_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_id_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_id_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_id_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_id_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_id_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_id_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_id_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_id_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_id_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_id_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_id_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_id_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_id_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_id_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_id_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_m2, rb_define_method_m3) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n)) +# define RBIMPL_ANYARGS_ATTRSET(sym) RBIMPL_ATTR_MAYBE_UNUSED() RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_WEAKREF(sym) +# define RBIMPL_ANYARGS_DECL(sym, ...) \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _00(__VA_ARGS__, VALUE(*)(VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _01(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _02(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _03(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _04(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _05(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _06(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _07(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _08(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _09(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _10(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _11(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _12(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _13(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _14(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ +RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _15(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); +RBIMPL_ANYARGS_DECL(rb_define_singleton_method, VALUE, const char *) +RBIMPL_ANYARGS_DECL(rb_define_protected_method, VALUE, const char *) +RBIMPL_ANYARGS_DECL(rb_define_private_method, VALUE, const char *) +RBIMPL_ANYARGS_DECL(rb_define_module_function, VALUE, const char *) +RBIMPL_ANYARGS_DECL(rb_define_global_function, const char *) +RBIMPL_ANYARGS_DECL(rb_define_method_id, VALUE, ID) +RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) +/** @endcond */ + +/** + * @brief Defines klass\#mid. + * @see ::rb_define_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid. + * @see ::rb_define_method_id + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_method_id(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method_id((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines obj.mid. + * @see ::rb_define_singleton_method + * @param obj Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of obj.mid. + * @param arity Arity of obj.mid. + */ +#define rb_define_singleton_method(obj, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method((arity), (func))((obj), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid and make it protected. + * @see ::rb_define_protected_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_protected_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines klass\#mid and make it private. + * @see ::rb_define_private_method + * @param klass Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of klass\#mid. + * @param arity Arity of klass\#mid. + */ +#define rb_define_private_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_private_method((arity), (func))((klass), (mid), (func), (arity)) + +/** + * @brief Defines mod\#mid and make it a module function. + * @see ::rb_define_module_function + * @param mod Where the method lives. + * @param mid Name of the defining method. + * @param func Implementation of mod\#mid. + * @param arity Arity of mod\#mid. + */ +#define rb_define_module_function(mod, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_module_function((arity), (func))((mod), (mid), (func), (arity)) + +/** + * @brief Defines ::rb_mKerbel \#mid. + * @see ::rb_define_global_function + * @param mid Name of the defining method. + * @param func Implementation of ::rb_mKernel \#mid. + * @param arity Arity of ::rb_mKernel \#mid. + */ +#define rb_define_global_function(mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_global_function((arity), (func))((mid), (func), (arity)) + +#endif /* __cplusplus */ + +/** + * This macro is to properly cast a function parameter of *_define_method + * family. It has been around since 1.x era so you can maximise backwards + * compatibility by using it. + * + * ```CXX + * rb_define_method(klass, "method", RUBY_METHOD_FUNC(func), arity); + * ``` + * + * @param func A pointer to a function that implements a method. + */ +#if ! defined(RUBY_DEVEL) +# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) + +#elif ! RUBY_DEVEL +# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) + +#elif ! defined(rb_define_method) +# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) + +#else +# define RUBY_METHOD_FUNC(func) (func) + +#endif + +#endif /* RBIMPL_ANYARGS_H */ diff --git a/ruby/include/ruby/internal/arithmetic.h b/ruby/include/ruby/internal/arithmetic.h new file mode 100644 index 000000000..3f7840c38 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_ARITHMETIC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Conversion between C's arithmtic types and Ruby's numeric types. + */ +#include "ruby/internal/arithmetic/char.h" +#include "ruby/internal/arithmetic/double.h" +#include "ruby/internal/arithmetic/fixnum.h" +#include "ruby/internal/arithmetic/gid_t.h" +#include "ruby/internal/arithmetic/int.h" +#include "ruby/internal/arithmetic/intptr_t.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/arithmetic/long_long.h" +#include "ruby/internal/arithmetic/mode_t.h" +#include "ruby/internal/arithmetic/off_t.h" +#include "ruby/internal/arithmetic/pid_t.h" +#include "ruby/internal/arithmetic/short.h" +#include "ruby/internal/arithmetic/size_t.h" +#include "ruby/internal/arithmetic/st_data_t.h" +#include "ruby/internal/arithmetic/uid_t.h" +#endif /* RBIMPL_ARITHMETIC_H */ diff --git a/ruby/include/ruby/internal/arithmetic/char.h b/ruby/include/ruby/internal/arithmetic/char.h new file mode 100644 index 000000000..920fdc0c9 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/char.h @@ -0,0 +1,81 @@ +#ifndef RBIMPL_ARITHMETIC_CHAR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_CHAR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `char` and Ruby's. + */ +#include "ruby/internal/arithmetic/int.h" /* NUM2INT is here, but */ +#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here.*/ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rstring.h" +#include "ruby/internal/value_type.h" + +#define RB_NUM2CHR rb_num2char_inline /**< @alias{rb_num2char_inline} */ +#define NUM2CHR RB_NUM2CHR /**< @old{RB_NUM2CHR} */ +#define CHR2FIX RB_CHR2FIX /**< @old{RB_CHR2FIX} */ + +/** @cond INTERNAL_MACRO */ +#define RB_CHR2FIX RB_CHR2FIX +/** @endcond */ + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Converts a C's `unsigned char` into an instance of ::rb_cInteger. + * + * @param[in] c Arbitrary `unsigned char` value. + * @return An instance of ::rb_cInteger. + * + * @internal + * + * Nobody explicitly states this but in Ruby, a char means an unsigned integer + * value of range 0..255. This is a general principle. AFAIK there is no + * single line of code where char is signed. + */ +static inline VALUE +RB_CHR2FIX(unsigned char c) +{ + return RB_INT2FIX(c); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `char`. At the same time it + * accepts a String of more than one character, and returns its first byte. In + * the early days there was a Ruby level "character" literal `?c`, which + * roughly worked this way. + * + * @param[in] x Either a string or a numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `unsigned int`. + * @return The passed value converted into C's `char`. + */ +static inline char +rb_num2char_inline(VALUE x) +{ + if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1)) + return RSTRING_PTR(x)[0]; + else + return RBIMPL_CAST((char)RB_NUM2INT(x)); +} + +#endif /* RBIMPL_ARITHMETIC_CHAR_H */ diff --git a/ruby/include/ruby/internal/arithmetic/double.h b/ruby/include/ruby/internal/arithmetic/double.h new file mode 100644 index 000000000..229de47ae --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/double.h @@ -0,0 +1,72 @@ +#ifndef RBIMPL_ARITHMETIC_DOUBLE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_DOUBLE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `double` and Ruby's. + */ +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +#define NUM2DBL rb_num2dbl /**< @old{rb_num2dbl} */ +#define RFLOAT_VALUE rb_float_value /**< @old{rb_float_value} */ +#define DBL2NUM rb_float_new /**< @old{rb_float_new} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Converts an instance of ::rb_cNumeric into C's `double`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @return The passed value converted into C's `double`. + */ +double rb_num2dbl(VALUE num); + +RBIMPL_ATTR_PURE() +/** + * Extracts its double value from an instance of ::rb_cFloat. + * + * @param[in] num An instance of ::rb_cFloat. + * @pre Must not pass anything other than a Fixnum. + * @return The passed value converted into C's `double`. + */ +double rb_float_value(VALUE num); + +/** + * Converts a C's `double` into an instance of ::rb_cFloat. + * + * @param[in] d Arbitrary `double` value. + * @return An instance of ::rb_cFloat. + */ +VALUE rb_float_new(double d); + +/** + * Identical to rb_float_new(), except it does not generate Flonums. + * + * @param[in] d Arbitrary `double` value. + * @return An instance of ::rb_cFloat. + * + * @internal + * + * @shyouhei has no idea why it is here. + */ +VALUE rb_float_new_in_heap(double d); +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_ARITHMETIC_DOUBLE_H */ diff --git a/ruby/include/ruby/internal/arithmetic/fixnum.h b/ruby/include/ruby/internal/arithmetic/fixnum.h new file mode 100644 index 000000000..c8927ac82 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/fixnum.h @@ -0,0 +1,60 @@ +#ifndef RBIMPL_ARITHMETIC_FIXNUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_FIXNUM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Handling of integers formerly known as Fixnums. + */ +#include "ruby/backward/2/limits.h" + +#define FIXABLE RB_FIXABLE /**< @old{RB_FIXABLE} */ +#define FIXNUM_MAX RUBY_FIXNUM_MAX /**< @old{RUBY_FIXNUM_MAX} */ +#define FIXNUM_MIN RUBY_FIXNUM_MIN /**< @old{RUBY_FIXNUM_MIN} */ +#define NEGFIXABLE RB_NEGFIXABLE /**< @old{RB_NEGFIXABLE} */ +#define POSFIXABLE RB_POSFIXABLE /**< @old{RB_POSFIXABLE} */ + +/** + * Checks if the passed value is in range of fixnum, assuming it is a positive + * number. Can sometimes be useful for C's unsigned integer types. + * + * @internal + * + * FIXABLE can be applied to anything, from double to intmax_t. The problem is + * double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903, + * which is not representable by a double. The nearest value that a double can + * represent is 4,611,686,018,427,387,904, which is not fixable. The + * seemingly-strange "< FIXNUM_MAX + 1" expression below is due to this. + */ +#define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1) + +/** + * Checks if the passed value is in range of fixnum, assuming it is a negative + * number. This is an implementation of #RB_FIXABLE. Rarely used stand alone. + */ +#define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN) + +/** Checks if the passed value is in range of fixnum */ +#define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_)) + +/** Maximum possible value that a fixnum can represent. */ +#define RUBY_FIXNUM_MAX (LONG_MAX / 2) + +/** Minimum possible value that a fixnum can represent. */ +#define RUBY_FIXNUM_MIN (LONG_MIN / 2) + +#endif /* RBIMPL_ARITHMETIC_FIXNUM_H */ diff --git a/ruby/include/ruby/internal/arithmetic/gid_t.h b/ruby/include/ruby/internal/arithmetic/gid_t.h new file mode 100644 index 000000000..361220bfa --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/gid_t.h @@ -0,0 +1,41 @@ +#ifndef RBIMPL_ARITHMETIC_GID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_GID_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `gid_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/long.h" + +/** Converts a C's `gid_t` into an instance of ::rb_cInteger. */ +#ifndef GIDT2NUM +# define GIDT2NUM RB_LONG2NUM +#endif + +/** Converts an instance of ::rb_cNumeric into C's `gid_t`. */ +#ifndef NUM2GIDT +# define NUM2GIDT RB_NUM2LONG +#endif + +/** A rb_sprintf() format prefix to be used for a `gid_t` parameter. */ +#ifndef PRI_GIDT_PREFIX +# define PRI_GIDT_PREFIX PRI_LONG_PREFIX +#endif + +#endif /* RBIMPL_ARITHMETIC_GID_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/int.h b/ruby/include/ruby/internal/arithmetic/int.h new file mode 100644 index 000000000..6bd8ec218 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/int.h @@ -0,0 +1,264 @@ +#ifndef RBIMPL_ARITHMETIC_INT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_INT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `int` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/fixnum.h" +#include "ruby/internal/arithmetic/intptr_t.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/compiler_is.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/value.h" +#include "ruby/internal/warning_push.h" +#include "ruby/assert.h" + +#define RB_INT2NUM rb_int2num_inline /**< @alias{rb_int2num_inline} */ +#define RB_NUM2INT rb_num2int_inline /**< @alias{rb_num2int_inline} */ +#define RB_UINT2NUM rb_uint2num_inline /**< @alias{rb_uint2num_inline} */ + +#define FIX2INT RB_FIX2INT /**< @old{RB_FIX2INT} */ +#define FIX2UINT RB_FIX2UINT /**< @old{RB_FIX2UINT} */ +#define INT2NUM RB_INT2NUM /**< @old{RB_INT2NUM} */ +#define NUM2INT RB_NUM2INT /**< @old{RB_NUM2INT} */ +#define NUM2UINT RB_NUM2UINT /**< @old{RB_NUM2UINT} */ +#define UINT2NUM RB_UINT2NUM /**< @old{RB_UINT2NUM} */ + +/** @cond INTERNAL_MACRO */ +#define RB_FIX2INT RB_FIX2INT +#define RB_NUM2UINT RB_NUM2UINT +#define RB_FIX2UINT RB_FIX2UINT +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Converts an instance of ::rb_cNumeric into C's `long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `int`. + * @return The passed value converted into C's `long`. + * + * @internal + * + * Yes, the API is really strange. It returns `long`, but raises when the + * value is out of `int`. This seems to be due to the fact that Matz favoured + * K&R before, and his machine at that moment was an ILP32 architecture. + */ +long rb_num2int(VALUE num); + +/** + * Identical to rb_num2int(). + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `int`. + * @return The passed value converted into C's `long`. + * + * @internal + * + * This function seems to be a complete waste of disk space. @shyouhei has no + * idea why this is a different thing from rb_num2short(). + */ +long rb_fix2int(VALUE num); + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned int`. + * @return The passed value converted into C's `unsigned long`. + * + * @internal + * + * Yes, the API is really strange. It returns `unsigned long`, but raises when + * the value is out of `unsigned int`. This seems to be due to the fact that + * Matz favoured K&R before, and his machine at that moment was an ILP32 + * architecture. + */ +unsigned long rb_num2uint(VALUE num); + +/** + * Identical to rb_num2uint(). + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned int`. + * @return The passed value converted into C's `unsigned long`. + * + * @internal + * + * This function seems to be a complete waste of disk space. @shyouhei has no + * idea why this is a different thing from rb_num2short(). + */ +unsigned long rb_fix2uint(VALUE num); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Converts a Fixnum into C's `int`. + * + * @param[in] x Some Fixnum. + * @pre Must not pass anything other than a Fixnum. + * @return The passed value converted into C's `int`. + */ +static inline int +RB_FIX2INT(VALUE x) +{ + /* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if + * that is a desired behaviour but just preserve backwards compatilibily. + */ +#if 0 + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); +#endif + long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_fix2int(x); + } + else { + ret = RB_FIX2LONG(x); + } + + return RBIMPL_CAST((int)ret); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `int`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `int`. + * @return The passed value converted into C's `int`. + */ +static inline int +rb_num2int_inline(VALUE x) +{ + long ret; + + if /* constexpr */ (sizeof(int) == sizeof(long)) { + ret = RB_NUM2LONG(x); + } + else if (RB_FIXNUM_P(x)) { + ret = rb_fix2int(x); + } + else { + ret = rb_num2int(x); + } + + return RBIMPL_CAST((int)ret); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned int`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `unsigned int`. + * @return The passed value converted into C's `unsigned int`. + */ +RBIMPL_ATTR_ARTIFICIAL() +static inline unsigned int +RB_NUM2UINT(VALUE x) +{ + unsigned long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_num2uint(x); + } + else { + ret = RB_NUM2ULONG(x); + } + + return RBIMPL_CAST((unsigned int)ret); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Converts a Fixnum into C's `int`. + * + * @param[in] x Some Fixnum. + * @pre Must not pass anything other than a Fixnum. + * @return The passed value converted into C's `int`. + */ +static inline unsigned int +RB_FIX2UINT(VALUE x) +{ +#if 0 /* Ditto for RB_FIX2INT. */ + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); +#endif + unsigned long ret; + + if /* constexpr */ (sizeof(int) < sizeof(long)) { + ret = rb_fix2uint(x); + } + else { + ret = RB_FIX2ULONG(x); + } + + return RBIMPL_CAST((unsigned int)ret); +} + +RBIMPL_WARNING_PUSH() +#if RBIMPL_COMPILER_IS(GCC) +RBIMPL_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */ +#elif RBIMPL_HAS_WARNING("-Wtautological-constant-out-of-range-compare") +RBIMPL_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare) +#endif + +/** + * Converts a C's `int` into an instance of ::rb_cInteger. + * + * @param[in] v Arbitrary `int` value. + * @return An instance of ::rb_cInteger. + */ +static inline VALUE +rb_int2num_inline(int v) +{ + if (RB_FIXABLE(v)) + return RB_INT2FIX(v); + else + return rb_int2big(v); +} + +/** + * Converts a C's `unsigned int` into an instance of ::rb_cInteger. + * + * @param[in] v Arbitrary `unsigned int` value. + * @return An instance of ::rb_cInteger. + */ +static inline VALUE +rb_uint2num_inline(unsigned int v) +{ + if (RB_POSFIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_uint2big(v); +} + +RBIMPL_WARNING_POP() + +#endif /* RBIMPL_ARITHMETIC_INT_H */ diff --git a/ruby/include/ruby/internal/arithmetic/intptr_t.h b/ruby/include/ruby/internal/arithmetic/intptr_t.h new file mode 100644 index 000000000..a354f4469 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/intptr_t.h @@ -0,0 +1,74 @@ +#ifndef RBIMPL_ARITHMETIC_INTPTR_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_INTPTR_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `intptr_t` and Ruby's. + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_STDINT_H +# include +#endif + +#include "ruby/internal/value.h" +#include "ruby/internal/dllexport.h" + +#define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */ +#define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Converts a C's `intptr_t` into an instance of ::rb_cInteger. + * + * @param[in] i Arbitrary `intptr_t` value. + * @return An instance of ::rb_cInteger. + * @note This function always allocates Bignums, even if the given number + * is small enough to fit into a Fixnum. + */ +VALUE rb_int2big(intptr_t i); + +/** + * Converts a C's `intptr_t` into an instance of ::rb_cInteger. + * + * @param[in] i Arbitrary `intptr_t` value. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_int2inum(intptr_t i); + +/** + * Converts a C's `intptr_t` into an instance of ::rb_cInteger. + * + * @param[in] i Arbitrary `intptr_t` value. + * @return An instance of ::rb_cInteger. + * @note This function always allocates Bignums, even if the given number + * is small enough to fit into a Fixnum. + */ +VALUE rb_uint2big(uintptr_t i); + +/** + * Converts a C's `uintptr_t` into an instance of ::rb_cInteger. + * + * @param[in] i Arbitrary `uintptr_t` value. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_uint2inum(uintptr_t i); +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_ARITHMETIC_INTPTR_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/long.h b/ruby/include/ruby/internal/arithmetic/long.h new file mode 100644 index 000000000..792f7be17 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/long.h @@ -0,0 +1,356 @@ +#ifndef RBIMPL_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_LONG_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `long` and Ruby's. + * + * ### Q&A ### + * + * - Q: Why are INT2FIX etc. here, not in `int.h`? + * + * - A: Because they are in fact handling `long`. It seems someone did not + * understand the difference of `int` and `long` when they designed those + * macros. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/fixnum.h" /* FIXABLE */ +#include "ruby/internal/arithmetic/intptr_t.h" /* rb_int2big etc.*/ +#include "ruby/internal/assume.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" /* FIXNUM_FLAG */ +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +#define FIX2LONG RB_FIX2LONG /**< @old{RB_FIX2LONG} */ +#define FIX2ULONG RB_FIX2ULONG /**< @old{RB_FIX2ULONG} */ +#define INT2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */ +#define LONG2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */ +#define LONG2NUM RB_LONG2NUM /**< @old{RB_LONG2NUM} */ +#define NUM2LONG RB_NUM2LONG /**< @old{RB_NUM2LONG} */ +#define NUM2ULONG RB_NUM2ULONG /**< @old{RB_NUM2ULONG} */ +#define RB_FIX2LONG rb_fix2long /**< @alias{rb_fix2long} */ +#define RB_FIX2ULONG rb_fix2ulong /**< @alias{rb_fix2ulong} */ +#define RB_LONG2FIX RB_INT2FIX /**< @alias{RB_INT2FIX} */ +#define RB_LONG2NUM rb_long2num_inline /**< @alias{rb_long2num_inline} */ +#define RB_NUM2LONG rb_num2long_inline /**< @alias{rb_num2long_inline} */ +#define RB_NUM2ULONG rb_num2ulong_inline /**< @alias{rb_num2ulong_inline} */ +#define RB_ULONG2NUM rb_ulong2num_inline /**< @alias{rb_ulong2num_inline} */ +#define ULONG2NUM RB_ULONG2NUM /**< @old{RB_ULONG2NUM} */ +#define rb_fix_new RB_INT2FIX /**< @alias{RB_INT2FIX} */ +#define rb_long2int rb_long2int_inline /**< @alias{rb_long2int_inline} */ + +/** @cond INTERNAL_MACRO */ +#define RB_INT2FIX RB_INT2FIX +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_COLD() +/** + * This is an utility function to raise an ::rb_eRangeError. + * + * @param[in] num A signed value about to overflow. + * @exception rb_eRangeError `num` is out of range of `int`. + */ +void rb_out_of_int(SIGNED_VALUE num); + +/** + * Converts an instance of ::rb_cNumeric into C's `long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `long`. + * @return The passed value converted into C's `long`. + */ +long rb_num2long(VALUE num); + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned long`. + * @return The passed value converted into C's `unsigned long`. + */ +unsigned long rb_num2ulong(VALUE num); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Converts a C's `long` into an instance of ::rb_cInteger. + * + * @param[in] i Arbitrary `long` value. + * @return An instance of ::rb_cInteger. + */ +static inline VALUE +RB_INT2FIX(long i) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(i)); + + /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully + * defined. Also it can be compiled into a single LEA instruction. */ + const unsigned long j = i; + const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG; + const long l = k; + const SIGNED_VALUE m = l; /* Sign extend */ + const VALUE n = m; + + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n)); + return n; +} + +/** + * Checks if `int` can hold the given integer. + * + * @param[in] n Arbitrary `long` value. + * @exception rb_eRangeError `n` is out of range of `int`. + * @return Identical value of type `int` + */ +static inline int +rb_long2int_inline(long n) +{ + int i = RBIMPL_CAST((int)n); + + if /* constexpr */ (sizeof(long) <= sizeof(int)) { + RBIMPL_ASSUME(i == n); + } + + if (i != n) + rb_out_of_int(n); + + return i; +} + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +/** + * @private + * + * This is an implementation detail of rb_fix2long(). People don't use it + * directly. + * + * @param[in] x A Fixnum. + * @return Identical value of type `long` + * @pre Must not pass anything other than a Fixnum. + */ +static inline long +rbimpl_fix2long_by_idiv(VALUE x) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + + /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because + * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1 + * below. */ + const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG; + const SIGNED_VALUE z = y / 2; + const long w = RBIMPL_CAST((long)z); + + RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); + return w; +} + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +/** + * @private + * + * This is an implementation detail of rb_fix2long(). People don't use it + * directly. + * + * @param[in] x A Fixnum. + * @return Identical value of type `long` + * @pre Must not pass anything other than a Fixnum. + */ +static inline long +rbimpl_fix2long_by_shift(VALUE x) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + + /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this + * is noticeably faster than above. */ + const SIGNED_VALUE y = x; + const SIGNED_VALUE z = y >> 1; + const long w = RBIMPL_CAST((long)z); + + RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); + return w; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +/** + * @private + * + * This is an implementation detail of rb_fix2long(). People don't use it + * directly. + * + * @retval true This C compiler's right shift operator is arithmetic. + * @retval false This C compiler's right shift operator is logical. + */ +static inline bool +rbimpl_right_shift_is_arithmetic_p(void) +{ + return (-1 >> 1) == -1; +} + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +/** + * Converts a Fixnum into C's `long`. + * + * @param[in] x Some Fixnum. + * @pre Must not pass anything other than a Fixnum. + * @return The passed value converted into C's `long`. + */ +static inline long +rb_fix2long(VALUE x) +{ + if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) { + return rbimpl_fix2long_by_shift(x); + } + else { + return rbimpl_fix2long_by_idiv(x); + } +} + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +/** + * Converts a Fixnum into C's `unsigned long`. + * + * @param[in] x Some Fixnum. + * @pre Must not pass anything other than a Fixnum. + * @return The passed value converted into C's `unsigned long`. + * @note Negative fixnums will be converted into large unsigned longs. + */ +static inline unsigned long +rb_fix2ulong(VALUE x) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); + return rb_fix2long(x); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `long`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `long`. + * @return The passed value converted into C's `long`. + */ +static inline long +rb_num2long_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2LONG(x); + else + return rb_num2long(x); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned long`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `unsigned long`. + * @return The passed value converted into C's `unsigned long`. + * + * @internal + * + * This (negative fixnum would become a large unsigned long while negative + * bignum is an exception) has been THE behaviour of NUM2ULONG since the + * beginning. It is strange, but we can no longer change how it works at this + * moment. We have to get by with it. + * + * @see https://bugs.ruby-lang.org/issues/9089 + */ +static inline unsigned long +rb_num2ulong_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2ULONG(x); + else + return rb_num2ulong(x); +} + +/** + * Converts a C's `long` into an instance of ::rb_cInteger. + * + * @param[in] v Arbitrary `long` value. + * @return An instance of ::rb_cInteger. + */ +static inline VALUE +rb_long2num_inline(long v) +{ + if (RB_FIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_int2big(v); +} + +/** + * Converts a C's `unsigned long` into an instance of ::rb_cInteger. + * + * @param[in] v Arbitrary `unsigned long` value. + * @return An instance of ::rb_cInteger. + */ +static inline VALUE +rb_ulong2num_inline(unsigned long v) +{ + if (RB_POSFIXABLE(v)) + return RB_LONG2FIX(v); + else + return rb_uint2big(v); +} + +/** + * @cond INTERNAL_MACRO + * + * Following overload is necessary because sometimes INT2FIX is used as a enum + * value (e.g. `enum { FOO = INT2FIX(0) };`). THIS IS NG in theory because a + * VALUE does not fit into an enum (which must be a signed int). But we cannot + * break existing codes. + */ +#if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 +# /* C++ can write constexpr as enum values. */ + +#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# undef INT2FIX +# define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG) + +#else +# undef INT2FIX +# define INT2FIX(i) \ + __builtin_choose_expr( \ + __builtin_constant_p(i), \ + RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \ + RB_INT2FIX(i)) +#endif +/** @endcond */ + +#endif /* RBIMPL_ARITHMETIC_LONG_H */ diff --git a/ruby/include/ruby/internal/arithmetic/long_long.h b/ruby/include/ruby/internal/arithmetic/long_long.h new file mode 100644 index 000000000..65dec8729 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/long_long.h @@ -0,0 +1,135 @@ +#ifndef RBIMPL_ARITHMETIC_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_LONG_LONG_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `long long` and Ruby's. + */ +#include "ruby/internal/value.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" +#include "ruby/backward/2/long_long.h" + +#define RB_LL2NUM rb_ll2num_inline /**< @alias{rb_ll2num_inline} */ +#define RB_ULL2NUM rb_ull2num_inline /**< @alias{rb_ull2num_inline} */ +#define LL2NUM RB_LL2NUM /**< @old{RB_LL2NUM} */ +#define ULL2NUM RB_ULL2NUM /**< @old{RB_ULL2NUM} */ +#define RB_NUM2LL rb_num2ll_inline /**< @alias{rb_num2ll_inline} */ +#define RB_NUM2ULL rb_num2ull_inline /**< @alias{rb_num2ull_inline} */ +#define NUM2LL RB_NUM2LL /**< @old{RB_NUM2LL} */ +#define NUM2ULL RB_NUM2ULL /**< @old{RB_NUM2ULL} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Converts a C's `long long` into an instance of ::rb_cInteger. + * + * @param[in] num Arbitrary `long long` value. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_ll2inum(LONG_LONG num); + +/** + * Converts a C's `unsigned long long` into an instance of ::rb_cInteger. + * + * @param[in] num Arbitrary `unsigned long long` value. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_ull2inum(unsigned LONG_LONG num); + +/** + * Converts an instance of ::rb_cNumeric into C's `long long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `long long`. + * @return The passed value converted into C's `long long`. + */ +LONG_LONG rb_num2ll(VALUE num); + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned long long`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned long long`. + * @return The passed value converted into C's `unsigned long long`. + */ +unsigned LONG_LONG rb_num2ull(VALUE num); +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Converts a C's `long long` into an instance of ::rb_cInteger. + * + * @param[in] n Arbitrary `long long` value. + * @return An instance of ::rb_cInteger + */ +static inline VALUE +rb_ll2num_inline(LONG_LONG n) +{ + if (FIXABLE(n)) return LONG2FIX((long)n); + return rb_ll2inum(n); +} + +/** + * Converts a C's `unsigned long long` into an instance of ::rb_cInteger. + * + * @param[in] n Arbitrary `unsigned long long` value. + * @return An instance of ::rb_cInteger + */ +static inline VALUE +rb_ull2num_inline(unsigned LONG_LONG n) +{ + if (POSFIXABLE(n)) return LONG2FIX((long)n); + return rb_ull2inum(n); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `long long`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `long long`. + * @return The passed value converted into C's `long long`. + */ +static inline LONG_LONG +rb_num2ll_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2LONG(x); + else + return rb_num2ll(x); +} + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned long long`. + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `unsigned long long`. + * @return The passed value converted into C's `unsigned long long`. + */ +static inline unsigned LONG_LONG +rb_num2ull_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return RB_FIX2LONG(x); + else + return rb_num2ull(x); +} + +#endif /* RBIMPL_ARITHMETIC_LONG_LONG_H */ diff --git a/ruby/include/ruby/internal/arithmetic/mode_t.h b/ruby/include/ruby/internal/arithmetic/mode_t.h new file mode 100644 index 000000000..5b7ad35fb --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/mode_t.h @@ -0,0 +1,41 @@ +#ifndef RBIMPL_ARITHMETIC_MODE_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_MODE_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `mode_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/int.h" + +/** Converts a C's `mode_t` into an instance of ::rb_cInteger. */ +#ifndef NUM2MODET +# define NUM2MODET RB_NUM2INT +#endif + +/** Converts an instance of ::rb_cNumeric into C's `mode_t`. */ +#ifndef MODET2NUM +# define MODET2NUM RB_INT2NUM +#endif + +/** A rb_sprintf() format prefix to be used for a `mode_t` parameter. */ +#ifndef PRI_MODET_PREFIX +# define PRI_MODET_PREFIX PRI_INT_PREFIX +#endif + +#endif /* RBIMPL_ARITHMETIC_MODE_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/off_t.h b/ruby/include/ruby/internal/arithmetic/off_t.h new file mode 100644 index 000000000..0ec9362cc --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/off_t.h @@ -0,0 +1,62 @@ +#ifndef RBIMPL_ARITHMETIC_OFF_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_OFF_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `off_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/int.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/arithmetic/long_long.h" +#include "ruby/backward/2/long_long.h" + +/** Converts a C's `off_t` into an instance of ::rb_cInteger. */ +#ifdef OFFT2NUM +# /* take that. */ +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +# define OFFT2NUM RB_LL2NUM +#elif SIZEOF_OFF_T == SIZEOF_LONG +# define OFFT2NUM RB_LONG2NUM +#else +# define OFFT2NUM RB_INT2NUM +#endif + +/** Converts an instance of ::rb_cNumeric into C's `off_t`. */ +#ifdef NUM2OFFT +# /* take that. */ +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +# define NUM2OFFT RB_NUM2LL +#elif SIZEOF_OFF_T == SIZEOF_LONG +# define NUM2OFFT RB_NUM2LONG +#else +# define NUM2OFFT RB_NUM2INT +#endif + +/** A rb_sprintf() format prefix to be used for an `off_t` parameter. */ +#ifdef PRI_OFFT_PREFIX +# /* take that. */ +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +# define PRI_OFFT_PREFIX PRI_LL_PREFIX +#elif SIZEOF_OFF_T == SIZEOF_LONG +# define PRI_OFFT_PREFIX PRI_LONG_PREFIX +#else +# define PRI_OFFT_PREFIX PRI_INT_PREFIX +#endif + +#endif /* RBIMPL_ARITHMETIC_OFF_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/pid_t.h b/ruby/include/ruby/internal/arithmetic/pid_t.h new file mode 100644 index 000000000..df9704e8f --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/pid_t.h @@ -0,0 +1,41 @@ +#ifndef RBIMPL_ARITHMETIC_PID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_PID_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `pid_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/long.h" + +/** Converts a C's `pid_t` into an instance of ::rb_cInteger. */ +#ifndef PIDT2NUM +# define PIDT2NUM RB_LONG2NUM +#endif + +/** Converts an instance of ::rb_cNumeric into C's `pid_t`. */ +#ifndef NUM2PIDT +# define NUM2PIDT RB_NUM2LONG +#endif + +/** A rb_sprintf() format prefix to be used for a `pid_t` parameter. */ +#ifndef PRI_PIDT_PREFIX +# define PRI_PIDT_PREFIX PRI_LONG_PREFIX +#endif + +#endif /* RBIMPL_ARITHMETIC_PID_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/short.h b/ruby/include/ruby/internal/arithmetic/short.h new file mode 100644 index 000000000..7a324d945 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/short.h @@ -0,0 +1,113 @@ +#ifndef RBIMPL_ARITHMETIC_SHORT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_SHORT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `short` and Ruby's. + * + * Shyouhei wonders: why there is no SHORT2NUM, given there are both + * #USHORT2NUM and #CHR2FIX? + */ +#include "ruby/internal/value.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" + +#define RB_NUM2SHORT rb_num2short_inline /**< @alias{rb_num2short_inline} */ +#define RB_NUM2USHORT rb_num2ushort /**< @alias{rb_num2ushort} */ +#define NUM2SHORT RB_NUM2SHORT /**< @old{RB_NUM2SHORT} */ +#define NUM2USHORT RB_NUM2USHORT /**< @old{RB_NUM2USHORT} */ +#define USHORT2NUM RB_INT2FIX /**< @old{RB_INT2FIX} */ +#define RB_FIX2SHORT rb_fix2short /**< @alias{rb_fix2ushort} */ +#define FIX2SHORT RB_FIX2SHORT /**< @old{RB_FIX2SHORT} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Converts an instance of ::rb_cNumeric into C's `short`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `short`. + * @return The passed value converted into C's `short`. + */ +short rb_num2short(VALUE num); + +/** + * Converts an instance of ::rb_cNumeric into C's `unsigned short`. + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned short`. + * @return The passed value converted into C's `unsigned short`. + */ +unsigned short rb_num2ushort(VALUE num); + +/** + * Identical to rb_num2short(). + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `short`. + * @return The passed value converted into C's `short`. + * + * @internal + * + * This function seems to be a complete waste of disk space. @shyouhei has no + * idea why this is a different thing from rb_num2short(). + */ +short rb_fix2short(VALUE num); + +/** + * Identical to rb_num2ushort(). + * + * @param[in] num Something numeric. + * @exception rb_eTypeError `num` is not a numeric. + * @exception rb_eRangeError `num` is out of range of `unsigned short`. + * @return The passed value converted into C's `unsigned short`. + * + * @internal + * + * This function seems to be a complete waste of disk space. @shyouhei has no + * idea why this is a different thing from rb_num2ushort(). + */ +unsigned short rb_fix2ushort(VALUE num); +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Identical to rb_num2short(). + * + * @param[in] x Something numeric. + * @exception rb_eTypeError `x` is not a numeric. + * @exception rb_eRangeError `x` is out of range of `short`. + * @return The passed value converted into C's `short`. + * + * @internal + * + * This function seems to be a complete waste of time. @shyouhei has no idea + * why this is a different thing from rb_num2short(). + */ +static inline short +rb_num2short_inline(VALUE x) +{ + if (RB_FIXNUM_P(x)) + return rb_fix2short(x); + else + return rb_num2short(x); +} + +#endif /* RBIMPL_ARITHMETIC_SHORT_H */ diff --git a/ruby/include/ruby/internal/arithmetic/size_t.h b/ruby/include/ruby/internal/arithmetic/size_t.h new file mode 100644 index 000000000..1082160b8 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/size_t.h @@ -0,0 +1,66 @@ +#ifndef RBIMPL_ARITHMETIC_SIZE_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_SIZE_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `size_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/int.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/arithmetic/long_long.h" +#include "ruby/backward/2/long_long.h" + +#if defined(__DOXYGEN__) +# /** Converts a C's `size_t` into an instance of ::rb_cInteger. */ +# define RB_SIZE2NUM RB_ULONG2NUM +# /** Converts a C's `ssize_t` into an instance of ::rb_cInteger. */ +# define RB_SSIZE2NUM RB_LONG2NUM +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define RB_SIZE2NUM RB_ULL2NUM +# define RB_SSIZE2NUM RB_LL2NUM +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define RB_SIZE2NUM RB_ULONG2NUM +# define RB_SSIZE2NUM RB_LONG2NUM +#else +# define RB_SIZE2NUM RB_UINT2NUM +# define RB_SSIZE2NUM RB_INT2NUM +#endif + +#if defined(__DOXYGEN__) +# /** Converts an instance of ::rb_cInteger into C's `size_t`. */ +# define RB_NUM2SIZE RB_NUM2ULONG +# /** Converts an instance of ::rb_cInteger into C's `ssize_t`. */ +# define RB_NUM2SSIZE RB_NUM2LONG +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +# define RB_NUM2SIZE RB_NUM2ULL +# define RB_NUM2SSIZE RB_NUM2LL +#elif SIZEOF_SIZE_T == SIZEOF_LONG +# define RB_NUM2SIZE RB_NUM2ULONG +# define RB_NUM2SSIZE RB_NUM2LONG +#else +# define RB_NUM2SIZE RB_NUM2UINT +# define RB_NUM2SSIZE RB_NUM2INT +#endif + +#define NUM2SIZET RB_NUM2SIZE /**< @old{RB_NUM2SIZE} */ +#define SIZET2NUM RB_SIZE2NUM /**< @old{RB_SIZE2NUM} */ +#define NUM2SSIZET RB_NUM2SSIZE /**< @old{RB_NUM2SSIZE} */ +#define SSIZET2NUM RB_SSIZE2NUM /**< @old{RB_SSIZE2NUM} */ + +#endif /* RBIMPL_ARITHMETIC_SIZE_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/st_data_t.h b/ruby/include/ruby/internal/arithmetic/st_data_t.h new file mode 100644 index 000000000..3bff4ffc0 --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/st_data_t.h @@ -0,0 +1,75 @@ +#ifndef RBIMPL_ARITHMERIC_ST_DATA_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMERIC_ST_DATA_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `st_data_t` and Ruby's. + */ +#include "ruby/internal/arithmetic/fixnum.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" +#include "ruby/st.h" + +#define ST2FIX RB_ST2FIX /**< @old{RB_ST2FIX} */ +/** @cond INTERNAL_MACRO */ +#define RB_ST2FIX RB_ST2FIX +/** @endcond */ + +RBIMPL_ATTR_CONST_UNLESS_DEBUG() +RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Converts a C's `st_data_t` into an instance of ::rb_cInteger. + * + * @param[in] i The data in question. + * @return A converted result + * @warning THIS CONVERSION LOSES DATA! Be warned. + * @see https://bugs.ruby-lang.org/issues/13877 + * @see https://bugs.ruby-lang.org/issues/14218 + * + * @internal + * + * This is needed because of hash functions. Hash functions return + * `st_data_t`, which could theoretically be bigger than Fixnums. However + * allocating Bignums for them every time we calculate hash values is just too + * heavy. To avoid penalty we need to ignore some upper bit(s) and stick to + * Fixnums. This function is used for that purpose. + */ +static inline VALUE +RB_ST2FIX(st_data_t i) +{ + SIGNED_VALUE x = i; + + if (x >= 0) { + x &= RUBY_FIXNUM_MAX; + } + else { + x |= RUBY_FIXNUM_MIN; + } + + RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x)); + unsigned long y = RBIMPL_CAST((unsigned long)x); + return RB_LONG2FIX(y); +} + +#endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */ diff --git a/ruby/include/ruby/internal/arithmetic/uid_t.h b/ruby/include/ruby/internal/arithmetic/uid_t.h new file mode 100644 index 000000000..12cde2a9c --- /dev/null +++ b/ruby/include/ruby/internal/arithmetic/uid_t.h @@ -0,0 +1,41 @@ +#ifndef RBIMPL_ARITHMETIC_UID_T_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ARITHMETIC_UID_T_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Arithmetic conversion between C's `uid_t` and Ruby's. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/long.h" + +/** Converts a C's `uid_t` into an instance of ::rb_cInteger. */ +#ifndef UIDT2NUM +# define UIDT2NUM RB_LONG2NUM +#endif + +/** Converts an instance of ::rb_cNumeric into C's `uid_t`. */ +#ifndef NUM2UIDT +# define NUM2UIDT RB_NUM2LONG +#endif + +/** A rb_sprintf() format prefix to be used for a `uid_t` parameter. */ +#ifndef PRI_UIDT_PREFIX +# define PRI_UIDT_PREFIX PRI_LONG_PREFIX +#endif + +#endif /* RBIMPL_ARITHMETIC_UID_T_H */ diff --git a/ruby/include/ruby/internal/assume.h b/ruby/include/ruby/internal/assume.h new file mode 100644 index 000000000..65d34d4ac --- /dev/null +++ b/ruby/include/ruby/internal/assume.h @@ -0,0 +1,90 @@ +#ifndef RBIMPL_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ASSUME_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ASSUME / #RBIMPL_UNREACHABLE. + * + * These macros must be defined at once because: + * + * - #RBIMPL_ASSUME could fallback to #RBIMPL_UNREACHABLE. + * - #RBIMPL_UNREACHABLE could fallback to #RBIMPL_ASSUME. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/warning_push.h" + +/** @cond INTERNAL_MACRO */ +#if RBIMPL_COMPILER_SINCE(MSVC, 13, 10, 0) +# define RBIMPL_HAVE___ASSUME + +#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) +# define RBIMPL_HAVE___ASSUME +#endif +/** @endcond */ + +/** Wraps (or simulates) `__builtin_unreachable`. */ +#if RBIMPL_HAS_BUILTIN(__builtin_unreachable) +# define RBIMPL_UNREACHABLE_RETURN(_) __builtin_unreachable() + +#elif defined(RBIMPL_HAVE___ASSUME) +# define RBIMPL_UNREACHABLE_RETURN(_) return (__assume(0), (_)) + +#else +# define RBIMPL_UNREACHABLE_RETURN(_) return (_) +#endif + +/** Wraps (or simulates) `__builtin_unreachable`. */ +#if RBIMPL_HAS_BUILTIN(__builtin_unreachable) +# define RBIMPL_UNREACHABLE __builtin_unreachable + +#elif defined(RBIMPL_HAVE___ASSUME) +# define RBIMPL_UNREACHABLE() __assume(0) +#endif + +/** Wraps (or simulates) `__assume`. */ +#if RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) +# /* icc warnings are false positives. Ignore them. */ +# /* "warning #2261: __assume expression with side effects discarded" */ +# define RBIMPL_ASSUME(expr) \ + RBIMPL_WARNING_PUSH() \ + RBIMPL_WARNING_IGNORED(2261) \ + __assume(expr) \ + RBIMPL_WARNING_POP() + +#elif defined(RBIMPL_HAVE___ASSUME) +# define RBIMPL_ASSUME __assume + +#elif RBIMPL_HAS_BUILTIN(__builtin_assume) +# define RBIMPL_ASSUME __builtin_assume + +#elif ! defined(RBIMPL_UNREACHABLE) +# define RBIMPL_ASSUME(_) RBIMPL_CAST((void)(_)) + +#else +# define RBIMPL_ASSUME(_) \ + (RB_LIKELY(!!(_)) ? RBIMPL_CAST((void)0) : RBIMPL_UNREACHABLE()) +#endif + +#if ! defined(RBIMPL_UNREACHABLE) +# define RBIMPL_UNREACHABLE() RBIMPL_ASSUME(0) +#endif + +#endif /* RBIMPL_ASSUME_H */ diff --git a/ruby/include/ruby/internal/attr/alloc_size.h b/ruby/include/ruby/internal/attr/alloc_size.h new file mode 100644 index 000000000..954a2010f --- /dev/null +++ b/ruby/include/ruby/internal/attr/alloc_size.h @@ -0,0 +1,32 @@ +#ifndef RBIMPL_ATTR_ALLOC_SIZE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_ALLOC_SIZE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_ALLOC_SIZE. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((alloc_size))` */ +#if RBIMPL_HAS_ATTRIBUTE(alloc_size) +# define RBIMPL_ATTR_ALLOC_SIZE(tuple) __attribute__((__alloc_size__ tuple)) +#else +# define RBIMPL_ATTR_ALLOC_SIZE(tuple) /* void */ +#endif + +#endif /* RBIMPL_ATTR_ALLOC_SIZE_H */ diff --git a/ruby/include/ruby/internal/attr/artificial.h b/ruby/include/ruby/internal/attr/artificial.h new file mode 100644 index 000000000..ef5f36abf --- /dev/null +++ b/ruby/include/ruby/internal/attr/artificial.h @@ -0,0 +1,46 @@ +#ifndef RBIMPL_ATTR_ARTIFICIAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_ARTIFICIAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_ARTIFICIAL. + * + * ### Q&A ### + * + * - Q: What is this attribute? I don't get what GCC manual is talking about. + * + * - A: In short it is an attribute to manipulate GDB backtraces. The + * attribute makes the best sense when it comes with + * __attribute__((always_inline)). When a function annotated with this + * attribute gets inlined, and when you somehow look at a backtrace which + * includes such inlined call site, then the backtrace shows the caller + * and not the callee. This is handy for instance when an identical + * function is inlined more than once in a single big function. On such + * case it gets vital to know where the inlining happened in the callee. + * See also https://stackoverflow.com/a/21936099 + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((artificial))` */ +#if RBIMPL_HAS_ATTRIBUTE(artificial) +# define RBIMPL_ATTR_ARTIFICIAL() __attribute__((__artificial__)) +#else +# define RBIMPL_ATTR_ARTIFICIAL() /* void */ +#endif + +#endif /* RBIMPL_ATTR_ARTIFICIAL_H */ diff --git a/ruby/include/ruby/internal/attr/cold.h b/ruby/include/ruby/internal/attr/cold.h new file mode 100644 index 000000000..c68b3ae78 --- /dev/null +++ b/ruby/include/ruby/internal/attr/cold.h @@ -0,0 +1,37 @@ +#ifndef RBIMPL_ATTR_COLD_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_COLD_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_COLD. + */ +#include "ruby/internal/compiler_is.h" +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((cold))` */ +#if RBIMPL_COMPILER_IS(SunPro) +# /* Recent SunPro has __has_attribute, and is broken. */ +# /* It reports it has attribute cold, reality isn't (warnings issued). */ +# define RBIMPL_ATTR_COLD() /* void */ +#elif RBIMPL_HAS_ATTRIBUTE(cold) +# define RBIMPL_ATTR_COLD() __attribute__((__cold__)) +#else +# define RBIMPL_ATTR_COLD() /* void */ +#endif + +#endif /* RBIMPL_ATTR_COLD_H */ diff --git a/ruby/include/ruby/internal/attr/const.h b/ruby/include/ruby/internal/attr/const.h new file mode 100644 index 000000000..e66aa17c7 --- /dev/null +++ b/ruby/include/ruby/internal/attr/const.h @@ -0,0 +1,46 @@ +#ifndef RBIMPL_ATTR_CONST_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_CONST_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_CONST. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/declspec_attribute.h" + +/** Wraps (or simulates) `__attribute__((const))` */ +#if RBIMPL_HAS_ATTRIBUTE(const) +# define RBIMPL_ATTR_CONST() __attribute__((__const__)) +#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) +# /* If a function can be a const, that is also a noalias. */ +# define RBIMPL_ATTR_CONST() __declspec(noalias) +#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_ATTR_CONST() _Pragma("no_side_effect") +#else +# define RBIMPL_ATTR_CONST() /* void */ +#endif + +/** Enables #RBIMPL_ATTR_CONST if and only if. ! #RUBY_DEBUG. */ +#if !defined(RUBY_DEBUG) || !RUBY_DEBUG +# define RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONST() +#else +# define RBIMPL_ATTR_CONST_UNLESS_DEBUG() /* void */ +#endif + +#endif /* RBIMPL_ATTR_CONST_H */ diff --git a/ruby/include/ruby/internal/attr/constexpr.h b/ruby/include/ruby/internal/attr/constexpr.h new file mode 100644 index 000000000..abc4f238b --- /dev/null +++ b/ruby/include/ruby/internal/attr/constexpr.h @@ -0,0 +1,84 @@ +#ifndef RBIMPL_ATTR_CONSTEXPR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_CONSTEXPR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief #RBIMPL_ATTR_CONSTEXPR. + */ +#include "ruby/internal/has/feature.h" +#include "ruby/internal/compiler_is.h" + +/** @cond INTERNAL_MACRO */ +#if ! defined(__cplusplus) +# /* Makes no sense. */ +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 + +#elif defined(__cpp_constexpr) +# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cpp_constexpr >= 200704L) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cpp_constexpr >= 201304L) + +#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 00) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 00) + +#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 13, 0) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) + +#elif RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) + +#elif RBIMPL_HAS_FEATURE(cxx_relaxed_constexpr) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 1 + +#elif RBIMPL_HAS_FEATURE(cxx_constexpr) +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 + +#else +# /* :FIXME: icpc must have constexpr but don't know how to detect. */ +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 +# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 +#endif +/** @endcond */ + +/** Wraps (or simulates) C++11 `constexpr`. */ +#if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 +# define RBIMPL_ATTR_CONSTEXPR(_) constexpr + +#elif RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 +# define RBIMPL_ATTR_CONSTEXPR(_) RBIMPL_ATTR_CONSTEXPR_ ## _ +# define RBIMPL_ATTR_CONSTEXPR_CXX11 constexpr +# define RBIMPL_ATTR_CONSTEXPR_CXX14 /* void */ + +#else +# define RBIMPL_ATTR_CONSTEXPR(_) /* void */ +#endif + +/** Enables #RBIMPL_ATTR_CONSTEXPR if and only if. ! #RUBY_DEBUG. */ +#if !RUBY_DEBUG +# define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) RBIMPL_ATTR_CONSTEXPR(_) +#else +# define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) /* void */ +#endif + +#endif /* RBIMPL_ATTR_CONSTEXPR_H */ diff --git a/ruby/include/ruby/internal/attr/deprecated.h b/ruby/include/ruby/internal/attr/deprecated.h new file mode 100644 index 000000000..e1bbdbd15 --- /dev/null +++ b/ruby/include/ruby/internal/attr/deprecated.h @@ -0,0 +1,75 @@ +#ifndef RBIMPL_ATTR_DEPRECATED_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_DEPRECATED_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_DEPRECATED. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/c_attribute.h" +#include "ruby/internal/has/cpp_attribute.h" +#include "ruby/internal/has/declspec_attribute.h" +#include "ruby/internal/has/extension.h" + +/** Wraps (or simulates) `[[deprecated]]` */ +#if defined(__COVERITY__) +/* Coverity Scan emulates gcc but seems not to support this attribute correctly */ +# define RBIMPL_ATTR_DEPRECATED(msg) + +#elif RBIMPL_HAS_EXTENSION(attribute_deprecated_with_message) +# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) + +#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(GCC, 10, 1, 0) && RBIMPL_COMPILER_BEFORE(GCC, 10, 3, 0) +# /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95302 */ +# define RBIMPL_ATTR_DEPRECATED(msg) /* disable until they fix this bug */ + +#elif RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) +# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) + +#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) +# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) + +#elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */ +# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__)) + +#elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +# define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg) + +#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated) +# define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated) + +#elif RBIMPL_HAS_CPP_ATTRIBUTE(deprecated) +# define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] + +#elif RBIMPL_HAS_C_ATTRIBUTE(deprecated) +# define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] + +#else +# define RBIMPL_ATTR_DEPRECATED(msg) /* void */ +#endif + +/** This is when a function is used internally (for backwards compatibility + * etc.), but extension libraries must consider it deprecated. */ +#if defined(RUBY_EXPORT) +# define RBIMPL_ATTR_DEPRECATED_EXT(msg) /* void */ +#else +# define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg) +#endif + +#endif /* RBIMPL_ATTR_DEPRECATED_H */ diff --git a/ruby/include/ruby/internal/attr/diagnose_if.h b/ruby/include/ruby/internal/attr/diagnose_if.h new file mode 100644 index 000000000..cadc6ce25 --- /dev/null +++ b/ruby/include/ruby/internal/attr/diagnose_if.h @@ -0,0 +1,42 @@ +#ifndef RBIMPL_ATTR_DIAGNOSE_IF_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_DIAGNOSE_IF_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_DIAGNOSE_IF. + */ +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/warning_push.h" + +/** Wraps (or simulates) `__attribute__((diagnose_if))` */ +#if RBIMPL_COMPILER_BEFORE(Clang, 5, 0, 0) +# /* https://bugs.llvm.org/show_bug.cgi?id=34319 */ +# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ + +#elif RBIMPL_HAS_ATTRIBUTE(diagnose_if) +# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) \ + RBIMPL_WARNING_PUSH() \ + RBIMPL_WARNING_IGNORED(-Wgcc-compat) \ + __attribute__((__diagnose_if__(_, __, ___))) \ + RBIMPL_WARNING_POP() + +#else +# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ +#endif + +#endif /* RBIMPL_ATTR_DIAGNOSE_IF_H */ diff --git a/ruby/include/ruby/internal/attr/enum_extensibility.h b/ruby/include/ruby/internal/attr/enum_extensibility.h new file mode 100644 index 000000000..eb0d5b6e9 --- /dev/null +++ b/ruby/include/ruby/internal/attr/enum_extensibility.h @@ -0,0 +1,32 @@ +#ifndef RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_ENUM_EXTENSIBILITY_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief #RBIMPL_ATTR_ENUM_EXTENSIBILITY. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((enum_extensibility))` */ +#if RBIMPL_HAS_ATTRIBUTE(enum_extensibility) +# define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) __attribute__((__enum_extensibility__(_))) +#else +# define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) /* void */ +#endif + +#endif /* RBIMPL_ATTR_ENUM_EXTENSIBILITY_H */ diff --git a/ruby/include/ruby/internal/attr/error.h b/ruby/include/ruby/internal/attr/error.h new file mode 100644 index 000000000..2ed388a77 --- /dev/null +++ b/ruby/include/ruby/internal/attr/error.h @@ -0,0 +1,32 @@ +#ifndef RBIMPL_ATTR_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_ERROR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_ERROR. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((error))` */ +#if RBIMPL_HAS_ATTRIBUTE(error) +# define RBIMPL_ATTR_ERROR(msg) __attribute__((__error__ msg)) +#else +# define RBIMPL_ATTR_ERROR(msg) /* void */ +#endif + +#endif /* RBIMPL_ATTR_ERROR_H */ diff --git a/ruby/include/ruby/internal/attr/flag_enum.h b/ruby/include/ruby/internal/attr/flag_enum.h new file mode 100644 index 000000000..3053d7507 --- /dev/null +++ b/ruby/include/ruby/internal/attr/flag_enum.h @@ -0,0 +1,33 @@ +#ifndef RBIMPL_ATTR_FLAG_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_FLAG_ENUM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_FLAG_ENUM. + * @see https://clang.llvm.org/docs/AttributeReference.html#flag_enum + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((flag_enum)` */ +#if RBIMPL_HAS_ATTRIBUTE(flag_enum) +# define RBIMPL_ATTR_FLAG_ENUM() __attribute__((__flag_enum__)) +#else +# define RBIMPL_ATTR_FLAG_ENUM() /* void */ +#endif + +#endif /* RBIMPLATTR_FLAG_ENUM_H */ diff --git a/ruby/include/ruby/internal/attr/forceinline.h b/ruby/include/ruby/internal/attr/forceinline.h new file mode 100644 index 000000000..b7daafede --- /dev/null +++ b/ruby/include/ruby/internal/attr/forceinline.h @@ -0,0 +1,40 @@ +#ifndef RBIMPL_ATTR_FORCEINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_FORCEINLINE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_FORCEINLINE. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" + +/** + * Wraps (or simulates) `__forceinline`. MSVC complains on declarations like + * `static inline __forceinline void foo()`. It seems MSVC's `inline` and + * `__forceinline` are mutually exclusive. We have to mimic that behaviour for + * non-MSVC compilers. + */ +#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +# define RBIMPL_ATTR_FORCEINLINE() __forceinline +#elif RBIMPL_HAS_ATTRIBUTE(always_inline) +# define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline +#else +# define RBIMPL_ATTR_FORCEINLINE() inline +#endif + +#endif /* RBIMPL_ATTR_FORCEINLINE_H */ diff --git a/ruby/include/ruby/internal/attr/format.h b/ruby/include/ruby/internal/attr/format.h new file mode 100644 index 000000000..b3488ee00 --- /dev/null +++ b/ruby/include/ruby/internal/attr/format.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_ATTR_FORMAT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_FORMAT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_FORMAT. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((format))` */ +#if RBIMPL_HAS_ATTRIBUTE(format) +# define RBIMPL_ATTR_FORMAT(x, y, z) __attribute__((__format__(x, y, z))) +#else +# define RBIMPL_ATTR_FORMAT(x, y, z) /* void */ +#endif + +#if defined(__MINGW_PRINTF_FORMAT) +# define RBIMPL_PRINTF_FORMAT __MINGW_PRINTF_FORMAT +#else +# define RBIMPL_PRINTF_FORMAT __printf__ +#endif + +#endif /* RBIMPL_ATTR_FORMAT_H */ diff --git a/ruby/include/ruby/internal/attr/maybe_unused.h b/ruby/include/ruby/internal/attr/maybe_unused.h new file mode 100644 index 000000000..3ee8be454 --- /dev/null +++ b/ruby/include/ruby/internal/attr/maybe_unused.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_ATTR_MAYBE_UNUSED_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_MAYBE_UNUSED_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_MAYBE_UNUSED. + */ +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/c_attribute.h" +#include "ruby/internal/has/cpp_attribute.h" + +/** Wraps (or simulates) `[[maybe_unused]]` */ +#if RBIMPL_HAS_CPP_ATTRIBUTE(maybe_unused) +# define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] +#elif RBIMPL_HAS_C_ATTRIBUTE(maybe_unused) +# define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] +#elif RBIMPL_HAS_ATTRIBUTE(unused) +# define RBIMPL_ATTR_MAYBE_UNUSED() __attribute__((__unused__)) +#else +# define RBIMPL_ATTR_MAYBE_UNUSED() /* void */ +#endif + +#endif /* RBIMPL_ATTR_MAYBE_UNUSED */ diff --git a/ruby/include/ruby/internal/attr/noalias.h b/ruby/include/ruby/internal/attr/noalias.h new file mode 100644 index 000000000..0790ef60e --- /dev/null +++ b/ruby/include/ruby/internal/attr/noalias.h @@ -0,0 +1,69 @@ +#ifndef RBIMPL_ATTR_NOALIAS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NOALIAS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NOALIAS. + * + * ### Q&A ### + * + * - Q: There are seemingly similar attributes named #RBIMPL_ATTR_CONST, + * #RBIMPL_ATTR_PURE, and #RBIMPL_ATTR_NOALIAS. What are the difference? + * + * - A: Allowed operations are different. + * + * - #RBIMPL_ATTR_CONST ... Functions attributed by this are not allowed to + * read/write _any_ pointers at all (there are exceptional situations + * when reading a pointer is possible but forget that; they are too + * exceptional to be useful). Just remember that everything pointer- + * related are NG. + * + * - #RBIMPL_ATTR_PURE ... Functions attributed by this can read any + * nonvolatile pointers, but no writes are allowed at all. The ability + * to read _any_ nonvolatile pointers makes it possible to mark ::VALUE- + * taking functions as being pure, as long as they are read-only. + * + * - #RBIMPL_ATTR_NOALIAS ... Can both read/write, but only through + * pointers passed to the function as parameters. This is a typical + * situation when you create a C++ non-static member function which only + * concerns `this`. No global variables are allowed to read/write. So + * this is not a super-set of being pure. If you want to read something, + * that has to be passed to the function as a pointer. ::VALUE -taking + * functions thus cannot be attributed as such. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/declspec_attribute.h" + +/** Wraps (or simulates) `__declspec((noalias))` */ +#if RBIMPL_COMPILER_BEFORE(Clang, 12, 0, 0) +# /* +# * `::llvm::Attribute::ArgMemOnly` was buggy before. Maybe because nobody +# * actually seriously used it. It seems they somehow mitigated the situation +# * in LLVM 12. Still not found the exact changeset which fiexed the +# * attribute, though. +# * +# * :FIXME: others (armclang, xlclang, ...) can also be affected? +# */ +# define RBIMPL_ATTR_NOALIAS() /* void */ +#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) +# define RBIMPL_ATTR_NOALIAS() __declspec(noalias) +#else +# define RBIMPL_ATTR_NOALIAS() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NOALIAS_H */ diff --git a/ruby/include/ruby/internal/attr/nodiscard.h b/ruby/include/ruby/internal/attr/nodiscard.h new file mode 100644 index 000000000..087192a7a --- /dev/null +++ b/ruby/include/ruby/internal/attr/nodiscard.h @@ -0,0 +1,45 @@ +#ifndef RBIMPL_ATTR_NODISCARD_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NODISCARD_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NODISCARD. + */ +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/c_attribute.h" +#include "ruby/internal/has/cpp_attribute.h" + +/** + * Wraps (or simulates) `[[nodiscard]]`. In C++ (at least since C++20) a + * nodiscard attribute can have a message why the result shall not be ignoed. + * However GCC attribute and SAL annotation cannot take them. + */ +#if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard) +# define RBIMPL_ATTR_NODISCARD() [[nodiscard]] +#elif RBIMPL_HAS_C_ATTRIBUTE(nodiscard) +# define RBIMPL_ATTR_NODISCARD() [[nodiscard]] +#elif RBIMPL_HAS_ATTRIBUTE(warn_unused_result) +# define RBIMPL_ATTR_NODISCARD() __attribute__((__warn_unused_result__)) +#elif defined(_Check_return_) +# /* Take SAL definition. */ +# define RBIMPL_ATTR_NODISCARD() _Check_return_ +#else +# define RBIMPL_ATTR_NODISCARD() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NODISCARD_H */ diff --git a/ruby/include/ruby/internal/attr/noexcept.h b/ruby/include/ruby/internal/attr/noexcept.h new file mode 100644 index 000000000..ea3001df2 --- /dev/null +++ b/ruby/include/ruby/internal/attr/noexcept.h @@ -0,0 +1,91 @@ +#ifndef RBIMPL_ATTR_NOEXCEPT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NOEXCEPT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NOEXCEPT. + * + * This isn't actually an attribute in C++ but who cares... + * + * Mainly due to aesthetic reasons, this one is rarely used in the project. + * But can be handy on occasions, especially when a function's noexcept-ness + * depends on its calling functions. + * + * ### Q&A ### + * + * - Q: Can a function that raises Ruby exceptions be attributed `noexcept`? + * + * - A: Yes. `noexcept` is about C++ exceptions, not Ruby's. They don't + * interface each other. You can safely attribute a function that raises + * Ruby exceptions as `noexcept`. + * + * - Q: How, then, can I assert that a function I wrote doesn't raise any Ruby + * exceptions? + * + * - A: `__attribute__((__leaf__))` is for that purpose. A function attributed + * as leaf can still throw C++ exceptions, but not Ruby's. Note however, + * that it's extremely difficult -- if not impossible -- to assert that a + * function doesn't raise any Ruby exceptions at all. Use of that + * attribute is not recommended; mere mortals can't properly use that by + * hand. + * + * - Q: Does it make sense to attribute an inline function `noexcept`? + * + * - A: I thought so before. But no, I don't think they are useful any longer. + * + * - When an inline function attributed `noexcept` actually doesn't throw + * any exceptions at all: these days I don't see any difference in + * generated assembly by adding/removing this attribute. C++ compilers + * get smarter and smarter. Today they can infer if it actually throws + * or not without any annotations by humans (correct me if I'm wrong). + * + * - When an inline function attributed `noexcepr` actually _does_ throw an + * exception: they have to call `std::terminate` then (C++ standard + * mandates so). This means exception handling routines are actually + * enforced, not omitted. This doesn't impact runtime performance (The + * Itanium C++ ABI has zero-cost exception handling), but does impact on + * generated binary size. This is bad. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/feature.h" + +/** Wraps (or simulates) C++11 `noexcept` */ +#if ! defined(__cplusplus) +# /* Doesn't make sense. */ +# define RBIMPL_ATTR_NOEXCEPT(_) /* void */ + +#elif RBIMPL_HAS_FEATURE(cxx_noexcept) +# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) + +#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ +# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) + +#elif defined(__INTEL_CXX11_MODE__) +# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) + +#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) +# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) + +#elif __cplusplus >= 201103L +# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) + +#else +# define RBIMPL_ATTR_NOEXCEPT(_) /* void */ +#endif + +#endif /* RBIMPL_ATTR_NOEXCEPT_H */ diff --git a/ruby/include/ruby/internal/attr/noinline.h b/ruby/include/ruby/internal/attr/noinline.h new file mode 100644 index 000000000..b7605a0c9 --- /dev/null +++ b/ruby/include/ruby/internal/attr/noinline.h @@ -0,0 +1,35 @@ +#ifndef RBIMPL_ATTR_NOINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NOINLINE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NOINLINE. + */ +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/declspec_attribute.h" + +/** Wraps (or simulates) `__declspec(noinline)` */ +#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noinline) +# define RBIMPL_ATTR_NOINLINE() __declspec(noinline) +#elif RBIMPL_HAS_ATTRIBUTE(noinline) +# define RBIMPL_ATTR_NOINLINE() __attribute__((__noinline__)) +#else +# define RBIMPL_ATTR_NOINLINE() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NOINLINE_H */ diff --git a/ruby/include/ruby/internal/attr/nonnull.h b/ruby/include/ruby/internal/attr/nonnull.h new file mode 100644 index 000000000..778d5be20 --- /dev/null +++ b/ruby/include/ruby/internal/attr/nonnull.h @@ -0,0 +1,34 @@ +#ifndef RBIMPL_ATTR_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NONNULL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NONNULL. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((nonnull))` */ +#if RBIMPL_HAS_ATTRIBUTE(nonnull) +# define RBIMPL_ATTR_NONNULL(list) __attribute__((__nonnull__ list)) +# define RBIMPL_NONNULL_ARG(arg) RBIMPL_ASSERT_NOTHING +#else +# define RBIMPL_ATTR_NONNULL(list) /* void */ +# define RBIMPL_NONNULL_ARG(arg) RUBY_ASSERT(arg) +#endif + +#endif /* RBIMPL_ATTR_NONNULL_H */ diff --git a/ruby/include/ruby/internal/attr/noreturn.h b/ruby/include/ruby/internal/attr/noreturn.h new file mode 100644 index 000000000..583921203 --- /dev/null +++ b/ruby/include/ruby/internal/attr/noreturn.h @@ -0,0 +1,48 @@ +#ifndef RBIMPL_ATTR_NORETURN_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NORETURN_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NORETURN. + */ +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/cpp_attribute.h" +#include "ruby/internal/has/declspec_attribute.h" + +/** Wraps (or simulates) `[[noreturn]]` */ +#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noreturn) +# define RBIMPL_ATTR_NORETURN() __declspec(noreturn) + +#elif RBIMPL_HAS_ATTRIBUTE(noreturn) +# define RBIMPL_ATTR_NORETURN() __attribute__((__noreturn__)) + +#elif RBIMPL_HAS_CPP_ATTRIBUTE(noreturn) +# define RBIMPL_ATTR_NORETURN() [[noreturn]] + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112) +# define RBIMPL_ATTR_NORETURN() _Noreturn + +#elif defined(_Noreturn) +# /* glibc has this macro. */ +# define RBIMPL_ATTR_NORETURN() _Noreturn + +#else +# define RBIMPL_ATTR_NORETURN() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NORETURN_H */ diff --git a/ruby/include/ruby/internal/attr/pure.h b/ruby/include/ruby/internal/attr/pure.h new file mode 100644 index 000000000..015711bda --- /dev/null +++ b/ruby/include/ruby/internal/attr/pure.h @@ -0,0 +1,43 @@ +#ifndef RBIMPL_ATTR_PURE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_PURE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_PURE. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/assert.h" + +/** Wraps (or simulates) `__attribute__((pure))` */ +#if RBIMPL_HAS_ATTRIBUTE(pure) +# define RBIMPL_ATTR_PURE() __attribute__((__pure__)) +#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_ATTR_PURE() _Pragma("does_not_write_global_data") +#else +# define RBIMPL_ATTR_PURE() /* void */ +#endif + +/** Enables #RBIMPL_ATTR_PURE if and only if. ! #RUBY_DEBUG. */ +#if !RUBY_DEBUG +# define RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_PURE() +#else +# define RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* void */ +#endif + +#endif /* RBIMPL_ATTR_PURE_H */ diff --git a/ruby/include/ruby/internal/attr/restrict.h b/ruby/include/ruby/internal/attr/restrict.h new file mode 100644 index 000000000..e39104138 --- /dev/null +++ b/ruby/include/ruby/internal/attr/restrict.h @@ -0,0 +1,44 @@ +#ifndef RBIMPL_ATTR_RESTRICT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_RESTRICT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_RESTRICT. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" + +/* :FIXME: config.h includes conflicting `#define restrict`. MSVC can be + * detected using `RBIMPL_COMPILER_SINCE()`, but Clang & family cannot use + * `__has_declspec_attribute()` which involves macro substitution. */ + +/** Wraps (or simulates) `__declspec(restrict)` */ +#if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +# define RBIMPL_ATTR_RESTRICT() __declspec(re ## strict) + +#elif RBIMPL_HAS_ATTRIBUTE(malloc) +# define RBIMPL_ATTR_RESTRICT() __attribute__((__malloc__)) + +#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_ATTR_RESTRICT() _Pragma("returns_new_memory") + +#else +# define RBIMPL_ATTR_RESTRICT() /* void */ +#endif + +#endif /* RBIMPL_ATTR_RESTRICT_H */ diff --git a/ruby/include/ruby/internal/attr/returns_nonnull.h b/ruby/include/ruby/internal/attr/returns_nonnull.h new file mode 100644 index 000000000..5d6f1d145 --- /dev/null +++ b/ruby/include/ruby/internal/attr/returns_nonnull.h @@ -0,0 +1,37 @@ +#ifndef RBIMPL_ATTR_RETURNS_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_RETURNS_NONNULL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_RETURNS_NONNULL. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((returns_nonnull))` */ +#if defined(_Ret_nonnull_) +# /* Take SAL definition. */ +# define RBIMPL_ATTR_RETURNS_NONNULL() _Ret_nonnull_ + +#elif RBIMPL_HAS_ATTRIBUTE(returns_nonnull) +# define RBIMPL_ATTR_RETURNS_NONNULL() __attribute__((__returns_nonnull__)) + +#else +# define RBIMPL_ATTR_RETURNS_NONNULL() /* void */ +#endif + +#endif /* RBIMPL_ATTR_RETURNS_NONNULL_H */ diff --git a/ruby/include/ruby/internal/attr/warning.h b/ruby/include/ruby/internal/attr/warning.h new file mode 100644 index 000000000..e5ced269b --- /dev/null +++ b/ruby/include/ruby/internal/attr/warning.h @@ -0,0 +1,32 @@ +#ifndef RBIMPL_ATTR_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_WARNING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_WARNING. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((warning))` */ +#if RBIMPL_HAS_ATTRIBUTE(warning) +# define RBIMPL_ATTR_WARNING(msg) __attribute__((__warning__ msg)) +#else +# define RBIMPL_ATTR_WARNING(msg) /* void */ +#endif + +#endif /* RBIMPL_ATTR_WARNING_H */ diff --git a/ruby/include/ruby/internal/attr/weakref.h b/ruby/include/ruby/internal/attr/weakref.h new file mode 100644 index 000000000..f118bb62b --- /dev/null +++ b/ruby/include/ruby/internal/attr/weakref.h @@ -0,0 +1,32 @@ +#ifndef RBIMPL_ATTR_WEAKREF_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_WEAKREF_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_WEAKREF. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((weakref))` */ +#if RBIMPL_HAS_ATTRIBUTE(weakref) +# define RBIMPL_ATTR_WEAKREF(sym) __attribute__((__weakref__(# sym))) +#else +# define RBIMPL_ATTR_WEAKREF(sym) /* void */ +#endif + +#endif /* RBIMPL_ATTR_WEAKREF_H */ diff --git a/ruby/include/ruby/internal/cast.h b/ruby/include/ruby/internal/cast.h new file mode 100644 index 000000000..a31fddbe4 --- /dev/null +++ b/ruby/include/ruby/internal/cast.h @@ -0,0 +1,50 @@ +#ifndef RBIMPL_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_CAST_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_CAST. + * + * This casting macro makes sense only inside of other macros that are part of + * public headers. They could be used from C++, and C-style casts could issue + * warnings. Ruby internals are pure C so they should not bother. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/warning.h" +#include "ruby/internal/warning_push.h" + +#if ! defined(__cplusplus) +# define RBIMPL_CAST(expr) (expr) + +#elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) +# /* g++ has -Wold-style-cast since 1997 or so, but its _Pragma is broken. */ +# /* See https://gcc.godbolt.org/z/XWhU6J */ +# define RBIMPL_CAST(expr) (expr) +# pragma GCC diagnostic ignored "-Wold-style-cast" + +#elif RBIMPL_HAS_WARNING("-Wold-style-cast") +# define RBIMPL_CAST(expr) \ + RBIMPL_WARNING_PUSH() \ + RBIMPL_WARNING_IGNORED(-Wold-style-cast) \ + (expr) \ + RBIMPL_WARNING_POP() + +#else +# define RBIMPL_CAST(expr) (expr) +#endif + +#endif /* RBIMPL_CAST_H */ diff --git a/ruby/include/ruby/internal/compiler_is.h b/ruby/include/ruby/internal/compiler_is.h new file mode 100644 index 000000000..7070b033a --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is.h @@ -0,0 +1,45 @@ +#ifndef RBIMPL_COMPILER_IS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_COMPILER_IS. + */ + +/** + * @brief Checks if the compiler is of given brand. + * @param cc Compiler brand, like `MSVC`. + * @retval true It is. + * @retval false It isn't. + */ +#define RBIMPL_COMPILER_IS(cc) RBIMPL_COMPILER_IS_ ## cc + +#include "ruby/internal/compiler_is/apple.h" +#include "ruby/internal/compiler_is/clang.h" +#include "ruby/internal/compiler_is/gcc.h" +#include "ruby/internal/compiler_is/intel.h" +#include "ruby/internal/compiler_is/msvc.h" +#include "ruby/internal/compiler_is/sunpro.h" +/* :TODO: Other possible compilers to support: + * + * - IBM XL: recent XL are clang-backended so some tweaks like we do for + * Apple's might be needed. + * + * - ARM's armclang: ditto, it can be clang-backended. */ + +#endif /* RBIMPL_COMPILER_IS_H */ diff --git a/ruby/include/ruby/internal/compiler_is/apple.h b/ruby/include/ruby/internal/compiler_is/apple.h new file mode 100644 index 000000000..a81f1f2c8 --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/apple.h @@ -0,0 +1,40 @@ +#ifndef RBIMPL_COMPILER_IS_APPLE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_APPLE_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_Apple. + * + * Apple ships clang. Problem is, its `__clang_major__` etc. are not the + * upstream LLVM version, but XCode's. We have to think Apple's is distinct + * from LLVM's, when it comes to compiler detection business in this header + * file. + */ +#if ! defined(__clang__) +# define RBIMPL_COMPILER_IS_Apple 0 + +#elif ! defined(__apple_build_version__) +# define RBIMPL_COMPILER_IS_Apple 0 + +#else +# define RBIMPL_COMPILER_IS_Apple 1 +# define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ +# define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ +# define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ +#endif + +#endif /* RBIMPL_COMPILER_IS_APPLE_H */ diff --git a/ruby/include/ruby/internal/compiler_is/clang.h b/ruby/include/ruby/internal/compiler_is/clang.h new file mode 100644 index 000000000..169ff789f --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/clang.h @@ -0,0 +1,37 @@ +#ifndef RBIMPL_COMPILER_IS_CLANG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_CLANG_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_Clang. + */ +#include "ruby/internal/compiler_is/apple.h" + +#if ! defined(__clang__) +# define RBIMPL_COMPILER_IS_Clang 0 + +#elif RBIMPL_COMPILER_IS(Apple) +# define RBIMPL_COMPILER_IS_Clang 0 + +#else +# define RBIMPL_COMPILER_IS_Clang 1 +# define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ +# define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ +# define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ +#endif + +#endif /* RBIMPL_COMPILER_IS_CLANG_H */ diff --git a/ruby/include/ruby/internal/compiler_is/gcc.h b/ruby/include/ruby/internal/compiler_is/gcc.h new file mode 100644 index 000000000..accc80e9a --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/gcc.h @@ -0,0 +1,45 @@ +#ifndef RBIMPL_COMPILER_IS_GCC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_GCC_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_GCC. + */ +#include "ruby/internal/compiler_is/apple.h" +#include "ruby/internal/compiler_is/clang.h" +#include "ruby/internal/compiler_is/intel.h" + +#if ! defined(__GNUC__) +# define RBIMPL_COMPILER_IS_GCC 0 + +#elif RBIMPL_COMPILER_IS(Apple) +# define RBIMPL_COMPILER_IS_GCC 0 + +#elif RBIMPL_COMPILER_IS(Clang) +# define RBIMPL_COMPILER_IS_GCC 0 + +#elif RBIMPL_COMPILER_IS(Intel) +# define RBIMPL_COMPILER_IS_GCC 0 + +#else +# define RBIMPL_COMPILER_IS_GCC 1 +# define RBIMPL_COMPILER_VERSION_MAJOR __GNUC__ +# define RBIMPL_COMPILER_VERSION_MINOR __GNUC_MINOR__ +# define RBIMPL_COMPILER_VERSION_PATCH __GNUC_PATCHLEVEL__ +#endif + +#endif /* RBIMPL_COMPILER_IS_GCC_H */ diff --git a/ruby/include/ruby/internal/compiler_is/intel.h b/ruby/include/ruby/internal/compiler_is/intel.h new file mode 100644 index 000000000..377946ace --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/intel.h @@ -0,0 +1,40 @@ +#ifndef RBIMPL_COMPILER_IS_INTEL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_INTEL_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_Intel. + */ +#if ! defined(__INTEL_COMPILER) +# define RBIMPL_COMPILER_IS_Intel 0 + +#elif ! defined(__INTEL_COMPILER_UPDATE) +# define RBIMPL_COMPILER_IS_Intel 1 +# /* __INTEL_COMPILER = XXYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) +# define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) +# define RBIMPL_COMPILER_VERSION_PATCH (__INTEL_COMPILER % 10) + +#else +# define RBIMPL_COMPILER_IS_Intel 1 +# /* __INTEL_COMPILER = XXYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) +# define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) +# define RBIMPL_COMPILER_VERSION_PATCH __INTEL_COMPILER_UPDATE +#endif + +#endif /* RBIMPL_COMPILER_IS_INTEL_H */ diff --git a/ruby/include/ruby/internal/compiler_is/msvc.h b/ruby/include/ruby/internal/compiler_is/msvc.h new file mode 100644 index 000000000..8a864ea55 --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/msvc.h @@ -0,0 +1,56 @@ +#ifndef RBIMPL_COMPILER_IS_MSVC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_MSVC_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_MSVC. + */ +#include "ruby/internal/compiler_is/clang.h" +#include "ruby/internal/compiler_is/intel.h" + +#if ! defined(_MSC_VER) +# define RBIMPL_COMPILER_IS_MSVC 0 + +#elif RBIMPL_COMPILER_IS(Clang) +# define RBIMPL_COMPILER_IS_MSVC 0 + +#elif RBIMPL_COMPILER_IS(Intel) +# define RBIMPL_COMPILER_IS_MSVC 0 + +#elif _MSC_VER >= 1400 +# define RBIMPL_COMPILER_IS_MSVC 1 +# /* _MSC_FULL_VER = XXYYZZZZZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 10000000) +# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000) +# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000) + +#elif defined(_MSC_FULL_VER) +# define RBIMPL_COMPILER_IS_MSVC 1 +# /* _MSC_FULL_VER = XXYYZZZZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000) +# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000) +# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000) + +#else +# define RBIMPL_COMPILER_IS_MSVC 1 +# /* _MSC_VER = XXYY */ +# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100) +# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100) +# define RBIMPL_COMPILER_VERSION_PATCH 0 +#endif + +#endif /* RBIMPL_COMPILER_IS_MSVC_H */ diff --git a/ruby/include/ruby/internal/compiler_is/sunpro.h b/ruby/include/ruby/internal/compiler_is/sunpro.h new file mode 100644 index 000000000..c11c8452e --- /dev/null +++ b/ruby/include/ruby/internal/compiler_is/sunpro.h @@ -0,0 +1,54 @@ +#ifndef RBIMPL_COMPILER_IS_SUNPRO_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_IS_SUNPRO_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines RBIMPL_COMPILER_IS_SunPro. + */ +#if ! (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) +# define RBIMPL_COMPILER_IS_SunPro 0 + +#elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x5100 +# define RBIMPL_COMPILER_IS_SunPro 1 +# /* __SUNPRO_C = 0xXYYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 12) +# define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_C >> 8 & 0xF) * 10 + (__SUNPRO_C >> 4 & 0xF)) +# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) + +#elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5100 +# define RBIMPL_COMPILER_IS_SunPro 1 +# /* __SUNPRO_CC = 0xXYYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 12) +# define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_CC >> 8 & 0xF) * 10 + (__SUNPRO_CC >> 4 & 0xF)) +# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) + +#elif defined(__SUNPRO_C) +# define RBIMPL_COMPILER_IS_SunPro 1 +# /* __SUNPRO_C = 0xXYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 8) +# define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_C >> 4 & 0xF) +# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) + +#else +# define RBIMPL_COMPILER_IS_SunPro 1 +# /* __SUNPRO_CC = 0xXYZ */ +# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 8) +# define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_CC >> 4 & 0xF) +# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) +#endif + +#endif /* RBIMPL_COMPILER_IS_SUNPRO_H */ diff --git a/ruby/include/ruby/internal/compiler_since.h b/ruby/include/ruby/internal/compiler_since.h new file mode 100644 index 000000000..192903288 --- /dev/null +++ b/ruby/include/ruby/internal/compiler_since.h @@ -0,0 +1,61 @@ +#ifndef RBIMPL_COMPILER_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_COMPILER_SINCE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_COMPILER_SINCE. + */ +#include "ruby/internal/compiler_is.h" + +/** + * @brief Checks if the compiler is of given brand and is newer than or equal + * to the passed version. + * @param cc Compiler brand, like `MSVC`. + * @param x Major version. + * @param y Minor version. + * @param z Patchlevel. + * @retval true cc >= x.y.z. + * @retval false otherwise. + */ +#define RBIMPL_COMPILER_SINCE(cc, x, y, z) \ + (RBIMPL_COMPILER_IS(cc) && \ + ((RBIMPL_COMPILER_VERSION_MAJOR > (x)) || \ + ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ + ((RBIMPL_COMPILER_VERSION_MINOR > (y)) || \ + ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ + (RBIMPL_COMPILER_VERSION_PATCH >= (z))))))) + +/** + * @brief Checks if the compiler is of given brand and is older than the + * passed version. + * @param cc Compiler brand, like `MSVC`. + * @param x Major version. + * @param y Minor version. + * @param z Patchlevel. + * @retval true cc < x.y.z. + * @retval false otherwise. + */ +#define RBIMPL_COMPILER_BEFORE(cc, x, y, z) \ + (RBIMPL_COMPILER_IS(cc) && \ + ((RBIMPL_COMPILER_VERSION_MAJOR < (x)) || \ + ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ + ((RBIMPL_COMPILER_VERSION_MINOR < (y)) || \ + ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ + (RBIMPL_COMPILER_VERSION_PATCH < (z))))))) + +#endif /* RBIMPL_COMPILER_SINCE_H */ diff --git a/ruby/include/ruby/internal/config.h b/ruby/include/ruby/internal/config.h new file mode 100644 index 000000000..51f863fc2 --- /dev/null +++ b/ruby/include/ruby/internal/config.h @@ -0,0 +1,153 @@ +#ifndef RBIMPL_CONFIG_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_CONFIG_H +/** + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Thin wrapper to ruby/config.h + */ +#include "ruby/config.h" + +#ifdef RUBY_EXTCONF_H +# include RUBY_EXTCONF_H +#endif + +#include "ruby/internal/compiler_since.h" + +#undef HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 + +#undef HAVE_STDARG_PROTOTYPES +#define HAVE_STDARG_PROTOTYPES 1 + +#undef TOKEN_PASTE +#define TOKEN_PASTE(x,y) x##y + +#if defined(__cplusplus) +#/* __builtin_choose_expr and __builtin_types_compatible aren't available +# * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ +# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P +# undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P + +/* HAVE_VA_ARGS_MACRO is for C. C++ situations might be different. */ +# undef HAVE_VA_ARGS_MACRO +# if __cplusplus >= 201103L +# define HAVE_VA_ARGS_MACRO +# elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ +# define HAVE_VA_ARGS_MACRO +# elif defined(__INTEL_CXX11_MODE__) +# define HAVE_VA_ARGS_MACRO +# elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +# define HAVE_VA_ARGS_MACRO +# else +# /* NG, not known. */ +# endif +#endif + +#if RBIMPL_COMPILER_BEFORE(GCC, 4, 9, 0) +# /* See https://bugs.ruby-lang.org/issues/14221 */ +# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P +#endif + +#if RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) +# /* GCC 4.9.2 reportedly has this feature and is broken. The function is not +# * officially documented below. Seems we should not use it. +# * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html */ +# undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN +#endif + +#if defined(__SUNPRO_CC) +# /* Oracle Developer Studio 12.5: GCC compatibility guide says it supports +# * statement expressions. But to our knowledge they support the extension +# * only for C and not for C++. Prove me wrong. Am happy to support them if +# * there is a way. */ +# undef HAVE_STMT_AND_DECL_IN_EXPR +#endif + +#ifndef STRINGIZE0 +# define STRINGIZE(expr) STRINGIZE0(expr) +# define STRINGIZE0(expr) #expr +#endif + +#ifdef AC_APPLE_UNIVERSAL_BUILD +# undef WORDS_BIGENDIAN +# ifdef __BIG_ENDIAN__ +# define WORDS_BIGENDIAN +# endif +#endif + +#ifndef DLEXT_MAXLEN +# define DLEXT_MAXLEN 4 +#endif + +#ifndef RUBY_PLATFORM +# define RUBY_PLATFORM "unknown-unknown" +#endif + +#ifdef UNALIGNED_WORD_ACCESS +# /* Take that. */ +#elif defined(__i386) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__i386__) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(_M_IX86) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__x86_64) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__x86_64__) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(_M_AMD64) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__powerpc64__) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__aarch64__) +# define UNALIGNED_WORD_ACCESS 1 +#elif defined(__mc68020__) +# define UNALIGNED_WORD_ACCESS 1 +#else +# define UNALIGNED_WORD_ACCESS 0 +#endif + +/* Detection of __VA_OPT__ */ +#if ! defined(HAVE_VA_ARGS_MACRO) +# undef HAVE___VA_OPT__ + +#elif defined(__cplusplus) +# if __cplusplus > 201703L +# define HAVE___VA_OPT__ +# else +# undef HAVE___VA_OPT__ +# endif +#else +# /* Idea taken from: https://stackoverflow.com/a/48045656 */ +# define RBIMPL_TEST3(q, w, e, ...) e +# define RBIMPL_TEST2(...) RBIMPL_TEST3(__VA_OPT__(,),1,0,0) +# define RBIMPL_TEST1() RBIMPL_TEST2("ruby") +# if RBIMPL_TEST1() +# define HAVE___VA_OPT__ +# else +# undef HAVE___VA_OPT__ +# endif +# undef RBIMPL_TEST1 +# undef RBIMPL_TEST2 +# undef RBIMPL_TEST3 +#endif /* HAVE_VA_ARGS_MACRO */ + +#ifndef USE_RVARGC +# define USE_RVARGC 0 +#endif + +#endif /* RBIMPL_CONFIG_H */ diff --git a/ruby/include/ruby/internal/constant_p.h b/ruby/include/ruby/internal/constant_p.h new file mode 100644 index 000000000..92d69cb97 --- /dev/null +++ b/ruby/include/ruby/internal/constant_p.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_CONSTANT_P_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_CONSTANT_P_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_CONSTANT_P. + * + * Note that __builtin_constant_p can be applicable inside of inline functions, + * according to GCC manual. Clang lacks that feature, though. + * + * @see https://bugs.llvm.org/show_bug.cgi?id=4898 + * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html + */ +#include "ruby/internal/has/builtin.h" + +/** Wraps (or simulates) `__builtin_constant_p` */ +#if RBIMPL_HAS_BUILTIN(__builtin_constant_p) +# define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr) +#else +# define RBIMPL_CONSTANT_P(expr) 0 +#endif + +#endif /* RBIMPL_CONSTANT_P_H */ diff --git a/ruby/include/ruby/internal/core.h b/ruby/include/ruby/internal/core.h new file mode 100644 index 000000000..3f4561c6a --- /dev/null +++ b/ruby/include/ruby/internal/core.h @@ -0,0 +1,35 @@ +#ifndef RBIMPL_CORE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_CORE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Core data structures, definitions and manipulations. + */ +#include "ruby/internal/core/rarray.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/core/rbignum.h" +#include "ruby/internal/core/rclass.h" +#include "ruby/internal/core/rdata.h" +#include "ruby/internal/core/rfile.h" +#include "ruby/internal/core/rhash.h" +#include "ruby/internal/core/robject.h" +#include "ruby/internal/core/rregexp.h" +#include "ruby/internal/core/rstring.h" +#include "ruby/internal/core/rstruct.h" +#include "ruby/internal/core/rtypeddata.h" +#endif /* RBIMPL_CORE_H */ diff --git a/ruby/include/ruby/internal/core/rarray.h b/ruby/include/ruby/internal/core/rarray.h new file mode 100644 index 000000000..9f1d0509e --- /dev/null +++ b/ruby/include/ruby/internal/core/rarray.h @@ -0,0 +1,590 @@ +#ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RARRAY_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RArray. + */ +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/maybe_unused.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/rgengc.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/assert.h" + +/** + * @private + * @warning Do not touch this macro. + * @warning It is an implementation detail. + * @warning The value of this macro must match for ruby itself and all + * extension libraries, otherwise serious memory corruption shall + * occur. + */ +#ifndef USE_TRANSIENT_HEAP +# define USE_TRANSIENT_HEAP 1 +#endif + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RArray. + * @return The passed object casted to ::RArray. + */ +#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj)) +/** @cond INTERNAL_MACRO */ +#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG +#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK +#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX +#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT +#if USE_TRANSIENT_HEAP +# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG +#else +# define RARRAY_TRANSIENT_FLAG 0 +#endif +/** @endcond */ +#define RARRAY_LEN rb_array_len /**< @alias{rb_array_len} */ +#define RARRAY_CONST_PTR rb_array_const_ptr /**< @alias{rb_array_const_ptr} */ +#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient /**< @alias{rb_array_const_ptr_transient} */ + +/** @cond INTERNAL_MACRO */ +#if defined(__fcc__) || defined(__fcc_version) || \ + defined(__FCC__) || defined(__FCC_VERSION) +/* workaround for old version of Fujitsu C Compiler (fcc) */ +# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) +#else +# define FIX_CONST_VALUE_PTR(x) (x) +#endif + +#define RARRAY_EMBED_LEN RARRAY_EMBED_LEN +#define RARRAY_LENINT RARRAY_LENINT +#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P +#define RARRAY_ASET RARRAY_ASET +#define RARRAY_PTR RARRAY_PTR +/** @endcond */ + +/** + * @private + * + * Bits that you can set to ::RBasic::flags. + * + * @warning These enums are not the only bits we use for arrays. + * + * @internal + * + * Unlike strings, flag usages for arrays are scattered across the entire + * source codes. @shyouhei doesn't know the complete list. But what is listed + * here is at least incomplete. + */ +enum ruby_rarray_flags { + /** + * This flag has something to do with memory footprint. If the array is + * "small" enough, ruby tries to be creative to abuse padding bits of + * struct ::RArray for storing its contents. This flag denotes that + * situation. + * + * @warning This bit has to be considered read-only. Setting/clearing + * this bit without corresponding fix up must cause immediate + * SEGV. Also, internal structures of an array change + * dynamically and transparently throughout of its lifetime. + * Don't assume it being persistent. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store array elements. It was a bad idea to expose this to them. + */ + RARRAY_EMBED_FLAG = RUBY_FL_USER1, + + /* RUBY_FL_USER2 is for ELTS_SHARED */ + + /** + * When an array employs embedded strategy (see ::RARRAY_EMBED_FLAG), these + * bits are used to store the number of elements actually filled into + * ::RArray::ary. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store array elements. It was a bad idea to expose this to them. + */ + RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3 +#if USE_TRANSIENT_HEAP + , + + /** + * This flag has something to do with an array's "transiency". A transient + * array is an array of young generation (of generational GC), who stores + * its elements inside of dedicated memory pages called a transient heap. + * Not every young generation share that storage scheme, but elder + * generations must no join. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store array elements. It was a bad idea to expose this to them. + */ + RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13 +#endif +}; + +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_rarray_consts { + /** Where ::RARRAY_EMBED_LEN_MASK resides. */ + RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3, + + /** Max possible number elements that can be embedded. */ + RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) +}; + +/** Ruby's array. */ +struct RArray { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** Array's specific fields. */ + union { + + /** + * Arrays that use separated memory region for elements use this + * pattern. + */ + struct { + + /** Number of elements of the array. */ + long len; + + /** Auxiliary info. */ + union { + + /** + * Capacity of `*ptr`. A continuous memory region of at least + * `capa` elements is expected to exist at `*ptr`. This can be + * bigger than `len`. + */ + long capa; + + /** + * Parent of the array. Nowadays arrays can share their + * backend memory regions each other, constructing gigantic + * nest of objects. This situation is called "shared", and + * this is the field to control such properties. + */ +#if defined(__clang__) /* <- clang++ is sane */ || \ + !defined(__cplusplus) /* <- C99 is sane */ || \ + (__cplusplus > 199711L) /* <- C++11 is sane */ + const +#endif + VALUE shared_root; + } aux; + + /** + * Pointer to the C array that holds the elements of the array. In + * the old days each array had dedicated memory regions. That is + * no longer true today, but there still are arrays of such + * properties. This field could be used to point such things. + */ + const VALUE *ptr; + } heap; + + /** + * Embedded elements. When an array is short enough, it uses this area + * to store its elements. In this case the length is encoded into the + * flags. + */ + const VALUE ary[RARRAY_EMBED_LEN_MAX]; + } as; +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * @private + * + * Declares a section of code where raw pointers are used. This is an + * implementation detail of #RARRAY_PTR_USE. People don't use it directly. + * + * @param[in] ary An object of ::RArray. + * @return `ary`'s backend C array. + */ +VALUE *rb_ary_ptr_use_start(VALUE ary); + +/** + * @private + * + * Declares an end of a section formerly started by rb_ary_ptr_use_start(). + * This is an implementation detail of #RARRAY_PTR_USE. People don't use it + * directly. + * + * @param[in] a An object of ::RArray. + */ +void rb_ary_ptr_use_end(VALUE a); + +#if USE_TRANSIENT_HEAP +/** + * Destructively converts an array of transient backend into ordinal one. + * + * @param[out] a An object of ::RArray. + * @pre `a` must be a transient array. + * @post `a` gets out of transient heap, destructively. + */ +void rb_ary_detransient(VALUE a); +#endif +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the length of the array. + * + * @param[in] ary Array in question. + * @return Its number of elements. + * @pre `ary` must be an instance of ::RArray, and must has its + * ::RARRAY_EMBED_FLAG flag set. + * + * @internal + * + * This was a macro before. It was inevitable to be public, since macros are + * global constructs. But should it be forever? Now that it is a function, + * @shyouhei thinks it could just be eliminated, hidden into implementation + * details. + */ +static inline long +RARRAY_EMBED_LEN(VALUE ary) +{ + RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG)); + + VALUE f = RBASIC(ary)->flags; + f &= RARRAY_EMBED_LEN_MASK; + f >>= RARRAY_EMBED_LEN_SHIFT; + return RBIMPL_CAST((long)f); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * Queries the length of the array. + * + * @param[in] a Array in question. + * @return Its number of elements. + * @pre `a` must be an instance of ::RArray. + */ +static inline long +rb_array_len(VALUE a) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + + if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { + return RARRAY_EMBED_LEN(a); + } + else { + return RARRAY(a)->as.heap.len; + } +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to rb_array_len(), except it differs for the return type. + * + * @param[in] ary Array in question. + * @exception rb_eRangeError Too long. + * @return Its number of elements. + * @pre `ary` must be an instance of ::RArray. + * + * @internal + * + * This API seems redundant but has actual usages. + */ +static inline int +RARRAY_LENINT(VALUE ary) +{ + return rb_long2int(RARRAY_LEN(ary)); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the array is a transient array. + * + * @param[in] ary Array in question. + * @retval true Yes it is. + * @retval false No it isn't. + * @pre `ary` must be an instance of ::RArray. + * + * @internal + * + * @shyouhei doesn't understand the benefit of this function called from + * extension libraries. + */ +static inline bool +RARRAY_TRANSIENT_P(VALUE ary) +{ + RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG); +#else + return false; +#endif +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * @private + * + * This is an implementation detail of RARRAY_PTR(). People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @return Its backend storage. + */ +static inline const VALUE * +rb_array_const_ptr_transient(VALUE a) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + + if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { + return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary); + } + else { + return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr); + } +} + +#if ! USE_TRANSIENT_HEAP +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +#endif +/** + * @private + * + * This is an implementation detail of RARRAY_PTR(). People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @return Its backend storage. + * @post `a` is not a transient array. + */ +static inline const VALUE * +rb_array_const_ptr(VALUE a) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + if (RARRAY_TRANSIENT_P(a)) { + rb_ary_detransient(a); + } +#endif + return rb_array_const_ptr_transient(a); +} + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @param[in] allow_transient Whether `a` can be transient or not. + * @return Its backend storage. + * @post `a` is not a transient array unless `allow_transient`. + */ +static inline VALUE * +rb_array_ptr_use_start(VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + int allow_transient) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + if (!allow_transient) { + if (RARRAY_TRANSIENT_P(a)) { + rb_ary_detransient(a); + } + } +#endif + + return rb_ary_ptr_use_start(a); +} + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @param[in] allow_transient Whether `a` can be transient or not. + */ +static inline void +rb_array_ptr_use_end(VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + int allow_transient) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + rb_ary_ptr_use_end(a); +} + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \ + RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \ + const VALUE rbimpl_ary = (ary); \ + VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \ + expr; \ + rb_array_ptr_use_end(rbimpl_ary, (flag)); \ +} while (0) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0) + +/** + * Declares a section of code where raw pointers are used. In case you need to + * touch the raw C array instead of polite CAPIs, then that operation shall be + * wrapped using this macro. + * + * ```CXX + * const auto ary = rb_eval_string("[...]"); + * const auto len = RARRAY_LENINT(ary); + * const auto symwrite = rb_intern("write"); + * + * RARRAY_PTR_USE(ary, ptr, { + * rb_funcallv(rb_stdout, symwrite, len, ptr); + * }); + * ``` + * + * @param ary An object of ::RArray. + * @param ptr_name A variable name which points the C array in `expr`. + * @param expr The expression that touches `ptr_name`. + * + * @internal + * + * For historical reasons use of this macro is not enforced. There are + * extension libraries in the wild which call RARRAY_PTR() without it. We want + * them use it... Maybe some transition path can be implemented later. + */ +#define RARRAY_PTR_USE(ary, ptr_name, expr) \ + RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE_TRANSIENT. People do + * not use it directly. + */ +#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE_TRANSIENT. People do + * not use it directly. + */ +#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1) + +/** + * Identical to #RARRAY_PTR_USE, except the pointer can be a transient one. + * + * @param ary An object of ::RArray. + * @param ptr_name A variable name which points the C array in `expr`. + * @param expr The expression that touches `ptr_name`. + */ +#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \ + RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr) + +/** + * Wild use of a C pointer. This function accesses the backend storage + * directly. This is slower than #RARRAY_PTR_USE_TRANSIENT. It exercises + * extra manoeuvres to protect our generational GC. Use of this function is + * considered archaic. Use a modern way instead. + * + * @param[in] ary An object of ::RArray. + * @return The backend C array. + * + * @internal + * + * That said... there are extension libraries in the wild who uses it. We + * cannot but continue supporting. + */ +static inline VALUE * +RARRAY_PTR(VALUE ary) +{ + RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); + + VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary); + return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp)); +} + +/** + * Assigns an object in an array. + * + * @param[out] ary Destination array object. + * @param[in] i Index of `ary`. + * @param[in] v Arbitrary ruby object. + * @pre `ary` must be an instance of ::RArray. + * @pre `ary`'s length must be longer than or equal to `i`. + * @pre `i` must be greater than or equal to zero. + * @post `ary`'s `i`th element is set to `v`. + */ +static inline void +RARRAY_ASET(VALUE ary, long i, VALUE v) +{ + RARRAY_PTR_USE_TRANSIENT(ary, ptr, + RB_OBJ_WRITE(ary, &ptr[i], v)); +} + +/** + * @deprecated + * + * :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms + * for more sanity checks). However there were situations where the address of + * this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this + * is not a macro. Such usages are abuse, and we eliminated them internally. + * However we are afraid of similar things to remain in the wild. This macro + * remains as it is due to that. If we could warn such usages we can set a + * transition path, but currently no way is found to do so. + */ +#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i] + +#endif /* RBIMPL_RARRAY_H */ diff --git a/ruby/include/ruby/internal/core/rbasic.h b/ruby/include/ruby/internal/core/rbasic.h new file mode 100644 index 000000000..4617f743a --- /dev/null +++ b/ruby/include/ruby/internal/core/rbasic.h @@ -0,0 +1,158 @@ +#ifndef RBIMPL_RBASIC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RBASIC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RBasic. + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/forceinline.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +/** + * Convenient casting macro. + * + * @param obj Arbitrary Ruby object. + * @return The passed object casted to ::RBasic. + */ +#define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj)) +/** @cond INTERNAL_MACRO */ +#define RBASIC_CLASS RBASIC_CLASS +#define RBIMPL_RVALUE_EMBED_LEN_MAX 3 +#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX +#define RBIMPL_EMBED_LEN_MAX_OF(T) \ + RBIMPL_CAST((int)(sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) / (sizeof(T)))) +/** @endcond */ + +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_rvalue_flags { + /** Max possible number of objects that can be embedded. */ + RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX +}; + +/** + * Ruby's object's, base components. Every single ruby objects have them in + * common. + */ +struct +RUBY_ALIGNAS(SIZEOF_VALUE) +RBasic { + + /** + * Per-object flags. Each ruby objects have their own characteristics + * apart from their classes. For instance whether an object is frozen or + * not is not controlled by its class. This is where such properties are + * stored. + * + * @see enum ::ruby_fl_type + * + * @note This is ::VALUE rather than an enum for alignment purpose. Back + * in the 1990s there were no such thing like `_Alignas` in C. + */ + VALUE flags; + + /** + * Class of an object. Every object has its class. Also, everything is an + * object in Ruby. This means classes are also objects. Classes have + * their own classes, classes of classes have their classes, too ... and + * it recursively continues forever. + * + * Also note the `const` qualifier. In ruby an object cannot "change" its + * class. + */ + const VALUE klass; + +#ifdef __cplusplus + public: + RBIMPL_ATTR_CONSTEXPR(CXX11) + RBIMPL_ATTR_ARTIFICIAL() + RBIMPL_ATTR_FORCEINLINE() + RBIMPL_ATTR_NOALIAS() + /** + * We need to define this explicit constructor because the field `klass` is + * const-qualified above, which effectively defines the implicit default + * constructor as "deleted" (as of C++11) -- No way but to define one by + * ourselves. + */ + RBasic() : + flags(RBIMPL_VALUE_NULL), + klass(RBIMPL_VALUE_NULL) + { + } +#endif +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Make the object invisible from Ruby code. + * + * It is useful to let Ruby's GC manage your internal data structure -- The + * object keeps being managed by GC, but `ObjectSpace.each_object` never yields + * the object. + * + * Note that the object also lose a way to call a method on it. + * + * @param[out] obj A Ruby object. + * @return The passed object. + * @post The object is destructively modified to be invisible. + * @see rb_obj_reveal + */ +VALUE rb_obj_hide(VALUE obj); + +/** + * Make a hidden object visible again. + * + * It is the caller's responsibility to pass the right `klass` which `obj` + * originally used to belong to. + * + * @param[out] obj A Ruby object. + * @param[in] klass Class of `obj`. + * @return Passed `obj`. + * @pre `obj` was previously hidden. + * @post `obj`'s class is `klass`. + * @see rb_obj_hide + */ +VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */ +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the class of an object. + * + * @param[in] obj An object. + * @return Its class. + */ +static inline VALUE +RBASIC_CLASS(VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); + return RBASIC(obj)->klass; +} + +#endif /* RBIMPL_RBASIC_H */ diff --git a/ruby/include/ruby/internal/core/rbignum.h b/ruby/include/ruby/internal/core/rbignum.h new file mode 100644 index 000000000..1d3174323 --- /dev/null +++ b/ruby/include/ruby/internal/core/rbignum.h @@ -0,0 +1,80 @@ +#ifndef RBIMPL_RBIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RBIGNUM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate struct RBignum. + * @note The struct RBignum itself is opaque. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/internal/stdbool.h" + +#define RBIGNUM_SIGN rb_big_sign /**< @alias{rb_big_sign} */ + +/** @cond INTERNAL_MACRO */ +#define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P +#define RBIGNUM_NEGATIVE_P RBIGNUM_NEGATIVE_P +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * The "sign" of a bignum. + * + * @param[in] num An object of RBignum. + * @retval 1 It is greater than or equal to zero. + * @retval 0 It is less than zero. + * + * @internal + * + * Implementation wise, unlike fixnums (which are 2's complement), bignums are + * signed magnitude system. Theoretically it could be possible to have + * negative zero instances. But in reality there is no way to create such + * thing. Nobody ever needed that kind of insanity. + */ +int rb_big_sign(VALUE num); +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Checks if the bignum is positive. + * @param[in] b An object of RBignum. + * @retval false `b` is less than zero. + * @retval true Otherwise. + */ +static inline bool +RBIGNUM_POSITIVE_P(VALUE b) +{ + RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); + return RBIGNUM_SIGN(b); +} + +/** + * Checks if the bignum is negative. + * @param[in] b An object of RBignum. + * @retval true `b` is less than zero. + * @retval false Otherwise. + */ +static inline bool +RBIGNUM_NEGATIVE_P(VALUE b) +{ + RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); + return ! RBIGNUM_POSITIVE_P(b); +} + +#endif /* RBIMPL_RBIGNUM_H */ diff --git a/ruby/include/ruby/internal/core/rclass.h b/ruby/include/ruby/internal/core/rclass.h new file mode 100644 index 000000000..13a33a28b --- /dev/null +++ b/ruby/include/ruby/internal/core/rclass.h @@ -0,0 +1,140 @@ +#ifndef RBIMPL_RCLASS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RCLASS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate struct RClass. + * @note The struct RClass itself is opaque. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/cast.h" + +/** @cond INTERNAL_MACRO */ +#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID +#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT +#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT +/** @endcond */ + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an RClass. + * @return The passed object casted to RClass. + */ +#define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj)) + +/** @alias{RCLASS} */ +#define RMODULE RCLASS + +/** @alias{rb_class_get_superclass} */ +#define RCLASS_SUPER rb_class_get_superclass + +/** + * @private + * + * Bits that you can set to ::RBasic::flags. + * + * @internal + * + * Why is it here, given RClass itself is not? + */ +enum ruby_rmodule_flags { + + /** + * This flag has something to do with refinements... I guess? It is set on + * occasions for modules that are refined by refinements, but it seems + * ... nobody cares about such things? Not sure but this flag could + * perhaps be a write-only information. + */ + RMODULE_IS_OVERLAID = RUBY_FL_USER2, + + /** + * This flag has something to do with refinements. A module created using + * rb_mod_refine() has this flag set. This is the bit which controls + * difference between normal inclusion versus refinements. + */ + RMODULE_IS_REFINEMENT = RUBY_FL_USER3, + + /** + * This flag has something to do with refinements. This is set when a + * (non-refinement) module is included into another module, which is a + * refinement. This amends the way `super` searches for a super method. + * + * ```ruby + * class Foo + * def foo + * "Foo" + * end + * end + * + * module Bar + * def foo + * "[#{super}]" # this + * end + * end + * + * module Baz + * refine Foo do + * include Bar + * def foo + * "<#{super}>" + * end + * end + * end + * + * using Baz + * Foo.new.foo # => "[]" + * ``` + * + * The `super` marked with "this" comment shall look for overlaid + * `Foo#foo`, which is not the ordinal method lookup direction. + */ + RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4 +}; + +struct RClass; /* Opaque, declared here for RCLASS() macro. */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Returns the superclass of a class. + * @param[in] klass An object of RClass. + * @retval RUBY_Qfalse `klass` has no super class. + * @retval otherwise Raw superclass of `klass` + * @see rb_class_superclass + * + * ### Q&A ### + * + * - Q: How can a class have no super class? + * + * - A: `klass` could be a module. Or it could be ::rb_cBasicObject. + * + * - Q: What do you mean by "raw" superclass? + * + * - A: This is a really good question. The answer is that this function + * returns something different from what you would normally expect. On + * occasions ruby inserts hidden classes in a hierarchy of class + * inheritance behind-the-scene. Such classes are called "iclass"es and + * distinguished using ::RUBY_T_ICLASS in C level. They are truly + * transparent from Ruby level but can be accessed from C, by using this + * API. + */ +VALUE rb_class_get_superclass(VALUE klass); +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_RCLASS_H */ diff --git a/ruby/include/ruby/internal/core/rdata.h b/ruby/include/ruby/internal/core/rdata.h new file mode 100644 index 000000000..f6656b654 --- /dev/null +++ b/ruby/include/ruby/internal/core/rdata.h @@ -0,0 +1,410 @@ +#ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RDATA_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RData. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/warning.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/defines.h" + +/** @cond INTERNAL_MACRO */ +#ifdef RUBY_UNTYPED_DATA_WARNING +# /* Take that. */ +#elif defined(RUBY_EXPORT) +# define RUBY_UNTYPED_DATA_WARNING 1 +#else +# define RUBY_UNTYPED_DATA_WARNING 0 +#endif + +#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f)) +#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \ + RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \ + RBIMPL_ATTR_DEPRECATED(("by TypedData")) + +#define RBIMPL_MACRO_SELECT(x, y) x ## y +#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y) +/** @endcond */ + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RData. + * @return The passed object casted to ::RData. + */ +#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj)) + +/** + * Convenient getter macro. + * + * @param obj An object, which is in fact an ::RData. + * @return The passed object's ::RData::data field. + */ +#define DATA_PTR(obj) RDATA(obj)->data + +/** + * This is a value you can set to ::RData::dfree. Setting this means the data + * was allocated using ::ruby_xmalloc() (or variants), and shall be freed using + * ::ruby_xfree(). + * + * @warning Do not use this if you want to use system malloc, because the + * system and Ruby might or might not share the same malloc + * implementation. + */ +#define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1) + +/** + * This is a value you can set to ::RData::dfree. Setting this means the data + * is managed by someone else, like, statically allocated. Of course you are + * on your own then. + */ +#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0) + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() + +/* +#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func)) +*/ + +/** + * This is the type of callbacks registered to ::RData. The argument is the + * `data` field. + */ +typedef void (*RUBY_DATA_FUNC)(void*); + +/** + * @deprecated + * + * Old "untyped" user data. It has roughly the same usage as struct + * ::RTypedData, but lacked several features such as support for compaction GC. + * Use of this struct is not recommended any longer. If it is dead necessary, + * please inform the core devs about your usage. + * + * @internal + * + * @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded + * too many warnings in the core. Maybe we want to retry later... Just add + * deprecated document for now. + */ +struct RData { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** + * This function is called when the object is experiencing GC marks. If it + * contains references to other Ruby objects, you need to mark them also. + * Otherwise GC will smash your data. + * + * @see rb_gc_mark() + * @warning This is called during GC runs. Object allocations are + * impossible at that moment (that is why GC runs). + */ + RUBY_DATA_FUNC dmark; + + /** + * This function is called when the object is no longer used. You need to + * do whatever necessary to avoid memory leaks. + * + * @warning This is called during GC runs. Object allocations are + * impossible at that moment (that is why GC runs). + */ + RUBY_DATA_FUNC dfree; + + /** Pointer to the actual C level struct that you want to wrap. */ + void *data; +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * This is the primitive way to wrap an existing C struct into ::RData. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] datap Pointer to the target C struct. + * @param[in] dmark Mark function. + * @param[in] dfree Free function. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return An allocated object that wraps `datap`. + */ +VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); + +/** + * Identical to rb_data_object_wrap(), except it allocates a new data region + * internally instead of taking an existing one. The allocation is done using + * ruby_calloc(). Hence it makes no sense to pass anything other than + * ::RUBY_DEFAULT_FREE to the last argument. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] size Requested size of memory to allocate. + * @param[in] dmark Mark function. + * @param[in] dfree Free function. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return An allocated object that wraps a new `size` byte region. + */ +VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); + +/** + * @private + * Documented in include/ruby/internal/globals.h + */ +RUBY_EXTERN VALUE rb_cObject; +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Converts sval, a pointer to your struct, into a Ruby object. + * + * @param klass A ruby level class. + * @param mark Mark function. + * @param free Free function. + * @param sval A pointer to your struct. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + */ +#define Data_Wrap_Struct(klass, mark, free, sval) \ + rb_data_object_wrap( \ + (klass), \ + (sval), \ + RBIMPL_DATA_FUNC(mark), \ + RBIMPL_DATA_FUNC(free)) + +/** + * @private + * + * This is an implementation detail of #Data_Make_Struct. People don't use it + * directly. + * + * @param result Variable name of created Ruby object. + * @param klass Ruby level class of the object. + * @param type Type name of the C struct. + * @param size Size of the C struct. + * @param mark Mark function. + * @param free Free function. + * @param sval Variable name of created C struct. + */ +#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \ + VALUE result = rb_data_object_zalloc( \ + (klass), \ + (size), \ + RBIMPL_DATA_FUNC(mark), \ + RBIMPL_DATA_FUNC(free)); \ + (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \ + RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) + +/** + * Identical to #Data_Wrap_Struct, except it allocates a new data region + * internally instead of taking an existing one. The allocation is done using + * ruby_calloc(). Hence it makes no sense to pass anything other than + * ::RUBY_DEFAULT_FREE to the `free` argument. + * + * @param klass Ruby level class of the returning object. + * @param type Type name of the C struct. + * @param mark Mark function. + * @param free Free function. + * @param sval Variable name of created C struct. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + */ +#ifdef HAVE_STMT_AND_DECL_IN_EXPR +#define Data_Make_Struct(klass, type, mark, free, sval) \ + RB_GNUC_EXTENSION({ \ + Data_Make_Struct0( \ + data_struct_obj, \ + klass, \ + type, \ + sizeof(type), \ + mark, \ + free, \ + sval); \ + data_struct_obj; \ + }) +#else +#define Data_Make_Struct(klass, type, mark, free, sval) \ + rb_data_object_make( \ + (klass), \ + RBIMPL_DATA_FUNC(mark), \ + RBIMPL_DATA_FUNC(free), \ + RBIMPL_CAST((void **)&(sval)), \ + sizeof(type)) +#endif + +/** + * Obtains a C struct from inside of a wrapper Ruby object. + * + * @param obj An instance of ::RData. + * @param type Type name of the C struct. + * @param sval Variable name of obtained C struct. + * @return Unwrapped C struct that `obj` holds. + */ +#define Data_Get_Struct(obj, type, sval) \ + ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj))) + +RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() +/** + * @private + * + * This is an implementation detail of rb_data_object_wrap(). People don't use + * it directly. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] ptr Pointer to the target C struct. + * @param[in] mark Mark function. + * @param[in] free Free function. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return An allocated object that wraps `datap`. + */ +static inline VALUE +rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free) +{ + return rb_data_object_wrap(klass, ptr, mark, free); +} + +/** + * @private + * + * This is an implementation detail of #Data_Get_Struct. People don't use it + * directly. + * + * @param[in] obj An instance of ::RData. + * @return Unwrapped C struct that `obj` holds. + */ +static inline void * +rb_data_object_get(VALUE obj) +{ + Check_Type(obj, RUBY_T_DATA); + return DATA_PTR(obj); +} + +RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() +/** + * @private + * + * This is an implementation detail of #Data_Get_Struct. People don't use it + * directly. + * + * @param[in] obj An instance of ::RData. + * @return Unwrapped C struct that `obj` holds. + */ +static inline void * +rb_data_object_get_warning(VALUE obj) +{ + return rb_data_object_get(obj); +} + +#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# define rb_data_object_wrap_warning(klass, ptr, mark, free) \ + RB_GNUC_EXTENSION( \ + __builtin_choose_expr( \ + __builtin_constant_p(klass) && !(klass), \ + rb_data_object_wrap(klass, ptr, mark, free), \ + (rb_data_object_wrap_warning)(klass, ptr, mark, free))) +#endif + +/** + * This is an implementation detail of #Data_Make_Struct. People don't use it + * directly. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] mark_func Mark function. + * @param[in] free_func Free function. + * @param[in] datap Variable of created C struct. + * @param[in] size Requested size of allocation. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + * @post `*datap` holds the created C struct. + */ +static inline VALUE +rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size) +{ + Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap); + return result; +} + +RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap")) +/** @deprecated This function was renamed to rb_data_object_wrap(). */ +static inline VALUE +rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) +{ + return rb_data_object_wrap(klass, data, dmark, dfree); +} + +RBIMPL_ATTR_DEPRECATED(("by: rb_cObject. Will be removed in 3.1.")) +RBIMPL_ATTR_PURE() +/** + * @private + * + * @deprecated There once was a variable called rb_cData, which no longer + * exists today. This function is a function because we want + * warnings for the usages. + */ +static inline VALUE +rb_cData(void) +{ + return rb_cObject; +} + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define rb_cData rb_cData() + +/** @cond INTERNAL_MACRO */ +#define rb_data_object_wrap_0 rb_data_object_wrap +#define rb_data_object_wrap_1 rb_data_object_wrap_warning +#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */ +#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING) +#define rb_data_object_get_0 rb_data_object_get +#define rb_data_object_get_1 rb_data_object_get_warning +#define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */ +#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING) +#define rb_data_object_make_0 rb_data_object_make +#define rb_data_object_make_1 rb_data_object_make_warning +#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */ +#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING) +/** @endcond */ +#endif /* RBIMPL_RDATA_H */ diff --git a/ruby/include/ruby/internal/core/rfile.h b/ruby/include/ruby/internal/core/rfile.h new file mode 100644 index 000000000..f8dddde9e --- /dev/null +++ b/ruby/include/ruby/internal/core/rfile.h @@ -0,0 +1,51 @@ +#ifndef RBIMPL_RFILE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RFILE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RFile. + */ +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/cast.h" + +/* rb_io_t is in ruby/io.h. The header file has historically not been included + * into ruby/ruby.h. We follow that tradition. */ +struct rb_io_t; + +/** + * Ruby's File and IO. Ruby's IO are not just file descriptors. They have + * buffers. They also have encodings. Various information are controlled + * using this struct. + */ +struct RFile { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** IO's specific fields. */ + struct rb_io_t *fptr; +}; + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RFile. + * @return The passed object casted to ::RFile. + */ +#define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj)) +#endif /* RBIMPL_RFILE_H */ diff --git a/ruby/include/ruby/internal/core/rhash.h b/ruby/include/ruby/internal/core/rhash.h new file mode 100644 index 000000000..61d2c15d8 --- /dev/null +++ b/ruby/include/ruby/internal/core/rhash.h @@ -0,0 +1,144 @@ +#ifndef RBIMPL_RHASH_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RHASH_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate struct RHash. + * @note The struct RHash itself is opaque. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY +# include "ruby/backward.h" +#endif + +/** + * Retrieves the internal table. + * + * @param[in] h An instance of RHash. + * @pre `h` must be of ::RUBY_T_HASH. + * @return A struct st_table which has the contents of this hash. + * @note Nowadays as Ruby evolved over ages, RHash has multiple backend + * storage engines. `h`'s backend is not guaranteed to be a + * st_table. This function creates one when necessary. + */ +#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__) + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * Declaration of rb_hash_iter_lev() is at include/ruby/backward.h. + */ +#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h) + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * Declaration of rb_hash_ifnone() is at include/ruby/backward.h. + */ +#define RHASH_IFNONE(h) rb_hash_ifnone(h) + +/** + * Queries the size of the hash. Size here means the number of keys that the + * hash stores. + * + * @param[in] h An instance of RHash. + * @pre `h` must be of ::RUBY_T_HASH. + * @return The size of the hash. + */ +#define RHASH_SIZE(h) rb_hash_size_num(h) + +/** + * Checks if the hash is empty. + * + * @param[in] h An instance of RHash. + * @pre `h` must be of ::RUBY_T_HASH. + * @retval true It is. + * @retval false It isn't. + */ +#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0) + +/** + * Destructively updates the default value of the hash. + * + * @param[out] h An instance of RHash. + * @param[in] ifnone Arbitrary default value. + * @pre `h` must be of ::RUBY_T_HASH. + * + * @internal + * + * But why you can set this, given rb_hash_ifnone() doesn't exist? + */ +#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone) + +struct st_table; /* in ruby/st.h */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * This is the implementation detail of #RHASH_SIZE. People don't call this + * directly. + * + * @param[in] hash An instance of RHash. + * @pre `hash` must be of ::RUBY_T_HASH. + * @return The size of the hash. + */ +size_t rb_hash_size_num(VALUE hash); + +/** + * This is the implementation detail of #RHASH_TBL. People don't call this + * directly. + * + * @param[in] hash An instance of RHash. + * @param[in] file The `__FILE__`. + * @param[in] line The `__LINE__`. + * @pre `hash` must be of ::RUBY_T_HASH. + * @return Table that has the contents of the hash. + */ +struct st_table *rb_hash_tbl(VALUE hash, const char *file, int line); + +/** + * This is the implementation detail of #RHASH_SET_IFNONE. People don't call + * this directly. + * + * @param[out] hash An instance of RHash. + * @param[in] ifnone Arbitrary default value. + * @pre `hash` must be of ::RUBY_T_HASH. + */ +VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone); +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_RHASH_H */ diff --git a/ruby/include/ruby/internal/core/rmatch.h b/ruby/include/ruby/internal/core/rmatch.h new file mode 100644 index 000000000..2d2fd897f --- /dev/null +++ b/ruby/include/ruby/internal/core/rmatch.h @@ -0,0 +1,146 @@ +#ifndef RBIMPL_RMATCH_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RMATCH_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RMatch. + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/assert.h" + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RMatch. + * @return The passed object casted to ::RMatch. + */ +#define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj)) +/** @cond INTERNAL_MACRO */ +#define RMATCH_REGS RMATCH_REGS +/** @endcond */ + +struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ +struct re_registers; /* Also in onigmo.h */ + +/** + * @old{re_pattern_buffer} + * + * @internal + * + * @shyouhei wonders: is anyone actively using this typedef ...? + */ +typedef struct re_pattern_buffer Regexp; + +/** + * Represents the region of a capture group. This is basically for caching + * purpose. re_registers have similar concepts (`beg` and `end`) but they are + * in `ptrdiff_t*`. In order for us to implement `MatchData#offset` that info + * has to be converted to offset integers. This is the struct to hold such + * things. + * + * @internal + * + * But why on earth it has to be visible from extension libraries? + */ +struct rmatch_offset { + long beg; /**< Beginning of a group. */ + long end; /**< End of a group. */ +}; + +/** Represents a match. */ +struct rmatch { + /** + * "Registers" of a match. This is a quasi-opaque struct that holds + * execution result of a match. Roughly resembles `&~`. + */ + struct re_registers regs; + + /** Capture group offsets, in C array. */ + struct rmatch_offset *char_offset; + + /** Number of ::rmatch_offset that ::rmatch::char_offset holds. */ + int char_offset_num_allocated; +}; + +/** + * Regular expression execution context. When a regular expression "matches" + * to a string, it generates capture groups etc. This struct holds that info. + * Visible from Ruby as an instance of `MatchData`. + * + * @note There is no way for extension libraries to manually generate this + * struct except by actually exercising the match operation of a regular + * expression. + */ +struct RMatch { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** + * The target string that the match was made against. + */ + VALUE str; + + /** + * The result of this match. + */ + struct rmatch *rmatch; + + /** + * The expression of this match. + */ + VALUE regexp; /* RRegexp */ +}; + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the raw ::re_registers. + * + * @param[in] match A match object + * @pre `match` must be of ::RMatch. + * @return Its execution result. + * @note Good. So you are aware of the fact that it could return NULL. + * Yes. It actually does. This is a really bizarre thing. The + * situation is about `String#gsub` and its family. They take + * strings as arguments, like `"foo".sub("bar", "baz")`. On such + * situations, in order to optimise memory allocations, these + * methods do not involve regular expressions at all. They just + * sequentially scan the receiver. Okay. The story begins here. + * Even when they do not kick our regexp engine, there must be + * backref objects e.g. `$&`. But how? You know what? Ruby fakes + * them. It allocates an empty ::RMatch and behaves as if there + * were execution contexts. In reality there weren't. No + * ::re_registers are allocated then. There is no way for this + * function but to return NULL for those fake ::RMatch. This is + * the reason for the nullability of this function. + */ +static inline struct re_registers * +RMATCH_REGS(VALUE match) +{ + RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH); + RBIMPL_ASSERT_OR_ASSUME(RMATCH(match)->rmatch != NULL); + return &RMATCH(match)->rmatch->regs; +} + +#endif /* RBIMPL_RMATCH_H */ diff --git a/ruby/include/ruby/internal/core/robject.h b/ruby/include/ruby/internal/core/robject.h new file mode 100644 index 000000000..f2028063a --- /dev/null +++ b/ruby/include/ruby/internal/core/robject.h @@ -0,0 +1,185 @@ +#ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ROBJECT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RObject. + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_STDINT_H +# include +#endif + +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RRegexp. + * @return The passed object casted to ::RRegexp. + */ +#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj)) +/** @cond INTERNAL_MACRO */ +#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX +#define ROBJECT_EMBED ROBJECT_EMBED +#define ROBJECT_NUMIV ROBJECT_NUMIV +#define ROBJECT_IVPTR ROBJECT_IVPTR +#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL +/** @endcond */ + +/** + * @private + * + * Bits that you can set to ::RBasic::flags. + */ +enum ruby_robject_flags { + /** + * This flag has something to do with memory footprint. If the object is + * "small" enough, ruby tries to be creative to abuse padding bits of + * struct ::RObject for storing instance variables. This flag denotes that + * situation. + * + * @warning This bit has to be considered read-only. Setting/clearing + * this bit without corresponding fix up must cause immediate + * SEGV. Also, internal structures of an object change + * dynamically and transparently throughout of its lifetime. + * Don't assume it being persistent. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store instance variables. Might better be hidden. + */ + ROBJECT_EMBED = RUBY_FL_USER1 +}; + +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_robject_consts { + /** Max possible number of instance variables that can be embedded. */ + ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) +}; + +struct st_table; + +/** + * Ruby's ordinal objects. Unless otherwise special cased, all predefined and + * user-defined classes share this struct to hold their instances. + */ +struct RObject { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** Object's specific fields. */ + union { + + /** + * Object that use separated memory region for instance variables use + * this pattern. + */ + struct { + + /** + * Number of instance variables. This is per object; objects might + * differ in this field even if they have the identical classes. + */ + uint32_t numiv; + + /** Pointer to a C array that holds instance variables. */ + VALUE *ivptr; + + /** + * This is a table that holds instance variable name to index + * mapping. Used when accessing instance variables using names. + * + * @internal + * + * This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`. + */ + struct st_table *iv_index_tbl; + } heap; + + /** + * Embedded instance variables. When an object is small enough, it + * uses this area to store the instance variables. + */ + VALUE ary[ROBJECT_EMBED_LEN_MAX]; + } as; +}; + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the number of instance variables. + * + * @param[in] obj Object in question. + * @return Its number of instance variables. + * @pre `obj` must be an instance of ::RObject. + */ +static inline uint32_t +ROBJECT_NUMIV(VALUE obj) +{ + RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); + + if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { + return ROBJECT_EMBED_LEN_MAX; + } + else { + return ROBJECT(obj)->as.heap.numiv; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the instance variables. + * + * @param[in] obj Object in question. + * @return Its instance variables, in C array. + * @pre `obj` must be an instance of ::RObject. + * + * @internal + * + * @shyouhei finds no reason for this to be visible from extension libraries. + */ +static inline VALUE * +ROBJECT_IVPTR(VALUE obj) +{ + RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); + + struct RObject *const ptr = ROBJECT(obj); + + if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { + return ptr->as.ary; + } + else { + return ptr->as.heap.ivptr; + } +} + +#endif /* RBIMPL_ROBJECT_H */ diff --git a/ruby/include/ruby/internal/core/rregexp.h b/ruby/include/ruby/internal/core/rregexp.h new file mode 100644 index 000000000..cf54a399f --- /dev/null +++ b/ruby/include/ruby/internal/core/rregexp.h @@ -0,0 +1,168 @@ +#ifndef RBIMPL_RREGEXP_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RREGEXP_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RRegexp. + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/core/rstring.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RRegexp. + * @return The passed object casted to ::RRegexp. + */ +#define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj)) + +/** + * Convenient accessor macro. + * + * @param obj An object, which is in fact an ::RRegexp. + * @return The passed object's pattern buffer. + */ +#define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr) +/** @cond INTERNAL_MACRO */ +#define RREGEXP_SRC RREGEXP_SRC +#define RREGEXP_SRC_PTR RREGEXP_SRC_PTR +#define RREGEXP_SRC_LEN RREGEXP_SRC_LEN +#define RREGEXP_SRC_END RREGEXP_SRC_END +/** @endcond */ + +struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ + +/** + * Ruby's regular expression. A regexp is compiled into its own intermediate + * representation. This one holds that info. Regexp "match" operation then + * executes that IR. + */ +struct RRegexp { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** + * The pattern buffer. This is a quasi-opaque struct that holds compiled + * intermediate representation of the regular expression. + * + * @note Compilation of a regexp could be delayed until actual match. + */ + struct re_pattern_buffer *ptr; + + /** Source code of this expression. */ + const VALUE src; + + /** + * Reference count. A regexp match can take extraordinarily long time to + * run. Ruby's regular expression is heavily extended and not a regular + * language any longer; runs in NP-time in practice. Now, Ruby also has + * threads and GVL. In order to prevent long GVL lockup, our regexp engine + * can release it on occasions. This means that multiple threads can touch + * a regular expressions at once. That itself is okay. But their cleanup + * phase shall wait for all the concurrent runs, to prevent use-after-free + * situation. This field is used to count such threads that are executing + * this particular pattern buffer. + * + * @warning Of course, touching this field from extension libraries causes + * catastrophic effects. Just leave it. + */ + unsigned long usecnt; +}; + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Convenient getter function. + * + * @param[in] rexp The regular expression in question. + * @return The source code of the regular expression. + * @pre `rexp` must be of ::RRegexp. + */ +static inline VALUE +RREGEXP_SRC(VALUE rexp) +{ + RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP); + VALUE ret = RREGEXP(rexp)->src; + RBIMPL_ASSERT_TYPE(ret, RUBY_T_STRING); + return ret; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Convenient getter function. + * + * @param[in] rexp The regular expression in question. + * @return The source code of the regular expression, in C's string. + * @pre `rexp` must be of ::RRegexp. + * + * @internal + * + * It seems nobody uses this function in the wild. Subject to hide? + */ +static inline char * +RREGEXP_SRC_PTR(VALUE rexp) +{ + return RSTRING_PTR(RREGEXP_SRC(rexp)); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Convenient getter function. + * + * @param[in] rexp The regular expression in question. + * @return The length of the source code of the regular expression. + * @pre `rexp` must be of ::RRegexp. + * + * @internal + * + * It seems nobody uses this function in the wild. Subject to hide? + */ +static inline long +RREGEXP_SRC_LEN(VALUE rexp) +{ + return RSTRING_LEN(RREGEXP_SRC(rexp)); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Convenient getter function. + * + * @param[in] rexp The regular expression in question. + * @return The end of the source code of the regular expression. + * @pre `rexp` must be of ::RRegexp. + * + * @internal + * + * It seems nobody uses this function in the wild. Subject to hide? + */ +static inline char * +RREGEXP_SRC_END(VALUE rexp) +{ + return RSTRING_END(RREGEXP_SRC(rexp)); +} + +#endif /* RBIMPL_RREGEXP_H */ diff --git a/ruby/include/ruby/internal/core/rstring.h b/ruby/include/ruby/internal/core/rstring.h new file mode 100644 index 000000000..a682dbe22 --- /dev/null +++ b/ruby/include/ruby/internal/core/rstring.h @@ -0,0 +1,577 @@ +#ifndef RBIMPL_RSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RSTRING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RString. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/value_type.h" +#include "ruby/internal/warning_push.h" +#include "ruby/assert.h" + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RString. + * @return The passed object casted to ::RString. + */ +#define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj)) + +/** @cond INTERNAL_MACRO */ +#define RSTRING_NOEMBED RSTRING_NOEMBED +#if !USE_RVARGC +#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK +#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT +#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX +#endif +#define RSTRING_FSTR RSTRING_FSTR +#define RSTRING_EMBED_LEN RSTRING_EMBED_LEN +#define RSTRING_LEN RSTRING_LEN +#define RSTRING_LENINT RSTRING_LENINT +#define RSTRING_PTR RSTRING_PTR +#define RSTRING_END RSTRING_END +/** @endcond */ + +/** + * @name Conversion of Ruby strings into C's + * + * @{ + */ + +/** + * Ensures that the parameter object is a String. This is done by calling its + * `to_str` method. + * + * @param[in,out] v Arbitrary Ruby object. + * @exception rb_eTypeError No implicit conversion defined. + * @post `v` is a String. + */ +#define StringValue(v) rb_string_value(&(v)) + +/** + * Identical to #StringValue, except it returns a `char*`. + * + * @param[in,out] v Arbitrary Ruby object. + * @exception rb_eTypeError No implicit conversion defined. + * @return Converted Ruby string's backend C string. + * @post `v` is a String. + */ +#define StringValuePtr(v) rb_string_value_ptr(&(v)) + +/** + * Identical to #StringValuePtr, except it additionally checks for the contents + * for viability as a C string. Ruby can accept wider range of contents as + * strings, compared to C. This function is to check that. + * + * @param[in,out] v Arbitrary Ruby object. + * @exception rb_eTypeError No implicit conversion defined. + * @exception rb_eArgError String is not C-compatible. + * @return Converted Ruby string's backend C string. + * @post `v` is a String. + */ +#define StringValueCStr(v) rb_string_value_cstr(&(v)) + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define SafeStringValue(v) StringValue(v) + +/** + * Identical to #StringValue, except it additionally converts the string's + * encoding to default external encoding. Ruby has a concept called encodings. + * A string can have different encoding than the environment expects. Someone + * has to make sure its contents be converted to something suitable. This is + * that routine. Call it when necessary. + * + * @param[in,out] v Arbitrary Ruby object. + * @exception rb_eTypeError No implicit conversion defined. + * @return Converted Ruby string's backend C string. + * @post `v` is a String. + * + * @internal + * + * Not sure but it seems this macro does not raise on encoding + * incompatibilities? Doesn't sound right to @shyouhei. + */ +#define ExportStringValue(v) do { \ + StringValue(v); \ + (v) = rb_str_export(v); \ +} while (0) + +/** @} */ + +/** + * @private + * + * Bits that you can set to ::RBasic::flags. + * + * @warning These enums are not the only bits we use for strings. + * + * @internal + * + * Actually all bits through FL_USER1 to FL_USER19 are used for strings. Why + * only this tiny part of them are made public here? @shyouhei can find no + * reason. + */ +enum ruby_rstring_flags { + + /** + * This flag has something to do with memory footprint. If the string is + * short enough, ruby tries to be creative to abuse padding bits of struct + * ::RString for storing contents. If this flag is set that string does + * _not_ do that, to resort to good old fashioned external allocation + * strategy instead. + * + * @warning This bit has to be considered read-only. Setting/clearing + * this bit without corresponding fix up must cause immediate + * SEGV. Also, internal structures of a string change + * dynamically and transparently throughout of its lifetime. + * Don't assume it being persistent. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store a string. Might better be hidden. + */ + RSTRING_NOEMBED = RUBY_FL_USER1, + +#if !USE_RVARGC + /** + * When a string employs embedded strategy (see ::RSTRING_NOEMBED), these + * bits are used to store the number of bytes actually filled into + * ::RString::ary. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store a string. Might better be hidden. + */ + RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 | + RUBY_FL_USER5 | RUBY_FL_USER6, +#endif + + /* Actually, string encodings are also encoded into the flags, using + * remaining bits.*/ + + /** + * This flag has something to do with infamous "f"string. What is a + * fstring? Well it is a special subkind of strings that is immutable, + * deduped globally, and managed by our GC. It is much like a Symbol (in + * fact Symbols are dynamic these days and are backended using fstrings). + * This concept has been silently introduced at some point in 2.x era. + * Since then it gained wider acceptance in the core. But extension + * libraries could not know that until very recently. Strings of this flag + * live in a special Limbo deep inside of the interpreter. Never try to + * manipulate it by hand. + * + * @internal + * + * Fstrings are not the only variant strings that we implement today. + * Other things are behind-the-scene. This is the only one that is visible + * from extension library. There is no clear reason why it has to be. + * Given there are more "polite" ways to create fstrings, it seems this bit + * need not be exposed to extension libraries. Might better be hidden. + */ + RSTRING_FSTR = RUBY_FL_USER17 +}; + +#if !USE_RVARGC +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_rstring_consts { + /** Where ::RSTRING_EMBED_LEN_MASK resides. */ + RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2, + + /** Max possible number of characters that can be embedded. */ + RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1 +}; +#endif + +/** + * Ruby's String. A string in ruby conceptually has these information: + * + * - Encoding of the string. + * - Length of the string. + * - Contents of the string. + * + * It is worth noting that a string is _not_ an array of characters in ruby. + * It has never been. In 1.x a string was an array of integers. Since 2.x a + * string is no longer an array of anything. A string is a string -- just like + * a Time is not an integer. + */ +struct RString { + + /** Basic part, including flags and class. */ + struct RBasic basic; + + /** String's specific fields. */ + union { + + /** + * Strings that use separated memory region for contents use this + * pattern. + */ + struct { + + /** + * Length of the string, not including terminating NUL character. + * + * @note This is in bytes. + */ + long len; + + /** + * Pointer to the contents of the string. In the old days each + * string had dedicated memory regions. That is no longer true + * today, but there still are strings of such properties. This + * field could be used to point such things. + */ + char *ptr; + + /** Auxiliary info. */ + union { + + /** + * Capacity of `*ptr`. A continuous memory region of at least + * `capa` bytes is expected to exist at `*ptr`. This can be + * bigger than `len`. + */ + long capa; + + /** + * Parent of the string. Nowadays strings can share their + * contents each other, constructing gigantic nest of objects. + * This situation is called "shared", and this is the field to + * control such properties. + */ + VALUE shared; + } aux; + } heap; + + /** Embedded contents. */ + struct { +#if USE_RVARGC + short len; + /* This is a length 1 array because: + * 1. GCC has a bug that does not optimize C flexible array members + * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) + * 2. Zero length arrays are not supported by all compilers + */ + char ary[1]; +#else + /** + * When a string is short enough, it uses this area to store the + * contents themselves. This was impractical in the 20th century, + * but these days 64 bit machines can typically hold 24 bytes here. + * Could be sufficiently large. In this case the length is encoded + * into the flags. + */ + char ary[RSTRING_EMBED_LEN_MAX + 1]; +#endif + } embed; + } as; +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Identical to rb_check_string_type(), except it raises exceptions in case of + * conversion failures. + * + * @param[in] obj Target object. + * @exception rb_eTypeError No implicit conversion to String. + * @return Return value of `obj.to_str`. + * @see rb_io_get_io + * @see rb_ary_to_ary + */ +VALUE rb_str_to_str(VALUE obj); + +/** + * Identical to rb_str_to_str(), except it fills the passed pointer with the + * converted object. + * + * @param[in,out] ptr Pointer to a variable of target object. + * @exception rb_eTypeError No implicit conversion to String. + * @return Return value of `obj.to_str`. + * @post `*ptr` is the return value. + */ +VALUE rb_string_value(volatile VALUE *ptr); + +/** + * Identical to rb_str_to_str(), except it returns the converted string's + * backend memory region. + * + * @param[in,out] ptr Pointer to a variable of target object. + * @exception rb_eTypeError No implicit conversion to String. + * @post `*ptr` is the return value of `obj.to_str`. + * @return Pointer to the contents of the return value. + */ +char *rb_string_value_ptr(volatile VALUE *ptr); + +/** + * Identical to rb_string_value_ptr(), except it additionally checks for the + * contents for viability as a C string. Ruby can accept wider range of + * contents as strings, compared to C. This function is to check that. + * + * @param[in,out] ptr Pointer to a variable of target object. + * @exception rb_eTypeError No implicit conversion to String. + * @exception rb_eArgError String is not C-compatible. + * @post `*ptr` is the return value of `obj.to_str`. + * @return Pointer to the contents of the return value. + */ +char *rb_string_value_cstr(volatile VALUE *ptr); + +/** + * Identical to rb_str_to_str(), except it additionally converts the string + * into default external encoding. Ruby has a concept called encodings. A + * string can have different encoding than the environment expects. Someone + * has to make sure its contents be converted to something suitable. This is + * that routine. Call it when necessary. + * + * @param[in] obj Target object. + * @exception rb_eTypeError No implicit conversion to String. + * @return Converted ruby string of default external encoding. + */ +VALUE rb_str_export(VALUE obj); + +/** + * Identical to rb_str_export(), except it converts into the locale encoding + * instead. + * + * @param[in] obj Target object. + * @exception rb_eTypeError No implicit conversion to String. + * @return Converted ruby string of locale encoding. + */ +VALUE rb_str_export_locale(VALUE obj); + +RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead")) +/** + * @private + * + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ +void rb_check_safe_str(VALUE); + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v))) + +/** + * @private + * + * Prints diagnostic message to stderr when RSTRING_PTR or RSTRING_END + * is NULL. + * + * @param[in] func The function name where encountered NULL pointer. + */ +void rb_debug_rstring_null_ptr(const char *func); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the length of the string. + * + * @param[in] str String in question. + * @return Its length, in bytes. + * @pre `str` must be an instance of ::RString, and must has its + * ::RSTRING_NOEMBED flag off. + * + * @internal + * + * This was a macro before. It was inevitable to be public, since macros are + * global constructs. But should it be forever? Now that it is a function, + * @shyouhei thinks it could just be eliminated, hidden into implementation + * details. + */ +static inline long +RSTRING_EMBED_LEN(VALUE str) +{ + RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); + RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED)); + +#if USE_RVARGC + short f = RSTRING(str)->as.embed.len; +#else + VALUE f = RBASIC(str)->flags; + f &= RSTRING_EMBED_LEN_MASK; + f >>= RSTRING_EMBED_LEN_SHIFT; +#endif + return RBIMPL_CAST((long)f); +} + +RBIMPL_WARNING_PUSH() +#if RBIMPL_COMPILER_IS(Intel) +RBIMPL_WARNING_IGNORED(413) +#endif + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * "Expands" an embedded string into an ordinal one. This is a function that + * returns aggregated type. The returned struct always has its `as.heap.len` + * an `as.heap.ptr` fields set appropriately. + * + * This is an implementation detail that 3rd parties should never bother. + */ +static inline struct RString +rbimpl_rstring_getmem(VALUE str) +{ + RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); + + if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) { + return *RSTRING(str); + } + else { + /* Expecting compilers to optimize this on-stack struct away. */ + struct RString retval; + retval.as.heap.len = RSTRING_EMBED_LEN(str); + retval.as.heap.ptr = RSTRING(str)->as.embed.ary; + return retval; + } +} + +RBIMPL_WARNING_POP() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the length of the string. + * + * @param[in] str String in question. + * @return Its length, in bytes. + * @pre `str` must be an instance of ::RString. + */ +static inline long +RSTRING_LEN(VALUE str) +{ + return rbimpl_rstring_getmem(str).as.heap.len; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the contents pointer of the string. + * + * @param[in] str String in question. + * @return Pointer to its contents. + * @pre `str` must be an instance of ::RString. + */ +static inline char * +RSTRING_PTR(VALUE str) +{ + char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; + + if (RB_UNLIKELY(! ptr)) { + /* :BEWARE: @shyouhei thinks that currently, there are rooms for this + * function to return NULL. In the 20th century that was a pointless + * concern. However struct RString can hold fake strings nowadays. It + * seems no check against NULL are exercised around handling of them + * (one of such usages is located in marshal.c, which scares + * @shyouhei). Better check here for maximum safety. + * + * Also, this is not rb_warn() because RSTRING_PTR() can be called + * during GC (see what obj_info() does). rb_warn() needs to allocate + * Ruby objects. That is not possible at this moment. */ + rb_debug_rstring_null_ptr("RSTRING_PTR"); + } + + return ptr; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the end of the contents pointer of the string. + * + * @param[in] str String in question. + * @return Pointer to its end of contents. + * @pre `str` must be an instance of ::RString. + */ +static inline char * +RSTRING_END(VALUE str) +{ + struct RString buf = rbimpl_rstring_getmem(str); + + if (RB_UNLIKELY(! buf.as.heap.ptr)) { + /* Ditto. */ + rb_debug_rstring_null_ptr("RSTRING_END"); + } + + return &buf.as.heap.ptr[buf.as.heap.len]; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RSTRING_LEN(), except it differs for the return type. + * + * @param[in] str String in question. + * @exception rb_eRangeError Too long. + * @return Its length, in bytes. + * @pre `str` must be an instance of ::RString. + * + * @internal + * + * This API seems redundant but has actual usages. + */ +static inline int +RSTRING_LENINT(VALUE str) +{ + return rb_long2int(RSTRING_LEN(str)); +} + +/** + * Convenient macro to obtain the contents and length at once. + * + * @param str String in question. + * @param ptrvar Variable where its contents is stored. + * @param lenvar Variable where its length is stored. + */ +#ifdef HAVE_STMT_AND_DECL_IN_EXPR +# define RSTRING_GETMEM(str, ptrvar, lenvar) \ + __extension__ ({ \ + struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ + (ptrvar) = rbimpl_str.as.heap.ptr; \ + (lenvar) = rbimpl_str.as.heap.len; \ + }) +#else +# define RSTRING_GETMEM(str, ptrvar, lenvar) \ + ((ptrvar) = RSTRING_PTR(str), \ + (lenvar) = RSTRING_LEN(str)) +#endif /* HAVE_STMT_AND_DECL_IN_EXPR */ +#endif /* RBIMPL_RSTRING_H */ diff --git a/ruby/include/ruby/internal/core/rstruct.h b/ruby/include/ruby/internal/core/rstruct.h new file mode 100644 index 000000000..69be487b5 --- /dev/null +++ b/ruby/include/ruby/internal/core/rstruct.h @@ -0,0 +1,121 @@ +#ifndef RBIMPL_RSTRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RSTRUCT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate struct RStruct. + * @note The struct RStruct itself is opaque. + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/internal/arithmetic/long.h" +#include "ruby/internal/arithmetic/int.h" +#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY +# include "ruby/backward.h" +#endif + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * Declaration of rb_struct_ptr() is at include/ruby/backward.h. + */ +#define RSTRUCT_PTR(st) rb_struct_ptr(st) +/** @cond INTERNAL_MACRO */ +#define RSTRUCT_LEN RSTRUCT_LEN +#define RSTRUCT_SET RSTRUCT_SET +#define RSTRUCT_GET RSTRUCT_GET +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * Returns the number of struct members. + * + * @param[in] st An instance of RStruct. + * @return The number of members of `st`. + * @pre `st` must be of ::RUBY_T_STRUCT. + */ +VALUE rb_struct_size(VALUE st); + +/** + * Resembles `Struct#[]`. + * + * @param[in] st An instance of RStruct. + * @param[in] k Index a.k.a. key of the struct. + * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String. + * @exception rb_eIndexError Numerical index out of range. + * @exception rb_eNameError No such key. + * @return The member stored at `k` in `st`. + * @pre `st` must be of ::RUBY_T_STRUCT. + */ +VALUE rb_struct_aref(VALUE st, VALUE k); + +/** + * Resembles `Struct#[]=`. + * + * @param[out] st An instance of RStruct. + * @param[in] k Index a.k.a. key of the struct. + * @param[in] v Value to store. + * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String. + * @exception rb_eIndexError Numerical index out of range. + * @exception rb_eNameError No such key. + * @return Passed `v`. + * @pre `st` must be of ::RUBY_T_STRUCT. + * @post `v` is stored at `k` in `st`. + */ +VALUE rb_struct_aset(VALUE st, VALUE k, VALUE v); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_ARTIFICIAL() +/** @copydoc rb_struct_size() */ +static inline long +RSTRUCT_LEN(VALUE st) +{ + RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); + + return RB_NUM2LONG(rb_struct_size(st)); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** @copydoc rb_struct_aset() */ +static inline VALUE +RSTRUCT_SET(VALUE st, int k, VALUE v) +{ + RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); + + return rb_struct_aset(st, INT2NUM(k), (v)); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** @copydoc rb_struct_aref() */ +static inline VALUE +RSTRUCT_GET(VALUE st, int k) +{ + RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); + + return rb_struct_aref(st, INT2NUM(k)); +} + +#endif /* RBIMPL_RSTRUCT_H */ diff --git a/ruby/include/ruby/internal/core/rtypeddata.h b/ruby/include/ruby/internal/core/rtypeddata.h new file mode 100644 index 000000000..bbf208867 --- /dev/null +++ b/ruby/include/ruby/internal/core/rtypeddata.h @@ -0,0 +1,604 @@ +#ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RTYPEDDATA_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines struct ::RTypedData. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/assume.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/flag_enum.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/core/rdata.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/error.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value_type.h" + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_TYPE_RB_DATA_TYPE_T 1 + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_DATA_TYPE_T_FUNCTION 1 + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_DATA_TYPE_T_PARENT 1 + +/** + * This is a value you can set to ::rb_data_type_struct::dfree. Setting this + * means the data was allocated using ::ruby_xmalloc() (or variants), and shall + * be freed using ::ruby_xfree(). + * + * @warning Do not use this if you want to use system malloc, because the + * system and Ruby might or might not share the same malloc + * implementation. + */ +#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE + +/** + * This is a value you can set to ::rb_data_type_struct::dfree. Setting this + * means the data is managed by someone else, like, statically allocated. Of + * course you are on your own then. + */ +#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE + +/** + * Convenient casting macro. + * + * @param obj An object, which is in fact an ::RTypedData. + * @return The passed object casted to ::RTypedData. + */ +#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj)) + +/** + * Convenient getter macro. + * + * @param v An object, which is in fact an ::RTypedData. + * @return The passed object's ::RTypedData::data field. + */ +#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data) + +/** @old{rb_check_typeddata} */ +#define Check_TypedStruct(v, t) \ + rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t)) + +/** @cond INTERNAL_MACRO */ +#define RTYPEDDATA_P RTYPEDDATA_P +#define RTYPEDDATA_TYPE RTYPEDDATA_TYPE +#define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY +#define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE +#define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED +#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 +/** @endcond */ + +/** + * @private + * + * Bits for rb_data_type_struct::flags. + */ +enum +RBIMPL_ATTR_FLAG_ENUM() +rbimpl_typeddata_flags { + /** + * This flag has something to do with Ruby's global interpreter lock. For + * maximum safety, Ruby locks the entire VM during GC. However your + * callback functions could unintentionally unlock it, for instance when + * they try to flush an IO buffer. Such operations are dangerous (threads + * then run alongside of GC). By default, to prevent those scenario, + * callbacks are deferred until the GC engine is 100% sure threads can run. + * This flag skips that; structs with it are deallocated during the sweep + * phase. + * + * Using this flag needs deep understanding of both GC and threads. You + * would better leave it unspecified. + */ + RUBY_TYPED_FREE_IMMEDIATELY = 1, + + /** + * This flag has something to do with Ractor. Multiple Ractors run without + * protecting each other. Sharing an object among Ractors is basically + * dangerous, disabled by default. This flag is used to bypass that + * restriction. but setting it is not enough. In addition to do so, an + * object also has to be frozen, and be passed to + * rb_ractor_make_shareable() before being actually shareable. Of course, + * you have to manually prevent race conditions then. + * + * Using this flag needs deep understanding of multithreaded programming. + * You would better leave it unspecified. + */ + RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE, + + /** + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This basically works. + * But there is one tweak that has to be exercised. When an elder object + * has reference(s) to younger one(s), that referenced objects must not + * die. In order to detect additions of such references, old generations + * are protected by write barriers. It is a very difficult hack to + * appropriately insert write barriers everywhere. This mechanism is + * disabled by default for 3rd party extensions (they never get aged). By + * specifying this flag you can enable the generational feature to your + * data structure. Of course, you have to manually insert write barriers + * then. + * + * Using this flag needs deep understanding of GC internals, often at the + * level of source code. You would better leave it unspecified. + */ + RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ + + /** + * This flag is mysterious. It seems nobody is currently using it. The + * intention of this flag is also unclear. We need further investigations. + */ + RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */ +}; + +/** + * This is the struct that holds necessary info for a struct. It roughly + * resembles a Ruby level class; multiple objects can share a ::rb_data_type_t + * instance. + */ +typedef struct rb_data_type_struct rb_data_type_t; + +/** @copydoc rb_data_type_t */ +struct rb_data_type_struct { + + /** + * Name of structs of this kind. This is used for diagnostic purposes. + * This has to be unique in the process, but doesn't has to be a valid + * C/Ruby identifier. + */ + const char *wrap_struct_name; + + /** Function pointers. Resembles C++ `vtbl`.*/ + struct { + + /** + * This function is called when the object is experiencing GC marks. + * If it contains references to other Ruby objects, you need to mark + * them also. Otherwise GC will smash your data. + * + * @see rb_gc_mark() + * @warning This is called during GC runs. Object allocations are + * impossible at that moment (that is why GC runs). + */ + RUBY_DATA_FUNC dmark; + + /** + * This function is called when the object is no longer used. You need + * to do whatever necessary to avoid memory leaks. + * + * @warning This is called during GC runs. Object allocations are + * impossible at that moment (that is why GC runs). + */ + RUBY_DATA_FUNC dfree; + + /** + * This function is to query the size of the underlying memory regions. + * + * @internal + * + * This function has only one usage, which is form inside of + * `ext/objspace`. + */ + size_t (*dsize)(const void *); + + /** + * This function is called when the object is relocated. Like + * ::rb_data_type_struct::dmark, you need to update references to Ruby + * objects inside of your structs. + * + * @see rb_gc_location() + * @warning This is called during GC runs. Object allocations are + * impossible at that moment (that is why GC runs). + */ + RUBY_DATA_FUNC dcompact; + + /** + * This field is reserved for future extension. For now, it must be + * filled with zeros. + */ + void *reserved[1]; /* For future extension. + This array *must* be filled with ZERO. */ + } function; + + /** + * Parent of this class. Sometimes C structs have inheritance-like + * relationships. An example is `struct sockaddr` and its family. If you + * design such things, make ::rb_data_type_t for each of them and connect + * using this field. Ruby can then transparently cast your data back and + * forth when you call #TypedData_Get_Struct(). + * + * ```CXX + * struct parent { }; + * static inline const rb_data_type_t parent_type = { + * .wrap_struct_name = "parent", + * }; + * + * struct child: public parent { }; + * static inline const rb_data_type_t child_type = { + * .wrap_struct_name = "child", + * .parent = &parent_type, + * }; + * + * // This function can take both parent_class and child_class. + * static inline struct parent * + * get_parent(VALUE v) + * { + * struct parent *p; + * TypedData_Get_Struct(v, parent_type, struct parent, p); + * return p; + * } + * ``` + */ + const rb_data_type_t *parent; + + /** + * Type-specific static data. This area can be used for any purpose by a + * programmer who define the type. Ruby does not manage this at all. + */ + void *data; /* This area can be used for any purpose + by a programmer who define the type. */ + + /** + * Type-specific behavioural characteristics. This is a bitfield. It is + * an EXTREMELY WISE IDEA to leave this field blank. It is designed so + * that setting zero is the safest thing to do. If you risk to set any + * bits on, you have to know exactly what you are doing. + * + * @internal + * + * Why it has to be a ::VALUE? @shyouhei doesn't understand the design. + */ + VALUE flags; /* RUBY_FL_WB_PROTECTED */ +}; + +/** + * "Typed" user data. By using this, extension libraries can wrap a C struct + * to make it visible from Ruby. For instance if you have a `struct timeval`, + * and you want users to use it, + * + * ```CXX + * static inline const rb_data_type_t timeval_type = { + * // Note that unspecified fields are 0-filled by default. + * .wrap_struct_name = "timeval", + * .function = { + * .dmark = nullptr, // no need to mark + * .dfree = RUBY_TYPED_DEFAULT_FREE, // use ruby_xfree() + * .dsize = [](auto) { + * return sizeof(struct timeval); + * }, + * }, + * }; + * + * extern "C" void + * Init_timeval(void) + * { + * auto klass = rb_define_class("YourName", rb_cObject); + * + * rb_define_alloc_func(klass, [](auto klass) { + * struct timeval *t; + * auto ret = TypedData_Make_Struct( + * klass, struct timeval, &timeval_type, t); + * + * if (auto i = gettimeofday(t, nullptr); i == -1) { + * rb_sys_fail("gettimeofday(3)"); + * } + * else { + * return ret; + * } + * }); + * } + * ``` + */ +struct RTypedData { + + /** The part that all ruby objects have in common. */ + struct RBasic basic; + + /** + * This field stores various information about how Ruby should handle a + * data. This roughly resembles a Ruby level class (apart from method + * definition etc.) + */ + const rb_data_type_t *type; + + /** + * This has to be always 1. + * + * @internal + * + * Why, then, this is not a const ::VALUE? + */ + VALUE typed_flag; + + /** Pointer to the actual C level struct that you want to wrap. */ + void *data; +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NONNULL((3)) +/** + * This is the primitive way to wrap an existing C struct into ::RTypedData. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] datap Pointer to the target C struct. + * @param[in] type The characteristics of the passed data. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return An allocated object that wraps `datap`. + */ +VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type); + +/** + * Identical to rb_data_typed_object_wrap(), except it allocates a new data + * region internally instead of taking an existing one. The allocation is done + * using ruby_calloc(). Hence it makes no sense for `type->function.dfree` to + * be anything other than ::RUBY_TYPED_DEFAULT_FREE. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] size Requested size of memory to allocate. + * @param[in] type The characteristics of the passed data. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return An allocated object that wraps a new `size` byte region. + */ +VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); + +/** + * Checks for the domestic relationship between the two. + * + * @param[in] child A data type supposed to be a child of `parent`. + * @param[in] parent A data type supposed to be a parent of `child`. + * @retval true `child` is a descendent of `parent`. + * @retval false Otherwise. + * + * @internal + * + * You can path NULL to both arguments, don't know what that means though. + */ +int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); + +/** + * Checks if the given object is of given kind. + * + * @param[in] obj An instance of ::RTypedData. + * @param[in] data_type Expected data type of `obj`. + * @retval true `obj` is of `data_type`. + * @retval false Otherwise. + */ +int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); + +/** + * Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead + * of returning false. + * + * @param[in] obj An instance of ::RTypedData. + * @param[in] data_type Expected data type of `obj`. + * @exception rb_eTypeError obj is not of `data_type`. + * @return Unwrapped C struct that `obj` holds. + * @post Upon successful return `obj`'s type is guaranteed `data_type`. + */ +void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type); +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Converts sval, a pointer to your struct, into a Ruby object. + * + * @param klass A ruby level class. + * @param data_type The type of `sval`. + * @param sval A pointer to your struct. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + */ +#define TypedData_Wrap_Struct(klass,data_type,sval)\ + rb_data_typed_object_wrap((klass),(sval),(data_type)) + +/** + * @private + * + * This is an implementation detail of #TypedData_Make_Struct. People don't + * use it directly. + * + * @param result Variable name of created Ruby object. + * @param klass Ruby level class of the object. + * @param type Type name of the C struct. + * @param size Size of the C struct. + * @param data_type The data type describing `type`. + * @param sval Variable name of created C struct. + */ +#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ + VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ + (sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \ + RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) + +/** + * Identical to #TypedData_Wrap_Struct, except it allocates a new data region + * internally instead of taking an existing one. The allocation is done using + * ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to + * be anything other than ::RUBY_TYPED_DEFAULT_FREE. + * + * @param klass Ruby level class of the object. + * @param type Type name of the C struct. + * @param data_type The data type describing `type`. + * @param sval Variable name of created C struct. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + */ +#ifdef HAVE_STMT_AND_DECL_IN_EXPR +#define TypedData_Make_Struct(klass, type, data_type, sval) \ + RB_GNUC_EXTENSION({ \ + TypedData_Make_Struct0( \ + data_struct_obj, \ + klass, \ + type, \ + sizeof(type), \ + data_type, \ + sval); \ + data_struct_obj; \ + }) +#else +#define TypedData_Make_Struct(klass, type, data_type, sval) \ + rb_data_typed_object_make( \ + (klass), \ + (data_type), \ + RBIMPL_CAST((void **)&(sval)), \ + sizeof(type)) +#endif + +/** + * Obtains a C struct from inside of a wrapper Ruby object. + * + * @param obj An instance of ::RTypedData. + * @param type Type name of the C struct. + * @param data_type The data type describing `type`. + * @param sval Variable name of obtained C struct. + * @exception rb_eTypeError `obj` is not a kind of `data_type`. + * @return Unwrapped C struct that `obj` holds. + */ +#define TypedData_Get_Struct(obj,type,data_type,sval) \ + ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implementation detail of Check_Type(). People don't use it + * directly. + * + * @param[in] obj Object in question + * @retval true `obj` is an instance of ::RTypedData. + * @retval false `obj` is an instance of ::RData. + * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. + */ +static inline bool +rbimpl_rtypeddata_p(VALUE obj) +{ + return RTYPEDDATA(obj)->typed_flag == 1; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks whether the passed object is ::RTypedData or ::RData. + * + * @param[in] obj Object in question + * @retval true `obj` is an instance of ::RTypedData. + * @retval false `obj` is an instance of ::RData. + * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. + */ +static inline bool +RTYPEDDATA_P(VALUE obj) +{ +#if RUBY_DEBUG + if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) { + Check_Type(obj, RUBY_T_DATA); + RBIMPL_UNREACHABLE_RETURN(false); + } +#endif + + return rbimpl_rtypeddata_p(obj); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ +/** + * Queries for the type of given object. + * + * @param[in] obj Object in question + * @return Data type struct that corresponds to `obj`. + * @pre `obj` must be an instance of ::RTypedData. + */ +static inline const struct rb_data_type_struct * +RTYPEDDATA_TYPE(VALUE obj) +{ +#if RUBY_DEBUG + if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) { + rb_unexpected_type(obj, RUBY_T_DATA); + RBIMPL_UNREACHABLE_RETURN(NULL); + } +#endif + + return RTYPEDDATA(obj)->type; +} + +/** + * While we don't stop you from using this function, it seems to be an + * implementation detail of #TypedData_Make_Struct, which is preferred over + * this one. + * + * @param[in] klass Ruby level class of the returning object. + * @param[in] type The data type + * @param[out] datap Return pointer. + * @param[in] size Size of the C struct. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eNoMemError Out of memory. + * @return A created Ruby object. + * @post `*datap` points to the C struct wrapped by the returned object. + */ +static inline VALUE +rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size) +{ + TypedData_Make_Struct0(result, klass, void, size, type, *datap); + return result; +} + +RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap")) +/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */ +static inline VALUE +rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) +{ + return rb_data_typed_object_wrap(klass, datap, type); +} + +#endif /* RBIMPL_RTYPEDDATA_H */ diff --git a/ruby/include/ruby/internal/ctype.h b/ruby/include/ruby/internal/ctype.h new file mode 100644 index 000000000..0f7ca6c51 --- /dev/null +++ b/ruby/include/ruby/internal/ctype.h @@ -0,0 +1,545 @@ +#ifndef RBIMPL_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_CTYPE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Our own, locale independent, character handling routines. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" + +/** + * @name Old character classification macros + * + * What is this #ISPRINT business? Well, according to our VCS and some + * internet surfing, it appears that the initial intent of these macros were to + * mimic codes appear in common in several GNU projects. As far as @shyouhei + * detects they seem to originate GNU regex (that standalone one rather than + * Gnulib or Glibc), and at least date back to 1995. + * + * Let me lawfully quote from a GNU coreutils commit + * https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=49803907f5dbd7646184a8912c9db9b09dcd0f22 + * + * > Jim Meyering writes: + * > + * > "... Some ctype macros are valid only for character codes that + * > isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + * > using /bin/cc or gcc but without giving an ansi option). So, all + * > ctype uses should be through macros like ISPRINT... If + * > STDC_HEADERS is defined, then autoconf has verified that the ctype + * > macros don't need to be guarded with references to isascii. ... + * > Defining isascii to 1 should let any compiler worth its salt + * > eliminate the && through constant folding." + * > + * > Bruno Haible adds: + * > + * > "... Furthermore, isupper(c) etc. have an undefined result if c is + * > outside the range -1 <= c <= 255. One is tempted to write isupper(c) + * > with c being of type `char', but this is wrong if c is an 8-bit + * > character >= 128 which gets sign-extended to a negative value. + * > The macro ISUPPER protects against this as well." + * + * So the intent was to reroute old problematic systems that no longer exist. + * At the same time the problems described above no longer hurt us, because we + * decided to completely avoid using system-provided isupper etc. to reinvent + * the wheel. These macros are entirely legacy; please ignore them. + * + * But let me also put stress that GNU people are wise; they use those macros + * only inside of their own implementations and never let them be public. On + * the other hand ruby has thoughtlessly publicised them to 3rd party libraries + * since its beginning, which is a very bad idea. These macros are too easy to + * get conflicted with definitions elsewhere. + * + * New programs should stick to the `rb_` prefixed names. + * + * @note It seems we just mimic the API. We do not share their implementation + * with GPL-ed programs. + * + * @{ + */ +#ifndef ISPRINT +# define ISASCII rb_isascii /**< @old{rb_isascii}*/ +# define ISPRINT rb_isprint /**< @old{rb_isprint}*/ +# define ISGRAPH rb_isgraph /**< @old{rb_isgraph}*/ +# define ISSPACE rb_isspace /**< @old{rb_isspace}*/ +# define ISUPPER rb_isupper /**< @old{rb_isupper}*/ +# define ISLOWER rb_islower /**< @old{rb_islower}*/ +# define ISALNUM rb_isalnum /**< @old{rb_isalnum}*/ +# define ISALPHA rb_isalpha /**< @old{rb_isalpha}*/ +# define ISDIGIT rb_isdigit /**< @old{rb_isdigit}*/ +# define ISXDIGIT rb_isxdigit /**< @old{rb_isxdigit}*/ +# define ISBLANK rb_isblank /**< @old{rb_isblank}*/ +# define ISCNTRL rb_iscntrl /**< @old{rb_iscntrl}*/ +# define ISPUNCT rb_ispunct /**< @old{rb_ispunct}*/ +#endif + +#define TOUPPER rb_toupper /**< @old{rb_toupper}*/ +#define TOLOWER rb_tolower /**< @old{rb_tolower}*/ +#define STRCASECMP st_locale_insensitive_strcasecmp /**< @old{st_locale_insensitive_strcasecmp}*/ +#define STRNCASECMP st_locale_insensitive_strncasecmp /**< @old{st_locale_insensitive_strncasecmp}*/ +#define STRTOUL ruby_strtoul /**< @old{ruby_strtoul}*/ + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** @name locale insensitive functions + * @{ + */ + +/* In descriptions below, `the POSIX Locale` and `the "C" locale` are tactfully + * used as to whether the described function mimics POSIX or C99. */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Our own locale-insensitive version of `strcasecmp(3)`. The "case" here + * always means that of the POSIX Locale. It doesn't depend on runtime locale + * settings. + * + * @param[in] s1 Comparison LHS. + * @param[in] s2 Comparison RHS. + * @retval -1 `s1` is "less" than `s2`. + * @retval 0 Both strings converted into lowercase would be identical. + * @retval 1 `s1` is "greater" than `s2`. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + */ +int st_locale_insensitive_strcasecmp(const char *s1, const char *s2); + +RBIMPL_ATTR_NONNULL(()) +/** + * Our own locale-insensitive version of `strcnasecmp(3)`. The "case" here + * always means that of the POSIX Locale. It doesn't depend on runtime locale + * settings. + * + * @param[in] s1 Comparison LHS. + * @param[in] s2 Comparison RHS. + * @param[in] n Comparison shall stop after first `n` bytes are scanned. + * @retval -1 `s1` is "less" than `s2`. + * @retval 0 Both strings converted into lowercase would be identical. + * @retval 1 `s1` is "greater" than `s2`. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning This function is _not_ timing safe. + */ +int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Our own locale-insensitive version of `strtoul(3)`. The conversion is done + * as if the current locale is set to the "C" locale, no matter actual runtime + * locale settings. + * + * @note This is needed because `strtoul("i", 0, 36)` would return zero + * if it is locale sensitive and the current locale is `tr_TR`. + * @param[in] str String of digits, optionally preceded with whitespaces + * (ignored) and optionally `+` or `-` sign. + * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return). + * @param[in] base `2` to `36` inclusive for each base, or special case + * `0` to detect the base from the contents of the string. + * @return Converted integer, casted to unsigned long. + * @post If `endptr` is not NULL, it is updated to point the first such + * byte where conversion failed. + * @note This function sets `errno` on failure. + * - `EINVAL`: Passed `base` is out of range. + * - `ERANGE`: Converted integer is out of range of `long`. + * @warning As far as @shyouhei reads ISO/IEC 9899:2018 section 7.22.1.4, a + * conforming `strtoul` implementation shall render `ERANGE` + * whenever it finds the input string represents a negative + * integer. Such thing can never be representable using `unsigned + * long`. However this implementation does not honour that + * language. It just casts such negative value to the return + * type, resulting a very big return value. This behaviour is at + * least questionable. But we can no longer change that at this + * point. + * @note Not only does this function works under the "C" locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + */ +unsigned long ruby_strtoul(const char *str, char **endptr, int base); +RBIMPL_SYMBOL_EXPORT_END() + +/* + * We are making the functions below to return `int` instead of `bool`. They + * have been as such since their birth at 5f237d79033b2109afb768bc889611fa9630. + */ + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isascii(3)`. + * + * @param[in] c Byte in question to query. + * @retval false `c` is out of range of ASCII character set. + * @retval true Yes it is. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isascii(int c) +{ + return '\0' <= c && c <= '\x7f'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isupper(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "upper". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isupper(int c) +{ + return 'A' <= c && c <= 'Z'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `islower(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "lower". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_islower(int c) +{ + return 'a' <= c && c <= 'z'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isalpha(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 + * "upper" or "lower". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isalpha(int c) +{ + return rb_isupper(c) || rb_islower(c); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isdigit(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "digit". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isdigit(int c) +{ + return '0' <= c && c <= '9'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isalnum(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 + * "upper", "lower", or "digit". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isalnum(int c) +{ + return rb_isalpha(c) || rb_isdigit(c); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isxdigit(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "xdigit". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isxdigit(int c) +{ + return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isblank(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "blank". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isspace(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "space". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isspace(int c) +{ + return c == ' ' || ('\t' <= c && c <= '\r'); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `iscntrl(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "cntrl". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_iscntrl(int c) +{ + return ('\0' <= c && c < ' ') || c == '\x7f'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to rb_isgraph(), except it also returns true for `' '`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 + * "upper", "lower", "digit", "punct", or a `' '`. + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isprint(int c) +{ + return ' ' <= c && c <= '\x7e'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `ispunct(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "punct". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_ispunct(int c) +{ + return !rb_isalnum(c); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `isgraph(3)`. + * + * @param[in] c Byte in question to query. + * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 + * "upper", "lower", "digit", or "punct". + * @retval false Anything else. + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_isgraph(int c) +{ + return '!' <= c && c <= '\x7e'; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `tolower(3)`. + * + * @param[in] c Byte in question to convert. + * @retval c The byte is not listed in in IEEE 1003.1 section + * 7.3.1.1 "upper". + * @retval otherwise Byte converted using the map defined in IEEE 1003.1 + * section 7.3.1 "tolower". + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_tolower(int c) +{ + return rb_isupper(c) ? (c|0x20) : c; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Our own locale-insensitive version of `toupper(3)`. + * + * @param[in] c Byte in question to convert. + * @retval c The byte is not listed in in IEEE 1003.1 section + * 7.3.1.1 "lower". + * @retval otherwise Byte converted using the map defined in IEEE 1003.1 + * section 7.3.1 "toupper". + * @note Not only does this function works under the POSIX Locale, but + * also assumes its execution character set be what ruby calls an + * ASCII-compatible character set; which does not include for + * instance EBCDIC or UTF-16LE. + * @warning `c` is an int. This means that when you pass a `char` value + * here, it experiences "integer promotion" as defined in ISO/IEC + * 9899:2018 section 6.3.1.1 paragraph 1. + */ +static inline int +rb_toupper(int c) +{ + return rb_islower(c) ? (c&0x5f) : c; +} + +/** @} */ +#endif /* RBIMPL_CTYPE_H */ diff --git a/ruby/include/ruby/internal/dllexport.h b/ruby/include/ruby/internal/dllexport.h new file mode 100644 index 000000000..08a262209 --- /dev/null +++ b/ruby/include/ruby/internal/dllexport.h @@ -0,0 +1,112 @@ +#ifndef RBIMPL_DLLEXPORT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_DLLEXPORT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Tweaking visibility of C variables/functions. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/compiler_is.h" + +/** + * Declaration of externally visible global variables. Here "externally" means + * they should be visible from extension libraries. Depending on operating + * systems (dynamic linkers, to be precise), global variables inside of a DLL + * may or may not be visible form outside of that DLL by default. This + * declaration manually tweaks that default and ensures the declared variable + * be truly globally visible. + * + * ```CXX + * extern VALUE foo; // hidden on some OS + * RUBY_EXTERN VALUE foo; // ensure visible + * ``` + */ +#undef RUBY_EXTERN +#if defined(MJIT_HEADER) && defined(_WIN32) +# define RUBY_EXTERN extern __declspec(dllimport) +#elif defined(RUBY_EXPORT) +# define RUBY_EXTERN extern +#elif defined(_WIN32) +# define RUBY_EXTERN extern __declspec(dllimport) +#else +# define RUBY_EXTERN extern +#endif + +#ifndef RUBY_SYMBOL_EXPORT_BEGIN +# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */ +#endif + +#ifndef RUBY_SYMBOL_EXPORT_END +# define RUBY_SYMBOL_EXPORT_END /* end */ +#endif + +#ifndef RUBY_FUNC_EXPORTED +# define RUBY_FUNC_EXPORTED /* void */ +#endif + +/** + * @cond INTERNAL_MACRO + * + * These MJIT related macros are placed here because translate_mjit_header can + * need them. Extension libraries should not touch. + */ + +/* These macros are used for functions which are exported only for MJIT + and NOT ensured to be exported in future versions. */ + +#if ! defined(MJIT_HEADER) +# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED +#elif ! RBIMPL_COMPILER_IS(MSVC) +# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED +#else +# define MJIT_FUNC_EXPORTED static +#endif + +#define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN +#define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END + +/* On mswin, MJIT header transformation can't be used since cl.exe can't output + preprocessed output preserving macros. So this `MJIT_STATIC` is needed + to force non-static function to static on MJIT header to avoid symbol conflict. */ +#ifdef MJIT_HEADER +# define MJIT_STATIC static +#else +# define MJIT_STATIC +#endif + +/** @endcond */ + +/** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`. + * \@shyouhei finds it handy. */ +#if defined(__DOXYGEN__) +# define RBIMPL_SYMBOL_EXPORT_BEGIN() /* void */ +#elif defined(__cplusplus) +# define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN extern "C" { +#else +# define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN +#endif + +/** Counterpart of #RBIMPL_SYMBOL_EXPORT_BEGIN */ +#if defined(__DOXYGEN__) +# define RBIMPL_SYMBOL_EXPORT_END() /* void */ +#elif defined(__cplusplus) +# define RBIMPL_SYMBOL_EXPORT_END() } RUBY_SYMBOL_EXPORT_END +#else +# define RBIMPL_SYMBOL_EXPORT_END() RUBY_SYMBOL_EXPORT_END +#endif +#endif /* RBIMPL_DLLEXPORT_H */ diff --git a/ruby/include/ruby/internal/dosish.h b/ruby/include/ruby/internal/dosish.h new file mode 100644 index 000000000..7d354ddd1 --- /dev/null +++ b/ruby/include/ruby/internal/dosish.h @@ -0,0 +1,89 @@ +#ifndef RBIMPL_DOSISH_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_DOSISH_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Support for so-called dosish systems. + */ +#ifdef __CYGWIN__ +#undef _WIN32 +#endif + +#if defined(_WIN32) +/* + DOSISH mean MS-Windows style filesystem. + But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP, + ENV_IGNORECASE or CASEFOLD_FILESYSTEM. + */ +#define DOSISH 1 +# define DOSISH_DRIVE_LETTER +#endif + +#ifdef _WIN32 +#include "ruby/win32.h" +#endif + +/** The delimiter of `PATH` environment variable. */ +#if defined(DOSISH) +#define PATH_SEP ";" +#else +#define PATH_SEP ":" +#endif + +/** Identical to #PATH_SEP, except it is of type `char`. */ +#define PATH_SEP_CHAR PATH_SEP[0] + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * For historical interests: there was an operating system called Human68k + * which used an environment variable called `"path"` for this purpose. + */ +#define PATH_ENV "PATH" + +#if defined(DOSISH) +#define ENV_IGNORECASE +#endif + +/** + * Stone age assumption was that an operating system supports only one file + * system at a moment. This macro was to detect if such (one and only) file + * system has case sensitivity. This assumption is largely not true any + * longer; most operating systems can mount many kinds of file systems side by + * side. Also there are file systems that do or do not ignore cases depending + * on configuration (e.g. EXT4's `casefold` feature). + * + * This macro is still used internally (for instance Ruby level constant + * `File::FNM_SYSCASE` depends on it), but it is basically a wrong idea for you + * to use it today. Please just find another way. + */ +#ifndef CASEFOLD_FILESYSTEM +# if defined DOSISH +# define CASEFOLD_FILESYSTEM 1 +# else +# define CASEFOLD_FILESYSTEM 0 +# endif +#endif + +#endif /* RBIMPL_DOSISH_H */ diff --git a/ruby/include/ruby/internal/encoding/coderange.h b/ruby/include/ruby/internal/encoding/coderange.h new file mode 100644 index 000000000..7a81208c9 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/coderange.h @@ -0,0 +1,202 @@ +#ifndef RUBY_INTERNAL_ENCODING_CODERANGE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_CODERANGE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines for code ranges. + */ + +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** What rb_enc_str_coderange() returns. */ +enum ruby_coderange_type { + + /** The object's coderange is unclear yet. */ + RUBY_ENC_CODERANGE_UNKNOWN = 0, + + /** The object holds 0 to 127 inclusive and nothing else. */ + RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8), + + /** The object's encoding and contents are consistent each other */ + RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9), + + /** The object holds invalid/malformed/broken character(s). */ + RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)), + + /** Where the coderange resides. */ + RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT| + RUBY_ENC_CODERANGE_VALID| + RUBY_ENC_CODERANGE_BROKEN) +}; + +RBIMPL_ATTR_CONST() +/** + * @private + * + * This is an implementation detail of #RB_ENC_CODERANGE_CLEAN_P. People don't + * use it directly. + * + * @param[in] cr An enum ::ruby_coderange_type. + * @retval 1 It is. + * @retval 0 It isn't. + */ +static inline int +rb_enc_coderange_clean_p(int cr) +{ + return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT; +} + +RBIMPL_ATTR_CONST() +/** + * Queries if a code range is "clean". "Clean" in this context means it is + * known and valid. + * + * @param[in] cr An enum ::ruby_coderange_type. + * @retval 1 It is. + * @retval 0 It isn't. + */ +static inline bool +RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr) +{ + return rb_enc_coderange_clean_p(cr); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * Queries the (inline) code range of the passed object. The object must be + * capable of having inline encoding. Using this macro needs deep + * understanding of bit level object binary layout. + * + * @param[in] obj Target object. + * @return An enum ::ruby_coderange_type. + */ +static inline enum ruby_coderange_type +RB_ENC_CODERANGE(VALUE obj) +{ + VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENC_CODERANGE_MASK); + + return RBIMPL_CAST((enum ruby_coderange_type)ret); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * Queries the (inline) code range of the passed object is + * ::RUBY_ENC_CODERANGE_7BIT. The object must be capable of having inline + * encoding. Using this macro needs deep understanding of bit level object + * binary layout. + * + * @param[in] obj Target object. + * @retval 1 It is ascii only. + * @retval 0 Otherwise (including cases when the range is not known). + */ +static inline bool +RB_ENC_CODERANGE_ASCIIONLY(VALUE obj) +{ + return RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT; +} + +/** + * Destructively modifies the passed object so that its (inline) code range is + * the passed one. The object must be capable of having inline encoding. + * Using this macro needs deep understanding of bit level object binary layout. + * + * @param[out] obj Target object. + * @param[out] cr An enum ::ruby_coderange_type. + * @post `obj`'s code range is `cr`. + */ +static inline void +RB_ENC_CODERANGE_SET(VALUE obj, enum ruby_coderange_type cr) +{ + RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); + RB_FL_SET_RAW(obj, cr); +} + +/** + * Destructively clears the passed object's (inline) code range. The object + * must be capable of having inline encoding. Using this macro needs deep + * understanding of bit level object binary layout. + * + * @param[out] obj Target object. + * @post `obj`'s code range is ::RUBY_ENC_CODERANGE_UNKNOWN. + */ +static inline void +RB_ENC_CODERANGE_CLEAR(VALUE obj) +{ + RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); +} + +RBIMPL_ATTR_CONST() +/* assumed ASCII compatibility */ +/** + * "Mix" two code ranges into one. This is handy for instance when you + * concatenate two strings into one. Consider one of then is valid but the + * other isn't. The result must be invalid. This macro computes that kind of + * mixture. + * + * @param[in] a An enum ::ruby_coderange_type. + * @param[in] b Another enum ::ruby_coderange_type. + * @return The `a` "and" `b`. + */ +static inline enum ruby_coderange_type +RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b) +{ + if (a == RUBY_ENC_CODERANGE_7BIT) { + return b; + } + else if (a != RUBY_ENC_CODERANGE_VALID) { + return RUBY_ENC_CODERANGE_UNKNOWN; + } + else if (b == RUBY_ENC_CODERANGE_7BIT) { + return RUBY_ENC_CODERANGE_VALID; + } + else { + return b; + } +} + +#define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK /**< @old{RUBY_ENC_CODERANGE_MASK} */ +#define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN /**< @old{RUBY_ENC_CODERANGE_UNKNOWN} */ +#define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT /**< @old{RUBY_ENC_CODERANGE_7BIT} */ +#define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID /**< @old{RUBY_ENC_CODERANGE_VALID} */ +#define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN /**< @old{RUBY_ENC_CODERANGE_BROKEN} */ +#define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) /**< @old{RB_ENC_CODERANGE_CLEAN_P} */ +#define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) /**< @old{RB_ENC_CODERANGE} */ +#define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) /**< @old{RB_ENC_CODERANGE_ASCIIONLY} */ +#define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) /**< @old{RB_ENC_CODERANGE_SET} */ +#define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) /**< @old{RB_ENC_CODERANGE_CLEAR} */ +#define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) /**< @old{RB_ENC_CODERANGE_AND} */ +#define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) /**< @old{RB_ENCODING_CODERANGE_SET} */ + +/** @cond INTERNAL_MACRO */ +#define RB_ENC_CODERANGE RB_ENC_CODERANGE +#define RB_ENC_CODERANGE_AND RB_ENC_CODERANGE_AND +#define RB_ENC_CODERANGE_ASCIIONLY RB_ENC_CODERANGE_ASCIIONLY +#define RB_ENC_CODERANGE_CLEAN_P RB_ENC_CODERANGE_CLEAN_P +#define RB_ENC_CODERANGE_CLEAR RB_ENC_CODERANGE_CLEAR +#define RB_ENC_CODERANGE_SET RB_ENC_CODERANGE_SET +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_CODERANGE_H */ diff --git a/ruby/include/ruby/internal/encoding/ctype.h b/ruby/include/ruby/internal/encoding/ctype.h new file mode 100644 index 000000000..64aaf0a99 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/ctype.h @@ -0,0 +1,243 @@ +#ifndef RUBY_INTERNAL_ENCODING_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_CTYPE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to query chacater types. + */ + +#include "ruby/onigmo.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Queries if the passed pointer points to a newline character. What is a + * newline and what is not depends on the passed encoding. + * + * @param[in] p Pointer to a possibly-middle of a character. + * @param[in] end End of the string. + * @param[in] enc Encoding. + * @retval 0 It isn't. + * @retval otherwise It is. + */ +static inline bool +rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc) +{ + OnigUChar *up = RBIMPL_CAST((OnigUChar *)p); + OnigUChar *ue = RBIMPL_CAST((OnigUChar *)e); + + return ONIGENC_IS_MBC_NEWLINE(enc, up, ue); +} + +/** + * Queries if the passed code point is of passed character type in the passed + * encoding. The "character type" here is a set of macros defined in onigmo.h, + * like `ONIGENC_CTYPE_PUNCT`. + * + * @param[in] c An `OnigCodePoint` value. + * @param[in] t An `OnigCtype` value. + * @param[in] enc A `rb_encoding*` value. + * @retval 1 `c` is of `t` in `enc`. + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_CTYPE(enc, c, t); +} + +/** + * Identical to rb_isascii(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 0 `c` is out of range of ASCII character set in `enc`. + * @retval 1 Otherwise. + * + * @internal + * + * `enc` is ignored. This is at least an intentional implementation detail + * (not a bug). But there could be rooms for future extensions. + */ +static inline bool +rb_enc_isascii(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_ASCII(c); +} + +/** + * Identical to rb_isalpha(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "ALPHA". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_ALPHA(enc, c); +} + +/** + * Identical to rb_islower(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "LOWER". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_islower(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_LOWER(enc, c); +} + +/** + * Identical to rb_isupper(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "UPPER". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isupper(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_UPPER(enc, c); +} + +/** + * Identical to rb_ispunct(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PUNCT". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_PUNCT(enc, c); +} + +/** + * Identical to rb_isalnum(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "ANUM". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_ALNUM(enc, c); +} + +/** + * Identical to rb_isprint(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PRINT". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isprint(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_PRINT(enc, c); +} + +/** + * Identical to rb_isspace(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PRINT". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isspace(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_SPACE(enc, c); +} + +/** + * Identical to rb_isdigit(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "DIGIT". + * @retval 0 Otherwise. + */ +static inline bool +rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc) +{ + return ONIGENC_IS_CODE_DIGIT(enc, c); +} + +RBIMPL_ATTR_CONST() +/** + * Identical to rb_toupper(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @return `c`'s (Ruby's definition of) upper case counterpart. + * + * @internal + * + * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. + */ +int rb_enc_toupper(int c, rb_encoding *enc); + +RBIMPL_ATTR_CONST() +/** + * Identical to rb_tolower(), except it additionally takes an encoding. + * + * @param[in] c A code point. + * @param[in] enc An encoding. + * @return `c`'s (Ruby's definition of) lower case counterpart. + * + * @internal + * + * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. + */ +int rb_enc_tolower(int c, rb_encoding *enc); + +RBIMPL_SYMBOL_EXPORT_END() + +/** @cond INTERNAL_MACRO */ +#define rb_enc_is_newline rb_enc_is_newline +#define rb_enc_isalnum rb_enc_isalnum +#define rb_enc_isalpha rb_enc_isalpha +#define rb_enc_isascii rb_enc_isascii +#define rb_enc_isctype rb_enc_isctype +#define rb_enc_isdigit rb_enc_isdigit +#define rb_enc_islower rb_enc_islower +#define rb_enc_isprint rb_enc_isprint +#define rb_enc_ispunct rb_enc_ispunct +#define rb_enc_isspace rb_enc_isspace +#define rb_enc_isupper rb_enc_isupper +/** @endcond */ + +#endif /* RUBY_INTERNAL_ENCODING_CTYPE_H */ diff --git a/ruby/include/ruby/internal/encoding/encoding.h b/ruby/include/ruby/internal/encoding/encoding.h new file mode 100644 index 000000000..9208d27ec --- /dev/null +++ b/ruby/include/ruby/internal/encoding/encoding.h @@ -0,0 +1,1058 @@ +#ifndef RUBY_INTERNAL_ENCODING_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_ENCODING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines ::rb_encoding + */ + +#include "ruby/oniguruma.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/fl_type.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * `Encoding` class. + * + * @ingroup object + */ +RUBY_EXTERN VALUE rb_cEncoding; + +/** + * @private + * + * Bit constants used when embedding encodings into ::RBasic::flags. Extension + * libraries must not bother such things. + */ +enum ruby_encoding_consts { + + /** Max possible number of embeddable encodings. */ + RUBY_ENCODING_INLINE_MAX = 127, + + /** Where inline encodings reside. */ + RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10), + + /** Bits we use to store inline encodings. */ + RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<> RUBY_ENCODING_SHIFT; + + return RBIMPL_CAST((int)ret); +} + +#define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) /**< @old{RB_ENCODING_SET_INLINED} */ +#define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) /**< @old{RB_ENCODING_SET} */ +#define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) /**< @old{RB_ENCODING_GET_INLINED} */ +#define ENCODING_GET(obj) RB_ENCODING_GET(obj) /**< @old{RB_ENCODING_GET} */ +#define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) /**< @old{RB_ENCODING_IS_ASCII8BIT} */ +#define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN /**< @old{RUBY_ENCODING_MAXNAMELEN} */ + +/** + * The type of encoding. Our design here is we take Oniguruma/Onigmo's + * multilingualisation schema as our base data structure. + */ +typedef const OnigEncodingType rb_encoding; + +RBIMPL_ATTR_NOALIAS() +/** + * Converts a character option to its encoding. It only supports a very + * limited set of Japanese encodings due to its Japanese origin. Ruby still + * has this in-core for backwards compatibility. But new codes must not bother + * such concept like one-character encoding option. Consider deprecated in + * practice. + * + * @param[in] c One of `['n', 'e', 's', 'u', 'i', 'x', 'm']`. + * @param[out] option Return buffer. + * @param[out] kcode Return buffer. + * @retval 1 `c` understood properly. + * @retval 0 `c` is not understood. + * @post `option` is a ::OnigOptionType. + * @post `kcode` is an enum `ruby_preserved_encindex`. + * + * @internal + * + * `kcode` is opaque because `ruby_preserved_encindex` is not visible from + * extension libraries. But who cares? + */ +int rb_char_to_option_kcode(int c, int *option, int *kcode); + +/** + * Creates a new encoding, using the passed one as a template. + * + * @param[in] name Name of the creating encoding. + * @param[in] src Template. + * @exception rb_eArgError Duplicated or malformed `name`. + * @return Replicated new encoding's index. + * @post Encoding named `name` is created as a copy of `src`, whose index + * is the return value. + * + * @internal + * + * `name` can be `NULL`, but that just raises an exception. OTOH it seems no + * sanity check is done against `src`...? + */ +int rb_enc_replicate(const char *name, rb_encoding *src); + +/** + * Creates a new "dummy" encoding. Roughly speaking, an encoding is dummy when + * it is stateful. Notable example of dummy encoding are those defined in + * ISO/IEC 2022 + * + * @param[in] name Name of the creating encoding. + * @exception rb_eArgError Duplicated or malformed `name`. + * @return New dummy encoding's index. + * @post Encoding named `name` is created, whose index is the return + * value. + */ +int rb_define_dummy_encoding(const char *name); + +RBIMPL_ATTR_PURE() +/** + * Queries if the passed encoding is dummy. + * + * @param[in] enc Encoding in question. + * @retval 1 It is. + * @retval 0 It isn't. + */ +int rb_enc_dummy_p(rb_encoding *enc); + +RBIMPL_ATTR_PURE() +/** + * Queries the index of the encoding. An encoding's index is a Ruby-local + * concept. It is a (sequential) number assigned to each encoding. + * + * @param[in] enc Encoding in question. + * @return Its index. + * @note You can pass null pointers to this function. It is equivalent + * to rb_usascii_encindex() then. + */ +int rb_enc_to_index(rb_encoding *enc); + +/** + * Queries the index of the encoding of the passed object, if any. + * + * @param[in] obj Object in question. + * @retval -1 `obj` is incapable of having an encoding. + * @retval otherwise `obj`'s encoding's index. + */ +int rb_enc_get_index(VALUE obj); + +/** + * @alias{rb_enc_get_index} + * + * @internal + * + * Implementation wise this is not a verbatim alias of rb_enc_get_index(). But + * the API is consistent. Don't bother. + */ +static inline int +RB_ENCODING_GET(VALUE obj) +{ + int encindex = RB_ENCODING_GET_INLINED(obj); + + if (encindex == RUBY_ENCODING_INLINE_MAX) { + return rb_enc_get_index(obj); + } + else { + return encindex; + } +} + +/** + * Destructively assigns an encoding (via its index) to an object. + * + * @param[out] obj Object in question. + * @param[in] encindex An encoding index. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eArgError `obj` is incapable of having an encoding. + * @exception rb_eEncodingError `encindex` is out of bounds. + * @exception rb_eLoadError Failed to load the encoding. + */ +void rb_enc_set_index(VALUE obj, int encindex); + +/** @alias{rb_enc_set_index} */ +static inline void +RB_ENCODING_SET(VALUE obj, int encindex) +{ + rb_enc_set_index(obj, encindex); +} + +/** + * This is #RB_ENCODING_SET + RB_ENC_CODERANGE_SET combo. The object must be + * capable of having inline encoding. Using this macro needs deep + * understanding of bit level object binary layout. + * + * @param[out] obj Target object. + * @param[in] encindex Encoding in encindex format. + * @param[in] cr An enum ::ruby_coderange_type. + * @post `obj`'s encoding is `encindex`. + * @post `obj`'s code range is `cr`. + */ +static inline void +RB_ENCODING_CODERANGE_SET(VALUE obj, int encindex, enum ruby_coderange_type cr) +{ + RB_ENCODING_SET(obj, encindex); + RB_ENC_CODERANGE_SET(obj, cr); +} + +RBIMPL_ATTR_PURE() +/** + * Queries if the passed object can have its encoding. + * + * @param[in] obj Object in question. + * @retval 1 It can. + * @retval 0 It cannot. + */ +int rb_enc_capable(VALUE obj); + +/** + * Queries the index of the encoding. + * + * @param[in] name Name of the encoding to find. + * @exception rb_eArgError No such encoding named `name`. + * @retval -1 `name` exists, but unable to load. + * @retval otherwise Index of encoding named `name`. + */ +int rb_enc_find_index(const char *name); + +/** + * Registers an "alias" name. In the wild, an encoding can be called using + * multiple names. For instance an encoding known as `"CP932"` is also called + * `"SJIS"` on occasions. This API registers such relationships. + * + * @param[in] alias New name. + * @param[in] orig Old name. + * @exception rb_eArgError `alias` is duplicated or malformed. + * @retval -1 Failed to load `orig`. + * @retval otherwise The index of `orig` and `alias`. + * @post `alias` is a synonym of `orig`. They refer to the identical + * encoding. + */ +int rb_enc_alias(const char *alias, const char *orig); + +/** + * Obtains a encoding index from a wider range of objects (than + * rb_enc_find_index()). + * + * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. + * @retval -1 `obj` is unexpected type/contents. + * @retval otherwise Index corresponding to `obj`. + */ +int rb_to_encoding_index(VALUE obj); + +/** + * Identical to rb_find_encoding(), except it raises an exception instead of + * returning NULL. + * + * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. + * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. + * @exception rb_eArgError `obj` is an unknown encoding name. + * @return Encoding of `obj`. + */ +rb_encoding *rb_to_encoding(VALUE obj); + +/** + * Identical to rb_to_encoding_index(), except the return type. + * + * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. + * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. + * @retval NULL No such encoding. + * @return otherwise Encoding of `obj`. + */ +rb_encoding *rb_find_encoding(VALUE obj); + +/** + * Identical to rb_enc_get_index(), except the return type. + * + * @param[in] obj Object in question. + * @retval NULL Obj is incapable of having an encoding. + * @retval otherwise `obj`'s encoding. + */ +rb_encoding *rb_enc_get(VALUE obj); + +/** + * Look for the "common" encoding between the two. One character can or cannot + * be expressed depending on an encoding. This function finds the super-set of + * encodings that satisfy contents of both arguments. If that is impossible + * returns NULL. + * + * @param[in] str1 An object. + * @param[in] str2 Another object. + * @retval NULL No encoding can satisfy both at once. + * @retval otherwise Common encoding between the two. + * @note Arguments can be non-string, e.g. Regexp. + */ +rb_encoding *rb_enc_compatible(VALUE str1, VALUE str2); + +/** + * Identical to rb_enc_compatible(), except it raises an exception instead of + * returning NULL. + * + * @param[in] str1 An object. + * @param[in] str2 Another object. + * @exception rb_eEncCompatError No encoding can satisfy both. + * @return Common encoding between the two. + * @note Arguments can be non-string, e.g. Regexp. + */ +rb_encoding *rb_enc_check(VALUE str1,VALUE str2); + +/** + * Identical to rb_enc_set_index(), except it additionally does contents fix-up + * depending on the passed object. It for instance changes the byte length of + * terminating `U+0000` according to the passed encoding. + * + * @param[out] obj Object in question. + * @param[in] encindex An encoding index. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eArgError `obj` is incapable of having an encoding. + * @exception rb_eEncodingError `encindex` is out of bounds. + * @exception rb_eLoadError Failed to load the encoding. + * @return The passed `obj`. + * @post `obj`'s contents might be fixed according to `encindex`. + */ +VALUE rb_enc_associate_index(VALUE obj, int encindex); + +/** + * Identical to rb_enc_associate(), except it takes an encoding itself instead + * of its index. + * + * @param[out] obj Object in question. + * @param[in] enc An encoding. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eArgError `obj` is incapable of having an encoding. + * @return The passed `obj`. + * @post `obj`'s contents might be fixed according to `enc`. + */ +VALUE rb_enc_associate(VALUE obj, rb_encoding *enc); + +/** + * Destructively copies the encoding of the latter object to that of former + * one. It can also be seen as a routine identical to + * rb_enc_associate_index(), except it takes an object's encoding instead of an + * encoding's index. + * + * @param[out] dst Object to modify. + * @param[in] src Object to reference. + * @exception rb_eFrozenError `dst` is frozen. + * @exception rb_eArgError `dst` is incapable of having an encoding. + * @exception rb_eEncodingError `src` is incapable of having an encoding. + * @post `dst`'s encoding is that of `src`'s. + */ +void rb_enc_copy(VALUE dst, VALUE src); + + +/** + * Identical to rb_find_encoding(), except it takes an encoding index instead + * of a Ruby object. + * + * @param[in] idx An encoding index. + * @retval NULL No such encoding. + * @retval otherwise An encoding whose index is `idx`. + */ +rb_encoding *rb_enc_from_index(int idx); + +/** + * Identical to rb_find_encoding(), except it takes a C's string instead of + * Ruby's. + * + * @param[in] name Name of the encoding to query. + * @retval NULL No such encoding. + * @retval otherwise An encoding whose index is `idx`. + */ +rb_encoding *rb_enc_find(const char *name); + +/** + * Queries the (canonical) name of the passed encoding. + * + * @param[in] enc An encoding. + * @return Its name. + */ +static inline const char * +rb_enc_name(rb_encoding *enc) +{ + return enc->name; +} + +/** + * Queries the minimum number of bytes that the passed encoding needs to + * represent a character. For ASCII and compatible encodings this is typically + * 1. There are however encodings whose minimum is not 1; they are + * historically called wide characters. + * + * @param[in] enc An encoding. + * @return Its least possible number of bytes except 0. + */ +static inline int +rb_enc_mbminlen(rb_encoding *enc) +{ + return enc->min_enc_len; +} + +/** + * Queries the maximum number of bytes that the passed encoding needs to + * represent a character. Fixed-width encodings have the same value for this + * one and #rb_enc_mbminlen. However there are variable-width encodings. + * UTF-8, for instance, takes from 1 up to 6 bytes. + * + * @param[in] enc An encoding. + * @return Its maximum possible number of bytes of a character. + */ +static inline int +rb_enc_mbmaxlen(rb_encoding *enc) +{ + return enc->max_enc_len; +} + +/** + * Queries the number of bytes of the character at the passed pointer. + * + * @param[in] p Pointer to a character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] enc Encoding of the string. + * @return If the character at `p` does not end until `e`, number of bytes + * between `p` and `e`. Otherwise the number of bytes that the + * character at `p` is encoded. + * + * @internal + * + * Strictly speaking there are chances when `p` points to a middle byte of a + * wide character. This function returns "the number of bytes from `p` to + * nearest of either `e` or the next character boundary", if you go strict. + */ +int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc); + +/** + * Identical to rb_enc_mbclen() unless the character at `p` overruns `e`. That + * can happen for instance when you read from a socket and its partial read + * cuts a wide character in-between. In those situations this function + * "estimates" theoretical length of the character in question. Typically it + * tends to be possible to know how many bytes a character needs before + * actually reaching its end; for instance UTF-8 encodes a character's length + * in the first byte of it. This function returns that info. + * + * @note This implies that the string is not broken. + * + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] enc Encoding of the string. + * @return Number of bytes of character at `p`, measured or estimated. + */ +int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc); + +/** + * Queries the number of bytes of the character at the passed pointer. This + * function returns 3 different types of information: + * + * ```CXX + * auto n = rb_enc_precise_mbclen(p, q, r); + * + * if (ONIGENC_MBCLEN_CHARFOUND_P(n)) { + * // Character found. Normal return. + * auto found_length = ONIGENC_MBCLEN_CHARFOUND_LEN(n); + * } + * else if (ONIGENC_MBCLEN_NEEDMORE_P(n)) { + * // Character overruns past `q`; needs more. + * auto requested_length = ONIGENC_MBCLEN_NEEDMORE_LEN(n); + * } + * else { + * // `p` is broken. + * assert(ONIGENC_MBCLEN_INVALID_P(n)); + * } + * ``` + * + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] enc Encoding of the string. + * @return Encoded read/needed number of bytes (see above). + */ +int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc); + +#define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_P} */ +#define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_LEN} */ +#define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) /**< @old{ONIGENC_MBCLEN_INVALID_P} */ +#define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_P} */ +#define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_LEN} */ + +/** + * Queries the code point of character pointed by the passed pointer. If that + * code point is included in ASCII that code point is returned. Otherwise -1. + * This can be different from just looking at the first byte. For instance it + * reads 2 bytes in case of UTF-16BE. + * + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] len Return buffer. + * @param[in] enc Encoding of the string. + * @retval -1 The character at `p` is not i ASCII. + * @retval otherwise A code point of the character at `p`. + * @post `len` (if set) is the number of bytes of `p`. + */ +int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc); + +/** + * Queries the code point of character pointed by the passed pointer. + * Exceptions happen in case of broken input. + * + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] len Return buffer. + * @param[in] enc Encoding of the string. + * @exception rb_eArgError `p` is broken. + * @return Code point of the character pointed by `p`. + * @post `len` (if set) is the number of bytes of `p`. + */ +unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc); + +/** + * Queries the code point of character pointed by the passed pointer. + * Exceptions happen in case of broken input. + * + * @deprecated Use rb_enc_codepoint_len() instead. + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] enc Encoding of the string. + * @exception rb_eArgError `p` is broken. + * @return Code point of the character pointed by `p`. + * + * @internal + * + * @matz says in commit 91e5ba1cb865a2385d3e1cbfacd824496898e098 that the line + * below is a "prototype for obsolete function". However even today there + * still are some use cases of it throughout our repository. It seems it has + * its own niche. + */ +static inline unsigned int +rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc) +{ + return rb_enc_codepoint_len(p, e, 0, enc); + /* ^^^ + * This can be `NULL` in C, `nullptr` in C++, and `0` for both. + * We choose the most portable one here. + */ +} + + +/** + * Identical to rb_enc_codepoint(), except it assumes the passed character is + * not broken. + * + * @param[in] p Pointer to the character's first byte. + * @param[in] e End of the string that has `p`. + * @param[in] enc Encoding of the string. + * @return Code point of the character pointed by `p`. + */ +static inline OnigCodePoint +rb_enc_mbc_to_codepoint(const char *p, const char *e, rb_encoding *enc) +{ + const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); + const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); + + return ONIGENC_MBC_TO_CODE(enc, up, ue); +} + +/** + * Queries the number of bytes requested to represent the passed code point + * using the passed encoding. + * + * @param[in] code Code point in question. + * @param[in] enc Encoding to convert the code into a byte sequence. + * @exception rb_eArgError `enc` does not glean `code`. + * @return Number of bytes requested to represent `code` using `enc`. + */ +int rb_enc_codelen(int code, rb_encoding *enc); + +/** + * Identical to rb_enc_codelen(), except it returns 0 for invalid code points. + * + * @param[in] c Code point in question. + * @param[in] enc Encoding to convert `c` into a byte sequence. + * @retval 0 `c` is invalid. + * @return otherwise Number of bytes needed for `enc` to encode `c`. + */ +static inline int +rb_enc_code_to_mbclen(int c, rb_encoding *enc) +{ + OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); + + return ONIGENC_CODE_TO_MBCLEN(enc, uc); +} + +/** + * Identical to rb_enc_uint_chr(), except it writes back to the passed buffer + * instead of allocating one. + * + * @param[in] c Code point. + * @param[out] buf Return buffer. + * @param[in] enc Target encoding scheme. + * @post `c` is encoded according to `enc`, then written to `buf`. + * + * @internal + * + * The second argument must be typed. But its current usages prevent us from + * being any stricter than this. :FIXME: + */ +static inline int +rb_enc_mbcput(unsigned int c, void *buf, rb_encoding *enc) +{ + OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); + OnigUChar *ubuf = RBIMPL_CAST((OnigUChar *)buf); + + return ONIGENC_CODE_TO_MBC(enc, uc, ubuf); +} + +/** + * Queries the previous (left) character. + * + * @param[in] s Start of the string. + * @param[in] p Pointer to a character. + * @param[in] e End of the string. + * @param[in] enc Encoding. + * @retval NULL No previous character. + * @retval otherwise Pointer to the head of the previous character. + */ +static inline char * +rb_enc_prev_char(const char *s, const char *p, const char *e, rb_encoding *enc) +{ + const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); + const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); + const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); + OnigUChar *ur = onigenc_get_prev_char_head(enc, us, up, ue); + + return RBIMPL_CAST((char *)ur); +} + +/** + * Queries the left boundary of a character. This function takes a pointer + * that is not necessarily a head of a character, and searches for its head. + * + * @param[in] s Start of the string. + * @param[in] p Pointer to a possibly-middle of a character. + * @param[in] e End of the string. + * @param[in] enc Encoding. + * @return Pointer to the head of the character that contains `p`. + */ +static inline char * +rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) +{ + const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); + const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); + const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); + OnigUChar *ur = onigenc_get_left_adjust_char_head(enc, us, up, ue); + + return RBIMPL_CAST((char *)ur); +} + +/** + * Queries the right boundary of a character. This function takes a pointer + * that is not necessarily a head of a character, and searches for its tail. + * + * @param[in] s Start of the string. + * @param[in] p Pointer to a possibly-middle of a character. + * @param[in] e End of the string. + * @param[in] enc Encoding. + * @return Pointer to the end of the character that contains `p`. + */ +static inline char * +rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) +{ + const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); + const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); + const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); + OnigUChar *ur = onigenc_get_right_adjust_char_head(enc, us, up, ue); + + return RBIMPL_CAST((char *)ur); +} + +/** + * Scans the string backwards for n characters. + * + * @param[in] s Start of the string. + * @param[in] p Pointer to a character. + * @param[in] e End of the string. + * @param[in] n Steps. + * @param[in] enc Encoding. + * @retval NULL There are no `n` characters left. + * @retval otherwise Pointer to `n` character before `p`. + */ +static inline char * +rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc) +{ + const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); + const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); + const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); + const OnigUChar *ur = onigenc_step_back(enc, us, up, ue, n); + + return RBIMPL_CAST((char *)ur); +} + +/** + * @private + * + * This is an implementation detail of rb_enc_asciicompat(). People don't use + * it directly. Just always use rb_enc_asciicompat(). + * + * @param[in] enc Encoding in question. + * @retval 1 It is ASCII compatible. + * @retval 0 It isn't. + */ +static inline int +rb_enc_asciicompat_inline(rb_encoding *enc) +{ + return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc); +} + +/** + * Queries if the passed encoding is _in some sense_ compatible with ASCII. + * The concept of ASCII compatibility is nuanced, and private to our + * implementation. For instance SJIS is ASCII compatible to us, despite their + * having different characters at code point `0x5C`. This is based on some + * practical consideration that Japanese people confuses SJIS to be "upper + * compatible" with ASCII (which is in fact a wrong idea, but we just don't go + * strict here). An example of ASCII incompatible encoding is UTF-16. UTF-16 + * shares code points with ASCII, but employs a completely different encoding + * scheme. + * + * @param[in] enc Encoding in question. + * @retval 0 It is incompatible. + * @retval 1 It is compatible. + */ +static inline bool +rb_enc_asciicompat(rb_encoding *enc) +{ + if (rb_enc_mbminlen(enc) != 1) { + return false; + } + else if (rb_enc_dummy_p(enc)) { + return false; + } + else { + return true; + } +} + +/** + * Queries if the passed string is in an ASCII-compatible encoding. + * + * @param[in] str A Ruby's string to query. + * @retval 0 `str` is not a String, or an ASCII-incompatible string. + * @retval 1 Otherwise. + */ +static inline bool +rb_enc_str_asciicompat_p(VALUE str) +{ + rb_encoding *enc = rb_enc_get(str); + + return rb_enc_asciicompat(enc); +} + +/** + * Queries the Ruby-level counterpart instance of ::rb_cEncoding that + * corresponds to the passed encoding. + * + * @param[in] enc An encoding + * @retval RUBY_Qnil `enc` is a null pointer. + * @retval otherwise An instance of ::rb_cEncoding. + */ +VALUE rb_enc_from_encoding(rb_encoding *enc); + +RBIMPL_ATTR_PURE() +/** + * Queries if the passed encoding is either one of UTF-8/16/32. + * + * @note It does not take UTF-7, which we actually support, into account. + * + * @param[in] enc Encoding in question. + * @retval 0 It is not a Unicode variant. + * @retval otherwise It is. + * + * @internal + * + * In reality it returns 1/0, but the value is abstracted as + * `ONIGENC_FLAG_UNICODE`. + */ +int rb_enc_unicode_p(rb_encoding *enc); + +RBIMPL_ATTR_RETURNS_NONNULL() +/** + * Queries the encoding that represents ASCII-8BIT a.k.a. binary. + * + * @return The encoding that represents ASCII-8BIT. + * + * @internal + * + * This can not return NULL once the process properly boots up. + */ +rb_encoding *rb_ascii8bit_encoding(void); + +RBIMPL_ATTR_RETURNS_NONNULL() +/** + * Queries the encoding that represents UTF-8. + * + * @return The encoding that represents UTF-8. + * + * @internal + * + * This can not return NULL once the process properly boots up. + */ +rb_encoding *rb_utf8_encoding(void); + +RBIMPL_ATTR_RETURNS_NONNULL() +/** + * Queries the encoding that represents US-ASCII. + * + * @return The encoding that represents US-ASCII. + * + * @internal + * + * This can not return NULL once the process properly boots up. + */ +rb_encoding *rb_usascii_encoding(void); + +/** + * Queries the encoding that represents the current locale. + * + * @return The encoding that represents the process' locale. + * + * @internal + * + * This is dynamic. If you change the process' locale by e.g. calling + * `setlocale(3)`, that should also change the return value of this function. + * + * There is no official way for Ruby scripts to manipulate locales, though. + */ +rb_encoding *rb_locale_encoding(void); + +/** + * Queries the "filesystem" encoding. This is the encoding that ruby expects + * info from the OS' file system are in. This affects for instance return + * value of rb_dir_getwd(). Most notably on Windows it can be an alias of OS + * codepage. Most notably on Linux users can set this via default external + * encoding. + * + * @return The "filesystem" encoding. + */ +rb_encoding *rb_filesystem_encoding(void); + +/** + * Queries the "default external" encoding. This is used to interact with + * outer-process things such as File. Though not recommended, you can set this + * using rb_enc_set_default_external(). + * + * @return The "default external" encoding. + */ +rb_encoding *rb_default_external_encoding(void); + +/** + * Queries the "default internal" encoding. This could be a null pointer. + * Otherwise, outer-process info are transcoded from default external encoding + * to this one during reading from an IO. + * + * @return The "default internal" encoding (if any). + */ +rb_encoding *rb_default_internal_encoding(void); + +#ifndef rb_ascii8bit_encindex +RBIMPL_ATTR_CONST() +/** + * Identical to rb_ascii8bit_encoding(), except it returns the encoding's index + * instead of the encoding itself. + * + * @return The index of encoding of ASCII-8BIT. + * + * @internal + * + * This happens to be 0. + */ +int rb_ascii8bit_encindex(void); +#endif + +/** + * Queries if the passed object is in ascii 8bit (== binary) encoding. The + * object must be capable of having inline encoding. Using this macro needs + * deep understanding of bit level object binary layout. + * + * @param[in] obj An object to check. + * @retval 1 It is. + * @retval 0 It isn't. + */ +static inline bool +RB_ENCODING_IS_ASCII8BIT(VALUE obj) +{ + return RB_ENCODING_GET_INLINED(obj) == rb_ascii8bit_encindex(); +} + +#ifndef rb_utf8_encindex +RBIMPL_ATTR_CONST() +/** + * Identical to rb_utf8_encoding(), except it returns the encoding's index + * instead of the encoding itself. + * + * @return The index of encoding of UTF-8. + */ +int rb_utf8_encindex(void); +#endif + +#ifndef rb_usascii_encindex +RBIMPL_ATTR_CONST() +/** + * Identical to rb_usascii_encoding(), except it returns the encoding's index + * instead of the encoding itself. + * + * @return The index of encoding of UTF-8. + */ +int rb_usascii_encindex(void); +#endif + +/** + * Identical to rb_locale_encoding(), except it returns the encoding's index + * instead of the encoding itself. + * + * @return The index of the locale encoding. + */ +int rb_locale_encindex(void); + +/** + * Identical to rb_filesystem_encoding(), except it returns the encoding's + * index instead of the encoding itself. + * + * @return The index of the filesystem encoding. + */ +int rb_filesystem_encindex(void); + +/** + * Identical to rb_default_external_encoding(), except it returns the + * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the + * default external encoding. + * + * @return An instance of ::rb_cEncoding of default external. + */ +VALUE rb_enc_default_external(void); + +/** + * Identical to rb_default_internal_encoding(), except it returns the + * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the + * default internal encoding. + * + * @return An instance of ::rb_cEncoding of default internal. + */ +VALUE rb_enc_default_internal(void); + +/** + * Destructively assigns the passed encoding as the default external encoding. + * You should not use this API. It has process-global side effects. Also it + * doesn't change encodings of strings that have already been read. + * + * @param[in] encoding Ruby level encoding. + * @exception rb_eArgError `encoding` is ::RUBY_Qnil. + * @post The default external encoding is `encoding`. + */ +void rb_enc_set_default_external(VALUE encoding); + +/** + * Destructively assigns the passed encoding as the default internal encoding. + * You should not use this API. It has process-global side effects. Also it + * doesn't change encodings of strings that have already been read. + * + * @param[in] encoding Ruby level encoding. + * @post The default internal encoding is `encoding`. + * @note Unlike rb_enc_set_default_external() you can pass ::RUBY_Qnil. + */ +void rb_enc_set_default_internal(VALUE encoding); + +/** + * Returns a platform-depended "charmap" of the current locale. This + * information is called a "Codeset name" in IEEE 1003.1 section 13 + * (``). This is a very low-level API. The return value can have + * no corresponding encoding when passed to rb_find_encoding(). + * + * @param[in] klass Ignored for no reason (why...) + * @return The low-level locale charmap, in Ruby's String. + */ +VALUE rb_locale_charmap(VALUE klass); + +RBIMPL_SYMBOL_EXPORT_END() + +/** @cond INTERNAL_MACRO */ +#define RB_ENCODING_GET RB_ENCODING_GET +#define RB_ENCODING_GET_INLINED RB_ENCODING_GET_INLINED +#define RB_ENCODING_IS_ASCII8BIT RB_ENCODING_IS_ASCII8BIT +#define RB_ENCODING_SET RB_ENCODING_SET +#define RB_ENCODING_SET_INLINED RB_ENCODING_SET_INLINED +#define rb_enc_asciicompat rb_enc_asciicompat +#define rb_enc_code_to_mbclen rb_enc_code_to_mbclen +#define rb_enc_codepoint rb_enc_codepoint +#define rb_enc_left_char_head rb_enc_left_char_head +#define rb_enc_mbc_to_codepoint rb_enc_mbc_to_codepoint +#define rb_enc_mbcput rb_enc_mbcput +#define rb_enc_mbmaxlen rb_enc_mbmaxlen +#define rb_enc_mbminlen rb_enc_mbminlen +#define rb_enc_name rb_enc_name +#define rb_enc_prev_char rb_enc_prev_char +#define rb_enc_right_char_head rb_enc_right_char_head +#define rb_enc_step_back rb_enc_step_back +#define rb_enc_str_asciicompat_p rb_enc_str_asciicompat_p +/** @endcond */ + +#endif /* RUBY_INTERNAL_ENCODING_ENCODING_H */ diff --git a/ruby/include/ruby/internal/encoding/pathname.h b/ruby/include/ruby/internal/encoding/pathname.h new file mode 100644 index 000000000..0b5e85a52 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/pathname.h @@ -0,0 +1,184 @@ +#ifndef RUBY_INTERNAL_ENCODING_PATHNAME_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_PATHNAME_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate encodings of pathnames. + */ + +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NONNULL(()) +/** + * Returns a path component directly adjacent to the passed pointer. + * + * ``` + * "/multi/byte/encoded/pathname.txt" + * ^ ^ ^ + * | | +--- end + * | +--- @return + * +--- path + * ``` + * + * @param[in] path Where to start scanning. + * @param[in] end End of the path string. + * @param[in] enc Encoding of the string. + * @return A pointer in the passed string where the next path component + * resides, or `end` if there is no next path component. + */ +char *rb_enc_path_next(const char *path, const char *end, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL(()) +/** + * Seeks for non-prefix part of a pathname. This can be a no-op when the OS + * has no such concept like a path prefix. But there are OSes where path + * prefixes do exist. + * + * ``` + * "C:\multi\byte\encoded\pathname.txt" + * ^ ^ ^ + * | | +--- end + * | +--- @return + * +--- path + * ``` + * + * @param[in] path Where to start scanning. + * @param[in] end End of the path string. + * @param[in] enc Encoding of the string. + * @return A pointer in the passed string where non-prefix part starts, or + * `path` if the OS does not have path prefix. + */ +char *rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL(()) +/** + * Returns the last path component. + * + * ``` + * "/multi/byte/encoded/pathname.txt" + * ^ ^ ^ + * | | +--- end + * | +--- @return + * +--- path + * ``` + * + * @param[in] path Where to start scanning. + * @param[in] end End of the path string. + * @param[in] enc Encoding of the string. + * @return A pointer in the passed string where the last path component + * resides, or `end` if there is no more path component. + */ +char *rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL(()) +/** + * This just returns the passed end basically. It makes difference in case the + * passed string ends with tons of path separators like the following: + * + * ``` + * "/path/that/ends/with/lots/of/slashes//////////////" + * ^ ^ ^ + * | | +--- end + * | +--- @return + * +--- path + * ``` + * + * @param[in] path Where to start scanning. + * @param[in] end End of the path string. + * @param[in] enc Encoding of the string. + * @return A pointer in the passed string where the trailing path + * separators start, or `end` if there is no trailing path + * separators. + * + * @internal + * + * It seems this function was introduced to mimic what POSIX says about + * `basename(3)`. + */ +char *rb_enc_path_end(const char *path, const char *end, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL((1, 4)) +/** + * Our own encoding-aware version of `basename(3)`. Normally, this function + * returns the last path component of the given name. However in case the + * passed name ends with a path separator, it returns the name of the + * directory, not the last (empty) component. Also if the passed name is a + * root directory, it returns that root directory. Note however that Windows + * filesystem have drive letters, which this function does not return. + * + * @param[in] name Target path. + * @param[out] baselen Return buffer. + * @param[in,out] alllen Number of bytes of `name`. + * @param[enc] enc Encoding of `name`. + * @return The rightmost component of `name`. + * @post `baselen`, if passed, is updated to be the number of bytes + * of the returned basename. + * @post `alllen`, if passed, is updated to be the number of bytes of + * strings not considered as the basename. + */ +const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL((1, 3)) +/** + * Our own encoding-aware version of `extname`. This function first applies + * rb_enc_path_last_separator() to the passed name and only concerns its return + * value (ignores any parent directories). This function returns complicated + * results: + * + * ```CXX + * auto path = "..."; + * auto len = strlen(path); + * auto ret = ruby_enc_find_extname(path, &len, rb_ascii8bit_encoding()); + * + * switch(len) { + * case 0: + * if (ret == 0) { + * // `path` is a file without extensions. + * } + * else { + * // `path` is a dotfile. + * // `ret` is the file's name. + * } + * break; + * + * case 1: + * // `path` _ends_ with a dot. + * // `ret` is that dot. + * break; + * + * default: + * // `path` has an extension. + * // `ret` is that extension. + * } + * ``` + * + * @param[in] name Target path. + * @param[in,out] len Number of bytes of `name`. + * @param[in] enc Encoding of `name`. + * @return See above. + * @post `len`, if passed, is updated (see above). + */ +const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_PATHNAME_H */ diff --git a/ruby/include/ruby/internal/encoding/re.h b/ruby/include/ruby/internal/encoding/re.h new file mode 100644 index 000000000..d0de23bc8 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/re.h @@ -0,0 +1,46 @@ +#ifndef RUBY_INTERNAL_ENCODING_RE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_RE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate encodings of symbols. + */ + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Identical to rb_reg_new(), except it additionally takes an encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @param[in] enc Encoding of `ptr`. + * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. + * @exception rb_eRegexpError Failed to compile `ptr`. + * @return An allocated new instance of ::rb_cRegexp, of `enc` encoding, + * whose expression is compiled according to `ptr`. + */ +VALUE rb_enc_reg_new(const char *ptr, long len, rb_encoding *enc, int opts); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_RE_H */ diff --git a/ruby/include/ruby/internal/encoding/sprintf.h b/ruby/include/ruby/internal/encoding/sprintf.h new file mode 100644 index 000000000..cb8737b41 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/sprintf.h @@ -0,0 +1,78 @@ +#ifndef RUBY_INTERNAL_ENCODING_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_SPRINTF_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate encodings of symbols. + */ +#include "ruby/internal/config.h" +#include +#include "ruby/internal/attr/format.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_sprintf(), except it additionally takes an encoding. The + * passed encoding rules both the incoming format specifier and the resulting + * string. + * + * @param[in] enc Encoding of `fmt`. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ... Variadic number of contents to format. + * @return A rendered new instance of ::rb_cString, of `enc` encoding. + */ +VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) +/** + * Identical to rb_enc_sprintf(), except it takes a `va_list` instead of + * variadic arguments. It can also be seen as a routine identical to + * rb_vsprintf(), except it additionally takes an encoding. + * + * @param[in] enc Encoding of `fmt`. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ap Contents to format. + * @return A rendered new instance of ::rb_cString, of `enc` encoding. + */ +VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((3)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) +/** + * Identical to rb_raise(), except it additionally takes an encoding. + * + * @param[in] enc Encoding of the generating exception. + * @param[in] exc A subclass of ::rb_eException. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @param[in] ... Contents of the message. + * @exception exc The specified exception. + * @note It never returns. + */ +void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_SPRINTF_H */ diff --git a/ruby/include/ruby/internal/encoding/string.h b/ruby/include/ruby/internal/encoding/string.h new file mode 100644 index 000000000..6ed7ca1c9 --- /dev/null +++ b/ruby/include/ruby/internal/encoding/string.h @@ -0,0 +1,346 @@ +#ifndef RUBY_INTERNAL_ENCODING_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_STRING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate encodings of strings. + */ + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/intern/string.h" /* rbimpl_strlen */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Identical to rb_enc_str_new(), except it additionally takes an encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of `enc` + * encoding, whose contents are verbatim copy of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + * @note `enc` can be a null pointer. It can also be seen as a routine + * identical to rb_usascii_str_new() then. + */ +VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_enc_str_new(), except it assumes the passed pointer is a + * pointer to a C string. It can also be seen as a routine identical to + * rb_str_new_cstr(), except it additionally takes an encoding. + * + * @param[in] ptr A C string. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of `enc` encoding, whose contents + * are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + * @pre Because `ptr` is a C string it makes no sense for `enc` to be + * something like UTF-32. + * @note `enc` can be a null pointer. It can also be seen as a routine + * identical to rb_usascii_str_new_cstr() then. + */ +VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc); + +/** + * Identical to rb_enc_str_new(), except it takes a C string literal. It can + * also be seen as a routine identical to rb_str_new_static(), except it + * additionally takes an encoding. + * + * @param[in] ptr A C string literal. + * @param[in] len `strlen(ptr)`. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eArgError `len` out of range of `size_t`. + * @pre `ptr` must be a C string constant. + * @return An instance of ::rb_cString, of `enc` encoding, whose backend + * storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + * @note `enc` can be a null pointer. It can also be seen as a routine + * identical to rb_usascii_str_new_static() then. + */ +VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc); + +/** + * Identical to rb_enc_str_new(), except it returns a "f"string. It can also + * be seen as a routine identical to rb_interned_str(), except it additionally + * takes an encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eArgError `len` is negative. + * @return A found or created instance of ::rb_cString, of `len` bytes + * length, of `enc` encoding, whose contents are identical to that + * of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + * @note `enc` can be a null pointer. + */ +VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_enc_str_new_cstr(), except it returns a "f"string. It can + * also be seen as a routine identical to rb_interned_str_cstr(), except it + * additionally takes an encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] enc Encoding of `ptr`. + * @return A found or created instance of ::rb_cString of `enc` encoding, + * whose contents are identical to that of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + * @note `enc` can be a null pointer. + */ +VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc); + +/** + * Counts the number of characters of the passed string, according to the + * passed encoding. This has to be complicated. The passed string could be + * invalid and/or broken. This routine would scan from the beginning til the + * end, byte by byte, to seek out character boundaries. Could be super slow. + * + * @param[in] head Leftmost pointer to the string. + * @param[in] tail Rightmost pointer to the string. + * @param[in] enc Encoding of the string. + * @return Number of characters exist in `head` .. `tail`. The definition + * of "character" depends on the passed `enc`. + */ +long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc); + +/** + * Queries the n-th character. Like rb_enc_strlen() this function can be fast + * or slow depending on the contents. Don't expect characters to be uniformly + * distributed across the entire string. + * + * @param[in] head Leftmost pointer to the string. + * @param[in] tail Rightmost pointer to the string. + * @param[in] nth Requested index of characters. + * @param[in] enc Encoding of the string. + * @return Pointer to the first byte of the character that is `nth` + * character ahead of `head`, or `tail` if there is no such + * character (OOB etc). The definition of "character" depends on + * the passed `enc`. + */ +char *rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc); + +/** + * Identical to rb_enc_get_index(), except the return type. + * + * @param[in] obj Object in question. + * @exception rb_eTypeError `obj` is incapable of having an encoding. + * @return `obj`'s encoding. + */ +VALUE rb_obj_encoding(VALUE obj); + +/** + * Identical to rb_str_cat(), except it additionally takes an encoding. + * + * @param[out] str Destination object. + * @param[in] ptr Contents to append. + * @param[in] len Length of `src`, in bytes. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eArgError `len` is negative. + * @exception rb_eEncCompatError `enc` is not compatible with `str`. + * @return The passed `dst`. + * @post The contents of `ptr` is copied, transcoded into `dst`'s + * encoding, then pasted into `dst`'s end. + */ +VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc); + +/** + * Encodes the passed code point into a series of bytes. + * + * @param[in] code Code point. + * @param[in] enc Target encoding scheme. + * @exception rb_eRangeError `enc` does not glean `code`. + * @return An instance of ::rb_cString, of `enc` encoding, whose sole + * contents is `code` represented in `enc`. + * @note No way to encode code points bigger than UINT_MAX. + * + * @internal + * + * In other languages, APIs like this one could be seen as the primitive + * routines where encodings' "encode" feature are implemented. However in case + * of Ruby this is not the primitive one. We directly manipulate encoded + * strings. Encoding conversion routines transcode an encoded string directly + * to another one; not via a code point array. + */ +VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc); + +/** + * Identical to rb_external_str_new(), except it additionally takes an + * encoding. However the whole point of rb_external_str_new() is to encode a + * string into default external encoding. Being able to specify arbitrary + * encoding just ruins the designed purpose the function meseems. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @param[in] enc Target encoding scheme. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to `enc` is fully defined over the given + * contents, then the return value is a string of `enc` encoding, + * whose contents are the converted ones. Otherwise the string is + * a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * + * @internal + * + * @shyouhei has no idea why this one does not follow the naming convention + * that others obey. It seems to him that this should have been called + * `rb_enc_external_str_new`. + */ +VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc); + +/** + * Identical to rb_str_export(), except it additionally takes an encoding. + * + * @param[in] obj Target object. + * @param[in] enc Target encoding. + * @exception rb_eTypeError No implicit conversion to String. + * @return Converted ruby string of `enc` encoding. + */ +VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc); + +/** + * Encoding conversion main routine. + * + * @param[in] str String to convert. + * @param[in] from Source encoding. + * @param[in] to Destination encoding. + * @return A copy of `str`, with conversion from `from` to `to` applied. + * @note `from` can be a null pointer. `str`'s encoding is taken then. + * @note `to` can be a null pointer. No-op then. + */ +VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to); + +/** + * Identical to rb_str_conv_enc(), except it additionally takes IO encoder + * options. The extra arguments can be constructed using io_extract_modeenc() + * etc. + * + * @param[in] str String to convert. + * @param[in] from Source encoding. + * @param[in] to Destination encoding. + * @param[in] ecflags A set of enum ::ruby_econv_flag_type. + * @param[in] ecopts Optional hash. + * @return A copy of `str`, with conversion from `from` to `to` applied. + * @note `from` can be a null pointer. `str`'s encoding is taken then. + * @note `to` can be a null pointer. No-op then. + * @note `ecopts` can be ::RUBY_Qnil, which is equivalent to passing an + * empty hash. + */ +VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); + +/** + * Scans the passed string to collect its code range. Because a Ruby's string + * is mutable, its contents change from time to time; so does its code range. + * A long-lived string tends to fall back to ::RUBY_ENC_CODERANGE_UNKNOWN. + * This API scans it and re-assigns a fine-grained code range constant. + * + * @param[out] str A string. + * @return An enum ::ruby_coderange_type. + */ +int rb_enc_str_coderange(VALUE str); + +/** + * Scans the passed string until it finds something odd. Returns the number of + * bytes scanned. As the name implies this is suitable for repeated call. One + * of its application is `IO#readlines`. The method reads from its receiver's + * read buffer, maybe more than once, looking for newlines. But "newline" can + * be different among encodings. This API is used to detect broken contents to + * properly mark them as such. + * + * @param[in] str String to scan. + * @param[in] end End of `str`. + * @param[in] enc `str`'s encoding. + * @param[out] cr Return buffer. + * @return Distance between `str` and first such byte where broken. + * @post `cr` has the code range type. + */ +long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr); + +/** + * Queries if the passed string is "ASCII only". An ASCII only string is a + * string who doesn't have any non-ASCII characters at all. This doesn't + * necessarily mean the string is in ASCII encoding. For instance a String of + * CP932 encoding can quite much be ASCII only, depending on its contents. + * + * @param[in] str String in question. + * @retval 1 It doesn't have non-ASCII characters. + * @retval 0 It has characters that are out of ASCII. + */ +int rb_enc_str_asciionly_p(VALUE str); + +RBIMPL_ATTR_NONNULL(()) +/** + * Looks for the passed string in the passed buffer. + * + * @param[in] x Buffer that potentially includes `y`. + * @param[in] m Number of bytes of `x`. + * @param[in] y Query string. + * @param[in] n Number of bytes of `y`. + * @param[in] enc Encoding of both `x` and `y`. + * @retval -1 Not found. + * @retval otherwise Found index in `x`. + * @note This API can match at a non-character-boundary. + */ +long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc); + +/** @cond INTERNAL_MACRO */ +RBIMPL_ATTR_NONNULL(()) +static inline VALUE +rbimpl_enc_str_new_cstr(const char *str, rb_encoding *enc) +{ + long len = rbimpl_strlen(str); + + return rb_enc_str_new_static(str, len, enc); +} + +#define rb_enc_str_new(str, len, enc) \ + ((RBIMPL_CONSTANT_P(str) && \ + RBIMPL_CONSTANT_P(len) ? \ + rb_enc_str_new_static: \ + rb_enc_str_new) ((str), (len), (enc))) + +#define rb_enc_str_new_cstr(str, enc) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_enc_str_new_cstr : \ + rb_enc_str_new_cstr) ((str), (enc))) + +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_STRING_H */ diff --git a/ruby/include/ruby/internal/encoding/symbol.h b/ruby/include/ruby/internal/encoding/symbol.h new file mode 100644 index 000000000..9cd1b0dbf --- /dev/null +++ b/ruby/include/ruby/internal/encoding/symbol.h @@ -0,0 +1,100 @@ +#ifndef RUBY_INTERNAL_ENCODING_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_SYMBOL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Routines to manipulate encodings of symbols. + */ + +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/encoding.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Identical to rb_intern2(), except it additionally takes an encoding. + * + * @param[in] name The name of the id. + * @param[in] len Length of `name`. + * @param[in] enc `name`'s encoding. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given name. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become static ones; i.e. would never be garbage collected. It + * is up to you to avoid memory leaks. Think twice before using + * it. + */ +ID rb_intern3(const char *name, long len, rb_encoding *enc); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_symname_p(), except it additionally takes an encoding. + * + * @param[in] str A C string to check. + * @param[in] enc `str`'s encoding. + * @retval 1 It is a valid symbol name. + * @retval 0 It is invalid as a symbol name. + */ +int rb_enc_symname_p(const char *str, rb_encoding *enc); + +/** + * Identical to rb_enc_symname_p(), except it additionally takes the passed + * string's length. This is needed for strings containing NUL bytes, like in + * case of UTF-32. + * + * @param[in] name A C string to check. + * @param[in] len Number of bytes of `str`. + * @param[in] enc `str`'s encoding. + * @retval 1 It is a valid symbol name. + * @retval 0 It is invalid as a symbol name. + */ +int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc); + +/** + * Identical to rb_check_id(), except it takes a pointer to a memory region + * instead of Ruby's string. + * + * @param[in] ptr A pointer to a memory region. + * @param[in] len Number of bytes of `ptr`. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. + * @retval 0 No such id ever existed in the history. + * @retval otherwise The id that represents the given name. + */ +ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc); + +/** + * Identical to rb_check_id_cstr(), except for the return type. It can also be + * seen as a routine identical to rb_check_symbol(), except it takes a pointer + * to a memory region instead of Ruby's string. + * + * @param[in] ptr A pointer to a memory region. + * @param[in] len Number of bytes of `ptr`. + * @param[in] enc Encoding of `ptr`. + * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. + * @retval RUBY_Qnil No such id ever existed in the history. + * @retval otherwise The id that represents the given name. + */ +VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_SYMBOL_H */ diff --git a/ruby/include/ruby/internal/encoding/transcode.h b/ruby/include/ruby/internal/encoding/transcode.h new file mode 100644 index 000000000..60c96a41c --- /dev/null +++ b/ruby/include/ruby/internal/encoding/transcode.h @@ -0,0 +1,558 @@ +#ifndef RUBY_INTERNAL_ENCODING_TRANSCODE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_INTERNAL_ENCODING_TRANSCODE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief econv stuff + */ + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** return value of rb_econv_convert() */ +typedef enum { + + /** + * The conversion stopped when it found an invalid sequence. + */ + econv_invalid_byte_sequence, + + /** + * The conversion stopped when it found a character in the input which + * cannot be representable in the output. + */ + econv_undefined_conversion, + + /** + * The conversion stopped because there is no destination. + */ + econv_destination_buffer_full, + + /** + * The conversion stopped because there is no input. + */ + econv_source_buffer_empty, + + /** + * The conversion stopped after converting everything. This is arguably + * the expected normal end of conversion. + */ + econv_finished, + + /** + * The conversion stopped after writing something to somewhere, before + * reading everything. + */ + econv_after_output, + + /** + * The conversion stopped in middle of reading a character, possibly due to + * a partial read of a socket etc. + */ + econv_incomplete_input +} rb_econv_result_t; + +/** An opaque struct that represents a lowest level of encoding conversion. */ +typedef struct rb_econv_t rb_econv_t; + +/** + * Converts the contents of the passed string from its encoding to the passed + * one. + * + * @param[in] str Target string. + * @param[in] to Destination encoding. + * @param[in] ecflags A set of enum + * ::ruby_econv_flag_type. + * @param[in] ecopts A keyword hash, like + * ::rb_io_t::rb_io_enc_t::ecopts. + * @exception rb_eArgError Not fully converted. + * @exception rb_eInvalidByteSequenceError `str` is malformed. + * @exception rb_eUndefinedConversionError `str` has a character not + * representable using `to`. + * @exception rb_eConversionNotFoundError There is no known conversion from + * `str`'s encoding to `to`. + * @return A string whose encoding is `to`, and whose contents is converted + * contents of `str`. + * @note Use rb_econv_prepare_options() to generate `ecopts`. + */ +VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts); + +/** + * Queries if there is more than one way to convert between the passed two + * encodings. Encoding conversion are has_and_belongs_to_many relationships. + * There could be no direct conversion defined for the passed pair. Ruby tries + * to find an indirect way to do so then. For instance ISO-8859-1 has no + * direct conversion to ISO-2022-JP. But there is ISO-8859-1 to UTF-8 + * conversion; then there is UTF-8 to EUC-JP conversion; finally there also is + * EUC-JP to ISO-2022-JP conversion. So in short ISO-8859-1 can be converted + * to ISO-2022-JP using that path. This function returns true. Obviously not + * everything that can be represented using UTF-8 can also be represented using + * EUC-JP. Conversions in practice can fail depending on the actual input, and + * that renders exceptions in case of rb_str_encode(). + * + * @param[in] from_encoding One encoding. + * @param[in] to_encoding Another encoding. + * @retval 0 No way to convert the two. + * @retval 1 At least one way to convert the two. + * + * @internal + * + * Practically @shyouhei knows no way for this function to return 0. It seems + * everything can eventually be converted to/from UTF-8, which connects + * everything. + */ +int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding); + +/** + * Identical to rb_econv_prepare_opts(), except it additionally takes the + * initial value of flags. The extra bits are bitwise-ORed to the return + * value. + * + * @param[in] opthash Keyword arguments. + * @param[out] ecopts Return buffer. + * @param[in] ecflags Default set of enum ::ruby_econv_flag_type. + * @exception rb_eArgError Unknown/Broken values passed. + * @return Calculated set of enum ::ruby_econv_flag_type. + * @post `ecopts` holds a hash object suitable for + * ::rb_io_t::rb_io_enc_t::ecopts. + */ +int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags); + +/** + * Splits a keyword arguments hash (that for instance `String#encode` took) + * into a set of enum ::ruby_econv_flag_type and a hash storing replacement + * characters etc. + * + * @param[in] opthash Keyword arguments. + * @param[out] ecopts Return buffer. + * @exception rb_eArgError Unknown/Broken values passed. + * @return Calculated set of enum ::ruby_econv_flag_type. + * @post `ecopts` holds a hash object suitable for + * ::rb_io_t::rb_io_enc_t::ecopts. + */ +int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts); + +/** + * Creates a new instance of struct ::rb_econv_t. + * + * @param[in] source_encoding Name of an encoding. + * @param[in] destination_encoding Name of another encoding. + * @param[in] ecflags A set of enum ::ruby_econv_flag_type. + * @exception rb_eArgError No such encoding. + * @retval NULL Failed to create a struct ::rb_econv_t. + * @retval otherwise Allocated struct ::rb_econv_t. + * @warning Return value must be passed to rb_econv_close() exactly once. + */ +rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags); + +/** + * Identical to rb_econv_open(), except it additionally takes a hash of + * optional strings. + * + * + * @param[in] source_encoding Name of an encoding. + * @param[in] destination_encoding Name of another encoding. + * @param[in] ecflags A set of enum ::ruby_econv_flag_type. + * @param[in] ecopts Optional set of strings. + * @exception rb_eArgError No such encoding. + * @retval NULL Failed to create a struct ::rb_econv_t. + * @retval otherwise Allocated struct ::rb_econv_t. + * @warning Return value must be passed to rb_econv_close() exactly once. + */ +rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts); + +/** + * Converts a string from an encoding to another. + * + * Possible flags are either ::RUBY_ECONV_PARTIAL_INPUT (means the source + * buffer is a part of much larger one), ::RUBY_ECONV_AFTER_OUTPUT (instructs + * the converter to stop after output before input), or both of them. + * + * @param[in,out] ec Conversion specification/state etc. + * @param[in] source_buffer_ptr Target string. + * @param[in] source_buffer_end End of target string. + * @param[out] destination_buffer_ptr Return buffer. + * @param[out] destination_buffer_end End of return buffer. + * @param[in] flags Flags (see above). + * @return The status of the conversion. + * @post `destination_buffer_ptr` holds conversion results. + */ +rb_econv_result_t rb_econv_convert(rb_econv_t *ec, + const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, + unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, + int flags); + +/** + * Destructs a converter. Note that a converter can have a buffer, and can be + * non-empty. Calling this would lose your data then. + * + * @param[out] ec The converter to destroy. + * @post `ec` is no longer a valid pointer. + */ +void rb_econv_close(rb_econv_t *ec); + +/** + * Assigns the replacement string. The string passed here would appear in + * converted string when it cannot represent its source counterpart. This can + * happen for instance you convert an emoji to ISO-8859-1. + * + * @param[out] ec Target converter. + * @param[in] str Replacement string. + * @param[in] len Number of bytes of `str`. + * @param[in] encname Name of encoding of `str`. + * @retval 0 Success. + * @retval -1 Failure (ENOMEM etc.). + * @post `ec`'s replacement string is set to `str`. + */ +int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname); + +/** + * "Decorate"s a converter. There are special kind of converters that + * transforms the contents, like replacing CR into CRLF. You can add such + * decorators to a converter using this API. By using this function a + * decorator is prepended at the beginning of a conversion sequence: in case of + * CRLF conversion, newlines are converted before encodings are converted. + * + * @param[out] ec Target converter to decorate. + * @param[in] decorator_name Name of decorator to prepend. + * @retval 0 Success. + * @retval -1 Failure (no such decorator etc.). + * @post Decorator works before encoding conversion happens. + * + * @internal + * + * What is the possible value of the `decorator_name` is not public. You have + * to read through `transcode.c` carefully. + */ +int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name); + +/** + * Identical to rb_econv_decorate_at_first(), except it adds to the opposite + * direction. For instance CRLF conversion would run _after_ encodings are + * converted. + * + * @param[out] ec Target converter to decorate. + * @param[in] decorator_name Name of decorator to prepend. + * @retval 0 Success. + * @retval -1 Failure (no such decorator etc.). + * @post Decorator works after encoding conversion happens. + */ +int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name); + +/** + * Creates a `rb_eConverterNotFoundError` exception object (but does not + * raise). + * + * @param[in] senc Name of source encoding. + * @param[in] denc Name of destination encoding. + * @param[in] ecflags A set of enum ::ruby_econv_flag_type. + * @return An instance of `rb_eConverterNotFoundError`. + */ +VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags); + +/** + * Appends the passed string to the passed converter's output buffer. This can + * be handy when an encoding needs bytes out of thin air; for instance + * ISO-2022-JP has "shift function" which does not correspond to any + * characters. + * + * @param[out] ec Target converter. + * @param[in] str String to insert. + * @param[in] len Number of bytes of `str`. + * @param[in] str_encoding Encoding of `str`. + * @retval 0 Success. + * @retval -1 Failure (conversion error etc.). + * @note `str_encoding` can be anything, and `str` itself is converted + * when necessary. + */ +int rb_econv_insert_output(rb_econv_t *ec, + const unsigned char *str, size_t len, const char *str_encoding); + +/** + * Queries an encoding name which best suits for rb_econv_insert_output()'s + * last parameter. Strings in this encoding need no conversion when inserted; + * can be both time/space efficient. + * + * @param[in] ec Target converter. + * @return Its encoding for insertion. + */ +const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); + +/** + * This is a rb_econv_make_exception() + rb_exc_raise() combo. + * + * @param[in] ec (Possibly failed) conversion. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @note This function can return when no error. + */ +void rb_econv_check_error(rb_econv_t *ec); + +/** + * This function makes sense right after rb_econv_convert() returns. As listed + * in ::rb_econv_result_t, rb_econv_convert() can bail out for various reasons. + * This function checks the passed converter's internal state and convert it to + * an appropriate exception object. + * + * @param[in] ec Target converter. + * @retval RUBY_Qnil The converter has no error. + * @retval otherwise Conversion error turned into an exception. + */ +VALUE rb_econv_make_exception(rb_econv_t *ec); + +/** + * Queries if rb_econv_putback() makes sense, i.e. there are invalid byte + * sequences remain in the buffer. + * + * @param[in] ec Target converter. + * @return Number of bytes that can be pushed back. + */ +int rb_econv_putbackable(rb_econv_t *ec); + +/** + * Puts back the bytes. In case of ::econv_invalid_byte_sequence, some of + * those invalid bytes are discarded and the others are buffered to be + * converted later. The latter bytes can be put back using this API. + * + * @param[out] ec Target converter (invalid byte sequence). + * @param[out] p Return buffer. + * @param[in] n Max number of bytes to put back. + * @post At most `n` bytes of what was put back is written to `p`. + */ +void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); + +/** + * Queries the passed encoding's corresponding ASCII compatible encoding. "The + * corresponding ASCII compatible encoding" in this context is an ASCII + * compatible encoding which can represent exactly the same character sets as + * the given ASCII incompatible encoding. For instance that of UTF-16LE is + * UTF-8. + * + * @param[in] encname Name of an ASCII incompatible encoding. + * @retval NULL `encname` is already ASCII compatible. + * @retval otherwise The corresponding ASCII compatible encoding. + */ +const char *rb_econv_asciicompat_encoding(const char *encname); + +/** + * Identical to rb_econv_convert(), except it takes Ruby's string instead of + * C's pointer. + * + * @param[in,out] ec Target converter. + * @param[in] src Source string. + * @param[in] flags Flags (see rb_econv_convert). + * @exception rb_eArgError Converted string is too long. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @return The conversion result. + */ +VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags); + +/** + * Identical to rb_econv_str_convert(), except it converts only a part of the + * passed string. Can be handy when you for instance want to do line-buffered + * conversion. + * + * @param[in,out] ec Target converter. + * @param[in] src Source string. + * @param[in] byteoff Number of bytes to seek. + * @param[in] bytesize Number of bytes to read. + * @param[in] flags Flags (see rb_econv_convert). + * @exception rb_eArgError Converted string is too long. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @return The conversion result. + */ +VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags); + +/** + * Identical to rb_econv_str_convert(), except it appends the conversion result + * to the additionally passed string instead of creating a new string. It can + * also be seen as a routine identical to rb_econv_append(), except it takes a + * Ruby's string instead of C's pointer. + * + * @param[in,out] ec Target converter. + * @param[in] src Source string. + * @param[in] dst Return buffer. + * @param[in] flags Flags (see rb_econv_convert). + * @exception rb_eArgError Converted string is too long. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @return The conversion result. + */ +VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags); + +/** + * Identical to rb_econv_str_append(), except it appends only a part of the + * passed string with conversion. It can also be seen as a routine identical + * to rb_econv_substr_convert(), except it appends the conversion result to the + * additionally passed string instead of creating a new string. + * + * @param[in,out] ec Target converter. + * @param[in] src Source string. + * @param[in] byteoff Number of bytes to seek. + * @param[in] bytesize Number of bytes to read. + * @param[in] dst Return buffer. + * @param[in] flags Flags (see rb_econv_convert). + * @exception rb_eArgError Converted string is too long. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @return The conversion result. + */ +VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags); + +/** + * Converts the passed C's pointer according to the passed converter, then + * append the conversion result to the passed Ruby's string. This way buffer + * overflow is properly avoided to resize the destination properly. + * + * @param[in,out] ec Target converter. + * @param[in] bytesrc Target string. + * @param[in] bytesize Number of bytes of `bytesrc`. + * @param[in] dst Return buffer. + * @param[in] flags Flags (see rb_econv_convert). + * @exception rb_eArgError Converted string is too long. + * @exception rb_eInvalidByteSequenceError Invalid byte sequence. + * @exception rb_eUndefinedConversionError Conversion undefined. + * @return The conversion result. + */ +VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags); + +/** + * This badly named function does not set the destination encoding to binary, + * but instead just nullifies newline conversion decorators if any. Other + * ordinal character conversions still happen after this; something non-binary + * would still be generated. + * + * @param[out] ec Target converter to modify. + * @post Any newline conversions, if any, would be killed. + */ +void rb_econv_binmode(rb_econv_t *ec); + +/** + * This enum is kind of omnibus. Gathers various constants. + */ +enum ruby_econv_flag_type { + + /** + * @name Flags for rb_econv_open() + * + * @{ + */ + + /** Mask for error handling related bits. */ + RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff, + + /** Special handling of invalid sequences are there. */ + RUBY_ECONV_INVALID_MASK = 0x0000000f, + + /** Invalid sequences shall be replaced. */ + RUBY_ECONV_INVALID_REPLACE = 0x00000002, + + /** Special handling of undefined conversion are there. */ + RUBY_ECONV_UNDEF_MASK = 0x000000f0, + + /** Undefined characters shall be replaced. */ + RUBY_ECONV_UNDEF_REPLACE = 0x00000020, + + /** Undefined characters shall be escaped. */ + RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, + + /** Decorators are there. */ + RUBY_ECONV_DECORATOR_MASK = 0x0000ff00, + + /** Newline converters are there. */ + RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00, + + /** (Unclear; seems unused). */ + RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, + + /** (Unclear; seems unused). */ + RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000, + + /** Universal newline mode. */ + RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, + + /** CR to CRLF conversion shall happen. */ + RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000, + + /** CRLF to CR conversion shall happen. */ + RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, + + /** Texts shall be XML-escaped. */ + RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000, + + /** Texts shall be AttrValue escaped */ + RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000, + + /** (Unclear; seems unused). */ + RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, + + /** Texts shall be AttrValue escaped. */ + RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000, + + /** Newline decorator's default. */ + RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR = +#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) + RUBY_ECONV_CRLF_NEWLINE_DECORATOR, +#else + 0, +#endif + +#define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK /**< @old{RUBY_ECONV_ERROR_HANDLER_MASK} */ +#define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK /**< @old{RUBY_ECONV_INVALID_MASK} */ +#define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE /**< @old{RUBY_ECONV_INVALID_REPLACE} */ +#define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK /**< @old{RUBY_ECONV_UNDEF_MASK} */ +#define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE /**< @old{RUBY_ECONV_UNDEF_REPLACE} */ +#define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF /**< @old{RUBY_ECONV_UNDEF_HEX_CHARREF} */ +#define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK /**< @old{RUBY_ECONV_DECORATOR_MASK} */ +#define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_MASK} */ +#define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK} */ +#define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK} */ +#define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR} */ +#define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CRLF_NEWLINE_DECORATOR} */ +#define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CR_NEWLINE_DECORATOR} */ +#define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR /**< @old{RUBY_ECONV_XML_TEXT_DECORATOR} */ +#define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR} */ +#define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK /**< @old{RUBY_ECONV_STATEFUL_DECORATOR_MASK} */ +#define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR} */ +#define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR} */ + /** @} */ + + /** + * @name Flags for rb_econv_convert() + * + * @{ + */ + + /** Indicates the input is a part of much larger one. */ + RUBY_ECONV_PARTIAL_INPUT = 0x00010000, + + /** Instructs the converter to stop after output. */ + RUBY_ECONV_AFTER_OUTPUT = 0x00020000, +#define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT /**< @old{RUBY_ECONV_PARTIAL_INPUT} */ +#define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /**< @old{RUBY_ECONV_AFTER_OUTPUT} */ + + RUBY_ECONV_FLAGS_PLACEHOLDER /**< Placeholder (not used) */ +}; + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_INTERNAL_ENCODING_TRANSCODE_H */ diff --git a/ruby/include/ruby/internal/error.h b/ruby/include/ruby/internal/error.h new file mode 100644 index 000000000..49e2276cb --- /dev/null +++ b/ruby/include/ruby/internal/error.h @@ -0,0 +1,582 @@ +#ifndef RBIMPL_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ERROR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Declares ::rb_raise(). + */ +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/format.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +/** + * @defgroup exception Exception handlings + * @{ + */ + +/** + * Warning categories. A warning issued using this API can be selectively + * requested / suppressed by the end-users. For instance passing + * `-W:no-deprecated` to the ruby process would suppress those warnings in + * deprecated category. + * + * @warning There is no way to declare a new category (for now). + */ +typedef enum { + /** Category unspecified. */ + RB_WARN_CATEGORY_NONE, + + /** Warning is for deprecated features. */ + RB_WARN_CATEGORY_DEPRECATED, + + /** Warning is for experimental features. */ + RB_WARN_CATEGORY_EXPERIMENTAL, + + RB_WARN_CATEGORY_ALL_BITS = 0x6 /* no RB_WARN_CATEGORY_NONE bit */ +} rb_warning_category_t; + +/** for rb_readwrite_sys_fail first argument */ +enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE}; +/** @cond INTERNAL_MACRO */ +#define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE +#define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * This is the same as `$!` in Ruby. + * + * @retval RUBY_Qnil Not handling exceptions at the moment. + * @retval otherwise The current exception in the current thread. + * @ingroup exception + */ +VALUE rb_errinfo(void); + +/** + * Sets the current exception (`$!`) to the given value. + * + * @param[in] err An instance of ::rb_eException, or ::RUBY_Qnil. + * @exception rb_eTypeError What is given was neither ::rb_eException nor + * ::RUBY_Qnil. + * @note Use rb_raise() instead to raise `err`. This function just + * assigns the given object to the global variable. + * @ingroup exception + */ +void rb_set_errinfo(VALUE err); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Exception entry point. By calling this function the execution of your + * program gets interrupted to "raise" an exception up to the callee entities. + * Programs could "rescue" that exception, or could "ensure" some part of them. + * If nobody cares about such things, the raised exception reaches at the top + * of execution. This yields abnormal end of the process. + * + * @param[in] exc A subclass of ::rb_eException. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception exc The specified exception. + * @note It never returns. + */ +void rb_raise(VALUE exc, const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Raises the unsung "fatal" exception. This is considered severe. Nobody can + * rescue the exception. Once raised, process termination is inevitable. + * However ensure clauses still run, so that resources are properly cleaned up. + * + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eFatal An exception that you cannot rescue. + * @note It never returns. + */ +void rb_fatal(const char *fmt, ...); + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Interpreter panic switch. Immediate process termination without any + * synchronisations shall occur. LOTS of internal states, stack traces, and + * even machine registers are displayed if possible for debugging purposes + * then. + * + * @warning Do not use this API. + * @warning You are not expected to use this API. + * @warning Why not just fix your code instead of calling this API? + * @warning It was a bad idea to expose this API to extension libraries at + * the first place. We just cannot delete it at this point for + * backwards compatibility. That doesn't mean everyone are + * welcomed to call this function at will. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @note It never returns. + */ +void rb_bug(const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * This is a wrapper of rb_bug() which automatically constructs appropriate + * message from the passed errno. + * + * @param[in] msg Additional message to display. + * @exception err C level errno. + * @note It never returns. + */ +void rb_bug_errno(const char *msg, int err); + +RBIMPL_ATTR_NORETURN() +/** + * Converts a C errno into a Ruby exception, then raises it. For instance: + * + * ```CXX + * static VALUE + * foo(VALUE argv) + * { + * const auto cmd = StringValueCStr(argv); + * const auto waitr = system(cmd); + * if (waitr == -1) { + * rb_sys_fail("system(3posix)"); // <-------------- this + * } + * else { + * return INT2FIX(fd); + * } + * } + * ``` + * + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing errno. + * @note It never returns. + */ +void rb_sys_fail(const char *msg); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_sys_fail(), except it takes the message in Ruby's String + * instead of C's. + * + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing errno. + * @note It never returns. + */ +void rb_sys_fail_str(VALUE msg); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +/** + * Identical to rb_sys_fail(), except it takes additional module to extend the + * exception object before raising. + * + * @param[in] mod A ::rb_cModule instance. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing errno. + * @note It never returns. + * + * @internal + * + * Does anybody use it? + */ +void rb_mod_sys_fail(VALUE mod, const char *msg); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_mod_sys_fail(), except it takes the message in Ruby's String + * instead of C's. + * + * @param[in] mod A ::rb_cModule instance. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing errno. + * @note It never returns. + */ +void rb_mod_sys_fail_str(VALUE mod, VALUE msg); + +RBIMPL_ATTR_NORETURN() +/** + * Raises appropriate exception using the parameters. + * + * In Ruby level there are rb_eEAGAINWaitReadable etc. This function maps the + * given parameter to an appropriate exception class, then raises it. + * + * @param[in] waiting Reason for the IO to wait. + * @param[in] msg Additional message to raise. + * @exception rb_eEAGAINWaitWritable + * @exception rb_eEWOULDBLOCKWaitWritable + * @exception rb_eEINPROGRESSWaitWritable + * @exception rb_eEAGAINWaitReadable + * @exception rb_eEWOULDBLOCKWaitReadable + * @exception rb_eEINPROGRESSWaitReadable + * @exception rb_eSystemCallError + * @note It never returns. + */ +void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *msg); + +RBIMPL_ATTR_NORETURN() +/** + * Breaks from a block. Because you are using a CAPI this is not as intuitive + * as it sounds. In order for this function to properly work, make a + * ::rb_block_call_func_t function that calls it internally, and pass that + * function to rb_block_call(). + * + * @exception rb_eLocalJumpError Called from outside of a block. + * @note It never returns. + */ +void rb_iter_break(void); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_iter_break(), except it additionally takes the "value" of + * this breakage. It will be the evaluation result of the iterator. This is + * kind of complicated; you cannot see this as a "return from a block" + * behaviour. Take a look at this example: + * + * ```ruby + * def foo(q) + * puts(w = yield(q)) + * puts(e = yield(w)) + * puts(r = yield(e)) + * puts(t = yield(r)) + * puts(y = yield(t)) + * return "howdy!" + * end + * + * x = foo(0) {|i| + * if i > 2 + * break "hello!" + * else + * next i + 1 + * end + * } + * + * puts x + * ``` + * + * This script outputs 1, 2, 3, and hello. Note that the value passed to break + * becomes the return value of foo method, not the value of yield. This is + * confusing, but can be handy on occasions e.g. when you want to bring a + * local variable out of a block. + * + * @param[in] val The value of the iterator. + * @exception rb_eLocalJumpError Called from outside of a block. + * @note It never returns. + */ +void rb_iter_break_value(VALUE val); + +RBIMPL_ATTR_NORETURN() +/** + * Terminates the current execution context. This API is the entry point of a + * "well-mannered" termination sequence. When called from an extension + * library, it raises ::rb_eSystemExit exception. Programs could rescue that + * exception. Can cancel process exit then. Otherwise, that exception results + * in a process termination with the status passed to this function. + * + * @param[in] status Exit status, see also exit(3). + * @exception rb_eSystemExit Exception representing the exit status. + * @note It never returns. + * + * @internal + * + * "When called from an extension library"? You might wonder. In fact there + * are chances for this function to be called from outside of it, for instance + * when dlopen(3) failed. In case it is not possible for this function to + * raise an exception, it does not (silently enters to process cleanup). But + * that is a kind of implementation detail which extension library authors + * should not bother. + */ +void rb_exit(int status); + +RBIMPL_ATTR_NORETURN() +/** + * @exception rb_eNotImpError + * @note It never returns. + */ +void rb_notimplement(void); + +/** + * Creates an exception object that represents the given C errno. + * + * @param[in] err C level errno. + * @param[in] msg Additional message. + * @retval rb_eSystemCallError An exception for the errno. + */ +VALUE rb_syserr_new(int err, const char * msg); + +/** + * Identical to rb_syserr_new(), except it takes the message in Ruby's String + * instead of C's. + * + * @param[in] n C level errno. + * @param[in] arg Additional message. + * @retval rb_eSystemCallError An exception for the errno. + */ +VALUE rb_syserr_new_str(int n, VALUE arg); + +RBIMPL_ATTR_NORETURN() +/** + * Raises appropriate exception that represents a C errno. + * + * @param[in] err C level errno. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing `err`. + * @note It never returns. + */ +void rb_syserr_fail(int err, const char *msg); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_syserr_fail(), except it takes the message in Ruby's String + * instead of C's. + * + * @param[in] err C level errno. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing `err`. + * @note It never returns. + */ +void rb_syserr_fail_str(int err, VALUE msg); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_mod_sys_fail(), except it does not depend on C global + * variable errno. Pass it explicitly. + * + * @param[in] mod A ::rb_cModule instance. + * @param[in] err C level errno. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing `err`. + * @note It never returns. + */ +void rb_mod_syserr_fail(VALUE mod, int err, const char *msg); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's + * String instead of C's. + * + * @param[in] mod A ::rb_cModule instance. + * @param[in] err C level errno. + * @param[in] msg Additional message to raise. + * @exception rb_eSystemCallError An exception representing `err`. + * @note It never returns. + */ +void rb_mod_syserr_fail_str(VALUE mod, int err, VALUE msg); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_readwrite_sys_fail(), except it does not depend on C global + * variable errno. Pass it explicitly. + * + * @param[in] waiting Reason for the IO to wait. + * @param[in] err C level errno. + * @param[in] msg Additional message to raise. + * @exception rb_eEAGAINWaitWritable + * @exception rb_eEWOULDBLOCKWaitWritable + * @exception rb_eEINPROGRESSWaitWritable + * @exception rb_eEAGAINWaitReadable + * @exception rb_eEWOULDBLOCKWaitReadable + * @exception rb_eEINPROGRESSWaitReadable + * @exception rb_eSystemCallError + * @note It never returns. + */ +void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const char *msg); + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NORETURN() +/** + * Fails with the given object's type incompatibility to the type. + * + * It seems this function is visible from extension libraries only because + * RTYPEDDATA_TYPE() uses it on RUBY_DEBUG. So you can basically ignore it; + * use some other fine-grained method instead. + * + * @param[in] self The object in question. + * @param[in] t Expected type of the object. + * @exception rb_eTypeError `self` not in type `t`. + * @note It never returns. + * @note The second argument must have been an enum ::ruby_value_type, + * but for historical reasons it remains to be an int (in other + * words we see no benefits fixing this bug). + */ +void rb_unexpected_type(VALUE self, int t); + +/** + * @private + * + * This is an implementation detail of #ruby_verbose. Please don't use it + * directly. + * + * @retval Qnil Interpreter is quiet. + * @retval Qfalse Interpreter is kind of chatty. + * @retval otherwise Interpreter is very verbose. + */ +VALUE *rb_ruby_verbose_ptr(void); + +/** + * @private + * + * This is an implementation detail of #ruby_debug. Please don't use it + * directly. + * + * @retval Qnil Interpreter not in debug mode. + * @retval Qfalse Interpreter not in debug mode. + * @retval otherwise Interpreter is in debug mode. + */ +VALUE *rb_ruby_debug_ptr(void); + +/** + * This variable controls whether the interpreter is in debug mode. Setting + * this to some truthy value is equivalent to passing `-W` flag to the + * interpreter. Setting this to ::Qfalse is equivalent to passing `-W1` flag + * to the interpreter. Setting this to ::Qnil is equivalent to passing `-W0` + * flag to the interpreter. + * + * @retval Qnil Interpreter is quiet. + * @retval Qfalse Interpreter is kind of chatty. + * @retval otherwise Interpreter is very verbose. + */ +#define ruby_verbose (*rb_ruby_verbose_ptr()) + +/** + * This variable controls whether the interpreter is in debug mode. Setting + * this to some truthy value is equivalent to passing `-d` flag to the + * interpreter. + * + * @retval Qnil Interpreter not in debug mode. + * @retval Qfalse Interpreter not in debug mode. + * @retval otherwise Interpreter is in debug mode. + */ +#define ruby_debug (*rb_ruby_debug_ptr()) + +/* reports if `-W' specified */ +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Issues a warning. + * + * In ruby, warnings these days are tightly coupled with the rb_mWarning + * constant and its `warn` singleton method. This CAPI is just a thin wrapper + * of it; everything passed are formatted like what rb_sprintf() does, then + * passed through to the method. Programs can have their own `def + * Warning.warn` at will to do whatever they want, from ignoring the warnings + * at all to sinking them to some BigQuery data set via a Fluentd cluster. By + * default, the method just emits its passed contents to ::rb_stderr using + * rb_io_write(). + * + * @note This function is affected by the `-W` flag. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_warning(const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_warning(), except it takes additional "category" parameter. + * + * @param[in] cat Name of a known category. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_category_warning(rb_warning_category_t cat, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((1, 3)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) +/** + * Issues a compile-time warning that happens at `__file__:__line__`. Purpose + * of this function being exposed to CAPI is unclear. + * + * @note This function is affected by the `-W` flag. + * @param[in] file The path corresponding to Ruby level `__FILE__`. + * @param[in] line The number corresponding to Ruby level `__LINE__`. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_compile_warning(const char *file, int line, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Identical to rb_sys_fail(), except it does not raise an exception to render + * a warning instead. + * + * @note This function is affected by the `-W` flag. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_sys_warning(const char *fmt, ...); + +/* reports always */ +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Identical to rb_warning(), except it reports always regardless of runtime + * `-W` flag. + * + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_warn(const char *fmt, ...); + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_category_warning(), except it reports always regardless of + * runtime `-W` flag. + * + * @param[in] cat Category e.g. deprecated. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_category_warn(rb_warning_category_t cat, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((1, 3)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) +/** + * Identical to rb_compile_warning(), except it reports always regardless of + * runtime `-W` flag. + * + * @param[in] file The path corresponding to Ruby level `__FILE__`. + * @param[in] line The number corresponding to Ruby level `__LINE__`. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_compile_warn(const char *file, int line, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((2, 4)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) +/** + * Identical to rb_compile_warn(), except it also accepts category. + * + * @param[in] cat Category e.g. deprecated. + * @param[in] file The path corresponding to Ruby level `__FILE__`. + * @param[in] line The number corresponding to Ruby level `__LINE__`. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + */ +void rb_category_compile_warn(rb_warning_category_t cat, const char *file, int line, const char *fmt, ...); + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_ERROR_H */ diff --git a/ruby/include/ruby/internal/eval.h b/ruby/include/ruby/internal/eval.h new file mode 100644 index 000000000..34a53849d --- /dev/null +++ b/ruby/include/ruby/internal/eval.h @@ -0,0 +1,373 @@ +#ifndef RBIMPL_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_EVAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Declares ::rb_eval_string(). + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NONNULL(()) +/** + * Evaluates the given string in an isolated binding. + * + * Here "isolated" means that the binding does not inherit any other + * bindings. This behaves same as the binding for required libraries. + * + * `__FILE__` will be `"(eval)"`, and `__LINE__` starts from 1 in the + * evaluation. + * + * @param[in] str Ruby code to evaluate. + * @exception rb_eException Raises an exception on error. + * @return The evaluated result. + */ +VALUE rb_eval_string(const char *str); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_eval_string(), except it avoids potential global escapes. + * Such global escapes include exceptions, `throw`, `break`, for example. + * + * It first evaluates the given string as rb_eval_string() does. If no global + * escape occurred during the evaluation, it returns the result and `*state` is + * zero. Otherwise, it returns some undefined value and sets `*state` to + * nonzero. If state is `NULL`, it is not set in both cases. + * + * @param[in] str Ruby code to evaluate. + * @param[out] state State of execution. + * @return The evaluated result if succeeded, an undefined value if + * otherwise. + * @post `*state` is set to zero if succeeded. Nonzero otherwise. + * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if + * you decide to ignore the caught exception. + * @see rb_eval_string + * @see rb_protect + * + * @internal + * + * The "undefined value" described above is in fact ::RUBY_Qnil for now. But + * @shyouhei doesn't think that we would never change that. + * + * Though not a part of our public API, `state` is in fact an + * enum ruby_tag_type. You can see the potential "nonzero" values by looking + * at vm_core.h. + */ +VALUE rb_eval_string_protect(const char *str, int *state); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_eval_string_protect(), except it evaluates the given string + * under a module binding in an isolated binding. This is the same as a + * binding for loaded libraries on `rb_load(something, true)`. + * + * @param[in] str Ruby code to evaluate. + * @param[out] state State of execution. + * @return The evaluated result if succeeded, an undefined value if + * otherwise. + * @post `*state` is set to zero if succeeded. Nonzero otherwise. + * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if + * you decide to ignore the caught exception. + * @see rb_eval_string + */ +VALUE rb_eval_string_wrap(const char *str, int *state); + +/** + * Calls a method. Can call both public and private methods. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] n Number of arguments that follow. + * @param[in] ... Arbitrary number of method arguments. + * @exception rb_eNoMethodError No such method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcall(VALUE recv, ID mid, int n, ...); + +/** + * Identical to rb_funcall(), except it takes the method arguments as a C + * array. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @exception rb_eNoMethodError No such method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv); + +/** + * Identical to rb_funcallv(), except you can specify how to handle the last + * element of the given array. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No such method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); + +/** + * Identical to rb_funcallv(), except it only takes public methods into + * account. This is roughly Ruby's `Object#public_send`. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv); + +/** + * Identical to rb_funcallv_public(), except you can specify how to handle the + * last element of the given array. It can also be seen as a routine identical + * to rb_funcallv_kw(), except it only takes public methods into account. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); + +/** + * @deprecated This is an old name of rb_funcallv(). Provided here for + * backwards compatibility to 2.x programs (introduced in 2.1). + * It is not a good name. Please don't use it any longer. + */ +#define rb_funcall2 rb_funcallv + +/** + * @deprecated This is an old name of rb_funcallv_public(). Provided here + * for backwards compatibility to 2.x programs (introduced in + * 2.1). It is not a good name. Please don't use it any longer. + */ +#define rb_funcall3 rb_funcallv_public + +/** + * Identical to rb_funcallv_public(), except you can pass the passed block. + * + * Sometimes you want to "pass" a block parameter form one method to another. + * Suppose you have this Ruby method `foo`: + * + * ```ruby + * def foo(x, y, &z) + * x.open(y, &z) + * end + * ``` + * + * And suppose you want to translate this into C. Then + * rb_funcall_passing_block() function is usable in this situation. + * + * ```CXX + * VALUE + * foo_translated_into_C(VALUE self, VALUE x, VALUE y) + * { + * const auto open = rb_intern("open"); + * + * return rb_funcall_passing_block(x, open, 1, &y); + * } + * ``` + * + * @see rb_yield_block + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv); + +/** + * Identical to rb_funcallv_passing_block(), except you can specify how to + * handle the last element of the given array. It can also be seen as a + * routine identical to rb_funcallv_public_kw(), except you can pass the passed + * block. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); + +/** + * Identical to rb_funcallv_public(), except you can pass a block. A block + * here basically is an instance of ::rb_cProc. If you want to exercise + * `to_proc` conversion, do so before passing it here. However nil and symbols + * are special-case allowed. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] procval An instance of Proc, Symbol, or NilClass. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + * + * @internal + * + * Implementation-wise, `procval` is in fact a "block handler" object. You + * could also pass an IFUNC (block_handler_ifunc) here to say precise. --- But + * AFAIK there is no 3rd party way to even know that there are objects called + * IFUNC behind-the-scene. + */ +VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval); + +/** + * Identical to rb_funcallv_with_block(), except you can specify how to handle + * the last element of the given array. It can also be seen as a routine + * identical to rb_funcallv_public_kw(), except you can pass a block. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] procval An instance of Proc, Symbol, or NilClass. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No such method. + * @exception rb_eNoMethodError The method is private or protected. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + */ +VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat); + +/** + * This resembles ruby's `super`. + * + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @exception rb_eNoMethodError No super method are there. + * @exception rb_eException Any exceptions happen inside. + * @return What the super method evaluates to. + */ +VALUE rb_call_super(int argc, const VALUE *argv); + +/** + * Identical to rb_call_super(), except you can specify how to handle the last + * element of the given array. + * + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No super method are there. + * @exception rb_eException Any exceptions happen inside. + * @return What the super method evaluates to. + */ +VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat); + +/** + * This resembles ruby's `self`. + * + * @exception rb_eRuntimeError Called from outside of method context. + * @return Current receiver. + */ +VALUE rb_current_receiver(void); + +RBIMPL_ATTR_NONNULL((2)) +/** + * Keyword argument deconstructor. + * + * Retrieves argument values bound to keywords, which directed by `table` into + * `values`, deleting retrieved entries from `keyword_hash` along the way. + * First `required` number of IDs referred by `table` are mandatory, and + * succeeding `optional` (`-optional-1` if `optional` is negative) number of + * IDs are optional. If a mandatory key is not contained in `keyword_hash`, + * raises ::rb_eArgError. If an optional key is not present in `keyword_hash`, + * the corresponding element in `values` is set to ::RUBY_Qundef. If + * `optional` is negative, rest of `keyword_hash` are ignored, otherwise raises + * ::rb_eArgError. + * + * @warning Handling keyword arguments in the C API is less efficient than + * handling them in Ruby. Consider using a Ruby wrapper method + * around a non-keyword C function. + * @see https://bugs.ruby-lang.org/issues/11339 + * @param[out] keyword_hash Target hash to deconstruct. + * @param[in] table List of keywords that you are interested in. + * @param[in] required Number of mandatory keywords. + * @param[in] optional Number of optional keywords (can be negative). + * @param[out] values Buffer to be filled. + * @exception rb_eArgError Absence of a mandatory keyword. + * @exception rb_eArgError Found an unknown keyword. + * @return Number of found values that are stored into `values`. + */ +int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values); + +RBIMPL_ATTR_NONNULL(()) +/** + * Splits a hash into two. + * + * Takes a hash of various keys, and split it into symbol-keyed parts and + * others. Symbol-keyed part becomes the return value. What remains are + * returned as a new hash object stored at the argument pointer. + * + * @param[in,out] orighash Pointer to a target hash to split. + * @return An extracted keyword hash. + * @post Upon successful return `orighash` points to another hash + * object, whose contents are the remainder of the operation. + * @note The argument hash object is not modified. + */ +VALUE rb_extract_keywords(VALUE *orighash); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_EVAL_H */ diff --git a/ruby/include/ruby/internal/event.h b/ruby/include/ruby/internal/event.h new file mode 100644 index 000000000..04b137a19 --- /dev/null +++ b/ruby/include/ruby/internal/event.h @@ -0,0 +1,154 @@ +#ifndef RBIMPL_EVENT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_EVENT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Debugging and tracing APIs. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +/* These macros are not enums because they are wider than int.*/ + +/** + * @name Traditional set_trace_func events + * + * @{ + */ +#define RUBY_EVENT_NONE 0x0000 /**< No events. */ +#define RUBY_EVENT_LINE 0x0001 /**< Encountered a new line. */ +#define RUBY_EVENT_CLASS 0x0002 /**< Encountered a new class. */ +#define RUBY_EVENT_END 0x0004 /**< Encountered an end of a class clause. */ +#define RUBY_EVENT_CALL 0x0008 /**< A method, written in Ruby, is called. */ +#define RUBY_EVENT_RETURN 0x0010 /**< Encountered a `return` statement. */ +#define RUBY_EVENT_C_CALL 0x0020 /**< A method, written in C, is called. */ +#define RUBY_EVENT_C_RETURN 0x0040 /**< Return from a method, written in C. */ +#define RUBY_EVENT_RAISE 0x0080 /**< Encountered a `raise` statement. */ +#define RUBY_EVENT_ALL 0x00ff /**< Bitmask of traditional events. */ + +/** @} */ + +/** + * @name TracePoint extended events + * + * @{ + */ +#define RUBY_EVENT_B_CALL 0x0100 /**< Encountered an `yield` statement. */ +#define RUBY_EVENT_B_RETURN 0x0200 /**< Encountered a `next` statement. */ +#define RUBY_EVENT_THREAD_BEGIN 0x0400 /**< Encountered a new thread. */ +#define RUBY_EVENT_THREAD_END 0x0800 /**< Encountered an end of a thread. */ +#define RUBY_EVENT_FIBER_SWITCH 0x1000 /**< Encountered a `Fiber#yield`. */ +#define RUBY_EVENT_SCRIPT_COMPILED 0x2000 /**< Encountered an `eval`. */ +#define RUBY_EVENT_TRACEPOINT_ALL 0xffff /**< Bitmask of extended events. */ + +/** @} */ + +/** + * @name Special events + * + * @internal + * + * These bits are actually used internally. See vm_core.h if you are curious. + * + * @endinternal + * + * @{ + */ +#define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 /**< Opaque bits. */ + +/** @} */ + +/** + * @name Internal events + * + * @shyouhei's understanding is that some of them are visible from extension + * libraries because of `ext/objspace`. But it seems that doesn't describe + * everything? The ultimate reason why they are here remains unclear. + * + * @{ + */ +#define RUBY_INTERNAL_EVENT_SWITCH 0x040000 /**< Thread switched. */ +#define RUBY_EVENT_SWITCH 0x040000 /**< @old{RUBY_INTERNAL_EVENT_SWITCH} */ + /* 0x080000 */ +#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 /**< Object allocated. */ +#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 /**< Object swept. */ +#define RUBY_INTERNAL_EVENT_GC_START 0x400000 /**< GC started. */ +#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 /**< GC ended mark phase. */ +#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 /**< GC ended sweep phase. */ +#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 /**< `gc_enter()` is called. */ +#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 /**< `gc_exit()` is called. */ +#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 /**< Bitmask of GC events. */ +#define RUBY_INTERNAL_EVENT_MASK 0xffff0000 /**< Bitmask of internal events. */ + +/** @} */ + +/** + * Represents event(s). As the name implies events are bit flags. + */ +typedef uint32_t rb_event_flag_t; + +/** + * Type of event hooks. When an event happens registered functions are kicked + * with appropriate parameters. + * + * @param[in] evflag The kind of event that happened. + * @param[in] data The `data` passed to rb_add_event_hook(). + * @param[in] self Current receiver. + * @param[in] mid Name of the current method. + * @param[in] klass Current class. + */ +typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass); + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1 + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Registers an event hook function. + * + * @param[in] func A callback. + * @param[in] events A set of events that `func` should run. + * @param[in] data Passed as-is to `func`. + */ +void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); + +/** + * Removes the passed function from the list of event hooks. + * + * @param[in] func A callback. + * @return Number of deleted event hooks. + * @note As multiple events can share the same `func` it is quite + * possible for the return value to become more than one. + * + * @internal + * + * @shyouhei doesn't know if this is an Easter egg or an official feature, but + * you can pass 0 to the argument. That effectively swipes everything out from + * the hook list. + */ +int rb_remove_event_hook(rb_event_hook_func_t func); +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_EVENT_H */ diff --git a/ruby/include/ruby/internal/fl_type.h b/ruby/include/ruby/internal/fl_type.h new file mode 100644 index 000000000..08405d6f3 --- /dev/null +++ b/ruby/include/ruby/internal/fl_type.h @@ -0,0 +1,967 @@ +#ifndef RBIMPL_FL_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_FL_TYPE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines enum ::ruby_fl_type. + */ +#include "ruby/internal/config.h" /* for ENUM_OVER_INT */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/flag_enum.h" +#include "ruby/internal/attr/forceinline.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/has/extension.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/assert.h" +#include "ruby/defines.h" + +/** @cond INTERNAL_MACRO */ +#if RBIMPL_HAS_EXTENSION(enumerator_attributes) +# define RBIMPL_HAVE_ENUM_ATTRIBUTE 1 +#elif RBIMPL_COMPILER_SINCE(GCC, 6, 0, 0) +# define RBIMPL_HAVE_ENUM_ATTRIBUTE 1 +#endif + +#ifdef ENUM_OVER_INT +# define RBIMPL_WIDER_ENUM 1 +#elif SIZEOF_INT * CHAR_BIT > 12+19+1 +# define RBIMPL_WIDER_ENUM 1 +#else +# define RBIMPL_WIDER_ENUM 0 +#endif +/** @endcond */ + +#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */ +#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */ +#define FL_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) /**< @old{RUBY_FL_PROMOTED0} */ +#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) /**< @old{RUBY_FL_PROMOTED1} */ +#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */ +#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */ +#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */ +#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */ +#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */ +#define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */ +#define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */ + +#define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) /**< @old{RUBY_FL_USHIFT} */ + +#define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) /**< @old{RUBY_FL_USER0} */ +#define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) /**< @old{RUBY_FL_USER1} */ +#define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) /**< @old{RUBY_FL_USER2} */ +#define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) /**< @old{RUBY_FL_USER3} */ +#define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) /**< @old{RUBY_FL_USER4} */ +#define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) /**< @old{RUBY_FL_USER5} */ +#define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) /**< @old{RUBY_FL_USER6} */ +#define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) /**< @old{RUBY_FL_USER7} */ +#define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) /**< @old{RUBY_FL_USER8} */ +#define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) /**< @old{RUBY_FL_USER9} */ +#define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) /**< @old{RUBY_FL_USER10} */ +#define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) /**< @old{RUBY_FL_USER11} */ +#define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) /**< @old{RUBY_FL_USER12} */ +#define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) /**< @old{RUBY_FL_USER13} */ +#define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) /**< @old{RUBY_FL_USER14} */ +#define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) /**< @old{RUBY_FL_USER15} */ +#define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) /**< @old{RUBY_FL_USER16} */ +#define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) /**< @old{RUBY_FL_USER17} */ +#define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) /**< @old{RUBY_FL_USER18} */ +#define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) /**< @old{RUBY_FL_USER19} */ + +#define ELTS_SHARED RUBY_ELTS_SHARED /**< @old{RUBY_ELTS_SHARED} */ +#define RB_OBJ_FREEZE rb_obj_freeze_inline /**< @alias{rb_obj_freeze_inline} */ + +/** @cond INTERNAL_MACRO */ +#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED +#define RB_FL_ABLE RB_FL_ABLE +#define RB_FL_ALL RB_FL_ALL +#define RB_FL_ALL_RAW RB_FL_ALL_RAW +#define RB_FL_ANY RB_FL_ANY +#define RB_FL_ANY_RAW RB_FL_ANY_RAW +#define RB_FL_REVERSE RB_FL_REVERSE +#define RB_FL_REVERSE_RAW RB_FL_REVERSE_RAW +#define RB_FL_SET RB_FL_SET +#define RB_FL_SET_RAW RB_FL_SET_RAW +#define RB_FL_TEST RB_FL_TEST +#define RB_FL_TEST_RAW RB_FL_TEST_RAW +#define RB_FL_UNSET RB_FL_UNSET +#define RB_FL_UNSET_RAW RB_FL_UNSET_RAW +#define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW +#define RB_OBJ_FROZEN RB_OBJ_FROZEN +#define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW +#define RB_OBJ_INFECT RB_OBJ_INFECT +#define RB_OBJ_INFECT_RAW RB_OBJ_INFECT_RAW +#define RB_OBJ_TAINT RB_OBJ_TAINT +#define RB_OBJ_TAINTABLE RB_OBJ_TAINTABLE +#define RB_OBJ_TAINTED RB_OBJ_TAINTED +#define RB_OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW +#define RB_OBJ_TAINT_RAW RB_OBJ_TAINT_RAW +#define RB_OBJ_UNTRUST RB_OBJ_TAINT +#define RB_OBJ_UNTRUSTED RB_OBJ_TAINTED +/** @endcond */ + +/** + * @defgroup deprecated_macros Deprecated macro APIs + * @{ + * These macros are deprecated. Prefer their `RB_`-prefixed versions. + */ +#define FL_ABLE RB_FL_ABLE /**< @old{RB_FL_ABLE} */ +#define FL_ALL RB_FL_ALL /**< @old{RB_FL_ALL} */ +#define FL_ALL_RAW RB_FL_ALL_RAW /**< @old{RB_FL_ALL_RAW} */ +#define FL_ANY RB_FL_ANY /**< @old{RB_FL_ANY} */ +#define FL_ANY_RAW RB_FL_ANY_RAW /**< @old{RB_FL_ANY_RAW} */ +#define FL_REVERSE RB_FL_REVERSE /**< @old{RB_FL_REVERSE} */ +#define FL_REVERSE_RAW RB_FL_REVERSE_RAW /**< @old{RB_FL_REVERSE_RAW} */ +#define FL_SET RB_FL_SET /**< @old{RB_FL_SET} */ +#define FL_SET_RAW RB_FL_SET_RAW /**< @old{RB_FL_SET_RAW} */ +#define FL_TEST RB_FL_TEST /**< @old{RB_FL_TEST} */ +#define FL_TEST_RAW RB_FL_TEST_RAW /**< @old{RB_FL_TEST_RAW} */ +#define FL_UNSET RB_FL_UNSET /**< @old{RB_FL_UNSET} */ +#define FL_UNSET_RAW RB_FL_UNSET_RAW /**< @old{RB_FL_UNSET_RAW} */ +#define OBJ_FREEZE RB_OBJ_FREEZE /**< @old{RB_OBJ_FREEZE} */ +#define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW /**< @old{RB_OBJ_FREEZE_RAW} */ +#define OBJ_FROZEN RB_OBJ_FROZEN /**< @old{RB_OBJ_FROZEN} */ +#define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW /**< @old{RB_OBJ_FROZEN_RAW} */ +#define OBJ_INFECT RB_OBJ_INFECT /**< @old{RB_OBJ_INFECT} */ +#define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW /**< @old{RB_OBJ_INFECT_RAW} */ +#define OBJ_TAINT RB_OBJ_TAINT /**< @old{RB_OBJ_TAINT} */ +#define OBJ_TAINTABLE RB_OBJ_TAINTABLE /**< @old{RB_OBJ_TAINT_RAW} */ +#define OBJ_TAINTED RB_OBJ_TAINTED /**< @old{RB_OBJ_TAINTED} */ +#define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW /**< @old{RB_OBJ_TAINTED_RAW} */ +#define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW /**< @old{RB_OBJ_TAINT_RAW} */ +#define OBJ_UNTRUST RB_OBJ_UNTRUST /**< @old{RB_OBJ_TAINT} */ +#define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /**< @old{RB_OBJ_TAINTED} */ +/** @} */ + +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_fl_ushift { + /** + * Number of bits in ::ruby_fl_type that are _not_ open to users. This is + * an implementation detail. Please ignore. + */ + RUBY_FL_USHIFT = 12 +}; + +/* > The expression that defines the value of an enumeration constant shall be + * > an integer constant expression that has a value representable as an `int`. + * + * -- ISO/IEC 9899:2018 section 6.7.2.2 + * + * So ENUM_OVER_INT situation is an extension to the standard. Note however + * that we do not support 16 bit `int` environment. */ +RB_GNUC_EXTENSION +/** + * The flags. Each ruby objects have their own characteristics apart from + * their classes. For instance whether an object is frozen or not is not + * controlled by its class. This is the type that represents such properties. + * + * @note About the `FL_USER` terminology: the "user" here does not necessarily + * mean only you. For instance struct ::RString instances use these + * bits to cache their encodings etc. Devs discussed about this topic, + * reached their consensus that ::RUBY_T_DATA is the only valid data + * structure that can use these bits; other data structures including + * ::RUBY_T_OBJECT use these bits for their own purpose. See also + * https://bugs.ruby-lang.org/issues/18059 + */ +enum +RBIMPL_ATTR_FLAG_ENUM() +ruby_fl_type { + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @internal + * + * The reality is our GC no longer remembers write barriers inside of each + * objects, to use dedicated bitmap instead. But this flag is still used + * internally. The current usages of this flag should be something + * different, which is unclear to @shyouhei. + */ + RUBY_FL_WB_PROTECTED = (1<<5), + + /** + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced promotion i.e. survived a garbage collection. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_PROMOTED0 = (1<<5), + + /** + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced two promotions i.e. survived garbage collections + * twice. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_PROMOTED1 = (1<<6), + + /** + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced promotions i.e. survived more than one garbage + * collections. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1, + + /** + * This flag has something to do with finalisers. A ruby object can have + * its finaliser, which is another object that evaluates when the target + * object is about to die. This flag is used to denote that there is an + * attached finaliser. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_FINALIZE = (1<<7), + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ + RUBY_FL_TAINT + +#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) + RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +#elif defined(_MSC_VER) +# pragma deprecated(RUBY_FL_TAINT) +#endif + + = (1<<8), + + /** + * This flag has something to do with Ractor. Multiple Ractors run without + * protecting each other. Sharing an object among Ractors are basically + * dangerous, disabled by default. This flag is used to bypass that + * restriction. Of course, you have to manually prevent race conditions + * then. + * + * This flag needs deep understanding of multithreaded programming. You + * would better not use it. + */ + RUBY_FL_SHAREABLE = (1<<8), + + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ + RUBY_FL_UNTRUSTED + +#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) + RBIMPL_ATTR_DEPRECATED(("trustedness turned out to be a wrong idea.")) +#elif defined(_MSC_VER) +# pragma deprecated(RUBY_FL_UNTRUSTED) +#endif + + = (1<<8), + + /** + * This flag has something to do with object IDs. Unlike in the old days, + * an object's object ID (that a user can query using `Object#object_id`) + * is no longer its physical address represented using Ruby level integers. + * It is now a monotonic-increasing integer unrelated to the underlying + * memory arrangement. Object IDs are assigned when necessary; objects are + * born without one, and will eventually have such property when queried. + * The interpreter has to manage which one is which. This is the flag that + * helps the management. Objects with this flag set are the ones with + * object IDs assigned. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_SEEN_OBJ_ID = (1<<9), + + /** + * This flag has something to do with instance variables. 3rd parties need + * not know, but there are several ways to store an object's instance + * variables. Objects with this flag use so-called "generic" backend + * storage. This distinction is purely an implementation detail. People + * need not be aware of this working behind-the-scene. + * + * @internal + * + * As of writing everything except ::RObject and RModule use this scheme. + */ + RUBY_FL_EXIVAR = (1<<10), + + /** + * This flag has something to do with data immutability. When this flag is + * set an object is considered "frozen". No modification are expected to + * happen beyond that point for the particular object. Immutability is + * basically considered to be a good property these days. Library authors + * are expected to obey. Test this bit before you touch a data structure. + * + * @see rb_check_frozen() + */ + RUBY_FL_FREEZE = (1<<11), + +/** (@shyouhei doesn't know how to excude this macro from doxygen). */ +#define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n)) + RBIMPL_FL_USER_N(0), /**< User-defined flag. */ + RBIMPL_FL_USER_N(1), /**< User-defined flag. */ + RBIMPL_FL_USER_N(2), /**< User-defined flag. */ + RBIMPL_FL_USER_N(3), /**< User-defined flag. */ + RBIMPL_FL_USER_N(4), /**< User-defined flag. */ + RBIMPL_FL_USER_N(5), /**< User-defined flag. */ + RBIMPL_FL_USER_N(6), /**< User-defined flag. */ + RBIMPL_FL_USER_N(7), /**< User-defined flag. */ + RBIMPL_FL_USER_N(8), /**< User-defined flag. */ + RBIMPL_FL_USER_N(9), /**< User-defined flag. */ + RBIMPL_FL_USER_N(10), /**< User-defined flag. */ + RBIMPL_FL_USER_N(11), /**< User-defined flag. */ + RBIMPL_FL_USER_N(12), /**< User-defined flag. */ + RBIMPL_FL_USER_N(13), /**< User-defined flag. */ + RBIMPL_FL_USER_N(14), /**< User-defined flag. */ + RBIMPL_FL_USER_N(15), /**< User-defined flag. */ + RBIMPL_FL_USER_N(16), /**< User-defined flag. */ + RBIMPL_FL_USER_N(17), /**< User-defined flag. */ + RBIMPL_FL_USER_N(18), /**< User-defined flag. */ +#ifdef ENUM_OVER_INT + RBIMPL_FL_USER_N(19), /**< User-defined flag. */ +#else +# define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19)) +#endif +#undef RBIMPL_FL_USER_N +#undef RBIMPL_WIDER_ENUM + + /** + * This flag has something to do with data structures. Over time, ruby + * evolved to reduce memory footprints. One of such attempt is so-called + * copy-on-write, which delays duplication of resources until ultimately + * necessary. Some data structures share this scheme. For example + * multiple instances of struct ::RArray could point identical memory + * region in common, as long as they don't differ. As people favour + * immutable style of programming than before, this situation is getting + * more and more common. Because such "shared" memory regions have nuanced + * ownership by nature, each structures need special care for them. This + * flag is used to distinguish such shared constructs. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_ELTS_SHARED = RUBY_FL_USER2, + + /** + * This flag has something to do with an object's class. There are kind of + * classes called "singleton class", each of which have exactly one + * instance. What is interesting about singleton classes is that they are + * created _after_ their instance were instantiated, like this: + * + * ```ruby + * foo = Object.new # foo is an instance of Object... + * bar = foo.singleton_class # foo is now an instance of bar. + * ``` + * + * Here as you see `bar` is a singleton class of `foo`, which is injected + * into `foo`'s inheritance tree in a different statement (== distinct + * sequence point). In order to achieve this property singleton classes + * are special-cased in the interpreter. There is one bit flag that + * distinguishes if a class is a singleton class or not, and this is it. + * + * @internal + * + * But honestly, @shyouhei doesn't think this flag should be visible from + * 3rd parties. It must be an implementation detail that they should never + * know. Might better be hidden. + */ + RUBY_FL_SINGLETON = RUBY_FL_USER0, +}; + +enum { + /** + * @deprecated This flag once was a thing back in the old days, but makes + * no sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + */ + RUBY_FL_DUPPED + +#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) + RBIMPL_ATTR_DEPRECATED(("It seems there is no actual usage of this enum.")) +#elif defined(_MSC_VER) +# pragma deprecated(RUBY_FL_DUPPED) +#endif + + = (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR +}; + +#undef RBIMPL_HAVE_ENUM_ATTRIBUTE + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_obj_infect(VALUE victim, VALUE carrier); + +/** + * This is an implementation detail of #RB_OBJ_FREEZE(). People don't use it + * directly. + * + * @param[out] klass A singleton class. + * @post `klass` gets frozen. + */ +void rb_freeze_singleton_class(VALUE klass); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_FORCEINLINE() +/** + * Checks if the object is flaggable. There are some special cases (most + * notably ::RUBY_Qfalse) where appending a flag to an object is not possible. + * This function can detect that. + * + * @param[in] obj Object in question + * @retval true It is flaggable. + * @retval false No it isn't. + */ +static bool +RB_FL_ABLE(VALUE obj) +{ + if (RB_SPECIAL_CONST_P(obj)) { + return false; + } + else if (RB_TYPE_P(obj, RUBY_T_NODE)) { + return false; + } + else { + return true; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_TEST(). 3rd parties need not use + * this. Just always use RB_FL_TEST(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @pre The object must not be an enum ::ruby_special_consts. + * @return `obj`'s flags, masked by `flags`. + */ +static inline VALUE +RB_FL_TEST_RAW(VALUE obj, VALUE flags) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + return RBASIC(obj)->flags & flags; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Tests if the given flag(s) are set or not. You can pass multiple flags at + * once: + * + * ```CXX + * auto obj = rb_eval_string("..."); + * if (RB_FL_TEST(obj, RUBY_FL_FREEZE | RUBY_FL_SHAREABLE)) { + * printf("Ractor ready!\n"); + * } + * ``` + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @return `obj`'s flags, masked by `flags`. + * @note It is intentional for this function to return ::VALUE. The + * return value could be passed to RB_FL_STE() etc. + */ +static inline VALUE +RB_FL_TEST(VALUE obj, VALUE flags) +{ + if (RB_FL_ABLE(obj)) { + return RB_FL_TEST_RAW(obj, flags); + } + else { + return RBIMPL_VALUE_NULL; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_ANY(). 3rd parties need not use + * this. Just always use RB_FL_ANY(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has any of the flags set. + * @retval false No it doesn't at all. + * @pre The object must not be an enum ::ruby_special_consts. + */ +static inline bool +RB_FL_ANY_RAW(VALUE obj, VALUE flags) +{ + return RB_FL_TEST_RAW(obj, flags); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RB_FL_TEST(), except it returns bool. + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has any of the flags set. + * @retval false No it doesn't at all. + */ +static inline bool +RB_FL_ANY(VALUE obj, VALUE flags) +{ + return RB_FL_TEST(obj, flags); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_ALL(). 3rd parties need not use + * this. Just always use RB_FL_ALL(). + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has all of the flags set. + * @retval false The object lacks any of the flags. + * @pre The object must not be an enum ::ruby_special_consts. + */ +static inline bool +RB_FL_ALL_RAW(VALUE obj, VALUE flags) +{ + return RB_FL_TEST_RAW(obj, flags) == flags; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RB_FL_ANY(), except it mandates all passed flags be set. + * + * @param[in] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @retval true The object has all of the flags set. + * @retval false The object lacks any of the flags. + */ +static inline bool +RB_FL_ALL(VALUE obj, VALUE flags) +{ + return RB_FL_TEST(obj, flags) == flags; +} + +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use + * this. Just always use RB_FL_SET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_SET_RAW() as + * `__declspec(noalias)`. + */ +static inline void +rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) +{ + obj->flags |= flags; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use + * this. Just always use RB_FL_SET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + */ +static inline void +RB_FL_SET_RAW(VALUE obj, VALUE flags) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + rbimpl_fl_set_raw_raw(RBASIC(obj), flags); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Sets the given flag(s). + * + * ```CXX + * auto v = rb_eval_string("..."); + * RB_FL_SET(v, RUBY_FL_FREEZE); + * ``` + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` set. + */ +static inline void +RB_FL_SET(VALUE obj, VALUE flags) +{ + if (RB_FL_ABLE(obj)) { + RB_FL_SET_RAW(obj, flags); + } +} + +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use + * this. Just always use RB_FL_UNSET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_UNSET_RAW() as + * `__declspec(noalias)`. + */ +static inline void +rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) +{ + obj->flags &= ~flags; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use + * this. Just always use RB_FL_UNSET(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + */ +static inline void +RB_FL_UNSET_RAW(VALUE obj, VALUE flags) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + rbimpl_fl_unset_raw_raw(RBASIC(obj), flags); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Clears the given flag(s). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleard. + */ +static inline void +RB_FL_UNSET(VALUE obj, VALUE flags) +{ + if (RB_FL_ABLE(obj)) { + RB_FL_UNSET_RAW(obj, flags); + } +} + +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not + * use this. Just always use RB_FL_REVERSE(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` reversed. + * + * @internal + * + * This is function is here to annotate a part of RB_FL_REVERSE_RAW() as + * `__declspec(noalias)`. + */ +static inline void +rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) +{ + obj->flags ^= flags; +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not + * use this. Just always use RB_FL_REVERSE(). + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` cleared. + */ +static inline void +RB_FL_REVERSE_RAW(VALUE obj, VALUE flags) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + rbimpl_fl_reverse_raw_raw(RBASIC(obj), flags); +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Reverses the flags. This function is here mainly for symmetry on set/unset. + * Rarely used in practice. + * + * @param[out] obj Object in question. + * @param[in] flags A set of enum ::ruby_fl_type. + * @post `obj` has `flags` reversed. + */ +static inline void +RB_FL_REVERSE(VALUE obj, VALUE flags) +{ + if (RB_FL_ABLE(obj)) { + RB_FL_REVERSE_RAW(obj, flags); + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ +static inline bool +RB_OBJ_TAINTABLE(VALUE obj) +{ + return false; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ +static inline VALUE +RB_OBJ_TAINTED_RAW(VALUE obj) +{ + return false; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return false always. + */ +static inline bool +RB_OBJ_TAINTED(VALUE obj) +{ + return false; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + */ +static inline void +RB_OBJ_TAINT_RAW(VALUE obj) +{ + return; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + */ +static inline void +RB_OBJ_TAINT(VALUE obj) +{ + return; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] dst Victim object. + * @param[in] src Infectant object. + */ +static inline void +RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) +{ + return; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] dst Victim object. + * @param[in] src Infectant object. + */ +static inline void +RB_OBJ_INFECT(VALUE dst, VALUE src) +{ + return; +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_OBJ_FROZEN(). 3rd parties need not + * use this. Just always use RB_OBJ_FROZEN(). + * + * @param[in] obj Object in question. + * @retval RUBY_FL_FREEZE Yes it is. + * @retval 0 No it isn't. + * + * @internal + * + * It is intentional not to return bool here. There is a place in ruby core + * (namely `class.c:singleton_class_of()`) where return value of this function + * is passed to RB_FL_SET_RAW(). + */ +static inline VALUE +RB_OBJ_FROZEN_RAW(VALUE obj) +{ + return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if an object is frozen. + * + * @param[in] obj Object in question. + * @retval true Yes it is. + * @retval false No it isn't. + */ +static inline bool +RB_OBJ_FROZEN(VALUE obj) +{ + if (! RB_FL_ABLE(obj)) { + return true; + } + else { + return RB_OBJ_FROZEN_RAW(obj); + } +} + +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is an implenentation detail of RB_OBJ_FREEZE(). 3rd parties need not + * use this. Just always use RB_OBJ_FREEZE(). + * + * @param[out] obj Object in question. + */ +static inline void +RB_OBJ_FREEZE_RAW(VALUE obj) +{ + RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); +} + +/** + * Prevents further modifications to the given object. ::rb_eFrozenError shall + * be raised if modification is attempted. + * + * @param[out] x Object in question. + */ +static inline void +rb_obj_freeze_inline(VALUE x) +{ + if (RB_FL_ABLE(x)) { + RB_OBJ_FREEZE_RAW(x); + if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) { + rb_freeze_singleton_class(x); + } + } +} + +#endif /* RBIMPL_FL_TYPE_H */ diff --git a/ruby/include/ruby/internal/gc.h b/ruby/include/ruby/internal/gc.h new file mode 100644 index 000000000..66fc14e51 --- /dev/null +++ b/ruby/include/ruby/internal/gc.h @@ -0,0 +1,57 @@ +#ifndef RBIMPL_GC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_GC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Registering values to the GC. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Inform the garbage collector that `valptr` points to a live Ruby object that + * should not be moved. Note that extensions should use this API on global + * constants instead of assuming constants defined in Ruby are always alive. + * Ruby code can remove global constants. + */ +void rb_gc_register_address(VALUE *valptr); + +/** + * An alias for `rb_gc_register_address()`. + */ +void rb_global_variable(VALUE *); + +/** + * Inform the garbage collector that a pointer previously passed to + * `rb_gc_register_address()` no longer points to a live Ruby object. + */ +void rb_gc_unregister_address(VALUE *valptr); + +/** + * Inform the garbage collector that `object` is a live Ruby object that should + * not be moved. + * + * See also: rb_gc_register_address() + */ +void rb_gc_register_mark_object(VALUE object); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_GC_H */ diff --git a/ruby/include/ruby/internal/glob.h b/ruby/include/ruby/internal/glob.h new file mode 100644 index 000000000..adbccbdc5 --- /dev/null +++ b/ruby/include/ruby/internal/glob.h @@ -0,0 +1,113 @@ +#ifndef RBIMPL_GLOB_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_GLOB_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Declares ::rb_glob(). + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Type of a glob callback function. Called every time glob scans a path. + * + * @param[in] path The path in question. + * @param[in] arg The argument passed to rb_glob(). + * @param[in] enc Encoding of the path. + * @retval -1 Not enough memory to do the operation. + * @retval 0 Operation successful. + * @retval otherwise Opaque exception state. + * @note You can use rb_protect() to generate the return value. + * + * @internal + * + * This is a wrong design. Type of `enc` should have been `rb_encoding*` + * instead of just `void*`. But we cannot change the API any longer. + * + * Though not a part of our public API, the "opaque exception state" is in fact + * an enum ruby_tag_type. You can see the potential "otherwise" values by + * looking at vm_core.h. + */ +typedef int ruby_glob_func(const char *path, VALUE arg, void *enc); + +RBIMPL_ATTR_NONNULL(()) +/** + * The "glob" operator. Expands the given pattern against the actual local + * filesystem, then iterates over the expanded filenames by calling the + * callback function. + * + * @param[in] pattern A glob pattern. + * @param[in] func Identical to ruby_glob_func, except it can raise + * exceptions instead of returning opaque state. + * @param[in] arg Extra argument passed to func. + * @exception rb_eException Can propagate what `func` raises. + * @note The language accepted as the pattern is not a regular + * expression. It resembles shell's glob. + */ +void rb_glob(const char *pattern, void (*func)(const char *path, VALUE arg, void *enc), VALUE arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_glob(), except it returns opaque exception states instead of + * raising exceptions. + * + * @param[in] pattern A glob pattern. + * @param[in] flags No, you are not allowed to use this. Just pass 0. + * @param[in] func A callback function. + * @param[in] arg Extra argument passed to func. + * @return Return value of `func`. + * + * @internal + * + * This function is completely broken by design... Not only is there no sane + * way to pass flags, but there also is no sane way to know what a return value + * is meant to be. + * + * Though not a part of our public API, and @shyouhei thinks it's a failure not + * to be a public API, the flags can be `FNM_EXTGLOB`, `FNM_DOTMATCH` etc. + * Look at dir.c for the list. + * + * Though not a part of our public API, the return value is in fact an + * enum ruby_tag_type. You can see the potential values by looking at + * vm_core.h. + */ +int ruby_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to ruby_glob(), @shyouhei currently suspects. Historically you + * had to call this function instead of ruby_glob() if the pattern included + * "{x,y,...}" syntax. However since commit 0f63d961169989a7f6dcf7c0487fe29da, + * ruby_glob() also supports that syntax. It seems as of writing these two + * functions provide basically the same functionality in a different + * implementation. Is this analysis right? Correct me! :FIXME: + * + * @param[in] pattern A glob pattern. + * @param[in] flags No, you are not allowed to use this. Just pass 0. + * @param[in] func A callback function. + * @param[in] arg Extra argument passed to func. + * @return Return value of `func`. + */ +int ruby_brace_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_GLOB_H */ diff --git a/ruby/include/ruby/internal/globals.h b/ruby/include/ruby/internal/globals.h new file mode 100644 index 000000000..5a414fc47 --- /dev/null +++ b/ruby/include/ruby/internal/globals.h @@ -0,0 +1,209 @@ +#ifndef RBIMPL_GLOBALS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_GLOBALS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Ruby-level global variables / constants, visible from C. + */ +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" + +/** + * @defgroup object Core objects and their operations + * + * @internal + * + * There are several questionable constants listed in this header file. They + * are intentionally left untouched for purely academic backwards compatibility + * concerns. But for instance do any one of 3rd party extension libraries even + * need to know that there is NameError::Message? + * + * @endinternal + * + * @{ + */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RUBY_INTEGER_UNIFICATION 1 + +RUBY_EXTERN VALUE rb_mKernel; /**< `Kernel` module. */ +RUBY_EXTERN VALUE rb_mComparable; /**< `Comparable` module. */ +RUBY_EXTERN VALUE rb_mEnumerable; /**< `Enumerable` module. */ +RUBY_EXTERN VALUE rb_mErrno; /**< `Errno` module. */ +RUBY_EXTERN VALUE rb_mFileTest; /**< `FileTest` module. */ +RUBY_EXTERN VALUE rb_mGC; /**< `GC` module. */ +RUBY_EXTERN VALUE rb_mMath; /**< `Math` module. */ +RUBY_EXTERN VALUE rb_mProcess; /**< `Process` module. */ +RUBY_EXTERN VALUE rb_mWaitReadable; /**< `IO::WaitReadable` module. */ +RUBY_EXTERN VALUE rb_mWaitWritable; /**< `IO::WaitReadable` module. */ + +RUBY_EXTERN VALUE rb_cBasicObject; /**< `BasicObject` class. */ +RUBY_EXTERN VALUE rb_cObject; /**< `Object` class. */ +RUBY_EXTERN VALUE rb_cArray; /**< `Array` class. */ +RUBY_EXTERN VALUE rb_cBinding; /**< `Binding` class. */ +RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */ +RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */ +RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */ +RUBY_EXTERN VALUE rb_cEnumerator; /**< `Enumerator` class. */ +RUBY_EXTERN VALUE rb_cFalseClass; /**< `FalseClass` class. */ +RUBY_EXTERN VALUE rb_cFile; /**< `File` class. */ +RUBY_EXTERN VALUE rb_cComplex; /**< `Complex` class. */ +RUBY_EXTERN VALUE rb_cFloat; /**< `Float` class. */ +RUBY_EXTERN VALUE rb_cHash; /**< `Hash` class. */ +RUBY_EXTERN VALUE rb_cIO; /**< `IO` class. */ +RUBY_EXTERN VALUE rb_cInteger; /**< `Module` class. */ +RUBY_EXTERN VALUE rb_cMatch; /**< `MatchData` class. */ +RUBY_EXTERN VALUE rb_cMethod; /**< `Method` class. */ +RUBY_EXTERN VALUE rb_cModule; /**< `Module` class. */ +RUBY_EXTERN VALUE rb_cRefinement; /**< `Refinement` class. */ +RUBY_EXTERN VALUE rb_cNameErrorMesg; /**< `NameError::Message` class. */ +RUBY_EXTERN VALUE rb_cNilClass; /**< `NilClass` class. */ +RUBY_EXTERN VALUE rb_cNumeric; /**< `Numeric` class. */ +RUBY_EXTERN VALUE rb_cProc; /**< `Proc` class. */ +RUBY_EXTERN VALUE rb_cRandom; /**< `Random` class. */ +RUBY_EXTERN VALUE rb_cRange; /**< `Range` class. */ +RUBY_EXTERN VALUE rb_cRational; /**< `Rational` class. */ +RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */ +RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */ +RUBY_EXTERN VALUE rb_cString; /**< `String` class. */ +RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */ +RUBY_EXTERN VALUE rb_cSymbol; /**< `Sumbol` class. */ +RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */ +RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */ +RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */ +RUBY_EXTERN VALUE rb_cUnboundMethod; /**< `UnboundMethod` class. */ + +/** + * @} + * @addtogroup exception + * @{ + */ + +RUBY_EXTERN VALUE rb_eException; /**< Mother of all exceptions. */ +RUBY_EXTERN VALUE rb_eStandardError; /**< `StandardError` exception. */ +RUBY_EXTERN VALUE rb_eSystemExit; /**< `SystemExit` exception. */ +RUBY_EXTERN VALUE rb_eInterrupt; /**< `Interrupt` exception. */ +RUBY_EXTERN VALUE rb_eSignal; /**< `SignalException` exception. */ +RUBY_EXTERN VALUE rb_eFatal; /**< `fatal` exception. */ +RUBY_EXTERN VALUE rb_eArgError; /**< `ArgumentError` exception. */ +RUBY_EXTERN VALUE rb_eEOFError; /**< `EOFError` exception. */ +RUBY_EXTERN VALUE rb_eIndexError; /**< `IndexError` exception. */ +RUBY_EXTERN VALUE rb_eStopIteration; /**< `StopIteration` exception. */ +RUBY_EXTERN VALUE rb_eKeyError; /**< `KeyError` exception. */ +RUBY_EXTERN VALUE rb_eRangeError; /**< `RangeError` exception. */ +RUBY_EXTERN VALUE rb_eIOError; /**< `IOError` exception. */ +RUBY_EXTERN VALUE rb_eRuntimeError; /**< `RuntimeError` exception. */ +RUBY_EXTERN VALUE rb_eFrozenError; /**< `FrozenError` exception. */ +RUBY_EXTERN VALUE rb_eSecurityError; /**< `SecurityError` exception. */ +RUBY_EXTERN VALUE rb_eSystemCallError; /**< `SystemCallError` exception. */ +RUBY_EXTERN VALUE rb_eThreadError; /**< `ThreadError` exception. */ +RUBY_EXTERN VALUE rb_eTypeError; /**< `TypeError` exception. */ +RUBY_EXTERN VALUE rb_eZeroDivError; /**< `ZeroDivisionError` exception. */ +RUBY_EXTERN VALUE rb_eNotImpError; /**< `NotImplementedError` exception. */ +RUBY_EXTERN VALUE rb_eNoMemError; /**< `NoMemoryError` exception. */ +RUBY_EXTERN VALUE rb_eNoMethodError; /**< `NoMethodError` exception. */ +RUBY_EXTERN VALUE rb_eFloatDomainError; /**< `FloatDomainError` exception. */ +RUBY_EXTERN VALUE rb_eLocalJumpError; /**< `LocalJumpError` exception. */ +RUBY_EXTERN VALUE rb_eSysStackError; /**< `SystemStackError` exception. */ +RUBY_EXTERN VALUE rb_eRegexpError; /**< `RegexpError` exception. */ +RUBY_EXTERN VALUE rb_eEncodingError; /**< `EncodingError` exception. */ +RUBY_EXTERN VALUE rb_eEncCompatError; /**< `Encoding::CompatibilityError` exception. */ +RUBY_EXTERN VALUE rb_eNoMatchingPatternError; /**< `NoMatchingPatternError` exception. */ +RUBY_EXTERN VALUE rb_eNoMatchingPatternKeyError; /**< `NoMatchingPatternKeyError` exception. */ + +RUBY_EXTERN VALUE rb_eScriptError; /**< `ScriptError` exception. */ +RUBY_EXTERN VALUE rb_eNameError; /**< `NameError` exception. */ +RUBY_EXTERN VALUE rb_eSyntaxError; /**< `SyntaxError` exception. */ +RUBY_EXTERN VALUE rb_eLoadError; /**< `LoadError` exception. */ + +RUBY_EXTERN VALUE rb_eMathDomainError; /**< `Math::DomainError` exception. */ + +/** + * @} + * @addtogroup object + * @{ + */ + +RUBY_EXTERN VALUE rb_stdin; /**< `STDIN` constant. */ +RUBY_EXTERN VALUE rb_stdout; /**< `STDOUT` constant. */ +RUBY_EXTERN VALUE rb_stderr; /**< `STDERR` constant. */ + +RBIMPL_ATTR_PURE() +/** + * Object to class mapping function. Every object have its class. This + * function obtains that. + * + * @param[in] obj Target object to query. + * @return The class of the given object. + * + * @internal + * + * This function is a super-duper hot path. Optimised targeting modern C + * compilers and x86_64 architecture. + */ +static inline VALUE +rb_class_of(VALUE obj) +{ + if (! RB_SPECIAL_CONST_P(obj)) { + return RBASIC_CLASS(obj); + } + else if (obj == RUBY_Qfalse) { + return rb_cFalseClass; + } + else if (obj == RUBY_Qnil) { + return rb_cNilClass; + } + else if (obj == RUBY_Qtrue) { + return rb_cTrueClass; + } + else if (RB_FIXNUM_P(obj)) { + return rb_cInteger; + } + else if (RB_STATIC_SYM_P(obj)) { + return rb_cSymbol; + } + else if (RB_FLONUM_P(obj)) { + return rb_cFloat; + } + +#if !RUBY_DEBUG + RBIMPL_UNREACHABLE_RETURN(Qfalse); +#else + RUBY_ASSERT_FAIL("unexpected type"); +#endif +} + +#define CLASS_OF rb_class_of /**< @old{rb_class_of} */ + +RBIMPL_SYMBOL_EXPORT_END() + +/** @} */ + +#endif /* RBIMPL_GLOBALS_H */ diff --git a/ruby/include/ruby/internal/has/attribute.h b/ruby/include/ruby/internal/has/attribute.h new file mode 100644 index 000000000..f068a65ca --- /dev/null +++ b/ruby/include/ruby/internal/has/attribute.h @@ -0,0 +1,163 @@ +#ifndef RBIMPL_HAS_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_ATTRIBUTE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_ATTRIBUTE. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/compiler_since.h" + +#if defined(__has_attribute) +# if __has_attribute(pure) || RBIMPL_COMPILER_IS(GCC) +# /* FreeBSD's defines its own *broken* version of +# * __has_attribute. Cygwin copied that content to be a victim of the +# * broken-ness. We don't take them into account. */ +# define RBIMPL_HAVE___HAS_ATTRIBUTE 1 +# endif +#endif + +/** Wraps (or simulates) `__has_attribute`. */ +#if defined(RBIMPL_HAVE___HAS_ATTRIBUTE) +# define RBIMPL_HAS_ATTRIBUTE(_) __has_attribute(_) + +#elif RBIMPL_COMPILER_IS(GCC) +# /* GCC <= 4 lack __has_attribute predefined macro, while have attributes +# * themselves. We can simulate the macro like the following: */ +# define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_HAS_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_alloc_size RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_artificial RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) +# define RBIMPL_HAS_ATTRIBUTE_cdecl RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_cold RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(GCC, 2, 6, 0) +# define RBIMPL_HAS_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) +# define RBIMPL_HAS_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_error RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_format RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_hot RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_leaf RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) +# define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) +# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) +# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_undefined RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) +# define RBIMPL_HAS_ATTRIBUTE_nonnull RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(GCC, 2, 5, 0) +# define RBIMPL_HAS_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(GCC, 2,96, 0) +# define RBIMPL_HAS_ATTRIBUTE_returns_nonnull RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(GCC, 4, 1, 0) +# define RBIMPL_HAS_ATTRIBUTE_stdcall RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_unused RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_warn_unused_result RBIMPL_COMPILER_SINCE(GCC, 3, 4, 0) +# define RBIMPL_HAS_ATTRIBUTE_warning RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) +# define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# /* Note that "0, 0, 0" might be inaccurate. */ + +#elif RBIMPL_COMPILER_IS(SunPro) +# /* Oracle Solaris Studio 12.4 (cc version 5.11) introduced __has_attribute. +# * Before that, following attributes were available. */ +# /* See https://docs.oracle.com/cd/F24633_01/index.html */ +# define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_HAS_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_ATTRIBUTE_alias RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_constructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_destructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_packed RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_HAS_ATTRIBUTE_vector_size RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) +# define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) +# define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) + +#elif defined (_MSC_VER) +# define RBIMPL_HAS_ATTRIBUTE(_) 0 +# /* Fallback below doesn't work: see win32/Makefile.sub */ + +#else +# /* Take config.h definition when available. */ +# define RBIMPL_HAS_ATTRIBUTE(_) ((RBIMPL_HAS_ATTRIBUTE_ ## _)+0) +# ifdef ALWAYS_INLINE +# define RBIMPL_HAS_ATTRIBUTE_always_inline 1 +# endif +# ifdef FUNC_CDECL +# define RBIMPL_HAS_ATTRIBUTE_cdecl 1 +# endif +# ifdef CONSTFUNC +# define RBIMPL_HAS_ATTRIBUTE_const 1 +# endif +# ifdef DEPRECATED +# define RBIMPL_HAS_ATTRIBUTE_deprecated 1 +# endif +# ifdef ERRORFUNC +# define RBIMPL_HAS_ATTRIBUTE_error 1 +# endif +# ifdef FUNC_FASTCALL +# define RBIMPL_HAS_ATTRIBUTE_fastcall 1 +# endif +# ifdef PUREFUNC +# define RBIMPL_HAS_ATTRIBUTE_pure 1 +# endif +# ifdef NO_ADDRESS_SAFETY_ANALYSIS +# define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis 1 +# endif +# ifdef NO_SANITIZE +# define RBIMPL_HAS_ATTRIBUTE_no_sanitize 1 +# endif +# ifdef NO_SANITIZE_ADDRESS +# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address 1 +# endif +# ifdef NOINLINE +# define RBIMPL_HAS_ATTRIBUTE_noinline 1 +# endif +# ifdef RBIMPL_FUNC_NONNULL +# define RBIMPL_HAS_ATTRIBUTE_nonnull 1 +# endif +# ifdef NORETURN +# define RBIMPL_HAS_ATTRIBUTE_noreturn 1 +# endif +# ifdef FUNC_OPTIMIZED +# define RBIMPL_HAS_ATTRIBUTE_optimize 1 +# endif +# ifdef FUNC_STDCALL +# define RBIMPL_HAS_ATTRIBUTE_stdcall 1 +# endif +# ifdef MAYBE_UNUSED +# define RBIMPL_HAS_ATTRIBUTE_unused 1 +# endif +# ifdef WARN_UNUSED_RESULT +# define RBIMPL_HAS_ATTRIBUTE_warn_unused_result 1 +# endif +# ifdef WARNINGFUNC +# define RBIMPL_HAS_ATTRIBUTE_warning 1 +# endif +# ifdef WEAK +# define RBIMPL_HAS_ATTRIBUTE_weak 1 +# endif +#endif + +#endif /* RBIMPL_HAS_ATTRIBUTE_H */ diff --git a/ruby/include/ruby/internal/has/builtin.h b/ruby/include/ruby/internal/has/builtin.h new file mode 100644 index 000000000..957aff837 --- /dev/null +++ b/ruby/include/ruby/internal/has/builtin.h @@ -0,0 +1,119 @@ +#ifndef RBIMPL_HAS_BUILTIN_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_BUILTIN_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_BUILTIN. + */ +#include "ruby/internal/config.h" +#include "ruby/internal/compiler_since.h" + +#if defined(__has_builtin) +# if RBIMPL_COMPILER_IS(Intel) +# /* :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 RBIMPL_COMPILER_IS(GCC) && ! __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 RBIMPL_HAVE___HAS_BUILTIN 1 +# endif +#endif + +/** Wraps (or simulates) `__has_builtin`. */ +#if defined(RBIMPL_HAVE___HAS_BUILTIN) +# define RBIMPL_HAS_BUILTIN(_) __has_builtin(_) + +#elif RBIMPL_COMPILER_IS(GCC) +# /* :FIXME: Historically GCC has had tons of builtins, but it implemented +# * __has_builtin only since GCC 10. This section can be made more +# * granular. */ +# /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */ +# define RBIMPL_HAS_BUILTIN(_) (RBIMPL_HAS_BUILTIN_ ## _) +# define RBIMPL_HAS_BUILTIN___builtin_add_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_alloca RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) +# define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align RBIMPL_COMPILER_SINCE(GCC, 6, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_assume 0 +# /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */ +# define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) +# define RBIMPL_HAS_BUILTIN___builtin_bswap32 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_bswap64 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_clz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_clzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_clzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_constant_p RBIMPL_COMPILER_SINCE(GCC, 2,95, 3) +# define RBIMPL_HAS_BUILTIN___builtin_ctz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_ctzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_ctzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_expect RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) +# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) +# define RBIMPL_HAS_BUILTIN___builtin_popcount RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_popcountl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_popcountll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) +# define RBIMPL_HAS_BUILTIN___builtin_rotateleft32 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateleft64 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateright32 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 +# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) +# /* Note that "0, 0, 0" might be inaccurate. */ + +#elif RBIMPL_COMPILER_IS(MSVC) +# /* MSVC has UNREACHABLE, but that is not __builtin_unreachable. */ +# define RBIMPL_HAS_BUILTIN(_) 0 + +#else +# /* Take config.h definition when available */ +# define RBIMPL_HAS_BUILTIN(_) ((RBIMPL_HAS_BUILTIN_ ## _)+0) +# define RBIMPL_HAS_BUILTIN___builtin_add_overflow HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW +# define RBIMPL_HAS_BUILTIN___builtin_alloca 0 +# define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN +# define RBIMPL_HAS_BUILTIN___builtin_assume 0 +# define RBIMPL_HAS_BUILTIN___builtin_assume_aligned HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED +# define RBIMPL_HAS_BUILTIN___builtin_bswap16 HAVE_BUILTIN___BUILTIN_BSWAP16 +# define RBIMPL_HAS_BUILTIN___builtin_bswap32 HAVE_BUILTIN___BUILTIN_BSWAP32 +# define RBIMPL_HAS_BUILTIN___builtin_bswap64 HAVE_BUILTIN___BUILTIN_BSWAP64 +# define RBIMPL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ +# define RBIMPL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL +# define RBIMPL_HAS_BUILTIN___builtin_clzll HAVE_BUILTIN___BUILTIN_CLZLL +# define RBIMPL_HAS_BUILTIN___builtin_constant_p HAVE_BUILTIN___BUILTIN_CONSTANT_P +# define RBIMPL_HAS_BUILTIN___builtin_ctz HAVE_BUILTIN___BUILTIN_CTZ +# define RBIMPL_HAS_BUILTIN___builtin_ctzl 0 +# define RBIMPL_HAS_BUILTIN___builtin_ctzll HAVE_BUILTIN___BUILTIN_CTZLL +# define RBIMPL_HAS_BUILTIN___builtin_expect HAVE_BUILTIN___BUILTIN_EXPECT +# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW +# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P +# define RBIMPL_HAS_BUILTIN___builtin_popcount HAVE_BUILTIN___BUILTIN_POPCOUNT +# define RBIMPL_HAS_BUILTIN___builtin_popcountl 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateleft32 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateleft64 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateright32 0 +# define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 +# define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL +# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW +# if defined(UNREACHABLE) +# define RBIMPL_HAS_BUILTIN___builtin_unreachable 1 +# else +# define RBIMPL_HAS_BUILTIN___builtin_unreachable 0 +# endif +#endif + +#endif /* RBIMPL_HAS_BUILTIN_H */ diff --git a/ruby/include/ruby/internal/has/c_attribute.h b/ruby/include/ruby/internal/has/c_attribute.h new file mode 100644 index 000000000..c5c48867b --- /dev/null +++ b/ruby/include/ruby/internal/has/c_attribute.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_HAS_C_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_C_ATTRIBUTE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_C_ATTRIBUTE. + */ + +/** Wraps (or simulates) `__has_c_attribute`. */ +#if defined(__cplusplus) +# /* Makes no sense. */ +# define RBIMPL_HAS_C_ATTRIBUTE(_) 0 + +#elif defined(__has_c_attribute) +# define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) + +#else +# /* As of writing everything that lacks __has_c_attribute also completely +# * lacks C2x attributes as well. Might change in future? */ +# define RBIMPL_HAS_C_ATTRIBUTE(_) 0 +#endif + +#endif /* RBIMPL_HAS_C_ATTRIBUTE_H */ diff --git a/ruby/include/ruby/internal/has/cpp_attribute.h b/ruby/include/ruby/internal/has/cpp_attribute.h new file mode 100644 index 000000000..6a393b1a2 --- /dev/null +++ b/ruby/include/ruby/internal/has/cpp_attribute.h @@ -0,0 +1,86 @@ +#ifndef RBIMPL_HAS_CPP_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_CPP_ATTRIBUTE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_CPP_ATTRIBUTE. + */ +#include "ruby/internal/compiler_is.h" +#include "ruby/internal/compiler_since.h" + +/** @cond INTERNAL_MACRO */ +#if RBIMPL_COMPILER_IS(SunPro) +# /* Oracle Developer Studio 12.5's C++ preprocessor is reportedly broken. We +# * could simulate __has_cpp_attribute like below, but don't know the exact +# * list of which version supported which attribute. Just kill everything for +# * now. If you can please :FIXME: */ +# /* https://unicode-org.atlassian.net/browse/ICU-12893 */ +# /* https://github.com/boostorg/config/pull/95 */ +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 + +#elif defined(__has_cpp_attribute) +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) __has_cpp_attribute(_) + +#elif RBIMPL_COMPILER_IS(MSVC) +# /* MSVC has never updated its __cplusplus since forever (unless specified +# * explicitly by a compiler flag). They also lack __has_cpp_attribute until +# * 2019. However, they do have attributes since 2015 or so. */ +# /* https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance */ +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_carries_dependency 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_fallthrough 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_maybe_unused 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_nodiscard 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) + +#elif RBIMPL_COMPILER_BEFORE(Clang, 3, 6, 0) +# /* Clang 3.6.0 introduced __has_cpp_attribute. Prior to that following +# * attributes were already there. */ +# /* https://clang.llvm.org/cxx_status.html */ +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(Clang, 3, 3, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(Clang, 3, 4, 0) + +#elif RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) +# /* GCC 5+ have __has_cpp_attribute, while 4.x had following attributes. */ +# /* https://gcc.gnu.org/projects/cxx-status.html */ +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) +# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) + +#else +# /* :FIXME: +# * Candidate compilers to list here: +# * - icpc: They have __INTEL_CXX11_MODE__. +# */ +# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 +#endif +/** @endcond */ + +/** Wraps (or simulates) `__has_cpp_attribute`. */ +#if ! defined(__cplusplus) +# /* Makes no sense. */ +# define RBIMPL_HAS_CPP_ATTRIBUTE(_) 0 +#else +# /* GCC needs workarounds. See https://gcc.godbolt.org/z/jdz3pa */ +# define RBIMPL_HAS_CPP_ATTRIBUTE(_) \ + ((RBIMPL_HAS_CPP_ATTRIBUTE0(_) <= __cplusplus) ? RBIMPL_HAS_CPP_ATTRIBUTE0(_) : 0) +#endif + +#endif /* RBIMPL_HAS_CPP_ATTRIBUTE_H */ diff --git a/ruby/include/ruby/internal/has/declspec_attribute.h b/ruby/include/ruby/internal/has/declspec_attribute.h new file mode 100644 index 000000000..1c526daf7 --- /dev/null +++ b/ruby/include/ruby/internal/has/declspec_attribute.h @@ -0,0 +1,47 @@ +#ifndef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_DECLSPEC_ATTRIBUTE. + */ +#include "ruby/internal/compiler_since.h" + +/** Wraps (or simulates) `__has_declspec_attribute`. */ +#if defined(__has_declspec_attribute) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) __has_declspec_attribute(_) +#else +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) (RBIMPL_HAS_DECLSPEC_ATTRIBUTE_ ## _) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_align RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_empty_bases RBIMPL_COMPILER_SINCE(MSVC,19, 0, 23918) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noalias RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(MSVC,11, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) +# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_restrict RBIMPL_COMPILER_SINCE(MSVC,14, 0, 0) +# /* Note that "8, 0, 0" might be inaccurate. */ +# if ! defined(__cplusplus) +# /* Clang has this in both C/C++, but MSVC has this in C++ only.*/ +# undef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow +# endif +#endif + +#endif /* RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H */ diff --git a/ruby/include/ruby/internal/has/extension.h b/ruby/include/ruby/internal/has/extension.h new file mode 100644 index 000000000..da8c0d3cc --- /dev/null +++ b/ruby/include/ruby/internal/has/extension.h @@ -0,0 +1,33 @@ +#ifndef RBIMPL_HAS_EXTENSION_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_EXTENSION_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_EXTENSION. + */ +#include "ruby/internal/has/feature.h" + +/** Wraps (or simulates) `__has_extension`. */ +#if defined(__has_extension) +# define RBIMPL_HAS_EXTENSION(_) __has_extension(_) +#else +# /* Pre-3.0 clang had __has_feature but not __has_extension. */ +# define RBIMPL_HAS_EXTENSION(_) RBIMPL_HAS_FEATURE(_) +#endif + +#endif /* RBIMPL_HAS_EXTENSION_H */ diff --git a/ruby/include/ruby/internal/has/feature.h b/ruby/include/ruby/internal/has/feature.h new file mode 100644 index 000000000..7be8d2731 --- /dev/null +++ b/ruby/include/ruby/internal/has/feature.h @@ -0,0 +1,31 @@ +#ifndef RBIMPL_HAS_FEATURE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_FEATURE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_FEATURE. + */ + +/** Wraps (or simulates) `__has_feature`. */ +#if defined(__has_feature) +# define RBIMPL_HAS_FEATURE(_) __has_feature(_) +#else +# define RBIMPL_HAS_FEATURE(_) 0 +#endif + +#endif /* RBIMPL_HAS_FEATURE_H */ diff --git a/ruby/include/ruby/internal/has/warning.h b/ruby/include/ruby/internal/has/warning.h new file mode 100644 index 000000000..12d7db183 --- /dev/null +++ b/ruby/include/ruby/internal/has/warning.h @@ -0,0 +1,31 @@ +#ifndef RBIMPL_HAS_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_HAS_WARNING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_HAS_WARNING. + */ + +/** Wraps (or simulates) `__has_warning`. */ +#if defined(__has_warning) +# define RBIMPL_HAS_WARNING(_) __has_warning(_) +#else +# define RBIMPL_HAS_WARNING(_) 0 +#endif + +#endif /* RBIMPL_HAS_WARNING_H */ diff --git a/ruby/include/ruby/internal/intern/array.h b/ruby/include/ruby/internal/intern/array.h new file mode 100644 index 000000000..17964bf81 --- /dev/null +++ b/ruby/include/ruby/internal/intern/array.h @@ -0,0 +1,657 @@ +#ifndef RBIMPL_INTERN_ARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_ARRAY_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cArray. + */ +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/noexcept.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* array.c */ + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_NOALIAS() +/** + * Fills the memory region with a series of ::RUBY_Qnil. + * + * @param[out] buf Buffer to squash. + * @param[in] len Number of objects of `buf`. + * @post `buf` is filled with ::RUBY_Qnil. + */ +void rb_mem_clear(VALUE *buf, long len) + RBIMPL_ATTR_NOEXCEPT(true) + ; + +/** + * Identical to rb_ary_new_from_values(), except it expects exactly two + * parameters. + * + * @param[in] car Arbitrary ruby object. + * @param[in] cdr Arbitrary ruby object. + * @return An allocated new array, of length 2, whose contents are the + * passed objects. + */ +VALUE rb_assoc_new(VALUE car, VALUE cdr); + +/** + * Try converting an object to its array representation using its `to_ary` + * method, if any. If there is no such thing, returns ::RUBY_Qnil. + * + * @param[in] obj Arbitrary ruby object to convert. + * @exception rb_eTypeError `obj.to_ary` returned something non-Array. + * @retval RUBY_Qnil No conversion from `obj` to array defined. + * @retval otherwise Converted array representation of `obj`. + * @see rb_io_check_io + * @see rb_check_string_type + * @see rb_check_hash_type + */ +VALUE rb_check_array_type(VALUE obj); + +/** + * Allocates a new, empty array. + * + * @return An allocated new array, whose length is 0. + */ +VALUE rb_ary_new(void); + +/** + * Identical to rb_ary_new(), except it additionally specifies how many rooms + * of objects it should allocate. This way you can create an array whose + * capacity is bigger than the length of it. If you can say that an array + * grows to a specific amount, this could be effective than resizing an array + * over and over again and again. + * + * @param[in] capa Designed capacity of the generating array. + * @return An empty array, whose capacity is `capa`. + */ +VALUE rb_ary_new_capa(long capa); + +/** + * Constructs an array from the passed objects. + * + * @param[in] n Number of passed objects. + * @param[in] ... Arbitrary ruby objects, filled into the returning array. + * @return An array of size `n`, whose contents are the passed objects. + */ +VALUE rb_ary_new_from_args(long n, ...); + +/** + * Identical to rb_ary_new_from_args(), except how objects are passed. + * + * @param[in] n Number of objects of `elts`. + * @param[in] elts Arbitrary ruby objects, filled into the returning array. + * @return An array of size `n`, whose contents are the passed objects. + */ +VALUE rb_ary_new_from_values(long n, const VALUE *elts); + +/** + * Allocates a "temporary" array. This is a hidden empty array. Handy on + * occasions. + * + * @param[in] capa Designed capacity of the array. + * @return A hidden, empty array. + * @see rb_obj_hide() + */ +VALUE rb_ary_tmp_new(long capa); + +/** + * Destroys the given array for no reason. + * + * @warning DO NOT USE IT. + * @warning Leave this task to our GC. + * @warning It was a wrong indea at the first place to let you know about it. + * + * @param[out] ary The array to be executed. + * @post The given array no longer exists. + * @note Maybe `Array#clear` could be what you want. + * + * @internal + * + * Should have moved this to `internal/array.h`. + */ +void rb_ary_free(VALUE ary); + +/** + * Declares that the array is about to be modified. This for instance let the + * array have a dedicated backend storage. + * + * @param[out] ary Array about to be modified. + * @exception rb_eFrozenError `ary` is frozen. + * @post Upon successful return the passed array is eligible to be + * modified. + */ +void rb_ary_modify(VALUE ary); + +/** @alias{rb_obj_freeze} */ +VALUE rb_ary_freeze(VALUE obj); + +RBIMPL_ATTR_PURE() +/** + * Queries if the passed two arrays share the same backend storage. A use-case + * for knowing such property is to take a snapshot of an array (using + * e.g. rb_ary_replace()), then check later if that snapshot still shares the + * storage with the original. Taking a snapshot is ultra-cheap. If nothing + * happens the impact shall be minimal. But if someone modifies the original, + * that entity shall pay the cost of copy-on-write. You can detect that using + * this API. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval RUBY_Qtrue They share the same backend storage. + * @retval RUBY_Qfalse They are distinct. + * @pre Both arguments must be of ::RUBY_T_ARRAY. + */ +VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs); + +/** + * Queries element(s) of an array. This is complicated! Refer `Array#slice` + * document for the complete description of how it behaves. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Up to 2 objects. + * @param[in] ary Target array. + * @exception rb_eTypeError `argv` (or its part) includes non-Integer. + * @exception rb_eRangeError rb_cArithSeq is passed, and is OOB. + * @return An element (if requested), or an array of elements (if + * requested), or ::RUBY_Qnil (if index OOB). + * + * @internal + * + * ```rbs + * # "int" is ::Integer or `#to_int`, defined in builtin.rbs + * + * class ::Array[unchecked out T] + * def slice + * : (int i) -> T? + * | (int beg, int len) -> ::Array[T]? + * | (Range[int] r) -> ::Array[T]? + * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RagneError. + * end + * ``` + */ +VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary); + +/** + * Obtains a part of the passed array. + * + * @param[in] ary Target array. + * @param[in] beg Subpart index. + * @param[in] len Requested length of returning array. + * @retval RUBY_Qnil Requested range out of bounds of `ary`. + * @retval otherwise An allocated new array whose contents are `ary`'s + * `beg` to `len`. + * @note Return array can be shorter than `len` when for instance + * `[0, 1, 2, 3]`'s 4th to 1,000,000,000th is requested. + */ +VALUE rb_ary_subseq(VALUE ary, long beg, long len); + +/** + * Destructively stores the passed value to the passed array's passed index. + * It also resizes the array's backend storage so that the requested index is + * not out of bounds. + * + * @param[out] ary Target array to modify. + * @param[in] key Where to store `val`. + * @param[in] val What to store at `key`. + * @exception rb_eFrozenError `ary` is frozen. + * @exception rb_eIndexError `key` is negative. + * @post `ary`'s `key`th position is occupied with `val`. + * @post Depending on `key` and previous length of `ary` this operation + * can also create a series of "hole" positions inside of the + * backend storage. They are filled with ::RUBY_Qnil. + */ +void rb_ary_store(VALUE ary, long key, VALUE val); + +/** + * Duplicates an array. + * + * @param[in] ary Target to duplicate. + * @return An allocated new array whose contents are identical to `ary`. + * + * @internal + * + * Not sure why this has to be something different from `ary_make_shared_copy`, + * which seems much efficient. + */ +VALUE rb_ary_dup(VALUE ary); + +/** + * I guess there is no use case of this function in extension libraries, but + * this is a routine identical to rb_ary_dup(). This makes the most sense when + * the passed array is formerly hidden by rb_obj_hide(). + * + * @param[in] ary An array, possibly hidden. + * @return A duplicated new instance of ::rb_cArray. + */ +VALUE rb_ary_resurrect(VALUE ary); + +/** + * Force converts an object to an array. It first tries its `#to_ary` method. + * Takes the result if any. Otherwise creates an array of size 1 whose sole + * element is the passed object. + * + * @param[in] obj Arbitrary ruby object. + * @return An array representation of `obj`. + * @note Unlike rb_str_to_str() which is a variant of + * rb_check_string_type(), rb_ary_to_ary() is not a variant of + * rb_check_array_type(). + */ +VALUE rb_ary_to_ary(VALUE obj); + +/** + * Converts an array into a human-readable string. Historically its behaviour + * changed over time. Currently it is identical to calling `inspect` method. + * This behaviour is from that of python (!!) circa 2006. + * + * @param[in] ary Array to inspect. + * @return Recursively inspected representation of `ary`. + * @see `[ruby-dev:29520]` + */ +VALUE rb_ary_to_s(VALUE ary); + +/** + * Destructively appends multiple elements at the end of the array. + * + * @param[out] ary Where to push `train`. + * @param[in] train Arbitrary ruby objects to push to `ary`. + * @param[in] len Number of objects of `train`. + * @exception rb_eIndexError `len` too large. + * @exception rb_eFrozenError `ary` is frozen. + * @return The passed `ary`. + * @post `ary` has contents from `train` appended at its end. + */ +VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len); + +/** + * Special case of rb_ary_cat() that it adds only one element. + * + * @param[out] ary Where to push `elem`. + * @param[in] elem Arbitrary ruby object to push. + * @exception rb_eFrozenError `ary` is frozen. + * @return The passed `ary`. + * @post `ary` has `elem` appended at its end. + */ +VALUE rb_ary_push(VALUE ary, VALUE elem); + +/** + * Destructively deletes an element from the end of the passed array and + * returns what was deleted. + * + * @param[out] ary Target array to modify. + * @exception rb_eFrozenError `ary` is frozen. + * @return What was at the end of `ary`, or ::RUBY_Qnil if there is + * nothing to remove. + * @post `ary`'s last element, if any, is removed. + * @note There is no way to distinguish whether `ary` was an 1-element + * array whose content was ::RUBY_Qnil, or was empty. + */ +VALUE rb_ary_pop(VALUE ary); + +/** + * Destructively deletes an element from the beginning of the passed array and + * returns what was deleted. It can also be seen as a routine identical to + * rb_ary_pop(), except which side of the array to scrub. + * + * @param[out] ary Target array to modify. + * @exception rb_eFrozenError `ary` is frozen. + * @return What was at the beginning of `ary`, or ::RUBY_Qnil if there is + * nothing to remove. + * @post `ary`'s first element, if any, is removed. As the name implies + * everything else remaining in `ary` gets moved towards `ary`'s + * beginning. + * @note There is no way to distinguish whether `ary` was an 1-element + * array whose content was ::RUBY_Qnil, or was empty. + */ +VALUE rb_ary_shift(VALUE ary); + +/** + * Destructively prepends the passed item at the beginning of the passed array. + * It can also be seen as a routine identical to rb_ary_push(), except which + * side of the array to modify. + * + * @param[out] ary Target array to modify. + * @param[in] elem Arbitrary ruby object to unshift. + * @exception rb_eFrozenError `ary` is frozen. + * @return The passed `ary`. + * @post `ary` has `elem` prepended at this beginning. + */ +VALUE rb_ary_unshift(VALUE ary, VALUE elem); + +RBIMPL_ATTR_PURE() +/** + * Queries an element of an array. When passed offset is negative it counts + * backwards. + * + * @param[in] ary An array to look into. + * @param[in] off Offset (can be negative). + * @return ::RUBY_Qnil when `off` is out of bounds of `ary`. Otherwise + * what is stored at `off`-th position of `ary`. + * @note `ary`'s `off`-th element can happen to be ::RUBY_Qnil. + */ +VALUE rb_ary_entry(VALUE ary, long off); + +/** + * Iteratively yields each element of the passed array to the implicitly passed + * block if any. In case there is no block given, an enumerator that does the + * thing is generated instead. + * + * @param[in] ary Array to iterate over. + * @retval ary Passed block was evaluated. + * @retval otherwise An instance of ::rb_cEnumerator for `Array#each`. + */ +VALUE rb_ary_each(VALUE ary); + +/** + * Recursively stringises the elements of the passed array, flattens that + * result, then joins the sequence using the passed separator. + * + * @param[in] ary Target array to convert. + * @param[in] sep Separator. Either a string, or ::RUBY_Qnil + * if you want no separator. + * @exception rb_eArgError Infinite recursion in `ary`. + * @exception rb_eTypeError `sep` is not a string. + * @exception rb_eEncCompatError Strings do not agree with their encodings. + * @return An instance of ::rb_cString which concatenates stringised + * contents of `ary`, using `sep` as separator. + */ +VALUE rb_ary_join(VALUE ary, VALUE sep); + +/** + * _Destructively_ reverses the passed array in-place. + * + * @warning This is `Array#reverse!`, not `Array#reverse`. + * @param[out] ary Target array to modify. + * @exception rb_eFrozenError `ary` is frozen. + * @return Passed `ary`. + * @post `ary` is reversed. + */ +VALUE rb_ary_reverse(VALUE ary); + +/** + * _Destructively_ rotates the passed array in-place to towards its end. The + * amount can be negative. Would rotate to the opposite direction then. + * + * @warning This is `Array#rotate!`, not `Array#rotate`. + * @param[out] ary Target array to modify. + * @param[in] rot Amount of rotation. + * @exception rb_eFrozenError `ary` is frozen. + * @retval RUBY_Qnil Not rotated. + * @retval ary Rotated. + * @post `ary` is rotated. + */ +VALUE rb_ary_rotate(VALUE ary, long rot); + +/** + * Creates a copy of the passed array, whose elements are sorted according to + * their `<=>` result. + * + * @param[in] ary Array to sort. + * @exception rb_eArgError Comparison not defined among elements. + * @exception rb_eRuntimeError Infinite recursion in `<=>`. + * @return A copy of `ary`, sorted. + * @note As of writing this function uses `qsort` as backend algorithm, + * which means the result is unstable (in terms of sort stability). + */ +VALUE rb_ary_sort(VALUE ary); + +/** + * Destructively sorts the passed array in-place, according to each elements' + * `<=>` result. + * + * @param[in] ary Target array to modify. + * @exception rb_eArgError Comparison not defined among elements. + * @exception rb_eRuntimeError Infinite recursion in `<=>`. + * @return Passed `ary`. + * @post `ary` is sorted. + * @note As of writing this function uses `qsort` as backend algorithm, + * which means the result is unstable (in terms of sort stability). + */ +VALUE rb_ary_sort_bang(VALUE ary); + +/** + * Destructively removes elements from the passed array, so that there would be + * no elements inside that satisfy `==` relationship with the passed object. + * Returns the last deleted element if any. But in case there was nothing to + * delete it gets complicated. It checks for the implicitly passed block. If + * there is a block the return value would be what the block evaluates to. + * Otherwise it resorts to ::RUBY_Qnil. + * + * @param[out] ary Target array to modify. + * @param[in] elem Template object to match against each element. + * @exception rb_eFrozenError `ary` is frozen. + * @return What was deleted, or what was the block returned, or + * ::RUBY_Qnil (see above). + * @post All elements that have `==` relationship with `elem` are purged + * from `ary`. Elements shift their positions so that `ary` gets + * compact. + * + * @internal + * + * Internally there also is `rb_ary_delete_same`, which compares by identity. + */ +VALUE rb_ary_delete(VALUE ary, VALUE elem); + +/** + * Destructively removes an element which resides at the specific index of the + * passed array. Unlike rb_ary_stre() the index can be negative, which means + * the index counts backwards from the array's tail. + * + * @param[out] ary Target array to modify. + * @param[in] pos Position (can be negative). + * @exception rb_eFrozenError `ary` is frozen. + * @return What was deleted, or ::RUBY_Qnil in case of OOB. + * @post `ary`'s `pos`-th element is deleted if any. + * @note There is no way to distinguish whether `pos` is out of bound, + * or `pos` did exist but stored ::RUBY_Qnil as an ordinal value. + */ +VALUE rb_ary_delete_at(VALUE ary, long pos); + +/** + * Destructively removes everything form an array. + * + * @param[out] ary Target array to modify. + * @exception rb_eFrozenError `ary` is frozen. + * @return The passed `ary`. + * @post `ary` is an empty array. + */ +VALUE rb_ary_clear(VALUE ary); + +/** + * Creates a new array, concatenating the former to the latter. + * + * @param[in] lhs Source array #1. + * @param[in] rhs Source array #2. + * @exception rb_eIndexError Result array too big. + * @return A new array containing `rhs` concatenated to `lhs`. + * @note This operation doesn't commute. Don't get confused by the + * "plus" terminology. For historical reasons there are some + * noncommutative `+`s in Ruby. This is one of such things. There + * has been a long discussion around `+`s in programming languages. + * + * @internal + * + * rb_ary_concat() is not a destructive version of rb_ary_plus(). They raise + * different exceptions. Don't know why though. + */ +VALUE rb_ary_plus(VALUE lhs, VALUE rhs); + +/** + * Destructively appends the contents of latter into the end of former. + * + * @param[out] lhs Destination array. + * @param[in] rhs Source array. + * @exception rb_eFrozenError `lhs` is frozen. + * @exception rb_eIndexError Result array too big. + * @exception rb_eTypeError `rhs` doesn't respond to `#to_ary`. + * @return The passed `lhs`. + * @post `lhs` has contents of `rhs` appended to its end. + */ +VALUE rb_ary_concat(VALUE lhs, VALUE rhs); + +/** + * Looks up the passed key, assuming the passed array is an alist. An "alist" + * here is a list of "association"s, much like that of Emacs. Emacs has + * `assoc` function that behaves exactly the same as this one. + * + * ```ruby + * # This is an example of aliist. + * auto_mode_alist = [ + * [ /\.[ch]\z/, :"c-mode" ], + * [ /\.[ch]pp\z/, :"c++-mode" ], + * [ /\.awk\z/, :"awk-mode" ], + * [ /\.cs\z/, :"csharp-mode" ], + * [ /\.go\z/, :"go-mode" ], + * [ /\.java\z/, :"java-mode" ], + * [ /\.pas\z/, :"pascal-mode" ], + * [ /\.rs\z/, :"rust-mode" ], + * [ /\.txt\z/, :"text-mode" ], + * ] + * ``` + * + * This function scans the passed array looking for an element, which itself is + * an array, whose first element is the passed key. If no such element is + * found, returns ::RUBY_Qnil. + * + * Although this function expects the passed array be an array of arrays, it + * can happily accept non-array elements; it just ignores such things. + * + * @param[in] alist An array of arrays. + * @param[in] key Needle. + * @retval RUBY_Qnil Nothing was found. + * @retval otherwise An element in `alist` whose first element is in `==` + * relationship with `key`. + */ +VALUE rb_ary_assoc(VALUE alist, VALUE key); + +/** + * Identical to rb_ary_assoc(), except it scans the passed array from the + * opposite direction. + * + * @param[in] alist An array of arrays. + * @param[in] key Needle. + * @retval RUBY_Qnil Nothing was found. + * @retval otherwise An element in `alist` whose first element is in `==` + * relationship with `key`. + */ +VALUE rb_ary_rassoc(VALUE alist, VALUE key); + +/** + * Queries if the passed array has the passed entry. + * + * @param[in] ary Target array to scan. + * @param[in] elem Target array to find. + * @retval RUBY_Qfalse No element in `ary` is in `==` relationship with + * `elem`. + * @retval RUBY_Qtrue There is at least one element in `ary` which is in + * `==` relationship with `elem`. + * + * @internal + * + * This is the only function in the entire C API that is named using third + * person singular form of a verb (except #ISASCII etc., which are not our + * naming). The counterpart Ruby API of this function is `Array#include?`. + */ +VALUE rb_ary_includes(VALUE ary, VALUE elem); + +/** + * Recursively compares each elements of the two arrays one-by-one using `<=>`. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval RUBY_Qnil `lhs` and `rhs` are not comparable. + * @retval -1 `lhs` is less than `rhs`. + * @retval 0 They are equal. + * @retval 1 `rhs` is less then `lhs`. + */ +VALUE rb_ary_cmp(VALUE lhs, VALUE rhs); + +/** + * Replaces the contents of the former object with the contents of the latter. + * + * @param[out] copy Destination object. + * @param[in] orig Source object. + * @exception rb_eTypeError `orig` has no implicit conversion to Array. + * @exception rb_eFrozenError `copy` is frozen. + * @return The passed `copy`. + * @post `copy`'s former components are abandoned. It now has the + * identical length and contents to `orig`. + */ +VALUE rb_ary_replace(VALUE copy, VALUE orig); + +/** + * This _was_ a generalisation of `Array#values_at`, `Struct#values_at`, and + * `MatchData#values_at`. It begun its life as a refactoring effort. However + * as Ruby evolves over time, as of writing none of aforementioned methods + * share their implementations at all. This function is not deprecated; still + * works as it has been. But it is now kind of like a rudimentum. + * + * This function takes an object, which is a receiver, and a series of + * "indices", which are either integers, or ranges of integers. Calls the + * passed callback for each of those indices, along with the receiver. This + * callback is expected to do something like rb_ary_aref(), rb_struct_aref(), + * etc. In case of a range index rb_range_beg_len() expands the range. + * Finally return values of the callback are gathered as an array, then + * returned. + * + * @param[in] obj Arbitrary ruby object. + * @param[in] olen "Length" of `obj`. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv List of "indices", described above. + * @param[in] func Callback function. + * @return A new instance of ::rb_cArray gathering `func`outputs. + * + * @internal + * + * `Array#values_at` no longer uses this function. There is no reason apart + * from historical ones to list this function here. + */ +VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func)(VALUE obj, long oidx)); + +/** + * Expands or shrinks the passed array to the passed length. + * + * @param[out] ary An array to modify. + * @param[in] len Desired length of `ary`. + * @exception rb_eFrozenError `ary` is frozen. + * @exception rb_eIndexError `len` too long. + * @return The passed `ary`. + * @post `ary`'s length is `len`. + * @post Depending on `len` and previous length of `ary` this operation + * can also create a series of "hole" positions inside of the + * backend storage. They are filled with ::RUBY_Qnil. + * + * @internal + * + * `len` is signed. Intentional or...? + */ +VALUE rb_ary_resize(VALUE ary, long len); + +#define rb_ary_new2 rb_ary_new_capa /**< @old{rb_ary_new_capa} */ +#define rb_ary_new3 rb_ary_new_from_args /**< @old{rb_ary_new_from_args} */ +#define rb_ary_new4 rb_ary_new_from_values /**< @old{rb_ary_new_from_values} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_ARRAY_H */ diff --git a/ruby/include/ruby/internal/intern/bignum.h b/ruby/include/ruby/internal/intern/bignum.h new file mode 100644 index 000000000..43d68018d --- /dev/null +++ b/ruby/include/ruby/internal/intern/bignum.h @@ -0,0 +1,846 @@ +#ifndef RBIMPL_INTERN_BIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_BIGNUM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to so-called rb_cBignum. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/backward/2/long_long.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* bignum.c */ + +/** + * Allocates a bignum object. + * + * @param[in] len Length of the bignum's backend storage, in words. + * @param[in] sign Sign of the bignum. + * @return An allocated new bignum instance. + * @note This only allocates an object, doesn't fill its value in. + * + * @internal + * + * @shyouhei finds it hard to use from extension libraries. `len` is per + * `BDIGIT` but its definition is hidden. + */ +VALUE rb_big_new(size_t len, int sign); + +/** + * Queries if the passed bignum instance is a "bigzro". What is a bigzero? + * Well, bignums are for very big integers, but can also represent tiny ones + * like -1, 0, 1. Bigzero are instances of bignums whose values are zero. + * Knowing if a bignum is bigzero can be handy on occasions, like for instance + * detecting division by zero situation. + * + * @param[in] x A bignum. + * @retval 1 It is a bigzero. + * @retval 0 Otherwise. + */ +int rb_bigzero_p(VALUE x); + +/** + * Duplicates the given bignum. + * + * @param[in] num A bignum. + * @return An allocated bignum, who is equivalent to `num`. + */ +VALUE rb_big_clone(VALUE num); + +/** + * Destructively modify the passed bignum into 2's complement representation. + * + * @note By default bignums are in signed magnitude system. + * + * @param[out] num A bignum to modify. + */ +void rb_big_2comp(VALUE num); + +/** + * Normalises the passed bignum. It for instance returns a fixnum of the same + * value if fixnum can represent that number. + * + * @param[out] x Target bignum (can be destructively modified). + * @return An integer of the identical value (can be `x` itself). + */ +VALUE rb_big_norm(VALUE x); + +/** + * Destructively resizes the backend storage of the passed bignum. + * + * @param[out] big A bignum. + * @param[in] len New length of `big`'s backend, in words. + */ +void rb_big_resize(VALUE big, size_t len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Parses C's string to convert into a Ruby's integer. It understands prefixes + * (e.g. `0x`) and underscores. + * + * @param[in] str Stringised representation of the return value. + * @param[in] base Base of conversion. Must be `-36..36` inclusive, + * except `1`. `2..36` means the conversion is done + * according to it, with unmatched prefix understood + * as a part of the result. `-36..-2` means the + * conversion honours prefix when present, or use + * `-base` when absent. `0` is equivalent to `-10`. + * `-1` mandates a prefix. `1` is an error. + * @param[in] badcheck Whether to raise ::rb_eArgError on failure. If + * `0` is passed here this function can return + * `INT2FIX(0)` for parse errors. + * @exception rb_eArgError Failed to parse (and `badcheck` is truthy). + * @return An instance of ::rb_cInteger, which is a numeric interpretation + * of what is written in `str`. + * + * @internal + * + * Not sure if it intentionally accepts `base == -1` or is just buggy. Nobody + * practically uses negative bases these days. + */ +VALUE rb_cstr_to_inum(const char *str, int base, int badcheck); + +/** + * Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's. + * + * @param[in] str Stringised representation of the return + * value. + * @param[in] base Base of conversion. Must be `-36..36` + * inclusive, except `1`. `2..36` means the + * conversion is done according to it, with + * unmatched prefix understood as a part of the + * result. `-36..-2` means the conversion + * honours prefix when present, or use `-base` + * when absent. `0` is equivalent to `-10`. + * `-1` mandates a prefix. `1` is an error. + * @param[in] badcheck Whether to raise ::rb_eArgError on failure. + * If `0` is passed here this function can + * return `INT2FIX(0)` for parse errors. + * @exception rb_eArgError Failed to parse (and `badcheck` is truthy). + * @exception rb_eTypeError `str` is not a string. + * @exception rb_eEncCompatError `str` is not ASCII compatible. + * @return An instance of ::rb_cInteger, which is a numeric interpretation + * of what is written in `str`. + */ +VALUE rb_str_to_inum(VALUE str, int base, int badcheck); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_cstr_to_inum(), except the second argument controls the base + * and badcheck at once. It basically doesn't raise for parse errors, unless + * the base is zero. + * + * This is an older API. New codes might prefer rb_cstr_to_inum(). + * + * @param[in] str Stringised representation of the return value. + * @param[in] base Base of conversion. Must be `-36..36` inclusive, + * except `1`. `2..36` means the conversion is done + * according to it, with unmatched prefix understood + * as a part of the result. `-36..-2` means the + * conversion honours prefix when present, or use + * `-base` when absent. `0` is equivalent to `-10`. + * `-1` mandates a prefix. `1` is an error. + * @exception rb_eArgError Failed to parse (and `base` is zero). + * @return An instance of ::rb_cInteger, which is a numeric interpretation + * of what is written in `str`. + */ +VALUE rb_cstr2inum(const char *str, int base); + +/** + * Identical to rb_str_to_inum(), except the second argument controls the base + * and badcheck at once. It can also be seen as a routine identical to + * rb_cstr2inum(), except it takes Ruby's strings instead of C's. + * + * This is an older API. New codes might prefer rb_cstr_to_inum(). + * + * @param[in] str Stringised representation of the return + * value. + * @param[in] base Base of conversion. Must be `-36..36` + * inclusive, except `1`. `2..36` means the + * conversion is done according to it, with + * unmatched prefix understood as a part of the + * result. `-36..-2` means the conversion + * honours prefix when present, or use `-base` + * when absent. `0` is equivalent to `-10`. + * `-1` mandates a prefix. `1` is an error. + * @exception rb_eArgError Failed to parse (and `base` is zero). + * @exception rb_eTypeError `str` is not a string. + * @exception rb_eEncCompatError `str` is not ASCII compatible. + * @return An instance of ::rb_cInteger, which is a numeric interpretation + * of what is written in `str`. + */ +VALUE rb_str2inum(VALUE str, int base); + +/** + * Generates a place-value representation of the passed integer. + * + * @param[in] x An integer to stringify. + * @param[in] base `2` to `36` inclusive for each radix. + * @exception rb_eArgError `base` is out of range. + * @exception rb_eRangeError `x` is too big, cannot represent in string. + * @return An instance of ::rb_cString which represents `x`. + */ +VALUE rb_big2str(VALUE x, int base); + +/** + * Converts a bignum into C's `long`. + * + * @param[in] x A bignum. + * @exception rb_eRangeError `x` is out of range of `long`. + * @return The passed value converted into C's `long`. + */ +long rb_big2long(VALUE x); + +/** @alias{rb_big2long} */ +#define rb_big2int(x) rb_big2long(x) + +/** + * Converts a bignum into C's `unsigned long`. + * + * @param[in] x A bignum. + * @exception rb_eRangeError `x` is out of range of `unsigned long`. + * @return The passed value converted into C's `unsigned long`. + * + * @internal + * + * This function can generate a very large positive integer for a negative + * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this + * function yields C's 13,835,058,055,282,163,711 on my machine. This is how + * it has been. Cannot change any longer. + */ +unsigned long rb_big2ulong(VALUE x); + +/** @alias{rb_big2long} */ +#define rb_big2uint(x) rb_big2ulong(x) + +#if HAVE_LONG_LONG +/** + * Converts a bignum into C's `long long`. + * + * @param[in] x A bignum. + * @exception rb_eRangeError `x` is out of range of `long long`. + * @return The passed value converted into C's `long long`. + */ +LONG_LONG rb_big2ll(VALUE); + +/** + * Converts a bignum into C's `unsigned long long`. + * + * @param[in] x A bignum. + * @exception rb_eRangeError `x` is out of range of `unsigned long long`. + * @return The passed value converted into C's `unsigned long long`. + * + * @internal + * + * This function can generate a very large positive integer for a negative + * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this + * function yields C's 13,835,058,055,282,163,711 on my machine. This is how + * it has been. Cannot change any longer. + */ +unsigned LONG_LONG rb_big2ull(VALUE); + +#endif /* HAVE_LONG_LONG */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Converts a bignum into a series of its parts. + * + * @param[in] val An integer. + * @param[out] buf Return buffer. + * @param[in] num_longs Number of words of `buf`. + * @exception rb_eTypeError `val` doesn't respond to `#to_int`. + * @post `buf` is filled with `val`'s 2's complement representation, in + * the host CPU's native byte order, from least significant word + * towards the most significant one, for `num_longs` words. + * @note The "pack" terminology comes from `Array#pack`. + */ +void rb_big_pack(VALUE val, unsigned long *buf, long num_longs); + +RBIMPL_ATTR_NONNULL(()) +/** + * Constructs a (possibly very big) bignum from a series of integers. `buf[0]` + * would be the return value's least significant word; `buf[num_longs-1]` would + * be that of most significant. + * + * @param[in] buf A series of integers. + * @param[in] num_longs Number of words of `buf`. + * @exception rb_eArgError Result would be too big. + * @return An instance of ::rb_cInteger which is an "unpack"-ed value of + * the parameters. + * @note The "unpack" terminology comes from `String#pack`. + */ +VALUE rb_big_unpack(unsigned long *buf, long num_longs); + +/* pack.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Encodes a Unicode codepoint into its UTF-8 representation. + * + * @param[out] buf Return buffer, must at least be 6 bytes width. + * @param[in] uv An Unicode codepoint. + * @exception rb_eRangeError `uv` is out of Unicode. + * @return Number of bytes written to `buf` + * @post `buf` holds a UTF-8 representation of `uv`. + */ +int rb_uv_to_utf8(char buf[6], unsigned long uv); + +/* bignum.c */ + +/** + * Converts a C's `double` into a bignum. + * + * @param[in] d A value to convert. + * @exception rb_eFloatDomainError `d` is Inf/NaN. + * @return An instance of ::rb_cInteger whose value is approximately `d`. + * + * @internal + * + * @shyouhei is not sure if the result is guaranteed to be the nearest integer + * of `d`. + */ +VALUE rb_dbl2big(double d); + +/** + * Converts a bignum into C's `double`. + * + * @param[in] x A bignum. + * @return The passed value converted into C's `double`. + * + * @internal + * + * @shyouhei is not sure if the result is guaranteed to be `x`'s nearest value + * that a `double` can represent. + */ +double rb_big2dbl(VALUE x); + +/** + * Compares the passed two bignums. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval -1 `rhs` is bigger than `lhs`. + * @retval 0 They are identical. + * @retval 1 `lhs` is bigger than `rhs`. + * @see rb_num_coerce_cmp() + */ +VALUE rb_big_cmp(VALUE lhs, VALUE rhs); + +/** + * Equality, in terms of `==`. This checks if the _value_ is the same, not the + * identity. For instance `1 == 1.0` must hold. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval RUBY_Qtrue They are the same. + * @retval RUBY_Qfalse They are different. + */ +VALUE rb_big_eq(VALUE lhs, VALUE rhs); + +/** + * Equality, in terms of `eql?`. Unlike rb_big_eq() it does not convert + * ::rb_cFloat etc. This function returns ::RUBY_Qtrue if and only if both + * parameters are bignums, which represent the identical numerical value. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval RUBY_Qtrue They are identical. + * @retval RUBY_Qfalse They are distinct. + */ +VALUE rb_big_eql(VALUE lhs, VALUE rhs); + +/** + * Performs addition of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x + y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_plus(VALUE x, VALUE y); + +/** + * Performs subtraction of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x - y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_minus(VALUE x, VALUE y); + +/** + * Performs multiplication of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x * y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_mul(VALUE x, VALUE y); + +/** + * Performs division of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x / y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_div(VALUE x, VALUE y); + +/** + * Performs "integer division". This is different from rb_big_div(). + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x.div y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_idiv(VALUE x, VALUE y); + +/** + * Performs modulo of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x % y` evaluates to. + * @see rb_num_coerce_bin() + * + * @internal + * + * There also is `rb_big_remainder()` internally, which is different from this + * one. + */ +VALUE rb_big_modulo(VALUE x, VALUE y); + +/** + * Performs "divmod" operation. The operation in bignum's context is that it + * calculates rb_big_idiv() and rb_big_modulo() at once. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x.divmod y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_big_divmod(VALUE x, VALUE y); + +/** + * Raises `x` to the powerof `y`. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x ** y` evaluates to. + * @see rb_num_coerce_bin() + * @note This can return an instance of ::rb_cFloat, even when both `x` + * and `y` are bignums. Or an instance of ::rb_cRational, when for + * instance `y` is negative. + */ +VALUE rb_big_pow(VALUE x, VALUE y); + +/** + * Performs bitwise and of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x & y` evaluates to. + * @see rb_num_coerce_bit() + */ +VALUE rb_big_and(VALUE x, VALUE y); + +/** + * Performs bitwise or of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x | y` evaluates to. + * @see rb_num_coerce_bit() + */ +VALUE rb_big_or(VALUE x, VALUE y); + +/** + * Performs exclusive or of the passed two objects. + * + * @param[in] x A bignum. + * @param[in] y Arbitrary ruby object. + * @return What `x ^ y` evaluates to. + * @see rb_num_coerce_bit() + */ +VALUE rb_big_xor(VALUE x, VALUE y); + +/** + * Performs shift left. + * + * @param[in] x A bignum. + * @param[in] y Shift amount. + * @exception rb_eTypeError `y` is not an integer. + * @exception rb_eArgError `y` is too big. + * @return `x` shifted left to `y` bits. + * @note `y` can be negative. Shifts right then. + */ +VALUE rb_big_lshift(VALUE x, VALUE y); + +/** + * Performs shift right. + * + * @param[in] x A bignum. + * @param[in] y Shift amount. + * @exception rb_eTypeError `y` is not an integer. + * @return `x` shifted right to `y` bits. + * @note This is arithmetic. Because bignums are not bitfields there is + * no shift right logical operator. + */ +VALUE rb_big_rshift(VALUE x, VALUE y); + +/** + * @name Flags for rb_integer_pack()/rb_integer_unpack() + * @{ + */ + +/** Stores/interprets the most significant word as the first word. */ +#define INTEGER_PACK_MSWORD_FIRST 0x01 + +/** Stores/interprets the least significant word as the first word. */ +#define INTEGER_PACK_LSWORD_FIRST 0x02 + +/** + * Stores/interprets the most significant byte in a word as the first byte in + * the word. + */ +#define INTEGER_PACK_MSBYTE_FIRST 0x10 + +/** + * Stores/interprets the least significant byte in a word as the first byte in + * the word. + */ +#define INTEGER_PACK_LSBYTE_FIRST 0x20 + +/** + * Means either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST, + * depending on the host processor's endian. + */ +#define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40 + +/** Uses 2's complement representation. */ +#define INTEGER_PACK_2COMP 0x80 + +/** Uses "generic" implementation (handy on test). */ +#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400 + +/** + * Always generates a bignum object even if the integer can be representable + * using fixnum scheme (unpack only) + */ +#define INTEGER_PACK_FORCE_BIGNUM 0x100 + +/** + * Interprets the input as a signed negative number (unpack only). If not + * specified returns a positive number. + */ +#define INTEGER_PACK_NEGATIVE 0x200 + +/** Little endian combination. */ +#define INTEGER_PACK_LITTLE_ENDIAN \ + (INTEGER_PACK_LSWORD_FIRST | \ + INTEGER_PACK_LSBYTE_FIRST) + +/** Big endian combination */ +#define INTEGER_PACK_BIG_ENDIAN \ + (INTEGER_PACK_MSWORD_FIRST | \ + INTEGER_PACK_MSBYTE_FIRST) + +/** @} */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Exports an integer into a buffer. This function fills the buffer specified + * by `words` and `numwords` as `val` in the format specified by `wordsize`, + * `nails` and `flags`. + * + * @param[in] val Integer or integer-like object which has + * `#to_int` method. + * @param[out] words Return buffer. + * @param[in] numwords Number of words of `words`. + * @param[in] wordsize Number of bytes per word. + * @param[in] nails Number of padding bits in a word. Most + * significant nails bits of each word are filled + * by zero. + * @param[in] flags Bitwise or of constants whose name starts + * "INTEGER_PACK_". + * @exception rb_eTypeError `val` doesn't respond to `#to_int`. + * + * Possible flags are: + * + * - #INTEGER_PACK_MSWORD_FIRST: + * Stores the most significant word as the first word. + * + * - #INTEGER_PACK_LSWORD_FIRST: + * Stores the least significant word as the first word. + * + * - #INTEGER_PACK_MSBYTE_FIRST: + * Stores the most significant byte in a word as the first byte in the + * word. + * + * - #INTEGER_PACK_LSBYTE_FIRST: + * Stores the least significant byte in a word as the first byte in the + * word. + * + * - #INTEGER_PACK_NATIVE_BYTE_ORDER: + * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST + * corresponding to the host's endian. + * + * - #INTEGER_PACK_2COMP: + * Uses 2's complement representation. + * + * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of + * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST`. + * + * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of + * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST`. + * + * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION: + * Uses generic implementation (for test and debug). + * + * This function fills the buffer specified by `words` as `val`'s 2's + * complement representation if #INTEGER_PACK_2COMP is specified in `flags`. + * Otherwise it fills `words` as `abs(val)` and signedness is returned via the + * return value. + * + * @return The signedness and overflow condition. The overflow condition + * depends on #INTEGER_PACK_2COMP. + * + * When #INTEGER_PACK_2COMP is not specified: + * + * - `-2` : + * Negative overflow. `val <= -2**(numwords*(wordsize*CHAR_BIT-nails))` + * + * - `-1` : + * Negative without overflow. + * `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0` + * + * - `0` : zero. `val == 0` + * + * - `1` : + * Positive without overflow. + * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))` + * + * - `2` : + * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val` + * + * When #INTEGER_PACK_2COMP is specified: + * + * - `-2` : + * Negative overflow. `val < -2**(numwords*(wordsize*CHAR_BIT-nails))` + * + * - `-1` : + * Negative without overflow. + * `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0` + * + * - `0` : zero. `val == 0` + * + * - `1` : + * Positive without overflow. + * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))` + * + * - `2` : + * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val` + * + * The value, `-2**(numwords*(wordsize*CHAR_BIT-nails))`, is representable in + * 2's complement representation but not representable in absolute value. So + * `-1` is returned for the value if #INTEGER_PACK_2COMP is specified but + * returns `-2` if #INTEGER_PACK_2COMP is not specified. + * + * The least significant words are filled in the buffer when overflow occur. + */ +int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); + +RBIMPL_ATTR_NONNULL(()) +/** + * Import an integer from a buffer. + * + * @param[in] words Buffer to import. + * @param[in] numwords Number of words of `words`. + * @param[in] wordsize Number of bytes per word. + * @param[in] nails Number of padding bits in a word. Most + * significant nails bits of each word are ignored. + * @param[in] flags Bitwise or of constants whose name starts + * "INTEGER_PACK_". + * @exception rb_eArgError `numwords * wordsize` too big. + * + * Possible flags are: + * + * - #INTEGER_PACK_MSWORD_FIRST: + * Interpret the first word as the most significant word. + * + * - #INTEGER_PACK_LSWORD_FIRST: + * Interpret the first word as the least significant word. + * + * - #INTEGER_PACK_MSBYTE_FIRST: + * Interpret the first byte in a word as the most significant byte in the + * word. + * + * - #INTEGER_PACK_LSBYTE_FIRST: + * Interpret the first byte in a word as the least significant byte in + * the word. + * + * - #INTEGER_PACK_NATIVE_BYTE_ORDER: + * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST + * corresponding to the host's endian. + * + * - #INTEGER_PACK_2COMP: + * Uses 2's complement representation. + * + * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of + * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST` + * + * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of + * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST` + * + * - #INTEGER_PACK_FORCE_BIGNUM: + * Returns a bignum even if its value is representable as a fixnum. + * + * - #INTEGER_PACK_NEGATIVE: + * Returns a non-positive value. (Returns a non-negative value if not + * specified.) + * + * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION: + * Uses generic implementation (for test and debug). + * + * @return An instance of ::rb_cInteger whose value is the interpreted + * `words`. The range of the result value depends on + * #INTEGER_PACK_2COMP and #INTEGER_PACK_NEGATIVE. + * + * When #INTEGER_PACK_2COMP is not set: + * + * - `0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails))` if + * `!INTEGER_PACK_NEGATIVE` + * + * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0` if + * `INTEGER_PACK_NEGATIVE` + * + * When #INTEGER_PACK_2COMP is set: + * + * - `-2**(numwords*(wordsize*CHAR_BIT-nails)-1)` `<= val <=` + * `2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1` if + * `!INTEGER_PACK_NEGATIVE` + * + * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1` if + * `INTEGER_PACK_NEGATIVE` + * + * Passing #INTEGER_PACK_2COMP without #INTEGER_PACK_NEGATIVE means sign + * extension. #INTEGER_PACK_2COMP with #INTEGER_PACK_NEGATIVE means assuming + * the higher bits are `1`. + * + * Note that this function returns 0 when `numwords` is zero and + * #INTEGER_PACK_2COMP is set but #INTEGER_PACK_NEGATIVE is not set. + */ +VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); + +/** + * Calculates the number of bytes needed to represent the absolute value of the + * passed integer. + * + * @param[in] val Integer or integer-like object which has + * `#to_int` method. + * @param[out] nlz_bits_ret Number of leading zero bits in the most + * significant byte is returned if not `NULL`. + * @exception rb_eTypeError `val` doesn't respond to `#to_int`. + * @return `((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)`, where + * val_numbits is the number of bits of `abs(val)`. + * @post If `nlz_bits_ret` is not `NULL`, + * `(return_value * CHAR_BIT - val_numbits)` is stored in + * `*nlz_bits_ret`. In this case, + * `0 <= *nlz_bits_ret < CHAR_BIT`. + * + * This function should not overflow. + */ +size_t rb_absint_size(VALUE val, int *nlz_bits_ret); + +/** + * Calculates the number of words needed represent the absolute value of the + * passed integer. Unlike rb_absint_size() this function can overflow. It + * returns `(size_t)-1` then. + * + * @param[in] val Integer or integer-like object which has + * `#to_int` method. + * @param[in] word_numbits Number of bits per word. + * @param[out] nlz_bits_ret Number of leading zero bits in the most + * significant word is returned if not `NULL`. + * @exception rb_eTypeError `val` doesn't respond to `#to_int`. + * @retval (size_t)-1 Overflowed. + * @retval otherwise + `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, + * where val_numbits is the number of bits of `abs(val)`. + * @post If `nlz_bits_ret` is not `NULL` and there is no overflow, + * `(return_value * word_numbits - val_numbits)` is stored in + * `*nlz_bits_ret`. In this case, + * `0 <= *nlz_bits_ret < word_numbits.` + * + */ +size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); + +/** + * Tests `abs(val)` consists only of a bit or not. + * + * @param[in] val Integer or integer-like object which has + * `#to_int` method. + * @exception rb_eTypeError `val` doesn't respond to `#to_int`. + * @retval 1 `abs(val) == 1 << n` for some `n >= 0`. + * @retval 0 Otherwise. + * + * rb_absint_singlebit_p() can be used to determine required buffer size for + * rb_integer_pack() used with #INTEGER_PACK_2COMP (two's complement). + * + * Following example calculates number of bits required to represent val in + * two's complement number, without sign bit. + * + * ```CXX + * size_t size; + * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); + * size = rb_absint_numwords(val, 1, NULL) + * if (size == (size_t)-1) ...overflow... + * if (neg && rb_absint_singlebit_p(val)) + * size--; + * ``` + * + * Following example calculates number of bytes required to represent val in + * two's complement number, with sign bit. + * + * ```CXX + * size_t size; + * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); + * int nlz_bits; + * size = rb_absint_size(val, &nlz_bits); + * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val))) + * size++; + * ``` + */ +int rb_absint_singlebit_p(VALUE val); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_BIGNUM_H */ diff --git a/ruby/include/ruby/internal/intern/class.h b/ruby/include/ruby/internal/intern/class.h new file mode 100644 index 000000000..2181ab93c --- /dev/null +++ b/ruby/include/ruby/internal/intern/class.h @@ -0,0 +1,382 @@ +#ifndef RBIMPL_INTERN_CLASS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_CLASS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cClass/::rb_cModule. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/backward/2/stdarg.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* class.c */ + +/** + * Creates a new, anonymous class. + * + * @param[in] super What would become a parent class. + * @exception rb_eTypeError `super` is not something inheritable. + * @return An anonymous class that inherits `super`. + */ +VALUE rb_class_new(VALUE super); + +/** + * The comment that comes with this function says `:nodoc:`. Not sure what + * that means though. + * + * @param[out] clone Destination object. + * @param[in] orig Source object. + * @exception rb_eTypeError Cannot copy `orig`. + * @return The passed `clone`. + */ +VALUE rb_mod_init_copy(VALUE clone, VALUE orig); + +/** + * Asserts that the given class can derive a child class. A class might or + * might not be able to do so; for instance a singleton class cannot. + * + * @param[in] super Possible super class. + * @exception rb_eTypeError No it cannot. + * @post Upon successful return `super` can derive. + */ +void rb_check_inheritable(VALUE super); + +/** + * This is a very badly designed API that creates an anonymous class. + * + * @param[in] id Discarded for no reason (why...). + * @param[in] super What would become a parent class. 0 means + * ::rb_cObject. + * @exception rb_eTypeError `super` is not something inheritable. + * @return An anonymous class that inherits `super`. + * @warning You must explicitly name the return value. + */ +VALUE rb_define_class_id(ID id, VALUE super); + +/** + * Identical to rb_define_class_under(), except it takes the name in ::ID + * instead of C's string. + * + * @param[out] outer A class which contains the new class. + * @param[in] id Name of the new class + * @param[in] super A class from which the new class will derive. + * 0 means ::rb_cObject. + * @exception rb_eTypeError The constant name `id` is already taken but the + * constant is not a class. + * @exception rb_eTypeError The class is already defined but the class can + * not be reopened because its superclass is not + * `super`. + * @exception rb_eArgError `super` is NULL. + * @return The created class. + * @post `outer::id` refers the returned class. + * @note If a class named `id` is already defined and its superclass is + * `super`, the function just returns the defined class. + * @note The compaction GC does not move classes returned by this + * function. + */ +VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super); + +/** + * Creates a new, anonymous module. + * + * @return An anonymous module. + */ +VALUE rb_module_new(void); + + +/** + * Creates a new, anonymous refinement. + * + * @return An anonymous refinement. + */ +VALUE rb_refinement_new(void); + +/** + * This is a very badly designed API that creates an anonymous module. + * + * @param[in] id Discarded for no reason (why...). + * @return An anonymous module. + * @warning You must explicitly name the return value. + */ +VALUE rb_define_module_id(ID id); + +/** + * Identical to rb_define_module_under(), except it takes the name in ::ID + * instead of C's string. + * + * @param[out] outer A class which contains the new module. + * @param[in] id Name of the new module + * @exception rb_eTypeError The constant name `id` is already taken but the + * constant is not a module. + * @return The created module. + * @post `outer::id` refers the returned module. + * @note The compaction GC does not move classes returned by this + * function. + */ +VALUE rb_define_module_id_under(VALUE outer, ID id); + +/** + * Queries the list of included modules. It can also be seen as a routine to + * first call rb_mod_ancestors(), then rejects non-modules from the return + * value. + * + * @param[in] mod Class or Module. + * @return An array of modules that are either included or prepended in any + * of `mod`'s ancestry tree (including itself). + */ +VALUE rb_mod_included_modules(VALUE mod); + +/** + * Queries if the passed module is included by the module. It can also be seen + * as a routine to first call rb_mod_included_modules(), then see if the return + * value contains the passed module. + * + * @param[in] child A Module. + * @param[in] parent Another Module. + * @exception rb_eTypeError `child` is not an instance of ::rb_cModule. + * @retval RUBY_Qtrue `parent` is either included or prepended in any + * of `child`'s ancestry tree (including itself). + * @return RUBY_Qfalse Otherwise. + */ +VALUE rb_mod_include_p(VALUE child, VALUE parent); + +/** + * Queries the module's ancestors. This routine gathers classes and modules + * that the passed module either inherits, includes, or prepends, then + * recursively applies that routine again and again to the collected entries + * until the list doesn't grow up. + * + * @param[in] mod A module or a class. + * @return An array of classes or modules that `mod` possibly recursively + * inherits, includes, or prepends. + * + * @internal + * + * Above description is written in a recursive language but in practice it + * computes the return value iteratively. + */ +VALUE rb_mod_ancestors(VALUE mod); + +/** + * Queries the class's descendants. This routine gathers classes that are + * subclasses of the given class (or subclasses of those subclasses, etc.), + * returning an array of classes that have the given class as an ancestor. + * The returned array does not include the given class or singleton classes. + * + * @param[in] klass A class. + * @return An array of classes where `klass` is an ancestor. + * + * @internal + */ +VALUE rb_class_descendants(VALUE klass); + +/** + * Queries the class's direct descendants. This routine gathers classes that are + * direct subclasses of the given class, + * returning an array of classes that have the given class as a superclass. + * The returned array does not include singleton classes. + * + * @param[in] klass A class. + * @return An array of classes where `klass` is the `superclass`. + * + * @internal + */ +VALUE rb_class_subclasses(VALUE klass); + +/** + * Generates an array of symbols, which are the list of method names defined in + * the passed class. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Array of at most one object, which controls (if + * any) whether the return array includes the names + * of methods defined in ancestors or not. + * @param[in] mod A module or a class. + * @exception rb_eArgError `argc` out of range. + * @return An array of symbols collecting names of instance methods that + * are not private, defined at `mod`. + */ +VALUE rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod); + +/** + * Identical to rb_class_instance_methods(), except it returns names of methods + * that are public only. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Array of at most one object, which controls (if + * any) whether the return array includes the names + * of methods defined in ancestors or not. + * @param[in] mod A module or a class. + * @exception rb_eArgError `argc` out of range. + * @return An array of symbols collecting names of instance methods that + * are public, defined at `mod`. + */ +VALUE rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod); + +/** + * Identical to rb_class_instance_methods(), except it returns names of methods + * that are protected only. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Array of at most one object, which controls (if + * any) whether the return array includes the names + * of methods defined in ancestors or not. + * @param[in] mod A module or a class. + * @exception rb_eArgError `argc` out of range. + * @return An array of symbols collecting names of instance methods that + * are protected, defined at `mod`. + */ +VALUE rb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod); + +/** + * Identical to rb_class_instance_methods(), except it returns names of methods + * that are private only. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Array of at most one object, which controls (if + * any) whether the return array includes the names + * of methods defined in ancestors or not. + * @param[in] mod A module or a class. + * @exception rb_eArgError `argc` out of range. + * @return An array of symbols collecting names of instance methods that + * are protected, defined at `mod`. + */ +VALUE rb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod); + +/** + * Identical to rb_class_instance_methods(), except it returns names of + * singleton methods instead of instance methods. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Array of at most one object, which controls (if + * any) whether the return array includes the names + * of methods defined in ancestors or not. + * @param[in] obj Arbitrary ruby object. + * @exception rb_eArgError `argc` out of range. + * @return An array of symbols collecting names of instance methods that + * are not private, defined at the singleton class of `obj`. + */ +VALUE rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj); + +/** + * Identical to rb_define_method(), except it takes the name of the method in + * ::ID instead of C's string. + * + * @param[out] klass A module or a class. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method_id + */ +void rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int arity); + +/* vm_method.c */ + +/** + * Inserts a method entry that hides previous method definition of the given + * name. This is not a deletion of a method. Method of the same name defined + * in a parent class is kept invisible in this way. + * + * @param[out] mod The module to insert an undef. + * @param[in] mid Name of the undef. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError No such method named `klass#name`. + * @post `klass#name` is undefined. + * @see rb_undef_method + * + * @internal + * + * @shyouhei doesn't understand why this is not the ::ID -taking variant of + * rb_undef_method(), given rb_remove_method() has its ::ID -taking counterpart + * named rb_remove_method_id(). + */ +void rb_undef(VALUE mod, ID mid); + +/* class.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_define_method(), except it defines a protected method. + * + * @param[out] klass A module or a class. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method + */ +void rb_define_protected_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_define_method(), except it defines a private method. + * + * @param[out] klass A module or a class. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method + */ +void rb_define_private_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_define_method(), except it defines a singleton method. + * + * @param[out] obj Arbitrary ruby object. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_singleton_method + */ +void rb_define_singleton_method(VALUE obj, const char *mid, VALUE(*func)(ANYARGS), int arity); + +/** + * Finds or creates the singleton class of the passed object. + * + * @param[out] obj Arbitrary ruby object. + * @exception rb_eTypeError `obj` cannot have its singleton class. + * @return A (possibly newly allocated) instance of ::rb_cClass. + * @post `obj` has its singleton class, which is the return value. + * @post In case `obj` is a class, the returned singleton class also has + * its own singleton class in order to keep consistency of the + * inheritance structure of metaclasses. + * @note A new singleton class will be created if `obj` did not have + * one. + * @note The singleton classes for ::RUBY_Qnil, ::RUBY_Qtrue, and + * ::RUBY_Qfalse are ::rb_cNilClass, ::rb_cTrueClass, and + * ::rb_cFalseClass respectively. + * + * @internal + * + * You can _create_ a singleton class of a frozen object. Intentional or ...? + * + * Nowadays there are wider range of objects who cannot have singleton classes + * than before. For instance some string instances cannot for some reason. + */ +VALUE rb_singleton_class(VALUE obj); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_CLASS_H */ diff --git a/ruby/include/ruby/internal/intern/compar.h b/ruby/include/ruby/internal/intern/compar.h new file mode 100644 index 000000000..dc3b377b0 --- /dev/null +++ b/ruby/include/ruby/internal/intern/compar.h @@ -0,0 +1,62 @@ +#ifndef RBIMPL_INTERN_COMPAR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_COMPAR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_mComparable. + */ +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* bignum.c */ + +/** + * Canonicalises the passed `val`, which is the return value of `a <=> b`, into + * C's `{-1, 0, 1}`. This can be handy when you implement a callback function + * to pass to `qsort(3)` etc. + * + * @param[in] val Return value of a space ship operator. + * @param[in] a Comparison LHS. + * @param[in] b Comparison RHS. + * @exception rb_eArgError `a` and `b` are not comparable each other. + * @retval -1 `val` is less than zero. + * @retval 0 `val` is equal to zero. + * @retval 1 `val` is greater than zero. + */ +int rb_cmpint(VALUE val, VALUE a, VALUE b); + +/* compar.c */ + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NORETURN() +/** + * Raises "comparison failed" error. + * + * @param[in] a Comparison LHS. + * @param[in] b Comparison RHS. + * @exception rb_eArgError `a` and `b` are not comparable each other. + */ +void rb_cmperr(VALUE a, VALUE b); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_COMPAR_H */ diff --git a/ruby/include/ruby/internal/intern/complex.h b/ruby/include/ruby/internal/intern/complex.h new file mode 100644 index 000000000..e111bd8ce --- /dev/null +++ b/ruby/include/ruby/internal/intern/complex.h @@ -0,0 +1,253 @@ +#ifndef RBIMPL_INTERN_COMPLEX_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_COMPLEX_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cComplex. + */ +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* complex.c */ + +/** + * Identical to rb_complex_new(), except it assumes both arguments are not + * instances of ::rb_cComplex. It is thus dangerous for extension libraries. + * + * @param[in] real Real part, in any numeric except Complex. + * @param[in] imag Imaginary part, in any numeric except Complex. + * @return An instance of ::rb_cComplex whose value is `real + (imag)i`. + */ +VALUE rb_complex_raw(VALUE real, VALUE imag); + +/** + * Shorthand of `x+0i`. It practically converts `x` into a Complex of the + * identical value. + * + * @param[in] x Any numeric except Complex. + * @return An instance of ::rb_cComplex, whose value is `x + 0i`. + */ +#define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0)) + +/** @alias{rb_complex_raw} */ +#define rb_complex_raw2(x,y) rb_complex_raw((x), (y)) + +/** + * Constructs a Complex, by first multiplying the imaginary part with `1i` then + * adds it to the real part. This definition doesn't need both arguments be + * real numbers. It can happily combine two instances of ::rb_cComplex (with + * rotating the latter one). + * + * @param[in] real An instance of ::rb_cNumeric. + * @param[in] imag Another instance of ::rb_cNumeric. + * @return An instance of ::rb_cComplex whose value is `imag * 1i + real`. + */ +VALUE rb_complex_new(VALUE real, VALUE imag); + +/** + * Shorthand of `x+0i`. It practically converts `x` into a Complex of the + * identical value. + * + * @param[in] x Any numeric value. + * @return An instance of ::rb_cComplex, whose value is `x + 0i`. + */ +#define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0)) + +/** @alias{rb_complex_new} */ +#define rb_complex_new2(x,y) rb_complex_new((x), (y)) + +/** + * Constructs a Complex using polar representations. Unlike rb_complex_new() + * it makes no sense to pass non-real instances to this function. + * + * @param[in] abs Magnitude, in any numeric except Complex. + * @param[in] arg Angle, in radians, in any numeric except Complex. + * @return An instance of ::rb_cComplex which denotes the given polar + * coordinates. + */ +VALUE rb_complex_new_polar(VALUE abs, VALUE arg); + +RBIMPL_ATTR_DEPRECATED(("by: rb_complex_new_polar")) +/** @old{rb_complex_new_polar} */ +VALUE rb_complex_polar(VALUE abs, VALUE arg); + +RBIMPL_ATTR_PURE() +/** + * Queries the real part of the passed Complex. + * + * @param[in] z An instance of ::rb_cComplex. + * @return Its real part, which is an instance of ::rb_cNumeric. + */ +VALUE rb_complex_real(VALUE z); + +RBIMPL_ATTR_PURE() +/** + * Queries the imaginary part of the passed Complex. + * + * @param[in] z An instance of ::rb_cComplex. + * @return Its imaginary part, which is an instance of ::rb_cNumeric. + */ +VALUE rb_complex_imag(VALUE z); + +/** + * Performs addition of the passed two objects. + * + * @param[in] x An instance of ::rb_cComplex. + * @param[in] y Arbitrary ruby object. + * @return What `x + y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_complex_plus(VALUE x, VALUE y); + +/** + * Performs subtraction of the passed two objects. + * + * @param[in] x An instance of ::rb_cComplex. + * @param[in] y Arbitrary ruby object. + * @return What `x - y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_complex_minus(VALUE x, VALUE y); + +/** + * Performs multiplication of the passed two objects. + * + * @param[in] x An instance of ::rb_cComplex. + * @param[in] y Arbitrary ruby object. + * @return What `x * y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_complex_mul(VALUE x, VALUE y); + +/** + * Performs division of the passed two objects. + * + * @param[in] x An instance of ::rb_cComplex. + * @param[in] y Arbitrary ruby object. + * @return What `x / y` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_complex_div(VALUE x, VALUE y); + +/** + * Performs negation of the passed object. + * + * @param[in] z An instance of ::rb_cComplex. + * @return What `-z` evaluates to. + */ +VALUE rb_complex_uminus(VALUE z); + +/** + * Performs complex conjugation of the passed object. + * + * @param[in] z An instance of ::rb_cComplex. + * @return Its complex conjugate, in ::rb_cComplex. + */ +VALUE rb_complex_conjugate(VALUE z); + +/** + * Queries the absolute (or the magnitude) of the passed object. + * + * @param[in] z An instance of ::rb_cComplex. + * @return Its magnitude, in ::rb_cFloat. + */ +VALUE rb_complex_abs(VALUE z); + +/** + * Queries the argument (or the angle) of the passed object. + * + * @param[in] z An instance of ::rb_cComplex. + * @return Its magnitude, in ::rb_cFloat. + */ +VALUE rb_complex_arg(VALUE z); + +/** + * Performs exponentiation of the passed two objects. + * + * @param[in] base An instance of ::rb_cComplex. + * @param[in] exp Arbitrary ruby object. + * @return What `base ** exp` evaluates to. + * @see rb_num_coerce_bin() + */ +VALUE rb_complex_pow(VALUE base, VALUE exp); + +/** + * Identical to rb_complex_new(), except it takes the arguments as C's double + * instead of Ruby's object. + * + * @param[in] real Real part. + * @param[in] imag Imaginary part. + * @return An instance of ::rb_cComplex whose value is `real + (imag)i`. + */ +VALUE rb_dbl_complex_new(double real, double imag); + +/** @alias{rb_complex_plus} */ +#define rb_complex_add rb_complex_plus + +/** @alias{rb_complex_minus} */ +#define rb_complex_sub rb_complex_minus + +/** @alias{rb_complex_uminus} */ +#define rb_complex_nagate rb_complex_uminus + +/** + * Converts various values into a Complex. This function accepts: + * + * - Instances of ::rb_cComplex (taken as-is), + * - Instances of ::rb_cNumeric (adds `0i`), + * - Instances of ::rb_cString (parses), + * - Other objects that respond to `#to_c`. + * + * It (possibly recursively) applies `#to_c` until both sides become a Complex + * value, then computes `imag * 1i + real`. + * + * As a special case, passing ::RUBY_Qundef to `imag` is the same as passing + * `RB_INT2NUM(0)`. + * + * @param[in] real Real part (see above). + * @param[in] imag Imaginary part (see above). + * @exception rb_eTypeError Passed something not described above. + * @return An instance of ::rb_cComplex whose value is `1i * imag + real`. + * + * @internal + * + * This was the implementation of `Kernel#Complex` before, but they diverged. + */ +VALUE rb_Complex(VALUE real, VALUE imag); + +/** + * Shorthand of `x+0i`. It practically converts `x` into a Complex of the + * identical value. + * + * @param[in] x ::rb_cNumeric, ::rb_cString, or something that responds to + * `#to_c`. + * @return An instance of ::rb_cComplex, whose value is `x + 0i`. + */ +#define rb_Complex1(x) rb_Complex((x), INT2FIX(0)) + +/** @alias{rb_Complex} */ +#define rb_Complex2(x,y) rb_Complex((x), (y)) + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_COMPLEX_H */ diff --git a/ruby/include/ruby/internal/intern/cont.h b/ruby/include/ruby/internal/intern/cont.h new file mode 100644 index 000000000..37493009f --- /dev/null +++ b/ruby/include/ruby/internal/intern/cont.h @@ -0,0 +1,260 @@ +#ifndef RBIMPL_INTERN_CONT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_CONT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to rb_cFiber. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/iterator.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* cont.c */ + +/** + * Creates a Fiber instance from a C-backended block. + * + * @param[in] func A function, to become the fiber's body. + * @param[in] callback_obj Passed as-is to `func`. + * @return An allocated new instance of rb_cFiber, which is ready to be + * "resume"d. + */ +VALUE rb_fiber_new(rb_block_call_func_t func, VALUE callback_obj); + +/** + * Queries the fiber which is calling this function. Any ruby execution + * context has its fiber, either explicitly or implicitly. + * + * @return The current fiber. + */ +VALUE rb_fiber_current(void); + +/** + * Queries the liveness of the passed fiber. "Alive" in this context means + * that the fiber can still be resumed. Once it reaches is its end of + * execution, this function returns ::RUBY_Qfalse. + * + * @param[in] fiber A target fiber. + * @retval RUBY_Qtrue It is. + * @retval RUBY_Qfalse It isn't. + */ +VALUE rb_fiber_alive_p(VALUE fiber); + +/** + * Queries if an object is a fiber. + * + * @param[in] obj Arbitrary ruby object. + * @retval RUBY_Qtrue It is. + * @retval RUBY_Qfalse It isn't. + */ +VALUE rb_obj_is_fiber(VALUE obj); + +/** + * Resumes the execution of the passed fiber, either from the point at which + * the last rb_fiber_yield() was called if any, or at the beginning of the + * fiber body if it is the first call to this function. + * + * Other arguments are passed into the fiber's body, either as return values of + * rb_fiber_yield() in case it switches to there, or as the block parameter of + * the fiber body if it switches to the beginning of the fiber. + * + * The return value of this function is either the value passed to previous + * rb_fiber_yield() call, or the ultimate evaluated value of the entire fiber + * body if the execution reaches the end of it. + * + * When an exception happens inside of a fiber it propagates to this function. + * + * ```ruby + * f = Fiber.new do |i| + * puts " =>> #{i}" + * puts " <-- #{i + 1}" + * j = Fiber.yield(i + 1) + * puts " =>> #{j}" + * puts " <-- #{j + 1}" + * next j + 1 + * end + * + * puts "[a] <-- 1" + * p = f.resume(1) + * puts "[b] =>> #{p}" + * puts "[c] <-- #{p + 1}" + * q = f.resume(p + 1) + * puts "[d] =>> #{q}" + * ``` + * + * Above program executes in `[a] [b] [c] [d]`. + * + * @param[out] fiber The fiber to resume. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed (somehow) to `fiber`. + * @exception rb_eFiberError `fib` is terminated etc. + * @exception rb_eException Any exceptions happen in `fiber`. + * @return (See above) + * @note This function _does_ return. + * + * @internal + * + * @shyouhei expected this function to raise ::rb_eFrozenError for frozen + * fibers but it doesn't in practice. Intentional or ...? + */ +VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv); + +/** + * Identical to rb_fiber_resume(), except you can specify how to handle the + * last element of the given array. + * + * @param[out] fiber The fiber to resume. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed (somehow) to `fiber`. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eFiberError `fiber` is terminated etc. + * @exception rb_eException Any exceptions happen in `fiber`. + * @return Either what was yielded or the last value of the fiber body. + */ +VALUE rb_fiber_resume_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat); + +/** + * Yields the control back to the point where the current fiber was resumed. + * The passed objects would be the return value of rb_fiber_resume(). This + * fiber then suspends its execution until next time it is resumed. + * + * This function can also raise arbitrary exceptions injected from outside of + * the fiber using rb_fiber_raise(). + * + * ```ruby + * exc = Class.new Exception + * + * f = Fiber.new do + * Fiber.yield + * rescue exc => e + * puts e.message + * end + * + * f.resume + * f.raise exc, "Hi!" + * ``` + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed to rb_fiber_resume(). + * @exception rb_eException (See above) + * @return (See rb_fiber_resume() for details) + */ +VALUE rb_fiber_yield(int argc, const VALUE *argv); + +/** + * Identical to rb_fiber_yield(), except you can specify how to handle the last + * element of the given array. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed to rb_fiber_resume(). + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eException What was raised using `Fiber#raise`. + * @return (See rb_fiber_resume() for details) + */ +VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat); + +/** + * Transfers control to another fiber, resuming it from where it last stopped + * or starting it if it was not resumed before. The calling fiber will be + * suspended much like in a call to rb_fiber_yield(). + * + * The fiber which receives the transfer call treats it much like a resume + * call. Arguments passed to transfer are treated like those passed to resume. + * + * The two style of control passing to and from fiber (one is rb_fiber_resume() + * and rb_fiber_yield(), another is rb_fiber_transfer() to and from fiber) + * can't be freely mixed. + * + * - If the Fiber's lifecycle had started with transfer, it will never be + * able to yield or be resumed control passing, only finish or transfer + * back. (It still can resume other fibers that are allowed to be + * resumed.) + * + * - If the Fiber's lifecycle had started with resume, it can yield or + * transfer to another Fiber, but can receive control back only the way + * compatible with the way it was given away: if it had transferred, it + * only can be transferred back, and if it had yielded, it only can be + * resumed back. After that, it again can transfer or yield. + * + * If those rules are broken, rb_eFiberError is raised. + * + * For an individual Fiber design, yield/resume is easier to use (the Fiber + * just gives away control, it doesn't need to think about who the control is + * given to), while transfer is more flexible for complex cases, allowing to + * build arbitrary graphs of Fibers dependent on each other. + * + * @param[out] fiber Explicit control destination. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed to rb_fiber_resume(). + * @exception rb_eFiberError (See above) + * @exception rb_eException What was raised using `Fiber#raise`. + * @return (See rb_fiber_resume() for details) + */ +VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv); + +/** + * Identical to rb_fiber_transfer(), except you can specify how to handle the + * last element of the given array. + * + * @param[out] fiber Explicit control destination. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed to rb_fiber_resume(). + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eFiberError (See above) + * @exception rb_eException What was raised using `Fiber#raise`. + * @return (See rb_fiber_resume() for details) + */ +VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat); + +/** + * Identical to rb_fiber_resume() but instead of resuming normal execution of + * the passed fiber, it raises the given exception in it. From inside of the + * fiber this would be seen as if rb_fiber_yield() raised. + * + * This function does return in case the passed fiber gracefully handled the + * passed exception. But if it does not, the raised exception propagates out + * of the passed fiber; this function then does not return. + * + * Parameters are passed to rb_make_exception() to create an exception object. + * See its document for what are allowed here. + * + * It is a failure to call this function against a fiber which is resuming, + * have never run yet, or has already finished running. + * + * @param[out] fiber Where exception is raised. + * @param[in] argc Passed as-is to rb_make_exception(). + * @param[in] argv Passed as-is to rb_make_exception(). + * @exception rb_eFiberError `fiber` is terminated etc. + * @return (See rb_fiber_resume() for details) + */ +VALUE rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_CONT_H */ diff --git a/ruby/include/ruby/internal/intern/dir.h b/ruby/include/ruby/internal/intern/dir.h new file mode 100644 index 000000000..da1873e06 --- /dev/null +++ b/ruby/include/ruby/internal/intern/dir.h @@ -0,0 +1,42 @@ +#ifndef RBIMPL_INTERN_DIR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_DIR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cDir. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* dir.c */ + +/** + * Queries the path of the current working directory of the current process. + * + * @return An instance of ::rb_cString that holds the working directory. + * @note The returned string is in "filesystem" encoding. Most notably on + * Linux this is an alias of default external encoding. Most notably + * on Windows it can be an alias of OS codepage. + */ +VALUE rb_dir_getwd(void); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_DIR_H */ diff --git a/ruby/include/ruby/internal/intern/enum.h b/ruby/include/ruby/internal/intern/enum.h new file mode 100644 index 000000000..215ad8267 --- /dev/null +++ b/ruby/include/ruby/internal/intern/enum.h @@ -0,0 +1,73 @@ +#ifndef RBIMPL_INTERN_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_ENUM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_mEnumerable. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* enum.c */ + +/** + * Basically identical to rb_ary_new_form_values(), except it returns something + * different when `argc` < 2. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary objects. + * @retval RUBY_Qnil `argc` is zero. + * @retval argv[0] `argc` is one. + * @retval otherwise Otherwise. + * + * @internal + * + * What is this business? Well, this function is about `yield`'s taking + * multiple values. Consider following user-defined class: + * + * ```ruby + * class Foo + * include Enumerable + * + * def each + * yield :q, :w, :e, :r + * end + * end + * + * Foo.new.each_with_object([]) do |i, j| + * j << i # ^^^ <- What to expect for `i`? + * end + * ``` + * + * Here, `Foo#each_with_object` is in fact `Enumerable#each_with_object`, which + * doesn't know what would be yielded. Yet, it has to take a block of arity 2. + * This function is used here, to "pack" arbitrary number of yielded objects + * into one. + * + * If people want to implement their own `Enumerable#each_with_object` this API + * can be handy. Though @shyouhei suspects it is relatively rare for 3rd party + * extension libraries to have such things. Also `Enumerable#each_entry` is + * basically this function exposed as a Ruby method. + */ +VALUE rb_enum_values_pack(int argc, const VALUE *argv); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_ENUM_H */ diff --git a/ruby/include/ruby/internal/intern/enumerator.h b/ruby/include/ruby/internal/intern/enumerator.h new file mode 100644 index 000000000..20e5d7c6f --- /dev/null +++ b/ruby/include/ruby/internal/intern/enumerator.h @@ -0,0 +1,259 @@ +#ifndef RBIMPL_INTERN_ENUMERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_ENUMERATOR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cEnumerator. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/intern/eval.h" /* rb_frame_this_func */ +#include "ruby/internal/iterator.h" /* rb_block_given_p */ +#include "ruby/internal/symbol.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * This is the type of functions that rb_enumeratorize_with_size() expects. In + * theory an enumerator can have indefinite number of elements, but in practice + * it often is the case we can compute the size of an enumerator beforehand. + * If your enumerator has such property, supply a function that calculates such + * values. + * + * @param[in] recv The original receiver of the enumerator. + * @param[in] argv Arguments passed to `Object#enum_for` etc. + * @param[in] eobj The enumerator object. + * @return The size of `eobj`, in ::rb_cNumeric, or ::RUBY_Qnil if the size + * is not known until we actually iterate. + */ +typedef VALUE rb_enumerator_size_func(VALUE recv, VALUE argv, VALUE eobj); + +/** + * Decomposed `Enumerator::ArithmeicSequence`. This is a subclass of + * ::rb_cEnumerator, which represents a sequence of numbers with common + * difference. Internal data structure of the class is opaque to users, but + * you can obtain a decomposed one using rb_arithmetic_sequence_extract(). + */ +typedef struct { + VALUE begin; /**< "Left" or "lowest" endpoint of the sequence. */ + VALUE end; /**< "Right" or "highest" endpoint of the sequence.*/ + VALUE step; /**< Step between a sequence. */ + int exclude_end; /**< Whether the endpoint is open or closed. */ +} rb_arithmetic_sequence_components_t; + +/* enumerator.c */ + +/** + * Constructs an enumerator. This roughly resembles `Object#enum_for`. + * + * @param[in] recv A receiver of `meth`. + * @param[in] meth Method ID in a symbol object. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to `meth`. + * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. + * @return A new instance of ::rb_cEnumerator which, when yielded, + * enumerates by calling `meth` on `recv` with `argv`. + */ +VALUE rb_enumeratorize(VALUE recv, VALUE meth, int argc, const VALUE *argv); + +/** + * Identical to rb_enumeratorize(), except you can additionally specify the + * size function of return value. + * + * @param[in] recv A receiver of `meth`. + * @param[in] meth Method ID in a symbol object. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to `meth`. + * @param[in] func Size calculator. + * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. + * @return A new instance of ::rb_cEnumerator which, when yielded, + * enumerates by calling `meth` on `recv` with `argv`. + * @note `func` can be zero, which means the size is unknown. + */ +VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func); + +/** + * Identical to rb_enumeratorize_with_func(), except you can specify how to + * handle the last element of the given array. + * + * @param[in] recv A receiver of `meth`. + * @param[in] meth Method ID in a symbol object. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to `meth`. + * @param[in] func Size calculator. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. + * @return A new instance of ::rb_cEnumerator which, when yielded, + * enumerates by calling `meth` on `recv` with `argv`. + * @note `func` can be zero, which means the size is unknown. + */ +VALUE rb_enumeratorize_with_size_kw(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func, int kw_splat); + +RBIMPL_ATTR_NONNULL(()) +/** + * Extracts components of the passed arithmetic sequence. This can be seen as + * an extended version of rb_range_values(). + * + * @param[in] as Target instance of `Enumerator::ArithmericSequence`. + * @param[out] buf Decomposed results buffer. + * @return 0 `as` is not `Enumerator::ArithmericSequence`. + * @return 1 Success. + * @post `buf` is filled. + */ +int rb_arithmetic_sequence_extract(VALUE as, rb_arithmetic_sequence_components_t *buf); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_range_beg_len(), except it takes an instance of + * `Enumerator::ArithmericSequence`. + * + * @param[in] as An `Enumerator::ArithmericSequence` instance. + * @param[out] begp Return value buffer. + * @param[out] lenp Return value buffer. + * @param[out] stepp Return value buffer. + * @param[in] len Updated length. + * @param[in] err In case `len` is out of range... + * - `0`: returns ::RUBY_Qnil. + * - `1`: raises ::rb_eRangeError. + * - `2`: `beg` and `len` expanded accordingly. + * @exception rb_eRangeError `as` cannot fit into `long`. + * @retval RUBY_Qfalse `as` is not `Enumerator::ArithmericSequence`. + * @retval RUBY_Qnil `len` is out of `as` but `err` is zero. + * @retval RUBY_Qtrue Otherwise. + * @post `beg` is the (possibly updated) left endpoint. + * @post `len` is the (possibly updated) length of the range. + * + * @internal + * + * Currently no 3rd party applications of this function is found. But that can + * be because this function is relatively new. + */ +VALUE rb_arithmetic_sequence_beg_len_step(VALUE as, long *begp, long *lenp, long *stepp, long len, int err); + +RBIMPL_SYMBOL_EXPORT_END() + +/** @cond INTERNAL_MACRO */ +#ifndef RUBY_EXPORT +# define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \ + rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn)) +# define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \ + rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat) +#endif +/** @endcond */ + +/** + * This is an implementation detail of #RETURN_SIZED_ENUMERATOR(). You could + * use it directly, but can hardly be handy. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @param[in] size_fn Size calculator. + * @return A new instance of ::rb_cEnumerator which, when yielded, + * enumerates by calling the current method on `recv` with `argv`. + */ +#define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \ + rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \ + (argc), (argv), (size_fn)) + +/** + * This is an implementation detail of #RETURN_SIZED_ENUMERATOR_KW(). You + * could use it directly, but can hardly be handy. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @param[in] size_fn Size calculator. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @return A new instance of ::rb_cEnumerator which, when yielded, + * enumerates by calling the current method on `recv` with `argv`. + */ +#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ + rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \ + (argc), (argv), (size_fn), (kw_splat)) + +/** + * This roughly resembles `return enum_for(__callee__) unless block_given?`. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @param[in] size_fn Size calculator. + * @note This macro may return inside. + */ +#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \ + if (!rb_block_given_p()) \ + return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ + } while (0) + + +/** + * Identical to #RETURN_SIZED_ENUMERATOR(), except you can specify how to + * handle the last element of the given array. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @param[in] size_fn Size calculator. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @note This macro may return inside. + */ +#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ + if (!rb_block_given_p()) \ + return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \ + } while (0) + +/** + * Identical to #RETURN_SIZED_ENUMERATOR(), except its size is unknown. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @note This macro may return inside. + */ +#define RETURN_ENUMERATOR(obj, argc, argv) \ + RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0) + +/** + * Identical to #RETURN_SIZED_ENUMERATOR_KW(), except its size is unknown. It + * can also be seen as a routine identical to #RETURN_ENUMERATOR(), except you + * can specify how to handle the last element of the given array. + * + * @param[in] obj A receiver. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to the current method. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @note This macro may return inside. + */ +#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \ + RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat) + +#endif /* RBIMPL_INTERN_ENUMERATOR_H */ diff --git a/ruby/include/ruby/internal/intern/error.h b/ruby/include/ruby/internal/intern/error.h new file mode 100644 index 000000000..37d3b8592 --- /dev/null +++ b/ruby/include/ruby/internal/intern/error.h @@ -0,0 +1,301 @@ +#ifndef RBIMPL_INTERN_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_ERROR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_eException. + */ +#include "ruby/internal/attr/format.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/fl_type.h" +#include "ruby/backward/2/assume.h" + +/** + * This macro is used in conjunction with rb_check_arity(). If you pass it to + * the function's last (max) argument, that means the function does not check + * upper limit. + */ +#define UNLIMITED_ARGUMENTS (-1) + +#define rb_exc_new2 rb_exc_new_cstr /**< @old{rb_exc_new_cstr} */ +#define rb_exc_new3 rb_exc_new_str /**< @old{rb_exc_new_str} */ + +/** @cond INTERNAL_MACRO */ +#define rb_check_trusted rb_check_trusted +#define rb_check_trusted_inline rb_check_trusted +#define rb_check_arity rb_check_arity +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* error.c */ + +/** + * Creates an instance of the passed exception class. + * + * @param[in] etype A subclass of ::rb_eException. + * @param[in] ptr Buffer contains error message. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eTypeError `etype` is not a class. + * @exception rb_eArgError `len` is negative. + * @return An instance of `etype`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + * + * @internal + * + * This function works for non-exception classes as well, as long as they take + * one string argument. + */ +VALUE rb_exc_new(VALUE etype, const char *ptr, long len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[in] etype A subclass of ::rb_eException. + * @param[in] str A C string (becomes an error message). + * @exception rb_eTypeError `etype` is not a class. + * @return An instance of `etype`. + */ +VALUE rb_exc_new_cstr(VALUE etype, const char *str); + +/** + * Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of + * C's. + * + * @param[in] etype A subclass of ::rb_eException. + * @param[in] str An instance of ::rb_cString. + * @exception rb_eTypeError `etype` is not a class. + * @return An instance of `etype`. + */ +VALUE rb_exc_new_str(VALUE etype, VALUE str); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Raises an instance of ::rb_eLoadError. + * + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eLoadError Always raises this. + * @note It never returns. + * + * @internal + * + * Who needs this? Except ruby itself? + */ +void rb_loaderror(const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_loaderror(), except it additionally takes which file is + * unable to load. The path can be obtained later using `LoadError#path` of + * the raising exception. + * + * @param[in] path What failed. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eLoadError Always raises this. + * @note It never returns. + */ +void rb_loaderror_with_path(VALUE path, const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Raises an instance of ::rb_eNameError. The name can be obtained later using + * `NameError#name` of the raising exception. + * + * @param[in] name What failed. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eNameError Always raises this. + * @note It never returns. + */ +void rb_name_error(ID name, const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_name_error(), except it takes a ::VALUE instead of ::ID. + * + * @param[in] name What failed. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eNameError Always raises this. + * @note It never returns. + */ +void rb_name_error_str(VALUE name, const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Raises an instance of ::rb_eFrozenError. The object can be obtained later + * using `FrozenError#receiver` of the raising exception. + * + * @param[in] recv What is frozen. + * @param[in] fmt Format specifier string compatible with rb_sprintf(). + * @exception rb_eFrozenError Always raises this. + * @note It never returns. + * + * @internal + * + * Note however, that it is often not possible to inspect a frozen object, + * because the inspection itself could be forbidden by the frozen-ness. + */ +void rb_frozen_error_raise(VALUE recv, const char *fmt, ...); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * Honestly I don't understand the name, but it raises an instance of + * ::rb_eArgError. + * + * @param[in] str A message. + * @param[in] type Another message. + * @exception rb_eArgError Always raises this. + * @note It never returns. + */ +void rb_invalid_str(const char *str, const char *type); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_frozen_error_raise(), except its raising exception has a + * message like "can't modify frozen /what/". + * + * @param[in] what What was frozen. + * @exception rb_eFrozenError Always raises this. + * @note It never returns. + */ +void rb_error_frozen(const char *what); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_error_frozen(), except it takes arbitrary Ruby object + * instead of C's string. + * + * @param[in] what What was frozen. + * @exception rb_eFrozenError Always raises this. + * @note It never returns. + */ +void rb_error_frozen_object(VALUE what); + +/** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_error_untrusted(VALUE); + +/** + * Queries if the passed object is frozen. + * + * @param[in] obj Target object to test frozen-ness. + * @exception rb_eFrozenError It is frozen. + * @post Upon successful return it is guaranteed _not_ frozen. + */ +void rb_check_frozen(VALUE obj); + +/** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_check_trusted(VALUE); + +/** + * Ensures that the passed object can be `initialize_copy` relationship. When + * you implement your own one you would better call this at the right beginning + * of your implementation. + * + * @param[in] obj Destination object. + * @param[in] orig Source object. + * @exception rb_eFrozenError `obj` is frozen. + * @post Upon successful return obj is guaranteed safe to copy orig. + */ +void rb_check_copyable(VALUE obj, VALUE orig); + +RBIMPL_ATTR_NORETURN() +/** + * @private + * + * This is an implementation detail of rb_scan_args(). You don't have to + * bother. + * + * @pre `argc` is out of range of `min`..`max`, both inclusive. + * @param[in] argc Arbitrary integer. + * @param[in] min Minimum allowed `argc`. + * @param[in] max Maximum allowed `argc`. + * @exception rb_eArgError Always. + */ +MJIT_STATIC void rb_error_arity(int argc, int min, int max); + +RBIMPL_SYMBOL_EXPORT_END() + +/** + * @deprecated + * + * Does anyone use this? Remain not deleted for compatibility. + */ +#define rb_check_frozen_internal(obj) do { \ + VALUE frozen_obj = (obj); \ + if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \ + rb_error_frozen_object(frozen_obj); \ + } \ + } while (0) + +/** @alias{rb_check_frozen} */ +static inline void +rb_check_frozen_inline(VALUE obj) +{ + if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) { + rb_error_frozen_object(obj); + } +} + +/** @alias{rb_check_frozen} */ +#define rb_check_frozen rb_check_frozen_inline + +/** + * Ensures that the passed integer is in the passed range. When you can use + * rb_scan_args() that is preferred over this one (powerful, descriptive). But + * it can have its own application area. + * + * @param[in] argc Arbitrary integer. + * @param[in] min Minimum allowed `argv`. + * @param[in] max Maximum allowed `argv`, or `UNLIMITED_ARGUMENTS`. + * @exception rb_eArgError `argc` out of range. + * @return The passed `argc`. + * @post Upon successful return `argc` is in range of `min`..`max`, both + * inclusive. + */ +static inline int +rb_check_arity(int argc, int min, int max) +{ + if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max)) + rb_error_arity(argc, min, max); + return argc; +} + +#endif /* RBIMPL_INTERN_ERROR_H */ diff --git a/ruby/include/ruby/internal/intern/eval.h b/ruby/include/ruby/internal/intern/eval.h new file mode 100644 index 000000000..2230f7ab0 --- /dev/null +++ b/ruby/include/ruby/internal/intern/eval.h @@ -0,0 +1,222 @@ +#ifndef RBIMPL_INTERN_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_EVAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Pre-1.9 era evaluator APIs (now considered miscellaneous). + */ +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* eval.c */ +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_raise(), except it raises the passed exception instance as- + * is instead of creating new one. + * + * @param[in] exc An instance of a subclass of ::rb_eException. + * @exception exc What is passed. + * @exception rb_eTypeError `exc` is not an exception. + * @note It never returns. + * + * @internal + * + * Wellll actually, it can take more than what is described above. This + * function tries to call `exception` method of the passed object. If that + * function returns an exception object that is used instead. + */ +void rb_exc_raise(VALUE exc); + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_fatal(), except it raises the passed exception instance as- + * is instead of creating new one. + * + * @param[in] exc An instance of a subclass of ::rb_eException. + * @exception exc What is passed. + * @note It never returns. + * + * @internal + * + * You know what...? Using this API you can make arbitrary exceptions, like + * `RuntimeError`, that doesn't interface with `rescue` clause. This is very + * confusing. + */ +void rb_exc_fatal(VALUE exc); + +/* process.c */ + +RBIMPL_ATTR_NORETURN() +/** + * Identical to rb_exit(), except how arguments are passed. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Contains at most one of the following: + * - ::RUBY_Qtrue - means `EXIT_SUCCESS`. + * - ::RUBY_Qfalse - means `EXIT_FAILURE`. + * - Numerical value - takes that value. + * @exception rb_eArgError Wrong `argc`. + * @exception rb_eSystemExit Exception representing the exit status. + * @note It never returns. + */ +VALUE rb_f_exit(int argc, const VALUE *argv); + +RBIMPL_ATTR_NORETURN() +/** + * This is similar to rb_f_exit(). In fact on some situation it internally + * calls rb_exit(). But can be very esoteric on occasions. + * + * It takes up to one argument. If an argument is passed, it tries to display + * that. Otherwise if there is `$!`, displays that exception instead. It + * finally raise ::rb_eSystemExit in both cases. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Contains at most one string-ish object. + * @exception rb_eArgError Wrong `argc`. + * @exception rb_eTypeError No conversion from `argv[0]` to String. + * @exception rb_eSystemExit Exception representing `EXIT_FAILURE`. + * @note It never returns. + */ +VALUE rb_f_abort(int argc, const VALUE *argv); + +/* eval.c*/ + +RBIMPL_ATTR_NORETURN() +/** + * Raises an instance of ::rb_eInterrupt. + * + * @exception rb_eInterrupt Always raises this exception. + * @note It never returns. + */ +void rb_interrupt(void); + +/** + * Queries the name of the Ruby level method that is calling this function. + * The "name" in this context is the one assigned to the function for the first + * time (note that methods can have multiple names via aliases). + * + * @retval 0 There is no method (e.g. toplevel context). + * @retval otherwise The name of the current method. + */ +ID rb_frame_this_func(void); + +RBIMPL_ATTR_NORETURN() +/** + * This function is to re-throw global escapes. Such global escapes include + * exceptions, `throw`, `break`, for example. + * + * It makes sense only when used in conjunction with "protect" series APIs + * e.g. rb_protect(), rb_load_protect(), rb_eval_string_protect(), etc. In + * case these functions experience global escapes, they fill their opaque + * `state` return buffer. You can ignore such escapes. But if you decide + * otherwise, you have to somehow escape globally again. This function is used + * for that purpose. + * + * @param[in] state Opaque state of execution. + * @note It never returns. + * + * @internal + * + * Though not a part of our public API, `state` is in fact an enum + * ruby_tag_type. You can see the potential values by looking at vm_core.h. + */ +void rb_jump_tag(int state); + +/** + * Calls `initialize` method of the passed object with the passed arguments. + * It also forwards the implicitly passed block to the method. + * + * @param[in] obj Receiver object. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed as-is to `obj.initialize`. + * @exception rb_eException Any exceptions happen inside. + */ +void rb_obj_call_init(VALUE obj, int argc, const VALUE *argv); + +/** + * Identical to rb_obj_call_init(), except you can specify how to handle the + * last element of the given array. + * + * @param[in] obj Receiver object. + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Passed as-is to `obj.initialize`. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eNoMethodError No such method. + * @exception rb_eException Any exceptions happen inside. + */ +void rb_obj_call_init_kw(VALUE, int, const VALUE*, int); + +/** + * Identical to rb_frame_this_func(), except it returns the named used to call + * the method. + * + * @retval 0 There is no method (e.g. toplevel context). + * @retval otherwise The name of the current method. + */ +ID rb_frame_callee(void); + +/** + * Constructs an exception object from the list of arguments, in a manner + * similar to Ruby's `raise`. This function can take: + * + * - No arguments at all, i.e. `argc == 0`. This is not a failure. It + * returns ::RUBY_Qnil then. + * + * - An object, which is an instance of ::rb_cString. In this case an + * instance of ::rb_eRuntimeError whose message is the passed string is + * created then returned. + * + * - An object, which responds to `exception` method, and optionally its + * argument, and optionally its backtrace. For example instances of + * subclasses of ::rb_eException have this method. What is returned from + * the method is returned. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv 0 up to 3 objects. + * @exception rb_eArgError Wrong `argc`. + * @exception rb_eTypeError `argv[0].exception` returned non-exception. + * @return An instance of a subclass of ::rb_eException. + * + * @internal + * + * Historically this was _the_ way `raise` converted its arguments to an + * exception. However they diverged. + */ +VALUE rb_make_exception(int argc, const VALUE *argv); + +/* eval_jump.c */ + +/** + * Registers a function that shall run on process exit. Registered functions + * run in reverse-chronological order, mixed with syntactic `END` block and + * `Kernel#at_exit`. + * + * @param[in] func Function to run at process exit. + * @param[in] arg Passed as-is to `func`. + */ +void rb_set_end_proc(void (*func)(VALUE arg), VALUE arg); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_EVAL_H */ diff --git a/ruby/include/ruby/internal/intern/file.h b/ruby/include/ruby/internal/intern/file.h new file mode 100644 index 000000000..2dc60c7ba --- /dev/null +++ b/ruby/include/ruby/internal/intern/file.h @@ -0,0 +1,213 @@ +#ifndef RBIMPL_INTERN_FILE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_FILE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cFile. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* file.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_file_expand_path(), except how arguments are passed. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Filename, and base directory, in that order. + * @exception rb_eArgError Wrong `argc`. + * @exception rb_eTypeError Non-string passed. + * @exception rb_eEncCompatError No conversion from arguments to a path. + * @return Expanded path. + * + * @internal + * + * It seems nobody actually uses this function right now. Maybe delete it? + */ +VALUE rb_file_s_expand_path(int argc, const VALUE *argv); + +/** + * Identical to rb_file_absolute_path(), except it additionally understands + * `~`. If a given pathname starts with `~someone/`, that part expands to the + * user's home directory (or that of current process' owner's in case of `~/`). + * + * @param[in] fname Relative file name. + * @param[in] dname Lookup base directory name, or in case + * ::RUBY_Qnil is passed the process' current + * working directory is assumed. + * @exception rb_eArgError Home directory is not absolute. + * @exception rb_eTypeError Non-string passed. + * @exception rb_eEncCompatError No conversion from arguments to a path. + * @return Expanded path. + */ +VALUE rb_file_expand_path(VALUE fname, VALUE dname); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_file_absolute_path(), except how arguments are passed. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Filename, and base directory, in that order. + * @exception rb_eArgError Wrong `argc`. + * @exception rb_eTypeError Non-string passed. + * @exception rb_eEncCompatError No conversion from arguments to a path. + * @return Expanded path. + * + * @internal + * + * It seems nobody actually uses this function right now. Maybe delete it? + */ +VALUE rb_file_s_absolute_path(int argc, const VALUE *argv); + +/** + * Maps a relative path to its absolute representation. Relative paths are + * referenced from the passed directory name, or from the process' current + * working directory in case ::RUBY_Qnil is passed. + * + * @param[in] fname Relative file name. + * @param[in] dname Lookup base directory name, or in case + * ::RUBY_Qnil is passed the process' current + * working directory is assumed. + * @exception rb_eArgError Strings contain NUL bytes. + * @exception rb_eTypeError Non-string passed. + * @exception rb_eEncCompatError No conversion from arguments to a path. + * @return Expanded path. + */ +VALUE rb_file_absolute_path(VALUE fname, VALUE dname); + +/** + * Strips a file path's last component (and trailing separators if any). This + * function is relatively simple on POSIX environments; just splits the input + * with `/`, strips the last one, if something remains joins them again, + * otherwise the return value is `"."`. However when it comes to Windows this + * function is quite very much complicated. We have to take UNC etc. into + * account. So for instance `"C:foo"`'s dirname is `"C:."`. + * + * @param[in] fname File name to strip. + * @exception rb_eTypeError `fname` is not a String. + * @exception rb_eArgError `fname` contains NUL bytes. + * @exception rb_eEncCompatError `fname`'s encoding is not path-compat. + * @return A dirname of `fname`. + * @note This is a "pure" operation; it computes the return value solely + * from the passed object and never does any file IO. + */ +VALUE rb_file_dirname(VALUE fname); + +RBIMPL_ATTR_NONNULL(()) +/** + * Resolves a feature's path. This function takes for instance `"json"` and + * `[".so", ".rb"]`, and iterates over the `$LOAD_PATH` to see if there is + * either `json.so` or `json.rb` in the directory. + * + * This is not what everything `require` does, but at least `require` is built + * on top of it. + * + * @param[in,out] feature File to search, and return buffer. + * @param[in] exts List of file extensions. + * @exception rb_eTypeError `feature` is not a String. + * @exception rb_eArgError `feature` contains NUL bytes. + * @exception rb_eEncCompatError `feature`'s encoding is not path-compat. + * @retval 0 Not found + * @retval otherwise Found index in `ext`, plus one. + * @post `*feature` is a resolved path. + */ +int rb_find_file_ext(VALUE *feature, const char *const *exts); + +/** + * Identical to rb_find_file_ext(), except it takes a feature name and is + * extension at once, e.g. `"json.rb"`. This difference is much like how + * `require` and `load` are different. + * + * @param[in] path A path relative to `$LOAD_PATH`. + * @exception rb_eTypeError `path` is not a String. + * @exception rb_eArgError `path` contains NUL bytes. + * @exception rb_eEncCompatError `path`'s encoding is not path-compat. + * @return Expanded path. + */ +VALUE rb_find_file(VALUE path); + +/** + * Queries if the given path is either a directory, or a symlink that + * (potentially recursively) points to such thing. + * + * @param[in] _ Ignored (why...?) + * @param[in] path String, or IO. In case of IO it issues + * `fstat(2)` instead of `stat(2)`. + * @exception rb_eFrozenError `path` is a frozen IO (why...?) + * @exception rb_eTypeError `path` is neither String nor IO. + * @exception rb_eArgError `path` contains NUL bytes. + * @exception rb_eEncCompatError `path`'s encoding is not path-compat. + * @retval RUBY_Qtrue `path` is a directory. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_file_directory_p(VALUE _, VALUE path); + +/** + * Converts a string into an "OS Path" encoding, if any. In most operating + * systems there are no such things like per-OS default encoding of filename. + * For them this function is no-op. However most notably on MacOS, pathnames + * are UTF-8 encoded. It converts the given string into such encoding. + * + * @param[in] path An instance of ::rb_cString. + * @exception rb_eEncCompatError `path`'s encoding is not path-compat. + * @return `path`'s contents converted to the OS' path encoding. + */ +VALUE rb_str_encode_ospath(VALUE path); + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE() +/** + * Queries if the given path is an absolute path. On POSIX environments it is + * as easy as `path[0] == '/'`. However on Windows, drive letters and UNC + * paths are also taken into account. + * + * @param[in] path A possibly relative path string. + * @retval 1 `path` is absolute. + * @retval 0 `path` is relative. + */ +int rb_is_absolute_path(const char *path); + +/** + * Queries the file size of the given file. Because this function calls + * `fstat(2)` internally, it is a failure to pass a closed file to this + * function. + * + * This function flushes the passed file's buffer if any. Can take time. + * + * @param[in] file A file object. + * @exception rb_eFrozenError `file` is frozen. + * @exception rb_eIOError `file` is closed. + * @exception rb_eSystemCallError Permission denied etc. + * @exception rb_eNoMethodError The given non-file object doesn't respond + * to `#size`. + * @return The size of the passed file. + * @note Passing a non-regular file such as a UNIX domain socket to this + * function is not a failure. But the return value is + * unpredictable. POSIX's `` states that "the use of + * this field is unspecified" then. + */ +off_t rb_file_size(VALUE file); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_FILE_H */ diff --git a/ruby/include/ruby/internal/intern/gc.h b/ruby/include/ruby/internal/intern/gc.h new file mode 100644 index 000000000..e7b800872 --- /dev/null +++ b/ruby/include/ruby/internal/intern/gc.h @@ -0,0 +1,392 @@ +#ifndef RBIMPL_INTERN_GC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_GC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_mGC. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include /* size_t */ +#endif + +#if HAVE_SYS_TYPES_H +# include /* ssize_t */ +#endif + +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* gc.c */ + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NORETURN() +/** + * Triggers out-of-memory error. If possible it raises ::rb_eNoMemError. But + * because we are running out of memory that is not always doable. This + * function tries hard to show something, but ultimately can die silently. + * + * @exception rb_eNoMemError Raises it if possible. + */ +void rb_memerror(void); + +RBIMPL_ATTR_PURE() +/** + * Queries if the GC is busy. + * + * @retval 0 It isn't. + * @retval 1 It is. + */ +int rb_during_gc(void); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Marks objects between the two pointers. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @pre Continuous memory region from `start` to `end` shall be fully + * addressable. + * @param[out] start Pointer to an array of objects. + * @param[out] end Pointer that terminates the array of objects. + * @post Objects from `start` to `end`, both inclusive, are marked. + * + * @internal + * + * `end` can be NULL... But that just results in no-op. + */ +void rb_gc_mark_locations(const VALUE *start, const VALUE *end); + +/** + * Identical to rb_mark_hash(), except it marks only values of the table and + * leave their associated keys unmarked. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Values stored in `tbl` are marked. + */ +void rb_mark_tbl(struct st_table *tbl); + +/** + * Identical to rb_mark_tbl(), except it marks objects using + * rb_gc_mark_movable(). This is one of the GC utility functions that you can + * call when you design your own ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Values stored in `tbl` are marked. + */ +void rb_mark_tbl_no_pin(struct st_table *tbl); + +/** + * Identical to rb_mark_hash(), except it marks only keys of the table and + * leave their associated values unmarked. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Keys stored in `tbl` are marked. + */ +void rb_mark_set(struct st_table *tbl); + +/** + * Marks keys and values associated inside of the given table. This is one of + * the GC utility functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @param[in] tbl A table to mark. + * @post Objects stored in `tbl` are marked. + */ +void rb_mark_hash(struct st_table *tbl); + +/** + * Updates references inside of tables. After you marked values using + * rb_mark_tbl_no_pin(), the objects inside of the table could of course be + * moved. This function is to fixup those references. You can call this from + * your ::rb_data_type_struct::dcompact. + * + * @param[out] ptr A table that potentially includes moved references. + * @post Moved references, if any, are corrected. + */ +void rb_gc_update_tbl_refs(st_table *ptr); + +/** + * Identical to rb_gc_mark(), except it allows the passed value be a + * non-object. For instance pointers to different type of memory regions are + * allowed here. Such values are silently ignored. This is one of the GC + * utility functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @param[out] obj A possible object. + * @post `obj` is marked, if possible. + */ +void rb_gc_mark_maybe(VALUE obj); + +/** + * Marks an object. This is one of the GC utility functions that you can call + * when you design your own ::rb_data_type_struct::dmark. + * + * @param[out] obj Arbitrary Ruby object. + * @post `obj` is marked. + */ +void rb_gc_mark(VALUE obj); + +/** + * Maybe this is the only function provided for C extensions to control the + * pinning of objects, so let us describe it in detail. These days Ruby's GC + * is copying. As far as an object's physical address is guaranteed unused, it + * can move around the object space. Our GC engine rearranges these objects + * after it reclaims unreachable objects from our object space, so that the + * space is compact (improves memory locality). This is called the + * "compaction" phase, and works well most of the time... as far as there are + * no C extensions. C extensions complicate the scenario because Ruby core + * cannot detect any use of the physical address of an object inside of C + * functions. In order to prevent memory corruptions, objects observable from + * C extensions are "pinned"; they stick to where they are born until they die, + * just in case any C extensions touch their raw pointers. This variant of + * scheme is called "Mostly-Copying" garbage collector. Authors of C + * extensions, however, can extremely carefully write them to become + * compaction-aware. To do so avoid referring to a Ruby object from inside of + * your struct in the first place. But if that is not possible, use this + * function from your ::rb_data_type_struct::dmark then. This way objects + * marked using it are considered movable. If you chose this way you have to + * manually fix up locations of such moved pointers using rb_gc_location(). + * + * @see Bartlett, Joel F., "Compacting Garbage Collection with Ambiguous + * Roots", ACM SIGPLAN Lisp Pointers Volume 1 Issue 6 pp. 3-12, + * April-May-June, 1988. https://doi.org/10.1145/1317224.1317225 + * + * @param[in] obj Object that is movable. + * @post Values stored in `tbl` are marked. + */ +void rb_gc_mark_movable(VALUE obj); + +/** + * Finds a new "location" of an object. An object can be moved on compaction. + * This function projects its new abode, or just returns the passed object if + * not moved. This is one of the GC utility functions that you can call when + * you design your own ::rb_data_type_struct::dcompact. + * + * @param[in] obj An object, possibly already moved to somewhere else. + * @return An object, which holds the current contents of former `obj`. + */ +VALUE rb_gc_location(VALUE obj); + +/** + * Asserts that the passed object is no longer needed. Such objects are + * reclaimed sooner or later so this function is not mandatory. But sometimes + * you can know from your application knowledge that an object is surely dead + * at some point. Calling this as a hint can be a polite way. + * + * @param[out] obj Object, dead. + * @pre `obj` have never been passed to this function before. + * @post `obj` could be invalidated. + * @warning It is a failure to pass an object multiple times to this + * function. + * @deprecated This is now a no-op function. + */ +RBIMPL_ATTR_DEPRECATED(("this is now a no-op function")) +void rb_gc_force_recycle(VALUE obj); + +/** + * Triggers a GC process. This was the only GC entry point that we had at the + * beginning. Over time our GC evolved. Now what this function does is just a + * very simplified variation of the entire GC algorithms. A series of + * procedures kicked by this API is called a "full" GC. + * + * - It immediately scans the entire object space to sort the dead. + * - It immediately reclaims any single dead bodies to reuse later. + * + * It is worth noting that the procedures above do not include evaluations of + * finalisers. They run later. + * + * @internal + * + * Finalisers are deferred until we can handle interrupts. See + * `rb_postponed_job_flush` in vm_trace.c. + * + * Of course there are GC that are not "full". For instance this one and the + * GC which runs when we are running out of memory are different. See + * `gc_profile_record_flag` defined in gc.c for the kinds of GC. + * + * In spite of the name this is not what everything that a GC can trigger. As + * of writing it seems this function does not trigger compaction. But this + * might change in future. + */ +void rb_gc(void); + +/** + * Copy&paste an object's finaliser to another. This is one of the GC utility + * functions that you can call when you design your own `initialize_copy`, + * `initialize_dup`, `initialize_clone`. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @post `dst` and `src` share the same finaliser. + * + * @internal + * + * But isn't it easier for you to call super, and let `Object#initialize_copy` + * call this function instead? + */ +void rb_gc_copy_finalizer(VALUE dst, VALUE src); + +/** + * (Re-) enables GC. This makes sense only after you called rb_gc_disable(). + * + * @retval RUBY_Qtrue GC was disabled before. + * @retval RUBY_Qfalse GC was enabled before. + * @post GC is enabled. + * + * @internal + * + * This is one of such exceptional functions that does not raise both Ruby + * exceptions and C++ exceptions. + */ +VALUE rb_gc_enable(void); + +/** + * Disables GC. This prevents automatic GC runs when the process is running + * out of memory. Such situations shall result in rb_memerror(). However this + * does not prevent users from manually invoking rb_gc(). That should work. + * People abused this by disabling GC at the beginning of an event loop, + * process events without GC overheads, then manually force reclaiming garbage + * at the bottom of the loop. However because our GC is now much smarter than + * just calling rb_gc(), this technique is proven to be sub-optimal these days. + * It is believed that there is currently practically no needs of this + * function. + * + * @retval RUBY_Qtrue GC was disabled before. + * @retval RUBY_Qfalse GC was enabled before. + * @post GC is disabled. + */ +VALUE rb_gc_disable(void); + +/** + * Identical to rb_gc(), except the return value. + * + * @return Always returns ::RUBY_Qnil. + */ +VALUE rb_gc_start(void); + +/** + * Assigns a finaliser for an object. Each objects can have objects (typically + * blocks) that run immediately after that object dies. They are called + * finalisers of an object. This function associates a finaliser object with a + * target object. + * + * @note Note that finalisers run _after_ the object they finalise dies. You + * cannot for instance call its methods. + * @note If your finaliser references the object it finalises that object + * loses any chance to become a garbage; effectively leaks memory until + * the end of the process. + * + * @param[in] obj Target to finalise. + * @param[in] block Something `call`able. + * @exception rb_eRuntimeError Somehow `obj` cannot have finalisers. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eArgError `block` doesn't respond to `call`. + * @return The passed `block`. + * @post `block` runs after `obj` dies. + */ +VALUE rb_define_finalizer(VALUE obj, VALUE block); + +/** + * Modifies the object so that it has no finalisers at all. This function is + * mainly provided for symmetry. No practical usages can be thought of. + * + * @param[out] obj Object to clear its finalisers. + * @exception rb_eFrozenError `obj` is frozen. + * @return The passed `obj`. + * @post `obj` has no finalisers. + * @note There is no way to undefine a specific part of many finalisers + * that `obj` could have. All you can do is to clear them all. + */ +VALUE rb_undefine_finalizer(VALUE obj); + +/** + * Identical to rb_gc_stat(), with "count" parameter. + * + * @return Lifetime total number of runs of GC. + */ +size_t rb_gc_count(void); + +/** + * Obtains various GC related profiles. The parameter can be either a Symbol + * or a Hash. If a Hash is passed, it is filled with everything currently + * available. If a Symbol is passed just that portion is returned. + * + * Possible variations of keys you can pass here change from version to + * version. You can get the list of known keys by passing an empty hash and + * let it be filled. + * + * @param[in,out] key_or_buf A Symbol, or a Hash. + * @exception rb_eTypeError Neither Symbol nor Hash. + * @exception rb_eFrozenError Frozen hash is passed. + * @return In case a Hash is passed it returns 0. Otherwise the + * profile value associated with the given key is returned. + * @post In case a Hash is passed it is filled with values. + */ +size_t rb_gc_stat(VALUE key_or_buf); + +/** + * Obtains various info regarding the most recent GC run. This includes for + * instance the reason of the GC. The parameter can be either a Symbol or a + * Hash. If a Hash is passed, it is filled with everything currently + * available. If a Symbol is passed just that portion is returned. + * + * Possible variations of keys you can pass here change from version to + * version. You can get the list of known keys by passing an empty hash and + * let it be filled. + * + * @param[in,out] key_or_buf A Symbol, or a Hash. + * @exception rb_eTypeError Neither Symbol nor Hash. + * @exception rb_eFrozenError Frozen hash is passed. + * @return In case a Hash is passed it returns that hash. Otherwise + * the profile value associated with the given key is returned. + * @post In case a Hash is passed it is filled with values. + */ +VALUE rb_gc_latest_gc_info(VALUE key_or_buf); + +/** + * Informs that there are external memory usages. Our GC runs when we are + * running out of memory. The amount of memory, however, can increase/decrease + * behind-the-scene. For instance DLLs can allocate memories using `mmap(2)` + * etc, which are opaque to us. Registering such external allocations using + * this function enables proper detection of how much memories an object used + * as a whole. That will trigger GCs more often than it would otherwise. You + * can also pass negative numbers here, to indicate that such external + * allocations are gone. + * + * @param[in] diff Amount of memory increased(+)/decreased(-). + */ +void rb_gc_adjust_memory_usage(ssize_t diff); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_GC_H */ diff --git a/ruby/include/ruby/internal/intern/hash.h b/ruby/include/ruby/internal/intern/hash.h new file mode 100644 index 000000000..9d2ce8279 --- /dev/null +++ b/ruby/include/ruby/internal/intern/hash.h @@ -0,0 +1,318 @@ +#ifndef RBIMPL_INTERN_HASH_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_HASH_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cHash. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/st.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* hash.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_st_foreach(), except it raises exceptions when the callback + * function tampers the table during iterating over it. + * + * @param[in] st Table to iterate over. + * @param[in] func Callback function to apply. + * @param[in] arg Passed as-is to `func`. + * @exception rb_eRuntimeError `st` was tampered during iterating. + * + * @internal + * + * This is declared here because exceptions are Ruby level concept. + * + * This is in fact a very thin wrapper of rb_st_foreach_check(). + */ +void rb_st_foreach_safe(struct st_table *st, st_foreach_callback_func *func, st_data_t arg); + +/** @alias{rb_st_foreach_safe} */ +#define st_foreach_safe rb_st_foreach_safe + +/** + * Try converting an object to its hash representation using its `to_hash` + * method, if any. If there is no such thing, returns ::RUBY_Qnil. + * + * @param[in] obj Arbitrary ruby object to convert. + * @exception rb_eTypeError `obj.to_hash` returned something non-Hash. + * @retval RUBY_Qnil No conversion from `obj` to hash defined. + * @retval otherwise Converted hash representation of `obj`. + * @see rb_io_check_io + * @see rb_check_array_type + * @see rb_check_string_type + * + * @internal + * + * There is no rb_hash_to_hash() that analogous to rb_str_to_str(). + * Intentional or ...? + */ +VALUE rb_check_hash_type(VALUE obj); + +RBIMPL_ATTR_NONNULL(()) +/** + * Iterates over a hash. This basically does the same thing as + * rb_st_foreach(). But because the passed hash is a Ruby object, its keys and + * values are both Ruby objects. + * + * @param[in] hash An instance of ::rb_cHash to iterate over. + * @param[in] func Callback function to yield. + * @param[in] arg Passed as-is to `func`. + * @exception rb_eRuntimeError `hash` was tampered during iterating. + */ +void rb_hash_foreach(VALUE hash, int (*func)(VALUE key, VALUE val, VALUE arg), VALUE arg); + +/** + * Calculates a message authentication code of the passed object. The return + * value is a very small integer used as an index of a key of a table. In + * order to calculate the value this function calls `#hash` method of the + * passed object. Ruby provides you a default implementation. But if you + * implement your class in C, that default implementation cannot know the + * underlying data structure. You must implement your own `#hash` method then, + * which must return an integer of uniform distribution in a sufficiently + * instant manner. + * + * @param[in] obj Arbitrary Ruby object. + * @exception rb_eTypeError `obj.hash` returned something non-Integer. + * @return A small integer. + * @note `#hash` can return very big integers, but they get truncated. + */ +VALUE rb_hash(VALUE obj); + +/** + * Creates a new, empty hash object. + * + * @return An allocated new instance of ::rb_cHash. + */ +VALUE rb_hash_new(void); + +/** + * Duplicates a hash. + * + * @param[in] hash An instance of ::rb_cHash. + * @return An allocated new instance of ::rb_cHash, whose contents are + * a verbatim copy of from `hash`. + */ +VALUE rb_hash_dup(VALUE hash); + +/** @alias{rb_obj_freeze} */ +VALUE rb_hash_freeze(VALUE obj); + +/** + * Queries the given key in the given hash table. If there is the key in the + * hash, returns the value associated with the key. Otherwise it returns the + * "default" value (defined per hash table). + * + * @param[in] hash Hash table to look into. + * @param[in] key Hash key to look for. + * @return Either the value associated with the key, or the default one if + * absent. + */ +VALUE rb_hash_aref(VALUE hash, VALUE key); + +/** + * Identical to rb_hash_aref(), except it always returns ::RUBY_Qnil for + * misshits. + * + * @param[in] hash Hash table to look into. + * @param[in] key Hash key to look for. + * @return Either the value associated with the key, or ::RUBY_Qnil if + * absent. + * @note A hash can store ::RUBY_Qnil as an ordinary value. You cannot + * distinguish whether the key is missing, or just its associated + * value happens to be ::RUBY_Qnil, as far as you use this API. + */ +VALUE rb_hash_lookup(VALUE hash, VALUE key); + +/** + * Identical to rb_hash_lookup(), except you can specify what to return on + * misshits. This is much like 2-arguments version of `Hash#fetch`. + * + * ```CXX + * VALUE hash; + * VALUE key; + * VALUE tmp = rb_obj_alloc(rb_cObject); + * VALUE val = rb_hash_lookup2(hash, key, tmp); + * if (val == tmp) { + * printf("misshit"); + * } + * else { + * printf("hit"); + * } + * ``` + * + * @param[in] hash Hash table to look into. + * @param[in] key Hash key to look for. + * @param[in] def Default value. + * @retval def `hash` does not have `key`. + * @retval otherwise The value associated with `key`. + */ +VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def); + +/** + * Identical to rb_hash_lookup(), except it yields the (implicitly) passed + * block instead of returning ::RUBY_Qnil. + * + * @param[in] hash Hash table to look into. + * @param[in] key Hash key to look for. + * @exception rb_eKeyError No block given. + * @return Either the value associated with the key, or what the block + * evaluates to if absent. + */ +VALUE rb_hash_fetch(VALUE hash, VALUE key); + +/** + * Inserts or replaces ("upsert"s) the objects into the given hash table. This + * basically associates the given value with the given key. On duplicate key + * this function updates its associated value with the given one. Otherwise it + * inserts the association at the end of the table. + * + * @param[out] hash Target hash table to modify. + * @param[in] key Arbitrary Ruby object. + * @param[in] val A value to be associated with `key`. + * @exception rb_eFrozenError `hash` is frozen. + * @return The passed `val` + * @post `val` is associated with `key` in `hash`. + */ +VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val); + +/** + * Swipes everything out of the passed hash table. + * + * @param[out] hash Target to clear. + * @exception rb_eFrozenError `hash`is frozen. + * @return The passed `hash` + * @post `hash` has no contents. + */ +VALUE rb_hash_clear(VALUE hash); + +/** + * Deletes each entry for which the block returns a truthy value. If there is + * no block given, it returns an enumerator that does the thing. + * + * @param[out] hash Target hash to modify. + * @exception rb_eFrozenError `hash` is frozen. + * @retval hash The hash is modified. + * @retval otherwise An instance of ::rb_cEnumerator that does it. + */ +VALUE rb_hash_delete_if(VALUE hash); + +/** + * Deletes the passed key from the passed hash table, if any. + * + * @param[out] hash Target hash to modify. + * @param[in] key Key to delete. + * @retval RUBY_Qnil `hash` has no such key as `key`. + * @retval otherwise What was associated with `key`. + * @post `hash` has no such key as `key`. + */ +VALUE rb_hash_delete(VALUE hash, VALUE key); + +/** + * Inserts a list of key-value pairs into a hash table at once. It is + * semantically identical to repeatedly calling rb_hash_aset(), but can be + * faster than that. + * + * @param[in] argc Length of `argv`, must be even. + * @param[in] argv A list of key, value, key, value, ... + * @param[out] hash Target hash table to modify. + * @post `hash` has contents from `argv`. + * @note `argv` is allowed to be NULL as long as `argc` is zero. + * + * @internal + * + * What happens for duplicated keys? Well it silently discards older ones to + * accept the newest (rightmost) one. This behaviour also mimics repeated call + * of rb_hash_aset(). + */ +void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash); + +/** + * Type of callback functions to pass to rb_hash_update_by(). + * + * @param[in] newkey A key of the table. + * @param[in] oldkey Value associated with `key` in hash1. + * @param[in] value Value associated with `key` in hash2. + * @return Either one of the passed values to take. + */ +typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); + +/** + * Destructively merges two hash tables into one. It resolves key conflicts by + * calling the passed function and take its return value. + * + * @param[out] hash1 Target hash to be modified. + * @param[in] hash2 A hash to merge into `hash1`. + * @param[in] func Conflict reconciler. + * @exception rb_eFrozenError `hash1` is frozen. + * @exception rb_eRuntimeError `hash2` is updated instead. + * @return The passed `hash1`. + * @post Contents of `hash2` is merged into `hash1`. + * @note You can pass zero to `func`. This means values from `hash2` + * are always taken. + */ +VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func); + +/* file.c */ + +/** + * This function is mysterious. What it does is not immediately obvious. Also + * what it does seems platform dependent. + * + * @param[in] path A local path. + * @retval 0 The "check" succeeded. + * @retval otherwise The "check" failed. + */ +int rb_path_check(const char *path); + +/* hash.c */ + +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @return 0 always. + */ +int rb_env_path_tainted(void); + +/** + * Destructively removes every environment variables of the running process. + * + * @return The `ENV` object. + * @post The process has no environment variables. + */ +VALUE rb_env_clear(void); + +/** + * Identical to #RHASH_SIZE(), except it returns the size in Ruby's integer + * instead of C's. + * + * @param[in] hash A hash object. + * @return The size of the hash. + */ +VALUE rb_hash_size(VALUE hash); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_HASH_H */ diff --git a/ruby/include/ruby/internal/intern/io.h b/ruby/include/ruby/internal/intern/io.h new file mode 100644 index 000000000..02c249723 --- /dev/null +++ b/ruby/include/ruby/internal/intern/io.h @@ -0,0 +1,661 @@ +#ifndef RBIMPL_INTERN_IO_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_IO_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cIO. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* io.c */ + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define rb_defout rb_stdout + +/* string.c */ /* ...why? moved in commit de7161526014b781468cea5d84411e23be */ + +/** + * The field separator character for inputs, or the `$;`. This affects how + * `String#split` works. You can set this via the `-F` command line option. + * You can also assign arbitrary ruby objects programmatically, but it makes + * best sense for you to assign a regular expression here. + * + * @internal + * + * Tidbit: "fs" comes from AWK's `FS` variable. + */ +RUBY_EXTERN VALUE rb_fs; + +/* io.c */ /* ...why? given rb_fs is in string.c? */ + +/** + * The field separator character for outputs, or the `$,`. This affects how + * `Array#join` works. + * + * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is + * deprecated. + */ +RUBY_EXTERN VALUE rb_output_fs; + +/** + * The record separator character for inputs, or the `$/`. This affects how + * `IO#gets` works. You can set this via the `-0` command line option. + * + * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is + * deprecated. + * + * @internal + * + * Tidbit: "rs" comes from AWK's `RS` variable. + */ +RUBY_EXTERN VALUE rb_rs; + +/** + * This is the default value of ::rb_rs, i.e. `"\n"`. It seems it has always + * been just a newline string since the beginning. Not sure why C codes has to + * use this, given there is no way for ruby programs to interface. + * + * Also it has not been deprecated for unknown reasons. + */ +RUBY_EXTERN VALUE rb_default_rs; + +/** + * The record separator character for outputs, or the `$\`. This affects how + * `IO#print` works. + * + * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is + * deprecated. + */ +RUBY_EXTERN VALUE rb_output_rs; + +/** + * Writes the given string to the given IO. + * + * @param[out] io An IO, opened for writing. + * @param[in] str A String-like object to write to `io`. + * @exception rb_eIOError `io` isn't opened for writing. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `str` to String. + * @exception rb_eSystemCallError `write(2)` failed for some reason. + * @return The number of bytes written to the `io`. + * @post `str` (up to the length of return value) is written to `io`. + * @note This function blocks. + * @note Partial write is a thing. It must be at least questionable not + * to check the return value. + * + * @internal + * + * Above description is in fact inaccurate. This function can take arbitrary + * objects, and calls their `write` method. What is written above in fact + * describes how `IO#write` works. You can pass StringIO etc. here, and would + * work completely differently. + */ +VALUE rb_io_write(VALUE io, VALUE str); + +/** + * Reads a "line" from the given IO. A line here means a chunk of characters + * which is terminated by either `"\n"` or an EOF. + * + * @param[in,out] io An IO, opened for reading. + * @exception rb_eIOError `io` isn't opened for reading. + * @exception rb_eFrozenError `io` is frozen. + * @retval RUBY_Qnil `io` is at EOF. + * @retval otherwise An instance of ::rb_cString. + * @post `io` is read. + * @note Unlike `IO#gets` it doesn't set `$_`. + * @note Unlike `IO#gets` it doesn't consider `$/`. + */ +VALUE rb_io_gets(VALUE io); + +/** + * Reads a byte from the given IO. + * + * @note In Ruby a "byte" always means an 8 bit integer ranging from + * 0 to 255 inclusive. + * @param[in,out] io An IO, opened for reading. + * @exception rb_eIOError `io` is not opened for reading. + * @exception rb_eFrozenError `io` is frozen. + * @retval RUBY_Qnil `io` is at EOF. + * @retval otherwise An instance of ::rb_cInteger. + * @post `io` is read. + * + * @internal + * + * Of course there was a function called `rb_io_getc()`. It was removed in + * commit a25fbe3b3e531bbe479f344af24eaf9d2eeae6ea. + */ +VALUE rb_io_getbyte(VALUE io); + +/** + * "Unget"s a string. This function pushes back the passed string onto the + * passed IO, such that a subsequent buffered read will return it. If the + * passed content is in fact an integer, a single character string of that + * codepoint of the encoding of the IO will be pushed back instead. + * + * It might be counter-intuitive but this function can push back multiple + * characters at once. Also this function can be called multiple times on a + * same IO. Also a "character" can be wider than a byte, depending on the + * encoding of the IO. + * + * @param[out] io An IO, opened for reading. + * @param[in] c Either a String, or an Integer. + * @exception rb_eIOError `io` is not opened for reading. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `c` to ::rb_cString. + * @return Always returns ::RUBY_Qnil. + * + * @internal + * + * Why there is ungetc, given there is no getc? + */ +VALUE rb_io_ungetc(VALUE io, VALUE c); + +/** + * Identical to rb_io_ungetc(), except it doesn't take the encoding of the + * passed IO into account. When an integer is passed, it just casts that value + * to C's `unsigned char`, and pushes that back. + * + * @param[out] io An IO, opened for reading. + * @param[in] b Either a String, or an Integer. + * @exception rb_eIOError `io` is not opened for reading. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `b` to ::rb_cString. + * @return Always returns ::RUBY_Qnil. + */ +VALUE rb_io_ungetbyte(VALUE io, VALUE b); + +/** + * Closes the IO. Any buffered contents are flushed to the operating system. + * Any future operations against the IO would raise ::rb_eIOError. In case the + * io was created using `IO.popen`, it also sets the `$?`. + * + * @param[out] io Target IO to close. + * @return Always returns ::RUBY_Qnil. + * @post `$?` is set in case IO is a pipe. + * @post No operations are possible against `io` any further. + * @note This can block to flush the contents. + * @note This can wake other threads up, especially those who are + * `select()`-ing the passed IO. + * @note Multiple invocations of this function over the same IO again + * and again is not an error, since Ruby 2.3. + * + * @internal + * + * You can close a frozen IO... Is this intentional? + */ +VALUE rb_io_close(VALUE io); + +/** + * Flushes any buffered data within the passed IO to the underlying operating + * system. + * + * @param[out] io Target IO to flush. + * @exception rb_eIOError `io` is closed. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eSystemCallError `write(2)` failed for some reason. + * @return The passed `io`. + * @post `io`'s buffers are empty. + * @note This operation also discards the read buffer. Should basically + * be harmless, but in an esoteric situation like when user pushed + * something different from what was read using `ungetc`, this + * operation in fact changes the behaviour of the `io`. + * @note Buffering is difficult. This operation flushes the data from + * our userspace to the kernel, but that doesn't always mean you + * can expect them stored persistently onto your hard drive. + */ +VALUE rb_io_flush(VALUE io); + +/** + * Queries if the passed IO is at the end of file. "The end of file" here mans + * that there are no more data to read. This function blocks until the read + * buffer is filled in, and if that operation reached the end of file, it still + * returns ::RUBY_Qfalse (because there are data yet in that buffer). It + * returns ::RUBY_Qtrue once after the buffer is cleared. + * + * @param[in,out] io Target io to query. + * @exception rb_eIOError `io` is not opened for reading. + * @exception rb_eFrozenError `io` is frozen. + * @retval RUBY_Qfalse There are things yet to be read. + * @retval RUBY_Qtrue "The end of file" situation. + */ +VALUE rb_io_eof(VALUE io); + +/** + * Sets the binmode. This operation nullifies the effect of textmode (newline + * conversion from `"\r\n"` to `"\n"` or vice versa). Note that it doesn't + * stop character encodings conversions. For instance an IO created using: + * + * ```ruby + * File.open( + * "/dev/urandom", + * textmode: true, + * external_encoding: Encoding::GB18030, + * internal_encoding: Encoding::Windows_31J) + * ``` + * + * has both newline and character conversions. If you pass such IO to this + * function, only the `textmode:true` part is cancelled. Texts read through + * the IO would still be encoded in Windows-31J; texts written to the IO will + * be encoded in GB18030. + * + * @param[out] io Target IO to modify. + * @exception rb_eFrozenError `io` is frozen. + * @return The passed `io`. + * @post `io` is in binmode. + * @note There is no equivalent operation in Ruby. You can do this only + * in C. + */ +VALUE rb_io_binmode(VALUE io); + +/** + * Forces no conversions be applied to the passed IO. Unlike rb_io_binmode(), + * this cancels any newline conversions as well as encoding conversions. Any + * texts read/written through the IO will be the verbatim binary contents. + * + * @param[out] io Target IO to modify. + * @exception rb_eFrozenError `io` is frozen. + * @return The passed `io`. + * @post `io` is in binmode. Both external/internal encoding are set to + * rb_ascii8bit_encoding(). + * @note This is the implementation of `IO#binmode`. + */ +VALUE rb_io_ascii8bit_binmode(VALUE io); + +/** + * Identical to rb_io_write(), except it always returns the passed IO. + * + * @param[out] io An IO, opened for writing. + * @param[in] str A String-like object to write to `io`. + * @exception rb_eIOError `io` isn't opened for writing. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `str` to String. + * @exception rb_eSystemCallError `write(2)` failed. + * @return The passed `io`. + * @post `str` is written to `io`. + * @note This function blocks. + * + * @internal + * + * As rb_io_write(), above description is a fake. + */ +VALUE rb_io_addstr(VALUE io, VALUE str); + +/** + * This is a rb_f_sprintf() + rb_io_write() combo. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv A format string followed by its arguments. + * @param[out] io An IO, opened for writing. + * @exception rb_eIOError `io` isn't opened for writing. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `str` to String. + * @exception rb_eSystemCallError `write(2)` failed. + * @return Always returns ::RUBY_Qnil. + * @post `argv` is formatted, then written to `io`. + * @note This function blocks. + * + * @internal + * + * As rb_io_write(), above descriptions include fakes. + */ +VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io); + +/** + * Iterates over the passed array to apply rb_io_write() individually. If + * there is `$,`, this function inserts the string in middle of each + * iterations. If there is `$\`, this function appends the string at the end. + * If the array is empty, this function outputs `$_`. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv An array of strings to display. + * @param[out] io An IO, opened for writing. + * @exception rb_eIOError `io` isn't opened for writing. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `str` to String. + * @exception rb_eSystemCallError `write(2)` failed. + * @return Always returns ::RUBY_Qnil. + * @post `argv` is written to `io`. + * @note This function blocks. + * @note This function calls rb_io_write() multiple times. Which means, + * it is not an atomic operation. Outputs from multiple threads + * can interleave. + * + * @internal + * + * As rb_io_write(), above descriptions include fakes. + */ +VALUE rb_io_print(int argc, const VALUE *argv, VALUE io); + +/** + * Iterates over the passed array to apply rb_io_write() individually. Unlike + * rb_io_print(), this function prints a newline per each element. It also + * flattens the passed array (OTOH rb_io_print() just resorts to + * rb_ary_to_s()). + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv An array of strings to display. + * @param[out] io An IO, opened for writing. + * @exception rb_eIOError `io` isn't opened for writing. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eTypeError No conversion from `str` to String. + * @exception rb_eSystemCallError `write(2)` failed. + * @return Always returns ::RUBY_Qnil. + * @post `argv` is written to `io`. + * @note This function blocks. + * @note This function calls rb_io_write() multiple times. Which means, + * it is not an atomic operation. Outputs from multiple threads + * can interleave. + * + * @internal + * + * As rb_io_write(), above descriptions include fakes. + */ +VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io); + +/** + * Creates an IO instance whose backend is the given file descriptor. C + * extension libraries sometimes have file descriptors created elsewhere (maybe + * deep inside of another shared library), which they want ruby programs to + * handle. This function is handy for such situations. + * + * @param[in] fd Target file descriptor. + * @param[in] flags Flags, e.g. `O_CREAT|O_EXCL` + * @param[in] path The path of the file that backs `fd`, for diagnostics. + * @return An allocated instance of ::rb_cIO. + * @note Leave `path` NULL if you don't know. + */ +VALUE rb_io_fdopen(int fd, int flags, const char *path); + +RBIMPL_ATTR_NONNULL(()) +/** + * Opens a file located at the given path. + * + * `fmode` is a C string that represents the open mode. It can be one of: + * + * - `r` (means `O_RDONLY`), + * - `w` (means `O_WRONLY | O_TRUNC | O_CREAT`), + * - `a` (means `O_WRONLY | O_APPEND | O_CREAT`), + * + * Followed by zero or more combinations of: + * + * - `b` (means `_O_BINARY`), + * - `t` (means `_O_TEXT`), + * - `+` (means `O_RDWR`), + * - `x` (means `O_TRUNC`), or + * - `:[BOM|]enc[:enc]` (see below). + * + * This last one specifies external (and internal if any) encodings, + * respectively. If optional `BOM|` is specified and the specified external + * encoding is capable of expressing BOMs, opening file's contents' byte order + * is auto-detected using the mechanism. + * + * So for instance, fmode of `"rt|BOM:utf-16le:utf-8"` specifies that... + * + * - the physical representation of the contents of the file is in UTF-16; + * - honours its BOM but assumes little endian if absent; + * - opens the file for reading; + * - what is read is converted into UTF-8; + * - with newlines cannibalised to `\n`. + * + * @param[in] fname Path to open. + * @param[in] fmode Mode specifier much like `fopen(3)`. + * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`). + * @exception rb_eSystemCallError `open(2)` failed for some reason. + * @return An instance of ::rb_cIO. + */ +VALUE rb_file_open(const char *fname, const char *fmode); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_file_open(), except it takes the pathname as a Ruby's string + * instead of C's. In case the passed Ruby object is a non-String it tries to + * call `#to_path`. + * + * @param[in] fname Path to open. + * @param[in] fmode Mode specifier much like `fopen(3)`. + * @exception rb_eTypeError `fname` is not a String. + * @exception rb_eEncCompatError `fname` is not ASCII-compatible. + * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`). + * @exception rb_eSystemCallError `open(2)` failed for some reason. + * @return An instance of ::rb_cIO. + */ +VALUE rb_file_open_str(VALUE fname, const char *fmode); + +/** + * Much like rb_io_gets(), but it reads from the mysterious ARGF object. ARGF + * in this context can be seen as a virtual IO which concatenates contents of + * the files passed to the process via the ARGV, or just STDIN if there are no + * such files. + * + * Unlike rb_io_gets() this function sets `$_`. + * + * @exception rb_eFrozenError ARGF resorts to STDIN but it is frozen. + * @retval RUBY_Qnil ARGF is at EOF. + * @retval otherwise An instance of ::rb_cString. + * @post ARGF is read. + * @post `$_` is set. + * + * @internal + * + * In reality, this function can call `ARGF.gets`. Its redefinition can affect + * the behaviour. + * + * Also, you can tamper ARGV on-the-fly in middle of ARGF usages: + * + * ``` + * gets # Reads the first file. + * ARGV << '/proc/self/limits' # Adds a file. + * gets # Can read from /proc/self/limits. + * ``` + */ +VALUE rb_gets(void); + +RBIMPL_ATTR_NONNULL(()) +/** + * Writes the given error message to somewhere applicable. On Windows it goes + * to the console. On POSIX environments it goes to the standard error. + * + * @warning IT IS A BAD IDEA to use this function form your C extensions. + * It is often annoying when GUI applications write to consoles; + * users don't want to look at there. Programmers also want to + * control the cause of the message itself, like by rescuing an + * exception. Just let ruby handle errors. That must be better than + * going your own way. + * + * @param[in] str Error message to display. + * @post `str` is written to somewhere. + * + * @internal + * + * AFAIK this function is listed here without marked deprecated because there + * are usages of this function in the wild. + */ +void rb_write_error(const char *str); + +/** + * Identical to rb_write_error(), except it additionally takes the message's + * length. Necessary when you want to handle wide characters. + * + * @param[in] str Error message to display. + * @param[in] len Length of `str`, in bytes. + * @post `str` is written to somewhere. + */ +void rb_write_error2(const char *str, long len); + +/** + * Closes everything. In case of POSIX environments, a child process inherits + * its parent's opened file descriptors. Which is nowadays considered as one + * of the UNIX mistakes. This function closes such inherited file descriptors. + * When your C extension needs to have a child process, don't forget to call + * this from your child process right before exec. + * + * @param[in] lowfd Lower bound of FDs (you want STDIN to remain, no?). + * @param[in] maxhint Hint of max FDs. + * @param[in] noclose_fds A hash, whose keys are an allowlist. + * + * @internal + * + * As of writing, in spite of the name, this function does not actually close + * anything. It just sets `FD_CLOEXEC` for everything and let `execve(2)` to + * atomically close them at once. This is because as far as we know there are + * no such platform that has `fork(2)` but lacks `FD_CLOEXEC`. + * + * Because this function is expected to run on a forked process it is entirely + * async-signal-safe. + */ +void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds); + +RBIMPL_ATTR_NONNULL(()) +/** + * This is an rb_cloexec_pipe() + rb_update_max_fd() combo. + * + * @param[out] pipes Return buffer. Must at least hold 2 elements. + * @retval 0 Successful creation of a pipe. + * @retval -1 Failure in underlying system call(s). + * @post `pipes` is filled with file descriptors. + * @post `errno` is set on failure. + */ +int rb_pipe(int *pipes); + +/** + * Queries if the given FD is reserved or not. Occasionally Ruby interpreter + * opens files for its own purposes. Use this function to prevent touching + * such behind-the-scene descriptors. + * + * @param[in] fd Target file descriptor. + * @retval 1 `fd` is reserved. + * @retval 0 Otherwise. + */ +int rb_reserved_fd_p(int fd); + +/** @alias{rb_reserved_fd_p} */ +#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd) + +/** + * Opens a file that closes on exec. In case of POSIX environments, a child + * process inherits its parent's opened file descriptors. Which is nowadays + * considered as one of the UNIX mistakes. This function opens a file + * descriptor as `open(2)` does, but additionally instructs the operating + * system that we don't want it be seen from child processes. + * + * @param[in] pathname File path to open. + * @param[in] flags Open mode, as in `open(2)`. + * @param[in] mode File mode, in case of `O_CREAT`. + * @retval -1 `open(2)` failed for some reason. + * @retval otherwise An allocated new file descriptor. + * @note This function does not raise. + * + * @internal + * + * Whether this function can take NULL or not depends on the underlying open(2) + * system call implementation but @shyouhei doesn't think it's worth trying. + */ +int rb_cloexec_open(const char *pathname, int flags, mode_t mode); + +/** + * Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3. + * + * @param[in] oldfd File descriptor to duplicate. + * @retval -1 `dup2(2)` failed for some reason. + * @retval otherwise An allocated new file descriptor. + * @note This function does not raise. + */ +int rb_cloexec_dup(int oldfd); + +/** + * Identical to rb_cloexec_dup(), except you can specify the destination file + * descriptor. If the destination is already squatted by another file + * descriptor that gets silently closed without any warnings. (This is a spec + * requested by POSIX.) + * + * @param[in] oldfd File descriptor to duplicate. + * @param[in] newfd Return value destination. + * @retval -1 `dup2(2)` failed for some reason. + * @retval newfd An allocated new file descriptor. + * @post Whatever sat at `newfd` gets closed with no notifications. + * @post In case return value is -1 `newfd` is untouched. + * @note This function does not raise. + */ +int rb_cloexec_dup2(int oldfd, int newfd); + +RBIMPL_ATTR_NONNULL(()) +/** + * Opens a pipe with closing on exec. In case of POSIX environments, a child + * process inherits its parent's opened file descriptors. Which is nowadays + * considered as one of the UNIX mistakes. This function opens a pipe as + * `pipe(2)` does, but additionally instructs the operating system that we + * don't want the duplicated FDs be seen from child processes. + * + * @param[out] fildes Return buffer. Must at least hold 2 elements. + * @retval 0 Successful creation of a pipe. + * @retval -1 Failure in underlying system call(s). + * @post `pipes` is filled with file descriptors. + * @post `errno` is set on failure. + */ +int rb_cloexec_pipe(int fildes[2]); + +/** + * Duplicates a file descriptor with closing on exec. In case of POSIX + * environments, a child process inherits its parent's opened file descriptors. + * Which is nowadays considered as one of the UNIX mistakes. This function + * duplicates a file descriptor as `dup(2)` does, but additionally instructs + * the operating system that we don't want the duplicated FD be seen from child + * processes. + * + * @param[in] fd File descriptor to duplicate. + * @param[in] minfd Minimum allowed FD to return. + * @retval -1 `dup(2)` failed for some reason. + * @retval otherwise An allocated new file descriptor. + * @note This function does not raise. + * + * `minfd` is handy when for instance STDERR is closed but you don't want to + * use fd 2. + */ +int rb_cloexec_fcntl_dupfd(int fd, int minfd); + +/** + * Informs the interpreter that the passed fd can be the max. This information + * is used from rb_close_before_exec(). + * + * @param[in] fd An open FD, which can be large. + */ +void rb_update_max_fd(int fd); + +/** + * Sets or clears the close-on-exec flag of the passed file descriptor to the + * desired state. STDIN, STDOUT, STDERR are the exceptional file descriptors + * that shall remain open. All others are to be closed on exec. When a C + * extension library opens a file descriptor using anything other than + * rb_cloexec_open() etc., that file descriptor shall experience this function. + * + * @param[in] fd An open file descriptor. + */ +void rb_fd_fix_cloexec(int fd); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_IO_H */ diff --git a/ruby/include/ruby/internal/intern/load.h b/ruby/include/ruby/internal/intern/load.h new file mode 100644 index 000000000..288a16c2e --- /dev/null +++ b/ruby/include/ruby/internal/intern/load.h @@ -0,0 +1,218 @@ +#ifndef RBIMPL_INTERN_LOAD_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_LOAD_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_f_require(). + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* load.c */ + +/** + * Loads and executes the Ruby program in the given file. + * + * If the path is an absolute path (e.g. starts with `'/'`), the file will be + * loaded directly using the absolute path. If the path is an explicit + * relative path (e.g. starts with `'./'` or `'../'`), the file will be loaded + * using the relative path from the current directory. Otherwise, the file + * will be searched for in the library directories listed in the `$LOAD_PATH`. + * If the file is found in a directory, this function will attempt to load the + * file relative to that directory. If the file is not found in any of the + * directories in the `$LOAD_PATH`, the file will be loaded using the relative + * path from the current directory. + * + * If the file doesn't exist when there is an attempt to load it, a LoadError + * will be raised. + * + * If the `wrap` parameter is true, the loaded script will be executed under an + * anonymous module, protecting the calling program's global namespace. In no + * circumstance will any local variables in the loaded file be propagated to + * the loading environment. + * + * @param[in] path Pathname of a file to load. + * @param[in] wrap Either to load under an anonymous module. + * @exception rb_eTypeError `path` is not a string. + * @exception rb_eArgError `path` is broken as a pathname. + * @exception rb_eEncCompatError `path` is incompatible with pathnames. + * @exception rb_eLoadError `path` not found. + * @exception rb_eException Any exceptions while loading the contents. + * + * @internal + * + * It seems this function is under the rule of bootsnap's regime? + */ +void rb_load(VALUE path, int wrap); + +/** + * Identical to rb_load(), except it avoids potential global escapes. Such + * global escapes include exceptions, `throw`, `break`, for example. + * + * It first evaluates the given file as rb_load() does. If no global escape + * occurred during the evaluation, it `*state` is set to zero on return. + * Otherwise, it sets `*state` to nonzero. If state is `NULL`, it is not set + * in both cases. + * + * @param[in] path Pathname of a file to load. + * @param[in] wrap Either to load under an anonymous module. + * @param[out] state State of execution. + * @post `*state` is set to zero if succeeded. Nonzero otherwise. + * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if + * you decide to ignore the caught exception. + * @see rb_load + * @see rb_protect + * + * @internal + * + * Though not a part of our public API, `state` is in fact an + * enum ruby_tag_type. You can see the potential "nonzero" values by looking + * at vm_core.h. + */ +void rb_load_protect(VALUE path, int wrap, int *state); + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries if the given feature has already been loaded into the execution + * context. The "feature" head are things like `"json"` or `"socket"`. + * + * @param[in] feature Name of a library you want to know about. + * @retval 1 Yes there is. + * @retval 0 Not yet. + */ +int rb_provided(const char *feature); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_provided(), except it additionally returns the "canonical" + * name of the loaded feature. This can be handy when for instance you want to + * know the actually loaded library is either `foo.rb` or `foo.so`. + * + * @param[in] feature Name of a library you want to know about. + * @param[out] loading Return buffer. + * @retval 1 Yes there is. + * @retval 0 Not yet. + */ +int rb_feature_provided(const char *feature, const char **loading); + +RBIMPL_ATTR_NONNULL(()) +/** + * Declares that the given feature is already provided by someone else. This + * API can be handy when you have an extension called `foo.so` which, when + * required, also provides functionality of `bar.so`. + * + * @param[in] feature Name of a library which had already been provided. + * @post No further `require` would search `feature`. + */ +void rb_provide(const char *feature); + +/** + * Identical to rb_require_string(), except it ignores the first argument for + * no reason. There seems to be no reason for 3rd party extension libraries to + * use it. + * + * @param[in] self Ignored. Can be anything. + * @param[in] feature Name of a feature, e.g. `"json"`. + * @exception rb_eLoadError No such feature. + * @exception rb_eRuntimeError `$"` is frozen; unable to push. + * @retval RUBY_Qtrue The feature is loaded for the first time. + * @retval RUBY_Qfalse The feature has already been loaded. + * @post `$"` is updated. + */ +VALUE rb_f_require(VALUE self, VALUE feature); + +/** + * Finds and loads the given feature, if absent. + * + * If the feature is an absolute path (e.g. starts with `'/'`), the feature + * will be loaded directly using the absolute path. If the feature is an + * explicit relative path (e.g. starts with `'./'` or `'../'`), the feature + * will be loaded using the relative path from the current directory. + * Otherwise, the feature will be searched for in the library directories + * listed in the `$LOAD_PATH`. + * + * If the feature has the extension `".rb"`, it is loaded as a source file; if + * the extension is `".so"`, `".o"`, or `".dll"`, or the default shared library + * extension on the current platform, Ruby loads the shared library as a Ruby + * extension. Otherwise, Ruby tries adding `".rb"`, `".so"`, and so on to the + * name until found. If the file named cannot be found, a LoadError will be + * raised. + * + * For extension libraries the given feature may use any shared library + * extension. For example, on Linux you can require `"socket.dll"` to actually + * load `socket.so`. + * + * The absolute path of the loaded file is added to `$LOADED_FEATURES`. A file + * will not be loaded again if its path already appears in there. + * + * Any constants or globals within the loaded source file will be available in + * the calling program's global namespace. However, local variables will not + * be propagated to the loading environment. + * + * @param[in] feature Name of a feature, e.g. `"json"`. + * @exception rb_eLoadError No such feature. + * @exception rb_eRuntimeError `$"` is frozen; unable to push. + * @retval RUBY_Qtrue The feature is loaded for the first time. + * @retval RUBY_Qfalse The feature has already been loaded. + * @post `$"` is updated. + */ +VALUE rb_require_string(VALUE feature); + +/** + * @name extension configuration + * @{ + */ + +/** + * Asserts that the extension library that calls this function is aware of + * Ractor. Multiple Ractors run without protecting each other. This doesn't + * interface well with C programs, unless designed with an in-depth + * understanding of how Ractors work. Extension libraries are shut out from + * Ractors by default. This API is to bypass that restriction. Once after it + * was called, successive calls to rb_define_method() etc. become definitions + * of methods that are aware of Ractors. The amendment would be in effect + * until the end of rb_require_string() etc. + * + * @param[in] flag Either the library is aware of Ractors or not. + * @post Methods would be callable form Ractors, if `flag` is true. + */ +void rb_ext_ractor_safe(bool flag); + +/** @alias{rb_ext_ractor_safe} */ +#define RB_EXT_RACTOR_SAFE(f) rb_ext_ractor_safe(f) + +/** + * This macro is to provide backwards compatibility. It must be safe to do + * something like: + * + * ```CXX + * #ifdef HAVE_RB_EXT_RACTOR_SAFE + * rb_ext_ractor_safe(true); + * #endif + * ``` + */ +#define HAVE_RB_EXT_RACTOR_SAFE 1 + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_LOAD_H */ diff --git a/ruby/include/ruby/internal/intern/marshal.h b/ruby/include/ruby/internal/intern/marshal.h new file mode 100644 index 000000000..118d78a4a --- /dev/null +++ b/ruby/include/ruby/internal/intern/marshal.h @@ -0,0 +1,112 @@ +#ifndef RBIMPL_INTERN_MARSHAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_MARSHAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to rb_mMarshal. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* marshal.c */ + +/** + * Serialises the given object and all its referring objects, to write them + * down to the passed port. + * + * @param[in] obj Target object to dump. + * @param[out] port IO-like destination buffer. + * @exception rb_eTypeError `obj` cannot be dumped for some reason. + * @exception rb_eRuntimeError `obj` was tampered during dumping. + * @exception rb_eArgError Traversal too deep. + * @return The passed `port` as-is. + * @post Serialised representation of `obj` is written to `port`. + * @note `port` is basically an IO but StringIO is also possible. + */ +VALUE rb_marshal_dump(VALUE obj, VALUE port); + +/** + * Deserialises a previous output of rb_marshal_dump() into a network of + * objects. + * + * @param[in,out] port Either IO or String. + * @exception rb_eTypeError `port` is in unexpected type. + * @exception rb_eArgError Contents of `port` is broken. + * @return Object(s) rebuilt using the info from `port`. + * + * SECURITY CONSIDERATIONS + * ======================== + * + * @warning By design, rb_marshal_load() can deserialise almost any + * class loaded into the Ruby process. In many cases this can + * lead to remote code execution if the Marshal data is loaded + * from an untrusted source. + * @warning As a result, rb_marshal_load() is not suitable as a general + * purpose serialisation format and you should never unmarshal + * user supplied input or other untrusted data. + * @warning If you need to deserialise untrusted data, use JSON or + * another serialisation format that is only able to load + * simple, 'primitive' types such as String, Array, Hash, etc. + * Never allow user input to specify arbitrary types to + * deserialise into. + */ +VALUE rb_marshal_load(VALUE port); + +/** + * Marshal format compatibility layer. Over time, classes evolve, so that + * their internal data structure change drastically. For instance an instance + * of ::rb_cRange was made of ::RUBY_T_OBJECT in 1.x., but in 3.x it is a + * ::RUBY_T_STRUCT now. In order to keep binary compatibility, we "fake" the + * marshalled representation to stick to old types. This is the API to enable + * that manoeuvre. Here is how: + * + * First, because you are going to keep backwards compatibility, you need to + * retain the old implementation of your class. Rename it, and keep the class + * somewhere (for instance rb_register_global_address() could help). Next + * create your new class. Do whatever you want. + * + * Then, this is the key point. Create two new "bridge" functions that convert + * the structs back and forth: + * + * - the "dumper" function that takes an instance of the new class, and + * returns an instance of the old one. This is called from + * rb_marshal_dump(), to keep it possible for old programs to read your new + * data. + * + * - the "loader" function that takes two arguments, new one and old one, in + * that order. rb_marshal_load() calls this function when it finds a + * representation of the retained old class. The old one passed to this + * function is the reconstructed instance of the old class. + * Reverse-engineer that to modify the new one, to have the identical + * contents. + * + * Finally, connect all of them using this function. + * + * @param[in] newclass The class that needs conversion. + * @param[in] oldclass Old implementation of `newclass`. + * @param[in] dumper Function that converts `newclass` to `oldclass`. + * @param[in] loader Function that converts `oldclass` to `newclass`. + * @exception rb_eTypeError `newclass` has no allocator. + */ +void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_MARSHAL_H */ diff --git a/ruby/include/ruby/internal/intern/numeric.h b/ruby/include/ruby/internal/intern/numeric.h new file mode 100644 index 000000000..30863fb0c --- /dev/null +++ b/ruby/include/ruby/internal/intern/numeric.h @@ -0,0 +1,208 @@ +#ifndef RBIMPL_INTERN_NUMERIC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_NUMERIC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cNumeric. + */ +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RB_NUM_COERCE_FUNCS_NEED_OPID 1 + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* numeric.c */ + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_COLD() +/** + * Just always raises an exception. + * + * @exception rb_eZeroDivError Division by zero error. + */ +void rb_num_zerodiv(void); + +/** + * @name Coercion operators. + * + * What is a coercion? Well Ruby is basically an OOPL but it also has + * arithmetic operators. They are implemented in OO manners. For instance + * `a+b` is a binary operation `+`, whose receiver is `a`, and whose (sole) + * argument is `b`. + * + * The problem is, you often want `a+b == b+a` to hold. That is easy if both + * `a` and `b` belongs to the same class... Ensuring `1 + 2 == 2 + 1` is kind + * of intuitive. But if you want `1.0 + 2 == 2 + 1.0`, things start getting + * complicated. `1.0+2` is `Float#+`, while `2+1.0` is `Integer#+`. In order + * to achieve the equality Float's and Integer's methods must agree with their + * behaviours. + * + * Now. Floats versus Integers situation is still controllable because they + * are both built-in. But in Ruby you can define your own numeric classes. + * BigDecimal, which is a rubygems gem distributed along with the interpreter, + * is one of such examples. Rational was another such example before. In + * short you cannot create list of all possible combination of the classes that + * could be the operand of `+` operator. Then how do we achieve the + * commutativity? + * + * Here comes the concept of coercion. If a definition of an operator + * encounters an object which is unknown to the author, just assumes that the + * unknown object knows how to handle the situation. So for instance when + * `1+x` has unknown `x`, it lets the `x` handle this. + * + * ```ruby + * class Foo + * def +(x) + * if we_know_what_is_x? then + * ... # handle here + * else + * y, z = x.coerce self + * return y + z + * end + * end + * end + * ``` + * + * The `x.coerce` method returns a 2-element array which are "casted" versions + * of `x` and `self`. + * + * @{ + */ + +/** + * Coerced binary operation. This function first coerces the two objects, then + * applies the operation. + * + * @param[in] lhs LHS operand. + * @param[in] rhs RHS operand. + * @param[in] op Operator method name. + * @exception rb_eTypeError Coercion failed for some reason. + * @return `lhs op rhs`, in a coerced way. + */ +VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op); + +/** + * Identical to rb_num_coerce_bin(), except for return values. This function + * best suits for comparison operators e.g. `<=>`. + * + * @param[in] lhs LHS operand. + * @param[in] rhs RHS operand. + * @param[in] op Operator method name. + * @retval RUBY_Qnil Coercion failed for some reason. + * @retval otherwise `lhs op rhs`, in a coerced way. + */ +VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op); + +/** + * Identical to rb_num_coerce_cmp(), except for return values. This function + * best suits for relationship operators e.g. `<=`. + * + * @param[in] lhs LHS operand. + * @param[in] rhs RHS operand. + * @param[in] op Operator method name. + * @exception rb_eArgError Coercion failed for some reason. + * @return `lhs op rhs`, in a coerced way. + */ +VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op); + +/** + * This one is optimised for bitwise operations, but the API is identical to + * rb_num_coerce_bin(). + * + * @param[in] lhs LHS operand. + * @param[in] rhs RHS operand. + * @param[in] op Operator method name. + * @exception rb_eArgError Coercion failed for some reason. + * @return `lhs op rhs`, in a coerced way. + */ +VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op); + +/** @} */ + +/** + * Converts a numeric value into a Fixnum. This is not a preserving + * conversion; for instance 1.5 would be converted into 1. + * + * @param[in] val A numeric object. + * @exception rb_eTypeError No conversion from `val` to Integer. + * @exception rb_eRangeError `val` out of range. + * @return A fixnum converted from `val`. + * + * @internal + * + * This seems used from nowhere? + */ +VALUE rb_num2fix(VALUE val); + +/** + * Generates a place-value representation of the given Fixnum, with given + * radix. + * + * @param[in] val A fixnum to stringify. + * @param[in] base `2` to `36` inclusive for each radix. + * @exception rb_eArgError `base` is out of range. + * @return An instance of ::rb_cString representing `val`. + * @pre `val` must be a Fixnum (no checks performed). + */ +VALUE rb_fix2str(VALUE val, int base); + +RBIMPL_ATTR_CONST() +/** + * Compares two `double`s. Handy when implementing a spaceship operator. + * + * @param[in] lhs A value. + * @param[in] rhs Another value. + * @retval RB_INT2FIX(-1) `lhs` is "bigger than" `rhs`. + * @retval RB_INT2FIX(1) `rhs` is "bigger than" `lhs`. + * @retval RB_INT2FIX(0) They are equal. + * @retval RUBY_Qnil Not comparable, e.g. NaN. + */ +VALUE rb_dbl_cmp(double lhs, double rhs); + +/** + * Raises the passed `x` to the power of `y`. + * + * @note The return value can be really big. + * @note Also the return value can be really small, in case `x` is a + * negative number. + * @param[in] x A number. + * @param[in] y Another number. + * @retval Inf Cannot express the result. + * @retval 1 Either `y` is 0 or `x` is 1. + * @retval otherwise An instance of ::rb_cInteger whose value is `x ** y`. + * + * @internal + * + * This function returns Infinity when `y` is big enough not to fit into a + * Fixnum. Warning is issued then. + */ +RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_NUMERIC_H */ diff --git a/ruby/include/ruby/internal/intern/object.h b/ruby/include/ruby/internal/intern/object.h new file mode 100644 index 000000000..6bb4ccb2f --- /dev/null +++ b/ruby/include/ruby/internal/intern/object.h @@ -0,0 +1,569 @@ +#ifndef RBIMPL_INTERN_OBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_OBJECT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cObject. + */ +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * This macro is (used but) mysterious. Why on earth do we need this? + * + * - `obj != orig` check is done anyways inside of rb_obj_init_copy(). + * - rb_obj_init_copy() returns something. No need are there to add `, 1`. + */ +#define RB_OBJ_INIT_COPY(obj, orig) \ + ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1)) +/** @old{RB_OBJ_INIT_COPY} */ +#define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig) + +/* object.c */ + +/** + * Identical to rb_class_new_instance(), except it passes the passed keywords + * if any to the `#initialize` method. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] klass An instance of ::rb_cClass. + * @exception rb_eTypeError `klass`'s allocator is undefined. + * @exception rb_eException Any exceptions can happen inside. + * @return An allocated new instance of `klass`. + * @note This is _the_ implementation of `Object.new`. + */ +VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass); + +/** + * Allocates, then initialises an instance of the given class. It first calls + * the passed class' allocator to obtain an uninitialised object, then calls + * its initialiser with the remaining arguments. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arguments passed to `#initialize`. + * @param[in] klass An instance of ::rb_cClass. + * @exception rb_eTypeError `klass`'s allocator is undefined. + * @exception rb_eException Any exceptions can happen inside. + * @return An allocated new instance of `klass`. + */ +VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass); + +/** + * Identical to rb_class_new_instance(), except you can specify how to handle + * the last element of the given array. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] klass An instance of ::rb_cClass. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eTypeError `klass`'s allocator is undefined. + * @exception rb_eException Any exceptions can happen inside. + * @return An allocated new instance of `klass`. + */ +VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat); + +/** + * Checks for equality of the passed objects, in terms of `Object#eql?`. + * + * @param[in] lhs Comparison left hand side. + * @param[in] rhs Comparison right hand side. + * @retval RUBY_Qtrue They are equal. + * @retval RUBY_Qfalse Otherwise. + * @note This function actually calls `lhs.eql?(rhs)` so you cannot + * implement your class' `#eql?` method using it. + */ +int rb_eql(VALUE lhs, VALUE rhs); + +/** + * Generates a textual representation of the given object. + * + * @param[in] obj Arbitrary ruby object. + * @return An instance of ::rb_cString that represents `obj`. + * @note This is the default implementation of `Object#to_s` that each + * subclasses want to override. + */ +VALUE rb_any_to_s(VALUE obj); + +/** + * Generates a human-readable textual representation of the given object. This + * is largely similar to Ruby level `Object#inspect` but not the same; it + * additionally escapes the inspection result so that the string be compatible + * with that of default internal (or default external, if absent). + * + * @param[in] obj Arbitrary ruby object. + * @return An instance of ::rb_cString that represents `obj`. + */ +VALUE rb_inspect(VALUE obj); + +/** + * Queries if the given object is a direct instance of the given class. + * + * @param[in] obj Arbitrary ruby object. + * @param[in] klass An instance of ::rb_cModule. + * @exception rb_eTypeError `klass` is neither module nor class. + * @retval RUBY_Qtrue `obj` is an instance of `klass`. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_obj_is_instance_of(VALUE obj, VALUE klass); + +/** + * Queries if the given object is an instance (of possibly descendants) of the + * given class. + * + * @param[in] obj Arbitrary ruby object. + * @param[in] klass An instance of ::rb_cModule. + * @exception rb_eTypeError `klass` is neither module nor class. + * @retval RUBY_Qtrue `obj` is a `klass`. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass); + +/** + * Allocates an instance of the given class. + * + * @param[in] klass A class to instantiate. + * @exception rb_eTypeError `klass` is not a class. + * @return An allocated, not yet initialised instance of `klass`. + * @note It calls the allocator defined by rb_define_alloc_func(). You + * cannot use this function to define an allocator. Use + * rb_newobj_of(), #TypedData_Make_Struct or others, instead. + * @note Usually prefer rb_class_new_instance() to rb_obj_alloc() and + * rb_obj_call_init(). + * @see rb_class_new_instance() + * @see rb_obj_call_init() + * @see rb_define_alloc_func() + * @see rb_newobj_of() + * @see #TypedData_Make_Struct + */ +VALUE rb_obj_alloc(VALUE klass); + +/** + * Produces a shallow copy of the given object. Its list of instance variables + * are copied, but not the objects they reference. It also copies the frozen + * value state. + * + * @param[in] obj Arbitrary ruby object. + * @exception rb_eException `#initialize_copy` can raise anything. + * @return A "clone" of `obj`. + * + * @internal + * + * Unlike ruby-level `Object#clone`, there is no way to control the frozen-ness + * of the return value. + */ +VALUE rb_obj_clone(VALUE obj); + +/** + * Duplicates the given object. This does almost the same thing as + * rb_obj_clone() do. However it does not copy the singleton class (if any). + * It also doesn't copy frozen-ness. + * + * @param[in] obj Arbitrary ruby object. + * @exception rb_eException `#initialize_copy` can raise anything. + * @return A shallow copy of `obj`. + */ +VALUE rb_obj_dup(VALUE obj); + +/** + * Default implementation of `#initialize_copy`, `#initialize_dup` and + * `#initialize_clone`. It does almost nothing. Just raises exceptions for + * checks. + * + * @param[in] dst The destination object. + * @param[in] src The source object. + * @exception rb_eFrozenError `dst` is frozen. + * @exception rb_eTypeError `dst` and `src` have different classes. + * @return Always returns `dst`. + */ +VALUE rb_obj_init_copy(VALUE src, VALUE dst); + +RBIMPL_ATTR_DEPRECATED_EXT(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Verbatim `obj`. + */ +VALUE rb_obj_taint(VALUE obj); + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_DEPRECATED_EXT(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Always returns ::RUBY_Qfalse. + */ +VALUE rb_obj_tainted(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("taintedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Verbatim `obj`. + */ +VALUE rb_obj_untaint(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Verbatim `obj`. + */ +VALUE rb_obj_untrust(VALUE obj); + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Always returns ::RUBY_Qfalse. + */ +VALUE rb_obj_untrusted(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness turned out to be a wrong idea.")) +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @return Verbatim `obj`. + */ +VALUE rb_obj_trust(VALUE obj); + +/** + * Just calls rb_obj_freeze_inline() inside. Does this make any sens to + * extension libraries? + * + * @param[out] obj Object to freeze. + * @return Verbatim `obj`. + */ +VALUE rb_obj_freeze(VALUE obj); + +RBIMPL_ATTR_PURE() +/** + * Just calls RB_OBJ_FROZEN() inside. Does this make any sens to extension + * libraries? + * + * @param[in] obj Object in question. + * @retval RUBY_Qtrue Yes it is. + * @retval RUBY_Qfalse No it isn't. + */ +VALUE rb_obj_frozen_p(VALUE obj); + +/* gc.c */ + +/** + * Finds or creates an integer primary key of the given object. In the old + * days this function was a purely arithmetic operation that maps the + * underlying memory address where the object resides into a Ruby's integer. + * Some time around 2.x this changed. It no longer relates its return values + * to C level pointers. This function assigns some random number to the given + * object if absent. The same number will be returned on all subsequent + * requests. No two active objects share a number. + * + * @param[in] obj Arbitrary ruby object. + * @return An instance of ::rb_cInteger which is an "identifier" of `obj`. + * + * @internal + * + * The "some random number" is in fact a monotonic-increasing process-global + * unique integer, much like an `INTEGER AUTO_INCREMENT PRIMARY KEY` column in + * a MySQL table. + */ +VALUE rb_obj_id(VALUE obj); + +RBIMPL_ATTR_CONST() +/** + * Identical to rb_obj_id(), except it hesitates from allocating a new instance + * of ::rb_cInteger. rb_obj_id() could allocate ::RUBY_T_BIGNUM objects. That + * allocation might perhaps impact negatively. On such situations, this + * function instead returns one-shot temporary small integers that need no + * allocations at all. The values are guaranteed unique at the moment, but no + * future promise is made; could be reused. Use of this API should be very + * instant. It is a failure to store the returned integer to somewhere else. + * + * In short it is difficult to use. + * + * @param[in] obj Arbitrary ruby object. + * @return An instance of ::rb_cInteger unique at the moment. + * + * @internal + * + * This is roughly the old behaviour of rb_obj_id(). + */ +VALUE rb_memory_id(VALUE obj); + +/* object.c */ + +RBIMPL_ATTR_PURE() +/** + * Finds a "real" class. As the name implies there are class objects that are + * surreal. This function takes a class, traverses its ancestry tree, and + * returns its nearest ancestor which is neither a module nor a singleton + * class. + * + * @param[in] klass An instance of ::rb_cClass. + * @retval RUBY_Qfalse No real class in `klass`' ancestry tree. + * @retval klass `klass` itself is a real class. + * @retval otherwise Nearest ancestor of `klass` who is real. + */ +VALUE rb_class_real(VALUE klass); + +RBIMPL_ATTR_PURE() +/** + * Determines if the given two modules are relatives. + * + * @param[in] scion Possible subclass. + * @param[in] ascendant Possible superclass. + * @exception rb_eTypeError `ascendant` is not a module. + * @retval RUBY_Qtrue `scion` inherits, or is equal to `ascendant`. + * @retval RUBY_Qfalse `ascendant` inherits `scion`. + * @retval RUBY_Qnil They are not relatives. + */ +VALUE rb_class_inherited_p(VALUE scion, VALUE ascendant); + +RBIMPL_ATTR_PURE() +/** + * Queries the parent of the given class. + * + * @param[in] klass A child class. + * @exception rb_eTypeError `klass` is a `Class.allocate`. + * @retval RUBY_Qfalse `klass` has no superclass. + * @retval otherwise `klass`' superclass. + * + * @internal + * + * Is there any class except ::rb_cBasicObject, that has no superclass? + */ +VALUE rb_class_superclass(VALUE klass); + +RBIMPL_ATTR_NONNULL(()) +/** + * Converts an object into another type. Calls the specified conversion method + * if necessary. + * + * @param[in] val An object to convert. + * @param[in] type A value of enum ::ruby_value_type. + * @param[in] name Name to display on error (e.g. "Array"). + * @param[in] mid Conversion method (e.g. "to_ary"). + * @exception rb_eTypeError Failed to convert. + * @return An object of the specified type. + */ +VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_convert_type(), except it returns ::RUBY_Qnil instead of + * raising exceptions, in case of conversion failure. It still raises + * exceptions for various reasons, like when the conversion method itself + * raises, though. + * + * @param[in] val An object to convert. + * @param[in] type A value of enum ::ruby_value_type. + * @param[in] name Name to display on error (e.g. "Array"). + * @param[in] mid Conversion method (e.g. "to_ary"). + * @exception rb_eTypeError The `mid` does not generate `type`. + * @retval RUBY_Qnil No conversion defined. + * @retval otherwise An object of the specified type. + */ +VALUE rb_check_convert_type(VALUE val, int type, const char *name, const char *mid); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_check_convert_type(), except the return value type is fixed + * to ::rb_cInteger. + * + * @param[in] val An object to convert. + * @param[in] mid Conversion method (e.g. "to_ary"). + * @exception rb_eTypeError The `mid` does not generate an integer. + * @retval RUBY_Qnil No conversion defined. + * @retval otherwise An instance of ::rb_cInteger. + */ +VALUE rb_check_to_integer(VALUE val, const char *mid); + +/** + * This is complicated. + * + * - When the passed object is already an instance of ::rb_cFloat, just + * returns it as-is. + * + * - When the passed object is something numeric, the function tries to + * convert it using `#to_f` method. + * + * - If that conversion fails (this happens for instance when the numeric + * is a complex) it returns ::RUBY_Qnil. + * + * - Otherwise returns the conversion result. + * + * - Otherwise it also returns ::RUBY_Qnil. + * + * @param[in] val An object to convert. + * @retval RUBY_Qnil Conversion from `val` to float is undefined. + * @retval otherwise Converted result. + */ +VALUE rb_check_to_float(VALUE val); + +/** + * Identical to rb_check_to_int(), except it raises in case of conversion + * mismatch. + * + * @param[in] val An object to convert. + * @exception rb_eTypeError `#to_int` does not generate an integer. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_to_int(VALUE val); + +/** + * Identical to rb_check_to_integer(), except it uses `#to_int` for conversion. + * + * @param[in] val An object to convert. + * @exception rb_eTypeError `#to_int` does not return an integer. + * @retval RUBY_Qnil No conversion defined. + * @retval otherwise An instance of ::rb_cInteger. + */ +VALUE rb_check_to_int(VALUE val); + +/** + * This is the logic behind `Kernel#Integer`. Numeric types are converted + * directly, with floating point numbers being truncated. Strings are + * interpreted strictly; only leading/trailing whitespaces, plus/minus sign, + * radix indicators such as `0x`, digits, and underscores are allowed. + * Anything else are converted by first trying `#to_int`, then `#to_i`. + * + * This is slightly stricter than `String#to_i`. + * + * @param[in] val An object to convert. + * @exception rb_eArgError Malformed `val` passed. + * @exception rb_eTypeError No conversion defined. + * @return An instance of ::rb_cInteger. + */ +VALUE rb_Integer(VALUE val); + +/** + * Identical to rb_check_to_float(), except it raises on error. + * + * @param[in] val An object to convert. + * @exception rb_eTypeError No conversion defined. + * @return An instance of ::rb_cFloat. + */ +VALUE rb_to_float(VALUE val); + +/** + * This is the logic behind `Kernel#Float`. Numeric types are converted + * directly to the nearest value that a Float can represent. Strings are + * interpreted strictly; only leading/trailing whitespaces are allowed except + * what `strtod` understands. Anything else are converted using `#to_f`. + * + * This is slightly stricter than `String#to_f`. + * + * @param[in] val An object to convert. + * @exception rb_eArgError Malformed `val` passed. + * @exception rb_eTypeError No conversion defined. + * @return An instance of ::rb_cFloat. + */ +VALUE rb_Float(VALUE val); + +/** + * This is the logic behind `Kernel#String`. Arguments are converted by first + * trying `#to_str`, then `#to_s`. + * + * @param[in] val An object to convert. + * @exception rb_eTypeError No conversion defined. + * @return An instance of ::rb_cString. + */ +VALUE rb_String(VALUE val); + +/** + * This is the logic behind `Kernel#Array`. Arguments are converted by first + * trying `#to_ary`, then `#to_a`, and if both failed, returns an array of + * length 1 that contains the passed argument as the sole contents. + * + * @param[in] val An object to convert. + * @return An instance of ::rb_cArray. + */ +VALUE rb_Array(VALUE val); + +/** + * This is the logic behind `Kernel#Hash`. Arguments are converted by first + * trying `#to_hash`. if it failed, and the argument is either ::RUBY_Qnil or + * an empty array, returns an empty hash. Otherwise an exception is raised. + * + * @param[in] val An object to convert. + * @exception rb_eTypeError No conversion defined. + * @return An instance of ::rb_cHash. + */ +VALUE rb_Hash(VALUE val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Converts a textual representation of a real number into a numeric, which is + * the nearest value that the return type can represent, of the value that the + * argument represents. This is in fact a 2-in-1 function whose behaviour can + * be controlled using the second (mode) argument. If the mode is zero, this + * function is in "historical" mode which only understands "floating-constant" + * defined at ISO/IEC 9899:1990 section 6.1.3.1. If the mode is nonzero, it is + * in "extended" mode, which also accepts "hexadecimal-floating-constant" + * defined at ISO/IEC 9899:2018 section 6.4.4.2. + * + * @param[in] str A textual representation of a real number. + * @param[in] mode Conversion mode, as described above. + * @exception rb_eArgError Malformed `str` passed. + * @see https://bugs.ruby-lang.org/issues/2969 + * @note Null pointers are allowed, and it returns 0.0 then. + */ +double rb_cstr_to_dbl(const char *str, int mode); + +/** + * Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of + * C's. + * + * @param[in] str A textual representation of a real number. + * @param[in] mode Conversion mode, as described in rb_cstr_to_dbl(). + * @exception rb_eArgError Malformed `str` passed. + * @see https://bugs.ruby-lang.org/issues/2969 + */ +double rb_str_to_dbl(VALUE str, int mode); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_OBJECT_H */ diff --git a/ruby/include/ruby/internal/intern/parse.h b/ruby/include/ruby/internal/intern/parse.h new file mode 100644 index 000000000..7c4e9925b --- /dev/null +++ b/ruby/include/ruby/internal/intern/parse.h @@ -0,0 +1,194 @@ +#ifndef RBIMPL_INTERN_PARSE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_PARSE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cSymbol. + */ +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* symbol.c */ + +/** + * Calculates an ID of attribute writer. For instance it returns `:foo=` when + * passed `:foo`. + * + * @param[in] id An id. + * @exception rb_eNameError `id` is not for attributes (e.g. operator). + * @return Calculated name of attribute writer. + */ +ID rb_id_attrset(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is a constant. In case an ID is in + * Unicode (likely), its "constant"-ness is determined if its first character + * is either upper case or title case. Otherwise it is detected if case- + * folding the first character changes its case or not. + * + * @param[in] id An id to classify. + * @retval 1 It is a constant. + * @retval 0 It isn't. + */ +int rb_is_const_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is a global variable. A global + * variable must start with `$`. + * + * @param[in] id An id to classify. + * @retval 1 It is a global variable. + * @retval 0 It isn't. + */ +int rb_is_global_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is an instance variable. An + * instance variable must start with `@`, but not `@@`. + * + * @param[in] id An id to classify. + * @retval 1 It is an instance variable. + * @retval 0 It isn't. + */ +int rb_is_instance_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is an attribute writer. An + * attribute writer is otherwise a local variable, except it ends with `=`. + * + * @param[in] id An id to classify. + * @retval 1 It is an attribute writer. + * @retval 0 It isn't. + */ +int rb_is_attrset_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is a class variable. A class + * variable is must start with `@@`. + * + * @param[in] id An id to classify. + * @retval 1 It is a class variable. + * @retval 0 It isn't. + */ +int rb_is_class_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is a local variable. A local + * variable starts with a lowercase character, followed by some alphanumeric + * characters or `_`, then ends with anything other than `!`, `?`, or `=`. + * + * @param[in] id An id to classify. + * @retval 1 It is a local variable. + * @retval 0 It isn't. + */ +int rb_is_local_id(ID id); + +RBIMPL_ATTR_CONST() +/** + * Classifies the given ID, then sees if it is a junk ID. An ID with no + * special syntactic structure is considered junk. This category includes for + * instance punctuation. + * + * @param[in] id An id to classify. + * @retval 1 It is a junk. + * @retval 0 It isn't. + */ +int rb_is_junk_id(ID); + +RBIMPL_ATTR_NONNULL(()) +/** + * Sees if the passed C string constructs a valid syntactic symbol. Invalid + * ones for instance includes whitespaces. + * + * @param[in] str A C string to check. + * @retval 1 It is a valid symbol name. + * @retval 0 It is invalid as a symbol name. + */ +int rb_symname_p(const char *str); + +/* vm.c */ + +/** + * Queries the last match, or `Regexp.last_match`, or the `$~`. You don't have + * to use it, because in reality you can get `$~` using rb_gv_get() as usual. + * + * @retval RUBY_Qnil The method has not ran a regular expression. + * @retval otherwise An instance of ::rb_cMatch. + */ +VALUE rb_backref_get(void); + +/** + * Updates `$~`. You don't have to use it, because in reality you can set `$~` + * using rb_gv_set() as usual. + * + * @param[in] md Arbitrary Ruby object. + * @post The passed object is assigned to `$~`. + * + * @internal + * + * Yes, this function bypasses the Check_Type() that would normally prevent + * evil souls from assigning evil objects to `$~`. Use of this function is a + * really bad smell. + */ +void rb_backref_set(VALUE md); + +/** + * Queries the last line, or the `$_`. You don't have to use it, because in + * reality you can get `$_` using rb_gv_get() as usual. + * + * @retval RUBY_Qnil There has never been a "line" yet. + * @retval otherwise The last set `$_` value. + */ +VALUE rb_lastline_get(void); + +/** + * Updates `$_`. You don't have to use it, because in reality you can set `$_` + * using rb_gv_set() as usual. + * + * @param[in] str Arbitrary Ruby object. + * @post The passed object is assigned to `$_`. + * + * @internal + * + * Unlike `$~`, you can assign non-strings to `$_`, even from ruby scripts. + */ +void rb_lastline_set(VALUE str); + +/* symbol.c */ + +/** + * Collects every single bits of symbols that have ever interned in the entire + * history of the current process. + * + * @return An array that contains all symbols that have ever existed. + */ +VALUE rb_sym_all_symbols(void); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_PARSE_H */ diff --git a/ruby/include/ruby/internal/intern/proc.h b/ruby/include/ruby/internal/intern/proc.h new file mode 100644 index 000000000..b8c3c5e14 --- /dev/null +++ b/ruby/include/ruby/internal/intern/proc.h @@ -0,0 +1,353 @@ +#ifndef RBIMPL_INTERN_PROC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_PROC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cProc. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/iterator.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* proc.c */ + +/** + * Constructs a Proc object from implicitly passed components. When a ruby + * method is called with a block, that block is not explicitly passed around + * using C level function parameters. This function gathers all the necessary + * info to turn them into a Ruby level instance of ::rb_cProc. + * + * @exception rb_eArgError There is no passed block. + * @return An instance of ::rb_cProc. + */ +VALUE rb_block_proc(void); + +/** + * Identical to rb_proc_new(), except it returns a lambda. + * + * @exception rb_eArgError There is no passed block. + * @return An instance of ::rb_cProc. + */ +VALUE rb_block_lambda(void); + +/** + * This is an rb_iterate() + rb_block_proc() combo. + * + * ```CXX + * VALUE + * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)) + * { + * const auto plus = rb_intern("+"); + * return rb_funcall(c, plus, 1, y); + * } + * + * VALUE + * my_own_method(VALUE self) + * { + * return rb_proc_new(my_own_iterator, self); + * } + * ``` + * + * @param[in] func A backend function of a proc. + * @param[in] callback_arg Passed to `func`'s callback_arg. + * @return A C-backended proc object. + * + */ +VALUE rb_proc_new(rb_block_call_func_t func, VALUE callback_arg); + +/** + * Queries if the given object is a proc. + * + * @note This is about the object's data structure, not its class etc. + * @param[in] recv Object in question. + * @retval RUBY_Qtrue It is a proc. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_obj_is_proc(VALUE recv); + +/** + * Evaluates the passed proc with the passed arguments. + * + * @param[in] recv The proc to call. + * @param[in] args An instance of ::RArray which is the arguments. + * @exception rb_eException Any exceptions happen inside. + * @return What the proc evaluates to. + */ +VALUE rb_proc_call(VALUE recv, VALUE args); + +/** + * Identical to rb_proc_call(), except you can specify how to handle the last + * element of the given array. + * + * @param[in] recv The proc to call. + * @param[in] args An instance of ::RArray which is the arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `args`' last is not a keyword argument. + * - RB_PASS_KEYWORDS `args`' last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eException Any exceptions happen inside. + * @return What the proc evaluates to. + */ +VALUE rb_proc_call_kw(VALUE recv, VALUE args, int kw_splat); + +/** + * Identical to rb_proc_call(), except you can additionally pass another proc + * object, as a block. Nowadays procs can take blocks: + * + * ```ruby + * l = -> (positional, optional=nil, *rest, kwarg:, **kwrest, &block) { + * # ... how can we pass this `&block`? ^^^^^^ + * } + * ``` + * + * And this function is to pass one to such procs. + * + * @param[in] recv The proc to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of proc arguments. + * @param[in] proc Proc as a passed block. + * @exception rb_eException Any exceptions happen inside. + * @return What the proc evaluates to. + */ +VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc); + +/** + * Identical to rb_proc_call_with_block(), except you can specify how to handle + * the last element of the given array. It can also be seen as a routine + * identical to rb_proc_call_kw(), except you can additionally pass another + * proc object as a block. + * + * @param[in] recv The proc to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of proc arguments. + * @param[in] proc Proc as a passed block. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `args`' last is not a keyword argument. + * - RB_PASS_KEYWORDS `args`' last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eException Any exceptions happen inside. + * @return What the proc evaluates to. + */ +VALUE rb_proc_call_with_block_kw(VALUE recv, int argc, const VALUE *argv, VALUE proc, int kw_splat); + +/** + * Queries the number of mandatory arguments of the given Proc. If its block + * is declared to take no arguments, returns `0`. If the block is known to + * take exactly `n` arguments, returns `n`. If the block has optional + * arguments, returns `-n-1`, where `n` is the number of mandatory arguments, + * with the exception for blocks that are not lambdas and have only a finite + * number of optional arguments; in this latter case, returns `n`. Keyword + * arguments will be considered as a single additional argument, that argument + * being mandatory if any keyword argument is mandatory. + * + * @param[in] recv Target Proc object. + * @retval 0 It takes no arguments. + * @retval >0 It takes exactly this number of arguments. + * @retval <0 It takes optional arguments. + */ +int rb_proc_arity(VALUE recv); + +/** + * Queries if the given object is a lambda. Instances of ::rb_cProc are either + * lambda or proc. They differ in several points. This function can + * distinguish them without actually evaluating their contents. + * + * @param[in] recv Target proc object. + * @retval RUBY_Qtrue It is a lambda. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_proc_lambda_p(VALUE recv); + +/** + * Snapshots the current execution context and turn it into an instance of + * ::rb_cBinding. + * + * @return An instance of ::rb_cBinding. + */ +VALUE rb_binding_new(void); + +/** + * Creates a method object. A method object is a proc-like object that you can + * "call". Note that a method object snapshots the method at the time the + * object is created: + * + * ```ruby + * class Foo + * def foo + * return 1 + * end + * end + * + * obj = Foo.new.method(:foo) + * + * class Foo + * def foo + * return 2 + * end + * end + * + * obj.call # => 1, not 2. + * ``` + * + * @param[in] recv Receiver of the method. + * @param[in] mid Method name, in either String or Symbol. + * @exception rb_eNoMethodError No such method. + * @return An instance of ::rb_cMethod. + */ +VALUE rb_obj_method(VALUE recv, VALUE mid); + +/** + * Queries if the given object is a method. + * + * @note This is about the object's data structure, not its class etc. + * @param[in] recv Object in question. + * @retval RUBY_Qtrue It is a method. + * @retval RUBY_Qfalse Otherwise. + */ +VALUE rb_obj_is_method(VALUE recv); + +/** + * Evaluates the passed method with the passed arguments. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] recv The method object to call. + * @exception rb_eTypeError `recv` is not a method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method returns. + */ +VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv); + +/** + * Identical to rb_method_call(), except you can specify how to handle the last + * element of the given array. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] recv The method object to call. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `args`' last is not a keyword argument. + * - RB_PASS_KEYWORDS `args`' last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eTypeError `recv` is not a method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method returns. + */ +VALUE rb_method_call_kw(int argc, const VALUE *argv, VALUE recv, int kw_splat); + +/** + * Identical to rb_proc_call(), except you can additionally pass a proc as a + * block. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] recv The method object to call. + * @param[in] proc Proc as a passed block. + * @exception rb_eTypeError `recv` is not a method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method returns. + */ +VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE proc); + +/** + * Identical to rb_method_call_with_block(), except you can specify how to + * handle the last element of the given array. It can also be seen as a + * routine identical to rb_method_call_kw(), except you can additionally pass + * another proc object as a block. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] recv The method object to call. + * @param[in] proc Proc as a passed block. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `args`' last is not a keyword argument. + * - RB_PASS_KEYWORDS `args`' last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @exception rb_eTypeError `recv` is not a method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method returns. + */ +VALUE rb_method_call_with_block_kw(int argc, const VALUE *argv, VALUE recv, VALUE proc, int kw_splat); + +/** + * Queries the number of mandatory arguments of the method defined in the given + * module. If it is declared to take no arguments, returns `0`. If it takes + * exactly `n` arguments, returns `n`. If it has optional arguments, returns + * `-n-1`, where `n` is the number of mandatory arguments. Keyword arguments + * will be considered as a single additional argument, that argument being + * mandatory if any keyword argument is mandatory. + * + * @param[in] mod Namespace to search a method for. + * @param[in] mid Method id. + * @retval 0 It takes no arguments. + * @retval >0 It takes exactly this number of arguments. + * @retval <0 It takes optional arguments. + */ +int rb_mod_method_arity(VALUE mod, ID mid); + +/** + * Identical to rb_mod_method_arity(), except it searches for singleton methods + * rather than instance methods. + * + * @param[in] obj Object to search for a singleton method. + * @param[in] mid Method id. + * @retval 0 It takes no arguments. + * @retval >0 It takes exactly this number of arguments. + * @retval <0 It takes optional arguments. + */ +int rb_obj_method_arity(VALUE obj, ID mid); + +/* eval.c */ + +RBIMPL_ATTR_NONNULL((1)) +/** + * Protects a function call from potential global escapes from the function. + * Such global escapes include exceptions, `throw`, `break`, for example. + * + * It first calls the function func with `args` as the argument. If no global + * escape occurred during the function, it returns the result and `*state` is + * zero. Otherwise, it returns ::RUBY_Qnil and sets `*state` to nonzero. If + * `state` is `NULL`, it is not set in both cases. + * + * @param[in] func A function that potentially escapes globally. + * @param[in] args Passed as-is to `func`. + * @param[out] state State of execution. + * @return What `func` returns, or an undefined value when it did not + * return. + * @post `*state` is set to zero if succeeded. Nonzero otherwise. + * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if + * you decide to ignore the caught exception. + * @see rb_eval_string_protect() + * @see rb_load_protect() + * + * @internal + * + * The "undefined value" described above is in fact ::RUBY_Qnil for now. But + * @shyouhei doesn't think that we would never change that. + * + * Though not a part of our public API, `state` is in fact an + * enum ruby_tag_type. You can see the potential "nonzero" values by looking + * at vm_core.h. + */ +VALUE rb_protect(VALUE (*func)(VALUE args), VALUE args, int *state); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_PROC_H */ diff --git a/ruby/include/ruby/internal/intern/process.h b/ruby/include/ruby/internal/intern/process.h new file mode 100644 index 000000000..7a7b24ed4 --- /dev/null +++ b/ruby/include/ruby/internal/intern/process.h @@ -0,0 +1,273 @@ +#ifndef RBIMPL_INTERN_PROCESS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_PROCESS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_mProcess. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/config.h" /* rb_pid_t is defined here. */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* process.c */ + +/** + * Sets the "last status", or the `$?`. + * + * @param[in] status The termination status, as defined in `waitpid(3posix)`. + * @param[in] pid The last child of the current process. + * @post `$?` is updated. + */ +void rb_last_status_set(int status, rb_pid_t pid); + +/** + * Queries the "last status", or the `$?`. + * + * @retval RUBY_Qnil The current thread has no dead children. + * @retval otherwise An instance of Process::Status describing the status of + * the child that was most recently `wait`-ed. + */ +VALUE rb_last_status_get(void); + +RBIMPL_ATTR_NONNULL(()) +/** + * Executes a shell command. + * + * @warning THIS FUNCTION RETURNS on error! + * @param[in] cmd Passed to the shell. + * @retval -1 Something prevented the command execution. + * @post Upon successful execution this function doesn't return. + * @post In case it returns the `errno` is set properly. + */ +int rb_proc_exec(const char *cmd); + +RBIMPL_ATTR_NORETURN() +/** + * Replaces the current process by running the given external command. This is + * the implementation of `Kernel#exec`. + * + * @param[in] argc Number of objects in `argv`. + * @param[in] argv Command and its options to execute. + * @exception rb_eTypeError Invalid options e.g. non-String argv. + * @exception rb_eArgError Invalid options e.g. redirection cycle. + * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. + * @exception rb_eRuntimeError `Process::UID.switch` in operation. + * @exception rb_eSystemCallError `execve(2)` failed. + * @warning This function doesn't return. + * @warning On failure it raises. On success the process is replaced. + * + * @internal + * + * @shyouhei have to say that the rdoc for `Kernel#exec` is fairly incomplete. + * AFAIK this function ultimately takes the following signature: + * + * ```rbs + * type boolx = bool | nil # != `boolish` + * + * type rlim_t = Integer # rlim_cur + * | [ Integer, Integer ] # rlim_cur, rlim_max + * + * type uid_t = String # e.g. "root" + * | Integer # e.g. 0 + * + * type gid_t = String # e.g. "wheel" + * | Integer # e.g. 0 + * + * type fmode = String # e.g. "rb" + * | Integer # e.g. O_RDONLY | O_BINARY + * + * type mode_t = Integer # e.g. 0644 + * + * type pgrp = true # Creates a dedicated pgroup + * | 0 # ditto + * | nil # Uses the current one + * | Integer # Uses this specific pgroup + * + * type fd = :in # STDIN + * | :out # STDOUT + * | :err # STDERR + * | IO # This specific IO + * | Integer # A file descriptor of this # + * + * type src = fd | [ fd ] + * type dst = :close # Intuitive + * | fd # Intuitive + * | String # Open a file at this path + * | [ String ] # ... using O_RDONLY + * | [ String, fmode ] # ... using this mode + * | [ String, fmode, mode_t ] # ... with a permission + * | [ :child, fd ] # fd of child side + * + * type redir = Hash[ src, dst ] + * + * # ---- + * + * # Key-value pair of environment variables + * type envp = Hash[ String, String ] + * + * # Actual name (and the name passed to the subprocess if any) + * type arg0 = String | [ String, String ] + * + * # Arbitrary string parameters + * type argv = String + * + * # Exec options: + * type argh = redir | { + * chdir: String, # Working directory + * close_others: boolx, # O_CLOEXEC like behaviour + * gid: gid_t, # setegid(2) + * pgrooup: pgrp, # setpgrp(2) + * rlimit_as: rlim_t, # setrlimit(2) + * rlimit_core: rlim_t, # ditto + * rlimit_cpu: rlim_t, # ditto + * rlimit_data: rlim_t, # ditto + * rlimit_fsize: rlim_t, # ditto + * rlimit_memlock: rlim_t, # ditto + * rlimit_msgqueue: rlim_t, # ditto + * rlimit_nice: rlim_t, # ditto + * rlimit_nofile: rlim_t, # ditto + * rlimit_nproc: rlim_t, # ditto + * rlimit_rss: rlim_t, # ditto + * rlimit_rtprio: rlim_t, # ditto + * rlimit_rttime: rlim_t, # ditto + * rlimit_sbsize: rlim_t, # ditto + * rlimit_sigpending: rlim_t, # ditto + * rlimit_stack: rlim_t, # ditto + * uid: uid_t, # seteuid(2) + * umask: mode_t, # umask(2) + * unsetenv_others: boolx # Unset everything except the passed envp + * } + * + * # ==== + * + * class Kernel + * def self?.exec + * : ( arg0 cmd, *argv args ) -> void + * | ( arg0 cmd, *argv args, argh opts) -> void + * | (envp env, arg0 cmd, *argv args ) -> void + * | (envp env, arg0 cmd, *argv args, argh opts) -> void + * end + * ``` + */ +VALUE rb_f_exec(int argc, const VALUE *argv); + +/** + * Waits for a process, with releasing GVL. + * + * @param[in] pid Process ID. + * @param[out] status The wait status is filled back. + * @param[in] flags Wait options. + * @retval -1 System call failed, errno set. + * @retval 0 WNOHANG but no waitable children. + * @retval otherwise A process ID that was `wait()`-ed. + * @post Upon successful return `status` is updated to have the process' + * status. + * @note `status` can be NULL. + * @note The arguments are passed through to underlying system call(s). + * Can have special meanings. For instance passing `(rb_pid_t)-1` + * to `pid` means it waits for any processes, under + * POSIX-compliant situations. + */ +rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags); + +/** + * This is a shorthand of rb_waitpid without status and flags. It has been + * like this since the very beginning. The initial revision already did the + * same thing. Not sure why, then, it has been named `syswait`. AFAIK this is + * different from how `wait(3posix)` works. + * + * @param[in] pid Passed to rb_waitpid(). + */ +void rb_syswait(rb_pid_t pid); + +/** + * Identical to rb_f_exec(), except it spawns a child process instead of + * replacing the current one. + * + * @param[in] argc Number of objects in `argv`. + * @param[in] argv Command and its options to execute. + * @exception rb_eTypeError Invalid options e.g. non-String argv. + * @exception rb_eArgError Invalid options e.g. redirection cycle. + * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. + * @exception rb_eRuntimeError `Process::UID.switch` in operation. + * @retval -1 Child process died for some reason. + * @retval otherwise The ID of the born child. + * + * @internal + * + * This is _really_ identical to rb_f_exec() until ultimately calling the + * system call. Almost everything are shared among these two (and + * rb_f_system()). + */ +rb_pid_t rb_spawn(int argc, const VALUE *argv); + +/** + * Identical to rb_spawn(), except you can additionally know the detailed + * situation in case of abnormal parturitions. + * + * @param[in] argc Number of objects in `argv`. + * @param[in] argv Command and its options to execute. + * @param[out] errbuf Error description write-back buffer. + * @param[in] buflen Number of bytes of `errbuf`, including NUL. + * @exception rb_eTypeError Invalid options e.g. non-String argv. + * @exception rb_eArgError Invalid options e.g. redirection cycle. + * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. + * @exception rb_eRuntimeError `Process::UID.switch` in operation. + * @retval -1 Child process died for some reason. + * @retval otherwise The ID of the born child. + * @post In case of `-1`, at most `buflen` bytes of the reason why is + * written back to `errbuf`. + */ +rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen); + +/** + * Gathers info about resources consumed by the current process. + * + * @param[in] _ Not used. Pass anything. + * @return An instance of `Process::Tms`. + * + * @internal + * + * This function might or might not exist depending on `./confiugre` result. + * It must be a portability hell. Better not use. + */ +VALUE rb_proc_times(VALUE _); + +/** + * "Detaches" a subprocess. In POSIX systems every child processes that a + * process creates must be `wait(2)`-ed. A child process that died yet has not + * been waited so far is called a "zombie", which more or less consumes + * resources. This function automates reclamation of such processes. Once + * after this function successfully returns you can basically forget about the + * child process. + * + * @param[in] pid Process to wait. + * @return An instance of ::rb_cThread which is `waitpid(2)`-ing `pid`. + * @post You can just forget about the return value. GC reclaims it. + * @post You can know the exit status by querying `#value` of the + * return value (which is a blocking operation). + */ +VALUE rb_detach_process(rb_pid_t pid); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_PROCESS_H */ diff --git a/ruby/include/ruby/internal/intern/random.h b/ruby/include/ruby/internal/intern/random.h new file mode 100644 index 000000000..5577f53cb --- /dev/null +++ b/ruby/include/ruby/internal/intern/random.h @@ -0,0 +1,116 @@ +#ifndef RBIMPL_INTERN_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_RANDOM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief MT19937 backended pseudo random number generator. + * @see Matsumoto, M., Nishimura, T., "Mersenne Twister: A 623- + * dimensionally equidistributed uniform pseudorandom number + * generator", ACM Trans. on Modeling and Computer Simulation, 8 + * (1): pp 3-30, 1998. https://doi.org/10.1145/272991.272995 + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* random.c */ + +/** + * Generates a 32 bit random number. + * + * @return A random number. + * @note Now that we have ractors, the RNG behind this function is + * per-ractor. + */ +unsigned int rb_genrand_int32(void); + +/** + * Generates a `double` random number. + * + * @return A random number. + * @note This function shares the RNG with rb_genrand_int32(). + */ +double rb_genrand_real(void); + +/** + * Resets the RNG behind rb_genrand_int32()/rb_genrand_real(). + * + * @post The (now per-ractor) default RNG's internal state is cleared. + */ +void rb_reset_random_seed(void); + +/** + * Generates a String of random bytes. + * + * @param[in,out] rnd An instance of ::rb_cRandom. + * @param[in] n Requested number of bytes. + * @return An instance of ::rb_cString, of binary, of `n` bytes length, + * whose contents are random bits. + * + * @internal + * + * @shyouhei doesn't know if this is an Easter egg or an official feature, but + * this function can take a wider range of objects, such as `Socket::Ifaddr`. + * The arguments are just silently ignored and the default RNG is used instead, + * if they are non-RNG. + */ +VALUE rb_random_bytes(VALUE rnd, long n); + +/** + * Identical to rb_genrand_int32(), except it generates using the passed RNG. + * + * @param[in,out] rnd An instance of ::rb_cRandom. + * @return A random number. + */ +unsigned int rb_random_int32(VALUE rnd); + +/** + * Identical to rb_genrand_real(), except it generates using the passed RNG. + * + * @param[in,out] rnd An instance of ::rb_cRandom. + * @return A random number. + */ +double rb_random_real(VALUE rnd); + +/** + * Identical to rb_genrand_ulong_limited(), except it generates using the + * passed RNG. + * + * @param[in,out] rnd An instance of ::rb_cRandom. + * @param[in] limit Max possible return value. + * @return A random number, distributed in `[0, limit]` interval. + * @note Note it can return `limit`. + * @note Whether the return value distributes uniformly in the + * interval or not depends on how the argument RNG behaves; at + * least in case of MT19937 it does. + */ +unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit); + +/** + * Generates a random number whose upper limit is `i`. + * + * @param[in] i Max possible return value. + * @return A random number, uniformly distributed in `[0, limit]` interval. + * @note Note it can return `i`. + */ +unsigned long rb_genrand_ulong_limited(unsigned long i); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_RANDOM_H */ diff --git a/ruby/include/ruby/internal/intern/range.h b/ruby/include/ruby/internal/intern/range.h new file mode 100644 index 000000000..1f7d7c313 --- /dev/null +++ b/ruby/include/ruby/internal/intern/range.h @@ -0,0 +1,89 @@ +#ifndef RBIMPL_INTERN_RANGE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_RANGE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cRange. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* range.c */ + +/** + * Creates a new Range. + * + * @param[in] beg "Left" or "lowest" endpoint of the range. + * @param[in] end "Right" or "highest" endpoint of the range. + * @param[in] excl Whether the range is open-ended. + * @exception rb_eArgError `beg` and `end` are not comparable. + * @note These days both endpoints can be ::RUBY_Qnil, which means that + * endpoint is unbound. + */ +VALUE rb_range_new(VALUE beg, VALUE end, int excl); + +RBIMPL_ATTR_NONNULL(()) +/** + * Deconstructs a numerical range. As the arguments are `long` based, it + * expects everything are in the `long` domain. + * + * @param[in] range A range of numerical endpoints. + * @param[out] begp Return value buffer. + * @param[out] lenp Return value buffer. + * @param[in] len Updated length. + * @param[in] err In case `len` is out of range... + * - `0`: returns ::RUBY_Qnil. + * - `1`: raises ::rb_eRangeError. + * - `2`: `beg` and `len` expanded accordingly. + * @exception rb_eTypeError `range` is not a numerical range. + * @exception rb_eRangeError `range` cannot fit into `long`. + * @retval RUBY_Qfalse `range` is not an ::rb_cRange. + * @retval RUBY_Qnil `len` is out of `range` but `err` is zero. + * @retval RUBY_Qtrue Otherwise. + * @post `beg` is the (possibly updated) left endpoint. + * @post `len` is the (possibly updated) length of the range. + * + * @internal + * + * The complex error handling switch reflects the fact that `Array#[]=` and + * `String#[]=` behave differently when they take ranges. + */ +VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err); + +RBIMPL_ATTR_NONNULL(()) +/** + * Deconstructs a range into its components. + * + * @param[in] range Range or range-ish object. + * @param[out] begp Return value buffer. + * @param[out] endp Return value buffer. + * @param[out] exclp Return value buffer. + * @retval RUBY_Qfalse `range` is not an instance of ::rb_cRange. + * @retval RUBY_Qtrue Argument pointers are updated. + * @post `*begp` is the left endpoint of the range. + * @post `*endp` is the right endpoint of the range. + * @post `*exclp` is whether the range is open-ended or not. + */ +int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_RANGE_H */ diff --git a/ruby/include/ruby/internal/intern/rational.h b/ruby/include/ruby/internal/intern/rational.h new file mode 100644 index 000000000..ff4beca29 --- /dev/null +++ b/ruby/include/ruby/internal/intern/rational.h @@ -0,0 +1,172 @@ +#ifndef RBIMPL_INTERN_RATIONAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_RATIONAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cRational. + */ +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* rational.c */ + +/** + * Identical to rb_rational_new(), except it skips argument validations. It is + * thus dangerous for extension libraries. For instance `1/0r` could be + * constructed using this. + * + * @param[in] num Numerator, an instance of ::rb_cInteger. + * @param[in] den Denominator, an instance of ::rb_cInteger. + * @exception rb_eTypeError Either argument is not an Integer. + * @return An instance of ::rb_cRational whose value is `(num/den)r`. + */ +VALUE rb_rational_raw(VALUE num, VALUE den); + +/** + * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically + * converts it into a Rational of the identical value. + * + * @param[in] x An instance of ::rb_cInteger. + * @return An instance of ::rb_cRational, whose value is `(x/1)r`. + */ +#define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1)) + +/** @alias{rb_rational_raw} */ +#define rb_rational_raw2(x,y) rb_rational_raw((x), (y)) + +/** + * Constructs a Rational, with reduction. This returns for instance `(2/3)r` + * for `rb_rational_new(INT2NUM(-384), INT2NUM(-576))`. + * + * @param[in] num Numerator, an instance of ::rb_cInteger. + * @param[in] den Denominator, an instance of ::rb_cInteger. + * @exception rb_eZeroDivError `den` is zero. + * @return An instance of ::rb_cRational whose value is `(num/den)r`. + */ +VALUE rb_rational_new(VALUE num, VALUE den); + +/** + * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically + * converts it into a Rational of the identical value. + * + * @param[in] x An instance of ::rb_cInteger. + * @return An instance of ::rb_cRational, whose value is `(x/1)r`. + */ +#define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1)) + +/** @alias{rb_rational_new} */ +#define rb_rational_new2(x,y) rb_rational_new((x), (y)) + +/** + * Converts various values into a Rational. This function accepts: + * + * - Instances of ::rb_cInteger (taken as-is), + * - Instances of ::rb_cRational (taken as-is), + * - Instances of ::rb_cFloat (applies `#to_r`), + * - Instances of ::rb_cComplex (applies `#to_r`), + * - Instances of ::rb_cString (applies `#to_r`), + * - Other objects that respond to `#to_r`. + * + * It (possibly recursively) applies `#to_r` until both sides become either + * Integer or Rational, then divides them. + * + * As a special case, passing ::RUBY_Qundef to `den` is the same as passing + * `RB_INT2NUM(1)`. + * + * @param[in] num Numerator (see above). + * @param[in] den Denominator (see above). + * @exception rb_eTypeError Passed something not described above. + * @exception rb_eFloatDomainError `#to_r` produced Nan/Inf. + * @exception rb_eZeroDivError `#to_r` produced zero for `den`. + * @return An instance of ::rb_cRational whose value is `(num/den)r`. + * + * @internal + * + * This was the implementation of `Kernel#Rational` before, but they diverged. + */ +VALUE rb_Rational(VALUE num, VALUE den); + +/** + * Shorthand of `(x/1)r`. It practically converts it into a Rational of the + * identical value. + * + * @param[in] x ::rb_cInteger, ::rb_cRational, or something that responds to + * `#to_r`. + * @return An instance of ::rb_cRational, whose value is `(x/1)r`. + */ +#define rb_Rational1(x) rb_Rational((x), INT2FIX(1)) + +/** @alias{rb_Rational} */ +#define rb_Rational2(x,y) rb_Rational((x), (y)) + +RBIMPL_ATTR_PURE() +/** + * Queries the numerator of the passed Rational. + * + * @param[in] rat An instance of ::rb_cRational. + * @return Its numerator part, which is an instance of ::rb_cInteger. + */ +VALUE rb_rational_num(VALUE rat); + +RBIMPL_ATTR_PURE() +/** + * Queries the denominator of the passed Rational. + * + * @param[in] rat An instance of ::rb_cRational. + * @return Its denominator part, which is an instance of ::rb_cInteger + * greater than or equal to one.. + */ +VALUE rb_rational_den(VALUE rat); + +/** + * Simplified approximation of a float. It returns a rational `rat` which + * satisfies: + * + * ``` + * flt - |prec| <= rat <= flt + |prec| + * ``` + * + * ```ruby + * 3.141592.rationalize(0.001) # => (201/64)r + * 3.141592.rationalize(0.01)' # => (22/7)r + * 3.141592.rationalize(0.1)' # => (16/5)r + * 3.141592.rationalize(1)' # => (3/1)r + * ``` + * + * @param[in] flt An instance of ::rb_cFloat to rationalise. + * @param[in] prec Another ::rb_cFloat, which is the "precision". + * @return Approximation of `flt`, in ::rb_cRational. + */ +VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec); + +/** + * Identical to rb_flt_rationalize_with_prec(), except it auto-detects + * appropriate precision depending on the passed value. + * + * @param[in] flt An instance of ::rb_cFloat to rationalise. + * @return Approximation of `flt`, in ::rb_cRational. + */ +VALUE rb_flt_rationalize(VALUE flt); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_RATIONAL_H */ diff --git a/ruby/include/ruby/internal/intern/re.h b/ruby/include/ruby/internal/intern/re.h new file mode 100644 index 000000000..31f559327 --- /dev/null +++ b/ruby/include/ruby/internal/intern/re.h @@ -0,0 +1,249 @@ +#ifndef RBIMPL_INTERN_RE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_RE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cRegexp. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* re.c */ + +/** + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * This was a function that switched between memcmp and rb_memcicmp depending + * on then-called `ruby_ignorecase`, or the `$=` global variable. That feature + * was abandoned in sometime around version 1.9.0. + */ +#define rb_memcmp memcmp + +/** + * Identical to st_locale_insensitive_strcasecmp(), except it is timing safe + * and returns something different. + * + * @param[in] s1 Comparison LHS. + * @param[in] s2 Comparison RHS. + * @param[in] n Comparison shall stop after first `n` bytes are scanned. + * @retval <0 `s1` is "less" than `s2`. + * @retval 0 Both sides converted into lowercase would be identical. + * @retval >0 `s1` is "greater" than `s2`. + * @note The "case" here means that of the POSIX Locale. + * + * @internal + * + * Can accept NULLs as long as n is also 0, and returns 0. + */ +int rb_memcicmp(const void *s1,const void *s2, long n); + +/** + * Asserts that the given MatchData is "occupied". MatchData shares its + * backend storages with its Regexp object. But programs can destructively + * tamper its contents. Calling this function beforehand shall prevent such + * modifications to spill over into other objects. + * + * @param[out] md Target instance of ::rb_cMatch. + * @post The object is "busy". + * + * @internal + * + * There is rb_match_unbusy internally, but extension libraries are left unable + * to do so. + */ +void rb_match_busy(VALUE md); + +/** + * Identical to rb_reg_nth_match(), except it just returns Boolean. This could + * skip allocating a returning string, resulting in reduced memory footprints + * if applicable. + * + * @param[in] n Match index. + * @param[in] md An instance of ::rb_cMatch. + * @exception rb_eTypeError `md` is not initialised. + * @retval RUBY_Qnil There is no `n`-th capture. + * @retval RUBY_Qfalse There is a `n`-th capture and is empty. + * @retval RUBY_Qtrue There is a `n`-th capture that has something. + * + * @internal + * + * @shyouhei wonders: why there are both rb_reg_match_defined() and + * rb_match_nth_defined, which are largely the same things, but do not share + * their implementations at all? + */ +VALUE rb_reg_nth_defined(int n, VALUE md); + +/** + * Queries the nth captured substring. + * + * @param[in] n Match index. + * @param[in] md An instance of ::rb_cMatch. + * @exception rb_eTypeError `md` is not initialised. + * @retval RUBY_Qnil There is no `n`-th capture. + * @retval otherwise An allocated instance of ::rb_cString containing + * the contents captured. + */ +VALUE rb_reg_nth_match(int n, VALUE md); + +/** + * Queries the index of the given named capture. Captures could be named. But + * that doesn't mean named ones are not indexed. A regular expression can mix + * named and non-named captures, and they are all indexed. This function + * converts from a name to its index. + * + * @param[in] match An instance of ::rb_cMatch. + * @param[in] backref Capture name, in String, Symbol, or Numeric. + * @exception rb_eIndexError No such named capture. + * @return The index of the given name. + */ +int rb_reg_backref_number(VALUE match, VALUE backref); + +/** + * This just returns the argument, stringified. What a poor name. + * + * @param[in] md An instance of ::rb_cMatch. + * @return Its 0th capture (i.e. entire matched string). + */ +VALUE rb_reg_last_match(VALUE md); + +/** + * The portion of the original string before the given match. + * + * @param[in] md An instance of ::rb_cMatch. + * @return Its "prematch". This is perl's ``$```. + */ +VALUE rb_reg_match_pre(VALUE md); + +/** + * The portion of the original string after the given match. + * + * @param[in] md An instance of ::rb_cMatch. + * @return Its "postmatch". This is perl's `$'`. + */ +VALUE rb_reg_match_post(VALUE md); + +/** + * The portion of the original string that captured at the very last. + * + * @param[in] md An instance of ::rb_cMatch. + * @return Its "lastmatch". This is perl's `$+`. + */ +VALUE rb_reg_match_last(VALUE md); + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_REG_NEW_STR 1 + +/** + * Identical to rb_reg_new(), except it takes the expression in Ruby's string + * instead of C's. + * + * @param[in] src Source code in String. + * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. + * @exception rb_eRegexpError `src` and `opts` do not interface. + * @return Allocated new instance of ::rb_cRegexp. + */ +VALUE rb_reg_new_str(VALUE src, int opts); + +RBIMPL_ATTR_NONNULL(()) +/** + * Creates a new Regular expression. + * + * @param[in] src Source code. + * @param[in] len `strlen(src)`. + * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. + * @return Allocated new instance of ::rb_cRegexp. + */ +VALUE rb_reg_new(const char *src, long len, int opts); + +/** + * Allocates an instance of ::rb_cRegexp. + * + * @private + * + * Nobody should call this function. Regular expressions that are not + * initialised must not exist in the wild. + */ +VALUE rb_reg_alloc(void); + +/** + * Initialises an instance of ::rb_cRegexp. + * + * @private + * + * This just raises for ordinal regexp objects. Extension libraries must not + * use. + */ +VALUE rb_reg_init_str(VALUE re, VALUE s, int options); + +/** + * This is the match operator. + * + * @param[in] re An instance of ::rb_cRegexp. + * @param[in] str An instance of ::rb_cString. + * @exception rb_eTypeError `str` is not a string. + * @exception rb_eRegexpError Error inside of Onigmo (unlikely). + * @retval RUBY_Qnil Match failed. + * @retval otherwise Matched position (character index inside of + * `str`). + * @post `Regexp.last_match` is updated. + * @post `$&`, `$~`, etc., are updated. + * @note If you do this in ruby, named captures are assigned to local + * variable of the local scope. But that doesn't happen here. The + * assignment is done by the interpreter. + */ +VALUE rb_reg_match(VALUE re, VALUE str); + +/** + * Identical to rb_reg_match(), except it matches against rb_lastline_get() + * (or, the `$_`). + * + * @param[in] re An instance of ::rb_cRegexp. + * @exception rb_eRegexpError Error inside of Onigmo (unlikely). + * @retval RUBY_Qnil Match failed or `$_` is absent. + * @retval otherwise Matched position (character index inside of + * `$_`). + * @post `Regexp.last_match` is updated. + * @post `$&`, `$~`, etc., are updated. + */ +VALUE rb_reg_match2(VALUE re); + +/** + * Queries the options of the passed regular expression. + * + * @param[in] re An instance of ::rb_cRegexp. + * @return Its options. + * @note Possible return values are defined in Onigmo.h. + */ +int rb_reg_options(VALUE re); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_RE_H */ diff --git a/ruby/include/ruby/internal/intern/ruby.h b/ruby/include/ruby/internal/intern/ruby.h new file mode 100644 index 000000000..efe61424c --- /dev/null +++ b/ruby/include/ruby/internal/intern/ruby.h @@ -0,0 +1,77 @@ +#ifndef RBIMPL_INTERN_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_RUBY_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Process-global APIs. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* ruby.c */ +/** @alias{rb_get_argv} */ +#define rb_argv rb_get_argv() + +/** + * The value of `$0` at process bootup. + * + * @note This is just a snapshot of `$0`, not the backend storage of it. `$0` + * could become something different because it is a writable global + * variable. Modifying it for instance affects `ps(1)` output. Don't + * assume they are synced. + */ +RUBY_EXTERN VALUE rb_argv0; + +/* io.c */ + +/** + * Queries the arguments passed to the current process that you can access from + * Ruby as `ARGV`. + * + * @return An array of strings containing arguments passed to the process. + */ +VALUE rb_get_argv(void); + +/* ruby.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Loads the given file. This function opens the given pathname for reading, + * parses the contents as a Ruby script, and returns an opaque "node" pointer. + * You can then pass it to ruby_run_node() for evaluation. + * + * @param[in] file File name, or "-" to read from stdin. + * @return Opaque "node" pointer. + */ +void *rb_load_file(const char *file); + +/** + * Identical to rb_load_file(), except it takes the argument as a Ruby's string + * instead of C's. + * + * @param[in] file File name, or "-" to read from stdin. + * @return Opaque "node" pointer. + */ +void *rb_load_file_str(VALUE file); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_RUBY_H */ diff --git a/ruby/include/ruby/internal/intern/select.h b/ruby/include/ruby/internal/intern/select.h new file mode 100644 index 000000000..fabc287cd --- /dev/null +++ b/ruby/include/ruby/internal/intern/select.h @@ -0,0 +1,86 @@ +#ifndef RBIMPL_INTERN_SELECT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SELECT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs to provide ::rb_fd_select(). + * @note Functions and structs defined in this header file are not + * necessarily ruby-specific. They don't need ::VALUE etc. + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_SYS_TYPES_H +# include /* for NFDBITS (BSD Net/2) */ +#endif + +#include "ruby/internal/dllexport.h" + +/* thread.c */ +#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT) +# include "ruby/internal/intern/select/largesize.h" +#elif defined(_WIN32) +# include "ruby/internal/intern/select/win32.h" +# /** Does nothing (defined for compatibility). */ +# define rb_fd_resize(n, f) ((void)(f)) +#else +# include "ruby/internal/intern/select/posix.h" +# /** Does nothing (defined for compatibility). */ +# define rb_fd_resize(n, f) ((void)(f)) +#endif + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +struct timeval; + +/** + * Waits for multiple file descriptors at once. This is basically a wrapper of + * system-provided select() with releasing GVL, to allow other Ruby threads run + * in parallel. + * + * @param[in] nfds Max FD in everything passed, plus one. + * @param[in,out] rfds Set of FDs to wait for reads. + * @param[in,out] wfds Set of FDs to wait for writes. + * @param[in,out] efds Set of FDs to wait for OOBs. + * @param[in,out] timeout Max blocking duration. + * @retval -1 Failed, errno set. + * @retval 0 Timeout exceeded. + * @retval otherwise Total number of file descriptors returned. + * @post `rfds` contains readable FDs. + * @post `wfds` contains writable FDs. + * @post `efds` contains exceptional FDs. + * @post `timeout` is the time left. + * @note All pointers are allowed to be null pointers. + * + * Although backend threads can run in parallel of this function, touching a + * file descriptor from multiple threads could be problematic. For instance + * what happens when a thread closes a file descriptor that is selected by + * someone else, vastly varies among operating systems. You would better avoid + * touching an fd from more than one threads. + * + * @internal + * + * Although any file descriptors are possible here, it makes completely no + * sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know + * the reason for this limitatuon in detail, you might find this thread super + * interesting: https://lkml.org/lkml/2004/10/6/117 + */ +int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_SELECT_H */ diff --git a/ruby/include/ruby/internal/intern/select/largesize.h b/ruby/include/ruby/internal/intern/select/largesize.h new file mode 100644 index 000000000..d156f6203 --- /dev/null +++ b/ruby/include/ruby/internal/intern/select/largesize.h @@ -0,0 +1,217 @@ +#ifndef RBIMPL_INTERN_SELECT_LARGESIZE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SELECT_LARGESIZE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs to provide ::rb_fd_select(). + * + * Several Unix platforms support file descriptors bigger than FD_SETSIZE in + * `select(2)` system call. + * + * - Linux 2.2.12 (?) + * + * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25) + * `select(2)` documents how to allocate fd_set dynamically. + * http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0 + * + * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19) + * + * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4) + * `select(2)` documents how to allocate fd_set dynamically. + * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4 + * + * - HP-UX documents how to allocate fd_set dynamically. + * http://docs.hp.com/en/B2355-60105/select.2.html + * + * - Solaris 8 has `select_large_fdset` + * + * - Mac OS X 10.7 (Lion) + * `select(2)` returns `EINVAL` if `nfds` is greater than `FD_SET_SIZE` and + * `_DARWIN_UNLIMITED_SELECT` (or `_DARWIN_C_SOURCE`) isn't defined. + * http://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/_index.html + * + * When `fd_set` is not big enough to hold big file descriptors, it should be + * allocated dynamically. Note that this assumes `fd_set` is structured as + * bitmap. + * + * `rb_fd_init` allocates the memory. + * `rb_fd_term` frees the memory. + * `rb_fd_set` may re-allocate bitmap. + * + * So `rb_fd_set` doesn't reject file descriptors bigger than `FD_SETSIZE`. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" + +/**@cond INTERNAL_MACRO */ +#define rb_fd_ptr rb_fd_ptr +#define rb_fd_max rb_fd_max +/** @endcond */ + +struct timeval; + +/** + * The data structure which wraps the fd_set bitmap used by select(2). This + * allows Ruby to use FD sets larger than that allowed by historic limitations + * on modern platforms. + */ +typedef struct { + int maxfd; /**< Maximum allowed number of FDs. */ + fd_set *fdset; /**< File descriptors buffer */ +} rb_fdset_t; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NONNULL(()) +/** + * (Re-)initialises a fdset. One must be initialised before other `rb_fd_*` + * operations. Analogous to calling `malloc(3)` to allocate an `fd_set`. + * + * @param[out] f An fdset to squash. + * @post `f` holds no file descriptors. + */ +void rb_fd_init(rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Destroys the ::rb_fdset_t, releasing any memory and resources it used. It + * must be reinitialised using rb_fd_init() before future use. Analogous to + * calling `free(3)` to release memory for an `fd_set`. + * + * @param[out] f An fdset to squash. + * @post `f` holds no file descriptors. + */ +void rb_fd_term(rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Wipes out the current set of FDs. + * + * @param[out] f The fdset to clear. + * @post `f` has no FDs. + */ +void rb_fd_zero(rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Sets an fd to a fdset. + * + * @param[in] fd A file descriptor. + * @param[out] f Target fdset. + * @post `f` holds `fd`. + */ +void rb_fd_set(int fd, rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Releases a specific FD from the given fdset. + * + * @param[in] fd Target FD. + * @param[out] f The fdset that holds `fd`. + * @post `f` doesn't hold n. + */ +void rb_fd_clr(int fd, rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE() +/** + * Queries if the given FD is in the given set. + * + * @param[in] fd Target FD. + * @param[in] f The fdset to scan. + * @retval 1 Yes there is. + * @retval 0 No there isn't. + * @see http://www.freebsd.org/cgi/query-pr.cgi?pr=91421 + */ +int rb_fd_isset(int fd, const rb_fdset_t *f); + +/** + * Destructively overwrites an fdset with another. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @param[in] max Maximum number of file descriptors to copy. + * @post `dst` is a copy of `src`. + */ +void rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max); + +/** + * Identical to rb_fd_copy(), except it copies unlimited number of file + * descriptors. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @post `dst` is a copy of `src`. + */ +void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); + +/** + * Waits for multiple file descriptors at once. + * + * @param[in] nfds Max FD in everything passed, plus one. + * @param[in,out] rfds Set of FDs to wait for reads. + * @param[in,out] wfds Set of FDs to wait for writes. + * @param[in,out] efds Set of FDs to wait for OOBs. + * @param[in,out] timeout Max blocking duration. + * @retval -1 Failed, errno set. + * @retval 0 Timeout exceeded. + * @retval otherwise Total number of file descriptors returned. + * @post `rfds` contains readable FDs. + * @post `wfds` contains writable FDs. + * @post `efds` contains exceptional FDs. + * @post `timeout` is the time left. + * @note All pointers are allowed to be null pointers. + */ +int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE() +/** + * Raw pointer to `fd_set`. + * + * @param[in] f Target fdset. + * @retval NULL `f` is already terminated by rb_fd_term(). + * @retval otherwise Underlying fd_set. + * + * @internal + * + * Extension library must not touch raw pointers. It was a bad idea to let + * them use it. + */ +static inline fd_set * +rb_fd_ptr(const rb_fdset_t *f) +{ + return f->fdset; +} + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE() +/** + * It seems this function has no use. Maybe just remove? + * + * @param[in] f A set. + * @return Number of file descriptors stored. + */ +static inline int +rb_fd_max(const rb_fdset_t *f) +{ + return f->maxfd; +} + +#endif /* RBIMPL_INTERN_SELECT_LARGESIZE_H */ diff --git a/ruby/include/ruby/internal/intern/select/posix.h b/ruby/include/ruby/internal/intern/select/posix.h new file mode 100644 index 000000000..5f828e66e --- /dev/null +++ b/ruby/include/ruby/internal/intern/select/posix.h @@ -0,0 +1,144 @@ +#ifndef RBIMPL_INTERN_SELECT_POSIX_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SELECT_POSIX_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs to provide ::rb_fd_select(). + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_SYS_SELECT_H +# include /* for select(2) (modern POSIX) */ +#endif + +#ifdef HAVE_UNISTD_H +# include /* for select(2) (archaic UNIX) */ +#endif + +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" + +/** + * The data structure which wraps the fd_set bitmap used by `select(2)`. This + * allows Ruby to use FD sets larger than what has been historically allowed on + * modern platforms. + * + * @internal + * + * ... but because this header file is included only when the system is with + * that "historic restrictions", this is nothing more than an alias of fd_set. + */ +typedef fd_set rb_fdset_t; + +/** Clears the given ::rb_fdset_t. */ +#define rb_fd_zero FD_ZERO + +/** Sets the given fd to the ::rb_fdset_t. */ +#define rb_fd_set FD_SET + +/** Unsets the given fd from the ::rb_fdset_t. */ +#define rb_fd_clr FD_CLR + +/** Queries if the given fd is in the ::rb_fdset_t. */ +#define rb_fd_isset FD_ISSET + +/** Initialises the :given :rb_fdset_t. */ +#define rb_fd_init FD_ZERO + +/** Waits for multiple file descriptors at once. */ +#define rb_fd_select select + +/**@cond INTERNAL_MACRO */ +#define rb_fd_copy rb_fd_copy +#define rb_fd_dup rb_fd_dup +#define rb_fd_ptr rb_fd_ptr +#define rb_fd_max rb_fd_max +/** @endcond */ + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_NOALIAS() +/** + * Destructively overwrites an fdset with another. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @param[in] n Unused parameter. + * @post `dst` is a copy of `src`. + */ +static inline void +rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n) +{ + *dst = *src; +} + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_NOALIAS() +/** + * Destructively overwrites an fdset with another. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @post `dst` is a copy of `src`. + */ +static inline void +rb_fd_dup(rb_fdset_t *dst, const fd_set *src) +{ + *dst = *src; +} + +RBIMPL_ATTR_PURE() +/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ +/** + * Raw pointer to `fd_set`. + * + * @param[in] f Target fdset. + * @return Underlying fd_set. + * + * @internal + * + * Extension library must not touch raw pointers. It was a bad idea to let + * them use it. + */ +static inline fd_set * +rb_fd_ptr(rb_fdset_t *f) +{ + return f; +} + +RBIMPL_ATTR_CONST() +/** + * It seems this function has no use. Maybe just remove? + * + * @param[in] f A set. + * @return Number of file descriptors stored. + */ +static inline int +rb_fd_max(const rb_fdset_t *f) +{ + return FD_SETSIZE; +} + +/** @cond INTERNAL_MACRO */ +/* :FIXME: What are these? They don't exist for shibling implementations. */ +#define rb_fd_init_copy(d, s) (*(d) = *(s)) +#define rb_fd_term(f) ((void)(f)) +/** @endcond */ + +#endif /* RBIMPL_INTERN_SELECT_POSIX_H */ diff --git a/ruby/include/ruby/internal/intern/select/win32.h b/ruby/include/ruby/internal/intern/select/win32.h new file mode 100644 index 000000000..edaf7a852 --- /dev/null +++ b/ruby/include/ruby/internal/intern/select/win32.h @@ -0,0 +1,259 @@ +#ifndef RBIMPL_INTERN_SELECT_WIN32_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SELECT_WIN32_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs to provide ::rb_fd_select(). + */ +#include "ruby/internal/dosish.h" /* for rb_w32_select */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/dllexport.h" +#include "ruby/assert.h" + +/**@cond INTERNAL_MACRO */ +#define rb_fd_zero rb_fd_zero +#define rb_fd_clr rb_fd_clr +#define rb_fd_isset rb_fd_isset +#define rb_fd_copy rb_fd_copy +#define rb_fd_dup rb_fd_dup +#define rb_fd_ptr rb_fd_ptr +#define rb_fd_max rb_fd_max +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +struct timeval; + +/** + * The data structure which wraps the fd_set bitmap used by select(2). This + * allows Ruby to use FD sets larger than that allowed by historic limitations + * on modern platforms. + */ +typedef struct { + int capa; /**< Maximum allowed number of FDs. */ + fd_set *fdset; /**< File descriptors buffer. */ +} rb_fdset_t; + +RBIMPL_ATTR_NONNULL(()) +/** + * (Re-)initialises a fdset. One must be initialised before other `rb_fd_*` + * operations. Analogous to calling `malloc(3)` to allocate an `fd_set`. + * + * @param[out] f An fdset to squash. + * @post `f` holds no file descriptors. + * + * @internal + * + * Can't this leak memory if the same `f` is passed twice...? + */ +void rb_fd_init(rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Destroys the ::rb_fdset_t, releasing any memory and resources it used. It + * must be reinitialised using rb_fd_init() before future use. Analogous to + * calling `free(3)` to release memory for an `fd_set`. + * + * @param[out] f An fdset to squash. + * @post `f` holds no file descriptors. + */ +void rb_fd_term(rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Sets an fd to a fdset. + * + * @param[in] fd A file descriptor. + * @param[out] f Target fdset. + * @post `f` holds `fd`. + */ +void rb_fd_set(int fd, rb_fdset_t *f); + +RBIMPL_ATTR_NONNULL(()) +/** + * Destructively overwrites an fdset with another. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @param[in] max Maximum number of file descriptors to copy. + * @post `dst` is a copy of `src`. + */ +void rb_w32_fd_copy(rb_fdset_t *dst, const fd_set *src, int max); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_w32_fd_copy(), except it copies unlimited number of file + * descriptors. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @post `dst` is a copy of `src`. + */ +void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); + +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_NOALIAS() +/** + * Wipes out the current set of FDs. + * + * @param[out] f The fdset to clear. + * @post `f` has no FDs. + */ +static inline void +rb_fd_zero(rb_fdset_t *f) +{ + f->fdset->fd_count = 0; +} + +RBIMPL_ATTR_NONNULL(()) +/** + * Releases a specific FD from the given fdset. + * + * @param[in] n Target FD. + * @param[out] f The fdset that holds `n`. + * @post `f` doesn't hold n. + */ +static inline void +rb_fd_clr(int n, rb_fdset_t *f) +{ + rb_w32_fdclr(n, f->fdset); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * Queries if the given FD is in the given set. + * + * @param[in] n Target FD. + * @param[in] f The fdset to scan. + * @retval 1 Yes there is. + * @retval 0 No there isn't. + */ +static inline int +rb_fd_isset(int n, rb_fdset_t *f) +{ + return rb_w32_fdisset(n, f->fdset); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * Destructively overwrites an fdset with another. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @param[in] n Maximum number of file descriptors to copy. + * @post `dst` is a copy of `src`. + */ +static inline void +rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n) +{ + rb_w32_fd_copy(dst, src, n); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_fd_copy(), except it copies unlimited number of file + * descriptors. + * + * @param[out] dst Target fdset. + * @param[in] src Source fdset. + * @post `dst` is a copy of `src`. + */ +static inline void +rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src) +{ + rb_w32_fd_dup(dst, src); +} + +/** + * Waits for multiple file descriptors at once. + * + * @param[in] n Max FD in everything passed, plus one. + * @param[in,out] rfds Set of FDs to wait for reads. + * @param[in,out] wfds Set of FDs to wait for writes. + * @param[in,out] efds Set of FDs to wait for OOBs. + * @param[in,out] timeout Max blocking duration. + * @retval -1 Failed, errno set. + * @retval 0 Timeout exceeded. + * @retval otherwise Total number of file descriptors returned. + * @post `rfds` contains readable FDs. + * @post `wfds` contains writable FDs. + * @post `efds` contains exceptional FDs. + * @post `timeout` is the time left. + * @note All pointers are allowed to be null pointers. + * + * @internal + * + * This can wait for `SOCKET` and `HANDLE` at once. In order to achieve that + * property we heavily touch the internals of MSVCRT. We `CreateFile` a + * `"NUL"` alongside of a socket and directly manipulate its `struct ioinfo`. + * This is of course a very dirty hack. If we could design the API today we + * could use `CancellIoEx`. But we are older than that Win32 API. + */ +static inline int +rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout) +{ + return rb_w32_select( + n, + rfds ? rfds->fdset : NULL, + wfds ? wfds->fdset : NULL, + efds ? efds->fdset : NULL, + timeout); +} + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE() +/** + * Raw pointer to `fd_set`. + * + * @param[in] f Target fdset. + * @retval NULL `f` is already terminated by rb_fd_term(). + * @retval otherwise Underlying fd_set. + * + * @internal + * + * Extension library must not touch raw pointers. It was a bad idea to let + * them use it. + */ +static inline fd_set * +rb_fd_ptr(const rb_fdset_t *f) +{ + return f->fdset; +} + +RBIMPL_ATTR_NONNULL(()) +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * It seems this function has no use. Maybe just remove? + * + * @param[in] f A set. + * @return Number of file descriptors stored. + */ +static inline int +rb_fd_max(const rb_fdset_t *f) +{ + const fd_set *p = f->fdset; + + RBIMPL_ASSERT_OR_ASSUME(p); + return p->fd_count; +} + +#endif /* RBIMPL_INTERN_SELECT_WIN32_H */ diff --git a/ruby/include/ruby/internal/intern/signal.h b/ruby/include/ruby/internal/intern/signal.h new file mode 100644 index 000000000..84f755840 --- /dev/null +++ b/ruby/include/ruby/internal/intern/signal.h @@ -0,0 +1,152 @@ +#ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SIGNAL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Signal handling APIs. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* signal.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Sends a signal ("kills") to processes. + * + * The first argument is the signal, either in: + * + * - Numerical representation (e.g. `9`), or + * - Textual representation of canonical (e.g. `:SIGKILL`) name or + * abbreviated (e.g. `:KILL`) name, either in ::rb_cSymbol or ::rb_cString. + * + * All the remaining arguments are numerical representations of process IDs. + * This function iterates over them to send the specified signal. + * + * You can specify both negative PIDs and negative signo to this function: + * + * ``` + * sig \ pid | >= 1 | == 0 | == -1 | <= -2 + * ===========+======+======+=======+======= + * > 0 | #1 | #2 | #3 | #4 + * == 0 | #5 | #6 | #7 | #8 + * < 0 | #9 | #10 | #11 + * ``` + * + * - Case #1: When signo and PID are both positive, this function sends the + * specified signal to the specified process (intuitive). + * + * - Case #2: When signo is positive and PID is zero, this function sends + * that signal to the current process group. + * + * - Case #3: When signo is positive and PID is -1, this function sends that + * signal to everything that the current process is allowed to kill. + * + * - Case #4: When signo is positive and PID is negative (but not -1), this + * function sends that signal to every processes in a process group, whose + * process group ID is the absolute value of the passed PID. + * + * - Case #5: When signo is zero and PID is positive, this function just + * checks for the existence of the specified process and doesn't send + * anything to anyone. In case the process is absent `Errno::ESRCH` is + * raised. + * + * - Case #6: When signo and PID are both zero, this function checks for the + * existence of the current process group. And it must do. This function + * is effectively a no-op then. + * + * - Case #7: When signo is zero and PID is -1, this function checks if there + * is any other process that the current process can kill. At least init + * (PID 1) must exist, so this must not fail. + * + * - Case #8: When signo is zero and PID is negative (but not -1), this + * function checks if there is a process group whose process group ID is + * the absolute value of the passed PID. In case the process group is + * absent `Errno::ESRCH` is raised. + * + * - Case #9: When signo is negative and PID is positive, this function sends + * the absolute value of the passed signo to the process group specified as + * the PID. + * + * - Case #10: When signo is negative and PID is zero, it is highly expected + * that this function sends the absolute value of the passed signo to the + * current process group. Strictly speaking, IEEE Std 1003.1-2017 + * specifies that this (`killpg(3posix)` with an argument of zero) is an + * undefined behaviour. But no operating system is known so far that does + * things differently. + * + * - Case #11: When signo and PID are both negative, the behaviour of this + * function depends on how `killpg(3)` works. On Linux, it seems such + * attempt is strictly prohibited and `Errno::EINVAL` is raised. But on + * macOS, it seems it tries to to send the signal actually to the process + * group. + * + * @note Above description is in fact different from how `kill(2)` works. + * We interpret the passed arguments before passing them through to + * system calls. + * @param[in] argc Number of objects in `argv`. + * @param[in] argv Signal, followed by target PIDs. + * @exception rb_eArgError Unknown signal name. + * @exception rb_eSystemCallError Various errors sending signal to processes. + * @return Something numeric. The meaning of this return value is unclear. + * It seems in case of #1 above, this could be the body count. But + * other cases remain mysterious. + */ +VALUE rb_f_kill(int argc, const VALUE *argv); + +/* This must be private, @shyouhei guesses. */ +#ifdef POSIX_SIGNAL +#define posix_signal ruby_posix_signal +void (*posix_signal(int, void (*)(int)))(int); +#endif + +RBIMPL_ATTR_PURE() +/** + * Queries the name of the signal. It returns for instance `"KILL"` for + * SIGKILL. + * + * @param[in] signo Signal number to query. + * @retval 0 No such signal. + * @retval otherwise A pointer to a static C string that is the name of + * the signal. + * @warning Don't free the return value. + */ +const char *ruby_signal_name(int signo); + +/** + * Pretends as if there was no custom signal handler. This function sets the + * signal action to SIG_DFL, then kills itself. + * + * @param[in] sig The signal. + * @post Previous signal handler is lost. + * @post Passed signal is sent to the current process. + * + * @internal + * + * @shyouhei doesn't understand the needs of this function being visible from + * extension libraries. + */ +void ruby_default_signal(int sig); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_SIGNAL_H */ diff --git a/ruby/include/ruby/internal/intern/sprintf.h b/ruby/include/ruby/internal/intern/sprintf.h new file mode 100644 index 000000000..aedc0f9ab --- /dev/null +++ b/ruby/include/ruby/internal/intern/sprintf.h @@ -0,0 +1,159 @@ +#ifndef RBIMPL_INTERN_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SPRINTF_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Our own private `printf(3)`. + */ +#include "ruby/internal/attr/format.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* sprintf.c */ + +/** + * Identical to rb_str_format(), except how the arguments are arranged. + * + * @param[in] argc Number of objects of `argv`. + * @param[in] argv A format string, followed by its arguments. + * @return A rendered new instance of ::rb_cString. + * + * @internal + * + * You can safely pass NULL to `argv`. Doesn't make any sense though. + */ +VALUE rb_f_sprintf(int argc, const VALUE *argv); + +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) +/** + * Ruby's extended `sprintf(3)`. We ended up reinventing the entire `printf` + * business because we don't want to depend on locales. OS-provided `printf` + * routines might or might not, which caused instabilities of the result + * strings. + * + * The format sequence is a mixture of format specifiers and other verbatim + * contents. Each format specifier starts with a `%`, and has the following + * structure: + * + * ``` + * %[flags][width][.precision][length]conversion + * ``` + * + * This function supports flags of ` `, `#`, `+`, `-`, `0`, width of + * non-negative decimal integer and `*`, precision of non-negative decimal + * integers and `*`, length of `L`, `h`, `t`, `z`, `l`, `ll`, `q`, conversions + * of `A`, `D`, `E`, `G`, `O`, `U`, `X`, `a`, `c`, `d`, `e`, `f`, `g`, `i`, + * `n`, `o`, `p`, `s`, `u`, `x`, and `%`. In case of `_WIN32` it also supports + * `I`. And additionally, it supports magical `PRIsVALUE` macro that can + * stringise arbitrary Ruby objects: + * + * ```CXX + * rb_sprintf("|%"PRIsVALUE"|", RUBY_Qtrue); // => "|true|" + * rb_sprintf("%+"PRIsVALUE, rb_stdin); // => "#>" + * ``` + * + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ... Variadic number of contents to format. + * @return A rendered new instance of ::rb_cString. + * + * @internal + * + * :FIXME: We can improve this document. + */ +VALUE rb_sprintf(const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0) +/** + * Identical to rb_sprintf(), except it takes a `va_list`. + * + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ap Contents to format. + * @return A rendered new instance of ::rb_cString. + */ +VALUE rb_vsprintf(const char *fmt, va_list ap); + +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +/** + * Identical to rb_sprintf(), except it renders the output to the specified + * object rather than creating a new one. + * + * @param[out] dst String to modify. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ... Variadic number of contents to format. + * @exception rb_eTypeError `dst` is not a String. + * @return Passed `dst`. + * @post `dst` has the rendered output appended to its end. + */ +VALUE rb_str_catf(VALUE dst, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((2)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) +/** + * Identical to rb_str_catf(), except it takes a `va_list`. It can also be + * seen as a routine identical to rb_vsprintf(), except it renders the output + * to the specified object rather than creating a new one. + * + * @param[out] dst String to modify. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ap Contents to format. + * @exception rb_eTypeError `dst` is not a String. + * @return Passed `dst`. + * @post `dst` has the rendered output appended to its end. + */ +VALUE rb_str_vcatf(VALUE dst, const char *fmt, va_list ap); + +/** + * Formats a string. + * + * Returns the string resulting from applying `fmt` to `argv`. The format + * sequence is a mixture of format specifiers and other verbatim contents. + * Each format specifier starts with a `%`, and has the following structure: + * + * ``` + * %[flags][width][.precision]type + * ``` + * + * ... which is different from that of rb_sprintf(). Because ruby has no + * `short` or `long`, there is no way to specify a "length" of an argument. + * + * This function supports flags of ` `, `#`, `+`, `-`, `<>`, `{}`, with of + * non-negative decimal integer and `$`, `*`, precision of non-negative decimal + * integer and `$`, `*`, type of `A`, `B`, `E`, `G`, `X`, `a`, `b`, `c`, `d`, + * `e`, `f`, `g`, `i`, `o`, `p`, `s`, `u`, `x`, `%`. This list is also + * (largely the same but) not identical to that of rb_sprintf(). + * + * @param[in] argc Number of objects in `argv`. + * @param[in] argv Format arguments. + * @param[in] fmt A printf-like format specifier. + * @exception rb_eTypeError `fmt` is not a string. + * @exception rb_eArgError Failed to parse `fmt`. + * @return A rendered new instance of ::rb_cString. + * @note Everything it takes must be Ruby objects. + * + */ +VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_SPRINTF_H */ diff --git a/ruby/include/ruby/internal/intern/string.h b/ruby/include/ruby/internal/intern/string.h new file mode 100644 index 000000000..2ee849625 --- /dev/null +++ b/ruby/include/ruby/internal/intern/string.h @@ -0,0 +1,1821 @@ +#ifndef RBIMPL_INTERN_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_STRING_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cString. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDINT_H +# include +#endif + +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/constant_p.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/variable.h" /* rb_gvar_setter_t */ +#include "ruby/st.h" /* st_index_t */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* string.c */ + +/** + * Allocates an instance of ::rb_cString. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "binary" encoding, whose contents are verbatim copy of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + */ +VALUE rb_str_new(const char *ptr, long len); + +/** + * Identical to rb_str_new(), except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @exception rb_eArgError `ptr` is a null pointer. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_str_new_cstr(const char *ptr); + +/** + * Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of + * C's. Implementation wise it creates a string that shares the backend memory + * region with the receiver. So the name. But there is no way for extension + * libraries to know if a string is of such variant. + * + * @param[in] str An object of ::RString. + * @return An allocated instance of ::rb_cString, which shares the + * encoding, length, and contents with the passed string. + * @pre `str` must not be any arbitrary object except ::RString. + * @note Use #StringValue to enforce the precondition. + */ +VALUE rb_str_new_shared(VALUE str); + +/** + * Creates a frozen copy of the string, if necessary. This function does + * nothing when the passed string is already frozen. Otherwise, it allocates a + * copy of it, which is frozen. The passed string is untouched either ways. + * + * @param[in] str An object of ::RString. + * @return Something frozen. + * @pre `str` must not be any arbitrary object except ::RString. + * @note Use #StringValue to enforce the precondition. + */ +VALUE rb_str_new_frozen(VALUE str); + +/** + * Identical to rb_str_new(), except it takes the class of the allocating + * object. + * + * @param[in] obj A string-ish object. + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of the class of `obj`, of `len` bytes length, of + * "binary" encoding, whose contents are verbatim copy of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + * + * @internal + * + * Why it doesn't take an instance of ::rb_cClass? + */ +VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len); + +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @exception rb_eArgError `ptr` is a null pointer. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_tainted_str_new_cstr(const char *ptr); + +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "binary" encoding, whose contents are verbatim copy of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + */ +VALUE rb_tainted_str_new(const char *ptr, long len); + +/** + * Identical to rb_str_new(), except it generates a string of "default + * external" encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "default external" is fully defined over + * the given contents, then the return value is a string of + * "default external" encoding, whose contents are the converted + * ones. Otherwise the string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + */ +VALUE rb_external_str_new(const char *ptr, long len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_external_str_new(), except it assumes the passed pointer is + * a pointer to a C string. It can also be seen as a routine identical to + * rb_str_new_cstr(), except it generates a string of "default external" + * encoding. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "default external" is fully defined over + * the given contents, then the return value is a string of + * "default external" encoding, whose contents are the converted + * ones. Otherwise the string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_external_str_new_cstr(const char *ptr); + +/** + * Identical to rb_str_new(), except it generates a string of "locale" + * encoding. It can also be seen as a routine identical to + * rb_external_str_new(), except it generates a string of "locale" encoding + * instead of "default external" encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "locale" is fully defined over the given + * contents, then the return value is a string of "locale" + * encoding, whose contents are the converted ones. Otherwise the + * string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + */ +VALUE rb_locale_str_new(const char *ptr, long len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_locale_str_new(), except it assumes the passed pointer is a + * pointer to a C string. It can also be seen as a routine identical to + * rb_external_str_new_cstr(), except it generates a string of "locale" + * encoding instead of "default external". + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "locale" is fully defined over the given + * contents, then the return value is a string of "locale" + * encoding, whose contents are the converted ones. Otherwise the + * string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_locale_str_new_cstr(const char *ptr); + +/** + * Identical to rb_str_new(), except it generates a string of "filesystem" + * encoding. It can also be seen as a routine identical to + * rb_external_str_new(), except it generates a string of "filesystem" encoding + * instead of "default external" encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "filesystem" is fully defined over the + * given contents, then the return value is a string of + * "filesystem" encoding, whose contents are the converted ones. + * Otherwise the string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + */ +VALUE rb_filesystem_str_new(const char *ptr, long len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_filesystem_str_new(), except it assumes the passed pointer + * is a pointer to a C string. It can also be seen as a routine identical to + * rb_external_str_new_cstr(), except it generates a string of "filesystem" + * encoding instead of "default external". + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "filesystem" is fully defined over the + * given contents, then the return value is a string of + * "filesystem" encoding, whose contents are the converted ones. + * Otherwise the string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_filesystem_str_new_cstr(const char *ptr); + +/** + * Allocates a "string buffer". A string buffer here is an instance of + * ::rb_cString, whose capacity is bigger than the length of it. If you can + * say that a string grows to a specific amount of bytes, this could be + * effective than resizing a string over and over again and again. + * + * @param[in] capa Designed capacity of the generating string. + * @return An empty string, of "binary" encoding, whose capacity is `capa`. + */ +VALUE rb_str_buf_new(long capa); + +RBIMPL_ATTR_NONNULL(()) +/** + * This is a rb_str_buf_new() + rb_str_buf_cat() combo. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + * + * @internal + * + * This must be identical to rb_str_new_cstr(), except done in inefficient way? + * @shyouhei doesn't understand why this is not a simple alias. + */ +VALUE rb_str_buf_new_cstr(const char *ptr); + +/** + * Allocates a "temporary" string. This is a hidden empty string. Handy on + * occasions. + * + * @param[in] len Designed length of the string. + * @return A hidden, empty string. + * @see rb_obj_hide() + */ +VALUE rb_str_tmp_new(long len); + +/** + * Identical to rb_str_new(), except it generates a string of "US ASCII" + * encoding. This is different from rb_external_str_new(), not only for the + * output encoding, but also it doesn't convert the contents. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "US ASCII" encoding, whose contents are verbatim copy of `ptr`. + */ +VALUE rb_usascii_str_new(const char *ptr, long len); + +/** + * Identical to rb_str_new_cstr(), except it generates a string of "US ASCII" + * encoding. It can also be seen as a routine Identical to + * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a + * C string. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @exception rb_eArgError `ptr` is a null pointer. + * @return An instance of ::rb_cString, of "US ASCII" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_usascii_str_new_cstr(const char *ptr); + +/** + * Identical to rb_str_new(), except it generates a string of "UTF-8" encoding. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "UTF-8" encoding, whose contents are verbatim copy of `ptr`. + */ +VALUE rb_utf8_str_new(const char *ptr, long len); + +/** + * Identical to rb_str_new_cstr(), except it generates a string of "UTF-8" + * encoding. It can also be seen as a routine Identical to + * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a + * C string. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @exception rb_eArgError `ptr` is a null pointer. + * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents + * are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_utf8_str_new_cstr(const char *ptr); + +/** + * @name Special strings that are backended by C string literals. + * + * *_str_new_static functions are intended for C string literals. + * They require memory in the range [ptr, ptr+len] to always be readable. + * Note that this range covers a total of len + 1 bytes. + * + * @{ + */ + +/** + * Identical to rb_str_new(), except it takes a C string literal. + * + * @param[in] ptr A C string literal. + * @param[in] len `strlen(ptr)`. + * @exception rb_eArgError `len` out of range of `size_t`. + * @pre `ptr` must be a C string constant. + * @return An instance of ::rb_cString, of "binary" encoding, whose backend + * storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + * + * @internal + * + * Surprisingly it can take NULL, and generates an empty string. + */ +VALUE rb_str_new_static(const char *ptr, long len); + +/** + * Identical to rb_str_new_static(), except it generates a string of "US ASCII" + * encoding instead of "binary". It can also be seen as a routine identical to + * rb_usascii_str_new(), except it takes a C string literal. + * + * @param[in] ptr A C string literal. + * @param[in] len `strlen(ptr)`. + * @exception rb_eArgError `len` out of range of `size_t`. + * @pre `ptr` must be a C string constant. + * @return An instance of ::rb_cString, of "US ASCII" encoding, whose + * backend storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +VALUE rb_usascii_str_new_static(const char *ptr, long len); + +/** + * Identical to rb_str_new_static(), except it generates a string of "UTF-8" + * encoding instead of "binary". It can also be seen as a routine identical to + * rb_utf8_str_new(), except it takes a C string literal. + * + * @param[in] ptr A C string literal. + * @param[in] len `strlen(ptr)`. + * @exception rb_eArgError `len` out of range of `size_t`. + * @pre `ptr` must be a C string constant. + * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend + * storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +VALUE rb_utf8_str_new_static(const char *ptr, long len); + +/** @} */ + +/** + * Identical to rb_interned_str(), except it takes a Ruby's string instead of + * C's. It can also be seen as a routine identical to to rb_str_new_shared(), + * except it returns an infamous "f"string. + * + * @param[in] str An object of ::RString. + * @return An instance of ::rb_cString, either cached or allocated, which + * has the identical encoding, length, and contents with the passed + * string. + * @pre `str` must not be any arbitrary object except ::RString. + * @note Use #StringValue to enforce the precondition. + * + * @internal + * + * It actually finds or creates a fstring of the needed property, and + * destructively modifies the receiver behind-the-scene so that it becomes a + * shared string whose parent is the returning fstring. + */ +VALUE rb_str_to_interned_str(VALUE str); + +/** + * Identical to rb_str_new(), except it returns an infamous "f"string. What is + * a fstring? Well it is a special subkind of strings that is immutable, + * deduped globally, and managed by our GC. It is much like a Symbol (in fact + * Symbols are dynamic these days and are backended using fstrings). This + * concept has been silently introduced at some point in 2.x era. Since then + * it gained wider acceptance in the core. Starting from 3.x extension + * libraries can also generate ones. + * + * @param[in] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eArgError `len` is negative. + * @return A found or created instance of ::rb_cString, of `len` bytes + * length, of "binary" encoding, whose contents are identical to + * that of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + */ +VALUE rb_interned_str(const char *ptr, long len); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_interned_str(), except it assumes the passed pointer is a + * pointer to a C's string. It can also be seen as a routine identical to to + * rb_str_to_interned_str(), except it takes a C's string instead of Ruby's. + * Or it can also be seen as a routine identical to rb_str_new_cstr(), except + * it returns an infamous "f"string. + * + * @param[in] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_interned_str_cstr(const char *ptr); + +/** + * Destroys the given string for no reason. + * + * @warning DO NOT USE IT. + * @warning Leave this task to our GC. + * @warning It was a bad idea at the first place to let you know about it. + * + * @param[out] str The string to be executed. + * @post The given string no longer exists. + * @note Maybe `String#clear` could be what you want. + * + * @internal + * + * Should have moved this to `internal/string.h`. + */ +void rb_str_free(VALUE str); + +/** + * Replaces the contents of the former with the latter. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @pre Both objects must not be any arbitrary objects except + * ::RString. + * @post `dst`'s former components are abandoned. It now has the + * identical encoding, length, and contents to `src`. + * @see rb_str_replace() + * + * @internal + * + * @shyouhei doesn't understand why this is useful to extension libraries. + * Just use rb_str_replace(). What's wrong with that? + */ +void rb_str_shared_replace(VALUE dst, VALUE src); + +/** + * Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of + * C's. It can also be seen as a routine identical to rb_str_shared_replace(), + * except it appends instead of replaces. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @exception rb_eEncCompatError Can't mix the encodings. + * @exception rb_eArgError Result string too big. + * @return The passed `dst`. + * @pre Both objects must not be any arbitrary objects except + * ::RString. + * @post `dst` has the contents of `src` appended, with encoding + * converted into `dst`'s one, into the end of `dst`. + */ +VALUE rb_str_buf_append(VALUE dst, VALUE src); + +/** @alias{rb_str_cat} */ +VALUE rb_str_buf_cat(VALUE, const char*, long); + +/** @alias{rb_str_cat_cstr} */ +VALUE rb_str_buf_cat2(VALUE, const char*); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_str_cat_cstr(), except it additionally assumes the source + * string be a NUL terminated ASCII string. + * + * @param[out] dst Destination object. + * @param[in] src Source string. + * @exception rb_eArgError Result string too big. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary object except ::RString. + * @pre `src` must be a NUL terminated ASCII string. + * @post `dst` has the contents of `src` appended, with encoding + * converted into `dst`'s one, into the end of `dst`. + */ +VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src); + +/** + * Try converting an object to its stringised representation using its `to_s` + * method, if any. If there is no such thing, it resorts to rb_any_to_s() + * output. + * + * @param[in] obj Arbitrary ruby object to stringise. + * @return An instance of ::rb_cString. + */ +VALUE rb_obj_as_string(VALUE obj); + +/** + * Try converting an object to its stringised representation using its `to_str` + * method, if any. If there is no such thing, returns ::RUBY_Qnil. + * + * @param[in] obj Arbitrary ruby object to stringise. + * @exception rb_eTypeError `obj.to_str` returned something non-String. + * @retval RUBY_Qnil No conversion from obj to String defined. + * @return otherwise Stringised representation of `obj`. + * @see rb_io_check_io + * @see rb_check_array_type + * @see rb_check_hash_type + */ +VALUE rb_check_string_type(VALUE obj); + +/** + * Asserts that the given string's encoding is (Ruby's definition of) ASCII + * compatible. + * + * @param[in] obj An instance of ::rb_cString. + * @exception rb_eEncCompatError `obj` is ASCII incompatible. + * + * @internal + * + * @shyouhei doesn't know if this is an Easter egg or an official feature, but + * this function can in fact take non-strings such as Symbols, Regexps, IOs, + * etc. However if something unsupported is passed, it causes SEGV. It seems + * the feature is kind of untested. + */ +void rb_must_asciicompat(VALUE obj); + +/** + * Duplicates a string. + * + * @param[in] str String in question to duplicate. + * @return A duplicated new instance. + * @pre `str` must be of ::RString. + */ +VALUE rb_str_dup(VALUE str); + +/** + * I guess there is no use case of this function in extension libraries, but + * this is a routine identical to rb_str_dup(), except it always creates an + * instance of ::rb_cString regardless of the given object's class. This makes + * the most sense when the passed string is formerly hidden by rb_obj_hide(). + * + * @param[in] str A string, possibly hidden. + * @return A duplicated new instance of ::rb_cString. + */ +VALUE rb_str_resurrect(VALUE str); + +/** + * Obtains a "temporary lock" of the string. This advisory locking mechanism + * prevents other cooperating threads from tampering the receiver. The same + * thing could be done via freeze mechanism, but this one can also be unlocked + * using rb_str_unlocktmp(). + * + * @param[out] str String to lock. + * @exception rb_eRuntimeError `str` already locked. + * @return The given string. + * @post The string is locked. + */ +VALUE rb_str_locktmp(VALUE str); + +/** + * Releases a lock formerly obtained by rb_str_locktmp(). + * + * @param[out] str String to unlock. + * @exception rb_eRuntimeError `str` already unlocked. + * @return The given string. + * @post The string is locked. + */ +VALUE rb_str_unlocktmp(VALUE str); + +/** @alias{rb_str_new_frozen} */ +VALUE rb_str_dup_frozen(VALUE); + +/** @alias{rb_str_new_frozen} */ +#define rb_str_dup_frozen rb_str_new_frozen + +/** + * Generates a new string, concatenating the former to the latter. It can also + * be seen as a routine identical to rb_str_append(), except it doesn't tamper + * the passed strings to create a new one instead. + * + * @param[in] lhs Source string #1. + * @param[in] rhs Source string #2. + * @exception rb_eEncCompatError Can't mix the encodings. + * @exception rb_eArgError Result string too big. + * @return A new string containing `rhs` concatenated to `lhs`. + * @pre Both objects must not be any arbitrary objects except ::RString. + * @note This operation doesn't commute. Don't get confused by the + * "plus" terminology. For historical reasons there are some + * noncommutative `+`s in Ruby. This is one of such things. There + * has been a long discussion around `+`s in programming languages. + */ +VALUE rb_str_plus(VALUE lhs, VALUE rhs); + +/** + * Repetition of a string. + * + * @param[in] str String to repeat. + * @param[in] num Count, something numeric. + * @exception rb_eArgError `num` is negative. + * @return A new string repeating `num` times of `str`. + */ +VALUE rb_str_times(VALUE str, VALUE num); + +/** + * Byte offset to character offset conversion. This makes sense when the + * receiver is in a multibyte encoding. The string's i-th character does not + * always sit at its i-th byte. This function scans the contents to find the + * character index that matches the byte index. Generally speaking this is an + * `O(n)` operation. Could be slow. + * + * @param[in] str The string to scan. + * @param[in] pos Offset, in bytes. + * @return Offset, in characters. + */ +long rb_str_sublen(VALUE str, long pos); + +/** + * This is the implementation of two-argumented `String#slice`. + * + * - Returns the substring of the given `len` found in `str` at offset `beg`: + * + * ```ruby + * 'foo'[0, 2] # => "fo" + * 'foo'[0, 0] # => "" + * ``` + * + * - Counts backward from the end of `str` if `beg` is negative: + * + * ```ruby + * 'foo'[-2, 2] # => "oo" + * ``` + * + * - Special case: returns a new empty string if `beg` is equal to the length + * of `str`: + * + * ```ruby + * 'foo'[3, 2] # => "" + * ``` + * + * - Returns a null pointer if `beg` is out of range: + * + * ```ruby + * 'foo'[4, 2] # => nil + * 'foo'[-4, 2] # => nil + * ``` + * + * - Returns the trailing substring of `str` if `len` is large: + * + * ```ruby + * 'foo'[1, 50] # => "oo" + * ``` + * + * - Returns a null pointer if `len` is negative: + * + * ```ruby + * 'foo'[0, -1] # => nil + * ``` + * + * @param[in] str The string to slice. + * @param[in] beg Requested offset of the substring. + * @param[in] len Requested length of the substring. + * @retval RUBY_Qnil Parameters out of range. + * @retval otherwise A new string whose contents is the specified + * substring of `str`. + * @pre `str` must not be any arbitrary objects except ::RString. + */ +VALUE rb_str_substr(VALUE str, long beg, long len); + +/** + * Identical to rb_str_substr(), except the numbers are interpreted as byte + * offsets instead of character offsets. + * + * @param[in] str The string to slice. + * @param[in] beg Requested offset of the substring. + * @param[in] len Requested length of the substring. + * @return A new string whose contents is the specified substring of `str`. + * @pre `str` must not be any arbitrary objects except ::RString. + * @pre `beg` and `len` must not point to OOB contents. + */ +VALUE rb_str_subseq(VALUE str, long beg, long len); + +/** + * Identical to rb_str_substr(), except it returns a C's string instead of + * Ruby's. + * + * @param[in] str The string to slice. + * @param[in] beg Requested offset of the substring. + * @param[in,out] len Requested length of the substring. + * @retval NULL Parameters out of range. + * @retval otherwise A pointer inside of `str`'s backend storage where + * the specified substring exist. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post `len` is updated to have the length of the return value. + */ +char *rb_str_subpos(VALUE str, long beg, long *len); + +/** + * Declares that the string is about to be modified. This for instance let the + * string have a dedicated backend storage. + * + * @param[out] str String about to be modified. + * @exception rb_eRuntimeError `str` is `locktmp`-ed. + * @exception rb_eFrozenError `str` is frozen. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post Upon successful return the passed string is eligible to be + * modified. + */ +void rb_str_modify(VALUE str); + +/** + * Identical to rb_str_modify(), except it additionally expands the capacity of + * the receiver. + * + * @param[out] str Target string to modify. + * @param[in] capa Additional capacity to add. + * @exception rb_eArgError `capa` is negative. + * @exception rb_eRuntimeError `str` is `locktmp`-ed. + * @exception rb_eFrozenError `str` is frozen. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post Upon successful return the passed string is modified so that + * its capacity is increased for `capa` bytes. + */ +void rb_str_modify_expand(VALUE str, long capa); + +/** + * This is the implementation of `String#freeze`. + * + * @param[out] str Target string to freeze. + * @return The passed string. + * @post Upon successful return the passed string is frozen. + */ +VALUE rb_str_freeze(VALUE str); + +/** + * Overwrites the length of the string. Typically this is used to shrink a + * string that was formerly expanded. + * + * ```CXX + * extern int fd; + * auto str = rb_eval_string("'...'"); + * rb_str_modify_expand(str, BUFSIZ); + * if (auto len = recv(fd, RSTRING_PTR(str), BUFSIZ, 0); len >= 0) { + * rb_str_set_len(str, len); + * } + * else { + * rb_sys_fail("recv(2)"); + * } + * ``` + * + * @param[out] str String to shrink. + * @param[in] len New length of the string. + * @exception rb_eRuntimeError `str` is `locktmp`-ed. + * @exception rb_eFrozenError `str` is frozen. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post Upon successful return `str`'s length is set to `len`. + */ +void rb_str_set_len(VALUE str, long len); + +/** + * Overwrites the length of the string. In contrast to rb_str_set_len(), this + * function can also expand a string. + * + * @param[out] str String to shrink. + * @param[in] len New length of the string. + * @exception rb_eArgError `len` is negative. + * @exception rb_eRuntimeError `str` is `locktmp`-ed. + * @exception rb_eFrozenError `str` is frozen. + * @return The passed `str`. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post Upon successful return `str` is either expanded or shrunken to + * have its length be `len`. + */ +VALUE rb_str_resize(VALUE str, long len); + +/** + * Destructively appends the passed contents to the string. + * + * @param[out] dst Destination object. + * @param[in] src Contents to append. + * @param[in] srclen Length of `src`. + * @exception rb_eArgError `srclen` is negative. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary objects except ::RString. + * @post `dst` has the contents of `ptr` appended. + */ +VALUE rb_str_cat(VALUE dst, const char *src, long srclen); + +/** + * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[out] dst Destination object. + * @param[in] src Contents to append. + * @exception rb_eArgError Result string too big. + * @exception rb_eArgError `src` is a null pointer. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary objects except ::RString. + * @pre `src` must not be a null pointer. + * @post `dst` has the contents of `src` appended. + */ +VALUE rb_str_cat_cstr(VALUE dst, const char *src); + +/** @alias{rb_str_cat_cstr} */ +VALUE rb_str_cat2(VALUE, const char*); + +/** + * Identical to rb_str_buf_append(), except it converts the right hand side + * before concatenating. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @exception rb_eEncCompatError Can't mix the encodings. + * @exception rb_eArgError Result string too big. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary objects except ::RString. + * @post `dst` has the contents of `src` appended, with encoding + * converted into `dst`'s one, into the end of `dst`. + */ +VALUE rb_str_append(VALUE dst, VALUE src); + +/** + * Identical to rb_str_append(), except it also accepts an integer as a + * codepoint. This resembles `String#<<`. + * + * @param[out] dst Destination object. + * @param[in] src Source object, String or Numeric. + * @exception rb_eRangeError Source numeric is out of range. + * @exception rb_eEncCompatError Source string too long. + * @exception rb_eArgError Result string too big. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary objects except ::RString. + * @post `dst` has the contents of `src` appended, with encoding + * converted into `dst`'s one, into the end of `dst`. + */ +VALUE rb_str_concat(VALUE dst, VALUE src); + +/* random.c */ + +/** + * This is a universal hash function. + * + * @warning This function changes its value per process. + * @param[in] ptr Target message. + * @param[in] len Length of `ptr` in bytes. + * @return A pseudorandom number suitable for Hash's hash value. + * @see Aumasson, JP., Bernstein, D.J., "SipHash: A Fast Short-Input + * PRF", In proceedings of 13th International Conference on + * Cryptology in India (INDOCRYPT 2012), LNCS 7668, pp. 489-508, + * 2012. http://doi.org/10.1007/978-3-642-34931-7_28 +*/ +st_index_t rb_memhash(const void *ptr, long len); + +/** + * Starts a series of hashing. Suppose you have a struct: + * + * ```CXX + * struct foo_tag { + * unsigned char bar; + * uint32_t baz; + * }; + * ``` + * + * It is not a wise idea to call rb_memhash() over it, because there could be + * padding bits. Instead you should explicitly iterate over each fields: + * + * ```CXX + * foo_tag foo = { 0, 0, }; + * st_index_t hash = 0; + * + * hash = rb_hash_start(0); + * hash = rb_hash_uint(hash, foo.bar); + * hash = rb_hash_uint32(hash, foo.baz); + * hash = rb_hash_end(hash); + * ``` + * + * @param[in] i Initial value. + * @return A hash value. + */ +st_index_t rb_hash_start(st_index_t i); + +/** @alias{st_hash_uint32} */ +#define rb_hash_uint32(h, i) st_hash_uint32((h), (i)) + +/** @alias{st_hash_uint} */ +#define rb_hash_uint(h, i) st_hash_uint((h), (i)) + +/** @alias{st_hash_end} */ +#define rb_hash_end(h) st_hash_end(h) + +/* string.c */ + +/** + * Calculates a hash value of a string. This is one of the two functions that + * constructs struct ::st_hash_type. + * + * @param[in] str An object of ::RString. + * @return A hash value. + * @pre `str` must not be any arbitrary object except ::RString. + * + * @internal + * + * Although safe to call, there must be no particular use case of this function + * for extension libraries. Only ruby internals must know about it. + * + * This is not a simple alias of rb_memhash(), because it considers the passed + * string's encoding as well as its contents. + */ +st_index_t rb_str_hash(VALUE str); + +/** + * Compares two strings. This is one of the two functions that constructs + * struct ::st_hash_type. + * + * @param[in] str1 A string. + * @param[in] str2 Another string. + * @retval 1 They have identical contents, length, and encodings. + * @retval 0 Otherwise. + * @pre Both objects must not be any arbitrary objects except + * ::RString. + * + * @internal + * + * In contrast to rb_str_hash(), this could be handy for comparison that only + * concerns equality. rb_str_cmp() returns 1, 0, -1. + */ +int rb_str_hash_cmp(VALUE str1, VALUE str2); + +/** + * Checks if two strings are comparable each other or not. Because + * rb_str_cmp() must return "lesser than" or "greater than" information, + * comparing two strings needs a stricter restriction. Both sides must be in a + * same set of strings which have total order. This is to check that property. + * Intuitive it sounds? But they can have different encodings. A character + * and another might or might not appear in the same order in their codepoints. + * It is complicated than you think. + * + * @param[in] str1 A string. + * @param[in] str2 Another string. + * @retval 1 They agree on a total order. + * @retval 0 Otherwise. + * @pre Both objects must not be any arbitrary objects except + * ::RString. + */ +int rb_str_comparable(VALUE str1, VALUE str2); + +/** + * Compares two strings, as in `strcmp(3)`. This does not consider the current + * locale, but considers the encodings of both sides instead. + * + * @param[in] lhs A string. + * @param[in] rhs Another string. + * @retval -1 `lhs` is "bigger than" `rhs`. + * @retval 1 `rhs` is "bigger than" `lhs`. + * @retval 0 Otherwise, e.g. not comparable. + * @pre Both objects must not be any arbitrary objects except + * ::RString. + */ +int rb_str_cmp(VALUE lhs, VALUE rhs); + +/** + * Equality of two strings. + * + * If `str2` is not a String, it resorts to `str2 == str1`. Otherwise if they + * are not comparable, returns ::RUBY_Qfalse. Otherwise if they have the same + * contents and the length, returns ::RUBY_Qtrue. Otherwise, returns + * ::RUBY_Qfalse. + * + * @param[in] str1 A string. + * @param[in] str2 Another string. + * @retval RUBY_Qtrue They are equal. + * @retval RUBY_Qfalse They are either different, or not comparable. + */ +VALUE rb_str_equal(VALUE str1, VALUE str2); + +/** + * Shrinks the given string for the given number of bytes. + * + * @param[out] str String to squash. + * @param[in] len Number of bytes to reduce. + * @exception rb_eRuntimeError `str` is `locktmp`-ed. + * @exception rb_eFrozenError `str` is frozen. + * @return The passed `str`. + * @pre `str` must not be any arbitrary objects except ::RString. + * @post `str` is shrunken. + * @warning Can break a multibyte character in middle. + * + * @internal + * + * What if `len` is negative? + */ +VALUE rb_str_drop_bytes(VALUE str, long len); + +/** + * Replaces some (or all) of the contents of the given string. This is the + * implementation of three-argumented `String#[]=`. + * + * @param[out] dst Target string to update. + * @param[in] beg Offset of the affected portion. + * @param[in] len Length of the affected portion. + * @param[in] src Object to be assigned. + * @exception rb_eTypeError `src` has no implicit conversion to String. + * @exception rb_eIndexError `len` is negative, or `beg` is OOB. + * @exception rb_eRuntimeError `dst` is `locktmp`-ed. + * @exception rb_eFrozenError `dst` is frozen. + * @note Unlike rb_str_substr(), this function raises. + * @post A portion of `dst` from `beg` to `len` is the stringised + * representation of `src`. If that replacement string is not the + * same length as the portion it is replacing, `dst` will be + * resized accordingly. + */ +void rb_str_update(VALUE dst, long beg, long len, VALUE src); + +/** + * Replaces the contents of the former object with the stringised contents of + * the latter. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @exception rb_eTypeError `src` has no implicit conversion to String. + * @exception rb_eRuntimeError `dst` is `locktmp`-ed. + * @exception rb_eFrozenError `dst` is frozen. + * @return The passed `dst`. + * @pre `dst` must not be any arbitrary object except ::RString. + * @post `dst`'s former components are abandoned. It now has the + * identical encoding, length, and contents to `src`. + */ +VALUE rb_str_replace(VALUE dst, VALUE src); + +/** + * Generates a "readable" version of the receiver. + * + * @warning The output is _insecure_. Never feed one to `eval`. + * @warning The output is not always in the same encoding as the given one. + * @warning A character might or might not be escaped, depending on the + * result encoding. + * @param[in] str String to inspect. + * @return Its inspection, either in default internal encoding if any, or + * in default external encoding otherwise. + * @see rb_str_dump() + * + * @internal + * + * This is a (silent) fix of an actual vulnerability feeding `inspect` output + * strings to `eval`: + * https://github.com/hiki/hiki/commit/8771a6e25198e264a2bf9dc1c102fea2cc8ff975 + * + * ... and its advisory: + * http://hikiwiki.org/en/advisory20040712.html + */ +VALUE rb_str_inspect(VALUE str); + +/** + * "Inverse" of rb_eval_string(). Returns a quoted version of the string. All + * non-printing characters are replaced by `\uNNNN` or `\xHH` notation and all + * special characters are escaped. The result string is guaranteed to render a + * string of the same contents when passed to `eval` and friends. + * + * @param[in] str String to dump. + * @exception rb_eRuntimeError Too many escape sequences causes integer + * overflow on the length of the string. + * @return An US-ASCII string that includes all the necessary info to + * reconstruct the original string. + */ +VALUE rb_str_dump(VALUE str); + +/** + * Divides the given string based on the given delimiter. This is the + * 1-argument 0-block version of `String#split`. + * + * @param[in] str Object in question to split. + * @param[in] delim Delimiter, in C string. + * @exception rb_eTypeError `str` has no implicit conversion to String. + * @exception rb_eArgError `delim` is a null pointer. + * @return An array of strings, which are substrings of the passed `str`. + * If `delim` is an empty C string (i.e. `""`), `str` is split into + * each characters. If `delim` is a C string whose sole content is + * a whitespace (i.e. `" "`), `str` is split on whitespaces, with + * leading and trailing whitespace and runs of contiguous + * whitespace characters ignored. Otherwise, `str` is split + * according to `delim`. + */ +VALUE rb_str_split(VALUE str, const char *delim); + +/** + * This is a ::rb_gvar_setter_t that refutes non-string assignments. + * + * @exception rb_eTypeError Passed something non-string. + */ +rb_gvar_setter_t rb_str_setter; + +/* symbol.c */ + +/** + * Identical to rb_to_symbol(), except it assumes the receiver being an + * instance of ::RString. + * + * @param[in] str The name of the id. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given `str`. + * @pre `str` must not be any arbitrary object except ::RString. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become dynamic ones; i.e. would be garbage collected. It could + * be safer for you to use it than alternatives, when applicable. + */ +VALUE rb_str_intern(VALUE str); + +/* string.c */ + +/** + * This is an rb_sym2str() + rb_str_dup() combo. + * + * @param[in] sym A symbol to query. + * @return A string duplicating the symbol's backend storage. + * + * @internal + * + * This function causes SEGV when the passed value is a static symbol that + * doesn't exist. + */ +VALUE rb_sym_to_s(VALUE sym); + +/** + * Counts the number of characters (not bytes) that are stored inside of the + * given string. This of course depends on its encoding. Also this function + * generally runs in O(n), because for instance you have to scan the entire + * string to know how many characters are there in a UTF-8 string. + * + * @param[in] str Target string to query. + * @return Its number of characters. + */ +long rb_str_strlen(VALUE str); + +/** + * Identical to rb_str_strlen(), except it returns the value in ::rb_cInteger. + * + * @param[in] str Target string to query. + * @return Its number of characters. + */ +VALUE rb_str_length(VALUE); + +/** + * "Inverse" of rb_str_sublen(). This function scans the contents to find the + * byte index that matches the character index. Generally speaking this is an + * `O(n)` operation. Could be slow. + * + * @param[in] str The string to scan. + * @param[in] pos Offset, in characters. + * @return Offset, in bytes. + */ +long rb_str_offset(VALUE str, long pos); + +RBIMPL_ATTR_PURE() +/** + * Queries the capacity of the given string. + * + * @see ::RString::capa + * @param[in] str String in question. + * @return Its capacity. + */ +size_t rb_str_capacity(VALUE str); + +/** + * Shortens `str` and adds three dots, an ellipsis, if it is longer than `len` + * characters. The length of the returned string in characters is less than or + * equal to `len`. If the length of `str` is less than or equal `len`, returns + * `str` itself. The encoding of returned string is equal to that of passed + * one. The class of returned string is equal to that of passed one. + * + * @param[in] str The string to shorten. + * @param[in] len The maximum string length. + * @exception rb_eIndexError `len` is negative. + * @retval str No need to add ellipsis. + * @retval otherwise A new, shortened string. + * @note The length is counted in characters. + */ +VALUE rb_str_ellipsize(VALUE str, long len); + +/** + * "Cleanses" the string. A string has its encoding and its contents. They, + * in practice, do not always fit. There are strings in the wild that are + * "broken"; include bit patterns that are not allowed by its encoding. That + * can happen when a user copy&pasted something bad, network input got + * clobbered by a middleman, cosmic rays hit the physical memory, and many more + * occasions. This function takes such strings, and fills the "broken" portion + * with the passed replacement bit pattern. + * + * This function also takes a ruby block. That is a neat way to do things, but + * can be annoying when the caller function want to use a block for another + * purpose. + * + * @param[in] str Target string to scrub. + * @param[in] repl Replacement string. When it is a string, + * this function takes that as a replacement. + * When it is ::RUBY_Qnil, this function tries + * to yield a block (if any) and takes its + * evaluated value as a replacement. In case + * of ::RUBY_Qnil without a block, this + * function takes an encoding-specific default + * character (`U+FFFD`, for instance) as a last + * resort. + * @exception rb_eTypeError `repl` is neither string nor nil. + * @exception rb_eArgError `repl` itself is broken. + * @exception rb_eEncCompatError `repl` and `str` are incompatible. + * @retval RUBY_Qnil `str` is already clean. + * @retval otherwise A new, clean string. + */ +VALUE rb_str_scrub(VALUE str, VALUE repl); + +/** + * Searches for the "successor" of a string. This function is complicated! + * This is the only function in the entire ruby API (either C or Ruby) that + * generates a string out of thin air. First, the successor to an empty string + * is a new empty string: + * + * ```ruby + * ''.succ # => "" + * ``` + * + * Otherwise the successor is calculated by "incrementing" characters. The + * first character to be incremented is the rightmost alphanumeric: or, if no + * alphanumerics, the rightmost character: + * + * ```ruby + * 'THX1138'.succ # => "THX1139" + * '<>'.succ # => "<>" + * '***'.succ # => '**+' + * ``` + * + * The successor to a digit is another digit, "carrying" to the next-left + * character for a "rollover" from 9 to 0, and prepending another digit if + * necessary: + * + * ```ruby + * '00'.succ # => "01" + * '09'.succ # => "10" + * '99'.succ # => "100" + * '-9'.succ # => "-10" + * ``` + * + * The successor to a letter is another letter of the same case, carrying to + * the next-left character for a rollover, and prepending another same-case + * letter if necessary: + * + * ```ruby + * 'aa'.succ # => "ab" + * 'az'.succ # => "ba" + * 'zz'.succ # => "aaa" + * 'AA'.succ # => "AB" + * 'AZ'.succ # => "BA" + * 'ZZ'.succ # => "AAA" + * ``` + * + * The successor to a non-alphanumeric character is the next character in the + * underlying character set's collating sequence, carrying to the next-left + * character for a rollover, and prepending another character if necessary: + * + * ```ruby + * s = "\u03A1" + * s.succ # => "\u03A3" # There is no such thing like \u03A2. + * s = 255.chr * 3 + * s # => "\xFF\xFF\xFF" + * s.succ # => "\x01\x00\x00\x00" + * ``` + * + * Carrying can occur between and among mixtures of alphanumeric characters: + * + * ```ruby + * s = 'zz99zz99' + * s.succ # => "aaa00aa00" + * s = '99zz99zz' + * s.succ # => "100aa00aa" + * s = '1.9.9' + * s.succ # => "2.0.0" + * ``` + * + * @param[in] orig Predecessor string. + * @return Successor string. + */ +VALUE rb_str_succ(VALUE orig); + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string. + * @return `strlen`, casted to `long`. + */ +static inline long +rbimpl_strlen(const char *str) +{ + return RBIMPL_CAST((long)strlen(str)); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_str_new_static(str, len); +} + +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_tainted_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_tainted_str_new(str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_usascii_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_usascii_str_new_static(str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_utf8_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_utf8_str_new_static(str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_external_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_external_str_new(str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_locale_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_locale_str_new(str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_str_buf_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + VALUE buf = rb_str_buf_new(len); + return rb_str_buf_cat(buf, str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[out] buf A string buffer. + * @param[in] str A C string literal. + * @return `buf` itself. + */ +static inline VALUE +rbimpl_str_cat_cstr(VALUE buf, const char *str) +{ + long len = rbimpl_strlen(str); + return rb_str_cat(buf, str, len); +} + +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] exc An exception class. + * @param[in] str A C string literal. + * @return An instance of `exc`. + */ +static inline VALUE +rbimpl_exc_new_cstr(VALUE exc, const char *str) +{ + long len = rbimpl_strlen(str); + return rb_exc_new(exc, str, len); +} + +/** + * Allocates an instance of ::rb_cString. + * + * @param[in] str A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "binary" encoding, whose contents are verbatim copy of `str`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `str`. + */ +#define rb_str_new(str, len) \ + ((RBIMPL_CONSTANT_P(str) && \ + RBIMPL_CONSTANT_P(len) ? \ + rb_str_new_static : \ + rb_str_new) ((str), (len))) + +/** + * Identical to #rb_str_new, except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_str_new_cstr : \ + rb_str_new_cstr) (str)) + +/** + * Identical to #rb_str_new, except it generates a string of "US ASCII" + * encoding. This is different from rb_external_str_new(), not only for the + * output encoding, but also it doesn't convert the contents. + * + * @param[in] str A memory region of `len` bytes length. + * @param[in] len Length of `str`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "US ASCII" encoding, whose contents are verbatim copy of `str`. + */ +#define rb_usascii_str_new(str, len) \ + ((RBIMPL_CONSTANT_P(str) && \ + RBIMPL_CONSTANT_P(len) ? \ + rb_usascii_str_new_static : \ + rb_usascii_str_new) ((str), (len))) + +/** + * Identical to #rb_str_new, except it generates a string of "UTF-8" encoding. + * + * @param[in] str A memory region of `len` bytes length. + * @param[in] len Length of `str`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "UTF-8" encoding, whose contents are verbatim copy of `str`. + */ +#define rb_utf8_str_new(str, len) \ + ((RBIMPL_CONSTANT_P(str) && \ + RBIMPL_CONSTANT_P(len) ? \ + rb_utf8_str_new_static : \ + rb_utf8_str_new) ((str), (len))) + +/** + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_tainted_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_tainted_str_new_cstr : \ + rb_tainted_str_new_cstr) (str)) + +/** + * Identical to #rb_str_new_cstr, except it generates a string of "US ASCII" + * encoding. It can also be seen as a routine Identical to + * #rb_usascii_str_new, except it assumes the passed pointer is a pointer to a + * C string. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "US ASCII" encoding, whose + * contents are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_usascii_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_usascii_str_new_cstr : \ + rb_usascii_str_new_cstr) (str)) + +/** + * Identical to #rb_str_new_cstr, except it generates a string of "UTF-8" + * encoding. It can also be seen as a routine Identical to #rb_utf8_str_new, + * except it assumes the passed pointer is a pointer to a C string. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents + * are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_utf8_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_utf8_str_new_cstr : \ + rb_utf8_str_new_cstr) (str)) + +/** + * Identical to #rb_str_new_cstr, except it generates a string of "default + * external" encoding. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "default external" is fully defined over + * the given contents, then the return value is a string of + * "default external" encoding, whose contents are the converted + * ones. Otherwise the string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * @pre `str` must not be a null pointer. + */ +#define rb_external_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_external_str_new_cstr : \ + rb_external_str_new_cstr) (str)) + +/** + * Identical to #rb_external_str_new_cstr, except it generates a string of + * "locale" encoding instead of "default external". + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString. In case encoding conversion from + * "default internal" to "locale" is fully defined over the given + * contents, then the return value is a string of "locale" + * encoding, whose contents are the converted ones. Otherwise the + * string is a junk. + * @warning It doesn't raise on a conversion failure and silently ends up in + * a corrupted output. You can know the failure by querying + * `valid_encoding?` of the result object. + * @pre `str` must not be a null pointer. + */ +#define rb_locale_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_locale_str_new_cstr : \ + rb_locale_str_new_cstr) (str)) + +/** + * Identical to #rb_str_new_cstr, except done differently. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_str_buf_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_str_buf_new_cstr : \ + rb_str_buf_new_cstr) (str)) + +/** + * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[out] buf Destination object. + * @param[in] str Contents to append. + * @exception rb_eArgError Result string too big. + * @return The passed `buf`. + * @pre `buf` must not be any arbitrary objects except ::RString. + * @pre `str` must not be a null pointer. + * @post `buf` has the contents of `str` appended. + */ +#define rb_str_cat_cstr(buf, str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_str_cat_cstr : \ + rb_str_cat_cstr) ((buf), (str))) + +/** + * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer + * to a C string. + * + * @param[out] exc A subclass of ::rb_eException. + * @param[in] str Message to raise. + * @return An instance of `exc` whose message is `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_exc_new_cstr(exc, str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_exc_new_cstr : \ + rb_exc_new_cstr) ((exc), (str))) + +#define rb_str_new2 rb_str_new_cstr /**< @old{rb_str_new_cstr} */ +#define rb_str_new3 rb_str_new_shared /**< @old{rb_str_new_shared} */ +#define rb_str_new4 rb_str_new_frozen /**< @old{rb_str_new_frozen} */ +#define rb_str_new5 rb_str_new_with_class /**< @old{rb_str_new_with_class} */ +#define rb_tainted_str_new2 rb_tainted_str_new_cstr /**< @old{rb_tainted_str_new_cstr} */ +#define rb_str_buf_new2 rb_str_buf_new_cstr /**< @old{rb_str_buf_new_cstr} */ +#define rb_usascii_str_new2 rb_usascii_str_new_cstr /**< @old{rb_usascii_str_new_cstr} */ +#define rb_str_buf_cat rb_str_cat /**< @alias{rb_str_cat} */ +#define rb_str_buf_cat2 rb_str_cat_cstr /**< @old{rb_usascii_str_new_cstr} */ +#define rb_str_cat2 rb_str_cat_cstr /**< @old{rb_str_cat_cstr} */ + +/** + * Length of a string literal. + * + * @param[in] str A C String literal. + * @return An integer constant expression that represents `str`'s length, + * in bytes, not including the terminating NUL character. + */ +#define rb_strlen_lit(str) (sizeof(str "") - 1) + +/** + * Identical to rb_str_new_static(), except it cannot take string variables. + * + * @param[in] str A C string literal. + * @pre `str` must not be a variable. + * @return An instance of ::rb_cString, of "binary" encoding, whose backend + * storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str)) + +/** + * Identical to rb_usascii_str_new_static(), except it cannot take string + * variables. + * + * @param[in] str A C string literal. + * @pre `str` must not be a variable. + * @return An instance of ::rb_cString, of "US ASCII" encoding, whose + * backend storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str)) + +/** + * Identical to rb_utf8_str_new_static(), except it cannot take string + * variables. + * + * @param[in] str A C string literal. + * @pre `str` must not be a variable. + * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend + * storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str)) + +/** + * Identical to rb_enc_str_new_static(), except it cannot take string + * variables. + * + * @param[in] str A C string literal. + * @param[in] enc A pointer to an encoding. + * @pre `str` must not be a variable. + * @return An instance of ::rb_cString, of the passed encoding, whose + * backend storage is the passed C string literal. + * @warning It is a very bad idea to write to a C string literal (often + * immediate SEGV shall occur). Consider return values of this + * function be read-only. + */ +#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc)) + +#define rb_str_new_literal(str) rb_str_new_lit(str) /**< @alias{rb_str_new_lit} */ +#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str) /**< @alias{rb_usascii_str_new_lit} */ +#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str) /**< @alias{rb_utf8_str_new_lit} */ +#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc) /**< @alias{rb_enc_str_new_lit} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_STRING_H */ diff --git a/ruby/include/ruby/internal/intern/struct.h b/ruby/include/ruby/internal/intern/struct.h new file mode 100644 index 000000000..312cf444e --- /dev/null +++ b/ruby/include/ruby/internal/intern/struct.h @@ -0,0 +1,203 @@ +#ifndef RBIMPL_INTERN_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_STRUCT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cStruct. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */ +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* struct.c */ + +/** + * Creates an instance of the given struct. + * + * @param[in] klass The class of the instance to allocate. + * @param[in] ... The fields. + * @return Allocated instance of `klass`. + * @pre `klass` must be a subclass of ::rb_cStruct. + * @note Number of variadic arguments must much that of the passed klass' + * fields. + */ +VALUE rb_struct_new(VALUE klass, ...); + +/** + * Defines a struct class. + * + * @param[in] name Name of the class. + * @param[in] ... Arbitrary number of `const char*`, terminated by + * zero. Each of which are the name of fields. + * @exception rb_eNameError `name` is not a constant name. + * @exception rb_eTypeError `name` is already taken. + * @exception rb_eArgError Duplicated field name. + * @return The defined class. + * @post Global toplevel constant `name` is defined. + * @note `name` is allowed to be a null pointer. This function creates + * an anonymous struct class then. + * + * @internal + * + * Not seriously checked but it seems this function does not share its + * implementation with how `Struct.new` is implemented...? + */ +VALUE rb_struct_define(const char *name, ...); + +RBIMPL_ATTR_NONNULL((2)) +/** + * Identical to rb_struct_define(), except it defines the class under the + * specified namespace instead of global toplevel. + * + * @param[out] space Namespace that the defining class shall reside. + * @param[in] name Name of the class. + * @param[in] ... Arbitrary number of `const char*`, terminated by + * zero. Each of which are the name of fields. + * @exception rb_eNameError `name` is not a constant name. + * @exception rb_eTypeError `name` is already taken. + * @exception rb_eArgError Duplicated field name. + * @return The defined class. + * @post `name` is a constant under `space`. + * @note In contrast to rb_struct_define(), it doesn't make any sense to + * pass a null pointer to this function. + */ +VALUE rb_struct_define_under(VALUE space, const char *name, ...); + +/** + * Identical to rb_struct_new(), except it takes the field values as a Ruby + * array. + * + * @param[in] klass The class of the instance to allocate. + * @param[in] values Field values. + * @return Allocated instance of `klass`. + * @pre `klass` must be a subclass of ::rb_cStruct. + * @pre `values` must be an instance of struct ::RArray. + */ +VALUE rb_struct_alloc(VALUE klass, VALUE values); + +/** + * Mass-assigns a struct's fields. + * + * @param[out] self An instance of a struct class to squash. + * @param[in] values New values. + * @return ::RUBY_Qnil. + */ +VALUE rb_struct_initialize(VALUE self, VALUE values); + +/** + * Identical to rb_struct_aref(), except it takes ::ID instead of ::VALUE. + * + * @param[in] self An instance of a struct class. + * @param[in] key Key to query. + * @exception rb_eTypeError `self` is not a struct. + * @exception rb_eNameError No such field. + * @return The value stored at `key` in `self`. + */ +VALUE rb_struct_getmember(VALUE self, ID key); + +/** + * Queries the list of the names of the fields of the given struct class. + * + * @param[in] klass A subclass of ::rb_cStruct. + * @return The list of the names of the fields of `klass`. + */ +VALUE rb_struct_s_members(VALUE klass); + +/** + * Queries the list of the names of the fields of the class of the given struct + * object. This is almost the same as calling rb_struct_s_members() over the + * class of the receiver. + * + * @internal + * + * "Almost"? What exactly is the difference? + * + * @endinternal + * + * @param[in] self An instance of a subclass of ::rb_cStruct. + * @return The list of the names of the fields. + */ +VALUE rb_struct_members(VALUE self); + +/** + * Allocates an instance of the given class. This consequential name is of + * course because rb_struct_alloc() not only allocates but also initialises an + * instance. The API design is broken. + * + * @param[in] klass A subclass of ::rb_cStruct. + * @return An allocated instance of `klass`, not initialised. + */ +VALUE rb_struct_alloc_noinit(VALUE klass); + +/** + * Identical to rb_struct_define(), except it does not define accessor methods. + * You have to define them yourself. Forget about the allocator function + * parameter; it is for internal use only. Extension libraries are unable to + * properly allocate a ruby struct, because `RStruct` is opaque. + * + * @internal + * + * Several flags must be set up properly for ::RUBY_T_STRUCT objects, which are + * also missing for extension libraries. + * + * @endinternal + * + * @param[in] name Name of the class. + * @param[in] super Superclass of the defining class. + * @param[in] func Must be 0 for extension libraries. + * @param[in] ... Arbitrary number of `const char*`, terminated by + * zero. Each of which are the name of fields. + * @exception rb_eNameError `name` is not a constant name. + * @exception rb_eTypeError `name` is already taken. + * @exception rb_eArgError Duplicated field name. + * @return The defined class. + * @post Global toplevel constant `name` is defined. + * @note `name` is allowed to be a null pointer. This function creates + * an anonymous struct class then. + */ +VALUE rb_struct_define_without_accessor(const char *name, VALUE super, rb_alloc_func_t func, ...); + +RBIMPL_ATTR_NONNULL((2)) +/** + * Identical to rb_struct_define_without_accessor(), except it defines the + * class under the specified namespace instead of global toplevel. It can also + * be seen as a routine identical to rb_struct_define_under(), except it does + * not define accessor methods. + * + * @param[out] outer Namespace that the defining class shall reside. + * @param[in] class_name Name of the class. + * @param[in] super Superclass of the defining class. + * @param[in] alloc Must be 0 for extension libraries. + * @param[in] ... Arbitrary number of `const char*`, terminated by + * zero. Each of which are the name of fields. + * @exception rb_eNameError `class_name` is not a constant name. + * @exception rb_eTypeError `class_name` is already taken. + * @exception rb_eArgError Duplicated field name. + * @return The defined class. + * @post `class_name` is a constant under `outer`. + * @note In contrast to rb_struct_define_without_accessor(), it doesn't + * make any sense to pass a null name. + */ +VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_STRUCT_H */ diff --git a/ruby/include/ruby/internal/intern/thread.h b/ruby/include/ruby/internal/intern/thread.h new file mode 100644 index 000000000..716375acd --- /dev/null +++ b/ruby/include/ruby/internal/intern/thread.h @@ -0,0 +1,492 @@ +#ifndef RBIMPL_INTERN_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_THREAD_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cThread. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/config.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +struct timeval; + +/* thread.c */ + +/** + * Tries to switch to another thread. This function blocks until the current + * thread re-acquires the GVL. + * + * @exception rb_eInterrupt Operation interrupted. + */ +void rb_thread_schedule(void); + +/** + * Blocks the current thread until the given file descriptor is ready to be + * read. + * + * @param[in] fd A file descriptor. + * @exception rb_eIOError Closed stream. + * @exception rb_eSystemCallError Situations like EBADF. + */ +int rb_thread_wait_fd(int fd); + +/** + * Identical to rb_thread_wait_fd(), except it blocks the current thread until + * the given file descriptor is ready to be written. + * + * @param[in] fd A file descriptor. + * @exception rb_eIOError Closed stream. + * @exception rb_eSystemCallError Situations like EBADF. + */ +int rb_thread_fd_writable(int fd); + +/** + * Notifies a closing of a file descriptor to other threads. Multiple threads + * can wait for the given file descriptor at once. If such file descriptor is + * closed, threads need to start propagating their exceptions. This is the API + * to kick that process. + * + * @param[in] fd A file descriptor. + * @note This function blocks until all the threads waiting for such fd + * have woken up. + */ +void rb_thread_fd_close(int fd); + +/** + * Checks if the thread this function is running is the only thread that is + * currently alive. + * + * @retval 1 Yes it is. + * @retval 0 No it isn't. + * + * @internal + * + * Above description is in fact inaccurate. There are Ractors these days. + */ +int rb_thread_alone(void); + +/** + * Blocks for the given period of time. + * + * @warning This function can be interrupted by signals. + * @param[in] sec Duration in seconds. + * @exception rb_eInterrupt Interrupted. + */ +void rb_thread_sleep(int sec); + +/** + * Blocks indefinitely. + * + * @exception rb_eInterrupt Interrupted. + */ +void rb_thread_sleep_forever(void); + +/** + * Identical to rb_thread_sleep_forever(), except the thread calling this + * function is considered "dead" when our deadlock checker is triggered. + * + * @exception rb_eInterrupt Interrupted. + */ +void rb_thread_sleep_deadly(void); + +/** + * Stops the current thread. This is not the end of the thread's lifecycle. A + * stopped thread can later be woken up. + * + * @exception rb_eThreadError Stopping this thread would deadlock. + * @retval ::RUBY_Qnil Always. + * + * @internal + * + * The return value makes no sense at all. + */ +VALUE rb_thread_stop(void); + +/** + * Marks a given thread as eligible for scheduling. + * + * @note It may still remain blocked on I/O. + * @note This does not invoke the scheduler itself. + * + * @param[out] thread Thread in question to wake up. + * @exception rb_eThreadError Stop flogging a dead horse. + * @return The passed thread. + * @post The passed thread is made runnable. + */ +VALUE rb_thread_wakeup(VALUE thread); + +/** + * Identical to rb_thread_wakeup(), except it doesn't raise on an already + * killed thread. + * + * @param[out] thread A thread to wake up. + * @retval RUBY_Qnil `thread` is already killed. + * @retval otherwise `thread` is alive. + * @post The passed thread is made runnable, unless killed. + */ +VALUE rb_thread_wakeup_alive(VALUE thread); + +/** + * This is a rb_thread_wakeup() + rb_thread_schedule() combo. + * + * @note There is no guarantee that this function yields to the passed + * thread. It may still remain blocked on I/O. + * @param[out] thread Thread in question to wake up. + * @exception rb_eThreadError Stop flogging a dead horse. + * @return The passed thread. + */ +VALUE rb_thread_run(VALUE thread); + +/** + * Terminates the given thread. Unlike a stopped thread, a killed thread could + * never be revived. This function does return, when passed e.g. an already + * killed thread. But if the passed thread is the only one, or a special + * thread called "main", then it also terminates the entire process. + * + * @param[out] thread The thread to terminate. + * @exception rb_eFatal The passed thread is the running thread. + * @exception rb_eSystemExit The passed thread is the last thread. + * @return The passed thread. + * @post Either the passed thread, or the process entirely, is killed. + * + * @internal + * + * It seems killing the main thread also kills the entire process even if there + * are multiple running ractors. No idea why. + */ +VALUE rb_thread_kill(VALUE thread); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Creates a Ruby thread that is backended by a C function. + * + * @param[in] f The function to run on a thread. + * @param[in,out] g Passed through to `f`. + * @exception rb_eThreadError Could not create a ruby thread. + * @exception rb_eSystemCallError Situations like `EPERM`. + * @return Allocated instance of ::rb_cThread. + * @note This doesn't wait for anything. + */ +VALUE rb_thread_create(VALUE (*f)(void *g), void *g); + +/** + * Identical to rb_thread_sleep(), except it takes struct `timeval` instead. + * + * @warning This function can be interrupted by signals. + * @param[in] time Duration. + * @exception rb_eInterrupt Interrupted. + */ +void rb_thread_wait_for(struct timeval time); + +/** + * Obtains the "current" thread. + * + * @return The current thread of the current ractor of the current execution + * context. + * @pre This function must be called from a thread controlled by ruby. + */ +VALUE rb_thread_current(void); + +/** + * Obtains the "main" thread. There are threads called main. Historically the + * (only) main thread was the one which runs when the process boots. Now that + * we have Ractor, there are more than one main threads. + * + * @return The main thread of the current ractor of the current execution + * context. + * @pre This function must be called from a thread controlled by ruby. + */ +VALUE rb_thread_main(void); + +/** + * This badly named function reads from a Fiber local storage. When this + * function was born there was no such thing like a Fiber. The world was + * innocent. But now... This is a Fiber local storage. Sorry. + * + * @param[in] thread Thread that the target Fiber is running. + * @param[in] key The name of the Fiber local storage to read. + * @retval RUBY_Qnil No such storage. + * @retval otherwise The value stored at `key`. + * @note There in fact are "true" thread local storage, but Ruby doesn't + * provide any interface of them to you, C programmers. + */ +VALUE rb_thread_local_aref(VALUE thread, ID key); + +/** + * This badly named function writes to a Fiber local storage. When this + * function was born there was no such thing like a Fiber. The world was + * innocent. But now... This is a Fiber local storage. Sorry. + * + * @param[in] thread Thread that the target Fiber is running. + * @param[in] key The name of the Fiber local storage to write. + * @param[in] val The new value of the storage. + * @exception rb_eFrozenError `thread` is frozen. + * @return The passed `val` as-is. + * @post Fiber local storage `key` has value of `val`. + * @note There in fact are "true" thread local storage, but Ruby doesn't + * provide any interface of them to you, C programmers. + */ +VALUE rb_thread_local_aset(VALUE thread, ID key, VALUE val); + +/** + * A `pthread_atfork(3posix)`-like API. Ruby expects its child processes to + * call this function at the very beginning of their processes. If you plan to + * fork a process don't forget to call it. + */ +void rb_thread_atfork(void); + +/** + * :FIXME: situation of this function is unclear. It seems nobody uses it. + * Maybe a good idea to KonMari. + */ +void rb_thread_atfork_before_exec(void); + +/** + * "Recursion" API entry point. This basically calls the given function with + * the given arguments, but additionally with recursion flag. The flag is set + * to 1 if the execution have already experienced the passed `g` parameter + * before. + * + * @param[in] f The function that possibly recurs. + * @param[in,out] g Passed as-is to `f`. + * @param[in,out] h Passed as-is to `f`. + * @return The return value of f. + */ +VALUE rb_exec_recursive(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h); + +/** + * Identical to rb_exec_recursive(), except it checks for the recursion on the + * ordered pair of `{ g, p }` instead of just `g`. + * + * @param[in] f The function that possibly recurs. + * @param[in,out] g Passed as-is to `f`. + * @param[in] p Paired object for recursion detection. + * @param[in,out] h Passed as-is to `f`. + */ +VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h); + +/** + * Identical to rb_exec_recursive(), except it calls `f` for outermost + * recursion only. Inner recursions yield calls to rb_throw_obj(). + * + * @param[in] f The function that possibly recurs. + * @param[in,out] g Passed as-is to `f`. + * @param[in,out] h Passed as-is to `f`. + * @return The return value of f. + * + * @internal + * + * It seems nobody uses the "it calls rb_throw_obj()" part of this function. + * @shyouhei doesn't understand the needs. + */ +VALUE rb_exec_recursive_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h); + +/** + * Identical to rb_exec_recursive_outer(), except it checks for the recursion + * on the ordered pair of `{ g, p }` instead of just `g`. It can also be seen + * as a routine identical to rb_exec_recursive_paired(), except it calls `f` + * for outermost recursion only. Inner recursions yield calls to + * rb_throw_obj(). + * + * @param[in] f The function that possibly recurs. + * @param[in,out] g Passed as-is to `f`. + * @param[in] p Paired object for recursion detection. + * @param[in,out] h Passed as-is to `f`. + * + * @internal + * + * It seems nobody uses the "it calls rb_throw_obj()" part of this function. + * @shyouhei doesn't understand the needs. + */ +VALUE rb_exec_recursive_paired_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h); + +/** + * This is the type of UBFs. An UBF is a function that unblocks a blocking + * region. For instance when a thread is blocking due to `pselect(3posix)`, it + * is highly expected that `pthread_kill(3posix)` can interrupt the system call + * and the thread could revive. Or when a thread is blocking due to + * `waitpid(3posix)`, it is highly expected that killing the waited process + * should suffice. An UBF is a function that does such things. Designing your + * own UBF needs deep understanding of why your blocking region blocks, how + * threads work in ruby, and a matter of luck. It often is the case you simply + * cannot cancel something that had already begun. + * + * @see rb_thread_call_without_gvl() + */ +typedef void rb_unblock_function_t(void *); + +/** + * @private + * + * This is an implementation detail. Must be a mistake to be here. + * + * @internal + * + * Why is this function type different from what rb_thread_call_without_gvl() + * takes? + */ +typedef VALUE rb_blocking_function_t(void *); + +/** + * Checks for interrupts. In ruby, signals are masked by default. You can + * call this function at will to check if there are pending signals. In case + * there are, they would be handled in this function. + * + * If your extension library has a function that takes a long time, consider + * calling it periodically. + * + * @note It might switch to another thread. + */ +void rb_thread_check_ints(void); + +/** + * Checks if the thread's execution was recently interrupted. If called from + * that thread, this function can be used to detect spurious wake-ups. + * + * @param[in] thval Thread in question. + * @retval 0 The thread was not interrupted. + * @retval otherwise The thread was interrupted recently. + * + * @internal + * + * Above description is not a lie. But actually the return value is an opaque + * trap vector. If you know which bit means which, you can know what happened. + */ +int rb_thread_interrupted(VALUE thval); + +/** + * A special UBF for blocking IO operations. You need deep understanding of + * what this actually do before using. Basically you should not use it from + * extension libraries. It is too easy to mess up. + */ +#define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1) + +/** + * A special UBF for blocking process operations. You need deep understanding + * of what this actually do before using. Basically you should not use it from + * extension libraries. It is too easy to mess up. + */ +#define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1) + +/* thread_sync.c */ + +/** + * Creates a mutex. + * + * @return An allocated instance of rb_cMutex. + */ +VALUE rb_mutex_new(void); + +/** + * Queries if there are any threads that holds the lock. + * + * @param[in] mutex The mutex in question. + * @retval RUBY_Qtrue The mutex is locked by someone. + * @retval RUBY_Qfalse The mutex is not locked by anyone. + */ +VALUE rb_mutex_locked_p(VALUE mutex); + +/** + * Attempts to lock the mutex, without waiting for other threads to unlock it. + * Failure in locking the mutex can be detected by the return value. + * + * @param[out] mutex The mutex to lock. + * @retval RUBY_Qtrue Successfully locked by the current thread. + * @retval RUBY_Qfalse Otherwise. + * @note This function also returns ::RUBY_Qfalse when the mutex is + * already owned by the calling thread itself. + */ +VALUE rb_mutex_trylock(VALUE mutex); + +/** + * Attempts to lock the mutex. It waits until the mutex gets available. + * + * @param[out] mutex The mutex to lock. + * @exception rb_eThreadError Recursive deadlock situation. + * @return The passed mutex. + * @post The mutex is owned by the current thread. + */ +VALUE rb_mutex_lock(VALUE mutex); + +/** + * Releases the mutex. + * + * @param[out] mutex The mutex to unlock. + * @exception rb_eThreadError The mutex is not owned by the current thread. + * @return The passed mutex. + * @post Upon successful return the passed mutex is no longer owned by + * the current thread. + */ +VALUE rb_mutex_unlock(VALUE mutex); + +/** + * Releases the lock held in the mutex and waits for the period of time; + * reacquires the lock on wakeup. + * + * @pre The lock has to be owned by the current thread beforehand. + * @param[out] self The target mutex. + * @param[in] timeout Duration, in seconds, in ::rb_cNumeric. + * @exception rb_eArgError `timeout` is negative. + * @exception rb_eRangeError `timeout` is out of range of `time_t`. + * @exception rb_eThreadError The mutex is not owned by the current thread. + * @return Number of seconds it actually slept. + * @warning It is a failure not to check the return value. This function + * can return spuriously for various reasons. Maybe other threads + * can rb_thread_wakeup(). Maybe an end user can press the + * Control and C key from the interactive console. On the other + * hand it can also take longer than the specified. The mutex + * could be locked by someone else. It waits then. + * @post Upon successful return the passed mutex is owned by the current + * thread. + * + * @internal + * + * This function is called from `ConditionVariable#wait`. So it is not a + * deprecated feature. However @shyouhei have never seen any similar mutex + * primitive available in any other languages than Ruby. + * + * EDIT: In 2021, @shyouhei asked @ko1 in person about this API. He answered + * that it is his invention. The motivation behind its design is to eliminate + * needs of condition variables as primitives. Unlike other languages, Ruby's + * `ConditionVariable` class was written in pure-Ruby initially. We don't have + * to implement machine-native condition variables in assembly each time we + * port Ruby to a new architecture. This function made it possible. "I felt I + * was a genius when this idea came to me", said @ko1. + * + * `rb_cConditionVariable` is now written in C for speed, though. + */ +VALUE rb_mutex_sleep(VALUE self, VALUE timeout); + +/** + * Obtains the lock, runs the passed function, and releases the lock when it + * completes. + * + * @param[out] mutex The mutex to lock. + * @param[in] func What to do during the mutex is locked. + * @param[in,out] arg Passed as-is to `func`. + */ +VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_THREAD_H */ diff --git a/ruby/include/ruby/internal/intern/time.h b/ruby/include/ruby/internal/intern/time.h new file mode 100644 index 000000000..df482862e --- /dev/null +++ b/ruby/include/ruby/internal/intern/time.h @@ -0,0 +1,161 @@ +#ifndef RBIMPL_INTERN_TIME_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_TIME_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cTime. + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_TIME_H +# include /* for time_t */ +#endif + +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +struct timespec; +struct timeval; + +/* time.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Fills the current time into the given struct. + * + * @param[out] ts Return buffer. + * @exception rb_eSystemCallError Access denied for hardware clock. + * @post Current time is stored in `*ts`. + */ +void rb_timespec_now(struct timespec *ts); + +/** + * Creates an instance of ::rb_cTime with the given time and the local + * timezone. + * + * @param[in] sec Seconds since the UNIX epoch. + * @param[in] usec Subsecond part, in microseconds resolution. + * @exception rb_eRangeError Cannot express the time. + * @return An allocated instance of ::rb_cTime. + */ +VALUE rb_time_new(time_t sec, long usec); + +/** + * Identical to rb_time_new(), except it accepts the time in nanoseconds + * resolution. + * + * @param[in] sec Seconds since the UNIX epoch. + * @param[in] nsec Subsecond part, in nanoseconds resolution. + * @exception rb_eRangeError Cannot express the time. + * @return An allocated instance of ::rb_cTime. + */ +VALUE rb_time_nano_new(time_t sec, long nsec); + +RBIMPL_ATTR_NONNULL(()) +/** + * Creates an instance of ::rb_cTime, with given time and offset. + * + * @param[in] ts Time specifier. + * @param[in] offset Offset specifier, can take following values: + * - `INT_MAX`: `ts` is in local time. + * - `INT_MAX - 1`: `ts` is in UTC. + * - `-86400` to `86400`: fixed timezone. + * @exception rb_eArgError Malformed `offset`. + * @return An allocated instance of ::rb_cTime. + */ +VALUE rb_time_timespec_new(const struct timespec *ts, int offset); + +/** + * Identical to rb_time_timespec_new(), except it takes Ruby values instead of + * C structs. + * + * @param[in] timev Something numeric. Currently Integers, Rationals, + * and Floats are accepted. + * @param[in] off Offset specifier. As of 2.7 this argument is + * heavily extended to take following kinds of + * objects: + * - ::RUBY_Qundef ... means UTC. + * - ::rb_cString ... "+12:34" etc. + * - A mysterious "zone" object. This is largely + * undocumented. However the initial intent was + * that we want to accept + * `ActiveSupport::TimeZone` here. Other gems + * could also be possible... But how to make an + * acceptable class is beyond this document. + * @exception rb_eArgError Malformed `off`. + * @return An allocated instance of ::rb_cTime. + */ +VALUE rb_time_num_new(VALUE timev, VALUE off); + +/** + * Creates a "time interval". This basically converts an instance of + * ::rb_cNumeric into a struct `timeval`, but for instance negative time + * interval must not exist. + * + * @param[in] num An instance of ::rb_cNumeric. + * @exception rb_eArgError `num` is negative. + * @exception rb_eRangeError `num` is out of range of `timeval::tv_sec`. + * @return A struct that represents the identical time to `num`. + */ +struct timeval rb_time_interval(VALUE num); + +/** + * Converts an instance of rb_cTime to a struct timeval that represents the + * identical point of time. It can also take something numeric; would consider + * it as a UNIX time then. + * + * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric. + * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. + * @return A struct that represents the identical time to `num`. + */ +struct timeval rb_time_timeval(VALUE time); + +/** + * Identical to rb_time_timeval(), except for return type. + * + * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric. + * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. + * @return A struct that represents the identical time to `num`. + */ +struct timespec rb_time_timespec(VALUE time); + +/** + * Identical to rb_time_interval(), except for return type. + * + * @param[in] num An instance of ::rb_cNumeric. + * @exception rb_eArgError `num` is negative. + * @exception rb_eRangeError `num` is out of range of `timespec::tv_sec`. + * @return A struct that represents the identical time to `num`. + */ +struct timespec rb_time_timespec_interval(VALUE num); + +/** + * Queries the offset, in seconds between the time zone of the time and the + * UTC. + * + * @param[in] time An instance of ::rb_cTime. + * @return Numeric offset. + */ +VALUE rb_time_utc_offset(VALUE time); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_TIME_H */ diff --git a/ruby/include/ruby/internal/intern/variable.h b/ruby/include/ruby/internal/intern/variable.h new file mode 100644 index 000000000..479c3950c --- /dev/null +++ b/ruby/include/ruby/internal/intern/variable.h @@ -0,0 +1,628 @@ +#ifndef RBIMPL_INTERN_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_VARIABLE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to names inside of a Ruby program. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/st.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* variable.c */ + +/** + * Queries the name of a module. + * + * @param[in] mod An instance of ::rb_cModule. + * @retval RUBY_Qnil `mod` is anonymous. + * @retval otherwise `mod` is onymous. + */ +VALUE rb_mod_name(VALUE mod); + +/** + * Identical to rb_mod_name(), except it returns `#` style + * inspection for anonymous modules. + * + * @param[in] mod An instance of ::rb_cModule. + * @return An instance of ::rb_cString representing `mod`'s path. + */ +VALUE rb_class_path(VALUE mod); + +/** + * @alias{rb_mod_name} + * + * @internal + * + * Am I missing something? Why we have the same thing in different names? + */ +VALUE rb_class_path_cached(VALUE mod); + +RBIMPL_ATTR_NONNULL(()) +/** + * Names a class. + * + * @param[out] klass Target module to name. + * @param[out] space Namespace that `klass` shall reside. + * @param[in] name Name of `klass`. + * @post `klass` has `space::klass` name. + */ +void rb_set_class_path(VALUE klass, VALUE space, const char *name); + +/** + * Identical to rb_set_class_path(), except it accepts the name as Ruby's + * string instead of C's. + * + * @param[out] klass Target module to name. + * @param[out] space Namespace that `klass` shall reside. + * @param[in] name Name of `klass`. + * @post `klass` has `space::klass` name. + */ +void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name); + +/** + * Identical to rb_path2class(), except it accepts the path as Ruby's string + * instead of C's. + * + * @param[in] path Path to query. + * @exception rb_eArgError No such constant. + * @exception rb_eTypeError The path resolved to a non-module. + * @return Resolved class. + */ +VALUE rb_path_to_class(VALUE path); + +RBIMPL_ATTR_NONNULL(()) +/** + * Resolves a `Q::W::E::R`-style path string to the actual class it points. + * + * @param[in] path Path to query. + * @exception rb_eArgError No such constant. + * @exception rb_eTypeError The path resolved to a non-module. + * @return Resolved class. + */ +VALUE rb_path2class(const char *path); + +/** + * Queries the name of the given object's class. + * + * @param[in] obj Arbitrary object. + * @return An instance of ::rb_cString representing `obj`'s class' path. + */ +VALUE rb_class_name(VALUE obj); + +/** + * Kicks the autoload procedure as if it was "touched". + * + * @param[out] space Namespace where autoload is defined. + * @param[in] name Name of the autoloaded constant. + * @retval RUBY_Qfalse No such autoload. + * @retval RUBY_Qtrue Autoload successfully initiated. + * @note As an autoloaded library is expected to define `space::name`, + * it is a nature of this function to have process-global side + * effects. + * @note Multiple threads can simultaneously call this API. It blocks + * then. That must not last indefinitely but can take longer than + * you expect. + * + * @internal + * + * @shyouhei has no idea why extension libraries should use this API. + */ +VALUE rb_autoload_load(VALUE space, ID name); + +/** + * Queries if an autoload is defined at a point. + * + * @param[in] space Namespace where autoload is defined. + * @param[in] name Name of the autoloaded constant. + * @retval RUBY_Qnil No such autoload. + * @retval otherwise The feature (path) registered at `space::name`. + */ +VALUE rb_autoload_p(VALUE space, ID name); + +/** + * Traces a global variable. + * + * @param[in] argc Either 1 or 2. + * @param[in] argv Variable name, optionally a Proc. + * @retval RUBY_Qnil No previous tracers. + * @retval otherwise Previous tracers. + * + * @internal + * + * @shyouhei has no idea why extension libraries should use this API. + */ +VALUE rb_f_trace_var(int argc, const VALUE *argv); + +/** + * Deletes the passed tracer from the passed global variable, or if omitted, + * deletes everything. + * + * @param[in] argc Either 1 or 2. + * @param[in] argv Variable name, optionally a Proc. + * @retval RUBY_Qnil No previous tracers. + * @retval otherwise Deleted tracers. + * + * @internal + * + * @shyouhei has no idea why extension libraries should use this API. + */ +VALUE rb_f_untrace_var(int argc, const VALUE *argv); + +/** + * Queries the list of global variables. + * + * @return The list of the name of the global variables. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_f_global_variables(void); + +/** + * Aliases a global variable. Did you know that you can alias a global + * variable? It is like aliasing methods: + * + * ```ruby + * alias $dst $src + * ``` + * + * This C function does the same thing. + * + * @param[in] dst Destination name. + * @param[in] src Source name. + * @post A global variable named `dst` is defined to be an alias of a + * global variable named `src`. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_alias_variable(ID dst, ID src); + +/** + * Frees the list of instance variables. 3rd parties need not know, but there + * are several ways to store an object's instance variables, depending on its + * internal structure. This function makes sense when the passed objects is + * using so-called "generic" backend storage. People need not be aware of this + * working behind-the-scenes. + * + * @param[out] obj The object in question. + * + * @internal + * + * This just destroys the given object. @shyouhei has no idea why extension + * libraries should use this API. + */ +void rb_free_generic_ivar(VALUE obj); + +/** + * Identical to rb_iv_get(), except it accepts the name as an ::ID instead of a + * C string. + * + * @param[in] obj Target object. + * @param[in] name Target instance variable to query. + * @retval RUBY_nil No such instance variable. + * @retval otherwise The value assigned to the instance variable. + */ +VALUE rb_ivar_get(VALUE obj, ID name); + +/** + * Identical to rb_iv_set(), except it accepts the name as an ::ID instead of a + * C string. + * + * @param[out] obj Target object. + * @param[in] name Target instance variable. + * @param[in] val Value to assign. + * @exception rb_eFrozenError Can't modify `obj`. + * @exception rb_eArgError `obj` has too many instance variables. + * @return Passed value. + * @post An instance variable named `name` is defined if absent on + * `obj`, whose value is set to `val`. + */ +VALUE rb_ivar_set(VALUE obj, ID name, VALUE val); + +/** + * Queries if the instance variable is defined at the object. This roughly + * resembles `defined?(@name)` in `obj`'s context. + * + * @param[in] obj Target object. + * @param[in] name Target instance variable to query. + * @retval RUBY_Qtrue There is an instance variable. + * @retval RUBY_Qfalse No such instance variable. + */ +VALUE rb_ivar_defined(VALUE obj, ID name); + +/** + * Iterates over an object's instance variables. + * + * @param[in] obj Target object. + * @param[in] func Callback function. + * @param[in] arg Passed as-is to the last argument of `func`. + */ +void rb_ivar_foreach(VALUE obj, int (*func)(ID name, VALUE val, st_data_t arg), st_data_t arg); + +/** + * Number of instance variables defined on an object. + * + * @param[in] obj Target object. + * @return Number of instance variables defined on `obj`. + */ +st_index_t rb_ivar_count(VALUE obj); + +/** + * Identical to rb_ivar_get() + * + * @param[in] obj Target object. + * @param[in] name Target instance variable to query. + * @retval RUBY_nil No such instance variable. + * @retval otherwise The value assigned to the instance variable. + * + * @internal + * + * Am I missing something? Why we have the same thing in different names? + */ +VALUE rb_attr_get(VALUE obj, ID name); + +/** + * Resembles `Object#instance_variables`. + * + * @param[in] obj Target object to query. + * @return An array of instance variable names for the receiver. + * @note Simply defining an accessor does not create the corresponding + * instance variable. + */ +VALUE rb_obj_instance_variables(VALUE obj); + +/** + * Resembles `Object#remove_instance_variable`. + * + * @param[out] obj Target object. + * @param[in] name Variable name to remove, either in Symbol or String. + * @return What was removed. + * @pre Instance variable named `name` is deleted from `obj`. + */ +VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name); + +/** + * This API is mysterious. It has been there since the initial revision. No + * single bits of documents has ever been written. The function name doesn't + * describe anything. What should be passed to the argument, or what should be + * the return value, are not obvious. Yet it has evolved over time. The + * source code is written in counter-intuitive way (as of 3.0). + * + * Simply put, don't try to understand this API. + */ +void *rb_mod_const_at(VALUE, void*); + +/** + * This is a variant of rb_mod_const_at(). As a result, it is also mysterious. + * It _seems_ it iterates over the ancestry tree of the module. But what that + * means is beyond a human brain. + */ +void *rb_mod_const_of(VALUE, void*); + +/** + * This is another mysterious API that comes with no documents at all. It + * seems it expects some specific data structure for the passed pointer. But + * the details has never been made explicit. It seems nobody should use this + * API. + */ +VALUE rb_const_list(void*); + +/** + * Resembles `Module#constants`. List up the constants defined at the + * receiver. This includes the names of constants in any included modules, + * unless `argv[0]` is ::RUBY_Qfalse. + * + * The implementation makes no guarantees about the order in which the + * constants are yielded. + * + * @param[in] argc Either 0 or 1. + * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`. + * @param[in] recv Target namespace. + * @return An array of symbols, which are constant names under `recv`. + */ +VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv); + +/** + * Resembles `Module#remove_const`. + * + * @param[out] space Target namespace. + * @param[in] name Variable name to remove, either in Symbol or String. + * @return What was removed. + * @pre Constant named `space::name` is deleted. + * @note In case what was removed was in fact a module or a class, this + * operation does not affect its name. Which means when people + * for instance look at it using `p` etc., it still introduces + * itself using the deleted name. Can confuse people. + */ +VALUE rb_mod_remove_const(VALUE space, VALUE name); + +/** + * Queries if the constant is defined at the namespace. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @retval RUBY_Qtrue There is a constant. + * @retval RUBY_Qfalse No such constant. + * + * @internal + * + * The return values are not typo! This function returns ruby values casted to + * `int`. Completely brain-damaged design. + */ +int rb_const_defined(VALUE space, ID name); + +/** + * Identical to rb_const_defined(), except it doesn't look for parent classes. + * For instance `Array` is a toplevel constant, which is visible from + * everywhere. But this function does not take such things into account. It + * concerns only what is directly defined inside of the given namespace. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @retval RUBY_Qtrue There is a constant. + * @retval RUBY_Qfalse No such constant. + * + * @internal + * + * The return values are not typo! This function returns ruby values casted to + * `int`. Completely brain-damaged design. + */ +int rb_const_defined_at(VALUE space, ID name); + +/** + * Identical to rb_const_defined(), except it returns false for private + * constants. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @retval RUBY_Qtrue There is a constant. + * @retval RUBY_Qfalse No such constant. + * + * @internal + * + * What does "from" mean? The name sounds quite cryptic. + * + * The return values are not typo! This function returns ruby values casted to + * `int`. Completely brain-damaged design. + */ +int rb_const_defined_from(VALUE space, ID name); + +/** + * Identical to rb_const_defined(), except it returns the actual defined value. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @exception rb_eNameError No such constant. + * @return The defined constant. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_const_get(VALUE space, ID name); + +/** + * Identical to rb_const_defined_at(), except it returns the actual defined + * value. It can also be seen as a routine identical to rb_const_get(), except + * it doesn't look for parent classes. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @exception rb_eNameError No such constant. + * @return The defined constant. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_const_get_at(VALUE space, ID name); + +/** + * Identical to rb_const_defined_at(), except it returns the actual defined + * value. It can also be seen as a routine identical to rb_const_get(), except + * it doesn't return a private constant. + * + * @param[in] space Target namespace. + * @param[in] name Target name to query. + * @exception rb_eNameError No such constant. + * @return The defined constant. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_const_get_from(VALUE space, ID name); + +/** + * Names a constant. + * + * @param[out] space Target namespace. + * @param[in] name Target name to query. + * @param[in] val Value to define. + * @exception rb_eTypeError `space` is not a module. + * @post `name` is a constant under `space`, whose value is `val`. + * @note You can reassign. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_const_set(VALUE space, ID name, VALUE val); + +/** + * Identical to rb_mod_remove_const(), except it takes the name as ::ID instead + * of ::VALUE. + * + * @param[out] space Target namespace. + * @param[in] name Variable name to remove, either in Symbol or String. + * @return What was removed. + * @pre Constant named `space::name` is deleted. + * @note In case what was removed was in fact a module or a class, this + * operation does not affect its name. Which means when people + * for instance look at it using `p` etc., it still introduces + * itself using the deleted name. Can confuse people. + */ +VALUE rb_const_remove(VALUE space, ID name); + +#if 0 /* EXPERIMENTAL: remove if no problem */ +RBIMPL_ATTR_NORETURN() +/** + * This is the default implementation of `Module#const_missing`. + * + * @param[in] space Target namespace. + * @param[in] name Target name that is nonexistent. + * @exception rb_eNameError Always. + */ +VALUE rb_mod_const_missing(VALUE space, VALUE name); +#endif + +/** + * Queries if the given class has the given class variable. + * + * @param[in] klass Target class. + * @param[in] name Name to query. + * @return RUBY_Qtrue Yes there is. + * @return RUBY_Qfalse No there isn't. + * @pre `klass` must be an instance of rb_cModule. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_cvar_defined(VALUE klass, ID name); + +/** + * Assigns a value to a class variable. + * + * @param[out] klass Target class. + * @param[in] name Variable name. + * @param[in] val Value to be assigned. + * @post `klass` has a class variable named `name` whose value is `val`. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_cvar_set(VALUE klass, ID name, VALUE val); + +/** + * Obtains a value from a class variable. + * + * @param[in] klass Target class. + * @param[in] name Variable name. + * @exception rb_eNameError Uninitialised class variable. + * @exception rb_eRuntimeError `[Bug#14541]` situation. + * @return Class variable named `name` under `klass`. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_cvar_get(VALUE klass, ID name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_cvar_get(), except it takes additional "front" pointer. + * This extra parameter is a buffer, which will have the class where the + * queried class variable actually resides. + * + * @param[in] klass Target class. + * @param[in] name Variable name. + * @param[out] front Return buffer. + * @exception rb_eNameError Uninitialised class variable. + * @exception rb_eRuntimeError `[Bug#14541]` situation. + * @return Class variable named `name` under `klass`. + * @post `front` has the class object, which is an ancestor of `klass`, + * where the queried class variable actually resides. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_cvar_set(), except it accepts C's string instead of ::ID. + * + * @param[out] klass Target class. + * @param[in] name Variable name. + * @param[in] val Value to be assigned. + * @post `klass` has a class variable named `name` whose value is `val`. + */ +void rb_cv_set(VALUE klass, const char *name, VALUE val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_cvar_get(), except it accepts C's string instead of ::ID. + * + * @param[in] klass Target class. + * @param[in] name Variable name. + * @exception rb_eNameError Uninitialised class variable. + * @exception rb_eRuntimeError `[Bug#14541]` situation. + * @return Class variable named `name` under `klass`. + */ +VALUE rb_cv_get(VALUE klass, const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * @alias{rb_cv_set} + * + * @internal + * + * Am I missing something? Why we have the same thing in different names? + */ +void rb_define_class_variable(VALUE, const char*, VALUE); + +/** + * Resembles `Module#class_variables`. List up the variables defined at the + * receiver. This includes the names of constants in any included modules, + * unless `argv[0]` is ::RUBY_Qfalse. + * + * The implementation makes no guarantees about the order in which the + * constants are yielded. + * + * @param[in] argc Either 0 or 1. + * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`. + * @param[in] recv Target class. + * @return An array of symbols, which are class variable names under + * `recv`. + */ +VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv); + +/** + * Resembles `Module#remove_class_variable`. + * + * @param[out] mod Target class. + * @param[in] name Variable name to remove, either in Symbol or String. + * @return What was removed. + * @pre Instance variable named `name` is deleted from `obj`. + */ +VALUE rb_mod_remove_cvar(VALUE mod, VALUE name); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_VARIABLE_H */ diff --git a/ruby/include/ruby/internal/intern/vm.h b/ruby/include/ruby/internal/intern/vm.h new file mode 100644 index 000000000..562d30a6f --- /dev/null +++ b/ruby/include/ruby/internal/intern/vm.h @@ -0,0 +1,435 @@ +#ifndef RBIMPL_INTERN_VM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_VM_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to rb_cRubyVM. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* vm.c */ + +/** + * Resembles `__LINE__`. + * + * @retval 0 Current execution context not in a ruby method. + * @retval otherwise The current line number of the current thread of the + * current ractor of the current execution context. + */ +int rb_sourceline(void); + +/** + * Resembles `__FILE__`. + * + * @retval 0 Current execution context not in a ruby method. + * @retval otherwise The current source path of the current thread of the + * current ractor of the current execution context. + * @note This may or may not be an absolute path. + */ +const char *rb_sourcefile(void); + +/** + * Resembles `__method__`. + * + * @param[out] idp Return buffer for method id. + * @param[out] klassp Return buffer for class. + * @retval 0 Current execution context not in a method. + * @retval 1 Successful return. + * @post Upon successful return `*idp` and `*klassp` are updated to have + * the current method name and its defined class respectively. + * @note Both parameters can be `NULL`. + */ +int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); + +/* vm_eval.c */ + +/** + * Identical to rb_funcallv(), except it returns ::RUBY_Qundef instead of + * raising ::rb_eNoMethodError. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @retval RUBY_Qundef `recv` doesn't respond to `mid`. + * @retval otherwise What the method evaluates to. + */ +VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv); + +/** + * Identical to rb_check_funcall(), except you can specify how to handle the + * last element of the given array. It can also be seen as a routine identical + * to rb_funcallv_kw(), except it returns ::RUBY_Qundef instead of raising + * ::rb_eNoMethodError. + * + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] argc Number of arguments. + * @param[in] argv Arbitrary number of method arguments. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @retval RUBY_Qundef `recv` doesn't respond to `mid`. + * @retval otherwise What the method evaluates to. + */ +VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); + +/** + * This API is practically a variant of rb_proc_call_kw() now. Historically + * when there still was a concept called `$SAFE`, this was an API for that. + * But we no longer have that. This function basically ended its role. It + * just remains here because of no harm. + * + * @param[in] cmd A string, or something callable. + * @param[in] arg Argument passed to the call. + * @param[in] kw_splat Handling of keyword parameters: + * - RB_NO_KEYWORDS `arg`'s last is not a keyword argument. + * - RB_PASS_KEYWORDS `arg`'s last is a keyword argument. + * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * @return What the command evaluates to. + */ +VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat); + +/** + * Identical to rb_funcallv(), except it takes Ruby's array instead of C's. + * @param[in,out] recv Receiver of the method. + * @param[in] mid Name of the method to call. + * @param[in] args An instance of ::RArray. + * @exception rb_eNoMethodError No such method. + * @exception rb_eException Any exceptions happen inside. + * @return What the method evaluates to. + * @pre `args` must be an ::RArray. Call `to_ary` beforehand when + * necessary. + */ +VALUE rb_apply(VALUE recv, ID mid, VALUE args); + +/** + * Evaluates a string containing Ruby source code, or the given block, within + * the context of the receiver. In order to set the context, the variable + * `self` is set to `recv` while the code is executing, giving the code access + * to `recv`'s instance variables and private methods. + * + * When given a block, `recv` is also passed in as the block's only argument. + * + * When given a string, the optional second and third parameters supply a + * filename and starting line number that are used when reporting compilation + * errors. + * + * @param[in] argc Number of objects in `argv` + * @param[in] argv C array of 0 up to 3 elements. + * @param[in] recv The object in question. + * @return What was evaluated. + */ +VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE recv); + +/** + * Executes the given block within the context of the receiver. In order to + * set the context, the variable `self` is set to `recv` while the code is + * executing, giving the code access to `recv`'s instance variables. Arguments + * are passed as block parameters. + * + * @param[in] argc Number of objects in `argv` + * @param[in] argv Arbitrary parameters to be passed to the block. + * @param[in] recv The object in question. + * @return What was evaluated. + * @note Don't confuse this with rb_obj_instance_eval(). The key + * difference is whether you can pass arbitrary parameters to the + * block, like this: + * + * ```ruby + * class Foo + * def initialize + * @foo = 5 + * end + * end + * Foo.new.instance_exec(7) {|i| @foo + i } # => 12 + * ``` + */ +VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE recv); + +/** + * Identical to rb_obj_instance_eval(), except it evaluates within the context + * of module. + * + * @param[in] argc Number of objects in `argv` + * @param[in] argv C array of 0 up to 3 elements. + * @param[in] mod The module in question. + * @pre `mod` must be a Module. + * @return What was evaluated. + */ +VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod); + +/** + * Identical to rb_obj_instance_exec(), except it evaluates within the context + * of module. + * + * @param[in] argc Number of objects in `argv` + * @param[in] argv Arbitrary parameters to be passed to the block. + * @param[in] mod The module in question. + * @pre `mod` must be a Module. + * @return What was evaluated. + */ +VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod); + +/* vm_method.c */ + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_DEFINE_ALLOC_FUNC 1 + +/** + * This is the type of functions that ruby calls when trying to allocate an + * object. It is sometimes necessary to allocate extra memory regions for an + * object. When you define a class that uses ::RTypedData, it is typically the + * case. On such situations define a function of this type and pass it to + * rb_define_alloc_func(). + * + * @param[in] klass The class that this function is registered. + * @return A newly allocated instance of `klass`. + */ +typedef VALUE (*rb_alloc_func_t)(VALUE klass); + +/** + * Sets the allocator function of a class. + * + * @param[out] klass The class to modify. + * @param[in] func An allocator function for the class. + * @pre `klass` must be an instance of Class. + */ +void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func); + +/** + * Deletes the allocator function of a class. It is sometimes desirable to + * restrict creation of an instance of a class. For example it rarely makes + * sense for a DB adaptor class to allow programmers creating DB row objects + * without querying the DB itself. You can kill sporadic creation of such + * objects then, by nullifying the allocator function using this API. Your + * object shall be allocated using #RB_NEWOBJ_OF() directly. + * + * @param[out] klass The class to modify. + * @pre `klass` must be an instance of Class. + */ +void rb_undef_alloc_func(VALUE klass); + +/** + * Queries the allocator function of a class. + * + * @param[in] klass The class in question. + * @pre `klass` must be an instance of Class. + * @retval 0 No allocator function is registered. + * @retval otherwise The allocator function. + * + * @internal + * + * Who cares? @shyouhei fins no practical usage of the return value. Maybe we + * need KonMari. + */ +rb_alloc_func_t rb_get_alloc_func(VALUE klass); + +/** + * Clears the constant cache. Extension libraries should not bother such + * things. Just forget about this API (or even, the presence of constant + * cache). + * + * @internal + * + * Completely no idea why this function is defined in vm_method.c. + */ +void rb_clear_constant_cache(void); + +/** + * Resembles `alias`. + * + * @param[out] klass Where to define an alias. + * @param[in] dst New name. + * @param[in] src Existing name. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError No such method named `src`. + * @post `klass` has a method named `dst`, which is the identical to its + * method named `src`. + */ +void rb_alias(VALUE klass, ID dst, ID src); + +/** + * This function resembles now-deprecated `Module#attr`. + * + * @param[out] klass Where to define an attribute. + * @param[in] name Name of an instance variable. + * @param[in] need_reader Whether attr_reader is needed. + * @param[in] need_writer Whether attr_writer is needed. + * @param[in] honour_visibility Whether to use the current visibility. + * @exception rb_eTypeError `klass` is not a class. + * @exception rb_eFrozenError `klass` is frozen. + * @post If `need_reader` is set `klass` has a method named `name`. + * @post If `need_writer` is set `klass` has a method named `name=`. + * + * @internal + * + * The three `int` arguments should have been bool, but there was no such thing + * like a bool when K&R was used in this project. + */ +void rb_attr(VALUE klass, ID name, int need_reader, int need_writer, int honour_visibility); + +RBIMPL_ATTR_NONNULL(()) +/** + * Removes a method. Don't confuse this to rb_undef_method(), which doesn't + * remove a method. This one resembles `Module#remove_method`. + * + * @param[out] klass The class to remove a method. + * @param[in] name Name of a method to be removed. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError No such method. + * @see rb_undef_method + */ +void rb_remove_method(VALUE klass, const char *name); + +/** + * Identical to rb_remove_method(), except it accepts the method name as ::ID. + * + * @param[out] klass The class to remove a method. + * @param[in] mid Name of a method to be removed. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError No such method. + * @see rb_undef + */ +void rb_remove_method_id(VALUE klass, ID mid); + +/** + * Queries if the klass has this method. This function has only one line of + * document in the implementation that states "// deprecated". Don't know what + * that means though. + * + * @param[in] klass The class in question. + * @param[in] id The method name to query. + * @param[in] ex Undocumented magic value. + * @retval false Method not found. + * @retval true There is a method. + * @pre `klass` must be a module. + * + * @internal + * + * @shyouhei has no motivation to describe what should be passed to `ex`. It + * seems this function should just be trashed. + */ +int rb_method_boundp(VALUE klass, ID id, int ex); + +/** + * Well... Let us hesitate from describing what a "basic definition" is. This + * nuanced concept should have been kept private. Just please. Don't touch + * it. This function is a badly distributed random number generator. Right? + * + * @param[in] klass The class in question. + * @param[in] mid The method name in question. + * @retval 1 It is. + * @retval 0 It isn't. + */ +int rb_method_basic_definition_p(VALUE klass, ID mid); + +/** + * Identical to rb_respond_to(), except it additionally takes the visibility + * parameter. This does not make difference unless the object has + * `respond_to?` undefined, but has `respond_to_missing?` defined. That case + * the passed argument becomes the second argument of `respond_to_missing?`. + * + * @param[in] obj The object in question. + * @param[in] mid The method name in question. + * @param[in] private_p This is the second argument of `obj`'s + * `respond_to_missing?`. + * @retval 1 Yes it does. + * @retval 0 No it doesn't. + */ +int rb_obj_respond_to(VALUE obj, ID mid, int private_p); + +/** + * Queries if the object responds to the method. This involves calling the + * object's `respond_to?` method. + * + * @param[in] obj The object in question. + * @param[in] mid The method name in question. + * @retval 1 Yes it does. + * @retval 0 No it doesn't. + */ +int rb_respond_to(VALUE obj, ID mid); + +RBIMPL_ATTR_NORETURN() +/** + * Raises ::rb_eNotImpError. This function is used as an argument to + * rb_define_method() etc. + * + * ```CXX + * rb_define_method(rb_cFoo, "foo", rb_f_notimplement, -1); + * ``` + * + * @param argc Unused parameter. + * @param argv Unused parameter. + * @param obj Unused parameter. + * @param marker Unused parameter. + * @exception rb_eNotImpError Always. + * @return Never returns. + * + * @internal + * + * See also the Q&A section of include/ruby/internal/anyargs.h. + */ +VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker); +#if !defined(RUBY_EXPORT) && defined(_WIN32) +RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker); +#define rb_f_notimplement (*rb_f_notimplement_) +#endif + +/* vm_backtrace.c */ + +/** + * Prints the backtrace out to the standard error. This just confuses people + * for no reason. Evil souls must only use it. + * + * @internal + * + * Actually it is very useful when called from an interactive GDB session. + */ +void rb_backtrace(void); + +/** + * Creates the good old fashioned array-of-strings style backtrace info. + * + * @return An array which contains strings, which are the textual + * representations of the backtrace locations of the current thread of + * the current ractor of the current execution context. + * @note Ruby scripts can access more sophisticated + * `Thread::Backtrace::Location`. But it seems there is no way for C + * extensions to use that API. + */ +VALUE rb_make_backtrace(void); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_VM_H */ diff --git a/ruby/include/ruby/internal/interpreter.h b/ruby/include/ruby/internal/interpreter.h new file mode 100644 index 000000000..662d39c0e --- /dev/null +++ b/ruby/include/ruby/internal/interpreter.h @@ -0,0 +1,304 @@ +#ifndef RBIMPL_INTERPRETER_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERPRETER_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Interpreter embedding APIs. + */ +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * @defgroup embed CRuby Embedding APIs + * + * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your + * program. + * These functions are not a part of Ruby extension library API. + * Extension libraries of Ruby should not depend on these functions. + * + * @{ + */ + +/** + * @defgroup ruby1 ruby(1) implementation + * + * A part of the implementation of ruby(1) command. + * Other programs that embed Ruby interpreter do not always need to use these + * functions. + * + * @{ + */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Initializes the process for libruby. + * + * This function assumes this process is `ruby(1)` and it has just started. + * Usually programs that embed CRuby interpreter may not call this function, + * and may do their own initialization. + * + * @param[in] argc Pointer to process main's `argc`. + * @param[in] argv Pointer to process main's `argv`. + * @warning `argc` and `argv` cannot be `NULL`. + * + * @internal + * + * AFAIK Ruby does write to argv, especially `argv[0][0]`, via setproctitle(3). + * It is intentional that the argument is not const-qualified. + */ +void ruby_sysinit(int *argc, char ***argv); + +/** + * Calls ruby_setup() and check error. + * + * Prints errors and calls exit(3) if an error occurred. + */ +void ruby_init(void); + +/** + * Processes command line arguments and compiles the Ruby source to execute. + * + * This function does: + * - Processes the given command line flags and arguments for `ruby(1)` + * - Compiles the source code from the given argument, `-e` or `stdin`, and + * - Returns the compiled source as an opaque pointer to an internal data + * structure + * + * @param[in] argc Process main's `argc`. + * @param[in] argv Process main's `argv`. + * @return An opaque pointer to the compiled source or an internal special + * value. Pass it to ruby_executable_node() to detect which. + * @see ruby_executable_node + */ +void* ruby_options(int argc, char** argv); + +/** + * Checks the return value of ruby_options(). + * + * ruby_options() sometimes returns a special value to indicate this process + * should immediately exit. This function checks if the case. Also stores the + * exit status that the caller have to pass to exit(3) into `*status`. + * + * @param[in] n A return value of ruby_options(). + * @param[out] status Pointer to the exit status of this process. + * @retval 0 The given value is such a special value. + * @retval otherwise The given opaque pointer is actually a compiled + * source. + */ +int ruby_executable_node(void *n, int *status); + +/** + * Runs the given compiled source and exits this process. + * + * @param[in] n Opaque "node" pointer. + * @retval EXIT_SUCCESS Successfully run the source. + * @retval EXIT_FAILURE An error occurred. + */ +int ruby_run_node(void *n); + +/* version.c */ +/** Prints the version information of the CRuby interpreter to stdout. */ +void ruby_show_version(void); + +#ifndef ruby_show_copyright +/** Prints the copyright notice of the CRuby interpreter to stdout. */ +void ruby_show_copyright(void); +#endif + +/** + * A convenience macro to call ruby_init_stack(). + * Must be placed just after variable declarations. + */ +#define RUBY_INIT_STACK \ + VALUE variable_in_this_stack_frame; \ + ruby_init_stack(&variable_in_this_stack_frame); +/** @} */ + +/** + * Set stack bottom of Ruby implementation. + * + * You must call this function before any heap allocation by Ruby + * implementation. Or GC will break living objects. + * + * @param[in] addr A pointer somewhere on the stack, near its bottom. + */ +void ruby_init_stack(volatile VALUE *addr); + +/** + * Initializes the VM and builtin libraries. + * + * @retval 0 Initialization succeeded. + * @retval otherwise An error occurred. + * + * @internal + * + * Though not a part of our public API, the return value is in fact an enum + * ruby_tag_type. You can see the potential "otherwise" values by looking at + * vm_core.h. + */ +int ruby_setup(void); + +/** + * Destructs the VM. + * + * Runs the VM finalization processes as well as ruby_finalize(), and frees + * resources used by the VM. + * + * @param[in] ex Default value to the return value. + * @retval EXIT_FAILURE An error occurred. + * @retval ex Successful cleanup. + * @note This function does not raise any exception. + */ +int ruby_cleanup(int ex); + +/** + * Runs the VM finalization processes. + * + * `END{}` and procs registered by `Kernel.#at_exit` are executed here. See the + * Ruby language spec for more details. + * + * @note This function is allowed to raise an exception if an error occurred. + */ +void ruby_finalize(void); + +RBIMPL_ATTR_NORETURN() +/** Calls ruby_cleanup() and exits the process. */ +void ruby_stop(int); + +/** + * Checks for stack overflow. + * + * @retval true NG machine stack is about to overflow. + * @retval false OK there still is a room in the stack. + * + * @internal + * + * Does anybody use it? So far @shyouhei have never seen any actual use-case. + */ +int ruby_stack_check(void); + +/** + * Queries what Ruby thinks is the machine stack. Ruby manages a region of + * memory. It calls that area the "machine stack". By calling this function, + * in spite of its name, you can obtain both one end of the stack and its + * length at once. Which means you can know the entire region. + * + * @param[out] topnotch On return the pointer points to the upmost address of + * the macihne stack that Ruby knows. + * @return Length of the machine stack that Ruby knows. + * + * @internal + * + * Does anybody use it? @shyouhei is quite skeptical if this is useful outside + * of the VM. Maybe it was a wrong idea to expose this API to 3rd parties. + */ +size_t ruby_stack_length(VALUE **topnotch); + +/** + * Identical to ruby_run_node(), except it returns an opaque execution status. + * You can pass it to rb_cleanup(). + * + * @param[in] n Opaque "node" pointer. + * @retval 0 Successful end-of-execution. + * @retval otherwise An error occurred. + * + * @internal + * + * Though not a part of our public API, the return value is in fact an enum + * ruby_tag_type. You can see the potential "otherwise" values by looking at + * vm_core.h. + */ +int ruby_exec_node(void *n); + +/** + * Sets the current script name to this value. + * + * This is similar to `$0 = name` in Ruby level but also affects + * `Method#location` and others. + * + * @param[in] name File name to set. + */ +void ruby_script(const char* name); + +/** + * Identical to ruby_script(), except it takes the name as a Ruby String + * instance. + * + * @param[in] name File name to set. + */ +void ruby_set_script_name(VALUE name); + +/** Defines built-in variables */ +void ruby_prog_init(void); + +/** + * Sets argv that ruby understands. Your program might have its own command + * line parameters etc. Handle them as you wish, and pass remaining parts of + * argv here. + * + * @param[in] argc Number of elements of `argv`. + * @param[in] argv Command line arguments. + */ +void ruby_set_argv(int argc, char **argv); + +/** + * Identical to ruby_options(), except it raises ruby-level exceptions on + * failure. + * + * @param[in] argc Process main's `argc`. + * @param[in] argv Process main's `argv`. + * @return An opaque "node" pointer. + */ +void *ruby_process_options(int argc, char **argv); + +/** + * Sets up `$LOAD_PATH`. + * + * @internal + * + * @shyouhei guesses this has to be called at very later stage, at least after + * the birth of object system. But is not exactly sure when. + */ +void ruby_init_loadpath(void); + +/** + * Appends the given path to the end of the load path. + * + * @pre ruby_init_loadpath() must be done beforehand. + * @param[in] path The path you want to push to the load path. + */ +void ruby_incpush(const char *path); + +/** + * Clear signal handlers. + * + * Ruby installs its own signal handler (apart from those which user scripts + * set). This is to clear that. Must be called when the ruby part terminates, + * before switching to your program's own logic. + */ +void ruby_sig_finalize(void); + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERPRETER_H */ diff --git a/ruby/include/ruby/internal/iterator.h b/ruby/include/ruby/internal/iterator.h new file mode 100644 index 000000000..5f706460f --- /dev/null +++ b/ruby/include/ruby/internal/iterator.h @@ -0,0 +1,513 @@ +#ifndef RBIMPL_ITERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ITERATOR_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Block related APIs. + */ +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RB_BLOCK_CALL_FUNC_STRICT 1 + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1 + +/** + * Shim for block function parameters. Historically ::rb_block_call_func_t had + * only two parameters. Over time it evolved to have much more than that. By + * using this macro you can absorb such API differences. + * + * ```CXX + * // This works since 2.1.0 + * VALUE my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)); + * ``` + */ +#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \ + VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg + +/** + * This is the type of a function that the interpreter expect for C-backended + * blocks. Blocks are often written in Ruby. But C extensions might want to + * have their own blocks. In order to do so authors have to create a separate + * C function of this type, and pass its pointer to rb_block_call(). + * + * ```CXX + * VALUE + * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)) + * { + * const auto plus = rb_intern("+"); + * return rb_funcall(c, plus, 1, y); + * } + * + * VALUE + * my_own_method(VALUE self) + * { + * const auto each = rb_intern("each"); + * return rb_block_call(self, each, 0, 0, my_own_iterator, self); + * } + * ``` + */ +typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); + +/** + * Shorthand type that represents an iterator-written-in-C function pointer. + */ +typedef rb_block_call_func *rb_block_call_func_t; + +/** + * This is a shorthand of calling `obj.each`. + * + * @param[in] obj The receiver. + * @return What `obj.each` returns. + * + * @internal + * + * Does anyone still need it? This API was to use with rb_iterate(), which is + * marked deprecated (see below). Old idiom to call an iterator was: + * + * ```CXX + * VALUE recv; + * VALUE iter_func(ANYARGS); + * VALUE iter_data; + * rb_iterate(rb_each, recv, iter_func, iter_data); + * ``` + */ +VALUE rb_each(VALUE obj); + +/** + * Yields the block. In Ruby there is a concept called a block. You can pass + * one to a method. In a method, when called with a block, you can yield it + * using this function. + * + * ```CXX + * VALUE + * iterate(VALUE self) + * { + * extern int get_n(VALUE); + * extern VALUE get_v(VALUE, VALUE); + * const auto n = get_n(self); + * + * for (int i=0; i + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Memory management stuff. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDINT_H +# include +#endif + +#ifdef HAVE_ALLOCA_H +# include +#endif + +#if defined(_MSC_VER) && defined(_WIN64) +# include +# pragma intrinsic(_umul128) +#endif + +#include "ruby/internal/attr/alloc_size.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/restrict.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/stdalign.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/xmalloc.h" +#include "ruby/backward/2/limits.h" +#include "ruby/backward/2/long_long.h" +#include "ruby/backward/2/assume.h" +#include "ruby/defines.h" + +/** @cond INTENAL_MACRO */ + +/* Make alloca work the best possible way. */ +#if defined(alloca) +# /* Take that. */ +#elif RBIMPL_HAS_BUILTIN(__builtin_alloca) +# define alloca __builtin_alloca +#elif defined(_AIX) +# pragma alloca +#elif defined(__cplusplus) +extern "C" void *alloca(size_t); +#else +extern void *alloca(); +#endif + +/** @endcond */ + +#if defined(__DOXYGEN__) +/** + * @private + * + * Type that is as twice wider as size_t. This is an implementation detail of + * rb_mul_size_overflow(). People should not use it. This is not a good name + * either. + */ +typedef uint128_t DSIZE_T; +#elif defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8 +# define DSIZE_T uint128_t +#elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG +# define DSIZE_T unsigned LONG_LONG +#endif + +/** + * @private + * + * Maximum possible number of bytes that #RB_ALLOCV can allocate using + * `alloca`. Anything beyond this is allocated using rb_alloc_tmp_buffer(). + * This selection is transparent to users. People don't have to bother. + */ +#ifdef C_ALLOCA +# define RUBY_ALLOCV_LIMIT 0 +#else +# define RUBY_ALLOCV_LIMIT 1024 +#endif + +/** + * Prevents premature destruction of local objects. Ruby's garbage collector + * is conservative; it scans the C level machine stack as well. Possible in- + * use Ruby objects must remain visible on stack, to be properly marked as + * such. However contemporary C compilers do not interface well with this. + * Consider the following example: + * + * ```CXX + * auto s = rb_str_new_cstr(" world"); + * auto sptr = RSTRING_PTR(s); + * auto t = rb_str_new_cstr("hello,"); // Possible GC invocation + * auto u = rb_str_cat_cstr(t, sptr); + * + * RB_GC_GUARD(s); // ensure `s` (and thus `sptr`) do not get GC-ed + * ``` + * + * Here, without the #RB_GC_GUARD, the last use of `s` is _before_ the last use + * of `sptr`. Compilers could thus think `s` and `t` are allowed to overlap. + * That would eliminate `s` from the stack, while `sptr` is still in use. If + * our GC ran at that very moment, `s` gets swept out, which also destroys + * `sptr`. Boom! You got a SEGV. + * + * In order to prevent this scenario #RB_GC_GUARD must be placed _after_ the + * last use of `sptr`. Placing #RB_GC_GUARD before dereferencing `sptr` would + * be of no use. + * + * #RB_GC_GUARD would not be necessary at all in the above example if non- + * inlined function calls are made on the `s` variable after `sptr` is + * dereferenced. Thus, in the above example, calling any un-inlined function + * on `s` such as `rb_str_modify(s);` will ensure `s` stays on the stack or + * register to prevent a GC invocation from prematurely freeing it. + * + * Using the #RB_GC_GUARD macro is preferable to using the `volatile` keyword + * in C. #RB_GC_GUARD has the following advantages: + * + * - the intent of the macro use is clear. + * + * - #RB_GC_GUARD only affects its call site. OTOH `volatile` generates some + * extra code every time the variable is used, hurting optimisation. + * + * - `volatile` implementations may be buggy/inconsistent in some compilers + * and architectures. #RB_GC_GUARD is customisable for broken + * systems/compilers without negatively affecting other systems. + * + * - C++ since C++20 deprecates `volatile`. If you write your extension + * library in that language there is no escape but to use this macro. + * + * @param v A variable of ::VALUE type. + * @post `v` is still alive. + */ +#ifdef __GNUC__ +#define RB_GC_GUARD(v) \ + (*__extension__ ({ \ + volatile VALUE *rb_gc_guarded_ptr = &(v); \ + __asm__("" : : "m"(rb_gc_guarded_ptr)); \ + rb_gc_guarded_ptr; \ + })) +#elif defined _MSC_VER +#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v))) +#else +#define HAVE_RB_GC_GUARDED_PTR_VAL 1 +#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v))) +#endif + +/* Casts needed because void* is NOT compatible with others in C++. */ + +/** + * Convenient macro that allocates an array of n elements. + * + * @param type Type of array elements. + * @param n Length of the array. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError Integer overflow trying to calculate the length + * of continuous memory region of `n` elements of + * `type`. + * @return Storage instance that is capable of storing at least `n` + * elements of type `type`. + * @note It doesn't return NULL, even when `n` is zero. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +#define RB_ALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type))) + +/** + * Shorthand of #RB_ALLOC_N with `n=1`. + * + * @param type Type of allocation. + * @exception rb_eNoMemError No space left for allocation. + * @return Storage instance that can hold an `type` object. + * @note It doesn't return NULL. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +#define RB_ALLOC(type) RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type))) + +/** + * Identical to #RB_ALLOC_N() but also nullifies the allocated region before + * returning. + * + * @param type Type of array elements. + * @param n Length of the array. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError Integer overflow trying to calculate the length + * of continuous memory region of `n` elements of + * `type`. + * @return Storage instance that is capable of storing at least `n` + * elements of type `type`. + * @post Returned array is filled with zeros. + * @note It doesn't return NULL, even when `n` is zero. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +#define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type))) + +/** + * Shorthand of #RB_ZALLOC_N with `n=1`. + * + * @param type Type of allocation. + * @exception rb_eNoMemError No space left for allocation. + * @return Storage instance that can hold an `type` object. + * @post Returned object is filled with zeros. + * @note It doesn't return NULL. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +#define RB_ZALLOC(type) (RB_ZALLOC_N(type, 1)) + +/** + * Convenient macro that reallocates an array with a new size. + * + * @param var A variable of `type`, which points to a storage + * instance that was previously returned from + * either + * - ruby_xmalloc(), + * - ruby_xmalloc2(), + * - ruby_xcalloc(), + * - ruby_xrealloc(), or + * - ruby_xrealloc2(). + * @param type Type of allocation. + * @param n Requested new size of each element. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError Integer overflow trying to calculate the length + * of continuous memory region of `n` elements of + * `type`. + * @return Storage instance that is capable of storing at least `n` + * elements of type `type`. + * @pre The passed variable must point to a valid live storage instance. + * It is a failure to pass a variable that holds an already-freed + * pointer. + * @note It doesn't return NULL, even when `n` is zero. + * @warning Do not assume anything on the alignment of the return value. + * There is no guarantee that it inherits the passed argument's + * one. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +#define RB_REALLOC_N(var,type,n) \ + ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type)))) + +/** + * @deprecated This macro is dangerous (does not bother stack overflow at + * all). #RB_ALLOCV is the modern way to do the same thing. + * @param type Type of array elements. + * @param n Length of the array. + * @return A pointer on stack. + */ +#define ALLOCA_N(type,n) \ + RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n)))) + +/** + * Identical to #RB_ALLOCV_N(), except it implicitly assumes the type of array + * is ::VALUE. + * + * @param v A variable to hold the just-in-case opaque Ruby object. + * @param n Size of allocation, in bytes. + * @return An array of `n` bytes of ::VALUE. + * @note `n` may be evaluated twice. + */ +#define RB_ALLOCV(v, n) \ + ((n) < RUBY_ALLOCV_LIMIT ? \ + ((v) = 0, alloca(n)) : \ + rb_alloc_tmp_buffer(&(v), (n))) + +/** + * Allocates a memory region, possibly on stack. If the given size exceeds + * #RUBY_ALLOCV_LIMIT, it allocates a dedicated opaque ruby object instead and + * let our GC sweep that region after use. Either way you can fire-and-forget. + * + * ```CXX + * #include + * + * VALUE + * foo(int n) + * { + * VALUE v; + * auto ptr = RB_ALLOCV(struct tms, v, n); + * ... + * // no need to free `ptr`. + * } + * ``` + * + * If you want to be super-duper polite you can also explicitly state the end + * of use of such memory region by calling #RB_ALLOCV_END(). + * + * @param type The type of array elements. + * @param v A variable to hold the just-in-case opaque Ruby object. + * @param n Number of elements requested to allocate. + * @return An array of `n` elements of `type`. + * @note `n` may be evaluated twice. + */ +#define RB_ALLOCV_N(type, v, n) \ + RBIMPL_CAST((type *) \ + (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ + ((v) = 0, alloca((n) * sizeof(type))) : \ + rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) + +/** + * Polite way to declare that the given array is not used any longer. Calling + * this not mandatory. Our GC can baby-sit you. However it is not a very bad + * idea to use it when possible. Doing so could reduce memory footprint. + * + * @param v A variable previously passed to either #RB_ALLOCV/#RB_ALLOCV_N. + */ +#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) + +/** + * Handy macro to erase a region of memory. + * + * @param p Target pointer. + * @param type Type of `p[0]` + * @param n Length of `p`. + * @return `p`. + * @post First `n` elements of `p` are squashed. + */ +#define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n))) + +/** + * Handy macro to call memcpy. + * + * @param p1 Destination pointer. + * @param p2 Source pointer. + * @param type Type of `p2[0]` + * @param n Length of `p2`. + * @return `p1`. + * @post First `n` elements of `p2` are copied into `p1`. + */ +#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) + +/** + * Handy macro to call memmove. + * + * @param p1 Destination pointer. + * @param p2 Source pointer. + * @param type Type of `p2[0]` + * @param n Length of `p2`. + * @return `p1`. + * @post First `n` elements of `p2` are copied into `p1`. + */ +#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) + +/** + * Handy macro to call memcmp + * + * @param p1 Target LHS. + * @param p2 Target RHS. + * @param type Type of `p1[0]` + * @param n Length of `p1`. + * @retval <0 `p1` is "less" than `p2`. + * @retval 0 `p1` is equal to `p2`. + * @retval >0 `p1` is "greater" than `p2`. + */ +#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) + +#define ALLOC_N RB_ALLOC_N /**< @old{RB_ALLOC_N} */ +#define ALLOC RB_ALLOC /**< @old{RB_ALLOC} */ +#define ZALLOC_N RB_ZALLOC_N /**< @old{RB_ZALLOC_N} */ +#define ZALLOC RB_ZALLOC /**< @old{RB_ZALLOC} */ +#define REALLOC_N RB_REALLOC_N /**< @old{RB_REALLOC_N} */ +#define ALLOCV RB_ALLOCV /**< @old{RB_ALLOCV} */ +#define ALLOCV_N RB_ALLOCV_N /**< @old{RB_ALLOCV_N} */ +#define ALLOCV_END RB_ALLOCV_END /**< @old{RB_ALLOCV_END} */ + +/** + * @private + * + * This is an implementation detail of rbimpl_size_mul_overflow(). + * + * @internal + * + * Expecting this struct to be eliminated by function inlinings. This is + * nothing more than std::variant if we could use recent C++, but + * reality is we cannot. + */ +struct rbimpl_size_mul_overflow_tag { + bool left; /**< Whether overflow happened or not. */ + size_t right; /**< Multiplication result. */ +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2)) +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV(). People don't use this + * directly. + * + * @param[out] store Pointer to a variable. + * @param[in] len Requested number of bytes to allocate. + * @return Allocated `len` bytes array. + * @post `store` holds the corresponding tmp buffer object. + */ +void *rb_alloc_tmp_buffer(volatile VALUE *store, long len); + +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2,3)) +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV_N(). People don't use this + * directly. + * + * @param[out] store Pointer to a variable. + * @param[in] len Requested number of bytes to allocate. + * @param[in] count Number of elements in an array. + * @return Allocated `len` bytes array. + * @post `store` holds the corresponding tmp buffer object. + * + * @internal + * + * Although the meaning of `count` variable is clear, @shyouhei doesn't + * understand its needs. + */ +void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count); + +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV_END(). People don't use this + * directly. + * + * @param[out] store Pointer to a variable. + * @pre `store` is a NULL, or a pointer to a tmp buffer object. + * @post `*store` is ::RUBY_Qfalse. + * @post The object formerly stored in `store` is destroyed. + */ +void rb_free_tmp_buffer(volatile VALUE *store); + +RBIMPL_ATTR_NORETURN() +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV_N(). People don't use this + * directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @exception rb_eArgError `x` * `y` would integer overflow. + */ +void ruby_malloc_size_overflow(size_t x, size_t y); + +#ifdef HAVE_RB_GC_GUARDED_PTR_VAL +volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val); +#endif +RBIMPL_SYMBOL_EXPORT_END() + +#ifdef _MSC_VER +# pragma optimize("", off) + +/** + * @private + * + * This is an implementation detail of #RB_GC_GUARD(). People don't use this + * directly. + * + * @param[in] ptr A pointer to an on-stack C variable. + * @return `ptr` as-is. + */ +static inline volatile VALUE * +rb_gc_guarded_ptr(volatile VALUE *ptr) +{ + return ptr; +} + +# pragma optimize("", on) +#endif + +/** + * @deprecated This function was an implementation detail of old + * #RB_ALLOCV_N(). We no longer use it. @shyouhei suspects that + * there are no actual usage now. However it was not marked as + * private before. We cannot delete it any longer. + * @param[in] a Arbitrary value. + * @param[in] b Arbitrary value. + * @param[in] max Possible maximum value. + * @param[out] c A pointer to return the computation result. + * @retval 1 `c` is insane. + * @retval 0 `c` is sane. + * @post `c` holds `a` * `b`, but could be overflowed. + */ +static inline int +rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c) +{ +#ifdef DSIZE_T + RB_GNUC_EXTENSION DSIZE_T da, db, c2; + da = a; + db = b; + c2 = da * db; + if (c2 > max) return 1; + *c = RBIMPL_CAST((size_t)c2); +#else + if (b != 0 && a > max / b) return 1; + *c = a * b; +#endif + return 0; +} + +#if defined(__DOXYGEN__) +RBIMPL_ATTR_CONSTEXPR(CXX14) +#elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) +RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */ +#elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0) +RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */ +#endif +RBIMPL_ATTR_CONST() +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV_N(). People don't use this + * directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @return `{ left, right }`, where `left` is whether there is an integer + * overflow or not, and `right` is a (possibly overflowed) result + * of `x` * `y`. + * + * @internal + * + * This is in fact also an implementation detail of ruby_xmalloc2() etc. + */ +static inline struct rbimpl_size_mul_overflow_tag +rbimpl_size_mul_overflow(size_t x, size_t y) +{ + struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; + +#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) + ret.left = __builtin_mul_overflow(x, y, &ret.right); + +#elif defined(DSIZE_T) + RB_GNUC_EXTENSION DSIZE_T dx = x; + RB_GNUC_EXTENSION DSIZE_T dy = y; + RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; + ret.left = dz > SIZE_MAX; + ret.right = RBIMPL_CAST((size_t)dz); + +#elif defined(_MSC_VER) && defined(_WIN64) + unsigned __int64 dp = 0; + unsigned __int64 dz = _umul128(x, y, &dp); + ret.left = RBIMPL_CAST((bool)dp); + ret.right = RBIMPL_CAST((size_t)dz); + +#else + /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ + ret.left = (y != 0) && (x > SIZE_MAX / y); + ret.right = x * y; +#endif + + return ret; +} + +/** + * @private + * + * This is an implementation detail of #RB_ALLOCV_N(). People don't use this + * directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @exception rb_eArgError Multiplication could integer overflow. + * @return `x` * `y`. + * + * @internal + * + * This is in fact also an implementation detail of ruby_xmalloc2() etc. + */ +static inline size_t +rbimpl_size_mul_or_raise(size_t x, size_t y) +{ + struct rbimpl_size_mul_overflow_tag size = + rbimpl_size_mul_overflow(x, y); + + if (RB_LIKELY(! size.left)) { + return size.right; + } + else { + ruby_malloc_size_overflow(x, y); + RBIMPL_UNREACHABLE_RETURN(0); + } +} + +/** + * This is an implementation detail of #RB_ALLOCV_N(). People don't use this + * directly. + * + * @param[out] store Pointer to a variable. + * @param[in] count Number of elements in an array. + * @param[in] elsize Size of each elements. + * @return Region of `count` * `elsize` bytes. + * @post `store` holds the corresponding tmp buffer object. + * + * @internal + * + * We might want to deprecate this function and make a `rbimpl_` counterpart. + */ +static inline void * +rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) +{ + const size_t total_size = rbimpl_size_mul_or_raise(count, elsize); + const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE); + return rb_alloc_tmp_buffer_with_count(store, total_size, cnt); +} + +#if ! defined(__MINGW32__) && ! defined(__DOXYGEN__) +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +RBIMPL_ATTR_RETURNS_NONNULL() +/* At least since 2004, glibc's annotates memcpy to be + * __attribute__((__nonnull__(1, 2))). However it is safe to pass NULL to the + * source pointer, if n is 0. Let's wrap memcpy. */ +static inline void * +ruby_nonempty_memcpy(void *dest, const void *src, size_t n) +{ + if (n) { + return memcpy(dest, src, n); + } + else { + return dest; + } +} +RBIMPL_SYMBOL_EXPORT_END() +#undef memcpy +#define memcpy ruby_nonempty_memcpy +#endif + +#endif /* RBIMPL_MEMORY_H */ diff --git a/ruby/include/ruby/internal/method.h b/ruby/include/ruby/internal/method.h new file mode 100644 index 000000000..19feb0c10 --- /dev/null +++ b/ruby/include/ruby/internal/method.h @@ -0,0 +1,205 @@ +#ifndef RBIMPL_METHOD_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_METHOD_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Creation and modification of Ruby methods. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/backward/2/stdarg.h" + +/** + * @defgroup defmethod Defining methods + * + * There are some APIs to define a method from C. + * These API takes a C function as a method body. + * + * ### Method body functions + * + * Method body functions must return a VALUE and + * can be one of the following form: + * + * #### Fixed number of parameters + * + * This form is a normal C function, excepting it takes + * a receiver object as the first argument. + * + * ```CXX + * static VALUE my_method(VALUE self, VALUE x, VALUE y); + * ``` + * + * #### argc and argv style + * + * This form takes three parameters: argc, argv and self. + * self is the receiver. argc is the number of arguments. + * argv is a pointer to an array of the arguments. + * + * ```CXX + * static VALUE my_method(int argc, VALUE *argv, VALUE self); + * ``` + * + * #### Ruby array style + * + * This form takes two parameters: self and args. + * self is the receiver. args is an Array object which + * contains the arguments. + * + * ```CXX + * static VALUE my_method(VALUE self, VALUE args); + * ``` + * + * ### Number of parameters + * + * Method defining APIs takes the number of parameters which the + * method will takes. This number is called argc. + * argc can be: + * + * - Zero or positive number. + * This means the method body function takes a fixed number of parameters. + * + * - `-1`. + * This means the method body function is "argc and argv" style. + * + * - `-2`. + * This means the method body function is "self and args" style. + * + * @{ + */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a method. + * + * @param[out] klass A module or a class. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method + */ +void rb_define_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a module function for a module. + * + * @param[out] klass A module or a class. + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_module_function + */ +void rb_define_module_function(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a global function. + * + * @param[in] mid Name of the function. + * @param[in] func The method body. + * @param[in] arity The number of parameters. See @ref defmethod. + * @note There are in fact 18 different prototypes for func. + * @see ::ruby::backward::cxxanyargs::define_method::rb_define_global_function + */ +void rb_define_global_function(const char *mid, VALUE (*func)(ANYARGS), int arity); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines an undef of a method. -- What? + * + * In ruby, there are two separate concepts called "undef" and "remove_method". + * The thing you imagine when you "un-define" a method is remove_method. This + * one on the other hand is masking of a previous method definition. Suppose + * for instance: + * + * ```ruby + * class Foo + * def foo + * end + * end + * + * class Bar < Foo + * def bar + * foo + * end + * end + * + * class Baz < Foo + * undef foo # <--- (*1) + * end + * ``` + * + * This `undef foo` at `(*1)` must not eliminate `Foo#foo`, because that method + * is also used from `Bar#bar`. So instead of physically executing the target + * method, `undef` inserts a special filtering entry to the class (`Baz` this + * case). That entry, when called, acts as if there were no methods at all. + * But the original can still be accessible, via ways like `Bar#bar` above. + * + * @param[out] klass The class to insert an undef. + * @param[in] name Name of the undef. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @see rb_remove_method + */ +void rb_undef_method(VALUE klass, const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines an alias of a method. + * + * @param[in,out] klass The class which the original method belongs + * to; this is also where the new method will + * belong to. + * @param[in] dst A new name for the method. + * @param[in] src The original name of the method. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError There is no such method named as `src` in + * `klass`. + * + * @internal + * + * Above description is in fact a bit inaccurate because it ignores + * Refinements. + */ +void rb_define_alias(VALUE klass, const char *dst, const char *src); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines public accessor method(s) for an attribute. + * + * @param[out] klass The class which the attribute will belong to. + * @param[in] name Name of the attribute. + * @param[in] read Whether to define a getter method. + * @param[in] write Whether to define a setter method. + * @exception rb_eTypeError `klass` is a non-module. + * @exception rb_eFrozenError `klass` is frozen. + * @exception rb_eNameError `name` invalid as an attr e.g. an operator. + */ +void rb_define_attr(VALUE klass, const char *name, int read, int write); + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_METHOD_H */ diff --git a/ruby/include/ruby/internal/module.h b/ruby/include/ruby/internal/module.h new file mode 100644 index 000000000..d678dd210 --- /dev/null +++ b/ruby/include/ruby/internal/module.h @@ -0,0 +1,177 @@ +#ifndef RBIMPL_MODULE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_MODULE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Creation and modification of Ruby modules. + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +/** + * @defgroup class Classes and their hierarchy. + * + * @par Terminology + * - class: same as in Ruby. + * - singleton class: class for a particular object. + * - eigenclass: = singleton class + * - metaclass: class of a class. Metaclass is a kind of singleton class. + * - metametaclass: class of a metaclass. + * - meta^(n)-class: class of a meta^(n-1)-class. + * - attached object: A singleton class knows its unique instance. + * The instance is called the attached object for the singleton class. + * @{ + */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a top-level class. + * + * @param[in] name Name of the class. + * @param[in] super A class from which the new class will derive. + * @exception rb_eTypeError The constant name `name` is already taken but the + * constant is not a class. + * @exception rb_eTypeError The class is already defined but the class can + * not be reopened because its superclass is not + * `super`. + * @exception rb_eArgError `super` is NULL. + * @return The created class. + * @post Top-level constant named `name` refers the returned class. + * @note If a class named `name` is already defined and its superclass is + * `super`, the function just returns the defined class. + * @note The compaction GC does not move classes returned by this + * function. + * + * @internal + * + * There are classes without names, but you can't pass NULL here. You have to + * use other ways to create one. + */ +VALUE rb_define_class(const char *name, VALUE super); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a top-level module. + * + * @param[in] name Name of the module. + * @exception rb_eTypeError The constant name `name` is already taken but the + * constant is not a module. + * @return The created module. + * @post Top-level constant named `name` refers the returned module. + * @note The compaction GC does not move classes returned by this + * function. + * + * @internal + * + * There are modules without names, but you can't pass NULL here. You have to + * use other ways to create one. + */ +VALUE rb_define_module(const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a class under the namespace of `outer`. + * + * @param[out] outer A class which contains the new class. + * @param[in] name Name of the new class + * @param[in] super A class from which the new class will derive. + * 0 means ::rb_cObject. + * @exception rb_eTypeError The constant name `name` is already taken but + * the constant is not a class. + * @exception rb_eTypeError The class is already defined but the class can + * not be reopened because its superclass is not + * `super`. + * @exception rb_eArgError `super` is NULL. + * @return The created class. + * @post `outer::name` refers the returned class. + * @note If a class named `name` is already defined and its superclass + * is `super`, the function just returns the defined class. + * @note The compaction GC does not move classes returned by this + * function. + */ +VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a module under the namespace of `outer`. + * + * @param[out] outer A class which contains the new module. + * @param[in] name Name of the new module + * @exception rb_eTypeError The constant name `name` is already taken but + * the constant is not a class. + * @return The created module. + * @post `outer::name` refers the returned module. + * @note The compaction GC does not move classes returned by this + * function. + */ +VALUE rb_define_module_under(VALUE outer, const char *name); + +/** + * Includes a module to a class. + * + * @param[out] klass Inclusion destination. + * @param[in] module Inclusion source. + * @exception rb_eArgError Cyclic inclusion. + * + * @internal + * + * :FIXME: @shyouhei suspects this function lacks assertion that the arguments + * being modules... Could silently SEGV if non-module was passed? + */ +void rb_include_module(VALUE klass, VALUE module); + +/** + * Extend the object with the module. + * + * @warning This is the same as `Module#extend_object`, not + * `Object#extend`! These two methods are very similar, but not + * identical. The difference is the hook. `Module#extend_object` + * does not invoke `Module#extended`, while `Object#extend` does. + * @param[out] obj Object to extend. + * @param[in] mod Module of extension. + */ +void rb_extend_object(VALUE obj, VALUE mod); + +/** + * Identical to rb_include_module(), except it "prepends" the passed module to + * the klass, instead of includes. This affects how `super` resolves. For + * instance: + * + * ```ruby + * class Q; def foo; "" end end + * module W; def foo; "#{super}" end end + * class E < Q; include W; def foo; "#{super}" end end + * class R < Q; prepend W; def foo; "#{super}" end end + * + * E.new.foo # => "" + * r.new.foo # => "" + * ``` + * + * @param[out] klass Target class to modify. + * @param[in] module Module to prepend. + * @exception rb_eArgError Cyclic inclusion. + */ +void rb_prepend_module(VALUE klass, VALUE module); + +/** @} */ + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_MODULE_H */ diff --git a/ruby/include/ruby/internal/newobj.h b/ruby/include/ruby/internal/newobj.h new file mode 100644 index 000000000..a8a5557a2 --- /dev/null +++ b/ruby/include/ruby/internal/newobj.h @@ -0,0 +1,195 @@ +#ifndef RBIMPL_NEWOBJ_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_NEWOBJ_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #NEWOBJ. + */ +#include "ruby/internal/attr/deprecated.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +/** + * Declares, allocates, then assigns a new object to the given variable. + * + * @param obj Variable name. + * @param type Variable type. + * @exception rb_eNoMemError No space left. + * @return An allocated object, not initialised. + * @note Modern programs tend to use #NEWOBJ_OF instead. + * + * @internal + * + * :FIXME: Should we deprecate it? + */ +#define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj()) + +/** + * Identical to #RB_NEWOBJ, except it also accepts the allocating object's + * class and flags. + * + * @param obj Variable name. + * @param type Variable type. + * @param klass Object's class. + * @param flags Object's flags. + * @exception rb_eNoMemError No space left. + * @return An allocated object, filled with the arguments. + */ +#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags)) + +#define NEWOBJ RB_NEWOBJ /**< @old{RB_NEWOBJ} */ +#define NEWOBJ_OF RB_NEWOBJ_OF /**< @old{RB_NEWOBJ_OF} */ +#define OBJSETUP rb_obj_setup /**< @old{rb_obj_setup} */ +#define CLONESETUP rb_clone_setup /**< @old{rb_clone_setup} */ +#define DUPSETUP rb_dup_setup /**< @old{rb_dup_setup} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * This is the implementation detail of #RB_NEWOBJ. + * + * @exception rb_eNoMemError No space left. + * @return An allocated object, not initialised. + */ +VALUE rb_newobj(void); + +/** + * This is the implementation detail of #RB_NEWOBJ_OF. + * + * @param klass Object's class. + * @param flags Object's flags. + * @exception rb_eNoMemError No space left. + * @return An allocated object, filled with the arguments. + */ +VALUE rb_newobj_of(VALUE klass, VALUE flags); + +/** + * Fills common fields in the object. + * + * @note Prefer rb_newobj_of() to this function. + * @param[in,out] obj A Ruby object to be set up. + * @param[in] klass `obj` will belong to this class. + * @param[in] type One of ::ruby_value_type. + * @return The passed object. + * + * @internal + * + * Historically, authors of Ruby has described the `type` argument as "one of + * ::ruby_value_type". In reality it accepts either ::ruby_value_type, + * ::ruby_fl_type, or any combinations of the two. For instance + * `RUBY_T_STRING | RUBY_FL_FREEZE` is a valid value that this function takes, + * and means this is a frozen string. + * + * 3rd party extension libraries rarely need to allocate Strings this way. + * They normally only concern ::RUBY_T_DATA. This argument is mainly used for + * specifying flags, @shyouhei suspects. + */ +VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type); + +/** + * Queries the class of an object. This is not always identical to + * `RBASIC_CLASS(obj)`. It searches for the nearest ancestor skipping + * singleton classes or included modules. + * + * @param[in] obj Object in question. + * @return The object's class, in a normal sense. + */ +VALUE rb_obj_class(VALUE obj); + +/** + * Clones a singleton class. An object can have its own singleton class. OK. + * Then what happens when a program clones such object? The singleton class + * that is attached to the source object must also be cloned. Otherwise a + * singleton object gets shared with two objects, which breaks "singleton"-ness + * of such class. + * + * This is basically an implementation detail of rb_clone_setup(). People + * need not be aware of this working behind-the-scene. + * + * @param[in] obj The object that has its own singleton class. + * @return Cloned singleton class. + */ +VALUE rb_singleton_class_clone(VALUE obj); + +/** + * Attaches a singleton class to its corresponding object. + * + * This is basically an implementation detail of rb_clone_setup(). People + * need not be aware of this working behind-the-scene. + * + * @param[in] klass The singleton class. + * @param[out] obj The object to attach a class. + * @pre The passed two objects must agree with each other that `klass` + * becomes a singleton class of `obj`. + * @post `klass` becomes the singleton class of `obj`. + */ +void rb_singleton_class_attached(VALUE klass, VALUE obj); + +/** + * Copies the list of instance variables. 3rd parties need not know, but there + * are several ways to store an object's instance variables, depending on its + * internal structure. This function makes sense when either of the passed + * objects are using so-called "generic" backend storage. This distinction is + * purely an implementation detail of rb_clone_setup(). People need not be + * aware of this working behind-the-scenes. + * + * @param[out] clone The destination object. + * @param[in] obj The source object. + */ +void rb_copy_generic_ivar(VALUE clone, VALUE obj); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works.")) +/** + * @deprecated Not sure exactly when but at some time, the implementation of + * `Object#clone` stopped using this function. It remained + * untouched for a while, and then @shyouhei realised that they + * are no longer doing the same thing. It seems nobody seriously + * uses this function any longer. Let's just abandon it. + * + * @param[out] clone The destination object. + * @param[in] obj The source object. + */ +static inline void +rb_clone_setup(VALUE clone, VALUE obj) +{ + return; +} + +RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works.")) +/** + * @deprecated Not sure exactly when but at some time, the implementation of + * `Object#dup` stopped using this function. It remained + * untouched for a while, and then @shyouhei realised that they + * are no longer the same thing. It seems nobody seriously uses + * this function any longer. Let's just abandon it. + * + * @param[out] dup The destination object. + * @param[in] obj The source object. + */ +static inline void +rb_dup_setup(VALUE dup, VALUE obj) +{ + return; +} + +#endif /* RBIMPL_NEWOBJ_H */ diff --git a/ruby/include/ruby/internal/rgengc.h b/ruby/include/ruby/internal/rgengc.h new file mode 100644 index 000000000..7ea04442f --- /dev/null +++ b/ruby/include/ruby/internal/rgengc.h @@ -0,0 +1,443 @@ +#ifndef RBIMPL_RGENGC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RGENGC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief RGENGC write-barrier APIs. + * @see Sasada, K., "Gradual write-barrier insertion into a Ruby + * interpreter", in proceedings of the 2019 ACM SIGPLAN + * International Symposium on Memory Management (ISMM 2019), pp + * 115-121, 2019. https://doi.org/10.1145/3315573.3329986 + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/maybe_unused.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#undef USE_RGENGC +#define USE_RGENGC 1 + +/** + * @private + * + * This is a compile-time flag to enable/disable incremental GC feature. It + * has to be set at the time ruby itself compiles. Makes no sense for 3rd + * parties. It is safe for them to set this though; that just doesn't change + * anything. + */ +#ifndef USE_RINCGC +# define USE_RINCGC 1 +#endif + +/** + * @deprecated This macro seems broken. Setting this to anything other than + * zero just doesn't compile. We need to KonMari. + */ +#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT +# define USE_RGENGC_LOGGING_WB_UNPROTECT 0 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RArray. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_ARRAY +# define RGENGC_WB_PROTECTED_ARRAY 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RHash. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_HASH +# define RGENGC_WB_PROTECTED_HASH 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RStruct. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_STRUCT +# define RGENGC_WB_PROTECTED_STRUCT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RString. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_STRING +# define RGENGC_WB_PROTECTED_STRING 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RObject. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_OBJECT +# define RGENGC_WB_PROTECTED_OBJECT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RRegexp. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_REGEXP +# define RGENGC_WB_PROTECTED_REGEXP 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RClass. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_CLASS +# define RGENGC_WB_PROTECTED_CLASS 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RFloat. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_FLOAT +# define RGENGC_WB_PROTECTED_FLOAT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RComplex. It has to be set at the time ruby itself compiles. + * Makes no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_COMPLEX +# define RGENGC_WB_PROTECTED_COMPLEX 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RRational. It has to be set at the time ruby itself compiles. + * Makes no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_RATIONAL +# define RGENGC_WB_PROTECTED_RATIONAL 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RBignum. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_BIGNUM +# define RGENGC_WB_PROTECTED_BIGNUM 1 +#endif + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + * + * @internal + * + * @shyouhei doesn't think anybody uses this right now. + */ +#ifndef RGENGC_WB_PROTECTED_NODE_CREF +# define RGENGC_WB_PROTECTED_NODE_CREF 1 +#endif + +/** + * @defgroup rgengc Write barrier (WB) interfaces: + * + * @note The following core interfaces can be changed in the future. Please + * catch up if you want to insert WB into C-extensions correctly. + * + * @{ + */ + +/** + * Declaration of a "back" pointer. This is a write barrier for new reference + * from "old" generation to "young" generation. It writes `young` into + * `*slot`, which is a pointer inside of `old`. + * + * @param[in] old An old object. + * @param[in] slot A pointer inside of `old`. + * @param[out] young A young object. + */ +#define RB_OBJ_WRITE(old, slot, young) \ + RBIMPL_CAST(rb_obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __FILE__, __LINE__)) + +/** + * Identical to #RB_OBJ_WRITE(), except it doesn't write any values, but only a + * WB declaration. `oldv` is replaced value with `b` (not used in current + * Ruby). + * + * @param[in] old An old object. + * @param[in] oldv An object previously stored inside of `old`. + * @param[out] young A young object. + */ +#define RB_OBJ_WRITTEN(old, oldv, young) \ + RBIMPL_CAST(rb_obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young), __FILE__, __LINE__)) +/** @} */ + +#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW /**< @old{RB_OBJ_PROMOTED_RAW} */ +#define OBJ_PROMOTED RB_OBJ_PROMOTED /**< @old{RB_OBJ_PROMOTED} */ +#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT /**< @old{RB_OBJ_WB_UNPROTECT} */ + +/** + * Asserts that the passed object is not fenced by write barriers. Objects of + * such property do not contribute to generational GCs. They are scanned + * always. + * + * @param[out] x An object that would not be protected by the barrier. + */ +#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) + +/** + * Identical to #RB_OBJ_WB_UNPROTECT(), except it can also assert that the + * given object is of given type. + * + * @param[in] type One of `ARRAY`, `STRING`, etc. + * @param[out] obj An object of `type` that would not be protected. + * + * @internal + * + * @shyouhei doesn't understand why this has to be visible from extensions. + */ +#define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ + (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj) + +/** + * @private + * + * This is an implementation detail of rb_obj_wb_unprotect(). People don't use + * it directly. + */ +#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging + +/** @cond INTERNAL_MACRO */ +#define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW +#define RB_OBJ_PROMOTED RB_OBJ_PROMOTED +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * This is the implementation of #RB_OBJ_WRITE(). People don't use it + * directly. + * + * @param[in] old An object that points to `young`. + * @param[out] young An object that is referenced from `old`. + */ +void rb_gc_writebarrier(VALUE old, VALUE young); + +/** + * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it + * directly. + * + * @param[out] obj An object that does not participate in WB. + */ +void rb_gc_writebarrier_unprotect(VALUE obj); + +#if USE_RGENGC_LOGGING_WB_UNPROTECT +/** + * @private + * + * This is the implementation of #RGENGC_LOGGING_WB_UNPROTECT(). People + * don't use it directly. + * + * @param[in] objptr Don't know why this is a pointer to void but in + * reality this is a pointer to an object that is about + * to be un-protected. + * @param[in] filename Pass C's `__FILE__` here. + * @param[in] line Pass C's `__LINE__` here. + */ +void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); +#endif + +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is the implementation of #RB_OBJ_PROMOTED(). People don't use it + * directly. + * + * @param[in] obj An object to query. + * @retval true The object is "promoted". + * @retval false The object is young. Have not experienced GC at all. + */ +static inline bool +RB_OBJ_PROMOTED_RAW(VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Tests if the object is "promoted" -- that is, whether the object experienced + * one or more GC marks. + * + * @param[in] obj An object to query. + * @retval true The object is "promoted". + * @retval false The object is young. Have not experienced GC at all. + * @note Hello, is anyone actively calling this function? @shyouhei have + * never seen any actual usages outside of the GC implementation + * itself. + */ +static inline bool +RB_OBJ_PROMOTED(VALUE obj) +{ + if (! RB_FL_ABLE(obj)) { + return false; + } + else { + return RB_OBJ_PROMOTED_RAW(obj); + } +} + +/** + * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it + * directly. + * + * @param[out] x An object that does not participate in WB. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return x + */ +static inline VALUE +rb_obj_wb_unprotect( + VALUE x, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#if USE_RGENGC_LOGGING_WB_UNPROTECT + RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line); +#endif + rb_gc_writebarrier_unprotect(x); + return x; +} + +/** + * @private + * + * This is the implementation of #RB_OBJ_WRITTEN(). People don't use it + * directly. + * + * @param[in] a An old object. + * @param[in] oldv An object previously stored inside of `old`. + * @param[out] b A young object. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return a + */ +static inline VALUE +rb_obj_written( + VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + VALUE oldv, + VALUE b, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#if USE_RGENGC_LOGGING_WB_UNPROTECT + RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); +#endif + + if (!RB_SPECIAL_CONST_P(b)) { + rb_gc_writebarrier(a, b); + } + + return a; +} + +/** + * @private + * + * This is the implementation of #RB_OBJ_WRITE(). People don't use it + * directly. + * + * @param[in] a An old object. + * @param[in] slot A pointer inside of `old`. + * @param[out] b A young object. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return a + */ +static inline VALUE +rb_obj_write( + VALUE a, VALUE *slot, VALUE b, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#ifdef RGENGC_LOGGING_WRITE + RGENGC_LOGGING_WRITE(a, slot, b, filename, line); +#endif + + *slot = b; + + rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); + return a; +} + +#endif /* RBIMPL_RGENGC_H */ diff --git a/ruby/include/ruby/internal/scan_args.h b/ruby/include/ruby/internal/scan_args.h new file mode 100644 index 000000000..cf5b18f77 --- /dev/null +++ b/ruby/include/ruby/internal/scan_args.h @@ -0,0 +1,534 @@ +#ifndef RBIMPL_SCAN_ARGS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_SCAN_ARGS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Compile-time static implementation of ::rb_scan_args(). + * + * This is a beast. It statically analyses the argument spec string, and + * expands the assignment of variables into dedicated codes. + */ +#include "ruby/assert.h" +#include "ruby/internal/attr/diagnose_if.h" +#include "ruby/internal/attr/error.h" +#include "ruby/internal/attr/forceinline.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/config.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/intern/array.h" /* rb_ary_new_from_values */ +#include "ruby/internal/intern/error.h" /* rb_error_arity */ +#include "ruby/internal/intern/hash.h" /* rb_hash_dup */ +#include "ruby/internal/intern/proc.h" /* rb_block_proc */ +#include "ruby/internal/iterator.h" /* rb_block_given_p / rb_keyword_given_p */ +#include "ruby/internal/static_assert.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" + +/** + * @name Possible values that you should pass to rb_scan_args_kw(). + * @{ + */ + +/** Same behaviour as rb_scan_args(). */ +#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0 + +/** The final argument should be a hash treated as keywords.*/ +#define RB_SCAN_ARGS_KEYWORDS 1 + +/** + * Treat a final argument as keywords if it is a hash, and not as keywords + * otherwise. + */ +#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3 + +/** @} */ + +/** + * @name Possible values that you should pass to rb_funcallv_kw(). + * @{ + */ + +/** Do not pass keywords. */ +#define RB_NO_KEYWORDS 0 + +/** Pass keywords, final argument should be a hash of keywords. */ +#define RB_PASS_KEYWORDS 1 + +/** + * Pass keywords if current method is called with keywords, useful for argument + * delegation + */ +#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p() + +/** @} */ + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1 + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_NONNULL((2, 3)) +/** + * Retrieves argument from argc and argv to given ::VALUE references according + * to the format string. The format can be described in ABNF as follows: + * + * ``` + * scan-arg-spec := param-arg-spec [keyword-arg-spec] [block-arg-spec] + * + * param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec / + * pre-opt-post-arg-spec + * pre-arg-spec := num-of-leading-mandatory-args + [num-of-optional-args] + * post-arg-spec := sym-for-variable-length-args + * [num-of-trailing-mandatory-args] + * pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args + * num-of-trailing-mandatory-args + * keyword-arg-spec := sym-for-keyword-arg + * block-arg-spec := sym-for-block-arg + * + * num-of-leading-mandatory-args := DIGIT ; The number of leading mandatory + * ; arguments + * num-of-optional-args := DIGIT ; The number of optional arguments + * sym-for-variable-length-args := "*" ; Indicates that variable length + * ; arguments are captured as a ruby + * ; array + * num-of-trailing-mandatory-args := DIGIT ; The number of trailing mandatory + * ; arguments + * sym-for-keyword-arg := ":" ; Indicates that keyword argument + * ; captured as a hash. + * ; If keyword arguments are not + * ; provided, returns nil. + * sym-for-block-arg := "&" ; Indicates that an iterator block + * ; should be captured if given + * ``` + * + * For example, "12" means that the method requires at least one argument, and + * at most receives three (1+2) arguments. So, the format string must be + * followed by three variable references, which are to be assigned to captured + * arguments. For omitted arguments, variables are set to ::RUBY_Qnil. `NULL` + * can be put in place of a variable reference, which means the corresponding + * captured argument(s) should be just dropped. + * + * The number of given arguments, excluding an option hash or iterator block, + * is returned. + * + * @param[in] argc Length of `argv`. + * @param[in] argv Pointer to the arguments to parse. + * @param[in] fmt Format, in the language described above. + * @param[out] ... Variables to fill in. + * @exception rb_eFatal Malformed `fmt`. + * @exception rb_eArgError Arity mismatch. + * @return Actually parsed number of given arguments. + * @post Each values passed to `argv` is filled into the variadic + * arguments, according to the format. + */ +int rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...); + +RBIMPL_ATTR_NONNULL((3, 4)) +/** + * Identical to rb_scan_args(), except it also accepts `kw_splat`. + * + * @param[in] kw_splat How to understand the keyword arguments. + * - RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: Same behaviour as rb_scan_args(). + * - RB_SCAN_ARGS_KEYWORDS: The final argument is a kwarg. + * - RB_SCAN_ARGS_LAST_HASH_KEYWORDS: The final argument is a kwarg, iff it + * is a hash. + * @param[in] argc Length of `argv`. + * @param[in] argv Pointer to the arguments to parse. + * @param[in] fmt Format, in the language described above. + * @param[out] ... Variables to fill in. + * @exception rb_eFatal Malformed `fmt`. + * @exception rb_eArgError Arity mismatch. + * @return Actually parsed number of given arguments. + * @post Each values passed to `argv` is filled into the variadic + * arguments, according to the format. + */ +int rb_scan_args_kw(int kw_splat, int argc, const VALUE *argv, const char *fmt, ...); + +RBIMPL_ATTR_ERROR(("bad scan arg format")) +/** + * @private + * + * This is an implementation detail of rb_scan_args(). People don't use it + * directly. + */ +void rb_scan_args_bad_format(const char*); + +RBIMPL_ATTR_ERROR(("variable argument length doesn't match")) +/** + * @private + * + * This is an implementation detail of rb_scan_args(). People don't use it + * directly. + */ +void rb_scan_args_length_mismatch(const char*,int); + +RBIMPL_SYMBOL_EXPORT_END() + +/** @cond INTERNAL_MACRO */ + +/* If we could use constexpr the following macros could be inline functions + * ... but sadly we cannot. */ + +#define rb_scan_args_isdigit(c) (RBIMPL_CAST((unsigned char)((c)-'0'))<10) + +#define rb_scan_args_count_end(fmt, ofs, vari) \ + ((fmt)[ofs] ? -1 : (vari)) + +#define rb_scan_args_count_block(fmt, ofs, vari) \ + ((fmt)[ofs]!='&' ? \ + rb_scan_args_count_end(fmt, ofs, vari) : \ + rb_scan_args_count_end(fmt, (ofs)+1, (vari)+1)) + +#define rb_scan_args_count_hash(fmt, ofs, vari) \ + ((fmt)[ofs]!=':' ? \ + rb_scan_args_count_block(fmt, ofs, vari) : \ + rb_scan_args_count_block(fmt, (ofs)+1, (vari)+1)) + +#define rb_scan_args_count_trail(fmt, ofs, vari) \ + (!rb_scan_args_isdigit((fmt)[ofs]) ? \ + rb_scan_args_count_hash(fmt, ofs, vari) : \ + rb_scan_args_count_hash(fmt, (ofs)+1, (vari)+((fmt)[ofs]-'0'))) + +#define rb_scan_args_count_var(fmt, ofs, vari) \ + ((fmt)[ofs]!='*' ? \ + rb_scan_args_count_trail(fmt, ofs, vari) : \ + rb_scan_args_count_trail(fmt, (ofs)+1, (vari)+1)) + +#define rb_scan_args_count_opt(fmt, ofs, vari) \ + (!rb_scan_args_isdigit((fmt)[ofs]) ? \ + rb_scan_args_count_var(fmt, ofs, vari) : \ + rb_scan_args_count_var(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) + +#define rb_scan_args_count_lead(fmt, ofs, vari) \ + (!rb_scan_args_isdigit((fmt)[ofs]) ? \ + rb_scan_args_count_var(fmt, ofs, vari) : \ + rb_scan_args_count_opt(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) + +#define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0) + +#if RBIMPL_HAS_ATTRIBUTE(diagnose_if) +# /* Assertions done in the attribute. */ +# define rb_scan_args_verify(fmt, varc) RBIMPL_ASSERT_NOTHING +#else +# /* At one sight it _seems_ the expressions below could be written using +# * static assertions. The reality is no, they don't. Because fmt is a +# * string literal, any operations against fmt cannot produce the "integer +# * constant expression"s, as defined in ISO/IEC 9899:2018 section 6.6 +# * paragraph #6. Static assertions need such integer constant expressions as +# * defined in ISO/IEC 9899:2018 section 6.7.10 paragraph #3. +# * +# * GCC nonetheless constant-folds this into a no-op, though. */ +# define rb_scan_args_verify(fmt, varc) \ + (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \ + rb_scan_args_bad_format(fmt) : \ + sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \ + rb_scan_args_length_mismatch(fmt, varc) : \ + RBIMPL_ASSERT_NOTHING) +#endif + +static inline bool +rb_scan_args_keyword_p(int kw_flag, VALUE last) +{ + switch (kw_flag) { + case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: + return !! rb_keyword_given_p(); + case RB_SCAN_ARGS_KEYWORDS: + return true; + case RB_SCAN_ARGS_LAST_HASH_KEYWORDS: + return RB_TYPE_P(last, T_HASH); + default: + return false; + } +} + +RBIMPL_ATTR_FORCEINLINE() +static bool +rb_scan_args_lead_p(const char *fmt) +{ + return rb_scan_args_isdigit(fmt[0]); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_n_lead(const char *fmt) +{ + return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0); +} + +RBIMPL_ATTR_FORCEINLINE() +static bool +rb_scan_args_opt_p(const char *fmt) +{ + return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1])); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_n_opt(const char *fmt) +{ + return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_var_idx(const char *fmt) +{ + return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2); +} + +RBIMPL_ATTR_FORCEINLINE() +static bool +rb_scan_args_f_var(const char *fmt) +{ + return (fmt[rb_scan_args_var_idx(fmt)]=='*'); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_trail_idx(const char *fmt) +{ + const int idx = rb_scan_args_var_idx(fmt); + return idx+(fmt[idx]=='*'); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_n_trail(const char *fmt) +{ + const int idx = rb_scan_args_trail_idx(fmt); + return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_hash_idx(const char *fmt) +{ + const int idx = rb_scan_args_trail_idx(fmt); + return idx+rb_scan_args_isdigit(fmt[idx]); +} + +RBIMPL_ATTR_FORCEINLINE() +static bool +rb_scan_args_f_hash(const char *fmt) +{ + return (fmt[rb_scan_args_hash_idx(fmt)]==':'); +} + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_block_idx(const char *fmt) +{ + const int idx = rb_scan_args_hash_idx(fmt); + return idx+(fmt[idx]==':'); +} + +RBIMPL_ATTR_FORCEINLINE() +static bool +rb_scan_args_f_block(const char *fmt) +{ + return (fmt[rb_scan_args_block_idx(fmt)]=='&'); +} + +# if 0 +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_end_idx(const char *fmt) +{ + const int idx = rb_scan_args_block_idx(fmt); + return idx+(fmt[idx]=='&'); +} +# endif + +/* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/ +/* https://bugs.llvm.org/show_bug.cgi?id=38095 */ +# define rb_scan_args0(argc, argv, fmt, varc, vars) \ + rb_scan_args_set(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, \ + rb_scan_args_n_lead(fmt), \ + rb_scan_args_n_opt(fmt), \ + rb_scan_args_n_trail(fmt), \ + rb_scan_args_f_var(fmt), \ + rb_scan_args_f_hash(fmt), \ + rb_scan_args_f_block(fmt), \ + (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) +# define rb_scan_args_kw0(kw_flag, argc, argv, fmt, varc, vars) \ + rb_scan_args_set(kw_flag, argc, argv, \ + rb_scan_args_n_lead(fmt), \ + rb_scan_args_n_opt(fmt), \ + rb_scan_args_n_trail(fmt), \ + rb_scan_args_f_var(fmt), \ + rb_scan_args_f_hash(fmt), \ + rb_scan_args_f_block(fmt), \ + (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) + +RBIMPL_ATTR_FORCEINLINE() +static int +rb_scan_args_set(int kw_flag, int argc, const VALUE *argv, + int n_lead, int n_opt, int n_trail, + bool f_var, bool f_hash, bool f_block, + VALUE *vars[], RB_UNUSED_VAR(const char *fmt), RB_UNUSED_VAR(int varc)) + RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) < 0, "bad scan arg format", "error") + RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) != varc, "variable argument length doesn't match", "error") +{ + int i, argi = 0, vari = 0; + VALUE *var, hash = Qnil; +#define rb_scan_args_next_param() vars[vari++] + const int n_mand = n_lead + n_trail; + + /* capture an option hash - phase 1: pop from the argv */ + if (f_hash && argc > 0) { + VALUE last = argv[argc - 1]; + if (rb_scan_args_keyword_p(kw_flag, last)) { + hash = rb_hash_dup(last); + argc--; + } + } + + if (argc < n_mand) { + goto argc_error; + } + + /* capture leading mandatory arguments */ + for (i = 0; i < n_lead; i++) { + var = rb_scan_args_next_param(); + if (var) *var = argv[argi]; + argi++; + } + + /* capture optional arguments */ + for (i = 0; i < n_opt; i++) { + var = rb_scan_args_next_param(); + if (argi < argc - n_trail) { + if (var) *var = argv[argi]; + argi++; + } + else { + if (var) *var = Qnil; + } + } + + /* capture variable length arguments */ + if (f_var) { + int n_var = argc - argi - n_trail; + + var = rb_scan_args_next_param(); + if (0 < n_var) { + if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]); + argi += n_var; + } + else { + if (var) *var = rb_ary_new(); + } + } + + /* capture trailing mandatory arguments */ + for (i = 0; i < n_trail; i++) { + var = rb_scan_args_next_param(); + if (var) *var = argv[argi]; + argi++; + } + + /* capture an option hash - phase 2: assignment */ + if (f_hash) { + var = rb_scan_args_next_param(); + if (var) *var = hash; + } + + /* capture iterator block */ + if (f_block) { + var = rb_scan_args_next_param(); + if (rb_block_given_p()) { + *var = rb_block_proc(); + } + else { + *var = Qnil; + } + } + + if (argi == argc) { + return argc; + } + + argc_error: + rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); + UNREACHABLE_RETURN(-1); +#undef rb_scan_args_next_param +} + +/** @endcond */ + +#if defined(__DOXYGEN__) +# /* don't bother */ + +#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) +# /* skip */ + +#elif ! defined(HAVE_VA_ARGS_MACRO) +# /* skip */ + +#elif ! defined(__OPTIMIZE__) +# /* skip */ + +#elif defined(HAVE___VA_OPT__) +# define rb_scan_args(argc, argvp, fmt, ...) \ + __builtin_choose_expr( \ + __builtin_constant_p(fmt), \ + rb_scan_args0( \ + argc, argvp, fmt, \ + (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ + ((VALUE*[]){__VA_ARGS__})), \ + (rb_scan_args)(argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) +# define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ + __builtin_choose_expr( \ + __builtin_constant_p(fmt), \ + rb_scan_args_kw0( \ + kw_flag, argc, argvp, fmt, \ + (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ + ((VALUE*[]){__VA_ARGS__})), \ + (rb_scan_args_kw)(kw_flag, argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) + +#elif defined(__STRICT_ANSI__) +# /* skip */ + +#elif defined(__GNUC__) +# define rb_scan_args(argc, argvp, fmt, ...) \ + __builtin_choose_expr( \ + __builtin_constant_p(fmt), \ + rb_scan_args0( \ + argc, argvp, fmt, \ + (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ + ((VALUE*[]){__VA_ARGS__})), \ + (rb_scan_args)(argc, argvp, fmt, __VA_ARGS__)) +# define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ + __builtin_choose_expr( \ + __builtin_constant_p(fmt), \ + rb_scan_args_kw0( \ + kw_flag, argc, argvp, fmt, \ + (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ + ((VALUE*[]){__VA_ARGS__})), \ + (rb_scan_args_kw)(kw_flag, argc, argvp, fmt, __VA_ARGS__ /**/)) +#endif + +#endif /* RBIMPL_SCAN_ARGS_H */ diff --git a/ruby/include/ruby/internal/special_consts.h b/ruby/include/ruby/internal/special_consts.h new file mode 100644 index 000000000..38934e4da --- /dev/null +++ b/ruby/include/ruby/internal/special_consts.h @@ -0,0 +1,295 @@ +#ifndef RBIMPL_SPECIAL_CONSTS_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_SPECIAL_CONSTS_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines enum ::ruby_special_consts. + * @see Sasada, K., "A Lightweight Representation of Floating-Point + * Numbers on Ruby Interpreter", in proceedings of 10th JSSST + * SIGPPL Workshop on Programming and Programming Languages + * (PPL2008), pp. 9-16, 2008. + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/constexpr.h" +#include "ruby/internal/attr/enum_extensibility.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" + +/** + * @private + * @warning Do not touch this macro. + * @warning It is an implementation detail. + * @warning The value of this macro must match for ruby itself and all + * extension libraries, otherwise serious memory corruption shall + * occur. + */ +#if defined(USE_FLONUM) +# /* Take that. */ +#elif SIZEOF_VALUE >= SIZEOF_DOUBLE +# define USE_FLONUM 1 +#else +# define USE_FLONUM 0 +#endif + +/** This is an old name of #RB_TEST. Not sure which name is preferred. */ +#define RTEST RB_TEST + +#define FIXNUM_P RB_FIXNUM_P /**< @old{RB_FIXNUM_P} */ +#define IMMEDIATE_P RB_IMMEDIATE_P /**< @old{RB_IMMEDIATE_P} */ +#define NIL_P RB_NIL_P /**< @old{RB_NIL_P} */ +#define SPECIAL_CONST_P RB_SPECIAL_CONST_P /**< @old{RB_SPECIAL_CONST_P} */ +#define STATIC_SYM_P RB_STATIC_SYM_P /**< @old{RB_STATIC_SYM_P} */ + +#define Qfalse RUBY_Qfalse /**< @old{RUBY_Qfalse} */ +#define Qnil RUBY_Qnil /**< @old{RUBY_Qnil} */ +#define Qtrue RUBY_Qtrue /**< @old{RUBY_Qtrue} */ +#define Qundef RUBY_Qundef /**< @old{RUBY_Qundef} */ + +#define FIXNUM_FLAG RUBY_FIXNUM_FLAG /**< @old{RUBY_FIXNUM_FLAG} */ +#define FLONUM_FLAG RUBY_FLONUM_FLAG /**< @old{RUBY_FLONUM_FLAG} */ +#define FLONUM_MASK RUBY_FLONUM_MASK /**< @old{RUBY_FLONUM_MASK} */ +#define FLONUM_P RB_FLONUM_P /**< @old{RB_FLONUM_P} */ +#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK /**< @old{RUBY_IMMEDIATE_MASK} */ +#define SYMBOL_FLAG RUBY_SYMBOL_FLAG /**< @old{RUBY_SYMBOL_FLAG} */ + +/** @cond INTERNAL_MACRO */ +#define RB_FIXNUM_P RB_FIXNUM_P +#define RB_FLONUM_P RB_FLONUM_P +#define RB_IMMEDIATE_P RB_IMMEDIATE_P +#define RB_NIL_P RB_NIL_P +#define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P +#define RB_STATIC_SYM_P RB_STATIC_SYM_P +#define RB_TEST RB_TEST +/** @endcond */ + +/** special constants - i.e. non-zero and non-fixnum constants */ +enum +RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) +ruby_special_consts { +#if defined(__DOXYGEN__) + RUBY_Qfalse, /**< @see ::rb_cFalseClass */ + RUBY_Qtrue, /**< @see ::rb_cTrueClass */ + RUBY_Qnil, /**< @see ::rb_cNilClass */ + RUBY_Qundef, /**< Represents so-called undef. */ + RUBY_IMMEDIATE_MASK, /**< Bit mask detecting special consts. */ + RUBY_FIXNUM_FLAG, /**< Flag to denote a fixnum. */ + RUBY_FLONUM_MASK, /**< Bit mask detecting a flonum. */ + RUBY_FLONUM_FLAG, /**< Flag to denote a flonum. */ + RUBY_SYMBOL_FLAG, /**< Flag to denote a static symbol. */ +#elif USE_FLONUM + RUBY_Qfalse = 0x00, /* ...0000 0000 */ + RUBY_Qtrue = 0x14, /* ...0001 0100 */ + RUBY_Qnil = 0x08, /* ...0000 1000 */ + RUBY_Qundef = 0x34, /* ...0011 0100 */ + RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */ + RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ + RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */ + RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */ + RUBY_SYMBOL_FLAG = 0x0c, /* ...xxxx 1100 */ +#else + RUBY_Qfalse = 0x00, /* ...0000 0000 */ + RUBY_Qtrue = 0x02, /* ...0000 0010 */ + RUBY_Qnil = 0x04, /* ...0000 0100 */ + RUBY_Qundef = 0x06, /* ...0000 0110 */ + RUBY_IMMEDIATE_MASK = 0x03, /* ...0000 0011 */ + RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ + RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */ + RUBY_FLONUM_FLAG = 0x02, /* ...0000 0010 */ + RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */ +#endif + + RUBY_SPECIAL_SHIFT = 8 /**< Least significant 8 bits are reserved. */ +}; + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Emulates Ruby's "if" statement. + * + * @param[in] obj An arbitrary ruby object. + * @retval false `obj` is either ::RUBY_Qfalse or ::RUBY_Qnil. + * @retval true Anything else. + * + * @internal + * + * It HAS to be `__attribute__((const))` in order for clang to properly deduce + * `__builtin_assume()`. + */ +static inline bool +RB_TEST(VALUE obj) +{ + /* + * Qfalse: ....0000 0000 + * Qnil: ....0000 1000 + * ~Qnil: ....1111 0111 + * v ....xxxx xxxx + * ---------------------------- + * RTEST(v) ....xxxx 0xxx + * + * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil). + */ + return obj & ~RUBY_Qnil; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is nil. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is ::RUBY_Qnil. + * @retval false Anything else. + */ +static inline bool +RB_NIL_P(VALUE obj) +{ + return obj == RUBY_Qnil; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is a so-called Fixnum. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is a Fixnum. + * @retval false Anything else. + * @note Fixnum was a thing in the 20th century, but it is rather an + * implementation detail today. + */ +static inline bool +RB_FIXNUM_P(VALUE obj) +{ + return obj & RUBY_FIXNUM_FLAG; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX14) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is a static symbol. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is a static symbol + * @retval false Anything else. + * @see RB_DYNAMIC_SYM_P() + * @see RB_SYMBOL_P() + * @note These days there are static and dynamic symbols, just like we + * once had Fixnum/Bignum back in the old days. + */ +static inline bool +RB_STATIC_SYM_P(VALUE obj) +{ + RBIMPL_ATTR_CONSTEXPR(CXX14) + const VALUE mask = ~(RBIMPL_VALUE_FULL << RUBY_SPECIAL_SHIFT); + return (obj & mask) == RUBY_SYMBOL_FLAG; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is a so-called Flonum. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is a Flonum. + * @retval false Anything else. + * @see RB_FLOAT_TYPE_P() + * @note These days there are Flonums and non-Flonum floats, just like we + * once had Fixnum/Bignum back in the old days. + */ +static inline bool +RB_FLONUM_P(VALUE obj) +{ +#if USE_FLONUM + return (obj & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG; +#else + return false; +#endif +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is an immediate i.e. an object which has no + * corresponding storage inside of the object space. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is a Flonum. + * @retval false Anything else. + * @see RB_FLOAT_TYPE_P() + * @note The concept of "immediate" is purely C specific. + */ +static inline bool +RB_IMMEDIATE_P(VALUE obj) +{ + return obj & RUBY_IMMEDIATE_MASK; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is of enum ::ruby_special_consts. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is a special constant. + * @retval false Anything else. + */ +static inline bool +RB_SPECIAL_CONST_P(VALUE obj) +{ + return RB_IMMEDIATE_P(obj) || ! RB_TEST(obj); +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +/** + * Identical to RB_SPECIAL_CONST_P, except it returns a ::VALUE. + * + * @param[in] obj An arbitrary ruby object. + * @retval RUBY_Qtrue `obj` is a special constant. + * @retval RUBY_Qfalse Anything else. + * + * @internal + * + * This function is to mimic old rb_special_const_p macro but have anyone + * actually used its return value? Wasn't it just something no one needed? + */ +static inline VALUE +rb_special_const_p(VALUE obj) +{ + return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue; +} + +/** + * @cond INTERNAL_MACRO + * See [ruby-dev:27513] for the following macros. + */ +#define RUBY_Qfalse RBIMPL_CAST((VALUE)RUBY_Qfalse) +#define RUBY_Qtrue RBIMPL_CAST((VALUE)RUBY_Qtrue) +#define RUBY_Qnil RBIMPL_CAST((VALUE)RUBY_Qnil) +#define RUBY_Qundef RBIMPL_CAST((VALUE)RUBY_Qundef) +/** @endcond */ + +#endif /* RBIMPL_SPECIAL_CONSTS_H */ diff --git a/ruby/include/ruby/internal/static_assert.h b/ruby/include/ruby/internal/static_assert.h new file mode 100644 index 000000000..594c2b291 --- /dev/null +++ b/ruby/include/ruby/internal/static_assert.h @@ -0,0 +1,77 @@ +#ifndef RBIMPL_STATIC_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_STATIC_ASSERT_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_STATIC_ASSERT. + */ +#include +#include "ruby/internal/has/extension.h" +#include "ruby/internal/compiler_since.h" + +/** @cond INTERNAL_MACRO */ +#if defined(__cplusplus) && defined(__cpp_static_assert) +# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ +# define RBIMPL_STATIC_ASSERT0 static_assert + +#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +# define RBIMPL_STATIC_ASSERT0 static_assert + +#elif defined(__INTEL_CXX11_MODE__) +# define RBIMPL_STATIC_ASSERT0 static_assert + +#elif defined(__cplusplus) && __cplusplus >= 201103L +# define RBIMPL_STATIC_ASSERT0 static_assert + +#elif defined(__cplusplus) && RBIMPL_HAS_EXTENSION(cxx_static_assert) +# define RBIMPL_STATIC_ASSERT0 __extension__ static_assert + +#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ +# define RBIMPL_STATIC_ASSERT0 __extension__ static_assert + +#elif defined(__STDC_VERSION__) && RBIMPL_HAS_EXTENSION(c_static_assert) +# define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert + +#elif defined(__STDC_VERSION__) && RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) +# define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert + +#elif defined(static_assert) +# /* Take definition */ +# define RBIMPL_STATIC_ASSERT0 static_assert +#endif +/** @endcond */ + +/** + * @brief Wraps (or simulates) `static_assert` + * @param name Valid C/C++ identifier, describing the assertion. + * @param expr Expression to assert. + * @note `name` shall not be a string literal. + */ +#if defined(__DOXYGEN__) +# define RBIMPL_STATIC_ASSERT static_assert + +#elif defined(RBIMPL_STATIC_ASSERT0) +# define RBIMPL_STATIC_ASSERT(name, expr) \ + RBIMPL_STATIC_ASSERT0(expr, # name ": " # expr) + +#else +# define RBIMPL_STATIC_ASSERT(name, expr) \ + typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] +#endif + +#endif /* RBIMPL_STATIC_ASSERT_H */ diff --git a/ruby/include/ruby/internal/stdalign.h b/ruby/include/ruby/internal/stdalign.h new file mode 100644 index 000000000..ec68f6a88 --- /dev/null +++ b/ruby/include/ruby/internal/stdalign.h @@ -0,0 +1,135 @@ +#ifndef RBIMPL_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_STDALIGN_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ALIGNAS / #RBIMPL_ALIGNOF + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#include "ruby/internal/compiler_is.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/declspec_attribute.h" +#include "ruby/internal/has/feature.h" + +/** + * Wraps (or simulates) `alignas`. This is C++11's `alignas` and is _different_ + * from C11 `_Alignas`. For instance, + * + * ```CXX + * typedef struct alignas(128) foo { int foo } foo; + * ``` + * + * is a valid C++ while + * + * ```C + * typedef struct _Alignas(128) foo { int foo } foo; + * ``` + * + * is an invalid C because: + * + * - You cannot `struct _Alignas`. + * - A `typedef` cannot have alignments. + */ +#if defined(__cplusplus) && RBIMPL_HAS_FEATURE(cxx_alignas) +# define RBIMPL_ALIGNAS alignas + +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +# define RBIMPL_ALIGNAS alignas + +#elif defined(__INTEL_CXX11_MODE__) +# define RBIMPL_ALIGNAS alignas + +#elif defined(__GXX_EXPERIMENTAL_CXX0X__) +# define RBIMPL_ALIGNAS alignas + +#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(align) +# define RBIMPL_ALIGNAS(_) __declspec(align(_)) + +#elif RBIMPL_HAS_ATTRIBUTE(aligned) +# define RBIMPL_ALIGNAS(_) __attribute__((__aligned__(_))) + +#else +# define RBIMPL_ALIGNAS(_) /* void */ +#endif + +/** + * Wraps (or simulates) `alignof`. + * + * We want C11's `_Alignof`. However in spite of its clear language, compilers + * (including GCC and clang) tend to have buggy implementations. We have to + * avoid such things to resort to our own version. + * + * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 + * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 + * @see https://bugs.llvm.org/show_bug.cgi?id=26547 + */ +#if defined(__DOXYGEN__) +# define RBIMPL_ALIGNOF alignof +#elif defined(__cplusplus) +# /* C++11 `alignof()` can be buggy. */ +# /* see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 */ +# /* But don't worry, we can use templates. */ +# define RBIMPL_ALIGNOF(T) (static_cast(ruby::rbimpl_alignof::value)) + +namespace ruby { +template +struct rbimpl_alignof { + typedef struct { + char _; + T t; + } type; + + enum { + value = offsetof(type, t) + }; +}; +} + +#elif RBIMPL_COMPILER_IS(MSVC) +# /* Windows have no alignment glitch.*/ +# define RBIMPL_ALIGNOF __alignof + +#elif defined(HAVE__ALIGNOF) +# /* Autoconf detected availability of a sane `_Alignof()`. */ +# define RBIMPL_ALIGNOF(T) RB_GNUC_EXTENSION(_Alignof(T)) + +#else +# /* :BEWARE: This is the last resort. If your compiler somehow supports +# * querying the alignment of a type, you definitely should use that instead. +# * There are 2 known pitfalls for this fallback implementation: +# * +# * First, it is either an undefined behaviour (C) or an explicit error (C++) +# * to define a struct inside of `offsetof`. C compilers tend to accept such +# * things, but AFAIK C++ has no room to allow. +# * +# * Second, there exist T such that `struct { char _; T t; }` is invalid. A +# * known example is when T is a struct with a flexible array member. Such +# * struct cannot be enclosed into another one. +# */ +# /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2083.htm */ +# /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm */ +# define RBIMPL_ALIGNOF(T) offsetof(struct { char _; T t; }, t) + +#endif + +#endif /* RBIMPL_STDALIGN_H */ diff --git a/ruby/include/ruby/internal/stdbool.h b/ruby/include/ruby/internal/stdbool.h new file mode 100644 index 000000000..b15321cb0 --- /dev/null +++ b/ruby/include/ruby/internal/stdbool.h @@ -0,0 +1,51 @@ +#ifndef RBIMPL_STDBOOL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_STDBOOL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief C99 shim for + */ +#include "ruby/internal/config.h" + +#if defined(__bool_true_false_are_defined) +# /* Take that. */ + +#elif defined(__cplusplus) +# /* bool is a keyword in C++. */ +# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) +# include +# endif +# +# ifndef __bool_true_false_are_defined +# define __bool_true_false_are_defined +# endif + +#elif defined(HAVE_STDBOOL_H) +# /* Take stdbool.h definition. */ +# include + +#else +typedef unsigned char _Bool; +# /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ +# define bool _Bool +# define true ((_Bool)+1) +# define false ((_Bool)+0) +# define __bool_true_false_are_defined +#endif + +#endif /* RBIMPL_STDBOOL_H */ diff --git a/ruby/include/ruby/internal/symbol.h b/ruby/include/ruby/internal/symbol.h new file mode 100644 index 000000000..869a31115 --- /dev/null +++ b/ruby/include/ruby/internal/symbol.h @@ -0,0 +1,332 @@ +#ifndef RBIMPL_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_SYMBOL_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #rb_intern + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/constant_p.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/value.h" + +#define RB_ID2SYM rb_id2sym /**< @alias{rb_id2sym} */ +#define RB_SYM2ID rb_sym2id /**< @alias{rb_sym2id} */ +#define ID2SYM RB_ID2SYM /**< @old{RB_ID2SYM} */ +#define SYM2ID RB_SYM2ID /**< @old{RB_SYM2ID} */ +#define CONST_ID_CACHE RUBY_CONST_ID_CACHE /**< @old{RUBY_CONST_ID_CACHE} */ +#define CONST_ID RUBY_CONST_ID /**< @old{RUBY_CONST_ID} */ + +/** @cond INTERNAL_MACRO */ +#define rb_intern_const rb_intern_const +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Converts an instance of ::rb_cSymbol into an ::ID. + * + * @param[in] obj An instance of ::rb_cSymbol. + * @exception rb_eTypeError `obj` is not an instance of ::rb_cSymbol. + * @return An ::ID of the identical symbol. + */ +ID rb_sym2id(VALUE obj); + +/** + * Allocates an instance of ::rb_cSymbol that has the given id. + * + * @param[in] id An id. + * @retval RUBY_Qfalse No such id ever existed in the history. + * @retval Otherwise An allocated ::rb_cSymbol instance. + */ +VALUE rb_id2sym(ID id); + +RBIMPL_ATTR_NONNULL(()) +/** + * Finds or creates a symbol of the given name. + * + * @param[in] name The name of the id. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given name. + * @note These days Ruby internally has two kinds of symbols (static / + * dynamic). Symbols created using this function would become a + * static one; i.e. would never be garbage collected. It is up to + * you to avoid memory leaks. Think twice before using it. + */ +ID rb_intern(const char *name); + +/** + * Identical to rb_intern(), except it additionally takes the length of the + * string. This way you can have a symbol that contains NUL characters. + * + * @param[in] name The name of the id. + * @param[in] len Length of `name`. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given name. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become static ones; i.e. would never be garbage collected. It + * is up to you to avoid memory leaks. Think twice before using + * it. + */ +ID rb_intern2(const char *name, long len); + +/** + * Identical to rb_intern(), except it takes an instance of ::rb_cString. + * + * @param[in] str The name of the id. + * @pre `str` must either be an instance of ::rb_cSymbol, or an instance + * of ::rb_cString, or responds to `#to_str` method. + * @exception rb_eTypeError Can't convert `str` into ::rb_cString. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given str. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become static ones; i.e. would never be garbage collected. It + * is up to you to avoid memory leaks. Think twice before using + * it. + */ +ID rb_intern_str(VALUE str); + +/** + * Retrieves the name mapped to the given id. + * + * @param[in] id An id to query. + * @retval NULL No such id ever existed in the history. + * @retval otherwise A name that the id represents. + * @note The return value is managed by the interpreter. Don't pass it + * to free(). + */ +const char *rb_id2name(ID id); + +RBIMPL_ATTR_NONNULL(()) +/** + * Detects if the given name is already interned or not. It first tries to + * convert the argument to an instance of ::rb_cString if it is neither an + * instance of ::rb_cString nor ::rb_cSymbol. The conversion result is written + * back to the variable. Then queries if that name was already interned + * before. If found it returns such id, otherwise zero. + * + * We eventually introduced this API to avoid inadvertent symbol pin-down. + * Before, there was no way to know if an ID was already interned or not + * without actually creating one (== leaking memory). By using this API you + * can avoid such situations: + * + * ```CXX + * bool does_interning_this_leak_memory(VALUE obj) + * { + * auto tmp = obj; + * if (auto id = rb_check_id(&tmp); id) { + * return false; + * } + * else { + * return true; // Let GC sweep tmp if necessary. + * } + * } + * ``` + * + * @param[in,out] namep A pointer to a name to query. + * @pre The object referred by `*namep` must either be an instance + * of ::rb_cSymbol, or an instance of ::rb_cString, or responds + * to `#to_str` method. + * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. + * @exception rb_eEncodingError Given string is non-ASCII. + * @retval 0 No such id ever existed in the history. + * @retval otherwise The id that represents the given name. + * @post The object that `*namep` points to is a converted result + * object, which is always an instance of either ::rb_cSymbol + * or ::rb_cString. + * @see https://bugs.ruby-lang.org/issues/5072 + * + * @internal + * + * @shyouhei doesn't know why this has to raise rb_eEncodingError. + */ +ID rb_check_id(volatile VALUE *namep); + +/** + * @copydoc rb_intern_str() + * + * @internal + * + * :FIXME: Can anyone tell us what is the difference between this one and + * rb_intern_str()? As far as @shyouhei reads the implementation it seems what + * rb_to_id() does is is just waste some CPU time, then call rb_intern_str(). + * He hopes he is wrong. + */ +ID rb_to_id(VALUE str); + +/** + * Identical to rb_id2name(), except it returns a Ruby's String instead of C's. + * + * @param[in] id An id to query. + * @retval RUBY_Qfalse No such id ever existed in the history. + * @retval otherwise An instance of ::rb_cString with the name of id. + * + * @internal + * + * In reality "rb_id2str() is identical to rb_id2name() except it returns Ruby + * string" is just describing things upside down; truth is `rb_id2name(foo)` is + * a shorthand of `RSTRING_PTR(rb_id2str(foo))`. + */ +VALUE rb_id2str(ID id); + +/** + * Identical to rb_id2str(), except it takes an instance of ::rb_cSymbol rather + * than an ::ID. + * + * @param[in] id An id to query. + * @retval RUBY_Qfalse No such id ever existed in the history. + * @retval otherwise An instance of ::rb_cString with the name of id. + */ +VALUE rb_sym2str(VALUE id); + +/** + * Identical to rb_intern_str(), except it generates a dynamic symbol if + * necessary. + * + * @param[in] name The name of the id. + * @pre `name` must either be an instance of ::rb_cSymbol, or an + * instance of ::rb_cString, or responds to `#to_str` method. + * @exception rb_eTypeError Can't convert `name` into ::rb_cString. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given name. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become dynamic ones; i.e. would be garbage collected. It could + * be safer for you to use it than alternatives, when applicable. + */ +VALUE rb_to_symbol(VALUE name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_check_id(), except it returns an instance of ::rb_cSymbol + * instead. + * + * @param[in,out] namep A pointer to a name to query. + * @pre The object referred by `*namep` must either be an instance + * of ::rb_cSymbol, or an instance of ::rb_cString, or responds + * to `#to_str` method. + * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. + * @exception rb_eEncodingError Given string is non-ASCII. + * @retval RUBY_Qnil No such id ever existed in the history. + * @retval otherwise The id that represents the given name. + * @post The object that `*namep` points to is a converted result + * object, which is always an instance of either ::rb_cSymbol + * or ::rb_cString. + * @see https://bugs.ruby-lang.org/issues/5072 + * + * @internal + * + * @shyouhei doesn't know why this has to raise rb_eEncodingError. + */ +VALUE rb_check_symbol(volatile VALUE *namep); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_NONNULL(()) +/** + * This is a "tiny optimisation" over rb_intern(). If you pass a string + * _literal_, and if your C compiler can special-case strlen of such literal to + * strength-reduce into an integer constant expression, then this inline + * function can precalc a part of conversion. + * + * @note This function also works happily for non-constant strings. Why + * bother then? Just apply liberally to everything. + * @note But #rb_intern() could be faster on compilers with statement + * expressions, because they can cache the created ::ID. + * @param[in] str The name of the id. + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given str. + * @note These days Ruby internally has two kinds of symbols (static / + * dynamic). Symbols created using this function would become a + * static one; i.e. would never be garbage collected. It is up to + * you to avoid memory leaks. Think twice before using it. + */ +static inline ID +rb_intern_const(const char *str) +{ + size_t len = strlen(str); + return rb_intern2(str, RBIMPL_CAST((long)len)); +} + +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * This is an implementation detail of #rb_intern(). Just don't use it. + */ +static inline ID +rbimpl_intern_const(ID *ptr, const char *str) +{ + while (! *ptr) { + *ptr = rb_intern_const(str); + } + + return *ptr; +} + +/** + * Old implementation detail of rb_intern(). + * @deprecated Does anyone use it? Preserved for backward compat. + */ +#define RUBY_CONST_ID_CACHE(result, str) \ + { \ + static ID rb_intern_id_cache; \ + rbimpl_intern_const(&rb_intern_id_cache, (str)); \ + result rb_intern_id_cache; \ + } + +/** + * Old implementation detail of rb_intern(). + * @deprecated Does anyone use it? Preserved for backward compat. + */ +#define RUBY_CONST_ID(var, str) \ + do { \ + static ID rbimpl_id; \ + (var) = rbimpl_intern_const(&rbimpl_id, (str)); \ + } while (0) + +#if defined(HAVE_STMT_AND_DECL_IN_EXPR) +/* __builtin_constant_p and statement expression is available + * since gcc-2.7.2.3 at least. */ +#define rb_intern(str) \ + (RBIMPL_CONSTANT_P(str) ? \ + __extension__ ({ \ + static ID rbimpl_id; \ + rbimpl_intern_const(&rbimpl_id, (str)); \ + }) : \ + (rb_intern)(str)) +#endif + +#endif /* RBIMPL_SYMBOL_H */ diff --git a/ruby/include/ruby/internal/value.h b/ruby/include/ruby/internal/value.h new file mode 100644 index 000000000..805cd8351 --- /dev/null +++ b/ruby/include/ruby/internal/value.h @@ -0,0 +1,133 @@ +#ifndef RBIMPL_VALUE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_VALUE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines ::VALUE and ::ID. + */ +#include "ruby/internal/static_assert.h" +#include "ruby/backward/2/long_long.h" +#include "ruby/backward/2/limits.h" + +#if defined(__DOXYGEN__) + +/** + * Type that represents a Ruby object. It is an unsigned integer of some kind, + * depending on platforms. + * + * ```CXX + * VALUE value = rb_eval_string("ARGF.readlines.map.with_index"); + * ``` + * + * @warning ::VALUE is not a pointer. + * @warning ::VALUE can be wider than `long`. + */ +typedef uintptr_t VALUE; + +/** + * Type that represents a Ruby identifier such as a variable name. + * + * ```CXX + * ID method = rb_intern("method"); + * VALUE result = rb_funcall(obj, method, 0); + * ``` + * + * @note ::rb_cSymbol is a Ruby-level data type for the same thing. + */ +typedef uintptr_t ID; + +/** + * A signed integer type that has the same width with ::VALUE. + * + * @internal + * + * @shyouhei wonders: is it guaranteed that `uintptr_t` and `intptr_t` are the + * same width? As far as I read ISO/IEC 9899:2018 section 7.20.1.4 paragraph 1 + * no such description is given... or defined elsewhere? + */ +typedef intptr_t SIGNED_VALUE; + +/** + * Identical to `sizeof(VALUE)`, except it is a macro that can also be used + * inside of preprocessor directives such as `#if`. Handy on occasions. + */ +#define SIZEOF_VALUE SIZEOF_UINTPTR_T + +/** + * @private + * + * A compile-time constant of type ::VALUE whose value is 0. + */ +#define RBIMPL_VALUE_NULL UINTPTR_C(0) + +/** + * @private + * + * A compile-time constant of type ::VALUE whose value is 1. + */ +#define RBIMPL_VALUE_ONE UINTPTR_C(1) + +/** + * @private + * + * Maximum possible value that a ::VALUE can take. + */ +#define RBIMPL_VALUE_FULL UINTPTR_MAX + +#elif defined HAVE_UINTPTR_T && 0 +typedef uintptr_t VALUE; +typedef uintptr_t ID; +# define SIGNED_VALUE intptr_t +# define SIZEOF_VALUE SIZEOF_UINTPTR_T +# undef PRI_VALUE_PREFIX +# define RBIMPL_VALUE_NULL UINTPTR_C(0) +# define RBIMPL_VALUE_ONE UINTPTR_C(1) +# define RBIMPL_VALUE_FULL UINTPTR_MAX + +#elif SIZEOF_LONG == SIZEOF_VOIDP +typedef unsigned long VALUE; +typedef unsigned long ID; +# define SIGNED_VALUE long +# define SIZEOF_VALUE SIZEOF_LONG +# define PRI_VALUE_PREFIX "l" +# define RBIMPL_VALUE_NULL 0UL +# define RBIMPL_VALUE_ONE 1UL +# define RBIMPL_VALUE_FULL ULONG_MAX + +#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP +typedef unsigned LONG_LONG VALUE; +typedef unsigned LONG_LONG ID; +# define SIGNED_VALUE LONG_LONG +# define LONG_LONG_VALUE 1 +# define SIZEOF_VALUE SIZEOF_LONG_LONG +# define PRI_VALUE_PREFIX PRI_LL_PREFIX +# define RBIMPL_VALUE_NULL 0ULL +# define RBIMPL_VALUE_ONE 1ULL +# define RBIMPL_VALUE_FULL ULLONG_MAX + +#else +# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- +#endif + +/** @cond INTERNAL_MACRO */ +RBIMPL_STATIC_ASSERT(sizeof_int, SIZEOF_INT == sizeof(int)); +RBIMPL_STATIC_ASSERT(sizeof_long, SIZEOF_LONG == sizeof(long)); +RBIMPL_STATIC_ASSERT(sizeof_long_long, SIZEOF_LONG_LONG == sizeof(LONG_LONG)); +RBIMPL_STATIC_ASSERT(sizeof_voidp, SIZEOF_VOIDP == sizeof(void *)); +/** @endcond */ +#endif /* RBIMPL_VALUE_H */ diff --git a/ruby/include/ruby/internal/value_type.h b/ruby/include/ruby/internal/value_type.h new file mode 100644 index 000000000..977f60a00 --- /dev/null +++ b/ruby/include/ruby/internal/value_type.h @@ -0,0 +1,449 @@ +#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_VALUE_TYPE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines enum ::ruby_value_type. + */ +#include "ruby/internal/assume.h" +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/enum_extensibility.h" +#include "ruby/internal/attr/forceinline.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/constant_p.h" +#include "ruby/internal/core/rbasic.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/error.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +#if defined(T_DATA) +/* + * :!BEWARE!: (Recent?) Solaris' have conflicting definition of + * T_DATA. Let us stop here. Please have a workaround like this: + * + * ```C + * #include // <- Include this one first. + * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever. + * #include // <- OS-provided T_DATA introduced. + * ``` + * + * See also [ruby-core:4261] + */ +# error Bail out due to conflicting definition of T_DATA. +#endif + +#define T_ARRAY RUBY_T_ARRAY /**< @old{RUBY_T_ARRAY} */ +#define T_BIGNUM RUBY_T_BIGNUM /**< @old{RUBY_T_BIGNUM} */ +#define T_CLASS RUBY_T_CLASS /**< @old{RUBY_T_CLASS} */ +#define T_COMPLEX RUBY_T_COMPLEX /**< @old{RUBY_T_COMPLEX} */ +#define T_DATA RUBY_T_DATA /**< @old{RUBY_T_DATA} */ +#define T_FALSE RUBY_T_FALSE /**< @old{RUBY_T_FALSE} */ +#define T_FILE RUBY_T_FILE /**< @old{RUBY_T_FILE} */ +#define T_FIXNUM RUBY_T_FIXNUM /**< @old{RUBY_T_FIXNUM} */ +#define T_FLOAT RUBY_T_FLOAT /**< @old{RUBY_T_FLOAT} */ +#define T_HASH RUBY_T_HASH /**< @old{RUBY_T_HASH} */ +#define T_ICLASS RUBY_T_ICLASS /**< @old{RUBY_T_ICLASS} */ +#define T_IMEMO RUBY_T_IMEMO /**< @old{RUBY_T_IMEMO} */ +#define T_MASK RUBY_T_MASK /**< @old{RUBY_T_MASK} */ +#define T_MATCH RUBY_T_MATCH /**< @old{RUBY_T_MATCH} */ +#define T_MODULE RUBY_T_MODULE /**< @old{RUBY_T_MODULE} */ +#define T_MOVED RUBY_T_MOVED /**< @old{RUBY_T_MOVED} */ +#define T_NIL RUBY_T_NIL /**< @old{RUBY_T_NIL} */ +#define T_NODE RUBY_T_NODE /**< @old{RUBY_T_NODE} */ +#define T_NONE RUBY_T_NONE /**< @old{RUBY_T_NONE} */ +#define T_OBJECT RUBY_T_OBJECT /**< @old{RUBY_T_OBJECT} */ +#define T_RATIONAL RUBY_T_RATIONAL /**< @old{RUBY_T_RATIONAL} */ +#define T_REGEXP RUBY_T_REGEXP /**< @old{RUBY_T_REGEXP} */ +#define T_STRING RUBY_T_STRING /**< @old{RUBY_T_STRING} */ +#define T_STRUCT RUBY_T_STRUCT /**< @old{RUBY_T_STRUCT} */ +#define T_SYMBOL RUBY_T_SYMBOL /**< @old{RUBY_T_SYMBOL} */ +#define T_TRUE RUBY_T_TRUE /**< @old{RUBY_T_TRUE} */ +#define T_UNDEF RUBY_T_UNDEF /**< @old{RUBY_T_UNDEF} */ +#define T_ZOMBIE RUBY_T_ZOMBIE /**< @old{RUBY_T_ZOMBIE} */ + +#define BUILTIN_TYPE RB_BUILTIN_TYPE /**< @old{RB_BUILTIN_TYPE} */ +#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P /**< @old{RB_DYNAMIC_SYM_P} */ +#define RB_INTEGER_TYPE_P rb_integer_type_p /**< @old{rb_integer_type_p} */ +#define SYMBOL_P RB_SYMBOL_P /**< @old{RB_SYMBOL_P} */ +#define rb_type_p RB_TYPE_P /**< @alias{RB_TYPE_P} */ + +/** @cond INTERNAL_MACRO */ +#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE +#define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P +#define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P +#define RB_SYMBOL_P RB_SYMBOL_P +#define RB_TYPE_P RB_TYPE_P +#define Check_Type Check_Type + +#if !RUBY_DEBUG +# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t))) +#else +# define RBIMPL_ASSERT_TYPE Check_Type +#endif +/** @endcond */ + +/** @old{rb_type} */ +#define TYPE(_) RBIMPL_CAST((int)rb_type(_)) + +/** C-level type of an object. */ +enum +RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) +ruby_value_type { + RUBY_T_NONE = 0x00, /**< Non-object (swept etc.) */ + + RUBY_T_OBJECT = 0x01, /**< @see struct ::RObject */ + RUBY_T_CLASS = 0x02, /**< @see struct ::RClass and ::rb_cClass */ + RUBY_T_MODULE = 0x03, /**< @see struct ::RClass and ::rb_cModule */ + RUBY_T_FLOAT = 0x04, /**< @see struct ::RFloat */ + RUBY_T_STRING = 0x05, /**< @see struct ::RString */ + RUBY_T_REGEXP = 0x06, /**< @see struct ::RRegexp */ + RUBY_T_ARRAY = 0x07, /**< @see struct ::RArray */ + RUBY_T_HASH = 0x08, /**< @see struct ::RHash */ + RUBY_T_STRUCT = 0x09, /**< @see struct ::RStruct */ + RUBY_T_BIGNUM = 0x0a, /**< @see struct ::RBignum */ + RUBY_T_FILE = 0x0b, /**< @see struct ::RFile */ + RUBY_T_DATA = 0x0c, /**< @see struct ::RTypedData */ + RUBY_T_MATCH = 0x0d, /**< @see struct ::RMatch */ + RUBY_T_COMPLEX = 0x0e, /**< @see struct ::RComplex */ + RUBY_T_RATIONAL = 0x0f, /**< @see struct ::RRational */ + + RUBY_T_NIL = 0x11, /**< @see ::RUBY_Qnil */ + RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qfalse */ + RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qtrue */ + RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */ + RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */ + RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */ + + RUBY_T_IMEMO = 0x1a, /**< @see struct ::RIMemo */ + RUBY_T_NODE = 0x1b, /**< @see struct ::RNode */ + RUBY_T_ICLASS = 0x1c, /**< Hidden classes known as IClasses. */ + RUBY_T_ZOMBIE = 0x1d, /**< @see struct ::RZombie */ + RUBY_T_MOVED = 0x1e, /**< @see struct ::RMoved */ + + RUBY_T_MASK = 0x1f /**< Bitmask of ::ruby_value_type. */ +}; + +RBIMPL_SYMBOL_EXPORT_BEGIN() +RBIMPL_ATTR_COLD() +/** + * @private + * + * This was the old implementation of Check_Type(), but they diverged. This + * one remains for theoretical backwards compatibility. People normally need + * not use it. + * + * @param[in] obj An object. + * @param[in] t A type. + * @exception rb_eTypeError `obj` is not of type `t`. + * @exception rb_eFatal `obj` is corrupt. + * @post Upon successful return `obj` is guaranteed to have type `t`. + * + * @internal + * + * The second argument shall have been enum ::ruby_value_type. But at the time + * matz designed this function he still used K&R C. There was no such thing + * like a function prototype. We can no longer change this API. + */ +void rb_check_type(VALUE obj, int t); +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the type of the object. + * + * @param[in] obj Object in question. + * @pre `obj` must not be a special constant. + * @return The type of `obj`. + */ +static inline enum ruby_value_type +RB_BUILTIN_TYPE(VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); + +#if 0 && defined __GNUC__ && !defined __clang__ + /* Don't move the access to `flags` before the preceding + * RB_SPECIAL_CONST_P check. */ + __asm volatile("": : :"memory"); +#endif + VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK; + return RBIMPL_CAST((enum ruby_value_type)ret); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * Queries if the object is an instance of ::rb_cInteger. + * + * @param[in] obj Object in question. + * @retval true It is. + * @retval false It isn't. + */ +static inline bool +rb_integer_type_p(VALUE obj) +{ + if (RB_FIXNUM_P(obj)) { + return true; + } + else if (RB_SPECIAL_CONST_P(obj)) { + return false; + } + else { + return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/** + * Identical to RB_BUILTIN_TYPE(), except it can also accept special constants. + * + * @param[in] obj Object in question. + * @return The type of `obj`. + */ +static inline enum ruby_value_type +rb_type(VALUE obj) +{ + if (! RB_SPECIAL_CONST_P(obj)) { + return RB_BUILTIN_TYPE(obj); + } + else if (obj == RUBY_Qfalse) { + return RUBY_T_FALSE; + } + else if (obj == RUBY_Qnil) { + return RUBY_T_NIL; + } + else if (obj == RUBY_Qtrue) { + return RUBY_T_TRUE; + } + else if (obj == RUBY_Qundef) { + return RUBY_T_UNDEF; + } + else if (RB_FIXNUM_P(obj)) { + return RUBY_T_FIXNUM; + } + else if (RB_STATIC_SYM_P(obj)) { + return RUBY_T_SYMBOL; + } + else { + RBIMPL_ASSUME(RB_FLONUM_P(obj)); + return RUBY_T_FLOAT; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the object is an instance of ::rb_cFloat. + * + * @param[in] obj Object in question. + * @retval true It is. + * @retval false It isn't. + */ +static inline bool +RB_FLOAT_TYPE_P(VALUE obj) +{ + if (RB_FLONUM_P(obj)) { + return true; + } + else if (RB_SPECIAL_CONST_P(obj)) { + return false; + } + else { + return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the object is a dynamic symbol. + * + * @param[in] obj Object in question. + * @retval true It is. + * @retval false It isn't. + */ +static inline bool +RB_DYNAMIC_SYM_P(VALUE obj) +{ + if (RB_SPECIAL_CONST_P(obj)) { + return false; + } + else { + return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the object is an instance of ::rb_cSymbol. + * + * @param[in] obj Object in question. + * @retval true It is. + * @retval false It isn't. + */ +static inline bool +RB_SYMBOL_P(VALUE obj) +{ + return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_FORCEINLINE() +/** + * @private + * + * This is an implementation detail of RB_TYPE_P(). Just don't use it. + * + * @param[in] obj An object. + * @param[in] t A type. + * @retval true `obj` is of type `t`. + * @retval false Otherwise. + */ +static bool +rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t) +{ + if (t == RUBY_T_TRUE) { + return obj == RUBY_Qtrue; + } + else if (t == RUBY_T_FALSE) { + return obj == RUBY_Qfalse; + } + else if (t == RUBY_T_NIL) { + return obj == RUBY_Qnil; + } + else if (t == RUBY_T_UNDEF) { + return obj == RUBY_Qundef; + } + else if (t == RUBY_T_FIXNUM) { + return RB_FIXNUM_P(obj); + } + else if (t == RUBY_T_SYMBOL) { + return RB_SYMBOL_P(obj); + } + else if (t == RUBY_T_FLOAT) { + return RB_FLOAT_TYPE_P(obj); + } + else if (RB_SPECIAL_CONST_P(obj)) { + return false; + } + else if (t == RB_BUILTIN_TYPE(obj)) { + return true; + } + else { + return false; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the given object is of given type. + * + * @param[in] obj An object. + * @param[in] t A type. + * @retval true `obj` is of type `t`. + * @retval false Otherwise. + * + * @internal + * + * This function is a super-duper hot path. Optimised targeting modern C + * compilers and x86_64 architecture. + */ +static inline bool +RB_TYPE_P(VALUE obj, enum ruby_value_type t) +{ + if (RBIMPL_CONSTANT_P(t)) { + return rbimpl_RB_TYPE_P_fastpath(obj, t); + } + else { + return t == rb_type(obj); + } +} + +/** @cond INTERNAL_MACRO */ +/* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function + * boundary. */ +#if defined(__clang__) +# undef RB_TYPE_P +# define RB_TYPE_P(obj, t) \ + (RBIMPL_CONSTANT_P(t) ? \ + rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \ + (RB_TYPE_P)((obj), (t))) +#endif + +/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE + * in inline function and caller function + * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba + */ +#if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0) +# undef rb_integer_type_p +# define rb_integer_type_p(obj) \ + __extension__ ({ \ + const VALUE integer_type_obj = (obj); \ + (RB_FIXNUM_P(integer_type_obj) || \ + (!RB_SPECIAL_CONST_P(integer_type_obj) && \ + RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \ + }) +#endif +/** @endcond */ + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * Defined in ruby/internal/core/rtypeddata.h + */ +static inline bool rbimpl_rtypeddata_p(VALUE obj); + +RBIMPL_ATTR_ARTIFICIAL() +/** + * Identical to RB_TYPE_P(), except it raises exceptions on predication + * failure. + * + * @param[in] v An object. + * @param[in] t A type. + * @exception rb_eTypeError `obj` is not of type `t`. + * @exception rb_eFatal `obj` is corrupt. + * @post Upon successful return `obj` is guaranteed to have type `t`. + */ +static inline void +Check_Type(VALUE v, enum ruby_value_type t) +{ + if (RB_UNLIKELY(! RB_TYPE_P(v, t))) { + goto unexpected_type; + } + else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) { + /* Typed data is not simple `T_DATA`, see `rb_check_type` */ + goto unexpected_type; + } + else { + return; + } + + unexpected_type: + rb_unexpected_type(v, t); +} + +#endif /* RBIMPL_VALUE_TYPE_H */ diff --git a/ruby/include/ruby/internal/variable.h b/ruby/include/ruby/internal/variable.h new file mode 100644 index 000000000..1f84b92db --- /dev/null +++ b/ruby/include/ruby/internal/variable.h @@ -0,0 +1,337 @@ +#ifndef RBIMPL_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_VARIABLE_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Declares rb_define_variable(). + */ +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/noreturn.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Type that represents a global variable getter function. + * + * @param[in] id The variable name. + * @param[in,out] data Where the value is stored. + * @return The value that shall be visible from Ruby. + */ +typedef VALUE rb_gvar_getter_t(ID id, VALUE *data); + +/** + * Type that represents a global variable setter function. + * + * @param[in] val The value to set. + * @param[in] id The variable name. + * @param[in,out] data Where the value is to be stored. + */ +typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data); + +/** + * Type that represents a global variable marker function. + * + * @param[in] var Where the value is to be stored. + */ +typedef void rb_gvar_marker_t(VALUE *var); + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_getter_t rb_gvar_undef_getter; + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_setter_t rb_gvar_undef_setter; + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_marker_t rb_gvar_undef_marker; + +/** + * This is the getter function that backs global variables defined from a ruby + * script. Extension libraries can use this if its global variable needs no + * custom logic. + */ +rb_gvar_getter_t rb_gvar_val_getter; + +/** + * This is the setter function that backs global variables defined from a ruby + * script. Extension libraries can use this if its global variable needs no + * custom logic. + */ +rb_gvar_setter_t rb_gvar_val_setter; + +/** + * This is the setter function that backs global variables defined from a ruby + * script. Extension libraries can use this if its global variable needs no + * custom logic. + */ +rb_gvar_marker_t rb_gvar_val_marker; + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_getter_t rb_gvar_var_getter; + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_setter_t rb_gvar_var_setter; + +/** + * @deprecated + * + * This function has no actual usage (than in ruby itself). Please ignore. It + * was a bad idea to expose this function to 3rd parties, but we can no longer + * delete it. + */ +rb_gvar_marker_t rb_gvar_var_marker; + +RBIMPL_ATTR_NORETURN() +/** + * This function just raises ::rb_eNameError. Handy when you want to prohibit + * a global variable from being squashed by someone. + */ +rb_gvar_setter_t rb_gvar_readonly_setter; + +RBIMPL_ATTR_NONNULL(()) +/** + * "Shares" a global variable between Ruby and C. Normally a Ruby-level global + * variable is stored somewhere deep inside of the interpreter's execution + * context, but this way you can explicitly specify its storage. + * + * ```CXX + * static VALUE foo; + * + * extern "C" void + * init_Foo(void) + * { + * foo = rb_eval_string("..."); + * rb_define_global_variable("$foo", &foo); + * } + * ``` + * + * In the above example a Ruby global variable named `$foo` is stored in a C + * global variable named `foo`. + * + * @param[in] name Variable (Ruby side). + * @param[in] var Variable (C side). + * @post Ruby level global variable named `name` is defined if absent, + * and its storage is set to `var`. + */ +void rb_define_variable(const char *name, VALUE *var); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Defines a global variable that is purely function-backended. By using this + * API a programmer can define a global variable that dynamically changes from + * time to time. + * + * @param[in] name Variable name, in C's string. + * @param[in] getter A getter function. + * @param[in] setter A setter function. + * @post Ruby level global variable named `name` is defined if absent. + * + * @internal + * + * @shyouhei doesn't know if this is an Easter egg or an official feature, but + * you can pass 0 to the third argument (setter). That effectively nullifies + * any efforts to write to the defining global variable. + */ +void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_define_virtual_variable(), but can also specify a storage. + * A programmer can use the storage for e.g. memoisation, storing intermediate + * computation result, etc. + * + * Also you can pass 0 to this function, unlike other variants: + * + * - When getter is 0 ::rb_gvar_var_getter is used instead. + * - When setter is 0 ::rb_gvar_var_setter is used instead. + * - When data is 0, you must specify a non-zero setter function. Otherwise + * ::rb_gvar_var_setter tries to write to `*NULL`, and just causes SEGV. + * + * @param[in] name Variable name, in C's string. + * @param[in] var Variable storage. + * @param[in] getter A getter function. + * @param[in] setter A setter function. + * @post Ruby level global variable named `name` is defined if absent. + */ +void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_define_variable(), except it does not allow Ruby programs to + * assign values to such global variable. C codes can still set values at + * will. This could be handy for you when implementing an `errno`-like + * experience, where a method updates a read-only global variable as a side- + * effect. + * + * @param[in] name Variable (Ruby side). + * @param[in] var Variable (C side). + * @post Ruby level global variable named `name` is defined if absent, + * and its storage is set to `var`. + */ +void rb_define_readonly_variable(const char *name, const VALUE *var); + +RBIMPL_ATTR_NONNULL(()) +/** + * Defines a Ruby level constant under a namespace. + * + * @param[out] klass Namespace for the constant to reside. + * @param[in] name Name of the constant. + * @param[in] val Value of the constant. + * @exception rb_eTypeError `klass` is not a kind of ::rb_cModule. + * @exception rb_eFrozenError `klass` is frozen. + * @post Ruby level constant `klass::name` is defined to be `val`. + * @note This API does not stop you from defining a constant that is + * unable to reach from ruby (like for instance passing + * non-capital letter to `name`). + * @note This API does not stop you from overwriting a constant that + * already exist. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_define_const(VALUE klass, const char *name, VALUE val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Identical to rb_define_const(), except it defines that of "global", + * i.e. toplevel constant. + * + * @param[in] name Name of the constant. + * @param[in] val Value of the constant. + * @exception rb_eFrozenError ::rb_cObject is frozen. + * @post Ruby level constant \::name is defined to be `val`. + * @note This API does not stop you from defining a constant that is + * unable to reach from ruby (like for instance passing + * non-capital letter to `name`). + * @note This API does not stop you from overwriting a constant that + * already exist. + */ +void rb_define_global_const(const char *name, VALUE val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Asserts that the given constant is deprecated. Attempt to refer such + * constant will produce a warning. + * + * @param[in] mod Namespace of the target constant. + * @param[in] name Name of the constant. + * @exception rb_eNameError No such constant. + * @exception rb_eFrozenError `mod` is frozen. + * @post `name` under `mod` is deprecated. + */ +void rb_deprecate_constant(VALUE mod, const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Assigns to a global variable. + * + * @param[in] name Target global variable. + * @param[in] val Value to assign. + * @return Passed value. + * @post Ruby level global variable named `name` is defined if absent, + * whose value is set to `val`. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with + * `set_trace_func`. + */ +VALUE rb_gv_set(const char *name, VALUE val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Obtains a global variable. + * + * @param[in] name Global variable to query. + * @retval RUBY_Qnil The global variable does not exist. + * @retval otherwise The value assigned to the global variable. + * + * @internal + * + * Unlike rb_gv_set(), there is no way to trace this function. + */ +VALUE rb_gv_get(const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Obtains an instance variable. + * + * @param[in] obj Target object. + * @param[in] name Target instance variable to query. + * @exception rb_eEncodingError `name` is corrupt (contains Hanzi etc.). + * @retval RUBY_nil No such instance variable. + * @retval otherwise The value assigned to the instance variable. + */ +VALUE rb_iv_get(VALUE obj, const char *name); + +RBIMPL_ATTR_NONNULL(()) +/** + * Assigns to an instance variable. + * + * @param[out] obj Target object. + * @param[in] name Target instance variable. + * @param[in] val Value to assign. + * @exception rb_eFrozenError Can't modify `obj`. + * @exception rb_eArgError `obj` has too many instance variables. + * @return Passed value. + * @post An instance variable named `name` is defined if absent on + * `obj`, whose value is set to `val`. + * + * @internal + * + * This function does not stop you form creating an ASCII-incompatible instance + * variable, but there is no way to get one because rb_iv_get raises exceptions + * for such things. This design seems broken... But no idea why. + */ +VALUE rb_iv_set(VALUE obj, const char *name, VALUE val); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_VARIABLE_H */ diff --git a/ruby/include/ruby/internal/warning_push.h b/ruby/include/ruby/internal/warning_push.h new file mode 100644 index 000000000..f5981633f --- /dev/null +++ b/ruby/include/ruby/internal/warning_push.h @@ -0,0 +1,124 @@ +#ifndef RBIMPL_WARNING_PUSH_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_WARNING_PUSH_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_WARNING_PUSH. + * + * ### Q&A ### + * + * Q: Why all the macros defined in this file are function-like macros? + * + * A: Sigh. This is because of Doxygen. Its `SKIP_FUNCTION_MACROS = YES` + * configuration setting requests us that if we want it to ignore these + * macros, then we have to do two things: (1) let them be defined as + * function-like macros, and (2) place them separately in their own line, + * like below: + * + * ```CXX + * // NG -- foo's type considered something like `unsigned int`. + * RBIMPL_WARNING_PUSH + * int foo(void); + * RBIMPL_WARNING_POP + * + * // OK -- the macros are ignored by Doxygen. + * RBIMPL_WARNING_PUSH() + * int foo(void); + * RBIMPL_WARNING_POP() + * ``` + */ +#include "ruby/internal/compiler_is.h" +#include "ruby/internal/compiler_since.h" + +#if defined(__DOXYGEN__) + +/** + * @private + * + * Pushes compiler warning state. + */ +#define RBIMPL_WARNING_PUSH() __pragma(warning(push)) + +/** + * @private + * + * Pops compiler warning state. + */ +#define RBIMPL_WARNING_POP() __pragma(warning(pop)) + +/** + * @private + * + * Turns a warning into a fatal error. + * + * @param flag A flag that represents the kind of warnings. + */ +#define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) + +/** + * @private + * + * Suppresses a warning. + * + * @param flag A flag that represents the kind of warnings. + */ +#define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) + +#elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +# /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/ +# define RBIMPL_WARNING_PUSH() __pragma(warning(push)) +# define RBIMPL_WARNING_POP() __pragma(warning(pop)) +# define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) +# define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) + +#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) +# define RBIMPL_WARNING_PUSH() __pragma(warning(push)) +# define RBIMPL_WARNING_POP() __pragma(warning(pop)) +# define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) +# define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) + +#elif RBIMPL_COMPILER_IS(Clang) || RBIMPL_COMPILER_IS(Apple) +# /* Not sure exactly when but it seems LLVM 2.6.0 is a version with it. */ +# define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) +# define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(clang diagnostic x) +# define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) +# define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) +# define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) +# define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) +# define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) + +#elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) +# /* https://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html */ +# define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) +# define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(GCC diagnostic x) +# define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) +# define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) +# define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) +# define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) +# define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) + +#else +# /* :FIXME: improve here */ +# define RBIMPL_WARNING_PUSH() /* void */ +# define RBIMPL_WARNING_POP() /* void */ +# define RBIMPL_WARNING_ERROR(flag) /* void */ +# define RBIMPL_WARNING_IGNORED(flag) /* void */ +#endif /* _MSC_VER */ +/** @endcond */ + +#endif /* RBIMPL_WARNING_PUSH_H */ diff --git a/ruby/include/ruby/internal/xmalloc.h b/ruby/include/ruby/internal/xmalloc.h new file mode 100644 index 000000000..57552e4e7 --- /dev/null +++ b/ruby/include/ruby/internal/xmalloc.h @@ -0,0 +1,392 @@ +#ifndef RBIMPL_XMALLOC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_XMALLOC_H +/** + * @file + * @author Ruby developers + * @copyright 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. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Declares ::ruby_xmalloc(). + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include +#endif + +#ifdef HAVE_STDLIB_H +# include +#endif + +#include "ruby/internal/attr/alloc_size.h" +#include "ruby/internal/attr/nodiscard.h" +#include "ruby/internal/attr/noexcept.h" +#include "ruby/internal/attr/restrict.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/dllexport.h" + +/** + * @private + * @warning Do not touch this macro. + * @warning It is an implementation detail. + * @warning It was a failure at the first place to let you know about it. + * @warning The value of this macro must match for ruby itself and all + * extension libraries, otherwise serious memory corruption shall + * occur. + */ +#ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS +# define USE_GC_MALLOC_OBJ_INFO_DETAILS 0 +#endif + +#define xmalloc ruby_xmalloc /**< @old{ruby_xmalloc} */ +#define xmalloc2 ruby_xmalloc2 /**< @old{ruby_xmalloc2} */ +#define xcalloc ruby_xcalloc /**< @old{ruby_xcalloc} */ +#define xrealloc ruby_xrealloc /**< @old{ruby_xrealloc} */ +#define xrealloc2 ruby_xrealloc2 /**< @old{ruby_xrealloc2} */ +#define xfree ruby_xfree /**< @old{ruby_xfree} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1)) +/** + * Allocates a storage instance. It is largely the same as system malloc(), + * except: + * + * - It raises Ruby exceptions instead of returning NULL, and + * - In case of `ENOMEM` it tries to GC to make some room. + * + * @param[in] size Requested amount of memory. + * @exception rb_eNoMemError No space left for `size` bytes allocation. + * @return A valid pointer to an allocated storage instance; which has at + * least `size` bytes width, with appropriate alignment detected by + * the underlying malloc() routine. + * @note It doesn't return NULL. + * @note Unlike some malloc() implementations, it allocates something and + * returns a meaningful value even when `size` is equal to zero. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +void *ruby_xmalloc(size_t size) +RBIMPL_ATTR_NOEXCEPT(malloc(size)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1,2)) +/** + * Identical to ruby_xmalloc(), except it allocates `nelems` * `elemsiz` bytes. + * This is needed because the multiplication could integer overflow. On such + * situations Ruby does not try to allocate at all but raises Ruby level + * exceptions instead. If there is no integer overflow the behaviour is + * exactly the same as `ruby_xmalloc(nelems*elemsiz)`. + * + * @param[in] nelems Number of elements. + * @param[in] elemsiz Size of an element. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError `nelems` * `elemsiz` would overflow. + * @return A valid pointer to an allocated storage instance; which has at + * least `nelems` * `elemsiz` bytes width, with appropriate + * alignment detected by the underlying malloc() routine. + * @note It doesn't return NULL. + * @note Unlike some malloc() implementations, it allocates something and + * returns a meaningful value even when `nelems` or `elemsiz` or + * both are zero. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +void *ruby_xmalloc2(size_t nelems, size_t elemsiz) +RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1,2)) +/** + * Identical to ruby_xmalloc2(), except it returns a zero-filled storage + * instance. It can also be seen as a routine identical to ruby_xmalloc(), + * except it calls calloc() instead of malloc(). + * + * @param[in] nelems Number of elements. + * @param[in] elemsiz Size of an element. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError `nelems` * `elemsiz` would overflow. + * @return A valid pointer to an allocated storage instance; which has at + * least `nelems` * `elemsiz` bytes width, with appropriate + * alignment detected by the underlying calloc() routine. + * @post The returned storage instance is filled with zeros. + * @note It doesn't return NULL. + * @note Unlike some calloc() implementations, it allocates something and + * returns a meaningful value even when `nelems` or `elemsiz` or + * both are zero. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +void *ruby_xcalloc(size_t nelems, size_t elemsiz) +RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2)) +/** + * Resize the storage instance. + * + * @param[in] ptr A valid pointer to a storage instance that was + * previously returned from either: + * - ruby_xmalloc(), + * - ruby_xmalloc2(), + * - ruby_xcalloc(), + * - ruby_xrealloc(), or + * - ruby_xrealloc2(). + * @param[in] newsiz Requested new amount of memory. + * @exception rb_eNoMemError No space left for `newsiz` bytes allocation. + * @return A valid pointer to a (possibly newly allocated) storage + * instance; which has at least `newsiz` bytes width, with + * appropriate alignment detected by the underlying realloc() + * routine. + * @pre The passed pointer must point to a valid live storage instance. + * It is a failure to pass an already freed pointer. + * @post In case the function returns the passed pointer as-is, the + * storage instance that the pointer holds is either grown or + * shrunken to have at least `newsiz` bytes. Otherwise a valid + * pointer to a newly allocated storage instance is returned. In + * this case `ptr` is invalidated as if it was passed to + * ruby_xfree(). + * @note It doesn't return NULL. + * @warning Unlike some realloc() implementations, passing zero to `newsiz` + * is not the same as calling ruby_xfree(), because this function + * never returns NULL. Something meaningful still returns then. + * @warning It is a failure not to check the return value. Do not assume + * anything on it. It could be either identical to, or distinct + * form the passed argument. + * @warning Do not assume anything on the alignment of the return value. + * There is no guarantee that it inherits the passed argument's + * one. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +void *ruby_xrealloc(void *ptr, size_t newsiz) +RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2,3)) +/** + * Identical to ruby_xrealloc(), except it resizes the given storage instance + * to `newelems` * `newsiz` bytes. This is needed because the multiplication + * could integer overflow. On such situations Ruby does not try to touch the + * contents of argument pointer at all but raises Ruby level exceptions + * instead. If there is no integer overflow the behaviour is exactly the same + * as `ruby_xrealloc(ptr,nelems*elemsiz)`. + * + * This is roughly the same as reallocarray() function that OpenBSD + * etc. provides, but also interacts with our GC. + * + * @param[in] ptr A valid pointer to a storage instance that was + * previously returned from either: + * - ruby_xmalloc(), + * - ruby_xmalloc2(), + * - ruby_xcalloc(), + * - ruby_xrealloc(), or + * - ruby_xrealloc2(). + * @param[in] newelems Requested new number of elements. + * @param[in] newsiz Requested new size of each element. + * @exception rb_eNoMemError No space left for allocation. + * @exception rb_eArgError `newelems` * `newsiz` would overflow. + * @return A valid pointer to a (possibly newly allocated) storage + * instance; which has at least `newelems` * `newsiz` bytes width, + * with appropriate alignment detected by the underlying realloc() + * routine. + * @pre The passed pointer must point to a valid live storage instance. + * It is a failure to pass an already freed pointer. + * @post In case the function returns the passed pointer as-is, the + * storage instance that the pointer holds is either grown or + * shrunken to have at least `newelems` * `newsiz` bytes. + * Otherwise a valid pointer to a newly allocated storage instance + * is returned. In this case `ptr` is invalidated as if it was + * passed to ruby_xfree(). + * @note It doesn't return NULL. + * @warning Unlike some realloc() implementations, passing zero to either + * `newelems` or `elemsiz` are not the same as calling + * ruby_xfree(), because this function never returns NULL. + * Something meaningful still returns then. + * @warning It is a failure not to check the return value. Do not assume + * anything on it. It could be either identical to, or distinct + * form the passed argument. + * @warning Do not assume anything on the alignment of the return value. + * There is no guarantee that it inherits the passed argument's + * one. + * @warning The return value shall be invalidated exactly once by either + * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a + * failure to pass it to system free(), because the system and Ruby + * might or might not share the same malloc() implementation. + */ +void *ruby_xrealloc2(void *ptr, size_t newelems, size_t newsiz) +RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) +; + +/** + * Deallocates a storage instance. + * + * @param[out] ptr Either + * - NULL, or + * - a valid pointer previously returned from one of: + * - ruby_xmalloc(), + * - ruby_xmalloc2(), + * - ruby_xcalloc(), + * - ruby_xrealloc(), or + * - ruby_xrealloc2(). + * @pre The passed pointer must point to a valid live storage instance. + * It is a failure to pass an already freed pointer. + * @post The storage instance pointed by the passed pointer gets + * invalidated; it is no longer addressable. + * @warning Every single storage instance that was previously allocated by + * either ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(), + * ruby_xrealloc(), or ruby_xrealloc2() shall be invalidated + * exactly once by either passing it to ruby_xfree(), or passing + * it to either ruby_xrealloc(), ruby_xrealloc2() then check the + * return value for invalidation. + * @warning Do not pass anything other than pointers described above. For + * instance pointers returned from malloc() or mmap() shall not be + * passed to this function, because the underlying memory + * management mechanism could differ. + * @warning Do not pass any invalid pointers to this function e.g. by + * calling it twice with a same argument. + */ +void ruby_xfree(void *ptr) +RBIMPL_ATTR_NOEXCEPT(free(ptr)) +; + +#if USE_GC_MALLOC_OBJ_INFO_DETAILS +# define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__) +# define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__) +# define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__) +# define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__) +# define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__) + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1)) +void *ruby_xmalloc_body(size_t size) +RBIMPL_ATTR_NOEXCEPT(malloc(size)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1,2)) +void *ruby_xmalloc2_body(size_t nelems, size_t elemsiz) +RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((1,2)) +void *ruby_xcalloc_body(size_t nelems, size_t elemsiz) +RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2)) +void *ruby_xrealloc_body(void *ptr, size_t newsiz) +RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) +; + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_ALLOC_SIZE((2,3)) +void *ruby_xrealloc2_body(void *ptr, size_t newelems, size_t newsiz) +RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) +; + +RUBY_EXTERN const char *ruby_malloc_info_file; +RUBY_EXTERN int ruby_malloc_info_line; + +static inline void * +ruby_xmalloc_with_location(size_t s, const char *file, int line) +{ + void *ptr; + ruby_malloc_info_file = file; + ruby_malloc_info_line = line; + ptr = ruby_xmalloc_body(s); + ruby_malloc_info_file = NULL; + return ptr; +} + +static inline void * +ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line) +{ + void *ptr; + ruby_malloc_info_file = file; + ruby_malloc_info_line = line; + ptr = ruby_xmalloc2_body(s1, s2); + ruby_malloc_info_file = NULL; + return ptr; +} + +static inline void * +ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line) +{ + void *ptr; + ruby_malloc_info_file = file; + ruby_malloc_info_line = line; + ptr = ruby_xcalloc_body(s1, s2); + ruby_malloc_info_file = NULL; + return ptr; +} + +static inline void * +ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line) +{ + void *rptr; + ruby_malloc_info_file = file; + ruby_malloc_info_line = line; + rptr = ruby_xrealloc_body(ptr, s); + ruby_malloc_info_file = NULL; + return rptr; +} + +static inline void * +ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line) +{ + void *rptr; + ruby_malloc_info_file = file; + ruby_malloc_info_line = line; + rptr = ruby_xrealloc2_body(ptr, s1, s2); + ruby_malloc_info_file = NULL; + return rptr; +} +#endif + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_XMALLOC_H */ diff --git a/ruby/include/ruby/io.h b/ruby/include/ruby/io.h index 152f4ef76..3e035c114 100644 --- a/ruby/include/ruby/io.h +++ b/ruby/include/ruby/io.h @@ -1,27 +1,16 @@ -/********************************************************************** - - rubyio.h - - - $Author$ - created at: Fri Nov 12 16:47:09 JST 1993 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_IO_H +#ifndef RUBY_IO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_IO_H 1 - -#ifdef RUBY_INTERNAL_H -#error "Include this file before internal.h" -#endif - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif +/** + * @file + * @author $Author$ + * @date Fri Nov 12 16:47:09 JST 1993 + * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto + * @copyright 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. + */ +#include "ruby/internal/config.h" #include #include "ruby/encoding.h" @@ -30,8 +19,9 @@ extern "C" { #include #endif -#include "ruby/config.h" #include + +/** @cond INTERNAL_MACRO */ #if defined(HAVE_POLL) # ifdef _AIX # define reqevents events @@ -52,30 +42,99 @@ extern "C" { # define RB_WAITFD_PRI 0x002 # define RB_WAITFD_OUT 0x004 #endif +/** @endcond */ + +#include "ruby/internal/attr/const.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" +#include "ruby/backward/2/attributes.h" /* PACKED_STRUCT_UNALIGNED */ -RUBY_SYMBOL_EXPORT_BEGIN +RBIMPL_SYMBOL_EXPORT_BEGIN() +struct stat; +struct timeval; + +/** + * Type of events that an IO can wait. + * + * @internal + * + * This is visible from extension libraries because `io/wait` wants it. + */ +typedef enum { + RUBY_IO_READABLE = RB_WAITFD_IN, /**< `IO::READABLE` */ + RUBY_IO_WRITABLE = RB_WAITFD_OUT, /**< `IO::WRITABLE` */ + RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */ +} rb_io_event_t; + +/** + * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and + * ::rb_io_t::rbuf. People don't manipulate it directly. + */ PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t { + + /** Pointer to the underlying memory region, of at least `capa` bytes. */ char *ptr; /* off + len <= capa */ + + /** Offset inside of `ptr`. */ int off; + + /** Length of the buffer. */ int len; + + /** Designed capacity of the buffer. */ int capa; }); + +/** @alias{rb_io_buffer_t} */ typedef struct rb_io_buffer_t rb_io_buffer_t; +/** Ruby's IO, metadata and buffers. */ typedef struct rb_io_t { - FILE *stdio_file; /* stdio ptr for read/write if available */ - int fd; /* file descriptor */ - int mode; /* mode flags: FMODE_XXXs */ - rb_pid_t pid; /* child's pid (for pipes) */ - int lineno; /* number of lines read */ - VALUE pathv; /* pathname for file */ - void (*finalize)(struct rb_io_t*,int); /* finalize proc */ - rb_io_buffer_t wbuf, rbuf; + /** The IO's Ruby level counterpart. */ + VALUE self; + + /** stdio ptr for read/write, if available. */ + FILE *stdio_file; + + /** file descriptor. */ + int fd; + /** mode flags: FMODE_XXXs */ + int mode; + + /** child's pid (for pipes) */ + rb_pid_t pid; + + /** number of lines read */ + int lineno; + + /** pathname for file */ + VALUE pathv; + + /** finalize proc */ + void (*finalize)(struct rb_io_t*,int); + + /** Write buffer. */ + rb_io_buffer_t wbuf; + + /** + * (Byte) read buffer. Note also that there is a field called + * ::rb_io_t::cbuf, which also concerns read IO. + */ + rb_io_buffer_t rbuf; + + /** + * Duplex IO object, if set. + * + * @see rb_io_set_write_io() + */ VALUE tied_io_for_writing; + /** Decomposed encoding flags (e.g. `"enc:enc2""`). */ /* * enc enc2 read action write action * NULL NULL force_encoding(default_external) write the byte sequence of str @@ -83,103 +142,835 @@ typedef struct rb_io_t { * e1 e2 convert from e2 to e1 convert str.encoding to e2 */ struct rb_io_enc_t { + /** Internal encoding. */ rb_encoding *enc; + + /** External encoding. */ rb_encoding *enc2; + + /** + * Flags. + * + * @see enum ::ruby_econv_flag_type + */ int ecflags; + + /** + * Flags as Ruby hash. + * + * @internal + * + * This is set. But used from nowhere maybe? + */ VALUE ecopts; - } encs; + } encs; /**< Decomposed encoding flags. */ + /** Encoding converter used when reading from this IO. */ rb_econv_t *readconv; + + /** + * rb_io_ungetc() destination. This buffer is read before checking + * ::rb_io_t::rbuf + */ rb_io_buffer_t cbuf; + /** Encoding converter used when writing to this IO. */ rb_econv_t *writeconv; + + /** + * This is, when set, an instance of ::rb_cString which holds the "common" + * encoding. Write conversion can convert strings twice... In case + * conversion from encoding X to encoding Y does not exist, Ruby finds an + * encoding Z that bridges the two, so that X to Z to Y conversion happens. + */ VALUE writeconv_asciicompat; + + /** Whether ::rb_io_t::writeconv is already set up. */ int writeconv_initialized; + + /** + * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before + * initialising ::rb_io_t::writeconv. + */ int writeconv_pre_ecflags; + + /** + * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising + * ::rb_io_t::writeconv. + */ VALUE writeconv_pre_ecopts; + /** + * This is a Ruby level mutex. It avoids multiple threads to write to an + * IO at once; helps for instance rb_io_puts() to ensure newlines right + * next to its arguments. + * + * This of course doesn't help inter-process IO interleaves, though. + */ VALUE write_lock; } rb_io_t; +/** @alias{rb_io_enc_t} */ typedef struct rb_io_enc_t rb_io_enc_t; +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ #define HAVE_RB_IO_T 1 +/** + * @name Possible flags for ::rb_io_t::mode + * + * @{ + */ + +/** The IO is opened for reading. */ #define FMODE_READABLE 0x00000001 + +/** The IO is opened for writing. */ #define FMODE_WRITABLE 0x00000002 + +/** The IO is opened for both read/write. */ #define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE) + +/** + * The IO is in "binary mode". This is not what everything rb_io_binmode() + * concerns. This low-level flag is to stop CR <-> CRLF conversions that would + * happen in the underlying operating system. + * + * Setting this one and #FMODE_TEXTMODE at the same time is a contradiction. + * Setting this one and #ECONV_NEWLINE_DECORATOR_MASK at the same time is also + * a contradiction. + */ #define FMODE_BINMODE 0x00000004 + +/** + * The IO is in "sync mode". All output is immediately flushed to the + * underlying operating system then. Can be set via rb_io_synchronized(), but + * there is no way except calling `IO#sync=` to reset. + */ #define FMODE_SYNC 0x00000008 + +/** + * The IO is a TTY. What is a TTY and what isn't depends on the underlying + * operating system's `isatty(3)` output. You cannot change this. + */ #define FMODE_TTY 0x00000010 + +/** + * Ruby eventually detects that the IO is bidirectional. For instance a TTY + * has such property. There are several other things known to be duplexed. + * Additionally you (extension library authors) can also implement your own + * bidirectional IO subclasses. One of such example is `Socket`. + */ #define FMODE_DUPLEX 0x00000020 + +/** + * The IO is opened for appending. This mode always writes at the end of the + * IO. Ruby manages this flag for record but basically the logic behind this + * mode is at the underlying operating system. We almost do nothing. + */ #define FMODE_APPEND 0x00000040 + +/** + * The IO is opened for creating. This makes sense only when the destination + * file does not exist at the time the IO object was created. This is the + * default mode for writing, but you can pass `"r+"` to `IO.open` etc., to + * reroute this creation. + */ #define FMODE_CREATE 0x00000080 /* #define FMODE_NOREVLOOKUP 0x00000100 */ + +/** + * This flag amends the effect of #FMODE_CREATE, so that if there already is a + * file at the given path the operation fails. Using this you can be sure that + * the file you get is a fresh new one. + */ #define FMODE_EXCL 0x00000400 + +/** + * This flag amends the effect of #FMODE_CREATE, so that if there already is a + * file at the given path it gets truncated. + */ #define FMODE_TRUNC 0x00000800 + +/** + * The IO is in "text mode". On systems where such mode make sense, this flag + * changes the way the IO handles the contents. On POSIX systems it is + * basically a no-op, but with this flag set you can optionally let Ruby + * manually convert newlines, unlike when in binary mode: + * + * ```ruby + * IO.open("/p/a/t/h", "wt", crlf_newline: true) # "wb" is NG. + * ``` + * + * Setting this one and #FMODE_BINMODE at the same time is a contradiction. + */ #define FMODE_TEXTMODE 0x00001000 /* #define FMODE_PREP 0x00010000 */ +/* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */ + +/** + * This flag amends the encoding of the IO so that the BOM of the contents of + * the IO takes effect. + */ #define FMODE_SETENC_BY_BOM 0x00100000 /* #define FMODE_UNIX 0x00200000 */ /* #define FMODE_INET 0x00400000 */ /* #define FMODE_INET6 0x00800000 */ -#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) - -#define MakeOpenFile(obj, fp) do {\ +/** @} */ + +/** + * Queries the underlying IO pointer. + * + * @param[in] obj An IO object. + * @param[out] fp A variable of type ::rb_io_t. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eIOError `obj` is closed. + * @post `fp` holds `obj`'s underlying IO. + */ +#define RB_IO_POINTER(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) + +/** + * This is an old name of #RB_IO_POINTER. Not sure if we want to deprecate + * this macro. There still are tons of usages out there in the wild. + */ +#define GetOpenFile RB_IO_POINTER + +/** + * Fills an IO object. This makes the best sense when called from inside of an + * `#initialize` method of a 3rd party extension library that inherits + * ::rb_cIO. + * + * If the passed IO is already opened for something it first closes that and + * opens a new one instead. + * + * @param[out] obj An IO object to fill in. + * @param[out] fp A variable of type ::rb_io_t. + * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE. + * @post `fp` holds `obj`'s underlying IO. + */ +#define RB_IO_OPEN(obj, fp) do {\ (fp) = rb_io_make_open_file(obj);\ } while (0) +/** + * This is an old name of #RB_IO_OPEN. Not sure if we want to deprecate this + * macro. There still are usages out there in the wild. + */ +#define MakeOpenFile RB_IO_OPEN + +/** + * @private + * + * This is an implementation detail of #RB_IO_OPEN. People don't use it + * directly. + * + * @param[out] obj An IO object to fill in. + * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE. + * @return `obj`'s backend IO. + * @post `obj` is initialised. + */ rb_io_t *rb_io_make_open_file(VALUE obj); +/** + * Finds or creates a stdio's file structure from a Ruby's one. This can be + * handy if you want to call an external API that accepts `FILE *`. + * + * @note Note however, that `FILE`s can have their own buffer. Mixing Ruby's + * and stdio's file are basically dangerous. Use with care. + * + * @param[in,out] fptr Target IO. + * @return A stdio's file, created if absent. + * @post `fptr` has its corresponding stdio's file. + * + * @internal + * + * We had rich support for `FILE` before! In the days of 1.8.x ::rb_io_t was + * like this: + * + * ```CXX + * typedef struct rb_io_t { + * FILE *f; // stdio ptr for read/write + * FILE *f2; // additional ptr for rw pipes + * int mode; // mode flags + * int pid; // child's pid (for pipes) + * int lineno; // number of lines read + * char *path; // pathname for file + * void (*finalize) _((struct rb_io_t*,int)); // finalize proc + * } rb_io_t; + *``` + * + * But we eventually abandoned this layout. It was too difficult. We could + * not have fine-grained control over the `f` field. + * + * - `FILE` tends to be an opaque struct. It does not interface well with + * `select(2)` etc. This makes IO multiplexing quite hard. Using stdio, + * there is arguably no portable way to know if `fwrite(3)` blocks. + * + * - Nonblocking mode, which is another core concept that enables IO + * multiplexing, does not interface with stdio routines at all. + * + * - Detection of duplexed IO is also hard for the same reason. + * + * - `feof(3)` is not portable. + * https://mail.python.org/pipermail/python-dev/2001-January/011390.html + * + * - Solaris was a thing back then. They could not have more than 256 `FILE` + * structures at a time. Their file descriptors ware stored in an + * `unsigned char`. + * + * - It is next to impossible to avoid SEGV, especially when a thread tries to + * `ungetc(3)`-ing from a `FILE` which is `fread(3)`-ed by another one. + * + * In short, it is a bad idea to let someone else manage IO buffers, especially + * someone you cannot control. This still applies to extension libraries + * methinks. Ruby doesn't prevent you from shooting yourself in the foot, but + * consider yourself warned here. + */ FILE *rb_io_stdio_file(rb_io_t *fptr); -FILE *rb_fdopen(int, const char*); +/** + * Identical to rb_io_stdio_file(), except it takes file descriptors instead of + * Ruby's IO. It can also be seen as a compatibility layer to wrap + * `fdopen(3)`. Nowadays all supporting systems, including Windows, have + * `fdopen`. Why not use them. + * + * @param[in] fd A file descriptor. + * @param[in] modestr C string, something like `"r+"`. + * @exception rb_eSystemCallError `fdopen` failed for some reason. + * @return A stdio's file associated with `fd`. + * @note Interpretation of `modestr` depends on the underlying operating + * system. On glibc you might be able to pass e.g. `"rm"`, but + * that's an extension to POSIX. + */ +FILE *rb_fdopen(int fd, const char *modestr); + +/** + * Maps a file mode string (that rb_file_open() takes) into a mixture of + * `FMODE_` flags. This for instance returns + * `FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_EXCL` for `"wx"`. + * + * @note You cannot pass this return value to OS provided `open(2)` etc. + * + * @param[in] modestr File mode, in C's string. + * @exception rb_eArgError `modestr` is broken. + * @return A set of flags. + * + * @internal + * + * rb_io_modestr_fmode() is not a pure function because it raises. + */ int rb_io_modestr_fmode(const char *modestr); + +/** + * Identical to rb_io_modestr_fmode(), except it returns a mixture of `O_` + * flags. This for instance returns `O_WRONLY | O_TRUNC | O_CREAT | O_EXCL` for + * `"wx"`. + * + * @param[in] modestr File mode, in C's string. + * @exception rb_eArgError `modestr` is broken. + * @return A set of flags. + * + * @internal + * + * rb_io_modestr_oflags() is not a pure function because it raises. + */ int rb_io_modestr_oflags(const char *modestr); -CONSTFUNC(int rb_io_oflags_fmode(int oflags)); -void rb_io_check_writable(rb_io_t*); -void rb_io_check_readable(rb_io_t*); + +RBIMPL_ATTR_CONST() +/** + * Converts an oflags (that rb_io_modestr_oflags() returns) to a fmode (that + * rb_io_mode_flags() returns). This is a purely functional operation. + * + * @param[in] oflags A set of `O_` flags. + * @return Corresponding set of `FMODE_` flags. + */ +int rb_io_oflags_fmode(int oflags); + +/** + * Asserts that an IO is opened for writing. + * + * @param[in] fptr An IO you want to write to. + * @exception rb_eIOError `fptr` is not for writing. + * @post Upon successful return `fptr` is ready for writing. + * + * @internal + * + * The parameter must have been `const rb_io_t *`. + */ +void rb_io_check_writable(rb_io_t *fptr); + +/** @alias{rb_io_check_byte_readable} */ +void rb_io_check_readable(rb_io_t *fptr); + +/** + * Asserts that an IO is opened for character-based reading. A character can + * be wider than a byte. Because of this we have to buffer reads from + * descriptors. This fiction checks if that is possible. + * + * @param[in] fptr An IO you want to read characters from. + * @exception rb_eIOError `fptr` is not for reading. + * @post Upon successful return `fptr` is ready for reading characters. + * + * @internal + * + * Unlike rb_io_check_writable() the parameter cannot be `const rb_io_t *`. + * Behind the scene this operation flushes its write buffers. This is because + * of OpenSSL. They mandate this way. + * + * @see "Can I use OpenSSL's SSL library with non-blocking I/O?" + * https://www.openssl.org/docs/faq.html + */ void rb_io_check_char_readable(rb_io_t *fptr); + +/** + * Asserts that an IO is opened for byte-based reading. Byte-based and + * character-based reading operations cannot be mixed at a time. + * + * @param[in] fptr An IO you want to read characters from. + * @exception rb_eIOError `fptr` is not for reading. + * @post Upon successful return `fptr` is ready for reading bytes. + */ void rb_io_check_byte_readable(rb_io_t *fptr); -int rb_io_fptr_finalize(rb_io_t*); -void rb_io_synchronized(rb_io_t*); -void rb_io_check_initialized(rb_io_t*); -void rb_io_check_closed(rb_io_t*); + +/** + * Destroys the given IO. Any pending operations are flushed. + * + * @note It makes no sense to call this function from anywhere outside of your + * class' ::rb_data_type_struct::dfree. + * + * @param[out] fptr IO to close. + * @post `fptr` is no longer a valid pointer. + */ +int rb_io_fptr_finalize(rb_io_t *fptr); + +/** + * Sets #FMODE_SYNC. + * + * @note There is no way for C extensions to undo this operation. + * + * @param[out] fptr IO to set the flag. + * @exception rb_eIOError `fptr` is not opened. + * @post `fptr` is in sync mode. + */ +void rb_io_synchronized(rb_io_t *fptr); + +/** + * Asserts that the passed IO is initialised. + * + * @param[in] fptr IO that you expect be initialised. + * @exception rb_eIOError `fptr` is not initialised. + * @post `fptr` is initialised. + */ +void rb_io_check_initialized(rb_io_t *fptr); + +/** + * This badly named function asserts that the passed IO is _open_. + * + * @param[in] fptr An IO + * @exception rb_eIOError `fptr` is closed. + * @post `fptr` is open. + */ +void rb_io_check_closed(rb_io_t *fptr); + +/** + * Identical to rb_io_check_io(), except it raises exceptions on conversion + * failures. + * + * @param[in] io Target object. + * @exception rb_eTypeError No implicit conversion to IO. + * @return Return value of `obj.to_io`. + * @see rb_str_to_str + * @see rb_ary_to_ary + */ VALUE rb_io_get_io(VALUE io); + +/** + * Try converting an object to its IO representation using its `to_io` method, + * if any. If there is no such thing, returns ::RUBY_Qnil. + * + * @param[in] io Arbitrary ruby object to convert. + * @exception rb_eTypeError `obj.to_io` returned something non-IO. + * @retval RUBY_Qnil No conversion from `obj` to IO defined. + * @retval otherwise Converted IO representation of `obj`. + * @see rb_check_array_type + * @see rb_check_string_type + * @see rb_check_hash_type + */ VALUE rb_io_check_io(VALUE io); + +/** + * Queries the tied IO for writing. An IO can be duplexed. Fine. The thing + * is, that characteristics could sometimes be achieved by the underlying + * operating system (for instance a socket's duplexity is by nature) but + * sometimes by us. Notable example is a bidirectional pipe. Suppose you + * have: + * + * ```ruby + * fp = IO.popen("-", "r+") + * ``` + * + * This pipe is duplexed (the `"r+"`). You can both read from/write to it. + * However your operating system may or may not implement bidirectional pipes. + * FreeBSD is one of such operating systems known to have one; OTOH Linux is + * known to lack such things. So to achieve maximum portability, Ruby's + * bidirectional pipes are done purely in user land. A pipe in ruby can have + * multiple file descriptors; one for reading and the other for writing. This + * API is to obtain the IO port which corresponds to the passed one, for + * writing. + * + * @param[in] io An IO. + * @return Its tied IO for writing, if any, or `io` itself otherwise. + */ VALUE rb_io_get_write_io(VALUE io); + +/** + * Assigns the tied IO for writing. See rb_io_get_write_io() for what a "tied + * IO for writing" is. + * + * @param[out] io An IO. + * @param[in] w Another IO. + * @retval RUBY_Qnil There was no tied IO for writing for `io`. + * @retval otherwise The IO formerly tied to `io`. + * @post `io` ties `w` for writing. + * + * @internal + * + * @shyouhei doesn't think there is any needs of this function for 3rd party + * extension libraries. + */ VALUE rb_io_set_write_io(VALUE io, VALUE w); -int rb_io_wait_readable(int); -int rb_io_wait_writable(int); -int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); + +/** + * Sets an IO to a "nonblock mode". This amends the way an IO operates so that + * instead of waiting for rooms for read/write, it returns errors. In case of + * multiplexed IO situations it can be vital for IO operations not to block. + * This is the key API to achieve that property. + * + * @note Note however that nonblocking-ness propagates across process + * boundaries. You must really carefully watch your step when turning + * for instance `stderr` into nonblock mode (it tends to be shared + * across many processes). Also it is a complete disaster to mix a + * nonblocking file and stdio, and `stderr` tends to be under control of + * stdio in other processes. + * + * @param[out] fptr An IO that is to ne nonblocking. + * @post Descriptor that `fptr` describes is under nonblocking mode. + * + * @internal + * + * There is `O_NONBLOCK` but not `FMODE_NONBLOCK`. You cannot atomically + * create a nonblocking file descriptor using our API. + */ void rb_io_set_nonblock(rb_io_t *fptr); + +/** + * Returns an integer representing the numeric file descriptor for + * io. + * + * @param[in] io An IO. + * @retval int A file descriptor. + */ +int rb_io_descriptor(VALUE io); + +/** + * This function breaks down the option hash that `IO#initialize` takes into + * components. This is an implementation detail of rb_io_extract_modeenc() + * today. People prefer that API instead. + * + * @param[in] opt The hash to decompose. + * @param[out] enc_p Return value buffer. + * @param[out] enc2_p Return value buffer. + * @param[out] fmode_p Return value buffer. + * @exception rb_eTypeError `opt` is broken. + * @exception rb_eArgError Specified encoding does not exist. + * @retval 1 Components got extracted. + * @retval 0 Otherwise. + * @post `enc_p` is the specified internal encoding. + * @post `enc2_p` is the specified external encoding. + * @post `fmode_p` is the specified set of `FMODE_` modes. + */ int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p); + +/** + * This function can be seen as an extended version of + * rb_io_extract_encoding_option() that not only concerns the option hash but + * also mode string and so on. This should be mixed with rb_scan_args() like: + * + * ```CXX + * // This method mimics File.new + * static VALUE + * your_method(int argc, const VALUE *argv, VALUE self) + * { + * VALUE f; // file name + * VALUE m; // open mode + * VALUE p; // permission (O_CREAT) + * VALUE k; // keywords + * rb_io_enc_t c; // converter + * int oflags; + * int fmode; + * + * int n = rb_scan_args(argc, argv, "12:", &f, &m, &p, &k); + * rb_io_extract_modeenc(&m, &p, k, &oflags, &fmode, &c); + * + * // Every local variables declared so far has been properly filled here. + * ... + * } + * ``` + * + * @param[in,out] vmode_p Pointer to a mode object. + * @param[in,out] vperm_p Pointer to a permission object. + * @param[in] opthash Keyword arguments + * @param[out] oflags_p `O_` flags return buffer. + * @param[out] fmode_p `FMODE_` flags return buffer. + * @param[out] convconfig_p Encoding config return buffer. + * @exception rb_eTypeError Unexpected object (e.g. Time) passed. + * @exception rb_eArgError Contradiction inside of params. + * @post `*vmode_p` is a mode object (filled if any). + * @post `*vperm_p` is a permission object (filled if any). + * @post `*oflags_p` is filled with `O_` flags. + * @post `*fmode_p` is filled with `FMODE_` flags. + * @post `*convconfig_p` is filled with conversion instructions. + * + * @internal + * + * ```rbs + * class File + * def initialize: ( + * (String | int) path, + * ?(String | int) fmode, + * ?(String | int) perm, + * ?mode: (String | int), + * ?flags: int, + * ?external_encoding: (Encoding | String), + * ?internal_encoding: (Encoding | String), + * ?encoding: String, + * ?textmode: bool, + * ?binmode: bool, + * ?autoclose: bool, + * ?invalid: :replace, + * ?undef: :replace, + * ?replace: String, + * ?fallback: (Hash | Proc | Method), + * ?xml: (:text | :attr), + * ?crlf_newline: bool, + * ?cr_newline: bool, + * ?universal_newline: bool + * ) -> void + * ``` + */ void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p); + +/* :TODO: can this function be __attribute__((warn_unused_result)) or not? */ +/** + * Buffered write to the passed IO. + * + * @param[out] io Destination IO. + * @param[in] buf Contents to go to `io`. + * @param[in] size Number of bytes of `buf`. + * @exception rb_eFrozenError `io` is frozen. + * @exception rb_eIOError `io` is not open for writing. + * @exception rb_eSystemCallError `writev(2)` failed for some reason. + * @retval -1 Write failed. + * @retval otherwise Number of bytes actually written. + * @post `buf` is written to `io`. + * @note Partial write is a thing. It is a failure not to check the + * return value. + */ ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size); +//RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_readable")) +/** + * Blocks until the passed file descriptor gets readable. + * + * @deprecated We now prefer rb_io_maybe_wait_readable() over this one. + * @param[in] fd The file descriptor to wait. + * @exception rb_eIOError Bad file descriptor. + * @return 0 or 1 (meaning unclear). + * @post `fd` is ready for reading. + */ +int rb_io_wait_readable(int fd); + +//RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_writable")) +/** + * Blocks until the passed file descriptor gets writable. + * + * @deprecated We now prefer rb_io_maybe_wait_writable() over this one. + * @param[in] fd The file descriptor to wait. + * @exception rb_eIOError Bad file descriptor. + * @return 0 or 1 (meaning unclear). + */ +int rb_io_wait_writable(int fd); + +//RBIMPL_ATTR_DEPRECATED(("use rb_io_wait")) +/** + * Blocks until the passed file descriptor is ready for the passed events. + * + * @deprecated We now prefer rb_io_maybe_wait() over this one. + * @param[in] fd The file descriptor to wait. + * @param[in] events A set of enum ::rb_io_event_t. + * @param[in,out] tv Timeout. + * @retval 0 Operation timed out. + * @retval -1 `select(2)` failed for some reason. + * @retval otherwise A set of enum ::rb_io_event_t. + * @note Depending on your operating system `tv` might or might not + * be updated (POSIX permits both). Portable programs must + * have no assumptions. + */ +int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); + +/** + * Blocks until the passed IO is ready for the passed events. The "events" + * here is a Ruby level integer, which is an OR-ed value of `IO::READABLE`, + * `IO::WRITable`, and `IO::PRIORITY`. + * + * @param[in] io An IO object to wait. + * @param[in] events See above. + * @param[in] timeout Time, or numeric seconds since UNIX epoch. + * @exception rb_eIOError `io` is not open. + * @exception rb_eRangeError `timeout` is out of range. + * @exception rb_eSystemCallError `select(2)` failed for some reason. + * @retval RUBY_Qfalse Operation timed out. + * @retval Otherwise Actual events reached. + */ +VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout); + +/** + * Identical to rb_io_wait() except it additionally takes previous errno. If + * the passed errno indicates for instance `EINTR`, this function returns + * immediately. This is expected to be called in a loop. + * + * ```CXX + * while (true) { + * + * ... // Your interesting operation here + * // `errno` could be updated + * + * rb_io_maybe_wait(errno, io, ev, Qnil); + * } + * ``` + * + * @param[in] error System errno. + * @param[in] io An IO object to wait. + * @param[in] events An integer set of interests. + * @param[in] timeout Time, or numeric seconds since UNIX epoch. + * @exception rb_eIOError `io` is not open. + * @exception rb_eRangeError `timeout` is out of range. + * @exception rb_eSystemCallError `select(2)` failed for some reason. + * @retval RUBY_Qfalse Operation timed out. + * @retval Otherwise Actual events reached. + * + * @internal + * + * This function to return ::RUBY_Qfalse on timeout could be unintended. It + * seems timeout feature has some rough edge. + */ +VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout); + +/** + * Blocks until the passed IO is ready for reading, if that makes sense for the + * passed errno. This is a special case of rb_io_maybe_wait() that only + * concerns for reading. + * + * @param[in] error System errno. + * @param[in] io An IO object to wait. + * @param[in] timeout Time, or numeric seconds since UNIX epoch. + * @exception rb_eIOError `io` is not open. + * @exception rb_eRangeError `timeout` is out of range. + * @exception rb_eSystemCallError `select(2)` failed for some reason. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_READABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. + */ +int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); + +/** + * Blocks until the passed IO is ready for writing, if that makes sense for the + * passed errno. This is a special case of rb_io_maybe_wait() that only + * concernsfor writing. + * + * @param[in] error System errno. + * @param[in] io An IO object to wait. + * @param[in] timeout Time, or numeric seconds since UNIX epoch. + * @exception rb_eIOError `io` is not open. + * @exception rb_eRangeError `timeout` is out of range. + * @exception rb_eSystemCallError `select(2)` failed for some reason. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_WRITABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. + */ +int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout); + +/** @cond INTERNAL_MACRO */ /* compatibility for ruby 1.8 and older */ #define rb_io_mode_flags(modestr) [<"rb_io_mode_flags() is obsolete; use rb_io_modestr_fmode()">] #define rb_io_modenum_flags(oflags) [<"rb_io_modenum_flags() is obsolete; use rb_io_oflags_fmode()">] - -VALUE rb_io_taint_check(VALUE); -NORETURN(void rb_eof_error(void)); - -void rb_io_read_check(rb_io_t*); -int rb_io_read_pending(rb_io_t*); - -struct stat; -VALUE rb_stat_new(const struct stat *); +/** @endcond */ + +/** + * @deprecated This function once was a thing in the old days, but makes no + * sense any longer today. Exists here for backwards + * compatibility only. You can safely forget about it. + * + * @param[in] obj Object in question. + * @exception rb_eFrozenError obj is frozen. + * @return The passed `obj` + */ +VALUE rb_io_taint_check(VALUE obj); + +RBIMPL_ATTR_NORETURN() +/** + * Utility function to raise ::rb_eEOFError. + * + * @exception rb_eEOFError End of file situation. + * @note It never returns. + */ +void rb_eof_error(void); + +/** + * Blocks until there is a pending read in the passed IO. If there already is + * it just returns. + * + * @param[out] fptr An IO to wait for reading. + * @post The are bytes to be read. + */ +void rb_io_read_check(rb_io_t *fptr); + +RBIMPL_ATTR_PURE() +/** + * Queries if the passed IO has any pending reads. Unlike rb_io_read_check() + * this doesn't block; has no side effects. + * + * @param[in] fptr An IO which can have pending reads. + * @retval 0 The IO is empty. + * @retval 1 There is something buffered. + */ +int rb_io_read_pending(rb_io_t *fptr); + +/** + * Constructs an instance of ::rb_cStat from the passed information. + * + * @param[in] st A stat. + * @return Allocated new instance of ::rb_cStat. + */ +VALUE rb_stat_new(const struct stat *st); /* gc.c */ -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_IO_H */ diff --git a/ruby/include/ruby/io/buffer.h b/ruby/include/ruby/io/buffer.h new file mode 100644 index 000000000..907fec20b --- /dev/null +++ b/ruby/include/ruby/io/buffer.h @@ -0,0 +1,91 @@ +#ifndef RUBY_IO_BUFFER_T +#define RUBY_IO_BUFFER_T 1 +/** + * @file + * @author Samuel Williams + * @date Fri 2 Jul 2021 16:29:01 NZST + * @copyright Copyright (C) 2021 Samuel Williams + * @copyright 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. + */ + +#pragma once + +#include "ruby/ruby.h" +#include "ruby/internal/config.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +// WARNING: This entire interface is experimental and may change in the future! +#define RB_IO_BUFFER_EXPERIMENTAL 1 + +RUBY_EXTERN VALUE rb_cIOBuffer; +RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE; +RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE; + +enum rb_io_buffer_flags { + // The memory in the buffer is owned by someone else. + // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it. + RB_IO_BUFFER_EXTERNAL = 1, + // The memory in the buffer is allocated internally. + RB_IO_BUFFER_INTERNAL = 2, + // The memory in the buffer is mapped. + // A non-private mapping is marked as external. + RB_IO_BUFFER_MAPPED = 4, + + // The buffer is locked and cannot be resized. + // More specifically, it means we can't change the base address or size. + // A buffer is typically locked before a system call that uses the data. + RB_IO_BUFFER_LOCKED = 32, + + // The buffer mapping is private and will not impact other processes or the underlying file. + RB_IO_BUFFER_PRIVATE = 64, + + // The buffer is read-only and cannot be modified. + RB_IO_BUFFER_READONLY = 128 +}; + +enum rb_io_buffer_endian { + RB_IO_BUFFER_LITTLE_ENDIAN = 4, + RB_IO_BUFFER_BIG_ENDIAN = 8, + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, +#elif REG_DWORD == REG_DWORD_LITTLE_ENDIAN + RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, +#elif REG_DWORD == REG_DWORD_BIG_ENDIAN + RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, +#endif + + RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN +}; + +VALUE rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags); +VALUE rb_io_buffer_map(VALUE io, size_t size, off_t offset, enum rb_io_buffer_flags flags); + +VALUE rb_io_buffer_lock(VALUE self); +VALUE rb_io_buffer_unlock(VALUE self); +int rb_io_buffer_try_unlock(VALUE self); +VALUE rb_io_buffer_free(VALUE self); + +int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size); +void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size); +void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size); + +VALUE rb_io_buffer_transfer(VALUE self); +void rb_io_buffer_resize(VALUE self, size_t size); +void rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length); + +// The length is the minimum required length. +VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length); +VALUE rb_io_buffer_pread(VALUE self, VALUE io, size_t length, off_t offset); +VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length); +VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, size_t length, off_t offset); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_IO_BUFFER_T */ diff --git a/ruby/include/ruby/memory_view.h b/ruby/include/ruby/memory_view.h new file mode 100644 index 000000000..83931038a --- /dev/null +++ b/ruby/include/ruby/memory_view.h @@ -0,0 +1,325 @@ +#ifndef RUBY_MEMORY_VIEW_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_MEMORY_VIEW_H 1 +/** + * @file + * @author Ruby developers + * @copyright 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. + * @brief Memory View. + */ + +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include /* size_t */ +#endif + +#if HAVE_SYS_TYPES_H +# include /* ssize_t */ +#endif + +#include "ruby/internal/attr/pure.h" /* RBIMPL_ATTR_PURE */ +#include "ruby/internal/core/rtypeddata.h" /* rb_data_type_t */ +#include "ruby/internal/dllexport.h" /* RUBY_EXTERN */ +#include "ruby/internal/stdbool.h" /* bool */ +#include "ruby/internal/value.h" /* VALUE */ + +/** + * Flags passed to rb_memory_view_get(), then to ::rb_memory_view_get_func_t. + */ +enum ruby_memory_view_flags { + RUBY_MEMORY_VIEW_SIMPLE = 0, + RUBY_MEMORY_VIEW_WRITABLE = (1<<0), + RUBY_MEMORY_VIEW_FORMAT = (1<<1), + RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL = (1<<2), + RUBY_MEMORY_VIEW_STRIDES = (1<<3) | RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL, + RUBY_MEMORY_VIEW_ROW_MAJOR = (1<<4) | RUBY_MEMORY_VIEW_STRIDES, + RUBY_MEMORY_VIEW_COLUMN_MAJOR = (1<<5) | RUBY_MEMORY_VIEW_STRIDES, + RUBY_MEMORY_VIEW_ANY_CONTIGUOUS = RUBY_MEMORY_VIEW_ROW_MAJOR | RUBY_MEMORY_VIEW_COLUMN_MAJOR, + RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES, +}; + +/** Memory view component metadata. */ +typedef struct { + /** @see ::rb_memory_view_t::format */ + char format; + + /** :FIXME: what is a "native" size is unclear. */ + unsigned native_size_p: 1; + + /** Endian of the component */ + unsigned little_endian_p: 1; + + /** The component's offset. */ + size_t offset; + + /** The component's size. */ + size_t size; + + /** + * How many numbers of components are there. For instance "CCC"'s repeat is + * 3. + */ + size_t repeat; +} rb_memory_view_item_component_t; + +/** + * A MemoryView structure, `rb_memory_view_t`, is used for exporting objects' + * MemoryView. + * + * This structure contains the reference of the object, which is the owner of + * the MemoryView, the pointer to the head of exported memory, and the metadata + * that describes the structure of the memory. The metadata can describe + * multidimensional arrays with strides. + */ +typedef struct { + /** + * The original object that has the memory exported via this memory view. + */ + VALUE obj; + + /** The pointer to the exported memory. */ + void *data; + + /** The number of bytes in data. */ + ssize_t byte_size; + + /** true for readonly memory, false for writable memory. */ + bool readonly; + + /** + * A string to describe the format of an element, or NULL for unsigned bytes. + * The format string is a sequence of the following pack-template specifiers: + * + * c, C, s, s!, S, S!, n, v, i, i!, I, I!, l, l!, L, L!, + * N, V, f, e, g, q, q!, Q, Q!, d, E, G, j, J, x + * + * For example, "dd" for an element that consists of two double values, + * and "CCC" for an element that consists of three bytes, such as + * an RGB color triplet. + * + * Also, the value endianness can be explicitly specified by '<' or '>' + * following a value type specifier. + * + * The items are packed contiguously. When you emulate the alignment of + * structure members, put '|' at the beginning of the format string, + * like "|iqc". On x86_64 Linux ABI, the size of the item by this format + * is 24 bytes instead of 13 bytes. + */ + const char *format; + + /** + * The number of bytes in each element. + * item_size should equal to rb_memory_view_item_size_from_format(format). */ + ssize_t item_size; + + /** Description of each components. */ + struct { + /** + * The array of rb_memory_view_item_component_t that describes the + * item structure. rb_memory_view_prepare_item_desc and + * rb_memory_view_get_item allocate this memory if needed, + * and rb_memory_view_release frees it. */ + const rb_memory_view_item_component_t *components; + + /** The number of components in an item. */ + size_t length; + } item_desc; + + /** The number of dimension. */ + ssize_t ndim; + + /** + * ndim size array indicating the number of elements in each dimension. + * This can be NULL when ndim == 1. */ + const ssize_t *shape; + + /** + * ndim size array indicating the number of bytes to skip to go to the + * next element in each dimension. */ + const ssize_t *strides; + + /** + * The offset in each dimension when this memory view exposes a nested array. + * Or, NULL when this memory view exposes a flat array. */ + const ssize_t *sub_offsets; + + /** The private data for managing this exported memory */ + void *private_data; + + /** DO NOT TOUCH THIS: The memory view entry for the internal use */ + const struct rb_memory_view_entry *_memory_view_entry; +} rb_memory_view_t; + +/** Type of function of ::rb_memory_view_entry_t::get_func. */ +typedef bool (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags); + +/** Type of function of ::rb_memory_view_entry_t::release_func. */ +typedef bool (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view); + +/** Type of function of ::rb_memory_view_entry_t::available_p_func. */ +typedef bool (* rb_memory_view_available_p_func_t)(VALUE obj); + +/** Operations applied to a specific kind of a memory view. */ +typedef struct rb_memory_view_entry { + /** + * Exports a memory view from a Ruby object. + */ + rb_memory_view_get_func_t get_func; + + /** + * Releases a memory view that was previously generated using + * ::rb_memory_view_entry_t::get_func. + */ + rb_memory_view_release_func_t release_func; + + /** + * Queries if an object understands memory view protocol. + */ + rb_memory_view_available_p_func_t available_p_func; +} rb_memory_view_entry_t; + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* memory_view.c */ + +/** + * Associates the passed class with the passed memory view entry. This has to + * be called before actually creating a memory view from an instance. + */ +bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry); + +RBIMPL_ATTR_PURE() +/** + * Return `true` if the data in the MemoryView `view` is row-major contiguous. + * + * Return `false` otherwise. + */ +bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view); + +RBIMPL_ATTR_PURE() +/** + * Return `true` if the data in the MemoryView `view` is column-major + * contiguous. + * + * Return `false` otherwise. + */ +bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view); + +RBIMPL_ATTR_NOALIAS() +/** + * Fill the `strides` array with byte-Strides of a contiguous array of the + * given shape with the given element size. + */ +void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides); + +RBIMPL_ATTR_NOALIAS() +/** + * Fill the members of `view` as an 1-dimensional byte array. + */ +bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly); + +/** + * Deconstructs the passed format string, as describe in + * ::rb_memory_view_t::format. + */ +ssize_t rb_memory_view_parse_item_format(const char *format, + rb_memory_view_item_component_t **members, + size_t *n_members, const char **err); + +/** + * Calculate the number of bytes occupied by an element. + * + * When the calculation fails, the failed location in `format` is stored into + * `err`, and returns `-1`. + */ +ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err); + +/** + * Calculate the location of the item indicated by the given `indices`. + * + * The length of `indices` must equal to `view->ndim`. + * + * This function initializes `view->item_desc` if needed. + */ +void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices); + +/** + * Return a value that consists of item members. + * + * When an item is a single member, the return value is a single value. + * + * When an item consists of multiple members, an array will be returned. + */ +VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members); + +/** Fill the `item_desc` member of `view`. */ +void rb_memory_view_prepare_item_desc(rb_memory_view_t *view); + +/** * Return a value that consists of item members in the given memory view. */ +VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices); + +/** + * Return `true` if `obj` supports to export a MemoryView. Return `false` + * otherwise. + * + * If this function returns `true`, it doesn't mean the function + * `rb_memory_view_get` will succeed. + */ +bool rb_memory_view_available_p(VALUE obj); + +/** + * If the given `obj` supports to export a MemoryView that conforms the given + * `flags`, this function fills `view` by the information of the MemoryView and + * returns `true`. In this case, the reference count of `obj` is increased. + * + * If the given combination of `obj` and `flags` cannot export a MemoryView, + * this function returns `false`. The content of `view` is not touched in this + * case. + * + * The exported MemoryView must be released by `rb_memory_view_release` when + * the MemoryView is no longer needed. + */ +bool rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags); + +/** + * Release the given MemoryView `view` and decrement the reference count of + * `memory_view->obj`. + * + * Consumers must call this function when the MemoryView is no longer needed. + * Missing to call this function leads memory leak. + */ +bool rb_memory_view_release(rb_memory_view_t* memory_view); + +/* for testing */ +/** @cond INTERNAL_MACRO */ +RUBY_EXTERN VALUE rb_memory_view_exported_object_registry; +RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type; +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE() +/** + * Return `true` if the data in the MemoryView `view` is row-major or + * column-major contiguous. + * + * Return `false` otherwise. + */ +static inline bool +rb_memory_view_is_contiguous(const rb_memory_view_t *view) +{ + if (rb_memory_view_is_row_major_contiguous(view)) { + return true; + } + else if (rb_memory_view_is_column_major_contiguous(view)) { + return true; + } + else { + return false; + } +} + +#endif /* RUBY_BUFFER_H */ diff --git a/ruby/include/ruby/missing.h b/ruby/include/ruby/missing.h index 03657042c..1e97e294f 100644 --- a/ruby/include/ruby/missing.h +++ b/ruby/include/ruby/missing.h @@ -1,42 +1,45 @@ -/************************************************ - - missing.h - prototype for *.c in ./missing, and - for missing timeval struct - - $Author$ - created at: Sat May 11 23:46:03 JST 2002 - -************************************************/ - -#ifndef RUBY_MISSING_H +#ifndef RUBY_MISSING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_MISSING_H 1 +/** + * @author $Author$ + * @date Sat May 11 23:46:03 JST 2002 + * @copyright 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. + * @brief Prototype for *.c in ./missing, and for missing timeval struct. + */ +#include "ruby/internal/config.h" -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ +#ifdef STDC_HEADERS +# include #endif + +#if defined(__cplusplus) +# include +#else +# include /* for INFINITY and NAN */ #endif -#include "ruby/config.h" -#include -#include /* for INFINITY and NAN */ #ifdef RUBY_ALTERNATIVE_MALLOC_HEADER # include RUBY_ALTERNATIVE_MALLOC_HEADER #endif -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif -#if !defined(HAVE_STRUCT_TIMEVAL) || !defined(HAVE_STRUCT_TIMESPEC) #if defined(HAVE_TIME_H) # include #endif + #if defined(HAVE_SYS_TIME_H) # include #endif + +#ifdef HAVE_IEEEFP_H +# include #endif +#include "ruby/internal/dllexport.h" +#include "ruby/internal/attr/format.h" + #ifndef M_PI # define M_PI 3.14159265358979323846 #endif @@ -44,11 +47,6 @@ extern "C" { # define M_PI_2 (M_PI/2) #endif -#ifndef RUBY_SYMBOL_EXPORT_BEGIN -# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */ -# define RUBY_SYMBOL_EXPORT_END /* end */ -#endif - #if !defined(HAVE_STRUCT_TIMEVAL) struct timeval { time_t tv_sec; /* seconds */ @@ -57,6 +55,10 @@ struct timeval { #endif /* HAVE_STRUCT_TIMEVAL */ #if !defined(HAVE_STRUCT_TIMESPEC) +/* :BEWARE: @shyouhei warns that IT IS A WRONG IDEA to define our own version + * of struct timespec here. `clock_gettime` is a system call, and your kernel + * could expect something other than just `long` (results stack smashing if + * that happens). See also https://ewontfix.com/19/ */ struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ @@ -70,14 +72,7 @@ struct timezone { }; #endif -#ifdef RUBY_EXPORT -#undef RUBY_EXTERN -#endif -#ifndef RUBY_EXTERN -#define RUBY_EXTERN extern -#endif - -RUBY_SYMBOL_EXPORT_BEGIN +RBIMPL_SYMBOL_EXPORT_BEGIN() #ifndef HAVE_ACOSH RUBY_EXTERN double acosh(double); @@ -89,10 +84,6 @@ RUBY_EXTERN double atanh(double); RUBY_EXTERN char *crypt(const char *, const char *); #endif -#ifndef HAVE_DUP2 -RUBY_EXTERN int dup2(int, int); -#endif - #ifndef HAVE_EACCESS RUBY_EXTERN int eaccess(const char*, int); #endif @@ -101,10 +92,6 @@ RUBY_EXTERN int eaccess(const char*, int); RUBY_EXTERN double round(double); /* numeric.c */ #endif -#ifndef HAVE_FINITE -RUBY_EXTERN int finite(double); -#endif - #ifndef HAVE_FLOCK RUBY_EXTERN int flock(int, int); #endif @@ -161,36 +148,9 @@ RUBY_EXTERN const union bytesequence4_or_float rb_nan; # define HUGE_VAL ((double)INFINITY) #endif -#ifndef isinf -# ifndef HAVE_ISINF -# if defined(HAVE_FINITE) && defined(HAVE_ISNAN) -# ifdef HAVE_IEEEFP_H -# include -# endif -# define isinf(x) (!finite(x) && !isnan(x)) -# elif defined(__cplusplus) && __cplusplus >= 201103L -# include // it must include constexpr bool isinf(double); -# else -RUBY_EXTERN int isinf(double); -# endif -# endif -#endif - -#ifndef isnan -# ifndef HAVE_ISNAN -# if defined(__cplusplus) && __cplusplus >= 201103L -# include // it must include constexpr bool isnan(double); -# else -RUBY_EXTERN int isnan(double); -# endif -# endif -#endif - -#ifndef isfinite -# ifndef HAVE_ISFINITE -# define HAVE_ISFINITE 1 -# define isfinite(x) finite(x) -# endif +#ifndef HAVE_FINITE +# define HAVE_FINITE 1 +# define finite(x) isfinite(x) #endif #ifndef HAVE_NAN @@ -238,17 +198,13 @@ RUBY_EXTERN size_t strlcpy(char *, const char*, size_t); RUBY_EXTERN size_t strlcat(char *, const char*, size_t); #endif -#ifndef HAVE_SIGNBIT -RUBY_EXTERN int signbit(double x); -#endif - #ifndef HAVE_FFS RUBY_EXTERN int ffs(int); #endif #ifdef BROKEN_CLOSE -#include -#include +# include +# include RUBY_EXTERN int ruby_getpeername(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_getsockname(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_shutdown(int, int); @@ -256,23 +212,18 @@ RUBY_EXTERN int ruby_close(int); #endif #ifndef HAVE_SETPROCTITLE +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) RUBY_EXTERN void setproctitle(const char *fmt, ...); #endif -#ifndef HAVE_EXPLICIT_BZERO +#ifdef HAVE_EXPLICIT_BZERO +# /* Take that. */ +#elif defined(SecureZeroMemory) +# define explicit_bzero(b, len) SecureZeroMemory(b, len) +#else RUBY_EXTERN void explicit_bzero(void *b, size_t len); -# if defined SecureZeroMemory -# define explicit_bzero(b, len) SecureZeroMemory(b, len) -# endif #endif -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_MISSING_H */ diff --git a/ruby/include/ruby/ractor.h b/ruby/include/ruby/ractor.h new file mode 100644 index 000000000..7811616f6 --- /dev/null +++ b/ruby/include/ruby/ractor.h @@ -0,0 +1,264 @@ +#ifndef RUBY_RACTOR_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_RACTOR_H 1 + +/** + * @file + * @author Koichi Sasada + * @date Tue Nov 17 16:39:15 2020 + * @copyright Copyright (C) 2020 Yukihiro Matsumoto + * @copyright 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. + */ +#include "internal/dllexport.h" /* RUBY_EXTERN is here */ +#include "internal/fl_type.h" /* FL_TEST_RAW is here */ +#include "internal/special_consts.h" /* RB_SPECIAL_CONSTS_P is here */ +#include "internal/stdbool.h" /* bool is here */ +#include "internal/value.h" /* VALUE is here */ + +/** Type that defines a ractor-local storage. */ +struct rb_ractor_local_storage_type { + + /** + * A function to mark a ractor-local storage. + * + * @param[out] ptr A ractor-local storage. + * @post Ruby objects inside of `ptr` are marked. + */ + void (*mark)(void *ptr); + + /** + * A function to destruct a ractor-local storage. + * + * @param[out] ptr A ractor-local storage. + * @post `ptr` is not a valid pointer. + */ + void (*free)(void *ptr); + // TODO: update +}; + +/** (Opaque) struct that holds a ractor-local storage key. */ +typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t; + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * `Ractor` class. + * + * @ingroup object + */ +RUBY_EXTERN VALUE rb_cRactor; + +/** + * Queries the standard input of the current Ractor that is calling this + * function. + * + * @return An IO. + * @note This can be different from the process-global one. + */ +VALUE rb_ractor_stdin(void); + +/** + * Queries the standard output of the current Ractor that is calling this + * function. + * + * @return An IO. + * @note This can be different from the process-global one. + */ +VALUE rb_ractor_stdout(void); + +/** + * Queries the standard error of the current Ractor that is calling this + * function. + * + * @return An IO. + * @note This can be different from the process-global one. + */ +VALUE rb_ractor_stderr(void); + +/** + * Assigns an IO to the standard input of the Ractor that is calling this + * function. + * + * @param[in] io An IO. + * @post `io` is the standard input of the current ractor. + * @post In case the calling Ractor is the main Ractor, it also updates + * the process global ::rb_stdin. + */ +void rb_ractor_stdin_set(VALUE io); + +/** + * Assigns an IO to the standard output of the Ractor that is calling this + * function. + * + * @param[in] io An IO. + * @post `io` is the standard input of the current ractor. + * @post In case the calling Ractor is the main Ractor, it also updates + * the process global ::rb_stdout. + */ +void rb_ractor_stdout_set(VALUE io); + +/** + * Assigns an IO to the standard error of the Ractor that is calling this + * function. + * + * @param[in] io An IO. + * @post `io` is the standard input of the current ractor. + * @post In case the calling Ractor is the main Ractor, it also updates + * the process global ::rb_stderr. + */ +void rb_ractor_stderr_set(VALUE io); + +/** + * Issues a new key. + * + * @return A newly issued ractor-local storage key. Keys issued using this + * key can be associated to a Ruby object per Ractor. + */ +rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void); + +/** + * Queries the key. + * + * @param[in] key A ractor-local storage key to lookup. + * @retval RUBY_Qnil No such key. + * @retval otherwise A value corresponds to `key` in the current Ractor. + * @note This cannot distinguish between a nonexistent key and a key + * exists and corresponds to ::RUBY_Qnil. + */ +VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key); + +/** + * Queries the key. + * + * @param[in] key A ractor-local storage key to lookup. + * @param[out] val Return value buffer. + * @retval false `key` not found. + * @retval true `key` found. + * @post `val` is updated so that it has the value corresponds to `key` + * in the current Ractor. + */ +bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val); + +/** + * Associates the passed value to the passed key. + * + * @param[in] key A ractor-local storage key. + * @param[in] val Arbitrary ruby object. + * @post `val` corresponds to `key` in the current Ractor. + */ +void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val); + +/** + * A type of ractor-local storage that destructs itself using ::ruby_xfree. + * + * @internal + * + * Why it is visible from 3rd party extension libraries is not obvious to + * @shyouhei. + */ +RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free; + +/** @alias{rb_ractor_local_storage_type_free} */ +#define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free) + +/** + * Extended version of rb_ractor_local_storage_value_newkey(). It additionally + * takes the type of the issuing key. + * + * @param[in] type How the value associated with the issuing key should + * behave. + * @return A newly issued ractor-local storage key, of type `type`. + */ +rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type); + +/** + * Identical to rb_ractor_local_storage_value() except the return type. + * + * @param[in] key A ractor-local storage key to lookup. + * @retval NULL No such key. + * @retval otherwise A value corresponds to `key` in the current Ractor. + */ +void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key); + +/** + * Identical to rb_ractor_local_storage_value_set() except the parameter type. + * + * @param[in] key A ractor-local storage key. + * @param[in] ptr A pointer that conforms `key`'s type. + * @post `ptr` corresponds to `key` in the current Ractor. + */ +void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr); + +/** + * Destructively transforms the passed object so that multiple Ractors can + * share it. What is a shareable object and what is not is a nuanced concept, + * and @ko1 says the definition can still change. However extension library + * authors might interest to learn how to use #RUBY_TYPED_FROZEN_SHAREABLE. + * + * @param[out] obj Arbitrary ruby object to modify. + * @exception rb_eRactorError Ractors cannot share `obj` by nature. + * @return Passed `obj`. + * @post Multiple Ractors can share `obj`. + * + * @internal + * + * In case an exception is raised, `obj` remains in an intermediate state where + * some of its part is frozen and others are not. @shyouhei is not sure if it + * is either an intended behaviour, current implementation limitation, or + * simply a bug. Note also that there is no way to "melt" a frozen object. + */ +VALUE rb_ractor_make_shareable(VALUE obj); + +/** + * Identical to rb_ractor_make_shareable(), except it returns a (deep) copy of + * the passed one instead of modifying it in-place. + * + * @param[in] obj Arbitrary ruby object to duplicate. + * @exception rb_eRactorError Ractors cannot share `obj` by nature. + * @return A deep copy of `obj` which is sharable among Ractors. + */ +VALUE rb_ractor_make_shareable_copy(VALUE obj); + +RBIMPL_SYMBOL_EXPORT_END() + +/** + * Queries if the passed object has previously classified as shareable or not. + * This doesn't mean anything in practice... Objects can be shared later. + * Always use rb_ractor_shareable_p() instead. + * + * @param[in] obj Object in question. + * @retval RUBY_FL_SHAREABLE It once was shareable before. + * @retval 0 Otherwise. + */ +#define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE) + +/** + * Queries if multiple Ractors can share the passed object or not. Ractors run + * without protecting each other. Sharing an object among them is basically + * dangerous, disabled by default. However there are objects that are + * extremely carefully implemented to be Ractor-safe; for instance integers + * have such property. This function can classify that. + * + * @param[in] obj Arbitrary ruby object. + * @retval true `obj` is capable of shared across ractors. + * @retval false `obj` cannot travel across ractor boundaries. + */ +static inline bool +rb_ractor_shareable_p(VALUE obj) +{ + bool rb_ractor_shareable_p_continue(VALUE obj); + + if (RB_SPECIAL_CONST_P(obj)) { + return true; + } + else if (RB_OBJ_SHAREABLE_P(obj)) { + return true; + } + else { + return rb_ractor_shareable_p_continue(obj); + } +} + +#endif /* RUBY_RACTOR_H */ diff --git a/ruby/include/ruby/random.h b/ruby/include/ruby/random.h new file mode 100644 index 000000000..657b37f03 --- /dev/null +++ b/ruby/include/ruby/random.h @@ -0,0 +1,304 @@ +#ifndef RUBY_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_RANDOM_H 1 +/** + * @file + * @date Sat May 7 11:51:14 JST 2016 + * @copyright 2007-2020 Yukihiro Matsumoto + * @copyright 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. + * + * This is a set of APIs to roll your own subclass of ::rb_cRandom. An + * illustrative example of such PRNG can be found at + * `ext/-test-/ramdom/loop.c`. + */ + +#include "ruby/ruby.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Base components of the random interface. + * + * @internal + * + * Ideally this could be an empty class if we could assume C++, but in C a + * struct must have at least one field. + */ +struct rb_random_struct { + /** Seed, passed through e.g. `Random.new` */ + VALUE seed; +}; +typedef struct rb_random_struct rb_random_t; /**< @see ::rb_random_struct */ + +RBIMPL_ATTR_NONNULL(()) +/** + * This is the type of functions called when your random object is initialised. + * Passed buffer is the seed object basically. But in Ruby a number can be + * really big. This type of functions accept such big integers as a series of + * machine words. + * + * @param[out] rng Your random struct to fill in. + * @param[in] buf Seed, maybe converted from a bignum. + * @param[in] len Number of words of `buf`. + * @post `rng` is initialised using the passed seeds. + */ +typedef void rb_random_init_func(rb_random_t *rng, const uint32_t *buf, size_t len); + +RBIMPL_ATTR_NONNULL(()) +/** + * This is the type of functions called from your object's `#rand` method. + * + * @param[out] rng Your random struct to extract an integer from. + * @return A random number. + * @post `rng` is consumed somehow. + */ +typedef unsigned int rb_random_get_int32_func(rb_random_t *rng); + +RBIMPL_ATTR_NONNULL(()) +/** + * This is the type of functions called from your object's `#bytes` method. + * + * @param[out] rng Your random struct to extract an integer from. + * @param[out] buf Return buffer of at least `len` bytes length. + * @param[in] len Number of bytes of `buf`. + * @post `rng` is consumed somehow. + * @post `buf` is filled with random bytes. + */ +typedef void rb_random_get_bytes_func(rb_random_t *rng, void *buf, size_t len); + +RBIMPL_ATTR_NONNULL(()) +/** + * This is the type of functions called from your object's `#rand` method. + * + * @param[out] rng Your random struct to extract an integer from. + * @param[in] excl Pass nonzero value here to indicate you don't want 1.0. + * @return A random number of range 0.0 to 1.0. + * @post `rng` is consumed somehow. + */ +typedef double rb_random_get_real_func(rb_random_t *rng, int excl); + +/** PRNG algorithmic interface, analogous to Ruby level classes. */ +typedef struct { + /** Number of bits of seed numbers. */ + size_t default_seed_bits; + + /** Initialiser function. */ + rb_random_init_func *init; + + /** Function to obtain a random integer. */ + rb_random_get_int32_func *get_int32; + + /** + * Function to obtain a series of random bytes. If your PRNG have a native + * method to yield arbitrary number of bytes use that to implement this. + * But in case you lack such things, you can do so by using + * rb_rand_bytes_int32() + * + * ```CXX + * extern rb_random_get_int32_func your_get_int32_func; + * + * void + * your_get_byes_func(rb_random_t *rng, void *buf, size_t len) + * { + * rb_rand_bytes_int32(your_get_int32_func, rng, buf, len); + * } + * ``` + */ + rb_random_get_bytes_func *get_bytes; + + /** + * Function to obtain a random double. If your PRNG have a native method + * to yield a floating point random number use that to implement this. But + * in case you lack such things, you can do so by using + * rb_int_pair_to_real(). + * + * ```CXX + * extern rb_random_get_int32_func your_get_int32_func; + * + * void + * your_get_real_func(rb_random_t *rng, int excl) + * { + * auto a = your_get_int32_func(rng); + * auto b = your_get_int32_func(rng); + * return rb_int_pair_to_real(a, b, excl); + * } + * ``` + */ + rb_random_get_real_func *get_real; +} rb_random_interface_t; + +/** + * This utility macro defines 3 functions named prefix_init, prefix_get_int32, + * prefix_get_bytes. + */ +#define RB_RANDOM_INTERFACE_DECLARE(prefix) \ + static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \ + static unsigned int prefix##_get_int32(rb_random_t *); \ + static void prefix##_get_bytes(rb_random_t *, void *, size_t) + +/** + * Identical to #RB_RANDOM_INTERFACE_DECLARE except it also declares + * prefix_get_real. + */ +#define RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(prefix) \ + RB_RANDOM_INTERFACE_DECLARE(prefix); \ + static double prefix##_get_real(rb_random_t *, int) + +/** + * This utility macro expands to the names declared using + * #RB_RANDOM_INTERFACE_DECLARE. Expected to be used inside of a + * ::rb_random_interface_t initialiser: + * + * ```CXX + * RB_RANDOM_INTERFACE_DECLARE(foo); + * + * static inline constexpr rb_random_interface_t foo_interface = { + * 32768, // bits + * RB_RANDOM_INTERFACE_DEFINE(foo), + * }; + * ``` + */ +#define RB_RANDOM_INTERFACE_DEFINE(prefix) \ + prefix##_init, \ + prefix##_get_int32, \ + prefix##_get_bytes + +/** + * Identical to #RB_RANDOM_INTERFACE_DEFINE except it also defines + * prefix_get_real. + */ +#define RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(prefix) \ + RB_RANDOM_INTERFACE_DEFINE(prefix), \ + prefix##_get_real + +#if defined _WIN32 && !defined __CYGWIN__ +typedef rb_data_type_t rb_random_data_type_t; +# define RB_RANDOM_PARENT 0 +#else + +/** This is the type of ::rb_random_data_type. */ +typedef const rb_data_type_t rb_random_data_type_t; + +/** + * This utility macro can be used when you define your own PRNG type: + * + * ```CXX + * static inline constexpr rb_random_interface_t your_if = { + * 0, RB_RANDOM_INTERFACE_DEFINE(your), + * }; + * + * static inline constexpr your_prng = { + * "your PRNG", + * { rb_random_mark, }, + * RB_RANDOM_PARENT, // <<-- HERE + * &your_if, + * 0, + * } + * ``` + */ +# define RB_RANDOM_PARENT &rb_random_data_type +#endif + +/** + * This macro is expected to be called exactly once at the beginning of a + * program, possibly from inside of your `Init_Foo()` function. Depending on + * platforms #RB_RANDOM_PARENT can require a fixup. This routine does that + * when necessary. + */ +#define RB_RANDOM_DATA_INIT_PARENT(random_data) \ + rbimpl_random_data_init_parent(&random_data) + +/** + * This is the implementation of ::rb_data_type_struct::dmark for + * ::rb_random_data_type. In case your PRNG does not involve Ruby objects at + * all (which is quite likely), you can simply reuse it. + * + * @param[out] ptr Target to mark, which is a ::rb_random_t this case. + */ +void rb_random_mark(void *ptr); + +/** + * Initialises an allocated ::rb_random_t instance. Call it from your own + * initialiser appropriately. + * + * @param[out] rnd Your PRNG's base part. + * @post `rnd` is filled with an initial state. + */ +void rb_random_base_init(rb_random_t *rnd); + +/** + * Generates a 64 bit floating point number by concatenating two 32bit unsigned + * integers. + * + * @param[in] a Most significant 32 bits of the result. + * @param[in] b Least significant 32 bits of the result. + * @param[in] excl Whether the result should exclude 1.0 or not. + * @return A double, whose range is either `[0, 1)` or `[0, 1]`. + * @see ::rb_random_interface_t::get_real() + * + * @internal + * + * This in fact has nothing to do with PRNGs. + */ +double rb_int_pair_to_real(uint32_t a, uint32_t b, int excl); + +/** + * Repeatedly calls the passed function over and over again until the passed + * buffer is filled with random bytes. + * + * @param[in] func Generator function. + * @param[out] prng Passed as-is to `func`. + * @param[out] buff Return buffer. + * @param[in] size Number of words of `buff`. + * @post `buff` is filled with random bytes. + * @post `prng` is updated by `func`. + * @see ::rb_random_interface_t::get_bytes() + */ +void rb_rand_bytes_int32(rb_random_get_int32_func *func, rb_random_t *prng, void *buff, size_t size); + +/** + * The data that holds the backend type of ::rb_cRandom. Used as your PRNG's + * ::rb_data_type_struct::parent. + */ +RUBY_EXTERN const rb_data_type_t rb_random_data_type; + +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ +/** + * Queries the interface of the passed random object. + * + * @param[in] obj An instance (of a subclass) of ::rb_cRandom. + * @return Its corresponding ::rb_random_interface_t interface. + */ +static inline const rb_random_interface_t * +rb_rand_if(VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj)); + const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj); + const void *ret = t->data; + return RBIMPL_CAST((const rb_random_interface_t *)ret); +} + +RBIMPL_ATTR_NOALIAS() +/** + * @private + * + * This is an implementation detail of #RB_RANDOM_DATA_INIT_PARENT. People + * don't use it directly. + * + * @param[out] random_data Region to fill. + * @post ::rb_random_data_type is filled appropriately. + */ +static inline void +rbimpl_random_data_init_parent(rb_random_data_type_t *random_data) +{ +#if defined _WIN32 && !defined __CYGWIN__ + random_data->parent = &rb_random_data_type; +#endif +} + +#endif /* RUBY_RANDOM_H */ diff --git a/ruby/include/ruby/re.h b/ruby/include/ruby/re.h index 7102c7ace..3892d6e7f 100644 --- a/ruby/include/ruby/re.h +++ b/ruby/include/ruby/re.h @@ -1,71 +1,147 @@ -/********************************************************************** - - re.h - - - $Author$ - created at: Thu Sep 30 14:18:32 JST 1993 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_RE_H +#ifndef RUBY_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RE_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif +/** + * @file + * @author $Author$ + * @date Thu Sep 30 14:18:32 JST 1993 + * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto + * @copyright 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. + */ +#include "ruby/internal/config.h" + +#ifdef HAVE_SYS_TYPES_H +# include #endif -#include #include #include "ruby/regex.h" - -RUBY_SYMBOL_EXPORT_BEGIN - -typedef struct re_pattern_buffer Regexp; - -struct rmatch_offset { - long beg; - long end; -}; - -struct rmatch { - struct re_registers regs; - - struct rmatch_offset *char_offset; - int char_offset_num_allocated; -}; - -struct RMatch { - struct RBasic basic; - VALUE str; - struct rmatch *rmatch; - VALUE regexp; /* RRegexp */ -}; - -#define RMATCH(obj) (R_CAST(RMatch)(obj)) -#define RMATCH_REGS(obj) (&(R_CAST(RMatch)(obj))->rmatch->regs) - -VALUE rb_reg_regcomp(VALUE); -long rb_reg_search(VALUE, VALUE, long, int); -VALUE rb_reg_regsub(VALUE, VALUE, struct re_registers *, VALUE); -long rb_reg_adjust_startpos(VALUE, VALUE, long, int); -void rb_match_busy(VALUE); -VALUE rb_reg_quote(VALUE); +#include "ruby/internal/core/rmatch.h" +#include "ruby/internal/dllexport.h" + +struct re_registers; /* Defined in onigmo.h */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * Creates a new instance of ::rb_cRegexp. It can be seen as a specialised + * version of rb_reg_new_str() where it does not take options. + * + * @param[in] str Source code in String. + * @return Allocated new instance of ::rb_cRegexp. + */ +VALUE rb_reg_regcomp(VALUE str); + +/** + * Runs the passed regular expression over the passed string. Unlike + * rb_reg_search() this function also takes position and direction of the + * search, which make it possible for this function to run from in middle of + * the string. + * + * @param[in] re Regular expression to execute. + * @param[in] str Target string to search. + * @param[in] pos Offset in `str` to start searching, in bytes. + * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for + * the opposite. + * @exception rb_eArgError `re` is broken. + * @exception rb_eRegexpError `re` is malformed. + * @retval -1 Match failed. + * @retval otherwise Offset of first such byte where match happened. + * @post `Regexp.last_match` is updated. + * @post `$&`, `$~`, etc., are updated. + * + * @internal + * + * Distinction between raising ::rb_eArgError and ::rb_eRegexpError is not + * obvious, at least to @shyouhei. + */ +long rb_reg_search(VALUE re, VALUE str, long pos, int dir); + +/** + * Substitution. This is basically the implementation of `String#sub`. Also + * `String#gsub` repeatedly calls this function. + * + * @param[in] repl Replacement string, e.g. `"\\1\\2"` + * @param[in] src Source string, to be replaced. + * @param[in] regs Matched data generated by applying `rexp` to `src`. + * @param[in] rexp Regular expression. + * @return A substituted string. + * + * @internal + * + * This function does not check for encoding compatibility. `String#sub!` + * etc. employ their own checker. + * + * `regs` should have been `const struct re_registers *` because it is read + * only. Kept as-is for compatibility. + */ +VALUE rb_reg_regsub(VALUE repl, VALUE src, struct re_registers *regs, VALUE rexp); + +/** + * Tell us if this is a wrong idea, but it seems this function has no usage at + * all. Just remains here for theoretical backwards compatibility. + * + * @param[in] re Regular expression to execute. + * @param[in] str Target string to search. + * @param[in] pos Offset in `str` to start searching, in bytes. + * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for + * the opposite. + * @return Adjusted nearest offset to `pos` inside of `str`, where is a + * character boundary. + * + */ +long rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int dir); + +/** + * Escapes any characters that would have special meaning in a regular + * expression. + * + * @param[in] str Target string to escape. + * @return A copy of `str` whose contents are escaped. + */ +VALUE rb_reg_quote(VALUE str); + +/** + * Exercises various checks and preprocesses so that the given regular + * expression can be applied to the given string. The preprocess here includes + * (but not limited to) for instance encoding conversion. + * + * @param[in] re Target regular expression. + * @param[in] str What `re` is about to run on. + * @exception rb_eArgError `re` does not fit for `str`. + * @exception rb_eEncCompatError `re` and `str` are incompatible. + * @exception rb_eRegexpError `re` is malformed. + * @return A preprocessesed pattern buffer ready to be applied to `str`. + * @note The return value is manages by our GC. Don't free. + * + * @internal + * + * The return type, `regex_t *`, is defined in ``, _and_ + * _conflicts_ with POSIX's ``. We can no longer save the situation + * at this point. Just don't mix the two. + */ regex_t *rb_reg_prepare_re(VALUE re, VALUE str); -int rb_reg_region_copy(struct re_registers *, const struct re_registers *); - -RUBY_SYMBOL_EXPORT_END -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +/** + * Duplicates a match data. This is roughly the same as `onig_region_copy()`, + * except it tries to GC when there is not enough memory. + * + * @param[out] dst Target registers to fill. + * @param[in] src Source registers to duplicate. + * @exception rb_eNoMemError Not enough memory. + * @retval 0 Successful + * @retval ONIGERR_MEMORY Not enough memory, even after GC (unlikely). + * @post `dst` has identical contents to `src`. + * + * @internal + * + * It seems this function is here for `ext/strscan` and nothing else. + */ +int rb_reg_region_copy(struct re_registers *dst, const struct re_registers *src); + +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RE_H */ diff --git a/ruby/include/ruby/regex.h b/ruby/include/ruby/regex.h index 024bed4a4..53278173f 100644 --- a/ruby/include/ruby/regex.h +++ b/ruby/include/ruby/regex.h @@ -1,16 +1,13 @@ -/********************************************************************** - - regex.h - - - $Author$ - - Copyright (C) 1993-2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef ONIGURUMA_REGEX_H +#ifndef ONIGURUMA_REGEX_H /*-*-C++-*-vi:se ft=cpp:*/ #define ONIGURUMA_REGEX_H 1 - +/** + * @author $Author$ + * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto + * @copyright 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. + */ #if defined(__cplusplus) extern "C" { #if 0 diff --git a/ruby/include/ruby/ruby.h b/ruby/include/ruby/ruby.h index 9b7c9842f..f35d13685 100644 --- a/ruby/include/ruby/ruby.h +++ b/ruby/include/ruby/ruby.h @@ -1,1856 +1,109 @@ -/********************************************************************** - - ruby/ruby.h - - - $Author$ - created at: Thu Jun 10 14:26:32 JST 1993 - - Copyright (C) 1993-2008 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -#ifndef RUBY_RUBY_H -#define RUBY_RUBY_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#include "ruby/config.h" -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif - -#include "defines.h" -#include "ruby/assert.h" - -/* For MinGW, we need __declspec(dllimport) for RUBY_EXTERN on MJIT. - mswin's RUBY_EXTERN already has that. See also: win32/Makefile.sub */ -#if defined(MJIT_HEADER) && defined(_WIN32) && defined(__GNUC__) -# undef RUBY_EXTERN -# define RUBY_EXTERN extern __declspec(dllimport) -#endif - -#if defined(__cplusplus) -/* __builtin_choose_expr and __builtin_types_compatible aren't available - * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ -# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P -# undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P -#elif GCC_VERSION_BEFORE(4,8,6) /* Bug #14221 */ -# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P -#endif - -#ifndef ASSUME -# ifdef UNREACHABLE -# define ASSUME(x) (RB_LIKELY(!!(x)) ? (void)0 : UNREACHABLE) -# else -# define ASSUME(x) ((void)(x)) -# endif -#endif -#ifndef UNREACHABLE_RETURN -# ifdef UNREACHABLE -# define UNREACHABLE_RETURN(val) UNREACHABLE -# else -# define UNREACHABLE_RETURN(val) return (val) -# endif -#endif -#ifndef UNREACHABLE -# define UNREACHABLE ((void)0) /* unreachable */ -#endif - -#define RUBY_MACRO_SELECT(base, n) TOKEN_PASTE(base, n) - -#ifdef HAVE_INTRINSICS_H -# include -#endif - -#include - -RUBY_SYMBOL_EXPORT_BEGIN - -/* Make alloca work the best possible way. */ -#ifdef __GNUC__ -# ifndef alloca -# define alloca __builtin_alloca -# endif -#else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifdef _AIX -#pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -void *alloca(); -# endif -# endif /* AIX */ -# endif /* HAVE_ALLOCA_H */ -#endif /* __GNUC__ */ - -#if defined HAVE_UINTPTR_T && 0 -typedef uintptr_t VALUE; -typedef uintptr_t ID; -# define SIGNED_VALUE intptr_t -# define SIZEOF_VALUE SIZEOF_UINTPTR_T -# undef PRI_VALUE_PREFIX -#elif SIZEOF_LONG == SIZEOF_VOIDP -typedef unsigned long VALUE; -typedef unsigned long ID; -# define SIGNED_VALUE long -# define SIZEOF_VALUE SIZEOF_LONG -# define PRI_VALUE_PREFIX "l" -#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP -typedef unsigned LONG_LONG VALUE; -typedef unsigned LONG_LONG ID; -# define SIGNED_VALUE LONG_LONG -# define LONG_LONG_VALUE 1 -# define SIZEOF_VALUE SIZEOF_LONG_LONG -# define PRI_VALUE_PREFIX PRI_LL_PREFIX -#else -# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- -#endif - -typedef char ruby_check_sizeof_int[SIZEOF_INT == sizeof(int) ? 1 : -1]; -typedef char ruby_check_sizeof_long[SIZEOF_LONG == sizeof(long) ? 1 : -1]; -#ifdef HAVE_LONG_LONG -typedef char ruby_check_sizeof_long_long[SIZEOF_LONG_LONG == sizeof(LONG_LONG) ? 1 : -1]; -#endif -typedef char ruby_check_sizeof_voidp[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1]; - -#ifndef PRI_INT_PREFIX -#define PRI_INT_PREFIX "" -#endif -#ifndef PRI_LONG_PREFIX -#define PRI_LONG_PREFIX "l" -#endif -#ifndef PRI_SHORT_PREFIX -#define PRI_SHORT_PREFIX "h" -#endif - -#ifndef PRI_64_PREFIX -#if SIZEOF_LONG == 8 -#define PRI_64_PREFIX PRI_LONG_PREFIX -#elif SIZEOF_LONG_LONG == 8 -#define PRI_64_PREFIX PRI_LL_PREFIX -#endif -#endif - -#ifndef PRIdPTR -#define PRIdPTR PRI_PTR_PREFIX"d" -#define PRIiPTR PRI_PTR_PREFIX"i" -#define PRIoPTR PRI_PTR_PREFIX"o" -#define PRIuPTR PRI_PTR_PREFIX"u" -#define PRIxPTR PRI_PTR_PREFIX"x" -#define PRIXPTR PRI_PTR_PREFIX"X" -#endif - -#define RUBY_PRI_VALUE_MARK "\v" -#if defined PRIdPTR && !defined PRI_VALUE_PREFIX -#define PRIdVALUE PRIdPTR -#define PRIoVALUE PRIoPTR -#define PRIuVALUE PRIuPTR -#define PRIxVALUE PRIxPTR -#define PRIXVALUE PRIXPTR -#define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK -#else -#define PRIdVALUE PRI_VALUE_PREFIX"d" -#define PRIoVALUE PRI_VALUE_PREFIX"o" -#define PRIuVALUE PRI_VALUE_PREFIX"u" -#define PRIxVALUE PRI_VALUE_PREFIX"x" -#define PRIXVALUE PRI_VALUE_PREFIX"X" -#define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK -#endif -#ifndef PRI_VALUE_PREFIX -# define PRI_VALUE_PREFIX "" -#endif - -#ifndef PRI_TIMET_PREFIX -# if SIZEOF_TIME_T == SIZEOF_INT -# define PRI_TIMET_PREFIX -# elif SIZEOF_TIME_T == SIZEOF_LONG -# define PRI_TIMET_PREFIX "l" -# elif SIZEOF_TIME_T == SIZEOF_LONG_LONG -# define PRI_TIMET_PREFIX PRI_LL_PREFIX -# endif -#endif - -#if defined PRI_PTRDIFF_PREFIX -#elif SIZEOF_PTRDIFF_T == SIZEOF_INT -# define PRI_PTRDIFF_PREFIX "" -#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG -# define PRI_PTRDIFF_PREFIX "l" -#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG -# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX -#endif -#define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d" -#define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i" -#define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o" -#define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u" -#define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x" -#define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X" - -#if defined PRI_SIZE_PREFIX -#elif SIZEOF_SIZE_T == SIZEOF_INT -# define PRI_SIZE_PREFIX "" -#elif SIZEOF_SIZE_T == SIZEOF_LONG -# define PRI_SIZE_PREFIX "l" -#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG -# define PRI_SIZE_PREFIX PRI_LL_PREFIX -#endif -#define PRIdSIZE PRI_SIZE_PREFIX"d" -#define PRIiSIZE PRI_SIZE_PREFIX"i" -#define PRIoSIZE PRI_SIZE_PREFIX"o" -#define PRIuSIZE PRI_SIZE_PREFIX"u" -#define PRIxSIZE PRI_SIZE_PREFIX"x" -#define PRIXSIZE PRI_SIZE_PREFIX"X" - -#ifdef __STDC__ -# include -#else -# ifndef LONG_MAX -# ifdef HAVE_LIMITS_H -# include -# else - /* assuming 32bit(2's complement) long */ -# define LONG_MAX 2147483647 -# endif -# endif -# ifndef LONG_MIN -# define LONG_MIN (-LONG_MAX-1) -# endif -# ifndef CHAR_BIT -# define CHAR_BIT 8 -# endif -#endif - -#ifdef HAVE_LONG_LONG -# ifndef LLONG_MAX -# ifdef LONG_LONG_MAX -# define LLONG_MAX LONG_LONG_MAX -# else -# ifdef _I64_MAX -# define LLONG_MAX _I64_MAX -# else - /* assuming 64bit(2's complement) long long */ -# define LLONG_MAX 9223372036854775807LL -# endif -# endif -# endif -# ifndef LLONG_MIN -# ifdef LONG_LONG_MIN -# define LLONG_MIN LONG_LONG_MIN -# else -# ifdef _I64_MIN -# define LLONG_MIN _I64_MIN -# else -# define LLONG_MIN (-LLONG_MAX-1) -# endif -# endif -# endif -#endif - -#define RUBY_FIXNUM_MAX (LONG_MAX>>1) -#define RUBY_FIXNUM_MIN RSHIFT((long)LONG_MIN,1) -#define FIXNUM_MAX RUBY_FIXNUM_MAX -#define FIXNUM_MIN RUBY_FIXNUM_MIN - -#define RB_INT2FIX(i) (((VALUE)(i))<<1 | RUBY_FIXNUM_FLAG) -#define INT2FIX(i) RB_INT2FIX(i) -#define RB_LONG2FIX(i) RB_INT2FIX(i) -#define LONG2FIX(i) RB_INT2FIX(i) -#define rb_fix_new(v) RB_INT2FIX(v) -VALUE rb_int2inum(intptr_t); - -#define rb_int_new(v) rb_int2inum(v) -VALUE rb_uint2inum(uintptr_t); - -#define rb_uint_new(v) rb_uint2inum(v) - -#ifdef HAVE_LONG_LONG -VALUE rb_ll2inum(LONG_LONG); -#define LL2NUM(v) rb_ll2inum(v) -VALUE rb_ull2inum(unsigned LONG_LONG); -#define ULL2NUM(v) rb_ull2inum(v) -#endif - -#ifndef OFFT2NUM -#if SIZEOF_OFF_T > SIZEOF_LONG && defined(HAVE_LONG_LONG) -# define OFFT2NUM(v) LL2NUM(v) -#elif SIZEOF_OFF_T == SIZEOF_LONG -# define OFFT2NUM(v) LONG2NUM(v) -#else -# define OFFT2NUM(v) INT2NUM(v) -#endif -#endif - -#if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG) -# define SIZET2NUM(v) ULL2NUM(v) -# define SSIZET2NUM(v) LL2NUM(v) -#elif SIZEOF_SIZE_T == SIZEOF_LONG -# define SIZET2NUM(v) ULONG2NUM(v) -# define SSIZET2NUM(v) LONG2NUM(v) -#else -# define SIZET2NUM(v) UINT2NUM(v) -# define SSIZET2NUM(v) INT2NUM(v) -#endif - -#ifndef SIZE_MAX -# if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG) -# define SIZE_MAX ULLONG_MAX -# define SIZE_MIN ULLONG_MIN -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define SIZE_MAX ULONG_MAX -# define SIZE_MIN ULONG_MIN -# elif SIZEOF_SIZE_T == SIZEOF_INT -# define SIZE_MAX UINT_MAX -# define SIZE_MIN UINT_MIN -# else -# define SIZE_MAX USHRT_MAX -# define SIZE_MIN USHRT_MIN -# endif -#endif - -#ifndef SSIZE_MAX -# if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG) -# define SSIZE_MAX LLONG_MAX -# define SSIZE_MIN LLONG_MIN -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define SSIZE_MAX LONG_MAX -# define SSIZE_MIN LONG_MIN -# elif SIZEOF_SIZE_T == SIZEOF_INT -# define SSIZE_MAX INT_MAX -# define SSIZE_MIN INT_MIN -# else -# define SSIZE_MAX SHRT_MAX -# define SSIZE_MIN SHRT_MIN -# endif -#endif - -#if SIZEOF_INT < SIZEOF_VALUE -NORETURN(void rb_out_of_int(SIGNED_VALUE num)); -#endif - -#if SIZEOF_INT < SIZEOF_LONG -static inline int -rb_long2int_inline(long n) -{ - int i = (int)n; - if ((long)i != n) - rb_out_of_int(n); - - return i; -} -#define rb_long2int(n) rb_long2int_inline(n) -#else -#define rb_long2int(n) ((int)(n)) -#endif - -#ifndef PIDT2NUM -#define PIDT2NUM(v) LONG2NUM(v) -#endif -#ifndef NUM2PIDT -#define NUM2PIDT(v) NUM2LONG(v) -#endif -#ifndef UIDT2NUM -#define UIDT2NUM(v) LONG2NUM(v) -#endif -#ifndef NUM2UIDT -#define NUM2UIDT(v) NUM2LONG(v) -#endif -#ifndef GIDT2NUM -#define GIDT2NUM(v) LONG2NUM(v) -#endif -#ifndef NUM2GIDT -#define NUM2GIDT(v) NUM2LONG(v) -#endif -#ifndef NUM2MODET -#define NUM2MODET(v) NUM2INT(v) -#endif -#ifndef MODET2NUM -#define MODET2NUM(v) INT2NUM(v) -#endif - -#define RB_FIX2LONG(x) ((long)RSHIFT((SIGNED_VALUE)(x),1)) -static inline long -rb_fix2long(VALUE x) -{ - return RB_FIX2LONG(x); -} -#define RB_FIX2ULONG(x) ((unsigned long)RB_FIX2LONG(x)) -static inline unsigned long -rb_fix2ulong(VALUE x) -{ - return RB_FIX2ULONG(x); -} -#define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG) -#define RB_POSFIXABLE(f) ((f) < RUBY_FIXNUM_MAX+1) -#define RB_NEGFIXABLE(f) ((f) >= RUBY_FIXNUM_MIN) -#define RB_FIXABLE(f) (RB_POSFIXABLE(f) && RB_NEGFIXABLE(f)) -#define FIX2LONG(x) RB_FIX2LONG(x) -#define FIX2ULONG(x) RB_FIX2ULONG(x) -#define FIXNUM_P(f) RB_FIXNUM_P(f) -#define POSFIXABLE(f) RB_POSFIXABLE(f) -#define NEGFIXABLE(f) RB_NEGFIXABLE(f) -#define FIXABLE(f) RB_FIXABLE(f) - -#define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK) -#define IMMEDIATE_P(x) RB_IMMEDIATE_P(x) - -ID rb_sym2id(VALUE); -VALUE rb_id2sym(ID); -#define RB_STATIC_SYM_P(x) (((VALUE)(x)&~((~(VALUE)0)<= SIZEOF_DOUBLE -#define USE_FLONUM 1 -#else -#define USE_FLONUM 0 -#endif -#endif - -#if USE_FLONUM -#define RB_FLONUM_P(x) ((((int)(SIGNED_VALUE)(x))&RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG) -#else -#define RB_FLONUM_P(x) 0 -#endif -#define FLONUM_P(x) RB_FLONUM_P(x) - -/* Module#methods, #singleton_methods and so on return Symbols */ -#define USE_SYMBOL_AS_METHOD_NAME 1 - -/* special constants - i.e. non-zero and non-fixnum constants */ -enum ruby_special_consts { -#if USE_FLONUM - RUBY_Qfalse = 0x00, /* ...0000 0000 */ - RUBY_Qtrue = 0x14, /* ...0001 0100 */ - RUBY_Qnil = 0x08, /* ...0000 1000 */ - RUBY_Qundef = 0x34, /* ...0011 0100 */ - - RUBY_IMMEDIATE_MASK = 0x07, - RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ - RUBY_FLONUM_MASK = 0x03, - RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */ - RUBY_SYMBOL_FLAG = 0x0c, /* ...0000 1100 */ -#else - RUBY_Qfalse = 0, /* ...0000 0000 */ - RUBY_Qtrue = 2, /* ...0000 0010 */ - RUBY_Qnil = 4, /* ...0000 0100 */ - RUBY_Qundef = 6, /* ...0000 0110 */ - - RUBY_IMMEDIATE_MASK = 0x03, - RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ - RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */ - RUBY_FLONUM_FLAG = 0x02, - RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */ -#endif - RUBY_SPECIAL_SHIFT = 8 -}; - -#define RUBY_Qfalse ((VALUE)RUBY_Qfalse) -#define RUBY_Qtrue ((VALUE)RUBY_Qtrue) -#define RUBY_Qnil ((VALUE)RUBY_Qnil) -#define RUBY_Qundef ((VALUE)RUBY_Qundef) /* undefined value for placeholder */ -#define Qfalse RUBY_Qfalse -#define Qtrue RUBY_Qtrue -#define Qnil RUBY_Qnil -#define Qundef RUBY_Qundef -#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK -#define FIXNUM_FLAG RUBY_FIXNUM_FLAG -#if USE_FLONUM -#define FLONUM_MASK RUBY_FLONUM_MASK -#define FLONUM_FLAG RUBY_FLONUM_FLAG -#endif -#define SYMBOL_FLAG RUBY_SYMBOL_FLAG - -#define RB_TEST(v) !(((VALUE)(v) & (VALUE)~RUBY_Qnil) == 0) -#define RB_NIL_P(v) !((VALUE)(v) != RUBY_Qnil) -#define RTEST(v) RB_TEST(v) -#define NIL_P(v) RB_NIL_P(v) - -#define CLASS_OF(v) rb_class_of((VALUE)(v)) - -enum ruby_value_type { - RUBY_T_NONE = 0x00, - - RUBY_T_OBJECT = 0x01, - RUBY_T_CLASS = 0x02, - RUBY_T_MODULE = 0x03, - RUBY_T_FLOAT = 0x04, - RUBY_T_STRING = 0x05, - RUBY_T_REGEXP = 0x06, - RUBY_T_ARRAY = 0x07, - RUBY_T_HASH = 0x08, - RUBY_T_STRUCT = 0x09, - RUBY_T_BIGNUM = 0x0a, - RUBY_T_FILE = 0x0b, - RUBY_T_DATA = 0x0c, - RUBY_T_MATCH = 0x0d, - RUBY_T_COMPLEX = 0x0e, - RUBY_T_RATIONAL = 0x0f, - - RUBY_T_NIL = 0x11, - RUBY_T_TRUE = 0x12, - RUBY_T_FALSE = 0x13, - RUBY_T_SYMBOL = 0x14, - RUBY_T_FIXNUM = 0x15, - RUBY_T_UNDEF = 0x16, - - RUBY_T_IMEMO = 0x1a, /*!< @see imemo_type */ - RUBY_T_NODE = 0x1b, - RUBY_T_ICLASS = 0x1c, - RUBY_T_ZOMBIE = 0x1d, - RUBY_T_MOVED = 0x1e, - - RUBY_T_MASK = 0x1f -}; - -#define T_NONE RUBY_T_NONE -#define T_NIL RUBY_T_NIL -#define T_OBJECT RUBY_T_OBJECT -#define T_CLASS RUBY_T_CLASS -#define T_ICLASS RUBY_T_ICLASS -#define T_MODULE RUBY_T_MODULE -#define T_FLOAT RUBY_T_FLOAT -#define T_STRING RUBY_T_STRING -#define T_REGEXP RUBY_T_REGEXP -#define T_ARRAY RUBY_T_ARRAY -#define T_HASH RUBY_T_HASH -#define T_STRUCT RUBY_T_STRUCT -#define T_BIGNUM RUBY_T_BIGNUM -#define T_FILE RUBY_T_FILE -#define T_FIXNUM RUBY_T_FIXNUM -#define T_TRUE RUBY_T_TRUE -#define T_FALSE RUBY_T_FALSE -#define T_DATA RUBY_T_DATA -#define T_MATCH RUBY_T_MATCH -#define T_SYMBOL RUBY_T_SYMBOL -#define T_RATIONAL RUBY_T_RATIONAL -#define T_COMPLEX RUBY_T_COMPLEX -#define T_IMEMO RUBY_T_IMEMO -#define T_UNDEF RUBY_T_UNDEF -#define T_NODE RUBY_T_NODE -#define T_ZOMBIE RUBY_T_ZOMBIE -#define T_MOVED RUBY_T_MOVED -#define T_MASK RUBY_T_MASK - -#define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK) -#define BUILTIN_TYPE(x) RB_BUILTIN_TYPE(x) - -static inline int rb_type(VALUE obj); -#define TYPE(x) rb_type((VALUE)(x)) - -#define RB_FLOAT_TYPE_P(obj) (\ - RB_FLONUM_P(obj) || \ - (!RB_SPECIAL_CONST_P(obj) && RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT)) - -#define RB_TYPE_P(obj, type) ( \ - ((type) == RUBY_T_FIXNUM) ? RB_FIXNUM_P(obj) : \ - ((type) == RUBY_T_TRUE) ? ((obj) == RUBY_Qtrue) : \ - ((type) == RUBY_T_FALSE) ? ((obj) == RUBY_Qfalse) : \ - ((type) == RUBY_T_NIL) ? ((obj) == RUBY_Qnil) : \ - ((type) == RUBY_T_UNDEF) ? ((obj) == RUBY_Qundef) : \ - ((type) == RUBY_T_SYMBOL) ? RB_SYMBOL_P(obj) : \ - ((type) == RUBY_T_FLOAT) ? RB_FLOAT_TYPE_P(obj) : \ - (!RB_SPECIAL_CONST_P(obj) && RB_BUILTIN_TYPE(obj) == (type))) - -#ifdef __GNUC__ -#define RB_GC_GUARD(v) \ - (*__extension__ ({ \ - volatile VALUE *rb_gc_guarded_ptr = &(v); \ - __asm__("" : : "m"(rb_gc_guarded_ptr)); \ - rb_gc_guarded_ptr; \ - })) -#elif defined _MSC_VER -#pragma optimize("", off) -static inline volatile VALUE *rb_gc_guarded_ptr(volatile VALUE *ptr) {return ptr;} -#pragma optimize("", on) -#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v))) -#else -volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val); -#define HAVE_RB_GC_GUARDED_PTR_VAL 1 -#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v))) -#endif - -#ifdef __GNUC__ -#define RB_UNUSED_VAR(x) x __attribute__ ((unused)) -#else -#define RB_UNUSED_VAR(x) x -#endif - -void rb_check_type(VALUE,int); -#define Check_Type(v,t) rb_check_type((VALUE)(v),(t)) - -VALUE rb_str_to_str(VALUE); -VALUE rb_string_value(volatile VALUE*); -char *rb_string_value_ptr(volatile VALUE*); -char *rb_string_value_cstr(volatile VALUE*); - -#define StringValue(v) rb_string_value(&(v)) -#define StringValuePtr(v) rb_string_value_ptr(&(v)) -#define StringValueCStr(v) rb_string_value_cstr(&(v)) - -void rb_check_safe_obj(VALUE); -#define SafeStringValue(v) StringValue(v) -#if GCC_VERSION_SINCE(4,4,0) -void rb_check_safe_str(VALUE) __attribute__((error("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead"))); -# define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) -#else -# define rb_check_safe_str(x) [<"rb_check_safe_str() is obsolete; use StringValue() instead">] -# define Check_SafeStr(v) [<"Check_SafeStr() is obsolete; use StringValue() instead">] -#endif - -VALUE rb_str_export(VALUE); -#define ExportStringValue(v) do {\ - StringValue(v);\ - (v) = rb_str_export(v);\ -} while (0) -VALUE rb_str_export_locale(VALUE); - -VALUE rb_get_path(VALUE); -#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v)) - -VALUE rb_get_path_no_checksafe(VALUE); -#define FilePathStringValue(v) ((v) = rb_get_path(v)) - -/* Remove in 3.0 */ -#define RUBY_SAFE_LEVEL_MAX 1 -void rb_secure(int); -int rb_safe_level(void); -void rb_set_safe_level(int); -#if GCC_VERSION_SINCE(4,4,0) -int ruby_safe_level_2_error(void) __attribute__((error("$SAFE=2 to 4 are obsolete"))); -int ruby_safe_level_2_warning(void) __attribute__((const,warning("$SAFE=2 to 4 are obsolete"))); -# ifdef RUBY_EXPORT -# define ruby_safe_level_2_warning() ruby_safe_level_2_error() -# endif -# if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -# define RUBY_SAFE_LEVEL_INVALID_P(level) \ - __extension__(\ - __builtin_choose_expr(\ - __builtin_constant_p(level), \ - ((level) < 0 || RUBY_SAFE_LEVEL_MAX < (level)), 0)) -# define RUBY_SAFE_LEVEL_CHECK(level, type) \ - __extension__(__builtin_choose_expr(RUBY_SAFE_LEVEL_INVALID_P(level), ruby_safe_level_2_##type(), (level))) -# else -/* in gcc 4.8 or earlier, __builtin_choose_expr() does not consider - * __builtin_constant_p(variable) a constant expression. - */ -# define RUBY_SAFE_LEVEL_INVALID_P(level) \ - __extension__(__builtin_constant_p(level) && \ - ((level) < 0 || RUBY_SAFE_LEVEL_MAX < (level))) -# define RUBY_SAFE_LEVEL_CHECK(level, type) \ - (RUBY_SAFE_LEVEL_INVALID_P(level) ? ruby_safe_level_2_##type() : (level)) -# endif -# define rb_secure(level) rb_secure(RUBY_SAFE_LEVEL_CHECK(level, warning)) -# define rb_set_safe_level(level) rb_set_safe_level(RUBY_SAFE_LEVEL_CHECK(level, error)) -#endif -void rb_set_safe_level_force(int); -void rb_secure_update(VALUE); -NORETURN(void rb_insecure_operation(void)); - -VALUE rb_errinfo(void); -void rb_set_errinfo(VALUE); - -long rb_num2long(VALUE); -unsigned long rb_num2ulong(VALUE); -static inline long -rb_num2long_inline(VALUE x) -{ - if (RB_FIXNUM_P(x)) - return RB_FIX2LONG(x); - else - return rb_num2long(x); -} -#define RB_NUM2LONG(x) rb_num2long_inline(x) -#define NUM2LONG(x) RB_NUM2LONG(x) -static inline unsigned long -rb_num2ulong_inline(VALUE x) -{ - if (RB_FIXNUM_P(x)) - return RB_FIX2ULONG(x); - else - return rb_num2ulong(x); -} -#define RB_NUM2ULONG(x) rb_num2ulong_inline(x) -#define NUM2ULONG(x) RB_NUM2ULONG(x) -#if SIZEOF_INT < SIZEOF_LONG -long rb_num2int(VALUE); -long rb_fix2int(VALUE); -#define RB_FIX2INT(x) ((int)rb_fix2int((VALUE)(x))) - -static inline int -rb_num2int_inline(VALUE x) -{ - if (RB_FIXNUM_P(x)) - return (int)rb_fix2int(x); - else - return (int)rb_num2int(x); -} -#define RB_NUM2INT(x) rb_num2int_inline(x) - -unsigned long rb_num2uint(VALUE); -#define RB_NUM2UINT(x) ((unsigned int)rb_num2uint(x)) -unsigned long rb_fix2uint(VALUE); -#define RB_FIX2UINT(x) ((unsigned int)rb_fix2uint(x)) -#else /* SIZEOF_INT < SIZEOF_LONG */ -#define RB_NUM2INT(x) ((int)RB_NUM2LONG(x)) -#define RB_NUM2UINT(x) ((unsigned int)RB_NUM2ULONG(x)) -#define RB_FIX2INT(x) ((int)RB_FIX2LONG(x)) -#define RB_FIX2UINT(x) ((unsigned int)RB_FIX2ULONG(x)) -#endif /* SIZEOF_INT < SIZEOF_LONG */ -#define NUM2INT(x) RB_NUM2INT(x) -#define NUM2UINT(x) RB_NUM2UINT(x) -#define FIX2INT(x) RB_FIX2INT(x) -#define FIX2UINT(x) RB_FIX2UINT(x) - -short rb_num2short(VALUE); -unsigned short rb_num2ushort(VALUE); -short rb_fix2short(VALUE); -unsigned short rb_fix2ushort(VALUE); -#define RB_FIX2SHORT(x) (rb_fix2short((VALUE)(x))) -#define FIX2SHORT(x) RB_FIX2SHORT(x) -static inline short -rb_num2short_inline(VALUE x) -{ - if (RB_FIXNUM_P(x)) - return rb_fix2short(x); - else - return rb_num2short(x); -} - -#define RB_NUM2SHORT(x) rb_num2short_inline(x) -#define RB_NUM2USHORT(x) rb_num2ushort(x) -#define NUM2SHORT(x) RB_NUM2SHORT(x) -#define NUM2USHORT(x) RB_NUM2USHORT(x) - -#ifdef HAVE_LONG_LONG -LONG_LONG rb_num2ll(VALUE); -unsigned LONG_LONG rb_num2ull(VALUE); -static inline LONG_LONG -rb_num2ll_inline(VALUE x) -{ - if (RB_FIXNUM_P(x)) - return RB_FIX2LONG(x); - else - return rb_num2ll(x); -} -# define RB_NUM2LL(x) rb_num2ll_inline(x) -# define RB_NUM2ULL(x) rb_num2ull(x) -# define NUM2LL(x) RB_NUM2LL(x) -# define NUM2ULL(x) RB_NUM2ULL(x) -#endif - -#if !defined(NUM2OFFT) -# if defined(HAVE_LONG_LONG) && SIZEOF_OFF_T > SIZEOF_LONG -# define NUM2OFFT(x) ((off_t)NUM2LL(x)) -# else -# define NUM2OFFT(x) NUM2LONG(x) -# endif -#endif - -#if defined(HAVE_LONG_LONG) && SIZEOF_SIZE_T > SIZEOF_LONG -# define NUM2SIZET(x) ((size_t)NUM2ULL(x)) -# define NUM2SSIZET(x) ((ssize_t)NUM2LL(x)) -#else -# define NUM2SIZET(x) NUM2ULONG(x) -# define NUM2SSIZET(x) NUM2LONG(x) -#endif - -double rb_num2dbl(VALUE); -#define NUM2DBL(x) rb_num2dbl((VALUE)(x)) - -VALUE rb_uint2big(uintptr_t); -VALUE rb_int2big(intptr_t); - -VALUE rb_newobj(void); -VALUE rb_newobj_of(VALUE, VALUE); -VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type); -#define RB_NEWOBJ(obj,type) type *(obj) = (type*)rb_newobj() -#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = (type*)rb_newobj_of(klass, flags) -#define NEWOBJ(obj,type) RB_NEWOBJ(obj,type) -#define NEWOBJ_OF(obj,type,klass,flags) RB_NEWOBJ_OF(obj,type,klass,flags) /* core has special NEWOBJ_OF() in internal.h */ -#define OBJSETUP(obj,c,t) rb_obj_setup(obj, c, t) /* use NEWOBJ_OF instead of NEWOBJ()+OBJSETUP() */ -#define CLONESETUP(clone,obj) rb_clone_setup(clone,obj) -#define DUPSETUP(dup,obj) rb_dup_setup(dup,obj) - -#ifndef USE_RGENGC -#define USE_RGENGC 1 -#ifndef USE_RINCGC -#define USE_RINCGC 1 -#endif -#endif - -#if USE_RGENGC == 0 -#define USE_RINCGC 0 -#endif - -#ifndef RGENGC_WB_PROTECTED_ARRAY -#define RGENGC_WB_PROTECTED_ARRAY 1 -#endif -#ifndef RGENGC_WB_PROTECTED_HASH -#define RGENGC_WB_PROTECTED_HASH 1 -#endif -#ifndef RGENGC_WB_PROTECTED_STRUCT -#define RGENGC_WB_PROTECTED_STRUCT 1 -#endif -#ifndef RGENGC_WB_PROTECTED_STRING -#define RGENGC_WB_PROTECTED_STRING 1 -#endif -#ifndef RGENGC_WB_PROTECTED_OBJECT -#define RGENGC_WB_PROTECTED_OBJECT 1 -#endif -#ifndef RGENGC_WB_PROTECTED_REGEXP -#define RGENGC_WB_PROTECTED_REGEXP 1 -#endif -#ifndef RGENGC_WB_PROTECTED_CLASS -#define RGENGC_WB_PROTECTED_CLASS 1 -#endif -#ifndef RGENGC_WB_PROTECTED_FLOAT -#define RGENGC_WB_PROTECTED_FLOAT 1 -#endif -#ifndef RGENGC_WB_PROTECTED_COMPLEX -#define RGENGC_WB_PROTECTED_COMPLEX 1 -#endif -#ifndef RGENGC_WB_PROTECTED_RATIONAL -#define RGENGC_WB_PROTECTED_RATIONAL 1 -#endif -#ifndef RGENGC_WB_PROTECTED_BIGNUM -#define RGENGC_WB_PROTECTED_BIGNUM 1 -#endif -#ifndef RGENGC_WB_PROTECTED_NODE_CREF -#define RGENGC_WB_PROTECTED_NODE_CREF 1 -#endif - -#ifdef __GNUC__ -__extension__ -#endif -enum ruby_fl_type { - RUBY_FL_WB_PROTECTED = (1<<5), - RUBY_FL_PROMOTED0 = (1<<5), - RUBY_FL_PROMOTED1 = (1<<6), - RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0|RUBY_FL_PROMOTED1, - RUBY_FL_FINALIZE = (1<<7), - RUBY_FL_TAINT = (1<<8), - RUBY_FL_UNTRUSTED = RUBY_FL_TAINT, - RUBY_FL_SEEN_OBJ_ID = (1<<9), - RUBY_FL_EXIVAR = (1<<10), - RUBY_FL_FREEZE = (1<<11), - - RUBY_FL_USHIFT = 12, - -#define RUBY_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n)) - RUBY_FL_USER_N(0), - RUBY_FL_USER_N(1), - RUBY_FL_USER_N(2), - RUBY_FL_USER_N(3), - RUBY_FL_USER_N(4), - RUBY_FL_USER_N(5), - RUBY_FL_USER_N(6), - RUBY_FL_USER_N(7), - RUBY_FL_USER_N(8), - RUBY_FL_USER_N(9), - RUBY_FL_USER_N(10), - RUBY_FL_USER_N(11), - RUBY_FL_USER_N(12), - RUBY_FL_USER_N(13), - RUBY_FL_USER_N(14), - RUBY_FL_USER_N(15), - RUBY_FL_USER_N(16), - RUBY_FL_USER_N(17), - RUBY_FL_USER_N(18), -#if defined ENUM_OVER_INT || SIZEOF_INT*CHAR_BIT>12+19+1 - RUBY_FL_USER_N(19), -#else -#define RUBY_FL_USER19 (((VALUE)1)<<(RUBY_FL_USHIFT+19)) -#endif - - RUBY_ELTS_SHARED = RUBY_FL_USER2, - RUBY_FL_DUPPED = (RUBY_T_MASK|RUBY_FL_EXIVAR|RUBY_FL_TAINT), - RUBY_FL_SINGLETON = RUBY_FL_USER0 -}; - -struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { - VALUE flags; - const VALUE klass; -}; - -VALUE rb_obj_hide(VALUE obj); -VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */ - -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -# define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ - __extension__( \ - __builtin_choose_expr( \ - RGENGC_WB_PROTECTED_##type, \ - OBJ_WB_UNPROTECT((VALUE)(obj)), ((VALUE)(obj)))) -#else -# define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ - (RGENGC_WB_PROTECTED_##type ? \ - OBJ_WB_UNPROTECT((VALUE)(obj)) : ((VALUE)(obj))) -#endif - -#define RBASIC_CLASS(obj) (RBASIC(obj)->klass) - -#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX -enum ruby_rvalue_flags { - RVALUE_EMBED_LEN_MAX = 3, -}; - -#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX -#define ROBJECT_EMBED ROBJECT_EMBED -enum ruby_robject_flags { - ROBJECT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX, - ROBJECT_EMBED = RUBY_FL_USER1, - - ROBJECT_ENUM_END -}; - -struct RObject { - struct RBasic basic; - union { - struct { - uint32_t numiv; - VALUE *ivptr; - void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -}; -#define ROBJECT_NUMIV(o) \ - ((RBASIC(o)->flags & ROBJECT_EMBED) ? \ - ROBJECT_EMBED_LEN_MAX : \ - ROBJECT(o)->as.heap.numiv) -#define ROBJECT_IVPTR(o) \ - ((RBASIC(o)->flags & ROBJECT_EMBED) ? \ - ROBJECT(o)->as.ary : \ - ROBJECT(o)->as.heap.ivptr) -#define ROBJECT_IV_INDEX_TBL(o) \ - ((RBASIC(o)->flags & ROBJECT_EMBED) ? \ - RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \ - ROBJECT(o)->as.heap.iv_index_tbl) - -#define RCLASS_SUPER(c) rb_class_get_superclass(c) -#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -#define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m) -#define RMODULE_M_TBL(m) RCLASS_M_TBL(m) -#define RMODULE_SUPER(m) RCLASS_SUPER(m) -#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID -#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT -#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT -enum ruby_rmodule_flags { - RMODULE_IS_OVERLAID = RUBY_FL_USER2, - RMODULE_IS_REFINEMENT = RUBY_FL_USER3, - RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4, - - RMODULE_ENUM_END -}; - -PUREFUNC(double rb_float_value(VALUE)); -VALUE rb_float_new(double); -VALUE rb_float_new_in_heap(double); - -#define RFLOAT_VALUE(v) rb_float_value(v) -#define DBL2NUM(dbl) rb_float_new(dbl) - -#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED -#define ELTS_SHARED RUBY_ELTS_SHARED - -#define RSTRING_NOEMBED RSTRING_NOEMBED -#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK -#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT -#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX -#define RSTRING_FSTR RSTRING_FSTR -enum ruby_rstring_flags { - RSTRING_NOEMBED = RUBY_FL_USER1, - RSTRING_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4| - RUBY_FL_USER5|RUBY_FL_USER6), - RSTRING_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+2), - RSTRING_EMBED_LEN_MAX = (int)((sizeof(VALUE)*RVALUE_EMBED_LEN_MAX)/sizeof(char)-1), - RSTRING_FSTR = RUBY_FL_USER17, - - RSTRING_ENUM_END -}; - -struct RString { - struct RBasic basic; - union { - struct { - long len; - char *ptr; - union { - long capa; - VALUE shared; - } aux; - } heap; - char ary[RSTRING_EMBED_LEN_MAX + 1]; - } as; -}; -#define RSTRING_EMBED_LEN(str) \ - (long)((RBASIC(str)->flags >> RSTRING_EMBED_LEN_SHIFT) & \ - (RSTRING_EMBED_LEN_MASK >> RSTRING_EMBED_LEN_SHIFT)) -#define RSTRING_LEN(str) \ - (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \ - RSTRING_EMBED_LEN(str) : \ - RSTRING(str)->as.heap.len) -#define RSTRING_PTR(str) \ - (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \ - RSTRING(str)->as.ary : \ - RSTRING(str)->as.heap.ptr) -#define RSTRING_END(str) \ - (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \ - (RSTRING(str)->as.ary + RSTRING_EMBED_LEN(str)) : \ - (RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len)) -#define RSTRING_LENINT(str) rb_long2int(RSTRING_LEN(str)) -#define RSTRING_GETMEM(str, ptrvar, lenvar) \ - (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \ - ((ptrvar) = RSTRING(str)->as.ary, (lenvar) = RSTRING_EMBED_LEN(str)) : \ - ((ptrvar) = RSTRING(str)->as.heap.ptr, (lenvar) = RSTRING(str)->as.heap.len)) - -#ifndef USE_TRANSIENT_HEAP -#define USE_TRANSIENT_HEAP 1 -#endif - -enum ruby_rarray_flags { - RARRAY_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX, - RARRAY_EMBED_FLAG = RUBY_FL_USER1, - /* RUBY_FL_USER2 is for ELTS_SHARED */ - RARRAY_EMBED_LEN_MASK = (RUBY_FL_USER4|RUBY_FL_USER3), - RARRAY_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+3), - -#if USE_TRANSIENT_HEAP - RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13, -#define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG -#else -#define RARRAY_TRANSIENT_FLAG 0 -#endif - - RARRAY_ENUM_END -}; -#define RARRAY_EMBED_FLAG (VALUE)RARRAY_EMBED_FLAG -#define RARRAY_EMBED_LEN_MASK (VALUE)RARRAY_EMBED_LEN_MASK -#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX -#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT - -struct RArray { - struct RBasic basic; - union { - struct { - long len; - union { - long capa; -#if defined(__clang__) /* <- clang++ is sane */ || \ - !defined(__cplusplus) /* <- C99 is sane */ || \ - (__cplusplus > 199711L) /* <- C++11 is sane */ - const -#endif - VALUE shared_root; - } aux; - const VALUE *ptr; - } heap; - const VALUE ary[RARRAY_EMBED_LEN_MAX]; - } as; -}; -#define RARRAY_EMBED_LEN(a) \ - (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \ - (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)) -#define RARRAY_LEN(a) rb_array_len(a) -#define RARRAY_LENINT(ary) rb_long2int(RARRAY_LEN(ary)) -#define RARRAY_CONST_PTR(a) rb_array_const_ptr(a) -#define RARRAY_CONST_PTR_TRANSIENT(a) rb_array_const_ptr_transient(a) - -#if USE_TRANSIENT_HEAP -#define RARRAY_TRANSIENT_P(ary) FL_TEST_RAW((ary), RARRAY_TRANSIENT_FLAG) -#else -#define RARRAY_TRANSIENT_P(ary) 0 -#endif - -#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1) -#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1) - -#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) do { \ - const VALUE _ary = (ary); \ - VALUE *ptr_name = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \ - expr; \ - RARRAY_PTR_USE_END_TRANSIENT(_ary); \ -} while (0) - -#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0) -#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0) - -#define RARRAY_PTR_USE(ary, ptr_name, expr) do { \ - const VALUE _ary = (ary); \ - VALUE *ptr_name = (VALUE *)RARRAY_PTR_USE_START(_ary); \ - expr; \ - RARRAY_PTR_USE_END(_ary); \ -} while (0) - -#define RARRAY_AREF(a, i) (RARRAY_CONST_PTR_TRANSIENT(a)[i]) -#define RARRAY_ASET(a, i, v) do { \ - const VALUE _ary = (a); \ - const VALUE _v = (v); \ - VALUE *ptr = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \ - RB_OBJ_WRITE(_ary, &ptr[i], _v); \ - RARRAY_PTR_USE_END_TRANSIENT(_ary); \ -} while (0) - -#define RARRAY_PTR(a) ((VALUE *)RARRAY_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(ARRAY, a))) - -struct RRegexp { - struct RBasic basic; - struct re_pattern_buffer *ptr; - const VALUE src; - unsigned long usecnt; -}; -#define RREGEXP_PTR(r) (RREGEXP(r)->ptr) -#define RREGEXP_SRC(r) (RREGEXP(r)->src) -#define RREGEXP_SRC_PTR(r) RSTRING_PTR(RREGEXP(r)->src) -#define RREGEXP_SRC_LEN(r) RSTRING_LEN(RREGEXP(r)->src) -#define RREGEXP_SRC_END(r) RSTRING_END(RREGEXP(r)->src) - -/* RHash is defined at internal.h */ -size_t rb_hash_size_num(VALUE hash); - -#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__) -#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h) -#define RHASH_IFNONE(h) rb_hash_ifnone(h) -#define RHASH_SIZE(h) rb_hash_size_num(h) -#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0) -#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone) - -struct RFile { - struct RBasic basic; - struct rb_io_t *fptr; -}; - -struct RData { - struct RBasic basic; - void (*dmark)(void*); - void (*dfree)(void*); - void *data; -}; - -typedef struct rb_data_type_struct rb_data_type_t; - -struct rb_data_type_struct { - const char *wrap_struct_name; - struct { - void (*dmark)(void*); - void (*dfree)(void*); - size_t (*dsize)(const void *); - void (*dcompact)(void*); - void *reserved[1]; /* For future extension. - This array *must* be filled with ZERO. */ - } function; - const rb_data_type_t *parent; - void *data; /* This area can be used for any purpose - by a programmer who define the type. */ - VALUE flags; /* RUBY_FL_WB_PROTECTED */ -}; - -#define HAVE_TYPE_RB_DATA_TYPE_T 1 -#define HAVE_RB_DATA_TYPE_T_FUNCTION 1 -#define HAVE_RB_DATA_TYPE_T_PARENT 1 - -struct RTypedData { - struct RBasic basic; - const rb_data_type_t *type; - VALUE typed_flag; /* 1 or not */ - void *data; -}; - -#define DATA_PTR(dta) (RDATA(dta)->data) - -#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1) -#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type) -#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data) - -/* -#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func)) -*/ -typedef void (*RUBY_DATA_FUNC)(void*); - -#ifndef RUBY_UNTYPED_DATA_WARNING -# if defined RUBY_EXPORT -# define RUBY_UNTYPED_DATA_WARNING 1 -# else -# define RUBY_UNTYPED_DATA_WARNING 0 -# endif -#endif -VALUE rb_data_object_wrap(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC); -VALUE rb_data_object_zalloc(VALUE,size_t,RUBY_DATA_FUNC,RUBY_DATA_FUNC); -VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *); -VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); -int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); -int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *); -void *rb_check_typeddata(VALUE, const rb_data_type_t *); -#define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t)) -#define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1) -#define RUBY_NEVER_FREE ((RUBY_DATA_FUNC)0) -#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE -#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE - -/* bits for rb_data_type_struct::flags */ -#define RUBY_TYPED_FREE_IMMEDIATELY 1 /* TYPE field */ -#define RUBY_TYPED_WB_PROTECTED RUBY_FL_WB_PROTECTED /* THIS FLAG DEPENDS ON Ruby version */ -#define RUBY_TYPED_PROMOTED1 RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */ - -#define Data_Wrap_Struct(klass,mark,free,sval)\ - rb_data_object_wrap((klass),(sval),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free)) - -#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \ - VALUE result = rb_data_object_zalloc((klass), (size), \ - (RUBY_DATA_FUNC)(mark), \ - (RUBY_DATA_FUNC)(free)); \ - (void)((sval) = (type *)DATA_PTR(result)); - -#ifdef __GNUC__ -#define Data_Make_Struct(klass,type,mark,free,sval) RB_GNUC_EXTENSION_BLOCK(\ - Data_Make_Struct0(data_struct_obj, klass, type, sizeof(type), mark, free, sval); \ - data_struct_obj \ -) -#else -#define Data_Make_Struct(klass,type,mark,free,sval) (\ - rb_data_object_make((klass),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free),(void **)&(sval),sizeof(type)) \ -) -#endif - -#define TypedData_Wrap_Struct(klass,data_type,sval)\ - rb_data_typed_object_wrap((klass),(sval),(data_type)) - -#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ - VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ - (void)((sval) = (type *)DATA_PTR(result)); - -#ifdef __GNUC__ -#define TypedData_Make_Struct(klass, type, data_type, sval) RB_GNUC_EXTENSION_BLOCK(\ - TypedData_Make_Struct0(data_struct_obj, klass, type, sizeof(type), data_type, sval); \ - data_struct_obj \ -) -#else -#define TypedData_Make_Struct(klass, type, data_type, sval) (\ - rb_data_typed_object_make((klass),(data_type),(void **)&(sval),sizeof(type)) \ -) -#endif - -#define Data_Get_Struct(obj,type,sval) \ - ((sval) = (type*)rb_data_object_get(obj)) - -#define TypedData_Get_Struct(obj,type,data_type,sval) \ - ((sval) = (type*)rb_check_typeddata((obj), (data_type))) - -#define RSTRUCT_LEN(st) NUM2LONG(rb_struct_size(st)) -#define RSTRUCT_PTR(st) rb_struct_ptr(st) -#define RSTRUCT_SET(st, idx, v) rb_struct_aset(st, INT2NUM(idx), (v)) -#define RSTRUCT_GET(st, idx) rb_struct_aref(st, INT2NUM(idx)) - -int rb_big_sign(VALUE); -#define RBIGNUM_SIGN(b) (rb_big_sign(b)) -#define RBIGNUM_POSITIVE_P(b) (RBIGNUM_SIGN(b)!=0) -#define RBIGNUM_NEGATIVE_P(b) (RBIGNUM_SIGN(b)==0) - -#define R_CAST(st) (struct st*) -#define RMOVED(obj) (R_CAST(RMoved)(obj)) -#define RBASIC(obj) (R_CAST(RBasic)(obj)) -#define ROBJECT(obj) (R_CAST(RObject)(obj)) -#define RCLASS(obj) (R_CAST(RClass)(obj)) -#define RMODULE(obj) RCLASS(obj) -#define RSTRING(obj) (R_CAST(RString)(obj)) -#define RREGEXP(obj) (R_CAST(RRegexp)(obj)) -#define RARRAY(obj) (R_CAST(RArray)(obj)) -#define RDATA(obj) (R_CAST(RData)(obj)) -#define RTYPEDDATA(obj) (R_CAST(RTypedData)(obj)) -#define RFILE(obj) (R_CAST(RFile)(obj)) - -#define FL_SINGLETON ((VALUE)RUBY_FL_SINGLETON) -#define FL_WB_PROTECTED ((VALUE)RUBY_FL_WB_PROTECTED) -#define FL_PROMOTED0 ((VALUE)RUBY_FL_PROMOTED0) -#define FL_PROMOTED1 ((VALUE)RUBY_FL_PROMOTED1) -#define FL_FINALIZE ((VALUE)RUBY_FL_FINALIZE) -#define FL_TAINT ((VALUE)RUBY_FL_TAINT) -#define FL_UNTRUSTED ((VALUE)RUBY_FL_UNTRUSTED) -#define FL_SEEN_OBJ_ID ((VALUE)RUBY_FL_SEEN_OBJ_ID) -#define FL_EXIVAR ((VALUE)RUBY_FL_EXIVAR) -#define FL_FREEZE ((VALUE)RUBY_FL_FREEZE) - -#define FL_USHIFT ((VALUE)RUBY_FL_USHIFT) - -#define FL_USER0 ((VALUE)RUBY_FL_USER0) -#define FL_USER1 ((VALUE)RUBY_FL_USER1) -#define FL_USER2 ((VALUE)RUBY_FL_USER2) -#define FL_USER3 ((VALUE)RUBY_FL_USER3) -#define FL_USER4 ((VALUE)RUBY_FL_USER4) -#define FL_USER5 ((VALUE)RUBY_FL_USER5) -#define FL_USER6 ((VALUE)RUBY_FL_USER6) -#define FL_USER7 ((VALUE)RUBY_FL_USER7) -#define FL_USER8 ((VALUE)RUBY_FL_USER8) -#define FL_USER9 ((VALUE)RUBY_FL_USER9) -#define FL_USER10 ((VALUE)RUBY_FL_USER10) -#define FL_USER11 ((VALUE)RUBY_FL_USER11) -#define FL_USER12 ((VALUE)RUBY_FL_USER12) -#define FL_USER13 ((VALUE)RUBY_FL_USER13) -#define FL_USER14 ((VALUE)RUBY_FL_USER14) -#define FL_USER15 ((VALUE)RUBY_FL_USER15) -#define FL_USER16 ((VALUE)RUBY_FL_USER16) -#define FL_USER17 ((VALUE)RUBY_FL_USER17) -#define FL_USER18 ((VALUE)RUBY_FL_USER18) -#define FL_USER19 ((VALUE)(unsigned int)RUBY_FL_USER19) - -#define RB_SPECIAL_CONST_P(x) (RB_IMMEDIATE_P(x) || !RB_TEST(x)) -#define SPECIAL_CONST_P(x) RB_SPECIAL_CONST_P(x) - -#define RB_FL_ABLE(x) (!RB_SPECIAL_CONST_P(x) && RB_BUILTIN_TYPE(x) != RUBY_T_NODE) -#define RB_FL_TEST_RAW(x,f) (RBASIC(x)->flags&(f)) -#define RB_FL_TEST(x,f) (RB_FL_ABLE(x)?RB_FL_TEST_RAW((x),(f)):0) -#define RB_FL_ANY_RAW(x,f) RB_FL_TEST_RAW((x),(f)) -#define RB_FL_ANY(x,f) RB_FL_TEST((x),(f)) -#define RB_FL_ALL_RAW(x,f) (RB_FL_TEST_RAW((x),(f)) == (f)) -#define RB_FL_ALL(x,f) (RB_FL_TEST((x),(f)) == (f)) -#define RB_FL_SET_RAW(x,f) (void)(RBASIC(x)->flags |= (f)) -#define RB_FL_SET(x,f) (RB_FL_ABLE(x) ? RB_FL_SET_RAW(x, f) : (void)0) -#define RB_FL_UNSET_RAW(x,f) (void)(RBASIC(x)->flags &= ~(VALUE)(f)) -#define RB_FL_UNSET(x,f) (RB_FL_ABLE(x) ? RB_FL_UNSET_RAW(x, f) : (void)0) -#define RB_FL_REVERSE_RAW(x,f) (void)(RBASIC(x)->flags ^= (f)) -#define RB_FL_REVERSE(x,f) (RB_FL_ABLE(x) ? RB_FL_REVERSE_RAW(x, f) : (void)0) - -#define RB_OBJ_TAINTABLE(x) (RB_FL_ABLE(x) && RB_BUILTIN_TYPE(x) != RUBY_T_BIGNUM && RB_BUILTIN_TYPE(x) != RUBY_T_FLOAT) -#define RB_OBJ_TAINTED_RAW(x) RB_FL_TEST_RAW(x, RUBY_FL_TAINT) -#define RB_OBJ_TAINTED(x) (!!RB_FL_TEST((x), RUBY_FL_TAINT)) -#define RB_OBJ_TAINT_RAW(x) RB_FL_SET_RAW(x, RUBY_FL_TAINT) -#define RB_OBJ_TAINT(x) (RB_OBJ_TAINTABLE(x) ? RB_OBJ_TAINT_RAW(x) : (void)0) -#define RB_OBJ_UNTRUSTED(x) RB_OBJ_TAINTED(x) -#define RB_OBJ_UNTRUST(x) RB_OBJ_TAINT(x) -#define RB_OBJ_INFECT_RAW(x,s) RB_FL_SET_RAW(x, RB_OBJ_TAINTED_RAW(s)) -#define RB_OBJ_INFECT(x,s) ( \ - (RB_OBJ_TAINTABLE(x) && RB_FL_ABLE(s)) ? \ - RB_OBJ_INFECT_RAW(x, s) : (void)0) - -#define RB_OBJ_FROZEN_RAW(x) (RBASIC(x)->flags&RUBY_FL_FREEZE) -#define RB_OBJ_FROZEN(x) (!RB_FL_ABLE(x) || RB_OBJ_FROZEN_RAW(x)) -#define RB_OBJ_FREEZE_RAW(x) (void)(RBASIC(x)->flags |= RUBY_FL_FREEZE) -#define RB_OBJ_FREEZE(x) rb_obj_freeze_inline((VALUE)x) - -/*! - * \defgroup deprecated_macros deprecated macro APIs - * \{ - * \par These macros are deprecated. Prefer their `RB_`-prefixed versions. - */ -#define FL_ABLE(x) RB_FL_ABLE(x) -#define FL_TEST_RAW(x,f) RB_FL_TEST_RAW(x,f) -#define FL_TEST(x,f) RB_FL_TEST(x,f) -#define FL_ANY_RAW(x,f) RB_FL_ANY_RAW(x,f) -#define FL_ANY(x,f) RB_FL_ANY(x,f) -#define FL_ALL_RAW(x,f) RB_FL_ALL_RAW(x,f) -#define FL_ALL(x,f) RB_FL_ALL(x,f) -#define FL_SET_RAW(x,f) RB_FL_SET_RAW(x,f) -#define FL_SET(x,f) RB_FL_SET(x,f) -#define FL_UNSET_RAW(x,f) RB_FL_UNSET_RAW(x,f) -#define FL_UNSET(x,f) RB_FL_UNSET(x,f) -#define FL_REVERSE_RAW(x,f) RB_FL_REVERSE_RAW(x,f) -#define FL_REVERSE(x,f) RB_FL_REVERSE(x,f) - -#define OBJ_TAINTABLE(x) RB_OBJ_TAINTABLE(x) -#define OBJ_TAINTED_RAW(x) RB_OBJ_TAINTED_RAW(x) -#define OBJ_TAINTED(x) RB_OBJ_TAINTED(x) -#define OBJ_TAINT_RAW(x) RB_OBJ_TAINT_RAW(x) -#define OBJ_TAINT(x) RB_OBJ_TAINT(x) -#define OBJ_UNTRUSTED(x) RB_OBJ_UNTRUSTED(x) -#define OBJ_UNTRUST(x) RB_OBJ_UNTRUST(x) -#define OBJ_INFECT_RAW(x,s) RB_OBJ_INFECT_RAW(x,s) -#define OBJ_INFECT(x,s) RB_OBJ_INFECT(x,s) -#define OBJ_FROZEN_RAW(x) RB_OBJ_FROZEN_RAW(x) -#define OBJ_FROZEN(x) RB_OBJ_FROZEN(x) -#define OBJ_FREEZE_RAW(x) RB_OBJ_FREEZE_RAW(x) -#define OBJ_FREEZE(x) RB_OBJ_FREEZE(x) - -/* \} */ - -void rb_freeze_singleton_class(VALUE klass); - -static inline void -rb_obj_freeze_inline(VALUE x) -{ - if (RB_FL_ABLE(x)) { - RB_OBJ_FREEZE_RAW(x); - if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) { - rb_freeze_singleton_class(x); - } - } -} - -#if GCC_VERSION_SINCE(4,4,0) -# define RUBY_UNTYPED_DATA_FUNC(func) func __attribute__((warning("untyped Data is unsafe; use TypedData instead"))) -#else -# define RUBY_UNTYPED_DATA_FUNC(func) DEPRECATED(func) -#endif - -#if defined(__GNUC__) && !defined(__NO_INLINE__) -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -RUBY_UNTYPED_DATA_FUNC(static inline VALUE rb_data_object_wrap_warning(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC)); -#endif -RUBY_UNTYPED_DATA_FUNC(static inline void *rb_data_object_get_warning(VALUE)); - -static inline VALUE -rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free) -{ - return rb_data_object_wrap(klass, ptr, mark, free); -} - -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -#define rb_data_object_wrap_warning(klass, ptr, mark, free) \ - __extension__( \ - __builtin_choose_expr( \ - __builtin_constant_p(klass) && !(klass), \ - rb_data_object_wrap(klass, ptr, mark, free), \ - rb_data_object_wrap_warning(klass, ptr, mark, free))) -#endif -#endif - -static inline void * -rb_data_object_get(VALUE obj) -{ - Check_Type(obj, RUBY_T_DATA); - return ((struct RData *)obj)->data; -} - -#if defined(__GNUC__) && !defined(__NO_INLINE__) -static inline void * -rb_data_object_get_warning(VALUE obj) -{ - return rb_data_object_get(obj); -} -#endif - -static inline VALUE -rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size) -{ - Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap); - return result; -} - -static inline VALUE -rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size) -{ - TypedData_Make_Struct0(result, klass, void, size, type, *datap); - return result; -} - -#ifndef rb_data_object_alloc -DEPRECATED_BY(rb_data_object_wrap, static inline VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC)); -static inline VALUE -rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) -{ - return rb_data_object_wrap(klass, data, dmark, dfree); -} -#endif - -#ifndef rb_data_typed_object_alloc -DEPRECATED_BY(rb_data_typed_object_wrap, static inline VALUE rb_data_typed_object_alloc(VALUE,void*,const rb_data_type_t*)); -static inline VALUE -rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) -{ - return rb_data_typed_object_wrap(klass, datap, type); -} -#endif +#ifndef RUBY_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_RUBY_H 1 +/** + * @file + * @author $Author$ + * @date Thu Jun 10 14:26:32 JST 1993 + * @copyright Copyright (C) 1993-2008 Yukihiro Matsumoto + * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. + * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan + * @copyright 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. + */ +#include "ruby/internal/config.h" -#if defined(__GNUC__) && !defined(__NO_INLINE__) -#define rb_data_object_wrap_0 rb_data_object_wrap -#define rb_data_object_wrap_1 rb_data_object_wrap_warning -#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_, RUBY_UNTYPED_DATA_WARNING) -#define rb_data_object_get_0 rb_data_object_get -#define rb_data_object_get_1 rb_data_object_get_warning -#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_, RUBY_UNTYPED_DATA_WARNING) -#define rb_data_object_make_0 rb_data_object_make -#define rb_data_object_make_1 rb_data_object_make_warning -#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_, RUBY_UNTYPED_DATA_WARNING) +/* @shyouhei doesn't understand why we need at this very + * beginning of the entire circus. */ +#ifdef HAVE_INTRINSICS_H +# include #endif -#if USE_RGENGC -#define RB_OBJ_PROMOTED_RAW(x) RB_FL_ALL_RAW(x, RUBY_FL_PROMOTED) -#define RB_OBJ_PROMOTED(x) (RB_SPECIAL_CONST_P(x) ? 0 : RB_OBJ_PROMOTED_RAW(x)) -#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) +#include -void rb_gc_writebarrier(VALUE a, VALUE b); -void rb_gc_writebarrier_unprotect(VALUE obj); +#include "defines.h" +#include "ruby/internal/anyargs.h" +#include "ruby/internal/arithmetic.h" +#include "ruby/internal/core.h" +#include "ruby/internal/ctype.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/error.h" +#include "ruby/internal/eval.h" +#include "ruby/internal/event.h" +#include "ruby/internal/fl_type.h" +#include "ruby/internal/gc.h" +#include "ruby/internal/glob.h" +#include "ruby/internal/globals.h" +#include "ruby/internal/has/warning.h" +#include "ruby/internal/interpreter.h" +#include "ruby/internal/iterator.h" +#include "ruby/internal/memory.h" +#include "ruby/internal/method.h" +#include "ruby/internal/module.h" +#include "ruby/internal/newobj.h" +#include "ruby/internal/rgengc.h" +#include "ruby/internal/scan_args.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/symbol.h" +#include "ruby/internal/value.h" +#include "ruby/internal/value_type.h" +#include "ruby/internal/variable.h" +#include "ruby/assert.h" +#include "ruby/backward/2/assume.h" +#include "ruby/backward/2/inttypes.h" +#include "ruby/backward/2/limits.h" -#else /* USE_RGENGC */ -#define RB_OBJ_PROMOTED(x) 0 -#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) -#endif -#define OBJ_PROMOTED_RAW(x) RB_OBJ_PROMOTED_RAW(x) -#define OBJ_PROMOTED(x) RB_OBJ_PROMOTED(x) -#define OBJ_WB_UNPROTECT(x) RB_OBJ_WB_UNPROTECT(x) +RBIMPL_SYMBOL_EXPORT_BEGIN() -/* Write barrier (WB) interfaces: - * - RB_OBJ_WRITE(a, slot, b): WB for new reference from `a' to `b'. - * Write `b' into `*slot'. `slot' is a pointer in `a'. - * - RB_OBJ_WRITTEN(a, oldv, b): WB for new reference from `a' to `b'. - * This doesn't write any values, but only a WB declaration. - * `oldv' is replaced value with `b' (not used in current Ruby). +/* Module#methods, #singleton_methods and so on return Symbols */ +/** + * @private * - * NOTE: The following core interfaces can be changed in the future. - * Please catch up if you want to insert WB into C-extensions - * correctly. + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. */ -#define RB_OBJ_WRITE(a, slot, b) rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__) -#define RB_OBJ_WRITTEN(a, oldv, b) rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__) - -#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT -#define USE_RGENGC_LOGGING_WB_UNPROTECT 0 -#endif - -#if USE_RGENGC_LOGGING_WB_UNPROTECT -void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); -#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging -#endif - -static inline VALUE -rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) -{ -#ifdef RGENGC_LOGGING_WB_UNPROTECT - RGENGC_LOGGING_WB_UNPROTECT((void *)x, filename, line); -#endif -#if USE_RGENGC - rb_gc_writebarrier_unprotect(x); -#endif - return x; -} - -static inline VALUE -rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) -{ -#ifdef RGENGC_LOGGING_OBJ_WRITTEN - RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); -#endif - -#if USE_RGENGC - if (!RB_SPECIAL_CONST_P(b)) { - rb_gc_writebarrier(a, b); - } -#endif - - return a; -} - -static inline VALUE -rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) -{ -#ifdef RGENGC_LOGGING_WRITE - RGENGC_LOGGING_WRITE(a, slot, b, filename, line); -#endif - - *slot = b; - -#if USE_RGENGC - rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); -#endif - return a; -} - -#define RUBY_INTEGER_UNIFICATION 1 -#define RB_INTEGER_TYPE_P(obj) rb_integer_type_p(obj) -#if defined __GNUC__ && !GCC_VERSION_SINCE(4, 3, 0) -/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE - * in inline function and caller function */ -#define rb_integer_type_p(obj) \ - __extension__ ({ \ - const VALUE integer_type_obj = (obj); \ - (RB_FIXNUM_P(integer_type_obj) || \ - (!RB_SPECIAL_CONST_P(integer_type_obj) && \ - RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \ - }) -#else -static inline int -rb_integer_type_p(VALUE obj) -{ - return (RB_FIXNUM_P(obj) || - (!RB_SPECIAL_CONST_P(obj) && - RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM)); -} -#endif - -#if SIZEOF_INT < SIZEOF_LONG -# define RB_INT2NUM(v) RB_INT2FIX((int)(v)) -# define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v)) -#else -static inline VALUE -rb_int2num_inline(int v) -{ - if (RB_FIXABLE(v)) - return RB_INT2FIX(v); - else - return rb_int2big(v); -} -#define RB_INT2NUM(x) rb_int2num_inline(x) - -static inline VALUE -rb_uint2num_inline(unsigned int v) -{ - if (RB_POSFIXABLE(v)) - return RB_LONG2FIX(v); - else - return rb_uint2big(v); -} -#define RB_UINT2NUM(x) rb_uint2num_inline(x) -#endif -#define INT2NUM(x) RB_INT2NUM(x) -#define UINT2NUM(x) RB_UINT2NUM(x) - -static inline VALUE -rb_long2num_inline(long v) -{ - if (RB_FIXABLE(v)) - return RB_LONG2FIX(v); - else - return rb_int2big(v); -} -#define RB_LONG2NUM(x) rb_long2num_inline(x) - -static inline VALUE -rb_ulong2num_inline(unsigned long v) -{ - if (RB_POSFIXABLE(v)) - return RB_LONG2FIX(v); - else - return rb_uint2big(v); -} -#define RB_ULONG2NUM(x) rb_ulong2num_inline(x) - -static inline char -rb_num2char_inline(VALUE x) -{ - if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1)) - return RSTRING_PTR(x)[0]; - else - return (char)(NUM2INT(x) & 0xff); -} -#define RB_NUM2CHR(x) rb_num2char_inline(x) - -#define RB_CHR2FIX(x) RB_INT2FIX((long)((x)&0xff)) - -#define LONG2NUM(x) RB_LONG2NUM(x) -#define ULONG2NUM(x) RB_ULONG2NUM(x) -#define USHORT2NUM(x) RB_INT2FIX(x) -#define NUM2CHR(x) RB_NUM2CHR(x) -#define CHR2FIX(x) RB_CHR2FIX(x) - -#if SIZEOF_LONG < SIZEOF_VALUE -#define RB_ST2FIX(h) RB_LONG2FIX((long)((h) > 0 ? (h) & (unsigned long)-1 >> 2 : (h) | ~((unsigned long)-1 >> 2))) -#else -#define RB_ST2FIX(h) RB_LONG2FIX((long)(h)) -#endif -#define ST2FIX(h) RB_ST2FIX(h) - -#define RB_ALLOC_N(type,n) ((type*)ruby_xmalloc2((size_t)(n),sizeof(type))) -#define RB_ALLOC(type) ((type*)ruby_xmalloc(sizeof(type))) -#define RB_ZALLOC_N(type,n) ((type*)ruby_xcalloc((size_t)(n),sizeof(type))) -#define RB_ZALLOC(type) (RB_ZALLOC_N(type,1)) -#define RB_REALLOC_N(var,type,n) ((var)=(type*)ruby_xrealloc2((char*)(var),(size_t)(n),sizeof(type))) - -#define ALLOC_N(type,n) RB_ALLOC_N(type,n) -#define ALLOC(type) RB_ALLOC(type) -#define ZALLOC_N(type,n) RB_ZALLOC_N(type,n) -#define ZALLOC(type) RB_ZALLOC(type) -#define REALLOC_N(var,type,n) RB_REALLOC_N(var,type,n) - -#if GCC_VERSION_BEFORE(4,9,5) -/* GCC 4.9.2 reportedly has this feature and is broken. - * The function is not officially documented below. - * Seems we should not use it. - * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html#Other-Builtins */ -# undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN -#endif - -#if defined(HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN) && defined(RUBY_ALIGNOF) -/* I don't know why but __builtin_alloca_with_align's second argument - takes bits rather than bytes. */ -#define ALLOCA_N(type, n) \ - (type*)__builtin_alloca_with_align((sizeof(type)*(n)), \ - RUBY_ALIGNOF(type) * CHAR_BIT) -#else -#define ALLOCA_N(type,n) ((type*)alloca(sizeof(type)*(n))) -#endif - -void *rb_alloc_tmp_buffer(volatile VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2)); -void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count) RUBY_ATTR_ALLOC_SIZE((2,3)); -void rb_free_tmp_buffer(volatile VALUE *store); -NORETURN(void ruby_malloc_size_overflow(size_t, size_t)); -#if HAVE_LONG_LONG && SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG -# define DSIZE_T unsigned LONG_LONG -#elif defined(HAVE_INT128_T) -# define DSIZE_T uint128_t -#endif -static inline int -rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c) -{ -#ifdef DSIZE_T -# ifdef __GNUC__ - __extension__ -# endif - DSIZE_T c2 = (DSIZE_T)a * (DSIZE_T)b; - if (c2 > max) return 1; - *c = (size_t)c2; -#else - if (b != 0 && a > max / b) return 1; - *c = a * b; -#endif - return 0; -} -static inline void * -rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) -{ - size_t cnt = (size_t)count; - if (elsize == sizeof(VALUE)) { - if (RB_UNLIKELY(cnt > LONG_MAX / sizeof(VALUE))) { - ruby_malloc_size_overflow(cnt, elsize); - } - } - else { - size_t size, max = LONG_MAX - sizeof(VALUE) + 1; - if (RB_UNLIKELY(rb_mul_size_overflow(cnt, elsize, max, &size))) { - ruby_malloc_size_overflow(cnt, elsize); - } - cnt = (size + sizeof(VALUE) - 1) / sizeof(VALUE); - } - return rb_alloc_tmp_buffer_with_count(store, cnt * sizeof(VALUE), cnt); -} -/* allocates _n_ bytes temporary buffer and stores VALUE including it - * in _v_. _n_ may be evaluated twice. */ -#ifdef C_ALLOCA -# define RB_ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n)) -# define RB_ALLOCV_N(type, v, n) \ - rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)) -#else -# define RUBY_ALLOCV_LIMIT 1024 -# define RB_ALLOCV(v, n) ((n) < RUBY_ALLOCV_LIMIT ? \ - ((v) = 0, alloca(n)) : \ - rb_alloc_tmp_buffer(&(v), (n))) -# define RB_ALLOCV_N(type, v, n) \ - ((type*)(((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ - ((v) = 0, alloca((size_t)(n) * sizeof(type))) : \ - rb_alloc_tmp_buffer2(&(v), (long)(n), sizeof(type)))) -#endif -#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) - -#define ALLOCV(v, n) RB_ALLOCV(v, n) -#define ALLOCV_N(type, v, n) RB_ALLOCV_N(type, v, n) -#define ALLOCV_END(v) RB_ALLOCV_END(v) - -#define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(size_t)(n)) -#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(size_t)(n)) -#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(size_t)(n)) -#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(size_t)(n)) -#ifdef __GLIBC__ -static inline void * -ruby_nonempty_memcpy(void *dest, const void *src, size_t n) -{ - /* if nothing to be copied, src may be NULL */ - return (n ? memcpy(dest, src, n) : dest); -} -#define memcpy(p1,p2,n) ruby_nonempty_memcpy(p1, p2, n) -#endif - -void rb_obj_infect(VALUE victim, VALUE carrier); - -typedef int ruby_glob_func(const char*,VALUE, void*); -void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE); -int ruby_glob(const char*,int,ruby_glob_func*,VALUE); -int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE); - -VALUE rb_define_class(const char*,VALUE); -VALUE rb_define_module(const char*); -VALUE rb_define_class_under(VALUE, const char*, VALUE); -VALUE rb_define_module_under(VALUE, const char*); - -void rb_include_module(VALUE,VALUE); -void rb_extend_object(VALUE,VALUE); -void rb_prepend_module(VALUE,VALUE); - -typedef VALUE rb_gvar_getter_t(ID id, VALUE *data); -typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data); -typedef void rb_gvar_marker_t(VALUE *var); - -rb_gvar_getter_t rb_gvar_undef_getter; -rb_gvar_setter_t rb_gvar_undef_setter; -rb_gvar_marker_t rb_gvar_undef_marker; - -rb_gvar_getter_t rb_gvar_val_getter; -rb_gvar_setter_t rb_gvar_val_setter; -rb_gvar_marker_t rb_gvar_val_marker; - -rb_gvar_getter_t rb_gvar_var_getter; -rb_gvar_setter_t rb_gvar_var_setter; -rb_gvar_marker_t rb_gvar_var_marker; - -NORETURN(rb_gvar_setter_t rb_gvar_readonly_setter); - -void rb_define_variable(const char*,VALUE*); -void rb_define_virtual_variable(const char*,rb_gvar_getter_t*,rb_gvar_setter_t*); -void rb_define_hooked_variable(const char*,VALUE*,rb_gvar_getter_t*,rb_gvar_setter_t*); -void rb_define_readonly_variable(const char*,const VALUE*); -void rb_define_const(VALUE,const char*,VALUE); -void rb_define_global_const(const char*,VALUE); +#define USE_SYMBOL_AS_METHOD_NAME 1 -void rb_define_method(VALUE,const char*,VALUE(*)(ANYARGS),int); -void rb_define_module_function(VALUE,const char*,VALUE(*)(ANYARGS),int); -void rb_define_global_function(const char*,VALUE(*)(ANYARGS),int); +/** + * Converts an object to a path. It first tries `#to_path` method if any, then + * falls back to `#to_str` method. + * + * @param[in] obj Arbitrary ruby object. + * @exception rb_eArgError `obj` contains a NUL byte. + * @exception rb_eTypeError `obj` is not path-ish. + * @exception rb_eEncCompatError No encoding conversion from `obj` to path. + * @return Converted path object. + */ +VALUE rb_get_path(VALUE obj); -void rb_undef_method(VALUE,const char*); -void rb_define_alias(VALUE,const char*,const char*); -void rb_define_attr(VALUE,const char*,int,int); +/** + * Ensures that the parameter object is a path. + * + * @param[in,out] v Arbitrary ruby object. + * @exception rb_eArgError `v` contains a NUL byte. + * @exception rb_eTypeError `v` is not path-ish. + * @exception rb_eEncCompatError `v` is not path-compatible. + * @post `v` is a path. + */ +#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v)) -void rb_global_variable(VALUE*); -void rb_gc_register_mark_object(VALUE); -void rb_gc_register_address(VALUE*); -void rb_gc_unregister_address(VALUE*); +/** + * @deprecated This function is an alias of rb_get_path() now. The part that + * did "no_checksafe" was deleted. It remains here because of no + * harm. + */ +VALUE rb_get_path_no_checksafe(VALUE); -ID rb_intern(const char*); -ID rb_intern2(const char*, long); -ID rb_intern_str(VALUE str); -const char *rb_id2name(ID); -ID rb_check_id(volatile VALUE *); -ID rb_to_id(VALUE); -VALUE rb_id2str(ID); -VALUE rb_sym2str(VALUE); -VALUE rb_to_symbol(VALUE name); -VALUE rb_check_symbol(volatile VALUE *namep); +/** + * @deprecated This macro is an alias of #FilePathValue now. The part that did + * "String" was deleted. It remains here because of no harm. + */ +#define FilePathStringValue(v) ((v) = rb_get_path(v)) -#define RUBY_CONST_ID_CACHE(result, str) \ - { \ - static ID rb_intern_id_cache; \ - if (!rb_intern_id_cache) \ - rb_intern_id_cache = rb_intern2((str), (long)strlen(str)); \ - result rb_intern_id_cache; \ - } -#define RUBY_CONST_ID(var, str) \ - do RUBY_CONST_ID_CACHE((var) =, (str)) while (0) -#define CONST_ID_CACHE(result, str) RUBY_CONST_ID_CACHE(result, str) -#define CONST_ID(var, str) RUBY_CONST_ID(var, str) +/** @cond INTERNAL_MACRO */ #if defined(HAVE_BUILTIN___BUILTIN_CONSTANT_P) && defined(HAVE_STMT_AND_DECL_IN_EXPR) -/* __builtin_constant_p and statement expression is available - * since gcc-2.7.2.3 at least. */ -#define rb_intern(str) \ - (__builtin_constant_p(str) ? \ - __extension__ (RUBY_CONST_ID_CACHE((ID), (str))) : \ - rb_intern(str)) -#define rb_intern_const(str) \ - (__builtin_constant_p(str) ? \ - __extension__ (rb_intern2((str), (long)strlen(str))) : \ - (rb_intern)(str)) - # define rb_varargs_argc_check_runtime(argc, vargc) \ (((argc) <= (vargc)) ? (argc) : \ (rb_fatal("argc(%d) exceeds actual arguments(%d)", \ @@ -1859,7 +112,7 @@ VALUE rb_check_symbol(volatile VALUE *namep); ((argc) == 0 ? (vargc) <= 1 : /* [ruby-core:85266] [Bug #14425] */ \ (argc) == (vargc)) # if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -# if HAVE_ATTRIBUTE_ERRORFUNC +# ifdef HAVE_ATTRIBUTE_ERRORFUNC ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int)); # else # define rb_varargs_bad_length(argc, vargc) \ @@ -1874,801 +127,153 @@ ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int) # define rb_varargs_argc_check(argc, vargc) \ rb_varargs_argc_check_runtime(argc, vargc) # endif - -#else -#define rb_intern_const(str) rb_intern2((str), (long)strlen(str)) -#endif - -const char *rb_class2name(VALUE); -const char *rb_obj_classname(VALUE); - -void rb_p(VALUE); - -VALUE rb_eval_string(const char*); -VALUE rb_eval_string_protect(const char*, int*); -VALUE rb_eval_string_wrap(const char*, int*); -VALUE rb_funcall(VALUE, ID, int, ...); -VALUE rb_funcallv(VALUE, ID, int, const VALUE*); -VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE*, int); -VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*); -VALUE rb_funcallv_public_kw(VALUE, ID, int, const VALUE*, int); -#define rb_funcall2 rb_funcallv -#define rb_funcall3 rb_funcallv_public -VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*); -VALUE rb_funcall_passing_block_kw(VALUE, ID, int, const VALUE*, int); -VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE); -VALUE rb_funcall_with_block_kw(VALUE, ID, int, const VALUE*, VALUE, int); -int rb_scan_args(int, const VALUE*, const char*, ...); -#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0 -#define RB_SCAN_ARGS_KEYWORDS 1 -#define RB_SCAN_ARGS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */ -#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3 -int rb_scan_args_kw(int, int, const VALUE*, const char*, ...); -VALUE rb_call_super(int, const VALUE*); -VALUE rb_call_super_kw(int, const VALUE*, int); -VALUE rb_current_receiver(void); -int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *); -VALUE rb_extract_keywords(VALUE *orighash); - -/* rb_scan_args() format allows ':' for optional hash */ -#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1 - -VALUE rb_gv_set(const char*, VALUE); -VALUE rb_gv_get(const char*); -VALUE rb_iv_get(VALUE, const char*); -VALUE rb_iv_set(VALUE, const char*, VALUE); - -VALUE rb_equal(VALUE,VALUE); - -VALUE *rb_ruby_verbose_ptr(void); -VALUE *rb_ruby_debug_ptr(void); -#define ruby_verbose (*rb_ruby_verbose_ptr()) -#define ruby_debug (*rb_ruby_debug_ptr()) - -/* for rb_readwrite_sys_fail first argument */ -enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE}; -#define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE -#define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE - -PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3); -PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2); -COLDFUNC PRINTF_ARGS(NORETURN(void rb_bug(const char*, ...)), 1, 2); -NORETURN(void rb_bug_errno(const char*, int)); -NORETURN(void rb_sys_fail(const char*)); -NORETURN(void rb_sys_fail_str(VALUE)); -NORETURN(void rb_mod_sys_fail(VALUE, const char*)); -NORETURN(void rb_mod_sys_fail_str(VALUE, VALUE)); -NORETURN(void rb_readwrite_sys_fail(enum rb_io_wait_readwrite, const char*)); -NORETURN(void rb_iter_break(void)); -NORETURN(void rb_iter_break_value(VALUE)); -NORETURN(void rb_exit(int)); -NORETURN(void rb_notimplement(void)); -VALUE rb_syserr_new(int, const char *); -VALUE rb_syserr_new_str(int n, VALUE arg); -NORETURN(void rb_syserr_fail(int, const char*)); -NORETURN(void rb_syserr_fail_str(int, VALUE)); -NORETURN(void rb_mod_syserr_fail(VALUE, int, const char*)); -NORETURN(void rb_mod_syserr_fail_str(VALUE, int, VALUE)); -NORETURN(void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite, int, const char*)); - -/* reports if `-W' specified */ -PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2); -PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4); -PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2); -/* reports always */ -COLDFUNC PRINTF_ARGS(void rb_warn(const char*, ...), 1, 2); -PRINTF_ARGS(void rb_compile_warn(const char *, int, const char*, ...), 3, 4); - -#define RB_BLOCK_CALL_FUNC_STRICT 1 -#define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1 -#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \ - VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg -typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); -typedef rb_block_call_func *rb_block_call_func_t; - -VALUE rb_each(VALUE); -VALUE rb_yield(VALUE); -VALUE rb_yield_values(int n, ...); -VALUE rb_yield_values2(int n, const VALUE *argv); -VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat); -VALUE rb_yield_splat(VALUE); -VALUE rb_yield_splat_kw(VALUE, int); -VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */ -#define RB_NO_KEYWORDS 0 -#define RB_PASS_KEYWORDS 1 -#define RB_PASS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */ -#define RB_PASS_CALLED_KEYWORDS 3 -int rb_keyword_given_p(void); -int rb_block_given_p(void); -void rb_need_block(void); -VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE); -VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE); -VALUE rb_block_call_kw(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE,int); -VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE); -VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...); -VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list); -VALUE rb_ensure(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE),VALUE); -VALUE rb_catch(const char*,rb_block_call_func_t,VALUE); -VALUE rb_catch_obj(VALUE,rb_block_call_func_t,VALUE); -NORETURN(void rb_throw(const char*,VALUE)); -NORETURN(void rb_throw_obj(VALUE,VALUE)); - -VALUE rb_require(const char*); - -RUBY_EXTERN VALUE rb_mKernel; -RUBY_EXTERN VALUE rb_mComparable; -RUBY_EXTERN VALUE rb_mEnumerable; -RUBY_EXTERN VALUE rb_mErrno; -RUBY_EXTERN VALUE rb_mFileTest; -RUBY_EXTERN VALUE rb_mGC; -RUBY_EXTERN VALUE rb_mMath; -RUBY_EXTERN VALUE rb_mProcess; -RUBY_EXTERN VALUE rb_mWaitReadable; -RUBY_EXTERN VALUE rb_mWaitWritable; - -RUBY_EXTERN VALUE rb_cBasicObject; -RUBY_EXTERN VALUE rb_cObject; -RUBY_EXTERN VALUE rb_cArray; -#ifndef RUBY_INTEGER_UNIFICATION -RUBY_EXTERN VALUE rb_cBignum; -#endif -RUBY_EXTERN VALUE rb_cBinding; -RUBY_EXTERN VALUE rb_cClass; -RUBY_EXTERN VALUE rb_cCont; -RUBY_EXTERN VALUE rb_cData; -RUBY_EXTERN VALUE rb_cDir; -RUBY_EXTERN VALUE rb_cEncoding; -RUBY_EXTERN VALUE rb_cEnumerator; -RUBY_EXTERN VALUE rb_cFalseClass; -RUBY_EXTERN VALUE rb_cFile; -#ifndef RUBY_INTEGER_UNIFICATION -RUBY_EXTERN VALUE rb_cFixnum; #endif -RUBY_EXTERN VALUE rb_cComplex; -RUBY_EXTERN VALUE rb_cFloat; -RUBY_EXTERN VALUE rb_cHash; -RUBY_EXTERN VALUE rb_cIO; -RUBY_EXTERN VALUE rb_cInteger; -RUBY_EXTERN VALUE rb_cMatch; -RUBY_EXTERN VALUE rb_cMethod; -RUBY_EXTERN VALUE rb_cModule; -RUBY_EXTERN VALUE rb_cNameErrorMesg; -RUBY_EXTERN VALUE rb_cNilClass; -RUBY_EXTERN VALUE rb_cNumeric; -RUBY_EXTERN VALUE rb_cProc; -RUBY_EXTERN VALUE rb_cRandom; -RUBY_EXTERN VALUE rb_cRange; -RUBY_EXTERN VALUE rb_cRational; -RUBY_EXTERN VALUE rb_cRegexp; -RUBY_EXTERN VALUE rb_cStat; -RUBY_EXTERN VALUE rb_cString; -RUBY_EXTERN VALUE rb_cStruct; -RUBY_EXTERN VALUE rb_cSymbol; -RUBY_EXTERN VALUE rb_cThread; -RUBY_EXTERN VALUE rb_cTime; -RUBY_EXTERN VALUE rb_cTrueClass; -RUBY_EXTERN VALUE rb_cUnboundMethod; +/** @endcond */ -RUBY_EXTERN VALUE rb_eException; -RUBY_EXTERN VALUE rb_eStandardError; -RUBY_EXTERN VALUE rb_eSystemExit; -RUBY_EXTERN VALUE rb_eInterrupt; -RUBY_EXTERN VALUE rb_eSignal; -RUBY_EXTERN VALUE rb_eFatal; -RUBY_EXTERN VALUE rb_eArgError; -RUBY_EXTERN VALUE rb_eEOFError; -RUBY_EXTERN VALUE rb_eIndexError; -RUBY_EXTERN VALUE rb_eStopIteration; -RUBY_EXTERN VALUE rb_eKeyError; -RUBY_EXTERN VALUE rb_eRangeError; -RUBY_EXTERN VALUE rb_eIOError; -RUBY_EXTERN VALUE rb_eRuntimeError; -RUBY_EXTERN VALUE rb_eFrozenError; -RUBY_EXTERN VALUE rb_eSecurityError; -RUBY_EXTERN VALUE rb_eSystemCallError; -RUBY_EXTERN VALUE rb_eThreadError; -RUBY_EXTERN VALUE rb_eTypeError; -RUBY_EXTERN VALUE rb_eZeroDivError; -RUBY_EXTERN VALUE rb_eNotImpError; -RUBY_EXTERN VALUE rb_eNoMemError; -RUBY_EXTERN VALUE rb_eNoMethodError; -RUBY_EXTERN VALUE rb_eFloatDomainError; -RUBY_EXTERN VALUE rb_eLocalJumpError; -RUBY_EXTERN VALUE rb_eSysStackError; -RUBY_EXTERN VALUE rb_eRegexpError; -RUBY_EXTERN VALUE rb_eEncodingError; -RUBY_EXTERN VALUE rb_eEncCompatError; -RUBY_EXTERN VALUE rb_eNoMatchingPatternError; - -RUBY_EXTERN VALUE rb_eScriptError; -RUBY_EXTERN VALUE rb_eNameError; -RUBY_EXTERN VALUE rb_eSyntaxError; -RUBY_EXTERN VALUE rb_eLoadError; - -RUBY_EXTERN VALUE rb_eMathDomainError; - -RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr; +/** + * Queries the name of the passed class. + * + * @param[in] klass An instance of a class. + * @return The name of `klass`. + * @note Return value is managed by our GC. Don't free. + */ +const char *rb_class2name(VALUE klass); -static inline VALUE -rb_class_of(VALUE obj) -{ - if (RB_IMMEDIATE_P(obj)) { - if (RB_FIXNUM_P(obj)) return rb_cInteger; - if (RB_FLONUM_P(obj)) return rb_cFloat; - if (obj == RUBY_Qtrue) return rb_cTrueClass; - if (RB_STATIC_SYM_P(obj)) return rb_cSymbol; - } - else if (!RB_TEST(obj)) { - if (obj == RUBY_Qnil) return rb_cNilClass; - if (obj == RUBY_Qfalse) return rb_cFalseClass; - } - return RBASIC(obj)->klass; -} +/** + * Queries the name of the class of the passed object. + * + * @param[in] obj Arbitrary ruby object. + * @return The name of the class of `obj`. + * @note Return value is managed by our GC. Don't free. + */ +const char *rb_obj_classname(VALUE obj); -static inline int -rb_type(VALUE obj) -{ - if (RB_IMMEDIATE_P(obj)) { - if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM; - if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT; - if (obj == RUBY_Qtrue) return RUBY_T_TRUE; - if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL; - if (obj == RUBY_Qundef) return RUBY_T_UNDEF; - } - else if (!RB_TEST(obj)) { - if (obj == RUBY_Qnil) return RUBY_T_NIL; - if (obj == RUBY_Qfalse) return RUBY_T_FALSE; - } - return RB_BUILTIN_TYPE(obj); -} +/** + * Inspects an object. It first calls the argument's `#inspect` method, then + * feeds its result string into ::rb_stdout. + * + * This is identical to Ruby level `Kernel#p`, except it takes only one object. + * + * @internal + * + * Above description is in fact inaccurate. This API interfaces with Ractors. + */ +void rb_p(VALUE obj); -#ifdef __GNUC__ -#define rb_type_p(obj, type) \ - __extension__ (__builtin_constant_p(type) ? RB_TYPE_P((obj), (type)) : \ - rb_type(obj) == (type)) -#else -#define rb_type_p(obj, type) (rb_type(obj) == (type)) -#endif +/** + * This function is an optimised version of calling `#==`. It checks equality + * between two objects by first doing a fast identity check using using C's + * `==` (same as `BasicObject#equal?`). If that check fails, it calls `#==` + * dynamically. This optimisation actually affects semantics, because when + * `#==` returns false for the same object obj, `rb_equal(obj, obj)` would + * still return true. This happens for `Float::NAN`, where `Float::NAN == + * Float::NAN` is `false`, but `rb_equal(Float::NAN, Float::NAN)` is `true`. + * + * @param[in] lhs Comparison LHS. + * @param[in] rhs Comparison RHS. + * @retval RUBY_Qtrue They are the same. + * @retval RUBY_Qfalse They are different. + */ +VALUE rb_equal(VALUE lhs, VALUE rhs); -#ifdef __GNUC__ -#define rb_special_const_p(obj) \ - __extension__ ({ \ - VALUE special_const_obj = (obj); \ - (int)(RB_SPECIAL_CONST_P(special_const_obj) ? RUBY_Qtrue : RUBY_Qfalse); \ - }) -#else -static inline int -rb_special_const_p(VALUE obj) -{ - if (RB_SPECIAL_CONST_P(obj)) return (int)RUBY_Qtrue; - return (int)RUBY_Qfalse; -} -#endif +/** + * Identical to rb_require_string(), except it takes C's string instead of + * Ruby's. + * + * @param[in] feature Name of a feature, e.g. `"json"`. + * @exception rb_eLoadError No such feature. + * @exception rb_eRuntimeError `$"` is frozen; unable to push. + * @retval RUBY_Qtrue The feature is loaded for the first time. + * @retval RUBY_Qfalse The feature has already been loaded. + * @post `$"` is updated. + */ +VALUE rb_require(const char *feature); #include "ruby/intern.h" -static inline void -rb_clone_setup(VALUE clone, VALUE obj) -{ - rb_obj_setup(clone, rb_singleton_class_clone(obj), - RBASIC(obj)->flags & ~(FL_PROMOTED0|FL_PROMOTED1|FL_FINALIZE)); - rb_singleton_class_attached(RBASIC_CLASS(clone), clone); - if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(clone, obj); -} - -static inline void -rb_dup_setup(VALUE dup, VALUE obj) -{ - rb_obj_setup(dup, rb_obj_class(obj), RB_FL_TEST_RAW(obj, RUBY_FL_DUPPED)); - if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(dup, obj); -} - -static inline long -rb_array_len(VALUE a) -{ - return (RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? - RARRAY_EMBED_LEN(a) : RARRAY(a)->as.heap.len; -} - -#if defined(__fcc__) || defined(__fcc_version) || \ - defined(__FCC__) || defined(__FCC_VERSION) -/* workaround for old version of Fujitsu C Compiler (fcc) */ -# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) -#else -# define FIX_CONST_VALUE_PTR(x) (x) -#endif - -/* internal function. do not use this function */ -static inline const VALUE * -rb_array_const_ptr_transient(VALUE a) -{ - return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? - RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); -} - -/* internal function. do not use this function */ -static inline const VALUE * -rb_array_const_ptr(VALUE a) -{ -#if USE_TRANSIENT_HEAP - void rb_ary_detransient(VALUE a); - - if (RARRAY_TRANSIENT_P(a)) { - rb_ary_detransient(a); - } -#endif - return rb_array_const_ptr_transient(a); -} - -/* internal function. do not use this function */ -static inline VALUE * -rb_array_ptr_use_start(VALUE a, int allow_transient) -{ - VALUE *rb_ary_ptr_use_start(VALUE ary); - -#if USE_TRANSIENT_HEAP - if (!allow_transient) { - if (RARRAY_TRANSIENT_P(a)) { - void rb_ary_detransient(VALUE a); - rb_ary_detransient(a); - } - } -#endif - (void)allow_transient; - - return rb_ary_ptr_use_start(a); -} - -/* internal function. do not use this function */ -static inline void -rb_array_ptr_use_end(VALUE a, int allow_transient) -{ - void rb_ary_ptr_use_end(VALUE a); - rb_ary_ptr_use_end(a); - (void)allow_transient; -} - -#if defined(EXTLIB) && defined(USE_DLN_A_OUT) -/* hook for external modules */ -static char *dln_libs_to_be_linked[] = { EXTLIB, 0 }; -#endif - +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ #define RUBY_VM 1 /* YARV */ -#define HAVE_NATIVETHREAD -int ruby_native_thread_p(void); - -/* traditional set_trace_func events */ -#define RUBY_EVENT_NONE 0x0000 -#define RUBY_EVENT_LINE 0x0001 -#define RUBY_EVENT_CLASS 0x0002 -#define RUBY_EVENT_END 0x0004 -#define RUBY_EVENT_CALL 0x0008 -#define RUBY_EVENT_RETURN 0x0010 -#define RUBY_EVENT_C_CALL 0x0020 -#define RUBY_EVENT_C_RETURN 0x0040 -#define RUBY_EVENT_RAISE 0x0080 -#define RUBY_EVENT_ALL 0x00ff - -/* for TracePoint extended events */ -#define RUBY_EVENT_B_CALL 0x0100 -#define RUBY_EVENT_B_RETURN 0x0200 -#define RUBY_EVENT_THREAD_BEGIN 0x0400 -#define RUBY_EVENT_THREAD_END 0x0800 -#define RUBY_EVENT_FIBER_SWITCH 0x1000 -#define RUBY_EVENT_SCRIPT_COMPILED 0x2000 -#define RUBY_EVENT_TRACEPOINT_ALL 0xffff - -/* special events */ -#define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 - -/* internal events */ -#define RUBY_INTERNAL_EVENT_SWITCH 0x040000 -#define RUBY_EVENT_SWITCH 0x040000 /* obsolete name. this macro is for compatibility */ - /* 0x080000 */ -#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 -#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 -#define RUBY_INTERNAL_EVENT_GC_START 0x400000 -#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 -#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 -#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 -#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 -#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 -#define RUBY_INTERNAL_EVENT_MASK 0xffff0000 -typedef uint32_t rb_event_flag_t; -typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass); - -#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1 -void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); -int rb_remove_event_hook(rb_event_hook_func_t func); - -/* locale insensitive functions */ - -static inline int rb_isascii(int c){ return '\0' <= c && c <= '\x7f'; } -static inline int rb_isupper(int c){ return 'A' <= c && c <= 'Z'; } -static inline int rb_islower(int c){ return 'a' <= c && c <= 'z'; } -static inline int rb_isalpha(int c){ return rb_isupper(c) || rb_islower(c); } -static inline int rb_isdigit(int c){ return '0' <= c && c <= '9'; } -static inline int rb_isalnum(int c){ return rb_isalpha(c) || rb_isdigit(c); } -static inline int rb_isxdigit(int c){ return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } -static inline int rb_isblank(int c){ return c == ' ' || c == '\t'; } -static inline int rb_isspace(int c){ return c == ' ' || ('\t' <= c && c <= '\r'); } -static inline int rb_iscntrl(int c){ return ('\0' <= c && c < ' ') || c == '\x7f'; } -static inline int rb_isprint(int c){ return ' ' <= c && c <= '\x7e'; } -static inline int rb_ispunct(int c){ return !rb_isalnum(c); } -static inline int rb_isgraph(int c){ return '!' <= c && c <= '\x7e'; } -static inline int rb_tolower(int c) { return rb_isupper(c) ? (c|0x20) : c; } -static inline int rb_toupper(int c) { return rb_islower(c) ? (c&0x5f) : c; } - -#ifndef ISPRINT -#define ISASCII(c) rb_isascii(c) -#define ISPRINT(c) rb_isprint(c) -#define ISGRAPH(c) rb_isgraph(c) -#define ISSPACE(c) rb_isspace(c) -#define ISUPPER(c) rb_isupper(c) -#define ISLOWER(c) rb_islower(c) -#define ISALNUM(c) rb_isalnum(c) -#define ISALPHA(c) rb_isalpha(c) -#define ISDIGIT(c) rb_isdigit(c) -#define ISXDIGIT(c) rb_isxdigit(c) -#define ISBLANK(c) rb_isblank(c) -#define ISCNTRL(c) rb_iscntrl(c) -#define ISPUNCT(c) rb_ispunct(c) -#endif -#define TOUPPER(c) rb_toupper(c) -#define TOLOWER(c) rb_tolower(c) - -int st_locale_insensitive_strcasecmp(const char *s1, const char *s2); -int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n); -#define STRCASECMP(s1, s2) (st_locale_insensitive_strcasecmp((s1), (s2))) -#define STRNCASECMP(s1, s2, n) (st_locale_insensitive_strncasecmp((s1), (s2), (n))) +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_NATIVETHREAD -unsigned long ruby_strtoul(const char *str, char **endptr, int base); -#define STRTOUL(str, endptr, base) (ruby_strtoul((str), (endptr), (base))) +/** + * Queries if the thread which calls this function is a ruby's thread. + * "Ruby's" in this context is a thread created using one of our APIs like + * rb_thread_create(). There are distinctions between ruby's and other + * threads. For instance calling ruby methods are allowed only from inside of + * a ruby's thread. + * + * @retval 1 The current thread is a Ruby's thread. + * @retval 0 The current thread is a random thread from outside of Ruby. + */ +int ruby_native_thread_p(void); +/** + * @private + * + * This macro is for internal use. Must be a mistake to place here. + */ #define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();} -PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4); -int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap); - -/* -- Remove In 3.0, Only public for rb_scan_args optimized version -- */ -int rb_empty_keyword_given_p(void); - -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) -# define rb_scan_args(argc,argvp,fmt,...) \ - __builtin_choose_expr(__builtin_constant_p(fmt), \ - rb_scan_args0(argc,argvp,fmt,\ - (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ - ((VALUE*[]){__VA_ARGS__})), \ - rb_scan_args(argc,argvp,fmt,##__VA_ARGS__)) -# if HAVE_ATTRIBUTE_ERRORFUNC -ERRORFUNC(("bad scan arg format"), void rb_scan_args_bad_format(const char*)); -ERRORFUNC(("variable argument length doesn't match"), void rb_scan_args_length_mismatch(const char*,int)); -# else -# define rb_scan_args_bad_format(fmt) ((void)0) -# define rb_scan_args_length_mismatch(fmt, varc) ((void)0) -# endif - -# define rb_scan_args_isdigit(c) ((unsigned char)((c)-'0')<10) - -# define rb_scan_args_count_end(fmt, ofs, vari) \ - (fmt[ofs] ? -1 : (vari)) - -# define rb_scan_args_count_block(fmt, ofs, vari) \ - (fmt[ofs]!='&' ? \ - rb_scan_args_count_end(fmt, ofs, vari) : \ - rb_scan_args_count_end(fmt, ofs+1, vari+1)) - -# define rb_scan_args_count_hash(fmt, ofs, vari) \ - (fmt[ofs]!=':' ? \ - rb_scan_args_count_block(fmt, ofs, vari) : \ - rb_scan_args_count_block(fmt, ofs+1, vari+1)) - -# define rb_scan_args_count_trail(fmt, ofs, vari) \ - (!rb_scan_args_isdigit(fmt[ofs]) ? \ - rb_scan_args_count_hash(fmt, ofs, vari) : \ - rb_scan_args_count_hash(fmt, ofs+1, vari+(fmt[ofs]-'0'))) - -# define rb_scan_args_count_var(fmt, ofs, vari) \ - (fmt[ofs]!='*' ? \ - rb_scan_args_count_trail(fmt, ofs, vari) : \ - rb_scan_args_count_trail(fmt, ofs+1, vari+1)) - -# define rb_scan_args_count_opt(fmt, ofs, vari) \ - (!rb_scan_args_isdigit(fmt[ofs]) ? \ - rb_scan_args_count_var(fmt, ofs, vari) : \ - rb_scan_args_count_var(fmt, ofs+1, vari+fmt[ofs]-'0')) - -# define rb_scan_args_count_lead(fmt, ofs, vari) \ - (!rb_scan_args_isdigit(fmt[ofs]) ? \ - rb_scan_args_count_var(fmt, ofs, vari) : \ - rb_scan_args_count_opt(fmt, ofs+1, vari+fmt[ofs]-'0')) - -# define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0) - -# if defined(__has_attribute) && __has_attribute(diagnose_if) -# define rb_scan_args_verify(fmt, varc) (void)0 -# else -# define rb_scan_args_verify(fmt, varc) \ - (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \ - rb_scan_args_bad_format(fmt) : \ - sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \ - rb_scan_args_length_mismatch(fmt, varc) : \ - (void)0) -# endif - -ALWAYS_INLINE(static int rb_scan_args_lead_p(const char *fmt)); -static inline int -rb_scan_args_lead_p(const char *fmt) -{ - return rb_scan_args_isdigit(fmt[0]); -} - -ALWAYS_INLINE(static int rb_scan_args_n_lead(const char *fmt)); -static inline int -rb_scan_args_n_lead(const char *fmt) -{ - return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0); -} - -ALWAYS_INLINE(static int rb_scan_args_opt_p(const char *fmt)); -static inline int -rb_scan_args_opt_p(const char *fmt) -{ - return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1])); -} - -ALWAYS_INLINE(static int rb_scan_args_n_opt(const char *fmt)); -static inline int -rb_scan_args_n_opt(const char *fmt) -{ - return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0); -} - -ALWAYS_INLINE(static int rb_scan_args_var_idx(const char *fmt)); -static inline int -rb_scan_args_var_idx(const char *fmt) -{ - return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2); -} - -ALWAYS_INLINE(static int rb_scan_args_f_var(const char *fmt)); -static inline int -rb_scan_args_f_var(const char *fmt) -{ - return (fmt[rb_scan_args_var_idx(fmt)]=='*'); -} - -ALWAYS_INLINE(static int rb_scan_args_trail_idx(const char *fmt)); -static inline int -rb_scan_args_trail_idx(const char *fmt) -{ - const int idx = rb_scan_args_var_idx(fmt); - return idx+(fmt[idx]=='*'); -} - -ALWAYS_INLINE(static int rb_scan_args_n_trail(const char *fmt)); -static inline int -rb_scan_args_n_trail(const char *fmt) -{ - const int idx = rb_scan_args_trail_idx(fmt); - return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0); -} - -ALWAYS_INLINE(static int rb_scan_args_hash_idx(const char *fmt)); -static inline int -rb_scan_args_hash_idx(const char *fmt) -{ - const int idx = rb_scan_args_trail_idx(fmt); - return idx+rb_scan_args_isdigit(fmt[idx]); -} - -ALWAYS_INLINE(static int rb_scan_args_f_hash(const char *fmt)); -static inline int -rb_scan_args_f_hash(const char *fmt) -{ - return (fmt[rb_scan_args_hash_idx(fmt)]==':'); -} - -ALWAYS_INLINE(static int rb_scan_args_block_idx(const char *fmt)); -static inline int -rb_scan_args_block_idx(const char *fmt) -{ - const int idx = rb_scan_args_hash_idx(fmt); - return idx+(fmt[idx]==':'); -} - -ALWAYS_INLINE(static int rb_scan_args_f_block(const char *fmt)); -static inline int -rb_scan_args_f_block(const char *fmt) -{ - return (fmt[rb_scan_args_block_idx(fmt)]=='&'); -} - -# if 0 -ALWAYS_INLINE(static int rb_scan_args_end_idx(const char *fmt)); -static inline int -rb_scan_args_end_idx(const char *fmt) -{ - const int idx = rb_scan_args_block_idx(fmt); - return idx+(fmt[idx]=='&'); -} -# endif - -/* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/ -/* https://bugs.llvm.org/show_bug.cgi?id=38095 */ -# define rb_scan_args0(argc, argv, fmt, varc, vars) \ - rb_scan_args_set(argc, argv, \ - rb_scan_args_n_lead(fmt), \ - rb_scan_args_n_opt(fmt), \ - rb_scan_args_n_trail(fmt), \ - rb_scan_args_f_var(fmt), \ - rb_scan_args_f_hash(fmt), \ - rb_scan_args_f_block(fmt), \ - (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) -ALWAYS_INLINE(static int -rb_scan_args_set(int argc, const VALUE *argv, - int n_lead, int n_opt, int n_trail, - int f_var, int f_hash, int f_block, - VALUE *vars[], char *fmt, int varc)); - -inline int -rb_scan_args_set(int argc, const VALUE *argv, - int n_lead, int n_opt, int n_trail, - int f_var, int f_hash, int f_block, - VALUE *vars[], RB_UNUSED_VAR(char *fmt), RB_UNUSED_VAR(int varc)) -# if defined(__has_attribute) && __has_attribute(diagnose_if) - __attribute__((diagnose_if(rb_scan_args_count(fmt)<0,"bad scan arg format","error"))) - __attribute__((diagnose_if(rb_scan_args_count(fmt)!=varc,"variable argument length doesn't match","error"))) -# endif -{ - int i, argi = 0, vari = 0, last_idx = -1; - VALUE *var, hash = Qnil, last_hash = 0; - const int n_mand = n_lead + n_trail; - int keyword_given = rb_keyword_given_p(); - int empty_keyword_given = 0; - VALUE tmp_buffer = 0; - - if (!keyword_given) { - empty_keyword_given = rb_empty_keyword_given_p(); - } - - /* capture an option hash - phase 1: pop */ - /* Ignore final positional hash if empty keywords given */ - if (argc > 0 && !(f_hash && empty_keyword_given)) { - VALUE last = argv[argc - 1]; - - if (f_hash && n_mand < argc) { - if (keyword_given) { - if (!RB_TYPE_P(last, T_HASH)) { - rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash"); - } - else { - hash = last; - } - } - else if (NIL_P(last)) { - /* For backwards compatibility, nil is taken as an empty - option hash only if it is not ambiguous; i.e. '*' is - not specified and arguments are given more than sufficient. - This will be removed in Ruby 3. */ - if (!f_var && n_mand + n_opt < argc) { - rb_warn("The last argument is nil, treating as empty keywords"); - argc--; - } - } - else { - hash = rb_check_hash_type(last); - } - - /* Ruby 3: Remove if branch, as it will not attempt to split hashes */ - if (!NIL_P(hash)) { - VALUE opts = rb_extract_keywords(&hash); - - if (!(last_hash = hash)) { - if (!keyword_given) { - /* Warn if treating positional as keyword, as in Ruby 3, - this will be an error */ - rb_warn("Using the last argument as keyword parameters is deprecated"); - } - argc--; - } - else { - /* Warn if splitting either positional hash to keywords or keywords - to positional hash, as in Ruby 3, no splitting will be done */ - rb_warn("The last argument is split into positional and keyword parameters"); - last_idx = argc - 1; - } - hash = opts ? opts : Qnil; - } - } - else if (f_hash && keyword_given && n_mand == argc) { - /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */ - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - } - } - if (f_hash && n_mand > 0 && n_mand == argc+1 && empty_keyword_given) { - VALUE *ptr = (VALUE *)rb_alloc_tmp_buffer2(&tmp_buffer, argc+1, sizeof(VALUE)); - memcpy(ptr, argv, sizeof(VALUE)*argc); - ptr[argc] = rb_hash_new(); - argc++; - *(&argv) = ptr; - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - } - - - if (argc < n_mand) { - goto argc_error; - } - - /* capture leading mandatory arguments */ - for (i = n_lead; i-- > 0; ) { - var = vars[vari++]; - if (var) *var = (argi == last_idx) ? last_hash : argv[argi]; - argi++; - } - /* capture optional arguments */ - for (i = n_opt; i-- > 0; ) { - var = vars[vari++]; - if (argi < argc - n_trail) { - if (var) *var = (argi == last_idx) ? last_hash : argv[argi]; - argi++; - } - else { - if (var) *var = Qnil; - } - } - /* capture variable length arguments */ - if (f_var) { - int n_var = argc - argi - n_trail; - - var = vars[vari++]; - if (0 < n_var) { - if (var) { - int f_last = (last_idx + 1 == argc - n_trail); - *var = rb_ary_new4(n_var-f_last, &argv[argi]); - if (f_last) rb_ary_push(*var, last_hash); - } - argi += n_var; - } - else { - if (var) *var = rb_ary_new(); - } - } - /* capture trailing mandatory arguments */ - for (i = n_trail; i-- > 0; ) { - var = vars[vari++]; - if (var) *var = (argi == last_idx) ? last_hash : argv[argi]; - argi++; - } - /* capture an option hash - phase 2: assignment */ - if (f_hash) { - var = vars[vari++]; - if (var) *var = hash; - } - /* capture iterator block */ - if (f_block) { - var = vars[vari++]; - if (rb_block_given_p()) { - *var = rb_block_proc(); - } - else { - *var = Qnil; - } - } - - if (argi < argc) { - argc_error: - if (tmp_buffer) rb_free_tmp_buffer(&tmp_buffer); - rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); - } +RBIMPL_ATTR_NONNULL((3)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) +/** + * Our own locale-insensitive version of `snprintf(3)`. It can also be seen as + * a routine identical to rb_sprintf(), except it writes back to the passed + * buffer instead of allocating a new Ruby object. + * + * @param[out] str Return buffer + * @param[in] n Number of bytes of `str`. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ... Variadic number of contents to format. + * @return Number of bytes that would have been written to `str`, if `n` + * was large enough. Comparing this to `n` can give you insights + * that the buffer is too small or too big. Especially passing 0 + * to `n` gives you the exact number of bytes necessary to hold + * the result string without writing anything to anywhere. + * @post `str` holds up to `n-1` bytes of formatted contents (and the + * terminating NUL character.) + */ +int ruby_snprintf(char *str, size_t n, char const *fmt, ...); - if (tmp_buffer) rb_free_tmp_buffer(&tmp_buffer); - return argc; -} -#endif +RBIMPL_ATTR_NONNULL((3)) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0) +/** + * Identical to ruby_snprintf(), except it takes a `va_list`. It can also be + * seen as a routine identical to rb_vsprintf(), except it writes back to the + * passed buffer instead of allocating a new Ruby object. + * + * @param[out] str Return buffer + * @param[in] n Number of bytes of `str`. + * @param[in] fmt A `printf`-like format specifier. + * @param[in] ap Contents to format. + * @return Number of bytes that would have been written to `str`, if `n` + * was large enough. Comparing this to `n` can give you insights + * that the buffer is too small or too big. Especially passing 0 + * to `n` gives you the exact number of bytes necessary to hold + * the result string without writing anything to anywhere. + * @post `str` holds up to `n-1` bytes of formatted contents (and the + * terminating NUL character.) + */ +int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap); -#if defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) +/** @cond INTERNAL_MACRO */ +#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") +# /* Skip it; clang -pedantic doesn't like the following */ +#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) # define rb_yield_values(argc, ...) \ __extension__({ \ const int rb_yield_values_argc = (argc); \ @@ -2691,181 +296,16 @@ __extension__({ \ rb_funcall_nargs ? rb_funcall_args : NULL); \ }) #endif +/** @endcond */ #ifndef RUBY_DONT_SUBST #include "ruby/subst.h" #endif -/** - * @defgroup embed CRuby Embedding APIs - * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your - * program. - * These functions are not a part of Ruby extension library API. - * Extension libraries of Ruby should not depend on these functions. - * @{ - */ - -/** @defgroup ruby1 ruby(1) implementation - * A part of the implementation of ruby(1) command. - * Other programs that embed Ruby interpreter do not always need to use these - * functions. - * @{ - */ - -void ruby_sysinit(int *argc, char ***argv); -void ruby_init(void); -void* ruby_options(int argc, char** argv); -int ruby_executable_node(void *n, int *status); -int ruby_run_node(void *n); - -/* version.c */ -void ruby_show_version(void); -void ruby_show_copyright(void); - - -/*! A convenience macro to call ruby_init_stack(). Must be placed just after - * variable declarations */ -#define RUBY_INIT_STACK \ - VALUE variable_in_this_stack_frame; \ - ruby_init_stack(&variable_in_this_stack_frame); -/*! @} */ - -void ruby_init_stack(volatile VALUE*); - -int ruby_setup(void); -int ruby_cleanup(volatile int); - -void ruby_finalize(void); -NORETURN(void ruby_stop(int)); - -void ruby_set_stack_size(size_t); -int ruby_stack_check(void); -size_t ruby_stack_length(VALUE**); - -int ruby_exec_node(void *n); - -void ruby_script(const char* name); -void ruby_set_script_name(VALUE name); - -void ruby_prog_init(void); -void ruby_set_argv(int, char**); -void *ruby_process_options(int, char**); -void ruby_init_loadpath(void); -void ruby_incpush(const char*); -void ruby_sig_finalize(void); - -/*! @} */ - #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -extern "C++" { -#endif - -#ifdef RB_METHOD_DEFINITION_DECL - -RB_METHOD_DEFINITION_DECL(rb_define_method, (2,3), (VALUE klass, const char *name), (klass, name)) -#ifdef __cplusplus -#define rb_define_method(m, n, f, a) rb_define_method_tmpl::define(m, n, f) -#else -#define rb_define_method_if_constexpr(x, t, f) __builtin_choose_expr(__builtin_choose_expr(__builtin_constant_p(x),(x),0),(t),(f)) -#define rb_define_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_method15,rb_define_methodm3) -#define rb_define_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_method14,rb_define_method_choose_prototype15(n)) -#define rb_define_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_method13,rb_define_method_choose_prototype14(n)) -#define rb_define_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_method12,rb_define_method_choose_prototype13(n)) -#define rb_define_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_method11,rb_define_method_choose_prototype12(n)) -#define rb_define_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_method10,rb_define_method_choose_prototype11(n)) -#define rb_define_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_method9, rb_define_method_choose_prototype10(n)) -#define rb_define_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_method8, rb_define_method_choose_prototype9(n)) -#define rb_define_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_method7, rb_define_method_choose_prototype8(n)) -#define rb_define_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_method6, rb_define_method_choose_prototype7(n)) -#define rb_define_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_method5, rb_define_method_choose_prototype6(n)) -#define rb_define_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_method4, rb_define_method_choose_prototype5(n)) -#define rb_define_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_method3, rb_define_method_choose_prototype4(n)) -#define rb_define_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_method2, rb_define_method_choose_prototype3(n)) -#define rb_define_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_method1, rb_define_method_choose_prototype2(n)) -#define rb_define_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_method0, rb_define_method_choose_prototype1(n)) -#define rb_define_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_methodm1,rb_define_method_choose_prototype0(n)) -#define rb_define_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_methodm2,rb_define_method_choose_prototypem1(n)) -#define rb_define_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_methodm3,rb_define_method_choose_prototypem2(n)) -#define rb_define_method(klass, mid, func, arity) rb_define_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -RB_METHOD_DEFINITION_DECL(rb_define_module_function, (2,3), (VALUE klass, const char *name), (klass, name)) -#ifdef __cplusplus -#define rb_define_module_function(m, n, f, a) rb_define_module_function_tmpl::define(m, n, f) -#else -#define rb_define_module_function_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_module_function15,rb_define_module_functionm3) -#define rb_define_module_function_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_module_function14,rb_define_module_function_choose_prototype15(n)) -#define rb_define_module_function_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_module_function13,rb_define_module_function_choose_prototype14(n)) -#define rb_define_module_function_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_module_function12,rb_define_module_function_choose_prototype13(n)) -#define rb_define_module_function_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_module_function11,rb_define_module_function_choose_prototype12(n)) -#define rb_define_module_function_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_module_function10,rb_define_module_function_choose_prototype11(n)) -#define rb_define_module_function_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_module_function9, rb_define_module_function_choose_prototype10(n)) -#define rb_define_module_function_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_module_function8, rb_define_module_function_choose_prototype9(n)) -#define rb_define_module_function_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_module_function7, rb_define_module_function_choose_prototype8(n)) -#define rb_define_module_function_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_module_function6, rb_define_module_function_choose_prototype7(n)) -#define rb_define_module_function_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_module_function5, rb_define_module_function_choose_prototype6(n)) -#define rb_define_module_function_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_module_function4, rb_define_module_function_choose_prototype5(n)) -#define rb_define_module_function_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_module_function3, rb_define_module_function_choose_prototype4(n)) -#define rb_define_module_function_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_module_function2, rb_define_module_function_choose_prototype3(n)) -#define rb_define_module_function_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_module_function1, rb_define_module_function_choose_prototype2(n)) -#define rb_define_module_function_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_module_function0, rb_define_module_function_choose_prototype1(n)) -#define rb_define_module_function_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_module_functionm1,rb_define_module_function_choose_prototype0(n)) -#define rb_define_module_function_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_module_functionm2,rb_define_module_function_choose_prototypem1(n)) -#define rb_define_module_function_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_module_functionm3,rb_define_module_function_choose_prototypem2(n)) -#define rb_define_module_function(klass, mid, func, arity) rb_define_module_function_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity)); -#endif - -RB_METHOD_DEFINITION_DECL(rb_define_global_function, (1,2), (const char *name), (name)) -#ifdef __cplusplus -#define rb_define_global_function(n, f, a) rb_define_global_function_tmpl::define(n, f) -#else -#define rb_define_global_function_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_global_function15,rb_define_global_functionm3) -#define rb_define_global_function_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_global_function14,rb_define_global_function_choose_prototype15(n)) -#define rb_define_global_function_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_global_function13,rb_define_global_function_choose_prototype14(n)) -#define rb_define_global_function_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_global_function12,rb_define_global_function_choose_prototype13(n)) -#define rb_define_global_function_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_global_function11,rb_define_global_function_choose_prototype12(n)) -#define rb_define_global_function_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_global_function10,rb_define_global_function_choose_prototype11(n)) -#define rb_define_global_function_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_global_function9, rb_define_global_function_choose_prototype10(n)) -#define rb_define_global_function_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_global_function8, rb_define_global_function_choose_prototype9(n)) -#define rb_define_global_function_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_global_function7, rb_define_global_function_choose_prototype8(n)) -#define rb_define_global_function_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_global_function6, rb_define_global_function_choose_prototype7(n)) -#define rb_define_global_function_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_global_function5, rb_define_global_function_choose_prototype6(n)) -#define rb_define_global_function_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_global_function4, rb_define_global_function_choose_prototype5(n)) -#define rb_define_global_function_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_global_function3, rb_define_global_function_choose_prototype4(n)) -#define rb_define_global_function_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_global_function2, rb_define_global_function_choose_prototype3(n)) -#define rb_define_global_function_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_global_function1, rb_define_global_function_choose_prototype2(n)) -#define rb_define_global_function_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_global_function0, rb_define_global_function_choose_prototype1(n)) -#define rb_define_global_function_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_global_functionm1,rb_define_global_function_choose_prototype0(n)) -#define rb_define_global_function_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_global_functionm2,rb_define_global_function_choose_prototypem1(n)) -#define rb_define_global_function_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_global_functionm3,rb_define_global_function_choose_prototypem2(n)) -#define rb_define_global_function(mid, func, arity) rb_define_global_function_choose_prototypem3((arity),(func))((mid),(func),(arity)); -#endif - -#endif - -#if defined(RUBY_DEVEL) && RUBY_DEVEL && (!defined(__cplusplus) || defined(RB_METHOD_DEFINITION_DECL)) -# define RUBY_METHOD_FUNC(func) (func) -#else -# define RUBY_METHOD_FUNC(func) ((VALUE (*)(ANYARGS))(func)) -#endif - -#ifdef __cplusplus -#include "backward/cxxanyargs.hpp" - -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C++" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RUBY_H */ diff --git a/ruby/include/ruby/st.h b/ruby/include/ruby/st.h index ea1637bd9..1e4bb8068 100644 --- a/ruby/include/ruby/st.h +++ b/ruby/include/ruby/st.h @@ -1,7 +1,7 @@ /* This is a public domain general purpose hash table package originally written by Peter Moore @ UCB. - The hash table data strutures were redesigned and the package was + The hash table data structures were redesigned and the package was rewritten by Vladimir Makarov . */ #ifndef RUBY_ST_H diff --git a/ruby/include/ruby/subst.h b/ruby/include/ruby/subst.h index 1f0e6db5a..d7b9a6305 100644 --- a/ruby/include/ruby/subst.h +++ b/ruby/include/ruby/subst.h @@ -1,5 +1,12 @@ -#ifndef RUBY_SUBST_H +#ifndef RUBY_SUBST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_SUBST_H 1 +/** + * @author Ruby developers + * @copyright 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. + */ #undef snprintf #undef vsnprintf diff --git a/ruby/include/ruby/thread.h b/ruby/include/ruby/thread.h index d398cc127..18c792b38 100644 --- a/ruby/include/ruby/thread.h +++ b/ruby/include/ruby/thread.h @@ -1,36 +1,156 @@ -/********************************************************************** - - thread.h - - - $Author: matz $ - created at: Tue Jul 10 17:35:43 JST 2012 - - Copyright (C) 2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_THREAD_H +#ifndef RUBY_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_H 1 +/** + * @file + * @author $Author: matz $ + * @date Tue Jul 10 17:35:43 JST 2012 + * @copyright Copyright (C) 2007 Yukihiro Matsumoto + * @copyright 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. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/intern/thread.h" /* rb_unblock_function_t */ +#include "ruby/internal/dllexport.h" + +/** + * @name Flags for rb_nogvl() + * + * @{ + */ -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#include "ruby/intern.h" - -/* flags for rb_nogvl */ +/** + * Passing this flag to rb_nogvl() prevents it from checking interrupts. + * Interrupts can impact your program negatively. For instance consider + * following callback function: + * + * ```CXX + * static inline int fd; // set elsewhere. + * static inline auto callback(auto buf) { + * auto tmp = ruby_xmalloc(BUFSIZ); + * auto ret = ruby_xmalloc(sizeof(ssize_t)); // (a) + * auto n = read(fd, tmp, BUFSIZ); // (b) + * memcpy(buf, tmp, n); // (c) + * memcpy(ret, n, sizeof(n)); + * ruby_xfree(tmp); + * return ret; + * } + * ``` + * + * Here, if it gets interrupted at (a) or (b), `read(2)` is cancelled and this + * function leaks memory (which is not a good thing of course, but...). But if + * it gets interrupted at (c), where `read(2)` is already done, interruption is + * way more catastrophic because what was read gets lost. To reroute this kind + * of problem you should set this flag. And check interrupts elsewhere at your + * own risk. + */ #define RB_NOGVL_INTR_FAIL (0x1) -#define RB_NOGVL_UBF_ASYNC_SAFE (0x2) -RUBY_SYMBOL_EXPORT_BEGIN +/** + * Passing this flag to rb_nogvl() indicates that the passed UBF is + * async-signal-safe. An UBF could be async safe, and that makes things + * simpler. However async unsafe UBFs are just okay. If unsure, you can + * safely leave it unspecified. + * + * @internal + * + * This makes sense only in case of POSIX threads. + */ +#define RB_NOGVL_UBF_ASYNC_SAFE (0x2) +/** @} */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +RBIMPL_ATTR_NONNULL((1)) +/** + * (Re-)acquires the GVL. This manoeuvre makes it possible for an out-of-GVL + * routine to one-shot call a ruby method. + * + * What this function does: + * + * 1. Blocks until it acquires the GVL. + * 2. Calls the passed function. + * 3. Releases the GVL. + * 4. Returns what was returned form the passed function. + * + * @param[in] func What to call with GVL. + * @param[in,out] data1 Passed as-is to `func`. + * @return What was returned from `func`. + * @warning `func` must not return a Ruby object. If it did such return + * value would escape from GC's scope; would not be marked. + * @warning Global escapes from this function just yield whatever fatal + * undefined behaviours. You must make sure that `func` does + * not raise, by properly rescuing everything using + * e.g. rb_protect(). + * @warning You cannot convert a non-Ruby thread into a Ruby thread + * using this API. This function makes sense only from inside + * of a rb_thread_call_without_gvl()'s callback. + */ void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1); +RBIMPL_ATTR_NONNULL((1)) +/** + * Allows the passed function to run in parallel with other Ruby threads. + * + * What this function does: + * + * 1. Checks (and handles) pending interrupts. + * 2. Releases the GVL. (Others can run here in parallel...) + * 3. Calls the passed function. + * 4. Blocks until it re-acquires the GVL. + * 5. Checks interrupts that happened between 2 to 4. + * + * In case other threads interfaced with this thread using rb_thread_kill() + * etc., the passed UBF is additionally called. See ::rb_unblock_function_t + * for details. + * + * Unlike rb_thread_call_without_gvl2() this function also reacts to signals + * etc. + * + * @param[in] func A function to call without GVL. + * @param[in,out] data1 Passed as-is to `func`. + * @param[in] ubf An UBF to cancel `func`. + * @param[in,out] data2 Passed as-is to `ubf`. + * @return What `func` returned, or 0 in case `ubf` cancelled `func`. + * @warning You cannot use most of Ruby C APIs like calling methods or + * raising exceptions from any of the functions passed to it. + * If that is dead necessary use rb_thread_call_with_gvl() to + * re-acquire the GVL. + * @warning In short, this API is difficult. @ko1 recommends you to use + * other ways if any. We lack experiences to use this API. If + * you find any corner cases etc., please report it to the + * devs. + * @warning Releasing and re-acquiring the GVL are expensive operations. + * For a short-running `func`, it might be faster to just call + * `func` with blocking everything else. Be sure to benchmark + * your code to see if it is actually worth releasing the GVL. + */ void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_thread_call_without_gvl(), except it does not interface with + * signals etc. As described in #RB_NOGVL_INTR_FAIL, interrupts can hurt you. + * In case this function detects an interrupt, it returns immediately. You can + * record progress of your callback and check it after returning from this + * function. + * + * What this function does: + * + * 1. Checks for pending interrupts and if any, just returns. + * 2. Releases the GVL. (Others can run here in parallel...) + * 3. Calls the passed function. + * 4. Blocks until it re-acquires the GVL. + * + * @param[in] func A function to call without GVL. + * @param[in,out] data1 Passed as-is to `func`. + * @param[in] ubf An UBF to cancel `func`. + * @param[in,out] data2 Passed as-is to `ubf`. + * @return What `func` returned, or 0 in case `func` did not return. + */ void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); @@ -38,20 +158,38 @@ void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, * XXX: unstable/unapproved - out-of-tree code should NOT not depend * on this until it hits Ruby 2.6.1 */ + +RBIMPL_ATTR_NONNULL((1)) +/** + * Identical to rb_thread_call_without_gvl(), except it additionally takes + * "flags" that change the behaviour. + * + * @param[in] func A function to call without GVL. + * @param[in,out] data1 Passed as-is to `func`. + * @param[in] ubf An UBF to cancel `func`. + * @param[in,out] data2 Passed as-is to `ubf`. + * @param[in] flags Flags. + * @return What `func` returned, or 0 in case `func` did not return. + */ void *rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags); +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01 -#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_ -RUBY_SYMBOL_EXPORT_END +/** + * @private + * @deprecated It seems even in the old days it made no sense...? + */ +#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_ -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_THREAD_H */ diff --git a/ruby/include/ruby/thread_native.h b/ruby/include/ruby/thread_native.h index 8e500c5a1..2945ff1e4 100644 --- a/ruby/include/ruby/thread_native.h +++ b/ruby/include/ruby/thread_native.h @@ -1,28 +1,24 @@ -/********************************************************************** - - thread_native.h - - - $Author: ko1 $ - created at: Wed May 14 19:37:31 2014 - - Copyright (C) 2014 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_THREAD_NATIVE_H +#ifndef RUBY_THREAD_NATIVE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_NATIVE_H 1 - -/* +/** + * @file + * @author $Author: ko1 $ + * @date Wed May 14 19:37:31 2014 + * @copyright Copyright (C) 2014 Yukihiro Matsumoto + * @copyright 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. + * * This file contains wrapper APIs for native thread primitives * which Ruby interpreter uses. * - * Now, we only suppors pthread and Windows threads. + * Now, we only support pthread and Windows threads. * * If you want to use Ruby's Mutex and so on to synchronize Ruby Threads, * please use Mutex directly. */ - #if defined(_WIN32) #include typedef HANDLE rb_nativethread_id_t; @@ -32,25 +28,172 @@ typedef union rb_thread_lock_union { CRITICAL_SECTION crit; } rb_nativethread_lock_t; +typedef struct rb_thread_cond_struct rb_nativethread_cond_t; + #elif defined(HAVE_PTHREAD_H) + #include typedef pthread_t rb_nativethread_id_t; typedef pthread_mutex_t rb_nativethread_lock_t; +typedef pthread_cond_t rb_nativethread_cond_t; + +#elif defined(__DOXYGEN__) + +/** Opaque type that holds an ID of a native thread. */ +struct rb_nativethread_id_t; + +/** Opaque type that holds a lock. */ +struct rb_nativethread_lock_t; + +/** Opaque type that holds a condition variable. */ +struct rb_nativethread_cond_t; #else #error "unsupported thread type" #endif -RUBY_SYMBOL_EXPORT_BEGIN +RBIMPL_SYMBOL_EXPORT_BEGIN() -rb_nativethread_id_t rb_nativethread_self(); +/** + * Queries the ID of the native thread that is calling this function. + * + * @return The caller thread's native ID. + */ +rb_nativethread_id_t rb_nativethread_self(void); +/** + * Fills the passed lock with an initial value. + * + * @param[out] lock A mutex to initialise. + * @post `lock` is updated to its initial state. + * + * @internal + * + * There is no data structure that analogous to pthread_once_t in ruby. It is + * pretty much tricky (if not impossible) to properly initialise a mutex + * exactly once. + */ void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock); + +/** + * Destroys the passed mutex. + * + * @param[out] lock A mutex to kill. + * @post `lock` is no longer eligible for other functions. + * + * @internal + * + * It is an undefined behaviour (see `pthread_mutex_destroy(3posix)`) to + * destroy a locked mutex. So it has to be unlocked. But an unlocked mutex + * can of course be locked by another thread. That's the ultimate reason why + * we do mutex. There is an inevitable race condition here. 2017 edition of + * IEEE 1003.1 issue 7 says in its rationale that "care must be taken". Care? + * How? + * + * @shyouhei thinks that POSIX is broken by design. + */ void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock); + +/** + * Blocks until the current thread obtains a lock. + * + * @param[out] lock A mutex to lock. + * @post `lock` is owned by the current native thread. + */ void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock); + +/** + * Releases a lock. + * + * @param[out] lock A mutex to unlock. + * @pre `lock` is owned by the current native thread. + * @post `lock` is not owned by the current native thread. + */ void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock); -RUBY_SYMBOL_EXPORT_END +/** @alias{rb_nativethread_lock_lock} */ +void rb_native_mutex_lock(rb_nativethread_lock_t *lock); + +/** + * Identical to rb_native_mutex_lock(), except it doesn't block in case + * rb_native_mutex_lock() would. + * + * @param[out] lock A mutex to lock. + * @retval 0 `lock` is successfully owned by the current thread. + * @retval EBUSY `lock` is owned by someone else. + */ +int rb_native_mutex_trylock(rb_nativethread_lock_t *lock); + +/** @alias{rb_nativethread_lock_unlock} */ +void rb_native_mutex_unlock(rb_nativethread_lock_t *lock); + +/** @alias{rb_nativethread_lock_initialize} */ +void rb_native_mutex_initialize(rb_nativethread_lock_t *lock); + +/** @alias{rb_nativethread_lock_destroy} */ +void rb_native_mutex_destroy(rb_nativethread_lock_t *lock); + +/** + * Signals a condition variable. + * + * @param[out] cond A condition variable to ping. + * @post More than one threads waiting for `cond` gets signalled. + * @note This function can spuriously wake multiple threads up. + * `pthread_cond_signal(3posix)` says it can even be "impossible + * to avoid the unblocking of more than one thread blocked on a + * condition variable". Just brace spurious wakeups. + */ +void rb_native_cond_signal(rb_nativethread_cond_t *cond); + +/** + * Signals a condition variable. + * + * @param[out] cond A condition variable to ping. + * @post All threads waiting for `cond` gets signalled. + */ +void rb_native_cond_broadcast(rb_nativethread_cond_t *cond); + +/** + * Waits for the passed condition variable to be signalled. + * + * @param[out] cond A condition variable to wait. + * @param[out] mutex A mutex. + * @pre `mutex` is owned by the current thread. + * @post `mutex` is owned by the current thread. + * @note This can wake up spuriously. + */ +void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex); + +/** + * Identical to rb_native_cond_wait(), except it additionally takes timeout in + * msec resolution. Timeouts can be detected by catching exceptions. + * + * @param[out] cond A condition variable to wait. + * @param[out] mutex A mutex. + * @param[in] msec Timeout. + * @exception rb_eSystemCallError `Errno::ETIMEDOUT` for timeout. + * @pre `mutex` is owned by the current thread. + * @post `mutex` is owned by the current thread. + * @note This can wake up spuriously. + */ +void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec); + +/** + * Fills the passed condition variable with an initial value. + * + * @param[out] cond A condition variable to initialise. + * @post `cond` is updated to its initial state. + */ +void rb_native_cond_initialize(rb_nativethread_cond_t *cond); + +/** + * Destroys the passed condition variable. + * + * @param[out] cond A condition variable to kill. + * @post `cond` is no longer eligible for other functions. + */ +void rb_native_cond_destroy(rb_nativethread_cond_t *cond); +RBIMPL_SYMBOL_EXPORT_END() #endif diff --git a/ruby/include/ruby/util.h b/ruby/include/ruby/util.h index 3fecba8eb..b2bc1a09f 100644 --- a/ruby/include/ruby/util.h +++ b/ruby/include/ruby/util.h @@ -1,60 +1,125 @@ -/********************************************************************** - - util.h - - - $Author$ - created at: Thu Mar 9 11:55:53 JST 1995 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_UTIL_H +#ifndef RUBY_UTIL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_UTIL_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif +/** + * @file + * @author $Author$ + * @date Thu Mar 9 11:55:53 JST 1995 + * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto + * @copyright 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. + * @warning DO NOT ADD RANDOM GARBAGES IN THIS FILE! Contents of this file + * reside here for historical reasons. Find a right place for your + * API! + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include /* size_t */ #endif -#include "ruby/defines.h" -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H +#if HAVE_SYS_TYPES_H +# include /* ssize_t */ #endif -#ifndef _ -#ifdef __cplusplus -# ifndef HAVE_PROTOTYPES -# define HAVE_PROTOTYPES 1 -# endif -# ifndef HAVE_STDARG_PROTOTYPES -# define HAVE_STDARG_PROTOTYPES 1 -# endif -#endif -#ifdef HAVE_PROTOTYPES -# define _(args) args -#else -# define _(args) () -#endif -#ifdef HAVE_STDARG_PROTOTYPES -# define __(args) args -#else -# define __(args) () -#endif -#endif +#include "ruby/internal/attr/noalias.h" +#include "ruby/internal/attr/nodiscard.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/restrict.h" +#include "ruby/internal/attr/returns_nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/defines.h" -RUBY_SYMBOL_EXPORT_BEGIN +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** an approximation of ceil(n * log10(2)), up to 65536 at least */ #define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999) -/* an approximation of ceil(n * log10(2)), up to 65536 at least */ +/** + * Character to number mapping like `'a'` -> `10`, `'b'` -> `11` etc. For + * punctuation etc., the value is -1. "36" terminology comes from the fact + * that this is the table behind `str.to_i(36)`. + */ +RUBY_EXTERN const signed char ruby_digit36_to_number_table[]; + +/** + * Characters that Ruby accepts as hexadecimal digits. This is `/\h/` expanded + * into an array. + */ +RUBY_EXTERN const char ruby_hexdigits[]; + +/** + * Scans the passed string, assuming the string is a textual representation of + * an integer. Stops when encountering something non-digit for the passed + * base. + * + * @note This does not understand minus sign. + * @note This does not understand e.g. `0x` prefix. + * @note It is a failure to pass `0` to `base`, unlike ruby_strtoul(). + * @param[in] str Target string of digits to interpret. + * @param[in] len Number of bytes of `str`, or -1 to detect `NUL`. + * @param[in] base Base, `2` to `36` inclusive. + * @param[out] retlen Return value buffer. + * @param[out] overflow Return value buffer. + * @return Interpreted numeric representation of `str`. + * @post `retlen` is the number of bytes scanned so far. + * @post `overflow` is set to true if the string represents something + * bigger than `ULONG_MAX`. Something meaningful still returns; + * which is the designed belabour of C's unsigned arithmetic. + */ +unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); + +/** @old{ruby_scan_oct} */ #define scan_oct(s,l,e) ((int)ruby_scan_oct((s),(l),(e))) -unsigned long ruby_scan_oct(const char *, size_t, size_t *); + +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL(()) +/** + * Interprets the passed string as an octal unsigned integer. Stops when + * encounters something not understood. + * + * @param[in] str C string to scan. + * @param[in] len Length of `str`. + * @param[out] consumed Return value buffer. + * @return Parsed integer. + * @post `ret` is the number of characters read. + * + * @internal + * + * No consideration is made for integer overflows. As the return value is + * unsigned this function has fully defined behaviour, but you cannot know if + * there was an integer wrap-around or not. + */ +unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed); + +/** @old{ruby_scan_hex} */ #define scan_hex(s,l,e) ((int)ruby_scan_hex((s),(l),(e))) -unsigned long ruby_scan_hex(const char *, size_t, size_t *); +RBIMPL_ATTR_NONNULL(()) +/** + * Interprets the passed string a hexadecimal unsigned integer. Stops when + * encounters something not understood. + * + * @param[in] str C string to scan. + * @param[in] len Length of `str`. + * @param[out] ret Return value buffer. + * @return Parsed integer. + * @post `ret` is the number of characters read. + * + * @internal + * + * No consideration is made for integer overflows. As the return value is + * unsigned this function has fully defined behaviour, but you cannot know if + * there was an integer wrap-around or not. + */ +unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret); + +/** + * Reentrant implementation of quick sort. If your system provides something + * (like C11 qsort_s), this is a thin wrapper of that routine. Otherwise + * resorts to our own version. + */ #ifdef HAVE_GNU_QSORT_R # define ruby_qsort qsort_r #else @@ -62,28 +127,102 @@ void ruby_qsort(void *, const size_t, const size_t, int (*)(const void *, const void *, void *), void *); #endif -void ruby_setenv(const char *, const char *); -void ruby_unsetenv(const char *); +RBIMPL_ATTR_NONNULL((1)) +/** + * Sets an environment variable. In case of POSIX this is a wrapper of + * `setenv(3)`. But there are systems which lack one. We try hard emulating. + * + * @param[in] key An environment variable. + * @param[in] val A value to be associated with `key`, or 0. + * @exception rb_eSystemCallError `setenv(3)` failed for some reason. + * @post Environment variable `key` is created if necessary. Its value + * is updated to be `val`. + */ +void ruby_setenv(const char *key, const char *val); + +RBIMPL_ATTR_NONNULL(()) +/** + * Deletes the passed environment variable, if any. + * + * @param[in] key An environment variable. + * @exception rb_eSystemCallError `unsetenv(3)` failed for some reason. + * @post Environment variable `key` does not exist. + */ +void ruby_unsetenv(const char *key); + +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +RBIMPL_ATTR_NONNULL(()) +/** + * This is our own version of `strdup(3)` that uses ruby_xmalloc() instead of + * system malloc (benefits our GC). + * + * @param[in] str Target C string to duplicate. + * @return An allocated C string holding the identical contents. + * @note Return value must be discarded using ruby_xfree(). + */ +char *ruby_strdup(const char *str); -char *ruby_strdup(const char *); #undef strdup +/** + * @alias{ruby_strdup} + * + * @internal + * + * @shyouhei doesn't think it is a wise idea. ruby_strdup()'s return value + * must be passed to ruby_xfree(), but this macro makes it almost impossible. + */ #define strdup(s) ruby_strdup(s) +RBIMPL_ATTR_NODISCARD() +RBIMPL_ATTR_RESTRICT() +RBIMPL_ATTR_RETURNS_NONNULL() +/** + * This is our own version of `getcwd(3)` that uses ruby_xmalloc() instead of + * system malloc (benefits our GC). + * + * @return An allocated C string holding the process working directory. + * @note Return value must be discarded using ruby_xfree(). + */ char *ruby_getcwd(void); -double ruby_strtod(const char *, char **); +RBIMPL_ATTR_NONNULL((1)) +/** + * Our own locale-insensitive version of `strtod(3)`. The conversion is done + * as if the current locale is set to the "C" locale, no matter actual runtime + * locale settings. + * + * @param[in] str Decimal or hexadecimal representation of a floating + * point number. + * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return). + * @return Converted number. + * @post If `endptr` is not NULL, it is updated to point the first such + * byte where conversion failed. + * @note This function sets `errno` on failure. + * - `ERANGE`: Converted integer is out of range of `double`. + * @see William D. Clinger, "How to Read Floating Point Numbers + * Accurately" in Proc. ACM SIGPLAN '90, pp. 92-101. + * https://doi.org/10.1145/93542.93557 + */ +double ruby_strtod(const char *str, char **endptr); + #undef strtod +/** @alias{ruby_strtod} */ #define strtod(s,e) ruby_strtod((s),(e)) -void ruby_each_words(const char *, void (*)(const char*, int, void*), void *); - -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_ATTR_NONNULL((2)) +/** + * Scans the passed string, with calling the callback function every time it + * encounters a "word". A word here is a series of characters separated by + * either a space (of IEEE 1003.1 section 7.3.1.1), or a `','`. + * + * @param[in] str Target string to split into each words. + * @param[in] func Callback function. + * @param[in,out] argv Passed as-is to `func`. + */ +void ruby_each_words(const char *str, void (*func)(const char *word, int len, void *argv), void *argv); + +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_UTIL_H */ diff --git a/ruby/include/ruby/version.h b/ruby/include/ruby/version.h index 64c5c614e..104f78a0c 100644 --- a/ruby/include/ruby/version.h +++ b/ruby/include/ruby/version.h @@ -1,17 +1,17 @@ -/********************************************************************** - - ruby/version.h - - - $Author$ - created at: Wed May 13 12:56:56 JST 2009 - - Copyright (C) 1993-2009 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -/* +#ifndef RUBY_VERSION_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RUBY_VERSION_H 1 +/** + * @file + * @author $Author$ + * @date Wed May 13 12:56:56 JST 2009 + * @copyright Copyright (C) 1993-2009 Yukihiro Matsumoto + * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. + * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan + * @copyright 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. + * * This file contains only * - never-changeable information, and * - interfaces accessible from extension libraries. @@ -20,55 +20,139 @@ * check the features with mkmf.rb instead. */ -#ifndef RUBY_VERSION_H -#define RUBY_VERSION_H 1 +/** + * @name The origin. + * + * These information never change. Just written here to remember. + * + * @{ + */ -/* The origin. */ +/** Author of this project. */ #define RUBY_AUTHOR "Yukihiro Matsumoto" + +/** Ruby's birth year. */ #define RUBY_BIRTH_YEAR 1993 + +/** Ruby's birth month. */ #define RUBY_BIRTH_MONTH 2 + +/** Ruby's birth day. */ #define RUBY_BIRTH_DAY 24 -/* API version */ -#define RUBY_API_VERSION_MAJOR 2 -#define RUBY_API_VERSION_MINOR 7 +/** @} */ + +/** + * @name The API version. + * + * API version is different from binary version. These numbers are for API + * stability. When you have distinct API versions x and y, you cannot expect + * codes targeted to x also works for y. + * + * However let us repeat here that it's a BAD idea to check + * #RUBY_API_VERSION_CODE form extension libraries. Different API versions are + * just different. There is no such thing like upper compatibility. + * + * @{ + */ + +/** + * Major version. This digit changes sometimes for various reasons, but that + * doesn't mean a total rewrite. Practically when it comes to API versioning, + * major and minor version changes are equally catastrophic. + */ +#define RUBY_API_VERSION_MAJOR 3 + +/** + * Minor version. As of writing this version changes annually. Greater + * version doesn't mean "better"; they just mean years passed. + */ +#define RUBY_API_VERSION_MINOR 1 + +/** + * Teeny version. This digit is kind of reserved these days. Kept 0 for the + * entire 2.x era. Waiting for future uses. + */ #define RUBY_API_VERSION_TEENY 0 + +/** + * This macro is API versions encoded into a C integer. + * + * @note Use mkmf. + * @note Don't rely on it. + */ #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) -#ifdef RUBY_EXTERN -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif +/** @} */ -RUBY_SYMBOL_EXPORT_BEGIN +#ifdef RUBY_EXTERN +/* Internal note: this file could be included from verconf.mk _before_ + * generating config.h, on Windows. The #ifdef above is to trick such + * situation. */ +RBIMPL_SYMBOL_EXPORT_BEGIN() -/* - * Interfaces from extension libraries. +/** + * @name Interfaces from extension libraries. * * Before using these infos, think thrice whether they are really * necessary or not, and if the answer was yes, think twice a week * later again. + * + * @{ */ + +/** API versions, in { major, minor, teeny } order. */ RUBY_EXTERN const int ruby_api_version[3]; + +/** + * Stringised version. + * + * @note This is the runtime version, not the API version. For instance it + * was `"2.5.9"` when ::ruby_api_version was `{ 2, 5, 0 }`. + */ RUBY_EXTERN const char ruby_version[]; + +/** Date of release, in a C string. */ RUBY_EXTERN const char ruby_release_date[]; + +/** + * Target platform identifier, in a C string. + * + * @note Seasoned UNIX programmers should beware that this "platform + * identifier" is our invention; not always identical to so-called + * target triplets that GNU systems use. For instance on @shyouhei's + * machine, ::ruby_platform is `"x64_64-linux"` while its target triplet + * is `x86_64-pc-linux-gnu`. + * @note Note also that we support Windows. + */ RUBY_EXTERN const char ruby_platform[]; + +/** + * This is a monotonic increasing integer that describes specific "patch" + * level. You can know the exact changeset your binary is running by this info + * (and ::ruby_version), unless this is -1. -1 means there is no release yet + * for the version; ruby is actively developed. 0 means the initial GA version. + */ RUBY_EXTERN const int ruby_patchlevel; + +/** + * This is what `ruby -v` prints to the standard error. Something like: + * `"ruby 2.5.9p229 (2021-04-05 revision 67829) [x86_64-linux]"` + */ RUBY_EXTERN const char ruby_description[]; + +/** Copyright notice. */ RUBY_EXTERN const char ruby_copyright[]; + +/** + * This is just `"ruby"` for us. But different implementations can have + * different strings here. + */ RUBY_EXTERN const char ruby_engine[]; -RUBY_SYMBOL_EXPORT_END +/** @} */ -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif #endif diff --git a/ruby/include/ruby/vm.h b/ruby/include/ruby/vm.h index b137a280c..3458c28be 100644 --- a/ruby/include/ruby/vm.h +++ b/ruby/include/ruby/vm.h @@ -1,36 +1,34 @@ -/********************************************************************** - - ruby/vm.h - - - $Author$ - created at: Sat May 31 15:17:36 2008 - - Copyright (C) 2008 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_VM_H +#ifndef RUBY_VM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_VM_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -RUBY_SYMBOL_EXPORT_BEGIN - -/* Place holder. - * - * We will prepare VM creation/control APIs on 1.9.2 or later. +/** + * @file + * @author $Author$ + * @date Sat May 31 15:17:36 2008 + * @copyright Copyright (C) 2008 Yukihiro Matsumoto + * @copyright 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. * + * We planned to have multiple VMs run side-by-side. The API here was a + * preparation of that feature. The topic branch was eventually abandoned, and + * we now have Ractor. This file is kind of obsolescent. */ +#include "ruby/internal/dllexport.h" -/* VM type declaration */ +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/** + * The opaque struct to hold VM internals. Its fields are intentionally hidden + * from extension libraries because it changes drastically time to time. + */ typedef struct rb_vm_struct ruby_vm_t; -/* core API */ +/** + * Destructs the passed VM. You don't have to call this API directly now, + * because there is no way to create one. There is only one VM at one time. + * ruby_stop() should just suffice. + */ int ruby_vm_destruct(ruby_vm_t *vm); /** @@ -51,13 +49,6 @@ int ruby_vm_destruct(ruby_vm_t *vm); */ void ruby_vm_at_exit(void(*func)(ruby_vm_t *)); -RUBY_SYMBOL_EXPORT_END - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_VM_H */ diff --git a/ruby/include/ruby/win32.h b/ruby/include/ruby/win32.h index b29470b0c..c8ae599f2 100644 --- a/ruby/include/ruby/win32.h +++ b/ruby/include/ruby/win32.h @@ -138,18 +138,18 @@ typedef int clockid_t; #undef stat #undef fstat #ifdef RUBY_EXPORT -#define utime(_p, _t) rb_w32_utime(_p, _t) +#define utime(_p, _t) rb_w32_uutime(_p, _t) #undef HAVE_UTIMES #define HAVE_UTIMES 1 -#define utimes(_p, _t) rb_w32_utimes(_p, _t) +#define utimes(_p, _t) rb_w32_uutimes(_p, _t) #undef HAVE_UTIMENSAT #define HAVE_UTIMENSAT 1 #define AT_FDCWD -100 -#define utimensat(_d, _p, _t, _f) rb_w32_utimensat(_d, _p, _t, _f) +#define utimensat(_d, _p, _t, _f) rb_w32_uutimensat(_d, _p, _t, _f) #define lseek(_f, _o, _w) rb_w32_lseek(_f, _o, _w) #define pipe(p) rb_w32_pipe(p) -#define open rb_w32_open +#define open rb_w32_uopen #define close(h) rb_w32_close(h) #define fclose(f) rb_w32_fclose(f) #define read(f, b, s) rb_w32_read(f, b, s) @@ -160,16 +160,16 @@ typedef int clockid_t; #define Sleep(msec) (void)rb_w32_Sleep(msec) #undef execv -#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv) +#define execv(path,argv) rb_w32_uaspawn(P_OVERLAY,path,argv) #undef isatty #define isatty(h) rb_w32_isatty(h) #undef mkdir -#define mkdir(p, m) rb_w32_mkdir(p, m) +#define mkdir(p, m) rb_w32_umkdir(p, m) #undef rmdir -#define rmdir(p) rb_w32_rmdir(p) +#define rmdir(p) rb_w32_urmdir(p) #undef unlink -#define unlink(p) rb_w32_unlink(p) +#define unlink(p) rb_w32_uunlink(p) #endif /* RUBY_EXPORT */ /* same with stati64 except the size of st_ino and nanosecond timestamps */ @@ -191,7 +191,6 @@ struct stati128 { long st_ctimensec; }; -#if SIZEOF_OFF_T == 8 #define off_t __int64 #define stat stati128 #undef SIZEOF_STRUCT_STAT_ST_INO @@ -201,15 +200,9 @@ struct stati128 { #define HAVE_STRUCT_STAT_ST_MTIMENSEC #define HAVE_STRUCT_STAT_ST_CTIMENSEC #define fstat(fd,st) rb_w32_fstati128(fd,st) -#define stati128(path, st) rb_w32_stati128(path,st) -#else -#define stat(path,st) rb_w32_stat(path,st) -#define fstat(fd,st) rb_w32_fstat(fd,st) -extern int rb_w32_stat(const char *, struct stat *); -extern int rb_w32_fstat(int, struct stat *); -#endif -#define lstat(path,st) rb_w32_lstati128(path,st) -#define access(path,mode) rb_w32_access(path,mode) +#define stati128(path, st) rb_w32_ustati128(path,st) +#define lstat(path,st) rb_w32_ulstati128(path,st) +#define access(path,mode) rb_w32_uaccess(path,mode) #define strcasecmp _stricmp #define strncasecmp _strnicmp @@ -258,7 +251,6 @@ struct ifaddrs { extern void rb_w32_sysinit(int *, char ***); extern DWORD rb_w32_osid(void); -extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *); extern int flock(int fd, int oper); extern int rb_w32_io_cancelable_p(int); extern int rb_w32_is_socket(int); @@ -294,10 +286,8 @@ extern struct servent *WSAAPI rb_w32_getservbyport(int, const char *); extern int socketpair(int, int, int, int *); extern int getifaddrs(struct ifaddrs **); extern void freeifaddrs(struct ifaddrs *); -extern char * rb_w32_getcwd(char *, int); +extern char * rb_w32_ugetcwd(char *, int); extern char * rb_w32_ugetenv(const char *); -extern char * rb_w32_getenv(const char *); -extern int rb_w32_rename(const char *, const char *); extern int rb_w32_urename(const char *, const char *); extern char **rb_w32_get_environ(void); extern void rb_w32_free_environ(char **); @@ -306,22 +296,16 @@ extern const char *WSAAPI rb_w32_inet_ntop(int,const void *,char *,size_t); extern int WSAAPI rb_w32_inet_pton(int,const char *,void *); extern DWORD rb_w32_osver(void); -extern int chown(const char *, int, int); extern int rb_w32_uchown(const char *, int, int); -extern int link(const char *, const char *); extern int rb_w32_ulink(const char *, const char *); -extern ssize_t readlink(const char *, char *, size_t); extern ssize_t rb_w32_ureadlink(const char *, char *, size_t); extern ssize_t rb_w32_wreadlink(const WCHAR *, WCHAR *, size_t); -extern int symlink(const char *src, const char *link); extern int rb_w32_usymlink(const char *src, const char *link); extern int gettimeofday(struct timeval *, struct timezone *); extern int clock_gettime(clockid_t, struct timespec *); extern int clock_getres(clockid_t, struct timespec *); -extern rb_pid_t waitpid (rb_pid_t, int *, int); -extern rb_pid_t rb_w32_spawn(int, const char *, const char*); -extern rb_pid_t rb_w32_aspawn(int, const char *, char *const *); -extern rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD); +extern rb_pid_t waitpid(rb_pid_t, int *, int); +extern rb_pid_t wait(int *); extern rb_pid_t rb_w32_uspawn(int, const char *, const char*); extern rb_pid_t rb_w32_uaspawn(int, const char *, char *const *); extern rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD); @@ -332,18 +316,12 @@ extern rb_pid_t rb_w32_getpid(void); extern rb_pid_t rb_w32_getppid(void); extern int rb_w32_isatty(int); extern int rb_w32_uchdir(const char *); -extern int rb_w32_mkdir(const char *, int); extern int rb_w32_umkdir(const char *, int); -extern int rb_w32_rmdir(const char *); extern int rb_w32_urmdir(const char *); -extern int rb_w32_unlink(const char *); extern int rb_w32_uunlink(const char *); extern int rb_w32_uchmod(const char *, int); -extern int rb_w32_stati128(const char *, struct stati128 *); extern int rb_w32_ustati128(const char *, struct stati128 *); -extern int rb_w32_lstati128(const char *, struct stati128 *); extern int rb_w32_ulstati128(const char *, struct stati128 *); -extern int rb_w32_access(const char *, int); extern int rb_w32_uaccess(const char *, int); extern char rb_w32_fd_is_text(int); extern int rb_w32_fstati128(int, struct stati128 *); @@ -365,14 +343,6 @@ rb_infinity_float(void) #endif #if !defined __MINGW32__ || defined __NO_ISOCEXT -#ifndef isnan -#define isnan(x) _isnan(x) -#endif -static inline int -finite(double x) -{ - return _finite(x); -} #ifndef copysign #define copysign(a, b) _copysign(a, b) #endif @@ -381,8 +351,6 @@ scalb(double a, long b) { return _scalb(a, b); } -#else -__declspec(dllimport) extern int finite(double); #endif #if !defined S_IFIFO && defined _S_IFIFO @@ -441,11 +409,7 @@ extern int rb_w32_utruncate(const char *path, off_t length); #undef HAVE_TRUNCATE #define HAVE_TRUNCATE 1 -#if defined HAVE_TRUNCATE64 -#define truncate truncate64 -#else -#define truncate rb_w32_truncate -#endif +#define truncate rb_w32_utruncate #if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1800 #define strtoll _strtoi64 @@ -714,13 +678,13 @@ extern char *rb_w32_strerror(int); #define get_osfhandle(h) rb_w32_get_osfhandle(h) #undef getcwd -#define getcwd(b, s) rb_w32_getcwd(b, s) +#define getcwd(b, s) rb_w32_ugetcwd(b, s) #undef getenv -#define getenv(n) rb_w32_getenv(n) +#define getenv(n) rb_w32_ugetenv(n) #undef rename -#define rename(o, n) rb_w32_rename(o, n) +#define rename(o, n) rb_w32_urename(o, n) #undef times #define times(t) rb_w32_times(t) @@ -743,7 +707,6 @@ struct tm *localtime_r(const time_t *, struct tm *); /* thread stuff */ int rb_w32_sleep(unsigned long msec); -int rb_w32_open(const char *, int, ...); int rb_w32_uopen(const char *, int, ...); int rb_w32_wopen(const WCHAR *, int, ...); int rb_w32_close(int); @@ -752,11 +715,8 @@ int rb_w32_pipe(int[2]); ssize_t rb_w32_read(int, void *, size_t); ssize_t rb_w32_write(int, const void *, size_t); off_t rb_w32_lseek(int, off_t, int); -int rb_w32_utime(const char *, const struct utimbuf *); int rb_w32_uutime(const char *, const struct utimbuf *); -int rb_w32_utimes(const char *, const struct timeval *); int rb_w32_uutimes(const char *, const struct timeval *); -int rb_w32_utimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */); int rb_w32_uutimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */); long rb_w32_write_console(uintptr_t, int); /* use uintptr_t instead of VALUE because it's not defined yet here */ int WINAPI rb_w32_Sleep(unsigned long msec); @@ -767,6 +727,27 @@ int rb_w32_unwrap_io_handle(int); WCHAR *rb_w32_mbstr_to_wstr(UINT, const char *, int, long *); char *rb_w32_wstr_to_mbstr(UINT, const WCHAR *, int, long *); +DEPRECATED_BY(rb_w32_ugetcwd, char *rb_w32_getcwd(char *, int)); +DEPRECATED_BY(rb_w32_ugetenv, char *rb_w32_getenv(const char *)); +DEPRECATED_BY(rb_w32_urename, int rb_w32_rename(const char *, const char *)); +DEPRECATED_BY(rb_w32_uopen, int rb_w32_open(const char *, int, ...)); +DEPRECATED_BY(rb_w32_uchown, int chown(const char *, int, int)); +DEPRECATED_BY(rb_w32_ulink, int link(const char *, const char *)); +DEPRECATED_BY(rb_w32_ureadlink, ssize_t readlink(const char *, char *, size_t)); +DEPRECATED_BY(rb_w32_usymlink, int symlink(const char *src, const char *link)); +DEPRECATED_BY(rb_w32_umkdir, int rb_w32_mkdir(const char *, int)); +DEPRECATED_BY(rb_w32_urmdir, int rb_w32_rmdir(const char *)); +DEPRECATED_BY(rb_w32_uunlink, int rb_w32_unlink(const char *)); +DEPRECATED_BY(rb_w32_uutime, int rb_w32_utime(const char *, const struct utimbuf *)); +DEPRECATED_BY(rb_w32_uutimes, int rb_w32_utimes(const char *, const struct timeval *)); +DEPRECATED_BY(rb_w32_uutimensat, int rb_w32_utimensat(int, const char *, const struct timespec *, int)); +DEPRECATED_BY(rb_w32_ustati128, int rb_w32_stati128(const char *, struct stati128 *)); +DEPRECATED_BY(rb_w32_ulstati128, int rb_w32_lstati128(const char *, struct stati128 *)); +DEPRECATED_BY(rb_w32_uaccess, int rb_w32_access(const char *, int)); +DEPRECATED_BY(rb_w32_uspawn, rb_pid_t rb_w32_spawn(int, const char *, const char*)); +DEPRECATED_BY(rb_w32_uaspawn, rb_pid_t rb_w32_aspawn(int, const char *, char *const *)); +DEPRECATED_BY(rb_w32_uaspawn_flags, rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD)); + /* == ***CAUTION*** Since this function is very dangerous, ((*NEVER*)) diff --git a/ruby/inits.c b/ruby/inits.c index 79a6cf014..8c230c6df 100644 --- a/ruby/inits.c +++ b/ruby/inits.c @@ -9,8 +9,10 @@ **********************************************************************/ -#include "internal.h" +#include "internal/inits.h" +#include "ruby.h" #include "builtin.h" +static void Init_builtin_prelude(void); #include "prelude.rbinc" #define CALL(n) {void Init_##n(void); Init_##n();} @@ -18,6 +20,7 @@ void rb_call_inits(void) { + CALL(Thread_Mutex); #if USE_TRANSIENT_HEAP CALL(TransientHeap); #endif @@ -35,7 +38,6 @@ rb_call_inits(void) CALL(String); CALL(Exception); CALL(eval); - CALL(safe); CALL(jump); CALL(Numeric); CALL(Bignum); @@ -44,10 +46,12 @@ rb_call_inits(void) CALL(Hash); CALL(Struct); CALL(Regexp); + CALL(pack); CALL(transcode); CALL(marshal); CALL(Range); CALL(IO); + CALL(IO_Buffer) CALL(Dir); CALL(Time); CALL(Random); @@ -56,27 +60,47 @@ rb_call_inits(void) CALL(Proc); CALL(Binding); CALL(Math); + CALL(GC); CALL(Enumerator); + CALL(Ractor); CALL(VM); CALL(ISeq); CALL(Thread); + CALL(Fiber_Scheduler); CALL(process); CALL(Cont); CALL(Rational); CALL(Complex); + CALL(MemoryView); CALL(version); + CALL(vm_trace); CALL(vm_stack_canary); + CALL(ast); CALL(gc_stress); // enable builtin loading CALL(builtin); +} - CALL(GC); - CALL(IO_nonblock); - CALL(ast); - CALL(vm_trace); - CALL(pack); - CALL(warning); - load_prelude(); +void +rb_call_builtin_inits(void) +{ +#define BUILTIN(n) CALL(builtin_##n) + BUILTIN(gc); + BUILTIN(ractor); + BUILTIN(numeric); + BUILTIN(io); + BUILTIN(dir); + BUILTIN(ast); + BUILTIN(trace_point); + BUILTIN(pack); + BUILTIN(warning); + BUILTIN(array); + BUILTIN(kernel); + BUILTIN(timev); + BUILTIN(yjit); + BUILTIN(nilclass); + BUILTIN(marshal); + Init_builtin_prelude(); } #undef CALL diff --git a/ruby/insns.def b/ruby/insns.def index bd1bffbe0..87624a050 100644 --- a/ruby/insns.def +++ b/ruby/insns.def @@ -210,10 +210,10 @@ getinstancevariable (ID id, IVC ic) () (VALUE val) -/* "instance variable not initialized" warning can be hooked. */ -// attr bool leaf = false; /* has rb_warning() */ +/* Ractor crashes when it accesses class/module-level instances variables. */ +// attr bool leaf = false; /* has IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() */ { - val = vm_getinstancevariable(GET_SELF(), id, ic); + val = vm_getinstancevariable(GET_ISEQ(), GET_SELF(), id, ic); } /* Set value of instance variable id of self to val. */ @@ -224,32 +224,33 @@ setinstancevariable () // attr bool leaf = false; /* has rb_check_frozen_internal() */ { - vm_setinstancevariable(GET_SELF(), id, val, ic); + vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic); } /* Get value of class variable id of klass as val. */ DEFINE_INSN getclassvariable -(ID id) +(ID id, IVC ic) () (VALUE val) /* "class variable access from toplevel" warning can be hooked. */ // attr bool leaf = false; /* has rb_warning() */ { - val = rb_cvar_get(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id); + rb_control_frame_t *cfp = GET_CFP(); + val = vm_getclassvariable(GET_ISEQ(), cfp, id, (ICVARC)ic); } /* Set value of class variable id of klass as val. */ DEFINE_INSN setclassvariable -(ID id) +(ID id, IVC ic) (VALUE val) () /* "class variable access from toplevel" warning can be hooked. */ // attr bool leaf = false; /* has rb_warning() */ { vm_ensure_not_refinement_module(GET_SELF()); - rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val); + vm_setclassvariable(GET_ISEQ(), GET_CFP(), id, val, (ICVARC)ic); } /* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants @@ -288,25 +289,23 @@ setconstant /* get global variable id. */ DEFINE_INSN getglobal -(GENTRY entry) +(ID gid) () (VALUE val) -// attr bool leaf = leafness_of_getglobal(entry); +// attr bool leaf = false; { - struct rb_global_entry *gentry = (void *)entry; - val = rb_gvar_get(gentry); + val = rb_gvar_get(gid); } /* set global variable id as val. */ DEFINE_INSN setglobal -(GENTRY entry) +(ID gid) (VALUE val) () -// attr bool leaf = leafness_of_setglobal(entry); +// attr bool leaf = false; { - struct rb_global_entry *gentry = (void *)entry; - rb_gvar_set(gentry, val); + rb_gvar_set(gid, val); } /**********************************************************/ @@ -351,6 +350,7 @@ putspecialobject (rb_num_t value_type) () (VALUE val) +// attr bool leaf = (value_type == VM_SPECIAL_OBJECT_VMCORE); /* others may raise when allocating singleton */ { enum vm_special_object_type type; @@ -365,7 +365,7 @@ putstring () (VALUE val) { - val = rb_str_resurrect(str); + val = rb_ec_str_resurrect(ec, str); } /* put concatenate strings */ @@ -375,16 +375,17 @@ concatstrings (...) (VALUE val) /* This instruction can concat UTF-8 and binary strings, resulting in - * Encoding::CompatiblityError. */ + * Encoding::CompatibilityError. */ // attr bool leaf = false; /* has rb_enc_cr_str_buf_cat() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { val = rb_str_concat_literals(num, STACK_ADDR_FROM_TOP(num)); } -/* push the result of to_s. */ +/* Convert the result to string if not already a string. + This is used as a backup if to_s does not return a string. */ DEFINE_INSN -tostring +anytostring () (VALUE val, VALUE str) (VALUE val) @@ -392,16 +393,6 @@ tostring val = rb_obj_as_string_result(str, val); } -/* Freeze (dynamically) created strings. if debug_info is given, set it. */ -DEFINE_INSN -freezestring -(VALUE debug_info) -(VALUE str) -(VALUE str) -{ - vm_freezestring(str, debug_info); -} - /* compile str to Regexp and push it. opt is the option for the Regexp. */ @@ -438,7 +429,7 @@ newarray (VALUE val) // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { - val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num)); + val = rb_ec_ary_new_from_values(ec, num, STACK_ADDR_FROM_TOP(num)); } /* put new array initialized with num values on the stack. There @@ -536,11 +527,13 @@ newhash { RUBY_DTRACE_CREATE_HOOK(HASH, num); - val = rb_hash_new_with_size(num / 2); - if (num) { + val = rb_hash_new_with_size(num / 2); rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val); } + else { + val = rb_hash_new(); + } } /* put new Range object.(Range.new(low, high, flag)) */ @@ -604,25 +597,6 @@ swap /* none */ } -/* reverse stack top N order. */ -DEFINE_INSN -reverse -(rb_num_t n) -(...) -(...) -// attr rb_snum_t sp_inc = 0; -{ - rb_num_t i; - VALUE *sp = STACK_ADDR_FROM_TOP(n); - - for (i=0; ibody->iseq_encoded, GET_SP(), class_iseq->body->local_table_size, class_iseq->body->stack_max); @@ -775,11 +752,11 @@ send (CALL_DATA cd, ISEQ blockiseq) (...) (VALUE val) -// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci); +// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci); // attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci); { - VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), &cd->ci, blockiseq, false); - val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_method_wrap); + VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, false); + val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method); if (val == Qundef) { RESTORE_REGS(); @@ -794,11 +771,11 @@ opt_send_without_block (...) (VALUE val) // attr bool handles_sp = true; -// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci); +// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci); // attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci); { VALUE bh = VM_BLOCK_HANDLER_NONE; - val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_method_wrap); + val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method); if (val == Qundef) { RESTORE_REGS(); @@ -806,6 +783,21 @@ opt_send_without_block } } +/* Convert object to string using to_s or equivalent. */ +DEFINE_INSN +objtostring +(CALL_DATA cd) +(VALUE recv) +(VALUE val) +// attr bool leaf = false; +{ + val = vm_objtostring(GET_ISEQ(), recv, cd); + + if (val == Qundef) { + CALL_SIMPLE_METHOD(); + } +} + DEFINE_INSN opt_str_freeze (VALUE str, CALL_DATA cd) @@ -827,7 +819,7 @@ opt_nil_p (VALUE recv) (VALUE val) { - val = vm_opt_nil_p(cd, recv); + val = vm_opt_nil_p(GET_ISEQ(), cd, recv); if (val == Qundef) { CALL_SIMPLE_METHOD(); @@ -860,7 +852,7 @@ opt_newarray_max // attr bool leaf = false; /* has rb_funcall() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { - val = vm_opt_newarray_max(num, STACK_ADDR_FROM_TOP(num)); + val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num)); } DEFINE_INSN @@ -872,7 +864,7 @@ opt_newarray_min // attr bool leaf = false; /* has rb_funcall() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { - val = vm_opt_newarray_min(num, STACK_ADDR_FROM_TOP(num)); + val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num)); } /* super(args) # args.size => num */ @@ -881,11 +873,11 @@ invokesuper (CALL_DATA cd, ISEQ blockiseq) (...) (VALUE val) -// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci); +// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci); // attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci); { - VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), &cd->ci, blockiseq, true); - val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_super_method); + VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, true); + val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super); if (val == Qundef) { RESTORE_REGS(); @@ -900,15 +892,11 @@ invokeblock (...) (VALUE val) // attr bool handles_sp = true; -// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(&cd->ci); +// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(cd->ci); // attr rb_snum_t comptime_sp_inc = sp_inc_of_invokeblock(ci); { - if (UNLIKELY(cd->cc.call != vm_invokeblock_i)) { - cd->cc.call = vm_invokeblock_i; // check before setting to avoid CoW - } - VALUE bh = VM_BLOCK_HANDLER_NONE; - val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_invokeblock); + val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock); if (val == Qundef) { RESTORE_REGS(); @@ -977,7 +965,7 @@ jump () () /* Same discussion as leave. */ -// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */ +// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { RUBY_VM_CHECK_INTS(ec); JUMP(dst); @@ -990,7 +978,7 @@ branchif (VALUE val) () /* Same discussion as jump. */ -// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */ +// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (RTEST(val)) { RUBY_VM_CHECK_INTS(ec); @@ -1005,7 +993,7 @@ branchunless (VALUE val) () /* Same discussion as jump. */ -// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */ +// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (!RTEST(val)) { RUBY_VM_CHECK_INTS(ec); @@ -1020,7 +1008,7 @@ branchnil (VALUE val) () /* Same discussion as jump. */ -// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */ +// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (NIL_P(val)) { RUBY_VM_CHECK_INTS(ec); @@ -1039,9 +1027,10 @@ opt_getinlinecache () (VALUE val) { - if (vm_ic_hit_p(ic, GET_EP())) { - val = ic->value; - JUMP(dst); + struct iseq_inline_constant_cache_entry *ice = ic->entry; + if (ice && vm_ic_hit_p(ice, GET_EP())) { + val = ice->value; + JUMP(dst); } else { val = Qnil; @@ -1054,8 +1043,9 @@ opt_setinlinecache (IC ic) (VALUE val) (VALUE val) +// attr bool leaf = false; { - vm_ic_update(ic, val, GET_EP()); + vm_ic_update(GET_ISEQ(), ic, val, GET_EP()); } /* run iseq only once */ @@ -1150,7 +1140,7 @@ opt_mod (CALL_DATA cd) (VALUE recv, VALUE obj) (VALUE val) -/* Same discussion as opt_mod. */ +/* Same discussion as opt_div. */ // attr bool leaf = false; { val = vm_opt_mod(recv, obj); @@ -1167,7 +1157,7 @@ opt_eq (VALUE recv, VALUE obj) (VALUE val) { - val = opt_eq_func(recv, obj, cd); + val = opt_equality(GET_ISEQ(), recv, obj, cd); if (val == Qundef) { CALL_SIMPLE_METHOD(); @@ -1181,7 +1171,7 @@ opt_neq (VALUE recv, VALUE obj) (VALUE val) { - val = vm_opt_neq(cd, cd_eq, recv, obj); + val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj); if (val == Qundef) { CALL_SIMPLE_METHOD(); @@ -1431,7 +1421,7 @@ opt_not (VALUE recv) (VALUE val) { - val = vm_opt_not(cd, recv); + val = vm_opt_not(GET_ISEQ(), cd, recv); if (val == Qundef) { CALL_SIMPLE_METHOD(); @@ -1454,7 +1444,7 @@ opt_regexpmatch2 } /* call native compiled method */ -DEFINE_INSN +DEFINE_INSN_IF(SUPPORT_CALL_C_FUNCTION) opt_call_c_function (rb_insn_func_t funcptr) () @@ -1479,11 +1469,11 @@ DEFINE_INSN invokebuiltin (RB_BUILTIN bf) (...) -(VALUE ret) +(VALUE val) // attr bool leaf = false; /* anything can happen inside */ // attr rb_snum_t sp_inc = 1 - bf->argc; { - ret = vm_invoke_builtin(ec, reg_cfp, bf, STACK_ADDR_FROM_TOP(bf->argc)); + val = vm_invoke_builtin(ec, reg_cfp, bf, STACK_ADDR_FROM_TOP(bf->argc)); } /* call specific function with args (same parameters) */ @@ -1491,10 +1481,10 @@ DEFINE_INSN opt_invokebuiltin_delegate (RB_BUILTIN bf, rb_num_t index) () -(VALUE ret) +(VALUE val) // attr bool leaf = false; /* anything can happen inside */ { - ret = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index); + val = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index); } /* call specific function with args (same parameters) and leave */ @@ -1508,7 +1498,7 @@ opt_invokebuiltin_delegate_leave val = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index); /* leave fastpath */ - /* TracePoint/return should fallback this insn to opt_invokebuiltin_delegate */ + /* TracePoint/return fallbacks this insn to opt_invokebuiltin_delegate */ if (vm_pop_frame(ec, GET_CFP(), GET_EP())) { #if OPT_CALL_THREADED_CODE rb_ec_thread_ptr(ec)->retval = val; diff --git a/ruby/internal.h b/ruby/internal.h index d5f1b93b3..00a829529 100644 --- a/ruby/internal.h +++ b/ruby/internal.h @@ -1,2702 +1,109 @@ -/********************************************************************** - - internal.h - - - $Author$ - created at: Tue May 17 11:42:20 JST 2011 - - Copyright (C) 2011 Yukihiro Matsumoto - -**********************************************************************/ - -#ifndef RUBY_INTERNAL_H +#ifndef RUBY_INTERNAL_H /*-*-C-*-vi:se ft=c:*/ #define RUBY_INTERNAL_H 1 +/** + * @author $Author$ + * @date Tue May 17 11:42:20 JST 2011 + * @copyright Copyright (C) 2011 Yukihiro Matsumoto + * @copyright 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. + */ +#include "ruby/internal/config.h" -#include "ruby.h" - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#ifdef HAVE_STDBOOL_H -# include -#else -# include "missing/stdbool.h" +#ifdef __cplusplus +# error not for C++ #endif -/* The most significant bit of the lower part of half-long integer. - * If sizeof(long) == 4, this is 0x8000. - * If sizeof(long) == 8, this is 0x80000000. - */ -#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2)) - #define LIKELY(x) RB_LIKELY(x) #define UNLIKELY(x) RB_UNLIKELY(x) -#ifndef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x -#endif - -#ifndef WARN_UNUSED_RESULT -# define WARN_UNUSED_RESULT(x) x -#endif - -#ifndef __has_feature -# define __has_feature(x) 0 -#endif - -#ifndef __has_extension -# define __has_extension __has_feature -#endif - -#if 0 -#elif defined(NO_SANITIZE) && __has_feature(memory_sanitizer) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ - NO_SANITIZE("memory", NO_SANITIZE("address", NOINLINE(x))) -#elif defined(NO_SANITIZE) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ - NO_SANITIZE("address", NOINLINE(x)) -#elif defined(NO_SANITIZE_ADDRESS) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ - NO_SANITIZE_ADDRESS(NOINLINE(x)) -#elif defined(NO_ADDRESS_SAFETY_ANALYSIS) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ - NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x)) -#else -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x -#endif - -#if defined(NO_SANITIZE) && defined(__GNUC__) &&! defined(__clang__) -/* GCC warns about unknown sanitizer, which is annoying. */ -#undef NO_SANITIZE -#define NO_SANITIZE(x, y) \ - COMPILER_WARNING_PUSH; \ - COMPILER_WARNING_IGNORED(-Wattributes); \ - __attribute__((__no_sanitize__(x))) y; \ - COMPILER_WARNING_POP -#endif - -#ifndef NO_SANITIZE -# define NO_SANITIZE(x, y) y -#endif - -#ifdef HAVE_VALGRIND_MEMCHECK_H -# include -# ifndef VALGRIND_MAKE_MEM_DEFINED -# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n)) -# endif -# ifndef VALGRIND_MAKE_MEM_UNDEFINED -# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n)) -# endif -#else -# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0 -# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 -#endif - #define numberof(array) ((int)(sizeof(array) / sizeof((array)[0]))) - -#ifndef MJIT_HEADER - -#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H -# include -#endif - -#if !__has_feature(address_sanitizer) -# define __asan_poison_memory_region(x, y) -# define __asan_unpoison_memory_region(x, y) -# define __asan_region_is_poisoned(x, y) 0 -#endif - -#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H -# if __has_feature(memory_sanitizer) -# include -# endif -#endif - -#if !__has_feature(memory_sanitizer) -# define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) -# define __msan_poison(x, y) ((void)(x), (void)(y)) -# define __msan_unpoison(x, y) ((void)(x), (void)(y)) -# define __msan_unpoison_string(x) ((void)(x)) -#endif - -/*! - * This function asserts that a (continuous) memory region from ptr to size - * being "poisoned". Both read / write access to such memory region are - * prohibited until properly unpoisoned. The region must be previously - * allocated (do not pass a freed pointer here), but not necessarily be an - * entire object that the malloc returns. You can punch hole a part of a - * gigantic heap arena. This is handy when you do not free an allocated memory - * region to reuse later: poison when you keep it unused, and unpoison when you - * reuse. - * - * \param[in] ptr pointer to the beginning of the memory region to poison. - * \param[in] size the length of the memory region to poison. - */ -static inline void -asan_poison_memory_region(const volatile void *ptr, size_t size) -{ - __msan_poison(ptr, size); - __asan_poison_memory_region(ptr, size); -} - -/*! - * This is a variant of asan_poison_memory_region that takes a VALUE. - * - * \param[in] obj target object. - */ -static inline void -asan_poison_object(VALUE obj) -{ - MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; - asan_poison_memory_region(ptr, SIZEOF_VALUE); -} - -#if !__has_feature(address_sanitizer) -#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) -#else -#define asan_poison_object_if(ptr, obj) do { \ - if (ptr) asan_poison_object(obj); \ - } while (0) -#endif - -/*! - * This function predicates if the given object is fully addressable or not. - * - * \param[in] obj target object. - * \retval 0 the given object is fully addressable. - * \retval otherwise pointer to first such byte who is poisoned. - */ -static inline void * -asan_poisoned_object_p(VALUE obj) -{ - MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; - return __asan_region_is_poisoned(ptr, SIZEOF_VALUE); -} - -/*! - * This function asserts that a (formally poisoned) memory region from ptr to - * size is now addressable. Write access to such memory region gets allowed. - * However read access might or might not be possible depending on situations, - * because the region can have contents of previous usages. That information - * should be passed by the malloc_p flag. If that is true, the contents of the - * region is _not_ fully defined (like the return value of malloc behaves). - * Reading from there is NG; write something first. If malloc_p is false on - * the other hand, that memory region is fully defined and can be read - * immediately. - * - * \param[in] ptr pointer to the beginning of the memory region to unpoison. - * \param[in] size the length of the memory region. - * \param[in] malloc_p if the memory region is like a malloc's return value or not. - */ -static inline void -asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p) -{ - __asan_unpoison_memory_region(ptr, size); - if (malloc_p) { - __msan_allocated_memory(ptr, size); - } - else { - __msan_unpoison(ptr, size); - } -} - -/*! - * This is a variant of asan_unpoison_memory_region that takes a VALUE. - * - * \param[in] obj target object. - * \param[in] malloc_p if the memory region is like a malloc's return value or not. - */ -static inline void -asan_unpoison_object(VALUE obj, bool newobj_p) -{ - MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; - asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); -} - -#endif +#define roomof(x, y) (((x) + (y) - 1) / (y)) +#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) /* Prevent compiler from reordering access */ #define ACCESS_ONCE(type,x) (*((volatile type *)&(x))) -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -# define STATIC_ASSERT(name, expr) _Static_assert(expr, #name ": " #expr) -#elif GCC_VERSION_SINCE(4, 6, 0) || __has_extension(c_static_assert) -# define STATIC_ASSERT(name, expr) RB_GNUC_EXTENSION _Static_assert(expr, #name ": " #expr) -#else -# define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)] -#endif - -#define SIGNED_INTEGER_TYPE_P(int_type) (0 > ((int_type)0)-1) -#define SIGNED_INTEGER_MAX(sint_type) \ - (sint_type) \ - ((((sint_type)1) << (sizeof(sint_type) * CHAR_BIT - 2)) | \ - ((((sint_type)1) << (sizeof(sint_type) * CHAR_BIT - 2)) - 1)) -#define SIGNED_INTEGER_MIN(sint_type) (-SIGNED_INTEGER_MAX(sint_type)-1) -#define UNSIGNED_INTEGER_MAX(uint_type) (~(uint_type)0) - -#if SIGNEDNESS_OF_TIME_T < 0 /* signed */ -# define TIMET_MAX SIGNED_INTEGER_MAX(time_t) -# define TIMET_MIN SIGNED_INTEGER_MIN(time_t) -#elif SIGNEDNESS_OF_TIME_T > 0 /* unsigned */ -# define TIMET_MAX UNSIGNED_INTEGER_MAX(time_t) -# define TIMET_MIN ((time_t)0) -#endif -#define TIMET_MAX_PLUS_ONE (2*(double)(TIMET_MAX/2+1)) - -#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P -#define MUL_OVERFLOW_P(a, b) \ - __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0) -#elif defined HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW -#define MUL_OVERFLOW_P(a, b) \ - RB_GNUC_EXTENSION_BLOCK(__typeof__(a) c; __builtin_mul_overflow((a), (b), &c)) -#endif - -#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_BUILTIN___BUILTIN_MUL_OVERFLOW_P -/* __builtin_mul_overflow_p can take bitfield */ -/* and GCC permits bitfields for integers other than int */ -#define MUL_OVERFLOW_FIXNUM_P(a, b) RB_GNUC_EXTENSION_BLOCK( \ - struct { long fixnum : SIZEOF_LONG * CHAR_BIT - 1; } c; \ - __builtin_mul_overflow_p((a), (b), c.fixnum); \ -) -#else -#define MUL_OVERFLOW_FIXNUM_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX) -#endif - -#ifdef MUL_OVERFLOW_P -#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b) -#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b) -#define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b) -#else -#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX) -#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX) -#define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX) -#endif - -#ifndef swap16 -# ifdef HAVE_BUILTIN___BUILTIN_BSWAP16 -# define swap16(x) __builtin_bswap16(x) -# endif -#endif - -#ifndef swap16 -# define swap16(x) ((uint16_t)((((x)&0xFF)<<8) | (((x)>>8)&0xFF))) -#endif - -#ifndef swap32 -# ifdef HAVE_BUILTIN___BUILTIN_BSWAP32 -# define swap32(x) __builtin_bswap32(x) -# endif -#endif - -#ifndef swap32 -# define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \ - |(((x)>>24)&0xFF) \ - |(((x)&0x0000FF00)<<8) \ - |(((x)&0x00FF0000)>>8) )) -#endif - -#ifndef swap64 -# ifdef HAVE_BUILTIN___BUILTIN_BSWAP64 -# define swap64(x) __builtin_bswap64(x) -# endif -#endif - -#ifndef swap64 -# ifdef HAVE_INT64_T -# define byte_in_64bit(n) ((uint64_t)0xff << (n)) -# define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \ - |(((x)>>56)&0xFF) \ - |(((x)&byte_in_64bit(8))<<40) \ - |(((x)&byte_in_64bit(48))>>40) \ - |(((x)&byte_in_64bit(16))<<24) \ - |(((x)&byte_in_64bit(40))>>24) \ - |(((x)&byte_in_64bit(24))<<8) \ - |(((x)&byte_in_64bit(32))>>8))) -# endif -#endif - -static inline unsigned int -nlz_int(unsigned int x) -{ -#if defined(HAVE_BUILTIN___BUILTIN_CLZ) - if (x == 0) return SIZEOF_INT * CHAR_BIT; - return (unsigned int)__builtin_clz(x); -#else - unsigned int y; -# if 64 < SIZEOF_INT * CHAR_BIT - unsigned int n = 128; -# elif 32 < SIZEOF_INT * CHAR_BIT - unsigned int n = 64; -# else - unsigned int n = 32; -# endif -# if 64 < SIZEOF_INT * CHAR_BIT - y = x >> 64; if (y) {n -= 64; x = y;} -# endif -# if 32 < SIZEOF_INT * CHAR_BIT - y = x >> 32; if (y) {n -= 32; x = y;} -# endif - 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_long(unsigned long x) -{ -#if defined(HAVE_BUILTIN___BUILTIN_CLZL) - if (x == 0) return SIZEOF_LONG * CHAR_BIT; - return (unsigned int)__builtin_clzl(x); -#else - unsigned long y; -# if 64 < SIZEOF_LONG * CHAR_BIT - unsigned int n = 128; -# elif 32 < SIZEOF_LONG * CHAR_BIT - unsigned int n = 64; -# else - unsigned int n = 32; -# endif -# if 64 < SIZEOF_LONG * CHAR_BIT - y = x >> 64; if (y) {n -= 64; x = y;} -# endif -# if 32 < SIZEOF_LONG * CHAR_BIT - y = x >> 32; if (y) {n -= 32; x = y;} -# endif - 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_LONG_LONG -static inline unsigned int -nlz_long_long(unsigned LONG_LONG x) -{ -#if defined(HAVE_BUILTIN___BUILTIN_CLZLL) - if (x == 0) return SIZEOF_LONG_LONG * CHAR_BIT; - return (unsigned int)__builtin_clzll(x); -#else - unsigned LONG_LONG y; -# if 64 < SIZEOF_LONG_LONG * CHAR_BIT - unsigned int n = 128; -# elif 32 < SIZEOF_LONG_LONG * CHAR_BIT - unsigned int n = 64; -# else - unsigned int n = 32; -# endif -# if 64 < SIZEOF_LONG_LONG * CHAR_BIT - y = x >> 64; if (y) {n -= 64; x = y;} -# endif -# if 32 < SIZEOF_LONG_LONG * CHAR_BIT - y = x >> 32; if (y) {n -= 32; x = y;} -# endif - 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 -} -#endif - -#ifdef HAVE_UINT128_T -static inline unsigned int -nlz_int128(uint128_t x) -{ - uint128_t y; - unsigned int n = 128; - y = x >> 64; if (y) {n -= 64; x = y;} - 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 - -static inline unsigned int -nlz_intptr(uintptr_t x) -{ -#if SIZEOF_UINTPTR_T == SIZEOF_INT - return nlz_int(x); -#elif SIZEOF_UINTPTR_T == SIZEOF_LONG - return nlz_long(x); -#elif SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG - return nlz_long_long(x); -#else - #error no known integer type corresponds uintptr_t - return /* sane compiler */ ~0; -#endif -} - -static inline unsigned int -rb_popcount32(uint32_t x) -{ -#ifdef HAVE_BUILTIN___BUILTIN_POPCOUNT - return (unsigned int)__builtin_popcount(x); -#else - x = (x & 0x55555555) + (x >> 1 & 0x55555555); - x = (x & 0x33333333) + (x >> 2 & 0x33333333); - x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f); - x = (x & 0x001f001f) + (x >> 8 & 0x001f001f); - return (x & 0x0000003f) + (x >>16 & 0x0000003f); -#endif -} - -static inline int -rb_popcount64(uint64_t x) -{ -#ifdef HAVE_BUILTIN___BUILTIN_POPCOUNT - return __builtin_popcountll(x); -#else - x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555); - x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333); - x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707); - x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f); - x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f); - return (x & 0x7f) + (x >>32 & 0x7f); -#endif -} - -static inline int -rb_popcount_intptr(uintptr_t x) -{ -#if SIZEOF_VOIDP == 8 - return rb_popcount64(x); -#elif SIZEOF_VOIDP == 4 - return rb_popcount32(x); -#endif -} - -static inline int -ntz_int32(uint32_t x) -{ -#ifdef HAVE_BUILTIN___BUILTIN_CTZ - return __builtin_ctz(x); -#else - return rb_popcount32((~x) & (x-1)); -#endif -} - -static inline int -ntz_int64(uint64_t x) -{ -#ifdef HAVE_BUILTIN___BUILTIN_CTZLL - return __builtin_ctzll(x); -#else - return rb_popcount64((~x) & (x-1)); -#endif -} - -static inline int -ntz_intptr(uintptr_t x) -{ -#if SIZEOF_VOIDP == 8 - return ntz_int64(x); -#elif SIZEOF_VOIDP == 4 - return ntz_int32(x); -#endif -} - -#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG -# define DLONG LONG_LONG -# define DL2NUM(x) LL2NUM(x) -#elif defined(HAVE_INT128_T) -# define DLONG int128_t -# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x)) -VALUE rb_int128t2big(int128_t n); -#endif - -static inline long -rb_overflowed_fix_to_int(long x) -{ - return (long)((unsigned long)(x >> 1) ^ (1LU << (SIZEOF_LONG * CHAR_BIT - 1))); -} - -static inline VALUE -rb_fix_plus_fix(VALUE x, VALUE y) -{ -#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW - long lz; - /* NOTE - * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))` - + = `((lx*2+1)/2 + (ly*2+1)/2)*2+1` - + = `lx*2 + ly*2 + 1` - + = `(lx*2+1) + (ly*2+1) - 1` - + = `x + y - 1` - * (2) Fixnum's LSB is always 1. - * It means you can always run `x - 1` without overflow. - * (3) Of course `z = x + (y-1)` may overflow. - * At that time true value is - * * positive: 0b0 1xxx...1, and z = 0b1xxx...1 - * * nevative: 0b1 0xxx...1, and z = 0b0xxx...1 - * To convert this true value to long, - * (a) Use arithmetic shift - * * positive: 0b11xxx... - * * negative: 0b00xxx... - * (b) invert MSB - * * positive: 0b01xxx... - * * negative: 0b10xxx... - */ - if (__builtin_add_overflow((long)x, (long)y-1, &lz)) { - return rb_int2big(rb_overflowed_fix_to_int(lz)); - } - else { - return (VALUE)lz; - } -#else - long lz = FIX2LONG(x) + FIX2LONG(y); - return LONG2NUM(lz); -#endif -} - -static inline VALUE -rb_fix_minus_fix(VALUE x, VALUE y) -{ -#ifdef HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW - long lz; - if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) { - return rb_int2big(rb_overflowed_fix_to_int(lz)); - } - else { - return (VALUE)lz; - } -#else - long lz = FIX2LONG(x) - FIX2LONG(y); - return LONG2NUM(lz); -#endif -} - -/* arguments must be Fixnum */ -static inline VALUE -rb_fix_mul_fix(VALUE x, VALUE y) -{ - long lx = FIX2LONG(x); - long ly = FIX2LONG(y); -#ifdef DLONG - return DL2NUM((DLONG)lx * (DLONG)ly); -#else - if (MUL_OVERFLOW_FIXNUM_P(lx, ly)) { - return rb_big_mul(rb_int2big(lx), rb_int2big(ly)); - } - else { - return LONG2FIX(lx * ly); - } -#endif -} - -/* - * This behaves different from C99 for negative arguments. - * Note that div may overflow fixnum. - */ -static inline void -rb_fix_divmod_fix(VALUE a, VALUE b, VALUE *divp, VALUE *modp) -{ - /* assume / and % comply C99. - * ldiv(3) won't be inlined by GCC and clang. - * I expect / and % are compiled as single idiv. - */ - long x = FIX2LONG(a); - long y = FIX2LONG(b); - long div, mod; - if (x == FIXNUM_MIN && y == -1) { - if (divp) *divp = LONG2NUM(-FIXNUM_MIN); - if (modp) *modp = LONG2FIX(0); - return; - } - div = x / y; - mod = x % y; - if (y > 0 ? mod < 0 : mod > 0) { - mod += y; - div -= 1; - } - if (divp) *divp = LONG2FIX(div); - if (modp) *modp = LONG2FIX(mod); -} - -/* div() for Ruby - * This behaves different from C99 for negative arguments. - */ -static inline VALUE -rb_fix_div_fix(VALUE x, VALUE y) -{ - VALUE div; - rb_fix_divmod_fix(x, y, &div, NULL); - return div; -} - -/* mod() for Ruby - * This behaves different from C99 for negative arguments. - */ -static inline VALUE -rb_fix_mod_fix(VALUE x, VALUE y) -{ - VALUE mod; - rb_fix_divmod_fix(x, y, NULL, &mod); - return mod; -} - -#if defined(HAVE_UINT128_T) && defined(HAVE_LONG_LONG) -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \ - sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \ - sizeof(x) <= SIZEOF_LONG_LONG ? SIZEOF_LONG_LONG * CHAR_BIT - nlz_long_long((unsigned LONG_LONG)(x)) : \ - SIZEOF_INT128_T * CHAR_BIT - nlz_int128((uint128_t)(x))) -#elif defined(HAVE_UINT128_T) -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \ - sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \ - SIZEOF_INT128_T * CHAR_BIT - nlz_int128((uint128_t)(x))) -#elif defined(HAVE_LONG_LONG) -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \ - sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \ - SIZEOF_LONG_LONG * CHAR_BIT - nlz_long_long((unsigned LONG_LONG)(x))) -#else -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \ - SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x))) -#endif - -#ifndef BDIGIT -# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG -# define BDIGIT unsigned int -# define SIZEOF_BDIGIT SIZEOF_INT -# define BDIGIT_DBL unsigned LONG_LONG -# define BDIGIT_DBL_SIGNED LONG_LONG -# define PRI_BDIGIT_PREFIX "" -# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX -# elif SIZEOF_INT*2 <= SIZEOF_LONG -# define BDIGIT unsigned int -# define SIZEOF_BDIGIT SIZEOF_INT -# define BDIGIT_DBL unsigned long -# define BDIGIT_DBL_SIGNED long -# define PRI_BDIGIT_PREFIX "" -# define PRI_BDIGIT_DBL_PREFIX "l" -# elif SIZEOF_SHORT*2 <= SIZEOF_LONG -# define BDIGIT unsigned short -# define SIZEOF_BDIGIT SIZEOF_SHORT -# define BDIGIT_DBL unsigned long -# define BDIGIT_DBL_SIGNED long -# define PRI_BDIGIT_PREFIX "h" -# define PRI_BDIGIT_DBL_PREFIX "l" -# else -# define BDIGIT unsigned short -# define SIZEOF_BDIGIT (SIZEOF_LONG/2) -# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG -# define BDIGIT_DBL unsigned long -# define BDIGIT_DBL_SIGNED long -# define PRI_BDIGIT_PREFIX "h" -# define PRI_BDIGIT_DBL_PREFIX "l" -# endif -#endif -#ifndef SIZEOF_ACTUAL_BDIGIT -# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT -#endif - -#ifdef PRI_BDIGIT_PREFIX -# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d" -# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i" -# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o" -# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u" -# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x" -# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X" -#endif - -#ifdef PRI_BDIGIT_DBL_PREFIX -# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d" -# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i" -# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o" -# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u" -# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x" -# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X" -#endif - -#define BIGNUM_EMBED_LEN_NUMBITS 3 -#ifndef BIGNUM_EMBED_LEN_MAX -# if (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1 -# define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) -# else -# define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1) -# endif -#endif - -struct RBignum { - struct RBasic basic; - union { - struct { - size_t len; - BDIGIT *digits; - } heap; - BDIGIT ary[BIGNUM_EMBED_LEN_MAX]; - } as; -}; -#define BIGNUM_SIGN_BIT ((VALUE)FL_USER1) -/* sign: positive:1, negative:0 */ -#define BIGNUM_SIGN(b) ((RBASIC(b)->flags & BIGNUM_SIGN_BIT) != 0) -#define BIGNUM_SET_SIGN(b,sign) \ - ((sign) ? (RBASIC(b)->flags |= BIGNUM_SIGN_BIT) \ - : (RBASIC(b)->flags &= ~BIGNUM_SIGN_BIT)) -#define BIGNUM_POSITIVE_P(b) BIGNUM_SIGN(b) -#define BIGNUM_NEGATIVE_P(b) (!BIGNUM_SIGN(b)) -#define BIGNUM_NEGATE(b) (RBASIC(b)->flags ^= BIGNUM_SIGN_BIT) - -#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2) -#define BIGNUM_EMBED_LEN_MASK \ - (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT) -#define BIGNUM_EMBED_LEN_SHIFT \ - (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */ -#define BIGNUM_LEN(b) \ - ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \ - (size_t)((RBASIC(b)->flags >> BIGNUM_EMBED_LEN_SHIFT) & \ - (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT)) : \ - RBIGNUM(b)->as.heap.len) -/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */ -#define BIGNUM_DIGITS(b) \ - ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \ - RBIGNUM(b)->as.ary : \ - RBIGNUM(b)->as.heap.digits) -#define BIGNUM_LENINT(b) rb_long2int(BIGNUM_LEN(b)) - -#define RBIGNUM(obj) (R_CAST(RBignum)(obj)) - -struct RRational { - struct RBasic basic; - VALUE num; - VALUE den; -}; - -#define RRATIONAL(obj) (R_CAST(RRational)(obj)) -#define RRATIONAL_SET_NUM(rat, n) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->num,(n)) -#define RRATIONAL_SET_DEN(rat, d) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->den,(d)) - -struct RFloat { - struct RBasic basic; - double float_value; -}; +#include "ruby/ruby.h" -#define RFLOAT(obj) (R_CAST(RFloat)(obj)) - -struct RComplex { - struct RBasic basic; - VALUE real; - VALUE imag; -}; - -#define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) - -/* shortcut macro for internal only */ -#define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->real,(r)) -#define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->imag,(i)) - -enum ruby_rhash_flags { - RHASH_PASS_AS_KEYWORDS = FL_USER1, /* FL 1 */ - RHASH_PROC_DEFAULT = FL_USER2, /* FL 2 */ - RHASH_ST_TABLE_FLAG = FL_USER3, /* FL 3 */ -#define RHASH_AR_TABLE_MAX_SIZE SIZEOF_VALUE - RHASH_AR_TABLE_SIZE_MASK = (FL_USER4|FL_USER5|FL_USER6|FL_USER7), /* FL 4..7 */ - RHASH_AR_TABLE_SIZE_SHIFT = (FL_USHIFT+4), - RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */ - RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8), - - // we can not put it in "enum" because it can exceed "int" range. -#define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \ - FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19) - -#if USE_TRANSIENT_HEAP - RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */ -#endif +/* Following macros were formerly defined in this header but moved to somewhere + * else. In order to detect them we undef here. */ - RHASH_LEV_SHIFT = (FL_USHIFT + 13), - RHASH_LEV_MAX = 127, /* 7 bits */ +/* internal/array.h */ +#undef RARRAY_AREF - RHASH_ENUM_END -}; - -#define RHASH_AR_TABLE_SIZE_RAW(h) \ - ((unsigned int)((RBASIC(h)->flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT)) - -void rb_hash_st_table_set(VALUE hash, st_table *st); - -#if 0 /* for debug */ -int rb_hash_ar_table_p(VALUE hash); -struct ar_table_struct *rb_hash_ar_table(VALUE hash); -st_table *rb_hash_st_table(VALUE hash); -#define RHASH_AR_TABLE_P(hash) rb_hash_ar_table_p(hash) -#define RHASH_AR_TABLE(h) rb_hash_ar_table(h) -#define RHASH_ST_TABLE(h) rb_hash_st_table(h) -#else -#define RHASH_AR_TABLE_P(hash) (!FL_TEST_RAW((hash), RHASH_ST_TABLE_FLAG)) -#define RHASH_AR_TABLE(hash) (RHASH(hash)->as.ar) -#define RHASH_ST_TABLE(hash) (RHASH(hash)->as.st) -#endif - -#define RHASH(obj) (R_CAST(RHash)(obj)) -#define RHASH_ST_SIZE(h) (RHASH_ST_TABLE(h)->num_entries) -#define RHASH_ST_TABLE_P(h) (!RHASH_AR_TABLE_P(h)) -#define RHASH_ST_CLEAR(h) (FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG), RHASH(h)->as.ar = NULL) - -#define RHASH_AR_TABLE_SIZE_MASK (VALUE)RHASH_AR_TABLE_SIZE_MASK -#define RHASH_AR_TABLE_SIZE_SHIFT RHASH_AR_TABLE_SIZE_SHIFT -#define RHASH_AR_TABLE_BOUND_MASK (VALUE)RHASH_AR_TABLE_BOUND_MASK -#define RHASH_AR_TABLE_BOUND_SHIFT RHASH_AR_TABLE_BOUND_SHIFT - -#if USE_TRANSIENT_HEAP -#define RHASH_TRANSIENT_P(hash) FL_TEST_RAW((hash), RHASH_TRANSIENT_FLAG) -#define RHASH_SET_TRANSIENT_FLAG(h) FL_SET_RAW(h, RHASH_TRANSIENT_FLAG) -#define RHASH_UNSET_TRANSIENT_FLAG(h) FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG) -#else -#define RHASH_TRANSIENT_P(hash) 0 -#define RHASH_SET_TRANSIENT_FLAG(h) ((void)0) -#define RHASH_UNSET_TRANSIENT_FLAG(h) ((void)0) -#endif - -#if SIZEOF_VALUE / RHASH_AR_TABLE_MAX_SIZE == 2 -typedef uint16_t ar_hint_t; -#elif SIZEOF_VALUE / RHASH_AR_TABLE_MAX_SIZE == 1 -typedef unsigned char ar_hint_t; -#else -#error unsupported -#endif - -struct RHash { - struct RBasic basic; - union { - st_table *st; - struct ar_table_struct *ar; /* possibly 0 */ - } as; - const VALUE ifnone; - union { - ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE]; - VALUE word; - } ar_hint; -}; - -#ifdef RHASH_IFNONE -# undef RHASH_IFNONE -# undef RHASH_SIZE - -# define RHASH_IFNONE(h) (RHASH(h)->ifnone) -# define RHASH_SIZE(h) (RHASH_AR_TABLE_P(h) ? RHASH_AR_TABLE_SIZE_RAW(h) : RHASH_ST_SIZE(h)) -#endif /* ifdef RHASH_IFNONE */ - -struct RMoved { - VALUE flags; - VALUE destination; - VALUE next; -}; - -/* missing/setproctitle.c */ -#ifndef HAVE_SETPROCTITLE -extern void ruby_init_setproctitle(int argc, char *argv[]); -#endif - -#define RSTRUCT_EMBED_LEN_MAX RSTRUCT_EMBED_LEN_MAX -#define RSTRUCT_EMBED_LEN_MASK RSTRUCT_EMBED_LEN_MASK -#define RSTRUCT_EMBED_LEN_SHIFT RSTRUCT_EMBED_LEN_SHIFT - -enum { - RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX, - RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1), - RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1), - RSTRUCT_TRANSIENT_FLAG = FL_USER3, +/* internal/class.h */ +#undef RClass +#undef RCLASS_SUPER - RSTRUCT_ENUM_END -}; +/* internal/gc.h */ +#undef NEWOBJ_OF +#undef RB_NEWOBJ_OF +#undef RB_OBJ_WRITE -#if USE_TRANSIENT_HEAP -#define RSTRUCT_TRANSIENT_P(st) FL_TEST_RAW((obj), RSTRUCT_TRANSIENT_FLAG) -#define RSTRUCT_TRANSIENT_SET(st) FL_SET_RAW((st), RSTRUCT_TRANSIENT_FLAG) -#define RSTRUCT_TRANSIENT_UNSET(st) FL_UNSET_RAW((st), RSTRUCT_TRANSIENT_FLAG) -#else -#define RSTRUCT_TRANSIENT_P(st) 0 -#define RSTRUCT_TRANSIENT_SET(st) ((void)0) -#define RSTRUCT_TRANSIENT_UNSET(st) ((void)0) -#endif +/* internal/hash.h */ +#undef RHASH_IFNONE +#undef RHASH_SIZE +#undef RHASH_TBL +#undef RHASH_EMPTY_P -struct RStruct { - struct RBasic basic; - union { - struct { - long len; - const VALUE *ptr; - } heap; - const VALUE ary[RSTRUCT_EMBED_LEN_MAX]; - } as; -}; +/* internal/object.h */ +#undef ROBJECT_IV_INDEX_TBL +/* internal/struct.h */ #undef RSTRUCT_LEN #undef RSTRUCT_PTR #undef RSTRUCT_SET #undef RSTRUCT_GET -#define RSTRUCT_EMBED_LEN(st) \ - (long)((RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \ - (RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT)) -#define RSTRUCT_LEN(st) rb_struct_len(st) -#define RSTRUCT_LENINT(st) rb_long2int(RSTRUCT_LEN(st)) -#define RSTRUCT_CONST_PTR(st) rb_struct_const_ptr(st) -#define RSTRUCT_PTR(st) ((VALUE *)RSTRUCT_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(STRUCT, st))) -#define RSTRUCT_SET(st, idx, v) RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[idx], (v)) -#define RSTRUCT_GET(st, idx) (RSTRUCT_CONST_PTR(st)[idx]) -#define RSTRUCT(obj) (R_CAST(RStruct)(obj)) - -static inline long -rb_struct_len(VALUE st) -{ - return (RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? - RSTRUCT_EMBED_LEN(st) : RSTRUCT(st)->as.heap.len; -} - -static inline const VALUE * -rb_struct_const_ptr(VALUE st) -{ - return FIX_CONST_VALUE_PTR((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? - RSTRUCT(st)->as.ary : RSTRUCT(st)->as.heap.ptr); -} - -static inline const VALUE * -rb_struct_const_heap_ptr(VALUE st) -{ - /* TODO: check embed on debug mode */ - return RSTRUCT(st)->as.heap.ptr; -} - -/* class.c */ - -struct rb_deprecated_classext_struct { - char conflict[sizeof(VALUE) * 3]; -}; - -struct rb_subclass_entry; -typedef struct rb_subclass_entry rb_subclass_entry_t; - -struct rb_subclass_entry { - VALUE klass; - rb_subclass_entry_t *next; -}; - -#if defined(HAVE_LONG_LONG) -typedef unsigned LONG_LONG rb_serial_t; -#define SERIALT2NUM ULL2NUM -#define PRI_SERIALT_PREFIX PRI_LL_PREFIX -#define SIZEOF_SERIAL_T SIZEOF_LONG_LONG -#elif defined(HAVE_UINT64_T) -typedef uint64_t rb_serial_t; -#define SERIALT2NUM SIZET2NUM -#define PRI_SERIALT_PREFIX PRI_64_PREFIX -#define SIZEOF_SERIAL_T SIZEOF_UINT64_T -#else -typedef unsigned long rb_serial_t; -#define SERIALT2NUM ULONG2NUM -#define PRI_SERIALT_PREFIX PRI_LONG_PREFIX -#define SIZEOF_SERIAL_T SIZEOF_LONG -#endif - -struct rb_classext_struct { - struct st_table *iv_index_tbl; - struct st_table *iv_tbl; -#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */ - struct rb_id_table *m_tbl; -#endif - struct rb_id_table *const_tbl; - struct rb_id_table *callable_m_tbl; - rb_subclass_entry_t *subclasses; - rb_subclass_entry_t **parent_subclasses; - /** - * In the case that this is an `ICLASS`, `module_subclasses` points to the link - * in the module's `subclasses` list that indicates that the klass has been - * included. Hopefully that makes sense. - */ - rb_subclass_entry_t **module_subclasses; -#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */ - rb_serial_t class_serial; -#endif - const VALUE origin_; - const VALUE refined_class; - rb_alloc_func_t allocator; - const VALUE includer; -}; - -typedef struct rb_classext_struct rb_classext_t; - -#undef RClass -struct RClass { - struct RBasic basic; - VALUE super; - rb_classext_t *ptr; -#if SIZEOF_SERIAL_T == SIZEOF_VALUE - /* Class serial is as wide as VALUE. Place it here. */ - rb_serial_t class_serial; -#else - /* Class serial does not fit into struct RClass. Place m_tbl instead. */ - struct rb_id_table *m_tbl; -#endif -}; - -void rb_class_subclass_add(VALUE super, VALUE klass); -void rb_class_remove_from_super_subclasses(VALUE); -int rb_singleton_class_internal_p(VALUE sklass); - -#define RCLASS_EXT(c) (RCLASS(c)->ptr) -#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) -#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) -#if SIZEOF_SERIAL_T == SIZEOF_VALUE -# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl) -#else -# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) -#endif -#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl) -#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl) -#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_) -#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class) -#if SIZEOF_SERIAL_T == SIZEOF_VALUE -# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial) -#else -# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial) -#endif -#define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer) - -#define RCLASS_CLONED FL_USER6 -#define RICLASS_IS_ORIGIN FL_USER5 -#define RCLASS_REFINED_BY_ANY FL_USER7 - -static inline void -RCLASS_SET_ORIGIN(VALUE klass, VALUE origin) -{ - RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin); - if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN); -} - -static inline void -RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass) -{ - RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass); -} - -#undef RCLASS_SUPER -static inline VALUE -RCLASS_SUPER(VALUE klass) -{ - return RCLASS(klass)->super; -} - -static inline VALUE -RCLASS_SET_SUPER(VALUE klass, VALUE super) -{ - if (super) { - rb_class_remove_from_super_subclasses(klass); - rb_class_subclass_add(super, klass); - } - RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super); - return super; -} -/* IMEMO: Internal memo object */ - -#ifndef IMEMO_DEBUG -#define IMEMO_DEBUG 0 -#endif - -struct RIMemo { - VALUE flags; - VALUE v0; - VALUE v1; - VALUE v2; - VALUE v3; -}; - -enum imemo_type { - imemo_env = 0, - imemo_cref = 1, /*!< class reference */ - imemo_svar = 2, /*!< special variable */ - imemo_throw_data = 3, - imemo_ifunc = 4, /*!< iterator function */ - imemo_memo = 5, - imemo_ment = 6, - imemo_iseq = 7, - imemo_tmpbuf = 8, - imemo_ast = 9, - imemo_parser_strterm = 10 -}; -#define IMEMO_MASK 0x0f - -static inline enum imemo_type -imemo_type(VALUE imemo) -{ - return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK; -} - -static inline int -imemo_type_p(VALUE imemo, enum imemo_type imemo_type) -{ - if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) { - /* fixed at compile time if imemo_type is given. */ - const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK; - const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO; - /* fixed at runtime. */ - return expected_type == (RBASIC(imemo)->flags & mask); - } - else { - return 0; - } -} - -VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); - -/* FL_USER0 to FL_USER3 is for type */ -#define IMEMO_FL_USHIFT (FL_USHIFT + 4) -#define IMEMO_FL_USER0 FL_USER4 -#define IMEMO_FL_USER1 FL_USER5 -#define IMEMO_FL_USER2 FL_USER6 -#define IMEMO_FL_USER3 FL_USER7 -#define IMEMO_FL_USER4 FL_USER8 - -/* CREF (Class REFerence) is defined in method.h */ - -/*! SVAR (Special VARiable) */ -struct vm_svar { - VALUE flags; - const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ - const VALUE lastline; - const VALUE backref; - const VALUE others; -}; - - -#define THROW_DATA_CONSUMED IMEMO_FL_USER0 - -/*! THROW_DATA */ -struct vm_throw_data { - VALUE flags; - VALUE reserved; - const VALUE throw_obj; - const struct rb_control_frame_struct *catch_frame; - int throw_state; -}; - -#define THROW_DATA_P(err) RB_TYPE_P((VALUE)(err), T_IMEMO) - -/* IFUNC (Internal FUNCtion) */ - -struct vm_ifunc_argc { -#if SIZEOF_INT * 2 > SIZEOF_VALUE - signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2; - signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2; -#else - int min, max; -#endif -}; - -/*! IFUNC (Internal FUNCtion) */ -struct vm_ifunc { - VALUE flags; - VALUE reserved; - rb_block_call_func_t func; - const void *data; - struct vm_ifunc_argc argc; -}; - -#define IFUNC_NEW(a, b, c) ((struct vm_ifunc *)rb_imemo_new(imemo_ifunc, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) -struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc); -static inline struct vm_ifunc * -rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data) -{ - return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS); -} - -typedef struct rb_imemo_tmpbuf_struct { - VALUE flags; - VALUE reserved; - VALUE *ptr; /* malloc'ed buffer */ - struct rb_imemo_tmpbuf_struct *next; /* next imemo */ - size_t cnt; /* buffer size in VALUE */ -} rb_imemo_tmpbuf_t; - -#define rb_imemo_tmpbuf_auto_free_pointer() rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0) -rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt); - -#define RB_IMEMO_TMPBUF_PTR(v) \ - ((void *)(((const struct rb_imemo_tmpbuf_struct *)(v))->ptr)) - -static inline void * -rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr) -{ - return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr; -} - -static inline VALUE -rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str) -{ - const void *src; - VALUE imemo; - rb_imemo_tmpbuf_t *tmpbuf; - void *dst; - size_t len; - - SafeStringValue(str); - /* create tmpbuf to keep the pointer before xmalloc */ - imemo = rb_imemo_tmpbuf_auto_free_pointer(); - tmpbuf = (rb_imemo_tmpbuf_t *)imemo; - len = RSTRING_LEN(str); - src = RSTRING_PTR(str); - dst = ruby_xmalloc(len); - memcpy(dst, src, len); - tmpbuf->ptr = dst; - return imemo; -} - -void rb_strterm_mark(VALUE obj); - -/*! MEMO - * - * @see imemo_type - * */ -struct MEMO { - VALUE flags; - VALUE reserved; - const VALUE v1; - const VALUE v2; - union { - long cnt; - long state; - const VALUE value; - void (*func)(void); - } u3; -}; - -#define MEMO_V1_SET(m, v) RB_OBJ_WRITE((m), &(m)->v1, (v)) -#define MEMO_V2_SET(m, v) RB_OBJ_WRITE((m), &(m)->v2, (v)) - -#define MEMO_CAST(m) ((struct MEMO *)m) - -#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) - -#define roomof(x, y) (((x) + (y) - 1) / (y)) -#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) -#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value)) -#define NEW_MEMO_FOR(type, value) \ - ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) -#define NEW_PARTIAL_MEMO_FOR(type, value, member) \ - ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \ - rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \ - MEMO_FOR(type, value)) -#define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString) +/* Also, we keep the following macros here. They are expected to be + * overridden in each headers. */ -#ifdef RUBY_INTEGER_UNIFICATION -# define rb_cFixnum rb_cInteger -# define rb_cBignum rb_cInteger -#endif - -enum { - cmp_opt_Fixnum, - cmp_opt_String, - cmp_opt_Float, - cmp_optimizable_count -}; - -struct cmp_opt_data { - unsigned int opt_methods; - unsigned int opt_inited; -}; - -#define NEW_CMP_OPT_MEMO(type, value) \ - NEW_PARTIAL_MEMO_FOR(type, value, cmp_opt) -#define CMP_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(cmp_opt_,type)) -#define CMP_OPTIMIZABLE(data, type) \ - (((data).opt_inited & CMP_OPTIMIZABLE_BIT(type)) ? \ - ((data).opt_methods & CMP_OPTIMIZABLE_BIT(type)) : \ - (((data).opt_inited |= CMP_OPTIMIZABLE_BIT(type)), \ - rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \ - ((data).opt_methods |= CMP_OPTIMIZABLE_BIT(type)))) - -#define OPTIMIZED_CMP(a, b, data) \ - ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data, Fixnum)) ? \ - (((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \ - (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \ - rb_str_cmp(a, b) : \ - (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \ - rb_float_cmp(a, b) : \ - rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b)) - -/* ment is in method.h */ - -/* global variable */ - -struct rb_global_entry { - struct rb_global_variable *var; - ID id; -}; - -struct rb_global_entry *rb_global_entry(ID); -VALUE rb_gvar_get(struct rb_global_entry *); -VALUE rb_gvar_set(struct rb_global_entry *, VALUE); -VALUE rb_gvar_defined(struct rb_global_entry *); - -/* array.c */ - -#ifndef ARRAY_DEBUG -#define ARRAY_DEBUG (0+RUBY_DEBUG) -#endif - -#ifdef ARRAY_DEBUG -#define RARRAY_PTR_IN_USE_FLAG FL_USER14 -#define ARY_PTR_USING_P(ary) FL_TEST_RAW((ary), RARRAY_PTR_IN_USE_FLAG) -#else - -/* disable debug function */ -#undef RARRAY_PTR_USE_START_TRANSIENT -#undef RARRAY_PTR_USE_END_TRANSIENT -#define RARRAY_PTR_USE_START_TRANSIENT(a) ((VALUE *)RARRAY_CONST_PTR_TRANSIENT(a)) -#define RARRAY_PTR_USE_END_TRANSIENT(a) -#define ARY_PTR_USING_P(ary) 0 +/* internal/array.h */ +#define rb_ary_new_from_args(...) rb_nonexistent_symbol(__VA_ARGS__) -#endif +/* internal/io.h */ +#define rb_io_fptr_finalize(...) rb_nonexistent_symbol(__VA_ARGS__) -#if USE_TRANSIENT_HEAP -#define RARY_TRANSIENT_SET(ary) FL_SET_RAW((ary), RARRAY_TRANSIENT_FLAG); -#define RARY_TRANSIENT_UNSET(ary) FL_UNSET_RAW((ary), RARRAY_TRANSIENT_FLAG); -#else -#undef RARRAY_TRANSIENT_P -#define RARRAY_TRANSIENT_P(a) 0 -#define RARY_TRANSIENT_SET(ary) ((void)0) -#define RARY_TRANSIENT_UNSET(ary) ((void)0) -#endif +/* internal/string.h */ +#define rb_fstring_cstr(...) rb_nonexistent_symbol(__VA_ARGS__) +/* internal/symbol.h */ +#define rb_sym_intern_ascii_cstr(...) rb_nonexistent_symbol(__VA_ARGS__) -VALUE rb_ary_last(int, const VALUE *, VALUE); -void rb_ary_set_len(VALUE, long); -void rb_ary_delete_same(VALUE, VALUE); -VALUE rb_ary_tmp_new_fill(long capa); -VALUE rb_ary_at(VALUE, VALUE); -VALUE rb_ary_aref1(VALUE ary, VALUE i); -size_t rb_ary_memsize(VALUE); -VALUE rb_to_array_type(VALUE obj); -VALUE rb_check_to_array(VALUE ary); -VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *); -VALUE rb_ary_behead(VALUE, long); -#if defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) -#define rb_ary_new_from_args(n, ...) \ - __extension__ ({ \ - const VALUE args_to_new_ary[] = {__VA_ARGS__}; \ - if (__builtin_constant_p(n)) { \ - STATIC_ASSERT(rb_ary_new_from_args, numberof(args_to_new_ary) == (n)); \ - } \ - rb_ary_new_from_values(numberof(args_to_new_ary), args_to_new_ary); \ - }) -#endif +/* internal/vm.h */ +#define rb_funcallv(...) rb_nonexistent_symbol(__VA_ARGS__) +#define rb_method_basic_definition_p(...) rb_nonexistent_symbol(__VA_ARGS__) -static inline VALUE -rb_ary_entry_internal(VALUE ary, long offset) -{ - long len = RARRAY_LEN(ary); - const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary); - if (len == 0) return Qnil; - if (offset < 0) { - offset += len; - if (offset < 0) return Qnil; - } - else if (len <= offset) { - return Qnil; - } - return ptr[offset]; -} /* MRI debug support */ + +/* gc.c */ void rb_obj_info_dump(VALUE obj); void rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func); + +/* debug.c */ + +RUBY_SYMBOL_EXPORT_BEGIN void ruby_debug_breakpoint(void); +PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2); +RUBY_SYMBOL_EXPORT_END // show obj data structure without any side-effect -#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, __func__) +#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING) // same as rp, but add message header #define rp_m(msg, obj) do { \ - fprintf(stderr, "%s", (msg)); \ - rb_obj_info_dump((VALUE)obj); \ + fputs((msg), stderr); \ + rb_obj_info_dump((VALUE)(obj)); \ } while (0) // `ruby_debug_breakpoint()` does nothing, // but breakpoint is set in run.gdb, so `make gdb` can stop here. #define bp() ruby_debug_breakpoint() -/* bignum.c */ -extern const char ruby_digitmap[]; -double rb_big_fdiv_double(VALUE x, VALUE y); -VALUE rb_big_uminus(VALUE x); -VALUE rb_big_hash(VALUE); -VALUE rb_big_odd_p(VALUE); -VALUE rb_big_even_p(VALUE); -size_t rb_big_size(VALUE); -VALUE rb_integer_float_cmp(VALUE x, VALUE y); -VALUE rb_integer_float_eq(VALUE x, VALUE y); -VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception); -VALUE rb_big_comp(VALUE x); -VALUE rb_big_aref(VALUE x, VALUE y); -VALUE rb_big_abs(VALUE x); -VALUE rb_big_size_m(VALUE big); -VALUE rb_big_bit_length(VALUE big); -VALUE rb_big_remainder(VALUE x, VALUE y); -VALUE rb_big_gt(VALUE x, VALUE y); -VALUE rb_big_ge(VALUE x, VALUE y); -VALUE rb_big_lt(VALUE x, VALUE y); -VALUE rb_big_le(VALUE x, VALUE y); -VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num); - -/* class.c */ -VALUE rb_class_boot(VALUE); -VALUE rb_class_inherited(VALUE, VALUE); -VALUE rb_make_metaclass(VALUE, VALUE); -VALUE rb_include_class_new(VALUE, VALUE); -void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE); -void rb_class_detach_subclasses(VALUE); -void rb_class_detach_module_subclasses(VALUE); -void rb_class_remove_from_module_subclasses(VALUE); -VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj); -VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj); -VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj); -VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj); -VALUE rb_special_singleton_class(VALUE); -VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach); -VALUE rb_singleton_class_get(VALUE obj); -void Init_class_hierarchy(void); - -int rb_class_has_methods(VALUE c); -void rb_undef_methods_from(VALUE klass, VALUE super); - -/* compar.c */ -VALUE rb_invcmp(VALUE, VALUE); - -/* compile.c */ -struct rb_block; -struct rb_iseq_struct; -int rb_dvar_defined(ID, const struct rb_iseq_struct *); -int rb_local_defined(ID, const struct rb_iseq_struct *); -const char * rb_insns_name(int i); -VALUE rb_insns_name_array(void); -int rb_vm_insn_addr2insn(const void *); - -/* complex.c */ -VALUE rb_dbl_complex_new_polar_pi(double abs, double ang); - -struct rb_thread_struct; -/* cont.c */ -struct rb_fiber_struct; -VALUE rb_obj_is_fiber(VALUE); -void rb_fiber_reset_root_local_storage(struct rb_thread_struct *); -void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE)); -void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber); - -/* debug.c */ -PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2); - -/* dir.c */ -VALUE rb_dir_getwd_ospath(void); - -/* dmyext.c */ -void Init_enc(void); -void Init_ext(void); - -/* encoding.c */ -ID rb_id_encoding(void); -#ifdef RUBY_ENCODING_H -rb_encoding *rb_enc_get_from_index(int index); -rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2); -#endif -int rb_encdb_replicate(const char *alias, const char *orig); -int rb_encdb_alias(const char *alias, const char *orig); -int rb_encdb_dummy(const char *name); -void rb_encdb_declare(const char *name); -void rb_enc_set_base(const char *name, const char *orig); -int rb_enc_set_dummy(int index); -void rb_encdb_set_unicode(int index); -PUREFUNC(int rb_data_is_encoding(VALUE obj)); - -/* enum.c */ -extern VALUE rb_cArithSeq; -VALUE rb_f_send(int argc, VALUE *argv, VALUE recv); -VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary); - -/* error.c */ -extern VALUE rb_eEAGAIN; -extern VALUE rb_eEWOULDBLOCK; -extern VALUE rb_eEINPROGRESS; -void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args); -NORETURN(void rb_async_bug_errno(const char *,int)); -const char *rb_builtin_type_name(int t); -const char *rb_builtin_class_name(VALUE x); -PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3); -#ifdef RUBY_ENCODING_H -VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list); -PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3); -PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3); -PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4); -#endif - -typedef enum { - RB_WARN_CATEGORY_NONE, - RB_WARN_CATEGORY_DEPRECATED, - RB_WARN_CATEGORY_EXPERIMENTAL, -} rb_warning_category_t; -rb_warning_category_t rb_warning_category_from_name(VALUE category); -bool rb_warning_category_enabled_p(rb_warning_category_t category); - -#define rb_raise_cstr(etype, mesg) \ - rb_exc_raise(rb_exc_new_str(etype, rb_str_new_cstr(mesg))) -#define rb_raise_static(etype, mesg) \ - rb_exc_raise(rb_exc_new_str(etype, rb_str_new_static(mesg, rb_strlen_lit(mesg)))) - -VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method); -#define rb_name_err_raise_str(mesg, recv, name) \ - rb_exc_raise(rb_name_err_new(mesg, recv, name)) -#define rb_name_err_raise(mesg, recv, name) \ - rb_name_err_raise_str(rb_fstring_cstr(mesg), (recv), (name)) -VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv); -VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name); -#define rb_key_err_raise(mesg, recv, name) \ - rb_exc_raise(rb_key_err_new(mesg, recv, name)) -PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2); -NORETURN(void rb_vraise(VALUE, const char *, va_list)); - -/* eval.c */ -VALUE rb_refinement_module_get_refined_class(VALUE module); -extern ID ruby_static_id_signo, ruby_static_id_status; -void rb_class_modify_check(VALUE); -#define id_signo ruby_static_id_signo -#define id_status ruby_static_id_status -NORETURN(VALUE rb_f_raise(int argc, VALUE *argv)); - -/* eval_error.c */ -VALUE rb_get_backtrace(VALUE info); - -/* eval_jump.c */ -void rb_call_end_proc(VALUE data); -void rb_mark_end_proc(void); - -/* file.c */ -extern const char ruby_null_device[]; -VALUE rb_home_dir_of(VALUE user, VALUE result); -VALUE rb_default_home_dir(VALUE result); -VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); -#ifdef RUBY_ENCODING_H -VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *origenc); -#endif -void rb_file_const(const char*, VALUE); -int rb_file_load_ok(const char *); -VALUE rb_file_expand_path_fast(VALUE, VALUE); -VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -VALUE rb_get_path_check_to_string(VALUE); -VALUE rb_get_path_check_convert(VALUE); -void Init_File(void); -int ruby_is_fd_loadable(int fd); - -#ifdef RUBY_FUNCTION_NAME_STRING -# if defined __GNUC__ && __GNUC__ >= 4 -# pragma GCC visibility push(default) -# endif -NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path)); -NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path)); -# if defined __GNUC__ && __GNUC__ >= 4 -# pragma GCC visibility pop -# endif -# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path) -# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path)) -#else -# define rb_sys_fail_path(path) rb_sys_fail_str(path) -# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path)) -#endif - -/* gc.c */ -extern VALUE *ruby_initial_gc_stress_ptr; -extern int ruby_disable_gc; -struct rb_objspace; /* in vm_core.h */ -void Init_heap(void); -void *ruby_mimmalloc(size_t size) RUBY_ATTR_MALLOC; -void ruby_mimfree(void *ptr); -void rb_objspace_set_event_hook(const rb_event_flag_t event); -VALUE rb_objspace_gc_enable(struct rb_objspace *); -VALUE rb_objspace_gc_disable(struct rb_objspace *); -#if USE_RGENGC -void rb_gc_writebarrier_remember(VALUE obj); -#else -#define rb_gc_writebarrier_remember(obj) 0 -#endif -void ruby_gc_set_params(void); -void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj); - -#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32) -#define ruby_sized_xrealloc(ptr, new_size, old_size) ruby_xrealloc(ptr, new_size) -#define ruby_sized_xrealloc2(ptr, new_count, element_size, old_count) ruby_xrealloc2(ptr, new_count, element_size) -#define ruby_sized_xfree(ptr, size) ruby_xfree(ptr) -#define SIZED_REALLOC_N(var,type,n,old_n) REALLOC_N(var, type, n) -#else -RUBY_SYMBOL_EXPORT_BEGIN -void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); -void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3)); -void ruby_sized_xfree(void *x, size_t size); -RUBY_SYMBOL_EXPORT_END -#define SIZED_REALLOC_N(var,type,n,old_n) ((var)=(type*)ruby_sized_xrealloc2((void*)(var), (n), sizeof(type), (old_n))) -#endif - -/* optimized version of NEWOBJ() */ -#undef NEWOBJF_OF -#undef RB_NEWOBJ_OF -#define RB_NEWOBJ_OF(obj,type,klass,flags) \ - type *(obj) = (type*)(((flags) & FL_WB_PROTECTED) ? \ - rb_wb_protected_newobj_of(klass, (flags) & ~FL_WB_PROTECTED) : \ - rb_wb_unprotected_newobj_of(klass, flags)) -#define NEWOBJ_OF(obj,type,klass,flags) RB_NEWOBJ_OF(obj,type,klass,flags) - -#ifdef __has_attribute -#if __has_attribute(alloc_align) -__attribute__((__alloc_align__(1))) -#endif -#endif -void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_MALLOC RUBY_ATTR_ALLOC_SIZE((2)); - -size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */ -size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */ -void *rb_xmalloc_mul_add(size_t, size_t, size_t) RUBY_ATTR_MALLOC; -void *rb_xrealloc_mul_add(const void *, size_t, size_t, size_t); -void *rb_xmalloc_mul_add_mul(size_t, size_t, size_t, size_t) RUBY_ATTR_MALLOC; -void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t) RUBY_ATTR_MALLOC; - -/* hash.c */ -#if RHASH_CONVERT_TABLE_DEBUG -struct st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line); -#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__) -#else -struct st_table *rb_hash_tbl_raw(VALUE hash); -#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h) -#endif - -VALUE rb_hash_new_with_size(st_index_t size); -VALUE rb_hash_has_key(VALUE hash, VALUE key); -VALUE rb_hash_default_value(VALUE hash, VALUE key); -VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc); -long rb_dbl_long_hash(double d); -st_table *rb_init_identtable(void); -VALUE rb_hash_compare_by_id_p(VALUE hash); -VALUE rb_to_hash_type(VALUE obj); -VALUE rb_hash_key_str(VALUE); -VALUE rb_hash_keys(VALUE hash); -VALUE rb_hash_values(VALUE hash); -VALUE rb_hash_rehash(VALUE hash); -VALUE rb_hash_resurrect(VALUE hash); -int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val); -VALUE rb_hash_set_pair(VALUE hash, VALUE pair); - -int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval); -int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval); -RUBY_SYMBOL_EXPORT_BEGIN -int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg); -RUBY_SYMBOL_EXPORT_END -int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg); -int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg); - -/* inits.c */ -void rb_call_inits(void); - -/* io.c */ -void ruby_set_inplace_mode(const char *); -void rb_stdio_set_default_encoding(void); -VALUE rb_io_flush_raw(VALUE, int); -#ifdef RUBY_IO_H -size_t rb_io_memsize(const rb_io_t *); -#endif -int rb_stderr_tty_p(void); -void rb_io_fptr_finalize_internal(void *ptr); -#define rb_io_fptr_finalize rb_io_fptr_finalize_internal - -/* load.c */ -VALUE rb_get_expanded_load_path(void); -int rb_require_internal(VALUE fname); -NORETURN(void rb_load_fail(VALUE, const char*)); - -/* loadpath.c */ -extern const char ruby_exec_prefix[]; -extern const char ruby_initial_load_paths[]; - -/* localeinit.c */ -int Init_enc_set_filesystem_encoding(void); - -/* math.c */ -VALUE rb_math_atan2(VALUE, VALUE); -VALUE rb_math_cos(VALUE); -VALUE rb_math_cosh(VALUE); -VALUE rb_math_exp(VALUE); -VALUE rb_math_hypot(VALUE, VALUE); -VALUE rb_math_log(int argc, const VALUE *argv); -VALUE rb_math_sin(VALUE); -VALUE rb_math_sinh(VALUE); - -/* mjit.c */ - -#if USE_MJIT -extern bool mjit_enabled; -VALUE mjit_pause(bool wait_p); -VALUE mjit_resume(void); -void mjit_finish(bool close_handle_p); -#else -#define mjit_enabled 0 -static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable -static inline VALUE mjit_resume(void){ return Qnil; } // unreachable -static inline void mjit_finish(bool close_handle_p){} -#endif - -/* newline.c */ -void Init_newline(void); - -/* numeric.c */ - -#define FIXNUM_POSITIVE_P(num) ((SIGNED_VALUE)(num) > (SIGNED_VALUE)INT2FIX(0)) -#define FIXNUM_NEGATIVE_P(num) ((SIGNED_VALUE)(num) < 0) -#define FIXNUM_ZERO_P(num) ((num) == INT2FIX(0)) - -#define INT_NEGATIVE_P(x) (FIXNUM_P(x) ? FIXNUM_NEGATIVE_P(x) : BIGNUM_NEGATIVE_P(x)) - -#define FLOAT_ZERO_P(x) (RFLOAT_VALUE(x) == 0.0) - -#ifndef ROUND_DEFAULT -# define ROUND_DEFAULT RUBY_NUM_ROUND_HALF_UP -#endif -enum ruby_num_rounding_mode { - RUBY_NUM_ROUND_HALF_UP, - RUBY_NUM_ROUND_HALF_EVEN, - RUBY_NUM_ROUND_HALF_DOWN, - RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT -}; -#define ROUND_TO(mode, even, up, down) \ - ((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \ - (mode) == RUBY_NUM_ROUND_HALF_UP ? up : down) -#define ROUND_FUNC(mode, name) \ - ROUND_TO(mode, name##_half_even, name##_half_up, name##_half_down) -#define ROUND_CALL(mode, name, args) \ - ROUND_TO(mode, name##_half_even args, \ - name##_half_up args, name##_half_down args) - -int rb_num_to_uint(VALUE val, unsigned int *ret); -VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl); -double ruby_float_step_size(double beg, double end, double unit, int excl); -int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless); -double ruby_float_mod(double x, double y); -int rb_num_negative_p(VALUE); -VALUE rb_int_succ(VALUE num); -VALUE rb_int_uminus(VALUE num); -VALUE rb_float_uminus(VALUE num); -VALUE rb_int_plus(VALUE x, VALUE y); -VALUE rb_float_plus(VALUE x, VALUE y); -VALUE rb_int_minus(VALUE x, VALUE y); -VALUE rb_int_mul(VALUE x, VALUE y); -VALUE rb_float_mul(VALUE x, VALUE y); -VALUE rb_float_div(VALUE x, VALUE y); -VALUE rb_int_idiv(VALUE x, VALUE y); -VALUE rb_int_modulo(VALUE x, VALUE y); -VALUE rb_int2str(VALUE num, int base); -VALUE rb_fix_plus(VALUE x, VALUE y); -VALUE rb_fix_aref(VALUE fix, VALUE idx); -VALUE rb_int_gt(VALUE x, VALUE y); -int rb_float_cmp(VALUE x, VALUE y); -VALUE rb_float_gt(VALUE x, VALUE y); -VALUE rb_int_ge(VALUE x, VALUE y); -enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts); -double rb_int_fdiv_double(VALUE x, VALUE y); -VALUE rb_int_pow(VALUE x, VALUE y); -VALUE rb_float_pow(VALUE x, VALUE y); -VALUE rb_int_cmp(VALUE x, VALUE y); -VALUE rb_int_equal(VALUE x, VALUE y); -VALUE rb_int_divmod(VALUE x, VALUE y); -VALUE rb_int_and(VALUE x, VALUE y); -VALUE rb_int_lshift(VALUE x, VALUE y); -VALUE rb_int_div(VALUE x, VALUE y); -VALUE rb_int_abs(VALUE num); -VALUE rb_int_odd_p(VALUE num); -int rb_int_positive_p(VALUE num); -int rb_int_negative_p(VALUE num); -VALUE rb_num_pow(VALUE x, VALUE y); -VALUE rb_float_ceil(VALUE num, int ndigits); - -static inline VALUE -rb_num_compare_with_zero(VALUE num, ID mid) -{ - VALUE zero = INT2FIX(0); - VALUE r = rb_check_funcall(num, mid, 1, &zero); - if (r == Qundef) { - rb_cmperr(num, zero); - } - return r; -} - -static inline int -rb_num_positive_int_p(VALUE num) -{ - const ID mid = '>'; - - if (FIXNUM_P(num)) { - if (rb_method_basic_definition_p(rb_cInteger, mid)) - return FIXNUM_POSITIVE_P(num); - } - else if (RB_TYPE_P(num, T_BIGNUM)) { - if (rb_method_basic_definition_p(rb_cInteger, mid)) - return BIGNUM_POSITIVE_P(num); - } - return RTEST(rb_num_compare_with_zero(num, mid)); -} - - -static inline int -rb_num_negative_int_p(VALUE num) -{ - const ID mid = '<'; - - if (FIXNUM_P(num)) { - if (rb_method_basic_definition_p(rb_cInteger, mid)) - return FIXNUM_NEGATIVE_P(num); - } - else if (RB_TYPE_P(num, T_BIGNUM)) { - if (rb_method_basic_definition_p(rb_cInteger, mid)) - return BIGNUM_NEGATIVE_P(num); - } - return RTEST(rb_num_compare_with_zero(num, mid)); -} - - -VALUE rb_float_abs(VALUE flt); -VALUE rb_float_equal(VALUE x, VALUE y); -VALUE rb_float_eql(VALUE x, VALUE y); -VALUE rb_flo_div_flo(VALUE x, VALUE y); - -#if USE_FLONUM -#define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) -#define RUBY_BIT_ROTR(v, n) (((v) >> (n)) | ((v) << ((sizeof(v) * 8) - n))) -#endif - -static inline double -rb_float_flonum_value(VALUE v) -{ -#if USE_FLONUM - if (v != (VALUE)0x8000000000000002) { /* LIKELY */ - union { - double d; - VALUE v; - } t; - - VALUE b63 = (v >> 63); - /* e: xx1... -> 011... */ - /* xx0... -> 100... */ - /* ^b63 */ - t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~(VALUE)0x03), 3); - return t.d; - } -#endif - return 0.0; -} - -static inline double -rb_float_noflonum_value(VALUE v) -{ - return ((struct RFloat *)v)->float_value; -} - -static inline double -rb_float_value_inline(VALUE v) -{ - if (FLONUM_P(v)) { - return rb_float_flonum_value(v); - } - return rb_float_noflonum_value(v); -} - -static inline VALUE -rb_float_new_inline(double d) -{ -#if USE_FLONUM - union { - double d; - VALUE v; - } t; - int bits; - - t.d = d; - bits = (int)((VALUE)(t.v >> 60) & 0x7); - /* bits contains 3 bits of b62..b60. */ - /* bits - 3 = */ - /* b011 -> b000 */ - /* b100 -> b001 */ - - if (t.v != 0x3000000000000000 /* 1.72723e-77 */ && - !((bits-3) & ~0x01)) { - return (RUBY_BIT_ROTL(t.v, 3) & ~(VALUE)0x01) | 0x02; - } - else if (t.v == (VALUE)0) { - /* +0.0 */ - return 0x8000000000000002; - } - /* out of range */ -#endif - return rb_float_new_in_heap(d); -} - -#define rb_float_value(v) rb_float_value_inline(v) -#define rb_float_new(d) rb_float_new_inline(d) - -/* object.c */ -void rb_obj_copy_ivar(VALUE dest, VALUE obj); -CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2)); -CONSTFUNC(VALUE rb_obj_not(VALUE obj)); -VALUE rb_class_search_ancestor(VALUE klass, VALUE super); -NORETURN(void rb_undefined_alloc(VALUE klass)); -double rb_num_to_dbl(VALUE val); -VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound); -VALUE rb_immutable_obj_clone(int, VALUE *, VALUE); -VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); -VALUE rb_convert_type_with_id(VALUE,int,const char*,ID); -VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID); -int rb_bool_expected(VALUE, const char *); - -struct RBasicRaw { - VALUE flags; - VALUE klass; -}; - -#define RBASIC_CLEAR_CLASS(obj) memset(&(((struct RBasicRaw *)((VALUE)(obj)))->klass), 0, sizeof(VALUE)) -#define RBASIC_SET_CLASS_RAW(obj, cls) memcpy(&((struct RBasicRaw *)((VALUE)(obj)))->klass, &(cls), sizeof(VALUE)) -#define RBASIC_SET_CLASS(obj, cls) do { \ - VALUE _obj_ = (obj); \ - RB_OBJ_WRITE(_obj_, &((struct RBasicRaw *)(_obj_))->klass, cls); \ -} while (0) - -/* parse.y */ -#ifndef USE_SYMBOL_GC -#define USE_SYMBOL_GC 1 -#endif -VALUE rb_parser_set_yydebug(VALUE, VALUE); -RUBY_SYMBOL_EXPORT_BEGIN -VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); -RUBY_SYMBOL_EXPORT_END -void *rb_parser_load_file(VALUE parser, VALUE name); -int rb_is_const_name(VALUE name); -int rb_is_class_name(VALUE name); -int rb_is_instance_name(VALUE name); -int rb_is_local_name(VALUE name); -PUREFUNC(int rb_is_const_sym(VALUE sym)); -PUREFUNC(int rb_is_attrset_sym(VALUE sym)); -ID rb_make_internal_id(void); -void rb_gc_free_dsymbol(VALUE); - -/* proc.c */ -VALUE rb_proc_location(VALUE self); -st_index_t rb_hash_proc(st_index_t hash, VALUE proc); -int rb_block_arity(void); -int rb_block_min_max_arity(int *max); -VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val); -VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc); -VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info); - -/* process.c */ -#define RB_MAX_GROUPS (65536) - -struct waitpid_state; -struct rb_execarg { - union { - struct { - VALUE shell_script; - } sh; - struct { - VALUE command_name; - VALUE command_abspath; /* full path string or nil */ - VALUE argv_str; - VALUE argv_buf; - } cmd; - } invoke; - VALUE redirect_fds; - VALUE envp_str; - VALUE envp_buf; - VALUE dup2_tmpbuf; - unsigned use_shell : 1; - unsigned pgroup_given : 1; - unsigned umask_given : 1; - unsigned unsetenv_others_given : 1; - unsigned unsetenv_others_do : 1; - unsigned close_others_given : 1; - unsigned close_others_do : 1; - unsigned chdir_given : 1; - unsigned new_pgroup_given : 1; - unsigned new_pgroup_flag : 1; - unsigned uid_given : 1; - unsigned gid_given : 1; - unsigned exception : 1; - unsigned exception_given : 1; - struct waitpid_state *waitpid_state; /* for async process management */ - rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0as.ary[0]) -#define RANGE_END(r) (RSTRUCT(r)->as.ary[1]) -#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2]) - -/* rational.c */ -VALUE rb_rational_canonicalize(VALUE x); -VALUE rb_rational_uminus(VALUE self); -VALUE rb_rational_plus(VALUE self, VALUE other); -VALUE rb_rational_mul(VALUE self, VALUE other); -VALUE rb_lcm(VALUE x, VALUE y); -VALUE rb_rational_reciprocal(VALUE x); -VALUE rb_cstr_to_rat(const char *, int); -VALUE rb_rational_abs(VALUE self); -VALUE rb_rational_cmp(VALUE self, VALUE other); -VALUE rb_rational_pow(VALUE self, VALUE other); -VALUE rb_numeric_quo(VALUE x, VALUE y); -VALUE rb_float_numerator(VALUE x); -VALUE rb_float_denominator(VALUE x); - -/* re.c */ -VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline); -VALUE rb_reg_check_preprocess(VALUE); -long rb_reg_search0(VALUE, VALUE, long, int, int); -VALUE rb_reg_match_p(VALUE re, VALUE str, long pos); -bool rb_reg_start_with_p(VALUE re, VALUE str); -void rb_backref_set_string(VALUE string, long pos, long len); -void rb_match_unbusy(VALUE); -int rb_match_count(VALUE match); -int rb_match_nth_defined(int nth, VALUE match); -VALUE rb_reg_new_ary(VALUE ary, int options); - -/* signal.c */ -extern int ruby_enable_coredump; -int rb_get_next_signal(void); - -/* string.c */ -VALUE rb_fstring(VALUE); -VALUE rb_fstring_new(const char *ptr, long len); -#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str)) -#define rb_fstring_literal(str) rb_fstring_lit(str) -VALUE rb_fstring_cstr(const char *str); -#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P -# define rb_fstring_cstr(str) RB_GNUC_EXTENSION_BLOCK( \ - (__builtin_constant_p(str)) ? \ - rb_fstring_new((str), (long)strlen(str)) : \ - rb_fstring_cstr(str) \ -) -#endif -#ifdef RUBY_ENCODING_H -VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc); -#define rb_fstring_enc_lit(str, enc) rb_fstring_enc_new((str), rb_strlen_lit(str), (enc)) -#define rb_fstring_enc_literal(str, enc) rb_fstring_enc_lit(str, enc) -#endif -int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p); -int rb_str_symname_p(VALUE); -VALUE rb_str_quote_unprintable(VALUE); -VALUE rb_id_quote_unprintable(ID); -#define QUOTE(str) rb_str_quote_unprintable(str) -#define QUOTE_ID(id) rb_id_quote_unprintable(id) -char *rb_str_fill_terminator(VALUE str, const int termlen); -void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen); -VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg); -VALUE rb_str_chomp_string(VALUE str, VALUE chomp); -#ifdef RUBY_ENCODING_H -VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc); -VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, - rb_encoding *from, int ecflags, VALUE ecopts); -VALUE rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl); -VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc); -#endif -#define STR_NOEMBED FL_USER1 -#define STR_SHARED FL_USER2 /* = ELTS_SHARED */ -#define STR_EMBED_P(str) (!FL_TEST_RAW((str), STR_NOEMBED)) -#define STR_SHARED_P(s) FL_ALL_RAW((s), STR_NOEMBED|ELTS_SHARED) -#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) -#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) -size_t rb_str_memsize(VALUE); -VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc); -VALUE rb_sym_to_proc(VALUE sym); -char *rb_str_to_cstr(VALUE str); -VALUE rb_str_eql(VALUE str1, VALUE str2); -VALUE rb_obj_as_string_result(VALUE str, VALUE obj); -const char *ruby_escaped_char(int c); -VALUE rb_str_opt_plus(VALUE, VALUE); - -/* expect tail call optimization */ -static inline VALUE -rb_str_eql_internal(const VALUE str1, const VALUE str2) -{ - const long len = RSTRING_LEN(str1); - const char *ptr1, *ptr2; - - if (len != RSTRING_LEN(str2)) return Qfalse; - if (!rb_str_comparable(str1, str2)) return Qfalse; - if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2))) - return Qtrue; - if (memcmp(ptr1, ptr2, len) == 0) - return Qtrue; - return Qfalse; -} - -/* symbol.c */ -#ifdef RUBY_ENCODING_H -VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc); -#endif -VALUE rb_sym_intern_ascii(const char *ptr, long len); -VALUE rb_sym_intern_ascii_cstr(const char *ptr); -#ifdef __GNUC__ -#define rb_sym_intern_ascii_cstr(ptr) __extension__ ( \ -{ \ - (__builtin_constant_p(ptr)) ? \ - rb_sym_intern_ascii((ptr), (long)strlen(ptr)) : \ - rb_sym_intern_ascii_cstr(ptr); \ -}) -#endif -VALUE rb_to_symbol_type(VALUE obj); - -/* struct.c */ -VALUE rb_struct_init_copy(VALUE copy, VALUE s); -VALUE rb_struct_lookup(VALUE s, VALUE idx); -VALUE rb_struct_s_keyword_init(VALUE klass); - -/* time.c */ -struct timeval rb_time_timeval(VALUE); - -/* thread.c */ -#define COVERAGE_INDEX_LINES 0 -#define COVERAGE_INDEX_BRANCHES 1 -#define COVERAGE_TARGET_LINES 1 -#define COVERAGE_TARGET_BRANCHES 2 -#define COVERAGE_TARGET_METHODS 4 -#define COVERAGE_TARGET_ONESHOT_LINES 8 - -VALUE rb_obj_is_mutex(VALUE obj); -VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg); -void rb_thread_execute_interrupts(VALUE th); -VALUE rb_get_coverages(void); -int rb_get_coverage_mode(void); -VALUE rb_default_coverage(int); -VALUE rb_thread_shield_new(void); -VALUE rb_thread_shield_wait(VALUE self); -VALUE rb_thread_shield_release(VALUE self); -VALUE rb_thread_shield_destroy(VALUE self); -int rb_thread_to_be_killed(VALUE thread); -void rb_mutex_allow_trap(VALUE self, int val); -VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data); -VALUE rb_mutex_owned_p(VALUE self); - -/* transcode.c */ -extern VALUE rb_cEncodingConverter; -#ifdef RUBY_ENCODING_H -size_t rb_econv_memsize(rb_econv_t *); -#endif - -/* us_ascii.c */ -#ifdef RUBY_ENCODING_H -extern rb_encoding OnigEncodingUS_ASCII; -#endif - -/* util.c */ -char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve); -char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve); - -/* utf_8.c */ -#ifdef RUBY_ENCODING_H -extern rb_encoding OnigEncodingUTF_8; -#endif - -/* variable.c */ -#if USE_TRANSIENT_HEAP -#define ROBJECT_TRANSIENT_FLAG FL_USER13 -#define ROBJ_TRANSIENT_P(obj) FL_TEST_RAW((obj), ROBJECT_TRANSIENT_FLAG) -#define ROBJ_TRANSIENT_SET(obj) FL_SET_RAW((obj), ROBJECT_TRANSIENT_FLAG) -#define ROBJ_TRANSIENT_UNSET(obj) FL_UNSET_RAW((obj), ROBJECT_TRANSIENT_FLAG) -#else -#define ROBJ_TRANSIENT_P(obj) 0 -#define ROBJ_TRANSIENT_SET(obj) ((void)0) -#define ROBJ_TRANSIENT_UNSET(obj) ((void)0) -#endif -void rb_gc_mark_global_tbl(void); -size_t rb_generic_ivar_memsize(VALUE); -VALUE rb_search_class_path(VALUE); -VALUE rb_attr_delete(VALUE, ID); -VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); -void rb_autoload_str(VALUE mod, ID id, VALUE file); -VALUE rb_autoload_at_p(VALUE, ID, int); -void rb_deprecate_constant(VALUE mod, const char *name); -NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE)); -rb_gvar_getter_t *rb_gvar_getter_function_of(const struct rb_global_entry *); -rb_gvar_setter_t *rb_gvar_setter_function_of(const struct rb_global_entry *); -bool rb_gvar_is_traced(const struct rb_global_entry *); -void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_); - -/* vm_insnhelper.h */ -rb_serial_t rb_next_class_serial(void); - -/* vm.c */ -VALUE rb_obj_is_thread(VALUE obj); -void rb_vm_mark(void *ptr); -void Init_BareVM(void); -void Init_vm_objects(void); -PUREFUNC(VALUE rb_vm_top_self(void)); -void rb_vm_inc_const_missing_count(void); -const void **rb_vm_get_insns_address_table(void); -VALUE rb_source_location(int *pline); -const char *rb_source_location_cstr(int *pline); -MJIT_STATIC void rb_vm_pop_cfunc_frame(void); -int rb_vm_add_root_module(ID id, VALUE module); -void rb_vm_check_redefinition_by_prepend(VALUE klass); -int rb_vm_check_optimizable_mid(VALUE mid); -VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements); -MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE); -PUREFUNC(st_table *rb_vm_fstring_table(void)); - - -/* vm_dump.c */ -void rb_print_backtrace(void); - -/* vm_eval.c */ -void Init_vm_eval(void); -VALUE rb_adjust_argv_kw_splat(int *, const VALUE **, int *); -VALUE rb_current_realfilepath(void); -VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE); -typedef void rb_check_funcall_hook(int, VALUE, ID, int, const VALUE *, VALUE); -VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv, - rb_check_funcall_hook *hook, VALUE arg); -VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *argv, - rb_check_funcall_hook *hook, VALUE arg, int kw_splat); -const char *rb_type_str(enum ruby_value_type type); -VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE); -VALUE rb_yield_1(VALUE val); -VALUE rb_yield_force_blockarg(VALUE values); -VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv, - rb_block_call_func_t bl_proc, int min_argc, int max_argc, - VALUE data2); - -/* vm_insnhelper.c */ -VALUE rb_equal_opt(VALUE obj1, VALUE obj2); -VALUE rb_eql_opt(VALUE obj1, VALUE obj2); -void Init_vm_stack_canary(void); - -/* vm_method.c */ -void Init_eval_method(void); - -enum method_missing_reason { - MISSING_NOENTRY = 0x00, - MISSING_PRIVATE = 0x01, - MISSING_PROTECTED = 0x02, - MISSING_FCALL = 0x04, - MISSING_VCALL = 0x08, - MISSING_SUPER = 0x10, - MISSING_MISSING = 0x20, - MISSING_NONE = 0x40 -}; -struct rb_callable_method_entry_struct; -struct rb_method_definition_struct; -struct rb_execution_context_struct; -struct rb_control_frame_struct; -struct rb_calling_info; -struct rb_call_data; -/* I have several reasons to chose 64 here: - * - * - A cache line must be a power-of-two size. - * - Setting this to anything less than or equal to 32 boosts nothing. - * - I have never seen an architecture that has 128 byte L1 cache line. - * - I know Intel Core and Sparc T4 at least uses 64. - * - I know jemalloc internally has this exact same `#define CACHE_LINE 64`. - * https://github.com/jemalloc/jemalloc/blob/dev/include/jemalloc/internal/jemalloc_internal_types.h - */ -#define CACHELINE 64 -struct rb_call_cache { - /* inline cache: keys */ - rb_serial_t method_state; - rb_serial_t class_serial[ - (CACHELINE - - sizeof(rb_serial_t) /* method_state */ - - sizeof(struct rb_callable_method_entry_struct *) /* me */ - - sizeof(uintptr_t) /* method_serial */ - - sizeof(enum method_missing_reason) /* aux */ - - sizeof(VALUE (*)( /* call */ - struct rb_execution_context_struct *e, - struct rb_control_frame_struct *, - struct rb_calling_info *, - const struct rb_call_data *))) - / sizeof(rb_serial_t) - ]; - - /* inline cache: values */ - const struct rb_callable_method_entry_struct *me; - uintptr_t method_serial; /* me->def->method_serial */ - - VALUE (*call)(struct rb_execution_context_struct *ec, - struct rb_control_frame_struct *cfp, - struct rb_calling_info *calling, - struct rb_call_data *cd); - - union { - unsigned int index; /* used by ivar */ - enum method_missing_reason method_missing_reason; /* used by method_missing */ - } aux; -}; -STATIC_ASSERT(cachelined, sizeof(struct rb_call_cache) <= CACHELINE); -struct rb_call_info { - /* fixed at compile time */ - ID mid; - unsigned int flag; - int orig_argc; -}; -struct rb_call_data { - struct rb_call_cache cc; - struct rb_call_info ci; -}; -RUBY_FUNC_EXPORTED -RUBY_FUNC_NONNULL(1, VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, int, const VALUE*)); -RUBY_FUNC_EXPORTED -RUBY_FUNC_NONNULL(1, bool rb_method_basic_definition_p_with_cc(struct rb_call_data *, VALUE, ID)); - -#ifdef __GNUC__ -# define rb_funcallv(recv, mid, argc, argv) \ - __extension__({ \ - static struct rb_call_data rb_funcallv_data; \ - rb_funcallv_with_cc(&rb_funcallv_data, recv, mid, argc, argv); \ - }) -# define rb_method_basic_definition_p(klass, mid) \ - __extension__({ \ - static struct rb_call_data rb_mbdp; \ - (klass == Qfalse) ? /* hidden object cannot be overridden */ true : \ - rb_method_basic_definition_p_with_cc(&rb_mbdp, klass, mid); \ - }) -#endif - -/* vm_backtrace.c */ -void Init_vm_backtrace(void); -VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval); -VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval); - -VALUE rb_make_backtrace(void); -void rb_backtrace_print_as_bugreport(void); -int rb_backtrace_p(VALUE obj); -VALUE rb_backtrace_to_str_ary(VALUE obj); -VALUE rb_backtrace_to_location_ary(VALUE obj); -void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output); - -RUBY_SYMBOL_EXPORT_BEGIN -const char *rb_objspace_data_type_name(VALUE obj); - -/* Temporary. This API will be removed (renamed). */ -VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd); - -/* array.c (export) */ -void rb_ary_detransient(VALUE a); -VALUE *rb_ary_ptr_use_start(VALUE ary); -void rb_ary_ptr_use_end(VALUE ary); - -/* bignum.c (export) */ -VALUE rb_big_mul_normal(VALUE x, VALUE y); -VALUE rb_big_mul_balance(VALUE x, VALUE y); -VALUE rb_big_mul_karatsuba(VALUE x, VALUE y); -VALUE rb_big_mul_toom3(VALUE x, VALUE y); -VALUE rb_big_sq_fast(VALUE x); -VALUE rb_big_divrem_normal(VALUE x, VALUE y); -VALUE rb_big2str_poweroftwo(VALUE x, int base); -VALUE rb_big2str_generic(VALUE x, int base); -VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck); -VALUE rb_str2big_normal(VALUE arg, int base, int badcheck); -VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck); -#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) -VALUE rb_big_mul_gmp(VALUE x, VALUE y); -VALUE rb_big_divrem_gmp(VALUE x, VALUE y); -VALUE rb_big2str_gmp(VALUE x, int base); -VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck); -#endif -enum rb_int_parse_flags { - RB_INT_PARSE_SIGN = 0x01, - RB_INT_PARSE_UNDERSCORE = 0x02, - RB_INT_PARSE_PREFIX = 0x04, - RB_INT_PARSE_ALL = 0x07, - RB_INT_PARSE_DEFAULT = 0x07 -}; -VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags); - -/* enumerator.c (export) */ -VALUE 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); - -/* error.c (export) */ -int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data); -NORETURN(void rb_unexpected_type(VALUE,int)); -#undef Check_Type -#define Check_Type(v, t) \ - (!RB_TYPE_P((VALUE)(v), (t)) || \ - ((t) == RUBY_T_DATA && RTYPEDDATA_P(v)) ? \ - rb_unexpected_type((VALUE)(v), (t)) : (void)0) - -static inline int -rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type) -{ - return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type); -} -#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline - -/* file.c (export) */ -#if defined HAVE_READLINK && defined RUBY_ENCODING_H -VALUE rb_readlink(VALUE path, rb_encoding *enc); -#endif -#ifdef __APPLE__ -VALUE rb_str_normalize_ospath(const char *ptr, long len); -#endif - -/* hash.c (export) */ -VALUE rb_hash_delete_entry(VALUE hash, VALUE key); -VALUE rb_ident_hash_new(void); - -/* io.c (export) */ -void rb_maygvl_fd_fix_cloexec(int fd); -int rb_gc_for_fd(int err); -void rb_write_error_str(VALUE mesg); - -/* numeric.c (export) */ -VALUE rb_int_positive_pow(long x, unsigned long y); - -/* object.c (export) */ -int rb_opts_exception_p(VALUE opts, int default_value); - -/* process.c (export) */ -int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen); -rb_pid_t rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen); -VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt); -struct rb_execarg *rb_execarg_get(VALUE execarg_obj); /* dangerous. needs GC guard. */ -int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val); -void rb_execarg_parent_start(VALUE execarg_obj); -void rb_execarg_parent_end(VALUE execarg_obj); -int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char* errmsg, size_t errmsg_buflen); -VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash); -void rb_execarg_setenv(VALUE execarg_obj, VALUE env); - -/* rational.c (export) */ -VALUE rb_gcd(VALUE x, VALUE y); -VALUE rb_gcd_normal(VALUE self, VALUE other); -#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) -VALUE rb_gcd_gmp(VALUE x, VALUE y); -#endif - -/* signal.c (export) */ -int rb_grantpt(int fd); - -/* string.c (export) */ -VALUE rb_str_tmp_frozen_acquire(VALUE str); -void rb_str_tmp_frozen_release(VALUE str, VALUE tmp); -#ifdef RUBY_ENCODING_H -/* internal use */ -VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc); -#endif -VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE); -VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE); - -/* thread.c (export) */ -int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */ - -/* time.c (export) */ -void ruby_reset_leap_second_info(void); - -/* util.c (export) */ -extern const signed char ruby_digit36_to_number_table[]; -extern const char ruby_hexdigits[]; -extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); - -/* variable.c (export) */ -void rb_mark_generic_ivar(VALUE); -void rb_mv_generic_ivar(VALUE src, VALUE dst); -VALUE rb_const_missing(VALUE klass, VALUE name); -int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); -void rb_iv_tbl_copy(VALUE dst, VALUE src); - -/* gc.c (export) */ -VALUE rb_wb_protected_newobj_of(VALUE, VALUE); -VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE); - -size_t rb_obj_memsize_of(VALUE); -void rb_gc_verify_internal_consistency(void); - -#define RB_OBJ_GC_FLAGS_MAX 6 -size_t rb_obj_gc_flags(VALUE, ID[], size_t); -void rb_gc_mark_values(long n, const VALUE *values); -void rb_gc_mark_vm_stack_values(long n, const VALUE *values); - -#if IMEMO_DEBUG -VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line); -#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__) -#else -VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); -#endif - -/* random.c */ -int ruby_fill_random_bytes(void *, size_t, int); - -RUBY_SYMBOL_EXPORT_END - -#define RUBY_DTRACE_CREATE_HOOK(name, arg) \ - RUBY_DTRACE_HOOK(name##_CREATE, arg) -#define RUBY_DTRACE_HOOK(name, arg) \ -do { \ - if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \ - int dtrace_line; \ - const char *dtrace_file = rb_source_location_cstr(&dtrace_line); \ - if (!dtrace_file) dtrace_file = ""; \ - RUBY_DTRACE_##name(arg, dtrace_file, dtrace_line); \ - } \ -} while (0) - -#define RB_OBJ_BUILTIN_TYPE(obj) rb_obj_builtin_type(obj) -#define OBJ_BUILTIN_TYPE(obj) RB_OBJ_BUILTIN_TYPE(obj) -#ifdef __GNUC__ -#define rb_obj_builtin_type(obj) \ -__extension__({ \ - VALUE arg_obj = (obj); \ - RB_SPECIAL_CONST_P(arg_obj) ? -1 : \ - RB_BUILTIN_TYPE(arg_obj); \ - }) -#else -static inline int -rb_obj_builtin_type(VALUE obj) -{ - return RB_SPECIAL_CONST_P(obj) ? -1 : - RB_BUILTIN_TYPE(obj); -} -#endif - -/* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define FLEX_ARY_LEN /* VALUE ary[]; */ -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) -# define FLEX_ARY_LEN 0 /* VALUE ary[0]; */ -#else -# define FLEX_ARY_LEN 1 /* VALUE ary[1]; */ -#endif - -/* - * For declaring bitfields out of non-unsigned int types: - * struct date { - * BITFIELD(enum months, month, 4); - * ... - * }; - */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define BITFIELD(type, name, size) type name : size -#else -# define BITFIELD(type, name, size) unsigned int name : size -#endif - -#if defined(_MSC_VER) -# define COMPILER_WARNING_PUSH __pragma(warning(push)) -# define COMPILER_WARNING_POP __pragma(warning(pop)) -# define COMPILER_WARNING_ERROR(flag) __pragma(warning(error: flag))) -# define COMPILER_WARNING_IGNORED(flag) __pragma(warning(suppress: flag))) - -#elif defined(__clang__) /* clang 2.6 already had this feature */ -# define COMPILER_WARNING_PUSH _Pragma("clang diagnostic push") -# define COMPILER_WARNING_POP _Pragma("clang diagnostic pop") -# define COMPILER_WARNING_SPECIFIER(kind, msg) \ - clang diagnostic kind # msg -# define COMPILER_WARNING_ERROR(flag) \ - COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(error, flag)) -# define COMPILER_WARNING_IGNORED(flag) \ - COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(ignored, flag)) - -#elif GCC_VERSION_SINCE(4, 6, 0) -/* https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Diagnostic-Pragmas.html */ -# define COMPILER_WARNING_PUSH _Pragma("GCC diagnostic push") -# define COMPILER_WARNING_POP _Pragma("GCC diagnostic pop") -# define COMPILER_WARNING_SPECIFIER(kind, msg) \ - GCC diagnostic kind # msg -# define COMPILER_WARNING_ERROR(flag) \ - COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(error, flag)) -# define COMPILER_WARNING_IGNORED(flag) \ - COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(ignored, flag)) - -#else /* other compilers to follow? */ -# define COMPILER_WARNING_PUSH /* nop */ -# define COMPILER_WARNING_POP /* nop */ -# define COMPILER_WARNING_ERROR(flag) /* nop */ -# define COMPILER_WARNING_IGNORED(flag) /* nop */ -#endif - -#define COMPILER_WARNING_PRAGMA(str) COMPILER_WARNING_PRAGMA_(str) -#define COMPILER_WARNING_PRAGMA_(str) _Pragma(#str) - -#if defined(USE_UNALIGNED_MEMBER_ACCESS) && USE_UNALIGNED_MEMBER_ACCESS && \ - (defined(__clang__) || GCC_VERSION_SINCE(9, 0, 0)) -# define UNALIGNED_MEMBER_ACCESS(expr) __extension__({ \ - COMPILER_WARNING_PUSH; \ - COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \ - typeof(expr) unaligned_member_access_result = (expr); \ - COMPILER_WARNING_POP; \ - unaligned_member_access_result; \ -}) -#else -# define UNALIGNED_MEMBER_ACCESS(expr) expr -#endif -#define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem) - -#undef RB_OBJ_WRITE -#define RB_OBJ_WRITE(a, slot, b) UNALIGNED_MEMBER_ACCESS(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__)) - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif +#define RBOOL(v) ((v) ? Qtrue : Qfalse) +#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM) #endif /* RUBY_INTERNAL_H */ diff --git a/ruby/internal/array.h b/ruby/internal/array.h new file mode 100644 index 000000000..60f66f31b --- /dev/null +++ b/ruby/internal/array.h @@ -0,0 +1,113 @@ +#ifndef INTERNAL_ARRAY_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ARRAY_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Array. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "internal/static_assert.h" /* for STATIC_ASSERT */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for RARRAY_LEN */ + +#ifndef ARRAY_DEBUG +# define ARRAY_DEBUG (0+RUBY_DEBUG) +#endif + +#define RARRAY_PTR_IN_USE_FLAG FL_USER14 + +/* array.c */ +VALUE rb_ary_last(int, const VALUE *, VALUE); +void rb_ary_set_len(VALUE, long); +void rb_ary_delete_same(VALUE, VALUE); +VALUE rb_ary_tmp_new_fill(long capa); +VALUE rb_ary_at(VALUE, VALUE); +size_t rb_ary_memsize(VALUE); +VALUE rb_to_array_type(VALUE obj); +VALUE rb_to_array(VALUE obj); +void rb_ary_cancel_sharing(VALUE ary); + +static inline VALUE rb_ary_entry_internal(VALUE ary, long offset); +static inline bool ARY_PTR_USING_P(VALUE ary); +static inline void RARY_TRANSIENT_SET(VALUE ary); +static inline void RARY_TRANSIENT_UNSET(VALUE ary); + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *); +VALUE rb_check_to_array(VALUE ary); +VALUE rb_ary_behead(VALUE, long); +VALUE rb_ary_aref1(VALUE ary, VALUE i); + +struct rb_execution_context_struct; +VALUE rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts); +MJIT_SYMBOL_EXPORT_END + +// YJIT needs this function to never allocate and never raise +static inline VALUE +rb_ary_entry_internal(VALUE ary, long offset) +{ + long len = RARRAY_LEN(ary); + const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary); + if (len == 0) return Qnil; + if (offset < 0) { + offset += len; + if (offset < 0) return Qnil; + } + else if (len <= offset) { + return Qnil; + } + return ptr[offset]; +} + +static inline bool +ARY_PTR_USING_P(VALUE ary) +{ + return FL_TEST_RAW(ary, RARRAY_PTR_IN_USE_FLAG); +} + +static inline void +RARY_TRANSIENT_SET(VALUE ary) +{ +#if USE_TRANSIENT_HEAP + FL_SET_RAW(ary, RARRAY_TRANSIENT_FLAG); +#endif +} + +static inline void +RARY_TRANSIENT_UNSET(VALUE ary) +{ +#if USE_TRANSIENT_HEAP + FL_UNSET_RAW(ary, RARRAY_TRANSIENT_FLAG); +#endif +} + +#undef rb_ary_new_from_args +#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") +# /* Skip it; clang -pedantic doesn't like the following */ +#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) +#define rb_ary_new_from_args(n, ...) \ + __extension__ ({ \ + const VALUE args_to_new_ary[] = {__VA_ARGS__}; \ + if (__builtin_constant_p(n)) { \ + STATIC_ASSERT(rb_ary_new_from_args, numberof(args_to_new_ary) == (n)); \ + } \ + rb_ary_new_from_values(numberof(args_to_new_ary), args_to_new_ary); \ + }) +#endif + +#undef RARRAY_AREF +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +static inline VALUE +RARRAY_AREF(VALUE ary, long i) +{ + RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); + + return RARRAY_CONST_PTR_TRANSIENT(ary)[i]; +} + +#endif /* INTERNAL_ARRAY_H */ diff --git a/ruby/internal/bignum.h b/ruby/internal/bignum.h new file mode 100644 index 000000000..5cd35ede8 --- /dev/null +++ b/ruby/internal/bignum.h @@ -0,0 +1,246 @@ +#ifndef INTERNAL_BIGNUM_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_BIGNUM_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Bignums. + */ +#include "ruby/internal/config.h" /* for HAVE_LIBGMP */ +#include /* for size_t */ + +#ifdef HAVE_SYS_TYPES_H +# include /* for ssize_t (note: on Windows ssize_t is */ +#endif /* `#define`d in ruby/config.h) */ + +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for struct RBasic */ + +#ifndef BDIGIT +# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG +# define BDIGIT unsigned int +# define SIZEOF_BDIGIT SIZEOF_INT +# define BDIGIT_DBL unsigned LONG_LONG +# define BDIGIT_DBL_SIGNED LONG_LONG +# define PRI_BDIGIT_PREFIX "" +# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX +# elif SIZEOF_INT*2 <= SIZEOF_LONG +# define BDIGIT unsigned int +# define SIZEOF_BDIGIT SIZEOF_INT +# define BDIGIT_DBL unsigned long +# define BDIGIT_DBL_SIGNED long +# define PRI_BDIGIT_PREFIX "" +# define PRI_BDIGIT_DBL_PREFIX "l" +# elif SIZEOF_SHORT*2 <= SIZEOF_LONG +# define BDIGIT unsigned short +# define SIZEOF_BDIGIT SIZEOF_SHORT +# define BDIGIT_DBL unsigned long +# define BDIGIT_DBL_SIGNED long +# define PRI_BDIGIT_PREFIX "h" +# define PRI_BDIGIT_DBL_PREFIX "l" +# else +# define BDIGIT unsigned short +# define SIZEOF_BDIGIT (SIZEOF_LONG/2) +# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG +# define BDIGIT_DBL unsigned long +# define BDIGIT_DBL_SIGNED long +# define PRI_BDIGIT_PREFIX "h" +# define PRI_BDIGIT_DBL_PREFIX "l" +# endif +#endif + +#ifndef SIZEOF_ACTUAL_BDIGIT +# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT +#endif + +#ifdef PRI_BDIGIT_PREFIX +# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d" +# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i" +# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o" +# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u" +# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x" +# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X" +#endif + +#ifdef PRI_BDIGIT_DBL_PREFIX +# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d" +# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i" +# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o" +# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u" +# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x" +# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X" +#endif + +#define RBIGNUM(obj) ((struct RBignum *)(obj)) +#define BIGNUM_SIGN_BIT FL_USER1 +#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2) +#define BIGNUM_EMBED_LEN_NUMBITS 3 +#define BIGNUM_EMBED_LEN_MASK \ + (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT) +#define BIGNUM_EMBED_LEN_SHIFT \ + (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */ +#ifndef BIGNUM_EMBED_LEN_MAX +# if (SIZEOF_VALUE*RBIMPL_RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1 +# define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RBIMPL_RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) +# else +# define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1) +# endif +#endif + +enum rb_int_parse_flags { + RB_INT_PARSE_SIGN = 0x01, + RB_INT_PARSE_UNDERSCORE = 0x02, + RB_INT_PARSE_PREFIX = 0x04, + RB_INT_PARSE_ALL = 0x07, + RB_INT_PARSE_DEFAULT = 0x07, +}; + +struct RBignum { + struct RBasic basic; + union { + struct { + size_t len; + BDIGIT *digits; + } heap; + BDIGIT ary[BIGNUM_EMBED_LEN_MAX]; + } as; +}; + +/* bignum.c */ +extern const char ruby_digitmap[]; +double rb_big_fdiv_double(VALUE x, VALUE y); +VALUE rb_big_uminus(VALUE x); +VALUE rb_big_hash(VALUE); +VALUE rb_big_odd_p(VALUE); +VALUE rb_big_even_p(VALUE); +size_t rb_big_size(VALUE); +VALUE rb_integer_float_cmp(VALUE x, VALUE y); +VALUE rb_integer_float_eq(VALUE x, VALUE y); +VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception); +VALUE rb_big_comp(VALUE x); +VALUE rb_big_aref(VALUE x, VALUE y); +VALUE rb_big_abs(VALUE x); +VALUE rb_big_size_m(VALUE big); +VALUE rb_big_bit_length(VALUE big); +VALUE rb_big_remainder(VALUE x, VALUE y); +VALUE rb_big_gt(VALUE x, VALUE y); +VALUE rb_big_ge(VALUE x, VALUE y); +VALUE rb_big_lt(VALUE x, VALUE y); +VALUE rb_big_le(VALUE x, VALUE y); +VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num); +VALUE rb_big_isqrt(VALUE n); +static inline bool BIGNUM_SIGN(VALUE b); +static inline bool BIGNUM_POSITIVE_P(VALUE b); +static inline bool BIGNUM_NEGATIVE_P(VALUE b); +static inline void BIGNUM_SET_SIGN(VALUE b, bool sign); +static inline void BIGNUM_NEGATE(VALUE b); +static inline size_t BIGNUM_LEN(VALUE b); +static inline BDIGIT *BIGNUM_DIGITS(VALUE b); +static inline int BIGNUM_LENINT(VALUE b); +static inline bool BIGNUM_EMBED_P(VALUE b); + +RUBY_SYMBOL_EXPORT_BEGIN +/* bignum.c (export) */ +VALUE rb_big_mul_normal(VALUE x, VALUE y); +VALUE rb_big_mul_balance(VALUE x, VALUE y); +VALUE rb_big_mul_karatsuba(VALUE x, VALUE y); +VALUE rb_big_mul_toom3(VALUE x, VALUE y); +VALUE rb_big_sq_fast(VALUE x); +VALUE rb_big_divrem_normal(VALUE x, VALUE y); +VALUE rb_big2str_poweroftwo(VALUE x, int base); +VALUE rb_big2str_generic(VALUE x, int base); +VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck); +VALUE rb_str2big_normal(VALUE arg, int base, int badcheck); +VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck); +#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) +VALUE rb_big_mul_gmp(VALUE x, VALUE y); +VALUE rb_big_divrem_gmp(VALUE x, VALUE y); +VALUE rb_big2str_gmp(VALUE x, int base); +VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck); +#endif +VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +#if defined(HAVE_INT128_T) +VALUE rb_int128t2big(int128_t n); +#endif +MJIT_SYMBOL_EXPORT_END + +/* sign: positive:1, negative:0 */ +static inline bool +BIGNUM_SIGN(VALUE b) +{ + return FL_TEST_RAW(b, BIGNUM_SIGN_BIT); +} + +static inline bool +BIGNUM_POSITIVE_P(VALUE b) +{ + return BIGNUM_SIGN(b); +} + +static inline bool +BIGNUM_NEGATIVE_P(VALUE b) +{ + return ! BIGNUM_POSITIVE_P(b); +} + +static inline void +BIGNUM_SET_SIGN(VALUE b, bool sign) +{ + if (sign) { + FL_SET_RAW(b, BIGNUM_SIGN_BIT); + } + else { + FL_UNSET_RAW(b, BIGNUM_SIGN_BIT); + } +} + +static inline void +BIGNUM_NEGATE(VALUE b) +{ + FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT); +} + +static inline size_t +BIGNUM_LEN(VALUE b) +{ + if (! BIGNUM_EMBED_P(b)) { + return RBIGNUM(b)->as.heap.len; + } + else { + size_t ret = RBASIC(b)->flags; + ret &= BIGNUM_EMBED_LEN_MASK; + ret >>= BIGNUM_EMBED_LEN_SHIFT; + return ret; + } +} + +static inline int +BIGNUM_LENINT(VALUE b) +{ + return rb_long2int(BIGNUM_LEN(b)); +} + +/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */ +static inline BDIGIT * +BIGNUM_DIGITS(VALUE b) +{ + if (BIGNUM_EMBED_P(b)) { + return RBIGNUM(b)->as.ary; + } + else { + return RBIGNUM(b)->as.heap.digits; + } +} + +static inline bool +BIGNUM_EMBED_P(VALUE b) +{ + return FL_TEST_RAW(b, BIGNUM_EMBED_FLAG); +} + +#endif /* INTERNAL_BIGNUM_H */ diff --git a/ruby/internal/bits.h b/ruby/internal/bits.h new file mode 100644 index 000000000..2602ff7a3 --- /dev/null +++ b/ruby/internal/bits.h @@ -0,0 +1,565 @@ +#ifndef INTERNAL_BITS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_BITS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for bitwise integer algorithms. + * @see Henry S. Warren Jr., "Hacker's Delight" (2nd ed.), 2013. + * @see SEI CERT C Coding Standard INT32-C. "Ensure that operations on + * signed integers do not result in overflow" + * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html + * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateleft + * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateright + * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/byteswap-uint64-byteswap-ulong-byteswap-ushort + * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rotl-rotl64-rotr-rotr64 + * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64 + * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64 + * @see https://docs.microsoft.com/en-us/cpp/intrinsics/lzcnt16-lzcnt-lzcnt64 + * @see https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64 + * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_lzcnt_u32 + * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_tzcnt_u32 + * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotl64 + * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotr64 + * @see https://stackoverflow.com/a/776523 + */ +#include "ruby/internal/config.h" +#include /* for CHAR_BITS */ +#include /* for uintptr_t */ +#include "internal/compilers.h" /* for MSC_VERSION_SINCE */ + +#if MSC_VERSION_SINCE(1310) +# include /* for _byteswap_uint64 */ +#endif + +#if defined(HAVE_X86INTRIN_H) && ! defined(MJIT_HEADER) +# /* Rule out MJIT_HEADER, which does not interface well with */ +# include /* for _lzcnt_u64 */ +#elif MSC_VERSION_SINCE(1310) +# include /* for the following intrinsics */ +#endif + +#if defined(_MSC_VER) && defined(__AVX__) +# pragma intrinsic(__popcnt) +# pragma intrinsic(__popcnt64) +#endif + +#if defined(_MSC_VER) && defined(__AVX2__) +# pragma intrinsic(__lzcnt) +# pragma intrinsic(__lzcnt64) +#endif + +#if MSC_VERSION_SINCE(1310) +# pragma intrinsic(_rotl) +# pragma intrinsic(_rotr) +# ifdef _WIN64 +# pragma intrinsic(_rotl64) +# pragma intrinsic(_rotr64) +# endif +#endif + +#if MSC_VERSION_SINCE(1400) +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# ifdef _WIN64 +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif +#endif + +#include "ruby/ruby.h" /* for VALUE */ +#include "internal/static_assert.h" /* for STATIC_ASSERT */ + +/* The most significant bit of the lower part of half-long integer. + * If sizeof(long) == 4, this is 0x8000. + * If sizeof(long) == 8, this is 0x80000000. + */ +#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2)) + +#define SIGNED_INTEGER_TYPE_P(T) (0 > ((T)0)-1) + +#define SIGNED_INTEGER_MIN(T) \ + ((sizeof(T) == sizeof(int8_t)) ? ((T)INT8_MIN) : \ + ((sizeof(T) == sizeof(int16_t)) ? ((T)INT16_MIN) : \ + ((sizeof(T) == sizeof(int32_t)) ? ((T)INT32_MIN) : \ + ((sizeof(T) == sizeof(int64_t)) ? ((T)INT64_MIN) : \ + 0)))) + +#define SIGNED_INTEGER_MAX(T) ((T)(SIGNED_INTEGER_MIN(T) ^ ((T)~(T)0))) + +#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0) + +#if __has_builtin(__builtin_mul_overflow_p) +# define MUL_OVERFLOW_P(a, b) \ + __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0) +#elif __has_builtin(__builtin_mul_overflow) +# define MUL_OVERFLOW_P(a, b) \ + __extension__ ({ __typeof__(a) c; __builtin_mul_overflow((a), (b), &c); }) +#endif + +#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))) + +#if __has_builtin(__builtin_mul_overflow_p) +/* __builtin_mul_overflow_p can take bitfield */ +/* and GCC permits bitfields for integers other than int */ +# define MUL_OVERFLOW_FIXNUM_P(a, b) \ + __extension__ ({ \ + struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \ + __builtin_mul_overflow_p((a), (b), c.fixnum); \ + }) +#else +# define MUL_OVERFLOW_FIXNUM_P(a, b) \ + MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX) +#endif + +#ifdef MUL_OVERFLOW_P +# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b) +# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b) +# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b) +#else +# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX) +# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX) +# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX) +#endif + +#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 + +#ifndef swap16 +# define swap16 ruby_swap16 +#endif + +#ifndef swap32 +# define swap32 ruby_swap32 +#endif + +#ifndef swap64 +# define swap64 ruby_swap64 +#endif + +static inline uint16_t ruby_swap16(uint16_t); +static inline uint32_t ruby_swap32(uint32_t); +static inline uint64_t ruby_swap64(uint64_t); +static inline unsigned nlz_int(unsigned x); +static inline unsigned nlz_long(unsigned long x); +static inline unsigned nlz_long_long(unsigned long long x); +static inline unsigned nlz_intptr(uintptr_t x); +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 rb_popcount32(uint32_t x); +static inline unsigned rb_popcount64(uint64_t x); +static inline unsigned rb_popcount_intptr(uintptr_t x); +static inline int ntz_int32(uint32_t x); +static inline int ntz_int64(uint64_t x); +static inline int ntz_intptr(uintptr_t x); +static inline VALUE RUBY_BIT_ROTL(VALUE, int); +static inline VALUE RUBY_BIT_ROTR(VALUE, int); + +static inline uint16_t +ruby_swap16(uint16_t x) +{ +#if __has_builtin(__builtin_bswap16) + return __builtin_bswap16(x); + +#elif MSC_VERSION_SINCE(1310) + return _byteswap_ushort(x); + +#else + return (x << 8) | (x >> 8); + +#endif +} + +static inline uint32_t +ruby_swap32(uint32_t x) +{ +#if __has_builtin(__builtin_bswap32) + return __builtin_bswap32(x); + +#elif MSC_VERSION_SINCE(1310) + return _byteswap_ulong(x); + +#else + x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16); + x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8); + return x; + +#endif +} + +static inline uint64_t +ruby_swap64(uint64_t x) +{ +#if __has_builtin(__builtin_bswap64) + return __builtin_bswap64(x); + +#elif MSC_VERSION_SINCE(1310) + return _byteswap_uint64(x); + +#else + x = ((x & 0x00000000FFFFFFFFULL) << 32) | ((x & 0xFFFFFFFF00000000ULL) >> 32); + x = ((x & 0x0000FFFF0000FFFFULL) << 16) | ((x & 0xFFFF0000FFFF0000ULL) >> 16); + x = ((x & 0x00FF00FF00FF00FFULL) << 8) | ((x & 0xFF00FF00FF00FF00ULL) >> 8); + return x; + +#endif +} + +static inline unsigned int +nlz_int32(uint32_t x) +{ +#if defined(_MSC_VER) && defined(__AVX2__) + /* 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(MJIT_HEADER) + return (unsigned int)_lzcnt_u32(x); + +#elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */ + 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__) + return (unsigned int)__lzcnt64(x); + +#elif defined(__x86_64__) && defined(__LZCNT__) && ! defined(MJIT_HEADER) + return (unsigned int)_lzcnt_u64(x); + +#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */ + unsigned long r; + return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64; + +#elif __has_builtin(__builtin_clzl) + 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? */ + UNREACHABLE_RETURN(~0); + } + +#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 + +static inline unsigned int +nlz_int(unsigned int x) +{ + if (sizeof(unsigned int) * CHAR_BIT == 32) { + return nlz_int32((uint32_t)x); + } + else if (sizeof(unsigned int) * CHAR_BIT == 64) { + return nlz_int64((uint64_t)x); + } + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline unsigned int +nlz_long(unsigned long x) +{ + if (sizeof(unsigned long) * CHAR_BIT == 32) { + return nlz_int32((uint32_t)x); + } + else if (sizeof(unsigned long) * CHAR_BIT == 64) { + return nlz_int64((uint64_t)x); + } + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline unsigned int +nlz_long_long(unsigned long long x) +{ + if (sizeof(unsigned long long) * CHAR_BIT == 64) { + return nlz_int64((uint64_t)x); + } +#ifdef HAVE_UINT128_T + else if (sizeof(unsigned long long) * CHAR_BIT == 128) { + return nlz_int128((uint128_t)x); + } +#endif + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline unsigned int +nlz_intptr(uintptr_t x) +{ + if (sizeof(uintptr_t) == sizeof(unsigned int)) { + return nlz_int((unsigned int)x); + } + if (sizeof(uintptr_t) == sizeof(unsigned long)) { + return nlz_long((unsigned long)x); + } + if (sizeof(uintptr_t) == sizeof(unsigned long long)) { + return nlz_long_long((unsigned long long)x); + } + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline unsigned int +rb_popcount32(uint32_t x) +{ +#if defined(_MSC_VER) && defined(__AVX__) + /* Note: CPUs since Nehalem and Barcelona have had this instruction so SSE + * 4.2 should suffice, but it seems there is no such thing like __SSE_4_2__ + * predefined macro in MSVC. They do have __AVX__ so use it instead. */ + return (unsigned int)__popcnt(x); + +#elif __has_builtin(__builtin_popcount) + STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT >= 32); + return (unsigned int)__builtin_popcount(x); + +#else + x = (x & 0x55555555) + (x >> 1 & 0x55555555); + x = (x & 0x33333333) + (x >> 2 & 0x33333333); + x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f); + x = (x & 0x001f001f) + (x >> 8 & 0x001f001f); + x = (x & 0x0000003f) + (x >>16 & 0x0000003f); + return (unsigned int)x; + +#endif +} + +static inline unsigned int +rb_popcount64(uint64_t x) +{ +#if defined(_MSC_VER) && defined(__AVX__) + return (unsigned int)__popcnt64(x); + +#elif __has_builtin(__builtin_popcount) + if (sizeof(long) * CHAR_BIT == 64) { + return (unsigned int)__builtin_popcountl((unsigned long)x); + } + else if (sizeof(long long) * CHAR_BIT == 64) { + return (unsigned int)__builtin_popcountll((unsigned long long)x); + } + else { + /* :FIXME: Is there a way to make this branch a compile-time error? */ + UNREACHABLE_RETURN(~0); + } + +#else + x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555); + x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333); + x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707); + x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f); + x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f); + x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f); + return (unsigned int)x; + +#endif +} + +static inline unsigned int +rb_popcount_intptr(uintptr_t x) +{ + if (sizeof(uintptr_t) * CHAR_BIT == 64) { + return rb_popcount64((uint64_t)x); + } + else if (sizeof(uintptr_t) * CHAR_BIT == 32) { + return rb_popcount32((uint32_t)x); + } + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline int +ntz_int32(uint32_t x) +{ +#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER) + return (unsigned)_tzcnt_u32(x); + +#elif MSC_VERSION_SINCE(1400) + /* :FIXME: Is there any way to issue TZCNT instead of BSF, apart from using + * assembly? Because issuing LZCNT seems possible (see nlz.h). */ + unsigned long r; + return _BitScanForward(&r, x) ? (int)r : 32; + +#elif __has_builtin(__builtin_ctz) + STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32); + return x ? (unsigned)__builtin_ctz(x) : 32; + +#else + return rb_popcount32((~x) & (x-1)); + +#endif +} + +static inline int +ntz_int64(uint64_t x) +{ +#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER) + return (unsigned)_tzcnt_u64(x); + +#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) + unsigned long r; + return _BitScanForward64(&r, x) ? (int)r : 64; + +#elif __has_builtin(__builtin_ctzl) + if (x == 0) { + return 64; + } + else if (sizeof(long) * CHAR_BIT == 64) { + return (unsigned)__builtin_ctzl((unsigned long)x); + } + else if (sizeof(long long) * CHAR_BIT == 64) { + return (unsigned)__builtin_ctzll((unsigned long long)x); + } + else { + /* :FIXME: Is there a way to make this branch a compile-time error? */ + UNREACHABLE_RETURN(~0); + } + +#else + return rb_popcount64((~x) & (x-1)); + +#endif +} + +static inline int +ntz_intptr(uintptr_t x) +{ + if (sizeof(uintptr_t) * CHAR_BIT == 64) { + return ntz_int64((uint64_t)x); + } + else if (sizeof(uintptr_t) * CHAR_BIT == 32) { + return ntz_int32((uint32_t)x); + } + else { + UNREACHABLE_RETURN(~0); + } +} + +static inline VALUE +RUBY_BIT_ROTL(VALUE v, int n) +{ +#if __has_builtin(__builtin_rotateleft32) && (SIZEOF_VALUE * CHAR_BIT == 32) + return __builtin_rotateleft32(v, n); + +#elif __has_builtin(__builtin_rotateleft64) && (SIZEOF_VALUE * CHAR_BIT == 64) + return __builtin_rotateleft64(v, n); + +#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32) + return _rotl(v, n); + +#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64) + return _rotl64(v, n); + +#elif defined(_lrotl) && (SIZEOF_VALUE == SIZEOF_LONG) + return _lrotl(v, n); + +#else + const int m = (sizeof(VALUE) * CHAR_BIT) - 1; + return (v << (n & m)) | (v >> (-n & m)); +#endif +} + +static inline VALUE +RUBY_BIT_ROTR(VALUE v, int n) +{ +#if __has_builtin(__builtin_rotateright32) && (SIZEOF_VALUE * CHAR_BIT == 32) + return __builtin_rotateright32(v, n); + +#elif __has_builtin(__builtin_rotateright64) && (SIZEOF_VALUE * CHAR_BIT == 64) + return __builtin_rotateright64(v, n); + +#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32) + return _rotr(v, n); + +#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64) + return _rotr64(v, n); + +#elif defined(_lrotr) && (SIZEOF_VALUE == SIZEOF_LONG) + return _lrotr(v, n); + +#else + const int m = (sizeof(VALUE) * CHAR_BIT) - 1; + return (v << (-n & m)) | (v >> (n & m)); +#endif +} + +#endif /* INTERNAL_BITS_H */ diff --git a/ruby/internal/class.h b/ruby/internal/class.h new file mode 100644 index 000000000..9edc82170 --- /dev/null +++ b/ruby/internal/class.h @@ -0,0 +1,196 @@ +#ifndef INTERNAL_CLASS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_CLASS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Class. + */ +#include "id_table.h" /* for struct rb_id_table */ +#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "internal/serial.h" /* for rb_serial_t */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/intern.h" /* for rb_alloc_func_t */ +#include "ruby/ruby.h" /* for struct RBasic */ + +#ifdef RCLASS_SUPER +# undef RCLASS_SUPER +#endif + +struct rb_subclass_entry { + VALUE klass; + struct rb_subclass_entry *next; + struct rb_subclass_entry *prev; +}; + +struct rb_iv_index_tbl_entry { + uint32_t index; + rb_serial_t class_serial; + VALUE class_value; +}; + +struct rb_cvar_class_tbl_entry { + uint32_t index; + rb_serial_t global_cvar_state; + VALUE class_value; +}; + +struct rb_classext_struct { + struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry + struct st_table *iv_tbl; +#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */ + struct rb_id_table *m_tbl; +#endif + struct rb_id_table *const_tbl; + struct rb_id_table *callable_m_tbl; + struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */ + struct rb_id_table *cvc_tbl; + struct rb_subclass_entry *subclasses; + struct rb_subclass_entry *subclass_entry; + /** + * In the case that this is an `ICLASS`, `module_subclasses` points to the link + * in the module's `subclasses` list that indicates that the klass has been + * included. Hopefully that makes sense. + */ + struct rb_subclass_entry *module_subclass_entry; +#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */ + rb_serial_t class_serial; +#endif + const VALUE origin_; + const VALUE refined_class; + rb_alloc_func_t allocator; + const VALUE includer; +}; + +struct RClass { + struct RBasic basic; + VALUE super; +#if !USE_RVARGC + struct rb_classext_struct *ptr; +#endif +#if SIZEOF_SERIAL_T == SIZEOF_VALUE + /* Class serial is as wide as VALUE. Place it here. */ + rb_serial_t class_serial; +#else + /* Class serial does not fit into struct RClass. Place m_tbl instead. */ + struct rb_id_table *m_tbl; +#endif +}; + +typedef struct rb_subclass_entry rb_subclass_entry_t; +typedef struct rb_classext_struct rb_classext_t; + +#if USE_RVARGC +# define RCLASS_EXT(c) ((rb_classext_t *)((char *)c + sizeof(struct RClass))) +#else +# define RCLASS_EXT(c) (RCLASS(c)->ptr) +#endif +#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) +#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) +#if SIZEOF_SERIAL_T == SIZEOF_VALUE +# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl) +#else +# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#endif +#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl) +#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl) +#define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl) +#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl) +#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_) +#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class) +#if SIZEOF_SERIAL_T == SIZEOF_VALUE +# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial) +#else +# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial) +#endif +#define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer) +#define RCLASS_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->subclass_entry) +#define RCLASS_MODULE_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->module_subclass_entry) +#define RCLASS_ALLOCATOR(c) (RCLASS_EXT(c)->allocator) +#define RCLASS_SUBCLASSES(c) (RCLASS_EXT(c)->subclasses) + +#define RICLASS_IS_ORIGIN FL_USER5 +#define RCLASS_CLONED FL_USER6 +#define RICLASS_ORIGIN_SHARED_MTBL FL_USER8 + +/* class.c */ +void rb_class_subclass_add(VALUE super, VALUE klass); +void rb_class_remove_from_super_subclasses(VALUE); +void rb_class_remove_subclass_head(VALUE); +int rb_singleton_class_internal_p(VALUE sklass); +VALUE rb_class_boot(VALUE); +VALUE rb_class_s_alloc(VALUE klass); +VALUE rb_module_s_alloc(VALUE klass); +void rb_module_set_initialized(VALUE module); +void rb_module_check_initializable(VALUE module); +VALUE rb_make_metaclass(VALUE, VALUE); +VALUE rb_include_class_new(VALUE, VALUE); +void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE); +void rb_class_detach_subclasses(VALUE); +void rb_class_detach_module_subclasses(VALUE); +void rb_class_remove_from_module_subclasses(VALUE); +VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_special_singleton_class(VALUE); +VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach); +VALUE rb_singleton_class_get(VALUE obj); +void rb_undef_methods_from(VALUE klass, VALUE super); + +static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin); +static inline void RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass); +static inline VALUE RCLASS_SUPER(VALUE klass); +static inline VALUE RCLASS_SET_SUPER(VALUE klass, VALUE super); +static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass); + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_class_inherited(VALUE, VALUE); +VALUE rb_keyword_error_new(const char *, VALUE); +MJIT_SYMBOL_EXPORT_END + +static inline void +RCLASS_SET_ORIGIN(VALUE klass, VALUE origin) +{ + RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin); + if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN); +} + +static inline void +RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass) +{ + FL_SET(iclass, RICLASS_ORIGIN_SHARED_MTBL); +} + +static inline bool +RICLASS_OWNS_M_TBL_P(VALUE iclass) +{ + return FL_TEST_RAW(iclass, RICLASS_IS_ORIGIN | RICLASS_ORIGIN_SHARED_MTBL) == RICLASS_IS_ORIGIN; +} + +static inline void +RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass) +{ + RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass); +} + +static inline VALUE +RCLASS_SUPER(VALUE klass) +{ + return RCLASS(klass)->super; +} + +static inline VALUE +RCLASS_SET_SUPER(VALUE klass, VALUE super) +{ + if (super) { + rb_class_remove_from_super_subclasses(klass); + rb_class_subclass_add(super, klass); + } + RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super); + return super; +} + +#endif /* INTERNAL_CLASS_H */ diff --git a/ruby/internal/compar.h b/ruby/internal/compar.h new file mode 100644 index 000000000..5e336adaf --- /dev/null +++ b/ruby/internal/compar.h @@ -0,0 +1,49 @@ +#ifndef INTERNAL_COMPAR_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_COMPAR_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Comparable. + */ +#include "internal/vm.h" /* for rb_method_basic_definition_p */ + +#define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString) + +enum { + cmp_opt_Integer, + cmp_opt_String, + cmp_opt_Float, + cmp_optimizable_count +}; + +struct cmp_opt_data { + unsigned int opt_methods; + unsigned int opt_inited; +}; + +#define NEW_CMP_OPT_MEMO(type, value) \ + NEW_PARTIAL_MEMO_FOR(type, value, cmp_opt) +#define CMP_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(cmp_opt_,type)) +#define CMP_OPTIMIZABLE(data, type) \ + (((data).opt_inited & CMP_OPTIMIZABLE_BIT(type)) ? \ + ((data).opt_methods & CMP_OPTIMIZABLE_BIT(type)) : \ + (((data).opt_inited |= CMP_OPTIMIZABLE_BIT(type)), \ + rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \ + ((data).opt_methods |= CMP_OPTIMIZABLE_BIT(type)))) + +#define OPTIMIZED_CMP(a, b, data) \ + ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data, Integer)) ? \ + (((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \ + (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \ + rb_str_cmp(a, b) : \ + (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \ + rb_float_cmp(a, b) : \ + rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b)) + +/* compar.c */ +VALUE rb_invcmp(VALUE, VALUE); + +#endif /* INTERNAL_COMPAR_H */ diff --git a/ruby/internal/compile.h b/ruby/internal/compile.h new file mode 100644 index 000000000..d32c2233c --- /dev/null +++ b/ruby/internal/compile.h @@ -0,0 +1,35 @@ +#ifndef INTERNAL_COMPILE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_COMPILE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for the compiler. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "ruby/ruby.h" /* for rb_event_flag_t */ + +struct rb_iseq_struct; /* in vm_core.h */ + +/* compile.c */ +int rb_dvar_defined(ID, const struct rb_iseq_struct *); +int rb_local_defined(ID, const struct rb_iseq_struct *); +const char *rb_insns_name(int i); +VALUE rb_insns_name_array(void); +int rb_iseq_cdhash_cmp(VALUE val, VALUE lit); +st_index_t rb_iseq_cdhash_hash(VALUE a); + +/* iseq.c */ +int rb_vm_insn_addr2insn(const void *); +int rb_vm_insn_decode(const VALUE encoded); +extern bool ruby_vm_keep_script_lines; + +MJIT_SYMBOL_EXPORT_BEGIN +/* iseq.c (export) */ +rb_event_flag_t rb_iseq_event_flags(const struct rb_iseq_struct *iseq, size_t pos); +MJIT_SYMBOL_EXPORT_END + +#endif /* INTERNAL_COMPILE_H */ diff --git a/ruby/internal/compilers.h b/ruby/internal/compilers.h new file mode 100644 index 000000000..26c2f05cc --- /dev/null +++ b/ruby/internal/compilers.h @@ -0,0 +1,107 @@ +#ifndef INTERNAL_COMPILERS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_COMPILERS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header absorbing C compiler differences. + */ +#include "ruby/internal/compiler_since.h" +#include "ruby/internal/has/attribute.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/has/c_attribute.h" +#include "ruby/internal/has/declspec_attribute.h" +#include "ruby/internal/has/extension.h" +#include "ruby/internal/has/feature.h" +#include "ruby/internal/has/warning.h" +#include "ruby/backward/2/gcc_version_since.h" + +#define MSC_VERSION_SINCE(_) RBIMPL_COMPILER_SINCE(MSVC, (_) / 100, (_) % 100, 0) +#define MSC_VERSION_BEFORE(_) RBIMPL_COMPILER_BEFORE(MSVC, (_) / 100, (_) % 100, 0) + +#ifndef __has_attribute +# define __has_attribute(...) RBIMPL_HAS_ATTRIBUTE(__VA_ARGS__) +#endif + +#ifndef __has_c_attribute +# /* As of writing everything that lacks __has_c_attribute also completely +# * lacks C2x attributes as well. Might change in future? */ +# define __has_c_attribute(...) 0 +#endif + +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(...) RBIMPL_HAS_DECLSPEC_ATTRIBUTE(__VA_ARGS__) +#endif + +#ifndef __has_builtin +# define __has_builtin(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__) +#endif + +#ifndef __has_feature +# define __has_feature(...) RBIMPL_HAS_FEATURE(__VA_ARGS__) +#endif + +#ifndef __has_extension +# define __has_extension(...) RBIMPL_HAS_EXTENSION(__VA_ARGS__) +#endif + +#ifndef __has_warning +# define __has_warning(...) RBIMPL_HAS_WARNING(__VA_ARGS__) +#endif + +#ifndef __GNUC__ +# define __extension__ /* void */ +#endif + +#ifndef MAYBE_UNUSED +# define MAYBE_UNUSED(x) x +#endif + +#ifndef WARN_UNUSED_RESULT +# define WARN_UNUSED_RESULT(x) x +#endif + +#define RB_OBJ_BUILTIN_TYPE(obj) rb_obj_builtin_type(obj) +#define OBJ_BUILTIN_TYPE(obj) RB_OBJ_BUILTIN_TYPE(obj) +#ifdef __GNUC__ +#define rb_obj_builtin_type(obj) \ +__extension__({ \ + VALUE arg_obj = (obj); \ + RB_SPECIAL_CONST_P(arg_obj) ? -1 : \ + (int)RB_BUILTIN_TYPE(arg_obj); \ + }) +#else +# include "ruby/ruby.h" +static inline int +rb_obj_builtin_type(VALUE obj) +{ + return RB_SPECIAL_CONST_P(obj) ? -1 : + (int)RB_BUILTIN_TYPE(obj); +} +#endif + +/* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define FLEX_ARY_LEN /* VALUE ary[]; */ +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) +# define FLEX_ARY_LEN 0 /* VALUE ary[0]; */ +#else +# define FLEX_ARY_LEN 1 /* VALUE ary[1]; */ +#endif + +/* + * For declaring bitfields out of non-unsigned int types: + * struct date { + * BITFIELD(enum months, month, 4); + * ... + * }; + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define BITFIELD(type, name, size) type name : size +#else +# define BITFIELD(type, name, size) unsigned int name : size +#endif + +#endif /* INTERNAL_COMPILERS_H */ diff --git a/ruby/internal/complex.h b/ruby/internal/complex.h new file mode 100644 index 000000000..42151652b --- /dev/null +++ b/ruby/internal/complex.h @@ -0,0 +1,29 @@ +#ifndef INTERNAL_COMPLEX_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_COMPLEX_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Complex. + */ +#include "ruby/internal/value.h" /* for struct RBasic */ + +struct RComplex { + struct RBasic basic; + VALUE real; + VALUE imag; +}; + +#define RCOMPLEX(obj) ((struct RComplex *)(obj)) + +/* shortcut macro for internal only */ +#define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->real, (r)) +#define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->imag, (i)) + +/* complex.c */ +VALUE rb_dbl_complex_new_polar_pi(double abs, double ang); +st_index_t rb_complex_hash(VALUE comp); + +#endif /* INTERNAL_COMPLEX_H */ diff --git a/ruby/internal/cont.h b/ruby/internal/cont.h new file mode 100644 index 000000000..5ab120e9a --- /dev/null +++ b/ruby/internal/cont.h @@ -0,0 +1,24 @@ +#ifndef INTERNAL_CONT_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_CONT_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Fiber. + */ +#include "ruby/ruby.h" /* for VALUE */ + +struct rb_thread_struct; /* in vm_core.h */ +struct rb_fiber_struct; /* in cont.c */ + +/* cont.c */ +void rb_fiber_reset_root_local_storage(struct rb_thread_struct *); +void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE)); +void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber); + +VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber); +unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber); + +#endif /* INTERNAL_CONT_H */ diff --git a/ruby/internal/dir.h b/ruby/internal/dir.h new file mode 100644 index 000000000..0a4dc90ec --- /dev/null +++ b/ruby/internal/dir.h @@ -0,0 +1,16 @@ +#ifndef INTERNAL_DIR_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_DIR_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Dir. + */ +#include "ruby/ruby.h" /* for VALUE */ + +/* dir.c */ +VALUE rb_dir_getwd_ospath(void); + +#endif /* INTERNAL_DIR_H */ diff --git a/ruby/internal/enc.h b/ruby/internal/enc.h new file mode 100644 index 000000000..a005dc810 --- /dev/null +++ b/ruby/internal/enc.h @@ -0,0 +1,19 @@ +#ifndef INTERNAL_ENC_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ENC_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Encoding. + */ +#include "ruby/encoding.h" /* for rb_encoding */ + +/* us_ascii.c */ +extern rb_encoding OnigEncodingUS_ASCII; + +/* utf_8.c */ +extern rb_encoding OnigEncodingUTF_8; + +#endif /* INTERNAL_ENC_H */ diff --git a/ruby/internal/encoding.h b/ruby/internal/encoding.h new file mode 100644 index 000000000..c48cb24b0 --- /dev/null +++ b/ruby/internal/encoding.h @@ -0,0 +1,30 @@ +#ifndef INTERNAL_ENCODING_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ENCODING_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Encoding. + */ +#include "ruby/ruby.h" /* for ID */ +#include "ruby/encoding.h" /* for rb_encoding */ + +#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc)) + +/* encoding.c */ +ID rb_id_encoding(void); +rb_encoding *rb_enc_get_from_index(int index); +rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2); +int rb_encdb_replicate(const char *alias, const char *orig); +int rb_encdb_alias(const char *alias, const char *orig); +int rb_enc_autoload(rb_encoding *enc); +int rb_encdb_dummy(const char *name); +void rb_encdb_declare(const char *name); +void rb_enc_set_base(const char *name, const char *orig); +int rb_enc_set_dummy(int index); +void rb_encdb_set_unicode(int index); +PUREFUNC(int rb_data_is_encoding(VALUE obj)); + +#endif /* INTERNAL_ENCODING_H */ diff --git a/ruby/internal/enum.h b/ruby/internal/enum.h new file mode 100644 index 000000000..282464436 --- /dev/null +++ b/ruby/internal/enum.h @@ -0,0 +1,18 @@ +#ifndef INTERNAL_ENUM_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ENUM_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Enumerable. + */ +#include "ruby/ruby.h" /* for VALUE */ + +/* enum.c */ +extern VALUE rb_cArithSeq; +VALUE rb_f_send(int argc, VALUE *argv, VALUE recv); +VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary); + +#endif /* INTERNAL_ENUM_H */ diff --git a/ruby/internal/enumerator.h b/ruby/internal/enumerator.h new file mode 100644 index 000000000..e11a684c5 --- /dev/null +++ b/ruby/internal/enumerator.h @@ -0,0 +1,21 @@ +#ifndef INTERNAL_ENUMERATOR_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ENUMERATOR_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Enumerator. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/intern.h" /* for rb_enumerator_size_func */ + +RUBY_SYMBOL_EXPORT_BEGIN +/* enumerator.c (export) */ +VALUE 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); +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_ENUMERATOR_H */ diff --git a/ruby/internal/error.h b/ruby/internal/error.h new file mode 100644 index 000000000..11601858f --- /dev/null +++ b/ruby/internal/error.h @@ -0,0 +1,191 @@ +#ifndef INTERNAL_ERROR_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_ERROR_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Exception. + */ +#include "ruby/internal/config.h" +#include /* for va_list */ +#include "internal/string.h" /* for rb_fstring_cstr */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/encoding.h" /* for rb_encoding */ +#include "ruby/intern.h" /* for rb_exc_raise */ +#include "ruby/ruby.h" /* for enum ruby_value_type */ + +#ifdef Check_Type +# undef Check_Type /* in ruby/ruby.h */ +#endif + +#ifdef rb_raise_static +# undef rb_raise_static +# undef rb_sys_fail_path +# undef rb_syserr_fail_path +#endif + +#define rb_raise_static(e, m) \ + rb_raise_cstr_i((e), rb_str_new_static((m), rb_strlen_lit(m))) +#ifdef RUBY_FUNCTION_NAME_STRING +# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path) +# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path)) +# define rb_syserr_new_path(err, path) rb_syserr_new_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path)) +#else +# define rb_sys_fail_path(path) rb_sys_fail_str(path) +# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path)) +# define rb_syserr_new_path(err, path) rb_syserr_new_str((err), (path)) +#endif + +/* error.c */ +extern long rb_backtrace_length_limit; +extern VALUE rb_eEAGAIN; +extern VALUE rb_eEWOULDBLOCK; +extern VALUE rb_eEINPROGRESS; +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0) +void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args); +NORETURN(void rb_async_bug_errno(const char *,int)); +const char *rb_builtin_type_name(int t); +const char *rb_builtin_class_name(VALUE x); +PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3); +PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...), 2, 4); +#if RUBY_DEBUG +# include "ruby/version.h" +# define RUBY_VERSION_SINCE(major, minor) (RUBY_API_VERSION_CODE >= (major * 10000) + (minor) * 100) +# define RUBY_VERSION_BEFORE(major, minor) (RUBY_API_VERSION_CODE < (major * 10000) + (minor) * 100) +# if defined(RBIMPL_WARNING_PRAGMA0) +# define RBIMPL_TODO0(x) RBIMPL_WARNING_PRAGMA0(message(x)) +# elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +# define RBIMPL_TODO0(x) __pragma(message(x)) +# endif + +# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__) + +#define RUBY_VERSION_isdigit(c) ('0'<=(c)&&(c)<='9') +// upto 99 +#define RUBY_VERSION__number_len(v, ofs) \ + (!RUBY_VERSION_isdigit((v)[ofs]) ? \ + 0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? 1 : 2) +#define RUBY_VERSION__to_number(v, ofs) \ + (!RUBY_VERSION_isdigit((v)[ofs]) ? \ + 0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? \ + ((v)[ofs]-'0') : \ + (((v)[ofs]-'0')*10+(v)[(ofs)+1]-'0')) + +#define RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v) \ + (RUBY_VERSION__to_number(v, 0) * 10000 + \ + ((v)[RUBY_VERSION__number_len(v, 0)] == '.' ? \ + RUBY_VERSION__to_number(v, RUBY_VERSION__number_len(v, 0)+1) * 100 : 0)) +#define RUBY_VERSION_STRING_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v)) +#define RUBY_VERSION_STRING_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v)) + +# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) +RBIMPL_ATTR_FORCEINLINE() +static void +rb_deprecated_method_to_be_removed(const char *removal) + RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(removal[0]), "malformed version number", "error") + RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error") +{ +} +# else +RBIMPL_ATTR_ERROR(("deprecated")) +void rb_deprecated_method_to_be_removed(const char *); +# define rb_deprecated_method_to_be_removed(removal) \ + (sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_STRING_SINCE(removal))])!=1 ? \ + rb_deprecated_method_to_be_removed(removal) : \ + RBIMPL_ASSERT_NOTHING) +# endif +# define rb_warn_deprecated_to_remove_at(removal, ...) \ + (rb_deprecated_method_to_be_removed(#removal), \ + rb_warn_deprecated_to_remove(#removal, __VA_ARGS__)) +# endif +#endif +#ifndef rb_warn_deprecated_to_remove_at +# define rb_warn_deprecated_to_remove_at(removal, ...) \ + rb_warn_deprecated_to_remove(#removal, __VA_ARGS__) +#endif +#ifndef RUBY_VERSION_SINCE +# define RUBY_VERSION_SINCE(major, minor) 0 +#endif +#ifndef RUBY_VERSION_BEFORE +# define RUBY_VERSION_BEFORE(major, minor) 0 +#endif +#ifndef RBIMPL_TODO0 +# define RBIMPL_TODO0(x) +#endif +#define RBIMPL_TODO(message) RBIMPL_TODO0("TODO: " message) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0) +VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list); +PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3); +PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3); +PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4); +rb_warning_category_t rb_warning_category_from_name(VALUE category); +bool rb_warning_category_enabled_p(rb_warning_category_t category); +VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method); +VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv); +VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name); +PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2); +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) +NORETURN(void rb_vraise(VALUE, const char *, va_list)); +NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg)); +NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg)); +NORETURN(static inline void rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name)); +NORETURN(static inline void rb_name_err_raise(const char *mesg, VALUE recv, VALUE name)); +NORETURN(static inline void rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name)); +static inline void Check_Type(VALUE v, enum ruby_value_type t); +static inline bool rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type); +#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline + +RUBY_SYMBOL_EXPORT_BEGIN +/* error.c (export) */ +int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data); +#ifdef RUBY_FUNCTION_NAME_STRING +NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path)); +NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path)); +VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path); +#endif +RUBY_SYMBOL_EXPORT_END + +static inline void +rb_raise_cstr_i(VALUE etype, VALUE mesg) +{ + VALUE exc = rb_exc_new_str(etype, mesg); + rb_exc_raise(exc); +} + +static inline void +rb_raise_cstr(VALUE etype, const char *mesg) +{ + VALUE str = rb_str_new_cstr(mesg); + rb_raise_cstr_i(etype, str); +} + +static inline void +rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name) +{ + VALUE exc = rb_name_err_new(mesg, recv, name); + rb_exc_raise(exc); +} + +static inline void +rb_name_err_raise(const char *mesg, VALUE recv, VALUE name) +{ + VALUE str = rb_fstring_cstr(mesg); + rb_name_err_raise_str(str, recv, name); +} + +static inline void +rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name) +{ + VALUE exc = rb_key_err_new(mesg, recv, name); + rb_exc_raise(exc); +} + +static inline bool +rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type) +{ + return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type); +} + +#endif /* INTERNAL_ERROR_H */ diff --git a/ruby/internal/eval.h b/ruby/internal/eval.h new file mode 100644 index 000000000..73bb656d9 --- /dev/null +++ b/ruby/internal/eval.h @@ -0,0 +1,32 @@ +#ifndef INTERNAL_EVAL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_EVAL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for the evaluator. + * @note There also is eval_intern.h, which is evaluator's internal + * header (related to this file, but not the same role). + */ +#include "ruby/ruby.h" /* for ID */ + +#define id_signo ruby_static_id_signo +#define id_status ruby_static_id_status + +/* eval.c */ +extern ID ruby_static_id_signo; +extern ID ruby_static_id_status; +VALUE rb_refinement_module_get_refined_class(VALUE module); +void rb_class_modify_check(VALUE); +NORETURN(VALUE rb_f_raise(int argc, VALUE *argv)); + +/* eval_error.c */ +VALUE rb_get_backtrace(VALUE info); + +/* eval_jump.c */ +void rb_call_end_proc(VALUE data); +void rb_mark_end_proc(void); + +#endif /* INTERNAL_EVAL_H */ diff --git a/ruby/internal/file.h b/ruby/internal/file.h new file mode 100644 index 000000000..9c192ff4d --- /dev/null +++ b/ruby/internal/file.h @@ -0,0 +1,38 @@ +#ifndef INTERNAL_FILE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_FILE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for File. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/encoding.h" /* for rb_encodinng */ + +/* file.c */ +extern const char ruby_null_device[]; +VALUE rb_home_dir_of(VALUE user, VALUE result); +VALUE rb_default_home_dir(VALUE result); +VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); +VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *origenc); +void rb_file_const(const char*, VALUE); +int rb_file_load_ok(const char *); +VALUE rb_file_expand_path_fast(VALUE, VALUE); +VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); +VALUE rb_get_path_check_to_string(VALUE); +VALUE rb_get_path_check_convert(VALUE); +int ruby_is_fd_loadable(int fd); + +RUBY_SYMBOL_EXPORT_BEGIN +/* file.c (export) */ +#ifdef HAVE_READLINK +VALUE rb_readlink(VALUE path, rb_encoding *enc); +#endif +#ifdef __APPLE__ +VALUE rb_str_normalize_ospath(const char *ptr, long len); +#endif +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_FILE_H */ diff --git a/ruby/internal/fixnum.h b/ruby/internal/fixnum.h new file mode 100644 index 000000000..cdb60ee1f --- /dev/null +++ b/ruby/internal/fixnum.h @@ -0,0 +1,184 @@ +#ifndef INTERNAL_FIXNUM_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_FIXNUM_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Fixnums. + */ +#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */ +#include /* for CHAR_BIT */ +#include "internal/compilers.h" /* for __has_builtin */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/intern.h" /* for rb_big_mul */ +#include "ruby/ruby.h" /* for RB_FIXABLE */ + +#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG +# define DLONG LONG_LONG +# define DL2NUM(x) LL2NUM(x) +#elif defined(HAVE_INT128_T) +# define DLONG int128_t +# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x)) +VALUE rb_int128t2big(int128_t n); /* in bignum.c */ +#endif + +static inline long rb_overflowed_fix_to_int(long x); +static inline VALUE rb_fix_plus_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_minus_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_mul_fix(VALUE x, VALUE y); +static inline void rb_fix_divmod_fix(VALUE x, VALUE y, VALUE *divp, VALUE *modp); +static inline VALUE rb_fix_div_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_mod_fix(VALUE x, VALUE y); +static inline bool FIXNUM_POSITIVE_P(VALUE num); +static inline bool FIXNUM_NEGATIVE_P(VALUE num); +static inline bool FIXNUM_ZERO_P(VALUE num); + +static inline long +rb_overflowed_fix_to_int(long x) +{ + return (long)((unsigned long)(x >> 1) ^ (1LU << (SIZEOF_LONG * CHAR_BIT - 1))); +} + +static inline VALUE +rb_fix_plus_fix(VALUE x, VALUE y) +{ +#if !__has_builtin(__builtin_add_overflow) + long lz = FIX2LONG(x) + FIX2LONG(y); + return LONG2NUM(lz); +#else + long lz; + /* NOTE + * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))` + + = `((lx*2+1)/2 + (ly*2+1)/2)*2+1` + + = `lx*2 + ly*2 + 1` + + = `(lx*2+1) + (ly*2+1) - 1` + + = `x + y - 1` + * (2) Fixnum's LSB is always 1. + * It means you can always run `x - 1` without overflow. + * (3) Of course `z = x + (y-1)` may overflow. + * At that time true value is + * * positive: 0b0 1xxx...1, and z = 0b1xxx...1 + * * negative: 0b1 0xxx...1, and z = 0b0xxx...1 + * To convert this true value to long, + * (a) Use arithmetic shift + * * positive: 0b11xxx... + * * negative: 0b00xxx... + * (b) invert MSB + * * positive: 0b01xxx... + * * negative: 0b10xxx... + */ + if (__builtin_add_overflow((long)x, (long)y-1, &lz)) { + return rb_int2big(rb_overflowed_fix_to_int(lz)); + } + else { + return (VALUE)lz; + } +#endif +} + +static inline VALUE +rb_fix_minus_fix(VALUE x, VALUE y) +{ +#if !__has_builtin(__builtin_sub_overflow) + long lz = FIX2LONG(x) - FIX2LONG(y); + return LONG2NUM(lz); +#else + long lz; + if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) { + return rb_int2big(rb_overflowed_fix_to_int(lz)); + } + else { + return (VALUE)lz; + } +#endif +} + +/* arguments must be Fixnum */ +static inline VALUE +rb_fix_mul_fix(VALUE x, VALUE y) +{ + long lx = FIX2LONG(x); + long ly = FIX2LONG(y); +#ifdef DLONG + return DL2NUM((DLONG)lx * (DLONG)ly); +#else + if (MUL_OVERFLOW_FIXNUM_P(lx, ly)) { + return rb_big_mul(rb_int2big(lx), rb_int2big(ly)); + } + else { + return LONG2FIX(lx * ly); + } +#endif +} + +/* + * This behaves different from C99 for negative arguments. + * Note that div may overflow fixnum. + */ +static inline void +rb_fix_divmod_fix(VALUE a, VALUE b, VALUE *divp, VALUE *modp) +{ + /* assume / and % comply C99. + * ldiv(3) won't be inlined by GCC and clang. + * I expect / and % are compiled as single idiv. + */ + long x = FIX2LONG(a); + long y = FIX2LONG(b); + long div, mod; + if (x == FIXNUM_MIN && y == -1) { + if (divp) *divp = LONG2NUM(-FIXNUM_MIN); + if (modp) *modp = LONG2FIX(0); + return; + } + div = x / y; + mod = x % y; + if (y > 0 ? mod < 0 : mod > 0) { + mod += y; + div -= 1; + } + if (divp) *divp = LONG2FIX(div); + if (modp) *modp = LONG2FIX(mod); +} + +/* div() for Ruby + * This behaves different from C99 for negative arguments. + */ +static inline VALUE +rb_fix_div_fix(VALUE x, VALUE y) +{ + VALUE div; + rb_fix_divmod_fix(x, y, &div, NULL); + return div; +} + +/* mod() for Ruby + * This behaves different from C99 for negative arguments. + */ +static inline VALUE +rb_fix_mod_fix(VALUE x, VALUE y) +{ + VALUE mod; + rb_fix_divmod_fix(x, y, NULL, &mod); + return mod; +} + +static inline bool +FIXNUM_POSITIVE_P(VALUE num) +{ + return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0); +} + +static inline bool +FIXNUM_NEGATIVE_P(VALUE num) +{ + return (SIGNED_VALUE)num < 0; +} + +static inline bool +FIXNUM_ZERO_P(VALUE num) +{ + return num == INT2FIX(0); +} +#endif /* INTERNAL_FIXNUM_H */ diff --git a/ruby/internal/gc.h b/ruby/internal/gc.h new file mode 100644 index 000000000..baf4f36a1 --- /dev/null +++ b/ruby/internal/gc.h @@ -0,0 +1,186 @@ +#ifndef INTERNAL_GC_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_GC_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for GC. + */ +#include "ruby/internal/config.h" + +#include /* for size_t */ + +#include "internal/compilers.h" /* for __has_attribute */ +#include "ruby/ruby.h" /* for rb_event_flag_t */ + +struct rb_execution_context_struct; /* in vm_core.h */ +struct rb_objspace; /* in vm_core.h */ + +#ifdef NEWOBJ_OF +# undef NEWOBJ_OF +# undef RB_NEWOBJ_OF +# undef RB_OBJ_WRITE +#endif + +#define RVALUE_SIZE (sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX])) + +#define RB_RVARGC_NEWOBJ_OF(var, T, c, f, s) \ + T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ + rb_wb_protected_newobj_of((c), (f) & ~FL_WB_PROTECTED, s) : \ + rb_wb_unprotected_newobj_of((c), (f), s)) + +#define RB_RVARGC_EC_NEWOBJ_OF(ec, var, T, c, f, s) \ + T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ + rb_ec_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, s) : \ + rb_wb_unprotected_newobj_of((c), (f), s)) + +/* optimized version of NEWOBJ() */ +#define RB_NEWOBJ_OF(var, T, c, f) RB_RVARGC_NEWOBJ_OF(var, T, c, f, RVALUE_SIZE) + +#define RB_EC_NEWOBJ_OF(ec, var, T, c, f) RB_RVARGC_EC_NEWOBJ_OF(ec, var, T, c, f, RVALUE_SIZE) + +#define NEWOBJ_OF(var, T, c, f) RB_NEWOBJ_OF((var), T, (c), (f)) +#define RVARGC_NEWOBJ_OF(var, T, c, f, s) RB_RVARGC_NEWOBJ_OF((var), T, (c), (f), (s)) +#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */ + +#ifndef USE_UNALIGNED_MEMBER_ACCESS +# define UNALIGNED_MEMBER_ACCESS(expr) (expr) +#elif ! USE_UNALIGNED_MEMBER_ACCESS +# define UNALIGNED_MEMBER_ACCESS(expr) (expr) +#elif ! (__has_warning("-Waddress-of-packed-member") || GCC_VERSION_SINCE(9, 0, 0)) +# define UNALIGNED_MEMBER_ACCESS(expr) (expr) +#else +# include "internal/warnings.h" +# define UNALIGNED_MEMBER_ACCESS(expr) __extension__({ \ + COMPILER_WARNING_PUSH; \ + COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \ + __typeof__(expr) unaligned_member_access_result = (expr); \ + COMPILER_WARNING_POP; \ + unaligned_member_access_result; \ +}) +#endif + +#define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem) +#define RB_OBJ_WRITE(a, slot, b) \ + rb_obj_write((VALUE)(a), UNALIGNED_MEMBER_ACCESS((VALUE *)(slot)), \ + (VALUE)(b), __FILE__, __LINE__) + +#if USE_RVARGC +# define SIZE_POOL_COUNT 4 +#else +# define SIZE_POOL_COUNT 1 +#endif + +typedef struct ractor_newobj_size_pool_cache { + struct RVALUE *freelist; + struct heap_page *using_page; +} rb_ractor_newobj_size_pool_cache_t; + +typedef struct ractor_newobj_cache { + rb_ractor_newobj_size_pool_cache_t size_pool_caches[SIZE_POOL_COUNT]; +} rb_ractor_newobj_cache_t; + +/* gc.c */ +extern VALUE *ruby_initial_gc_stress_ptr; +extern int ruby_disable_gc; +RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size); +void ruby_mimfree(void *ptr); +void rb_objspace_set_event_hook(const rb_event_flag_t event); +VALUE rb_objspace_gc_enable(struct rb_objspace *); +VALUE rb_objspace_gc_disable(struct rb_objspace *); +void ruby_gc_set_params(void); +void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj); +#if __has_attribute(alloc_align) +__attribute__((__alloc_align__(1))) +#endif +RUBY_ATTR_MALLOC void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_ALLOC_SIZE((2)); +size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */ +size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */ +RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add(size_t, size_t, size_t); +void *rb_xrealloc_mul_add(const void *, size_t, size_t, size_t); +RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add_mul(size_t, size_t, size_t, size_t); +RUBY_ATTR_MALLOC void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t); +static inline void *ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); +static inline void *ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3)); +static inline void ruby_sized_xfree_inlined(void *ptr, size_t size); +VALUE rb_class_allocate_instance(VALUE klass); +void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache); +size_t rb_gc_obj_slot_size(VALUE obj); +bool rb_gc_size_allocatable_p(size_t size); +int rb_objspace_garbage_object_p(VALUE obj); + +RUBY_SYMBOL_EXPORT_BEGIN +/* gc.c (export) */ +const char *rb_objspace_data_type_name(VALUE obj); +VALUE rb_wb_protected_newobj_of(VALUE, VALUE, size_t); +VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, size_t); +VALUE rb_ec_wb_protected_newobj_of(struct rb_execution_context_struct *ec, VALUE klass, VALUE flags, size_t); +size_t rb_obj_memsize_of(VALUE); +void rb_gc_verify_internal_consistency(void); +size_t rb_obj_gc_flags(VALUE, ID[], size_t); +void rb_gc_mark_values(long n, const VALUE *values); +void rb_gc_mark_vm_stack_values(long n, const VALUE *values); +void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); +void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3)); +void ruby_sized_xfree(void *x, size_t size); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +int rb_ec_stack_check(struct rb_execution_context_struct *ec); +void rb_gc_writebarrier_remember(VALUE obj); +const char *rb_obj_info(VALUE obj); +MJIT_SYMBOL_EXPORT_END + +#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32) + +static inline void * +ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) +{ + return ruby_xrealloc(ptr, new_size); +} + +static inline void * +ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) +{ + return ruby_xrealloc2(ptr, new_count, elemsiz); +} + +static inline void +ruby_sized_xfree_inlined(void *ptr, size_t size) +{ + ruby_xfree(ptr); +} + +# define SIZED_REALLOC_N(x, y, z, w) REALLOC_N(x, y, z) + +#else + +static inline void * +ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) +{ + return ruby_sized_xrealloc(ptr, new_size, old_size); +} + +static inline void * +ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) +{ + return ruby_sized_xrealloc2(ptr, new_count, elemsiz, old_count); +} + +static inline void +ruby_sized_xfree_inlined(void *ptr, size_t size) +{ + ruby_sized_xfree(ptr, size); +} + +# define SIZED_REALLOC_N(v, T, m, n) \ + ((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n))) + +#endif /* HAVE_MALLOC_USABLE_SIZE */ + +#define ruby_sized_xrealloc ruby_sized_xrealloc_inlined +#define ruby_sized_xrealloc2 ruby_sized_xrealloc2_inlined +#define ruby_sized_xfree ruby_sized_xfree_inlined +#endif /* INTERNAL_GC_H */ diff --git a/ruby/internal/hash.h b/ruby/internal/hash.h new file mode 100644 index 000000000..657e5eff3 --- /dev/null +++ b/ruby/internal/hash.h @@ -0,0 +1,243 @@ +#ifndef INTERNAL_HASH_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_HASH_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Hash. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for struct RBasic */ +#include "ruby/st.h" /* for struct st_table */ + +#define RHASH_AR_TABLE_MAX_SIZE SIZEOF_VALUE + +struct ar_table_struct; +typedef unsigned char ar_hint_t; + +enum ruby_rhash_flags { + RHASH_PASS_AS_KEYWORDS = FL_USER1, /* FL 1 */ + RHASH_PROC_DEFAULT = FL_USER2, /* FL 2 */ + RHASH_ST_TABLE_FLAG = FL_USER3, /* FL 3 */ + RHASH_AR_TABLE_SIZE_MASK = (FL_USER4|FL_USER5|FL_USER6|FL_USER7), /* FL 4..7 */ + RHASH_AR_TABLE_SIZE_SHIFT = (FL_USHIFT+4), + RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */ + RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8), + +#if USE_TRANSIENT_HEAP + RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */ +#endif + + // we can not put it in "enum" because it can exceed "int" range. +#define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \ + FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19) + + RHASH_LEV_SHIFT = (FL_USHIFT + 13), + RHASH_LEV_MAX = 127, /* 7 bits */ +}; + +struct RHash { + struct RBasic basic; + union { + st_table *st; + struct ar_table_struct *ar; /* possibly 0 */ + } as; + const VALUE ifnone; + union { + ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE]; + VALUE word; + } ar_hint; +}; + +#define RHASH(obj) ((struct RHash *)(obj)) + +#ifdef RHASH_IFNONE +# undef RHASH_IFNONE +#endif + +#ifdef RHASH_SIZE +# undef RHASH_SIZE +#endif + +#ifdef RHASH_EMPTY_P +# undef RHASH_EMPTY_P +#endif + +/* hash.c */ +void rb_hash_st_table_set(VALUE hash, st_table *st); +VALUE rb_hash_default_value(VALUE hash, VALUE key); +VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc); +long rb_dbl_long_hash(double d); +st_table *rb_init_identtable(void); +VALUE rb_to_hash_type(VALUE obj); +VALUE rb_hash_key_str(VALUE); +VALUE rb_hash_values(VALUE hash); +VALUE rb_hash_rehash(VALUE hash); +int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val); +VALUE rb_hash_set_pair(VALUE hash, VALUE pair); +int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval); +int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg); +int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg); +extern st_table *rb_hash_st_table(VALUE hash); +VALUE rb_ident_hash_new_with_size(st_index_t size); + +static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h); +static inline VALUE RHASH_IFNONE(VALUE h); +static inline size_t RHASH_SIZE(VALUE h); +static inline bool RHASH_EMPTY_P(VALUE h); +static inline bool RHASH_AR_TABLE_P(VALUE h); +static inline bool RHASH_ST_TABLE_P(VALUE h); +static inline struct ar_table_struct *RHASH_AR_TABLE(VALUE h); +static inline st_table *RHASH_ST_TABLE(VALUE h); +static inline size_t RHASH_ST_SIZE(VALUE h); +static inline void RHASH_ST_CLEAR(VALUE h); +static inline bool RHASH_TRANSIENT_P(VALUE h); +static inline void RHASH_SET_TRANSIENT_FLAG(VALUE h); +static inline void RHASH_UNSET_TRANSIENT_FLAG(VALUE h); + +RUBY_SYMBOL_EXPORT_BEGIN +/* hash.c (export) */ +VALUE rb_hash_delete_entry(VALUE hash, VALUE key); +VALUE rb_ident_hash_new(void); +int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_hash_new_with_size(st_index_t size); +VALUE rb_hash_resurrect(VALUE hash); +int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval); +VALUE rb_hash_keys(VALUE hash); +VALUE rb_hash_has_key(VALUE hash, VALUE key); +VALUE rb_hash_compare_by_id_p(VALUE hash); + +st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line); +#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__) +MJIT_SYMBOL_EXPORT_END + +VALUE rb_hash_compare_by_id(VALUE hash); + +#if 0 /* for debug */ + +static inline bool +RHASH_AR_TABLE_P(VALUE h) +{ + extern int rb_hash_ar_table_p(VALUE hash); + return rb_hash_ar_table_p(h) +} + +static inline struct ar_table_struct * +RHASH_AR_TABLE(VALUE h) +{ + extern struct ar_table_struct *rb_hash_ar_table(VALUE hash); + return rb_hash_ar_table(h) +} + +static inline st_table * +RHASH_ST_TABLE(VALUE h) +{ + return rb_hash_st_table(h) +} + +#else + +static inline bool +RHASH_AR_TABLE_P(VALUE h) +{ + return ! FL_TEST_RAW(h, RHASH_ST_TABLE_FLAG); +} + +static inline struct ar_table_struct * +RHASH_AR_TABLE(VALUE h) +{ + return RHASH(h)->as.ar; +} + +static inline st_table * +RHASH_ST_TABLE(VALUE h) +{ + return RHASH(h)->as.st; +} + +#endif + +static inline VALUE +RHASH_IFNONE(VALUE h) +{ + return RHASH(h)->ifnone; +} + +static inline size_t +RHASH_SIZE(VALUE h) +{ + if (RHASH_AR_TABLE_P(h)) { + return RHASH_AR_TABLE_SIZE_RAW(h); + } + else { + return RHASH_ST_SIZE(h); + } +} + +static inline bool +RHASH_EMPTY_P(VALUE h) +{ + return RHASH_SIZE(h) == 0; +} + +static inline bool +RHASH_ST_TABLE_P(VALUE h) +{ + return ! RHASH_AR_TABLE_P(h); +} + +static inline size_t +RHASH_ST_SIZE(VALUE h) +{ + return RHASH_ST_TABLE(h)->num_entries; +} + +static inline void +RHASH_ST_CLEAR(VALUE h) +{ + FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG); + RHASH(h)->as.ar = NULL; +} + +static inline unsigned +RHASH_AR_TABLE_SIZE_RAW(VALUE h) +{ + VALUE ret = FL_TEST_RAW(h, RHASH_AR_TABLE_SIZE_MASK); + ret >>= RHASH_AR_TABLE_SIZE_SHIFT; + return (unsigned)ret; +} + +static inline bool +RHASH_TRANSIENT_P(VALUE h) +{ +#if USE_TRANSIENT_HEAP + return FL_TEST_RAW(h, RHASH_TRANSIENT_FLAG); +#else + return false; +#endif +} + +static inline void +RHASH_SET_TRANSIENT_FLAG(VALUE h) +{ +#if USE_TRANSIENT_HEAP + FL_SET_RAW(h, RHASH_TRANSIENT_FLAG); +#endif +} + +static inline void +RHASH_UNSET_TRANSIENT_FLAG(VALUE h) +{ +#if USE_TRANSIENT_HEAP + FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG); +#endif +} + +#endif /* INTERNAL_HASH_H */ diff --git a/ruby/internal/imemo.h b/ruby/internal/imemo.h new file mode 100644 index 000000000..ea36c4514 --- /dev/null +++ b/ruby/internal/imemo.h @@ -0,0 +1,243 @@ +#ifndef INTERNAL_IMEMO_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_IMEMO_H +/** + * @author Ruby developers + * @copyright 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. + * @brief IMEMO: Internal memo object. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "internal/array.h" /* for rb_ary_tmp_new_fill */ +#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for rb_block_call_func_t */ + +#ifndef IMEMO_DEBUG +# define IMEMO_DEBUG 0 +#endif + +#define IMEMO_MASK 0x0f + +/* FL_USER0 to FL_USER3 is for type */ +#define IMEMO_FL_USHIFT (FL_USHIFT + 4) +#define IMEMO_FL_USER0 FL_USER4 +#define IMEMO_FL_USER1 FL_USER5 +#define IMEMO_FL_USER2 FL_USER6 +#define IMEMO_FL_USER3 FL_USER7 +#define IMEMO_FL_USER4 FL_USER8 +#define IMEMO_FL_USER5 FL_USER9 + +enum imemo_type { + imemo_env = 0, + imemo_cref = 1, /*!< class reference */ + imemo_svar = 2, /*!< special variable */ + imemo_throw_data = 3, + imemo_ifunc = 4, /*!< iterator function */ + imemo_memo = 5, + imemo_ment = 6, + imemo_iseq = 7, + imemo_tmpbuf = 8, + imemo_ast = 9, + imemo_parser_strterm = 10, + imemo_callinfo = 11, + imemo_callcache = 12, + imemo_constcache = 13, +}; + +/* CREF (Class REFerence) is defined in method.h */ + +/*! SVAR (Special VARiable) */ +struct vm_svar { + VALUE flags; + const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ + const VALUE lastline; + const VALUE backref; + const VALUE others; +}; + +/*! THROW_DATA */ +struct vm_throw_data { + VALUE flags; + VALUE reserved; + const VALUE throw_obj; + const struct rb_control_frame_struct *catch_frame; + int throw_state; +}; + +#define THROW_DATA_CONSUMED IMEMO_FL_USER0 + +/* IFUNC (Internal FUNCtion) */ + +struct vm_ifunc_argc { +#if SIZEOF_INT * 2 > SIZEOF_VALUE + signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2; + signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2; +#else + int min, max; +#endif +}; + +/*! IFUNC (Internal FUNCtion) */ +struct vm_ifunc { + VALUE flags; + VALUE reserved; + rb_block_call_func_t func; + const void *data; + struct vm_ifunc_argc argc; +}; + +struct rb_imemo_tmpbuf_struct { + VALUE flags; + VALUE reserved; + VALUE *ptr; /* malloc'ed buffer */ + struct rb_imemo_tmpbuf_struct *next; /* next imemo */ + size_t cnt; /* buffer size in VALUE */ +}; + +/*! MEMO + * + * @see imemo_type + * */ +struct MEMO { + VALUE flags; + VALUE reserved; + const VALUE v1; + const VALUE v2; + union { + long cnt; + long state; + const VALUE value; + void (*func)(void); + } u3; +}; + +/* ment is in method.h */ + +#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err) +#define MEMO_CAST(m) ((struct MEMO *)(m)) +#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) +#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value)) +#define NEW_MEMO_FOR(type, value) \ + ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) +#define NEW_PARTIAL_MEMO_FOR(type, value, member) \ + ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \ + rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \ + MEMO_FOR(type, value)) + +typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t; +VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt); +struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc); +void rb_strterm_mark(VALUE obj); +static inline enum imemo_type imemo_type(VALUE imemo); +static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type); +static inline bool imemo_throw_data_p(VALUE imemo); +static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data); +static inline VALUE rb_imemo_tmpbuf_auto_free_pointer(void); +static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v); +static inline void *rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr); +static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str); +static inline void MEMO_V1_SET(struct MEMO *m, VALUE v); +static inline void MEMO_V2_SET(struct MEMO *m, VALUE v); + +RUBY_SYMBOL_EXPORT_BEGIN +#if IMEMO_DEBUG +VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line); +#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__) +#else +VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +#endif +const char *rb_imemo_name(enum imemo_type type); +RUBY_SYMBOL_EXPORT_END + +static inline enum imemo_type +imemo_type(VALUE imemo) +{ + return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK; +} + +static inline int +imemo_type_p(VALUE imemo, enum imemo_type imemo_type) +{ + if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) { + /* fixed at compile time if imemo_type is given. */ + const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK; + const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO; + /* fixed at runtime. */ + return expected_type == (RBASIC(imemo)->flags & mask); + } + else { + return 0; + } +} + +#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)v, t) + +static inline bool +imemo_throw_data_p(VALUE imemo) +{ + return RB_TYPE_P(imemo, T_IMEMO); +} + +static inline struct vm_ifunc * +rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data) +{ + return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS); +} + +static inline VALUE +rb_imemo_tmpbuf_auto_free_pointer(void) +{ + return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0); +} + +static inline void * +RB_IMEMO_TMPBUF_PTR(VALUE v) +{ + const struct rb_imemo_tmpbuf_struct *p = (const void *)v; + return p->ptr; +} + +static inline void * +rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr) +{ + return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr; +} + +static inline VALUE +rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str) +{ + const void *src; + VALUE imemo; + rb_imemo_tmpbuf_t *tmpbuf; + void *dst; + size_t len; + + SafeStringValue(str); + /* create tmpbuf to keep the pointer before xmalloc */ + imemo = rb_imemo_tmpbuf_auto_free_pointer(); + tmpbuf = (rb_imemo_tmpbuf_t *)imemo; + len = RSTRING_LEN(str); + src = RSTRING_PTR(str); + dst = ruby_xmalloc(len); + memcpy(dst, src, len); + tmpbuf->ptr = dst; + return imemo; +} + +static inline void +MEMO_V1_SET(struct MEMO *m, VALUE v) +{ + RB_OBJ_WRITE(m, &m->v1, v); +} + +static inline void +MEMO_V2_SET(struct MEMO *m, VALUE v) +{ + RB_OBJ_WRITE(m, &m->v2, v); +} + +#endif /* INTERNAL_IMEMO_H */ diff --git a/ruby/internal/inits.h b/ruby/internal/inits.h new file mode 100644 index 000000000..03e180f77 --- /dev/null +++ b/ruby/internal/inits.h @@ -0,0 +1,50 @@ +#ifndef INTERNAL_INITS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_INITS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header aggregating init functions. + */ + +/* class.c */ +void Init_class_hierarchy(void); + +/* dmyext.c */ +void Init_enc(void); +void Init_ext(void); + +/* file.c */ +void Init_File(void); + +/* gc.c */ +void Init_heap(void); + +/* localeinit.c */ +int Init_enc_set_filesystem_encoding(void); + +/* newline.c */ +void Init_newline(void); + +/* vm.c */ +void Init_BareVM(void); +void Init_vm_objects(void); + +/* vm_backtrace.c */ +void Init_vm_backtrace(void); + +/* vm_eval.c */ +void Init_vm_eval(void); + +/* vm_insnhelper.c */ +void Init_vm_stack_canary(void); + +/* vm_method.c */ +void Init_eval_method(void); + +/* inits.c */ +void rb_call_inits(void); + +#endif /* INTERNAL_INITS_H */ diff --git a/ruby/internal/io.h b/ruby/internal/io.h new file mode 100644 index 000000000..b5f15499d --- /dev/null +++ b/ruby/internal/io.h @@ -0,0 +1,38 @@ +#ifndef INTERNAL_IO_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_IO_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for IO. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/io.h" /* for rb_io_t */ + +/* io.c */ +void ruby_set_inplace_mode(const char *); +void rb_stdio_set_default_encoding(void); +VALUE rb_io_flush_raw(VALUE, int); +size_t rb_io_memsize(const rb_io_t *); +int rb_stderr_tty_p(void); +void rb_io_fptr_finalize_internal(void *ptr); +#ifdef rb_io_fptr_finalize +# undef rb_io_fptr_finalize +#endif +#define rb_io_fptr_finalize rb_io_fptr_finalize_internal +VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt); + +VALUE rb_io_prep_stdin(void); +VALUE rb_io_prep_stdout(void); +VALUE rb_io_prep_stderr(void); + +RUBY_SYMBOL_EXPORT_BEGIN +/* io.c (export) */ +void rb_maygvl_fd_fix_cloexec(int fd); +int rb_gc_for_fd(int err); +void rb_write_error_str(VALUE mesg); +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_IO_H */ diff --git a/ruby/internal/load.h b/ruby/internal/load.h new file mode 100644 index 000000000..d4c0bb91b --- /dev/null +++ b/ruby/internal/load.h @@ -0,0 +1,18 @@ +#ifndef INTERNAL_LOAD_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_LOAD_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for require. + */ +#include "ruby/ruby.h" /* for VALUE */ + +/* load.c */ +VALUE rb_get_expanded_load_path(void); +int rb_require_internal(VALUE fname); +NORETURN(void rb_load_fail(VALUE, const char*)); + +#endif /* INTERNAL_LOAD_H */ diff --git a/ruby/internal/loadpath.h b/ruby/internal/loadpath.h new file mode 100644 index 000000000..b3a85e7b4 --- /dev/null +++ b/ruby/internal/loadpath.h @@ -0,0 +1,16 @@ +#ifndef INTERNAL_LOADPATH_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_LOADPATH_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for $LOAD_PATH. + */ + +/* loadpath.c */ +extern const char ruby_exec_prefix[]; +extern const char ruby_initial_load_paths[]; + +#endif /* INTERNAL_LOADPATH_H */ diff --git a/ruby/internal/math.h b/ruby/internal/math.h new file mode 100644 index 000000000..08f852ffc --- /dev/null +++ b/ruby/internal/math.h @@ -0,0 +1,23 @@ +#ifndef INTERNAL_MATH_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_MATH_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Math. + */ +#include "ruby/ruby.h" /* for VALUE */ + +/* math.c */ +VALUE rb_math_atan2(VALUE, VALUE); +VALUE rb_math_cos(VALUE); +VALUE rb_math_cosh(VALUE); +VALUE rb_math_exp(VALUE); +VALUE rb_math_hypot(VALUE, VALUE); +VALUE rb_math_log(int argc, const VALUE *argv); +VALUE rb_math_sin(VALUE); +VALUE rb_math_sinh(VALUE); + +#endif /* INTERNAL_MATH_H */ diff --git a/ruby/internal/missing.h b/ruby/internal/missing.h new file mode 100644 index 000000000..c0992a151 --- /dev/null +++ b/ruby/internal/missing.h @@ -0,0 +1,18 @@ +#ifndef INTERNAL_MISSING_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_MISSING_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header corresponding missing. + */ +#include "ruby/internal/config.h" /* for HAVE_SETPROCTITLE */ + +/* missing/setproctitle.c */ +#ifndef HAVE_SETPROCTITLE +extern void ruby_init_setproctitle(int argc, char *argv[]); +#endif + +#endif /* INTERNAL_MISSING_H */ diff --git a/ruby/internal/numeric.h b/ruby/internal/numeric.h new file mode 100644 index 000000000..19069cb3b --- /dev/null +++ b/ruby/internal/numeric.h @@ -0,0 +1,271 @@ +#ifndef INTERNAL_NUMERIC_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_NUMERIC_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Numeric. + */ +#include "internal/bignum.h" /* for BIGNUM_POSITIVE_P */ +#include "internal/bits.h" /* for RUBY_BIT_ROTL */ +#include "internal/fixnum.h" /* for FIXNUM_POSITIVE_P */ +#include "internal/vm.h" /* for rb_method_basic_definition_p */ +#include "ruby/intern.h" /* for rb_cmperr */ +#include "ruby/ruby.h" /* for USE_FLONUM */ + +#define ROUND_TO(mode, even, up, down) \ + ((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \ + (mode) == RUBY_NUM_ROUND_HALF_UP ? up : down) +#define ROUND_FUNC(mode, name) \ + ROUND_TO(mode, name##_half_even, name##_half_up, name##_half_down) +#define ROUND_CALL(mode, name, args) \ + ROUND_TO(mode, name##_half_even args, \ + name##_half_up args, name##_half_down args) + +#ifndef ROUND_DEFAULT +# define ROUND_DEFAULT RUBY_NUM_ROUND_HALF_UP +#endif + +enum ruby_num_rounding_mode { + RUBY_NUM_ROUND_HALF_UP, + RUBY_NUM_ROUND_HALF_EVEN, + RUBY_NUM_ROUND_HALF_DOWN, + RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT, +}; + +#if SIZEOF_DOUBLE <= SIZEOF_VALUE +typedef double rb_float_value_type; +#else +typedef struct { + VALUE values[(SIZEOF_DOUBLE + SIZEOF_VALUE - 1) / SIZEOF_VALUE]; + /* roomof() needs internal.h, and the order of some macros may matter */ +} rb_float_value_type; +#endif + +struct RFloat { + struct RBasic basic; + rb_float_value_type float_value; +}; + +#define RFLOAT(obj) ((struct RFloat *)(obj)) + +/* numeric.c */ +int rb_num_to_uint(VALUE val, unsigned int *ret); +VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl); +double ruby_float_step_size(double beg, double end, double unit, int excl); +int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless); +int rb_num_negative_p(VALUE); +VALUE rb_int_succ(VALUE num); +VALUE rb_float_uminus(VALUE num); +VALUE rb_int_plus(VALUE x, VALUE y); +VALUE rb_float_plus(VALUE x, VALUE y); +VALUE rb_int_minus(VALUE x, VALUE y); +VALUE rb_float_minus(VALUE x, VALUE y); +VALUE rb_int_mul(VALUE x, VALUE y); +VALUE rb_float_mul(VALUE x, VALUE y); +VALUE rb_float_div(VALUE x, VALUE y); +VALUE rb_int_idiv(VALUE x, VALUE y); +VALUE rb_int_modulo(VALUE x, VALUE y); +VALUE rb_int2str(VALUE num, int base); +VALUE rb_fix_plus(VALUE x, VALUE y); +VALUE rb_int_gt(VALUE x, VALUE y); +VALUE rb_float_gt(VALUE x, VALUE y); +VALUE rb_int_ge(VALUE x, VALUE y); +enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts); +double rb_int_fdiv_double(VALUE x, VALUE y); +VALUE rb_int_pow(VALUE x, VALUE y); +VALUE rb_float_pow(VALUE x, VALUE y); +VALUE rb_int_cmp(VALUE x, VALUE y); +VALUE rb_int_equal(VALUE x, VALUE y); +VALUE rb_int_divmod(VALUE x, VALUE y); +VALUE rb_int_and(VALUE x, VALUE y); +VALUE rb_int_lshift(VALUE x, VALUE y); +VALUE rb_int_div(VALUE x, VALUE y); +int rb_int_positive_p(VALUE num); +int rb_int_negative_p(VALUE num); +VALUE rb_check_integer_type(VALUE); +VALUE rb_num_pow(VALUE x, VALUE y); +VALUE rb_float_ceil(VALUE num, int ndigits); +VALUE rb_float_floor(VALUE x, int ndigits); +VALUE rb_float_abs(VALUE flt); +static inline VALUE rb_num_compare_with_zero(VALUE num, ID mid); +static inline int rb_num_positive_int_p(VALUE num); +static inline int rb_num_negative_int_p(VALUE num); +static inline double rb_float_flonum_value(VALUE v); +static inline double rb_float_noflonum_value(VALUE v); +static inline double rb_float_value_inline(VALUE v); +static inline VALUE rb_float_new_inline(double d); +static inline bool INT_POSITIVE_P(VALUE num); +static inline bool INT_NEGATIVE_P(VALUE num); +static inline bool FLOAT_ZERO_P(VALUE num); +#define rb_float_value rb_float_value_inline +#define rb_float_new rb_float_new_inline + +RUBY_SYMBOL_EXPORT_BEGIN +/* numeric.c (export) */ +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_flo_div_flo(VALUE x, VALUE y); +double ruby_float_mod(double x, double y); +VALUE rb_float_equal(VALUE x, VALUE y); +int rb_float_cmp(VALUE x, VALUE y); +VALUE rb_float_eql(VALUE x, VALUE y); +VALUE rb_fix_aref(VALUE fix, VALUE idx); +VALUE rb_int_zero_p(VALUE num); +VALUE rb_int_even_p(VALUE num); +VALUE rb_int_odd_p(VALUE num); +VALUE rb_int_abs(VALUE num); +VALUE rb_int_bit_length(VALUE num); +VALUE rb_int_uminus(VALUE num); +VALUE rb_int_comp(VALUE num); +MJIT_SYMBOL_EXPORT_END + +static inline bool +INT_POSITIVE_P(VALUE num) +{ + if (FIXNUM_P(num)) { + return FIXNUM_POSITIVE_P(num); + } + else { + return BIGNUM_POSITIVE_P(num); + } +} + +static inline bool +INT_NEGATIVE_P(VALUE num) +{ + if (FIXNUM_P(num)) { + return FIXNUM_NEGATIVE_P(num); + } + else { + return BIGNUM_NEGATIVE_P(num); + } +} + +static inline bool +FLOAT_ZERO_P(VALUE num) +{ + return RFLOAT_VALUE(num) == 0.0; +} + +static inline VALUE +rb_num_compare_with_zero(VALUE num, ID mid) +{ + VALUE zero = INT2FIX(0); + VALUE r = rb_check_funcall(num, mid, 1, &zero); + if (r == Qundef) { + rb_cmperr(num, zero); + } + return r; +} + +static inline int +rb_num_positive_int_p(VALUE num) +{ + const ID mid = '>'; + + if (FIXNUM_P(num)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return FIXNUM_POSITIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return BIGNUM_POSITIVE_P(num); + } + return RTEST(rb_num_compare_with_zero(num, mid)); +} + +static inline int +rb_num_negative_int_p(VALUE num) +{ + const ID mid = '<'; + + if (FIXNUM_P(num)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return FIXNUM_NEGATIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return BIGNUM_NEGATIVE_P(num); + } + return RTEST(rb_num_compare_with_zero(num, mid)); +} + +static inline double +rb_float_flonum_value(VALUE v) +{ +#if USE_FLONUM + if (v != (VALUE)0x8000000000000002) { /* LIKELY */ + union { + double d; + VALUE v; + } t; + + VALUE b63 = (v >> 63); + /* e: xx1... -> 011... */ + /* xx0... -> 100... */ + /* ^b63 */ + t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~(VALUE)0x03), 3); + return t.d; + } +#endif + return 0.0; +} + +static inline double +rb_float_noflonum_value(VALUE v) +{ +#if SIZEOF_DOUBLE <= SIZEOF_VALUE + return RFLOAT(v)->float_value; +#else + union { + rb_float_value_type v; + double d; + } u = {RFLOAT(v)->float_value}; + return u.d; +#endif +} + +static inline double +rb_float_value_inline(VALUE v) +{ + if (FLONUM_P(v)) { + return rb_float_flonum_value(v); + } + return rb_float_noflonum_value(v); +} + +static inline VALUE +rb_float_new_inline(double d) +{ +#if USE_FLONUM + union { + double d; + VALUE v; + } t; + int bits; + + t.d = d; + bits = (int)((VALUE)(t.v >> 60) & 0x7); + /* bits contains 3 bits of b62..b60. */ + /* bits - 3 = */ + /* b011 -> b000 */ + /* b100 -> b001 */ + + if (t.v != 0x3000000000000000 /* 1.72723e-77 */ && + !((bits-3) & ~0x01)) { + return (RUBY_BIT_ROTL(t.v, 3) & ~(VALUE)0x01) | 0x02; + } + else if (t.v == (VALUE)0) { + /* +0.0 */ + return 0x8000000000000002; + } + /* out of range */ +#endif + return rb_float_new_in_heap(d); +} + +#endif /* INTERNAL_NUMERIC_H */ diff --git a/ruby/internal/object.h b/ruby/internal/object.h new file mode 100644 index 000000000..f560fb7f9 --- /dev/null +++ b/ruby/internal/object.h @@ -0,0 +1,83 @@ +#ifndef INTERNAL_OBJECT_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_OBJECT_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Object. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "internal/class.h" /* for RCLASS_IV_INDEX_TBL */ + +#ifdef ROBJECT_IV_INDEX_TBL +# undef ROBJECT_IV_INDEX_TBL +#endif + +/* object.c */ +VALUE rb_class_search_ancestor(VALUE klass, VALUE super); +NORETURN(void rb_undefined_alloc(VALUE klass)); +double rb_num_to_dbl(VALUE val); +VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound); +VALUE rb_immutable_obj_clone(int, VALUE *, VALUE); +VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID); +int rb_bool_expected(VALUE, const char *); +static inline void RBASIC_CLEAR_CLASS(VALUE obj); +static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass); +static inline void RBASIC_SET_CLASS(VALUE obj, VALUE klass); +static inline struct st_table *ROBJECT_IV_INDEX_TBL_inline(VALUE obj); + +RUBY_SYMBOL_EXPORT_BEGIN +/* object.c (export) */ +int rb_opts_exception_p(VALUE opts, int default_value); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2)); +CONSTFUNC(VALUE rb_obj_not(VALUE obj)); +VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); +void rb_obj_copy_ivar(VALUE dest, VALUE obj); +VALUE rb_false(VALUE obj); +VALUE rb_convert_type_with_id(VALUE v, int t, const char* nam, ID mid); +VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj); +VALUE rb_get_freeze_opt(int argc, VALUE *argv); +MJIT_SYMBOL_EXPORT_END + +static inline void +RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass) +{ + const VALUE *ptr = &RBASIC(obj)->klass; + *(VALUE *)ptr = klass; +} + +static inline void +RBASIC_CLEAR_CLASS(VALUE obj) +{ + RBASIC_SET_CLASS_RAW(obj, 0); +} + +static inline void +RBASIC_SET_CLASS(VALUE obj, VALUE klass) +{ + VALUE oldv = RBASIC_CLASS(obj); + RBASIC_SET_CLASS_RAW(obj, klass); + RB_OBJ_WRITTEN(obj, oldv, klass); +} + +RBIMPL_ATTR_PURE() +static inline struct st_table * +ROBJECT_IV_INDEX_TBL_inline(VALUE obj) +{ + if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { + VALUE klass = rb_obj_class(obj); + return RCLASS_IV_INDEX_TBL(klass); + } + else { + const struct RObject *const ptr = ROBJECT(obj); + return ptr->as.heap.iv_index_tbl; + } +} +#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL_inline + +#endif /* INTERNAL_OBJECT_H */ diff --git a/ruby/internal/parse.h b/ruby/internal/parse.h new file mode 100644 index 000000000..d9f5b56bc --- /dev/null +++ b/ruby/internal/parse.h @@ -0,0 +1,23 @@ +#ifndef INTERNAL_PARSE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_PARSE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for the parser. + */ +#include "ruby/ruby.h" /* for VALUE */ +struct rb_iseq_struct; /* in vm_core.h */ + +/* parse.y */ +VALUE rb_parser_set_yydebug(VALUE, VALUE); +void *rb_parser_load_file(VALUE parser, VALUE name); +void rb_parser_keep_script_lines(VALUE vparser); + +RUBY_SYMBOL_EXPORT_BEGIN +VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_PARSE_H */ diff --git a/ruby/internal/proc.h b/ruby/internal/proc.h new file mode 100644 index 000000000..2416c31e1 --- /dev/null +++ b/ruby/internal/proc.h @@ -0,0 +1,32 @@ +#ifndef INTERNAL_PROC_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_PROC_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Proc. + */ +#include "ruby/ruby.h" /* for rb_block_call_func_t */ +#include "ruby/st.h" /* for st_index_t */ +struct rb_block; /* in vm_core.h */ +struct rb_iseq_struct; /* in vm_core.h */ + +/* proc.c */ +VALUE rb_proc_location(VALUE self); +st_index_t rb_hash_proc(st_index_t hash, VALUE proc); +int rb_block_pair_yield_optimizable(void); +int rb_block_arity(void); +int rb_block_min_max_arity(int *max); +VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info); +VALUE rb_callable_receiver(VALUE); + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val); +VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc); +VALUE rb_iseq_location(const struct rb_iseq_struct *iseq); +VALUE rb_sym_to_proc(VALUE sym); +MJIT_SYMBOL_EXPORT_END + +#endif /* INTERNAL_PROC_H */ diff --git a/ruby/internal/process.h b/ruby/internal/process.h new file mode 100644 index 000000000..ceadfdcbb --- /dev/null +++ b/ruby/internal/process.h @@ -0,0 +1,137 @@ +#ifndef INTERNAL_PROCESS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_PROCESS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Process. + */ +#include "ruby/internal/config.h" /* for rb_pid_t */ +#include /* for size_t */ + +#ifdef HAVE_SYS_TYPES_H +# include /* for mode_t */ +#endif + +#ifdef _WIN32 +# include "ruby/win32.h" /* for mode_t */ +#endif + +#include "ruby/ruby.h" /* for VALUE */ +#include "internal/imemo.h" /* for RB_IMEMO_TMPBUF_PTR */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ + +#define RB_MAX_GROUPS (65536) + +struct waitpid_state; +struct rb_process_status; +struct rb_execarg { + union { + struct { + VALUE shell_script; + } sh; + struct { + VALUE command_name; + VALUE command_abspath; /* full path string or nil */ + VALUE argv_str; + VALUE argv_buf; + } cmd; + } invoke; + VALUE redirect_fds; + VALUE envp_str; + VALUE envp_buf; + VALUE dup2_tmpbuf; + unsigned use_shell : 1; + unsigned pgroup_given : 1; + unsigned umask_given : 1; + unsigned unsetenv_others_given : 1; + unsigned unsetenv_others_do : 1; + unsigned close_others_given : 1; + unsigned close_others_do : 1; + unsigned chdir_given : 1; + unsigned new_pgroup_given : 1; + unsigned new_pgroup_flag : 1; + unsigned uid_given : 1; + unsigned gid_given : 1; + unsigned exception : 1; + unsigned exception_given : 1; + struct rb_process_status *status; + struct waitpid_state *waitpid_state; /* for async process management */ + rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0 + * @copyright 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. + * @brief Internal header for Random. + */ +#include /* for size_t */ + +/* random.c */ +int ruby_fill_random_bytes(void *, size_t, int); + +#endif /* INTERNAL_RANDOM_H */ diff --git a/ruby/internal/range.h b/ruby/internal/range.h new file mode 100644 index 000000000..8daba0eca --- /dev/null +++ b/ruby/internal/range.h @@ -0,0 +1,40 @@ +#ifndef INTERNAL_RANGE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_RANGE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Range. + */ +#include "internal/struct.h" /* for RSTRUCT */ + +/* range.c */ +static inline VALUE RANGE_BEG(VALUE r); +static inline VALUE RANGE_END(VALUE r); +static inline VALUE RANGE_EXCL(VALUE r); + +static inline VALUE +RANGE_BEG(VALUE r) +{ + return RSTRUCT(r)->as.ary[0]; +} + +static inline VALUE +RANGE_END(VALUE r) +{ + return RSTRUCT(r)->as.ary[1]; +} + +static inline VALUE +RANGE_EXCL(VALUE r) +{ + return RSTRUCT(r)->as.ary[2]; +} + +VALUE +rb_range_component_beg_len(VALUE b, VALUE e, int excl, + long *begp, long *lenp, long len, int err); + +#endif /* INTERNAL_RANGE_H */ diff --git a/ruby/internal/rational.h b/ruby/internal/rational.h new file mode 100644 index 000000000..61ddbf089 --- /dev/null +++ b/ruby/internal/rational.h @@ -0,0 +1,72 @@ +#ifndef INTERNAL_RATIONAL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_RATIONAL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Rational. + */ +#include "ruby/internal/config.h" /* for HAVE_LIBGMP */ +#include "ruby/ruby.h" /* for struct RBasic */ +#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "internal/numeric.h" /* for INT_POSITIVE_P */ +#include "ruby_assert.h" /* for assert */ + +struct RRational { + struct RBasic basic; + VALUE num; + VALUE den; +}; + +#define RRATIONAL(obj) ((struct RRational *)(obj)) + +/* rational.c */ +VALUE rb_rational_canonicalize(VALUE x); +VALUE rb_rational_uminus(VALUE self); +VALUE rb_rational_plus(VALUE self, VALUE other); +VALUE rb_rational_minus(VALUE self, VALUE other); +VALUE rb_rational_mul(VALUE self, VALUE other); +VALUE rb_rational_div(VALUE self, VALUE other); +VALUE rb_lcm(VALUE x, VALUE y); +VALUE rb_rational_reciprocal(VALUE x); +VALUE rb_cstr_to_rat(const char *, int); +VALUE rb_rational_hash(VALUE self); +VALUE rb_rational_abs(VALUE self); +VALUE rb_rational_cmp(VALUE self, VALUE other); +VALUE rb_rational_pow(VALUE self, VALUE other); +VALUE rb_rational_floor(VALUE self, int ndigits); +VALUE rb_numeric_quo(VALUE x, VALUE y); +VALUE rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num); +VALUE rb_float_numerator(VALUE x); +VALUE rb_float_denominator(VALUE x); + +static inline void RATIONAL_SET_NUM(VALUE r, VALUE n); +static inline void RATIONAL_SET_DEN(VALUE r, VALUE d); + +RUBY_SYMBOL_EXPORT_BEGIN +/* rational.c (export) */ +VALUE rb_gcd(VALUE x, VALUE y); +VALUE rb_gcd_normal(VALUE self, VALUE other); +#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) +VALUE rb_gcd_gmp(VALUE x, VALUE y); +#endif +RUBY_SYMBOL_EXPORT_END + +static inline void +RATIONAL_SET_NUM(VALUE r, VALUE n) +{ + assert(RB_INTEGER_TYPE_P(n)); + RB_OBJ_WRITE(r, &RRATIONAL(r)->num, n); +} + +static inline void +RATIONAL_SET_DEN(VALUE r, VALUE d) +{ + assert(RB_INTEGER_TYPE_P(d)); + assert(INT_POSITIVE_P(d)); + RB_OBJ_WRITE(r, &RRATIONAL(r)->den, d); +} + +#endif /* INTERNAL_RATIONAL_H */ diff --git a/ruby/internal/re.h b/ruby/internal/re.h new file mode 100644 index 000000000..8b31b3d8a --- /dev/null +++ b/ruby/internal/re.h @@ -0,0 +1,30 @@ +#ifndef INTERNAL_RE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_RE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Regexp. + */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for VALUE */ + +/* re.c */ +VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline); +VALUE rb_reg_check_preprocess(VALUE); +long rb_reg_search0(VALUE, VALUE, long, int, int); +VALUE rb_reg_match_p(VALUE re, VALUE str, long pos); +bool rb_reg_start_with_p(VALUE re, VALUE str); +VALUE rb_reg_hash(VALUE re); +VALUE rb_reg_equal(VALUE re1, VALUE re2); +void rb_backref_set_string(VALUE string, long pos, long len); +void rb_match_unbusy(VALUE); +int rb_match_count(VALUE match); +int rb_match_nth_defined(int nth, VALUE match); +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_reg_new_ary(VALUE ary, int options); +MJIT_SYMBOL_EXPORT_END + +#endif /* INTERNAL_RE_H */ diff --git a/ruby/internal/sanitizers.h b/ruby/internal/sanitizers.h new file mode 100644 index 000000000..6e2d81137 --- /dev/null +++ b/ruby/internal/sanitizers.h @@ -0,0 +1,190 @@ +#ifndef INTERNAL_SANITIZERS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_SANITIZERS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for ASAN / MSAN / etc. + */ +#include "ruby/internal/config.h" +#include "internal/compilers.h" /* for __has_feature */ + +#ifdef HAVE_VALGRIND_MEMCHECK_H +# include +#endif + +#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H +# include +#endif + +#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for VALUE */ + +#if 0 +#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer) +# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ + __attribute__((__no_sanitize__("memory, address"), __noinline__)) x +#elif __has_feature(address_sanitizer) +# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ + __attribute__((__no_sanitize__("address"), __noinline__)) x +#elif defined(NO_SANITIZE_ADDRESS) +# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ + NO_SANITIZE_ADDRESS(NOINLINE(x)) +#elif defined(NO_ADDRESS_SAFETY_ANALYSIS) +# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ + NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x)) +#else +# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x +#endif + +#if defined(NO_SANITIZE) && RBIMPL_COMPILER_IS(GCC) +/* GCC warns about unknown sanitizer, which is annoying. */ +# include "internal/warnings.h" +# undef NO_SANITIZE +# define NO_SANITIZE(x, y) \ + COMPILER_WARNING_PUSH; \ + COMPILER_WARNING_IGNORED(-Wattributes); \ + __attribute__((__no_sanitize__(x))) y; \ + COMPILER_WARNING_POP +#endif + +#ifndef NO_SANITIZE +# define NO_SANITIZE(x, y) y +#endif + +#if !__has_feature(address_sanitizer) +# define __asan_poison_memory_region(x, y) +# define __asan_unpoison_memory_region(x, y) +# define __asan_region_is_poisoned(x, y) 0 +#endif + +#if !__has_feature(memory_sanitizer) +# define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) +# define __msan_poison(x, y) ((void)(x), (void)(y)) +# define __msan_unpoison(x, y) ((void)(x), (void)(y)) +# define __msan_unpoison_string(x) ((void)(x)) +#endif + +#ifdef VALGRIND_MAKE_READABLE +# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n)) +#endif + +#ifdef VALGRIND_MAKE_WRITABLE +# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n)) +#endif + +#ifndef VALGRIND_MAKE_MEM_DEFINED +# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0 +#endif + +#ifndef VALGRIND_MAKE_MEM_UNDEFINED +# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 +#endif + +#ifndef MJIT_HEADER + +/*! + * This function asserts that a (continuous) memory region from ptr to size + * being "poisoned". Both read / write access to such memory region are + * prohibited until properly unpoisoned. The region must be previously + * allocated (do not pass a freed pointer here), but not necessarily be an + * entire object that the malloc returns. You can punch hole a part of a + * gigantic heap arena. This is handy when you do not free an allocated memory + * region to reuse later: poison when you keep it unused, and unpoison when you + * reuse. + * + * \param[in] ptr pointer to the beginning of the memory region to poison. + * \param[in] size the length of the memory region to poison. + */ +static inline void +asan_poison_memory_region(const volatile void *ptr, size_t size) +{ + __msan_poison(ptr, size); + __asan_poison_memory_region(ptr, size); +} + +/*! + * This is a variant of asan_poison_memory_region that takes a VALUE. + * + * \param[in] obj target object. + */ +static inline void +asan_poison_object(VALUE obj) +{ + MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; + asan_poison_memory_region(ptr, SIZEOF_VALUE); +} + +#if !__has_feature(address_sanitizer) +#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) +#else +#define asan_poison_object_if(ptr, obj) do { \ + if (ptr) asan_poison_object(obj); \ + } while (0) +#endif + +/*! + * This function predicates if the given object is fully addressable or not. + * + * \param[in] obj target object. + * \retval 0 the given object is fully addressable. + * \retval otherwise pointer to first such byte who is poisoned. + */ +static inline void * +asan_poisoned_object_p(VALUE obj) +{ + MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; + return __asan_region_is_poisoned(ptr, SIZEOF_VALUE); +} + +/*! + * This function asserts that a (formally poisoned) memory region from ptr to + * size is now addressable. Write access to such memory region gets allowed. + * However read access might or might not be possible depending on situations, + * because the region can have contents of previous usages. That information + * should be passed by the malloc_p flag. If that is true, the contents of the + * region is _not_ fully defined (like the return value of malloc behaves). + * Reading from there is NG; write something first. If malloc_p is false on + * the other hand, that memory region is fully defined and can be read + * immediately. + * + * \param[in] ptr pointer to the beginning of the memory region to unpoison. + * \param[in] size the length of the memory region. + * \param[in] malloc_p if the memory region is like a malloc's return value or not. + */ +static inline void +asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p) +{ + __asan_unpoison_memory_region(ptr, size); + if (malloc_p) { + __msan_allocated_memory(ptr, size); + } + else { + __msan_unpoison(ptr, size); + } +} + +/*! + * This is a variant of asan_unpoison_memory_region that takes a VALUE. + * + * \param[in] obj target object. + * \param[in] malloc_p if the memory region is like a malloc's return value or not. + */ +static inline void +asan_unpoison_object(VALUE obj, bool newobj_p) +{ + MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj; + asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); +} + +#endif /* MJIT_HEADER */ + +#endif /* INTERNAL_SANITIZERS_H */ diff --git a/ruby/internal/serial.h b/ruby/internal/serial.h new file mode 100644 index 000000000..df9e9a44f --- /dev/null +++ b/ruby/internal/serial.h @@ -0,0 +1,23 @@ +#ifndef INTERNAL_SERIAL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_SERIAL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for rb_serial_t. + */ +#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */ +#include "ruby/defines.h" /* for LONG_LONG */ + +#ifndef HAVE_LONG_LONG +# error need C99+ +#endif + +typedef unsigned LONG_LONG rb_serial_t; +#define SERIALT2NUM ULL2NUM +#define PRI_SERIALT_PREFIX PRI_LL_PREFIX +#define SIZEOF_SERIAL_T SIZEOF_LONG_LONG + +#endif /* INTERNAL_SERIAL_H */ diff --git a/ruby/internal/signal.h b/ruby/internal/signal.h new file mode 100644 index 000000000..86fb54e94 --- /dev/null +++ b/ruby/internal/signal.h @@ -0,0 +1,21 @@ +#ifndef INTERNAL_SIGNAL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_SIGNAL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for SignalException. + */ + +/* signal.c */ +extern int ruby_enable_coredump; +int rb_get_next_signal(void); + +RUBY_SYMBOL_EXPORT_BEGIN +/* signal.c (export) */ +int rb_grantpt(int fd); +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_SIGNAL_H */ diff --git a/ruby/internal/static_assert.h b/ruby/internal/static_assert.h new file mode 100644 index 000000000..70dd0b7a1 --- /dev/null +++ b/ruby/internal/static_assert.h @@ -0,0 +1,16 @@ +#ifndef INTERNAL_STATIC_ASSERT_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_STATIC_ASSERT_H +/** + * @author Ruby developers + * @copyright 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. + * @brief C11 shim for _Static_assert. + */ +#include "ruby/internal/static_assert.h" +#ifndef STATIC_ASSERT +# define STATIC_ASSERT RBIMPL_STATIC_ASSERT +#endif + +#endif /* INTERNAL_STATIC_ASSERT_H */ diff --git a/ruby/internal/string.h b/ruby/internal/string.h new file mode 100644 index 000000000..18b01862f --- /dev/null +++ b/ruby/internal/string.h @@ -0,0 +1,141 @@ +#ifndef INTERNAL_STRING_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_STRING_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for String. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "internal/compilers.h" /* for __has_builtin */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/encoding.h" /* for rb_encoding */ +#include "ruby/ruby.h" /* for VALUE */ + +#define STR_NOEMBED FL_USER1 +#define STR_SHARED FL_USER2 /* = ELTS_SHARED */ + +#ifdef rb_fstring_cstr +# undef rb_fstring_cstr +#endif + +/* string.c */ +VALUE rb_fstring(VALUE); +VALUE rb_fstring_cstr(const char *str); +VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc); +int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p); +int rb_str_symname_p(VALUE); +VALUE rb_str_quote_unprintable(VALUE); +char *rb_str_fill_terminator(VALUE str, const int termlen); +void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen); +VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg); +VALUE rb_str_chomp_string(VALUE str, VALUE chomp); +VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc); +VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, + rb_encoding *from, int ecflags, VALUE ecopts); +VALUE rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl); +VALUE rb_str_escape(VALUE str); +size_t rb_str_memsize(VALUE); +char *rb_str_to_cstr(VALUE str); +const char *ruby_escaped_char(int c); +void rb_str_make_independent(VALUE str); +int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc); + +static inline bool STR_EMBED_P(VALUE str); +static inline bool STR_SHARED_P(VALUE str); +static inline VALUE QUOTE(VALUE v); +static inline VALUE QUOTE_ID(ID v); +static inline bool is_ascii_string(VALUE str); +static inline bool is_broken_string(VALUE str); +static inline VALUE rb_str_eql_internal(const VALUE str1, const VALUE str2); + +RUBY_SYMBOL_EXPORT_BEGIN +/* string.c (export) */ +VALUE rb_str_tmp_frozen_acquire(VALUE str); +void rb_str_tmp_frozen_release(VALUE str, VALUE tmp); +VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc); +VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE); +VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_fstring_new(const char *ptr, long len); +VALUE rb_obj_as_string_result(VALUE str, VALUE obj); +VALUE rb_str_opt_plus(VALUE x, VALUE y); +VALUE rb_str_concat_literals(size_t num, const VALUE *strary); +VALUE rb_str_eql(VALUE str1, VALUE str2); +VALUE rb_id_quote_unprintable(ID); +VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc); + +struct rb_execution_context_struct; +VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str); +MJIT_SYMBOL_EXPORT_END + +#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str)) +#define rb_fstring_literal(str) rb_fstring_lit(str) +#define rb_fstring_enc_lit(str, enc) rb_fstring_enc_new((str), rb_strlen_lit(str), (enc)) +#define rb_fstring_enc_literal(str, enc) rb_fstring_enc_lit(str, enc) + +static inline VALUE +QUOTE(VALUE v) +{ + return rb_str_quote_unprintable(v); +} + +static inline VALUE +QUOTE_ID(ID i) +{ + return rb_id_quote_unprintable(i); +} + +static inline bool +STR_EMBED_P(VALUE str) +{ + return ! FL_TEST_RAW(str, STR_NOEMBED); +} + +static inline bool +STR_SHARED_P(VALUE str) +{ + return FL_ALL_RAW(str, STR_NOEMBED | ELTS_SHARED); +} + +static inline bool +is_ascii_string(VALUE str) +{ + return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT; +} + +static inline bool +is_broken_string(VALUE str) +{ + return rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN; +} + +/* expect tail call optimization */ +// YJIT needs this function to never allocate and never raise +static inline VALUE +rb_str_eql_internal(const VALUE str1, const VALUE str2) +{ + const long len = RSTRING_LEN(str1); + const char *ptr1, *ptr2; + + if (len != RSTRING_LEN(str2)) return Qfalse; + if (!rb_str_comparable(str1, str2)) return Qfalse; + if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2))) + return Qtrue; + if (memcmp(ptr1, ptr2, len) == 0) + return Qtrue; + return Qfalse; +} + +#if __has_builtin(__builtin_constant_p) +# define rb_fstring_cstr(str) \ + (__builtin_constant_p(str) ? \ + rb_fstring_new((str), (long)strlen(str)) : \ + (rb_fstring_cstr)(str)) +#endif +#endif /* INTERNAL_STRING_H */ diff --git a/ruby/internal/struct.h b/ruby/internal/struct.h new file mode 100644 index 000000000..8acc00ec3 --- /dev/null +++ b/ruby/internal/struct.h @@ -0,0 +1,153 @@ +#ifndef INTERNAL_STRUCT_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_STRUCT_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Struct. + */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "ruby/ruby.h" /* for struct RBasic */ + +enum { + RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX, + RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1), + RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1), + RSTRUCT_TRANSIENT_FLAG = FL_USER3, +}; + +struct RStruct { + struct RBasic basic; + union { + struct { + long len; + const VALUE *ptr; + } heap; + const VALUE ary[RSTRUCT_EMBED_LEN_MAX]; + } as; +}; + +#define RSTRUCT(obj) ((struct RStruct *)(obj)) + +#ifdef RSTRUCT_LEN +# undef RSTRUCT_LEN +#endif + +#ifdef RSTRUCT_PTR +# undef RSTRUCT_PTR +#endif + +#ifdef RSTRUCT_SET +# undef RSTRUCT_SET +#endif + +#ifdef RSTRUCT_GET +# undef RSTRUCT_GET +#endif + +#define RSTRUCT_LEN internal_RSTRUCT_LEN +#define RSTRUCT_SET internal_RSTRUCT_SET +#define RSTRUCT_GET internal_RSTRUCT_GET + +/* struct.c */ +VALUE rb_struct_init_copy(VALUE copy, VALUE s); +VALUE rb_struct_lookup(VALUE s, VALUE idx); +VALUE rb_struct_s_keyword_init(VALUE klass); +static inline const VALUE *rb_struct_const_heap_ptr(VALUE st); +static inline bool RSTRUCT_TRANSIENT_P(VALUE st); +static inline void RSTRUCT_TRANSIENT_SET(VALUE st); +static inline void RSTRUCT_TRANSIENT_UNSET(VALUE st); +static inline long RSTRUCT_EMBED_LEN(VALUE st); +static inline long RSTRUCT_LEN(VALUE st); +static inline int RSTRUCT_LENINT(VALUE st); +static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st); +static inline void RSTRUCT_SET(VALUE st, long k, VALUE v); +static inline VALUE RSTRUCT_GET(VALUE st, long k); + +static inline bool +RSTRUCT_TRANSIENT_P(VALUE st) +{ +#if USE_TRANSIENT_HEAP + return FL_TEST_RAW(st, RSTRUCT_TRANSIENT_FLAG); +#else + return false; +#endif +} + +static inline void +RSTRUCT_TRANSIENT_SET(VALUE st) +{ +#if USE_TRANSIENT_HEAP + FL_SET_RAW(st, RSTRUCT_TRANSIENT_FLAG); +#endif +} + +static inline void +RSTRUCT_TRANSIENT_UNSET(VALUE st) +{ +#if USE_TRANSIENT_HEAP + FL_UNSET_RAW(st, RSTRUCT_TRANSIENT_FLAG); +#endif +} + +static inline long +RSTRUCT_EMBED_LEN(VALUE st) +{ + long ret = FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK); + ret >>= RSTRUCT_EMBED_LEN_SHIFT; + return ret; +} + +static inline long +RSTRUCT_LEN(VALUE st) +{ + if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) { + return RSTRUCT_EMBED_LEN(st); + } + else { + return RSTRUCT(st)->as.heap.len; + } +} + +static inline int +RSTRUCT_LENINT(VALUE st) +{ + return rb_long2int(RSTRUCT_LEN(st)); +} + +static inline const VALUE * +RSTRUCT_CONST_PTR(VALUE st) +{ + const struct RStruct *p = RSTRUCT(st); + + if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) { + return p->as.ary; + } + else { + return p->as.heap.ptr; + } +} + +static inline void +RSTRUCT_SET(VALUE st, long k, VALUE v) +{ + RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[k], v); +} + +static inline VALUE +RSTRUCT_GET(VALUE st, long k) +{ + return RSTRUCT_CONST_PTR(st)[k]; +} + +static inline const VALUE * +rb_struct_const_heap_ptr(VALUE st) +{ + /* TODO: check embed on debug mode */ + return RSTRUCT(st)->as.heap.ptr; +} + +#endif /* INTERNAL_STRUCT_H */ diff --git a/ruby/internal/symbol.h b/ruby/internal/symbol.h new file mode 100644 index 000000000..4f041330f --- /dev/null +++ b/ruby/internal/symbol.h @@ -0,0 +1,41 @@ +#ifndef INTERNAL_SYMBOL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_SYMBOL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Symbol. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/encoding.h" /* for rb_encoding */ +#include "internal/compilers.h" /* for __has_builtin */ + +#ifdef rb_sym_intern_ascii_cstr +# undef rb_sym_intern_ascii_cstr +#endif + +/* symbol.c */ +VALUE rb_to_symbol_type(VALUE obj); +VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc); +VALUE rb_sym_intern_ascii(const char *ptr, long len); +VALUE rb_sym_intern_ascii_cstr(const char *ptr); +int rb_is_const_name(VALUE name); +int rb_is_class_name(VALUE name); +int rb_is_instance_name(VALUE name); +int rb_is_local_name(VALUE name); +PUREFUNC(int rb_is_const_sym(VALUE sym)); +PUREFUNC(int rb_is_attrset_sym(VALUE sym)); +ID rb_make_internal_id(void); +ID rb_make_temporary_id(size_t n); +void rb_gc_free_dsymbol(VALUE); + +#if __has_builtin(__builtin_constant_p) +#define rb_sym_intern_ascii_cstr(ptr) \ + (__builtin_constant_p(ptr) ? \ + rb_sym_intern_ascii((ptr), (long)strlen(ptr)) : \ + rb_sym_intern_ascii_cstr(ptr)) +#endif + +#endif /* INTERNAL_SYMBOL_H */ diff --git a/ruby/internal/thread.h b/ruby/internal/thread.h new file mode 100644 index 000000000..919ad9658 --- /dev/null +++ b/ruby/internal/thread.h @@ -0,0 +1,53 @@ +#ifndef INTERNAL_THREAD_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_THREAD_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Thread. + */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/intern.h" /* for rb_blocking_function_t */ + +struct rb_thread_struct; /* in vm_core.h */ + +/* thread.c */ +#define COVERAGE_INDEX_LINES 0 +#define COVERAGE_INDEX_BRANCHES 1 +#define COVERAGE_TARGET_LINES 1 +#define COVERAGE_TARGET_BRANCHES 2 +#define COVERAGE_TARGET_METHODS 4 +#define COVERAGE_TARGET_ONESHOT_LINES 8 + +VALUE rb_obj_is_mutex(VALUE obj); +VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg); +void rb_thread_execute_interrupts(VALUE th); +VALUE rb_get_coverages(void); +int rb_get_coverage_mode(void); +VALUE rb_default_coverage(int); +VALUE rb_thread_shield_new(void); +VALUE rb_thread_shield_wait(VALUE self); +VALUE rb_thread_shield_release(VALUE self); +VALUE rb_thread_shield_destroy(VALUE self); +int rb_thread_to_be_killed(VALUE thread); +void rb_mutex_allow_trap(VALUE self, int val); +VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data); +VALUE rb_mutex_owned_p(VALUE self); + +int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout); + +RUBY_SYMBOL_EXPORT_BEGIN +/* Temporary. This API will be removed (renamed). */ +VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd); + +/* thread.c (export) */ +int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */ +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing); +MJIT_SYMBOL_EXPORT_END + +#endif /* INTERNAL_THREAD_H */ diff --git a/ruby/internal/time.h b/ruby/internal/time.h new file mode 100644 index 000000000..a3bf0587e --- /dev/null +++ b/ruby/internal/time.h @@ -0,0 +1,34 @@ +#ifndef INTERNAL_TIME_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_TIME_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Time. + */ +#include "ruby/internal/config.h" /* for SIGNEDNESS_OF_TIME_T */ +#include "internal/bits.h" /* for SIGNED_INTEGER_MAX */ +#include "ruby/ruby.h" /* for VALUE */ + +#if SIGNEDNESS_OF_TIME_T < 0 /* signed */ +# define TIMET_MAX SIGNED_INTEGER_MAX(time_t) +# define TIMET_MIN SIGNED_INTEGER_MIN(time_t) +#elif SIGNEDNESS_OF_TIME_T > 0 /* unsigned */ +# define TIMET_MAX UNSIGNED_INTEGER_MAX(time_t) +# define TIMET_MIN ((time_t)0) +#endif + +struct timeval; /* <- in or */ + +/* time.c */ +struct timeval rb_time_timeval(VALUE); + +RUBY_SYMBOL_EXPORT_BEGIN +/* time.c (export) */ +void ruby_reset_leap_second_info(void); +void ruby_reset_timezone(void); +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_TIME_H */ diff --git a/ruby/internal/transcode.h b/ruby/internal/transcode.h new file mode 100644 index 000000000..9922332ea --- /dev/null +++ b/ruby/internal/transcode.h @@ -0,0 +1,20 @@ +#ifndef INTERNAL_TRANSCODE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_TRANSCODE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for Encoding::Converter. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "ruby/ruby.h" /* for VALUE */ +#include "ruby/encoding.h" /* for rb_econv_t */ + +/* transcode.c */ +extern VALUE rb_cEncodingConverter; +size_t rb_econv_memsize(rb_econv_t *); + +#endif /* INTERNAL_TRANSCODE_H */ diff --git a/ruby/internal/util.h b/ruby/internal/util.h new file mode 100644 index 000000000..6eadbb9f9 --- /dev/null +++ b/ruby/internal/util.h @@ -0,0 +1,27 @@ +#ifndef INTERNAL_UTIL_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_UTIL_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header corresponding util.c. + * @warning DO NOT ADD RANDOM GARBAGE HERE THIS FILE IS FOR util.c + */ +#include "ruby/internal/config.h" +#include /* for size_t */ + +#ifdef HAVE_SYS_TYPES_H +# include /* for ssize_t (note: on Windows ssize_t is */ +#endif /* `#define`d in ruby/config.h) */ + +/* util.c */ +char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve); +char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve); + +RUBY_SYMBOL_EXPORT_BEGIN +/* util.c (export) */ +RUBY_SYMBOL_EXPORT_END + +#endif /* INTERNAL_UTIL_H */ diff --git a/ruby/internal/variable.h b/ruby/internal/variable.h new file mode 100644 index 000000000..4b67bef90 --- /dev/null +++ b/ruby/internal/variable.h @@ -0,0 +1,83 @@ +#ifndef INTERNAL_VARIABLE_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_VARIABLE_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for variables. + */ +#include "ruby/internal/config.h" +#include /* for size_t */ +#include "constant.h" /* for rb_const_entry_t */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for VALUE */ + +/* global variable */ + +#define ROBJECT_TRANSIENT_FLAG FL_USER13 + +/* variable.c */ +void rb_gc_mark_global_tbl(void); +void rb_gc_update_global_tbl(void); +size_t rb_generic_ivar_memsize(VALUE); +VALUE rb_search_class_path(VALUE); +VALUE rb_attr_delete(VALUE, ID); +VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); +void rb_autoload_str(VALUE mod, ID id, VALUE file); +VALUE rb_autoload_at_p(VALUE, ID, int); +NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE)); +rb_gvar_getter_t *rb_gvar_getter_function_of(ID); +rb_gvar_setter_t *rb_gvar_setter_function_of(ID); +void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_); +void rb_gvar_ractor_local(const char *name); +static inline bool ROBJ_TRANSIENT_P(VALUE obj); +static inline void ROBJ_TRANSIENT_SET(VALUE obj); +static inline void ROBJ_TRANSIENT_UNSET(VALUE obj); +uint32_t rb_obj_ensure_iv_index_mapping(VALUE obj, ID id); + +RUBY_SYMBOL_EXPORT_BEGIN +/* variable.c (export) */ +void rb_mark_generic_ivar(VALUE); +void rb_mv_generic_ivar(VALUE src, VALUE dst); +VALUE rb_const_missing(VALUE klass, VALUE name); +int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); +void rb_iv_tbl_copy(VALUE dst, VALUE src); +RUBY_SYMBOL_EXPORT_END + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_gvar_get(ID); +VALUE rb_gvar_set(ID, VALUE); +VALUE rb_gvar_defined(ID); +void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID); +void rb_init_iv_list(VALUE obj); +MJIT_SYMBOL_EXPORT_END + +static inline bool +ROBJ_TRANSIENT_P(VALUE obj) +{ +#if USE_TRANSIENT_HEAP + return FL_TEST_RAW(obj, ROBJECT_TRANSIENT_FLAG); +#else + return false; +#endif +} + +static inline void +ROBJ_TRANSIENT_SET(VALUE obj) +{ +#if USE_TRANSIENT_HEAP + FL_SET_RAW(obj, ROBJECT_TRANSIENT_FLAG); +#endif +} + +static inline void +ROBJ_TRANSIENT_UNSET(VALUE obj) +{ +#if USE_TRANSIENT_HEAP + FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG); +#endif +} + +#endif /* INTERNAL_VARIABLE_H */ diff --git a/ruby/internal/vm.h b/ruby/internal/vm.h new file mode 100644 index 000000000..bfb593176 --- /dev/null +++ b/ruby/internal/vm.h @@ -0,0 +1,133 @@ +#ifndef INTERNAL_VM_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_VM_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header for RubyVM. + */ +#include "ruby/internal/stdbool.h" /* for bool */ +#include "internal/serial.h" /* for rb_serial_t */ +#include "internal/static_assert.h" /* for STATIC_ASSERT */ +#include "ruby/ruby.h" /* for ID */ +#include "ruby/st.h" /* for st_table */ + +#ifdef rb_funcallv +# undef rb_funcallv +#endif + +#ifdef rb_method_basic_definition_p +# undef rb_method_basic_definition_p +#endif + +struct rb_callable_method_entry_struct; /* in method.h */ +struct rb_method_definition_struct; /* in method.h */ +struct rb_execution_context_struct; /* in vm_core.h */ +struct rb_control_frame_struct; /* in vm_core.h */ +struct rb_callinfo; /* in vm_core.h */ + +enum method_missing_reason { + MISSING_NOENTRY = 0x00, + MISSING_PRIVATE = 0x01, + MISSING_PROTECTED = 0x02, + MISSING_FCALL = 0x04, + MISSING_VCALL = 0x08, + MISSING_SUPER = 0x10, + MISSING_MISSING = 0x20, + MISSING_NONE = 0x40 +}; + +/* vm_insnhelper.h */ +rb_serial_t rb_next_class_serial(void); + +/* vm.c */ +VALUE rb_obj_is_thread(VALUE obj); +void rb_vm_mark(void *ptr); +void rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx); +PUREFUNC(VALUE rb_vm_top_self(void)); +void rb_vm_inc_const_missing_count(void); +const void **rb_vm_get_insns_address_table(void); +VALUE rb_source_location(int *pline); +const char *rb_source_location_cstr(int *pline); +MJIT_STATIC void rb_vm_pop_cfunc_frame(void); +int rb_vm_add_root_module(VALUE module); +void rb_vm_check_redefinition_by_prepend(VALUE klass); +int rb_vm_check_optimizable_mid(VALUE mid); +VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements); +MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE); +PUREFUNC(st_table *rb_vm_fstring_table(void)); + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE vm_exec(struct rb_execution_context_struct *, bool); /* used in JIT-ed code */ +MJIT_SYMBOL_EXPORT_END + +/* vm_eval.c */ +VALUE rb_current_realfilepath(void); +VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE); +typedef void rb_check_funcall_hook(int, VALUE, ID, int, const VALUE *, VALUE); +VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv, + rb_check_funcall_hook *hook, VALUE arg); +VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *argv, + rb_check_funcall_hook *hook, VALUE arg, int kw_splat); +const char *rb_type_str(enum ruby_value_type type); +VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE); +VALUE rb_check_funcall_basic_kw(VALUE, ID, VALUE, int, const VALUE*, int); +VALUE rb_yield_1(VALUE val); +VALUE rb_yield_force_blockarg(VALUE values); +VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv, + rb_block_call_func_t bl_proc, int min_argc, int max_argc, + VALUE data2); +void rb_check_stack_overflow(void); + +/* vm_insnhelper.c */ +VALUE rb_equal_opt(VALUE obj1, VALUE obj2); +VALUE rb_eql_opt(VALUE obj1, VALUE obj2); + +struct rb_iseq_struct; +MJIT_SYMBOL_EXPORT_BEGIN +const struct rb_callcache *rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass); +MJIT_SYMBOL_EXPORT_END + +/* vm_method.c */ +struct rb_execution_context_struct; +MJIT_SYMBOL_EXPORT_BEGIN +int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv); +MJIT_SYMBOL_EXPORT_END + +/* vm_dump.c */ +void rb_print_backtrace(void); + +/* vm_backtrace.c */ +VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval); +VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval); +VALUE rb_vm_backtrace(int argc, const VALUE * argv, struct rb_execution_context_struct * ec); +VALUE rb_vm_backtrace_locations(int argc, const VALUE * argv, struct rb_execution_context_struct * ec); +VALUE rb_make_backtrace(void); +void rb_backtrace_print_as_bugreport(void); +int rb_backtrace_p(VALUE obj); +VALUE rb_backtrace_to_str_ary(VALUE obj); +VALUE rb_backtrace_to_location_ary(VALUE obj); +void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output); +int rb_frame_info_p(VALUE obj); +int rb_get_node_id_from_frame_info(VALUE obj); +const struct rb_iseq_struct *rb_get_iseq_from_frame_info(VALUE obj); + +MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec); +void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self); +MJIT_SYMBOL_EXPORT_END + +#define RUBY_DTRACE_CREATE_HOOK(name, arg) \ + RUBY_DTRACE_HOOK(name##_CREATE, arg) +#define RUBY_DTRACE_HOOK(name, arg) \ +do { \ + if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \ + int dtrace_line; \ + const char *dtrace_file = rb_source_location_cstr(&dtrace_line); \ + if (!dtrace_file) dtrace_file = ""; \ + RUBY_DTRACE_##name(arg, dtrace_file, dtrace_line); \ + } \ +} while (0) +#endif /* INTERNAL_VM_H */ diff --git a/ruby/internal/warnings.h b/ruby/internal/warnings.h new file mode 100644 index 000000000..020212ebd --- /dev/null +++ b/ruby/internal/warnings.h @@ -0,0 +1,16 @@ +#ifndef INTERNAL_WARNINGS_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_WARNINGS_H +/** + * @author Ruby developers + * @copyright 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. + * @brief Internal header to suppress / mandate warnings. + */ +#include "ruby/internal/warning_push.h" +#define COMPILER_WARNING_PUSH RBIMPL_WARNING_PUSH() +#define COMPILER_WARNING_POP RBIMPL_WARNING_POP() +#define COMPILER_WARNING_ERROR(flag) RBIMPL_WARNING_ERROR(flag) +#define COMPILER_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag) +#endif /* INTERNAL_WARNINGS_H */ diff --git a/ruby/io.c b/ruby/io.c index 046f070f5..0b543108b 100644 --- a/ruby/io.c +++ b/ruby/io.c @@ -11,38 +11,34 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/io.h" -#include "ruby/thread.h" -#include "internal.h" -#include "dln.h" -#include "encindex.h" -#include "id.h" +#include "ruby/internal/config.h" + +#include "ruby/fiber/scheduler.h" +#include "ruby/io/buffer.h" + +#ifdef _WIN32 +# include "ruby/ruby.h" +# include "ruby/io.h" +#endif + #include #include -#include "ruby_atomic.h" -#include "ccan/list/list.h" +#include /* non-Linux poll may not work on all FDs */ #if defined(HAVE_POLL) -# if defined(__linux__) -# define USE_POLL 1 -# endif -# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000 -# define USE_POLL 1 -# endif +# if defined(__linux__) +# define USE_POLL 1 +# endif +# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000 +# define USE_POLL 1 +# endif #endif #ifndef USE_POLL -# define USE_POLL 0 +# define USE_POLL 0 #endif -#if !USE_POLL -# include "vm_core.h" -#endif - -#include "builtin.h" - #undef free #define free(x) xfree(x) @@ -119,7 +115,34 @@ # include #endif +#include "ruby/internal/stdbool.h" +#include "ccan/list/list.h" +#include "dln.h" +#include "encindex.h" +#include "id.h" +#include "internal.h" +#include "internal/encoding.h" +#include "internal/error.h" +#include "internal/inits.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/process.h" +#include "internal/thread.h" +#include "internal/transcode.h" +#include "internal/variable.h" +#include "ruby/io.h" +#include "ruby/io/buffer.h" +#include "ruby/thread.h" #include "ruby/util.h" +#include "ruby_atomic.h" +#include "ruby/ractor.h" + +#if !USE_POLL +# include "vm_core.h" +#endif + +#include "builtin.h" #ifndef O_ACCMODE #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) @@ -159,19 +182,6 @@ off_t __syscall(quad_t number, ...); #define rename(f, t) rb_w32_urename((f), (t)) #endif -#if defined(_WIN32) -# define RUBY_PIPE_NONBLOCK_DEFAULT (0) -#elif defined(O_NONBLOCK) - /* disabled for [Bug #15356] (Rack::Deflater + rails) failure: */ -# define RUBY_PIPE_NONBLOCK_DEFAULT (0) -#else /* any platforms where O_NONBLOCK does not exist? */ -# define RUBY_PIPE_NONBLOCK_DEFAULT (0) -#endif - -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - VALUE rb_cIO; VALUE rb_eEOFError; VALUE rb_eIOError; @@ -195,7 +205,7 @@ VALUE rb_default_rs; static VALUE argf; -static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding; +static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno; static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args; static VALUE sym_textmode, sym_binmode, sym_autoclose; static VALUE sym_SET, sym_CUR, sym_END; @@ -207,6 +217,8 @@ static VALUE sym_DATA; static VALUE sym_HOLE; #endif +static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path); + struct argf { VALUE filename, current_file; long last_lineno; /* $. */ @@ -292,19 +304,38 @@ rb_fix_detect_o_cloexec(int fd) return 0; } +static inline bool +io_again_p(int e) +{ + return (e == EWOULDBLOCK) || (e == EAGAIN); +} + int rb_cloexec_open(const char *pathname, int flags, mode_t mode) { int ret; static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ + static const int retry_interval = 0; + static const int retry_max_count = 10000; + + int retry_count = 0; + #ifdef O_CLOEXEC /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */ flags |= O_CLOEXEC; #elif defined O_NOINHERIT flags |= O_NOINHERIT; #endif - ret = open(pathname, flags, mode); + + while ((ret = open(pathname, flags, mode)) == -1) { + int e = errno; + if (!io_again_p(e)) break; + if (retry_count++ >= retry_max_count) break; + + sleep(retry_interval); + } + if (ret < 0) return ret; if (ret <= 2 || o_cloexec_state == 0) { rb_maygvl_fd_fix_cloexec(ret); @@ -379,44 +410,37 @@ rb_fd_set_nonblock(int fd) } int -rb_cloexec_pipe(int fildes[2]) +rb_cloexec_pipe(int descriptors[2]) { - int ret; - -#if defined(HAVE_PIPE2) - static int try_pipe2 = 1; - if (try_pipe2) { - ret = pipe2(fildes, O_CLOEXEC | RUBY_PIPE_NONBLOCK_DEFAULT); - if (ret != -1) - return ret; - /* pipe2 is available since Linux 2.6.27, glibc 2.9. */ - if (errno == ENOSYS) { - try_pipe2 = 0; - ret = pipe(fildes); - } - } - else { - ret = pipe(fildes); - } +#ifdef HAVE_PIPE2 + int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK); #else - ret = pipe(fildes); + int result = pipe(descriptors); #endif - if (ret < 0) return ret; + + if (result < 0) + return result; + #ifdef __CYGWIN__ - if (ret == 0 && fildes[1] == -1) { - close(fildes[0]); - fildes[0] = -1; - errno = ENFILE; - return -1; + if (result == 0 && descriptors[1] == -1) { + close(descriptors[0]); + descriptors[0] = -1; + errno = ENFILE; + return -1; } #endif - rb_maygvl_fd_fix_cloexec(fildes[0]); - rb_maygvl_fd_fix_cloexec(fildes[1]); - if (RUBY_PIPE_NONBLOCK_DEFAULT) { - rb_fd_set_nonblock(fildes[0]); - rb_fd_set_nonblock(fildes[1]); - } - return ret; + +#ifndef HAVE_PIPE2 + rb_maygvl_fd_fix_cloexec(descriptors[0]); + rb_maygvl_fd_fix_cloexec(descriptors[1]); + +#ifndef _WIN32 + rb_fd_set_nonblock(descriptors[0]); + rb_fd_set_nonblock(descriptors[1]); +#endif +#endif + + return result; } int @@ -446,7 +470,7 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd) } #elif defined(HAVE_FCNTL) && defined(F_DUPFD) ret = fcntl(fd, F_DUPFD, minfd); -#elif defined(HAVE_DUP) +#else ret = dup(fd); if (ret >= 0 && ret < minfd) { const int prev_fd = ret; @@ -454,8 +478,6 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd) close(prev_fd); } return ret; -#else -# error "dup() or fcntl(F_DUPFD) must be supported." #endif if (ret < 0) return ret; rb_maygvl_fd_fix_cloexec(ret); @@ -478,15 +500,15 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd) #if defined(_WIN32) #define WAIT_FD_IN_WIN32(fptr) \ - (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd)) + (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil)) #else #define WAIT_FD_IN_WIN32(fptr) #endif #define READ_CHECK(fptr) do {\ if (!READ_DATA_PENDING(fptr)) {\ - WAIT_FD_IN_WIN32(fptr);\ - rb_io_check_closed(fptr);\ + WAIT_FD_IN_WIN32(fptr);\ + rb_io_check_closed(fptr);\ }\ } while(0) @@ -507,9 +529,51 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd) static int io_fflush(rb_io_t *); static rb_io_t *flush_before_seek(rb_io_t *fptr); +#define FMODE_PREP (1<<16) +#define FMODE_SIGNAL_ON_EPIPE (1<<17) + +#define fptr_signal_on_epipe(fptr) \ + (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0) + +#define fptr_set_signal_on_epipe(fptr, flag) \ + ((flag) ? \ + (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \ + (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE) + +extern ID ruby_static_id_signo; + +NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)); +static void +raise_on_write(rb_io_t *fptr, int e, VALUE errinfo) +{ +#if defined EPIPE + if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) { + const VALUE sig = +# if defined SIGPIPE + INT2FIX(SIGPIPE) - INT2FIX(0) + +# endif + INT2FIX(0); + rb_ivar_set(errinfo, ruby_static_id_signo, sig); + } +#endif + rb_exc_raise(errinfo); +} + +#define rb_sys_fail_on_write(fptr) \ + do { \ + int e = errno; \ + raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \ + } while (0) + #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE) #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE) #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +# define RUBY_CRLF_ENVIRONMENT 1 +#else +# define RUBY_CRLF_ENVIRONMENT 0 +#endif + +#if RUBY_CRLF_ENVIRONMENT /* Windows */ # define DEFAULT_TEXTMODE FMODE_TEXTMODE # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR @@ -774,19 +838,14 @@ rb_io_set_write_io(VALUE io, VALUE w) /* * call-seq: - * IO.try_convert(obj) -> io or nil + * IO.try_convert(object) -> new_io or nil * - * Try to convert obj into an IO, using to_io method. - * Returns converted IO or +nil+ if obj cannot be converted - * for any reason. + * Attempts to convert +object+ into an \IO object via method +to_io+; + * returns the new \IO object if successful, or +nil+ otherwise: * - * IO.try_convert(STDOUT) #=> STDOUT - * IO.try_convert("STDOUT") #=> nil - * - * require 'zlib' - * f = open("/tmp/zz.gz") #=> # - * z = Zlib::GzipReader.open(f) #=> # - * IO.try_convert(z) #=> # + * IO.try_convert(STDOUT) # => #> + * IO.try_convert(ARGF) # => #> + * IO.try_convert('STDOUT') # => nil * */ static VALUE @@ -795,7 +854,7 @@ rb_io_s_try_convert(VALUE dummy, VALUE io) return rb_io_check_io(io); } -#if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)) +#if !RUBY_CRLF_ENVIRONMENT static void io_unread(rb_io_t *fptr) { @@ -856,7 +915,7 @@ static rb_io_t * flush_before_seek(rb_io_t *fptr) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); io_unread(fptr); errno = 0; return fptr; @@ -880,13 +939,13 @@ rb_io_check_char_readable(rb_io_t *fptr) } if (fptr->wbuf.len) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); } if (fptr->tied_io_for_writing) { rb_io_t *wfptr; GetOpenFile(fptr->tied_io_for_writing, wfptr); if (io_fflush(wfptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(wfptr); } } @@ -948,7 +1007,7 @@ void rb_io_read_check(rb_io_t *fptr) { if (!READ_DATA_PENDING(fptr)) { - rb_thread_wait_fd(fptr->fd); + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); } return; } @@ -997,7 +1056,8 @@ io_alloc(VALUE klass) #endif struct io_internal_read_struct { - int fd; + VALUE th; + rb_io_t *fptr; int nonblock; void *buf; size_t capa; @@ -1017,18 +1077,18 @@ struct io_internal_writev_struct { }; #endif -static int nogvl_wait_for_single_fd(int fd, short events); +static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events); static VALUE internal_read_func(void *ptr) { struct io_internal_read_struct *iis = ptr; ssize_t r; retry: - r = read(iis->fd, iis->buf, iis->capa); + r = read(iis->fptr->fd, iis->buf, iis->capa); if (r < 0 && !iis->nonblock) { int e = errno; - if (e == EAGAIN || e == EWOULDBLOCK) { - if (nogvl_wait_for_single_fd(iis->fd, RB_WAITFD_IN) != -1) { + if (io_again_p(e)) { + if (nogvl_wait_for(iis->th, iis->fptr, RB_WAITFD_IN) != -1) { goto retry; } errno = e; @@ -1069,51 +1129,74 @@ internal_writev_func(void *ptr) #endif static ssize_t -rb_read_internal(int fd, void *buf, size_t count) +rb_read_internal(rb_io_t *fptr, void *buf, size_t count) { - struct io_internal_read_struct iis; + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, fptr->self, buf, count, 0); - iis.fd = fd; - iis.nonblock = 0; - iis.buf = buf; - iis.capa = count; + if (result != Qundef) { + return rb_fiber_scheduler_io_result_apply(result); + } + } + + struct io_internal_read_struct iis = { + .th = rb_thread_current(), + .fptr = fptr, + .nonblock = 0, + .buf = buf, + .capa = count + }; - return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd); + return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->fd); } static ssize_t -rb_write_internal(int fd, const void *buf, size_t count) +rb_write_internal(rb_io_t *fptr, const void *buf, size_t count) { - struct io_internal_write_struct iis; - iis.fd = fd; - iis.buf = buf; - iis.capa = count; + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, buf, count, 0); - return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd); -} + if (result != Qundef) { + return rb_fiber_scheduler_io_result_apply(result); + } + } -static ssize_t -rb_write_internal2(int fd, const void *buf, size_t count) -{ - struct io_internal_write_struct iis; - iis.fd = fd; - iis.buf = buf; - iis.capa = count; + struct io_internal_write_struct iis = { + .fd = fptr->fd, + .buf = buf, + .capa = count + }; - return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis, - RUBY_UBF_IO, NULL); + if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock)) + return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis, RUBY_UBF_IO, NULL); + else + return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->fd); } #ifdef HAVE_WRITEV static ssize_t -rb_writev_internal(int fd, const struct iovec *iov, int iovcnt) +rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt) { - struct io_internal_writev_struct iis; - iis.fd = fd; - iis.iov = iov; - iis.iovcnt = iovcnt; + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + for (int i = 0; i < iovcnt; i += 1) { + VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[i].iov_base, iov[i].iov_len, 0); - return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd); + if (result != Qundef) { + return rb_fiber_scheduler_io_result_apply(result); + } + } + } + + struct io_internal_writev_struct iis = { + .fd = fptr->fd, + .iov = iov, + .iovcnt = iovcnt, + }; + + return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->fd); } #endif @@ -1162,8 +1245,7 @@ io_flush_buffer_async2(VALUE arg) rb_io_t *fptr = (rb_io_t *)arg; VALUE ret; - ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr, - RUBY_UBF_IO, NULL); + ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr, RUBY_UBF_IO, NULL); if (!ret) { /* pending async interrupt is there. */ @@ -1194,37 +1276,108 @@ static int io_fflush(rb_io_t *fptr) { rb_io_check_closed(fptr); + if (fptr->wbuf.len == 0) return 0; + while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) { - if (!rb_io_wait_writable(fptr->fd)) - return -1; + if (!rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) + return -1; + rb_io_check_closed(fptr); } + return 0; } +VALUE +rb_io_wait(VALUE io, VALUE events, VALUE timeout) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + + if (scheduler != Qnil) { + return rb_fiber_scheduler_io_wait(scheduler, io, events, timeout); + } + + rb_io_t * fptr = NULL; + RB_IO_POINTER(io, fptr); + + struct timeval tv_storage; + struct timeval *tv = NULL; + + if (timeout != Qnil) { + tv_storage = rb_time_interval(timeout); + tv = &tv_storage; + } + + int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv); + + if (ready < 0) { + rb_sys_fail(0); + } + + // Not sure if this is necessary: + rb_io_check_closed(fptr); + + if (ready) { + return RB_INT2NUM(ready); + } + else { + return Qfalse; + } +} + +static VALUE +io_from_fd(int fd) +{ + return prep_io(fd, FMODE_PREP, rb_cIO, NULL); +} + +static int +io_wait_for_single_fd(int fd, int events, struct timeval *timeout) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + + if (scheduler != Qnil) { + return RTEST( + rb_fiber_scheduler_io_wait(scheduler, io_from_fd(fd), RB_INT2NUM(events), rb_fiber_scheduler_make_timeout(timeout)) + ); + } + + return rb_thread_wait_for_single_fd(fd, events, timeout); +} + int rb_io_wait_readable(int f) { io_fd_check_closed(f); + + VALUE scheduler = rb_fiber_scheduler_current(); + switch (errno) { case EINTR: #if defined(ERESTART) case ERESTART: #endif - rb_thread_check_ints(); - return TRUE; + rb_thread_check_ints(); + return TRUE; case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +#if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif - rb_thread_wait_fd(f); - return TRUE; + if (scheduler != Qnil) { + return RTEST( + rb_fiber_scheduler_io_wait_readable(scheduler, io_from_fd(f)) + ); + } + else { + io_wait_for_single_fd(f, RUBY_IO_READABLE, NULL); + } + return TRUE; default: - return FALSE; + return FALSE; } } @@ -1232,32 +1385,127 @@ int rb_io_wait_writable(int f) { io_fd_check_closed(f); + + VALUE scheduler = rb_fiber_scheduler_current(); + switch (errno) { case EINTR: #if defined(ERESTART) case ERESTART: #endif - /* - * In old Linux, several special files under /proc and /sys don't handle - * select properly. Thus we need avoid to call if don't use O_NONBLOCK. - * Otherwise, we face nasty hang up. Sigh. - * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 - * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 - * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING(). - * Then rb_thread_check_ints() is enough. - */ - rb_thread_check_ints(); - return TRUE; + /* + * In old Linux, several special files under /proc and /sys don't handle + * select properly. Thus we need avoid to call if don't use O_NONBLOCK. + * Otherwise, we face nasty hang up. Sigh. + * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 + * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 + * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING(). + * Then rb_thread_check_ints() is enough. + */ + rb_thread_check_ints(); + return TRUE; case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +#if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif - rb_thread_fd_writable(f); - return TRUE; + if (scheduler != Qnil) { + return RTEST( + rb_fiber_scheduler_io_wait_writable(scheduler, io_from_fd(f)) + ); + } + else { + io_wait_for_single_fd(f, RUBY_IO_WRITABLE, NULL); + } + return TRUE; default: - return FALSE; + return FALSE; + } +} + +int +rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) +{ + return io_wait_for_single_fd(fd, events, timeout); +} + +int +rb_thread_wait_fd(int fd) +{ + return rb_wait_for_single_fd(fd, RUBY_IO_READABLE, NULL); +} + +int +rb_thread_fd_writable(int fd) +{ + return rb_wait_for_single_fd(fd, RUBY_IO_WRITABLE, NULL); +} + +VALUE +rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout) +{ + // fptr->fd can be set to -1 at any time by another thread when the GVL is + // released. Many code, e.g. `io_bufread` didn't check this correctly and + // instead relies on `read(-1) -> -1` which causes this code path. We then + // check here whether the IO was in fact closed. Probably it's better to + // check that `fptr->fd != -1` before using it in syscall. + rb_io_check_closed(RFILE(io)->fptr); + + switch (error) { + // In old Linux, several special files under /proc and /sys don't handle + // select properly. Thus we need avoid to call if don't use O_NONBLOCK. + // Otherwise, we face nasty hang up. Sigh. + // e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 + // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8 + // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING(). + // Then rb_thread_check_ints() is enough. + case EINTR: +#if defined(ERESTART) + case ERESTART: +#endif + // We might have pending interrupts since the previous syscall was interrupted: + rb_thread_check_ints(); + + // The operation was interrupted, so retry it immediately: + return events; + + case EAGAIN: +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + // The operation would block, so wait for the specified events: + return rb_io_wait(io, events, timeout); + + default: + // Non-specific error, no event is ready: + return Qfalse; + } +} + +int +rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout) +{ + VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_READABLE), timeout); + + if (RTEST(result)) { + return RB_NUM2INT(result); + } + else { + return 0; + } +} + +int +rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout) +{ + VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_WRITABLE), timeout); + + if (RTEST(result)) { + return RB_NUM2INT(result); + } + else { + return 0; } } @@ -1346,7 +1594,7 @@ io_binwrite_string(VALUE arg) iov[1].iov_base = (char *)p->ptr; iov[1].iov_len = p->length; - r = rb_writev_internal(fptr->fd, iov, 2); + r = rb_writev_internal(fptr, iov, 2); if (r < 0) return r; @@ -1363,7 +1611,7 @@ io_binwrite_string(VALUE arg) } } else { - r = rb_write_internal(fptr->fd, p->ptr, p->length); + r = rb_write_internal(fptr, p->ptr, p->length); } return r; @@ -1394,10 +1642,7 @@ io_binwrite_string(VALUE arg) return len; } - if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) - rb_io_check_closed(fptr); - - return rb_write_internal(p->fptr->fd, p->ptr, p->length); + return rb_write_internal(p->fptr, p->ptr, p->length); } #endif @@ -1410,43 +1655,50 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync) rb_thread_check_ints(); if ((n = len) <= 0) return n; + if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) { fptr->wbuf.off = 0; fptr->wbuf.len = 0; fptr->wbuf.capa = IO_WBUF_CAPA_MIN; fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa); - fptr->write_lock = rb_mutex_new(); - rb_mutex_allow_trap(fptr->write_lock, 1); + fptr->write_lock = rb_mutex_new(); + rb_mutex_allow_trap(fptr->write_lock, 1); } + if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) || (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) { - struct binwrite_arg arg; + struct binwrite_arg arg; - arg.fptr = fptr; - arg.str = str; + arg.fptr = fptr; + arg.str = str; retry: - arg.ptr = ptr + offset; - arg.length = n; - if (fptr->write_lock) { - r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg); - } - else { - r = io_binwrite_string((VALUE)&arg); - } - /* xxx: other threads may modify given string. */ + arg.ptr = ptr + offset; + arg.length = n; + + if (fptr->write_lock) { + r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg); + } + else { + r = io_binwrite_string((VALUE)&arg); + } + + /* xxx: other threads may modify given string. */ if (r == n) return len; if (0 <= r) { offset += r; n -= r; errno = EAGAIN; - } - if (r == -2L) - return -1L; - if (rb_io_wait_writable(fptr->fd)) { + } + + if (r == -2L) + return -1L; + if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) { rb_io_check_closed(fptr); - if (offset < len) - goto retry; + + if (offset < len) + goto retry; } + return -1L; } @@ -1455,8 +1707,10 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync) MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len); fptr->wbuf.off = 0; } + MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len); fptr->wbuf.len += (int)len; + return len; } @@ -1504,7 +1758,7 @@ do_writeconv(VALUE str, rb_io_t *fptr, int *converted) *converted = 1; } } -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT #define fmode (fptr->mode) else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) { if ((fptr->mode & FMODE_READABLE) && @@ -1580,7 +1834,7 @@ io_write(VALUE io, VALUE str, int nosync) rb_io_check_writable(fptr); n = io_fwrite(str, fptr, nosync); - if (n < 0L) rb_sys_fail_path(fptr->pathv); + if (n < 0L) rb_sys_fail_on_write(fptr); return LONG2FIX(n); } @@ -1596,7 +1850,7 @@ static VALUE call_writev_internal(VALUE arg) { struct binwritev_arg *p = (struct binwritev_arg *)arg; - return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt); + return rb_writev_internal(p->fptr, p->iov, p->iovcnt); } static long @@ -1649,7 +1903,7 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr) r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg); } else { - r = rb_writev_internal(fptr->fd, iov, iovcnt); + r = rb_writev_internal(fptr, iov, iovcnt); } if (r >= 0) { @@ -1680,7 +1934,7 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr) errno = EAGAIN; } - if (rb_io_wait_writable(fptr->fd)) { + if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) { rb_io_check_closed(fptr); goto retry; } @@ -1689,7 +1943,7 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr) } static long -io_fwritev(int argc, VALUE *argv, rb_io_t *fptr) +io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr) { int i, converted, iovcnt = argc + 1; long n; @@ -1737,7 +1991,7 @@ iovcnt_ok(int iovcnt) #endif /* HAVE_WRITEV */ static VALUE -io_writev(int argc, VALUE *argv, VALUE io) +io_writev(int argc, const VALUE *argv, VALUE io) { rb_io_t *fptr; long n; @@ -1767,7 +2021,7 @@ io_writev(int argc, VALUE *argv, VALUE io) /* sync at last item */ n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1)); } - if (n < 0L) rb_sys_fail_path(fptr->pathv); + if (n < 0L) rb_sys_fail_on_write(fptr); total = rb_fix_plus(LONG2FIX(n), total); } @@ -1776,20 +2030,21 @@ io_writev(int argc, VALUE *argv, VALUE io) /* * call-seq: - * ios.write(string, ...) -> integer + * write(*objects) -> integer * - * Writes the given strings to ios. The stream must be opened - * for writing. Arguments that are not a string will be converted - * to a string using to_s. Returns the number of bytes - * written in total. + * Writes each of the given +objects+ to +self+, + * which must be opened for writing (see {Modes}[#class-IO-label-Modes]); + * returns the total number bytes written; + * each of +objects+ that is not a string is converted via method +to_s+: * - * count = $stdout.write("This is", " a test\n") - * puts "That was #{count} bytes of data" + * $stdout.write('Hello', ', ', 'World!', "\n") # => 14 + * $stdout.write('foo', :bar, 2, "\n") # => 8 * - * produces: + * Output: + * + * Hello, World! + * foobar2 * - * This is a test - * That was 15 bytes of data */ static VALUE @@ -1811,13 +2066,13 @@ rb_io_write(VALUE io, VALUE str) } static VALUE -rb_io_writev(VALUE io, int argc, VALUE *argv) +rb_io_writev(VALUE io, int argc, const VALUE *argv) { if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) { - if (io != rb_stderr && RTEST(ruby_verbose)) { + if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) { VALUE klass = CLASS_OF(io); char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#'; - rb_warning("%+"PRIsVALUE"%c""write is outdated interface" + rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface" " which accepts just one argument", klass, sep); } @@ -1829,17 +2084,21 @@ rb_io_writev(VALUE io, int argc, VALUE *argv) /* * call-seq: - * ios << obj -> ios + * self << object -> self * - * String Output---Writes obj to ios. - * obj will be converted to a string using - * to_s. + * Writes the given +object+ to +self+, + * which must be opened for writing (see {Modes}[#class-IO-label-Modes]); + * returns +self+; + * if +object+ is not a string, it is converted via method +to_s+: * - * $stdout << "Hello " << "world!\n" + * $stdout << 'Hello' << ', ' << 'World!' << "\n" + * $stdout << 'foo' << :bar << 2 << "\n" * - * produces: + * Output: + * + * Hello, World! + * foobar2 * - * Hello world! */ @@ -1878,7 +2137,7 @@ rb_io_flush_raw(VALUE io, int sync) if (fptr->mode & FMODE_WRITABLE) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); } if (fptr->mode & FMODE_READABLE) { io_unread(fptr); @@ -1889,18 +2148,14 @@ rb_io_flush_raw(VALUE io, int sync) /* * call-seq: - * ios.flush -> ios - * - * Flushes any buffered data within ios to the underlying - * operating system (note that this is Ruby internal buffering only; - * the OS may buffer the data as well). + * flush -> self * - * $stdout.print "no newline" - * $stdout.flush + * Flushes data buffered in +self+ to the operating system + * (but does not necessarily flush data buffered in the operating system): * - * produces: + * $stdout.print 'no newline' # Not necessarily flushed. + * $stdout.flush # Flushed. * - * no newline */ VALUE @@ -1911,15 +2166,20 @@ rb_io_flush(VALUE io) /* * call-seq: - * ios.pos -> integer - * ios.tell -> integer + * tell -> integer * - * Returns the current offset (in bytes) of ios. + * Returns the current position (in bytes) in +self+ + * (see {Position}[#class-IO-label-Position]): + * + * f = File.new('t.txt') + * f.tell # => 0 + * f.readline # => "This is line one.\n" + * f.tell # => 19 + * + * Related: IO#pos=, IO#seek. + * + * IO#pos is an alias for IO#tell. * - * f = File.new("testfile") - * f.pos #=> 0 - * f.gets #=> "This is line one\n" - * f.pos #=> 17 */ static VALUE @@ -1971,23 +2231,46 @@ interpret_seek_whence(VALUE vwhence) /* * call-seq: - * ios.seek(amount, whence=IO::SEEK_SET) -> 0 + * seek(offset, whence = IO::SEEK_SET) -> 0 * - * Seeks to a given offset anInteger in the stream according to - * the value of whence: + * Seeks to the position given by integer +offset+ + * (see {Position}[#class-IO-label-Position]) + * and constant +whence+, which is one of: * - * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position - * ----------------------+-------------------------------------------------- - * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you - * | probably want a negative value for _amount_) - * ----------------------+-------------------------------------------------- - * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_ + * - +:CUR+ or IO::SEEK_CUR: + * Repositions the stream to its current position plus the given +offset+: * - * Example: + * f = File.open('t.txt') + * f.tell # => 0 + * f.seek(20, :CUR) # => 0 + * f.tell # => 20 + * f.seek(-10, :CUR) # => 0 + * f.tell # => 10 + * + * - +:END+ or IO::SEEK_END: + * Repositions the stream to its end plus the given +offset+: + * + * f = File.open('t.txt') + * f.tell # => 0 + * f.seek(0, :END) # => 0 # Repositions to stream end. + * f.tell # => 70 + * f.seek(-20, :END) # => 0 + * f.tell # => 50 + * f.seek(-40, :END) # => 0 + * f.tell # => 30 + * + * - +:SET+ or IO:SEEK_SET: + * Repositions the stream to the given +offset+: + * + * f = File.open('t.txt') + * f.tell # => 0 + * f.seek(20, :SET) # => 0 + * f.tell # => 20 + * f.seek(40, :SET) # => 0 + * f.tell # => 40 + * + * Related: IO#pos=, IO#tell. * - * f = File.new("testfile") - * f.seek(-13, IO::SEEK_END) #=> 0 - * f.readline #=> "And so on...\n" */ static VALUE @@ -2005,15 +2288,18 @@ rb_io_seek_m(int argc, VALUE *argv, VALUE io) /* * call-seq: - * ios.pos = integer -> integer + * pos = new_position -> new_position * - * Seeks to the given position (in bytes) in ios. - * It is not guaranteed that seeking to the right position when ios - * is textmode. + * Seeks to the given +new_position+ (in bytes); + * see {Position}[#class-IO-label-Position]: + * + * f = File.open('t.txt') + * f.tell # => 0 + * f.pos = 20 # => 20 + * f.tell # => 20 + * + * Related: IO#seek, IO#tell. * - * f = File.new("testfile") - * f.pos = 17 - * f.gets #=> "This is line two\n" */ static VALUE @@ -2034,18 +2320,25 @@ static void clear_readconv(rb_io_t *fptr); /* * call-seq: - * ios.rewind -> 0 + * rewind -> 0 * - * Positions ios to the beginning of input, resetting - * #lineno to zero. + * Repositions the stream to its beginning, + * setting both the position and the line number to zero; + * see {Position}[#class-IO-label-Position] + * and {Line Number}[#class-IO-label-Line+Number]: * - * f = File.new("testfile") - * f.readline #=> "This is line one\n" - * f.rewind #=> 0 - * f.lineno #=> 0 - * f.readline #=> "This is line one\n" + * f = File.open('t.txt') + * f.tell # => 0 + * f.lineno # => 0 + * f.readline # => "This is line one.\n" + * f.tell # => 19 + * f.lineno # => 1 + * f.rewind # => 0 + * f.tell # => 0 + * f.lineno # => 0 + * + * Note that this method cannot be used with streams such as pipes, ttys, and sockets. * - * Note that it cannot be used with streams such as pipes, ttys, and sockets. */ static VALUE @@ -2069,10 +2362,11 @@ rb_io_rewind(VALUE io) static int fptr_wait_readable(rb_io_t *fptr) { - int ret = rb_io_wait_readable(fptr->fd); + int ret = rb_io_maybe_wait_readable(errno, fptr->self, Qnil); if (ret) rb_io_check_closed(fptr); + return ret; } @@ -2087,27 +2381,26 @@ io_fillbuf(rb_io_t *fptr) fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr); fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa); #ifdef _WIN32 - fptr->rbuf.capa--; + fptr->rbuf.capa--; #endif } if (fptr->rbuf.len == 0) { retry: - { - r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa); - } + r = rb_read_internal(fptr, fptr->rbuf.ptr, fptr->rbuf.capa); + if (r < 0) { if (fptr_wait_readable(fptr)) goto retry; - { - int e = errno; - VALUE path = rb_sprintf("fd:%d ", fptr->fd); - if (!NIL_P(fptr->pathv)) { - rb_str_append(path, fptr->pathv); - } - rb_syserr_fail_path(e, path); - } + + int e = errno; + VALUE path = rb_sprintf("fd:%d ", fptr->fd); + if (!NIL_P(fptr->pathv)) { + rb_str_append(path, fptr->pathv); + } + + rb_syserr_fail_path(e, path); } - if (r > 0) rb_io_check_closed(fptr); + if (r > 0) rb_io_check_closed(fptr); fptr->rbuf.off = 0; fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */ if (r == 0) @@ -2118,35 +2411,39 @@ io_fillbuf(rb_io_t *fptr) /* * call-seq: - * ios.eof -> true or false - * ios.eof? -> true or false + * eof -> true or false * - * Returns true if ios is at end of file that means - * there are no more data to read. - * The stream must be opened for reading or an IOError will be - * raised. + * Returns +true+ if the stream is positioned at its end, +false+ otherwise; + * see {Position}[#class-IO-label-Position]: * - * f = File.new("testfile") - * dummy = f.readlines - * f.eof #=> true + * f = File.open('t.txt') + * f.eof # => false + * f.seek(0, :END) # => 0 + * f.eof # => true + * + * Raises an exception unless the stream is opened for reading; + * see {Mode}[#class-IO-label-Mode]. * - * If ios is a stream such as pipe or socket, IO#eof? - * blocks until the other end sends some data or closes it. + * If +self+ is a stream such as pipe or socket, this method + * blocks until the other end sends some data or closes it: * - * r, w = IO.pipe - * Thread.new { sleep 1; w.close } - * r.eof? #=> true after 1 second blocking + * r, w = IO.pipe + * Thread.new { sleep 1; w.close } + * r.eof? # => true # After 1-second wait. * - * r, w = IO.pipe - * Thread.new { sleep 1; w.puts "a" } - * r.eof? #=> false after 1 second blocking + * r, w = IO.pipe + * Thread.new { sleep 1; w.puts "a" } + * r.eof? # => false # After 1-second wait. * - * r, w = IO.pipe - * r.eof? # blocks forever + * r, w = IO.pipe + * r.eof? # blocks forever * - * Note that IO#eof? reads data to the input byte buffer. So + * Note that this method reads data to the input byte buffer. So * IO#sysread may not behave as you intend with IO#eof?, unless you * call IO#rewind first (which is not available for some streams). + * + * I#eof? is an alias for IO#eof. + * */ VALUE @@ -2160,28 +2457,27 @@ rb_io_eof(VALUE io) if (READ_CHAR_PENDING(fptr)) return Qfalse; if (READ_DATA_PENDING(fptr)) return Qfalse; READ_CHECK(fptr); -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) { - return eof(fptr->fd) ? Qtrue : Qfalse; + return RBOOL(eof(fptr->fd));; } #endif - if (io_fillbuf(fptr) < 0) { - return Qtrue; - } - return Qfalse; + return RBOOL(io_fillbuf(fptr) < 0); } /* * call-seq: - * ios.sync -> true or false + * sync -> true or false * - * Returns the current ``sync mode'' of ios. When sync mode is - * true, all output is immediately flushed to the underlying operating - * system and is not buffered by Ruby internally. See also - * IO#fsync. + * Returns the current sync mode of the stream. + * When sync mode is true, all output is immediately flushed to the underlying + * operating system and is not buffered by Ruby internally. See also #fsync. + * + * f = File.open('t.tmp', 'w') + * f.sync # => false + * f.sync = true + * f.sync # => true * - * f = File.new("testfile") - * f.sync #=> false */ static VALUE @@ -2191,22 +2487,33 @@ rb_io_sync(VALUE io) io = GetWriteIO(io); GetOpenFile(io, fptr); - return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse; + return RBOOL(fptr->mode & FMODE_SYNC); } #ifdef HAVE_FSYNC /* * call-seq: - * ios.sync = boolean -> boolean + * sync = boolean -> boolean * - * Sets the ``sync mode'' to true or false. - * When sync mode is true, all output is immediately flushed to the - * underlying operating system and is not buffered internally. Returns - * the new state. See also IO#fsync. + * Sets the _sync_ _mode_ for the stream to the given value; + * returns the given value. + * + * Values for the sync mode: + * + * - +true+: All output is immediately flushed to the + * underlying operating system and is not buffered internally. + * - +false+: Output may be buffered internally. + * + * Example; + * + * f = File.open('t.tmp', 'w') + * f.sync # => false + * f.sync = true + * f.sync # => true + * + * Related: IO#fsync. * - * f = File.new("testfile") - * f.sync = true */ static VALUE @@ -2227,15 +2534,20 @@ rb_io_set_sync(VALUE io, VALUE sync) /* * call-seq: - * ios.fsync -> 0 or nil + * fsync -> 0 + * + * Immediately writes to disk all data buffered in the stream, + * via the operating system's fsync(2). + + * Note this difference: + * + * - IO#sync=: Ensures that data is flushed from the stream's internal buffers, + * but does not guarantee that the operating system actually writes the data to disk. + * - IO#fsync: Ensures both that data is flushed from internal buffers, + * and that data is written to disk. * - * Immediately writes all buffered data in ios to disk. - * Note that #fsync differs from using IO#sync=. The latter ensures - * that data is flushed from Ruby's buffers, but does not guarantee - * that the underlying operating system actually writes it to disk. + * Raises an exception if the operating system does not support fsync(2). * - * NotImplementedError is raised - * if the underlying operating system does not support fsync(2). */ static VALUE @@ -2247,7 +2559,7 @@ rb_io_fsync(VALUE io) GetOpenFile(io, fptr); if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0) rb_sys_fail_path(fptr->pathv); return INT2FIX(0); @@ -2278,13 +2590,13 @@ nogvl_fdatasync(void *ptr) /* * call-seq: - * ios.fdatasync -> 0 or nil + * fdatasync -> 0 * - * Immediately writes all buffered data in ios to disk. + * Immediately writes to disk all data buffered in the stream, + * via the operating system's: fdatasync(2), if supported, + * otherwise via fsync(2), if supported; + * otherwise raises an exception. * - * If the underlying operating system does not support fdatasync(2), - * IO#fsync is called instead (which might raise a - * NotImplementedError). */ static VALUE @@ -2296,7 +2608,7 @@ rb_io_fdatasync(VALUE io) GetOpenFile(io, fptr); if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0) return INT2FIX(0); @@ -2310,14 +2622,17 @@ rb_io_fdatasync(VALUE io) /* * call-seq: - * ios.fileno -> integer - * ios.to_i -> integer + * fileno -> integer * - * Returns an integer representing the numeric file descriptor for - * ios. + * Returns the integer file descriptor for the stream: + * + * $stdin.fileno # => 0 + * $stdout.fileno # => 1 + * $stderr.fileno # => 2 + * File.open('t.txt').fileno # => 10 + * + * IO#to_i is an alias for IO#fileno. * - * $stdin.fileno #=> 0 - * $stdout.fileno #=> 1 */ static VALUE @@ -2331,25 +2646,39 @@ rb_io_fileno(VALUE io) return INT2FIX(fd); } +int +rb_io_descriptor(VALUE io) +{ + if (RB_TYPE_P(io, T_FILE)) { + rb_io_t *fptr = RFILE(io)->fptr; + rb_io_check_closed(fptr); + return fptr->fd; + } + else { + return RB_NUM2INT(rb_funcall(io, id_fileno, 0)); + } +} /* * call-seq: - * ios.pid -> integer + * pid -> integer or nil * - * Returns the process ID of a child process associated with - * ios. This will be set by IO.popen. + * Returns the process ID of a child process associated with the stream, + * which will have been set by IO#popen, or +nil+ if the stream was not + * created by IO#popen: * - * pipe = IO.popen("-") - * if pipe - * $stderr.puts "In parent, child pid is #{pipe.pid}" - * else - * $stderr.puts "In child, pid is #{$$}" - * end + * pipe = IO.popen("-") + * if pipe + * $stderr.puts "In parent, child pid is #{pipe.pid}" + * else + * $stderr.puts "In child, pid is #{$$}" + * end * - * produces: + * Output: + * + * In child, pid is 26209 + * In parent, child pid is 26209 * - * In child, pid is 26209 - * In parent, child pid is 26209 */ static VALUE @@ -2365,10 +2694,14 @@ rb_io_pid(VALUE io) /* - * call-seq: - * ios.inspect -> string + * call-seq: + * inspect -> string + * + * Returns a string representation of +self+: + * + * f = File.open('t.txt') + * f.inspect # => "#" * - * Return a string describing this IO object. */ static VALUE @@ -2402,9 +2735,10 @@ rb_io_inspect(VALUE obj) /* * call-seq: - * ios.to_io -> ios + * to_io -> self + * + * Returns +self+. * - * Returns ios. */ static VALUE @@ -2436,31 +2770,32 @@ io_bufread(char *ptr, long len, rb_io_t *fptr) long c; if (READ_DATA_PENDING(fptr) == 0) { - while (n > 0) { + while (n > 0) { again: - c = rb_read_internal(fptr->fd, ptr+offset, n); - if (c == 0) break; - if (c < 0) { + rb_io_check_closed(fptr); + c = rb_read_internal(fptr, ptr+offset, n); + if (c == 0) break; + if (c < 0) { if (fptr_wait_readable(fptr)) goto again; - return -1; - } - offset += c; - if ((n -= c) <= 0) break; - } - return len - n; + return -1; + } + offset += c; + if ((n -= c) <= 0) break; + } + return len - n; } while (n > 0) { - c = read_buffered_data(ptr+offset, n, fptr); - if (c > 0) { - offset += c; - if ((n -= c) <= 0) break; - } - rb_io_check_closed(fptr); - if (io_fillbuf(fptr) < 0) { - break; - } + c = read_buffered_data(ptr+offset, n, fptr); + if (c > 0) { + offset += c; + if ((n -= c) <= 0) break; + } + rb_io_check_closed(fptr); + if (io_fillbuf(fptr) < 0) { + break; + } } return len - n; } @@ -2511,7 +2846,7 @@ remain_size(rb_io_t *fptr) ) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); pos = lseek(fptr->fd, 0, SEEK_CUR); if (st.st_size >= pos && pos >= 0) { siz += st.st_size - pos; @@ -2795,7 +3130,17 @@ read_internal_call(VALUE arg) { struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg; - return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd); + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, iis->fptr->self, iis->buf, iis->capa, 0); + + if (result != Qundef) { + // This is actually returned as a pseudo-VALUE and later cast to a long: + return (VALUE)rb_fiber_scheduler_io_result_apply(result); + } + } + + return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->fd); } static long @@ -2826,8 +3171,10 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock) GetOpenFile(io, fptr); rb_io_check_byte_readable(fptr); - if (len == 0) + if (len == 0) { + io_set_read_length(str, 0, shrinkable); return str; + } if (!nonblock) READ_CHECK(fptr); @@ -2838,7 +3185,8 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock) rb_io_set_nonblock(fptr); } io_setstrbuf(&str, len); - iis.fd = fptr->fd; + iis.th = rb_thread_current(); + iis.fptr = fptr; iis.nonblock = nonblock; iis.buf = RSTRING_PTR(str); iis.capa = len; @@ -2847,7 +3195,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock) int e = errno; if (!nonblock && fptr_wait_readable(fptr)) goto again; - if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) { + if (nonblock && (io_again_p(e))) { if (no_exception) return sym_wait_readable; else @@ -2867,67 +3215,93 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock) /* * call-seq: - * ios.readpartial(maxlen) -> string - * ios.readpartial(maxlen, outbuf) -> outbuf + * readpartial(maxlen) -> string + * readpartial(maxlen, out_string) -> out_string * - * Reads at most maxlen bytes from the I/O stream. - * It blocks only if ios has no data immediately available. - * It doesn't block if some data available. + * Reads up to +maxlen+ bytes from the stream; + * returns a string (either a new string or the given +out_string+). + * Its encoding is: * - * If the optional _outbuf_ argument is present, - * it must reference a String, which will receive the data. - * The _outbuf_ will contain only the received data after the method call - * even if it is not empty at the beginning. + * - The unchanged encoding of +out_string+, if +out_string+ is given. + * - ASCII-8BIT, otherwise. * - * It raises EOFError on end of file. - * - * readpartial is designed for streams such as pipe, socket, tty, etc. - * It blocks only when no data immediately available. - * This means that it blocks only when following all conditions hold. - * * the byte buffer in the IO object is empty. - * * the content of the stream is empty. - * * the stream is not reached to EOF. - * - * When readpartial blocks, it waits data or EOF on the stream. - * If some data is reached, readpartial returns with the data. - * If EOF is reached, readpartial raises EOFError. - * - * When readpartial doesn't blocks, it returns or raises immediately. - * If the byte buffer is not empty, it returns the data in the buffer. - * Otherwise if the stream has some content, - * it returns the data in the stream. - * Otherwise if the stream is reached to EOF, it raises EOFError. - * - * r, w = IO.pipe # buffer pipe content - * w << "abc" # "" "abc". - * r.readpartial(4096) #=> "abc" "" "" - * r.readpartial(4096) # blocks because buffer and pipe is empty. - * - * r, w = IO.pipe # buffer pipe content - * w << "abc" # "" "abc" - * w.close # "" "abc" EOF - * r.readpartial(4096) #=> "abc" "" EOF - * r.readpartial(4096) # raises EOFError + * - Contains +maxlen+ bytes from the stream, if available. + * - Otherwise contains all available bytes, if any available. + * - Otherwise is an empty string. + * + * With the single non-negative integer argument +maxlen+ given, + * returns a new string: + * + * f = File.new('t.txt') + * f.readpartial(30) # => "This is line one.\nThis is the" + * f.readpartial(30) # => " second line.\nThis is the thi" + * f.readpartial(30) # => "rd line.\n" + * f.eof # => true + * f.readpartial(30) # Raises EOFError. + * + * With both argument +maxlen+ and string argument +out_string+ given, + * returns modified +out_string+: + * + * f = File.new('t.txt') + * s = 'foo' + * f.readpartial(30, s) # => "This is line one.\nThis is the" + * s = 'bar' + * f.readpartial(0, s) # => "" * - * r, w = IO.pipe # buffer pipe content - * w << "abc\ndef\n" # "" "abc\ndef\n" - * r.gets #=> "abc\n" "def\n" "" - * w << "ghi\n" # "def\n" "ghi\n" - * r.readpartial(4096) #=> "def\n" "" "ghi\n" - * r.readpartial(4096) #=> "ghi\n" "" "" + * This method is useful for a stream such as a pipe, a socket, or a tty. + * It blocks only when no data is immediately available. + * This means that it blocks only when _all_ of the following are true: * - * Note that readpartial behaves similar to sysread. - * The differences are: - * * If the byte buffer is not empty, read from the byte buffer + * - The byte buffer in the stream is empty. + * - The content of the stream is empty. + * - The stream is not at EOF. + * + * When blocked, the method waits for either more data or EOF on the stream: + * + * - If more data is read, the method returns the data. + * - If EOF is reached, the method raises EOFError. + * + * When not blocked, the method responds immediately: + * + * - Returns data from the buffer if there is any. + * - Otherwise returns data from the stream if there is any. + * - Otherwise raises EOFError if the stream has reached EOF. + * + * Note that this method is similar to sysread. The differences are: + * + * - If the byte buffer is not empty, read from the byte buffer * instead of "sysread for buffered IO (IOError)". - * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When + * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When * readpartial meets EWOULDBLOCK and EINTR by read system call, - * readpartial retry the system call. + * readpartial retries the system call. * - * The latter means that readpartial is nonblocking-flag insensitive. + * The latter means that readpartial is non-blocking-flag insensitive. * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as * if the fd is blocking mode. * + * Examples: + * + * # # Returned Buffer Content Pipe Content + * r, w = IO.pipe # + * w << 'abc' # "" "abc". + * r.readpartial(4096) # => "abc" "" "" + * r.readpartial(4096) # (Blocks because buffer and pipe are empty.) + * + * # # Returned Buffer Content Pipe Content + * r, w = IO.pipe # + * w << 'abc' # "" "abc" + * w.close # "" "abc" EOF + * r.readpartial(4096) # => "abc" "" EOF + * r.readpartial(4096) # raises EOFError + * + * # # Returned Buffer Content Pipe Content + * r, w = IO.pipe # + * w << "abc\ndef\n" # "" "abc\ndef\n" + * r.gets # => "abc\n" "def\n" "" + * w << "ghi\n" # "def\n" "ghi\n" + * r.readpartial(4096) # => "def\n" "" "ghi\n" + * r.readpartial(4096) # => "ghi\n" "" "" + * */ static VALUE @@ -2969,21 +3343,23 @@ io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, GetOpenFile(io, fptr); rb_io_check_byte_readable(fptr); - if (len == 0) + if (len == 0) { + io_set_read_length(str, 0, shrinkable); return str; + } n = read_buffered_data(RSTRING_PTR(str), len, fptr); if (n <= 0) { rb_io_set_nonblock(fptr); shrinkable |= io_setstrbuf(&str, len); - iis.fd = fptr->fd; + iis.fptr = fptr; iis.nonblock = 1; iis.buf = RSTRING_PTR(str); iis.capa = len; n = read_internal_locktmp(str, &iis); if (n < 0) { int e = errno; - if ((e == EWOULDBLOCK || e == EAGAIN)) { + if (io_again_p(e)) { if (!ex) return sym_wait_readable; rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "read would block"); @@ -3017,7 +3393,7 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex) rb_io_check_writable(fptr); if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); rb_io_set_nonblock(fptr); n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str)); @@ -3025,7 +3401,7 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex) if (n < 0) { int e = errno; - if (e == EWOULDBLOCK || e == EAGAIN) { + if (io_again_p(e)) { if (!ex) { return sym_wait_writable; } @@ -3041,69 +3417,71 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex) /* * call-seq: - * ios.read([length [, outbuf]]) -> string, outbuf, or nil + * read(maxlen = nil) -> string or nil + * read(maxlen = nil, out_string) -> out_string or nil * - * Reads _length_ bytes from the I/O stream. + * Reads bytes from the stream (in binary mode): * - * _length_ must be a non-negative integer or +nil+. + * - If +maxlen+ is +nil+, reads all bytes. + * - Otherwise reads +maxlen+ bytes, if available. + * - Otherwise reads all bytes. * - * If _length_ is a positive integer, +read+ tries to read - * _length_ bytes without any conversion (binary mode). - * It returns +nil+ if an EOF is encountered before anything can be read. - * Fewer than _length_ bytes are returned if an EOF is encountered during - * the read. - * In the case of an integer _length_, the resulting string is always - * in ASCII-8BIT encoding. + * Returns a string (either a new string or the given +out_string+) + * containing the bytes read. + * The encoding of the string depends on both +maxLen+ and +out_string+: * - * If _length_ is omitted or is +nil+, it reads until EOF - * and the encoding conversion is applied, if applicable. - * A string is returned even if EOF is encountered before any data is read. + * - +maxlen+ is +nil+: uses internal encoding of +self+ + * (regardless of whether +out_string+ was given). + * - +maxlen+ not +nil+: * - * If _length_ is zero, it returns an empty string (""). + * - +out_string+ given: encoding of +out_string+ not modified. + * - +out_string+ not given: ASCII-8BIT is used. * - * If the optional _outbuf_ argument is present, - * it must reference a String, which will receive the data. - * The _outbuf_ will contain only the received data after the method call - * even if it is not empty at the beginning. + * Without Argument +out_string+ * - * When this method is called at end of file, it returns +nil+ - * or "", depending on _length_: - * +read+, read(nil), and read(0) return - * "", - * read(positive_integer) returns +nil+. + * When argument +out_string+ is omitted, + * the returned value is a new string: * - * f = File.new("testfile") - * f.read(16) #=> "This is line one" + * f = File.new('t.txt') + * f.read + * # => "This is line one.\nThis is the second line.\nThis is the third line.\n" + * f.rewind + * f.read(40) # => "This is line one.\r\nThis is the second li" + * f.read(40) # => "ne.\r\nThis is the third line.\r\n" + * f.read(40) # => nil * - * # read whole file - * open("file") do |f| - * data = f.read # This returns a string even if the file is empty. - * # ... - * end + * If +maxlen+ is zero, returns an empty string. * - * # iterate over fixed length records - * open("fixed-record-file") do |f| - * while record = f.read(256) - * # ... - * end - * end + * With Argument +out_string+ * - * # iterate over variable length records, - * # each record is prefixed by its 32-bit length - * open("variable-record-file") do |f| - * while len = f.read(4) - * len = len.unpack("N")[0] # 32-bit length - * record = f.read(len) # This returns a string even if len is 0. - * end - * end + * When argument +out_string+ is given, + * the returned value is +out_string+, whose content is replaced: + * + * f = File.new('t.txt') + * s = 'foo' # => "foo" + * f.read(nil, s) # => "This is line one.\nThis is the second line.\nThis is the third line.\n" + * s # => "This is line one.\nThis is the second line.\nThis is the third line.\n" + * f.rewind + * s = 'bar' + * f.read(40, s) # => "This is line one.\r\nThis is the second li" + * s # => "This is line one.\r\nThis is the second li" + * s = 'baz' + * f.read(40, s) # => "ne.\r\nThis is the third line.\r\n" + * s # => "ne.\r\nThis is the third line.\r\n" + * s = 'bat' + * f.read(40, s) # => nil + * s # => "" * * Note that this method behaves like the fread() function in C. * This means it retries to invoke read(2) system calls to read data - * with the specified length (or until EOF). - * This behavior is preserved even if ios is in non-blocking mode. - * (This method is non-blocking flag insensitive as other methods.) + * with the specified maxlen (or until EOF). + * + * This behavior is preserved even if the stream is in non-blocking mode. + * (This method is non-blocking-flag insensitive as other methods.) + * * If you need the behavior like a single read(2) system call, * consider #readpartial, #read_nonblock, and #sysread. + * */ static VALUE @@ -3113,7 +3491,7 @@ io_read(int argc, VALUE *argv, VALUE io) long n, len; VALUE length, str; int shrinkable; -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT int previous_mode; #endif @@ -3139,12 +3517,12 @@ io_read(int argc, VALUE *argv, VALUE io) } READ_CHECK(fptr); -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT previous_mode = set_binary_mode_with_seek_cur(fptr); #endif n = io_fread(str, 0, len, fptr); io_set_read_length(str, n, shrinkable); -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT if (previous_mode == O_TEXT) { setmode(fptr->fd, O_TEXT); } @@ -3589,35 +3967,76 @@ rb_io_gets_internal(VALUE io) /* * call-seq: - * ios.gets(sep=$/ [, getline_args]) -> string or nil - * ios.gets(limit [, getline_args]) -> string or nil - * ios.gets(sep, limit [, getline_args]) -> string or nil + * gets(sep = $/, **getline_opts) -> string or nil + * gets(limit, **getline_opts) -> string or nil + * gets(sep, limit, **getline_opts) -> string or nil + * + * Reads and returns data from the stream; + * assigns the return value to $_. + * + * With no arguments given, returns the next line + * as determined by line separator $/, or +nil+ if none: + * + * f = File.open('t.txt') + * f.gets # => "This is line one.\n" + * $_ # => "This is line one.\n" + * f.gets # => "This is the second line.\n" + * f.gets # => "This is the third line.\n" + * f.gets # => nil + * + * With string argument +sep+ given, but not argument +limit+, + * returns the next line as determined by line separator +sep+, + * or +nil+ if none: * - * Reads the next ``line'' from the I/O stream; lines are separated by - * sep. A separator of +nil+ reads the entire - * contents, and a zero-length separator reads the input a paragraph at - * a time (two successive newlines in the input separate paragraphs). - * The stream must be opened for reading or an IOError will be raised. - * The line read in will be returned and also assigned to - * $_. Returns +nil+ if called at end of file. If the - * first argument is an integer, or optional second argument is given, - * the returning string would not be longer than the given value in - * bytes. + * f = File.open('t.txt') + * f.gets(' is') # => "This is" + * f.gets(' is') # => " line one.\nThis is" + * f.gets(' is') # => " the second line.\nThis is" + * f.gets(' is') # => " the third line.\n" + * f.gets(' is') # => nil * - * File.new("testfile").gets #=> "This is line one\n" - * $_ #=> "This is line one\n" + * Note two special values for +sep+: * - * File.new("testfile").gets(4)#=> "This" + * - +nil+: The entire stream is read and returned. + * - '' (empty string): The next "paragraph" is read and returned, + * the paragraph separator being two successive line separators. * - * If IO contains multibyte characters byte then gets(1) - * returns character entirely: + * With integer argument +limit+ given, + * returns up to limit+1 bytes: + * + * # Text with 1-byte characters. + * File.open('t.txt') {|f| f.gets(1) } # => "T" + * File.open('t.txt') {|f| f.gets(2) } # => "Th" + * File.open('t.txt') {|f| f.gets(3) } # => "Thi" + * File.open('t.txt') {|f| f.gets(4) } # => "This" + * # No more than one line. + * File.open('t.txt') {|f| f.gets(17) } # => "This is line one." + * File.open('t.txt') {|f| f.gets(18) } # => "This is line one.\n" + * File.open('t.txt') {|f| f.gets(19) } # => "This is line one.\n" + * + * # Text with 2-byte characters, which will not be split. + * File.open('t.rus') {|f| f.gets(1).size } # => 1 + * File.open('t.rus') {|f| f.gets(2).size } # => 1 + * File.open('t.rus') {|f| f.gets(3).size } # => 2 + * File.open('t.rus') {|f| f.gets(4).size } # => 2 + * + * With arguments +sep+ and +limit+, + * combines the two behaviors above: + * + * - Returns the next line as determined by line separator +sep+, + * or +nil+ if none. + * - But returns no more than limit+1 bytes. + * + * For all forms above, trailing optional keyword arguments may be given; + * see {Getline Options}[#class-IO-label-Getline+Options]: + * + * f = File.open('t.txt') + * # Chomp the lines. + * f.gets(chomp: true) # => "This is line one." + * f.gets(chomp: true) # => "This is the second line." + * f.gets(chomp: true) # => "This is the third line." + * f.gets(chomp: true) # => nil * - * # Russian characters take 2 bytes - * File.write("testfile", "\u{442 435 441 442}") - * File.open("testfile") {|f|f.gets(1)} #=> "\u0442" - * File.open("testfile") {|f|f.gets(2)} #=> "\u0442" - * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435" - * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435" */ static VALUE @@ -3807,19 +4226,6 @@ rb_io_each_line(int argc, VALUE *argv, VALUE io) return io; } -/* - * This is a deprecated alias for #each_line. - */ - -static VALUE -rb_io_lines(int argc, VALUE *argv, VALUE io) -{ - rb_warn_deprecated("IO#lines", "#each_line"); - if (!rb_block_given_p()) - return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv); - return rb_io_each_line(argc, argv, io); -} - /* * call-seq: * ios.each_byte {|byte| block } -> ios @@ -3850,27 +4256,14 @@ rb_io_each_byte(VALUE io) char *p = fptr->rbuf.ptr + fptr->rbuf.off++; fptr->rbuf.len--; rb_yield(INT2FIX(*p & 0xff)); + rb_io_check_byte_readable(fptr); errno = 0; } - rb_io_check_byte_readable(fptr); READ_CHECK(fptr); } while (io_fillbuf(fptr) >= 0); return io; } -/* - * This is a deprecated alias for #each_byte. - */ - -static VALUE -rb_io_bytes(VALUE io) -{ - rb_warn_deprecated("IO#bytes", "#each_byte"); - if (!rb_block_given_p()) - return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0); - return rb_io_each_byte(io); -} - static VALUE io_getc(rb_io_t *fptr, rb_encoding *enc) { @@ -4012,26 +4405,10 @@ rb_io_each_char(VALUE io) return io; } -/* - * This is a deprecated alias for #each_char. - */ - -static VALUE -rb_io_chars(VALUE io) -{ - rb_warn_deprecated("IO#chars", "#each_char"); - if (!rb_block_given_p()) - return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0); - return rb_io_each_char(io); -} - - /* * call-seq: * ios.each_codepoint {|c| block } -> ios - * ios.codepoints {|c| block } -> ios * ios.each_codepoint -> an_enumerator - * ios.codepoints -> an_enumerator * * Passes the Integer ordinal of each character in ios, * passing the codepoint as an argument. The stream must be opened for @@ -4098,6 +4475,7 @@ rb_io_each_codepoint(VALUE io) fptr->cbuf.off += n; fptr->cbuf.len -= n; rb_yield(UINT2NUM(c)); + rb_io_check_byte_readable(fptr); } } NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr); @@ -4114,8 +4492,7 @@ rb_io_each_codepoint(VALUE io) rb_yield(UINT2NUM(c)); } else if (MBCLEN_INVALID_P(r)) { - invalid: - rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc)); + goto invalid; } else if (MBCLEN_NEEDMORE_P(r)) { char cbuf[8], *p = cbuf; @@ -4136,24 +4513,15 @@ rb_io_each_codepoint(VALUE io) else { continue; } + rb_io_check_byte_readable(fptr); } return io; -} - -/* - * This is a deprecated alias for #each_codepoint. - */ -static VALUE -rb_io_codepoints(VALUE io) -{ - rb_warn_deprecated("IO#codepoints", "#each_codepoint"); - if (!rb_block_given_p()) - return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0); - return rb_io_each_codepoint(io); + invalid: + rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc)); + UNREACHABLE_RETURN(Qundef); } - /* * call-seq: * ios.getc -> string or nil @@ -4224,11 +4592,12 @@ rb_io_getbyte(VALUE io) GetOpenFile(io, fptr); rb_io_check_byte_readable(fptr); READ_CHECK(fptr); - if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) { + VALUE r_stdout = rb_ractor_stdout(); + if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) { rb_io_t *ofp; - GetOpenFile(rb_stdout, ofp); + GetOpenFile(r_stdout, ofp); if (ofp->mode & FMODE_TTY) { - rb_io_flush(rb_stdout); + rb_io_flush(r_stdout); } } if (io_fillbuf(fptr) < 0) { @@ -4265,15 +4634,34 @@ rb_io_readbyte(VALUE io) * ios.ungetbyte(integer) -> nil * * Pushes back bytes (passed as a parameter) onto ios, - * such that a subsequent buffered read will return it. Only one byte - * may be pushed back before a subsequent read operation (that is, - * you will be able to read only the last of several bytes that have been pushed - * back). Has no effect with unbuffered reads (such as IO#sysread). + * such that a subsequent buffered read will return it. + * It is only guaranteed to support a single byte, and only if ungetbyte + * or ungetc has not already been called on ios since the previous + * read of at least a single byte from ios. + * However, it can support additional bytes if there is space in the + * internal buffer to allow for it. * * f = File.new("testfile") #=> # * b = f.getbyte #=> 0x38 * f.ungetbyte(b) #=> nil * f.getbyte #=> 0x38 + * + * If given an integer, only uses the lower 8 bits of the integer as the byte + * to push. + * + * f = File.new("testfile") #=> # + * f.ungetbyte(0x102) #=> nil + * f.getbyte #=> 0x2 + * + * Calling this method prepends to the existing buffer, even if the method + * has already been called previously: + * + * f = File.new("testfile") #=> # + * f.ungetbyte("ab") #=> nil + * f.ungetbyte("cd") #=> nil + * f.read(5) #=> "cdab8" + * + * Has no effect with unbuffered reads (such as IO#sysread). */ VALUE @@ -4301,18 +4689,34 @@ rb_io_ungetbyte(VALUE io, VALUE b) /* * call-seq: + * ios.ungetc(integer) -> nil * ios.ungetc(string) -> nil * - * Pushes back one character (passed as a parameter) onto ios, - * such that a subsequent buffered character read will return it. Only one character - * may be pushed back before a subsequent read operation (that is, - * you will be able to read only the last of several characters that have been pushed - * back). Has no effect with unbuffered reads (such as IO#sysread). + * Pushes back characters (passed as a parameter) onto ios, + * such that a subsequent buffered read will return it. + * It is only guaranteed to support a single byte, and only if ungetbyte + * or ungetc has not already been called on ios since the previous + * read of at least a single byte from ios. + * However, it can support additional bytes if there is space in the + * internal buffer to allow for it. * * f = File.new("testfile") #=> # * c = f.getc #=> "8" * f.ungetc(c) #=> nil * f.getc #=> "8" + * + * If given an integer, the integer must represent a valid codepoint in the + * external encoding of ios. + * + * Calling this method prepends to the existing buffer, even if the method + * has already been called previously: + * + * f = File.new("testfile") #=> # + * f.ungetc("ab") #=> nil + * f.ungetc("cd") #=> nil + * f.read(5) #=> "cdab8" + * + * Has no effect with unbuffered reads (such as IO#sysread). */ VALUE @@ -4323,11 +4727,10 @@ rb_io_ungetc(VALUE io, VALUE c) GetOpenFile(io, fptr); rb_io_check_char_readable(fptr); - if (NIL_P(c)) return Qnil; if (FIXNUM_P(c)) { c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr)); } - else if (RB_TYPE_P(c, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(c)) { c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr)); } else { @@ -4378,9 +4781,7 @@ rb_io_isatty(VALUE io) rb_io_t *fptr; GetOpenFile(io, fptr); - if (isatty(fptr->fd) == 0) - return Qfalse; - return Qtrue; + return RBOOL(isatty(fptr->fd) != 0); } #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) @@ -4483,7 +4884,6 @@ rb_io_set_close_on_exec(VALUE io, VALUE arg) #define rb_io_set_close_on_exec rb_f_notimplement #endif -#define FMODE_PREP (1<<16) #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP) #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv)) @@ -4504,16 +4904,13 @@ finish_writeconv(rb_io_t *fptr, int noalloc) res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0); while (dp-ds) { retry: - if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock)) - r = rb_write_internal2(fptr->fd, ds, dp-ds); - else - r = rb_write_internal(fptr->fd, ds, dp-ds); + r = rb_write_internal(fptr, ds, dp-ds); if (r == dp-ds) break; if (0 <= r) { ds += r; } - if (rb_io_wait_writable(fptr->fd)) { + if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) { if (fptr->fd < 0) return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream)); goto retry; @@ -4574,7 +4971,7 @@ static int maygvl_close(int fd, int keepgvl) { if (keepgvl) - return close(fd); + return close(fd); /* * close() may block for certain file types (NFS, SO_LINGER sockets, @@ -4595,7 +4992,7 @@ static int maygvl_fclose(FILE *file, int keepgvl) { if (keepgvl) - return fclose(file); + return fclose(file); return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0); } @@ -4613,64 +5010,77 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl, int mode = fptr->mode; if (fptr->writeconv) { - if (fptr->write_lock && !noraise) { + if (fptr->write_lock && !noraise) { struct finish_writeconv_arg arg; arg.fptr = fptr; arg.noalloc = noraise; err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg); - } - else { - err = finish_writeconv(fptr, noraise); - } + } + else { + err = finish_writeconv(fptr, noraise); + } } if (fptr->wbuf.len) { - if (noraise) { - io_flush_buffer_sync(fptr); - } - else { - if (io_fflush(fptr) < 0 && NIL_P(err)) - err = INT2NUM(errno); - } + if (noraise) { + io_flush_buffer_sync(fptr); + } + else { + if (io_fflush(fptr) < 0 && NIL_P(err)) + err = INT2NUM(errno); + } + } + + int done = 0; + + if (IS_PREP_STDIO(fptr) || fd <= 2) { + // Need to keep FILE objects of stdin, stdout and stderr, so we are done: + done = 1; } fptr->fd = -1; fptr->stdio_file = 0; fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE); - /* - * ensure waiting_fd users do not hit EBADF, wait for them - * to exit before we call close(). - */ + // Ensure waiting_fd users do not hit EBADF. if (busy) { + // Wait for them to exit before we call close(). do rb_thread_schedule(); while (!list_empty(busy)); } - if (IS_PREP_STDIO(fptr) || fd <= 2) { - /* need to keep FILE objects of stdin, stdout and stderr */ - } - else if (stdio_file) { - /* stdio_file is deallocated anyway - * even if fclose failed. */ - if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err)) - if (!noraise) err = INT2NUM(errno); + // Disable for now. + // if (!done && fd >= 0) { + // VALUE scheduler = rb_fiber_scheduler_current(); + // if (scheduler != Qnil) { + // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self); + // if (result != Qundef) done = 1; + // } + // } + + if (!done && stdio_file) { + // stdio_file is deallocated anyway even if fclose failed. + if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err)) + if (!noraise) err = INT2NUM(errno); + + done = 1; } - else if (0 <= fd) { - /* fptr->fd may be closed even if close fails. - * POSIX doesn't specify it. - * We assumes it is closed. */ - /**/ - keepgvl |= !(mode & FMODE_WRITABLE); - keepgvl |= noraise; - if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err)) - if (!noraise) err = INT2NUM(errno); + if (!done && fd >= 0) { + // fptr->fd may be closed even if close fails. POSIX doesn't specify it. + // We assumes it is closed. + + keepgvl |= !(mode & FMODE_WRITABLE); + keepgvl |= noraise; + if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err)) + if (!noraise) err = INT2NUM(errno); + + done = 1; } if (!NIL_P(err) && !noraise) { - if (RB_INTEGER_TYPE_P(err)) - rb_syserr_fail_path(NUM2INT(err), fptr->pathv); - else - rb_exc_raise(err); + if (RB_INTEGER_TYPE_P(err)) + rb_syserr_fail_path(NUM2INT(err), fptr->pathv); + else + rb_exc_raise(err); } } @@ -4814,9 +5224,9 @@ fptr_waitpid(rb_io_t *fptr, int nohang) { int status; if (fptr->pid) { - rb_last_status_clear(); - rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0); - fptr->pid = 0; + rb_last_status_clear(); + rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0); + fptr->pid = 0; } } @@ -4919,7 +5329,7 @@ rb_io_closed(VALUE io) } fptr = rb_io_get_fptr(io); - return 0 <= fptr->fd ? Qfalse : Qtrue; + return RBOOL(0 > fptr->fd); } /* @@ -5111,7 +5521,7 @@ rb_io_syswrite(VALUE io, VALUE str) tmp = rb_str_tmp_frozen_acquire(str); RSTRING_GETMEM(tmp, ptr, len); - n = rb_write_internal(fptr->fd, ptr, len); + n = rb_write_internal(fptr, ptr, len); if (n < 0) rb_sys_fail_path(fptr->pathv); rb_str_tmp_frozen_release(str, tmp); @@ -5156,33 +5566,27 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io) rb_io_check_byte_readable(fptr); if (READ_DATA_BUFFERED(fptr)) { - rb_raise(rb_eIOError, "sysread for buffered IO"); + rb_raise(rb_eIOError, "sysread for buffered IO"); } - /* - * FIXME: removing rb_thread_wait_fd() here changes sysread semantics - * on non-blocking IOs. However, it's still currently possible - * for sysread to raise Errno::EAGAIN if another thread read()s - * the IO after we return from rb_thread_wait_fd() but before - * we call read() - */ - rb_thread_wait_fd(fptr->fd); - rb_io_check_closed(fptr); io_setstrbuf(&str, ilen); - iis.fd = fptr->fd; - iis.nonblock = 1; /* for historical reasons, maybe (see above) */ + iis.th = rb_thread_current(); + iis.fptr = fptr; + iis.nonblock = 0; iis.buf = RSTRING_PTR(str); iis.capa = ilen; n = read_internal_locktmp(str, &iis); if (n < 0) { - rb_sys_fail_path(fptr->pathv); + rb_sys_fail_path(fptr->pathv); } + io_set_read_length(str, n, shrinkable); + if (n == 0 && ilen > 0) { - rb_eof_error(); + rb_eof_error(); } return str; @@ -5427,7 +5831,7 @@ rb_io_binmode_p(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); - return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse; + return RBOOL(fptr->mode & FMODE_BINMODE); } static const char* @@ -5482,8 +5886,7 @@ rb_io_modestr_fmode(const char *modestr) fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE; break; default: - error: - rb_raise(rb_eArgError, "invalid access mode %s", modestr); + goto error; } while (*m) { @@ -5517,6 +5920,10 @@ rb_io_modestr_fmode(const char *modestr) goto error; return fmode; + + error: + rb_raise(rb_eArgError, "invalid access mode %s", modestr); + UNREACHABLE_RETURN(Qundef); } int @@ -5929,6 +6336,18 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, #endif SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags); ecopts = Qnil; + if (fmode & FMODE_BINMODE) { +#ifdef O_BINARY + oflags |= O_BINARY; +#endif + if (!has_enc) + rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode); + } +#if DEFAULT_TEXTMODE + else if (NIL_P(vmode)) { + fmode |= DEFAULT_TEXTMODE; + } +#endif } else { VALUE v; @@ -6319,7 +6738,7 @@ pipe_finalize(rb_io_t *fptr, int noraise) #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32) int status = 0; if (fptr->stdio_file) { - status = pclose(fptr->stdio_file); + status = pclose(fptr->stdio_file); } fptr->fd = -1; fptr->stdio_file = 0; @@ -6403,6 +6822,7 @@ struct popen_arg { #endif #ifdef HAVE_WORKING_FORK +# ifndef __EMSCRIPTEN__ static void popen_redirect(struct popen_arg *p) { @@ -6433,6 +6853,7 @@ popen_redirect(struct popen_arg *p) } } } +# endif #if defined(__linux__) /* Linux /proc/self/status contains a line: "FDSize:\t\n" @@ -6513,6 +6934,7 @@ rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds) #endif } +# ifndef __EMSCRIPTEN__ static int popen_exec(void *pp, char *errmsg, size_t errmsg_len) { @@ -6520,9 +6942,10 @@ popen_exec(void *pp, char *errmsg, size_t errmsg_len) return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len); } +# endif #endif -#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) +#if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__ static VALUE rb_execarg_fixup_v(VALUE execarg_obj) { @@ -6533,6 +6956,7 @@ rb_execarg_fixup_v(VALUE execarg_obj) char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog); #endif +#ifndef __EMSCRIPTEN__ static VALUE pipe_open(VALUE execarg_obj, const char *modestr, int fmode, const convconfig_t *convconfig) @@ -6646,7 +7070,7 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, /* exec failed */ switch (e = errno) { case EAGAIN: -# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +# if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: # endif rb_thread_sleep(1); @@ -6661,9 +7085,8 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, } else { # if defined(HAVE_WORKING_FORK) - pid = rb_fork_ruby(&status); + pid = rb_call_proc__fork(); if (pid == 0) { /* child */ - rb_thread_atfork(); popen_redirect(&arg); rb_io_synchronized(RFILE(orig_stdout)->fptr); rb_io_synchronized(RFILE(orig_stderr)->fptr); @@ -6728,7 +7151,7 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX; if (convconfig) { fptr->encs = *convconfig; -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) { fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR; } @@ -6762,6 +7185,14 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, #endif return port; } +#else +static VALUE +pipe_open(VALUE execarg_obj, const char *modestr, int fmode, + const convconfig_t *convconfig) +{ + rb_raise(rb_eNotImpError, "popen() is not available"); +} +#endif static int is_popen_fork(VALUE prog) @@ -6800,6 +7231,8 @@ pipe_close(VALUE io) return Qnil; } +static VALUE popen_finish(VALUE port, VALUE klass); + /* * call-seq: * IO.popen([env,] cmd, mode="r" [, opt]) -> io @@ -6889,10 +7322,7 @@ pipe_close(VALUE io) static VALUE rb_io_s_popen(int argc, VALUE *argv, VALUE klass) { - const char *modestr; - VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil; - int oflags, fmode; - convconfig_t convconfig; + VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil; if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc; if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv; @@ -6908,6 +7338,16 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass) rb_error_arity(argc + ex, 1 + ex, 2 + ex); } } + return popen_finish(rb_io_popen(pname, pmode, env, opt), klass); +} + +VALUE +rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt) +{ + const char *modestr; + VALUE tmp, execarg_obj = Qnil; + int oflags, fmode; + convconfig_t convconfig; tmp = rb_check_array_type(pname); if (!NIL_P(tmp)) { @@ -6935,13 +7375,18 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass) rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig); modestr = rb_io_oflags_modestr(oflags); - port = pipe_open(execarg_obj, modestr, fmode, &convconfig); + return pipe_open(execarg_obj, modestr, fmode, &convconfig); +} + +static VALUE +popen_finish(VALUE port, VALUE klass) +{ if (NIL_P(port)) { /* child */ if (rb_block_given_p()) { rb_yield(Qnil); - rb_io_flush(rb_stdout); - rb_io_flush(rb_stderr); + rb_io_flush(rb_ractor_stdout()); + rb_io_flush(rb_ractor_stderr()); _exit(0); } return Qnil; @@ -7125,7 +7570,8 @@ check_pipe_command(VALUE filename_or_command) * If the command following the pipe is a single minus sign * ("|-"), Ruby forks, and this subprocess is connected to the * parent. If the command is not "-", the subprocess runs the - * command. + * command. Note that the command may be processed by shell if it contains + * shell metacharacters. * * When the subprocess is Ruby (opened via "|-"), the +open+ * call returns +nil+. If a block is associated with the open call, that @@ -7277,7 +7723,7 @@ io_reopen(VALUE io, VALUE nfile) } if (fptr->mode & FMODE_WRITABLE) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); } else { flush_before_seek(fptr); @@ -7287,7 +7733,7 @@ io_reopen(VALUE io, VALUE nfile) } if (orig->mode & FMODE_WRITABLE) { if (io_fflush(orig) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); } /* copy rb_io_t structure */ @@ -7416,7 +7862,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file) if (fptr->mode & FMODE_WRITABLE) { if (io_fflush(fptr) < 0) - rb_sys_fail(0); + rb_sys_fail_on_write(fptr); } fptr->rbuf.off = fptr->rbuf.len = 0; @@ -7424,7 +7870,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file) int e = rb_freopen(rb_str_encode_ospath(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file); - if (e) rb_syserr_fail_path(e, fptr->pathv); + if (e) rb_syserr_fail_path(e, fptr->pathv); fptr->fd = fileno(fptr->stdio_file); rb_fd_fix_cloexec(fptr->fd); #ifdef USE_SETVBUF @@ -7530,7 +7976,7 @@ rb_f_printf(int argc, VALUE *argv, VALUE _) if (argc == 0) return Qnil; if (RB_TYPE_P(argv[0], T_STRING)) { - out = rb_stdout; + out = rb_ractor_stdout(); } else { out = argv[0]; @@ -7543,11 +7989,11 @@ rb_f_printf(int argc, VALUE *argv, VALUE _) } static void -rb_output_fs_setter(VALUE val, ID id, VALUE *var) +deprecated_str_setter(VALUE val, ID id, VALUE *var) { rb_str_setter(val, id, &val); if (!NIL_P(val)) { - rb_warn_deprecated("`$,'", NULL); + rb_warn_deprecated("`%s'", NULL, rb_id2name(id)); } *var = val; } @@ -7588,6 +8034,9 @@ rb_io_print(int argc, const VALUE *argv, VALUE out) line = rb_lastline_get(); argv = &line; } + if (argc > 1 && !NIL_P(rb_output_fs)) { + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value"); + } for (i=0; i0) { rb_io_write(out, rb_output_fs); @@ -7627,7 +8076,7 @@ rb_io_print(int argc, const VALUE *argv, VALUE out) static VALUE rb_f_print(int argc, const VALUE *argv, VALUE _) { - rb_io_print(argc, argv, rb_stdout); + rb_io_print(argc, argv, rb_ractor_stdout()); return Qnil; } @@ -7663,6 +8112,13 @@ rb_io_putc(VALUE io, VALUE ch) return ch; } +#define forward(obj, id, argc, argv) \ + rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS) +#define forward_public(obj, id, argc, argv) \ + rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS) +#define forward_current(id, argc, argv) \ + forward_public(ARGF.current_file, id, argc, argv) + /* * call-seq: * putc(int) -> int @@ -7678,10 +8134,11 @@ rb_io_putc(VALUE io, VALUE ch) static VALUE rb_f_putc(VALUE recv, VALUE ch) { - if (recv == rb_stdout) { + VALUE r_stdout = rb_ractor_stdout(); + if (recv == r_stdout) { return rb_io_putc(recv, ch); } - return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch); + return forward(r_stdout, rb_intern("putc"), 1, &ch); } @@ -7792,52 +8249,50 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out) static VALUE rb_f_puts(int argc, VALUE *argv, VALUE recv) { - if (recv == rb_stdout) { + VALUE r_stdout = rb_ractor_stdout(); + if (recv == r_stdout) { return rb_io_puts(argc, argv, recv); } - return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv); + return forward(r_stdout, rb_intern("puts"), argc, argv); } -void -rb_p(VALUE obj) /* for debug print within C code */ +static VALUE +rb_p_write(VALUE str) { VALUE args[2]; - args[0] = rb_obj_as_string(rb_inspect(obj)); + args[0] = str; args[1] = rb_default_rs; - if (RB_TYPE_P(rb_stdout, T_FILE) && - rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) { - io_writev(2, args, rb_stdout); + VALUE r_stdout = rb_ractor_stdout(); + if (RB_TYPE_P(r_stdout, T_FILE) && + rb_method_basic_definition_p(CLASS_OF(r_stdout), id_write)) { + io_writev(2, args, r_stdout); } else { - rb_io_writev(rb_stdout, 2, args); + rb_io_writev(r_stdout, 2, args); } + return Qnil; } -struct rb_f_p_arg { - int argc; - VALUE *argv; -}; +void +rb_p(VALUE obj) /* for debug print within C code */ +{ + rb_p_write(rb_obj_as_string(rb_inspect(obj))); +} static VALUE -rb_f_p_internal(VALUE arg) +rb_p_result(int argc, const VALUE *argv) { - struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg; - int argc = arg1->argc; - VALUE *argv = arg1->argv; - int i; VALUE ret = Qnil; - - for (i=0; i 1) { ret = rb_ary_new4(argc, argv); } - if (RB_TYPE_P(rb_stdout, T_FILE)) { - rb_io_flush(rb_stdout); + VALUE r_stdout = rb_ractor_stdout(); + if (RB_TYPE_P(r_stdout, T_FILE)) { + rb_io_flush(r_stdout); } return ret; } @@ -7863,11 +8318,12 @@ rb_f_p_internal(VALUE arg) static VALUE rb_f_p(int argc, VALUE *argv, VALUE self) { - struct rb_f_p_arg arg; - arg.argc = argc; - arg.argv = argv; - - return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg); + int i; + for (i=0; ifptr->fd < 0); + return (err == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0); } void rb_write_error2(const char *mesg, long len) { - if (rb_stderr_to_original_p()) { + VALUE out = rb_ractor_stderr(); + if (rb_stderr_to_original_p(out)) { #ifdef _WIN32 if (isatty(fileno(stderr))) { if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return; @@ -7926,7 +8383,7 @@ rb_write_error2(const char *mesg, long len) } } else { - rb_io_write(rb_stderr, rb_str_new(mesg, len)); + rb_io_write(out, rb_str_new(mesg, len)); } } @@ -7939,8 +8396,9 @@ rb_write_error(const char *mesg) void rb_write_error_str(VALUE mesg) { + VALUE out = rb_ractor_stderr(); /* a stopgap measure for the time being */ - if (rb_stderr_to_original_p()) { + if (rb_stderr_to_original_p(out)) { size_t len = (size_t)RSTRING_LEN(mesg); #ifdef _WIN32 if (isatty(fileno(stderr))) { @@ -7954,14 +8412,14 @@ rb_write_error_str(VALUE mesg) } else { /* may unlock GVL, and */ - rb_io_write(rb_stderr, mesg); + rb_io_write(out, mesg); } } int rb_stderr_tty_p(void) { - if (rb_stderr_to_original_p()) + if (rb_stderr_to_original_p(rb_ractor_stderr())) return isatty(fileno(stderr)); return 0; } @@ -7977,10 +8435,41 @@ must_respond_to(ID mid, VALUE val, ID id) } static void -stdout_setter(VALUE val, ID id, VALUE *variable) +stdin_setter(VALUE val, ID id, VALUE *ptr) +{ + rb_ractor_stdin_set(val); +} + +static VALUE +stdin_getter(ID id, VALUE *ptr) +{ + return rb_ractor_stdin(); +} + +static void +stdout_setter(VALUE val, ID id, VALUE *ptr) +{ + must_respond_to(id_write, val, id); + rb_ractor_stdout_set(val); +} + +static VALUE +stdout_getter(ID id, VALUE *ptr) +{ + return rb_ractor_stdout(); +} + +static void +stderr_setter(VALUE val, ID id, VALUE *ptr) { must_respond_to(id_write, val, id); - *variable = val; + rb_ractor_stderr_set(val); +} + +static VALUE +stderr_getter(ID id, VALUE *ptr) +{ + return rb_ractor_stderr(); } static VALUE @@ -7990,6 +8479,7 @@ prep_io(int fd, int fmode, VALUE klass, const char *path) VALUE io = io_alloc(klass); MakeOpenFile(io, fp); + fp->self = io; fp->fd = fd; fp->mode = fmode; if (!io_check_tty(fp)) { @@ -8032,6 +8522,24 @@ prep_stdio(FILE *f, int fmode, VALUE klass, const char *path) return io; } +VALUE +rb_io_prep_stdin(void) +{ + return prep_stdio(stdin, FMODE_READABLE, rb_cIO, ""); +} + +VALUE +rb_io_prep_stdout(void) +{ + return prep_stdio(stdout, FMODE_WRITABLE|FMODE_SIGNAL_ON_EPIPE, rb_cIO, ""); +} + +VALUE +rb_io_prep_stderr(void) +{ + return prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, ""); +} + FILE * rb_io_stdio_file(rb_io_t *fptr) { @@ -8055,6 +8563,7 @@ static inline rb_io_t * rb_io_fptr_new(void) { rb_io_t *fp = ALLOC(rb_io_t); + fp->self = Qnil; fp->fd = -1; fp->stdio_file = NULL; fp->mode = 0; @@ -8087,11 +8596,12 @@ rb_io_make_open_file(VALUE obj) Check_Type(obj, T_FILE); if (RFILE(obj)->fptr) { - rb_io_close(obj); - rb_io_fptr_finalize(RFILE(obj)->fptr); - RFILE(obj)->fptr = 0; + rb_io_close(obj); + rb_io_fptr_finalize(RFILE(obj)->fptr); + RFILE(obj)->fptr = 0; } fp = rb_io_fptr_new(); + fp->self = obj; RFILE(obj)->fptr = fp; return fp; } @@ -8292,6 +8802,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io) fmode |= FMODE_PREP; } MakeOpenFile(io, fp); + fp->self = io; fp->fd = fd; fp->mode = fmode; fp->encs = convconfig; @@ -8579,7 +9090,7 @@ argf_lineno(VALUE argf) static VALUE argf_forward(int argc, VALUE *argv, VALUE argf) { - return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv); + return forward_current(rb_frame_this_func(), argc, argv); } #define next_argv() argf_next_argv(argf) @@ -8614,8 +9125,10 @@ argf_next_argv(VALUE argf) int stdout_binmode = 0; int fmode; - if (RB_TYPE_P(rb_stdout, T_FILE)) { - GetOpenFile(rb_stdout, fptr); + VALUE r_stdout = rb_ractor_stdout(); + + if (RB_TYPE_P(r_stdout, T_FILE)) { + GetOpenFile(r_stdout, fptr); if (fptr->mode & FMODE_BINMODE) stdout_binmode = 1; } @@ -8666,8 +9179,8 @@ argf_next_argv(VALUE argf) VALUE str; int fw; - if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) { - rb_io_close(rb_stdout); + if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) { + rb_io_close(r_stdout); } fstat(fr, &st); str = filename; @@ -8736,7 +9249,7 @@ argf_next_argv(VALUE argf) } #endif write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn); - rb_stdout = write_io; + rb_ractor_stdout_set(write_io); if (stdout_binmode) rb_io_binmode(rb_stdout); } fmode = FMODE_READABLE; @@ -8776,7 +9289,7 @@ argf_next_argv(VALUE argf) ARGF.filename = rb_str_new2("-"); if (ARGF.inplace) { rb_warn("Can't do inplace edit for stdio"); - rb_stdout = orig_stdout; + rb_ractor_stdout_set(orig_stdout); } } if (ARGF.init_p == -1) ARGF.init_p = 1; @@ -8792,7 +9305,7 @@ argf_getline(int argc, VALUE *argv, VALUE argf) retry: if (!next_argv()) return Qnil; if (ARGF_GENERIC_INPUT_P()) { - line = rb_funcall3(ARGF.current_file, idGets, argc, argv); + line = forward_current(idGets, argc, argv); } else { if (argc == 0 && rb_rs == rb_default_rs) { @@ -8870,7 +9383,7 @@ rb_f_gets(int argc, VALUE *argv, VALUE recv) if (recv == argf) { return argf_gets(argc, argv, argf); } - return rb_funcallv(argf, idGets, argc, argv); + return forward(argf, idGets, argc, argv); } /* @@ -8946,7 +9459,7 @@ rb_f_readline(int argc, VALUE *argv, VALUE recv) if (recv == argf) { return argf_readline(argc, argv, argf); } - return rb_funcallv(argf, rb_intern("readline"), argc, argv); + return forward(argf, rb_intern("readline"), argc, argv); } @@ -9000,7 +9513,7 @@ rb_f_readlines(int argc, VALUE *argv, VALUE recv) if (recv == argf) { return argf_readlines(argc, argv, argf); } - return rb_funcallv(argf, rb_intern("readlines"), argc, argv); + return forward(argf, rb_intern("readlines"), argc, argv); } /* @@ -9028,7 +9541,7 @@ argf_readlines(int argc, VALUE *argv, VALUE argf) ary = rb_ary_new(); while (next_argv()) { if (ARGF_GENERIC_INPUT_P()) { - lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv); + lines = forward_current(rb_intern("readlines"), argc, argv); } else { lines = rb_io_readlines(argc, argv, ARGF.current_file); @@ -9074,7 +9587,7 @@ rb_f_backquote(VALUE obj, VALUE str) rb_io_close(port); RFILE(port)->fptr = NULL; rb_io_fptr_finalize(fptr); - rb_gc_force_recycle(port); /* also guards from premature GC */ + RB_GC_GUARD(port); return result; } @@ -9570,9 +10083,8 @@ rb_f_select(int argc, VALUE *argv, VALUE obj) return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args); } -#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) - typedef unsigned long ioctl_req_t; -# define NUM2IOCTLREQ(num) NUM2ULONG(num) +#ifdef IOCTL_REQ_TYPE + typedef IOCTL_REQ_TYPE ioctl_req_t; #else typedef int ioctl_req_t; # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num)) @@ -9609,7 +10121,7 @@ do_ioctl(int fd, ioctl_req_t cmd, long narg) } #endif -#define DEFULT_IOCTL_NARG_LEN (256) +#define DEFAULT_IOCTL_NARG_LEN (256) #if defined(__linux__) && defined(_IOC_SIZE) static long @@ -9619,14 +10131,14 @@ linux_iocparm_len(ioctl_req_t cmd) if ((cmd & 0xFFFF0000) == 0) { /* legacy and unstructured ioctl number. */ - return DEFULT_IOCTL_NARG_LEN; + return DEFAULT_IOCTL_NARG_LEN; } len = _IOC_SIZE(cmd); /* paranoia check for silly drivers which don't keep ioctl convention */ - if (len < DEFULT_IOCTL_NARG_LEN) - len = DEFULT_IOCTL_NARG_LEN; + if (len < DEFAULT_IOCTL_NARG_LEN) + len = DEFAULT_IOCTL_NARG_LEN; return len; } @@ -9648,7 +10160,7 @@ ioctl_narg_len(ioctl_req_t cmd) len = linux_iocparm_len(cmd); #else /* otherwise guess at what's safe */ - len = DEFULT_IOCTL_NARG_LEN; + len = DEFAULT_IOCTL_NARG_LEN; #endif return len; @@ -9663,7 +10175,7 @@ typedef int fcntl_arg_t; #endif static long -fcntl_narg_len(int cmd) +fcntl_narg_len(ioctl_req_t cmd) { long len; @@ -9783,19 +10295,21 @@ fcntl_narg_len(int cmd) } #else /* HAVE_FCNTL */ static long -fcntl_narg_len(int cmd) +fcntl_narg_len(ioctl_req_t cmd) { return 0; } #endif /* HAVE_FCNTL */ +#define NARG_SENTINEL 17 + static long -setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p) +setup_narg(ioctl_req_t cmd, VALUE *argp, long (*narg_len)(ioctl_req_t)) { long narg = 0; VALUE arg = *argp; - if (NIL_P(arg) || arg == Qfalse) { + if (!RTEST(arg)) { narg = 0; } else if (FIXNUM_P(arg)) { @@ -9815,10 +10329,7 @@ setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p) long len, slen; *argp = arg = tmp; - if (io_p) - len = ioctl_narg_len(cmd); - else - len = fcntl_narg_len((int)cmd); + len = narg_len(cmd); rb_str_modify(arg); slen = RSTRING_LEN(arg); @@ -9830,7 +10341,7 @@ setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p) } /* a little sanity check here */ ptr = RSTRING_PTR(arg); - ptr[slen - 1] = 17; + ptr[slen - 1] = NARG_SENTINEL; narg = (long)(SIGNED_VALUE)ptr; } } @@ -9838,24 +10349,15 @@ setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p) return narg; } -#ifdef HAVE_IOCTL static VALUE -rb_ioctl(VALUE io, VALUE req, VALUE arg) +finish_narg(int retval, VALUE arg, const rb_io_t *fptr) { - ioctl_req_t cmd = NUM2IOCTLREQ(req); - rb_io_t *fptr; - long narg; - int retval; - - narg = setup_narg(cmd, &arg, 1); - GetOpenFile(io, fptr); - retval = do_ioctl(fptr->fd, cmd, narg); if (retval < 0) rb_sys_fail_path(fptr->pathv); if (RB_TYPE_P(arg, T_STRING)) { char *ptr; long slen; RSTRING_GETMEM(arg, ptr, slen); - if (ptr[slen-1] != 17) + if (ptr[slen-1] != NARG_SENTINEL) rb_raise(rb_eArgError, "return value overflowed string"); ptr[slen-1] = '\0'; } @@ -9863,6 +10365,21 @@ rb_ioctl(VALUE io, VALUE req, VALUE arg) return INT2NUM(retval); } +#ifdef HAVE_IOCTL +static VALUE +rb_ioctl(VALUE io, VALUE req, VALUE arg) +{ + ioctl_req_t cmd = NUM2IOCTLREQ(req); + rb_io_t *fptr; + long narg; + int retval; + + narg = setup_narg(cmd, &arg, ioctl_narg_len); + GetOpenFile(io, fptr); + retval = do_ioctl(fptr->fd, cmd, narg); + return finish_narg(retval, arg, fptr); +} + /* * call-seq: * ios.ioctl(integer_cmd, arg) -> integer @@ -9940,20 +10457,10 @@ rb_fcntl(VALUE io, VALUE req, VALUE arg) long narg; int retval; - narg = setup_narg(cmd, &arg, 0); + narg = setup_narg(cmd, &arg, fcntl_narg_len); GetOpenFile(io, fptr); retval = do_fcntl(fptr->fd, cmd, narg); - if (retval < 0) rb_sys_fail_path(fptr->pathv); - if (RB_TYPE_P(arg, T_STRING)) { - char *ptr; - long slen; - RSTRING_GETMEM(arg, ptr, slen); - if (ptr[slen-1] != 17) - rb_raise(rb_eArgError, "return value overflowed string"); - ptr[slen-1] = '\0'; - } - - return INT2NUM(retval); + return finish_narg(retval, arg, fptr); } /* @@ -9993,7 +10500,7 @@ rb_io_fcntl(int argc, VALUE *argv, VALUE io) * Arguments for the function can follow _num_. They must be either * +String+ objects or +Integer+ objects. A +String+ object is passed * as a pointer to the byte sequence. An +Integer+ object is passed - * as an integer whose bit size is same as a pointer. + * as an integer whose bit size is the same as a pointer. * Up to nine parameters may be passed. * * The function identified by _num_ is system @@ -10052,7 +10559,8 @@ rb_f_syscall(int argc, VALUE *argv, VALUE _) int i; if (RTEST(ruby_verbose)) { - rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative."); + rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, + "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative."); } if (argc == 0) @@ -10320,7 +10828,7 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass) extract_binmode(opt, &fmode); - if ((fmode & FMODE_BINMODE) && v1 == Qnil) { + if ((fmode & FMODE_BINMODE) && NIL_P(v1)) { rb_io_ascii8bit_binmode(r); rb_io_ascii8bit_binmode(w); } @@ -10330,7 +10838,7 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass) fptr->mode &= ~FMODE_TEXTMODE; setmode(fptr->fd, O_BINARY); } -#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) +#if RUBY_CRLF_ENVIRONMENT if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) { fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR; } @@ -10408,13 +10916,23 @@ io_s_foreach(VALUE v) * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil * IO.foreach(...) -> an_enumerator + * File.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil + * File.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil + * File.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil + * File.foreach(...) -> an_enumerator * * Executes the block for every line in the named I/O port, where lines * are separated by sep. * * If no block is given, an enumerator is returned instead. * - * IO.foreach("testfile") {|x| print "GOT ", x } + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.foreach to disable the behavior of subprocess invocation. + * + * File.foreach("testfile") {|x| print "GOT ", x } + * IO.foreach("| cat testfile") {|x| print "GOT ", x } * * produces: * @@ -10459,17 +10977,27 @@ io_s_readlines(VALUE v) * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array * IO.readlines(name, limit [, getline_args, open_args]) -> array * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array + * File.readlines(name, sep=$/ [, getline_args, open_args]) -> array + * File.readlines(name, limit [, getline_args, open_args]) -> array + * File.readlines(name, sep, limit [, getline_args, open_args]) -> array * * Reads the entire file specified by name as individual * lines, and returns those lines in an array. Lines are separated by * sep. * - * a = IO.readlines("testfile") + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.readlines to disable the behavior of subprocess invocation. + * + * a = File.readlines("testfile") * a[0] #=> "This is line one\n" * - * b = IO.readlines("testfile", chomp: true) + * b = File.readlines("testfile", chomp: true) * b[0] #=> "This is line one" * + * IO.readlines("|ls -a") #=> [".\n", "..\n", ...] + * * If the last argument is a hash, it's the keyword argument to open. * * === Options for getline @@ -10481,7 +11009,7 @@ io_s_readlines(VALUE v) * \n, \r, and \r\n * will be removed from the end of each line. * - * See also IO.read for details about open_args. + * See also IO.read for details about +name+ and open_args. */ static VALUE @@ -10523,14 +11051,17 @@ seek_before_access(VALUE argp) /* * call-seq: - * IO.read(name, [length [, offset]] [, opt] ) -> string + * IO.read(name, [length [, offset]] [, opt]) -> string + * File.read(name, [length [, offset]] [, opt]) -> string * * Opens the file, optionally seeks to the given +offset+, then returns * +length+ bytes (defaulting to the rest of the file). #read ensures * the file is closed before returning. * - * If +name+ starts with a pipe character ("|"), a subprocess is - * created in the same way as Kernel#open, and its output is returned. + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.read to disable the behavior of subprocess invocation. * * === Options * @@ -10557,10 +11088,11 @@ seek_before_access(VALUE argp) * * Examples: * - * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" - * IO.read("testfile", 20) #=> "This is line one\nThi" - * IO.read("testfile", 20, 10) #=> "ne one\nThis is line " - * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12" + * File.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" + * File.read("testfile", 20) #=> "This is line one\nThi" + * File.read("testfile", 20, 10) #=> "ne one\nThis is line " + * File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12" + * IO.read("|ls -a") #=> ".\n..\n"... */ static VALUE @@ -10590,16 +11122,25 @@ rb_io_s_read(int argc, VALUE *argv, VALUE io) /* * call-seq: - * IO.binread(name, [length [, offset]] ) -> string + * IO.binread(name, [length [, offset]]) -> string + * File.binread(name, [length [, offset]]) -> string * * Opens the file, optionally seeks to the given offset, then * returns length bytes (defaulting to the rest of the file). * #binread ensures the file is closed before returning. The open mode * would be "rb:ASCII-8BIT". * - * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" - * IO.binread("testfile", 20) #=> "This is line one\nThi" - * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line " + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.binread to disable the behavior of subprocess invocation. + * + * File.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" + * File.binread("testfile", 20) #=> "This is line one\nThi" + * File.binread("testfile", 20, 10) #=> "ne one\nThis is line " + * IO.binread("| cat testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" + * + * See also IO.read for details about +name+ and open_args. */ static VALUE @@ -10641,7 +11182,7 @@ rb_io_s_binread(int argc, VALUE *argv, VALUE io) static VALUE io_s_write0(VALUE v) { - struct write_arg *arg = (void * )v; + struct write_arg *arg = (void *)v; return io_write(arg->io,arg->str,arg->nosync); } @@ -10697,16 +11238,25 @@ io_s_write(int argc, VALUE *argv, VALUE klass, int binary) * call-seq: * IO.write(name, string [, offset]) -> integer * IO.write(name, string [, offset] [, opt]) -> integer + * File.write(name, string [, offset]) -> integer + * File.write(name, string [, offset] [, opt]) -> integer * * Opens the file, optionally seeks to the given offset, writes * string, then returns the length written. #write ensures the * file is closed before returning. If offset is not given in * write mode, the file is truncated. Otherwise, it is not truncated. * - * IO.write("testfile", "0123456789", 20) #=> 10 + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.write to disable the behavior of subprocess invocation. + * + * File.write("testfile", "0123456789", 20) #=> 10 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n" - * IO.write("testfile", "0123456789") #=> 10 + * File.write("testfile", "0123456789") #=> 10 * # File would now read: "0123456789" + * IO.write("|tr a-z A-Z", "abc") #=> 3 + * # Prints "ABC" to the standard output * * If the last argument is a hash, it specifies options for the internal * open(). It accepts the following keys: @@ -10734,6 +11284,8 @@ io_s_write(int argc, VALUE *argv, VALUE klass, int binary) * * Specifies arguments for open() as an array. * This key can not be used in combination with other keys. + * + * See also IO.read for details about +name+ and open_args. */ static VALUE @@ -10744,11 +11296,20 @@ rb_io_s_write(int argc, VALUE *argv, VALUE io) /* * call-seq: - * IO.binwrite(name, string, [offset] ) -> integer - * IO.binwrite(name, string, [offset], open_args ) -> integer + * IO.binwrite(name, string, [offset]) -> integer + * IO.binwrite(name, string, [offset], open_args) -> integer + * File.binwrite(name, string, [offset]) -> integer + * File.binwrite(name, string, [offset], open_args) -> integer * * Same as IO.write except opening the file in binary mode and * ASCII-8BIT encoding ("wb:ASCII-8BIT"). + * + * If +name+ starts with a pipe character ("|") and the receiver + * is the IO class, a subprocess is created in the same way as Kernel#open, + * and its output is returned. + * Consider to use File.binwrite to disable the behavior of subprocess invocation. + * + * See also IO.read for details about +name+ and open_args. */ static VALUE @@ -10763,8 +11324,8 @@ struct copy_stream_struct { off_t copy_length; /* (off_t)-1 if not specified */ off_t src_offset; /* (off_t)-1 if not specified */ - int src_fd; - int dst_fd; + rb_io_t *src_fptr; + rb_io_t *dst_fptr; unsigned close_src : 1; unsigned close_dst : 1; int error_no; @@ -10811,13 +11372,42 @@ maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp) return FALSE; } +struct wait_for_single_fd { + VALUE scheduler; + + rb_io_t *fptr; + short events; + + VALUE result; +}; + +static void * +rb_thread_fiber_scheduler_wait_for(void * _args) +{ + struct wait_for_single_fd *args = (struct wait_for_single_fd *)_args; + + args->result = rb_fiber_scheduler_io_wait(args->scheduler, args->fptr->self, INT2NUM(args->events), Qnil); + + return NULL; +} + #if USE_POLL # define IOWAIT_SYSCALL "poll" STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN); STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT); static int -nogvl_wait_for_single_fd(int fd, short events) +nogvl_wait_for(VALUE th, rb_io_t *fptr, short events) { + VALUE scheduler = rb_fiber_scheduler_current_for_thread(th); + if (scheduler != Qnil) { + struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events}; + rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for, &args); + return RTEST(args.result); + } + + int fd = fptr->fd; + if (fd == -1) return 0; + struct pollfd fds; fds.fd = fd; @@ -10828,8 +11418,18 @@ nogvl_wait_for_single_fd(int fd, short events) #else /* !USE_POLL */ # define IOWAIT_SYSCALL "select" static int -nogvl_wait_for_single_fd(int fd, short events) +nogvl_wait_for(VALUE th, rb_io_t *fptr, short events) { + VALUE scheduler = rb_fiber_scheduler_current_for_thread(th); + if (scheduler != Qnil) { + struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events}; + rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for, &args); + return RTEST(args.result); + } + + int fd = fptr->fd; + if (fd == -1) return 0; + rb_fdset_t fds; int ret; @@ -10844,7 +11444,7 @@ nogvl_wait_for_single_fd(int fd, short events) ret = rb_fd_select(fd + 1, 0, &fds, 0, 0); break; default: - VM_UNREACHABLE(nogvl_wait_for_single_fd); + VM_UNREACHABLE(nogvl_wait_for); } rb_fd_term(&fds); @@ -10858,12 +11458,12 @@ maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp) int ret; do { - if (has_gvl) { - ret = rb_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN, NULL); - } - else { - ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN); - } + if (has_gvl) { + ret = RB_NUM2INT(rb_io_wait(stp->src, RB_INT2NUM(RUBY_IO_READABLE), Qnil)); + } + else { + ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN); + } } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp)); if (ret < 0) { @@ -10880,7 +11480,7 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp) int ret; do { - ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT); + ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT); } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp)); if (ret < 0) { @@ -10891,10 +11491,6 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp) return 0; } -#if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range) -# define USE_COPY_FILE_RANGE -#endif - #ifdef USE_COPY_FILE_RANGE static ssize_t @@ -10931,7 +11527,7 @@ nogvl_copy_file_range(struct copy_stream_struct *stp) if (src_offset < (off_t)0) { off_t current_offset; errno = 0; - current_offset = lseek(stp->src_fd, 0, SEEK_CUR); + current_offset = lseek(stp->src_fptr->fd, 0, SEEK_CUR); if (current_offset < (off_t)0 && errno) { stp->syserr = "lseek"; stp->error_no = errno; @@ -10951,7 +11547,7 @@ nogvl_copy_file_range(struct copy_stream_struct *stp) # else ss = (ssize_t)copy_length; # endif - ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0); + ss = simple_copy_file_range(stp->src_fptr->fd, src_offset_ptr, stp->dst_fptr->fd, NULL, ss, 0); if (0 < ss) { stp->total += ss; copy_length -= ss; @@ -10975,7 +11571,7 @@ nogvl_copy_file_range(struct copy_stream_struct *stp) #endif return 0; case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +#if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif { @@ -10986,7 +11582,7 @@ nogvl_copy_file_range(struct copy_stream_struct *stp) case EBADF: { int e = errno; - int flags = fcntl(stp->dst_fd, F_GETFL); + int flags = fcntl(stp->dst_fptr->fd, F_GETFL); if (flags != -1 && flags & O_APPEND) { return 0; @@ -11020,22 +11616,29 @@ nogvl_fcopyfile(struct copy_stream_struct *stp) if (!S_ISREG(stp->dst_stat.st_mode)) return 0; - if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */ + if (lseek(stp->dst_fptr->fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */ return 0; + if (fcntl(stp->dst_fptr->fd, F_GETFL) & O_APPEND) { + /* fcopyfile(3) appends src IO to dst IO and then truncates + * dst IO to src IO's original size. */ + off_t end = lseek(stp->dst_fptr->fd, 0, SEEK_END); + lseek(stp->dst_fptr->fd, 0, SEEK_SET); + if (end > (off_t)0) return 0; + } if (src_offset > (off_t)0) { off_t r; /* get current offset */ errno = 0; - cur = lseek(stp->src_fd, 0, SEEK_CUR); + cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR); if (cur < (off_t)0 && errno) { stp->error_no = errno; return 1; } errno = 0; - r = lseek(stp->src_fd, src_offset, SEEK_SET); + r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET); if (r < (off_t)0 && errno) { stp->error_no = errno; return 1; @@ -11043,7 +11646,7 @@ nogvl_fcopyfile(struct copy_stream_struct *stp) } stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */ - ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA); + ret = fcopyfile(stp->src_fptr->fd, stp->dst_fptr->fd, stp->copyfile_state, COPYFILE_DATA); copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */ if (ret == 0) { /* success */ @@ -11052,7 +11655,7 @@ nogvl_fcopyfile(struct copy_stream_struct *stp) off_t r; errno = 0; /* reset offset */ - r = lseek(stp->src_fd, cur, SEEK_SET); + r = lseek(stp->src_fptr->fd, cur, SEEK_SET); if (r < (off_t)0 && errno) { stp->error_no = errno; return 1; @@ -11150,7 +11753,7 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp) else { off_t cur; errno = 0; - cur = lseek(stp->src_fd, 0, SEEK_CUR); + cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR); if (cur < (off_t)0 && errno) { stp->syserr = "lseek"; stp->error_no = errno; @@ -11168,10 +11771,10 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp) ss = (ssize_t)copy_length; # endif if (use_pread) { - ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss); + ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, &src_offset, ss); } else { - ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss); + ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, NULL, ss); } if (0 < ss) { stp->total += ss; @@ -11187,17 +11790,22 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp) case EINVAL: #ifdef ENOSYS case ENOSYS: +#endif +#ifdef EOPNOTSUP + /* some RedHat kernels may return EOPNOTSUP on an NFS mount. + see also: [Feature #16965] */ + case EOPNOTSUP: #endif return 0; case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +#if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif { int ret; #ifndef __linux__ /* - * Linux requires stp->src_fd to be a mmap-able (regular) file, + * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file, * select() reports regular files to always be "ready", so * there is no need to select() on it. * Other OSes may have the same limitation for sendfile() which @@ -11220,12 +11828,12 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp) #endif static ssize_t -maygvl_read(int has_gvl, int fd, void *buf, size_t count) +maygvl_read(int has_gvl, rb_io_t *fptr, void *buf, size_t count) { if (has_gvl) - return rb_read_internal(fd, buf, count); + return rb_read_internal(fptr, buf, count); else - return read(fd, buf, count); + return read(fptr->fd, buf, count); } static ssize_t @@ -11234,11 +11842,11 @@ maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, ssize_t ss; retry_read: if (offset < (off_t)0) { - ss = maygvl_read(has_gvl, stp->src_fd, buf, len); + ss = maygvl_read(has_gvl, stp->src_fptr, buf, len); } else { #ifdef HAVE_PREAD - ss = pread(stp->src_fd, buf, len, offset); + ss = pread(stp->src_fptr->fd, buf, len, offset); #else stp->notimp = "pread"; return -1; @@ -11252,7 +11860,7 @@ maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, goto retry_read; switch (errno) { case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN +#if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif { @@ -11278,11 +11886,11 @@ nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len) ssize_t ss; int off = 0; while (len) { - ss = write(stp->dst_fd, buf+off, len); + ss = write(stp->dst_fptr->fd, buf+off, len); if (ss < 0) { if (maygvl_copy_stream_continue_p(0, stp)) continue; - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (io_again_p(errno)) { int ret = nogvl_copy_stream_wait_write(stp); if (ret < 0) return ret; continue; @@ -11318,7 +11926,7 @@ nogvl_copy_stream_read_write(struct copy_stream_struct *stp) if (use_pread && stp->close_src) { off_t r; errno = 0; - r = lseek(stp->src_fd, src_offset, SEEK_SET); + r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET); if (r < (off_t)0 && errno) { stp->syserr = "lseek"; stp->error_no = errno; @@ -11400,7 +12008,7 @@ copy_stream_fallback_body(VALUE arg) off_t off = stp->src_offset; ID read_method = id_readpartial; - if (stp->src_fd < 0) { + if (!stp->src_fptr) { if (!rb_respond_to(stp->src, read_method)) { read_method = id_read; } @@ -11419,7 +12027,7 @@ copy_stream_fallback_body(VALUE arg) } l = buflen < rest ? buflen : (long)rest; } - if (stp->src_fd < 0) { + if (!stp->src_fptr) { VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf); if (read_method == id_read && NIL_P(rc)) @@ -11452,7 +12060,7 @@ copy_stream_fallback_body(VALUE arg) static VALUE copy_stream_fallback(struct copy_stream_struct *stp) { - if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) { + if (!stp->src_fptr && stp->src_offset >= (off_t)0) { rb_raise(rb_eArgError, "cannot specify src_offset for non-IO"); } rb_rescue2(copy_stream_fallback_body, (VALUE)stp, @@ -11466,8 +12074,6 @@ copy_stream_body(VALUE arg) { struct copy_stream_struct *stp = (struct copy_stream_struct *)arg; VALUE src_io = stp->src, dst_io = stp->dst; - rb_io_t *src_fptr = 0, *dst_fptr = 0; - int src_fd, dst_fd; const int common_oflags = 0 #ifdef O_NOCTTY | O_NOCTTY @@ -11482,7 +12088,7 @@ copy_stream_body(VALUE arg) !(RB_TYPE_P(src_io, T_FILE) || RB_TYPE_P(src_io, T_STRING) || rb_respond_to(src_io, rb_intern("to_path")))) { - src_fd = -1; + stp->src_fptr = NULL; } else { int stat_ret; @@ -11499,24 +12105,22 @@ copy_stream_body(VALUE arg) stp->src = src_io; stp->close_src = 1; } - GetOpenFile(src_io, src_fptr); - rb_io_check_byte_readable(src_fptr); - src_fd = src_fptr->fd; + RB_IO_POINTER(src_io, stp->src_fptr); + rb_io_check_byte_readable(stp->src_fptr); - stat_ret = fstat(src_fd, &stp->src_stat); + stat_ret = fstat(stp->src_fptr->fd, &stp->src_stat); if (stat_ret < 0) { stp->syserr = "fstat"; stp->error_no = errno; return Qnil; } } - stp->src_fd = src_fd; if (dst_io == argf || !(RB_TYPE_P(dst_io, T_FILE) || RB_TYPE_P(dst_io, T_STRING) || rb_respond_to(dst_io, rb_intern("to_path")))) { - dst_fd = -1; + stp->dst_fptr = NULL; } else { int stat_ret; @@ -11538,38 +12142,36 @@ copy_stream_body(VALUE arg) dst_io = GetWriteIO(dst_io); stp->dst = dst_io; } - GetOpenFile(dst_io, dst_fptr); - rb_io_check_writable(dst_fptr); - dst_fd = dst_fptr->fd; + RB_IO_POINTER(dst_io, stp->dst_fptr); + rb_io_check_writable(stp->dst_fptr); - stat_ret = fstat(dst_fd, &stp->dst_stat); + stat_ret = fstat(stp->dst_fptr->fd, &stp->dst_stat); if (stat_ret < 0) { stp->syserr = "fstat"; stp->error_no = errno; return Qnil; } } - stp->dst_fd = dst_fd; #ifdef O_BINARY - if (src_fptr) - SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr); + if (stp->src_fptr) + SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr); #endif - if (dst_fptr) - io_ascii8bit_binmode(dst_fptr); + if (stp->dst_fptr) + io_ascii8bit_binmode(stp->dst_fptr); - if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) { - size_t len = src_fptr->rbuf.len; + if (stp->src_offset < (off_t)0 && stp->src_fptr && stp->src_fptr->rbuf.len) { + size_t len = stp->src_fptr->rbuf.len; VALUE str; if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) { len = (size_t)stp->copy_length; } str = rb_str_buf_new(len); rb_str_resize(str,len); - read_buffered_data(RSTRING_PTR(str), len, src_fptr); - if (dst_fptr) { /* IO or filename */ - if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0) - rb_sys_fail(0); + read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr); + if (stp->dst_fptr) { /* IO or filename */ + if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0) + rb_sys_fail_on_write(stp->dst_fptr); } else /* others such as StringIO */ rb_io_write(dst_io, str); @@ -11579,14 +12181,14 @@ copy_stream_body(VALUE arg) stp->copy_length -= len; } - if (dst_fptr && io_fflush(dst_fptr) < 0) { + if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) { rb_raise(rb_eIOError, "flush failed"); } if (stp->copy_length == 0) return Qnil; - if (src_fd < 0 || dst_fd < 0) { + if (stp->src_fptr == NULL || stp->dst_fptr == NULL) { return copy_stream_fallback(stp); } @@ -11665,6 +12267,9 @@ rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io) st.src = src; st.dst = dst; + st.src_fptr = NULL; + st.dst_fptr = NULL; + if (NIL_P(length)) st.copy_length = (off_t)-1; else @@ -11691,9 +12296,8 @@ rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io) static VALUE rb_io_external_encoding(VALUE io) { - rb_io_t *fptr; + rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr; - GetOpenFile(io, fptr); if (fptr->encs.enc2) { return rb_enc_from_encoding(fptr->encs.enc2); } @@ -11716,9 +12320,8 @@ rb_io_external_encoding(VALUE io) static VALUE rb_io_internal_encoding(VALUE io) { - rb_io_t *fptr; + rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr; - GetOpenFile(io, fptr); if (!fptr->encs.enc2) return Qnil; return rb_enc_from_encoding(io_read_encoding(fptr)); } @@ -11749,7 +12352,7 @@ rb_io_set_encoding(int argc, VALUE *argv, VALUE io) VALUE v1, v2, opt; if (!RB_TYPE_P(io, T_FILE)) { - return rb_funcallv(io, id_set_encoding, argc, argv); + return forward(io, id_set_encoding, argc, argv); } argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt); @@ -11763,6 +12366,18 @@ rb_stdio_set_default_encoding(void) { VALUE val = Qnil; +#ifdef _WIN32 + if (isatty(fileno(stdin))) { + rb_encoding *external = rb_locale_encoding(); + rb_encoding *internal = rb_default_internal_encoding(); + if (!internal) internal = rb_default_external_encoding(); + io_encoding_set(RFILE(rb_stdin)->fptr, + rb_enc_from_encoding(external), + rb_enc_from_encoding(internal), + Qnil); + } + else +#endif rb_io_set_encoding(1, &val, rb_stdin); rb_io_set_encoding(1, &val, rb_stdout); rb_io_set_encoding(1, &val, rb_stderr); @@ -12115,8 +12730,7 @@ argf_read(int argc, VALUE *argv, VALUE argf) else if (argc >= 1) { long slen = RSTRING_LEN(str); if (slen < len) { - len -= slen; - argv[0] = INT2NUM(len); + argv[0] = LONG2NUM(len - slen); goto retry; } } @@ -12265,7 +12879,7 @@ argf_getc(VALUE argf) retry: if (!next_argv()) return Qnil; if (ARGF_GENERIC_INPUT_P()) { - ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0); + ch = forward_current(rb_intern("getc"), 0, 0); } else { ch = rb_io_getc(ARGF.current_file); @@ -12305,7 +12919,7 @@ argf_getbyte(VALUE argf) retry: if (!next_argv()) return Qnil; if (!RB_TYPE_P(ARGF.current_file, T_FILE)) { - ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0); + ch = forward_current(rb_intern("getbyte"), 0, 0); } else { ch = rb_io_getbyte(ARGF.current_file); @@ -12345,7 +12959,7 @@ argf_readchar(VALUE argf) retry: if (!next_argv()) rb_eof_error(); if (!RB_TYPE_P(ARGF.current_file, T_FILE)) { - ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0); + ch = forward_current(rb_intern("getc"), 0, 0); } else { ch = rb_io_getc(ARGF.current_file); @@ -12480,24 +13094,8 @@ argf_each_line(int argc, VALUE *argv, VALUE argf) return argf; } -/* - * This is a deprecated alias for #each_line. - */ - -static VALUE -argf_lines(int argc, VALUE *argv, VALUE argf) -{ - rb_warn_deprecated("ARGF#lines", "#each_line"); - if (!rb_block_given_p()) - return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv); - return argf_each_line(argc, argv, argf); -} - /* * call-seq: - * ARGF.bytes {|byte| block } -> ARGF - * ARGF.bytes -> an_enumerator - * * ARGF.each_byte {|byte| block } -> ARGF * ARGF.each_byte -> an_enumerator * @@ -12527,19 +13125,6 @@ argf_each_byte(VALUE argf) return argf; } -/* - * This is a deprecated alias for #each_byte. - */ - -static VALUE -argf_bytes(VALUE argf) -{ - rb_warn_deprecated("ARGF#bytes", "#each_byte"); - if (!rb_block_given_p()) - return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0); - return argf_each_byte(argf); -} - /* * call-seq: * ARGF.each_char {|char| block } -> ARGF @@ -12566,19 +13151,6 @@ argf_each_char(VALUE argf) return argf; } -/* - * This is a deprecated alias for #each_char. - */ - -static VALUE -argf_chars(VALUE argf) -{ - rb_warn_deprecated("ARGF#chars", "#each_char"); - if (!rb_block_given_p()) - return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0); - return argf_each_char(argf); -} - /* * call-seq: * ARGF.each_codepoint {|codepoint| block } -> ARGF @@ -12605,19 +13177,6 @@ argf_each_codepoint(VALUE argf) return argf; } -/* - * This is a deprecated alias for #each_codepoint. - */ - -static VALUE -argf_codepoints(VALUE argf) -{ - rb_warn_deprecated("ARGF#codepoints", "#each_codepoint"); - if (!rb_block_given_p()) - return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0); - return argf_each_codepoint(argf); -} - /* * call-seq: * ARGF.filename -> String @@ -12715,7 +13274,7 @@ argf_binmode_m(VALUE argf) static VALUE argf_binmode_p(VALUE argf) { - return ARGF.binmode ? Qtrue : Qfalse; + return RBOOL(ARGF.binmode); } /* @@ -12864,7 +13423,7 @@ opt_i_set(VALUE val, ID id, VALUE *var) void ruby_set_inplace_mode(const char *suffix) { - ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix); + ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix)); } /* @@ -12928,53 +13487,55 @@ argf_write(VALUE argf, VALUE str) } void -rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg) +rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg) { - rb_readwrite_syserr_fail(writable, errno, mesg); + rb_readwrite_syserr_fail(waiting, errno, mesg); } void -rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg) +rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg) { - VALUE arg; + VALUE arg, c = Qnil; arg = mesg ? rb_str_new2(mesg) : Qnil; - if (writable == RB_IO_WAIT_WRITABLE) { + switch (waiting) { + case RB_IO_WAIT_WRITABLE: switch (n) { case EAGAIN: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable)); + c = rb_eEAGAINWaitWritable; break; #if EAGAIN != EWOULDBLOCK case EWOULDBLOCK: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable)); + c = rb_eEWOULDBLOCKWaitWritable; break; #endif case EINPROGRESS: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable)); + c = rb_eEINPROGRESSWaitWritable; break; default: - rb_mod_sys_fail_str(rb_mWaitWritable, arg); + rb_mod_syserr_fail_str(rb_mWaitWritable, n, arg); } - } - else if (writable == RB_IO_WAIT_READABLE) { + break; + case RB_IO_WAIT_READABLE: switch (n) { case EAGAIN: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable)); + c = rb_eEAGAINWaitReadable; break; #if EAGAIN != EWOULDBLOCK case EWOULDBLOCK: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable)); + c = rb_eEWOULDBLOCKWaitReadable; break; #endif case EINPROGRESS: - rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable)); + c = rb_eEINPROGRESSWaitReadable; break; default: - rb_mod_sys_fail_str(rb_mWaitReadable, arg); + rb_mod_syserr_fail_str(rb_mWaitReadable, n, arg); } + break; + default: + rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting); } - else { - rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable); - } + rb_exc_raise(rb_class_new_instance(1, &arg, c)); } static VALUE @@ -13142,14 +13703,431 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y) * require 'io/console' * rows, columns = $stdout.winsize * puts "Your screen is #{columns} wide and #{rows} tall" + * + * == Example Files + * + * Many examples here use these filenames and their corresponding files: + * + * - t.txt: A text-only file that is assumed to exist via: + * + * text = <<~EOT + * This is line one. + * This is the second line. + * This is the third line. + * EOT + * File.write('t.txt', text) + * + * - t.dat: A data file that is assumed to exist via: + * + * data = "\u9990\u9991\u9992\u9993\u9994" + * f = File.open('t.dat', 'wb:UTF-16') + * f.write(data) + * f.close + * + * - t.rus: A Russian-language text file that is assumed to exist via: + * + * File.write('t.rus', "\u{442 435 441 442}") + * + * - t.tmp: A file that is assumed _not_ to exist. + * + * == Modes + * + * A number of \IO method calls must or may specify a _mode_ for the stream; + * the mode determines how stream is to be accessible, including: + * + * - Whether the stream is to be read-only, write-only, or read-write. + * - Whether the stream is positioned at its beginning or its end. + * - Whether the stream treats data as text-only or binary. + * - The external and internal encodings. + * + * === Mode Specified as an \Integer + * + * When +mode+ is an integer it must be one or more (combined by bitwise OR (|) + * of the modes defined in File::Constants: + * + * - +File::RDONLY+: Open for reading only. + * - +File::WRONLY+: Open for writing only. + * - +File::RDWR+: Open for reading and writing. + * - +File::APPEND+: Open for appending only. + * - +File::CREAT+: Create file if it does not exist. + * - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists. + * + * Examples: + * + * File.new('t.txt', File::RDONLY) + * File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL) + * + * Note: Method IO#set_encoding does not allow the mode to be specified as an integer. + * + * === Mode Specified As a \String + * + * When +mode+ is a string it must begin with one of the following: + * + * - 'r': Read-only stream, positioned at the beginning; + * the stream cannot be changed to writable. + * - 'w': Write-only stream, positioned at the beginning; + * the stream cannot be changed to readable. + * - 'a': Write-only stream, positioned at the end; + * every write appends to the end; + * the stream cannot be changed to readable. + * - 'r+': Read-write stream, positioned at the beginning. + * - 'w+': Read-write stream, positioned at the end. + * - 'a+': Read-write stream, positioned at the end. + * + * For a writable file stream (that is, any except read-only), + * the file is truncated to zero if it exists, + * and is created if it does not exist. + * + * Examples: + * + * File.open('t.txt', 'r') + * File.open('t.tmp', 'w') + * + * Either of the following may be suffixed to any of the above: + * + * - 't': Text data; sets the default external encoding to +Encoding::UTF_8+; + * on Windows, enables conversion between EOL and CRLF. + * - 'b': Binary data; sets the default external encoding to +Encoding::ASCII_8BIT+; + * on Windows, suppresses conversion between EOL and CRLF. + * + * If neither is given, the stream defaults to text data. + * + * Examples: + * + * File.open('t.txt', 'rt') + * File.open('t.dat', 'rb') + * + * The following may be suffixed to any writable mode above: + * + * - 'x': Creates the file if it does not exist; + * raises an exception if the file exists. + * + * Example: + * + * File.open('t.tmp', 'wx') + * + * Finally, the mode string may specify encodings -- + * either external encoding only or both external and internal encodings -- + * by appending one or both encoding names, separated by colons: + * + * f = File.new('t.dat', 'rb') + * f.external_encoding # => # + * f.internal_encoding # => nil + * f = File.new('t.dat', 'rb:UTF-16') + * f.external_encoding # => # + * f.internal_encoding # => nil + * f = File.new('t.dat', 'rb:UTF-16:UTF-16') + * f.external_encoding # => # + * f.internal_encoding # => # + * + * The numerous encoding names are available in array Encoding.name_list: + * + * Encoding.name_list.size # => 175 + * Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"] + * + * == Encodings + * + * When the external encoding is set, + * strings read are tagged by that encoding + * when reading, and strings written are converted to that + * encoding when writing. + * + * When both external and internal encodings are set, + * strings read are converted from external to internal encoding, + * and strings written are converted from internal to external encoding. + * For further details about transcoding input and output, see Encoding. + * + * If the external encoding is 'BOM|UTF-8', 'BOM|UTF-16LE' + * or 'BOM|UTF16-BE', Ruby checks for + * a Unicode BOM in the input document to help determine the encoding. For + * UTF-16 encodings the file open mode must be binary. + * If the BOM is found, it is stripped and the external encoding from the BOM is used. + * + * Note that the BOM-style encoding option is case insensitive, + * so 'bom|utf-8' is also valid.) + * + * == Open Options + * + * A number of \IO methods accept an optional parameter +opts+, + * which determines how a new stream is to be opened: + * + * - +:mode+: Stream mode. + * - +:flags+: \Integer file open flags; + * If +mode+ is also given, the two are bitwise-ORed. + * - +:external_encoding+: External encoding for the stream. + * - +:internal_encoding+: Internal encoding for the stream. + * '-' is a synonym for the default internal encoding. + * If the value is +nil+ no conversion occurs. + * - +:encoding+: Specifies external and internal encodings as 'extern:intern'. + * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise. + * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise. + * - +:autoclose+: If a truthy value, specifies that the +fd+ will close + * when the stream closes; otherwise it remains open. + * + * Also available are the options offered in String#encode, + * which may control conversion between external internal encoding. + * + * == Getline Options + * + * A number of \IO methods accept optional keyword arguments + * that determine how a stream is to be treated: + * + * - +:chomp+: If +true+, line separators are omitted; default is +false+. + * + * == Position + * + * An \IO stream has a _position_, which is the non-negative integer offset + * (in bytes) in the stream where the next read or write will occur. + * + * Note that a text stream may have multi-byte characters, + * so a text stream whose position is +n+ (_bytes_) may not have +n+ _characters_ + * preceding the current position -- there may be fewer. + * + * A new stream is initially positioned: + * + * - At the beginning (position +0+) + * if its mode is 'r', 'w', or 'r+'. + * - At the end (position self.size) + * if its mode is 'a', 'w+', or 'a+'. + * + * Methods to query the position: + * + * - IO#tell and its alias IO#pos return the position for an open stream. + * - IO#eof? and its alias IO#eof return whether the position is at the end + * of a readable stream. + * + * Reading from a stream usually changes its position: + * + * f = File.open('t.txt') + * f.tell # => 0 + * f.readline # => "This is line one.\n" + * f.tell # => 19 + * f.readline # => "This is the second line.\n" + * f.tell # => 45 + * f.eof? # => false + * f.readline # => "Here's the third line.\n" + * f.eof? # => true + * + * + * Writing to a stream usually changes its position: + * + * f = File.open('t.tmp', 'w') + * f.tell # => 0 + * f.write('foo') # => 3 + * f.tell # => 3 + * f.write('bar') # => 3 + * f.tell # => 6 + * + * + * Iterating over a stream usually changes its position: + * + * f = File.open('t.txt') + * f.each do |line| + * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}" + * end + * + * Output: + * + * "position=19 eof?=false line=This is line one.\n" + * "position=45 eof?=false line=This is the second line.\n" + * "position=70 eof?=true line=This is the third line.\n" + * + * The position may also be changed by certain other methods: + * + * - IO#pos= and IO#seek change the position to a specified offset. + * - IO#rewind changes the position to the beginning. + * + * == Line Number + * + * A readable \IO stream has a _line_ _number_, + * which is the non-negative integer line number + * in the stream where the next read will occur. + * + * A new stream is initially has line number +0+. + * + * \Method IO#lineno returns the line number. + * + * Reading lines from a stream usually changes its line number: + * + * f = File.open('t.txt', 'r') + * f.lineno # => 0 + * f.readline # => "This is line one.\n" + * f.lineno # => 1 + * f.readline # => "This is the second line.\n" + * f.lineno # => 2 + * f.readline # => "Here's the third line.\n" + * f.lineno # => 3 + * f.eof? # => true + * + * Iterating over lines in a stream usually changes its line number: + * + * f = File.open('t.txt') + * f.each_line do |line| + * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}" + * end + * + * Output: + * + * "position=19 eof?=false line=This is line one.\n" + * "position=45 eof?=false line=This is the second line.\n" + * "position=70 eof?=true line=This is the third line.\n" + * + * == What's Here + * + * First, what's elsewhere. \Class \IO: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * which provides dozens of additional methods. + * + * Here, class \IO provides methods that are useful for: + * + * - {Creating}[#class-IO-label-Creating] + * - {Reading}[#class-IO-label-Reading] + * - {Writing}[#class-IO-label-Writing] + * - {Positioning}[#class-IO-label-Positioning] + * - {Iterating}[#class-IO-label-Iterating] + * - {Settings}[#class-IO-label-Settings] + * - {Querying}[#class-IO-label-Querying] + * - {Buffering}[#class-IO-label-Buffering] + * - {Low-Level Access}[#class-IO-label-Low-Level+Access] + * - {Other}[#class-IO-label-Other] + * + * === Creating + * + * - ::new (aliased as ::for_fd):: Creates and returns a new \IO object for the given + * integer file descriptor. + * - ::open:: Creates a new \IO object. + * - ::pipe:: Creates a connected pair of reader and writer \IO objects. + * - ::popen:: Creates an \IO object to interact with a subprocess. + * - ::select:: Selects which given \IO instances are ready for reading, + * writing, or have pending exceptions. + * + * === Reading + * + * - ::binread:: Returns a binary string with all or a subset of bytes + * from the given file. + * - ::read:: Returns a string with all or a subset of bytes from the given file. + * - ::readlines:: Returns an array of strings, which are the lines from the given file. + * - #getbyte:: Returns the next 8-bit byte read from +self+ as an integer. + * - #getc:: Returns the next character read from +self+ as a string. + * - #gets:: Returns the line read from +self+. + * - #pread:: Returns all or the next _n_ bytes read from +self+, + * not updating the receiver's offset. + * - #read:: Returns all remaining or the next _n_ bytes read from +self+ + * for a given _n_. + * - #read_nonblock:: the next _n_ bytes read from +self+ for a given _n_, + * in non-block mode. + * - #readbyte:: Returns the next byte read from +self+; + * same as #getbyte, but raises an exception on end-of-file. + * - #readchar:: Returns the next character read from +self+; + * same as #getc, but raises an exception on end-of-file. + * - #readline:: Returns the next line read from +self+; + * same as #getline, but raises an exception of end-of-file. + * - #readlines:: Returns an array of all lines read read from +self+. + * - #readpartial:: Returns up to the given number of bytes from +self+. + * + * === Writing + * + * - ::binwrite:: Writes the given string to the file at the given filepath, + in binary mode. + * - ::write:: Writes the given string to +self+. + * - {::<<}[#method-i-3C-3C]:: Appends the given string to +self+. + * - #print:: Prints last read line or given objects to +self+. + * - #printf:: Writes to +self+ based on the given format string and objects. + * - #putc:: Writes a character to +self+. + * - #puts:: Writes lines to +self+, making sure line ends with a newline. + * - #pwrite:: Writes the given string at the given offset, + * not updating the receiver's offset. + * - #write:: Writes one or more given strings to +self+. + * - #write_nonblock:: Writes one or more given strings to +self+ in non-blocking mode. + * + * === Positioning + * + * - #lineno:: Returns the current line number in +self+. + * - #lineno=:: Sets the line number is +self+. + * - #pos (aliased as #tell):: Returns the current byte offset in +self+. + * - #pos=:: Sets the byte offset in +self+. + * - #reopen:: Reassociates +self+ with a new or existing \IO stream. + * - #rewind:: Positions +self+ to the beginning of input. + * - #seek:: Sets the offset for +self+ relative to given position. + * + * === Iterating + * + * - ::foreach:: Yields each line of given file to the block. + * - #each (aliased as #each_line):: Calls the given block + * with each successive line in +self+. + * - #each_byte:: Calls the given block with each successive byte in +self+ + * as an integer. + * - #each_char:: Calls the given block with each successive character in +self+ + * as a string. + * - #each_codepoint:: Calls the given block with each successive codepoint in +self+ + * as an integer. + * + * === Settings + * + * - #autoclose=:: Sets whether +self+ auto-closes. + * - #binmode:: Sets +self+ to binary mode. + * - #close:: Closes +self+. + * - #close_on_exec=:: Sets the close-on-exec flag. + * - #close_read:: Closes +self+ for reading. + * - #close_write:: Closes +self+ for writing. + * - #set_encoding:: Sets the encoding for +self+. + * - #set_encoding_by_bom:: Sets the encoding for +self+, based on its + * Unicode byte-order-mark. + * - #sync=:: Sets the sync-mode to the given value. + * + * === Querying + * + * - #autoclose?:: Returns whether +self+ auto-closes. + * - #binmode?:: Returns whether +self+ is in binary mode. + * - #close_on_exec?:: Returns the close-on-exec flag for +self+. + * - #closed?:: Returns whether +self+ is closed. + * - #eof? (aliased as #eof):: Returns whether +self+ is at end-of-file. + * - #external_encoding:: Returns the external encoding object for +self+. + * - #fileno (aliased as #to_i):: Returns the integer file descriptor for +self+ + * - #internal_encoding:: Returns the internal encoding object for +self+. + * - #pid:: Returns the process ID of a child process associated with +self+, + * if +self+ was created by ::popen. + * - #stat:: Returns the File::Stat object containing status information for +self+. + * - #sync:: Returns whether +self+ is in sync-mode. + * - #tty (aliased as #isatty):: Returns whether +self+ is a terminal. + * + * === Buffering + * + * - #fdatasync:: Immediately writes all buffered data in +self+ to disk. + * - #flush:: Flushes any buffered data within +self+ to the underlying + * operating system. + * - #fsync:: Immediately writes all buffered data and attributes in +self+ to disk. + * - #ungetbyte:: Prepends buffer for +self+ with given integer byte or string. + * - #ungetc:: Prepends buffer for +self+ with given string. + * + * === Low-Level Access + * + * - ::sysopen:: Opens the file given by its path, + * returning the integer file descriptor. + * - #advise:: Announces the intention to access data from +self+ in a specific way. + * - #fcntl:: Passes a low-level command to the file specified + * by the given file descriptor. + * - #ioctl:: Passes a low-level command to the device specified + * by the given file descriptor. + * - #sysread:: Returns up to the next _n_ bytes read from self using a low-level read. + * - #sysseek:: Sets the offset for +self+. + * - #syswrite:: Writes the given string to +self+ using a low-level write. + * + * === Other + * + * - ::copy_stream:: Copies data from a source to a destination, + * each of which is a filepath or an \IO-like object. + * - ::try_convert:: Returns a new \IO object resulting from converting + * the given object. + * - #inspect:: Returns the string representation of +self+. + * */ void Init_IO(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - VALUE rb_cARGF; #ifdef __CYGWIN__ #include @@ -13167,12 +14145,13 @@ Init_IO(void) rb_eIOError = rb_define_class("IOError", rb_eStandardError); rb_eEOFError = rb_define_class("EOFError", rb_eIOError); - id_write = rb_intern("write"); - id_read = rb_intern("read"); - id_getc = rb_intern("getc"); - id_flush = rb_intern("flush"); - id_readpartial = rb_intern("readpartial"); - id_set_encoding = rb_intern("set_encoding"); + id_write = rb_intern_const("write"); + id_read = rb_intern_const("read"); + id_getc = rb_intern_const("getc"); + id_flush = rb_intern_const("flush"); + id_readpartial = rb_intern_const("readpartial"); + id_set_encoding = rb_intern_const("set_encoding"); + id_fileno = rb_intern_const("fileno"); rb_define_global_function("syscall", rb_f_syscall, -1); @@ -13195,6 +14174,10 @@ Init_IO(void) rb_cIO = rb_define_class("IO", rb_cObject); rb_include_module(rb_cIO, rb_mEnumerable); + rb_define_const(rb_cIO, "READABLE", INT2NUM(RUBY_IO_READABLE)); + rb_define_const(rb_cIO, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE)); + rb_define_const(rb_cIO, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY)); + /* exception to wait for reading. see IO.select. */ rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable"); /* exception to wait for writing. see IO.select. */ @@ -13252,17 +14235,18 @@ Init_IO(void) rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1); rb_output_fs = Qnil; - rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter); + rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter); rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */ rb_gc_register_mark_object(rb_default_rs); rb_rs = rb_default_rs; rb_output_rs = Qnil; - rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter); - rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter); - rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter); + rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter); + rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter); + rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter); rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE); + rb_gvar_ractor_local("$_"); rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1); rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1); @@ -13277,10 +14261,6 @@ Init_IO(void) rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0); rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0); rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0); - rb_define_method(rb_cIO, "lines", rb_io_lines, -1); - rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0); - rb_define_method(rb_cIO, "chars", rb_io_chars, 0); - rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0); rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1); rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1); @@ -13365,13 +14345,24 @@ Init_IO(void) rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0); rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1); - rb_define_variable("$stdin", &rb_stdin); - rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, ""); - rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter); - rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, ""); - rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter); - rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, ""); - rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter); + rb_define_virtual_variable("$stdin", stdin_getter, stdin_setter); + rb_define_virtual_variable("$stdout", stdout_getter, stdout_setter); + rb_define_virtual_variable("$>", stdout_getter, stdout_setter); + rb_define_virtual_variable("$stderr", stderr_getter, stderr_setter); + + rb_gvar_ractor_local("$stdin"); + rb_gvar_ractor_local("$stdout"); + rb_gvar_ractor_local("$>"); + rb_gvar_ractor_local("$stderr"); + + rb_stdin = rb_io_prep_stdin(); + rb_stdout = rb_io_prep_stdout(); + rb_stderr = rb_io_prep_stderr(); + + rb_global_variable(&rb_stdin); + rb_global_variable(&rb_stdout); + rb_global_variable(&rb_stderr); + orig_stdout = rb_stdout; orig_stderr = rb_stderr; @@ -13408,10 +14399,6 @@ Init_IO(void) rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0); rb_define_method(rb_cARGF, "each_char", argf_each_char, 0); rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0); - rb_define_method(rb_cARGF, "lines", argf_lines, -1); - rb_define_method(rb_cARGF, "bytes", argf_bytes, 0); - rb_define_method(rb_cARGF, "chars", argf_chars, 0); - rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0); rb_define_method(rb_cARGF, "read", argf_read, -1); rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1); @@ -13473,6 +14460,8 @@ Init_IO(void) ARGF.filename = rb_str_new2("-"); rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set); + rb_gvar_ractor_local("$-i"); + rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter); #if defined (_WIN32) || defined(__CYGWIN__) @@ -13483,39 +14472,33 @@ Init_IO(void) rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1); - sym_mode = ID2SYM(rb_intern("mode")); - sym_perm = ID2SYM(rb_intern("perm")); - sym_flags = ID2SYM(rb_intern("flags")); - sym_extenc = ID2SYM(rb_intern("external_encoding")); - sym_intenc = ID2SYM(rb_intern("internal_encoding")); + sym_mode = ID2SYM(rb_intern_const("mode")); + sym_perm = ID2SYM(rb_intern_const("perm")); + sym_flags = ID2SYM(rb_intern_const("flags")); + sym_extenc = ID2SYM(rb_intern_const("external_encoding")); + sym_intenc = ID2SYM(rb_intern_const("internal_encoding")); sym_encoding = ID2SYM(rb_id_encoding()); - sym_open_args = ID2SYM(rb_intern("open_args")); - sym_textmode = ID2SYM(rb_intern("textmode")); - sym_binmode = ID2SYM(rb_intern("binmode")); - sym_autoclose = ID2SYM(rb_intern("autoclose")); - sym_normal = ID2SYM(rb_intern("normal")); - sym_sequential = ID2SYM(rb_intern("sequential")); - sym_random = ID2SYM(rb_intern("random")); - sym_willneed = ID2SYM(rb_intern("willneed")); - sym_dontneed = ID2SYM(rb_intern("dontneed")); - sym_noreuse = ID2SYM(rb_intern("noreuse")); - sym_SET = ID2SYM(rb_intern("SET")); - sym_CUR = ID2SYM(rb_intern("CUR")); - sym_END = ID2SYM(rb_intern("END")); + sym_open_args = ID2SYM(rb_intern_const("open_args")); + sym_textmode = ID2SYM(rb_intern_const("textmode")); + sym_binmode = ID2SYM(rb_intern_const("binmode")); + sym_autoclose = ID2SYM(rb_intern_const("autoclose")); + sym_normal = ID2SYM(rb_intern_const("normal")); + sym_sequential = ID2SYM(rb_intern_const("sequential")); + sym_random = ID2SYM(rb_intern_const("random")); + sym_willneed = ID2SYM(rb_intern_const("willneed")); + sym_dontneed = ID2SYM(rb_intern_const("dontneed")); + sym_noreuse = ID2SYM(rb_intern_const("noreuse")); + sym_SET = ID2SYM(rb_intern_const("SET")); + sym_CUR = ID2SYM(rb_intern_const("CUR")); + sym_END = ID2SYM(rb_intern_const("END")); #ifdef SEEK_DATA - sym_DATA = ID2SYM(rb_intern("DATA")); + sym_DATA = ID2SYM(rb_intern_const("DATA")); #endif #ifdef SEEK_HOLE - sym_HOLE = ID2SYM(rb_intern("HOLE")); + sym_HOLE = ID2SYM(rb_intern_const("HOLE")); #endif - sym_wait_readable = ID2SYM(rb_intern("wait_readable")); - sym_wait_writable = ID2SYM(rb_intern("wait_writable")); + sym_wait_readable = ID2SYM(rb_intern_const("wait_readable")); + sym_wait_writable = ID2SYM(rb_intern_const("wait_writable")); } #include "io.rbinc" - -void -Init_IO_nonblock(void) -{ - load_io(); -} diff --git a/ruby/io.rb b/ruby/io.rb index 1b6dddf9e..40873ea4f 100644 --- a/ruby/io.rb +++ b/ruby/io.rb @@ -60,7 +60,7 @@ class IO # return the symbol +:wait_readable+ instead. At EOF, it will return nil # instead of raising EOFError. def read_nonblock(len, buf = nil, exception: true) - __builtin_io_read_nonblock(len, buf, exception) + Primitive.io_read_nonblock(len, buf, exception) end # call-seq: @@ -118,6 +118,6 @@ def read_nonblock(len, buf = nil, exception: true) # that write_nonblock should not raise an IO::WaitWritable exception, but # return the symbol +:wait_writable+ instead. def write_nonblock(buf, exception: true) - __builtin_io_write_nonblock(buf, exception) + Primitive.io_write_nonblock(buf, exception) end end diff --git a/ruby/io.rbinc b/ruby/io.rbinc index d392d7faa..ae430e3a3 100644 --- a/ruby/io.rbinc +++ b/ruby/io.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with io.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_io(void) +void Init_builtin_io(void) { // table definition static const struct rb_builtin_function io_table[] = { diff --git a/ruby/io_buffer.c b/ruby/io_buffer.c new file mode 100644 index 000000000..5227a2a5b --- /dev/null +++ b/ruby/io_buffer.c @@ -0,0 +1,2214 @@ +/********************************************************************** + + io_buffer.c + + Copyright (C) 2021 Samuel Grant Dawson Williams + +**********************************************************************/ + +#include "ruby/io.h" +#include "ruby/io/buffer.h" +#include "ruby/fiber/scheduler.h" + +#include "internal.h" +#include "internal/string.h" +#include "internal/bits.h" +#include "internal/error.h" + +VALUE rb_cIOBuffer; +VALUE rb_eIOBufferLockedError; +VALUE rb_eIOBufferAllocationError; +VALUE rb_eIOBufferAccessError; +VALUE rb_eIOBufferInvalidatedError; + +size_t RUBY_IO_BUFFER_PAGE_SIZE; +size_t RUBY_IO_BUFFER_DEFAULT_SIZE; + +#ifdef _WIN32 +#else +#include +#include +#endif + +struct rb_io_buffer { + void *base; + size_t size; + enum rb_io_buffer_flags flags; + +#if defined(_WIN32) + HANDLE mapping; +#endif + + VALUE source; +}; + +static inline void * +io_buffer_map_memory(size_t size) +{ +#if defined(_WIN32) + void * base = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); + + if (!base) { + rb_sys_fail("io_buffer_map_memory:VirtualAlloc"); + } +#else + void * base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + + if (base == MAP_FAILED) { + rb_sys_fail("io_buffer_map_memory:mmap"); + } +#endif + + return base; +} + +static void +io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, off_t offset, enum rb_io_buffer_flags flags) +{ +#if defined(_WIN32) + HANDLE file = (HANDLE)_get_osfhandle(descriptor); + if (!file) rb_sys_fail("io_buffer_map_descriptor:_get_osfhandle"); + + DWORD protect = PAGE_READONLY, access = FILE_MAP_READ; + + if (flags & RB_IO_BUFFER_READONLY) { + data->flags |= RB_IO_BUFFER_READONLY; + } + else { + protect = PAGE_READWRITE; + access = FILE_MAP_WRITE; + } + + HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL); + if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping"); + + if (flags & RB_IO_BUFFER_PRIVATE) { + access |= FILE_MAP_COPY; + data->flags |= RB_IO_BUFFER_PRIVATE; + } else { + // This buffer refers to external data. + data->flags |= RB_IO_BUFFER_EXTERNAL; + } + + void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size); + + if (!base) { + CloseHandle(mapping); + rb_sys_fail("io_buffer_map_file:MapViewOfFile"); + } + + data->mapping = mapping; +#else + int protect = PROT_READ, access = 0; + + if (flags & RB_IO_BUFFER_READONLY) { + data->flags |= RB_IO_BUFFER_READONLY; + } + else { + protect |= PROT_WRITE; + } + + if (flags & RB_IO_BUFFER_PRIVATE) { + data->flags |= RB_IO_BUFFER_PRIVATE; + } + else { + // This buffer refers to external data. + data->flags |= RB_IO_BUFFER_EXTERNAL; + access |= MAP_SHARED; + } + + void *base = mmap(NULL, size, protect, access, descriptor, offset); + + if (base == MAP_FAILED) { + rb_sys_fail("io_buffer_map_file:mmap"); + } +#endif + + data->base = base; + data->size = size; + + data->flags |= RB_IO_BUFFER_MAPPED; +} + +static inline void +io_buffer_unmap(void* base, size_t size) +{ +#ifdef _WIN32 + VirtualFree(base, 0, MEM_RELEASE); +#else + munmap(base, size); +#endif +} + +static void +io_buffer_experimental(void) +{ + static int warned = 0; + + if (warned) return; + + warned = 1; + + if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) { + rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL, + "IO::Buffer is experimental and both the Ruby and C interface may change in the future!" + ); + } +} + +static void +io_buffer_zero(struct rb_io_buffer *data) +{ + data->base = NULL; + data->size = 0; +#if defined(_WIN32) + data->mapping = NULL; +#endif + data->source = Qnil; +} + +static void +io_buffer_initialize(struct rb_io_buffer *data, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source) +{ + if (base) { + // If we are provided a pointer, we use it. + } + else if (size) { + // If we are provided a non-zero size, we allocate it: + if (flags & RB_IO_BUFFER_INTERNAL) { + base = calloc(size, 1); + } + else if (flags & RB_IO_BUFFER_MAPPED) { + base = io_buffer_map_memory(size); + } + + if (!base) { + rb_raise(rb_eIOBufferAllocationError, "Could not allocate buffer!"); + } + } else { + // Otherwise we don't do anything. + return; + } + + data->base = base; + data->size = size; + data->flags = flags; + data->source = source; +} + +static int +io_buffer_free(struct rb_io_buffer *data) +{ + if (data->base) { + if (data->flags & RB_IO_BUFFER_INTERNAL) { + free(data->base); + } + + if (data->flags & RB_IO_BUFFER_MAPPED) { + io_buffer_unmap(data->base, data->size); + } + + if (RB_TYPE_P(data->source, T_STRING)) { + rb_str_unlocktmp(data->source); + } + + data->base = NULL; + +#if defined(_WIN32) + if (data->mapping) { + CloseHandle(data->mapping); + data->mapping = NULL; + } +#endif + data->size = 0; + data->flags = 0; + data->source = Qnil; + + return 1; + } + + return 0; +} + +void +rb_io_buffer_type_mark(void *_data) +{ + struct rb_io_buffer *data = _data; + rb_gc_mark(data->source); +} + +void +rb_io_buffer_type_free(void *_data) +{ + struct rb_io_buffer *data = _data; + + io_buffer_free(data); + + free(data); +} + +size_t +rb_io_buffer_type_size(const void *_data) +{ + const struct rb_io_buffer *data = _data; + size_t total = sizeof(struct rb_io_buffer); + + if (data->flags) { + total += data->size; + } + + return total; +} + +static const rb_data_type_t rb_io_buffer_type = { + .wrap_struct_name = "IO::Buffer", + .function = { + .dmark = rb_io_buffer_type_mark, + .dfree = rb_io_buffer_type_free, + .dsize = rb_io_buffer_type_size, + }, + .data = NULL, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +VALUE +rb_io_buffer_type_allocate(VALUE self) +{ + struct rb_io_buffer *data = NULL; + VALUE instance = TypedData_Make_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_zero(data); + + return instance; +} + +/* + * call-seq: IO::Buffer.for(string) -> io_buffer + * + * Creates a IO::Buffer from the given string's memory. The buffer remains + * associated with the string, and writing to a buffer will update the string's + * contents. + * + * Until #free is invoked on the buffer, either explicitly or via the garbage + * collector, the source string will be locked and cannot be modified. + * + * If the string is frozen, it will create a read-only buffer which cannot be + * modified. + * + * string = 'test' + * buffer = IO::Buffer.for(str) + * buffer.external? #=> true + * + * buffer.get_string(0, 1) + * # => "t" + * string + * # => "best" + * + * buffer.resize(100) + * # in `resize': Cannot resize external buffer! (IO::Buffer::AccessError) + */ +VALUE +rb_io_buffer_type_for(VALUE klass, VALUE string) +{ + io_buffer_experimental(); + + StringValue(string); + + VALUE instance = rb_io_buffer_type_allocate(klass); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, data); + + rb_str_locktmp(string); + + enum rb_io_buffer_flags flags = RB_IO_BUFFER_EXTERNAL; + + if (RB_OBJ_FROZEN(string)) + flags |= RB_IO_BUFFER_READONLY; + + io_buffer_initialize(data, RSTRING_PTR(string), RSTRING_LEN(string), flags, string); + + return instance; +} + +VALUE +rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags) +{ + VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_initialize(data, base, size, flags, Qnil); + + return instance; +} + +VALUE +rb_io_buffer_map(VALUE io, size_t size, off_t offset, enum rb_io_buffer_flags flags) +{ + io_buffer_experimental(); + + VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, data); + + int descriptor = rb_io_descriptor(io); + + io_buffer_map_file(data, descriptor, size, offset, flags); + + return instance; +} + +/* + * call-seq: IO::Buffer.map(file, [size, [offset, [flags]]]) -> io_buffer + * + * Create an IO::Buffer for reading from +file+ by memory-mapping the file. + * +file_io+ should be a +File+ instance, opened for reading. + * + * Optional +size+ and +offset+ of mapping can be specified. + * + * By default, the buffer would be immutable (read only); to create a writable + * mapping, you need to open a file in read-write mode, and explicitly pass + * +flags+ argument without IO::Buffer::IMMUTABLE. + * + * File.write('test.txt', 'test') + * + * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY) + * # => # + * + * buffer.readonly? # => true + * + * buffer.get_string + * # => "test" + * + * buffer.set_string('b', 0) + * # `set_string': Buffer is not writable! (IO::Buffer::AccessError) + * + * # create read/write mapping: length 4 bytes, offset 0, flags 0 + * buffer = IO::Buffer.map(File.open('test.txt', 'r+'), 4, 0) + * buffer.set_string('b', 0) + * # => 1 + * + * # Check it + * File.read('test.txt') + * # => "best" + * + * Note that some operating systems may not have cache coherency between mapped + * buffers and file reads. + * + */ +static VALUE +io_buffer_map(int argc, VALUE *argv, VALUE klass) +{ + if (argc < 1 || argc > 4) { + rb_error_arity(argc, 2, 4); + } + + // We might like to handle a string path? + VALUE io = argv[0]; + + size_t size; + if (argc >= 2 && !RB_NIL_P(argv[1])) { + size = RB_NUM2SIZE(argv[1]); + } + else { + off_t file_size = rb_file_size(io); + + // Compiler can confirm that we handled file_size < 0 case: + if (file_size < 0) { + rb_raise(rb_eArgError, "Invalid negative file size!"); + } + // Here, we assume that file_size is positive: + else if ((uintmax_t)file_size > SIZE_MAX) { + rb_raise(rb_eArgError, "File larger than address space!"); + } + else { + // This conversion should be safe: + size = (size_t)file_size; + } + } + + off_t offset = 0; + if (argc >= 3) { + offset = NUM2OFFT(argv[2]); + } + + enum rb_io_buffer_flags flags = 0; + if (argc >= 4) { + flags = RB_NUM2UINT(argv[3]); + } + + return rb_io_buffer_map(io, size, offset, flags); +} + +// Compute the optimal allocation flags for a buffer of the given size. +static inline enum rb_io_buffer_flags +io_flags_for_size(size_t size) +{ + if (size >= RUBY_IO_BUFFER_PAGE_SIZE) { + return RB_IO_BUFFER_MAPPED; + } + + return RB_IO_BUFFER_INTERNAL; +} + +/* + * call-seq: IO::Buffer.new([size = DEFAULT_SIZE, [flags = 0]]) -> io_buffer + * + * Create a new zero-filled IO::Buffer of +size+ bytes. + * By default, the buffer will be _internal_: directly allocated chunk + * of the memory. But if the requested +size+ is more than OS-specific + * IO::Bufer::PAGE_SIZE, the buffer would be allocated using the + * virtual memory mechanism (anonymous +mmap+ on Unix, +VirtualAlloc+ + * on Windows). The behavior can be forced by passing IO::Buffer::MAPPED + * as a second parameter. + * + * Examples + * + * buffer = IO::Buffer.new(4) + * # => + * # # + * # 0x00000000 00 00 00 00 .... + * + * buffer.get_string(0, 1) # => "\x00" + * + * buffer.set_string("test") + * buffer + * # => + * # # + * # 0x00000000 74 65 73 74 test + * + */ +VALUE +rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self) +{ + io_buffer_experimental(); + + if (argc < 0 || argc > 2) { + rb_error_arity(argc, 0, 2); + } + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + size_t size; + + if (argc > 0) { + size = RB_NUM2SIZE(argv[0]); + } else { + size = RUBY_IO_BUFFER_DEFAULT_SIZE; + } + + enum rb_io_buffer_flags flags = 0; + if (argc >= 2) { + flags = RB_NUM2UINT(argv[1]); + } + else { + flags |= io_flags_for_size(size); + } + + io_buffer_initialize(data, NULL, size, flags, Qnil); + + return self; +} + +static int +io_buffer_validate_slice(VALUE source, void *base, size_t size) +{ + void *source_base = NULL; + size_t source_size = 0; + + if (RB_TYPE_P(source, T_STRING)) { + RSTRING_GETMEM(source, source_base, source_size); + } + else { + rb_io_buffer_get_bytes(source, &source_base, &source_size); + } + + // Source is invalid: + if (source_base == NULL) return 0; + + // Base is out of range: + if (base < source_base) return 0; + + const void *source_end = (char*)source_base + source_size; + const void *end = (char*)base + size; + + // End is out of range: + if (end > source_end) return 0; + + // It seems okay: + return 1; +} + +static int +io_buffer_validate(struct rb_io_buffer *data) +{ + if (data->source != Qnil) { + // Only slices incur this overhead, unfortunately... better safe than sorry! + return io_buffer_validate_slice(data->source, data->base, data->size); + } + else { + return 1; + } +} + +/* + * call-seq: to_s -> string + * + * Short representation of the buffer. It includes the address, size and + * symbolic flags. This format is subject to change. + * + * puts IO::Buffer.new(4) # uses to_s internally + * # # + * + */ +VALUE +rb_io_buffer_to_s(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + VALUE result = rb_str_new_cstr("#<"); + + rb_str_append(result, rb_class_name(CLASS_OF(self))); + rb_str_catf(result, " %p+%"PRIdSIZE, data->base, data->size); + + if (data->base == NULL) { + rb_str_cat2(result, " NULL"); + } + + if (data->flags & RB_IO_BUFFER_EXTERNAL) { + rb_str_cat2(result, " EXTERNAL"); + } + + if (data->flags & RB_IO_BUFFER_INTERNAL) { + rb_str_cat2(result, " INTERNAL"); + } + + if (data->flags & RB_IO_BUFFER_MAPPED) { + rb_str_cat2(result, " MAPPED"); + } + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_str_cat2(result, " LOCKED"); + } + + if (data->flags & RB_IO_BUFFER_READONLY) { + rb_str_cat2(result, " READONLY"); + } + + if (data->source != Qnil) { + rb_str_cat2(result, " SLICE"); + } + + if (!io_buffer_validate(data)) { + rb_str_cat2(result, " INVALID"); + } + + return rb_str_cat2(result, ">"); +} + +static VALUE +io_buffer_hexdump(VALUE string, size_t width, char *base, size_t size, int first) +{ + char *text = alloca(width+1); + text[width] = '\0'; + + for (size_t offset = 0; offset < size; offset += width) { + memset(text, '\0', width); + if (first) { + rb_str_catf(string, "0x%08zx ", offset); + first = 0; + } else { + rb_str_catf(string, "\n0x%08zx ", offset); + } + + for (size_t i = 0; i < width; i += 1) { + if (offset+i < size) { + unsigned char value = ((unsigned char*)base)[offset+i]; + + if (value < 127 && isprint(value)) { + text[i] = (char)value; + } + else { + text[i] = '.'; + } + + rb_str_catf(string, " %02x", value); + } + else { + rb_str_cat2(string, " "); + } + } + + rb_str_catf(string, " %s", text); + } + + return string; +} + +static VALUE +rb_io_buffer_hexdump(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + VALUE result = Qnil; + + if (io_buffer_validate(data) && data->base) { + result = rb_str_buf_new(data->size*3 + (data->size/16)*12 + 1); + + io_buffer_hexdump(result, 16, data->base, data->size, 1); + } + + return result; +} + +VALUE +rb_io_buffer_inspect(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + VALUE result = rb_io_buffer_to_s(self); + + if (io_buffer_validate(data)) { + // Limit the maximum size genearted by inspect. + if (data->size <= 256) { + io_buffer_hexdump(result, 16, data->base, data->size, 0); + } + } + + return result; +} + +/* + * call-seq: size -> integer + * + * Returns the size of the buffer that was explicitly set (on creation with ::new + * or on #resize), or deduced on buffer's creation from string or file. + * + */ +VALUE +rb_io_buffer_size(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return SIZET2NUM(data->size); +} + +/* + * call-seq: valid? -> true or false + * + * Returns whether the buffer data is accessible. + * + * A buffer becomes invalid if it is a slice of another buffer which has been + * freed. + * + */ +static VALUE +rb_io_buffer_valid_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(io_buffer_validate(data)); +} + +/* + * call-seq: null? -> true or false + * + * If the buffer was freed with #free or was never allocated in the first + * place. + * + */ +static VALUE +rb_io_buffer_null_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->base == NULL); +} + +/* + * call-seq: external? -> true or false + * + * If the buffer is _external_, meaning it references from memory which is not + * allocated or mapped by the buffer itself. + * + * A buffer created using ::for has an external reference to the string's + * memory. + * + * External buffer can't be resized. + * + */ +static VALUE +rb_io_buffer_empty_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->size == 0); +} + +static VALUE +rb_io_buffer_external_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->flags & RB_IO_BUFFER_EXTERNAL); +} + +/* + * call-seq: internal? -> true or false + * + * If the buffer is _internal_, meaning it references memory allocated by the + * buffer itself. + * + * An internal buffer is not associated with any external memory (e.g. string) + * or file mapping. + * + * Internal buffers are created using ::new and is the default when the + * requested size is less than the IO::Buffer::PAGE_SIZE and it was not + * requested to be mapped on creation. + * + * Internal buffers can be resized, and such an operation will typically + * invalidate all slices, but not always. + * + */ +static VALUE +rb_io_buffer_internal_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->flags & RB_IO_BUFFER_INTERNAL); +} + +/* + * call-seq: mapped? -> true or false + * + * If the buffer is _mapped_, meaning it references memory mapped by the + * buffer. + * + * Mapped buffers are either anonymous, if created by ::new with the + * IO::Buffer::MAPPED flag or if the size was at least IO::Buffer::PAGE_SIZE, + * or backed by a file if created with ::map. + * + * Mapped buffers can usually be resized, and such an operation will typically + * invalidate all slices, but not always. + * + */ +static VALUE +rb_io_buffer_mapped_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->flags & RB_IO_BUFFER_MAPPED); +} + +/* + * call-seq: locked? -> true or false + * + * If the buffer is _locked_, meaning it is inside #locked block execution. + * Locked buffer can't be resized or freed, and another lock can't be acquired + * on it. + * + * Locking is not thread safe, but is a semantic used to ensure buffers don't + * move while being used by a system call. + * + * buffer.locked do + * buffer.write(io) # theoretical system call interface + * end + * + */ +static VALUE +rb_io_buffer_locked_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return RBOOL(data->flags & RB_IO_BUFFER_LOCKED); +} + +/* + * call-seq: readonly? -> true or false + * + * If the buffer is _read only_, meaning the buffer cannot be modified using + * #set_value, #set_string or #copy and similar. + * + * Frozen strings and read-only files create read-only buffers. + * + */ +int +rb_io_buffer_readonly_p(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + return data->flags & RB_IO_BUFFER_READONLY; +} + +static VALUE +io_buffer_readonly_p(VALUE self) +{ + return RBOOL(rb_io_buffer_readonly_p(self)); +} + +VALUE +rb_io_buffer_lock(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_raise(rb_eIOBufferLockedError, "Buffer already locked!"); + } + + data->flags |= RB_IO_BUFFER_LOCKED; + + return self; +} + +VALUE +rb_io_buffer_unlock(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (!(data->flags & RB_IO_BUFFER_LOCKED)) { + rb_raise(rb_eIOBufferLockedError, "Buffer not locked!"); + } + + data->flags &= ~RB_IO_BUFFER_LOCKED; + + return self; +} + +int +rb_io_buffer_try_unlock(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + data->flags &= ~RB_IO_BUFFER_LOCKED; + return 1; + } + + return 0; +} + +/* + * call-seq: locked { ... } + * + * Allows to process a buffer in exclusive way, for concurrency-safety. While + * the block is performed, the buffer is considered locked, and no other code + * can enter the lock. Also, locked buffer can't be changed with #resize or + * #free. + * + * buffer = IO::Buffer.new(4) + * buffer.locked? #=> false + * + * Fiber.schedule do + * buffer.locked do + * buffer.write(io) # theoretical system call interface + * end + * end + * + * Fiber.schedule do + * # in `locked': Buffer already locked! (IO::Buffer::LockedError) + * buffer.locked do + * buffer.set_string(...) + * end + * end + * + * The following operations acquire a lock: #resize, #free. + * + * Locking is not thread safe. It is designed as a safety net around + * non-blocking system calls. You can only share a buffer between threads with + * appropriate synchronisation techniques. + */ +VALUE +rb_io_buffer_locked(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_raise(rb_eIOBufferLockedError, "Buffer already locked!"); + } + + data->flags |= RB_IO_BUFFER_LOCKED; + + VALUE result = rb_yield(self); + + data->flags &= ~RB_IO_BUFFER_LOCKED; + + return result; +} + +/* + * call-seq: free -> self + * + * If the buffer references memory, release it back to the operating system. + * * for a _mapped_ buffer (e.g. from file): unmap. + * * for a buffer created from scratch: free memory. + * * for a buffer created from string: undo the association. + * + * After the buffer is freed, no further operations can't be performed on it. + * + * buffer = IO::Buffer.for('test') + * buffer.free + * # => # + * + * buffer.get_value(:U8, 0) + * # in `get_value': The buffer is not allocated! (IO::Buffer::AllocationError) + * + * buffer.get_string + * # in `get_string': The buffer is not allocated! (IO::Buffer::AllocationError) + * + * buffer.null? + * # => true + * + * You can resize a freed buffer to re-allocate it. + * + */ +VALUE +rb_io_buffer_free(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_raise(rb_eIOBufferLockedError, "Buffer is locked!"); + } + + io_buffer_free(data); + + return self; +} + +static inline void +io_buffer_validate_range(struct rb_io_buffer *data, size_t offset, size_t length) +{ + if (offset + length > data->size) { + rb_raise(rb_eArgError, "Specified offset+length exceeds data size!"); + } +} + +/* + * call-seq: slice(offset, length) -> io_buffer + * + * Produce another IO::Buffer which is a slice (or view into) the current one + * starting at +offset+ bytes and going for +length+ bytes. + * + * The slicing happens without copying of memory, and the slice keeps being + * associated with the original buffer's source (string, or file), if any. + * + * Raises RuntimeError if the offset+length is out of the current + * buffer's bounds. + * + * string = 'test' + * buffer = IO::Buffer.for(string) + * + * slice = buffer.slice(1, 2) + * # => + * # # + * # 0x00000000 65 73 es + * + * # Put "o" into 0s position of the slice + * slice.set_string('o', 0) + * slice + * # => + * # # + * # 0x00000000 6f 73 os + * + * + * # it is also visible at position 1 of the original buffer + * buffer + * # => + * # # + * # 0x00000000 74 6f 73 74 tost + * + * # ...and original string + * string + * # => tost + * + */ +VALUE +rb_io_buffer_slice(VALUE self, VALUE _offset, VALUE _length) +{ + // TODO fail on negative offets/lengths. + size_t offset = NUM2SIZET(_offset); + size_t length = NUM2SIZET(_length); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_validate_range(data, offset, length); + + VALUE instance = rb_io_buffer_type_allocate(rb_class_of(self)); + struct rb_io_buffer *slice = NULL; + TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, slice); + + slice->base = (char*)data->base + offset; + slice->size = length; + + // The source should be the root buffer: + if (data->source != Qnil) + slice->source = data->source; + else + slice->source = self; + + return instance; +} + +int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (io_buffer_validate(data)) { + if (data->base) { + *base = data->base; + *size = data->size; + + return data->flags; + } + } + + *base = NULL; + *size = 0; + + return 0; +} + +static void +io_buffer_get_bytes_for_writing(struct rb_io_buffer *data, void **base, size_t *size) +{ + if (data->flags & RB_IO_BUFFER_READONLY) { + rb_raise(rb_eIOBufferAccessError, "Buffer is not writable!"); + } + + if (!io_buffer_validate(data)) { + rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!"); + } + + if (data->base) { + *base = data->base; + *size = data->size; + + return; + } + + rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!"); +} + +void +rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_get_bytes_for_writing(data, base, size); +} + +static void +io_buffer_get_bytes_for_reading(struct rb_io_buffer *data, const void **base, size_t *size) +{ + if (!io_buffer_validate(data)) { + rb_raise(rb_eIOBufferInvalidatedError, "Buffer has been invalidated!"); + } + + if (data->base) { + *base = data->base; + *size = data->size; + + return; + } + + rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!"); +} + +void +rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_get_bytes_for_reading(data, base, size); +} + +/* + * call-seq: transfer -> new_io_buffer + * + * Transfers ownership to a new buffer, deallocating the current one. + * + * buffer = IO::Buffer.new('test') + * other = buffer.transfer + * other + * # => + * # # + * # 0x00000000 74 65 73 74 test + * buffer + * # => + * # # + * buffer.null? + * # => true + * + */ +VALUE +rb_io_buffer_transfer(VALUE self) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_raise(rb_eIOBufferLockedError, "Cannot transfer ownership of locked buffer!"); + } + + VALUE instance = rb_io_buffer_type_allocate(rb_class_of(self)); + struct rb_io_buffer *transferred; + TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, transferred); + + *transferred = *data; + io_buffer_zero(data); + + return instance; +} + +static void +io_buffer_resize_clear(struct rb_io_buffer *data, void* base, size_t size) +{ + if (size > data->size) { + memset((unsigned char*)base+data->size, 0, size - data->size); + } +} + +static void +io_buffer_resize_copy(struct rb_io_buffer *data, size_t size) +{ + // Slow path: + struct rb_io_buffer resized; + io_buffer_initialize(&resized, NULL, size, io_flags_for_size(size), Qnil); + + if (data->base) { + size_t preserve = data->size; + if (preserve > size) preserve = size; + memcpy(resized.base, data->base, preserve); + + io_buffer_resize_clear(data, resized.base, size); + } + + io_buffer_free(data); + *data = resized; +} + +void +rb_io_buffer_resize(VALUE self, size_t size) +{ + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + if (data->flags & RB_IO_BUFFER_LOCKED) { + rb_raise(rb_eIOBufferLockedError, "Cannot resize locked buffer!"); + } + + if (data->base == NULL) { + io_buffer_initialize(data, NULL, size, io_flags_for_size(size), Qnil); + return; + } + + if (data->flags & RB_IO_BUFFER_EXTERNAL) { + rb_raise(rb_eIOBufferAccessError, "Cannot resize external buffer!"); + } + +#ifdef MREMAP_MAYMOVE + if (data->flags & RB_IO_BUFFER_MAPPED) { + void *base = mremap(data->base, data->size, size, MREMAP_MAYMOVE); + + if (base == MAP_FAILED) { + rb_sys_fail("rb_io_buffer_resize:mremap"); + } + + io_buffer_resize_clear(data, base, size); + + data->base = base; + data->size = size; + + return; + } +#endif + + if (data->flags & RB_IO_BUFFER_INTERNAL) { + void *base = realloc(data->base, size); + + if (!base) { + rb_sys_fail("rb_io_buffer_resize:realloc"); + } + + io_buffer_resize_clear(data, base, size); + + data->base = base; + data->size = size; + + return; + } + + io_buffer_resize_copy(data, size); +} + +/* + * call-seq: resize(new_size) -> self + * + * Resizes a buffer to a +new_size+ bytes, preserving its content. + * Depending on the old and new size, the memory area associated with + * the buffer might be either extended, or rellocated at different + * address with content being copied. + * + * buffer = IO::Buffer.new(4) + * buffer.set_string("test", 0) + * buffer.resize(8) # resize to 8 bytes + * # => + * # # + * # 0x00000000 74 65 73 74 00 00 00 00 test.... + * + * External buffer (created with ::for), and locked buffer + * can not be resized. + * + */ +static VALUE +io_buffer_resize(VALUE self, VALUE size) +{ + rb_io_buffer_resize(self, NUM2SIZET(size)); + + return self; +} + +/* + * call-seq: <=>(other) -> true or false + * + * Buffers are compared by size and exact contents of the memory they are + * referencing using +memcmp+. + * + */ +static VALUE +rb_io_buffer_compare(VALUE self, VALUE other) +{ + const void *ptr1, *ptr2; + size_t size1, size2; + + rb_io_buffer_get_bytes_for_reading(self, &ptr1, &size1); + rb_io_buffer_get_bytes_for_reading(other, &ptr2, &size2); + + if (size1 < size2) { + return RB_INT2NUM(-1); + } + + if (size1 > size2) { + return RB_INT2NUM(1); + } + + return RB_INT2NUM(memcmp(ptr1, ptr2, size1)); +} + +static void +io_buffer_validate_type(size_t size, size_t offset) +{ + if (offset > size) { + rb_raise(rb_eArgError, "Type extends beyond end of buffer!"); + } +} + +// Lower case: little endian. +// Upper case: big endian (network endian). +// +// :U8 | unsigned 8-bit integer. +// :S8 | signed 8-bit integer. +// +// :u16, :U16 | unsigned 16-bit integer. +// :s16, :S16 | signed 16-bit integer. +// +// :u32, :U32 | unsigned 32-bit integer. +// :s32, :S32 | signed 32-bit integer. +// +// :u64, :U64 | unsigned 64-bit integer. +// :s64, :S64 | signed 64-bit integer. +// +// :f32, :F32 | 32-bit floating point number. +// :f64, :F64 | 64-bit floating point number. + +#define ruby_swap8(value) value + +union swapf32 { + uint32_t integral; + float value; +}; + +static float +ruby_swapf32(float value) +{ + union swapf32 swap = {.value = value}; + swap.integral = ruby_swap32(swap.integral); + return swap.value; +} + +union swapf64 { + uint64_t integral; + double value; +}; + +static double +ruby_swapf64(double value) +{ + union swapf64 swap = {.value = value}; + swap.integral = ruby_swap64(swap.integral); + return swap.value; +} + +#define DECLARE_TYPE(name, type, endian, wrap, unwrap, swap) \ +static ID RB_IO_BUFFER_TYPE_##name; \ +\ +static VALUE \ +io_buffer_read_##name(const void* base, size_t size, size_t *offset) \ +{ \ + io_buffer_validate_type(size, *offset + sizeof(type)); \ + type value; \ + memcpy(&value, (char*)base + *offset, sizeof(type)); \ + if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \ + *offset += sizeof(type); \ + return wrap(value); \ +} \ +\ +static void \ +io_buffer_write_##name(const void* base, size_t size, size_t *offset, VALUE _value) \ +{ \ + io_buffer_validate_type(size, *offset + sizeof(type)); \ + type value = unwrap(_value); \ + if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \ + memcpy((char*)base + *offset, &value, sizeof(type)); \ + *offset += sizeof(type); \ +} + +DECLARE_TYPE(U8, uint8_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap8) +DECLARE_TYPE(S8, int8_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap8) + +DECLARE_TYPE(u16, uint16_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap16) +DECLARE_TYPE(U16, uint16_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap16) +DECLARE_TYPE(s16, int16_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap16) +DECLARE_TYPE(S16, int16_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap16) + +DECLARE_TYPE(u32, uint32_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap32) +DECLARE_TYPE(U32, uint32_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap32) +DECLARE_TYPE(s32, int32_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap32) +DECLARE_TYPE(S32, int32_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap32) + +DECLARE_TYPE(u64, uint64_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_ULL2NUM, RB_NUM2ULL, ruby_swap64) +DECLARE_TYPE(U64, uint64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_ULL2NUM, RB_NUM2ULL, ruby_swap64) +DECLARE_TYPE(s64, int64_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64) +DECLARE_TYPE(S64, int64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64) + +DECLARE_TYPE(f32, float, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32) +DECLARE_TYPE(F32, float, RB_IO_BUFFER_BIG_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32) +DECLARE_TYPE(f64, double, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf64) +DECLARE_TYPE(F64, double, RB_IO_BUFFER_BIG_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf64) +#undef DECLARE_TYPE + +VALUE +rb_io_buffer_get_value(const void* base, size_t size, ID type, size_t offset) +{ +#define READ_TYPE(name) if (type == RB_IO_BUFFER_TYPE_##name) return io_buffer_read_##name(base, size, &offset); + READ_TYPE(U8) + READ_TYPE(S8) + + READ_TYPE(u16) + READ_TYPE(U16) + READ_TYPE(s16) + READ_TYPE(S16) + + READ_TYPE(u32) + READ_TYPE(U32) + READ_TYPE(s32) + READ_TYPE(S32) + + READ_TYPE(u64) + READ_TYPE(U64) + READ_TYPE(s64) + READ_TYPE(S64) + + READ_TYPE(f32) + READ_TYPE(F32) + READ_TYPE(f64) + READ_TYPE(F64) +#undef READ_TYPE + + rb_raise(rb_eArgError, "Invalid type name!"); +} + +/* + * call-seq: get_value(type, offset) -> numeric + * + * Read from buffer a value of +type+ at +offset+. +type+ should be one + * of symbols: + * + * * +:U8+: unsigned integer, 1 byte + * * +:S8+: signed integer, 1 byte + * * +:u16+: unsigned integer, 2 bytes, little-endian + * * +:U16+: unsigned integer, 2 bytes, big-endian + * * +:s16+: signed integer, 2 bytes, little-endian + * * +:S16+: signed integer, 2 bytes, big-endian + * * +:u32+: unsigned integer, 4 bytes, little-endian + * * +:U32+: unsigned integer, 4 bytes, big-endian + * * +:s32+: signed integer, 4 bytes, little-endian + * * +:S32+: signed integer, 4 bytes, big-endian + * * +:u64+: unsigned integer, 8 bytes, little-endian + * * +:U64+: unsigned integer, 8 bytes, big-endian + * * +:s64+: signed integer, 8 bytes, little-endian + * * +:S64+: signed integer, 8 bytes, big-endian + * * +:f32+: float, 4 bytes, little-endian + * * +:F32+: float, 4 bytes, big-endian + * * +:f64+: double, 8 bytes, little-endian + * * +:F64+: double, 8 bytes, big-endian + * + * Example: + * + * string = [1.5].pack('f') + * # => "\x00\x00\xC0?" + * IO::Buffer.for(string).get_value(:f32, 0) + * # => 1.5 + * + */ +static VALUE +io_buffer_get_value(VALUE self, VALUE type, VALUE _offset) +{ + const void *base; + size_t size; + size_t offset = NUM2SIZET(_offset); + + rb_io_buffer_get_bytes_for_reading(self, &base, &size); + + return rb_io_buffer_get_value(base, size, RB_SYM2ID(type), offset); +} + +void +rb_io_buffer_set_value(const void* base, size_t size, ID type, size_t offset, VALUE value) +{ +#define WRITE_TYPE(name) if (type == RB_IO_BUFFER_TYPE_##name) {io_buffer_write_##name(base, size, &offset, value); return;} + WRITE_TYPE(U8) + WRITE_TYPE(S8) + + WRITE_TYPE(u16) + WRITE_TYPE(U16) + WRITE_TYPE(s16) + WRITE_TYPE(S16) + + WRITE_TYPE(u32) + WRITE_TYPE(U32) + WRITE_TYPE(s32) + WRITE_TYPE(S32) + + WRITE_TYPE(u64) + WRITE_TYPE(U64) + WRITE_TYPE(s64) + WRITE_TYPE(S64) + + WRITE_TYPE(f32) + WRITE_TYPE(F32) + WRITE_TYPE(f64) + WRITE_TYPE(F64) +#undef WRITE_TYPE + + rb_raise(rb_eArgError, "Invalid type name!"); +} + +/* + * call-seq: set_value(type, offset, value) -> offset + * + * Write to a buffer a +value+ of +type+ at +offset+. +type+ should be one of + * symbols described in #get_value. + * + * buffer = IO::Buffer.new(8) + * # => + * # # + * # 0x00000000 00 00 00 00 00 00 00 00 + * buffer.set_value(:U8, 1, 111) + * # => 1 + * buffer + * # => + * # # + * # 0x00000000 00 6f 00 00 00 00 00 00 .o...... + * + * Note that if the +type+ is integer and +value+ is Float, the implicit truncation is performed: + * + * buffer = IO::Buffer.new(8) + * buffer.set_value(:U32, 0, 2.5) + * buffer + * # => + * # # + * # 0x00000000 00 00 00 02 00 00 00 00 + * # ^^ the same as if we'd pass just integer 2 + */ +static VALUE +io_buffer_set_value(VALUE self, VALUE type, VALUE _offset, VALUE value) +{ + void *base; + size_t size; + size_t offset = NUM2SIZET(_offset); + + rb_io_buffer_get_bytes_for_writing(self, &base, &size); + + rb_io_buffer_set_value(base, size, RB_SYM2ID(type), offset, value); + + return SIZET2NUM(offset); +} + +static void +io_buffer_memcpy(struct rb_io_buffer *data, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length) +{ + void *base; + size_t size; + io_buffer_get_bytes_for_writing(data, &base, &size); + + io_buffer_validate_range(data, offset, length); + + if (source_offset + length > source_size) { + rb_raise(rb_eArgError, "The computed source range exceeds the size of the source!"); + } + + memcpy((unsigned char*)base+offset, (unsigned char*)source_base+source_offset, length); +} + +// (offset, length, source_offset) -> length +static VALUE +io_buffer_copy_from(struct rb_io_buffer *data, const void *source_base, size_t source_size, int argc, VALUE *argv) +{ + size_t offset; + size_t length; + size_t source_offset; + + // The offset we copy into the buffer: + if (argc >= 1) { + offset = NUM2SIZET(argv[0]); + } else { + offset = 0; + } + + // The offset we start from within the string: + if (argc >= 3) { + source_offset = NUM2SIZET(argv[2]); + + if (source_offset > source_size) { + rb_raise(rb_eArgError, "The given source offset is bigger than the source itself!"); + } + } else { + source_offset = 0; + } + + // The length we are going to copy: + if (argc >= 2 && !RB_NIL_P(argv[1])) { + length = NUM2SIZET(argv[1]); + } else { + // Default to the source offset -> source size: + length = source_size - source_offset; + } + + io_buffer_memcpy(data, offset, source_base, source_offset, source_size, length); + + return SIZET2NUM(length); +} + +/* + * call-seq: + * copy(source, [offset, [length, [source_offset]]]) -> size + * + * Efficiently copy data from a source IO::Buffer into the buffer, + * at +offset+ using +memcpy+. For copying String instances, see #set_string. + * + * buffer = IO::Buffer.new(32) + * # => + * # # + * # 0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + * # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * + * + * buffer.copy(IO::Buffer.for("test"), 8) + * # => 4 -- size of data copied + * buffer + * # => + * # # + * # 0x00000000 00 00 00 00 00 00 00 00 74 65 73 74 00 00 00 00 ........test.... + * # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * + * + * #copy can be used to put data into strings associated with buffer: + * + * string= "data: " + * # => "data: " + * buffer = IO::Buffer.for(str) + * buffer.copy(IO::Buffer.for("test"), 5) + * # => 4 + * string + * # => "data:test" + * + * Attempt to copy into a read-only buffer will fail: + * + * File.write('test.txt', 'test') + * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY) + * buffer.copy(IO::Buffer.for("test"), 8) + * # in `copy': Buffer is not writable! (IO::Buffer::AccessError) + * + * See ::map for details of creation of mutable file mappings, this will + * work: + * + * buffer = IO::Buffer.map(File.open('test.txt', 'r+')) + * buffer.copy("boom", 0) + * # => 4 + * File.read('test.txt') + * # => "boom" + * + * Attempt to copy the data which will need place outside of buffer's + * bounds will fail: + * + * buffer = IO::Buffer.new(2) + * buffer.copy('test', 0) + * # in `copy': Specified offset+length exceeds source size! (ArgumentError) + * + */ +static VALUE +io_buffer_copy(int argc, VALUE *argv, VALUE self) +{ + if (argc < 1 || argc > 4) rb_error_arity(argc, 1, 4); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + VALUE source = argv[0]; + const void *source_base; + size_t source_size; + + rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size); + + return io_buffer_copy_from(data, source_base, source_size, argc-1, argv+1); +} + +/* + * call-seq: get_string([offset, [length, [encoding]]]) -> string + * + * Read a chunk or all of the buffer into a string, in the specified + * +encoding+. If no encoding is provided +Encoding::BINARY+ is used. + * + * + * buffer = IO::Buffer.for('test') + * buffer.get_string + * # => "test" + * buffer.get_string(2) + * # => "st" + * buffer.get_string(2, 1) + * # => "s" + * + */ +static VALUE +io_buffer_get_string(int argc, VALUE *argv, VALUE self) +{ + if (argc > 3) rb_error_arity(argc, 0, 3); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + const void *base; + size_t size; + io_buffer_get_bytes_for_reading(data, &base, &size); + + size_t offset = 0; + size_t length = size; + rb_encoding *encoding = rb_ascii8bit_encoding(); + + if (argc >= 1) { + offset = NUM2SIZET(argv[0]); + } + + if (argc >= 2 && !RB_NIL_P(argv[1])) { + length = NUM2SIZET(argv[1]); + } else { + length = size - offset; + } + + if (argc >= 3) { + encoding = rb_find_encoding(argv[2]); + } + + io_buffer_validate_range(data, offset, length); + + return rb_enc_str_new((const char*)base + offset, length, encoding); +} + +static VALUE +io_buffer_set_string(int argc, VALUE *argv, VALUE self) +{ + if (argc < 1 || argc > 4) rb_error_arity(argc, 1, 4); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + VALUE string = rb_str_to_str(argv[0]); + + const void *source_base = RSTRING_PTR(string); + size_t source_size = RSTRING_LEN(string); + + return io_buffer_copy_from(data, source_base, source_size, argc-1, argv+1); +} + +void +rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length) +{ + void *base; + size_t size; + + rb_io_buffer_get_bytes_for_writing(self, &base, &size); + + if (offset + length > size) { + rb_raise(rb_eArgError, "The given offset + length out of bounds!"); + } + + memset((char*)base + offset, value, length); +} + +/* + * call-seq: clear(value = 0, [offset, [length]]) -> self + * + * Fill buffer with +value+, starting with +offset+ and going for +length+ + * bytes. + * + * buffer = IO::Buffer.for('test') + * # => + * # + * # 0x00000000 74 65 73 74 test + * + * buffer.clear + * # => + * # + * # 0x00000000 00 00 00 00 .... + * + * buf.clear(1) # fill with 1 + * # => + * # + * # 0x00000000 01 01 01 01 .... + * + * buffer.clear(2, 1, 2) # fill with 2, starting from offset 1, for 2 bytes + * # => + * # + * # 0x00000000 01 02 02 01 .... + * + * buffer.clear(2, 1) # fill with 2, starting from offset 1 + * # => + * # + * # 0x00000000 01 02 02 02 .... + * + */ +static VALUE +io_buffer_clear(int argc, VALUE *argv, VALUE self) +{ + if (argc > 3) rb_error_arity(argc, 0, 3); + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + uint8_t value = 0; + if (argc >= 1) { + value = NUM2UINT(argv[0]); + } + + size_t offset = 0; + if (argc >= 2) { + offset = NUM2SIZET(argv[1]); + } + + size_t length; + if (argc >= 3) { + length = NUM2SIZET(argv[2]); + } else { + length = data->size - offset; + } + + rb_io_buffer_clear(self, value, offset, length); + + return self; +} + +static +size_t io_buffer_default_size(size_t page_size) { + // Platform agnostic default size, based on empirical performance observation: + const size_t platform_agnostic_default_size = 64*1024; + + // Allow user to specify custom default buffer size: + const char *default_size = getenv("RUBY_IO_BUFFER_DEFAULT_SIZE"); + if (default_size) { + // For the purpose of setting a default size, 2^31 is an acceptable maximum: + int value = atoi(default_size); + + // assuming sizeof(int) <= sizeof(size_t) + if (value > 0) { + return value; + } + } + + if (platform_agnostic_default_size < page_size) { + return page_size; + } + + return platform_agnostic_default_size; +} + +VALUE +rb_io_buffer_read(VALUE self, VALUE io, size_t length) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_read(scheduler, io, self, length); + + if (result != Qundef) { + return result; + } + } + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_validate_range(data, 0, length); + + int descriptor = rb_io_descriptor(io); + + void * base; + size_t size; + io_buffer_get_bytes_for_writing(data, &base, &size); + + ssize_t result = read(descriptor, base, size); + + return rb_fiber_scheduler_io_result(result, errno); +} + +static VALUE +io_buffer_read(VALUE self, VALUE io, VALUE length) +{ + return rb_io_buffer_read(self, io, RB_NUM2SIZE(length)); +} + +VALUE +rb_io_buffer_pread(VALUE self, VALUE io, size_t length, off_t offset) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, self, length, offset); + + if (result != Qundef) { + return result; + } + } + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_validate_range(data, 0, length); + + int descriptor = rb_io_descriptor(io); + + void * base; + size_t size; + io_buffer_get_bytes_for_writing(data, &base, &size); + +#if defined(HAVE_PREAD) + ssize_t result = pread(descriptor, base, size, offset); +#else + // This emulation is not thread safe, but the GVL means it's unlikely to be a problem. + off_t current_offset = lseek(descriptor, 0, SEEK_CUR); + if (current_offset == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); + + if (lseek(descriptor, offset, SEEK_SET) == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); + + ssize_t result = read(descriptor, base, size); + + if (lseek(descriptor, current_offset, SEEK_SET) == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); +#endif + + return rb_fiber_scheduler_io_result(result, errno); +} + +static VALUE +io_buffer_pread(VALUE self, VALUE io, VALUE length, VALUE offset) +{ + return rb_io_buffer_pread(self, io, RB_NUM2SIZE(length), NUM2OFFT(offset)); +} + +VALUE +rb_io_buffer_write(VALUE self, VALUE io, size_t length) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_write(scheduler, io, self, length); + + if (result != Qundef) { + return result; + } + } + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_validate_range(data, 0, length); + + int descriptor = rb_io_descriptor(io); + + const void * base; + size_t size; + io_buffer_get_bytes_for_reading(data, &base, &size); + + ssize_t result = write(descriptor, base, length); + + return rb_fiber_scheduler_io_result(result, errno); +} + +static VALUE +io_buffer_write(VALUE self, VALUE io, VALUE length) +{ + return rb_io_buffer_write(self, io, RB_NUM2SIZE(length)); +} + +VALUE +rb_io_buffer_pwrite(VALUE self, VALUE io, size_t length, off_t offset) +{ + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, self, length, OFFT2NUM(offset)); + + if (result != Qundef) { + return result; + } + } + + struct rb_io_buffer *data = NULL; + TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); + + io_buffer_validate_range(data, 0, length); + + int descriptor = rb_io_descriptor(io); + + const void * base; + size_t size; + io_buffer_get_bytes_for_reading(data, &base, &size); + +#if defined(HAVE_PWRITE) + ssize_t result = pwrite(descriptor, base, length, offset); +#else + // This emulation is not thread safe, but the GVL means it's unlikely to be a problem. + off_t current_offset = lseek(descriptor, 0, SEEK_CUR); + if (current_offset == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); + + if (lseek(descriptor, offset, SEEK_SET) == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); + + ssize_t result = write(descriptor, base, length); + + if (lseek(descriptor, current_offset, SEEK_SET) == (off_t)-1) + return rb_fiber_scheduler_io_result(-1, errno); +#endif + + return rb_fiber_scheduler_io_result(result, errno); +} + +static VALUE +io_buffer_pwrite(VALUE self, VALUE io, VALUE length, VALUE offset) +{ + return rb_io_buffer_pwrite(self, io, RB_NUM2SIZE(length), NUM2OFFT(offset)); +} + +/* + * Document-class: IO::Buffer + * + * IO::Buffer is a low-level efficient buffer for input/output. There are three + * ways of using buffer: + * + * * Create an empty buffer with ::new, fill it with data using #copy or + * #set_value, #set_string, get data with #get_string; + * * Create a buffer mapped to some string with ::for, then it could be used + * both for reading with #get_string or #get_value, and writing (writing will + * change the source string, too); + * * Create a buffer mapped to some file with ::map, then it could be used for + * reading and writing the underlying file. + * + * Interaction with string and file memory is performed by efficient low-level + * C mechanisms like `memcpy`. + * + * The class is meant to be an utility for implementing more high-level mechanisms + * like Fiber::SchedulerInterface#io_read and Fiber::SchedulerInterface#io_write. + * + * Examples of usage: + * + * Empty buffer: + * + * buffer = IO::Buffer.new(8) # create empty 8-byte buffer + * # => + * # # + * # ... + * buffer + * # => + * # + * # 0x00000000 00 00 00 00 00 00 00 00 + * buffer.set_string('test', 2) # put there bytes of the "test" string, starting from offset 2 + * # => 4 + * buffer.get_string # get the result + * # => "\x00\x00test\x00\x00" + * + * \Buffer from string: + * + * string = 'data' + * buffer = IO::Buffer.for(str) + * # => + * # # + * # ... + * buffer + * # => + * # # + * # 0x00000000 64 61 74 61 data + * + * buffer.get_string(2) # read content starting from offset 2 + * # => "ta" + * buffer.set_string('---', 1) # write content, starting from offset 1 + * # => 3 + * buffer + * # => + * # # + * # 0x00000000 64 2d 2d 2d d--- + * string # original string changed, too + * # => "d---" + * + * \Buffer from file: + * + * File.write('test.txt', 'test data') + * # => 9 + * buffer = IO::Buffer.map(File.open('test.txt')) + * # => + * # # + * # ... + * buffer.get_string(5, 2) # read 2 bytes, starting from offset 5 + * # => "da" + * buffer.set_string('---', 1) # attempt to write + * # in `set_string': Buffer is not writable! (IO::Buffer::AccessError) + * + * # To create writable file-mapped buffer + * # Open file for read-write, pass size, offset, and flags=0 + * buffer = IO::Buffer.map(File.open('test.txt', 'r+'), 9, 0, 0) + * buffer.set_string('---', 1) + * # => 3 -- bytes written + * File.read('test.txt') + * # => "t--- data" + * + * The class is experimental and the interface is subject to change. + */ +void +Init_IO_Buffer(void) +{ + rb_cIOBuffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject); + rb_eIOBufferLockedError = rb_define_class_under(rb_cIOBuffer, "LockedError", rb_eRuntimeError); + rb_eIOBufferAllocationError = rb_define_class_under(rb_cIOBuffer, "AllocationError", rb_eRuntimeError); + rb_eIOBufferAccessError = rb_define_class_under(rb_cIOBuffer, "AccessError", rb_eRuntimeError); + rb_eIOBufferInvalidatedError = rb_define_class_under(rb_cIOBuffer, "InvalidatedError", rb_eRuntimeError); + + rb_define_alloc_func(rb_cIOBuffer, rb_io_buffer_type_allocate); + rb_define_singleton_method(rb_cIOBuffer, "for", rb_io_buffer_type_for, 1); + +#ifdef _WIN32 + SYSTEM_INFO info; + GetSystemInfo(&info); + RUBY_IO_BUFFER_PAGE_SIZE = info.dwPageSize; +#else /* not WIN32 */ + RUBY_IO_BUFFER_PAGE_SIZE = sysconf(_SC_PAGESIZE); +#endif + + RUBY_IO_BUFFER_DEFAULT_SIZE = io_buffer_default_size(RUBY_IO_BUFFER_PAGE_SIZE); + + // Efficient sizing of mapped buffers: + rb_define_const(rb_cIOBuffer, "PAGE_SIZE", SIZET2NUM(RUBY_IO_BUFFER_PAGE_SIZE)); + rb_define_const(rb_cIOBuffer, "DEFAULT_SIZE", SIZET2NUM(RUBY_IO_BUFFER_DEFAULT_SIZE)); + + rb_define_singleton_method(rb_cIOBuffer, "map", io_buffer_map, -1); + + // General use: + rb_define_method(rb_cIOBuffer, "initialize", rb_io_buffer_initialize, -1); + rb_define_method(rb_cIOBuffer, "inspect", rb_io_buffer_inspect, 0); + rb_define_method(rb_cIOBuffer, "hexdump", rb_io_buffer_hexdump, 0); + rb_define_method(rb_cIOBuffer, "to_s", rb_io_buffer_to_s, 0); + rb_define_method(rb_cIOBuffer, "size", rb_io_buffer_size, 0); + rb_define_method(rb_cIOBuffer, "valid?", rb_io_buffer_valid_p, 0); + + // Ownership: + rb_define_method(rb_cIOBuffer, "transfer", rb_io_buffer_transfer, 0); + + // Flags: + rb_define_const(rb_cIOBuffer, "EXTERNAL", RB_INT2NUM(RB_IO_BUFFER_EXTERNAL)); + rb_define_const(rb_cIOBuffer, "INTERNAL", RB_INT2NUM(RB_IO_BUFFER_INTERNAL)); + rb_define_const(rb_cIOBuffer, "MAPPED", RB_INT2NUM(RB_IO_BUFFER_MAPPED)); + rb_define_const(rb_cIOBuffer, "LOCKED", RB_INT2NUM(RB_IO_BUFFER_LOCKED)); + rb_define_const(rb_cIOBuffer, "PRIVATE", RB_INT2NUM(RB_IO_BUFFER_PRIVATE)); + rb_define_const(rb_cIOBuffer, "READONLY", RB_INT2NUM(RB_IO_BUFFER_READONLY)); + + // Endian: + rb_define_const(rb_cIOBuffer, "LITTLE_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_LITTLE_ENDIAN)); + rb_define_const(rb_cIOBuffer, "BIG_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_BIG_ENDIAN)); + rb_define_const(rb_cIOBuffer, "HOST_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_HOST_ENDIAN)); + rb_define_const(rb_cIOBuffer, "NETWORK_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_NETWORK_ENDIAN)); + + rb_define_method(rb_cIOBuffer, "null?", rb_io_buffer_null_p, 0); + rb_define_method(rb_cIOBuffer, "empty?", rb_io_buffer_empty_p, 0); + rb_define_method(rb_cIOBuffer, "external?", rb_io_buffer_external_p, 0); + rb_define_method(rb_cIOBuffer, "internal?", rb_io_buffer_internal_p, 0); + rb_define_method(rb_cIOBuffer, "mapped?", rb_io_buffer_mapped_p, 0); + rb_define_method(rb_cIOBuffer, "locked?", rb_io_buffer_locked_p, 0); + rb_define_method(rb_cIOBuffer, "readonly?", io_buffer_readonly_p, 0); + + // Locking to prevent changes while using pointer: + // rb_define_method(rb_cIOBuffer, "lock", rb_io_buffer_lock, 0); + // rb_define_method(rb_cIOBuffer, "unlock", rb_io_buffer_unlock, 0); + rb_define_method(rb_cIOBuffer, "locked", rb_io_buffer_locked, 0); + + // Manipulation: + rb_define_method(rb_cIOBuffer, "slice", rb_io_buffer_slice, 2); + rb_define_method(rb_cIOBuffer, "<=>", rb_io_buffer_compare, 1); + rb_define_method(rb_cIOBuffer, "resize", io_buffer_resize, 1); + rb_define_method(rb_cIOBuffer, "clear", io_buffer_clear, -1); + rb_define_method(rb_cIOBuffer, "free", rb_io_buffer_free, 0); + + rb_include_module(rb_cIOBuffer, rb_mComparable); + +#define DEFINE_TYPE(name) RB_IO_BUFFER_TYPE_##name = rb_intern_const(#name) + DEFINE_TYPE(U8); DEFINE_TYPE(S8); + DEFINE_TYPE(u16); DEFINE_TYPE(U16); DEFINE_TYPE(s16); DEFINE_TYPE(S16); + DEFINE_TYPE(u32); DEFINE_TYPE(U32); DEFINE_TYPE(s32); DEFINE_TYPE(S32); + DEFINE_TYPE(u64); DEFINE_TYPE(U64); DEFINE_TYPE(s64); DEFINE_TYPE(S64); + DEFINE_TYPE(f32); DEFINE_TYPE(F32); DEFINE_TYPE(f64); DEFINE_TYPE(F64); +#undef DEFINE_TYPE + + // Data access: + rb_define_method(rb_cIOBuffer, "get_value", io_buffer_get_value, 2); + rb_define_method(rb_cIOBuffer, "set_value", io_buffer_set_value, 3); + + rb_define_method(rb_cIOBuffer, "copy", io_buffer_copy, -1); + + rb_define_method(rb_cIOBuffer, "get_string", io_buffer_get_string, -1); + rb_define_method(rb_cIOBuffer, "set_string", io_buffer_set_string, -1); + + // IO operations: + rb_define_method(rb_cIOBuffer, "read", io_buffer_read, 2); + rb_define_method(rb_cIOBuffer, "pread", io_buffer_pread, 3); + rb_define_method(rb_cIOBuffer, "write", io_buffer_write, 2); + rb_define_method(rb_cIOBuffer, "pwrite", io_buffer_pwrite, 3); +} diff --git a/ruby/iseq.c b/ruby/iseq.c index cbf62176b..f711367cf 100644 --- a/ruby/iseq.c +++ b/ruby/iseq.c @@ -9,25 +9,40 @@ **********************************************************************/ -#include "internal.h" -#include "ruby/util.h" -#include "eval_intern.h" +#define RUBY_VM_INSNS_INFO 1 +/* #define RUBY_MARK_FREE_DEBUG 1 */ + +#include "ruby/internal/config.h" #ifdef HAVE_DLADDR # include #endif -#define RUBY_VM_INSNS_INFO 1 -/* #define RUBY_MARK_FREE_DEBUG 1 */ +#include "eval_intern.h" #include "gc.h" -#include "vm_core.h" -#include "iseq.h" #include "id_table.h" +#include "internal.h" +#include "internal/bits.h" +#include "internal/class.h" +#include "internal/compile.h" +#include "internal/error.h" +#include "internal/file.h" +#include "internal/hash.h" +#include "internal/parse.h" +#include "internal/sanitizers.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "iseq.h" +#include "mjit.h" +#include "ruby/util.h" +#include "vm_core.h" +#include "vm_callinfo.h" +#include "yjit.h" +#include "ruby/ractor.h" #include "builtin.h" - #include "insns.inc" #include "insns_info.inc" -#include "mjit.h" VALUE rb_cISeq; static VALUE iseqw_new(const rb_iseq_t *iseq); @@ -55,6 +70,8 @@ obj_resurrect(VALUE obj) case T_HASH: obj = rb_hash_resurrect(obj); break; + default: + break; } } return obj; @@ -93,6 +110,7 @@ rb_iseq_free(const rb_iseq_t *iseq) if (iseq && iseq->body) { struct rb_iseq_constant_body *const body = iseq->body; mjit_free_iseq(iseq); /* Notify MJIT */ + rb_yjit_iseq_free(body); ruby_xfree((void *)body->iseq_encoded); ruby_xfree((void *)body->insns_info.body); if (body->insns_info.positions) ruby_xfree((void *)body->insns_info.positions); @@ -104,12 +122,6 @@ rb_iseq_free(const rb_iseq_t *iseq) ruby_xfree((void *)body->is_entries); if (body->call_data) { - unsigned int i; - struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size]; - for (i=0; ici_kw_size; i++) { - const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg; - ruby_xfree((void *)kw_arg); - } ruby_xfree(body->call_data); } ruby_xfree((void *)body->catch_table); @@ -120,6 +132,7 @@ rb_iseq_free(const rb_iseq_t *iseq) ruby_xfree((void *)body->param.keyword); } compile_data_free(ISEQ_COMPILE_DATA(iseq)); + if (body->outer_variables) rb_id_table_free(body->outer_variables); ruby_xfree(body); } @@ -171,6 +184,31 @@ iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data } } break; + case TS_IC: + { + IC ic = (IC)code[pos + op_no + 1]; + if (ic->entry) { + VALUE nv = func(data, (VALUE)ic->entry); + if ((VALUE)ic->entry != nv) { + ic->entry = (void *)nv; + } + } + } + break; + case TS_IVC: + { + IVC ivc = (IVC)code[pos + op_no + 1]; + if (ivc->entry) { + if (RB_TYPE_P(ivc->entry->class_value, T_NONE)) { + rb_bug("!! %u", ivc->entry->index); + } + VALUE nv = func(data, ivc->entry->class_value); + if (ivc->entry->class_value != nv) { + ivc->entry->class_value = nv; + } + } + } + break; case TS_ISE: { union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; @@ -198,7 +236,7 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) size_t n; rb_vm_insns_translator_t *const translator = #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - (FL_TEST(iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 : + (FL_TEST((VALUE)iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 : #endif rb_vm_insn_null_translator; const struct rb_iseq_constant_body *const body = iseq->body; @@ -225,6 +263,7 @@ rb_iseq_update_references(rb_iseq_t *iseq) body->variable.coverage = rb_gc_location(body->variable.coverage); body->variable.pc2branchindex = rb_gc_location(body->variable.pc2branchindex); + body->variable.script_lines = rb_gc_location(body->variable.script_lines); body->location.label = rb_gc_location(body->location.label); body->location.base_label = rb_gc_location(body->location.base_label); body->location.pathobj = rb_gc_location(body->location.pathobj); @@ -234,7 +273,19 @@ rb_iseq_update_references(rb_iseq_t *iseq) if (body->parent_iseq) { body->parent_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->parent_iseq); } - if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) { + if (body->mandatory_only_iseq) { + body->mandatory_only_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->mandatory_only_iseq); + } + if (body->call_data) { + for (unsigned int i=0; ici_size; i++) { + struct rb_call_data *cds = body->call_data; + if (!SPECIAL_CONST_P((VALUE)cds[i].ci)) { + cds[i].ci = (struct rb_callinfo *)rb_gc_location((VALUE)cds[i].ci); + } + cds[i].cc = (struct rb_callcache *)rb_gc_location((VALUE)cds[i].cc); + } + } + if (FL_TEST((VALUE)iseq, ISEQ_MARKABLE_ISEQ)) { rb_iseq_each_value(iseq, update_each_insn_value, NULL); VALUE *original_iseq = ISEQ_ORIGINAL_ISEQ(iseq); if (original_iseq) { @@ -273,6 +324,7 @@ rb_iseq_update_references(rb_iseq_t *iseq) #if USE_MJIT mjit_update_references(iseq); #endif + rb_yjit_iseq_update_references(body); } } @@ -293,16 +345,43 @@ rb_iseq_mark(const rb_iseq_t *iseq) if (iseq->body) { const struct rb_iseq_constant_body *const body = iseq->body; - if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) { + if (FL_TEST((VALUE)iseq, ISEQ_MARKABLE_ISEQ)) { rb_iseq_each_value(iseq, each_insn_value, NULL); } rb_gc_mark_movable(body->variable.coverage); rb_gc_mark_movable(body->variable.pc2branchindex); + rb_gc_mark_movable(body->variable.script_lines); rb_gc_mark_movable(body->location.label); rb_gc_mark_movable(body->location.base_label); rb_gc_mark_movable(body->location.pathobj); - RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)body->parent_iseq); + RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)body->mandatory_only_iseq); + RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)body->parent_iseq); + + if (body->call_data) { + struct rb_call_data *cds = (struct rb_call_data *)body->call_data; + for (unsigned int i=0; ici_size; i++) { + const struct rb_callinfo *ci = cds[i].ci; + const struct rb_callcache *cc = cds[i].cc; + + if (vm_ci_markable(ci)) { + rb_gc_mark_movable((VALUE)ci); + } + + if (cc) { + VM_ASSERT((cc->flags & VM_CALLCACHE_ON_STACK) == 0); + + if (vm_cc_markable(cc)) { + if (!vm_cc_invalidated_p(cc)) { + rb_gc_mark_movable((VALUE)cc); + } + else { + cds[i].cc = rb_vm_empty_cc(); + } + } + } + } + } if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) { const struct rb_iseq_param_keyword *const keyword = body->param.keyword; @@ -329,12 +408,17 @@ rb_iseq_mark(const rb_iseq_t *iseq) } } } + +#if USE_MJIT + mjit_mark_cc_entries(body); +#endif + rb_yjit_iseq_mark(body); } - if (FL_TEST_RAW(iseq, ISEQ_NOT_LOADED_YET)) { + if (FL_TEST_RAW((VALUE)iseq, ISEQ_NOT_LOADED_YET)) { rb_gc_mark(iseq->aux.loader.obj); } - else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) { + else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) { const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq); rb_iseq_mark_insn_storage(compile_data->insn.storage_head); @@ -379,8 +463,6 @@ rb_iseq_memsize(const rb_iseq_t *iseq) /* TODO: should we count original_iseq? */ if (ISEQ_EXECUTABLE_P(iseq) && body) { - struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size]; - size += sizeof(struct rb_iseq_constant_body); size += body->iseq_size * sizeof(VALUE); size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int)); @@ -396,19 +478,7 @@ rb_iseq_memsize(const rb_iseq_t *iseq) /* body->call_data */ size += body->ci_size * sizeof(struct rb_call_data); - size += body->ci_kw_size * sizeof(struct rb_kwarg_call_data); - - if (kw_calls) { - unsigned int i; - - for (i = 0; i < body->ci_kw_size; i++) { - const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg; - - if (kw_arg) { - size += rb_call_info_kw_arg_bytes(kw_arg->keyword_len); - } - } - } + // TODO: should we count imemo_callinfo? } compile_data = ISEQ_COMPILE_DATA(iseq); @@ -427,14 +497,11 @@ rb_iseq_memsize(const rb_iseq_t *iseq) return size; } -static uintptr_t fresh_iseq_unique_id = 0; /* -- Remove In 3.0 -- */ - struct rb_iseq_constant_body * rb_iseq_constant_body_alloc(void) { struct rb_iseq_constant_body *iseq_body; iseq_body = ZALLOC(struct rb_iseq_constant_body); - iseq_body->iseq_unique_id = fresh_iseq_unique_id++; /* -- Remove In 3.0 -- */ return iseq_body; } @@ -451,7 +518,7 @@ rb_iseq_pathobj_new(VALUE path, VALUE realpath) { VALUE pathobj; VM_ASSERT(RB_TYPE_P(path, T_STRING)); - VM_ASSERT(realpath == Qnil || RB_TYPE_P(realpath, T_STRING)); + VM_ASSERT(NIL_P(realpath) || RB_TYPE_P(realpath, T_STRING)); if (path == realpath || (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) { @@ -539,8 +606,8 @@ new_arena(void) static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id, - const rb_iseq_t *parent, enum iseq_type type, - const rb_compile_option_t *option) + const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, + VALUE script_lines, const rb_compile_option_t *option) { VALUE coverage = Qfalse; VALUE err_info = Qnil; @@ -561,18 +628,25 @@ prepare_iseq_build(rb_iseq_t *iseq, ISEQ_ORIGINAL_ISEQ_CLEAR(iseq); body->variable.flip_count = 0; + if (NIL_P(script_lines)) { + RB_OBJ_WRITE(iseq, &body->variable.script_lines, Qnil); + } + else { + RB_OBJ_WRITE(iseq, &body->variable.script_lines, rb_ractor_make_shareable(script_lines)); + } + ISEQ_COMPILE_DATA_ALLOC(iseq); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil); ISEQ_COMPILE_DATA(iseq)->node.storage_head = ISEQ_COMPILE_DATA(iseq)->node.storage_current = new_arena(); ISEQ_COMPILE_DATA(iseq)->insn.storage_head = ISEQ_COMPILE_DATA(iseq)->insn.storage_current = new_arena(); + ISEQ_COMPILE_DATA(iseq)->isolated_depth = isolated_depth; ISEQ_COMPILE_DATA(iseq)->option = option; - ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = NULL; - ISEQ_COMPILE_DATA(iseq)->builtin_function_table = GET_VM()->builtin_function_table; + if (option->coverage_enabled) { VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { @@ -595,6 +669,7 @@ void rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq) { #if VM_INSN_INFO_TABLE_IMPL == 2 + /* create succ_index_table */ struct rb_iseq_constant_body *const body = iseq->body; int size = body->insns_info.size; int max_pos = body->iseq_size; @@ -637,13 +712,6 @@ finish_iseq_build(rb_iseq_t *iseq) ISEQ_COMPILE_DATA_CLEAR(iseq); compile_data_free(data); -#if VM_INSN_INFO_TABLE_IMPL == 2 /* succinct bitvector */ - /* create succ_index_table */ - if (body->insns_info.succ_index_table == NULL) { - rb_iseq_insns_info_encode_positions(iseq); - } -#endif - #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0 validate_get_insn_info(iseq); #endif @@ -655,6 +723,9 @@ finish_iseq_build(rb_iseq_t *iseq) rb_exc_raise(err); } + RB_DEBUG_COUNTER_INC(iseq_num); + RB_DEBUG_COUNTER_ADD(iseq_cd_num, iseq->body->ci_size); + rb_iseq_init_trace(iseq); return Qtrue; } @@ -711,7 +782,7 @@ rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt) static void make_compile_option(rb_compile_option_t *option, VALUE opt) { - if (opt == Qnil) { + if (NIL_P(opt)) { *option = COMPILE_OPTION_DEFAULT; } else if (opt == Qfalse) { @@ -736,7 +807,7 @@ make_compile_option_value(rb_compile_option_t *option) { VALUE opt = rb_hash_new_with_size(11); #define SET_COMPILE_OPTION(o, h, mem) \ - rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse) + rb_hash_aset((h), ID2SYM(rb_intern(#mem)), RBOOL((o)->mem)) #define SET_COMPILE_OPTION_NUM(o, h, mem) \ rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem)) { @@ -761,8 +832,21 @@ rb_iseq_t * rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type type) { - return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, type, - &COMPILE_OPTION_DEFAULT); + return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, + 0, type, &COMPILE_OPTION_DEFAULT); +} + +static int +ast_line_count(const rb_ast_body_t *ast) +{ + if (ast->script_lines == Qfalse) { + // this occurs when failed to parse the source code with a syntax error + return 0; + } + if (RB_TYPE_P(ast->script_lines, T_ARRAY)){ + return (int)RARRAY_LEN(ast->script_lines); + } + return FIX2INT(ast->script_lines); } rb_iseq_t * @@ -770,23 +854,31 @@ rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath { VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { - if (ast->line_count >= 0) { - int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : ast->line_count; + int line_count = ast_line_count(ast); + if (line_count >= 0) { + int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count; VALUE coverage = rb_default_coverage(len); rb_hash_aset(coverages, path, coverage); } } - return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, ISEQ_TYPE_TOP, - &COMPILE_OPTION_DEFAULT); + return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, 0, + ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT); } rb_iseq_t * -rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent) +rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt) { return rb_iseq_new_with_opt(ast, rb_fstring_lit("
"), path, realpath, INT2FIX(0), - parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT); + parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE); +} + +rb_iseq_t * +rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth) +{ + return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno, + parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT); } static inline rb_iseq_t * @@ -805,18 +897,33 @@ iseq_translate(rb_iseq_t *iseq) rb_iseq_t * rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, - VALUE first_lineno, const rb_iseq_t *parent, - enum iseq_type type, const rb_compile_option_t *option) + VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth, + enum iseq_type type, const rb_compile_option_t *option) { const NODE *node = ast ? ast->root : 0; /* TODO: argument check */ rb_iseq_t *iseq = iseq_alloc(); rb_compile_option_t new_opt; - new_opt = option ? *option : COMPILE_OPTION_DEFAULT; + if (option) { + new_opt = *option; + } + else { + new_opt = COMPILE_OPTION_DEFAULT; + } if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option); - prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, type, &new_opt); + VALUE script_lines = Qnil; + + if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) { + script_lines = ast->script_lines; + } + else if (parent) { + script_lines = parent->body->variable.script_lines; + } + + prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, + parent, isolated_depth, type, script_lines, &new_opt); rb_iseq_compile_node(iseq, node); finish_iseq_build(iseq); @@ -835,12 +942,12 @@ rb_iseq_new_with_callback( rb_iseq_t *iseq = iseq_alloc(); if (!option) option = &COMPILE_OPTION_DEFAULT; - prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, type, option); + prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, Qnil, option); rb_iseq_compile_callback(iseq, ifunc); finish_iseq_build(iseq); - return iseq_translate(iseq); + return iseq; } const rb_iseq_t * @@ -948,7 +1055,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) make_compile_option(&option, opt); option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */ prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id), - parent, (enum iseq_type)iseq_type, &option); + parent, 0, (enum iseq_type)iseq_type, Qnil, &option); rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body); @@ -1016,7 +1123,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V else { INITIALIZED VALUE label = rb_fstring_lit(""); iseq = rb_iseq_new_with_opt(&ast->body, label, file, realpath, line, - 0, ISEQ_TYPE_TOP, &option); + NULL, 0, ISEQ_TYPE_TOP, &option); rb_ast_dispose(ast); } @@ -1041,6 +1148,12 @@ rb_iseq_absolute_path(const rb_iseq_t *iseq) return rb_iseq_realpath(iseq); } +int +rb_iseq_from_eval_p(const rb_iseq_t *iseq) +{ + return NIL_P(rb_iseq_realpath(iseq)); +} + VALUE rb_iseq_label(const rb_iseq_t *iseq) { @@ -1082,6 +1195,14 @@ rb_iseq_code_location(const rb_iseq_t *iseq, int *beg_pos_lineno, int *beg_pos_c if (end_pos_column) *end_pos_column = loc->end_pos.column; } +static ID iseq_type_id(enum iseq_type type); + +VALUE +rb_iseq_type(const rb_iseq_t *iseq) +{ + return ID2SYM(iseq_type_id(iseq->body->type)); +} + VALUE rb_iseq_coverage(const rb_iseq_t *iseq) { @@ -1258,7 +1379,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) parser = rb_parser_new(); rb_parser_set_context(parser, NULL, FALSE); - ast = rb_parser_compile_file_path(parser, file, f, NUM2INT(line)); + ast = (rb_ast_t *)rb_parser_load_file(parser, file); if (!ast->body.root) exc = GET_EC()->errinfo; rb_io_close(f); @@ -1272,7 +1393,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("
"), file, rb_realpath_internal(Qnil, file, 1), - line, NULL, ISEQ_TYPE_TOP, &option)); + line, NULL, 0, ISEQ_TYPE_TOP, &option)); rb_ast_dispose(ast); return ret; } @@ -1770,6 +1891,21 @@ rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos) } } +#ifdef USE_ISEQ_NODE_ID +int +rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos) +{ + const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos); + + if (entry) { + return entry->node_id; + } + else { + return 0; + } +} +#endif + MJIT_FUNC_EXPORTED rb_event_flag_t rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos) { @@ -1823,6 +1959,7 @@ local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op) } int rb_insn_unified_local_var_level(VALUE); +VALUE rb_dump_literal(VALUE lit); VALUE rb_insn_operand_intern(const rb_iseq_t *iseq, @@ -1898,7 +2035,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, break; } } - ret = rb_inspect(op); + ret = rb_dump_literal(op); if (CLASS_OF(op) == rb_cISeq) { if (child) { rb_ary_push(child, op); @@ -1920,12 +2057,6 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, } break; } - case TS_GENTRY: - { - struct rb_global_entry *entry = (struct rb_global_entry *)op; - ret = rb_str_dup(rb_id2str(entry->id)); - } - break; case TS_IC: case TS_IVC: @@ -1936,24 +2067,25 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, case TS_CALLDATA: { struct rb_call_data *cd = (struct rb_call_data *)op; - struct rb_call_info *ci = &cd->ci; + const struct rb_callinfo *ci = cd->ci; VALUE ary = rb_ary_new(); + ID mid = vm_ci_mid(ci); - if (ci->mid) { - rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(ci->mid))); + if (mid) { + rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(mid))); } - rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc)); + rb_ary_push(ary, rb_sprintf("argc:%d", vm_ci_argc(ci))); - if (ci->flag & VM_CALL_KWARG) { - struct rb_call_info_kw_arg *kw_args = ((struct rb_call_info_with_kwarg *)ci)->kw_arg; - VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords); - rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(",")))); + if (vm_ci_flag(ci) & VM_CALL_KWARG) { + const struct rb_callinfo_kwarg *kw_args = vm_ci_kwarg(ci); + VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords); + rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(",")))); } - if (ci->flag) { + if (vm_ci_flag(ci)) { VALUE flags = rb_ary_new(); -# define CALL_FLAG(n) if (ci->flag & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n)) +# define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n)) CALL_FLAG(ARGS_SPLAT); CALL_FLAG(ARGS_BLOCKARG); CALL_FLAG(FCALL); @@ -1965,6 +2097,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, CALL_FLAG(ZSUPER); CALL_FLAG(KWARG); CALL_FLAG(KW_SPLAT); + CALL_FLAG(KW_SPLAT_MUT); CALL_FLAG(OPT_SEND); /* maybe not reachable */ rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|"))); } @@ -2277,7 +2410,9 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent) VALUE rb_iseq_disasm(const rb_iseq_t *iseq) { - return rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0)); + VALUE str = rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0)); + rb_str_resize(str, RSTRING_LEN(str)); + return str; } /* @@ -2319,7 +2454,7 @@ iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t * UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]); child = entry->iseq; if (child) { - if (rb_hash_aref(all_children, (VALUE)child) == Qnil) { + if (NIL_P(rb_hash_aref(all_children, (VALUE)child))) { rb_hash_aset(all_children, (VALUE)child, Qtrue); (*iter_func)(child, data); } @@ -2338,7 +2473,7 @@ iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t * case TS_ISEQ: child = (const rb_iseq_t *)code[i+j+1]; if (child) { - if (rb_hash_aref(all_children, (VALUE)child) == Qnil) { + if (NIL_P(rb_hash_aref(all_children, (VALUE)child))) { rb_hash_aset(all_children, (VALUE)child, Qtrue); (*iter_func)(child, data); } @@ -2541,12 +2676,6 @@ ruby_node_name(int node) } } -#define DECL_SYMBOL(name) \ - static ID sym_##name - -#define INIT_SYMBOL(name) \ - sym_##name = rb_intern(#name) - static VALUE register_label(struct st_table *table, unsigned long idx) { @@ -2586,6 +2715,52 @@ static const rb_data_type_t label_wrapper = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; +#define DECL_ID(name) \ + static ID id_##name + +#define INIT_ID(name) \ + id_##name = rb_intern(#name) + +static VALUE +iseq_type_id(enum iseq_type type) +{ + DECL_ID(top); + DECL_ID(method); + DECL_ID(block); + DECL_ID(class); + DECL_ID(rescue); + DECL_ID(ensure); + DECL_ID(eval); + DECL_ID(main); + DECL_ID(plain); + + if (id_top == 0) { + INIT_ID(top); + INIT_ID(method); + INIT_ID(block); + INIT_ID(class); + INIT_ID(rescue); + INIT_ID(ensure); + INIT_ID(eval); + INIT_ID(main); + INIT_ID(plain); + } + + switch (type) { + case ISEQ_TYPE_TOP: return id_top; + case ISEQ_TYPE_METHOD: return id_method; + case ISEQ_TYPE_BLOCK: return id_block; + case ISEQ_TYPE_CLASS: return id_class; + case ISEQ_TYPE_RESCUE: return id_rescue; + case ISEQ_TYPE_ENSURE: return id_ensure; + case ISEQ_TYPE_EVAL: return id_eval; + case ISEQ_TYPE_MAIN: return id_main; + case ISEQ_TYPE_PLAIN: return id_plain; + }; + + rb_bug("unsupported iseq type: %d", (int)type); +} + static VALUE iseq_data_to_ary(const rb_iseq_t *iseq) { @@ -2610,45 +2785,15 @@ iseq_data_to_ary(const rb_iseq_t *iseq) struct st_table *labels_table = st_init_numtable(); VALUE labels_wrapper = TypedData_Wrap_Struct(0, &label_wrapper, labels_table); - DECL_SYMBOL(top); - DECL_SYMBOL(method); - DECL_SYMBOL(block); - DECL_SYMBOL(class); - DECL_SYMBOL(rescue); - DECL_SYMBOL(ensure); - DECL_SYMBOL(eval); - DECL_SYMBOL(main); - DECL_SYMBOL(plain); - - if (sym_top == 0) { - int i; - for (i=0; itype) { - case ISEQ_TYPE_TOP: type = sym_top; break; - case ISEQ_TYPE_METHOD: type = sym_method; break; - case ISEQ_TYPE_BLOCK: type = sym_block; break; - case ISEQ_TYPE_CLASS: type = sym_class; break; - case ISEQ_TYPE_RESCUE: type = sym_rescue; break; - case ISEQ_TYPE_ENSURE: type = sym_ensure; break; - case ISEQ_TYPE_EVAL: type = sym_eval; break; - case ISEQ_TYPE_MAIN: type = sym_main; break; - case ISEQ_TYPE_PLAIN: type = sym_plain; break; - default: rb_bug("unsupported iseq type: %d", (int)iseq_body->type); - }; + type = iseq_type_id(iseq_body->type); /* locals */ for (i=0; ilocal_table_size; i++) { @@ -2746,12 +2891,6 @@ iseq_data_to_ary(const rb_iseq_t *iseq) } } break; - case TS_GENTRY: - { - struct rb_global_entry *entry = (struct rb_global_entry *)*seq; - rb_ary_push(ary, ID2SYM(entry->id)); - } - break; case TS_IC: case TS_IVC: case TS_ISE: @@ -2763,27 +2902,28 @@ iseq_data_to_ary(const rb_iseq_t *iseq) case TS_CALLDATA: { struct rb_call_data *cd = (struct rb_call_data *)*seq; - struct rb_call_info *ci = &cd->ci; + const struct rb_callinfo *ci = cd->ci; VALUE e = rb_hash_new(); - int orig_argc = ci->orig_argc; + int argc = vm_ci_argc(ci); - rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil); - rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag)); + ID mid = vm_ci_mid(ci); + rb_hash_aset(e, ID2SYM(rb_intern("mid")), mid ? ID2SYM(mid) : Qnil); + rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(vm_ci_flag(ci))); - if (ci->flag & VM_CALL_KWARG) { - struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci; - int i; - VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len); + if (vm_ci_flag(ci) & VM_CALL_KWARG) { + const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci); + int i; + VALUE kw = rb_ary_new2((long)kwarg->keyword_len); - orig_argc -= ci_kw->kw_arg->keyword_len; - for (i = 0; i < ci_kw->kw_arg->keyword_len; i++) { - rb_ary_push(kw, ci_kw->kw_arg->keywords[i]); + argc -= kwarg->keyword_len; + for (i = 0; i < kwarg->keyword_len; i++) { + rb_ary_push(kw, kwarg->keywords[i]); } rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw); } rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")), - INT2FIX(orig_argc)); + INT2FIX(argc)); rb_ary_push(ary, e); } break; @@ -2864,6 +3004,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq) /* make body with labels and insert line number */ body = rb_ary_new(); prev_insn_info = NULL; +#ifdef USE_ISEQ_NODE_ID + VALUE node_ids = rb_ary_new(); +#endif for (l=0, pos=0; lnode_id)); +#endif if (prev_insn_info != info) { int line = info->line_no; @@ -2912,6 +3058,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq) INT2FIX(iseq_body->location.code_location.beg_pos.column), INT2FIX(iseq_body->location.code_location.end_pos.lineno), INT2FIX(iseq_body->location.code_location.end_pos.column))); +#ifdef USE_ISEQ_NODE_ID + rb_hash_aset(misc, ID2SYM(rb_intern("node_ids")), node_ids); +#endif /* * [:magic, :major_version, :minor_version, :format_type, :misc, @@ -3018,9 +3167,18 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) rb_ary_push(args, a); } } - if (body->param.flags.has_kwrest) { + if (body->param.flags.has_kwrest || body->param.flags.ruby2_keywords) { + ID param; CONST_ID(keyrest, "keyrest"); - rb_ary_push(args, PARAM(keyword->rest_start, keyrest)); + PARAM_TYPE(keyrest); + if (body->param.flags.has_kwrest && + rb_id2str(param = PARAM_ID(keyword->rest_start))) { + rb_ary_push(a, ID2SYM(param)); + } + else if (body->param.flags.ruby2_keywords) { + rb_ary_push(a, ID2SYM(idPow)); + } + rb_ary_push(args, a); } if (body->param.flags.has_block) { CONST_ID(block, "block"); @@ -3049,24 +3207,10 @@ rb_iseq_defined_string(enum defined_type type) "expression", }; const char *estr; - VALUE *defs, str; - if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) return 0; + if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) rb_bug("unknown defined type %d", type); estr = expr_names[type - 1]; - if (!estr[0]) return 0; - defs = GET_VM()->defined_strings; - if (!defs) { - defs = ruby_xcalloc(numberof(expr_names), sizeof(VALUE)); - GET_VM()->defined_strings = defs; - } - str = defs[type-1]; - if (!str) { - str = rb_str_new_cstr(estr); - OBJ_FREEZE(str); - defs[type-1] = str; - rb_gc_register_mark_object(str); - } - return str; + return rb_fstring_cstr(estr); } /* A map from encoded_insn to insn_data: decoded insn number, its len, @@ -3099,8 +3243,15 @@ rb_vm_encoded_insn_data_table_init(void) insn_data[insn].insn = (int)insn; insn_data[insn].insn_len = insn_len(insn); - insn_data[insn].notrace_encoded_insn = (void *) key1; - insn_data[insn].trace_encoded_insn = (void *) key2; + + if (insn != BIN(opt_invokebuiltin_delegate_leave)) { + insn_data[insn].notrace_encoded_insn = (void *) key1; + insn_data[insn].trace_encoded_insn = (void *) key2; + } + else { + insn_data[insn].notrace_encoded_insn = (void *) INSN_CODE(BIN(opt_invokebuiltin_delegate)); + insn_data[insn].trace_encoded_insn = (void *) INSN_CODE(BIN(opt_invokebuiltin_delegate) + VM_INSTRUCTION_SIZE/2); + } st_add_direct(encoded_insn_data, key1, (st_data_t)&insn_data[insn]); st_add_direct(encoded_insn_data, key2, (st_data_t)&insn_data[insn]); @@ -3121,14 +3272,48 @@ rb_vm_insn_addr2insn(const void *addr) rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr); } +// Unlike rb_vm_insn_addr2insn, this function can return trace opcode variants. +int +rb_vm_insn_addr2opcode(const void *addr) +{ + st_data_t key = (st_data_t)addr; + st_data_t val; + + if (st_lookup(encoded_insn_data, key, &val)) { + insn_data_t *e = (insn_data_t *)val; + int opcode = e->insn; + if (addr == e->trace_encoded_insn) { + opcode += VM_INSTRUCTION_SIZE/2; + } + return opcode; + } + + rb_bug("rb_vm_insn_addr2opcode: invalid insn address: %p", addr); +} + +// Decode `iseq->body->iseq_encoded[i]` to an insn. +int +rb_vm_insn_decode(const VALUE encoded) +{ +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE + int insn = rb_vm_insn_addr2insn((void *)encoded); +#else + int insn = (int)encoded; +#endif + return insn; +} + static inline int -encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon) +encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace) { st_data_t key = (st_data_t)*iseq_encoded_insn; st_data_t val; if (st_lookup(encoded_insn_data, key, &val)) { insn_data_t *e = (insn_data_t *)val; + if (remain_current_trace && key == (st_data_t)e->trace_encoded_insn) { + turnon = 1; + } *iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn); return e->insn_len; } @@ -3141,9 +3326,26 @@ rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos) { const struct rb_iseq_constant_body *const body = iseq->body; VALUE *iseq_encoded = (VALUE *)body->iseq_encoded; - encoded_iseq_trace_instrument(&iseq_encoded[pos], 0); + encoded_iseq_trace_instrument(&iseq_encoded[pos], 0, false); +} + +// We need to fire call events on instructions with b_call events if the block +// is running as a method. So, if we are listening for call events, then +// instructions that have b_call events need to become trace variants. +// Use this function when making decisions about recompiling to trace variants. +static inline rb_event_flag_t +add_bmethod_events(rb_event_flag_t events) +{ + if (events & RUBY_EVENT_CALL) { + events |= RUBY_EVENT_B_CALL; + } + if (events & RUBY_EVENT_RETURN) { + events |= RUBY_EVENT_B_RETURN; + } + return events; } +// Note, to support call/return events for bmethods, turnon_event can have more events than tpval. static int iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line) { @@ -3170,12 +3372,13 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, if (pc_events & target_events) { n++; } - pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events)); + pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events), true); } if (n > 0) { if (iseq->aux.exec.local_hooks == NULL) { ((rb_iseq_t *)iseq)->aux.exec.local_hooks = RB_ZALLOC(rb_hook_list_t); + iseq->aux.exec.local_hooks->is_local = true; } rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->aux.exec.local_hooks, tpval, target_line); } @@ -3199,9 +3402,12 @@ iseq_add_local_tracepoint_i(const rb_iseq_t *iseq, void *p) } int -rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line) +rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod) { struct trace_set_local_events_struct data; + if (target_bmethod) { + turnon_events = add_bmethod_events(turnon_events); + } data.turnon_events = turnon_events; data.tpval = tpval; data.target_line = target_line; @@ -3227,15 +3433,14 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval) local_events = iseq->aux.exec.local_hooks->events; if (local_events == 0) { - if (iseq->aux.exec.local_hooks->running == 0) { - rb_hook_list_free(iseq->aux.exec.local_hooks); - } + rb_hook_list_free(iseq->aux.exec.local_hooks); ((rb_iseq_t *)iseq)->aux.exec.local_hooks = NULL; } + local_events = add_bmethod_events(local_events); for (pc = 0; pciseq_size;) { rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc); - pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events)); + pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events), false); } } return n; @@ -3283,15 +3488,41 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events) rb_event_flag_t enabled_events; rb_event_flag_t local_events = iseq->aux.exec.local_hooks ? iseq->aux.exec.local_hooks->events : 0; ((rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events; - enabled_events = turnon_events | local_events; + enabled_events = add_bmethod_events(turnon_events | local_events); for (pc=0; pciseq_size;) { rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc); - pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events); + pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events, true); } } } +bool rb_vm_call_ivar_attrset_p(const vm_call_handler ch); +void rb_vm_cc_general(const struct rb_callcache *cc); + +static int +clear_attr_ccs_i(void *vstart, void *vend, size_t stride, void *data) +{ + VALUE v = (VALUE)vstart; + for (; v != (VALUE)vend; v += stride) { + void *ptr = asan_poisoned_object_p(v); + asan_unpoison_object(v, false); + + if (imemo_type_p(v, imemo_callcache) && rb_vm_call_ivar_attrset_p(((const struct rb_callcache *)v)->call_)) { + rb_vm_cc_general((struct rb_callcache *)v); + } + + asan_poison_object_if(ptr, v); + } + return 0; +} + +void +rb_clear_attr_ccs(void) +{ + rb_objspace_each_objects(clear_attr_ccs_i, NULL); +} + static int trace_set_i(void *vstart, void *vend, size_t stride, void *data) { @@ -3305,6 +3536,9 @@ trace_set_i(void *vstart, void *vend, size_t stride, void *data) if (rb_obj_is_iseq(v)) { rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events); } + else if (imemo_type_p(v, imemo_callcache) && rb_vm_call_ivar_attrset_p(((const struct rb_callcache *)v)->call_)) { + rb_vm_cc_general((struct rb_callcache *)v); + } asan_poison_object_if(ptr, v); } @@ -3513,6 +3747,26 @@ succ_index_lookup(const struct succ_index_table *sd, int x) } #endif + +/* + * call-seq: + * iseq.script_lines -> array or nil + * + * It returns recorded script lines if it is availalble. + * The script lines are not limited to the iseq range, but + * are entire lines of the source file. + * + * Note that this is an API for ruby internal use, debugging, + * and research. Do not use this for any other purpose. + * The compatibility is not guaranteed. + */ +static VALUE +iseqw_script_lines(VALUE self) +{ + const rb_iseq_t *iseq = iseqw_check(self); + return iseq->body->variable.script_lines; +} + /* * Document-class: RubyVM::InstructionSequence * @@ -3553,7 +3807,6 @@ Init_ISeq(void) rb_define_singleton_method(rb_cISeq, "load_from_binary", iseqw_s_load_from_binary, 1); rb_define_singleton_method(rb_cISeq, "load_from_binary_extra_data", iseqw_s_load_from_binary_extra_data, 1); - /* location APIs */ rb_define_method(rb_cISeq, "path", iseqw_path, 0); rb_define_method(rb_cISeq, "absolute_path", iseqw_absolute_path, 0); @@ -3580,6 +3833,9 @@ Init_ISeq(void) rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1); rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1); + // script lines + rb_define_method(rb_cISeq, "script_lines", iseqw_script_lines, 0); + rb_undef_method(CLASS_OF(rb_cISeq), "translate"); rb_undef_method(CLASS_OF(rb_cISeq), "load_iseq"); } diff --git a/ruby/iseq.h b/ruby/iseq.h index 25c62a384..fc61d03b7 100644 --- a/ruby/iseq.h +++ b/ruby/iseq.h @@ -1,3 +1,5 @@ +#ifndef RUBY_ISEQ_H +#define RUBY_ISEQ_H 1 /********************************************************************** iseq.h - @@ -8,14 +10,17 @@ Copyright (C) 2004-2008 Koichi Sasada **********************************************************************/ - -#ifndef RUBY_ISEQ_H -#define RUBY_ISEQ_H 1 +#include "internal/gc.h" +#include "vm_core.h" RUBY_EXTERN const int ruby_api_version[]; #define ISEQ_MAJOR_VERSION ((unsigned int)ruby_api_version[0]) #define ISEQ_MINOR_VERSION ((unsigned int)ruby_api_version[1]) +#ifndef USE_ISEQ_NODE_ID +#define USE_ISEQ_NODE_ID 1 +#endif + #ifndef rb_iseq_t typedef struct rb_iseq_struct rb_iseq_t; #define rb_iseq_t rb_iseq_t @@ -23,14 +28,6 @@ typedef struct rb_iseq_struct rb_iseq_t; extern const ID rb_iseq_shared_exc_local_tbl[]; -static inline size_t -rb_call_info_kw_arg_bytes(int keyword_len) -{ - return rb_size_mul_add_or_raise( - keyword_len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg), - rb_eRuntimeError); -} - #define ISEQ_COVERAGE(iseq) iseq->body->variable.coverage #define ISEQ_COVERAGE_SET(iseq, cov) RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, cov) #define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES) @@ -77,6 +74,8 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) RUBY_EVENT_END | \ RUBY_EVENT_CALL | \ RUBY_EVENT_RETURN| \ + RUBY_EVENT_C_CALL| \ + RUBY_EVENT_C_RETURN| \ RUBY_EVENT_B_CALL| \ RUBY_EVENT_B_RETURN| \ RUBY_EVENT_COVERAGE_LINE| \ @@ -87,7 +86,7 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) #define ISEQ_TRANSLATED IMEMO_FL_USER3 #define ISEQ_MARKABLE_ISEQ IMEMO_FL_USER4 -#define ISEQ_EXECUTABLE_P(iseq) (FL_TEST_RAW((iseq), ISEQ_NOT_LOADED_YET | ISEQ_USE_COMPILE_DATA) == 0) +#define ISEQ_EXECUTABLE_P(iseq) (FL_TEST_RAW(((VALUE)iseq), ISEQ_NOT_LOADED_YET | ISEQ_USE_COMPILE_DATA) == 0) struct iseq_compile_data { /* GC is needed */ @@ -108,15 +107,17 @@ struct iseq_compile_data { struct iseq_compile_data_storage *storage_head; struct iseq_compile_data_storage *storage_current; } insn; + bool in_rescue; int loopval_popped; /* used by NODE_BREAK */ int last_line; int label_no; int node_level; + int isolated_depth; unsigned int ci_index; - unsigned int ci_kw_index; const rb_compile_option_t *option; struct rb_id_table *ivar_cache_table; const struct rb_builtin_function *builtin_function_table; + const NODE *root_node; #if OPT_SUPPORT_JOKE st_table *labels_table; #endif @@ -159,7 +160,7 @@ const rb_iseq_t *rb_iseq_ibf_load(VALUE str); const rb_iseq_t *rb_iseq_ibf_load_bytes(const char *cstr, size_t); VALUE rb_iseq_ibf_load_extra_data(VALUE str); void rb_iseq_init_trace(rb_iseq_t *iseq); -int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line); +int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod); int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval); const rb_iseq_t *rb_iseq_load_iseq(VALUE fname); @@ -167,6 +168,8 @@ const rb_iseq_t *rb_iseq_load_iseq(VALUE fname); unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body); #endif +int rb_vm_insn_addr2opcode(const void *addr); + RUBY_SYMBOL_EXPORT_BEGIN /* compile.c */ @@ -182,6 +185,9 @@ void rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *arena); VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt); VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc); unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos); +#ifdef USE_ISEQ_NODE_ID +int rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos); +#endif void rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events); void rb_iseq_trace_set_all(rb_event_flag_t turnon_events); void rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq); @@ -191,6 +197,8 @@ VALUE rb_iseqw_new(const rb_iseq_t *iseq); const rb_iseq_t *rb_iseqw_to_iseq(VALUE iseqw); VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq); /* obsolete */ +int rb_iseq_from_eval_p(const rb_iseq_t *iseq); +VALUE rb_iseq_type(const rb_iseq_t *iseq); VALUE rb_iseq_label(const rb_iseq_t *iseq); VALUE rb_iseq_base_label(const rb_iseq_t *iseq); VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq); @@ -219,6 +227,9 @@ struct rb_compile_option_struct { struct iseq_insn_info_entry { int line_no; +#ifdef USE_ISEQ_NODE_ID + int node_id; +#endif rb_event_flag_t events; }; @@ -296,7 +307,6 @@ enum defined_type { DEFINED_FALSE, DEFINED_ASGN, DEFINED_EXPR, - DEFINED_IVAR2, DEFINED_REF, DEFINED_FUNC, DEFINED_CONST_FROM diff --git a/ruby/kernel.rb b/ruby/kernel.rb new file mode 100644 index 000000000..9cc58bc1d --- /dev/null +++ b/ruby/kernel.rb @@ -0,0 +1,178 @@ +module Kernel + # + # call-seq: + # obj.class -> class + # + # Returns the class of obj. This method must always be called + # with an explicit receiver, as #class is also a reserved word in + # Ruby. + # + # 1.class #=> Integer + # self.class #=> Object + #-- + # Equivalent to \c Object\#class in Ruby. + # + # Returns the class of \c obj, skipping singleton classes or module inclusions. + #++ + # + def class + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_obj_class(self)' + end + + # + # call-seq: + # obj.clone(freeze: nil) -> an_object + # + # Produces a shallow copy of obj---the instance variables of + # obj are copied, but not the objects they reference. + # #clone copies the frozen value state of obj, unless the + # +:freeze+ keyword argument is given with a false or true value. + # See also the discussion under Object#dup. + # + # class Klass + # attr_accessor :str + # end + # s1 = Klass.new #=> # + # s1.str = "Hello" #=> "Hello" + # s2 = s1.clone #=> # + # s2.str[1,4] = "i" #=> "i" + # s1.inspect #=> "#" + # s2.inspect #=> "#" + # + # This method may have class-specific behavior. If so, that + # behavior will be documented under the #+initialize_copy+ method of + # the class. + # + def clone(freeze: nil) + Primitive.rb_obj_clone2(freeze) + end + + # + # call-seq: + # obj.frozen? -> true or false + # + # Returns the freeze status of obj. + # + # a = [ "a", "b", "c" ] + # a.freeze #=> ["a", "b", "c"] + # a.frozen? #=> true + #-- + # Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby. + # \param[in] obj the object to be determines + # \retval Qtrue if frozen + # \retval Qfalse if not frozen + #++ + # + def frozen? + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_obj_frozen_p(self)' + end + + # + # call-seq: + # obj.tap {|x| block } -> obj + # + # Yields self to the block, and then returns self. + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # (1..10) .tap {|x| puts "original: #{x}" } + # .to_a .tap {|x| puts "array: #{x}" } + # .select {|x| x.even? } .tap {|x| puts "evens: #{x}" } + # .map {|x| x*x } .tap {|x| puts "squares: #{x}" } + # + #-- + # \private + #++ + # + def tap + yield(self) + self + end + + # + # call-seq: + # obj.then {|x| block } -> an_object + # + # Yields self to the block and returns the result of the block. + # + # 3.next.then {|x| x**x }.to_s #=> "256" + # + # Good usage for +then+ is value piping in method chains: + # + # require 'open-uri' + # require 'json' + # + # construct_url(arguments). + # then {|url| URI(url).read }. + # then {|response| JSON.parse(response) } + # + # When called without block, the method returns +Enumerator+, + # which can be used, for example, for conditional + # circuit-breaking: + # + # # meets condition, no-op + # 1.then.detect(&:odd?) # => 1 + # # does not meet condition, drop value + # 2.then.detect(&:odd?) # => nil + # + def then + unless Primitive.block_given_p + return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)' + end + yield(self) + end + + # + # call-seq: + # obj.yield_self {|x| block } -> an_object + # + # Yields self to the block and returns the result of the block. + # + # "my string".yield_self {|s| s.upcase } #=> "MY STRING" + # + # Good usage for +then+ is value piping in method chains: + # + # require 'open-uri' + # require 'json' + # + # construct_url(arguments). + # then {|url| URI(url).read }. + # then {|response| JSON.parse(response) } + # + def yield_self + unless Primitive.block_given_p + return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)' + end + yield(self) + end + + module_function + + # + # call-seq: + # Float(arg, exception: true) -> float or nil + # + # Returns arg converted to a float. Numeric types are + # converted directly, and with exception to String and + # nil the rest are converted using + # arg.to_f. Converting a String with invalid + # characters will result in a ArgumentError. Converting + # nil generates a TypeError. Exceptions can be + # suppressed by passing exception: false. + # + # Float(1) #=> 1.0 + # Float("123.456") #=> 123.456 + # Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring" + # Float(nil) #=> TypeError: can't convert nil into Float + # Float("123.0_badstring", exception: false) #=> nil + # + def Float(arg, exception: true) + if Primitive.mandatory_only? + Primitive.rb_f_float1(arg) + else + Primitive.rb_f_float(arg, exception) + end + end +end diff --git a/ruby/lib/.document b/ruby/lib/.document deleted file mode 100644 index 668152021..000000000 --- a/ruby/lib/.document +++ /dev/null @@ -1,25 +0,0 @@ -# Add files to this as they become documented - -*.rb - -bundler -cgi -csv -drb -forwardable -irb -matrix -net -optparse -racc -rdoc -rexml -rinda -rss -rubygems -scanf.rb -shell -unicode_normalize -uri -webrick -yaml diff --git a/ruby/lib/English.gemspec b/ruby/lib/English.gemspec new file mode 100644 index 000000000..274fb047b --- /dev/null +++ b/ruby/lib/English.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "english" + spec.version = "0.7.1" + spec.authors = ["Yukihiro Matsumoto"] + spec.email = ["matz@ruby-lang.org"] + + spec.summary = %q{Require 'English.rb' to reference global variables with less cryptic names.} + spec.description = %q{Require 'English.rb' to reference global variables with less cryptic names.} + spec.homepage = "https://github.com/ruby/English" + 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 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + end + spec.require_paths = ["lib"] +end diff --git a/ruby/lib/abbrev.gemspec b/ruby/lib/abbrev.gemspec new file mode 100644 index 000000000..72837ed2a --- /dev/null +++ b/ruby/lib/abbrev.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "abbrev" + spec.version = "0.1.0" + spec.authors = ["Akinori MUSHA"] + spec.email = ["knu@idaemons.org"] + + spec.summary = %q{Calculates a set of unique abbreviations for a given set of strings} + spec.description = %q{Calculates a set of unique abbreviations for a given set of strings} + spec.homepage = "https://github.com/ruby/abbrev" + 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 + + 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.require_paths = ["lib"] +end diff --git a/ruby/lib/base64.gemspec b/ruby/lib/base64.gemspec new file mode 100644 index 000000000..daa0b7fa1 --- /dev/null +++ b/ruby/lib/base64.gemspec @@ -0,0 +1,20 @@ +Gem::Specification.new do |spec| + spec.name = "base64" + spec.version = "0.1.1" + spec.authors = ["Yusuke Endoh"] + spec.email = ["mame@ruby-lang.org"] + + spec.summary = %q{Support for encoding and decoding binary data using a Base64 representation.} + spec.description = %q{Support for encoding and decoding binary data using a Base64 representation.} + spec.homepage = "https://github.com/ruby/base64" + 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 + + spec.files = ["README.md", "LICENSE.txt", "lib/base64.rb"] + spec.bindir = "exe" + spec.executables = [] + spec.require_paths = ["lib"] +end diff --git a/ruby/lib/base64.rb b/ruby/lib/base64.rb index 5c8df841f..693aa1f51 100644 --- a/ruby/lib/base64.rb +++ b/ruby/lib/base64.rb @@ -82,8 +82,8 @@ def strict_decode64(str) # You can remove the padding by setting +padding+ as false. def urlsafe_encode64(bin, padding: true) str = strict_encode64(bin) + str.chomp!("==") or str.chomp!("=") unless padding str.tr!("+/", "-_") - str.delete!("=") unless padding str end @@ -99,9 +99,11 @@ def urlsafe_decode64(str) # NOTE: RFC 4648 does say nothing about unpadded input, but says that # "the excess pad characters MAY also be ignored", so it is inferred that # unpadded input is also acceptable. - str = str.tr("-_", "+/") if !str.end_with?("=") && str.length % 4 != 0 str = str.ljust((str.length + 3) & ~3, "=") + str.tr!("-_", "+/") + else + str = str.tr("-_", "+/") end strict_decode64(str) end diff --git a/ruby/lib/benchmark.rb b/ruby/lib/benchmark.rb index 5ce971058..79c782e26 100644 --- a/ruby/lib/benchmark.rb +++ b/ruby/lib/benchmark.rb @@ -128,6 +128,9 @@ module Benchmark # benchmark tests. Reserves +label_width+ leading spaces for # labels on each line. Prints +caption+ at the top of the # report, and uses +format+ to format each line. + # (Note: +caption+ must contain a terminating newline character, + # see the default Benchmark::Tms::CAPTION for an example.) + # # Returns an array of Benchmark::Tms objects. # # If the block returns an array of @@ -163,8 +166,8 @@ module Benchmark # def benchmark(caption = "", label_width = nil, format = nil, *labels) # :yield: report - sync = STDOUT.sync - STDOUT.sync = true + sync = $stdout.sync + $stdout.sync = true label_width ||= 0 label_width += 1 format ||= FORMAT @@ -176,7 +179,7 @@ def benchmark(caption = "", label_width = nil, format = nil, *labels) # :yield: } report.list ensure - STDOUT.sync = sync unless sync.nil? + $stdout.sync = sync unless sync.nil? end @@ -247,8 +250,8 @@ def bmbm(width = 0) # :yield: job job = Job.new(width) yield(job) width = job.width + 1 - sync = STDOUT.sync - STDOUT.sync = true + sync = $stdout.sync + $stdout.sync = true # rehearsal puts 'Rehearsal '.ljust(width+CAPTION.length,'-') @@ -268,7 +271,7 @@ def bmbm(width = 0) # :yield: job Benchmark.measure(label, &item).tap { |res| print res } } ensure - STDOUT.sync = sync unless sync.nil? + $stdout.sync = sync unless sync.nil? end # @@ -527,6 +530,20 @@ def to_a [@label, @utime, @stime, @cutime, @cstime, @real] end + # + # Returns a hash containing the same data as `to_a`. + # + def to_h + { + label: @label, + utime: @utime, + stime: @stime, + cutime: @cutime, + cstime: @cstime, + real: @real + } + end + protected # diff --git a/ruby/lib/benchmark/benchmark.gemspec b/ruby/lib/benchmark/benchmark.gemspec index 773cab19b..58b47d95e 100644 --- a/ruby/lib/benchmark/benchmark.gemspec +++ b/ruby/lib/benchmark/benchmark.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |spec| spec.summary = %q{a performance benchmarking library} spec.description = spec.summary spec.homepage = "https://github.com/ruby/benchmark" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage @@ -24,6 +24,6 @@ Gem::Specification.new do |spec| `git ls-files -z 2>/dev/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.executables = [] spec.require_paths = ["lib"] end diff --git a/ruby/lib/benchmark/version.rb b/ruby/lib/benchmark/version.rb index d74cc74ee..545575f4a 100644 --- a/ruby/lib/benchmark/version.rb +++ b/ruby/lib/benchmark/version.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module Benchmark - VERSION = "0.1.0" + VERSION = "0.2.0" end diff --git a/ruby/lib/bundler.rb b/ruby/lib/bundler.rb index df345539c..868820628 100644 --- a/ruby/lib/bundler.rb +++ b/ruby/lib/bundler.rb @@ -34,15 +34,16 @@ # of loaded and required modules. # module Bundler - environment_preserver = EnvironmentPreserver.new(ENV, EnvironmentPreserver::BUNDLER_KEYS) + environment_preserver = EnvironmentPreserver.from_env ORIGINAL_ENV = environment_preserver.restore - ENV.replace(environment_preserver.backup) - SUDO_MUTEX = Mutex.new + environment_preserver.replace_with_backup + SUDO_MUTEX = Thread::Mutex.new autoload :Definition, File.expand_path("bundler/definition", __dir__) autoload :Dependency, File.expand_path("bundler/dependency", __dir__) autoload :DepProxy, File.expand_path("bundler/dep_proxy", __dir__) autoload :Deprecate, File.expand_path("bundler/deprecate", __dir__) + autoload :Digest, File.expand_path("bundler/digest", __dir__) autoload :Dsl, File.expand_path("bundler/dsl", __dir__) autoload :EndpointSpecification, File.expand_path("bundler/endpoint_specification", __dir__) autoload :Env, File.expand_path("bundler/env", __dir__) @@ -63,13 +64,14 @@ module Bundler autoload :Resolver, File.expand_path("bundler/resolver", __dir__) autoload :Retry, File.expand_path("bundler/retry", __dir__) autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__) - autoload :RubyGemsGemInstaller, File.expand_path("bundler/rubygems_gem_installer", __dir__) autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__) autoload :Runtime, File.expand_path("bundler/runtime", __dir__) + autoload :SelfManager, File.expand_path("bundler/self_manager", __dir__) autoload :Settings, File.expand_path("bundler/settings", __dir__) autoload :SharedHelpers, File.expand_path("bundler/shared_helpers", __dir__) autoload :Source, File.expand_path("bundler/source", __dir__) autoload :SourceList, File.expand_path("bundler/source_list", __dir__) + autoload :SourceMap, File.expand_path("bundler/source_map", __dir__) autoload :SpecSet, File.expand_path("bundler/spec_set", __dir__) autoload :StubSpecification, File.expand_path("bundler/stub_specification", __dir__) autoload :UI, File.expand_path("bundler/ui", __dir__) @@ -198,7 +200,7 @@ def definition(unlock = nil) def frozen_bundle? frozen = settings[:deployment] - frozen ||= settings[:frozen] unless feature_flag.deployment_means_frozen? + frozen ||= settings[:frozen] frozen end @@ -212,6 +214,12 @@ def locked_gems end end + def most_specific_locked_platform?(platform) + return false unless defined?(@definition) && @definition + + definition.most_specific_locked_platform == platform + end + def ruby_scope "#{Bundler.rubygems.ruby_engine}/#{RbConfig::CONFIG["ruby_version"]}" end @@ -230,8 +238,9 @@ def user_home end if warning - user_home = tmp_home_path(warning) - Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n" + Bundler.ui.warn "#{warning}\n" + user_home = tmp_home_path + Bundler.ui.warn "Bundler will use `#{user_home}' as your home directory temporarily.\n" user_home else Pathname.new(home) @@ -285,7 +294,13 @@ def root def app_config_path if app_config = ENV["BUNDLE_APP_CONFIG"] - Pathname.new(app_config).expand_path(root) + app_config_pathname = Pathname.new(app_config) + + if app_config_pathname.absolute? + app_config_pathname + else + app_config_pathname.expand_path(root) + end else root.join(".bundle") end @@ -347,7 +362,10 @@ def unbundled_env env.delete_if {|k, _| k[0, 7] == "BUNDLE_" } if env.key?("RUBYOPT") - env["RUBYOPT"] = env["RUBYOPT"].sub "-rbundler/setup", "" + rubyopt = env["RUBYOPT"].split(" ") + rubyopt.delete("-r#{File.expand_path("bundler/setup", __dir__)}") + rubyopt.delete("-rbundler/setup") + env["RUBYOPT"] = rubyopt.join(" ") end if env.key?("RUBYLIB") @@ -426,7 +444,7 @@ def unbundled_exec(*args) end def local_platform - return Gem::Platform::RUBY if settings[:force_ruby_platform] + return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY] Gem::Platform.local end @@ -447,10 +465,14 @@ def system_bindir # system binaries. If you put '-n foo' in your .gemrc, RubyGems will # install binstubs there instead. Unfortunately, RubyGems doesn't expose # that directory at all, so rather than parse .gemrc ourselves, we allow - # the directory to be set as well, via `bundle config set bindir foo`. + # the directory to be set as well, via `bundle config set --local bindir foo`. Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir end + def preferred_gemfile_name + Bundler.settings[:init_gems_rb] ? "gems.rb" : "Gemfile" + end + def use_system_gems? configured_bundle_path.use_system_gems? end @@ -512,7 +534,8 @@ def sudo(str) Your user account isn't allowed to install to the system RubyGems. You can cancel this installation and run: - bundle install --path vendor/bundle + bundle config set --local path 'vendor/bundle' + bundle install to install the gems into ./vendor/bundle/, or you can enter your password and install the bundled gems to RubyGems using sudo. @@ -588,6 +611,11 @@ def reset! reset_rubygems! end + def reset_settings_and_root! + @settings = nil + @root = nil + end + def reset_paths! @bin_path = nil @bundler_major_version = nil @@ -610,15 +638,26 @@ def reset_rubygems! @rubygems = nil end - private + def configure_gem_home_and_path(path = bundle_path) + configure_gem_path + configure_gem_home(path) + Bundler.rubygems.clear_paths + end + + def self_manager + @self_manager ||= begin + require_relative "bundler/self_manager" + Bundler::SelfManager.new + end + end + + private def eval_yaml_gemspec(path, contents) - require_relative "bundler/psyched_yaml" + Kernel.require "psych" - # If the YAML is invalid, Syck raises an ArgumentError, and Psych - # raises a Psych::SyntaxError. See psyched_yaml.rb for more info. Gem::Specification.from_yaml(contents) - rescue YamlLibrarySyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception + rescue ::Psych::SyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception eval_gemspec(path, contents) end @@ -627,47 +666,29 @@ def eval_gemspec(path, contents) rescue ScriptError, StandardError => e msg = "There was an error while loading `#{path.basename}`: #{e.message}" - if e.is_a?(LoadError) - msg += "\nDoes it try to require a relative path? That's been removed in Ruby 1.9" - end - raise GemspecError, Dsl::DSLError.new(msg, path, e.backtrace, contents) end - def configure_gem_home_and_path - configure_gem_path - configure_gem_home - bundle_path - end - - def configure_gem_path(env = ENV) - blank_home = env["GEM_HOME"].nil? || env["GEM_HOME"].empty? - if !use_system_gems? + def configure_gem_path + unless use_system_gems? # this needs to be empty string to cause # PathSupport.split_gem_path to only load up the # Bundler --path setting as the GEM_PATH. - env["GEM_PATH"] = "" - elsif blank_home - possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] - paths = possibles.flatten.compact.uniq.reject(&:empty?) - env["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) + Bundler::SharedHelpers.set_env "GEM_PATH", "" end end - def configure_gem_home - Bundler::SharedHelpers.set_env "GEM_HOME", File.expand_path(bundle_path, root) - Bundler.rubygems.clear_paths + def configure_gem_home(path) + Bundler::SharedHelpers.set_env "GEM_HOME", path.to_s end - def tmp_home_path(warning) + def tmp_home_path Kernel.send(:require, "tmpdir") SharedHelpers.filesystem_access(Dir.tmpdir) do path = Bundler.tmp at_exit { Bundler.rm_rf(path) } path end - rescue RuntimeError => e - raise e.exception("#{warning}\nBundler also failed to create a temporary home directory':\n#{e}") end # @param env [Hash] diff --git a/ruby/lib/bundler/.document b/ruby/lib/bundler/.document new file mode 100644 index 000000000..238bbd870 --- /dev/null +++ b/ruby/lib/bundler/.document @@ -0,0 +1 @@ +# not in RDoc diff --git a/ruby/lib/bundler/build_metadata.rb b/ruby/lib/bundler/build_metadata.rb index 4dfad2f8d..0846e82e0 100644 --- a/ruby/lib/bundler/build_metadata.rb +++ b/ruby/lib/bundler/build_metadata.rb @@ -27,19 +27,11 @@ def self.git_commit_sha # If Bundler has been installed without its .git directory and without a # commit instance variable then we can't determine its commits SHA. - git_dir = File.join(File.expand_path("../../..", __FILE__), ".git") + git_dir = File.join(File.expand_path("../../../..", __FILE__), ".git") if File.directory?(git_dir) return @git_commit_sha = Dir.chdir(git_dir) { `git rev-parse --short HEAD`.strip.freeze } end - # If Bundler is a submodule in RubyGems, get the submodule commit - git_sub_dir = File.join(File.expand_path("../../../..", __FILE__), ".git") - if File.directory?(git_sub_dir) - return @git_commit_sha = Dir.chdir(git_sub_dir) do - `git ls-tree --abbrev=8 HEAD bundler`.split(/\s/).fetch(2, "").strip.freeze - end - end - @git_commit_sha ||= "unknown" end diff --git a/ruby/lib/bundler/bundler.gemspec b/ruby/lib/bundler/bundler.gemspec index 30a21f155..38c533b0c 100644 --- a/ruby/lib/bundler/bundler.gemspec +++ b/ruby/lib/bundler/bundler.gemspec @@ -24,19 +24,20 @@ Gem::Specification.new do |s| if s.respond_to?(:metadata=) s.metadata = { - "bug_tracker_uri" => "https://github.com/bundler/bundler/issues", - "changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md", + "bug_tracker_uri" => "https://github.com/rubygems/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler", + "changelog_uri" => "https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md", "homepage_uri" => "https://bundler.io/", - "source_code_uri" => "https://github.com/bundler/bundler/", + "source_code_uri" => "https://github.com/rubygems/rubygems/", } end s.required_ruby_version = ">= 2.3.0" s.required_rubygems_version = ">= 2.5.2" - s.files = (Dir.glob("lib/bundler/**/*", File::FNM_DOTMATCH) + Dir.glob("man/bundler*") + Dir.glob("libexec/bundle*")).reject {|f| File.directory?(f) } + s.files = Dir.glob("lib/bundler{.rb,/**/*}", File::FNM_DOTMATCH).reject {|f| File.directory?(f) } - s.files += ["lib/bundler.rb"] + # include the gemspec itself because warbler breaks w/o it + s.files += %w[lib/bundler/bundler.gemspec] s.bindir = "libexec" s.executables = %w[bundle bundler] diff --git a/ruby/lib/bundler/cli.rb b/ruby/lib/bundler/cli.rb index 443458f2d..16651dfad 100644 --- a/ruby/lib/bundler/cli.rb +++ b/ruby/lib/bundler/cli.rb @@ -14,6 +14,7 @@ class CLI < Thor COMMAND_ALIASES = { "check" => "c", "install" => "i", + "plugin" => "", "list" => "ls", "exec" => ["e", "ex", "exe"], "cache" => ["package", "pack"], @@ -57,9 +58,11 @@ def initialize(*args) custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile] if custom_gemfile && !custom_gemfile.empty? Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile) - Bundler.reset_paths! + Bundler.reset_settings_and_root! end + Bundler.self_manager.restart_with_locked_bundler_if_needed + Bundler.settings.set_command_option_if_given :retry, options[:retry] current_cmd = args.last[:current_command].name @@ -72,14 +75,6 @@ def initialize(*args) Bundler.ui = UI::Shell.new(options) Bundler.ui.level = "debug" if options["verbose"] unprinted_warnings.each {|w| Bundler.ui.warn(w) } - - if ENV["RUBYGEMS_GEMDEPS"] && !ENV["RUBYGEMS_GEMDEPS"].empty? - Bundler.ui.warn( - "The RUBYGEMS_GEMDEPS environment variable is set. This enables RubyGems' " \ - "experimental Gemfile mode, which may conflict with Bundler and cause unexpected errors. " \ - "To remove this warning, unset RUBYGEMS_GEMDEPS.", :wrap => true - ) - end end check_unknown_options!(:except => [:config, :exec]) @@ -122,16 +117,17 @@ def help(cli = nil) else command = "bundle-#{cli}" end - man_path = File.expand_path("../../../man", __FILE__) - man_pages = Hash[Dir.glob(File.join(man_path, "*")).grep(/.*\.\d*\Z/).collect do |f| + man_path = File.expand_path("man", __dir__) + man_pages = Hash[Dir.glob(File.join(man_path, "**", "*")).grep(/.*\.\d*\Z/).collect do |f| [File.basename(f, ".*"), f] end] if man_pages.include?(command) + man_page = man_pages[command] if Bundler.which("man") && man_path !~ %r{^file:/.+!/META-INF/jruby.home/.+} - Kernel.exec "man #{man_pages[command]}" + Kernel.exec "man #{man_page}" else - puts File.read("#{man_path}/#{File.basename(man_pages[command])}.txt") + puts File.read("#{man_path}/#{File.basename(man_page)}.ronn") end elsif command_path = Bundler.which("bundler-#{cli}") Kernel.exec(command_path, "--help") @@ -190,6 +186,7 @@ def check method_option "install", :type => :boolean, :banner => "Runs 'bundle install' after removing the gems from the Gemfile" def remove(*gems) + SharedHelpers.major_deprecation(2, "The `--install` flag has been deprecated. `bundle install` is triggered by default.") if ARGV.include?("--install") require_relative "cli/remove" Remove.new(gems, options).run end @@ -247,10 +244,12 @@ def remove(*gems) def install SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force") - %w[clean deployment frozen no-cache no-prune path shebang system without with].each do |option| + %w[clean deployment frozen no-prune path shebang system without with].each do |option| remembered_flag_deprecation(option) end + remembered_negative_flag_deprecation("no-deployment") + require_relative "cli/install" Bundler.settings.temporary(:no_install => false) do Install.new(options.dup).run @@ -305,45 +304,25 @@ def update(*gems) end end - unless Bundler.feature_flag.bundler_3_mode? - desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem" - long_desc <<-D - Show lists the names and versions of all gems that are required by your Gemfile. - Calling show with [GEM] will list the exact location of that gem on your machine. - D - method_option "paths", :type => :boolean, - :banner => "List the paths of all gems that are required by your Gemfile." - method_option "outdated", :type => :boolean, - :banner => "Show verbose output including whether gems are outdated." - def show(gem_name = nil) - if ARGV[0] == "show" - rest = ARGV[1..-1] - - if flag = rest.find{|arg| ["--verbose", "--outdated"].include?(arg) } - Bundler::SharedHelpers.major_deprecation(2, "the `#{flag}` flag to `bundle show` was undocumented and will be removed without replacement") - else - new_command = rest.find {|arg| !arg.start_with?("--") } ? "info" : "list" - - new_arguments = rest.map do |arg| - next arg if arg != "--paths" - next "--path" if new_command == "info" - end - - old_argv = ARGV.join(" ") - new_argv = [new_command, *new_arguments.compact].join(" ") - - Bundler::SharedHelpers.major_deprecation(2, "use `bundle #{new_argv}` instead of `bundle #{old_argv}`") - end - end - require_relative "cli/show" - Show.new(options, gem_name).run - end + desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem" + long_desc <<-D + Show lists the names and versions of all gems that are required by your Gemfile. + Calling show with [GEM] will list the exact location of that gem on your machine. + D + method_option "paths", :type => :boolean, + :banner => "List the paths of all gems that are required by your Gemfile." + method_option "outdated", :type => :boolean, + :banner => "Show verbose output including whether gems are outdated." + def show(gem_name = nil) + SharedHelpers.major_deprecation(2, "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") if ARGV.include?("--outdated") + require_relative "cli/show" + Show.new(options, gem_name).run end desc "list", "List all gems in the bundle" method_option "name-only", :type => :boolean, :banner => "print only the gem names" - method_option "only-group", :type => :string, :banner => "print gems from a particular group" - method_option "without-group", :type => :string, :banner => "print all gems except from a group" + method_option "only-group", :type => :array, :default => [], :banner => "print gems from a given set of groups" + method_option "without-group", :type => :array, :default => [], :banner => "print all gems except from a given set of groups" method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle" def list require_relative "cli/list" @@ -354,6 +333,7 @@ def list desc "info GEM [OPTIONS]", "Show information for the given gem" method_option "path", :type => :boolean, :banner => "Print full path to gem" + method_option "version", :type => :boolean, :banner => "Print gem version" def info(gem_name) require_relative "cli/info" Info.new(options, gem_name).run @@ -375,6 +355,8 @@ def info(gem_name) "Make binstubs that can work without the Bundler runtime" method_option "all", :type => :boolean, :banner => "Install binstubs for all gems" + method_option "all-platforms", :type => :boolean, :default => false, :banner => + "Install binstubs for all platforms" def binstubs(*gems) require_relative "cli/binstubs" Binstubs.new(options, gems).run @@ -387,8 +369,11 @@ def binstubs(*gems) method_option "version", :aliases => "-v", :type => :string method_option "group", :aliases => "-g", :type => :string method_option "source", :aliases => "-s", :type => :string + method_option "require", :aliases => "-r", :type => :string, :banner => "Adds require path to gem. Provide false, or a path as a string." method_option "git", :type => :string + method_option "github", :type => :string method_option "branch", :type => :string + method_option "ref", :type => :string method_option "skip-install", :type => :boolean, :banner => "Adds gem to the Gemfile but does not install it" method_option "optimistic", :type => :boolean, :banner => "Adds optimistic declaration of version to gem" @@ -434,11 +419,18 @@ def outdated(*gems) Outdated.new(options, gems).run end - desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache" - unless Bundler.feature_flag.cache_all? - method_option "all", :type => :boolean, - :banner => "Include all sources (including path and git)." + desc "fund [OPTIONS]", "Lists information about gems seeking funding assistance" + method_option "group", :aliases => "-g", :type => :array, :banner => + "Fetch funding information for a specific group" + def fund + require_relative "cli/fund" + Fund.new(options).run end + + desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache" + method_option "all", :type => :boolean, + :default => Bundler.feature_flag.cache_all?, + :banner => "Include all sources (including path and git)." method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one" method_option "cache-path", :type => :string, :banner => "Specify a different cache path than the default (vendor/cache)." @@ -457,6 +449,18 @@ def outdated(*gems) bundle without having to download any additional gems. D def cache + SharedHelpers.major_deprecation 2, + "The `--all` flag is deprecated because it relies on being " \ + "remembered across bundler invocations, which bundler will no longer " \ + "do in future versions. Instead please use `bundle config set cache_all true`, " \ + "and stop using this flag" if ARGV.include?("--all") + + SharedHelpers.major_deprecation 2, + "The `--path` flag is deprecated because its semantics are unclear. " \ + "Use `bundle config cache_path` to configure the path of your cache of gems, " \ + "and `bundle config path` to configure the path where your gems are installed, " \ + "and stop using this flag" if ARGV.include?("--path") + require_relative "cli/cache" Cache.new(options).run end @@ -464,7 +468,7 @@ def cache map aliases_for("cache") desc "exec [OPTIONS]", "Run the command in context of the bundle" - method_option :keep_file_descriptors, :type => :boolean, :default => false + method_option :keep_file_descriptors, :type => :boolean, :default => true method_option :gemfile, :type => :string, :required => false long_desc <<-D Exec runs a command, providing it access to the gems in the bundle. While using @@ -472,6 +476,10 @@ def cache into the system wide RubyGems repository. D def exec(*args) + if ARGV.include?("--no-keep-file-descriptors") + SharedHelpers.major_deprecation(2, "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to") + end + require_relative "cli/exec" Exec.new(options, args).run end @@ -486,8 +494,8 @@ def exec(*args) By default, setting a configuration value sets it for all projects on the machine. - If a global setting is superceded by local configuration, this command - will show the current value, as well as any superceded values and + If a global setting is superseded by local configuration, this command + will show the current value, as well as any superseded values and where they were specified. D require_relative "cli/config" @@ -550,7 +558,7 @@ def licenses method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version." method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group." def viz - SharedHelpers.major_deprecation 2, "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz" + SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph" require_relative "cli/viz" Viz.new(options.dup).run end @@ -560,15 +568,23 @@ def viz desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem" method_option :exe, :type => :boolean, :default => false, :aliases => ["--bin", "-b"], :desc => "Generate a binary executable for your library." - method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set gem.coc true`." + method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`." method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR", :lazy_default => [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, :desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" method_option :ext, :type => :boolean, :default => false, :desc => "Generate the boilerplate for C extension code" method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library." - method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set gem.mit true`." - method_option :test, :type => :string, :lazy_default => "rspec", :aliases => "-t", :banner => "rspec", - :desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config set gem.test rspec`." + method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." + method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." + method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." + method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library", + :desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`." + method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "", + :desc => "Generate CI configuration, either GitHub Actions, Travis CI, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|travis|gitlab|circle)`" + method_option :linter, :type => :string, :lazy_default => Bundler.settings["gem.linter"] || "", + :desc => "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`" + method_option :github_username, :type => :string, :default => Bundler.settings["gem.github_username"], :banner => "Set your username on GitHub", :desc => "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username `." + def gem(name) end @@ -731,11 +747,11 @@ def self.reformatted_help_args(args) end end - private + private # Automatically invoke `bundle install` and resume if # Bundler.settings[:auto_install] exists. This is set through config cmd - # `bundle config set auto_install 1`. + # `bundle config set --global auto_install 1`. # # Note that this method `nil`s out the global Definition object, so it # should be called first, before you instantiate anything like an @@ -793,35 +809,40 @@ def warn_on_outdated_bundler current = Gem::Version.new(VERSION) return if current >= latest - latest_installed = Bundler.rubygems.find_name("bundler").map(&:version).max - - installation = "To install the latest version, run `gem install bundler#{" --pre" if latest.prerelease?}`" - if latest_installed && latest_installed > current - suggestion = "To update to the most recent installed version (#{latest_installed}), run `bundle update --bundler`" - suggestion = "#{installation}\n#{suggestion}" if latest_installed < latest - else - suggestion = installation - end - Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\n#{suggestion}" + Bundler.ui.warn \ + "The latest bundler is #{latest}, but you are currently running #{current}.\n" \ + "To update to the most recent version, run `bundle update --bundler`" rescue RuntimeError nil end + def remembered_negative_flag_deprecation(name) + positive_name = name.gsub(/\Ano-/, "") + option = current_command.options[positive_name] + flag_name = "--no-" + option.switch_name.gsub(/\A--/, "") + + flag_deprecation(positive_name, flag_name, option) + end + def remembered_flag_deprecation(name) option = current_command.options[name] flag_name = option.switch_name - name_index = ARGV.find {|arg| flag_name == arg } + flag_deprecation(name, flag_name, option) + end + + def flag_deprecation(name, flag_name, option) + name_index = ARGV.find {|arg| flag_name == arg.split("=")[0] } return unless name_index value = options[name] value = value.join(" ").to_s if option.type == :array - Bundler::SharedHelpers.major_deprecation 2,\ + Bundler::SharedHelpers.major_deprecation 2, "The `#{flag_name}` flag is deprecated because it relies on being " \ "remembered across bundler invocations, which bundler will no longer " \ - "do in future versions. Instead please use `bundle config set #{name} " \ + "do in future versions. Instead please use `bundle config set --local #{name.tr("-", "_")} " \ "'#{value}'`, and stop using this flag" end end diff --git a/ruby/lib/bundler/cli/add.rb b/ruby/lib/bundler/cli/add.rb index 07b951f1e..5bcf30d82 100644 --- a/ruby/lib/bundler/cli/add.rb +++ b/ruby/lib/bundler/cli/add.rb @@ -17,7 +17,7 @@ def run perform_bundle_install unless options["skip-install"] end - private + private def perform_bundle_install Installer.install(Bundler.root, Bundler.definition) diff --git a/ruby/lib/bundler/cli/binstubs.rb b/ruby/lib/bundler/cli/binstubs.rb index 266396eed..639c01ff3 100644 --- a/ruby/lib/bundler/cli/binstubs.rb +++ b/ruby/lib/bundler/cli/binstubs.rb @@ -16,7 +16,11 @@ def run Bundler.settings.set_command_option_if_given :shebang, options["shebang"] installer = Installer.new(Bundler.root, Bundler.definition) - installer_opts = { :force => options[:force], :binstubs_cmd => true } + installer_opts = { + :force => options[:force], + :binstubs_cmd => true, + :all_platforms => options["all-platforms"], + } if options[:all] raise InvalidOption, "Cannot specify --all with specific gems" unless gems.empty? @@ -38,7 +42,7 @@ def run if options[:standalone] next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler" Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do - installer.generate_standalone_bundler_executable_stubs(spec) + installer.generate_standalone_bundler_executable_stubs(spec, installer_opts) end else installer.generate_bundler_executable_stubs(spec, installer_opts) diff --git a/ruby/lib/bundler/cli/cache.rb b/ruby/lib/bundler/cli/cache.rb index 5e8420990..c8698ed7e 100644 --- a/ruby/lib/bundler/cli/cache.rb +++ b/ruby/lib/bundler/cli/cache.rb @@ -9,7 +9,7 @@ def initialize(options) end def run - Bundler.ui.level = "error" if options[:quiet] + Bundler.ui.level = "warn" if options[:quiet] Bundler.settings.set_command_option_if_given :path, options[:path] Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"] @@ -24,12 +24,13 @@ def run end end - private + private def install require_relative "install" options = self.options.dup options["local"] = false if Bundler.settings[:cache_all_platforms] + options["no-cache"] = true Bundler::CLI::Install.new(options).run end @@ -37,12 +38,6 @@ def setup_cache_all all = options.fetch(:all, Bundler.feature_flag.cache_all? || nil) Bundler.settings.set_command_option_if_given :cache_all, all - - if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all? - Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ - "to cache them as well, please pass the --all flag. This will be the default " \ - "on Bundler 3.0." - end end end end diff --git a/ruby/lib/bundler/cli/check.rb b/ruby/lib/bundler/cli/check.rb index 19c0aaea0..65c51337d 100644 --- a/ruby/lib/bundler/cli/check.rb +++ b/ruby/lib/bundler/cli/check.rb @@ -11,9 +11,11 @@ def initialize(options) def run Bundler.settings.set_command_option_if_given :path, options[:path] + definition = Bundler.definition + definition.validate_runtime! + begin - definition = Bundler.definition - definition.validate_runtime! + definition.resolve_only_locally! not_installed = definition.missing_specs rescue GemNotFound, VersionConflict Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies." diff --git a/ruby/lib/bundler/cli/clean.rb b/ruby/lib/bundler/cli/clean.rb index 4a407fbae..c6b0968e3 100644 --- a/ruby/lib/bundler/cli/clean.rb +++ b/ruby/lib/bundler/cli/clean.rb @@ -13,7 +13,7 @@ def run Bundler.load.clean(options[:"dry-run"]) end - protected + protected def require_path_or_force return unless Bundler.use_system_gems? && !options[:force] diff --git a/ruby/lib/bundler/cli/common.rb b/ruby/lib/bundler/cli/common.rb index cec7bcadb..ba259143b 100644 --- a/ruby/lib/bundler/cli/common.rb +++ b/ruby/lib/bundler/cli/common.rb @@ -14,6 +14,20 @@ def self.print_post_install_message(name, msg) Bundler.ui.info msg end + def self.output_fund_metadata_summary + definition = Bundler.definition + current_dependencies = definition.requested_dependencies + current_specs = definition.specs + + count = current_dependencies.count {|dep| current_specs[dep.name].first.metadata.key?("funding_uri") } + + return if count.zero? + + intro = count > 1 ? "#{count} installed gems you directly depend on are" : "#{count} installed gem you directly depend on is" + message = "#{intro} looking for funding.\n Run `bundle fund` for details" + Bundler.ui.info message + end + def self.output_without_groups_message(command) return if Bundler.settings[:without].empty? Bundler.ui.confirm without_groups_message(command) @@ -22,10 +36,15 @@ def self.output_without_groups_message(command) def self.without_groups_message(command) command_in_past_tense = command == :install ? "installed" : "updated" groups = Bundler.settings[:without] + "Gems in the #{verbalize_groups(groups)} were not #{command_in_past_tense}." + end + + def self.verbalize_groups(groups) + groups.map!{|g| "'#{g}'" } group_list = [groups[0...-1].join(", "), groups[-1..-1]]. reject {|s| s.to_s.empty? }.join(" and ") group_str = groups.size == 1 ? "group" : "groups" - "Gems in the #{group_str} #{group_list} were not #{command_in_past_tense}." + "#{group_str} #{group_list}" end def self.select_spec(name, regex_match = nil) @@ -39,7 +58,13 @@ def self.select_spec(name, regex_match = nil) case specs.count when 0 - raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) + dep_in_other_group = Bundler.definition.current_dependencies.find {|dep|dep.name == name } + + if dep_in_other_group + raise GemNotFound, "Could not find gem '#{name}', because it's in the #{verbalize_groups(dep_in_other_group.groups)}, configured to be ignored." + else + raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) + end when 1 specs.first else @@ -69,6 +94,8 @@ def self.gem_not_found_message(missing_gem_name, alternatives) end def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems) + return unless locked_gems + locked_names = locked_gems.specs.map(&:name).uniq names.-(locked_names).each do |g| raise GemNotFound, gem_not_found_message(g, locked_names) diff --git a/ruby/lib/bundler/cli/config.rb b/ruby/lib/bundler/cli/config.rb index 8d2aba091..e1222c75d 100644 --- a/ruby/lib/bundler/cli/config.rb +++ b/ruby/lib/bundler/cli/config.rb @@ -180,7 +180,7 @@ def validate_scope! scopes = %w[global local].select {|s| options[s] } case scopes.size when 0 - @scope = "global" + @scope = inside_app? ? "local" : "global" @explicit_scope = false when 1 @scope = scopes.first @@ -189,6 +189,15 @@ def validate_scope! "The options #{scopes.join " and "} were specified. Please only use one of the switches at a time." end end + + private + + def inside_app? + Bundler.root + true + rescue GemfileNotFound + false + end end end end diff --git a/ruby/lib/bundler/cli/console.rb b/ruby/lib/bundler/cli/console.rb index 6e0dfe28a..97b8dc066 100644 --- a/ruby/lib/bundler/cli/console.rb +++ b/ruby/lib/bundler/cli/console.rb @@ -12,7 +12,7 @@ def run Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \ "by `bin/console` generated by `bundle gem `" - group ? Bundler.require(:default, *group.split.map!(&:to_sym)) : Bundler.require + group ? Bundler.require(:default, *group.split(" ").map!(&:to_sym)) : Bundler.require ARGV.clear console = get_console(Bundler.settings[:console] || "irb") diff --git a/ruby/lib/bundler/cli/doctor.rb b/ruby/lib/bundler/cli/doctor.rb index fcf139ed1..74444ad0c 100644 --- a/ruby/lib/bundler/cli/doctor.rb +++ b/ruby/lib/bundler/cli/doctor.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require "rbconfig" +require "shellwords" +require "fiddle" module Bundler class CLI::Doctor @@ -22,14 +24,14 @@ def ldd_available? end def dylibs_darwin(path) - output = `/usr/bin/otool -L "#{path}"`.chomp + output = `/usr/bin/otool -L #{path.shellescape}`.chomp dylibs = output.split("\n")[1..-1].map {|l| l.match(DARWIN_REGEX).captures[0] }.uniq # ignore @rpath and friends dylibs.reject {|dylib| dylib.start_with? "@" } end def dylibs_ldd(path) - output = `/usr/bin/ldd "#{path}"`.chomp + output = `/usr/bin/ldd #{path.shellescape}`.chomp output.split("\n").map do |l| match = l.match(LDD_REGEX) next if match.nil? @@ -61,7 +63,7 @@ def check! end def run - Bundler.ui.level = "error" if options[:quiet] + Bundler.ui.level = "warn" if options[:quiet] Bundler.settings.validate! check! @@ -70,7 +72,14 @@ def run definition.specs.each do |spec| bundles_for_gem(spec).each do |bundle| - bad_paths = dylibs(bundle).select {|f| !File.exist?(f) } + bad_paths = dylibs(bundle).select do |f| + begin + Fiddle.dlopen(f) + false + rescue Fiddle::DLError + true + end + end if bad_paths.any? broken_links[spec] ||= [] broken_links[spec].concat(bad_paths) @@ -93,15 +102,18 @@ def run end end - private + private def check_home_permissions require "find" files_not_readable_or_writable = [] files_not_rw_and_owned_by_different_user = [] files_not_owned_by_current_user_but_still_rw = [] + broken_symlinks = [] Find.find(Bundler.bundle_path.to_s).each do |f| - if !File.writable?(f) || !File.readable?(f) + if !File.exist?(f) + broken_symlinks << f + elsif !File.writable?(f) || !File.readable?(f) if File.stat(f).uid != Process.uid files_not_rw_and_owned_by_different_user << f else @@ -113,6 +125,13 @@ def check_home_permissions end ok = true + + if broken_symlinks.any? + Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}" + + ok = false + end + if files_not_owned_by_current_user_but_still_rw.any? Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \ "user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}" diff --git a/ruby/lib/bundler/cli/exec.rb b/ruby/lib/bundler/cli/exec.rb index 0a1edbdbb..42b602a05 100644 --- a/ruby/lib/bundler/cli/exec.rb +++ b/ruby/lib/bundler/cli/exec.rb @@ -12,12 +12,7 @@ def initialize(options, args) @options = options @cmd = args.shift @args = args - - if !Bundler.current_ruby.jruby? - @args << { :close_others => !options.keep_file_descriptors? } - elsif options.keep_file_descriptors? - Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec." - end + @args << { :close_others => !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby? end def run @@ -34,7 +29,7 @@ def run end end - private + private def validate_cmd! return unless cmd.nil? @@ -63,10 +58,10 @@ def kernel_load(file, *args) Kernel.load(file) rescue SystemExit, SignalException raise - rescue Exception => e # rubocop:disable Lint/RescueException + rescue Exception # rubocop:disable Lint/RescueException Bundler.ui.error "bundler: failed to load command: #{cmd} (#{file})" - backtrace = e.backtrace ? e.backtrace.take_while {|bt| !bt.start_with?(__FILE__) } : [] - abort "#{e.class}: #{e.message}\n #{backtrace.join("\n ")}" + Bundler::FriendlyErrors.disable! + raise end def process_title(file, args) diff --git a/ruby/lib/bundler/cli/fund.rb b/ruby/lib/bundler/cli/fund.rb new file mode 100644 index 000000000..52db5aef6 --- /dev/null +++ b/ruby/lib/bundler/cli/fund.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Bundler + class CLI::Fund + attr_reader :options + + def initialize(options) + @options = options + end + + def run + Bundler.definition.validate_runtime! + + groups = Array(options[:group]).map(&:to_sym) + + deps = if groups.any? + Bundler.definition.dependencies_for(groups) + else + Bundler.definition.current_dependencies + end + + fund_info = deps.each_with_object([]) do |dep, arr| + spec = Bundler.definition.specs[dep.name].first + if spec.metadata.key?("funding_uri") + arr << "* #{spec.name} (#{spec.version})\n Funding: #{spec.metadata["funding_uri"]}" + end + end + + if fund_info.empty? + Bundler.ui.info "None of the installed gems you directly depend on are looking for funding." + else + Bundler.ui.info fund_info.join("\n") + end + end + end +end diff --git a/ruby/lib/bundler/cli/gem.rb b/ruby/lib/bundler/cli/gem.rb index d3e583175..c4c76d1b6 100644 --- a/ruby/lib/bundler/cli/gem.rb +++ b/ruby/lib/bundler/cli/gem.rb @@ -12,6 +12,7 @@ class CLI::Gem TEST_FRAMEWORK_VERSIONS = { "rspec" => "3.0", "minitest" => "5.0", + "test-unit" => "3.0", }.freeze attr_reader :options, :gem_name, :thor, :name, :target @@ -37,12 +38,21 @@ def run namespaced_path = name.tr("-", "/") constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase } constant_array = constant_name.split("::") + minitest_constant_name = constant_array.clone.tap {|a| a[-1] = "Test#{a[-1]}" }.join("::") # Foo::Bar => Foo::TestBar - git_installed = Bundler.git_present? + use_git = Bundler.git_present? && options[:git] - git_author_name = git_installed ? `git config user.name`.chomp : "" - github_username = git_installed ? `git config github.user`.chomp : "" - git_user_email = git_installed ? `git config user.email`.chomp : "" + git_author_name = use_git ? `git config user.name`.chomp : "" + git_username = use_git ? `git config github.user`.chomp : "" + git_user_email = use_git ? `git config user.email`.chomp : "" + + github_username = if options[:github_username].nil? + git_username + elsif options[:github_username] == false + "" + else + options[:github_username] + end config = { :name => name, @@ -57,14 +67,18 @@ def run :ext => options[:ext], :exe => options[:exe], :bundler_version => bundler_dependency_version, + :git => use_git, :github_username => github_username.empty? ? "[USERNAME]" : github_username, + :required_ruby_version => required_ruby_version, + :minitest_constant_name => minitest_constant_name, } ensure_safe_gem_name(name, constant_array) templates = { - "Gemfile.tt" => "Gemfile", + "#{Bundler.preferred_gemfile_name}.tt" => Bundler.preferred_gemfile_name, "lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb", "lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb", + "sig/newgem.rbs.tt" => "sig/#{namespaced_path}.rbs", "newgem.gemspec.tt" => "#{name}.gemspec", "Rakefile.tt" => "Rakefile", "README.md.tt" => "README.md", @@ -77,14 +91,12 @@ def run bin/setup ] - templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present? + templates.merge!("gitignore.tt" => ".gitignore") if use_git if test_framework = ask_and_set_test_framework config[:test] = test_framework config[:test_framework_version] = TEST_FRAMEWORK_VERSIONS[test_framework] - templates.merge!("travis.yml.tt" => ".travis.yml") - case test_framework when "rspec" templates.merge!( @@ -92,15 +104,41 @@ def run "spec/spec_helper.rb.tt" => "spec/spec_helper.rb", "spec/newgem_spec.rb.tt" => "spec/#{namespaced_path}_spec.rb" ) + config[:test_task] = :spec when "minitest" + # Generate path for minitest target file (FileList["test/**/test_*.rb"]) + # foo => test/test_foo.rb + # foo-bar => test/foo/test_bar.rb + # foo_bar => test/test_foo_bar.rb + paths = namespaced_path.rpartition("/") + paths[2] = "test_#{paths[2]}" + minitest_namespaced_path = paths.join("") + + templates.merge!( + "test/minitest/test_helper.rb.tt" => "test/test_helper.rb", + "test/minitest/test_newgem.rb.tt" => "test/#{minitest_namespaced_path}.rb" + ) + config[:test_task] = :test + when "test-unit" templates.merge!( - "test/test_helper.rb.tt" => "test/test_helper.rb", - "test/newgem_test.rb.tt" => "test/#{namespaced_path}_test.rb" + "test/test-unit/test_helper.rb.tt" => "test/test_helper.rb", + "test/test-unit/newgem_test.rb.tt" => "test/#{namespaced_path}_test.rb" ) + config[:test_task] = :test end end - config[:test_task] = config[:test] == "minitest" ? "test" : "spec" + config[:ci] = ask_and_set_ci + case config[:ci] + when "github" + templates.merge!("github/workflows/main.yml.tt" => ".github/workflows/main.yml") + when "travis" + templates.merge!("travis.yml.tt" => ".travis.yml") + when "gitlab" + templates.merge!("gitlab-ci.yml.tt" => ".gitlab-ci.yml") + when "circle" + templates.merge!("circleci/config.yml.tt" => ".circleci/config.yml") + end if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?", "This means that any other developer or company will be legally allowed to use your code " \ @@ -124,6 +162,30 @@ def run templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md") end + if ask_and_set(:changelog, "Do you want to include a changelog?", + "A changelog is a file which contains a curated, chronologically ordered list of notable " \ + "changes for each version of a project. To make it easier for users and contributors to" \ + " see precisely what notable changes have been made between each release (or version) of" \ + " the project. Whether consumers or developers, the end users of software are" \ + " human beings who care about what's in the software. When the software changes, people " \ + "want to know why and how. see https://keepachangelog.com") + config[:changelog] = true + Bundler.ui.info "Changelog enabled in config" + templates.merge!("CHANGELOG.md.tt" => "CHANGELOG.md") + end + + config[:linter] = ask_and_set_linter + case config[:linter] + when "rubocop" + config[:linter_version] = rubocop_version + Bundler.ui.info "RuboCop enabled in config" + templates.merge!("rubocop.yml.tt" => ".rubocop.yml") + when "standard" + config[:linter_version] = standard_version + Bundler.ui.info "Standard enabled in config" + templates.merge!("standard.yml.tt" => ".standard.yml") + end + templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe] if options[:ext] @@ -134,24 +196,32 @@ def run ) end + if target.exist? && !target.directory? + Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`." + exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError] + end + + if use_git + Bundler.ui.info "Initializing git repo in #{target}" + require "shellwords" + `git init #{target.to_s.shellescape}` + + config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp + end + templates.each do |src, dst| destination = target.join(dst) - SharedHelpers.filesystem_access(destination) do - thor.template("newgem/#{src}", destination, config) - end + thor.template("newgem/#{src}", destination, config) end executables.each do |file| - SharedHelpers.filesystem_access(target.join(file)) do |path| - executable = (path.stat.mode | 0o111) - path.chmod(executable) - end + path = target.join(file) + executable = (path.stat.mode | 0o111) + path.chmod(executable) end - if Bundler.git_present? && options[:git] - Bundler.ui.info "Initializing git repo in #{target}" + if use_git Dir.chdir(target) do - `git init` `git add .` end end @@ -161,11 +231,9 @@ def run Bundler.ui.info "Gem '#{name}' was successfully created. " \ "For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html" - rescue Errno::EEXIST => e - raise GenericSystemCallError.new(e, "There was a conflict while creating the new gem.") end - private + private def resolve_name(name) SharedHelpers.pwd.join(name).basename.to_s @@ -197,11 +265,12 @@ def validate_ext_name def ask_and_set_test_framework test_framework = options[:test] || Bundler.settings["gem.test"] - if test_framework.nil? + if test_framework.to_s.empty? Bundler.ui.confirm "Do you want to generate tests with your gem?" - result = Bundler.ui.ask "Type 'rspec' or 'minitest' to generate those test files now and " \ - "in the future. rspec/minitest/(none):" - if result =~ /rspec|minitest/ + Bundler.ui.info hint_text("test") + + result = Bundler.ui.ask "Enter a test framework. rspec/minitest/test-unit/(none):" + if result =~ /rspec|minitest|test-unit/ test_framework = result else test_framework = false @@ -212,9 +281,106 @@ def ask_and_set_test_framework Bundler.settings.set_global("gem.test", test_framework) end + if options[:test] == Bundler.settings["gem.test"] + Bundler.ui.info "#{options[:test]} is already configured, ignoring --test flag." + end + test_framework end + def hint_text(setting) + if Bundler.settings["gem.#{setting}"] == false + "Your choice will only be applied to this gem." + else + "Future `bundle gem` calls will use your choice. " \ + "This setting can be changed anytime with `bundle config gem.#{setting}`." + end + end + + def ask_and_set_ci + ci_template = options[:ci] || Bundler.settings["gem.ci"] + + if ci_template.to_s.empty? + Bundler.ui.confirm "Do you want to set up continuous integration for your gem? " \ + "Supported services:\n" \ + "* CircleCI: https://circleci.com/\n" \ + "* GitHub Actions: https://github.com/features/actions\n" \ + "* GitLab CI: https://docs.gitlab.com/ee/ci/\n" \ + "* Travis CI: https://travis-ci.org/\n" \ + "\n" + Bundler.ui.info hint_text("ci") + + result = Bundler.ui.ask "Enter a CI service. github/travis/gitlab/circle/(none):" + if result =~ /github|travis|gitlab|circle/ + ci_template = result + else + ci_template = false + end + end + + if Bundler.settings["gem.ci"].nil? + Bundler.settings.set_global("gem.ci", ci_template) + end + + if options[:ci] == Bundler.settings["gem.ci"] + Bundler.ui.info "#{options[:ci]} is already configured, ignoring --ci flag." + end + + ci_template + end + + def ask_and_set_linter + linter_template = options[:linter] || Bundler.settings["gem.linter"] + linter_template = deprecated_rubocop_option if linter_template.nil? + + if linter_template.to_s.empty? + Bundler.ui.confirm "Do you want to add a code linter and formatter to your gem? " \ + "Supported Linters:\n" \ + "* RuboCop: https://rubocop.org\n" \ + "* Standard: https://github.com/testdouble/standard\n" \ + "\n" + Bundler.ui.info hint_text("linter") + + result = Bundler.ui.ask "Enter a linter. rubocop/standard/(none):" + if result =~ /rubocop|standard/ + linter_template = result + else + linter_template = false + end + end + + if Bundler.settings["gem.linter"].nil? + Bundler.settings.set_global("gem.linter", linter_template) + end + + # Once gem.linter safely set, unset the deprecated gem.rubocop + unless Bundler.settings["gem.rubocop"].nil? + Bundler.settings.set_global("gem.rubocop", nil) + end + + if options[:linter] == Bundler.settings["gem.linter"] + Bundler.ui.info "#{options[:linter]} is already configured, ignoring --linter flag." + end + + linter_template + end + + def deprecated_rubocop_option + if !options[:rubocop].nil? + if options[:rubocop] + Bundler::SharedHelpers.major_deprecation 2, "--rubocop is deprecated, use --linter=rubocop" + "rubocop" + else + Bundler::SharedHelpers.major_deprecation 2, "--no-rubocop is deprecated, use --linter" + false + end + elsif !Bundler.settings["gem.rubocop"].nil? + Bundler::SharedHelpers.major_deprecation 2, + "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead" + Bundler.settings["gem.rubocop"] ? "rubocop" : false + end + end + def bundler_dependency_version v = Gem::Version.new(Bundler::VERSION) req = v.segments[0..1] @@ -248,5 +414,30 @@ def ensure_safe_gem_name(name, constant_array) def open_editor(editor, file) thor.run(%(#{editor} "#{file}")) end + + def required_ruby_version + if Gem.ruby_version < Gem::Version.new("2.4.a") then "2.3.0" + elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "2.4.0" + elsif Gem.ruby_version < Gem::Version.new("2.6.a") then "2.5.0" + else + "2.6.0" + end + end + + def rubocop_version + if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.81.0" + elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.12" + else + "1.21" + end + end + + def standard_version + if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.2.5" + elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.0" + else + "1.3" + end + end end end diff --git a/ruby/lib/bundler/cli/info.rb b/ruby/lib/bundler/cli/info.rb index 4733675e8..38bc008cb 100644 --- a/ruby/lib/bundler/cli/info.rb +++ b/ruby/lib/bundler/cli/info.rb @@ -18,11 +18,12 @@ def run if spec return print_gem_path(spec) if @options[:path] + return print_gem_version(spec) if @options[:version] print_gem_info(spec) end end - private + private def spec_for_gem(gem_name) spec = Bundler.definition.specs.find {|s| s.name == gem_name } @@ -39,24 +40,55 @@ def spec_not_found(gem_name) raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies) end + def print_gem_version(spec) + Bundler.ui.info spec.version.to_s + end + def print_gem_path(spec) - path = if spec.name == "bundler" - File.expand_path("../../../..", __FILE__) + name = spec.name + if name == "bundler" + path = File.expand_path("../../../..", __FILE__) else - spec.full_gem_path + path = spec.full_gem_path + if spec.deleted_gem? + return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}" + end end Bundler.ui.info path end def print_gem_info(spec) + metadata = spec.metadata + name = spec.name gem_info = String.new - gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n" + gem_info << " * #{name} (#{spec.version}#{spec.git_version})\n" gem_info << "\tSummary: #{spec.summary}\n" if spec.summary gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage + gem_info << "\tDocumentation: #{metadata["documentation_uri"]}\n" if metadata.key?("documentation_uri") + gem_info << "\tSource Code: #{metadata["source_code_uri"]}\n" if metadata.key?("source_code_uri") + gem_info << "\tFunding: #{metadata["funding_uri"]}\n" if metadata.key?("funding_uri") + gem_info << "\tWiki: #{metadata["wiki_uri"]}\n" if metadata.key?("wiki_uri") + gem_info << "\tChangelog: #{metadata["changelog_uri"]}\n" if metadata.key?("changelog_uri") + gem_info << "\tBug Tracker: #{metadata["bug_tracker_uri"]}\n" if metadata.key?("bug_tracker_uri") + gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri") gem_info << "\tPath: #{spec.full_gem_path}\n" - gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem? + gem_info << "\tDefault Gem: yes\n" if spec.respond_to?(:default_gem?) && spec.default_gem? + gem_info << "\tReverse Dependencies: \n\t\t#{gem_dependencies.join("\n\t\t")}" if gem_dependencies.any? + + if name != "bundler" && spec.deleted_gem? + return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}" + end + Bundler.ui.info gem_info end + + def gem_dependencies + @gem_dependencies ||= Bundler.definition.specs.map do |spec| + dependency = spec.dependencies.find {|dep| dep.name == gem_name } + next unless dependency + "#{spec.name} (#{spec.version}) depends on #{gem_name} (#{dependency.requirements_list.join(", ")})" + end.compact.sort + end end end diff --git a/ruby/lib/bundler/cli/init.rb b/ruby/lib/bundler/cli/init.rb index 65dd08dfe..d851d02d4 100644 --- a/ruby/lib/bundler/cli/init.rb +++ b/ruby/lib/bundler/cli/init.rb @@ -38,10 +38,10 @@ def run puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}" end - private + private def gemfile - @gemfile ||= Bundler.settings[:init_gems_rb] ? "gems.rb" : "Gemfile" + @gemfile ||= Bundler.preferred_gemfile_name end end end diff --git a/ruby/lib/bundler/cli/inject.rb b/ruby/lib/bundler/cli/inject.rb index b00675d34..8093a8528 100644 --- a/ruby/lib/bundler/cli/inject.rb +++ b/ruby/lib/bundler/cli/inject.rb @@ -44,7 +44,7 @@ def run end end - private + private def last_version_number definition = Bundler.definition(true) diff --git a/ruby/lib/bundler/cli/install.rb b/ruby/lib/bundler/cli/install.rb index ecd474971..e9b85f7f6 100644 --- a/ruby/lib/bundler/cli/install.rb +++ b/ruby/lib/bundler/cli/install.rb @@ -8,11 +8,11 @@ def initialize(options) end def run - Bundler.ui.level = "error" if options[:quiet] + Bundler.ui.level = "warn" if options[:quiet] warn_if_root - normalize_groups + Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD @@ -35,12 +35,8 @@ def run options[:local] = true if Bundler.app_cache.exist? - if Bundler.feature_flag.deployment_means_frozen? - Bundler.settings.set_command_option :deployment, true - else - Bundler.settings.set_command_option :deployment, true if options[:deployment] - Bundler.settings.set_command_option :frozen, true if options[:frozen] - end + Bundler.settings.set_command_option :deployment, true if options[:deployment] + Bundler.settings.set_command_option :frozen, true if options[:frozen] end # When install is called with --no-deployment, disable deployment mode @@ -55,7 +51,7 @@ def run if options["binstubs"] Bundler::SharedHelpers.major_deprecation 2, - "The --binstubs option will be removed in favor of `bundle binstubs`" + "The --binstubs option will be removed in favor of `bundle binstubs --all`" end Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins? @@ -64,7 +60,10 @@ def run definition.validate_runtime! installer = Installer.install(Bundler.root, definition, options) - Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle? + + Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do + Bundler.load.cache(nil, options[:local]) if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle? + end Bundler.ui.confirm "Bundle complete! #{dependencies_count_for(definition)}, #{gems_installed_for(definition)}." Bundler::CLI::Common.output_without_groups_message(:install) @@ -84,28 +83,17 @@ def run require_relative "clean" Bundler::CLI::Clean.new(options).run end - rescue GemNotFound, VersionConflict => e - if options[:local] && Bundler.app_cache.exist? - Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory." - end - unless Bundler.definition.has_rubygems_remotes? - Bundler.ui.warn <<-WARN, :wrap => true - Your Gemfile has no gem server sources. If you need gems that are \ - not already on your machine, add a line like this to your Gemfile: - source 'https://rubygems.org' - WARN - end - raise e - rescue Gem::InvalidSpecificationException => e + Bundler::CLI::Common.output_fund_metadata_summary + rescue Gem::InvalidSpecificationException Bundler.ui.warn "You have one or more invalid gemspecs that need to be fixed." - raise e + raise end - private + private def warn_if_root - return if Bundler.settings[:silence_root_warning] || Bundler::WINDOWS || !Process.uid.zero? + return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero? Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \ "if it is needed, and installing your bundle as root will break this " \ "application for all non-root users on this machine.", :wrap => true @@ -147,31 +135,17 @@ def check_trust_policy end def normalize_groups - options[:with] &&= options[:with].join(":").tr(" ", ":").split(":") - options[:without] &&= options[:without].join(":").tr(" ", ":").split(":") - check_for_group_conflicts_in_cli_options - Bundler.settings.set_command_option :with, nil if options[:with] == [] - Bundler.settings.set_command_option :without, nil if options[:without] == [] - - with = options.fetch(:with, []) - with |= Bundler.settings[:with].map(&:to_s) - with -= options[:without] if options[:without] - - without = options.fetch(:without, []) - without |= Bundler.settings[:without].map(&:to_s) - without -= options[:with] if options[:with] - - options[:with] = with - options[:without] = without + # need to nil them out first to get around validation for backwards compatibility + Bundler.settings.set_command_option :without, nil + Bundler.settings.set_command_option :with, nil + Bundler.settings.set_command_option :without, options[:without] + Bundler.settings.set_command_option :with, options[:with] end def normalize_settings Bundler.settings.set_command_option :path, nil if options[:system] - Bundler.settings.temporary(:path_relative_to_cwd => false) do - Bundler.settings.set_command_option :path, "vendor/bundle" if Bundler.settings[:deployment] && Bundler.settings[:path].nil? - end Bundler.settings.set_command_option_if_given :path, options[:path] Bundler.settings.temporary(:path_relative_to_cwd => false) do Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil? @@ -191,13 +165,7 @@ def normalize_settings Bundler.settings.set_command_option_if_given :clean, options["clean"] - unless Bundler.settings[:without] == options[:without] && Bundler.settings[:with] == options[:with] - # need to nil them out first to get around validation for backwards compatibility - Bundler.settings.set_command_option :without, nil - Bundler.settings.set_command_option :with, nil - Bundler.settings.set_command_option :without, options[:without] - options[:with] - Bundler.settings.set_command_option :with, options[:with] - end + normalize_groups if options[:without] || options[:with] options[:force] = options[:redownload] end diff --git a/ruby/lib/bundler/cli/issue.rb b/ruby/lib/bundler/cli/issue.rb index 054ce7631..b891ecb1d 100644 --- a/ruby/lib/bundler/cli/issue.rb +++ b/ruby/lib/bundler/cli/issue.rb @@ -10,7 +10,7 @@ def run be sure to check out these resources: 1. Check out our troubleshooting guide for quick fixes to common issues: - https://github.com/bundler/bundler/blob/master/doc/TROUBLESHOOTING.md + https://github.com/rubygems/rubygems/blob/master/bundler/doc/TROUBLESHOOTING.md 2. Instructions for common Bundler uses can be found on the documentation site: https://bundler.io/ @@ -20,9 +20,10 @@ def run Hopefully the troubleshooting steps above resolved your problem! If things still aren't working the way you expect them to, please let us know so - that we can diagnose and help fix the problem you're having. Please - view the Filing Issues guide for more information: - https://github.com/bundler/bundler/blob/master/doc/contributing/ISSUES.md + that we can diagnose and help fix the problem you're having, by filling + in the new issue form located at + https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md, + and copy and pasting the information below. EOS diff --git a/ruby/lib/bundler/cli/list.rb b/ruby/lib/bundler/cli/list.rb index d1799196e..f56bf5b86 100644 --- a/ruby/lib/bundler/cli/list.rb +++ b/ruby/lib/bundler/cli/list.rb @@ -4,17 +4,25 @@ module Bundler class CLI::List def initialize(options) @options = options + @without_group = options["without-group"].map(&:to_sym) + @only_group = options["only-group"].map(&:to_sym) end def run - raise InvalidOption, "The `--only-group` and `--without-group` options cannot be used together" if @options["only-group"] && @options["without-group"] + raise InvalidOption, "The `--only-group` and `--without-group` options cannot be used together" if @only_group.any? && @without_group.any? raise InvalidOption, "The `--name-only` and `--paths` options cannot be used together" if @options["name-only"] && @options[:paths] - specs = if @options["only-group"] || @options["without-group"] + specs = if @only_group.any? || @without_group.any? filtered_specs_by_groups else - Bundler.load.specs + begin + Bundler.load.specs + rescue GemNotFound => e + Bundler.ui.error e.message + Bundler.ui.warn "Install missing gems with `bundle install`." + exit 1 + end end.reject {|s| s.name == "bundler" }.sort_by(&:name) return Bundler.ui.info "No gems in the Gemfile" if specs.empty? @@ -29,12 +37,12 @@ def run Bundler.ui.info "Use `bundle info` to print more detailed information about a gem" end - private + private def verify_group_exists(groups) - raise InvalidOption, "`#{@options["without-group"]}` group could not be found." if @options["without-group"] && !groups.include?(@options["without-group"].to_sym) - - raise InvalidOption, "`#{@options["only-group"]}` group could not be found." if @options["only-group"] && !groups.include?(@options["only-group"].to_sym) + (@without_group + @only_group).each do |group| + raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group) + end end def filtered_specs_by_groups @@ -44,10 +52,10 @@ def filtered_specs_by_groups verify_group_exists(groups) show_groups = - if @options["without-group"] - groups.reject {|g| g == @options["without-group"].to_sym } - elsif @options["only-group"] - groups.select {|g| g == @options["only-group"].to_sym } + if @without_group.any? + groups.reject {|g| @without_group.include?(g) } + elsif @only_group.any? + groups.select {|g| @only_group.include?(g) } else groups end.map(&:to_sym) diff --git a/ruby/lib/bundler/cli/lock.rb b/ruby/lib/bundler/cli/lock.rb index 7dd078b1e..7d613a664 100644 --- a/ruby/lib/bundler/cli/lock.rb +++ b/ruby/lib/bundler/cli/lock.rb @@ -21,9 +21,13 @@ def run Bundler::Fetcher.disable_endpoint = options["full-index"] update = options[:update] + conservative = options[:conservative] + if update.is_a?(Array) # unlocking specific gems Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update) - update = { :gems => update, :lock_shared_dependencies => options[:conservative] } + update = { :gems => update, :conservative => conservative } + elsif update + update = { :conservative => conservative } if conservative end definition = Bundler.definition(update) diff --git a/ruby/lib/bundler/cli/open.rb b/ruby/lib/bundler/cli/open.rb index df32e2f38..ea504344f 100644 --- a/ruby/lib/bundler/cli/open.rb +++ b/ruby/lib/bundler/cli/open.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "shellwords" - module Bundler class CLI::Open attr_reader :options, :name @@ -19,6 +17,7 @@ def run else path = spec.full_gem_path Dir.chdir(path) do + require "shellwords" command = Shellwords.split(editor) + [path] Bundler.with_original_env do system(*command) diff --git a/ruby/lib/bundler/cli/outdated.rb b/ruby/lib/bundler/cli/outdated.rb index 0b710e978..d5183b060 100644 --- a/ruby/lib/bundler/cli/outdated.rb +++ b/ruby/lib/bundler/cli/outdated.rb @@ -3,18 +3,16 @@ module Bundler class CLI::Outdated attr_reader :options, :gems, :options_include_groups, :filter_options_patch, :sources, :strict - attr_accessor :outdated_gems_by_groups, :outdated_gems_list + attr_accessor :outdated_gems def initialize(options, gems) @options = options @gems = gems @sources = Array(options[:source]) - @filter_options_patch = options.keys & - %w[filter-major filter-minor filter-patch] + @filter_options_patch = options.keys & %w[filter-major filter-minor filter-patch] - @outdated_gems_by_groups = {} - @outdated_gems_list = [] + @outdated_gems = [] @options_include_groups = [:group, :groups].any? do |v| options.keys.include?(v.to_s) @@ -22,8 +20,7 @@ def initialize(options, gems) # the patch level options imply strict is also true. It wouldn't make # sense otherwise. - @strict = options["filter-strict"] || - Bundler::CLI::Common.patch_level_options(options).any? + @strict = options["filter-strict"] || Bundler::CLI::Common.patch_level_options(options).any? end def run @@ -75,87 +72,67 @@ def run gemfile_specs + dependency_specs end - specs.sort_by(&:name).each do |current_spec| - next if !gems.empty? && !gems.include?(current_spec.name) + specs.sort_by(&:name).uniq(&:name).each do |current_spec| + next unless gems.empty? || gems.include?(current_spec.name) - dependency = current_dependencies[current_spec.name] active_spec = retrieve_active_spec(definition, current_spec) + next unless active_spec - next if active_spec.nil? - next if filter_options_patch.any? && - !update_present_via_semver_portions(current_spec, active_spec, options) + next unless filter_options_patch.empty? || update_present_via_semver_portions(current_spec, active_spec, options) gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version) next unless gem_outdated || (current_spec.git_version != active_spec.git_version) - groups = nil + + dependency = current_dependencies[current_spec.name] + groups = "" if dependency && !options[:parseable] groups = dependency.groups.join(", ") end - outdated_gems_list << { :active_spec => active_spec, - :current_spec => current_spec, - :dependency => dependency, - :groups => groups } - - outdated_gems_by_groups[groups] ||= [] - outdated_gems_by_groups[groups] << outdated_gems_list[-1] + outdated_gems << { + :active_spec => active_spec, + :current_spec => current_spec, + :dependency => dependency, + :groups => groups, + } end - if outdated_gems_list.empty? - display_nothing_outdated_message - else + if outdated_gems.empty? unless options[:parseable] - Bundler.ui.info(header_outdated_message) + Bundler.ui.info(nothing_outdated_message) end - + else if options_include_groups - ordered_groups = outdated_gems_by_groups.keys.compact.sort - ordered_groups.insert(0, nil).each do |groups| - gems = outdated_gems_by_groups[groups] - contains_group = if groups - groups.split(", ").include?(options[:group]) - else - options[:group] == "group" - end + relevant_outdated_gems = outdated_gems.group_by {|g| g[:groups] }.sort.flat_map do |groups, gems| + contains_group = groups.split(", ").include?(options[:group]) + next unless options[:groups] || contains_group - next if (!options[:groups] && !contains_group) || gems.nil? + gems + end.compact - unless options[:parseable] - Bundler.ui.info(header_group_message(groups)) + if options[:parseable] + relevant_outdated_gems.each do |gems| + print_gems(gems) end - - print_gems(gems) + else + print_gems_table(relevant_outdated_gems) end + elsif options[:parseable] + print_gems(outdated_gems) else - print_gems(outdated_gems_list) + print_gems_table(outdated_gems) end exit 1 end end - private + private def groups_text(group_text, groups) "#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\"" end - def header_outdated_message - if options[:pre] - "Outdated gems included in the bundle (including pre-releases):" - else - "Outdated gems included in the bundle:" - end - end - - def header_group_message(groups) - if groups - "===== #{groups_text("Group", groups)} =====" - else - "===== Without group =====" - end - end - def nothing_outdated_message if filter_options_patch.any? display = filter_options_patch.map do |o| @@ -169,23 +146,16 @@ def nothing_outdated_message end def retrieve_active_spec(definition, current_spec) - if strict - active_spec = definition.find_resolved_spec(current_spec) - else - active_specs = definition.find_indexed_specs(current_spec) - if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1 - active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? } - end - active_spec = active_specs.last - end + active_spec = definition.resolve.find_by_name_and_platform(current_spec.name, current_spec.platform) + return unless active_spec - active_spec - end + return active_spec if strict - def display_nothing_outdated_message - unless options[:parseable] - Bundler.ui.info(nothing_outdated_message) + active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version) + if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1 + active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? } end + active_specs.last end def print_gems(gems_list) @@ -199,6 +169,19 @@ def print_gems(gems_list) end end + def print_gems_table(gems_list) + data = gems_list.map do |gem| + gem_column_for( + gem[:current_spec], + gem[:active_spec], + gem[:dependency], + gem[:groups], + ) + end + + print_indented([table_header] + data) + end + def print_gem(current_spec, active_spec, dependency, groups) spec_version = "#{active_spec.version}#{active_spec.git_version}" spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from @@ -213,7 +196,7 @@ def print_gem(current_spec, active_spec, dependency, groups) output_message = if options[:parseable] spec_outdated_info.to_s - elsif options_include_groups || !groups + elsif options_include_groups || groups.empty? " * #{spec_outdated_info}" else " * #{spec_outdated_info} in #{groups_text("group", groups)}" @@ -222,14 +205,22 @@ def print_gem(current_spec, active_spec, dependency, groups) Bundler.ui.info output_message.rstrip end + def gem_column_for(current_spec, active_spec, dependency, groups) + current_version = "#{current_spec.version}#{current_spec.git_version}" + spec_version = "#{active_spec.version}#{active_spec.git_version}" + dependency = dependency.requirement if dependency + + ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s] + ret_val << active_spec.loaded_from.to_s if Bundler.ui.debug? + ret_val + end + def check_for_deployment_mode! return unless Bundler.frozen_bundle? - suggested_command = if Bundler.settings.locations("frozen")[:global] + suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any? "bundle config unset frozen" elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any? "bundle config unset deployment" - else - "bundle install --no-deployment" end raise ProductionError, "You are trying to check outdated gems in " \ "deployment mode. Run `bundle outdated` elsewhere.\n" \ @@ -266,5 +257,34 @@ def get_version_semver_portion_value(spec, version_portion_index) version_section = spec.version.segments[version_portion_index, 1] version_section.to_a[0].to_i end + + def print_indented(matrix) + header = matrix[0] + data = matrix[1..-1] + + column_sizes = Array.new(header.size) do |index| + matrix.max_by {|row| row[index].length }[index].length + end + + Bundler.ui.info justify(header, column_sizes) + + data.sort_by! {|row| row[0] } + + data.each do |row| + Bundler.ui.info justify(row, column_sizes) + end + end + + def table_header + header = ["Gem", "Current", "Latest", "Requested", "Groups"] + header << "Path" if Bundler.ui.debug? + header + end + + def justify(row, sizes) + row.each_with_index.map do |element, index| + element.ljust(sizes[index]) + end.join(" ").strip + "\n" + end end end diff --git a/ruby/lib/bundler/cli/package.rb b/ruby/lib/bundler/cli/package.rb deleted file mode 100644 index b31b67776..000000000 --- a/ruby/lib/bundler/cli/package.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -module Bundler - class CLI::Package - attr_reader :options - - def initialize(options) - @options = options - end - - def run - Bundler.ui.level = "error" if options[:quiet] - Bundler.settings.set_command_option_if_given :path, options[:path] - Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"] - - setup_cache_all - install - - # TODO: move cache contents here now that all bundles are locked - custom_path = Bundler.settings[:path] if options[:path] - - Bundler.settings.temporary(:cache_all_platforms => options["all-platforms"]) do - Bundler.load.cache(custom_path) - end - end - - private - - def install - require_relative "install" - options = self.options.dup - options["local"] = false if Bundler.settings[:cache_all_platforms] - Bundler::CLI::Install.new(options).run - end - - def setup_cache_all - all = options.fetch(:all, Bundler.feature_flag.cache_all? || nil) - - Bundler.settings.set_command_option_if_given :cache_all, all - - if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all? - Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \ - "to package them as well, please pass the --all flag. This will be the default " \ - "on Bundler 3.0." - end - end - end -end diff --git a/ruby/lib/bundler/cli/platform.rb b/ruby/lib/bundler/cli/platform.rb index e97cad49a..068c765aa 100644 --- a/ruby/lib/bundler/cli/platform.rb +++ b/ruby/lib/bundler/cli/platform.rb @@ -23,7 +23,7 @@ def run output << "No ruby version specified" end else - output << "Your platform is: #{RUBY_PLATFORM}" + output << "Your platform is: #{Gem::Platform.local}" output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}" if ruby_version diff --git a/ruby/lib/bundler/cli/plugin.rb b/ruby/lib/bundler/cli/plugin.rb index 1155c4ec9..fe3f4412f 100644 --- a/ruby/lib/bundler/cli/plugin.rb +++ b/ruby/lib/bundler/cli/plugin.rb @@ -23,6 +23,16 @@ def install(*plugins) Bundler::Plugin.install(plugins, options) end + desc "uninstall PLUGINS", "Uninstall the plugins" + long_desc <<-D + Uninstall given list of plugins. To uninstall all the plugins, use -all option. + D + method_option "all", :type => :boolean, :default => nil, :banner => + "Uninstall all the installed plugins. If no plugin is installed, then it does nothing." + def uninstall(*plugins) + Bundler::Plugin.uninstall(plugins, options) + end + desc "list", "List the installed plugins and available commands" def list Bundler::Plugin.list diff --git a/ruby/lib/bundler/cli/pristine.rb b/ruby/lib/bundler/cli/pristine.rb index 532b3e0b5..d6654f805 100644 --- a/ruby/lib/bundler/cli/pristine.rb +++ b/ruby/lib/bundler/cli/pristine.rb @@ -29,6 +29,11 @@ def run FileUtils.rm_rf spec.full_gem_path when Source::Git + if source.local? + Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.") + next + end + source.remote! if extension_cache_path = source.extension_cache_path(spec) FileUtils.rm_rf extension_cache_path diff --git a/ruby/lib/bundler/cli/remove.rb b/ruby/lib/bundler/cli/remove.rb index cd6a2cec2..44a4d891d 100644 --- a/ruby/lib/bundler/cli/remove.rb +++ b/ruby/lib/bundler/cli/remove.rb @@ -11,8 +11,7 @@ def run raise InvalidOption, "Please specify gems to remove." if @gems.empty? Injector.remove(@gems, {}) - - Installer.install(Bundler.root, Bundler.definition) if @options["install"] + Installer.install(Bundler.root, Bundler.definition) end end end diff --git a/ruby/lib/bundler/cli/show.rb b/ruby/lib/bundler/cli/show.rb index 3748c25b8..5eaaba1ef 100644 --- a/ruby/lib/bundler/cli/show.rb +++ b/ruby/lib/bundler/cli/show.rb @@ -53,7 +53,7 @@ def run end end - private + private def fetch_latest_specs definition = Bundler.definition(true) diff --git a/ruby/lib/bundler/cli/update.rb b/ruby/lib/bundler/cli/update.rb index 529dd9c94..b49182655 100644 --- a/ruby/lib/bundler/cli/update.rb +++ b/ruby/lib/bundler/cli/update.rb @@ -9,14 +9,18 @@ def initialize(options, gems) end def run - Bundler.ui.level = "error" if options[:quiet] + Bundler.ui.level = "warn" if options[:quiet] + + update_bundler = options[:bundler] + + Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler) if update_bundler Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins? sources = Array(options[:source]) groups = Array(options[:group]).map(&:to_sym) - full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !options[:bundler] + full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !update_bundler if full_update && !options[:all] if Bundler.feature_flag.update_requires_all_flag? @@ -27,9 +31,14 @@ def run raise InvalidOption, "Cannot specify --all along with specific options." end + conservative = options[:conservative] + if full_update - # We're doing a full update - Bundler.definition(true) + if conservative + Bundler.definition(:conservative => conservative) + else + Bundler.definition(true) + end else unless Bundler.default_lockfile.exist? raise GemfileLockNotFound, "This Bundle hasn't been installed yet. " \ @@ -43,8 +52,8 @@ def run end Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby], - :lock_shared_dependencies => options[:conservative], - :bundler => options[:bundler]) + :conservative => conservative, + :bundler => update_bundler) end Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options) @@ -61,7 +70,7 @@ def run if locked_gems = Bundler.definition.locked_gems previous_locked_info = locked_gems.specs.reduce({}) do |h, s| - h[s.name] = { :spec => s, :version => s.version, :source => s.source.to_s } + h[s.name] = { :spec => s, :version => s.version, :source => s.source.identifier } h end end @@ -82,7 +91,7 @@ def run locked_spec = locked_info[:spec] new_spec = Bundler.definition.specs[name].first unless new_spec - if Bundler.rubygems.platforms.none? {|p| locked_spec.match_platform(p) } + unless locked_spec.match_platform(Bundler.local_platform) Bundler.ui.warn "Bundler attempted to update #{name} but it was not considered because it is for a different platform from the current one" end @@ -90,7 +99,7 @@ def run end locked_source = locked_info[:source] - new_source = new_spec.source.to_s + new_source = new_spec.source.identifier next if locked_source != new_source new_version = new_spec.version @@ -106,6 +115,8 @@ def run Bundler.ui.confirm "Bundle updated!" Bundler::CLI::Common.output_without_groups_message(:update) Bundler::CLI::Common.output_post_install_messages installer.post_install_messages + + Bundler::CLI::Common.output_fund_metadata_summary end end end diff --git a/ruby/lib/bundler/compact_index_client.rb b/ruby/lib/bundler/compact_index_client.rb index a5120dbba..127a50e81 100644 --- a/ruby/lib/bundler/compact_index_client.rb +++ b/ruby/lib/bundler/compact_index_client.rb @@ -5,7 +5,7 @@ module Bundler class CompactIndexClient - DEBUG_MUTEX = Mutex.new + DEBUG_MUTEX = Thread::Mutex.new def self.debug return unless ENV["DEBUG_COMPACT_INDEX"] DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") } @@ -25,7 +25,7 @@ def initialize(directory, fetcher) @endpoints = Set.new @info_checksums_by_name = {} @parsed_checksums = false - @mutex = Mutex.new + @mutex = Thread::Mutex.new end def execution_mode=(block) @@ -73,12 +73,6 @@ def dependencies(names) end.flatten(1) end - def spec(name, version, platform = nil) - Bundler::CompactIndexClient.debug { "spec(name = #{name}, version = #{version}, platform = #{platform})" } - update_info(name) - @cache.specific_dependency(name, version, platform) - end - def update_and_parse_checksums! Bundler::CompactIndexClient.debug { "update_and_parse_checksums!" } return @info_checksums_by_name if @parsed_checksums @@ -87,7 +81,7 @@ def update_and_parse_checksums! @parsed_checksums = true end - private + private def update(local_path, remote_path) Bundler::CompactIndexClient.debug { "update(#{local_path}, #{remote_path})" } diff --git a/ruby/lib/bundler/compact_index_client/cache.rb b/ruby/lib/bundler/compact_index_client/cache.rb index f6105d3bb..2d8377713 100644 --- a/ruby/lib/bundler/compact_index_client/cache.rb +++ b/ruby/lib/bundler/compact_index_client/cache.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require_relative "gem_parser" + module Bundler class CompactIndexClient class Cache @@ -74,16 +76,7 @@ def info_path(name) end end - def specific_dependency(name, version, platform) - pattern = [version, platform].compact.join("-") - return nil if pattern.empty? - - gem_lines = info_path(name).read - gem_line = gem_lines[/^#{Regexp.escape(pattern)}\b.*/, 0] - gem_line ? parse_gem(gem_line) : nil - end - - private + private def lines(path) return [] unless path.file? @@ -92,19 +85,9 @@ def lines(path) header ? lines[header + 1..-1] : lines end - def parse_gem(string) - version_and_platform, rest = string.split(" ", 2) - version, platform = version_and_platform.split("-", 2) - dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest - dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : [] - requirements = requirements ? requirements.map {|r| parse_dependency(r) } : [] - [version, platform, dependencies, requirements] - end - - def parse_dependency(string) - dependency = string.split(":") - dependency[-1] = dependency[-1].split("&") if dependency.size > 1 - dependency + def parse_gem(line) + @dependency_parser ||= GemParser.new + @dependency_parser.parse(line) end def info_roots diff --git a/ruby/lib/bundler/compact_index_client/gem_parser.rb b/ruby/lib/bundler/compact_index_client/gem_parser.rb new file mode 100644 index 000000000..e7bf4c600 --- /dev/null +++ b/ruby/lib/bundler/compact_index_client/gem_parser.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Bundler + class CompactIndexClient + if defined?(Gem::Resolver::APISet::GemParser) + GemParser = Gem::Resolver::APISet::GemParser + else + class GemParser + def parse(line) + version_and_platform, rest = line.split(" ", 2) + version, platform = version_and_platform.split("-", 2) + dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest + dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : [] + requirements = requirements ? requirements.map {|d| parse_dependency(d) } : [] + [version, platform, dependencies, requirements] + end + + private + + def parse_dependency(string) + dependency = string.split(":") + dependency[-1] = dependency[-1].split("&") if dependency.size > 1 + dependency + end + end + end + end +end diff --git a/ruby/lib/bundler/compact_index_client/updater.rb b/ruby/lib/bundler/compact_index_client/updater.rb index 40232019b..d9b9cec0d 100644 --- a/ruby/lib/bundler/compact_index_client/updater.rb +++ b/ruby/lib/bundler/compact_index_client/updater.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true require_relative "../vendored_fileutils" -require "stringio" -require "zlib" module Bundler class CompactIndexClient @@ -22,13 +20,13 @@ def message def initialize(fetcher) @fetcher = fetcher - require "tmpdir" + require_relative "../vendored_tmpdir" end def update(local_path, remote_path, retrying = nil) headers = {} - Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir| + Bundler::Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir| local_temp_path = Pathname.new(local_temp_dir).join(local_path.basename) # first try to fetch any new bytes on the existing file @@ -45,29 +43,27 @@ def update(local_path, remote_path, retrying = nil) else "bytes=#{local_temp_path.size}-" end - else - # Fastly ignores Range when Accept-Encoding: gzip is set - headers["Accept-Encoding"] = "gzip" end response = @fetcher.call(remote_path, headers) return nil if response.is_a?(Net::HTTPNotModified) content = response.body - if response["Content-Encoding"] == "gzip" - content = Zlib::GzipReader.new(StringIO.new(content)).read - end - SharedHelpers.filesystem_access(local_temp_path) do + etag = (response["ETag"] || "").gsub(%r{\AW/}, "") + correct_response = SharedHelpers.filesystem_access(local_temp_path) do if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero? local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) } + + etag_for(local_temp_path) == etag else - local_temp_path.open("w") {|f| f << content } + local_temp_path.open("wb") {|f| f << content } + + etag.length.zero? || etag_for(local_temp_path) == etag end end - response_etag = (response["ETag"] || "").gsub(%r{\AW/}, "") - if etag_for(local_temp_path) == response_etag + if correct_response SharedHelpers.filesystem_access(local_path) do FileUtils.mv(local_temp_path, local_path) end @@ -75,16 +71,11 @@ def update(local_path, remote_path, retrying = nil) end if retrying - raise MisMatchedChecksumError.new(remote_path, response_etag, etag_for(local_temp_path)) + raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path)) end update(local_path, remote_path, :retrying) end - rescue Errno::EACCES - raise Bundler::PermissionError, - "Bundler does not have write access to create a temp directory " \ - "within #{Dir.tmpdir}. Bundler must have write access to your " \ - "systems temp directory to function properly. " rescue Zlib::GzipFile::Error raise Bundler::HTTPError end @@ -100,11 +91,11 @@ def slice_body(body, range) def checksum_for_file(path) return nil unless path.file? - # This must use IO.read instead of Digest.file().hexdigest + # This must use File.read instead of Digest.file().hexdigest # because we need to preserve \n line endings on windows when calculating # the checksum SharedHelpers.filesystem_access(path, :read) do - SharedHelpers.digest(:MD5).hexdigest(IO.read(path)) + SharedHelpers.digest(:MD5).hexdigest(File.read(path)) end end end diff --git a/ruby/lib/bundler/current_ruby.rb b/ruby/lib/bundler/current_ruby.rb index c132e8ecc..f84d68e26 100644 --- a/ruby/lib/bundler/current_ruby.rb +++ b/ruby/lib/bundler/current_ruby.rb @@ -20,6 +20,7 @@ class CurrentRuby 2.5 2.6 2.7 + 3.0 ].freeze KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze @@ -64,19 +65,19 @@ def truffleruby? end def mswin? - Bundler::WINDOWS + Gem.win_platform? end def mswin64? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64" + Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64" end def mingw? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64" + Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64" end def x64_mingw? - Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64" + Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64" end (KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version| diff --git a/ruby/lib/bundler/definition.rb b/ruby/lib/bundler/definition.rb index d6fbb0b5b..fbe6b2c87 100644 --- a/ruby/lib/bundler/definition.rb +++ b/ruby/lib/bundler/definition.rb @@ -1,12 +1,16 @@ # frozen_string_literal: true require_relative "lockfile_parser" -require "set" module Bundler class Definition include GemHelpers + class << self + # Do not create or modify a lockfile (Makes #lock a noop) + attr_accessor :no_lock + end + attr_reader( :dependencies, :locked_deps, @@ -57,10 +61,8 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti @unlocking_bundler = false @unlocking = unlock else - unlock = unlock.dup @unlocking_bundler = unlock.delete(:bundler) - unlock.delete_if {|_k, v| Array(v).empty? } - @unlocking = !unlock.empty? + @unlocking = unlock.any? {|_k, v| !Array(v).empty? } end @dependencies = dependencies @@ -76,7 +78,7 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti @lockfile_contents = String.new @locked_bundler_version = nil @locked_ruby_version = nil - @locked_specs_incomplete_for_platform = false + @new_platform = nil if lockfile && File.exist?(lockfile) @lockfile_contents = Bundler.read_file(lockfile) @@ -106,27 +108,43 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti @locked_platforms = [] end - @unlock[:gems] ||= [] + locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } + @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle? + + if @multisource_allowed + unless sources.aggregate_global_source? + msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure." + + Bundler::SharedHelpers.major_deprecation 2, msg + end + + @sources.merged_gem_lockfile_sections!(locked_gem_sources.first) + end + @unlock[:sources] ||= [] @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object @ruby_version.diff(locked_ruby_version_object) end @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version) - add_current_platform unless Bundler.frozen_bundle? + add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle? converge_path_sources_to_gemspec_sources @path_changes = converge_paths @source_changes = converge_sources - unless @unlock[:lock_shared_dependencies] - eager_unlock = expand_dependencies(@unlock[:gems], true) - @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name) + if @unlock[:conservative] + @unlock[:gems] ||= @dependencies.map(&:name) + else + eager_unlock = expand_dependencies(@unlock[:gems] || [], true) + @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name) end @dependency_changes = converge_dependencies @local_changes = converge_locals + @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true) + @requires = compute_requires end @@ -145,17 +163,21 @@ def gem_version_promoter end end + def resolve_only_locally! + @remote = false + sources.local_only! + resolve + end + def resolve_with_cache! - raise "Specs already loaded" if @specs sources.cached! - specs + resolve end def resolve_remotely! - raise "Specs already loaded" if @specs @remote = true sources.remote! - specs + resolve end # For given dependency list returns a SpecSet with Gemspec of all the required @@ -165,25 +187,7 @@ def resolve_remotely! # # @return [Bundler::SpecSet] def specs - @specs ||= begin - begin - specs = resolve.materialize(requested_dependencies) - rescue GemNotFound => e # Handle yanked gem - gem_name, gem_version = extract_gem_info(e) - locked_gem = @locked_specs[gem_name].last - raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote - raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \ - "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \ - "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \ - "to a version other than #{locked_gem} that hasn't been removed in order to install." - end - unless specs["bundler"].any? - bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last - specs["bundler"] = bundler - end - - specs - end + @specs ||= materialize(requested_dependencies) end def new_specs @@ -194,14 +198,8 @@ def removed_specs @locked_specs - specs end - def new_platform? - @new_platform - end - def missing_specs - missing = [] - resolve.materialize(requested_dependencies, missing) - missing + resolve.materialize(requested_dependencies).missing_specs end def missing_specs? @@ -210,7 +208,6 @@ def missing_specs? Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}" true rescue BundlerError => e - @index = nil @resolve = nil @specs = nil @gem_version_promoter = nil @@ -220,21 +217,35 @@ def missing_specs? end def requested_specs - @requested_specs ||= begin - groups = requested_groups - groups.map!(&:to_sym) - specs_for(groups) - end + specs_for(requested_groups) + end + + def requested_dependencies + dependencies_for(requested_groups) end def current_dependencies - dependencies.select(&:should_include?) + dependencies.select do |d| + d.should_include? && !d.gem_platforms(@platforms).empty? + end + end + + def locked_dependencies + @locked_deps.values end def specs_for(groups) - deps = dependencies.select {|d| (d.groups & groups).any? } - deps.delete_if {|d| !d.should_include? } - specs.for(expand_dependencies(deps)) + return specs if groups.empty? + deps = dependencies_for(groups) + materialize(deps) + end + + def dependencies_for(groups) + groups.map!(&:to_sym) + deps = current_dependencies.reject do |d| + (d.groups & groups).empty? + end + expand_dependencies(deps) end # Resolve all the dependencies specified in Gemfile. It ensures that @@ -245,76 +256,20 @@ def specs_for(groups) def resolve @resolve ||= begin last_resolve = converge_locked_specs - resolve = - if Bundler.frozen_bundle? - Bundler.ui.debug "Frozen, using resolution from the lockfile" - last_resolve - elsif !unlocking? && nothing_changed? - Bundler.ui.debug("Found no changes, using resolution from the lockfile") - last_resolve - else - # Run a resolve against the locally available gems - Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") - last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) - end - - # filter out gems that _can_ be installed on multiple platforms, but don't need - # to be - resolve.for(expand_dependencies(dependencies, true), [], false, false, false) - end - end - - def index - @index ||= Index.build do |idx| - dependency_names = @dependencies.map(&:name) - - sources.all_sources.each do |source| - source.dependency_names = dependency_names - pinned_spec_names(source) - idx.add_source source.specs - dependency_names.concat(source.unmet_deps).uniq! - end - - double_check_for_index(idx, dependency_names) - end - end - - # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both - # sources A and B. At this point, the API request will have found all the versions of Bar in source A, - # but will not have found any versions of Bar from source B, which is a problem if the requested version - # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for - # each spec we found, we add all possible versions from all sources to the index. - def double_check_for_index(idx, dependency_names) - pinned_names = pinned_spec_names - loop do - idxcount = idx.size - - names = :names # do this so we only have to traverse to get dependency_names from the index once - unmet_dependency_names = lambda do - return names unless names == :names - new_names = sources.all_sources.map(&:dependency_names_to_double_check) - return names = nil if new_names.compact! - names = new_names.flatten(1).concat(dependency_names) - names.uniq! - names -= pinned_names - names - end - - sources.all_sources.each do |source| - source.double_check_for(unmet_dependency_names) + if Bundler.frozen_bundle? + Bundler.ui.debug "Frozen, using resolution from the lockfile" + last_resolve + elsif !unlocking? && nothing_changed? + Bundler.ui.debug("Found no changes, using resolution from the lockfile") + last_resolve + else + # Run a resolve against the locally available gems + Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") + expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true) + Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) end - - break if idxcount == idx.size end end - private :double_check_for_index - - def has_rubygems_remotes? - sources.rubygems_sources.any? {|s| s.remotes.any? } - end - - def has_local_dependencies? - !sources.path_sources.empty? || !sources.git_sources.empty? - end def spec_git_paths sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact @@ -325,6 +280,8 @@ def groups end def lock(file, preserve_unknown_sections = false) + return if Definition.no_lock + contents = to_lock # Convert to \r\n if the existing lock has them @@ -335,10 +292,7 @@ def lock(file, preserve_unknown_sections = false) locked_major = @locked_bundler_version.segments.first current_major = Gem::Version.create(Bundler::VERSION).segments.first - if updating_major = locked_major < current_major - Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \ - "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}." - end + updating_major = locked_major < current_major end preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler)) @@ -355,14 +309,6 @@ def lock(file, preserve_unknown_sections = false) end end - def locked_bundler_version - if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION) - new_version = Bundler::VERSION - end - - new_version || @locked_bundler_version || Bundler::VERSION - end - def locked_ruby_version return unless ruby_version if @unlock[:ruby] || !@locked_ruby_version @@ -396,12 +342,10 @@ def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control." unless explicit_flag - suggested_command = if Bundler.settings.locations("frozen")[:global] + suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any? "bundle config unset frozen" elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any? "bundle config unset deployment" - else - "bundle install --no-deployment" end msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \ "freeze \nby running `#{suggested_command}`." @@ -416,44 +360,31 @@ def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) added.concat new_platforms.map {|p| "* platform: #{p}" } deleted.concat deleted_platforms.map {|p| "* platform: #{p}" } - gemfile_sources = sources.lock_sources - - new_sources = gemfile_sources - @locked_sources - deleted_sources = @locked_sources - gemfile_sources + new_deps = @dependencies - locked_dependencies + deleted_deps = locked_dependencies - @dependencies - new_deps = @dependencies - @locked_deps.values - deleted_deps = @locked_deps.values - @dependencies + added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any? + deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any? - # Check if it is possible that the source is only changed thing - if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?) - new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) } - deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) } - end + both_sources = Hash.new {|h, k| h[k] = [] } + @dependencies.each {|d| both_sources[d.name][0] = d } - if @locked_sources != gemfile_sources - if new_sources.any? - added.concat new_sources.map {|source| "* source: #{source}" } - end + locked_dependencies.each do |d| + next if !Bundler.feature_flag.bundler_3_mode? && @locked_specs[d.name].empty? - if deleted_sources.any? - deleted.concat deleted_sources.map {|source| "* source: #{source}" } - end + both_sources[d.name][1] = d end - added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any? - if deleted_deps.any? - deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } - end + both_sources.each do |name, (dep, lock_dep)| + next if dep.nil? || lock_dep.nil? - both_sources = Hash.new {|h, k| h[k] = [] } - @dependencies.each {|d| both_sources[d.name][0] = d } - @locked_deps.each {|name, d| both_sources[name][1] = d.source } + gemfile_source = dep.source || sources.default_source + lock_source = lock_dep.source || sources.default_source + next if lock_source.include?(gemfile_source) - both_sources.each do |name, (dep, lock_source)| - next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep)) - gemfile_source_name = (dep && dep.source) || "no specified source" - lockfile_source_name = lock_source || "no specified source" - changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`" + gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source" + lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source" + changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`" end reason = change_reason @@ -497,15 +428,11 @@ def validate_ruby! end def validate_platforms! - return if @platforms.any? do |bundle_platform| - Bundler.rubygems.platforms.any? do |local_platform| - MatchPlatform.platforms_match?(bundle_platform, local_platform) - end - end + return if current_platform_locked? raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \ - "but your local platforms are #{Bundler.rubygems.platforms.map(&:to_s)}, and " \ - "there's no compatible match between those two lists." + "but your local platform is #{Bundler.local_platform}. " \ + "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again." end def add_platform(platform) @@ -518,16 +445,10 @@ def remove_platform(platform) raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}" end - def add_current_platform - current_platforms.each {|platform| add_platform(platform) } - end - - def find_resolved_spec(current_spec) - specs.find_by_name_and_platform(current_spec.name, current_spec.platform) - end - - def find_indexed_specs(current_spec) - index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version) + def most_specific_locked_platform + @platforms.min_by do |bundle_platform| + platform_specificity_match(bundle_platform, local_platform) + end end attr_reader :sources @@ -541,16 +462,54 @@ def unlocking? @unlocking end - private + private + + def materialize(dependencies) + specs = resolve.materialize(dependencies) + missing_specs = specs.missing_specs + + if missing_specs.any? + missing_specs.each do |s| + locked_gem = @locked_specs[s.name].last + next if locked_gem.nil? || locked_gem.version != s.version || !@remote + raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \ + "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \ + "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \ + "removed in order to install." + end + + raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources" + end + + unless specs["bundler"].any? + bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last + specs["bundler"] = bundler + end + + specs + end + + def precompute_source_requirements_for_indirect_dependencies? + @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source? + end + + def current_ruby_platform_locked? + return false unless generic_local_platform == Gem::Platform::RUBY + return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY) + + current_platform_locked? + end - def current_platforms - current_platform = Bundler.local_platform - [].tap do |platforms| - platforms << current_platform if Bundler.feature_flag.specific_platform? - platforms << generic(current_platform) + def current_platform_locked? + @platforms.any? do |bundle_platform| + MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform) end end + def add_current_platform + add_platform(local_platform) + end + def change_reason if unlocking? unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v| @@ -587,9 +546,9 @@ def specs_changed?(source) def dependencies_for_source_changed?(source, locked_source = source) deps_for_source = @dependencies.select {|s| s.source == source } - locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source } + locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source } - Set.new(deps_for_source) != Set.new(locked_deps_for_source) + deps_for_source.uniq.sort != locked_deps_for_source.sort end def specs_for_source_changed?(source) @@ -648,36 +607,11 @@ def converge_path_sources_to_gemspec_sources end end - def converge_rubygems_sources - return false if Bundler.feature_flag.disable_multisource? - - changes = false - - # Get the RubyGems sources from the Gemfile.lock - locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } - # Get the RubyGems remotes from the Gemfile - actual_remotes = sources.rubygems_remotes - - # If there is a RubyGems source in both - if !locked_gem_sources.empty? && !actual_remotes.empty? - locked_gem_sources.each do |locked_gem| - # Merge the remotes from the Gemfile into the Gemfile.lock - changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes]) - end - end - - changes - end - def converge_sources - changes = false - - changes |= converge_rubygems_sources - # Replace the sources from the Gemfile with the sources from the Gemfile.lock, # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent # source in the Gemfile.lock, use the one from the Gemfile. - changes |= sources.replace_sources!(@locked_sources) + changes = sources.replace_sources!(@locked_sources) sources.all_sources.each do |source| # If the source is unlockable and the current command allows an unlock of @@ -695,28 +629,14 @@ def converge_sources end def converge_dependencies - frozen = Bundler.frozen_bundle? - (@dependencies + @locked_deps.values).each do |dep| - locked_source = @locked_deps[dep.name] - # This is to make sure that if bundler is installing in deployment mode and - # after locked_source and sources don't match, we still use locked_source. - if frozen && !locked_source.nil? && - locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist? - dep.source = locked_source.source - elsif dep.source + changes = false + + @dependencies.each do |dep| + if dep.source dep.source = sources.get(dep.source) end - if dep.source.is_a?(Source::Gemspec) - dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq! - end - end - changes = false - # We want to know if all match, but don't want to check all entries - # This means we need to return false if any dependency doesn't match - # the lock or doesn't exist in the lock. - @dependencies.each do |dependency| - unless locked_dep = @locked_deps[dependency.name] + unless locked_dep = @locked_deps[dep.name] changes = true next end @@ -727,11 +647,11 @@ def converge_dependencies # directive, the lockfile dependencies and resolved dependencies end up # with a mismatch on #type. Work around that by setting the type on the # dep from the lockfile. - locked_dep.instance_variable_set(:@type, dependency.type) + locked_dep.instance_variable_set(:@type, dep.type) # We already know the name matches from the hash lookup # so we only need to check the requirement now - changes ||= dependency.requirement != locked_dep.requirement + changes ||= dep.requirement != locked_dep.requirement end changes @@ -741,47 +661,37 @@ def converge_dependencies # commonly happen if the Gemfile has changed since the lockfile was last # generated def converge_locked_specs - deps = [] - - # Build a list of dependencies that are the same in the Gemfile - # and Gemfile.lock. If the Gemfile modified a dependency, but - # the gem in the Gemfile.lock still satisfies it, this is fine - # too. - @dependencies.each do |dep| - locked_dep = @locked_deps[dep.name] + resolve = converge_specs(@locked_specs) - # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep - locked_dep = nil unless locked_dep == dep + diff = nil - if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep) - deps << dep - elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source) - @locked_specs.each do |s| - @unlock[:gems] << s.name if s.source == dep.source - end + # Now, we unlock any sources that do not have anymore gems pinned to it + sources.all_sources.each do |source| + next unless source.respond_to?(:unlock!) - dep.source.unlock! if dep.source.respond_to?(:unlock!) - dep.source.specs.each {|s| @unlock[:gems] << s.name } + unless resolve.any? {|s| s.source == source } + diff ||= @locked_specs.to_a - resolve.to_a + source.unlock! if diff.any? {|s| s.source == source } end end - unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec? + resolve + end + def converge_specs(specs) + deps = [] converged = [] - @locked_specs.each do |s| + specs.each do |s| # Replace the locked dependency's source with the equivalent source from the Gemfile dep = @dependencies.find {|d| s.satisfies?(d) } - s.source = (dep && dep.source) || sources.get(s.source) - # Don't add a spec to the list if its source is expired. For example, - # if you change a Git gem to RubyGems. - next if s.source.nil? - next if @unlock[:sources].include?(s.source.name) + if dep && (!dep.source || s.source.include?(dep.source)) + deps << dep + end + + s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle? - # XXX This is a backwards-compatibility fix to preserve the ability to - # unlock a single gem by passing its name via `--source`. See issue #3759 - # TODO: delete in Bundler 2 - next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name) + next if @unlock[:sources].include?(s.source.name) # If the spec is from a path source and it doesn't exist anymore # then we unlock it. @@ -793,8 +703,8 @@ def converge_locked_specs rescue PathError, GitError # if we won't need the source (according to the lockfile), # don't error if the path/git source isn't available - next if @locked_specs. - for(requested_dependencies, [], false, true, false). + next if specs. + for(requested_dependencies, false, true). none? {|locked_spec| locked_spec.source == s.source } raise @@ -806,61 +716,23 @@ def converge_locked_specs # commonly happens if the version changed in the gemspec next unless new_spec - new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development } - old_runtime_deps = s.dependencies.select {|d| d.type != :development } - # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it - next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) } - s.dependencies.replace(new_spec.dependencies) end - converged << s - end - - resolve = SpecSet.new(converged) - @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(deps), @unlock[:gems], true, true) - resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false) - diff = nil - - # Now, we unlock any sources that do not have anymore gems pinned to it - sources.all_sources.each do |source| - next unless source.respond_to?(:unlock!) - - unless resolve.any? {|s| s.source == source } - diff ||= @locked_specs.to_a - resolve.to_a - source.unlock! if diff.any? {|s| s.source == source } + if dep.nil? && requested_dependencies.find {|d| s.name == d.name } + @unlock[:gems] << s.name + else + converged << s end end - resolve - end - - def in_locked_deps?(dep, locked_dep) - # Because the lockfile can't link a dep to a specific remote, we need to - # treat sources as equivalent anytime the locked dep has all the remotes - # that the Gemfile dep does. - locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source) - end - - def satisfies_locked_spec?(dep) - @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) } - end - - # This list of dependencies is only used in #resolve, so it's OK to add - # the metadata dependencies here - def expanded_dependencies - @expanded_dependencies ||= begin - expand_dependencies(dependencies + metadata_dependencies, @remote) - end + resolve = SpecSet.new(converged) + SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) }) end def metadata_dependencies @metadata_dependencies ||= begin - ruby_versions = concat_ruby_version_requirements(@ruby_version) - if ruby_versions.empty? || !@ruby_version.exact? - concat_ruby_version_requirements(RubyVersion.system) - concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby] - end + ruby_versions = ruby_version_requirements(@ruby_version) [ Dependency.new("Ruby\0", ruby_versions), Dependency.new("RubyGems\0", Gem::VERSION), @@ -868,83 +740,56 @@ def metadata_dependencies end end - def concat_ruby_version_requirements(ruby_version, ruby_versions = []) - return ruby_versions unless ruby_version + def ruby_version_requirements(ruby_version) + return [] unless ruby_version if ruby_version.patchlevel - ruby_versions << ruby_version.to_gem_version_with_patchlevel + [ruby_version.to_gem_version_with_patchlevel] else - ruby_versions.concat(ruby_version.versions.map do |version| + ruby_version.versions.map do |version| requirement = Gem::Requirement.new(version) if requirement.exact? "~> #{version}.0" else requirement end - end) + end end end def expand_dependencies(dependencies, remote = false) - sorted_platforms = Resolver.sort_platforms(@platforms) deps = [] dependencies.each do |dep| dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name) - next if !remote && !dep.current_platform? - platforms = dep.gem_platforms(sorted_platforms) - if platforms.empty? && !Bundler.settings[:disable_platform_warnings] - mapped_platforms = dep.expanded_platforms - Bundler.ui.warn \ - "The dependency #{dep} will be unused by any of the platforms Bundler is installing for. " \ - "Bundler is installing for #{@platforms.join ", "} but the dependency " \ - "is only for #{mapped_platforms.join ", "}. " \ - "To add those platforms to the bundle, " \ - "run `bundle lock --add-platform #{mapped_platforms.join " "}`." - end - platforms.each do |p| - deps << DepProxy.new(dep, p) if remote || p == generic_local_platform - end + next unless remote || dep.current_platform? + target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform]) + deps += expand_dependency_with_platforms(dep, target_platforms) end deps end - def requested_dependencies - groups = requested_groups - groups.map!(&:to_sym) - dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? } + def expand_dependency_with_platforms(dep, platforms) + platforms.map do |p| + DepProxy.get_proxy(dep, p) + end end def source_requirements - # Load all specs from remote sources - index - # Record the specs available in each gem's source, so that those # specs will be available later when the resolver knows where to # look for that gemspec (or its dependencies) - default = sources.default_source - source_requirements = { :default => default } - default = nil unless Bundler.feature_flag.disable_multisource? - dependencies.each do |dep| - next unless source = dep.source || default - source_requirements[dep.name] = source + source_requirements = if precompute_source_requirements_for_indirect_dependencies? + { :default => sources.default_source }.merge(source_map.all_requirements) + else + { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements) end metadata_dependencies.each do |dep| source_requirements[dep.name] = sources.metadata_source end + source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source source_requirements["bundler"] = sources.metadata_source # needs to come last to override source_requirements end - def pinned_spec_names(skip = nil) - pinned_names = [] - default = Bundler.feature_flag.disable_multisource? && sources.default_source - @dependencies.each do |dep| - next unless dep_source = dep.source || default - next if dep_source == skip - pinned_names << dep.name - end - pinned_names - end - def requested_groups groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with] end @@ -962,12 +807,6 @@ def lockfiles_equal?(current, proposed, preserve_unknown_sections) current == proposed end - def extract_gem_info(error) - # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources" - # to an array. The first element will be the gem name (e.g. foo), the second will be the version number. - error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten - end - def compute_requires dependencies.reduce({}) do |requires, dep| next requires unless dep.should_include? @@ -980,23 +819,16 @@ def compute_requires end def additional_base_requirements_for_resolve - return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions? - dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) } - @locked_gems.specs.reduce({}) do |requirements, locked_spec| + return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources) + converge_specs(@locked_gems.specs).map do |locked_spec| name = locked_spec.name - dependency = dependencies_by_name[name] - next requirements if @locked_gems.dependencies[name] != dependency - next requirements if dependency && dependency.source.is_a?(Source::Path) dep = Gem::Dependency.new(name, ">= #{locked_spec.version}") - requirements[name] = DepProxy.new(dep, locked_spec.platform) - requirements - end.values + DepProxy.get_proxy(dep, locked_spec.platform) + end end - def equivalent_rubygems_remotes?(source) - return false unless source.is_a?(Source::Rubygems) - - Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes) + def source_map + @source_map ||= SourceMap.new(sources, dependencies) end end end diff --git a/ruby/lib/bundler/dep_proxy.rb b/ruby/lib/bundler/dep_proxy.rb index 6c32179ac..a32dc37b4 100644 --- a/ruby/lib/bundler/dep_proxy.rb +++ b/ruby/lib/bundler/dep_proxy.rb @@ -4,19 +4,18 @@ module Bundler class DepProxy attr_reader :__platform, :dep + @proxies = {} + + def self.get_proxy(dep, platform) + @proxies[[dep, platform]] ||= new(dep, platform).freeze + end + def initialize(dep, platform) @dep = dep @__platform = platform end - def hash - @hash ||= [dep, __platform].hash - end - - def ==(other) - return false if other.class != self.class - dep == other.dep && __platform == other.__platform - end + private_class_method :new alias_method :eql?, :== @@ -39,7 +38,15 @@ def to_s s end - private + def dup + raise NoMethodError.new("DepProxy cannot be duplicated") + end + + def clone + raise NoMethodError.new("DepProxy cannot be cloned") + end + + private def method_missing(*args, &blk) @dep.send(*args, &blk) diff --git a/ruby/lib/bundler/dependency.rb b/ruby/lib/bundler/dependency.rb index 6c2642163..94e85053d 100644 --- a/ruby/lib/bundler/dependency.rb +++ b/ruby/lib/bundler/dependency.rb @@ -7,7 +7,7 @@ module Bundler class Dependency < Gem::Dependency attr_reader :autorequire - attr_reader :groups, :platforms, :gemfile, :git, :branch + attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref PLATFORM_MAP = { :ruby => Gem::Platform::RUBY, @@ -74,15 +74,6 @@ class Dependency < Gem::Dependency :x64_mingw_26 => Gem::Platform::X64_MINGW, }.freeze - REVERSE_PLATFORM_MAP = {}.tap do |reverse_platform_map| - PLATFORM_MAP.each do |key, value| - reverse_platform_map[value] ||= [] - reverse_platform_map[value] << key - end - - reverse_platform_map.each {|_, platforms| platforms.freeze } - end.freeze - def initialize(name, version, options = {}, &blk) type = options["type"] || :runtime super(name, version, type) @@ -91,7 +82,9 @@ def initialize(name, version, options = {}, &blk) @groups = Array(options["group"] || :default).map(&:to_sym) @source = options["source"] @git = options["git"] + @github = options["github"] @branch = options["branch"] + @ref = options["ref"] @platforms = Array(options["platforms"]) @env = options["env"] @should_include = options.fetch("should_include", true) @@ -105,13 +98,11 @@ def initialize(name, version, options = {}, &blk) def gem_platforms(valid_platforms) return valid_platforms if @platforms.empty? - @gem_platforms ||= expanded_platforms.compact.uniq - - valid_platforms & @gem_platforms + valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) } end def expanded_platforms - @platforms.map {|pl| PLATFORM_MAP[pl] } + @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq end def should_include? diff --git a/ruby/lib/bundler/digest.rb b/ruby/lib/bundler/digest.rb new file mode 100644 index 000000000..759f60941 --- /dev/null +++ b/ruby/lib/bundler/digest.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +# This code was extracted from https://github.com/Solistra/ruby-digest which is under public domain +module Bundler + module Digest + # The initial constant values for the 32-bit constant words A, B, C, D, and + # E, respectively. + SHA1_WORDS = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0].freeze + + # The 8-bit field used for bitwise `AND` masking. Defaults to `0xFFFFFFFF`. + SHA1_MASK = 0xFFFFFFFF + + class << self + def sha1(string) + unless string.is_a?(String) + raise TypeError, "can't convert #{string.class.inspect} into String" + end + + buffer = string.b + + words = SHA1_WORDS.dup + generate_split_buffer(buffer) do |chunk| + w = [] + chunk.each_slice(4) do |a, b, c, d| + w << (((a << 8 | b) << 8 | c) << 8 | d) + end + a, b, c, d, e = *words + (16..79).each do |i| + w[i] = SHA1_MASK & rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1) + end + 0.upto(79) do |i| + case i + when 0..19 + f = ((b & c) | (~b & d)) + k = 0x5A827999 + when 20..39 + f = (b ^ c ^ d) + k = 0x6ED9EBA1 + when 40..59 + f = ((b & c) | (b & d) | (c & d)) + k = 0x8F1BBCDC + when 60..79 + f = (b ^ c ^ d) + k = 0xCA62C1D6 + end + t = SHA1_MASK & (SHA1_MASK & rotate(a, 5) + f + e + k + w[i]) + a, b, c, d, e = t, a, SHA1_MASK & rotate(b, 30), c, d # rubocop:disable Style/ParallelAssignment + end + mutated = [a, b, c, d, e] + words.map!.with_index {|word, index| SHA1_MASK & (word + mutated[index]) } + end + + words.pack("N*").unpack("H*").first + end + + private + + def generate_split_buffer(string, &block) + size = string.bytesize * 8 + buffer = string.bytes << 128 + buffer << 0 while buffer.size % 64 != 56 + buffer.concat([size].pack("Q>").bytes) + buffer.each_slice(64, &block) + end + + def rotate(value, spaces) + value << spaces | value >> (32 - spaces) + end + end + end +end diff --git a/ruby/lib/bundler/dsl.rb b/ruby/lib/bundler/dsl.rb index 99a369281..f7922b1fb 100644 --- a/ruby/lib/bundler/dsl.rb +++ b/ruby/lib/bundler/dsl.rb @@ -18,6 +18,8 @@ def self.evaluate(gemfile, lockfile, unlock) VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules platform platforms type source install_if gemfile].freeze + GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}.freeze + attr_reader :gemspecs attr_accessor :dependencies @@ -63,7 +65,7 @@ def gemspec(opts = nil) development_group = opts[:development_group] || :development expanded_path = gemfile_root.join(path) - gemspecs = Dir[File.join(expanded_path, "{,*}.gemspec")].map {|g| Bundler.load_gemspec(g) }.compact + gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).map {|g| Bundler.load_gemspec(g) }.compact gemspecs.reject! {|s| s.name != name } if name Index.sort_specs(gemspecs) specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] } @@ -75,8 +77,7 @@ def gemspec(opts = nil) @gemspecs << spec - gem_platforms = Bundler::Dependency::REVERSE_PLATFORM_MAP[Bundler::GemHelpers.generic_local_platform] - gem spec.name, :name => spec.name, :path => path, :glob => glob, :platforms => gem_platforms + gem spec.name, :name => spec.name, :path => path, :glob => glob group(development_group) do spec.development_dependencies.each do |dep| @@ -104,8 +105,8 @@ def gem(name, *args) if current = @dependencies.find {|d| d.name == dep.name } deleted_dep = @dependencies.delete(current) if current.type == :development - if current.requirement != dep.requirement - unless deleted_dep + unless deleted_dep + if current.requirement != dep.requirement return if dep.type == :development update_prompt = "" @@ -123,17 +124,14 @@ def gem(name, *args) raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \ "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \ "#{update_prompt}" + else + Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \ + "You should probably keep only one of them.\n" \ + "Remove any duplicate entries and specify the gem only once.\n" \ + "While it's not a problem now, it could cause errors if you change the version of one of them later." end - else - Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \ - "You should probably keep only one of them.\n" \ - "Remove any duplicate entries and specify the gem only once.\n" \ - "While it's not a problem now, it could cause errors if you change the version of one of them later." - end - - if current.source != dep.source - unless deleted_dep + if current.source != dep.source return if dep.type == :development raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \ "You specified that #{dep.name} (#{dep.requirement}) should come from " \ @@ -165,8 +163,7 @@ def source(source, *args, &blk) elsif block_given? with_source(@sources.add_rubygems_source("remotes" => source), &blk) else - check_primary_source_safety(@sources) - @sources.global_rubygems_source = source + @sources.add_global_rubygems_remote(source) end end @@ -184,24 +181,14 @@ def git_source(name, &block) end def path(path, options = {}, &blk) - unless block_given? - msg = "You can no longer specify a path source by itself. Instead, \n" \ - "either use the :path option on a gem, or specify the gems that \n" \ - "bundler should find in the path source by passing a block to \n" \ - "the path method, like: \n\n" \ - " path 'dir/containing/rails' do\n" \ - " gem 'rails'\n" \ - " end\n\n" - - raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource? - SharedHelpers.major_deprecation(2, msg.strip) - end - source_options = normalize_hash(options).merge( "path" => Pathname.new(path), "root_path" => gemfile_root, "gemspec" => gemspecs.find {|g| g.name == options["name"] } ) + + source_options["global"] = true unless block_given? + source = @sources.add_path_source(source_options) with_source(source, &blk) end @@ -223,7 +210,6 @@ def git(uri, options = {}, &blk) def github(repo, options = {}) raise ArgumentError, "GitHub sources require a block" unless block_given? - raise DeprecatedError, "The #github method has been removed" if Bundler.feature_flag.skip_default_git_sources? github_uri = @git_sources["github"].call(repo) git_options = normalize_hash(options).merge("uri" => github_uri) git_source = @sources.add_git_source(git_options) @@ -231,6 +217,7 @@ def github(repo, options = {}) end def to_definition(lockfile, unlock) + check_primary_source_safety Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles) end @@ -281,32 +268,33 @@ def method_missing(name, *args) raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile" end - private + def check_primary_source_safety + check_path_source_safety + check_rubygems_source_safety + end - def add_git_sources - return if Bundler.feature_flag.skip_default_git_sources? + private + def add_git_sources git_source(:github) do |repo_name| - warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".') -"https://github.com/#{repo_name}.git" - RUBY - repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") - "https://github.com/#{repo_name}.git" + if repo_name =~ GITHUB_PULL_REQUEST_URL + { + "git" => "https://github.com/#{$1}.git", + "branch" => "refs/pull/#{$2}/head", + "ref" => nil, + "tag" => nil, + } + else + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://github.com/#{repo_name}.git" + end end git_source(:gist) do |repo_name| - warn_deprecated_git_source(:gist, '"https://gist.github.com/#{repo_name}.git"') - "https://gist.github.com/#{repo_name}.git" end git_source(:bitbucket) do |repo_name| - warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip) -user_name, repo_name = repo_name.split("/") -repo_name ||= user_name -"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git" - RUBY - user_name, repo_name = repo_name.split("/") repo_name ||= user_name "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git" @@ -377,7 +365,11 @@ def normalize_options(name, version, opts) git_name = (git_names & opts.keys).last if @git_sources[git_name] - opts["git"] = @git_sources[git_name].call(opts[git_name]) + git_opts = @git_sources[git_name].call(opts[git_name]) + git_opts = { "git" => git_opts } if git_opts.is_a?(String) + opts.merge!(git_opts) do |key, _gemfile_value, _git_source_value| + raise GemfileError, %(The :#{key} option can't be used with `#{git_name}: #{opts[git_name].inspect}`) + end end %w[git path].each do |type| @@ -444,42 +436,47 @@ def normalize_source(source) end end - def check_primary_source_safety(source_list) - return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil? + def check_path_source_safety + return if @sources.global_path_source.nil? + + msg = "You can no longer specify a path source by itself. Instead, \n" \ + "either use the :path option on a gem, or specify the gems that \n" \ + "bundler should find in the path source by passing a block to \n" \ + "the path method, like: \n\n" \ + " path 'dir/containing/rails' do\n" \ + " gem 'rails'\n" \ + " end\n\n" + + SharedHelpers.major_deprecation(2, msg.strip) + end + + def check_rubygems_source_safety + if @sources.implicit_global_source? + implicit_global_source_warning + elsif @sources.aggregate_global_source? + multiple_global_source_warning + end + end + + def implicit_global_source_warning + Bundler::SharedHelpers.major_deprecation 2, "This Gemfile does not include an explicit global source. " \ + "Not using an explicit global source may result in a different lockfile being generated depending on " \ + "the gems you have installed locally before bundler is run. " \ + "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"." + end - if Bundler.feature_flag.disable_multisource? + def multiple_global_source_warning + if Bundler.feature_flag.bundler_3_mode? msg = "This Gemfile contains multiple primary sources. " \ "Each source after the first must include a block to indicate which gems " \ "should come from that source" - unless Bundler.feature_flag.bundler_2_mode? - msg += ". To downgrade this error to a warning, run " \ - "`bundle config unset disable_multisource`" - end raise GemfileEvalError, msg else Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \ "Using `source` more than once without a block is a security risk, and " \ "may result in installing unexpected gems. To resolve this warning, use " \ - "a block to indicate which gems should come from the secondary source. " \ - "To upgrade this warning to an error, run `bundle config set " \ - "disable_multisource true`." - end - end - - def warn_deprecated_git_source(name, replacement, additional_message = nil) - additional_message &&= " #{additional_message}" - replacement = if replacement.count("\n").zero? - "{|repo_name| #{replacement} }" - else - "do |repo_name|\n#{replacement.to_s.gsub(/^/, " ")}\n end" + "a block to indicate which gems should come from the secondary source." end - - Bundler::SharedHelpers.major_deprecation 3, <<-EOS -The :#{name} git source is deprecated, and will be removed in the future.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work: - - git_source(:#{name}) #{replacement} - - EOS end class DSLError < GemfileError @@ -571,7 +568,7 @@ def to_s end end - private + private def parse_line_number_from_description description = self.description diff --git a/ruby/lib/bundler/endpoint_specification.rb b/ruby/lib/bundler/endpoint_specification.rb index 9a00b64e0..f3260a38e 100644 --- a/ruby/lib/bundler/endpoint_specification.rb +++ b/ruby/lib/bundler/endpoint_specification.rb @@ -3,17 +3,17 @@ module Bundler # used for Creating Specifications from the Gemcutter Endpoint class EndpointSpecification < Gem::Specification - ILLFORMED_MESSAGE = 'Ill-formed requirement ["# e - raise unless e.message.include?(ILLFORMED_MESSAGE) - puts # we shouldn't print the error message on the "fetching info" status line - raise GemspecError, - "Unfortunately, the gem #{name} (#{version}) has an invalid " \ - "gemspec.\nPlease ask the gem author to yank the bad version to fix " \ - "this issue. For more information, see http://bit.ly/syck-defaultkey." end end end diff --git a/ruby/lib/bundler/env.rb b/ruby/lib/bundler/env.rb index 17624b4fe..1763035a8 100644 --- a/ruby/lib/bundler/env.rb +++ b/ruby/lib/bundler/env.rb @@ -71,7 +71,7 @@ def self.read_file(filename) def self.ruby_version str = String.new(RUBY_VERSION) str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL - str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]" + str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{Gem::Platform.local}]" end def self.git_version @@ -105,7 +105,7 @@ def self.environment out << [" User Home", Gem.user_home] out << [" User Path", Gem.user_dir] out << [" Bin Dir", Gem.bindir] - if defined?(OpenSSL) + if defined?(OpenSSL::SSL) out << ["OpenSSL"] out << [" Compiled", OpenSSL::OPENSSL_VERSION] if defined?(OpenSSL::OPENSSL_VERSION) out << [" Loaded", OpenSSL::OPENSSL_LIBRARY_VERSION] if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION) diff --git a/ruby/lib/bundler/environment_preserver.rb b/ruby/lib/bundler/environment_preserver.rb index c9014bada..0f08e049d 100644 --- a/ruby/lib/bundler/environment_preserver.rb +++ b/ruby/lib/bundler/environment_preserver.rb @@ -17,14 +17,41 @@ class EnvironmentPreserver ].map(&:freeze).freeze BUNDLER_PREFIX = "BUNDLER_ORIG_".freeze - # @param env [ENV] + def self.from_env + new(env_to_hash(ENV), BUNDLER_KEYS) + end + + def self.env_to_hash(env) + to_hash = env.to_hash + return to_hash unless Gem.win_platform? + + to_hash.each_with_object({}) {|(k,v), a| a[k.upcase] = v } + end + + # @param env [Hash] # @param keys [Array] def initialize(env, keys) - @original = env.to_hash + @original = env @keys = keys @prefix = BUNDLER_PREFIX end + # Replaces `ENV` with the bundler environment variables backed up + def replace_with_backup + unless Gem.win_platform? + ENV.replace(backup) + return + end + + # Fallback logic for Windows below to workaround + # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all + # supported rubies include the fix for that. + + ENV.clear + + backup.each {|k, v| ENV[k] = v } + end + # @return [Hash] def backup env = @original.clone diff --git a/ruby/lib/bundler/errors.rb b/ruby/lib/bundler/errors.rb index e471bce0b..9ad7460e5 100644 --- a/ruby/lib/bundler/errors.rb +++ b/ruby/lib/bundler/errors.rb @@ -56,6 +56,7 @@ class PluginError < BundlerError; status_code(29); end class SudoNotPermittedError < BundlerError; status_code(30); end class ThreadCreationError < BundlerError; status_code(33); end class APIResponseMismatchError < BundlerError; status_code(34); end + class APIResponseInvalidDependenciesError < BundlerError; status_code(35); end class GemfileEvalError < GemfileError; end class MarshalError < StandardError; end @@ -74,10 +75,26 @@ def action end end + def permission_type + case @permission_type + when :create + "executable permissions for all parent directories and write permissions for `#{parent_folder}`" + when :delete + permissions = "executable permissions for all parent directories and write permissions for `#{parent_folder}`" + permissions += ", and the same thing for all subdirectories inside #{@path}" if File.directory?(@path) + permissions + else + "#{@permission_type} permissions for that path" + end + end + + def parent_folder + File.dirname(@path) + end + def message "There was an error while trying to #{action} `#{@path}`. " \ - "It is likely that you need to grant #{@permission_type} permissions " \ - "for that path." + "It is likely that you need to grant #{permission_type}." end status_code(23) @@ -121,7 +138,7 @@ def message class VirtualProtocolError < BundlerError def message - "There was an error relating to virtualization and file access." \ + "There was an error relating to virtualization and file access. " \ "It is likely that you need to grant access to or mount some file system correctly." end diff --git a/ruby/lib/bundler/feature_flag.rb b/ruby/lib/bundler/feature_flag.rb index 01739ec4a..e441b941c 100644 --- a/ruby/lib/bundler/feature_flag.rb +++ b/ruby/lib/bundler/feature_flag.rb @@ -27,25 +27,17 @@ def self.settings_method(name, key, &default) (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } } - settings_flag(:allow_bundler_dependency_conflicts) { bundler_3_mode? } settings_flag(:allow_offline_install) { bundler_3_mode? } settings_flag(:auto_clean_without_path) { bundler_3_mode? } - settings_flag(:auto_config_jobs) { bundler_3_mode? } settings_flag(:cache_all) { bundler_3_mode? } settings_flag(:default_install_uses_path) { bundler_3_mode? } - settings_flag(:deployment_means_frozen) { bundler_3_mode? } - settings_flag(:disable_multisource) { bundler_3_mode? } settings_flag(:forget_cli_options) { bundler_3_mode? } settings_flag(:global_gem_cache) { bundler_3_mode? } - settings_flag(:only_update_to_newer_versions) { bundler_3_mode? } settings_flag(:path_relative_to_cwd) { bundler_3_mode? } settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") } settings_flag(:print_only_version_number) { bundler_3_mode? } settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? } - settings_flag(:skip_default_git_sources) { bundler_3_mode? } - settings_flag(:specific_platform) { bundler_3_mode? } settings_flag(:suppress_install_using_messages) { bundler_3_mode? } - settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? } settings_flag(:update_requires_all_flag) { bundler_4_mode? } settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? } diff --git a/ruby/lib/bundler/fetcher.rb b/ruby/lib/bundler/fetcher.rb index caf33bcfc..e07f92510 100644 --- a/ruby/lib/bundler/fetcher.rb +++ b/ruby/lib/bundler/fetcher.rb @@ -28,7 +28,8 @@ def initialize(remote_uri) " is a chance you are experiencing a man-in-the-middle attack, but" \ " most likely your system doesn't have the CA certificates needed" \ " for verification. For information about OpenSSL certificates, see" \ - " http://bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile" \ + " https://railsapps.github.io/openssl-certificate-verify-failed.html." \ + " To connect without using SSL, edit your Gemfile" \ " sources and change 'https' to 'http'." end end @@ -47,7 +48,8 @@ def initialize(remote_uri) remote_uri = filter_uri(remote_uri) super "Authentication is required for #{remote_uri}.\n" \ "Please supply credentials for this source. You can do this by running:\n" \ - " bundle config set #{remote_uri} username:password" + "`bundle config set --global #{remote_uri} username:password`\n" \ + "or by storing the credentials in the `#{Settings.key_for(remote_uri)}` environment variable" end end # This error is raised if HTTP authentication is provided, but incorrect. @@ -69,8 +71,8 @@ def initialize(remote_uri) :HTTPUnsupportedMediaType, :HTTPVersionNotSupported].freeze FAIL_ERRORS = begin fail_errors = [AuthenticationRequiredError, BadAuthenticationError, FallbackError] - fail_errors << Gem::Requirement::BadRequirementError if defined?(Gem::Requirement::BadRequirementError) - fail_errors.concat(NET_ERRORS.map {|e| SharedHelpers.const_get_safely(e, Net) }.compact) + fail_errors << Gem::Requirement::BadRequirementError + fail_errors.concat(NET_ERRORS.map {|e| Net.const_get(e) }) end.freeze class << self @@ -120,7 +122,6 @@ def specs_with_retry(gem_names, source) # return the specs in the bundler format as an index def specs(gem_names, source) - old = Bundler.rubygems.sources index = Bundler::Index.new if Bundler::Fetcher.disable_endpoint @@ -128,18 +129,15 @@ def specs(gem_names, source) specs = fetchers.last.specs(gem_names) else specs = [] - fetchers.shift until fetchers.first.available? || fetchers.empty? - fetchers.dup.each do |f| - break unless f.api_fetcher? && !gem_names || !specs = f.specs(gem_names) - fetchers.delete(f) + @fetchers = fetchers.drop_while do |f| + !f.available? || (f.api_fetcher? && !gem_names) || !specs = f.specs(gem_names) end @use_api = false if fetchers.none?(&:api_fetcher?) end specs.each do |name, version, platform, dependencies, metadata| - next if name == "bundler" spec = if dependencies - EndpointSpecification.new(name, version, platform, dependencies, metadata) + EndpointSpecification.new(name, version, platform, self, dependencies, metadata) else RemoteSpecification.new(name, version, platform, self) end @@ -152,8 +150,6 @@ def specs(gem_names, source) rescue CertificateFailureError Bundler.ui.info "" if gem_names && use_api # newline after dots raise - ensure - Bundler.rubygems.sources = old end def use_api @@ -216,7 +212,7 @@ def inspect "#<#{self.class}:0x#{object_id} uri=#{uri}>" end - private + private FETCHERS = [CompactIndex, Dependency, Index].freeze @@ -229,6 +225,7 @@ def cis "BUILDBOX" => "buildbox", "GO_SERVER_URL" => "go", "SNAP_CI" => "snap", + "GITLAB_CI" => "gitlab", "CI_NAME" => ENV["CI_NAME"], "CI" => "ci", } @@ -243,7 +240,7 @@ def connection raise SSLError if needs_ssl && !defined?(OpenSSL::SSL) con = PersistentHTTP.new :name => "bundler", :proxy => :ENV - if gem_proxy = Bundler.rubygems.configuration[:http_proxy] + if gem_proxy = Gem.configuration[:http_proxy] con.proxy = Bundler::URI.parse(gem_proxy) if gem_proxy != :no_proxy end @@ -254,8 +251,8 @@ def connection end ssl_client_cert = Bundler.settings[:ssl_client_cert] || - (Bundler.rubygems.configuration.ssl_client_cert if - Bundler.rubygems.configuration.respond_to?(:ssl_client_cert)) + (Gem.configuration.ssl_client_cert if + Gem.configuration.respond_to?(:ssl_client_cert)) if ssl_client_cert pem = File.read(ssl_client_cert) con.cert = OpenSSL::X509::Certificate.new(pem) @@ -273,8 +270,7 @@ def connection # cached gem specification path, if one exists def gemspec_cached_path(spec_file_name) paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) } - paths = paths.select {|path| File.file? path } - paths.first + paths.find {|path| File.file? path } end HTTP_ERRORS = [ @@ -287,8 +283,8 @@ def gemspec_cached_path(spec_file_name) def bundler_cert_store store = OpenSSL::X509::Store.new ssl_ca_cert = Bundler.settings[:ssl_ca_cert] || - (Bundler.rubygems.configuration.ssl_ca_cert if - Bundler.rubygems.configuration.respond_to?(:ssl_ca_cert)) + (Gem.configuration.ssl_ca_cert if + Gem.configuration.respond_to?(:ssl_ca_cert)) if ssl_ca_cert if File.directory? ssl_ca_cert store.add_path ssl_ca_cert @@ -302,8 +298,6 @@ def bundler_cert_store store end - private - def remote_uri @remote.uri end diff --git a/ruby/lib/bundler/fetcher/base.rb b/ruby/lib/bundler/fetcher/base.rb index 27987f670..16cc98273 100644 --- a/ruby/lib/bundler/fetcher/base.rb +++ b/ruby/lib/bundler/fetcher/base.rb @@ -38,7 +38,7 @@ def api_fetcher? false end - private + private def log_specs(debug_msg) if Bundler.ui.debug? diff --git a/ruby/lib/bundler/fetcher/compact_index.rb b/ruby/lib/bundler/fetcher/compact_index.rb index f36d76d4a..b23176588 100644 --- a/ruby/lib/bundler/fetcher/compact_index.rb +++ b/ruby/lib/bundler/fetcher/compact_index.rb @@ -57,22 +57,17 @@ def specs_for_names(gem_names) gem_info end - def fetch_spec(spec) - spec -= [nil, "ruby", ""] - contents = compact_index_client.spec(*spec) - return nil if contents.nil? - contents.unshift(spec.first) - contents[3].map! {|d| Gem::Dependency.new(*d) } - EndpointSpecification.new(*contents) - end - compact_index_request :fetch_spec - def available? - return nil unless SharedHelpers.md5_available? - user_home = Bundler.user_home - return nil unless user_home.directory? && user_home.writable? + unless SharedHelpers.md5_available? + Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API") + return nil + end + if fetch_uri.scheme == "file" + Bundler.ui.debug("Using a local server, bundler won't use the CompactIndex API") + return false + end # Read info file checksums out of /versions, so we can know if gems are up to date - fetch_uri.scheme != "file" && compact_index_client.update_and_parse_checksums! + compact_index_client.update_and_parse_checksums! rescue CompactIndexClient::Updater::MisMatchedChecksumError => e Bundler.ui.debug(e.message) nil @@ -83,7 +78,7 @@ def api_fetcher? true end - private + private def compact_index_client @compact_index_client ||= @@ -111,7 +106,7 @@ def serial_compact_index_client def bundle_worker(func = nil) @bundle_worker ||= begin worker_name = "Compact Index (#{display_uri.host})" - Bundler::Worker.new(Bundler.current_ruby.rbx? ? 1 : 25, worker_name, func) + Bundler::Worker.new(Bundler.settings.processor_count, worker_name, func) end @bundle_worker.tap do |worker| worker.instance_variable_set(:@func, func) if func diff --git a/ruby/lib/bundler/fetcher/downloader.rb b/ruby/lib/bundler/fetcher/downloader.rb index 498852c17..f2aad3a50 100644 --- a/ruby/lib/bundler/fetcher/downloader.rb +++ b/ruby/lib/bundler/fetcher/downloader.rb @@ -14,8 +14,10 @@ def initialize(connection, redirect_limit) def fetch(uri, headers = {}, counter = 0) raise HTTPError, "Too many redirects" if counter >= redirect_limit + filtered_uri = URICredentialsFilter.credential_filtered_uri(uri) + response = request(uri, headers) - Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}") + Bundler.ui.debug("HTTP #{response.code} #{response.message} #{filtered_uri}") case response when Net::HTTPSuccess, Net::HTTPNotModified @@ -40,7 +42,7 @@ def fetch(uri, headers = {}, counter = 0) raise BadAuthenticationError, uri.host if uri.userinfo raise AuthenticationRequiredError, uri.host when Net::HTTPNotFound - raise FallbackError, "Net::HTTPNotFound: #{URICredentialsFilter.credential_filtered_uri(uri)}" + raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}" else raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}" end @@ -49,7 +51,9 @@ def fetch(uri, headers = {}, counter = 0) def request(uri, headers) validate_uri_scheme!(uri) - Bundler.ui.debug "HTTP GET #{uri}" + filtered_uri = URICredentialsFilter.credential_filtered_uri(uri) + + Bundler.ui.debug "HTTP GET #{filtered_uri}" req = Net::HTTP::Get.new uri.request_uri, headers if uri.user user = CGI.unescape(uri.user) @@ -64,17 +68,16 @@ def request(uri, headers) raise CertificateFailureError.new(uri) rescue *HTTP_ERRORS => e Bundler.ui.trace e - case e.message - when /host down:/, /getaddrinfo: nodename nor servname provided/ + if e.is_a?(SocketError) || e.message =~ /host down:/ raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \ "connection and try again." else - raise HTTPError, "Network error while fetching #{URICredentialsFilter.credential_filtered_uri(uri)}" \ + raise HTTPError, "Network error while fetching #{filtered_uri}" \ " (#{e})" end end - private + private def validate_uri_scheme!(uri) return if uri.scheme =~ /\Ahttps?\z/ diff --git a/ruby/lib/bundler/fetcher/index.rb b/ruby/lib/bundler/fetcher/index.rb index 034a22519..6bb9fcc19 100644 --- a/ruby/lib/bundler/fetcher/index.rb +++ b/ruby/lib/bundler/fetcher/index.rb @@ -1,14 +1,13 @@ # frozen_string_literal: true require_relative "base" -require "rubygems/remote_fetcher" module Bundler class Fetcher class Index < Base def specs(_gem_names) Bundler.rubygems.fetch_all_remote_specs(remote) - rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError, Net::HTTPFatalError => e + rescue Gem::RemoteFetcher::FetchError => e case e.message when /certificate verify failed/ raise CertificateFailureError.new(display_uri) @@ -19,36 +18,9 @@ def specs(_gem_names) raise BadAuthenticationError, remote_uri if remote_uri.userinfo raise AuthenticationRequiredError, remote_uri else - Bundler.ui.trace e - raise HTTPError, "Could not fetch specs from #{display_uri}" + raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>" end end - - def fetch_spec(spec) - spec -= [nil, "ruby", ""] - spec_file_name = "#{spec.join "-"}.gemspec" - - uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") - if uri.scheme == "file" - path = Bundler.rubygems.correct_for_windows_path(uri.path) - Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(path)) - elsif cached_spec_path = gemspec_cached_path(spec_file_name) - Bundler.load_gemspec(cached_spec_path) - else - Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body) - end - rescue MarshalError - raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \ - "Your network or your gem server is probably having issues right now." - end - - private - - # cached gem specification path, if one exists - def gemspec_cached_path(spec_file_name) - paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) } - paths.find {|path| File.file? path } - end end end end diff --git a/ruby/lib/bundler/friendly_errors.rb b/ruby/lib/bundler/friendly_errors.rb index 080697b02..cc615db60 100644 --- a/ruby/lib/bundler/friendly_errors.rb +++ b/ruby/lib/bundler/friendly_errors.rb @@ -4,7 +4,19 @@ module Bundler module FriendlyErrors - module_function + module_function + + def enable! + @disabled = false + end + + def disabled? + @disabled + end + + def disable! + @disabled = true + end def log_error(error) case error @@ -23,13 +35,7 @@ def log_error(error) Bundler.ui.error error.message when LoadError raise error unless error.message =~ /cannot load such file -- openssl|openssl.so|libcrypto.so/ - Bundler.ui.error "\nCould not load OpenSSL." - Bundler.ui.warn <<-WARN, :wrap => true - You must recompile Ruby with OpenSSL support or change the sources in your \ - Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL \ - using RVM are available at https://rvm.io/packages/openssl. - WARN - Bundler.ui.trace error + Bundler.ui.error "\nCould not load OpenSSL. #{error.class}: #{error}\n#{error.backtrace.join("\n ")}" when Interrupt Bundler.ui.error "\nQuitting..." Bundler.ui.trace error @@ -43,8 +49,6 @@ def log_error(error) "Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)." else request_issue_report_for(error) end - rescue StandardError - raise error end def exit_status(error) @@ -57,36 +61,8 @@ def exit_status(error) end def request_issue_report_for(e) - Bundler.ui.info <<-EOS.gsub(/^ {8}/, "") + Bundler.ui.error <<-EOS.gsub(/^ {8}/, ""), nil, nil --- ERROR REPORT TEMPLATE ------------------------------------------------------- - # Error Report - - ## Questions - - Please fill out answers to these questions, it'll help us figure out - why things are going wrong. - - - **What did you do?** - - I ran the command `#{$PROGRAM_NAME} #{ARGV.join(" ")}` - - - **What did you expect to happen?** - - I expected Bundler to... - - - **What happened instead?** - - Instead, what happened was... - - - **Have you tried any solutions posted on similar issues in our issue tracker, stack overflow, or google?** - - I tried... - - - **Have you read our issues document, https://github.com/bundler/bundler/blob/master/doc/contributing/ISSUES.md?** - - ... - - ## Backtrace ``` #{e.class}: #{e.message} @@ -100,13 +76,12 @@ def request_issue_report_for(e) Bundler.ui.error "Unfortunately, an unexpected error occurred, and Bundler cannot continue." - Bundler.ui.warn <<-EOS.gsub(/^ {8}/, "") + Bundler.ui.error <<-EOS.gsub(/^ {8}/, ""), nil, :yellow First, try this link to see if there are any existing issue reports for this error: #{issues_url(e)} - If there aren't any reports for this error yet, please create copy and paste the report template above into a new issue. Don't forget to anonymize any private data! The new issue form is located at: - https://github.com/bundler/bundler/issues/new + If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}, and copy and paste the report template above in there. EOS end @@ -114,16 +89,23 @@ def issues_url(exception) message = exception.message.lines.first.tr(":", " ").chomp message = message.split("-").first if exception.is_a?(Errno) require "cgi" - "https://github.com/bundler/bundler/search?q=" \ + "https://github.com/rubygems/rubygems/search?q=" \ "#{CGI.escape(message)}&type=Issues" end + + def new_issue_url + "https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md" + end end def self.with_friendly_errors + FriendlyErrors.enable! yield rescue SignalException raise rescue Exception => e # rubocop:disable Lint/RescueException + raise if FriendlyErrors.disabled? + FriendlyErrors.log_error(e) exit FriendlyErrors.exit_status(e) end diff --git a/ruby/lib/bundler/gem_helper.rb b/ruby/lib/bundler/gem_helper.rb index 204dd2405..0bbd2d9b7 100644 --- a/ruby/lib/bundler/gem_helper.rb +++ b/ruby/lib/bundler/gem_helper.rb @@ -15,6 +15,10 @@ def install_tasks(opts = {}) new(opts[:dir], opts[:name]).install end + def tag_prefix=(prefix) + instance.tag_prefix = prefix + end + def gemspec(&block) gemspec = instance.gemspec block.call(gemspec) if block @@ -24,12 +28,15 @@ def gemspec(&block) attr_reader :spec_path, :base, :gemspec + attr_writer :tag_prefix + def initialize(base = nil, name = nil) - @base = (base ||= SharedHelpers.pwd) - gemspecs = name ? [File.join(base, "#{name}.gemspec")] : Dir[File.join(base, "{,*}.gemspec")] + @base = File.expand_path(base || SharedHelpers.pwd) + gemspecs = name ? [File.join(@base, "#{name}.gemspec")] : Gem::Util.glob_files_in_dir("{,*}.gemspec", @base) raise "Unable to determine name from existing gemspec. Use :name => 'gemname' in #install_tasks to manually set it." unless gemspecs.size == 1 @spec_path = gemspecs.first @gemspec = Bundler.load_gemspec(@spec_path) + @tag_prefix = "" end def install @@ -40,6 +47,11 @@ def install built_gem_path = build_gem end + desc "Generate SHA512 checksum if #{name}-#{version}.gem into the checksums directory." + task "build:checksum" => "build" do + build_checksum(built_gem_path) + end + desc "Build and install #{name}-#{version}.gem into system gems." task "install" => "build" do install_gem(built_gem_path) @@ -64,7 +76,7 @@ def install tag_version { git_push(args[:remote]) } unless already_tagged? end - task "release:rubygem_push" do + task "release:rubygem_push" => "build" do rubygem_push(built_gem_path) if gem_push? end @@ -73,7 +85,7 @@ def install def build_gem file_name = nil - sh("#{gem_command} build -V #{spec_path.shellescape}".shellsplit) do + sh([*gem_command, "build", "-V", spec_path]) do file_name = File.basename(built_gem_path) SharedHelpers.filesystem_access(File.join(base, "pkg")) {|p| FileUtils.mkdir_p(p) } FileUtils.mv(built_gem_path, "pkg") @@ -84,36 +96,54 @@ def build_gem def install_gem(built_gem_path = nil, local = false) built_gem_path ||= build_gem - cmd = "#{gem_command} install #{built_gem_path}" - cmd += " --local" if local - _, status = sh_with_status(cmd.shellsplit) - unless status.success? - raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" - end + cmd = [*gem_command, "install", built_gem_path.to_s] + cmd << "--local" if local + sh(cmd) Bundler.ui.confirm "#{name} (#{version}) installed." end - protected + def build_checksum(built_gem_path = nil) + built_gem_path ||= build_gem + SharedHelpers.filesystem_access(File.join(base, "checksums")) {|p| FileUtils.mkdir_p(p) } + file_name = "#{File.basename(built_gem_path)}.sha512" + require "digest/sha2" + checksum = ::Digest::SHA512.file(built_gem_path).hexdigest + target = File.join(base, "checksums", file_name) + File.write(target, checksum + "\n") + Bundler.ui.confirm "#{name} #{version} checksum written to checksums/#{file_name}." + end + + protected def rubygem_push(path) - cmd = %W[#{gem_command} push #{path}] + cmd = [*gem_command, "push", path] cmd << "--key" << gem_key if gem_key cmd << "--host" << allowed_push_host if allowed_push_host - unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file? - raise "Your rubygems.org credentials aren't set. Run `gem push` to set them." - end sh_with_input(cmd) Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_push_host}" end def built_gem_path - Dir[File.join(base, "#{name}-*.gem")].sort_by {|f| File.mtime(f) }.last + Gem::Util.glob_files_in_dir("#{name}-*.gem", base).sort_by {|f| File.mtime(f) }.last end - def git_push(remote = "") - perform_git_push remote - perform_git_push "#{remote} --tags" - Bundler.ui.confirm "Pushed git commits and tags." + def git_push(remote = nil) + remote ||= default_remote + sh("git push #{remote} refs/heads/#{current_branch}".shellsplit) + sh("git push #{remote} refs/tags/#{version_tag}".shellsplit) + Bundler.ui.confirm "Pushed git commits and release tag." + end + + def default_remote + remote_for_branch, status = sh_with_status(%W[git config --get branch.#{current_branch}.remote]) + return "origin" unless status.success? + + remote_for_branch.strip + end + + def current_branch + # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0 + sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip end def allowed_push_host @@ -128,13 +158,6 @@ def gem_push_host allowed_push_host || env_rubygems_host || "rubygems.org" end - def perform_git_push(options = "") - cmd = "git push #{options}" - out, status = sh_with_status(cmd.shellsplit) - return if status.success? - raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" - end - def already_tagged? return false unless sh(%w[git tag]).split(/\n/).include?(version_tag) Bundler.ui.confirm "Tag #{version_tag} has already been created." @@ -168,7 +191,7 @@ def version end def version_tag - "v#{version}" + "#{@tag_prefix}v#{version}" end def name @@ -185,8 +208,7 @@ def sh_with_input(cmd) def sh(cmd, &block) out, status = sh_with_status(cmd, &block) unless status.success? - cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin) - raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out) + raise("Running `#{cmd.shelljoin}` failed with the following output:\n\n#{out}\n") end out end @@ -210,7 +232,7 @@ def gem_push? end def gem_command - ENV["GEM_COMMAND"] ? ENV["GEM_COMMAND"] : "gem" + ENV["GEM_COMMAND"]&.shellsplit || ["gem"] end end end diff --git a/ruby/lib/bundler/gem_helpers.rb b/ruby/lib/bundler/gem_helpers.rb index be047f439..b271b8d22 100644 --- a/ruby/lib/bundler/gem_helpers.rb +++ b/ruby/lib/bundler/gem_helpers.rb @@ -24,47 +24,44 @@ def generic(p) module_function :generic def generic_local_platform - generic(Bundler.local_platform) + generic(local_platform) end module_function :generic_local_platform + def local_platform + Bundler.local_platform + end + module_function :local_platform + def platform_specificity_match(spec_platform, user_platform) spec_platform = Gem::Platform.new(spec_platform) - return PlatformMatch::EXACT_MATCH if spec_platform == user_platform - return PlatformMatch::WORST_MATCH if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY - - PlatformMatch.new( - PlatformMatch.os_match(spec_platform, user_platform), - PlatformMatch.cpu_match(spec_platform, user_platform), - PlatformMatch.platform_version_match(spec_platform, user_platform) - ) + + PlatformMatch.specificity_score(spec_platform, user_platform) end module_function :platform_specificity_match def select_best_platform_match(specs, platform) - specs.select {|spec| spec.match_platform(platform) }. - min_by {|spec| platform_specificity_match(spec.platform, platform) } + matching = specs.select {|spec| spec.match_platform(platform) } + exact = matching.select {|spec| spec.platform == platform } + return exact if exact.any? + + sorted_matching = matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) } + exemplary_spec = sorted_matching.first + + sorted_matching.take_while{|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) } end module_function :select_best_platform_match - PlatformMatch = Struct.new(:os_match, :cpu_match, :platform_version_match) class PlatformMatch - def <=>(other) - return nil unless other.is_a?(PlatformMatch) - - m = os_match <=> other.os_match - return m unless m.zero? - - m = cpu_match <=> other.cpu_match - return m unless m.zero? + def self.specificity_score(spec_platform, user_platform) + return -1 if spec_platform == user_platform + return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY - m = platform_version_match <=> other.platform_version_match - m + os_match(spec_platform, user_platform) + + cpu_match(spec_platform, user_platform) * 10 + + platform_version_match(spec_platform, user_platform) * 100 end - EXACT_MATCH = new(-1, -1, -1).freeze - WORST_MATCH = new(1_000_000, 1_000_000, 1_000_000).freeze - def self.os_match(spec_platform, user_platform) if spec_platform.os == user_platform.os 0 @@ -95,5 +92,19 @@ def self.platform_version_match(spec_platform, user_platform) end end end + + def same_specificity(platform, spec, exemplary_spec) + platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform) + end + module_function :same_specificity + + def same_deps(spec, exemplary_spec) + same_runtime_deps = spec.dependencies.sort == exemplary_spec.dependencies.sort + return same_runtime_deps unless spec.is_a?(Gem::Specification) && exemplary_spec.is_a?(Gem::Specification) + + same_metadata_deps = spec.required_ruby_version == exemplary_spec.required_ruby_version && spec.required_rubygems_version == exemplary_spec.required_rubygems_version + same_runtime_deps && same_metadata_deps + end + module_function :same_deps end end diff --git a/ruby/lib/bundler/gem_remote_fetcher.rb b/ruby/lib/bundler/gem_remote_fetcher.rb deleted file mode 100644 index 9577535d6..000000000 --- a/ruby/lib/bundler/gem_remote_fetcher.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require "rubygems/remote_fetcher" - -module Bundler - # Adds support for setting custom HTTP headers when fetching gems from the - # server. - # - # TODO: Get rid of this when and if gemstash only supports RubyGems versions - # that contain https://github.com/rubygems/rubygems/commit/3db265cc20b2f813. - class GemRemoteFetcher < Gem::RemoteFetcher - attr_accessor :headers - - # Extracted from RubyGems 2.4. - def fetch_http(uri, last_modified = nil, head = false, depth = 0) - fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get - # beginning of change - response = request uri, fetch_type, last_modified do |req| - headers.each {|k, v| req.add_field(k, v) } if headers - end - # end of change - - case response - when Net::HTTPOK, Net::HTTPNotModified then - response.uri = uri if response.respond_to? :uri - head ? response : response.body - when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther, - Net::HTTPTemporaryRedirect then - raise FetchError.new("too many redirects", uri) if depth > 10 - - location = URI.parse response["Location"] - - if https?(uri) && !https?(location) - raise FetchError.new("redirecting to non-https resource: #{location}", uri) - end - - fetch_http(location, last_modified, head, depth + 1) - else - raise FetchError.new("bad response #{response.message} #{response.code}", uri) - end - end - end -end diff --git a/ruby/lib/bundler/gem_version_promoter.rb b/ruby/lib/bundler/gem_version_promoter.rb index 311b0cbbf..3cce3f213 100644 --- a/ruby/lib/bundler/gem_version_promoter.rb +++ b/ruby/lib/bundler/gem_version_promoter.rb @@ -7,7 +7,7 @@ module Bundler # available dependency versions as found in its index, before returning it to # to the resolution engine to select the best version. class GemVersionPromoter - DEBUG = ENV["DEBUG_RESOLVER"] + DEBUG = ENV["BUNDLER_DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER"] attr_reader :level, :locked_specs, :unlock_gems @@ -81,8 +81,8 @@ def sort_versions(dep, spec_groups) sort_dep_specs(spec_groups, locked_spec) end.tap do |specs| if DEBUG - warn before_result - warn " after sort_versions: #{debug_format_result(dep, specs).inspect}" + puts before_result + puts " after sort_versions: #{debug_format_result(dep, specs).inspect}" end end end @@ -98,7 +98,7 @@ def minor? level == :minor end - private + private def filter_dep_specs(spec_groups, locked_spec) res = spec_groups.select do |spec_group| diff --git a/ruby/lib/bundler/gemdeps.rb b/ruby/lib/bundler/gemdeps.rb deleted file mode 100644 index cd4b25d0e..000000000 --- a/ruby/lib/bundler/gemdeps.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Bundler - class Gemdeps - def initialize(runtime) - @runtime = runtime - end - - def requested_specs - @runtime.requested_specs - end - - def specs - @runtime.specs - end - - def dependencies - @runtime.dependencies - end - - def current_dependencies - @runtime.current_dependencies - end - - def requires - @runtime.requires - end - end -end diff --git a/ruby/lib/bundler/graph.rb b/ruby/lib/bundler/graph.rb index 5644e4107..8f52e2f0f 100644 --- a/ruby/lib/bundler/graph.rb +++ b/ruby/lib/bundler/graph.rb @@ -27,7 +27,7 @@ def viz GraphVizClient.new(self).run end - private + private def _populate_relations parent_dependencies = _groups.values.to_set.flatten diff --git a/ruby/lib/bundler/index.rb b/ruby/lib/bundler/index.rb index 9166a9273..8930fca6d 100644 --- a/ruby/lib/bundler/index.rb +++ b/ruby/lib/bundler/index.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "set" - module Bundler class Index include Enumerable @@ -65,11 +63,14 @@ def search(query, base = nil) def unsorted_search(query, base) results = local_search(query, base) - seen = results.map(&:full_name).to_set unless @sources.empty? + seen = results.map(&:full_name).uniq unless @sources.empty? @sources.each do |source| source.unsorted_search(query, base).each do |spec| - results << spec if seen.add?(spec.full_name) + next if seen.include?(spec.full_name) + + seen << spec.full_name + results << spec end end @@ -121,10 +122,9 @@ def spec_names names end - # returns a list of the dependencies def unmet_dependency_names dependency_names.select do |name| - name != "bundler" && search(name).empty? + search(name).empty? end end @@ -170,7 +170,7 @@ def ==(other) def dependencies_eql?(spec, other_spec) deps = spec.dependencies.select {|d| d.type != :development } other_deps = other_spec.dependencies.select {|d| d.type != :development } - Set.new(deps) == Set.new(other_deps) + deps.sort == other_deps.sort end def add_source(index) @@ -179,7 +179,7 @@ def add_source(index) @sources.uniq! # need to use uniq! here instead of checking for the item before adding end - private + private def specs_by_name(name) @specs[name].values @@ -195,7 +195,7 @@ def search_by_dependency(dependency, base = nil) if base # allow all platforms when searching from a lockfile dependency.matches_spec?(spec) else - dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform) + dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec) end end diff --git a/ruby/lib/bundler/injector.rb b/ruby/lib/bundler/injector.rb index 2cdda578e..42f837a91 100644 --- a/ruby/lib/bundler/injector.rb +++ b/ruby/lib/bundler/injector.rb @@ -74,7 +74,7 @@ def remove(gemfile_path, lockfile_path) end end - private + private def conservative_version(spec) version = spec.version @@ -112,9 +112,12 @@ def build_gem_lines(conservative_versioning) source = ", :source => \"#{d.source}\"" unless d.source.nil? git = ", :git => \"#{d.git}\"" unless d.git.nil? + github = ", :github => \"#{d.github}\"" unless d.github.nil? branch = ", :branch => \"#{d.branch}\"" unless d.branch.nil? + ref = ", :ref => \"#{d.ref}\"" unless d.ref.nil? + require_path = ", :require => #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil? - %(gem #{name}#{requirement}#{group}#{source}#{git}#{branch}) + %(gem #{name}#{requirement}#{group}#{source}#{git}#{github}#{branch}#{ref}#{require_path}) end.join("\n") end @@ -128,7 +131,7 @@ def append_to(gemfile_path, new_gem_lines) # evaluates a gemfile to remove the specified gem # from it. def remove_deps(gemfile_path) - initial_gemfile = IO.readlines(gemfile_path) + initial_gemfile = File.readlines(gemfile_path) Bundler.ui.info "Removing gems from #{gemfile_path}" @@ -179,11 +182,22 @@ def remove_gems_from_dependencies(builder, gems, gemfile_path) # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies. def remove_gems_from_gemfile(gems, gemfile_path) patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/ + new_gemfile = [] + multiline_removal = false + File.readlines(gemfile_path).each do |line| + match_data = line.match(patterns) + if match_data && is_not_within_comment?(line, match_data) + multiline_removal = line.rstrip.end_with?(",") + # skip lines which match the regex + next + end - # remove lines which match the regex - new_gemfile = IO.readlines(gemfile_path).reject {|line| line.match(patterns) } + # skip followup lines until line does not end with ',' + new_gemfile << line unless multiline_removal + multiline_removal = line.rstrip.end_with?(",") if multiline_removal + end - # remove lone \n and append them with other strings + # remove line \n and append them with other strings new_gemfile.each_with_index do |_line, index| if new_gemfile[index + 1] == "\n" new_gemfile[index] += new_gemfile[index + 1] @@ -196,6 +210,13 @@ def remove_gems_from_gemfile(gems, gemfile_path) new_gemfile.join.chomp end + # @param [String] line Individual line of gemfile content. + # @param [MatchData] match_data Data about Regex match. + def is_not_within_comment?(line, match_data) + match_start_index = match_data.offset(0).first + !line[0..match_start_index].include?("#") + end + # @param [Array] gemfile Array of gemfile contents. # @param [String] block_name Name of block name to look for. def remove_nested_blocks(gemfile, block_name) @@ -251,5 +272,11 @@ def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_ge def show_warning(message) Bundler.ui.info Bundler.ui.add_color(message, :yellow) end + + def convert_autorequire(autorequire) + autorequire = autorequire.first + return autorequire if autorequire == "false" + autorequire.inspect + end end end diff --git a/ruby/lib/bundler/inline.rb b/ruby/lib/bundler/inline.rb index f1f77a7a9..a718418fc 100644 --- a/ruby/lib/bundler/inline.rb +++ b/ruby/lib/bundler/inline.rb @@ -50,15 +50,16 @@ def Bundler.root Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins? builder = Bundler::Dsl.new builder.instance_eval(&gemfile) + builder.check_primary_source_safety - Bundler.settings.temporary(:frozen => false) do + Bundler.settings.temporary(:deployment => false, :frozen => false) do definition = builder.to_definition(nil, true) def definition.lock(*); end definition.validate_runtime! Bundler.ui = install ? ui : Bundler::UI::Silent.new if install || definition.missing_specs? - Bundler.settings.temporary(:inline => true, :disable_platform_warnings => true) do + Bundler.settings.temporary(:inline => true) do installer = Bundler::Installer.install(Bundler.root, definition, :system => true) installer.post_install_messages.each do |name, message| Bundler.ui.info "Post-install message from #{name}:\n#{message}" diff --git a/ruby/lib/bundler/installer.rb b/ruby/lib/bundler/installer.rb index 700f0a473..61bf1e06d 100644 --- a/ruby/lib/bundler/installer.rb +++ b/ruby/lib/bundler/installer.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "erb" -require "rubygems/dependency_installer" require_relative "worker" require_relative "installer/parallel_installer" require_relative "installer/standalone" @@ -83,7 +81,6 @@ def run(options) if resolve_if_needed(options) ensure_specs_are_compatible! - warn_on_incompatible_bundler_deps load_plugins options.delete(:jobs) else @@ -91,6 +88,8 @@ def run(options) end install(options) + Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available + lock unless Bundler.frozen_bundle? Standalone.new(options[:standalone], @definition).generate if options[:standalone] end @@ -135,12 +134,18 @@ def generate_bundler_executable_stubs(spec, options = {}) next end - File.open(binstub_path, "w", 0o777 & ~File.umask) do |f| - if RUBY_VERSION >= "2.6" - f.puts ERB.new(template, :trim_mode => "-").result(binding) - else - f.puts ERB.new(template, nil, "-").result(binding) - end + mode = Gem.win_platform? ? "wb:UTF-8" : "w" + require "erb" + content = if RUBY_VERSION >= "2.6" + ERB.new(template, :trim_mode => "-").result(binding) + else + ERB.new(template, nil, "-").result(binding) + end + + File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask) + if Gem.win_platform? || options[:all_platforms] + prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" + File.write("#{binstub_path}.cmd", prefix + content, :mode => mode) end end @@ -159,7 +164,7 @@ def generate_bundler_executable_stubs(spec, options = {}) end end - def generate_standalone_bundler_executable_stubs(spec) + def generate_standalone_bundler_executable_stubs(spec, options = {}) # double-assignment to avoid warnings about variables that will be used by ERB bin_path = Bundler.bin_path unless path = Bundler.settings[:path] @@ -175,17 +180,24 @@ def generate_standalone_bundler_executable_stubs(spec) next if executable == "bundle" executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path) executable_path = executable_path - File.open "#{bin_path}/#{executable}", "w", 0o755 do |f| - if RUBY_VERSION >= "2.6" - f.puts ERB.new(template, :trim_mode => "-").result(binding) - else - f.puts ERB.new(template, nil, "-").result(binding) - end + + mode = Gem.win_platform? ? "wb:UTF-8" : "w" + require "erb" + content = if RUBY_VERSION >= "2.6" + ERB.new(template, :trim_mode => "-").result(binding) + else + ERB.new(template, nil, "-").result(binding) + end + + File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755) + if Gem.win_platform? || options[:all_platforms] + prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" + File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode) end end end - private + private # the order that the resolver provides is significant, since # dependencies might affect the installation of a gem. @@ -202,27 +214,11 @@ def installation_parallelization(options) return jobs end - return 1 unless can_install_in_parallel? - - auto_config_jobs = Bundler.feature_flag.auto_config_jobs? if jobs = Bundler.settings[:jobs] - if auto_config_jobs - jobs - else - [jobs.pred, 1].max - end - elsif auto_config_jobs - processor_count - else - 1 + return jobs end - end - def processor_count - require "etc" - Etc.nprocessors - rescue StandardError - 1 + Bundler.settings.processor_count end def load_plugins @@ -238,11 +234,12 @@ def load_plugins end end.flatten Bundler.rubygems.load_plugin_files(path_plugin_files) + Bundler.rubygems.load_env_plugins end def ensure_specs_are_compatible! system_ruby = Bundler::RubyVersion.system - rubygems_version = Gem::Version.create(Gem::VERSION) + rubygems_version = Bundler.rubygems.version @definition.specs.each do |spec| if required_ruby_version = spec.required_ruby_version unless required_ruby_version.satisfied_by?(system_ruby.gem_version) @@ -258,26 +255,6 @@ def ensure_specs_are_compatible! end end - def warn_on_incompatible_bundler_deps - bundler_version = Gem::Version.create(Bundler::VERSION) - @definition.specs.each do |spec| - spec.dependencies.each do |dep| - next if dep.type == :development - next unless dep.name == "bundler".freeze - next if dep.requirement.satisfied_by?(bundler_version) - - Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \ - " #{SharedHelpers.pretty_dependency(dep)}" \ - ", which is unsatisfied by the current bundler version #{VERSION}" \ - ", so the dependency is being ignored" - end - end - end - - def can_install_in_parallel? - true - end - def install_in_parallel(size, standalone, force = false) spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force) spec_installations.each do |installation| @@ -296,7 +273,7 @@ def create_bundle_path # returns whether or not a re-resolve was needed def resolve_if_needed(options) - if !@definition.unlocking? && !options["force"] && !options["all-platforms"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file? + if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file? return false if @definition.nothing_changed? && !@definition.missing_specs? end diff --git a/ruby/lib/bundler/installer/gem_installer.rb b/ruby/lib/bundler/installer/gem_installer.rb index 9689911d6..13a1356f5 100644 --- a/ruby/lib/bundler/installer/gem_installer.rb +++ b/ruby/lib/bundler/installer/gem_installer.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "shellwords" - module Bundler class GemInstaller attr_reader :spec, :standalone, :worker, :force, :installer @@ -15,50 +13,39 @@ def initialize(spec, installer, standalone = false, worker = 0, force = false) end def install_from_spec - post_install_message = spec_settings ? install_with_settings : install + post_install_message = install Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}" generate_executable_stubs return true, post_install_message - rescue Bundler::InstallHookError, Bundler::SecurityError, APIResponseMismatchError + rescue Bundler::InstallHookError, Bundler::SecurityError, Bundler::APIResponseMismatchError raise rescue Errno::ENOSPC return false, out_of_space_message - rescue StandardError => e + rescue Bundler::BundlerError, Gem::InstallError, Bundler::APIResponseInvalidDependenciesError => e return false, specific_failure_message(e) end - private + private def specific_failure_message(e) message = "#{e.class}: #{e.message}\n" - message += " " + e.backtrace.join("\n ") + "\n\n" if Bundler.ui.debug? + message += " " + e.backtrace.join("\n ") + "\n\n" message = message.lines.first + Bundler.ui.add_color(message.lines.drop(1).join, :clear) message + Bundler.ui.add_color(failure_message, :red) end def failure_message - return install_error_message if spec.source.options["git"] - "#{install_error_message}\n#{gem_install_message}" + install_error_message end def install_error_message "An error occurred while installing #{spec.name} (#{spec.version}), and Bundler cannot continue." end - def gem_install_message - source = spec.source - return unless source.respond_to?(:remotes) - - if source.remotes.size == 1 - "Make sure that `gem install #{spec.name} -v '#{spec.version}' --source '#{source.remotes.first}'` succeeds before bundling." - else - "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling." - end - end - def spec_settings # Fetch the build settings, if there are any if settings = Bundler.settings["build.#{spec.name}"] + require "shellwords" Shellwords.shellsplit(settings) end end @@ -67,11 +54,6 @@ def install spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone, :build_args => Array(spec_settings)) end - def install_with_settings - # Build arguments are global, so this is mutexed - Bundler.rubygems.install_with_build_args([spec_settings]) { install } - end - def out_of_space_message "#{install_error_message}\nYour disk is out of space. Free some space to be able to install your bundle." end diff --git a/ruby/lib/bundler/installer/parallel_installer.rb b/ruby/lib/bundler/installer/parallel_installer.rb index 391540af0..5b6680e5e 100644 --- a/ruby/lib/bundler/installer/parallel_installer.rb +++ b/ruby/lib/bundler/installer/parallel_installer.rb @@ -6,10 +6,11 @@ module Bundler class ParallelInstaller class SpecInstallation - attr_accessor :spec, :name, :post_install_message, :state, :error + attr_accessor :spec, :name, :full_name, :post_install_message, :state, :error def initialize(spec) @spec = spec @name = spec.name + @full_name = spec.full_name @state = :none @post_install_message = "" @error = nil @@ -27,13 +28,8 @@ def failed? state == :failed end - def installation_attempted? - installed? || failed? - end - - # Only true when spec in neither installed nor already enqueued def ready_to_enqueue? - !enqueued? && !installation_attempted? + state == :none end def has_post_install_message? @@ -54,14 +50,11 @@ def dependencies_installed?(all_specs) # Represents only the non-development dependencies, the ones that are # itself and are in the total list. def dependencies - @dependencies ||= begin - all_dependencies.reject {|dep| ignorable_dependency? dep } - end + @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep } end def missing_lockfile_dependencies(all_spec_names) - deps = all_dependencies.reject {|dep| ignorable_dependency? dep } - deps.reject {|dep| all_spec_names.include? dep.name } + dependencies.reject {|dep| all_spec_names.include? dep.name } end # Represents all dependencies @@ -70,7 +63,7 @@ def all_dependencies end def to_s - "#<#{self.class} #{@spec.full_name} (#{state})>" + "#<#{self.class} #{full_name} (#{state})>" end end @@ -93,18 +86,48 @@ def initialize(installer, all_specs, size, standalone, force) def call check_for_corrupt_lockfile + if @rake + do_install(@rake, 0) + Gem::Specification.reset + end + if @size > 1 install_with_worker else install_serially end - handle_error if @specs.any?(&:failed?) + check_for_unmet_dependencies + + handle_error if failed_specs.any? @specs ensure worker_pool && worker_pool.stop end + def check_for_unmet_dependencies + unmet_dependencies = @specs.map do |s| + [ + s, + s.dependencies.reject {|dep| @specs.any? {|spec| dep.matches_spec?(spec.spec) } }, + ] + end.reject {|a| a.last.empty? } + return if unmet_dependencies.empty? + + warning = [] + warning << "Your lockfile doesn't include a valid resolution." + warning << "You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies." + warning << "The unmet dependencies are:" + + unmet_dependencies.each do |spec, unmet_spec_dependencies| + unmet_spec_dependencies.each do |unmet_spec_dependency| + warning << "* #{unmet_spec_dependency}, depended upon #{spec.full_name}, unsatisfied by #{@specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }.full_name}" + end + end + + Bundler.ui.warn(warning.join("\n")) + end + def check_for_corrupt_lockfile missing_dependencies = @specs.map do |s| [ @@ -130,7 +153,11 @@ def check_for_corrupt_lockfile Bundler.ui.warn(warning.join("\n")) end - private + private + + def failed_specs + @specs.select(&:failed?) + end def install_with_worker enqueue_specs @@ -156,17 +183,13 @@ def do_install(spec_install, worker_num) gem_installer = Bundler::GemInstaller.new( spec_install.spec, @installer, @standalone, worker_num, @force ) - success, message = begin - gem_installer.install_from_spec - rescue RuntimeError => e - raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}" - end + success, message = gem_installer.install_from_spec if success spec_install.state = :installed spec_install.post_install_message = message unless message.nil? else - spec_install.state = :failed spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}" + spec_install.state = :failed end Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL, spec_install) spec_install @@ -190,11 +213,11 @@ def finished_installing? end def handle_error - errors = @specs.select(&:failed?).map(&:error) + errors = failed_specs.map(&:error) if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) } raise exception end - raise Bundler::InstallError, errors.map(&:to_s).join("\n\n") + raise Bundler::InstallError, errors.join("\n\n") end def require_tree_for_spec(spec) @@ -217,8 +240,6 @@ def require_tree_for_spec(spec) # are installed. def enqueue_specs @specs.select(&:ready_to_enqueue?).each do |spec| - next if @rake && !@rake.installed? && spec.name != @rake.name - if spec.dependencies_installed? @specs spec.state = :enqueued worker_pool.enq spec diff --git a/ruby/lib/bundler/installer/standalone.rb b/ruby/lib/bundler/installer/standalone.rb index e1beb25ad..e8494b4bc 100644 --- a/ruby/lib/bundler/installer/standalone.rb +++ b/ruby/lib/bundler/installer/standalone.rb @@ -3,7 +3,7 @@ module Bundler class Standalone def initialize(groups, definition) - @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym)) + @specs = definition.specs_for(groups) end def generate @@ -12,29 +12,31 @@ def generate end File.open File.join(bundler_path, "setup.rb"), "w" do |file| file.puts "require 'rbconfig'" - file.puts "ruby_engine = RUBY_ENGINE" - file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]" - file.puts "path = File.expand_path('..', __FILE__)" + file.puts reverse_rubygems_kernel_mixin paths.each do |path| - file.puts %($:.unshift "\#{path}/#{path}") + if Pathname.new(path).absolute? + file.puts %($:.unshift "#{path}") + else + file.puts %($:.unshift File.expand_path("\#{__dir__}/#{path}")) + end end end end - private + private def paths @specs.map do |spec| next if spec.name == "bundler" Array(spec.require_paths).map do |path| - gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}') + gem_path(path, spec).sub(version_dir, '#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}') # This is a static string intentionally. It's interpolated at a later time. end - end.flatten + end.flatten.compact end def version_dir - "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}" + "#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}" end def bundler_path @@ -43,10 +45,28 @@ def bundler_path def gem_path(path, spec) full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path) - Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s + if spec.source.instance_of?(Source::Path) + full_path + else + Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s + end rescue TypeError error_message = "#{spec.name} #{spec.version} has an invalid gemspec" raise Gem::InvalidSpecificationException.new(error_message) end + + def reverse_rubygems_kernel_mixin + <<~END + kernel = (class << ::Kernel; self; end) + [kernel, ::Kernel].each do |k| + if k.private_method_defined?(:gem_original_require) + private_require = k.private_method_defined?(:require) + k.send(:remove_method, :require) + k.send(:define_method, :require, k.instance_method(:gem_original_require)) + k.send(:private, :require) if private_require + end + end + END + end end end diff --git a/ruby/lib/bundler/lazy_specification.rb b/ruby/lib/bundler/lazy_specification.rb index 32c8bb955..fd7c8defd 100644 --- a/ruby/lib/bundler/lazy_specification.rb +++ b/ruby/lib/bundler/lazy_specification.rb @@ -4,22 +4,6 @@ module Bundler class LazySpecification - Identifier = Struct.new(:name, :version, :source, :platform, :dependencies) - class Identifier - include Comparable - def <=>(other) - return unless other.is_a?(Identifier) - [name, version, platform_string] <=> [other.name, other.version, other.platform_string] - end - - protected - - def platform_string - platform_string = platform.to_s - platform_string == Index::RUBY ? Index::NULL : platform_string - end - end - include MatchPlatform attr_reader :name, :version, :dependencies, :platform @@ -46,8 +30,32 @@ def ==(other) identifier == other.identifier end + def eql?(other) + identifier.eql?(other.identifier) + end + + def hash + identifier.hash + end + + ## + # Does this locked specification satisfy +dependency+? + # + # NOTE: Rubygems default requirement is ">= 0", which doesn't match + # prereleases of 0 versions, like "0.0.0.dev" or "0.0.0.SNAPSHOT". However, + # bundler users expect those to work. We need to make sure that Gemfile + # dependencies without explicit requirements (which use ">= 0" under the + # hood by default) are still valid for locked specs using this kind of + # versions. The method implements an ad-hoc fix for that. A better solution + # might be to change default rubygems requirement of dependencies to be ">= + # 0.A" but that's a major refactoring likely to break things. Hopefully we + # can attempt it in the future. + # + def satisfies?(dependency) - @name == dependency.name && dependency.requirement.satisfied_by?(Gem::Version.new(@version)) + effective_requirement = dependency.requirement == Gem::Requirement.default ? Gem::Requirement.new(">= 0.A") : dependency.requirement + + @name == dependency.name && effective_requirement.satisfied_by?(Gem::Version.new(@version)) end def to_lock @@ -68,17 +76,25 @@ def to_lock end def __materialize__ - search_object = Bundler.feature_flag.specific_platform? || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version) @specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name source.gemspec.tap {|s| s.source = source } else - search = source.specs.search(search_object).last - if search && Gem::Platform.new(search.platform) != Gem::Platform.new(platform) && !search.runtime_dependencies.-(dependencies.reject {|d| d.type == :development }).empty? - Bundler.ui.warn "Unable to use the platform-specific (#{search.platform}) version of #{name} (#{version}) " \ - "because it has different dependencies from the #{platform} version. " \ - "To use the platform-specific version of the gem, run `bundle config set specific_platform true` and install again." - search = source.specs.search(self).last + search_object = if source.is_a?(Source::Path) + Dependency.new(name, version) + else + ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version) + end + platform_object = Gem::Platform.new(platform) + candidates = source.specs.search(search_object) + same_platform_candidates = candidates.select do |spec| + MatchPlatform.platforms_match?(spec.platform, platform_object) end + installable_candidates = same_platform_candidates.select do |spec| + spec.is_a?(StubSpecification) || + (spec.required_ruby_version.satisfied_by?(Gem.ruby_version) && + spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version)) + end + search = installable_candidates.last search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)) search end @@ -97,7 +113,7 @@ def to_s end def identifier - @__identifier ||= Identifier.new(name, version, source, platform, dependencies) + @__identifier ||= [name, version, platform_string] end def git_version @@ -105,7 +121,14 @@ def git_version " #{source.revision[0..6]}" end - private + protected + + def platform_string + platform_string = platform.to_s + platform_string == Index::RUBY ? Index::NULL : platform_string + end + + private def to_ary nil @@ -118,5 +141,18 @@ def method_missing(method, *args, &blk) @specification.send(method, *args, &blk) end + + # + # For backwards compatibility with existing lockfiles, if the most specific + # locked platform is RUBY, we keep the previous behaviour of resolving the + # best platform variant at materiliazation time. For previous bundler + # versions (before 2.2.0) this was always the case (except when the lockfile + # only included non-ruby platforms), but we're also keeping this behaviour + # on newer bundlers unless users generate the lockfile from scratch or + # explicitly add a more specific platform. + # + def ruby_platform_materializes_to_ruby_platform? + !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform] + end end end diff --git a/ruby/lib/bundler/lockfile_generator.rb b/ruby/lib/bundler/lockfile_generator.rb index 585077d18..0578a93fd 100644 --- a/ruby/lib/bundler/lockfile_generator.rb +++ b/ruby/lib/bundler/lockfile_generator.rb @@ -25,7 +25,7 @@ def generate! out end - private + private def add_sources definition.send(:sources).lock_sources.each_with_index do |source, idx| @@ -71,7 +71,7 @@ def add_locked_ruby_version end def add_bundled_with - add_section("BUNDLED WITH", definition.locked_bundler_version.to_s) + add_section("BUNDLED WITH", Bundler::VERSION) end def add_section(name, value) diff --git a/ruby/lib/bundler/lockfile_parser.rb b/ruby/lib/bundler/lockfile_parser.rb index caabd524d..e074cbfc3 100644 --- a/ruby/lib/bundler/lockfile_parser.rb +++ b/ruby/lib/bundler/lockfile_parser.rb @@ -1,16 +1,5 @@ # frozen_string_literal: true -#-- -# Some versions of the Bundler 1.1 RC series introduced corrupted -# lockfiles. There were two major problems: -# -# * multiple copies of the same GIT section appeared in the lockfile -# * when this happened, those sections got multiple copies of gems -# in those sections. -# -# As a result, Bundler 1.1 contains code that fixes the earlier -# corruption. We will remove this fix-up code in Bundler 1.2. - module Bundler class LockfileParser attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version @@ -57,6 +46,16 @@ def self.sections_to_ignore(base_version = nil) attributes end + def self.bundled_with + lockfile = Bundler.default_lockfile + return unless lockfile.file? + + lockfile_contents = Bundler.read_file(lockfile) + return unless lockfile_contents.include?(BUNDLED) + + lockfile_contents.split(BUNDLED).last.strip + end + def initialize(lockfile) @platforms = [] @sources = [] @@ -64,8 +63,6 @@ def initialize(lockfile) @state = nil @specs = {} - @rubygems_aggregate = Source::Rubygems.new - if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/) raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \ "Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock." @@ -89,27 +86,14 @@ def initialize(lockfile) send("parse_#{@state}", line) end end - @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource? @specs = @specs.values.sort_by(&:identifier) - warn_for_outdated_bundler_version rescue ArgumentError => e Bundler.ui.debug(e) raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \ "and then `bundle install` to generate a new lockfile." end - def warn_for_outdated_bundler_version - return unless bundler_version - prerelease_text = bundler_version.prerelease? ? " --pre" : "" - current_version = Gem::Version.create(Bundler::VERSION) - return unless current_version < bundler_version - Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \ - "than the version that created the lockfile (#{bundler_version}). We suggest you to " \ - "upgrade to the version that created the lockfile by running `gem install " \ - "bundler:#{bundler_version}#{prerelease_text}`.\n" - end - - private + private TYPES = { GIT => Bundler::Source::Git, @@ -127,23 +111,11 @@ def parse_source(line) @sources << @current_source when GIT @current_source = TYPES[@type].from_lock(@opts) - # Strip out duplicate GIT sections - if @sources.include?(@current_source) - @current_source = @sources.find {|s| s == @current_source } - else - @sources << @current_source - end + @sources << @current_source when GEM - if Bundler.feature_flag.disable_multisource? - @opts["remotes"] = @opts.delete("remote") - @current_source = TYPES[@type].from_lock(@opts) - @sources << @current_source - else - Array(@opts["remote"]).each do |url| - @rubygems_aggregate.add_remote(url) - end - @current_source = @rubygems_aggregate - end + @opts["remotes"] = Array(@opts.delete("remote")).reverse + @current_source = TYPES[@type].from_lock(@opts) + @sources << @current_source when PLUGIN @current_source = Plugin.source_from_lock(@opts) @sources << @current_source @@ -221,10 +193,9 @@ def parse_spec(line) platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY @current_spec = LazySpecification.new(name, version, platform) @current_spec.source = @current_source + @current_source.add_dependency_names(name) - # Avoid introducing multiple copies of the same spec (caused by - # duplicate GIT sections) - @specs[@current_spec.identifier] ||= @current_spec + @specs[@current_spec.identifier] = @current_spec elsif spaces.size == 6 version = version.split(",").map(&:strip) if version dep = Gem::Dependency.new(name, version) diff --git a/ruby/lib/bundler/man/.document b/ruby/lib/bundler/man/.document new file mode 100644 index 000000000..fb66f13c3 --- /dev/null +++ b/ruby/lib/bundler/man/.document @@ -0,0 +1 @@ +# Ignore all files in this directory diff --git a/ruby/man/bundle-add.1 b/ruby/lib/bundler/man/bundle-add.1 similarity index 80% rename from ruby/man/bundle-add.1 rename to ruby/lib/bundler/man/bundle-add.1 index 8b7585910..6c462ba83 100644 --- a/ruby/man/bundle-add.1 +++ b/ruby/lib/bundler/man/bundle-add.1 @@ -1,13 +1,13 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-ADD" "1" "January 2020" "" "" +.TH "BUNDLE\-ADD" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install . .SH "SYNOPSIS" -\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-git=GIT] [\-\-branch=BRANCH] [\-\-skip\-install] [\-\-strict] [\-\-optimistic] +\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-git=GIT] [\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-skip\-install] [\-\-strict] [\-\-optimistic] . .SH "DESCRIPTION" Adds the named gem to the Gemfile and run \fBbundle install\fR\. \fBbundle install\fR can be avoided by using the flag \fB\-\-skip\-install\fR\. @@ -49,10 +49,18 @@ Specify the source for the added gem\. Specify the git source for the added gem\. . .TP +\fB\-\-github\fR +Specify the github source for the added gem\. +. +.TP \fB\-\-branch\fR Specify the git branch for the added gem\. . .TP +\fB\-\-ref\fR +Specify the git ref for the added gem\. +. +.TP \fB\-\-skip\-install\fR Adds the gem to the Gemfile but does not install it\. . diff --git a/ruby/lib/bundler/man/bundle-add.1.ronn b/ruby/lib/bundler/man/bundle-add.1.ronn new file mode 100644 index 000000000..6547297c8 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-add.1.ronn @@ -0,0 +1,52 @@ +bundle-add(1) -- Add gem to the Gemfile and run bundle install +================================================================ + +## SYNOPSIS + +`bundle add` [--group=GROUP] [--version=VERSION] [--source=SOURCE] [--git=GIT] [--github=GITHUB] [--branch=BRANCH] [--ref=REF] [--skip-install] [--strict] [--optimistic] + +## DESCRIPTION +Adds the named gem to the Gemfile and run `bundle install`. `bundle install` can be avoided by using the flag `--skip-install`. + +Example: + +bundle add rails + +bundle add rails --version "< 3.0, > 1.1" + +bundle add rails --version "~> 5.0.0" --source "https://gems.example.com" --group "development" + +bundle add rails --skip-install + +bundle add rails --group "development, test" + +## OPTIONS +* `--version`, `-v`: + Specify version requirements(s) for the added gem. + +* `--group`, `-g`: + Specify the group(s) for the added gem. Multiple groups should be separated by commas. + +* `--source`, , `-s`: + Specify the source for the added gem. + +* `--git`: + Specify the git source for the added gem. + +* `--github`: + Specify the github source for the added gem. + +* `--branch`: + Specify the git branch for the added gem. + +* `--ref`: + Specify the git ref for the added gem. + +* `--skip-install`: + Adds the gem to the Gemfile but does not install it. + +* `--optimistic`: + Adds optimistic declaration of version + +* `--strict`: + Adds strict declaration of version diff --git a/ruby/man/bundle-binstubs.1 b/ruby/lib/bundler/man/bundle-binstubs.1 similarity index 86% rename from ruby/man/bundle-binstubs.1 rename to ruby/lib/bundler/man/bundle-binstubs.1 index 4f9e5c0e3..6d1b1d424 100644 --- a/ruby/man/bundle-binstubs.1 +++ b/ruby/lib/bundler/man/bundle-binstubs.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-BINSTUBS" "1" "January 2020" "" "" +.TH "BUNDLE\-BINSTUBS" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems @@ -36,5 +36,7 @@ Makes binstubs that can work without depending on Rubygems or Bundler at runtime \fB\-\-shebang\fR Specify a different shebang executable name than the default (default \'ruby\') . -.SH "BUNDLE INSTALL \-\-BINSTUBS" -To create binstubs for all the gems in the bundle you can use the \fB\-\-binstubs\fR flag in bundle install(1) \fIbundle\-install\.1\.html\fR\. +.TP +\fB\-\-all\fR +Create binstubs for all gems in the bundle\. + diff --git a/ruby/lib/bundler/man/bundle-binstubs.1.ronn b/ruby/lib/bundler/man/bundle-binstubs.1.ronn new file mode 100644 index 000000000..a96186929 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-binstubs.1.ronn @@ -0,0 +1,41 @@ +bundle-binstubs(1) -- Install the binstubs of the listed gems +============================================================= + +## SYNOPSIS + +`bundle binstubs` [--force] [--path PATH] [--standalone] + +## DESCRIPTION + +Binstubs are scripts that wrap around executables. Bundler creates a +small Ruby file (a binstub) that loads Bundler, runs the command, +and puts it into `bin/`. Binstubs are a shortcut-or alternative- +to always using `bundle exec`. This gives you a file that can be run +directly, and one that will always run the correct gem version +used by the application. + +For example, if you run `bundle binstubs rspec-core`, Bundler will create +the file `bin/rspec`. That file will contain enough code to load Bundler, +tell it to load the bundled gems, and then run rspec. + +This command generates binstubs for executables in `GEM_NAME`. +Binstubs are put into `bin`, or the `--path` directory if one has been set. +Calling binstubs with [GEM [GEM]] will create binstubs for all given gems. + +## OPTIONS + +* `--force`: + Overwrite existing binstubs if they exist. + +* `--path`: + The location to install the specified binstubs to. This defaults to `bin`. + +* `--standalone`: + Makes binstubs that can work without depending on Rubygems or Bundler at + runtime. + +* `--shebang`: + Specify a different shebang executable name than the default (default 'ruby') + +* `--all`: + Create binstubs for all gems in the bundle. diff --git a/ruby/man/bundle-cache.1 b/ruby/lib/bundler/man/bundle-cache.1 similarity index 98% rename from ruby/man/bundle-cache.1 rename to ruby/lib/bundler/man/bundle-cache.1 index cb376777f..acbdae0df 100644 --- a/ruby/man/bundle-cache.1 +++ b/ruby/lib/bundler/man/bundle-cache.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CACHE" "1" "January 2020" "" "" +.TH "BUNDLE\-CACHE" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application diff --git a/ruby/man/bundle-cache.ronn b/ruby/lib/bundler/man/bundle-cache.1.ronn similarity index 100% rename from ruby/man/bundle-cache.ronn rename to ruby/lib/bundler/man/bundle-cache.1.ronn diff --git a/ruby/man/bundle-check.1 b/ruby/lib/bundler/man/bundle-check.1 similarity index 95% rename from ruby/man/bundle-check.1 rename to ruby/lib/bundler/man/bundle-check.1 index aba5b6634..e555c9b39 100644 --- a/ruby/man/bundle-check.1 +++ b/ruby/lib/bundler/man/bundle-check.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CHECK" "1" "January 2020" "" "" +.TH "BUNDLE\-CHECK" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems diff --git a/ruby/man/bundle-check.ronn b/ruby/lib/bundler/man/bundle-check.1.ronn similarity index 100% rename from ruby/man/bundle-check.ronn rename to ruby/lib/bundler/man/bundle-check.1.ronn diff --git a/ruby/man/bundle-clean.1 b/ruby/lib/bundler/man/bundle-clean.1 similarity index 92% rename from ruby/man/bundle-clean.1 rename to ruby/lib/bundler/man/bundle-clean.1 index cc5c8e86d..d40324752 100644 --- a/ruby/man/bundle-clean.1 +++ b/ruby/lib/bundler/man/bundle-clean.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CLEAN" "1" "January 2020" "" "" +.TH "BUNDLE\-CLEAN" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory diff --git a/ruby/man/bundle-clean.ronn b/ruby/lib/bundler/man/bundle-clean.1.ronn similarity index 100% rename from ruby/man/bundle-clean.ronn rename to ruby/lib/bundler/man/bundle-clean.1.ronn diff --git a/ruby/man/bundle-config.1 b/ruby/lib/bundler/man/bundle-config.1 similarity index 84% rename from ruby/man/bundle-config.1 rename to ruby/lib/bundler/man/bundle-config.1 index c3464fb2e..5c07e227f 100644 --- a/ruby/man/bundle-config.1 +++ b/ruby/lib/bundler/man/bundle-config.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CONFIG" "1" "January 2020" "" "" +.TH "BUNDLE\-CONFIG" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options @@ -16,7 +16,7 @@ This command allows you to interact with Bundler\'s configuration system\. Bundler loads configuration settings in this order: . .IP "1." 4 -Local config (\fBapp/\.bundle/config\fR) +Local config (\fB/\.bundle/config\fR or \fB$BUNDLE_APP_CONFIG/config\fR) . .IP "2." 4 Environmental variables (\fBENV\fR) @@ -42,7 +42,7 @@ Executing \fBbundle config set \fR will set that configuration to Executing \fBbundle config set \-\-global \fR works the same as above\. . .P -Executing \fBbundle config set \-\-local \fR will set that configuration to the local application\. The configuration will be stored in \fBapp/\.bundle/config\fR\. +Executing \fBbundle config set \-\-local \fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\. . .P Executing \fBbundle config unset \fR will delete the configuration in both local and global sources\. @@ -56,14 +56,11 @@ Executing \fBbundle config unset \-\-local \fR will delete the con .P Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. . -.P -Executing \fBbundle config set disable_multisource true\fR upgrades the warning about the Gemfile containing multiple primary sources to an error\. Executing \fBbundle config unset disable_multisource\fR downgrades this error to a warning\. -. .SH "REMEMBERING OPTIONS" Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\. . .P -However, this will be changed in bundler 3, so it\'s better not to rely on this behavior\. If these options must be remembered, it\'s better to set them using \fBbundle config\fR (e\.g\., \fBbundle config set path foo\fR)\. +However, this will be changed in bundler 3, so it\'s better not to rely on this behavior\. If these options must be remembered, it\'s better to set them using \fBbundle config\fR (e\.g\., \fBbundle config set \-\-local path foo\fR)\. . .P The options that can be configured are: @@ -111,7 +108,7 @@ Since the specific location of that executable can change from machine to machin . .nf -bundle config set build\.mysql \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config +bundle config set \-\-global build\.mysql \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config . .fi . @@ -136,9 +133,6 @@ Any periods in the configuration keys must be replaced with two underscores when The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\. . .IP "\(bu" 4 -\fBallow_bundler_dependency_conflicts\fR (\fBBUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS\fR): Allow resolving to specifications that have dependencies on \fBbundler\fR that are incompatible with the running Bundler version\. -. -.IP "\(bu" 4 \fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR . .IP "\(bu" 4 @@ -154,7 +148,7 @@ The following is a list of all configuration keys and their purpose\. You can le \fBbin\fR (\fBBUNDLE_BIN\fR): Install executables from gems in the bundle to the specified directory\. Defaults to \fBfalse\fR\. . .IP "\(bu" 4 -\fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR): Cache all gems, including path and git gems\. +\fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR): Cache all gems, including path and git gems\. This needs to be explicitly configured on bundler 1 and bundler 2, but will be the default on bundler 3\. . .IP "\(bu" 4 \fBcache_all_platforms\fR (\fBBUNDLE_CACHE_ALL_PLATFORMS\fR): Cache gems for all platforms\. @@ -184,10 +178,7 @@ The following is a list of all configuration keys and their purpose\. You can le \fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\. . .IP "\(bu" 4 -\fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\. -. -.IP "\(bu" 4 -\fBdisable_platform_warnings\fR (\fBBUNDLE_DISABLE_PLATFORM_WARNINGS\fR): Disable warnings during bundle install when a dependency is unused on the current platform\. +\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\. . .IP "\(bu" 4 \fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\. @@ -202,6 +193,9 @@ The following is a list of all configuration keys and their purpose\. You can le \fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\. Defaults to \fBtrue\fR when \fB\-\-deployment\fR is used\. . .IP "\(bu" 4 +\fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR): Sets a GitHub username or organization to be used in \fBREADME\fR file when you create a new gem via \fBbundle gem\fR command\. It can be overridden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\. +. +.IP "\(bu" 4 \fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\. . .IP "\(bu" 4 @@ -214,10 +208,10 @@ The following is a list of all configuration keys and their purpose\. You can le \fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR): When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\. . .IP "\(bu" 4 -\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR) Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\. +\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\. . .IP "\(bu" 4 -\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to 1\. +\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to the number of available processors\. . .IP "\(bu" 4 \fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\. @@ -226,9 +220,6 @@ The following is a list of all configuration keys and their purpose\. You can le \fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\. . .IP "\(bu" 4 -\fBonly_update_to_newer_versions\fR (\fBBUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS\fR): During \fBbundle update\fR, only resolve to newer versions of the gems in the lockfile\. -. -.IP "\(bu" 4 \fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. Defaults to \fBGem\.dir\fR\. When \-\-deployment is used, defaults to vendor/bundle\. . .IP "\(bu" 4 @@ -244,7 +235,7 @@ The following is a list of all configuration keys and their purpose\. You can le \fBprefer_patch\fR (BUNDLE_PREFER_PATCH): Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\. . .IP "\(bu" 4 -\fBprint_only_version_number\fR (\fBBUNDLE_PRINT_ONLY_VERSION_NUMBER\fR) Print only version number from \fBbundler \-\-version\fR\. +\fBprint_only_version_number\fR (\fBBUNDLE_PRINT_ONLY_VERSION_NUMBER\fR): Print only version number from \fBbundler \-\-version\fR\. . .IP "\(bu" 4 \fBredirect\fR (\fBBUNDLE_REDIRECT\fR): The number of redirects allowed for network requests\. Defaults to \fB5\fR\. @@ -265,12 +256,6 @@ The following is a list of all configuration keys and their purpose\. You can le \fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR): Silence the warning Bundler prints when installing gems as root\. . .IP "\(bu" 4 -\fBskip_default_git_sources\fR (\fBBUNDLE_SKIP_DEFAULT_GIT_SOURCES\fR): Whether Bundler should skip adding default git source shortcuts to the Gemfile DSL\. -. -.IP "\(bu" 4 -\fBspecific_platform\fR (\fBBUNDLE_SPECIFIC_PLATFORM\fR): Allow bundler to resolve for the specific running platform and store it in the lockfile, instead of only using a generic platform\. A specific platform is the exact platform triple reported by \fBGem::Platform\.local\fR, such as \fBx86_64\-darwin\-16\fR or \fBuniversal\-java\-1\.8\fR\. On the other hand, generic platforms are those such as \fBruby\fR, \fBmswin\fR, or \fBjava\fR\. In this example, \fBx86_64\-darwin\-16\fR would map to \fBruby\fR and \fBuniversal\-java\-1\.8\fR to \fBjava\fR\. -. -.IP "\(bu" 4 \fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR): Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\. . .IP "\(bu" 4 @@ -289,10 +274,7 @@ The following is a list of all configuration keys and their purpose\. You can le \fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\. . .IP "\(bu" 4 -\fBunlock_source_unlocks_spec\fR (\fBBUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC\fR): Whether running \fBbundle update \-\-source NAME\fR unlocks a gem with the given name\. Defaults to \fBtrue\fR\. -. -.IP "\(bu" 4 -\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR) Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\. +\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\. . .IP "\(bu" 4 \fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\. @@ -318,7 +300,7 @@ Bundler also allows you to work against a git repository locally instead of usin . .nf -bundle config set local\.GEM_NAME /path/to/local/git/repository +bundle config set \-\-local local\.GEM_NAME /path/to/local/git/repository . .fi . @@ -331,7 +313,7 @@ For example, in order to use a local Rack repository, a developer could call: . .nf -bundle config set local\.rack ~/Work/git/rack +bundle config set \-\-local local\.rack ~/Work/git/rack . .fi . @@ -353,7 +335,7 @@ Bundler supports overriding gem sources with mirrors\. This allows you to config . .nf -bundle config set mirror\.SOURCE_URL MIRROR_URL +bundle config set \-\-global mirror\.SOURCE_URL MIRROR_URL . .fi . @@ -366,7 +348,7 @@ For example, to use a mirror of rubygems\.org hosted at rubygems\-mirror\.org: . .nf -bundle config set mirror\.http://rubygems\.org http://rubygems\-mirror\.org +bundle config set \-\-global mirror\.http://rubygems\.org http://rubygems\-mirror\.org . .fi . @@ -379,7 +361,7 @@ Each mirror also provides a fallback timeout setting\. If the mirror does not re . .nf -bundle config set mirror\.SOURCE_URL\.fallback_timeout TIMEOUT +bundle config set \-\-global mirror\.SOURCE_URL\.fallback_timeout TIMEOUT . .fi . @@ -392,7 +374,7 @@ For example, to fall back to rubygems\.org after 3 seconds: . .nf -bundle config set mirror\.https://rubygems\.org\.fallback_timeout 3 +bundle config set \-\-global mirror\.https://rubygems\.org\.fallback_timeout 3 . .fi . @@ -408,7 +390,7 @@ Bundler allows you to configure credentials for any gem source, which allows you . .nf -bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD +bundle config set \-\-global SOURCE_HOSTNAME USERNAME:PASSWORD . .fi . @@ -421,7 +403,7 @@ For example, to save the credentials of user \fBclaudette\fR for the gem source . .nf -bundle config set gems\.longerous\.com claudette:s00pers3krit +bundle config set \-\-global gems\.longerous\.com claudette:s00pers3krit . .fi . @@ -447,7 +429,7 @@ For gems with a git source with HTTP(S) URL you can specify credentials like so: . .nf -bundle config set https://github\.com/bundler/bundler\.git username:password +bundle config set \-\-global https://github\.com/rubygems/rubygems\.git username:password . .fi . @@ -467,7 +449,7 @@ export BUNDLE_GITHUB__COM=username:password .IP "" 0 . .P -This is especially useful for private repositories on hosts such as Github, where you can use personal OAuth tokens: +This is especially useful for private repositories on hosts such as GitHub, where you can use personal OAuth tokens: . .IP "" 4 . @@ -479,6 +461,23 @@ export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic . .IP "" 0 . +.P +Note that any configured credentials will be redacted by informative commands such as \fBbundle config list\fR or \fBbundle config get\fR, unless you use the \fB\-\-parseable\fR flag\. This is to avoid unintentionally leaking credentials when copy\-pasting bundler output\. +. +.P +Also note that to guarantee a sane mapping between valid environment variable names and valid host names, bundler makes the following transformations: +. +.IP "\(bu" 4 +Any \fB\-\fR characters in a host name are mapped to a triple dash (\fB___\fR) in the corresponding environment variable\. +. +.IP "\(bu" 4 +Any \fB\.\fR characters in a host name are mapped to a double dash (\fB__\fR) in the corresponding environment variable\. +. +.IP "" 0 +. +.P +This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you\'ll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\. +. .SH "CONFIGURE BUNDLER DIRECTORIES" Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values . diff --git a/ruby/lib/bundler/man/bundle-config.1.ronn b/ruby/lib/bundler/man/bundle-config.1.ronn new file mode 100644 index 000000000..a21aa027a --- /dev/null +++ b/ruby/lib/bundler/man/bundle-config.1.ronn @@ -0,0 +1,396 @@ +bundle-config(1) -- Set bundler configuration options +===================================================== + +## SYNOPSIS + +`bundle config` [list|get|set|unset] [ []] + +## DESCRIPTION + +This command allows you to interact with Bundler's configuration system. + +Bundler loads configuration settings in this order: + +1. Local config (`/.bundle/config` or `$BUNDLE_APP_CONFIG/config`) +2. Environmental variables (`ENV`) +3. Global config (`~/.bundle/config`) +4. Bundler default config + +Executing `bundle config list` with will print a list of all bundler +configuration for the current bundle, and where that configuration +was set. + +Executing `bundle config get ` will print the value of that configuration +setting, and where it was set. + +Executing `bundle config set ` will set that configuration to the +value specified for all bundles executed as the current user. The configuration +will be stored in `~/.bundle/config`. If already is set, will be +overridden and user will be warned. + +Executing `bundle config set --global ` works the same as above. + +Executing `bundle config set --local ` will set that configuration +in the directory for the local application. The configuration will be stored in +`/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration +will be stored in `$BUNDLE_APP_CONFIG/config`. + +Executing `bundle config unset ` will delete the configuration in both +local and global sources. + +Executing `bundle config unset --global ` will delete the configuration +only from the user configuration. + +Executing `bundle config unset --local ` will delete the +configuration only from the local application. + +Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will +cause it to ignore all configuration. + +## REMEMBERING OPTIONS + +Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or +`--without production`, are remembered between commands and saved to your local +application's configuration (normally, `./.bundle/config`). + +However, this will be changed in bundler 3, so it's better not to rely on this +behavior. If these options must be remembered, it's better to set them using +`bundle config` (e.g., `bundle config set --local path foo`). + +The options that can be configured are: + +* `bin`: + Creates a directory (defaults to `~/bin`) and place any executables from the + gem there. These executables run in Bundler's context. If used, you might add + this directory to your environment's `PATH` variable. For instance, if the + `rails` gem comes with a `rails` executable, this flag will create a + `bin/rails` executable that ensures that all referred dependencies will be + resolved using the bundled gems. + +* `deployment`: + In deployment mode, Bundler will 'roll-out' the bundle for + `production` use. Please check carefully if you want to have this option + enabled in `development` or `test` environments. + +* `path`: + The location to install the specified gems to. This defaults to Rubygems' + setting. Bundler shares this location with Rubygems, `gem install ...` will + have gem installed there, too. Therefore, gems installed without a + `--path ...` setting will show up by calling `gem list`. Accordingly, gems + installed to other locations will not get listed. + +* `without`: + A space-separated list of groups referencing gems to skip during installation. + +* `with`: + A space-separated list of groups referencing gems to include during installation. + +## BUILD OPTIONS + +You can use `bundle config` to give Bundler the flags to pass to the gem +installer every time bundler tries to install a particular gem. + +A very common example, the `mysql` gem, requires Snow Leopard users to +pass configuration flags to `gem install` to specify where to find the +`mysql_config` executable. + + gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config + +Since the specific location of that executable can change from machine +to machine, you can specify these flags on a per-machine basis. + + bundle config set --global build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config + +After running this command, every time bundler needs to install the +`mysql` gem, it will pass along the flags you specified. + +## CONFIGURATION KEYS + +Configuration keys in bundler have two forms: the canonical form and the +environment variable form. + +For instance, passing the `--without` flag to [bundle install(1)](bundle-install.1.html) +prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler +persists this value in `app/.bundle/config` so that calls to `Bundler.setup` +do not try to find gems from the `Gemfile` that you didn't install. Additionally, +subsequent calls to [bundle install(1)](bundle-install.1.html) remember this setting +and skip those groups. + +The canonical form of this configuration is `"without"`. To convert the canonical +form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The +environment variable form of `"without"` is `BUNDLE_WITHOUT`. + +Any periods in the configuration keys must be replaced with two underscores when +setting it via environment variables. The configuration key `local.rack` becomes +the environment variable `BUNDLE_LOCAL__RACK`. + +## LIST OF AVAILABLE KEYS + +The following is a list of all configuration keys and their purpose. You can +learn more about their operation in [bundle install(1)](bundle-install.1.html). + +* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`): + When in deployment mode, allow changing the credentials to a gem's source. + Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path` +* `allow_offline_install` (`BUNDLE_ALLOW_OFFLINE_INSTALL`): + Allow Bundler to use cached data when installing without network access. +* `auto_clean_without_path` (`BUNDLE_AUTO_CLEAN_WITHOUT_PATH`): + Automatically run `bundle clean` after installing when an explicit `path` + has not been set and Bundler is not installing into the system gems. +* `auto_install` (`BUNDLE_AUTO_INSTALL`): + Automatically run `bundle install` when gems are missing. +* `bin` (`BUNDLE_BIN`): + Install executables from gems in the bundle to the specified directory. + Defaults to `false`. +* `cache_all` (`BUNDLE_CACHE_ALL`): + Cache all gems, including path and git gems. This needs to be explicitly + configured on bundler 1 and bundler 2, but will be the default on bundler 3. +* `cache_all_platforms` (`BUNDLE_CACHE_ALL_PLATFORMS`): + Cache gems for all platforms. +* `cache_path` (`BUNDLE_CACHE_PATH`): + The directory that bundler will place cached gems in when running + bundle package, and that bundler will look in when installing gems. + Defaults to `vendor/cache`. +* `clean` (`BUNDLE_CLEAN`): + Whether Bundler should run `bundle clean` automatically after + `bundle install`. +* `console` (`BUNDLE_CONSOLE`): + The console that `bundle console` starts. Defaults to `irb`. +* `default_install_uses_path` (`BUNDLE_DEFAULT_INSTALL_USES_PATH`): + Whether a `bundle install` without an explicit `--path` argument defaults + to installing gems in `.bundle`. +* `deployment` (`BUNDLE_DEPLOYMENT`): + Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the + lockfile has not been updated, running Bundler commands will be blocked. +* `disable_checksum_validation` (`BUNDLE_DISABLE_CHECKSUM_VALIDATION`): + Allow installing gems even if they do not match the checksum provided by + RubyGems. +* `disable_exec_load` (`BUNDLE_DISABLE_EXEC_LOAD`): + Stop Bundler from using `load` to launch an executable in-process in + `bundle exec`. +* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`): + Allow Bundler to use a local git override without a branch specified in the + Gemfile. +* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`): + Allow Bundler to use a local git override without checking if the revision + present in the lockfile is present in the repository. +* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`): + Stop Bundler from accessing gems installed to RubyGems' normal location. +* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`): + Stop Bundler from checking if a newer Bundler version is available on + rubygems.org. +* `force_ruby_platform` (`BUNDLE_FORCE_RUBY_PLATFORM`): + Ignore the current machine's platform and install only `ruby` platform gems. + As a result, gems with native extensions will be compiled from source. +* `frozen` (`BUNDLE_FROZEN`): + Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the + lockfile has not been updated, running Bundler commands will be blocked. + Defaults to `true` when `--deployment` is used. +* `gem.github_username` (`BUNDLE_GEM__GITHUB_USERNAME`): + Sets a GitHub username or organization to be used in `README` file when you + create a new gem via `bundle gem` command. It can be overridden by passing an + explicit `--github-username` flag to `bundle gem`. +* `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`): + Sets the `--key` parameter for `gem push` when using the `rake release` + command with a private gemstash server. +* `gemfile` (`BUNDLE_GEMFILE`): + The name of the file that bundler should use as the `Gemfile`. This location + of this file also sets the root of the project, which is used to resolve + relative paths in the `Gemfile`, among other things. By default, bundler + will search up from the current working directory until it finds a + `Gemfile`. +* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`): + Whether Bundler should cache all gems globally, rather than locally to the + installing Ruby installation. +* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`): + When set, no post install messages will be printed. To silence a single gem, + use dot notation like `ignore_messages.httparty true`. +* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`): + Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`. +* `jobs` (`BUNDLE_JOBS`): + The number of gems Bundler can install in parallel. Defaults to the number of + available processors. +* `no_install` (`BUNDLE_NO_INSTALL`): + Whether `bundle package` should skip installing gems. +* `no_prune` (`BUNDLE_NO_PRUNE`): + Whether Bundler should leave outdated gems unpruned when caching. +* `path` (`BUNDLE_PATH`): + The location on disk where all gems in your bundle will be located regardless + of `$GEM_HOME` or `$GEM_PATH` values. Bundle gems not found in this location + will be installed by `bundle install`. Defaults to `Gem.dir`. When --deployment + is used, defaults to vendor/bundle. +* `path.system` (`BUNDLE_PATH__SYSTEM`): + Whether Bundler will install gems into the default system path (`Gem.dir`). +* `path_relative_to_cwd` (`BUNDLE_PATH_RELATIVE_TO_CWD`) + Makes `--path` relative to the CWD instead of the `Gemfile`. +* `plugins` (`BUNDLE_PLUGINS`): + Enable Bundler's experimental plugin system. +* `prefer_patch` (BUNDLE_PREFER_PATCH): + Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`. +* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`): + Print only version number from `bundler --version`. +* `redirect` (`BUNDLE_REDIRECT`): + The number of redirects allowed for network requests. Defaults to `5`. +* `retry` (`BUNDLE_RETRY`): + The number of times to retry failed network requests. Defaults to `3`. +* `setup_makes_kernel_gem_public` (`BUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC`): + Have `Bundler.setup` make the `Kernel#gem` method public, even though + RubyGems declares it as private. +* `shebang` (`BUNDLE_SHEBANG`): + The program name that should be invoked for generated binstubs. Defaults to + the ruby install name used to generate the binstub. +* `silence_deprecations` (`BUNDLE_SILENCE_DEPRECATIONS`): + Whether Bundler should silence deprecation warnings for behavior that will + be changed in the next major version. +* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`): + Silence the warning Bundler prints when installing gems as root. +* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`): + Path to a designated CA certificate file or folder containing multiple + certificates for trusted CAs in PEM format. +* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`): + Path to a designated file containing a X.509 client certificate + and key in PEM format. +* `ssl_verify_mode` (`BUNDLE_SSL_VERIFY_MODE`): + The SSL verification mode Bundler uses when making HTTPS requests. + Defaults to verify peer. +* `suppress_install_using_messages` (`BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES`): + Avoid printing `Using ...` messages during installation when the version of + a gem has not changed. +* `system_bindir` (`BUNDLE_SYSTEM_BINDIR`): + The location where RubyGems installs binstubs. Defaults to `Gem.bindir`. +* `timeout` (`BUNDLE_TIMEOUT`): + The seconds allowed before timing out for network requests. Defaults to `10`. +* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`): + Require passing `--all` to `bundle update` when everything should be updated, + and disallow passing no options to `bundle update`. +* `user_agent` (`BUNDLE_USER_AGENT`): + The custom user agent fragment Bundler includes in API requests. +* `with` (`BUNDLE_WITH`): + A `:`-separated list of groups whose gems bundler should install. +* `without` (`BUNDLE_WITHOUT`): + A `:`-separated list of groups whose gems bundler should not install. + +In general, you should set these settings per-application by using the applicable +flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command. + +You can set them globally either via environment variables or `bundle config`, +whichever is preferable for your setup. If you use both, environment variables +will take preference over global settings. + +## LOCAL GIT REPOS + +Bundler also allows you to work against a git repository locally +instead of using the remote version. This can be achieved by setting +up a local override: + + bundle config set --local local.GEM_NAME /path/to/local/git/repository + +For example, in order to use a local Rack repository, a developer could call: + + bundle config set --local local.rack ~/Work/git/rack + +Now instead of checking out the remote git repository, the local +override will be used. Similar to a path source, every time the local +git repository change, changes will be automatically picked up by +Bundler. This means a commit in the local git repo will update the +revision in the `Gemfile.lock` to the local git repo revision. This +requires the same attention as git submodules. Before pushing to +the remote, you need to ensure the local override was pushed, otherwise +you may point to a commit that only exists in your local machine. +You'll also need to CGI escape your usernames and passwords as well. + +Bundler does many checks to ensure a developer won't work with +invalid references. Particularly, we force a developer to specify +a branch in the `Gemfile` in order to use this feature. If the branch +specified in the `Gemfile` and the current branch in the local git +repository do not match, Bundler will abort. This ensures that +a developer is always working against the correct branches, and prevents +accidental locking to a different branch. + +Finally, Bundler also ensures that the current revision in the +`Gemfile.lock` exists in the local git repository. By doing this, Bundler +forces you to fetch the latest changes in the remotes. + +## MIRRORS OF GEM SOURCES + +Bundler supports overriding gem sources with mirrors. This allows you to +configure rubygems.org as the gem source in your Gemfile while still using your +mirror to fetch gems. + + bundle config set --global mirror.SOURCE_URL MIRROR_URL + +For example, to use a mirror of rubygems.org hosted at rubygems-mirror.org: + + bundle config set --global mirror.http://rubygems.org http://rubygems-mirror.org + +Each mirror also provides a fallback timeout setting. If the mirror does not +respond within the fallback timeout, Bundler will try to use the original +server instead of the mirror. + + bundle config set --global mirror.SOURCE_URL.fallback_timeout TIMEOUT + +For example, to fall back to rubygems.org after 3 seconds: + + bundle config set --global mirror.https://rubygems.org.fallback_timeout 3 + +The default fallback timeout is 0.1 seconds, but the setting can currently +only accept whole seconds (for example, 1, 15, or 30). + +## CREDENTIALS FOR GEM SOURCES + +Bundler allows you to configure credentials for any gem source, which allows +you to avoid putting secrets into your Gemfile. + + bundle config set --global SOURCE_HOSTNAME USERNAME:PASSWORD + +For example, to save the credentials of user `claudette` for the gem source at +`gems.longerous.com`, you would run: + + bundle config set --global gems.longerous.com claudette:s00pers3krit + +Or you can set the credentials as an environment variable like this: + + export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit" + +For gems with a git source with HTTP(S) URL you can specify credentials like so: + + bundle config set --global https://github.com/rubygems/rubygems.git username:password + +Or you can set the credentials as an environment variable like so: + + export BUNDLE_GITHUB__COM=username:password + +This is especially useful for private repositories on hosts such as GitHub, +where you can use personal OAuth tokens: + + export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic + +Note that any configured credentials will be redacted by informative commands +such as `bundle config list` or `bundle config get`, unless you use the +`--parseable` flag. This is to avoid unintentionally leaking credentials when +copy-pasting bundler output. + +Also note that to guarantee a sane mapping between valid environment variable +names and valid host names, bundler makes the following transformations: + +* Any `-` characters in a host name are mapped to a triple dash (`___`) in the + corresponding environment variable. + +* Any `.` characters in a host name are mapped to a double dash (`__`) in the + corresponding environment variable. + +This means that if you have a gem server named `my.gem-host.com`, you'll need to +use the `BUNDLE_MY__GEM___HOST__COM` variable to configure credentials for it +through ENV. + +## CONFIGURE BUNDLER DIRECTORIES + +Bundler's home, config, cache and plugin directories are able to be configured +through environment variables. The default location for Bundler's home directory is +`~/.bundle`, which all directories inherit from by default. The following +outlines the available environment variables and their default values + + BUNDLE_USER_HOME : $HOME/.bundle + BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache + BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config + BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin diff --git a/ruby/man/bundle-doctor.1 b/ruby/lib/bundler/man/bundle-doctor.1 similarity index 95% rename from ruby/man/bundle-doctor.1 rename to ruby/lib/bundler/man/bundle-doctor.1 index 344c40066..87a7fe5f2 100644 --- a/ruby/man/bundle-doctor.1 +++ b/ruby/lib/bundler/man/bundle-doctor.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-DOCTOR" "1" "January 2020" "" "" +.TH "BUNDLE\-DOCTOR" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems diff --git a/ruby/man/bundle-doctor.ronn b/ruby/lib/bundler/man/bundle-doctor.1.ronn similarity index 100% rename from ruby/man/bundle-doctor.ronn rename to ruby/lib/bundler/man/bundle-doctor.1.ronn diff --git a/ruby/man/bundle-exec.1 b/ruby/lib/bundler/man/bundle-exec.1 similarity index 99% rename from ruby/man/bundle-exec.1 rename to ruby/lib/bundler/man/bundle-exec.1 index 555819a5b..69adfa7c9 100644 --- a/ruby/man/bundle-exec.1 +++ b/ruby/lib/bundler/man/bundle-exec.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-EXEC" "1" "January 2020" "" "" +.TH "BUNDLE\-EXEC" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle diff --git a/ruby/man/bundle-exec.ronn b/ruby/lib/bundler/man/bundle-exec.1.ronn similarity index 100% rename from ruby/man/bundle-exec.ronn rename to ruby/lib/bundler/man/bundle-exec.1.ronn diff --git a/ruby/lib/bundler/man/bundle-gem.1 b/ruby/lib/bundler/man/bundle-gem.1 new file mode 100644 index 000000000..fae5c34e7 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-gem.1 @@ -0,0 +1,115 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "BUNDLE\-GEM" "1" "December 2021" "" "" +. +.SH "NAME" +\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem +. +.SH "SYNOPSIS" +\fBbundle gem\fR \fIGEM_NAME\fR \fIOPTIONS\fR +. +.SH "DESCRIPTION" +Generates a directory named \fBGEM_NAME\fR with a \fBRakefile\fR, \fBGEM_NAME\.gemspec\fR, and other supporting files and directories that can be used to develop a rubygem with that name\. +. +.P +Run \fBrake \-T\fR in the resulting project for a list of Rake tasks that can be used to test and publish the gem to rubygems\.org\. +. +.P +The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler\'s global configuration file using the following names: +. +.IP "\(bu" 4 +\fBgem\.coc\fR +. +.IP "\(bu" 4 +\fBgem\.mit\fR +. +.IP "\(bu" 4 +\fBgem\.test\fR +. +.IP "" 0 +. +.SH "OPTIONS" +. +.TP +\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR +Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\. +. +.TP +\fB\-\-no\-exe\fR +Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\. +. +.TP +\fB\-\-coc\fR +Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. +. +.TP +\fB\-\-no\-coc\fR +Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\. +. +.TP +\fB\-\-ext\fR +Add boilerplate for C extension code to the generated project\. This behavior is disabled by default\. +. +.TP +\fB\-\-no\-ext\fR +Do not add C extension code (overrides \fB\-\-ext\fR specified in the global config)\. +. +.TP +\fB\-\-mit\fR +Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. +. +.TP +\fB\-\-no\-mit\fR +Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\. +. +.TP +\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR, \fB\-\-test=test\-unit\fR +Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR, \fBrspec\fR and \fBtest\-unit\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. Given no option is specified: +. +.IP +When Bundler is configured to generate tests, this defaults to Bundler\'s global config setting \fBgem\.test\fR\. +. +.IP +When Bundler is configured to not generate tests, an interactive prompt will be displayed and the answer will be used for the current rubygem project\. +. +.IP +When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. +. +.TP +\fB\-\-ci\fR, \fB\-\-ci=github\fR, \fB\-\-ci=travis\fR, \fB\-\-ci=gitlab\fR, \fB\-\-ci=circle\fR +Specify the continuous integration service that Bundler should use when generating the project\. Acceptable values are \fBgithub\fR, \fBtravis\fR, \fBgitlab\fR and \fBcircle\fR\. A configuration file will be generated in the project directory\. Given no option is specified: +. +.IP +When Bundler is configured to generate CI files, this defaults to Bundler\'s global config setting \fBgem\.ci\fR\. +. +.IP +When Bundler is configured to not generate CI files, an interactive prompt will be displayed and the answer will be used for the current rubygem project\. +. +.IP +When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. +. +.TP +\fB\-\-linter\fR, \fB\-\-linter=rubocop\fR, \fB\-\-linter=standard\fR +Specify the linter and code formatter that Bundler should add to the project\'s development dependencies\. Acceptable values are \fBrubocop\fR and \fBstandard\fR\. A configuration file will be generated in the project directory\. Given no option is specified: +. +.IP +When Bundler is configured to add a linter, this defaults to Bundler\'s global config setting \fBgem\.linter\fR\. +. +.IP +When Bundler is configured not to add a linter, an interactive prompt will be displayed and the answer will be used for the current rubygem project\. +. +.IP +When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. +. +.TP +\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR +Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\. +. +.SH "SEE ALSO" +. +.IP "\(bu" 4 +bundle config(1) \fIbundle\-config\.1\.html\fR +. +.IP "" 0 + diff --git a/ruby/lib/bundler/man/bundle-gem.1.ronn b/ruby/lib/bundler/man/bundle-gem.1.ronn new file mode 100644 index 000000000..61c741fb2 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-gem.1.ronn @@ -0,0 +1,117 @@ +bundle-gem(1) -- Generate a project skeleton for creating a rubygem +==================================================================== + +## SYNOPSIS + +`bundle gem` [OPTIONS] + +## DESCRIPTION + +Generates a directory named `GEM_NAME` with a `Rakefile`, `GEM_NAME.gemspec`, +and other supporting files and directories that can be used to develop a +rubygem with that name. + +Run `rake -T` in the resulting project for a list of Rake tasks that can be used +to test and publish the gem to rubygems.org. + +The generated project skeleton can be customized with OPTIONS, as explained +below. Note that these options can also be specified via Bundler's global +configuration file using the following names: + +* `gem.coc` +* `gem.mit` +* `gem.test` + +## OPTIONS + +* `--exe` or `-b` or `--bin`: + Specify that Bundler should create a binary executable (as `exe/GEM_NAME`) + in the generated rubygem project. This binary will also be added to the + `GEM_NAME.gemspec` manifest. This behavior is disabled by default. + +* `--no-exe`: + Do not create a binary (overrides `--exe` specified in the global config). + +* `--coc`: + Add a `CODE_OF_CONDUCT.md` file to the root of the generated project. If + this option is unspecified, an interactive prompt will be displayed and the + answer will be saved in Bundler's global config for future `bundle gem` use. + +* `--no-coc`: + Do not create a `CODE_OF_CONDUCT.md` (overrides `--coc` specified in the + global config). + +* `--ext`: + Add boilerplate for C extension code to the generated project. This behavior + is disabled by default. + +* `--no-ext`: + Do not add C extension code (overrides `--ext` specified in the global + config). + +* `--mit`: + Add an MIT license to a `LICENSE.txt` file in the root of the generated + project. Your name from the global git config is used for the copyright + statement. If this option is unspecified, an interactive prompt will be + displayed and the answer will be saved in Bundler's global config for future + `bundle gem` use. + +* `--no-mit`: + Do not create a `LICENSE.txt` (overrides `--mit` specified in the global + config). + +* `-t`, `--test=minitest`, `--test=rspec`, `--test=test-unit`: + Specify the test framework that Bundler should use when generating the + project. Acceptable values are `minitest`, `rspec` and `test-unit`. The + `GEM_NAME.gemspec` will be configured and a skeleton test/spec directory will + be created based on this option. Given no option is specified: + + When Bundler is configured to generate tests, this defaults to Bundler's + global config setting `gem.test`. + + When Bundler is configured to not generate tests, an interactive prompt will + be displayed and the answer will be used for the current rubygem project. + + When Bundler is unconfigured, an interactive prompt will be displayed and + the answer will be saved in Bundler's global config for future `bundle gem` + use. + +* `--ci`, `--ci=github`, `--ci=travis`, `--ci=gitlab`, `--ci=circle`: + Specify the continuous integration service that Bundler should use when + generating the project. Acceptable values are `github`, `travis`, `gitlab` + and `circle`. A configuration file will be generated in the project directory. + Given no option is specified: + + When Bundler is configured to generate CI files, this defaults to Bundler's + global config setting `gem.ci`. + + When Bundler is configured to not generate CI files, an interactive prompt + will be displayed and the answer will be used for the current rubygem project. + + When Bundler is unconfigured, an interactive prompt will be displayed and + the answer will be saved in Bundler's global config for future `bundle gem` + use. + +* `--linter`, `--linter=rubocop`, `--linter=standard`: + Specify the linter and code formatter that Bundler should add to the + project's development dependencies. Acceptable values are `rubocop` and + `standard`. A configuration file will be generated in the project directory. + Given no option is specified: + + When Bundler is configured to add a linter, this defaults to Bundler's + global config setting `gem.linter`. + + When Bundler is configured not to add a linter, an interactive prompt + will be displayed and the answer will be used for the current rubygem project. + + When Bundler is unconfigured, an interactive prompt will be displayed and + the answer will be saved in Bundler's global config for future `bundle gem` + use. + +* `-e`, `--edit[=EDITOR]`: + Open the resulting GEM_NAME.gemspec in EDITOR, or the default editor if not + specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`. + +## SEE ALSO + +* [bundle config(1)](bundle-config.1.html) diff --git a/ruby/man/bundle-info.1 b/ruby/lib/bundler/man/bundle-info.1 similarity index 89% rename from ruby/man/bundle-info.1 rename to ruby/lib/bundler/man/bundle-info.1 index d7c73e9bb..9e1400ec5 100644 --- a/ruby/man/bundle-info.1 +++ b/ruby/lib/bundler/man/bundle-info.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INFO" "1" "January 2020" "" "" +.TH "BUNDLE\-INFO" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle diff --git a/ruby/man/bundle-info.ronn b/ruby/lib/bundler/man/bundle-info.1.ronn similarity index 100% rename from ruby/man/bundle-info.ronn rename to ruby/lib/bundler/man/bundle-info.1.ronn diff --git a/ruby/man/bundle-init.1 b/ruby/lib/bundler/man/bundle-init.1 similarity index 95% rename from ruby/man/bundle-init.1 rename to ruby/lib/bundler/man/bundle-init.1 index 803d4b9be..612d16031 100644 --- a/ruby/man/bundle-init.1 +++ b/ruby/lib/bundler/man/bundle-init.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INIT" "1" "January 2020" "" "" +.TH "BUNDLE\-INIT" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory diff --git a/ruby/man/bundle-init.ronn b/ruby/lib/bundler/man/bundle-init.1.ronn similarity index 100% rename from ruby/man/bundle-init.ronn rename to ruby/lib/bundler/man/bundle-init.1.ronn diff --git a/ruby/man/bundle-inject.1 b/ruby/lib/bundler/man/bundle-inject.1 similarity index 93% rename from ruby/man/bundle-inject.1 rename to ruby/lib/bundler/man/bundle-inject.1 index 3370a9157..ded4d6d64 100644 --- a/ruby/man/bundle-inject.1 +++ b/ruby/lib/bundler/man/bundle-inject.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INJECT" "1" "January 2020" "" "" +.TH "BUNDLE\-INJECT" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile diff --git a/ruby/man/bundle-inject.ronn b/ruby/lib/bundler/man/bundle-inject.1.ronn similarity index 100% rename from ruby/man/bundle-inject.ronn rename to ruby/lib/bundler/man/bundle-inject.1.ronn diff --git a/ruby/man/bundle-install.1 b/ruby/lib/bundler/man/bundle-install.1 similarity index 92% rename from ruby/man/bundle-install.1 rename to ruby/lib/bundler/man/bundle-install.1 index 4a289f5c2..6824dea3b 100644 --- a/ruby/man/bundle-install.1 +++ b/ruby/lib/bundler/man/bundle-install.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INSTALL" "1" "January 2020" "" "" +.TH "BUNDLE\-INSTALL" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile @@ -19,7 +19,7 @@ If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), B If a \fBGemfile\.lock\fR does exist, and you have updated your Gemfile(5), Bundler will use the dependencies in the \fBGemfile\.lock\fR for all gems that you did not update, but will re\-resolve the dependencies of gems that you did update\. You can find more information about this update process below under \fICONSERVATIVE UPDATING\fR\. . .SH "OPTIONS" -To apply any of \fB\-\-binstubs\fR, \fB\-\-deployment\fR, \fB\-\-path\fR, or \fB\-\-without\fR every time \fBbundle install\fR is run, use \fBbundle config\fR (see bundle\-config(1))\. +The \fB\-\-clean\fR, \fB\-\-deployment\fR, \fB\-\-frozen\fR, \fB\-\-no\-prune\fR, \fB\-\-path\fR, \fB\-\-shebang\fR, \fB\-\-system\fR, \fB\-\-without\fR and \fB\-\-with\fR options are deprecated because they only make sense if they are applied to every subsequent \fBbundle install\fR run automatically and that requires \fBbundler\fR to silently remember them\. Since \fBbundler\fR will no longer remember CLI flags in future versions, \fBbundle config\fR (see bundle\-config(1)) should be used to apply them permanently\. . .TP \fB\-\-binstubs[=]\fR @@ -32,10 +32,16 @@ Creates a directory (defaults to \fB~/bin\fR) and places any executables from th \fB\-\-clean\fR On finishing the installation Bundler is going to remove any gems not present in the current Gemfile(5)\. Don\'t worry, gems currently in use will not be removed\. . +.IP +This option is deprecated in favor of the \fBclean\fR setting\. +. .TP \fB\-\-deployment\fR In \fIdeployment mode\fR, Bundler will \'roll\-out\' the bundle for production or CI use\. Please check carefully if you want to have this option enabled in your development environment\. . +.IP +This option is deprecated in favor of the \fBdeployment\fR setting\. +. .TP \fB\-\-redownload\fR Force download every gem, even if the required versions are already available locally\. @@ -44,6 +50,9 @@ Force download every gem, even if the required versions are already available lo \fB\-\-frozen\fR Do not allow the Gemfile\.lock to be updated after this install\. Exits non\-zero if there are going to be changes to the Gemfile\.lock\. . +.IP +This option is deprecated in favor of the \fBfrozen\fR setting\. +. .TP \fB\-\-full\-index\fR Bundler will not call Rubygems\' API endpoint (default) but download and cache a (currently big) index file of all gems\. Performance can be improved for large bundles that seldom change by enabling this option\. @@ -54,11 +63,11 @@ The location of the Gemfile(5) which Bundler should use\. This defaults to a Gem . .TP \fB\-\-jobs=[]\fR, \fB\-j[]\fR -The maximum number of parallel download and install jobs\. The default is \fB1\fR\. +The maximum number of parallel download and install jobs\. The default is the number of available processors\. . .TP \fB\-\-local\fR -Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if a appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\. +Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\. . .TP \fB\-\-no\-cache\fR @@ -68,10 +77,16 @@ Do not update the cache in \fBvendor/cache\fR with the newly bundled gems\. This \fB\-\-no\-prune\fR Don\'t remove stale gems from the cache when the installation finishes\. . +.IP +This option is deprecated in favor of the \fBno_prune\fR setting\. +. .TP \fB\-\-path=\fR The location to install the specified gems to\. This defaults to Rubygems\' setting\. Bundler shares this location with Rubygems, \fBgem install \.\.\.\fR will have gem installed there, too\. Therefore, gems installed without a \fB\-\-path \.\.\.\fR setting will show up by calling \fBgem list\fR\. Accordingly, gems installed to other locations will not get listed\. . +.IP +This option is deprecated in favor of the \fBpath\fR setting\. +. .TP \fB\-\-quiet\fR Do not print progress information to the standard output\. Instead, Bundler will exit using a status code (\fB$?\fR)\. @@ -84,6 +99,9 @@ Retry failed network or git requests for \fInumber\fR times\. \fB\-\-shebang=\fR Uses the specified ruby executable (usually \fBruby\fR) to execute the scripts created with \fB\-\-binstubs\fR\. In addition, if you use \fB\-\-binstubs\fR together with \fB\-\-shebang jruby\fR these executables will be changed to execute \fBjruby\fR instead\. . +.IP +This option is deprecated in favor of the \fBshebang\fR setting\. +. .TP \fB\-\-standalone[=]\fR Makes a bundle that can work without depending on Rubygems or Bundler at runtime\. A space separated list of groups to install has to be specified\. Bundler creates a directory named \fBbundle\fR and installs the bundle there\. It also generates a \fBbundle/bundler/setup\.rb\fR file to replace Bundler\'s own setup in the manner required\. Using this option implicitly sets \fBpath\fR, which is a [remembered option][REMEMBERED OPTIONS]\. @@ -92,6 +110,9 @@ Makes a bundle that can work without depending on Rubygems or Bundler at runtime \fB\-\-system\fR Installs the gems specified in the bundle to the system\'s Rubygems location\. This overrides any previous configuration of \fB\-\-path\fR\. . +.IP +This option is deprecated in favor of the \fBsystem\fR setting\. +. .TP \fB\-\-trust\-policy=[]\fR Apply the Rubygems security policy \fIpolicy\fR, where policy is one of \fBHighSecurity\fR, \fBMediumSecurity\fR, \fBLowSecurity\fR, \fBAlmostNoSecurity\fR, or \fBNoSecurity\fR\. For more details, please see the Rubygems signing documentation linked below in \fISEE ALSO\fR\. @@ -100,10 +121,16 @@ Apply the Rubygems security policy \fIpolicy\fR, where policy is one of \fBHighS \fB\-\-with=\fR A space\-separated list of groups referencing gems to install\. If an optional group is given it is installed\. If a group is given that is in the remembered list of groups given to \-\-without, it is removed from that list\. . +.IP +This option is deprecated in favor of the \fBwith\fR setting\. +. .TP \fB\-\-without=\fR A space\-separated list of groups referencing gems to skip during installation\. If a group is given that is in the remembered list of groups given to \-\-with, it is removed from that list\. . +.IP +This option is deprecated in favor of the \fBwithout\fR setting\. +. .SH "DEPLOYMENT MODE" Bundler\'s defaults are optimized for development\. To switch to defaults optimized for deployment and for CI, use the \fB\-\-deployment\fR flag\. Do not activate deployment mode on development machines, as it will cause an error when the Gemfile(5) is modified\. . diff --git a/ruby/lib/bundler/man/bundle-install.1.ronn b/ruby/lib/bundler/man/bundle-install.1.ronn new file mode 100644 index 000000000..bec05187f --- /dev/null +++ b/ruby/lib/bundler/man/bundle-install.1.ronn @@ -0,0 +1,405 @@ +bundle-install(1) -- Install the dependencies specified in your Gemfile +======================================================================= + +## SYNOPSIS + +`bundle install` [--binstubs[=DIRECTORY]] + [--clean] + [--deployment] + [--frozen] + [--full-index] + [--gemfile=GEMFILE] + [--jobs=NUMBER] + [--local] + [--no-cache] + [--no-prune] + [--path PATH] + [--quiet] + [--redownload] + [--retry=NUMBER] + [--shebang] + [--standalone[=GROUP[ GROUP...]]] + [--system] + [--trust-policy=POLICY] + [--with=GROUP[ GROUP...]] + [--without=GROUP[ GROUP...]] + +## DESCRIPTION + +Install the gems specified in your Gemfile(5). If this is the first +time you run bundle install (and a `Gemfile.lock` does not exist), +Bundler will fetch all remote sources, resolve dependencies and +install all needed gems. + +If a `Gemfile.lock` does exist, and you have not updated your Gemfile(5), +Bundler will fetch all remote sources, but use the dependencies +specified in the `Gemfile.lock` instead of resolving dependencies. + +If a `Gemfile.lock` does exist, and you have updated your Gemfile(5), +Bundler will use the dependencies in the `Gemfile.lock` for all gems +that you did not update, but will re-resolve the dependencies of +gems that you did update. You can find more information about this +update process below under [CONSERVATIVE UPDATING][]. + +## OPTIONS + +The `--clean`, `--deployment`, `--frozen`, `--no-prune`, `--path`, `--shebang`, +`--system`, `--without` and `--with` options are deprecated because they only +make sense if they are applied to every subsequent `bundle install` run +automatically and that requires `bundler` to silently remember them. Since +`bundler` will no longer remember CLI flags in future versions, `bundle config` +(see bundle-config(1)) should be used to apply them permanently. + +* `--binstubs[=]`: + Binstubs are scripts that wrap around executables. Bundler creates a small Ruby + file (a binstub) that loads Bundler, runs the command, and puts it in `bin/`. + This lets you link the binstub inside of an application to the exact gem + version the application needs. + + Creates a directory (defaults to `~/bin`) and places any executables from the + gem there. These executables run in Bundler's context. If used, you might add + this directory to your environment's `PATH` variable. For instance, if the + `rails` gem comes with a `rails` executable, this flag will create a + `bin/rails` executable that ensures that all referred dependencies will be + resolved using the bundled gems. + +* `--clean`: + On finishing the installation Bundler is going to remove any gems not present + in the current Gemfile(5). Don't worry, gems currently in use will not be + removed. + + This option is deprecated in favor of the `clean` setting. + +* `--deployment`: + In [deployment mode][DEPLOYMENT MODE], Bundler will 'roll-out' the bundle for + production or CI use. Please check carefully if you want to have this option + enabled in your development environment. + + This option is deprecated in favor of the `deployment` setting. + +* `--redownload`: + Force download every gem, even if the required versions are already available + locally. + +* `--frozen`: + Do not allow the Gemfile.lock to be updated after this install. Exits + non-zero if there are going to be changes to the Gemfile.lock. + + This option is deprecated in favor of the `frozen` setting. + +* `--full-index`: + Bundler will not call Rubygems' API endpoint (default) but download and cache + a (currently big) index file of all gems. Performance can be improved for + large bundles that seldom change by enabling this option. + +* `--gemfile=`: + The location of the Gemfile(5) which Bundler should use. This defaults + to a Gemfile(5) in the current working directory. In general, Bundler + will assume that the location of the Gemfile(5) is also the project's + root and will try to find `Gemfile.lock` and `vendor/cache` relative + to this location. + +* `--jobs=[]`, `-j[]`: + The maximum number of parallel download and install jobs. The default is the + number of available processors. + +* `--local`: + Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the + gems already present in Rubygems' cache or in `vendor/cache`. Note that if an + appropriate platform-specific gem exists on `rubygems.org` it will not be + found. + +* `--no-cache`: + Do not update the cache in `vendor/cache` with the newly bundled gems. This + does not remove any gems in the cache but keeps the newly bundled gems from + being cached during the install. + +* `--no-prune`: + Don't remove stale gems from the cache when the installation finishes. + + This option is deprecated in favor of the `no_prune` setting. + +* `--path=`: + The location to install the specified gems to. This defaults to Rubygems' + setting. Bundler shares this location with Rubygems, `gem install ...` will + have gem installed there, too. Therefore, gems installed without a + `--path ...` setting will show up by calling `gem list`. Accordingly, gems + installed to other locations will not get listed. + + This option is deprecated in favor of the `path` setting. + +* `--quiet`: + Do not print progress information to the standard output. Instead, Bundler + will exit using a status code (`$?`). + +* `--retry=[]`: + Retry failed network or git requests for times. + +* `--shebang=`: + Uses the specified ruby executable (usually `ruby`) to execute the scripts + created with `--binstubs`. In addition, if you use `--binstubs` together with + `--shebang jruby` these executables will be changed to execute `jruby` + instead. + + This option is deprecated in favor of the `shebang` setting. + +* `--standalone[=]`: + Makes a bundle that can work without depending on Rubygems or Bundler at + runtime. A space separated list of groups to install has to be specified. + Bundler creates a directory named `bundle` and installs the bundle there. It + also generates a `bundle/bundler/setup.rb` file to replace Bundler's own setup + in the manner required. Using this option implicitly sets `path`, which is a + [remembered option][REMEMBERED OPTIONS]. + +* `--system`: + Installs the gems specified in the bundle to the system's Rubygems location. + This overrides any previous configuration of `--path`. + + This option is deprecated in favor of the `system` setting. + +* `--trust-policy=[]`: + Apply the Rubygems security policy , where policy is one of + `HighSecurity`, `MediumSecurity`, `LowSecurity`, `AlmostNoSecurity`, or + `NoSecurity`. For more details, please see the Rubygems signing documentation + linked below in [SEE ALSO][]. + +* `--with=`: + A space-separated list of groups referencing gems to install. If an + optional group is given it is installed. If a group is given that is + in the remembered list of groups given to --without, it is removed + from that list. + + This option is deprecated in favor of the `with` setting. + +* `--without=`: + A space-separated list of groups referencing gems to skip during installation. + If a group is given that is in the remembered list of groups given + to --with, it is removed from that list. + + This option is deprecated in favor of the `without` setting. + +## DEPLOYMENT MODE + +Bundler's defaults are optimized for development. To switch to +defaults optimized for deployment and for CI, use the `--deployment` +flag. Do not activate deployment mode on development machines, as it +will cause an error when the Gemfile(5) is modified. + +1. A `Gemfile.lock` is required. + + To ensure that the same versions of the gems you developed with + and tested with are also used in deployments, a `Gemfile.lock` + is required. + + This is mainly to ensure that you remember to check your + `Gemfile.lock` into version control. + +2. The `Gemfile.lock` must be up to date + + In development, you can modify your Gemfile(5) and re-run + `bundle install` to [conservatively update][CONSERVATIVE UPDATING] + your `Gemfile.lock` snapshot. + + In deployment, your `Gemfile.lock` should be up-to-date with + changes made in your Gemfile(5). + +3. Gems are installed to `vendor/bundle` not your default system location + + In development, it's convenient to share the gems used in your + application with other applications and other scripts that run on + the system. + + In deployment, isolation is a more important default. In addition, + the user deploying the application may not have permission to install + gems to the system, or the web server may not have permission to + read them. + + As a result, `bundle install --deployment` installs gems to + the `vendor/bundle` directory in the application. This may be + overridden using the `--path` option. + +## SUDO USAGE + +By default, Bundler installs gems to the same location as `gem install`. + +In some cases, that location may not be writable by your Unix user. In +that case, Bundler will stage everything in a temporary directory, +then ask you for your `sudo` password in order to copy the gems into +their system location. + +From your perspective, this is identical to installing the gems +directly into the system. + +You should never use `sudo bundle install`. This is because several +other steps in `bundle install` must be performed as the current user: + +* Updating your `Gemfile.lock` +* Updating your `vendor/cache`, if necessary +* Checking out private git repositories using your user's SSH keys + +Of these three, the first two could theoretically be performed by +`chown`ing the resulting files to `$SUDO_USER`. The third, however, +can only be performed by invoking the `git` command as +the current user. Therefore, git gems are downloaded and installed +into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH. + +As a result, you should run `bundle install` as the current user, +and Bundler will ask for your password if it is needed to put the +gems into their final location. + +## INSTALLING GROUPS + +By default, `bundle install` will install all gems in all groups +in your Gemfile(5), except those declared for a different platform. + +However, you can explicitly tell Bundler to skip installing +certain groups with the `--without` option. This option takes +a space-separated list of groups. + +While the `--without` option will skip _installing_ the gems in the +specified groups, it will still _download_ those gems and use them to +resolve the dependencies of every gem in your Gemfile(5). + +This is so that installing a different set of groups on another + machine (such as a production server) will not change the +gems and versions that you have already developed and tested against. + +`Bundler offers a rock-solid guarantee that the third-party +code you are running in development and testing is also the +third-party code you are running in production. You can choose +to exclude some of that code in different environments, but you +will never be caught flat-footed by different versions of +third-party code being used in different environments.` + +For a simple illustration, consider the following Gemfile(5): + + source 'https://rubygems.org' + + gem 'sinatra' + + group :production do + gem 'rack-perftools-profiler' + end + +In this case, `sinatra` depends on any version of Rack (`>= 1.0`), while +`rack-perftools-profiler` depends on 1.x (`~> 1.0`). + +When you run `bundle install --without production` in development, we +look at the dependencies of `rack-perftools-profiler` as well. That way, +you do not spend all your time developing against Rack 2.0, using new +APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2 +when the `production` group _is_ used. + +This should not cause any problems in practice, because we do not +attempt to `install` the gems in the excluded groups, and only evaluate +as part of the dependency resolution process. + +This also means that you cannot include different versions of the same +gem in different groups, because doing so would result in different +sets of dependencies used in development and production. Because of +the vagaries of the dependency resolution process, this usually +affects more than the gems you list in your Gemfile(5), and can +(surprisingly) radically change the gems you are using. + +## THE GEMFILE.LOCK + +When you run `bundle install`, Bundler will persist the full names +and versions of all gems that you used (including dependencies of +the gems specified in the Gemfile(5)) into a file called `Gemfile.lock`. + +Bundler uses this file in all subsequent calls to `bundle install`, +which guarantees that you always use the same exact code, even +as your application moves across machines. + +Because of the way dependency resolution works, even a +seemingly small change (for instance, an update to a point-release +of a dependency of a gem in your Gemfile(5)) can result in radically +different gems being needed to satisfy all dependencies. + +As a result, you `SHOULD` check your `Gemfile.lock` into version +control, in both applications and gems. If you do not, every machine that +checks out your repository (including your production server) will resolve all +dependencies again, which will result in different versions of +third-party code being used if `any` of the gems in the Gemfile(5) +or any of their dependencies have been updated. + +When Bundler first shipped, the `Gemfile.lock` was included in the `.gitignore` +file included with generated gems. Over time, however, it became clear that +this practice forces the pain of broken dependencies onto new contributors, +while leaving existing contributors potentially unaware of the problem. Since +`bundle install` is usually the first step towards a contribution, the pain of +broken dependencies would discourage new contributors from contributing. As a +result, we have revised our guidance for gem authors to now recommend checking +in the lock for gems. + +## CONSERVATIVE UPDATING + +When you make a change to the Gemfile(5) and then run `bundle install`, +Bundler will update only the gems that you modified. + +In other words, if a gem that you `did not modify` worked before +you called `bundle install`, it will continue to use the exact +same versions of all dependencies as it used before the update. + +Let's take a look at an example. Here's your original Gemfile(5): + + source 'https://rubygems.org' + + gem 'actionpack', '2.3.8' + gem 'activemerchant' + +In this case, both `actionpack` and `activemerchant` depend on +`activesupport`. The `actionpack` gem depends on `activesupport 2.3.8` +and `rack ~> 1.1.0`, while the `activemerchant` gem depends on +`activesupport >= 2.3.2`, `braintree >= 2.0.0`, and `builder >= 2.0.0`. + +When the dependencies are first resolved, Bundler will select +`activesupport 2.3.8`, which satisfies the requirements of both +gems in your Gemfile(5). + +Next, you modify your Gemfile(5) to: + + source 'https://rubygems.org' + + gem 'actionpack', '3.0.0.rc' + gem 'activemerchant' + +The `actionpack 3.0.0.rc` gem has a number of new dependencies, +and updates the `activesupport` dependency to `= 3.0.0.rc` and +the `rack` dependency to `~> 1.2.1`. + +When you run `bundle install`, Bundler notices that you changed +the `actionpack` gem, but not the `activemerchant` gem. It +evaluates the gems currently being used to satisfy its requirements: + + * `activesupport 2.3.8`: + also used to satisfy a dependency in `activemerchant`, + which is not being updated + * `rack ~> 1.1.0`: + not currently being used to satisfy another dependency + +Because you did not explicitly ask to update `activemerchant`, +you would not expect it to suddenly stop working after updating +`actionpack`. However, satisfying the new `activesupport 3.0.0.rc` +dependency of actionpack requires updating one of its dependencies. + +Even though `activemerchant` declares a very loose dependency +that theoretically matches `activesupport 3.0.0.rc`, Bundler treats +gems in your Gemfile(5) that have not changed as an atomic unit +together with their dependencies. In this case, the `activemerchant` +dependency is treated as `activemerchant 1.7.1 + activesupport 2.3.8`, +so `bundle install` will report that it cannot update `actionpack`. + +To explicitly update `actionpack`, including its dependencies +which other gems in the Gemfile(5) still depend on, run +`bundle update actionpack` (see `bundle update(1)`). + +`Summary`: In general, after making a change to the Gemfile(5) , you +should first try to run `bundle install`, which will guarantee that no +other gem in the Gemfile(5) is impacted by the change. If that +does not work, run [bundle update(1)](bundle-update.1.html). + +## SEE ALSO + +* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems) +* [Rubygems signing docs](http://guides.rubygems.org/security/) diff --git a/ruby/lib/bundler/man/bundle-list.1 b/ruby/lib/bundler/man/bundle-list.1 new file mode 100644 index 000000000..a697173af --- /dev/null +++ b/ruby/lib/bundler/man/bundle-list.1 @@ -0,0 +1,50 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "BUNDLE\-LIST" "1" "December 2021" "" "" +. +.SH "NAME" +\fBbundle\-list\fR \- List all the gems in the bundle +. +.SH "SYNOPSIS" +\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP[ GROUP\.\.\.]] [\-\-only\-group=GROUP[ GROUP\.\.\.]] +. +.SH "DESCRIPTION" +Prints a list of all the gems in the bundle including their version\. +. +.P +Example: +. +.P +bundle list \-\-name\-only +. +.P +bundle list \-\-paths +. +.P +bundle list \-\-without\-group test +. +.P +bundle list \-\-only\-group dev +. +.P +bundle list \-\-only\-group dev test \-\-paths +. +.SH "OPTIONS" +. +.TP +\fB\-\-name\-only\fR +Print only the name of each gem\. +. +.TP +\fB\-\-paths\fR +Print the path to each gem in the bundle\. +. +.TP +\fB\-\-without\-group=\fR +A space\-separated list of groups of gems to skip during printing\. +. +.TP +\fB\-\-only\-group=\fR +A space\-separated list of groups of gems to print\. + diff --git a/ruby/lib/bundler/man/bundle-list.1.ronn b/ruby/lib/bundler/man/bundle-list.1.ronn new file mode 100644 index 000000000..dc058ecd5 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-list.1.ronn @@ -0,0 +1,33 @@ +bundle-list(1) -- List all the gems in the bundle +========================================================================= + +## SYNOPSIS + +`bundle list` [--name-only] [--paths] [--without-group=GROUP[ GROUP...]] [--only-group=GROUP[ GROUP...]] + +## DESCRIPTION + +Prints a list of all the gems in the bundle including their version. + +Example: + +bundle list --name-only + +bundle list --paths + +bundle list --without-group test + +bundle list --only-group dev + +bundle list --only-group dev test --paths + +## OPTIONS + +* `--name-only`: + Print only the name of each gem. +* `--paths`: + Print the path to each gem in the bundle. +* `--without-group=`: + A space-separated list of groups of gems to skip during printing. +* `--only-group=`: + A space-separated list of groups of gems to print. diff --git a/ruby/man/bundle-lock.1 b/ruby/lib/bundler/man/bundle-lock.1 similarity index 98% rename from ruby/man/bundle-lock.1 rename to ruby/lib/bundler/man/bundle-lock.1 index 89f6e3517..ef515b033 100644 --- a/ruby/man/bundle-lock.1 +++ b/ruby/lib/bundler/man/bundle-lock.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LOCK" "1" "January 2020" "" "" +.TH "BUNDLE\-LOCK" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing diff --git a/ruby/man/bundle-lock.ronn b/ruby/lib/bundler/man/bundle-lock.1.ronn similarity index 100% rename from ruby/man/bundle-lock.ronn rename to ruby/lib/bundler/man/bundle-lock.1.ronn diff --git a/ruby/man/bundle-open.1 b/ruby/lib/bundler/man/bundle-open.1 similarity index 92% rename from ruby/man/bundle-open.1 rename to ruby/lib/bundler/man/bundle-open.1 index 5a11eeeb6..dd28566bd 100644 --- a/ruby/man/bundle-open.1 +++ b/ruby/lib/bundler/man/bundle-open.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OPEN" "1" "January 2020" "" "" +.TH "BUNDLE\-OPEN" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle diff --git a/ruby/man/bundle-open.ronn b/ruby/lib/bundler/man/bundle-open.1.ronn similarity index 100% rename from ruby/man/bundle-open.ronn rename to ruby/lib/bundler/man/bundle-open.1.ronn diff --git a/ruby/man/bundle-outdated.1 b/ruby/lib/bundler/man/bundle-outdated.1 similarity index 98% rename from ruby/man/bundle-outdated.1 rename to ruby/lib/bundler/man/bundle-outdated.1 index 408e56803..b9d50a1c7 100644 --- a/ruby/man/bundle-outdated.1 +++ b/ruby/lib/bundler/man/bundle-outdated.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OUTDATED" "1" "January 2020" "" "" +.TH "BUNDLE\-OUTDATED" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available diff --git a/ruby/man/bundle-outdated.ronn b/ruby/lib/bundler/man/bundle-outdated.1.ronn similarity index 100% rename from ruby/man/bundle-outdated.ronn rename to ruby/lib/bundler/man/bundle-outdated.1.ronn diff --git a/ruby/man/bundle-platform.1 b/ruby/lib/bundler/man/bundle-platform.1 similarity index 96% rename from ruby/man/bundle-platform.1 rename to ruby/lib/bundler/man/bundle-platform.1 index c83aa3c5d..b1c859f64 100644 --- a/ruby/man/bundle-platform.1 +++ b/ruby/lib/bundler/man/bundle-platform.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PLATFORM" "1" "January 2020" "" "" +.TH "BUNDLE\-PLATFORM" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information diff --git a/ruby/man/bundle-platform.ronn b/ruby/lib/bundler/man/bundle-platform.1.ronn similarity index 100% rename from ruby/man/bundle-platform.ronn rename to ruby/lib/bundler/man/bundle-platform.1.ronn diff --git a/ruby/man/bundle-pristine.1 b/ruby/lib/bundler/man/bundle-pristine.1 similarity index 97% rename from ruby/man/bundle-pristine.1 rename to ruby/lib/bundler/man/bundle-pristine.1 index 460e3d4e5..6e4a02866 100644 --- a/ruby/man/bundle-pristine.1 +++ b/ruby/lib/bundler/man/bundle-pristine.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PRISTINE" "1" "January 2020" "" "" +.TH "BUNDLE\-PRISTINE" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition diff --git a/ruby/man/bundle-pristine.ronn b/ruby/lib/bundler/man/bundle-pristine.1.ronn similarity index 100% rename from ruby/man/bundle-pristine.ronn rename to ruby/lib/bundler/man/bundle-pristine.1.ronn diff --git a/ruby/man/bundle-remove.1 b/ruby/lib/bundler/man/bundle-remove.1 similarity index 94% rename from ruby/man/bundle-remove.1 rename to ruby/lib/bundler/man/bundle-remove.1 index cb4ad8d38..0b4edd141 100644 --- a/ruby/man/bundle-remove.1 +++ b/ruby/lib/bundler/man/bundle-remove.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-REMOVE" "1" "January 2020" "" "" +.TH "BUNDLE\-REMOVE" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile diff --git a/ruby/man/bundle-remove.ronn b/ruby/lib/bundler/man/bundle-remove.1.ronn similarity index 100% rename from ruby/man/bundle-remove.ronn rename to ruby/lib/bundler/man/bundle-remove.1.ronn diff --git a/ruby/man/bundle-show.1 b/ruby/lib/bundler/man/bundle-show.1 similarity index 93% rename from ruby/man/bundle-show.1 rename to ruby/lib/bundler/man/bundle-show.1 index 2922a3346..375699ddf 100644 --- a/ruby/man/bundle-show.1 +++ b/ruby/lib/bundler/man/bundle-show.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-SHOW" "1" "January 2020" "" "" +.TH "BUNDLE\-SHOW" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem diff --git a/ruby/man/bundle-show.ronn b/ruby/lib/bundler/man/bundle-show.1.ronn similarity index 100% rename from ruby/man/bundle-show.ronn rename to ruby/lib/bundler/man/bundle-show.1.ronn diff --git a/ruby/man/bundle-update.1 b/ruby/lib/bundler/man/bundle-update.1 similarity index 96% rename from ruby/man/bundle-update.1 rename to ruby/lib/bundler/man/bundle-update.1 index f315532bb..f5a79fe24 100644 --- a/ruby/man/bundle-update.1 +++ b/ruby/lib/bundler/man/bundle-update.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-UPDATE" "1" "January 2020" "" "" +.TH "BUNDLE\-UPDATE" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions @@ -47,7 +47,7 @@ Fall back to using the single\-file index of all gems\. . .TP \fB\-\-jobs=[]\fR, \fB\-j[]\fR -Specify the number of jobs to run in parallel\. The default is \fB1\fR\. +Specify the number of jobs to run in parallel\. The default is the number of available processors\. . .TP \fB\-\-retry=[]\fR @@ -79,7 +79,7 @@ Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR . .TP \fB\-\-conservative\fR -Use bundle install conservative update behavior and do not allow shared dependencies to be updated\. +Use bundle install conservative update behavior and do not allow indirect dependencies to be updated\. . .SH "UPDATING ALL GEMS" If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\. @@ -208,13 +208,13 @@ In this case, the two gems have their own set of dependencies, but they share \f In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\. . .P -To prevent updating shared dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR: +To prevent updating indirect dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR: . .P In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\. . .P -Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent shared dependencies from being updated\. +Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent indirect dependencies from being updated\. . .SH "PATCH LEVEL OPTIONS" Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\. diff --git a/ruby/lib/bundler/man/bundle-update.1.ronn b/ruby/lib/bundler/man/bundle-update.1.ronn new file mode 100644 index 000000000..fe500cdc9 --- /dev/null +++ b/ruby/lib/bundler/man/bundle-update.1.ronn @@ -0,0 +1,351 @@ +bundle-update(1) -- Update your gems to the latest available versions +===================================================================== + +## SYNOPSIS + +`bundle update` <*gems> [--all] + [--group=NAME] + [--source=NAME] + [--local] + [--ruby] + [--bundler[=VERSION]] + [--full-index] + [--jobs=JOBS] + [--quiet] + [--patch|--minor|--major] + [--redownload] + [--strict] + [--conservative] + +## DESCRIPTION + +Update the gems specified (all gems, if `--all` flag is used), ignoring +the previously installed gems specified in the `Gemfile.lock`. In +general, you should use [bundle install(1)](bundle-install.1.html) to install the same exact +gems and versions across machines. + +You would use `bundle update` to explicitly update the version of a +gem. + +## OPTIONS + +* `--all`: + Update all gems specified in Gemfile. + +* `--group=`, `-g=[]`: + Only update the gems in the specified group. For instance, you can update all gems + in the development group with `bundle update --group development`. You can also + call `bundle update rails --group test` to update the rails gem and all gems in + the test group, for example. + +* `--source=`: + The name of a `:git` or `:path` source used in the Gemfile(5). For + instance, with a `:git` source of `http://github.com/rails/rails.git`, + you would call `bundle update --source rails` + +* `--local`: + Do not attempt to fetch gems remotely and use the gem cache instead. + +* `--ruby`: + Update the locked version of Ruby to the current version of Ruby. + +* `--bundler`: + Update the locked version of bundler to the invoked bundler version. + +* `--full-index`: + Fall back to using the single-file index of all gems. + +* `--jobs=[]`, `-j[]`: + Specify the number of jobs to run in parallel. The default is the number of + available processors. + +* `--retry=[]`: + Retry failed network or git requests for times. + +* `--quiet`: + Only output warnings and errors. + +* `--redownload`: + Force downloading every gem. + +* `--patch`: + Prefer updating only to next patch version. + +* `--minor`: + Prefer updating only to next minor version. + +* `--major`: + Prefer updating to next major version (default). + +* `--strict`: + Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`. + +* `--conservative`: + Use bundle install conservative update behavior and do not allow indirect dependencies to be updated. + +## UPDATING ALL GEMS + +If you run `bundle update --all`, bundler will ignore +any previously installed gems and resolve all dependencies again +based on the latest versions of all gems available in the sources. + +Consider the following Gemfile(5): + + source "https://rubygems.org" + + gem "rails", "3.0.0.rc" + gem "nokogiri" + +When you run [bundle install(1)](bundle-install.1.html) the first time, bundler will resolve +all of the dependencies, all the way down, and install what you need: + + Fetching gem metadata from https://rubygems.org/......... + Resolving dependencies... + Installing builder 2.1.2 + Installing abstract 1.0.0 + Installing rack 1.2.8 + Using bundler 1.7.6 + Installing rake 10.4.0 + Installing polyglot 0.3.5 + Installing mime-types 1.25.1 + Installing i18n 0.4.2 + Installing mini_portile 0.6.1 + Installing tzinfo 0.3.42 + Installing rack-mount 0.6.14 + Installing rack-test 0.5.7 + Installing treetop 1.4.15 + Installing thor 0.14.6 + Installing activesupport 3.0.0.rc + Installing erubis 2.6.6 + Installing activemodel 3.0.0.rc + Installing arel 0.4.0 + Installing mail 2.2.20 + Installing activeresource 3.0.0.rc + Installing actionpack 3.0.0.rc + Installing activerecord 3.0.0.rc + Installing actionmailer 3.0.0.rc + Installing railties 3.0.0.rc + Installing rails 3.0.0.rc + Installing nokogiri 1.6.5 + + Bundle complete! 2 Gemfile dependencies, 26 gems total. + Use `bundle show [gemname]` to see where a bundled gem is installed. + +As you can see, even though you have two gems in the Gemfile(5), your application +needs 26 different gems in order to run. Bundler remembers the exact versions +it installed in `Gemfile.lock`. The next time you run [bundle install(1)](bundle-install.1.html), bundler skips +the dependency resolution and installs the same gems as it installed last time. + +After checking in the `Gemfile.lock` into version control and cloning it on another +machine, running [bundle install(1)](bundle-install.1.html) will _still_ install the gems that you installed +last time. You don't need to worry that a new release of `erubis` or `mail` changes +the gems you use. + +However, from time to time, you might want to update the gems you are using to the +newest versions that still match the gems in your Gemfile(5). + +To do this, run `bundle update --all`, which will ignore the `Gemfile.lock`, and resolve +all the dependencies again. Keep in mind that this process can result in a significantly +different set of the 25 gems, based on the requirements of new gems that the gem +authors released since the last time you ran `bundle update --all`. + +## UPDATING A LIST OF GEMS + +Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the +gems that you specified locked to the versions in the `Gemfile.lock`. + +For instance, in the scenario above, imagine that `nokogiri` releases version `1.4.4`, and +you want to update it _without_ updating Rails and all of its dependencies. To do this, +run `bundle update nokogiri`. + +Bundler will update `nokogiri` and any of its dependencies, but leave alone Rails and +its dependencies. + +## OVERLAPPING DEPENDENCIES + +Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same +second-level dependency. For instance, consider the case of `thin` and +`rack-perftools-profiler`. + + source "https://rubygems.org" + + gem "thin" + gem "rack-perftools-profiler" + +The `thin` gem depends on `rack >= 1.0`, while `rack-perftools-profiler` depends +on `rack ~> 1.0`. If you run bundle install, you get: + + Fetching source index for https://rubygems.org/ + Installing daemons (1.1.0) + Installing eventmachine (0.12.10) with native extensions + Installing open4 (1.0.1) + Installing perftools.rb (0.4.7) with native extensions + Installing rack (1.2.1) + Installing rack-perftools_profiler (0.0.2) + Installing thin (1.2.7) with native extensions + Using bundler (1.0.0.rc.3) + +In this case, the two gems have their own set of dependencies, but they share +`rack` in common. If you run `bundle update thin`, bundler will update `daemons`, +`eventmachine` and `rack`, which are dependencies of `thin`, but not `open4` or +`perftools.rb`, which are dependencies of `rack-perftools_profiler`. Note that +`bundle update thin` will update `rack` even though it's _also_ a dependency of +`rack-perftools_profiler`. + +In short, by default, when you update a gem using `bundle update`, bundler will +update all dependencies of that gem, including those that are also dependencies +of another gem. + +To prevent updating indirect dependencies, prior to version 1.14 the only option +was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html): + +In this scenario, updating the `thin` version manually in the Gemfile(5), +and then running [bundle install(1)](bundle-install.1.html) will only update `daemons` and `eventmachine`, +but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section +of [bundle install(1)](bundle-install.1.html). + +Starting with 1.14, specifying the `--conservative` option will also prevent indirect +dependencies from being updated. + +## PATCH LEVEL OPTIONS + +Version 1.14 introduced 4 patch-level options that will influence how gem +versions are resolved. One of the following options can be used: `--patch`, +`--minor` or `--major`. `--strict` can be added to further influence resolution. + +* `--patch`: + Prefer updating only to next patch version. + +* `--minor`: + Prefer updating only to next minor version. + +* `--major`: + Prefer updating to next major version (default). + +* `--strict`: + Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`. + +When Bundler is resolving what versions to use to satisfy declared +requirements in the Gemfile or in parent gems, it looks up all +available versions, filters out any versions that don't satisfy +the requirement, and then, by default, sorts them from newest to +oldest, considering them in that order. + +Providing one of the patch level options (e.g. `--patch`) changes the +sort order of the satisfying versions, causing Bundler to consider the +latest `--patch` or `--minor` version available before other versions. +Note that versions outside the stated patch level could still be +resolved to if necessary to find a suitable dependency graph. + +For example, if gem 'foo' is locked at 1.0.2, with no gem requirement +defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 +all exist, the default order of preference by default (`--major`) will +be "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2". + +If the `--patch` option is used, the order of preference will change to +"1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0". + +If the `--minor` option is used, the order of preference will change to +"1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0". + +Combining the `--strict` option with any of the patch level options +will remove any versions beyond the scope of the patch level option, +to ensure that no gem is updated that far. + +To continue the previous example, if both `--patch` and `--strict` +options are used, the available versions for resolution would be +"1.0.4, 1.0.3, 1.0.2". If `--minor` and `--strict` are used, it would +be "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2". + +Gem requirements as defined in the Gemfile will still be the first +determining factor for what versions are available. If the gem +requirement for `foo` in the Gemfile is '~> 1.0', that will accomplish +the same thing as providing the `--minor` and `--strict` options. + +## PATCH LEVEL EXAMPLES + +Given the following gem specifications: + + foo 1.4.3, requires: ~> bar 2.0 + foo 1.4.4, requires: ~> bar 2.0 + foo 1.4.5, requires: ~> bar 2.1 + foo 1.5.0, requires: ~> bar 2.1 + foo 1.5.1, requires: ~> bar 3.0 + bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0 + +Gemfile: + + gem 'foo' + +Gemfile.lock: + + foo (1.4.3) + bar (~> 2.0) + bar (2.0.3) + +Cases: + + # Command Line Result + ------------------------------------------------------------ + 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1' + 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1' + 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0' + 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1' + 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4' + +In case 1, bar is upgraded to 2.1.1, a minor version increase, because +the dependency from foo 1.4.5 required it. + +In case 2, only foo is requested to be unlocked, but bar is also +allowed to move because it's not a declared dependency in the Gemfile. + +In case 3, bar goes up a whole major release, because a minor increase +is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0 +of bar. + +In case 4, foo is preferred up to a minor version, but 1.5.1 won't work +because the --strict flag removes bar 3.0.0 from consideration since +it's a major increment. + +In case 5, both foo and bar have any minor or major increments removed +from consideration because of the --strict flag, so the most they can +move is up to 1.4.4 and 2.0.4. + +## RECOMMENDED WORKFLOW + +In general, when working with an application managed with bundler, you should +use the following workflow: + +* After you create your Gemfile(5) for the first time, run + + $ bundle install + +* Check the resulting `Gemfile.lock` into version control + + $ git add Gemfile.lock + +* When checking out this repository on another development machine, run + + $ bundle install + +* When checking out this repository on a deployment machine, run + + $ bundle install --deployment + +* After changing the Gemfile(5) to reflect a new or update dependency, run + + $ bundle install + +* Make sure to check the updated `Gemfile.lock` into version control + + $ git add Gemfile.lock + +* If [bundle install(1)](bundle-install.1.html) reports a conflict, manually update the specific + gems that you changed in the Gemfile(5) + + $ bundle update rails thin + +* If you want to update all the gems to the latest possible versions that + still match the gems listed in the Gemfile(5), run + + $ bundle update --all diff --git a/ruby/man/bundle-viz.1 b/ruby/lib/bundler/man/bundle-viz.1 similarity index 96% rename from ruby/man/bundle-viz.1 rename to ruby/lib/bundler/man/bundle-viz.1 index a2153da28..f792aa634 100644 --- a/ruby/man/bundle-viz.1 +++ b/ruby/lib/bundler/man/bundle-viz.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-VIZ" "1" "January 2020" "" "" +.TH "BUNDLE\-VIZ" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile diff --git a/ruby/man/bundle-viz.ronn b/ruby/lib/bundler/man/bundle-viz.1.ronn similarity index 100% rename from ruby/man/bundle-viz.ronn rename to ruby/lib/bundler/man/bundle-viz.1.ronn diff --git a/ruby/man/bundle.1 b/ruby/lib/bundler/man/bundle.1 similarity index 98% rename from ruby/man/bundle.1 rename to ruby/lib/bundler/man/bundle.1 index 4a9a9bec4..b1458bf57 100644 --- a/ruby/man/bundle.1 +++ b/ruby/lib/bundler/man/bundle.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE" "1" "January 2020" "" "" +.TH "BUNDLE" "1" "December 2021" "" "" . .SH "NAME" \fBbundle\fR \- Ruby Dependency Management diff --git a/ruby/man/bundle.ronn b/ruby/lib/bundler/man/bundle.1.ronn similarity index 100% rename from ruby/man/bundle.ronn rename to ruby/lib/bundler/man/bundle.1.ronn diff --git a/ruby/man/gemfile.5 b/ruby/lib/bundler/man/gemfile.5 similarity index 97% rename from ruby/man/gemfile.5 rename to ruby/lib/bundler/man/gemfile.5 index a9d2cee7c..1ac003a78 100644 --- a/ruby/man/gemfile.5 +++ b/ruby/lib/bundler/man/gemfile.5 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "GEMFILE" "5" "January 2020" "" "" +.TH "GEMFILE" "5" "December 2021" "" "" . .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs @@ -150,7 +150,7 @@ gem "RedCloth", ">= 4\.1\.0", "< 4\.2\.0" .IP "" 0 . .SS "REQUIRE AS" -Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring via \fBBundler\.require\fR\. You may pass an array with multiple files or \fBtrue\fR if file you want \fBrequired\fR has same name as \fIgem\fR or \fBfalse\fR to prevent any file from being autorequired\. +Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring via \fBBundler\.require\fR\. You may pass an array with multiple files or \fBtrue\fR if the file you want \fBrequired\fR has the same name as \fIgem\fR or \fBfalse\fR to prevent any file from being autorequired\. . .IP "" 4 . @@ -227,8 +227,8 @@ To specify multiple groups to ignore, specify a list of groups separated by spac . .nf -bundle config set without test -bundle config set without development test +bundle config set \-\-local without test +bundle config set \-\-local without development test . .fi . @@ -506,8 +506,34 @@ gem "rails", :git => "git://github\.com/rails/rails\.git" .P Since the \fBgithub\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\. . +.P +You can also directly pass a pull request URL: +. +.IP "" 4 +. +.nf + +gem "rails", :github => "https://github\.com/rails/rails/pull/43753" +. +.fi +. +.IP "" 0 +. +.P +Which is equivalent to: +. +.IP "" 4 +. +.nf + +gem "rails", :github => "rails/rails", branch: "refs/pull/43753/head" +. +.fi +. +.IP "" 0 +. .SS "GIST" -If the git repository you want to use is hosted as a Github Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\. +If the git repository you want to use is hosted as a GitHub Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\. . .IP "" 4 . diff --git a/ruby/man/gemfile.5.ronn b/ruby/lib/bundler/man/gemfile.5.ronn similarity index 97% rename from ruby/man/gemfile.5.ronn rename to ruby/lib/bundler/man/gemfile.5.ronn index 832577130..0feaf5824 100644 --- a/ruby/man/gemfile.5.ronn +++ b/ruby/lib/bundler/man/gemfile.5.ronn @@ -120,8 +120,8 @@ Each _gem_ `MAY` have one or more version specifiers. ### REQUIRE AS Each _gem_ `MAY` specify files that should be used when autorequiring via -`Bundler.require`. You may pass an array with multiple files or `true` if file -you want `required` has same name as _gem_ or `false` to +`Bundler.require`. You may pass an array with multiple files or `true` if the file +you want `required` has the same name as _gem_ or `false` to prevent any file from being autorequired. gem "redis", :require => ["redis/connection/hiredis", "redis"] @@ -163,8 +163,8 @@ not install with the `without` configuration. To specify multiple groups to ignore, specify a list of groups separated by spaces. - bundle config set without test - bundle config set without development test + bundle config set --local without test + bundle config set --local without development test Also, calling `Bundler.setup` with no parameters, or calling `require "bundler/setup"` will setup all groups except for the ones you excluded via `--without` (since they @@ -372,9 +372,17 @@ Are both equivalent to Since the `github` method is a specialization of `git_source`, it accepts a `:branch` named argument. +You can also directly pass a pull request URL: + + gem "rails", :github => "https://github.com/rails/rails/pull/43753" + +Which is equivalent to: + + gem "rails", :github => "rails/rails", branch: "refs/pull/43753/head" + ### GIST -If the git repository you want to use is hosted as a Github Gist and is public, you can use +If the git repository you want to use is hosted as a GitHub Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing ".git"). gem "the_hatch", :gist => "4815162342" diff --git a/ruby/lib/bundler/man/index.txt b/ruby/lib/bundler/man/index.txt new file mode 100644 index 000000000..ef2956b2f --- /dev/null +++ b/ruby/lib/bundler/man/index.txt @@ -0,0 +1,25 @@ +Gemfile(5) gemfile.5 +bundle(1) bundle.1 +bundle-add(1) bundle-add.1 +bundle-binstubs(1) bundle-binstubs.1 +bundle-cache(1) bundle-cache.1 +bundle-check(1) bundle-check.1 +bundle-clean(1) bundle-clean.1 +bundle-config(1) bundle-config.1 +bundle-doctor(1) bundle-doctor.1 +bundle-exec(1) bundle-exec.1 +bundle-gem(1) bundle-gem.1 +bundle-info(1) bundle-info.1 +bundle-init(1) bundle-init.1 +bundle-inject(1) bundle-inject.1 +bundle-install(1) bundle-install.1 +bundle-list(1) bundle-list.1 +bundle-lock(1) bundle-lock.1 +bundle-open(1) bundle-open.1 +bundle-outdated(1) bundle-outdated.1 +bundle-platform(1) bundle-platform.1 +bundle-pristine(1) bundle-pristine.1 +bundle-remove(1) bundle-remove.1 +bundle-show(1) bundle-show.1 +bundle-update(1) bundle-update.1 +bundle-viz(1) bundle-viz.1 diff --git a/ruby/lib/bundler/mirror.rb b/ruby/lib/bundler/mirror.rb index 0e554bcc3..a63b45b47 100644 --- a/ruby/lib/bundler/mirror.rb +++ b/ruby/lib/bundler/mirror.rb @@ -43,7 +43,7 @@ def parse(key, value) config.update_mirror(mirror) end - private + private def fetch_valid_mirror_for(uri) downcased = uri.to_s.downcase @@ -158,7 +158,7 @@ def replies?(mirror) end end - private + private def wait_for_writtable_socket(socket, address, timeout) if IO.select(nil, [socket], nil, timeout) diff --git a/ruby/lib/bundler/plugin.rb b/ruby/lib/bundler/plugin.rb index f4dd435df..158c69e1a 100644 --- a/ruby/lib/bundler/plugin.rb +++ b/ruby/lib/bundler/plugin.rb @@ -13,10 +13,11 @@ module Plugin class MalformattedPlugin < PluginError; end class UndefinedCommandError < PluginError; end class UnknownSourceError < PluginError; end + class PluginInstallError < PluginError; end PLUGIN_FILE_NAME = "plugins.rb".freeze - module_function + module_function def reset! instance_variables.each {|i| remove_instance_variable(i) } @@ -38,13 +39,37 @@ def install(names, options) specs = Installer.new.install(names, options) save_plugins names, specs - rescue PluginError => e - if specs - specs_to_delete = Hash[specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }] - specs_to_delete.values.each {|spec| Bundler.rm_rf(spec.full_gem_path) } + rescue PluginError + specs_to_delete = specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) } + specs_to_delete.each_value {|spec| Bundler.rm_rf(spec.full_gem_path) } + + raise + end + + # Uninstalls plugins by the given names + # + # @param [Array] names the names of plugins to be uninstalled + def uninstall(names, options) + if names.empty? && !options[:all] + Bundler.ui.error "No plugins to uninstall. Specify at least 1 plugin to uninstall.\n"\ + "Use --all option to uninstall all the installed plugins." + return end - Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}" + names = index.installed_plugins if options[:all] + if names.any? + names.each do |name| + if index.installed?(name) + Bundler.rm_rf(index.plugin_path(name)) + index.unregister_plugin(name) + Bundler.ui.info "Uninstalled plugin #{name}" + else + Bundler.ui.error "Plugin #{name} is not installed \n" + end + end + else + Bundler.ui.info "No plugins installed" + end end # List installed plugins and commands @@ -80,6 +105,7 @@ def gemfile_install(gemfile = nil, &inline) else builder.eval_gemfile(gemfile) end + builder.check_primary_source_safety definition = builder.to_definition(nil, true) return if definition.dependencies.empty? @@ -138,7 +164,7 @@ def command?(command) end # To be called from Cli class to pass the command and argument to - # approriate plugin class + # appropriate plugin class def exec_command(command, args) raise UndefinedCommandError, "Command `#{command}` not found" unless command? command @@ -157,7 +183,7 @@ def source?(name) !index.source_plugin(name.to_s).nil? end - # @return [Class] that handles the source. The calss includes API::Source + # @return [Class] that handles the source. The class includes API::Source def source(name) raise UnknownSourceError, "Source #{name} not found" unless source? name @@ -219,10 +245,11 @@ def installed?(plugin) # @param [Array] names of inferred source plugins that can be ignored def save_plugins(plugins, specs, optional_plugins = []) plugins.each do |name| + next if index.installed?(name) + spec = specs[name] - validate_plugin! Pathname.new(spec.full_gem_path) - installed = register_plugin(name, spec, optional_plugins.include?(name)) - Bundler.ui.info "Installed plugin #{name}" if installed + + save_plugin(name, spec, optional_plugins.include?(name)) end end @@ -237,6 +264,22 @@ def validate_plugin!(plugin_path) raise MalformattedPlugin, "#{PLUGIN_FILE_NAME} was not found in the plugin." unless plugin_file.file? end + # Validates and registers a plugin. + # + # @param [String] name the name of the plugin + # @param [Specification] spec of installed plugin + # @param [Boolean] optional_plugin, removed if there is conflict with any + # other plugin (used for default source plugins) + # + # @raise [PluginInstallError] if validation or registration raises any error + def save_plugin(name, spec, optional_plugin = false) + validate_plugin! Pathname.new(spec.full_gem_path) + installed = register_plugin(name, spec, optional_plugin) + Bundler.ui.info "Installed plugin #{name}" if installed + rescue PluginError => e + raise PluginInstallError, "Failed to install plugin `#{spec.name}`, due to #{e.class} (#{e.message})" + end + # Runs the plugins.rb file in an isolated namespace, records the plugin # actions it registers for and then passes the data to index to be stored. # @@ -283,6 +326,8 @@ def register_plugin(name, spec, optional_plugin = false) # # @param [String] name of the plugin def load_plugin(name) + return unless name && !name.empty? + # Need to ensure before this that plugin root where the rest of gems # are installed to be on load path to support plugin deps. Currently not # done to avoid conflicts diff --git a/ruby/lib/bundler/plugin/api/source.rb b/ruby/lib/bundler/plugin/api/source.rb index 56e97f4aa..32b1d0ee3 100644 --- a/ruby/lib/bundler/plugin/api/source.rb +++ b/ruby/lib/bundler/plugin/api/source.rb @@ -140,6 +140,13 @@ def specs end end + # Set internal representation to fetch the gems/specs locally. + # + # When this is called, the source should try to fetch the specs and + # install from the local system. + def local! + end + # Set internal representation to fetch the gems/specs from remote. # # When this is called, the source should try to fetch the specs and @@ -237,6 +244,20 @@ def unmet_deps specs.unmet_dependency_names end + # Used by definition. + # + # Note: Do not override if you don't know what you are doing. + def spec_names + specs.spec_names + end + + # Used by definition. + # + # Note: Do not override if you don't know what you are doing. + def add_dependency_names(names) + @dependencies |= Array(names) + end + # Note: Do not override if you don't know what you are doing. def can_lock?(spec) spec.source == self @@ -260,8 +281,9 @@ def to_lock end def to_s - "plugin source for #{options[:type]} with uri #{uri}" + "plugin source for #{@type} with uri #{@uri}" end + alias_method :identifier, :to_s # Note: Do not override if you don't know what you are doing. def include?(other) diff --git a/ruby/lib/bundler/plugin/dsl.rb b/ruby/lib/bundler/plugin/dsl.rb index 4bfc8437e..da751d177 100644 --- a/ruby/lib/bundler/plugin/dsl.rb +++ b/ruby/lib/bundler/plugin/dsl.rb @@ -10,7 +10,7 @@ class PluginGemfileError < PluginError; end # So that we don't have to override all there methods to dummy ones # explicitly. # They will be handled by method_missing - [:gemspec, :gem, :path, :install_if, :platforms, :env].each {|m| undef_method m } + [:gemspec, :gem, :install_if, :platforms, :env].each {|m| undef_method m } # This lists the plugins that was added automatically and not specified by # the user. diff --git a/ruby/lib/bundler/plugin/index.rb b/ruby/lib/bundler/plugin/index.rb index 2d70a046b..29d33be71 100644 --- a/ruby/lib/bundler/plugin/index.rb +++ b/ruby/lib/bundler/plugin/index.rb @@ -71,6 +71,18 @@ def register_plugin(name, path, load_paths, commands, sources, hooks) raise end + def unregister_plugin(name) + @commands.delete_if {|_, v| v == name } + @sources.delete_if {|_, v| v == name } + @hooks.each do |hook, names| + names.delete(name) + @hooks.delete(hook) if names.empty? + end + @plugin_paths.delete(name) + @load_paths.delete(name) + save_index + end + # Path of default index file def index_file Plugin.root.join("index") @@ -124,7 +136,7 @@ def hook_plugins(event) @hooks[event] || [] end - private + private # Reads the index file from the directory and initializes the instance # variables. diff --git a/ruby/lib/bundler/plugin/installer.rb b/ruby/lib/bundler/plugin/installer.rb index bcea3f0e4..81ecafa47 100644 --- a/ruby/lib/bundler/plugin/installer.rb +++ b/ruby/lib/bundler/plugin/installer.rb @@ -16,15 +16,13 @@ def install(names, options) version = options[:version] || [">= 0"] - Bundler.settings.temporary(:disable_multisource => false) do - if options[:git] - install_git(names, version, options) - elsif options[:local_git] - install_local_git(names, version, options) - else - sources = options[:source] || Bundler.rubygems.sources - install_rubygems(names, version, sources) - end + if options[:git] + install_git(names, version, options) + elsif options[:local_git] + install_local_git(names, version, options) + else + sources = options[:source] || Gem.sources + install_rubygems(names, version, sources) end end @@ -41,7 +39,7 @@ def definition.lock(*); end install_from_specs specs end - private + private def check_sources_consistency!(options) if options.key?(:git) && options.key?(:local_git) @@ -79,10 +77,12 @@ def install_all_sources(names, version, git_source_options, rubygems_source) source_list = SourceList.new source_list.add_git_source(git_source_options) if git_source_options - source_list.add_rubygems_source("remotes" => rubygems_source) if rubygems_source + Array(rubygems_source).each {|remote| source_list.add_global_rubygems_remote(remote) } if rubygems_source deps = names.map {|name| Dependency.new name, version } + Bundler.configure_gem_home_and_path(Plugin.root) + definition = Definition.new(nil, deps, source_list, true) install_definition(definition) end diff --git a/ruby/lib/bundler/plugin/installer/rubygems.rb b/ruby/lib/bundler/plugin/installer/rubygems.rb index 7ae74fa93..e144c14b2 100644 --- a/ruby/lib/bundler/plugin/installer/rubygems.rb +++ b/ruby/lib/bundler/plugin/installer/rubygems.rb @@ -8,7 +8,7 @@ def version_message(spec) "#{spec.name} #{spec.version}" end - private + private def requires_sudo? false # Will change on implementation of project level plugins diff --git a/ruby/lib/bundler/plugin/source_list.rb b/ruby/lib/bundler/plugin/source_list.rb index f0e212205..547661cf2 100644 --- a/ruby/lib/bundler/plugin/source_list.rb +++ b/ruby/lib/bundler/plugin/source_list.rb @@ -17,7 +17,11 @@ def all_sources path_sources + git_sources + rubygems_sources + [metadata_source] end - private + def default_source + git_sources.first || global_rubygems_source + end + + private def rubygems_aggregate_class Plugin::Installer::Rubygems diff --git a/ruby/lib/bundler/process_lock.rb b/ruby/lib/bundler/process_lock.rb index cba4fcdba..a5cc614e2 100644 --- a/ruby/lib/bundler/process_lock.rb +++ b/ruby/lib/bundler/process_lock.rb @@ -12,7 +12,7 @@ def self.lock(bundle_path = Bundler.bundle_path) yield f.flock(File::LOCK_UN) end - rescue Errno::EACCES, Errno::ENOLCK, *[SharedHelpers.const_get_safely(:ENOTSUP, Errno)].compact + rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP # In the case the user does not have access to # create the lock file or is using NFS where # locks are not available we skip locking. diff --git a/ruby/lib/bundler/psyched_yaml.rb b/ruby/lib/bundler/psyched_yaml.rb deleted file mode 100644 index c086b7651..000000000 --- a/ruby/lib/bundler/psyched_yaml.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -# Psych could be a gem, so try to ask for it -begin - gem "psych" -rescue LoadError -end if defined?(gem) - -# Psych could be in the stdlib -# but it's too late if Syck is already loaded -begin - require "psych" unless defined?(Syck) -rescue LoadError - # Apparently Psych wasn't available. Oh well. -end - -# At least load the YAML stdlib, whatever that may be -require "yaml" unless defined?(YAML.dump) - -module Bundler - # On encountering invalid YAML, - # Psych raises Psych::SyntaxError - if defined?(::Psych::SyntaxError) - YamlLibrarySyntaxError = ::Psych::SyntaxError - else # Syck raises ArgumentError - YamlLibrarySyntaxError = ::ArgumentError - end -end - -require_relative "deprecate" -begin - Bundler::Deprecate.skip_during do - require "rubygems/safe_yaml" - end -rescue LoadError - # it's OK if the file isn't there -end diff --git a/ruby/lib/bundler/remote_specification.rb b/ruby/lib/bundler/remote_specification.rb index f87a09b9a..4e966b820 100644 --- a/ruby/lib/bundler/remote_specification.rb +++ b/ruby/lib/bundler/remote_specification.rb @@ -27,6 +27,13 @@ def fetch_platform @platform = _remote_specification.platform end + # A fallback is included because the original version of the specification + # API didn't include that field, so some marshalled specs in the index have it + # set to +nil+. + def required_rubygems_version + @required_rubygems_version ||= _remote_specification.required_rubygems_version || Gem::Requirement.default + end + def full_name if platform == Gem::Platform::RUBY || platform.nil? "#{@name}-#{@version}" @@ -50,6 +57,8 @@ def <=>(other) # once the remote gem is downloaded, the backend specification will # be swapped out. def __swap__(spec) + raise APIResponseInvalidDependenciesError unless spec.dependencies.all? {|d| d.is_a?(Gem::Dependency) } + SharedHelpers.ensure_same_dependencies(self, dependencies, spec.dependencies) @_remote_specification = spec end @@ -76,7 +85,8 @@ def dependencies deps = method_missing(:dependencies) # allow us to handle when the specs dependencies are an array of array of string - # see https://github.com/bundler/bundler/issues/5797 + # in order to delay the crash to `#__swap__` where it results in a friendlier error + # see https://github.com/rubygems/bundler/issues/5797 deps = deps.map {|d| d.is_a?(Gem::Dependency) ? d : Gem::Dependency.new(*d) } deps @@ -88,7 +98,7 @@ def git_version " #{source.revision[0..6]}" end - private + private def to_ary nil diff --git a/ruby/lib/bundler/resolver.rb b/ruby/lib/bundler/resolver.rb index c7caf01c7..be0751d9d 100644 --- a/ruby/lib/bundler/resolver.rb +++ b/ruby/lib/bundler/resolver.rb @@ -5,6 +5,8 @@ class Resolver require_relative "vendored_molinillo" require_relative "resolver/spec_group" + include GemHelpers + # Figures out the best possible configuration of gems that satisfies # the list of passed dependencies and any child dependencies without # causing any gem activation errors. @@ -15,16 +17,14 @@ class Resolver # ==== Returns # ,nil:: If the list of dependencies can be resolved, a # collection of gemspecs is returned. Otherwise, nil is returned. - def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) - platforms = Set.new(platforms) if platforms + def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) base = SpecSet.new(base) unless base.is_a?(SpecSet) - resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) + resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) result = resolver.start(requirements) - SpecSet.new(result) + SpecSet.new(SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") })) end - def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) - @index = index + def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) @source_requirements = source_requirements @base = base @resolver = Molinillo::Resolver.new(self, self) @@ -32,14 +32,13 @@ def initialize(index, source_requirements, base, gem_version_promoter, additiona @base_dg = Molinillo::DependencyGraph.new @base.each do |ls| dep = Dependency.new(ls.name, ls.version) - @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true) + @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true) end additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) } - @platforms = platforms + @platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } } + @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY] @gem_version_promoter = gem_version_promoter - @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts? @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major? - @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource? end def start(requirements) @@ -49,7 +48,6 @@ def start(requirements) verify_gemfile_dependencies_are_found!(requirements) dg = @resolver.resolve(requirements, @base_dg) dg. - tap {|resolved| validate_resolved_specs!(resolved) }. map(&:payload). reject {|sg| sg.name.end_with?("\0") }. map(&:to_specs). @@ -75,12 +73,17 @@ def debug(depth = 0) return unless debug? debug_info = yield debug_info = debug_info.inspect unless debug_info.is_a?(String) - warn debug_info.split("\n").map {|s| " " * depth + s } + puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" } end def debug? return @debug_mode if defined?(@debug_mode) - @debug_mode = ENV["DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER_TREE"] || false + @debug_mode = + ENV["BUNDLER_DEBUG_RESOLVER"] || + ENV["BUNDLER_DEBUG_RESOLVER_TREE"] || + ENV["DEBUG_RESOLVER"] || + ENV["DEBUG_RESOLVER_TREE"] || + false end def before_resolution @@ -101,18 +104,18 @@ def dependencies_for(specification) specification.dependencies_for_activated_platforms end - def search_for(dependency) - platform = dependency.__platform - dependency = dependency.dep unless dependency.is_a? Gem::Dependency - search = @search_for[dependency] ||= begin - index = index_for(dependency) - results = index.search(dependency, @base[dependency.name]) + def search_for(dependency_proxy) + platform = dependency_proxy.__platform + dependency = dependency_proxy.dep + name = dependency.name + @search_for[dependency_proxy] ||= begin + results = results_for(dependency, @base[name]) - if vertex = @base_dg.vertex_named(dependency.name) + if vertex = @base_dg.vertex_named(name) locked_requirement = vertex.payload.requirement end - if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?) + if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?) # Move prereleases to the beginning of the list, so they're considered # last during resolution. pre, results = results.partition {|spec| spec.version.prerelease? } @@ -131,9 +134,21 @@ def search_for(dependency) end nested.reduce([]) do |groups, (version, specs)| next groups if locked_requirement && !locked_requirement.satisfied_by?(version) - spec_group = SpecGroup.new(specs) - spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts + next groups unless specs.any? {|spec| spec.match_platform(platform) } + + specs_by_platform = Hash.new do |current_specs, current_platform| + current_specs[current_platform] = select_best_platform_match(specs, current_platform) + end + + spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY) + groups << spec_group_ruby if spec_group_ruby + + next groups if @resolving_only_for_ruby + + spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform) groups << spec_group + + groups end else [] @@ -146,24 +161,18 @@ def search_for(dependency) @gem_version_promoter.sort_versions(dependency, spec_groups) end end - search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) } end def index_for(dependency) - source = @source_requirements[dependency.name] - if source - source.specs - elsif @lockfile_uses_separate_rubygems_sources - Index.build do |idx| - if dependency.all_sources - dependency.all_sources.each {|s| idx.add_source(s.specs) if s } - else - idx.add_source @source_requirements[:default].specs - end - end - else - @index - end + source_for(dependency.name).specs + end + + def source_for(name) + @source_requirements[name] || @source_requirements[:default] + end + + def results_for(dependency, base) + index_for(dependency).search(dependency, base) end def name_for(dependency) @@ -183,24 +192,15 @@ def name_for_locking_dependency_source end def requirement_satisfied_by?(requirement, activated, spec) - return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec) - spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform) - true + requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec) end - def relevant_sources_for_vertex(vertex) - if vertex.root? - [@source_requirements[vertex.name]] - elsif @lockfile_uses_separate_rubygems_sources - vertex.recursive_predecessors.map do |v| - @source_requirements[v.name] - end << @source_requirements[:default] - end + def dependencies_equal?(dependencies, other_dependencies) + dependencies.map(&:dep) == other_dependencies.map(&:dep) end def sort_dependencies(dependencies, activated, conflicts) dependencies.sort_by do |dependency| - dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name)) name = name_for(dependency) vertex = activated.vertex_named(name) [ @@ -215,19 +215,13 @@ def sort_dependencies(dependencies, activated, conflicts) end end - # Sort platforms from most general to most specific - def self.sort_platforms(platforms) - platforms.sort_by do |platform| - platform_sort_key(platform) - end - end - def self.platform_sort_key(platform) - return ["", "", ""] if Gem::Platform::RUBY == platform - platform.to_a.map {|part| part || "" } + # Prefer specific platform to not specific platform + return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform + ["00", *platform.to_a.map {|part| part || "" }] end - private + private # returns an integer \in (-\infty, 0] # a number closer to 0 means the dependency is less constraining @@ -255,16 +249,11 @@ def amount_constrained(dependency) end def verify_gemfile_dependencies_are_found!(requirements) - requirements.each do |requirement| + requirements.map! do |requirement| name = requirement.name - next if name == "bundler" - next unless search_for(requirement).empty? - - cache_message = begin - " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist? - rescue GemfileNotFound - nil - end + next requirement if name == "bundler" + next requirement unless search_for(requirement).empty? + next unless requirement.current_platform? if (base = @base[name]) && !base.empty? version = base.first.version @@ -274,41 +263,53 @@ def verify_gemfile_dependencies_are_found!(requirements) "Try running `bundle update #{name}`\n\n" \ "If you are updating multiple gems in your Gemfile at once,\n" \ "try passing them all to `bundle update`" - elsif source = @source_requirements[name] - specs = source.specs[name] - versions_with_platforms = specs.map {|s| [s.version, s.platform] } - message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n") - message << if versions_with_platforms.any? - "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}" - else - "The source does not contain any versions of '#{name}'" - end else - message = "Could not find gem '#{requirement}' in any of the gem sources " \ - "listed in your Gemfile#{cache_message}." + message = gem_not_found_message(name, requirement, source_for(name)) end raise GemNotFound, message - end + end.compact! end - def formatted_versions_with_platforms(versions_with_platforms) - version_platform_strs = versions_with_platforms.map do |vwp| - version = vwp.first - platform = vwp.last - version_platform_str = String.new(version.to_s) - version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY - version_platform_str + def gem_not_found_message(name, requirement, source, extra_message = "") + specs = source.specs.search(name) + matching_part = name + requirement_label = SharedHelpers.pretty_dependency(requirement) + cache_message = begin + " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist? + rescue GemfileNotFound + nil + end + specs_matching_requirement = specs.select {| spec| requirement.matches_spec?(spec) } + + if specs_matching_requirement.any? + specs = specs_matching_requirement + matching_part = requirement_label + requirement_label = "#{requirement_label} #{requirement.__platform}" end - version_platform_strs.join(", ") + + message = String.new("Could not find gem '#{requirement_label}'#{extra_message} in #{source}#{cache_message}.\n") + + if specs.any? + message << "\nThe source contains the following gems matching '#{matching_part}':\n" + message << specs.map {|s| " * #{s.full_name}" }.join("\n") + end + + message end def version_conflict_message(e) # only show essential conflicts, if possible conflicts = e.conflicts.dup - conflicts.delete_if do |_name, conflict| - deps = conflict.requirement_trees.map(&:last).flatten(1) - !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement))) + + if conflicts["bundler"] + conflicts.replace("bundler" => conflicts["bundler"]) + else + conflicts.delete_if do |_name, conflict| + deps = conflict.requirement_trees.map(&:last).flatten(1) + !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement))) + end end + e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty? solver_name = "Bundler" @@ -336,51 +337,40 @@ def version_conflict_message(e) :additional_message_for_conflict => lambda do |o, name, conflict| if name == "bundler" o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION})) - other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION)) - end - if name == "bundler" && other_bundler_required - o << "\n" - o << "This Gemfile requires a different version of Bundler.\n" - o << "Perhaps you need to update Bundler by running `gem install bundler`?\n" - end - if conflict.locked_requirement + conflict_dependency = conflict.requirement + conflict_requirement = conflict_dependency.requirement + other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION)) + + if other_bundler_required + o << "\n\n" + + candidate_specs = source_for(:default_bundler).specs.search(conflict_dependency) + if candidate_specs.any? + target_version = candidate_specs.last.version + new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ") + o << "Your bundle requires a different version of Bundler than the one you're running.\n" + o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n" + else + o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n" + end + end + elsif conflict.locked_requirement o << "\n" o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n) o << %(the gems in your Gemfile, which may resolve the conflict.\n) - elsif !conflict.existing + elsif !conflict.existing && !name.end_with?("\0") o << "\n" - relevant_sources = if conflict.requirement.source - [conflict.requirement.source] - elsif conflict.requirement.all_sources - conflict.requirement.all_sources - elsif @lockfile_uses_separate_rubygems_sources - # every conflict should have an explicit group of sources when we - # enforce strict pinning - raise "no source set for #{conflict}" - else - [] - end.compact.map(&:to_s).uniq.sort - - metadata_requirement = name.end_with?("\0") - - o << "Could not find gem '" unless metadata_requirement - o << SharedHelpers.pretty_dependency(conflict.requirement) - o << "'" unless metadata_requirement - if conflict.requirement_trees.first.size > 1 - o << ", which is required by " - o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}'," - end - o << " " + relevant_source = conflict.requirement.source || source_for(name) - o << if relevant_sources.empty? - "in any of the sources.\n" - elsif metadata_requirement - "is not available in #{relevant_sources.join(" or ")}" + extra_message = if conflict.requirement_trees.first.size > 1 + ", which is required by gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}'," else - "in any of the relevant sources:\n #{relevant_sources * "\n "}\n" + "" end + + o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message) end end, :version_for_spec => lambda {|spec| spec.version }, @@ -393,29 +383,5 @@ def version_conflict_message(e) end ) end - - def validate_resolved_specs!(resolved_specs) - resolved_specs.each do |v| - name = v.name - next unless sources = relevant_sources_for_vertex(v) - sources.compact! - if default_index = sources.index(@source_requirements[:default]) - sources.delete_at(default_index) - end - sources.reject! {|s| s.specs[name].empty? } - sources.uniq! - next if sources.size <= 1 - - multisource_disabled = Bundler.feature_flag.disable_multisource? - - msg = ["The gem '#{name}' was found in multiple relevant sources."] - msg.concat sources.map {|s| " * #{s}" }.sort - msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from." - msg = msg.join("\n") - - raise SecurityError, msg if multisource_disabled - Bundler.ui.warn "Warning: #{msg}" - end - end end end diff --git a/ruby/lib/bundler/resolver/spec_group.rb b/ruby/lib/bundler/resolver/spec_group.rb index e5772eed8..232520de7 100644 --- a/ruby/lib/bundler/resolver/spec_group.rb +++ b/ruby/lib/bundler/resolver/spec_group.rb @@ -3,61 +3,58 @@ module Bundler class Resolver class SpecGroup - include GemHelpers - attr_accessor :name, :version, :source - attr_accessor :ignores_bundler_dependencies + attr_accessor :activated_platforms + + def self.create_for(specs, all_platforms, specific_platform) + specific_platform_specs = specs[specific_platform] + return unless specific_platform_specs.any? + + platforms = all_platforms.select {|p| specs[p].any? } + + new(specific_platform_specs.first, specs, platforms) + end - def initialize(all_specs) - raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first + def initialize(exemplary_spec, specs, relevant_platforms) + @exemplary_spec = exemplary_spec @name = exemplary_spec.name @version = exemplary_spec.version @source = exemplary_spec.source - @activated_platforms = [] - @dependencies = nil - @specs = Hash.new do |specs, platform| - specs[platform] = select_best_platform_match(all_specs, platform) + @activated_platforms = relevant_platforms + @dependencies = Hash.new do |dependencies, platforms| + dependencies[platforms] = dependencies_for(platforms) end - @ignores_bundler_dependencies = true + @specs = specs end def to_specs - @activated_platforms.map do |p| - next unless s = @specs[p] - lazy_spec = LazySpecification.new(name, version, s.platform, source) - lazy_spec.dependencies.replace s.dependencies - lazy_spec - end.compact - end - - def activate_platform!(platform) - return unless for?(platform) - return if @activated_platforms.include?(platform) - @activated_platforms << platform - end + activated_platforms.map do |p| + specs = @specs[p] + next unless specs.any? - def for?(platform) - spec = @specs[platform] - !spec.nil? + specs.map do |s| + lazy_spec = LazySpecification.new(name, version, s.platform, source) + lazy_spec.dependencies.replace s.dependencies + lazy_spec + end + end.flatten.compact.uniq end def to_s - @to_s ||= "#{name} (#{version})" + activated_platforms_string = sorted_activated_platforms.join(", ") + "#{name} (#{version}) (#{activated_platforms_string})" end def dependencies_for_activated_platforms - dependencies = @activated_platforms.map {|p| __dependencies[p] } - metadata_dependencies = @activated_platforms.map do |platform| - metadata_dependencies(@specs[platform], platform) - end - dependencies.concat(metadata_dependencies).flatten + @dependencies[activated_platforms] end def ==(other) return unless other.is_a?(SpecGroup) name == other.name && version == other.version && + sorted_activated_platforms == other.sorted_activated_platforms && source == other.source end @@ -65,40 +62,46 @@ def eql?(other) return unless other.is_a?(SpecGroup) name.eql?(other.name) && version.eql?(other.version) && + sorted_activated_platforms.eql?(other.sorted_activated_platforms) && source.eql?(other.source) end def hash - to_s.hash ^ source.hash + name.hash ^ version.hash ^ sorted_activated_platforms.hash ^ source.hash end - private - - def __dependencies - @dependencies = Hash.new do |dependencies, platform| - dependencies[platform] = [] - if spec = @specs[platform] - spec.dependencies.each do |dep| - next if dep.type == :development - next if @ignores_bundler_dependencies && dep.name == "bundler".freeze - dependencies[platform] << DepProxy.new(dep, platform) - end - end - dependencies[platform] + protected + + def sorted_activated_platforms + activated_platforms.sort_by(&:to_s) + end + + private + + def dependencies_for(platforms) + platforms.map do |platform| + __dependencies(platform) + metadata_dependencies(platform) + end.flatten + end + + def __dependencies(platform) + dependencies = [] + @specs[platform].first.dependencies.each do |dep| + next if dep.type == :development + dependencies << DepProxy.get_proxy(dep, platform) end + dependencies end - def metadata_dependencies(spec, platform) - return [] unless spec - # Only allow endpoint specifications since they won't hit the network to - # fetch the full gemspec when calling required_ruby_version - return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification) + def metadata_dependencies(platform) + spec = @specs[platform].first + return [] if spec.is_a?(LazySpecification) dependencies = [] if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none? - dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform) + dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform) end if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none? - dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform) + dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform) end dependencies end diff --git a/ruby/lib/bundler/retry.rb b/ruby/lib/bundler/retry.rb index d64958ba7..2415ade20 100644 --- a/ruby/lib/bundler/retry.rb +++ b/ruby/lib/bundler/retry.rb @@ -32,7 +32,7 @@ def attempt(&block) end alias_method :attempts, :attempt - private + private def run(&block) @failed = false @@ -49,7 +49,7 @@ def fail_attempt(e) raise e end return true unless name - Bundler.ui.info "" unless Bundler.ui.debug? # Add new line incase dots preceded this + Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug? end diff --git a/ruby/lib/bundler/ruby_version.rb b/ruby/lib/bundler/ruby_version.rb index 7e403ce6f..d3b796392 100644 --- a/ruby/lib/bundler/ruby_version.rb +++ b/ruby/lib/bundler/ruby_version.rb @@ -103,7 +103,7 @@ def versions_string(versions) def self.system ruby_engine = RUBY_ENGINE.dup - ruby_version = ENV.fetch("BUNDLER_SPEC_RUBY_VERSION") { RUBY_VERSION }.dup + ruby_version = RUBY_VERSION.dup ruby_engine_version = RUBY_ENGINE_VERSION.dup patchlevel = RUBY_PATCHLEVEL.to_s @@ -123,7 +123,7 @@ def exact? @exact = versions.all? {|v| Gem::Requirement.create(v).exact? } end - private + private def matches?(requirements, version) # Handles RUBY_PATCHLEVEL of -1 for instances like ruby-head diff --git a/ruby/lib/bundler/rubygems_ext.rb b/ruby/lib/bundler/rubygems_ext.rb index eda826422..cc06b9ee9 100644 --- a/ruby/lib/bundler/rubygems_ext.rb +++ b/ruby/lib/bundler/rubygems_ext.rb @@ -4,14 +4,12 @@ require "rubygems/specification" -# Possible use in Gem::Specification#source below and require -# shouldn't be deferred. -require "rubygems/source" - require_relative "match_platform" module Gem class Specification + include ::Bundler::MatchPlatform + attr_accessor :remote, :location, :relative_loaded_from remove_method :source @@ -47,14 +45,13 @@ def load_paths full_require_paths end - if method_defined?(:extension_dir) - alias_method :rg_extension_dir, :extension_dir - def extension_dir - @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name) - File.expand_path(File.join(extensions_dir, source.extension_dir_name)) - else - rg_extension_dir - end + alias_method :rg_extension_dir, :extension_dir + def extension_dir + @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name) + unique_extension_dir = [source.extension_dir_name, File.basename(full_gem_path)].uniq.join("-") + File.expand_path(File.join(extensions_dir, unique_extension_dir)) + else + rg_extension_dir end end @@ -82,11 +79,26 @@ def to_gemfile(path = nil) gemfile end + # Backfill missing YAML require when not defined. Fixed since 3.1.0.pre1. + module YamlBackfiller + def to_yaml(opts = {}) + Gem.load_yaml unless defined?(::YAML) + + super(opts) + end + end + + prepend YamlBackfiller + def nondevelopment_dependencies dependencies - development_dependencies end - private + def deleted_gem? + !default_gem? && !File.directory?(full_gem_path) + end + + private def dependencies_to_gemfile(dependencies, group = nil) gemfile = String.new @@ -106,7 +118,7 @@ def dependencies_to_gemfile(dependencies, group = nil) end class Dependency - attr_accessor :source, :groups, :all_sources + attr_accessor :source, :groups alias_method :eql?, :== @@ -117,7 +129,7 @@ def encode_with(coder) end def to_yaml_properties - instance_variables.reject {|p| ["@source", "@groups", "@all_sources"].include?(p.to_s) } + instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) } end def to_lock @@ -130,25 +142,98 @@ def to_lock end end + # comparison is done order independently since rubygems 3.2.0.rc.2 + unless Gem::Requirement.new("> 1", "< 2") == Gem::Requirement.new("< 2", "> 1") + class Requirement + module OrderIndependentComparison + def ==(other) + return unless Gem::Requirement === other + + if _requirements_sorted? && other._requirements_sorted? + super + else + _with_sorted_requirements == other._with_sorted_requirements + end + end + + protected + + def _requirements_sorted? + return @_are_requirements_sorted if defined?(@_are_requirements_sorted) + strings = as_list + @_are_requirements_sorted = strings == strings.sort + end + + def _with_sorted_requirements + @_with_sorted_requirements ||= _requirements_sorted? ? self : self.class.new(as_list.sort) + end + end + + prepend OrderIndependentComparison + end + end + + if Gem::Requirement.new("~> 2.0").hash == Gem::Requirement.new("~> 2.0.0").hash + class Requirement + module CorrectHashForLambdaOperator + def hash + if requirements.any? {|r| r.first == "~>" } + requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash + else + super + end + end + end + + prepend CorrectHashForLambdaOperator + end + end + + require "rubygems/platform" + class Platform JAVA = Gem::Platform.new("java") unless defined?(JAVA) MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN) MSWIN64 = Gem::Platform.new("mswin64") unless defined?(MSWIN64) MINGW = Gem::Platform.new("x86-mingw32") unless defined?(MINGW) X64_MINGW = Gem::Platform.new("x64-mingw32") unless defined?(X64_MINGW) + end - undef_method :hash if method_defined? :hash - def hash - @cpu.hash ^ @os.hash ^ @version.hash - end + Platform.singleton_class.module_eval do + unless Platform.singleton_methods.include?(:match_spec?) + def match_spec?(spec) + match_gem?(spec.platform, spec.name) + end - undef_method :eql? if method_defined? :eql? - alias_method :eql?, :== + def match_gem?(platform, gem_name) + match_platforms?(platform, Gem.platforms) + end + + private + + def match_platforms?(platform, platforms) + platforms.any? do |local_platform| + platform.nil? || + local_platform == platform || + (local_platform != Gem::Platform::RUBY && local_platform =~ platform) + end + end + end end -end -module Gem - class Specification - include ::Bundler::MatchPlatform + require "rubygems/util" + + Util.singleton_class.module_eval do + if Util.singleton_methods.include?(:glob_files_in_dir) # since 3.0.0.beta.2 + remove_method :glob_files_in_dir + end + + def glob_files_in_dir(glob, base_path) + if RUBY_VERSION >= "2.5" + Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) } + else + Dir.glob(File.join(base_path.to_s.gsub(/[\[\]]/, '\\\\\\&'), glob)).map! {|f| File.expand_path(f) } + end + end end end diff --git a/ruby/lib/bundler/rubygems_gem_installer.rb b/ruby/lib/bundler/rubygems_gem_installer.rb index b1076b455..452583617 100644 --- a/ruby/lib/bundler/rubygems_gem_installer.rb +++ b/ruby/lib/bundler/rubygems_gem_installer.rb @@ -4,14 +4,60 @@ module Bundler class RubyGemsGemInstaller < Gem::Installer - unless respond_to?(:at) - def self.at(*args) - new(*args) + def check_executable_overwrite(filename) + # Bundler needs to install gems regardless of binstub overwriting + end + + def install + pre_install_checks + + run_pre_install_hooks + + spec.loaded_from = spec_file + + # Completely remove any previous gem files + strict_rm_rf gem_dir + strict_rm_rf spec.extension_dir + + SharedHelpers.filesystem_access(gem_dir, :create) do + FileUtils.mkdir_p gem_dir, :mode => 0o755 + end + + extract_files + + build_extensions + write_build_info_file + run_post_build_hooks + + generate_bin + generate_plugins + + write_spec + + SharedHelpers.filesystem_access("#{gem_home}/cache", :write) do + write_cache_file end + + say spec.post_install_message unless spec.post_install_message.nil? + + run_post_install_hooks + + spec end - def check_executable_overwrite(filename) - # Bundler needs to install gems regardless of binstub overwriting + def generate_plugins + return unless Gem::Installer.instance_methods(false).include?(:generate_plugins) + + latest = Gem::Specification.stubs_for(spec.name).first + return if latest && latest.version > spec.version + + ensure_writable_dir @plugins_dir + + if spec.plugins.empty? + remove_plugins_for(spec, @plugins_dir) + else + regenerate_plugins_for(spec, @plugins_dir) + end end def pre_install_checks @@ -20,7 +66,10 @@ def pre_install_checks def build_extensions extension_cache_path = options[:bundler_extension_cache_path] - return super unless extension_cache_path && extension_dir = Bundler.rubygems.spec_extension_dir(spec) + unless extension_cache_path && extension_dir = spec.extension_dir + require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25") + return super + end extension_dir = Pathname.new(extension_dir) build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?) @@ -30,6 +79,7 @@ def build_extensions FileUtils.cp_r extension_cache_path, spec.extension_dir end else + require "shellwords" # compensate missing require in rubygems before version 3.2.25 super if extension_dir.directory? # not made for gems without extensions SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath) @@ -40,7 +90,18 @@ def build_extensions end end - private + private + + def strict_rm_rf(dir) + # FileUtils.rm_rf should probably rise in case of permission issues like + # `rm -rf` does. However, it fails to delete the folder silently due to + # https://github.com/ruby/fileutils/issues/57. It should probably be fixed + # inside `fileutils` but for now I`m checking whether the folder was + # removed after it completes, and raising otherwise. + FileUtils.rm_rf dir + + raise PermissionError.new(dir, :delete) if File.directory?(dir) + end def validate_bundler_checksum(checksum) return true if Bundler.settings[:disable_checksum_validation] @@ -66,7 +127,7 @@ def validate_bundler_checksum(checksum) If you wish to continue installing the downloaded gem, and are certain it does not pose a \ security issue despite the mismatching checksum, do the following: - 1. run `bundle config set disable_checksum_validation true` to turn off checksum verification + 1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification 2. run `bundle install` (More info: The expected SHA256 checksum was #{checksum.inspect}, but the \ diff --git a/ruby/lib/bundler/rubygems_integration.rb b/ruby/lib/bundler/rubygems_integration.rb index d97621cd9..1c2b374d8 100644 --- a/ruby/lib/bundler/rubygems_integration.rb +++ b/ruby/lib/bundler/rubygems_integration.rb @@ -12,32 +12,30 @@ class RubygemsIntegration EXT_LOCK = Monitor.new end - def self.version - @version ||= Gem::Version.new(Gem::VERSION) - end - - def self.provides?(req_str) - Gem::Requirement.new(req_str).satisfied_by?(version) - end - def initialize @replaced_methods = {} backport_ext_builder_monitor end def version - self.class.version + @version ||= Gem.rubygems_version end def provides?(req_str) - self.class.provides?(req_str) + Gem::Requirement.new(req_str).satisfied_by?(version) + end + + def supports_bundler_trampolining? + provides?(">= 3.3.0.a") end def build_args + require "rubygems/command" Gem::Command.build_args end def build_args=(args) + require "rubygems/command" Gem::Command.build_args = args end @@ -84,16 +82,12 @@ def set_installed_by_version(spec, installed_by_version = Gem::VERSION) def spec_missing_extensions?(spec, default = true) return spec.missing_extensions? if spec.respond_to?(:missing_extensions?) - return false if spec_default_gem?(spec) + return false if spec.default_gem? return false if spec.extensions.empty? default end - def spec_default_gem?(spec) - spec.respond_to?(:default_gem?) && spec.default_gem? - end - def spec_matches_for_glob(spec, glob) return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob) @@ -102,11 +96,6 @@ def spec_matches_for_glob(spec, glob) end.flatten(1) end - def spec_extension_dir(spec) - return unless spec.respond_to?(:extension_dir) - spec.extension_dir - end - def stub_set_spec(stub, spec) stub.instance_variable_set(:@spec, spec) end @@ -115,23 +104,6 @@ def path(obj) obj.to_s end - def platforms - return [Gem::Platform::RUBY] if Bundler.settings[:force_ruby_platform] - Gem.platforms - end - - def configuration - require_relative "psyched_yaml" - Gem.configuration - rescue Gem::SystemExitException, LoadError => e - Bundler.ui.error "#{e.class}: #{e.message}" - Bundler.ui.trace e - raise - rescue YamlLibrarySyntaxError => e - raise YamlSyntaxError.new(e, "Your RubyGems configuration, which is " \ - "usually located in ~/.gemrc, contains invalid YAML syntax.") - end - def ruby_engine Gem.ruby_engine end @@ -141,14 +113,10 @@ def read_binary(path) end def inflate(obj) - require "rubygems/util" - Gem::Util.inflate(obj) end def correct_for_windows_path(path) - require "rubygems/util" - if Gem::Util.respond_to?(:correct_for_windows_path) Gem::Util.correct_for_windows_path(path) elsif path[0].chr == "/" && path[1].chr =~ /[a-z]/i && path[2].chr == ":" @@ -158,19 +126,6 @@ def correct_for_windows_path(path) end end - def sources=(val) - # Gem.configuration creates a new Gem::ConfigFile, which by default will read ~/.gemrc - # If that file exists, its settings (including sources) will overwrite the values we - # are about to set here. In order to avoid that, we force memoizing the config file now. - configuration - - Gem.sources = val - end - - def sources - Gem.sources - end - def gem_dir Gem.dir end @@ -223,11 +178,6 @@ def bin_path(gem, bin, ver) Gem.bin_path(gem, bin, ver) end - def preserve_paths - # this is a no-op outside of RubyGems 1.8 - yield - end - def loaded_gem_paths loaded_gem_paths = Gem.loaded_specs.map {|_, s| s.full_require_paths } loaded_gem_paths.flatten @@ -241,6 +191,10 @@ def load_plugin_files(files) Gem.load_plugin_files(files) if Gem.respond_to?(:load_plugin_files) end + def load_env_plugins + Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins) + end + def ui=(obj) Gem::DefaultUserInteraction.ui = obj end @@ -249,24 +203,10 @@ def ext_lock EXT_LOCK end - def with_build_args(args) - ext_lock.synchronize do - old_args = build_args - begin - self.build_args = args - yield - ensure - self.build_args = old_args - end - end - end - def spec_from_gem(path, policy = nil) require "rubygems/security" - require_relative "psyched_yaml" + require "psych" gem_from_path(path, security_policies[policy]).spec - rescue Gem::Package::FormatError - raise GemspecError, "Could not read gem at #{path}. It may be corrupted." rescue Exception, Gem::Exception, Gem::Security::Exception => e # rubocop:disable Lint/RescueException if e.is_a?(Gem::Security::Exception) || e.message =~ /unknown trust policy|unsigned gem/i || @@ -329,8 +269,13 @@ def replace_gem(specs, specs_by_name) end message = if spec.nil? + target_file = begin + Bundler.default_gemfile.basename + rescue GemfileNotFound + "inline Gemfile" + end "#{dep.name} is not part of the bundle." \ - " Add it to your #{Bundler.default_gemfile.basename}." + " Add it to your #{target_file}." else "can't activate #{dep}, already activated #{spec.full_name}. " \ "Make sure all dependencies are added to Gemfile." @@ -346,7 +291,7 @@ def replace_gem(specs, specs_by_name) raise e end - # backwards compatibility shim, see https://github.com/bundler/bundler/issues/5102 + # backwards compatibility shim, see https://github.com/rubygems/bundler/issues/5102 kernel_class.send(:public, :gem) if Bundler.feature_flag.setup_makes_kernel_gem_public? end end @@ -422,6 +367,17 @@ def replace_bin_path(specs_by_name) # Replace or hook into RubyGems to provide a bundlerized view # of the world. def replace_entrypoints(specs) + specs_by_name = add_default_gems_to(specs) + + replace_gem(specs, specs_by_name) + stub_rubygems(specs) + replace_bin_path(specs_by_name) + + Gem.clear_paths + end + + # Add default gems not already present in specs, and return them as a hash. + def add_default_gems_to(specs) specs_by_name = specs.reduce({}) do |h, s| h[s.name] = s h @@ -436,40 +392,7 @@ def replace_entrypoints(specs) specs_by_name[default_spec_name] = default_spec end - replace_gem(specs, specs_by_name) - stub_rubygems(specs) - replace_bin_path(specs_by_name) - - Gem.clear_paths - end - - # This backports base_dir which replaces installation path - # RubyGems 1.8+ - def backport_base_dir - redefine_method(Gem::Specification, :base_dir) do - return Gem.dir unless loaded_from - File.dirname File.dirname loaded_from - end - end - - def backport_cache_file - redefine_method(Gem::Specification, :cache_dir) do - @cache_dir ||= File.join base_dir, "cache" - end - - redefine_method(Gem::Specification, :cache_file) do - @cache_file ||= File.join cache_dir, "#{full_name}.gem" - end - end - - def backport_spec_file - redefine_method(Gem::Specification, :spec_dir) do - @spec_dir ||= File.join base_dir, "specifications" - end - - redefine_method(Gem::Specification, :spec_file) do - @spec_file ||= File.join spec_dir, "#{full_name}.gemspec" - end + specs_by_name end def undo_replacements @@ -536,14 +459,15 @@ def plain_specs=(specs) end def fetch_specs(remote, name) + require "rubygems/remote_fetcher" path = remote.uri.to_s + "#{name}.#{Gem.marshal_version}.gz" fetcher = gem_remote_fetcher fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri string = fetcher.fetch_path(path) Bundler.load_marshal(string) - rescue Gem::RemoteFetcher::FetchError => e + rescue Gem::RemoteFetcher::FetchError # it's okay for prerelease to fail - raise e unless name == "prerelease_specs" + raise unless name == "prerelease_specs" end def fetch_all_remote_specs(remote) @@ -553,20 +477,41 @@ def fetch_all_remote_specs(remote) specs.concat(pres) end - def download_gem(spec, uri, path) + def download_gem(spec, uri, cache_dir) + require "rubygems/remote_fetcher" uri = Bundler.settings.mirror_for(uri) fetcher = gem_remote_fetcher fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri Bundler::Retry.new("download gem from #{uri}").attempts do - fetcher.download(spec, uri, path) + gem_file_name = spec.file_name + local_gem_path = File.join cache_dir, gem_file_name + return if File.exist? local_gem_path + + begin + remote_gem_path = uri + "gems/#{gem_file_name}" + remote_gem_path = remote_gem_path.to_s if provides?("< 3.2.0.rc.1") + + SharedHelpers.filesystem_access(local_gem_path) do + fetcher.cache_update_path remote_gem_path, local_gem_path + end + rescue Gem::RemoteFetcher::FetchError + raise if spec.original_platform == spec.platform + + original_gem_file_name = "#{spec.original_name}.gem" + raise if gem_file_name == original_gem_file_name + + gem_file_name = original_gem_file_name + retry + end end + rescue Gem::RemoteFetcher::FetchError => e + raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>" end def gem_remote_fetcher - require "resolv" - proxy = configuration[:http_proxy] - dns = Resolv::DNS.new - Gem::RemoteFetcher.new(proxy, dns) + require "rubygems/remote_fetcher" + proxy = Gem.configuration[:http_proxy] + Gem::RemoteFetcher.new(proxy) end def gem_from_path(path, policy = nil) @@ -585,16 +530,11 @@ def repository_subdirectories Gem::REPOSITORY_SUBDIRECTORIES end - def install_with_build_args(args) - yield - end - def path_separator Gem.path_separator end def all_specs - require_relative "remote_specification" Gem::Specification.stubs.map do |stub| StubSpecification.from_stub(stub) end @@ -602,10 +542,10 @@ def all_specs def backport_ext_builder_monitor # So we can avoid requiring "rubygems/ext" in its entirety - Gem.module_eval <<-RB, __FILE__, __LINE__ + 1 + Gem.module_eval <<-RUBY, __FILE__, __LINE__ + 1 module Ext end - RB + RUBY require "rubygems/ext/builder" @@ -619,6 +559,10 @@ module Ext end end + def find_bundler(version) + find_name("bundler").find {|s| s.version.to_s == version } + end + def find_name(name) Gem::Specification.stubs_for(name).map(&:to_spec) end @@ -632,14 +576,6 @@ def default_stubs Gem::Specification.send(:default_stubs, "*.gemspec") end end - - def use_gemdeps(gemfile) - ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile) - require_relative "gemdeps" - runtime = Bundler.setup - activated_spec_names = runtime.requested_specs.map(&:to_spec).sort_by(&:name) - [Gemdeps.new(runtime), activated_spec_names] - end end def self.rubygems diff --git a/ruby/lib/bundler/runtime.rb b/ruby/lib/bundler/runtime.rb index 93a801eb6..c7276b0e2 100644 --- a/ruby/lib/bundler/runtime.rb +++ b/ruby/lib/bundler/runtime.rb @@ -12,22 +12,16 @@ def initialize(root, definition) def setup(*groups) @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle? - groups.map!(&:to_sym) - # Has to happen first clean_load_path - specs = groups.any? ? @definition.specs_for(groups) : requested_specs + specs = @definition.specs_for(groups) SharedHelpers.set_bundle_environment Bundler.rubygems.replace_entrypoints(specs) # Activate the specs load_paths = specs.map do |spec| - unless spec.loaded_from - raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it." - end - check_for_activated_spec!(spec) Bundler.rubygems.mark_loaded(spec) @@ -43,14 +37,6 @@ def setup(*groups) self end - REQUIRE_ERRORS = [ - /^no such file to load -- (.+)$/i, - /^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i, - /^Missing API definition file in (.+)$/i, - /^cannot load such file -- (.+)$/i, - /^dlopen\([^)]*\): Library not loaded: (.+)$/i, - ].freeze - def require(*groups) groups.map!(&:to_sym) groups = [:default] if groups.empty? @@ -79,16 +65,14 @@ def require(*groups) end end rescue LoadError => e - REQUIRE_ERRORS.find {|r| r =~ e.message } - raise if dep.autorequire || $1 != required_file + raise if dep.autorequire || e.path != required_file if dep.autorequire.nil? && dep.name.include?("-") begin namespaced_file = dep.name.tr("-", "/") Kernel.require namespaced_file rescue LoadError => e - REQUIRE_ERRORS.find {|r| r =~ e.message } - raise if $1 != namespaced_file + raise if e.path != namespaced_file end end end @@ -116,7 +100,7 @@ def lock(opts = {}) alias_method :gems, :specs - def cache(custom_path = nil) + def cache(custom_path = nil, local = false) cache_path = Bundler.app_cache(custom_path) SharedHelpers.filesystem_access(cache_path) do |p| FileUtils.mkdir_p(p) @@ -124,7 +108,20 @@ def cache(custom_path = nil) Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}" - specs_to_cache = Bundler.settings[:cache_all_platforms] ? @definition.resolve.materialized_for_all_platforms : specs + specs_to_cache = if Bundler.settings[:cache_all_platforms] + @definition.resolve.materialized_for_all_platforms + else + begin + specs + rescue GemNotFound + if local + Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory." + end + + raise + end + end + specs_to_cache.each do |spec| next if spec.name == "bundler" next if spec.source.is_a?(Source::Gemspec) @@ -165,7 +162,7 @@ def clean(dry_run = false) spec_cache_paths = [] spec_gemspec_paths = [] spec_extension_paths = [] - specs.each do |spec| + Bundler.rubygems.add_default_gems_to(specs).values.each do |spec| spec_gem_paths << spec.full_gem_path # need to check here in case gems are nested like for the rails git repo md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path) @@ -213,7 +210,7 @@ def clean(dry_run = false) output end - private + private def prune_gem_cache(resolve, cache_path) cached = Dir["#{cache_path}/*.gem"] @@ -268,7 +265,7 @@ def setup_manpath return if manuals.empty? Bundler::SharedHelpers.set_env "MANPATH", manuals.concat( - ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR) + ENV["MANPATH"] ? ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR) : [""] ).uniq.join(File::PATH_SEPARATOR) end @@ -294,7 +291,7 @@ def check_for_activated_spec!(spec) return unless activated_spec = Bundler.rubygems.loaded_specs(spec.name) return if activated_spec.version == spec.version - suggestion = if Bundler.rubygems.spec_default_gem?(activated_spec) + suggestion = if activated_spec.default_gem? "Since #{spec.name} is a default gem, you can either remove your dependency on it" \ " or try updating to a newer version of bundler that supports #{spec.name} as a default gem." else diff --git a/ruby/lib/bundler/self_manager.rb b/ruby/lib/bundler/self_manager.rb new file mode 100644 index 000000000..827f3f922 --- /dev/null +++ b/ruby/lib/bundler/self_manager.rb @@ -0,0 +1,168 @@ +# frozen_string_literal: true + +module Bundler + # + # This class handles installing and switching to the version of bundler needed + # by an application. + # + class SelfManager + def restart_with_locked_bundler_if_needed + return unless needs_switching? && installed? + + restart_with(lockfile_version) + end + + def install_locked_bundler_and_restart_with_it_if_needed + return unless needs_switching? + + Bundler.ui.info \ + "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \ + "Installing Bundler #{lockfile_version} and restarting using that version." + + install_and_restart_with(lockfile_version) + end + + def update_bundler_and_restart_with_it_if_needed(target) + return unless autoswitching_applies? + + spec = resolve_update_version_from(target) + return unless spec + + version = spec.version + + Bundler.ui.info "Updating bundler to #{version}." + + install(spec) + + restart_with(version) + end + + private + + def install_and_restart_with(version) + requirement = Gem::Requirement.new(version) + spec = find_latest_matching_spec(requirement) + + if spec.nil? + Bundler.ui.warn "Your lockfile is locked to a version of bundler (#{lockfile_version}) that doesn't exist at https://rubygems.org/. Going on using #{current_version}" + return + end + + install(spec) + rescue StandardError => e + Bundler.ui.trace e + Bundler.ui.warn "There was an error installing the locked bundler version (#{lockfile_version}), rerun with the `--verbose` flag for more details. Going on using bundler #{current_version}." + else + restart_with(version) + end + + def install(spec) + spec.source.install(spec) + end + + def restart_with(version) + configured_gem_home = ENV["GEM_HOME"] + configured_gem_path = ENV["GEM_PATH"] + + cmd = [$PROGRAM_NAME, *ARGV] + cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME) + + Bundler.with_original_env do + Kernel.exec( + { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => version.to_s }, + *cmd + ) + end + end + + def needs_switching? + autoswitching_applies? && + released?(lockfile_version) && + !running?(lockfile_version) && + !updating? + end + + def autoswitching_applies? + ENV["BUNDLER_VERSION"].nil? && + Bundler.rubygems.supports_bundler_trampolining? && + SharedHelpers.in_bundle? && + lockfile_version + end + + def resolve_update_version_from(target) + requirement = Gem::Requirement.new(target) + update_candidate = find_latest_matching_spec(requirement) + + if update_candidate.nil? + raise InvalidOption, "The `bundle update --bundler` target version (#{target}) does not exist" + end + + resolved_version = update_candidate.version + needs_update = requirement.specific? ? !running?(resolved_version) : running_older_than?(resolved_version) + + return unless needs_update + + update_candidate + end + + def local_specs + @local_specs ||= Bundler::Source::Rubygems.new("allow_local" => true).specs.select {|spec| spec.name == "bundler" } + end + + def remote_specs + @remote_specs ||= begin + source = Bundler::Source::Rubygems.new("remotes" => "https://rubygems.org") + source.remote! + source.add_dependency_names("bundler") + source.specs + end + end + + def find_latest_matching_spec(requirement) + local_result = find_latest_matching_spec_from_collection(local_specs, requirement) + return local_result if local_result && requirement.specific? + + remote_result = find_latest_matching_spec_from_collection(remote_specs, requirement) + return remote_result if local_result.nil? + + [local_result, remote_result].max + end + + def find_latest_matching_spec_from_collection(specs, requirement) + specs.sort.reverse_each.find {|spec| requirement.satisfied_by?(spec.version) } + end + + def running?(version) + version == current_version + end + + def running_older_than?(version) + current_version < version + end + + def released?(version) + !version.to_s.end_with?(".dev") + end + + def updating? + "update".start_with?(ARGV.first || " ") && ARGV[1..-1].any? {|a| a.start_with?("--bundler") } + end + + def installed? + Bundler.configure + + Bundler.rubygems.find_bundler(lockfile_version.to_s) + end + + def current_version + @current_version ||= Gem::Version.new(Bundler::VERSION) + end + + def lockfile_version + return @lockfile_version if defined?(@lockfile_version) + + parsed_version = Bundler::LockfileParser.bundled_with + @lockfile_version = parsed_version ? Gem::Version.new(parsed_version) : nil + end + end +end diff --git a/ruby/lib/bundler/settings.rb b/ruby/lib/bundler/settings.rb index afbb02397..8f263cd01 100644 --- a/ruby/lib/bundler/settings.rb +++ b/ruby/lib/bundler/settings.rb @@ -7,35 +7,34 @@ class Settings autoload :Validator, File.expand_path("settings/validator", __dir__) BOOL_KEYS = %w[ - allow_bundler_dependency_conflicts allow_deployment_source_credential_changes allow_offline_install auto_clean_without_path auto_install - auto_config_jobs cache_all cache_all_platforms + clean default_install_uses_path deployment - deployment_means_frozen disable_checksum_validation disable_exec_load disable_local_branch_check - disable_multisource - disable_platform_warnings + disable_local_revision_check disable_shared_gems disable_version_check force_ruby_platform forget_cli_options frozen + gem.changelog gem.coc gem.mit + git.allow_insecure global_gem_cache ignore_messages init_gems_rb + inline no_install no_prune - only_update_to_newer_versions path_relative_to_cwd path.system plugins @@ -44,10 +43,7 @@ class Settings setup_makes_kernel_gem_public silence_deprecations silence_root_warning - skip_default_git_sources - specific_platform suppress_install_using_messages - unlock_source_unlocks_spec update_requires_all_flag use_gem_version_promoter_for_major_updates ].freeze @@ -65,31 +61,42 @@ class Settings without ].freeze + STRING_KEYS = %w[ + bin + cache_path + console + gem.ci + gem.github_username + gem.linter + gem.rubocop + gem.test + gemfile + path + shebang + system_bindir + trust-policy + ].freeze + DEFAULT_CONFIG = { - :silence_deprecations => false, - :disable_version_check => true, - :prefer_patch => false, - :redirect => 5, - :retry => 3, - :timeout => 10, + "BUNDLE_SILENCE_DEPRECATIONS" => false, + "BUNDLE_DISABLE_VERSION_CHECK" => true, + "BUNDLE_PREFER_PATCH" => false, + "BUNDLE_REDIRECT" => 5, + "BUNDLE_RETRY" => 3, + "BUNDLE_TIMEOUT" => 10, }.freeze def initialize(root = nil) @root = root @local_config = load_config(local_config_file) + @env_config = ENV.to_h.select {|key, _value| key =~ /\ABUNDLE_.+/ } @global_config = load_config(global_config_file) @temporary = {} end def [](name) key = key_for(name) - value = @temporary.fetch(key) do - @local_config.fetch(key) do - ENV.fetch(key) do - @global_config.fetch(key) do - DEFAULT_CONFIG.fetch(name) do - nil - end end end end end + value = configs.values.map {|config| config[key] }.compact.first converted_value(value, name) end @@ -132,13 +139,11 @@ def set_global(key, value) end def all - env_keys = ENV.keys.grep(/\ABUNDLE_.+/) - - keys = @temporary.keys | @global_config.keys | @local_config.keys | env_keys + keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys keys.map do |key| - key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase - end + key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase + end.sort end def local_overrides @@ -171,13 +176,11 @@ def gem_mirrors def locations(key) key = key_for(key) - locations = {} - locations[:temporary] = @temporary[key] if @temporary.key?(key) - locations[:local] = @local_config[key] if @local_config.key?(key) - locations[:env] = ENV[key] if ENV[key] - locations[:global] = @global_config[key] if @global_config.key?(key) - locations[:default] = DEFAULT_CONFIG[key] if DEFAULT_CONFIG.key?(key) - locations + configs.keys.inject({}) do |partial_locations, level| + value_on_level = configs[level][key] + partial_locations[level] = value_on_level unless value_on_level.nil? + partial_locations + end end def pretty_values_for(exposed_key) @@ -185,39 +188,49 @@ def pretty_values_for(exposed_key) locations = [] - if @temporary.key?(key) - locations << "Set for the current command: #{converted_value(@temporary[key], exposed_key).inspect}" + if value = @temporary[key] + locations << "Set for the current command: #{printable_value(value, exposed_key).inspect}" end - if @local_config.key?(key) - locations << "Set for your local app (#{local_config_file}): #{converted_value(@local_config[key], exposed_key).inspect}" + if value = @local_config[key] + locations << "Set for your local app (#{local_config_file}): #{printable_value(value, exposed_key).inspect}" end - if value = ENV[key] - locations << "Set via #{key}: #{converted_value(value, exposed_key).inspect}" + if value = @env_config[key] + locations << "Set via #{key}: #{printable_value(value, exposed_key).inspect}" end - if @global_config.key?(key) - locations << "Set for the current user (#{global_config_file}): #{converted_value(@global_config[key], exposed_key).inspect}" + if value = @global_config[key] + locations << "Set for the current user (#{global_config_file}): #{printable_value(value, exposed_key).inspect}" end return ["You have not configured a value for `#{exposed_key}`"] if locations.empty? locations end + def processor_count + require "etc" + Etc.nprocessors + rescue StandardError + 1 + end + # for legacy reasons, in Bundler 2, we do not respect :disable_shared_gems def path - key = key_for(:path) - path = ENV[key] || @global_config[key] - if path && !@temporary.key?(key) && !@local_config.key?(key) - return Path.new(path, false, false) + configs.each do |_level, settings| + path = value_for("path", settings) + path = "vendor/bundle" if value_for("deployment", settings) && path.nil? + path_system = value_for("path.system", settings) + disabled_shared_gems = value_for("disable_shared_gems", settings) + next if path.nil? && path_system.nil? && disabled_shared_gems.nil? + system_path = path_system || (disabled_shared_gems == false) + return Path.new(path, system_path) end - system_path = self["path.system"] || (self[:disable_shared_gems] == false) - Path.new(self[:path], system_path, Bundler.feature_flag.default_install_uses_path?) + Path.new(nil, false) end - Path = Struct.new(:explicit_path, :system_path, :default_install_uses_path) do + Path = Struct.new(:explicit_path, :system_path) do def path path = base_path path = File.join(path, Bundler.ruby_scope) unless use_system_gems? @@ -227,7 +240,7 @@ def path def use_system_gems? return true if system_path return false if explicit_path - !default_install_uses_path + !Bundler.feature_flag.default_install_uses_path? end def base_path @@ -280,20 +293,32 @@ def app_cache_path def validate! all.each do |raw_key| - [@local_config, ENV, @global_config].each do |settings| - value = converted_value(settings[key_for(raw_key)], raw_key) - Validator.validate!(raw_key, value, settings.to_hash.dup) + [@local_config, @env_config, @global_config].each do |settings| + value = value_for(raw_key, settings) + Validator.validate!(raw_key, value, settings.dup) end end end def key_for(key) - key = Settings.normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key - key = key.to_s.gsub(".", "__").upcase - "BUNDLE_#{key}" + self.class.key_for(key) end - private + private + + def configs + { + :temporary => @temporary, + :local => @local_config, + :env => @env_config, + :global => @global_config, + :default => DEFAULT_CONFIG, + } + end + + def value_for(name, config) + converted_value(config[key_for(name)], name) + end def parent_setting_for(name) split_specific_setting_for(name)[0] @@ -311,6 +336,10 @@ def is_bool(name) BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s)) end + def is_string(name) + STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.") + end + def to_bool(value) case value when nil, /\A(false|f|no|n|0|)\z/i, false @@ -328,9 +357,17 @@ def is_array(key) ARRAY_KEYS.include?(key.to_s) end + def is_credential(key) + key == "gem.push_key" + end + + def is_userinfo(value) + value.include?(":") + end + def to_array(value) return [] unless value - value.split(":").map(&:to_sym) + value.tr(" ", ":").split(":").map(&:to_sym) end def array_to_s(array) @@ -374,15 +411,38 @@ def converted_value(value, key) end end + def printable_value(value, key) + converted = converted_value(value, key) + return converted unless converted.is_a?(String) + + if is_string(key) + converted + elsif is_credential(key) + "[REDACTED]" + elsif is_userinfo(converted) + username, pass = converted.split(":", 2) + + if pass == "x-oauth-basic" + username = "[REDACTED]" + else + pass = "[REDACTED]" + end + + [username, pass].join(":") + else + converted + end + end + def global_config_file if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty? Pathname.new(ENV["BUNDLE_CONFIG"]) - else - begin - Bundler.user_bundle_path("config") - rescue PermissionError, GenericSystemCallError - nil - end + elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty? + Pathname.new(ENV["BUNDLE_USER_CONFIG"]) + elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty? + Pathname.new(ENV["BUNDLE_USER_HOME"]).join("config") + elsif Bundler.rubygems.user_home && !Bundler.rubygems.user_home.empty? + Pathname.new(Bundler.rubygems.user_home).join(".bundle/config") end end @@ -396,7 +456,20 @@ def load_config(config_file) valid_file = file.exist? && !file.size.zero? return {} unless valid_file require_relative "yaml_serializer" - YAMLSerializer.load file.read + YAMLSerializer.load(file.read).inject({}) do |config, (k, v)| + new_k = k + + if k.include?("-") + Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \ + "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ + "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)." + + new_k = k.gsub("-", "___") + end + + config[new_k] = v + config + end end end @@ -413,6 +486,12 @@ def load_config(config_file) \z /ix.freeze + def self.key_for(key) + key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key + key = key.to_s.gsub(".", "__").gsub("-", "___").upcase + "BUNDLE_#{key}" + end + # TODO: duplicates Rubygems#normalize_uri # TODO: is this the correct place to validate mirror URIs? def self.normalize_uri(uri) diff --git a/ruby/lib/bundler/setup.rb b/ruby/lib/bundler/setup.rb index 27911dc1a..32e9b2d7c 100644 --- a/ruby/lib/bundler/setup.rb +++ b/ruby/lib/bundler/setup.rb @@ -9,10 +9,10 @@ begin Bundler.ui.silence { Bundler.setup } rescue Bundler::BundlerError => e - Bundler.ui.warn "\e[31m#{e.message}\e[0m" + Bundler.ui.error e.message Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"] if e.is_a?(Bundler::GemNotFound) - Bundler.ui.warn "\e[33mRun `bundle install` to install missing gems.\e[0m" + Bundler.ui.warn "Run `bundle install` to install missing gems." end exit e.status_code end diff --git a/ruby/lib/bundler/shared_helpers.rb b/ruby/lib/bundler/shared_helpers.rb index 6e83bc5ff..e48010232 100644 --- a/ruby/lib/bundler/shared_helpers.rb +++ b/ruby/lib/bundler/shared_helpers.rb @@ -109,7 +109,7 @@ def filesystem_access(path, action = :write, &block) raise VirtualProtocolError.new rescue Errno::ENOSPC raise NoSpaceOnDeviceError.new(path, action) - rescue *[const_get_safely(:ENOTSUP, Errno)].compact + rescue Errno::ENOTSUP raise OperationNotSupportedError.new(path, action) rescue Errno::EEXIST, Errno::ENOENT raise @@ -117,13 +117,6 @@ def filesystem_access(path, action = :write, &block) raise GenericSystemCallError.new(e, "There was an error accessing `#{path}`.") end - def const_get_safely(constant_name, namespace) - const_in_namespace = namespace.constants.include?(constant_name.to_s) || - namespace.constants.include?(constant_name.to_sym) - return nil unless const_in_namespace - namespace.const_get(constant_name) - end - def major_deprecation(major_version, message, print_caller_location: false) if print_caller_location caller_location = caller_locations(2, 2).first @@ -152,13 +145,6 @@ def print_major_deprecations! Bundler.ui.warn message end - def trap(signal, override = false, &block) - prior = Signal.trap(signal) do - block.call - prior.call unless override - end - end - def ensure_same_dependencies(spec, old_deps, new_deps) new_deps = new_deps.reject {|d| d.type == :development } old_deps = old_deps.reject {|d| d.type == :development } @@ -194,11 +180,11 @@ def md5_available? return @md5_available if defined?(@md5_available) @md5_available = begin require "openssl" - OpenSSL::Digest::MD5.digest("") + ::OpenSSL::Digest.digest("MD5", "") true rescue LoadError true - rescue OpenSSL::Digest::DigestError + rescue ::OpenSSL::Digest::DigestError false end end @@ -212,7 +198,7 @@ def write_to_gemfile(gemfile_path, contents) filesystem_access(gemfile_path) {|g| File.open(g, "w") {|file| file.puts contents } } end - private + private def validate_bundle_path path_separator = Bundler.rubygems.path_separator @@ -253,7 +239,7 @@ def search_up(*names) current = File.expand_path(SharedHelpers.pwd).tap{|x| x.untaint if RUBY_VERSION < "2.7" } until !File.directory?(current) || current == previous - if ENV["BUNDLE_SPEC_RUN"] + if ENV["BUNDLER_SPEC_RUN"] # avoid stepping above the tmp directory when testing gemspec = if ENV["GEM_COMMAND"] # for Ruby Core @@ -327,12 +313,11 @@ def bundler_ruby_lib end def clean_load_path - bundler_lib = bundler_ruby_lib - loaded_gem_paths = Bundler.rubygems.loaded_gem_paths $LOAD_PATH.reject! do |p| - next if resolve_path(p).start_with?(bundler_lib) + resolved_path = resolve_path(p) + next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) } loaded_gem_paths.delete(p) end $LOAD_PATH.uniq! diff --git a/ruby/lib/bundler/similarity_detector.rb b/ruby/lib/bundler/similarity_detector.rb index bd9971f88..50e66b9ca 100644 --- a/ruby/lib/bundler/similarity_detector.rb +++ b/ruby/lib/bundler/similarity_detector.rb @@ -26,7 +26,7 @@ def similar_word_list(word, limit = 3) end end - protected + protected # https://www.informit.com/articles/article.aspx?p=683059&seqNum=36 def levenshtein_distance(this, that, ins = 2, del = 2, sub = 1) diff --git a/ruby/lib/bundler/source.rb b/ruby/lib/bundler/source.rb index 4b2e305bd..2a2b332cf 100644 --- a/ruby/lib/bundler/source.rb +++ b/ruby/lib/bundler/source.rb @@ -7,6 +7,7 @@ class Source autoload :Metadata, File.expand_path("source/metadata", __dir__) autoload :Path, File.expand_path("source/path", __dir__) autoload :Rubygems, File.expand_path("source/rubygems", __dir__) + autoload :RubygemsAggregate, File.expand_path("source/rubygems_aggregate", __dir__) attr_accessor :dependency_names @@ -33,6 +34,18 @@ def can_lock?(spec) spec.source == self end + def local!; end + + def local_only!; end + + def cached!; end + + def remote!; end + + def add_dependency_names(names) + @dependency_names = Array(dependency_names) | Array(names) + end + # it's possible that gems from one source depend on gems from some # other source, so now we download gemspecs and iterate over those # dependencies, looking for gems we don't have info on yet. @@ -42,6 +55,10 @@ def dependency_names_to_double_check specs.dependency_names end + def spec_names + specs.spec_names + end + def include?(other) other == self end @@ -50,6 +67,10 @@ def inspect "#<#{self.class}:0x#{object_id} #{self}>" end + def identifier + to_s + end + def path? instance_of?(Bundler::Source::Path) end @@ -63,7 +84,7 @@ def extension_cache_path(spec) ) end - private + private def version_color(spec_version, locked_spec_version) if Gem::Version.correct?(spec_version) && Gem::Version.correct?(locked_spec_version) diff --git a/ruby/lib/bundler/source/git.rb b/ruby/lib/bundler/source/git.rb index 7c1533ad9..a41a2f23e 100644 --- a/ruby/lib/bundler/source/git.rb +++ b/ruby/lib/bundler/source/git.rb @@ -22,7 +22,7 @@ def initialize(options) @uri = options["uri"] || "" @safe_uri = URICredentialsFilter.credential_filtered_uri(@uri) @branch = options["branch"] - @ref = options["ref"] || options["branch"] || options["tag"] || "master" + @ref = options["ref"] || options["branch"] || options["tag"] @submodules = options["submodules"] @name = options["name"] @version = options["version"].to_s.strip.gsub("-", ".pre.") @@ -42,7 +42,7 @@ def to_lock %w[ref branch tag submodules].each do |opt| out << " #{opt}: #{options[opt]}\n" if options[opt] end - out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB + out << " glob: #{@glob}\n" unless default_glob? out << " specs:\n" end @@ -60,25 +60,35 @@ def eql?(other) alias_method :==, :eql? def to_s - at = if local? - path - elsif user_ref = options["ref"] - if ref =~ /\A[a-z0-9]{4,}\z/i - shortref_for_display(user_ref) + begin + at = if local? + path + elsif user_ref = options["ref"] + if ref =~ /\A[a-z0-9]{4,}\z/i + shortref_for_display(user_ref) + else + user_ref + end + elsif ref + ref else - user_ref + git_proxy.branch end - else - ref + + rev = "at #{at}@#{shortref_for_display(revision)}" + rescue GitError + "" end - rev = begin - "@#{shortref_for_display(revision)}" - rescue GitError - nil - end + specifiers = [rev, glob_for_display].compact + suffix = + if specifiers.any? + " (#{specifiers.join(", ")})" + else + "" + end - "#{@safe_uri} (at #{at}#{rev})" + "#{@safe_uri}#{suffix}" end def name @@ -146,7 +156,7 @@ def local_override!(path) changed = cached_revision && cached_revision != git_proxy.revision - if changed && !@unlocked && !git_proxy.contains?(cached_revision) + if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision) raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \ "but the current branch in your local override for #{name} does not contain such commit. " \ "Please make sure your branch is up to date." @@ -230,7 +240,11 @@ def allow_git_ops? @allow_remote || @allow_cached end - private + def local? + @local + end + + private def serialize_gemspecs_in(destination) destination = destination.expand_path(Bundler.root) if destination.relative? @@ -256,10 +270,6 @@ def has_app_cache? cached_revision && super end - def local? - @local - end - def requires_checkout? allow_git_ops? && !local? && !cached_revision_checked_out? end @@ -280,6 +290,14 @@ def shortref_for_path(ref) ref[0..11] end + def glob_for_display + default_glob? ? nil : "glob: #{@glob}" + end + + def default_glob? + @glob == DEFAULT_GLOB + end + def uri_hash if uri =~ %r{^\w+://(\w+@)?} # Downcase the domain component of the URI @@ -289,7 +307,9 @@ def uri_hash # If there is no URI scheme, assume it is an ssh/git URI input = uri end - SharedHelpers.digest(:SHA1).hexdigest(input) + # We use SHA1 here for historical reason and to preserve backward compatibility. + # But a transition to a simpler mangling algorithm would be welcome. + Bundler::Digest.sha1(input) end def cached_revision diff --git a/ruby/lib/bundler/source/git/git_proxy.rb b/ruby/lib/bundler/source/git/git_proxy.rb index 7612eb16c..745a7fe11 100644 --- a/ruby/lib/bundler/source/git/git_proxy.rb +++ b/ruby/lib/bundler/source/git/git_proxy.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "shellwords" - module Bundler class Source class Git @@ -17,8 +15,8 @@ def initialize class GitNotAllowedError < GitError def initialize(command) msg = String.new - msg << "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " - msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/bundler/bundler/issues " + msg << "Bundler is trying to run `#{command}` at runtime. You probably need to run `bundle install`. However, " + msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md " msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}" super msg end @@ -27,21 +25,21 @@ def initialize(command) class GitCommandError < GitError attr_reader :command - def initialize(command, path = nil, extra_info = nil) + def initialize(command, path, extra_info = nil) @command = command msg = String.new - msg << "Git error: command `git #{command}` in directory #{SharedHelpers.pwd} has failed." + msg << "Git error: command `#{command}` in directory #{path} has failed." msg << "\n#{extra_info}" if extra_info - msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path && path.exist? + msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist? super msg end end class MissingGitRevisionError < GitCommandError - def initialize(command, path, ref, repo) + def initialize(command, destination_path, ref, repo) msg = "Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?" - super command, path, msg + super command, destination_path, msg end end @@ -58,30 +56,21 @@ def initialize(path, uri, ref, revision = nil, git = nil) @ref = ref @revision = revision @git = git - raise GitNotInstalledError.new if allow? && !Bundler.git_present? end def revision - return @revision if @revision - - begin - @revision ||= find_local_revision - rescue GitCommandError => e - raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri)) - end - - @revision + @revision ||= find_local_revision end def branch - @branch ||= allowed_in_path do - git("rev-parse --abbrev-ref HEAD").strip + @branch ||= allowed_with_path do + git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip end end def contains?(commit) - allowed_in_path do - result, status = git_null("branch --contains #{commit}") + allowed_with_path do + result, status = git_null("branch", "--contains", commit, :dir => path) status.success? && result =~ /^\* (.*)$/ end end @@ -96,20 +85,22 @@ def full_version def checkout return if path.exist? && has_revision_cached? - extra_ref = "#{Shellwords.shellescape(ref)}:#{Shellwords.shellescape(ref)}" if ref && ref.start_with?("refs/") + extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/") Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}" + configured_uri = configured_uri_for(uri).to_s + unless path.exist? SharedHelpers.filesystem_access(path.dirname) do |p| FileUtils.mkdir_p(p) end - git_retry %(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet) + git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s return unless extra_ref end - in_path do - git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*" #{extra_ref}) + with_path do + git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path) end end @@ -123,68 +114,69 @@ def copy_to(destination, submodules = false) SharedHelpers.filesystem_access(destination) do |p| FileUtils.rm_rf(p) end - git_retry %(clone --no-checkout --quiet "#{path}" "#{destination}") + git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination) rescue Errno::EEXIST => e - file_path = e.message[%r{.*?(/.*)}, 1] + file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1] raise GitError, "Bundler could not install a gem because it needs to " \ "create a directory, but a file exists - #{file_path}. Please delete " \ "this file and try again." end end # method 2 - SharedHelpers.chdir(destination) do - git_retry %(fetch --force --quiet --tags "#{path}") + git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination - begin - git "reset --hard #{@revision}" - rescue GitCommandError => e - raise MissingGitRevisionError.new(e.command, path, @revision, URICredentialsFilter.credential_filtered_uri(uri)) - end + begin + git "reset", "--hard", @revision, :dir => destination + rescue GitCommandError => e + raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri)) + end - if submodules - git_retry "submodule update --init --recursive" - elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0") - git_retry "submodule deinit --all --force" - end + if submodules + git_retry "submodule", "update", "--init", "--recursive", :dir => destination + elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0") + inner_command = "git -C $toplevel submodule deinit --force $sm_path" + git_retry "submodule", "foreach", "--quiet", inner_command, :dir => destination end end - private + private - def git_null(command) - command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command, uri) - raise GitNotAllowedError.new(command_with_no_credentials) unless allow? + def git_null(*command, dir: nil) + check_allowed(command) out, status = SharedHelpers.with_clean_git_env do - capture_and_ignore_stderr("git #{command}") + capture_and_ignore_stderr(*capture3_args_for(command, dir)) end [URICredentialsFilter.credential_filtered_string(out, uri), status] end - def git_retry(command) - Bundler::Retry.new("`git #{URICredentialsFilter.credential_filtered_string(command, uri)}`", GitNotAllowedError).attempts do - git(command) + def git_retry(*command, dir: nil) + command_with_no_credentials = check_allowed(command) + + Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do + git(*command, :dir => dir) end end - def git(command, check_errors = true, error_msg = nil) - command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command, uri) - raise GitNotAllowedError.new(command_with_no_credentials) unless allow? + def git(*command, dir: nil) + command_with_no_credentials = check_allowed(command) out, status = SharedHelpers.with_clean_git_env do - capture_and_filter_stderr(uri, "git #{command}") + capture_and_filter_stderr(*capture3_args_for(command, dir)) end - stdout_with_no_credentials = URICredentialsFilter.credential_filtered_string(out, uri) - raise GitCommandError.new(command_with_no_credentials, path, error_msg) if check_errors && !status.success? - stdout_with_no_credentials + filtered_out = URICredentialsFilter.credential_filtered_string(out, uri) + + raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success? + + filtered_out end def has_revision_cached? return unless @revision - in_path { git("cat-file -e #{@revision}") } + with_path { git("cat-file", "-e", @revision, :dir => path) } true rescue GitError false @@ -195,23 +187,11 @@ def remove_cache end def find_local_revision - allowed_in_path do - git("rev-parse --verify #{Shellwords.shellescape(ref)}", true).strip - end - end - - # Escape the URI for git commands - def uri_escaped_with_configured_credentials - remote = configured_uri_for(uri) - if Bundler::WINDOWS - # Windows quoting requires double quotes only, with double quotes - # inside the string escaped by being doubled. - '"' + remote.gsub('"') { '""' } + '"' - else - # Bash requires single quoted strings, with the single quotes escaped - # by ending the string, escaping the quote, and restarting the string. - "'" + remote.gsub("'") { "'\\''" } + "'" + allowed_with_path do + git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip end + rescue GitCommandError => e + raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri)) end # Adds credentials to the URI as Fetcher#configured_uri_for does @@ -227,32 +207,56 @@ def configured_uri_for(uri) end def allow? - @git ? @git.allow_git_ops? : true + allowed = @git ? @git.allow_git_ops? : true + + raise GitNotInstalledError.new if allowed && !Bundler.git_present? + + allowed end - def in_path(&blk) + def with_path(&blk) checkout unless path.exist? - _ = URICredentialsFilter # load it before we chdir - SharedHelpers.chdir(path, &blk) + blk.call end - def allowed_in_path - return in_path { yield } if allow? + def allowed_with_path + return with_path { yield } if allow? raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application" end - def capture_and_filter_stderr(uri, cmd) + def check_allowed(command) + require "shellwords" + command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri) + raise GitNotAllowedError.new(command_with_no_credentials) unless allow? + command_with_no_credentials + end + + def capture_and_filter_stderr(*cmd) require "open3" - return_value, captured_err, status = Open3.capture3(cmd) - Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) if uri && !captured_err.empty? + return_value, captured_err, status = Open3.capture3(*cmd) + Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) unless captured_err.empty? [return_value, status] end - def capture_and_ignore_stderr(cmd) + def capture_and_ignore_stderr(*cmd) require "open3" - return_value, _, status = Open3.capture3(cmd) + return_value, _, status = Open3.capture3(*cmd) [return_value, status] end + + def capture3_args_for(cmd, dir) + return ["git", *cmd] unless dir + + if Bundler.feature_flag.bundler_3_mode? || supports_minus_c? + ["git", "-C", dir.to_s, *cmd] + else + ["git", *cmd, { :chdir => dir.to_s }] + end + end + + def supports_minus_c? + @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5") + end end end end diff --git a/ruby/lib/bundler/source/metadata.rb b/ruby/lib/bundler/source/metadata.rb index 086787986..8bdbaa552 100644 --- a/ruby/lib/bundler/source/metadata.rb +++ b/ruby/lib/bundler/source/metadata.rb @@ -25,7 +25,7 @@ def specs s.loaded_from = File.expand_path("..", __FILE__) end - if local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION } + if local_spec = Bundler.rubygems.find_bundler(VERSION) idx << local_spec end @@ -33,10 +33,6 @@ def specs end end - def cached!; end - - def remote!; end - def options {} end diff --git a/ruby/lib/bundler/source/path.rb b/ruby/lib/bundler/source/path.rb index f98f5155f..01f89b204 100644 --- a/ruby/lib/bundler/source/path.rb +++ b/ruby/lib/bundler/source/path.rb @@ -82,7 +82,9 @@ def name end def install(spec, options = {}) - print_using_message "Using #{version_message(spec)} from #{self}" + using_message = "Using #{version_message(spec)} from #{self}" + using_message += " and installing its executables" unless spec.executables.empty? + print_using_message using_message generate_bin(spec, :disable_extensions => true) nil # no post-install message end @@ -125,14 +127,18 @@ def expanded_original_path @expanded_original_path ||= expand(original_path) end - private + private def expanded_path @expanded_path ||= expand(path) end def expand(somepath) - somepath.expand_path(root_path) + if Bundler.current_ruby.jruby? # TODO: Unify when https://github.com/rubygems/bundler/issues/7598 fixed upstream and all supported jrubies include the fix + somepath.expand_path(root_path).expand_path + else + somepath.expand_path(root_path) + end rescue ArgumentError => e Bundler.ui.debug(e) raise PathError, "There was an error while trying to use the path " \ @@ -167,7 +173,7 @@ def load_spec_files if File.directory?(expanded_path) # We sort depth-first since `<<` will override the earlier-found specs - Dir["#{expanded_path}/#{@glob}"].sort_by {|p| -p.split(File::SEPARATOR).size }.each do |file| + Gem::Util.glob_files_in_dir(@glob, expanded_path).sort_by {|p| -p.split(File::SEPARATOR).size }.each do |file| next unless spec = load_gemspec(file) spec.source = self diff --git a/ruby/lib/bundler/source/path/installer.rb b/ruby/lib/bundler/source/path/installer.rb index a0357ffa3..a70973bde 100644 --- a/ruby/lib/bundler/source/path/installer.rb +++ b/ruby/lib/bundler/source/path/installer.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require_relative "../../rubygems_gem_installer" + module Bundler class Source class Path @@ -26,23 +28,21 @@ def initialize(spec, options = {}) end def post_install - SharedHelpers.chdir(@gem_dir) do - run_hooks(:pre_install) + run_hooks(:pre_install) - unless @disable_extensions - build_extensions - run_hooks(:post_build) - end + unless @disable_extensions + build_extensions + run_hooks(:post_build) + end - generate_bin unless spec.executables.nil? || spec.executables.empty? + generate_bin unless spec.executables.empty? - run_hooks(:post_install) - end + run_hooks(:post_install) ensure Bundler.rm_rf(@tmp_dir) if Bundler.requires_sudo? end - private + private def generate_bin super diff --git a/ruby/lib/bundler/source/rubygems.rb b/ruby/lib/bundler/source/rubygems.rb index 6c0de204e..8bc3aa17e 100644 --- a/ruby/lib/bundler/source/rubygems.rb +++ b/ruby/lib/bundler/source/rubygems.rb @@ -20,18 +20,38 @@ def initialize(options = {}) @dependency_names = [] @allow_remote = false @allow_cached = false + @allow_local = options["allow_local"] || false @caches = [cache_path, *Bundler.rubygems.gem_cache] - Array(options["remotes"] || []).reverse_each {|r| add_remote(r) } + Array(options["remotes"]).reverse_each {|r| add_remote(r) } + end + + def local_only! + @specs = nil + @allow_local = true + @allow_cached = false + @allow_remote = false + end + + def local! + return if @allow_local + + @specs = nil + @allow_local = true end def remote! + return if @allow_remote + @specs = nil @allow_remote = true end def cached! + return if @allow_cached + @specs = nil + @allow_local = true @allow_cached = true end @@ -49,9 +69,17 @@ def include?(o) o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty? end + def multiple_remotes? + @remotes.size > 1 + end + + def no_remotes? + @remotes.size == 0 + end + def can_lock?(spec) - return super if Bundler.feature_flag.disable_multisource? - spec.source.is_a?(Rubygems) + return super unless multiple_remotes? + include?(spec.source) end def options @@ -73,12 +101,27 @@ def to_lock def to_s if remotes.empty? "locally installed gems" - else - remote_names = remotes.map(&:to_s).join(", ") + elsif @allow_remote && @allow_cached && @allow_local + "rubygems repository #{remote_names}, cached gems or installed locally" + elsif @allow_remote && @allow_local "rubygems repository #{remote_names} or installed locally" + elsif @allow_remote + "rubygems repository #{remote_names}" + elsif @allow_cached && @allow_local + "cached gems or installed locally" + else + "locally installed gems" end end - alias_method :name, :to_s + + def identifier + if remotes.empty? + "locally installed gems" + else + "rubygems repository #{remote_names}" + end + end + alias_method :name, :identifier def specs @specs ||= begin @@ -87,7 +130,7 @@ def specs # small_idx.use large_idx. idx = @allow_remote ? remote_specs.dup : Index.new idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote - idx.use(installed_specs, :override_dupes) + idx.use(installed_specs, :override_dupes) if @allow_local idx end end @@ -96,7 +139,7 @@ def install(spec, opts = {}) force = opts[:force] ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached] - if ensure_builtin_gems_cached && builtin_gem?(spec) + if ensure_builtin_gems_cached && spec.default_gem? if !cached_path(spec) cached_built_in_gem(spec) unless spec.remote force = true @@ -105,7 +148,7 @@ def install(spec, opts = {}) end end - if (installed?(spec) || Plugin.installed?(spec.name)) && !force + if installed?(spec) && !force print_using_message "Using #{version_message(spec)}" return nil # no post-install message end @@ -123,7 +166,7 @@ def install(spec, opts = {}) begin s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"]) spec.__swap__(s) - rescue StandardError + rescue Gem::Package::FormatError Bundler.rm_rf(path) raise end @@ -135,6 +178,7 @@ def install(spec, opts = {}) Bundler.ui.confirm message path = cached_gem(spec) + raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path if requires_sudo? install_path = Bundler.tmp(spec.full_name) bin_path = install_path.join("bin") @@ -145,20 +189,19 @@ def install(spec, opts = {}) Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5") - installed_spec = nil - Bundler.rubygems.preserve_paths do - installed_spec = Bundler::RubyGemsGemInstaller.at( - path, - :install_dir => install_path.to_s, - :bin_dir => bin_path.to_s, - :ignore_dependencies => true, - :wrappers => true, - :env_shebang => true, - :build_args => opts[:build_args], - :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum, - :bundler_extension_cache_path => extension_cache_path(spec) - ).install - end + require_relative "../rubygems_gem_installer" + + installed_spec = Bundler::RubyGemsGemInstaller.at( + path, + :install_dir => install_path.to_s, + :bin_dir => bin_path.to_s, + :ignore_dependencies => true, + :wrappers => true, + :env_shebang => true, + :build_args => opts[:build_args], + :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum, + :bundler_extension_cache_path => extension_cache_path(spec) + ).install spec.full_gem_path = installed_spec.full_gem_path # SUDO HAX @@ -195,12 +238,8 @@ def install(spec, opts = {}) end def cache(spec, custom_path = nil) - if builtin_gem?(spec) - cached_path = cached_built_in_gem(spec) - else - cached_path = cached_gem(spec) - end - raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path + cached_path = cached_gem(spec) + raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path return if File.dirname(cached_path) == Bundler.app_cache.to_s Bundler.ui.info " * #{File.basename(cached_path)}" FileUtils.cp(cached_path, Bundler.app_cache(custom_path)) @@ -227,25 +266,16 @@ def add_remote(source) @remotes.unshift(uri) unless @remotes.include?(uri) end - def equivalent_remotes?(other_remotes) - other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth)) - end - - def replace_remotes(other_remotes, allow_equivalent = false) - return false if other_remotes == @remotes - - equivalent = allow_equivalent && equivalent_remotes?(other_remotes) - - @remotes = [] - other_remotes.reverse_each do |r| - add_remote r.to_s + def spec_names + if @allow_remote && dependency_api_available? + remote_specs.spec_names + else + [] end - - !equivalent end def unmet_deps - if @allow_remote && api_fetchers.any? + if @allow_remote && dependency_api_available? remote_specs.unmet_dependency_names else [] @@ -261,7 +291,7 @@ def fetchers def double_check_for(unmet_dependency_names) return unless @allow_remote - return unless api_fetchers.any? + return unless dependency_api_available? unmet_dependency_names = unmet_dependency_names.call unless unmet_dependency_names.nil? @@ -283,21 +313,32 @@ def dependency_names_to_double_check remote_specs.each do |spec| case spec when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification - names.concat(spec.runtime_dependencies) + names.concat(spec.runtime_dependencies.map(&:name)) when RemoteSpecification # from the full index return nil else raise "unhandled spec type (#{spec.inspect})" end end - names.map!(&:name) if names names end - protected + def dependency_api_available? + api_fetchers.any? + end + + protected + + def remote_names + remotes.map(&:to_s).join(", ") + end def credless_remotes - remotes.map(&method(:suppress_configured_credentials)) + if Bundler.settings[:allow_deployment_source_credential_changes] + remotes.map(&method(:remove_auth)) + else + remotes.map(&method(:suppress_configured_credentials)) + end end def remotes_for_spec(spec) @@ -312,14 +353,17 @@ def loaded_from(spec) end def cached_gem(spec) - cached_gem = cached_path(spec) - unless cached_gem - raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation" + if spec.default_gem? + cached_built_in_gem(spec) + else + cached_path(spec) end - cached_gem end def cached_path(spec) + global_cache_path = download_cache_path(spec) + @caches << global_cache_path if global_cache_path + possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" } possibilities.find {|p| File.exist?(p) } end @@ -354,7 +398,6 @@ def remove_auth(remote) def installed_specs @installed_specs ||= Index.build do |idx| Bundler.rubygems.all_specs.reverse_each do |spec| - next if spec.name == "bundler" spec.source = self if Bundler.rubygems.spec_missing_extensions?(spec, false) Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions" @@ -367,16 +410,12 @@ def installed_specs def cached_specs @cached_specs ||= begin - idx = installed_specs.dup + idx = @allow_local ? installed_specs.dup : Index.new Dir["#{cache_path}/*.gem"].each do |gemfile| next if gemfile =~ /^bundler\-[\d\.]+?\.gem/ s ||= Bundler.rubygems.spec_from_gem(gemfile) s.source = self - if Bundler.rubygems.spec_missing_extensions?(s, false) - Bundler.ui.debug "Source #{self} is ignoring #{s} because it is missing extensions" - next - end idx << s end @@ -409,11 +448,11 @@ def remote_specs def fetch_names(fetchers, dependency_names, index, override_dupes) fetchers.each do |f| if dependency_names - Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug? + Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug? index.use f.specs_with_retry(dependency_names, self), override_dupes Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over else - Bundler.ui.info "Fetching source index from #{f.uri}" + Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}" index.use f.specs_with_retry(nil, self), override_dupes end end @@ -424,19 +463,26 @@ def fetch_gem(spec) spec.fetch_platform - download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir - gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem" + cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir) + gem_path = "#{cache_path}/#{spec.file_name}" + + if requires_sudo? + download_path = Bundler.tmp(spec.full_name) + download_cache_path = default_cache_path_for(download_path) + else + download_cache_path = cache_path + end - SharedHelpers.filesystem_access("#{download_path}/cache") do |p| + SharedHelpers.filesystem_access(download_cache_path) do |p| FileUtils.mkdir_p(p) end - download_gem(spec, download_path) + download_gem(spec, download_cache_path) if requires_sudo? - SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p| + SharedHelpers.filesystem_access(cache_path) do |p| Bundler.mkdir_p(p) end - Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}" + Bundler.sudo "mv #{download_cache_path}/#{spec.file_name} #{gem_path}" end gem_path @@ -444,16 +490,8 @@ def fetch_gem(spec) Bundler.rm_rf(download_path) if requires_sudo? end - def builtin_gem?(spec) - # Ruby 2.1, where all included gems have this summary - return true if spec.summary =~ /is bundled with Ruby/ - - # Ruby 2.0, where gemspecs are stored in specifications/default/ - spec.loaded_from && spec.loaded_from.include?("specifications/default/") - end - def installed?(spec) - installed_specs[spec].any? + installed_specs[spec].any? && !spec.deleted_gem? end def requires_sudo? @@ -464,11 +502,15 @@ def rubygems_dir Bundler.rubygems.gem_dir end + def default_cache_path_for(dir) + "#{dir}/cache" + end + def cache_path Bundler.app_cache end - private + private # Checks if the requested spec exists in the global cache. If it does, # we copy it to the download path, and if it does not, we download it. @@ -476,45 +518,13 @@ def cache_path # @param [Specification] spec # the spec we want to download or retrieve from the cache. # - # @param [String] download_path + # @param [String] download_cache_path # the local directory the .gem will end up in. # - def download_gem(spec, download_path) - local_path = File.join(download_path, "cache/#{spec.full_name}.gem") - - if (cache_path = download_cache_path(spec)) && cache_path.file? - SharedHelpers.filesystem_access(local_path) do - FileUtils.cp(cache_path, local_path) - end - else - uri = spec.remote.uri - Bundler.ui.confirm("Fetching #{version_message(spec)}") - rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path) - if rubygems_local_path != local_path - FileUtils.mv(rubygems_local_path, local_path) - end - cache_globally(spec, local_path) - end - end - - # Checks if the requested spec exists in the global cache. If it does - # not, we create the relevant global cache subdirectory if it does not - # exist and copy the spec from the local cache to the global cache. - # - # @param [Specification] spec - # the spec we want to copy to the global cache. - # - # @param [String] local_cache_path - # the local directory from which we want to copy the .gem. - # - def cache_globally(spec, local_cache_path) - return unless cache_path = download_cache_path(spec) - return if cache_path.exist? - - SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath) - SharedHelpers.filesystem_access(cache_path) do - FileUtils.cp(local_cache_path, cache_path) - end + def download_gem(spec, download_cache_path) + uri = spec.remote.uri + Bundler.ui.confirm("Fetching #{version_message(spec)}") + Bundler.rubygems.download_gem(spec, uri, download_cache_path) end # Returns the global cache path of the calling Rubygems::Source object. @@ -533,7 +543,7 @@ def download_cache_path(spec) return unless remote = spec.remote return unless cache_slug = remote.cache_slug - Bundler.user_cache.join("gems", cache_slug, spec.file_name) + Bundler.user_cache.join("gems", cache_slug) end def extension_cache_slug(spec) diff --git a/ruby/lib/bundler/source/rubygems/remote.rb b/ruby/lib/bundler/source/rubygems/remote.rb index 45ea61acb..82c850ffb 100644 --- a/ruby/lib/bundler/source/rubygems/remote.rb +++ b/ruby/lib/bundler/source/rubygems/remote.rb @@ -39,7 +39,7 @@ def to_s "rubygems remote at #{anonymized_uri}" end - private + private def apply_auth(uri, auth) if auth && uri.userinfo.nil? diff --git a/ruby/lib/bundler/source/rubygems_aggregate.rb b/ruby/lib/bundler/source/rubygems_aggregate.rb new file mode 100644 index 000000000..99ef81ad5 --- /dev/null +++ b/ruby/lib/bundler/source/rubygems_aggregate.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +module Bundler + class Source + class RubygemsAggregate + attr_reader :source_map, :sources + + def initialize(sources, source_map) + @sources = sources + @source_map = source_map + + @index = build_index + end + + def specs + @index + end + + def identifier + to_s + end + + def to_s + "any of the sources" + end + + private + + def build_index + Index.build do |idx| + dependency_names = source_map.pinned_spec_names + + sources.all_sources.each do |source| + source.dependency_names = dependency_names - source_map.pinned_spec_names(source) + idx.add_source source.specs + dependency_names.concat(source.unmet_deps).uniq! + end + + double_check_for_index(idx, dependency_names) + end + end + + # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both + # sources A and B. At this point, the API request will have found all the versions of Bar in source A, + # but will not have found any versions of Bar from source B, which is a problem if the requested version + # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for + # each spec we found, we add all possible versions from all sources to the index. + def double_check_for_index(idx, dependency_names) + pinned_names = source_map.pinned_spec_names + + names = :names # do this so we only have to traverse to get dependency_names from the index once + unmet_dependency_names = lambda do + return names unless names == :names + new_names = sources.all_sources.map(&:dependency_names_to_double_check) + return names = nil if new_names.compact! + names = new_names.flatten(1).concat(dependency_names) + names.uniq! + names -= pinned_names + names + end + + sources.all_sources.each do |source| + source.double_check_for(unmet_dependency_names) + end + end + end + end +end diff --git a/ruby/lib/bundler/source_list.rb b/ruby/lib/bundler/source_list.rb index d3f649a12..a4773397c 100644 --- a/ruby/lib/bundler/source_list.rb +++ b/ruby/lib/bundler/source_list.rb @@ -1,30 +1,53 @@ # frozen_string_literal: true -require "set" - module Bundler class SourceList attr_reader :path_sources, :git_sources, :plugin_sources, - :global_rubygems_source, + :global_path_source, :metadata_source + def global_rubygems_source + @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true) + end + def initialize @path_sources = [] @git_sources = [] @plugin_sources = [] @global_rubygems_source = nil - @rubygems_aggregate = rubygems_aggregate_class.new + @global_path_source = nil @rubygems_sources = [] @metadata_source = Source::Metadata.new + + @merged_gem_lockfile_sections = false + end + + def merged_gem_lockfile_sections? + @merged_gem_lockfile_sections + end + + def merged_gem_lockfile_sections!(replacement_source) + @merged_gem_lockfile_sections = true + @global_rubygems_source = replacement_source + end + + def aggregate_global_source? + global_rubygems_source.multiple_remotes? + end + + def implicit_global_source? + global_rubygems_source.no_remotes? end def add_path_source(options = {}) if options["gemspec"] add_source_to_list Source::Gemspec.new(options), path_sources else - add_source_to_list Source::Path.new(options), path_sources + path_source = add_source_to_list Source::Path.new(options), path_sources + @global_path_source ||= path_source if options["global"] + path_source end end @@ -35,32 +58,31 @@ def add_git_source(options = {}) end def add_rubygems_source(options = {}) - add_source_to_list Source::Rubygems.new(options), @rubygems_sources + new_source = Source::Rubygems.new(options) + return @global_rubygems_source if @global_rubygems_source == new_source + + add_source_to_list new_source, @rubygems_sources end def add_plugin_source(source, options = {}) add_source_to_list Plugin.source(source).new(options), @plugin_sources end - def global_rubygems_source=(uri) - if Bundler.feature_flag.disable_multisource? - @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri) - end - add_rubygems_remote(uri) - end - - def add_rubygems_remote(uri) - return if Bundler.feature_flag.disable_multisource? - @rubygems_aggregate.add_remote(uri) - @rubygems_aggregate + def add_global_rubygems_remote(uri) + global_rubygems_source.add_remote(uri) + global_rubygems_source end def default_source - global_rubygems_source || @rubygems_aggregate + global_path_source || global_rubygems_source end def rubygems_sources - @rubygems_sources + [default_source] + non_global_rubygems_sources + [global_rubygems_source] + end + + def non_global_rubygems_sources + @rubygems_sources end def rubygems_remotes @@ -71,37 +93,51 @@ def all_sources path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source] end + def non_default_explicit_sources + all_sources - [default_source, metadata_source] + end + def get(source) - source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) } + source_list_for(source).find {|s| equivalent_source?(source, s) } end def lock_sources - lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s) - if Bundler.feature_flag.disable_multisource? - lock_sources + rubygems_sources.sort_by(&:to_s) + lock_other_sources + lock_rubygems_sources + end + + def lock_other_sources + (path_sources + git_sources + plugin_sources).sort_by(&:identifier) + end + + def lock_rubygems_sources + if merged_gem_lockfile_sections? + [combine_rubygems_sources] else - lock_sources << combine_rubygems_sources + rubygems_sources.sort_by(&:identifier) end end # Returns true if there are changes def replace_sources!(replacement_sources) - return true if replacement_sources.empty? + return false if replacement_sources.empty? - [path_sources, git_sources, plugin_sources].each do |source_list| - source_list.map! do |source| - replacement_sources.find {|s| s == source } || source - end - end + @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources) + @global_rubygems_source = global_replacement_source(replacement_sources) - replacement_rubygems = !Bundler.feature_flag.disable_multisource? && - replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } - @rubygems_aggregate = replacement_rubygems if replacement_rubygems + different_sources?(lock_sources, replacement_sources) + end - return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources) - return true if replacement_rubygems && rubygems_remotes.to_set != replacement_rubygems.remotes.to_set + # Returns true if there are changes + def expired_sources?(replacement_sources) + return false if replacement_sources.empty? + + lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources + + different_sources?(lock_sources, replacement_sources) + end - false + def local_only! + all_sources.each(&:local_only!) end def cached! @@ -112,11 +148,33 @@ def remote! all_sources.each(&:remote!) end - def rubygems_primary_remotes - @rubygems_aggregate.remotes + private + + def dup_with_replaced_sources(replacement_sources) + new_source_list = dup + new_source_list.replace_sources!(replacement_sources) + new_source_list + end + + def map_sources(replacement_sources) + [@rubygems_sources, @path_sources, @git_sources, @plugin_sources].map do |sources| + sources.map do |source| + replacement_sources.find {|s| s == source } || source + end + end end - private + def global_replacement_source(replacement_sources) + replacement_source = replacement_sources.find {|s| s == global_rubygems_source } + return global_rubygems_source unless replacement_source + + replacement_source.local! + replacement_source + end + + def different_sources?(lock_sources, replacement_sources) + !equivalent_sources?(lock_sources, replacement_sources) + end def rubygems_aggregate_class Source::Rubygems @@ -147,37 +205,17 @@ def warn_on_git_protocol(source) if source.uri =~ /^git\:/ Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \ "which transmits data without encryption. Disable this warning with " \ - "`bundle config set git.allow_insecure true`, or switch to the `https` " \ + "`bundle config set --local git.allow_insecure true`, or switch to the `https` " \ "protocol to keep your data secure." end end - def equal_sources?(lock_sources, replacement_sources) - lock_sources.to_set == replacement_sources.to_set - end - - def equal_source?(source, other_source) - source == other_source - end - - def equivalent_source?(source, other_source) - return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems) - - equivalent_rubygems_sources?([source], [other_source]) - end - def equivalent_sources?(lock_sources, replacement_sources) - return false unless Bundler.settings[:allow_deployment_source_credential_changes] - - lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) } - replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) } - - equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources) + lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier) end - def equivalent_rubygems_sources?(lock_sources, replacement_sources) - actual_remotes = replacement_sources.map(&:remotes).flatten.uniq - lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) } + def equivalent_source?(source, other_source) + source == other_source end end end diff --git a/ruby/lib/bundler/source_map.rb b/ruby/lib/bundler/source_map.rb new file mode 100644 index 000000000..a554f26f7 --- /dev/null +++ b/ruby/lib/bundler/source_map.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Bundler + class SourceMap + attr_reader :sources, :dependencies + + def initialize(sources, dependencies) + @sources = sources + @dependencies = dependencies + end + + def pinned_spec_names(skip = nil) + direct_requirements.reject {|_, source| source == skip }.keys + end + + def all_requirements + requirements = direct_requirements.dup + + unmet_deps = sources.non_default_explicit_sources.map do |source| + (source.spec_names - pinned_spec_names).each do |indirect_dependency_name| + previous_source = requirements[indirect_dependency_name] + if previous_source.nil? + requirements[indirect_dependency_name] = source + else + no_ambiguous_sources = Bundler.feature_flag.bundler_3_mode? + + msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."] + msg.concat [previous_source, source].map {|s| " * #{s}" }.sort + msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from." + msg = msg.join("\n") + + raise SecurityError, msg if no_ambiguous_sources + Bundler.ui.warn "Warning: #{msg}" + end + end + + source.unmet_deps + end + + sources.default_source.add_dependency_names(unmet_deps.flatten - requirements.keys) + + requirements + end + + def direct_requirements + @direct_requirements ||= begin + requirements = {} + default = sources.default_source + dependencies.each do |dep| + dep_source = dep.source || default + dep_source.add_dependency_names(dep.name) + requirements[dep.name] = dep_source + end + requirements + end + end + end +end diff --git a/ruby/lib/bundler/spec_set.rb b/ruby/lib/bundler/spec_set.rb index 463113ef8..a19d18388 100644 --- a/ruby/lib/bundler/spec_set.rb +++ b/ruby/lib/bundler/spec_set.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -require "tsort" -require "set" +require_relative "vendored_tsort" module Bundler class SpecSet @@ -12,31 +11,28 @@ def initialize(specs) @specs = specs end - def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true) - handled = Set.new + def for(dependencies, check = false, match_current_platform = false) + handled = [] deps = dependencies.dup specs = [] - skip += ["bundler"] loop do break unless dep = deps.shift - next if !handled.add?(dep) || skip.include?(dep.name) + next if handled.any?{|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler" - if spec = spec_for_dependency(dep, match_current_platform) - specs << spec + handled << dep - spec.dependencies.each do |d| + specs_for_dep = spec_for_dependency(dep, match_current_platform) + if specs_for_dep.any? + match_current_platform ? specs += specs_for_dep : specs |= specs_for_dep + + specs_for_dep.first.dependencies.each do |d| next if d.type == :development - d = DepProxy.new(d, dep.__platform) unless match_current_platform + d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform deps << d end elsif check return false - elsif raise_on_missing - others = lookup[dep.name] if match_current_platform - message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?" - message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty? - raise GemNotFound, message end end @@ -44,11 +40,7 @@ def for(dependencies, skip = [], check = false, match_current_platform = false, specs << spec end - check ? true : SpecSet.new(specs) - end - - def valid_for?(deps) - self.for(deps, [], true) + check ? true : specs end def [](key) @@ -74,38 +66,35 @@ def to_hash lookup.dup end - def materialize(deps, missing_specs = nil) - materialized = self.for(deps, [], false, true, !missing_specs).to_a - deps = materialized.map(&:name).uniq + def materialize(deps) + materialized = self.for(deps, false, true) + materialized.map! do |s| next s unless s.is_a?(LazySpecification) - s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=) - spec = s.__materialize__ - unless spec - unless missing_specs - raise GemNotFound, "Could not find #{s.full_name} in any of the sources" - end - missing_specs << s - end - spec + s.source.local! + s.__materialize__ || s end - SpecSet.new(missing_specs ? materialized.compact : materialized) + SpecSet.new(materialized) end # Materialize for all the specs in the spec set, regardless of what platform they're for # This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform) # @return [Array] def materialized_for_all_platforms - names = @specs.map(&:name).uniq @specs.map do |s| next s unless s.is_a?(LazySpecification) - s.source.dependency_names = names if s.source.respond_to?(:dependency_names=) + s.source.local! + s.source.remote! spec = s.__materialize__ raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec spec end end + def missing_specs + @specs.select {|s| s.is_a?(LazySpecification) } + end + def merge(set) arr = sorted.dup set.each do |set_spec| @@ -147,7 +136,7 @@ def each(&b) sorted.each(&b) end - private + private def sorted rake = @specs.find {|s| s.name == "rake" } @@ -183,11 +172,7 @@ def tsort_each_node def spec_for_dependency(dep, match_current_platform) specs_for_platforms = lookup[dep.name] if match_current_platform - Bundler.rubygems.platforms.reverse_each do |pl| - match = GemHelpers.select_best_platform_match(specs_for_platforms, pl) - return match if match - end - nil + GemHelpers.select_best_platform_match(specs_for_platforms.select{|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform) else GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform) end diff --git a/ruby/lib/bundler/stub_specification.rb b/ruby/lib/bundler/stub_specification.rb index d45f80a80..fa071901e 100644 --- a/ruby/lib/bundler/stub_specification.rb +++ b/ruby/lib/bundler/stub_specification.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_relative "remote_specification" - module Bundler class StubSpecification < RemoteSpecification def self.from_stub(stub) @@ -28,9 +26,21 @@ def to_yaml # @!group Stub Delegates - # This is defined directly to avoid having to load every installed spec + def manually_installed? + # This is for manually installed gems which are gems that were fixed in place after a + # failed installation. Once the issue was resolved, the user then manually created + # the gem specification using the instructions provided by `gem help install` + installed_by_version == Gem::Version.new(0) + end + + # This is defined directly to avoid having to loading the full spec def missing_extensions? - stub.missing_extensions? + return false if default_gem? + return false if extensions.empty? + return false if File.exist? gem_build_complete_path + return false if manually_installed? + + true end def activated @@ -41,8 +51,16 @@ def activated=(activated) stub.instance_variable_set(:@activated, activated) end - def default_gem - stub.default_gem + def extensions + stub.extensions + end + + def gem_build_complete_path + File.join(extension_dir, "gem.build_complete") + end + + def default_gem? + stub.default_gem? end def full_gem_path @@ -71,7 +89,7 @@ def raw_require_paths stub.raw_require_paths end - private + private def _remote_specification @_remote_specification ||= begin diff --git a/ruby/lib/bundler/templates/Executable.bundler b/ruby/lib/bundler/templates/Executable.bundler index 69f26bb9c..6bb5c5109 100644 --- a/ruby/lib/bundler/templates/Executable.bundler +++ b/ruby/lib/bundler/templates/Executable.bundler @@ -60,20 +60,20 @@ m = Module.new do Regexp.last_match(1) end - def bundler_version - @bundler_version ||= + def bundler_requirement + @bundler_requirement ||= env_var_version || cli_arg_version || - lockfile_version + bundler_requirement_for(lockfile_version) end - def bundler_requirement - return "#{Gem::Requirement.default}.a" unless bundler_version + def bundler_requirement_for(version) + return "#{Gem::Requirement.default}.a" unless version - bundler_gem_version = Gem::Version.new(bundler_version) + bundler_gem_version = Gem::Version.new(version) requirement = bundler_gem_version.approximate_recommendation - return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") + return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0") requirement += ".a" if bundler_gem_version.prerelease? diff --git a/ruby/lib/bundler/templates/Gemfile b/ruby/lib/bundler/templates/Gemfile index 1afd2cce6..d2403f18b 100644 --- a/ruby/lib/bundler/templates/Gemfile +++ b/ruby/lib/bundler/templates/Gemfile @@ -2,6 +2,4 @@ source "https://rubygems.org" -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - # gem "rails" diff --git a/ruby/lib/bundler/templates/gems.rb b/ruby/lib/bundler/templates/gems.rb index 547cd6e8d..d2403f18b 100644 --- a/ruby/lib/bundler/templates/gems.rb +++ b/ruby/lib/bundler/templates/gems.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true -# A sample gems.rb source "https://rubygems.org" -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - # gem "rails" diff --git a/ruby/lib/bundler/templates/newgem/CHANGELOG.md.tt b/ruby/lib/bundler/templates/newgem/CHANGELOG.md.tt new file mode 100644 index 000000000..c9ea96d45 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/CHANGELOG.md.tt @@ -0,0 +1,5 @@ +## [Unreleased] + +## [0.1.0] - <%= Time.now.strftime('%F') %> + +- Initial release diff --git a/ruby/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/ruby/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt index 7dfd14aab..175b821a6 100644 --- a/ruby/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +++ b/ruby/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt @@ -2,73 +2,83 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to a positive environment for our community include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall community -Examples of unacceptable behavior by participants include: +Examples of unacceptable behavior include: -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission +* Publishing others' private information, such as a physical or email + address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting -## Our Responsibilities +## Enforcement Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at <%= config[:email] %>. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at <%= config[:email] %>. All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [https://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, +available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org -[homepage]: https://contributor-covenant.org -[version]: https://contributor-covenant.org/version/1/4/ +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. diff --git a/ruby/lib/bundler/templates/newgem/Gemfile.tt b/ruby/lib/bundler/templates/newgem/Gemfile.tt index 83878ec7f..de82a63c5 100644 --- a/ruby/lib/bundler/templates/newgem/Gemfile.tt +++ b/ruby/lib/bundler/templates/newgem/Gemfile.tt @@ -1,12 +1,23 @@ +# frozen_string_literal: true + source "https://rubygems.org" # Specify your gem's dependencies in <%= config[:name] %>.gemspec gemspec -gem "rake", "~> 12.0" +gem "rake", "~> 13.0" <%- if config[:ext] -%> + gem "rake-compiler" <%- end -%> <%- if config[:test] -%> + gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>" <%- end -%> +<%- if config[:linter] == "rubocop" -%> + +gem "rubocop", "~> <%= config[:linter_version] %>" +<%- elsif config[:linter] == "standard" -%> + +gem "standard", "~> <%= config[:linter_version] %>" +<%- end -%> diff --git a/ruby/lib/bundler/templates/newgem/README.md.tt b/ruby/lib/bundler/templates/newgem/README.md.tt index c2f5f9dca..8fd87abe9 100644 --- a/ruby/lib/bundler/templates/newgem/README.md.tt +++ b/ruby/lib/bundler/templates/newgem/README.md.tt @@ -28,21 +28,22 @@ TODO: Write usage instructions here After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test].sub('mini', '').sub('rspec', 'spec') %>` to run the tests.<% end %> You can also run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the gem in this directory, ignoring other installed copies of this gem.<% end %> -To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). +To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). +<% if config[:git] -%> ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).<% end %> - +Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).<% end %> +<% end -%> <% if config[:mit] -%> ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). <% end -%> -<% if config[:coc] -%> +<% if config[:git] && config[:coc] -%> ## Code of Conduct -Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md). +Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md). <% end -%> diff --git a/ruby/lib/bundler/templates/newgem/Rakefile.tt b/ruby/lib/bundler/templates/newgem/Rakefile.tt index 099da6f3e..b02ada9b6 100644 --- a/ruby/lib/bundler/templates/newgem/Rakefile.tt +++ b/ruby/lib/bundler/templates/newgem/Rakefile.tt @@ -1,5 +1,18 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" -<% if config[:test] == "minitest" -%> +<% default_task_names = [config[:test_task]].compact -%> +<% case config[:test] -%> +<% when "minitest" -%> +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.test_files = FileList["test/**/test_*.rb"] +end + +<% when "test-unit" -%> require "rake/testtask" Rake::TestTask.new(:test) do |t| @@ -8,22 +21,36 @@ Rake::TestTask.new(:test) do |t| t.test_files = FileList["test/**/*_test.rb"] end -<% elsif config[:test] == "rspec" -%> +<% when "rspec" -%> require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) +<% end -%> +<% if config[:linter] == "rubocop" -%> +<% default_task_names << :rubocop -%> +require "rubocop/rake_task" + +RuboCop::RakeTask.new + +<% elsif config[:linter] == "standard" -%> +<% default_task_names << :standard -%> +require "standard/rake" + <% end -%> <% if config[:ext] -%> +<% default_task_names.unshift(:clobber, :compile) -%> require "rake/extensiontask" -task :build => :compile +task build: :compile Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext| ext.lib_dir = "lib/<%= config[:namespaced_path] %>" end -task :default => [:clobber, :compile, :<%= config[:test_task] %>] +<% end -%> +<% if default_task_names.size == 1 -%> +task default: <%= default_task_names.first.inspect %> <% else -%> -task :default => :<%= config[:test_task] %> +task default: %i[<%= default_task_names.join(" ") %>] <% end -%> diff --git a/ruby/lib/bundler/templates/newgem/bin/console.tt b/ruby/lib/bundler/templates/newgem/bin/console.tt index a27f82430..08dfaaef6 100644 --- a/ruby/lib/bundler/templates/newgem/bin/console.tt +++ b/ruby/lib/bundler/templates/newgem/bin/console.tt @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "<%= config[:namespaced_path] %>" diff --git a/ruby/lib/bundler/templates/newgem/circleci/config.yml.tt b/ruby/lib/bundler/templates/newgem/circleci/config.yml.tt new file mode 100644 index 000000000..79fd0dcc0 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/circleci/config.yml.tt @@ -0,0 +1,13 @@ +version: 2.1 +jobs: + build: + docker: + - image: ruby:<%= RUBY_VERSION %> + steps: + - checkout + - run: + name: Run the default task + command: | + gem install bundler -v <%= Bundler::VERSION %> + bundle install + bundle exec rake diff --git a/ruby/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt b/ruby/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt index 8cfc828f9..e918063dd 100644 --- a/ruby/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +++ b/ruby/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "mkmf" create_makefile(<%= config[:makefile_path].inspect %>) diff --git a/ruby/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/ruby/lib/bundler/templates/newgem/github/workflows/main.yml.tt new file mode 100644 index 000000000..6570d177a --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/github/workflows/main.yml.tt @@ -0,0 +1,27 @@ +name: Ruby + +on: + push: + branches: + - <%= config[:git_default_branch] %> + + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + name: Ruby ${{ matrix.ruby }} + strategy: + matrix: + ruby: + - '<%= RUBY_VERSION %>' + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run the default task + run: bundle exec rake diff --git a/ruby/lib/bundler/templates/newgem/gitlab-ci.yml.tt b/ruby/lib/bundler/templates/newgem/gitlab-ci.yml.tt new file mode 100644 index 000000000..0e71ff26a --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/gitlab-ci.yml.tt @@ -0,0 +1,9 @@ +image: ruby:<%= RUBY_VERSION %> + +before_script: + - gem install bundler -v <%= Bundler::VERSION %> + - bundle install + +example_job: + script: + - bundle exec rake diff --git a/ruby/lib/bundler/templates/newgem/lib/newgem.rb.tt b/ruby/lib/bundler/templates/newgem/lib/newgem.rb.tt index fae6337c3..caf6e32f4 100644 --- a/ruby/lib/bundler/templates/newgem/lib/newgem.rb.tt +++ b/ruby/lib/bundler/templates/newgem/lib/newgem.rb.tt @@ -1,6 +1,8 @@ -require "<%= config[:namespaced_path] %>/version" +# frozen_string_literal: true + +require_relative "<%= File.basename(config[:namespaced_path]) %>/version" <%- if config[:ext] -%> -require "<%= config[:namespaced_path] %>/<%= config[:underscored_name] %>" +require_relative "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>" <%- end -%> <%- config[:constant_array].each_with_index do |c, i| -%> diff --git a/ruby/lib/bundler/templates/newgem/lib/newgem/version.rb.tt b/ruby/lib/bundler/templates/newgem/lib/newgem/version.rb.tt index 389daf504..b5cd4cb23 100644 --- a/ruby/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +++ b/ruby/lib/bundler/templates/newgem/lib/newgem/version.rb.tt @@ -1,3 +1,5 @@ +# frozen_string_literal: true + <%- config[:constant_array].each_with_index do |c, i| -%> <%= " " * i %>module <%= c %> <%- end -%> diff --git a/ruby/lib/bundler/templates/newgem/newgem.gemspec.tt b/ruby/lib/bundler/templates/newgem/newgem.gemspec.tt index 9bb3d0ff5..546a28b78 100644 --- a/ruby/lib/bundler/templates/newgem/newgem.gemspec.tt +++ b/ruby/lib/bundler/templates/newgem/newgem.gemspec.tt @@ -1,20 +1,22 @@ -require_relative 'lib/<%=config[:namespaced_path]%>/version' +# frozen_string_literal: true + +require_relative "lib/<%=config[:namespaced_path]%>/version" Gem::Specification.new do |spec| - spec.name = <%= config[:name].inspect %> - spec.version = <%= config[:constant_name] %>::VERSION - spec.authors = [<%= config[:author].inspect %>] - spec.email = [<%= config[:email].inspect %>] - - spec.summary = %q{TODO: Write a short summary, because RubyGems requires one.} - spec.description = %q{TODO: Write a longer description or delete this line.} - spec.homepage = "TODO: Put your gem's website or public repo URL here." + spec.name = <%= config[:name].inspect %> + spec.version = <%= config[:constant_name] %>::VERSION + spec.authors = [<%= config[:author].inspect %>] + spec.email = [<%= config[:email].inspect %>] + + spec.summary = "TODO: Write a short summary, because RubyGems requires one." + spec.description = "TODO: Write a longer description or delete this line." + spec.homepage = "TODO: Put your gem's website or public repo URL here." <%- if config[:mit] -%> - spec.license = "MIT" + spec.license = "MIT" <%- end -%> - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") + spec.required_ruby_version = ">= <%= config[:required_ruby_version] %>" - spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" + spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." @@ -22,13 +24,21 @@ Gem::Specification.new do |spec| # 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)/}) } + spec.files = Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0").reject do |f| + (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) + end end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] <%- if config[:ext] -%> - spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"] + spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"] <%- end -%> + + # Uncomment to register a new dependency of your gem + # spec.add_dependency "example-gem", "~> 1.0" + + # For more information and examples about making a new gem, check out our + # guide at: https://bundler.io/guides/creating_gem.html end diff --git a/ruby/lib/bundler/templates/newgem/rubocop.yml.tt b/ruby/lib/bundler/templates/newgem/rubocop.yml.tt new file mode 100644 index 000000000..9ecec7880 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/rubocop.yml.tt @@ -0,0 +1,13 @@ +AllCops: + TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %> + +Style/StringLiterals: + Enabled: true + EnforcedStyle: double_quotes + +Style/StringLiteralsInInterpolation: + Enabled: true + EnforcedStyle: double_quotes + +Layout/LineLength: + Max: 120 diff --git a/ruby/lib/bundler/templates/newgem/sig/newgem.rbs.tt b/ruby/lib/bundler/templates/newgem/sig/newgem.rbs.tt new file mode 100644 index 000000000..eb7b380bb --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/sig/newgem.rbs.tt @@ -0,0 +1,8 @@ +<%- config[:constant_array].each_with_index do |c, i| -%> +<%= " " * i %>module <%= c %> +<%- end -%> +<%= " " * config[:constant_array].size %>VERSION: String +<%= " " * config[:constant_array].size %># See the writing guide of rbs: https://github.com/ruby/rbs#guides +<%- (config[:constant_array].size-1).downto(0) do |i| -%> +<%= " " * i %>end +<%- end -%> diff --git a/ruby/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt b/ruby/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt index c63b48783..82cada988 100644 --- a/ruby/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +++ b/ruby/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.describe <%= config[:constant_name] %> do it "has a version number" do expect(<%= config[:constant_name] %>::VERSION).not_to be nil diff --git a/ruby/lib/bundler/templates/newgem/spec/spec_helper.rb.tt b/ruby/lib/bundler/templates/newgem/spec/spec_helper.rb.tt index 805cf57e0..70c6d1fcd 100644 --- a/ruby/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +++ b/ruby/lib/bundler/templates/newgem/spec/spec_helper.rb.tt @@ -1,4 +1,5 @@ -require "bundler/setup" +# frozen_string_literal: true + require "<%= config[:namespaced_path] %>" RSpec.configure do |config| diff --git a/ruby/lib/bundler/templates/newgem/standard.yml.tt b/ruby/lib/bundler/templates/newgem/standard.yml.tt new file mode 100644 index 000000000..934b0b2c3 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/standard.yml.tt @@ -0,0 +1,3 @@ +# For available configuration options, see: +# https://github.com/testdouble/standard +ruby_version: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %> diff --git a/ruby/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt b/ruby/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt new file mode 100644 index 000000000..e05c387bf --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) +require "<%= config[:namespaced_path] %>" + +require "minitest/autorun" diff --git a/ruby/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt b/ruby/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt new file mode 100644 index 000000000..4b35a6307 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "test_helper" + +class <%= config[:minitest_constant_name] %> < Minitest::Test + def test_that_it_has_a_version_number + refute_nil ::<%= config[:constant_name] %>::VERSION + end + + def test_it_does_something_useful + assert false + end +end diff --git a/ruby/lib/bundler/templates/newgem/test/newgem_test.rb.tt b/ruby/lib/bundler/templates/newgem/test/newgem_test.rb.tt deleted file mode 100644 index f2af9f90e..000000000 --- a/ruby/lib/bundler/templates/newgem/test/newgem_test.rb.tt +++ /dev/null @@ -1,11 +0,0 @@ -require "test_helper" - -class <%= config[:constant_name] %>Test < Minitest::Test - def test_that_it_has_a_version_number - refute_nil ::<%= config[:constant_name] %>::VERSION - end - - def test_it_does_something_useful - assert false - end -end diff --git a/ruby/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt b/ruby/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt new file mode 100644 index 000000000..5c61094e6 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require "test_helper" + +class <%= config[:constant_name] %>Test < Test::Unit::TestCase + test "VERSION" do + assert do + ::<%= config[:constant_name] %>.const_defined?(:VERSION) + end + end + + test "something useful" do + assert_equal("expected", "actual") + end +end diff --git a/ruby/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt b/ruby/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt new file mode 100644 index 000000000..6f633c603 --- /dev/null +++ b/ruby/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) +require "<%= config[:namespaced_path] %>" + +require "test-unit" diff --git a/ruby/lib/bundler/templates/newgem/test/test_helper.rb.tt b/ruby/lib/bundler/templates/newgem/test/test_helper.rb.tt deleted file mode 100644 index 7d7db165e..000000000 --- a/ruby/lib/bundler/templates/newgem/test/test_helper.rb.tt +++ /dev/null @@ -1,4 +0,0 @@ -$LOAD_PATH.unshift File.expand_path("../lib", __dir__) -require "<%= config[:namespaced_path] %>" - -require "minitest/autorun" diff --git a/ruby/lib/bundler/ui/shell.rb b/ruby/lib/bundler/ui/shell.rb index 92476be7d..384752a34 100644 --- a/ruby/lib/bundler/ui/shell.rb +++ b/ruby/lib/bundler/ui/shell.rb @@ -28,17 +28,17 @@ def confirm(msg, newline = nil) tell_me(msg, :green, newline) if level("confirm") end - def warn(msg, newline = nil) + def warn(msg, newline = nil, color = :yellow) return unless level("warn") return if @warning_history.include? msg @warning_history << msg - tell_err(msg, :yellow, newline) + tell_err(msg, color, newline) end - def error(msg, newline = nil) + def error(msg, newline = nil, color = :red) return unless level("error") - tell_err(msg, :red, newline) + tell_err(msg, color, newline) end def debug(msg, newline = nil) @@ -81,7 +81,7 @@ def level(name = nil) def trace(e, newline = nil, force = false) return unless debug? || force msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n ")}" - tell_me(msg, nil, newline) + tell_err(msg, nil, newline) end def silence(&blk) @@ -92,7 +92,7 @@ def unprinted_warnings [] end - private + private # valimism def tell_me(msg, color = nil, newline = nil) diff --git a/ruby/lib/bundler/uri_credentials_filter.rb b/ruby/lib/bundler/uri_credentials_filter.rb index 9b9e9c279..ccfaf0bc5 100644 --- a/ruby/lib/bundler/uri_credentials_filter.rb +++ b/ruby/lib/bundler/uri_credentials_filter.rb @@ -2,12 +2,14 @@ module Bundler module URICredentialsFilter - module_function + module_function def credential_filtered_uri(uri_to_anonymize) return uri_to_anonymize if uri_to_anonymize.nil? uri = uri_to_anonymize.dup if uri.is_a?(String) + return uri if File.exist?(uri) + require_relative "vendored_uri" uri = Bundler::URI(uri) end diff --git a/ruby/lib/bundler/vendor/.document b/ruby/lib/bundler/vendor/.document new file mode 100644 index 000000000..0c43bbd6b --- /dev/null +++ b/ruby/lib/bundler/vendor/.document @@ -0,0 +1 @@ +# Vendored files do not need to be documented diff --git a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool.rb b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool.rb index fbcd26c76..984c1c3dc 100644 --- a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +++ b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool.rb @@ -1,14 +1,18 @@ -require_relative 'connection_pool/version' -require_relative 'connection_pool/timed_stack' +require "timeout" +require_relative "connection_pool/version" +class Bundler::ConnectionPool + class Error < ::RuntimeError; end + class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end + class TimeoutError < ::Timeout::Error; end +end -# Generic connection pool class for e.g. sharing a limited number of network connections -# among many threads. Note: Connections are lazily created. +# Generic connection pool class for sharing a limited number of objects or network connections +# among many threads. Note: pool elements are lazily created. # # Example usage with block (faster): # # @pool = Bundler::ConnectionPool.new { Redis.new } -# # @pool.with do |redis| # redis.lpop('my-list') if redis.llen('my-list') > 0 # end @@ -34,29 +38,23 @@ class Bundler::ConnectionPool DEFAULTS = {size: 5, timeout: 5} - class Error < RuntimeError - end - def self.wrap(options, &block) Wrapper.new(options, &block) end def initialize(options = {}, &block) - raise ArgumentError, 'Connection pool requires a block' unless block + raise ArgumentError, "Connection pool requires a block" unless block options = DEFAULTS.merge(options) - @size = options.fetch(:size) + @size = Integer(options.fetch(:size)) @timeout = options.fetch(:timeout) @available = TimedStack.new(@size, &block) - @key = :"current-#{@available.object_id}" - @key_count = :"current-#{@available.object_id}-count" + @key = :"pool-#{@available.object_id}" + @key_count = :"pool-#{@available.object_id}-count" end -if Thread.respond_to?(:handle_interrupt) - - # MRI def with(options = {}) Thread.handle_interrupt(Exception => :never) do conn = checkout(options) @@ -69,28 +67,15 @@ def with(options = {}) end end end - -else - - # jruby 1.7.x - def with(options = {}) - conn = checkout(options) - begin - yield conn - ensure - checkin - end - end - -end + alias then with def checkout(options = {}) if ::Thread.current[@key] - ::Thread.current[@key_count]+= 1 + ::Thread.current[@key_count] += 1 ::Thread.current[@key] else - ::Thread.current[@key_count]= 1 - ::Thread.current[@key]= @available.pop(options[:timeout] || @timeout) + ::Thread.current[@key_count] = 1 + ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout) end end @@ -98,64 +83,44 @@ def checkin if ::Thread.current[@key] if ::Thread.current[@key_count] == 1 @available.push(::Thread.current[@key]) - ::Thread.current[@key]= nil + ::Thread.current[@key] = nil + ::Thread.current[@key_count] = nil else - ::Thread.current[@key_count]-= 1 + ::Thread.current[@key_count] -= 1 end else - raise Bundler::ConnectionPool::Error, 'no connections are checked out' + raise Bundler::ConnectionPool::Error, "no connections are checked out" end nil end + ## + # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and + # then removing it from the pool. Attempting to checkout a connection after + # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+. + def shutdown(&block) @available.shutdown(&block) end - # Size of this connection pool - def size - @size + ## + # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then + # removing it the pool. Subsequent checkouts will create new connections as + # needed. + + def reload(&block) + @available.shutdown(reload: true, &block) end + # Size of this connection pool + attr_reader :size + # Number of pool entries available for checkout at this instant. def available @available.length end - - private - - class Wrapper < ::BasicObject - METHODS = [:with, :pool_shutdown] - - def initialize(options = {}, &block) - @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) } - end - - def with(&block) - @pool.with(&block) - end - - def pool_shutdown(&block) - @pool.shutdown(&block) - end - - def pool_size - @pool.size - end - - def pool_available - @pool.available - end - - def respond_to?(id, *args) - METHODS.include?(id) || with { |c| c.respond_to?(id, *args) } - end - - def method_missing(name, *args, &block) - with do |connection| - connection.send(name, *args, &block) - end - end - end end + +require_relative "connection_pool/timed_stack" +require_relative "connection_pool/wrapper" diff --git a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb deleted file mode 100644 index 5a9c4a27b..000000000 --- a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +++ /dev/null @@ -1,66 +0,0 @@ -# Global monotonic clock from Concurrent Ruby 1.0. -# Copyright (c) Jerry D'Antonio -- released under the MIT license. -# Slightly modified; used with permission. -# https://github.com/ruby-concurrency/concurrent-ruby - -require 'thread' - -class Bundler::ConnectionPool - - class_definition = Class.new do - - if defined?(Process::CLOCK_MONOTONIC) - - # @!visibility private - def get_time - Process.clock_gettime(Process::CLOCK_MONOTONIC) - end - - elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' - - # @!visibility private - def get_time - java.lang.System.nanoTime() / 1_000_000_000.0 - end - - else - - # @!visibility private - def initialize - @mutex = Mutex.new - @last_time = Time.now.to_f - end - - # @!visibility private - def get_time - @mutex.synchronize do - now = Time.now.to_f - if @last_time < now - @last_time = now - else # clock has moved back in time - @last_time += 0.000_001 - end - end - end - end - end - - ## - # Clock that cannot be set and represents monotonic time since - # some unspecified starting point. - # - # @!visibility private - GLOBAL_MONOTONIC_CLOCK = class_definition.new - private_constant :GLOBAL_MONOTONIC_CLOCK - - class << self - ## - # Returns the current time a tracked by the application monotonic clock. - # - # @return [Float] The current monotonic time when `since` not given else - # the elapsed monotonic time between `since` and the current time - def monotonic_time - GLOBAL_MONOTONIC_CLOCK.get_time - end - end -end diff --git a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb index f3fe1e04a..a7b1cf06a 100644 --- a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +++ b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb @@ -1,13 +1,3 @@ -require 'thread' -require 'timeout' -require_relative 'monotonic_time' - -## -# Raised when you attempt to retrieve a connection from a pool that has been -# shut down. - -class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end - ## # The TimedStack manages a pool of homogeneous connections (or any resource # you wish to manage). Connections are created lazily up to a given maximum @@ -25,7 +15,7 @@ class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end # # conn = ts.pop # ts.pop timeout: 5 -# #=> raises Timeout::Error after 5 seconds +# #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds class Bundler::ConnectionPool::TimedStack attr_reader :max @@ -39,8 +29,8 @@ def initialize(size = 0, &block) @created = 0 @que = [] @max = size - @mutex = Mutex.new - @resource = ConditionVariable.new + @mutex = Thread::Mutex.new + @resource = Thread::ConditionVariable.new @shutdown_block = nil end @@ -59,12 +49,12 @@ def push(obj, options = {}) @resource.broadcast end end - alias_method :<<, :push + alias << push ## # Retrieves a connection from the stack. If a connection is available it is # immediately returned. If no connection is available within the given - # timeout a Timeout::Error is raised. + # timeout a Bundler::ConnectionPool::TimeoutError is raised. # # +:timeout+ is the only checked entry in +options+ and is preferred over # the +timeout+ argument (which will be removed in a future release). Other @@ -74,7 +64,7 @@ def pop(timeout = 0.5, options = {}) options, timeout = timeout, 0.5 if Hash === timeout timeout = options.fetch :timeout, timeout - deadline = Bundler::ConnectionPool.monotonic_time + timeout + deadline = current_time + timeout @mutex.synchronize do loop do raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block @@ -83,18 +73,20 @@ def pop(timeout = 0.5, options = {}) connection = try_create(options) return connection if connection - to_wait = deadline - Bundler::ConnectionPool.monotonic_time - raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0 + to_wait = deadline - current_time + raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0 @resource.wait(@mutex, to_wait) end end end ## - # Shuts down the TimedStack which prevents connections from being checked - # out. The +block+ is called once for each connection on the stack. + # Shuts down the TimedStack by passing each connection to +block+ and then + # removing it from the pool. Attempting to checkout a connection after + # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless + # +:reload+ is +true+. - def shutdown(&block) + def shutdown(reload: false, &block) raise ArgumentError, "shutdown must receive a block" unless block_given? @mutex.synchronize do @@ -102,6 +94,7 @@ def shutdown(&block) @resource.broadcast shutdown_connections + @shutdown_block = nil if reload end end @@ -121,6 +114,10 @@ def length private + def current_time + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + ## # This is an extension point for TimedStack and is called with a mutex. # @@ -149,6 +146,7 @@ def shutdown_connections(options = nil) conn = fetch_connection(options) @shutdown_block.call(conn) end + @created = 0 end ## diff --git a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb index b149c0e24..56ebf6990 100644 --- a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +++ b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb @@ -1,3 +1,3 @@ class Bundler::ConnectionPool - VERSION = "2.2.2" + VERSION = "2.3.0" end diff --git a/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb new file mode 100644 index 000000000..880170c06 --- /dev/null +++ b/ruby/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb @@ -0,0 +1,57 @@ +class Bundler::ConnectionPool + class Wrapper < ::BasicObject + METHODS = [:with, :pool_shutdown, :wrapped_pool] + + def initialize(options = {}, &block) + @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) } + end + + def wrapped_pool + @pool + end + + def with(&block) + @pool.with(&block) + end + + def pool_shutdown(&block) + @pool.shutdown(&block) + end + + def pool_size + @pool.size + end + + def pool_available + @pool.available + end + + def respond_to?(id, *args) + METHODS.include?(id) || with { |c| c.respond_to?(id, *args) } + end + + # rubocop:disable Style/MethodMissingSuper + # rubocop:disable Style/MissingRespondToMissing + if ::RUBY_VERSION >= "3.0.0" + def method_missing(name, *args, **kwargs, &block) + with do |connection| + connection.send(name, *args, **kwargs, &block) + end + end + elsif ::RUBY_VERSION >= "2.7.0" + ruby2_keywords def method_missing(name, *args, &block) + with do |connection| + connection.send(name, *args, &block) + end + end + else + def method_missing(name, *args, &block) + with do |connection| + connection.send(name, *args, &block) + end + end + end + # rubocop:enable Style/MethodMissingSuper + # rubocop:enable Style/MissingRespondToMissing + end +end diff --git a/ruby/lib/bundler/vendor/fileutils/lib/fileutils/version.rb b/ruby/lib/bundler/vendor/fileutils/lib/fileutils/version.rb deleted file mode 100644 index b8f616e4f..000000000 --- a/ruby/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -module Bundler::FileUtils - VERSION = "1.3.0" -end diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo.rb index baedefe98..a52b96dea 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require_relative 'molinillo/compatibility' require_relative 'molinillo/gem_metadata' require_relative 'molinillo/errors' require_relative 'molinillo/resolver' diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb deleted file mode 100644 index 3eba8e408..000000000 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # Hacks needed for old Ruby versions. - module Compatibility - module_function - - if [].respond_to?(:flat_map) - # Flat map - # @param [Enumerable] enum an enumerable object - # @block the block to flat-map with - # @return The enum, flat-mapped - def flat_map(enum, &blk) - enum.flat_map(&blk) - end - else - # Flat map - # @param [Enumerable] enum an enumerable object - # @block the block to flat-map with - # @return The enum, flat-mapped - def flat_map(enum, &blk) - enum.map(&blk).flatten(1) - end - end - end -end diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb index ec9c770a2..f8c695c1e 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb @@ -26,6 +26,13 @@ def requirement_satisfied_by?(requirement, activated, spec) end end + # (see Bundler::Molinillo::SpecificationProvider#dependencies_equal?) + def dependencies_equal?(dependencies, other_dependencies) + with_no_such_dependency_error_handling do + specification_provider.dependencies_equal?(dependencies, other_dependencies) + end + end + # (see Bundler::Molinillo::SpecificationProvider#name_for) def name_for(dependency) with_no_such_dependency_error_handling do diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb index 31578bb5b..10a25d2f0 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -require 'set' -require 'tsort' +require_relative '../../../../vendored_tsort' require_relative 'dependency_graph/log' require_relative 'dependency_graph/vertex' @@ -18,7 +17,7 @@ def each vertices.values.each { |v| yield v } end - include TSort + include Bundler::TSort # @!visibility private alias tsort_each_node each @@ -124,6 +123,7 @@ def to_dot(options = {}) dot.join("\n") end + # @param [DependencyGraph] other # @return [Boolean] whether the two dependency graphs are equal, determined # by a recursive traversal of each {#root_vertices} and its # {Vertex#successors} @@ -190,7 +190,7 @@ def root_vertex_named(name) # @return [Edge] the added edge def add_edge(origin, destination, requirement) if destination.path_to?(origin) - raise CircularDependencyError.new([origin, destination]) + raise CircularDependencyError.new(path(destination, origin)) end add_edge_no_circular(origin, destination, requirement) end @@ -219,5 +219,37 @@ def set_payload(name, payload) def add_edge_no_circular(origin, destination, requirement) log.add_edge_no_circular(self, origin.name, destination.name, requirement) end + + # Returns the path between two vertices + # @raise [ArgumentError] if there is no path between the vertices + # @param [Vertex] from + # @param [Vertex] to + # @return [Array] the shortest path from `from` to `to` + def path(from, to) + distances = Hash.new(vertices.size + 1) + distances[from.name] = 0 + predecessors = {} + each do |vertex| + vertex.successors.each do |successor| + if distances[successor.name] > distances[vertex.name] + 1 + distances[successor.name] = distances[vertex.name] + 1 + predecessors[successor] = vertex + end + end + end + + path = [to] + while before = predecessors[to] + path << before + to = before + break if to == from + end + + unless path.last.equal?(from) + raise ArgumentError, "There is no path from #{from.name} to #{to.name}" + end + + path.reverse + end end end diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb index fccfc78cc..5b5da3e4f 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb @@ -14,11 +14,11 @@ def self.action_name end # (see Action#up) - def up(_graph) + def up(graph) end # (see Action#down) - def down(_graph) + def down(graph) end # @!group Tag diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb index 41bc01314..1185a8ab0 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb @@ -59,7 +59,7 @@ def recursive_predecessors # @param [Set] vertices the set to add the predecessors to # @return [Set] the vertices of {#graph} where `self` is a # {#descendent?} - def _recursive_predecessors(vertices = Set.new) + def _recursive_predecessors(vertices = new_vertex_set) incoming_edges.each do |edge| vertex = edge.origin next unless vertices.add?(vertex) @@ -85,7 +85,7 @@ def recursive_successors # @param [Set] vertices the set to add the successors to # @return [Set] the vertices of {#graph} where `self` is an # {#ancestor?} - def _recursive_successors(vertices = Set.new) + def _recursive_successors(vertices = new_vertex_set) outgoing_edges.each do |edge| vertex = edge.destination next unless vertices.add?(vertex) @@ -128,7 +128,7 @@ def hash # Is there a path from `self` to `other` following edges in the # dependency graph? - # @return true iff there is a path following edges within this {#graph} + # @return whether there is a path following edges within this {#graph} def path_to?(other) _path_to?(other) end @@ -138,7 +138,7 @@ def path_to?(other) # @param [Vertex] other the vertex to check if there's a path to # @param [Set] visited the vertices of {#graph} that have been visited # @return [Boolean] whether there is a path to `other` from `self` - def _path_to?(other, visited = Set.new) + def _path_to?(other, visited = new_vertex_set) return false unless visited.add?(self) return true if equal?(other) successors.any? { |v| v._path_to?(other, visited) } @@ -147,12 +147,18 @@ def _path_to?(other, visited = Set.new) # Is there a path from `other` to `self` following edges in the # dependency graph? - # @return true iff there is a path following edges within this {#graph} + # @return whether there is a path following edges within this {#graph} def ancestor?(other) other.path_to?(self) end alias is_reachable_from? ancestor? + + def new_vertex_set + require 'set' + Set.new + end + private :new_vertex_set end end end diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb index 89c7c324d..e210202b6 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb @@ -34,7 +34,7 @@ def message # An error caused by attempting to fulfil a dependency that was circular # - # @note This exception will be thrown iff a {Vertex} is added to a + # @note This exception will be thrown if and only if a {Vertex} is added to a # {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an # existing {DependencyGraph::Vertex} class CircularDependencyError < ResolverError @@ -65,7 +65,7 @@ class VersionConflict < ResolverError # @param [SpecificationProvider] specification_provider see {#specification_provider} def initialize(conflicts, specification_provider) pairs = [] - Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting| + conflicts.values.flat_map(&:requirements).each do |conflicting| conflicting.each do |source, conflict_requirements| conflict_requirements.each do |c| pairs << [c, source] @@ -121,7 +121,7 @@ def message_with_trees(opts = {}) t = ''.dup depth = 2 tree.each do |req| - t << ' ' * depth << req.to_s + t << ' ' * depth << printable_requirement.call(req) unless tree.last == req if spec = conflict.activated_by_name[name_for(req)] t << %( was resolved to #{version_for_spec.call(spec)}, which) diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb index 73f8fbf2a..e13a781a5 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb @@ -2,5 +2,5 @@ module Bundler::Molinillo # The version of Bundler::Molinillo. - VERSION = '0.6.6'.freeze + VERSION = '0.7.0'.freeze end diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb index fa094c198..eeae79af3 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Bundler::Molinillo - # Provides information about specifcations and dependencies to the resolver, + # Provides information about specifications and dependencies to the resolver, # allowing the {Resolver} class to remain generic while still providing power # and flexibility. # @@ -45,6 +45,17 @@ def requirement_satisfied_by?(requirement, activated, spec) true end + # Determines whether two arrays of dependencies are equal, and thus can be + # grouped. + # + # @param [Array] dependencies + # @param [Array] other_dependencies + # @return [Boolean] whether `dependencies` and `other_dependencies` should + # be considered equal. + def dependencies_equal?(dependencies, other_dependencies) + dependencies == other_dependencies + end + # Returns the name for the given `dependency`. # @note This method should be 'pure', i.e. the return value should depend # only on the `dependency` parameter. diff --git a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb index acf777741..c689ca763 100644 --- a/ruby/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +++ b/ruby/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb @@ -207,7 +207,7 @@ def resolve def start_resolution @started_at = Time.now - handle_missing_or_push_dependency_state(initial_state) + push_initial_state debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" } resolver_ui.before_resolution @@ -273,10 +273,10 @@ def state states.last end - # Creates the initial state for the resolution, based upon the + # Creates and pushes the initial state for the resolution, based upon the # {#requested} dependencies - # @return [DependencyState] the initial state for the resolution - def initial_state + # @return [void] + def push_initial_state graph = DependencyGraph.new.tap do |dg| original_requested.each do |requested| vertex = dg.add_vertex(name_for(requested), nil, true) @@ -285,18 +285,7 @@ def initial_state dg.tag(:initial_state) end - requirements = sort_dependencies(original_requested, graph, {}) - initial_requirement = requirements.shift - DependencyState.new( - initial_requirement && name_for(initial_requirement), - requirements, - graph, - initial_requirement, - possibilities_for_requirement(initial_requirement, graph), - 0, - {}, - [] - ) + push_state_for_requirements(original_requested, true, graph) end # Unwinds the states stack because a conflict has been encountered @@ -340,11 +329,11 @@ def build_details_for_unwind # Look for past conflicts that could be unwound to affect the # requirement tree for the current conflict + all_reqs = last_detail_for_current_unwind.all_requirements + all_reqs_size = all_reqs.size relevant_unused_unwinds = unused_unwind_options.select do |alternative| - intersecting_requirements = - last_detail_for_current_unwind.all_requirements & - alternative.requirements_unwound_to_instead - next if intersecting_requirements.empty? + diff_reqs = all_reqs - alternative.requirements_unwound_to_instead + next if diff_reqs.size == all_reqs_size # Find the highest index unwind whilst looping through current_detail = alternative if alternative > current_detail alternative @@ -355,13 +344,17 @@ def build_details_for_unwind state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 } # Update the requirements_unwound_to_instead on any relevant unused unwinds - relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement } - unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement } + relevant_unused_unwinds.each do |d| + (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq! + end + unwind_details.each do |d| + (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq! + end current_detail end - # @param [Array] array of requirements that combine to create a conflict + # @param [Array] binding_requirements array of requirements that combine to create a conflict # @return [Array] array of UnwindDetails that have a chance # of resolving the passed requirements def unwind_options_for_requirements(binding_requirements) @@ -429,7 +422,7 @@ def unwind_options_for_requirements(binding_requirements) end # @param [DependencyState] state - # @param [Array] array of requirements + # @param [Array] binding_requirements array of requirements # @return [Boolean] whether or not the given state has any possibilities # that could satisfy the given requirements def conflict_fixing_possibilities?(state, binding_requirements) @@ -444,7 +437,8 @@ def conflict_fixing_possibilities?(state, binding_requirements) # Filter's a state's possibilities to remove any that would not fix the # conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from + # @param [UnwindDetails] unwind_details details of the conflict just + # unwound from # @return [void] def filter_possibilities_after_unwind(unwind_details) return unless state && !state.possibilities.empty? @@ -458,7 +452,7 @@ def filter_possibilities_after_unwind(unwind_details) # Filter's a state's possibilities to remove any that would not satisfy # the requirements in the conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from + # @param [UnwindDetails] unwind_details details of the conflict just unwound from # @return [void] def filter_possibilities_for_primary_unwind(unwind_details) unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } @@ -491,7 +485,7 @@ def possibility_satisfies_requirements?(possibility, requirements) # Filter's a state's possibilities to remove any that would (eventually) # create a requirement in the conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from + # @param [UnwindDetails] unwind_details details of the conflict just unwound from # @return [void] def filter_possibilities_for_parent_unwind(unwind_details) unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } @@ -500,7 +494,7 @@ def filter_possibilities_for_parent_unwind(unwind_details) primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq parent_unwinds = unwinds_to_state.uniq - primary_unwinds - allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind| + allowed_possibility_sets = primary_unwinds.flat_map do |unwind| states[unwind.state_index].possibilities.select do |possibility_set| possibility_set.possibilities.any? do |poss| possibility_satisfies_requirements?(poss, unwind.conflicting_requirements) @@ -508,7 +502,7 @@ def filter_possibilities_for_parent_unwind(unwind_details) end end - requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid) + requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid) state.possibilities.reject! do |possibility_set| !allowed_possibility_sets.include?(possibility_set) && @@ -524,12 +518,12 @@ def binding_requirements_for_conflict(conflict) possible_binding_requirements = conflict.requirements.values.flatten(1).uniq - # When there’s a `CircularDependency` error the conflicting requirement - # (the one causing the circular) won’t be `conflict.requirement` - # (which won’t be for the right state, because we won’t have created it, - # because it’s circular). - # We need to make sure we have that requirement in the conflict’s list, - # otherwise we won’t be able to unwind properly, so we just return all + # When there's a `CircularDependency` error the conflicting requirement + # (the one causing the circular) won't be `conflict.requirement` + # (which won't be for the right state, because we won't have created it, + # because it's circular). + # We need to make sure we have that requirement in the conflict's list, + # otherwise we won't be able to unwind properly, so we just return all # the requirements for the conflict. return possible_binding_requirements if conflict.underlying_error @@ -558,8 +552,8 @@ def binding_requirements_for_conflict(conflict) end # @param [Object] requirement we wish to check - # @param [Array] array of requirements - # @param [Array] array of possibilities the requirements will be used to filter + # @param [Array] possible_binding_requirements array of requirements + # @param [Array] possibilities array of possibilities the requirements will be used to filter # @return [Boolean] whether or not the given requirement is required to filter # out all elements of the array of possibilities. def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities) @@ -568,6 +562,7 @@ def binding_requirement_in_set?(requirement, possible_binding_requirements, poss end end + # @param [Object] requirement # @return [Object] the requirement that led to `requirement` being added # to the list of requirements. def parent_of(requirement) @@ -577,6 +572,7 @@ def parent_of(requirement) parent_state.requirement end + # @param [String] name # @return [Object] the requirement that led to a version of a possibility # with the given name being activated. def requirement_for_existing_name(name) @@ -585,6 +581,7 @@ def requirement_for_existing_name(name) states.find { |s| s.name == name }.requirement end + # @param [Object] requirement # @return [ResolutionState] the state whose `requirement` is the given # `requirement`. def find_state_for(requirement) @@ -592,6 +589,7 @@ def find_state_for(requirement) states.find { |i| requirement == i.requirement } end + # @param [Object] underlying_error # @return [Conflict] a {Conflict} that reflects the failure to activate # the {#possibility} in conjunction with the current {#state} def create_conflict(underlying_error = nil) @@ -628,6 +626,7 @@ def requirement_trees vertex.requirements.map { |r| requirement_tree_for(r) } end + # @param [Object] requirement # @return [Array] the list of requirements that led to # `requirement` being required. def requirement_tree_for(requirement) @@ -673,9 +672,8 @@ def attempt_to_activate attempt_to_filter_existing_spec(existing_vertex) else latest = possibility.latest_version - # use reject!(!satisfied) for 1.8.7 compatibility - possibility.possibilities.reject! do |possibility| - !requirement_satisfied_by?(requirement, activated, possibility) + possibility.possibilities.select! do |possibility| + requirement_satisfied_by?(requirement, activated, possibility) end if possibility.latest_version.nil? # ensure there's a possibility for better error messages @@ -705,7 +703,7 @@ def attempt_to_filter_existing_spec(vertex) # Generates a filtered version of the existing vertex's `PossibilitySet` using the # current state's `requirement` - # @param [Object] existing vertex + # @param [Object] vertex existing vertex # @return [PossibilitySet] filtered possibility set def filtered_possibility_set(vertex) PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities) @@ -730,7 +728,7 @@ def activate_new_spec end # Requires the dependencies that the recently activated spec has - # @param [Object] activated_possibility the PossibilitySet that has just been + # @param [Object] possibility_set the PossibilitySet that has just been # activated # @return [void] def require_nested_dependencies_for(possibility_set) @@ -749,6 +747,8 @@ def require_nested_dependencies_for(possibility_set) # Pushes a new {DependencyState} that encapsulates both existing and new # requirements # @param [Array] new_requirements + # @param [Boolean] requires_sort + # @param [Object] new_activated # @return [void] def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated) new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort @@ -767,7 +767,8 @@ def push_state_for_requirements(new_requirements, requires_sort = true, new_acti # Checks a proposed requirement with any existing locked requirement # before generating an array of possibilities for it. - # @param [Object] the proposed requirement + # @param [Object] requirement the proposed requirement + # @param [Object] activated # @return [Array] possibilities def possibilities_for_requirement(requirement, activated = self.activated) return [] unless requirement @@ -778,7 +779,8 @@ def possibilities_for_requirement(requirement, activated = self.activated) group_possibilities(search_for(requirement)) end - # @param [Object] the proposed requirement + # @param [Object] requirement the proposed requirement + # @param [Object] activated # @return [Array] possibility set containing only the locked requirement, if any def locked_requirement_possibility_set(requirement, activated = self.activated) all_possibilities = search_for(requirement) @@ -797,15 +799,15 @@ def locked_requirement_possibility_set(requirement, activated = self.activated) # Build an array of PossibilitySets, with each element representing a group of # dependency versions that all have the same sub-dependency version constraints # and are contiguous. - # @param [Array] an array of possibilities - # @return [Array] an array of possibility sets + # @param [Array] possibilities an array of possibilities + # @return [Array] an array of possibility sets def group_possibilities(possibilities) possibility_sets = [] current_possibility_set = nil possibilities.reverse_each do |possibility| dependencies = dependencies_for(possibility) - if current_possibility_set && current_possibility_set.dependencies == dependencies + if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies) current_possibility_set.possibilities.unshift(possibility) else possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility])) diff --git a/ruby/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/ruby/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb index f9d140106..beff6d658 100644 --- a/ruby/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ b/ruby/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb @@ -12,15 +12,11 @@ # servers you wish to talk to. For each host:port you communicate with a # single persistent connection is created. # -# Multiple Bundler::Persistent::Net::HTTP::Persistent objects will share the same set of -# connections. +# Connections will be shared across threads through a connection pool to +# increase reuse of connections. # -# For each thread you start a new connection will be created. A -# Bundler::Persistent::Net::HTTP::Persistent connection will not be shared across threads. -# -# You can shut down the HTTP connections when done by calling #shutdown. You -# should name your Bundler::Persistent::Net::HTTP::Persistent object if you intend to call this -# method. +# You can shut down any remaining HTTP connections when done by calling +# #shutdown. # # Example: # @@ -28,7 +24,7 @@ # # uri = Bundler::URI 'http://example.com/awesome/web/service' # -# http = Bundler::Persistent::Net::HTTP::Persistent.new name: 'my_app_name' +# http = Bundler::Persistent::Net::HTTP::Persistent.new # # # perform a GET # response = http.request uri @@ -50,14 +46,14 @@ # to use Bundler::URI#request_uri not Bundler::URI#path. The request_uri contains the query # params which are sent in the body for other requests. # -# == SSL +# == TLS/SSL # -# SSL connections are automatically created depending upon the scheme of the -# Bundler::URI. SSL connections are automatically verified against the default +# TLS connections are automatically created depending upon the scheme of the +# Bundler::URI. TLS connections are automatically verified against the default # certificate store for your computer. You can override this by changing # verify_mode or by specifying an alternate cert_store. # -# Here are the SSL settings, see the individual methods for documentation: +# Here are the TLS settings, see the individual methods for documentation: # # #certificate :: This client's certificate # #ca_file :: The certificate-authorities @@ -67,7 +63,7 @@ # #private_key :: The client's SSL private key # #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new # connection -# #ssl_timeout :: SSL session lifetime +# #ssl_timeout :: Session lifetime # #ssl_version :: Which specific SSL version to use # #verify_callback :: For server certificate verification # #verify_depth :: Depth of certificate verification @@ -96,14 +92,15 @@ # # === Segregation # -# By providing an application name to ::new you can separate your connections -# from the connections of other applications. +# Each Bundler::Persistent::Net::HTTP::Persistent instance has its own pool of connections. There +# is no sharing with other instances (as was true in earlier versions). # # === Idle Timeout # -# If a connection hasn't been used for this number of seconds it will automatically be -# reset upon the next use to avoid attempting to send to a closed connection. -# The default value is 5 seconds. nil means no timeout. Set through #idle_timeout. +# If a connection hasn't been used for this number of seconds it will +# automatically be reset upon the next use to avoid attempting to send to a +# closed connection. The default value is 5 seconds. nil means no timeout. +# Set through #idle_timeout. # # Reducing this value may help avoid the "too many connection resets" error # when sending non-idempotent requests while increasing this value will cause @@ -118,8 +115,9 @@ # # The number of requests that should be made before opening a new connection. # Typically many keep-alive capable servers tune this to 100 or less, so the -# 101st request will fail with ECONNRESET. If unset (default), this value has no -# effect, if set, connections will be reset on the request after max_requests. +# 101st request will fail with ECONNRESET. If unset (default), this value has +# no effect, if set, connections will be reset on the request after +# max_requests. # # === Open Timeout # @@ -131,45 +129,6 @@ # Socket options may be set on newly-created connections. See #socket_options # for details. # -# === Non-Idempotent Requests -# -# By default non-idempotent requests will not be retried per RFC 2616. By -# setting retry_change_requests to true requests will automatically be retried -# once. -# -# Only do this when you know that retrying a POST or other non-idempotent -# request is safe for your application and will not create duplicate -# resources. -# -# The recommended way to handle non-idempotent requests is the following: -# -# require 'bundler/vendor/net-http-persistent/lib/net/http/persistent' -# -# uri = Bundler::URI 'http://example.com/awesome/web/service' -# post_uri = uri + 'create' -# -# http = Bundler::Persistent::Net::HTTP::Persistent.new name: 'my_app_name' -# -# post = Net::HTTP::Post.new post_uri.path -# # ... fill in POST request -# -# begin -# response = http.request post_uri, post -# rescue Bundler::Persistent::Net::HTTP::Persistent::Error -# -# # POST failed, make a new request to verify the server did not process -# # the request -# exists_uri = uri + '...' -# response = http.get exists_uri -# -# # Retry if it failed -# retry if response.code == '404' -# end -# -# The method of determining if the resource was created or not is unique to -# the particular service you are using. Of course, you will want to add -# protection from infinite looping. -# # === Connection Termination # # If you are done using the Bundler::Persistent::Net::HTTP::Persistent instance you may shut down @@ -195,33 +154,27 @@ class Bundler::Persistent::Net::HTTP::Persistent HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc: ## - # The default connection pool size is 1/4 the allowed open files. + # The default connection pool size is 1/4 the allowed open files + # (ulimit -n) or 256 if your OS does not support file handle + # limits (typically windows). - if Gem.win_platform? then - DEFAULT_POOL_SIZE = 256 + if Process.const_defined? :RLIMIT_NOFILE + open_file_limits = Process.getrlimit(Process::RLIMIT_NOFILE) + + # Under JRuby on Windows Process responds to `getrlimit` but returns something that does not match docs + if open_file_limits.respond_to?(:first) + DEFAULT_POOL_SIZE = open_file_limits.first / 4 + else + DEFAULT_POOL_SIZE = 256 + end else - DEFAULT_POOL_SIZE = Process.getrlimit(Process::RLIMIT_NOFILE).first / 4 + DEFAULT_POOL_SIZE = 256 end ## # The version of Bundler::Persistent::Net::HTTP::Persistent you are using - VERSION = '3.1.0' - - ## - # Exceptions rescued for automatic retry on ruby 2.0.0. This overlaps with - # the exception list for ruby 1.x. - - RETRIED_EXCEPTIONS = [ # :nodoc: - (Net::ReadTimeout if Net.const_defined? :ReadTimeout), - IOError, - EOFError, - Errno::ECONNRESET, - Errno::ECONNABORTED, - Errno::EPIPE, - (OpenSSL::SSL::SSLError if HAVE_OPENSSL), - Timeout::Error, - ].compact + VERSION = '4.0.0' ## # Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various @@ -348,6 +301,13 @@ def self.detect_idle_timeout uri, max = 10 attr_accessor :max_requests + ## + # Number of retries to perform if a request fails. + # + # See also #max_retries=, Net::HTTP#max_retries=. + + attr_reader :max_retries + ## # The value sent in the Keep-Alive header. Defaults to 30. Not needed for # HTTP/1.1 servers. @@ -360,8 +320,7 @@ def self.detect_idle_timeout uri, max = 10 attr_accessor :keep_alive ## - # A name for this connection. Allows you to keep your connections apart - # from everybody else's. + # The name for this collection of persistent connections. attr_reader :name @@ -490,23 +449,11 @@ def self.detect_idle_timeout uri, max = 10 attr_reader :verify_mode - ## - # Enable retries of non-idempotent requests that change data (e.g. POST - # requests) when the server has disconnected. - # - # This will in the worst case lead to multiple requests with the same data, - # but it may be useful for some applications. Take care when enabling - # this option to ensure it is safe to POST or perform other non-idempotent - # requests to the server. - - attr_accessor :retry_change_requests - ## # Creates a new Bundler::Persistent::Net::HTTP::Persistent. # - # Set +name+ to keep your connections apart from everybody else's. Not - # required currently, but highly recommended. Your library name should be - # good enough. This parameter will be required in a future version. + # Set a +name+ for fun. Your library name should be good enough, but this + # otherwise has no purpose. # # +proxy+ may be set to a Bundler::URI::HTTP or :ENV to pick up proxy options from # the environment. See proxy_from_env for details. @@ -519,8 +466,9 @@ def self.detect_idle_timeout uri, max = 10 # proxy.password = 'hunter2' # # Set +pool_size+ to limit the maximum number of connections allowed. - # Defaults to 1/4 the number of allowed file handles. You can have no more - # than this many threads with active HTTP transactions. + # Defaults to 1/4 the number of allowed file handles or 256 if your OS does + # not support a limit on allowed file handles. You can have no more than + # this many threads with active HTTP transactions. def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE @name = name @@ -537,6 +485,7 @@ def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE @write_timeout = nil @idle_timeout = 5 @max_requests = nil + @max_retries = 1 @socket_options = [] @ssl_generation = 0 # incremented when SSL session variables change @@ -568,8 +517,6 @@ def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE @reuse_ssl_sessions = OpenSSL::SSL.const_defined? :Session end - @retry_change_requests = false - self.proxy = proxy if proxy end @@ -630,7 +577,9 @@ def connection_for uri net_http_args = [uri.hostname, uri.port] - if @proxy_uri and not proxy_bypass? uri.hostname, uri.port then + # I'm unsure if uri.host or uri.hostname should be checked against + # the proxy bypass list. + if @proxy_uri and not proxy_bypass? uri.host, uri.port then net_http_args.concat @proxy_args else net_http_args.concat [nil, nil, nil, nil] @@ -650,9 +599,11 @@ def connection_for uri reset connection end - http.read_timeout = @read_timeout if @read_timeout - http.write_timeout = @write_timeout if @write_timeout && http.respond_to?(:write_timeout=) - http.keep_alive_timeout = @idle_timeout if @idle_timeout + http.keep_alive_timeout = @idle_timeout if @idle_timeout + http.max_retries = @max_retries if http.respond_to?(:max_retries=) + http.read_timeout = @read_timeout if @read_timeout + http.write_timeout = @write_timeout if + @write_timeout && http.respond_to?(:write_timeout=) return yield connection rescue Errno::ECONNREFUSED @@ -670,27 +621,14 @@ def connection_for uri end ## - # Returns an error message containing the number of requests performed on - # this connection - - def error_message connection - connection.requests -= 1 # fixup - - age = Time.now - connection.last_use - - "after #{connection.requests} requests on #{connection.http.object_id}, " \ - "last used #{age} seconds ago" - end - - ## - # Bundler::URI::escape wrapper + # CGI::escape wrapper def escape str CGI.escape str if str end ## - # Bundler::URI::unescape wrapper + # CGI::unescape wrapper def unescape str CGI.unescape str if str @@ -733,6 +671,7 @@ def start http def finish connection connection.finish + connection.http.instance_variable_set :@last_communicated, nil connection.http.instance_variable_set :@ssl_session, nil unless @reuse_ssl_sessions end @@ -741,31 +680,31 @@ def finish connection # Returns the HTTP protocol version for +uri+ def http_version uri - @http_versions["#{uri.host}:#{uri.port}"] + @http_versions["#{uri.hostname}:#{uri.port}"] end ## - # Is +req+ idempotent according to RFC 2616? + # Adds "http://" to the String +uri+ if it is missing. - def idempotent? req - case req.method - when 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE' then - true - end + def normalize_uri uri + (uri =~ /^https?:/) ? uri : "http://#{uri}" end ## - # Is the request +req+ idempotent or is retry_change_requests allowed. + # Set the maximum number of retries for a request. + # + # Defaults to one retry. + # + # Set this to 0 to disable retries. - def can_retry? req - @retry_change_requests && !idempotent?(req) - end + def max_retries= retries + retries = retries.to_int - ## - # Adds "http://" to the String +uri+ if it is missing. + raise ArgumentError, "max_retries must be positive" if retries < 0 - def normalize_uri uri - (uri =~ /^https?:/) ? uri : "http://#{uri}" + @max_retries = retries + + reconnect end ## @@ -806,7 +745,7 @@ def proxy= proxy if @proxy_uri then @proxy_args = [ - @proxy_uri.host, + @proxy_uri.hostname, @proxy_uri.port, unescape(@proxy_uri.user), unescape(@proxy_uri.password), @@ -881,14 +820,15 @@ def proxy_bypass? host, port end ## - # Forces reconnection of HTTP connections. + # Forces reconnection of all HTTP connections, including TLS/SSL + # connections. def reconnect @generation += 1 end ## - # Forces reconnection of SSL connections. + # Forces reconnection of only TLS/SSL connections. def reconnect_ssl @ssl_generation += 1 @@ -921,14 +861,8 @@ def reset connection # the response will not have been read). # # +req+ must be a Net::HTTPGenericRequest subclass (see Net::HTTP for a list). - # - # If there is an error and the request is idempotent according to RFC 2616 - # it will be retried automatically. def request uri, req = nil, &block - retried = false - bad_response = false - uri = Bundler::URI uri req = request_setup req || uri response = nil @@ -942,37 +876,12 @@ def request uri, req = nil, &block response = http.request req, &block if req.connection_close? or - (response.http_version <= '1.0' and + (response.http_version <= '1.0' and not response.connection_keep_alive?) or - response.connection_close? then + response.connection_close? then finish connection end - rescue Net::HTTPBadResponse => e - message = error_message connection - - finish connection - - raise Error, "too many bad responses #{message}" if - bad_response or not can_retry? req - - bad_response = true - retry - rescue *RETRIED_EXCEPTIONS => e - request_failed e, req, connection if - retried or not can_retry? req - - reset connection - - retried = true - retry - rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2 - request_failed e, req, connection if retried or not can_retry? req - - reset connection - - retried = true - retry - rescue Exception => e + rescue Exception # make sure to close the connection when it was interrupted finish connection raise @@ -981,26 +890,11 @@ def request uri, req = nil, &block end end - @http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version + @http_versions["#{uri.hostname}:#{uri.port}"] ||= response.http_version response end - ## - # Raises an Error for +exception+ which resulted from attempting the request - # +req+ on the +connection+. - # - # Finishes the +connection+. - - def request_failed exception, req, connection # :nodoc: - due_to = "(due to #{exception.message} - #{exception.class})" - message = "too many connection resets #{due_to} #{error_message connection}" - - finish connection - - raise Error, message, exception.backtrace - end - ## # Creates a GET request if +req_or_uri+ is a Bundler::URI and adds headers to the # request. @@ -1008,7 +902,7 @@ def request_failed exception, req, connection # :nodoc: # Returns the request. def request_setup req_or_uri # :nodoc: - req = if Bundler::URI === req_or_uri then + req = if req_or_uri.respond_to? 'request_uri' then Net::HTTP::Get.new req_or_uri.request_uri else req_or_uri @@ -1172,7 +1066,6 @@ def verify_callback= callback reconnect_ssl end - end require_relative 'persistent/connection' diff --git a/ruby/lib/bundler/vendor/thor/lib/thor.rb b/ruby/lib/bundler/vendor/thor/lib/thor.rb index 01c0b2f83..0794dbb52 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor.rb @@ -1,7 +1,7 @@ -require "set" require_relative "thor/base" class Bundler::Thor + $thor_runner ||= false class << self # Allows for custom "Command" package naming. # @@ -323,7 +323,7 @@ def check_unknown_options?(config) #:nodoc: # ==== Parameters # Symbol ...:: A list of commands that should be affected. def stop_on_unknown_option!(*command_names) - stop_on_unknown_option.merge(command_names) + @stop_on_unknown_option = stop_on_unknown_option | command_names end def stop_on_unknown_option?(command) #:nodoc: @@ -337,29 +337,22 @@ def stop_on_unknown_option?(command) #:nodoc: # ==== Parameters # Symbol ...:: A list of commands that should be affected. def disable_required_check!(*command_names) - disable_required_check.merge(command_names) + @disable_required_check = disable_required_check | command_names end def disable_required_check?(command) #:nodoc: command && disable_required_check.include?(command.name.to_sym) end - def deprecation_warning(message) #:nodoc: - unless ENV['THOR_SILENCE_DEPRECATION'] - warn "Deprecation warning: #{message}\n" + - 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.' - end - end - protected def stop_on_unknown_option #:nodoc: - @stop_on_unknown_option ||= Set.new + @stop_on_unknown_option ||= [] end # help command has the required check disabled by default. def disable_required_check #:nodoc: - @disable_required_check ||= Set.new([:help]) + @disable_required_check ||= [:help] end # The method responsible for dispatching given the args. @@ -405,7 +398,6 @@ def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable Me # the namespace should be displayed as arguments. # def banner(command, namespace = nil, subcommand = false) - $thor_runner ||= false command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage| "#{basename} #{formatted_usage}" end.join("\n") diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/actions.rb b/ruby/lib/bundler/vendor/thor/lib/thor/actions.rb index a5368d07f..de9b3b4c8 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/actions.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/actions.rb @@ -161,6 +161,8 @@ def find_in_source_paths(file) # to the block you provide. The path is set back to the previous path when # the method exits. # + # Returns the value yielded by the block. + # # ==== Parameters # dir:: the directory to move to. # config:: give :verbose => true to log and use padding. @@ -179,16 +181,18 @@ def inside(dir = "", config = {}, &block) FileUtils.mkdir_p(destination_root) end + result = nil if pretend # In pretend mode, just yield down to the block - block.arity == 1 ? yield(destination_root) : yield + result = block.arity == 1 ? yield(destination_root) : yield else require "fileutils" - FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } + FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield } end @destination_stack.pop shell.padding -= 1 if verbose + result end # Goes to the root and execute the given block. @@ -219,7 +223,7 @@ def apply(path, config = {}) contents = if is_uri require "open-uri" - open(path, "Accept" => "application/x-thor-template", &:read) + URI.open(path, "Accept" => "application/x-thor-template", &:read) else open(path, &:read) end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb b/ruby/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb index 70504a2c1..fb76fcdbe 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb @@ -33,7 +33,8 @@ class CreateLink < CreateFile #:nodoc: # Boolean:: true if it is identical, false otherwise. # def identical? - exists? && File.identical?(render, destination) + source = File.expand_path(render, File.dirname(destination)) + exists? && File.identical?(source, destination) end def invoke! diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/ruby/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb index afdbd53dd..bf2a737c8 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb @@ -210,9 +210,9 @@ def append_to_file(path, *args, &block) # # ==== Examples # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n" + # inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n" # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController do + # inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do # " filter_parameter :password\n" # end # @@ -233,9 +233,9 @@ def inject_into_class(path, klass, *args, &block) # # ==== Examples # - # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n" + # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n" # - # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do + # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do # " def help; 'help'; end\n" # end # @@ -251,7 +251,8 @@ def inject_into_module(path, module_name, *args, &block) # path:: path of the file to be changed # flag:: the regexp or string to be replaced # replacement:: the replacement, can be also given as a block - # config:: give :verbose => false to not log the status. + # config:: give :verbose => false to not log the status, and + # :force => true, to force the replacement regardles of runner behavior. # # ==== Example # @@ -262,9 +263,10 @@ def inject_into_module(path, module_name, *args, &block) # end # def gsub_file(path, flag, *args, &block) - return unless behavior == :invoke config = args.last.is_a?(Hash) ? args.pop : {} + return unless behavior == :invoke || config.fetch(:force, false) + path = File.expand_path(path, destination_root) say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) @@ -329,7 +331,7 @@ def remove_file(path, config = {}) path = File.expand_path(path, destination_root) say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) - if !options[:pretend] && File.exist?(path) + if !options[:pretend] && (File.exist?(path) || File.symlink?(path)) require "fileutils" ::FileUtils.rm_rf(path) end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb b/ruby/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb index 09ce0864f..bf013307f 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb @@ -106,12 +106,11 @@ def say_status(behavior, warning: nil, color: nil) # Adds the content to the file. # def replace!(regexp, string, force) - return if pretend? content = File.read(destination) if force || !content.include?(replacement) success = content.gsub!(regexp, string) - File.open(destination, "wb") { |file| file.write(content) } + File.open(destination, "wb") { |file| file.write(content) } unless pretend? success end end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/base.rb b/ruby/lib/bundler/vendor/thor/lib/thor/base.rb index 9ba524337..8487f9590 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/base.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/base.rb @@ -22,6 +22,15 @@ class Bundler::Thor TEMPLATE_EXTNAME = ".tt" + class << self + def deprecation_warning(message) #:nodoc: + unless ENV['THOR_SILENCE_DEPRECATION'] + warn "Deprecation warning: #{message}\n" + + 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.' + end + end + end + module Base attr_accessor :options, :parent_options, :args diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb b/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb index c167aa33b..3c4483e5d 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb @@ -28,6 +28,12 @@ def delete(key) super(convert_key(key)) end + def except(*keys) + dup.tap do |hash| + keys.each { |key| hash.delete(convert_key(key)) } + end + end + def fetch(key, *args) super(convert_key(key), *args) end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb b/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb deleted file mode 100644 index 0f6e2e0af..000000000 --- a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +++ /dev/null @@ -1,12 +0,0 @@ -class IO #:nodoc: - class << self - unless method_defined? :binread - def binread(file, *args) - raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3 - File.open(file, "rb") do |f| - f.read(*args) - end - end - end - end -end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb b/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb deleted file mode 100644 index 76f1e43c6..000000000 --- a/ruby/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +++ /dev/null @@ -1,129 +0,0 @@ -class Bundler::Thor - module CoreExt - class OrderedHash < ::Hash - if RUBY_VERSION < "1.9" - def initialize(*args, &block) - super - @keys = [] - end - - def initialize_copy(other) - super - # make a deep copy of keys - @keys = other.keys - end - - def []=(key, value) - @keys << key unless key?(key) - super - end - - def delete(key) - if key? key - index = @keys.index(key) - @keys.delete_at index - end - super - end - - def delete_if - super - sync_keys! - self - end - - alias_method :reject!, :delete_if - - def reject(&block) - dup.reject!(&block) - end - - def keys - @keys.dup - end - - def values - @keys.map { |key| self[key] } - end - - def to_hash - self - end - - def to_a - @keys.map { |key| [key, self[key]] } - end - - def each_key - return to_enum(:each_key) unless block_given? - @keys.each { |key| yield(key) } - self - end - - def each_value - return to_enum(:each_value) unless block_given? - @keys.each { |key| yield(self[key]) } - self - end - - def each - return to_enum(:each) unless block_given? - @keys.each { |key| yield([key, self[key]]) } - self - end - - def each_pair - return to_enum(:each_pair) unless block_given? - @keys.each { |key| yield(key, self[key]) } - self - end - - alias_method :select, :find_all - - def clear - super - @keys.clear - self - end - - def shift - k = @keys.first - v = delete(k) - [k, v] - end - - def merge!(other_hash) - if block_given? - other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v } - else - other_hash.each { |k, v| self[k] = v } - end - self - end - - alias_method :update, :merge! - - def merge(other_hash, &block) - dup.merge!(other_hash, &block) - end - - # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not. - def replace(other) - super - @keys = other.keys - self - end - - def inspect - "#<#{self.class} #{super}>" - end - - private - - def sync_keys! - @keys.delete_if { |k| !key?(k) } - end - end - end - end -end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/error.rb b/ruby/lib/bundler/vendor/thor/lib/thor/error.rb index 1553afd20..03f2ce85b 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/error.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/error.rb @@ -1,5 +1,5 @@ class Bundler::Thor - Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable) + Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable) # rubocop:disable Naming/ConstantName # In order to support versions of Ruby that don't have keyword # arguments, we need our own spell checker class that doesn't take key # words. Even though this code wouldn't be hit because of the check @@ -102,9 +102,14 @@ class MalformattedArgumentError < InvocationError end if Correctable - DidYouMean::SPELL_CHECKERS.merge!( - 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker, - 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker - ) + if DidYouMean.respond_to?(:correct_error) + DidYouMean.correct_error(Bundler::Thor::UndefinedCommandError, UndefinedCommandError::SpellChecker) + DidYouMean.correct_error(Bundler::Thor::UnknownArgumentError, UnknownArgumentError::SpellChecker) + else + DidYouMean::SPELL_CHECKERS.merge!( + 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker, + 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker + ) + end end end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb b/ruby/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb index d0f43e2d9..3a5d82cf2 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb @@ -30,7 +30,11 @@ def initialize(arguments = []) arguments.each do |argument| if !argument.default.nil? - @assigns[argument.human_name] = argument.default + begin + @assigns[argument.human_name] = argument.default.dup + rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4 + @assigns[argument.human_name] = argument.default + end elsif argument.required? @non_assigned_required << argument end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/ruby/lib/bundler/vendor/thor/lib/thor/parser/options.rb index 6d1342ee3..5bd97aba6 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/parser/options.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/parser/options.rb @@ -45,6 +45,7 @@ def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disabl @switches = {} @extra = [] @stopped_parsing_after_extra_index = nil + @is_treated_as_value = false options.each do |option| @switches[option.switch_name] = option @@ -74,8 +75,19 @@ def peek end end + def shift + @is_treated_as_value = false + super + end + + def unshift(arg, is_value: false) + @is_treated_as_value = is_value + super(arg) + end + def parse(args) # rubocop:disable MethodLength @pile = args.dup + @is_treated_as_value = false @parsing_options = true while peek @@ -88,7 +100,10 @@ def parse(args) # rubocop:disable MethodLength when SHORT_SQ_RE unshift($1.split("").map { |f| "-#{f}" }) next - when EQ_RE, SHORT_NUM + when EQ_RE + unshift($2, is_value: true) + switch = $1 + when SHORT_NUM unshift($2) switch = $1 when LONG_RE, SHORT_RE @@ -133,20 +148,22 @@ def check_unknown! protected - def assign_result!(option, result) - if option.repeatable && option.type == :hash - (@assigns[option.human_name] ||= {}).merge!(result) - elsif option.repeatable - (@assigns[option.human_name] ||= []) << result - else - @assigns[option.human_name] = result + def assign_result!(option, result) + if option.repeatable && option.type == :hash + (@assigns[option.human_name] ||= {}).merge!(result) + elsif option.repeatable + (@assigns[option.human_name] ||= []) << result + else + @assigns[option.human_name] = result + end end - end + # Check if the current value in peek is a registered switch. # # Two booleans are returned. The first is true if the current value # starts with a hyphen; the second is true if it is a registered switch. def current_is_switch? + return [false, false] if @is_treated_as_value case peek when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM [true, switch?($1)] @@ -158,6 +175,7 @@ def current_is_switch? end def current_is_switch_formatted? + return false if @is_treated_as_value case peek when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE true @@ -167,6 +185,7 @@ def current_is_switch_formatted? end def current_is_value? + return true if @is_treated_as_value peek && (!parsing_options? || super) end diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/shell.rb b/ruby/lib/bundler/vendor/thor/lib/thor/shell.rb index e36fa472d..a4137d1bd 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/shell.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/shell.rb @@ -21,7 +21,7 @@ def shell end module Shell - SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width] + SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_error, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width] attr_writer :shell autoload :Basic, File.expand_path("shell/basic", __dir__) diff --git a/ruby/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/ruby/lib/bundler/vendor/thor/lib/thor/shell/basic.rb index be48358cb..8eff00bf3 100644 --- a/ruby/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +++ b/ruby/lib/bundler/vendor/thor/lib/thor/shell/basic.rb @@ -94,6 +94,8 @@ def ask(statement, *args) # say("I know you knew that.") # def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) + return if quiet? + buffer = prepare_message(message, *color) buffer << "\n" if force_new_line && !message.to_s.end_with?("\n") @@ -101,6 +103,23 @@ def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/) stdout.flush end + # Say (print) an error to the user. If the sentence ends with a whitespace + # or tab character, a new line is not appended (print + flush). Otherwise + # are passed straight to puts (behavior got from Highline). + # + # ==== Example + # say_error("error: something went wrong") + # + def say_error(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) + return if quiet? + + buffer = prepare_message(message, *color) + buffer << "\n" if force_new_line && !message.to_s.end_with?("\n") + + stderr.print(buffer) + stderr.flush + end + # Say a status with the given color and appends the message. Since this # method is used frequently by actions, it allows nil or false to be given # in log_status, avoiding the message from being shown. If a Symbol is @@ -109,13 +128,14 @@ def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/) def say_status(status, message, log_status = true) return if quiet? || log_status == false spaces = " " * (padding + 1) - color = log_status.is_a?(Symbol) ? log_status : :green - status = status.to_s.rjust(12) + margin = " " * status.length + spaces + + color = log_status.is_a?(Symbol) ? log_status : :green status = set_color status, color, true if color - buffer = "#{status}#{spaces}#{message}" - buffer = "#{buffer}\n" unless buffer.end_with?("\n") + message = message.to_s.chomp.gsub(/(?prefix_suffix. + # - If it is not specified or nil, "d" is used as the prefix and no suffix is used. + # - If it is a string, it is used as the prefix and no suffix is used. + # - If it is an array, first element is used as the prefix and second element is used as a suffix. + # + # Bundler::Dir.mktmpdir {|dir| dir is ".../d..." } + # Bundler::Dir.mktmpdir("foo") {|dir| dir is ".../foo..." } + # Bundler::Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" } + # + # The directory is created under Bundler::Dir.tmpdir or + # the optional second argument tmpdir if non-nil value is given. + # + # Bundler::Dir.mktmpdir {|dir| dir is "#{Bundler::Dir.tmpdir}/d..." } + # Bundler::Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." } + # + # If a block is given, + # it is yielded with the path of the directory. + # The directory and its contents are removed + # using Bundler::FileUtils.remove_entry before Bundler::Dir.mktmpdir returns. + # The value of the block is returned. + # + # Bundler::Dir.mktmpdir {|dir| + # # use the directory... + # open("#{dir}/foo", "w") { ... } + # } + # + # If a block is not given, + # The path of the directory is returned. + # In this case, Bundler::Dir.mktmpdir doesn't remove the directory. + # + # dir = Bundler::Dir.mktmpdir + # begin + # # use the directory... + # open("#{dir}/foo", "w") { ... } + # ensure + # # remove the directory. + # Bundler::FileUtils.remove_entry dir + # end + # + def self.mktmpdir(prefix_suffix=nil, *rest, **options) + base = nil + path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|p, _, _, d| + base = d + mkdir(p, 0700) + } + if block_given? + begin + yield path.dup + ensure + unless base + stat = File.stat(File.dirname(path)) + if stat.world_writable? and !stat.sticky? + raise ArgumentError, "parent directory is world writable but not sticky" + end + end + Bundler::FileUtils.remove_entry path + end + else + path + end + end + + module Tmpname # :nodoc: + module_function + + def tmpdir + Bundler::Dir.tmpdir + end + + UNUSABLE_CHARS = "^,-.0-9A-Z_a-z~" + + class << (RANDOM = Random.new) + MAX = 36**6 # < 0x100000000 + def next + rand(MAX).to_s(36) + end + end + private_constant :RANDOM + + def create(basename, tmpdir=nil, max_try: nil, **opts) + origdir = tmpdir + tmpdir ||= tmpdir() + n = nil + prefix, suffix = basename + prefix = (String.try_convert(prefix) or + raise ArgumentError, "unexpected prefix: #{prefix.inspect}") + prefix = prefix.delete(UNUSABLE_CHARS) + suffix &&= (String.try_convert(suffix) or + raise ArgumentError, "unexpected suffix: #{suffix.inspect}") + suffix &&= suffix.delete(UNUSABLE_CHARS) + begin + t = Time.now.strftime("%Y%m%d") + path = "#{prefix}#{t}-#{$$}-#{RANDOM.next}"\ + "#{n ? %[-#{n}] : ''}#{suffix||''}" + path = File.join(tmpdir, path) + yield(path, n, opts, origdir) + rescue Errno::EEXIST + n ||= 0 + n += 1 + retry if !max_try or n < max_try + raise "cannot generate temporary name using `#{basename}' under `#{tmpdir}'" + end + path + end + end +end diff --git a/ruby/lib/bundler/vendor/tsort/lib/tsort.rb b/ruby/lib/bundler/vendor/tsort/lib/tsort.rb new file mode 100644 index 000000000..845458329 --- /dev/null +++ b/ruby/lib/bundler/vendor/tsort/lib/tsort.rb @@ -0,0 +1,453 @@ +# frozen_string_literal: true + +#-- +# tsort.rb - provides a module for topological sorting and strongly connected components. +#++ +# + +# +# TSort implements topological sorting using Tarjan's algorithm for +# strongly connected components. +# +# TSort is designed to be able to be used with any object which can be +# interpreted as a directed graph. +# +# TSort requires two methods to interpret an object as a graph, +# tsort_each_node and tsort_each_child. +# +# * tsort_each_node is used to iterate for all nodes over a graph. +# * tsort_each_child is used to iterate for child nodes of a given node. +# +# The equality of nodes are defined by eql? and hash since +# TSort uses Hash internally. +# +# == A Simple Example +# +# The following example demonstrates how to mix the TSort module into an +# existing class (in this case, Hash). Here, we're treating each key in +# the hash as a node in the graph, and so we simply alias the required +# #tsort_each_node method to Hash's #each_key method. For each key in the +# hash, the associated value is an array of the node's child nodes. This +# choice in turn leads to our implementation of the required #tsort_each_child +# method, which fetches the array of child nodes and then iterates over that +# array using the user-supplied block. +# +# require 'tsort' +# +# class Hash +# include TSort +# alias tsort_each_node each_key +# def tsort_each_child(node, &block) +# fetch(node).each(&block) +# end +# end +# +# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort +# #=> [3, 2, 1, 4] +# +# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components +# #=> [[4], [2, 3], [1]] +# +# == A More Realistic Example +# +# A very simple `make' like tool can be implemented as follows: +# +# require 'tsort' +# +# class Make +# def initialize +# @dep = {} +# @dep.default = [] +# end +# +# def rule(outputs, inputs=[], &block) +# triple = [outputs, inputs, block] +# outputs.each {|f| @dep[f] = [triple]} +# @dep[triple] = inputs +# end +# +# def build(target) +# each_strongly_connected_component_from(target) {|ns| +# if ns.length != 1 +# fs = ns.delete_if {|n| Array === n} +# raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}") +# end +# n = ns.first +# if Array === n +# outputs, inputs, block = n +# inputs_time = inputs.map {|f| File.mtime f}.max +# begin +# outputs_time = outputs.map {|f| File.mtime f}.min +# rescue Errno::ENOENT +# outputs_time = nil +# end +# if outputs_time == nil || +# inputs_time != nil && outputs_time <= inputs_time +# sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i +# block.call +# end +# end +# } +# end +# +# def tsort_each_child(node, &block) +# @dep[node].each(&block) +# end +# include TSort +# end +# +# def command(arg) +# print arg, "\n" +# system arg +# end +# +# m = Make.new +# m.rule(%w[t1]) { command 'date > t1' } +# m.rule(%w[t2]) { command 'date > t2' } +# m.rule(%w[t3]) { command 'date > t3' } +# m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' } +# m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' } +# m.build('t5') +# +# == Bugs +# +# * 'tsort.rb' is wrong name because this library uses +# Tarjan's algorithm for strongly connected components. +# Although 'strongly_connected_components.rb' is correct but too long. +# +# == References +# +# R. E. Tarjan, "Depth First Search and Linear Graph Algorithms", +# SIAM Journal on Computing, Vol. 1, No. 2, pp. 146-160, June 1972. +# +module Bundler + module TSort + class Cyclic < StandardError + end + + # Returns a topologically sorted array of nodes. + # The array is sorted from children to parents, i.e. + # the first element has no child and the last node has no parent. + # + # If there is a cycle, TSort::Cyclic is raised. + # + # class G + # include TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # p graph.tsort #=> [4, 2, 3, 1] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # p graph.tsort # raises TSort::Cyclic + # + def tsort + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + TSort.tsort(each_node, each_child) + end + + # Returns a topologically sorted array of nodes. + # The array is sorted from children to parents, i.e. + # the first element has no child and the last node has no parent. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # If there is a cycle, TSort::Cyclic is raised. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic + # + def TSort.tsort(each_node, each_child) + TSort.tsort_each(each_node, each_child).to_a + end + + # The iterator version of the #tsort method. + # obj.tsort_each is similar to obj.tsort.each, but + # modification of _obj_ during the iteration may lead to unexpected results. + # + # #tsort_each returns +nil+. + # If there is a cycle, TSort::Cyclic is raised. + # + # class G + # include TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.tsort_each {|n| p n } + # #=> 4 + # # 2 + # # 3 + # # 1 + # + def tsort_each(&block) # :yields: node + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + TSort.tsort_each(each_node, each_child, &block) + end + + # The iterator version of the TSort.tsort method. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # TSort.tsort_each(each_node, each_child) {|n| p n } + # #=> 4 + # # 2 + # # 3 + # # 1 + # + def TSort.tsort_each(each_node, each_child) # :yields: node + return to_enum(__method__, each_node, each_child) unless block_given? + + TSort.each_strongly_connected_component(each_node, each_child) {|component| + if component.size == 1 + yield component.first + else + raise Cyclic.new("topological sort failed: #{component.inspect}") + end + } + end + + # Returns strongly connected components as an array of arrays of nodes. + # The array is sorted from children to parents. + # Each elements of the array represents a strongly connected component. + # + # class G + # include TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # p graph.strongly_connected_components #=> [[4], [2], [3], [1]] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # p graph.strongly_connected_components #=> [[4], [2, 3], [1]] + # + def strongly_connected_components + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + TSort.strongly_connected_components(each_node, each_child) + end + + # Returns strongly connected components as an array of arrays of nodes. + # The array is sorted from children to parents. + # Each elements of the array represents a strongly connected component. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p TSort.strongly_connected_components(each_node, each_child) + # #=> [[4], [2], [3], [1]] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p TSort.strongly_connected_components(each_node, each_child) + # #=> [[4], [2, 3], [1]] + # + def TSort.strongly_connected_components(each_node, each_child) + TSort.each_strongly_connected_component(each_node, each_child).to_a + end + + # The iterator version of the #strongly_connected_components method. + # obj.each_strongly_connected_component is similar to + # obj.strongly_connected_components.each, but + # modification of _obj_ during the iteration may lead to unexpected results. + # + # #each_strongly_connected_component returns +nil+. + # + # class G + # include TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.each_strongly_connected_component {|scc| p scc } + # #=> [4] + # # [2] + # # [3] + # # [1] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # graph.each_strongly_connected_component {|scc| p scc } + # #=> [4] + # # [2, 3] + # # [1] + # + def each_strongly_connected_component(&block) # :yields: nodes + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + TSort.each_strongly_connected_component(each_node, each_child, &block) + end + + # The iterator version of the TSort.strongly_connected_components method. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } + # #=> [4] + # # [2] + # # [3] + # # [1] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } + # #=> [4] + # # [2, 3] + # # [1] + # + def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes + return to_enum(__method__, each_node, each_child) unless block_given? + + id_map = {} + stack = [] + each_node.call {|node| + unless id_map.include? node + TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c| + yield c + } + end + } + nil + end + + # Iterates over strongly connected component in the subgraph reachable from + # _node_. + # + # Return value is unspecified. + # + # #each_strongly_connected_component_from doesn't call #tsort_each_node. + # + # class G + # include TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.each_strongly_connected_component_from(2) {|scc| p scc } + # #=> [4] + # # [2] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # graph.each_strongly_connected_component_from(2) {|scc| p scc } + # #=> [4] + # # [2, 3] + # + def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes + TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block) + end + + # Iterates over strongly connected components in a graph. + # The graph is represented by _node_ and _each_child_. + # + # _node_ is the first node. + # _each_child_ should have +call+ method which takes a node argument + # and yields for each child node. + # + # Return value is unspecified. + # + # #TSort.each_strongly_connected_component_from is a class method and + # it doesn't need a class to represent a graph which includes TSort. + # + # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_child = lambda {|n, &b| graph[n].each(&b) } + # TSort.each_strongly_connected_component_from(1, each_child) {|scc| + # p scc + # } + # #=> [4] + # # [2, 3] + # # [1] + # + def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes + return to_enum(__method__, node, each_child, id_map, stack) unless block_given? + + minimum_id = node_id = id_map[node] = id_map.size + stack_length = stack.length + stack << node + + each_child.call(node) {|child| + if id_map.include? child + child_id = id_map[child] + minimum_id = child_id if child_id && child_id < minimum_id + else + sub_minimum_id = + TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c| + yield c + } + minimum_id = sub_minimum_id if sub_minimum_id < minimum_id + end + } + + if node_id == minimum_id + component = stack.slice!(stack_length .. -1) + component.each {|n| id_map[n] = nil} + yield component + end + + minimum_id + end + + # Should be implemented by a extended class. + # + # #tsort_each_node is used to iterate for all nodes over a graph. + # + def tsort_each_node # :yields: node + raise NotImplementedError.new + end + + # Should be implemented by a extended class. + # + # #tsort_each_child is used to iterate for child nodes of _node_. + # + def tsort_each_child(node) # :yields: child + raise NotImplementedError.new + end + end +end diff --git a/ruby/lib/bundler/vendor/uri/lib/uri.rb b/ruby/lib/bundler/vendor/uri/lib/uri.rb index 00c01bd07..0e574dd2b 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri.rb @@ -86,7 +86,6 @@ # License:: # Copyright (c) 2001 akira yamada # You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # module Bundler::URI diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/common.rb b/ruby/lib/bundler/vendor/uri/lib/uri/common.rb index cc1ab86c2..6539e1810 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/common.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/common.rb @@ -3,7 +3,6 @@ # = uri/common.rb # # Author:: Akira Yamada -# Revision:: $Id$ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # @@ -61,82 +60,6 @@ def make_components_hash(klass, array_hash) module_function :make_components_hash end - # Module for escaping unsafe characters with codes. - module Escape - # - # == Synopsis - # - # Bundler::URI.escape(str [, unsafe]) - # - # == Args - # - # +str+:: - # String to replaces in. - # +unsafe+:: - # Regexp that matches all symbols that must be replaced with codes. - # By default uses UNSAFE. - # When this argument is a String, it represents a character set. - # - # == Description - # - # Escapes the string, replacing all unsafe characters with codes. - # - # This method is obsolete and should not be used. Instead, use - # CGI.escape, Bundler::URI.encode_www_form or Bundler::URI.encode_www_form_component - # depending on your specific use case. - # - # == Usage - # - # require 'bundler/vendor/uri/lib/uri' - # - # enc_uri = Bundler::URI.escape("http://example.com/?a=\11\15") - # # => "http://example.com/?a=%09%0D" - # - # Bundler::URI.unescape(enc_uri) - # # => "http://example.com/?a=\t\r" - # - # Bundler::URI.escape("@?@!", "!?") - # # => "@%3F@%21" - # - def escape(*arg) - warn "Bundler::URI.escape is obsolete", uplevel: 1 - DEFAULT_PARSER.escape(*arg) - end - alias encode escape - # - # == Synopsis - # - # Bundler::URI.unescape(str) - # - # == Args - # - # +str+:: - # String to unescape. - # - # == Description - # - # This method is obsolete and should not be used. Instead, use - # CGI.unescape, Bundler::URI.decode_www_form or Bundler::URI.decode_www_form_component - # depending on your specific use case. - # - # == Usage - # - # require 'bundler/vendor/uri/lib/uri' - # - # enc_uri = Bundler::URI.escape("http://example.com/?a=\11\15") - # # => "http://example.com/?a=%09%0D" - # - # Bundler::URI.unescape(enc_uri) - # # => "http://example.com/?a=\t\r" - # - def unescape(*arg) - warn "Bundler::URI.unescape is obsolete", uplevel: 1 - DEFAULT_PARSER.unescape(*arg) - end - alias decode unescape - end # module Escape - - extend Escape include REGEXP @@schemes = {} @@ -145,6 +68,20 @@ def self.scheme_list @@schemes end + # + # Construct a Bundler::URI instance, using the scheme to detect the appropriate class + # from +Bundler::URI.scheme_list+. + # + def self.for(scheme, *arguments, default: Generic) + if scheme + uri_class = @@schemes[scheme.upcase] || default + else + uri_class = default + end + + return uri_class.new(scheme, *arguments) + end + # # Base class for all Bundler::URI exceptions. # @@ -315,7 +252,7 @@ def self.extract(str, schemes = nil, &block) # # Returns a Regexp object which matches to Bundler::URI-like strings. # The Regexp object returned by this method includes arbitrary - # number of capture group (parentheses). Never rely on it's number. + # number of capture group (parentheses). Never rely on its number. # # == Usage # @@ -362,7 +299,7 @@ def self.regexp(schemes = nil) # If +enc+ is given, convert +str+ to the encoding before percent encoding. # # This is an implementation of - # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data. + # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data. # # See Bundler::URI.decode_www_form_component, Bundler::URI.encode_www_form. def self.encode_www_form_component(str, enc=nil) @@ -403,7 +340,7 @@ def self.decode_www_form_component(str, enc=Encoding::UTF_8) # This method doesn't handle files. When you send a file, use # multipart/form-data. # - # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer + # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer # # Bundler::URI.encode_www_form([["q", "ruby"], ["lang", "en"]]) # #=> "q=ruby&lang=en" diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/ftp.rb b/ruby/lib/bundler/vendor/uri/lib/uri/ftp.rb index ad39f57d7..2252e405d 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/ftp.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/ftp.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/generic.rb b/ruby/lib/bundler/vendor/uri/lib/uri/generic.rb index 56b09e1d7..f29ba6cf1 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/generic.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/generic.rb @@ -4,7 +4,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # @@ -1098,7 +1097,7 @@ def merge!(oth) # # => "http://my.example.com/main.rbx?page=1" # def merge(oth) - rel = parser.send(:convert_to_uri, oth) + rel = parser.__send__(:convert_to_uri, oth) if rel.absolute? #raise BadURIError, "both Bundler::URI are absolute" if absolute? @@ -1183,7 +1182,7 @@ def route_from_path(src, dst) # :stopdoc: def route_from0(oth) - oth = parser.send(:convert_to_uri, oth) + oth = parser.__send__(:convert_to_uri, oth) if self.relative? raise BadURIError, "relative Bundler::URI: #{self}" @@ -1291,7 +1290,7 @@ def route_from(oth) # #=> # # def route_to(oth) - parser.send(:convert_to_uri, oth).route_from(self) + parser.__send__(:convert_to_uri, oth).route_from(self) end # @@ -1405,7 +1404,7 @@ def eql?(oth) # Returns an Array of the components defined from the COMPONENT Array. def component_ary component.collect do |x| - self.send(x) + self.__send__(x) end end protected :component_ary @@ -1430,7 +1429,7 @@ def component_ary def select(*components) components.collect do |c| if component.include?(c) - self.send(c) + self.__send__(c) else raise ArgumentError, "expected of components of #{self.class} (#{self.class.component.join(', ')})" diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/http.rb b/ruby/lib/bundler/vendor/uri/lib/uri/http.rb index b6ca1c51d..50d7e427a 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/http.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/http.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/https.rb b/ruby/lib/bundler/vendor/uri/lib/uri/https.rb index 78dc6bf53..4fd4e9af7 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/https.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/https.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/ldap.rb b/ruby/lib/bundler/vendor/uri/lib/uri/ldap.rb index b707bedb9..6e9e1918f 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/ldap.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/ldap.rb @@ -7,7 +7,6 @@ # License:: # Bundler::URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada. # You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # @@ -119,6 +118,7 @@ def initialize(*arg) # Private method to cleanup +dn+ from using the +path+ component attribute. def parse_dn + raise InvalidURIError, 'bad LDAP URL' unless @path @dn = @path[1..-1] end private :parse_dn diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/mailto.rb b/ruby/lib/bundler/vendor/uri/lib/uri/mailto.rb index 5b2a4765c..ff7ab7e11 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/mailto.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/mailto.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See Bundler::URI for general documentation # diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb b/ruby/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb index a0d62ede6..e48e164f4 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb @@ -3,7 +3,6 @@ # = uri/common.rb # # Author:: Akira Yamada -# Revision:: $Id$ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # @@ -208,21 +207,9 @@ def split(uri) # #=> # # def parse(uri) - scheme, userinfo, host, port, - registry, path, opaque, query, fragment = self.split(uri) - - if scheme && Bundler::URI.scheme_list.include?(scheme.upcase) - Bundler::URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - else - Generic.new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - end + Bundler::URI.for(*self.split(uri), self) end - # # == Args # diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/ruby/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb index 07ef4391c..2029cfd05 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb @@ -69,18 +69,7 @@ def split(uri) #:nodoc: end def parse(uri) # :nodoc: - scheme, userinfo, host, port, - registry, path, opaque, query, fragment = self.split(uri) - scheme_list = Bundler::URI.scheme_list - if scheme && scheme_list.include?(uc = scheme.upcase) - scheme_list[uc].new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - else - Generic.new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - end + Bundler::URI.for(*self.split(uri), self) end diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/version.rb b/ruby/lib/bundler/vendor/uri/lib/uri/version.rb index 56177ef19..f2bb0ebad 100644 --- a/ruby/lib/bundler/vendor/uri/lib/uri/version.rb +++ b/ruby/lib/bundler/vendor/uri/lib/uri/version.rb @@ -1,6 +1,6 @@ module Bundler::URI # :stopdoc: - VERSION_CODE = '001000'.freeze + VERSION_CODE = '001001'.freeze VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze # :startdoc: end diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/ws.rb b/ruby/lib/bundler/vendor/uri/lib/uri/ws.rb new file mode 100644 index 000000000..58e08bf98 --- /dev/null +++ b/ruby/lib/bundler/vendor/uri/lib/uri/ws.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: false +# = uri/ws.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Bundler::URI for general documentation +# + +require_relative 'generic' + +module Bundler::URI + + # + # The syntax of WS URIs is defined in RFC6455 section 3. + # + # Note that the Ruby Bundler::URI library allows WS URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See . + # + class WS < Generic + # A Default port of 80 for Bundler::URI::WS. + DEFAULT_PORT = 80 + + # An Array of the available components for Bundler::URI::WS. + COMPONENT = %i[ + scheme + userinfo host port + path + query + ].freeze + + # + # == Description + # + # Creates a new Bundler::URI::WS object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, and query. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [userinfo, host, port, path, query]. + # + # Example: + # + # uri = Bundler::URI::WS.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = Bundler::URI::WS.build([nil, "www.example.com", nil, "/path", "query"]) + # + # Currently, if passed userinfo components this method generates + # invalid WS URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for a WS Bundler::URI, as required by Net::HTTP::Get. + # + # If the Bundler::URI contains a query, the full path is Bundler::URI#path + '?' + Bundler::URI#query. + # Otherwise, the path is simply Bundler::URI#path. + # + # Example: + # + # uri = Bundler::URI::WS.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + end + + @@schemes['WS'] = WS + +end diff --git a/ruby/lib/bundler/vendor/uri/lib/uri/wss.rb b/ruby/lib/bundler/vendor/uri/lib/uri/wss.rb new file mode 100644 index 000000000..3827053c7 --- /dev/null +++ b/ruby/lib/bundler/vendor/uri/lib/uri/wss.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: false +# = uri/wss.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Bundler::URI for general documentation +# + +require_relative 'ws' + +module Bundler::URI + + # The default port for WSS URIs is 443, and the scheme is 'wss:' rather + # than 'ws:'. Other than that, WSS URIs are identical to WS URIs; + # see Bundler::URI::WS. + class WSS < WS + # A Default port of 443 for Bundler::URI::WSS + DEFAULT_PORT = 443 + end + @@schemes['WSS'] = WSS +end diff --git a/ruby/lib/bundler/vendored_persistent.rb b/ruby/lib/bundler/vendored_persistent.rb index 045a761da..dc9573e02 100644 --- a/ruby/lib/bundler/vendored_persistent.rb +++ b/ruby/lib/bundler/vendored_persistent.rb @@ -1,12 +1,5 @@ # frozen_string_literal: true -# We forcibly require OpenSSL, because net/http/persistent will only autoload -# it. On some Rubies, autoload fails but explicit require succeeds. -begin - require "openssl" -rescue LoadError - # some Ruby builds don't have OpenSSL -end module Bundler module Persistent module Net diff --git a/ruby/lib/bundler/vendored_tmpdir.rb b/ruby/lib/bundler/vendored_tmpdir.rb new file mode 100644 index 000000000..43b4fa75f --- /dev/null +++ b/ruby/lib/bundler/vendored_tmpdir.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +module Bundler; end +require_relative "vendor/tmpdir/lib/tmpdir" diff --git a/ruby/lib/bundler/vendored_tsort.rb b/ruby/lib/bundler/vendored_tsort.rb new file mode 100644 index 000000000..38aed0b5d --- /dev/null +++ b/ruby/lib/bundler/vendored_tsort.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +module Bundler; end +require_relative "vendor/tsort/lib/tsort" diff --git a/ruby/lib/bundler/version.rb b/ruby/lib/bundler/version.rb index 85704816e..72c079b35 100644 --- a/ruby/lib/bundler/version.rb +++ b/ruby/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.1.4".freeze + VERSION = "2.3.7".freeze def self.bundler_major_version @bundler_major_version ||= VERSION.split(".").first.to_i diff --git a/ruby/lib/bundler/worker.rb b/ruby/lib/bundler/worker.rb index 3471654b4..5e4ee21c5 100644 --- a/ruby/lib/bundler/worker.rb +++ b/ruby/lib/bundler/worker.rb @@ -21,12 +21,12 @@ def initialize(exn) # @param func [Proc] job to run in inside the worker pool def initialize(size, name, func) @name = name - @request_queue = Queue.new - @response_queue = Queue.new + @request_queue = Thread::Queue.new + @response_queue = Thread::Queue.new @func = func @size = size @threads = nil - SharedHelpers.trap("INT") { abort_threads } + @previous_interrupt_handler = nil end # Enqueue a request to be executed in the worker pool @@ -48,7 +48,7 @@ def stop stop_threads end - private + private def process_queue(i) loop do @@ -68,13 +68,16 @@ def apply_func(obj, i) # so as worker threads after retrieving it, shut themselves down def stop_threads return unless @threads + @threads.each { @request_queue.enq POISON } @threads.each(&:join) + + remove_interrupt_handler + @threads = nil end def abort_threads - return unless @threads Bundler.ui.debug("\n#{caller.join("\n")}") @threads.each(&:exit) exit 1 @@ -94,11 +97,23 @@ def create_threads end end.compact + add_interrupt_handler unless @threads.empty? + return if creation_errors.empty? message = "Failed to create threads for the #{name} worker: #{creation_errors.map(&:to_s).uniq.join(", ")}" raise ThreadCreationError, message if @threads.empty? Bundler.ui.info message end + + def add_interrupt_handler + @previous_interrupt_handler = trap("INT") { abort_threads } + end + + def remove_interrupt_handler + return unless @previous_interrupt_handler + + trap "INT", @previous_interrupt_handler + end end end diff --git a/ruby/lib/bundler/yaml_serializer.rb b/ruby/lib/bundler/yaml_serializer.rb index 374b3bb5e..d5ecbd4ae 100644 --- a/ruby/lib/bundler/yaml_serializer.rb +++ b/ruby/lib/bundler/yaml_serializer.rb @@ -3,7 +3,7 @@ module Bundler # A stub yaml serializer that can handle only hashes and strings (as of now). module YAMLSerializer - module_function + module_function def dump(hash) yaml = String.new("---") diff --git a/ruby/lib/cgi.rb b/ruby/lib/cgi.rb index 4f16f309d..1a03d064f 100644 --- a/ruby/lib/cgi.rb +++ b/ruby/lib/cgi.rb @@ -288,6 +288,7 @@ # class CGI + VERSION = "0.3.1" end require 'cgi/core' diff --git a/ruby/lib/cgi/cgi.gemspec b/ruby/lib/cgi/cgi.gemspec index 58bd77027..3ba62b93f 100644 --- a/ruby/lib/cgi/cgi.gemspec +++ b/ruby/lib/cgi/cgi.gemspec @@ -1,27 +1,31 @@ -begin - require_relative "lib/cgi/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "cgi" - spec.version = CGI::VERSION + spec.name = name + spec.version = version spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{Support for the Common Gateway Interface protocol.} spec.description = %q{Support for the Common Gateway Interface protocol.} spec.homepage = "https://github.com/ruby/cgi" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = ">= 2.5.0" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{\A(?:(?:test|spec|features)/|\.git)}) } end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.extensions = ["ext/cgi/escape/extconf.rb"] + spec.executables = [] spec.require_paths = ["lib"] end diff --git a/ruby/lib/cgi/cookie.rb b/ruby/lib/cgi/cookie.rb index ae9ab58ed..6b0d89ca3 100644 --- a/ruby/lib/cgi/cookie.rb +++ b/ruby/lib/cgi/cookie.rb @@ -159,7 +159,6 @@ def self.parse(raw_cookie) raw_cookie.split(/;\s?/).each do |pairs| name, values = pairs.split('=',2) next unless name and values - name = CGI.unescape(name) values ||= "" values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) } if cookies.has_key?(name) diff --git a/ruby/lib/cgi/session.rb b/ruby/lib/cgi/session.rb index 29e7b3ece..70c7ebca4 100644 --- a/ruby/lib/cgi/session.rb +++ b/ruby/lib/cgi/session.rb @@ -189,6 +189,47 @@ def create_new_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). @@ -373,21 +414,8 @@ class FileStore # This session's FileStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) - dir = option['tmpdir'] || Dir::tmpdir - prefix = option['prefix'] || 'cgi_sid_' - suffix = option['suffix'] || '' - id = session.session_id - require 'digest/md5' - md5 = Digest::MD5.hexdigest(id)[0,16] - @path = dir+"/"+prefix+md5+suffix - if File::exist? @path - @hash = nil - else - unless session.new_session - raise CGI::Session::NoSession, "uninitialized session" - end - @hash = {} - end + option = {'prefix' => 'cgi_sid_'}.update(option) + @path, @hash = session.new_store_file(option) end # Restore session state from the session's FileStore file. diff --git a/ruby/lib/cgi/session/pstore.rb b/ruby/lib/cgi/session/pstore.rb index cc3006400..45d0d8ae2 100644 --- a/ruby/lib/cgi/session/pstore.rb +++ b/ruby/lib/cgi/session/pstore.rb @@ -44,20 +44,8 @@ class PStore # This session's PStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) - dir = option['tmpdir'] || Dir::tmpdir - prefix = option['prefix'] || '' - id = session.session_id - require 'digest/md5' - md5 = Digest::MD5.hexdigest(id)[0,16] - path = dir+"/"+prefix+md5 - if File::exist?(path) - @hash = nil - else - unless session.new_session - raise CGI::Session::NoSession, "uninitialized session" - end - @hash = {} - end + option = {'suffix'=>''}.update(option) + path, @hash = session.new_store_file(option) @p = ::PStore.new(path) @p.transaction do |p| File.chmod(0600, p.path) diff --git a/ruby/lib/cgi/util.rb b/ruby/lib/cgi/util.rb index aab8b000c..55e61bf98 100644 --- a/ruby/lib/cgi/util.rb +++ b/ruby/lib/cgi/util.rb @@ -49,9 +49,12 @@ def escapeHTML(string) 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 - return string + string + else + string = string.b + string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) + string.force_encoding(enc) end - string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) end begin @@ -90,7 +93,8 @@ def unescapeHTML(string) when Encoding::ISO_8859_1; 256 else 128 end - string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do + 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 "'" @@ -116,6 +120,7 @@ def unescapeHTML(string) "&#{match};" end end + string.force_encoding enc end # Synonym for CGI.escapeHTML(str) @@ -174,21 +179,12 @@ def unescapeElement(string, *elements) # Synonym for CGI.unescapeElement(str) alias unescape_element unescapeElement - # Abbreviated day-of-week names specified by RFC 822 - RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ] - - # Abbreviated month names specified by RFC 822 - RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ] - # 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) - t = time.clone.gmtime - return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", - RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, - t.hour, t.min, t.sec) + time.getgm.strftime("%a, %d %b %Y %T GMT") end # Prettify (indent) an HTML string. diff --git a/ruby/lib/cgi/version.rb b/ruby/lib/cgi/version.rb deleted file mode 100644 index 9d17c91b9..000000000 --- a/ruby/lib/cgi/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class CGI - VERSION = "0.1.0" -end diff --git a/ruby/lib/csv.rb b/ruby/lib/csv.rb index 8aa65868b..06a490f34 100644 --- a/ruby/lib/csv.rb +++ b/ruby/lib/csv.rb @@ -34,7 +34,7 @@ # 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 +# === \CSV Parsing # # * This parser is m17n aware. See CSV for full details. # * This library has a stricter parser and will throw MalformedCSVErrors on @@ -90,11 +90,11 @@ # with any questions. require "forwardable" -require "English" require "date" require "stringio" require_relative "csv/fields_converter" +require_relative "csv/input_record_separator" require_relative "csv/match_p" require_relative "csv/parser" require_relative "csv/row" @@ -103,85 +103,328 @@ using CSV::MatchP if CSV.const_defined?(:MatchP) +# == \CSV +# \CSV (comma-separated variables) 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 class 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. +# This \CSV \String, with row separator "\n" +# and column separator ",", +# has three rows and two columns: +# "foo,0\nbar,1\nbaz,2\n" # -# The most generic interface of the library is: +# Despite the name \CSV, a \CSV representation can use different separators. # -# csv = CSV.new(string_or_io, **options) +# 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]" # -# # Reading: IO object should be open for read -# csv.read # => array of rows -# # or -# csv.each do |row| -# # ... -# end -# # or -# row = csv.shift +# == \Class \CSV # -# # Writing: IO object should be open for write -# csv << row +# 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. # -# There are several specialized class methods for one-statement reading or writing, -# described in the Specialized Methods section. +# To make \CSV available: +# require 'csv' # -# If a String is passed into ::new, it is internally wrapped into a StringIO object. +# All examples here assume that this has been done. # -# +options+ can be used for specifying the particular CSV flavor (column -# separators, row separators, value quoting and so on), and for data conversion, -# see Data Conversion section for the description of the latter. +# == Keeping It Simple # -# == Specialized Methods +# 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. # -# === Reading +# 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. # -# # From a file: all at once -# arr_of_rows = CSV.read("path/to/file.csv", **options) -# # iterator-style: -# CSV.foreach("path/to/file.csv", **options) do |row| -# # ... -# end +# === Simple Parsing # -# # From a string -# arr_of_rows = CSV.parse("CSV,data,String", **options) -# # or -# CSV.parse("CSV,data,String", **options) do |row| -# # ... -# end +# 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"]] # -# === Writing +# As does method CSV.parse: +# File.open(path) do |file| +# CSV.parse(file) +# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] # -# # To a file -# CSV.open("path/to/file.csv", "wb") do |csv| -# csv << ["row", "of", "CSV", "data"] -# csv << ["another", "row"] -# # ... +# \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" # -# # To a String -# csv_string = CSV.generate do |csv| -# csv << ["row", "of", "CSV", "data"] -# csv << ["another", "row"] -# # ... +# === "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 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 # -# === Shortcuts +# :include: ../doc/csv/options/generating/write_headers.rdoc # -# # Core extensions for converting one line -# csv_string = ["CSV", "data"].to_csv # to CSV -# csv_array = "CSV,String".parse_csv # from CSV +# :include: ../doc/csv/options/generating/force_quotes.rdoc # -# # CSV() method -# CSV { |csv_out| csv_out << %w{my data here} } # to $stdout -# CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String -# CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr -# CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin +# :include: ../doc/csv/options/generating/quote_empty.rdoc # -# == Data Conversion +# :include: ../doc/csv/options/generating/write_converters.rdoc # -# === CSV with headers +# :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 @@ -203,24 +446,351 @@ # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary]) # data.first #=> # # -# === Typed data reading -# -# CSV allows to provide a set of data _converters_ e.g. transformations to try on input -# data. Converter could be a symbol from CSV::Converters constant's keys, or lambda. -# -# # Without any converters: -# CSV.parse('Bob,2018-03-01,100') -# #=> [["Bob", "2018-03-01", "100"]] -# -# # With built-in converters: -# CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date]) -# #=> [["Bob", #, 100]] -# -# # With custom converters: -# CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }]) -# #=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]] +# === \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 +:dowhcase+, +# 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" # -# == CSV and Character Encodings (M17n or Multilingualization) +# === 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 @@ -301,30 +871,12 @@ def initialize(message, line_number) # 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 holds the built-in converters of CSV that can be accessed by name. - # You can select Converters with CSV.convert() or through the +options+ Hash - # passed to CSV::new(). - # - # :integer:: Converts any field Integer() accepts. - # :float:: Converts any field Float() accepts. - # :numeric:: A combination of :integer - # and :float. - # :date:: Converts any field Date::parse() accepts. - # :date_time:: Converts any field DateTime::parse() accepts. - # :all:: All built-in converters. A combination of - # :date_time and :numeric. - # - # All built-in converters transcode field data to UTF-8 before attempting a - # conversion. If your data cannot be transcoded to UTF-8 the conversion will - # fail and the field will remain unchanged. - # - # This Hash is intentionally left unfrozen and users should feel free to add - # values to it that can be accessed by all CSV objects. - # - # To add a combo field, the value should be an Array of names. Combo fields - # can be nested with other combo fields. - # + # 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 @@ -352,27 +904,12 @@ def initialize(message, line_number) 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 holds the built-in header converters of CSV that can be accessed - # by name. You can select HeaderConverters with CSV.header_convert() or - # through the +options+ Hash passed to CSV::new(). - # - # :downcase:: Calls downcase() on the header String. - # :symbol:: Leading/trailing spaces are dropped, string is - # downcased, remaining spaces are replaced with - # underscores, non-word characters are dropped, - # and finally to_sym() is called. - # - # All built-in header converters transcode header data to UTF-8 before - # attempting a conversion. If your data cannot be transcoded to UTF-8 the - # conversion will fail and the header will remain unchanged. - # - # This Hash is intentionally left unfrozen and users should feel free to add - # values to it that can be accessed by all CSV objects. - # - # To add a combo field, the value should be an Array of names. Combo fields - # can be nested with other combo fields. - # + # 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| @@ -381,28 +918,13 @@ def initialize(message, line_number) } } - # - # The options used when no overrides are given by calling code. They are: - # - # :col_sep:: "," - # :row_sep:: :auto - # :quote_char:: '"' - # :field_size_limit:: +nil+ - # :converters:: +nil+ - # :unconverted_fields:: +nil+ - # :headers:: +false+ - # :return_headers:: +false+ - # :header_converters:: +nil+ - # :skip_blanks:: +false+ - # :force_quotes:: +false+ - # :skip_lines:: +nil+ - # :liberal_parsing:: +false+ - # :quote_empty:: +true+ - # + # 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, converters: nil, unconverted_fields: nil, @@ -410,22 +932,64 @@ def initialize(message, line_number) return_headers: false, header_converters: nil, skip_blanks: false, - force_quotes: 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. + # + # --- # - # This method will return a CSV instance, just like CSV::new(), but the - # instance will be cached and returned for all future calls to this method for - # the same +data+ object (tested by Object#object_id()) with the same - # +options+. + # With no block given, returns a \CSV object. # - # If a block is given, the instance is passed to the block and the return - # value becomes the return value of the block. + # 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] + @@ -442,33 +1006,64 @@ def instance(data = $stdout, **options) end end - # # :call-seq: - # filter( **options ) { |row| ... } - # filter( input, **options ) { |row| ... } - # filter( input, output, **options ) { |row| ... } - # - # This method is a convenience for building Unix-like filters for CSV data. - # Each row is yielded to the provided block which can alter it as needed. - # After the block returns, the row is appended to +output+ altered or not. + # filter(**options) {|row| ... } + # filter(in_string, **options) {|row| ... } + # filter(in_io, **options) {|row| ... } + # filter(in_string, out_string, **options) {|row| ... } + # filter(in_string, out_io, **options) {|row| ... } + # filter(in_io, out_string, **options) {|row| ... } + # filter(in_io, out_io, **options) {|row| ... } # - # The +input+ and +output+ arguments can be anything CSV::new() accepts - # (generally String or IO objects). If not given, they default to - # ARGF and $stdout. + # Reads \CSV input and writes \CSV output. # - # The +options+ parameter is also filtered down to CSV::new() after some - # clever key parsing. Any key beginning with :in_ or - # :input_ will have that leading identifier stripped and will only - # be used in the +options+ Hash for the +input+ object. Keys starting with - # :out_ or :output_ affect only +output+. All other keys - # are assigned to both objects. + # For each input row: + # - Forms the data into: + # - A CSV::Row object, if headers are in use. + # - An \Array of Arrays, otherwise. + # - Calls the block with that object. + # - Appends the block's return value to the output. # - # The :output_row_sep +option+ defaults to - # $INPUT_RECORD_SEPARATOR ($/). + # Arguments: + # * \CSV source: + # * Argument +in_string+, if given, should be a \String object; + # it will be put into a new StringIO object positioned at the beginning. + # * Argument +in_io+, if given, should be an IO object that is + # open for reading; on return, the IO object will be closed. + # * If neither +in_string+ nor +in_io+ is given, + # the input stream defaults to {ARGF}[https://ruby-doc.org/core/ARGF.html]. + # * \CSV output: + # * Argument +out_string+, if given, should be a \String object; + # it will be put into a new StringIO object positioned at the beginning. + # * Argument +out_io+, if given, should be an IO object that is + # ppen for writing; on return, the IO object will be closed. + # * If neither +out_string+ nor +out_io+ is given, + # the output stream defaults to $stdout. + # * Argument +options+ should be keyword arguments. + # - Each argument name that is prefixed with +in_+ or +input_+ + # is stripped of its prefix and is treated as an option + # for parsing the input. + # Option +input_row_sep+ defaults to $INPUT_RECORD_SEPARATOR. + # - Each argument name that is prefixed with +out_+ or +output_+ + # is stripped of its prefix and is treated as an option + # for generating the output. + # Option +output_row_sep+ defaults to $INPUT_RECORD_SEPARATOR. + # - Each argument not prefixed as above is treated as an option + # both for parsing the input and for generating the output. + # - See {Options for Parsing}[#class-CSV-label-Options+for+Parsing] + # and {Options for Generating}[#class-CSV-label-Options+for+Generating]. # + # Example: + # 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" def filter(input=nil, output=nil, **options) # parse options for input, output, or both - in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR} + in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value} options.each do |key, value| case key.to_s when /\Ain(?:put)?_(.+)\Z/ @@ -480,10 +1075,29 @@ def filter(input=nil, output=nil, **options) out_options[key] = value end end + # build input and output wrappers - input = new(input || ARGF, **in_options) + 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 @@ -492,18 +1106,111 @@ def filter(input=nil, output=nil, **options) end # - # This method is intended as the primary interface for reading CSV files. You - # pass a +path+ and any +options+ you wish to set for the read. Each row of - # file will be passed to the provided +block+ in turn. + # :call-seq: + # foreach(path, mode='r', **options) {|row| ... ) + # foreach(io, mode='r', **options {|row| ... ) + # foreach(path, mode='r', headers: ..., **options) {|row| ... ) + # foreach(io, mode='r', headers: ..., **options {|row| ... ) + # foreach(path, mode='r', **options) -> new_enumerator + # foreach(io, mode='r', **options -> new_enumerator + # + # Calls the block with each row read from source +path+ or +io+. + # + # * 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 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. + # + # ====== Without Option +headers+ + # + # Without option +headers+, returns each row as an \Array object. + # + # These examples assume prior execution of: + # string = "foo,0\nbar,1\nbaz,2\n" + # path = 't.csv' + # File.write(path, string) + # + # Read rows from a file at +path+: + # CSV.foreach(path) {|row| p row } + # Output: + # ["foo", "0"] + # ["bar", "1"] + # ["baz", "2"] + # + # Read rows from an \IO object: + # File.open(path) do |file| + # CSV.foreach(file) {|row| p row } + # end + # + # Output: + # ["foo", "0"] + # ["bar", "1"] + # ["baz", "2"] + # + # Returns a new \Enumerator if no block given: + # CSV.foreach(path) # => # + # CSV.foreach(File.open(path)) # => #, "r")> + # + # Issues a warning if an encoding is unsupported: + # CSV.foreach(File.open(path), encoding: 'foo:bar') {|row| } + # Output: + # warning: Unsupported encoding foo ignored + # warning: Unsupported encoding bar ignored + # + # ====== With Option +headers+ # - # The +options+ parameter can be anything CSV::new() understands. This method - # also understands an additional :encoding parameter that you can use - # to specify the Encoding of the data in the file to be read. You must provide - # this unless your data is in Encoding::default_external(). CSV 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 CSV parses it. + # With {option +headers+}[#class-CSV-label-Option+headers], + # returns each 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) + # + # Read rows from a file at +path+: + # CSV.foreach(path, headers: true) {|row| p row } + # + # Output: + # # + # # + # # + # + # Read rows from an \IO object: + # File.open(path) do |file| + # CSV.foreach(file, headers: true) {|row| p row } + # end + # + # Output: + # # + # # + # # + # + # --- + # + # Raises an exception if +path+ is a \String, but not the path to a readable file: + # # Raises Errno::ENOENT (No such file or directory @ rb_sysopen - nosuch.csv): + # CSV.foreach('nosuch.csv') {|row| } + # + # Raises an exception if +io+ is an \IO object, but not open for reading: + # io = File.open(path, 'w') {|row| } + # # Raises TypeError (no implicit conversion of nil into String): + # CSV.foreach(io) {|row| } + # + # Raises an exception if +mode+ is invalid: + # # Raises ArgumentError (invalid access mode nosuch): + # CSV.foreach(path, 'nosuch') {|row| } # def foreach(path, mode="r", **options, &block) return to_enum(__method__, path, mode, **options) unless block_given? @@ -514,29 +1221,71 @@ def foreach(path, mode="r", **options, &block) # # :call-seq: - # generate( str, **options ) { |csv| ... } - # generate( **options ) { |csv| ... } + # 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. + # + # --- # - # This method wraps a String you provide, or an empty default String, in a - # CSV object which is passed to the provided block. You can use the block to - # append CSV rows to the String and when the block exits, the final String - # will be returned. + # 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 # - # Note that a passed String *is* modified by this method. Call dup() before - # passing if you need a new String. + # 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 # - # The +options+ parameter can be anything CSV::new() understands. This method - # understands an additional :encoding parameter when not passed a - # String to set the base Encoding for the output. CSV needs this hint if you - # plan to output non-ASCII compatible data. + # 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 - encoding = options[:encoding] str = +"" str.force_encoding(encoding) if encoding end @@ -545,97 +1294,140 @@ def generate(str=nil, **options) 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]. + # + # --- # - # This method is a shortcut for converting a single row (Array) into a CSV - # String. + # Returns the \String generated from an \Array: + # CSV.generate_line(['foo', '0']) # => "foo,0\n" # - # The +options+ parameter can be anything CSV::new() understands. This method - # understands an additional :encoding parameter to set 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. + # --- # - # The :row_sep +option+ defaults to $INPUT_RECORD_SEPARATOR - # ($/) when calling this method. + # 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: $INPUT_RECORD_SEPARATOR}.merge(options) + options = {row_sep: InputRecordSeparator.value}.merge(options) str = +"" if options[:encoding] str.force_encoding(options[:encoding]) - elsif field = row.find {|f| f.is_a?(String)} - str.force_encoding(field.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: - # open( filename, mode = "rb", **options ) { |faster_csv| ... } - # open( filename, **options ) { |faster_csv| ... } - # open( filename, mode = "rb", **options ) - # open( filename, **options ) - # - # This method opens an IO object, and wraps that with CSV. This is intended - # as the primary interface for writing a CSV file. - # - # You must pass a +filename+ and may optionally add a +mode+ for Ruby's - # open(). You may also pass an optional Hash containing any +options+ - # CSV::new() understands as the final argument. - # - # This method works like Ruby's open() call, in that it will pass a CSV object - # to a provided block and close it when the block terminates, or it will - # return the CSV object when no block is provided. (*Note*: This is different - # from the Ruby 1.8 CSV library which passed rows to the block. Use - # CSV::foreach() for that behavior.) - # - # You must provide a +mode+ with an embedded Encoding designator unless your - # data is in Encoding::default_external(). CSV will check the Encoding of the - # underlying IO object (set by the +mode+ you pass) to determine how to parse - # the data. You may provide a second Encoding to have the data transcoded as - # it is read just as you can with a normal call to IO::open(). For example, - # "rb:UTF-32BE:UTF-8" would read UTF-32BE data from the file but - # transcode it to UTF-8 before CSV parses it. - # - # An opened CSV object will delegate to many IO methods for convenience. You - # may call: - # - # * binmode() - # * binmode?() - # * close() - # * close_read() - # * close_write() - # * closed?() - # * eof() - # * eof?() - # * external_encoding() - # * fcntl() - # * fileno() - # * flock() - # * flush() - # * fsync() - # * internal_encoding() - # * ioctl() - # * isatty() - # * path() - # * pid() - # * pos() - # * pos=() - # * reopen() - # * seek() - # * stat() - # * sync() - # * sync=() - # * tell() - # * to_i() - # * to_io() - # * truncate() - # * tty?() + # 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: + # hash 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 = {universal_newline: false}.merge(options) + options.delete(:invalid) + options.delete(:undef) + options.delete(:replace) begin f = File.open(filename, mode, **file_opts) @@ -666,16 +1458,116 @@ def open(filename, mode="r", **options) # # :call-seq: - # parse( str, **options ) { |row| ... } - # parse( str, **options ) + # 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) # - # This method can be used to easily parse CSV out of a String. You may either - # provide a +block+ which will be called with each row of the String in turn, - # or just use the returned Array of Arrays (when no +block+ is given). + # --- # - # You pass your +str+ to read from, and an optional +options+ containing - # anything CSV::new() understands. + # 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) @@ -689,44 +1581,117 @@ def parse(str, **options, &block) 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"] # - # This method is a shortcut for converting a single line of a CSV String into - # an Array. Note that if +line+ contains multiple rows, anything beyond the - # first row is ignored. + # Returns +nil+ if the argument is an empty \String: + # CSV.parse_line('') # => nil # - # The +options+ parameter can be anything CSV::new() understands. + # ====== 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).shift + new(line, **options).each.first end # - # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the - # file and any +options+ CSV::new() understands. This method also understands - # an additional :encoding parameter that you can use to specify the - # Encoding of the data in the file to be read. You must provide this unless - # your data is in Encoding::default_external(). CSV 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 CSV parses it. + # :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 - # Alias for CSV::read(). + # :call-seq: + # CSV.readlines(source, **options) + # + # Alias for CSV.read. def readlines(path, **options) read(path, **options) end + # :call-seq: + # CSV.table(source, **options) # - # A shortcut for: + # Calls CSV.read with +source+, +options+, and certain default options: + # - +headers+: +true+ + # - +converters+: +:numeric+ + # - +header_converters+: +:symbol+ # - # CSV.read( path, { headers: true, - # converters: :numeric, - # header_converters: :symbol }.merge(options) ) + # 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, @@ -738,185 +1703,43 @@ def table(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. # - # This constructor will wrap either a String or IO object passed in +data+ for - # reading and/or writing. In addition to the CSV instance methods, several IO - # methods are delegated. (See CSV::open() for a complete list.) If you pass - # a String for +data+, you can later retrieve it (after writing to it, for - # example) with CSV.string(). - # - # Note that a wrapped String will be positioned at the beginning (for - # reading). If you want it at the end (for writing), use CSV::generate(). - # If you want any other positioning, pass a preset StringIO object instead. - # - # You may set any reading and/or writing preferences in the +options+ Hash. - # Available options are: - # - # :col_sep:: The String placed between each field. - # This String will be transcoded into - # the data's Encoding before parsing. - # :row_sep:: The String appended to the end of each - # row. This can be set to the special - # :auto setting, which requests - # that CSV automatically discover this - # from the data. Auto-discovery reads - # ahead in the data looking for the next - # "\r\n", "\n", or - # "\r" sequence. A sequence - # will be selected even if it occurs in - # a quoted field, assuming that you - # would have the same line endings - # there. If none of those sequences is - # found, +data+ is ARGF, - # STDIN, STDOUT, or - # STDERR, or the stream is only - # available for output, the default - # $INPUT_RECORD_SEPARATOR - # ($/) is used. Obviously, - # discovery takes a little time. Set - # manually if speed is important. Also - # note that IO objects should be opened - # in binary mode on Windows if this - # feature will be used as the - # line-ending translation can cause - # problems with resetting the document - # position to where it was before the - # read ahead. This String will be - # transcoded into the data's Encoding - # before parsing. - # :quote_char:: The character used to quote fields. - # This has to be a single character - # String. This is useful for - # application that incorrectly use - # ' as the quote character - # instead of the correct ". - # CSV will always consider a double - # sequence of this character to be an - # escaped quote. This String will be - # transcoded into the data's Encoding - # before parsing. - # :field_size_limit:: This is a maximum size CSV will read - # ahead looking for the closing quote - # for a field. (In truth, it reads to - # the first line ending beyond this - # size.) If a quote cannot be found - # within the limit CSV will raise a - # MalformedCSVError, assuming the data - # is faulty. You can use this limit to - # prevent what are effectively DoS - # attacks on the parser. However, this - # limit can cause a legitimate parse to - # fail and thus is set to +nil+, or off, - # by default. - # :converters:: An Array of names from the Converters - # Hash and/or lambdas that handle custom - # conversion. A single converter - # doesn't have to be in an Array. All - # built-in converters try to transcode - # fields to UTF-8 before converting. - # The conversion will fail if the data - # cannot be transcoded, leaving the - # field unchanged. - # :unconverted_fields:: If set to +true+, an - # unconverted_fields() method will be - # added to all returned rows (Array or - # CSV::Row) that will return the fields - # as they were before conversion. Note - # that :headers supplied by - # Array or String were not fields of the - # document and thus will have an empty - # Array attached. - # :headers:: If set to :first_row or - # +true+, the initial row of the CSV - # file will be treated as a row of - # headers. If set to an Array, the - # contents will be used as the headers. - # If set to a String, the String is run - # through a call of CSV::parse_line() - # with the same :col_sep, - # :row_sep, and - # :quote_char as this instance - # to produce an Array of headers. This - # setting causes CSV#shift() to return - # rows as CSV::Row objects instead of - # Arrays and CSV#read() to return - # CSV::Table objects instead of an Array - # of Arrays. - # :return_headers:: When +false+, header rows are silently - # swallowed. If set to +true+, header - # rows are returned in a CSV::Row object - # with identical headers and - # fields (save that the fields do not go - # through the converters). - # :write_headers:: When +true+ and :headers is - # set, a header row will be added to the - # output. - # :header_converters:: Identical in functionality to - # :converters save that the - # conversions are only made to header - # rows. All built-in converters try to - # transcode headers to UTF-8 before - # converting. The conversion will fail - # if the data cannot be transcoded, - # leaving the header unchanged. - # :skip_blanks:: When setting a +true+ value, CSV will - # skip over any empty rows. Note that - # this setting will not skip rows that - # contain column separators, even if - # the rows contain no actual data. If - # you want to skip rows that contain - # separators but no content, consider - # using :skip_lines, or - # inspecting fields.compact.empty? on - # each row. - # :force_quotes:: When setting a +true+ value, CSV will - # quote all CSV fields it creates. - # :skip_lines:: When setting an object responding to - # match, every line matching - # it is considered a comment and ignored - # during parsing. When set to a String, - # it is first converted to a Regexp. - # When set to +nil+ no line is considered - # a comment. If the passed object does - # not respond to match, - # ArgumentError is thrown. - # :liberal_parsing:: When setting a +true+ value, CSV will - # attempt to parse input not conformant - # with RFC 4180, such as double quotes - # in unquoted fields. - # :nil_value:: When set an object, any values of an - # empty field is replaced by the set - # object, not nil. - # :empty_value:: When setting an object, any values of a - # blank string field is replaced by - # the set object. - # :quote_empty:: When setting a +true+ value, CSV will - # quote empty values with double quotes. - # When +false+, CSV will emit an - # empty string for an empty field value. - # :write_converters:: Converts values on each line with the - # specified Proc object(s), - # which receive a String value - # and return a String or +nil+ - # value. - # When an array is specified, each - # converter will be applied in order. - # :write_nil_value:: When a String value, +nil+ - # value(s) on each line will be replaced - # with the specified value. - # :write_empty_value:: When a String or +nil+ value, - # empty value(s) on each line will be - # replaced with the specified value. - # :strip:: When setting a +true+ value, CSV will - # strip "\t\r\n\f\v" around the values. - # If you specify a string instead of - # +true+, CSV will strip string. The - # length of the string must be 1. - # - # See CSV::DEFAULT_OPTIONS for the default settings. - # - # Options cannot be overridden in the instance methods for performance reasons, - # so be sure to set what you want here. + # 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: ",", @@ -938,11 +1761,11 @@ def initialize(data, encoding: nil, nil_value: nil, empty_value: "", + strip: false, quote_empty: true, write_converters: nil, write_nil_value: nil, - write_empty_value: "", - strip: false) + write_empty_value: "") raise ArgumentError.new("Cannot parse nil as CSV") if data.nil? if data.is_a?(String) @@ -1001,51 +1824,71 @@ def initialize(data, writer if @writer_options[:write_headers] end + # :call-seq: + # csv.col_sep -> string # - # The encoded :col_sep used in parsing and writing. - # See CSV::new for details. - # + # 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 # - # The encoded :row_sep used in parsing and writing. - # See CSV::new for details. - # + # 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 # - # The encoded :quote_char used in parsing and writing. - # See CSV::new for details. - # + # 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 # - # The limit for field size, if any. - # See CSV::new for details. - # + # 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 def field_size_limit parser.field_size_limit end + # :call-seq: + # csv.skip_lines -> regexp or nil # - # The regex marking a line as a comment. - # See CSV::new for details. - # + # 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 - # - # Returns the current list of converters in effect. See CSV::new for details. - # Built-in converters will be returned by name, while others will be returned - # as is. - # + # :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) @@ -1053,19 +1896,23 @@ def converters end end + # :call-seq: + # csv.unconverted_fields? -> object # - # Returns +true+ if unconverted_fields() to parsed results. - # See CSV::new for details. - # + # 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 +nil+ if headers will not be used, +true+ if they will but have not - # yet been read, or the actual headers after they have been read. - # See CSV::new for details. - # + # 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 @@ -1077,27 +1924,37 @@ def headers raw_headers end end + + # :call-seq: + # csv.return_headers? -> true or false # - # Returns +true+ if headers will be returned as a row of results. - # See CSV::new for details. - # + # 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 +true+ if headers are written in output. - # See CSV::new for details. - # + # 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 the current list of converters in effect for headers. See CSV::new - # for details. Built-in converters will be returned by name, while others - # will be returned as is. + # 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) @@ -1105,34 +1962,74 @@ def header_converters end end + # :call-seq: + # csv.skip_blanks? -> true or false # - # Returns +true+ blank lines are skipped by the parser. See CSV::new - # for details. - # + # 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 - # Returns +true+ if all output fields are quoted. See CSV::new for details. + # :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 - # Returns +true+ if illegal input is handled. See CSV::new for details. + # :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 -> endcoding # - # The Encoding CSV is parsing or writing in. This will be the Encoding you - # receive parsed data in and/or the Encoding data will be written in. - # + # 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 - # - # The line number of the last row read from this file. Fields with nested - # line-end characters will not affect this count. - # + # :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 @@ -1141,9 +2038,22 @@ def lineno end end - # - # The last row read from this file. - # + # :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 @@ -1219,13 +2129,56 @@ def rewind ### End Delegation ### - # - # The primary write method for wrapped Strings and IOs, +row+ (an Array or - # CSV::Row) is converted to CSV and appended to the data source. When a - # CSV::Row is passed, only the row's fields() are appended to the output. - # - # The data source must be open for writing. - # + # :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 @@ -1233,58 +2186,216 @@ def <<(row) alias_method :add_row, :<< alias_method :puts, :<< - # # :call-seq: - # convert( name ) - # convert { |field| ... } - # convert { |field, field_info| ... } - # - # You can use this method to install a CSV::Converters built-in, or provide a - # block that handles a custom conversion. - # - # If you provide a block that takes one argument, it will be passed the field - # and is expected to return the converted value or the field itself. If your - # block takes two arguments, it will also be passed a CSV::FieldInfo Struct, - # containing details about the field. Again, the block should return a - # converted field or the field itself. - # + # 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( name ) - # header_convert { |field| ... } - # header_convert { |field, field_info| ... } - # - # Identical to CSV#convert(), but for header rows. - # - # Note that this method must be called before header rows are read to have any - # effect. - # + # 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 - # - # Yields each row of the data source in turn. - # - # Support for Enumerable. - # - # The data source must be open for reading. - # + # :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) parser_enumerator.each(&block) end - # - # Slurps the remaining rows and returns an Array of Arrays. - # - # The data source must be open for reading. - # + # :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? @@ -1295,18 +2406,69 @@ def read end alias_method :readlines, :read - # Returns +true+ if the next row read will be a header row. + # :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 - # - # The primary read method for wrapped Strings and IOs, a single row is pulled - # from the data source, parsed and returned as an Array of fields (if header - # rows are not used) or a CSV::Row (when header rows are used). - # - # The data source must be open for reading. - # + # :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 @@ -1321,10 +2483,14 @@ def shift alias_method :gets, :shift alias_method :readline, :shift + # :call-seq: + # csv.inspect -> string # - # Returns a simplified description of the key CSV attributes in an - # ASCII compatible 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 @@ -1429,7 +2595,7 @@ def parser_fields_converter def build_parser_fields_converter specific_options = { - builtin_converters: Converters, + builtin_converters_name: :Converters, } options = @base_fields_converter_options.merge(specific_options) build_fields_converter(@initial_converters, options) @@ -1441,7 +2607,7 @@ def header_fields_converter def build_header_fields_converter specific_options = { - builtin_converters: HeaderConverters, + builtin_converters_name: :HeaderConverters, accept_nil: true, } options = @base_fields_converter_options.merge(specific_options) @@ -1504,8 +2670,15 @@ def writer_options # c.read.any? { |a| a.include?("zombies") } # } #=> false # -def CSV(*args, &block) - CSV.instance(*args, &block) +# 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" diff --git a/ruby/lib/csv/csv.gemspec b/ruby/lib/csv/csv.gemspec index 98110bc13..11c5b0f2a 100644 --- a/ruby/lib/csv/csv.gemspec +++ b/ruby/lib/csv/csv.gemspec @@ -16,29 +16,49 @@ Gem::Specification.new do |spec| 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [ + 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", - "lib/csv.rb", - "lib/csv/core_ext/array.rb", - "lib/csv/core_ext/string.rb", - "lib/csv/delete_suffix.rb", - "lib/csv/fields_converter.rb", - "lib/csv/match_p.rb", - "lib/csv/parser.rb", - "lib/csv/row.rb", - "lib/csv/table.rb", - "lib/csv/version.rb", - "lib/csv/writer.rb", ] - spec.require_paths = ["lib"] - spec.required_ruby_version = ">= 2.3.0" + 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 "simplecov" + spec.add_development_dependency "test-unit", ">= 3.4.8" end diff --git a/ruby/lib/csv/fields_converter.rb b/ruby/lib/csv/fields_converter.rb index a751c9ea1..b206118d9 100644 --- a/ruby/lib/csv/fields_converter.rb +++ b/ruby/lib/csv/fields_converter.rb @@ -16,7 +16,7 @@ def initialize(options={}) @empty_value = options[:empty_value] @empty_value_is_empty_string = (@empty_value == "") @accept_nil = options[:accept_nil] - @builtin_converters = options[:builtin_converters] + @builtin_converters_name = options[:builtin_converters_name] @need_static_convert = need_static_convert? end @@ -24,7 +24,7 @@ def add_converter(name=nil, &converter) if name.nil? # custom converter @converters << converter else # named converter - combo = @builtin_converters[name] + combo = builtin_converters[name] case combo when Array # combo converter combo.each do |sub_name| @@ -50,7 +50,7 @@ def convert(fields, headers, lineno) fields.collect.with_index do |field, index| if field.nil? field = @nil_value - elsif field.empty? + elsif field.is_a?(String) and field.empty? field = @empty_value unless @empty_value_is_empty_string end @converters.each do |converter| @@ -80,5 +80,9 @@ 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/ruby/lib/csv/input_record_separator.rb b/ruby/lib/csv/input_record_separator.rb new file mode 100644 index 000000000..bbf13479f --- /dev/null +++ b/ruby/lib/csv/input_record_separator.rb @@ -0,0 +1,31 @@ +require "English" +require "stringio" + +class CSV + module InputRecordSeparator + class << self + is_input_record_separator_deprecated = false + verbose, $VERBOSE = $VERBOSE, true + stderr, $stderr = $stderr, StringIO.new + input_record_separator = $INPUT_RECORD_SEPARATOR + begin + $INPUT_RECORD_SEPARATOR = "\r\n" + is_input_record_separator_deprecated = (not $stderr.string.empty?) + ensure + $INPUT_RECORD_SEPARATOR = input_record_separator + $stderr = stderr + $VERBOSE = verbose + end + + if is_input_record_separator_deprecated + def value + "\n" + end + else + def value + $INPUT_RECORD_SEPARATOR + end + end + end + end +end diff --git a/ruby/lib/csv/parser.rb b/ruby/lib/csv/parser.rb index 42145f892..7e943acf2 100644 --- a/ruby/lib/csv/parser.rb +++ b/ruby/lib/csv/parser.rb @@ -3,6 +3,7 @@ require "strscan" require_relative "delete_suffix" +require_relative "input_record_separator" require_relative "match_p" require_relative "row" require_relative "table" @@ -84,9 +85,10 @@ def keep_drop # If there is no more data (eos? = true), it returns "". # class InputsScanner - def initialize(inputs, encoding, chunk_size: 8192) + 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 = [] @@ -232,7 +234,7 @@ def read_chunk @last_scanner = @inputs.empty? true else - chunk = input.gets(nil, @chunk_size) + chunk = input.gets(@row_separator, @chunk_size) if chunk raise InvalidEncoding unless chunk.valid_encoding? @scanner = StringScanner.new(chunk) @@ -360,6 +362,7 @@ def prepare prepare_skip_lines prepare_strip prepare_separators + validate_strip_and_col_sep_options prepare_quoted prepare_unquoted prepare_line @@ -446,6 +449,7 @@ 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 @@ -460,6 +464,8 @@ def prepare_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 @@ -467,6 +473,7 @@ def prepare_strip @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 @@ -475,9 +482,9 @@ def prepare_strip begin StringScanner.new("x").scan("x") rescue TypeError - @@string_scanner_scan_accept_string = false + STRING_SCANNER_SCAN_ACCEPT_STRING = false else - @@string_scanner_scan_accept_string = true + STRING_SCANNER_SCAN_ACCEPT_STRING = true end def prepare_separators @@ -501,7 +508,7 @@ def prepare_separators @first_column_separators = Regexp.new(@escaped_first_column_separator + "+".encode(@encoding)) else - if @@string_scanner_scan_accept_string + if STRING_SCANNER_SCAN_ACCEPT_STRING @column_end = @column_separator else @column_end = Regexp.new(@escaped_column_separator) @@ -522,10 +529,32 @@ def prepare_separators @cr = "\r".encode(@encoding) @lf = "\n".encode(@encoding) - @cr_or_lf = Regexp.new("[\r\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 + @@ -561,9 +590,6 @@ def prepare_unquoted unless @liberal_parsing no_unquoted_values << @escaped_quote_character end - if @escaped_strip - no_unquoted_values << @escaped_strip - end @unquoted_value = Regexp.new("[^".encode(@encoding) + no_unquoted_values + "]+".encode(@encoding)) @@ -604,7 +630,7 @@ def resolve_row_separator(separator) # do nothing: ensure will set default end end - separator = $INPUT_RECORD_SEPARATOR if separator == :auto + separator = InputRecordSeparator.value if separator == :auto end separator.to_s.encode(@encoding) end @@ -707,7 +733,7 @@ def may_quoted? if SCANNER_TEST class UnoptimizedStringIO def initialize(string) - @io = StringIO.new(string) + @io = StringIO.new(string, "rb:#{string.encoding}") end def gets(*args) @@ -723,6 +749,8 @@ def eof? end end + SCANNER_TEST_CHUNK_SIZE = + Integer((ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] || "1"), 10) def build_scanner inputs = @samples.collect do |sample| UnoptimizedStringIO.new(sample) @@ -732,17 +760,20 @@ def build_scanner else inputs << @input end - chunk_size = ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] || "1" InputsScanner.new(inputs, @encoding, - chunk_size: Integer(chunk_size, 10)) + @row_separator, + chunk_size: SCANNER_TEST_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.respond_to?(:eof?) and @input.eof? + elsif @samples.size == 1 and + @input != ARGF and + @input.respond_to?(:eof?) and + @input.eof? string = @samples[0] end if string @@ -761,7 +792,7 @@ def build_scanner StringIO.new(sample) end inputs << @input - InputsScanner.new(inputs, @encoding) + InputsScanner.new(inputs, @encoding, @row_separator) end end end @@ -769,7 +800,7 @@ def build_scanner def skip_needless_lines return unless @skip_lines - while true + until @scanner.eos? @scanner.keep_start line = @scanner.scan_all(@not_line_end) || "".encode(@encoding) line << @row_separator if parse_row_end @@ -784,6 +815,7 @@ def skip_needless_lines end def skip_line?(line) + line = line.delete_suffix(@row_separator) case @skip_lines when String line.include?(@skip_lines) @@ -912,7 +944,7 @@ def parse_quotable_robust(&block) message = "Any value after quoted field isn't allowed" raise MalformedCSVError.new(message, @lineno) elsif @unquoted_column_value and - (new_line = @scanner.scan(@cr_or_lf)) + (new_line = @scanner.scan(@line_end)) ignore_broken_line message = "Unquoted fields do not allow new line " + "<#{new_line.inspect}>" @@ -921,7 +953,7 @@ def parse_quotable_robust(&block) ignore_broken_line message = "Illegal quoting" raise MalformedCSVError.new(message, @lineno) - elsif (new_line = @scanner.scan(@cr_or_lf)) + elsif (new_line = @scanner.scan(@line_end)) ignore_broken_line message = "New line must be <#{@row_separator.inspect}> " + "not <#{new_line.inspect}>" @@ -939,6 +971,7 @@ 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 @@ -986,6 +1019,9 @@ def parse_unquoted_column_value end end value.gsub!(@backslash_quote_character, @quote_character) if @backslash_quote + if @rstrip_value + value.gsub!(@rstrip_value, "") + end value end @@ -1083,7 +1119,7 @@ def strip_value(value) def ignore_broken_line @scanner.scan_all(@not_line_end) - @scanner.scan_all(@cr_or_lf) + @scanner.scan_all(@line_end) @lineno += 1 end diff --git a/ruby/lib/csv/row.rb b/ruby/lib/csv/row.rb index 4aa0f3091..0f465ea2a 100644 --- a/ruby/lib/csv/row.rb +++ b/ruby/lib/csv/row.rb @@ -49,42 +49,82 @@ def initialize(headers, fields, header_row = false) def_delegators :@row, :empty?, :length, :size def initialize_copy(other) - super - @row = @row.dup + super_return_value = super + @row = @row.collect(&:dup) + super_return_value end - # Returns +true+ if this is a header row. + # :call-seq: + # row.header_row? -> true or false + # + # Returns +true+ if this is a header row, +false+ otherwise. def header_row? @header_row end - # Returns +true+ if this is a field row. + # :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 - # Returns the headers of this row. + # :call-seq: + # row.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( header ) - # field( header, offset ) - # field( index ) + # field(index) + # field(header) + # field(header, offset) + # + # 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 + # + # --- # - # This method will return the field value by +header+ or +index+. If a field - # is not found, +nil+ is returned. + # 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" # - # When provided, +offset+ ensures that a header match occurs on or later - # than the +offset+ index. You can use this to find duplicate headers, - # without resorting to hard-coding exact indices. + # 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].send(finder, header_or_index) + pair = @row[minimum_index..-1].public_send(finder, header_or_index) # return the field if we have a pair if pair.nil? @@ -97,16 +137,45 @@ def field(header_or_index, minimum_index = 0) # # :call-seq: - # fetch( header ) - # fetch( header ) { |row| ... } - # fetch( header, default ) - # - # This method will fetch the field value by +header+. It has the same - # behavior as Hash#fetch: if there is a field with the given +header+, its - # value is returned. Otherwise, if a block is given, it is yielded the - # +header+ and its result is returned; if a +default+ is given as the - # second argument, it is returned; otherwise a KeyError is raised. - # + # fetch(header) + # fetch(header, default) + # fetch(header) {|row| ... } + # + # 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) @@ -123,7 +192,11 @@ def fetch(header, *varargs) end end - # Returns +true+ if there is a field with the given +header+. + # :call-seq: + # row.has_key?(header) + # + # Returns +true+ if there is a field with the given +header+, + # +false+ otherwise. def has_key?(header) !!@row.assoc(header) end @@ -134,17 +207,56 @@ def has_key?(header) # # :call-seq: - # []=( header, value ) - # []=( header, offset, value ) - # []=( index, value ) - # - # Looks up the field by the semantics described in CSV::Row.field() and - # assigns the +value+. - # - # Assigning past the end of the row with an index will set all pairs between - # to [nil, nil]. Assigning to an unused header appends the new - # pair. - # + # 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 @@ -167,17 +279,34 @@ def []=(*args) # # :call-seq: - # <<( field ) - # <<( header_and_field_array ) - # <<( header_and_field_hash ) - # - # If a two-element Array is provided, it is assumed to be a header and field - # and the pair is appended. A Hash works the same way with the key being - # the header and the value being the field. Anything else is assumed to be - # a lone field which is appended with a +nil+ header. - # - # This method returns the row for chaining. - # + # 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 @@ -190,13 +319,15 @@ def <<(arg) self # for chaining end - # - # A shortcut for appending multiple fields. Equivalent to: - # - # args.each { |arg| csv_row << arg } - # - # This method returns the row for chaining. - # + # :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 } @@ -205,14 +336,39 @@ def push(*args) # # :call-seq: - # delete( header ) - # delete( header, offset ) - # delete( index ) - # - # Removes a pair from the row by +header+ or +index+. The pair is - # located as described in CSV::Row.field(). The deleted pair is returned, - # or +nil+ if a pair could not be found. - # + # 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) @@ -223,15 +379,21 @@ def delete(header_or_index, minimum_index = 0) end end + # :call-seq: + # row.delete_if {|header, value| ... } -> self # - # The provided +block+ is passed a header and field for each pair in the row - # and expected to return +true+ or +false+, depending on whether the pair - # should be deleted. - # - # This method returns the row for chaining. + # Removes fields from +self+ as selected by the block; returns +self+. # - # If no block is given, an Enumerator is returned. + # 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? @@ -240,14 +402,52 @@ def delete_if(&block) self # for chaining end - # - # This method accepts any number of arguments which can be headers, indices, - # Ranges of either, or two-element Arrays containing a header and offset. - # Each argument will be replaced with a field lookup as described in - # CSV::Row.field(). - # - # If called with no arguments, all fields are returned. - # + # :call-seq: + # self.fields(*specifiers) + # + # 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) @@ -324,10 +524,21 @@ def ==(other) @row == other end - # - # Collapses the row into a simple Hash. Be warned that this discards field - # order and clobbers duplicate fields. - # + # :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| @@ -339,20 +550,35 @@ def to_h alias_method :to_ary, :to_a + # :call-seq: + # row.to_csv -> csv_string # - # Returns the row as a CSV String. Headers are not used. Equivalent to: - # - # csv_row.fields.to_csv( options ) - # + # 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+. # - # 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. + # The nested objects may be instances of various classes. + # See {Dig Methods}[https://docs.ruby-lang.org/en/master/doc/dig_methods_rdoc.html]. # + # 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? @@ -367,9 +593,17 @@ def dig(index_or_header, *indexes) end end - # - # A summary of fields, by header, in an ASCII compatible String. - # + # :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| diff --git a/ruby/lib/csv/table.rb b/ruby/lib/csv/table.rb index e6c1ee11f..1ce0dd6da 100644 --- a/ruby/lib/csv/table.rb +++ b/ruby/lib/csv/table.rb @@ -144,14 +144,91 @@ def headers end end - # - # In the default mixed mode, this method returns rows for index access and - # columns for header access. You can force the index association by first - # calling by_col!() or by_row!(). - # - # Columns are returned as an Array of values. Altering that Array has no - # effect on the table. - # + # :call-seq: + # table[n] -> row + # table[range] -> array_of_rows + # table[header] -> array_of_fields + # + # Returns data from the table; does not modify the table. + # + # --- + # + # The expression table[n], where +n+ is a non-negative \Integer, + # returns the +n+th row of the table, if that row exists, + # and if the access mode is :row or :col_or_row: + # 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-convertible object}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Integer-Convertible+Objects]. + # table.by_row! # => # + # # Raises TypeError (no implicit conversion of String into Integer): + # table['Name'] + # + # --- + # + # The expression table[range], where +range+ is a Range object, + # returns rows from the table, beginning at row range.first, + # if those rows exist, and if the access mode is :row or :col_or_row: + # 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.first 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 + # + # --- + # + # The expression table[header], where +header+ is a \String, + # returns column values (\Array of \Strings) if the column exists + # and if the access mode is :col or :col_or_row: + # 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))) @@ -210,15 +287,58 @@ def []=(index_or_header, value) end end - # - # The mixed mode default is to treat a list of indices as row access, - # returning the rows indicated. Anything else is considered columnar - # access. For columnar access, the return set has an Array for each row - # with the values indicated by the headers in each Array. You can force - # column or row mode using by_col!() or by_row!(). - # - # You cannot mix column and row access. - # + # :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| @@ -233,13 +353,20 @@ def values_at(*indices_or_headers) end end + # :call-seq: + # table << row_or_array -> self # - # Adds a new row to the bottom end of this table. You can provide an Array, - # which will be converted to a CSV::Row (inheriting the table's headers()), - # or a CSV::Row. - # - # This method returns the table for chaining. + # 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) @@ -251,23 +378,67 @@ def <<(row_or_array) end # - # A shortcut for appending multiple rows. Equivalent to: - # - # rows.each { |row| self << row } - # - # This method returns the table for chaining. + # :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. # - # Removes and returns the indicated columns or rows. In the default mixed - # mode indices refer to rows and everything else is assumed to be a column - # headers. Use by_col!() or by_row!() to force the lookup. + # 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+)" @@ -292,16 +463,32 @@ def delete(*indexes_or_headers) end end - # - # Removes any column or row for which the block returns +true+. In the - # default mixed mode or row mode, iteration is the standard row major - # walking of rows. In column mode, iteration will +yield+ two element - # tuples containing the column name and an Array of values for that column. - # - # This method returns the table for chaining. - # - # If no block is given, an Enumerator is returned. - # + # 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? @@ -319,15 +506,30 @@ def delete_if(&block) include Enumerable - # - # In the default mixed mode or row mode, iteration is the standard row major - # walking of rows. In column mode, iteration will +yield+ two element - # tuples containing the column name and an Array of values for that column. - # - # This method returns the table for chaining. - # - # If no block is given, an Enumerator is returned. - # + # 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? @@ -340,7 +542,24 @@ def each(&block) self # for chaining end - # Returns +true+ if all rows of this table ==() +other+'s rows. + # 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 diff --git a/ruby/lib/csv/version.rb b/ruby/lib/csv/version.rb index 072400fe0..d1d0dc0e0 100644 --- a/ruby/lib/csv/version.rb +++ b/ruby/lib/csv/version.rb @@ -2,5 +2,5 @@ class CSV # The version of the installed library. - VERSION = "3.1.2" + VERSION = "3.2.2" end diff --git a/ruby/lib/csv/writer.rb b/ruby/lib/csv/writer.rb index 9243d2364..4a9a35c5a 100644 --- a/ruby/lib/csv/writer.rb +++ b/ruby/lib/csv/writer.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative "input_record_separator" require_relative "match_p" require_relative "row" @@ -43,8 +44,10 @@ def <<(row) row = @fields_converter.convert(row, nil, lineno) if @fields_converter + i = -1 converted_row = row.collect do |field| - quote(field) + i += 1 + quote(field, i) end line = converted_row.join(@column_separator) + @row_separator if @output_encoding @@ -100,16 +103,53 @@ def prepare_header 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 = $INPUT_RECORD_SEPARATOR.encode(@encoding) + @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] + 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) + @@ -147,16 +187,18 @@ def quote_field(field) encoded_quote_character end - def quote(field) + 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 @quotable_pattern.match?(field) + if (@quote_empty and field.empty?) or (field.valid_encoding? and @quotable_pattern.match?(field)) quote_field(field) else field # unquoted field diff --git a/ruby/lib/debug.rb b/ruby/lib/debug.rb deleted file mode 100644 index 6f519c6c7..000000000 --- a/ruby/lib/debug.rb +++ /dev/null @@ -1,1106 +0,0 @@ -# frozen_string_literal: true -# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. -# Copyright (C) 2000 Information-technology Promotion Agency, Japan -# Copyright (C) 2000-2003 NAKAMURA, Hiroshi - -require 'continuation' - -require 'tracer' -require 'pp' - -class Tracer # :nodoc: - def Tracer.trace_func(*vars) - Single.trace_func(*vars) - end -end - -SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc: - -## -# This library provides debugging functionality to Ruby. -# -# To add a debugger to your code, start by requiring +debug+ in your -# program: -# -# def say(word) -# require 'debug' -# puts word -# end -# -# This will cause Ruby to interrupt execution and show a prompt when the +say+ -# method is run. -# -# Once you're inside the prompt, you can start debugging your program. -# -# (rdb:1) p word -# "hello" -# -# == Getting help -# -# You can get help at any time by pressing +h+. -# -# (rdb:1) h -# Debugger help v.-0.002b -# Commands -# b[reak] [file:|class:] -# b[reak] [class.] -# set breakpoint to some position -# wat[ch] set watchpoint to some expression -# cat[ch] (|off) set catchpoint to an exception -# b[reak] list breakpoints -# cat[ch] show catchpoint -# del[ete][ nnn] delete some or all breakpoints -# disp[lay] add expression into display expression list -# undisp[lay][ nnn] delete one particular or all display expressions -# c[ont] run until program ends or hit breakpoint -# s[tep][ nnn] step (into methods) one line or till line nnn -# n[ext][ nnn] go over one line or till line nnn -# w[here] display frames -# f[rame] alias for where -# l[ist][ (-|nn-mm)] list program, - lists backwards -# nn-mm lists given lines -# up[ nn] move to higher frame -# down[ nn] move to lower frame -# fin[ish] return to outer frame -# tr[ace] (on|off) set trace mode of current thread -# tr[ace] (on|off) all set trace mode of all threads -# q[uit] exit from debugger -# v[ar] g[lobal] show global variables -# v[ar] l[ocal] show local variables -# v[ar] i[nstance] show instance variables of object -# v[ar] c[onst] show constants of object -# m[ethod] i[nstance] show methods of object -# m[ethod] show instance methods of class or module -# th[read] l[ist] list all threads -# th[read] c[ur[rent]] show current thread -# th[read] [sw[itch]] switch thread context to nnn -# th[read] stop stop thread nnn -# th[read] resume resume thread nnn -# p expression evaluate expression and print its value -# h[elp] print this help -# evaluate -# -# == Usage -# -# The following is a list of common functionalities that the debugger -# provides. -# -# === Navigating through your code -# -# In general, a debugger is used to find bugs in your program, which -# often means pausing execution and inspecting variables at some point -# in time. -# -# Let's look at an example: -# -# def my_method(foo) -# require 'debug' -# foo = get_foo if foo.nil? -# raise if foo.nil? -# end -# -# When you run this program, the debugger will kick in just before the -# +foo+ assignment. -# -# (rdb:1) p foo -# nil -# -# In this example, it'd be interesting to move to the next line and -# inspect the value of +foo+ again. You can do that by pressing +n+: -# -# (rdb:1) n # goes to next line -# (rdb:1) p foo -# nil -# -# You now know that the original value of +foo+ was nil, and that it -# still was nil after calling +get_foo+. -# -# Other useful commands for navigating through your code are: -# -# +c+:: -# Runs the program until it either exists or encounters another breakpoint. -# You usually press +c+ when you are finished debugging your program and -# want to resume its execution. -# +s+:: -# Steps into method definition. In the previous example, +s+ would take you -# inside the method definition of +get_foo+. -# +r+:: -# Restart the program. -# +q+:: -# Quit the program. -# -# === Inspecting variables -# -# You can use the debugger to easily inspect both local and global variables. -# We've seen how to inspect local variables before: -# -# (rdb:1) p my_arg -# 42 -# -# You can also pretty print the result of variables or expressions: -# -# (rdb:1) pp %w{a very long long array containing many words} -# ["a", -# "very", -# "long", -# ... -# ] -# -# You can list all local variables with +v l+: -# -# (rdb:1) v l -# foo => "hello" -# -# Similarly, you can show all global variables with +v g+: -# -# (rdb:1) v g -# all global variables -# -# Finally, you can omit +p+ if you simply want to evaluate a variable or -# expression -# -# (rdb:1) 5**2 -# 25 -# -# === Going beyond basics -# -# Ruby Debug provides more advanced functionalities like switching -# between threads, setting breakpoints and watch expressions, and more. -# The full list of commands is available at any time by pressing +h+. -# -# == Staying out of trouble -# -# Make sure you remove every instance of +require 'debug'+ before -# shipping your code. Failing to do so may result in your program -# hanging unpredictably. -# -# Debug is not available in safe mode. - -class DEBUGGER__ - MUTEX = Thread::Mutex.new # :nodoc: - - class Context # :nodoc: - DEBUG_LAST_CMD = [] - - begin - require 'readline' - def readline(prompt, hist) - Readline::readline(prompt, hist) - end - rescue LoadError - def readline(prompt, hist) - STDOUT.print prompt - STDOUT.flush - line = STDIN.gets - exit unless line - line.chomp! - line - end - USE_READLINE = false - end - - def initialize - if Thread.current == Thread.main - @stop_next = 1 - else - @stop_next = 0 - end - @last_file = nil - @file = nil - @line = nil - @no_step = nil - @frames = [] - @finish_pos = 0 - @trace = false - @catch = "StandardError" - @suspend_next = false - end - - def stop_next(n=1) - @stop_next = n - end - - def set_suspend - @suspend_next = true - end - - def clear_suspend - @suspend_next = false - end - - def suspend_all - DEBUGGER__.suspend - end - - def resume_all - DEBUGGER__.resume - end - - def check_suspend - while MUTEX.synchronize { - if @suspend_next - DEBUGGER__.waiting.push Thread.current - @suspend_next = false - true - end - } - end - end - - def trace? - @trace - end - - def set_trace(arg) - @trace = arg - end - - def stdout - DEBUGGER__.stdout - end - - def break_points - DEBUGGER__.break_points - end - - def display - DEBUGGER__.display - end - - def context(th) - DEBUGGER__.context(th) - end - - def set_trace_all(arg) - DEBUGGER__.set_trace(arg) - end - - def set_last_thread(th) - DEBUGGER__.set_last_thread(th) - end - - def debug_eval(str, binding) - begin - eval(str, binding) - rescue StandardError, ScriptError => e - at = eval("caller(1)", binding) - stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '') - for i in at - stdout.printf "\tfrom %s\n", i - end - throw :debug_error - end - end - - def debug_silent_eval(str, binding) - begin - eval(str, binding) - rescue StandardError, ScriptError - nil - end - end - - def var_list(ary, binding) - ary.sort! - for v in ary - stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect - end - end - - def debug_variable_info(input, binding) - case input - when /^\s*g(?:lobal)?\s*$/ - var_list(global_variables, binding) - - when /^\s*l(?:ocal)?\s*$/ - var_list(eval("local_variables", binding), binding) - - when /^\s*i(?:nstance)?\s+/ - obj = debug_eval($', binding) - var_list(obj.instance_variables, obj.instance_eval{binding()}) - - when /^\s*c(?:onst(?:ant)?)?\s+/ - obj = debug_eval($', binding) - unless obj.kind_of? Module - stdout.print "Should be Class/Module: ", $', "\n" - else - var_list(obj.constants, obj.module_eval{binding()}) - end - end - end - - def debug_method_info(input, binding) - case input - when /^i(:?nstance)?\s+/ - obj = debug_eval($', binding) - - len = 0 - for v in obj.methods.sort - len += v.size + 1 - if len > 70 - len = v.size + 1 - stdout.print "\n" - end - stdout.print v, " " - end - stdout.print "\n" - - else - obj = debug_eval(input, binding) - unless obj.kind_of? Module - stdout.print "Should be Class/Module: ", input, "\n" - else - len = 0 - for v in obj.instance_methods(false).sort - len += v.size + 1 - if len > 70 - len = v.size + 1 - stdout.print "\n" - end - stdout.print v, " " - end - stdout.print "\n" - end - end - end - - def thnum - num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} - unless num - DEBUGGER__.make_thread_list - num = DEBUGGER__.instance_eval{@thread_list[Thread.current]} - end - num - end - - def debug_command(file, line, id, binding) - MUTEX.lock - unless defined?($debugger_restart) and $debugger_restart - callcc{|c| $debugger_restart = c} - end - set_last_thread(Thread.current) - frame_pos = 0 - binding_file = file - binding_line = line - previous_line = nil - if ENV['EMACS'] - stdout.printf "\032\032%s:%d:\n", binding_file, binding_line - else - stdout.printf "%s:%d:%s", binding_file, binding_line, - line_at(binding_file, binding_line) - end - @frames[0] = [binding, file, line, id] - display_expressions(binding) - prompt = true - while prompt and input = readline("(rdb:%d) "%thnum(), true) - catch(:debug_error) do - if input == "" - next unless DEBUG_LAST_CMD[0] - input = DEBUG_LAST_CMD[0] - stdout.print input, "\n" - else - DEBUG_LAST_CMD[0] = input - end - - case input - when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/ - if defined?( $2 ) - if $1 == 'on' - set_trace_all true - else - set_trace_all false - end - elsif defined?( $1 ) - if $1 == 'on' - set_trace true - else - set_trace false - end - end - if trace? - stdout.print "Trace on.\n" - else - stdout.print "Trace off.\n" - end - - when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/ - pos = $2 - if $1 - klass = debug_silent_eval($1, binding) - file = File.expand_path($1) - end - if pos =~ /^\d+$/ - pname = pos - pos = pos.to_i - else - pname = pos = pos.intern.id2name - end - break_points.push [true, 0, klass || file, pos] - stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname - - when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/ - pos = $2.intern.id2name - klass = debug_eval($1, binding) - break_points.push [true, 0, klass, pos] - stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos - - when /^\s*wat(?:ch)?\s+(.+)$/ - exp = $1 - break_points.push [true, 1, exp] - stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp - - when /^\s*b(?:reak)?$/ - if break_points.find{|b| b[1] == 0} - n = 1 - stdout.print "Breakpoints:\n" - break_points.each do |b| - if b[0] and b[1] == 0 - stdout.printf " %d %s:%s\n", n, b[2], b[3] - end - n += 1 - end - end - if break_points.find{|b| b[1] == 1} - n = 1 - stdout.print "\n" - stdout.print "Watchpoints:\n" - for b in break_points - if b[0] and b[1] == 1 - stdout.printf " %d %s\n", n, b[2] - end - n += 1 - end - end - if break_points.size == 0 - stdout.print "No breakpoints\n" - else - stdout.print "\n" - end - - when /^\s*del(?:ete)?(?:\s+(\d+))?$/ - pos = $1 - unless pos - input = readline("Clear all breakpoints? (y/n) ", false) - if input == "y" - for b in break_points - b[0] = false - end - end - else - pos = pos.to_i - if break_points[pos-1] - break_points[pos-1][0] = false - else - stdout.printf "Breakpoint %d is not defined\n", pos - end - end - - when /^\s*disp(?:lay)?\s+(.+)$/ - exp = $1 - display.push [true, exp] - stdout.printf "%d: ", display.size - display_expression(exp, binding) - - when /^\s*disp(?:lay)?$/ - display_expressions(binding) - - when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/ - pos = $1 - unless pos - input = readline("Clear all expressions? (y/n) ", false) - if input == "y" - for d in display - d[0] = false - end - end - else - pos = pos.to_i - if display[pos-1] - display[pos-1][0] = false - else - stdout.printf "Display expression %d is not defined\n", pos - end - end - - when /^\s*c(?:ont)?$/ - prompt = false - - when /^\s*s(?:tep)?(?:\s+(\d+))?$/ - if $1 - lev = $1.to_i - else - lev = 1 - end - @stop_next = lev - prompt = false - - when /^\s*n(?:ext)?(?:\s+(\d+))?$/ - if $1 - lev = $1.to_i - else - lev = 1 - end - @stop_next = lev - @no_step = @frames.size - frame_pos - prompt = false - - when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/ - display_frames(frame_pos) - - when /^\s*l(?:ist)?(?:\s+(.+))?$/ - if not $1 - b = previous_line ? previous_line + 10 : binding_line - 5 - e = b + 9 - elsif $1 == '-' - b = previous_line ? previous_line - 10 : binding_line - 5 - e = b + 9 - else - b, e = $1.split(/[-,]/) - if e - b = b.to_i - e = e.to_i - else - b = b.to_i - 5 - e = b + 9 - end - end - previous_line = b - display_list(b, e, binding_file, binding_line) - - when /^\s*up(?:\s+(\d+))?$/ - previous_line = nil - if $1 - lev = $1.to_i - else - lev = 1 - end - frame_pos += lev - if frame_pos >= @frames.size - frame_pos = @frames.size - 1 - stdout.print "At toplevel\n" - end - binding, binding_file, binding_line = @frames[frame_pos] - stdout.print format_frame(frame_pos) - - when /^\s*down(?:\s+(\d+))?$/ - previous_line = nil - if $1 - lev = $1.to_i - else - lev = 1 - end - frame_pos -= lev - if frame_pos < 0 - frame_pos = 0 - stdout.print "At stack bottom\n" - end - binding, binding_file, binding_line = @frames[frame_pos] - stdout.print format_frame(frame_pos) - - when /^\s*fin(?:ish)?$/ - if frame_pos == @frames.size - stdout.print "\"finish\" not meaningful in the outermost frame.\n" - else - @finish_pos = @frames.size - frame_pos - frame_pos = 0 - prompt = false - end - - when /^\s*cat(?:ch)?(?:\s+(.+))?$/ - if $1 - excn = $1 - if excn == 'off' - @catch = nil - stdout.print "Clear catchpoint.\n" - else - @catch = excn - stdout.printf "Set catchpoint %s.\n", @catch - end - else - if @catch - stdout.printf "Catchpoint %s.\n", @catch - else - stdout.print "No catchpoint.\n" - end - end - - when /^\s*q(?:uit)?$/ - input = readline("Really quit? (y/n) ", false) - if input == "y" - exit! # exit -> exit!: No graceful way to stop threads... - end - - when /^\s*v(?:ar)?\s+/ - debug_variable_info($', binding) - - when /^\s*m(?:ethod)?\s+/ - debug_method_info($', binding) - - when /^\s*th(?:read)?\s+/ - if DEBUGGER__.debug_thread_info($', binding) == :cont - prompt = false - end - - when /^\s*pp\s+/ - PP.pp(debug_eval($', binding), stdout) - - when /^\s*p\s+/ - stdout.printf "%s\n", debug_eval($', binding).inspect - - when /^\s*r(?:estart)?$/ - $debugger_restart.call - - when /^\s*h(?:elp)?$/ - debug_print_help() - - else - v = debug_eval(input, binding) - stdout.printf "%s\n", v.inspect - end - end - end - MUTEX.unlock - resume_all - end - - def debug_print_help - stdout.print < - b[reak] [class.] - set breakpoint to some position - wat[ch] set watchpoint to some expression - cat[ch] (|off) set catchpoint to an exception - b[reak] list breakpoints - cat[ch] show catchpoint - del[ete][ nnn] delete some or all breakpoints - disp[lay] add expression into display expression list - undisp[lay][ nnn] delete one particular or all display expressions - c[ont] run until program ends or hit breakpoint - s[tep][ nnn] step (into methods) one line or till line nnn - n[ext][ nnn] go over one line or till line nnn - w[here] display frames - f[rame] alias for where - l[ist][ (-|nn-mm)] list program, - lists backwards - nn-mm lists given lines - up[ nn] move to higher frame - down[ nn] move to lower frame - fin[ish] return to outer frame - tr[ace] (on|off) set trace mode of current thread - tr[ace] (on|off) all set trace mode of all threads - q[uit] exit from debugger - v[ar] g[lobal] show global variables - v[ar] l[ocal] show local variables - v[ar] i[nstance] show instance variables of object - v[ar] c[onst] show constants of object - m[ethod] i[nstance] show methods of object - m[ethod] show instance methods of class or module - th[read] l[ist] list all threads - th[read] c[ur[rent]] show current thread - th[read] [sw[itch]] switch thread context to nnn - th[read] stop stop thread nnn - th[read] resume resume thread nnn - pp expression evaluate expression and pretty_print its value - p expression evaluate expression and print its value - r[estart] restart program - h[elp] print this help - evaluate -EOHELP - end - - def display_expressions(binding) - n = 1 - for d in display - if d[0] - stdout.printf "%d: ", n - display_expression(d[1], binding) - end - n += 1 - end - end - - def display_expression(exp, binding) - stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s - end - - def frame_set_pos(file, line) - if @frames[0] - @frames[0][1] = file - @frames[0][2] = line - end - end - - def display_frames(pos) - 0.upto(@frames.size - 1) do |n| - if n == pos - stdout.print "--> " - else - stdout.print " " - end - stdout.print format_frame(n) - end - end - - def format_frame(pos) - _, file, line, id = @frames[pos] - sprintf "#%d %s:%s%s\n", pos + 1, file, line, - (id ? ":in `#{id.id2name}'" : "") - end - - def script_lines(file, line) - unless (lines = SCRIPT_LINES__[file]) and lines != true - Tracer::Single.get_line(file, line) if File.exist?(file) - lines = SCRIPT_LINES__[file] - lines = nil if lines == true - end - lines - end - - def display_list(b, e, file, line) - if lines = script_lines(file, line) - stdout.printf "[%d, %d] in %s\n", b, e, file - b.upto(e) do |n| - if n > 0 && lines[n-1] - if n == line - stdout.printf "=> %d %s\n", n, lines[n-1].chomp - else - stdout.printf " %d %s\n", n, lines[n-1].chomp - end - end - end - else - stdout.printf "No sourcefile available for %s\n", file - end - end - - def line_at(file, line) - lines = script_lines(file, line) - if lines and line = lines[line-1] - return line - end - return "\n" - end - - def debug_funcname(id) - if id.nil? - "toplevel" - else - id.id2name - end - end - - def check_break_points(file, klass, pos, binding, id) - return false if break_points.empty? - n = 1 - for b in break_points - if b[0] # valid - if b[1] == 0 # breakpoint - if (b[2] == file and b[3] == pos) or - (klass and b[2] == klass and b[3] == pos) - stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos - return true - end - elsif b[1] == 1 # watchpoint - if debug_silent_eval(b[2], binding) - stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos - return true - end - end - end - n += 1 - end - return false - end - - def excn_handle(file, line, id, binding) - if $!.class <= SystemExit - set_trace_func nil - exit - end - - if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch }) - stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class - fs = @frames.size - tb = caller(0)[-fs..-1] - if tb - for i in tb - stdout.printf "\tfrom %s\n", i - end - end - suspend_all - debug_command(file, line, id, binding) - end - end - - def trace_func(event, file, line, id, binding, klass) - Tracer.trace_func(event, file, line, id, binding, klass) if trace? - context(Thread.current).check_suspend - @file = file - @line = line - case event - when 'line' - frame_set_pos(file, line) - if !@no_step or @frames.size == @no_step - @stop_next -= 1 - @stop_next = -1 if @stop_next < 0 - elsif @frames.size < @no_step - @stop_next = 0 # break here before leaving... - else - # nothing to do. skipped. - end - if @stop_next == 0 or check_break_points(file, nil, line, binding, id) - @no_step = nil - suspend_all - debug_command(file, line, id, binding) - end - - when 'call' - @frames.unshift [binding, file, line, id] - if check_break_points(file, klass, id.id2name, binding, id) - suspend_all - debug_command(file, line, id, binding) - end - - when 'c-call' - frame_set_pos(file, line) - - when 'class' - @frames.unshift [binding, file, line, id] - - when 'return', 'end' - if @frames.size == @finish_pos - @stop_next = 1 - @finish_pos = 0 - end - @frames.shift - - when 'raise' - excn_handle(file, line, id, binding) - - end - @last_file = file - end - end - - trap("INT") { DEBUGGER__.interrupt } - @last_thread = Thread::main - @max_thread = 1 - @thread_list = {Thread::main => 1} - @break_points = [] - @display = [] - @waiting = [] - @stdout = STDOUT - - class << DEBUGGER__ - # Returns the IO used as stdout. Defaults to STDOUT - def stdout - @stdout - end - - # Sets the IO used as stdout. Defaults to STDOUT - def stdout=(s) - @stdout = s - end - - # Returns the display expression list - # - # See DEBUGGER__ for more usage - def display - @display - end - - # Returns the list of break points where execution will be stopped. - # - # See DEBUGGER__ for more usage - def break_points - @break_points - end - - # Returns the list of waiting threads. - # - # When stepping through the traces of a function, thread gets suspended, to - # be resumed later. - def waiting - @waiting - end - - def set_trace( arg ) - MUTEX.synchronize do - make_thread_list - for th, in @thread_list - context(th).set_trace arg - end - end - arg - end - - def set_last_thread(th) - @last_thread = th - end - - def suspend - MUTEX.synchronize do - make_thread_list - for th, in @thread_list - next if th == Thread.current - context(th).set_suspend - end - end - # Schedule other threads to suspend as soon as possible. - Thread.pass - end - - def resume - MUTEX.synchronize do - make_thread_list - @thread_list.each do |th,| - next if th == Thread.current - context(th).clear_suspend - end - waiting.each do |th| - th.run - end - waiting.clear - end - # Schedule other threads to restart as soon as possible. - Thread.pass - end - - def context(thread=Thread.current) - c = thread[:__debugger_data__] - unless c - thread[:__debugger_data__] = c = Context.new - end - c - end - - def interrupt - context(@last_thread).stop_next - end - - def get_thread(num) - th = @thread_list.key(num) - unless th - @stdout.print "No thread ##{num}\n" - throw :debug_error - end - th - end - - def thread_list(num) - th = get_thread(num) - if th == Thread.current - @stdout.print "+" - else - @stdout.print " " - end - @stdout.printf "%d ", num - @stdout.print th.inspect, "\t" - file = context(th).instance_eval{@file} - if file - @stdout.print file,":",context(th).instance_eval{@line} - end - @stdout.print "\n" - end - - # Prints all threads in @thread_list to @stdout. Returns a sorted array of - # values from the @thread_list hash. - # - # While in the debugger you can list all of - # the threads with: DEBUGGER__.thread_list_all - # - # (rdb:1) DEBUGGER__.thread_list_all - # +1 # debug_me.rb.rb:3 - # 2 # - # 3 # - # [1, 2, 3] - # - # Your current thread is indicated by a + - # - # Additionally you can list all threads with th l - # - # (rdb:1) th l - # +1 # debug_me.rb:3 - # 2 # debug_me.rb:3 - # 3 # debug_me.rb:3 - # - # See DEBUGGER__ for more usage. - - def thread_list_all - for th in @thread_list.values.sort - thread_list(th) - end - end - - def make_thread_list - hash = {} - for th in Thread::list - if @thread_list.key? th - hash[th] = @thread_list[th] - else - @max_thread += 1 - hash[th] = @max_thread - end - end - @thread_list = hash - end - - def debug_thread_info(input, binding) - case input - when /^l(?:ist)?/ - make_thread_list - thread_list_all - - when /^c(?:ur(?:rent)?)?$/ - make_thread_list - thread_list(@thread_list[Thread.current]) - - when /^(?:sw(?:itch)?\s+)?(\d+)/ - make_thread_list - th = get_thread($1.to_i) - if th == Thread.current - @stdout.print "It's the current thread.\n" - else - thread_list(@thread_list[th]) - context(th).stop_next - th.run - return :cont - end - - when /^stop\s+(\d+)/ - make_thread_list - th = get_thread($1.to_i) - if th == Thread.current - @stdout.print "It's the current thread.\n" - elsif th.stop? - @stdout.print "Already stopped.\n" - else - thread_list(@thread_list[th]) - context(th).suspend - end - - when /^resume\s+(\d+)/ - make_thread_list - th = get_thread($1.to_i) - if th == Thread.current - @stdout.print "It's the current thread.\n" - elsif !th.stop? - @stdout.print "Already running." - else - thread_list(@thread_list[th]) - th.run - end - end - end - end - - stdout.printf "Debug.rb\n" - stdout.printf "Emacs support available.\n\n" - RubyVM::InstructionSequence.compile_option = { - trace_instruction: true - } - set_trace_func proc { |event, file, line, id, binding, klass, *rest| - DEBUGGER__.context.trace_func event, file, line, id, binding, klass - } -end diff --git a/ruby/lib/delegate.rb b/ruby/lib/delegate.rb index 1587c7e3b..a5ae605e9 100644 --- a/ruby/lib/delegate.rb +++ b/ruby/lib/delegate.rb @@ -21,6 +21,8 @@ # SimpleDelegator's implementation serves as a nice example of the use of # Delegator: # +# require 'delegate' +# # class SimpleDelegator < Delegator # def __getobj__ # @delegate_sd_obj # return object we are delegating to, required @@ -37,6 +39,8 @@ # Be advised, RDoc will not detect delegated methods. # class Delegator < BasicObject + VERSION = "0.2.0" + kernel = ::Kernel.dup kernel.class_eval do alias __raise__ raise @@ -218,8 +222,8 @@ def marshal_load(data) end end - def initialize_clone(obj) # :nodoc: - self.__setobj__(obj.__getobj__.clone) + def initialize_clone(obj, freeze: nil) # :nodoc: + self.__setobj__(obj.__getobj__.clone(freeze: freeze)) end def initialize_dup(obj) # :nodoc: self.__setobj__(obj.__getobj__.dup) @@ -253,6 +257,8 @@ def self.public_api # :nodoc: # end # end # +# require 'delegate' +# # class UserDecorator < SimpleDelegator # def birth_year # born_on.year @@ -418,6 +424,21 @@ def __setobj__(obj) # :nodoc: klass.define_singleton_method :protected_instance_methods do |all=true| super(all) | superclass.protected_instance_methods end + klass.define_singleton_method :instance_methods do |all=true| + super(all) | superclass.instance_methods + end + klass.define_singleton_method :public_instance_method do |name| + super(name) + rescue NameError + raise unless self.public_instance_methods.include?(name) + superclass.public_instance_method(name) + end + klass.define_singleton_method :instance_method do |name| + super(name) + rescue NameError + raise unless self.instance_methods.include?(name) + superclass.instance_method(name) + end klass.module_eval(&block) if block return klass end diff --git a/ruby/lib/delegate/delegate.gemspec b/ruby/lib/delegate/delegate.gemspec index 268cc5a81..1cfacfeb2 100644 --- a/ruby/lib/delegate/delegate.gemspec +++ b/ruby/lib/delegate/delegate.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/delegate/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "delegate" - spec.version = Delegator::VERSION + spec.name = name + spec.version = version spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{Provides three abilities to delegate method calls to an object.} spec.description = %q{Provides three abilities to delegate method calls to an object.} spec.homepage = "https://github.com/ruby/delegate" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage @@ -21,7 +24,6 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z 2>/dev/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"] + spec.required_ruby_version = '>= 2.7' end diff --git a/ruby/lib/delegate/version.rb b/ruby/lib/delegate/version.rb deleted file mode 100644 index 456e8f772..000000000 --- a/ruby/lib/delegate/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Delegator - VERSION = "0.1.0" -end diff --git a/ruby/lib/did_you_mean.rb b/ruby/lib/did_you_mean.rb index b8f92579c..2df238da0 100644 --- a/ruby/lib/did_you_mean.rb +++ b/ruby/lib/did_you_mean.rb @@ -6,7 +6,9 @@ require_relative 'did_you_mean/spell_checkers/method_name_checker' require_relative 'did_you_mean/spell_checkers/key_error_checker' require_relative 'did_you_mean/spell_checkers/null_checker' -require_relative 'did_you_mean/formatters/plain_formatter' +require_relative 'did_you_mean/spell_checkers/require_path_checker' +require_relative 'did_you_mean/spell_checkers/pattern_key_name_checker' +require_relative 'did_you_mean/formatter' require_relative 'did_you_mean/tree_spell_checker' # The +DidYouMean+ gem adds functionality to suggest possible method/class @@ -84,27 +86,70 @@ # module DidYouMean # Map of error types and spell checker objects. - SPELL_CHECKERS = Hash.new(NullChecker) + @spell_checkers = Hash.new(NullChecker) + + # Returns a sharable hash map of error types and spell checker objects. + def self.spell_checkers + @spell_checkers + end # Adds +DidYouMean+ functionality to an error using a given spell checker def self.correct_error(error_class, spell_checker) - SPELL_CHECKERS[error_class.name] = spell_checker - error_class.prepend(Correctable) unless error_class < Correctable + if defined?(Ractor) + new_mapping = { **@spell_checkers, error_class.to_s => spell_checker } + new_mapping.default = NullChecker + + @spell_checkers = Ractor.make_shareable(new_mapping) + else + spell_checkers[error_class.to_s] = spell_checker + end + + error_class.prepend(Correctable) if error_class.is_a?(Class) && !(error_class < Correctable) end correct_error NameError, NameErrorCheckers correct_error KeyError, KeyErrorChecker correct_error NoMethodError, MethodNameChecker + correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0' + correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError) + + # TODO: Remove on 3.3: + 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 - # Returns the currenctly set formatter. By default, it is set to +DidYouMean::Formatter+. + 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 3.3: + 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 - @@formatter + if defined?(Ractor) + Ractor.current[:__did_you_mean_formatter__] || Formatter + else + Formatter + end end # Updates the primary formatter used to format the suggestions. def self.formatter=(formatter) - @@formatter = formatter + if defined?(Ractor) + Ractor.current[:__did_you_mean_formatter__] = formatter + end end - - self.formatter = PlainFormatter.new end diff --git a/ruby/lib/did_you_mean/core_ext/name_error.rb b/ruby/lib/did_you_mean/core_ext/name_error.rb index 77dcd520c..eb3ef117a 100644 --- a/ruby/lib/did_you_mean/core_ext/name_error.rb +++ b/ruby/lib/did_you_mean/core_ext/name_error.rb @@ -1,14 +1,21 @@ module DidYouMean module Correctable + SKIP_TO_S_FOR_SUPER_LOOKUP = true + private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP + def original_message - method(:to_s).super_method.call + meth = method(:to_s) + while meth.owner.const_defined?(:SKIP_TO_S_FOR_SUPER_LOOKUP) + meth = meth.super_method + end + meth.call end def to_s msg = super.dup suggestion = DidYouMean.formatter.message_for(corrections) - msg << suggestion if !msg.end_with?(suggestion) + msg << suggestion if !msg.include?(suggestion) msg rescue super @@ -19,7 +26,7 @@ def corrections end def spell_checker - SPELL_CHECKERS[self.class.to_s].new(self) + DidYouMean.spell_checkers[self.class.to_s].new(self) end end end diff --git a/ruby/lib/did_you_mean/experimental/initializer_name_correction.rb b/ruby/lib/did_you_mean/experimental/initializer_name_correction.rb deleted file mode 100644 index b59c98e77..000000000 --- a/ruby/lib/did_you_mean/experimental/initializer_name_correction.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen-string-literal: true - -require_relative '../levenshtein' - -module DidYouMean - module Experimental - module InitializerNameCorrection - def method_added(name) - super - - distance = Levenshtein.distance(name.to_s, 'initialize') - if distance != 0 && distance <= 2 - warn "warning: #{name} might be misspelled, perhaps you meant initialize?" - end - end - end - - ::Class.prepend(InitializerNameCorrection) - end -end diff --git a/ruby/lib/did_you_mean/experimental/ivar_name_correction.rb b/ruby/lib/did_you_mean/experimental/ivar_name_correction.rb deleted file mode 100644 index 322e422c6..000000000 --- a/ruby/lib/did_you_mean/experimental/ivar_name_correction.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen-string-literal: true - -require_relative '../../did_you_mean' - -module DidYouMean - module Experimental #:nodoc: - class IvarNameCheckerBuilder #:nodoc: - attr_reader :original_checker - - def initialize(original_checker) #:nodoc: - @original_checker = original_checker - end - - def new(no_method_error) #:nodoc: - IvarNameChecker.new(no_method_error, original_checker: @original_checker) - end - end - - class IvarNameChecker #:nodoc: - REPLS = { - "(irb)" => -> { Readline::HISTORY.to_a.last } - } - - TRACE = TracePoint.trace(:raise) do |tp| - e = tp.raised_exception - - if SPELL_CHECKERS.include?(e.class.to_s) && !e.instance_variable_defined?(:@frame_binding) - e.instance_variable_set(:@frame_binding, tp.binding) - end - end - - attr_reader :original_checker - - def initialize(no_method_error, original_checker: ) - @original_checker = original_checker.new(no_method_error) - - @location = no_method_error.backtrace_locations.first - @ivar_names = no_method_error.frame_binding.receiver.instance_variables - - no_method_error.remove_instance_variable(:@frame_binding) - end - - def corrections - original_checker.corrections + ivar_name_corrections - end - - def ivar_name_corrections - @ivar_name_corrections ||= SpellChecker.new(dictionary: @ivar_names).correct(receiver_name.to_s) - end - - private - - def receiver_name - return unless @original_checker.receiver.nil? - - abs_path = @location.absolute_path - lineno = @location.lineno - - /@(\w+)*\.#{@original_checker.method_name}/ =~ line(abs_path, lineno).to_s && $1 - end - - def line(abs_path, lineno) - if REPLS[abs_path] - REPLS[abs_path].call - elsif File.exist?(abs_path) - File.open(abs_path) do |file| - file.detect { file.lineno == lineno } - end - end - end - end - end - - NameError.send(:attr, :frame_binding) - SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameCheckerBuilder.new(SPELL_CHECKERS['NoMethodError']) -end diff --git a/ruby/lib/did_you_mean/formatter.rb b/ruby/lib/did_you_mean/formatter.rb new file mode 100644 index 000000000..c43748f70 --- /dev/null +++ b/ruby/lib/did_you_mean/formatter.rb @@ -0,0 +1,44 @@ +# frozen-string-literal: true + +module DidYouMean + # The +DidYouMean::Formatter+ is the basic, default formatter for the + # gem. The formatter responds to the +message_for+ method and it returns a + # human readable string. + class Formatter + + # Returns a human readable string that contains +corrections+. This + # formatter is designed to be less verbose to not take too much screen + # space while being helpful enough to the user. + # + # @example + # + # formatter = DidYouMean::Formatter.new + # + # # displays suggestions in two lines with the leading empty line + # puts formatter.message_for(["methods", "method"]) + # + # Did you mean? methods + # method + # # => nil + # + # # displays an empty line + # puts formatter.message_for([]) + # + # # => nil + # + def self.message_for(corrections) + corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" + end + + def message_for(corrections) + warn "The instance method #message_for has been deprecated. Please use the class method " \ + "DidYouMean::Formatter.message_for(...) instead." + + self.class.message_for(corrections) + end + end + + PlainFormatter = Formatter + + deprecate_constant :PlainFormatter +end diff --git a/ruby/lib/did_you_mean/formatters/plain_formatter.rb b/ruby/lib/did_you_mean/formatters/plain_formatter.rb index e2d995f58..d669588e0 100644 --- a/ruby/lib/did_you_mean/formatters/plain_formatter.rb +++ b/ruby/lib/did_you_mean/formatters/plain_formatter.rb @@ -1,33 +1,4 @@ -# frozen-string-literal: true +require_relative '../formatter' -module DidYouMean - # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the - # gem. The formatter responds to the +message_for+ method and it returns a - # human readable string. - class PlainFormatter - - # Returns a human readable string that contains +corrections+. This - # formatter is designed to be less verbose to not take too much screen - # space while being helpful enough to the user. - # - # @example - # - # formatter = DidYouMean::PlainFormatter.new - # - # # displays suggestions in two lines with the leading empty line - # puts formatter.message_for(["methods", "method"]) - # - # Did you mean? methods - # method - # # => nil - # - # # displays an empty line - # puts formatter.message_for([]) - # - # # => nil - # - def message_for(corrections) - corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" - end - end -end +warn "`require 'did_you_mean/formatters/plain_formatter'` is deprecated. Please `require 'did_you_mean/formatter'` " \ + "instead." diff --git a/ruby/lib/did_you_mean/formatters/verbose_formatter.rb b/ruby/lib/did_you_mean/formatters/verbose_formatter.rb index b8fe214d5..8ee98fa07 100644 --- a/ruby/lib/did_you_mean/formatters/verbose_formatter.rb +++ b/ruby/lib/did_you_mean/formatters/verbose_formatter.rb @@ -1,49 +1,9 @@ -# frozen-string-literal: true - -module DidYouMean - # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the - # suggestion stand out more in the error message. - # - # In order to activate the verbose formatter, - # - # @example - # - # OBject - # # => NameError: uninitialized constant OBject - # # Did you mean? Object - # - # require 'did_you_mean/verbose' - # - # OBject - # # => NameError: uninitialized constant OBject - # # - # # Did you mean? Object - # # - # - class VerboseFormatter +warn "`require 'did_you_mean/formatters/verbose_formatter'` is deprecated and falls back to the default formatter. " - # Returns a human readable string that contains +corrections+. This - # formatter is designed to be less verbose to not take too much screen - # space while being helpful enough to the user. - # - # @example - # - # formatter = DidYouMean::PlainFormatter.new - # - # puts formatter.message_for(["methods", "method"]) - # - # - # Did you mean? methods - # method - # - # # => nil - # - def message_for(corrections) - return "" if corrections.empty? +require_relative '../formatter' - output = "\n\n Did you mean? ".dup - output << corrections.join("\n ") - output << "\n " - end - end +# frozen-string-literal: true +module DidYouMean + # For compatibility: + VerboseFormatter = Formatter end diff --git a/ruby/lib/did_you_mean/spell_checker.rb b/ruby/lib/did_you_mean/spell_checker.rb index e5106abba..37da2fc7a 100644 --- a/ruby/lib/did_you_mean/spell_checker.rb +++ b/ruby/lib/did_you_mean/spell_checker.rb @@ -10,25 +10,25 @@ def initialize(dictionary:) end def correct(input) - input = normalize(input) - threshold = input.length > 3 ? 0.834 : 0.77 + normalized_input = normalize(input) + threshold = normalized_input.length > 3 ? 0.834 : 0.77 - words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), input) >= threshold } - words.reject! { |word| input == word.to_s } - words.sort_by! { |word| JaroWinkler.distance(word.to_s, input) } + words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), normalized_input) >= threshold } + words.reject! { |word| input.to_s == word.to_s } + words.sort_by! { |word| JaroWinkler.distance(word.to_s, normalized_input) } words.reverse! # Correct mistypes - threshold = (input.length * 0.25).ceil - corrections = words.select { |c| Levenshtein.distance(normalize(c), input) <= threshold } + threshold = (normalized_input.length * 0.25).ceil + corrections = words.select { |c| Levenshtein.distance(normalize(c), normalized_input) <= threshold } # Correct misspells if corrections.empty? corrections = words.select do |word| word = normalize(word) - length = input.length < word.length ? input.length : word.length + length = normalized_input.length < word.length ? normalized_input.length : word.length - Levenshtein.distance(word, input) < length + Levenshtein.distance(word, normalized_input) < length end.first(1) end diff --git a/ruby/lib/did_you_mean/spell_checkers/method_name_checker.rb b/ruby/lib/did_you_mean/spell_checkers/method_name_checker.rb index 3a38245f0..d8ebaa461 100644 --- a/ruby/lib/did_you_mean/spell_checkers/method_name_checker.rb +++ b/ruby/lib/did_you_mean/spell_checkers/method_name_checker.rb @@ -6,6 +6,7 @@ class MethodNameChecker NAMES_TO_EXCLUDE = { NilClass => nil.methods } NAMES_TO_EXCLUDE.default = [] + Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor) # +MethodNameChecker::RB_RESERVED_WORDS+ is the list of reserved words in # Ruby that take an argument. Unlike @@ -36,6 +37,8 @@ class MethodNameChecker yield ) + Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor) + def initialize(exception) @method_name = exception.name @receiver = exception.receiver @@ -43,7 +46,12 @@ def initialize(exception) end def corrections - @corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) - names_to_exclude + @corrections ||= begin + dictionary = method_names + dictionary = RB_RESERVED_WORDS + dictionary if @private_call + + SpellChecker.new(dictionary: dictionary).correct(method_name) - names_to_exclude + end end def method_names diff --git a/ruby/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb b/ruby/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb index 3e51b4fa3..36d00349c 100644 --- a/ruby/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb +++ b/ruby/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb @@ -8,6 +8,7 @@ class VariableNameChecker NAMES_TO_EXCLUDE = { 'foo' => [:fork, :for] } NAMES_TO_EXCLUDE.default = [] + Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor) # +VariableNameChecker::RB_RESERVED_WORDS+ is the list of all reserved # words in Ruby. They could be declared like methods are, and a typo would @@ -62,6 +63,8 @@ class VariableNameChecker __ENCODING__ ) + Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor) + def initialize(exception) @name = exception.name.to_s.tr("@", "") @lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : [] diff --git a/ruby/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/ruby/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb new file mode 100644 index 000000000..ed263c8f9 --- /dev/null +++ b/ruby/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb @@ -0,0 +1,20 @@ +require_relative "../spell_checker" + +module DidYouMean + class PatternKeyNameChecker + def initialize(no_matching_pattern_key_error) + @key = no_matching_pattern_key_error.key + @keys = no_matching_pattern_key_error.matchee.keys + end + + def corrections + @corrections ||= exact_matches.empty? ? SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) : exact_matches + end + + private + + def exact_matches + @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect) + end + end +end diff --git a/ruby/lib/did_you_mean/spell_checkers/require_path_checker.rb b/ruby/lib/did_you_mean/spell_checkers/require_path_checker.rb new file mode 100644 index 000000000..586ced37d --- /dev/null +++ b/ruby/lib/did_you_mean/spell_checkers/require_path_checker.rb @@ -0,0 +1,39 @@ +# frozen-string-literal: true + +require_relative "../spell_checker" +require_relative "../tree_spell_checker" +require "rbconfig" + +module DidYouMean + class RequirePathChecker + attr_reader :path + + INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze + Ractor.make_shareable(INITIAL_LOAD_PATH) if defined?(Ractor) + + ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}" + Ractor.make_shareable(ENV_SPECIFIC_EXT) if defined?(Ractor) + + private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT + + def self.requireables + @requireables ||= INITIAL_LOAD_PATH + .flat_map {|path| Dir.glob("**/???*{.rb,#{ENV_SPECIFIC_EXT}}", base: path) } + .map {|path| path.chomp!(".rb") || path.chomp!(ENV_SPECIFIC_EXT) } + end + + def initialize(exception) + @path = exception.path + end + + def corrections + @corrections ||= begin + threshold = path.size * 2 + dictionary = self.class.requireables.reject {|str| str.size >= threshold } + spell_checker = path.include?("/") ? TreeSpellChecker : SpellChecker + + spell_checker.new(dictionary: dictionary).correct(path).uniq + end + end + end +end diff --git a/ruby/lib/did_you_mean/tree_spell_checker.rb b/ruby/lib/did_you_mean/tree_spell_checker.rb index 6a5b48541..799f07fcf 100644 --- a/ruby/lib/did_you_mean/tree_spell_checker.rb +++ b/ruby/lib/did_you_mean/tree_spell_checker.rb @@ -1,137 +1,109 @@ +# frozen_string_literal: true + module DidYouMean # spell checker for a dictionary that has a tree # structure, see doc/tree_spell_checker_api.md class TreeSpellChecker - attr_reader :dictionary, :dimensions, :separator, :augment + attr_reader :dictionary, :separator, :augment def initialize(dictionary:, separator: '/', augment: nil) @dictionary = dictionary @separator = separator @augment = augment - @dimensions = parse_dimensions end def correct(input) - plausibles = plausible_dimensions input - return no_idea(input) if plausibles.empty? - suggestions = find_suggestions input, plausibles - return no_idea(input) if suggestions.empty? - suggestions - end + plausibles = plausible_dimensions(input) + return fall_back_to_normal_spell_check(input) if plausibles.empty? - private + suggestions = find_suggestions(input, plausibles) + return fall_back_to_normal_spell_check(input) if suggestions.empty? - def parse_dimensions - ParseDimensions.new(dictionary, separator).call + suggestions end - def find_suggestions(input, plausibles) - states = plausibles[0].product(*plausibles[1..-1]) - paths = possible_paths states - leaf = input.split(separator).last - ideas = find_ideas(paths, leaf) - ideas.compact.flatten + def dictionary_without_leaves + @dictionary_without_leaves ||= dictionary.map { |word| word.split(separator)[0..-2] }.uniq end - def no_idea(input) - return [] unless augment - ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input) + def tree_depth + @tree_depth ||= dictionary_without_leaves.max { |a, b| a.size <=> b.size }.size end - def find_ideas(paths, leaf) - paths.map do |path| - names = find_leaves(path) - ideas = CorrectElement.new.call names, leaf - ideas_to_paths ideas, leaf, names, path - end + def dimensions + @dimensions ||= tree_depth.times.map do |index| + dictionary_without_leaves.map { |element| element[index] }.compact.uniq + end end - def ideas_to_paths(ideas, leaf, names, path) - return nil if ideas.empty? - return [path + separator + leaf] if names.include? leaf - ideas.map { |str| path + separator + str } + def find_leaves(path) + path_with_separator = "#{path}#{separator}" + + dictionary + .select {|str| str.include?(path_with_separator) } + .map {|str| str.gsub(path_with_separator, '') } end - def find_leaves(path) - dictionary.map do |str| - next unless str.include? "#{path}#{separator}" - str.gsub("#{path}#{separator}", '') - end.compact + def plausible_dimensions(input) + input.split(separator)[0..-2] + .map + .with_index { |element, index| correct_element(dimensions[index], element) if dimensions[index] } + .compact end def possible_paths(states) - states.map do |state| - state.join separator - end + states.map { |state| state.join(separator) } end - def plausible_dimensions(input) - elements = input.split(separator)[0..-2] - elements.each_with_index.map do |element, i| - next if dimensions[i].nil? - CorrectElement.new.call dimensions[i], element - end.compact - end - end + private - # parses the elements in each dimension - class ParseDimensions - def initialize(dictionary, separator) - @dictionary = dictionary - @separator = separator + def find_suggestions(input, plausibles) + states = plausibles[0].product(*plausibles[1..-1]) + paths = possible_paths(states) + leaf = input.split(separator).last + + find_ideas(paths, leaf) end - def call - leafless = remove_leaves - dimensions = find_elements leafless - dimensions.map do |elements| - elements.to_set.to_a - end + def fall_back_to_normal_spell_check(input) + return [] unless augment + + ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input) end - private + def find_ideas(paths, leaf) + paths.flat_map do |path| + names = find_leaves(path) + ideas = correct_element(names, leaf) - def remove_leaves - dictionary.map do |a| - elements = a.split(separator) - elements[0..-2] - end.to_set.to_a + ideas_to_paths(ideas, leaf, names, path) + end.compact end - def find_elements(leafless) - max_elements = leafless.map(&:size).max - dimensions = Array.new(max_elements) { [] } - (0...max_elements).each do |i| - leafless.each do |elements| - dimensions[i] << elements[i] unless elements[i].nil? - end + def ideas_to_paths(ideas, leaf, names, path) + if ideas.empty? + nil + elsif names.include?(leaf) + ["#{path}#{separator}#{leaf}"] + else + ideas.map {|str| "#{path}#{separator}#{str}" } end - dimensions end - attr_reader :dictionary, :separator - end + def correct_element(names, element) + return names if names.size == 1 - # identifies the elements close to element - class CorrectElement - def initialize - end + str = normalize(element) - def call(names, element) - return names if names.size == 1 - str = normalize element - return [str] if names.include? str - checker = ::DidYouMean::SpellChecker.new(dictionary: names) - checker.correct(str) - end + return [str] if names.include?(str) - private + ::DidYouMean::SpellChecker.new(dictionary: names).correct(str) + end - def normalize(leaf) - str = leaf.dup + def normalize(str) str.downcase! - return str unless str.include? '@' - str.tr!('@', ' ') + str.tr!('@', ' ') if str.include?('@') + str end end end diff --git a/ruby/lib/did_you_mean/verbose.rb b/ruby/lib/did_you_mean/verbose.rb index 4e86f167e..1ff19aef8 100644 --- a/ruby/lib/did_you_mean/verbose.rb +++ b/ruby/lib/did_you_mean/verbose.rb @@ -1,4 +1,2 @@ -require_relative '../did_you_mean' -require_relative 'formatters/verbose_formatter' - -DidYouMean.formatter = DidYouMean::VerboseFormatter.new +warn "The verbose formatter has been removed and now `require 'did_you_mean/verbose'` has no effect. Please " \ + "remove this call." diff --git a/ruby/lib/did_you_mean/version.rb b/ruby/lib/did_you_mean/version.rb index 6d3dd3a69..b5fe50b5e 100644 --- a/ruby/lib/did_you_mean/version.rb +++ b/ruby/lib/did_you_mean/version.rb @@ -1,3 +1,3 @@ module DidYouMean - VERSION = "1.4.0" + VERSION = "1.6.1".freeze end diff --git a/ruby/lib/drb/drb.gemspec b/ruby/lib/drb/drb.gemspec new file mode 100644 index 000000000..c9d7e40a5 --- /dev/null +++ b/ruby/lib/drb/drb.gemspec @@ -0,0 +1,43 @@ +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/ruby/lib/drb/drb.rb b/ruby/lib/drb/drb.rb index 4d3ea364f..3e2321391 100644 --- a/ruby/lib/drb/drb.rb +++ b/ruby/lib/drb/drb.rb @@ -1382,10 +1382,6 @@ def self.default_id_conv(idconv) @@idconv = idconv end - def self.default_safe_level(level) # :nodoc: - # Remove in Ruby 3.0 - end - # Set the default value of the :verbose option. # # See #new(). The initial default value is false. @@ -1495,11 +1491,6 @@ def initialize(uri=nil, front=nil, config_or_acl=nil) # The configuration of this DRbServer attr_reader :config - def safe_level # :nodoc: - # Remove in Ruby 3.0 - 0 - end - # Set whether to operate in verbose mode. # # In verbose mode, failed calls are logged to stdout. diff --git a/ruby/lib/drb/observer.rb b/ruby/lib/drb/observer.rb index 3ee15331a..0fb7301ed 100644 --- a/ruby/lib/drb/observer.rb +++ b/ruby/lib/drb/observer.rb @@ -13,7 +13,7 @@ def notify_observers(*arg) if defined? @observer_peers @observer_peers.each do |observer, method| begin - observer.send(method, *arg) + observer.__send__(method, *arg) rescue delete_observer(observer) end diff --git a/ruby/lib/drb/ssl.rb b/ruby/lib/drb/ssl.rb index 3d528c617..54ab1ef39 100644 --- a/ruby/lib/drb/ssl.rb +++ b/ruby/lib/drb/ssl.rb @@ -196,7 +196,7 @@ def setup_certificate if comment = self[:SSLCertComment] cert.add_extension(ef.create_extension("nsComment", comment)) end - cert.sign(rsa, OpenSSL::Digest::SHA256.new) + cert.sign(rsa, "SHA256") @cert = cert @pkey = rsa diff --git a/ruby/lib/drb/version.rb b/ruby/lib/drb/version.rb new file mode 100644 index 000000000..efaccf031 --- /dev/null +++ b/ruby/lib/drb/version.rb @@ -0,0 +1,3 @@ +module DRb + VERSION = "2.1.0" +end diff --git a/ruby/lib/erb.gemspec b/ruby/lib/erb.gemspec new file mode 100644 index 000000000..43ffc89c6 --- /dev/null +++ b/ruby/lib/erb.gemspec @@ -0,0 +1,31 @@ +begin + require_relative 'lib/erb/version' +rescue LoadError + # for Ruby core repository + require_relative 'erb/version' +end + +Gem::Specification.new do |spec| + spec.name = 'erb' + spec.version = ERB.const_get(:VERSION, false) + spec.authors = ['Masatoshi SEKI'] + spec.email = ['seki@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 + spec.metadata['source_code_uri'] = spec.homepage + + 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 = 'libexec' + spec.executables = ['erb'] + spec.require_paths = ['lib'] + + spec.add_dependency 'cgi' +end diff --git a/ruby/lib/erb.rb b/ruby/lib/erb.rb index d2ea64ab6..3045106c9 100644 --- a/ruby/lib/erb.rb +++ b/ruby/lib/erb.rb @@ -12,7 +12,8 @@ # # You can redistribute it and/or modify it under the same terms as Ruby. -require "cgi/util" +require 'cgi/util' +require 'erb/version' # # = ERB -- Ruby Templating @@ -45,7 +46,7 @@ # # <% Ruby code -- inline with output %> # <%= Ruby expression -- replace with result %> -# <%# comment -- ignored -- useful in testing %> +# <%# comment -- ignored -- useful in testing %> (`<% #` doesn't work. Don't use Ruby comments.) # % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new) # %% replaced with % if first thing on a line and % processing is used # <%% or %%> -- replace with <% or %> respectively @@ -257,10 +258,11 @@ # class ERB Revision = '$Date:: $' # :nodoc: #' + deprecate_constant :Revision # Returns revision information for the erb.rb module. def self.version - "erb.rb [2.2.0 #{ERB::Revision.split[1]}]" + VERSION end end @@ -809,14 +811,14 @@ class ERB 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. if safe_level != NOT_GIVEN - warn 'Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments.', uplevel: 1 if $VERBOSE || !ZERO_SAFE_LEVELS.include?(safe_level) + warn 'Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments.', uplevel: 1 end if legacy_trim_mode != NOT_GIVEN - warn 'Passing trim_mode with the 3rd argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, trim_mode: ...) instead.', uplevel: 1 if $VERBOSE + warn 'Passing trim_mode with the 3rd argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, trim_mode: ...) instead.', uplevel: 1 trim_mode = legacy_trim_mode end if legacy_eoutvar != NOT_GIVEN - warn 'Passing eoutvar with the 4th argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.', uplevel: 1 if $VERBOSE + warn 'Passing eoutvar with the 4th argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.', uplevel: 1 eoutvar = legacy_eoutvar end @@ -829,8 +831,6 @@ def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eou end NOT_GIVEN = Object.new private_constant :NOT_GIVEN - ZERO_SAFE_LEVELS = [0, nil] - private_constant :ZERO_SAFE_LEVELS ## # Creates a new compiler for ERB. See ERB::Compiler.new for details diff --git a/ruby/lib/erb/version.rb b/ruby/lib/erb/version.rb new file mode 100644 index 000000000..0aaa38258 --- /dev/null +++ b/ruby/lib/erb/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +class ERB + VERSION = '2.2.3' + private_constant :VERSION +end diff --git a/ruby/lib/error_highlight.rb b/ruby/lib/error_highlight.rb new file mode 100644 index 000000000..31db95d11 --- /dev/null +++ b/ruby/lib/error_highlight.rb @@ -0,0 +1,2 @@ +require_relative "error_highlight/base" +require_relative "error_highlight/core_ext" diff --git a/ruby/lib/error_highlight/base.rb b/ruby/lib/error_highlight/base.rb new file mode 100644 index 000000000..8392979e2 --- /dev/null +++ b/ruby/lib/error_highlight/base.rb @@ -0,0 +1,461 @@ +require_relative "version" + +module ErrorHighlight + # Identify the code fragment that seems associated with a given error + # + # Arguments: + # node: RubyVM::AbstractSyntaxTree::Node (script_lines should be enabled) + # point_type: :name | :args + # name: The name associated with the NameError/NoMethodError + # + # Returns: + # { + # first_lineno: Integer, + # first_column: Integer, + # last_lineno: Integer, + # last_column: Integer, + # snippet: String, + # } | nil + def self.spot(...) + Spotter.new(...).spot + end + + class Spotter + class NonAscii < Exception; end + private_constant :NonAscii + + def initialize(node, point_type: :name, name: nil) + @node = node + @point_type = point_type + @name = name + + # Not-implemented-yet options + @arg = nil # Specify the index or keyword at which argument caused the TypeError/ArgumentError + @multiline = false # Allow multiline spot + + @fetch = -> (lineno, last_lineno = lineno) do + snippet = @node.script_lines[lineno - 1 .. last_lineno - 1].join("") + snippet += "\n" unless snippet.end_with?("\n") + + # It require some work to support Unicode (or multibyte) characters. + # Tentatively, we stop highlighting if the code snippet has non-ascii characters. + # See https://github.com/ruby/error_highlight/issues/4 + raise NonAscii unless snippet.ascii_only? + + snippet + end + end + + def spot + return nil unless @node + + case @node.type + + when :CALL, :QCALL + case @point_type + when :name + spot_call_for_name + when :args + spot_call_for_args + end + + when :ATTRASGN + case @point_type + when :name + spot_attrasgn_for_name + when :args + spot_attrasgn_for_args + end + + when :OPCALL + case @point_type + when :name + spot_opcall_for_name + when :args + spot_opcall_for_args + end + + when :FCALL + case @point_type + when :name + spot_fcall_for_name + when :args + spot_fcall_for_args + end + + when :VCALL + spot_vcall + + when :OP_ASGN1 + case @point_type + when :name + spot_op_asgn1_for_name + when :args + spot_op_asgn1_for_args + end + + when :OP_ASGN2 + case @point_type + when :name + spot_op_asgn2_for_name + when :args + spot_op_asgn2_for_args + end + + when :CONST + spot_vcall + + when :COLON2 + spot_colon2 + + when :COLON3 + spot_vcall + + when :OP_CDECL + spot_op_cdecl + end + + if @snippet && @beg_column && @end_column && @beg_column < @end_column + return { + first_lineno: @beg_lineno, + first_column: @beg_column, + last_lineno: @end_lineno, + last_column: @end_column, + snippet: @snippet, + } + else + return nil + end + + rescue NonAscii + nil + end + + private + + # Example: + # x.foo + # ^^^^ + # x.foo(42) + # ^^^^ + # x&.foo + # ^^^^^ + # x[42] + # ^^^^ + # x += 1 + # ^ + def spot_call_for_name + nd_recv, mid, nd_args = @node.children + lineno = nd_recv.last_lineno + lines = @fetch[lineno, @node.last_lineno] + if mid == :[] && lines.match(/\G[\s)]*(\[(?:\s*\])?)/, nd_recv.last_column) + @beg_column = $~.begin(1) + @snippet = lines[/.*\n/] + @beg_lineno = @end_lineno = lineno + if nd_args + if nd_recv.last_lineno == nd_args.last_lineno && @snippet.match(/\s*\]/, nd_args.last_column) + @end_column = $~.end(0) + end + else + if lines.match(/\G[\s)]*?\[\s*\]/, nd_recv.last_column) + @end_column = $~.end(0) + end + end + elsif lines.match(/\G[\s)]*?(\&?\.)(\s*?)(#{ Regexp.quote(mid) }).*\n/, nd_recv.last_column) + lines = $` + $& + @beg_column = $~.begin($2.include?("\n") ? 3 : 1) + @end_column = $~.end(3) + if i = lines[..@beg_column].rindex("\n") + @beg_lineno = @end_lineno = lineno + lines[..@beg_column].count("\n") + @snippet = lines[i + 1..] + @beg_column -= i + 1 + @end_column -= i + 1 + else + @snippet = lines + @beg_lineno = @end_lineno = lineno + end + elsif mid.to_s =~ /\A\W+\z/ && lines.match(/\G\s*(#{ Regexp.quote(mid) })=.*\n/, nd_recv.last_column) + @snippet = $` + $& + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + + # Example: + # x.foo(42) + # ^^ + # x[42] + # ^^ + # x += 1 + # ^ + def spot_call_for_args + _nd_recv, _mid, nd_args = @node.children + if nd_args && nd_args.first_lineno == nd_args.last_lineno + fetch_line(nd_args.first_lineno) + @beg_column = nd_args.first_column + @end_column = nd_args.last_column + end + # TODO: support @arg + end + + # Example: + # x.foo = 1 + # ^^^^^^ + # x[42] = 1 + # ^^^^^^ + def spot_attrasgn_for_name + nd_recv, mid, nd_args = @node.children + *nd_args, _nd_last_arg, _nil = nd_args.children + fetch_line(nd_recv.last_lineno) + if mid == :[]= && @snippet.match(/\G[\s)]*(\[)/, nd_recv.last_column) + @beg_column = $~.begin(1) + args_last_column = $~.end(0) + if nd_args.last && nd_recv.last_lineno == nd_args.last.last_lineno + args_last_column = nd_args.last.last_column + end + if @snippet.match(/[\s)]*\]\s*=/, args_last_column) + @end_column = $~.end(0) + end + elsif @snippet.match(/\G[\s)]*(\.\s*#{ Regexp.quote(mid.to_s.sub(/=\z/, "")) }\s*=)/, nd_recv.last_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + + # Example: + # x.foo = 1 + # ^ + # x[42] = 1 + # ^^^^^^^ + # x[] = 1 + # ^^^^^ + def spot_attrasgn_for_args + nd_recv, mid, nd_args = @node.children + fetch_line(nd_recv.last_lineno) + if mid == :[]= && @snippet.match(/\G[\s)]*\[/, nd_recv.last_column) + @beg_column = $~.end(0) + if nd_recv.last_lineno == nd_args.last_lineno + @end_column = nd_args.last_column + end + elsif nd_args && nd_args.first_lineno == nd_args.last_lineno + @beg_column = nd_args.first_column + @end_column = nd_args.last_column + end + # TODO: support @arg + end + + # Example: + # x + 1 + # ^ + # +x + # ^ + def spot_opcall_for_name + nd_recv, op, nd_arg = @node.children + fetch_line(nd_recv.last_lineno) + if nd_arg + # binary operator + if @snippet.match(/\G[\s)]*(#{ Regexp.quote(op) })/, nd_recv.last_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + else + # unary operator + if @snippet[...nd_recv.first_column].match(/(#{ Regexp.quote(op.to_s.sub(/@\z/, "")) })\s*\(?\s*\z/) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + end + + # Example: + # x + 1 + # ^ + def spot_opcall_for_args + _nd_recv, _op, nd_arg = @node.children + if nd_arg && nd_arg.first_lineno == nd_arg.last_lineno + # binary operator + fetch_line(nd_arg.first_lineno) + @beg_column = nd_arg.first_column + @end_column = nd_arg.last_column + end + end + + # Example: + # foo(42) + # ^^^ + # foo 42 + # ^^^ + def spot_fcall_for_name + mid, _nd_args = @node.children + fetch_line(@node.first_lineno) + if @snippet.match(/(#{ Regexp.quote(mid) })/, @node.first_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + end + + # Example: + # foo(42) + # ^^ + # foo 42 + # ^^ + def spot_fcall_for_args + _mid, nd_args = @node.children + if nd_args && nd_args.first_lineno == nd_args.last_lineno + # binary operator + fetch_line(nd_args.first_lineno) + @beg_column = nd_args.first_column + @end_column = nd_args.last_column + end + end + + # Example: + # foo + # ^^^ + def spot_vcall + if @node.first_lineno == @node.last_lineno + fetch_line(@node.last_lineno) + @beg_column = @node.first_column + @end_column = @node.last_column + end + end + + # Example: + # x[1] += 42 + # ^^^ (for []) + # x[1] += 42 + # ^ (for +) + # x[1] += 42 + # ^^^^^^ (for []=) + def spot_op_asgn1_for_name + nd_recv, op, nd_args, _nd_rhs = @node.children + fetch_line(nd_recv.last_lineno) + if @snippet.match(/\G[\s)]*(\[)/, nd_recv.last_column) + bracket_beg_column = $~.begin(1) + args_last_column = $~.end(0) + if nd_args && nd_recv.last_lineno == nd_args.last_lineno + args_last_column = nd_args.last_column + end + if @snippet.match(/\s*\](\s*)(#{ Regexp.quote(op) })=()/, args_last_column) + case @name + when :[], :[]= + @beg_column = bracket_beg_column + @end_column = $~.begin(@name == :[] ? 1 : 3) + when op + @beg_column = $~.begin(2) + @end_column = $~.end(2) + end + end + end + end + + # Example: + # x[1] += 42 + # ^^^^^^^^ + def spot_op_asgn1_for_args + nd_recv, mid, nd_args, nd_rhs = @node.children + fetch_line(nd_recv.last_lineno) + if mid == :[]= && @snippet.match(/\G\s*\[/, nd_recv.last_column) + @beg_column = $~.end(0) + if nd_recv.last_lineno == nd_rhs.last_lineno + @end_column = nd_rhs.last_column + end + elsif nd_args && nd_args.first_lineno == nd_rhs.last_lineno + @beg_column = nd_args.first_column + @end_column = nd_rhs.last_column + end + # TODO: support @arg + end + + # Example: + # x.foo += 42 + # ^^^ (for foo) + # x.foo += 42 + # ^ (for +) + # x.foo += 42 + # ^^^^^^^ (for foo=) + def spot_op_asgn2_for_name + nd_recv, _qcall, attr, op, _nd_rhs = @node.children + fetch_line(nd_recv.last_lineno) + if @snippet.match(/\G[\s)]*(\.)\s*#{ Regexp.quote(attr) }()\s*(#{ Regexp.quote(op) })(=)/, nd_recv.last_column) + case @name + when attr + @beg_column = $~.begin(1) + @end_column = $~.begin(2) + when op + @beg_column = $~.begin(3) + @end_column = $~.end(3) + when :"#{ attr }=" + @beg_column = $~.begin(1) + @end_column = $~.end(4) + end + end + end + + # Example: + # x.foo += 42 + # ^^ + def spot_op_asgn2_for_args + _nd_recv, _qcall, _attr, _op, nd_rhs = @node.children + if nd_rhs.first_lineno == nd_rhs.last_lineno + fetch_line(nd_rhs.first_lineno) + @beg_column = nd_rhs.first_column + @end_column = nd_rhs.last_column + end + end + + # Example: + # Foo::Bar + # ^^^^^ + def spot_colon2 + nd_parent, const = @node.children + if nd_parent.last_lineno == @node.last_lineno + fetch_line(nd_parent.last_lineno) + @beg_column = nd_parent.last_column + @end_column = @node.last_column + else + @snippet = @fetch[@node.last_lineno] + if @snippet[...@node.last_column].match(/#{ Regexp.quote(const) }\z/) + @beg_column = $~.begin(0) + @end_column = $~.end(0) + end + end + end + + # Example: + # Foo::Bar += 1 + # ^^^^^^^^ + 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] + if @snippet.match(/\G\s*(#{ Regexp.quote(op) })=/, nd_lhs.last_column) + @beg_column = $~.begin(1) + @end_column = $~.end(1) + end + else + # constant access error + @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] + @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] + @beg_column = nd_parent_lhs.last.last_column + end + end + end + end + + def fetch_line(lineno) + @beg_lineno = @end_lineno = lineno + @snippet = @fetch[lineno] + end + end + + private_constant :Spotter +end diff --git a/ruby/lib/error_highlight/core_ext.rb b/ruby/lib/error_highlight/core_ext.rb new file mode 100644 index 000000000..d3a4dbacd --- /dev/null +++ b/ruby/lib/error_highlight/core_ext.rb @@ -0,0 +1,52 @@ +require_relative "formatter" + +module ErrorHighlight + module CoreExt + # This is a marker to let `DidYouMean::Correctable#original_message` skip + # the following method definition of `to_s`. + # See https://github.com/ruby/did_you_mean/pull/152 + SKIP_TO_S_FOR_SUPER_LOOKUP = true + private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP + + def to_s + msg = super.dup + + locs = backtrace_locations + return msg unless locs + + loc = locs.first + begin + node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true) + opts = {} + + case self + when NoMethodError, NameError + opts[:point_type] = :name + opts[:name] = name + when TypeError, ArgumentError + opts[:point_type] = :args + end + + spot = ErrorHighlight.spot(node, **opts) + + rescue SyntaxError + rescue SystemCallError # file not found or something + rescue ArgumentError # eval'ed code + end + + if spot + points = ErrorHighlight.formatter.message_for(spot) + msg << points if !msg.include?(points) + end + + msg + end + end + + NameError.prepend(CoreExt) + + # The extension for TypeError/ArgumentError is temporarily disabled due to many test failures + + #TypeError.prepend(CoreExt) + #ArgumentError.prepend(CoreExt) +end diff --git a/ruby/lib/error_highlight/error_highlight.gemspec b/ruby/lib/error_highlight/error_highlight.gemspec new file mode 100644 index 000000000..b2da18df8 --- /dev/null +++ b/ruby/lib/error_highlight/error_highlight.gemspec @@ -0,0 +1,27 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +begin + require_relative "lib/error_highlight/version" +rescue LoadError # Fallback to load version file in ruby core repository + require_relative "version" +end + +Gem::Specification.new do |spec| + spec.name = "error_highlight" + spec.version = ErrorHighlight::VERSION + spec.authors = ["Yusuke Endoh"] + spec.email = ["mame@ruby-lang.org"] + + spec.summary = 'Shows a one-line code snippet with an underline in the error backtrace' + spec.description = 'The gem enhances Exception#message by adding a short explanation where the exception is raised' + spec.homepage = "https://github.com/ruby/error_highlight" + + spec.license = "MIT" + spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0.dev") + + spec.files = Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) } + end + spec.require_paths = ["lib"] +end diff --git a/ruby/lib/error_highlight/formatter.rb b/ruby/lib/error_highlight/formatter.rb new file mode 100644 index 000000000..20ca78d46 --- /dev/null +++ b/ruby/lib/error_highlight/formatter.rb @@ -0,0 +1,23 @@ +module ErrorHighlight + class DefaultFormatter + 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]) + + "\n\n#{ spot[:snippet] }#{ marker }" + else + "" + end + end + end + + def self.formatter + Ractor.current[:__error_highlight_formatter__] || DefaultFormatter + end + + def self.formatter=(formatter) + Ractor.current[:__error_highlight_formatter__] = formatter + end +end diff --git a/ruby/lib/error_highlight/version.rb b/ruby/lib/error_highlight/version.rb new file mode 100644 index 000000000..49a34502c --- /dev/null +++ b/ruby/lib/error_highlight/version.rb @@ -0,0 +1,3 @@ +module ErrorHighlight + VERSION = "0.3.0" +end diff --git a/ruby/lib/fileutils.gemspec b/ruby/lib/fileutils.gemspec index cd35c09db..76baea303 100644 --- a/ruby/lib/fileutils.gemspec +++ b/ruby/lib/fileutils.gemspec @@ -18,12 +18,12 @@ Gem::Specification.new do |s| s.require_path = %w{lib} s.files = ["LICENSE.txt", "README.md", "Rakefile", "fileutils.gemspec", "lib/fileutils.rb"] - s.required_ruby_version = ">= 2.3.0" + s.required_ruby_version = ">= 2.5.0" s.authors = ["Minero Aoki"] s.email = [nil] s.homepage = "https://github.com/ruby/fileutils" - s.license = "BSD-2-Clause" + s.licenses = ["Ruby", "BSD-2-Clause"] s.metadata = { "source_code_uri" => "https://github.com/ruby/fileutils" diff --git a/ruby/lib/fileutils.rb b/ruby/lib/fileutils.rb index a7ad65ae5..c11500516 100644 --- a/ruby/lib/fileutils.rb +++ b/ruby/lib/fileutils.rb @@ -102,7 +102,7 @@ # :verbose flags to methods in FileUtils. # module FileUtils - VERSION = "1.4.1" + VERSION = "1.6.0" def self.private_module_function(name) #:nodoc: module_function name @@ -208,21 +208,14 @@ def mkdir_p(list, mode: nil, noop: nil, verbose: nil) fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose return *list if noop - list.map {|path| remove_trailing_slash(path)}.each do |path| - # optimize for the most common case - begin - fu_mkdir path, mode - next - rescue SystemCallError - next if File.directory?(path) - end + list.each do |item| + path = remove_trailing_slash(item) stack = [] - until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/" + until File.directory?(path) stack.push path path = File.dirname(path) end - stack.pop # root directory should exist stack.reverse_each do |dir| begin fu_mkdir dir, mode @@ -834,13 +827,8 @@ def compare_file(a, b) def compare_stream(a, b) bsize = fu_stream_blksize(a, b) - if RUBY_VERSION > "2.4" - sa = String.new(capacity: bsize) - sb = String.new(capacity: bsize) - else - sa = String.new - sb = String.new - end + sa = String.new(capacity: bsize) + sb = String.new(capacity: bsize) begin a.read(bsize, sa) @@ -917,11 +905,8 @@ def apply_mask(mode, user_mask, op, mode_mask) #:nodoc: private_module_function :apply_mask def symbolic_modes_to_i(mode_sym, path) #:nodoc: - mode = if File::Stat === path - path.mode - else - File.stat(path).mode - end + path = File.stat(path) unless File::Stat === path + mode = path.mode mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause| target, *actions = clause.split(/([=+-])/) raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty? @@ -938,7 +923,7 @@ def symbolic_modes_to_i(mode_sym, path) #:nodoc: when "x" mask | 0111 when "X" - if FileTest.directory? path + if path.directory? mask | 0111 else mask @@ -1290,14 +1275,9 @@ def door? def entries opts = {} - opts[:encoding] = ::Encoding::UTF_8 if fu_windows? + opts[:encoding] = fu_windows? ? ::Encoding::UTF_8 : path.encoding - files = if Dir.respond_to?(:children) - Dir.children(path, **opts) - else - Dir.entries(path(), **opts) - .reject {|n| n == '.' or n == '..' } - end + files = Dir.children(path, **opts) untaint = RUBY_VERSION < '2.7' files.map {|n| Entry_.new(prefix(), join(rel(), untaint ? n.untaint : n)) } @@ -1345,6 +1325,7 @@ def chmod(mode) else File.chmod mode, path() end + rescue Errno::EOPNOTSUPP end def chown(uid, gid) @@ -1439,7 +1420,7 @@ def copy_metadata(path) if st.symlink? begin File.lchmod mode, path - rescue NotImplementedError + rescue NotImplementedError, Errno::EOPNOTSUPP end else File.chmod mode, path @@ -1559,7 +1540,15 @@ def check_have_lchown? def join(dir, base) return File.path(dir) if not base or base == '.' return File.path(base) if not dir or dir == '.' - File.join(dir, base) + begin + File.join(dir, base) + rescue EncodingError + if fu_windows? + File.join(dir.encode(::Encoding::UTF_8), base.encode(::Encoding::UTF_8)) + else + raise + end + end end if File::ALT_SEPARATOR @@ -1614,7 +1603,7 @@ def fu_same?(a, b) #:nodoc: def fu_output_message(msg) #:nodoc: output = @fileutils_output if defined?(@fileutils_output) - output ||= $stderr + output ||= $stdout if defined?(@fileutils_label) msg = @fileutils_label + msg end diff --git a/ruby/lib/find.gemspec b/ruby/lib/find.gemspec new file mode 100644 index 000000000..3f0aadcda --- /dev/null +++ b/ruby/lib/find.gemspec @@ -0,0 +1,24 @@ +Gem::Specification.new do |spec| + spec.name = "find" + spec.version = "0.1.1" + spec.authors = ['Kazuki Tsujimoto'] + spec.email = ['kazuki@callcc.net'] + + spec.summary = %q{This module supports top-down traversal of a set of file paths.} + spec.description = %q{This module supports top-down traversal of a set of file paths.} + spec.homepage = "https://github.com/ruby/find" + 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"] +end diff --git a/ruby/lib/find.rb b/ruby/lib/find.rb index 3f54cf6b9..9bee99c66 100644 --- a/ruby/lib/find.rb +++ b/ruby/lib/find.rb @@ -49,14 +49,14 @@ def find(*paths, ignore_error: true) # :yield: path yield file.dup begin s = File.lstat(file) - rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG + rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG, Errno::EINVAL raise unless ignore_error next end if s.directory? then begin fs = Dir.children(file, encoding: enc) - rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG + rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG, Errno::EINVAL raise unless ignore_error next end diff --git a/ruby/lib/forwardable.rb b/ruby/lib/forwardable.rb index 4cfade470..c9c4128f9 100644 --- a/ruby/lib/forwardable.rb +++ b/ruby/lib/forwardable.rb @@ -76,7 +76,7 @@ # def_delegators :@q, :clear, :first, :push, :shift, :size # end # -# q = Queue.new +# q = Thread::Queue.new # q.enq 1, 2, 3, 4, 5 # q.push 6 # @@ -110,7 +110,10 @@ # module Forwardable require 'forwardable/impl' - require "forwardable/version" + + # Version of +forwardable.rb+ + VERSION = "1.3.2" + FORWARDABLE_VERSION = VERSION @debug = nil class << self @@ -186,7 +189,7 @@ def def_instance_delegator(accessor, method, ali = method) # If it's not a class or module, it's an instance mod = Module === self ? self : singleton_class ret = mod.module_eval(&gen) - mod.send(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7' + mod.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7' ret end @@ -306,7 +309,7 @@ def def_single_delegator(accessor, method, ali = method) gen = Forwardable._delegator_method(self, accessor, method, ali) ret = instance_eval(&gen) - singleton_class.send(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7' + singleton_class.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7' ret end diff --git a/ruby/lib/forwardable/forwardable.gemspec b/ruby/lib/forwardable/forwardable.gemspec index 2a3e637e2..9ad59c5f8 100644 --- a/ruby/lib/forwardable/forwardable.gemspec +++ b/ruby/lib/forwardable/forwardable.gemspec @@ -1,23 +1,26 @@ -begin - require_relative "lib/forwardable/version" -rescue LoadError - # for Ruby core repository - require_relative "version" +# 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 = "forwardable" - spec.version = Forwardable::VERSION + spec.name = name + spec.version = version spec.authors = ["Keiju ISHITSUKA"] spec.email = ["keiju@ruby-lang.org"] spec.summary = %q{Provides delegation of specified methods to a designated object.} spec.description = %q{Provides delegation of specified methods to a designated object.} spec.homepage = "https://github.com/ruby/forwardable" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = ["forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb", "lib/forwardable/version.rb"] + spec.required_ruby_version = '>= 2.4.0' + spec.files = ["forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb"] spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.executables = [] spec.require_paths = ["lib"] end diff --git a/ruby/lib/forwardable/version.rb b/ruby/lib/forwardable/version.rb deleted file mode 100644 index 8f3e1f510..000000000 --- a/ruby/lib/forwardable/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Forwardable - # Version of +forwardable.rb+ - VERSION = "1.3.1" - FORWARDABLE_VERSION = VERSION -end diff --git a/ruby/lib/getoptlong.rb b/ruby/lib/getoptlong.rb index ff7674f1c..d3fff34be 100644 --- a/ruby/lib/getoptlong.rb +++ b/ruby/lib/getoptlong.rb @@ -85,6 +85,9 @@ # hello -n 6 --name -- /tmp # class GetoptLong + # Version. + VERSION = "0.1.1" + # # Orderings. # @@ -111,7 +114,7 @@ class MissingArgument < Error; end class InvalidOption < Error; end # - # Set up option processing. + # \Set up option processing. # # The options to support are passed to new() as an array of arrays. # Each sub-array contains any number of String option names which carry @@ -187,7 +190,7 @@ def initialize(*arguments) end # - # Set the handling of the ordering of options and arguments. + # \Set the handling of the ordering of options and arguments. # A RuntimeError is raised if option processing has already started. # # The supplied value must be a member of GetoptLong::ORDERINGS. It alters @@ -264,7 +267,7 @@ def ordering=(ordering) attr_reader :ordering # - # Set options. Takes the same argument as GetoptLong.new. + # \Set options. Takes the same argument as GetoptLong.new. # # Raises a RuntimeError if option processing has already started. # @@ -338,7 +341,7 @@ def set_options(*arguments) end # - # Set/Unset `quiet' mode. + # \Set/Unset `quiet' mode. # attr_writer :quiet @@ -380,7 +383,7 @@ def terminated? end # - # Set an error (a protected method). + # \Set an error (a protected method). # def set_error(type, message) $stderr.print("#{$0}: #{message}\n") if !@quiet diff --git a/ruby/lib/getoptlong/getoptlong.gemspec b/ruby/lib/getoptlong/getoptlong.gemspec index 5e218b8e9..dfe087b88 100644 --- a/ruby/lib/getoptlong/getoptlong.gemspec +++ b/ruby/lib/getoptlong/getoptlong.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/getoptlong/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "getoptlong" - spec.version = GetoptLong::VERSION + 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage @@ -23,7 +26,5 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z 2>/dev/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/ruby/lib/getoptlong/version.rb b/ruby/lib/getoptlong/version.rb deleted file mode 100644 index 6375fb8ad..000000000 --- a/ruby/lib/getoptlong/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class GetoptLong - VERSION = "0.1.0" -end diff --git a/ruby/lib/ipaddr.gemspec b/ruby/lib/ipaddr.gemspec index 2de9ef488..1f4798e43 100644 --- a/ruby/lib/ipaddr.gemspec +++ b/ruby/lib/ipaddr.gemspec @@ -1,11 +1,23 @@ # frozen_string_literal: true # coding: utf-8 -lib = File.expand_path("../lib", __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) + +if File.exist?(File.expand_path("ipaddr.gemspec")) + lib = File.expand_path("../lib", __FILE__) + $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) + + file = File.expand_path("ipaddr.rb", lib) +else + # for ruby-core + file = File.expand_path("../ipaddr.rb", __FILE__) +end + +version = File.foreach(file).find do |line| + /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1 +end Gem::Specification.new do |spec| spec.name = "ipaddr" - spec.version = "1.2.2" + spec.version = version spec.authors = ["Akinori MUSHA", "Hajimu UMEMOTO"] spec.email = ["knu@idaemons.org", "ume@mahoroba.org"] @@ -15,14 +27,10 @@ IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and IPv6 are supported. DESCRIPTION spec.homepage = "https://github.com/ruby/ipaddr" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ipaddr.gemspec", "lib/ipaddr.rb"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.files = ["LICENSE.txt", "README.md", "ipaddr.gemspec", "lib/ipaddr.rb"] spec.require_paths = ["lib"] - spec.add_development_dependency "bundler", "~> 1.15" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "test-unit" + spec.required_ruby_version = ">= 2.3" end diff --git a/ruby/lib/ipaddr.rb b/ruby/lib/ipaddr.rb index 7fff54b9d..459b8478a 100644 --- a/ruby/lib/ipaddr.rb +++ b/ruby/lib/ipaddr.rb @@ -40,6 +40,7 @@ # p ipaddr3 #=> # class IPAddr + VERSION = "1.2.4" # 32 bit mask for IPv4 IN4MASK = 0xffffffff @@ -112,13 +113,12 @@ def self.new_ntoh(addr) def self.ntop(addr) case addr.size when 4 - s = addr.unpack('C4').join('.') + addr.unpack('C4').join('.') when 16 - s = IN6FORMAT % addr.unpack('n8') + IN6FORMAT % addr.unpack('n8') else raise AddressFamilyError, "unsupported address family" end - return s end # Returns a new ipaddr built by bitwise AND. @@ -168,34 +168,17 @@ def mask(prefixlen) # net1 = IPAddr.new("192.168.2.0/24") # net2 = IPAddr.new("192.168.2.100") # net3 = IPAddr.new("192.168.3.0") + # net4 = IPAddr.new("192.168.2.0/16") # p net1.include?(net2) #=> true # p net1.include?(net3) #=> false + # p net1.include?(net4) #=> false + # p net4.include?(net1) #=> true def include?(other) other = coerce_other(other) - if ipv4_mapped? - if (@mask_addr >> 32) != 0xffffffffffffffffffffffff - return false - end - mask_addr = (@mask_addr & IN4MASK) - addr = (@addr & IN4MASK) - family = Socket::AF_INET - else - mask_addr = @mask_addr - addr = @addr - family = @family - end - if other.ipv4_mapped? - other_addr = (other.to_i & IN4MASK) - other_family = Socket::AF_INET - else - other_addr = other.to_i - other_family = other.family - end - - if family != other_family - return false - end - return ((addr & mask_addr) == (other_addr & mask_addr)) + return false unless other.family == family + range = to_range + other = other.to_range + range.begin <= other.begin && range.end >= other.end end alias === include? @@ -232,7 +215,13 @@ def to_s # Returns a string containing the IP address representation in # canonical form. def to_string - return _to_string(@addr) + str = _to_string(@addr) + + if @family == Socket::AF_INET6 + str << zone_id.to_s + end + + return str end # Returns a network byte ordered string form of the IP address. @@ -328,9 +317,11 @@ def _ipv4_compat? # into an IPv4-mapped IPv6 address. def ipv4_mapped if !ipv4? - raise InvalidAddressError, "not an IPv4 address" + raise InvalidAddressError, "not an IPv4 address: #{@addr}" end - return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6) + clone = self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6) + clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000) + clone end # Returns a new ipaddr built by converting the native IPv4 address @@ -338,7 +329,7 @@ def ipv4_mapped def ipv4_compat warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE if !ipv4? - raise InvalidAddressError, "not an IPv4 address" + raise InvalidAddressError, "not an IPv4 address: #{@addr}" end return self.clone.set(@addr, Socket::AF_INET6) end @@ -369,7 +360,7 @@ def reverse # Returns a string for DNS reverse lookup compatible with RFC3172. def ip6_arpa if !ipv6? - raise InvalidAddressError, "not an IPv6 address" + raise InvalidAddressError, "not an IPv6 address: #{@addr}" end return _reverse + ".ip6.arpa" end @@ -377,7 +368,7 @@ def ip6_arpa # Returns a string for DNS reverse lookup compatible with RFC1886. def ip6_int if !ipv6? - raise InvalidAddressError, "not an IPv6 address" + raise InvalidAddressError, "not an IPv6 address: #{@addr}" end return _reverse + ".ip6.int" end @@ -404,7 +395,7 @@ def eql?(other) # Returns a hash value used by Hash, Set, and Array classes def hash - return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1) + return ([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1) end # Creates a Range object for the network address. @@ -420,7 +411,7 @@ def to_range raise AddressFamilyError, "unsupported address family" end - return clone.set(begin_addr, @family)..clone.set(end_addr, @family) + self.class.new(begin_addr, @family)..self.class.new(end_addr, @family) end # Returns the prefix length in bits for the ipaddr. @@ -448,7 +439,7 @@ def prefix=(prefix) when Integer mask!(prefix) else - raise InvalidPrefixError, "prefix must be an integer" + raise InvalidPrefixError, "prefix must be an integer: #{@addr}" end end @@ -460,11 +451,42 @@ def inspect af = "IPv4" when Socket::AF_INET6 af = "IPv6" + zone_id = @zone_id.to_s else raise AddressFamilyError, "unsupported address family" end - return sprintf("#<%s: %s:%s/%s>", self.class.name, - af, _to_string(@addr), _to_string(@mask_addr)) + return sprintf("#<%s: %s:%s%s/%s>", self.class.name, + af, _to_string(@addr), zone_id, _to_string(@mask_addr)) + end + + # Returns the netmask in string format e.g. 255.255.0.0 + def netmask + _to_string(@mask_addr) + end + + # Returns the IPv6 zone identifier, if present. + # Raises InvalidAddressError if not an IPv6 address. + def zone_id + if @family == Socket::AF_INET6 + @zone_id + else + raise InvalidAddressError, "not an IPv6 address" + end + end + + # Returns the IPv6 zone identifier, if present. + # Raises InvalidAddressError if not an IPv6 address. + def zone_id=(zid) + if @family == Socket::AF_INET6 + case zid + when nil, /\A%(\w+)\z/ + @zone_id = zid + else + raise InvalidAddressError, "invalid zone identifier for address" + end + else + raise InvalidAddressError, "not an IPv6 address" + end end protected @@ -476,11 +498,11 @@ def set(addr, *family) case family[0] ? family[0] : @family when Socket::AF_INET if addr < 0 || addr > IN4MASK - raise InvalidAddressError, "invalid address" + raise InvalidAddressError, "invalid address: #{@addr}" end when Socket::AF_INET6 if addr < 0 || addr > IN6MASK - raise InvalidAddressError, "invalid address" + raise InvalidAddressError, "invalid address: #{@addr}" end else raise AddressFamilyError, "unsupported address family" @@ -488,6 +510,9 @@ def set(addr, *family) @addr = addr if family[0] @family = family[0] + if @family == Socket::AF_INET + @mask_addr &= IN4MASK + end end return self end @@ -496,17 +521,20 @@ def set(addr, *family) def mask!(mask) case mask when String - if mask =~ /\A\d+\z/ + case mask + when /\A(0|[1-9]+\d*)\z/ prefixlen = mask.to_i + when /\A\d+\z/ + raise InvalidPrefixError, "leading zeros in prefix" else m = IPAddr.new(mask) if m.family != @family - raise InvalidPrefixError, "address family is not same" + raise InvalidPrefixError, "address family is not same: #{@addr}" 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}" + raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}" end @addr &= @mask_addr return self @@ -517,13 +545,13 @@ def mask!(mask) case @family when Socket::AF_INET if prefixlen < 0 || prefixlen > 32 - raise InvalidPrefixError, "invalid length" + raise InvalidPrefixError, "invalid length: #{@addr}" end masklen = 32 - prefixlen @mask_addr = ((IN4MASK >> masklen) << masklen) when Socket::AF_INET6 if prefixlen < 0 || prefixlen > 128 - raise InvalidPrefixError, "invalid length" + raise InvalidPrefixError, "invalid length: #{@addr}" end masklen = 128 - prefixlen @mask_addr = ((IN6MASK >> masklen) << masklen) @@ -555,6 +583,7 @@ def mask!(mask) # those, such as &, |, include? and ==, accept a string, or a packed # in_addr value instead of an IPAddr object. def initialize(addr = '::', family = Socket::AF_UNSPEC) + @mask_addr = nil if !addr.kind_of?(String) case family when Socket::AF_INET, Socket::AF_INET6 @@ -567,11 +596,16 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC) raise AddressFamilyError, "unsupported address family: #{family}" end end - prefix, prefixlen = addr.split('/') + prefix, prefixlen = addr.split('/', 2) if prefix =~ /\A\[(.*)\]\z/i prefix = $1 family = Socket::AF_INET6 end + if prefix =~ /\A(.*)(%\w+)\z/ + prefix = $1 + zone_id = $2 + family = Socket::AF_INET6 + end # It seems AI_NUMERICHOST doesn't do the job. #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil, # Socket::AI_NUMERICHOST) @@ -586,6 +620,7 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC) @addr = in6_addr(prefix) @family = Socket::AF_INET6 end + @zone_id = zone_id if family != Socket::AF_UNSPEC && @family != family raise AddressFamilyError, "address family mismatch" end @@ -594,8 +629,6 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC) else @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK end - rescue InvalidAddressError => e - raise e.class, "#{e.message}: #{addr}" end def coerce_other(other) @@ -618,8 +651,8 @@ def in_addr(addr) octets = m.captures end octets.inject(0) { |i, s| - (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address" - s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous" + (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}" i << 8 | n } end @@ -636,19 +669,19 @@ def in6_addr(left) right = '' when RE_IPV6ADDRLIKE_COMPRESSED if $4 - left.count(':') <= 6 or raise InvalidAddressError, "invalid address" + left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{@addr}" addr = in_addr($~[4,4]) left = $1 right = $3 + '0:0' else left.count(':') <= ($1.empty? || $2.empty? ? 8 : 7) or - raise InvalidAddressError, "invalid address" + raise InvalidAddressError, "invalid address: #{@addr}" left = $1 right = $2 addr = 0 end else - raise InvalidAddressError, "invalid address" + raise InvalidAddressError, "invalid address: #{@addr}" end l = left.split(':') r = right.split(':') diff --git a/ruby/lib/irb.rb b/ruby/lib/irb.rb index ee6979c6d..6887d5596 100644 --- a/ruby/lib/irb.rb +++ b/ruby/lib/irb.rb @@ -10,18 +10,19 @@ # # require "ripper" +require "reline" -require "irb/init" -require "irb/context" -require "irb/extend-command" +require_relative "irb/init" +require_relative "irb/context" +require_relative "irb/extend-command" -require "irb/ruby-lex" -require "irb/input-method" -require "irb/locale" -require "irb/color" +require_relative "irb/ruby-lex" +require_relative "irb/input-method" +require_relative "irb/locale" +require_relative "irb/color" -require "irb/version" -require "irb/easter-egg" +require_relative "irb/version" +require_relative "irb/easter-egg" # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby # expressions read from the standard input. @@ -59,7 +60,18 @@ # -E enc Same as `ruby -E` # -w Same as `ruby -w` # -W[level=2] Same as `ruby -W` -# --inspect Use `inspect' for output (default except for bc mode) +# --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 # --nomultiline Don't use multiline editor module @@ -67,19 +79,26 @@ # --nosingleline Don't use singleline editor module # --colorize Use colorization # --nocolorize Don't use colorization -# --prompt prompt-mode -# --prompt-mode prompt-mode +# --autocomplete Use autocompletion +# --noautocomplete Don't use autocompletion +# --prompt prompt-mode/--prompt-mode prompt-mode # Switch prompt mode. Pre-defined prompt modes are # `default', `simple', `xmp' and `inf-ruby' # --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. # Suppresses --multiline and --singleline. -# --simple-prompt Simple prompt mode +# --sample-book-mode/--simple-prompt +# Simple prompt mode # --noprompt No prompt mode +# --single-irb Share self with sub-irb. # --tracer Display trace for each execution of commands. # --back-trace-limit n # Display backtrace top n and tail n. The default # value is 16. -# -v, --version Print the version of irb +# --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 # # == Configuration # @@ -104,6 +123,7 @@ # 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 @@ -271,7 +291,7 @@ # 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 +# 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. # @@ -399,7 +419,7 @@ def IRB.start(ap_path = nil) irb.run(@CONF) end - # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits. + # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits. def IRB.irb_at_exit @CONF[:AT_EXIT].each{|hook| hook.call} end @@ -462,7 +482,7 @@ def run(conf = IRB.conf) conf[:IRB_RC].call(context) if conf[:IRB_RC] conf[:MAIN_CONTEXT] = context - trap("SIGINT") do + prev_trap = trap("SIGINT") do signal_handle end @@ -471,6 +491,7 @@ def run(conf = IRB.conf) eval_input end ensure + trap("SIGINT", prev_trap) conf[:AT_EXIT].each{|hook| hook.call} end end @@ -513,7 +534,7 @@ def eval_input @context.io.prompt end - @scanner.set_input(@context.io) do + @scanner.set_input(@context.io, context: @context) do signal_status(:IN_INPUT) do if l = @context.io.gets print l if @context.verbose? @@ -524,7 +545,7 @@ def eval_input printf "Use \"exit\" to leave %s\n", @context.ap_name end else - print "\n" + print "\n" if @context.prompting? end end l @@ -537,8 +558,33 @@ def eval_input signal_status(:IN_EVAL) do begin line.untaint if RUBY_VERSION < '2.7' - @context.evaluate(line, line_no, exception: exc) - output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line)) + if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty? + IRB.set_measure_callback + end + if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty? + result = nil + last_proc = proc{ result = @context.evaluate(line, line_no, exception: exc) } + IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) { |chain, item| + _name, callback, arg = item + proc { + callback.(@context, line, line_no, arg, exception: exc) do + chain.call + end + } + }.call + @context.set_last_value(result) + else + @context.evaluate(line, line_no, exception: exc) + end + if @context.echo? + if assignment_expression?(line) + if @context.echo_on_assignment? + output_value(@context.echo_on_assignment? == :truncate) + end + else + output_value + end + end rescue Interrupt => exc rescue SystemExit, SignalException raise @@ -548,10 +594,41 @@ def eval_input next end handle_exception(exc) + @context.workspace.local_variable_set(:_, exc) + exc = nil 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) @@ -561,49 +638,47 @@ def handle_exception(exc) irb_bug = false end - if STDOUT.tty? - attr = ATTR_TTY - print "#{attr[1]}Traceback#{attr[]} (most recent call last):\n" - else - attr = ATTR_PLAIN - end - messages = [] - lasts = [] - levels = 0 if exc.backtrace - count = 0 - exc.backtrace.each do |m| - m = @context.workspace.filter_backtrace(m) or next unless irb_bug - count += 1 - if attr == ATTR_TTY - m = sprintf("%9d: from %s", count, m) + order = nil + if '2.5.0' == RUBY_VERSION + # Exception#full_message doesn't have keyword arguments. + message = exc.full_message # the same of (highlight: true, order: bottom) + order = :bottom + elsif '2.5.1' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' + if STDOUT.tty? + message = exc.full_message(order: :bottom) + order = :bottom else - m = "\tfrom #{m}" - end - if messages.size < @context.back_trace_limit - messages.push(m) - elsif lasts.size < @context.back_trace_limit - lasts.push(m).shift - levels += 1 + message = exc.full_message(order: :top) + order = :top end + else # '3.0.0' <= RUBY_VERSION + message = exc.full_message(order: :top) + order = :top end - end - if attr == ATTR_TTY - unless lasts.empty? - puts lasts.reverse - printf "... %d levels...\n", levels if levels > 0 - end - puts messages.reverse - end - m = exc.to_s.split(/\n/) - print "#{attr[1]}#{exc.class} (#{attr[4]}#{m.shift}#{attr[0, 1]})#{attr[]}\n" - puts m.map {|s| "#{attr[1]}#{s}#{attr[]}\n"} - if attr == ATTR_PLAIN - puts messages - unless lasts.empty? - puts lasts - printf "... %d levels...\n", levels if levels > 0 - 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 @@ -737,9 +812,35 @@ def prompt(prompt, ltype, indent, line_no) # :nodoc: p end - def output_value # :nodoc: + 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 @context.use_colorize + multiline_p = false + else + str = str.gsub(/(\A.*?\n).*/m, "\\1...") + str += "\e[0m" if @context.use_colorize + 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 @context.use_colorize + end + end + end if multiline_p && @context.newline_before_multiline_output? printf @context.return_format, "\n#{str}" else @@ -770,7 +871,7 @@ def assignment_expression?(line) # 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 selement of the top level array is 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 diff --git a/ruby/lib/irb/cmd/fork.rb b/ruby/lib/irb/cmd/fork.rb index 31d53dcab..7566d10be 100644 --- a/ruby/lib/irb/cmd/fork.rb +++ b/ruby/lib/irb/cmd/fork.rb @@ -16,7 +16,7 @@ module IRB module ExtendCommand class Fork < Nop def execute - pid = send ExtendCommand.irb_original_method_name("fork") + pid = __send__ ExtendCommand.irb_original_method_name("fork") unless pid class << self alias_method :exit, ExtendCommand.irb_original_method_name('exit') @@ -35,5 +35,3 @@ class << self end end # :startdoc: - - diff --git a/ruby/lib/irb/cmd/help.rb b/ruby/lib/irb/cmd/help.rb index 0629479e9..d82e78fb5 100644 --- a/ruby/lib/irb/cmd/help.rb +++ b/ruby/lib/irb/cmd/help.rb @@ -17,7 +17,8 @@ module ExtendCommand class Help < Nop def execute(*names) require 'rdoc/ri/driver' - IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new) + opts = RDoc::RI::Driver.process_args([]) + IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new(opts)) rescue LoadError, SystemExit IRB::ExtendCommand::Help.remove_method(:execute) # raise NoMethodError in ensure diff --git a/ruby/lib/irb/cmd/info.rb b/ruby/lib/irb/cmd/info.rb new file mode 100644 index 000000000..dd93352ff --- /dev/null +++ b/ruby/lib/irb/cmd/info.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: false + +require_relative "nop" + +# :stopdoc: +module IRB + module ExtendCommand + class Info < Nop + def execute + Class.new { + def inspect + 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 + str + end + alias_method :to_s, :inspect + }.new + end + end + end +end +# :startdoc: diff --git a/ruby/lib/irb/cmd/ls.rb b/ruby/lib/irb/cmd/ls.rb new file mode 100644 index 000000000..cbbf96210 --- /dev/null +++ b/ruby/lib/irb/cmd/ls.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require "reline" +require_relative "nop" +require_relative "../color" + +# :stopdoc: +module IRB + module ExtendCommand + class Ls < Nop + 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) + end + + def dump_methods(o, klass, obj) + singleton_class = begin obj.singleton_class; rescue TypeError; nil end + maps = class_method_map((singleton_class || klass).ancestors) + 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 = Array.new + classes.reject { |mod| mod >= Object }.map do |mod| + methods = mod.public_instance_methods(false).select do |m| + dumped.push(m) unless dumped.include?(m) + end + [mod, methods] + end.reverse + end + + class Output + MARGIN = " " + + def initialize(grep: nil) + @grep = grep + @line_width = screen_width - MARGIN.length # right padding + end + + def dump(name, strs) + strs = strs.grep(@grep) if @grep + strs = strs.sort + return if strs.empty? + + # Attempt a single line + print "#{Color.colorize(name, [:BOLD, :BLUE])}: " + if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length) + puts strs.join(MARGIN) + return + end + 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| + 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 +end +# :startdoc: diff --git a/ruby/lib/irb/cmd/measure.rb b/ruby/lib/irb/cmd/measure.rb new file mode 100644 index 000000000..adea540e9 --- /dev/null +++ b/ruby/lib/irb/cmd/measure.rb @@ -0,0 +1,43 @@ +require_relative "nop" + +# :stopdoc: +module IRB + module ExtendCommand + class Measure < Nop + 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 +end +# :startdoc: diff --git a/ruby/lib/irb/cmd/nop.rb b/ruby/lib/irb/cmd/nop.rb index 9cf4337c2..d6f7a611a 100644 --- a/ruby/lib/irb/cmd/nop.rb +++ b/ruby/lib/irb/cmd/nop.rb @@ -14,10 +14,16 @@ module IRB module ExtendCommand class Nop - - def self.execute(conf, *opts) - command = new(conf) - command.execute(*opts) + if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0" + def self.execute(conf, *opts, **kwargs, &block) + command = new(conf) + command.execute(*opts, **kwargs, &block) + end + else + def self.execute(conf, *opts, &block) + command = new(conf) + command.execute(*opts, &block) + end end def initialize(conf) diff --git a/ruby/lib/irb/cmd/pushws.rb b/ruby/lib/irb/cmd/pushws.rb index 187b276e4..612157d8a 100644 --- a/ruby/lib/irb/cmd/pushws.rb +++ b/ruby/lib/irb/cmd/pushws.rb @@ -38,4 +38,3 @@ def execute(*obj) end end # :startdoc: - diff --git a/ruby/lib/irb/cmd/show_source.rb b/ruby/lib/irb/cmd/show_source.rb new file mode 100644 index 000000000..8f203ef12 --- /dev/null +++ b/ruby/lib/irb/cmd/show_source.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require_relative "nop" +require_relative "../color" +require_relative "../ruby-lex" + +# :stopdoc: +module IRB + module ExtendCommand + class ShowSource < Nop + def execute(str = nil) + unless str.is_a?(String) + puts "Error: Expected a string but got #{str.inspect}" + return + end + source = find_source(str) + if source && File.exist?(source.file) + show_source(source) + else + puts "Error: Couldn't locate a definition for #{str}" + end + nil + end + + private + + # @param [IRB::ExtendCommand::ShowSource::Source] source + 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 find_source(str) + case str + when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name + eval(str, irb_context.workspace.binding) # trigger autoload + base = irb_context.workspace.binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object } + file, line = base.const_source_location(str) if base.respond_to?(:const_source_location) # Ruby 2.7+ + when /\A(?[A-Z]\w*(::[A-Z]\w*)*)#(?[^ :.]+)\z/ # Class#method + owner = eval(Regexp.last_match[:owner], irb_context.workspace.binding) + method = Regexp.last_match[:method] + if owner.respond_to?(:instance_method) && owner.instance_methods.include?(method.to_sym) + file, line = owner.instance_method(method).source_location + end + when /\A((?.+)(\.|::))?(?[^ :.]+)\z/ # method, receiver.method, receiver::method + receiver = eval(Regexp.last_match[:receiver] || 'self', irb_context.workspace.binding) + method = Regexp.last_match[:method] + file, line = receiver.method(method).source_location if receiver.respond_to?(method) + end + if file && line + Source.new(file: file, first_line: line, last_line: find_end(file, line)) + end + end + + def find_end(file, first_line) + return first_line unless File.exist?(file) + lex = RubyLex.new + 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.process_continue(prev_tokens) + code_block_open = lex.check_code_block(code, prev_tokens) + if !continue && !code_block_open + return first_line + lnum + end + end + first_line + end + + def bold(str) + Color.colorize(str, [:BOLD]) + end + + 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 + end + end +end +# :startdoc: diff --git a/ruby/lib/irb/cmd/whereami.rb b/ruby/lib/irb/cmd/whereami.rb new file mode 100644 index 000000000..b3def11b9 --- /dev/null +++ b/ruby/lib/irb/cmd/whereami.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require_relative "nop" + +# :stopdoc: +module IRB + module ExtendCommand + class Whereami < Nop + 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 +end +# :startdoc: diff --git a/ruby/lib/irb/color.rb b/ruby/lib/irb/color.rb index d2b9674a7..40e9e04c9 100644 --- a/ruby/lib/irb/color.rb +++ b/ruby/lib/irb/color.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'reline' require 'ripper' +require 'irb/ruby-lex' module IRB # :nodoc: module Color @@ -16,7 +17,7 @@ module Color CYAN = 36 TOKEN_KEYWORDS = { - on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__'], + on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__', '__ENCODING__'], on_const: ['ENV'], } private_constant :TOKEN_KEYWORDS @@ -59,6 +60,11 @@ module Color 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 @@ -66,9 +72,12 @@ module Color 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? - $stdout.tty? && supported? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb')) + $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb')) end def inspect_colorable?(obj, seen: {}.compare_by_identity) @@ -92,43 +101,50 @@ def inspect_colorable?(obj, seen: {}.compare_by_identity) end end - def clear - return '' unless colorable? + def clear(colorable: colorable?) + return '' unless colorable "\e[#{CLEAR}m" end - def colorize(text, seq) - return text unless colorable? + def colorize(text, seq, colorable: colorable?) + return text unless colorable seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('') - "#{seq}#{text}#{clear}" + "#{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) - return code unless colorable? + def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?) + return code unless colorable symbol_state = SymbolState.new colored = +'' length = 0 + end_seen = false scan(code, allow_last_error: !complete) do |token, str, expr| + # 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) + colored << line.sub(/\Z/, clear(colorable: colorable)) else colored << line end end length += str.bytesize + end_seen = true if token == :on___end__ end # give up colorizing incomplete Ripper tokens - if length != code.bytesize + unless end_seen or length == code.bytesize return Reline::Unicode.escape_for_print(code) end @@ -145,44 +161,41 @@ def without_circular_ref(obj, seen:, &block) seen.delete(obj) end - # Ripper::Lexer::Elem#state is supported on Ruby 2.5+ - def supported? - return @supported if defined?(@supported) - @supported = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0') - end - def scan(code, allow_last_error:) pos = [1, 0] verbose, $VERBOSE = $VERBOSE, nil - lexer = Ripper::Lexer.new(code) - if lexer.respond_to?(:scan) # Ruby 2.7+ - lexer.scan.each do |elem| - str = elem.tok - next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message - next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0 - - str.each_line do |line| - if line.end_with?("\n") - pos[0] += 1 - pos[1] = 0 - else - pos[1] += line.bytesize + RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no| + lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no) + if lexer.respond_to?(:scan) # Ruby 2.7+ + lexer.scan.each do |elem| + str = elem.tok + next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message + next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0 + + str.each_line do |line| + if line.end_with?("\n") + pos[0] += 1 + pos[1] = 0 + else + pos[1] += line.bytesize + end end - end - yield(elem.event, str, elem.state) - end - else - lexer.parse.each do |elem| - yield(elem.event, elem.tok, elem.state) + yield(elem.event, str, elem.state) + end + else + lexer.parse.each do |elem| + yield(elem.event, elem.tok, elem.state) + end end end + ensure $VERBOSE = verbose end def dispatch_seq(token, expr, str, in_symbol:) - if token == :on_parse_error or token == :compile_error + if ERROR_TOKENS.include?(token) TOKEN_SEQ_EXPRS[token][0] elsif in_symbol [YELLOW] diff --git a/ruby/lib/irb/color_printer.rb b/ruby/lib/irb/color_printer.rb new file mode 100644 index 000000000..30c682575 --- /dev/null +++ b/ruby/lib/irb/color_printer.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true +require 'pp' +require 'irb/color' + +module IRB + class ColorPrinter < ::PP + 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 obj.is_a?(String) + # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n" + text(obj.inspect) + else + super + end + end + + def text(str, width = nil) + unless str.is_a?(String) + str = str.inspect + end + width ||= str.length + + case str + 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/ruby/lib/irb/completion.rb b/ruby/lib/irb/completion.rb index c44aa9039..9121174a5 100644 --- a/ruby/lib/irb/completion.rb +++ b/ruby/lib/irb/completion.rb @@ -7,8 +7,7 @@ # From Original Idea of shugo@ruby-lang.org # -require "readline" -autoload :RDoc, "rdoc" +require_relative 'ruby-lex' module IRB module InputCompletor # :nodoc: @@ -39,8 +38,101 @@ def defined? do BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{(" - CompletionProc = proc { |input| - retrieve_completion_data(input).compact.map{ |i| i.encode(Encoding.default_external) } + def self.absolute_path?(p) # TODO Remove this method after 2.6 EOL. + if File.respond_to?(:absolute_path?) + File.absolute_path?(p) + else + if File.absolute_path(p) == p + true + else + false + end + end + end + + def self.retrieve_gem_and_system_load_path + gem_paths = Gem::Specification.latest_specs(true).map { |s| + s.require_paths.map { |p| + if absolute_path?(p) + p + else + File.join(s.full_gem_path, p) + end + } + }.flatten if defined?(Gem::Specification) + (gem_paths.to_a | $LOAD_PATH).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) @@ -48,7 +140,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^((["'`]).*\2)\.([^.]*)$/ # String receiver = $1 - message = Regexp.quote($3) + message = $3 candidates = String.instance_methods.collect{|m| m.to_s} if doc_namespace @@ -60,7 +152,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp receiver = $1 - message = Regexp.quote($2) + message = $2 candidates = Regexp.instance_methods.collect{|m| m.to_s} if doc_namespace @@ -72,7 +164,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^([^\]]*\])\.([^.]*)$/ # Array receiver = $1 - message = Regexp.quote($2) + message = $2 candidates = Array.instance_methods.collect{|m| m.to_s} if doc_namespace @@ -84,7 +176,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash receiver = $1 - message = Regexp.quote($2) + message = $2 proc_candidates = Proc.instance_methods.collect{|m| m.to_s} hash_candidates = Hash.instance_methods.collect{|m| m.to_s} @@ -97,19 +189,15 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^(:[^:.]*)$/ # Symbol return nil if doc_namespace - if Symbol.respond_to?(:all_symbols) - sym = $1 - candidates = Symbol.all_symbols.collect do |s| - ":" + s.id2name.encode(Encoding.default_external) - rescue Encoding::UndefinedConversionError - # ignore - end - candidates.grep(/^#{Regexp.quote(sym)}/) - else - [] + sym = $1 + candidates = Symbol.all_symbols.collect do |s| + ":" + s.id2name.encode(Encoding.default_external) + rescue EncodingError + # ignore end + candidates.grep(/^#{Regexp.quote(sym)}/) - when /^::([A-Z][^:\.\(]*)$/ + when /^::([A-Z][^:\.\(\)]*)$/ # Absolute Constant or class methods receiver = $1 candidates = Object.constants.collect{|m| m.to_s} @@ -122,7 +210,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace when /^([A-Z].*)::([^:.]*)$/ # Constant or class methods receiver = $1 - message = Regexp.quote($2) + message = $2 begin candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) @@ -139,7 +227,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # Symbol receiver = $1 sep = $2 - message = Regexp.quote($3) + message = $3 candidates = Symbol.instance_methods.collect{|m| m.to_s} if doc_namespace @@ -152,7 +240,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # Numeric receiver = $~[:num] sep = $~[:sep] - message = Regexp.quote($~[:mes]) + message = $~[:mes] begin instance = eval(receiver, bind) @@ -174,7 +262,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # Numeric(0xFFFF) receiver = $1 sep = $2 - message = Regexp.quote($3) + message = $3 begin instance = eval(receiver, bind) @@ -202,11 +290,11 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace all_gvars.grep(Regexp.new(Regexp.quote(gvar))) end - when /^([^."].*)(\.|::)([^.]*)$/ + when /^([^.:"].*)(\.|::)([^.]*)$/ # variable.func or func.func receiver = $1 sep = $2 - message = Regexp.quote($3) + message = $3 gv = eval("global_variables", bind).collect{|m| m.to_s}.push("true", "false", "nil") lv = eval("local_variables", bind).collect{|m| m.to_s} @@ -240,7 +328,8 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace candidates.uniq! end if doc_namespace - "#{rec.class.name}#{sep}#{candidates.find{ |i| i == message }}" + 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 @@ -249,7 +338,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # unknown(maybe String) receiver = "" - message = Regexp.quote($1) + message = $1 candidates = String.instance_methods(true).collect{|m| m.to_s} if doc_namespace @@ -259,25 +348,41 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace end else - candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s} - candidates |= ReservedWords - if doc_namespace - candidates.find{ |i| i == input } + vars = eval("local_variables | instance_variables", bind).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 = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s} + candidates |= ReservedWords + candidates.find{ |i| i == input } + end else + candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s} + candidates |= ReservedWords candidates.grep(/^#{Regexp.quote(input)}/) 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) + 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| @@ -299,7 +404,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~] def self.select_message(receiver, message, candidates, sep = ".") - candidates.grep(/^#{message}/).collect do |e| + candidates.grep(/^#{Regexp.quote(message)}/).collect do |e| case e when /^[a-zA-Z_]/ receiver + sep + e diff --git a/ruby/lib/irb/context.rb b/ruby/lib/irb/context.rb index 218f7c603..0a46c1b1d 100644 --- a/ruby/lib/irb/context.rb +++ b/ruby/lib/irb/context.rb @@ -54,6 +54,7 @@ def initialize(irb, workspace = nil, input_method = nil) @use_multiline = nil end @use_colorize = IRB.conf[:USE_COLORIZE] + @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE] @verbose = IRB.conf[:VERBOSE] @io = nil @@ -124,6 +125,8 @@ def initialize(irb, workspace = nil, input_method = nil) end self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY] + @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS] + @echo = IRB.conf[:ECHO] if @echo.nil? @echo = true @@ -131,7 +134,7 @@ def initialize(irb, workspace = nil, input_method = nil) @echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT] if @echo_on_assignment.nil? - @echo_on_assignment = false + @echo_on_assignment = :truncate end @newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] @@ -147,18 +150,18 @@ def main # The toplevel workspace, see #home_workspace attr_reader :workspace_home - # WorkSpace in the current context + # WorkSpace in the current context. attr_accessor :workspace - # The current thread in this context + # The current thread in this context. attr_reader :thread - # The current input method + # The current input method. # # Can be either StdioInputMethod, ReadlineInputMethod, # ReidlineInputMethod, FileInputMethod or other specified when the # context is created. See ::new for more # information on +input_method+. attr_accessor :io - # Current irb session + # Current irb session. attr_accessor :irb # A copy of the default IRB.conf[:AP_NAME] attr_accessor :ap_name @@ -185,20 +188,22 @@ def main # # A copy of the default IRB.conf[:USE_COLORIZE] attr_reader :use_colorize + # 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 + # Standard IRB prompt. # # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_i - # IRB prompt for continuated strings + # 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+) + # IRB prompt for continuated statement. (e.g. immediately after an +if+) # # See IRB@Customizing+the+IRB+Prompt for more information. attr_accessor :prompt_c @@ -238,9 +243,12 @@ def main # # 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+. + # Uses IRB.conf[:ECHO] if available, or defaults to +true+. # # puts "hello" # # hello @@ -249,18 +257,44 @@ def main # puts "omg" # # omg attr_accessor :echo - # Whether to echo for assignment expressions + # Whether to echo for assignment expressions. # - # Uses IRB.conf[:ECHO_ON_ASSIGNMENT] if available, or defaults to +false+. + # 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" - # IRB.CurrentContext.echo_on_assignment = true # 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, + # Uses IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] if available, # or defaults to +true+. # # "abc\ndef" @@ -300,6 +334,8 @@ def main alias use_readline? use_singleline # Alias for #use_colorize alias use_colorize? use_colorize + # Alias for #use_autocomplete + alias use_autocomplete? use_autocomplete # Alias for #rc alias rc? rc alias ignore_sigint? ignore_sigint @@ -355,6 +391,7 @@ def prompt_mode=(mode) @prompt_c = pconf[:PROMPT_C] @prompt_n = pconf[:PROMPT_N] @return_format = pconf[:RETURN] + @return_format = "%s\n" if @return_format == nil if ai = pconf.include?(:AUTO_INDENT) @auto_indent_mode = ai else @@ -447,6 +484,8 @@ def inspect_last_value # :nodoc: # 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: diff --git a/ruby/lib/irb/easter-egg.rb b/ruby/lib/irb/easter-egg.rb index 64869d85f..3e79692de 100644 --- a/ruby/lib/irb/easter-egg.rb +++ b/ruby/lib/irb/easter-egg.rb @@ -126,6 +126,7 @@ def render_frame(i) print "\e[H" + buff sleep 0.05 end + rescue Interrupt ensure print "\e[0m\e[?1049l" end @@ -134,4 +135,4 @@ def render_frame(i) end end -IRB.send(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__ +IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__ diff --git a/ruby/lib/irb/ext/change-ws.rb b/ruby/lib/irb/ext/change-ws.rb index 94bfe62bc..4c57e44ea 100644 --- a/ruby/lib/irb/ext/change-ws.rb +++ b/ruby/lib/irb/ext/change-ws.rb @@ -43,4 +43,3 @@ def change_workspace(*_main) end end end - diff --git a/ruby/lib/irb/ext/history.rb b/ruby/lib/irb/ext/history.rb index 30e3fb901..fc304c6f6 100644 --- a/ruby/lib/irb/ext/history.rb +++ b/ruby/lib/irb/ext/history.rb @@ -153,5 +153,3 @@ def inspect # :nodoc: end end end - - diff --git a/ruby/lib/irb/ext/loader.rb b/ruby/lib/irb/ext/loader.rb index 840226db3..af028996e 100644 --- a/ruby/lib/irb/ext/loader.rb +++ b/ruby/lib/irb/ext/loader.rb @@ -31,8 +31,31 @@ def irb_load(fn, priv = nil) load_file(path, priv) end + if File.respond_to?(:absolute_path?) + def absolute_path?(path) + File.absolute_path?(path) + end + else + separator = + if File::ALT_SEPARATOR + "[#{Regexp.quote(File::SEPARATOR + File::ALT_SEPARATOR)}]" + else + File::SEPARATOR + end + ABSOLUTE_PATH_PATTERN = # :nodoc: + case Dir.pwd + when /\A\w:/, /\A#{separator}{2}/ + /\A(?:\w:|#{separator})#{separator}/ + else + /\A#{separator}/ + end + def absolute_path?(path) + ABSOLUTE_PATH_PATTERN =~ path + end + end + def search_file_from_ruby_path(fn) # :nodoc: - if /^#{Regexp.quote(File::Separator)}/ =~ fn + if absolute_path?(fn) return fn if File.exist?(fn) return nil end @@ -50,16 +73,18 @@ def search_file_from_ruby_path(fn) # :nodoc: # See Irb#suspend_input_method for more information. def source_file(path) irb.suspend_name(path, File.basename(path)) do - irb.suspend_input_method(FileInputMethod.new(path)) do - |back_io| - irb.signal_status(:IN_LOAD) do - if back_io.kind_of?(FileInputMethod) - irb.eval_input - else - begin + 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 - rescue LoadAbort - print "load abort!!\n" + else + begin + irb.eval_input + rescue LoadAbort + print "load abort!!\n" + end end end end @@ -79,16 +104,18 @@ def load_file(path, priv = nil) ws = WorkSpace.new end irb.suspend_workspace(ws) do - irb.suspend_input_method(FileInputMethod.new(path)) do - |back_io| - irb.signal_status(:IN_LOAD) do - if back_io.kind_of?(FileInputMethod) - irb.eval_input - else - begin + 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 - rescue LoadAbort - print "load abort!!\n" + else + begin + irb.eval_input + rescue LoadAbort + print "load abort!!\n" + end end end end @@ -126,4 +153,3 @@ def old # :nodoc: end end end - diff --git a/ruby/lib/irb/ext/save-history.rb b/ruby/lib/irb/ext/save-history.rb index edc4f234c..7acaebe36 100644 --- a/ruby/lib/irb/ext/save-history.rb +++ b/ruby/lib/irb/ext/save-history.rb @@ -9,8 +9,6 @@ # # -require "readline" - module IRB module HistorySavingAbility # :nodoc: end @@ -27,7 +25,7 @@ def save_history IRB.conf[:SAVE_HISTORY] end - remove_method :save_history= if method_defined?(:save_history=) + remove_method(:save_history=) if method_defined?(:save_history=) # Sets IRB.conf[:SAVE_HISTORY] to the given +val+ and calls # #init_save_history with this context. # @@ -83,13 +81,15 @@ def load_history end } end + @loaded_history_lines = history.size + @loaded_history_mtime = File.mtime(history_file) end end def save_history return unless self.class.const_defined?(:HISTORY) history = self.class::HISTORY - if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0 + 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 @@ -107,9 +107,22 @@ def save_history raise end - open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f| + if File.exist?(history_file) && @loaded_history_mtime && + File.mtime(history_file) != @loaded_history_mtime + history = history[@loaded_history_lines..-1] + append_history = true + end + + open(history_file, "#{append_history ? 'a' : 'w'}:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f| hist = history.map{ |l| l.split("\n").join("\\\n") } - f.puts(hist[-num..-1] || hist) + 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 diff --git a/ruby/lib/irb/ext/tracer.rb b/ruby/lib/irb/ext/tracer.rb index e3e325e6e..67ac4bb96 100644 --- a/ruby/lib/irb/ext/tracer.rb +++ b/ruby/lib/irb/ext/tracer.rb @@ -82,4 +82,3 @@ def evaluate(context, statements, file = nil, line = nil) IRB.initialize_tracer end - diff --git a/ruby/lib/irb/ext/use-loader.rb b/ruby/lib/irb/ext/use-loader.rb index cb10e8a25..1897bc89e 100644 --- a/ruby/lib/irb/ext/use-loader.rb +++ b/ruby/lib/irb/ext/use-loader.rb @@ -47,7 +47,7 @@ def use_loader alias use_loader? use_loader remove_method :use_loader= if method_defined?(:use_loader=) - # Sets IRB.conf[:USE_LOADER] + # Sets IRB.conf[:USE_LOADER] # # See #use_loader for more information. def use_loader=(opt) @@ -73,5 +73,3 @@ def use_loader=(opt) end end end - - diff --git a/ruby/lib/irb/ext/workspaces.rb b/ruby/lib/irb/ext/workspaces.rb index 5bd72c194..730b58e64 100644 --- a/ruby/lib/irb/ext/workspaces.rb +++ b/ruby/lib/irb/ext/workspaces.rb @@ -64,4 +64,3 @@ def pop_workspace end end end - diff --git a/ruby/lib/irb/extend-command.rb b/ruby/lib/irb/extend-command.rb index de145e962..339e9e608 100644 --- a/ruby/lib/irb/extend-command.rb +++ b/ruby/lib/irb/extend-command.rb @@ -121,6 +121,30 @@ def irb_context [:help, NO_OVERRIDE], ], + [ + :irb_info, :Info, "irb/cmd/info" + ], + + [ + :irb_ls, :Ls, "irb/cmd/ls", + [:ls, NO_OVERRIDE], + ], + + [ + :irb_measure, :Measure, "irb/cmd/measure", + [:measure, NO_OVERRIDE], + ], + + [ + :irb_show_source, :ShowSource, "irb/cmd/show_source", + [:show_source, NO_OVERRIDE], + ], + + [ + :irb_whereami, :Whereami, "irb/cmd/whereami", + [:whereami, NO_OVERRIDE], + ], + ] # Installs the default irb commands: @@ -160,20 +184,24 @@ def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases) end if load_file + kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0" line = __LINE__; eval %[ - def #{cmd_name}(*opts, &b) + def #{cmd_name}(*opts#{kwargs}, &b) require "#{load_file}" arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s } - args << "*opts" if arity < 0 + args << "*opts#{kwargs}" if arity < 0 args << "&block" args = args.join(", ") line = __LINE__; eval %[ - def #{cmd_name}(\#{args}) - ExtendCommand::#{cmd_class}.execute(irb_context, \#{args}) + unless singleton_class.class_variable_defined?(:@@#{cmd_name}_) + singleton_class.class_variable_set(:@@#{cmd_name}_, true) + def self.#{cmd_name}_(\#{args}) + ExtendCommand::#{cmd_class}.execute(irb_context, \#{args}) + end end ], nil, __FILE__, line - send :#{cmd_name}, *opts, &b + __send__ :#{cmd_name}_, *opts#{kwargs}, &b end ], nil, __FILE__, line else @@ -261,7 +289,7 @@ def self.def_extend_command(cmd_name, load_file, *aliases) def #{cmd_name}(*opts, &b) Context.module_eval {remove_method(:#{cmd_name})} require "#{load_file}" - send :#{cmd_name}, *opts, &b + __send__ :#{cmd_name}, *opts, &b end for ali in aliases alias_method ali, cmd_name @@ -284,8 +312,8 @@ def def_pre_proc(base_method, extend_method) module_eval %[ alias_method alias_name, base_method def #{base_method}(*opts) - send :#{extend_method}, *opts - send :#{alias_name}, *opts + __send__ :#{extend_method}, *opts + __send__ :#{alias_name}, *opts end ] end @@ -300,8 +328,8 @@ def def_post_proc(base_method, extend_method) module_eval %[ alias_method alias_name, base_method def #{base_method}(*opts) - send :#{alias_name}, *opts - send :#{extend_method}, *opts + __send__ :#{alias_name}, *opts + __send__ :#{extend_method}, *opts end ] end diff --git a/ruby/lib/irb/help.rb b/ruby/lib/irb/help.rb index 7868a70a6..3eeaf841b 100644 --- a/ruby/lib/irb/help.rb +++ b/ruby/lib/irb/help.rb @@ -34,4 +34,3 @@ def IRB.print_usage } end end - diff --git a/ruby/lib/irb/init.rb b/ruby/lib/irb/init.rb index 37d1f8d60..d2baee201 100644 --- a/ruby/lib/irb/init.rb +++ b/ruby/lib/irb/init.rb @@ -44,12 +44,14 @@ def IRB.init_config(ap_path) @CONF[:IRB_RC] = nil @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod) - @CONF[:USE_COLORIZE] = true + @CONF[:USE_COLORIZE] = !ENV['NO_COLOR'] + @CONF[:USE_AUTOCOMPLETE] = true @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 @@ -108,14 +110,101 @@ def IRB.init_config(ap_path) @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL) @CONF[:AUTO_INDENT] = true - @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING + @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] = [] 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 @@ -131,7 +220,7 @@ def IRB.parse_opts(argv: ::ARGV) $DEBUG = true $VERBOSE = true when "-w" - $VERBOSE = true + Warning[:deprecated] = $VERBOSE = true when /^-W(.+)?/ opt = $1 || argv.shift case opt @@ -140,7 +229,7 @@ def IRB.parse_opts(argv: ::ARGV) when "1" $VERBOSE = false else - $VERBOSE = true + Warning[:deprecated] = $VERBOSE = true end when /^-r(.+)?/ opt = $1 || argv.shift @@ -169,6 +258,9 @@ def IRB.parse_opts(argv: ::ARGV) @CONF[:USE_MULTILINE] = true when "--nomultiline", "--noreidline" @CONF[:USE_MULTILINE] = false + when /^--extra-doc-dir(?:=(.+))?/ + opt = $1 || argv.shift + @CONF[:EXTRA_DOC_DIRS] << opt when "--echo" @CONF[:ECHO] = true when "--noecho" @@ -177,6 +269,8 @@ def IRB.parse_opts(argv: ::ARGV) @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" @@ -185,6 +279,10 @@ def IRB.parse_opts(argv: ::ARGV) @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 @@ -224,11 +322,11 @@ def IRB.parse_opts(argv: ::ARGV) break end end + load_path.collect! do |path| /\A\.\// =~ path ? path : File.expand_path(path) end $LOAD_PATH.unshift(*load_path) - end # running config @@ -271,10 +369,19 @@ 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") + unless File.exist? irb_home + require 'fileutils' + FileUtils.mkdir_p irb_home + end + yield proc{|rc| irb_home + "/irb#{rc}"} + end if home = ENV["HOME"] yield proc{|rc| home+"/.irb#{rc}"} end current_dir = Dir.pwd + yield proc{|rc| current_dir+"/.config/irb/irb#{rc}"} yield proc{|rc| current_dir+"/.irb#{rc}"} yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"} yield proc{|rc| current_dir+"/_irb#{rc}"} diff --git a/ruby/lib/irb/input-method.rb b/ruby/lib/irb/input-method.rb index 9fbbaeb0f..64276e61b 100644 --- a/ruby/lib/irb/input-method.rb +++ b/ruby/lib/irb/input-method.rb @@ -12,7 +12,9 @@ require_relative 'src_encoding' require_relative 'magic-file' require_relative 'completion' +require 'io/console' require 'reline' +require 'rdoc' module IRB STDIN_FILE_NAME = "(line)" # :nodoc: @@ -36,6 +38,14 @@ def gets end public :gets + def winsize + if instance_variable_defined?(:@stdout) + @stdout.winsize + else + [24, 80] + end + end + # Whether this input method is still readable when there is no more data to # read. # @@ -43,6 +53,11 @@ def gets def readable_after_eof? false end + + # For debug message + def inspect + 'Abstract InputMethod' + end end class StdioInputMethod < InputMethod @@ -69,7 +84,14 @@ def gets # # See IO#eof? for more information. def eof? - @stdin.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 @@ -93,14 +115,31 @@ def line(line_no) 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) super @io = IRB::MagicFile.open(file) + @external_encoding = @io.external_encoding end # The file name of this input method, usually given during initialization. attr_reader :file_name @@ -110,7 +149,7 @@ def initialize(file) # # See IO#eof? for more information. def eof? - @io.eof? + @io.closed? || @io.eof? end # Reads the next line from this input method. @@ -123,16 +162,31 @@ def gets # The external encoding for standard input. def encoding - @io.external_encoding + @external_encoding + end + + # For debug message + def inspect + 'FileInputMethod' + end + + def close + @io.close end end begin - require "readline" class ReadlineInputMethod < InputMethod - include Readline + def self.initialize_readline + require "readline" + rescue LoadError + else + include ::Readline + end + # 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 @@ -197,18 +251,21 @@ def encoding @stdin.external_encoding end - if Readline.respond_to?("basic_word_break_characters=") - Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS + # 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 - Readline.completion_append_character = nil - Readline.completion_proc = IRB::InputCompletor::CompletionProc end - rescue LoadError end class ReidlineInputMethod < InputMethod include Reline - # Creates a new input method object using Readline + + # Creates a new input method object using Reline def initialize IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false) super @@ -224,10 +281,11 @@ def initialize Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS end 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:| + proc do |output, complete: | next unless IRB::Color.colorable? IRB::Color.colorize_code(output, complete: complete) end @@ -237,6 +295,10 @@ def initialize end end Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc + Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE] + if IRB.conf[:USE_AUTOCOMPLETE] + Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT) + end end def check_termination(&block) @@ -251,6 +313,99 @@ 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 + message = 'Press Alt+d to read the full document' + contents = [message] + doc.accept(formatter).split("\n") + + y = cursor_pos_to_render.y + 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. @@ -297,5 +452,18 @@ def line(line_no) def encoding @stdin.external_encoding end + + # For debug message + def inspect + config = Reline::Config.new + str = "ReidlineInputMethod with Reline #{Reline::VERSION}" + if config.respond_to?(:inputrc_path) + inputrc_path = File.expand_path(config.inputrc_path) + else + inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc') + end + str += " and #{inputrc_path}" if File.exist?(inputrc_path) + str + end end end diff --git a/ruby/lib/irb/inspector.rb b/ruby/lib/irb/inspector.rb index bc7fb0b12..c2f3b605d 100644 --- a/ruby/lib/irb/inspector.rb +++ b/ruby/lib/irb/inspector.rb @@ -100,28 +100,27 @@ def init # Proc to call when the input is evaluated and output in irb. def inspect_value(v) @inspect.call(v) + rescue + puts "(Object doesn't support #inspect)" + '' end end Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s} - Inspector.def_inspector([true, :p, :inspect]){|v| - begin - result = v.inspect - if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v) - result = Color.colorize_code(result) - end - result - rescue NoMethodError - puts "(Object doesn't support #inspect)" - end - } - Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v| - result = v.pretty_inspect.chomp + Inspector.def_inspector([:p, :inspect]){|v| + result = v.inspect if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v) result = Color.colorize_code(result) end result } + Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require "irb/color_printer"}){|v| + if IRB.conf[:MAIN_CONTEXT]&.use_colorize? + IRB::ColorPrinter.pp(v, '').chomp + else + v.pretty_inspect.chomp + end + } Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v| begin YAML.dump(v) @@ -135,8 +134,3 @@ def inspect_value(v) Marshal.dump(v) } end - - - - - diff --git a/ruby/lib/irb/irb.gemspec b/ruby/lib/irb/irb.gemspec index 658fe813f..26d0fb018 100644 --- a/ruby/lib/irb/irb.gemspec +++ b/ruby/lib/irb/irb.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |spec| 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.files = [ ".document", @@ -28,57 +28,13 @@ Gem::Specification.new do |spec| "doc/irb/irb.rd.ja", "exe/irb", "irb.gemspec", - "lib/irb.rb", - "lib/irb/cmd/chws.rb", - "lib/irb/cmd/fork.rb", - "lib/irb/cmd/help.rb", - "lib/irb/cmd/load.rb", - "lib/irb/cmd/nop.rb", - "lib/irb/cmd/pushws.rb", - "lib/irb/cmd/subirb.rb", - "lib/irb/color.rb", - "lib/irb/completion.rb", - "lib/irb/context.rb", - "lib/irb/easter-egg.rb", - "lib/irb/ext/change-ws.rb", - "lib/irb/ext/history.rb", - "lib/irb/ext/loader.rb", - "lib/irb/ext/multi-irb.rb", - "lib/irb/ext/save-history.rb", - "lib/irb/ext/tracer.rb", - "lib/irb/ext/use-loader.rb", - "lib/irb/ext/workspaces.rb", - "lib/irb/extend-command.rb", - "lib/irb/frame.rb", - "lib/irb/help.rb", - "lib/irb/init.rb", - "lib/irb/input-method.rb", - "lib/irb/inspector.rb", - "lib/irb/lc/error.rb", - "lib/irb/lc/help-message", - "lib/irb/lc/ja/encoding_aliases.rb", - "lib/irb/lc/ja/error.rb", - "lib/irb/lc/ja/help-message", - "lib/irb/locale.rb", - "lib/irb/magic-file.rb", - "lib/irb/notifier.rb", - "lib/irb/output-method.rb", - "lib/irb/ruby-lex.rb", - "lib/irb/ruby_logo.aa", - "lib/irb/src_encoding.rb", - "lib/irb/version.rb", - "lib/irb/workspace.rb", - "lib/irb/ws-for-case-2.rb", - "lib/irb/xmp.rb", "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.5") - spec.add_dependency "reline", ">= 0.0.1" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" + spec.add_dependency "reline", ">= 0.3.0" end diff --git a/ruby/lib/irb/lc/help-message b/ruby/lib/irb/lc/help-message index a80facc9c..939dc3897 100644 --- a/ruby/lib/irb/lc/help-message +++ b/ruby/lib/irb/lc/help-message @@ -10,7 +10,7 @@ # # Usage: irb.rb [options] [programfile] [arguments] - -f Suppress read of ~/.irbrc + -f Suppress read of ~/.irbrc -d Set $DEBUG to true (same as `ruby -d') -r load-module Same as `ruby -r' -I path Specify $LOAD_PATH directory @@ -18,10 +18,17 @@ Usage: irb.rb [options] [programfile] [arguments] -E enc Same as `ruby -E` -w Same as `ruby -w` -W[level=2] Same as `ruby -W` - --context-mode n Set n[0-3] to method to create Binding Object, + --context-mode n Set n[0-4] to method to create Binding Object, when new workspace was created - --echo Show result(default) + --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 @@ -30,9 +37,11 @@ Usage: irb.rb [options] [programfile] [arguments] --nosingleline Don't use singleline editor module --colorize Use colorization --nocolorize Don't use colorization + --autocomplete Use autocompletion + --noautocomplete Don't use autocompletion --prompt prompt-mode/--prompt-mode prompt-mode - Switch prompt mode. Pre-defined prompt modes are - `default', `simple', `xmp' and `inf-ruby' + Switch prompt mode. Pre-defined prompt modes are + `default', `simple', `xmp' and `inf-ruby' --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. Suppresses --multiline and --singleline. --sample-book-mode/--simple-prompt @@ -41,8 +50,8 @@ Usage: irb.rb [options] [programfile] [arguments] --single-irb Share self with sub-irb. --tracer Display trace for each execution of commands. --back-trace-limit n - Display backtrace top n and tail n. The default - value is 16. + Display backtrace top n and tail n. The default + value is 16. --verbose Show details --noverbose Don't show details -v, --version Print the version of irb diff --git a/ruby/lib/irb/lc/ja/help-message b/ruby/lib/irb/lc/ja/help-message index 9794a8e24..238535afb 100644 --- a/ruby/lib/irb/lc/ja/help-message +++ b/ruby/lib/irb/lc/ja/help-message @@ -29,6 +29,8 @@ Usage: irb.rb [options] [programfile] [arguments] --nosingleline シングルラインエディタを利用ã—ãªã„. --colorize 色付ã‘を利用ã™ã‚‹. --nocolorize 色付ã‘を利用ã—ãªã„. + --autocomplete オートコンプリートを利用ã™ã‚‹. + --noautocomplete オートコンプリートを利用ã—ãªã„. --prompt prompt-mode/--prompt-mode prompt-mode プロンプトモードを切替ãˆã¾ã™. ç¾åœ¨å®šç¾©ã•れã¦ã„るプ ロンプトモードã¯, default, simple, xmp, inf-ruby㌠diff --git a/ruby/lib/irb/ruby-lex.rb b/ruby/lib/irb/ruby-lex.rb index d5630c8b5..29862f550 100644 --- a/ruby/lib/irb/ruby-lex.rb +++ b/ruby/lib/irb/ruby-lex.rb @@ -11,6 +11,7 @@ # require "ripper" +require "jruby" if RUBY_ENGINE == "jruby" # :stopdoc: class RubyLex @@ -29,17 +30,48 @@ def initialize @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 + # io functions - def set_input(io, p = nil, &block) + def set_input(io, p = nil, context: nil, &block) @io = io if @io.respond_to?(:check_termination) @io.check_termination do |code| - code.gsub!(/\s*\z/, '').concat("\n") - ltype, indent, continue, code_block_open = check_state(code) - if ltype or indent > 0 or continue or code_block_open - false + if Reline::IOGate.in_pasting? + lex = RubyLex.new + rest = lex.check_termination_in_prev_line(code, context: context) + if rest + Reline.delete_text + rest.bytes.reverse_each do |c| + Reline.ungetc(c) + end + true + else + false + end else - true + code.gsub!(/\s*\z/, '').concat("\n") + ltype, indent, continue, code_block_open = check_state(code, context: context) + if ltype or indent > 0 or continue or code_block_open + false + else + true + end end end end @@ -47,14 +79,36 @@ def set_input(io, p = nil, &block) @io.dynamic_prompt do |lines| lines << '' if lines.empty? result = [] - lines.each_index { |i| - c = lines[0..i].map{ |l| l + "\n" }.join - ltype, indent, continue, code_block_open = check_state(c) - result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + i) - } + tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: context) + code = String.new + partial_tokens = [] + unprocessed_tokens = [] + line_num_offset = 0 + tokens.each do |t| + partial_tokens << t + unprocessed_tokens << t + if t.tok.include?("\n") + t_str = t.tok + t_str.each_line("\n") do |s| + code << s << "\n" + ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context) + result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset) + line_num_offset += 1 + end + unprocessed_tokens = [] + else + code << t.tok + end + end + + unless unprocessed_tokens.empty? + ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context) + result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset) + end result end end + if p.respond_to?(:call) @input = p elsif block_given? @@ -73,28 +127,89 @@ def set_prompt(p = nil, &block) end end - def ripper_lex_without_warning(code) + ERROR_TOKENS = [ + :on_parse_error, + :compile_error, + :on_assign_error, + :on_alias_error, + :on_class_name_error, + :on_param_error + ] + + def self.ripper_lex_without_warning(code, context: nil) verbose, $VERBOSE = $VERBOSE, nil - tokens = Ripper.lex(code) - $VERBOSE = verbose + if context + lvars = context&.workspace&.binding&.local_variables + if lvars && !lvars.empty? + code = "#{lvars.join('=')}=nil\n#{code}" + line_no = 0 + else + line_no = 1 + end + end + tokens = nil + compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no| + lexer = Ripper::Lexer.new(inner_code, '-', line_no) + if lexer.respond_to?(:scan) # Ruby 2.7+ + tokens = [] + pos_to_index = {} + lexer.scan.each do |t| + next if t.pos.first == 0 + if pos_to_index.has_key?(t.pos) + index = pos_to_index[t.pos] + found_tk = tokens[index] + if ERROR_TOKENS.include?(found_tk.event) && !ERROR_TOKENS.include?(t.event) + tokens[index] = t + end + else + pos_to_index[t.pos] = tokens.size + tokens << t + end + end + else + tokens = lexer.parse.reject { |it| it.pos.first == 0 } + end + end tokens + ensure + $VERBOSE = verbose + end + + def find_prev_spaces(line_index) + return 0 if @tokens.size == 0 + md = @tokens[0].tok.match(/(\A +)/) + prev_spaces = md.nil? ? 0 : md[1].count(' ') + line_count = 0 + @tokens.each_with_index do |t, i| + if t.tok.include?("\n") + line_count += t.tok.count("\n") + if line_count >= line_index + return prev_spaces + end + if (@tokens.size - 1) > i + md = @tokens[i + 1].tok.match(/(\A +)/) + prev_spaces = md.nil? ? 0 : md[1].count(' ') + end + end + end + prev_spaces end def set_auto_indent(context) if @io.respond_to?(:auto_indent) and context.auto_indent_mode @io.auto_indent do |lines, line_index, byte_pointer, is_newline| if is_newline - md = lines[line_index - 1].match(/(\A +)/) - prev_spaces = md.nil? ? 0 : md[1].count(' ') - @tokens = ripper_lex_without_warning(lines[0..line_index].join("\n")) + @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: context) + prev_spaces = find_prev_spaces(line_index) depth_difference = check_newline_depth_difference + depth_difference = 0 if depth_difference < 0 prev_spaces + depth_difference * 2 else code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join last_line = lines[line_index]&.byteslice(0, byte_pointer) code += last_line if last_line - @tokens = ripper_lex_without_warning(code) - corresponding_token_depth = check_corresponding_token_depth + @tokens = self.class.ripper_lex_without_warning(code, context: context) + corresponding_token_depth = check_corresponding_token_depth(lines, line_index) if corresponding_token_depth corresponding_token_depth else @@ -105,12 +220,12 @@ def set_auto_indent(context) end end - def check_state(code) - @tokens = ripper_lex_without_warning(code) - ltype = process_literal_type - indent = process_nesting_level - continue = process_continue - code_block_open = check_code_block(code) + def check_state(code, tokens = nil, context: nil) + tokens = self.class.ripper_lex_without_warning(code, context: context) unless tokens + ltype = process_literal_type(tokens) + indent = process_nesting_level(tokens) + continue = process_continue(tokens) + code_block_open = check_code_block(code, tokens) [ltype, indent, continue, code_block_open] end @@ -139,7 +254,10 @@ def each_top_level_statement throw :TERM_INPUT if @line == '' else @line_no += l.count("\n") - next if l == "\n" + if l == "\n" + @exp_line_no += 1 + next + end @line.concat l if @code_block_open or @ltype or @continue or @indent > 0 next @@ -149,7 +267,7 @@ def each_top_level_statement @line.force_encoding(@io.encoding) yield @line, @exp_line_no end - break if @io.eof? + raise TerminateLineInput if @io.eof? @line = '' @exp_line_no = @line_no @@ -169,7 +287,7 @@ def lex end code = @line + (line.nil? ? '' : line) code.gsub!(/\s*\z/, '').concat("\n") - @tokens = ripper_lex_without_warning(code) + @tokens = self.class.ripper_lex_without_warning(code) @continue = process_continue @code_block_open = check_code_block(code) @indent = process_nesting_level @@ -177,39 +295,47 @@ def lex line end - def process_continue + def process_continue(tokens = @tokens) # last token is always newline - if @tokens.size >= 2 and @tokens[-2][1] == :on_regexp_end + if tokens.size >= 2 and tokens[-2].event == :on_regexp_end # end of regexp literal return false - elsif @tokens.size >= 2 and @tokens[-2][1] == :on_semicolon + elsif tokens.size >= 2 and tokens[-2].event == :on_semicolon return false - elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(@tokens[-2][2]) + elsif tokens.size >= 2 and tokens[-2].event == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2].tok) return false - elsif !@tokens.empty? and @tokens.last[2] == "\\\n" + elsif !tokens.empty? and tokens.last.tok == "\\\n" return true - elsif @tokens.size >= 1 and @tokens[-1][1] == :on_heredoc_end # "EOH\n" + elsif tokens.size >= 1 and tokens[-1].event == :on_heredoc_end # "EOH\n" return false - elsif @tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and @tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) + elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2].state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2].tok !~ /\A\.\.\.?\z/ # end of literal except for regexp + # endless range at end of line is not a continue return true end false end - def check_code_block(code) - return true if @tokens.empty? - if @tokens.last[1] == :on_heredoc_beg + def check_code_block(code, tokens = @tokens) + return true if tokens.empty? + if tokens.last.event == :on_heredoc_beg return true end 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 - RubyVM::InstructionSequence.compile(code) + 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} @@ -230,7 +356,7 @@ def check_code_block(code) # "syntax error, unexpected end-of-input, expecting keyword_end" # # example: - # if ture + # if true # hoge # if false # fuga @@ -264,7 +390,7 @@ def check_code_block(code) end if defined?(Ripper::EXPR_BEG) - last_lex_state = @tokens.last[3] + last_lex_state = tokens.last.state if last_lex_state.allbits?(Ripper::EXPR_BEG) return false elsif last_lex_state.allbits?(Ripper::EXPR_DOT) @@ -283,31 +409,47 @@ def check_code_block(code) false end - def process_nesting_level + def process_nesting_level(tokens = @tokens) indent = 0 - @tokens.each_with_index { |t, index| - case t[1] - when :on_lbracket, :on_lbrace, :on_lparen + in_oneliner_def = nil + tokens.each_with_index { |t, index| + # detecting one-liner method definition + if in_oneliner_def.nil? + if t.state.allbits?(Ripper::EXPR_ENDFN) + in_oneliner_def = :ENDFN + end + else + if t.state.allbits?(Ripper::EXPR_ENDFN) + # continuing + elsif t.state.allbits?(Ripper::EXPR_BEG) + if t.tok == '=' + in_oneliner_def = :BODY + end + else + if in_oneliner_def == :BODY + # one-liner method definition + indent -= 1 + end + in_oneliner_def = nil + end + end + + case t.event + when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg indent += 1 when :on_rbracket, :on_rbrace, :on_rparen indent -= 1 when :on_kw - next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME) - case t[2] + next if index > 0 and tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME) + case t.tok when 'do' - if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG) - # method_with_block do; end - indent += 1 - else - # while cond do; end # also "until" or "for" - # This "do" doesn't increment indent because "while" already - # incremented. - end + syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index) + indent += 1 if syntax_of_do == :method_calling when 'def', 'case', 'for', 'begin', 'class', 'module' indent += 1 when 'if', 'unless', 'while', 'until' - # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL - indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL) + # postfix if/unless/while/until must be Ripper::EXPR_LABEL + indent += 1 unless t.state.allbits?(Ripper::EXPR_LABEL) when 'end' indent -= 1 end @@ -317,13 +459,112 @@ def process_nesting_level indent end + def is_method_calling?(tokens, index) + tk = tokens[index] + if tk.state.anybits?(Ripper::EXPR_CMDARG) and tk.event == :on_ident + # The target method call to pass the block with "do". + return true + elsif tk.state.anybits?(Ripper::EXPR_ARG) and tk.event == :on_ident + non_sp_index = tokens[0..(index - 1)].rindex{ |t| t.event != :on_sp } + if non_sp_index + prev_tk = tokens[non_sp_index] + if prev_tk.state.anybits?(Ripper::EXPR_DOT) and prev_tk.event == :on_period + # The target method call with receiver to pass the block with "do". + return true + end + end + end + false + end + + def take_corresponding_syntax_to_kw_do(tokens, index) + syntax_of_do = nil + # Finding a syntax corresponding to "do". + index.downto(0) do |i| + tk = tokens[i] + # In "continue", the token isn't the corresponding syntax to "do". + non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp } + first_in_fomula = false + if non_sp_index.nil? + first_in_fomula = true + elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event) + first_in_fomula = true + end + if is_method_calling?(tokens, i) + syntax_of_do = :method_calling + break if first_in_fomula + elsif tk.event == :on_kw && %w{while until for}.include?(tk.tok) + # A loop syntax in front of "do" found. + # + # while cond do # also "until" or "for" + # end + # + # This "do" doesn't increment indent because the loop syntax already + # incremented. + syntax_of_do = :loop_syntax + break if first_in_fomula + end + end + syntax_of_do + end + + def is_the_in_correspond_to_a_for(tokens, index) + syntax_of_in = nil + # Finding a syntax corresponding to "do". + index.downto(0) do |i| + tk = tokens[i] + # In "continue", the token isn't the corresponding syntax to "do". + non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp } + first_in_fomula = false + if non_sp_index.nil? + first_in_fomula = true + elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event) + first_in_fomula = true + end + if tk.event == :on_kw && tk.tok == 'for' + # A loop syntax in front of "do" found. + # + # while cond do # also "until" or "for" + # end + # + # This "do" doesn't increment indent because the loop syntax already + # incremented. + syntax_of_in = :for + end + break if first_in_fomula + end + syntax_of_in + end + def check_newline_depth_difference depth_difference = 0 open_brace_on_line = 0 + in_oneliner_def = nil @tokens.each_with_index do |t, index| - case t[1] + # detecting one-liner method definition + if in_oneliner_def.nil? + if t.state.allbits?(Ripper::EXPR_ENDFN) + in_oneliner_def = :ENDFN + end + else + if t.state.allbits?(Ripper::EXPR_ENDFN) + # continuing + elsif t.state.allbits?(Ripper::EXPR_BEG) + if t.tok == '=' + in_oneliner_def = :BODY + end + else + if in_oneliner_def == :BODY + # one-liner method definition + depth_difference -= 1 + end + in_oneliner_def = nil + end + end + + case t.event when :on_ignored_nl, :on_nl, :on_comment - if index != (@tokens.size - 1) + if index != (@tokens.size - 1) and in_oneliner_def != :BODY depth_difference = 0 open_brace_on_line = 0 end @@ -331,62 +572,98 @@ def check_newline_depth_difference when :on_sp next end - case t[1] - when :on_lbracket, :on_lbrace, :on_lparen + + case t.event + when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg depth_difference += 1 open_brace_on_line += 1 when :on_rbracket, :on_rbrace, :on_rparen depth_difference -= 1 if open_brace_on_line > 0 when :on_kw - next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME) - case t[2] + next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME) + case t.tok when 'do' - if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG) - # method_with_block do; end - depth_difference += 1 - else - # while cond do; end # also "until" or "for" - # This "do" doesn't increment indent because "while" already - # incremented. - end + syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index) + depth_difference += 1 if syntax_of_do == :method_calling when 'def', 'case', 'for', 'begin', 'class', 'module' depth_difference += 1 - when 'if', 'unless', 'while', 'until' + when 'if', 'unless', 'while', 'until', 'rescue' # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL - unless t[3].allbits?(Ripper::EXPR_LABEL) + unless t.state.allbits?(Ripper::EXPR_LABEL) depth_difference += 1 end - when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in' + when 'else', 'elsif', 'ensure', 'when' depth_difference += 1 + when 'in' + unless is_the_in_correspond_to_a_for(@tokens, index) + depth_difference += 1 + end + when 'end' + depth_difference -= 1 end end end depth_difference end - def check_corresponding_token_depth + def check_corresponding_token_depth(lines, line_index) corresponding_token_depth = nil is_first_spaces_of_line = true is_first_printable_of_line = true spaces_of_nest = [] spaces_at_line_head = 0 open_brace_on_line = 0 + in_oneliner_def = nil + + if heredoc_scope? + return lines[line_index][/^ */].length + end + @tokens.each_with_index do |t, index| - case t[1] + # detecting one-liner method definition + if in_oneliner_def.nil? + if t.state.allbits?(Ripper::EXPR_ENDFN) + in_oneliner_def = :ENDFN + end + else + if t.state.allbits?(Ripper::EXPR_ENDFN) + # continuing + elsif t.state.allbits?(Ripper::EXPR_BEG) + if t.tok == '=' + in_oneliner_def = :BODY + end + else + if in_oneliner_def == :BODY + # one-liner method definition + if is_first_printable_of_line + corresponding_token_depth = spaces_of_nest.pop + else + spaces_of_nest.pop + corresponding_token_depth = nil + end + end + in_oneliner_def = nil + end + end + + case t.event when :on_ignored_nl, :on_nl, :on_comment - corresponding_token_depth = nil - spaces_at_line_head = 0 - is_first_spaces_of_line = true - is_first_printable_of_line = true - open_brace_on_line = 0 + if in_oneliner_def != :BODY + corresponding_token_depth = nil + spaces_at_line_head = 0 + is_first_spaces_of_line = true + is_first_printable_of_line = true + open_brace_on_line = 0 + end next when :on_sp - spaces_at_line_head = t[2].count(' ') if is_first_spaces_of_line + spaces_at_line_head = t.tok.count(' ') if is_first_spaces_of_line is_first_spaces_of_line = false next end - case t[1] - when :on_lbracket, :on_lbrace, :on_lparen + + case t.event + when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2) open_brace_on_line += 1 when :on_rbracket, :on_rbrace, :on_rparen @@ -398,17 +675,30 @@ def check_corresponding_token_depth end open_brace_on_line -= 1 when :on_kw - next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME) - case t[2] - when 'def', 'do', 'case', 'for', 'begin', 'class', 'module' + next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME) + case t.tok + when 'do' + syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index) + if syntax_of_do == :method_calling + spaces_of_nest.push(spaces_at_line_head) + end + when 'def', 'case', 'for', 'begin', 'class', 'module' spaces_of_nest.push(spaces_at_line_head) + when 'rescue' + unless t.state.allbits?(Ripper::EXPR_LABEL) + corresponding_token_depth = spaces_of_nest.last + end when 'if', 'unless', 'while', 'until' - # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL - unless t[3].allbits?(Ripper::EXPR_LABEL) + # postfix if/unless/while/until must be Ripper::EXPR_LABEL + unless t.state.allbits?(Ripper::EXPR_LABEL) spaces_of_nest.push(spaces_at_line_head) end - when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in' + when 'else', 'elsif', 'ensure', 'when' corresponding_token_depth = spaces_of_nest.last + when 'in' + if in_keyword_case_scope? + corresponding_token_depth = spaces_of_nest.last + end when 'end' if is_first_printable_of_line corresponding_token_depth = spaces_of_nest.pop @@ -424,13 +714,16 @@ def check_corresponding_token_depth corresponding_token_depth end - def check_string_literal + def check_string_literal(tokens) i = 0 start_token = [] end_type = [] - while i < @tokens.size - t = @tokens[i] - case t[1] + while i < tokens.size + t = tokens[i] + case t.event + when *end_type.last + start_token.pop + end_type.pop when :on_tstring_beg start_token << t end_type << [:on_tstring_end, :on_label_end] @@ -438,10 +731,14 @@ def check_string_literal start_token << t end_type << :on_regexp_end when :on_symbeg - acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw} - if (i + 1) < @tokens.size and acceptable_single_tokens.all?{ |t| @tokens[i + 1][1] != t } - start_token << t - end_type << :on_tstring_end + acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int on_backtick} + if (i + 1) < tokens.size + if acceptable_single_tokens.all?{ |st| tokens[i + 1].event != st } + start_token << t + end_type << :on_tstring_end + else + i += 1 + end end when :on_backtick start_token << t @@ -452,20 +749,19 @@ def check_string_literal when :on_heredoc_beg start_token << t end_type << :on_heredoc_end - when *end_type.last - start_token.pop - end_type.pop end i += 1 end - start_token.last.nil? ? '' : start_token.last + start_token.last.nil? ? nil : start_token.last end - def process_literal_type - start_token = check_string_literal - case start_token[1] + def process_literal_type(tokens = @tokens) + start_token = check_string_literal(tokens) + return nil if start_token == "" + + case start_token&.event when :on_tstring_beg - case start_token[2] + case start_token&.tok when ?" then ?" when /^%.$/ then ?" when /^%Q.$/ then ?" @@ -480,7 +776,7 @@ def process_literal_type when :on_qsymbols_beg then ?] when :on_symbols_beg then ?] when :on_heredoc_beg - start_token[2] =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/ + start_token&.tok =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/ case $1 when ?" then ?" when ?' then ?' @@ -491,5 +787,75 @@ def process_literal_type nil end end + + def check_termination_in_prev_line(code, context: nil) + 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.nil? + return false + elsif first_token && first_token.state == Ripper::EXPR_DOT + return false + else + tokens_without_last_line = tokens[0..index] + ltype = process_literal_type(tokens_without_last_line) + indent = process_nesting_level(tokens_without_last_line) + continue = process_continue(tokens_without_last_line) + code_block_open = check_code_block(tokens_without_last_line.map(&:tok).join(''), tokens_without_last_line) + if ltype or indent > 0 or continue or code_block_open + return false + else + return last_line_tokens.map(&:tok).join('') + end + end + end + false + end + + private + + def heredoc_scope? + heredoc_tokens = @tokens.select { |t| [:on_heredoc_beg, :on_heredoc_end].include?(t.event) } + heredoc_tokens[-1]&.event == :on_heredoc_beg + end + + def in_keyword_case_scope? + kw_tokens = @tokens.select { |t| t.event == :on_kw && ['case', 'for', 'end'].include?(t.tok) } + counter = 0 + kw_tokens.reverse.each do |t| + if t.tok == 'case' + return true if counter.zero? + counter += 1 + elsif t.tok == 'for' + counter += 1 + elsif t.tok == 'end' + counter -= 1 + end + end + false + end end # :startdoc: diff --git a/ruby/lib/irb/ruby_logo.aa b/ruby/lib/irb/ruby_logo.aa index 043e6f85f..a34a3e2f2 100644 --- a/ruby/lib/irb/ruby_logo.aa +++ b/ruby/lib/irb/ruby_logo.aa @@ -35,4 +35,3 @@ m7 NW H N HSVO1z=?11- NgTH bB kH WBHWWHBHWmQgg&gggggNNN NNggggggNN - diff --git a/ruby/lib/irb/version.rb b/ruby/lib/irb/version.rb index 7669c1c53..481d14ffd 100644 --- a/ruby/lib/irb/version.rb +++ b/ruby/lib/irb/version.rb @@ -11,7 +11,7 @@ # module IRB # :nodoc: - VERSION = "1.2.3" + VERSION = "1.4.1" @RELEASE_VERSION = VERSION - @LAST_UPDATE_DATE = "2020-02-15" + @LAST_UPDATE_DATE = "2021-12-25" end diff --git a/ruby/lib/irb/workspace.rb b/ruby/lib/irb/workspace.rb index 794a51152..2c4c40f34 100644 --- a/ruby/lib/irb/workspace.rb +++ b/ruby/lib/irb/workspace.rb @@ -12,6 +12,7 @@ require "delegate" +IRB::TOPLEVEL_BINDING = binding module IRB # :nodoc: class WorkSpace # Creates a new workspace. @@ -51,11 +52,15 @@ def initialize(*main) end @binding = BINDING_QUEUE.pop - when 3 # binding in function on TOPLEVEL_BINDING(default) - @binding = eval("self.class.send(:remove_method, :irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding", + when 3 # binding in function on TOPLEVEL_BINDING + @binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding", TOPLEVEL_BINDING, __FILE__, __LINE__ - 3) + when 4 # binding is a copy of TOPLEVEL_BINDING (default) + # Note that this will typically be IRB::TOPLEVEL_BINDING + # This is to avoid RubyGems' local variables (see issue #17623) + @binding = TOPLEVEL_BINDING.dup end end @@ -126,6 +131,7 @@ def local_variable_get(name) 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! @@ -172,7 +178,7 @@ def code_around_binding 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" + "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear if use_colorize}\n" end def IRB.delete_caller diff --git a/ruby/lib/irb/xmp.rb b/ruby/lib/irb/xmp.rb index 60cf3b4e4..88cbd8852 100644 --- a/ruby/lib/irb/xmp.rb +++ b/ruby/lib/irb/xmp.rb @@ -10,7 +10,7 @@ # # -require "irb" +require_relative "../irb" require_relative "frame" # An example printer for irb. diff --git a/ruby/lib/logger.rb b/ruby/lib/logger.rb index f0b99f75a..4205380a6 100644 --- a/ruby/lib/logger.rb +++ b/ruby/lib/logger.rb @@ -302,35 +302,35 @@ def datetime_format alias sev_threshold level alias sev_threshold= level= - # Returns +true+ iff the current severity level allows for the printing of + # Returns +true+ if and only if the current severity level allows for the printing of # +DEBUG+ messages. def debug?; level <= DEBUG; end # Sets the severity to DEBUG. def debug!; self.level = DEBUG; end - # Returns +true+ iff the current severity level allows for the printing of + # Returns +true+ if and only if the current severity level allows for the printing of # +INFO+ messages. def info?; level <= INFO; end # Sets the severity to INFO. def info!; self.level = INFO; end - # Returns +true+ iff the current severity level allows for the printing of + # Returns +true+ if and only if the current severity level allows for the printing of # +WARN+ messages. def warn?; level <= WARN; end # Sets the severity to WARN. def warn!; self.level = WARN; end - # Returns +true+ iff the current severity level allows for the printing of + # Returns +true+ if and only if the current severity level allows for the printing of # +ERROR+ messages. def error?; level <= ERROR; end # Sets the severity to ERROR. def error!; self.level = ERROR; end - # Returns +true+ iff the current severity level allows for the printing of + # Returns +true+ if and only if the current severity level allows for the printing of # +FATAL+ messages. def fatal?; level <= FATAL; end @@ -349,8 +349,9 @@ def fatal!; self.level = FATAL; end # === Args # # +logdev+:: - # The log device. This is a filename (String) or IO object (typically - # +STDOUT+, +STDERR+, or an open file). + # The log device. This is a filename (String), IO object (typically + # +STDOUT+, +STDERR+, or an open file), +nil+ (it writes nothing) or + # +File::NULL+ (same as +nil+). # +shift_age+:: # Number of old log files to keep, *or* frequency of rotation (+daily+, # +weekly+ or +monthly+). Default value is 0, which disables log file @@ -385,7 +386,7 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, self.datetime_format = datetime_format self.formatter = formatter @logdev = nil - if logdev + if logdev && logdev != File::NULL @logdev = LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size, shift_period_suffix: shift_period_suffix, @@ -410,7 +411,7 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, # Reopen a log device. # def reopen(logdev = nil) - @logdev.reopen(logdev) + @logdev&.reopen(logdev) self end diff --git a/ruby/lib/logger/formatter.rb b/ruby/lib/logger/formatter.rb index 852cffe03..62bff7097 100644 --- a/ruby/lib/logger/formatter.rb +++ b/ruby/lib/logger/formatter.rb @@ -3,7 +3,8 @@ class Logger # Default formatter for log messages. class Formatter - Format = "%s, [%s#%d] %5s -- %s: %s\n" + Format = "%s, [%s #%d] %5s -- %s: %s\n" + DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N" attr_accessor :datetime_format @@ -12,14 +13,14 @@ def initialize end def call(severity, time, progname, msg) - Format % [severity[0..0], format_datetime(time), $$, severity, progname, + Format % [severity[0..0], format_datetime(time), Process.pid, severity, progname, msg2str(msg)] end private def format_datetime(time) - time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ") + time.strftime(@datetime_format || DatetimeFormat) end def msg2str(msg) diff --git a/ruby/lib/logger/log_device.rb b/ruby/lib/logger/log_device.rb index fe7d54fb8..96d77b7b6 100644 --- a/ruby/lib/logger/log_device.rb +++ b/ruby/lib/logger/log_device.rb @@ -135,7 +135,7 @@ def check_shift_log end end - if /mswin|mingw/ =~ RUBY_PLATFORM + if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM def lock_shift_log yield end diff --git a/ruby/lib/logger/logger.gemspec b/ruby/lib/logger/logger.gemspec index 8b3f70627..ccd4e70db 100644 --- a/ruby/lib/logger/logger.gemspec +++ b/ruby/lib/logger/logger.gemspec @@ -13,17 +13,15 @@ Gem::Specification.new do |spec| 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.3.0" spec.add_development_dependency "bundler", ">= 0" - spec.add_development_dependency "rake", "~> 10.0" + spec.add_development_dependency "rake", ">= 12.3.3" spec.add_development_dependency "test-unit" spec.add_development_dependency "rdoc" end diff --git a/ruby/lib/logger/version.rb b/ruby/lib/logger/version.rb index f90ce94e4..3cc001aa8 100644 --- a/ruby/lib/logger/version.rb +++ b/ruby/lib/logger/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class Logger - VERSION = "1.4.2" + VERSION = "1.5.0" end diff --git a/ruby/lib/matrix.rb b/ruby/lib/matrix.rb deleted file mode 100644 index fc0e8ef2f..000000000 --- a/ruby/lib/matrix.rb +++ /dev/null @@ -1,2407 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: false -# -# = matrix.rb -# -# An implementation of Matrix and Vector classes. -# -# See classes Matrix and Vector for documentation. -# -# Current Maintainer:: Marc-André Lafortune -# Original Author:: Keiju ISHITSUKA -# Original Documentation:: Gavin Sinclair (sourced from Ruby in a Nutshell (Matsumoto, O'Reilly)) -## - -require_relative "matrix/version" - -module ExceptionForMatrix # :nodoc: - class ErrDimensionMismatch < StandardError - def initialize(val = nil) - if val - super(val) - else - super("Dimension mismatch") - end - end - end - - class ErrNotRegular < StandardError - def initialize(val = nil) - if val - super(val) - else - super("Not Regular Matrix") - end - end - end - - class ErrOperationNotDefined < StandardError - def initialize(vals) - if vals.is_a?(Array) - super("Operation(#{vals[0]}) can\\'t be defined: #{vals[1]} op #{vals[2]}") - else - super(vals) - end - end - end - - class ErrOperationNotImplemented < StandardError - def initialize(vals) - super("Sorry, Operation(#{vals[0]}) not implemented: #{vals[1]} op #{vals[2]}") - end - end -end - -# -# The +Matrix+ class represents a mathematical matrix. It provides methods for creating -# matrices, operating on them arithmetically and algebraically, -# and determining their mathematical properties such as trace, rank, inverse, determinant, -# or eigensystem. -# -class Matrix - include Enumerable - include ExceptionForMatrix - autoload :EigenvalueDecomposition, "matrix/eigenvalue_decomposition" - autoload :LUPDecomposition, "matrix/lup_decomposition" - - # instance creations - private_class_method :new - attr_reader :rows - protected :rows - - # - # Creates a matrix where each argument is a row. - # Matrix[ [25, 93], [-1, 66] ] - # => 25 93 - # -1 66 - # - def Matrix.[](*rows) - rows(rows, false) - end - - # - # Creates a matrix where +rows+ is an array of arrays, each of which is a row - # of the matrix. If the optional argument +copy+ is false, use the given - # arrays as the internal structure of the matrix without copying. - # Matrix.rows([[25, 93], [-1, 66]]) - # => 25 93 - # -1 66 - # - def Matrix.rows(rows, copy = true) - rows = convert_to_array(rows, copy) - rows.map! do |row| - convert_to_array(row, copy) - end - size = (rows[0] || []).size - rows.each do |row| - raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size - end - new rows, size - end - - # - # Creates a matrix using +columns+ as an array of column vectors. - # Matrix.columns([[25, 93], [-1, 66]]) - # => 25 -1 - # 93 66 - # - def Matrix.columns(columns) - rows(columns, false).transpose - end - - # - # Creates a matrix of size +row_count+ x +column_count+. - # It fills the values by calling the given block, - # passing the current row and column. - # Returns an enumerator if no block is given. - # - # m = Matrix.build(2, 4) {|row, col| col - row } - # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]] - # m = Matrix.build(3) { rand } - # => a 3x3 matrix with random elements - # - def Matrix.build(row_count, column_count = row_count) - row_count = CoercionHelper.coerce_to_int(row_count) - column_count = CoercionHelper.coerce_to_int(column_count) - raise ArgumentError if row_count < 0 || column_count < 0 - return to_enum :build, row_count, column_count unless block_given? - rows = Array.new(row_count) do |i| - Array.new(column_count) do |j| - yield i, j - end - end - new rows, column_count - end - - # - # Creates a matrix where the diagonal elements are composed of +values+. - # Matrix.diagonal(9, 5, -3) - # => 9 0 0 - # 0 5 0 - # 0 0 -3 - # - def Matrix.diagonal(*values) - size = values.size - return Matrix.empty if size == 0 - rows = Array.new(size) {|j| - row = Array.new(size, 0) - row[j] = values[j] - row - } - new rows - end - - # - # Creates an +n+ by +n+ diagonal matrix where each diagonal element is - # +value+. - # Matrix.scalar(2, 5) - # => 5 0 - # 0 5 - # - def Matrix.scalar(n, value) - diagonal(*Array.new(n, value)) - end - - # - # Creates an +n+ by +n+ identity matrix. - # Matrix.identity(2) - # => 1 0 - # 0 1 - # - def Matrix.identity(n) - scalar(n, 1) - end - class << Matrix - alias_method :unit, :identity - alias_method :I, :identity - end - - # - # Creates a zero matrix. - # Matrix.zero(2) - # => 0 0 - # 0 0 - # - def Matrix.zero(row_count, column_count = row_count) - rows = Array.new(row_count){Array.new(column_count, 0)} - new rows, column_count - end - - # - # Creates a single-row matrix where the values of that row are as given in - # +row+. - # Matrix.row_vector([4,5,6]) - # => 4 5 6 - # - def Matrix.row_vector(row) - row = convert_to_array(row) - new [row] - end - - # - # Creates a single-column matrix where the values of that column are as given - # in +column+. - # Matrix.column_vector([4,5,6]) - # => 4 - # 5 - # 6 - # - def Matrix.column_vector(column) - column = convert_to_array(column) - new [column].transpose, 1 - end - - # - # Creates a empty matrix of +row_count+ x +column_count+. - # At least one of +row_count+ or +column_count+ must be 0. - # - # m = Matrix.empty(2, 0) - # m == Matrix[ [], [] ] - # => true - # n = Matrix.empty(0, 3) - # n == Matrix.columns([ [], [], [] ]) - # => true - # m * n - # => Matrix[[0, 0, 0], [0, 0, 0]] - # - def Matrix.empty(row_count = 0, column_count = 0) - raise ArgumentError, "One size must be 0" if column_count != 0 && row_count != 0 - raise ArgumentError, "Negative size" if column_count < 0 || row_count < 0 - - new([[]]*row_count, column_count) - end - - # - # Create a matrix by stacking matrices vertically - # - # x = Matrix[[1, 2], [3, 4]] - # y = Matrix[[5, 6], [7, 8]] - # Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]] - # - def Matrix.vstack(x, *matrices) - x = CoercionHelper.coerce_to_matrix(x) - result = x.send(:rows).map(&:dup) - matrices.each do |m| - m = CoercionHelper.coerce_to_matrix(m) - if m.column_count != x.column_count - raise ErrDimensionMismatch, "The given matrices must have #{x.column_count} columns, but one has #{m.column_count}" - end - result.concat(m.send(:rows)) - end - new result, x.column_count - end - - - # - # Create a matrix by stacking matrices horizontally - # - # x = Matrix[[1, 2], [3, 4]] - # y = Matrix[[5, 6], [7, 8]] - # Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]] - # - def Matrix.hstack(x, *matrices) - x = CoercionHelper.coerce_to_matrix(x) - result = x.send(:rows).map(&:dup) - total_column_count = x.column_count - matrices.each do |m| - m = CoercionHelper.coerce_to_matrix(m) - if m.row_count != x.row_count - raise ErrDimensionMismatch, "The given matrices must have #{x.row_count} rows, but one has #{m.row_count}" - end - result.each_with_index do |row, i| - row.concat m.send(:rows)[i] - end - total_column_count += m.column_count - end - new result, total_column_count - end - - # - # Create a matrix by combining matrices entrywise, using the given block - # - # x = Matrix[[6, 6], [4, 4]] - # y = Matrix[[1, 2], [3, 4]] - # Matrix.combine(x, y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]] - # - def Matrix.combine(*matrices) - return to_enum(__method__, *matrices) unless block_given? - - return Matrix.empty if matrices.empty? - matrices.map!(&CoercionHelper.method(:coerce_to_matrix)) - x = matrices.first - matrices.each do |m| - raise ErrDimensionMismatch unless x.row_count == m.row_count && x.column_count == m.column_count - end - - rows = Array.new(x.row_count) do |i| - Array.new(x.column_count) do |j| - yield matrices.map{|m| m[i,j]} - end - end - new rows, x.column_count - end - - def combine(*matrices, &block) - Matrix.combine(self, *matrices, &block) - end - - # - # Matrix.new is private; use Matrix.rows, columns, [], etc... to create. - # - def initialize(rows, column_count = rows[0].size) - # No checking is done at this point. rows must be an Array of Arrays. - # column_count must be the size of the first row, if there is one, - # otherwise it *must* be specified and can be any integer >= 0 - @rows = rows - @column_count = column_count - end - - private def new_matrix(rows, column_count = rows[0].size) # :nodoc: - self.class.send(:new, rows, column_count) # bypass privacy of Matrix.new - end - - # - # Returns element (+i+,+j+) of the matrix. That is: row +i+, column +j+. - # - def [](i, j) - @rows.fetch(i){return nil}[j] - end - alias element [] - alias component [] - - # - # :call-seq: - # matrix[range, range] = matrix/element - # matrix[range, integer] = vector/column_matrix/element - # matrix[integer, range] = vector/row_matrix/element - # matrix[integer, integer] = element - # - # Set element or elements of matrix. - def []=(i, j, v) - raise FrozenError, "can't modify frozen Matrix" if frozen? - rows = check_range(i, :row) or row = check_int(i, :row) - columns = check_range(j, :column) or column = check_int(j, :column) - if rows && columns - set_row_and_col_range(rows, columns, v) - elsif rows - set_row_range(rows, column, v) - elsif columns - set_col_range(row, columns, v) - else - set_value(row, column, v) - end - end - alias set_element []= - alias set_component []= - private :set_element, :set_component - - # Returns range or nil - private def check_range(val, direction) - return unless val.is_a?(Range) - count = direction == :row ? row_count : column_count - CoercionHelper.check_range(val, count, direction) - end - - private def check_int(val, direction) - count = direction == :row ? row_count : column_count - CoercionHelper.check_int(val, count, direction) - end - - private def set_value(row, col, value) - raise ErrDimensionMismatch, "Expected a a value, got a #{value.class}" if value.respond_to?(:to_matrix) - - @rows[row][col] = value - end - - private def set_row_and_col_range(row_range, col_range, value) - if value.is_a?(Matrix) - if row_range.size != value.row_count || col_range.size != value.column_count - raise ErrDimensionMismatch, [ - 'Expected a Matrix of dimensions', - "#{row_range.size}x#{col_range.size}", - 'got', - "#{value.row_count}x#{value.column_count}", - ].join(' ') - end - source = value.instance_variable_get :@rows - row_range.each_with_index do |row, i| - @rows[row][col_range] = source[i] - end - elsif value.is_a?(Vector) - raise ErrDimensionMismatch, 'Expected a Matrix or a value, got a Vector' - else - value_to_set = Array.new(col_range.size, value) - row_range.each do |i| - @rows[i][col_range] = value_to_set - end - end - end - - private def set_row_range(row_range, col, value) - if value.is_a?(Vector) - raise ErrDimensionMismatch unless row_range.size == value.size - set_column_vector(row_range, col, value) - elsif value.is_a?(Matrix) - raise ErrDimensionMismatch unless value.column_count == 1 - value = value.column(0) - raise ErrDimensionMismatch unless row_range.size == value.size - set_column_vector(row_range, col, value) - else - @rows[row_range].each{|e| e[col] = value } - end - end - - private def set_column_vector(row_range, col, value) - value.each_with_index do |e, index| - r = row_range.begin + index - @rows[r][col] = e - end - end - - private def set_col_range(row, col_range, value) - value = if value.is_a?(Vector) - value.to_a - elsif value.is_a?(Matrix) - raise ErrDimensionMismatch unless value.row_count == 1 - value.row(0).to_a - else - Array.new(col_range.size, value) - end - raise ErrDimensionMismatch unless col_range.size == value.size - @rows[row][col_range] = value - end - - # - # Returns the number of rows. - # - def row_count - @rows.size - end - - alias_method :row_size, :row_count - # - # Returns the number of columns. - # - attr_reader :column_count - alias_method :column_size, :column_count - - # - # Returns row vector number +i+ of the matrix as a Vector (starting at 0 like - # an array). When a block is given, the elements of that vector are iterated. - # - def row(i, &block) # :yield: e - if block_given? - @rows.fetch(i){return self}.each(&block) - self - else - Vector.elements(@rows.fetch(i){return nil}) - end - end - - # - # Returns column vector number +j+ of the matrix as a Vector (starting at 0 - # like an array). When a block is given, the elements of that vector are - # iterated. - # - def column(j) # :yield: e - if block_given? - return self if j >= column_count || j < -column_count - row_count.times do |i| - yield @rows[i][j] - end - self - else - return nil if j >= column_count || j < -column_count - col = Array.new(row_count) {|i| - @rows[i][j] - } - Vector.elements(col, false) - end - end - - # - # Returns a matrix that is the result of iteration of the given block over all - # elements of the matrix. - # Elements can be restricted by passing an argument: - # * :all (default): yields all elements - # * :diagonal: yields only elements on the diagonal - # * :off_diagonal: yields all elements except on the diagonal - # * :lower: yields only elements on or below the diagonal - # * :strict_lower: yields only elements below the diagonal - # * :strict_upper: yields only elements above the diagonal - # * :upper: yields only elements on or above the diagonal - # Matrix[ [1,2], [3,4] ].collect { |e| e**2 } - # => 1 4 - # 9 16 - # - def collect(which = :all, &block) # :yield: e - return to_enum(:collect, which) unless block_given? - dup.collect!(which, &block) - end - alias_method :map, :collect - - # - # Invokes the given block for each element of matrix, replacing the element with the value - # returned by the block. - # Elements can be restricted by passing an argument: - # * :all (default): yields all elements - # * :diagonal: yields only elements on the diagonal - # * :off_diagonal: yields all elements except on the diagonal - # * :lower: yields only elements on or below the diagonal - # * :strict_lower: yields only elements below the diagonal - # * :strict_upper: yields only elements above the diagonal - # * :upper: yields only elements on or above the diagonal - # - def collect!(which = :all) - return to_enum(:collect!, which) unless block_given? - raise FrozenError, "can't modify frozen Matrix" if frozen? - each_with_index(which){ |e, row_index, col_index| @rows[row_index][col_index] = yield e } - end - - alias map! collect! - - def freeze - @rows.freeze - super - end - - # - # Yields all elements of the matrix, starting with those of the first row, - # or returns an Enumerator if no block given. - # Elements can be restricted by passing an argument: - # * :all (default): yields all elements - # * :diagonal: yields only elements on the diagonal - # * :off_diagonal: yields all elements except on the diagonal - # * :lower: yields only elements on or below the diagonal - # * :strict_lower: yields only elements below the diagonal - # * :strict_upper: yields only elements above the diagonal - # * :upper: yields only elements on or above the diagonal - # - # Matrix[ [1,2], [3,4] ].each { |e| puts e } - # # => prints the numbers 1 to 4 - # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3] - # - def each(which = :all, &block) # :yield: e - return to_enum :each, which unless block_given? - last = column_count - 1 - case which - when :all - @rows.each do |row| - row.each(&block) - end - when :diagonal - @rows.each_with_index do |row, row_index| - yield row.fetch(row_index){return self} - end - when :off_diagonal - @rows.each_with_index do |row, row_index| - column_count.times do |col_index| - yield row[col_index] unless row_index == col_index - end - end - when :lower - @rows.each_with_index do |row, row_index| - 0.upto([row_index, last].min) do |col_index| - yield row[col_index] - end - end - when :strict_lower - @rows.each_with_index do |row, row_index| - [row_index, column_count].min.times do |col_index| - yield row[col_index] - end - end - when :strict_upper - @rows.each_with_index do |row, row_index| - (row_index+1).upto(last) do |col_index| - yield row[col_index] - end - end - when :upper - @rows.each_with_index do |row, row_index| - row_index.upto(last) do |col_index| - yield row[col_index] - end - end - else - raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" - end - self - end - - # - # Same as #each, but the row index and column index in addition to the element - # - # Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col| - # puts "#{e} at #{row}, #{col}" - # end - # # => Prints: - # # 1 at 0, 0 - # # 2 at 0, 1 - # # 3 at 1, 0 - # # 4 at 1, 1 - # - def each_with_index(which = :all) # :yield: e, row, column - return to_enum :each_with_index, which unless block_given? - last = column_count - 1 - case which - when :all - @rows.each_with_index do |row, row_index| - row.each_with_index do |e, col_index| - yield e, row_index, col_index - end - end - when :diagonal - @rows.each_with_index do |row, row_index| - yield row.fetch(row_index){return self}, row_index, row_index - end - when :off_diagonal - @rows.each_with_index do |row, row_index| - column_count.times do |col_index| - yield row[col_index], row_index, col_index unless row_index == col_index - end - end - when :lower - @rows.each_with_index do |row, row_index| - 0.upto([row_index, last].min) do |col_index| - yield row[col_index], row_index, col_index - end - end - when :strict_lower - @rows.each_with_index do |row, row_index| - [row_index, column_count].min.times do |col_index| - yield row[col_index], row_index, col_index - end - end - when :strict_upper - @rows.each_with_index do |row, row_index| - (row_index+1).upto(last) do |col_index| - yield row[col_index], row_index, col_index - end - end - when :upper - @rows.each_with_index do |row, row_index| - row_index.upto(last) do |col_index| - yield row[col_index], row_index, col_index - end - end - else - raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper" - end - self - end - - SELECTORS = {all: true, diagonal: true, off_diagonal: true, lower: true, strict_lower: true, strict_upper: true, upper: true}.freeze - # - # :call-seq: - # index(value, selector = :all) -> [row, column] - # index(selector = :all){ block } -> [row, column] - # index(selector = :all) -> an_enumerator - # - # The index method is specialized to return the index as [row, column] - # It also accepts an optional +selector+ argument, see #each for details. - # - # Matrix[ [1,2], [3,4] ].index(&:even?) # => [0, 1] - # Matrix[ [1,1], [1,1] ].index(1, :strict_lower) # => [1, 0] - # - def index(*args) - raise ArgumentError, "wrong number of arguments(#{args.size} for 0-2)" if args.size > 2 - which = (args.size == 2 || SELECTORS.include?(args.last)) ? args.pop : :all - return to_enum :find_index, which, *args unless block_given? || args.size == 1 - if args.size == 1 - value = args.first - each_with_index(which) do |e, row_index, col_index| - return row_index, col_index if e == value - end - else - each_with_index(which) do |e, row_index, col_index| - return row_index, col_index if yield e - end - end - nil - end - alias_method :find_index, :index - - # - # Returns a section of the matrix. The parameters are either: - # * start_row, nrows, start_col, ncols; OR - # * row_range, col_range - # - # Matrix.diagonal(9, 5, -3).minor(0..1, 0..2) - # => 9 0 0 - # 0 5 0 - # - # Like Array#[], negative indices count backward from the end of the - # row or column (-1 is the last element). Returns nil if the starting - # row or column is greater than row_count or column_count respectively. - # - def minor(*param) - case param.size - when 2 - row_range, col_range = param - from_row = row_range.first - from_row += row_count if from_row < 0 - to_row = row_range.end - to_row += row_count if to_row < 0 - to_row += 1 unless row_range.exclude_end? - size_row = to_row - from_row - - from_col = col_range.first - from_col += column_count if from_col < 0 - to_col = col_range.end - to_col += column_count if to_col < 0 - to_col += 1 unless col_range.exclude_end? - size_col = to_col - from_col - when 4 - from_row, size_row, from_col, size_col = param - return nil if size_row < 0 || size_col < 0 - from_row += row_count if from_row < 0 - from_col += column_count if from_col < 0 - else - raise ArgumentError, param.inspect - end - - return nil if from_row > row_count || from_col > column_count || from_row < 0 || from_col < 0 - rows = @rows[from_row, size_row].collect{|row| - row[from_col, size_col] - } - new_matrix rows, [column_count - from_col, size_col].min - end - - # - # Returns the submatrix obtained by deleting the specified row and column. - # - # Matrix.diagonal(9, 5, -3, 4).first_minor(1, 2) - # => 9 0 0 - # 0 0 0 - # 0 0 4 - # - def first_minor(row, column) - raise RuntimeError, "first_minor of empty matrix is not defined" if empty? - - unless 0 <= row && row < row_count - raise ArgumentError, "invalid row (#{row.inspect} for 0..#{row_count - 1})" - end - - unless 0 <= column && column < column_count - raise ArgumentError, "invalid column (#{column.inspect} for 0..#{column_count - 1})" - end - - arrays = to_a - arrays.delete_at(row) - arrays.each do |array| - array.delete_at(column) - end - - new_matrix arrays, column_count - 1 - end - - # - # Returns the (row, column) cofactor which is obtained by multiplying - # the first minor by (-1)**(row + column). - # - # Matrix.diagonal(9, 5, -3, 4).cofactor(1, 1) - # => -108 - # - def cofactor(row, column) - raise RuntimeError, "cofactor of empty matrix is not defined" if empty? - raise ErrDimensionMismatch unless square? - - det_of_minor = first_minor(row, column).determinant - det_of_minor * (-1) ** (row + column) - end - - # - # Returns the adjugate of the matrix. - # - # Matrix[ [7,6],[3,9] ].adjugate - # => 9 -6 - # -3 7 - # - def adjugate - raise ErrDimensionMismatch unless square? - Matrix.build(row_count, column_count) do |row, column| - cofactor(column, row) - end - end - - # - # Returns the Laplace expansion along given row or column. - # - # Matrix[[7,6], [3,9]].laplace_expansion(column: 1) - # => 45 - # - # Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0) - # => Vector[3, -2] - # - # - def laplace_expansion(row: nil, column: nil) - num = row || column - - if !num || (row && column) - raise ArgumentError, "exactly one the row or column arguments must be specified" - end - - raise ErrDimensionMismatch unless square? - raise RuntimeError, "laplace_expansion of empty matrix is not defined" if empty? - - unless 0 <= num && num < row_count - raise ArgumentError, "invalid num (#{num.inspect} for 0..#{row_count - 1})" - end - - send(row ? :row : :column, num).map.with_index { |e, k| - e * cofactor(*(row ? [num, k] : [k,num])) - }.inject(:+) - end - alias_method :cofactor_expansion, :laplace_expansion - - - #-- - # TESTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns +true+ if this is a diagonal matrix. - # Raises an error if matrix is not square. - # - def diagonal? - raise ErrDimensionMismatch unless square? - each(:off_diagonal).all?(&:zero?) - end - - # - # Returns +true+ if this is an empty matrix, i.e. if the number of rows - # or the number of columns is 0. - # - def empty? - column_count == 0 || row_count == 0 - end - - # - # Returns +true+ if this is an hermitian matrix. - # Raises an error if matrix is not square. - # - def hermitian? - raise ErrDimensionMismatch unless square? - each_with_index(:upper).all? do |e, row, col| - e == rows[col][row].conj - end - end - - # - # Returns +true+ if this is a lower triangular matrix. - # - def lower_triangular? - each(:strict_upper).all?(&:zero?) - end - - # - # Returns +true+ if this is a normal matrix. - # Raises an error if matrix is not square. - # - def normal? - raise ErrDimensionMismatch unless square? - rows.each_with_index do |row_i, i| - rows.each_with_index do |row_j, j| - s = 0 - rows.each_with_index do |row_k, k| - s += row_i[k] * row_j[k].conj - row_k[i].conj * row_k[j] - end - return false unless s == 0 - end - end - true - end - - # - # Returns +true+ if this is an orthogonal matrix - # Raises an error if matrix is not square. - # - def orthogonal? - raise ErrDimensionMismatch unless square? - rows.each_with_index do |row, i| - column_count.times do |j| - s = 0 - row_count.times do |k| - s += row[k] * rows[k][j] - end - return false unless s == (i == j ? 1 : 0) - end - end - true - end - - # - # Returns +true+ if this is a permutation matrix - # Raises an error if matrix is not square. - # - def permutation? - raise ErrDimensionMismatch unless square? - cols = Array.new(column_count) - rows.each_with_index do |row, i| - found = false - row.each_with_index do |e, j| - if e == 1 - return false if found || cols[j] - found = cols[j] = true - elsif e != 0 - return false - end - end - return false unless found - end - true - end - - # - # Returns +true+ if all entries of the matrix are real. - # - def real? - all?(&:real?) - end - - # - # Returns +true+ if this is a regular (i.e. non-singular) matrix. - # - def regular? - not singular? - end - - # - # Returns +true+ if this is a singular matrix. - # - def singular? - determinant == 0 - end - - # - # Returns +true+ if this is a square matrix. - # - def square? - column_count == row_count - end - - # - # Returns +true+ if this is a symmetric matrix. - # Raises an error if matrix is not square. - # - def symmetric? - raise ErrDimensionMismatch unless square? - each_with_index(:strict_upper) do |e, row, col| - return false if e != rows[col][row] - end - true - end - - # - # Returns +true+ if this is an antisymmetric matrix. - # Raises an error if matrix is not square. - # - def antisymmetric? - raise ErrDimensionMismatch unless square? - each_with_index(:upper) do |e, row, col| - return false unless e == -rows[col][row] - end - true - end - alias_method :skew_symmetric?, :antisymmetric? - - # - # Returns +true+ if this is a unitary matrix - # Raises an error if matrix is not square. - # - def unitary? - raise ErrDimensionMismatch unless square? - rows.each_with_index do |row, i| - column_count.times do |j| - s = 0 - row_count.times do |k| - s += row[k].conj * rows[k][j] - end - return false unless s == (i == j ? 1 : 0) - end - end - true - end - - # - # Returns +true+ if this is an upper triangular matrix. - # - def upper_triangular? - each(:strict_lower).all?(&:zero?) - end - - # - # Returns +true+ if this is a matrix with only zero elements - # - def zero? - all?(&:zero?) - end - - #-- - # OBJECT METHODS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns +true+ if and only if the two matrices contain equal elements. - # - def ==(other) - return false unless Matrix === other && - column_count == other.column_count # necessary for empty matrices - rows == other.rows - end - - def eql?(other) - return false unless Matrix === other && - column_count == other.column_count # necessary for empty matrices - rows.eql? other.rows - end - - # - # Called for dup & clone. - # - private def initialize_copy(m) - super - @rows = @rows.map(&:dup) unless frozen? - end - - # - # Returns a hash-code for the matrix. - # - def hash - @rows.hash - end - - #-- - # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Matrix multiplication. - # Matrix[[2,4], [6,8]] * Matrix.identity(2) - # => 2 4 - # 6 8 - # - def *(m) # m is matrix or vector or number - case(m) - when Numeric - rows = @rows.collect {|row| - row.collect {|e| e * m } - } - return new_matrix rows, column_count - when Vector - m = self.class.column_vector(m) - r = self * m - return r.column(0) - when Matrix - raise ErrDimensionMismatch if column_count != m.row_count - - rows = Array.new(row_count) {|i| - Array.new(m.column_count) {|j| - (0 ... column_count).inject(0) do |vij, k| - vij + self[i, k] * m[k, j] - end - } - } - return new_matrix rows, m.column_count - else - return apply_through_coercion(m, __method__) - end - end - - # - # Matrix addition. - # Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]] - # => 6 0 - # -4 12 - # - def +(m) - case m - when Numeric - raise ErrOperationNotDefined, ["+", self.class, m.class] - when Vector - m = self.class.column_vector(m) - when Matrix - else - return apply_through_coercion(m, __method__) - end - - raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count - - rows = Array.new(row_count) {|i| - Array.new(column_count) {|j| - self[i, j] + m[i, j] - } - } - new_matrix rows, column_count - end - - # - # Matrix subtraction. - # Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]] - # => -8 2 - # 8 1 - # - def -(m) - case m - when Numeric - raise ErrOperationNotDefined, ["-", self.class, m.class] - when Vector - m = self.class.column_vector(m) - when Matrix - else - return apply_through_coercion(m, __method__) - end - - raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count - - rows = Array.new(row_count) {|i| - Array.new(column_count) {|j| - self[i, j] - m[i, j] - } - } - new_matrix rows, column_count - end - - # - # Matrix division (multiplication by the inverse). - # Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]] - # => -7 1 - # -3 -6 - # - def /(other) - case other - when Numeric - rows = @rows.collect {|row| - row.collect {|e| e / other } - } - return new_matrix rows, column_count - when Matrix - return self * other.inverse - else - return apply_through_coercion(other, __method__) - end - end - - # - # Hadamard product - # Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,2]]) - # => 1 4 - # 9 8 - # - def hadamard_product(m) - combine(m){|a, b| a * b} - end - alias_method :entrywise_product, :hadamard_product - - # - # Returns the inverse of the matrix. - # Matrix[[-1, -1], [0, -1]].inverse - # => -1 1 - # 0 -1 - # - def inverse - raise ErrDimensionMismatch unless square? - self.class.I(row_count).send(:inverse_from, self) - end - alias_method :inv, :inverse - - private def inverse_from(src) # :nodoc: - last = row_count - 1 - a = src.to_a - - 0.upto(last) do |k| - i = k - akk = a[k][k].abs - (k+1).upto(last) do |j| - v = a[j][k].abs - if v > akk - i = j - akk = v - end - end - raise ErrNotRegular if akk == 0 - if i != k - a[i], a[k] = a[k], a[i] - @rows[i], @rows[k] = @rows[k], @rows[i] - end - akk = a[k][k] - - 0.upto(last) do |ii| - next if ii == k - q = a[ii][k].quo(akk) - a[ii][k] = 0 - - (k + 1).upto(last) do |j| - a[ii][j] -= a[k][j] * q - end - 0.upto(last) do |j| - @rows[ii][j] -= @rows[k][j] * q - end - end - - (k+1).upto(last) do |j| - a[k][j] = a[k][j].quo(akk) - end - 0.upto(last) do |j| - @rows[k][j] = @rows[k][j].quo(akk) - end - end - self - end - - # - # Matrix exponentiation. - # Equivalent to multiplying the matrix by itself N times. - # Non integer exponents will be handled by diagonalizing the matrix. - # - # Matrix[[7,6], [3,9]] ** 2 - # => 67 96 - # 48 99 - # - def **(other) - case other - when Integer - x = self - if other <= 0 - x = self.inverse - return self.class.identity(self.column_count) if other == 0 - other = -other - end - z = nil - loop do - z = z ? z * x : x if other[0] == 1 - return z if (other >>= 1).zero? - x *= x - end - when Numeric - v, d, v_inv = eigensystem - v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv - else - raise ErrOperationNotDefined, ["**", self.class, other.class] - end - end - - def +@ - self - end - - def -@ - collect {|e| -e } - end - - # - # Returns the absolute value elementwise - # - def abs - collect(&:abs) - end - - #-- - # MATRIX FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns the determinant of the matrix. - # - # Beware that using Float values can yield erroneous results - # because of their lack of precision. - # Consider using exact types like Rational or BigDecimal instead. - # - # Matrix[[7,6], [3,9]].determinant - # => 45 - # - def determinant - raise ErrDimensionMismatch unless square? - m = @rows - case row_count - # Up to 4x4, give result using Laplacian expansion by minors. - # This will typically be faster, as well as giving good results - # in case of Floats - when 0 - +1 - when 1 - + m[0][0] - when 2 - + m[0][0] * m[1][1] - m[0][1] * m[1][0] - when 3 - m0, m1, m2 = m - + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \ - - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \ - + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0] - when 4 - m0, m1, m2, m3 = m - + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \ - - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \ - + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \ - - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \ - + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \ - - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \ - + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \ - - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \ - + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \ - - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \ - + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \ - - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0] - else - # For bigger matrices, use an efficient and general algorithm. - # Currently, we use the Gauss-Bareiss algorithm - determinant_bareiss - end - end - alias_method :det, :determinant - - # - # Private. Use Matrix#determinant - # - # Returns the determinant of the matrix, using - # Bareiss' multistep integer-preserving gaussian elimination. - # It has the same computational cost order O(n^3) as standard Gaussian elimination. - # Intermediate results are fraction free and of lower complexity. - # A matrix of Integers will have thus intermediate results that are also Integers, - # with smaller bignums (if any), while a matrix of Float will usually have - # intermediate results with better precision. - # - private def determinant_bareiss - size = row_count - last = size - 1 - a = to_a - no_pivot = Proc.new{ return 0 } - sign = +1 - pivot = 1 - size.times do |k| - previous_pivot = pivot - if (pivot = a[k][k]) == 0 - switch = (k+1 ... size).find(no_pivot) {|row| - a[row][k] != 0 - } - a[switch], a[k] = a[k], a[switch] - pivot = a[k][k] - sign = -sign - end - (k+1).upto(last) do |i| - ai = a[i] - (k+1).upto(last) do |j| - ai[j] = (pivot * ai[j] - ai[k] * a[k][j]) / previous_pivot - end - end - end - sign * pivot - end - - # - # deprecated; use Matrix#determinant - # - def determinant_e - warn "Matrix#determinant_e is deprecated; use #determinant", uplevel: 1 - determinant - end - alias_method :det_e, :determinant_e - - # - # Returns a new matrix resulting by stacking horizontally - # the receiver with the given matrices - # - # x = Matrix[[1, 2], [3, 4]] - # y = Matrix[[5, 6], [7, 8]] - # x.hstack(y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]] - # - def hstack(*matrices) - self.class.hstack(self, *matrices) - end - - # - # Returns the rank of the matrix. - # Beware that using Float values can yield erroneous results - # because of their lack of precision. - # Consider using exact types like Rational or BigDecimal instead. - # - # Matrix[[7,6], [3,9]].rank - # => 2 - # - def rank - # We currently use Bareiss' multistep integer-preserving gaussian elimination - # (see comments on determinant) - a = to_a - last_column = column_count - 1 - last_row = row_count - 1 - pivot_row = 0 - previous_pivot = 1 - 0.upto(last_column) do |k| - switch_row = (pivot_row .. last_row).find {|row| - a[row][k] != 0 - } - if switch_row - a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row - pivot = a[pivot_row][k] - (pivot_row+1).upto(last_row) do |i| - ai = a[i] - (k+1).upto(last_column) do |j| - ai[j] = (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot - end - end - pivot_row += 1 - previous_pivot = pivot - end - end - pivot_row - end - - # - # deprecated; use Matrix#rank - # - def rank_e - warn "Matrix#rank_e is deprecated; use #rank", uplevel: 1 - rank - end - - # Returns a matrix with entries rounded to the given precision - # (see Float#round) - # - def round(ndigits=0) - map{|e| e.round(ndigits)} - end - - # - # Returns the trace (sum of diagonal elements) of the matrix. - # Matrix[[7,6], [3,9]].trace - # => 16 - # - def trace - raise ErrDimensionMismatch unless square? - (0...column_count).inject(0) do |tr, i| - tr + @rows[i][i] - end - end - alias_method :tr, :trace - - # - # Returns the transpose of the matrix. - # Matrix[[1,2], [3,4], [5,6]] - # => 1 2 - # 3 4 - # 5 6 - # Matrix[[1,2], [3,4], [5,6]].transpose - # => 1 3 5 - # 2 4 6 - # - def transpose - return self.class.empty(column_count, 0) if row_count.zero? - new_matrix @rows.transpose, row_count - end - alias_method :t, :transpose - - # - # Returns a new matrix resulting by stacking vertically - # the receiver with the given matrices - # - # x = Matrix[[1, 2], [3, 4]] - # y = Matrix[[5, 6], [7, 8]] - # x.vstack(y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]] - # - def vstack(*matrices) - self.class.vstack(self, *matrices) - end - - #-- - # DECOMPOSITIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - #++ - - # - # Returns the Eigensystem of the matrix; see +EigenvalueDecomposition+. - # m = Matrix[[1, 2], [3, 4]] - # v, d, v_inv = m.eigensystem - # d.diagonal? # => true - # v.inv == v_inv # => true - # (v * d * v_inv).round(5) == m # => true - # - def eigensystem - EigenvalueDecomposition.new(self) - end - alias_method :eigen, :eigensystem - - # - # Returns the LUP decomposition of the matrix; see +LUPDecomposition+. - # a = Matrix[[1, 2], [3, 4]] - # l, u, p = a.lup - # l.lower_triangular? # => true - # u.upper_triangular? # => true - # p.permutation? # => true - # l * u == p * a # => true - # a.lup.solve([2, 5]) # => Vector[(1/1), (1/2)] - # - def lup - LUPDecomposition.new(self) - end - alias_method :lup_decomposition, :lup - - #-- - # COMPLEX ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - #++ - - # - # Returns the conjugate of the matrix. - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] - # => 1+2i i 0 - # 1 2 3 - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate - # => 1-2i -i 0 - # 1 2 3 - # - def conjugate - collect(&:conjugate) - end - alias_method :conj, :conjugate - - # - # Returns the imaginary part of the matrix. - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] - # => 1+2i i 0 - # 1 2 3 - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary - # => 2i i 0 - # 0 0 0 - # - def imaginary - collect(&:imaginary) - end - alias_method :imag, :imaginary - - # - # Returns the real part of the matrix. - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] - # => 1+2i i 0 - # 1 2 3 - # Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real - # => 1 0 0 - # 1 2 3 - # - def real - collect(&:real) - end - - # - # Returns an array containing matrices corresponding to the real and imaginary - # parts of the matrix - # - # m.rect == [m.real, m.imag] # ==> true for all matrices m - # - def rect - [real, imag] - end - alias_method :rectangular, :rect - - #-- - # CONVERTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # The coerce method provides support for Ruby type coercion. - # This coercion mechanism is used by Ruby to handle mixed-type - # numeric operations: it is intended to find a compatible common - # type between the two operands of the operator. - # See also Numeric#coerce. - # - def coerce(other) - case other - when Numeric - return Scalar.new(other), self - else - raise TypeError, "#{self.class} can't be coerced into #{other.class}" - end - end - - # - # Returns an array of the row vectors of the matrix. See Vector. - # - def row_vectors - Array.new(row_count) {|i| - row(i) - } - end - - # - # Returns an array of the column vectors of the matrix. See Vector. - # - def column_vectors - Array.new(column_count) {|i| - column(i) - } - end - - # - # Explicit conversion to a Matrix. Returns self - # - def to_matrix - self - end - - # - # Returns an array of arrays that describe the rows of the matrix. - # - def to_a - @rows.collect(&:dup) - end - - # Deprecated. - # - # Use map(&:to_f) - def elements_to_f - warn "Matrix#elements_to_f is deprecated, use map(&:to_f)", uplevel: 1 - map(&:to_f) - end - - # Deprecated. - # - # Use map(&:to_i) - def elements_to_i - warn "Matrix#elements_to_i is deprecated, use map(&:to_i)", uplevel: 1 - map(&:to_i) - end - - # Deprecated. - # - # Use map(&:to_r) - def elements_to_r - warn "Matrix#elements_to_r is deprecated, use map(&:to_r)", uplevel: 1 - map(&:to_r) - end - - #-- - # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Overrides Object#to_s - # - def to_s - if empty? - "#{self.class}.empty(#{row_count}, #{column_count})" - else - "#{self.class}[" + @rows.collect{|row| - "[" + row.collect{|e| e.to_s}.join(", ") + "]" - }.join(", ")+"]" - end - end - - # - # Overrides Object#inspect - # - def inspect - if empty? - "#{self.class}.empty(#{row_count}, #{column_count})" - else - "#{self.class}#{@rows.inspect}" - end - end - - # Private helper modules - - module ConversionHelper # :nodoc: - # - # Converts the obj to an Array. If copy is set to true - # a copy of obj will be made if necessary. - # - private def convert_to_array(obj, copy = false) # :nodoc: - case obj - when Array - copy ? obj.dup : obj - when Vector - obj.to_a - else - begin - converted = obj.to_ary - rescue Exception => e - raise TypeError, "can't convert #{obj.class} into an Array (#{e.message})" - end - raise TypeError, "#{obj.class}#to_ary should return an Array" unless converted.is_a? Array - converted - end - end - end - - extend ConversionHelper - - module CoercionHelper # :nodoc: - # - # Applies the operator +oper+ with argument +obj+ - # through coercion of +obj+ - # - private def apply_through_coercion(obj, oper) - coercion = obj.coerce(self) - raise TypeError unless coercion.is_a?(Array) && coercion.length == 2 - coercion[0].public_send(oper, coercion[1]) - rescue - raise TypeError, "#{obj.inspect} can't be coerced into #{self.class}" - end - - # - # Helper method to coerce a value into a specific class. - # Raises a TypeError if the coercion fails or the returned value - # is not of the right class. - # (from Rubinius) - # - def self.coerce_to(obj, cls, meth) # :nodoc: - return obj if obj.kind_of?(cls) - raise TypeError, "Expected a #{cls} but got a #{obj.class}" unless obj.respond_to? meth - begin - ret = obj.__send__(meth) - rescue Exception => e - raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \ - "(#{e.message})" - end - raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls - ret - end - - def self.coerce_to_int(obj) - coerce_to(obj, Integer, :to_int) - end - - def self.coerce_to_matrix(obj) - coerce_to(obj, Matrix, :to_matrix) - end - - # Returns `nil` for non Ranges - # Checks range validity, return canonical range with 0 <= begin <= end < count - def self.check_range(val, count, kind) - canonical = (val.begin + (val.begin < 0 ? count : 0)).. - (val.end ? val.end + (val.end < 0 ? count : 0) - (val.exclude_end? ? 1 : 0) - : count - 1) - unless 0 <= canonical.begin && canonical.begin <= canonical.end && canonical.end < count - raise IndexError, "given range #{val} is outside of #{kind} dimensions: 0...#{count}" - end - canonical - end - - def self.check_int(val, count, kind) - val = CoercionHelper.coerce_to_int(val) - if val >= count || val < -count - raise IndexError, "given #{kind} #{val} is outside of #{-count}...#{count}" - end - val - end - end - - include CoercionHelper - - # Private CLASS - - class Scalar < Numeric # :nodoc: - include ExceptionForMatrix - include CoercionHelper - - def initialize(value) - @value = value - end - - # ARITHMETIC - def +(other) - case other - when Numeric - Scalar.new(@value + other) - when Vector, Matrix - raise ErrOperationNotDefined, ["+", @value.class, other.class] - else - apply_through_coercion(other, __method__) - end - end - - def -(other) - case other - when Numeric - Scalar.new(@value - other) - when Vector, Matrix - raise ErrOperationNotDefined, ["-", @value.class, other.class] - else - apply_through_coercion(other, __method__) - end - end - - def *(other) - case other - when Numeric - Scalar.new(@value * other) - when Vector, Matrix - other.collect{|e| @value * e} - else - apply_through_coercion(other, __method__) - end - end - - def /(other) - case other - when Numeric - Scalar.new(@value / other) - when Vector - raise ErrOperationNotDefined, ["/", @value.class, other.class] - when Matrix - self * other.inverse - else - apply_through_coercion(other, __method__) - end - end - - def **(other) - case other - when Numeric - Scalar.new(@value ** other) - when Vector - raise ErrOperationNotDefined, ["**", @value.class, other.class] - when Matrix - #other.powered_by(self) - raise ErrOperationNotImplemented, ["**", @value.class, other.class] - else - apply_through_coercion(other, __method__) - end - end - end - -end - - -# -# The +Vector+ class represents a mathematical vector, which is useful in its own right, and -# also constitutes a row or column of a Matrix. -# -# == Method Catalogue -# -# To create a Vector: -# * Vector.[](*array) -# * Vector.elements(array, copy = true) -# * Vector.basis(size: n, index: k) -# * Vector.zero(n) -# -# To access elements: -# * #[](i) -# -# To set elements: -# * #[]=(i, v) -# -# To enumerate the elements: -# * #each2(v) -# * #collect2(v) -# -# Properties of vectors: -# * #angle_with(v) -# * Vector.independent?(*vs) -# * #independent?(*vs) -# * #zero? -# -# Vector arithmetic: -# * #*(x) "is matrix or number" -# * #+(v) -# * #-(v) -# * #/(v) -# * #+@ -# * #-@ -# -# Vector functions: -# * #inner_product(v), dot(v) -# * #cross_product(v), cross(v) -# * #collect -# * #collect! -# * #magnitude -# * #map -# * #map! -# * #map2(v) -# * #norm -# * #normalize -# * #r -# * #round -# * #size -# -# Conversion to other data types: -# * #covector -# * #to_a -# * #coerce(other) -# -# String representations: -# * #to_s -# * #inspect -# -class Vector - include ExceptionForMatrix - include Enumerable - include Matrix::CoercionHelper - extend Matrix::ConversionHelper - #INSTANCE CREATION - - private_class_method :new - attr_reader :elements - protected :elements - - # - # Creates a Vector from a list of elements. - # Vector[7, 4, ...] - # - def Vector.[](*array) - new convert_to_array(array, false) - end - - # - # Creates a vector from an Array. The optional second argument specifies - # whether the array itself or a copy is used internally. - # - def Vector.elements(array, copy = true) - new convert_to_array(array, copy) - end - - # - # Returns a standard basis +n+-vector, where k is the index. - # - # Vector.basis(size:, index:) # => Vector[0, 1, 0] - # - def Vector.basis(size:, index:) - raise ArgumentError, "invalid size (#{size} for 1..)" if size < 1 - raise ArgumentError, "invalid index (#{index} for 0...#{size})" unless 0 <= index && index < size - array = Array.new(size, 0) - array[index] = 1 - new convert_to_array(array, false) - end - - # - # Return a zero vector. - # - # Vector.zero(3) => Vector[0, 0, 0] - # - def Vector.zero(size) - raise ArgumentError, "invalid size (#{size} for 0..)" if size < 0 - array = Array.new(size, 0) - new convert_to_array(array, false) - end - - # - # Vector.new is private; use Vector[] or Vector.elements to create. - # - def initialize(array) - # No checking is done at this point. - @elements = array - end - - # ACCESSING - - # - # :call-seq: - # vector[range] - # vector[integer] - # - # Returns element or elements of the vector. - # - def [](i) - @elements[i] - end - alias element [] - alias component [] - - # - # :call-seq: - # vector[range] = new_vector - # vector[range] = row_matrix - # vector[range] = new_element - # vector[integer] = new_element - # - # Set element or elements of vector. - # - def []=(i, v) - raise FrozenError, "can't modify frozen Vector" if frozen? - if i.is_a?(Range) - range = Matrix::CoercionHelper.check_range(i, size, :vector) - set_range(range, v) - else - index = Matrix::CoercionHelper.check_int(i, size, :index) - set_value(index, v) - end - end - alias set_element []= - alias set_component []= - private :set_element, :set_component - - private def set_value(index, value) - @elements[index] = value - end - - private def set_range(range, value) - if value.is_a?(Vector) - raise ArgumentError, "vector to be set has wrong size" unless range.size == value.size - @elements[range] = value.elements - elsif value.is_a?(Matrix) - raise ErrDimensionMismatch unless value.row_count == 1 - @elements[range] = value.row(0).elements - else - @elements[range] = Array.new(range.size, value) - end - end - - # Returns a vector with entries rounded to the given precision - # (see Float#round) - # - def round(ndigits=0) - map{|e| e.round(ndigits)} - end - - # - # Returns the number of elements in the vector. - # - def size - @elements.size - end - - #-- - # ENUMERATIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Iterate over the elements of this vector - # - def each(&block) - return to_enum(:each) unless block_given? - @elements.each(&block) - self - end - - # - # Iterate over the elements of this vector and +v+ in conjunction. - # - def each2(v) # :yield: e1, e2 - raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) - raise ErrDimensionMismatch if size != v.size - return to_enum(:each2, v) unless block_given? - size.times do |i| - yield @elements[i], v[i] - end - self - end - - # - # Collects (as in Enumerable#collect) over the elements of this vector and +v+ - # in conjunction. - # - def collect2(v) # :yield: e1, e2 - raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) - raise ErrDimensionMismatch if size != v.size - return to_enum(:collect2, v) unless block_given? - Array.new(size) do |i| - yield @elements[i], v[i] - end - end - - #-- - # PROPERTIES -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns +true+ iff all of vectors are linearly independent. - # - # Vector.independent?(Vector[1,0], Vector[0,1]) - # => true - # - # Vector.independent?(Vector[1,2], Vector[2,4]) - # => false - # - def Vector.independent?(*vs) - vs.each do |v| - raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector) - raise ErrDimensionMismatch unless v.size == vs.first.size - end - return false if vs.count > vs.first.size - Matrix[*vs].rank.eql?(vs.count) - end - - # - # Returns +true+ iff all of vectors are linearly independent. - # - # Vector[1,0].independent?(Vector[0,1]) - # => true - # - # Vector[1,2].independent?(Vector[2,4]) - # => false - # - def independent?(*vs) - self.class.independent?(self, *vs) - end - - # - # Returns +true+ iff all elements are zero. - # - def zero? - all?(&:zero?) - end - - def freeze - @elements.freeze - super - end - - # - # Called for dup & clone. - # - private def initialize_copy(v) - super - @elements = @elements.dup unless frozen? - end - - - #-- - # COMPARING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns +true+ iff the two vectors have the same elements in the same order. - # - def ==(other) - return false unless Vector === other - @elements == other.elements - end - - def eql?(other) - return false unless Vector === other - @elements.eql? other.elements - end - - # - # Returns a hash-code for the vector. - # - def hash - @elements.hash - end - - #-- - # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Multiplies the vector by +x+, where +x+ is a number or a matrix. - # - def *(x) - case x - when Numeric - els = @elements.collect{|e| e * x} - self.class.elements(els, false) - when Matrix - Matrix.column_vector(self) * x - when Vector - raise ErrOperationNotDefined, ["*", self.class, x.class] - else - apply_through_coercion(x, __method__) - end - end - - # - # Vector addition. - # - def +(v) - case v - when Vector - raise ErrDimensionMismatch if size != v.size - els = collect2(v) {|v1, v2| - v1 + v2 - } - self.class.elements(els, false) - when Matrix - Matrix.column_vector(self) + v - else - apply_through_coercion(v, __method__) - end - end - - # - # Vector subtraction. - # - def -(v) - case v - when Vector - raise ErrDimensionMismatch if size != v.size - els = collect2(v) {|v1, v2| - v1 - v2 - } - self.class.elements(els, false) - when Matrix - Matrix.column_vector(self) - v - else - apply_through_coercion(v, __method__) - end - end - - # - # Vector division. - # - def /(x) - case x - when Numeric - els = @elements.collect{|e| e / x} - self.class.elements(els, false) - when Matrix, Vector - raise ErrOperationNotDefined, ["/", self.class, x.class] - else - apply_through_coercion(x, __method__) - end - end - - def +@ - self - end - - def -@ - collect {|e| -e } - end - - #-- - # VECTOR FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Returns the inner product of this vector with the other. - # Vector[4,7].inner_product Vector[10,1] => 47 - # - def inner_product(v) - raise ErrDimensionMismatch if size != v.size - - p = 0 - each2(v) {|v1, v2| - p += v1 * v2.conj - } - p - end - alias_method :dot, :inner_product - - # - # Returns the cross product of this vector with the others. - # Vector[1, 0, 0].cross_product Vector[0, 1, 0] => Vector[0, 0, 1] - # - # It is generalized to other dimensions to return a vector perpendicular - # to the arguments. - # Vector[1, 2].cross_product # => Vector[-2, 1] - # Vector[1, 0, 0, 0].cross_product( - # Vector[0, 1, 0, 0], - # Vector[0, 0, 1, 0] - # ) #=> Vector[0, 0, 0, 1] - # - def cross_product(*vs) - raise ErrOperationNotDefined, "cross product is not defined on vectors of dimension #{size}" unless size >= 2 - raise ArgumentError, "wrong number of arguments (#{vs.size} for #{size - 2})" unless vs.size == size - 2 - vs.each do |v| - raise TypeError, "expected Vector, got #{v.class}" unless v.is_a? Vector - raise ErrDimensionMismatch unless v.size == size - end - case size - when 2 - Vector[-@elements[1], @elements[0]] - when 3 - v = vs[0] - Vector[ v[2]*@elements[1] - v[1]*@elements[2], - v[0]*@elements[2] - v[2]*@elements[0], - v[1]*@elements[0] - v[0]*@elements[1] ] - else - rows = self, *vs, Array.new(size) {|i| Vector.basis(size: size, index: i) } - Matrix.rows(rows).laplace_expansion(row: size - 1) - end - end - alias_method :cross, :cross_product - - # - # Like Array#collect. - # - def collect(&block) # :yield: e - return to_enum(:collect) unless block_given? - els = @elements.collect(&block) - self.class.elements(els, false) - end - alias_method :map, :collect - - # - # Like Array#collect! - # - def collect!(&block) - return to_enum(:collect!) unless block_given? - raise FrozenError, "can't modify frozen Vector" if frozen? - @elements.collect!(&block) - self - end - alias map! collect! - - # - # Returns the modulus (Pythagorean distance) of the vector. - # Vector[5,8,2].r => 9.643650761 - # - def magnitude - Math.sqrt(@elements.inject(0) {|v, e| v + e.abs2}) - end - alias_method :r, :magnitude - alias_method :norm, :magnitude - - # - # Like Vector#collect2, but returns a Vector instead of an Array. - # - def map2(v, &block) # :yield: e1, e2 - return to_enum(:map2, v) unless block_given? - els = collect2(v, &block) - self.class.elements(els, false) - end - - class ZeroVectorError < StandardError - end - # - # Returns a new vector with the same direction but with norm 1. - # v = Vector[5,8,2].normalize - # # => Vector[0.5184758473652127, 0.8295613557843402, 0.20739033894608505] - # v.norm => 1.0 - # - def normalize - n = magnitude - raise ZeroVectorError, "Zero vectors can not be normalized" if n == 0 - self / n - end - - # - # Returns an angle with another vector. Result is within the [0..Math::PI]. - # Vector[1,0].angle_with(Vector[0,1]) - # # => Math::PI / 2 - # - def angle_with(v) - raise TypeError, "Expected a Vector, got a #{v.class}" unless v.is_a?(Vector) - raise ErrDimensionMismatch if size != v.size - prod = magnitude * v.magnitude - raise ZeroVectorError, "Can't get angle of zero vector" if prod == 0 - dot = inner_product(v) - if dot.abs >= prod - dot.positive? ? 0 : Math::PI - else - Math.acos(dot / prod) - end - end - - #-- - # CONVERTING - #++ - - # - # Creates a single-row matrix from this vector. - # - def covector - Matrix.row_vector(self) - end - - # - # Returns the elements of the vector in an array. - # - def to_a - @elements.dup - end - - # - # Return a single-column matrix from this vector - # - def to_matrix - Matrix.column_vector(self) - end - - def elements_to_f - warn "Vector#elements_to_f is deprecated", uplevel: 1 - map(&:to_f) - end - - def elements_to_i - warn "Vector#elements_to_i is deprecated", uplevel: 1 - map(&:to_i) - end - - def elements_to_r - warn "Vector#elements_to_r is deprecated", uplevel: 1 - map(&:to_r) - end - - # - # The coerce method provides support for Ruby type coercion. - # This coercion mechanism is used by Ruby to handle mixed-type - # numeric operations: it is intended to find a compatible common - # type between the two operands of the operator. - # See also Numeric#coerce. - # - def coerce(other) - case other - when Numeric - return Matrix::Scalar.new(other), self - else - raise TypeError, "#{self.class} can't be coerced into #{other.class}" - end - end - - #-- - # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - #++ - - # - # Overrides Object#to_s - # - def to_s - "Vector[" + @elements.join(", ") + "]" - end - - # - # Overrides Object#inspect - # - def inspect - "Vector" + @elements.inspect - end -end diff --git a/ruby/lib/matrix/eigenvalue_decomposition.rb b/ruby/lib/matrix/eigenvalue_decomposition.rb deleted file mode 100644 index bf6637635..000000000 --- a/ruby/lib/matrix/eigenvalue_decomposition.rb +++ /dev/null @@ -1,882 +0,0 @@ -# frozen_string_literal: false -class Matrix - # Adapted from JAMA: http://math.nist.gov/javanumerics/jama/ - - # Eigenvalues and eigenvectors of a real matrix. - # - # Computes the eigenvalues and eigenvectors of a matrix A. - # - # If A is diagonalizable, this provides matrices V and D - # such that A = V*D*V.inv, where D is the diagonal matrix with entries - # equal to the eigenvalues and V is formed by the eigenvectors. - # - # If A is symmetric, then V is orthogonal and thus A = V*D*V.t - - class EigenvalueDecomposition - - # Constructs the eigenvalue decomposition for a square matrix +A+ - # - def initialize(a) - # @d, @e: Arrays for internal storage of eigenvalues. - # @v: Array for internal storage of eigenvectors. - # @h: Array for internal storage of nonsymmetric Hessenberg form. - raise TypeError, "Expected Matrix but got #{a.class}" unless a.is_a?(Matrix) - @size = a.row_count - @d = Array.new(@size, 0) - @e = Array.new(@size, 0) - - if (@symmetric = a.symmetric?) - @v = a.to_a - tridiagonalize - diagonalize - else - @v = Array.new(@size) { Array.new(@size, 0) } - @h = a.to_a - @ort = Array.new(@size, 0) - reduce_to_hessenberg - hessenberg_to_real_schur - end - end - - # Returns the eigenvector matrix +V+ - # - def eigenvector_matrix - Matrix.send(:new, build_eigenvectors.transpose) - end - alias_method :v, :eigenvector_matrix - - # Returns the inverse of the eigenvector matrix +V+ - # - def eigenvector_matrix_inv - r = Matrix.send(:new, build_eigenvectors) - r = r.transpose.inverse unless @symmetric - r - end - alias_method :v_inv, :eigenvector_matrix_inv - - # Returns the eigenvalues in an array - # - def eigenvalues - values = @d.dup - @e.each_with_index{|imag, i| values[i] = Complex(values[i], imag) unless imag == 0} - values - end - - # Returns an array of the eigenvectors - # - def eigenvectors - build_eigenvectors.map{|ev| Vector.send(:new, ev)} - end - - # Returns the block diagonal eigenvalue matrix +D+ - # - def eigenvalue_matrix - Matrix.diagonal(*eigenvalues) - end - alias_method :d, :eigenvalue_matrix - - # Returns [eigenvector_matrix, eigenvalue_matrix, eigenvector_matrix_inv] - # - def to_ary - [v, d, v_inv] - end - alias_method :to_a, :to_ary - - - private def build_eigenvectors - # JAMA stores complex eigenvectors in a strange way - # See http://web.archive.org/web/20111016032731/http://cio.nist.gov/esd/emaildir/lists/jama/msg01021.html - @e.each_with_index.map do |imag, i| - if imag == 0 - Array.new(@size){|j| @v[j][i]} - elsif imag > 0 - Array.new(@size){|j| Complex(@v[j][i], @v[j][i+1])} - else - Array.new(@size){|j| Complex(@v[j][i-1], -@v[j][i])} - end - end - end - - # Complex scalar division. - - private def cdiv(xr, xi, yr, yi) - if (yr.abs > yi.abs) - r = yi/yr - d = yr + r*yi - [(xr + r*xi)/d, (xi - r*xr)/d] - else - r = yr/yi - d = yi + r*yr - [(r*xr + xi)/d, (r*xi - xr)/d] - end - end - - - # Symmetric Householder reduction to tridiagonal form. - - private def tridiagonalize - - # This is derived from the Algol procedures tred2 by - # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - # Fortran subroutine in EISPACK. - - @size.times do |j| - @d[j] = @v[@size-1][j] - end - - # Householder reduction to tridiagonal form. - - (@size-1).downto(0+1) do |i| - - # Scale to avoid under/overflow. - - scale = 0.0 - h = 0.0 - i.times do |k| - scale = scale + @d[k].abs - end - if (scale == 0.0) - @e[i] = @d[i-1] - i.times do |j| - @d[j] = @v[i-1][j] - @v[i][j] = 0.0 - @v[j][i] = 0.0 - end - else - - # Generate Householder vector. - - i.times do |k| - @d[k] /= scale - h += @d[k] * @d[k] - end - f = @d[i-1] - g = Math.sqrt(h) - if (f > 0) - g = -g - end - @e[i] = scale * g - h -= f * g - @d[i-1] = f - g - i.times do |j| - @e[j] = 0.0 - end - - # Apply similarity transformation to remaining columns. - - i.times do |j| - f = @d[j] - @v[j][i] = f - g = @e[j] + @v[j][j] * f - (j+1).upto(i-1) do |k| - g += @v[k][j] * @d[k] - @e[k] += @v[k][j] * f - end - @e[j] = g - end - f = 0.0 - i.times do |j| - @e[j] /= h - f += @e[j] * @d[j] - end - hh = f / (h + h) - i.times do |j| - @e[j] -= hh * @d[j] - end - i.times do |j| - f = @d[j] - g = @e[j] - j.upto(i-1) do |k| - @v[k][j] -= (f * @e[k] + g * @d[k]) - end - @d[j] = @v[i-1][j] - @v[i][j] = 0.0 - end - end - @d[i] = h - end - - # Accumulate transformations. - - 0.upto(@size-1-1) do |i| - @v[@size-1][i] = @v[i][i] - @v[i][i] = 1.0 - h = @d[i+1] - if (h != 0.0) - 0.upto(i) do |k| - @d[k] = @v[k][i+1] / h - end - 0.upto(i) do |j| - g = 0.0 - 0.upto(i) do |k| - g += @v[k][i+1] * @v[k][j] - end - 0.upto(i) do |k| - @v[k][j] -= g * @d[k] - end - end - end - 0.upto(i) do |k| - @v[k][i+1] = 0.0 - end - end - @size.times do |j| - @d[j] = @v[@size-1][j] - @v[@size-1][j] = 0.0 - end - @v[@size-1][@size-1] = 1.0 - @e[0] = 0.0 - end - - - # Symmetric tridiagonal QL algorithm. - - private def diagonalize - # This is derived from the Algol procedures tql2, by - # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - # Fortran subroutine in EISPACK. - - 1.upto(@size-1) do |i| - @e[i-1] = @e[i] - end - @e[@size-1] = 0.0 - - f = 0.0 - tst1 = 0.0 - eps = Float::EPSILON - @size.times do |l| - - # Find small subdiagonal element - - tst1 = [tst1, @d[l].abs + @e[l].abs].max - m = l - while (m < @size) do - if (@e[m].abs <= eps*tst1) - break - end - m+=1 - end - - # If m == l, @d[l] is an eigenvalue, - # otherwise, iterate. - - if (m > l) - iter = 0 - begin - iter = iter + 1 # (Could check iteration count here.) - - # Compute implicit shift - - g = @d[l] - p = (@d[l+1] - g) / (2.0 * @e[l]) - r = Math.hypot(p, 1.0) - if (p < 0) - r = -r - end - @d[l] = @e[l] / (p + r) - @d[l+1] = @e[l] * (p + r) - dl1 = @d[l+1] - h = g - @d[l] - (l+2).upto(@size-1) do |i| - @d[i] -= h - end - f += h - - # Implicit QL transformation. - - p = @d[m] - c = 1.0 - c2 = c - c3 = c - el1 = @e[l+1] - s = 0.0 - s2 = 0.0 - (m-1).downto(l) do |i| - c3 = c2 - c2 = c - s2 = s - g = c * @e[i] - h = c * p - r = Math.hypot(p, @e[i]) - @e[i+1] = s * r - s = @e[i] / r - c = p / r - p = c * @d[i] - s * g - @d[i+1] = h + s * (c * g + s * @d[i]) - - # Accumulate transformation. - - @size.times do |k| - h = @v[k][i+1] - @v[k][i+1] = s * @v[k][i] + c * h - @v[k][i] = c * @v[k][i] - s * h - end - end - p = -s * s2 * c3 * el1 * @e[l] / dl1 - @e[l] = s * p - @d[l] = c * p - - # Check for convergence. - - end while (@e[l].abs > eps*tst1) - end - @d[l] = @d[l] + f - @e[l] = 0.0 - end - - # Sort eigenvalues and corresponding vectors. - - 0.upto(@size-2) do |i| - k = i - p = @d[i] - (i+1).upto(@size-1) do |j| - if (@d[j] < p) - k = j - p = @d[j] - end - end - if (k != i) - @d[k] = @d[i] - @d[i] = p - @size.times do |j| - p = @v[j][i] - @v[j][i] = @v[j][k] - @v[j][k] = p - end - end - end - end - - # Nonsymmetric reduction to Hessenberg form. - - private def reduce_to_hessenberg - # This is derived from the Algol procedures orthes and ortran, - # by Martin and Wilkinson, Handbook for Auto. Comp., - # Vol.ii-Linear Algebra, and the corresponding - # Fortran subroutines in EISPACK. - - low = 0 - high = @size-1 - - (low+1).upto(high-1) do |m| - - # Scale column. - - scale = 0.0 - m.upto(high) do |i| - scale = scale + @h[i][m-1].abs - end - if (scale != 0.0) - - # Compute Householder transformation. - - h = 0.0 - high.downto(m) do |i| - @ort[i] = @h[i][m-1]/scale - h += @ort[i] * @ort[i] - end - g = Math.sqrt(h) - if (@ort[m] > 0) - g = -g - end - h -= @ort[m] * g - @ort[m] = @ort[m] - g - - # Apply Householder similarity transformation - # @h = (I-u*u'/h)*@h*(I-u*u')/h) - - m.upto(@size-1) do |j| - f = 0.0 - high.downto(m) do |i| - f += @ort[i]*@h[i][j] - end - f = f/h - m.upto(high) do |i| - @h[i][j] -= f*@ort[i] - end - end - - 0.upto(high) do |i| - f = 0.0 - high.downto(m) do |j| - f += @ort[j]*@h[i][j] - end - f = f/h - m.upto(high) do |j| - @h[i][j] -= f*@ort[j] - end - end - @ort[m] = scale*@ort[m] - @h[m][m-1] = scale*g - end - end - - # Accumulate transformations (Algol's ortran). - - @size.times do |i| - @size.times do |j| - @v[i][j] = (i == j ? 1.0 : 0.0) - end - end - - (high-1).downto(low+1) do |m| - if (@h[m][m-1] != 0.0) - (m+1).upto(high) do |i| - @ort[i] = @h[i][m-1] - end - m.upto(high) do |j| - g = 0.0 - m.upto(high) do |i| - g += @ort[i] * @v[i][j] - end - # Double division avoids possible underflow - g = (g / @ort[m]) / @h[m][m-1] - m.upto(high) do |i| - @v[i][j] += g * @ort[i] - end - end - end - end - end - - # Nonsymmetric reduction from Hessenberg to real Schur form. - - private def hessenberg_to_real_schur - - # This is derived from the Algol procedure hqr2, - # by Martin and Wilkinson, Handbook for Auto. Comp., - # Vol.ii-Linear Algebra, and the corresponding - # Fortran subroutine in EISPACK. - - # Initialize - - nn = @size - n = nn-1 - low = 0 - high = nn-1 - eps = Float::EPSILON - exshift = 0.0 - p = q = r = s = z = 0 - - # Store roots isolated by balanc and compute matrix norm - - norm = 0.0 - nn.times do |i| - if (i < low || i > high) - @d[i] = @h[i][i] - @e[i] = 0.0 - end - ([i-1, 0].max).upto(nn-1) do |j| - norm = norm + @h[i][j].abs - end - end - - # Outer loop over eigenvalue index - - iter = 0 - while (n >= low) do - - # Look for single small sub-diagonal element - - l = n - while (l > low) do - s = @h[l-1][l-1].abs + @h[l][l].abs - if (s == 0.0) - s = norm - end - if (@h[l][l-1].abs < eps * s) - break - end - l-=1 - end - - # Check for convergence - # One root found - - if (l == n) - @h[n][n] = @h[n][n] + exshift - @d[n] = @h[n][n] - @e[n] = 0.0 - n-=1 - iter = 0 - - # Two roots found - - elsif (l == n-1) - w = @h[n][n-1] * @h[n-1][n] - p = (@h[n-1][n-1] - @h[n][n]) / 2.0 - q = p * p + w - z = Math.sqrt(q.abs) - @h[n][n] = @h[n][n] + exshift - @h[n-1][n-1] = @h[n-1][n-1] + exshift - x = @h[n][n] - - # Real pair - - if (q >= 0) - if (p >= 0) - z = p + z - else - z = p - z - end - @d[n-1] = x + z - @d[n] = @d[n-1] - if (z != 0.0) - @d[n] = x - w / z - end - @e[n-1] = 0.0 - @e[n] = 0.0 - x = @h[n][n-1] - s = x.abs + z.abs - p = x / s - q = z / s - r = Math.sqrt(p * p+q * q) - p /= r - q /= r - - # Row modification - - (n-1).upto(nn-1) do |j| - z = @h[n-1][j] - @h[n-1][j] = q * z + p * @h[n][j] - @h[n][j] = q * @h[n][j] - p * z - end - - # Column modification - - 0.upto(n) do |i| - z = @h[i][n-1] - @h[i][n-1] = q * z + p * @h[i][n] - @h[i][n] = q * @h[i][n] - p * z - end - - # Accumulate transformations - - low.upto(high) do |i| - z = @v[i][n-1] - @v[i][n-1] = q * z + p * @v[i][n] - @v[i][n] = q * @v[i][n] - p * z - end - - # Complex pair - - else - @d[n-1] = x + p - @d[n] = x + p - @e[n-1] = z - @e[n] = -z - end - n -= 2 - iter = 0 - - # No convergence yet - - else - - # Form shift - - x = @h[n][n] - y = 0.0 - w = 0.0 - if (l < n) - y = @h[n-1][n-1] - w = @h[n][n-1] * @h[n-1][n] - end - - # Wilkinson's original ad hoc shift - - if (iter == 10) - exshift += x - low.upto(n) do |i| - @h[i][i] -= x - end - s = @h[n][n-1].abs + @h[n-1][n-2].abs - x = y = 0.75 * s - w = -0.4375 * s * s - end - - # MATLAB's new ad hoc shift - - if (iter == 30) - s = (y - x) / 2.0 - s *= s + w - if (s > 0) - s = Math.sqrt(s) - if (y < x) - s = -s - end - s = x - w / ((y - x) / 2.0 + s) - low.upto(n) do |i| - @h[i][i] -= s - end - exshift += s - x = y = w = 0.964 - end - end - - iter = iter + 1 # (Could check iteration count here.) - - # Look for two consecutive small sub-diagonal elements - - m = n-2 - while (m >= l) do - z = @h[m][m] - r = x - z - s = y - z - p = (r * s - w) / @h[m+1][m] + @h[m][m+1] - q = @h[m+1][m+1] - z - r - s - r = @h[m+2][m+1] - s = p.abs + q.abs + r.abs - p /= s - q /= s - r /= s - if (m == l) - break - end - if (@h[m][m-1].abs * (q.abs + r.abs) < - eps * (p.abs * (@h[m-1][m-1].abs + z.abs + - @h[m+1][m+1].abs))) - break - end - m-=1 - end - - (m+2).upto(n) do |i| - @h[i][i-2] = 0.0 - if (i > m+2) - @h[i][i-3] = 0.0 - end - end - - # Double QR step involving rows l:n and columns m:n - - m.upto(n-1) do |k| - notlast = (k != n-1) - if (k != m) - p = @h[k][k-1] - q = @h[k+1][k-1] - r = (notlast ? @h[k+2][k-1] : 0.0) - x = p.abs + q.abs + r.abs - next if x == 0 - p /= x - q /= x - r /= x - end - s = Math.sqrt(p * p + q * q + r * r) - if (p < 0) - s = -s - end - if (s != 0) - if (k != m) - @h[k][k-1] = -s * x - elsif (l != m) - @h[k][k-1] = -@h[k][k-1] - end - p += s - x = p / s - y = q / s - z = r / s - q /= p - r /= p - - # Row modification - - k.upto(nn-1) do |j| - p = @h[k][j] + q * @h[k+1][j] - if (notlast) - p += r * @h[k+2][j] - @h[k+2][j] = @h[k+2][j] - p * z - end - @h[k][j] = @h[k][j] - p * x - @h[k+1][j] = @h[k+1][j] - p * y - end - - # Column modification - - 0.upto([n, k+3].min) do |i| - p = x * @h[i][k] + y * @h[i][k+1] - if (notlast) - p += z * @h[i][k+2] - @h[i][k+2] = @h[i][k+2] - p * r - end - @h[i][k] = @h[i][k] - p - @h[i][k+1] = @h[i][k+1] - p * q - end - - # Accumulate transformations - - low.upto(high) do |i| - p = x * @v[i][k] + y * @v[i][k+1] - if (notlast) - p += z * @v[i][k+2] - @v[i][k+2] = @v[i][k+2] - p * r - end - @v[i][k] = @v[i][k] - p - @v[i][k+1] = @v[i][k+1] - p * q - end - end # (s != 0) - end # k loop - end # check convergence - end # while (n >= low) - - # Backsubstitute to find vectors of upper triangular form - - if (norm == 0.0) - return - end - - (nn-1).downto(0) do |k| - p = @d[k] - q = @e[k] - - # Real vector - - if (q == 0) - l = k - @h[k][k] = 1.0 - (k-1).downto(0) do |i| - w = @h[i][i] - p - r = 0.0 - l.upto(k) do |j| - r += @h[i][j] * @h[j][k] - end - if (@e[i] < 0.0) - z = w - s = r - else - l = i - if (@e[i] == 0.0) - if (w != 0.0) - @h[i][k] = -r / w - else - @h[i][k] = -r / (eps * norm) - end - - # Solve real equations - - else - x = @h[i][i+1] - y = @h[i+1][i] - q = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] - t = (x * s - z * r) / q - @h[i][k] = t - if (x.abs > z.abs) - @h[i+1][k] = (-r - w * t) / x - else - @h[i+1][k] = (-s - y * t) / z - end - end - - # Overflow control - - t = @h[i][k].abs - if ((eps * t) * t > 1) - i.upto(k) do |j| - @h[j][k] = @h[j][k] / t - end - end - end - end - - # Complex vector - - elsif (q < 0) - l = n-1 - - # Last vector component imaginary so matrix is triangular - - if (@h[n][n-1].abs > @h[n-1][n].abs) - @h[n-1][n-1] = q / @h[n][n-1] - @h[n-1][n] = -(@h[n][n] - p) / @h[n][n-1] - else - cdivr, cdivi = cdiv(0.0, -@h[n-1][n], @h[n-1][n-1]-p, q) - @h[n-1][n-1] = cdivr - @h[n-1][n] = cdivi - end - @h[n][n-1] = 0.0 - @h[n][n] = 1.0 - (n-2).downto(0) do |i| - ra = 0.0 - sa = 0.0 - l.upto(n) do |j| - ra = ra + @h[i][j] * @h[j][n-1] - sa = sa + @h[i][j] * @h[j][n] - end - w = @h[i][i] - p - - if (@e[i] < 0.0) - z = w - r = ra - s = sa - else - l = i - if (@e[i] == 0) - cdivr, cdivi = cdiv(-ra, -sa, w, q) - @h[i][n-1] = cdivr - @h[i][n] = cdivi - else - - # Solve complex equations - - x = @h[i][i+1] - y = @h[i+1][i] - vr = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] - q * q - vi = (@d[i] - p) * 2.0 * q - if (vr == 0.0 && vi == 0.0) - vr = eps * norm * (w.abs + q.abs + - x.abs + y.abs + z.abs) - end - cdivr, cdivi = cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi) - @h[i][n-1] = cdivr - @h[i][n] = cdivi - if (x.abs > (z.abs + q.abs)) - @h[i+1][n-1] = (-ra - w * @h[i][n-1] + q * @h[i][n]) / x - @h[i+1][n] = (-sa - w * @h[i][n] - q * @h[i][n-1]) / x - else - cdivr, cdivi = cdiv(-r-y*@h[i][n-1], -s-y*@h[i][n], z, q) - @h[i+1][n-1] = cdivr - @h[i+1][n] = cdivi - end - end - - # Overflow control - - t = [@h[i][n-1].abs, @h[i][n].abs].max - if ((eps * t) * t > 1) - i.upto(n) do |j| - @h[j][n-1] = @h[j][n-1] / t - @h[j][n] = @h[j][n] / t - end - end - end - end - end - end - - # Vectors of isolated roots - - nn.times do |i| - if (i < low || i > high) - i.upto(nn-1) do |j| - @v[i][j] = @h[i][j] - end - end - end - - # Back transformation to get eigenvectors of original matrix - - (nn-1).downto(low) do |j| - low.upto(high) do |i| - z = 0.0 - low.upto([j, high].min) do |k| - z += @v[i][k] * @h[k][j] - end - @v[i][j] = z - end - end - end - - end -end diff --git a/ruby/lib/matrix/lup_decomposition.rb b/ruby/lib/matrix/lup_decomposition.rb deleted file mode 100644 index e37def75f..000000000 --- a/ruby/lib/matrix/lup_decomposition.rb +++ /dev/null @@ -1,219 +0,0 @@ -# frozen_string_literal: false -class Matrix - # Adapted from JAMA: http://math.nist.gov/javanumerics/jama/ - - # - # For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n - # unit lower triangular matrix L, an n-by-n upper triangular matrix U, - # and a m-by-m permutation matrix P so that L*U = P*A. - # If m < n, then L is m-by-m and U is m-by-n. - # - # The LUP decomposition with pivoting always exists, even if the matrix is - # singular, so the constructor will never fail. The primary use of the - # LU decomposition is in the solution of square systems of simultaneous - # linear equations. This will fail if singular? returns true. - # - - class LUPDecomposition - # Returns the lower triangular factor +L+ - - include Matrix::ConversionHelper - - def l - Matrix.build(@row_count, [@column_count, @row_count].min) do |i, j| - if (i > j) - @lu[i][j] - elsif (i == j) - 1 - else - 0 - end - end - end - - # Returns the upper triangular factor +U+ - - def u - Matrix.build([@column_count, @row_count].min, @column_count) do |i, j| - if (i <= j) - @lu[i][j] - else - 0 - end - end - end - - # Returns the permutation matrix +P+ - - def p - rows = Array.new(@row_count){Array.new(@row_count, 0)} - @pivots.each_with_index{|p, i| rows[i][p] = 1} - Matrix.send :new, rows, @row_count - end - - # Returns +L+, +U+, +P+ in an array - - def to_ary - [l, u, p] - end - alias_method :to_a, :to_ary - - # Returns the pivoting indices - - attr_reader :pivots - - # Returns +true+ if +U+, and hence +A+, is singular. - - def singular? - @column_count.times do |j| - if (@lu[j][j] == 0) - return true - end - end - false - end - - # Returns the determinant of +A+, calculated efficiently - # from the factorization. - - def det - if (@row_count != @column_count) - raise Matrix::ErrDimensionMismatch - end - d = @pivot_sign - @column_count.times do |j| - d *= @lu[j][j] - end - d - end - alias_method :determinant, :det - - # Returns +m+ so that A*m = b, - # or equivalently so that L*U*m = P*b - # +b+ can be a Matrix or a Vector - - def solve b - if (singular?) - raise Matrix::ErrNotRegular, "Matrix is singular." - end - if b.is_a? Matrix - if (b.row_count != @row_count) - raise Matrix::ErrDimensionMismatch - end - - # Copy right hand side with pivoting - nx = b.column_count - m = @pivots.map{|row| b.row(row).to_a} - - # Solve L*Y = P*b - @column_count.times do |k| - (k+1).upto(@column_count-1) do |i| - nx.times do |j| - m[i][j] -= m[k][j]*@lu[i][k] - end - end - end - # Solve U*m = Y - (@column_count-1).downto(0) do |k| - nx.times do |j| - m[k][j] = m[k][j].quo(@lu[k][k]) - end - k.times do |i| - nx.times do |j| - m[i][j] -= m[k][j]*@lu[i][k] - end - end - end - Matrix.send :new, m, nx - else # same algorithm, specialized for simpler case of a vector - b = convert_to_array(b) - if (b.size != @row_count) - raise Matrix::ErrDimensionMismatch - end - - # Copy right hand side with pivoting - m = b.values_at(*@pivots) - - # Solve L*Y = P*b - @column_count.times do |k| - (k+1).upto(@column_count-1) do |i| - m[i] -= m[k]*@lu[i][k] - end - end - # Solve U*m = Y - (@column_count-1).downto(0) do |k| - m[k] = m[k].quo(@lu[k][k]) - k.times do |i| - m[i] -= m[k]*@lu[i][k] - end - end - Vector.elements(m, false) - end - end - - def initialize a - raise TypeError, "Expected Matrix but got #{a.class}" unless a.is_a?(Matrix) - # Use a "left-looking", dot-product, Crout/Doolittle algorithm. - @lu = a.to_a - @row_count = a.row_count - @column_count = a.column_count - @pivots = Array.new(@row_count) - @row_count.times do |i| - @pivots[i] = i - end - @pivot_sign = 1 - lu_col_j = Array.new(@row_count) - - # Outer loop. - - @column_count.times do |j| - - # Make a copy of the j-th column to localize references. - - @row_count.times do |i| - lu_col_j[i] = @lu[i][j] - end - - # Apply previous transformations. - - @row_count.times do |i| - lu_row_i = @lu[i] - - # Most of the time is spent in the following dot product. - - kmax = [i, j].min - s = 0 - kmax.times do |k| - s += lu_row_i[k]*lu_col_j[k] - end - - lu_row_i[j] = lu_col_j[i] -= s - end - - # Find pivot and exchange if necessary. - - p = j - (j+1).upto(@row_count-1) do |i| - if (lu_col_j[i].abs > lu_col_j[p].abs) - p = i - end - end - if (p != j) - @column_count.times do |k| - t = @lu[p][k]; @lu[p][k] = @lu[j][k]; @lu[j][k] = t - end - k = @pivots[p]; @pivots[p] = @pivots[j]; @pivots[j] = k - @pivot_sign = -@pivot_sign - end - - # Compute multipliers. - - if (j < @row_count && @lu[j][j] != 0) - (j+1).upto(@row_count-1) do |i| - @lu[i][j] = @lu[i][j].quo(@lu[j][j]) - end - end - end - end - end -end diff --git a/ruby/lib/matrix/matrix.gemspec b/ruby/lib/matrix/matrix.gemspec deleted file mode 100644 index 75f6b69a9..000000000 --- a/ruby/lib/matrix/matrix.gemspec +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -begin - require_relative "lib/matrix/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "matrix" - spec.version = Matrix::VERSION - spec.authors = ["Marc-Andre Lafortune"] - spec.email = ["ruby-core@marc-andre.ca"] - - spec.summary = %q{An implementation of Matrix and Vector classes.} - spec.description = %q{An implementation of Matrix and Vector classes.} - spec.homepage = "https://github.com/ruby/matrix" - spec.license = "BSD-2-Clause" - - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/matrix.rb", "lib/matrix/eigenvalue_decomposition.rb", "lib/matrix/lup_decomposition.rb", "lib/matrix/version.rb", "matrix.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" -end diff --git a/ruby/lib/matrix/version.rb b/ruby/lib/matrix/version.rb deleted file mode 100644 index e6f91dae3..000000000 --- a/ruby/lib/matrix/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class Matrix - VERSION = "0.2.0" -end diff --git a/ruby/lib/mkmf.rb b/ruby/lib/mkmf.rb index 8820e5c0b..118b81314 100644 --- a/ruby/lib/mkmf.rb +++ b/ruby/lib/mkmf.rb @@ -207,8 +207,8 @@ def install_dirs(target_prefix = nil) ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'], ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'], - ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'], - ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'], + ['HDRDIR', '$(vendorhdrdir)$(target_prefix)'], + ['ARCHHDRDIR', '$(vendorarchhdrdir)$(target_prefix)'], ] else dirs = [ @@ -216,8 +216,8 @@ def install_dirs(target_prefix = nil) ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'], ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'], - ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'], - ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'], + ['HDRDIR', '$(sitehdrdir)$(target_prefix)'], + ['ARCHHDRDIR', '$(sitearchhdrdir)$(target_prefix)'], ] end dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")] @@ -284,7 +284,8 @@ def modified?(target, times) end def split_libs(*strs) - strs.map {|s| s.split(/\s+(?=-|\z)/)}.flatten + sep = $mswin ? /\s+/ : /\s+(?=-|\z)/ + strs.flat_map {|s| s.lstrip.split(sep)} end def merge_libs(*libs) @@ -385,38 +386,64 @@ def libpath_env end end - def xsystem command, opts = nil + def expand_command(commands, envs = libpath_env) varpat = /\$\((\w+)\)|\$\{(\w+)\}/ - if varpat =~ command - vars = Hash.new {|h, k| h[k] = ENV[k]} - command = command.dup - nil while command.gsub!(varpat) {vars[$1||$2]} + vars = nil + expand = proc do |command| + case command + when Array + command.map(&expand) + when String + if varpat =~ command + vars ||= Hash.new {|h, k| h[k] = ENV[k]} + command = command.dup + nil while command.gsub!(varpat) {vars[$1||$2]} + end + command + else + command + end end + if Array === commands + env, *commands = commands if Hash === commands.first + envs.merge!(env) if env + end + return envs, expand[commands] + end + + def env_quote(envs) + envs.map {|e, v| "#{e}=#{v.quote}"} + end + + def xsystem command, opts = nil + env, command = expand_command(command) Logging::open do - puts command.quote + puts [env_quote(env), command.quote].join(' ') if opts and opts[:werror] result = nil Logging.postpone do |log| - output = IO.popen(libpath_env, command, &:read) + output = IO.popen(env, command, &:read) result = ($?.success? and File.zero?(log.path)) output end result else - system(libpath_env, command) + system(env, *command) end end end def xpopen command, *mode, &block + env, commands = expand_command(command) + command = [env_quote(env), command].join(' ') Logging::open do case mode[0] - when nil, /^r/ + when nil, Hash, /^r/ puts "#{command} |" else puts "| #{command}" end - IO.popen(libpath_env, command, *mode, &block) + IO.popen(env, commands, *mode, &block) end end @@ -446,7 +473,7 @@ def create_tmpsrc(src) src.sub!(/[^\n]\z/, "\\&\n") count = 0 begin - open(conftest_source, "wb") do |cfile| + File.open(conftest_source, "wb") do |cfile| cfile.print src end rescue Errno::EACCES @@ -616,7 +643,7 @@ def try_cpp(src, opt="", *opts, &b) MakeMakefile.rm_f "#{CONFTEST}*" end - alias_method :try_header, (config_string('try_header') || :try_cpp) + alias try_header try_compile def cpp_include(header) if header @@ -770,11 +797,20 @@ def try_constant(const, headers = nil, opt = "", &b) # files. def try_func(func, libs, headers = nil, opt = "", &b) headers = cpp_include(headers) + prepare = String.new case func when /^&/ decltype = proc {|x|"const volatile void *#{x}"} when /\)$/ - call = func + strvars = [] + call = func.gsub(/""/) { + v = "s#{strvars.size + 1}" + strvars << v + v + } + unless strvars.empty? + prepare << "char " << strvars.map {|v| "#{v}[1024]"}.join(", ") << "; " + end when nil call = "" else @@ -784,7 +820,7 @@ def try_func(func, libs, headers = nil, opt = "", &b) if opt and !opt.empty? [[:to_str], [:join, " "], [:to_s]].each do |meth, *args| if opt.respond_to?(meth) - break opt = opt.send(meth, *args) + break opt = opt.__send__(meth, *args) end end opt = "#{opt} #{libs}" @@ -804,7 +840,7 @@ def try_func(func, libs, headers = nil, opt = "", &b) extern int t(void); #{MAIN_DOES_NOTHING 't'} #{"extern void #{call};" if decltype} -int t(void) { #{call}; return 0; } +int t(void) { #{prepare}#{call}; return 0; } SRC end @@ -982,7 +1018,7 @@ def checking_message(target, place = nil, opt = nil) if noun [[:to_str], [:join, ","], [:to_s]].each do |meth, *args| if noun.respond_to?(meth) - break noun = noun.send(meth, *args) + break noun = noun.__send__(meth, *args) end end unless noun.empty? @@ -1047,7 +1083,7 @@ def have_library(lib, func = nil, headers = nil, opt = "", &b) def find_library(lib, func, *paths, &b) dir_config(lib) lib = with_config(lib+'lib', lib) - paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten + paths = paths.flat_map {|path| path.split(File::PATH_SEPARATOR)} checking_for checking_message(func && func.funcall_style, LIBARG%lib) do libpath = $LIBPATH libs = append_library($libs, lib) @@ -1728,7 +1764,7 @@ def create_header(header = "extconf.h") hdr = hdr.join("") log_src(hdr, "#{header} is") unless (IO.read(header) == hdr rescue false) - open(header, "wb") do |hfile| + File.open(header, "wb") do |hfile| hfile.write(hdr) end end @@ -1820,16 +1856,24 @@ def dir_config(target, idefault=nil, ldefault=nil) # invoked with the option and a stripped output string is returned # without modifying any of the global values mentioned above. def pkg_config(pkg, option=nil) + _, ldir = dir_config(pkg) + if ldir + pkg_config_path = "#{ldir}/pkgconfig" + if File.directory?(pkg_config_path) + Logging.message("PKG_CONFIG_PATH = %s\n", pkg_config_path) + envs = ["PKG_CONFIG_PATH"=>[pkg_config_path, ENV["PKG_CONFIG_PATH"]].compact.join(File::PATH_SEPARATOR)] + end + end if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig) - # iff package specific config command is given + # if and only if package specific config command is given elsif ($PKGCONFIG ||= (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) && find_executable0(pkgconfig) && pkgconfig) and - xsystem("#{$PKGCONFIG} --exists #{pkg}") + xsystem([*envs, $PKGCONFIG, "--exists", pkg]) # default to pkg-config command pkgconfig = $PKGCONFIG get = proc {|opt| - opt = xpopen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read) + opt = xpopen([*envs, $PKGCONFIG, "--#{opt}", pkg], err:[:child, :out], &:read) Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}} opt.strip if $?.success? } @@ -1840,7 +1884,7 @@ def pkg_config(pkg, option=nil) end if pkgconfig get ||= proc {|opt| - opt = xpopen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read) + opt = xpopen([*envs, pkgconfig, "--#{opt}"], err:[:child, :out], &:read) Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}} opt.strip if $?.success? } @@ -1908,7 +1952,7 @@ def mkintpath(path) path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1') path end - when 'cygwin' + when 'cygwin', 'msys' if CONFIG['target_os'] != 'cygwin' def mkintpath(path) IO.popen(["cygpath", "-u", path], &:read).chomp @@ -1931,6 +1975,7 @@ def configuration(srcdir) # V=0 quiet, V=1 verbose. other values don't work. V = 0 +V0 = $(V:0=) Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@ #{CONFIG['NULLCMD']}) @@ -1942,7 +1987,7 @@ def configuration(srcdir) srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2]).unspace}} topdir = #{mkintpath(topdir = $extmk ? CONFIG["topdir"] : $topdir).unspace} hdrdir = #{(hdrdir = CONFIG["hdrdir"]) == topdir ? "$(topdir)" : mkintpath(hdrdir).unspace} -arch_hdrdir = #{$arch_hdrdir.quote} +arch_hdrdir = #{mkintpath($arch_hdrdir).unspace} PATH_SEPARATOR = #{CONFIG['PATH_SEPARATOR']} VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])} } @@ -1970,7 +2015,7 @@ def configuration(srcdir) else sep = "" end - possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk) + possible_command = (proc {|s| s if /top_srcdir|tooldir/ !~ s} unless $extmk) extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " " headers = %w[ $(hdrdir)/ruby.h @@ -2037,7 +2082,7 @@ def configuration(srcdir) ruby_headers = #{headers.join(' ')} RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'} -RM_RF = #{'$(RUBY) -run -e rm -- -rf'} +RM_RF = #{config_string('RMALL', &possible_command) || '$(RUBY) -run -e rm -- -rf'} RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'} MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'} INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'} @@ -2222,7 +2267,7 @@ def create_makefile(target, srcprefix = nil) message "creating Makefile\n" MakeMakefile.rm_f "#{CONFTEST}*" if CONFIG["DLEXT"] == $OBJEXT - for lib in libs = $libs.split + for lib in libs = $libs.split(' ') lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%) end $defs.push(format("-DEXTLIB='%s'", libs.join(","))) @@ -2339,7 +2384,7 @@ def create_makefile(target, srcprefix = nil) " #" conf = yield(conf) if block_given? - mfile = open("Makefile", "wb") + mfile = File.open("Makefile", "wb") mfile.puts(conf) mfile.print " all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"} @@ -2496,7 +2541,7 @@ def create_makefile(target, srcprefix = nil) mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) " mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)" config_string('RANLIB') do |ranlib| - mfile.print "\n\t-$(Q)#{ranlib} $(@) 2> /dev/null || true" + mfile.print "\n\t-$(Q)#{ranlib} $(@)#{$ignore_error}" end end mfile.print "\n\n" @@ -2719,17 +2764,17 @@ def MAIN_DOES_NOTHING(*refs) TRY_LINK = config_string('TRY_LINK') || "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \ - "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS) $(LDFLAGS)" + "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)" ## # Command which will link a shared library LINK_SO = (config_string('LINK_SO') || "").sub(/^$/) do if CONFIG["DLEXT"] == $OBJEXT - "ld $(DLDFLAGS) -r -o $@ $(OBJS) $(DLDFLAGS)\n" + "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n" else "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \ - "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) $(DLDFLAGS)" + "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)" end end @@ -2762,14 +2807,14 @@ def MAIN_DOES_NOTHING(*refs) clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb -\t\t-$(Q)$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time +\t\t-$(Q)$(RM_RF) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb -\t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log +\t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log#{' exts.mk' if $extmk} \t\t-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep}) \t\t-$(Q)$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error} @@ -2822,7 +2867,12 @@ def link_command(ldflags, *opts) end end -include MakeMakefile +# MakeMakefile::Global = # +m = Module.new { + include(MakeMakefile) + private(*MakeMakefile.public_instance_methods(false)) +} +include m if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0) END {mkmf_failed($0)} diff --git a/ruby/lib/mutex_m.gemspec b/ruby/lib/mutex_m.gemspec index 409ed5b7b..f614dcd9a 100644 --- a/ruby/lib/mutex_m.gemspec +++ b/ruby/lib/mutex_m.gemspec @@ -14,9 +14,9 @@ Gem::Specification.new do |spec| 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/mutex_m.rb", "mutex_m.gemspec"] + 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"] diff --git a/ruby/lib/mutex_m.rb b/ruby/lib/mutex_m.rb index dd47934be..abd0fc6ad 100644 --- a/ruby/lib/mutex_m.rb +++ b/ruby/lib/mutex_m.rb @@ -40,7 +40,8 @@ # module Mutex_m - VERSION = "0.1.0" + VERSION = "0.1.1" + Ractor.make_shareable(VERSION) if defined?(Ractor) def Mutex_m.define_aliases(cl) # :nodoc: cl.module_eval %q{ @@ -73,32 +74,32 @@ def mu_extended # :nodoc: mu_initialize end - # See Mutex#synchronize + # See Thread::Mutex#synchronize def mu_synchronize(&block) @_mutex.synchronize(&block) end - # See Mutex#locked? + # See Thread::Mutex#locked? def mu_locked? @_mutex.locked? end - # See Mutex#try_lock + # See Thread::Mutex#try_lock def mu_try_lock @_mutex.try_lock end - # See Mutex#lock + # See Thread::Mutex#lock def mu_lock @_mutex.lock end - # See Mutex#unlock + # See Thread::Mutex#unlock def mu_unlock @_mutex.unlock end - # See Mutex#sleep + # See Thread::Mutex#sleep def sleep(timeout = nil) @_mutex.sleep(timeout) end @@ -113,4 +114,5 @@ def initialize(*args) # :nodoc: mu_initialize super end + ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) end diff --git a/ruby/lib/net/ftp.rb b/ruby/lib/net/ftp.rb deleted file mode 100644 index d1e545c0c..000000000 --- a/ruby/lib/net/ftp.rb +++ /dev/null @@ -1,1533 +0,0 @@ -# frozen_string_literal: true -# -# = net/ftp.rb - FTP Client Library -# -# Written by Shugo Maeda . -# -# Documentation by Gavin Sinclair, sourced from "Programming Ruby" (Hunt/Thomas) -# and "Ruby In a Nutshell" (Matsumoto), used with permission. -# -# This library is distributed under the terms of the Ruby license. -# You can freely distribute/modify this library. -# -# It is included in the Ruby standard library. -# -# See the Net::FTP class for an overview. -# - -require "socket" -require "monitor" -require_relative "protocol" -require "time" -begin - require "openssl" -rescue LoadError -end - -module Net - - # :stopdoc: - class FTPError < StandardError; end - class FTPReplyError < FTPError; end - class FTPTempError < FTPError; end - class FTPPermError < FTPError; end - class FTPProtoError < FTPError; end - class FTPConnectionError < FTPError; end - # :startdoc: - - # - # This class implements the File Transfer Protocol. If you have used a - # command-line FTP program, and are familiar with the commands, you will be - # able to use this class easily. Some extra features are included to take - # advantage of Ruby's style and strengths. - # - # == Example - # - # require 'net/ftp' - # - # === Example 1 - # - # ftp = Net::FTP.new('example.com') - # ftp.login - # files = ftp.chdir('pub/lang/ruby/contrib') - # files = ftp.list('n*') - # ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024) - # ftp.close - # - # === Example 2 - # - # Net::FTP.open('example.com') do |ftp| - # ftp.login - # files = ftp.chdir('pub/lang/ruby/contrib') - # files = ftp.list('n*') - # ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024) - # end - # - # == Major Methods - # - # The following are the methods most likely to be useful to users: - # - FTP.open - # - #getbinaryfile - # - #gettextfile - # - #putbinaryfile - # - #puttextfile - # - #chdir - # - #nlst - # - #size - # - #rename - # - #delete - # - class FTP < Protocol - include MonitorMixin - if defined?(OpenSSL::SSL) - include OpenSSL - include SSL - end - - # :stopdoc: - FTP_PORT = 21 - CRLF = "\r\n" - DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE - @@default_passive = true - # :startdoc: - - # When +true+, transfers are performed in binary mode. Default: +true+. - attr_reader :binary - - # When +true+, the connection is in passive mode. Default: +true+. - attr_accessor :passive - - # When +true+, all traffic to and from the server is written - # to +$stdout+. Default: +false+. - attr_accessor :debug_mode - - # Sets or retrieves the +resume+ status, which decides whether incomplete - # transfers are resumed or restarted. Default: +false+. - attr_accessor :resume - - # Number of seconds to wait for the connection to open. Any number - # may be used, including Floats for fractional seconds. If the FTP - # object cannot open a connection in this many seconds, it raises a - # Net::OpenTimeout exception. The default value is +nil+. - attr_accessor :open_timeout - - # Number of seconds to wait for the TLS handshake. Any number - # may be used, including Floats for fractional seconds. If the FTP - # object cannot complete the TLS handshake in this many seconds, it - # raises a Net::OpenTimeout exception. The default value is +nil+. - # If +ssl_handshake_timeout+ is +nil+, +open_timeout+ is used instead. - attr_accessor :ssl_handshake_timeout - - # Number of seconds to wait for one block to be read (via one read(2) - # call). Any number may be used, including Floats for fractional - # seconds. If the FTP object cannot read data in this many seconds, - # it raises a Timeout::Error exception. The default value is 60 seconds. - attr_reader :read_timeout - - # Setter for the read_timeout attribute. - def read_timeout=(sec) - @sock.read_timeout = sec - @read_timeout = sec - end - - # The server's welcome message. - attr_reader :welcome - - # The server's last response code. - attr_reader :last_response_code - alias lastresp last_response_code - - # The server's last response. - attr_reader :last_response - - # When +true+, connections are in passive mode per default. - # Default: +true+. - def self.default_passive=(value) - @@default_passive = value - end - - # When +true+, connections are in passive mode per default. - # Default: +true+. - def self.default_passive - @@default_passive - end - - # - # A synonym for FTP.new, but with a mandatory host parameter. - # - # If a block is given, it is passed the +FTP+ object, which will be closed - # when the block finishes, or when an exception is raised. - # - def FTP.open(host, *args) - if block_given? - ftp = new(host, *args) - begin - yield ftp - ensure - ftp.close - end - else - new(host, *args) - end - end - - # :call-seq: - # Net::FTP.new(host = nil, options = {}) - # - # Creates and returns a new +FTP+ object. If a +host+ is given, a connection - # is made. - # - # +options+ is an option hash, each key of which is a symbol. - # - # The available options are: - # - # port:: Port number (default value is 21) - # ssl:: If options[:ssl] is true, then an attempt will be made - # to use SSL (now TLS) to connect to the server. For this - # to work OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] - # extensions need to be installed. If options[:ssl] is a - # hash, it's passed to OpenSSL::SSL::SSLContext#set_params - # as parameters. - # private_data_connection:: If true, TLS is used for data connections. - # Default: +true+ when options[:ssl] is true. - # username:: Username for login. If options[:username] is the string - # "anonymous" and the options[:password] is +nil+, - # "anonymous@" is used as a password. - # password:: Password for login. - # account:: Account information for ACCT. - # passive:: When +true+, the connection is in passive mode. Default: - # +true+. - # open_timeout:: Number of seconds to wait for the connection to open. - # See Net::FTP#open_timeout for details. Default: +nil+. - # read_timeout:: Number of seconds to wait for one block to be read. - # See Net::FTP#read_timeout for details. Default: +60+. - # ssl_handshake_timeout:: Number of seconds to wait for the TLS - # handshake. - # See Net::FTP#ssl_handshake_timeout for - # details. Default: +nil+. - # debug_mode:: When +true+, all traffic to and from the server is - # written to +$stdout+. Default: +false+. - # - def initialize(host = nil, user_or_options = {}, passwd = nil, acct = nil) - super() - begin - options = user_or_options.to_hash - rescue NoMethodError - # for backward compatibility - options = {} - options[:username] = user_or_options - options[:password] = passwd - options[:account] = acct - end - @host = nil - if options[:ssl] - unless defined?(OpenSSL::SSL) - raise "SSL extension not installed" - end - ssl_params = options[:ssl] == true ? {} : options[:ssl] - @ssl_context = SSLContext.new - @ssl_context.set_params(ssl_params) - if defined?(VerifyCallbackProc) - @ssl_context.verify_callback = VerifyCallbackProc - end - @ssl_context.session_cache_mode = - OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | - OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE - @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess } - @ssl_session = nil - if options[:private_data_connection].nil? - @private_data_connection = true - else - @private_data_connection = options[:private_data_connection] - end - else - @ssl_context = nil - if options[:private_data_connection] - raise ArgumentError, - "private_data_connection can be set to true only when ssl is enabled" - end - @private_data_connection = false - end - @binary = true - if options[:passive].nil? - @passive = @@default_passive - else - @passive = options[:passive] - end - if options[:debug_mode].nil? - @debug_mode = false - else - @debug_mode = options[:debug_mode] - end - @resume = false - @bare_sock = @sock = NullSocket.new - @logged_in = false - @open_timeout = options[:open_timeout] - @ssl_handshake_timeout = options[:ssl_handshake_timeout] - @read_timeout = options[:read_timeout] || 60 - if host - connect(host, options[:port] || FTP_PORT) - if options[:username] - login(options[:username], options[:password], options[:account]) - end - end - end - - # A setter to toggle transfers in binary mode. - # +newmode+ is either +true+ or +false+ - def binary=(newmode) - if newmode != @binary - @binary = newmode - send_type_command if @logged_in - end - end - - # Sends a command to destination host, with the current binary sendmode - # type. - # - # If binary mode is +true+, then "TYPE I" (image) is sent, otherwise "TYPE - # A" (ascii) is sent. - def send_type_command # :nodoc: - if @binary - voidcmd("TYPE I") - else - voidcmd("TYPE A") - end - end - private :send_type_command - - # Toggles transfers in binary mode and yields to a block. - # This preserves your current binary send mode, but allows a temporary - # transaction with binary sendmode of +newmode+. - # - # +newmode+ is either +true+ or +false+ - def with_binary(newmode) # :nodoc: - oldmode = binary - self.binary = newmode - begin - yield - ensure - self.binary = oldmode - end - end - private :with_binary - - # Obsolete - def return_code # :nodoc: - warn("Net::FTP#return_code is obsolete and do nothing", uplevel: 1) - return "\n" - end - - # Obsolete - def return_code=(s) # :nodoc: - warn("Net::FTP#return_code= is obsolete and do nothing", uplevel: 1) - end - - # Constructs a socket with +host+ and +port+. - # - # If SOCKSSocket is defined and the environment (ENV) defines - # SOCKS_SERVER, then a SOCKSSocket is returned, else a Socket is - # returned. - def open_socket(host, port) # :nodoc: - return Timeout.timeout(@open_timeout, OpenTimeout) { - if defined? SOCKSSocket and ENV["SOCKS_SERVER"] - @passive = true - SOCKSSocket.open(host, port) - else - Socket.tcp(host, port) - end - } - end - private :open_socket - - def start_tls_session(sock) - ssl_sock = SSLSocket.new(sock, @ssl_context) - ssl_sock.sync_close = true - ssl_sock.hostname = @host if ssl_sock.respond_to? :hostname= - if @ssl_session && - Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout - # ProFTPD returns 425 for data connections if session is not reused. - ssl_sock.session = @ssl_session - end - ssl_socket_connect(ssl_sock, @ssl_handshake_timeout || @open_timeout) - if @ssl_context.verify_mode != VERIFY_NONE - ssl_sock.post_connection_check(@host) - end - return ssl_sock - end - private :start_tls_session - - # - # Establishes an FTP connection to host, optionally overriding the default - # port. If the environment variable +SOCKS_SERVER+ is set, sets up the - # connection through a SOCKS proxy. Raises an exception (typically - # Errno::ECONNREFUSED) if the connection cannot be established. - # - def connect(host, port = FTP_PORT) - if @debug_mode - print "connect: ", host, ", ", port, "\n" - end - synchronize do - @host = host - @bare_sock = open_socket(host, port) - @sock = BufferedSocket.new(@bare_sock, read_timeout: @read_timeout) - voidresp - if @ssl_context - begin - voidcmd("AUTH TLS") - ssl_sock = start_tls_session(@bare_sock) - @sock = BufferedSSLSocket.new(ssl_sock, read_timeout: @read_timeout) - if @private_data_connection - voidcmd("PBSZ 0") - voidcmd("PROT P") - end - rescue OpenSSL::SSL::SSLError, OpenTimeout - @sock.close - raise - end - end - end - end - - # - # Set the socket used to connect to the FTP server. - # - # May raise FTPReplyError if +get_greeting+ is false. - def set_socket(sock, get_greeting = true) - synchronize do - @sock = sock - if get_greeting - voidresp - end - end - end - - # If string +s+ includes the PASS command (password), then the contents of - # the password are cleaned from the string using "*" - def sanitize(s) # :nodoc: - if s =~ /^PASS /i - return s[0, 5] + "*" * (s.length - 5) - else - return s - end - end - private :sanitize - - # Ensures that +line+ has a control return / line feed (CRLF) and writes - # it to the socket. - def putline(line) # :nodoc: - if @debug_mode - print "put: ", sanitize(line), "\n" - end - if /[\r\n]/ =~ line - raise ArgumentError, "A line must not contain CR or LF" - end - line = line + CRLF - @sock.write(line) - end - private :putline - - # Reads a line from the sock. If EOF, then it will raise EOFError - def getline # :nodoc: - line = @sock.readline # if get EOF, raise EOFError - line.sub!(/(\r\n|\n|\r)\z/n, "") - if @debug_mode - print "get: ", sanitize(line), "\n" - end - return line - end - private :getline - - # Receive a section of lines until the response code's match. - def getmultiline # :nodoc: - lines = [] - lines << getline - code = lines.last.slice(/\A([0-9a-zA-Z]{3})-/, 1) - if code - delimiter = code + " " - begin - lines << getline - end until lines.last.start_with?(delimiter) - end - return lines.join("\n") + "\n" - end - private :getmultiline - - # Receives a response from the destination host. - # - # Returns the response code or raises FTPTempError, FTPPermError, or - # FTPProtoError - def getresp # :nodoc: - @last_response = getmultiline - @last_response_code = @last_response[0, 3] - case @last_response_code - when /\A[123]/ - return @last_response - when /\A4/ - raise FTPTempError, @last_response - when /\A5/ - raise FTPPermError, @last_response - else - raise FTPProtoError, @last_response - end - end - private :getresp - - # Receives a response. - # - # Raises FTPReplyError if the first position of the response code is not - # equal 2. - def voidresp # :nodoc: - resp = getresp - if !resp.start_with?("2") - raise FTPReplyError, resp - end - end - private :voidresp - - # - # Sends a command and returns the response. - # - def sendcmd(cmd) - synchronize do - putline(cmd) - return getresp - end - end - - # - # Sends a command and expect a response beginning with '2'. - # - def voidcmd(cmd) - synchronize do - putline(cmd) - voidresp - end - end - - # Constructs and send the appropriate PORT (or EPRT) command - def sendport(host, port) # :nodoc: - remote_address = @bare_sock.remote_address - if remote_address.ipv4? - cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",") - elsif remote_address.ipv6? - cmd = sprintf("EPRT |2|%s|%d|", host, port) - else - raise FTPProtoError, host - end - voidcmd(cmd) - end - private :sendport - - # Constructs a TCPServer socket - def makeport # :nodoc: - Addrinfo.tcp(@bare_sock.local_address.ip_address, 0).listen - end - private :makeport - - # sends the appropriate command to enable a passive connection - def makepasv # :nodoc: - if @bare_sock.remote_address.ipv4? - host, port = parse227(sendcmd("PASV")) - else - host, port = parse229(sendcmd("EPSV")) - # host, port = parse228(sendcmd("LPSV")) - end - return host, port - end - private :makepasv - - # Constructs a connection for transferring data - def transfercmd(cmd, rest_offset = nil) # :nodoc: - if @passive - host, port = makepasv - conn = open_socket(host, port) - if @resume and rest_offset - resp = sendcmd("REST " + rest_offset.to_s) - if !resp.start_with?("3") - raise FTPReplyError, resp - end - end - resp = sendcmd(cmd) - # skip 2XX for some ftp servers - resp = getresp if resp.start_with?("2") - if !resp.start_with?("1") - raise FTPReplyError, resp - end - else - sock = makeport - begin - addr = sock.local_address - sendport(addr.ip_address, addr.ip_port) - if @resume and rest_offset - resp = sendcmd("REST " + rest_offset.to_s) - if !resp.start_with?("3") - raise FTPReplyError, resp - end - end - resp = sendcmd(cmd) - # skip 2XX for some ftp servers - resp = getresp if resp.start_with?("2") - if !resp.start_with?("1") - raise FTPReplyError, resp - end - conn, = sock.accept - sock.shutdown(Socket::SHUT_WR) rescue nil - sock.read rescue nil - ensure - sock.close - end - end - if @private_data_connection - return BufferedSSLSocket.new(start_tls_session(conn), - read_timeout: @read_timeout) - else - return BufferedSocket.new(conn, read_timeout: @read_timeout) - end - end - private :transfercmd - - # - # Logs in to the remote host. The session must have been - # previously connected. If +user+ is the string "anonymous" and - # the +password+ is +nil+, "anonymous@" is used as a password. If - # the +acct+ parameter is not +nil+, an FTP ACCT command is sent - # following the successful login. Raises an exception on error - # (typically Net::FTPPermError). - # - def login(user = "anonymous", passwd = nil, acct = nil) - if user == "anonymous" and passwd == nil - passwd = "anonymous@" - end - - resp = "" - synchronize do - resp = sendcmd('USER ' + user) - if resp.start_with?("3") - raise FTPReplyError, resp if passwd.nil? - resp = sendcmd('PASS ' + passwd) - end - if resp.start_with?("3") - raise FTPReplyError, resp if acct.nil? - resp = sendcmd('ACCT ' + acct) - end - end - if !resp.start_with?("2") - raise FTPReplyError, resp - end - @welcome = resp - send_type_command - @logged_in = true - end - - # - # Puts the connection into binary (image) mode, issues the given command, - # and fetches the data returned, passing it to the associated block in - # chunks of +blocksize+ characters. Note that +cmd+ is a server command - # (such as "RETR myfile"). - # - def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data - synchronize do - with_binary(true) do - begin - conn = transfercmd(cmd, rest_offset) - while data = conn.read(blocksize) - yield(data) - end - conn.shutdown(Socket::SHUT_WR) - conn.read_timeout = 1 - conn.read - ensure - conn.close if conn - end - voidresp - end - end - end - - # - # Puts the connection into ASCII (text) mode, issues the given command, and - # passes the resulting data, one line at a time, to the associated block. If - # no block is given, prints the lines. Note that +cmd+ is a server command - # (such as "RETR myfile"). - # - def retrlines(cmd) # :yield: line - synchronize do - with_binary(false) do - begin - conn = transfercmd(cmd) - while line = conn.gets - yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?) - end - conn.shutdown(Socket::SHUT_WR) - conn.read_timeout = 1 - conn.read - ensure - conn.close if conn - end - voidresp - end - end - end - - # - # Puts the connection into binary (image) mode, issues the given server-side - # command (such as "STOR myfile"), and sends the contents of the file named - # +file+ to the server. If the optional block is given, it also passes it - # the data, in chunks of +blocksize+ characters. - # - def storbinary(cmd, file, blocksize, rest_offset = nil) # :yield: data - if rest_offset - file.seek(rest_offset, IO::SEEK_SET) - end - synchronize do - with_binary(true) do - begin - conn = transfercmd(cmd) - while buf = file.read(blocksize) - conn.write(buf) - yield(buf) if block_given? - end - conn.shutdown(Socket::SHUT_WR) - conn.read_timeout = 1 - conn.read - ensure - conn.close if conn - end - voidresp - end - end - rescue Errno::EPIPE - # EPIPE, in this case, means that the data connection was unexpectedly - # terminated. Rather than just raising EPIPE to the caller, check the - # response on the control connection. If getresp doesn't raise a more - # appropriate exception, re-raise the original exception. - getresp - raise - end - - # - # Puts the connection into ASCII (text) mode, issues the given server-side - # command (such as "STOR myfile"), and sends the contents of the file - # named +file+ to the server, one line at a time. If the optional block is - # given, it also passes it the lines. - # - def storlines(cmd, file) # :yield: line - synchronize do - with_binary(false) do - begin - conn = transfercmd(cmd) - while buf = file.gets - if buf[-2, 2] != CRLF - buf = buf.chomp + CRLF - end - conn.write(buf) - yield(buf) if block_given? - end - conn.shutdown(Socket::SHUT_WR) - conn.read_timeout = 1 - conn.read - ensure - conn.close if conn - end - voidresp - end - end - rescue Errno::EPIPE - # EPIPE, in this case, means that the data connection was unexpectedly - # terminated. Rather than just raising EPIPE to the caller, check the - # response on the control connection. If getresp doesn't raise a more - # appropriate exception, re-raise the original exception. - getresp - raise - end - - # - # Retrieves +remotefile+ in binary mode, storing the result in +localfile+. - # If +localfile+ is nil, returns retrieved data. - # If a block is supplied, it is passed the retrieved data in +blocksize+ - # chunks. - # - def getbinaryfile(remotefile, localfile = File.basename(remotefile), - blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data - f = nil - result = nil - if localfile - if @resume - rest_offset = File.size?(localfile) - f = File.open(localfile, "a") - else - rest_offset = nil - f = File.open(localfile, "w") - end - elsif !block_given? - result = String.new - end - begin - f&.binmode - retrbinary("RETR #{remotefile}", blocksize, rest_offset) do |data| - f&.write(data) - block&.(data) - result&.concat(data) - end - return result - ensure - f&.close - end - end - - # - # Retrieves +remotefile+ in ASCII (text) mode, storing the result in - # +localfile+. - # If +localfile+ is nil, returns retrieved data. - # If a block is supplied, it is passed the retrieved data one - # line at a time. - # - def gettextfile(remotefile, localfile = File.basename(remotefile), - &block) # :yield: line - f = nil - result = nil - if localfile - f = File.open(localfile, "w") - elsif !block_given? - result = String.new - end - begin - retrlines("RETR #{remotefile}") do |line, newline| - l = newline ? line + "\n" : line - f&.print(l) - block&.(line, newline) - result&.concat(l) - end - return result - ensure - f&.close - end - end - - # - # Retrieves +remotefile+ in whatever mode the session is set (text or - # binary). See #gettextfile and #getbinaryfile. - # - def get(remotefile, localfile = File.basename(remotefile), - blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data - if @binary - getbinaryfile(remotefile, localfile, blocksize, &block) - else - gettextfile(remotefile, localfile, &block) - end - end - - # - # Transfers +localfile+ to the server in binary mode, storing the result in - # +remotefile+. If a block is supplied, calls it, passing in the transmitted - # data in +blocksize+ chunks. - # - def putbinaryfile(localfile, remotefile = File.basename(localfile), - blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data - if @resume - begin - rest_offset = size(remotefile) - rescue Net::FTPPermError - rest_offset = nil - end - else - rest_offset = nil - end - f = File.open(localfile) - begin - f.binmode - if rest_offset - storbinary("APPE #{remotefile}", f, blocksize, rest_offset, &block) - else - storbinary("STOR #{remotefile}", f, blocksize, rest_offset, &block) - end - ensure - f.close - end - end - - # - # Transfers +localfile+ to the server in ASCII (text) mode, storing the result - # in +remotefile+. If callback or an associated block is supplied, calls it, - # passing in the transmitted data one line at a time. - # - def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line - f = File.open(localfile) - begin - storlines("STOR #{remotefile}", f, &block) - ensure - f.close - end - end - - # - # Transfers +localfile+ to the server in whatever mode the session is set - # (text or binary). See #puttextfile and #putbinaryfile. - # - def put(localfile, remotefile = File.basename(localfile), - blocksize = DEFAULT_BLOCKSIZE, &block) - if @binary - putbinaryfile(localfile, remotefile, blocksize, &block) - else - puttextfile(localfile, remotefile, &block) - end - end - - # - # Sends the ACCT command. - # - # This is a less common FTP command, to send account - # information if the destination host requires it. - # - def acct(account) - cmd = "ACCT " + account - voidcmd(cmd) - end - - # - # Returns an array of filenames in the remote directory. - # - def nlst(dir = nil) - cmd = "NLST" - if dir - cmd = "#{cmd} #{dir}" - end - files = [] - retrlines(cmd) do |line| - files.push(line) - end - return files - end - - # - # Returns an array of file information in the directory (the output is like - # `ls -l`). If a block is given, it iterates through the listing. - # - def list(*args, &block) # :yield: line - cmd = "LIST" - args.each do |arg| - cmd = "#{cmd} #{arg}" - end - lines = [] - retrlines(cmd) do |line| - lines << line - end - if block - lines.each(&block) - end - return lines - end - alias ls list - alias dir list - - # - # MLSxEntry represents an entry in responses of MLST/MLSD. - # Each entry has the facts (e.g., size, last modification time, etc.) - # and the pathname. - # - class MLSxEntry - attr_reader :facts, :pathname - - def initialize(facts, pathname) - @facts = facts - @pathname = pathname - end - - standard_facts = %w(size modify create type unique perm - lang media-type charset) - standard_facts.each do |factname| - define_method factname.gsub(/-/, "_") do - facts[factname] - end - end - - # - # Returns +true+ if the entry is a file (i.e., the value of the type - # fact is file). - # - def file? - return facts["type"] == "file" - end - - # - # Returns +true+ if the entry is a directory (i.e., the value of the - # type fact is dir, cdir, or pdir). - # - def directory? - if /\A[cp]?dir\z/.match(facts["type"]) - return true - else - return false - end - end - - # - # Returns +true+ if the APPE command may be applied to the file. - # - def appendable? - return facts["perm"].include?(?a) - end - - # - # Returns +true+ if files may be created in the directory by STOU, - # STOR, APPE, and RNTO. - # - def creatable? - return facts["perm"].include?(?c) - end - - # - # Returns +true+ if the file or directory may be deleted by DELE/RMD. - # - def deletable? - return facts["perm"].include?(?d) - end - - # - # Returns +true+ if the directory may be entered by CWD/CDUP. - # - def enterable? - return facts["perm"].include?(?e) - end - - # - # Returns +true+ if the file or directory may be renamed by RNFR. - # - def renamable? - return facts["perm"].include?(?f) - end - - # - # Returns +true+ if the listing commands, LIST, NLST, and MLSD are - # applied to the directory. - # - def listable? - return facts["perm"].include?(?l) - end - - # - # Returns +true+ if the MKD command may be used to create a new - # directory within the directory. - # - def directory_makable? - return facts["perm"].include?(?m) - end - - # - # Returns +true+ if the objects in the directory may be deleted, or - # the directory may be purged. - # - def purgeable? - return facts["perm"].include?(?p) - end - - # - # Returns +true+ if the RETR command may be applied to the file. - # - def readable? - return facts["perm"].include?(?r) - end - - # - # Returns +true+ if the STOR command may be applied to the file. - # - def writable? - return facts["perm"].include?(?w) - end - end - - CASE_DEPENDENT_PARSER = ->(value) { value } - CASE_INDEPENDENT_PARSER = ->(value) { value.downcase } - DECIMAL_PARSER = ->(value) { value.to_i } - OCTAL_PARSER = ->(value) { value.to_i(8) } - TIME_PARSER = ->(value, local = false) { - unless /\A(?\d{4})(?\d{2})(?\d{2}) - (?\d{2})(?\d{2})(?\d{2}) - (\.(?\d+))?/x =~ value - raise FTPProtoError, "invalid time-val: #{value}" - end - usec = fractions.to_i * 10 ** (6 - fractions.to_s.size) - Time.send(local ? :local : :utc, year, month, day, hour, min, sec, usec) - } - FACT_PARSERS = Hash.new(CASE_DEPENDENT_PARSER) - FACT_PARSERS["size"] = DECIMAL_PARSER - FACT_PARSERS["modify"] = TIME_PARSER - FACT_PARSERS["create"] = TIME_PARSER - FACT_PARSERS["type"] = CASE_INDEPENDENT_PARSER - FACT_PARSERS["unique"] = CASE_DEPENDENT_PARSER - FACT_PARSERS["perm"] = CASE_INDEPENDENT_PARSER - FACT_PARSERS["lang"] = CASE_INDEPENDENT_PARSER - FACT_PARSERS["media-type"] = CASE_INDEPENDENT_PARSER - FACT_PARSERS["charset"] = CASE_INDEPENDENT_PARSER - FACT_PARSERS["unix.mode"] = OCTAL_PARSER - FACT_PARSERS["unix.owner"] = DECIMAL_PARSER - FACT_PARSERS["unix.group"] = DECIMAL_PARSER - FACT_PARSERS["unix.ctime"] = TIME_PARSER - FACT_PARSERS["unix.atime"] = TIME_PARSER - - def parse_mlsx_entry(entry) - facts, pathname = entry.chomp.split(/ /, 2) - unless pathname - raise FTPProtoError, entry - end - return MLSxEntry.new( - facts.scan(/(.*?)=(.*?);/).each_with_object({}) { - |(factname, value), h| - name = factname.downcase - h[name] = FACT_PARSERS[name].(value) - }, - pathname) - end - private :parse_mlsx_entry - - # - # Returns data (e.g., size, last modification time, entry type, etc.) - # about the file or directory specified by +pathname+. - # If +pathname+ is omitted, the current directory is assumed. - # - def mlst(pathname = nil) - cmd = pathname ? "MLST #{pathname}" : "MLST" - resp = sendcmd(cmd) - if !resp.start_with?("250") - raise FTPReplyError, resp - end - line = resp.lines[1] - unless line - raise FTPProtoError, resp - end - entry = line.sub(/\A(250-| *)/, "") - return parse_mlsx_entry(entry) - end - - # - # Returns an array of the entries of the directory specified by - # +pathname+. - # Each entry has the facts (e.g., size, last modification time, etc.) - # and the pathname. - # If a block is given, it iterates through the listing. - # If +pathname+ is omitted, the current directory is assumed. - # - def mlsd(pathname = nil, &block) # :yield: entry - cmd = pathname ? "MLSD #{pathname}" : "MLSD" - entries = [] - retrlines(cmd) do |line| - entries << parse_mlsx_entry(line) - end - if block - entries.each(&block) - end - return entries - end - - # - # Renames a file on the server. - # - def rename(fromname, toname) - resp = sendcmd("RNFR #{fromname}") - if !resp.start_with?("3") - raise FTPReplyError, resp - end - voidcmd("RNTO #{toname}") - end - - # - # Deletes a file on the server. - # - def delete(filename) - resp = sendcmd("DELE #{filename}") - if resp.start_with?("250") - return - elsif resp.start_with?("5") - raise FTPPermError, resp - else - raise FTPReplyError, resp - end - end - - # - # Changes the (remote) directory. - # - def chdir(dirname) - if dirname == ".." - begin - voidcmd("CDUP") - return - rescue FTPPermError => e - if e.message[0, 3] != "500" - raise e - end - end - end - cmd = "CWD #{dirname}" - voidcmd(cmd) - end - - def get_body(resp) # :nodoc: - resp.slice(/\A[0-9a-zA-Z]{3} (.*)$/, 1) - end - private :get_body - - # - # Returns the size of the given (remote) filename. - # - def size(filename) - with_binary(true) do - resp = sendcmd("SIZE #{filename}") - if !resp.start_with?("213") - raise FTPReplyError, resp - end - return get_body(resp).to_i - end - end - - # - # Returns the last modification time of the (remote) file. If +local+ is - # +true+, it is returned as a local time, otherwise it's a UTC time. - # - def mtime(filename, local = false) - return TIME_PARSER.(mdtm(filename), local) - end - - # - # Creates a remote directory. - # - def mkdir(dirname) - resp = sendcmd("MKD #{dirname}") - return parse257(resp) - end - - # - # Removes a remote directory. - # - def rmdir(dirname) - voidcmd("RMD #{dirname}") - end - - # - # Returns the current remote directory. - # - def pwd - resp = sendcmd("PWD") - return parse257(resp) - end - alias getdir pwd - - # - # Returns system information. - # - def system - resp = sendcmd("SYST") - if !resp.start_with?("215") - raise FTPReplyError, resp - end - return get_body(resp) - end - - # - # Aborts the previous command (ABOR command). - # - def abort - line = "ABOR" + CRLF - print "put: ABOR\n" if @debug_mode - @sock.send(line, Socket::MSG_OOB) - resp = getmultiline - unless ["426", "226", "225"].include?(resp[0, 3]) - raise FTPProtoError, resp - end - return resp - end - - # - # Returns the status (STAT command). - # - # pathname:: when stat is invoked with pathname as a parameter it acts like - # list but a lot faster and over the same tcp session. - # - def status(pathname = nil) - line = pathname ? "STAT #{pathname}" : "STAT" - if /[\r\n]/ =~ line - raise ArgumentError, "A line must not contain CR or LF" - end - print "put: #{line}\n" if @debug_mode - @sock.send(line + CRLF, Socket::MSG_OOB) - return getresp - end - - # - # Returns the raw last modification time of the (remote) file in the format - # "YYYYMMDDhhmmss" (MDTM command). - # - # Use +mtime+ if you want a parsed Time instance. - # - def mdtm(filename) - resp = sendcmd("MDTM #{filename}") - if resp.start_with?("213") - return get_body(resp) - end - end - - # - # Issues the HELP command. - # - def help(arg = nil) - cmd = "HELP" - if arg - cmd = cmd + " " + arg - end - sendcmd(cmd) - end - - # - # Exits the FTP session. - # - def quit - voidcmd("QUIT") - end - - # - # Issues a NOOP command. - # - # Does nothing except return a response. - # - def noop - voidcmd("NOOP") - end - - # - # Issues a SITE command. - # - def site(arg) - cmd = "SITE " + arg - voidcmd(cmd) - end - - # - # Issues a FEAT command - # - # Returns an array of supported optional features - # - def features - resp = sendcmd("FEAT") - if !resp.start_with?("211") - raise FTPReplyError, resp - end - - feats = [] - resp.split("\n").each do |line| - next if !line.start_with?(' ') # skip status lines - - feats << line.strip - end - - return feats - end - - # - # Issues an OPTS command - # - name Should be the name of the option to set - # - params is any optional parameters to supply with the option - # - # example: option('UTF8', 'ON') => 'OPTS UTF8 ON' - # - def option(name, params = nil) - cmd = "OPTS #{name}" - cmd += " #{params}" if params - - voidcmd(cmd) - end - - # - # Closes the connection. Further operations are impossible until you open - # a new connection with #connect. - # - def close - if @sock and not @sock.closed? - begin - @sock.shutdown(Socket::SHUT_WR) rescue nil - orig, self.read_timeout = self.read_timeout, 3 - @sock.read rescue nil - ensure - @sock.close - self.read_timeout = orig - end - end - end - - # - # Returns +true+ iff the connection is closed. - # - def closed? - @sock == nil or @sock.closed? - end - - # handler for response code 227 - # (Entering Passive Mode (h1,h2,h3,h4,p1,p2)) - # - # Returns host and port. - def parse227(resp) # :nodoc: - if !resp.start_with?("227") - raise FTPReplyError, resp - end - if m = /\((?\d+(,\d+){3}),(?\d+,\d+)\)/.match(resp) - return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"]) - else - raise FTPProtoError, resp - end - end - private :parse227 - - # handler for response code 228 - # (Entering Long Passive Mode) - # - # Returns host and port. - def parse228(resp) # :nodoc: - if !resp.start_with?("228") - raise FTPReplyError, resp - end - if m = /\(4,4,(?\d+(,\d+){3}),2,(?\d+,\d+)\)/.match(resp) - return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"]) - elsif m = /\(6,16,(?\d+(,(\d+)){15}),2,(?\d+,\d+)\)/.match(resp) - return parse_pasv_ipv6_host(m["host"]), parse_pasv_port(m["port"]) - else - raise FTPProtoError, resp - end - end - private :parse228 - - def parse_pasv_ipv4_host(s) - return s.tr(",", ".") - end - private :parse_pasv_ipv4_host - - def parse_pasv_ipv6_host(s) - return s.split(/,/).map { |i| - "%02x" % i.to_i - }.each_slice(2).map(&:join).join(":") - end - private :parse_pasv_ipv6_host - - def parse_pasv_port(s) - return s.split(/,/).map(&:to_i).inject { |x, y| - (x << 8) + y - } - end - private :parse_pasv_port - - # handler for response code 229 - # (Extended Passive Mode Entered) - # - # Returns host and port. - def parse229(resp) # :nodoc: - if !resp.start_with?("229") - raise FTPReplyError, resp - end - if m = /\((?[!-~])\k\k(?\d+)\k\)/.match(resp) - return @bare_sock.remote_address.ip_address, m["port"].to_i - else - raise FTPProtoError, resp - end - end - private :parse229 - - # handler for response code 257 - # ("PATHNAME" created) - # - # Returns host and port. - def parse257(resp) # :nodoc: - if !resp.start_with?("257") - raise FTPReplyError, resp - end - return resp.slice(/"(([^"]|"")*)"/, 1).to_s.gsub(/""/, '"') - end - private :parse257 - - # :stopdoc: - class NullSocket - def read_timeout=(sec) - end - - def closed? - true - end - - def close - end - - def method_missing(mid, *args) - raise FTPConnectionError, "not connected" - end - end - - class BufferedSocket < BufferedIO - [:local_address, :remote_address, :addr, :peeraddr, :send, :shutdown].each do |method| - define_method(method) { |*args| - @io.__send__(method, *args) - } - end - - def read(len = nil) - if len - s = super(len, String.new, true) - return s.empty? ? nil : s - else - result = String.new - while s = super(DEFAULT_BLOCKSIZE, String.new, true) - break if s.empty? - result << s - end - return result - end - end - - def gets - line = readuntil("\n", true) - return line.empty? ? nil : line - end - - def readline - line = gets - if line.nil? - raise EOFError, "end of file reached" - end - return line - end - end - - if defined?(OpenSSL::SSL::SSLSocket) - class BufferedSSLSocket < BufferedSocket - def initialize(*args, **options) - super - @is_shutdown = false - end - - def shutdown(*args) - # SSL_shutdown() will be called from SSLSocket#close, and - # SSL_shutdown() will send the "close notify" alert to the peer, - # so shutdown(2) should not be called. - @is_shutdown = true - end - - def send(mesg, flags, dest = nil) - # Ignore flags and dest. - @io.write(mesg) - end - - private - - def rbuf_fill - if @is_shutdown - raise EOFError, "shutdown has been called" - else - super - end - end - end - end - # :startdoc: - end -end - - -# Documentation comments: -# - sourced from pickaxe and nutshell, with improvements (hopefully) diff --git a/ruby/lib/net/http.rb b/ruby/lib/net/http.rb index 88a174a24..552f818e5 100644 --- a/ruby/lib/net/http.rb +++ b/ruby/lib/net/http.rb @@ -20,7 +20,7 @@ # See Net::HTTP for an overview and examples. # -require_relative 'protocol' +require 'net/protocol' require 'uri' autoload :OpenSSL, 'openssl' @@ -327,6 +327,8 @@ class HTTPHeaderSyntaxError < StandardError; end # HTTPInformation:: 1xx # HTTPContinue:: 100 # HTTPSwitchProtocol:: 101 + # HTTPProcessing:: 102 + # HTTPEarlyHints:: 103 # HTTPSuccess:: 2xx # HTTPOK:: 200 # HTTPCreated:: 201 @@ -336,6 +338,7 @@ class HTTPHeaderSyntaxError < StandardError; end # HTTPResetContent:: 205 # HTTPPartialContent:: 206 # HTTPMultiStatus:: 207 + # HTTPAlreadyReported:: 208 # HTTPIMUsed:: 226 # HTTPRedirection:: 3xx # HTTPMultipleChoices:: 300 @@ -345,6 +348,7 @@ class HTTPHeaderSyntaxError < StandardError; end # HTTPNotModified:: 304 # HTTPUseProxy:: 305 # HTTPTemporaryRedirect:: 307 + # HTTPPermanentRedirect:: 308 # HTTPClientError:: 4xx # HTTPBadRequest:: 400 # HTTPUnauthorized:: 401 @@ -364,6 +368,7 @@ class HTTPHeaderSyntaxError < StandardError; end # HTTPUnsupportedMediaType:: 415 # HTTPRequestedRangeNotSatisfiable:: 416 # HTTPExpectationFailed:: 417 + # HTTPMisdirectedRequest:: 421 # HTTPUnprocessableEntity:: 422 # HTTPLocked:: 423 # HTTPFailedDependency:: 424 @@ -379,7 +384,10 @@ class HTTPHeaderSyntaxError < StandardError; end # HTTPServiceUnavailable:: 503 # HTTPGatewayTimeOut:: 504 # HTTPVersionNotSupported:: 505 + # HTTPVariantAlsoNegotiates:: 506 # HTTPInsufficientStorage:: 507 + # HTTPLoopDetected:: 508 + # HTTPNotExtended:: 510 # HTTPNetworkAuthenticationRequired:: 511 # # There is also the Net::HTTPBadResponse exception which is raised when @@ -388,11 +396,11 @@ class HTTPHeaderSyntaxError < StandardError; end class HTTP < Protocol # :stopdoc: + VERSION = "0.2.0" Revision = %q$Revision$.split[1] HTTPVersion = '1.1' begin require 'zlib' - require 'stringio' #for our purposes (unpacking gzip) lump these together HAVE_ZLIB=true rescue LoadError HAVE_ZLIB=false @@ -427,7 +435,7 @@ class << HTTP # # Gets the body text from the target and outputs it to $stdout. The # target can either be specified as - # (+uri+), or as (+host+, +path+, +port+ = 80); so: + # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: # # Net::HTTP.get_print URI('http://www.example.com/index.html') # @@ -435,8 +443,12 @@ class << HTTP # # Net::HTTP.get_print 'www.example.com', '/index.html' # - def HTTP.get_print(uri_or_host, path = nil, port = nil) - get_response(uri_or_host, path, port) {|res| + # you can also specify request headers: + # + # Net::HTTP.get_print URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' } + # + def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil) + get_response(uri_or_host, path_or_headers, port) {|res| res.read_body do |chunk| $stdout.print chunk end @@ -446,7 +458,7 @@ def HTTP.get_print(uri_or_host, path = nil, port = nil) # Sends a GET request to the target and returns the HTTP response # as a string. The target can either be specified as - # (+uri+), or as (+host+, +path+, +port+ = 80); so: + # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: # # print Net::HTTP.get(URI('http://www.example.com/index.html')) # @@ -454,13 +466,17 @@ def HTTP.get_print(uri_or_host, path = nil, port = nil) # # print Net::HTTP.get('www.example.com', '/index.html') # - def HTTP.get(uri_or_host, path = nil, port = nil) - get_response(uri_or_host, path, port).body + # you can also specify request headers: + # + # Net::HTTP.get(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }) + # + def HTTP.get(uri_or_host, path_or_headers = nil, port = nil) + get_response(uri_or_host, path_or_headers, port).body end # Sends a GET request to the target and returns the HTTP response # as a Net::HTTPResponse object. The target can either be specified as - # (+uri+), or as (+host+, +path+, +port+ = 80); so: + # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: # # res = Net::HTTP.get_response(URI('http://www.example.com/index.html')) # print res.body @@ -470,17 +486,23 @@ def HTTP.get(uri_or_host, path = nil, port = nil) # res = Net::HTTP.get_response('www.example.com', '/index.html') # print res.body # - def HTTP.get_response(uri_or_host, path = nil, port = nil, &block) - if path + # you can also specify request headers: + # + # Net::HTTP.get_response(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }) + # + def HTTP.get_response(uri_or_host, path_or_headers = nil, port = nil, &block) + if path_or_headers && !path_or_headers.is_a?(Hash) host = uri_or_host + path = path_or_headers new(host, port || HTTP.default_port).start {|http| return http.request_get(path, &block) } else uri = uri_or_host + headers = path_or_headers start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') {|http| - return http.request_get(uri, &block) + return http.request_get(uri, headers, &block) } end end @@ -509,14 +531,13 @@ def HTTP.post(url, data, header = nil) # # { "cmd" => "search", "q" => "ruby", "max" => "50" } # - # This method also does Basic Authentication iff +url+.user exists. + # This method also does Basic Authentication if and only if +url+.user exists. # But userinfo for authentication is deprecated (RFC3986). # So this feature will be removed. # # Example: # # require 'net/http' - # require 'uri' # # Net::HTTP.post_form URI('http://www.example.com/search.cgi'), # { "q" => "ruby", "max" => "50" } @@ -571,7 +592,7 @@ def HTTP.socket_type #:nodoc: obsolete # _opt_ :: optional hash # # _opt_ sets following values by its accessor. - # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, + # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, keep_alive_timeout, # close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout, # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode. # If you set :use_ssl as true, you can use https and default value of @@ -836,6 +857,7 @@ def use_ssl=(flag) :@cert, :@cert_store, :@ciphers, + :@extra_chain_cert, :@key, :@ssl_timeout, :@ssl_version, @@ -844,6 +866,7 @@ def use_ssl=(flag) :@verify_callback, :@verify_depth, :@verify_mode, + :@verify_hostname, ] SSL_ATTRIBUTES = [ :ca_file, @@ -851,6 +874,7 @@ def use_ssl=(flag) :cert, :cert_store, :ciphers, + :extra_chain_cert, :key, :ssl_timeout, :ssl_version, @@ -859,6 +883,7 @@ def use_ssl=(flag) :verify_callback, :verify_depth, :verify_mode, + :verify_hostname, ] # Sets path of a CA certification file in PEM format. @@ -880,6 +905,10 @@ def use_ssl=(flag) # Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers= attr_accessor :ciphers + # Sets the extra X509 certificates to be added to the certificate chain. + # See OpenSSL::SSL::SSLContext#extra_chain_cert= + attr_accessor :extra_chain_cert + # Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. # (This method is appeared in Michal Rokos's OpenSSL extension.) attr_accessor :key @@ -908,6 +937,10 @@ def use_ssl=(flag) # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable. attr_accessor :verify_mode + # Sets to check the server certificate is valid for the hostname. + # See OpenSSL::SSL::SSLContext#verify_hostname= + attr_accessor :verify_hostname + # Returns the X.509 certificates the server presented. def peer_cert if not use_ssl? or not @socket @@ -946,6 +979,12 @@ def do_start private :do_start def connect + if use_ssl? + # reference early to load OpenSSL before connecting, + # as OpenSSL may take time to load. + @ssl_context = OpenSSL::SSL::SSLContext.new + end + if proxy? then conn_addr = proxy_address conn_port = proxy_port @@ -955,14 +994,13 @@ def connect end D "opening connection to #{conn_addr}:#{conn_port}..." - s = Timeout.timeout(@open_timeout, Net::OpenTimeout) { - begin - TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) - rescue => e - raise e, "Failed to open TCP connection to " + - "#{conn_addr}:#{conn_port} (#{e.message})" - end - } + begin + s = Socket.tcp conn_addr, conn_port, @local_host, @local_port, connect_timeout: @open_timeout + rescue => e + e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) #for compatibility with previous versions + raise e, "Failed to open TCP connection to " + + "#{conn_addr}:#{conn_port} (#{e.message})" + end s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) D "opened" if use_ssl? @@ -986,12 +1024,13 @@ def connect ssl_parameters = Hash.new iv_list = instance_variables SSL_IVNAMES.each_with_index do |ivname, i| - if iv_list.include?(ivname) and + if iv_list.include?(ivname) value = instance_variable_get(ivname) - ssl_parameters[SSL_ATTRIBUTES[i]] = value if value + unless value.nil? + ssl_parameters[SSL_ATTRIBUTES[i]] = value + end end end - @ssl_context = OpenSSL::SSL::SSLContext.new @ssl_context.set_params(ssl_parameters) @ssl_context.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | @@ -1007,7 +1046,7 @@ def connect s.session = @ssl_session end ssl_socket_connect(s, @open_timeout) - if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE + if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname s.post_connection_check(@address) end D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}" @@ -1016,6 +1055,7 @@ def connect write_timeout: @write_timeout, continue_timeout: @continue_timeout, debug_output: @debug_output) + @last_communicated = nil on_connect rescue => exception if s @@ -1151,7 +1191,8 @@ def proxy_port # The username of the proxy server, if one is configured. def proxy_user if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env - proxy_uri&.user + user = proxy_uri&.user + unescape(user) if user else @proxy_user end @@ -1160,7 +1201,8 @@ def proxy_user # The password of the proxy server, if one is configured. def proxy_pass if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env - proxy_uri&.password + pass = proxy_uri&.password + unescape(pass) if pass else @proxy_pass end @@ -1171,6 +1213,11 @@ def proxy_pass private + def unescape(value) + require 'cgi/util' + CGI.unescape(value) + end + # without proxy, obsolete def conn_address # :nodoc: diff --git a/ruby/lib/net/http/backward.rb b/ruby/lib/net/http/backward.rb index 9e24eae32..691e41e4f 100644 --- a/ruby/lib/net/http/backward.rb +++ b/ruby/lib/net/http/backward.rb @@ -5,22 +5,36 @@ class Net::HTTP ProxyMod = ProxyDelta -end - -module Net - HTTPSession = Net::HTTP + deprecate_constant :ProxyMod end module Net::NetPrivate HTTPRequest = ::Net::HTTPRequest + deprecate_constant :HTTPRequest end -Net::HTTPInformationCode = Net::HTTPInformation -Net::HTTPSuccessCode = Net::HTTPSuccess -Net::HTTPRedirectionCode = Net::HTTPRedirection -Net::HTTPRetriableCode = Net::HTTPRedirection -Net::HTTPClientErrorCode = Net::HTTPClientError -Net::HTTPFatalErrorCode = Net::HTTPClientError -Net::HTTPServerErrorCode = Net::HTTPServerError -Net::HTTPResponceReceiver = Net::HTTPResponse +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/ruby/lib/net/http/generic_request.rb b/ruby/lib/net/http/generic_request.rb index 003f59d0a..313de6ac9 100644 --- a/ruby/lib/net/http/generic_request.rb +++ b/ruby/lib/net/http/generic_request.rb @@ -31,12 +31,12 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) @decode_content = false - if @response_has_body and Net::HTTP::HAVE_ZLIB then + if Net::HTTP::HAVE_ZLIB then if !initheader || !initheader.keys.any? { |k| %w[accept-encoding range].include? k.downcase } then - @decode_content = true + @decode_content = true if @response_has_body initheader = initheader ? initheader.dup : {} initheader["accept-encoding"] = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" @@ -143,7 +143,7 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only end if host = self['host'] - host.sub!(/:.*/s, ''.freeze) + host.sub!(/:.*/m, ''.freeze) elsif host = @uri.host else host = addr @@ -202,9 +202,7 @@ def send_request_with_body_stream(sock, ver, path, f) IO.copy_stream(f, chunker) chunker.finish else - # copy_stream can sendfile() to sock.io unless we use SSL. - # If sock.io is an SSLSocket, copy_stream will hit SSL_write() - IO.copy_stream(f, sock.io) + IO.copy_stream(f, sock) end end diff --git a/ruby/lib/net/http/header.rb b/ruby/lib/net/http/header.rb index 8641be4ea..a8901e79c 100644 --- a/ruby/lib/net/http/header.rb +++ b/ruby/lib/net/http/header.rb @@ -423,30 +423,50 @@ def set_form_data(params, sep = '&') alias form_data= set_form_data # Set an HTML form data set. - # +params+ is the form data set; it is an Array of Arrays or a Hash - # +enctype is the type to encode the form data set. - # It is application/x-www-form-urlencoded or multipart/form-data. - # +formopt+ is an optional hash to specify the detail. + # +params+ :: The form data to set, which should be an enumerable. + # See below for more details. + # +enctype+ :: The content type to use to encode the form submission, + # which should be application/x-www-form-urlencoded or + # multipart/form-data. + # +formopt+ :: An options hash, supporting the following options: + # :boundary :: The boundary of the multipart message. If + # not given, a random boundary will be used. + # :charset :: The charset of the form submission. All + # field names and values of non-file fields + # should be encoded with this charset. # - # boundary:: the boundary of the multipart message - # charset:: the charset of the message. All names and the values of - # non-file fields are encoded as the charset. - # - # Each item of params is an array and contains following items: - # +name+:: the name of the field - # +value+:: the value of the field, it should be a String or a File - # +opt+:: an optional hash to specify additional information + # Each item of params should respond to +each+ and yield 2-3 arguments, + # or an array of 2-3 elements. The arguments yielded should be: + # * The name of the field. + # * The value of the field, it should be a String or a File or IO-like. + # * An options hash, supporting the following options, only + # used for file uploads: + # :filename :: The name of the file to use. + # :content_type :: The content type of the uploaded file. # # Each item is a file field or a normal field. - # If +value+ is a File object or the +opt+ have a filename key, + # If +value+ is a File object or the +opt+ hash has a :filename key, # the item is treated as a file field. # - # If Transfer-Encoding is set as chunked, this send the request in + # If Transfer-Encoding is set as chunked, this sends the request using # chunked encoding. Because chunked encoding is HTTP/1.1 feature, - # you must confirm the server to support HTTP/1.1 before sending it. + # you should confirm that the server supports HTTP/1.1 before using + # chunked encoding. # # Example: - # http.set_form([["q", "ruby"], ["lang", "en"]]) + # req.set_form([["q", "ruby"], ["lang", "en"]]) + # + # req.set_form({"f"=>File.open('/path/to/filename')}, + # "multipart/form-data", + # charset: "UTF-8", + # ) + # + # req.set_form([["f", + # File.open('/path/to/filename.bar'), + # {filename: "other-filename.foo"} + # ]], + # "multipart/form-data", + # ) # # See also RFC 2388, RFC 2616, HTML 4.01, and HTML5 # diff --git a/ruby/lib/net/http/net-http.gemspec b/ruby/lib/net/http/net-http.gemspec new file mode 100644 index 000000000..dd4fc2b17 --- /dev/null +++ b/ruby/lib/net/http/net-http.gemspec @@ -0,0 +1,35 @@ +# 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 = ["NARUSE, Yui"] + spec.email = ["naruse@airemix.jp"] + + spec.summary = %q{HTTP client api for Ruby.} + spec.description = %q{HTTP client api for Ruby.} + spec.homepage = "https://github.com/ruby/net-http" + spec.required_ruby_version = Gem::Requirement.new(">= 2.6.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 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + end + spec.bindir = "exe" + spec.require_paths = ["lib"] + + spec.add_dependency "net-protocol" + spec.add_dependency "uri" +end diff --git a/ruby/lib/net/http/response.rb b/ruby/lib/net/http/response.rb index 5a94f9569..08eaeb2ca 100644 --- a/ruby/lib/net/http/response.rb +++ b/ruby/lib/net/http/response.rb @@ -268,12 +268,13 @@ def inflater # :nodoc: begin yield inflate_body_io + success = true ensure - orig_err = $! begin inflate_body_io.finish rescue => err - raise orig_err || err + # Ignore #finish's error if there is an exception from yield + raise err if success end end when 'none', 'identity' then diff --git a/ruby/lib/net/imap.rb b/ruby/lib/net/imap.rb deleted file mode 100644 index 720acbc86..000000000 --- a/ruby/lib/net/imap.rb +++ /dev/null @@ -1,3728 +0,0 @@ -# frozen_string_literal: true -# -# = net/imap.rb -# -# Copyright (C) 2000 Shugo Maeda -# -# This library is distributed under the terms of the Ruby license. -# You can freely distribute/modify this library. -# -# Documentation: Shugo Maeda, with RDoc conversion and overview by William -# Webber. -# -# See Net::IMAP for documentation. -# - - -require "socket" -require "monitor" -require "digest/md5" -require "strscan" -require_relative 'protocol' -begin - require "openssl" -rescue LoadError -end - -module Net - - # - # Net::IMAP implements Internet Message Access Protocol (IMAP) client - # functionality. The protocol is described in [IMAP]. - # - # == IMAP Overview - # - # An IMAP client connects to a server, and then authenticates - # itself using either #authenticate() or #login(). Having - # authenticated itself, there is a range of commands - # available to it. Most work with mailboxes, which may be - # arranged in an hierarchical namespace, and each of which - # contains zero or more messages. How this is implemented on - # the server is implementation-dependent; on a UNIX server, it - # will frequently be implemented as files in mailbox format - # within a hierarchy of directories. - # - # To work on the messages within a mailbox, the client must - # first select that mailbox, using either #select() or (for - # read-only access) #examine(). Once the client has successfully - # selected a mailbox, they enter _selected_ state, and that - # mailbox becomes the _current_ mailbox, on which mail-item - # related commands implicitly operate. - # - # Messages have two sorts of identifiers: message sequence - # numbers and UIDs. - # - # Message sequence numbers number messages within a mailbox - # from 1 up to the number of items in the mailbox. If a new - # message arrives during a session, it receives a sequence - # number equal to the new size of the mailbox. If messages - # are expunged from the mailbox, remaining messages have their - # sequence numbers "shuffled down" to fill the gaps. - # - # UIDs, on the other hand, are permanently guaranteed not to - # identify another message within the same mailbox, even if - # the existing message is deleted. UIDs are required to - # be assigned in ascending (but not necessarily sequential) - # order within a mailbox; this means that if a non-IMAP client - # rearranges the order of mailitems within a mailbox, the - # UIDs have to be reassigned. An IMAP client thus cannot - # rearrange message orders. - # - # == Examples of Usage - # - # === List sender and subject of all recent messages in the default mailbox - # - # imap = Net::IMAP.new('mail.example.com') - # imap.authenticate('LOGIN', 'joe_user', 'joes_password') - # imap.examine('INBOX') - # imap.search(["RECENT"]).each do |message_id| - # envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"] - # puts "#{envelope.from[0].name}: \t#{envelope.subject}" - # end - # - # === Move all messages from April 2003 from "Mail/sent-mail" to "Mail/sent-apr03" - # - # imap = Net::IMAP.new('mail.example.com') - # imap.authenticate('LOGIN', 'joe_user', 'joes_password') - # imap.select('Mail/sent-mail') - # if not imap.list('Mail/', 'sent-apr03') - # imap.create('Mail/sent-apr03') - # end - # imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id| - # imap.copy(message_id, "Mail/sent-apr03") - # imap.store(message_id, "+FLAGS", [:Deleted]) - # end - # imap.expunge - # - # == Thread Safety - # - # Net::IMAP supports concurrent threads. For example, - # - # imap = Net::IMAP.new("imap.foo.net", "imap2") - # imap.authenticate("cram-md5", "bar", "password") - # imap.select("inbox") - # fetch_thread = Thread.start { imap.fetch(1..-1, "UID") } - # search_result = imap.search(["BODY", "hello"]) - # fetch_result = fetch_thread.value - # imap.disconnect - # - # This script invokes the FETCH command and the SEARCH command concurrently. - # - # == Errors - # - # An IMAP server can send three different types of responses to indicate - # failure: - # - # NO:: the attempted command could not be successfully completed. For - # instance, the username/password used for logging in are incorrect; - # the selected mailbox does not exist; etc. - # - # BAD:: the request from the client does not follow the server's - # understanding of the IMAP protocol. This includes attempting - # commands from the wrong client state; for instance, attempting - # to perform a SEARCH command without having SELECTed a current - # mailbox. It can also signal an internal server - # failure (such as a disk crash) has occurred. - # - # BYE:: the server is saying goodbye. This can be part of a normal - # logout sequence, and can be used as part of a login sequence - # to indicate that the server is (for some reason) unwilling - # to accept your connection. As a response to any other command, - # it indicates either that the server is shutting down, or that - # the server is timing out the client connection due to inactivity. - # - # These three error response are represented by the errors - # Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and - # Net::IMAP::ByeResponseError, all of which are subclasses of - # Net::IMAP::ResponseError. Essentially, all methods that involve - # sending a request to the server can generate one of these errors. - # Only the most pertinent instances have been documented below. - # - # Because the IMAP class uses Sockets for communication, its methods - # are also susceptible to the various errors that can occur when - # working with sockets. These are generally represented as - # Errno errors. For instance, any method that involves sending a - # request to the server and/or receiving a response from it could - # raise an Errno::EPIPE error if the network connection unexpectedly - # goes down. See the socket(7), ip(7), tcp(7), socket(2), connect(2), - # and associated man pages. - # - # Finally, a Net::IMAP::DataFormatError is thrown if low-level data - # is found to be in an incorrect format (for instance, when converting - # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is - # thrown if a server response is non-parseable. - # - # - # == References - # - # [[IMAP]] - # M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", - # RFC 2060, December 1996. (Note: since obsoleted by RFC 3501) - # - # [[LANGUAGE-TAGS]] - # Alvestrand, H., "Tags for the Identification of - # Languages", RFC 1766, March 1995. - # - # [[MD5]] - # Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC - # 1864, October 1995. - # - # [[MIME-IMB]] - # Freed, N., and N. Borenstein, "MIME (Multipurpose Internet - # Mail Extensions) Part One: Format of Internet Message Bodies", RFC - # 2045, November 1996. - # - # [[RFC-822]] - # Crocker, D., "Standard for the Format of ARPA Internet Text - # Messages", STD 11, RFC 822, University of Delaware, August 1982. - # - # [[RFC-2087]] - # Myers, J., "IMAP4 QUOTA extension", RFC 2087, January 1997. - # - # [[RFC-2086]] - # Myers, J., "IMAP4 ACL extension", RFC 2086, January 1997. - # - # [[RFC-2195]] - # Klensin, J., Catoe, R., and Krumviede, P., "IMAP/POP AUTHorize Extension - # for Simple Challenge/Response", RFC 2195, September 1997. - # - # [[SORT-THREAD-EXT]] - # Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD - # Extensions", draft-ietf-imapext-sort, May 2003. - # - # [[OSSL]] - # http://www.openssl.org - # - # [[RSSL]] - # http://savannah.gnu.org/projects/rubypki - # - # [[UTF7]] - # Goldsmith, D. and Davis, M., "UTF-7: A Mail-Safe Transformation Format of - # Unicode", RFC 2152, May 1997. - # - class IMAP < Protocol - include MonitorMixin - if defined?(OpenSSL::SSL) - include OpenSSL - include SSL - end - - # Returns an initial greeting response from the server. - attr_reader :greeting - - # Returns recorded untagged responses. For example: - # - # imap.select("inbox") - # p imap.responses["EXISTS"][-1] - # #=> 2 - # p imap.responses["UIDVALIDITY"][-1] - # #=> 968263756 - attr_reader :responses - - # Returns all response handlers. - attr_reader :response_handlers - - # Seconds to wait until a connection is opened. - # If the IMAP object cannot open a connection within this time, - # it raises a Net::OpenTimeout exception. The default value is 30 seconds. - attr_reader :open_timeout - - # The thread to receive exceptions. - attr_accessor :client_thread - - # Flag indicating a message has been seen. - SEEN = :Seen - - # Flag indicating a message has been answered. - ANSWERED = :Answered - - # Flag indicating a message has been flagged for special or urgent - # attention. - FLAGGED = :Flagged - - # Flag indicating a message has been marked for deletion. This - # will occur when the mailbox is closed or expunged. - DELETED = :Deleted - - # Flag indicating a message is only a draft or work-in-progress version. - DRAFT = :Draft - - # Flag indicating that the message is "recent," meaning that this - # session is the first session in which the client has been notified - # of this message. - RECENT = :Recent - - # Flag indicating that a mailbox context name cannot contain - # children. - NOINFERIORS = :Noinferiors - - # Flag indicating that a mailbox is not selected. - NOSELECT = :Noselect - - # Flag indicating that a mailbox has been marked "interesting" by - # the server; this commonly indicates that the mailbox contains - # new messages. - MARKED = :Marked - - # Flag indicating that the mailbox does not contains new messages. - UNMARKED = :Unmarked - - # Returns the debug mode. - def self.debug - return @@debug - end - - # Sets the debug mode. - def self.debug=(val) - return @@debug = val - end - - # Returns the max number of flags interned to symbols. - def self.max_flag_count - return @@max_flag_count - end - - # Sets the max number of flags interned to symbols. - def self.max_flag_count=(count) - @@max_flag_count = count - end - - # Adds an authenticator for Net::IMAP#authenticate. +auth_type+ - # is the type of authentication this authenticator supports - # (for instance, "LOGIN"). The +authenticator+ is an object - # which defines a process() method to handle authentication with - # the server. See Net::IMAP::LoginAuthenticator, - # Net::IMAP::CramMD5Authenticator, and Net::IMAP::DigestMD5Authenticator - # for examples. - # - # - # If +auth_type+ refers to an existing authenticator, it will be - # replaced by the new one. - def self.add_authenticator(auth_type, authenticator) - @@authenticators[auth_type] = authenticator - end - - # The default port for IMAP connections, port 143 - def self.default_port - return PORT - end - - # The default port for IMAPS connections, port 993 - def self.default_tls_port - return SSL_PORT - end - - class << self - alias default_imap_port default_port - alias default_imaps_port default_tls_port - alias default_ssl_port default_tls_port - end - - # Disconnects from the server. - def disconnect - return if disconnected? - begin - begin - # try to call SSL::SSLSocket#io. - @sock.io.shutdown - rescue NoMethodError - # @sock is not an SSL::SSLSocket. - @sock.shutdown - end - rescue Errno::ENOTCONN - # ignore `Errno::ENOTCONN: Socket is not connected' on some platforms. - rescue Exception => e - @receiver_thread.raise(e) - end - @receiver_thread.join - synchronize do - @sock.close - end - raise e if e - end - - # Returns true if disconnected from the server. - def disconnected? - return @sock.closed? - end - - # Sends a CAPABILITY command, and returns an array of - # capabilities that the server supports. Each capability - # is a string. See [IMAP] for a list of possible - # capabilities. - # - # Note that the Net::IMAP class does not modify its - # behaviour according to the capabilities of the server; - # it is up to the user of the class to ensure that - # a certain capability is supported by a server before - # using it. - def capability - synchronize do - send_command("CAPABILITY") - return @responses.delete("CAPABILITY")[-1] - end - end - - # Sends a NOOP command to the server. It does nothing. - def noop - send_command("NOOP") - end - - # Sends a LOGOUT command to inform the server that the client is - # done with the connection. - def logout - send_command("LOGOUT") - end - - # Sends a STARTTLS command to start TLS session. - def starttls(options = {}, verify = true) - send_command("STARTTLS") do |resp| - if resp.kind_of?(TaggedResponse) && resp.name == "OK" - begin - # for backward compatibility - certs = options.to_str - options = create_ssl_params(certs, verify) - rescue NoMethodError - end - start_tls_session(options) - end - end - end - - # Sends an AUTHENTICATE command to authenticate the client. - # The +auth_type+ parameter is a string that represents - # the authentication mechanism to be used. Currently Net::IMAP - # supports the authentication mechanisms: - # - # LOGIN:: login using cleartext user and password. - # CRAM-MD5:: login with cleartext user and encrypted password - # (see [RFC-2195] for a full description). This - # mechanism requires that the server have the user's - # password stored in clear-text password. - # - # For both of these mechanisms, there should be two +args+: username - # and (cleartext) password. A server may not support one or the other - # of these mechanisms; check #capability() for a capability of - # the form "AUTH=LOGIN" or "AUTH=CRAM-MD5". - # - # Authentication is done using the appropriate authenticator object: - # see @@authenticators for more information on plugging in your own - # authenticator. - # - # For example: - # - # imap.authenticate('LOGIN', user, password) - # - # A Net::IMAP::NoResponseError is raised if authentication fails. - def authenticate(auth_type, *args) - auth_type = auth_type.upcase - unless @@authenticators.has_key?(auth_type) - raise ArgumentError, - format('unknown auth type - "%s"', auth_type) - end - authenticator = @@authenticators[auth_type].new(*args) - send_command("AUTHENTICATE", auth_type) do |resp| - if resp.instance_of?(ContinuationRequest) - data = authenticator.process(resp.data.text.unpack("m")[0]) - s = [data].pack("m0") - send_string_data(s) - put_string(CRLF) - end - end - end - - # Sends a LOGIN command to identify the client and carries - # the plaintext +password+ authenticating this +user+. Note - # that, unlike calling #authenticate() with an +auth_type+ - # of "LOGIN", #login() does *not* use the login authenticator. - # - # A Net::IMAP::NoResponseError is raised if authentication fails. - def login(user, password) - send_command("LOGIN", user, password) - end - - # Sends a SELECT command to select a +mailbox+ so that messages - # in the +mailbox+ can be accessed. - # - # After you have selected a mailbox, you may retrieve the - # number of items in that mailbox from @responses["EXISTS"][-1], - # and the number of recent messages from @responses["RECENT"][-1]. - # Note that these values can change if new messages arrive - # during a session; see #add_response_handler() for a way of - # detecting this event. - # - # A Net::IMAP::NoResponseError is raised if the mailbox does not - # exist or is for some reason non-selectable. - def select(mailbox) - synchronize do - @responses.clear - send_command("SELECT", mailbox) - end - end - - # Sends a EXAMINE command to select a +mailbox+ so that messages - # in the +mailbox+ can be accessed. Behaves the same as #select(), - # except that the selected +mailbox+ is identified as read-only. - # - # A Net::IMAP::NoResponseError is raised if the mailbox does not - # exist or is for some reason non-examinable. - def examine(mailbox) - synchronize do - @responses.clear - send_command("EXAMINE", mailbox) - end - end - - # Sends a CREATE command to create a new +mailbox+. - # - # A Net::IMAP::NoResponseError is raised if a mailbox with that name - # cannot be created. - def create(mailbox) - send_command("CREATE", mailbox) - end - - # Sends a DELETE command to remove the +mailbox+. - # - # A Net::IMAP::NoResponseError is raised if a mailbox with that name - # cannot be deleted, either because it does not exist or because the - # client does not have permission to delete it. - def delete(mailbox) - send_command("DELETE", mailbox) - end - - # Sends a RENAME command to change the name of the +mailbox+ to - # +newname+. - # - # A Net::IMAP::NoResponseError is raised if a mailbox with the - # name +mailbox+ cannot be renamed to +newname+ for whatever - # reason; for instance, because +mailbox+ does not exist, or - # because there is already a mailbox with the name +newname+. - def rename(mailbox, newname) - send_command("RENAME", mailbox, newname) - end - - # Sends a SUBSCRIBE command to add the specified +mailbox+ name to - # the server's set of "active" or "subscribed" mailboxes as returned - # by #lsub(). - # - # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be - # subscribed to; for instance, because it does not exist. - def subscribe(mailbox) - send_command("SUBSCRIBE", mailbox) - end - - # Sends a UNSUBSCRIBE command to remove the specified +mailbox+ name - # from the server's set of "active" or "subscribed" mailboxes. - # - # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be - # unsubscribed from; for instance, because the client is not currently - # subscribed to it. - def unsubscribe(mailbox) - send_command("UNSUBSCRIBE", mailbox) - end - - # Sends a LIST command, and returns a subset of names from - # the complete set of all names available to the client. - # +refname+ provides a context (for instance, a base directory - # in a directory-based mailbox hierarchy). +mailbox+ specifies - # a mailbox or (via wildcards) mailboxes under that context. - # Two wildcards may be used in +mailbox+: '*', which matches - # all characters *including* the hierarchy delimiter (for instance, - # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%', - # which matches all characters *except* the hierarchy delimiter. - # - # If +refname+ is empty, +mailbox+ is used directly to determine - # which mailboxes to match. If +mailbox+ is empty, the root - # name of +refname+ and the hierarchy delimiter are returned. - # - # The return value is an array of +Net::IMAP::MailboxList+. For example: - # - # imap.create("foo/bar") - # imap.create("foo/baz") - # p imap.list("", "foo/%") - # #=> [#, \\ - # #, \\ - # #] - def list(refname, mailbox) - synchronize do - send_command("LIST", refname, mailbox) - return @responses.delete("LIST") - end - end - - # Sends a XLIST command, and returns a subset of names from - # the complete set of all names available to the client. - # +refname+ provides a context (for instance, a base directory - # in a directory-based mailbox hierarchy). +mailbox+ specifies - # a mailbox or (via wildcards) mailboxes under that context. - # Two wildcards may be used in +mailbox+: '*', which matches - # all characters *including* the hierarchy delimiter (for instance, - # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%', - # which matches all characters *except* the hierarchy delimiter. - # - # If +refname+ is empty, +mailbox+ is used directly to determine - # which mailboxes to match. If +mailbox+ is empty, the root - # name of +refname+ and the hierarchy delimiter are returned. - # - # The XLIST command is like the LIST command except that the flags - # returned refer to the function of the folder/mailbox, e.g. :Sent - # - # The return value is an array of +Net::IMAP::MailboxList+. For example: - # - # imap.create("foo/bar") - # imap.create("foo/baz") - # p imap.xlist("", "foo/%") - # #=> [#, \\ - # #, \\ - # #] - def xlist(refname, mailbox) - synchronize do - send_command("XLIST", refname, mailbox) - return @responses.delete("XLIST") - end - end - - # Sends the GETQUOTAROOT command along with the specified +mailbox+. - # This command is generally available to both admin and user. - # If this mailbox exists, it returns an array containing objects of type - # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota. - def getquotaroot(mailbox) - synchronize do - send_command("GETQUOTAROOT", mailbox) - result = [] - result.concat(@responses.delete("QUOTAROOT")) - result.concat(@responses.delete("QUOTA")) - return result - end - end - - # Sends the GETQUOTA command along with specified +mailbox+. - # If this mailbox exists, then an array containing a - # Net::IMAP::MailboxQuota object is returned. This - # command is generally only available to server admin. - def getquota(mailbox) - synchronize do - send_command("GETQUOTA", mailbox) - return @responses.delete("QUOTA") - end - end - - # Sends a SETQUOTA command along with the specified +mailbox+ and - # +quota+. If +quota+ is nil, then +quota+ will be unset for that - # mailbox. Typically one needs to be logged in as a server admin - # for this to work. The IMAP quota commands are described in - # [RFC-2087]. - def setquota(mailbox, quota) - if quota.nil? - data = '()' - else - data = '(STORAGE ' + quota.to_s + ')' - end - send_command("SETQUOTA", mailbox, RawData.new(data)) - end - - # Sends the SETACL command along with +mailbox+, +user+ and the - # +rights+ that user is to have on that mailbox. If +rights+ is nil, - # then that user will be stripped of any rights to that mailbox. - # The IMAP ACL commands are described in [RFC-2086]. - def setacl(mailbox, user, rights) - if rights.nil? - send_command("SETACL", mailbox, user, "") - else - send_command("SETACL", mailbox, user, rights) - end - end - - # Send the GETACL command along with a specified +mailbox+. - # If this mailbox exists, an array containing objects of - # Net::IMAP::MailboxACLItem will be returned. - def getacl(mailbox) - synchronize do - send_command("GETACL", mailbox) - return @responses.delete("ACL")[-1] - end - end - - # Sends a LSUB command, and returns a subset of names from the set - # of names that the user has declared as being "active" or - # "subscribed." +refname+ and +mailbox+ are interpreted as - # for #list(). - # The return value is an array of +Net::IMAP::MailboxList+. - def lsub(refname, mailbox) - synchronize do - send_command("LSUB", refname, mailbox) - return @responses.delete("LSUB") - end - end - - # Sends a STATUS command, and returns the status of the indicated - # +mailbox+. +attr+ is a list of one or more attributes whose - # statuses are to be requested. Supported attributes include: - # - # MESSAGES:: the number of messages in the mailbox. - # RECENT:: the number of recent messages in the mailbox. - # UNSEEN:: the number of unseen messages in the mailbox. - # - # The return value is a hash of attributes. For example: - # - # p imap.status("inbox", ["MESSAGES", "RECENT"]) - # #=> {"RECENT"=>0, "MESSAGES"=>44} - # - # A Net::IMAP::NoResponseError is raised if status values - # for +mailbox+ cannot be returned; for instance, because it - # does not exist. - def status(mailbox, attr) - synchronize do - send_command("STATUS", mailbox, attr) - return @responses.delete("STATUS")[-1].attr - end - end - - # Sends a APPEND command to append the +message+ to the end of - # the +mailbox+. The optional +flags+ argument is an array of - # flags initially passed to the new message. The optional - # +date_time+ argument specifies the creation time to assign to the - # new message; it defaults to the current time. - # For example: - # - # imap.append("inbox", <:: a set of message sequence numbers. ',' indicates - # an interval, ':' indicates a range. For instance, - # '2,10:12,15' means "2,10,11,12,15". - # - # BEFORE :: messages with an internal date strictly before - # . The date argument has a format similar - # to 8-Aug-2002. - # - # BODY :: messages that contain within their body. - # - # CC :: messages containing in their CC field. - # - # FROM :: messages that contain in their FROM field. - # - # NEW:: messages with the \Recent, but not the \Seen, flag set. - # - # NOT :: negate the following search key. - # - # OR :: "or" two search keys together. - # - # ON :: messages with an internal date exactly equal to , - # which has a format similar to 8-Aug-2002. - # - # SINCE :: messages with an internal date on or after . - # - # SUBJECT :: messages with in their subject. - # - # TO :: messages with in their TO field. - # - # For example: - # - # p imap.search(["SUBJECT", "hello", "NOT", "NEW"]) - # #=> [1, 6, 7, 8] - def search(keys, charset = nil) - return search_internal("SEARCH", keys, charset) - end - - # Similar to #search(), but returns unique identifiers. - def uid_search(keys, charset = nil) - return search_internal("UID SEARCH", keys, charset) - end - - # Sends a FETCH command to retrieve data associated with a message - # in the mailbox. - # - # The +set+ parameter is a number or a range between two numbers, - # or an array of those. The number is a message sequence number, - # where -1 represents a '*' for use in range notation like 100..-1 - # being interpreted as '100:*'. Beware that the +exclude_end?+ - # property of a Range object is ignored, and the contents of a - # range are independent of the order of the range endpoints as per - # the protocol specification, so 1...5, 5..1 and 5...1 are all - # equivalent to 1..5. - # - # +attr+ is a list of attributes to fetch; see the documentation - # for Net::IMAP::FetchData for a list of valid attributes. - # - # The return value is an array of Net::IMAP::FetchData or nil - # (instead of an empty array) if there is no matching message. - # - # For example: - # - # p imap.fetch(6..8, "UID") - # #=> [#98}>, \\ - # #99}>, \\ - # #100}>] - # p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]") - # #=> [#"Subject: test\r\n\r\n"}>] - # data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0] - # p data.seqno - # #=> 6 - # p data.attr["RFC822.SIZE"] - # #=> 611 - # p data.attr["INTERNALDATE"] - # #=> "12-Oct-2000 22:40:59 +0900" - # p data.attr["UID"] - # #=> 98 - def fetch(set, attr, mod = nil) - return fetch_internal("FETCH", set, attr, mod) - end - - # Similar to #fetch(), but +set+ contains unique identifiers. - def uid_fetch(set, attr, mod = nil) - return fetch_internal("UID FETCH", set, attr, mod) - end - - # Sends a STORE command to alter data associated with messages - # in the mailbox, in particular their flags. The +set+ parameter - # is a number, an array of numbers, or a Range object. Each number - # is a message sequence number. +attr+ is the name of a data item - # to store: 'FLAGS' will replace the message's flag list - # with the provided one, '+FLAGS' will add the provided flags, - # and '-FLAGS' will remove them. +flags+ is a list of flags. - # - # The return value is an array of Net::IMAP::FetchData. For example: - # - # p imap.store(6..8, "+FLAGS", [:Deleted]) - # #=> [#[:Seen, :Deleted]}>, \\ - # #[:Seen, :Deleted]}>, \\ - # #[:Seen, :Deleted]}>] - def store(set, attr, flags) - return store_internal("STORE", set, attr, flags) - end - - # Similar to #store(), but +set+ contains unique identifiers. - def uid_store(set, attr, flags) - return store_internal("UID STORE", set, attr, flags) - end - - # Sends a COPY command to copy the specified message(s) to the end - # of the specified destination +mailbox+. The +set+ parameter is - # a number, an array of numbers, or a Range object. The number is - # a message sequence number. - def copy(set, mailbox) - copy_internal("COPY", set, mailbox) - end - - # Similar to #copy(), but +set+ contains unique identifiers. - def uid_copy(set, mailbox) - copy_internal("UID COPY", set, mailbox) - end - - # Sends a MOVE command to move the specified message(s) to the end - # of the specified destination +mailbox+. The +set+ parameter is - # a number, an array of numbers, or a Range object. The number is - # a message sequence number. - # The IMAP MOVE extension is described in [RFC-6851]. - def move(set, mailbox) - copy_internal("MOVE", set, mailbox) - end - - # Similar to #move(), but +set+ contains unique identifiers. - def uid_move(set, mailbox) - copy_internal("UID MOVE", set, mailbox) - end - - # Sends a SORT command to sort messages in the mailbox. - # Returns an array of message sequence numbers. For example: - # - # p imap.sort(["FROM"], ["ALL"], "US-ASCII") - # #=> [1, 2, 3, 5, 6, 7, 8, 4, 9] - # p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII") - # #=> [6, 7, 8, 1] - # - # See [SORT-THREAD-EXT] for more details. - def sort(sort_keys, search_keys, charset) - return sort_internal("SORT", sort_keys, search_keys, charset) - end - - # Similar to #sort(), but returns an array of unique identifiers. - def uid_sort(sort_keys, search_keys, charset) - return sort_internal("UID SORT", sort_keys, search_keys, charset) - end - - # Adds a response handler. For example, to detect when - # the server sends a new EXISTS response (which normally - # indicates new messages being added to the mailbox), - # add the following handler after selecting the - # mailbox: - # - # imap.add_response_handler { |resp| - # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS" - # puts "Mailbox now has #{resp.data} messages" - # end - # } - # - def add_response_handler(handler = nil, &block) - raise ArgumentError, "two Procs are passed" if handler && block - @response_handlers.push(block || handler) - end - - # Removes the response handler. - def remove_response_handler(handler) - @response_handlers.delete(handler) - end - - # Similar to #search(), but returns message sequence numbers in threaded - # format, as a Net::IMAP::ThreadMember tree. The supported algorithms - # are: - # - # ORDEREDSUBJECT:: split into single-level threads according to subject, - # ordered by date. - # REFERENCES:: split into threads by parent/child relationships determined - # by which message is a reply to which. - # - # Unlike #search(), +charset+ is a required argument. US-ASCII - # and UTF-8 are sample values. - # - # See [SORT-THREAD-EXT] for more details. - def thread(algorithm, search_keys, charset) - return thread_internal("THREAD", algorithm, search_keys, charset) - end - - # Similar to #thread(), but returns unique identifiers instead of - # message sequence numbers. - def uid_thread(algorithm, search_keys, charset) - return thread_internal("UID THREAD", algorithm, search_keys, charset) - end - - # Sends an IDLE command that waits for notifications of new or expunged - # messages. Yields responses from the server during the IDLE. - # - # Use #idle_done() to leave IDLE. - # - # If +timeout+ is given, this method returns after +timeout+ seconds passed. - # +timeout+ can be used for keep-alive. For example, the following code - # checks the connection for each 60 seconds. - # - # loop do - # imap.idle(60) do |res| - # ... - # end - # end - def idle(timeout = nil, &response_handler) - raise LocalJumpError, "no block given" unless response_handler - - response = nil - - synchronize do - tag = Thread.current[:net_imap_tag] = generate_tag - put_string("#{tag} IDLE#{CRLF}") - - begin - add_response_handler(&response_handler) - @idle_done_cond = new_cond - @idle_done_cond.wait(timeout) - @idle_done_cond = nil - if @receiver_thread_terminating - raise @exception || Net::IMAP::Error.new("connection closed") - end - ensure - unless @receiver_thread_terminating - remove_response_handler(response_handler) - put_string("DONE#{CRLF}") - response = get_tagged_response(tag, "IDLE") - end - end - end - - return response - end - - # Leaves IDLE. - def idle_done - synchronize do - if @idle_done_cond.nil? - raise Net::IMAP::Error, "not during IDLE" - end - @idle_done_cond.signal - end - end - - # Decode a string from modified UTF-7 format to UTF-8. - # - # UTF-7 is a 7-bit encoding of Unicode [UTF7]. IMAP uses a - # slightly modified version of this to encode mailbox names - # containing non-ASCII characters; see [IMAP] section 5.1.3. - # - # Net::IMAP does _not_ automatically encode and decode - # mailbox names to and from UTF-7. - def self.decode_utf7(s) - return s.gsub(/&([^-]+)?-/n) { - if $1 - ($1.tr(",", "/") + "===").unpack1("m").encode(Encoding::UTF_8, Encoding::UTF_16BE) - else - "&" - end - } - end - - # Encode a string from UTF-8 format to modified UTF-7. - def self.encode_utf7(s) - return s.gsub(/(&)|[^\x20-\x7e]+/) { - if $1 - "&-" - else - base64 = [$&.encode(Encoding::UTF_16BE)].pack("m0") - "&" + base64.delete("=").tr("/", ",") + "-" - end - }.force_encoding("ASCII-8BIT") - end - - # Formats +time+ as an IMAP-style date. - def self.format_date(time) - return time.strftime('%d-%b-%Y') - end - - # Formats +time+ as an IMAP-style date-time. - def self.format_datetime(time) - return time.strftime('%d-%b-%Y %H:%M %z') - end - - private - - CRLF = "\r\n" # :nodoc: - PORT = 143 # :nodoc: - SSL_PORT = 993 # :nodoc: - - @@debug = false - @@authenticators = {} - @@max_flag_count = 10000 - - # :call-seq: - # Net::IMAP.new(host, options = {}) - # - # Creates a new Net::IMAP object and connects it to the specified - # +host+. - # - # +options+ is an option hash, each key of which is a symbol. - # - # The available options are: - # - # port:: Port number (default value is 143 for imap, or 993 for imaps) - # ssl:: If options[:ssl] is true, then an attempt will be made - # to use SSL (now TLS) to connect to the server. For this to work - # OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] extensions need to - # be installed. - # If options[:ssl] is a hash, it's passed to - # OpenSSL::SSL::SSLContext#set_params as parameters. - # open_timeout:: Seconds to wait until a connection is opened - # - # The most common errors are: - # - # Errno::ECONNREFUSED:: Connection refused by +host+ or an intervening - # firewall. - # Errno::ETIMEDOUT:: Connection timed out (possibly due to packets - # being dropped by an intervening firewall). - # Errno::ENETUNREACH:: There is no route to that network. - # SocketError:: Hostname not known or other socket error. - # Net::IMAP::ByeResponseError:: The connected to the host was successful, but - # it immediately said goodbye. - def initialize(host, port_or_options = {}, - usessl = false, certs = nil, verify = true) - super() - @host = host - begin - options = port_or_options.to_hash - rescue NoMethodError - # for backward compatibility - options = {} - options[:port] = port_or_options - if usessl - options[:ssl] = create_ssl_params(certs, verify) - end - end - @port = options[:port] || (options[:ssl] ? SSL_PORT : PORT) - @tag_prefix = "RUBY" - @tagno = 0 - @open_timeout = options[:open_timeout] || 30 - @parser = ResponseParser.new - @sock = tcp_socket(@host, @port) - begin - if options[:ssl] - start_tls_session(options[:ssl]) - @usessl = true - else - @usessl = false - end - @responses = Hash.new([].freeze) - @tagged_responses = {} - @response_handlers = [] - @tagged_response_arrival = new_cond - @continued_command_tag = nil - @continuation_request_arrival = new_cond - @continuation_request_exception = nil - @idle_done_cond = nil - @logout_command_tag = nil - @debug_output_bol = true - @exception = nil - - @greeting = get_response - if @greeting.nil? - raise Error, "connection closed" - end - if @greeting.name == "BYE" - raise ByeResponseError, @greeting - end - - @client_thread = Thread.current - @receiver_thread = Thread.start { - begin - receive_responses - rescue Exception - end - } - @receiver_thread_terminating = false - rescue Exception - @sock.close - raise - end - end - - def tcp_socket(host, port) - s = Socket.tcp(host, port, :connect_timeout => @open_timeout) - s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true) - s - rescue Errno::ETIMEDOUT - raise Net::OpenTimeout, "Timeout to open TCP connection to " + - "#{host}:#{port} (exceeds #{@open_timeout} seconds)" - end - - def receive_responses - connection_closed = false - until connection_closed - synchronize do - @exception = nil - end - begin - resp = get_response - rescue Exception => e - synchronize do - @sock.close - @exception = e - end - break - end - unless resp - synchronize do - @exception = EOFError.new("end of file reached") - end - break - end - begin - synchronize do - case resp - when TaggedResponse - @tagged_responses[resp.tag] = resp - @tagged_response_arrival.broadcast - case resp.tag - when @logout_command_tag - return - when @continued_command_tag - @continuation_request_exception = - RESPONSE_ERRORS[resp.name].new(resp) - @continuation_request_arrival.signal - end - when UntaggedResponse - record_response(resp.name, resp.data) - if resp.data.instance_of?(ResponseText) && - (code = resp.data.code) - record_response(code.name, code.data) - end - if resp.name == "BYE" && @logout_command_tag.nil? - @sock.close - @exception = ByeResponseError.new(resp) - connection_closed = true - end - when ContinuationRequest - @continuation_request_arrival.signal - end - @response_handlers.each do |handler| - handler.call(resp) - end - end - rescue Exception => e - @exception = e - synchronize do - @tagged_response_arrival.broadcast - @continuation_request_arrival.broadcast - end - end - end - synchronize do - @receiver_thread_terminating = true - @tagged_response_arrival.broadcast - @continuation_request_arrival.broadcast - if @idle_done_cond - @idle_done_cond.signal - end - end - end - - def get_tagged_response(tag, cmd) - until @tagged_responses.key?(tag) - raise @exception if @exception - @tagged_response_arrival.wait - end - resp = @tagged_responses.delete(tag) - case resp.name - when /\A(?:NO)\z/ni - raise NoResponseError, resp - when /\A(?:BAD)\z/ni - raise BadResponseError, resp - else - return resp - end - end - - def get_response - buff = String.new - while true - s = @sock.gets(CRLF) - break unless s - buff.concat(s) - if /\{(\d+)\}\r\n/n =~ s - s = @sock.read($1.to_i) - buff.concat(s) - else - break - end - end - return nil if buff.length == 0 - if @@debug - $stderr.print(buff.gsub(/^/n, "S: ")) - end - return @parser.parse(buff) - end - - def record_response(name, data) - unless @responses.has_key?(name) - @responses[name] = [] - end - @responses[name].push(data) - end - - def send_command(cmd, *args, &block) - synchronize do - args.each do |i| - validate_data(i) - end - tag = generate_tag - put_string(tag + " " + cmd) - args.each do |i| - put_string(" ") - send_data(i, tag) - end - put_string(CRLF) - if cmd == "LOGOUT" - @logout_command_tag = tag - end - if block - add_response_handler(&block) - end - begin - return get_tagged_response(tag, cmd) - ensure - if block - remove_response_handler(block) - end - end - end - end - - def generate_tag - @tagno += 1 - return format("%s%04d", @tag_prefix, @tagno) - end - - def put_string(str) - @sock.print(str) - if @@debug - if @debug_output_bol - $stderr.print("C: ") - end - $stderr.print(str.gsub(/\n(?!\z)/n, "\nC: ")) - if /\r\n\z/n.match(str) - @debug_output_bol = true - else - @debug_output_bol = false - end - end - end - - def validate_data(data) - case data - when nil - when String - when Integer - NumValidator.ensure_number(data) - when Array - if data[0] == 'CHANGEDSINCE' - NumValidator.ensure_mod_sequence_value(data[1]) - else - data.each do |i| - validate_data(i) - end - end - when Time - when Symbol - else - data.validate - end - end - - def send_data(data, tag = nil) - case data - when nil - put_string("NIL") - when String - send_string_data(data, tag) - when Integer - send_number_data(data) - when Array - send_list_data(data, tag) - when Time - send_time_data(data) - when Symbol - send_symbol_data(data) - else - data.send_data(self, tag) - end - end - - def send_string_data(str, tag = nil) - case str - when "" - put_string('""') - when /[\x80-\xff\r\n]/n - # literal - send_literal(str, tag) - when /[(){ \x00-\x1f\x7f%*"\\]/n - # quoted string - send_quoted_string(str) - else - put_string(str) - end - end - - def send_quoted_string(str) - put_string('"' + str.gsub(/["\\]/n, "\\\\\\&") + '"') - end - - def send_literal(str, tag = nil) - synchronize do - put_string("{" + str.bytesize.to_s + "}" + CRLF) - @continued_command_tag = tag - @continuation_request_exception = nil - begin - @continuation_request_arrival.wait - e = @continuation_request_exception || @exception - raise e if e - put_string(str) - ensure - @continued_command_tag = nil - @continuation_request_exception = nil - end - end - end - - def send_number_data(num) - put_string(num.to_s) - end - - def send_list_data(list, tag = nil) - put_string("(") - first = true - list.each do |i| - if first - first = false - else - put_string(" ") - end - send_data(i, tag) - end - put_string(")") - end - - DATE_MONTH = %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) - - def send_time_data(time) - t = time.dup.gmtime - s = format('"%2d-%3s-%4d %02d:%02d:%02d +0000"', - t.day, DATE_MONTH[t.month - 1], t.year, - t.hour, t.min, t.sec) - put_string(s) - end - - def send_symbol_data(symbol) - put_string("\\" + symbol.to_s) - end - - def search_internal(cmd, keys, charset) - if keys.instance_of?(String) - keys = [RawData.new(keys)] - else - normalize_searching_criteria(keys) - end - synchronize do - if charset - send_command(cmd, "CHARSET", charset, *keys) - else - send_command(cmd, *keys) - end - return @responses.delete("SEARCH")[-1] - end - end - - def fetch_internal(cmd, set, attr, mod = nil) - case attr - when String then - attr = RawData.new(attr) - when Array then - attr = attr.map { |arg| - arg.is_a?(String) ? RawData.new(arg) : arg - } - end - - synchronize do - @responses.delete("FETCH") - if mod - send_command(cmd, MessageSet.new(set), attr, mod) - else - send_command(cmd, MessageSet.new(set), attr) - end - return @responses.delete("FETCH") - end - end - - def store_internal(cmd, set, attr, flags) - if attr.instance_of?(String) - attr = RawData.new(attr) - end - synchronize do - @responses.delete("FETCH") - send_command(cmd, MessageSet.new(set), attr, flags) - return @responses.delete("FETCH") - end - end - - def copy_internal(cmd, set, mailbox) - send_command(cmd, MessageSet.new(set), mailbox) - end - - def sort_internal(cmd, sort_keys, search_keys, charset) - if search_keys.instance_of?(String) - search_keys = [RawData.new(search_keys)] - else - normalize_searching_criteria(search_keys) - end - normalize_searching_criteria(search_keys) - synchronize do - send_command(cmd, sort_keys, charset, *search_keys) - return @responses.delete("SORT")[-1] - end - end - - def thread_internal(cmd, algorithm, search_keys, charset) - if search_keys.instance_of?(String) - search_keys = [RawData.new(search_keys)] - else - normalize_searching_criteria(search_keys) - end - normalize_searching_criteria(search_keys) - send_command(cmd, algorithm, charset, *search_keys) - return @responses.delete("THREAD")[-1] - end - - def normalize_searching_criteria(keys) - keys.collect! do |i| - case i - when -1, Range, Array - MessageSet.new(i) - else - i - end - end - end - - def create_ssl_params(certs = nil, verify = true) - params = {} - if certs - if File.file?(certs) - params[:ca_file] = certs - elsif File.directory?(certs) - params[:ca_path] = certs - end - end - if verify - params[:verify_mode] = VERIFY_PEER - else - params[:verify_mode] = VERIFY_NONE - end - return params - end - - def start_tls_session(params = {}) - unless defined?(OpenSSL::SSL) - raise "SSL extension not installed" - end - if @sock.kind_of?(OpenSSL::SSL::SSLSocket) - raise RuntimeError, "already using SSL" - end - begin - params = params.to_hash - rescue NoMethodError - params = {} - end - context = SSLContext.new - context.set_params(params) - if defined?(VerifyCallbackProc) - context.verify_callback = VerifyCallbackProc - end - @sock = SSLSocket.new(@sock, context) - @sock.sync_close = true - @sock.hostname = @host if @sock.respond_to? :hostname= - ssl_socket_connect(@sock, @open_timeout) - if context.verify_mode != VERIFY_NONE - @sock.post_connection_check(@host) - end - end - - class RawData # :nodoc: - def send_data(imap, tag) - imap.send(:put_string, @data) - end - - def validate - end - - private - - def initialize(data) - @data = data - end - end - - class Atom # :nodoc: - def send_data(imap, tag) - imap.send(:put_string, @data) - end - - def validate - end - - private - - def initialize(data) - @data = data - end - end - - class QuotedString # :nodoc: - def send_data(imap, tag) - imap.send(:send_quoted_string, @data) - end - - def validate - end - - private - - def initialize(data) - @data = data - end - end - - class Literal # :nodoc: - def send_data(imap, tag) - imap.send(:send_literal, @data, tag) - end - - def validate - end - - private - - def initialize(data) - @data = data - end - end - - class MessageSet # :nodoc: - def send_data(imap, tag) - imap.send(:put_string, format_internal(@data)) - end - - def validate - validate_internal(@data) - end - - private - - def initialize(data) - @data = data - end - - def format_internal(data) - case data - when "*" - return data - when Integer - if data == -1 - return "*" - else - return data.to_s - end - when Range - return format_internal(data.first) + - ":" + format_internal(data.last) - when Array - return data.collect {|i| format_internal(i)}.join(",") - when ThreadMember - return data.seqno.to_s + - ":" + data.children.collect {|i| format_internal(i).join(",")} - end - end - - def validate_internal(data) - case data - when "*" - when Integer - NumValidator.ensure_nz_number(data) - when Range - when Array - data.each do |i| - validate_internal(i) - end - when ThreadMember - data.children.each do |i| - validate_internal(i) - end - else - raise DataFormatError, data.inspect - end - end - end - - # Common validators of number and nz_number types - module NumValidator # :nodoc - class << self - # Check is passed argument valid 'number' in RFC 3501 terminology - def valid_number?(num) - # [RFC 3501] - # number = 1*DIGIT - # ; Unsigned 32-bit integer - # ; (0 <= n < 4,294,967,296) - num >= 0 && num < 4294967296 - end - - # Check is passed argument valid 'nz_number' in RFC 3501 terminology - def valid_nz_number?(num) - # [RFC 3501] - # nz-number = digit-nz *DIGIT - # ; Non-zero unsigned 32-bit integer - # ; (0 < n < 4,294,967,296) - num != 0 && valid_number?(num) - end - - # Check is passed argument valid 'mod_sequence_value' in RFC 4551 terminology - def valid_mod_sequence_value?(num) - # mod-sequence-value = 1*DIGIT - # ; Positive unsigned 64-bit integer - # ; (mod-sequence) - # ; (1 <= n < 18,446,744,073,709,551,615) - num >= 1 && num < 18446744073709551615 - end - - # Ensure argument is 'number' or raise DataFormatError - def ensure_number(num) - return if valid_number?(num) - - msg = "number must be unsigned 32-bit integer: #{num}" - raise DataFormatError, msg - end - - # Ensure argument is 'nz_number' or raise DataFormatError - def ensure_nz_number(num) - return if valid_nz_number?(num) - - msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}" - raise DataFormatError, msg - end - - # Ensure argument is 'mod_sequence_value' or raise DataFormatError - def ensure_mod_sequence_value(num) - return if valid_mod_sequence_value?(num) - - msg = "mod_sequence_value must be unsigned 64-bit integer: #{num}" - raise DataFormatError, msg - end - end - end - - # Net::IMAP::ContinuationRequest represents command continuation requests. - # - # The command continuation request response is indicated by a "+" token - # instead of a tag. This form of response indicates that the server is - # ready to accept the continuation of a command from the client. The - # remainder of this response is a line of text. - # - # continue_req ::= "+" SPACE (resp_text / base64) - # - # ==== Fields: - # - # data:: Returns the data (Net::IMAP::ResponseText). - # - # raw_data:: Returns the raw data string. - ContinuationRequest = Struct.new(:data, :raw_data) - - # Net::IMAP::UntaggedResponse represents untagged responses. - # - # Data transmitted by the server to the client and status responses - # that do not indicate command completion are prefixed with the token - # "*", and are called untagged responses. - # - # response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / - # mailbox_data / message_data / capability_data) - # - # ==== Fields: - # - # name:: Returns the name, such as "FLAGS", "LIST", or "FETCH". - # - # data:: Returns the data such as an array of flag symbols, - # a (()) object. - # - # raw_data:: Returns the raw data string. - UntaggedResponse = Struct.new(:name, :data, :raw_data) - - # Net::IMAP::TaggedResponse represents tagged responses. - # - # The server completion result response indicates the success or - # failure of the operation. It is tagged with the same tag as the - # client command which began the operation. - # - # response_tagged ::= tag SPACE resp_cond_state CRLF - # - # tag ::= 1* - # - # resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text - # - # ==== Fields: - # - # tag:: Returns the tag. - # - # name:: Returns the name, one of "OK", "NO", or "BAD". - # - # data:: Returns the data. See (()). - # - # raw_data:: Returns the raw data string. - # - TaggedResponse = Struct.new(:tag, :name, :data, :raw_data) - - # Net::IMAP::ResponseText represents texts of responses. - # The text may be prefixed by the response code. - # - # resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) - # ;; text SHOULD NOT begin with "[" or "=" - # - # ==== Fields: - # - # code:: Returns the response code. See (()). - # - # text:: Returns the text. - # - ResponseText = Struct.new(:code, :text) - - # Net::IMAP::ResponseCode represents response codes. - # - # resp_text_code ::= "ALERT" / "PARSE" / - # "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" / - # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / - # "UIDVALIDITY" SPACE nz_number / - # "UNSEEN" SPACE nz_number / - # atom [SPACE 1*] - # - # ==== Fields: - # - # name:: Returns the name, such as "ALERT", "PERMANENTFLAGS", or "UIDVALIDITY". - # - # data:: Returns the data, if it exists. - # - ResponseCode = Struct.new(:name, :data) - - # Net::IMAP::MailboxList represents contents of the LIST response. - # - # mailbox_list ::= "(" #("\Marked" / "\Noinferiors" / - # "\Noselect" / "\Unmarked" / flag_extension) ")" - # SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox - # - # ==== Fields: - # - # attr:: Returns the name attributes. Each name attribute is a symbol - # capitalized by String#capitalize, such as :Noselect (not :NoSelect). - # - # delim:: Returns the hierarchy delimiter. - # - # name:: Returns the mailbox name. - # - MailboxList = Struct.new(:attr, :delim, :name) - - # Net::IMAP::MailboxQuota represents contents of GETQUOTA response. - # This object can also be a response to GETQUOTAROOT. In the syntax - # specification below, the delimiter used with the "#" construct is a - # single space (SPACE). - # - # quota_list ::= "(" #quota_resource ")" - # - # quota_resource ::= atom SPACE number SPACE number - # - # quota_response ::= "QUOTA" SPACE astring SPACE quota_list - # - # ==== Fields: - # - # mailbox:: The mailbox with the associated quota. - # - # usage:: Current storage usage of the mailbox. - # - # quota:: Quota limit imposed on the mailbox. - # - MailboxQuota = Struct.new(:mailbox, :usage, :quota) - - # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT - # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.) - # - # quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring) - # - # ==== Fields: - # - # mailbox:: The mailbox with the associated quota. - # - # quotaroots:: Zero or more quotaroots that affect the quota on the - # specified mailbox. - # - MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots) - - # Net::IMAP::MailboxACLItem represents the response from GETACL. - # - # acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights) - # - # identifier ::= astring - # - # rights ::= astring - # - # ==== Fields: - # - # user:: Login name that has certain rights to the mailbox - # that was specified with the getacl command. - # - # rights:: The access rights the indicated user has to the - # mailbox. - # - MailboxACLItem = Struct.new(:user, :rights, :mailbox) - - # Net::IMAP::StatusData represents the contents of the STATUS response. - # - # ==== Fields: - # - # mailbox:: Returns the mailbox name. - # - # attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT", - # "UIDVALIDITY", "UNSEEN". Each value is a number. - # - StatusData = Struct.new(:mailbox, :attr) - - # Net::IMAP::FetchData represents the contents of the FETCH response. - # - # ==== Fields: - # - # seqno:: Returns the message sequence number. - # (Note: not the unique identifier, even for the UID command response.) - # - # attr:: Returns a hash. Each key is a data item name, and each value is - # its value. - # - # The current data items are: - # - # [BODY] - # A form of BODYSTRUCTURE without extension data. - # [BODY[
]<>] - # A string expressing the body contents of the specified section. - # [BODYSTRUCTURE] - # An object that describes the [MIME-IMB] body structure of a message. - # See Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText, - # Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart. - # [ENVELOPE] - # A Net::IMAP::Envelope object that describes the envelope - # structure of a message. - # [FLAGS] - # A array of flag symbols that are set for this message. Flag symbols - # are capitalized by String#capitalize. - # [INTERNALDATE] - # A string representing the internal date of the message. - # [RFC822] - # Equivalent to BODY[]. - # [RFC822.HEADER] - # Equivalent to BODY.PEEK[HEADER]. - # [RFC822.SIZE] - # A number expressing the [RFC-822] size of the message. - # [RFC822.TEXT] - # Equivalent to BODY[TEXT]. - # [UID] - # A number expressing the unique identifier of the message. - # - FetchData = Struct.new(:seqno, :attr) - - # Net::IMAP::Envelope represents envelope structures of messages. - # - # ==== Fields: - # - # date:: Returns a string that represents the date. - # - # subject:: Returns a string that represents the subject. - # - # from:: Returns an array of Net::IMAP::Address that represents the from. - # - # sender:: Returns an array of Net::IMAP::Address that represents the sender. - # - # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to. - # - # to:: Returns an array of Net::IMAP::Address that represents the to. - # - # cc:: Returns an array of Net::IMAP::Address that represents the cc. - # - # bcc:: Returns an array of Net::IMAP::Address that represents the bcc. - # - # in_reply_to:: Returns a string that represents the in-reply-to. - # - # message_id:: Returns a string that represents the message-id. - # - Envelope = Struct.new(:date, :subject, :from, :sender, :reply_to, - :to, :cc, :bcc, :in_reply_to, :message_id) - - # - # Net::IMAP::Address represents electronic mail addresses. - # - # ==== Fields: - # - # name:: Returns the phrase from [RFC-822] mailbox. - # - # route:: Returns the route from [RFC-822] route-addr. - # - # mailbox:: nil indicates end of [RFC-822] group. - # If non-nil and host is nil, returns [RFC-822] group name. - # Otherwise, returns [RFC-822] local-part. - # - # host:: nil indicates [RFC-822] group syntax. - # Otherwise, returns [RFC-822] domain name. - # - Address = Struct.new(:name, :route, :mailbox, :host) - - # - # Net::IMAP::ContentDisposition represents Content-Disposition fields. - # - # ==== Fields: - # - # dsp_type:: Returns the disposition type. - # - # param:: Returns a hash that represents parameters of the Content-Disposition - # field. - # - ContentDisposition = Struct.new(:dsp_type, :param) - - # Net::IMAP::ThreadMember represents a thread-node returned - # by Net::IMAP#thread. - # - # ==== Fields: - # - # seqno:: The sequence number of this message. - # - # children:: An array of Net::IMAP::ThreadMember objects for mail - # items that are children of this in the thread. - # - ThreadMember = Struct.new(:seqno, :children) - - # Net::IMAP::BodyTypeBasic represents basic body structures of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name as defined in [MIME-IMB]. - # - # subtype:: Returns the content subtype name as defined in [MIME-IMB]. - # - # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. - # - # content_id:: Returns a string giving the content id as defined in [MIME-IMB]. - # - # description:: Returns a string giving the content description as defined in - # [MIME-IMB]. - # - # encoding:: Returns a string giving the content transfer encoding as defined in - # [MIME-IMB]. - # - # size:: Returns a number giving the size of the body in octets. - # - # md5:: Returns a string giving the body MD5 value as defined in [MD5]. - # - # disposition:: Returns a Net::IMAP::ContentDisposition object giving - # the content disposition. - # - # language:: Returns a string or an array of strings giving the body - # language value as defined in [LANGUAGE-TAGS]. - # - # extension:: Returns extension data. - # - # multipart?:: Returns false. - # - class BodyTypeBasic < Struct.new(:media_type, :subtype, - :param, :content_id, - :description, :encoding, :size, - :md5, :disposition, :language, - :extension) - def multipart? - return false - end - - # Obsolete: use +subtype+ instead. Calling this will - # generate a warning message to +stderr+, then return - # the value of +subtype+. - def media_subtype - warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1) - return subtype - end - end - - # Net::IMAP::BodyTypeText represents TEXT body structures of messages. - # - # ==== Fields: - # - # lines:: Returns the size of the body in text lines. - # - # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic. - # - class BodyTypeText < Struct.new(:media_type, :subtype, - :param, :content_id, - :description, :encoding, :size, - :lines, - :md5, :disposition, :language, - :extension) - def multipart? - return false - end - - # Obsolete: use +subtype+ instead. Calling this will - # generate a warning message to +stderr+, then return - # the value of +subtype+. - def media_subtype - warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1) - return subtype - end - end - - # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages. - # - # ==== Fields: - # - # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure. - # - # body:: Returns an object giving the body structure. - # - # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText. - # - class BodyTypeMessage < Struct.new(:media_type, :subtype, - :param, :content_id, - :description, :encoding, :size, - :envelope, :body, :lines, - :md5, :disposition, :language, - :extension) - def multipart? - return false - end - - # Obsolete: use +subtype+ instead. Calling this will - # generate a warning message to +stderr+, then return - # the value of +subtype+. - def media_subtype - warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1) - return subtype - end - end - - # Net::IMAP::BodyTypeAttachment represents attachment body structures - # of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name. - # - # subtype:: Returns +nil+. - # - # param:: Returns a hash that represents parameters. - # - # multipart?:: Returns false. - # - class BodyTypeAttachment < Struct.new(:media_type, :subtype, - :param) - def multipart? - return false - end - end - - # Net::IMAP::BodyTypeMultipart represents multipart body structures - # of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name as defined in [MIME-IMB]. - # - # subtype:: Returns the content subtype name as defined in [MIME-IMB]. - # - # parts:: Returns multiple parts. - # - # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. - # - # disposition:: Returns a Net::IMAP::ContentDisposition object giving - # the content disposition. - # - # language:: Returns a string or an array of strings giving the body - # language value as defined in [LANGUAGE-TAGS]. - # - # extension:: Returns extension data. - # - # multipart?:: Returns true. - # - class BodyTypeMultipart < Struct.new(:media_type, :subtype, - :parts, - :param, :disposition, :language, - :extension) - def multipart? - return true - end - - # Obsolete: use +subtype+ instead. Calling this will - # generate a warning message to +stderr+, then return - # the value of +subtype+. - def media_subtype - warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1) - return subtype - end - end - - class BodyTypeExtension < Struct.new(:media_type, :subtype, - :params, :content_id, - :description, :encoding, :size) - def multipart? - return false - end - end - - class ResponseParser # :nodoc: - def initialize - @str = nil - @pos = nil - @lex_state = nil - @token = nil - @flag_symbols = {} - end - - def parse(str) - @str = str - @pos = 0 - @lex_state = EXPR_BEG - @token = nil - return response - end - - private - - EXPR_BEG = :EXPR_BEG - EXPR_DATA = :EXPR_DATA - EXPR_TEXT = :EXPR_TEXT - EXPR_RTEXT = :EXPR_RTEXT - EXPR_CTEXT = :EXPR_CTEXT - - T_SPACE = :SPACE - T_NIL = :NIL - T_NUMBER = :NUMBER - T_ATOM = :ATOM - T_QUOTED = :QUOTED - T_LPAR = :LPAR - T_RPAR = :RPAR - T_BSLASH = :BSLASH - T_STAR = :STAR - T_LBRA = :LBRA - T_RBRA = :RBRA - T_LITERAL = :LITERAL - T_PLUS = :PLUS - T_PERCENT = :PERCENT - T_CRLF = :CRLF - T_EOF = :EOF - T_TEXT = :TEXT - - BEG_REGEXP = /\G(?:\ -(?# 1: SPACE )( +)|\ -(?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ -(?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ -(?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+]+)|\ -(?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ -(?# 6: LPAR )(\()|\ -(?# 7: RPAR )(\))|\ -(?# 8: BSLASH )(\\)|\ -(?# 9: STAR )(\*)|\ -(?# 10: LBRA )(\[)|\ -(?# 11: RBRA )(\])|\ -(?# 12: LITERAL )\{(\d+)\}\r\n|\ -(?# 13: PLUS )(\+)|\ -(?# 14: PERCENT )(%)|\ -(?# 15: CRLF )(\r\n)|\ -(?# 16: EOF )(\z))/ni - - DATA_REGEXP = /\G(?:\ -(?# 1: SPACE )( )|\ -(?# 2: NIL )(NIL)|\ -(?# 3: NUMBER )(\d+)|\ -(?# 4: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ -(?# 5: LITERAL )\{(\d+)\}\r\n|\ -(?# 6: LPAR )(\()|\ -(?# 7: RPAR )(\)))/ni - - TEXT_REGEXP = /\G(?:\ -(?# 1: TEXT )([^\x00\r\n]*))/ni - - RTEXT_REGEXP = /\G(?:\ -(?# 1: LBRA )(\[)|\ -(?# 2: TEXT )([^\x00\r\n]*))/ni - - CTEXT_REGEXP = /\G(?:\ -(?# 1: TEXT )([^\x00\r\n\]]*))/ni - - Token = Struct.new(:symbol, :value) - - def response - token = lookahead - case token.symbol - when T_PLUS - result = continue_req - when T_STAR - result = response_untagged - else - result = response_tagged - end - while lookahead.symbol == T_SPACE - # Ignore trailing space for Microsoft Exchange Server - shift_token - end - match(T_CRLF) - match(T_EOF) - return result - end - - def continue_req - match(T_PLUS) - token = lookahead - if token.symbol == T_SPACE - shift_token - return ContinuationRequest.new(resp_text, @str) - else - return ContinuationRequest.new(ResponseText.new(nil, ""), @str) - end - end - - def response_untagged - match(T_STAR) - match(T_SPACE) - token = lookahead - if token.symbol == T_NUMBER - return numeric_response - elsif token.symbol == T_ATOM - case token.value - when /\A(?:OK|NO|BAD|BYE|PREAUTH)\z/ni - return response_cond - when /\A(?:FLAGS)\z/ni - return flags_response - when /\A(?:LIST|LSUB|XLIST)\z/ni - return list_response - when /\A(?:QUOTA)\z/ni - return getquota_response - when /\A(?:QUOTAROOT)\z/ni - return getquotaroot_response - when /\A(?:ACL)\z/ni - return getacl_response - when /\A(?:SEARCH|SORT)\z/ni - return search_response - when /\A(?:THREAD)\z/ni - return thread_response - when /\A(?:STATUS)\z/ni - return status_response - when /\A(?:CAPABILITY)\z/ni - return capability_response - else - return text_response - end - else - parse_error("unexpected token %s", token.symbol) - end - end - - def response_tagged - tag = atom - match(T_SPACE) - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return TaggedResponse.new(tag, name, resp_text, @str) - end - - def response_cond - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return UntaggedResponse.new(name, resp_text, @str) - end - - def numeric_response - n = number - match(T_SPACE) - token = match(T_ATOM) - name = token.value.upcase - case name - when "EXISTS", "RECENT", "EXPUNGE" - return UntaggedResponse.new(name, n, @str) - when "FETCH" - shift_token - match(T_SPACE) - data = FetchData.new(n, msg_att(n)) - return UntaggedResponse.new(name, data, @str) - end - end - - def msg_att(n) - match(T_LPAR) - attr = {} - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - break - when T_SPACE - shift_token - next - end - case token.value - when /\A(?:ENVELOPE)\z/ni - name, val = envelope_data - when /\A(?:FLAGS)\z/ni - name, val = flags_data - when /\A(?:INTERNALDATE)\z/ni - name, val = internaldate_data - when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni - name, val = rfc822_text - when /\A(?:RFC822\.SIZE)\z/ni - name, val = rfc822_size - when /\A(?:BODY(?:STRUCTURE)?)\z/ni - name, val = body_data - when /\A(?:UID)\z/ni - name, val = uid_data - when /\A(?:MODSEQ)\z/ni - name, val = modseq_data - else - parse_error("unknown attribute `%s' for {%d}", token.value, n) - end - attr[name] = val - end - return attr - end - - def envelope_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, envelope - end - - def envelope - @lex_state = EXPR_DATA - token = lookahead - if token.symbol == T_NIL - shift_token - result = nil - else - match(T_LPAR) - date = nstring - match(T_SPACE) - subject = nstring - match(T_SPACE) - from = address_list - match(T_SPACE) - sender = address_list - match(T_SPACE) - reply_to = address_list - match(T_SPACE) - to = address_list - match(T_SPACE) - cc = address_list - match(T_SPACE) - bcc = address_list - match(T_SPACE) - in_reply_to = nstring - match(T_SPACE) - message_id = nstring - match(T_RPAR) - result = Envelope.new(date, subject, from, sender, reply_to, - to, cc, bcc, in_reply_to, message_id) - end - @lex_state = EXPR_BEG - return result - end - - def flags_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, flag_list - end - - def internaldate_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - token = match(T_QUOTED) - return name, token.value - end - - def rfc822_text - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - if token.symbol == T_LBRA - shift_token - match(T_RBRA) - end - match(T_SPACE) - return name, nstring - end - - def rfc822_size - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, number - end - - def body_data - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - if token.symbol == T_SPACE - shift_token - return name, body - end - name.concat(section) - token = lookahead - if token.symbol == T_ATOM - name.concat(token.value) - shift_token - end - match(T_SPACE) - data = nstring - return name, data - end - - def body - @lex_state = EXPR_DATA - token = lookahead - if token.symbol == T_NIL - shift_token - result = nil - else - match(T_LPAR) - token = lookahead - if token.symbol == T_LPAR - result = body_type_mpart - else - result = body_type_1part - end - match(T_RPAR) - end - @lex_state = EXPR_BEG - return result - end - - def body_type_1part - token = lookahead - case token.value - when /\A(?:TEXT)\z/ni - return body_type_text - when /\A(?:MESSAGE)\z/ni - return body_type_msg - when /\A(?:ATTACHMENT)\z/ni - return body_type_attachment - when /\A(?:MIXED)\z/ni - return body_type_mixed - else - return body_type_basic - end - end - - def body_type_basic - mtype, msubtype = media_type - token = lookahead - if token.symbol == T_RPAR - return BodyTypeBasic.new(mtype, msubtype) - end - match(T_SPACE) - param, content_id, desc, enc, size = body_fields - md5, disposition, language, extension = body_ext_1part - return BodyTypeBasic.new(mtype, msubtype, - param, content_id, - desc, enc, size, - md5, disposition, language, extension) - end - - def body_type_text - mtype, msubtype = media_type - match(T_SPACE) - param, content_id, desc, enc, size = body_fields - match(T_SPACE) - lines = number - md5, disposition, language, extension = body_ext_1part - return BodyTypeText.new(mtype, msubtype, - param, content_id, - desc, enc, size, - lines, - md5, disposition, language, extension) - end - - def body_type_msg - mtype, msubtype = media_type - match(T_SPACE) - param, content_id, desc, enc, size = body_fields - - token = lookahead - if token.symbol == T_RPAR - # If this is not message/rfc822, we shouldn't apply the RFC822 - # spec to it. We should handle anything other than - # message/rfc822 using multipart extension data [rfc3501] (i.e. - # the data itself won't be returned, we would have to retrieve it - # with BODYSTRUCTURE instead of with BODY - - # Also, sometimes a message/rfc822 is included as a large - # attachment instead of having all of the other details - # (e.g. attaching a .eml file to an email) - if msubtype == "RFC822" - return BodyTypeMessage.new(mtype, msubtype, param, content_id, - desc, enc, size, nil, nil, nil, nil, - nil, nil, nil) - else - return BodyTypeExtension.new(mtype, msubtype, - param, content_id, - desc, enc, size) - end - end - - match(T_SPACE) - env = envelope - match(T_SPACE) - b = body - match(T_SPACE) - lines = number - md5, disposition, language, extension = body_ext_1part - return BodyTypeMessage.new(mtype, msubtype, - param, content_id, - desc, enc, size, - env, b, lines, - md5, disposition, language, extension) - end - - def body_type_attachment - mtype = case_insensitive_string - match(T_SPACE) - param = body_fld_param - return BodyTypeAttachment.new(mtype, nil, param) - end - - def body_type_mixed - mtype = "MULTIPART" - msubtype = case_insensitive_string - param, disposition, language, extension = body_ext_mpart - return BodyTypeBasic.new(mtype, msubtype, param, nil, nil, nil, nil, nil, disposition, language, extension) - end - - def body_type_mpart - parts = [] - while true - token = lookahead - if token.symbol == T_SPACE - shift_token - break - end - parts.push(body) - end - mtype = "MULTIPART" - msubtype = case_insensitive_string - param, disposition, language, extension = body_ext_mpart - return BodyTypeMultipart.new(mtype, msubtype, parts, - param, disposition, language, - extension) - end - - def media_type - mtype = case_insensitive_string - token = lookahead - if token.symbol != T_SPACE - return mtype, nil - end - match(T_SPACE) - msubtype = case_insensitive_string - return mtype, msubtype - end - - def body_fields - param = body_fld_param - match(T_SPACE) - content_id = nstring - match(T_SPACE) - desc = nstring - match(T_SPACE) - enc = case_insensitive_string - match(T_SPACE) - size = number - return param, content_id, desc, enc, size - end - - def body_fld_param - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - end - match(T_LPAR) - param = {} - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - break - when T_SPACE - shift_token - end - name = case_insensitive_string - match(T_SPACE) - val = string - param[name] = val - end - return param - end - - def body_ext_1part - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return nil - end - md5 = nstring - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return md5 - end - disposition = body_fld_dsp - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return md5, disposition - end - language = body_fld_lang - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return md5, disposition, language - end - - extension = body_extensions - return md5, disposition, language, extension - end - - def body_ext_mpart - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return nil - end - param = body_fld_param - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return param - end - disposition = body_fld_dsp - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return param, disposition - end - language = body_fld_lang - - token = lookahead - if token.symbol == T_SPACE - shift_token - else - return param, disposition, language - end - - extension = body_extensions - return param, disposition, language, extension - end - - def body_fld_dsp - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - end - match(T_LPAR) - dsp_type = case_insensitive_string - match(T_SPACE) - param = body_fld_param - match(T_RPAR) - return ContentDisposition.new(dsp_type, param) - end - - def body_fld_lang - token = lookahead - if token.symbol == T_LPAR - shift_token - result = [] - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - return result - when T_SPACE - shift_token - end - result.push(case_insensitive_string) - end - else - lang = nstring - if lang - return lang.upcase - else - return lang - end - end - end - - def body_extensions - result = [] - while true - token = lookahead - case token.symbol - when T_RPAR - return result - when T_SPACE - shift_token - end - result.push(body_extension) - end - end - - def body_extension - token = lookahead - case token.symbol - when T_LPAR - shift_token - result = body_extensions - match(T_RPAR) - return result - when T_NUMBER - return number - else - return nstring - end - end - - def section - str = String.new - token = match(T_LBRA) - str.concat(token.value) - token = match(T_ATOM, T_NUMBER, T_RBRA) - if token.symbol == T_RBRA - str.concat(token.value) - return str - end - str.concat(token.value) - token = lookahead - if token.symbol == T_SPACE - shift_token - str.concat(token.value) - token = match(T_LPAR) - str.concat(token.value) - while true - token = lookahead - case token.symbol - when T_RPAR - str.concat(token.value) - shift_token - break - when T_SPACE - shift_token - str.concat(token.value) - end - str.concat(format_string(astring)) - end - end - token = match(T_RBRA) - str.concat(token.value) - return str - end - - def format_string(str) - case str - when "" - return '""' - when /[\x80-\xff\r\n]/n - # literal - return "{" + str.bytesize.to_s + "}" + CRLF + str - when /[(){ \x00-\x1f\x7f%*"\\]/n - # quoted string - return '"' + str.gsub(/["\\]/n, "\\\\\\&") + '"' - else - # atom - return str - end - end - - def uid_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, number - end - - def modseq_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - match(T_LPAR) - modseq = number - match(T_RPAR) - return name, modseq - end - - def text_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - @lex_state = EXPR_TEXT - token = match(T_TEXT) - @lex_state = EXPR_BEG - return UntaggedResponse.new(name, token.value) - end - - def flags_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return UntaggedResponse.new(name, flag_list, @str) - end - - def list_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return UntaggedResponse.new(name, mailbox_list, @str) - end - - def mailbox_list - attr = flag_list - match(T_SPACE) - token = match(T_QUOTED, T_NIL) - if token.symbol == T_NIL - delim = nil - else - delim = token.value - end - match(T_SPACE) - name = astring - return MailboxList.new(attr, delim, name) - end - - def getquota_response - # If quota never established, get back - # `NO Quota root does not exist'. - # If quota removed, get `()' after the - # folder spec with no mention of `STORAGE'. - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - mailbox = astring - match(T_SPACE) - match(T_LPAR) - token = lookahead - case token.symbol - when T_RPAR - shift_token - data = MailboxQuota.new(mailbox, nil, nil) - return UntaggedResponse.new(name, data, @str) - when T_ATOM - shift_token - match(T_SPACE) - token = match(T_NUMBER) - usage = token.value - match(T_SPACE) - token = match(T_NUMBER) - quota = token.value - match(T_RPAR) - data = MailboxQuota.new(mailbox, usage, quota) - return UntaggedResponse.new(name, data, @str) - else - parse_error("unexpected token %s", token.symbol) - end - end - - def getquotaroot_response - # Similar to getquota, but only admin can use getquota. - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - mailbox = astring - quotaroots = [] - while true - token = lookahead - break unless token.symbol == T_SPACE - shift_token - quotaroots.push(astring) - end - data = MailboxQuotaRoot.new(mailbox, quotaroots) - return UntaggedResponse.new(name, data, @str) - end - - def getacl_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - mailbox = astring - data = [] - token = lookahead - if token.symbol == T_SPACE - shift_token - while true - token = lookahead - case token.symbol - when T_CRLF - break - when T_SPACE - shift_token - end - user = astring - match(T_SPACE) - rights = astring - data.push(MailboxACLItem.new(user, rights, mailbox)) - end - end - return UntaggedResponse.new(name, data, @str) - end - - def search_response - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - if token.symbol == T_SPACE - shift_token - data = [] - while true - token = lookahead - case token.symbol - when T_CRLF - break - when T_SPACE - shift_token - when T_NUMBER - data.push(number) - when T_LPAR - # TODO: include the MODSEQ value in a response - shift_token - match(T_ATOM) - match(T_SPACE) - match(T_NUMBER) - match(T_RPAR) - end - end - else - data = [] - end - return UntaggedResponse.new(name, data, @str) - end - - def thread_response - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - - if token.symbol == T_SPACE - threads = [] - - while true - shift_token - token = lookahead - - case token.symbol - when T_LPAR - threads << thread_branch(token) - when T_CRLF - break - end - end - else - # no member - threads = [] - end - - return UntaggedResponse.new(name, threads, @str) - end - - def thread_branch(token) - rootmember = nil - lastmember = nil - - while true - shift_token # ignore first T_LPAR - token = lookahead - - case token.symbol - when T_NUMBER - # new member - newmember = ThreadMember.new(number, []) - if rootmember.nil? - rootmember = newmember - else - lastmember.children << newmember - end - lastmember = newmember - when T_SPACE - # do nothing - when T_LPAR - if rootmember.nil? - # dummy member - lastmember = rootmember = ThreadMember.new(nil, []) - end - - lastmember.children << thread_branch(token) - when T_RPAR - break - end - end - - return rootmember - end - - def status_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - mailbox = astring - match(T_SPACE) - match(T_LPAR) - attr = {} - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - break - when T_SPACE - shift_token - end - token = match(T_ATOM) - key = token.value.upcase - match(T_SPACE) - val = number - attr[key] = val - end - data = StatusData.new(mailbox, attr) - return UntaggedResponse.new(name, data, @str) - end - - def capability_response - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - data = [] - while true - token = lookahead - case token.symbol - when T_CRLF - break - when T_SPACE - shift_token - next - end - data.push(atom.upcase) - end - return UntaggedResponse.new(name, data, @str) - end - - def resp_text - @lex_state = EXPR_RTEXT - token = lookahead - if token.symbol == T_LBRA - code = resp_text_code - else - code = nil - end - token = match(T_TEXT) - @lex_state = EXPR_BEG - return ResponseText.new(code, token.value) - end - - def resp_text_code - @lex_state = EXPR_BEG - match(T_LBRA) - token = match(T_ATOM) - name = token.value.upcase - case name - when /\A(?:ALERT|PARSE|READ-ONLY|READ-WRITE|TRYCREATE|NOMODSEQ)\z/n - result = ResponseCode.new(name, nil) - when /\A(?:PERMANENTFLAGS)\z/n - match(T_SPACE) - result = ResponseCode.new(name, flag_list) - when /\A(?:UIDVALIDITY|UIDNEXT|UNSEEN)\z/n - match(T_SPACE) - result = ResponseCode.new(name, number) - else - token = lookahead - if token.symbol == T_SPACE - shift_token - @lex_state = EXPR_CTEXT - token = match(T_TEXT) - @lex_state = EXPR_BEG - result = ResponseCode.new(name, token.value) - else - result = ResponseCode.new(name, nil) - end - end - match(T_RBRA) - @lex_state = EXPR_RTEXT - return result - end - - def address_list - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - else - result = [] - match(T_LPAR) - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - break - when T_SPACE - shift_token - end - result.push(address) - end - return result - end - end - - ADDRESS_REGEXP = /\G\ -(?# 1: NAME )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ -(?# 2: ROUTE )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ -(?# 3: MAILBOX )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \ -(?# 4: HOST )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)")\ -\)/ni - - def address - match(T_LPAR) - if @str.index(ADDRESS_REGEXP, @pos) - # address does not include literal. - @pos = $~.end(0) - name = $1 - route = $2 - mailbox = $3 - host = $4 - for s in [name, route, mailbox, host] - if s - s.gsub!(/\\(["\\])/n, "\\1") - end - end - else - name = nstring - match(T_SPACE) - route = nstring - match(T_SPACE) - mailbox = nstring - match(T_SPACE) - host = nstring - match(T_RPAR) - end - return Address.new(name, route, mailbox, host) - end - - FLAG_REGEXP = /\ -(?# FLAG )\\([^\x80-\xff(){ \x00-\x1f\x7f%"\\]+)|\ -(?# ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\]+)/n - - def flag_list - if @str.index(/\(([^)]*)\)/ni, @pos) - @pos = $~.end(0) - return $1.scan(FLAG_REGEXP).collect { |flag, atom| - if atom - atom - else - symbol = flag.capitalize.intern - @flag_symbols[symbol] = true - if @flag_symbols.length > IMAP.max_flag_count - raise FlagCountError, "number of flag symbols exceeded" - end - symbol - end - } - else - parse_error("invalid flag list") - end - end - - def nstring - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - else - return string - end - end - - def astring - token = lookahead - if string_token?(token) - return string - else - return atom - end - end - - def string - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - end - token = match(T_QUOTED, T_LITERAL) - return token.value - end - - STRING_TOKENS = [T_QUOTED, T_LITERAL, T_NIL] - - def string_token?(token) - return STRING_TOKENS.include?(token.symbol) - end - - def case_insensitive_string - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - end - token = match(T_QUOTED, T_LITERAL) - return token.value.upcase - end - - def atom - result = String.new - while true - token = lookahead - if atom_token?(token) - result.concat(token.value) - shift_token - else - if result.empty? - parse_error("unexpected token %s", token.symbol) - else - return result - end - end - end - end - - ATOM_TOKENS = [ - T_ATOM, - T_NUMBER, - T_NIL, - T_LBRA, - T_RBRA, - T_PLUS - ] - - def atom_token?(token) - return ATOM_TOKENS.include?(token.symbol) - end - - def number - token = lookahead - if token.symbol == T_NIL - shift_token - return nil - end - token = match(T_NUMBER) - return token.value.to_i - end - - def nil_atom - match(T_NIL) - return nil - end - - def match(*args) - token = lookahead - unless args.include?(token.symbol) - parse_error('unexpected token %s (expected %s)', - token.symbol.id2name, - args.collect {|i| i.id2name}.join(" or ")) - end - shift_token - return token - end - - def lookahead - unless @token - @token = next_token - end - return @token - end - - def shift_token - @token = nil - end - - def next_token - case @lex_state - when EXPR_BEG - if @str.index(BEG_REGEXP, @pos) - @pos = $~.end(0) - if $1 - return Token.new(T_SPACE, $+) - elsif $2 - return Token.new(T_NIL, $+) - elsif $3 - return Token.new(T_NUMBER, $+) - elsif $4 - return Token.new(T_ATOM, $+) - elsif $5 - return Token.new(T_QUOTED, - $+.gsub(/\\(["\\])/n, "\\1")) - elsif $6 - return Token.new(T_LPAR, $+) - elsif $7 - return Token.new(T_RPAR, $+) - elsif $8 - return Token.new(T_BSLASH, $+) - elsif $9 - return Token.new(T_STAR, $+) - elsif $10 - return Token.new(T_LBRA, $+) - elsif $11 - return Token.new(T_RBRA, $+) - elsif $12 - len = $+.to_i - val = @str[@pos, len] - @pos += len - return Token.new(T_LITERAL, val) - elsif $13 - return Token.new(T_PLUS, $+) - elsif $14 - return Token.new(T_PERCENT, $+) - elsif $15 - return Token.new(T_CRLF, $+) - elsif $16 - return Token.new(T_EOF, $+) - else - parse_error("[Net::IMAP BUG] BEG_REGEXP is invalid") - end - else - @str.index(/\S*/n, @pos) - parse_error("unknown token - %s", $&.dump) - end - when EXPR_DATA - if @str.index(DATA_REGEXP, @pos) - @pos = $~.end(0) - if $1 - return Token.new(T_SPACE, $+) - elsif $2 - return Token.new(T_NIL, $+) - elsif $3 - return Token.new(T_NUMBER, $+) - elsif $4 - return Token.new(T_QUOTED, - $+.gsub(/\\(["\\])/n, "\\1")) - elsif $5 - len = $+.to_i - val = @str[@pos, len] - @pos += len - return Token.new(T_LITERAL, val) - elsif $6 - return Token.new(T_LPAR, $+) - elsif $7 - return Token.new(T_RPAR, $+) - else - parse_error("[Net::IMAP BUG] DATA_REGEXP is invalid") - end - else - @str.index(/\S*/n, @pos) - parse_error("unknown token - %s", $&.dump) - end - when EXPR_TEXT - if @str.index(TEXT_REGEXP, @pos) - @pos = $~.end(0) - if $1 - return Token.new(T_TEXT, $+) - else - parse_error("[Net::IMAP BUG] TEXT_REGEXP is invalid") - end - else - @str.index(/\S*/n, @pos) - parse_error("unknown token - %s", $&.dump) - end - when EXPR_RTEXT - if @str.index(RTEXT_REGEXP, @pos) - @pos = $~.end(0) - if $1 - return Token.new(T_LBRA, $+) - elsif $2 - return Token.new(T_TEXT, $+) - else - parse_error("[Net::IMAP BUG] RTEXT_REGEXP is invalid") - end - else - @str.index(/\S*/n, @pos) - parse_error("unknown token - %s", $&.dump) - end - when EXPR_CTEXT - if @str.index(CTEXT_REGEXP, @pos) - @pos = $~.end(0) - if $1 - return Token.new(T_TEXT, $+) - else - parse_error("[Net::IMAP BUG] CTEXT_REGEXP is invalid") - end - else - @str.index(/\S*/n, @pos) #/ - parse_error("unknown token - %s", $&.dump) - end - else - parse_error("invalid @lex_state - %s", @lex_state.inspect) - end - end - - def parse_error(fmt, *args) - if IMAP.debug - $stderr.printf("@str: %s\n", @str.dump) - $stderr.printf("@pos: %d\n", @pos) - $stderr.printf("@lex_state: %s\n", @lex_state) - if @token - $stderr.printf("@token.symbol: %s\n", @token.symbol) - $stderr.printf("@token.value: %s\n", @token.value.inspect) - end - end - raise ResponseParseError, format(fmt, *args) - end - end - - # Authenticator for the "LOGIN" authentication type. See - # #authenticate(). - class LoginAuthenticator - def process(data) - case @state - when STATE_USER - @state = STATE_PASSWORD - return @user - when STATE_PASSWORD - return @password - end - end - - private - - STATE_USER = :USER - STATE_PASSWORD = :PASSWORD - - def initialize(user, password) - @user = user - @password = password - @state = STATE_USER - end - end - add_authenticator "LOGIN", LoginAuthenticator - - # Authenticator for the "PLAIN" authentication type. See - # #authenticate(). - class PlainAuthenticator - def process(data) - return "\0#{@user}\0#{@password}" - end - - private - - def initialize(user, password) - @user = user - @password = password - end - end - add_authenticator "PLAIN", PlainAuthenticator - - # Authenticator for the "CRAM-MD5" authentication type. See - # #authenticate(). - class CramMD5Authenticator - def process(challenge) - digest = hmac_md5(challenge, @password) - return @user + " " + digest - end - - private - - def initialize(user, password) - @user = user - @password = password - end - - def hmac_md5(text, key) - if key.length > 64 - key = Digest::MD5.digest(key) - end - - k_ipad = key + "\0" * (64 - key.length) - k_opad = key + "\0" * (64 - key.length) - for i in 0..63 - k_ipad[i] = (k_ipad[i].ord ^ 0x36).chr - k_opad[i] = (k_opad[i].ord ^ 0x5c).chr - end - - digest = Digest::MD5.digest(k_ipad + text) - - return Digest::MD5.hexdigest(k_opad + digest) - end - end - add_authenticator "CRAM-MD5", CramMD5Authenticator - - # Authenticator for the "DIGEST-MD5" authentication type. See - # #authenticate(). - class DigestMD5Authenticator - def process(challenge) - case @stage - when STAGE_ONE - @stage = STAGE_TWO - sparams = {} - c = StringScanner.new(challenge) - while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/) - k, v = c[1], c[2] - if v =~ /^"(.*)"$/ - v = $1 - if v =~ /,/ - v = v.split(',') - end - end - sparams[k] = v - end - - raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0 - raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth") - - response = { - :nonce => sparams['nonce'], - :username => @user, - :realm => sparams['realm'], - :cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]), - :'digest-uri' => 'imap/' + sparams['realm'], - :qop => 'auth', - :maxbuf => 65535, - :nc => "%08d" % nc(sparams['nonce']), - :charset => sparams['charset'], - } - - response[:authzid] = @authname unless @authname.nil? - - # now, the real thing - a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') ) - - a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':') - a1 << ':' + response[:authzid] unless response[:authzid].nil? - - a2 = "AUTHENTICATE:" + response[:'digest-uri'] - a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/ - - response[:response] = Digest::MD5.hexdigest( - [ - Digest::MD5.hexdigest(a1), - response.values_at(:nonce, :nc, :cnonce, :qop), - Digest::MD5.hexdigest(a2) - ].join(':') - ) - - return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',') - when STAGE_TWO - @stage = nil - # if at the second stage, return an empty string - if challenge =~ /rspauth=/ - return '' - else - raise ResponseParseError, challenge - end - else - raise ResponseParseError, challenge - end - end - - def initialize(user, password, authname = nil) - @user, @password, @authname = user, password, authname - @nc, @stage = {}, STAGE_ONE - end - - private - - STAGE_ONE = :stage_one - STAGE_TWO = :stage_two - - def nc(nonce) - if @nc.has_key? nonce - @nc[nonce] = @nc[nonce] + 1 - else - @nc[nonce] = 1 - end - return @nc[nonce] - end - - # some responses need quoting - def qdval(k, v) - return if k.nil? or v.nil? - if %w"username authzid realm nonce cnonce digest-uri qop".include? k - v.gsub!(/([\\"])/, "\\\1") - return '%s="%s"' % [k, v] - else - return '%s=%s' % [k, v] - end - end - end - add_authenticator "DIGEST-MD5", DigestMD5Authenticator - - # Superclass of IMAP errors. - class Error < StandardError - end - - # Error raised when data is in the incorrect format. - class DataFormatError < Error - end - - # Error raised when a response from the server is non-parseable. - class ResponseParseError < Error - end - - # Superclass of all errors used to encapsulate "fail" responses - # from the server. - class ResponseError < Error - - # The response that caused this error - attr_accessor :response - - def initialize(response) - @response = response - - super @response.data.text - end - - end - - # Error raised upon a "NO" response from the server, indicating - # that the client command could not be completed successfully. - class NoResponseError < ResponseError - end - - # Error raised upon a "BAD" response from the server, indicating - # that the client command violated the IMAP protocol, or an internal - # server failure has occurred. - class BadResponseError < ResponseError - end - - # Error raised upon a "BYE" response from the server, indicating - # that the client is not being allowed to login, or has been timed - # out due to inactivity. - class ByeResponseError < ResponseError - end - - RESPONSE_ERRORS = Hash.new(ResponseError) - RESPONSE_ERRORS["NO"] = NoResponseError - RESPONSE_ERRORS["BAD"] = BadResponseError - - # Error raised when too many flags are interned to symbols. - class FlagCountError < Error - end - end -end diff --git a/ruby/lib/net/net-protocol.gemspec b/ruby/lib/net/net-protocol.gemspec new file mode 100644 index 000000000..021a5dcbf --- /dev/null +++ b/ruby/lib/net/net-protocol.gemspec @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +name = File.basename(__FILE__, ".gemspec") +version = ["lib", Array.new(name.count("-"), "..").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{The abstruct interface for net-* client.} + spec.description = %q{The abstruct interface for net-* client.} + spec.homepage = "https://github.com/ruby/net-protocol" + spec.required_ruby_version = Gem::Requirement.new(">= 2.6.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 2>/dev/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"] + + spec.add_dependency "timeout" + spec.add_dependency "io-wait" +end diff --git a/ruby/lib/net/pop.rb b/ruby/lib/net/pop.rb deleted file mode 100644 index 871234530..000000000 --- a/ruby/lib/net/pop.rb +++ /dev/null @@ -1,1023 +0,0 @@ -# frozen_string_literal: true -# = net/pop.rb -# -# Copyright (c) 1999-2007 Yukihiro Matsumoto. -# -# Copyright (c) 1999-2007 Minero Aoki. -# -# Written & maintained by Minero Aoki . -# -# Documented by William Webber and Minero Aoki. -# -# This program is free software. You can re-distribute and/or -# modify this program under the same terms as Ruby itself, -# Ruby Distribute License. -# -# NOTE: You can find Japanese version of this document at: -# http://docs.ruby-lang.org/ja/latest/library/net=2fpop.html -# -# $Id$ -# -# See Net::POP3 for documentation. -# - -require 'net/protocol' -require 'digest/md5' -require 'timeout' - -begin - require "openssl" -rescue LoadError -end - -module Net - - # Non-authentication POP3 protocol error - # (reply code "-ERR", except authentication). - class POPError < ProtocolError; end - - # POP3 authentication error. - class POPAuthenticationError < ProtoAuthError; end - - # Unexpected response from the server. - class POPBadResponse < POPError; end - - # - # == What is This Library? - # - # This library provides functionality for retrieving - # email via POP3, the Post Office Protocol version 3. For details - # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt). - # - # == Examples - # - # === Retrieving Messages - # - # This example retrieves messages from the server and deletes them - # on the server. - # - # Messages are written to files named 'inbox/1', 'inbox/2', .... - # Replace 'pop.example.com' with your POP3 server address, and - # 'YourAccount' and 'YourPassword' with the appropriate account - # details. - # - # require 'net/pop' - # - # pop = Net::POP3.new('pop.example.com') - # pop.start('YourAccount', 'YourPassword') # (1) - # if pop.mails.empty? - # puts 'No mail.' - # else - # i = 0 - # pop.each_mail do |m| # or "pop.mails.each ..." # (2) - # File.open("inbox/#{i}", 'w') do |f| - # f.write m.pop - # end - # m.delete - # i += 1 - # end - # puts "#{pop.mails.size} mails popped." - # end - # pop.finish # (3) - # - # 1. Call Net::POP3#start and start POP session. - # 2. Access messages by using POP3#each_mail and/or POP3#mails. - # 3. Close POP session by calling POP3#finish or use the block form of #start. - # - # === Shortened Code - # - # The example above is very verbose. You can shorten the code by using - # some utility methods. First, the block form of Net::POP3.start can - # be used instead of POP3.new, POP3#start and POP3#finish. - # - # require 'net/pop' - # - # Net::POP3.start('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |pop| - # if pop.mails.empty? - # puts 'No mail.' - # else - # i = 0 - # pop.each_mail do |m| # or "pop.mails.each ..." - # File.open("inbox/#{i}", 'w') do |f| - # f.write m.pop - # end - # m.delete - # i += 1 - # end - # puts "#{pop.mails.size} mails popped." - # end - # end - # - # POP3#delete_all is an alternative for #each_mail and #delete. - # - # require 'net/pop' - # - # Net::POP3.start('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |pop| - # if pop.mails.empty? - # puts 'No mail.' - # else - # i = 1 - # pop.delete_all do |m| - # File.open("inbox/#{i}", 'w') do |f| - # f.write m.pop - # end - # i += 1 - # end - # end - # end - # - # And here is an even shorter example. - # - # require 'net/pop' - # - # i = 0 - # Net::POP3.delete_all('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |m| - # File.open("inbox/#{i}", 'w') do |f| - # f.write m.pop - # end - # i += 1 - # end - # - # === Memory Space Issues - # - # All the examples above get each message as one big string. - # This example avoids this. - # - # require 'net/pop' - # - # i = 1 - # Net::POP3.delete_all('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |m| - # File.open("inbox/#{i}", 'w') do |f| - # m.pop do |chunk| # get a message little by little. - # f.write chunk - # end - # i += 1 - # end - # end - # - # === Using APOP - # - # The net/pop library supports APOP authentication. - # To use APOP, use the Net::APOP class instead of the Net::POP3 class. - # You can use the utility method, Net::POP3.APOP(). For example: - # - # require 'net/pop' - # - # # Use APOP authentication if $isapop == true - # pop = Net::POP3.APOP($isapop).new('apop.example.com', 110) - # pop.start('YourAccount', 'YourPassword') do |pop| - # # Rest of the code is the same. - # end - # - # === Fetch Only Selected Mail Using 'UIDL' POP Command - # - # If your POP server provides UIDL functionality, - # you can grab only selected mails from the POP server. - # e.g. - # - # def need_pop?( id ) - # # determine if we need pop this mail... - # end - # - # Net::POP3.start('pop.example.com', 110, - # 'Your account', 'Your password') do |pop| - # pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m| - # do_something(m.pop) - # end - # end - # - # The POPMail#unique_id() method returns the unique-id of the message as a - # String. Normally the unique-id is a hash of the message. - # - class POP3 < Protocol - - # svn revision of this library - Revision = %q$Revision$.split[1] - - # - # Class Parameters - # - - # returns the port for POP3 - def POP3.default_port - default_pop3_port() - end - - # The default port for POP3 connections, port 110 - def POP3.default_pop3_port - 110 - end - - # The default port for POP3S connections, port 995 - def POP3.default_pop3s_port - 995 - end - - def POP3.socket_type #:nodoc: obsolete - Net::InternetMessageIO - end - - # - # Utilities - # - - # Returns the APOP class if +isapop+ is true; otherwise, returns - # the POP class. For example: - # - # # Example 1 - # pop = Net::POP3::APOP($is_apop).new(addr, port) - # - # # Example 2 - # Net::POP3::APOP($is_apop).start(addr, port) do |pop| - # .... - # end - # - def POP3.APOP(isapop) - isapop ? APOP : POP3 - end - - # Starts a POP3 session and iterates over each POPMail object, - # yielding it to the +block+. - # This method is equivalent to: - # - # Net::POP3.start(address, port, account, password) do |pop| - # pop.each_mail do |m| - # yield m - # end - # end - # - # This method raises a POPAuthenticationError if authentication fails. - # - # === Example - # - # Net::POP3.foreach('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |m| - # file.write m.pop - # m.delete if $DELETE - # end - # - def POP3.foreach(address, port = nil, - account = nil, password = nil, - isapop = false, &block) # :yields: message - start(address, port, account, password, isapop) {|pop| - pop.each_mail(&block) - } - end - - # Starts a POP3 session and deletes all messages on the server. - # If a block is given, each POPMail object is yielded to it before - # being deleted. - # - # This method raises a POPAuthenticationError if authentication fails. - # - # === Example - # - # Net::POP3.delete_all('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |m| - # file.write m.pop - # end - # - def POP3.delete_all(address, port = nil, - account = nil, password = nil, - isapop = false, &block) - start(address, port, account, password, isapop) {|pop| - pop.delete_all(&block) - } - end - - # Opens a POP3 session, attempts authentication, and quits. - # - # This method raises POPAuthenticationError if authentication fails. - # - # === Example: normal POP3 - # - # Net::POP3.auth_only('pop.example.com', 110, - # 'YourAccount', 'YourPassword') - # - # === Example: APOP - # - # Net::POP3.auth_only('pop.example.com', 110, - # 'YourAccount', 'YourPassword', true) - # - def POP3.auth_only(address, port = nil, - account = nil, password = nil, - isapop = false) - new(address, port, isapop).auth_only account, password - end - - # Starts a pop3 session, attempts authentication, and quits. - # This method must not be called while POP3 session is opened. - # This method raises POPAuthenticationError if authentication fails. - def auth_only(account, password) - raise IOError, 'opening previously opened POP session' if started? - start(account, password) { - ; - } - end - - # - # SSL - # - - @ssl_params = nil - - # :call-seq: - # Net::POP.enable_ssl(params = {}) - # - # Enable SSL for all new instances. - # +params+ is passed to OpenSSL::SSLContext#set_params. - def POP3.enable_ssl(*args) - @ssl_params = create_ssl_params(*args) - end - - # Constructs proper parameters from arguments - def POP3.create_ssl_params(verify_or_params = {}, certs = nil) - begin - params = verify_or_params.to_hash - rescue NoMethodError - params = {} - params[:verify_mode] = verify_or_params - if certs - if File.file?(certs) - params[:ca_file] = certs - elsif File.directory?(certs) - params[:ca_path] = certs - end - end - end - return params - end - - # Disable SSL for all new instances. - def POP3.disable_ssl - @ssl_params = nil - end - - # returns the SSL Parameters - # - # see also POP3.enable_ssl - def POP3.ssl_params - return @ssl_params - end - - # returns +true+ if POP3.ssl_params is set - def POP3.use_ssl? - return !@ssl_params.nil? - end - - # returns whether verify_mode is enable from POP3.ssl_params - def POP3.verify - return @ssl_params[:verify_mode] - end - - # returns the :ca_file or :ca_path from POP3.ssl_params - def POP3.certs - return @ssl_params[:ca_file] || @ssl_params[:ca_path] - end - - # - # Session management - # - - # Creates a new POP3 object and open the connection. Equivalent to - # - # Net::POP3.new(address, port, isapop).start(account, password) - # - # If +block+ is provided, yields the newly-opened POP3 object to it, - # and automatically closes it at the end of the session. - # - # === Example - # - # Net::POP3.start(addr, port, account, password) do |pop| - # pop.each_mail do |m| - # file.write m.pop - # m.delete - # end - # end - # - def POP3.start(address, port = nil, - account = nil, password = nil, - isapop = false, &block) # :yield: pop - new(address, port, isapop).start(account, password, &block) - end - - # Creates a new POP3 object. - # - # +address+ is the hostname or ip address of your POP3 server. - # - # The optional +port+ is the port to connect to. - # - # The optional +isapop+ specifies whether this connection is going - # to use APOP authentication; it defaults to +false+. - # - # This method does *not* open the TCP connection. - def initialize(addr, port = nil, isapop = false) - @address = addr - @ssl_params = POP3.ssl_params - @port = port - @apop = isapop - - @command = nil - @socket = nil - @started = false - @open_timeout = 30 - @read_timeout = 60 - @debug_output = nil - - @mails = nil - @n_mails = nil - @n_bytes = nil - end - - # Does this instance use APOP authentication? - def apop? - @apop - end - - # does this instance use SSL? - def use_ssl? - return !@ssl_params.nil? - end - - # :call-seq: - # Net::POP#enable_ssl(params = {}) - # - # Enables SSL for this instance. Must be called before the connection is - # established to have any effect. - # +params[:port]+ is port to establish the SSL connection on; Defaults to 995. - # +params+ (except :port) is passed to OpenSSL::SSLContext#set_params. - def enable_ssl(verify_or_params = {}, certs = nil, port = nil) - begin - @ssl_params = verify_or_params.to_hash.dup - @port = @ssl_params.delete(:port) || @port - rescue NoMethodError - @ssl_params = POP3.create_ssl_params(verify_or_params, certs) - @port = port || @port - end - end - - # Disable SSL for all new instances. - def disable_ssl - @ssl_params = nil - end - - # Provide human-readable stringification of class state. - def inspect - +"#<#{self.class} #{@address}:#{@port} open=#{@started}>" - end - - # *WARNING*: This method causes a serious security hole. - # Use this method only for debugging. - # - # Set an output stream for debugging. - # - # === Example - # - # pop = Net::POP.new(addr, port) - # pop.set_debug_output $stderr - # pop.start(account, passwd) do |pop| - # .... - # end - # - def set_debug_output(arg) - @debug_output = arg - end - - # The address to connect to. - attr_reader :address - - # The port number to connect to. - def port - return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port) - end - - # Seconds to wait until a connection is opened. - # If the POP3 object cannot open a connection within this time, - # it raises a Net::OpenTimeout exception. The default value is 30 seconds. - attr_accessor :open_timeout - - # Seconds to wait until reading one block (by one read(1) call). - # If the POP3 object cannot complete a read() within this time, - # it raises a Net::ReadTimeout exception. The default value is 60 seconds. - attr_reader :read_timeout - - # Set the read timeout. - def read_timeout=(sec) - @command.socket.read_timeout = sec if @command - @read_timeout = sec - end - - # +true+ if the POP3 session has started. - def started? - @started - end - - alias active? started? #:nodoc: obsolete - - # Starts a POP3 session. - # - # When called with block, gives a POP3 object to the block and - # closes the session after block call finishes. - # - # This method raises a POPAuthenticationError if authentication fails. - def start(account, password) # :yield: pop - raise IOError, 'POP session already started' if @started - if block_given? - begin - do_start account, password - return yield(self) - ensure - do_finish - end - else - do_start account, password - return self - end - end - - # internal method for Net::POP3.start - def do_start(account, password) # :nodoc: - s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do - TCPSocket.open(@address, port) - end - if use_ssl? - raise 'openssl library not installed' unless defined?(OpenSSL) - context = OpenSSL::SSL::SSLContext.new - context.set_params(@ssl_params) - s = OpenSSL::SSL::SSLSocket.new(s, context) - s.hostname = @address - s.sync_close = true - ssl_socket_connect(s, @open_timeout) - if context.verify_mode != OpenSSL::SSL::VERIFY_NONE - s.post_connection_check(@address) - end - end - @socket = InternetMessageIO.new(s, - read_timeout: @read_timeout, - debug_output: @debug_output) - logging "POP session started: #{@address}:#{@port} (#{@apop ? 'APOP' : 'POP'})" - on_connect - @command = POP3Command.new(@socket) - if apop? - @command.apop account, password - else - @command.auth account, password - end - @started = true - ensure - # Authentication failed, clean up connection. - unless @started - s.close if s - @socket = nil - @command = nil - end - end - private :do_start - - # Does nothing - def on_connect # :nodoc: - end - private :on_connect - - # Finishes a POP3 session and closes TCP connection. - def finish - raise IOError, 'POP session not yet started' unless started? - do_finish - end - - # nil's out the: - # - mails - # - number counter for mails - # - number counter for bytes - # - quits the current command, if any - def do_finish # :nodoc: - @mails = nil - @n_mails = nil - @n_bytes = nil - @command.quit if @command - ensure - @started = false - @command = nil - @socket.close if @socket - @socket = nil - end - private :do_finish - - # Returns the current command. - # - # Raises IOError if there is no active socket - def command # :nodoc: - raise IOError, 'POP session not opened yet' \ - if not @socket or @socket.closed? - @command - end - private :command - - # - # POP protocol wrapper - # - - # Returns the number of messages on the POP server. - def n_mails - return @n_mails if @n_mails - @n_mails, @n_bytes = command().stat - @n_mails - end - - # Returns the total size in bytes of all the messages on the POP server. - def n_bytes - return @n_bytes if @n_bytes - @n_mails, @n_bytes = command().stat - @n_bytes - end - - # Returns an array of Net::POPMail objects, representing all the - # messages on the server. This array is renewed when the session - # restarts; otherwise, it is fetched from the server the first time - # this method is called (directly or indirectly) and cached. - # - # This method raises a POPError if an error occurs. - def mails - return @mails.dup if @mails - if n_mails() == 0 - # some popd raises error for LIST on the empty mailbox. - @mails = [] - return [] - end - - @mails = command().list.map {|num, size| - POPMail.new(num, size, self, command()) - } - @mails.dup - end - - # Yields each message to the passed-in block in turn. - # Equivalent to: - # - # pop3.mails.each do |popmail| - # .... - # end - # - # This method raises a POPError if an error occurs. - def each_mail(&block) # :yield: message - mails().each(&block) - end - - alias each each_mail - - # Deletes all messages on the server. - # - # If called with a block, yields each message in turn before deleting it. - # - # === Example - # - # n = 1 - # pop.delete_all do |m| - # File.open("inbox/#{n}") do |f| - # f.write m.pop - # end - # n += 1 - # end - # - # This method raises a POPError if an error occurs. - # - def delete_all # :yield: message - mails().each do |m| - yield m if block_given? - m.delete unless m.deleted? - end - end - - # Resets the session. This clears all "deleted" marks from messages. - # - # This method raises a POPError if an error occurs. - def reset - command().rset - mails().each do |m| - m.instance_eval { - @deleted = false - } - end - end - - def set_all_uids #:nodoc: internal use only (called from POPMail#uidl) - uidl = command().uidl - @mails.each {|m| m.uid = uidl[m.number] } - end - - # debugging output for +msg+ - def logging(msg) - @debug_output << msg + "\n" if @debug_output - end - - end # class POP3 - - # class aliases - POP = POP3 # :nodoc: - POPSession = POP3 # :nodoc: - POP3Session = POP3 # :nodoc: - - # - # This class is equivalent to POP3, except that it uses APOP authentication. - # - class APOP < POP3 - # Always returns true. - def apop? - true - end - end - - # class aliases - APOPSession = APOP - - # - # This class represents a message which exists on the POP server. - # Instances of this class are created by the POP3 class; they should - # not be directly created by the user. - # - class POPMail - - def initialize(num, len, pop, cmd) #:nodoc: - @number = num - @length = len - @pop = pop - @command = cmd - @deleted = false - @uid = nil - end - - # The sequence number of the message on the server. - attr_reader :number - - # The length of the message in octets. - attr_reader :length - alias size length - - # Provide human-readable stringification of class state. - def inspect - +"#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>" - end - - # - # This method fetches the message. If called with a block, the - # message is yielded to the block one chunk at a time. If called - # without a block, the message is returned as a String. The optional - # +dest+ argument will be prepended to the returned String; this - # argument is essentially obsolete. - # - # === Example without block - # - # POP3.start('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |pop| - # n = 1 - # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') do |f| - # f.write popmail.pop - # end - # popmail.delete - # n += 1 - # end - # end - # - # === Example with block - # - # POP3.start('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |pop| - # n = 1 - # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') do |f| - # popmail.pop do |chunk| #### - # f.write chunk - # end - # end - # n += 1 - # end - # end - # - # This method raises a POPError if an error occurs. - # - def pop( dest = +'', &block ) # :yield: message_chunk - if block_given? - @command.retr(@number, &block) - nil - else - @command.retr(@number) do |chunk| - dest << chunk - end - dest - end - end - - alias all pop #:nodoc: obsolete - alias mail pop #:nodoc: obsolete - - # Fetches the message header and +lines+ lines of body. - # - # The optional +dest+ argument is obsolete. - # - # This method raises a POPError if an error occurs. - def top(lines, dest = +'') - @command.top(@number, lines) do |chunk| - dest << chunk - end - dest - end - - # Fetches the message header. - # - # The optional +dest+ argument is obsolete. - # - # This method raises a POPError if an error occurs. - def header(dest = +'') - top(0, dest) - end - - # Marks a message for deletion on the server. Deletion does not - # actually occur until the end of the session; deletion may be - # cancelled for _all_ marked messages by calling POP3#reset(). - # - # This method raises a POPError if an error occurs. - # - # === Example - # - # POP3.start('pop.example.com', 110, - # 'YourAccount', 'YourPassword') do |pop| - # n = 1 - # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') do |f| - # f.write popmail.pop - # end - # popmail.delete #### - # n += 1 - # end - # end - # - def delete - @command.dele @number - @deleted = true - end - - alias delete! delete #:nodoc: obsolete - - # True if the mail has been deleted. - def deleted? - @deleted - end - - # Returns the unique-id of the message. - # Normally the unique-id is a hash string of the message. - # - # This method raises a POPError if an error occurs. - def unique_id - return @uid if @uid - @pop.set_all_uids - @uid - end - - alias uidl unique_id - - def uid=(uid) #:nodoc: internal use only - @uid = uid - end - - end # class POPMail - - - class POP3Command #:nodoc: internal use only - - def initialize(sock) - @socket = sock - @error_occurred = false - res = check_response(critical { recv_response() }) - @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/) - end - - attr_reader :socket - - def inspect - +"#<#{self.class} socket=#{@socket}>" - end - - def auth(account, password) - check_response_auth(critical { - check_response_auth(get_response('USER %s', account)) - get_response('PASS %s', password) - }) - end - - def apop(account, password) - raise POPAuthenticationError, 'not APOP server; cannot login' \ - unless @apop_stamp - check_response_auth(critical { - get_response('APOP %s %s', - account, - Digest::MD5.hexdigest(@apop_stamp + password)) - }) - end - - def list - critical { - getok 'LIST' - list = [] - @socket.each_list_item do |line| - m = /\A(\d+)[ \t]+(\d+)/.match(line) or - raise POPBadResponse, "bad response: #{line}" - list.push [m[1].to_i, m[2].to_i] - end - return list - } - end - - def stat - res = check_response(critical { get_response('STAT') }) - m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or - raise POPBadResponse, "wrong response format: #{res}" - [m[1].to_i, m[2].to_i] - end - - def rset - check_response(critical { get_response('RSET') }) - end - - def top(num, lines = 0, &block) - critical { - getok('TOP %d %d', num, lines) - @socket.each_message_chunk(&block) - } - end - - def retr(num, &block) - critical { - getok('RETR %d', num) - @socket.each_message_chunk(&block) - } - end - - def dele(num) - check_response(critical { get_response('DELE %d', num) }) - end - - def uidl(num = nil) - if num - res = check_response(critical { get_response('UIDL %d', num) }) - return res.split(/ /)[1] - else - critical { - getok('UIDL') - table = {} - @socket.each_list_item do |line| - num, uid = line.split - table[num.to_i] = uid - end - return table - } - end - end - - def quit - check_response(critical { get_response('QUIT') }) - end - - private - - def getok(fmt, *fargs) - @socket.writeline sprintf(fmt, *fargs) - check_response(recv_response()) - end - - def get_response(fmt, *fargs) - @socket.writeline sprintf(fmt, *fargs) - recv_response() - end - - def recv_response - @socket.readline - end - - def check_response(res) - raise POPError, res unless /\A\+OK/i =~ res - res - end - - def check_response_auth(res) - raise POPAuthenticationError, res unless /\A\+OK/i =~ res - res - end - - def critical - return '+OK dummy ok response' if @error_occurred - begin - return yield() - rescue Exception - @error_occurred = true - raise - end - end - - end # class POP3Command - -end # module Net diff --git a/ruby/lib/net/pop/net-pop.gemspec b/ruby/lib/net/pop/net-pop.gemspec deleted file mode 100644 index c1b0ffbd2..000000000 --- a/ruby/lib/net/pop/net-pop.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -begin - require_relative "lib/net/pop/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "net-pop" - spec.version = Net::POP3::VERSION - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{Ruby client library for POP3.} - spec.description = %q{Ruby client library for POP3.} - spec.homepage = "https://github.com/ruby/net-pop" - spec.license = "BSD-2-Clause" - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>/dev/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/ruby/lib/net/pop/version.rb b/ruby/lib/net/pop/version.rb deleted file mode 100644 index ef5c295cc..000000000 --- a/ruby/lib/net/pop/version.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Net - class Protocol; end - class POP3 < Protocol - VERSION = "0.1.0" - end -end diff --git a/ruby/lib/net/protocol.rb b/ruby/lib/net/protocol.rb index 07fbc6a21..add2c87a7 100644 --- a/ruby/lib/net/protocol.rb +++ b/ruby/lib/net/protocol.rb @@ -26,6 +26,8 @@ module Net # :nodoc: class Protocol #:nodoc: internal use only + VERSION = "0.1.2" + private def Protocol.protocol_param(name, val) module_eval(<<-End, __FILE__, __LINE__ + 1) @@ -381,7 +383,7 @@ def write_message_by_block(&block) len = writing { using_each_crlf_line { begin - block.call(WriteAdapter.new(self, :write_message_0)) + block.call(WriteAdapter.new(self.method(:write_message_0))) rescue LocalJumpError # allow `break' from writer block end @@ -445,17 +447,16 @@ def buffer_filling(buf, src) # The writer adapter class # class WriteAdapter - def initialize(socket, method) - @socket = socket - @method_id = method + def initialize(writer) + @writer = writer end def inspect - "#<#{self.class} socket=#{@socket.inspect}>" + "#<#{self.class} writer=#{@writer.inspect}>" end def write(str) - @socket.__send__(@method_id, str) + @writer.call(str) end alias print write diff --git a/ruby/lib/net/smtp.rb b/ruby/lib/net/smtp.rb deleted file mode 100644 index 460ad0823..000000000 --- a/ruby/lib/net/smtp.rb +++ /dev/null @@ -1,1072 +0,0 @@ -# frozen_string_literal: true -# = net/smtp.rb -# -# Copyright (c) 1999-2007 Yukihiro Matsumoto. -# -# Copyright (c) 1999-2007 Minero Aoki. -# -# Written & maintained by Minero Aoki . -# -# Documented by William Webber and Minero Aoki. -# -# This program is free software. You can re-distribute and/or -# modify this program under the same terms as Ruby itself. -# -# $Id$ -# -# See Net::SMTP for documentation. -# - -require 'net/protocol' -require 'digest/md5' -require 'timeout' -begin - require 'openssl' -rescue LoadError -end - -module Net - - # Module mixed in to all SMTP error classes - module SMTPError - # This *class* is a module for backward compatibility. - # In later release, this module becomes a class. - end - - # Represents an SMTP authentication error. - class SMTPAuthenticationError < ProtoAuthError - include SMTPError - end - - # Represents SMTP error code 4xx, a temporary error. - class SMTPServerBusy < ProtoServerError - include SMTPError - end - - # Represents an SMTP command syntax error (error code 500) - class SMTPSyntaxError < ProtoSyntaxError - include SMTPError - end - - # Represents a fatal SMTP error (error code 5xx, except for 500) - class SMTPFatalError < ProtoFatalError - include SMTPError - end - - # Unexpected reply code returned from server. - class SMTPUnknownError < ProtoUnknownError - include SMTPError - end - - # Command is not supported on server. - class SMTPUnsupportedCommand < ProtocolError - include SMTPError - end - - # - # == What is This Library? - # - # This library provides functionality to send internet - # mail via SMTP, the Simple Mail Transfer Protocol. For details of - # SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt). - # - # == What is This Library NOT? - # - # This library does NOT provide functions to compose internet mails. - # You must create them by yourself. If you want better mail support, - # try RubyMail or TMail or search for alternatives in - # {RubyGems.org}[https://rubygems.org/] or {The Ruby - # Toolbox}[https://www.ruby-toolbox.com/]. - # - # FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt). - # - # == Examples - # - # === Sending Messages - # - # You must open a connection to an SMTP server before sending messages. - # The first argument is the address of your SMTP server, and the second - # argument is the port number. Using SMTP.start with a block is the simplest - # way to do this. This way, the SMTP connection is closed automatically - # after the block is executed. - # - # require 'net/smtp' - # Net::SMTP.start('your.smtp.server', 25) do |smtp| - # # Use the SMTP object smtp only in this block. - # end - # - # Replace 'your.smtp.server' with your SMTP server. Normally - # your system manager or internet provider supplies a server - # for you. - # - # Then you can send messages. - # - # msgstr = < - # To: Destination Address - # Subject: test message - # Date: Sat, 23 Jun 2001 16:26:43 +0900 - # Message-Id: - # - # This is a test message. - # END_OF_MESSAGE - # - # require 'net/smtp' - # Net::SMTP.start('your.smtp.server', 25) do |smtp| - # smtp.send_message msgstr, - # 'your@mail.address', - # 'his_address@example.com' - # end - # - # === Closing the Session - # - # You MUST close the SMTP session after sending messages, by calling - # the #finish method: - # - # # using SMTP#finish - # smtp = Net::SMTP.start('your.smtp.server', 25) - # smtp.send_message msgstr, 'from@address', 'to@address' - # smtp.finish - # - # You can also use the block form of SMTP.start/SMTP#start. This closes - # the SMTP session automatically: - # - # # using block form of SMTP.start - # Net::SMTP.start('your.smtp.server', 25) do |smtp| - # smtp.send_message msgstr, 'from@address', 'to@address' - # end - # - # I strongly recommend this scheme. This form is simpler and more robust. - # - # === HELO domain - # - # In almost all situations, you must provide a third argument - # to SMTP.start/SMTP#start. This is the domain name which you are on - # (the host to send mail from). It is called the "HELO domain". - # The SMTP server will judge whether it should send or reject - # the SMTP session by inspecting the HELO domain. - # - # Net::SMTP.start('your.smtp.server', 25, - # 'mail.from.domain') { |smtp| ... } - # - # === SMTP Authentication - # - # The Net::SMTP class supports three authentication schemes; - # PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554]) - # To use SMTP authentication, pass extra arguments to - # SMTP.start/SMTP#start. - # - # # PLAIN - # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', - # 'Your Account', 'Your Password', :plain) - # # LOGIN - # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', - # 'Your Account', 'Your Password', :login) - # - # # CRAM MD5 - # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', - # 'Your Account', 'Your Password', :cram_md5) - # - class SMTP < Protocol - - Revision = %q$Revision$.split[1] - - # The default SMTP port number, 25. - def SMTP.default_port - 25 - end - - # The default mail submission port number, 587. - def SMTP.default_submission_port - 587 - end - - # The default SMTPS port number, 465. - def SMTP.default_tls_port - 465 - end - - class << self - alias default_ssl_port default_tls_port - end - - def SMTP.default_ssl_context - OpenSSL::SSL::SSLContext.new - end - - # - # Creates a new Net::SMTP object. - # - # +address+ is the hostname or ip address of your SMTP - # server. +port+ is the port to connect to; it defaults to - # port 25. - # - # This method does not open the TCP connection. You can use - # SMTP.start instead of SMTP.new if you want to do everything - # at once. Otherwise, follow SMTP.new with SMTP#start. - # - def initialize(address, port = nil) - @address = address - @port = (port || SMTP.default_port) - @esmtp = true - @capabilities = nil - @socket = nil - @started = false - @open_timeout = 30 - @read_timeout = 60 - @error_occurred = false - @debug_output = nil - @tls = false - @starttls = false - @ssl_context = nil - end - - # Provide human-readable stringification of class state. - def inspect - "#<#{self.class} #{@address}:#{@port} started=#{@started}>" - end - - # - # Set whether to use ESMTP or not. This should be done before - # calling #start. Note that if #start is called in ESMTP mode, - # and the connection fails due to a ProtocolError, the SMTP - # object will automatically switch to plain SMTP mode and - # retry (but not vice versa). - # - attr_accessor :esmtp - - # +true+ if the SMTP object uses ESMTP (which it does by default). - alias :esmtp? :esmtp - - # true if server advertises STARTTLS. - # You cannot get valid value before opening SMTP session. - def capable_starttls? - capable?('STARTTLS') - end - - def capable?(key) - return nil unless @capabilities - @capabilities[key] ? true : false - end - private :capable? - - # true if server advertises AUTH PLAIN. - # You cannot get valid value before opening SMTP session. - def capable_plain_auth? - auth_capable?('PLAIN') - end - - # true if server advertises AUTH LOGIN. - # You cannot get valid value before opening SMTP session. - def capable_login_auth? - auth_capable?('LOGIN') - end - - # true if server advertises AUTH CRAM-MD5. - # You cannot get valid value before opening SMTP session. - def capable_cram_md5_auth? - auth_capable?('CRAM-MD5') - end - - def auth_capable?(type) - return nil unless @capabilities - return false unless @capabilities['AUTH'] - @capabilities['AUTH'].include?(type) - end - private :auth_capable? - - # Returns supported authentication methods on this server. - # You cannot get valid value before opening SMTP session. - def capable_auth_types - return [] unless @capabilities - return [] unless @capabilities['AUTH'] - @capabilities['AUTH'] - end - - # true if this object uses SMTP/TLS (SMTPS). - def tls? - @tls - end - - alias ssl? tls? - - # Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for - # this object. Must be called before the connection is established - # to have any effect. +context+ is a OpenSSL::SSL::SSLContext object. - def enable_tls(context = SMTP.default_ssl_context) - raise 'openssl library not installed' unless defined?(OpenSSL) - raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls - @tls = true - @ssl_context = context - end - - alias enable_ssl enable_tls - - # Disables SMTP/TLS for this object. Must be called before the - # connection is established to have any effect. - def disable_tls - @tls = false - @ssl_context = nil - end - - alias disable_ssl disable_tls - - # Returns truth value if this object uses STARTTLS. - # If this object always uses STARTTLS, returns :always. - # If this object uses STARTTLS when the server support TLS, returns :auto. - def starttls? - @starttls - end - - # true if this object uses STARTTLS. - def starttls_always? - @starttls == :always - end - - # true if this object uses STARTTLS when server advertises STARTTLS. - def starttls_auto? - @starttls == :auto - end - - # Enables SMTP/TLS (STARTTLS) for this object. - # +context+ is a OpenSSL::SSL::SSLContext object. - def enable_starttls(context = SMTP.default_ssl_context) - raise 'openssl library not installed' unless defined?(OpenSSL) - raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls - @starttls = :always - @ssl_context = context - end - - # Enables SMTP/TLS (STARTTLS) for this object if server accepts. - # +context+ is a OpenSSL::SSL::SSLContext object. - def enable_starttls_auto(context = SMTP.default_ssl_context) - raise 'openssl library not installed' unless defined?(OpenSSL) - raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls - @starttls = :auto - @ssl_context = context - end - - # Disables SMTP/TLS (STARTTLS) for this object. Must be called - # before the connection is established to have any effect. - def disable_starttls - @starttls = false - @ssl_context = nil - end - - # The address of the SMTP server to connect to. - attr_reader :address - - # The port number of the SMTP server to connect to. - attr_reader :port - - # Seconds to wait while attempting to open a connection. - # If the connection cannot be opened within this time, a - # Net::OpenTimeout is raised. The default value is 30 seconds. - attr_accessor :open_timeout - - # Seconds to wait while reading one block (by one read(2) call). - # If the read(2) call does not complete within this time, a - # Net::ReadTimeout is raised. The default value is 60 seconds. - attr_reader :read_timeout - - # Set the number of seconds to wait until timing-out a read(2) - # call. - def read_timeout=(sec) - @socket.read_timeout = sec if @socket - @read_timeout = sec - end - - # - # WARNING: This method causes serious security holes. - # Use this method for only debugging. - # - # Set an output stream for debug logging. - # You must call this before #start. - # - # # example - # smtp = Net::SMTP.new(addr, port) - # smtp.set_debug_output $stderr - # smtp.start do |smtp| - # .... - # end - # - def debug_output=(arg) - @debug_output = arg - end - - alias set_debug_output debug_output= - - # - # SMTP session control - # - - # - # Creates a new Net::SMTP object and connects to the server. - # - # This method is equivalent to: - # - # Net::SMTP.new(address, port).start(helo_domain, account, password, authtype) - # - # === Example - # - # Net::SMTP.start('your.smtp.server') do |smtp| - # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] - # end - # - # === Block Usage - # - # If called with a block, the newly-opened Net::SMTP object is yielded - # to the block, and automatically closed when the block finishes. If called - # without a block, the newly-opened Net::SMTP object is returned to - # the caller, and it is the caller's responsibility to close it when - # finished. - # - # === Parameters - # - # +address+ is the hostname or ip address of your smtp server. - # - # +port+ is the port to connect to; it defaults to port 25. - # - # +helo+ is the _HELO_ _domain_ provided by the client to the - # server (see overview comments); it defaults to 'localhost'. - # - # The remaining arguments are used for SMTP authentication, if required - # or desired. +user+ is the account name; +secret+ is your password - # or other authentication token; and +authtype+ is the authentication - # type, one of :plain, :login, or :cram_md5. See the discussion of - # SMTP Authentication in the overview notes. - # - # === Errors - # - # This method may raise: - # - # * Net::SMTPAuthenticationError - # * Net::SMTPServerBusy - # * Net::SMTPSyntaxError - # * Net::SMTPFatalError - # * Net::SMTPUnknownError - # * Net::OpenTimeout - # * Net::ReadTimeout - # * IOError - # - def SMTP.start(address, port = nil, helo = 'localhost', - user = nil, secret = nil, authtype = nil, - &block) # :yield: smtp - new(address, port).start(helo, user, secret, authtype, &block) - end - - # +true+ if the SMTP session has been started. - def started? - @started - end - - # - # Opens a TCP connection and starts the SMTP session. - # - # === Parameters - # - # +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see - # the discussion in the overview notes. - # - # If both of +user+ and +secret+ are given, SMTP authentication - # will be attempted using the AUTH command. +authtype+ specifies - # the type of authentication to attempt; it must be one of - # :login, :plain, and :cram_md5. See the notes on SMTP Authentication - # in the overview. - # - # === Block Usage - # - # When this methods is called with a block, the newly-started SMTP - # object is yielded to the block, and automatically closed after - # the block call finishes. Otherwise, it is the caller's - # responsibility to close the session when finished. - # - # === Example - # - # This is very similar to the class method SMTP.start. - # - # require 'net/smtp' - # smtp = Net::SMTP.new('smtp.mail.server', 25) - # smtp.start(helo_domain, account, password, authtype) do |smtp| - # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] - # end - # - # The primary use of this method (as opposed to SMTP.start) - # is probably to set debugging (#set_debug_output) or ESMTP - # (#esmtp=), which must be done before the session is - # started. - # - # === Errors - # - # If session has already been started, an IOError will be raised. - # - # This method may raise: - # - # * Net::SMTPAuthenticationError - # * Net::SMTPServerBusy - # * Net::SMTPSyntaxError - # * Net::SMTPFatalError - # * Net::SMTPUnknownError - # * Net::OpenTimeout - # * Net::ReadTimeout - # * IOError - # - def start(helo = 'localhost', - user = nil, secret = nil, authtype = nil) # :yield: smtp - if block_given? - begin - do_start helo, user, secret, authtype - return yield(self) - ensure - do_finish - end - else - do_start helo, user, secret, authtype - return self - end - end - - # Finishes the SMTP session and closes TCP connection. - # Raises IOError if not started. - def finish - raise IOError, 'not yet started' unless started? - do_finish - end - - private - - def tcp_socket(address, port) - TCPSocket.open address, port - end - - def do_start(helo_domain, user, secret, authtype) - raise IOError, 'SMTP session already started' if @started - if user or secret - check_auth_method(authtype || DEFAULT_AUTH_TYPE) - check_auth_args user, secret - end - s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do - tcp_socket(@address, @port) - end - logging "Connection opened: #{@address}:#{@port}" - @socket = new_internet_message_io(tls? ? tlsconnect(s) : s) - check_response critical { recv_response() } - do_helo helo_domain - if starttls_always? or (capable_starttls? and starttls_auto?) - unless capable_starttls? - raise SMTPUnsupportedCommand, - "STARTTLS is not supported on this server" - end - starttls - @socket = new_internet_message_io(tlsconnect(s)) - # helo response may be different after STARTTLS - do_helo helo_domain - end - authenticate user, secret, (authtype || DEFAULT_AUTH_TYPE) if user - @started = true - ensure - unless @started - # authentication failed, cancel connection. - s.close if s - @socket = nil - end - end - - def ssl_socket(socket, context) - OpenSSL::SSL::SSLSocket.new socket, context - end - - def tlsconnect(s) - verified = false - s = ssl_socket(s, @ssl_context) - logging "TLS connection started" - s.sync_close = true - ssl_socket_connect(s, @open_timeout) - if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE - s.post_connection_check(@address) - end - verified = true - s - ensure - s.close unless verified - end - - def new_internet_message_io(s) - InternetMessageIO.new(s, read_timeout: @read_timeout, - debug_output: @debug_output) - end - - def do_helo(helo_domain) - res = @esmtp ? ehlo(helo_domain) : helo(helo_domain) - @capabilities = res.capabilities - rescue SMTPError - if @esmtp - @esmtp = false - @error_occurred = false - retry - end - raise - end - - def do_finish - quit if @socket and not @socket.closed? and not @error_occurred - ensure - @started = false - @error_occurred = false - @socket.close if @socket - @socket = nil - end - - # - # Message Sending - # - - public - - # - # Sends +msgstr+ as a message. Single CR ("\r") and LF ("\n") found - # in the +msgstr+, are converted into the CR LF pair. You cannot send a - # binary message with this method. +msgstr+ should include both - # the message headers and body. - # - # +from_addr+ is a String representing the source mail address. - # - # +to_addr+ is a String or Strings or Array of Strings, representing - # the destination mail address or addresses. - # - # === Example - # - # Net::SMTP.start('smtp.example.com') do |smtp| - # smtp.send_message msgstr, - # 'from@example.com', - # ['dest@example.com', 'dest2@example.com'] - # end - # - # === Errors - # - # This method may raise: - # - # * Net::SMTPServerBusy - # * Net::SMTPSyntaxError - # * Net::SMTPFatalError - # * Net::SMTPUnknownError - # * Net::ReadTimeout - # * IOError - # - def send_message(msgstr, from_addr, *to_addrs) - raise IOError, 'closed session' unless @socket - mailfrom from_addr - rcptto_list(to_addrs) {data msgstr} - end - - alias send_mail send_message - alias sendmail send_message # obsolete - - # - # Opens a message writer stream and gives it to the block. - # The stream is valid only in the block, and has these methods: - # - # puts(str = ''):: outputs STR and CR LF. - # print(str):: outputs STR. - # printf(fmt, *args):: outputs sprintf(fmt,*args). - # write(str):: outputs STR and returns the length of written bytes. - # <<(str):: outputs STR and returns self. - # - # If a single CR ("\r") or LF ("\n") is found in the message, - # it is converted to the CR LF pair. You cannot send a binary - # message with this method. - # - # === Parameters - # - # +from_addr+ is a String representing the source mail address. - # - # +to_addr+ is a String or Strings or Array of Strings, representing - # the destination mail address or addresses. - # - # === Example - # - # Net::SMTP.start('smtp.example.com', 25) do |smtp| - # smtp.open_message_stream('from@example.com', ['dest@example.com']) do |f| - # f.puts 'From: from@example.com' - # f.puts 'To: dest@example.com' - # f.puts 'Subject: test message' - # f.puts - # f.puts 'This is a test message.' - # end - # end - # - # === Errors - # - # This method may raise: - # - # * Net::SMTPServerBusy - # * Net::SMTPSyntaxError - # * Net::SMTPFatalError - # * Net::SMTPUnknownError - # * Net::ReadTimeout - # * IOError - # - def open_message_stream(from_addr, *to_addrs, &block) # :yield: stream - raise IOError, 'closed session' unless @socket - mailfrom from_addr - rcptto_list(to_addrs) {data(&block)} - end - - alias ready open_message_stream # obsolete - - # - # Authentication - # - - public - - DEFAULT_AUTH_TYPE = :plain - - def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) - check_auth_method authtype - check_auth_args user, secret - send auth_method(authtype), user, secret - end - - def auth_plain(user, secret) - check_auth_args user, secret - res = critical { - get_response('AUTH PLAIN ' + base64_encode("\0#{user}\0#{secret}")) - } - check_auth_response res - res - end - - def auth_login(user, secret) - check_auth_args user, secret - res = critical { - check_auth_continue get_response('AUTH LOGIN') - check_auth_continue get_response(base64_encode(user)) - get_response(base64_encode(secret)) - } - check_auth_response res - res - end - - def auth_cram_md5(user, secret) - check_auth_args user, secret - res = critical { - res0 = get_response('AUTH CRAM-MD5') - check_auth_continue res0 - crammed = cram_md5_response(secret, res0.cram_md5_challenge) - get_response(base64_encode("#{user} #{crammed}")) - } - check_auth_response res - res - end - - private - - def check_auth_method(type) - unless respond_to?(auth_method(type), true) - raise ArgumentError, "wrong authentication type #{type}" - end - end - - def auth_method(type) - "auth_#{type.to_s.downcase}".intern - end - - def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE) - unless user - raise ArgumentError, 'SMTP-AUTH requested but missing user name' - end - unless secret - raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase' - end - end - - def base64_encode(str) - # expects "str" may not become too long - [str].pack('m0') - end - - IMASK = 0x36 - OMASK = 0x5c - - # CRAM-MD5: [RFC2195] - def cram_md5_response(secret, challenge) - tmp = Digest::MD5.digest(cram_secret(secret, IMASK) + challenge) - Digest::MD5.hexdigest(cram_secret(secret, OMASK) + tmp) - end - - CRAM_BUFSIZE = 64 - - def cram_secret(secret, mask) - secret = Digest::MD5.digest(secret) if secret.size > CRAM_BUFSIZE - buf = secret.ljust(CRAM_BUFSIZE, "\0") - 0.upto(buf.size - 1) do |i| - buf[i] = (buf[i].ord ^ mask).chr - end - buf - end - - # - # SMTP command dispatcher - # - - public - - # Aborts the current mail transaction - - def rset - getok('RSET') - end - - def starttls - getok('STARTTLS') - end - - def helo(domain) - getok("HELO #{domain}") - end - - def ehlo(domain) - getok("EHLO #{domain}") - end - - def mailfrom(from_addr) - getok("MAIL FROM:<#{from_addr}>") - end - - def rcptto_list(to_addrs) - raise ArgumentError, 'mail destination not given' if to_addrs.empty? - ok_users = [] - unknown_users = [] - to_addrs.flatten.each do |addr| - begin - rcptto addr - rescue SMTPAuthenticationError - unknown_users << addr.dump - else - ok_users << addr - end - end - raise ArgumentError, 'mail destination not given' if ok_users.empty? - ret = yield - unless unknown_users.empty? - raise SMTPAuthenticationError, "failed to deliver for #{unknown_users.join(', ')}" - end - ret - end - - def rcptto(to_addr) - getok("RCPT TO:<#{to_addr}>") - end - - # This method sends a message. - # If +msgstr+ is given, sends it as a message. - # If block is given, yield a message writer stream. - # You must write message before the block is closed. - # - # # Example 1 (by string) - # smtp.data(</dev/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/ruby/lib/net/smtp/version.rb b/ruby/lib/net/smtp/version.rb deleted file mode 100644 index 7f5aaaa6d..000000000 --- a/ruby/lib/net/smtp/version.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Net - class Protocol; end - class SMTP < Protocol - VERSION = "0.1.0" - end -end diff --git a/ruby/lib/observer.rb b/ruby/lib/observer.rb index acfe65430..ef70e39dd 100644 --- a/ruby/lib/observer.rb +++ b/ruby/lib/observer.rb @@ -111,7 +111,32 @@ # 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 @@ -194,7 +219,7 @@ 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 + k.__send__(v, *arg) end end @observer_state = false diff --git a/ruby/lib/observer/observer.gemspec b/ruby/lib/observer/observer.gemspec index 188c6bae7..46538e881 100644 --- a/ruby/lib/observer/observer.gemspec +++ b/ruby/lib/observer/observer.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/observer/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "observer" - spec.version = Observer::VERSION + 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/lib/observer/version.rb b/ruby/lib/observer/version.rb deleted file mode 100644 index 92b509877..000000000 --- a/ruby/lib/observer/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Observer - VERSION = "0.1.0" -end diff --git a/ruby/lib/open-uri.gemspec b/ruby/lib/open-uri.gemspec new file mode 100644 index 000000000..12f10ef31 --- /dev/null +++ b/ruby/lib/open-uri.gemspec @@ -0,0 +1,25 @@ +Gem::Specification.new do |spec| + spec.name = "open-uri" + spec.version = "0.2.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP.} + spec.description = %q{An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP.} + spec.homepage = "https://github.com/ruby/open-uri" + 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 + + 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.executables = [] + spec.require_paths = ["lib"] + + spec.add_dependency "uri" + spec.add_dependency "stringio" + spec.add_dependency "time" +end diff --git a/ruby/lib/open-uri.rb b/ruby/lib/open-uri.rb index c52f67f52..e33e57a7f 100644 --- a/ruby/lib/open-uri.rb +++ b/ruby/lib/open-uri.rb @@ -3,27 +3,6 @@ require 'stringio' require 'time' -module Kernel - private - alias open_uri_original_open open # :nodoc: - class << self - alias open_uri_original_open open # :nodoc: - end - - def open(name, *rest, **kw, &block) # :nodoc: - if (name.respond_to?(:open) && !name.respond_to?(:to_path)) || - (name.respond_to?(:to_str) && - %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name && - (uri = URI.parse(name)).respond_to?(:open)) - warn('calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open', uplevel: 1) - URI.open(name, *rest, **kw, &block) - else - open_uri_original_open(name, *rest, **kw, &block) - end - end - module_function :open -end - module URI # Allows the opening of various resources including URIs. # @@ -49,9 +28,7 @@ def self.open(name, *rest, &block) (uri = URI.parse(name)).respond_to?(:open) uri.open(*rest, &block) else - open_uri_original_open(name, *rest, &block) - # After Kernel#open override is removed: - #super + super end end end @@ -744,7 +721,7 @@ def open(*rest, &block) OpenURI.open_uri(self, *rest, &block) end - # OpenURI::OpenRead#read([options]) reads a content referenced by self and + # OpenURI::OpenRead#read([ options ]) reads a content referenced by self and # returns the content as string. # The string is extended with OpenURI::Meta. # The argument +options+ is same as OpenURI::OpenRead#open. @@ -773,7 +750,12 @@ def buffer_open(buf, proxy, options) # :nodoc: OpenURI.open_http(buf, self, proxy, options) return end - require 'net/ftp' + + begin + require 'net/ftp' + rescue LoadError + abort "net/ftp is not found. You may need to `gem install net-ftp` to install net/ftp." + end path = self.path path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it. diff --git a/ruby/lib/open3.rb b/ruby/lib/open3.rb index 5e725317a..9652b2719 100644 --- a/ruby/lib/open3.rb +++ b/ruby/lib/open3.rb @@ -29,6 +29,8 @@ # - Open3.pipeline : run a pipeline and wait for its completion # +require 'open3/version' + module Open3 # Open stdin, stdout, and stderr streams and start external executable. @@ -206,6 +208,13 @@ def popen2e(*cmd, &block) opts[[:out, :err]] = out_w popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block) + ensure + if block + in_r.close + in_w.close + out_r.close + out_w.close + end end module_function :popen2e @@ -750,3 +759,6 @@ class << self end end + +# JRuby uses different popen logic on Windows, require it here to reuse wrapper methods above. +require 'open3/jruby_windows' if RUBY_ENGINE == 'jruby' && JRuby::Util::ON_WINDOWS diff --git a/ruby/lib/open3/open3.gemspec b/ruby/lib/open3/open3.gemspec index 543416e42..a33fca744 100644 --- a/ruby/lib/open3/open3.gemspec +++ b/ruby/lib/open3/open3.gemspec @@ -1,19 +1,23 @@ -begin - require_relative "lib/open3/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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('-', '/')}/version.rb")) do |line| + /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 + end rescue nil end Gem::Specification.new do |spec| - spec.name = "open3" - spec.version = Open3::VERSION + spec.name = name + spec.version = version spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{Popen, but with stderr, too} spec.description = spec.summary spec.homepage = "https://github.com/ruby/open3" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = ">= 2.6.0" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/lib/open3/version.rb b/ruby/lib/open3/version.rb index c670b79eb..5a8e84b4a 100644 --- a/ruby/lib/open3/version.rb +++ b/ruby/lib/open3/version.rb @@ -1,3 +1,3 @@ module Open3 - VERSION = "0.1.0" + VERSION = "0.1.1" end diff --git a/ruby/lib/optparse.rb b/ruby/lib/optparse.rb index 614ebc3ea..a61eff30c 100644 --- a/ruby/lib/optparse.rb +++ b/ruby/lib/optparse.rb @@ -48,6 +48,10 @@ # # == OptionParser # +# === New to \OptionParser? +# +# See the {Tutorial}[optparse/tutorial.rdoc]. +# # === Introduction # # OptionParser is a class for command-line option analysis. It is much more @@ -72,10 +76,10 @@ # require 'optparse' # # options = {} -# OptionParser.new do |opts| -# opts.banner = "Usage: example.rb [options]" +# OptionParser.new do |parser| +# parser.banner = "Usage: example.rb [options]" # -# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| +# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| # options[:verbose] = v # end # end.parse! @@ -96,15 +100,15 @@ # def self.parse(options) # args = Options.new("world") # -# opt_parser = OptionParser.new do |opts| -# opts.banner = "Usage: example.rb [options]" +# opt_parser = OptionParser.new do |parser| +# parser.banner = "Usage: example.rb [options]" # -# opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| +# parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| # args.name = n # end # -# opts.on("-h", "--help", "Prints this help") do -# puts opts +# parser.on("-h", "--help", "Prints this help") do +# puts parser # exit # end # end @@ -240,14 +244,14 @@ # # require 'optparse' # -# params = {} -# OptionParser.new do |opts| -# opts.on('-a') -# opts.on('-b NUM', Integer) -# opts.on('-v', '--verbose') -# end.parse!(into: params) +# options = {} +# OptionParser.new do |parser| +# parser.on('-a') +# parser.on('-b NUM', Integer) +# parser.on('-v', '--verbose') +# end.parse!(into: options) # -# p params +# p options # # Used: # @@ -415,10 +419,14 @@ # # === Further documentation # -# The above examples should be enough to learn how to use this class. If you -# have any questions, file a ticket at http://bugs.ruby-lang.org. +# The above examples, along with the accompanying +# {Tutorial}[optparse/tutorial.rdoc], +# should be enough to learn how to use this class. +# If you have any questions, file a ticket at http://bugs.ruby-lang.org. # class OptionParser + OptionParser::Version = "0.2.0" + # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze @@ -545,7 +553,7 @@ def initialize(pattern = nil, conv = nil, # Parses +arg+ and returns rest of +arg+ and matched portion to the # argument pattern. Yields when the pattern doesn't match substring. # - def parse_arg(arg) + def parse_arg(arg) # :nodoc: pattern or return nil, [arg] unless m = pattern.match(arg) yield(InvalidArgument, arg) @@ -570,7 +578,7 @@ def parse_arg(arg) # conversion. Yields at semi-error condition instead of raising an # exception. # - def conv_arg(arg, val = []) + def conv_arg(arg, val = []) # :nodoc: if conv val = conv.call(*val) else @@ -804,7 +812,7 @@ def reject(t) # +lopts+:: Long style option list. # +nlopts+:: Negated long style options list. # - def update(sw, sopts, lopts, nsw = nil, nlopts = nil) + def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc: sopts.each {|o| @short[o] = sw} if sopts lopts.each {|o| @long[o] = sw} if lopts nlopts.each {|o| @long[o] = nsw} if nsw and nlopts @@ -1089,6 +1097,7 @@ def initialize(banner = nil, width = 32, indent = ' ' * 4) @summary_width = width @summary_indent = indent @default_argv = ARGV + @require_exact = false add_officious yield self if block_given? end @@ -1162,6 +1171,10 @@ def self.reject(*args, &blk) top.reject(*args, &blk) end # Strings to be parsed in default. attr_accessor :default_argv + # Whether to require that options match exactly (disallows providing + # abbreviated long option as short option). + attr_accessor :require_exact + # # Heading banner preceding summary. # @@ -1293,7 +1306,7 @@ def to_a; summarize("#{banner}".split(/^/)) end # +prv+:: Previously specified argument. # +msg+:: Exception message. # - def notwice(obj, prv, msg) + def notwice(obj, prv, msg) # :nodoc: unless !prv or prv == obj raise(ArgumentError, "argument #{msg} given twice: #{obj}", ParseError.filter_backtrace(caller(2))) @@ -1303,65 +1316,11 @@ def notwice(obj, prv, msg) private :notwice SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc: + + # :call-seq: + # make_switch(params, block = nil) # - # Creates an OptionParser::Switch from the parameters. The parsed argument - # value is passed to the given block, where it can be processed. - # - # See at the beginning of OptionParser for some full examples. - # - # +opts+ can include the following elements: - # - # [Argument style:] - # One of the following: - # :NONE, :REQUIRED, :OPTIONAL - # - # [Argument pattern:] - # Acceptable option argument format, must be pre-defined with - # OptionParser.accept or OptionParser#accept, or Regexp. This can appear - # once or assigned as String if not present, otherwise causes an - # ArgumentError. Examples: - # Float, Time, Array - # - # [Possible argument values:] - # Hash or Array. - # [:text, :binary, :auto] - # %w[iso-2022-jp shift_jis euc-jp utf8 binary] - # { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } - # - # [Long style switch:] - # Specifies a long style switch which takes a mandatory, optional or no - # argument. It's a string of the following form: - # "--switch=MANDATORY" or "--switch MANDATORY" - # "--switch[=OPTIONAL]" - # "--switch" - # - # [Short style switch:] - # Specifies short style switch which takes a mandatory, optional or no - # argument. It's a string of the following form: - # "-xMANDATORY" - # "-x[OPTIONAL]" - # "-x" - # There is also a special form which matches character range (not full - # set of regular expression): - # "-[a-z]MANDATORY" - # "-[a-z][OPTIONAL]" - # "-[a-z]" - # - # [Argument style and description:] - # Instead of specifying mandatory or optional arguments directly in the - # switch parameter, this separate parameter can be used. - # "=MANDATORY" - # "=[OPTIONAL]" - # - # [Description:] - # Description string for the option. - # "Run verbosely" - # If you give multiple description strings, each string will be printed - # line by line. - # - # [Handler:] - # Handler for the parsed argument value. Either give a block or pass a - # Proc or Method as an argument. + # :include: ../doc/optparse/creates_option.rdoc # def make_switch(opts, block = nil) short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], [] @@ -1496,14 +1455,20 @@ def make_switch(opts, block = nil) nolong end + # :call-seq: + # define(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # def define(*opts, &block) top.append(*(sw = make_switch(opts, block))) sw[0] end + # :call-seq: + # on(*params, &block) # - # Add option switch and handler. See #make_switch for an explanation of - # parameters. + # :include: ../doc/optparse/creates_option.rdoc # def on(*opts, &block) define(*opts, &block) @@ -1511,13 +1476,22 @@ def on(*opts, &block) end alias def_option define + # :call-seq: + # define_head(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # def define_head(*opts, &block) top.prepend(*(sw = make_switch(opts, block))) sw[0] end + # :call-seq: + # on_head(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc # - # Add option switch like with #on, but at head of summary. + # The new option is added at the head of the summary. # def on_head(*opts, &block) define_head(*opts, &block) @@ -1525,13 +1499,23 @@ def on_head(*opts, &block) end alias def_head_option define_head + # :call-seq: + # define_tail(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # def define_tail(*opts, &block) base.append(*(sw = make_switch(opts, block))) sw[0] end # - # Add option switch like with #on, but at tail of summary. + # :call-seq: + # on_tail(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + # The new option is added at the tail of the summary. # def on_tail(*opts, &block) define_tail(*opts, &block) @@ -1581,6 +1565,9 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: opt.tr!('_', '-') begin sw, = complete(:long, opt, true) + if require_exact && !sw.long.include?(arg) + raise InvalidOption, arg + end rescue ParseError raise $!.set_option(arg, true) end @@ -1605,6 +1592,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 # if no short options match, try completion with long # options. sw, = complete(:long, opt) @@ -1616,7 +1604,12 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: end begin opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq} + rescue ParseError + raise $!.set_option(arg, arg.length > 2) + else raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}" + 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 @@ -1745,9 +1738,9 @@ def self.getopts(*args) # Traverses @stack, sending each element method +id+ with +args+ and # +block+. # - def visit(id, *args, &block) + def visit(id, *args, &block) # :nodoc: @stack.reverse_each do |el| - el.send(id, *args, &block) + el.__send__(id, *args, &block) end nil end @@ -1756,7 +1749,7 @@ def visit(id, *args, &block) # # Searches +key+ in @stack for +id+ hash and returns or yields the result. # - def search(id, key) + def search(id, key) # :nodoc: block_given = block_given? visit(:search, id, key) do |k| return block_given ? yield(k) : k @@ -1773,7 +1766,7 @@ def search(id, key) # +icase+:: Search case insensitive if true. # +pat+:: Optional pattern for completion. # - def complete(typ, opt, icase = false, *pat) + def complete(typ, opt, icase = false, *pat) # :nodoc: if pat.empty? search(typ, opt) {|sw| return [sw, opt]} # exact match or... end diff --git a/ruby/lib/optparse/kwargs.rb b/ruby/lib/optparse/kwargs.rb index ed58cc142..ccf20c65e 100644 --- a/ruby/lib/optparse/kwargs.rb +++ b/ruby/lib/optparse/kwargs.rb @@ -2,6 +2,11 @@ require 'optparse' class OptionParser + # :call-seq: + # define_by_keywords(options, method, **params) + # + # :include: ../../doc/optparse/creates_option.rdoc + # def define_by_keywords(options, meth, **opts) meth.parameters.each do |type, name| case type diff --git a/ruby/lib/optparse/optparse.gemspec b/ruby/lib/optparse/optparse.gemspec new file mode 100644 index 000000000..ae6596678 --- /dev/null +++ b/ruby/lib/optparse/optparse.gemspec @@ -0,0 +1,29 @@ +# 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*OptionParser::Version\s*=\s*"(.*)"/ =~ line and break $1 + end rescue nil +end + +Gem::Specification.new do |spec| + spec.name = name + spec.version = version + spec.authors = ["Nobu Nakada"] + 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.homepage = "https://github.com/ruby/optparse" + spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") + spec.licenses = ["Ruby", "BSD-2-Clause"] + + 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.bindir = "exe" + spec.executables = [] + spec.require_paths = ["lib"] +end diff --git a/ruby/lib/ostruct.rb b/ruby/lib/ostruct.rb index c40c897ff..4dccfc4c6 100644 --- a/ruby/lib/ostruct.rb +++ b/ruby/lib/ostruct.rb @@ -36,9 +36,10 @@ # 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. +# 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) @@ -61,8 +62,9 @@ # first_pet # => # # first_pet == second_pet # => true # +# Ractor compatibility: A frozen OpenStruct with shareable values is itself shareable. # -# == Implementation +# == Caveats # # An OpenStruct utilizes Ruby's method lookup structure to find and define the # necessary methods for properties. This is accomplished through the methods @@ -71,11 +73,41 @@ # 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. # - -require_relative 'ostruct/version' - class OpenStruct + VERSION = "0.5.2" # # Creates a new OpenStruct object. By default, the resulting OpenStruct @@ -92,19 +124,29 @@ class OpenStruct # data # => # # def initialize(hash=nil) - @table = {} if hash - hash.each_pair do |k, v| - k = k.to_sym - @table[k] = v - end + update_to_values!(hash) + else + @table = {} end end # Duplicates an OpenStruct object's Hash table. - def initialize_copy(orig) # :nodoc: + 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 - @table = @table.dup + 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 # @@ -124,11 +166,21 @@ def initialize_copy(orig) # :nodoc: # data.to_h {|name, value| [name.to_s, value.upcase] } # # => {"country" => "AUSTRALIA", "capital" => "CANBERRA" } # - def to_h(&block) - if block_given? - @table.to_h(&block) - else - @table.dup + 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 @@ -145,7 +197,7 @@ def to_h(&block) # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]] # def each_pair - return to_enum(__method__) { @table.size } unless block_given? + return to_enum(__method__) { @table.size } unless block_given! @table.each_pair{|p| yield p} self end @@ -153,31 +205,14 @@ def each_pair # # Provides marshalling support for use by the Marshal library. # - def marshal_dump + def marshal_dump # :nodoc: @table end # # Provides marshalling support for use by the Marshal library. # - def marshal_load(x) - @table = x - end - - # - # Used internally to check if the OpenStruct is able to be - # modified before granting access to the internal Hash table to be modified. - # - def modifiable? # :nodoc: - begin - @modifiable = true - rescue - exception_class = defined?(FrozenError) ? FrozenError : RuntimeError - raise exception_class, "can't modify frozen #{self.class}", caller(3) - end - @table - end - private :modifiable? + alias_method :marshal_load, :update_to_values! # :nodoc: # # Used internally to defined properties on the @@ -185,45 +220,60 @@ def modifiable? # :nodoc: # define_singleton_method for both the getter method and the setter method. # def new_ostruct_member!(name) # :nodoc: - name = name.to_sym - unless singleton_class.method_defined?(name) - define_singleton_method(name) { @table[name] } - define_singleton_method("#{name}=") {|x| modifiable?[name] = x} + 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 - name end private :new_ostruct_member! - def freeze - @table.each_key {|key| new_ostruct_member!(key)} - super + 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 respond_to_missing?(mid, include_private = false) # :nodoc: - mname = mid.to_s.chomp("=").to_sym - defined?(@table) && @table.key?(mname) || super + def freeze + @table.freeze + super end - def method_missing(mid, *args) # :nodoc: + 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 - modifiable?[new_ostruct_member!(mname)] = args[0] - elsif len == 0 # and /\A[a-z_]\w*\z/ =~ mid # - if @table.key?(mid) - new_ostruct_member!(mid) unless frozen? - @table[mid] + raise! ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1) end - elsif @table.key?(mid) - raise ArgumentError, "wrong number of arguments (given #{len}, expected 0)" + set_ostruct_member_value!(mname, args[0]) + elsif len == 0 + @table[mid] else begin super rescue NoMethodError => err err.backtrace.shift - raise + raise! end end end @@ -232,7 +282,7 @@ def method_missing(mid, *args) # :nodoc: # :call-seq: # ostruct[name] -> object # - # Returns the value of an attribute. + # Returns the value of an attribute, or +nil+ if there is no such attribute. # # require "ostruct" # person = OpenStruct.new("name" => "John Smith", "age" => 70) @@ -254,47 +304,47 @@ def [](name) # person.age # => 42 # def []=(name, value) - modifiable?[new_ostruct_member!(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, ...) -> object + # ostruct.dig(name, *identifiers) -> object # - # Extracts the nested value specified by the sequence of +name+ - # objects by calling +dig+ at each step, returning +nil+ if any - # intermediate step is +nil+. + # 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 - # - # data = OpenStruct.new(:array => [1, [2, 3]]) - # - # data.dig(:array, 1, 0) # => 2 - # data.dig(:array, 0, 0) # TypeError: Integer does not have #dig method - # + # 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" + raise! TypeError, "#{name} is not a symbol nor a string" end @table.dig(name, *names) end # - # Removes the named field from the object. Returns the value that the field - # contained if it was defined. + # 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.delete_field!("age") # => 70 # person # => # # # Setting the value to +nil+ will not remove the attribute: @@ -302,6 +352,10 @@ def dig(name, *names) # person.pension = nil # person # => # # + # person.delete_field('number') # => NameError + # + # person.delete_field('number') { 8675_309 } # => 8675309 + # def delete_field(name) sym = name.to_sym begin @@ -309,7 +363,8 @@ def delete_field(name) rescue NameError end @table.delete(sym) do - raise NameError.new("no field `#{sym}' in #{self}", sym) + return yield if block_given! + raise! NameError.new("no field `#{sym}' in #{self}", sym) end end @@ -332,13 +387,13 @@ def inspect ids.pop end end - ['#<', self.class, detail, '>'].join + ['#<', self.class!, detail, '>'].join end alias :to_s :inspect attr_reader :table # :nodoc: - protected :table alias table! table + protected :table! # # Compares this object and +other+ for equality. An OpenStruct is equal to @@ -369,11 +424,49 @@ def eql?(other) end # Computes a hash code for this OpenStruct. - # Two OpenStruct objects with the same content will have the same hash code - # (and will compare using #eql?). - # - # See also Object#hash. - def hash + 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 + alias_method :block_given!, :block_given? + private :raise!, :block_given! end diff --git a/ruby/lib/ostruct/ostruct.gemspec b/ruby/lib/ostruct/ostruct.gemspec index 4f8507045..f69a858aa 100644 --- a/ruby/lib/ostruct/ostruct.gemspec +++ b/ruby/lib/ostruct/ostruct.gemspec @@ -1,24 +1,25 @@ # frozen_string_literal: true -begin - require_relative "lib/ostruct/version" -rescue LoadError - # for Ruby core repository - require_relative "version" +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 = "ostruct" - spec.version = OpenStruct::VERSION + 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = ">= 2.5.0" - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "lib/ostruct/version.rb", "ostruct.gemspec"] + spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"] spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] diff --git a/ruby/lib/ostruct/version.rb b/ruby/lib/ostruct/version.rb deleted file mode 100644 index 91a404409..000000000 --- a/ruby/lib/ostruct/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class OpenStruct - VERSION = "0.2.0" -end diff --git a/ruby/lib/pp.gemspec b/ruby/lib/pp.gemspec new file mode 100644 index 000000000..d4b0be83d --- /dev/null +++ b/ruby/lib/pp.gemspec @@ -0,0 +1,27 @@ +Gem::Specification.new do |spec| + spec.name = "pp" + spec.version = "0.3.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Provides a PrettyPrinter for Ruby objects} + spec.description = %q{Provides a PrettyPrinter for Ruby objects} + spec.homepage = "https://github.com/ruby/pp" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0") + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + + spec.files = %w[ + LICENSE.txt + lib/pp.rb + pp.gemspec + ] + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] + + spec.add_dependency "prettyprint" +end diff --git a/ruby/lib/pp.rb b/ruby/lib/pp.rb index 012b328aa..f43356a3d 100644 --- a/ruby/lib/pp.rb +++ b/ruby/lib/pp.rb @@ -61,14 +61,34 @@ # Tanaka Akira class PP < PrettyPrint + # Returns the usable width for +out+. + # As the width of +out+: + # 1. If +out+ is assigned to a tty device, its width is used. + # 2. Otherwise, or it could not get the value, the +COLUMN+ + # environment variable is assumed to be set to the width. + # 3. If +COLUMN+ is not set to a non-zero number, 80 is assumed. + # + # And finally, returns the above width value - 1. + # * This -1 is for Windows command prompt, which moves the cursor to + # the next line if it reaches the last column. + def PP.width_for(out) + begin + require 'io/console' + _, width = out.winsize + rescue LoadError, NoMethodError, SystemCallError + end + (width || ENV['COLUMNS']&.to_i&.nonzero? || 80) - 1 + end + # Outputs +obj+ to +out+ in pretty printed format of # +width+ columns in width. # # If +out+ is omitted, $> is assumed. - # If +width+ is omitted, 79 is assumed. + # If +width+ is omitted, the width of +out+ is assumed (see + # width_for). # # PP.pp returns +out+. - def PP.pp(obj, out=$>, width=79) + def PP.pp(obj, out=$>, width=width_for(out)) q = PP.new(out, width) q.guard_inspect_key {q.pp obj} q.flush @@ -93,11 +113,25 @@ def PP.mcall(obj, mod, meth, *args, &block) end # :startdoc: - @sharing_detection = false - class << self - # Returns the sharing detection flag as a boolean value. - # It is false by default. - attr_accessor :sharing_detection + if defined? ::Ractor + class << self + # Returns the sharing detection flag as a boolean value. + # It is false (nil) by default. + def sharing_detection + Ractor.current[:pp_sharing_detection] + end + # Sets the sharing detection flag to b. + def sharing_detection=(b) + Ractor.current[:pp_sharing_detection] = b + end + end + else + @sharing_detection = false + class << self + # Returns the sharing detection flag as a boolean value. + # It is false by default. + attr_accessor :sharing_detection + end end module PPMethods @@ -223,16 +257,7 @@ def seplist(list, sep=nil, iter_method=:each) # :yield: element else sep.call end - case v.last - when Hash - if Hash.ruby2_keywords_hash?(v.last) - yield(*v, **{}) - else - yield(*v) - end - else - yield(*v) - end + RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v) } end @@ -419,7 +444,7 @@ def pretty_print(q) # :nodoc: class File < IO # :nodoc: class Stat # :nodoc: def pretty_print(q) # :nodoc: - require 'etc.so' + require 'etc' q.object_group(self) { q.breakable q.text sprintf("dev=0x%x", self.dev); q.comma_breakable @@ -525,37 +550,39 @@ def pretty_print(q) # :nodoc: end end -class RubyVM::AbstractSyntaxTree::Node - def pretty_print_children(q, names = []) - children.zip(names) do |c, n| - if n - q.breakable - q.text "#{n}:" - end - q.group(2) do - q.breakable - q.pp c +if defined?(RubyVM::AbstractSyntaxTree) + class RubyVM::AbstractSyntaxTree::Node + def pretty_print_children(q, names = []) + children.zip(names) do |c, n| + if n + q.breakable + q.text "#{n}:" + end + q.group(2) do + q.breakable + q.pp c + end end end - end - def pretty_print(q) - q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") { - case type - when :SCOPE - pretty_print_children(q, %w"tbl args body") - when :ARGS - pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block]) - when :DEFN - pretty_print_children(q, %w[mid body]) - when :ARYPTN - pretty_print_children(q, %w[const pre rest post]) - when :HSHPTN - pretty_print_children(q, %w[const kw kwrest]) - else - pretty_print_children(q) - end - } + def pretty_print(q) + q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") { + case type + when :SCOPE + pretty_print_children(q, %w"tbl args body") + when :ARGS + pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block]) + when :DEFN + pretty_print_children(q, %w[mid body]) + when :ARYPTN + pretty_print_children(q, %w[const pre rest post]) + when :HSHPTN + pretty_print_children(q, %w[const kw kwrest]) + else + pretty_print_children(q) + end + } + end end end diff --git a/ruby/lib/prettyprint.gemspec b/ruby/lib/prettyprint.gemspec new file mode 100644 index 000000000..eae2227d6 --- /dev/null +++ b/ruby/lib/prettyprint.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "prettyprint" + spec.version = "0.1.1" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Implements a pretty printing algorithm for readable structure.} + spec.description = %q{Implements a pretty printing algorithm for readable structure.} + spec.homepage = "https://github.com/ruby/prettyprint" + 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 + + 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/ruby/lib/prettyprint.rb b/ruby/lib/prettyprint.rb index 2a3ca90dc..188c2e6db 100644 --- a/ruby/lib/prettyprint.rb +++ b/ruby/lib/prettyprint.rb @@ -102,7 +102,7 @@ def initialize(output=''.dup, maxwidth=79, newline="\n", &genspace) # The maximum width of a line, before it is separated in to a newline # - # This defaults to 79, and should be a Fixnum + # This defaults to 79, and should be an Integer attr_reader :maxwidth # The value that is appended to +output+ to add a new line. @@ -110,7 +110,7 @@ def initialize(output=''.dup, maxwidth=79, newline="\n", &genspace) # This defaults to "\n", and should be String attr_reader :newline - # A lambda or Proc, that takes one argument, of a Fixnum, and returns + # A lambda or Proc, that takes one argument, of an Integer, and returns # the corresponding number of spaces. # # By default this is: @@ -340,7 +340,7 @@ class Breakable # :nodoc: # # Arguments: # * +sep+ String of the separator - # * +width+ Fixnum width of the +sep+ + # * +width+ Integer width of the +sep+ # * +q+ parent PrettyPrint object, to base from def initialize(sep, width, q) @obj = sep diff --git a/ruby/lib/prime.gemspec b/ruby/lib/prime.gemspec deleted file mode 100644 index 6a9aa683e..000000000 --- a/ruby/lib/prime.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -begin - require_relative "lib/prime" -rescue LoadError - # for Ruby core repository - require_relative "prime" -end - -Gem::Specification.new do |spec| - spec.name = "prime" - spec.version = Prime::VERSION - spec.authors = ["Yuki Sonoda"] - spec.email = ["yugui@yugui.jp"] - - spec.summary = %q{Prime numbers and factorization library.} - spec.description = %q{Prime numbers and factorization library.} - spec.homepage = "https://github.com/ruby/prime" - spec.license = "BSD-2-Clause" - - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/prime.rb", "lib/prime/version.rb", "prime.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "test-unit" -end diff --git a/ruby/lib/prime.rb b/ruby/lib/prime.rb deleted file mode 100644 index 5be12f24f..000000000 --- a/ruby/lib/prime.rb +++ /dev/null @@ -1,463 +0,0 @@ -# frozen_string_literal: false -# -# = prime.rb -# -# Prime numbers and factorization library. -# -# Copyright:: -# Copyright (c) 1998-2008 Keiju ISHITSUKA(SHL Japan Inc.) -# Copyright (c) 2008 Yuki Sonoda (Yugui) -# -# Documentation:: -# Yuki Sonoda -# - -require "singleton" -require "forwardable" - -class Integer - # Re-composes a prime factorization and returns the product. - # - # See Prime#int_from_prime_division for more details. - def Integer.from_prime_division(pd) - Prime.int_from_prime_division(pd) - end - - # Returns the factorization of +self+. - # - # See Prime#prime_division for more details. - def prime_division(generator = Prime::Generator23.new) - Prime.prime_division(self, generator) - end - - # Returns true if +self+ is a prime number, else returns false. - def prime? - return self >= 2 if self <= 3 - return true if self == 5 - return false unless 30.gcd(self) == 1 - (7..Integer.sqrt(self)).step(30) do |p| - return false if - self%(p) == 0 || self%(p+4) == 0 || self%(p+6) == 0 || self%(p+10) == 0 || - self%(p+12) == 0 || self%(p+16) == 0 || self%(p+22) == 0 || self%(p+24) == 0 - end - true - end - - # Iterates the given block over all prime numbers. - # - # See +Prime+#each for more details. - def Integer.each_prime(ubound, &block) # :yields: prime - Prime.each(ubound, &block) - end -end - -# -# The set of all prime numbers. -# -# == Example -# -# Prime.each(100) do |prime| -# p prime #=> 2, 3, 5, 7, 11, ...., 97 -# end -# -# Prime is Enumerable: -# -# Prime.first 5 # => [2, 3, 5, 7, 11] -# -# == Retrieving the instance -# -# For convenience, each instance method of +Prime+.instance can be accessed -# as a class method of +Prime+. -# -# e.g. -# Prime.instance.prime?(2) #=> true -# Prime.prime?(2) #=> true -# -# == Generators -# -# A "generator" provides an implementation of enumerating pseudo-prime -# numbers and it remembers the position of enumeration and upper bound. -# Furthermore, it is an external iterator of prime enumeration which is -# compatible with an Enumerator. -# -# +Prime+::+PseudoPrimeGenerator+ is the base class for generators. -# There are few implementations of generator. -# -# [+Prime+::+EratosthenesGenerator+] -# Uses eratosthenes' sieve. -# [+Prime+::+TrialDivisionGenerator+] -# Uses the trial division method. -# [+Prime+::+Generator23+] -# Generates all positive integers which are not divisible by either 2 or 3. -# This sequence is very bad as a pseudo-prime sequence. But this -# is faster and uses much less memory than the other generators. So, -# it is suitable for factorizing an integer which is not large but -# has many prime factors. e.g. for Prime#prime? . - -class Prime - - VERSION = "0.1.1" - - include Enumerable - include Singleton - - class << self - extend Forwardable - include Enumerable - - def method_added(method) # :nodoc: - (class<< self;self;end).def_delegator :instance, method - end - end - - # Iterates the given block over all prime numbers. - # - # == Parameters - # - # +ubound+:: - # Optional. An arbitrary positive number. - # The upper bound of enumeration. The method enumerates - # prime numbers infinitely if +ubound+ is nil. - # +generator+:: - # Optional. An implementation of pseudo-prime generator. - # - # == Return value - # - # An evaluated value of the given block at the last time. - # Or an enumerator which is compatible to an +Enumerator+ - # if no block given. - # - # == Description - # - # Calls +block+ once for each prime number, passing the prime as - # a parameter. - # - # +ubound+:: - # Upper bound of prime numbers. The iterator stops after it - # yields all prime numbers p <= +ubound+. - # - def each(ubound = nil, generator = EratosthenesGenerator.new, &block) - generator.upper_bound = ubound - generator.each(&block) - end - - - # Returns true if +value+ is a prime number, else returns false. - # - # == Parameters - # - # +value+:: an arbitrary integer to be checked. - # +generator+:: optional. A pseudo-prime generator. - def prime?(value, generator = Prime::Generator23.new) - raise ArgumentError, "Expected a prime generator, got #{generator}" unless generator.respond_to? :each - raise ArgumentError, "Expected an integer, got #{value}" unless value.respond_to?(:integer?) && value.integer? - return false if value < 2 - generator.each do |num| - q,r = value.divmod num - return true if q < num - return false if r == 0 - end - end - - # Re-composes a prime factorization and returns the product. - # - # == Parameters - # +pd+:: Array of pairs of integers. The each internal - # pair consists of a prime number -- a prime factor -- - # and a natural number -- an exponent. - # - # == Example - # For [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]], it returns: - # - # p_1**e_1 * p_2**e_2 * .... * p_n**e_n. - # - # Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12 - def int_from_prime_division(pd) - pd.inject(1){|value, (prime, index)| - value * prime**index - } - end - - # Returns the factorization of +value+. - # - # == Parameters - # +value+:: An arbitrary integer. - # +generator+:: Optional. A pseudo-prime generator. - # +generator+.succ must return the next - # pseudo-prime number in the ascending - # order. It must generate all prime numbers, - # but may also generate non prime numbers too. - # - # === Exceptions - # +ZeroDivisionError+:: when +value+ is zero. - # - # == Example - # For an arbitrary integer: - # - # n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n, - # - # prime_division(n) returns: - # - # [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]. - # - # Prime.prime_division(12) #=> [[2,2], [3,1]] - # - def prime_division(value, generator = Prime::Generator23.new) - raise ZeroDivisionError if value == 0 - if value < 0 - value = -value - pv = [[-1, 1]] - else - pv = [] - end - generator.each do |prime| - count = 0 - while (value1, mod = value.divmod(prime) - mod) == 0 - value = value1 - count += 1 - end - if count != 0 - pv.push [prime, count] - end - break if value1 <= prime - end - if value > 1 - pv.push [value, 1] - end - pv - end - - # An abstract class for enumerating pseudo-prime numbers. - # - # Concrete subclasses should override succ, next, rewind. - class PseudoPrimeGenerator - include Enumerable - - def initialize(ubound = nil) - @ubound = ubound - end - - def upper_bound=(ubound) - @ubound = ubound - end - def upper_bound - @ubound - end - - # returns the next pseudo-prime number, and move the internal - # position forward. - # - # +PseudoPrimeGenerator+#succ raises +NotImplementedError+. - def succ - raise NotImplementedError, "need to define `succ'" - end - - # alias of +succ+. - def next - raise NotImplementedError, "need to define `next'" - end - - # Rewinds the internal position for enumeration. - # - # See +Enumerator+#rewind. - def rewind - raise NotImplementedError, "need to define `rewind'" - end - - # Iterates the given block for each prime number. - def each - return self.dup unless block_given? - if @ubound - last_value = nil - loop do - prime = succ - break last_value if prime > @ubound - last_value = yield prime - end - else - loop do - yield succ - end - end - end - - # see +Enumerator+#with_index. - def with_index(offset = 0, &block) - return enum_for(:with_index, offset) { Float::INFINITY } unless block - return each_with_index(&block) if offset == 0 - - each do |prime| - yield prime, offset - offset += 1 - end - end - - # see +Enumerator+#with_object. - def with_object(obj) - return enum_for(:with_object, obj) { Float::INFINITY } unless block_given? - each do |prime| - yield prime, obj - end - end - - def size - Float::INFINITY - end - end - - # An implementation of +PseudoPrimeGenerator+. - # - # Uses +EratosthenesSieve+. - class EratosthenesGenerator < PseudoPrimeGenerator - def initialize - @last_prime_index = -1 - super - end - - def succ - @last_prime_index += 1 - EratosthenesSieve.instance.get_nth_prime(@last_prime_index) - end - def rewind - initialize - end - alias next succ - end - - # An implementation of +PseudoPrimeGenerator+ which uses - # a prime table generated by trial division. - class TrialDivisionGenerator < PseudoPrimeGenerator - def initialize - @index = -1 - super - end - - def succ - TrialDivision.instance[@index += 1] - end - def rewind - initialize - end - alias next succ - end - - # Generates all integers which are greater than 2 and - # are not divisible by either 2 or 3. - # - # This is a pseudo-prime generator, suitable on - # checking primality of an integer by brute force - # method. - class Generator23 < PseudoPrimeGenerator - def initialize - @prime = 1 - @step = nil - super - end - - def succ - if (@step) - @prime += @step - @step = 6 - @step - else - case @prime - when 1; @prime = 2 - when 2; @prime = 3 - when 3; @prime = 5; @step = 2 - end - end - @prime - end - alias next succ - def rewind - initialize - end - end - - # Internal use. An implementation of prime table by trial division method. - class TrialDivision - include Singleton - - def initialize # :nodoc: - # These are included as class variables to cache them for later uses. If memory - # usage is a problem, they can be put in Prime#initialize as instance variables. - - # There must be no primes between @primes[-1] and @next_to_check. - @primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101] - # @next_to_check % 6 must be 1. - @next_to_check = 103 # @primes[-1] - @primes[-1] % 6 + 7 - @ulticheck_index = 3 # @primes.index(@primes.reverse.find {|n| - # n < Math.sqrt(@@next_to_check) }) - @ulticheck_next_squared = 121 # @primes[@ulticheck_index + 1] ** 2 - end - - # Returns the +index+th prime number. - # - # +index+ is a 0-based index. - def [](index) - while index >= @primes.length - # Only check for prime factors up to the square root of the potential primes, - # but without the performance hit of an actual square root calculation. - if @next_to_check + 4 > @ulticheck_next_squared - @ulticheck_index += 1 - @ulticheck_next_squared = @primes.at(@ulticheck_index + 1) ** 2 - end - # Only check numbers congruent to one and five, modulo six. All others - - # are divisible by two or three. This also allows us to skip checking against - # two and three. - @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil? - @next_to_check += 4 - @primes.push @next_to_check if @primes[2..@ulticheck_index].find {|prime| @next_to_check % prime == 0 }.nil? - @next_to_check += 2 - end - @primes[index] - end - end - - # Internal use. An implementation of Eratosthenes' sieve - class EratosthenesSieve - include Singleton - - def initialize - @primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101] - # @max_checked must be an even number - @max_checked = @primes.last + 1 - end - - def get_nth_prime(n) - compute_primes while @primes.size <= n - @primes[n] - end - - private - def compute_primes - # max_segment_size must be an even number - max_segment_size = 1e6.to_i - max_cached_prime = @primes.last - # do not double count primes if #compute_primes is interrupted - # by Timeout.timeout - @max_checked = max_cached_prime + 1 if max_cached_prime > @max_checked - - segment_min = @max_checked - segment_max = [segment_min + max_segment_size, max_cached_prime * 2].min - root = Integer.sqrt(segment_max) - - segment = ((segment_min + 1) .. segment_max).step(2).to_a - - (1..Float::INFINITY).each do |sieving| - prime = @primes[sieving] - break if prime > root - composite_index = (-(segment_min + 1 + prime) / 2) % prime - while composite_index < segment.size do - segment[composite_index] = nil - composite_index += prime - end - end - - @primes.concat(segment.compact!) - - @max_checked = segment_max - end - end -end diff --git a/ruby/lib/pstore.rb b/ruby/lib/pstore.rb index 1180fd50a..a46bcb84b 100644 --- a/ruby/lib/pstore.rb +++ b/ruby/lib/pstore.rb @@ -92,6 +92,8 @@ # Needless to say, if you're storing valuable data with PStore, then you should # backup the PStore files from time to time. class PStore + VERSION = "0.1.1" + 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 diff --git a/ruby/lib/pstore/pstore.gemspec b/ruby/lib/pstore/pstore.gemspec index e781c7704..8425795af 100644 --- a/ruby/lib/pstore/pstore.gemspec +++ b/ruby/lib/pstore/pstore.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/pstore/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "pstore" - spec.version = PStore::VERSION + 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.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/ruby/pstore" diff --git a/ruby/lib/pstore/version.rb b/ruby/lib/pstore/version.rb deleted file mode 100644 index 0e7a3fbd1..000000000 --- a/ruby/lib/pstore/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class PStore - VERSION = "0.1.0" -end diff --git a/ruby/lib/racc/compat.rb b/ruby/lib/racc/compat.rb index ccb033e2e..62f4f630b 100644 --- a/ruby/lib/racc/compat.rb +++ b/ruby/lib/racc/compat.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 14fa1118eb3a23e85265e4f7afe2d5a297d69f9c $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ unless Object.method_defined?(:__send) class Object diff --git a/ruby/lib/racc/debugflags.rb b/ruby/lib/racc/debugflags.rb index 1b5d2fe54..ee34cf231 100644 --- a/ruby/lib/racc/debugflags.rb +++ b/ruby/lib/racc/debugflags.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 74ff4369ce53c7f45cfc2644ce907785104ebf6e $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ module Racc diff --git a/ruby/lib/racc/exception.rb b/ruby/lib/racc/exception.rb index 0069ca344..c11dc2e43 100644 --- a/ruby/lib/racc/exception.rb +++ b/ruby/lib/racc/exception.rb @@ -1,11 +1,14 @@ +#-- +# # -# $Id: ebb9798ad0b211e031670a12a1ab154678c1c8f3 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # see the file "COPYING". +# +#++ module Racc class Error < StandardError; end diff --git a/ruby/lib/racc/grammar.rb b/ruby/lib/racc/grammar.rb index 123f1f183..01c4c3df6 100644 --- a/ruby/lib/racc/grammar.rb +++ b/ruby/lib/racc/grammar.rb @@ -1,11 +1,14 @@ +#-- +# # -# $Id: 3fcabd58bef02540bf78e8142469681cb9f975c2 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # see the file "COPYING". +# +#++ require 'racc/compat' require 'racc/iset' @@ -83,14 +86,15 @@ def useless_nonterminal_exist? end def n_useless_nonterminals - @n_useless_nonterminals ||= - begin - n = 0 - @symboltable.each_nonterminal do |sym| - n += 1 if sym.useless? - end - n - end + @n_useless_nonterminals ||= each_useless_nonterminal.count + end + + def each_useless_nonterminal + return to_enum __method__ unless block_given? + + @symboltable.each_nonterminal do |sym| + yield sym if sym.useless? + end end def useless_rule_exist? @@ -98,14 +102,15 @@ def useless_rule_exist? end def n_useless_rules - @n_useless_rules ||= - begin - n = 0 - each do |r| - n += 1 if r.useless? - end - n - end + @n_useless_rules ||= each_useless_rule.count + end + + def each_useless_rule + return to_enum __method__ unless block_given? + + each do |r| + yield r if r.useless? + end end def nfa @@ -330,14 +335,14 @@ def _defmetasyntax(type, id, action, &block) if action idbase = "#{type}@#{id}-#{@seqs[type] += 1}" target = _wrap(idbase, "#{idbase}-core", action) - _regist("#{idbase}-core", &block) + _register("#{idbase}-core", &block) else - target = _regist("#{type}@#{id}", &block) + target = _register("#{type}@#{id}", &block) end @grammar.intern(target) end - def _regist(target_name) + def _register(target_name) target = target_name.intern unless _added?(@grammar.intern(target)) yield(target).each_rule do |rule| diff --git a/ruby/lib/racc/grammarfileparser.rb b/ruby/lib/racc/grammarfileparser.rb index 5e7081f00..c7d1207f0 100644 --- a/ruby/lib/racc/grammarfileparser.rb +++ b/ruby/lib/racc/grammarfileparser.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 63bd084db2dce8a2c9760318faae6104717cead7 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ require 'racc' require 'racc/compat' @@ -259,9 +260,9 @@ def parse_user_code _, *blocks = *@scanner.epilogue.split(/^----/) blocks.each do |block| header, *body = block.lines.to_a - label0, pathes = *header.sub(/\A-+/, '').split('=', 2) + label0, paths = *header.sub(/\A-+/, '').split('=', 2) label = canonical_label(label0) - (pathes ? pathes.strip.split(' ') : []).each do |path| + (paths ? paths.strip.split(' ') : []).each do |path| add_user_code label, SourceText.new(File.read(path), path, 1) end add_user_code label, SourceText.new(body.join(''), @filename, line + 1) @@ -286,7 +287,7 @@ def canonical_label(src) end def add_user_code(label, src) - @result.params.send(USER_CODE_LABELS[label]).push src + @result.params.public_send(USER_CODE_LABELS[label]).push src end end @@ -427,7 +428,7 @@ def skip_comment $raccs_print_type = false def scan_action - buf = '' + buf = String.new nest = 1 pre = nil @in_block = 'action' diff --git a/ruby/lib/racc/info.rb b/ruby/lib/racc/info.rb index b7db7b6c9..bb1f100ad 100644 --- a/ruby/lib/racc/info.rb +++ b/ruby/lib/racc/info.rb @@ -1,14 +1,17 @@ +#-- +# # -# $Id: 8ab2cb5341529fe5e35956bb1a1f42ec9b9c6f5a $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # see the file "COPYING". +# +#++ module Racc - VERSION = '1.4.16' + VERSION = '1.6.0' Version = VERSION Copyright = 'Copyright (c) 1999-2006 Minero Aoki' end diff --git a/ruby/lib/racc/iset.rb b/ruby/lib/racc/iset.rb index 245bad8b5..339221d21 100644 --- a/ruby/lib/racc/iset.rb +++ b/ruby/lib/racc/iset.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 31aa4331c08dfd4609c06eb5f94b7ef38dc708e1 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ module Racc diff --git a/ruby/lib/racc/logfilegenerator.rb b/ruby/lib/racc/logfilegenerator.rb index 68593c41f..2f5aa0c8b 100644 --- a/ruby/lib/racc/logfilegenerator.rb +++ b/ruby/lib/racc/logfilegenerator.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 5e9d0a01b5d56fd9cdc3d5cb078b1a3e1bbaf779 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ module Racc diff --git a/ruby/lib/racc/parser-text.rb b/ruby/lib/racc/parser-text.rb index 31b8e2c01..4188fa853 100644 --- a/ruby/lib/racc/parser-text.rb +++ b/ruby/lib/racc/parser-text.rb @@ -31,7 +31,7 @@ class ParseError < StandardError; end # == Command-line Reference # # racc [-ofilename] [--output-file=filename] -# [-erubypath] [--embedded=rubypath] +# [-erubypath] [--executable=rubypath] # [-v] [--verbose] # [-Ofilename] [--log-file=filename] # [-g] [--debug] @@ -43,7 +43,7 @@ class ParseError < StandardError; end # [-S] [--output-status] # [--version] [--copyright] [--help] grammarfile # -# [+filename+] +# [+grammarfile+] # Racc grammar file. Any extension is permitted. # [-o+outfile+, --output-file=+outfile+] # A filename for output. default is <+filename+>.tab.rb @@ -181,45 +181,39 @@ class ParseError < StandardError; end # Your own parser is completely yours. module Racc - unless defined?(Racc_No_Extentions) - Racc_No_Extentions = false # :nodoc: + unless defined?(Racc_No_Extensions) + Racc_No_Extensions = false # :nodoc: end class Parser Racc_Runtime_Version = ::Racc::VERSION - Racc_Runtime_Revision = '$Id: 7adc21ee7a5690f10b7ff399b8af4e2717b9d94c $' - Racc_Runtime_Core_Version_R = ::Racc::VERSION - Racc_Runtime_Core_Revision_R = '$Id: 7adc21ee7a5690f10b7ff399b8af4e2717b9d94c $'.split[1] + begin if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + require 'jruby' require 'racc/cparse-jruby.jar' com.headius.racc.Cparse.new.load(JRuby.runtime, false) else require 'racc/cparse' end - # Racc_Runtime_Core_Version_C = (defined in extension) - Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] + unless new.respond_to?(:_racc_do_parse_c, true) raise LoadError, 'old cparse.so' end - if Racc_No_Extentions + if Racc_No_Extensions raise LoadError, 'selecting ruby version of racc runtime core' end Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc: Racc_Runtime_Type = 'c' # :nodoc: rescue LoadError -puts $! -puts $!.backtrace Racc_Main_Parsing_Routine = :_racc_do_parse_rb Racc_YY_Parse_Method = :_racc_yyparse_rb Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R Racc_Runtime_Type = 'ruby' end @@ -332,7 +326,7 @@ def _racc_do_parse_rb(arg, in_debug) # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. class_eval %{ def yyparse(recv, mid) - #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), true) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false) end } @@ -554,7 +548,7 @@ def yyerror end # Exit parser. - # Return value is Symbol_Value_Stack[0]. + # Return value is +Symbol_Value_Stack[0]+. def yyaccept throw :racc_jump, 2 end diff --git a/ruby/lib/racc/parser.rb b/ruby/lib/racc/parser.rb index 56b4af9de..4237fb572 100644 --- a/ruby/lib/racc/parser.rb +++ b/ruby/lib/racc/parser.rb @@ -29,7 +29,7 @@ class ParseError < StandardError; end # == Command-line Reference # # racc [-ofilename] [--output-file=filename] -# [-erubypath] [--embedded=rubypath] +# [-erubypath] [--executable=rubypath] # [-v] [--verbose] # [-Ofilename] [--log-file=filename] # [-g] [--debug] @@ -41,7 +41,7 @@ class ParseError < StandardError; end # [-S] [--output-status] # [--version] [--copyright] [--help] grammarfile # -# [+filename+] +# [+grammarfile+] # Racc grammar file. Any extension is permitted. # [-o+outfile+, --output-file=+outfile+] # A filename for output. default is <+filename+>.tab.rb @@ -179,45 +179,39 @@ class ParseError < StandardError; end # Your own parser is completely yours. module Racc - unless defined?(Racc_No_Extentions) - Racc_No_Extentions = false # :nodoc: + unless defined?(Racc_No_Extensions) + Racc_No_Extensions = false # :nodoc: end class Parser Racc_Runtime_Version = ::Racc::VERSION - Racc_Runtime_Revision = '$Id: e754525bd317344c4284fca6fdce0a425979ade1 $' - Racc_Runtime_Core_Version_R = ::Racc::VERSION - Racc_Runtime_Core_Revision_R = '$Id: e754525bd317344c4284fca6fdce0a425979ade1 $'.split[1] + begin if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + require 'jruby' require 'racc/cparse-jruby.jar' com.headius.racc.Cparse.new.load(JRuby.runtime, false) else require 'racc/cparse' end - # Racc_Runtime_Core_Version_C = (defined in extension) - Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] + unless new.respond_to?(:_racc_do_parse_c, true) raise LoadError, 'old cparse.so' end - if Racc_No_Extentions + if Racc_No_Extensions raise LoadError, 'selecting ruby version of racc runtime core' end Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc: Racc_Runtime_Type = 'c' # :nodoc: rescue LoadError -puts $! -puts $!.backtrace Racc_Main_Parsing_Routine = :_racc_do_parse_rb Racc_YY_Parse_Method = :_racc_yyparse_rb Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R Racc_Runtime_Type = 'ruby' end @@ -330,7 +324,7 @@ def _racc_do_parse_rb(arg, in_debug) # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. class_eval %{ def yyparse(recv, mid) - #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), true) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false) end } @@ -552,7 +546,7 @@ def yyerror end # Exit parser. - # Return value is Symbol_Value_Stack[0]. + # Return value is +Symbol_Value_Stack[0]+. def yyaccept throw :racc_jump, 2 end diff --git a/ruby/lib/racc/parserfilegenerator.rb b/ruby/lib/racc/parserfilegenerator.rb index ee1262db2..713102692 100644 --- a/ruby/lib/racc/parserfilegenerator.rb +++ b/ruby/lib/racc/parserfilegenerator.rb @@ -1,13 +1,15 @@ +#-- +# # -# $Id: fff07ebfd582f8dbc845e424908cb9f41f8bf42f $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # see the file "COPYING". +# +#++ -require 'enumerator' require 'racc/compat' require 'racc/sourcetext' require 'racc/parser-text' @@ -235,7 +237,7 @@ def make_separator(src) end def unique_separator(id) - sep = "...end #{id}/module_eval..." + sep = String.new "...end #{id}/module_eval..." while @used_separator.key?(sep) sep.concat sprintf('%02x', rand(255)) end @@ -318,50 +320,6 @@ def state_transition_table end def integer_list(name, table) - if table.size > 2000 - serialize_integer_list_compressed name, table - else - serialize_integer_list_std name, table - end - end - - def serialize_integer_list_compressed(name, table) - # TODO: this can be made a LOT more clean with a simple split/map - sep = "\n" - nsep = ",\n" - buf = '' - com = '' - ncom = ',' - co = com - @f.print 'clist = [' - table.each do |i| - buf << co << i.to_s; co = ncom - if buf.size > 66 - @f.print sep; sep = nsep - @f.print "'", buf, "'" - buf = '' - co = com - end - end - unless buf.empty? - @f.print sep - @f.print "'", buf, "'" - end - line ' ]' - - @f.print(<<-End) - #{name} = arr = ::Array.new(#{table.size}, nil) - idx = 0 - clist.each do |str| - str.split(',', -1).each do |i| - arr[idx] = i.to_i unless i.empty? - idx += 1 - end - end - End - end - - def serialize_integer_list_std(name, table) sep = '' line "#{name} = [" table.each_slice(10) do |ns| diff --git a/ruby/lib/racc/pre-setup b/ruby/lib/racc/pre-setup deleted file mode 100644 index 5027d865b..000000000 --- a/ruby/lib/racc/pre-setup +++ /dev/null @@ -1,13 +0,0 @@ -def generate_parser_text_rb(target) - return if File.exist?(srcfile(target)) - $stderr.puts "generating #{target}..." - File.open(target, 'w') {|f| - f.puts "module Racc" - f.puts " PARSER_TEXT = <<'__end_of_file__'" - f.puts File.read(srcfile('parser.rb')) - f.puts "__end_of_file__" - f.puts "end" - } -end - -generate_parser_text_rb 'parser-text.rb' diff --git a/ruby/lib/racc/racc.gemspec b/ruby/lib/racc/racc.gemspec index 6beb16c5b..7ee706f63 100644 --- a/ruby/lib/racc/racc.gemspec +++ b/ruby/lib/racc/racc.gemspec @@ -1,8 +1,14 @@ # -*- encoding: utf-8 -*- +begin + require_relative "lib/racc/info" +rescue LoadError # Fallback to load version file in ruby core repository + require_relative "info" +end + Gem::Specification.new do |s| s.name = "racc" - s.version = "1.4.16" + s.version = Racc::VERSION s.summary = "Racc is a LALR(1) parser generator" s.description = <= 0") if s.respond_to? :required_rubygems_version= - s.extensions = ["ext/racc/extconf.rb"] + s.required_ruby_version = ">= 2.5" s.rdoc_options = ["--main", "README.rdoc"] - s.extra_rdoc_files = [ - "Manifest.txt", "README.ja.rdoc", "README.rdoc", - "rdoc/en/NEWS.en.rdoc", "rdoc/en/grammar.en.rdoc", - "rdoc/ja/NEWS.ja.rdoc", "rdoc/ja/debug.ja.rdoc", - "rdoc/ja/grammar.ja.rdoc", "rdoc/ja/parser.ja.rdoc", - "README.ja.rdoc", "README.rdoc" - ] + s.extra_rdoc_files = ["README.ja.rdoc", "README.rdoc"] if RUBY_PLATFORM =~ /java/ s.files << 'lib/racc/cparse-jruby.jar' + s.platform = 'java' + else + s.extensions = ["ext/racc/cparse/extconf.rb"] end - - s.add_development_dependency("rake-compiler", [">= 0.4.1"]) - s.add_development_dependency("minitest", ["~> 4.7"]) - s.add_development_dependency("rdoc", [">= 4.0", "< 7"]) - s.add_development_dependency("hoe", ["~> 3.18"]) end diff --git a/ruby/lib/racc/rdoc/grammar.en.rdoc b/ruby/lib/racc/rdoc/grammar.en.rdoc deleted file mode 100644 index af10803f3..000000000 --- a/ruby/lib/racc/rdoc/grammar.en.rdoc +++ /dev/null @@ -1,219 +0,0 @@ -= Racc Grammar File Reference - -== Global Structure - -== Class Block and User Code Block - -There are two blocks on the toplevel. One is the 'class' block, the other is the 'user code' -block. The 'user code' block MUST be placed after the 'class' block. - -== Comments - -You can insert comments about all places. Two styles of comments can be used, Ruby style '#.....' and C style '/\*......*\/'. - -== Class Block - -The class block is formed like this: - - class CLASS_NAME - [precedence table] - [token declarations] - [expected number of S/R conflicts] - [options] - [semantic value conversion] - [start rule] - rule - GRAMMARS - -CLASS_NAME is a name of the parser class. This is the name of the generating parser -class. - -If CLASS_NAME includes '::', Racc outputs the module clause. For example, writing -"class M::C" causes the code below to be created: - - module M - class C - : - : - end - end - -== Grammar Block - -The grammar block describes grammar which is able to be understood by the parser. -Syntax is: - - (token): (token) (token) (token).... (action) - - (token): (token) (token) (token).... (action) - | (token) (token) (token).... (action) - | (token) (token) (token).... (action) - -(action) is an action which is executed when its (token)s are found. -(action) is a ruby code block, which is surrounded by braces: - - { print val[0] - puts val[1] } - -Note that you cannot use '%' string, here document, '%r' regexp in action. - -Actions can be omitted. When it is omitted, '' (empty string) is used. - -A return value of action is a value of the left side value ($$). It is the value of the -result, or the returned value by `return` statement. - -Here is an example of the whole grammar block. - - rule - goal: definition rules source { result = val } - - definition: /* none */ { result = [] } - | definition startdesig { result[0] = val[1] } - | definition - precrule # this line continues from upper line - { - result[1] = val[1] - } - - startdesig: START TOKEN - -You can use the following special local variables in action: - -* result ($$) - -The value of the left-hand side (lhs). A default value is val[0]. - -* val ($1,$2,$3...) - -An array of value of the right-hand side (rhs). - -* _values (...$-2,$-1,$0) - -A stack of values. DO NOT MODIFY this stack unless you know what you are doing. - -== Operator Precedence - -This function is equal to '%prec' in yacc. -To designate this block: - - prechigh - nonassoc '++' - left '*' '/' - left '+' '-' - right '=' - preclow - -`right` is yacc's %right, `left` is yacc's %left. - -`=` + (symbol) means yacc's %prec: - - prechigh - nonassoc UMINUS - left '*' '/' - left '+' '-' - preclow - - rule - exp: exp '*' exp - | exp '-' exp - | '-' exp =UMINUS # equals to "%prec UMINUS" - : - : - -== expect - -Racc has bison's "expect" directive. - - # Example - - class MyParser - rule - expect 3 - : - : - -This directive declares "expected" number of shift/reduce conflicts. If -"expected" number is equal to real number of conflicts, Racc does not print -conflict warning message. - -== Declaring Tokens - -By declaring tokens, you can avoid many meaningless bugs. If declared token -does not exist or existing token does not decleared, Racc output warnings. -Declaration syntax is: - - token TOKEN_NAME AND_IS_THIS - ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST - -== Options - -You can write options for Racc command in your Racc file. - - options OPTION OPTION ... - -Options are: - -* omit_action_call - -omits empty action call or not. - -* result_var - -uses local variable "result" or not. - -You can use 'no_' prefix to invert their meanings. - -== Converting Token Symbol - -Token symbols are, as default, - - * naked token string in Racc file (TOK, XFILE, this_is_token, ...) - --> symbol (:TOK, :XFILE, :this_is_token, ...) - * quoted string (':', '.', '(', ...) - --> same string (':', '.', '(', ...) - -You can change this default by "convert" block. -Here is an example: - - convert - PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS' - MIN 'MinusClass' # We use MinusClass for symbol of `MIN' - end - -We can use almost all ruby value can be used by token symbol, -except 'false' and 'nil'. These cause unexpected parse error. - -If you want to use String as token symbol, special care is required. -For example: - - convert - class '"cls"' # in code, "cls" - PLUS '"plus\n"' # in code, "plus\n" - MIN "\"minus#{val}\"" # in code, \"minus#{val}\" - end - -== Start Rule - -'%start' in yacc. This changes start rule. - - start real_target - -== User Code Block - -"User Code Block" is a Ruby source code which is copied to output. There are -three user code blocks, "header" "inner" and "footer". - -Format of user code is like this: - - ---- header - ruby statement - ruby statement - ruby statement - - ---- inner - ruby statement - : - : - -If four '-' exist on the line head, Racc treats it as the beginning of the -user code block. The name of the user code block must be one word. diff --git a/ruby/lib/racc/sourcetext.rb b/ruby/lib/racc/sourcetext.rb index b33ba2929..de52dcae9 100644 --- a/ruby/lib/racc/sourcetext.rb +++ b/ruby/lib/racc/sourcetext.rb @@ -1,13 +1,14 @@ +#-- +# # -# $Id: 3b2d89d9ada2f5fcb043837dcc5c9631856d5b70 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ module Racc diff --git a/ruby/lib/racc/state.rb b/ruby/lib/racc/state.rb index 51b1d8366..f85809fbe 100644 --- a/ruby/lib/racc/state.rb +++ b/ruby/lib/racc/state.rb @@ -1,11 +1,14 @@ +#-- +# # -# $Id: 6bd3136439c94cb8d928917f5e0de9c593181527 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. # You can distribute/modify this program under the same terms of ruby. # see the file "COPYING". +# +#++ require 'racc/iset' require 'racc/statetransitiontable' diff --git a/ruby/lib/racc/statetransitiontable.rb b/ruby/lib/racc/statetransitiontable.rb index 23df4102e..4d5428725 100644 --- a/ruby/lib/racc/statetransitiontable.rb +++ b/ruby/lib/racc/statetransitiontable.rb @@ -1,22 +1,17 @@ +#-- +# # -# $Id: 4c5f4311663b6d03050953d64d6a0e7905ff2216 $ # # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". # +#++ require 'racc/parser' -unless Object.method_defined?(:funcall) - class Object - alias funcall __send__ - end -end - module Racc StateTransitionTable = Struct.new(:action_table, @@ -196,7 +191,7 @@ def addent(all, arr, chkval, ptr) def mkmapexp(arr) i = ii = 0 as = arr.size - map = '' + map = String.new maxdup = RE_DUP_MAX curr = nil while i < as @@ -229,7 +224,7 @@ def set_table(entries, dummy, tbl, chk, ptr) map = '-' * 10240 # sort long to short - entries.sort! {|a,b| b[0].size <=> a[0].size } + entries.sort_by!.with_index {|a,i| [-a[0].size, i] } entries.each do |arr, chkval, expr, min, ptri| if upper + arr.size > map.size @@ -299,9 +294,9 @@ def define_actions(c) c.module_eval "def _reduce_none(vals, vstack) vals[0] end" @grammar.each do |rule| if rule.action.empty? - c.funcall(:alias_method, "_reduce_#{rule.ident}", :_reduce_none) + c.alias_method("_reduce_#{rule.ident}", :_reduce_none) else - c.funcall(:define_method, "_racc_action_#{rule.ident}", &rule.action.proc) + c.define_method("_racc_action_#{rule.ident}", &rule.action.proc) c.module_eval(<<-End, __FILE__, __LINE__ + 1) def _reduce_#{rule.ident}(vals, vstack) _racc_action_#{rule.ident}(*vals) diff --git a/ruby/lib/random/formatter.rb b/ruby/lib/random/formatter.rb new file mode 100644 index 000000000..744853a4b --- /dev/null +++ b/ruby/lib/random/formatter.rb @@ -0,0 +1,217 @@ +# -*- coding: us-ascii -*- +# frozen_string_literal: true + +# == Random number formatter. +# +# Formats generated random numbers in many manners. +# +# === Examples +# +# Generate random hexadecimal strings: +# +# require 'random/formatter' +# +# prng.hex(10) #=> "52750b30ffbc7de3b362" +# prng.hex(10) #=> "92b15d6c8dc4beb5f559" +# prng.hex(13) #=> "39b290146bea6ce975c37cfc23" +# +# Generate random base64 strings: +# +# prng.base64(10) #=> "EcmTPZwWRAozdA==" +# prng.base64(10) #=> "KO1nIU+p9DKxGg==" +# prng.base64(12) #=> "7kJSM/MzBJI+75j8" +# +# Generate random binary strings: +# +# prng.random_bytes(10) #=> "\016\t{\370g\310pbr\301" +# prng.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337" +# +# Generate alphanumeric strings: +# +# prng.alphanumeric(10) #=> "S8baxMJnPl" +# prng.alphanumeric(10) #=> "aOxAg8BAJe" +# +# Generate UUIDs: +# +# prng.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594" +# prng.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab" + +module Random::Formatter + + # Random::Formatter#random_bytes generates a random binary string. + # + # The argument _n_ specifies the length of the result string. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in future. + # + # The result may contain any byte: "\x00" - "\xff". + # + # require 'random/formatter' + # + # prng.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6" + # prng.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97" + def random_bytes(n=nil) + n = n ? n.to_int : 16 + gen_random(n) + end + + # Random::Formatter#hex generates a random hexadecimal string. + # + # The argument _n_ specifies the length, in bytes, of the random number to be generated. + # The length of the resulting hexadecimal string is twice of _n_. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain 0-9 and a-f. + # + # require 'random/formatter' + # + # prng.hex #=> "eb693ec8252cd630102fd0d0fb7c3485" + # prng.hex #=> "91dc3bfb4de5b11d029d376634589b61" + def hex(n=nil) + random_bytes(n).unpack1("H*") + end + + # Random::Formatter#base64 generates a random base64 string. + # + # The argument _n_ specifies the length, in bytes, of the random number + # to be generated. The length of the result string is about 4/3 of _n_. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain A-Z, a-z, 0-9, "+", "/" and "=". + # + # require 'random/formatter' + # + # prng.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A==" + # prng.base64 #=> "6BbW0pxO0YENxn38HMUbcQ==" + # + # See RFC 3548 for the definition of base64. + def base64(n=nil) + [random_bytes(n)].pack("m0") + end + + # Random::Formatter#urlsafe_base64 generates a random URL-safe base64 string. + # + # The argument _n_ specifies the length, in bytes, of the random number + # to be generated. The length of the result string is about 4/3 of _n_. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The boolean argument _padding_ specifies the padding. + # If it is false or nil, padding is not generated. + # Otherwise padding is generated. + # By default, padding is not generated because "=" may be used as a URL delimiter. + # + # The result may contain A-Z, a-z, 0-9, "-" and "_". + # "=" is also used if _padding_ is true. + # + # require 'random/formatter' + # + # prng.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg" + # prng.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg" + # + # prng.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ==" + # prng.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg==" + # + # See RFC 3548 for the definition of URL-safe base64. + def urlsafe_base64(n=nil, padding=false) + s = [random_bytes(n)].pack("m0") + s.tr!("+/", "-_") + s.delete!("=") unless padding + s + end + + # Random::Formatter#uuid generates a random v4 UUID (Universally Unique IDentifier). + # + # require 'random/formatter' + # + # prng.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594" + # prng.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab" + # prng.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b" + # + # The version 4 UUID is purely random (except the version). + # It doesn't contain meaningful information such as MAC addresses, timestamps, etc. + # + # The result contains 122 random bits (15.25 random bytes). + # + # See RFC 4122 for details of UUID. + # + 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 + end + + private def gen_random(n) + self.bytes(n) + end + + # Random::Formatter#choose generates a string that randomly draws from a + # source array of characters. + # + # The argument _source_ specifies the array of characters from which + # to generate the string. + # The argument _n_ specifies the length, in characters, of the string to be + # generated. + # + # The result may contain whatever characters are in the source array. + # + # require 'random/formatter' + # + # prng.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron" + # prng.choose([*'0'..'9'], 5) #=> "27309" + private def choose(source, n) + size = source.size + m = 1 + limit = size + while limit * size <= 0x100000000 + limit *= size + m += 1 + end + result = ''.dup + while m <= n + rs = random_number(limit) + is = rs.digits(size) + (m-is.length).times { is << 0 } + result << source.values_at(*is).join('') + n -= m + end + if 0 < n + rs = random_number(limit) + is = rs.digits(size) + if is.length < n + (n-is.length).times { is << 0 } + else + is.pop while n < is.length + end + result.concat source.values_at(*is).join('') + end + result + end + + ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'] + # Random::Formatter#alphanumeric generates a random alphanumeric string. + # + # The argument _n_ specifies the length, in characters, of the alphanumeric + # string to be generated. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain A-Z, a-z and 0-9. + # + # require 'random/formatter' + # + # prng.alphanumeric #=> "2BuBuLf3WfSKyQbR" + # prng.alphanumeric(10) #=> "i6K93NdqiH" + def alphanumeric(n=nil) + n = 16 if n.nil? + choose(ALPHANUMERIC, n) + end +end diff --git a/ruby/lib/rdoc.rb b/ruby/lib/rdoc.rb index fc8ad9e14..2d3f8c112 100644 --- a/ruby/lib/rdoc.rb +++ b/ruby/lib/rdoc.rb @@ -120,6 +120,27 @@ def self.load_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, 'rdoc/rdoc' autoload :CrossReference, 'rdoc/cross_reference' diff --git a/ruby/lib/rdoc/any_method.rb b/ruby/lib/rdoc/any_method.rb index 9b0d30965..0b7dd717a 100644 --- a/ruby/lib/rdoc/any_method.rb +++ b/ruby/lib/rdoc/any_method.rb @@ -26,12 +26,9 @@ class RDoc::AnyMethod < RDoc::MethodAttr attr_accessor :c_function - ## - # Different ways to call this method + # The section title of the method (if defined in a C file via +:category:+) + attr_accessor :section_title - attr_reader :call_seq - - ## # Parameters for this method attr_accessor :params @@ -93,6 +90,19 @@ def arglists 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. @@ -312,5 +322,43 @@ def superclass_method @superclass_method end -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[0, 1] : n} + ignore.delete(method_name) + ignore = Regexp.union(ignore) + + matching = entries.reject do |entry| + entry =~ /^\w*\.?#{ignore}/ or + entry =~ /\s#{ignore}\s/ + end + + matching.empty? ? nil : matching.join("\n") + end +end diff --git a/ruby/lib/rdoc/context.rb b/ruby/lib/rdoc/context.rb index 6caf0d671..b3caa53aa 100644 --- a/ruby/lib/rdoc/context.rb +++ b/ruby/lib/rdoc/context.rb @@ -990,13 +990,21 @@ def instance_attributes @instance_attributes ||= attributes.reject { |a| a.singleton } end + ## + # Instance methods + + def instance_methods + @instance_methods ||= method_list.reject { |a| a.singleton } + end + ## # Instance methods #-- - # TODO rename to instance_methods + # TODO remove this later def instance_method_list - @instance_method_list ||= method_list.reject { |a| a.singleton } + warn '#instance_method_list is obsoleted, please use #instance_methods' + @instance_methods ||= method_list.reject { |a| a.singleton } end ## diff --git a/ruby/lib/rdoc/context/section.rb b/ruby/lib/rdoc/context/section.rb index 11f9ceaf8..5fef4a9ff 100644 --- a/ruby/lib/rdoc/context/section.rb +++ b/ruby/lib/rdoc/context/section.rb @@ -34,8 +34,6 @@ class RDoc::Context::Section attr_reader :title - @@sequence = "SEC00000" - ## # Creates a new section with +title+ and +comment+ @@ -43,9 +41,6 @@ def initialize parent, title, comment @parent = parent @title = title ? title.strip : title - @@sequence = @@sequence.succ - @sequence = @@sequence.dup - @comments = [] add_comment comment @@ -233,13 +228,5 @@ def remove_comment comment end end - ## - # Section sequence number (deprecated) - - def sequence - warn "RDoc::Context::Section#sequence is deprecated, use #aref" - @sequence - end - end diff --git a/ruby/lib/rdoc/cross_reference.rb b/ruby/lib/rdoc/cross_reference.rb index 07ba14c5c..ef8e21bde 100644 --- a/ruby/lib/rdoc/cross_reference.rb +++ b/ruby/lib/rdoc/cross_reference.rb @@ -19,7 +19,7 @@ class RDoc::CrossReference # # See CLASS_REGEXP_STR - METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>|-|\+|\*)(?:\([\w.+*/=<>-]*\))?' + METHOD_REGEXP_STR = '([A-Za-z]\w*[!?=]?|%|===?|\[\]=?|<<|>>|\+@|-@|-|\+|\*)(?:\([\w.+*/=<>-]*\))?' ## # Regular expressions matching text that should potentially have @@ -34,12 +34,6 @@ class RDoc::CrossReference # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - # Stand-alone method (preceded by a #) - | \\?\##{METHOD_REGEXP_STR} - - # Stand-alone method (preceded by ::) - | ::#{METHOD_REGEXP_STR} - # A::B::C # The stuff after CLASS_REGEXP_STR is a # nasty hack. CLASS_REGEXP_STR unfortunately matches @@ -56,6 +50,12 @@ class RDoc::CrossReference # 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 @@ -82,12 +82,12 @@ class RDoc::CrossReference # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - # Stand-alone method - | \\?#{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\/.]+ @@ -115,15 +115,8 @@ def initialize context @seen = {} 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 + def resolve_method name + ref = nil if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $2 @@ -165,15 +158,30 @@ def resolve name, text 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 unless ref + end + + ref = resolve_method name unless ref # Try a page name - ref = @store.page name if not ref and name =~ /^\w+$/ + ref = @store.page name if not ref and name =~ /^[\w.]+$/ ref = nil if RDoc::Alias === ref # external alias, can't link to it diff --git a/ruby/lib/rdoc/erb_partial.rb b/ruby/lib/rdoc/erb_partial.rb index 8dc2c4601..d6e3f41b7 100644 --- a/ruby/lib/rdoc/erb_partial.rb +++ b/ruby/lib/rdoc/erb_partial.rb @@ -12,7 +12,7 @@ class RDoc::ERBPartial < ERB def set_eoutvar compiler, eoutvar = '_erbout' super - compiler.pre_cmd = ["#{eoutvar} ||= ''"] + compiler.pre_cmd = ["#{eoutvar} ||= +''"] end end diff --git a/ruby/lib/rdoc/erbio.rb b/ruby/lib/rdoc/erbio.rb index 820a25ae0..0d5f96e13 100644 --- a/ruby/lib/rdoc/erbio.rb +++ b/ruby/lib/rdoc/erbio.rb @@ -20,11 +20,11 @@ class RDoc::ERBIO < ERB ## # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize - def initialize str, safe_level = nil, trim_mode = nil, eoutvar = 'io' + def initialize str, safe_level = nil, legacy_trim_mode = nil, legacy_eoutvar = 'io', trim_mode: nil, eoutvar: 'io' if RUBY_VERSION >= '2.6' super(str, trim_mode: trim_mode, eoutvar: eoutvar) else - super + super(str, safe_level, legacy_trim_mode, legacy_eoutvar) end end diff --git a/ruby/lib/rdoc/generator/darkfish.rb b/ruby/lib/rdoc/generator/darkfish.rb index c5d47ef35..60e0265e8 100644 --- a/ruby/lib/rdoc/generator/darkfish.rb +++ b/ruby/lib/rdoc/generator/darkfish.rb @@ -4,7 +4,7 @@ require 'erb' require 'fileutils' require 'pathname' -require 'rdoc/generator/markup' +require_relative 'markup' ## # Darkfish RDoc HTML Generator @@ -220,8 +220,8 @@ def write_style_sheet install_rdoc_static_file @template_dir + item, "./#{item}", options end - @options.template_stylesheets.each do |stylesheet| - FileUtils.cp stylesheet, '.', options + unless @options.template_stylesheets.empty? + FileUtils.cp @options.template_stylesheets, '.', **options end Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| @@ -779,9 +779,9 @@ def template_for file, page = true, klass = ERB end if RUBY_VERSION >= '2.6' - template = klass.new template, trim_mode: '<>', eoutvar: erbout + template = klass.new template, trim_mode: '-', eoutvar: erbout else - template = klass.new template, nil, '<>', erbout + template = klass.new template, nil, '-', erbout end @template_cache[file] = template template diff --git a/ruby/lib/rdoc/generator/pot.rb b/ruby/lib/rdoc/generator/pot.rb index a12cba750..bee1133b0 100644 --- a/ruby/lib/rdoc/generator/pot.rb +++ b/ruby/lib/rdoc/generator/pot.rb @@ -91,8 +91,8 @@ def extract_messages extractor.extract end - require 'rdoc/generator/pot/message_extractor' - require 'rdoc/generator/pot/po' - require 'rdoc/generator/pot/po_entry' + require_relative 'pot/message_extractor' + require_relative 'pot/po' + require_relative 'pot/po_entry' end diff --git a/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml index 8304310d4..4f331245c 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml @@ -15,9 +15,6 @@ -<% if @options.template_stylesheets.flatten.any? then %> -<% @options.template_stylesheets.flatten.each do |stylesheet| %> +<%- @options.template_stylesheets.each do |stylesheet| -%> -<% end %> -<% end %> - +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml index e889f8063..22a12d9e9 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml @@ -1,4 +1,4 @@ -<% if !svninfo.empty? then %> +<%- if !svninfo.empty? then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml index fe54d8339..530f25c76 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml @@ -2,8 +2,8 @@

Class and Module Index

diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml index 2bd8efee9..7602076c9 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml @@ -1,15 +1,15 @@ -<% unless klass.extends.empty? then %> +<%- unless klass.extends.empty? then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml index 0ba1d2be8..74869a4b5 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml @@ -2,8 +2,8 @@

Defined In

    -<% klass.in_files.each do |tl| %> +<%- klass.in_files.each do |tl| -%>
  • <%= h tl.relative_name %> -<% end %> +<%- end -%>
diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml index d141098ec..5b600e597 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml @@ -1,15 +1,15 @@ -<% unless klass.includes.empty? then %> +<%- unless klass.includes.empty? then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml index 1285bfd73..faed7e0a9 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml @@ -2,14 +2,14 @@

Documentation

    - <% installed.each do |name, href, exists, type, _| %> - <% next if type == :extra %> + <%- installed.each do |name, href, exists, type, _| -%> + <%- next if type == :extra -%>
  • - <% if exists then %> + <%- if exists then -%> <%= h name %> - <% else %> + <%- else -%> <%= h name %> - <% end %> - <% end %> + <%- end -%> + <%- end -%>
diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml index 45df08d8f..5b4c295be 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml @@ -1,12 +1,12 @@ -<% unless klass.method_list.empty? then %> +<%- unless klass.method_list.empty? then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml index 5f39825f0..8ec83abda 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml @@ -1,12 +1,12 @@ -<% simple_files = @files.select { |f| f.text? } %> -<% unless simple_files.empty? then %> +<%- simple_files = @files.select { |f| f.text? } %> +<%- unless simple_files.empty? then -%> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml index cc0485265..1420da320 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml @@ -1,11 +1,11 @@ -<% if klass.type == 'class' then %> +<%- if klass.type == 'class' then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml index 15ff78ba9..6dcd2ae81 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml @@ -1,11 +1,11 @@ -<% unless klass.sections.length == 1 then %> +<%- unless klass.sections.length == 1 then %> -<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml index b58e6b3c6..bf70819f6 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml @@ -1,4 +1,4 @@ -<% comment = if current.respond_to? :comment_location then +<%- comment = if current.respond_to? :comment_location then current.comment_location else current.comment @@ -10,9 +10,9 @@

Table of Contents

-<% end %> +<%- end -%> diff --git a/ruby/lib/rdoc/generator/template/darkfish/class.rhtml b/ruby/lib/rdoc/generator/template/darkfish/class.rhtml index 773309508..5d7b6a1b8 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/class.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/class.rhtml @@ -25,9 +25,9 @@ <%= klass.description %>
- <% klass.each_section do |section, constants, attributes| %> + <%- klass.each_section do |section, constants, attributes| -%>
- <% if section.title then %> + <%- if section.title then -%>

<%= section.title %> @@ -36,39 +36,39 @@ ↑ top

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

Constants

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

Attributes

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

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

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

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

- <% methods.each do |method| %> + <%- methods.each do |method| -%>
"> - <% if method.call_seq then %> - <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %> + <%- 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 %> + <%- if i == 0 and method.token_stream then -%> click to toggle source - <% end %> + <%- end -%>
- <% end %> - <% else %> + <%- end -%> + <%- else -%>
<%= h method.name %><%= h method.param_seq %> - <% if method.token_stream then %> + <%- if method.token_stream then -%> click to toggle source - <% end %> + <%- end -%>
- <% end %> + <%- end -%>
- <% if method.comment then %> + <%- if method.comment then -%> <%= method.description.strip %> - <% else %> + <%- else -%>

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

Calls superclass method <%= @@ -135,16 +135,16 @@ method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil %>
- <% end %> + <%- end -%> - <% if method.token_stream then %> + <%- if method.token_stream then -%>
<%= method.markup_code %>
- <% end %> + <%- end -%>
- <% unless method.aliases.empty? then %> + <%- unless method.aliases.empty? then -%>
Also aliased as: <%= method.aliases.map do |aka| if aka.parent then # HACK lib/rexml/encodings @@ -154,19 +154,19 @@ end end.join ", " %>
- <% end %> + <%- end -%> - <% if method.is_alias_for then %> + <%- if method.is_alias_for then -%> - <% end %> + <%- end -%>
- <% end %> + <%- end -%>
- <% end + <%- end end %> -<% end %> +<%- end -%>
diff --git a/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css b/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css index a52e44ff8..ebe2e93af 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css +++ b/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css @@ -79,6 +79,25 @@ pre { 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 { @@ -166,6 +185,7 @@ nav { width: 260px; font-family: Helvetica, sans-serif; font-size: 14px; + border-right: 1px solid #ccc; } main { @@ -276,7 +296,7 @@ ul.link-list .type { -webkit-border-radius: 5px; } -dl.label-list dt { +dl.note-list dt { float: left; margin-right: 1em; } diff --git a/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf index 61e3090c1..dd00982d4 100644 Binary files a/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf and b/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf differ diff --git a/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf index 85686d967..1decfb95a 100644 Binary files a/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf and b/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf differ diff --git a/ruby/lib/rdoc/generator/template/darkfish/index.rhtml b/ruby/lib/rdoc/generator/template/darkfish/index.rhtml index 7d1c74807..13fa3dcc7 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/index.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/index.rhtml @@ -13,11 +13,10 @@
-<% if @options.main_page and +<%- if @options.main_page and main_page = @files.find { |f| f.full_name == @options.main_page } then %> <%= main_page.description %> -<% else %> +<%- else -%>

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

- diff --git a/ruby/lib/rdoc/generator/template/darkfish/servlet_root.rhtml b/ruby/lib/rdoc/generator/template/darkfish/servlet_root.rhtml index 3a33659ae..cab3092b1 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/servlet_root.rhtml @@ -19,28 +19,28 @@

Here you can browse local documentation from the ruby standard library and your installed gems. -<% extra_dirs = installed.select { |_, _, _, type,| type == :extra } %> -<% unless extra_dirs.empty? %> +<%- extra_dirs = installed.select { |_, _, _, type,| type == :extra } -%> +<%- unless extra_dirs.empty? -%>

Extra Documentation Directories

The following additional documentation directories are available:

    - <% extra_dirs.each do |name, href, exists, _, path| %> + <%- extra_dirs.each do |name, href, exists, _, path| -%>
  1. - <% if exists %> + <%- if exists -%> <%= h name %> (<%= h path %>) - <% else %> + <%- else -%> <%= h name %> (<%= h path %>; not available) - <% end %> + <%- end -%>
  2. - <% end %> + <%- end -%>
-<% end %> +<%- end -%> -<% gems = installed.select { |_, _, _, type,| type == :gem } %> -<% missing = gems.reject { |_, _, exists,| exists } %> -<% unless missing.empty? then %> +<%- gems = installed.select { |_, _, _, type,| type == :gem } -%> +<%- missing = gems.reject { |_, _, exists,| exists } -%> +<%- unless missing.empty? then -%>

Missing Gem Documentation

You are missing documentation for some of your installed gems. @@ -53,11 +53,10 @@ the following commands.

    - <% names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq %> - <% names.each do |name| %> + <%- names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq -%> + <%- names.each do |name| -%>
  • gem rdoc <%=h name %> - <% end %> + <%- end -%>
-<% end %> +<%- end -%> - diff --git a/ruby/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/ruby/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml index 7ff1a9e93..303d7016c 100644 --- a/ruby/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +++ b/ruby/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml @@ -2,11 +2,11 @@

<%= h @title %>

-<% simple_files = @files.select { |f| f.text? } %> -<% unless simple_files.empty? then %> +<%- simple_files = @files.select { |f| f.text? } -%> +<%- unless simple_files.empty? then -%>

Pages

    -<% simple_files.sort.each do |file| %> +<%- simple_files.sort.each do |file| -%>
  • <%= h file.page_name %> <% @@ -14,45 +14,45 @@ table = file.parse(file.comment).table_of_contents unless table.empty? then %> -<% end %> +<%- end -%>
  • - <% end %> + <%- end -%>
-<% end %> +<%- end -%>

Classes and Modules

    -<% @modsort.each do |klass| %> +<%- @modsort.each do |klass| -%>
  • <%= klass.full_name %> -<% table = [] +<%- table = [] table.concat klass.parse(klass.comment_location).table_of_contents table.concat klass.section_contents unless table.empty? then %> -<% end %> +<%- end -%>
  • -<% end %> +<%- end -%>

Methods

    -<% @store.all_classes_and_modules.map do |mod| +<%- @store.all_classes_and_modules.map do |mod| mod.method_list end.flatten.sort.each do |method| %>
  • <%= h method.pretty_name %><%= method.parent.full_name %> -<% end %> +<%- end -%>
diff --git a/ruby/lib/rdoc/i18n.rb b/ruby/lib/rdoc/i18n.rb index af303858b..a32fd848a 100644 --- a/ruby/lib/rdoc/i18n.rb +++ b/ruby/lib/rdoc/i18n.rb @@ -5,6 +5,6 @@ module RDoc::I18n autoload :Locale, 'rdoc/i18n/locale' - require 'rdoc/i18n/text' + require_relative 'i18n/text' end diff --git a/ruby/lib/rdoc/markdown.rb b/ruby/lib/rdoc/markdown.rb index 43c70c8de..3442f76b1 100644 --- a/ruby/lib/rdoc/markdown.rb +++ b/ruby/lib/rdoc/markdown.rb @@ -173,7 +173,7 @@ # The port to kpeg was performed by Eric Hodel and Evan Phoenix # # [dingus]: http://daringfireball.net/projects/markdown/dingus -# [GFM]: http://github.github.com/github-flavored-markdown/ +# [GFM]: https://github.github.com/gfm/ # [pegmarkdown]: https://github.com/jgm/peg-markdown # [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list # [syntax]: http://daringfireball.net/projects/markdown/syntax @@ -344,9 +344,8 @@ def match_string(str) end def scan(reg) - if m = reg.match(@string[@pos..-1]) - width = m.end(0) - @pos += width + if m = reg.match(@string, @pos) + @pos = m.end(0) return true end @@ -897,7 +896,7 @@ def _Doc return _tmp end - # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain) + # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Table | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain) def _Block _save = self.pos @@ -923,6 +922,9 @@ def _Block _tmp = apply(:_CodeFence) break if _tmp self.pos = _save2 + _tmp = apply(:_Table) + break if _tmp + self.pos = _save2 _tmp = apply(:_Note) break if _tmp self.pos = _save2 @@ -1057,7 +1059,7 @@ def _AtxInline self.pos = _save3 break end - _tmp = scan(/\A(?-mix:#*)/) + _tmp = scan(/\G(?-mix:#*)/) unless _tmp self.pos = _save3 break @@ -1097,7 +1099,7 @@ def _AtxStart _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:\#{1,6})/) + _tmp = scan(/\G(?-mix:\#{1,6})/) if _tmp text = get_text(_text_start) end @@ -1162,7 +1164,7 @@ def _AtxHeading self.pos = _save3 break end - _tmp = scan(/\A(?-mix:#*)/) + _tmp = scan(/\G(?-mix:#*)/) unless _tmp self.pos = _save3 break @@ -1222,7 +1224,7 @@ def _SetextBottom1 _save = self.pos while true # sequence - _tmp = scan(/\A(?-mix:={1,})/) + _tmp = scan(/\G(?-mix:={1,})/) unless _tmp self.pos = _save break @@ -1243,7 +1245,7 @@ def _SetextBottom2 _save = self.pos while true # sequence - _tmp = scan(/\A(?-mix:-{1,})/) + _tmp = scan(/\G(?-mix:-{1,})/) unless _tmp self.pos = _save break @@ -2127,7 +2129,7 @@ def _Bullet self.pos = _save break end - _tmp = scan(/\A(?-mix:[+*-])/) + _tmp = scan(/\G(?-mix:[+*-])/) unless _tmp self.pos = _save break @@ -9320,7 +9322,7 @@ def _StyleBlock return _tmp end - # Inlines = (!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks } + # Inlines = (!@Endline Inline:i { i } | @Endline:c !(&{ github? } Ticks3 /[^`\n]*$/) &Inline { c })+:chunks @Endline? { chunks } def _Inlines _save = self.pos @@ -9367,12 +9369,41 @@ def _Inlines break end _save6 = self.pos - _tmp = apply(:_Inline) + + _save7 = self.pos + while true # sequence + _save8 = self.pos + _tmp = begin; github? ; end + self.pos = _save8 + unless _tmp + self.pos = _save7 + break + end + _tmp = apply(:_Ticks3) + unless _tmp + self.pos = _save7 + break + end + _tmp = scan(/\G(?-mix:[^`\n]*$)/) + unless _tmp + self.pos = _save7 + end + break + end # end sequence + + _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end + _save9 = self.pos + _tmp = apply(:_Inline) + self.pos = _save9 + unless _tmp + self.pos = _save5 + break + end @result = begin; c ; end _tmp = true unless _tmp @@ -9390,61 +9421,90 @@ def _Inlines _ary << @result while true - _save7 = self.pos + _save10 = self.pos while true # choice - _save8 = self.pos + _save11 = self.pos while true # sequence - _save9 = self.pos + _save12 = self.pos _tmp = _Endline() _tmp = _tmp ? nil : true - self.pos = _save9 + self.pos = _save12 unless _tmp - self.pos = _save8 + self.pos = _save11 break end _tmp = apply(:_Inline) i = @result unless _tmp - self.pos = _save8 + self.pos = _save11 break end @result = begin; i ; end _tmp = true unless _tmp - self.pos = _save8 + self.pos = _save11 end break end # end sequence break if _tmp - self.pos = _save7 + self.pos = _save10 - _save10 = self.pos + _save13 = self.pos while true # sequence _tmp = _Endline() c = @result unless _tmp - self.pos = _save10 + self.pos = _save13 break end - _save11 = self.pos + _save14 = self.pos + + _save15 = self.pos + while true # sequence + _save16 = self.pos + _tmp = begin; github? ; end + self.pos = _save16 + unless _tmp + self.pos = _save15 + break + end + _tmp = apply(:_Ticks3) + unless _tmp + self.pos = _save15 + break + end + _tmp = scan(/\G(?-mix:[^`\n]*$)/) + unless _tmp + self.pos = _save15 + end + break + end # end sequence + + _tmp = _tmp ? nil : true + self.pos = _save14 + unless _tmp + self.pos = _save13 + break + end + _save17 = self.pos _tmp = apply(:_Inline) - self.pos = _save11 + self.pos = _save17 unless _tmp - self.pos = _save10 + self.pos = _save13 break end @result = begin; c ; end _tmp = true unless _tmp - self.pos = _save10 + self.pos = _save13 end break end # end sequence break if _tmp - self.pos = _save7 + self.pos = _save10 break end # end choice @@ -9461,11 +9521,11 @@ def _Inlines self.pos = _save break end - _save12 = self.pos + _save18 = self.pos _tmp = _Endline() unless _tmp _tmp = true - self.pos = _save12 + self.pos = _save18 end unless _tmp self.pos = _save @@ -9664,7 +9724,7 @@ def _StrChunk _save3 = self.pos while true # sequence - _tmp = scan(/\A(?-mix:_+)/) + _tmp = scan(/\G(?-mix:_+)/) unless _tmp self.pos = _save3 break @@ -9694,7 +9754,7 @@ def _StrChunk _save6 = self.pos while true # sequence - _tmp = scan(/\A(?-mix:_+)/) + _tmp = scan(/\G(?-mix:_+)/) unless _tmp self.pos = _save6 break @@ -9757,7 +9817,7 @@ def _EscapedChar break end _text_start = self.pos - _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/) + _tmp = scan(/\G(?-mix:[:\\`|*_{}\[\]()#+.!><-])/) if _tmp text = get_text(_text_start) end @@ -9883,7 +9943,7 @@ def _NormalEndline self.pos = _save5 break end - _tmp = scan(/\A(?-mix:={1,}|-{1,})/) + _tmp = scan(/\G(?-mix:={1,}|-{1,})/) unless _tmp self.pos = _save5 break @@ -10035,7 +10095,7 @@ def _StarLine _save1 = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:\*{4,})/) + _tmp = scan(/\G(?-mix:\*{4,})/) if _tmp text = get_text(_text_start) end @@ -10065,7 +10125,7 @@ def _StarLine self.pos = _save3 break end - _tmp = scan(/\A(?-mix:\*+)/) + _tmp = scan(/\G(?-mix:\*+)/) unless _tmp self.pos = _save3 break @@ -10112,7 +10172,7 @@ def _UlLine _save1 = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:_{4,})/) + _tmp = scan(/\G(?-mix:_{4,})/) if _tmp text = get_text(_text_start) end @@ -10142,7 +10202,7 @@ def _UlLine self.pos = _save3 break end - _tmp = scan(/\A(?-mix:_+)/) + _tmp = scan(/\G(?-mix:_+)/) unless _tmp self.pos = _save3 break @@ -11503,7 +11563,7 @@ def _AutoLinkUrl _save1 = self.pos while true # sequence - _tmp = scan(/\A(?-mix:[A-Za-z]+)/) + _tmp = scan(/\G(?-mix:[A-Za-z]+)/) unless _tmp self.pos = _save1 break @@ -11628,7 +11688,7 @@ def _AutoLinkEmail _save2 = self.pos while true # sequence - _tmp = scan(/\A(?i-mx:[\w+.\/!%~$-]+)/) + _tmp = scan(/\G(?i-mx:[\w+.\/!%~$-]+)/) unless _tmp self.pos = _save2 break @@ -12492,7 +12552,7 @@ def _Code self.pos = _save10 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save10 end @@ -12629,7 +12689,7 @@ def _Code self.pos = _save24 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save24 end @@ -12806,7 +12866,7 @@ def _Code self.pos = _save40 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save40 end @@ -12943,7 +13003,7 @@ def _Code self.pos = _save54 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save54 end @@ -13120,7 +13180,7 @@ def _Code self.pos = _save70 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save70 end @@ -13257,7 +13317,7 @@ def _Code self.pos = _save84 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save84 end @@ -13434,7 +13494,7 @@ def _Code self.pos = _save100 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save100 end @@ -13571,7 +13631,7 @@ def _Code self.pos = _save114 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save114 end @@ -13748,7 +13808,7 @@ def _Code self.pos = _save130 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save130 end @@ -13885,7 +13945,7 @@ def _Code self.pos = _save144 break end - _tmp = scan(/\A(?-mix:`+)/) + _tmp = scan(/\G(?-mix:`+)/) unless _tmp self.pos = _save144 end @@ -14537,7 +14597,7 @@ def _SpecialChar _save = self.pos while true # choice - _tmp = scan(/\A(?-mix:[~*_`&\[\]() { text.strip } + def _TableItem + + _save = self.pos + while true # sequence + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + _text_start = self.pos + _save1 = self.pos + + _save2 = self.pos + while true # sequence + _save3 = self.pos + _tmp = match_string("|") + _tmp = _tmp ? nil : true + self.pos = _save3 + unless _tmp + self.pos = _save2 + break + end + _save4 = self.pos + _tmp = _Newline() + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save2 + break + end + _tmp = get_byte + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + if _tmp + while true + + _save5 = self.pos + while true # sequence + _save6 = self.pos + _tmp = match_string("|") + _tmp = _tmp ? nil : true + self.pos = _save6 + unless _tmp + self.pos = _save5 + break + end + _save7 = self.pos + _tmp = _Newline() + _tmp = _tmp ? nil : true + self.pos = _save7 + unless _tmp + self.pos = _save5 + break + end + _tmp = get_byte + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text.strip ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_TableItem unless _tmp + return _tmp + end + + # TableLine = TableColumn+:line "|" @Newline { line } + def _TableLine + + _save = self.pos + while true # sequence + _save1 = self.pos + _ary = [] + _tmp = apply(:_TableColumn) + if _tmp + _ary << @result + while true + _tmp = apply(:_TableColumn) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save1 + end + line = @result + unless _tmp + self.pos = _save + break + end + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + _tmp = _Newline() + unless _tmp + self.pos = _save + break + end + @result = begin; line ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_TableLine unless _tmp + return _tmp + end + + # TableColumn = "|" < ("-"+ ":"? | ":" "-"*) > { text.start_with?(":") ? :left : text.end_with?(":") ? :right : nil } + def _TableColumn + + _save = self.pos + while true # sequence + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + _text_start = self.pos + + _save1 = self.pos + while true # choice + + _save2 = self.pos + while true # sequence + _save3 = self.pos + _tmp = match_string("-") + if _tmp + while true + _tmp = match_string("-") + break unless _tmp + end + _tmp = true + else + self.pos = _save3 + end + unless _tmp + self.pos = _save2 + break + end + _save4 = self.pos + _tmp = match_string(":") + unless _tmp + _tmp = true + self.pos = _save4 + end + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save1 + + _save5 = self.pos + while true # sequence + _tmp = match_string(":") + unless _tmp + self.pos = _save5 + break + end + while true + _tmp = match_string("-") + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save5 + end + break + end # end sequence + + break if _tmp + self.pos = _save1 + break + end # end choice + + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text.start_with?(":") ? :left : + text.end_with?(":") ? :right : nil + ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_TableColumn unless _tmp + return _tmp + end + # DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten } def _DefinitionList @@ -16046,7 +16438,7 @@ def _DefinitionListDefinition Rules = {} Rules[:_root] = rule_info("root", "Doc") Rules[:_Doc] = rule_info("Doc", "BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }") - Rules[:_Block] = rule_info("Block", "@BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)") + Rules[:_Block] = rule_info("Block", "@BlankLine* (BlockQuote | Verbatim | CodeFence | Table | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)") Rules[:_Para] = rule_info("Para", "@NonindentSpace Inlines:a @BlankLine+ { paragraph a }") Rules[:_Plain] = rule_info("Plain", "Inlines:a { paragraph a }") Rules[:_AtxInline] = rule_info("AtxInline", "!@Newline !(@Sp /\#*/ @Sp @Newline) Inline") @@ -16190,7 +16582,7 @@ def _DefinitionListDefinition Rules[:_StyleClose] = rule_info("StyleClose", "\"<\" Spnl \"/\" (\"style\" | \"STYLE\") Spnl \">\"") Rules[:_InStyleTags] = rule_info("InStyleTags", "StyleOpen (!StyleClose .)* StyleClose") Rules[:_StyleBlock] = rule_info("StyleBlock", "< InStyleTags > @BlankLine* { if css? then RDoc::Markup::Raw.new text end }") - Rules[:_Inlines] = rule_info("Inlines", "(!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks }") + Rules[:_Inlines] = rule_info("Inlines", "(!@Endline Inline:i { i } | @Endline:c !(&{ github? } Ticks3 /[^`\\n]*$/) &Inline { c })+:chunks @Endline? { chunks }") Rules[:_Inline] = rule_info("Inline", "(Str | @Endline | UlOrStarLine | @Space | Strong | Emph | Strike | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)") Rules[:_Space] = rule_info("Space", "@Spacechar+ { \" \" }") Rules[:_Str] = rule_info("Str", "@StartList:a < @NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }") @@ -16279,6 +16671,11 @@ def _DefinitionListDefinition Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*") Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }") Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format.instance_of?(String) verbatim }") + Rules[:_Table] = rule_info("Table", "&{ github? } TableRow:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }") + Rules[:_TableRow] = rule_info("TableRow", "TableItem+:row \"|\" @Newline { row }") + Rules[:_TableItem] = rule_info("TableItem", "\"|\" < (!\"|\" !@Newline .)+ > { text.strip }") + Rules[:_TableLine] = rule_info("TableLine", "TableColumn+:line \"|\" @Newline { line }") + Rules[:_TableColumn] = rule_info("TableColumn", "\"|\" < (\"-\"+ \":\"? | \":\" \"-\"*) > { text.start_with?(\":\") ? :left : text.end_with?(\":\") ? :right : nil }") Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }") Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }") Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }") diff --git a/ruby/lib/rdoc/markdown/literals.rb b/ruby/lib/rdoc/markdown/literals.rb index 31cd237f1..943c2d268 100644 --- a/ruby/lib/rdoc/markdown/literals.rb +++ b/ruby/lib/rdoc/markdown/literals.rb @@ -174,9 +174,8 @@ def match_string(str) end def scan(reg) - if m = reg.match(@string[@pos..-1]) - width = m.end(0) - @pos += width + if m = reg.match(@string, @pos) + @pos = m.end(0) return true end @@ -366,14 +365,14 @@ def setup_foreign_grammar; end # Alphanumeric = /\p{Word}/ def _Alphanumeric - _tmp = scan(/\A(?-mix:\p{Word})/) + _tmp = scan(/\G(?-mix:\p{Word})/) set_failed_rule :_Alphanumeric unless _tmp return _tmp end # AlphanumericAscii = /[A-Za-z0-9]/ def _AlphanumericAscii - _tmp = scan(/\A(?-mix:[A-Za-z0-9])/) + _tmp = scan(/\G(?-mix:[A-Za-z0-9])/) set_failed_rule :_AlphanumericAscii unless _tmp return _tmp end @@ -387,21 +386,21 @@ def _BOM # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ def _Newline - _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/) + _tmp = scan(/\G(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/) set_failed_rule :_Newline unless _tmp return _tmp end # NonAlphanumeric = /\p{^Word}/ def _NonAlphanumeric - _tmp = scan(/\A(?-mix:\p{^Word})/) + _tmp = scan(/\G(?-mix:\p{^Word})/) set_failed_rule :_NonAlphanumeric unless _tmp return _tmp end # Spacechar = /\t|\p{Zs}/ def _Spacechar - _tmp = scan(/\A(?-mix:\t|\p{Zs})/) + _tmp = scan(/\G(?-mix:\t|\p{Zs})/) set_failed_rule :_Spacechar unless _tmp return _tmp end diff --git a/ruby/lib/rdoc/markup.rb b/ruby/lib/rdoc/markup.rb index fd59fca31..92aed757c 100644 --- a/ruby/lib/rdoc/markup.rb +++ b/ruby/lib/rdoc/markup.rb @@ -843,6 +843,7 @@ def convert input, formatter autoload :List, 'rdoc/markup/list' autoload :ListItem, 'rdoc/markup/list_item' autoload :Paragraph, 'rdoc/markup/paragraph' + autoload :Table, 'rdoc/markup/table' autoload :Raw, 'rdoc/markup/raw' autoload :Rule, 'rdoc/markup/rule' autoload :Verbatim, 'rdoc/markup/verbatim' diff --git a/ruby/lib/rdoc/markup/attr_span.rb b/ruby/lib/rdoc/markup/attr_span.rb index 63aace60d..20ef11cd6 100644 --- a/ruby/lib/rdoc/markup/attr_span.rb +++ b/ruby/lib/rdoc/markup/attr_span.rb @@ -7,16 +7,22 @@ class RDoc::Markup::AttrSpan ## # Creates a new AttrSpan for +length+ characters - def initialize(length) + def initialize(length, exclusive) @attrs = Array.new(length, 0) + @exclusive = exclusive end ## # Toggles +bits+ from +start+ to +length+ def set_attrs(start, length, bits) + updated = false for i in start ... (start+length) - @attrs[i] |= bits + if (@exclusive & @attrs[i]) == 0 || (@exclusive & bits) != 0 + @attrs[i] |= bits + updated = true + end end + updated end ## diff --git a/ruby/lib/rdoc/markup/attribute_manager.rb b/ruby/lib/rdoc/markup/attribute_manager.rb index f052bc8b0..50764510f 100644 --- a/ruby/lib/rdoc/markup/attribute_manager.rb +++ b/ruby/lib/rdoc/markup/attribute_manager.rb @@ -58,6 +58,10 @@ class RDoc::Markup::AttributeManager attr_reader :regexp_handlings + ## + # A bits of exclusive maps + attr_reader :exclusive_bitmap + ## # Creates a new attribute manager that understands bold, emphasized and # teletype text. @@ -68,17 +72,18 @@ def initialize @protectable = %w[<] @regexp_handlings = [] @word_pair_map = {} + @exclusive_bitmap = 0 @attributes = RDoc::Markup::Attributes.new - add_word_pair "*", "*", :BOLD - add_word_pair "_", "_", :EM - add_word_pair "+", "+", :TT + add_word_pair "*", "*", :BOLD, true + add_word_pair "_", "_", :EM, true + add_word_pair "+", "+", :TT, true - add_html "em", :EM - add_html "i", :EM - add_html "b", :BOLD - add_html "tt", :TT - add_html "code", :TT + add_html "em", :EM, true + add_html "i", :EM, true + add_html "b", :BOLD, true + add_html "tt", :TT, true + add_html "code", :TT, true end ## @@ -122,29 +127,67 @@ def copy_string(start_pos, end_pos) res end + def exclusive?(attr) + (attr & @exclusive_bitmap) != 0 + end + + NON_PRINTING_START = "\1" # :nodoc: + NON_PRINTING_END = "\2" # :nodoc: + ## # Map attributes like textto the sequence # \001\002\001\003, where is a per-attribute specific # character - def convert_attrs(str, attrs) + def convert_attrs(str, attrs, exclusive = false) + convert_attrs_matching_word_pairs(str, attrs, exclusive) + convert_attrs_word_pair_map(str, attrs, exclusive) + end + + def convert_attrs_matching_word_pairs(str, attrs, exclusive) # first do matching ones - tags = @matching_word_pairs.keys.join("") + tags = @matching_word_pairs.select { |start, bitmap| + if exclusive && exclusive?(bitmap) + true + elsif !exclusive && !exclusive?(bitmap) + true + else + false + end + }.keys + return if tags.empty? + all_tags = @matching_word_pairs.keys - re = /(^|\W)([#{tags}])([#\\]?[\w:.\/-]+?\S?)\2(\W|$)/ + re = /(^|\W|[#{all_tags.join("")}])([#{tags.join("")}])(\2*[#\\]?[\w:.\/\[\]-]+?\S?)\2(?!\2)([#{all_tags.join("")}]|\W|$)/ - 1 while str.gsub!(re) do + 1 while str.gsub!(re) { |orig| attr = @matching_word_pairs[$2] - attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) - $1 + NULL * $2.length + $3 + NULL * $2.length + $4 - end + attr_updated = attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) + if attr_updated + $1 + NULL * $2.length + $3 + NULL * $2.length + $4 + else + $1 + NON_PRINTING_START + $2 + NON_PRINTING_END + $3 + NON_PRINTING_START + $2 + NON_PRINTING_END + $4 + end + } + str.delete!(NON_PRINTING_START + NON_PRINTING_END) + end + def convert_attrs_word_pair_map(str, attrs, exclusive) # then non-matching unless @word_pair_map.empty? then @word_pair_map.each do |regexp, attr| - str.gsub!(regexp) { - attrs.set_attrs($`.length + $1.length, $2.length, attr) - NULL * $1.length + $2 + NULL * $3.length + if !exclusive + next if exclusive?(attr) + else + next if !exclusive?(attr) + end + 1 while str.gsub!(regexp) { |orig| + updated = attrs.set_attrs($`.length + $1.length, $2.length, attr) + if updated + NULL * $1.length + $2 + NULL * $3.length + else + orig + end } end end @@ -153,10 +196,18 @@ def convert_attrs(str, attrs) ## # Converts HTML tags to RDoc attributes - def convert_html(str, attrs) - tags = @html_tags.keys.join '|' + def convert_html(str, attrs, exclusive = false) + tags = @html_tags.select { |start, bitmap| + if exclusive && exclusive?(bitmap) + true + elsif !exclusive && !exclusive?(bitmap) + true + else + false + end + }.keys.join '|' - 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { + 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { |orig| attr = @html_tags[$1.downcase] html_length = $1.length + 2 seq = NULL * html_length @@ -168,8 +219,13 @@ def convert_html(str, attrs) ## # Converts regexp handling sequences to RDoc attributes - def convert_regexp_handlings str, attrs + def convert_regexp_handlings str, attrs, exclusive = false @regexp_handlings.each do |regexp, attribute| + if exclusive + next if !exclusive?(attribute) + else + next if exclusive?(attribute) + end str.scan(regexp) do capture = $~.size == 1 ? 0 : 1 @@ -205,7 +261,7 @@ def unmask_protected_sequences # # am.add_word_pair '*', '*', :BOLD - def add_word_pair(start, stop, name) + def add_word_pair(start, stop, name, exclusive = false) raise ArgumentError, "Word flags may not start with '<'" if start[0,1] == '<' @@ -220,6 +276,8 @@ def add_word_pair(start, stop, name) @protectable << start[0,1] @protectable.uniq! + + @exclusive_bitmap |= bitmap if exclusive end ## @@ -228,8 +286,10 @@ def add_word_pair(start, stop, name) # # am.add_html 'em', :EM - def add_html(tag, name) - @html_tags[tag.downcase] = @attributes.bitmap_for name + def add_html(tag, name, exclusive = false) + bitmap = @attributes.bitmap_for name + @html_tags[tag.downcase] = bitmap + @exclusive_bitmap |= bitmap if exclusive end ## @@ -238,8 +298,10 @@ def add_html(tag, name) # # @am.add_regexp_handling(/((https?:)\S+\w)/, :HYPERLINK) - def add_regexp_handling pattern, name - @regexp_handlings << [pattern, @attributes.bitmap_for(name)] + def add_regexp_handling pattern, name, exclusive = false + bitmap = @attributes.bitmap_for(name) + @regexp_handlings << [pattern, bitmap] + @exclusive_bitmap |= bitmap if exclusive end ## @@ -250,8 +312,11 @@ def flow str mask_protected_sequences - @attrs = RDoc::Markup::AttrSpan.new @str.length + @attrs = RDoc::Markup::AttrSpan.new @str.length, @exclusive_bitmap + convert_attrs @str, @attrs, true + convert_html @str, @attrs, true + convert_regexp_handlings @str, @attrs, true convert_attrs @str, @attrs convert_html @str, @attrs convert_regexp_handlings @str, @attrs diff --git a/ruby/lib/rdoc/markup/formatter.rb b/ruby/lib/rdoc/markup/formatter.rb index 6dff96c7d..2bac76e83 100644 --- a/ruby/lib/rdoc/markup/formatter.rb +++ b/ruby/lib/rdoc/markup/formatter.rb @@ -156,7 +156,7 @@ def convert_regexp_handling target method_name = "handle_regexp_#{name}" if respond_to? method_name then - target.text = send method_name, target + target.text = public_send method_name, target handled = true end end diff --git a/ruby/lib/rdoc/markup/pre_process.rb b/ruby/lib/rdoc/markup/pre_process.rb index d9e0dcac1..88078c9ce 100644 --- a/ruby/lib/rdoc/markup/pre_process.rb +++ b/ruby/lib/rdoc/markup/pre_process.rb @@ -163,6 +163,8 @@ def handle_directive prefix, directive, param, code_object = nil, if RDoc::Context === code_object then section = code_object.add_section param code_object.temporary_section = section + elsif RDoc::AnyMethod === code_object then + code_object.section_title = param end blankline # ignore category if we're not on an RDoc::Context @@ -178,7 +180,7 @@ def handle_directive prefix, directive, param, code_object = nil, blankline when 'include' then - filename = param.split.first + filename = param.split(' ', 2).first include_file filename, prefix, encoding when 'main' then @options.main_page = param if @options.respond_to? :main_page diff --git a/ruby/lib/rdoc/markup/table.rb b/ruby/lib/rdoc/markup/table.rb new file mode 100644 index 000000000..7bcb10aff --- /dev/null +++ b/ruby/lib/rdoc/markup/table.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true +## +# A section of table + +class RDoc::Markup::Table + attr_accessor :header, :align, :body + + def initialize header, align, body + @header, @align, @body = header, align, body + end + + def == other + self.class == other.class and + @header == other.header and + @align == other.align and + @body == other.body + end + + def accept visitor + visitor.accept_table @header, @body, @align + end + + def pretty_print q # :nodoc: + q.group 2, '[Table: ', ']' do + q.group 2, '[Head: ', ']' do + q.seplist @header.zip(@align) do |text, align| + q.pp text + if align + q.text ":" + q.breakable + q.text align.to_s + end + end + end + q.breakable + q.group 2, '[Body: ', ']' do + q.seplist @body do |body| + q.group 2, '[', ']' do + q.seplist body do |text| + q.pp text + end + end + end + end + end + end +end diff --git a/ruby/lib/rdoc/markup/to_html.rb b/ruby/lib/rdoc/markup/to_html.rb index 9ae0fff8a..d3bb8af83 100644 --- a/ruby/lib/rdoc/markup/to_html.rb +++ b/ruby/lib/rdoc/markup/to_html.rb @@ -52,12 +52,7 @@ def initialize options, markup = nil @th = nil @hard_break = "
\n" - # external links - @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/, - :HYPERLINK) - - add_regexp_handling_RDOCLINK - add_regexp_handling_TIDYLINK + init_regexp_handlings init_tags end @@ -66,6 +61,24 @@ def initialize options, markup = nil # # These methods are used by regexp handling markup added by RDoc::Markup#add_regexp_handling. + ## + # Adds regexp handlings. + + def init_regexp_handlings + # external links + @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/, + :HYPERLINK) + init_link_notation_regexp_handlings + end + + ## + # Adds regexp handlings about link notations. + + def init_link_notation_regexp_handlings + add_regexp_handling_RDOCLINK + add_regexp_handling_TIDYLINK + end + def handle_RDOCLINK url # :nodoc: case url when /^rdoc-ref:/ @@ -301,6 +314,29 @@ def accept_raw raw @res << raw.parts.join("\n") end + ## + # Adds +table+ to the output + + def accept_table header, body, aligns + @res << "\n\n\n\n" + header.zip(aligns) do |text, align| + @res << '' << CGI.escapeHTML(text) << "\n" + end + @res << "\n\n\n" + body.each do |row| + @res << "\n" + row.zip(aligns) do |text, align| + @res << '' << CGI.escapeHTML(text) << "\n" + end + @res << "\n" + end + @res << "\n
\n" + end + # :section: Utilities ## @@ -321,6 +357,10 @@ def gen_url url, text url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then "" else + if scheme != 'link' and %r%\A((?!https?:)(?:[^/#]*/)*+)([^/#]+)\.(rb|rdoc|md)(?=\z|#)%i =~ url + url = "#$1#{$2.tr('.', '_')}_#$3.html#$'" + end + text = text.sub %r%^#{scheme}:/*%i, '' text = text.sub %r%^[*\^](\d+)$%, '\1' diff --git a/ruby/lib/rdoc/markup/to_html_crossref.rb b/ruby/lib/rdoc/markup/to_html_crossref.rb index 9314f04fa..a9fd09df4 100644 --- a/ruby/lib/rdoc/markup/to_html_crossref.rb +++ b/ruby/lib/rdoc/markup/to_html_crossref.rb @@ -39,10 +39,18 @@ def initialize(options, from_path, context, markup = nil) @hyperlink_all = @options.hyperlink_all @show_hash = @options.show_hash - crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP + @cross_reference = RDoc::CrossReference.new @context + end + + def init_link_notation_regexp_handlings + add_regexp_handling_RDOCLINK + + # The crossref must be linked before tidylink because Klass.method[:sym] + # will be processed as a tidylink first and will be broken. + crossref_re = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP @markup.add_regexp_handling crossref_re, :CROSSREF - @cross_reference = RDoc::CrossReference.new @context + add_regexp_handling_TIDYLINK end ## @@ -54,7 +62,7 @@ def cross_reference name, text = nil, code = true name = name[1..-1] unless @show_hash if name[0, 1] == '#' - if name =~ /(.*[^#:])@/ + if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/ text ||= "#{CGI.unescape $'} at #{$1}" code = false else @@ -130,7 +138,7 @@ def gen_url url, text # Creates an HTML link to +name+ with the given +text+. def link name, text, code = true - if name =~ /(.*[^#:])@/ then + if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/ name = $1 label = $' end @@ -144,7 +152,7 @@ def link name, text, code = true path = ref.as_href @from_path if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref) - text = "#{text}" + text = "#{CGI.escapeHTML text}" end if path =~ /#/ then diff --git a/ruby/lib/rdoc/markup/to_joined_paragraph.rb b/ruby/lib/rdoc/markup/to_joined_paragraph.rb index 795f3f62e..46e07c94a 100644 --- a/ruby/lib/rdoc/markup/to_joined_paragraph.rb +++ b/ruby/lib/rdoc/markup/to_joined_paragraph.rb @@ -41,6 +41,7 @@ def accept_paragraph paragraph alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore + alias accept_table ignore end diff --git a/ruby/lib/rdoc/markup/to_rdoc.rb b/ruby/lib/rdoc/markup/to_rdoc.rb index 81b16c497..3cdf4fd08 100644 --- a/ruby/lib/rdoc/markup/to_rdoc.rb +++ b/ruby/lib/rdoc/markup/to_rdoc.rb @@ -237,6 +237,34 @@ def accept_verbatim verbatim @res << "\n" end + ## + # Adds +table+ to the output + + def accept_table header, body, aligns + widths = header.zip(body) do |h, b| + [h.size, b.size].max + end + aligns = aligns.map do |a| + case a + when nil + :center + when :left + :ljust + when :right + :rjust + end + end + @res << header.zip(widths, aligns) do |h, w, a| + h.__send__(a, w) + end.join("|").rstrip << "\n" + @res << widths.map {|w| "-" * w }.join("|") << "\n" + body.each do |row| + @res << row.zip(widths, aligns) do |t, w, a| + t.__send__(a, w) + end.join("|").rstrip << "\n" + end + end + ## # Applies attribute-specific markup to +text+ using RDoc::AttributeManager diff --git a/ruby/lib/rdoc/markup/to_table_of_contents.rb b/ruby/lib/rdoc/markup/to_table_of_contents.rb index f68b90bcf..eb8e8faa1 100644 --- a/ruby/lib/rdoc/markup/to_table_of_contents.rb +++ b/ruby/lib/rdoc/markup/to_table_of_contents.rb @@ -82,6 +82,7 @@ def suppressed? heading alias accept_list_item_end ignore alias accept_list_end_bullet ignore alias accept_list_start ignore + alias accept_table ignore # :startdoc: end diff --git a/ruby/lib/rdoc/options.rb b/ruby/lib/rdoc/options.rb index 43494c85b..792b473b7 100644 --- a/ruby/lib/rdoc/options.rb +++ b/ruby/lib/rdoc/options.rb @@ -338,8 +338,9 @@ class RDoc::Options attr_reader :visibility - def initialize # :nodoc: + def initialize loaded_options = nil # :nodoc: init_ivars + override loaded_options if loaded_options end def init_ivars # :nodoc: @@ -417,6 +418,37 @@ def yaml_initialize tag, map # :nodoc: init_with map end + def override map # :nodoc: + if map.has_key?('encoding') + encoding = map['encoding'] + @encoding = encoding ? Encoding.find(encoding) : encoding + end + + @charset = map['charset'] if map.has_key?('charset') + @exclude = map['exclude'] if map.has_key?('exclude') + @generator_name = map['generator_name'] if map.has_key?('generator_name') + @hyperlink_all = map['hyperlink_all'] if map.has_key?('hyperlink_all') + @line_numbers = map['line_numbers'] if map.has_key?('line_numbers') + @locale_name = map['locale_name'] if map.has_key?('locale_name') + @locale_dir = map['locale_dir'] if map.has_key?('locale_dir') + @main_page = map['main_page'] if map.has_key?('main_page') + @markup = map['markup'] if map.has_key?('markup') + @op_dir = map['op_dir'] if map.has_key?('op_dir') + @show_hash = map['show_hash'] if map.has_key?('show_hash') + @tab_width = map['tab_width'] if map.has_key?('tab_width') + @template_dir = map['template_dir'] if map.has_key?('template_dir') + @title = map['title'] if map.has_key?('title') + @visibility = map['visibility'] if map.has_key?('visibility') + @webcvs = map['webcvs'] if map.has_key?('webcvs') + + if map.has_key?('rdoc_include') + @rdoc_include = sanitize_path map['rdoc_include'] + end + if map.has_key?('static_path') + @static_path = sanitize_path map['static_path'] + end + end + def == other # :nodoc: self.class === other and @encoding == other.encoding and @@ -755,7 +787,7 @@ def parse argv opt.on("--[no-]force-update", "-U", "Forces rdoc to scan all sources even if", - "newer than the flag file.") do |value| + "no files are newer than the flag file.") do |value| @force_update = value end @@ -939,7 +971,7 @@ def parse argv opt.on("--template-stylesheets=FILES", PathArray, "Set (or add to) the list of files to", "include with the html template.") do |value| - @template_stylesheets << value + @template_stylesheets.concat value end opt.separator nil @@ -1250,4 +1282,33 @@ def write_options end end + ## + # Loads options from .rdoc_options if the file exists, otherwise creates a + # new RDoc::Options instance. + + def self.load_options + options_file = File.expand_path '.rdoc_options' + return RDoc::Options.new unless File.exist? options_file + + RDoc.load_yaml + + begin + options = YAML.safe_load File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol] + rescue Psych::SyntaxError + raise RDoc::Error, "#{options_file} is not a valid rdoc options file" + end + + return RDoc::Options.new unless options # Allow empty file. + + raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless + RDoc::Options === options or Hash === options + + if Hash === options + # Override the default values with the contents of YAML file. + options = RDoc::Options.new options + end + + options + end + end diff --git a/ruby/lib/rdoc/parser.rb b/ruby/lib/rdoc/parser.rb index 597bcd6b9..425bc4863 100644 --- a/ruby/lib/rdoc/parser.rb +++ b/ruby/lib/rdoc/parser.rb @@ -78,7 +78,7 @@ def self.binary?(file) return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00") - mode = 'r:utf-8' # default source encoding has been chagened to utf-8 + mode = 'r:utf-8' # default source encoding has been changed to utf-8 s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024. encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1] mode = "rb:#{encoding}" if encoding @@ -269,9 +269,9 @@ def initialize top_level, file_name, content, options, stats end # simple must come first in order to show up last in the parsers list -require 'rdoc/parser/simple' -require 'rdoc/parser/c' -require 'rdoc/parser/changelog' -require 'rdoc/parser/markdown' -require 'rdoc/parser/rd' -require 'rdoc/parser/ruby' +require_relative 'parser/simple' +require_relative 'parser/c' +require_relative 'parser/changelog' +require_relative 'parser/markdown' +require_relative 'parser/rd' +require_relative 'parser/ruby' diff --git a/ruby/lib/rdoc/parser/c.rb b/ruby/lib/rdoc/parser/c.rb index 826571237..b89aaa6dc 100644 --- a/ruby/lib/rdoc/parser/c.rb +++ b/ruby/lib/rdoc/parser/c.rb @@ -173,6 +173,8 @@ def initialize top_level, file_name, content, options, stats @classes = load_variable_map :c_class_variables @singleton_classes = load_variable_map :c_singleton_class_variables + @markup = @options.markup + # class_variable => { function => [method, ...] } @methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } } @@ -209,48 +211,6 @@ def @enclosure_dependencies.tsort_each_child node, &block end end - ## - # Removes duplicate call-seq entries for methods using the same - # implementation. - - def deduplicate_call_seq - @methods.each do |var_name, functions| - class_name = @known_classes[var_name] - next unless class_name - class_obj = find_class var_name, class_name - - functions.each_value do |method_names| - next if method_names.length == 1 - - method_names.each do |method_name| - deduplicate_method_name class_obj, method_name - end - end - end - end - - ## - # If two ruby methods share a C implementation (and comment) this - # deduplicates the examples in the call_seq for the method to reduce - # confusion in the output. - - def deduplicate_method_name class_obj, method_name # :nodoc: - return unless - method = class_obj.method_list.find { |m| m.name == method_name } - return unless call_seq = method.call_seq - - method_name = method_name[0, 1] if method_name =~ /\A\[/ - - entries = call_seq.split "\n" - - matching = entries.select do |entry| - entry =~ /^\w*\.?#{Regexp.escape method_name}/ or - entry =~ /\s#{Regexp.escape method_name}\s/ - end - - method.call_seq = matching.join "\n" - end - ## # Scans #content for rb_define_alias @@ -269,23 +229,29 @@ def do_aliases end class_obj = find_class var_name, class_name - - al = RDoc::Alias.new '', old_name, new_name, '' - al.singleton = @singleton_classes.key? var_name - comment = find_alias_comment var_name, new_name, old_name - comment.normalize - - al.comment = comment - - al.record_location @top_level - - class_obj.add_alias al - @stats.add_alias al + if comment.to_s.empty? and existing_method = class_obj.method_list.find { |m| m.name == old_name} + comment = existing_method.comment + end + add_alias(var_name, class_obj, old_name, new_name, comment) end end + ## + # Add alias, either from a direct alias definition, or from two + # method that reference the same function. + + def add_alias(var_name, class_obj, old_name, new_name, comment) + al = RDoc::Alias.new '', old_name, new_name, '' + al.singleton = @singleton_classes.key? var_name + al.comment = comment + al.record_location @top_level + class_obj.add_alias al + @stats.add_alias al + al + end + ## # Scans #content for rb_attr and rb_define_attr @@ -354,7 +320,7 @@ def do_classes_and_modules \s*"(?\w+)"\s* \) | - _under\s*\( # rb_define_module_under(module_under, module_name_1) + _under\s*\( # rb_define_module_under(module_under, module_name_2) \s*(?\w+), \s*"(?\w+)" \s*\) @@ -475,7 +441,7 @@ def do_includes next unless cls = @classes[c] m = @known_classes[m] || m - comment = RDoc::Comment.new '', @top_level, :c + comment = new_comment '', @top_level, :c incl = cls.add_include RDoc::Include.new(m, comment) incl.record_location @top_level end @@ -557,7 +523,7 @@ def find_alias_comment class_name, new_name, old_name \s*"#{Regexp.escape new_name}"\s*, \s*"#{Regexp.escape old_name}"\s*\);%xm - RDoc::Comment.new($1 || '', @top_level, :c) + new_comment($1 || '', @top_level, :c) end ## @@ -596,7 +562,7 @@ def find_attr_comment var_name, attr_name, read = nil, write = nil '' end - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -608,7 +574,7 @@ def gen_body_table file_content ((?>/\*.*?\*/\s*)?) ((?:(?:\w+)\s+)? (?:intern\s+)?VALUE\s+(\w+) - \s*(?:\([^)]*\))(?:[^;]|$)) + \s*(?:\([^)]*\))(?:[^\);]|$)) | ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+)) | ^\s*\#\s*define\s+(\w+)\s+(\w+) }xm) do @@ -636,7 +602,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false case type when :func_def - comment = RDoc::Comment.new args[0], @top_level, :c + comment = new_comment args[0], @top_level, :c body = args[1] offset, = args[2] @@ -666,7 +632,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false body when :macro_def - comment = RDoc::Comment.new args[0], @top_level, :c + comment = new_comment args[0], @top_level, :c body = args[1] offset, = args[2] @@ -773,7 +739,7 @@ def find_class_comment class_name, class_mod comment = '' end - comment = RDoc::Comment.new comment, @top_level, :c + comment = new_comment comment, @top_level, :c comment.normalize look_for_directives_in class_mod, comment @@ -818,7 +784,7 @@ def find_const_comment(type, const_name, class_name = nil) table[const_name] || '' - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -849,7 +815,7 @@ def find_override_comment class_name, meth_obj return unless comment - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -983,7 +949,7 @@ def handle_constants(type, var_name, const_name, definition) new_comment = "#{$1}#{new_comment.lstrip}" - new_comment = RDoc::Comment.new new_comment, @top_level, :c + new_comment = self.new_comment(new_comment, @top_level, :c) con = RDoc::Constant.new const_name, new_definition, new_comment else @@ -1021,6 +987,10 @@ def handle_method(type, var_name, meth_name, function, param_count, class_obj = find_class var_name, class_name + if existing_method = class_obj.method_list.find { |m| m.c_function == function } + add_alias(var_name, class_obj, existing_method.name, meth_name, existing_method.comment) + end + if class_obj then if meth_name == 'initialize' then meth_name = 'new' @@ -1060,7 +1030,12 @@ def handle_method(type, var_name, meth_name, function, param_count, meth_obj.record_location @top_level + + if meth_obj.section_title + class_obj.temporary_section = class_obj.add_section(meth_obj.section_title) + end class_obj.add_method meth_obj + @stats.add_method meth_obj meth_obj.visibility = :private if 'private_method' == type end @@ -1249,11 +1224,14 @@ def scan do_aliases do_attrs - deduplicate_call_seq - @store.add_c_variables self @top_level end + def new_comment text = nil, location = nil, language = nil + RDoc::Comment.new(text, location, language).tap do |comment| + comment.format = @markup + end + end end diff --git a/ruby/lib/rdoc/parser/changelog.rb b/ruby/lib/rdoc/parser/changelog.rb index 167892f54..9245d4937 100644 --- a/ruby/lib/rdoc/parser/changelog.rb +++ b/ruby/lib/rdoc/parser/changelog.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'time' ## # A ChangeLog file parser. @@ -106,14 +105,32 @@ def group_entries entries entries.group_by do |title, _| begin time = @time_cache[title] - (time || Time.parse(title)).strftime '%Y-%m-%d' + (time || parse_date(title)).strftime '%Y-%m-%d' rescue NoMethodError, ArgumentError time, = title.split ' ', 2 - Time.parse(time).strftime '%Y-%m-%d' + parse_date(time).strftime '%Y-%m-%d' end end end + ## + # Parse date in ISO-8601, RFC-2822, or default of Git + + def parse_date(date) + case date + when /\A\s*(\d+)-(\d+)-(\d+)(?:[ T](\d+):(\d+):(\d+) *([-+]\d\d):?(\d\d))?\b/ + Time.new($1, $2, $3, $4, $5, $6, ("#{$7}:#{$8}" if $7)) + when /\A\s*\w{3}, +(\d+) (\w{3}) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/ + Time.new($3, $2, $1, $4, $5, $6, ("#{$7}:#{$8}" if $7)) + when /\A\s*\w{3} (\w{3}) +(\d+) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/ + Time.new($3, $1, $2, $4, $5, $6, ("#{$7}:#{$8}" if $7)) + when /\A\s*\w{3} (\w{3}) +(\d+) (\d+):(\d+):(\d+) (\d+)\b/ + Time.new($6, $1, $2, $3, $4, $5) + else + raise ArgumentError, "bad date: #{date}" + end + end + ## # Parses the entries in the ChangeLog. # @@ -131,6 +148,13 @@ def group_entries entries def parse_entries @time_cache ||= {} + + if /\A((?:.*\n){,3})commit\s/ =~ @content + class << self; prepend Git; end + parse_info($1) + return parse_entries + end + entries = [] entry_name = nil entry_body = [] @@ -145,19 +169,10 @@ def parse_entries entry_name = $& begin - time = Time.parse entry_name + time = parse_date entry_name @time_cache[entry_name] = time - # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other" - entry_name = nil unless entry_name =~ /#{time.year}/ - rescue NoMethodError - # HACK Ruby 2.1.2 and earlier raises NoMethodError if time part is absent - entry_name.split ' ', 2 rescue ArgumentError - if /out of range/ =~ $!.message - Time.parse(entry_name.split(' ', 2)[0]) rescue entry_name = nil - else - entry_name = nil - end + entry_name = nil end entry_body = [] @@ -190,6 +205,7 @@ def parse_entries def scan @time_cache = {} + entries = parse_entries grouped_entries = group_entries entries @@ -200,5 +216,120 @@ def scan @top_level end + module Git + def parse_info(info) + /^\s*base-url\s*=\s*(.*\S)/ =~ info + @base_url = $1 + end + + def parse_entries + entries = [] + + @content.scan(/^commit\s+(\h{20})\h*\n((?:.+\n)*)\n((?: {4}.*\n+)*)/) do + entry_name, header, entry_body = $1, $2, $3.gsub(/^ {4}/, '') + # header = header.scan(/^ *(\S+?): +(.*)/).to_h + # date = header["CommitDate"] || header["Date"] + date = header[/^ *(?:Author)?Date: +(.*)/, 1] + author = header[/^ *Author: +(.*)/, 1] + begin + time = parse_date(header[/^ *CommitDate: +(.*)/, 1] || date) + @time_cache[entry_name] = time + author.sub!(/\s*<(.*)>/, '') + email = $1 + entries << [entry_name, [author, email, date, entry_body]] + rescue ArgumentError + end + end + + entries + end + + def create_entries entries + # git log entries have no strictly itemized style like the old + # style, just assume Markdown. + entries.map do |commit, entry| + LogEntry.new(@base_url, commit, *entry) + end + end + + LogEntry = Struct.new(:base, :commit, :author, :email, :date, :contents) do + HEADING_LEVEL = 3 + + def initialize(base, commit, author, email, date, contents) + case contents + when String + contents = RDoc::Markdown.parse(contents).parts.each do |body| + case body + when RDoc::Markup::Heading + body.level += HEADING_LEVEL + 1 + end + end + case first = contents[0] + when RDoc::Markup::Paragraph + contents[0] = RDoc::Markup::Heading.new(HEADING_LEVEL + 1, first.text) + end + end + super + end + + def level + HEADING_LEVEL + end + + def aref + "label-#{commit}" + end + + def label context = nil + aref + end + + def text + case base + when nil + "#{date}" + when /%s/ + "{#{date}}[#{base % commit}]" + else + "{#{date}}[#{base}#{commit}]" + end + " {#{author}}[mailto:#{email}]" + end + + def accept visitor + visitor.accept_heading self + begin + if visitor.respond_to?(:code_object=) + code_object = visitor.code_object + visitor.code_object = self + end + contents.each do |body| + body.accept visitor + end + ensure + if visitor.respond_to?(:code_object) + visitor.code_object = code_object + end + end + end + + def pretty_print q # :nodoc: + q.group(2, '[log_entry: ', ']') do + q.text commit + q.text ',' + q.breakable + q.group(2, '[date: ', ']') { q.text date } + q.text ',' + q.breakable + q.group(2, '[author: ', ']') { q.text author } + q.text ',' + q.breakable + q.group(2, '[email: ', ']') { q.text email } + q.text ',' + q.breakable + q.pp contents + end + end + end + end end diff --git a/ruby/lib/rdoc/parser/ruby.rb b/ruby/lib/rdoc/parser/ruby.rb index 8d021f3c6..e546fe214 100644 --- a/ruby/lib/rdoc/parser/ruby.rb +++ b/ruby/lib/rdoc/parser/ruby.rb @@ -1193,6 +1193,22 @@ def parse_extend_or_include klass, container, comment # :nodoc: end end + ## + # Parses an +included+ with a block feature of ActiveSupport::Concern. + + def parse_included_with_activesupport_concern container, comment # :nodoc: + skip_tkspace_without_nl + tk = get_tk + unless tk[:kind] == :on_lbracket || (tk[:kind] == :on_kw && tk[:text] == 'do') + unget_tk tk + return nil # should be a block + end + + parse_statements container + + container + end + ## # Parses identifiers that can create new methods or change visibility. # @@ -1893,6 +1909,8 @@ def parse_statements(container, single = NORMAL, current_method = nil, parse_extend_or_include RDoc::Include, container, comment when "extend" then parse_extend_or_include RDoc::Extend, container, comment + when "included" then + parse_included_with_activesupport_concern container, comment end else diff --git a/ruby/lib/rdoc/rd/block_parser.rb b/ruby/lib/rdoc/rd/block_parser.rb index be0b786bf..462ba869a 100644 --- a/ruby/lib/rdoc/rd/block_parser.rb +++ b/ruby/lib/rdoc/rd/block_parser.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.16 +# This file is automatically generated by Racc 1.5.2 # from Racc grammar file "". # diff --git a/ruby/lib/rdoc/rd/inline_parser.rb b/ruby/lib/rdoc/rd/inline_parser.rb index a64102cac..8f4c2c31e 100644 --- a/ruby/lib/rdoc/rd/inline_parser.rb +++ b/ruby/lib/rdoc/rd/inline_parser.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.16 +# This file is automatically generated by Racc 1.5.2 # from Racc grammar file "". # diff --git a/ruby/lib/rdoc/rdoc.gemspec b/ruby/lib/rdoc/rdoc.gemspec index 9b274c709..525a15fcd 100644 --- a/ruby/lib/rdoc/rdoc.gemspec +++ b/ruby/lib/rdoc/rdoc.gemspec @@ -166,6 +166,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat "lib/rdoc/markup/raw.rb", "lib/rdoc/markup/regexp_handling.rb", "lib/rdoc/markup/rule.rb", + "lib/rdoc/markup/table.rb", "lib/rdoc/markup/to_ansi.rb", "lib/rdoc/markup/to_bs.rb", "lib/rdoc/markup/to_html.rb", @@ -221,6 +222,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat "lib/rdoc/tom_doc.rb", "lib/rdoc/top_level.rb", "lib/rdoc/version.rb", + "man/ri.1", "rdoc.gemspec", ] # files from .gitignore @@ -240,7 +242,8 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat TODO.rdoc ] - s.required_ruby_version = Gem::Requirement.new(">= 2.4.0") - s.rubygems_version = "2.5.2" + s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") s.required_rubygems_version = Gem::Requirement.new(">= 2.2") + + s.add_dependency 'psych', '>= 4.0.0' end diff --git a/ruby/lib/rdoc/rdoc.rb b/ruby/lib/rdoc/rdoc.rb index c60e01760..5255e043f 100644 --- a/ruby/lib/rdoc/rdoc.rb +++ b/ruby/lib/rdoc/rdoc.rb @@ -14,7 +14,7 @@ # is: # # rdoc = RDoc::RDoc.new -# options = rdoc.load_options # returns an RDoc::Options instance +# options = RDoc::Options.load_options # returns an RDoc::Options instance # # set extra options # rdoc.document options # @@ -112,11 +112,17 @@ def gather_files files file_list = normalized_file_list files, true, @options.exclude - file_list = file_list.uniq + file_list = remove_unparseable(file_list) - file_list = remove_unparseable file_list - - file_list.sort + if file_list.count {|name, mtime| + file_list[name] = @last_modified[name] unless mtime + mtime + } > 0 + @last_modified.replace file_list + file_list.keys.sort + else + [] + end end ## @@ -145,27 +151,6 @@ def install_siginfo_handler end end - ## - # Loads options from .rdoc_options if the file exists, otherwise creates a - # new RDoc::Options instance. - - def load_options - options_file = File.expand_path '.rdoc_options' - return RDoc::Options.new unless File.exist? options_file - - RDoc.load_yaml - - begin - options = YAML.load_file '.rdoc_options' - rescue Psych::SyntaxError - end - - raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless - RDoc::Options === options - - options - end - ## # Create an output dir if it doesn't exist. If it does exist, but doesn't # contain the flag file created.rid then we refuse to use it, as @@ -254,11 +239,11 @@ def parse_dot_doc_file in_dir, filename # read and strip comments patterns = File.read(filename).gsub(/#.*/, '') - result = [] + result = {} - patterns.split.each do |patt| + patterns.split(' ').each do |patt| candidates = Dir.glob(File.join(in_dir, patt)) - result.concat normalized_file_list(candidates, false, @options.exclude) + result.update normalized_file_list(candidates, false, @options.exclude) end result @@ -278,21 +263,21 @@ def parse_dot_doc_file in_dir, filename def normalized_file_list(relative_files, force_doc = false, exclude_pattern = nil) - file_list = [] + file_list = {} relative_files.each do |rel_file_name| + rel_file_name = rel_file_name.sub(/^\.\//, '') next if rel_file_name.end_with? 'created.rid' next if exclude_pattern && exclude_pattern =~ rel_file_name stat = File.stat rel_file_name rescue next case type = stat.ftype when "file" then - next if last_modified = @last_modified[rel_file_name] and - stat.mtime.to_i <= last_modified.to_i + mtime = (stat.mtime unless (last_modified = @last_modified[rel_file_name] and + stat.mtime.to_i <= last_modified.to_i)) if force_doc or RDoc::Parser.can_parse(rel_file_name) then - file_list << rel_file_name.sub(/^\.\//, '') - @last_modified[rel_file_name] = stat.mtime + file_list[rel_file_name] = mtime end when "directory" then next if rel_file_name == "CVS" || rel_file_name == ".svn" @@ -303,16 +288,16 @@ def normalized_file_list(relative_files, force_doc = false, dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME if File.file? dot_doc then - file_list << parse_dot_doc_file(rel_file_name, dot_doc) + file_list.update(parse_dot_doc_file(rel_file_name, dot_doc)) else - file_list << list_files_in_directory(rel_file_name) + file_list.update(list_files_in_directory(rel_file_name)) end else warn "rdoc can't parse the #{type} #{rel_file_name}" end end - file_list.flatten + file_list end ## @@ -427,10 +412,10 @@ def parse_files files # files for emacs and vim. def remove_unparseable files - files.reject do |file| + files.reject do |file, *| file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)$/i or (file =~ /tags$/i and - open(file, 'rb') { |io| + File.open(file, 'rb') { |io| io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/ }) end @@ -457,7 +442,7 @@ def document options @options = options @options.finish else - @options = load_options + @options = RDoc::Options.load_options @options.parse options end @@ -561,6 +546,6 @@ def remove_siginfo_handler end # require built-in generators after discovery in case they've been replaced -require 'rdoc/generator/darkfish' -require 'rdoc/generator/ri' -require 'rdoc/generator/pot' +require_relative 'generator/darkfish' +require_relative 'generator/ri' +require_relative 'generator/pot' diff --git a/ruby/lib/rdoc/ri/driver.rb b/ruby/lib/rdoc/ri/driver.rb index 46b98e99b..7549a3920 100644 --- a/ruby/lib/rdoc/ri/driver.rb +++ b/ruby/lib/rdoc/ri/driver.rb @@ -17,7 +17,7 @@ ## # For RubyGems backwards compatibility -require 'rdoc/ri/formatter' +require_relative 'formatter' ## # The RI driver implements the command-line ri tool. @@ -142,6 +142,8 @@ def self.process_args argv gem_name: | gem_name:README | gem_name:History + ruby: | ruby:NEWS | ruby:globals + All class names may be abbreviated to their minimum unambiguous form. If a name is ambiguous, all valid options will be listed. @@ -153,6 +155,10 @@ def self.process_args argv gem will be shown. The file name extension may be omitted where it is unambiguous. +'ruby' can be used as a pseudo gem name to display files from the Ruby +core documentation. Use 'ruby:' by itself to get a list of all available +core documentation files. + For example: #{opt.program_name} Fil @@ -160,6 +166,7 @@ def self.process_args argv #{opt.program_name} File.new #{opt.program_name} zip #{opt.program_name} rdoc:README + #{opt.program_name} ruby:comments Note that shell quoting or escaping may be required for method names containing punctuation: @@ -356,7 +363,7 @@ def self.process_args argv end end - argv = ENV['RI'].to_s.split.concat argv + argv = ENV['RI'].to_s.split(' ').concat argv opts.parse! argv @@ -609,11 +616,11 @@ def ancestors_of klass stores = classes[current] - break unless stores and not stores.empty? + next unless stores and not stores.empty? - klasses = stores.map do |store| - store.ancestors[current] - end.flatten.uniq + klasses = stores.flat_map do |store| + store.ancestors[current] || [] + end.uniq klasses = klasses - seen @@ -1228,7 +1235,7 @@ def list_methods_matching name # +cache+ indicate if it is a class or instance method. def load_method store, cache, klass, type, name - methods = store.send(cache)[klass] + methods = store.public_send(cache)[klass] return unless methods @@ -1521,7 +1528,7 @@ def setup_pager pagers.compact.uniq.each do |pager| next unless pager - pager_cmd = pager.split.first + pager_cmd = pager.split(' ').first next unless in_path? pager_cmd @@ -1551,7 +1558,11 @@ def setup_pager # Starts a WEBrick server for ri. def start_server - require 'webrick' + begin + require 'webrick' + rescue LoadError + abort "webrick is not found. You may need to `gem install webrick` to install webrick." + end server = WEBrick::HTTPServer.new :Port => @server diff --git a/ruby/lib/rdoc/ri/paths.rb b/ruby/lib/rdoc/ri/paths.rb index f76721d31..8e89b04e5 100644 --- a/ruby/lib/rdoc/ri/paths.rb +++ b/ruby/lib/rdoc/ri/paths.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rdoc/rdoc' +require_relative '../rdoc' ## # The directories where ri data lives. Paths can be enumerated via ::each, or @@ -12,23 +12,9 @@ module RDoc::RI::Paths version = RbConfig::CONFIG['ruby_version'] - BASE = if RbConfig::CONFIG.key? 'ridir' then - File.join RbConfig::CONFIG['ridir'], version - else - File.join RbConfig::CONFIG['datadir'], 'ri', version - end + BASE = File.join RbConfig::CONFIG['ridir'], version - homedir = begin - File.expand_path('~') - rescue ArgumentError - end - - homedir ||= ENV['HOME'] || - ENV['USERPROFILE'] || ENV['HOMEPATH'] # for 1.8 compatibility - - HOMEDIR = if homedir then - File.join homedir, ".rdoc" - end + HOMEDIR = RDoc.home #:startdoc: ## diff --git a/ruby/lib/rdoc/ri/task.rb b/ruby/lib/rdoc/ri/task.rb index 6a6ea572b..1122ea377 100644 --- a/ruby/lib/rdoc/ri/task.rb +++ b/ruby/lib/rdoc/ri/task.rb @@ -4,7 +4,7 @@ rescue Gem::LoadError end unless defined?(RDoc) -require 'rdoc/task' +require_relative '../task' ## # RDoc::RI::Task creates ri data in ./.rdoc for your project. diff --git a/ruby/lib/rdoc/rubygems_hook.rb b/ruby/lib/rdoc/rubygems_hook.rb index 90b0541fc..3781ff985 100644 --- a/ruby/lib/rdoc/rubygems_hook.rb +++ b/ruby/lib/rdoc/rubygems_hook.rb @@ -70,7 +70,7 @@ def self.generation_hook installer, specs def self.load_rdoc return if @rdoc_version - require 'rdoc/rdoc' + require_relative 'rdoc' @rdoc_version = Gem::Version.new ::RDoc::VERSION end @@ -120,7 +120,9 @@ def document generator, options, destination options.exclude ||= [] # TODO maybe move to RDoc::Options#finish options.setup_generator generator options.op_dir = destination - options.finish + Dir.chdir @spec.full_gem_path do + options.finish + end generator = options.generator.new @rdoc.store, options @@ -158,7 +160,7 @@ def generate case config_args = Gem.configuration[:rdoc] when String then - args = args.concat config_args.split + args = args.concat config_args.split(' ') when Array then args = args.concat config_args end diff --git a/ruby/lib/rdoc/servlet.rb b/ruby/lib/rdoc/servlet.rb index e1d0f0ce8..0ab1eaf19 100644 --- a/ruby/lib/rdoc/servlet.rb +++ b/ruby/lib/rdoc/servlet.rb @@ -3,7 +3,12 @@ require 'erb' require 'time' require 'json' -require 'webrick' + +begin + require 'webrick' +rescue LoadError + abort "webrick is not found. You may need to `gem install webrick` to install webrick." +end ## # This is a WEBrick servlet that allows you to browse ri documentation. diff --git a/ruby/lib/rdoc/store.rb b/ruby/lib/rdoc/store.rb index 0f6cd06e3..5ba671ca1 100644 --- a/ruby/lib/rdoc/store.rb +++ b/ruby/lib/rdoc/store.rb @@ -482,7 +482,7 @@ def friendly_path when :gem then parent = File.expand_path '..', @path "gem #{File.basename parent}" - when :home then '~/.rdoc' + when :home then RDoc.home when :site then 'ruby site' when :system then 'ruby core' else @path @@ -723,7 +723,7 @@ def modules_hash def page name @text_files_hash.each_value.find do |file| - file.page_name == name + file.page_name == name or file.base_name == name end end diff --git a/ruby/lib/rdoc/text.rb b/ruby/lib/rdoc/text.rb index c3218fdb2..0bc4aba42 100644 --- a/ruby/lib/rdoc/text.rb +++ b/ruby/lib/rdoc/text.rb @@ -218,10 +218,10 @@ def to_html text when s.scan(/\.\.\.(\.?)/) then html << s[1] << encoded[:ellipsis] after_word = nil - when s.scan(/\(c\)/) then + when s.scan(/\(c\)/i) then html << encoded[:copyright] after_word = nil - when s.scan(/\(r\)/) then + when s.scan(/\(r\)/i) then html << encoded[:trademark] after_word = nil when s.scan(/---/) then @@ -237,10 +237,18 @@ def to_html text when s.scan(/``/) then # backtick double quote html << encoded[:open_dquote] after_word = nil - when s.scan(/''/) then # tick double quote + when s.scan(/(?:'|'){2}/) then # tick double quote html << encoded[:close_dquote] after_word = nil - when s.scan(/'/) then # single quote + when s.scan(/`/) then # backtick + if insquotes or after_word + html << '`' + after_word = false + else + html << encoded[:open_squote] + insquotes = true + end + when s.scan(/'|'/) then # single quote if insquotes html << encoded[:close_squote] insquotes = false diff --git a/ruby/lib/rdoc/version.rb b/ruby/lib/rdoc/version.rb index 5c7074406..86c5b360f 100644 --- a/ruby/lib/rdoc/version.rb +++ b/ruby/lib/rdoc/version.rb @@ -3,6 +3,6 @@ module RDoc ## # RDoc version you are using - VERSION = '6.2.1' + VERSION = '6.4.0' end diff --git a/ruby/lib/readline.gemspec b/ruby/lib/readline.gemspec index 5c641a88a..3a18f9edb 100644 --- a/ruby/lib/readline.gemspec +++ b/ruby/lib/readline.gemspec @@ -1,35 +1,33 @@ Gem::Specification.new do |spec| spec.name = 'readline' - spec.version = '0.0.2' + spec.version = '0.0.3' spec.authors = ['aycabta'] spec.email = ['aycabta@gmail.com'] - spec.summary = %q{It's a loader for "readline".} + spec.summary = %q{Loader for "readline".} spec.description = <<~EOD - This is just a loader for "readline". If Ruby has "readline-ext" gem that - is a native extension, this gem will load it first. If Ruby doesn't have - the "readline-ext" gem this gem will load "reline" that is a compatible - library with "readline-ext" gem and is implemented by pure Ruby. + This is just a loader for "readline". If Ruby has the "readline-ext" gem + that is a native extension, this gem will load it. If Ruby does not have + the "readline-ext" gem this gem will load "reline", a library that is + compatible with the "readline-ext" gem and implemented in pure Ruby. EOD spec.homepage = 'https://github.com/ruby/readline' - spec.license = 'Ruby license' + spec.license = 'Ruby' spec.files = Dir['BSDL', 'COPYING', 'README.md', 'lib/readline.rb'] spec.require_paths = ['lib'] spec.post_install_message = <<~EOM +---------------------------------------------------------------------------+ - | This is just a loader for "readline". If Ruby has "readline-ext" gem that | - | is a native extension, this gem will load it first. If Ruby doesn't have | - | the "readline-ext" gem this gem will load "reline" that is a compatible   | - | library with "readline-ext" gem and is implemented by pure Ruby.          | - |                                                                           | + | This is just a loader for "readline". If Ruby has the "readline-ext" gem | + | that is a native extension, this gem will load it. If Ruby does not have | + | the "readline-ext" gem this gem will load "reline", a library that is | + | compatible with the "readline-ext" gem and implemented in pure Ruby. | + | | | If you intend to use GNU Readline by `require 'readline'`, please install | - | "readline-ext" gem.                                                       | + | the "readline-ext" gem. | +---------------------------------------------------------------------------+ EOM spec.add_runtime_dependency 'reline' - spec.add_development_dependency 'bundler' - spec.add_development_dependency 'rake' end diff --git a/ruby/lib/readline.rb b/ruby/lib/readline.rb index 6cc923cb2..29cdf3a14 100644 --- a/ruby/lib/readline.rb +++ b/ruby/lib/readline.rb @@ -2,5 +2,6 @@ require 'readline.so' rescue LoadError require 'reline' unless defined? Reline + Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline) Readline = Reline end diff --git a/ruby/lib/reline.rb b/ruby/lib/reline.rb index 1537ee7e6..a9fc49b41 100644 --- a/ruby/lib/reline.rb +++ b/ruby/lib/reline.rb @@ -7,13 +7,33 @@ require 'reline/key_stroke' require 'reline/line_editor' require 'reline/history' +require 'reline/terminfo' +require 'rbconfig' module Reline FILENAME_COMPLETION_PROC = nil USERNAME_COMPLETION_PROC = nil - Key = Struct.new('Key', :char, :combined_char, :with_meta) + class ConfigEncodingConversionError < StandardError; end + + Key = Struct.new('Key', :char, :combined_char, :with_meta) do + def match?(other) + case other + when Reline::Key + (other.char.nil? or char.nil? or char == other.char) and + (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and + (other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta) + when Integer, Symbol + (combined_char and combined_char == other) or + (combined_char.nil? and char and char == other) + else + false + end + end + alias_method :==, :match? + end CursorPos = Struct.new(:x, :y) + DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true) class Core ATTR_READER_NAMES = %i( @@ -35,14 +55,15 @@ class Core attr_accessor :config attr_accessor :key_stroke attr_accessor :line_editor - attr_accessor :ambiguous_width attr_accessor :last_incremental_search attr_reader :output def initialize self.output = STDOUT + @dialog_proc_list = {} yield self @completion_quote_character = nil + @bracketed_paste_finished = false end def encoding @@ -98,22 +119,30 @@ def completion_quote_character end def completion_proc=(p) - raise ArgumentError unless p.respond_to?(:call) + raise ArgumentError unless p.respond_to?(:call) or p.nil? @completion_proc = p end + def autocompletion + @config.autocompletion + end + + def autocompletion=(val) + @config.autocompletion = val + end + def output_modifier_proc=(p) - raise ArgumentError unless p.respond_to?(:call) + raise ArgumentError unless p.respond_to?(:call) or p.nil? @output_modifier_proc = p end def prompt_proc=(p) - raise ArgumentError unless p.respond_to?(:call) + raise ArgumentError unless p.respond_to?(:call) or p.nil? @prompt_proc = p end def auto_indent_proc=(p) - raise ArgumentError unless p.respond_to?(:call) + raise ArgumentError unless p.respond_to?(:call) or p.nil? @auto_indent_proc = p end @@ -122,10 +151,21 @@ def pre_input_hook=(p) end def dig_perfect_match_proc=(p) - raise ArgumentError unless p.respond_to?(:call) + raise ArgumentError unless p.respond_to?(:call) or p.nil? @dig_perfect_match_proc = p end + DialogProc = Struct.new(:dialog_proc, :context) + def add_dialog_proc(name_sym, p, context = nil) + raise ArgumentError unless p.respond_to?(:call) or p.nil? + raise ArgumentError unless name_sym.instance_of?(Symbol) + @dialog_proc_list[name_sym] = DialogProc.new(p, context) + end + + def dialog_proc(name_sym) + @dialog_proc_list[name_sym] + end + def input=(val) raise TypeError unless val.respond_to?(:getc) or val.nil? if val.respond_to?(:getc) @@ -167,6 +207,46 @@ def get_screen_size Reline::IOGate.get_screen_size end + Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() { + # autocomplete + return nil unless config.autocompletion + if just_cursor_moving and completion_journey_data.nil? + # Auto complete starts only when edited + return nil + end + pre, target, post = retrieve_completion_block(true) + if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3) + return nil + end + if completion_journey_data and completion_journey_data.list + result = completion_journey_data.list.dup + result.shift + pointer = completion_journey_data.pointer - 1 + else + result = call_completion_proc_with_checking_args(pre, target, post) + pointer = nil + end + if result and result.size == 1 and result[0] == target and pointer != 0 + result = nil + end + target_width = Reline::Unicode.calculate_width(target) + x = cursor_pos.x - target_width + if x < 0 + x = screen_width + x + y = -1 + else + y = 0 + end + cursor_pos_to_render = Reline::CursorPos.new(x, y) + if context and context.is_a?(Array) + context.clear + context.push(cursor_pos_to_render, result, pointer, dialog) + end + dialog.pointer = pointer + DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15) + } + Reline::DEFAULT_DIALOG_CONTEXT = Array.new + def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination) unless confirm_multiline_termination raise ArgumentError.new('#readmultiline needs block to confirm multiline termination') @@ -198,7 +278,11 @@ def readline(prompt = '', add_hist = false) private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination) if ENV['RELINE_STDERR_TTY'] - $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w') + if Reline::IOGate.win? + $stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a') + else + $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w') + end $stderr.sync = true $stderr.puts "Reline is used by #{Process.pid}" end @@ -222,42 +306,65 @@ def readline(prompt = '', add_hist = false) line_editor.auto_indent_proc = auto_indent_proc line_editor.dig_perfect_match_proc = dig_perfect_match_proc line_editor.pre_input_hook = pre_input_hook - line_editor.rerender + @dialog_proc_list.each_pair do |name_sym, d| + line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context) + end unless config.test_mode config.read config.reset_default_key_bindings - Reline::IOGate::RAW_KEYSTROKE_CONFIG.each_pair do |key, func| - config.add_default_key_binding(key, func) - end + Reline::IOGate.set_default_key_bindings(config) end + line_editor.rerender + begin + line_editor.set_signal_handlers + prev_pasting_state = false loop do + prev_pasting_state = Reline::IOGate.in_pasting? read_io(config.keyseq_timeout) { |inputs| + line_editor.set_pasting_state(Reline::IOGate.in_pasting?) inputs.each { |c| line_editor.input_key(c) line_editor.rerender } + if @bracketed_paste_finished + line_editor.rerender_all + @bracketed_paste_finished = false + end } + if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished? + line_editor.set_pasting_state(false) + prev_pasting_state = false + line_editor.rerender_all + end break if line_editor.finished? end Reline::IOGate.move_cursor_column(0) + rescue Errno::EIO + # Maybe the I/O has been closed. rescue StandardError => e line_editor.finalize Reline::IOGate.deprep(otio) raise e + rescue Exception + # Including Interrupt + line_editor.finalize + Reline::IOGate.deprep(otio) + raise end line_editor.finalize Reline::IOGate.deprep(otio) end - # Keystrokes of GNU Readline will timeout it with the specification of - # "keyseq-timeout" when waiting for the 2nd character after the 1st one. - # If the 2nd character comes after 1st ESC without timeout it has a - # meta-property of meta-key to discriminate modified key with meta-key - # from multibyte characters that come with 8th bit on. + # GNU Readline waits for "keyseq-timeout" milliseconds to see if the ESC + # is followed by a character, and times out and treats it as a standalone + # ESC if the second character does not arrive. If the second character + # comes before timed out, it is treated as a modifier key with the + # meta-property of meta-key, so that it can be distinguished from + # multibyte characters with the 8th bit turned on. # # GNU Readline will wait for the 2nd character with "keyseq-timeout" # milli-seconds but wait forever after 3rd characters. @@ -265,8 +372,13 @@ def readline(prompt = '', add_hist = false) buffer = [] loop do c = Reline::IOGate.getc - buffer << c - result = key_stroke.match_status(buffer) + if c == -1 + result = :unmatched + @bracketed_paste_finished = true + else + buffer << c + result = key_stroke.match_status(buffer) + end case result when :matched expanded = key_stroke.expand(buffer).map{ |expanded_c| @@ -276,25 +388,9 @@ def readline(prompt = '', add_hist = false) break when :matching if buffer.size == 1 - begin - succ_c = nil - Timeout.timeout(keyseq_timeout / 1000.0) { - succ_c = Reline::IOGate.getc - } - rescue Timeout::Error # cancel matching only when first byte - block.([Reline::Key.new(c, c, false)]) - break - else - if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched - if c == "\e".ord - block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)]) - else - block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)]) - end - break - else - Reline::IOGate.ungetc(succ_c) - end + case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block) + when :break then break + when :next then next end end when :unmatched @@ -311,6 +407,38 @@ def readline(prompt = '', add_hist = false) end end + private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block) + begin + succ_c = nil + Timeout.timeout(keyseq_timeout / 1000.0) { + succ_c = Reline::IOGate.getc + } + rescue Timeout::Error # cancel matching only when first byte + block.([Reline::Key.new(c, c, false)]) + return :break + else + case key_stroke.match_status(buffer.dup.push(succ_c)) + when :unmatched + if c == "\e".ord + block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)]) + else + block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)]) + end + return :break + when :matching + Reline::IOGate.ungetc(succ_c) + return :next + when :matched + buffer << succ_c + expanded = key_stroke.expand(buffer).map{ |expanded_c| + Reline::Key.new(expanded_c, expanded_c, false) + } + block.(expanded) + return :break + end + end + end + private def read_escaped_key(keyseq_timeout, c, block) begin escaped_c = nil @@ -332,9 +460,14 @@ def readline(prompt = '', add_hist = false) end end + def ambiguous_width + may_req_ambiguous_char_width unless defined? @ambiguous_width + @ambiguous_width + end + private def may_req_ambiguous_char_width @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File) - return if ambiguous_width + return if defined? @ambiguous_width Reline::IOGate.move_cursor_column(0) begin output.write "\u{25bd}" @@ -357,7 +490,7 @@ def readline(prompt = '', add_hist = false) #-------------------------------------------------------- (Core::ATTR_READER_NAMES).each { |name| - def_single_delegators :core, "#{name}", "#{name}=" + def_single_delegators :core, :"#{name}", :"#{name}=" } def_single_delegators :core, :input=, :output= def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode @@ -392,6 +525,9 @@ def self.insert_text(*args, &block) def_single_delegators :core, :ambiguous_width def_single_delegators :core, :last_incremental_search def_single_delegators :core, :last_incremental_search= + def_single_delegators :core, :add_dialog_proc + def_single_delegators :core, :dialog_proc + def_single_delegators :core, :autocompletion, :autocompletion= def_single_delegators :core, :readmultiline def_instance_delegators self, :readmultiline @@ -413,25 +549,38 @@ def self.core core.completer_quote_characters = '"\'' core.filename_quote_characters = "" core.special_prefixes = "" + core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT) } end + def self.ungetc(c) + Reline::IOGate.ungetc(c) + end + def self.line_editor core.line_editor end end +require 'reline/general_io' if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ require 'reline/windows' if Reline::Windows.msys_tty? - require 'reline/ansi' - Reline::IOGate = Reline::ANSI + Reline::IOGate = if ENV['TERM'] == 'dumb' + Reline::GeneralIO + else + require 'reline/ansi' + Reline::ANSI + end else Reline::IOGate = Reline::Windows end else - require 'reline/ansi' - Reline::IOGate = Reline::ANSI + Reline::IOGate = if $stdout.isatty + require 'reline/ansi' + Reline::ANSI + else + Reline::GeneralIO + end end Reline::HISTORY = Reline::History.new(Reline.core.config) -require 'reline/general_io' diff --git a/ruby/lib/reline/ansi.rb b/ruby/lib/reline/ansi.rb index 3ef02d6e7..ab147a618 100644 --- a/ruby/lib/reline/ansi.rb +++ b/ruby/lib/reline/ansi.rb @@ -1,6 +1,26 @@ require 'io/console' +require 'io/wait' +require 'timeout' +require_relative 'terminfo' class Reline::ANSI + CAPNAME_KEY_BINDINGS = { + 'khome' => :ed_move_to_beg, + 'kend' => :ed_move_to_end, + 'kcuu1' => :ed_prev_history, + 'kcud1' => :ed_next_history, + 'kcuf1' => :ed_next_char, + 'kcub1' => :ed_prev_char, + 'cuu' => :ed_prev_history, + 'cud' => :ed_next_history, + 'cuf' => :ed_next_char, + 'cub' => :ed_prev_char, + } + + if Reline::Terminfo.enabled? + Reline::Terminfo.setupterm(0, 2) + end + def self.encoding Encoding.default_external end @@ -9,42 +29,108 @@ def self.win? false end - RAW_KEYSTROKE_CONFIG = { - # Console (80x25) - [27, 91, 49, 126] => :ed_move_to_beg, # Home - [27, 91, 52, 126] => :ed_move_to_end, # End - [27, 91, 51, 126] => :key_delete, # Del - [27, 91, 65] => :ed_prev_history, # ↑ - [27, 91, 66] => :ed_next_history, # ↓ - [27, 91, 67] => :ed_next_char, # → - [27, 91, 68] => :ed_prev_char, # ↠- - # KDE - [27, 91, 72] => :ed_move_to_beg, # Home - [27, 91, 70] => :ed_move_to_end, # End - # Del is 0x08 - [27, 71, 65] => :ed_prev_history, # ↑ - [27, 71, 66] => :ed_next_history, # ↓ - [27, 71, 67] => :ed_next_char, # → - [27, 71, 68] => :ed_prev_char, # ↠- - # GNOME - [27, 79, 72] => :ed_move_to_beg, # Home - [27, 79, 70] => :ed_move_to_end, # End - # Del is 0x08 - # Arrow keys are the same of KDE - - # others - [27, 32] => :em_set_mark, # M- - [24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows - [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→ - [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+↠- - [27, 79, 65] => :ed_prev_history, # ↑ - [27, 79, 66] => :ed_next_history, # ↓ - [27, 79, 67] => :ed_next_char, # → - [27, 79, 68] => :ed_prev_char, # ↠- } + def self.set_default_key_bindings(config) + if Reline::Terminfo.enabled? + set_default_key_bindings_terminfo(config) + else + set_default_key_bindings_comprehensive_list(config) + end + { + # extended entries of terminfo + [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→, extended entry + [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+â†, extended entry + [27, 91, 49, 59, 51, 67] => :em_next_word, # Meta+→, extended entry + [27, 91, 49, 59, 51, 68] => :ed_prev_word, # Meta+â†, extended entry + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + { + [27, 91, 90] => :completion_journey_up, # S-Tab + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + end + { + # default bindings + [27, 32] => :em_set_mark, # M- + [24, 24] => :em_exchange_mark, # C-x C-x + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + end + end + + def self.set_default_key_bindings_terminfo(config) + key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding| + begin + key_code = Reline::Terminfo.tigetstr(capname) + case capname + # Escape sequences that omit the move distance and are set to defaults + # value 1 may be sometimes sent by pressing the arrow-key. + when 'cuu', 'cud', 'cuf', 'cub' + [ key_code.sub(/%p1%d/, '').bytes, key_binding ] + else + [ key_code.bytes, key_binding ] + end + rescue Reline::Terminfo::TerminfoError + # capname is undefined + end + end.compact.to_h + + key_bindings.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + end + + def self.set_default_key_bindings_comprehensive_list(config) + { + # Console (80x25) + [27, 91, 49, 126] => :ed_move_to_beg, # Home + [27, 91, 52, 126] => :ed_move_to_end, # End + [27, 91, 51, 126] => :key_delete, # Del + [27, 91, 65] => :ed_prev_history, # ↑ + [27, 91, 66] => :ed_next_history, # ↓ + [27, 91, 67] => :ed_next_char, # → + [27, 91, 68] => :ed_prev_char, # ↠+ + # KDE + [27, 91, 72] => :ed_move_to_beg, # Home + [27, 91, 70] => :ed_move_to_end, # End + # Del is 0x08 + [27, 71, 65] => :ed_prev_history, # ↑ + [27, 71, 66] => :ed_next_history, # ↓ + [27, 71, 67] => :ed_next_char, # → + [27, 71, 68] => :ed_prev_char, # ↠+ + # urxvt / exoterm + [27, 91, 55, 126] => :ed_move_to_beg, # Home + [27, 91, 56, 126] => :ed_move_to_end, # End + + # GNOME + [27, 79, 72] => :ed_move_to_beg, # Home + [27, 79, 70] => :ed_move_to_end, # End + # Del is 0x08 + # Arrow keys are the same of KDE + + # iTerm2 + [27, 27, 91, 67] => :em_next_word, # Option+→, extended entry + [27, 27, 91, 68] => :ed_prev_word, # Option+â†, extended entry + [195, 166] => :em_next_word, # Option+f + [195, 162] => :ed_prev_word, # Option+b + + [27, 79, 65] => :ed_prev_history, # ↑ + [27, 79, 66] => :ed_next_history, # ↓ + [27, 79, 67] => :ed_next_char, # → + [27, 79, 68] => :ed_prev_char, # ↠+ }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + end @@input = STDIN def self.input=(val) @@ -57,12 +143,70 @@ def self.output=(val) end @@buf = [] - def self.getc + def self.inner_getc unless @@buf.empty? return @@buf.shift end - c = @@input.raw(intr: true, &:getbyte) + until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte } + Reline.core.line_editor.resize + end (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c + rescue Errno::EIO + # Maybe the I/O has been closed. + nil + rescue Errno::ENOTTY + nil + end + + @@in_bracketed_paste_mode = false + START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT) + END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT) + def self.getc_with_bracketed_paste + buffer = String.new(encoding: Encoding::ASCII_8BIT) + buffer << inner_getc + while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do + if START_BRACKETED_PASTE == buffer + @@in_bracketed_paste_mode = true + return inner_getc + elsif END_BRACKETED_PASTE == buffer + @@in_bracketed_paste_mode = false + ungetc(-1) + return inner_getc + end + begin + succ_c = nil + Timeout.timeout(Reline.core.config.keyseq_timeout * 100) { + succ_c = inner_getc + } + rescue Timeout::Error + break + else + buffer << succ_c + end + end + buffer.bytes.reverse_each do |ch| + ungetc ch + end + inner_getc + end + + def self.getc + if Reline.core.config.enable_bracketed_paste + getc_with_bracketed_paste + else + inner_getc + end + end + + def self.in_pasting? + @@in_bracketed_paste_mode or (not Reline::IOGate.empty_buffer?) + end + + def self.empty_buffer? + unless @@buf.empty? + return false + end + !@@input.wait_readable(0) end def self.ungetc(c) @@ -71,8 +215,7 @@ def self.ungetc(c) def self.retrieve_keybuffer begin - result = select([@@input], [], [], 0.001) - return if result.nil? + return unless @@input.wait_readable(0.001) str = @@input.read_nonblock(1024) str.bytes.each do |c| @@buf.push(c) @@ -100,15 +243,18 @@ def self.set_screen_size(rows, columns) def self.cursor_pos begin - res = '' + res = +'' m = nil @@input.raw do |stdin| @@output << "\e[6n" @@output.flush - while (c = stdin.getc) != 'R' - res << c if c + loop do + c = stdin.getc + next if c.nil? + res << c + m = res.match(/\e\[(?\d+);(?\d+)R/) + break if m end - m = res.match(/\e\[(?\d+);(?\d+)/) (m.pre_match + m.post_match).chars.reverse_each do |ch| stdin.ungetc ch end @@ -116,9 +262,16 @@ def self.cursor_pos column = m[:column].to_i - 1 row = m[:row].to_i - 1 rescue Errno::ENOTTY - buf = @@output.pread(@@output.pos, 0) - row = buf.count("\n") - column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0 + begin + buf = @@output.pread(@@output.pos, 0) + row = buf.count("\n") + column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0 + rescue Errno::ESPIPE + # Just returns column 1 for ambiguous width because this I/O is not + # tty and can't seek. + row = 0 + column = 1 + end end Reline::CursorPos.new(column, row) end @@ -129,7 +282,7 @@ def self.move_cursor_column(x) def self.move_cursor_up(x) if x > 0 - @@output.write "\e[#{x}A" if x > 0 + @@output.write "\e[#{x}A" elsif x < 0 move_cursor_down(-x) end @@ -137,12 +290,36 @@ def self.move_cursor_up(x) def self.move_cursor_down(x) if x > 0 - @@output.write "\e[#{x}B" if x > 0 + @@output.write "\e[#{x}B" elsif x < 0 move_cursor_up(-x) end end + def self.hide_cursor + if Reline::Terminfo.enabled? + begin + @@output.write Reline::Terminfo.tigetstr('civis') + rescue Reline::Terminfo::TerminfoError + # civis is undefined + end + else + # ignored + end + end + + def self.show_cursor + if Reline::Terminfo.enabled? + begin + @@output.write Reline::Terminfo.tigetstr('cnorm') + rescue Reline::Terminfo::TerminfoError + # cnorm is undefined + end + else + # ignored + end + end + def self.erase_after_cursor @@output.write "\e[K" end @@ -164,14 +341,10 @@ def self.set_winch_handler(&handler) def self.prep retrieve_keybuffer - int_handle = Signal.trap('INT', 'IGNORE') - Signal.trap('INT', int_handle) nil end def self.deprep(otio) - int_handle = Signal.trap('INT', 'IGNORE') - Signal.trap('INT', int_handle) Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler end end diff --git a/ruby/lib/reline/config.rb b/ruby/lib/reline/config.rb index 53b868fd2..5ef5ce4e8 100644 --- a/ruby/lib/reline/config.rb +++ b/ruby/lib/reline/config.rb @@ -1,10 +1,6 @@ -require 'pathname' - class Reline::Config attr_reader :test_mode - DEFAULT_PATH = '~/.inputrc' - KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./ class InvalidInputrc < RuntimeError @@ -37,6 +33,12 @@ class InvalidInputrc < RuntimeError show-all-if-ambiguous show-all-if-unmodified visible-stats + show-mode-in-prompt + vi-cmd-mode-string + vi-ins-mode-string + emacs-mode-string + enable-bracketed-paste + isearch-terminators } VARIABLE_NAME_SYMBOLS = VARIABLE_NAMES.map { |v| :"#{v.tr(?-, ?_)}" } VARIABLE_NAME_SYMBOLS.each do |v| @@ -45,7 +47,10 @@ class InvalidInputrc < RuntimeError def initialize @additional_key_bindings = {} # from inputrc - @default_key_bindings = {} # environment-dependent + @additional_key_bindings[:emacs] = {} + @additional_key_bindings[:vi_insert] = {} + @additional_key_bindings[:vi_command] = {} + @oneshot_key_bindings = {} @skip_section = nil @if_stack = nil @editing_mode_label = :emacs @@ -54,17 +59,26 @@ def initialize @key_actors[:emacs] = Reline::KeyActor::Emacs.new @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new - @history_size = 500 + @vi_cmd_mode_string = '(cmd)' + @vi_ins_mode_string = '(ins)' + @emacs_mode_string = '@' + # https://tiswww.case.edu/php/chet/readline/readline.html#IDX25 + @history_size = -1 # unlimited @keyseq_timeout = 500 @test_mode = false + @autocompletion = false + @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding) end def reset if editing_mode_is?(:vi_command) @editing_mode_label = :vi_insert end - @additional_key_bindings = {} - @default_key_bindings = {} + @additional_key_bindings.keys.each do |key| + @additional_key_bindings[key].clear + end + @oneshot_key_bindings.clear + reset_default_key_bindings end def editing_mode @@ -79,6 +93,14 @@ def editing_mode_is?(*val) (val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label) end + def autocompletion=(val) + @autocompletion = val + end + + def autocompletion + @autocompletion + end + def keymap @key_actors[@keymap_label] end @@ -86,14 +108,35 @@ def keymap def inputrc_path case ENV['INPUTRC'] when nil, '' - DEFAULT_PATH else - ENV['INPUTRC'] + return File.expand_path(ENV['INPUTRC']) end + + # In the XDG Specification, if ~/.config/readline/inputrc exists, then + # ~/.inputrc should not be read, but for compatibility with GNU Readline, + # if ~/.inputrc exists, then it is given priority. + home_rc_path = File.expand_path('~/.inputrc') + return home_rc_path if File.exist?(home_rc_path) + + case path = ENV['XDG_CONFIG_HOME'] + when nil, '' + else + path = File.join(path, 'readline/inputrc') + return path if File.exist?(path) and path == File.expand_path(path) + end + + path = File.expand_path('~/.config/readline/inputrc') + return path if File.exist?(path) + + return home_rc_path + end + + private def default_inputrc_path + @default_inputrc_path ||= inputrc_path end def read(file = nil) - file ||= File.expand_path(inputrc_path) + file ||= default_inputrc_path begin if file.respond_to?(:readlines) lines = file.readlines @@ -112,19 +155,46 @@ def read(file = nil) end def key_bindings - # override @default_key_bindings with @additional_key_bindings - @default_key_bindings.merge(@additional_key_bindings) + # The key bindings for each editing mode will be overwritten by the user-defined ones. + kb = @key_actors[@editing_mode_label].default_key_bindings.dup + kb.merge!(@additional_key_bindings[@editing_mode_label]) + kb.merge!(@oneshot_key_bindings) + kb + end + + def add_oneshot_key_binding(keystroke, target) + @oneshot_key_bindings[keystroke] = target + end + + def reset_oneshot_key_bindings + @oneshot_key_bindings.clear + end + + def add_default_key_binding_by_keymap(keymap, keystroke, target) + @key_actors[keymap].default_key_bindings[keystroke] = target end def add_default_key_binding(keystroke, target) - @default_key_bindings[keystroke] = target + @key_actors[@keymap_label].default_key_bindings[keystroke] = target end def reset_default_key_bindings - @default_key_bindings = {} + @key_actors.values.each do |ka| + ka.reset_default_key_bindings + end end def read_lines(lines, file = nil) + if not lines.empty? and lines.first.encoding != Reline.encoding_system_needs + begin + lines = lines.map do |l| + l.encode(Reline.encoding_system_needs) + rescue Encoding::UndefinedConversionError + mes = "The inputrc encoded in #{lines.first.encoding.name} can't be converted to the locale #{Reline.encoding_system_needs.name}." + raise Reline::ConfigEncodingConversionError.new(mes) + end + end + end conditions = [@skip_section, @if_stack] @skip_section = nil @if_stack = [] @@ -144,14 +214,14 @@ def read_lines(lines, file = nil) case line when /^set +([^ ]+) +([^ ]+)/i - var, value = $1.downcase, $2.downcase + var, value = $1.downcase, $2 bind_variable(var, value) next when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o key, func_name = $1, $2 keystroke, func = bind_key(key, func_name) next unless keystroke - @additional_key_bindings[keystroke] = func + @additional_key_bindings[@keymap_label][keystroke] = func end end unless @if_stack.empty? @@ -194,7 +264,11 @@ def handle_directive(directive, file, no) def bind_variable(name, value) case name when 'history-size' - @history_size = value.to_i + begin + @history_size = Integer(value) + rescue ArgumentError + @history_size = 500 + end when 'bell-style' @bell_style = case value @@ -212,7 +286,7 @@ def bind_variable(name, value) when 'completion-query-items' @completion_query_items = value.to_i when 'isearch-terminators' - @isearch_terminators = instance_eval(value) + @isearch_terminators = retrieve_string(value) when 'editing-mode' case value when 'emacs' @@ -233,12 +307,32 @@ def bind_variable(name, value) end when 'keyseq-timeout' @keyseq_timeout = value.to_i + when 'show-mode-in-prompt' + case value + when 'off' + @show_mode_in_prompt = false + when 'on' + @show_mode_in_prompt = true + else + @show_mode_in_prompt = false + end + when 'vi-cmd-mode-string' + @vi_cmd_mode_string = retrieve_string(value) + when 'vi-ins-mode-string' + @vi_ins_mode_string = retrieve_string(value) + when 'emacs-mode-string' + @emacs_mode_string = retrieve_string(value) when *VARIABLE_NAMES then variable_name = :"@#{name.tr(?-, ?_)}" instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on') end end + def retrieve_string(str) + str = $1 if str =~ /\A"(.*)"\z/ + parse_keyseq(str).map { |c| c.chr(Reline.encoding_system_needs) }.join + end + def bind_key(key, func_name) if key =~ /\A"(.*)"\z/ keyseq = parse_keyseq($1) @@ -294,4 +388,8 @@ def parse_keyseq(str) end ret end + + private def seven_bit_encoding?(encoding) + encoding == Encoding::US_ASCII + end end diff --git a/ruby/lib/reline/general_io.rb b/ruby/lib/reline/general_io.rb index 85f1f13ee..3fafad5c6 100644 --- a/ruby/lib/reline/general_io.rb +++ b/ruby/lib/reline/general_io.rb @@ -1,17 +1,31 @@ require 'timeout' +require 'io/wait' class Reline::GeneralIO + def self.reset(encoding: nil) + @@pasting = false + @@encoding = encoding + end + def self.encoding - RUBY_PLATFORM =~ /mswin|mingw/ ? Encoding::UTF_8 : Encoding::default_external + if defined?(@@encoding) + @@encoding + elsif RUBY_PLATFORM =~ /mswin|mingw/ + Encoding::UTF_8 + else + Encoding::default_external + end end def self.win? false end - RAW_KEYSTROKE_CONFIG = {} + def self.set_default_key_bindings(_) + end @@buf = [] + @@input = STDIN def self.input=(val) @@input = val @@ -23,7 +37,7 @@ def self.getc end c = nil loop do - result = select([@@input], [], [], 0.1) + result = @@input.wait_readable(0.1) next if result.nil? c = @@input.read(1) break @@ -67,6 +81,20 @@ def self.set_screen_size(rows, columns) def self.set_winch_handler(&handler) end + @@pasting = false + + def self.in_pasting? + @@pasting + end + + def self.start_pasting + @@pasting = true + end + + def self.finish_pasting + @@pasting = false + end + def self.prep end diff --git a/ruby/lib/reline/history.rb b/ruby/lib/reline/history.rb index d95f1cebc..7a1ed6b90 100644 --- a/ruby/lib/reline/history.rb +++ b/ruby/lib/reline/history.rb @@ -29,27 +29,47 @@ def concat(*val) end def push(*val) - diff = size + val.size - @config.history_size - if diff > 0 - if diff <= size - shift(diff) - else - diff -= size - clear - val.shift(diff) + # If history_size is zero, all histories are dropped. + return self if @config.history_size.zero? + # If history_size is negative, history size is unlimited. + if @config.history_size.positive? + diff = size + val.size - @config.history_size + if diff > 0 + if diff <= size + shift(diff) + else + diff -= size + clear + val.shift(diff) + end end end - super(*(val.map{ |v| String.new(v, encoding: Reline.encoding_system_needs) })) + super(*(val.map{ |v| + String.new(v, encoding: Reline.encoding_system_needs) + })) end def <<(val) - shift if size + 1 > @config.history_size + # If history_size is zero, all histories are dropped. + return self if @config.history_size.zero? + # If history_size is negative, history size is unlimited. + if @config.history_size.positive? + shift if size + 1 > @config.history_size + end super(String.new(val, encoding: Reline.encoding_system_needs)) end private def check_index(index) index += size if index < 0 - raise RangeError.new("index=<#{index}>") if index < -@config.history_size or @config.history_size < index + if index < -2147483648 or 2147483647 < index + raise RangeError.new("integer #{index} too big to convert to `int'") + end + # If history_size is negative, history size is unlimited. + if @config.history_size.positive? + if index < -@config.history_size or @config.history_size < index + raise RangeError.new("index=<#{index}>") + end + end raise IndexError.new("index=<#{index}>") if index < 0 or size <= index index end diff --git a/ruby/lib/reline/key_actor/base.rb b/ruby/lib/reline/key_actor/base.rb index f4abac55d..a1cd7fb2a 100644 --- a/ruby/lib/reline/key_actor/base.rb +++ b/ruby/lib/reline/key_actor/base.rb @@ -4,4 +4,16 @@ class Reline::KeyActor::Base def get_method(key) self.class::MAPPING[key] end + + def initialize + @default_key_bindings = {} + end + + def default_key_bindings + @default_key_bindings + end + + def reset_default_key_bindings + @default_key_bindings.clear + end end diff --git a/ruby/lib/reline/key_actor/emacs.rb b/ruby/lib/reline/key_actor/emacs.rb index 3886d17f2..86e39b705 100644 --- a/ruby/lib/reline/key_actor/emacs.rb +++ b/ruby/lib/reline/key_actor/emacs.rb @@ -37,13 +37,13 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 17 ^Q :ed_quoted_insert, # 18 ^R - :ed_search_prev_history, + :vi_search_prev, # 19 ^S - :ed_search_next_history, + :vi_search_next, # 20 ^T :ed_transpose_chars, # 21 ^U - :em_kill_line, + :ed_kill_line, # 22 ^V :ed_quoted_insert, # 23 ^W @@ -307,7 +307,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 152 M-^X :ed_unassigned, # 153 M-^Y - :ed_unassigned, + :em_yank_pop, # 154 M-^Z :ed_unassigned, # 155 M-^[ @@ -413,11 +413,11 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 205 M-M :ed_unassigned, # 206 M-N - :ed_search_next_history, + :vi_search_next, # 207 M-O :ed_sequence_lead_in, # 208 M-P - :ed_search_prev_history, + :vi_search_prev, # 209 M-Q :ed_unassigned, # 210 M-R @@ -477,11 +477,11 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 237 M-m :ed_unassigned, # 238 M-n - :ed_search_next_history, + :vi_search_next, # 239 M-o :ed_unassigned, # 240 M-p - :ed_search_prev_history, + :vi_search_prev, # 241 M-q :ed_unassigned, # 242 M-r diff --git a/ruby/lib/reline/key_actor/vi_command.rb b/ruby/lib/reline/key_actor/vi_command.rb index 865dfa2e0..98146d2f7 100644 --- a/ruby/lib/reline/key_actor/vi_command.rb +++ b/ruby/lib/reline/key_actor/vi_command.rb @@ -17,7 +17,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base # 7 ^G :ed_unassigned, # 8 ^H - :ed_delete_prev_char, + :ed_unassigned, # 9 ^I :ed_unassigned, # 10 ^J @@ -37,7 +37,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base # 17 ^Q :ed_ignore, # 18 ^R - :ed_search_prev_history, + :vi_search_prev, # 19 ^S :ed_ignore, # 20 ^T @@ -151,7 +151,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base # 74 J :vi_join_lines, # 75 K - :ed_search_prev_history, + :vi_search_prev, # 76 L :ed_unassigned, # 77 M @@ -255,7 +255,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base # 126 ~ :vi_change_case, # 127 ^? - :ed_delete_prev_char, + :ed_unassigned, # 128 M-^@ :ed_unassigned, # 129 M-^A diff --git a/ruby/lib/reline/key_actor/vi_insert.rb b/ruby/lib/reline/key_actor/vi_insert.rb index 06e94a9c3..b8e89f81d 100644 --- a/ruby/lib/reline/key_actor/vi_insert.rb +++ b/ruby/lib/reline/key_actor/vi_insert.rb @@ -37,9 +37,9 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base # 17 ^Q :ed_ignore, # 18 ^R - :ed_search_prev_history, + :vi_search_prev, # 19 ^S - :ed_search_next_history, + :vi_search_next, # 20 ^T :ed_insert, # 21 ^U diff --git a/ruby/lib/reline/key_stroke.rb b/ruby/lib/reline/key_stroke.rb index 83136edcf..c1c61513a 100644 --- a/ruby/lib/reline/key_stroke.rb +++ b/ruby/lib/reline/key_stroke.rb @@ -1,38 +1,88 @@ class Reline::KeyStroke - using Module.new { - refine Array do - def start_with?(other) - other.size <= size && other == self.take(other.size) + def initialize(config) + @config = config + end + + def compress_meta_key(ary) + return ary unless @config.convert_meta + ary.inject([]) { |result, key| + if result.size > 0 and result.last == "\e".ord + result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true) + else + result << key end + result + } + end - def bytes - self + def start_with?(me, other) + compressed_me = compress_meta_key(me) + compressed_other = compress_meta_key(other) + i = 0 + loop do + my_c = compressed_me[i] + other_c = compressed_other[i] + other_is_last = (i + 1) == compressed_other.size + me_is_last = (i + 1) == compressed_me.size + if my_c != other_c + if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta + return true + else + return false + end + elsif other_is_last + return true + elsif me_is_last + return false end + i += 1 end - } + end - def initialize(config) - @config = config + def equal?(me, other) + case me + when Array + compressed_me = compress_meta_key(me) + compressed_other = compress_meta_key(other) + compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) } + when Integer + if other.is_a?(Reline::Key) + if other.combined_char == "\e".ord + false + else + other.combined_char == me + end + else + me == other + end + when Reline::Key + if other.is_a?(Integer) + me.combined_char == other + else + me == other + end + end end def match_status(input) key_mapping.keys.select { |lhs| - lhs.start_with? input + start_with?(lhs, input) }.tap { |it| - return :matched if it.size == 1 && (it.max_by(&:size)&.size&.== input.size) - return :matching if it.size == 1 && (it.max_by(&:size)&.size&.!= input.size) + return :matched if it.size == 1 && equal?(it[0], input) + return :matching if it.size == 1 && !equal?(it[0], input) return :matched if it.max_by(&:size)&.size&.< input.size return :matching if it.size > 1 } key_mapping.keys.select { |lhs| - input.start_with? lhs + start_with?(input, lhs) }.tap { |it| return it.size > 0 ? :matched : :unmatched } end def expand(input) - lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).reverse.first + input = compress_meta_key(input) + lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last return input unless lhs rhs = key_mapping[lhs] @@ -42,6 +92,8 @@ def expand(input) expand(expand(rhs_bytes) + expand(input.drop(lhs.size))) when Symbol [rhs] + expand(input.drop(lhs.size)) + when Array + rhs end end diff --git a/ruby/lib/reline/kill_ring.rb b/ruby/lib/reline/kill_ring.rb index 842fd0469..bb3684b42 100644 --- a/ruby/lib/reline/kill_ring.rb +++ b/ruby/lib/reline/kill_ring.rb @@ -1,4 +1,6 @@ class Reline::KillRing + include Enumerable + module State FRESH = :fresh CONTINUED = :continued @@ -110,4 +112,14 @@ def yank_pop nil end end + + def each + start = head = @ring.head + loop do + break if head.nil? + yield head.str + head = head.backward + break if head == start + end + end end diff --git a/ruby/lib/reline/line_editor.rb b/ruby/lib/reline/line_editor.rb index 095a7b5a0..90cc4b2db 100644 --- a/ruby/lib/reline/line_editor.rb +++ b/ruby/lib/reline/line_editor.rb @@ -2,10 +2,10 @@ require 'reline/unicode' require 'tempfile' -require 'pathname' class Reline::LineEditor # TODO: undo + # TODO: Use "private alias_method" idiom after drop Ruby 2.5. attr_reader :line attr_reader :byte_pointer attr_accessor :confirm_multiline_termination_proc @@ -51,11 +51,7 @@ module CompletionState CompletionJourneyData = Struct.new('CompletionJourneyData', :preposing, :postposing, :list, :pointer) MenuInfo = Struct.new('MenuInfo', :target, :list) - CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/ - OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/ - NON_PRINTING_START = "\1" - NON_PRINTING_END = "\2" - WIDTH_SCANNER = /\G(?:#{NON_PRINTING_START}|#{NON_PRINTING_END}|#{CSI_REGEXP}|#{OSC_REGEXP}|\X)/ + PROMPT_LIST_CACHE_TIMEOUT = 0.5 def initialize(config, encoding) @config = config @@ -63,7 +59,41 @@ def initialize(config, encoding) reset_variables(encoding: encoding) end - private def check_multiline_prompt(buffer, prompt) + def set_pasting_state(in_pasting) + @in_pasting = in_pasting + end + + def simplified_rendering? + if finished? + false + elsif @just_cursor_moving and not @rerender_all + true + else + not @rerender_all and not finished? and @in_pasting + end + end + + private def check_mode_string + mode_string = nil + if @config.show_mode_in_prompt + if @config.editing_mode_is?(:vi_command) + mode_string = @config.vi_cmd_mode_string + elsif @config.editing_mode_is?(:vi_insert) + mode_string = @config.vi_ins_mode_string + elsif @config.editing_mode_is?(:emacs) + mode_string = @config.emacs_mode_string + else + mode_string = '?' + end + end + if mode_string != @prev_mode_string + @rerender_all = true + end + @prev_mode_string = mode_string + mode_string + end + + private def check_multiline_prompt(buffer) if @vi_arg prompt = "(arg: #{@vi_arg}) " @rerender_all = true @@ -73,13 +103,44 @@ def initialize(config, encoding) else prompt = @prompt end + if simplified_rendering? + mode_string = check_mode_string + prompt = mode_string + prompt if mode_string + return [prompt, calculate_width(prompt, true), [prompt] * buffer.size] + end if @prompt_proc - prompt_list = @prompt_proc.(buffer) + use_cached_prompt_list = false + if @cached_prompt_list + if @just_cursor_moving + use_cached_prompt_list = true + elsif Time.now.to_f < (@prompt_cache_time + PROMPT_LIST_CACHE_TIMEOUT) and buffer.size == @cached_prompt_list.size + use_cached_prompt_list = true + end + end + use_cached_prompt_list = false if @rerender_all + if use_cached_prompt_list + prompt_list = @cached_prompt_list + else + prompt_list = @cached_prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") } + @prompt_cache_time = Time.now.to_f + end prompt_list.map!{ prompt } if @vi_arg or @searching_prompt + prompt_list = [prompt] if prompt_list.empty? + mode_string = check_mode_string + prompt_list = prompt_list.map{ |pr| mode_string + pr } if mode_string prompt = prompt_list[@line_index] + prompt = prompt_list[0] if prompt.nil? + prompt = prompt_list.last if prompt.nil? + if buffer.size > prompt_list.size + (buffer.size - prompt_list.size).times do + prompt_list << prompt_list.last + end + end prompt_width = calculate_width(prompt, true) [prompt, prompt_width, prompt_list] else + mode_string = check_mode_string + prompt = mode_string + prompt if mode_string prompt_width = calculate_width(prompt, true) [prompt, prompt_width, nil] end @@ -88,51 +149,110 @@ def initialize(config, encoding) def reset(prompt = '', encoding:) @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y @screen_size = Reline::IOGate.get_screen_size + @screen_height = @screen_size.first reset_variables(prompt, encoding: encoding) - @old_trap = Signal.trap('SIGINT') { - @old_trap.call if @old_trap.respond_to?(:call) # can also be string, ex: "DEFAULT" - raise Interrupt - } Reline::IOGate.set_winch_handler do - @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y - old_screen_size = @screen_size - @screen_size = Reline::IOGate.get_screen_size - if old_screen_size.last < @screen_size.last # columns increase - @rerender_all = true - rerender - else - back = 0 - new_buffer = whole_lines - prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt) - new_buffer.each_with_index do |line, index| - prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc - width = prompt_width + calculate_width(line) - height = calculate_height_by_width(width) - back += height - end - @highest_in_all = back - @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) - @first_line_started_from = - if @line_index.zero? - 0 - else - calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list) - end - if @prompt_proc - prompt = prompt_list[@line_index] - prompt_width = calculate_width(prompt, true) + @resized = true + end + if ENV.key?('RELINE_ALT_SCROLLBAR') + @full_block = '::' + @upper_half_block = "''" + @lower_half_block = '..' + @block_elem_width = 2 + elsif Reline::IOGate.win? + @full_block = 'â–ˆ' + @upper_half_block = 'â–€' + @lower_half_block = 'â–„' + @block_elem_width = 1 + elsif @encoding == Encoding::UTF_8 + @full_block = 'â–ˆ' + @upper_half_block = 'â–€' + @lower_half_block = 'â–„' + @block_elem_width = Reline::Unicode.calculate_width('â–ˆ') + else + @full_block = '::' + @upper_half_block = "''" + @lower_half_block = '..' + @block_elem_width = 2 + end + end + + def resize + return unless @resized + @resized = false + @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y + old_screen_size = @screen_size + @screen_size = Reline::IOGate.get_screen_size + @screen_height = @screen_size.first + if old_screen_size.last < @screen_size.last # columns increase + @rerender_all = true + rerender + else + back = 0 + new_buffer = whole_lines + prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer) + new_buffer.each_with_index do |line, index| + prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc + width = prompt_width + calculate_width(line) + height = calculate_height_by_width(width) + back += height + end + @highest_in_all = back + @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) + @first_line_started_from = + if @line_index.zero? + 0 + else + calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) end - calculate_nearest_cursor - @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 - Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) - @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) - @rerender_all = true + if @prompt_proc + prompt = prompt_list[@line_index] + prompt_width = calculate_width(prompt, true) + end + calculate_nearest_cursor + @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) + @rerender_all = true + end + end + + def set_signal_handlers + @old_trap = Signal.trap('INT') { + clear_dialog + if @scroll_partial_screen + move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1) + else + move_cursor_down(@highest_in_all - @line_index - 1) end + Reline::IOGate.move_cursor_column(0) + scroll_down(1) + case @old_trap + when 'DEFAULT', 'SYSTEM_DEFAULT' + raise Interrupt + when 'IGNORE' + # Do nothing + when 'EXIT' + exit + else + @old_trap.call if @old_trap.respond_to?(:call) + end + } + begin + @old_tstp_trap = Signal.trap('TSTP') { + Reline::IOGate.ungetc("\C-z".ord) + @old_tstp_trap.call if @old_tstp_trap.respond_to?(:call) + } + rescue ArgumentError end end def finalize - Signal.trap('SIGINT', @old_trap) + Signal.trap('INT', @old_trap) + begin + Signal.trap('TSTP', @old_tstp_trap) + rescue ArgumentError + end end def eof? @@ -140,7 +260,7 @@ def eof? end def reset_variables(prompt = '', encoding:) - @prompt = prompt + @prompt = prompt.gsub("\n", "\\n") @mark_pointer = nil @encoding = encoding @is_multiline = false @@ -148,11 +268,12 @@ def reset_variables(prompt = '', encoding:) @cleared = false @rerender_all = false @history_pointer = nil - @kill_ring = Reline::KillRing.new + @kill_ring ||= Reline::KillRing.new @vi_clipboard = '' @vi_arg = nil @waiting_proc = nil @waiting_operator_proc = nil + @waiting_operator_vi_arg = nil @completion_journey_data = nil @completion_state = CompletionState::NORMAL @perfect_matched = nil @@ -160,7 +281,20 @@ def reset_variables(prompt = '', encoding:) @first_prompt = true @searching_prompt = nil @first_char = true + @add_newline_to_end_of_buffer = false + @just_cursor_moving = nil + @cached_prompt_list = nil + @prompt_cache_time = nil @eof = false + @continuous_insertion_buffer = String.new(encoding: @encoding) + @scroll_partial_screen = nil + @prev_mode_string = nil + @drop_terminate_spaces = false + @in_pasting = false + @auto_indent_proc = nil + @dialogs = [] + @last_key = nil + @resized = false reset_line end @@ -190,10 +324,10 @@ def multiline_off @is_multiline = false end - private def calculate_height_by_lines(lines, prompt_list) + private def calculate_height_by_lines(lines, prompt) result = 0 + prompt_list = prompt.is_a?(Array) ? prompt : nil lines.each_with_index { |line, i| - prompt = '' prompt = prompt_list[i] if prompt_list and prompt_list[i] result += calculate_height_by_width(calculate_width(prompt, true) + calculate_width(line)) } @@ -205,46 +339,15 @@ def multiline_off @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding)) @previous_line_index = @line_index @line_index += 1 + @just_cursor_moving = false end private def calculate_height_by_width(width) width.div(@screen_size.last) + 1 end - private def split_by_width(prompt, str, max_width) - lines = [String.new(encoding: @encoding)] - height = 1 - width = 0 - rest = "#{prompt}#{str}".encode(Encoding::UTF_8) - in_zero_width = false - rest.scan(WIDTH_SCANNER) do |gc| - case gc - when NON_PRINTING_START - in_zero_width = true - when NON_PRINTING_END - in_zero_width = false - when CSI_REGEXP, OSC_REGEXP - lines.last << gc - else - unless in_zero_width - mbchar_width = Reline::Unicode.get_mbchar_width(gc) - if (width += mbchar_width) > max_width - width = mbchar_width - lines << nil - lines << String.new(encoding: @encoding) - height += 1 - end - end - lines.last << gc - end - end - # The cursor moves to next line in first - if width == max_width - lines << nil - lines << String.new(encoding: @encoding) - height += 1 - end - [lines, height] + private def split_by_width(str, max_width) + Reline::Unicode.split_by_width(str, max_width, @encoding) end private def scroll_down(val) @@ -277,28 +380,29 @@ def multiline_off end end - private def calculate_nearest_cursor - @cursor_max = calculate_width(line) + private def calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true) + new_cursor_max = calculate_width(line_to_calc) new_cursor = 0 new_byte_pointer = 0 height = 1 max_width = @screen_size.last if @config.editing_mode_is?(:vi_command) - last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @line.bytesize) + last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize) if last_byte_size > 0 - last_mbchar = @line.byteslice(@line.bytesize - last_byte_size, last_byte_size) + last_mbchar = line_to_calc.byteslice(line_to_calc.bytesize - last_byte_size, last_byte_size) last_width = Reline::Unicode.get_mbchar_width(last_mbchar) - cursor_max = @cursor_max - last_width + end_of_line_cursor = new_cursor_max - last_width else - cursor_max = @cursor_max + end_of_line_cursor = new_cursor_max end else - cursor_max = @cursor_max + end_of_line_cursor = new_cursor_max end - @line.encode(Encoding::UTF_8).grapheme_clusters.each do |gc| - mbchar_width = Reline::Unicode.get_mbchar_width(gc) + line_to_calc.grapheme_clusters.each do |gc| + mbchar = gc.encode(Encoding::UTF_8) + mbchar_width = Reline::Unicode.get_mbchar_width(mbchar) now = new_cursor + mbchar_width - if now > cursor_max or now > @cursor + if now > end_of_line_cursor or now > cursor break end new_cursor += mbchar_width @@ -307,9 +411,21 @@ def multiline_off end new_byte_pointer += gc.bytesize end - @started_from = height - 1 - @cursor = new_cursor - @byte_pointer = new_byte_pointer + new_started_from = height - 1 + if update + @cursor = new_cursor + @cursor_max = new_cursor_max + @started_from = new_started_from + @byte_pointer = new_byte_pointer + else + [new_cursor, new_cursor_max, new_started_from, new_byte_pointer] + end + end + + def rerender_all + @rerender_all = true + process_insert(force: true) + rerender end def rerender @@ -317,178 +433,731 @@ def rerender if @menu_info scroll_down(@highest_in_all - @first_line_started_from) @rerender_all = true - @menu_info.list.sort!.each do |item| - Reline::IOGate.move_cursor_column(0) - @output.write item - @output.flush - scroll_down(1) - end - scroll_down(@highest_in_all - 1) - move_cursor_up(@highest_in_all - 1 - @first_line_started_from) + end + if @menu_info + show_menu @menu_info = nil end - prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt) + prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines) if @cleared - Reline::IOGate.clear_screen + clear_screen_buffer(prompt, prompt_list, prompt_width) @cleared = false - back = 0 - modify_lines(whole_lines).each_with_index do |line, index| - if @prompt_proc - pr = prompt_list[index] - height = render_partial(pr, calculate_width(pr), line, false) - else - height = render_partial(prompt, prompt_width, line, false) - end - if index < (@buffer_of_lines.size - 1) - move_cursor_down(height) - back += height - end - end - move_cursor_up(back) - move_cursor_down(@first_line_started_from + @started_from) - Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) return end - new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line)) - # FIXME: end of logical line sometimes breaks - if @previous_line_index or new_highest_in_this != @highest_in_this + if @is_multiline and finished? and @scroll_partial_screen + # Re-output all code higher than the screen when finished. + Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen) + Reline::IOGate.move_cursor_column(0) + @scroll_partial_screen = nil + prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines) if @previous_line_index new_lines = whole_lines(index: @previous_line_index, line: @line) else new_lines = whole_lines end - prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt) - all_height = calculate_height_by_lines(new_lines, prompt_list) - diff = all_height - @highest_in_all - move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1) - if diff > 0 - scroll_down(diff) - move_cursor_up(all_height - 1) - elsif diff < 0 - (-diff).times do - Reline::IOGate.move_cursor_column(0) - Reline::IOGate.erase_after_cursor - move_cursor_up(1) + modify_lines(new_lines).each_with_index do |line, index| + @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n" + Reline::IOGate.erase_after_cursor + end + @output.flush + clear_dialog + return + end + new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line)) + rendered = false + if @add_newline_to_end_of_buffer + rerender_added_newline(prompt, prompt_width) + @add_newline_to_end_of_buffer = false + else + if @just_cursor_moving and not @rerender_all + rendered = just_move_cursor + render_dialog((prompt_width + @cursor) % @screen_size.last) + @just_cursor_moving = false + return + elsif @previous_line_index or new_highest_in_this != @highest_in_this + rerender_changed_current_line + @previous_line_index = nil + rendered = true + elsif @rerender_all + rerender_all_lines + @rerender_all = false + rendered = true + else + end + end + if @is_multiline + if finished? + # Always rerender on finish because output_modifier_proc may return a different output. + if @previous_line_index + new_lines = whole_lines(index: @previous_line_index, line: @line) + else + new_lines = whole_lines end - move_cursor_up(all_height - 1) + line = modify_lines(new_lines)[@line_index] + clear_dialog + prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines) + render_partial(prompt, prompt_width, line, @first_line_started_from) + move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1) + scroll_down(1) + Reline::IOGate.move_cursor_column(0) + Reline::IOGate.erase_after_cursor else - move_cursor_up(all_height - 1) + if not rendered and not @in_pasting + line = modify_lines(whole_lines)[@line_index] + prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines) + render_partial(prompt, prompt_width, line, @first_line_started_from) + end + render_dialog((prompt_width + @cursor) % @screen_size.last) end - @highest_in_all = all_height - back = 0 - modify_lines(new_lines).each_with_index do |line, index| - if @prompt_proc - prompt = prompt_list[index] - prompt_width = calculate_width(prompt, true) + @buffer_of_lines[@line_index] = @line + @rest_height = 0 if @scroll_partial_screen + else + line = modify_lines(whole_lines)[@line_index] + render_partial(prompt, prompt_width, line, 0) + if finished? + scroll_down(1) + Reline::IOGate.move_cursor_column(0) + Reline::IOGate.erase_after_cursor + end + end + end + + class DialogProcScope + def initialize(line_editor, config, proc_to_exec, context) + @line_editor = line_editor + @config = config + @proc_to_exec = proc_to_exec + @context = context + @cursor_pos = Reline::CursorPos.new + end + + def context + @context + end + + def retrieve_completion_block(set_completion_quote_character = false) + @line_editor.retrieve_completion_block(set_completion_quote_character) + end + + def call_completion_proc_with_checking_args(pre, target, post) + @line_editor.call_completion_proc_with_checking_args(pre, target, post) + end + + def set_dialog(dialog) + @dialog = dialog + end + + def dialog + @dialog + end + + def set_cursor_pos(col, row) + @cursor_pos.x = col + @cursor_pos.y = row + end + + def set_key(key) + @key = key + end + + def key + @key + end + + def cursor_pos + @cursor_pos + end + + def just_cursor_moving + @line_editor.instance_variable_get(:@just_cursor_moving) + end + + def screen_width + @line_editor.instance_variable_get(:@screen_size).last + end + + def completion_journey_data + @line_editor.instance_variable_get(:@completion_journey_data) + end + + def config + @config + end + + def call + instance_exec(&@proc_to_exec) + end + end + + class Dialog + attr_reader :name, :contents, :width + attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key + + def initialize(name, config, proc_scope) + @name = name + @config = config + @proc_scope = proc_scope + @width = nil + @scroll_top = 0 + @trap_key = nil + end + + def set_cursor_pos(col, row) + @proc_scope.set_cursor_pos(col, row) + end + + def width=(v) + @width = v + end + + def contents=(contents) + @contents = contents + if contents and @width.nil? + @width = contents.map{ |line| Reline::Unicode.calculate_width(line, true) }.max + end + end + + def call(key) + @proc_scope.set_dialog(self) + @proc_scope.set_key(key) + dialog_render_info = @proc_scope.call + if @trap_key + if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap + @trap_key.each do |t| + @config.add_oneshot_key_binding(t, @name) + end + elsif @trap_key.is_a?(Array) + @config.add_oneshot_key_binding(@trap_key, @name) + elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key) + @config.add_oneshot_key_binding([@trap_key], @name) end - height = render_partial(prompt, prompt_width, line, false) - if index < (new_lines.size - 1) - scroll_down(1) - back += height - else - back += height - 1 + end + dialog_render_info + end + end + + def add_dialog_proc(name, p, context = nil) + dialog = Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context)) + if index = @dialogs.find_index { |d| d.name == name } + @dialogs[index] = dialog + else + @dialogs << dialog + end + end + + DIALOG_DEFAULT_HEIGHT = 20 + private def render_dialog(cursor_column) + @dialogs.each do |dialog| + render_each_dialog(dialog, cursor_column) + end + end + + private def padding_space_with_escape_sequences(str, width) + str + (' ' * (width - calculate_width(str, true))) + end + + private def render_each_dialog(dialog, cursor_column) + if @in_pasting + clear_each_dialog(dialog) + dialog.contents = nil + dialog.trap_key = nil + return + end + dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from) + dialog_render_info = dialog.call(@last_key) + if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty? + dialog.lines_backup = { + lines: modify_lines(whole_lines), + line_index: @line_index, + first_line_started_from: @first_line_started_from, + started_from: @started_from, + byte_pointer: @byte_pointer + } + clear_each_dialog(dialog) + dialog.contents = nil + dialog.trap_key = nil + return + end + old_dialog = dialog.clone + dialog.contents = dialog_render_info.contents + pointer = dialog.pointer + if dialog_render_info.width + dialog.width = dialog_render_info.width + else + dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max + end + height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT + height = dialog.contents.size if dialog.contents.size < height + if dialog.contents.size > height + if dialog.pointer + if dialog.pointer < 0 + dialog.scroll_top = 0 + elsif (dialog.pointer - dialog.scroll_top) >= (height - 1) + dialog.scroll_top = dialog.pointer - (height - 1) + elsif (dialog.pointer - dialog.scroll_top) < 0 + dialog.scroll_top = dialog.pointer end + pointer = dialog.pointer - dialog.scroll_top end - move_cursor_up(back) - if @previous_line_index - @buffer_of_lines[@previous_line_index] = @line - @line = @buffer_of_lines[@line_index] + dialog.contents = dialog.contents[dialog.scroll_top, height] + end + if dialog.contents and dialog.scroll_top >= dialog.contents.size + dialog.scroll_top = dialog.contents.size - height + end + if dialog_render_info.scrollbar and dialog_render_info.contents.size > height + bar_max_height = height * 2 + moving_distance = (dialog_render_info.contents.size - height) * 2 + position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance) + bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i + dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i + else + dialog.scrollbar_pos = nil + end + upper_space = @first_line_started_from - @started_from + dialog.column = dialog_render_info.pos.x + dialog.width += @block_elem_width if dialog.scrollbar_pos + diff = (dialog.column + dialog.width) - (@screen_size.last) + if diff > 0 + dialog.column -= diff + end + if (@rest_height - dialog_render_info.pos.y) >= height + dialog.vertical_offset = dialog_render_info.pos.y + 1 + elsif upper_space >= height + dialog.vertical_offset = dialog_render_info.pos.y - height + else + if (@rest_height - dialog_render_info.pos.y) < height + scroll_down(height + dialog_render_info.pos.y) + move_cursor_up(height + dialog_render_info.pos.y) + end + dialog.vertical_offset = dialog_render_info.pos.y + 1 + end + Reline::IOGate.hide_cursor + if dialog.column < 0 + dialog.column = 0 + dialog.width = @screen_size.last + end + reset_dialog(dialog, old_dialog) + move_cursor_down(dialog.vertical_offset) + Reline::IOGate.move_cursor_column(dialog.column) + dialog.contents.each_with_index do |item, i| + if i == pointer + bg_color = '45' + else + if dialog_render_info.bg_color + bg_color = dialog_render_info.bg_color + else + bg_color = '46' + end end - @first_line_started_from = - if @line_index.zero? - 0 + str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width) + str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width) + @output.write "\e[#{bg_color}m#{str}" + if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column) + @output.write "\e[37m" + if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height) + @output.write @full_block + elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height) + @output.write @upper_half_block + str += '' + elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height) + @output.write @lower_half_block else - calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list) + @output.write ' ' * @block_elem_width end - if @prompt_proc - prompt = prompt_list[@line_index] - prompt_width = calculate_width(prompt, true) end - move_cursor_down(@first_line_started_from) - calculate_nearest_cursor - @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 - move_cursor_down(@started_from) - Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) - @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) - @previous_line_index = nil - rendered = true - elsif @rerender_all - move_cursor_up(@first_line_started_from + @started_from) - Reline::IOGate.move_cursor_column(0) - back = 0 - new_buffer = whole_lines - prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt) - new_buffer.each_with_index do |line, index| - prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc - width = prompt_width + calculate_width(line) - height = calculate_height_by_width(width) - back += height + @output.write "\e[0m" + Reline::IOGate.move_cursor_column(dialog.column) + move_cursor_down(1) if i < (dialog.contents.size - 1) + end + Reline::IOGate.move_cursor_column(cursor_column) + move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1) + Reline::IOGate.show_cursor + dialog.lines_backup = { + lines: modify_lines(whole_lines), + line_index: @line_index, + first_line_started_from: @first_line_started_from, + started_from: @started_from, + byte_pointer: @byte_pointer + } + end + + private def reset_dialog(dialog, old_dialog) + return if dialog.lines_backup.nil? or old_dialog.contents.nil? + prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines]) + visual_lines = [] + visual_start = nil + dialog.lines_backup[:lines].each_with_index { |l, i| + pr = prompt_list ? prompt_list[i] : prompt + vl, _ = split_by_width(pr + l, @screen_size.last) + vl.compact! + if i == dialog.lines_backup[:line_index] + visual_start = visual_lines.size + dialog.lines_backup[:started_from] end - if back > @highest_in_all - scroll_down(back - 1) - move_cursor_up(back - 1) - elsif back < @highest_in_all - scroll_down(back) - Reline::IOGate.erase_after_cursor - (@highest_in_all - back - 1).times do - scroll_down(1) - Reline::IOGate.erase_after_cursor + visual_lines.concat(vl) + } + old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from] + y = @first_line_started_from + @started_from + y_diff = y - old_y + if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset) + # rerender top + move_cursor_down(old_dialog.vertical_offset - y_diff) + start = visual_start + old_dialog.vertical_offset + line_num = dialog.vertical_offset - old_dialog.vertical_offset + line_num.times do |i| + Reline::IOGate.move_cursor_column(old_dialog.column) + if visual_lines[start + i].nil? + s = ' ' * old_dialog.width + else + s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width) + s = padding_space_with_escape_sequences(s, old_dialog.width) end - move_cursor_up(@highest_in_all - 1) - end - modify_lines(new_buffer).each_with_index do |line, index| - if @prompt_proc - prompt = prompt_list[index] - prompt_width = calculate_width(prompt, true) + @output.write "\e[0m#{s}\e[0m" + move_cursor_down(1) if i < (line_num - 1) + end + move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff) + end + if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size) + # rerender bottom + move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff) + start = visual_start + dialog.vertical_offset + dialog.contents.size + line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size) + line_num.times do |i| + Reline::IOGate.move_cursor_column(old_dialog.column) + if visual_lines[start + i].nil? + s = ' ' * old_dialog.width + else + s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width) + s = padding_space_with_escape_sequences(s, old_dialog.width) end - render_partial(prompt, prompt_width, line, false) - if index < (new_buffer.size - 1) - move_cursor_down(1) + @output.write "\e[0m#{s}\e[0m" + move_cursor_down(1) if i < (line_num - 1) + end + move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff) + end + if old_dialog.column < dialog.column + # rerender left + move_cursor_down(old_dialog.vertical_offset - y_diff) + width = dialog.column - old_dialog.column + start = visual_start + old_dialog.vertical_offset + line_num = old_dialog.contents.size + line_num.times do |i| + Reline::IOGate.move_cursor_column(old_dialog.column) + if visual_lines[start + i].nil? + s = ' ' * width + else + s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width) + s = padding_space_with_escape_sequences(s, dialog.width) + end + @output.write "\e[0m#{s}\e[0m" + move_cursor_down(1) if i < (line_num - 1) + end + move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff) + end + if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width) + # rerender right + move_cursor_down(old_dialog.vertical_offset + y_diff) + width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width) + start = visual_start + old_dialog.vertical_offset + line_num = old_dialog.contents.size + line_num.times do |i| + Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width) + if visual_lines[start + i].nil? + s = ' ' * width + else + s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width) + rerender_width = old_dialog.width - dialog.width + s = padding_space_with_escape_sequences(s, rerender_width) end + Reline::IOGate.move_cursor_column(dialog.column + dialog.width) + @output.write "\e[0m#{s}\e[0m" + move_cursor_down(1) if i < (line_num - 1) end - move_cursor_up(back - 1) - if @prompt_proc - prompt = prompt_list[@line_index] - prompt_width = calculate_width(prompt, true) + move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff) + end + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + end + + private def clear_dialog + @dialogs.each do |dialog| + clear_each_dialog(dialog) + end + end + + private def clear_each_dialog(dialog) + dialog.trap_key = nil + return unless dialog.contents + prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines]) + visual_lines = [] + visual_lines_under_dialog = [] + visual_start = nil + dialog.lines_backup[:lines].each_with_index { |l, i| + pr = prompt_list ? prompt_list[i] : prompt + vl, _ = split_by_width(pr + l, @screen_size.last) + vl.compact! + if i == dialog.lines_backup[:line_index] + visual_start = visual_lines.size + dialog.lines_backup[:started_from] + dialog.vertical_offset end - @highest_in_all = back - @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) - @first_line_started_from = - if @line_index.zero? - 0 + visual_lines.concat(vl) + } + visual_lines_under_dialog = visual_lines[visual_start, dialog.contents.size] + visual_lines_under_dialog = [] if visual_lines_under_dialog.nil? + Reline::IOGate.hide_cursor + move_cursor_down(dialog.vertical_offset) + dialog_vertical_size = dialog.contents.size + dialog_vertical_size.times do |i| + if i < visual_lines_under_dialog.size + Reline::IOGate.move_cursor_column(dialog.column) + str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width) + str = padding_space_with_escape_sequences(str, dialog.width) + @output.write "\e[0m#{str}\e[0m" + else + Reline::IOGate.move_cursor_column(dialog.column) + @output.write "\e[0m#{' ' * dialog.width}\e[0m" + end + move_cursor_down(1) if i < (dialog_vertical_size - 1) + end + move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset) + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + Reline::IOGate.show_cursor + end + + private def calculate_scroll_partial_screen(highest_in_all, cursor_y) + if @screen_height < highest_in_all + old_scroll_partial_screen = @scroll_partial_screen + if cursor_y == 0 + @scroll_partial_screen = 0 + elsif cursor_y == (highest_in_all - 1) + @scroll_partial_screen = highest_in_all - @screen_height + else + if @scroll_partial_screen + if cursor_y <= @scroll_partial_screen + @scroll_partial_screen = cursor_y + elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y + @scroll_partial_screen = cursor_y - (@screen_height - 1) + end else - calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list) + if cursor_y > (@screen_height - 1) + @scroll_partial_screen = cursor_y - (@screen_height - 1) + else + @scroll_partial_screen = 0 + end end - @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 - move_cursor_down(@first_line_started_from + @started_from) - Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + end + if @scroll_partial_screen != old_scroll_partial_screen + @rerender_all = true + end + else + if @scroll_partial_screen + @rerender_all = true + end + @scroll_partial_screen = nil + end + end + + private def rerender_added_newline(prompt, prompt_width) + scroll_down(1) + @buffer_of_lines[@previous_line_index] = @line + @line = @buffer_of_lines[@line_index] + unless @in_pasting + render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false) + end + @cursor = @cursor_max = calculate_width(@line) + @byte_pointer = @line.bytesize + @highest_in_all += @highest_in_this + @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) + @first_line_started_from += @started_from + 1 + @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 + @previous_line_index = nil + end + + def just_move_cursor + prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines) + move_cursor_up(@started_from) + new_first_line_started_from = + if @line_index.zero? + 0 + else + calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) + end + first_line_diff = new_first_line_started_from - @first_line_started_from + new_cursor, new_cursor_max, new_started_from, new_byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false) + new_started_from = calculate_height_by_width(prompt_width + new_cursor) - 1 + calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from) + @previous_line_index = nil + if @rerender_all + @line = @buffer_of_lines[@line_index] + rerender_all_lines @rerender_all = false - rendered = true + true + else + @line = @buffer_of_lines[@line_index] + @first_line_started_from = new_first_line_started_from + @started_from = new_started_from + @cursor = new_cursor + @cursor_max = new_cursor_max + @byte_pointer = new_byte_pointer + move_cursor_down(first_line_diff + @started_from) + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + false + end + end + + private def rerender_changed_current_line + if @previous_line_index + new_lines = whole_lines(index: @previous_line_index, line: @line) + else + new_lines = whole_lines + end + prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines) + all_height = calculate_height_by_lines(new_lines, prompt_list || prompt) + diff = all_height - @highest_in_all + move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1) + if diff > 0 + scroll_down(diff) + move_cursor_up(all_height - 1) + elsif diff < 0 + (-diff).times do + Reline::IOGate.move_cursor_column(0) + Reline::IOGate.erase_after_cursor + move_cursor_up(1) + end + move_cursor_up(all_height - 1) + else + move_cursor_up(all_height - 1) + end + @highest_in_all = all_height + back = render_whole_lines(new_lines, prompt_list || prompt, prompt_width) + move_cursor_up(back) + if @previous_line_index + @buffer_of_lines[@previous_line_index] = @line + @line = @buffer_of_lines[@line_index] + end + @first_line_started_from = + if @line_index.zero? + 0 + else + calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) + end + if @prompt_proc + prompt = prompt_list[@line_index] + prompt_width = calculate_width(prompt, true) + end + move_cursor_down(@first_line_started_from) + calculate_nearest_cursor + @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 + move_cursor_down(@started_from) + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) + end + + private def rerender_all_lines + move_cursor_up(@first_line_started_from + @started_from) + Reline::IOGate.move_cursor_column(0) + back = 0 + new_buffer = whole_lines + prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer) + new_buffer.each_with_index do |line, index| + prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc + width = prompt_width + calculate_width(line) + height = calculate_height_by_width(width) + back += height + end + old_highest_in_all = @highest_in_all + if @line_index.zero? + new_first_line_started_from = 0 + else + new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt) end - line = modify_lines(whole_lines)[@line_index] - if @is_multiline - prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt) - if finished? - # Always rerender on finish because output_modifier_proc may return a different output. - render_partial(prompt, prompt_width, line) + new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1 + calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from) + if @scroll_partial_screen + move_cursor_up(@first_line_started_from + @started_from) + scroll_down(@screen_height - 1) + move_cursor_up(@screen_height) + Reline::IOGate.move_cursor_column(0) + elsif back > old_highest_in_all + scroll_down(back - 1) + move_cursor_up(back - 1) + elsif back < old_highest_in_all + scroll_down(back) + Reline::IOGate.erase_after_cursor + (old_highest_in_all - back - 1).times do scroll_down(1) - Reline::IOGate.move_cursor_column(0) Reline::IOGate.erase_after_cursor - elsif not rendered - render_partial(prompt, prompt_width, line) end + move_cursor_up(old_highest_in_all - 1) + end + render_whole_lines(new_buffer, prompt_list || prompt, prompt_width) + if @prompt_proc + prompt = prompt_list[@line_index] + prompt_width = calculate_width(prompt, true) + end + @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) + @highest_in_all = back + @first_line_started_from = new_first_line_started_from + @started_from = new_started_from + if @scroll_partial_screen + Reline::IOGate.move_cursor_up(@screen_height - (@first_line_started_from + @started_from - @scroll_partial_screen) - 1) + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) else - render_partial(prompt, prompt_width, line) - if finished? - scroll_down(1) - Reline::IOGate.move_cursor_column(0) - Reline::IOGate.erase_after_cursor + move_cursor_down(@first_line_started_from + @started_from - back + 1) + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + end + end + + private def render_whole_lines(lines, prompt, prompt_width) + rendered_height = 0 + modify_lines(lines).each_with_index do |line, index| + if prompt.is_a?(Array) + line_prompt = prompt[index] + prompt_width = calculate_width(line_prompt, true) + else + line_prompt = prompt + end + height = render_partial(line_prompt, prompt_width, line, rendered_height, with_control: false) + if index < (lines.size - 1) + if @scroll_partial_screen + if (@scroll_partial_screen - height) < rendered_height and (@scroll_partial_screen + @screen_height - 1) >= (rendered_height + height) + move_cursor_down(1) + end + else + scroll_down(1) + end + rendered_height += height + else + rendered_height += height - 1 end end + rendered_height end - private def render_partial(prompt, prompt_width, line_to_render, with_control = true) - visual_lines, height = split_by_width(prompt, line_to_render.nil? ? '' : line_to_render, @screen_size.last) + private def render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true) + visual_lines, height = split_by_width(line_to_render.nil? ? prompt : prompt + line_to_render, @screen_size.last) + cursor_up_from_last_line = 0 + if @scroll_partial_screen + last_visual_line = this_started_from + (height - 1) + last_screen_line = @scroll_partial_screen + (@screen_height - 1) + if (@scroll_partial_screen - this_started_from) >= height + # Render nothing because this line is before the screen. + visual_lines = [] + elsif this_started_from > last_screen_line + # Render nothing because this line is after the screen. + visual_lines = [] + else + deleted_lines_before_screen = [] + if @scroll_partial_screen > this_started_from and last_visual_line >= @scroll_partial_screen + # A part of visual lines are before the screen. + deleted_lines_before_screen = visual_lines.shift((@scroll_partial_screen - this_started_from) * 2) + deleted_lines_before_screen.compact! + end + if this_started_from <= last_screen_line and last_screen_line < last_visual_line + # A part of visual lines are after the screen. + visual_lines.pop((last_visual_line - last_screen_line) * 2) + end + move_cursor_up(deleted_lines_before_screen.size - @started_from) + cursor_up_from_last_line = @started_from - deleted_lines_before_screen.size + end + end if with_control if height > @highest_in_this diff = height - @highest_in_this @@ -503,12 +1172,26 @@ def rerender end move_cursor_up(@started_from) @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 + cursor_up_from_last_line = height - 1 - @started_from + end + if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render) + @output.write "\e[0m" # clear character decorations end - Reline::IOGate.move_cursor_column(0) visual_lines.each_with_index do |line, index| + Reline::IOGate.move_cursor_column(0) if line.nil? - if Reline::IOGate.win? and calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last - # A newline is automatically inserted if a character is rendered at eol on command prompt. + if calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last + # reaches the end of line + if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? + # A newline is automatically inserted if a character is rendered at + # eol on command prompt. + else + # When the cursor is at the end of the line and erases characters + # after the cursor, some terminals delete the character at the + # cursor position. + move_cursor_down(1) + Reline::IOGate.move_cursor_column(0) + end else Reline::IOGate.erase_after_cursor move_cursor_down(1) @@ -517,7 +1200,7 @@ def rerender next end @output.write line - if Reline::IOGate.win? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last + if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last # A newline is automatically inserted if a character is rendered at eol on command prompt. @rest_height -= 1 if @rest_height > 0 end @@ -527,28 +1210,68 @@ def rerender @pre_input_hook&.call end end - Reline::IOGate.erase_after_cursor + unless visual_lines.empty? + Reline::IOGate.erase_after_cursor + Reline::IOGate.move_cursor_column(0) + end if with_control - move_cursor_up(height - 1) + # Just after rendring, so the cursor is on the last line. if finished? - move_cursor_down(@started_from) + Reline::IOGate.move_cursor_column(0) + else + # Moves up from bottom of lines to the cursor position. + move_cursor_up(cursor_up_from_last_line) + # This logic is buggy if a fullwidth char is wrapped because there is only one halfwidth at end of a line. + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end - move_cursor_down(@started_from) - Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end height end private def modify_lines(before) - return before if before.nil? || before.empty? + return before if before.nil? || before.empty? || simplified_rendering? if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: finished?) - after.lines("\n", chomp: true) + after.lines("\n").map { |l| l.chomp('') } else before end end + private def show_menu + scroll_down(@highest_in_all - @first_line_started_from) + @rerender_all = true + @menu_info.list.sort!.each do |item| + Reline::IOGate.move_cursor_column(0) + @output.write item + @output.flush + scroll_down(1) + end + scroll_down(@highest_in_all - 1) + move_cursor_up(@highest_in_all - 1 - @first_line_started_from) + end + + private def clear_screen_buffer(prompt, prompt_list, prompt_width) + Reline::IOGate.clear_screen + back = 0 + modify_lines(whole_lines).each_with_index do |line, index| + if @prompt_proc + pr = prompt_list[index] + height = render_partial(pr, calculate_width(pr), line, back, with_control: false) + else + height = render_partial(prompt, prompt_width, line, back, with_control: false) + end + if index < (@buffer_of_lines.size - 1) + move_cursor_down(1) + back += height + end + end + move_cursor_up(back) + move_cursor_down(@first_line_started_from + @started_from) + @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y + Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + end + def editing_mode @config.editing_mode end @@ -568,7 +1291,7 @@ def editing_mode else i&.start_with?(target) end - } + }.uniq if is_menu menu(target, list) return nil @@ -658,6 +1381,16 @@ def editing_mode @completion_journey_data = CompletionJourneyData.new( preposing, postposing, [target] + list.select{ |item| item.start_with?(target) }, 0) + if @completion_journey_data.list.size == 1 + @completion_journey_data.pointer = 0 + else + case direction + when :up + @completion_journey_data.pointer = @completion_journey_data.list.size - 1 + when :down + @completion_journey_data.pointer = 1 + end + end @completion_state = CompletionState::JOURNEY else case direction @@ -672,20 +1405,23 @@ def editing_mode @completion_journey_data.pointer = 0 end end - completed = @completion_journey_data.list[@completion_journey_data.pointer] - @line = @completion_journey_data.preposing + completed + @completion_journey_data.postposing - line_to_pointer = @completion_journey_data.preposing + completed - @cursor_max = calculate_width(@line) - @cursor = calculate_width(line_to_pointer) - @byte_pointer = line_to_pointer.bytesize end + completed = @completion_journey_data.list[@completion_journey_data.pointer] + new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index] + @line = new_line.nil? ? String.new(encoding: @encoding) : new_line + line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last + line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil? + @cursor_max = calculate_width(@line) + @cursor = calculate_width(line_to_pointer) + @byte_pointer = line_to_pointer.bytesize end private def run_for_operators(key, method_symbol, &block) if @waiting_operator_proc if VI_MOTIONS.include?(method_symbol) old_cursor, old_byte_pointer = @cursor, @byte_pointer - block.() + @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg > 1 + block.(true) unless @waiting_proc cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer @cursor, @byte_pointer = old_cursor, old_byte_pointer @@ -693,27 +1429,59 @@ def editing_mode else old_waiting_proc = @waiting_proc old_waiting_operator_proc = @waiting_operator_proc + current_waiting_operator_proc = @waiting_operator_proc @waiting_proc = proc { |k| old_cursor, old_byte_pointer = @cursor, @byte_pointer old_waiting_proc.(k) cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer @cursor, @byte_pointer = old_cursor, old_byte_pointer - @waiting_operator_proc.(cursor_diff, byte_pointer_diff) + current_waiting_operator_proc.(cursor_diff, byte_pointer_diff) @waiting_operator_proc = old_waiting_operator_proc } end else # Ignores operator when not motion is given. - block.() + block.(false) end @waiting_operator_proc = nil + @waiting_operator_vi_arg = nil + if @vi_arg + @rerender_all = true + @vi_arg = nil + end else - block.() + block.(false) end end private def argumentable?(method_obj) - method_obj and method_obj.parameters.length != 1 + method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg } + end + + private def inclusive?(method_obj) + # If a motion method with the keyword argument "inclusive" follows the + # operator, it must contain the character at the cursor position. + method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive } + end + + def wrap_method_call(method_symbol, method_obj, key, with_operator = false) + if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil? + not_insertion = method_symbol != :ed_insert + process_insert(force: not_insertion) + end + if @vi_arg and argumentable?(method_obj) + if with_operator and inclusive?(method_obj) + method_obj.(key, arg: @vi_arg, inclusive: true) + else + method_obj.(key, arg: @vi_arg) + end + else + if with_operator and inclusive?(method_obj) + method_obj.(key, inclusive: true) + else + method_obj.(key) + end + end end private def process_key(key, method_symbol) @@ -724,46 +1492,52 @@ def editing_mode end if method_symbol and key.is_a?(Symbol) if @vi_arg and argumentable?(method_obj) - run_for_operators(key, method_symbol) do - method_obj.(key, arg: @vi_arg) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end else - method_obj&.(key) + wrap_method_call(method_symbol, method_obj, key) if method_obj end @kill_ring.process - @vi_arg = nil + if @vi_arg + @rerender_al = true + @vi_arg = nil + end elsif @vi_arg if key.chr =~ /[0-9]/ ed_argument_digit(key) else if argumentable?(method_obj) - run_for_operators(key, method_symbol) do - method_obj.(key, arg: @vi_arg) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end elsif @waiting_proc @waiting_proc.(key) elsif method_obj - method_obj.(key) + wrap_method_call(method_symbol, method_obj, key) else - ed_insert(key) + ed_insert(key) unless @config.editing_mode_is?(:vi_command) end @kill_ring.process - @vi_arg = nil + if @vi_arg + @rerender_all = true + @vi_arg = nil + end end elsif @waiting_proc @waiting_proc.(key) @kill_ring.process elsif method_obj if method_symbol == :ed_argument_digit - method_obj.(key) + wrap_method_call(method_symbol, method_obj, key) else - run_for_operators(key, method_symbol) do - method_obj.(key) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end end @kill_ring.process else - ed_insert(key) + ed_insert(key) unless @config.editing_mode_is?(:vi_command) end end @@ -806,6 +1580,14 @@ def editing_mode end def input_key(key) + @last_key = key + @config.reset_oneshot_key_bindings + @dialogs.each do |dialog| + if key.char.instance_of?(Symbol) and key.char == dialog.name + return + end + end + @just_cursor_moving = nil if key.char.nil? if @first_char @line = nil @@ -813,6 +1595,7 @@ def input_key(key) finish return end + old_line = @line.dup @first_char = false completion_occurs = false if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord @@ -820,7 +1603,21 @@ def input_key(key) result = call_completion_proc if result.is_a?(Array) completion_occurs = true - complete(result) + process_insert + if @config.autocompletion + move_completed_list(result, :down) + else + complete(result) + end + end + end + elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up + if not @config.disable_completion and @config.autocompletion + result = call_completion_proc + if result.is_a?(Array) + completion_occurs = true + process_insert + move_completed_list(result, :up) end end elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char) @@ -828,6 +1625,7 @@ def input_key(key) result = call_completion_proc if result.is_a?(Array) completion_occurs = true + process_insert move_completed_list(result, "\C-p".ord == key.char ? :up : :down) end end @@ -838,20 +1636,54 @@ def input_key(key) end unless completion_occurs @completion_state = CompletionState::NORMAL + @completion_journey_data = nil + end + if not @in_pasting and @just_cursor_moving.nil? + if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line + @just_cursor_moving = true + elsif @previous_line_index.nil? and @buffer_of_lines[@line_index] == @line and old_line == @line + @just_cursor_moving = true + else + @just_cursor_moving = false + end + else + @just_cursor_moving = false end - if @is_multiline and @auto_indent_proc + if @is_multiline and @auto_indent_proc and not simplified_rendering? process_auto_indent end end def call_completion_proc result = retrieve_completion_block(true) - slice = result[1] - result = @completion_proc.(slice) if @completion_proc and slice + pre, target, post = result + result = call_completion_proc_with_checking_args(pre, target, post) Reline.core.instance_variable_set(:@completion_quote_character, nil) result end + def call_completion_proc_with_checking_args(pre, target, post) + if @completion_proc and target + argnum = @completion_proc.parameters.inject(0) { |result, item| + case item.first + when :req, :opt + result + 1 + when :rest + break 3 + end + } + case argnum + when 1 + result = @completion_proc.(target) + when 2 + result = @completion_proc.(target, pre) + when 3..Float::INFINITY + result = @completion_proc.(target, pre, post) + end + end + result + end + private def process_auto_indent return if not @check_new_auto_indent and @previous_line_index # move cursor up or down if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index @@ -877,6 +1709,7 @@ def call_completion_proc new_lines = whole_lines end new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent) + new_indent = @cursor_max if new_indent&.> @cursor_max if new_indent&.>= 0 md = new_lines[@line_index].match(/\A */) prev_indent = md[0].count(' ') @@ -894,8 +1727,16 @@ def call_completion_proc end def retrieve_completion_block(set_completion_quote_character = false) - word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/ - quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/ + if Reline.completer_word_break_characters.empty? + word_break_regexp = nil + else + word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/ + end + if Reline.completer_quote_characters.empty? + quote_characters_regexp = nil + else + quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/ + end before = @line.byteslice(0, @byte_pointer) rest = nil break_pointer = nil @@ -916,14 +1757,14 @@ def retrieve_completion_block(set_completion_quote_character = false) elsif quote and slice.start_with?(escaped_quote) # skip i += 2 - elsif slice =~ quote_characters_regexp # find new " + elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new " rest = $' quote = $& closing_quote = /(?!\\)#{Regexp.escape(quote)}/ escaped_quote = /\\#{Regexp.escape(quote)}/ i += 1 break_pointer = i - 1 - elsif not quote and slice =~ word_break_regexp + elsif word_break_regexp and not quote and slice =~ word_break_regexp rest = $' i += 1 before = @line.byteslice(i, @byte_pointer - i) @@ -951,6 +1792,19 @@ def retrieve_completion_block(set_completion_quote_character = false) end target = before end + if @is_multiline + if @previous_line_index + lines = whole_lines(index: @previous_line_index, line: @line) + else + lines = whole_lines + end + if @line_index > 0 + preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing + end + if (lines.size - 1) > @line_index + postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n") + end + end [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)] end @@ -978,10 +1832,32 @@ def insert_text(text) def delete_text(start = nil, length = nil) if start.nil? and length.nil? - @line&.clear - @byte_pointer = 0 - @cursor = 0 - @cursor_max = 0 + if @is_multiline + if @buffer_of_lines.size == 1 + @line&.clear + @byte_pointer = 0 + @cursor = 0 + @cursor_max = 0 + elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0 + @buffer_of_lines.pop + @line_index -= 1 + @line = @buffer_of_lines[@line_index] + @byte_pointer = 0 + @cursor = 0 + @cursor_max = calculate_width(@line) + elsif @line_index < (@buffer_of_lines.size - 1) + @buffer_of_lines.delete_at(@line_index) + @line = @buffer_of_lines[@line_index] + @byte_pointer = 0 + @cursor = 0 + @cursor_max = calculate_width(@line) + end + else + @line&.clear + @byte_pointer = 0 + @cursor = 0 + @cursor_max = 0 + end elsif not start.nil? and not length.nil? if @line before = @line.byteslice(0, start) @@ -1031,7 +1907,11 @@ def whole_buffer if @buffer_of_lines.size == 1 and @line.nil? nil else - whole_lines.join("\n") + if @previous_line_index + whole_lines(index: @previous_line_index, line: @line).join("\n") + else + whole_lines.join("\n") + end end end @@ -1041,6 +1921,7 @@ def finished? def finish @finished = true + @rerender_all = true @config.reset end @@ -1058,29 +1939,7 @@ def finish end private def calculate_width(str, allow_escape_code = false) - if allow_escape_code - width = 0 - rest = str.encode(Encoding::UTF_8) - in_zero_width = false - rest.scan(WIDTH_SCANNER) do |gc| - case gc - when NON_PRINTING_START - in_zero_width = true - when NON_PRINTING_END - in_zero_width = false - when CSI_REGEXP, OSC_REGEXP - else - unless in_zero_width - width += Reline::Unicode.get_mbchar_width(gc) - end - end - end - width - else - str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc| - w + Reline::Unicode.get_mbchar_width(gc) - } - end + Reline::Unicode.calculate_width(str, allow_escape_code) end private def key_delete(key) @@ -1091,48 +1950,98 @@ def finish private def key_newline(key) if @is_multiline + if (@buffer_of_lines.size - 1) == @line_index and @line.bytesize == @byte_pointer + @add_newline_to_end_of_buffer = true + end next_line = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer) cursor_line = @line.byteslice(0, @byte_pointer) insert_new_line(cursor_line, next_line) @cursor = 0 - @check_new_auto_indent = true + @check_new_auto_indent = true unless @in_pasting end end + # Editline:: +ed-unassigned+ This editor command always results in an error. + # GNU Readline:: There is no corresponding macro. private def ed_unassigned(key) end # do nothing + private def process_insert(force: false) + return if @continuous_insertion_buffer.empty? or (@in_pasting and not force) + width = Reline::Unicode.calculate_width(@continuous_insertion_buffer) + bytesize = @continuous_insertion_buffer.bytesize + if @cursor == @cursor_max + @line += @continuous_insertion_buffer + else + @line = byteinsert(@line, @byte_pointer, @continuous_insertion_buffer) + end + @byte_pointer += bytesize + @cursor += width + @cursor_max += width + @continuous_insertion_buffer.clear + end + + # Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters) + # In insert mode, insert the input character left of the cursor + # position. In replace mode, overwrite the character at the + # cursor and move the cursor to the right by one character + # position. Accept an argument to do this repeatedly. It is an + # error if the input character is the NUL character (+Ctrl-@+). + # Failure to enlarge the edit buffer also results in an error. + # Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append + # the input digit to the argument being read. Otherwise, call + # +ed-insert+. It is an error if the input character is not a + # digit or if the existing argument is already greater than a + # million. + # GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself. private def ed_insert(key) + str = nil + width = nil + bytesize = nil if key.instance_of?(String) begin key.encode(Encoding::UTF_8) rescue Encoding::UndefinedConversionError return end - width = Reline::Unicode.get_mbchar_width(key) - if @cursor == @cursor_max - @line += key - else - @line = byteinsert(@line, @byte_pointer, key) - end - @byte_pointer += key.bytesize - @cursor += width - @cursor_max += width + str = key + bytesize = key.bytesize else begin key.chr.encode(Encoding::UTF_8) rescue Encoding::UndefinedConversionError return end - if @cursor == @cursor_max - @line += key.chr + str = key.chr + bytesize = 1 + end + if @in_pasting + @continuous_insertion_buffer << str + return + elsif not @continuous_insertion_buffer.empty? + process_insert + end + width = Reline::Unicode.get_mbchar_width(str) + if @cursor == @cursor_max + @line += str + else + @line = byteinsert(@line, @byte_pointer, str) + end + last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) + @byte_pointer += bytesize + last_mbchar = @line.byteslice((@byte_pointer - bytesize - last_byte_size), last_byte_size) + combined_char = last_mbchar + str + if last_byte_size != 0 and combined_char.grapheme_clusters.size == 1 + # combined char + last_mbchar_width = Reline::Unicode.get_mbchar_width(last_mbchar) + combined_char_width = Reline::Unicode.get_mbchar_width(combined_char) + if combined_char_width > last_mbchar_width + width = combined_char_width - last_mbchar_width else - @line = byteinsert(@line, @byte_pointer, key.chr) + width = 0 end - width = Reline::Unicode.get_mbchar_width(key.chr) - @byte_pointer += 1 - @cursor += width - @cursor_max += width end + @cursor += width + @cursor_max += width end alias_method :ed_digit, :ed_insert alias_method :self_insert, :ed_insert @@ -1142,6 +2051,8 @@ def finish arg.times do if key == "\C-j".ord or key == "\C-m".ord key_newline(key) + elsif key == 0 + # Ignore NUL. else ed_insert(key) end @@ -1189,6 +2100,7 @@ def finish arg -= 1 ed_prev_char(key, arg: arg) if arg > 0 end + alias_method :backward_char, :ed_prev_char private def vi_first_print(key) @byte_pointer, @cursor = Reline::Unicode.vi_first_print(@line) @@ -1258,7 +2170,7 @@ def finish if search_word.empty? and Reline.last_incremental_search search_word = Reline.last_incremental_search end - if @history_pointer # TODO + if @history_pointer case prev_search_key when "\C-r".ord history_pointer_base = 0 @@ -1330,7 +2242,7 @@ def finish end end - private def search_history(key) + private def incremental_search_history(key) unless @history_pointer if @is_multiline @line_backup_in_history = whole_buffer @@ -1341,9 +2253,11 @@ def finish searcher = generate_searcher searcher.resume(key) @searching_prompt = "(reverse-i-search)`': " + termination_keys = ["\C-j".ord] + termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators @waiting_proc = ->(k) { case k - when "\C-j".ord + when *termination_keys if @history_pointer buffer = Reline::HISTORY[@history_pointer] else @@ -1362,6 +2276,8 @@ def finish @waiting_proc = nil @cursor_max = calculate_width(@line) @cursor = @byte_pointer = 0 + @rerender_all = true + @cached_prompt_list = nil searcher.resume(-1) when "\C-g".ord if @is_multiline @@ -1405,21 +2321,122 @@ def finish @waiting_proc = nil @cursor_max = calculate_width(@line) @cursor = @byte_pointer = 0 + @rerender_all = true + @cached_prompt_list = nil searcher.resume(-1) end end } end - private def ed_search_prev_history(key) - search_history(key) + private def vi_search_prev(key) + incremental_search_history(key) + end + alias_method :reverse_search_history, :vi_search_prev + + private def vi_search_next(key) + incremental_search_history(key) end - alias_method :reverse_search_history, :ed_search_prev_history + alias_method :forward_search_history, :vi_search_next - private def ed_search_next_history(key) - search_history(key) + private def ed_search_prev_history(key, arg: 1) + history = nil + h_pointer = nil + line_no = nil + substr = @line.slice(0, @byte_pointer) + if @history_pointer.nil? + return if not @line.empty? and substr.empty? + history = Reline::HISTORY + elsif @history_pointer.zero? + history = nil + h_pointer = nil + else + history = Reline::HISTORY.slice(0, @history_pointer) + end + return if history.nil? + if @is_multiline + h_pointer = history.rindex { |h| + h.split("\n").each_with_index { |l, i| + if l.start_with?(substr) + line_no = i + break + end + } + not line_no.nil? + } + else + h_pointer = history.rindex { |l| + l.start_with?(substr) + } + end + return if h_pointer.nil? + @history_pointer = h_pointer + if @is_multiline + @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = line_no + @line = @buffer_of_lines[@line_index] + @rerender_all = true + else + @line = Reline::HISTORY[@history_pointer] + end + @cursor_max = calculate_width(@line) + arg -= 1 + ed_search_prev_history(key, arg: arg) if arg > 0 + end + alias_method :history_search_backward, :ed_search_prev_history + + private def ed_search_next_history(key, arg: 1) + substr = @line.slice(0, @byte_pointer) + if @history_pointer.nil? + return + elsif @history_pointer == (Reline::HISTORY.size - 1) and not substr.empty? + return + end + history = Reline::HISTORY.slice((@history_pointer + 1)..-1) + h_pointer = nil + line_no = nil + if @is_multiline + h_pointer = history.index { |h| + h.split("\n").each_with_index { |l, i| + if l.start_with?(substr) + line_no = i + break + end + } + not line_no.nil? + } + else + h_pointer = history.index { |l| + l.start_with?(substr) + } + end + h_pointer += @history_pointer + 1 if h_pointer and @history_pointer + return if h_pointer.nil? and not substr.empty? + @history_pointer = h_pointer + if @is_multiline + if @history_pointer.nil? and substr.empty? + @buffer_of_lines = [] + @line_index = 0 + else + @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") + @line_index = line_no + end + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line = @buffer_of_lines[@line_index] + @rerender_all = true + else + if @history_pointer.nil? and substr.empty? + @line = '' + else + @line = Reline::HISTORY[@history_pointer] + end + end + @cursor_max = calculate_width(@line) + arg -= 1 + ed_search_next_history(key, arg: arg) if arg > 0 end - alias_method :forward_search_history, :ed_search_next_history + alias_method :history_search_forward, :ed_search_next_history private def ed_prev_history(key, arg: 1) if @is_multiline and @line_index > 0 @@ -1470,6 +2487,7 @@ def finish arg -= 1 ed_prev_history(key, arg: arg) if arg > 0 end + alias_method :previous_history, :ed_prev_history private def ed_next_history(key, arg: 1) if @is_multiline and @line_index < (@buffer_of_lines.size - 1) @@ -1517,8 +2535,10 @@ def finish arg -= 1 ed_next_history(key, arg: arg) if arg > 0 end + alias_method :next_history, :ed_next_history private def ed_newline(key) + process_insert(force: true) if @is_multiline if @config.editing_mode_is?(:vi_command) if @line_index < (@buffer_of_lines.size - 1) @@ -1550,7 +2570,7 @@ def finish end end - private def em_delete_prev_char(key) + private def em_delete_prev_char(key, arg: 1) if @is_multiline and @cursor == 0 and @line_index > 0 @buffer_of_lines[@line_index] = @line @cursor = calculate_width(@buffer_of_lines[@line_index - 1]) @@ -1568,9 +2588,16 @@ def finish @cursor -= width @cursor_max -= width end + arg -= 1 + em_delete_prev_char(key, arg: arg) if arg > 0 end alias_method :backward_delete_char, :em_delete_prev_char + # Editline:: +ed-kill-line+ (vi command: +D+, +Ctrl-K+; emacs: +Ctrl-K+, + # +Ctrl-U+) + Kill from the cursor to the end of the line. + # GNU Readline:: +kill-line+ (+C-k+) Kill the text from point to the end of + # the line. With a negative numeric argument, kill backward + # from the cursor to the beginning of the current line. private def ed_kill_line(key) if @line.bytesize > @byte_pointer @line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer) @@ -1587,8 +2614,14 @@ def finish @rest_height += 1 end end + alias_method :kill_line, :ed_kill_line - private def em_kill_line(key) + # Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the + # beginning of the edit buffer to the cursor and save it to the + # cut buffer. + # GNU Readline:: +unix-line-discard+ (+C-u+) Kill backward from the cursor + # to the beginning of the current line. + private def vi_kill_line_prev(key) if @byte_pointer > 0 @line, deleted = byteslice!(@line, 0, @byte_pointer) @byte_pointer = 0 @@ -1597,6 +2630,22 @@ def finish @cursor = 0 end end + alias_method :unix_line_discard, :vi_kill_line_prev + + # Editline:: +em-kill-line+ (not bound) Delete the entire contents of the + # edit buffer and save it to the cut buffer. +vi-kill-line-prev+ + # GNU Readline:: +kill-whole-line+ (not bound) Kill all characters on the + # current line, no matter where point is. + private def em_kill_line(key) + if @line.size > 0 + @kill_ring.append(@line.dup, true) + @line.clear + @byte_pointer = 0 + @cursor_max = 0 + @cursor = 0 + end + end + alias_method :kill_whole_line, :em_kill_line private def em_delete(key) if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1) @@ -1647,6 +2696,7 @@ def finish @byte_pointer += yanked.bytesize end end + alias_method :yank, :em_yank private def em_yank_pop(key) yanked, prev_yank = @kill_ring.yank_pop @@ -1663,6 +2713,7 @@ def finish @byte_pointer += yanked.bytesize end end + alias_method :yank_pop, :em_yank_pop private def ed_clear_screen(key) @cleared = true @@ -1793,9 +2844,10 @@ def finish @byte_pointer -= byte_size @cursor -= width @cursor_max -= width - @kill_ring.append(deleted) + @kill_ring.append(deleted, true) end end + alias_method :unix_word_rubout, :em_kill_region private def copy_for_vi(text) if @config.editing_mode_is?(:vi_insert) or @config.editing_mode_is?(:vi_command) @@ -1816,11 +2868,11 @@ def finish ed_prev_char(key) @config.editing_mode = :vi_command end - alias_method :backward_char, :ed_prev_char + alias_method :vi_movement_mode, :vi_command_mode private def vi_next_word(key, arg: 1) if @line.bytesize > @byte_pointer - byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer) + byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer, @drop_terminate_spaces) @byte_pointer += byte_size @cursor += width end @@ -1838,13 +2890,22 @@ def finish vi_prev_word(key, arg: arg) if arg > 0 end - private def vi_end_word(key, arg: 1) + private def vi_end_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 + if inclusive and arg.zero? + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end vi_end_word(key, arg: arg) if arg > 0 end @@ -1868,13 +2929,22 @@ def finish vi_prev_big_word(key, arg: arg) if arg > 0 end - private def vi_end_big_word(key, arg: 1) + private def vi_end_big_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_big_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 + if inclusive and arg.zero? + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end vi_end_big_word(key, arg: arg) if arg > 0 end @@ -1929,7 +2999,8 @@ def finish @cursor = 0 end - private def vi_change_meta(key) + private def vi_change_meta(key, arg: 1) + @drop_terminate_spaces = true @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| if byte_pointer_diff > 0 @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff) @@ -1941,10 +3012,12 @@ def finish @cursor_max -= cursor_diff.abs @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0 @config.editing_mode = :vi_insert + @drop_terminate_spaces = false } + @waiting_operator_vi_arg = arg end - private def vi_delete_meta(key) + private def vi_delete_meta(key, arg: 1) @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| if byte_pointer_diff > 0 @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff) @@ -1956,9 +3029,19 @@ def finish @cursor_max -= cursor_diff.abs @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0 } + @waiting_operator_vi_arg = arg end - private def vi_yank(key) + private def vi_yank(key, arg: 1) + @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| + if byte_pointer_diff > 0 + cut = @line.byteslice(@byte_pointer, byte_pointer_diff) + elsif byte_pointer_diff < 0 + cut = @line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff) + end + copy_for_vi(cut) + } + @waiting_operator_vi_arg = arg end private def vi_list_or_eof(key) @@ -1985,6 +3068,9 @@ def finish width = Reline::Unicode.get_mbchar_width(mbchar) @cursor_max -= width if @cursor > 0 and @cursor >= @cursor_max + byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) + mbchar = @line.byteslice(@byte_pointer - byte_size, byte_size) + width = Reline::Unicode.get_mbchar_width(mbchar) @byte_pointer -= byte_size @cursor -= width end @@ -2018,11 +3104,23 @@ def finish private def vi_histedit(key) path = Tempfile.open { |fp| - fp.write @line + if @is_multiline + fp.write whole_lines.join("\n") + else + fp.write @line + end fp.path } system("#{ENV['EDITOR']} #{path}") - @line = Pathname.new(path).read + if @is_multiline + @buffer_of_lines = File.read(path).split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = 0 + @line = @buffer_of_lines[@line_index] + @rerender_all = true + else + @line = File.read(path) + end finish end @@ -2052,7 +3150,14 @@ def finish private def ed_argument_digit(key) if @vi_arg.nil? - unless key.chr.to_i.zero? + if key.chr.to_i.zero? + if key.anybits?(0b10000000) + unescaped_key = key ^ 0b10000000 + unless unescaped_key.chr.to_i.zero? + @vi_arg = unescaped_key.chr.to_i + end + end + else @vi_arg = key.chr.to_i end else @@ -2081,7 +3186,7 @@ def finish byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) before = @line.byteslice(0, @byte_pointer) remaining_point = @byte_pointer + byte_size - after = @line.byteslice(remaining_point, @line.size - remaining_point) + after = @line.byteslice(remaining_point, @line.bytesize - remaining_point) @line = before + k.chr + after @cursor_max = calculate_width(@line) @waiting_proc = nil @@ -2092,7 +3197,7 @@ def finish end before = @line.byteslice(0, @byte_pointer) remaining_point = @byte_pointer + byte_size - after = @line.byteslice(remaining_point, @line.size - remaining_point) + after = @line.byteslice(remaining_point, @line.bytesize - remaining_point) replaced = k.chr * arg @line = before + replaced + after @byte_pointer += replaced.bytesize @@ -2103,15 +3208,15 @@ def finish } end - private def vi_next_char(key, arg: 1) - @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg) } + private def vi_next_char(key, arg: 1, inclusive: false) + @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) } end - private def vi_to_next_char(key, arg: 1) - @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, true) } + private def vi_to_next_char(key, arg: 1, inclusive: false) + @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) } end - private def search_next_char(key, arg, need_prev_char = false) + private def search_next_char(key, arg, need_prev_char: false, inclusive: false) if key.instance_of?(String) inputed_char = key else @@ -2148,6 +3253,15 @@ def finish @byte_pointer += byte_size @cursor += width end + if inclusive + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end @waiting_proc = nil end @@ -2219,10 +3333,10 @@ def finish alias_method :set_mark, :em_set_mark private def em_exchange_mark(key) + return unless @mark_pointer new_pointer = [@byte_pointer, @line_index] @previous_line_index = @line_index @byte_pointer, @line_index = @mark_pointer - @byte_pointer, @line_index = @mark_pointer @cursor = calculate_width(@line.byteslice(0, @byte_pointer)) @cursor_max = calculate_width(@line) @mark_pointer = new_pointer diff --git a/ruby/lib/reline/reline.gemspec b/ruby/lib/reline/reline.gemspec index 3ced4b848..26809db87 100644 --- a/ruby/lib/reline/reline.gemspec +++ b/ruby/lib/reline/reline.gemspec @@ -1,7 +1,9 @@ -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'reline/version' +begin + require_relative 'lib/reline/version' +rescue LoadError + require_relative 'version' +end Gem::Specification.new do |spec| spec.name = 'reline' @@ -12,15 +14,12 @@ Gem::Specification.new do |spec| spec.summary = %q{Alternative GNU Readline or Editline implementation by pure Ruby.} spec.description = %q{Alternative GNU Readline or Editline implementation by pure Ruby.} spec.homepage = 'https://github.com/ruby/reline' - spec.license = 'Ruby License' + spec.license = 'Ruby' - spec.files = Dir['BSDL', 'COPYING', 'README.md', 'lib/**/*'] + spec.files = Dir['BSDL', 'COPYING', 'README.md', 'license_of_rb-readline', 'lib/**/*'] spec.require_paths = ['lib'] spec.required_ruby_version = Gem::Requirement.new('>= 2.5') spec.add_dependency 'io-console', '~> 0.5' - spec.add_development_dependency 'bundler' - spec.add_development_dependency 'rake' - spec.add_development_dependency 'test-unit' end diff --git a/ruby/lib/reline/terminfo.rb b/ruby/lib/reline/terminfo.rb new file mode 100644 index 000000000..b4d1d735f --- /dev/null +++ b/ruby/lib/reline/terminfo.rb @@ -0,0 +1,134 @@ +begin + require 'fiddle' + require 'fiddle/import' +rescue LoadError + module Reline::Terminfo + def self.curses_dl + false + end + end +end + +module Reline::Terminfo + extend Fiddle::Importer + + class TerminfoError < StandardError; end + + def self.curses_dl_files + case RUBY_PLATFORM + when /mingw/, /mswin/ + # aren't supported + [] + when /cygwin/ + %w[cygncursesw-10.dll cygncurses-10.dll] + when /darwin/ + %w[libncursesw.dylib libcursesw.dylib libncurses.dylib libcurses.dylib] + else + %w[libncursesw.so libcursesw.so libncurses.so libcurses.so] + end + end + + @curses_dl = false + def self.curses_dl + return @curses_dl unless @curses_dl == false + if RUBY_VERSION >= '3.0.0' + # Gem module isn't defined in test-all of the Ruby repository, and + # Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC. + fiddle_supports_variadic = true + elsif Fiddle.const_defined?(:VERSION) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1') + # Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1. + fiddle_supports_variadic = true + else + fiddle_supports_variadic = false + end + if fiddle_supports_variadic and not Fiddle.const_defined?(:TYPE_VARIADIC) + # If the libffi version is not 3.0.5 or higher, there isn't TYPE_VARIADIC. + fiddle_supports_variadic = false + end + if fiddle_supports_variadic + curses_dl_files.each do |curses_name| + result = Fiddle::Handle.new(curses_name) + rescue Fiddle::DLError + next + else + @curses_dl = result + break + end + end + @curses_dl = nil if @curses_dl == false + @curses_dl + end +end if not Reline.const_defined?(:Terminfo) or not Reline::Terminfo.respond_to?(:curses_dl) + +module Reline::Terminfo + dlload curses_dl + #extern 'int setupterm(char *term, int fildes, int *errret)' + @setupterm = Fiddle::Function.new(curses_dl['setupterm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) + #extern 'char *tigetstr(char *capname)' + @tigetstr = Fiddle::Function.new(curses_dl['tigetstr'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP) + begin + #extern 'char *tiparm(const char *str, ...)' + @tiparm = Fiddle::Function.new(curses_dl['tiparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP) + rescue Fiddle::DLError + # OpenBSD lacks tiparm + #extern 'char *tparm(const char *str, ...)' + @tiparm = Fiddle::Function.new(curses_dl['tparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP) + end + # TODO: add int tigetflag(char *capname) and int tigetnum(char *capname) + + def self.setupterm(term, fildes) + errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT') + ret = @setupterm.(term, fildes, errret_int) + errret = errret_int.unpack1('i') + case ret + when 0 # OK + 0 + when -1 # ERR + case errret + when 1 + raise TerminfoError.new('The terminal is hardcopy, cannot be used for curses applications.') + when 0 + raise TerminfoError.new('The terminal could not be found, or that it is a generic type, having too little information for curses applications to run.') + when -1 + raise TerminfoError.new('The terminfo database could not be found.') + else # unknown + -1 + end + else # unknown + -2 + end + end + + class StringWithTiparm < String + def tiparm(*args) # for method chain + Reline::Terminfo.tiparm(self, *args) + end + end + + def self.tigetstr(capname) + capability = @tigetstr.(capname) + case capability.to_i + when 0, -1 + raise TerminfoError, "can't find capability: #{capname}" + end + StringWithTiparm.new(capability.to_s) + end + + def self.tiparm(str, *args) + new_args = [] + args.each do |a| + new_args << Fiddle::TYPE_INT << a + end + @tiparm.(str, *new_args).to_s + end + + def self.enabled? + true + end +end if Reline::Terminfo.curses_dl + +module Reline::Terminfo + def self.enabled? + false + end +end unless Reline::Terminfo.curses_dl diff --git a/ruby/lib/reline/unicode.rb b/ruby/lib/reline/unicode.rb index 4b30f044f..6000c9f82 100644 --- a/ruby/lib/reline/unicode.rb +++ b/ruby/lib/reline/unicode.rb @@ -35,6 +35,17 @@ class Reline::Unicode } EscapedChars = EscapedPairs.keys.map(&:chr) + NON_PRINTING_START = "\1" + NON_PRINTING_END = "\2" + CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/ + OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/ + WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o + NON_PRINTING_START_INDEX = 0 + NON_PRINTING_END_INDEX = 1 + CSI_REGEXP_INDEX = 2 + OSC_REGEXP_INDEX = 3 + GRAPHEME_CLUSTER_INDEX = 4 + def self.get_mbchar_byte_size_by_first_char(c) # Checks UTF-8 character byte size case c.ord @@ -66,25 +77,153 @@ def self.escape_for_print(str) }.join end + require 'reline/unicode/east_asian_width' + + HalfwidthDakutenHandakuten = /[\u{FF9E}\u{FF9F}]/ + + MBCharWidthRE = / + (? + [#{ EscapedChars.map {|c| "\\x%02x" % c.ord }.join }] (?# ^ + char, such as ^M, ^H, ^[, ...) + ) + | (?^\u{2E3B}) (?# THREE-EM DASH) + | (?^\p{M}) + | (? + #{ EastAsianWidth::TYPE_F } + | #{ EastAsianWidth::TYPE_W } + ) + | (? + #{ EastAsianWidth::TYPE_H } + | #{ EastAsianWidth::TYPE_NA } + | #{ EastAsianWidth::TYPE_N } + )(?!#{ HalfwidthDakutenHandakuten }) + | (? + (?: #{ EastAsianWidth::TYPE_H } + | #{ EastAsianWidth::TYPE_NA } + | #{ EastAsianWidth::TYPE_N }) + #{ HalfwidthDakutenHandakuten } + ) + | (? + #{EastAsianWidth::TYPE_A} + ) + /x + def self.get_mbchar_width(mbchar) - case mbchar.encode(Encoding::UTF_8) - when *EscapedChars # ^ + char, such as ^M, ^H, ^[, ... - 2 - when /^\u{2E3B}/ # THREE-EM DASH - 3 - when /^\p{M}/ - 0 - when EastAsianWidth::TYPE_A - Reline.ambiguous_width - when EastAsianWidth::TYPE_F, EastAsianWidth::TYPE_W - 2 - when EastAsianWidth::TYPE_H, EastAsianWidth::TYPE_NA, EastAsianWidth::TYPE_N - 1 + ord = mbchar.ord + if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs + return 2 + elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars + return 1 + end + m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE) + case + when m.nil? then 1 # TODO should be U+FFFD � REPLACEMENT CHARACTER + when m[:width_2_1], m[:width_2_2], m[:width_2_3] then 2 + when m[:width_3] then 3 + when m[:width_0] then 0 + when m[:width_1] then 1 + when m[:ambiguous_width] then Reline.ambiguous_width else nil end end + def self.calculate_width(str, allow_escape_code = false) + if allow_escape_code + width = 0 + rest = str.encode(Encoding::UTF_8) + in_zero_width = false + rest.scan(WIDTH_SCANNER) do |gc| + case + when gc[NON_PRINTING_START_INDEX] + in_zero_width = true + when gc[NON_PRINTING_END_INDEX] + in_zero_width = false + when gc[CSI_REGEXP_INDEX], gc[OSC_REGEXP_INDEX] + when gc[GRAPHEME_CLUSTER_INDEX] + gc = gc[GRAPHEME_CLUSTER_INDEX] + unless in_zero_width + width += get_mbchar_width(gc) + end + end + end + width + else + str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc| + w + get_mbchar_width(gc) + } + end + end + + def self.split_by_width(str, max_width, encoding = str.encoding) + lines = [String.new(encoding: encoding)] + height = 1 + width = 0 + rest = str.encode(Encoding::UTF_8) + in_zero_width = false + rest.scan(WIDTH_SCANNER) do |gc| + case + when gc[NON_PRINTING_START_INDEX] + in_zero_width = true + when gc[NON_PRINTING_END_INDEX] + in_zero_width = false + when gc[CSI_REGEXP_INDEX] + lines.last << gc[CSI_REGEXP_INDEX] + when gc[OSC_REGEXP_INDEX] + lines.last << gc[OSC_REGEXP_INDEX] + when gc[GRAPHEME_CLUSTER_INDEX] + gc = gc[GRAPHEME_CLUSTER_INDEX] + unless in_zero_width + mbchar_width = get_mbchar_width(gc) + if (width += mbchar_width) > max_width + width = mbchar_width + lines << nil + lines << String.new(encoding: encoding) + height += 1 + end + end + lines.last << gc + end + end + # The cursor moves to next line in first + if width == max_width + lines << nil + lines << String.new(encoding: encoding) + height += 1 + end + [lines, height] + end + + # Take a chunk of a String cut by width with escape sequences. + def self.take_range(str, start_col, max_width, encoding = str.encoding) + chunk = String.new(encoding: encoding) + total_width = 0 + rest = str.encode(Encoding::UTF_8) + in_zero_width = false + rest.scan(WIDTH_SCANNER) do |gc| + case + when gc[NON_PRINTING_START_INDEX] + in_zero_width = true + when gc[NON_PRINTING_END_INDEX] + in_zero_width = false + when gc[CSI_REGEXP_INDEX] + chunk << gc[CSI_REGEXP_INDEX] + when gc[OSC_REGEXP_INDEX] + chunk << gc[OSC_REGEXP_INDEX] + when gc[GRAPHEME_CLUSTER_INDEX] + gc = gc[GRAPHEME_CLUSTER_INDEX] + if in_zero_width + chunk << gc + else + mbchar_width = get_mbchar_width(gc) + total_width += mbchar_width + break if (start_col + max_width) < total_width + chunk << gc if start_col < total_width + end + end + end + chunk + end + def self.get_next_mbchar_size(line, byte_pointer) grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first grapheme ? grapheme.bytesize : 0 @@ -359,8 +498,8 @@ def self.vi_big_backward_word(line, byte_pointer) [byte_size, width] end - def self.vi_forward_word(line, byte_pointer) - if (line.bytesize - 1) > byte_pointer + def self.vi_forward_word(line, byte_pointer, drop_terminate_spaces = false) + if line.bytesize > byte_pointer size = get_next_mbchar_size(line, byte_pointer) mbchar = line.byteslice(byte_pointer, size) if mbchar =~ /\w/ @@ -375,7 +514,7 @@ def self.vi_forward_word(line, byte_pointer) else return [0, 0] end - while (line.bytesize - 1) > (byte_pointer + byte_size) + while line.bytesize > (byte_pointer + byte_size) size = get_next_mbchar_size(line, byte_pointer + byte_size) mbchar = line.byteslice(byte_pointer + byte_size, size) case started_by @@ -389,7 +528,8 @@ def self.vi_forward_word(line, byte_pointer) width += get_mbchar_width(mbchar) byte_size += size end - while (line.bytesize - 1) > (byte_pointer + byte_size) + return [byte_size, width] if drop_terminate_spaces + while line.bytesize > (byte_pointer + byte_size) size = get_next_mbchar_size(line, byte_pointer + byte_size) mbchar = line.byteslice(byte_pointer + byte_size, size) break if mbchar =~ /\S/ @@ -523,5 +663,3 @@ def self.vi_first_print(line) [byte_size, width] end end - -require 'reline/unicode/east_asian_width' diff --git a/ruby/lib/reline/unicode/east_asian_width.rb b/ruby/lib/reline/unicode/east_asian_width.rb index b2749ab75..89bc9d943 100644 --- a/ruby/lib/reline/unicode/east_asian_width.rb +++ b/ruby/lib/reline/unicode/east_asian_width.rb @@ -1,1145 +1,1164 @@ class Reline::Unicode::EastAsianWidth # This is based on EastAsianWidth.txt - # http://www.unicode.org/Public/12.1.0/ucd/EastAsianWidth.txt + # EastAsianWidth.txt # Fullwidth - TYPE_F = /^( - \u{3000} | - [\u{FF01}-\u{FF60}] | - [\u{FFE0}-\u{FFE6}] - )/x + TYPE_F = /^[#{ %W( + \u{3000} + \u{FF01}-\u{FF60} + \u{FFE0}-\u{FFE6} + ).join }]/ # Halfwidth - TYPE_H = /^( - \u{20A9} | - [\u{FF61}-\u{FFBE}] | - [\u{FFC2}-\u{FFC7}] | - [\u{FFCA}-\u{FFCF}] | - [\u{FFD2}-\u{FFD7}] | - [\u{FFDA}-\u{FFDC}] | - [\u{FFE8}-\u{FFEE}] - )/x + TYPE_H = /^[#{ %W( + \u{20A9} + \u{FF61}-\u{FFBE} + \u{FFC2}-\u{FFC7} + \u{FFCA}-\u{FFCF} + \u{FFD2}-\u{FFD7} + \u{FFDA}-\u{FFDC} + \u{FFE8}-\u{FFEE} + ).join }]/ # Wide - TYPE_W = /^( - [\u{1100}-\u{115F}] | - [\u{231A}-\u{231B}] | - [\u{2329}-\u{232A}] | - [\u{23E9}-\u{23EC}] | - \u{23F0} | - \u{23F3} | - [\u{25FD}-\u{25FE}] | - [\u{2614}-\u{2615}] | - [\u{2648}-\u{2653}] | - \u{267F} | - \u{2693} | - \u{26A1} | - [\u{26AA}-\u{26AB}] | - [\u{26BD}-\u{26BE}] | - [\u{26C4}-\u{26C5}] | - \u{26CE} | - \u{26D4} | - \u{26EA} | - [\u{26F2}-\u{26F3}] | - \u{26F5} | - \u{26FA} | - \u{26FD} | - \u{2705} | - [\u{270A}-\u{270B}] | - \u{2728} | - \u{274C} | - \u{274E} | - [\u{2753}-\u{2755}] | - \u{2757} | - [\u{2795}-\u{2797}] | - \u{27B0} | - \u{27BF} | - [\u{2B1B}-\u{2B1C}] | - \u{2B50} | - \u{2B55} | - [\u{2E80}-\u{2E99}] | - [\u{2E9B}-\u{2EF3}] | - [\u{2F00}-\u{2FD5}] | - [\u{2FF0}-\u{2FFB}] | - [\u{3001}-\u{303E}] | - [\u{3041}-\u{3096}] | - [\u{3099}-\u{30FF}] | - [\u{3105}-\u{312F}] | - [\u{3131}-\u{318E}] | - [\u{3190}-\u{31BA}] | - [\u{31C0}-\u{31E3}] | - [\u{31F0}-\u{321E}] | - [\u{3220}-\u{3247}] | - [\u{3250}-\u{4DBF}] | - [\u{4E00}-\u{A48C}] | - [\u{A490}-\u{A4C6}] | - [\u{A960}-\u{A97C}] | - [\u{AC00}-\u{D7A3}] | - [\u{F900}-\u{FAFF}] | - [\u{FE10}-\u{FE19}] | - [\u{FE30}-\u{FE52}] | - [\u{FE54}-\u{FE66}] | - [\u{FE68}-\u{FE6B}] | - [\u{16FE0}-\u{16FE3}] | - [\u{17000}-\u{187F7}] | - [\u{18800}-\u{18AF2}] | - [\u{1B000}-\u{1B11E}] | - [\u{1B150}-\u{1B152}] | - [\u{1B164}-\u{1B167}] | - [\u{1B170}-\u{1B2FB}] | - \u{1F004} | - \u{1F0CF} | - \u{1F18E} | - [\u{1F191}-\u{1F19A}] | - [\u{1F200}-\u{1F202}] | - [\u{1F210}-\u{1F23B}] | - [\u{1F240}-\u{1F248}] | - [\u{1F250}-\u{1F251}] | - [\u{1F260}-\u{1F265}] | - [\u{1F300}-\u{1F320}] | - [\u{1F32D}-\u{1F335}] | - [\u{1F337}-\u{1F37C}] | - [\u{1F37E}-\u{1F393}] | - [\u{1F3A0}-\u{1F3CA}] | - [\u{1F3CF}-\u{1F3D3}] | - [\u{1F3E0}-\u{1F3F0}] | - \u{1F3F4} | - [\u{1F3F8}-\u{1F43E}] | - \u{1F440} | - [\u{1F442}-\u{1F4FC}] | - [\u{1F4FF}-\u{1F53D}] | - [\u{1F54B}-\u{1F54E}] | - [\u{1F550}-\u{1F567}] | - \u{1F57A} | - [\u{1F595}-\u{1F596}] | - \u{1F5A4} | - [\u{1F5FB}-\u{1F64F}] | - [\u{1F680}-\u{1F6C5}] | - \u{1F6CC} | - [\u{1F6D0}-\u{1F6D2}] | - \u{1F6D5} | - [\u{1F6EB}-\u{1F6EC}] | - [\u{1F6F4}-\u{1F6FA}] | - [\u{1F7E0}-\u{1F7EB}] | - [\u{1F90D}-\u{1F971}] | - [\u{1F973}-\u{1F976}] | - [\u{1F97A}-\u{1F9A2}] | - [\u{1F9A5}-\u{1F9AA}] | - [\u{1F9AE}-\u{1F9CA}] | - [\u{1F9CD}-\u{1F9FF}] | - [\u{1FA70}-\u{1FA73}] | - [\u{1FA78}-\u{1FA7A}] | - [\u{1FA80}-\u{1FA82}] | - [\u{1FA90}-\u{1FA95}] | - [\u{20000}-\u{2FFFD}] | - [\u{30000}-\u{3FFFD}] - )/x + TYPE_W = /^[#{ %W( + \u{1100}-\u{115F} + \u{231A}-\u{231B} + \u{2329}-\u{232A} + \u{23E9}-\u{23EC} + \u{23F0} + \u{23F3} + \u{25FD}-\u{25FE} + \u{2614}-\u{2615} + \u{2648}-\u{2653} + \u{267F} + \u{2693} + \u{26A1} + \u{26AA}-\u{26AB} + \u{26BD}-\u{26BE} + \u{26C4}-\u{26C5} + \u{26CE} + \u{26D4} + \u{26EA} + \u{26F2}-\u{26F3} + \u{26F5} + \u{26FA} + \u{26FD} + \u{2705} + \u{270A}-\u{270B} + \u{2728} + \u{274C} + \u{274E} + \u{2753}-\u{2755} + \u{2757} + \u{2795}-\u{2797} + \u{27B0} + \u{27BF} + \u{2B1B}-\u{2B1C} + \u{2B50} + \u{2B55} + \u{2E80}-\u{2E99} + \u{2E9B}-\u{2EF3} + \u{2F00}-\u{2FD5} + \u{2FF0}-\u{2FFB} + \u{3001}-\u{303E} + \u{3041}-\u{3096} + \u{3099}-\u{30FF} + \u{3105}-\u{312F} + \u{3131}-\u{318E} + \u{3190}-\u{31E3} + \u{31F0}-\u{321E} + \u{3220}-\u{3247} + \u{3250}-\u{4DBF} + \u{4E00}-\u{A48C} + \u{A490}-\u{A4C6} + \u{A960}-\u{A97C} + \u{AC00}-\u{D7A3} + \u{F900}-\u{FAFF} + \u{FE10}-\u{FE19} + \u{FE30}-\u{FE52} + \u{FE54}-\u{FE66} + \u{FE68}-\u{FE6B} + \u{16FE0}-\u{16FE4} + \u{16FF0}-\u{16FF1} + \u{17000}-\u{187F7} + \u{18800}-\u{18CD5} + \u{18D00}-\u{18D08} + \u{1B000}-\u{1B11E} + \u{1B150}-\u{1B152} + \u{1B164}-\u{1B167} + \u{1B170}-\u{1B2FB} + \u{1F004} + \u{1F0CF} + \u{1F18E} + \u{1F191}-\u{1F19A} + \u{1F200}-\u{1F202} + \u{1F210}-\u{1F23B} + \u{1F240}-\u{1F248} + \u{1F250}-\u{1F251} + \u{1F260}-\u{1F265} + \u{1F300}-\u{1F320} + \u{1F32D}-\u{1F335} + \u{1F337}-\u{1F37C} + \u{1F37E}-\u{1F393} + \u{1F3A0}-\u{1F3CA} + \u{1F3CF}-\u{1F3D3} + \u{1F3E0}-\u{1F3F0} + \u{1F3F4} + \u{1F3F8}-\u{1F43E} + \u{1F440} + \u{1F442}-\u{1F4FC} + \u{1F4FF}-\u{1F53D} + \u{1F54B}-\u{1F54E} + \u{1F550}-\u{1F567} + \u{1F57A} + \u{1F595}-\u{1F596} + \u{1F5A4} + \u{1F5FB}-\u{1F64F} + \u{1F680}-\u{1F6C5} + \u{1F6CC} + \u{1F6D0}-\u{1F6D2} + \u{1F6D5}-\u{1F6D7} + \u{1F6EB}-\u{1F6EC} + \u{1F6F4}-\u{1F6FC} + \u{1F7E0}-\u{1F7EB} + \u{1F90C}-\u{1F93A} + \u{1F93C}-\u{1F945} + \u{1F947}-\u{1F978} + \u{1F97A}-\u{1F9CB} + \u{1F9CD}-\u{1F9FF} + \u{1FA70}-\u{1FA74} + \u{1FA78}-\u{1FA7A} + \u{1FA80}-\u{1FA86} + \u{1FA90}-\u{1FAA8} + \u{1FAB0}-\u{1FAB6} + \u{1FAC0}-\u{1FAC2} + \u{1FAD0}-\u{1FAD6} + \u{20000}-\u{2FFFD} + \u{30000}-\u{3FFFD} + ).join }]/ # Narrow - TYPE_NA = /^( - [\u{0020}-\u{007E}] | - [\u{00A2}-\u{00A3}] | - [\u{00A5}-\u{00A6}] | - \u{00AC} | - \u{00AF} | - [\u{27E6}-\u{27ED}] | - [\u{2985}-\u{2986}] - )/x + TYPE_NA = /^[#{ %W( + \u{0020}-\u{007E} + \u{00A2}-\u{00A3} + \u{00A5}-\u{00A6} + \u{00AC} + \u{00AF} + \u{27E6}-\u{27ED} + \u{2985}-\u{2986} + ).join }]/ # Ambiguous - TYPE_A = /^( - \u{00A1} | - \u{00A4} | - [\u{00A7}-\u{00A8}] | - \u{00AA} | - [\u{00AD}-\u{00AE}] | - [\u{00B0}-\u{00B4}] | - [\u{00B6}-\u{00BA}] | - [\u{00BC}-\u{00BF}] | - \u{00C6} | - \u{00D0} | - [\u{00D7}-\u{00D8}] | - [\u{00DE}-\u{00E1}] | - \u{00E6} | - [\u{00E8}-\u{00EA}] | - [\u{00EC}-\u{00ED}] | - \u{00F0} | - [\u{00F2}-\u{00F3}] | - [\u{00F7}-\u{00FA}] | - \u{00FC} | - \u{00FE} | - \u{0101} | - \u{0111} | - \u{0113} | - \u{011B} | - [\u{0126}-\u{0127}] | - \u{012B} | - [\u{0131}-\u{0133}] | - \u{0138} | - [\u{013F}-\u{0142}] | - \u{0144} | - [\u{0148}-\u{014B}] | - \u{014D} | - [\u{0152}-\u{0153}] | - [\u{0166}-\u{0167}] | - \u{016B} | - \u{01CE} | - \u{01D0} | - \u{01D2} | - \u{01D4} | - \u{01D6} | - \u{01D8} | - \u{01DA} | - \u{01DC} | - \u{0251} | - \u{0261} | - \u{02C4} | - \u{02C7} | - [\u{02C9}-\u{02CB}] | - \u{02CD} | - \u{02D0} | - [\u{02D8}-\u{02DB}] | - \u{02DD} | - \u{02DF} | - [\u{0300}-\u{036F}] | - [\u{0391}-\u{03A1}] | - [\u{03A3}-\u{03A9}] | - [\u{03B1}-\u{03C1}] | - [\u{03C3}-\u{03C9}] | - \u{0401} | - [\u{0410}-\u{044F}] | - \u{0451} | - \u{2010} | - [\u{2013}-\u{2016}] | - [\u{2018}-\u{2019}] | - [\u{201C}-\u{201D}] | - [\u{2020}-\u{2022}] | - [\u{2024}-\u{2027}] | - \u{2030} | - [\u{2032}-\u{2033}] | - \u{2035} | - \u{203B} | - \u{203E} | - \u{2074} | - \u{207F} | - [\u{2081}-\u{2084}] | - \u{20AC} | - \u{2103} | - \u{2105} | - \u{2109} | - \u{2113} | - \u{2116} | - [\u{2121}-\u{2122}] | - \u{2126} | - \u{212B} | - [\u{2153}-\u{2154}] | - [\u{215B}-\u{215E}] | - [\u{2160}-\u{216B}] | - [\u{2170}-\u{2179}] | - \u{2189} | - [\u{2190}-\u{2199}] | - [\u{21B8}-\u{21B9}] | - \u{21D2} | - \u{21D4} | - \u{21E7} | - \u{2200} | - [\u{2202}-\u{2203}] | - [\u{2207}-\u{2208}] | - \u{220B} | - \u{220F} | - \u{2211} | - \u{2215} | - \u{221A} | - [\u{221D}-\u{2220}] | - \u{2223} | - \u{2225} | - [\u{2227}-\u{222C}] | - \u{222E} | - [\u{2234}-\u{2237}] | - [\u{223C}-\u{223D}] | - \u{2248} | - \u{224C} | - \u{2252} | - [\u{2260}-\u{2261}] | - [\u{2264}-\u{2267}] | - [\u{226A}-\u{226B}] | - [\u{226E}-\u{226F}] | - [\u{2282}-\u{2283}] | - [\u{2286}-\u{2287}] | - \u{2295} | - \u{2299} | - \u{22A5} | - \u{22BF} | - \u{2312} | - [\u{2460}-\u{24E9}] | - [\u{24EB}-\u{254B}] | - [\u{2550}-\u{2573}] | - [\u{2580}-\u{258F}] | - [\u{2592}-\u{2595}] | - [\u{25A0}-\u{25A1}] | - [\u{25A3}-\u{25A9}] | - [\u{25B2}-\u{25B3}] | - [\u{25B6}-\u{25B7}] | - [\u{25BC}-\u{25BD}] | - [\u{25C0}-\u{25C1}] | - [\u{25C6}-\u{25C8}] | - \u{25CB} | - [\u{25CE}-\u{25D1}] | - [\u{25E2}-\u{25E5}] | - \u{25EF} | - [\u{2605}-\u{2606}] | - \u{2609} | - [\u{260E}-\u{260F}] | - \u{261C} | - \u{261E} | - \u{2640} | - \u{2642} | - [\u{2660}-\u{2661}] | - [\u{2663}-\u{2665}] | - [\u{2667}-\u{266A}] | - [\u{266C}-\u{266D}] | - \u{266F} | - [\u{269E}-\u{269F}] | - \u{26BF} | - [\u{26C6}-\u{26CD}] | - [\u{26CF}-\u{26D3}] | - [\u{26D5}-\u{26E1}] | - \u{26E3} | - [\u{26E8}-\u{26E9}] | - [\u{26EB}-\u{26F1}] | - \u{26F4} | - [\u{26F6}-\u{26F9}] | - [\u{26FB}-\u{26FC}] | - [\u{26FE}-\u{26FF}] | - \u{273D} | - [\u{2776}-\u{277F}] | - [\u{2B56}-\u{2B59}] | - [\u{3248}-\u{324F}] | - [\u{E000}-\u{F8FF}] | - [\u{FE00}-\u{FE0F}] | - \u{FFFD} | - [\u{1F100}-\u{1F10A}] | - [\u{1F110}-\u{1F12D}] | - [\u{1F130}-\u{1F169}] | - [\u{1F170}-\u{1F18D}] | - [\u{1F18F}-\u{1F190}] | - [\u{1F19B}-\u{1F1AC}] | - [\u{E0100}-\u{E01EF}] | - [\u{F0000}-\u{FFFFD}] | - [\u{100000}-\u{10FFFD}] - )/x + TYPE_A = /^[#{ %W( + \u{00A1} + \u{00A4} + \u{00A7}-\u{00A8} + \u{00AA} + \u{00AD}-\u{00AE} + \u{00B0}-\u{00B4} + \u{00B6}-\u{00BA} + \u{00BC}-\u{00BF} + \u{00C6} + \u{00D0} + \u{00D7}-\u{00D8} + \u{00DE}-\u{00E1} + \u{00E6} + \u{00E8}-\u{00EA} + \u{00EC}-\u{00ED} + \u{00F0} + \u{00F2}-\u{00F3} + \u{00F7}-\u{00FA} + \u{00FC} + \u{00FE} + \u{0101} + \u{0111} + \u{0113} + \u{011B} + \u{0126}-\u{0127} + \u{012B} + \u{0131}-\u{0133} + \u{0138} + \u{013F}-\u{0142} + \u{0144} + \u{0148}-\u{014B} + \u{014D} + \u{0152}-\u{0153} + \u{0166}-\u{0167} + \u{016B} + \u{01CE} + \u{01D0} + \u{01D2} + \u{01D4} + \u{01D6} + \u{01D8} + \u{01DA} + \u{01DC} + \u{0251} + \u{0261} + \u{02C4} + \u{02C7} + \u{02C9}-\u{02CB} + \u{02CD} + \u{02D0} + \u{02D8}-\u{02DB} + \u{02DD} + \u{02DF} + \u{0300}-\u{036F} + \u{0391}-\u{03A1} + \u{03A3}-\u{03A9} + \u{03B1}-\u{03C1} + \u{03C3}-\u{03C9} + \u{0401} + \u{0410}-\u{044F} + \u{0451} + \u{2010} + \u{2013}-\u{2016} + \u{2018}-\u{2019} + \u{201C}-\u{201D} + \u{2020}-\u{2022} + \u{2024}-\u{2027} + \u{2030} + \u{2032}-\u{2033} + \u{2035} + \u{203B} + \u{203E} + \u{2074} + \u{207F} + \u{2081}-\u{2084} + \u{20AC} + \u{2103} + \u{2105} + \u{2109} + \u{2113} + \u{2116} + \u{2121}-\u{2122} + \u{2126} + \u{212B} + \u{2153}-\u{2154} + \u{215B}-\u{215E} + \u{2160}-\u{216B} + \u{2170}-\u{2179} + \u{2189} + \u{2190}-\u{2199} + \u{21B8}-\u{21B9} + \u{21D2} + \u{21D4} + \u{21E7} + \u{2200} + \u{2202}-\u{2203} + \u{2207}-\u{2208} + \u{220B} + \u{220F} + \u{2211} + \u{2215} + \u{221A} + \u{221D}-\u{2220} + \u{2223} + \u{2225} + \u{2227}-\u{222C} + \u{222E} + \u{2234}-\u{2237} + \u{223C}-\u{223D} + \u{2248} + \u{224C} + \u{2252} + \u{2260}-\u{2261} + \u{2264}-\u{2267} + \u{226A}-\u{226B} + \u{226E}-\u{226F} + \u{2282}-\u{2283} + \u{2286}-\u{2287} + \u{2295} + \u{2299} + \u{22A5} + \u{22BF} + \u{2312} + \u{2460}-\u{24E9} + \u{24EB}-\u{254B} + \u{2550}-\u{2573} + \u{2580}-\u{258F} + \u{2592}-\u{2595} + \u{25A0}-\u{25A1} + \u{25A3}-\u{25A9} + \u{25B2}-\u{25B3} + \u{25B6}-\u{25B7} + \u{25BC}-\u{25BD} + \u{25C0}-\u{25C1} + \u{25C6}-\u{25C8} + \u{25CB} + \u{25CE}-\u{25D1} + \u{25E2}-\u{25E5} + \u{25EF} + \u{2605}-\u{2606} + \u{2609} + \u{260E}-\u{260F} + \u{261C} + \u{261E} + \u{2640} + \u{2642} + \u{2660}-\u{2661} + \u{2663}-\u{2665} + \u{2667}-\u{266A} + \u{266C}-\u{266D} + \u{266F} + \u{269E}-\u{269F} + \u{26BF} + \u{26C6}-\u{26CD} + \u{26CF}-\u{26D3} + \u{26D5}-\u{26E1} + \u{26E3} + \u{26E8}-\u{26E9} + \u{26EB}-\u{26F1} + \u{26F4} + \u{26F6}-\u{26F9} + \u{26FB}-\u{26FC} + \u{26FE}-\u{26FF} + \u{273D} + \u{2776}-\u{277F} + \u{2B56}-\u{2B59} + \u{3248}-\u{324F} + \u{E000}-\u{F8FF} + \u{FE00}-\u{FE0F} + \u{FFFD} + \u{1F100}-\u{1F10A} + \u{1F110}-\u{1F12D} + \u{1F130}-\u{1F169} + \u{1F170}-\u{1F18D} + \u{1F18F}-\u{1F190} + \u{1F19B}-\u{1F1AC} + \u{E0100}-\u{E01EF} + \u{F0000}-\u{FFFFD} + \u{100000}-\u{10FFFD} + ).join }]/ # Neutral - TYPE_N = /^( - [\u{0000}-\u{001F}] | - [\u{007F}-\u{00A0}] | - \u{00A9} | - \u{00AB} | - \u{00B5} | - \u{00BB} | - [\u{00C0}-\u{00C5}] | - [\u{00C7}-\u{00CF}] | - [\u{00D1}-\u{00D6}] | - [\u{00D9}-\u{00DD}] | - [\u{00E2}-\u{00E5}] | - \u{00E7} | - \u{00EB} | - [\u{00EE}-\u{00EF}] | - \u{00F1} | - [\u{00F4}-\u{00F6}] | - \u{00FB} | - \u{00FD} | - [\u{00FF}-\u{0100}] | - [\u{0102}-\u{0110}] | - \u{0112} | - [\u{0114}-\u{011A}] | - [\u{011C}-\u{0125}] | - [\u{0128}-\u{012A}] | - [\u{012C}-\u{0130}] | - [\u{0134}-\u{0137}] | - [\u{0139}-\u{013E}] | - \u{0143} | - [\u{0145}-\u{0147}] | - \u{014C} | - [\u{014E}-\u{0151}] | - [\u{0154}-\u{0165}] | - [\u{0168}-\u{016A}] | - [\u{016C}-\u{01CD}] | - \u{01CF} | - \u{01D1} | - \u{01D3} | - \u{01D5} | - \u{01D7} | - \u{01D9} | - \u{01DB} | - [\u{01DD}-\u{0250}] | - [\u{0252}-\u{0260}] | - [\u{0262}-\u{02C3}] | - [\u{02C5}-\u{02C6}] | - \u{02C8} | - \u{02CC} | - [\u{02CE}-\u{02CF}] | - [\u{02D1}-\u{02D7}] | - \u{02DC} | - \u{02DE} | - [\u{02E0}-\u{02FF}] | - [\u{0370}-\u{0377}] | - [\u{037A}-\u{037F}] | - [\u{0384}-\u{038A}] | - \u{038C} | - [\u{038E}-\u{0390}] | - [\u{03AA}-\u{03B0}] | - \u{03C2} | - [\u{03CA}-\u{0400}] | - [\u{0402}-\u{040F}] | - \u{0450} | - [\u{0452}-\u{052F}] | - [\u{0531}-\u{0556}] | - [\u{0559}-\u{058A}] | - [\u{058D}-\u{058F}] | - [\u{0591}-\u{05C7}] | - [\u{05D0}-\u{05EA}] | - [\u{05EF}-\u{05F4}] | - [\u{0600}-\u{061C}] | - [\u{061E}-\u{070D}] | - [\u{070F}-\u{074A}] | - [\u{074D}-\u{07B1}] | - [\u{07C0}-\u{07FA}] | - [\u{07FD}-\u{082D}] | - [\u{0830}-\u{083E}] | - [\u{0840}-\u{085B}] | - \u{085E} | - [\u{0860}-\u{086A}] | - [\u{08A0}-\u{08B4}] | - [\u{08B6}-\u{08BD}] | - [\u{08D3}-\u{0983}] | - [\u{0985}-\u{098C}] | - [\u{098F}-\u{0990}] | - [\u{0993}-\u{09A8}] | - [\u{09AA}-\u{09B0}] | - \u{09B2} | - [\u{09B6}-\u{09B9}] | - [\u{09BC}-\u{09C4}] | - [\u{09C7}-\u{09C8}] | - [\u{09CB}-\u{09CE}] | - \u{09D7} | - [\u{09DC}-\u{09DD}] | - [\u{09DF}-\u{09E3}] | - [\u{09E6}-\u{09FE}] | - [\u{0A01}-\u{0A03}] | - [\u{0A05}-\u{0A0A}] | - [\u{0A0F}-\u{0A10}] | - [\u{0A13}-\u{0A28}] | - [\u{0A2A}-\u{0A30}] | - [\u{0A32}-\u{0A33}] | - [\u{0A35}-\u{0A36}] | - [\u{0A38}-\u{0A39}] | - \u{0A3C} | - [\u{0A3E}-\u{0A42}] | - [\u{0A47}-\u{0A48}] | - [\u{0A4B}-\u{0A4D}] | - \u{0A51} | - [\u{0A59}-\u{0A5C}] | - \u{0A5E} | - [\u{0A66}-\u{0A76}] | - [\u{0A81}-\u{0A83}] | - [\u{0A85}-\u{0A8D}] | - [\u{0A8F}-\u{0A91}] | - [\u{0A93}-\u{0AA8}] | - [\u{0AAA}-\u{0AB0}] | - [\u{0AB2}-\u{0AB3}] | - [\u{0AB5}-\u{0AB9}] | - [\u{0ABC}-\u{0AC5}] | - [\u{0AC7}-\u{0AC9}] | - [\u{0ACB}-\u{0ACD}] | - \u{0AD0} | - [\u{0AE0}-\u{0AE3}] | - [\u{0AE6}-\u{0AF1}] | - [\u{0AF9}-\u{0AFF}] | - [\u{0B01}-\u{0B03}] | - [\u{0B05}-\u{0B0C}] | - [\u{0B0F}-\u{0B10}] | - [\u{0B13}-\u{0B28}] | - [\u{0B2A}-\u{0B30}] | - [\u{0B32}-\u{0B33}] | - [\u{0B35}-\u{0B39}] | - [\u{0B3C}-\u{0B44}] | - [\u{0B47}-\u{0B48}] | - [\u{0B4B}-\u{0B4D}] | - [\u{0B56}-\u{0B57}] | - [\u{0B5C}-\u{0B5D}] | - [\u{0B5F}-\u{0B63}] | - [\u{0B66}-\u{0B77}] | - [\u{0B82}-\u{0B83}] | - [\u{0B85}-\u{0B8A}] | - [\u{0B8E}-\u{0B90}] | - [\u{0B92}-\u{0B95}] | - [\u{0B99}-\u{0B9A}] | - \u{0B9C} | - [\u{0B9E}-\u{0B9F}] | - [\u{0BA3}-\u{0BA4}] | - [\u{0BA8}-\u{0BAA}] | - [\u{0BAE}-\u{0BB9}] | - [\u{0BBE}-\u{0BC2}] | - [\u{0BC6}-\u{0BC8}] | - [\u{0BCA}-\u{0BCD}] | - \u{0BD0} | - \u{0BD7} | - [\u{0BE6}-\u{0BFA}] | - [\u{0C00}-\u{0C0C}] | - [\u{0C0E}-\u{0C10}] | - [\u{0C12}-\u{0C28}] | - [\u{0C2A}-\u{0C39}] | - [\u{0C3D}-\u{0C44}] | - [\u{0C46}-\u{0C48}] | - [\u{0C4A}-\u{0C4D}] | - [\u{0C55}-\u{0C56}] | - [\u{0C58}-\u{0C5A}] | - [\u{0C60}-\u{0C63}] | - [\u{0C66}-\u{0C6F}] | - [\u{0C77}-\u{0C8C}] | - [\u{0C8E}-\u{0C90}] | - [\u{0C92}-\u{0CA8}] | - [\u{0CAA}-\u{0CB3}] | - [\u{0CB5}-\u{0CB9}] | - [\u{0CBC}-\u{0CC4}] | - [\u{0CC6}-\u{0CC8}] | - [\u{0CCA}-\u{0CCD}] | - [\u{0CD5}-\u{0CD6}] | - \u{0CDE} | - [\u{0CE0}-\u{0CE3}] | - [\u{0CE6}-\u{0CEF}] | - [\u{0CF1}-\u{0CF2}] | - [\u{0D00}-\u{0D03}] | - [\u{0D05}-\u{0D0C}] | - [\u{0D0E}-\u{0D10}] | - [\u{0D12}-\u{0D44}] | - [\u{0D46}-\u{0D48}] | - [\u{0D4A}-\u{0D4F}] | - [\u{0D54}-\u{0D63}] | - [\u{0D66}-\u{0D7F}] | - [\u{0D82}-\u{0D83}] | - [\u{0D85}-\u{0D96}] | - [\u{0D9A}-\u{0DB1}] | - [\u{0DB3}-\u{0DBB}] | - \u{0DBD} | - [\u{0DC0}-\u{0DC6}] | - \u{0DCA} | - [\u{0DCF}-\u{0DD4}] | - \u{0DD6} | - [\u{0DD8}-\u{0DDF}] | - [\u{0DE6}-\u{0DEF}] | - [\u{0DF2}-\u{0DF4}] | - [\u{0E01}-\u{0E3A}] | - [\u{0E3F}-\u{0E5B}] | - [\u{0E81}-\u{0E82}] | - \u{0E84} | - [\u{0E86}-\u{0E8A}] | - [\u{0E8C}-\u{0EA3}] | - \u{0EA5} | - [\u{0EA7}-\u{0EBD}] | - [\u{0EC0}-\u{0EC4}] | - \u{0EC6} | - [\u{0EC8}-\u{0ECD}] | - [\u{0ED0}-\u{0ED9}] | - [\u{0EDC}-\u{0EDF}] | - [\u{0F00}-\u{0F47}] | - [\u{0F49}-\u{0F6C}] | - [\u{0F71}-\u{0F97}] | - [\u{0F99}-\u{0FBC}] | - [\u{0FBE}-\u{0FCC}] | - [\u{0FCE}-\u{0FDA}] | - [\u{1000}-\u{10C5}] | - \u{10C7} | - \u{10CD} | - [\u{10D0}-\u{10FF}] | - [\u{1160}-\u{1248}] | - [\u{124A}-\u{124D}] | - [\u{1250}-\u{1256}] | - \u{1258} | - [\u{125A}-\u{125D}] | - [\u{1260}-\u{1288}] | - [\u{128A}-\u{128D}] | - [\u{1290}-\u{12B0}] | - [\u{12B2}-\u{12B5}] | - [\u{12B8}-\u{12BE}] | - \u{12C0} | - [\u{12C2}-\u{12C5}] | - [\u{12C8}-\u{12D6}] | - [\u{12D8}-\u{1310}] | - [\u{1312}-\u{1315}] | - [\u{1318}-\u{135A}] | - [\u{135D}-\u{137C}] | - [\u{1380}-\u{1399}] | - [\u{13A0}-\u{13F5}] | - [\u{13F8}-\u{13FD}] | - [\u{1400}-\u{169C}] | - [\u{16A0}-\u{16F8}] | - [\u{1700}-\u{170C}] | - [\u{170E}-\u{1714}] | - [\u{1720}-\u{1736}] | - [\u{1740}-\u{1753}] | - [\u{1760}-\u{176C}] | - [\u{176E}-\u{1770}] | - [\u{1772}-\u{1773}] | - [\u{1780}-\u{17DD}] | - [\u{17E0}-\u{17E9}] | - [\u{17F0}-\u{17F9}] | - [\u{1800}-\u{180E}] | - [\u{1810}-\u{1819}] | - [\u{1820}-\u{1878}] | - [\u{1880}-\u{18AA}] | - [\u{18B0}-\u{18F5}] | - [\u{1900}-\u{191E}] | - [\u{1920}-\u{192B}] | - [\u{1930}-\u{193B}] | - \u{1940} | - [\u{1944}-\u{196D}] | - [\u{1970}-\u{1974}] | - [\u{1980}-\u{19AB}] | - [\u{19B0}-\u{19C9}] | - [\u{19D0}-\u{19DA}] | - [\u{19DE}-\u{1A1B}] | - [\u{1A1E}-\u{1A5E}] | - [\u{1A60}-\u{1A7C}] | - [\u{1A7F}-\u{1A89}] | - [\u{1A90}-\u{1A99}] | - [\u{1AA0}-\u{1AAD}] | - [\u{1AB0}-\u{1ABE}] | - [\u{1B00}-\u{1B4B}] | - [\u{1B50}-\u{1B7C}] | - [\u{1B80}-\u{1BF3}] | - [\u{1BFC}-\u{1C37}] | - [\u{1C3B}-\u{1C49}] | - [\u{1C4D}-\u{1C88}] | - [\u{1C90}-\u{1CBA}] | - [\u{1CBD}-\u{1CC7}] | - [\u{1CD0}-\u{1CFA}] | - [\u{1D00}-\u{1DF9}] | - [\u{1DFB}-\u{1F15}] | - [\u{1F18}-\u{1F1D}] | - [\u{1F20}-\u{1F45}] | - [\u{1F48}-\u{1F4D}] | - [\u{1F50}-\u{1F57}] | - \u{1F59} | - \u{1F5B} | - \u{1F5D} | - [\u{1F5F}-\u{1F7D}] | - [\u{1F80}-\u{1FB4}] | - [\u{1FB6}-\u{1FC4}] | - [\u{1FC6}-\u{1FD3}] | - [\u{1FD6}-\u{1FDB}] | - [\u{1FDD}-\u{1FEF}] | - [\u{1FF2}-\u{1FF4}] | - [\u{1FF6}-\u{1FFE}] | - [\u{2000}-\u{200F}] | - [\u{2011}-\u{2012}] | - \u{2017} | - [\u{201A}-\u{201B}] | - [\u{201E}-\u{201F}] | - \u{2023} | - [\u{2028}-\u{202F}] | - \u{2031} | - \u{2034} | - [\u{2036}-\u{203A}] | - [\u{203C}-\u{203D}] | - [\u{203F}-\u{2064}] | - [\u{2066}-\u{2071}] | - [\u{2075}-\u{207E}] | - \u{2080} | - [\u{2085}-\u{208E}] | - [\u{2090}-\u{209C}] | - [\u{20A0}-\u{20A8}] | - [\u{20AA}-\u{20AB}] | - [\u{20AD}-\u{20BF}] | - [\u{20D0}-\u{20F0}] | - [\u{2100}-\u{2102}] | - \u{2104} | - [\u{2106}-\u{2108}] | - [\u{210A}-\u{2112}] | - [\u{2114}-\u{2115}] | - [\u{2117}-\u{2120}] | - [\u{2123}-\u{2125}] | - [\u{2127}-\u{212A}] | - [\u{212C}-\u{2152}] | - [\u{2155}-\u{215A}] | - \u{215F} | - [\u{216C}-\u{216F}] | - [\u{217A}-\u{2188}] | - [\u{218A}-\u{218B}] | - [\u{219A}-\u{21B7}] | - [\u{21BA}-\u{21D1}] | - \u{21D3} | - [\u{21D5}-\u{21E6}] | - [\u{21E8}-\u{21FF}] | - \u{2201} | - [\u{2204}-\u{2206}] | - [\u{2209}-\u{220A}] | - [\u{220C}-\u{220E}] | - \u{2210} | - [\u{2212}-\u{2214}] | - [\u{2216}-\u{2219}] | - [\u{221B}-\u{221C}] | - [\u{2221}-\u{2222}] | - \u{2224} | - \u{2226} | - \u{222D} | - [\u{222F}-\u{2233}] | - [\u{2238}-\u{223B}] | - [\u{223E}-\u{2247}] | - [\u{2249}-\u{224B}] | - [\u{224D}-\u{2251}] | - [\u{2253}-\u{225F}] | - [\u{2262}-\u{2263}] | - [\u{2268}-\u{2269}] | - [\u{226C}-\u{226D}] | - [\u{2270}-\u{2281}] | - [\u{2284}-\u{2285}] | - [\u{2288}-\u{2294}] | - [\u{2296}-\u{2298}] | - [\u{229A}-\u{22A4}] | - [\u{22A6}-\u{22BE}] | - [\u{22C0}-\u{2311}] | - [\u{2313}-\u{2319}] | - [\u{231C}-\u{2328}] | - [\u{232B}-\u{23E8}] | - [\u{23ED}-\u{23EF}] | - [\u{23F1}-\u{23F2}] | - [\u{23F4}-\u{2426}] | - [\u{2440}-\u{244A}] | - \u{24EA} | - [\u{254C}-\u{254F}] | - [\u{2574}-\u{257F}] | - [\u{2590}-\u{2591}] | - [\u{2596}-\u{259F}] | - \u{25A2} | - [\u{25AA}-\u{25B1}] | - [\u{25B4}-\u{25B5}] | - [\u{25B8}-\u{25BB}] | - [\u{25BE}-\u{25BF}] | - [\u{25C2}-\u{25C5}] | - [\u{25C9}-\u{25CA}] | - [\u{25CC}-\u{25CD}] | - [\u{25D2}-\u{25E1}] | - [\u{25E6}-\u{25EE}] | - [\u{25F0}-\u{25FC}] | - [\u{25FF}-\u{2604}] | - [\u{2607}-\u{2608}] | - [\u{260A}-\u{260D}] | - [\u{2610}-\u{2613}] | - [\u{2616}-\u{261B}] | - \u{261D} | - [\u{261F}-\u{263F}] | - \u{2641} | - [\u{2643}-\u{2647}] | - [\u{2654}-\u{265F}] | - \u{2662} | - \u{2666} | - \u{266B} | - \u{266E} | - [\u{2670}-\u{267E}] | - [\u{2680}-\u{2692}] | - [\u{2694}-\u{269D}] | - \u{26A0} | - [\u{26A2}-\u{26A9}] | - [\u{26AC}-\u{26BC}] | - [\u{26C0}-\u{26C3}] | - \u{26E2} | - [\u{26E4}-\u{26E7}] | - [\u{2700}-\u{2704}] | - [\u{2706}-\u{2709}] | - [\u{270C}-\u{2727}] | - [\u{2729}-\u{273C}] | - [\u{273E}-\u{274B}] | - \u{274D} | - [\u{274F}-\u{2752}] | - \u{2756} | - [\u{2758}-\u{2775}] | - [\u{2780}-\u{2794}] | - [\u{2798}-\u{27AF}] | - [\u{27B1}-\u{27BE}] | - [\u{27C0}-\u{27E5}] | - [\u{27EE}-\u{2984}] | - [\u{2987}-\u{2B1A}] | - [\u{2B1D}-\u{2B4F}] | - [\u{2B51}-\u{2B54}] | - [\u{2B5A}-\u{2B73}] | - [\u{2B76}-\u{2B95}] | - [\u{2B98}-\u{2C2E}] | - [\u{2C30}-\u{2C5E}] | - [\u{2C60}-\u{2CF3}] | - [\u{2CF9}-\u{2D25}] | - \u{2D27} | - \u{2D2D} | - [\u{2D30}-\u{2D67}] | - [\u{2D6F}-\u{2D70}] | - [\u{2D7F}-\u{2D96}] | - [\u{2DA0}-\u{2DA6}] | - [\u{2DA8}-\u{2DAE}] | - [\u{2DB0}-\u{2DB6}] | - [\u{2DB8}-\u{2DBE}] | - [\u{2DC0}-\u{2DC6}] | - [\u{2DC8}-\u{2DCE}] | - [\u{2DD0}-\u{2DD6}] | - [\u{2DD8}-\u{2DDE}] | - [\u{2DE0}-\u{2E4F}] | - \u{303F} | - [\u{4DC0}-\u{4DFF}] | - [\u{A4D0}-\u{A62B}] | - [\u{A640}-\u{A6F7}] | - [\u{A700}-\u{A7BF}] | - [\u{A7C2}-\u{A7C6}] | - [\u{A7F7}-\u{A82B}] | - [\u{A830}-\u{A839}] | - [\u{A840}-\u{A877}] | - [\u{A880}-\u{A8C5}] | - [\u{A8CE}-\u{A8D9}] | - [\u{A8E0}-\u{A953}] | - \u{A95F} | - [\u{A980}-\u{A9CD}] | - [\u{A9CF}-\u{A9D9}] | - [\u{A9DE}-\u{A9FE}] | - [\u{AA00}-\u{AA36}] | - [\u{AA40}-\u{AA4D}] | - [\u{AA50}-\u{AA59}] | - [\u{AA5C}-\u{AAC2}] | - [\u{AADB}-\u{AAF6}] | - [\u{AB01}-\u{AB06}] | - [\u{AB09}-\u{AB0E}] | - [\u{AB11}-\u{AB16}] | - [\u{AB20}-\u{AB26}] | - [\u{AB28}-\u{AB2E}] | - [\u{AB30}-\u{AB67}] | - [\u{AB70}-\u{ABED}] | - [\u{ABF0}-\u{ABF9}] | - [\u{D7B0}-\u{D7C6}] | - [\u{D7CB}-\u{D7FB}] | - [\u{FB00}-\u{FB06}] | - [\u{FB13}-\u{FB17}] | - [\u{FB1D}-\u{FB36}] | - [\u{FB38}-\u{FB3C}] | - \u{FB3E} | - [\u{FB40}-\u{FB41}] | - [\u{FB43}-\u{FB44}] | - [\u{FB46}-\u{FBC1}] | - [\u{FBD3}-\u{FD3F}] | - [\u{FD50}-\u{FD8F}] | - [\u{FD92}-\u{FDC7}] | - [\u{FDF0}-\u{FDFD}] | - [\u{FE20}-\u{FE2F}] | - [\u{FE70}-\u{FE74}] | - [\u{FE76}-\u{FEFC}] | - \u{FEFF} | - [\u{FFF9}-\u{FFFC}] | - [\u{10000}-\u{1000B}] | - [\u{1000D}-\u{10026}] | - [\u{10028}-\u{1003A}] | - [\u{1003C}-\u{1003D}] | - [\u{1003F}-\u{1004D}] | - [\u{10050}-\u{1005D}] | - [\u{10080}-\u{100FA}] | - [\u{10100}-\u{10102}] | - [\u{10107}-\u{10133}] | - [\u{10137}-\u{1018E}] | - [\u{10190}-\u{1019B}] | - \u{101A0} | - [\u{101D0}-\u{101FD}] | - [\u{10280}-\u{1029C}] | - [\u{102A0}-\u{102D0}] | - [\u{102E0}-\u{102FB}] | - [\u{10300}-\u{10323}] | - [\u{1032D}-\u{1034A}] | - [\u{10350}-\u{1037A}] | - [\u{10380}-\u{1039D}] | - [\u{1039F}-\u{103C3}] | - [\u{103C8}-\u{103D5}] | - [\u{10400}-\u{1049D}] | - [\u{104A0}-\u{104A9}] | - [\u{104B0}-\u{104D3}] | - [\u{104D8}-\u{104FB}] | - [\u{10500}-\u{10527}] | - [\u{10530}-\u{10563}] | - \u{1056F} | - [\u{10600}-\u{10736}] | - [\u{10740}-\u{10755}] | - [\u{10760}-\u{10767}] | - [\u{10800}-\u{10805}] | - \u{10808} | - [\u{1080A}-\u{10835}] | - [\u{10837}-\u{10838}] | - \u{1083C} | - [\u{1083F}-\u{10855}] | - [\u{10857}-\u{1089E}] | - [\u{108A7}-\u{108AF}] | - [\u{108E0}-\u{108F2}] | - [\u{108F4}-\u{108F5}] | - [\u{108FB}-\u{1091B}] | - [\u{1091F}-\u{10939}] | - \u{1093F} | - [\u{10980}-\u{109B7}] | - [\u{109BC}-\u{109CF}] | - [\u{109D2}-\u{10A03}] | - [\u{10A05}-\u{10A06}] | - [\u{10A0C}-\u{10A13}] | - [\u{10A15}-\u{10A17}] | - [\u{10A19}-\u{10A35}] | - [\u{10A38}-\u{10A3A}] | - [\u{10A3F}-\u{10A48}] | - [\u{10A50}-\u{10A58}] | - [\u{10A60}-\u{10A9F}] | - [\u{10AC0}-\u{10AE6}] | - [\u{10AEB}-\u{10AF6}] | - [\u{10B00}-\u{10B35}] | - [\u{10B39}-\u{10B55}] | - [\u{10B58}-\u{10B72}] | - [\u{10B78}-\u{10B91}] | - [\u{10B99}-\u{10B9C}] | - [\u{10BA9}-\u{10BAF}] | - [\u{10C00}-\u{10C48}] | - [\u{10C80}-\u{10CB2}] | - [\u{10CC0}-\u{10CF2}] | - [\u{10CFA}-\u{10D27}] | - [\u{10D30}-\u{10D39}] | - [\u{10E60}-\u{10E7E}] | - [\u{10F00}-\u{10F27}] | - [\u{10F30}-\u{10F59}] | - [\u{10FE0}-\u{10FF6}] | - [\u{11000}-\u{1104D}] | - [\u{11052}-\u{1106F}] | - [\u{1107F}-\u{110C1}] | - \u{110CD} | - [\u{110D0}-\u{110E8}] | - [\u{110F0}-\u{110F9}] | - [\u{11100}-\u{11134}] | - [\u{11136}-\u{11146}] | - [\u{11150}-\u{11176}] | - [\u{11180}-\u{111CD}] | - [\u{111D0}-\u{111DF}] | - [\u{111E1}-\u{111F4}] | - [\u{11200}-\u{11211}] | - [\u{11213}-\u{1123E}] | - [\u{11280}-\u{11286}] | - \u{11288} | - [\u{1128A}-\u{1128D}] | - [\u{1128F}-\u{1129D}] | - [\u{1129F}-\u{112A9}] | - [\u{112B0}-\u{112EA}] | - [\u{112F0}-\u{112F9}] | - [\u{11300}-\u{11303}] | - [\u{11305}-\u{1130C}] | - [\u{1130F}-\u{11310}] | - [\u{11313}-\u{11328}] | - [\u{1132A}-\u{11330}] | - [\u{11332}-\u{11333}] | - [\u{11335}-\u{11339}] | - [\u{1133B}-\u{11344}] | - [\u{11347}-\u{11348}] | - [\u{1134B}-\u{1134D}] | - \u{11350} | - \u{11357} | - [\u{1135D}-\u{11363}] | - [\u{11366}-\u{1136C}] | - [\u{11370}-\u{11374}] | - [\u{11400}-\u{11459}] | - \u{1145B} | - [\u{1145D}-\u{1145F}] | - [\u{11480}-\u{114C7}] | - [\u{114D0}-\u{114D9}] | - [\u{11580}-\u{115B5}] | - [\u{115B8}-\u{115DD}] | - [\u{11600}-\u{11644}] | - [\u{11650}-\u{11659}] | - [\u{11660}-\u{1166C}] | - [\u{11680}-\u{116B8}] | - [\u{116C0}-\u{116C9}] | - [\u{11700}-\u{1171A}] | - [\u{1171D}-\u{1172B}] | - [\u{11730}-\u{1173F}] | - [\u{11800}-\u{1183B}] | - [\u{118A0}-\u{118F2}] | - \u{118FF} | - [\u{119A0}-\u{119A7}] | - [\u{119AA}-\u{119D7}] | - [\u{119DA}-\u{119E4}] | - [\u{11A00}-\u{11A47}] | - [\u{11A50}-\u{11AA2}] | - [\u{11AC0}-\u{11AF8}] | - [\u{11C00}-\u{11C08}] | - [\u{11C0A}-\u{11C36}] | - [\u{11C38}-\u{11C45}] | - [\u{11C50}-\u{11C6C}] | - [\u{11C70}-\u{11C8F}] | - [\u{11C92}-\u{11CA7}] | - [\u{11CA9}-\u{11CB6}] | - [\u{11D00}-\u{11D06}] | - [\u{11D08}-\u{11D09}] | - [\u{11D0B}-\u{11D36}] | - \u{11D3A} | - [\u{11D3C}-\u{11D3D}] | - [\u{11D3F}-\u{11D47}] | - [\u{11D50}-\u{11D59}] | - [\u{11D60}-\u{11D65}] | - [\u{11D67}-\u{11D68}] | - [\u{11D6A}-\u{11D8E}] | - [\u{11D90}-\u{11D91}] | - [\u{11D93}-\u{11D98}] | - [\u{11DA0}-\u{11DA9}] | - [\u{11EE0}-\u{11EF8}] | - [\u{11FC0}-\u{11FF1}] | - [\u{11FFF}-\u{12399}] | - [\u{12400}-\u{1246E}] | - [\u{12470}-\u{12474}] | - [\u{12480}-\u{12543}] | - [\u{13000}-\u{1342E}] | - [\u{13430}-\u{13438}] | - [\u{14400}-\u{14646}] | - [\u{16800}-\u{16A38}] | - [\u{16A40}-\u{16A5E}] | - [\u{16A60}-\u{16A69}] | - [\u{16A6E}-\u{16A6F}] | - [\u{16AD0}-\u{16AED}] | - [\u{16AF0}-\u{16AF5}] | - [\u{16B00}-\u{16B45}] | - [\u{16B50}-\u{16B59}] | - [\u{16B5B}-\u{16B61}] | - [\u{16B63}-\u{16B77}] | - [\u{16B7D}-\u{16B8F}] | - [\u{16E40}-\u{16E9A}] | - [\u{16F00}-\u{16F4A}] | - [\u{16F4F}-\u{16F87}] | - [\u{16F8F}-\u{16F9F}] | - [\u{1BC00}-\u{1BC6A}] | - [\u{1BC70}-\u{1BC7C}] | - [\u{1BC80}-\u{1BC88}] | - [\u{1BC90}-\u{1BC99}] | - [\u{1BC9C}-\u{1BCA3}] | - [\u{1D000}-\u{1D0F5}] | - [\u{1D100}-\u{1D126}] | - [\u{1D129}-\u{1D1E8}] | - [\u{1D200}-\u{1D245}] | - [\u{1D2E0}-\u{1D2F3}] | - [\u{1D300}-\u{1D356}] | - [\u{1D360}-\u{1D378}] | - [\u{1D400}-\u{1D454}] | - [\u{1D456}-\u{1D49C}] | - [\u{1D49E}-\u{1D49F}] | - \u{1D4A2} | - [\u{1D4A5}-\u{1D4A6}] | - [\u{1D4A9}-\u{1D4AC}] | - [\u{1D4AE}-\u{1D4B9}] | - \u{1D4BB} | - [\u{1D4BD}-\u{1D4C3}] | - [\u{1D4C5}-\u{1D505}] | - [\u{1D507}-\u{1D50A}] | - [\u{1D50D}-\u{1D514}] | - [\u{1D516}-\u{1D51C}] | - [\u{1D51E}-\u{1D539}] | - [\u{1D53B}-\u{1D53E}] | - [\u{1D540}-\u{1D544}] | - \u{1D546} | - [\u{1D54A}-\u{1D550}] | - [\u{1D552}-\u{1D6A5}] | - [\u{1D6A8}-\u{1D7CB}] | - [\u{1D7CE}-\u{1DA8B}] | - [\u{1DA9B}-\u{1DA9F}] | - [\u{1DAA1}-\u{1DAAF}] | - [\u{1E000}-\u{1E006}] | - [\u{1E008}-\u{1E018}] | - [\u{1E01B}-\u{1E021}] | - [\u{1E023}-\u{1E024}] | - [\u{1E026}-\u{1E02A}] | - [\u{1E100}-\u{1E12C}] | - [\u{1E130}-\u{1E13D}] | - [\u{1E140}-\u{1E149}] | - [\u{1E14E}-\u{1E14F}] | - [\u{1E2C0}-\u{1E2F9}] | - \u{1E2FF} | - [\u{1E800}-\u{1E8C4}] | - [\u{1E8C7}-\u{1E8D6}] | - [\u{1E900}-\u{1E94B}] | - [\u{1E950}-\u{1E959}] | - [\u{1E95E}-\u{1E95F}] | - [\u{1EC71}-\u{1ECB4}] | - [\u{1ED01}-\u{1ED3D}] | - [\u{1EE00}-\u{1EE03}] | - [\u{1EE05}-\u{1EE1F}] | - [\u{1EE21}-\u{1EE22}] | - \u{1EE24} | - \u{1EE27} | - [\u{1EE29}-\u{1EE32}] | - [\u{1EE34}-\u{1EE37}] | - \u{1EE39} | - \u{1EE3B} | - \u{1EE42} | - \u{1EE47} | - \u{1EE49} | - \u{1EE4B} | - [\u{1EE4D}-\u{1EE4F}] | - [\u{1EE51}-\u{1EE52}] | - \u{1EE54} | - \u{1EE57} | - \u{1EE59} | - \u{1EE5B} | - \u{1EE5D} | - \u{1EE5F} | - [\u{1EE61}-\u{1EE62}] | - \u{1EE64} | - [\u{1EE67}-\u{1EE6A}] | - [\u{1EE6C}-\u{1EE72}] | - [\u{1EE74}-\u{1EE77}] | - [\u{1EE79}-\u{1EE7C}] | - \u{1EE7E} | - [\u{1EE80}-\u{1EE89}] | - [\u{1EE8B}-\u{1EE9B}] | - [\u{1EEA1}-\u{1EEA3}] | - [\u{1EEA5}-\u{1EEA9}] | - [\u{1EEAB}-\u{1EEBB}] | - [\u{1EEF0}-\u{1EEF1}] | - [\u{1F000}-\u{1F003}] | - [\u{1F005}-\u{1F02B}] | - [\u{1F030}-\u{1F093}] | - [\u{1F0A0}-\u{1F0AE}] | - [\u{1F0B1}-\u{1F0BF}] | - [\u{1F0C1}-\u{1F0CE}] | - [\u{1F0D1}-\u{1F0F5}] | - [\u{1F10B}-\u{1F10C}] | - [\u{1F12E}-\u{1F12F}] | - [\u{1F16A}-\u{1F16C}] | - [\u{1F1E6}-\u{1F1FF}] | - [\u{1F321}-\u{1F32C}] | - \u{1F336} | - \u{1F37D} | - [\u{1F394}-\u{1F39F}] | - [\u{1F3CB}-\u{1F3CE}] | - [\u{1F3D4}-\u{1F3DF}] | - [\u{1F3F1}-\u{1F3F3}] | - [\u{1F3F5}-\u{1F3F7}] | - \u{1F43F} | - \u{1F441} | - [\u{1F4FD}-\u{1F4FE}] | - [\u{1F53E}-\u{1F54A}] | - \u{1F54F} | - [\u{1F568}-\u{1F579}] | - [\u{1F57B}-\u{1F594}] | - [\u{1F597}-\u{1F5A3}] | - [\u{1F5A5}-\u{1F5FA}] | - [\u{1F650}-\u{1F67F}] | - [\u{1F6C6}-\u{1F6CB}] | - [\u{1F6CD}-\u{1F6CF}] | - [\u{1F6D3}-\u{1F6D4}] | - [\u{1F6E0}-\u{1F6EA}] | - [\u{1F6F0}-\u{1F6F3}] | - [\u{1F700}-\u{1F773}] | - [\u{1F780}-\u{1F7D8}] | - [\u{1F800}-\u{1F80B}] | - [\u{1F810}-\u{1F847}] | - [\u{1F850}-\u{1F859}] | - [\u{1F860}-\u{1F887}] | - [\u{1F890}-\u{1F8AD}] | - [\u{1F900}-\u{1F90B}] | - [\u{1FA00}-\u{1FA53}] | - [\u{1FA60}-\u{1FA6D}] | - \u{E0001} | - [\u{E0020}-\u{E007F}] - )/x + TYPE_N = /^[#{ %W( + \u{0000}-\u{001F} + \u{007F}-\u{00A0} + \u{00A9} + \u{00AB} + \u{00B5} + \u{00BB} + \u{00C0}-\u{00C5} + \u{00C7}-\u{00CF} + \u{00D1}-\u{00D6} + \u{00D9}-\u{00DD} + \u{00E2}-\u{00E5} + \u{00E7} + \u{00EB} + \u{00EE}-\u{00EF} + \u{00F1} + \u{00F4}-\u{00F6} + \u{00FB} + \u{00FD} + \u{00FF}-\u{0100} + \u{0102}-\u{0110} + \u{0112} + \u{0114}-\u{011A} + \u{011C}-\u{0125} + \u{0128}-\u{012A} + \u{012C}-\u{0130} + \u{0134}-\u{0137} + \u{0139}-\u{013E} + \u{0143} + \u{0145}-\u{0147} + \u{014C} + \u{014E}-\u{0151} + \u{0154}-\u{0165} + \u{0168}-\u{016A} + \u{016C}-\u{01CD} + \u{01CF} + \u{01D1} + \u{01D3} + \u{01D5} + \u{01D7} + \u{01D9} + \u{01DB} + \u{01DD}-\u{0250} + \u{0252}-\u{0260} + \u{0262}-\u{02C3} + \u{02C5}-\u{02C6} + \u{02C8} + \u{02CC} + \u{02CE}-\u{02CF} + \u{02D1}-\u{02D7} + \u{02DC} + \u{02DE} + \u{02E0}-\u{02FF} + \u{0370}-\u{0377} + \u{037A}-\u{037F} + \u{0384}-\u{038A} + \u{038C} + \u{038E}-\u{0390} + \u{03AA}-\u{03B0} + \u{03C2} + \u{03CA}-\u{0400} + \u{0402}-\u{040F} + \u{0450} + \u{0452}-\u{052F} + \u{0531}-\u{0556} + \u{0559}-\u{058A} + \u{058D}-\u{058F} + \u{0591}-\u{05C7} + \u{05D0}-\u{05EA} + \u{05EF}-\u{05F4} + \u{0600}-\u{061C} + \u{061E}-\u{070D} + \u{070F}-\u{074A} + \u{074D}-\u{07B1} + \u{07C0}-\u{07FA} + \u{07FD}-\u{082D} + \u{0830}-\u{083E} + \u{0840}-\u{085B} + \u{085E} + \u{0860}-\u{086A} + \u{08A0}-\u{08B4} + \u{08B6}-\u{08C7} + \u{08D3}-\u{0983} + \u{0985}-\u{098C} + \u{098F}-\u{0990} + \u{0993}-\u{09A8} + \u{09AA}-\u{09B0} + \u{09B2} + \u{09B6}-\u{09B9} + \u{09BC}-\u{09C4} + \u{09C7}-\u{09C8} + \u{09CB}-\u{09CE} + \u{09D7} + \u{09DC}-\u{09DD} + \u{09DF}-\u{09E3} + \u{09E6}-\u{09FE} + \u{0A01}-\u{0A03} + \u{0A05}-\u{0A0A} + \u{0A0F}-\u{0A10} + \u{0A13}-\u{0A28} + \u{0A2A}-\u{0A30} + \u{0A32}-\u{0A33} + \u{0A35}-\u{0A36} + \u{0A38}-\u{0A39} + \u{0A3C} + \u{0A3E}-\u{0A42} + \u{0A47}-\u{0A48} + \u{0A4B}-\u{0A4D} + \u{0A51} + \u{0A59}-\u{0A5C} + \u{0A5E} + \u{0A66}-\u{0A76} + \u{0A81}-\u{0A83} + \u{0A85}-\u{0A8D} + \u{0A8F}-\u{0A91} + \u{0A93}-\u{0AA8} + \u{0AAA}-\u{0AB0} + \u{0AB2}-\u{0AB3} + \u{0AB5}-\u{0AB9} + \u{0ABC}-\u{0AC5} + \u{0AC7}-\u{0AC9} + \u{0ACB}-\u{0ACD} + \u{0AD0} + \u{0AE0}-\u{0AE3} + \u{0AE6}-\u{0AF1} + \u{0AF9}-\u{0AFF} + \u{0B01}-\u{0B03} + \u{0B05}-\u{0B0C} + \u{0B0F}-\u{0B10} + \u{0B13}-\u{0B28} + \u{0B2A}-\u{0B30} + \u{0B32}-\u{0B33} + \u{0B35}-\u{0B39} + \u{0B3C}-\u{0B44} + \u{0B47}-\u{0B48} + \u{0B4B}-\u{0B4D} + \u{0B55}-\u{0B57} + \u{0B5C}-\u{0B5D} + \u{0B5F}-\u{0B63} + \u{0B66}-\u{0B77} + \u{0B82}-\u{0B83} + \u{0B85}-\u{0B8A} + \u{0B8E}-\u{0B90} + \u{0B92}-\u{0B95} + \u{0B99}-\u{0B9A} + \u{0B9C} + \u{0B9E}-\u{0B9F} + \u{0BA3}-\u{0BA4} + \u{0BA8}-\u{0BAA} + \u{0BAE}-\u{0BB9} + \u{0BBE}-\u{0BC2} + \u{0BC6}-\u{0BC8} + \u{0BCA}-\u{0BCD} + \u{0BD0} + \u{0BD7} + \u{0BE6}-\u{0BFA} + \u{0C00}-\u{0C0C} + \u{0C0E}-\u{0C10} + \u{0C12}-\u{0C28} + \u{0C2A}-\u{0C39} + \u{0C3D}-\u{0C44} + \u{0C46}-\u{0C48} + \u{0C4A}-\u{0C4D} + \u{0C55}-\u{0C56} + \u{0C58}-\u{0C5A} + \u{0C60}-\u{0C63} + \u{0C66}-\u{0C6F} + \u{0C77}-\u{0C8C} + \u{0C8E}-\u{0C90} + \u{0C92}-\u{0CA8} + \u{0CAA}-\u{0CB3} + \u{0CB5}-\u{0CB9} + \u{0CBC}-\u{0CC4} + \u{0CC6}-\u{0CC8} + \u{0CCA}-\u{0CCD} + \u{0CD5}-\u{0CD6} + \u{0CDE} + \u{0CE0}-\u{0CE3} + \u{0CE6}-\u{0CEF} + \u{0CF1}-\u{0CF2} + \u{0D00}-\u{0D0C} + \u{0D0E}-\u{0D10} + \u{0D12}-\u{0D44} + \u{0D46}-\u{0D48} + \u{0D4A}-\u{0D4F} + \u{0D54}-\u{0D63} + \u{0D66}-\u{0D7F} + \u{0D81}-\u{0D83} + \u{0D85}-\u{0D96} + \u{0D9A}-\u{0DB1} + \u{0DB3}-\u{0DBB} + \u{0DBD} + \u{0DC0}-\u{0DC6} + \u{0DCA} + \u{0DCF}-\u{0DD4} + \u{0DD6} + \u{0DD8}-\u{0DDF} + \u{0DE6}-\u{0DEF} + \u{0DF2}-\u{0DF4} + \u{0E01}-\u{0E3A} + \u{0E3F}-\u{0E5B} + \u{0E81}-\u{0E82} + \u{0E84} + \u{0E86}-\u{0E8A} + \u{0E8C}-\u{0EA3} + \u{0EA5} + \u{0EA7}-\u{0EBD} + \u{0EC0}-\u{0EC4} + \u{0EC6} + \u{0EC8}-\u{0ECD} + \u{0ED0}-\u{0ED9} + \u{0EDC}-\u{0EDF} + \u{0F00}-\u{0F47} + \u{0F49}-\u{0F6C} + \u{0F71}-\u{0F97} + \u{0F99}-\u{0FBC} + \u{0FBE}-\u{0FCC} + \u{0FCE}-\u{0FDA} + \u{1000}-\u{10C5} + \u{10C7} + \u{10CD} + \u{10D0}-\u{10FF} + \u{1160}-\u{1248} + \u{124A}-\u{124D} + \u{1250}-\u{1256} + \u{1258} + \u{125A}-\u{125D} + \u{1260}-\u{1288} + \u{128A}-\u{128D} + \u{1290}-\u{12B0} + \u{12B2}-\u{12B5} + \u{12B8}-\u{12BE} + \u{12C0} + \u{12C2}-\u{12C5} + \u{12C8}-\u{12D6} + \u{12D8}-\u{1310} + \u{1312}-\u{1315} + \u{1318}-\u{135A} + \u{135D}-\u{137C} + \u{1380}-\u{1399} + \u{13A0}-\u{13F5} + \u{13F8}-\u{13FD} + \u{1400}-\u{169C} + \u{16A0}-\u{16F8} + \u{1700}-\u{170C} + \u{170E}-\u{1714} + \u{1720}-\u{1736} + \u{1740}-\u{1753} + \u{1760}-\u{176C} + \u{176E}-\u{1770} + \u{1772}-\u{1773} + \u{1780}-\u{17DD} + \u{17E0}-\u{17E9} + \u{17F0}-\u{17F9} + \u{1800}-\u{180E} + \u{1810}-\u{1819} + \u{1820}-\u{1878} + \u{1880}-\u{18AA} + \u{18B0}-\u{18F5} + \u{1900}-\u{191E} + \u{1920}-\u{192B} + \u{1930}-\u{193B} + \u{1940} + \u{1944}-\u{196D} + \u{1970}-\u{1974} + \u{1980}-\u{19AB} + \u{19B0}-\u{19C9} + \u{19D0}-\u{19DA} + \u{19DE}-\u{1A1B} + \u{1A1E}-\u{1A5E} + \u{1A60}-\u{1A7C} + \u{1A7F}-\u{1A89} + \u{1A90}-\u{1A99} + \u{1AA0}-\u{1AAD} + \u{1AB0}-\u{1AC0} + \u{1B00}-\u{1B4B} + \u{1B50}-\u{1B7C} + \u{1B80}-\u{1BF3} + \u{1BFC}-\u{1C37} + \u{1C3B}-\u{1C49} + \u{1C4D}-\u{1C88} + \u{1C90}-\u{1CBA} + \u{1CBD}-\u{1CC7} + \u{1CD0}-\u{1CFA} + \u{1D00}-\u{1DF9} + \u{1DFB}-\u{1F15} + \u{1F18}-\u{1F1D} + \u{1F20}-\u{1F45} + \u{1F48}-\u{1F4D} + \u{1F50}-\u{1F57} + \u{1F59} + \u{1F5B} + \u{1F5D} + \u{1F5F}-\u{1F7D} + \u{1F80}-\u{1FB4} + \u{1FB6}-\u{1FC4} + \u{1FC6}-\u{1FD3} + \u{1FD6}-\u{1FDB} + \u{1FDD}-\u{1FEF} + \u{1FF2}-\u{1FF4} + \u{1FF6}-\u{1FFE} + \u{2000}-\u{200F} + \u{2011}-\u{2012} + \u{2017} + \u{201A}-\u{201B} + \u{201E}-\u{201F} + \u{2023} + \u{2028}-\u{202F} + \u{2031} + \u{2034} + \u{2036}-\u{203A} + \u{203C}-\u{203D} + \u{203F}-\u{2064} + \u{2066}-\u{2071} + \u{2075}-\u{207E} + \u{2080} + \u{2085}-\u{208E} + \u{2090}-\u{209C} + \u{20A0}-\u{20A8} + \u{20AA}-\u{20AB} + \u{20AD}-\u{20BF} + \u{20D0}-\u{20F0} + \u{2100}-\u{2102} + \u{2104} + \u{2106}-\u{2108} + \u{210A}-\u{2112} + \u{2114}-\u{2115} + \u{2117}-\u{2120} + \u{2123}-\u{2125} + \u{2127}-\u{212A} + \u{212C}-\u{2152} + \u{2155}-\u{215A} + \u{215F} + \u{216C}-\u{216F} + \u{217A}-\u{2188} + \u{218A}-\u{218B} + \u{219A}-\u{21B7} + \u{21BA}-\u{21D1} + \u{21D3} + \u{21D5}-\u{21E6} + \u{21E8}-\u{21FF} + \u{2201} + \u{2204}-\u{2206} + \u{2209}-\u{220A} + \u{220C}-\u{220E} + \u{2210} + \u{2212}-\u{2214} + \u{2216}-\u{2219} + \u{221B}-\u{221C} + \u{2221}-\u{2222} + \u{2224} + \u{2226} + \u{222D} + \u{222F}-\u{2233} + \u{2238}-\u{223B} + \u{223E}-\u{2247} + \u{2249}-\u{224B} + \u{224D}-\u{2251} + \u{2253}-\u{225F} + \u{2262}-\u{2263} + \u{2268}-\u{2269} + \u{226C}-\u{226D} + \u{2270}-\u{2281} + \u{2284}-\u{2285} + \u{2288}-\u{2294} + \u{2296}-\u{2298} + \u{229A}-\u{22A4} + \u{22A6}-\u{22BE} + \u{22C0}-\u{2311} + \u{2313}-\u{2319} + \u{231C}-\u{2328} + \u{232B}-\u{23E8} + \u{23ED}-\u{23EF} + \u{23F1}-\u{23F2} + \u{23F4}-\u{2426} + \u{2440}-\u{244A} + \u{24EA} + \u{254C}-\u{254F} + \u{2574}-\u{257F} + \u{2590}-\u{2591} + \u{2596}-\u{259F} + \u{25A2} + \u{25AA}-\u{25B1} + \u{25B4}-\u{25B5} + \u{25B8}-\u{25BB} + \u{25BE}-\u{25BF} + \u{25C2}-\u{25C5} + \u{25C9}-\u{25CA} + \u{25CC}-\u{25CD} + \u{25D2}-\u{25E1} + \u{25E6}-\u{25EE} + \u{25F0}-\u{25FC} + \u{25FF}-\u{2604} + \u{2607}-\u{2608} + \u{260A}-\u{260D} + \u{2610}-\u{2613} + \u{2616}-\u{261B} + \u{261D} + \u{261F}-\u{263F} + \u{2641} + \u{2643}-\u{2647} + \u{2654}-\u{265F} + \u{2662} + \u{2666} + \u{266B} + \u{266E} + \u{2670}-\u{267E} + \u{2680}-\u{2692} + \u{2694}-\u{269D} + \u{26A0} + \u{26A2}-\u{26A9} + \u{26AC}-\u{26BC} + \u{26C0}-\u{26C3} + \u{26E2} + \u{26E4}-\u{26E7} + \u{2700}-\u{2704} + \u{2706}-\u{2709} + \u{270C}-\u{2727} + \u{2729}-\u{273C} + \u{273E}-\u{274B} + \u{274D} + \u{274F}-\u{2752} + \u{2756} + \u{2758}-\u{2775} + \u{2780}-\u{2794} + \u{2798}-\u{27AF} + \u{27B1}-\u{27BE} + \u{27C0}-\u{27E5} + \u{27EE}-\u{2984} + \u{2987}-\u{2B1A} + \u{2B1D}-\u{2B4F} + \u{2B51}-\u{2B54} + \u{2B5A}-\u{2B73} + \u{2B76}-\u{2B95} + \u{2B97}-\u{2C2E} + \u{2C30}-\u{2C5E} + \u{2C60}-\u{2CF3} + \u{2CF9}-\u{2D25} + \u{2D27} + \u{2D2D} + \u{2D30}-\u{2D67} + \u{2D6F}-\u{2D70} + \u{2D7F}-\u{2D96} + \u{2DA0}-\u{2DA6} + \u{2DA8}-\u{2DAE} + \u{2DB0}-\u{2DB6} + \u{2DB8}-\u{2DBE} + \u{2DC0}-\u{2DC6} + \u{2DC8}-\u{2DCE} + \u{2DD0}-\u{2DD6} + \u{2DD8}-\u{2DDE} + \u{2DE0}-\u{2E52} + \u{303F} + \u{4DC0}-\u{4DFF} + \u{A4D0}-\u{A62B} + \u{A640}-\u{A6F7} + \u{A700}-\u{A7BF} + \u{A7C2}-\u{A7CA} + \u{A7F5}-\u{A82C} + \u{A830}-\u{A839} + \u{A840}-\u{A877} + \u{A880}-\u{A8C5} + \u{A8CE}-\u{A8D9} + \u{A8E0}-\u{A953} + \u{A95F} + \u{A980}-\u{A9CD} + \u{A9CF}-\u{A9D9} + \u{A9DE}-\u{A9FE} + \u{AA00}-\u{AA36} + \u{AA40}-\u{AA4D} + \u{AA50}-\u{AA59} + \u{AA5C}-\u{AAC2} + \u{AADB}-\u{AAF6} + \u{AB01}-\u{AB06} + \u{AB09}-\u{AB0E} + \u{AB11}-\u{AB16} + \u{AB20}-\u{AB26} + \u{AB28}-\u{AB2E} + \u{AB30}-\u{AB6B} + \u{AB70}-\u{ABED} + \u{ABF0}-\u{ABF9} + \u{D7B0}-\u{D7C6} + \u{D7CB}-\u{D7FB} + \u{FB00}-\u{FB06} + \u{FB13}-\u{FB17} + \u{FB1D}-\u{FB36} + \u{FB38}-\u{FB3C} + \u{FB3E} + \u{FB40}-\u{FB41} + \u{FB43}-\u{FB44} + \u{FB46}-\u{FBC1} + \u{FBD3}-\u{FD3F} + \u{FD50}-\u{FD8F} + \u{FD92}-\u{FDC7} + \u{FDF0}-\u{FDFD} + \u{FE20}-\u{FE2F} + \u{FE70}-\u{FE74} + \u{FE76}-\u{FEFC} + \u{FEFF} + \u{FFF9}-\u{FFFC} + \u{10000}-\u{1000B} + \u{1000D}-\u{10026} + \u{10028}-\u{1003A} + \u{1003C}-\u{1003D} + \u{1003F}-\u{1004D} + \u{10050}-\u{1005D} + \u{10080}-\u{100FA} + \u{10100}-\u{10102} + \u{10107}-\u{10133} + \u{10137}-\u{1018E} + \u{10190}-\u{1019C} + \u{101A0} + \u{101D0}-\u{101FD} + \u{10280}-\u{1029C} + \u{102A0}-\u{102D0} + \u{102E0}-\u{102FB} + \u{10300}-\u{10323} + \u{1032D}-\u{1034A} + \u{10350}-\u{1037A} + \u{10380}-\u{1039D} + \u{1039F}-\u{103C3} + \u{103C8}-\u{103D5} + \u{10400}-\u{1049D} + \u{104A0}-\u{104A9} + \u{104B0}-\u{104D3} + \u{104D8}-\u{104FB} + \u{10500}-\u{10527} + \u{10530}-\u{10563} + \u{1056F} + \u{10600}-\u{10736} + \u{10740}-\u{10755} + \u{10760}-\u{10767} + \u{10800}-\u{10805} + \u{10808} + \u{1080A}-\u{10835} + \u{10837}-\u{10838} + \u{1083C} + \u{1083F}-\u{10855} + \u{10857}-\u{1089E} + \u{108A7}-\u{108AF} + \u{108E0}-\u{108F2} + \u{108F4}-\u{108F5} + \u{108FB}-\u{1091B} + \u{1091F}-\u{10939} + \u{1093F} + \u{10980}-\u{109B7} + \u{109BC}-\u{109CF} + \u{109D2}-\u{10A03} + \u{10A05}-\u{10A06} + \u{10A0C}-\u{10A13} + \u{10A15}-\u{10A17} + \u{10A19}-\u{10A35} + \u{10A38}-\u{10A3A} + \u{10A3F}-\u{10A48} + \u{10A50}-\u{10A58} + \u{10A60}-\u{10A9F} + \u{10AC0}-\u{10AE6} + \u{10AEB}-\u{10AF6} + \u{10B00}-\u{10B35} + \u{10B39}-\u{10B55} + \u{10B58}-\u{10B72} + \u{10B78}-\u{10B91} + \u{10B99}-\u{10B9C} + \u{10BA9}-\u{10BAF} + \u{10C00}-\u{10C48} + \u{10C80}-\u{10CB2} + \u{10CC0}-\u{10CF2} + \u{10CFA}-\u{10D27} + \u{10D30}-\u{10D39} + \u{10E60}-\u{10E7E} + \u{10E80}-\u{10EA9} + \u{10EAB}-\u{10EAD} + \u{10EB0}-\u{10EB1} + \u{10F00}-\u{10F27} + \u{10F30}-\u{10F59} + \u{10FB0}-\u{10FCB} + \u{10FE0}-\u{10FF6} + \u{11000}-\u{1104D} + \u{11052}-\u{1106F} + \u{1107F}-\u{110C1} + \u{110CD} + \u{110D0}-\u{110E8} + \u{110F0}-\u{110F9} + \u{11100}-\u{11134} + \u{11136}-\u{11147} + \u{11150}-\u{11176} + \u{11180}-\u{111DF} + \u{111E1}-\u{111F4} + \u{11200}-\u{11211} + \u{11213}-\u{1123E} + \u{11280}-\u{11286} + \u{11288} + \u{1128A}-\u{1128D} + \u{1128F}-\u{1129D} + \u{1129F}-\u{112A9} + \u{112B0}-\u{112EA} + \u{112F0}-\u{112F9} + \u{11300}-\u{11303} + \u{11305}-\u{1130C} + \u{1130F}-\u{11310} + \u{11313}-\u{11328} + \u{1132A}-\u{11330} + \u{11332}-\u{11333} + \u{11335}-\u{11339} + \u{1133B}-\u{11344} + \u{11347}-\u{11348} + \u{1134B}-\u{1134D} + \u{11350} + \u{11357} + \u{1135D}-\u{11363} + \u{11366}-\u{1136C} + \u{11370}-\u{11374} + \u{11400}-\u{1145B} + \u{1145D}-\u{11461} + \u{11480}-\u{114C7} + \u{114D0}-\u{114D9} + \u{11580}-\u{115B5} + \u{115B8}-\u{115DD} + \u{11600}-\u{11644} + \u{11650}-\u{11659} + \u{11660}-\u{1166C} + \u{11680}-\u{116B8} + \u{116C0}-\u{116C9} + \u{11700}-\u{1171A} + \u{1171D}-\u{1172B} + \u{11730}-\u{1173F} + \u{11800}-\u{1183B} + \u{118A0}-\u{118F2} + \u{118FF}-\u{11906} + \u{11909} + \u{1190C}-\u{11913} + \u{11915}-\u{11916} + \u{11918}-\u{11935} + \u{11937}-\u{11938} + \u{1193B}-\u{11946} + \u{11950}-\u{11959} + \u{119A0}-\u{119A7} + \u{119AA}-\u{119D7} + \u{119DA}-\u{119E4} + \u{11A00}-\u{11A47} + \u{11A50}-\u{11AA2} + \u{11AC0}-\u{11AF8} + \u{11C00}-\u{11C08} + \u{11C0A}-\u{11C36} + \u{11C38}-\u{11C45} + \u{11C50}-\u{11C6C} + \u{11C70}-\u{11C8F} + \u{11C92}-\u{11CA7} + \u{11CA9}-\u{11CB6} + \u{11D00}-\u{11D06} + \u{11D08}-\u{11D09} + \u{11D0B}-\u{11D36} + \u{11D3A} + \u{11D3C}-\u{11D3D} + \u{11D3F}-\u{11D47} + \u{11D50}-\u{11D59} + \u{11D60}-\u{11D65} + \u{11D67}-\u{11D68} + \u{11D6A}-\u{11D8E} + \u{11D90}-\u{11D91} + \u{11D93}-\u{11D98} + \u{11DA0}-\u{11DA9} + \u{11EE0}-\u{11EF8} + \u{11FB0} + \u{11FC0}-\u{11FF1} + \u{11FFF}-\u{12399} + \u{12400}-\u{1246E} + \u{12470}-\u{12474} + \u{12480}-\u{12543} + \u{13000}-\u{1342E} + \u{13430}-\u{13438} + \u{14400}-\u{14646} + \u{16800}-\u{16A38} + \u{16A40}-\u{16A5E} + \u{16A60}-\u{16A69} + \u{16A6E}-\u{16A6F} + \u{16AD0}-\u{16AED} + \u{16AF0}-\u{16AF5} + \u{16B00}-\u{16B45} + \u{16B50}-\u{16B59} + \u{16B5B}-\u{16B61} + \u{16B63}-\u{16B77} + \u{16B7D}-\u{16B8F} + \u{16E40}-\u{16E9A} + \u{16F00}-\u{16F4A} + \u{16F4F}-\u{16F87} + \u{16F8F}-\u{16F9F} + \u{1BC00}-\u{1BC6A} + \u{1BC70}-\u{1BC7C} + \u{1BC80}-\u{1BC88} + \u{1BC90}-\u{1BC99} + \u{1BC9C}-\u{1BCA3} + \u{1D000}-\u{1D0F5} + \u{1D100}-\u{1D126} + \u{1D129}-\u{1D1E8} + \u{1D200}-\u{1D245} + \u{1D2E0}-\u{1D2F3} + \u{1D300}-\u{1D356} + \u{1D360}-\u{1D378} + \u{1D400}-\u{1D454} + \u{1D456}-\u{1D49C} + \u{1D49E}-\u{1D49F} + \u{1D4A2} + \u{1D4A5}-\u{1D4A6} + \u{1D4A9}-\u{1D4AC} + \u{1D4AE}-\u{1D4B9} + \u{1D4BB} + \u{1D4BD}-\u{1D4C3} + \u{1D4C5}-\u{1D505} + \u{1D507}-\u{1D50A} + \u{1D50D}-\u{1D514} + \u{1D516}-\u{1D51C} + \u{1D51E}-\u{1D539} + \u{1D53B}-\u{1D53E} + \u{1D540}-\u{1D544} + \u{1D546} + \u{1D54A}-\u{1D550} + \u{1D552}-\u{1D6A5} + \u{1D6A8}-\u{1D7CB} + \u{1D7CE}-\u{1DA8B} + \u{1DA9B}-\u{1DA9F} + \u{1DAA1}-\u{1DAAF} + \u{1E000}-\u{1E006} + \u{1E008}-\u{1E018} + \u{1E01B}-\u{1E021} + \u{1E023}-\u{1E024} + \u{1E026}-\u{1E02A} + \u{1E100}-\u{1E12C} + \u{1E130}-\u{1E13D} + \u{1E140}-\u{1E149} + \u{1E14E}-\u{1E14F} + \u{1E2C0}-\u{1E2F9} + \u{1E2FF} + \u{1E800}-\u{1E8C4} + \u{1E8C7}-\u{1E8D6} + \u{1E900}-\u{1E94B} + \u{1E950}-\u{1E959} + \u{1E95E}-\u{1E95F} + \u{1EC71}-\u{1ECB4} + \u{1ED01}-\u{1ED3D} + \u{1EE00}-\u{1EE03} + \u{1EE05}-\u{1EE1F} + \u{1EE21}-\u{1EE22} + \u{1EE24} + \u{1EE27} + \u{1EE29}-\u{1EE32} + \u{1EE34}-\u{1EE37} + \u{1EE39} + \u{1EE3B} + \u{1EE42} + \u{1EE47} + \u{1EE49} + \u{1EE4B} + \u{1EE4D}-\u{1EE4F} + \u{1EE51}-\u{1EE52} + \u{1EE54} + \u{1EE57} + \u{1EE59} + \u{1EE5B} + \u{1EE5D} + \u{1EE5F} + \u{1EE61}-\u{1EE62} + \u{1EE64} + \u{1EE67}-\u{1EE6A} + \u{1EE6C}-\u{1EE72} + \u{1EE74}-\u{1EE77} + \u{1EE79}-\u{1EE7C} + \u{1EE7E} + \u{1EE80}-\u{1EE89} + \u{1EE8B}-\u{1EE9B} + \u{1EEA1}-\u{1EEA3} + \u{1EEA5}-\u{1EEA9} + \u{1EEAB}-\u{1EEBB} + \u{1EEF0}-\u{1EEF1} + \u{1F000}-\u{1F003} + \u{1F005}-\u{1F02B} + \u{1F030}-\u{1F093} + \u{1F0A0}-\u{1F0AE} + \u{1F0B1}-\u{1F0BF} + \u{1F0C1}-\u{1F0CE} + \u{1F0D1}-\u{1F0F5} + \u{1F10B}-\u{1F10F} + \u{1F12E}-\u{1F12F} + \u{1F16A}-\u{1F16F} + \u{1F1AD} + \u{1F1E6}-\u{1F1FF} + \u{1F321}-\u{1F32C} + \u{1F336} + \u{1F37D} + \u{1F394}-\u{1F39F} + \u{1F3CB}-\u{1F3CE} + \u{1F3D4}-\u{1F3DF} + \u{1F3F1}-\u{1F3F3} + \u{1F3F5}-\u{1F3F7} + \u{1F43F} + \u{1F441} + \u{1F4FD}-\u{1F4FE} + \u{1F53E}-\u{1F54A} + \u{1F54F} + \u{1F568}-\u{1F579} + \u{1F57B}-\u{1F594} + \u{1F597}-\u{1F5A3} + \u{1F5A5}-\u{1F5FA} + \u{1F650}-\u{1F67F} + \u{1F6C6}-\u{1F6CB} + \u{1F6CD}-\u{1F6CF} + \u{1F6D3}-\u{1F6D4} + \u{1F6E0}-\u{1F6EA} + \u{1F6F0}-\u{1F6F3} + \u{1F700}-\u{1F773} + \u{1F780}-\u{1F7D8} + \u{1F800}-\u{1F80B} + \u{1F810}-\u{1F847} + \u{1F850}-\u{1F859} + \u{1F860}-\u{1F887} + \u{1F890}-\u{1F8AD} + \u{1F8B0}-\u{1F8B1} + \u{1F900}-\u{1F90B} + \u{1F93B} + \u{1F946} + \u{1FA00}-\u{1FA53} + \u{1FA60}-\u{1FA6D} + \u{1FB00}-\u{1FB92} + \u{1FB94}-\u{1FBCA} + \u{1FBF0}-\u{1FBF9} + \u{E0001} + \u{E0020}-\u{E007F} + ).join }]/ end diff --git a/ruby/lib/reline/version.rb b/ruby/lib/reline/version.rb index 1bf544d74..3cc431839 100644 --- a/ruby/lib/reline/version.rb +++ b/ruby/lib/reline/version.rb @@ -1,3 +1,3 @@ module Reline - VERSION = '0.1.3' + VERSION = '0.3.0' end diff --git a/ruby/lib/reline/windows.rb b/ruby/lib/reline/windows.rb index c229c8536..f46ebd210 100644 --- a/ruby/lib/reline/windows.rb +++ b/ruby/lib/reline/windows.rb @@ -9,23 +9,48 @@ def self.win? true end - RAW_KEYSTROKE_CONFIG = { - [224, 72] => :ed_prev_history, # ↑ - [224, 80] => :ed_next_history, # ↓ - [224, 77] => :ed_next_char, # → - [224, 75] => :ed_prev_char, # ↠- [224, 83] => :key_delete, # Del - [224, 71] => :ed_move_to_beg, # Home - [224, 79] => :ed_move_to_end, # End - [ 0, 41] => :ed_unassigned, # input method on/off - [ 0, 72] => :ed_prev_history, # ↑ - [ 0, 80] => :ed_next_history, # ↓ - [ 0, 77] => :ed_next_char, # → - [ 0, 75] => :ed_prev_char, # ↠- [ 0, 83] => :key_delete, # Del - [ 0, 71] => :ed_move_to_beg, # Home - [ 0, 79] => :ed_move_to_end # End - } + def self.win_legacy_console? + @@legacy_console + end + + def self.set_default_key_bindings(config) + { + [224, 72] => :ed_prev_history, # ↑ + [224, 80] => :ed_next_history, # ↓ + [224, 77] => :ed_next_char, # → + [224, 75] => :ed_prev_char, # ↠+ [224, 83] => :key_delete, # Del + [224, 71] => :ed_move_to_beg, # Home + [224, 79] => :ed_move_to_end, # End + [ 0, 41] => :ed_unassigned, # input method on/off + [ 0, 72] => :ed_prev_history, # ↑ + [ 0, 80] => :ed_next_history, # ↓ + [ 0, 77] => :ed_next_char, # → + [ 0, 75] => :ed_prev_char, # ↠+ [ 0, 83] => :key_delete, # Del + [ 0, 71] => :ed_move_to_beg, # Home + [ 0, 79] => :ed_move_to_end # End + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + + { + [27, 32] => :em_set_mark, # M- + [24, 24] => :em_exchange_mark, # C-x C-x + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + end + + # Emulate ANSI key sequence. + { + [27, 91, 90] => :completion_journey_up, # S-Tab + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + end + end if defined? JRUBY_VERSION require 'win32api' @@ -69,13 +94,37 @@ def call(*args) end end + VK_RETURN = 0x0D VK_MENU = 0x12 VK_LMENU = 0xA4 VK_CONTROL = 0x11 VK_SHIFT = 0x10 + VK_DIVIDE = 0x6F + + KEY_EVENT = 0x01 + WINDOW_BUFFER_SIZE_EVENT = 0x04 + + CAPSLOCK_ON = 0x0080 + ENHANCED_KEY = 0x0100 + LEFT_ALT_PRESSED = 0x0002 + LEFT_CTRL_PRESSED = 0x0008 + NUMLOCK_ON = 0x0020 + RIGHT_ALT_PRESSED = 0x0001 + RIGHT_CTRL_PRESSED = 0x0004 + SCROLLLOCK_ON = 0x0040 + SHIFT_PRESSED = 0x0010 + + VK_TAB = 0x09 + VK_END = 0x23 + VK_HOME = 0x24 + VK_LEFT = 0x25 + VK_UP = 0x26 + VK_RIGHT = 0x27 + VK_DOWN = 0x28 + VK_DELETE = 0x2E + STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE = -11 - WINDOW_BUFFER_SIZE_EVENT = 0x04 FILE_TYPE_PIPE = 0x0003 FILE_NAME_INFO = 2 @@getwch = Win32API.new('msvcrt', '_getwch', [], 'I') @@ -89,14 +138,39 @@ def call(*args) @@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE) @@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE) @@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L') - @@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L') + @@ReadConsoleInputW = Win32API.new('kernel32', 'ReadConsoleInputW', ['L', 'P', 'L', 'P'], 'L') @@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L') @@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I') + @@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L') + @@SetConsoleCursorInfo = Win32API.new('kernel32', 'SetConsoleCursorInfo', ['L', 'P'], 'L') + + @@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L') + @@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L') + @@WaitForSingleObject = Win32API.new('kernel32', 'WaitForSingleObject', ['L', 'L'], 'L') + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4 + + private_class_method def self.getconsolemode + mode = "\000\000\000\000" + @@GetConsoleMode.call(@@hConsoleHandle, mode) + mode.unpack1('L') + end + + private_class_method def self.setconsolemode(mode) + @@SetConsoleMode.call(@@hConsoleHandle, mode) + end + + @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0) + #if @@legacy_console + # setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING) + # @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0) + #end @@input_buf = [] @@output_buf = [] - def self.msys_tty?(io=@@hConsoleInputHandle) + @@output = STDOUT + + def self.msys_tty?(io = @@hConsoleInputHandle) # check if fd is a pipe if @@GetFileType.call(io) != FILE_TYPE_PIPE return false @@ -112,7 +186,7 @@ def self.msys_tty?(io=@@hConsoleInputHandle) # DWORD FileNameLength; # WCHAR FileName[1]; # } FILE_NAME_INFO - len = p_buffer[0, 4].unpack("L")[0] + len = p_buffer[0, 4].unpack1("L") name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace) # Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX') @@ -120,95 +194,157 @@ def self.msys_tty?(io=@@hConsoleInputHandle) name =~ /(msys-|cygwin-).*-pty/ ? true : false end - def self.getwch - unless @@input_buf.empty? - return @@input_buf.shift - end - while @@kbhit.call == 0 - sleep(0.001) + KEY_MAP = [ + # It's treated as Meta+Enter on Windows. + [ { control_keys: :CTRL, virtual_key_code: 0x0D }, "\e\r".bytes ], + [ { control_keys: :SHIFT, virtual_key_code: 0x0D }, "\e\r".bytes ], + + # It's treated as Meta+Space on Windows. + [ { control_keys: :CTRL, char_code: 0x20 }, "\e ".bytes ], + + # Emulate getwch() key sequences. + [ { control_keys: [], virtual_key_code: VK_UP }, [0, 72] ], + [ { control_keys: [], virtual_key_code: VK_DOWN }, [0, 80] ], + [ { control_keys: [], virtual_key_code: VK_RIGHT }, [0, 77] ], + [ { control_keys: [], virtual_key_code: VK_LEFT }, [0, 75] ], + [ { control_keys: [], virtual_key_code: VK_DELETE }, [0, 83] ], + [ { control_keys: [], virtual_key_code: VK_HOME }, [0, 71] ], + [ { control_keys: [], virtual_key_code: VK_END }, [0, 79] ], + + # Emulate ANSI key sequence. + [ { control_keys: :SHIFT, virtual_key_code: VK_TAB }, [27, 91, 90] ], + ] + + @@hsg = nil + + def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state) + + # high-surrogate + if 0xD800 <= char_code and char_code <= 0xDBFF + @@hsg = char_code + return end - until @@kbhit.call == 0 - ret = @@getwch.call - if ret == 0 or ret == 0xE0 - @@input_buf << ret - ret = @@getwch.call - @@input_buf << ret - return @@input_buf.shift - end - begin - bytes = ret.chr(Encoding::UTF_8).bytes - @@input_buf.push(*bytes) - rescue Encoding::UndefinedConversionError - @@input_buf << ret - @@input_buf << @@getwch.call if ret == 224 + # low-surrogate + if 0xDC00 <= char_code and char_code <= 0xDFFF + if @@hsg + char_code = 0x10000 + (@@hsg - 0xD800) * 0x400 + char_code - 0xDC00 + @@hsg = nil + else + # no high-surrogate. ignored. + return end + else + # ignore high-surrogate without low-surrogate if there + @@hsg = nil end - @@input_buf.shift + + key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state) + + match = KEY_MAP.find { |args,| key.matches?(**args) } + unless match.nil? + @@output_buf.concat(match.last) + return + end + + # no char, only control keys + return if key.char_code == 0 and key.control_keys.any? + + @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) + + @@output_buf.concat(key.char.bytes) end - def self.getc + def self.check_input_event num_of_events = 0.chr * 8 - while @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) != 0 and num_of_events.unpack('L').first > 0 - input_record = 0.chr * 18 + while @@output_buf.empty? + Reline.core.line_editor.resize + if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec + # prevent for background consolemode change + @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0) + next + end + next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0 + input_records = 0.chr * 20 * 80 read_event = 0.chr * 4 - if @@ReadConsoleInput.(@@hConsoleInputHandle, input_record, 1, read_event) != 0 - event = input_record[0, 2].unpack('s*').first - if event == WINDOW_BUFFER_SIZE_EVENT - @@winch_handler.() + if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_records, 80, read_event) != 0 + read_events = read_event.unpack1('L') + 0.upto(read_events) do |idx| + input_record = input_records[idx * 20, 20] + event = input_record[0, 2].unpack1('s*') + case event + when WINDOW_BUFFER_SIZE_EVENT + @@winch_handler.() + when KEY_EVENT + key_down = input_record[4, 4].unpack1('l*') + repeat_count = input_record[8, 2].unpack1('s*') + virtual_key_code = input_record[10, 2].unpack1('s*') + virtual_scan_code = input_record[12, 2].unpack1('s*') + char_code = input_record[14, 2].unpack1('S*') + control_key_state = input_record[16, 2].unpack1('S*') + is_key_down = key_down.zero? ? false : true + if is_key_down + process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state) + end + end end end end - unless @@output_buf.empty? - return @@output_buf.shift - end - input = getwch - meta = (@@GetKeyState.call(VK_LMENU) & 0x80) != 0 - control = (@@GetKeyState.call(VK_CONTROL) & 0x80) != 0 - shift = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0 - force_enter = !input.instance_of?(Array) && (control or shift) && input == 0x0D - if force_enter - # It's treated as Meta+Enter on Windows - @@output_buf.push("\e".ord) - @@output_buf.push(input) - else - case input - when 0x00 - meta = false - @@output_buf.push(input) - input = getwch - @@output_buf.push(*input) - when 0xE0 - @@output_buf.push(input) - input = getwch - @@output_buf.push(*input) - when 0x03 - @@output_buf.push(input) - else - @@output_buf.push(input) - end - end - if meta - "\e".ord - else - @@output_buf.shift - end + end + + def self.getc + check_input_event + @@output_buf.shift end def self.ungetc(c) @@output_buf.unshift(c) end - def self.get_screen_size + def self.in_pasting? + not self.empty_buffer? + end + + def self.empty_buffer? + if not @@output_buf.empty? + false + elsif @@kbhit.call == 0 + true + else + false + end + end + + def self.get_console_screen_buffer_info + # CONSOLE_SCREEN_BUFFER_INFO + # [ 0,2] dwSize.X + # [ 2,2] dwSize.Y + # [ 4,2] dwCursorPositions.X + # [ 6,2] dwCursorPositions.Y + # [ 8,2] wAttributes + # [10,2] srWindow.Left + # [12,2] srWindow.Top + # [14,2] srWindow.Right + # [16,2] srWindow.Bottom + # [18,2] dwMaximumWindowSize.X + # [20,2] dwMaximumWindowSize.Y csbi = 0.chr * 22 - @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) + return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0 + csbi + end + + def self.get_screen_size + unless csbi = get_console_screen_buffer_info + return [1, 1] + end csbi[0, 4].unpack('SS').reverse end def self.cursor_pos - csbi = 0.chr * 22 - @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) - x = csbi[4, 2].unpack('s*').first - y = csbi[6, 2].unpack('s*').first + unless csbi = get_console_screen_buffer_info + return Reline::CursorPos.new(0, 0) + end + x = csbi[4, 2].unpack1('s') + y = csbi[6, 2].unpack1('s') Reline::CursorPos.new(x, y) end @@ -218,7 +354,9 @@ def self.move_cursor_column(val) def self.move_cursor_up(val) if val > 0 - @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x) + y = cursor_pos.y - val + y = 0 if y < 0 + @@SetConsoleCursorPosition.call(@@hConsoleHandle, y * 65536 + cursor_pos.x) elsif val < 0 move_cursor_down(-val) end @@ -226,6 +364,10 @@ def self.move_cursor_up(val) def self.move_cursor_down(val) if val > 0 + return unless csbi = get_console_screen_buffer_info + screen_height = get_screen_size.first + y = cursor_pos.y + val + y = screen_height - 1 if y > (screen_height - 1) @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x) elsif val < 0 move_cursor_up(-val) @@ -233,31 +375,74 @@ def self.move_cursor_down(val) end def self.erase_after_cursor - csbi = 0.chr * 24 - @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) - cursor = csbi[4, 4].unpack('L').first + return unless csbi = get_console_screen_buffer_info + attributes = csbi[8, 2].unpack1('S') + cursor = csbi[4, 4].unpack1('L') written = 0.chr * 4 @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written) + @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, get_screen_size.last - cursor_pos.x, cursor, written) end def self.scroll_down(val) - return if val.zero? - scroll_rectangle = [0, val, get_screen_size.last, get_screen_size.first].pack('s4') - destination_origin = 0 # y * 65536 + x - fill = [' '.ord, 0].pack('SS') - @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill) + return if val < 0 + return unless csbi = get_console_screen_buffer_info + buffer_width, x, y, buffer_lines, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s') + screen_height = window_bottom - window_top + 1 + val = screen_height if val > screen_height + + if @@legacy_console || window_left != 0 + # unless ENABLE_VIRTUAL_TERMINAL, + # if srWindow.Left != 0 then it's conhost.exe hosted console + # and puts "\n" causes horizontal scroll. its glitch. + # FYI irb write from culumn 1, so this gives no gain. + scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4') + destination_origin = 0 # y * 65536 + x + fill = [' '.ord, attributes].pack('SS') + @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill) + else + origin_x = x + 1 + origin_y = y - window_top + 1 + @@output.write [ + (origin_y != screen_height) ? "\e[#{screen_height};H" : nil, + "\n" * val, + (origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil + ].join + end end def self.clear_screen - # TODO: Use FillConsoleOutputCharacter and FillConsoleOutputAttribute - write "\e[2J" - write "\e[1;1H" + if @@legacy_console + return unless csbi = get_console_screen_buffer_info + buffer_width, _buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s') + fill_length = buffer_width * (window_bottom - window_top + 1) + screen_topleft = window_top * 65536 + written = 0.chr * 4 + @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, fill_length, screen_topleft, written) + @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, fill_length, screen_topleft, written) + @@SetConsoleCursorPosition.call(@@hConsoleHandle, screen_topleft) + else + @@output.write "\e[2J" "\e[H" + end end def self.set_screen_size(rows, columns) raise NotImplementedError end + def self.hide_cursor + size = 100 + visible = 0 # 0 means false + cursor_info = [size, visible].pack('Li') + @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info) + end + + def self.show_cursor + size = 100 + visible = 1 # 1 means true + cursor_info = [size, visible].pack('Li') + @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info) + end + def self.set_winch_handler(&handler) @@winch_handler = handler end @@ -270,4 +455,43 @@ def self.prep def self.deprep(otio) # do nothing end + + class KeyEventRecord + + attr_reader :virtual_key_code, :char_code, :control_key_state, :control_keys + + def initialize(virtual_key_code, char_code, control_key_state) + @virtual_key_code = virtual_key_code + @char_code = char_code + @control_key_state = control_key_state + @enhanced = control_key_state & ENHANCED_KEY != 0 + + (@control_keys = []).tap do |control_keys| + # symbols must be sorted to make comparison is easier later on + control_keys << :ALT if control_key_state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) != 0 + control_keys << :CTRL if control_key_state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) != 0 + control_keys << :SHIFT if control_key_state & SHIFT_PRESSED != 0 + end.freeze + end + + def char + @char_code.chr(Encoding::UTF_8) + end + + def enhanced? + @enhanced + end + + # Verifies if the arguments match with this key event. + # Nil arguments are ignored, but at least one must be passed as non-nil. + # To verify that no control keys were pressed, pass an empty array: `control_keys: []`. + def matches?(control_keys: nil, virtual_key_code: nil, char_code: nil) + raise ArgumentError, 'No argument was passed to match key event' if control_keys.nil? && virtual_key_code.nil? && char_code.nil? + + (control_keys.nil? || [*control_keys].sort == @control_keys) && + (virtual_key_code.nil? || @virtual_key_code == virtual_key_code) && + (char_code.nil? || char_code == @char_code) + end + + end end diff --git a/ruby/lib/resolv-replace.gemspec b/ruby/lib/resolv-replace.gemspec new file mode 100644 index 000000000..6bc07dbe1 --- /dev/null +++ b/ruby/lib/resolv-replace.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "resolv-replace" + spec.version = "0.1.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Replace Socket DNS with Resolv.} + spec.description = %q{Replace Socket DNS with Resolv.} + spec.homepage = "https://github.com/ruby/resolv-replace" + 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 + + 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.require_paths = ["lib"] + + spec.add_dependency "resolv" +end diff --git a/ruby/lib/resolv.gemspec b/ruby/lib/resolv.gemspec new file mode 100644 index 000000000..c6a0609b5 --- /dev/null +++ b/ruby/lib/resolv.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "resolv" + spec.version = "0.2.1" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Thread-aware DNS resolver library in Ruby.} + spec.description = %q{Thread-aware DNS resolver library in Ruby.} + spec.homepage = "https://github.com/ruby/resolv" + 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 + + 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.require_paths = ["lib"] +end diff --git a/ruby/lib/resolv.rb b/ruby/lib/resolv.rb index e7b45e785..b69c7045c 100644 --- a/ruby/lib/resolv.rb +++ b/ruby/lib/resolv.rb @@ -696,13 +696,13 @@ def request(sender, tout) rescue DecodeError next # broken DNS message ignored end - if s = sender_for(from, msg) + if sender == sender_for(from, msg) break else # unexpected DNS message ignored end end - return msg, s.data + return msg, sender.data end def sender_for(addr, msg) @@ -767,6 +767,7 @@ def recv_reply(readable_socks) end def sender(msg, data, host, port=Port) + host = Addrinfo.ip(host).ip_address lazy_initialize sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"] return nil if !sock @@ -2458,6 +2459,28 @@ class IPv6 (\d+)\.(\d+)\.(\d+)\.(\d+) \z/x + ## + # IPv6 link local address format fe80:b:c:d:e:f:g:h%em1 + Regex_8HexLinkLocal = /\A + [Ff][Ee]80 + (?::[0-9A-Fa-f]{1,4}){7} + %[0-9A-Za-z]+ + \z/x + + ## + # Compressed IPv6 link local address format fe80::b%em1 + + Regex_CompressedHexLinkLocal = /\A + [Ff][Ee]80: + (?: + ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) :: + ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) + | + :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) + )? + :[0-9A-Fa-f]{1,4}%[0-9A-Za-z.]+ + \z/x + ## # A composite IPv6 address Regexp. @@ -2465,7 +2488,10 @@ class IPv6 (?:#{Regex_8Hex}) | (?:#{Regex_CompressedHex}) | (?:#{Regex_6Hex4Dec}) | - (?:#{Regex_CompressedHex4Dec})/x + (?:#{Regex_CompressedHex4Dec}) | + (?:#{Regex_8HexLinkLocal}) | + (?:#{Regex_CompressedHexLinkLocal}) + /x ## # Creates a new IPv6 address from +arg+ which may be: diff --git a/ruby/lib/rexml/attlistdecl.rb b/ruby/lib/rexml/attlistdecl.rb deleted file mode 100644 index 44a91d66d..000000000 --- a/ruby/lib/rexml/attlistdecl.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: false -#vim:ts=2 sw=2 noexpandtab: -require_relative 'child' -require_relative 'source' - -module REXML - # This class needs: - # * Documentation - # * Work! Not all types of attlists are intelligently parsed, so we just - # spew back out what we get in. This works, but it would be better if - # we formatted the output ourselves. - # - # AttlistDecls provide *just* enough support to allow namespace - # declarations. If you need some sort of generalized support, or have an - # interesting idea about how to map the hideous, terrible design of DTD - # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate - # for anything to make DTDs more palateable. - class AttlistDecl < Child - include Enumerable - - # What is this? Got me. - attr_reader :element_name - - # Create an AttlistDecl, pulling the information from a Source. Notice - # that this isn't very convenient; to create an AttlistDecl, you basically - # have to format it yourself, and then have the initializer parse it. - # Sorry, but for the foreseeable future, DTD support in REXML is pretty - # weak on convenience. Have I mentioned how much I hate DTDs? - def initialize(source) - super() - if (source.kind_of? Array) - @element_name, @pairs, @contents = *source - end - end - - # Access the attlist attribute/value pairs. - # value = attlist_decl[ attribute_name ] - def [](key) - @pairs[key] - end - - # Whether an attlist declaration includes the given attribute definition - # if attlist_decl.include? "xmlns:foobar" - def include?(key) - @pairs.keys.include? key - end - - # Iterate over the key/value pairs: - # attlist_decl.each { |attribute_name, attribute_value| ... } - def each(&block) - @pairs.each(&block) - end - - # Write out exactly what we got in. - def write out, indent=-1 - out << @contents - end - - def node_type - :attlistdecl - end - end -end diff --git a/ruby/lib/rexml/attribute.rb b/ruby/lib/rexml/attribute.rb deleted file mode 100644 index 8933a013a..000000000 --- a/ruby/lib/rexml/attribute.rb +++ /dev/null @@ -1,205 +0,0 @@ -# frozen_string_literal: false -require_relative "namespace" -require_relative 'text' - -module REXML - # Defines an Element Attribute; IE, a attribute=value pair, as in: - # . Attributes can be in their own - # namespaces. General users of REXML will not interact with the - # Attribute class much. - class Attribute - include Node - include Namespace - - # The element to which this attribute belongs - attr_reader :element - # The normalized value of this attribute. That is, the attribute with - # entities intact. - attr_writer :normalized - PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um - - NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um - - # Constructor. - # FIXME: The parser doesn't catch illegal characters in attributes - # - # first:: - # Either: an Attribute, which this new attribute will become a - # clone of; or a String, which is the name of this attribute - # second:: - # If +first+ is an Attribute, then this may be an Element, or nil. - # If nil, then the Element parent of this attribute is the parent - # of the +first+ Attribute. If the first argument is a String, - # then this must also be a String, and is the content of the attribute. - # If this is the content, it must be fully normalized (contain no - # illegal characters). - # parent:: - # Ignored unless +first+ is a String; otherwise, may be the Element - # parent of this attribute, or nil. - # - # - # Attribute.new( attribute_to_clone ) - # Attribute.new( attribute_to_clone, parent_element ) - # Attribute.new( "attr", "attr_value" ) - # Attribute.new( "attr", "attr_value", parent_element ) - def initialize( first, second=nil, parent=nil ) - @normalized = @unnormalized = @element = nil - if first.kind_of? Attribute - self.name = first.expanded_name - @unnormalized = first.value - if second.kind_of? Element - @element = second - else - @element = first.element - end - elsif first.kind_of? String - @element = parent - self.name = first - @normalized = second.to_s - else - raise "illegal argument #{first.class.name} to Attribute constructor" - end - end - - # Returns the namespace of the attribute. - # - # e = Element.new( "elns:myelement" ) - # e.add_attribute( "nsa:a", "aval" ) - # e.add_attribute( "b", "bval" ) - # e.attributes.get_attribute( "a" ).prefix # -> "nsa" - # e.attributes.get_attribute( "b" ).prefix # -> "" - # a = Attribute.new( "x", "y" ) - # a.prefix # -> "" - def prefix - super - end - - # Returns the namespace URL, if defined, or nil otherwise - # - # e = Element.new("el") - # e.add_namespace("ns", "http://url") - # e.add_attribute("ns:a", "b") - # e.add_attribute("nsx:a", "c") - # e.attribute("ns:a").namespace # => "http://url" - # e.attribute("nsx:a").namespace # => nil - # - # This method always returns "" for no namespace attribute. Because - # the default namespace doesn't apply to attribute names. - # - # From https://www.w3.org/TR/xml-names/#uniqAttrs - # - # > the default namespace does not apply to attribute names - # - # e = REXML::Element.new("el") - # e.add_namespace("", "http://example.com/") - # e.namespace # => "http://example.com/" - # e.add_attribute("a", "b") - # e.attribute("a").namespace # => "" - def namespace arg=nil - arg = prefix if arg.nil? - if arg == "" - "" - else - @element.namespace(arg) - end - end - - # Returns true if other is an Attribute and has the same name and value, - # false otherwise. - def ==( other ) - other.kind_of?(Attribute) and other.name==name and other.value==value - end - - # Creates (and returns) a hash from both the name and value - def hash - name.hash + value.hash - end - - # Returns this attribute out as XML source, expanding the name - # - # a = Attribute.new( "x", "y" ) - # a.to_string # -> "x='y'" - # b = Attribute.new( "ns:x", "y" ) - # b.to_string # -> "ns:x='y'" - def to_string - if @element and @element.context and @element.context[:attribute_quote] == :quote - %Q^#@expanded_name="#{to_s().gsub(/"/, '"')}"^ - else - "#@expanded_name='#{to_s().gsub(/'/, ''')}'" - end - end - - def doctype - if @element - doc = @element.document - doc.doctype if doc - end - end - - # Returns the attribute value, with entities replaced - def to_s - return @normalized if @normalized - - @normalized = Text::normalize( @unnormalized, doctype ) - @unnormalized = nil - @normalized - end - - # Returns the UNNORMALIZED value of this attribute. That is, entities - # have been expanded to their values - def value - return @unnormalized if @unnormalized - @unnormalized = Text::unnormalize( @normalized, doctype ) - @normalized = nil - @unnormalized - end - - # Returns a copy of this attribute - def clone - Attribute.new self - end - - # Sets the element of which this object is an attribute. Normally, this - # is not directly called. - # - # Returns this attribute - def element=( element ) - @element = element - - if @normalized - Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype ) - end - - self - end - - # Removes this Attribute from the tree, and returns true if successful - # - # This method is usually not called directly. - def remove - @element.attributes.delete self.name unless @element.nil? - end - - # Writes this attribute (EG, puts 'key="value"' to the output) - def write( output, indent=-1 ) - output << to_string - end - - def node_type - :attribute - end - - def inspect - rv = "" - write( rv ) - rv - end - - def xpath - path = @element.xpath - path += "/@#{self.expanded_name}" - return path - end - end -end -#vim:ts=2 sw=2 noexpandtab: diff --git a/ruby/lib/rexml/cdata.rb b/ruby/lib/rexml/cdata.rb deleted file mode 100644 index 997f5a08d..000000000 --- a/ruby/lib/rexml/cdata.rb +++ /dev/null @@ -1,68 +0,0 @@ -# frozen_string_literal: false -require_relative "text" - -module REXML - class CData < Text - START = '' - ILLEGAL = /(\]\]>)/ - - # Constructor. CData is data between - # - # _Examples_ - # CData.new( source ) - # CData.new( "Here is some CDATA" ) - # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element ) - def initialize( first, whitespace=true, parent=nil ) - super( first, whitespace, parent, false, true, ILLEGAL ) - end - - # Make a copy of this object - # - # _Examples_ - # c = CData.new( "Some text" ) - # d = c.clone - # d.to_s # -> "Some text" - def clone - CData.new self - end - - # Returns the content of this CData object - # - # _Examples_ - # c = CData.new( "Some text" ) - # c.to_s # -> "Some text" - def to_s - @string - end - - def value - @string - end - - # == DEPRECATED - # See the rexml/formatters package - # - # Generates XML output of this object - # - # output:: - # Where to write the string. Defaults to $stdout - # indent:: - # The amount to indent this node by - # transitive:: - # Ignored - # ie_hack:: - # Ignored - # - # _Examples_ - # c = CData.new( " Some text " ) - # c.write( $stdout ) #-> - def write( output=$stdout, indent=-1, transitive=false, ie_hack=false ) - Kernel.warn( "#{self.class.name}.write is deprecated", uplevel: 1) - indent( output, indent ) - output << START - output << @string - output << STOP - end - end -end diff --git a/ruby/lib/rexml/child.rb b/ruby/lib/rexml/child.rb deleted file mode 100644 index cc6e9a471..000000000 --- a/ruby/lib/rexml/child.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: false -require_relative "node" - -module REXML - ## - # A Child object is something contained by a parent, and this class - # contains methods to support that. Most user code will not use this - # class directly. - class Child - include Node - attr_reader :parent # The Parent of this object - - # Constructor. Any inheritors of this class should call super to make - # sure this method is called. - # parent:: - # if supplied, the parent of this child will be set to the - # supplied value, and self will be added to the parent - def initialize( parent = nil ) - @parent = nil - # Declare @parent, but don't define it. The next line sets the - # parent. - parent.add( self ) if parent - end - - # Replaces this object with another object. Basically, calls - # Parent.replace_child - # - # Returns:: self - def replace_with( child ) - @parent.replace_child( self, child ) - self - end - - # Removes this child from the parent. - # - # Returns:: self - def remove - unless @parent.nil? - @parent.delete self - end - self - end - - # Sets the parent of this child to the supplied argument. - # - # other:: - # Must be a Parent object. If this object is the same object as the - # existing parent of this child, no action is taken. Otherwise, this - # child is removed from the current parent (if one exists), and is added - # to the new parent. - # Returns:: The parent added - def parent=( other ) - return @parent if @parent == other - @parent.delete self if defined? @parent and @parent - @parent = other - end - - alias :next_sibling :next_sibling_node - alias :previous_sibling :previous_sibling_node - - # Sets the next sibling of this child. This can be used to insert a child - # after some other child. - # a = Element.new("a") - # b = a.add_element("b") - # c = Element.new("c") - # b.next_sibling = c - # # => - def next_sibling=( other ) - parent.insert_after self, other - end - - # Sets the previous sibling of this child. This can be used to insert a - # child before some other child. - # a = Element.new("a") - # b = a.add_element("b") - # c = Element.new("c") - # b.previous_sibling = c - # # => - def previous_sibling=(other) - parent.insert_before self, other - end - - # Returns:: the document this child belongs to, or nil if this child - # belongs to no document - def document - return parent.document unless parent.nil? - nil - end - - # This doesn't yet handle encodings - def bytes - document.encoding - - to_s - end - end -end diff --git a/ruby/lib/rexml/comment.rb b/ruby/lib/rexml/comment.rb deleted file mode 100644 index 52c58b46f..000000000 --- a/ruby/lib/rexml/comment.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: false -require_relative "child" - -module REXML - ## - # Represents an XML comment; that is, text between \ - class Comment < Child - include Comparable - START = "" - - # The content text - - attr_accessor :string - - ## - # Constructor. The first argument can be one of three types: - # @param first If String, the contents of this comment are set to the - # argument. If Comment, the argument is duplicated. If - # Source, the argument is scanned for a comment. - # @param second If the first argument is a Source, this argument - # should be nil, not supplied, or a Parent to be set as the parent - # of this object - def initialize( first, second = nil ) - super(second) - if first.kind_of? String - @string = first - elsif first.kind_of? Comment - @string = first.string - end - end - - def clone - Comment.new self - end - - # == DEPRECATED - # See REXML::Formatters - # - # output:: - # Where to write the string - # indent:: - # An integer. If -1, no indenting will be used; otherwise, the - # indentation will be this number of spaces, and children will be - # indented an additional amount. - # transitive:: - # Ignored by this class. The contents of comments are never modified. - # ie_hack:: - # Needed for conformity to the child API, but not used by this class. - def write( output, indent=-1, transitive=false, ie_hack=false ) - Kernel.warn("Comment.write is deprecated. See REXML::Formatters", uplevel: 1) - indent( output, indent ) - output << START - output << @string - output << STOP - end - - alias :to_s :string - - ## - # Compares this Comment to another; the contents of the comment are used - # in the comparison. - def <=>(other) - other.to_s <=> @string - end - - ## - # Compares this Comment to another; the contents of the comment are used - # in the comparison. - def ==( other ) - other.kind_of? Comment and - (other <=> self) == 0 - end - - def node_type - :comment - end - end -end -#vim:ts=2 sw=2 noexpandtab: diff --git a/ruby/lib/rexml/doctype.rb b/ruby/lib/rexml/doctype.rb deleted file mode 100644 index 757b63963..000000000 --- a/ruby/lib/rexml/doctype.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: false -require_relative "parent" -require_relative "parseexception" -require_relative "namespace" -require_relative 'entity' -require_relative 'attlistdecl' -require_relative 'xmltokens' - -module REXML - # Represents an XML DOCTYPE declaration; that is, the contents of . DOCTYPES can be used to declare the DTD of a document, as well as - # being used to declare entities used in the document. - class DocType < Parent - include XMLTokens - START = "" - SYSTEM = "SYSTEM" - PUBLIC = "PUBLIC" - DEFAULT_ENTITIES = { - 'gt'=>EntityConst::GT, - 'lt'=>EntityConst::LT, - 'quot'=>EntityConst::QUOT, - "apos"=>EntityConst::APOS - } - - # name is the name of the doctype - # external_id is the referenced DTD, if given - attr_reader :name, :external_id, :entities, :namespaces - - # Constructor - # - # dt = DocType.new( 'foo', '-//I/Hate/External/IDs' ) - # # - # dt = DocType.new( doctype_to_clone ) - # # Incomplete. Shallow clone of doctype - # - # +Note+ that the constructor: - # - # Doctype.new( Source.new( "" ) ) - # - # is _deprecated_. Do not use it. It will probably disappear. - def initialize( first, parent=nil ) - @entities = DEFAULT_ENTITIES - @long_name = @uri = nil - if first.kind_of? String - super() - @name = first - @external_id = parent - elsif first.kind_of? DocType - super( parent ) - @name = first.name - @external_id = first.external_id - elsif first.kind_of? Array - super( parent ) - @name = first[0] - @external_id = first[1] - @long_name = first[2] - @uri = first[3] - elsif first.kind_of? Source - super( parent ) - parser = Parsers::BaseParser.new( first ) - event = parser.pull - if event[0] == :start_doctype - @name, @external_id, @long_name, @uri, = event[1..-1] - end - else - super() - end - end - - def node_type - :doctype - end - - def attributes_of element - rv = [] - each do |child| - child.each do |key,val| - rv << Attribute.new(key,val) - end if child.kind_of? AttlistDecl and child.element_name == element - end - rv - end - - def attribute_of element, attribute - att_decl = find do |child| - child.kind_of? AttlistDecl and - child.element_name == element and - child.include? attribute - end - return nil unless att_decl - att_decl[attribute] - end - - def clone - DocType.new self - end - - # output:: - # Where to write the string - # indent:: - # An integer. If -1, no indentation will be used; otherwise, the - # indentation will be this number of spaces, and children will be - # indented an additional amount. - # transitive:: - # Ignored - # ie_hack:: - # Ignored - def write( output, indent=0, transitive=false, ie_hack=false ) - f = REXML::Formatters::Default.new - c = context - if c and c[:prologue_quote] == :apostrophe - quote = "'" - else - quote = "\"" - end - indent( output, indent ) - output << START - output << ' ' - output << @name - output << " #{@external_id}" if @external_id - output << " #{quote}#{@long_name}#{quote}" if @long_name - output << " #{quote}#{@uri}#{quote}" if @uri - unless @children.empty? - output << ' [' - @children.each { |child| - output << "\n" - f.write( child, output ) - } - output << "\n]" - end - output << STOP - end - - def context - if @parent - @parent.context - else - nil - end - end - - def entity( name ) - @entities[name].unnormalized if @entities[name] - end - - def add child - super(child) - @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES - @entities[ child.name ] = child if child.kind_of? Entity - end - - # This method retrieves the public identifier identifying the document's - # DTD. - # - # Method contributed by Henrik Martensson - def public - case @external_id - when "SYSTEM" - nil - when "PUBLIC" - strip_quotes(@long_name) - end - end - - # This method retrieves the system identifier identifying the document's DTD - # - # Method contributed by Henrik Martensson - def system - case @external_id - when "SYSTEM" - strip_quotes(@long_name) - when "PUBLIC" - @uri.kind_of?(String) ? strip_quotes(@uri) : nil - end - end - - # This method returns a list of notations that have been declared in the - # _internal_ DTD subset. Notations in the external DTD subset are not - # listed. - # - # Method contributed by Henrik Martensson - def notations - children().select {|node| node.kind_of?(REXML::NotationDecl)} - end - - # Retrieves a named notation. Only notations declared in the internal - # DTD subset can be retrieved. - # - # Method contributed by Henrik Martensson - def notation(name) - notations.find { |notation_decl| - notation_decl.name == name - } - end - - private - - # Method contributed by Henrik Martensson - def strip_quotes(quoted_string) - quoted_string =~ /^[\'\"].*[\'\"]$/ ? - quoted_string[1, quoted_string.length-2] : - quoted_string - end - end - - # We don't really handle any of these since we're not a validating - # parser, so we can be pretty dumb about them. All we need to be able - # to do is spew them back out on a write() - - # This is an abstract class. You never use this directly; it serves as a - # parent class for the specific declarations. - class Declaration < Child - def initialize src - super() - @string = src - end - - def to_s - @string+'>' - end - - # == DEPRECATED - # See REXML::Formatters - # - def write( output, indent ) - output << to_s - end - end - - public - class ElementDecl < Declaration - def initialize( src ) - super - end - end - - class ExternalEntity < Child - def initialize( src ) - super() - @entity = src - end - def to_s - @entity - end - def write( output, indent ) - output << @entity - end - end - - class NotationDecl < Child - attr_accessor :public, :system - def initialize name, middle, pub, sys - super(nil) - @name = name - @middle = middle - @public = pub - @system = sys - end - - def to_s - c = nil - c = parent.context if parent - if c and c[:prologue_quote] == :apostrophe - quote = "'" - else - quote = "\"" - end - notation = "" - notation - end - - def write( output, indent=-1 ) - output << to_s - end - - # This method retrieves the name of the notation. - # - # Method contributed by Henrik Martensson - def name - @name - end - end -end diff --git a/ruby/lib/rexml/document.rb b/ruby/lib/rexml/document.rb deleted file mode 100644 index adec29306..000000000 --- a/ruby/lib/rexml/document.rb +++ /dev/null @@ -1,291 +0,0 @@ -# frozen_string_literal: false -require_relative "security" -require_relative "element" -require_relative "xmldecl" -require_relative "source" -require_relative "comment" -require_relative "doctype" -require_relative "instruction" -require_relative "rexml" -require_relative "parseexception" -require_relative "output" -require_relative "parsers/baseparser" -require_relative "parsers/streamparser" -require_relative "parsers/treeparser" - -module REXML - # Represents a full XML document, including PIs, a doctype, etc. A - # Document has a single child that can be accessed by root(). - # Note that if you want to have an XML declaration written for a document - # you create, you must add one; REXML documents do not write a default - # declaration for you. See |DECLARATION| and |write|. - class Document < Element - # A convenient default XML declaration. If you want an XML declaration, - # the easiest way to add one is mydoc << Document::DECLARATION - # +DEPRECATED+ - # Use: mydoc << XMLDecl.default - DECLARATION = XMLDecl.default - - # Constructor - # @param source if supplied, must be a Document, String, or IO. - # Documents have their context and Element attributes cloned. - # Strings are expected to be valid XML documents. IOs are expected - # to be sources of valid XML documents. - # @param context if supplied, contains the context of the document; - # this should be a Hash. - def initialize( source = nil, context = {} ) - @entity_expansion_count = 0 - super() - @context = context - return if source.nil? - if source.kind_of? Document - @context = source.context - super source - else - build( source ) - end - end - - def node_type - :document - end - - # Should be obvious - def clone - Document.new self - end - - # According to the XML spec, a root node has no expanded name - def expanded_name - '' - #d = doc_type - #d ? d.name : "UNDEFINED" - end - - alias :name :expanded_name - - # We override this, because XMLDecls and DocTypes must go at the start - # of the document - def add( child ) - if child.kind_of? XMLDecl - if @children[0].kind_of? XMLDecl - @children[0] = child - else - @children.unshift child - end - child.parent = self - elsif child.kind_of? DocType - # Find first Element or DocType node and insert the decl right - # before it. If there is no such node, just insert the child at the - # end. If there is a child and it is an DocType, then replace it. - insert_before_index = @children.find_index { |x| - x.kind_of?(Element) || x.kind_of?(DocType) - } - if insert_before_index # Not null = not end of list - if @children[ insert_before_index ].kind_of? DocType - @children[ insert_before_index ] = child - else - @children[ insert_before_index-1, 0 ] = child - end - else # Insert at end of list - @children << child - end - child.parent = self - else - rv = super - raise "attempted adding second root element to document" if @elements.size > 1 - rv - end - end - alias :<< :add - - def add_element(arg=nil, arg2=nil) - rv = super - raise "attempted adding second root element to document" if @elements.size > 1 - rv - end - - # @return the root Element of the document, or nil if this document - # has no children. - def root - elements[1] - #self - #@children.find { |item| item.kind_of? Element } - end - - # @return the DocType child of the document, if one exists, - # and nil otherwise. - def doctype - @children.find { |item| item.kind_of? DocType } - end - - # @return the XMLDecl of this document; if no XMLDecl has been - # set, the default declaration is returned. - def xml_decl - rv = @children[0] - return rv if rv.kind_of? XMLDecl - @children.unshift(XMLDecl.default)[0] - end - - # @return the XMLDecl version of this document as a String. - # If no XMLDecl has been set, returns the default version. - def version - xml_decl().version - end - - # @return the XMLDecl encoding of this document as an - # Encoding object. - # If no XMLDecl has been set, returns the default encoding. - def encoding - xml_decl().encoding - end - - # @return the XMLDecl standalone value of this document as a String. - # If no XMLDecl has been set, returns the default setting. - def stand_alone? - xml_decl().stand_alone? - end - - # :call-seq: - # doc.write(output=$stdout, indent=-1, transtive=false, ie_hack=false, encoding=nil) - # doc.write(options={:output => $stdout, :indent => -1, :transtive => false, :ie_hack => false, :encoding => nil}) - # - # Write the XML tree out, optionally with indent. This writes out the - # entire XML document, including XML declarations, doctype declarations, - # and processing instructions (if any are given). - # - # A controversial point is whether Document should always write the XML - # declaration () whether or not one is given by the - # user (or source document). REXML does not write one if one was not - # specified, because it adds unnecessary bandwidth to applications such - # as XML-RPC. - # - # Accept Nth argument style and options Hash style as argument. - # The recommended style is options Hash style for one or more - # arguments case. - # - # _Examples_ - # Document.new("").write - # - # output = "" - # Document.new("").write(output) - # - # output = "" - # Document.new("").write(:output => output, :indent => 2) - # - # See also the classes in the rexml/formatters package for the proper way - # to change the default formatting of XML output. - # - # _Examples_ - # - # output = "" - # tr = Transitive.new - # tr.write(Document.new(""), output) - # - # output:: - # output an object which supports '<< string'; this is where the - # document will be written. - # indent:: - # An integer. If -1, no indenting will be used; otherwise, the - # indentation will be twice this number of spaces, and children will be - # indented an additional amount. For a value of 3, every item will be - # indented 3 more levels, or 6 more spaces (2 * 3). Defaults to -1 - # transitive:: - # If transitive is true and indent is >= 0, then the output will be - # pretty-printed in such a way that the added whitespace does not affect - # the absolute *value* of the document -- that is, it leaves the value - # and number of Text nodes in the document unchanged. - # ie_hack:: - # This hack inserts a space before the /> on empty tags to address - # a limitation of Internet Explorer. Defaults to false - # encoding:: - # Encoding name as String. Change output encoding to specified encoding - # instead of encoding in XML declaration. - # Defaults to nil. It means encoding in XML declaration is used. - def write(*arguments) - if arguments.size == 1 and arguments[0].class == Hash - options = arguments[0] - - output = options[:output] - indent = options[:indent] - transitive = options[:transitive] - ie_hack = options[:ie_hack] - encoding = options[:encoding] - else - output, indent, transitive, ie_hack, encoding, = *arguments - end - - output ||= $stdout - indent ||= -1 - transitive = false if transitive.nil? - ie_hack = false if ie_hack.nil? - encoding ||= xml_decl.encoding - - if encoding != 'UTF-8' && !output.kind_of?(Output) - output = Output.new( output, encoding ) - end - formatter = if indent > -1 - if transitive - require_relative "formatters/transitive" - REXML::Formatters::Transitive.new( indent, ie_hack ) - else - REXML::Formatters::Pretty.new( indent, ie_hack ) - end - else - REXML::Formatters::Default.new( ie_hack ) - end - formatter.write( self, output ) - end - - - def Document::parse_stream( source, listener ) - Parsers::StreamParser.new( source, listener ).parse - end - - # Set the entity expansion limit. By default the limit is set to 10000. - # - # Deprecated. Use REXML::Security.entity_expansion_limit= instead. - def Document::entity_expansion_limit=( val ) - Security.entity_expansion_limit = val - end - - # Get the entity expansion limit. By default the limit is set to 10000. - # - # Deprecated. Use REXML::Security.entity_expansion_limit= instead. - def Document::entity_expansion_limit - return Security.entity_expansion_limit - end - - # Set the entity expansion limit. By default the limit is set to 10240. - # - # Deprecated. Use REXML::Security.entity_expansion_text_limit= instead. - def Document::entity_expansion_text_limit=( val ) - Security.entity_expansion_text_limit = val - end - - # Get the entity expansion limit. By default the limit is set to 10240. - # - # Deprecated. Use REXML::Security.entity_expansion_text_limit instead. - def Document::entity_expansion_text_limit - return Security.entity_expansion_text_limit - end - - attr_reader :entity_expansion_count - - def record_entity_expansion - @entity_expansion_count += 1 - if @entity_expansion_count > Security.entity_expansion_limit - raise "number of entity expansions exceeded, processing aborted." - end - end - - def document - self - end - - private - def build( source ) - Parsers::TreeParser.new( source, self ).parse - end - end -end diff --git a/ruby/lib/rexml/dtd/attlistdecl.rb b/ruby/lib/rexml/dtd/attlistdecl.rb deleted file mode 100644 index 1326cb21e..000000000 --- a/ruby/lib/rexml/dtd/attlistdecl.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: false -require_relative "../child" -module REXML - module DTD - class AttlistDecl < Child - START = ")/um - end - end -end diff --git a/ruby/lib/rexml/dtd/dtd.rb b/ruby/lib/rexml/dtd/dtd.rb deleted file mode 100644 index 8b0f2d753..000000000 --- a/ruby/lib/rexml/dtd/dtd.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: false -require_relative "elementdecl" -require_relative "entitydecl" -require_relative "../comment" -require_relative "notationdecl" -require_relative "attlistdecl" -require_relative "../parent" - -module REXML - module DTD - class Parser - def Parser.parse( input ) - case input - when String - parse_helper input - when File - parse_helper input.read - end - end - - # Takes a String and parses it out - def Parser.parse_helper( input ) - contents = Parent.new - while input.size > 0 - case input - when ElementDecl.PATTERN_RE - match = $& - contents << ElementDecl.new( match ) - when AttlistDecl.PATTERN_RE - matchdata = $~ - contents << AttlistDecl.new( matchdata ) - when EntityDecl.PATTERN_RE - matchdata = $~ - contents << EntityDecl.new( matchdata ) - when Comment.PATTERN_RE - matchdata = $~ - contents << Comment.new( matchdata ) - when NotationDecl.PATTERN_RE - matchdata = $~ - contents << NotationDecl.new( matchdata ) - end - end - contents - end - end - end -end diff --git a/ruby/lib/rexml/dtd/elementdecl.rb b/ruby/lib/rexml/dtd/elementdecl.rb deleted file mode 100644 index 20ed02324..000000000 --- a/ruby/lib/rexml/dtd/elementdecl.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: false -require_relative "../child" -module REXML - module DTD - class ElementDecl < Child - START = "/um - PATTERN_RE = /^\s*#{START}\s+((?:[:\w][-\.\w]*:)?[-!\*\.\w]*)(.*?)>/ - #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true) - - def initialize match - @name = match[1] - @rest = match[2] - end - end - end -end diff --git a/ruby/lib/rexml/dtd/entitydecl.rb b/ruby/lib/rexml/dtd/entitydecl.rb deleted file mode 100644 index 312df655f..000000000 --- a/ruby/lib/rexml/dtd/entitydecl.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: false -require_relative "../child" -module REXML - module DTD - class EntityDecl < Child - START = "/um - SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um - PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um - PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um - # - # - def initialize src - super() - md = nil - if src.match( PUBLIC ) - md = src.match( PUBLIC, true ) - @middle = "PUBLIC" - @content = "#{md[2]} #{md[4]}" - elsif src.match( SYSTEM ) - md = src.match( SYSTEM, true ) - @middle = "SYSTEM" - @content = md[2] - elsif src.match( PLAIN ) - md = src.match( PLAIN, true ) - @middle = "" - @content = md[2] - elsif src.match( PERCENT ) - md = src.match( PERCENT, true ) - @middle = "" - @content = md[2] - end - raise ParseException.new("failed Entity match", src) if md.nil? - @name = md[1] - end - - def to_s - rv = " 0 - rv << @content - rv - end - - def write( output, indent ) - indent( output, indent ) - output << to_s - end - - def EntityDecl.parse_source source, listener - md = source.match( PATTERN_RE, true ) - thing = md[0].squeeze(" \t\n\r") - listener.send inspect.downcase, thing - end - end - end -end diff --git a/ruby/lib/rexml/dtd/notationdecl.rb b/ruby/lib/rexml/dtd/notationdecl.rb deleted file mode 100644 index 04a9b08aa..000000000 --- a/ruby/lib/rexml/dtd/notationdecl.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: false -require_relative "../child" -module REXML - module DTD - class NotationDecl < Child - START = "/um - SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um - def initialize src - super() - if src.match( PUBLIC ) - md = src.match( PUBLIC, true ) - elsif src.match( SYSTEM ) - md = src.match( SYSTEM, true ) - else - raise ParseException.new( "error parsing notation: no matching pattern", src ) - end - @name = md[1] - @middle = md[2] - @rest = md[3] - end - - def to_s - "" - end - - def write( output, indent ) - indent( output, indent ) - output << to_s - end - - def NotationDecl.parse_source source, listener - md = source.match( PATTERN_RE, true ) - thing = md[0].squeeze(" \t\n\r") - listener.send inspect.downcase, thing - end - end - end -end diff --git a/ruby/lib/rexml/element.rb b/ruby/lib/rexml/element.rb deleted file mode 100644 index c706a7c24..000000000 --- a/ruby/lib/rexml/element.rb +++ /dev/null @@ -1,1269 +0,0 @@ -# frozen_string_literal: false -require_relative "parent" -require_relative "namespace" -require_relative "attribute" -require_relative "cdata" -require_relative "xpath" -require_relative "parseexception" - -module REXML - # An implementation note about namespaces: - # As we parse, when we find namespaces we put them in a hash and assign - # them a unique ID. We then convert the namespace prefix for the node - # to the unique ID. This makes namespace lookup much faster for the - # cost of extra memory use. We save the namespace prefix for the - # context node and convert it back when we write it. - @@namespaces = {} - - # Represents a tagged XML element. Elements are characterized by - # having children, attributes, and names, and can themselves be - # children. - class Element < Parent - include Namespace - - UNDEFINED = "UNDEFINED"; # The default name - - # Mechanisms for accessing attributes and child elements of this - # element. - attr_reader :attributes, :elements - # The context holds information about the processing environment, such as - # whitespace handling. - attr_accessor :context - - # Constructor - # arg:: - # if not supplied, will be set to the default value. - # If a String, the name of this object will be set to the argument. - # If an Element, the object will be shallowly cloned; name, - # attributes, and namespaces will be copied. Children will +not+ be - # copied. - # parent:: - # if supplied, must be a Parent, and will be used as - # the parent of this object. - # context:: - # If supplied, must be a hash containing context items. Context items - # include: - # * :respect_whitespace the value of this is :+all+ or an array of - # strings being the names of the elements to respect - # whitespace for. Defaults to :+all+. - # * :compress_whitespace the value can be :+all+ or an array of - # strings being the names of the elements to ignore whitespace on. - # Overrides :+respect_whitespace+. - # * :ignore_whitespace_nodes the value can be :+all+ or an array - # of strings being the names of the elements in which to ignore - # whitespace-only nodes. If this is set, Text nodes which contain only - # whitespace will not be added to the document tree. - # * :raw can be :+all+, or an array of strings being the names of - # the elements to process in raw mode. In raw mode, special - # characters in text is not converted to or from entities. - def initialize( arg = UNDEFINED, parent=nil, context=nil ) - super(parent) - - @elements = Elements.new(self) - @attributes = Attributes.new(self) - @context = context - - if arg.kind_of? String - self.name = arg - elsif arg.kind_of? Element - self.name = arg.expanded_name - arg.attributes.each_attribute{ |attribute| - @attributes << Attribute.new( attribute ) - } - @context = arg.context - end - end - - def inspect - rv = "<#@expanded_name" - - @attributes.each_attribute do |attr| - rv << " " - attr.write( rv, 0 ) - end - - if children.size > 0 - rv << "> ... " - else - rv << "/>" - end - end - - - # Creates a shallow copy of self. - # d = Document.new "" - # new_a = d.root.clone - # puts new_a # => "" - def clone - self.class.new self - end - - # Evaluates to the root node of the document that this element - # belongs to. If this element doesn't belong to a document, but does - # belong to another Element, the parent's root will be returned, until the - # earliest ancestor is found. - # - # Note that this is not the same as the document element. - # In the following example, is the document element, and the root - # node is the parent node of the document element. You may ask yourself - # why the root node is useful: consider the doctype and XML declaration, - # and any processing instructions before the document element... they - # are children of the root node, or siblings of the document element. - # The only time this isn't true is when an Element is created that is - # not part of any Document. In this case, the ancestor that has no - # parent acts as the root node. - # d = Document.new '' - # a = d[1] ; c = a[1][1] - # d.root_node == d # TRUE - # a.root_node # namely, d - # c.root_node # again, d - def root_node - parent.nil? ? self : parent.root_node - end - - def root - return elements[1] if self.kind_of? Document - return self if parent.kind_of? Document or parent.nil? - return parent.root - end - - # Evaluates to the document to which this element belongs, or nil if this - # element doesn't belong to a document. - def document - rt = root - rt.parent if rt - end - - # Evaluates to +true+ if whitespace is respected for this element. This - # is the case if: - # 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value - # 2. The context has :+respect_whitespace+ set to :+all+ or - # an array containing the name of this element, and - # :+compress_whitespace+ isn't set to :+all+ or an array containing the - # name of this element. - # The evaluation is tested against +expanded_name+, and so is namespace - # sensitive. - def whitespace - @whitespace = nil - if @context - if @context[:respect_whitespace] - @whitespace = (@context[:respect_whitespace] == :all or - @context[:respect_whitespace].include? expanded_name) - end - @whitespace = false if (@context[:compress_whitespace] and - (@context[:compress_whitespace] == :all or - @context[:compress_whitespace].include? expanded_name) - ) - end - @whitespace = true unless @whitespace == false - @whitespace - end - - def ignore_whitespace_nodes - @ignore_whitespace_nodes = false - if @context - if @context[:ignore_whitespace_nodes] - @ignore_whitespace_nodes = - (@context[:ignore_whitespace_nodes] == :all or - @context[:ignore_whitespace_nodes].include? expanded_name) - end - end - end - - # Evaluates to +true+ if raw mode is set for this element. This - # is the case if the context has :+raw+ set to :+all+ or - # an array containing the name of this element. - # - # The evaluation is tested against +expanded_name+, and so is namespace - # sensitive. - def raw - @raw = (@context and @context[:raw] and - (@context[:raw] == :all or - @context[:raw].include? expanded_name)) - @raw - end - - #once :whitespace, :raw, :ignore_whitespace_nodes - - ################################################# - # Namespaces # - ################################################# - - # Evaluates to an +Array+ containing the prefixes (names) of all defined - # namespaces at this context node. - # doc = Document.new("") - # doc.elements['//b'].prefixes # -> ['x', 'y'] - def prefixes - prefixes = [] - prefixes = parent.prefixes if parent - prefixes |= attributes.prefixes - return prefixes - end - - def namespaces - namespaces = {} - namespaces = parent.namespaces if parent - namespaces = namespaces.merge( attributes.namespaces ) - return namespaces - end - - # Evaluates to the URI for a prefix, or the empty string if no such - # namespace is declared for this element. Evaluates recursively for - # ancestors. Returns the default namespace, if there is one. - # prefix:: - # the prefix to search for. If not supplied, returns the default - # namespace if one exists - # Returns:: - # the namespace URI as a String, or nil if no such namespace - # exists. If the namespace is undefined, returns an empty string - # doc = Document.new("") - # b = doc.elements['//b'] - # b.namespace # -> '1' - # b.namespace("y") # -> '2' - def namespace(prefix=nil) - if prefix.nil? - prefix = prefix() - end - if prefix == '' - prefix = "xmlns" - else - prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns' - end - ns = attributes[ prefix ] - ns = parent.namespace(prefix) if ns.nil? and parent - ns = '' if ns.nil? and prefix == 'xmlns' - return ns - end - - # Adds a namespace to this element. - # prefix:: - # the prefix string, or the namespace URI if +uri+ is not - # supplied - # uri:: - # the namespace URI. May be nil, in which +prefix+ is used as - # the URI - # Evaluates to: this Element - # a = Element.new("a") - # a.add_namespace("xmlns:foo", "bar" ) - # a.add_namespace("foo", "bar") # shorthand for previous line - # a.add_namespace("twiddle") - # puts a #-> - def add_namespace( prefix, uri=nil ) - unless uri - @attributes["xmlns"] = prefix - else - prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/ - @attributes[ prefix ] = uri - end - self - end - - # Removes a namespace from this node. This only works if the namespace is - # actually declared in this node. If no argument is passed, deletes the - # default namespace. - # - # Evaluates to: this element - # doc = Document.new "" - # doc.root.delete_namespace - # puts doc # -> - # doc.root.delete_namespace 'foo' - # puts doc # -> - def delete_namespace namespace="xmlns" - namespace = "xmlns:#{namespace}" unless namespace == 'xmlns' - attribute = attributes.get_attribute(namespace) - attribute.remove unless attribute.nil? - self - end - - ################################################# - # Elements # - ################################################# - - # Adds a child to this element, optionally setting attributes in - # the element. - # element:: - # optional. If Element, the element is added. - # Otherwise, a new Element is constructed with the argument (see - # Element.initialize). - # attrs:: - # If supplied, must be a Hash containing String name,value - # pairs, which will be used to set the attributes of the new Element. - # Returns:: the Element that was added - # el = doc.add_element 'my-tag' - # el = doc.add_element 'my-tag', {'attr1'=>'val1', 'attr2'=>'val2'} - # el = Element.new 'my-tag' - # doc.add_element el - def add_element element, attrs=nil - raise "First argument must be either an element name, or an Element object" if element.nil? - el = @elements.add(element) - attrs.each do |key, value| - el.attributes[key]=value - end if attrs.kind_of? Hash - el - end - - # Deletes a child element. - # element:: - # Must be an +Element+, +String+, or +Integer+. If Element, - # the element is removed. If String, the element is found (via XPath) - # and removed. This means that any parent can remove any - # descendant. If Integer, the Element indexed by that number will be - # removed. - # Returns:: the element that was removed. - # doc.delete_element "/a/b/c[@id='4']" - # doc.delete_element doc.elements["//k"] - # doc.delete_element 1 - def delete_element element - @elements.delete element - end - - # Evaluates to +true+ if this element has at least one child Element - # doc = Document.new "Text" - # doc.root.has_elements # -> true - # doc.elements["/a/b"].has_elements # -> false - # doc.elements["/a/c"].has_elements # -> false - def has_elements? - !@elements.empty? - end - - # Iterates through the child elements, yielding for each Element that - # has a particular attribute set. - # key:: - # the name of the attribute to search for - # value:: - # the value of the attribute - # max:: - # (optional) causes this method to return after yielding - # for this number of matching children - # name:: - # (optional) if supplied, this is an XPath that filters - # the children to check. - # - # doc = Document.new "" - # # Yields b, c, d - # doc.root.each_element_with_attribute( 'id' ) {|e| p e} - # # Yields b, d - # doc.root.each_element_with_attribute( 'id', '1' ) {|e| p e} - # # Yields b - # doc.root.each_element_with_attribute( 'id', '1', 1 ) {|e| p e} - # # Yields d - # doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e} - def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element - each_with_something( proc {|child| - if value.nil? - child.attributes[key] != nil - else - child.attributes[key]==value - end - }, max, name, &block ) - end - - # Iterates through the children, yielding for each Element that - # has a particular text set. - # text:: - # the text to search for. If nil, or not supplied, will iterate - # over all +Element+ children that contain at least one +Text+ node. - # max:: - # (optional) causes this method to return after yielding - # for this number of matching children - # name:: - # (optional) if supplied, this is an XPath that filters - # the children to check. - # - # doc = Document.new 'bbd' - # # Yields b, c, d - # doc.each_element_with_text {|e|p e} - # # Yields b, c - # doc.each_element_with_text('b'){|e|p e} - # # Yields b - # doc.each_element_with_text('b', 1){|e|p e} - # # Yields d - # doc.each_element_with_text(nil, 0, 'd'){|e|p e} - def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element - each_with_something( proc {|child| - if text.nil? - child.has_text? - else - child.text == text - end - }, max, name, &block ) - end - - # Synonym for Element.elements.each - def each_element( xpath=nil, &block ) # :yields: Element - @elements.each( xpath, &block ) - end - - # Synonym for Element.to_a - # This is a little slower than calling elements.each directly. - # xpath:: any XPath by which to search for elements in the tree - # Returns:: an array of Elements that match the supplied path - def get_elements( xpath ) - @elements.to_a( xpath ) - end - - # Returns the next sibling that is an element, or nil if there is - # no Element sibling after this one - # doc = Document.new 'text' - # doc.root.elements['b'].next_element #-> - # doc.root.elements['c'].next_element #-> nil - def next_element - element = next_sibling - element = element.next_sibling until element.nil? or element.kind_of? Element - return element - end - - # Returns the previous sibling that is an element, or nil if there is - # no Element sibling prior to this one - # doc = Document.new 'text' - # doc.root.elements['c'].previous_element #-> - # doc.root.elements['b'].previous_element #-> nil - def previous_element - element = previous_sibling - element = element.previous_sibling until element.nil? or element.kind_of? Element - return element - end - - - ################################################# - # Text # - ################################################# - - # Evaluates to +true+ if this element has at least one Text child - def has_text? - not text().nil? - end - - # A convenience method which returns the String value of the _first_ - # child text element, if one exists, and +nil+ otherwise. - # - # Note that an element may have multiple Text elements, perhaps - # separated by other children. Be aware that this method only returns - # the first Text node. - # - # This method returns the +value+ of the first text child node, which - # ignores the +raw+ setting, so always returns normalized text. See - # the Text::value documentation. - # - # doc = Document.new "

some text this is bold! more text

" - # # The element 'p' has two text elements, "some text " and " more text". - # doc.root.text #-> "some text " - def text( path = nil ) - rv = get_text(path) - return rv.value unless rv.nil? - nil - end - - # Returns the first child Text node, if any, or +nil+ otherwise. - # This method returns the actual +Text+ node, rather than the String content. - # doc = Document.new "

some text this is bold! more text

" - # # The element 'p' has two text elements, "some text " and " more text". - # doc.root.get_text.value #-> "some text " - def get_text path = nil - rv = nil - if path - element = @elements[ path ] - rv = element.get_text unless element.nil? - else - rv = @children.find { |node| node.kind_of? Text } - end - return rv - end - - # Sets the first Text child of this object. See text() for a - # discussion about Text children. - # - # If a Text child already exists, the child is replaced by this - # content. This means that Text content can be deleted by calling - # this method with a nil argument. In this case, the next Text - # child becomes the first Text child. In no case is the order of - # any siblings disturbed. - # text:: - # If a String, a new Text child is created and added to - # this Element as the first Text child. If Text, the text is set - # as the first Child element. If nil, then any existing first Text - # child is removed. - # Returns:: this Element. - # doc = Document.new '' - # doc.root.text = 'Sean' #-> 'Sean' - # doc.root.text = 'Elliott' #-> 'Elliott' - # doc.root.add_element 'c' #-> 'Elliott' - # doc.root.text = 'Russell' #-> 'Russell' - # doc.root.text = nil #-> '' - def text=( text ) - if text.kind_of? String - text = Text.new( text, whitespace(), nil, raw() ) - elsif !text.nil? and !text.kind_of? Text - text = Text.new( text.to_s, whitespace(), nil, raw() ) - end - old_text = get_text - if text.nil? - old_text.remove unless old_text.nil? - else - if old_text.nil? - self << text - else - old_text.replace_with( text ) - end - end - return self - end - - # A helper method to add a Text child. Actual Text instances can - # be added with regular Parent methods, such as add() and <<() - # text:: - # if a String, a new Text instance is created and added - # to the parent. If Text, the object is added directly. - # Returns:: this Element - # e = Element.new('a') #-> - # e.add_text 'foo' #-> foo - # e.add_text Text.new(' bar') #-> foo bar - # Note that at the end of this example, the branch has 3 nodes; the 'e' - # element and 2 Text node children. - def add_text( text ) - if text.kind_of? String - if @children[-1].kind_of? Text - @children[-1] << text - return - end - text = Text.new( text, whitespace(), nil, raw() ) - end - self << text unless text.nil? - return self - end - - def node_type - :element - end - - def xpath - path_elements = [] - cur = self - path_elements << __to_xpath_helper( self ) - while cur.parent - cur = cur.parent - path_elements << __to_xpath_helper( cur ) - end - return path_elements.reverse.join( "/" ) - end - - ################################################# - # Attributes # - ################################################# - - # Fetches an attribute value or a child. - # - # If String or Symbol is specified, it's treated as attribute - # name. Attribute value as String or +nil+ is returned. This case - # is shortcut of +attributes[name]+. - # - # If Integer is specified, it's treated as the index of - # child. It returns Nth child. - # - # doc = REXML::Document.new("") - # doc.root["attr"] # => "1" - # doc.root.attributes["attr"] # => "1" - # doc.root[1] # => - def [](name_or_index) - case name_or_index - when String - attributes[name_or_index] - when Symbol - attributes[name_or_index.to_s] - else - super - end - end - - def attribute( name, namespace=nil ) - prefix = nil - if namespaces.respond_to? :key - prefix = namespaces.key(namespace) if namespace - else - prefix = namespaces.index(namespace) if namespace - end - prefix = nil if prefix == 'xmlns' - - ret_val = - attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" ) - - return ret_val unless ret_val.nil? - return nil if prefix.nil? - - # now check that prefix'es namespace is not the same as the - # default namespace - return nil unless ( namespaces[ prefix ] == namespaces[ 'xmlns' ] ) - - attributes.get_attribute( name ) - - end - - # Evaluates to +true+ if this element has any attributes set, false - # otherwise. - def has_attributes? - return !@attributes.empty? - end - - # Adds an attribute to this element, overwriting any existing attribute - # by the same name. - # key:: - # can be either an Attribute or a String. If an Attribute, - # the attribute is added to the list of Element attributes. If String, - # the argument is used as the name of the new attribute, and the value - # parameter must be supplied. - # value:: - # Required if +key+ is a String, and ignored if the first argument is - # an Attribute. This is a String, and is used as the value - # of the new Attribute. This should be the unnormalized value of the - # attribute (without entities). - # Returns:: the Attribute added - # e = Element.new 'e' - # e.add_attribute( 'a', 'b' ) #-> - # e.add_attribute( 'x:a', 'c' ) #-> - # e.add_attribute Attribute.new('b', 'd') #-> - def add_attribute( key, value=nil ) - if key.kind_of? Attribute - @attributes << key - else - @attributes[key] = value - end - end - - # Add multiple attributes to this element. - # hash:: is either a hash, or array of arrays - # el.add_attributes( {"name1"=>"value1", "name2"=>"value2"} ) - # el.add_attributes( [ ["name1","value1"], ["name2"=>"value2"] ] ) - def add_attributes hash - if hash.kind_of? Hash - hash.each_pair {|key, value| @attributes[key] = value } - elsif hash.kind_of? Array - hash.each { |value| @attributes[ value[0] ] = value[1] } - end - end - - # Removes an attribute - # key:: - # either an Attribute or a String. In either case, the - # attribute is found by matching the attribute name to the argument, - # and then removed. If no attribute is found, no action is taken. - # Returns:: - # the attribute removed, or nil if this Element did not contain - # a matching attribute - # e = Element.new('E') - # e.add_attribute( 'name', 'Sean' ) #-> - # r = e.add_attribute( 'sur:name', 'Russell' ) #-> - # e.delete_attribute( 'name' ) #-> - # e.delete_attribute( r ) #-> - def delete_attribute(key) - attr = @attributes.get_attribute(key) - attr.remove unless attr.nil? - end - - ################################################# - # Other Utilities # - ################################################# - - # Get an array of all CData children. - # IMMUTABLE - def cdatas - find_all { |child| child.kind_of? CData }.freeze - end - - # Get an array of all Comment children. - # IMMUTABLE - def comments - find_all { |child| child.kind_of? Comment }.freeze - end - - # Get an array of all Instruction children. - # IMMUTABLE - def instructions - find_all { |child| child.kind_of? Instruction }.freeze - end - - # Get an array of all Text children. - # IMMUTABLE - def texts - find_all { |child| child.kind_of? Text }.freeze - end - - # == DEPRECATED - # See REXML::Formatters - # - # Writes out this element, and recursively, all children. - # output:: - # output an object which supports '<< string'; this is where the - # document will be written. - # indent:: - # An integer. If -1, no indenting will be used; otherwise, the - # indentation will be this number of spaces, and children will be - # indented an additional amount. Defaults to -1 - # transitive:: - # If transitive is true and indent is >= 0, then the output will be - # pretty-printed in such a way that the added whitespace does not affect - # the parse tree of the document - # ie_hack:: - # This hack inserts a space before the /> on empty tags to address - # a limitation of Internet Explorer. Defaults to false - # - # out = '' - # doc.write( out ) #-> doc is written to the string 'out' - # doc.write( $stdout ) #-> doc written to the console - def write(output=$stdout, indent=-1, transitive=false, ie_hack=false) - Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1) - formatter = if indent > -1 - if transitive - require_relative "formatters/transitive" - REXML::Formatters::Transitive.new( indent, ie_hack ) - else - REXML::Formatters::Pretty.new( indent, ie_hack ) - end - else - REXML::Formatters::Default.new( ie_hack ) - end - formatter.write( self, output ) - end - - - private - def __to_xpath_helper node - rv = node.expanded_name.clone - if node.parent - results = node.parent.find_all {|n| - n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name - } - if results.length > 1 - idx = results.index( node ) - rv << "[#{idx+1}]" - end - end - rv - end - - # A private helper method - def each_with_something( test, max=0, name=nil ) - num = 0 - @elements.each( name ){ |child| - yield child if test.call(child) and num += 1 - return if max>0 and num == max - } - end - end - - ######################################################################## - # ELEMENTS # - ######################################################################## - - # A class which provides filtering of children for Elements, and - # XPath search support. You are expected to only encounter this class as - # the element.elements object. Therefore, you are - # _not_ expected to instantiate this yourself. - class Elements - include Enumerable - # Constructor - # parent:: the parent Element - def initialize parent - @element = parent - end - - # Fetches a child element. Filters only Element children, regardless of - # the XPath match. - # index:: - # the search parameter. This is either an Integer, which - # will be used to find the index'th child Element, or an XPath, - # which will be used to search for the Element. Because - # of the nature of XPath searches, any element in the connected XML - # document can be fetched through any other element. The - # Integer index is 1-based, not 0-based. This means that the first - # child element is at index 1, not 0, and the +n+th element is at index - # +n+, not n-1. This is because XPath indexes element children - # starting from 1, not 0, and the indexes should be the same. - # name:: - # optional, and only used in the first argument is an - # Integer. In that case, the index'th child Element that has the - # supplied name will be returned. Note again that the indexes start at 1. - # Returns:: the first matching Element, or nil if no child matched - # doc = Document.new '' - # doc.root.elements[1] #-> - # doc.root.elements['c'] #-> - # doc.root.elements[2,'c'] #-> - def []( index, name=nil) - if index.kind_of? Integer - raise "index (#{index}) must be >= 1" if index < 1 - name = literalize(name) if name - num = 0 - @element.find { |child| - child.kind_of? Element and - (name.nil? ? true : child.has_name?( name )) and - (num += 1) == index - } - else - return XPath::first( @element, index ) - #{ |element| - # return element if element.kind_of? Element - #} - #return nil - end - end - - # Sets an element, replacing any previous matching element. If no - # existing element is found ,the element is added. - # index:: Used to find a matching element to replace. See [](). - # element:: - # The element to replace the existing element with - # the previous element - # Returns:: nil if no previous element was found. - # - # doc = Document.new '' - # doc.root.elements[10] = Element.new('b') #-> - # doc.root.elements[1] #-> - # doc.root.elements[1] = Element.new('c') #-> - # doc.root.elements['c'] = Element.new('d') #-> - def []=( index, element ) - previous = self[index] - if previous.nil? - @element.add element - else - previous.replace_with element - end - return previous - end - - # Returns +true+ if there are no +Element+ children, +false+ otherwise - def empty? - @element.find{ |child| child.kind_of? Element}.nil? - end - - # Returns the index of the supplied child (starting at 1), or -1 if - # the element is not a child - # element:: an +Element+ child - def index element - rv = 0 - found = @element.find do |child| - child.kind_of? Element and - (rv += 1) and - child == element - end - return rv if found == element - return -1 - end - - # Deletes a child Element - # element:: - # Either an Element, which is removed directly; an - # xpath, where the first matching child is removed; or an Integer, - # where the n'th Element is removed. - # Returns:: the removed child - # doc = Document.new '' - # b = doc.root.elements[1] - # doc.root.elements.delete b #-> - # doc.elements.delete("a/c[@id='1']") #-> - # doc.root.elements.delete 1 #-> - def delete element - if element.kind_of? Element - @element.delete element - else - el = self[element] - el.remove if el - end - end - - # Removes multiple elements. Filters for Element children, regardless of - # XPath matching. - # xpath:: all elements matching this String path are removed. - # Returns:: an Array of Elements that have been removed - # doc = Document.new '' - # deleted = doc.elements.delete_all 'a/c' #-> [, , , ] - def delete_all( xpath ) - rv = [] - XPath::each( @element, xpath) {|element| - rv << element if element.kind_of? Element - } - rv.each do |element| - @element.delete element - element.remove - end - return rv - end - - # Adds an element - # element:: - # if supplied, is either an Element, String, or - # Source (see Element.initialize). If not supplied or nil, a - # new, default Element will be constructed - # Returns:: the added Element - # a = Element.new('a') - # a.elements.add(Element.new('b')) #-> - # a.elements.add('c') #-> - def add element=nil - if element.nil? - Element.new("", self, @element.context) - elsif not element.kind_of?(Element) - Element.new(element, self, @element.context) - else - @element << element - element.context = @element.context - element - end - end - - alias :<< :add - - # Iterates through all of the child Elements, optionally filtering - # them by a given XPath - # xpath:: - # optional. If supplied, this is a String XPath, and is used to - # filter the children, so that only matching children are yielded. Note - # that XPaths are automatically filtered for Elements, so that - # non-Element children will not be yielded - # doc = Document.new 'sean' - # doc.root.elements.each {|e|p e} #-> Yields b, c, d, b, c, d elements - # doc.root.elements.each('b') {|e|p e} #-> Yields b, b elements - # doc.root.elements.each('child::node()') {|e|p e} - # #-> Yields , , , , , - # XPath.each(doc.root, 'child::node()', &block) - # #-> Yields , , , sean, , , - def each( xpath=nil ) - XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element } - end - - def collect( xpath=nil ) - collection = [] - XPath::each( @element, xpath ) {|e| - collection << yield(e) if e.kind_of?(Element) - } - collection - end - - def inject( xpath=nil, initial=nil ) - first = true - XPath::each( @element, xpath ) {|e| - if (e.kind_of? Element) - if (first and initial == nil) - initial = e - first = false - else - initial = yield( initial, e ) if e.kind_of? Element - end - end - } - initial - end - - # Returns the number of +Element+ children of the parent object. - # doc = Document.new 'seanelliottrussell' - # doc.root.size #-> 6, 3 element and 3 text nodes - # doc.root.elements.size #-> 3 - def size - count = 0 - @element.each {|child| count+=1 if child.kind_of? Element } - count - end - - # Returns an Array of Element children. An XPath may be supplied to - # filter the children. Only Element children are returned, even if the - # supplied XPath matches non-Element children. - # doc = Document.new 'seanelliott' - # doc.root.elements.to_a #-> [ , ] - # doc.root.elements.to_a("child::node()") #-> [ , ] - # XPath.match(doc.root, "child::node()") #-> [ sean, , elliott, ] - def to_a( xpath=nil ) - rv = XPath.match( @element, xpath ) - return rv.find_all{|e| e.kind_of? Element} if xpath - rv - end - - private - # Private helper class. Removes quotes from quoted strings - def literalize name - name = name[1..-2] if name[0] == ?' or name[0] == ?" #' - name - end - end - - ######################################################################## - # ATTRIBUTES # - ######################################################################## - - # A class that defines the set of Attributes of an Element and provides - # operations for accessing elements in that set. - class Attributes < Hash - # Constructor - # element:: the Element of which this is an Attribute - def initialize element - @element = element - end - - # Fetches an attribute value. If you want to get the Attribute itself, - # use get_attribute() - # name:: an XPath attribute name. Namespaces are relevant here. - # Returns:: - # the String value of the matching attribute, or +nil+ if no - # matching attribute was found. This is the unnormalized value - # (with entities expanded). - # - # doc = Document.new "" - # doc.root.attributes['att'] #-> '<' - # doc.root.attributes['bar:att'] #-> '2' - def [](name) - attr = get_attribute(name) - return attr.value unless attr.nil? - return nil - end - - def to_a - enum_for(:each_attribute).to_a - end - - # Returns the number of attributes the owning Element contains. - # doc = Document "" - # doc.root.attributes.length #-> 3 - def length - c = 0 - each_attribute { c+=1 } - c - end - alias :size :length - - # Iterates over the attributes of an Element. Yields actual Attribute - # nodes, not String values. - # - # doc = Document.new '' - # doc.root.attributes.each_attribute {|attr| - # p attr.expanded_name+" => "+attr.value - # } - def each_attribute # :yields: attribute - return to_enum(__method__) unless block_given? - each_value do |val| - if val.kind_of? Attribute - yield val - else - val.each_value { |atr| yield atr } - end - end - end - - # Iterates over each attribute of an Element, yielding the expanded name - # and value as a pair of Strings. - # - # doc = Document.new '' - # doc.root.attributes.each {|name, value| p name+" => "+value } - def each - return to_enum(__method__) unless block_given? - each_attribute do |attr| - yield [attr.expanded_name, attr.value] - end - end - - # Fetches an attribute - # name:: - # the name by which to search for the attribute. Can be a - # prefix:name namespace name. - # Returns:: The first matching attribute, or nil if there was none. This - # value is an Attribute node, not the String value of the attribute. - # doc = Document.new '' - # doc.root.attributes.get_attribute("foo").value #-> "2" - # doc.root.attributes.get_attribute("x:foo").value #-> "1" - def get_attribute( name ) - attr = fetch( name, nil ) - if attr.nil? - return nil if name.nil? - # Look for prefix - name =~ Namespace::NAMESPLIT - prefix, n = $1, $2 - if prefix - attr = fetch( n, nil ) - # check prefix - if attr == nil - elsif attr.kind_of? Attribute - return attr if prefix == attr.prefix - else - attr = attr[ prefix ] - return attr - end - end - element_document = @element.document - if element_document and element_document.doctype - expn = @element.expanded_name - expn = element_document.doctype.name if expn.size == 0 - attr_val = element_document.doctype.attribute_of(expn, name) - return Attribute.new( name, attr_val ) if attr_val - end - return nil - end - if attr.kind_of? Hash - attr = attr[ @element.prefix ] - end - return attr - end - - # Sets an attribute, overwriting any existing attribute value by the - # same name. Namespace is significant. - # name:: the name of the attribute - # value:: - # (optional) If supplied, the value of the attribute. If - # nil, any existing matching attribute is deleted. - # Returns:: - # Owning element - # doc = Document.new "" - # doc.root.attributes['y:foo'] = '2' - # doc.root.attributes['foo'] = '4' - # doc.root.attributes['x:foo'] = nil - def []=( name, value ) - if value.nil? # Delete the named attribute - attr = get_attribute(name) - delete attr - return - end - - unless value.kind_of? Attribute - if @element.document and @element.document.doctype - value = Text::normalize( value, @element.document.doctype ) - else - value = Text::normalize( value, nil ) - end - value = Attribute.new(name, value) - end - value.element = @element - old_attr = fetch(value.name, nil) - if old_attr.nil? - store(value.name, value) - elsif old_attr.kind_of? Hash - old_attr[value.prefix] = value - elsif old_attr.prefix != value.prefix - # Check for conflicting namespaces - if value.prefix != "xmlns" and old_attr.prefix != "xmlns" - old_namespace = old_attr.namespace - new_namespace = value.namespace - if old_namespace == new_namespace - raise ParseException.new( - "Namespace conflict in adding attribute \"#{value.name}\": "+ - "Prefix \"#{old_attr.prefix}\" = \"#{old_namespace}\" and "+ - "prefix \"#{value.prefix}\" = \"#{new_namespace}\"") - end - end - store value.name, {old_attr.prefix => old_attr, - value.prefix => value} - else - store value.name, value - end - return @element - end - - # Returns an array of Strings containing all of the prefixes declared - # by this set of # attributes. The array does not include the default - # namespace declaration, if one exists. - # doc = Document.new("") - # prefixes = doc.root.attributes.prefixes #-> ['x', 'y'] - def prefixes - ns = [] - each_attribute do |attribute| - ns << attribute.name if attribute.prefix == 'xmlns' - end - if @element.document and @element.document.doctype - expn = @element.expanded_name - expn = @element.document.doctype.name if expn.size == 0 - @element.document.doctype.attributes_of(expn).each { - |attribute| - ns << attribute.name if attribute.prefix == 'xmlns' - } - end - ns - end - - def namespaces - namespaces = {} - each_attribute do |attribute| - namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns' - end - if @element.document and @element.document.doctype - expn = @element.expanded_name - expn = @element.document.doctype.name if expn.size == 0 - @element.document.doctype.attributes_of(expn).each { - |attribute| - namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns' - } - end - namespaces - end - - # Removes an attribute - # attribute:: - # either a String, which is the name of the attribute to remove -- - # namespaces are significant here -- or the attribute to remove. - # Returns:: the owning element - # doc = Document.new "" - # doc.root.attributes.delete 'foo' #-> " - # doc.root.attributes.delete 'x:foo' #-> " - # attr = doc.root.attributes.get_attribute('y:foo') - # doc.root.attributes.delete attr #-> " - def delete( attribute ) - name = nil - prefix = nil - if attribute.kind_of? Attribute - name = attribute.name - prefix = attribute.prefix - else - attribute =~ Namespace::NAMESPLIT - prefix, name = $1, $2 - prefix = '' unless prefix - end - old = fetch(name, nil) - if old.kind_of? Hash # the supplied attribute is one of many - old.delete(prefix) - if old.size == 1 - repl = nil - old.each_value{|v| repl = v} - store name, repl - end - elsif old.nil? - return @element - else # the supplied attribute is a top-level one - super(name) - end - @element - end - - # Adds an attribute, overriding any existing attribute by the - # same name. Namespaces are significant. - # attribute:: An Attribute - def add( attribute ) - self[attribute.name] = attribute - end - - alias :<< :add - - # Deletes all attributes matching a name. Namespaces are significant. - # name:: - # A String; all attributes that match this path will be removed - # Returns:: an Array of the Attributes that were removed - def delete_all( name ) - rv = [] - each_attribute { |attribute| - rv << attribute if attribute.expanded_name == name - } - rv.each{ |attr| attr.remove } - return rv - end - - # The +get_attribute_ns+ method retrieves a method by its namespace - # and name. Thus it is possible to reliably identify an attribute - # even if an XML processor has changed the prefix. - # - # Method contributed by Henrik Martensson - def get_attribute_ns(namespace, name) - result = nil - each_attribute() { |attribute| - if name == attribute.name && - namespace == attribute.namespace() && - ( !namespace.empty? || !attribute.fully_expanded_name.index(':') ) - # foo will match xmlns:foo, but only if foo isn't also an attribute - result = attribute if !result or !namespace.empty? or - !attribute.fully_expanded_name.index(':') - end - } - result - end - end -end diff --git a/ruby/lib/rexml/encoding.rb b/ruby/lib/rexml/encoding.rb deleted file mode 100644 index da2d70d6c..000000000 --- a/ruby/lib/rexml/encoding.rb +++ /dev/null @@ -1,51 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: false -module REXML - module Encoding - # ID ---> Encoding name - attr_reader :encoding - def encoding=(encoding) - encoding = encoding.name if encoding.is_a?(Encoding) - if encoding.is_a?(String) - original_encoding = encoding - encoding = find_encoding(encoding) - unless encoding - raise ArgumentError, "Bad encoding name #{original_encoding}" - end - end - return false if defined?(@encoding) and encoding == @encoding - if encoding - @encoding = encoding.upcase - else - @encoding = 'UTF-8' - end - true - end - - def encode(string) - string.encode(@encoding) - end - - def decode(string) - string.encode(::Encoding::UTF_8, @encoding) - end - - private - def find_encoding(name) - case name - when /\Ashift-jis\z/i - return "SHIFT_JIS" - when /\ACP-(\d+)\z/ - name = "CP#{$1}" - when /\AUTF-8\z/i - return name - end - begin - ::Encoding::Converter.search_convpath(name, 'UTF-8') - rescue ::Encoding::ConverterNotFoundError - return nil - end - name - end - end -end diff --git a/ruby/lib/rexml/entity.rb b/ruby/lib/rexml/entity.rb deleted file mode 100644 index 89a9e84c5..000000000 --- a/ruby/lib/rexml/entity.rb +++ /dev/null @@ -1,171 +0,0 @@ -# frozen_string_literal: false -require_relative 'child' -require_relative 'source' -require_relative 'xmltokens' - -module REXML - class Entity < Child - include XMLTokens - PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#" - SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))} - PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')} - EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" - NDATADECL = "\\s+NDATA\\s+#{NAME}" - PEREFERENCE = "%#{NAME};" - ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} - PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" - ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" - PEDECL = "" - GEDECL = "" - ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um - - attr_reader :name, :external, :ref, :ndata, :pubid - - # Create a new entity. Simple entities can be constructed by passing a - # name, value to the constructor; this creates a generic, plain entity - # reference. For anything more complicated, you have to pass a Source to - # the constructor with the entity definition, or use the accessor methods. - # +WARNING+: There is no validation of entity state except when the entity - # is read from a stream. If you start poking around with the accessors, - # you can easily create a non-conformant Entity. - # - # e = Entity.new( 'amp', '&' ) - def initialize stream, value=nil, parent=nil, reference=false - super(parent) - @ndata = @pubid = @value = @external = nil - if stream.kind_of? Array - @name = stream[1] - if stream[-1] == '%' - @reference = true - stream.pop - else - @reference = false - end - if stream[2] =~ /SYSTEM|PUBLIC/ - @external = stream[2] - if @external == 'SYSTEM' - @ref = stream[3] - @ndata = stream[4] if stream.size == 5 - else - @pubid = stream[3] - @ref = stream[4] - end - else - @value = stream[2] - end - else - @reference = reference - @external = nil - @name = stream - @value = value - end - end - - # Evaluates whether the given string matches an entity definition, - # returning true if so, and false otherwise. - def Entity::matches? string - (ENTITYDECL =~ string) == 0 - end - - # Evaluates to the unnormalized value of this entity; that is, replacing - # all entities -- both %ent; and &ent; entities. This differs from - # +value()+ in that +value+ only replaces %ent; entities. - def unnormalized - document.record_entity_expansion unless document.nil? - v = value() - return nil if v.nil? - @unnormalized = Text::unnormalize(v, parent) - @unnormalized - end - - #once :unnormalized - - # Returns the value of this entity unprocessed -- raw. This is the - # normalized value; that is, with all %ent; and &ent; entities intact - def normalized - @value - end - - # Write out a fully formed, correct entity definition (assuming the Entity - # object itself is valid.) - # - # out:: - # An object implementing << to which the entity will be - # output - # indent:: - # *DEPRECATED* and ignored - def write out, indent=-1 - out << '' - end - - # Returns this entity as a string. See write(). - def to_s - rv = '' - write rv - rv - end - - PEREFERENCE_RE = /#{PEREFERENCE}/um - # Returns the value of this entity. At the moment, only internal entities - # are processed. If the value contains internal references (IE, - # %blah;), those are replaced with their values. IE, if the doctype - # contains: - # - # - # then: - # doctype.entity('yada').value #-> "nanoo bar nanoo" - def value - if @value - matches = @value.scan(PEREFERENCE_RE) - rv = @value.clone - if @parent - sum = 0 - matches.each do |entity_reference| - entity_value = @parent.entity( entity_reference[0] ) - if sum + entity_value.bytesize > Security.entity_expansion_text_limit - raise "entity expansion has grown too large" - else - sum += entity_value.bytesize - end - rv.gsub!( /%#{entity_reference.join};/um, entity_value ) - end - end - return rv - end - nil - end - end - - # This is a set of entity constants -- the ones defined in the XML - # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+. - # CAUTION: these entities does not have parent and document - module EntityConst - # +>+ - GT = Entity.new( 'gt', '>' ) - # +<+ - LT = Entity.new( 'lt', '<' ) - # +&+ - AMP = Entity.new( 'amp', '&' ) - # +"+ - QUOT = Entity.new( 'quot', '"' ) - # +'+ - APOS = Entity.new( 'apos', "'" ) - end -end diff --git a/ruby/lib/rexml/formatters/default.rb b/ruby/lib/rexml/formatters/default.rb deleted file mode 100644 index 811b2ff3d..000000000 --- a/ruby/lib/rexml/formatters/default.rb +++ /dev/null @@ -1,116 +0,0 @@ -# frozen_string_literal: false - -module REXML - module Formatters - class Default - # Prints out the XML document with no formatting -- except if ie_hack is - # set. - # - # ie_hack:: - # If set to true, then inserts whitespace before the close of an empty - # tag, so that IE's bad XML parser doesn't choke. - def initialize( ie_hack=false ) - @ie_hack = ie_hack - end - - # Writes the node to some output. - # - # node:: - # The node to write - # output:: - # A class implementing <<. Pass in an Output object to - # change the output encoding. - def write( node, output ) - case node - - when Document - if node.xml_decl.encoding != 'UTF-8' && !output.kind_of?(Output) - output = Output.new( output, node.xml_decl.encoding ) - end - write_document( node, output ) - - when Element - write_element( node, output ) - - when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity, - Attribute, AttlistDecl - node.write( output,-1 ) - - when Instruction - write_instruction( node, output ) - - when DocType, XMLDecl - node.write( output ) - - when Comment - write_comment( node, output ) - - when CData - write_cdata( node, output ) - - when Text - write_text( node, output ) - - else - raise Exception.new("XML FORMATTING ERROR") - - end - end - - protected - def write_document( node, output ) - node.children.each { |child| write( child, output ) } - end - - def write_element( node, output ) - output << "<#{node.expanded_name}" - - node.attributes.to_a.map { |a| - Hash === a ? a.values : a - }.flatten.sort_by {|attr| attr.name}.each do |attr| - output << " " - attr.write( output ) - end unless node.attributes.empty? - - if node.children.empty? - output << " " if @ie_hack - output << "/" - else - output << ">" - node.children.each { |child| - write( child, output ) - } - output << "" - end - - def write_text( node, output ) - output << node.to_s() - end - - def write_comment( node, output ) - output << Comment::START - output << node.to_s - output << Comment::STOP - end - - def write_cdata( node, output ) - output << CData::START - output << node.to_s - output << CData::STOP - end - - def write_instruction( node, output ) - output << Instruction::START - output << node.target - content = node.content - if content - output << ' ' - output << content - end - output << Instruction::STOP - end - end - end -end diff --git a/ruby/lib/rexml/formatters/pretty.rb b/ruby/lib/rexml/formatters/pretty.rb deleted file mode 100644 index 562ef9462..000000000 --- a/ruby/lib/rexml/formatters/pretty.rb +++ /dev/null @@ -1,142 +0,0 @@ -# frozen_string_literal: false -require_relative 'default' - -module REXML - module Formatters - # Pretty-prints an XML document. This destroys whitespace in text nodes - # and will insert carriage returns and indentations. - # - # TODO: Add an option to print attributes on new lines - class Pretty < Default - - # If compact is set to true, then the formatter will attempt to use as - # little space as possible - attr_accessor :compact - # The width of a page. Used for formatting text - attr_accessor :width - - # Create a new pretty printer. - # - # output:: - # An object implementing '<<(String)', to which the output will be written. - # indentation:: - # An integer greater than 0. The indentation of each level will be - # this number of spaces. If this is < 1, the behavior of this object - # is undefined. Defaults to 2. - # ie_hack:: - # If true, the printer will insert whitespace before closing empty - # tags, thereby allowing Internet Explorer's XML parser to - # function. Defaults to false. - def initialize( indentation=2, ie_hack=false ) - @indentation = indentation - @level = 0 - @ie_hack = ie_hack - @width = 80 - @compact = false - end - - protected - def write_element(node, output) - output << ' '*@level - output << "<#{node.expanded_name}" - - node.attributes.each_attribute do |attr| - output << " " - attr.write( output ) - end unless node.attributes.empty? - - if node.children.empty? - if @ie_hack - output << " " - end - output << "/" - else - output << ">" - # If compact and all children are text, and if the formatted output - # is less than the specified width, then try to print everything on - # one line - skip = false - if compact - if node.children.inject(true) {|s,c| s & c.kind_of?(Text)} - string = "" - old_level = @level - @level = 0 - node.children.each { |child| write( child, string ) } - @level = old_level - if string.length < @width - output << string - skip = true - end - end - end - unless skip - output << "\n" - @level += @indentation - node.children.each { |child| - next if child.kind_of?(Text) and child.to_s.strip.length == 0 - write( child, output ) - output << "\n" - } - @level -= @indentation - output << ' '*@level - end - output << "" - end - - def write_text( node, output ) - s = node.to_s() - s.gsub!(/\s/,' ') - s.squeeze!(" ") - s = wrap(s, @width - @level) - s = indent_text(s, @level, " ", true) - output << (' '*@level + s) - end - - def write_comment( node, output) - output << ' ' * @level - super - end - - def write_cdata( node, output) - output << ' ' * @level - super - end - - def write_document( node, output ) - # Ok, this is a bit odd. All XML documents have an XML declaration, - # but it may not write itself if the user didn't specifically add it, - # either through the API or in the input document. If it doesn't write - # itself, then we don't need a carriage return... which makes this - # logic more complex. - node.children.each { |child| - next if child == node.children[-1] and child.instance_of?(Text) - unless child == node.children[0] or child.instance_of?(Text) or - (child == node.children[1] and !node.children[0].writethis) - output << "\n" - end - write( child, output ) - } - end - - private - def indent_text(string, level=1, style="\t", indentfirstline=true) - return string if level < 0 - string.gsub(/\n/, "\n#{style*level}") - end - - def wrap(string, width) - parts = [] - while string.length > width and place = string.rindex(' ', width) - parts << string[0...place] - string = string[place+1..-1] - end - parts << string - parts.join("\n") - end - - end - end -end - diff --git a/ruby/lib/rexml/formatters/transitive.rb b/ruby/lib/rexml/formatters/transitive.rb deleted file mode 100644 index 5ff51e10f..000000000 --- a/ruby/lib/rexml/formatters/transitive.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: false -require_relative 'pretty' - -module REXML - module Formatters - # The Transitive formatter writes an XML document that parses to an - # identical document as the source document. This means that no extra - # whitespace nodes are inserted, and whitespace within text nodes is - # preserved. Within these constraints, the document is pretty-printed, - # with whitespace inserted into the metadata to introduce formatting. - # - # Note that this is only useful if the original XML is not already - # formatted. Since this formatter does not alter whitespace nodes, the - # results of formatting already formatted XML will be odd. - class Transitive < Default - def initialize( indentation=2, ie_hack=false ) - @indentation = indentation - @level = 0 - @ie_hack = ie_hack - end - - protected - def write_element( node, output ) - output << "<#{node.expanded_name}" - - node.attributes.each_attribute do |attr| - output << " " - attr.write( output ) - end unless node.attributes.empty? - - output << "\n" - output << ' '*@level - if node.children.empty? - output << " " if @ie_hack - output << "/" - else - output << ">" - # If compact and all children are text, and if the formatted output - # is less than the specified width, then try to print everything on - # one line - @level += @indentation - node.children.each { |child| - write( child, output ) - } - @level -= @indentation - output << "" - end - - def write_text( node, output ) - output << node.to_s() - end - end - end -end diff --git a/ruby/lib/rexml/functions.rb b/ruby/lib/rexml/functions.rb deleted file mode 100644 index 77926bf2a..000000000 --- a/ruby/lib/rexml/functions.rb +++ /dev/null @@ -1,447 +0,0 @@ -# frozen_string_literal: false -module REXML - # If you add a method, keep in mind two things: - # (1) the first argument will always be a list of nodes from which to - # filter. In the case of context methods (such as position), the function - # should return an array with a value for each child in the array. - # (2) all method calls from XML will have "-" replaced with "_". - # Therefore, in XML, "local-name()" is identical (and actually becomes) - # "local_name()" - module Functions - @@available_functions = {} - @@context = nil - @@namespace_context = {} - @@variables = {} - - INTERNAL_METHODS = [ - :namespace_context, - :namespace_context=, - :variables, - :variables=, - :context=, - :get_namespace, - :send, - ] - class << self - def singleton_method_added(name) - unless INTERNAL_METHODS.include?(name) - @@available_functions[name] = true - end - end - end - - def Functions::namespace_context=(x) ; @@namespace_context=x ; end - def Functions::variables=(x) ; @@variables=x ; end - def Functions::namespace_context ; @@namespace_context ; end - def Functions::variables ; @@variables ; end - - def Functions::context=(value); @@context = value; end - - def Functions::text( ) - if @@context[:node].node_type == :element - return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value} - elsif @@context[:node].node_type == :text - return @@context[:node].value - else - return false - end - end - - # Returns the last node of the given list of nodes. - def Functions::last( ) - @@context[:size] - end - - def Functions::position( ) - @@context[:index] - end - - # Returns the size of the given list of nodes. - def Functions::count( node_set ) - node_set.size - end - - # Since REXML is non-validating, this method is not implemented as it - # requires a DTD - def Functions::id( object ) - end - - def Functions::local_name(node_set=nil) - get_namespace(node_set) do |node| - return node.local_name - end - "" - end - - def Functions::namespace_uri( node_set=nil ) - get_namespace( node_set ) {|node| node.namespace} - end - - def Functions::name( node_set=nil ) - get_namespace( node_set ) do |node| - node.expanded_name - end - end - - # Helper method. - def Functions::get_namespace( node_set = nil ) - if node_set == nil - yield @@context[:node] if @@context[:node].respond_to?(:namespace) - else - if node_set.respond_to? :each - result = [] - node_set.each do |node| - result << yield(node) if node.respond_to?(:namespace) - end - result - elsif node_set.respond_to? :namespace - yield node_set - end - end - end - - # A node-set is converted to a string by returning the string-value of the - # node in the node-set that is first in document order. If the node-set is - # empty, an empty string is returned. - # - # A number is converted to a string as follows - # - # NaN is converted to the string NaN - # - # positive zero is converted to the string 0 - # - # negative zero is converted to the string 0 - # - # positive infinity is converted to the string Infinity - # - # negative infinity is converted to the string -Infinity - # - # if the number is an integer, the number is represented in decimal form - # as a Number with no decimal point and no leading zeros, preceded by a - # minus sign (-) if the number is negative - # - # otherwise, the number is represented in decimal form as a Number - # including a decimal point with at least one digit before the decimal - # point and at least one digit after the decimal point, preceded by a - # minus sign (-) if the number is negative; there must be no leading zeros - # before the decimal point apart possibly from the one required digit - # immediately before the decimal point; beyond the one required digit - # after the decimal point there must be as many, but only as many, more - # digits as are needed to uniquely distinguish the number from all other - # IEEE 754 numeric values. - # - # The boolean false value is converted to the string false. The boolean - # true value is converted to the string true. - # - # An object of a type other than the four basic types is converted to a - # string in a way that is dependent on that type. - def Functions::string( object=@@context[:node] ) - if object.respond_to?(:node_type) - case object.node_type - when :attribute - object.value - when :element - string_value(object) - when :document - string_value(object.root) - when :processing_instruction - object.content - else - object.to_s - end - else - case object - when Array - string(object[0]) - when Float - if object.nan? - "NaN" - else - integer = object.to_i - if object == integer - "%d" % integer - else - object.to_s - end - end - else - object.to_s - end - end - end - - # A node-set is converted to a string by - # returning the concatenation of the string-value - # of each of the children of the node in the - # node-set that is first in document order. - # If the node-set is empty, an empty string is returned. - def Functions::string_value( o ) - rv = "" - o.children.each { |e| - if e.node_type == :text - rv << e.to_s - elsif e.node_type == :element - rv << string_value( e ) - end - } - rv - end - - def Functions::concat( *objects ) - concatenated = "" - objects.each do |object| - concatenated << string(object) - end - concatenated - end - - # Fixed by Mike Stok - def Functions::starts_with( string, test ) - string(string).index(string(test)) == 0 - end - - # Fixed by Mike Stok - def Functions::contains( string, test ) - string(string).include?(string(test)) - end - - # Kouhei fixed this - def Functions::substring_before( string, test ) - ruby_string = string(string) - ruby_index = ruby_string.index(string(test)) - if ruby_index.nil? - "" - else - ruby_string[ 0...ruby_index ] - end - end - - # Kouhei fixed this too - def Functions::substring_after( string, test ) - ruby_string = string(string) - return $1 if ruby_string =~ /#{test}(.*)/ - "" - end - - # Take equal portions of Mike Stok and Sean Russell; mix - # vigorously, and pour into a tall, chilled glass. Serves 10,000. - def Functions::substring( string, start, length=nil ) - ruby_string = string(string) - ruby_length = if length.nil? - ruby_string.length.to_f - else - number(length) - end - ruby_start = number(start) - - # Handle the special cases - return '' if ( - ruby_length.nan? or - ruby_start.nan? or - ruby_start.infinite? - ) - - infinite_length = ruby_length.infinite? == 1 - ruby_length = ruby_string.length if infinite_length - - # Now, get the bounds. The XPath bounds are 1..length; the ruby bounds - # are 0..length. Therefore, we have to offset the bounds by one. - ruby_start = round(ruby_start) - 1 - ruby_length = round(ruby_length) - - if ruby_start < 0 - ruby_length += ruby_start unless infinite_length - ruby_start = 0 - end - return '' if ruby_length <= 0 - ruby_string[ruby_start,ruby_length] - end - - # UNTESTED - def Functions::string_length( string ) - string(string).length - end - - # UNTESTED - def Functions::normalize_space( string=nil ) - string = string(@@context[:node]) if string.nil? - if string.kind_of? Array - string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string} - else - string.to_s.strip.gsub(/\s+/um, ' ') - end - end - - # This is entirely Mike Stok's beast - def Functions::translate( string, tr1, tr2 ) - from = string(tr1) - to = string(tr2) - - # the map is our translation table. - # - # if a character occurs more than once in the - # from string then we ignore the second & - # subsequent mappings - # - # if a character maps to nil then we delete it - # in the output. This happens if the from - # string is longer than the to string - # - # there's nothing about - or ^ being special in - # http://www.w3.org/TR/xpath#function-translate - # so we don't build ranges or negated classes - - map = Hash.new - 0.upto(from.length - 1) { |pos| - from_char = from[pos] - unless map.has_key? from_char - map[from_char] = - if pos < to.length - to[pos] - else - nil - end - end - } - - if ''.respond_to? :chars - string(string).chars.collect { |c| - if map.has_key? c then map[c] else c end - }.compact.join - else - string(string).unpack('U*').collect { |c| - if map.has_key? c then map[c] else c end - }.compact.pack('U*') - end - end - - def Functions::boolean(object=@@context[:node]) - case object - when true, false - object - when Float - return false if object.zero? - return false if object.nan? - true - when Numeric - not object.zero? - when String - not object.empty? - when Array - not object.empty? - else - object ? true : false - end - end - - # UNTESTED - def Functions::not( object ) - not boolean( object ) - end - - # UNTESTED - def Functions::true( ) - true - end - - # UNTESTED - def Functions::false( ) - false - end - - # UNTESTED - def Functions::lang( language ) - lang = false - node = @@context[:node] - attr = nil - until node.nil? - if node.node_type == :element - attr = node.attributes["xml:lang"] - unless attr.nil? - lang = compare_language(string(language), attr) - break - else - end - end - node = node.parent - end - lang - end - - def Functions::compare_language lang1, lang2 - lang2.downcase.index(lang1.downcase) == 0 - end - - # a string that consists of optional whitespace followed by an optional - # minus sign followed by a Number followed by whitespace is converted to - # the IEEE 754 number that is nearest (according to the IEEE 754 - # round-to-nearest rule) to the mathematical value represented by the - # string; any other string is converted to NaN - # - # boolean true is converted to 1; boolean false is converted to 0 - # - # a node-set is first converted to a string as if by a call to the string - # function and then converted in the same way as a string argument - # - # an object of a type other than the four basic types is converted to a - # number in a way that is dependent on that type - def Functions::number(object=@@context[:node]) - case object - when true - Float(1) - when false - Float(0) - when Array - number(string(object)) - when Numeric - object.to_f - else - str = string(object) - case str.strip - when /\A\s*(-?(?:\d+(?:\.\d*)?|\.\d+))\s*\z/ - $1.to_f - else - Float::NAN - end - end - end - - def Functions::sum( nodes ) - nodes = [nodes] unless nodes.kind_of? Array - nodes.inject(0) { |r,n| r + number(string(n)) } - end - - def Functions::floor( number ) - number(number).floor - end - - def Functions::ceiling( number ) - number(number).ceil - end - - def Functions::round( number ) - number = number(number) - begin - neg = number.negative? - number = number.abs.round - neg ? -number : number - rescue FloatDomainError - number - end - end - - def Functions::processing_instruction( node ) - node.node_type == :processing_instruction - end - - def Functions::send(name, *args) - if @@available_functions[name.to_sym] - super - else - # TODO: Maybe, this is not XPath spec behavior. - # This behavior must be reconsidered. - XPath.match(@@context[:node], name.to_s) - end - end - end -end diff --git a/ruby/lib/rexml/instruction.rb b/ruby/lib/rexml/instruction.rb deleted file mode 100644 index 318741f03..000000000 --- a/ruby/lib/rexml/instruction.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: false - -require_relative "child" -require_relative "source" - -module REXML - # Represents an XML Instruction; IE, - # TODO: Add parent arg (3rd arg) to constructor - class Instruction < Child - START = "" - - # target is the "name" of the Instruction; IE, the "tag" in - # content is everything else. - attr_accessor :target, :content - - # Constructs a new Instruction - # @param target can be one of a number of things. If String, then - # the target of this instruction is set to this. If an Instruction, - # then the Instruction is shallowly cloned (target and content are - # copied). - # @param content Must be either a String, or a Parent. Can only - # be a Parent if the target argument is a Source. Otherwise, this - # String is set as the content of this instruction. - def initialize(target, content=nil) - case target - when String - super() - @target = target - @content = content - when Instruction - super(content) - @target = target.target - @content = target.content - else - message = - "processing instruction target must be String or REXML::Instruction: " - message << "<#{target.inspect}>" - raise ArgumentError, message - end - @content.strip! if @content - end - - def clone - Instruction.new self - end - - # == DEPRECATED - # See the rexml/formatters package - # - def write writer, indent=-1, transitive=false, ie_hack=false - Kernel.warn( "#{self.class.name}.write is deprecated", uplevel: 1) - indent(writer, indent) - writer << START - writer << @target - if @content - writer << ' ' - writer << @content - end - writer << STOP - end - - # @return true if other is an Instruction, and the content and target - # of the other matches the target and content of this object. - def ==( other ) - other.kind_of? Instruction and - other.target == @target and - other.content == @content - end - - def node_type - :processing_instruction - end - - def inspect - "" - end - end -end diff --git a/ruby/lib/rexml/light/node.rb b/ruby/lib/rexml/light/node.rb deleted file mode 100644 index 01177c64d..000000000 --- a/ruby/lib/rexml/light/node.rb +++ /dev/null @@ -1,196 +0,0 @@ -# frozen_string_literal: false -require_relative '../xmltokens' - -# [ :element, parent, name, attributes, children* ] - # a = Node.new - # a << "B" # => B - # a.b # => B - # a.b[1] # => B - # a.b[1]["x"] = "y" # => B - # a.b[0].c # => B - # a.b.c << "D" # => BD -module REXML - module Light - # Represents a tagged XML element. Elements are characterized by - # having children, attributes, and names, and can themselves be - # children. - class Node - NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u - PARENTS = [ :element, :document, :doctype ] - # Create a new element. - def initialize node=nil - @node = node - if node.kind_of? String - node = [ :text, node ] - elsif node.nil? - node = [ :document, nil, nil ] - elsif node[0] == :start_element - node[0] = :element - elsif node[0] == :start_doctype - node[0] = :doctype - elsif node[0] == :start_document - node[0] = :document - end - end - - def size - if PARENTS.include? @node[0] - @node[-1].size - else - 0 - end - end - - def each - size.times { |x| yield( at(x+4) ) } - end - - def name - at(2) - end - - def name=( name_str, ns=nil ) - pfx = '' - pfx = "#{prefix(ns)}:" if ns - _old_put(2, "#{pfx}#{name_str}") - end - - def parent=( node ) - _old_put(1,node) - end - - def local_name - namesplit - @name - end - - def local_name=( name_str ) - _old_put( 1, "#@prefix:#{name_str}" ) - end - - def prefix( namespace=nil ) - prefix_of( self, namespace ) - end - - def namespace( prefix=prefix() ) - namespace_of( self, prefix ) - end - - def namespace=( namespace ) - @prefix = prefix( namespace ) - pfx = '' - pfx = "#@prefix:" if @prefix.size > 0 - _old_put(1, "#{pfx}#@name") - end - - def []( reference, ns=nil ) - if reference.kind_of? String - pfx = '' - pfx = "#{prefix(ns)}:" if ns - at(3)["#{pfx}#{reference}"] - elsif reference.kind_of? Range - _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) ) - else - _old_get( 4+reference ) - end - end - - def =~( path ) - XPath.match( self, path ) - end - - # Doesn't handle namespaces yet - def []=( reference, ns, value=nil ) - if reference.kind_of? String - value = ns unless value - at( 3 )[reference] = value - elsif reference.kind_of? Range - _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns ) - else - if value - _old_put( 4+reference, ns, value ) - else - _old_put( 4+reference, ns ) - end - end - end - - # Append a child to this element, optionally under a provided namespace. - # The namespace argument is ignored if the element argument is an Element - # object. Otherwise, the element argument is a string, the namespace (if - # provided) is the namespace the element is created in. - def << element - if node_type() == :text - at(-1) << element - else - newnode = Node.new( element ) - newnode.parent = self - self.push( newnode ) - end - at(-1) - end - - def node_type - _old_get(0) - end - - def text=( foo ) - replace = at(4).kind_of?(String)? 1 : 0 - self._old_put(4,replace, normalizefoo) - end - - def root - context = self - context = context.at(1) while context.at(1) - end - - def has_name?( name, namespace = '' ) - at(3) == name and namespace() == namespace - end - - def children - self - end - - def parent - at(1) - end - - def to_s - - end - - private - - def namesplit - return if @name.defined? - at(2) =~ NAMESPLIT - @prefix = '' || $1 - @name = $2 - end - - def namespace_of( node, prefix=nil ) - if not prefix - name = at(2) - name =~ NAMESPLIT - prefix = $1 - end - to_find = 'xmlns' - to_find = "xmlns:#{prefix}" if not prefix.nil? - ns = at(3)[ to_find ] - ns ? ns : namespace_of( @node[0], prefix ) - end - - def prefix_of( node, namespace=nil ) - if not namespace - name = node.name - name =~ NAMESPLIT - $1 - else - ns = at(3).find { |k,v| v == namespace } - ns ? ns : prefix_of( node.parent, namespace ) - end - end - end - end -end diff --git a/ruby/lib/rexml/namespace.rb b/ruby/lib/rexml/namespace.rb deleted file mode 100644 index 924edf950..000000000 --- a/ruby/lib/rexml/namespace.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: false - -require_relative 'xmltokens' - -module REXML - # Adds named attributes to an object. - module Namespace - # The name of the object, valid if set - attr_reader :name, :expanded_name - # The expanded name of the object, valid if name is set - attr_accessor :prefix - include XMLTokens - NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u - - # Sets the name and the expanded name - def name=( name ) - @expanded_name = name - case name - when NAMESPLIT - if $1 - @prefix = $1 - else - @prefix = "" - @namespace = "" - end - @name = $2 - when "" - @prefix = nil - @namespace = nil - @name = nil - else - message = "name must be \#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: " - message += "<#{name.inspect}>" - raise ArgumentError, message - end - end - - # Compares names optionally WITH namespaces - def has_name?( other, ns=nil ) - if ns - return (namespace() == ns and name() == other) - elsif other.include? ":" - return fully_expanded_name == other - else - return name == other - end - end - - alias :local_name :name - - # Fully expand the name, even if the prefix wasn't specified in the - # source file. - def fully_expanded_name - ns = prefix - return "#{ns}:#@name" if ns.size > 0 - return @name - end - end -end diff --git a/ruby/lib/rexml/node.rb b/ruby/lib/rexml/node.rb deleted file mode 100644 index 081caba6c..000000000 --- a/ruby/lib/rexml/node.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: false -require_relative "parseexception" -require_relative "formatters/pretty" -require_relative "formatters/default" - -module REXML - # Represents a node in the tree. Nodes are never encountered except as - # superclasses of other objects. Nodes have siblings. - module Node - # @return the next sibling (nil if unset) - def next_sibling_node - return nil if @parent.nil? - @parent[ @parent.index(self) + 1 ] - end - - # @return the previous sibling (nil if unset) - def previous_sibling_node - return nil if @parent.nil? - ind = @parent.index(self) - return nil if ind == 0 - @parent[ ind - 1 ] - end - - # indent:: - # *DEPRECATED* This parameter is now ignored. See the formatters in the - # REXML::Formatters package for changing the output style. - def to_s indent=nil - unless indent.nil? - Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated", uplevel: 1) - f = REXML::Formatters::Pretty.new( indent ) - f.write( self, rv = "" ) - else - f = REXML::Formatters::Default.new - f.write( self, rv = "" ) - end - return rv - end - - def indent to, ind - if @parent and @parent.context and not @parent.context[:indentstyle].nil? then - indentstyle = @parent.context[:indentstyle] - else - indentstyle = ' ' - end - to << indentstyle*ind unless ind<1 - end - - def parent? - false; - end - - - # Visit all subnodes of +self+ recursively - def each_recursive(&block) # :yields: node - self.elements.each {|node| - block.call(node) - node.each_recursive(&block) - } - end - - # Find (and return) first subnode (recursively) for which the block - # evaluates to true. Returns +nil+ if none was found. - def find_first_recursive(&block) # :yields: node - each_recursive {|node| - return node if block.call(node) - } - return nil - end - - # Returns the position that +self+ holds in its parent's array, indexed - # from 1. - def index_in_parent - parent.index(self)+1 - end - end -end diff --git a/ruby/lib/rexml/output.rb b/ruby/lib/rexml/output.rb deleted file mode 100644 index 88a5fb378..000000000 --- a/ruby/lib/rexml/output.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: false -require_relative 'encoding' - -module REXML - class Output - include Encoding - - attr_reader :encoding - - def initialize real_IO, encd="iso-8859-1" - @output = real_IO - self.encoding = encd - - @to_utf = encoding != 'UTF-8' - - if encoding == "UTF-16" - @output << "\ufeff".encode("UTF-16BE") - self.encoding = "UTF-16BE" - end - end - - def <<( content ) - @output << (@to_utf ? self.encode(content) : content) - end - - def to_s - "Output[#{encoding}]" - end - end -end diff --git a/ruby/lib/rexml/parent.rb b/ruby/lib/rexml/parent.rb deleted file mode 100644 index 6a53b37a1..000000000 --- a/ruby/lib/rexml/parent.rb +++ /dev/null @@ -1,166 +0,0 @@ -# frozen_string_literal: false -require_relative "child" - -module REXML - # A parent has children, and has methods for accessing them. The Parent - # class is never encountered except as the superclass for some other - # object. - class Parent < Child - include Enumerable - - # Constructor - # @param parent if supplied, will be set as the parent of this object - def initialize parent=nil - super(parent) - @children = [] - end - - def add( object ) - object.parent = self - @children << object - object - end - - alias :push :add - alias :<< :push - - def unshift( object ) - object.parent = self - @children.unshift object - end - - def delete( object ) - found = false - @children.delete_if {|c| c.equal?(object) and found = true } - object.parent = nil if found - found ? object : nil - end - - def each(&block) - @children.each(&block) - end - - def delete_if( &block ) - @children.delete_if(&block) - end - - def delete_at( index ) - @children.delete_at index - end - - def each_index( &block ) - @children.each_index(&block) - end - - # Fetches a child at a given index - # @param index the Integer index of the child to fetch - def []( index ) - @children[index] - end - - alias :each_child :each - - - - # Set an index entry. See Array.[]= - # @param index the index of the element to set - # @param opt either the object to set, or an Integer length - # @param child if opt is an Integer, this is the child to set - # @return the parent (self) - def []=( *args ) - args[-1].parent = self - @children[*args[0..-2]] = args[-1] - end - - # Inserts an child before another child - # @param child1 this is either an xpath or an Element. If an Element, - # child2 will be inserted before child1 in the child list of the parent. - # If an xpath, child2 will be inserted before the first child to match - # the xpath. - # @param child2 the child to insert - # @return the parent (self) - def insert_before( child1, child2 ) - if child1.kind_of? String - child1 = XPath.first( self, child1 ) - child1.parent.insert_before child1, child2 - else - ind = index(child1) - child2.parent.delete(child2) if child2.parent - @children[ind,0] = child2 - child2.parent = self - end - self - end - - # Inserts an child after another child - # @param child1 this is either an xpath or an Element. If an Element, - # child2 will be inserted after child1 in the child list of the parent. - # If an xpath, child2 will be inserted after the first child to match - # the xpath. - # @param child2 the child to insert - # @return the parent (self) - def insert_after( child1, child2 ) - if child1.kind_of? String - child1 = XPath.first( self, child1 ) - child1.parent.insert_after child1, child2 - else - ind = index(child1)+1 - child2.parent.delete(child2) if child2.parent - @children[ind,0] = child2 - child2.parent = self - end - self - end - - def to_a - @children.dup - end - - # Fetches the index of a given child - # @param child the child to get the index of - # @return the index of the child, or nil if the object is not a child - # of this parent. - def index( child ) - count = -1 - @children.find { |i| count += 1 ; i.hash == child.hash } - count - end - - # @return the number of children of this parent - def size - @children.size - end - - alias :length :size - - # Replaces one child with another, making sure the nodelist is correct - # @param to_replace the child to replace (must be a Child) - # @param replacement the child to insert into the nodelist (must be a - # Child) - def replace_child( to_replace, replacement ) - @children.map! {|c| c.equal?( to_replace ) ? replacement : c } - to_replace.parent = nil - replacement.parent = self - end - - # Deeply clones this object. This creates a complete duplicate of this - # Parent, including all descendants. - def deep_clone - cl = clone() - each do |child| - if child.kind_of? Parent - cl << child.deep_clone - else - cl << child.clone - end - end - cl - end - - alias :children :to_a - - def parent? - true - end - end -end diff --git a/ruby/lib/rexml/parseexception.rb b/ruby/lib/rexml/parseexception.rb deleted file mode 100644 index 7b16cd1a4..000000000 --- a/ruby/lib/rexml/parseexception.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: false -module REXML - class ParseException < RuntimeError - attr_accessor :source, :parser, :continued_exception - - def initialize( message, source=nil, parser=nil, exception=nil ) - super(message) - @source = source - @parser = parser - @continued_exception = exception - end - - def to_s - # Quote the original exception, if there was one - if @continued_exception - err = @continued_exception.inspect - err << "\n" - err << @continued_exception.backtrace.join("\n") - err << "\n...\n" - else - err = "" - end - - # Get the stack trace and error message - err << super - - # Add contextual information - if @source - err << "\nLine: #{line}\n" - err << "Position: #{position}\n" - err << "Last 80 unconsumed characters:\n" - err << @source.buffer[0..80].force_encoding("ASCII-8BIT").gsub(/\n/, ' ') - end - - err - end - - def position - @source.current_line[0] if @source and defined? @source.current_line and - @source.current_line - end - - def line - @source.current_line[2] if @source and defined? @source.current_line and - @source.current_line - end - - def context - @source.current_line - end - end -end diff --git a/ruby/lib/rexml/parsers/baseparser.rb b/ruby/lib/rexml/parsers/baseparser.rb deleted file mode 100644 index f76aed078..000000000 --- a/ruby/lib/rexml/parsers/baseparser.rb +++ /dev/null @@ -1,594 +0,0 @@ -# frozen_string_literal: false -require_relative '../parseexception' -require_relative '../undefinednamespaceexception' -require_relative '../source' -require 'set' -require "strscan" - -module REXML - module Parsers - # = Using the Pull Parser - # This API is experimental, and subject to change. - # parser = PullParser.new( "texttxet" ) - # while parser.has_next? - # res = parser.next - # puts res[1]['att'] if res.start_tag? and res[0] == 'b' - # end - # See the PullEvent class for information on the content of the results. - # The data is identical to the arguments passed for the various events to - # the StreamListener API. - # - # Notice that: - # parser = PullParser.new( "BAD DOCUMENT" ) - # while parser.has_next? - # res = parser.next - # raise res[1] if res.error? - # end - # - # Nat Price gave me some good ideas for the API. - class BaseParser - LETTER = '[:alpha:]' - DIGIT = '[:digit:]' - - COMBININGCHAR = '' # TODO - EXTENDER = '' # TODO - - NCNAME_STR= "[#{LETTER}_][-[:alnum:]._#{COMBININGCHAR}#{EXTENDER}]*" - QNAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})" - QNAME = /(#{QNAME_STR})/ - - # Just for backward compatibility. For example, kramdown uses this. - # It's not used in REXML. - UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" - - NAMECHAR = '[\-\w\.:]' - NAME = "([\\w:]#{NAMECHAR}*)" - NMTOKEN = "(?:#{NAMECHAR})+" - NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*" - REFERENCE = "&(?:#{NAME};|#\\d+;|#x[0-9a-fA-F]+;)" - REFERENCE_RE = /#{REFERENCE}/ - - DOCTYPE_START = /\A\s*/um - DOCTYPE_PATTERN = /\s*)/um - ATTRIBUTE_PATTERN = /\s*(#{QNAME_STR})\s*=\s*(["'])(.*?)\4/um - COMMENT_START = /\A/um - CDATA_START = /\A/um - CDATA_PATTERN = //um - XMLDECL_START = /\A<\?xml\s/u; - XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um - INSTRUCTION_START = /\A<\?/u - INSTRUCTION_PATTERN = /<\?#{NAME}(\s+.*?)?\?>/um - TAG_MATCH = /^<((?>#{QNAME_STR}))/um - CLOSE_MATCH = /^\s*<\/(#{QNAME_STR})\s*>/um - - VERSION = /\bversion\s*=\s*["'](.*?)['"]/um - ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um - STANDALONE = /\bstandalone\s*=\s*["'](.*?)['"]/um - - ENTITY_START = /\A\s*/um - SYSTEMENTITY = /\A\s*(%.*?;)\s*$/um - ENUMERATION = "\\(\\s*#{NMTOKEN}(?:\\s*\\|\\s*#{NMTOKEN})*\\s*\\)" - NOTATIONTYPE = "NOTATION\\s+\\(\\s*#{NAME}(?:\\s*\\|\\s*#{NAME})*\\s*\\)" - ENUMERATEDTYPE = "(?:(?:#{NOTATIONTYPE})|(?:#{ENUMERATION}))" - ATTTYPE = "(CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS|#{ENUMERATEDTYPE})" - ATTVALUE = "(?:\"((?:[^<&\"]|#{REFERENCE})*)\")|(?:'((?:[^<&']|#{REFERENCE})*)')" - DEFAULTDECL = "(#REQUIRED|#IMPLIED|(?:(#FIXED\\s+)?#{ATTVALUE}))" - ATTDEF = "\\s+#{NAME}\\s+#{ATTTYPE}\\s+#{DEFAULTDECL}" - ATTDEF_RE = /#{ATTDEF}/ - ATTLISTDECL_START = /\A\s*/um - NOTATIONDECL_START = /\A\s*/um - SYSTEM = /\A\s*/um - - TEXT_PATTERN = /\A([^<]*)/um - - # Entity constants - PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#" - SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))} - PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')} - EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" - NDATADECL = "\\s+NDATA\\s+#{NAME}" - PEREFERENCE = "%#{NAME};" - ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} - PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" - ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" - PEDECL = "" - GEDECL = "" - ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um - - EREFERENCE = /&(?!#{NAME};)/ - - DEFAULT_ENTITIES = { - 'gt' => [/>/, '>', '>', />/], - 'lt' => [/</, '<', '<', / [/"/, '"', '"', /"/], - "apos" => [/'/, "'", "'", /'/] - } - - def initialize( source ) - self.stream = source - @listeners = [] - end - - def add_listener( listener ) - @listeners << listener - end - - attr_reader :source - - def stream=( source ) - @source = SourceFactory.create_from( source ) - @closed = nil - @document_status = nil - @tags = [] - @stack = [] - @entities = [] - @nsstack = [] - end - - def position - if @source.respond_to? :position - @source.position - else - # FIXME - 0 - end - end - - # Returns true if there are no more events - def empty? - return (@source.empty? and @stack.empty?) - end - - # Returns true if there are more events. Synonymous with !empty? - def has_next? - return !(@source.empty? and @stack.empty?) - end - - # Push an event back on the head of the stream. This method - # has (theoretically) infinite depth. - def unshift token - @stack.unshift(token) - end - - # Peek at the +depth+ event in the stack. The first element on the stack - # is at depth 0. If +depth+ is -1, will parse to the end of the input - # stream and return the last event, which is always :end_document. - # Be aware that this causes the stream to be parsed up to the +depth+ - # event, so you can effectively pre-parse the entire document (pull the - # entire thing into memory) using this method. - def peek depth=0 - raise %Q[Illegal argument "#{depth}"] if depth < -1 - temp = [] - if depth == -1 - temp.push(pull()) until empty? - else - while @stack.size+temp.size < depth+1 - temp.push(pull()) - end - end - @stack += temp if temp.size > 0 - @stack[depth] - end - - # Returns the next event. This is a +PullEvent+ object. - def pull - pull_event.tap do |event| - @listeners.each do |listener| - listener.receive event - end - end - end - - def pull_event - if @closed - x, @closed = @closed, nil - return [ :end_element, x ] - end - return [ :end_document ] if empty? - return @stack.shift if @stack.size > 0 - #STDERR.puts @source.encoding - @source.read if @source.buffer.size<2 - #STDERR.puts "BUFFER = #{@source.buffer.inspect}" - if @document_status == nil - #@source.consume( /^\s*/um ) - word = @source.match( /^((?:\s+)|(?:<[^>]*>))/um ) - word = word[1] unless word.nil? - #STDERR.puts "WORD = #{word.inspect}" - case word - when COMMENT_START - return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ] - when XMLDECL_START - #STDERR.puts "XMLDECL" - results = @source.match( XMLDECL_PATTERN, true )[1] - version = VERSION.match( results ) - version = version[1] unless version.nil? - encoding = ENCODING.match(results) - encoding = encoding[1] unless encoding.nil? - if need_source_encoding_update?(encoding) - @source.encoding = encoding - end - if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding - encoding = "UTF-16" - end - standalone = STANDALONE.match(results) - standalone = standalone[1] unless standalone.nil? - return [ :xmldecl, version, encoding, standalone ] - when INSTRUCTION_START - return process_instruction - when DOCTYPE_START - md = @source.match( DOCTYPE_PATTERN, true ) - @nsstack.unshift(curr_ns=Set.new) - identity = md[1] - close = md[2] - identity =~ IDENTITY - name = $1 - raise REXML::ParseException.new("DOCTYPE is missing a name") if name.nil? - pub_sys = $2.nil? ? nil : $2.strip - long_name = $4.nil? ? nil : $4.strip - uri = $6.nil? ? nil : $6.strip - args = [ :start_doctype, name, pub_sys, long_name, uri ] - if close == ">" - @document_status = :after_doctype - @source.read if @source.buffer.size<2 - md = @source.match(/^\s*/um, true) - @stack << [ :end_doctype ] - else - @document_status = :in_doctype - end - return args - when /^\s+/ - else - @document_status = :after_doctype - @source.read if @source.buffer.size<2 - md = @source.match(/\s*/um, true) - if @source.encoding == "UTF-8" - @source.buffer.force_encoding(::Encoding::UTF_8) - end - end - end - if @document_status == :in_doctype - md = @source.match(/\s*(.*?>)/um) - case md[1] - when SYSTEMENTITY - match = @source.match( SYSTEMENTITY, true )[1] - return [ :externalentity, match ] - - when ELEMENTDECL_START - return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ] - - when ENTITY_START - match = @source.match( ENTITYDECL, true ).to_a.compact - match[0] = :entitydecl - ref = false - if match[1] == '%' - ref = true - match.delete_at 1 - end - # Now we have to sort out what kind of entity reference this is - if match[2] == 'SYSTEM' - # External reference - match[3] = match[3][1..-2] # PUBID - match.delete_at(4) if match.size > 4 # Chop out NDATA decl - # match is [ :entity, name, SYSTEM, pubid(, ndata)? ] - elsif match[2] == 'PUBLIC' - # External reference - match[3] = match[3][1..-2] # PUBID - match[4] = match[4][1..-2] # HREF - match.delete_at(5) if match.size > 5 # Chop out NDATA decl - # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ] - else - match[2] = match[2][1..-2] - match.pop if match.size == 4 - # match is [ :entity, name, value ] - end - match << '%' if ref - return match - when ATTLISTDECL_START - md = @source.match( ATTLISTDECL_PATTERN, true ) - raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? - element = md[1] - contents = md[0] - - pairs = {} - values = md[0].scan( ATTDEF_RE ) - values.each do |attdef| - unless attdef[3] == "#IMPLIED" - attdef.compact! - val = attdef[3] - val = attdef[4] if val == "#FIXED " - pairs[attdef[0]] = val - if attdef[0] =~ /^xmlns:(.*)/ - @nsstack[0] << $1 - end - end - end - return [ :attlistdecl, element, pairs, contents ] - when NOTATIONDECL_START - md = nil - if @source.match( PUBLIC ) - md = @source.match( PUBLIC, true ) - vals = [md[1],md[2],md[4],md[6]] - elsif @source.match( SYSTEM ) - md = @source.match( SYSTEM, true ) - vals = [md[1],md[2],nil,md[4]] - else - raise REXML::ParseException.new( "error parsing notation: no matching pattern", @source ) - end - return [ :notationdecl, *vals ] - when DOCTYPE_END - @document_status = :after_doctype - @source.match( DOCTYPE_END, true ) - return [ :end_doctype ] - end - end - begin - if @source.buffer[0] == ?< - if @source.buffer[1] == ?/ - @nsstack.shift - last_tag = @tags.pop - md = @source.match( CLOSE_MATCH, true ) - if md and !last_tag - message = "Unexpected top-level end tag (got '#{md[1]}')" - raise REXML::ParseException.new(message, @source) - end - if md.nil? or last_tag != md[1] - message = "Missing end tag for '#{last_tag}'" - message << " (got '#{md[1]}')" if md - raise REXML::ParseException.new(message, @source) - end - return [ :end_element, last_tag ] - elsif @source.buffer[1] == ?! - md = @source.match(/\A(\s*[^>]*>)/um) - #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}" - raise REXML::ParseException.new("Malformed node", @source) unless md - if md[0][2] == ?- - md = @source.match( COMMENT_PATTERN, true ) - - case md[1] - when /--/, /-\z/ - raise REXML::ParseException.new("Malformed comment", @source) - end - - return [ :comment, md[1] ] if md - else - md = @source.match( CDATA_PATTERN, true ) - return [ :cdata, md[1] ] if md - end - raise REXML::ParseException.new( "Declarations can only occur "+ - "in the doctype declaration.", @source) - elsif @source.buffer[1] == ?? - return process_instruction - else - # Get the next tag - md = @source.match(TAG_MATCH, true) - unless md - raise REXML::ParseException.new("malformed XML: missing tag start", @source) - end - prefixes = Set.new - prefixes << md[2] if md[2] - @nsstack.unshift(curr_ns=Set.new) - attributes, closed = parse_attributes(prefixes, curr_ns) - # Verify that all of the prefixes have been defined - for prefix in prefixes - unless @nsstack.find{|k| k.member?(prefix)} - raise UndefinedNamespaceException.new(prefix,@source,self) - end - end - - if closed - @closed = md[1] - @nsstack.shift - else - @tags.push( md[1] ) - end - return [ :start_element, md[1], attributes ] - end - else - md = @source.match( TEXT_PATTERN, true ) - if md[0].length == 0 - @source.match( /(\s+)/, true ) - end - #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0 - #return [ :text, "" ] if md[0].length == 0 - # unnormalized = Text::unnormalize( md[1], self ) - # return PullEvent.new( :text, md[1], unnormalized ) - return [ :text, md[1] ] - end - rescue REXML::UndefinedNamespaceException - raise - rescue REXML::ParseException - raise - rescue => error - raise REXML::ParseException.new( "Exception parsing", - @source, self, (error ? error : $!) ) - end - return [ :dummy ] - end - private :pull_event - - def entity( reference, entities ) - value = nil - value = entities[ reference ] if entities - if not value - value = DEFAULT_ENTITIES[ reference ] - value = value[2] if value - end - unnormalize( value, entities ) if value - end - - # Escapes all possible entities - def normalize( input, entities=nil, entity_filter=nil ) - copy = input.clone - # Doing it like this rather than in a loop improves the speed - copy.gsub!( EREFERENCE, '&' ) - entities.each do |key, value| - copy.gsub!( value, "&#{key};" ) unless entity_filter and - entity_filter.include?(entity) - end if entities - copy.gsub!( EREFERENCE, '&' ) - DEFAULT_ENTITIES.each do |key, value| - copy.gsub!( value[3], value[1] ) - end - copy - end - - # Unescapes all possible entities - def unnormalize( string, entities=nil, filter=nil ) - rv = string.clone - rv.gsub!( /\r\n?/, "\n" ) - matches = rv.scan( REFERENCE_RE ) - return rv if matches.size == 0 - rv.gsub!( /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) { - m=$1 - m = "0#{m}" if m[0] == ?x - [Integer(m)].pack('U*') - } - matches.collect!{|x|x[0]}.compact! - if matches.size > 0 - matches.each do |entity_reference| - unless filter and filter.include?(entity_reference) - entity_value = entity( entity_reference, entities ) - if entity_value - re = /&#{entity_reference};/ - rv.gsub!( re, entity_value ) - else - er = DEFAULT_ENTITIES[entity_reference] - rv.gsub!( er[0], er[2] ) if er - end - end - end - rv.gsub!( /&/, '&' ) - end - rv - end - - private - def need_source_encoding_update?(xml_declaration_encoding) - return false if xml_declaration_encoding.nil? - return false if /\AUTF-16\z/i =~ xml_declaration_encoding - true - end - - def process_instruction - match_data = @source.match(INSTRUCTION_PATTERN, true) - unless match_data - message = "Invalid processing instruction node" - raise REXML::ParseException.new(message, @source) - end - [:processing_instruction, match_data[1], match_data[2]] - end - - def parse_attributes(prefixes, curr_ns) - attributes = {} - closed = false - match_data = @source.match(/^(.*?)(\/)?>/um, true) - if match_data.nil? - message = "Start tag isn't ended" - raise REXML::ParseException.new(message, @source) - end - - raw_attributes = match_data[1] - closed = !match_data[2].nil? - return attributes, closed if raw_attributes.nil? - return attributes, closed if raw_attributes.empty? - - scanner = StringScanner.new(raw_attributes) - until scanner.eos? - if scanner.scan(/\s+/) - break if scanner.eos? - end - - pos = scanner.pos - loop do - break if scanner.scan(ATTRIBUTE_PATTERN) - unless scanner.scan(QNAME) - message = "Invalid attribute name: <#{scanner.rest}>" - raise REXML::ParseException.new(message, @source) - end - name = scanner[0] - unless scanner.scan(/\s*=\s*/um) - message = "Missing attribute equal: <#{name}>" - raise REXML::ParseException.new(message, @source) - end - quote = scanner.scan(/['"]/) - unless quote - message = "Missing attribute value start quote: <#{name}>" - raise REXML::ParseException.new(message, @source) - end - unless scanner.scan(/.*#{Regexp.escape(quote)}/um) - match_data = @source.match(/^(.*?)(\/)?>/um, true) - if match_data - scanner << "/" if closed - scanner << ">" - scanner << match_data[1] - scanner.pos = pos - closed = !match_data[2].nil? - next - end - message = - "Missing attribute value end quote: <#{name}>: <#{quote}>" - raise REXML::ParseException.new(message, @source) - end - end - name = scanner[1] - prefix = scanner[2] - local_part = scanner[3] - # quote = scanner[4] - value = scanner[5] - if prefix == "xmlns" - if local_part == "xml" - if value != "http://www.w3.org/XML/1998/namespace" - msg = "The 'xml' prefix must not be bound to any other namespace "+ - "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" - raise REXML::ParseException.new( msg, @source, self ) - end - elsif local_part == "xmlns" - msg = "The 'xmlns' prefix must not be declared "+ - "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" - raise REXML::ParseException.new( msg, @source, self) - end - curr_ns << local_part - elsif prefix - prefixes << prefix unless prefix == "xml" - end - - if attributes.has_key?(name) - msg = "Duplicate attribute #{name.inspect}" - raise REXML::ParseException.new(msg, @source, self) - end - - attributes[name] = value - end - return attributes, closed - end - end - end -end - -=begin - case event[0] - when :start_element - when :text - when :end_element - when :processing_instruction - when :cdata - when :comment - when :xmldecl - when :start_doctype - when :end_doctype - when :externalentity - when :elementdecl - when :entity - when :attlistdecl - when :notationdecl - when :end_doctype - end -=end diff --git a/ruby/lib/rexml/parsers/lightparser.rb b/ruby/lib/rexml/parsers/lightparser.rb deleted file mode 100644 index bdc08276a..000000000 --- a/ruby/lib/rexml/parsers/lightparser.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: false -require_relative 'streamparser' -require_relative 'baseparser' -require_relative '../light/node' - -module REXML - module Parsers - class LightParser - def initialize stream - @stream = stream - @parser = REXML::Parsers::BaseParser.new( stream ) - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - - def rewind - @stream.rewind - @parser.stream = @stream - end - - def parse - root = context = [ :document ] - while true - event = @parser.pull - case event[0] - when :end_document - break - when :start_element, :start_doctype - new_node = event - context << new_node - new_node[1,0] = [context] - context = new_node - when :end_element, :end_doctype - context = context[1] - else - new_node = event - context << new_node - new_node[1,0] = [context] - end - end - root - end - end - - # An element is an array. The array contains: - # 0 The parent element - # 1 The tag name - # 2 A hash of attributes - # 3..-1 The child elements - # An element is an array of size > 3 - # Text is a String - # PIs are [ :processing_instruction, target, data ] - # Comments are [ :comment, data ] - # DocTypes are DocType structs - # The root is an array with XMLDecls, Text, DocType, Array, Text - end -end diff --git a/ruby/lib/rexml/parsers/pullparser.rb b/ruby/lib/rexml/parsers/pullparser.rb deleted file mode 100644 index f8b232a2c..000000000 --- a/ruby/lib/rexml/parsers/pullparser.rb +++ /dev/null @@ -1,197 +0,0 @@ -# frozen_string_literal: false -require 'forwardable' - -require_relative '../parseexception' -require_relative 'baseparser' -require_relative '../xmltokens' - -module REXML - module Parsers - # = Using the Pull Parser - # This API is experimental, and subject to change. - # parser = PullParser.new( "texttxet" ) - # while parser.has_next? - # res = parser.next - # puts res[1]['att'] if res.start_tag? and res[0] == 'b' - # end - # See the PullEvent class for information on the content of the results. - # The data is identical to the arguments passed for the various events to - # the StreamListener API. - # - # Notice that: - # parser = PullParser.new( "BAD DOCUMENT" ) - # while parser.has_next? - # res = parser.next - # raise res[1] if res.error? - # end - # - # Nat Price gave me some good ideas for the API. - class PullParser - include XMLTokens - extend Forwardable - - def_delegators( :@parser, :has_next? ) - def_delegators( :@parser, :entity ) - def_delegators( :@parser, :empty? ) - def_delegators( :@parser, :source ) - - def initialize stream - @entities = {} - @listeners = nil - @parser = BaseParser.new( stream ) - @my_stack = [] - end - - def add_listener( listener ) - @listeners = [] unless @listeners - @listeners << listener - end - - def each - while has_next? - yield self.pull - end - end - - def peek depth=0 - if @my_stack.length <= depth - (depth - @my_stack.length + 1).times { - e = PullEvent.new(@parser.pull) - @my_stack.push(e) - } - end - @my_stack[depth] - end - - def pull - return @my_stack.shift if @my_stack.length > 0 - - event = @parser.pull - case event[0] - when :entitydecl - @entities[ event[1] ] = - event[2] unless event[2] =~ /PUBLIC|SYSTEM/ - when :text - unnormalized = @parser.unnormalize( event[1], @entities ) - event << unnormalized - end - PullEvent.new( event ) - end - - def unshift token - @my_stack.unshift token - end - end - - # A parsing event. The contents of the event are accessed as an +Array?, - # and the type is given either by the ...? methods, or by accessing the - # +type+ accessor. The contents of this object vary from event to event, - # but are identical to the arguments passed to +StreamListener+s for each - # event. - class PullEvent - # The type of this event. Will be one of :tag_start, :tag_end, :text, - # :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl, - # :notationdecl, :entity, :cdata, :xmldecl, or :error. - def initialize(arg) - @contents = arg - end - - def []( start, endd=nil) - if start.kind_of? Range - @contents.slice( start.begin+1 .. start.end ) - elsif start.kind_of? Numeric - if endd.nil? - @contents.slice( start+1 ) - else - @contents.slice( start+1, endd ) - end - else - raise "Illegal argument #{start.inspect} (#{start.class})" - end - end - - def event_type - @contents[0] - end - - # Content: [ String tag_name, Hash attributes ] - def start_element? - @contents[0] == :start_element - end - - # Content: [ String tag_name ] - def end_element? - @contents[0] == :end_element - end - - # Content: [ String raw_text, String unnormalized_text ] - def text? - @contents[0] == :text - end - - # Content: [ String text ] - def instruction? - @contents[0] == :processing_instruction - end - - # Content: [ String text ] - def comment? - @contents[0] == :comment - end - - # Content: [ String name, String pub_sys, String long_name, String uri ] - def doctype? - @contents[0] == :start_doctype - end - - # Content: [ String text ] - def attlistdecl? - @contents[0] == :attlistdecl - end - - # Content: [ String text ] - def elementdecl? - @contents[0] == :elementdecl - end - - # Due to the wonders of DTDs, an entity declaration can be just about - # anything. There's no way to normalize it; you'll have to interpret the - # content yourself. However, the following is true: - # - # * If the entity declaration is an internal entity: - # [ String name, String value ] - # Content: [ String text ] - def entitydecl? - @contents[0] == :entitydecl - end - - # Content: [ String text ] - def notationdecl? - @contents[0] == :notationdecl - end - - # Content: [ String text ] - def entity? - @contents[0] == :entity - end - - # Content: [ String text ] - def cdata? - @contents[0] == :cdata - end - - # Content: [ String version, String encoding, String standalone ] - def xmldecl? - @contents[0] == :xmldecl - end - - def error? - @contents[0] == :error - end - - def inspect - @contents[0].to_s + ": " + @contents[1..-1].inspect - end - end - end -end diff --git a/ruby/lib/rexml/parsers/sax2parser.rb b/ruby/lib/rexml/parsers/sax2parser.rb deleted file mode 100644 index 6a24ce222..000000000 --- a/ruby/lib/rexml/parsers/sax2parser.rb +++ /dev/null @@ -1,273 +0,0 @@ -# frozen_string_literal: false -require_relative 'baseparser' -require_relative '../parseexception' -require_relative '../namespace' -require_relative '../text' - -module REXML - module Parsers - # SAX2Parser - class SAX2Parser - def initialize source - @parser = BaseParser.new(source) - @listeners = [] - @procs = [] - @namespace_stack = [] - @has_listeners = false - @tag_stack = [] - @entities = {} - end - - def source - @parser.source - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - - # Listen arguments: - # - # Symbol, Array, Block - # Listen to Symbol events on Array elements - # Symbol, Block - # Listen to Symbol events - # Array, Listener - # Listen to all events on Array elements - # Array, Block - # Listen to :start_element events on Array elements - # Listener - # Listen to All events - # - # Symbol can be one of: :start_element, :end_element, - # :start_prefix_mapping, :end_prefix_mapping, :characters, - # :processing_instruction, :doctype, :attlistdecl, :elementdecl, - # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment - # - # There is an additional symbol that can be listened for: :progress. - # This will be called for every event generated, passing in the current - # stream position. - # - # Array contains regular expressions or strings which will be matched - # against fully qualified element names. - # - # Listener must implement the methods in SAX2Listener - # - # Block will be passed the same arguments as a SAX2Listener method would - # be, where the method name is the same as the matched Symbol. - # See the SAX2Listener for more information. - def listen( *args, &blok ) - if args[0].kind_of? Symbol - if args.size == 2 - args[1].each { |match| @procs << [args[0], match, blok] } - else - add( [args[0], nil, blok] ) - end - elsif args[0].kind_of? Array - if args.size == 2 - args[0].each { |match| add( [nil, match, args[1]] ) } - else - args[0].each { |match| add( [ :start_element, match, blok ] ) } - end - else - add([nil, nil, args[0]]) - end - end - - def deafen( listener=nil, &blok ) - if listener - @listeners.delete_if {|item| item[-1] == listener } - @has_listeners = false if @listeners.size == 0 - else - @procs.delete_if {|item| item[-1] == blok } - end - end - - def parse - @procs.each { |sym,match,block| block.call if sym == :start_document } - @listeners.each { |sym,match,block| - block.start_document if sym == :start_document or sym.nil? - } - context = [] - while true - event = @parser.pull - case event[0] - when :end_document - handle( :end_document ) - break - when :start_doctype - handle( :doctype, *event[1..-1]) - when :end_doctype - context = context[1] - when :start_element - @tag_stack.push(event[1]) - # find the observers for namespaces - procs = get_procs( :start_prefix_mapping, event[1] ) - listeners = get_listeners( :start_prefix_mapping, event[1] ) - if procs or listeners - # break out the namespace declarations - # The attributes live in event[2] - event[2].each {|n, v| event[2][n] = @parser.normalize(v)} - nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ } - nsdecl.collect! { |n, value| [ n[6..-1], value ] } - @namespace_stack.push({}) - nsdecl.each do |n,v| - @namespace_stack[-1][n] = v - # notify observers of namespaces - procs.each { |ob| ob.call( n, v ) } if procs - listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners - end - end - event[1] =~ Namespace::NAMESPLIT - prefix = $1 - local = $2 - uri = get_namespace(prefix) - # find the observers for start_element - procs = get_procs( :start_element, event[1] ) - listeners = get_listeners( :start_element, event[1] ) - # notify observers - procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs - listeners.each { |ob| - ob.start_element( uri, local, event[1], event[2] ) - } if listeners - when :end_element - @tag_stack.pop - event[1] =~ Namespace::NAMESPLIT - prefix = $1 - local = $2 - uri = get_namespace(prefix) - # find the observers for start_element - procs = get_procs( :end_element, event[1] ) - listeners = get_listeners( :end_element, event[1] ) - # notify observers - procs.each { |ob| ob.call( uri, local, event[1] ) } if procs - listeners.each { |ob| - ob.end_element( uri, local, event[1] ) - } if listeners - - namespace_mapping = @namespace_stack.pop - # find the observers for namespaces - procs = get_procs( :end_prefix_mapping, event[1] ) - listeners = get_listeners( :end_prefix_mapping, event[1] ) - if procs or listeners - namespace_mapping.each do |ns_prefix, ns_uri| - # notify observers of namespaces - procs.each { |ob| ob.call( ns_prefix ) } if procs - listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners - end - end - when :text - #normalized = @parser.normalize( event[1] ) - #handle( :characters, normalized ) - copy = event[1].clone - - esub = proc { |match| - if @entities.has_key?($1) - @entities[$1].gsub(Text::REFERENCE, &esub) - else - match - end - } - - copy.gsub!( Text::REFERENCE, &esub ) - copy.gsub!( Text::NUMERICENTITY ) {|m| - m=$1 - m = "0#{m}" if m[0] == ?x - [Integer(m)].pack('U*') - } - handle( :characters, copy ) - when :entitydecl - handle_entitydecl( event ) - when :processing_instruction, :comment, :attlistdecl, - :elementdecl, :cdata, :notationdecl, :xmldecl - handle( *event ) - end - handle( :progress, @parser.position ) - end - end - - private - def handle( symbol, *arguments ) - tag = @tag_stack[-1] - procs = get_procs( symbol, tag ) - listeners = get_listeners( symbol, tag ) - # notify observers - procs.each { |ob| ob.call( *arguments ) } if procs - listeners.each { |l| - l.send( symbol.to_s, *arguments ) - } if listeners - end - - def handle_entitydecl( event ) - @entities[ event[1] ] = event[2] if event.size == 3 - parameter_reference_p = false - case event[2] - when "SYSTEM" - if event.size == 5 - if event.last == "%" - parameter_reference_p = true - else - event[4, 0] = "NDATA" - end - end - when "PUBLIC" - if event.size == 6 - if event.last == "%" - parameter_reference_p = true - else - event[5, 0] = "NDATA" - end - end - else - parameter_reference_p = (event.size == 4) - end - event[1, 0] = event.pop if parameter_reference_p - handle( event[0], event[1..-1] ) - end - - # The following methods are duplicates, but it is faster than using - # a helper - def get_procs( symbol, name ) - return nil if @procs.size == 0 - @procs.find_all do |sym, match, block| - ( - (sym.nil? or symbol == sym) and - ((name.nil? and match.nil?) or match.nil? or ( - (name == match) or - (match.kind_of? Regexp and name =~ match) - ) - ) - ) - end.collect{|x| x[-1]} - end - def get_listeners( symbol, name ) - return nil if @listeners.size == 0 - @listeners.find_all do |sym, match, block| - ( - (sym.nil? or symbol == sym) and - ((name.nil? and match.nil?) or match.nil? or ( - (name == match) or - (match.kind_of? Regexp and name =~ match) - ) - ) - ) - end.collect{|x| x[-1]} - end - - def add( pair ) - if pair[-1].respond_to? :call - @procs << pair unless @procs.include? pair - else - @listeners << pair unless @listeners.include? pair - @has_listeners = true - end - end - - def get_namespace( prefix ) - uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) || - (@namespace_stack.find { |ns| not ns[nil].nil? }) - uris[-1][prefix] unless uris.nil? or 0 == uris.size - end - end - end -end diff --git a/ruby/lib/rexml/parsers/streamparser.rb b/ruby/lib/rexml/parsers/streamparser.rb deleted file mode 100644 index 9e0eb0b36..000000000 --- a/ruby/lib/rexml/parsers/streamparser.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: false -require_relative "baseparser" - -module REXML - module Parsers - class StreamParser - def initialize source, listener - @listener = listener - @parser = BaseParser.new( source ) - @tag_stack = [] - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - - def parse - # entity string - while true - event = @parser.pull - case event[0] - when :end_document - unless @tag_stack.empty? - tag_path = "/" + @tag_stack.join("/") - raise ParseException.new("Missing end tag for '#{tag_path}'", - @parser.source) - end - return - when :start_element - @tag_stack << event[1] - attrs = event[2].each do |n, v| - event[2][n] = @parser.unnormalize( v ) - end - @listener.tag_start( event[1], attrs ) - when :end_element - @listener.tag_end( event[1] ) - @tag_stack.pop - when :text - normalized = @parser.unnormalize( event[1] ) - @listener.text( normalized ) - when :processing_instruction - @listener.instruction( *event[1,2] ) - when :start_doctype - @listener.doctype( *event[1..-1] ) - when :end_doctype - # FIXME: remove this condition for milestone:3.2 - @listener.doctype_end if @listener.respond_to? :doctype_end - when :comment, :attlistdecl, :cdata, :xmldecl, :elementdecl - @listener.send( event[0].to_s, *event[1..-1] ) - when :entitydecl, :notationdecl - @listener.send( event[0].to_s, event[1..-1] ) - when :externalentity - entity_reference = event[1] - content = entity_reference.gsub(/\A%|;\z/, "") - @listener.entity(content) - end - end - end - end - end -end diff --git a/ruby/lib/rexml/parsers/treeparser.rb b/ruby/lib/rexml/parsers/treeparser.rb deleted file mode 100644 index bf9a42545..000000000 --- a/ruby/lib/rexml/parsers/treeparser.rb +++ /dev/null @@ -1,101 +0,0 @@ -# frozen_string_literal: false -require_relative '../validation/validationexception' -require_relative '../undefinednamespaceexception' - -module REXML - module Parsers - class TreeParser - def initialize( source, build_context = Document.new ) - @build_context = build_context - @parser = Parsers::BaseParser.new( source ) - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - - def parse - tag_stack = [] - in_doctype = false - entities = nil - begin - while true - event = @parser.pull - #STDERR.puts "TREEPARSER GOT #{event.inspect}" - case event[0] - when :end_document - unless tag_stack.empty? - raise ParseException.new("No close tag for #{@build_context.xpath}", - @parser.source, @parser) - end - return - when :start_element - tag_stack.push(event[1]) - el = @build_context = @build_context.add_element( event[1] ) - event[2].each do |key, value| - el.attributes[key]=Attribute.new(key,value,self) - end - when :end_element - tag_stack.pop - @build_context = @build_context.parent - when :text - if not in_doctype - if @build_context[-1].instance_of? Text - @build_context[-1] << event[1] - else - @build_context.add( - Text.new(event[1], @build_context.whitespace, nil, true) - ) unless ( - @build_context.ignore_whitespace_nodes and - event[1].strip.size==0 - ) - end - end - when :comment - c = Comment.new( event[1] ) - @build_context.add( c ) - when :cdata - c = CData.new( event[1] ) - @build_context.add( c ) - when :processing_instruction - @build_context.add( Instruction.new( event[1], event[2] ) ) - when :end_doctype - in_doctype = false - entities.each { |k,v| entities[k] = @build_context.entities[k].value } - @build_context = @build_context.parent - when :start_doctype - doctype = DocType.new( event[1..-1], @build_context ) - @build_context = doctype - entities = {} - in_doctype = true - when :attlistdecl - n = AttlistDecl.new( event[1..-1] ) - @build_context.add( n ) - when :externalentity - n = ExternalEntity.new( event[1] ) - @build_context.add( n ) - when :elementdecl - n = ElementDecl.new( event[1] ) - @build_context.add(n) - when :entitydecl - entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/ - @build_context.add(Entity.new(event)) - when :notationdecl - n = NotationDecl.new( *event[1..-1] ) - @build_context.add( n ) - when :xmldecl - x = XMLDecl.new( event[1], event[2], event[3] ) - @build_context.add( x ) - end - end - rescue REXML::Validation::ValidationException - raise - rescue REXML::ParseException - raise - rescue - raise ParseException.new( $!.message, @parser.source, @parser, $! ) - end - end - end - end -end diff --git a/ruby/lib/rexml/parsers/ultralightparser.rb b/ruby/lib/rexml/parsers/ultralightparser.rb deleted file mode 100644 index e0029f43d..000000000 --- a/ruby/lib/rexml/parsers/ultralightparser.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: false -require_relative 'streamparser' -require_relative 'baseparser' - -module REXML - module Parsers - class UltraLightParser - def initialize stream - @stream = stream - @parser = REXML::Parsers::BaseParser.new( stream ) - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - - def rewind - @stream.rewind - @parser.stream = @stream - end - - def parse - root = context = [] - while true - event = @parser.pull - case event[0] - when :end_document - break - when :end_doctype - context = context[1] - when :start_element, :start_doctype - context << event - event[1,0] = [context] - context = event - when :end_element - context = context[1] - else - context << event - end - end - root - end - end - - # An element is an array. The array contains: - # 0 The parent element - # 1 The tag name - # 2 A hash of attributes - # 3..-1 The child elements - # An element is an array of size > 3 - # Text is a String - # PIs are [ :processing_instruction, target, data ] - # Comments are [ :comment, data ] - # DocTypes are DocType structs - # The root is an array with XMLDecls, Text, DocType, Array, Text - end -end diff --git a/ruby/lib/rexml/parsers/xpathparser.rb b/ruby/lib/rexml/parsers/xpathparser.rb deleted file mode 100644 index d01d325e0..000000000 --- a/ruby/lib/rexml/parsers/xpathparser.rb +++ /dev/null @@ -1,675 +0,0 @@ -# frozen_string_literal: false -require_relative '../namespace' -require_relative '../xmltokens' - -module REXML - module Parsers - # You don't want to use this class. Really. Use XPath, which is a wrapper - # for this class. Believe me. You don't want to poke around in here. - # There is strange, dark magic at work in this code. Beware. Go back! Go - # back while you still can! - class XPathParser - include XMLTokens - LITERAL = /^'([^']*)'|^"([^"]*)"/u - - def namespaces=( namespaces ) - Functions::namespace_context = namespaces - @namespaces = namespaces - end - - def parse path - path = path.dup - path.gsub!(/([\(\[])\s+/, '\1') # Strip ignorable spaces - path.gsub!( /\s+([\]\)])/, '\1') - parsed = [] - OrExpr(path, parsed) - parsed - end - - def predicate path - parsed = [] - Predicate( "[#{path}]", parsed ) - parsed - end - - def abbreviate( path ) - path = path.kind_of?(String) ? parse( path ) : path - string = "" - document = false - while path.size > 0 - op = path.shift - case op - when :node - when :attribute - string << "/" if string.size > 0 - string << "@" - when :child - string << "/" if string.size > 0 - when :descendant_or_self - string << "/" - when :self - string << "." - when :parent - string << ".." - when :any - string << "*" - when :text - string << "text()" - when :following, :following_sibling, - :ancestor, :ancestor_or_self, :descendant, - :namespace, :preceding, :preceding_sibling - string << "/" unless string.size == 0 - string << op.to_s.tr("_", "-") - string << "::" - when :qname - prefix = path.shift - name = path.shift - string << prefix+":" if prefix.size > 0 - string << name - when :predicate - string << '[' - string << predicate_to_string( path.shift ) {|x| abbreviate( x ) } - string << ']' - when :document - document = true - when :function - string << path.shift - string << "( " - string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )} - string << " )" - when :literal - string << %Q{ "#{path.shift}" } - else - string << "/" unless string.size == 0 - string << "UNKNOWN(" - string << op.inspect - string << ")" - end - end - string = "/"+string if document - return string - end - - def expand( path ) - path = path.kind_of?(String) ? parse( path ) : path - string = "" - document = false - while path.size > 0 - op = path.shift - case op - when :node - string << "node()" - when :attribute, :child, :following, :following_sibling, - :ancestor, :ancestor_or_self, :descendant, :descendant_or_self, - :namespace, :preceding, :preceding_sibling, :self, :parent - string << "/" unless string.size == 0 - string << op.to_s.tr("_", "-") - string << "::" - when :any - string << "*" - when :qname - prefix = path.shift - name = path.shift - string << prefix+":" if prefix.size > 0 - string << name - when :predicate - string << '[' - string << predicate_to_string( path.shift ) { |x| expand(x) } - string << ']' - when :document - document = true - else - string << "/" unless string.size == 0 - string << "UNKNOWN(" - string << op.inspect - string << ")" - end - end - string = "/"+string if document - return string - end - - def predicate_to_string( path, &block ) - string = "" - case path[0] - when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union - op = path.shift - case op - when :eq - op = "=" - when :lt - op = "<" - when :gt - op = ">" - when :lteq - op = "<=" - when :gteq - op = ">=" - when :neq - op = "!=" - when :union - op = "|" - end - left = predicate_to_string( path.shift, &block ) - right = predicate_to_string( path.shift, &block ) - string << " " - string << left - string << " " - string << op.to_s - string << " " - string << right - string << " " - when :function - path.shift - name = path.shift - string << name - string << "( " - string << predicate_to_string( path.shift, &block ) - string << " )" - when :literal - path.shift - string << " " - string << path.shift.inspect - string << " " - else - string << " " - string << yield( path ) - string << " " - end - return string.squeeze(" ") - end - - private - #LocationPath - # | RelativeLocationPath - # | '/' RelativeLocationPath? - # | '//' RelativeLocationPath - def LocationPath path, parsed - path = path.lstrip - if path[0] == ?/ - parsed << :document - if path[1] == ?/ - parsed << :descendant_or_self - parsed << :node - path = path[2..-1] - else - path = path[1..-1] - end - end - return RelativeLocationPath( path, parsed ) if path.size > 0 - end - - #RelativeLocationPath - # | Step - # | (AXIS_NAME '::' | '@' | '') AxisSpecifier - # NodeTest - # Predicate - # | '.' | '..' AbbreviatedStep - # | RelativeLocationPath '/' Step - # | RelativeLocationPath '//' Step - AXIS = /^(ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self)::/ - def RelativeLocationPath path, parsed - loop do - original_path = path - path = path.lstrip - - return original_path if path.empty? - - # (axis or @ or ) nodetest predicate > - # OR > / Step - # (. or ..) > - if path[0] == ?. - if path[1] == ?. - parsed << :parent - parsed << :node - path = path[2..-1] - else - parsed << :self - parsed << :node - path = path[1..-1] - end - else - if path[0] == ?@ - parsed << :attribute - path = path[1..-1] - # Goto Nodetest - elsif path =~ AXIS - parsed << $1.tr('-','_').intern - path = $' - # Goto Nodetest - else - parsed << :child - end - - n = [] - path = NodeTest( path, n) - - path = Predicate( path, n ) - - parsed.concat(n) - end - - original_path = path - path = path.lstrip - return original_path if path.empty? - - return original_path if path[0] != ?/ - - if path[1] == ?/ - parsed << :descendant_or_self - parsed << :node - path = path[2..-1] - else - path = path[1..-1] - end - end - end - - # Returns a 1-1 map of the nodeset - # The contents of the resulting array are either: - # true/false, if a positive match - # String, if a name match - #NodeTest - # | ('*' | NCNAME ':' '*' | QNAME) NameTest - # | '*' ':' NCNAME NameTest since XPath 2.0 - # | NODE_TYPE '(' ')' NodeType - # | PI '(' LITERAL ')' PI - # | '[' expr ']' Predicate - PREFIX_WILDCARD = /^\*:(#{NCNAME_STR})/u - LOCAL_NAME_WILDCARD = /^(#{NCNAME_STR}):\*/u - QNAME = Namespace::NAMESPLIT - NODE_TYPE = /^(comment|text|node)\(\s*\)/m - PI = /^processing-instruction\(/ - def NodeTest path, parsed - original_path = path - path = path.lstrip - case path - when PREFIX_WILDCARD - prefix = nil - name = $1 - path = $' - parsed << :qname - parsed << prefix - parsed << name - when /^\*/ - path = $' - parsed << :any - when NODE_TYPE - type = $1 - path = $' - parsed << type.tr('-', '_').intern - when PI - path = $' - literal = nil - if path !~ /^\s*\)/ - path =~ LITERAL - literal = $1 - path = $' - raise ParseException.new("Missing ')' after processing instruction") if path[0] != ?) - path = path[1..-1] - end - parsed << :processing_instruction - parsed << (literal || '') - when LOCAL_NAME_WILDCARD - prefix = $1 - path = $' - parsed << :namespace - parsed << prefix - when QNAME - prefix = $1 - name = $2 - path = $' - prefix = "" unless prefix - parsed << :qname - parsed << prefix - parsed << name - else - path = original_path - end - return path - end - - # Filters the supplied nodeset on the predicate(s) - def Predicate path, parsed - original_path = path - path = path.lstrip - return original_path unless path[0] == ?[ - predicates = [] - while path[0] == ?[ - path, expr = get_group(path) - predicates << expr[1..-2] if expr - end - predicates.each{ |pred| - preds = [] - parsed << :predicate - parsed << preds - OrExpr(pred, preds) - } - path - end - - # The following return arrays of true/false, a 1-1 mapping of the - # supplied nodeset, except for axe(), which returns a filtered - # nodeset - - #| OrExpr S 'or' S AndExpr - #| AndExpr - def OrExpr path, parsed - n = [] - rest = AndExpr( path, n ) - if rest != path - while rest =~ /^\s*( or )/ - n = [ :or, n, [] ] - rest = AndExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| AndExpr S 'and' S EqualityExpr - #| EqualityExpr - def AndExpr path, parsed - n = [] - rest = EqualityExpr( path, n ) - if rest != path - while rest =~ /^\s*( and )/ - n = [ :and, n, [] ] - rest = EqualityExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| EqualityExpr ('=' | '!=') RelationalExpr - #| RelationalExpr - def EqualityExpr path, parsed - n = [] - rest = RelationalExpr( path, n ) - if rest != path - while rest =~ /^\s*(!?=)\s*/ - if $1[0] == ?! - n = [ :neq, n, [] ] - else - n = [ :eq, n, [] ] - end - rest = RelationalExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| RelationalExpr ('<' | '>' | '<=' | '>=') AdditiveExpr - #| AdditiveExpr - def RelationalExpr path, parsed - n = [] - rest = AdditiveExpr( path, n ) - if rest != path - while rest =~ /^\s*([<>]=?)\s*/ - if $1[0] == ?< - sym = "lt" - else - sym = "gt" - end - sym << "eq" if $1[-1] == ?= - n = [ sym.intern, n, [] ] - rest = AdditiveExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| AdditiveExpr ('+' | '-') MultiplicativeExpr - #| MultiplicativeExpr - def AdditiveExpr path, parsed - n = [] - rest = MultiplicativeExpr( path, n ) - if rest != path - while rest =~ /^\s*(\+|-)\s*/ - if $1[0] == ?+ - n = [ :plus, n, [] ] - else - n = [ :minus, n, [] ] - end - rest = MultiplicativeExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| MultiplicativeExpr ('*' | S ('div' | 'mod') S) UnaryExpr - #| UnaryExpr - def MultiplicativeExpr path, parsed - n = [] - rest = UnaryExpr( path, n ) - if rest != path - while rest =~ /^\s*(\*| div | mod )\s*/ - if $1[0] == ?* - n = [ :mult, n, [] ] - elsif $1.include?( "div" ) - n = [ :div, n, [] ] - else - n = [ :mod, n, [] ] - end - rest = UnaryExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace(n) - elsif n.size > 0 - parsed << n - end - rest - end - - #| '-' UnaryExpr - #| UnionExpr - def UnaryExpr path, parsed - path =~ /^(\-*)/ - path = $' - if $1 and (($1.size % 2) != 0) - mult = -1 - else - mult = 1 - end - parsed << :neg if mult < 0 - - n = [] - path = UnionExpr( path, n ) - parsed.concat( n ) - path - end - - #| UnionExpr '|' PathExpr - #| PathExpr - def UnionExpr path, parsed - n = [] - rest = PathExpr( path, n ) - if rest != path - while rest =~ /^\s*(\|)\s*/ - n = [ :union, n, [] ] - rest = PathExpr( $', n[-1] ) - end - end - if parsed.size == 0 and n.size != 0 - parsed.replace( n ) - elsif n.size > 0 - parsed << n - end - rest - end - - #| LocationPath - #| FilterExpr ('/' | '//') RelativeLocationPath - def PathExpr path, parsed - path = path.lstrip - n = [] - rest = FilterExpr( path, n ) - if rest != path - if rest and rest[0] == ?/ - rest = RelativeLocationPath(rest, n) - parsed.concat(n) - return rest - end - end - rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/ - parsed.concat(n) - return rest - end - - #| FilterExpr Predicate - #| PrimaryExpr - def FilterExpr path, parsed - n = [] - path = PrimaryExpr( path, n ) - path = Predicate(path, n) - parsed.concat(n) - path - end - - #| VARIABLE_REFERENCE - #| '(' expr ')' - #| LITERAL - #| NUMBER - #| FunctionCall - VARIABLE_REFERENCE = /^\$(#{NAME_STR})/u - NUMBER = /^(\d*\.?\d+)/ - NT = /^comment|text|processing-instruction|node$/ - def PrimaryExpr path, parsed - case path - when VARIABLE_REFERENCE - varname = $1 - path = $' - parsed << :variable - parsed << varname - #arry << @variables[ varname ] - when /^(\w[-\w]*)(?:\()/ - fname = $1 - tmp = $' - return path if fname =~ NT - path = tmp - parsed << :function - parsed << fname - path = FunctionCall(path, parsed) - when NUMBER - varname = $1.nil? ? $2 : $1 - path = $' - parsed << :literal - parsed << (varname.include?('.') ? varname.to_f : varname.to_i) - when LITERAL - varname = $1.nil? ? $2 : $1 - path = $' - parsed << :literal - parsed << varname - when /^\(/ #/ - path, contents = get_group(path) - contents = contents[1..-2] - n = [] - OrExpr( contents, n ) - parsed.concat(n) - end - path - end - - #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')' - def FunctionCall rest, parsed - path, arguments = parse_args(rest) - argset = [] - for argument in arguments - args = [] - OrExpr( argument, args ) - argset << args - end - parsed << argset - path - end - - # get_group( '[foo]bar' ) -> ['bar', '[foo]'] - def get_group string - ind = 0 - depth = 0 - st = string[0,1] - en = (st == "(" ? ")" : "]") - begin - case string[ind,1] - when st - depth += 1 - when en - depth -= 1 - end - ind += 1 - end while depth > 0 and ind < string.length - return nil unless depth==0 - [string[ind..-1], string[0..ind-1]] - end - - def parse_args( string ) - arguments = [] - ind = 0 - inquot = false - inapos = false - depth = 1 - begin - case string[ind] - when ?" - inquot = !inquot unless inapos - when ?' - inapos = !inapos unless inquot - else - unless inquot or inapos - case string[ind] - when ?( - depth += 1 - if depth == 1 - string = string[1..-1] - ind -= 1 - end - when ?) - depth -= 1 - if depth == 0 - s = string[0,ind].strip - arguments << s unless s == "" - string = string[ind+1..-1] - end - when ?, - if depth == 1 - s = string[0,ind].strip - arguments << s unless s == "" - string = string[ind+1..-1] - ind = -1 - end - end - end - end - ind += 1 - end while depth > 0 and ind < string.length - return nil unless depth==0 - [string,arguments] - end - end - end -end diff --git a/ruby/lib/rexml/quickpath.rb b/ruby/lib/rexml/quickpath.rb deleted file mode 100644 index a0466b25d..000000000 --- a/ruby/lib/rexml/quickpath.rb +++ /dev/null @@ -1,266 +0,0 @@ -# frozen_string_literal: false -require_relative 'functions' -require_relative 'xmltokens' - -module REXML - class QuickPath - include Functions - include XMLTokens - - # A base Hash object to be used when initializing a - # default empty namespaces set. - EMPTY_HASH = {} - - def QuickPath::first element, path, namespaces=EMPTY_HASH - match(element, path, namespaces)[0] - end - - def QuickPath::each element, path, namespaces=EMPTY_HASH, &block - path = "*" unless path - match(element, path, namespaces).each( &block ) - end - - def QuickPath::match element, path, namespaces=EMPTY_HASH - raise "nil is not a valid xpath" unless path - results = nil - Functions::namespace_context = namespaces - case path - when /^\/([^\/]|$)/u - # match on root - path = path[1..-1] - return [element.root.parent] if path == '' - results = filter([element.root], path) - when /^[-\w]*::/u - results = filter([element], path) - when /^\*/u - results = filter(element.to_a, path) - when /^[\[!\w:]/u - # match on child - children = element.to_a - results = filter(children, path) - else - results = filter([element], path) - end - return results - end - - # Given an array of nodes it filters the array based on the path. The - # result is that when this method returns, the array will contain elements - # which match the path - def QuickPath::filter elements, path - return elements if path.nil? or path == '' or elements.size == 0 - case path - when /^\/\//u # Descendant - return axe( elements, "descendant-or-self", $' ) - when /^\/?\b(\w[-\w]*)\b::/u # Axe - return axe( elements, $1, $' ) - when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child - rest = $' - results = [] - elements.each do |element| - results |= filter( element.to_a, rest ) - end - return results - when /^\/?(\w[-\w]*)\(/u # / Function - return function( elements, $1, $' ) - when Namespace::NAMESPLIT # Element name - name = $2 - ns = $1 - rest = $' - elements.delete_if do |element| - !(element.kind_of? Element and - (element.expanded_name == name or - (element.name == name and - element.namespace == Functions.namespace_context[ns]))) - end - return filter( elements, rest ) - when /^\/\[/u - matches = [] - elements.each do |element| - matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element - end - return matches - when /^\[/u # Predicate - return predicate( elements, path ) - when /^\/?\.\.\./u # Ancestor - return axe( elements, "ancestor", $' ) - when /^\/?\.\./u # Parent - return filter( elements.collect{|e|e.parent}, $' ) - when /^\/?\./u # Self - return filter( elements, $' ) - when /^\*/u # Any - results = [] - elements.each do |element| - results |= filter( [element], $' ) if element.kind_of? Element - #if element.kind_of? Element - # children = element.to_a - # children.delete_if { |child| !child.kind_of?(Element) } - # results |= filter( children, $' ) - #end - end - return results - end - return [] - end - - def QuickPath::axe( elements, axe_name, rest ) - matches = [] - matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u - case axe_name - when /^descendant/u - elements.each do |element| - matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element - end - when /^ancestor/u - elements.each do |element| - while element.parent - matches << element.parent - element = element.parent - end - end - matches = filter( matches, rest ) - when "self" - matches = filter( elements, rest ) - when "child" - elements.each do |element| - matches |= filter( element.to_a, rest ) if element.kind_of? Element - end - when "attribute" - elements.each do |element| - matches << element.attributes[ rest ] if element.kind_of? Element - end - when "parent" - matches = filter(elements.collect{|element| element.parent}.uniq, rest) - when "following-sibling" - matches = filter(elements.collect{|element| element.next_sibling}.uniq, - rest) - when "previous-sibling" - matches = filter(elements.collect{|element| - element.previous_sibling}.uniq, rest ) - end - return matches.uniq - end - - OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)' - # A predicate filters a node-set with respect to an axis to produce a - # new node-set. For each node in the node-set to be filtered, the - # PredicateExpr is evaluated with that node as the context node, with - # the number of nodes in the node-set as the context size, and with the - # proximity position of the node in the node-set with respect to the - # axis as the context position; if PredicateExpr evaluates to true for - # that node, the node is included in the new node-set; otherwise, it is - # not included. - # - # A PredicateExpr is evaluated by evaluating the Expr and converting - # the result to a boolean. If the result is a number, the result will - # be converted to true if the number is equal to the context position - # and will be converted to false otherwise; if the result is not a - # number, then the result will be converted as if by a call to the - # boolean function. Thus a location path para[3] is equivalent to - # para[position()=3]. - def QuickPath::predicate( elements, path ) - ind = 1 - bcount = 1 - while bcount > 0 - bcount += 1 if path[ind] == ?[ - bcount -= 1 if path[ind] == ?] - ind += 1 - end - ind -= 1 - predicate = path[1..ind-1] - rest = path[ind+1..-1] - - # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c' - # - predicate.gsub!( - /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u, - '\1 \2 \3 and \3 \4 \5' ) - # Let's do some Ruby trickery to avoid some work: - predicate.gsub!( /&/u, "&&" ) - predicate.gsub!( /=/u, "==" ) - predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' ) - predicate.gsub!( /\bmod\b/u, "%" ) - predicate.gsub!( /\b(\w[-\w.]*\()/u ) { - fname = $1 - fname.gsub( /-/u, "_" ) - } - - Functions.pair = [ 0, elements.size ] - results = [] - elements.each do |element| - Functions.pair[0] += 1 - Functions.node = element - res = eval( predicate ) - case res - when true - results << element - when Integer - results << element if Functions.pair[0] == res - when String - results << element - end - end - return filter( results, rest ) - end - - def QuickPath::attribute( name ) - return Functions.node.attributes[name] if Functions.node.kind_of? Element - end - - def QuickPath::name() - return Functions.node.name if Functions.node.kind_of? Element - end - - def QuickPath::method_missing( id, *args ) - begin - Functions.send( id.id2name, *args ) - rescue Exception - raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}" - end - end - - def QuickPath::function( elements, fname, rest ) - args = parse_args( elements, rest ) - Functions.pair = [0, elements.size] - results = [] - elements.each do |element| - Functions.pair[0] += 1 - Functions.node = element - res = Functions.send( fname, *args ) - case res - when true - results << element - when Integer - results << element if Functions.pair[0] == res - end - end - return results - end - - def QuickPath::parse_args( element, string ) - # /.*?(?:\)|,)/ - arguments = [] - buffer = "" - while string and string != "" - c = string[0] - string.sub!(/^./u, "") - case c - when ?, - # if depth = 1, then we start a new argument - arguments << evaluate( buffer ) - #arguments << evaluate( string[0..count] ) - when ?( - # start a new method call - function( element, buffer, string ) - buffer = "" - when ?) - # close the method call and return arguments - return arguments - else - buffer << c - end - end - "" - end - end -end diff --git a/ruby/lib/rexml/rexml.gemspec b/ruby/lib/rexml/rexml.gemspec deleted file mode 100644 index 263f013aa..000000000 --- a/ruby/lib/rexml/rexml.gemspec +++ /dev/null @@ -1,84 +0,0 @@ -begin - require_relative "lib/rexml/rexml" -rescue LoadError - # for Ruby core repository - require_relative "rexml" -end - -Gem::Specification.new do |spec| - spec.name = "rexml" - spec.version = REXML::VERSION - spec.authors = ["Kouhei Sutou"] - spec.email = ["kou@cozmixng.org"] - - spec.summary = %q{An XML toolkit for Ruby} - spec.description = %q{An XML toolkit for Ruby} - spec.homepage = "https://github.com/ruby/rexml" - spec.license = "BSD-2-Clause" - - spec.files = [ - ".gitignore", - ".travis.yml", - "Gemfile", - "LICENSE.txt", - "NEWS.md", - "README.md", - "Rakefile", - "lib/rexml/attlistdecl.rb", - "lib/rexml/attribute.rb", - "lib/rexml/cdata.rb", - "lib/rexml/child.rb", - "lib/rexml/comment.rb", - "lib/rexml/doctype.rb", - "lib/rexml/document.rb", - "lib/rexml/dtd/attlistdecl.rb", - "lib/rexml/dtd/dtd.rb", - "lib/rexml/dtd/elementdecl.rb", - "lib/rexml/dtd/entitydecl.rb", - "lib/rexml/dtd/notationdecl.rb", - "lib/rexml/element.rb", - "lib/rexml/encoding.rb", - "lib/rexml/entity.rb", - "lib/rexml/formatters/default.rb", - "lib/rexml/formatters/pretty.rb", - "lib/rexml/formatters/transitive.rb", - "lib/rexml/functions.rb", - "lib/rexml/instruction.rb", - "lib/rexml/light/node.rb", - "lib/rexml/namespace.rb", - "lib/rexml/node.rb", - "lib/rexml/output.rb", - "lib/rexml/parent.rb", - "lib/rexml/parseexception.rb", - "lib/rexml/parsers/baseparser.rb", - "lib/rexml/parsers/lightparser.rb", - "lib/rexml/parsers/pullparser.rb", - "lib/rexml/parsers/sax2parser.rb", - "lib/rexml/parsers/streamparser.rb", - "lib/rexml/parsers/treeparser.rb", - "lib/rexml/parsers/ultralightparser.rb", - "lib/rexml/parsers/xpathparser.rb", - "lib/rexml/quickpath.rb", - "lib/rexml/rexml.rb", - "lib/rexml/sax2listener.rb", - "lib/rexml/security.rb", - "lib/rexml/source.rb", - "lib/rexml/streamlistener.rb", - "lib/rexml/text.rb", - "lib/rexml/undefinednamespaceexception.rb", - "lib/rexml/validation/relaxng.rb", - "lib/rexml/validation/validation.rb", - "lib/rexml/validation/validationexception.rb", - "lib/rexml/xmldecl.rb", - "lib/rexml/xmltokens.rb", - "lib/rexml/xpath.rb", - "lib/rexml/xpath_parser.rb", - "rexml.gemspec", - ] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" -end diff --git a/ruby/lib/rexml/rexml.rb b/ruby/lib/rexml/rexml.rb deleted file mode 100644 index 944d88a86..000000000 --- a/ruby/lib/rexml/rexml.rb +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false -# REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby. -# -# REXML is a _pure_ Ruby, XML 1.0 conforming, -# non-validating[http://www.w3.org/TR/2004/REC-xml-20040204/#sec-conformance] -# toolkit with an intuitive API. REXML passes 100% of the non-validating Oasis -# tests[http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.shtml], -# and provides tree, stream, SAX2, pull, and lightweight APIs. REXML also -# includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since -# Ruby 1.8, REXML is included in the standard Ruby distribution. -# -# Main page:: http://www.germane-software.com/software/rexml -# Author:: Sean Russell -# Date:: 2008/019 -# Version:: 3.1.7.3 -# -# This API documentation can be downloaded from the REXML home page, or can -# be accessed online[http://www.germane-software.com/software/rexml_doc] -# -# A tutorial is available in the REXML distribution in docs/tutorial.html, -# or can be accessed -# online[http://www.germane-software.com/software/rexml/docs/tutorial.html] -module REXML - COPYRIGHT = "Copyright © 2001-2008 Sean Russell " - DATE = "2008/019" - VERSION = "3.2.3" - REVISION = "" - - Copyright = COPYRIGHT - Version = VERSION -end diff --git a/ruby/lib/rexml/sax2listener.rb b/ruby/lib/rexml/sax2listener.rb deleted file mode 100644 index 5afdc8089..000000000 --- a/ruby/lib/rexml/sax2listener.rb +++ /dev/null @@ -1,98 +0,0 @@ -# frozen_string_literal: false -module REXML - # A template for stream parser listeners. - # Note that the declarations (attlistdecl, elementdecl, etc) are trivially - # processed; REXML doesn't yet handle doctype entity declarations, so you - # have to parse them out yourself. - # === Missing methods from SAX2 - # ignorable_whitespace - # === Methods extending SAX2 - # +WARNING+ - # These methods are certainly going to change, until DTDs are fully - # supported. Be aware of this. - # start_document - # end_document - # doctype - # elementdecl - # attlistdecl - # entitydecl - # notationdecl - # cdata - # xmldecl - # comment - module SAX2Listener - def start_document - end - def end_document - end - def start_prefix_mapping prefix, uri - end - def end_prefix_mapping prefix - end - def start_element uri, localname, qname, attributes - end - def end_element uri, localname, qname - end - def characters text - end - def processing_instruction target, data - end - # Handles a doctype declaration. Any attributes of the doctype which are - # not supplied will be nil. # EG, - # @p name the name of the doctype; EG, "me" - # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" - # @p long_name the supplied long name, or nil. EG, "foo" - # @p uri the uri of the doctype, or nil. EG, "bar" - def doctype name, pub_sys, long_name, uri - end - # If a doctype includes an ATTLIST declaration, it will cause this - # method to be called. The content is the declaration itself, unparsed. - # EG, will come to this method as "el - # attr CDATA #REQUIRED". This is the same for all of the .*decl - # methods. - def attlistdecl(element, pairs, contents) - end - # - def elementdecl content - end - # - # The argument passed to this method is an array of the entity - # declaration. It can be in a number of formats, but in general it - # returns (example, result): - # - # ["%", "YN", "\"Yes\""] - # - # ["%", "YN", "Yes"] - # - # ["WhatHeSaid", "He said %YN;"] - # - # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"] - # - # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"] - # - # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "NDATA", "gif"] - def entitydecl declaration - end - # - def notationdecl name, public_or_system, public_id, system_id - end - # Called when is encountered in a document. - # @p content "..." - def cdata content - end - # Called when an XML PI is encountered in the document. - # EG: - # @p version the version attribute value. EG, "1.0" - # @p encoding the encoding attribute value, or nil. EG, "utf" - # @p standalone the standalone attribute value, or nil. EG, nil - # @p spaced the declaration is followed by a line break - def xmldecl version, encoding, standalone - end - # Called when a comment is encountered. - # @p comment The content of the comment - def comment comment - end - def progress position - end - end -end diff --git a/ruby/lib/rexml/security.rb b/ruby/lib/rexml/security.rb deleted file mode 100644 index 99b746077..000000000 --- a/ruby/lib/rexml/security.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: false -module REXML - module Security - @@entity_expansion_limit = 10_000 - - # Set the entity expansion limit. By default the limit is set to 10000. - def self.entity_expansion_limit=( val ) - @@entity_expansion_limit = val - end - - # Get the entity expansion limit. By default the limit is set to 10000. - def self.entity_expansion_limit - return @@entity_expansion_limit - end - - @@entity_expansion_text_limit = 10_240 - - # Set the entity expansion limit. By default the limit is set to 10240. - def self.entity_expansion_text_limit=( val ) - @@entity_expansion_text_limit = val - end - - # Get the entity expansion limit. By default the limit is set to 10240. - def self.entity_expansion_text_limit - return @@entity_expansion_text_limit - end - end -end diff --git a/ruby/lib/rexml/source.rb b/ruby/lib/rexml/source.rb deleted file mode 100644 index 90b370b98..000000000 --- a/ruby/lib/rexml/source.rb +++ /dev/null @@ -1,298 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: false -require_relative 'encoding' - -module REXML - # Generates Source-s. USE THIS CLASS. - class SourceFactory - # Generates a Source object - # @param arg Either a String, or an IO - # @return a Source, or nil if a bad argument was given - def SourceFactory::create_from(arg) - if arg.respond_to? :read and - arg.respond_to? :readline and - arg.respond_to? :nil? and - arg.respond_to? :eof? - IOSource.new(arg) - elsif arg.respond_to? :to_str - require 'stringio' - IOSource.new(StringIO.new(arg)) - elsif arg.kind_of? Source - arg - else - raise "#{arg.class} is not a valid input stream. It must walk \n"+ - "like either a String, an IO, or a Source." - end - end - end - - # A Source can be searched for patterns, and wraps buffers and other - # objects and provides consumption of text - class Source - include Encoding - # The current buffer (what we're going to read next) - attr_reader :buffer - # The line number of the last consumed text - attr_reader :line - attr_reader :encoding - - # Constructor - # @param arg must be a String, and should be a valid XML document - # @param encoding if non-null, sets the encoding of the source to this - # value, overriding all encoding detection - def initialize(arg, encoding=nil) - @orig = @buffer = arg - if encoding - self.encoding = encoding - else - detect_encoding - end - @line = 0 - end - - - # Inherited from Encoding - # Overridden to support optimized en/decoding - def encoding=(enc) - return unless super - encoding_updated - end - - # Scans the source for a given pattern. Note, that this is not your - # usual scan() method. For one thing, the pattern argument has some - # requirements; for another, the source can be consumed. You can easily - # confuse this method. Originally, the patterns were easier - # to construct and this method more robust, because this method - # generated search regexps on the fly; however, this was - # computationally expensive and slowed down the entire REXML package - # considerably, since this is by far the most commonly called method. - # @param pattern must be a Regexp, and must be in the form of - # /^\s*(#{your pattern, with no groups})(.*)/. The first group - # will be returned; the second group is used if the consume flag is - # set. - # @param consume if true, the pattern returned will be consumed, leaving - # everything after it in the Source. - # @return the pattern, if found, or nil if the Source is empty or the - # pattern is not found. - def scan(pattern, cons=false) - return nil if @buffer.nil? - rv = @buffer.scan(pattern) - @buffer = $' if cons and rv.size>0 - rv - end - - def read - end - - def consume( pattern ) - @buffer = $' if pattern.match( @buffer ) - end - - def match_to( char, pattern ) - return pattern.match(@buffer) - end - - def match_to_consume( char, pattern ) - md = pattern.match(@buffer) - @buffer = $' - return md - end - - def match(pattern, cons=false) - md = pattern.match(@buffer) - @buffer = $' if cons and md - return md - end - - # @return true if the Source is exhausted - def empty? - @buffer == "" - end - - def position - @orig.index( @buffer ) - end - - # @return the current line in the source - def current_line - lines = @orig.split - res = lines.grep @buffer[0..30] - res = res[-1] if res.kind_of? Array - lines.index( res ) if res - end - - private - def detect_encoding - buffer_encoding = @buffer.encoding - detected_encoding = "UTF-8" - begin - @buffer.force_encoding("ASCII-8BIT") - if @buffer[0, 2] == "\xfe\xff" - @buffer[0, 2] = "" - detected_encoding = "UTF-16BE" - elsif @buffer[0, 2] == "\xff\xfe" - @buffer[0, 2] = "" - detected_encoding = "UTF-16LE" - elsif @buffer[0, 3] == "\xef\xbb\xbf" - @buffer[0, 3] = "" - detected_encoding = "UTF-8" - end - ensure - @buffer.force_encoding(buffer_encoding) - end - self.encoding = detected_encoding - end - - def encoding_updated - if @encoding != 'UTF-8' - @buffer = decode(@buffer) - @to_utf = true - else - @to_utf = false - @buffer.force_encoding ::Encoding::UTF_8 - end - end - end - - # A Source that wraps an IO. See the Source class for method - # documentation - class IOSource < Source - #attr_reader :block_size - - # block_size has been deprecated - def initialize(arg, block_size=500, encoding=nil) - @er_source = @source = arg - @to_utf = false - @pending_buffer = nil - - if encoding - super("", encoding) - else - super(@source.read(3) || "") - end - - if !@to_utf and - @buffer.respond_to?(:force_encoding) and - @source.respond_to?(:external_encoding) and - @source.external_encoding != ::Encoding::UTF_8 - @force_utf8 = true - else - @force_utf8 = false - end - end - - def scan(pattern, cons=false) - rv = super - # You'll notice that this next section is very similar to the same - # section in match(), but just a liiittle different. This is - # because it is a touch faster to do it this way with scan() - # than the way match() does it; enough faster to warrant duplicating - # some code - if rv.size == 0 - until @buffer =~ pattern or @source.nil? - begin - @buffer << readline - rescue Iconv::IllegalSequence - raise - rescue - @source = nil - end - end - rv = super - end - rv.taint if RUBY_VERSION < '2.7' - rv - end - - def read - begin - @buffer << readline - rescue Exception, NameError - @source = nil - end - end - - def consume( pattern ) - match( pattern, true ) - end - - def match( pattern, cons=false ) - rv = pattern.match(@buffer) - @buffer = $' if cons and rv - while !rv and @source - begin - @buffer << readline - rv = pattern.match(@buffer) - @buffer = $' if cons and rv - rescue - @source = nil - end - end - rv.taint if RUBY_VERSION < '2.7' - rv - end - - def empty? - super and ( @source.nil? || @source.eof? ) - end - - def position - @er_source.pos rescue 0 - end - - # @return the current line in the source - def current_line - begin - pos = @er_source.pos # The byte position in the source - lineno = @er_source.lineno # The XML < position in the source - @er_source.rewind - line = 0 # The \r\n position in the source - begin - while @er_source.pos < pos - @er_source.readline - line += 1 - end - rescue - end - @er_source.seek(pos) - rescue IOError - pos = -1 - line = -1 - end - [pos, lineno, line] - end - - private - def readline - str = @source.readline(@line_break) - if @pending_buffer - if str.nil? - str = @pending_buffer - else - str = @pending_buffer + str - end - @pending_buffer = nil - end - return nil if str.nil? - - if @to_utf - decode(str) - else - str.force_encoding(::Encoding::UTF_8) if @force_utf8 - str - end - end - - def encoding_updated - case @encoding - when "UTF-16BE", "UTF-16LE" - @source.binmode - @source.set_encoding(@encoding, @encoding) - end - @line_break = encode(">") - @pending_buffer, @buffer = @buffer, "" - @pending_buffer.force_encoding(@encoding) - super - end - end -end diff --git a/ruby/lib/rexml/streamlistener.rb b/ruby/lib/rexml/streamlistener.rb deleted file mode 100644 index 30c894517..000000000 --- a/ruby/lib/rexml/streamlistener.rb +++ /dev/null @@ -1,93 +0,0 @@ -# frozen_string_literal: false -module REXML - # A template for stream parser listeners. - # Note that the declarations (attlistdecl, elementdecl, etc) are trivially - # processed; REXML doesn't yet handle doctype entity declarations, so you - # have to parse them out yourself. - module StreamListener - # Called when a tag is encountered. - # @p name the tag name - # @p attrs an array of arrays of attribute/value pairs, suitable for - # use with assoc or rassoc. IE, - # will result in - # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]]) - def tag_start name, attrs - end - # Called when the end tag is reached. In the case of , tag_end - # will be called immediately after tag_start - # @p the name of the tag - def tag_end name - end - # Called when text is encountered in the document - # @p text the text content. - def text text - end - # Called when an instruction is encountered. EG: - # @p name the instruction name; in the example, "xsl" - # @p instruction the rest of the instruction. In the example, - # "sheet='foo'" - def instruction name, instruction - end - # Called when a comment is encountered. - # @p comment The content of the comment - def comment comment - end - # Handles a doctype declaration. Any attributes of the doctype which are - # not supplied will be nil. # EG, - # @p name the name of the doctype; EG, "me" - # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" - # @p long_name the supplied long name, or nil. EG, "foo" - # @p uri the uri of the doctype, or nil. EG, "bar" - def doctype name, pub_sys, long_name, uri - end - # Called when the doctype is done - def doctype_end - end - # If a doctype includes an ATTLIST declaration, it will cause this - # method to be called. The content is the declaration itself, unparsed. - # EG, will come to this method as "el - # attr CDATA #REQUIRED". This is the same for all of the .*decl - # methods. - def attlistdecl element_name, attributes, raw_content - end - # - def elementdecl content - end - # - # The argument passed to this method is an array of the entity - # declaration. It can be in a number of formats, but in general it - # returns (example, result): - # - # ["YN", "\"Yes\"", "%"] - # - # ["YN", "Yes", "%"] - # - # ["WhatHeSaid", "He said %YN;"] - # - # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"] - # - # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"] - # - # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "gif"] - def entitydecl content - end - # - def notationdecl content - end - # Called when %foo; is encountered in a doctype declaration. - # @p content "foo" - def entity content - end - # Called when is encountered in a document. - # @p content "..." - def cdata content - end - # Called when an XML PI is encountered in the document. - # EG: - # @p version the version attribute value. EG, "1.0" - # @p encoding the encoding attribute value, or nil. EG, "utf" - # @p standalone the standalone attribute value, or nil. EG, nil - def xmldecl version, encoding, standalone - end - end -end diff --git a/ruby/lib/rexml/text.rb b/ruby/lib/rexml/text.rb deleted file mode 100644 index 050b09c97..000000000 --- a/ruby/lib/rexml/text.rb +++ /dev/null @@ -1,424 +0,0 @@ -# frozen_string_literal: false -require_relative 'security' -require_relative 'entity' -require_relative 'doctype' -require_relative 'child' -require_relative 'doctype' -require_relative 'parseexception' - -module REXML - # Represents text nodes in an XML document - class Text < Child - include Comparable - # The order in which the substitutions occur - SPECIALS = [ /&(?!#?[\w-]+;)/u, //u, /"/u, /'/u, /\r/u ] - SUBSTITUTES = ['&', '<', '>', '"', ''', ' '] - # Characters which are substituted in written strings - SLAICEPS = [ '<', '>', '"', "'", '&' ] - SETUTITSBUS = [ /</u, />/u, /"/u, /'/u, /&/u ] - - # If +raw+ is true, then REXML leaves the value alone - attr_accessor :raw - - NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um - NUMERICENTITY = /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ - VALID_CHAR = [ - 0x9, 0xA, 0xD, - (0x20..0xD7FF), - (0xE000..0xFFFD), - (0x10000..0x10FFFF) - ] - - if String.method_defined? :encode - VALID_XML_CHARS = Regexp.new('^['+ - VALID_CHAR.map { |item| - case item - when Integer - [item].pack('U').force_encoding('utf-8') - when Range - [item.first, '-'.ord, item.last].pack('UUU').force_encoding('utf-8') - end - }.join + - ']*$') - else - VALID_XML_CHARS = /^( - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE][\x80-\xBF]{2} # straight 3-byte - | \xEF[\x80-\xBE]{2} # - | \xEF\xBF[\x80-\xBD] # excluding U+fffe and U+ffff - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )*$/nx; - end - - # Constructor - # +arg+ if a String, the content is set to the String. If a Text, - # the object is shallowly cloned. - # - # +respect_whitespace+ (boolean, false) if true, whitespace is - # respected - # - # +parent+ (nil) if this is a Parent object, the parent - # will be set to this. - # - # +raw+ (nil) This argument can be given three values. - # If true, then the value of used to construct this object is expected to - # contain no unescaped XML markup, and REXML will not change the text. If - # this value is false, the string may contain any characters, and REXML will - # escape any and all defined entities whose values are contained in the - # text. If this value is nil (the default), then the raw value of the - # parent will be used as the raw value for this node. If there is no raw - # value for the parent, and no value is supplied, the default is false. - # Use this field if you have entities defined for some text, and you don't - # want REXML to escape that text in output. - # Text.new( "<&", false, nil, false ) #-> "<&" - # Text.new( "<&", false, nil, false ) #-> "&lt;&amp;" - # Text.new( "<&", false, nil, true ) #-> Parse exception - # Text.new( "<&", false, nil, true ) #-> "<&" - # # Assume that the entity "s" is defined to be "sean" - # # and that the entity "r" is defined to be "russell" - # Text.new( "sean russell" ) #-> "&s; &r;" - # Text.new( "sean russell", false, nil, true ) #-> "sean russell" - # - # +entity_filter+ (nil) This can be an array of entities to match in the - # supplied text. This argument is only useful if +raw+ is set to false. - # Text.new( "sean russell", false, nil, false, ["s"] ) #-> "&s; russell" - # Text.new( "sean russell", false, nil, true, ["s"] ) #-> "sean russell" - # In the last example, the +entity_filter+ argument is ignored. - # - # +illegal+ INTERNAL USE ONLY - def initialize(arg, respect_whitespace=false, parent=nil, raw=nil, - entity_filter=nil, illegal=NEEDS_A_SECOND_CHECK ) - - @raw = false - @parent = nil - @entity_filter = nil - - if parent - super( parent ) - @raw = parent.raw - end - - if arg.kind_of? String - @string = arg.dup - elsif arg.kind_of? Text - @string = arg.instance_variable_get(:@string).dup - @raw = arg.raw - @entity_filter = arg.instance_variable_get(:@entity_filter) - else - raise "Illegal argument of type #{arg.type} for Text constructor (#{arg})" - end - - @string.squeeze!(" \n\t") unless respect_whitespace - @string.gsub!(/\r\n?/, "\n") - @raw = raw unless raw.nil? - @entity_filter = entity_filter if entity_filter - clear_cache - - Text.check(@string, illegal, doctype) if @raw - end - - def parent= parent - super(parent) - Text.check(@string, NEEDS_A_SECOND_CHECK, doctype) if @raw and @parent - end - - # check for illegal characters - def Text.check string, pattern, doctype - - # illegal anywhere - if string !~ VALID_XML_CHARS - if String.method_defined? :encode - string.chars.each do |c| - case c.ord - when *VALID_CHAR - else - raise "Illegal character #{c.inspect} in raw string #{string.inspect}" - end - end - else - string.scan(/[\x00-\x7F]|[\x80-\xBF][\xC0-\xF0]*|[\xC0-\xF0]/n) do |c| - case c.unpack('U') - when *VALID_CHAR - else - raise "Illegal character #{c.inspect} in raw string #{string.inspect}" - end - end - end - end - - # context sensitive - string.scan(pattern) do - if $1[-1] != ?; - raise "Illegal character #{$1.inspect} in raw string #{string.inspect}" - elsif $1[0] == ?& - if $5 and $5[0] == ?# - case ($5[1] == ?x ? $5[2..-1].to_i(16) : $5[1..-1].to_i) - when *VALID_CHAR - else - raise "Illegal character #{$1.inspect} in raw string #{string.inspect}" - end - # FIXME: below can't work but this needs API change. - # elsif @parent and $3 and !SUBSTITUTES.include?($1) - # if !doctype or !doctype.entities.has_key?($3) - # raise "Undeclared entity '#{$1}' in raw string \"#{string}\"" - # end - end - end - end - end - - def node_type - :text - end - - def empty? - @string.size==0 - end - - - def clone - return Text.new(self, true) - end - - - # Appends text to this text node. The text is appended in the +raw+ mode - # of this text node. - # - # +returns+ the text itself to enable method chain like - # 'text << "XXX" << "YYY"'. - def <<( to_append ) - @string << to_append.gsub( /\r\n?/, "\n" ) - clear_cache - self - end - - - # +other+ a String or a Text - # +returns+ the result of (to_s <=> arg.to_s) - def <=>( other ) - to_s() <=> other.to_s - end - - def doctype - if @parent - doc = @parent.document - doc.doctype if doc - end - end - - REFERENCE = /#{Entity::REFERENCE}/ - # Returns the string value of this text node. This string is always - # escaped, meaning that it is a valid XML text node string, and all - # entities that can be escaped, have been inserted. This method respects - # the entity filter set in the constructor. - # - # # Assume that the entity "s" is defined to be "sean", and that the - # # entity "r" is defined to be "russell" - # t = Text.new( "< & sean russell", false, nil, false, ['s'] ) - # t.to_s #-> "< & &s; russell" - # t = Text.new( "< & &s; russell", false, nil, false ) - # t.to_s #-> "< & &s; russell" - # u = Text.new( "sean russell", false, nil, true ) - # u.to_s #-> "sean russell" - def to_s - return @string if @raw - @normalized ||= Text::normalize( @string, doctype, @entity_filter ) - end - - def inspect - @string.inspect - end - - # Returns the string value of this text. This is the text without - # entities, as it might be used programmatically, or printed to the - # console. This ignores the 'raw' attribute setting, and any - # entity_filter. - # - # # Assume that the entity "s" is defined to be "sean", and that the - # # entity "r" is defined to be "russell" - # t = Text.new( "< & sean russell", false, nil, false, ['s'] ) - # t.value #-> "< & sean russell" - # t = Text.new( "< & &s; russell", false, nil, false ) - # t.value #-> "< & sean russell" - # u = Text.new( "sean russell", false, nil, true ) - # u.value #-> "sean russell" - def value - @unnormalized ||= Text::unnormalize( @string, doctype ) - end - - # Sets the contents of this text node. This expects the text to be - # unnormalized. It returns self. - # - # e = Element.new( "a" ) - # e.add_text( "foo" ) # foo - # e[0].value = "bar" # bar - # e[0].value = "" # <a> - def value=( val ) - @string = val.gsub( /\r\n?/, "\n" ) - clear_cache - @raw = false - end - - def wrap(string, width, addnewline=false) - # Recursively wrap string at width. - return string if string.length <= width - place = string.rindex(' ', width) # Position in string with last ' ' before cutoff - if addnewline then - return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width) - else - return string[0,place] + "\n" + wrap(string[place+1..-1], width) - end - end - - def indent_text(string, level=1, style="\t", indentfirstline=true) - return string if level < 0 - new_string = '' - string.each_line { |line| - indent_string = style * level - new_line = (indent_string + line).sub(/[\s]+$/,'') - new_string << new_line - } - new_string.strip! unless indentfirstline - return new_string - end - - # == DEPRECATED - # See REXML::Formatters - # - def write( writer, indent=-1, transitive=false, ie_hack=false ) - Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1) - formatter = if indent > -1 - REXML::Formatters::Pretty.new( indent ) - else - REXML::Formatters::Default.new - end - formatter.write( self, writer ) - end - - # FIXME - # This probably won't work properly - def xpath - path = @parent.xpath - path += "/text()" - return path - end - - # Writes out text, substituting special characters beforehand. - # +out+ A String, IO, or any other object supporting <<( String ) - # +input+ the text to substitute and the write out - # - # z=utf8.unpack("U*") - # ascOut="" - # z.each{|r| - # if r < 0x100 - # ascOut.concat(r.chr) - # else - # ascOut.concat(sprintf("&#x%x;", r)) - # end - # } - # puts ascOut - def write_with_substitution out, input - copy = input.clone - # Doing it like this rather than in a loop improves the speed - copy.gsub!( SPECIALS[0], SUBSTITUTES[0] ) - copy.gsub!( SPECIALS[1], SUBSTITUTES[1] ) - copy.gsub!( SPECIALS[2], SUBSTITUTES[2] ) - copy.gsub!( SPECIALS[3], SUBSTITUTES[3] ) - copy.gsub!( SPECIALS[4], SUBSTITUTES[4] ) - copy.gsub!( SPECIALS[5], SUBSTITUTES[5] ) - out << copy - end - - private - def clear_cache - @normalized = nil - @unnormalized = nil - end - - # Reads text, substituting entities - def Text::read_with_substitution( input, illegal=nil ) - copy = input.clone - - if copy =~ illegal - raise ParseException.new( "malformed text: Illegal character #$& in \"#{copy}\"" ) - end if illegal - - copy.gsub!( /\r\n?/, "\n" ) - if copy.include? ?& - copy.gsub!( SETUTITSBUS[0], SLAICEPS[0] ) - copy.gsub!( SETUTITSBUS[1], SLAICEPS[1] ) - copy.gsub!( SETUTITSBUS[2], SLAICEPS[2] ) - copy.gsub!( SETUTITSBUS[3], SLAICEPS[3] ) - copy.gsub!( SETUTITSBUS[4], SLAICEPS[4] ) - copy.gsub!( /�*((?:\d+)|(?:x[a-f0-9]+));/ ) { - m=$1 - #m='0' if m=='' - m = "0#{m}" if m[0] == ?x - [Integer(m)].pack('U*') - } - end - copy - end - - EREFERENCE = /&(?!#{Entity::NAME};)/ - # Escapes all possible entities - def Text::normalize( input, doctype=nil, entity_filter=nil ) - copy = input.to_s - # Doing it like this rather than in a loop improves the speed - #copy = copy.gsub( EREFERENCE, '&' ) - copy = copy.gsub( "&", "&" ) - if doctype - # Replace all ampersands that aren't part of an entity - doctype.entities.each_value do |entity| - copy = copy.gsub( entity.value, - "&#{entity.name};" ) if entity.value and - not( entity_filter and entity_filter.include?(entity.name) ) - end - else - # Replace all ampersands that aren't part of an entity - DocType::DEFAULT_ENTITIES.each_value do |entity| - copy = copy.gsub(entity.value, "&#{entity.name};" ) - end - end - copy - end - - # Unescapes all possible entities - def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil ) - sum = 0 - string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) { - s = Text.expand($&, doctype, filter) - if sum + s.bytesize > Security.entity_expansion_text_limit - raise "entity expansion has grown too large" - else - sum += s.bytesize - end - s - } - end - - def Text.expand(ref, doctype, filter) - if ref[1] == ?# - if ref[2] == ?x - [ref[3...-1].to_i(16)].pack('U*') - else - [ref[2...-1].to_i].pack('U*') - end - elsif ref == '&' - '&' - elsif filter and filter.include?( ref[1...-1] ) - ref - elsif doctype - doctype.entity( ref[1...-1] ) or ref - else - entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ] - entity_value ? entity_value.value : ref - end - end - end -end diff --git a/ruby/lib/rexml/undefinednamespaceexception.rb b/ruby/lib/rexml/undefinednamespaceexception.rb deleted file mode 100644 index 492a09818..000000000 --- a/ruby/lib/rexml/undefinednamespaceexception.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false -require_relative 'parseexception' -module REXML - class UndefinedNamespaceException < ParseException - def initialize( prefix, source, parser ) - super( "Undefined prefix #{prefix} found" ) - end - end -end diff --git a/ruby/lib/rexml/validation/relaxng.rb b/ruby/lib/rexml/validation/relaxng.rb deleted file mode 100644 index f29a2c05e..000000000 --- a/ruby/lib/rexml/validation/relaxng.rb +++ /dev/null @@ -1,539 +0,0 @@ -# frozen_string_literal: false -require_relative "validation" -require_relative "../parsers/baseparser" - -module REXML - module Validation - # Implemented: - # * empty - # * element - # * attribute - # * text - # * optional - # * choice - # * oneOrMore - # * zeroOrMore - # * group - # * value - # * interleave - # * mixed - # * ref - # * grammar - # * start - # * define - # - # Not implemented: - # * data - # * param - # * include - # * externalRef - # * notAllowed - # * anyName - # * nsName - # * except - # * name - class RelaxNG - include Validator - - INFINITY = 1.0 / 0.0 - EMPTY = Event.new( nil ) - TEXT = [:start_element, "text"] - attr_accessor :current - attr_accessor :count - attr_reader :references - - # FIXME: Namespaces - def initialize source - parser = REXML::Parsers::BaseParser.new( source ) - - @count = 0 - @references = {} - @root = @current = Sequence.new(self) - @root.previous = true - states = [ @current ] - begin - event = parser.pull - case event[0] - when :start_element - case event[1] - when "empty" - when "element", "attribute", "text", "value" - states[-1] << event - when "optional" - states << Optional.new( self ) - states[-2] << states[-1] - when "choice" - states << Choice.new( self ) - states[-2] << states[-1] - when "oneOrMore" - states << OneOrMore.new( self ) - states[-2] << states[-1] - when "zeroOrMore" - states << ZeroOrMore.new( self ) - states[-2] << states[-1] - when "group" - states << Sequence.new( self ) - states[-2] << states[-1] - when "interleave" - states << Interleave.new( self ) - states[-2] << states[-1] - when "mixed" - states << Interleave.new( self ) - states[-2] << states[-1] - states[-1] << TEXT - when "define" - states << [ event[2]["name"] ] - when "ref" - states[-1] << Ref.new( event[2]["name"] ) - when "anyName" - states << AnyName.new( self ) - states[-2] << states[-1] - when "nsName" - when "except" - when "name" - when "data" - when "param" - when "include" - when "grammar" - when "start" - when "externalRef" - when "notAllowed" - end - when :end_element - case event[1] - when "element", "attribute" - states[-1] << event - when "zeroOrMore", "oneOrMore", "choice", "optional", - "interleave", "group", "mixed" - states.pop - when "define" - ref = states.pop - @references[ ref.shift ] = ref - #when "empty" - end - when :end_document - states[-1] << event - when :text - states[-1] << event - end - end while event[0] != :end_document - end - - def receive event - validate( event ) - end - end - - class State - def initialize( context ) - @previous = [] - @events = [] - @current = 0 - @count = context.count += 1 - @references = context.references - @value = false - end - - def reset - return if @current == 0 - @current = 0 - @events.each {|s| s.reset if s.kind_of? State } - end - - def previous=( previous ) - @previous << previous - end - - def next( event ) - #print "In next with #{event.inspect}. " - #p @previous - return @previous.pop.next( event ) if @events[@current].nil? - expand_ref_in( @events, @current ) if @events[@current].class == Ref - if ( @events[@current].kind_of? State ) - @current += 1 - @events[@current-1].previous = self - return @events[@current-1].next( event ) - end - if ( @events[@current].matches?(event) ) - @current += 1 - if @events[@current].nil? - return @previous.pop - elsif @events[@current].kind_of? State - @current += 1 - @events[@current-1].previous = self - return @events[@current-1] - else - return self - end - else - return nil - end - end - - def to_s - # Abbreviated: - self.class.name =~ /(?:::)(\w)\w+$/ - # Full: - #self.class.name =~ /(?:::)(\w+)$/ - "#$1.#@count" - end - - def inspect - "< #{to_s} #{@events.collect{|e| - pre = e == @events[@current] ? '#' : '' - pre + e.inspect unless self == e - }.join(', ')} >" - end - - def expected - return [@events[@current]] - end - - def <<( event ) - add_event_to_arry( @events, event ) - end - - - protected - def expand_ref_in( arry, ind ) - new_events = [] - @references[ arry[ind].to_s ].each{ |evt| - add_event_to_arry(new_events,evt) - } - arry[ind,1] = new_events - end - - def add_event_to_arry( arry, evt ) - evt = generate_event( evt ) - if evt.kind_of? String - arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value - @value = false - else - arry << evt - end - end - - def generate_event( event ) - return event if event.kind_of? State or event.class == Ref - evt = nil - arg = nil - case event[0] - when :start_element - case event[1] - when "element" - evt = :start_element - arg = event[2]["name"] - when "attribute" - evt = :start_attribute - arg = event[2]["name"] - when "text" - evt = :text - when "value" - evt = :text - @value = true - end - when :text - return event[1] - when :end_document - return Event.new( event[0] ) - else # then :end_element - case event[1] - when "element" - evt = :end_element - when "attribute" - evt = :end_attribute - end - end - return Event.new( evt, arg ) - end - end - - - class Sequence < State - def matches?(event) - @events[@current].matches?( event ) - end - end - - - class Optional < State - def next( event ) - if @current == 0 - rv = super - return rv if rv - @prior = @previous.pop - return @prior.next( event ) - end - super - end - - def matches?(event) - @events[@current].matches?(event) || - (@current == 0 and @previous[-1].matches?(event)) - end - - def expected - return [ @prior.expected, @events[0] ].flatten if @current == 0 - return [@events[@current]] - end - end - - - class ZeroOrMore < Optional - def next( event ) - expand_ref_in( @events, @current ) if @events[@current].class == Ref - if ( @events[@current].matches?(event) ) - @current += 1 - if @events[@current].nil? - @current = 0 - return self - elsif @events[@current].kind_of? State - @current += 1 - @events[@current-1].previous = self - return @events[@current-1] - else - return self - end - else - @prior = @previous.pop - return @prior.next( event ) if @current == 0 - return nil - end - end - - def expected - return [ @prior.expected, @events[0] ].flatten if @current == 0 - return [@events[@current]] - end - end - - - class OneOrMore < State - def initialize context - super - @ord = 0 - end - - def reset - super - @ord = 0 - end - - def next( event ) - expand_ref_in( @events, @current ) if @events[@current].class == Ref - if ( @events[@current].matches?(event) ) - @current += 1 - @ord += 1 - if @events[@current].nil? - @current = 0 - return self - elsif @events[@current].kind_of? State - @current += 1 - @events[@current-1].previous = self - return @events[@current-1] - else - return self - end - else - return @previous.pop.next( event ) if @current == 0 and @ord > 0 - return nil - end - end - - def matches?( event ) - @events[@current].matches?(event) || - (@current == 0 and @ord > 0 and @previous[-1].matches?(event)) - end - - def expected - if @current == 0 and @ord > 0 - return [@previous[-1].expected, @events[0]].flatten - else - return [@events[@current]] - end - end - end - - - class Choice < State - def initialize context - super - @choices = [] - end - - def reset - super - @events = [] - @choices.each { |c| c.each { |s| s.reset if s.kind_of? State } } - end - - def <<( event ) - add_event_to_arry( @choices, event ) - end - - def next( event ) - # Make the choice if we haven't - if @events.size == 0 - c = 0 ; max = @choices.size - while c < max - if @choices[c][0].class == Ref - expand_ref_in( @choices[c], 0 ) - @choices += @choices[c] - @choices.delete( @choices[c] ) - max -= 1 - else - c += 1 - end - end - @events = @choices.find { |evt| evt[0].matches? event } - # Remove the references - # Find the events - end - unless @events - @events = [] - return nil - end - super - end - - def matches?( event ) - return @events[@current].matches?( event ) if @events.size > 0 - !@choices.find{|evt| evt[0].matches?(event)}.nil? - end - - def expected - return [@events[@current]] if @events.size > 0 - return @choices.collect do |x| - if x[0].kind_of? State - x[0].expected - else - x[0] - end - end.flatten - end - - def inspect - "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' or ')} >" - end - - protected - def add_event_to_arry( arry, evt ) - if evt.kind_of? State or evt.class == Ref - arry << [evt] - elsif evt[0] == :text - if arry[-1] and - arry[-1][-1].kind_of?( Event ) and - arry[-1][-1].event_type == :text and @value - - arry[-1][-1].event_arg = evt[1] - @value = false - end - else - arry << [] if evt[0] == :start_element - arry[-1] << generate_event( evt ) - end - end - end - - - class Interleave < Choice - def initialize context - super - @choice = 0 - end - - def reset - @choice = 0 - end - - def next_current( event ) - # Expand references - c = 0 ; max = @choices.size - while c < max - if @choices[c][0].class == Ref - expand_ref_in( @choices[c], 0 ) - @choices += @choices[c] - @choices.delete( @choices[c] ) - max -= 1 - else - c += 1 - end - end - @events = @choices[@choice..-1].find { |evt| evt[0].matches? event } - @current = 0 - if @events - # reorder the choices - old = @choices[@choice] - idx = @choices.index( @events ) - @choices[@choice] = @events - @choices[idx] = old - @choice += 1 - end - - @events = [] unless @events - end - - - def next( event ) - # Find the next series - next_current(event) unless @events[@current] - return nil unless @events[@current] - - expand_ref_in( @events, @current ) if @events[@current].class == Ref - if ( @events[@current].kind_of? State ) - @current += 1 - @events[@current-1].previous = self - return @events[@current-1].next( event ) - end - return @previous.pop.next( event ) if @events[@current].nil? - if ( @events[@current].matches?(event) ) - @current += 1 - if @events[@current].nil? - return self unless @choices[@choice].nil? - return @previous.pop - elsif @events[@current].kind_of? State - @current += 1 - @events[@current-1].previous = self - return @events[@current-1] - else - return self - end - else - return nil - end - end - - def matches?( event ) - return @events[@current].matches?( event ) if @events[@current] - !@choices[@choice..-1].find{|evt| evt[0].matches?(event)}.nil? - end - - def expected - return [@events[@current]] if @events[@current] - return @choices[@choice..-1].collect do |x| - if x[0].kind_of? State - x[0].expected - else - x[0] - end - end.flatten - end - - def inspect - "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' and ')} >" - end - end - - class Ref - def initialize value - @value = value - end - def to_s - @value - end - def inspect - "{#{to_s}}" - end - end - end -end diff --git a/ruby/lib/rexml/validation/validation.rb b/ruby/lib/rexml/validation/validation.rb deleted file mode 100644 index 0ad6ada42..000000000 --- a/ruby/lib/rexml/validation/validation.rb +++ /dev/null @@ -1,144 +0,0 @@ -# frozen_string_literal: false -require_relative 'validationexception' - -module REXML - module Validation - module Validator - NILEVENT = [ nil ] - def reset - @current = @root - @root.reset - @root.previous = true - @attr_stack = [] - self - end - def dump - puts @root.inspect - end - def validate( event ) - @attr_stack = [] unless defined? @attr_stack - match = @current.next(event) - raise ValidationException.new( "Validation error. Expected: "+ - @current.expected.join( " or " )+" from #{@current.inspect} "+ - " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match - @current = match - - # Check for attributes - case event[0] - when :start_element - @attr_stack << event[2] - begin - sattr = [:start_attribute, nil] - eattr = [:end_attribute] - text = [:text, nil] - k, = event[2].find { |key,value| - sattr[1] = key - m = @current.next( sattr ) - if m - # If the state has text children... - if m.matches?( eattr ) - @current = m - else - text[1] = value - m = m.next( text ) - text[1] = nil - return false unless m - @current = m if m - end - m = @current.next( eattr ) - if m - @current = m - true - else - false - end - else - false - end - } - event[2].delete(k) if k - end while k - when :end_element - attrs = @attr_stack.pop - raise ValidationException.new( "Validation error. Illegal "+ - " attributes: #{attrs.inspect}") if attrs.length > 0 - end - end - end - - class Event - def initialize(event_type, event_arg=nil ) - @event_type = event_type - @event_arg = event_arg - end - - attr_reader :event_type - attr_accessor :event_arg - - def done? - @done - end - - def single? - return (@event_type != :start_element and @event_type != :start_attribute) - end - - def matches?( event ) - return false unless event[0] == @event_type - case event[0] - when nil - return true - when :start_element - return true if event[1] == @event_arg - when :end_element - return true - when :start_attribute - return true if event[1] == @event_arg - when :end_attribute - return true - when :end_document - return true - when :text - return (@event_arg.nil? or @event_arg == event[1]) -=begin - when :processing_instruction - false - when :xmldecl - false - when :start_doctype - false - when :end_doctype - false - when :externalentity - false - when :elementdecl - false - when :entity - false - when :attlistdecl - false - when :notationdecl - false - when :end_doctype - false -=end - else - false - end - end - - def ==( other ) - return false unless other.kind_of? Event - @event_type == other.event_type and @event_arg == other.event_arg - end - - def to_s - inspect - end - - def inspect - "#{@event_type.inspect}( #@event_arg )" - end - end - end -end diff --git a/ruby/lib/rexml/validation/validationexception.rb b/ruby/lib/rexml/validation/validationexception.rb deleted file mode 100644 index 78cd63fd0..000000000 --- a/ruby/lib/rexml/validation/validationexception.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: false -module REXML - module Validation - class ValidationException < RuntimeError - def initialize msg - super - end - end - end -end diff --git a/ruby/lib/rexml/xmldecl.rb b/ruby/lib/rexml/xmldecl.rb deleted file mode 100644 index d19407cef..000000000 --- a/ruby/lib/rexml/xmldecl.rb +++ /dev/null @@ -1,130 +0,0 @@ -# frozen_string_literal: false - -require_relative 'encoding' -require_relative 'source' - -module REXML - # NEEDS DOCUMENTATION - class XMLDecl < Child - include Encoding - - DEFAULT_VERSION = "1.0" - DEFAULT_ENCODING = "UTF-8" - DEFAULT_STANDALONE = "no" - START = "" - - attr_accessor :version, :standalone - attr_reader :writeencoding, :writethis - - def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil) - @writethis = true - @writeencoding = !encoding.nil? - if version.kind_of? XMLDecl - super() - @version = version.version - self.encoding = version.encoding - @writeencoding = version.writeencoding - @standalone = version.standalone - @writethis = version.writethis - else - super() - @version = version - self.encoding = encoding - @standalone = standalone - end - @version = DEFAULT_VERSION if @version.nil? - end - - def clone - XMLDecl.new(self) - end - - # indent:: - # Ignored. There must be no whitespace before an XML declaration - # transitive:: - # Ignored - # ie_hack:: - # Ignored - def write(writer, indent=-1, transitive=false, ie_hack=false) - return nil unless @writethis or writer.kind_of? Output - writer << START - writer << " #{content encoding}" - writer << STOP - end - - def ==( other ) - other.kind_of?(XMLDecl) and - other.version == @version and - other.encoding == self.encoding and - other.standalone == @standalone - end - - def xmldecl version, encoding, standalone - @version = version - self.encoding = encoding - @standalone = standalone - end - - def node_type - :xmldecl - end - - alias :stand_alone? :standalone - alias :old_enc= :encoding= - - def encoding=( enc ) - if enc.nil? - self.old_enc = "UTF-8" - @writeencoding = false - else - self.old_enc = enc - @writeencoding = true - end - self.dowrite - end - - # Only use this if you do not want the XML declaration to be written; - # this object is ignored by the XML writer. Otherwise, instantiate your - # own XMLDecl and add it to the document. - # - # Note that XML 1.1 documents *must* include an XML declaration - def XMLDecl.default - rv = XMLDecl.new( "1.0" ) - rv.nowrite - rv - end - - def nowrite - @writethis = false - end - - def dowrite - @writethis = true - end - - def inspect - "#{START} ... #{STOP}" - end - - private - def content(enc) - context = nil - context = parent.context if parent - if context and context[:prologue_quote] == :quote - quote = "\"" - else - quote = "'" - end - - rv = "version=#{quote}#{@version}#{quote}" - if @writeencoding or enc !~ /\Autf-8\z/i - rv << " encoding=#{quote}#{enc}#{quote}" - end - if @standalone - rv << " standalone=#{quote}#{@standalone}#{quote}" - end - rv - end - end -end diff --git a/ruby/lib/rexml/xmltokens.rb b/ruby/lib/rexml/xmltokens.rb deleted file mode 100644 index 392b47b1d..000000000 --- a/ruby/lib/rexml/xmltokens.rb +++ /dev/null @@ -1,85 +0,0 @@ -# frozen_string_literal: false -module REXML - # Defines a number of tokens used for parsing XML. Not for general - # consumption. - module XMLTokens - # From http://www.w3.org/TR/REC-xml/#sec-common-syn - # - # [4] NameStartChar ::= - # ":" | - # [A-Z] | - # "_" | - # [a-z] | - # [#xC0-#xD6] | - # [#xD8-#xF6] | - # [#xF8-#x2FF] | - # [#x370-#x37D] | - # [#x37F-#x1FFF] | - # [#x200C-#x200D] | - # [#x2070-#x218F] | - # [#x2C00-#x2FEF] | - # [#x3001-#xD7FF] | - # [#xF900-#xFDCF] | - # [#xFDF0-#xFFFD] | - # [#x10000-#xEFFFF] - name_start_chars = [ - ":", - "A-Z", - "_", - "a-z", - "\\u00C0-\\u00D6", - "\\u00D8-\\u00F6", - "\\u00F8-\\u02FF", - "\\u0370-\\u037D", - "\\u037F-\\u1FFF", - "\\u200C-\\u200D", - "\\u2070-\\u218F", - "\\u2C00-\\u2FEF", - "\\u3001-\\uD7FF", - "\\uF900-\\uFDCF", - "\\uFDF0-\\uFFFD", - "\\u{10000}-\\u{EFFFF}", - ] - # From http://www.w3.org/TR/REC-xml/#sec-common-syn - # - # [4a] NameChar ::= - # NameStartChar | - # "-" | - # "." | - # [0-9] | - # #xB7 | - # [#x0300-#x036F] | - # [#x203F-#x2040] - name_chars = name_start_chars + [ - "\\-", - "\\.", - "0-9", - "\\u00B7", - "\\u0300-\\u036F", - "\\u203F-\\u2040", - ] - NAME_START_CHAR = "[#{name_start_chars.join('')}]" - NAME_CHAR = "[#{name_chars.join('')}]" - NAMECHAR = NAME_CHAR # deprecated. Use NAME_CHAR instead. - - # From http://www.w3.org/TR/xml-names11/#NT-NCName - # - # [6] NCNameStartChar ::= NameStartChar - ':' - ncname_start_chars = name_start_chars - [":"] - # From http://www.w3.org/TR/xml-names11/#NT-NCName - # - # [5] NCNameChar ::= NameChar - ':' - ncname_chars = name_chars - [":"] - NCNAME_STR = "[#{ncname_start_chars.join('')}][#{ncname_chars.join('')}]*" - NAME_STR = "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" - - NAME = "(#{NAME_START_CHAR}#{NAME_CHAR}*)" - NMTOKEN = "(?:#{NAME_CHAR})+" - NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*" - REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)" - - #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})" - #ENTITYREF = "&#{NAME};" - #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;" - end -end diff --git a/ruby/lib/rexml/xpath.rb b/ruby/lib/rexml/xpath.rb deleted file mode 100644 index a0921bd8e..000000000 --- a/ruby/lib/rexml/xpath.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: false -require_relative 'functions' -require_relative 'xpath_parser' - -module REXML - # Wrapper class. Use this class to access the XPath functions. - class XPath - include Functions - # A base Hash object, supposing to be used when initializing a - # default empty namespaces set, but is currently unused. - # TODO: either set the namespaces=EMPTY_HASH, or deprecate this. - EMPTY_HASH = {} - - # Finds and returns the first node that matches the supplied xpath. - # element:: - # The context element - # path:: - # The xpath to search for. If not supplied or nil, returns the first - # node matching '*'. - # namespaces:: - # If supplied, a Hash which defines a namespace mapping. - # variables:: - # If supplied, a Hash which maps $variables in the query - # to values. This can be used to avoid XPath injection attacks - # or to automatically handle escaping string values. - # - # XPath.first( node ) - # XPath.first( doc, "//b"} ) - # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } ) - # XPath.first( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) - def XPath::first(element, path=nil, namespaces=nil, variables={}, options={}) - raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) - raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) - parser = XPathParser.new(**options) - parser.namespaces = namespaces - parser.variables = variables - path = "*" unless path - element = [element] unless element.kind_of? Array - parser.parse(path, element).flatten[0] - end - - # Iterates over nodes that match the given path, calling the supplied - # block with the match. - # element:: - # The context element - # path:: - # The xpath to search for. If not supplied or nil, defaults to '*' - # namespaces:: - # If supplied, a Hash which defines a namespace mapping - # variables:: - # If supplied, a Hash which maps $variables in the query - # to values. This can be used to avoid XPath injection attacks - # or to automatically handle escaping string values. - # - # XPath.each( node ) { |el| ... } - # XPath.each( node, '/*[@attr='v']' ) { |el| ... } - # XPath.each( node, 'ancestor::x' ) { |el| ... } - # XPath.each( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) \ - # {|el| ... } - def XPath::each(element, path=nil, namespaces=nil, variables={}, options={}, &block) - raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) - raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) - parser = XPathParser.new(**options) - parser.namespaces = namespaces - parser.variables = variables - path = "*" unless path - element = [element] unless element.kind_of? Array - parser.parse(path, element).each( &block ) - end - - # Returns an array of nodes matching a given XPath. - def XPath::match(element, path=nil, namespaces=nil, variables={}, options={}) - parser = XPathParser.new(**options) - parser.namespaces = namespaces - parser.variables = variables - path = "*" unless path - element = [element] unless element.kind_of? Array - parser.parse(path,element) - end - end -end diff --git a/ruby/lib/rexml/xpath_parser.rb b/ruby/lib/rexml/xpath_parser.rb deleted file mode 100644 index b98972540..000000000 --- a/ruby/lib/rexml/xpath_parser.rb +++ /dev/null @@ -1,968 +0,0 @@ -# frozen_string_literal: false - -require "pp" - -require_relative 'namespace' -require_relative 'xmltokens' -require_relative 'attribute' -require_relative 'parsers/xpathparser' - -class Object - # provides a unified +clone+ operation, for REXML::XPathParser - # to use across multiple Object types - def dclone - clone - end -end -class Symbol - # provides a unified +clone+ operation, for REXML::XPathParser - # to use across multiple Object types - def dclone ; self ; end -end -class Integer - # provides a unified +clone+ operation, for REXML::XPathParser - # to use across multiple Object types - def dclone ; self ; end -end -class Float - # provides a unified +clone+ operation, for REXML::XPathParser - # to use across multiple Object types - def dclone ; self ; end -end -class Array - # provides a unified +clone+ operation, for REXML::XPathParser - # to use across multiple Object+ types - def dclone - klone = self.clone - klone.clear - self.each{|v| klone << v.dclone} - klone - end -end - -module REXML - # You don't want to use this class. Really. Use XPath, which is a wrapper - # for this class. Believe me. You don't want to poke around in here. - # There is strange, dark magic at work in this code. Beware. Go back! Go - # back while you still can! - class XPathParser - include XMLTokens - LITERAL = /^'([^']*)'|^"([^"]*)"/u - - DEBUG = (ENV["REXML_XPATH_PARSER_DEBUG"] == "true") - - def initialize(strict: false) - @debug = DEBUG - @parser = REXML::Parsers::XPathParser.new - @namespaces = nil - @variables = {} - @nest = 0 - @strict = strict - end - - def namespaces=( namespaces={} ) - Functions::namespace_context = namespaces - @namespaces = namespaces - end - - def variables=( vars={} ) - Functions::variables = vars - @variables = vars - end - - def parse path, nodeset - path_stack = @parser.parse( path ) - match( path_stack, nodeset ) - end - - def get_first path, nodeset - path_stack = @parser.parse( path ) - first( path_stack, nodeset ) - end - - def predicate path, nodeset - path_stack = @parser.parse( path ) - match( path_stack, nodeset ) - end - - def []=( variable_name, value ) - @variables[ variable_name ] = value - end - - - # Performs a depth-first (document order) XPath search, and returns the - # first match. This is the fastest, lightest way to return a single result. - # - # FIXME: This method is incomplete! - def first( path_stack, node ) - return nil if path.size == 0 - - case path[0] - when :document - # do nothing - return first( path[1..-1], node ) - when :child - for c in node.children - r = first( path[1..-1], c ) - return r if r - end - when :qname - name = path[2] - if node.name == name - return node if path.size == 3 - return first( path[3..-1], node ) - else - return nil - end - when :descendant_or_self - r = first( path[1..-1], node ) - return r if r - for c in node.children - r = first( path, c ) - return r if r - end - when :node - return first( path[1..-1], node ) - when :any - return first( path[1..-1], node ) - end - return nil - end - - - def match(path_stack, nodeset) - nodeset = nodeset.collect.with_index do |node, i| - position = i + 1 - XPathNode.new(node, position: position) - end - result = expr(path_stack, nodeset) - case result - when Array # nodeset - unnode(result) - else - [result] - end - end - - private - def strict? - @strict - end - - # Returns a String namespace for a node, given a prefix - # The rules are: - # - # 1. Use the supplied namespace mapping first. - # 2. If no mapping was supplied, use the context node to look up the namespace - def get_namespace( node, prefix ) - if @namespaces - return @namespaces[prefix] || '' - else - return node.namespace( prefix ) if node.node_type == :element - return '' - end - end - - - # Expr takes a stack of path elements and a set of nodes (either a Parent - # or an Array and returns an Array of matching nodes - def expr( path_stack, nodeset, context=nil ) - enter(:expr, path_stack, nodeset) if @debug - return nodeset if path_stack.length == 0 || nodeset.length == 0 - while path_stack.length > 0 - trace(:while, path_stack, nodeset) if @debug - if nodeset.length == 0 - path_stack.clear - return [] - end - op = path_stack.shift - case op - when :document - first_raw_node = nodeset.first.raw_node - nodeset = [XPathNode.new(first_raw_node.root_node, position: 1)] - when :self - nodeset = step(path_stack) do - [nodeset] - end - when :child - nodeset = step(path_stack) do - child(nodeset) - end - when :literal - trace(:literal, path_stack, nodeset) if @debug - return path_stack.shift - when :attribute - nodeset = step(path_stack, any_type: :attribute) do - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - next unless raw_node.node_type == :element - attributes = raw_node.attributes - next if attributes.empty? - nodesets << attributes.each_attribute.collect.with_index do |attribute, i| - XPathNode.new(attribute, position: i + 1) - end - end - nodesets - end - when :namespace - pre_defined_namespaces = { - "xml" => "http://www.w3.org/XML/1998/namespace", - } - nodeset = step(path_stack, any_type: :namespace) do - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - case raw_node.node_type - when :element - if @namespaces - nodesets << pre_defined_namespaces.merge(@namespaces) - else - nodesets << pre_defined_namespaces.merge(raw_node.namespaces) - end - when :attribute - if @namespaces - nodesets << pre_defined_namespaces.merge(@namespaces) - else - nodesets << pre_defined_namespaces.merge(raw_node.element.namespaces) - end - end - end - nodesets - end - when :parent - nodeset = step(path_stack) do - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - if raw_node.node_type == :attribute - parent = raw_node.element - else - parent = raw_node.parent - end - nodesets << [XPathNode.new(parent, position: 1)] if parent - end - nodesets - end - when :ancestor - nodeset = step(path_stack) do - nodesets = [] - # new_nodes = {} - nodeset.each do |node| - raw_node = node.raw_node - new_nodeset = [] - while raw_node.parent - raw_node = raw_node.parent - # next if new_nodes.key?(node) - new_nodeset << XPathNode.new(raw_node, - position: new_nodeset.size + 1) - # new_nodes[node] = true - end - nodesets << new_nodeset unless new_nodeset.empty? - end - nodesets - end - when :ancestor_or_self - nodeset = step(path_stack) do - nodesets = [] - # new_nodes = {} - nodeset.each do |node| - raw_node = node.raw_node - next unless raw_node.node_type == :element - new_nodeset = [XPathNode.new(raw_node, position: 1)] - # new_nodes[node] = true - while raw_node.parent - raw_node = raw_node.parent - # next if new_nodes.key?(node) - new_nodeset << XPathNode.new(raw_node, - position: new_nodeset.size + 1) - # new_nodes[node] = true - end - nodesets << new_nodeset unless new_nodeset.empty? - end - nodesets - end - when :descendant_or_self - nodeset = step(path_stack) do - descendant(nodeset, true) - end - when :descendant - nodeset = step(path_stack) do - descendant(nodeset, false) - end - when :following_sibling - nodeset = step(path_stack) do - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - next unless raw_node.respond_to?(:parent) - next if raw_node.parent.nil? - all_siblings = raw_node.parent.children - current_index = all_siblings.index(raw_node) - following_siblings = all_siblings[(current_index + 1)..-1] - next if following_siblings.empty? - nodesets << following_siblings.collect.with_index do |sibling, i| - XPathNode.new(sibling, position: i + 1) - end - end - nodesets - end - when :preceding_sibling - nodeset = step(path_stack, order: :reverse) do - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - next unless raw_node.respond_to?(:parent) - next if raw_node.parent.nil? - all_siblings = raw_node.parent.children - current_index = all_siblings.index(raw_node) - preceding_siblings = all_siblings[0, current_index].reverse - next if preceding_siblings.empty? - nodesets << preceding_siblings.collect.with_index do |sibling, i| - XPathNode.new(sibling, position: i + 1) - end - end - nodesets - end - when :preceding - nodeset = step(path_stack, order: :reverse) do - unnode(nodeset) do |node| - preceding(node) - end - end - when :following - nodeset = step(path_stack) do - unnode(nodeset) do |node| - following(node) - end - end - when :variable - var_name = path_stack.shift - return [@variables[var_name]] - - when :eq, :neq, :lt, :lteq, :gt, :gteq - left = expr( path_stack.shift, nodeset.dup, context ) - right = expr( path_stack.shift, nodeset.dup, context ) - res = equality_relational_compare( left, op, right ) - trace(op, left, right, res) if @debug - return res - - when :or - left = expr(path_stack.shift, nodeset.dup, context) - return true if Functions.boolean(left) - right = expr(path_stack.shift, nodeset.dup, context) - return Functions.boolean(right) - - when :and - left = expr(path_stack.shift, nodeset.dup, context) - return false unless Functions.boolean(left) - right = expr(path_stack.shift, nodeset.dup, context) - return Functions.boolean(right) - - when :div, :mod, :mult, :plus, :minus - left = expr(path_stack.shift, nodeset, context) - right = expr(path_stack.shift, nodeset, context) - left = unnode(left) if left.is_a?(Array) - right = unnode(right) if right.is_a?(Array) - left = Functions::number(left) - right = Functions::number(right) - case op - when :div - return left / right - when :mod - return left % right - when :mult - return left * right - when :plus - return left + right - when :minus - return left - right - else - raise "[BUG] Unexpected operator: <#{op.inspect}>" - end - when :union - left = expr( path_stack.shift, nodeset, context ) - right = expr( path_stack.shift, nodeset, context ) - left = unnode(left) if left.is_a?(Array) - right = unnode(right) if right.is_a?(Array) - return (left | right) - when :neg - res = expr( path_stack, nodeset, context ) - res = unnode(res) if res.is_a?(Array) - return -Functions.number(res) - when :not - when :function - func_name = path_stack.shift.tr('-','_') - arguments = path_stack.shift - - if nodeset.size != 1 - message = "[BUG] Node set size must be 1 for function call: " - message += "<#{func_name}>: <#{nodeset.inspect}>: " - message += "<#{arguments.inspect}>" - raise message - end - - node = nodeset.first - if context - target_context = context - else - target_context = {:size => nodeset.size} - if node.is_a?(XPathNode) - target_context[:node] = node.raw_node - target_context[:index] = node.position - else - target_context[:node] = node - target_context[:index] = 1 - end - end - args = arguments.dclone.collect do |arg| - result = expr(arg, nodeset, target_context) - result = unnode(result) if result.is_a?(Array) - result - end - Functions.context = target_context - return Functions.send(func_name, *args) - - else - raise "[BUG] Unexpected path: <#{op.inspect}>: <#{path_stack.inspect}>" - end - end # while - return nodeset - ensure - leave(:expr, path_stack, nodeset) if @debug - end - - def step(path_stack, any_type: :element, order: :forward) - nodesets = yield - begin - enter(:step, path_stack, nodesets) if @debug - nodesets = node_test(path_stack, nodesets, any_type: any_type) - while path_stack[0] == :predicate - path_stack.shift # :predicate - predicate_expression = path_stack.shift.dclone - nodesets = evaluate_predicate(predicate_expression, nodesets) - end - if nodesets.size == 1 - ordered_nodeset = nodesets[0] - else - raw_nodes = [] - nodesets.each do |nodeset| - nodeset.each do |node| - if node.respond_to?(:raw_node) - raw_nodes << node.raw_node - else - raw_nodes << node - end - end - end - ordered_nodeset = sort(raw_nodes, order) - end - new_nodeset = [] - ordered_nodeset.each do |node| - # TODO: Remove duplicated - new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) - end - new_nodeset - ensure - leave(:step, path_stack, new_nodeset) if @debug - end - end - - def node_test(path_stack, nodesets, any_type: :element) - enter(:node_test, path_stack, nodesets) if @debug - operator = path_stack.shift - case operator - when :qname - prefix = path_stack.shift - name = path_stack.shift - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - case raw_node.node_type - when :element - if prefix.nil? - raw_node.name == name - elsif prefix.empty? - if strict? - raw_node.name == name and raw_node.namespace == "" - else - # FIXME: This DOUBLES the time XPath searches take - ns = get_namespace(raw_node, prefix) - raw_node.name == name and raw_node.namespace == ns - end - else - # FIXME: This DOUBLES the time XPath searches take - ns = get_namespace(raw_node, prefix) - raw_node.name == name and raw_node.namespace == ns - end - when :attribute - if prefix.nil? - raw_node.name == name - elsif prefix.empty? - raw_node.name == name and raw_node.namespace == "" - else - # FIXME: This DOUBLES the time XPath searches take - ns = get_namespace(raw_node.element, prefix) - raw_node.name == name and raw_node.namespace == ns - end - else - false - end - end - end - when :namespace - prefix = path_stack.shift - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - case raw_node.node_type - when :element - namespaces = @namespaces || raw_node.namespaces - raw_node.namespace == namespaces[prefix] - when :attribute - namespaces = @namespaces || raw_node.element.namespaces - raw_node.namespace == namespaces[prefix] - else - false - end - end - end - when :any - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - raw_node.node_type == any_type - end - end - when :comment - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - raw_node.node_type == :comment - end - end - when :text - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - raw_node.node_type == :text - end - end - when :processing_instruction - target = path_stack.shift - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - raw_node = node.raw_node - (raw_node.node_type == :processing_instruction) and - (target.empty? or (raw_node.target == target)) - end - end - when :node - new_nodesets = nodesets.collect do |nodeset| - filter_nodeset(nodeset) do |node| - true - end - end - else - message = "[BUG] Unexpected node test: " + - "<#{operator.inspect}>: <#{path_stack.inspect}>" - raise message - end - new_nodesets - ensure - leave(:node_test, path_stack, new_nodesets) if @debug - end - - def filter_nodeset(nodeset) - new_nodeset = [] - nodeset.each do |node| - next unless yield(node) - new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) - end - new_nodeset - end - - def evaluate_predicate(expression, nodesets) - enter(:predicate, expression, nodesets) if @debug - new_nodesets = nodesets.collect do |nodeset| - new_nodeset = [] - subcontext = { :size => nodeset.size } - nodeset.each_with_index do |node, index| - if node.is_a?(XPathNode) - subcontext[:node] = node.raw_node - subcontext[:index] = node.position - else - subcontext[:node] = node - subcontext[:index] = index + 1 - end - result = expr(expression.dclone, [node], subcontext) - trace(:predicate_evaluate, expression, node, subcontext, result) if @debug - result = result[0] if result.kind_of? Array and result.length == 1 - if result.kind_of? Numeric - if result == node.position - new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) - end - elsif result.instance_of? Array - if result.size > 0 and result.inject(false) {|k,s| s or k} - if result.size > 0 - new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) - end - end - else - if result - new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) - end - end - end - new_nodeset - end - new_nodesets - ensure - leave(:predicate, new_nodesets) if @debug - end - - def trace(*args) - indent = " " * @nest - PP.pp(args, "").each_line do |line| - puts("#{indent}#{line}") - end - end - - def enter(tag, *args) - trace(:enter, tag, *args) - @nest += 1 - end - - def leave(tag, *args) - @nest -= 1 - trace(:leave, tag, *args) - end - - # Reorders an array of nodes so that they are in document order - # It tries to do this efficiently. - # - # FIXME: I need to get rid of this, but the issue is that most of the XPath - # interpreter functions as a filter, which means that we lose context going - # in and out of function calls. If I knew what the index of the nodes was, - # I wouldn't have to do this. Maybe add a document IDX for each node? - # Problems with mutable documents. Or, rewrite everything. - def sort(array_of_nodes, order) - new_arry = [] - array_of_nodes.each { |node| - node_idx = [] - np = node.node_type == :attribute ? node.element : node - while np.parent and np.parent.node_type == :element - node_idx << np.parent.index( np ) - np = np.parent - end - new_arry << [ node_idx.reverse, node ] - } - ordered = new_arry.sort_by do |index, node| - if order == :forward - index - else - -index - end - end - ordered.collect do |_index, node| - node - end - end - - def descendant(nodeset, include_self) - nodesets = [] - nodeset.each do |node| - new_nodeset = [] - new_nodes = {} - descendant_recursive(node.raw_node, new_nodeset, new_nodes, include_self) - nodesets << new_nodeset unless new_nodeset.empty? - end - nodesets - end - - def descendant_recursive(raw_node, new_nodeset, new_nodes, include_self) - if include_self - return if new_nodes.key?(raw_node) - new_nodeset << XPathNode.new(raw_node, position: new_nodeset.size + 1) - new_nodes[raw_node] = true - end - - node_type = raw_node.node_type - if node_type == :element or node_type == :document - raw_node.children.each do |child| - descendant_recursive(child, new_nodeset, new_nodes, true) - end - end - end - - # Builds a nodeset of all of the preceding nodes of the supplied node, - # in reverse document order - # preceding:: includes every element in the document that precedes this node, - # except for ancestors - def preceding(node) - ancestors = [] - parent = node.parent - while parent - ancestors << parent - parent = parent.parent - end - - precedings = [] - preceding_node = preceding_node_of(node) - while preceding_node - if ancestors.include?(preceding_node) - ancestors.delete(preceding_node) - else - precedings << XPathNode.new(preceding_node, - position: precedings.size + 1) - end - preceding_node = preceding_node_of(preceding_node) - end - precedings - end - - def preceding_node_of( node ) - psn = node.previous_sibling_node - if psn.nil? - if node.parent.nil? or node.parent.class == Document - return nil - end - return node.parent - #psn = preceding_node_of( node.parent ) - end - while psn and psn.kind_of? Element and psn.children.size > 0 - psn = psn.children[-1] - end - psn - end - - def following(node) - followings = [] - following_node = next_sibling_node(node) - while following_node - followings << XPathNode.new(following_node, - position: followings.size + 1) - following_node = following_node_of(following_node) - end - followings - end - - def following_node_of( node ) - if node.kind_of? Element and node.children.size > 0 - return node.children[0] - end - return next_sibling_node(node) - end - - def next_sibling_node(node) - psn = node.next_sibling_node - while psn.nil? - if node.parent.nil? or node.parent.class == Document - return nil - end - node = node.parent - psn = node.next_sibling_node - end - return psn - end - - def child(nodeset) - nodesets = [] - nodeset.each do |node| - raw_node = node.raw_node - node_type = raw_node.node_type - # trace(:child, node_type, node) - case node_type - when :element - nodesets << raw_node.children.collect.with_index do |child_node, i| - XPathNode.new(child_node, position: i + 1) - end - when :document - new_nodeset = [] - raw_node.children.each do |child| - case child - when XMLDecl, Text - # Ignore - else - new_nodeset << XPathNode.new(child, position: new_nodeset.size + 1) - end - end - nodesets << new_nodeset unless new_nodeset.empty? - end - end - nodesets - end - - def norm b - case b - when true, false - return b - when 'true', 'false' - return Functions::boolean( b ) - when /^\d+(\.\d+)?$/, Numeric - return Functions::number( b ) - else - return Functions::string( b ) - end - end - - def equality_relational_compare(set1, op, set2) - set1 = unnode(set1) if set1.is_a?(Array) - set2 = unnode(set2) if set2.is_a?(Array) - - if set1.kind_of? Array and set2.kind_of? Array - # If both objects to be compared are node-sets, then the - # comparison will be true if and only if there is a node in the - # first node-set and a node in the second node-set such that the - # result of performing the comparison on the string-values of - # the two nodes is true. - set1.product(set2).any? do |node1, node2| - node_string1 = Functions.string(node1) - node_string2 = Functions.string(node2) - compare(node_string1, op, node_string2) - end - elsif set1.kind_of? Array or set2.kind_of? Array - # If one is nodeset and other is number, compare number to each item - # in nodeset s.t. number op number(string(item)) - # If one is nodeset and other is string, compare string to each item - # in nodeset s.t. string op string(item) - # If one is nodeset and other is boolean, compare boolean to each item - # in nodeset s.t. boolean op boolean(item) - if set1.kind_of? Array - a = set1 - b = set2 - else - a = set2 - b = set1 - end - - case b - when true, false - each_unnode(a).any? do |unnoded| - compare(Functions.boolean(unnoded), op, b) - end - when Numeric - each_unnode(a).any? do |unnoded| - compare(Functions.number(unnoded), op, b) - end - when /\A\d+(\.\d+)?\z/ - b = Functions.number(b) - each_unnode(a).any? do |unnoded| - compare(Functions.number(unnoded), op, b) - end - else - b = Functions::string(b) - each_unnode(a).any? do |unnoded| - compare(Functions::string(unnoded), op, b) - end - end - else - # If neither is nodeset, - # If op is = or != - # If either boolean, convert to boolean - # If either number, convert to number - # Else, convert to string - # Else - # Convert both to numbers and compare - compare(set1, op, set2) - end - end - - def value_type(value) - case value - when true, false - :boolean - when Numeric - :number - when String - :string - else - raise "[BUG] Unexpected value type: <#{value.inspect}>" - end - end - - def normalize_compare_values(a, operator, b) - a_type = value_type(a) - b_type = value_type(b) - case operator - when :eq, :neq - if a_type == :boolean or b_type == :boolean - a = Functions.boolean(a) unless a_type == :boolean - b = Functions.boolean(b) unless b_type == :boolean - elsif a_type == :number or b_type == :number - a = Functions.number(a) unless a_type == :number - b = Functions.number(b) unless b_type == :number - else - a = Functions.string(a) unless a_type == :string - b = Functions.string(b) unless b_type == :string - end - when :lt, :lteq, :gt, :gteq - a = Functions.number(a) unless a_type == :number - b = Functions.number(b) unless b_type == :number - else - message = "[BUG] Unexpected compare operator: " + - "<#{operator.inspect}>: <#{a.inspect}>: <#{b.inspect}>" - raise message - end - [a, b] - end - - def compare(a, operator, b) - a, b = normalize_compare_values(a, operator, b) - case operator - when :eq - a == b - when :neq - a != b - when :lt - a < b - when :lteq - a <= b - when :gt - a > b - when :gteq - a >= b - else - message = "[BUG] Unexpected compare operator: " + - "<#{operator.inspect}>: <#{a.inspect}>: <#{b.inspect}>" - raise message - end - end - - def each_unnode(nodeset) - return to_enum(__method__, nodeset) unless block_given? - nodeset.each do |node| - if node.is_a?(XPathNode) - unnoded = node.raw_node - else - unnoded = node - end - yield(unnoded) - end - end - - def unnode(nodeset) - each_unnode(nodeset).collect do |unnoded| - unnoded = yield(unnoded) if block_given? - unnoded - end - end - end - - # @private - class XPathNode - attr_reader :raw_node, :context - def initialize(node, context=nil) - if node.is_a?(XPathNode) - @raw_node = node.raw_node - else - @raw_node = node - end - @context = context || {} - end - - def position - @context[:position] - end - end -end diff --git a/ruby/lib/rinda/rinda.gemspec b/ruby/lib/rinda/rinda.gemspec new file mode 100644 index 000000000..0c13e3c2d --- /dev/null +++ b/ruby/lib/rinda/rinda.gemspec @@ -0,0 +1,28 @@ +Gem::Specification.new do |spec| + spec.name = "rinda" + spec.version = "0.1.1" + spec.authors = ["Masatoshi SEKI"] + spec.email = ["seki@ruby-lang.org"] + + spec.summary = %q{The Linda distributed computing paradigm in Ruby.} + spec.description = %q{The Linda distributed computing paradigm in Ruby.} + spec.homepage = "https://github.com/ruby/rinda" + 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.add_dependency "drb" + spec.add_dependency "ipaddr" + spec.add_dependency "forwardable" +end diff --git a/ruby/lib/rss.rb b/ruby/lib/rss.rb deleted file mode 100644 index 1438d97bd..000000000 --- a/ruby/lib/rss.rb +++ /dev/null @@ -1,94 +0,0 @@ -# frozen_string_literal: false -## -# = RSS reading and writing -# -# Really Simple Syndication (RSS) is a family of formats that describe 'feeds,' -# specially constructed XML documents that allow an interested person to -# subscribe and receive updates from a particular web service. This portion of -# the standard library provides tooling to read and create these feeds. -# -# The standard library supports RSS 0.91, 1.0, 2.0, and Atom, a related format. -# Here are some links to the standards documents for these formats: -# -# * RSS -# * 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape] -# * 1.0[http://web.resource.org/rss/1.0/] -# * 2.0[http://www.rssboard.org/rss-specification] -# * Atom[http://tools.ietf.org/html/rfc4287] -# -# == Consuming RSS -# -# If you'd like to read someone's RSS feed with your Ruby code, you've come to -# the right place. It's really easy to do this, but we'll need the help of -# open-uri: -# -# require 'rss' -# require 'open-uri' -# -# url = 'http://www.ruby-lang.org/en/feeds/news.rss' -# open(url) do |rss| -# feed = RSS::Parser.parse(rss) -# puts "Title: #{feed.channel.title}" -# feed.items.each do |item| -# puts "Item: #{item.title}" -# end -# end -# -# As you can see, the workhorse is RSS::Parser#parse, which takes the source of -# the feed and a parameter that performs validation on the feed. We get back an -# object that has all of the data from our feed, accessible through methods. -# This example shows getting the title out of the channel element, and looping -# through the list of items. -# -# == Producing RSS -# -# Producing our own RSS feeds is easy as well. Let's make a very basic feed: -# -# require "rss" -# -# rss = RSS::Maker.make("atom") do |maker| -# maker.channel.author = "matz" -# maker.channel.updated = Time.now.to_s -# maker.channel.about = "http://www.ruby-lang.org/en/feeds/news.rss" -# maker.channel.title = "Example Feed" -# -# maker.items.new_item do |item| -# item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" -# item.title = "Ruby 1.9.2-p136 is released" -# item.updated = Time.now.to_s -# end -# end -# -# puts rss -# -# As you can see, this is a very Builder-like DSL. This code will spit out an -# Atom feed with one item. If we needed a second item, we'd make another block -# with maker.items.new_item and build a second one. -# -# == Copyright -# -# Copyright (c) 2003-2007 Kouhei Sutou -# -# You can redistribute it and/or modify it under the same terms as Ruby. -# -# There is an additional tutorial by the author of RSS at: -# http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser%3A%3ATutorial.en - -module RSS -end - -require "rss/version" - -require 'rss/1.0' -require 'rss/2.0' -require 'rss/atom' -require 'rss/content' -require 'rss/dublincore' -require 'rss/image' -require 'rss/itunes' -require 'rss/slash' -require 'rss/syndication' -require 'rss/taxonomy' -require 'rss/trackback' - -require "rss/maker" diff --git a/ruby/lib/rss/0.9.rb b/ruby/lib/rss/0.9.rb deleted file mode 100644 index 219ccefcd..000000000 --- a/ruby/lib/rss/0.9.rb +++ /dev/null @@ -1,462 +0,0 @@ -# frozen_string_literal: false -require_relative "parser" - -module RSS - - ## - # = RSS 0.9 support - # - # RSS has three different versions. This module contains support for version - # 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape]. - # - # == Producing RSS 0.9 - # - # Producing our own RSS feeds is easy as well. Let's make a very basic feed: - # - # require "rss" - # - # rss = RSS::Maker.make("0.91") do |maker| - # maker.channel.language = "en" - # maker.channel.author = "matz" - # maker.channel.updated = Time.now.to_s - # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss" - # maker.channel.title = "Example Feed" - # maker.channel.description = "A longer description of my feed." - # maker.image.url = "http://www.ruby-lang.org/images/logo.gif" - # maker.image.title = "An image" - # maker.items.new_item do |item| - # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" - # item.title = "Ruby 1.9.2-p136 is released" - # item.updated = Time.now.to_s - # end - # end - # - # puts rss - # - # As you can see, this is a very Builder-like DSL. This code will spit out an - # RSS 0.9 feed with one item. If we needed a second item, we'd make another - # block with maker.items.new_item and build a second one. - module RSS09 - NSPOOL = {} - ELEMENTS = [] - - def self.append_features(klass) - super - - klass.install_must_call_validator('', "") - end - end - - class Rss < Element - - include RSS09 - include RootElementMixin - - %w(channel).each do |name| - install_have_child_element(name, "", nil) - end - - attr_writer :feed_version - alias_method(:rss_version, :feed_version) - alias_method(:rss_version=, :feed_version=) - - def initialize(feed_version, version=nil, encoding=nil, standalone=nil) - super - @feed_type = "rss" - end - - def items - if @channel - @channel.items - else - [] - end - end - - def image - if @channel - @channel.image - else - nil - end - end - - def textinput - if @channel - @channel.textInput - else - nil - end - end - - def setup_maker_elements(maker) - super - items.each do |item| - item.setup_maker(maker.items) - end - image.setup_maker(maker) if image - textinput.setup_maker(maker) if textinput - end - - private - def _attrs - [ - ["version", true, "feed_version"], - ] - end - - class Channel < Element - - include RSS09 - - [ - ["title", nil, :text], - ["link", nil, :text], - ["description", nil, :text], - ["language", nil, :text], - ["copyright", "?", :text], - ["managingEditor", "?", :text], - ["webMaster", "?", :text], - ["rating", "?", :text], - ["pubDate", "?", :date, :rfc822], - ["lastBuildDate", "?", :date, :rfc822], - ["docs", "?", :text], - ["cloud", "?", :have_attribute], - ["skipDays", "?", :have_child], - ["skipHours", "?", :have_child], - ["image", nil, :have_child], - ["item", "*", :have_children], - ["textInput", "?", :have_child], - ].each do |name, occurs, type, *args| - __send__("install_#{type}_element", name, "", occurs, name, *args) - end - alias date pubDate - alias date= pubDate= - - private - def maker_target(maker) - maker.channel - end - - def setup_maker_elements(channel) - super - [ - [skipDays, "day"], - [skipHours, "hour"], - ].each do |skip, key| - if skip - skip.__send__("#{key}s").each do |val| - target_skips = channel.__send__("skip#{key.capitalize}s") - new_target = target_skips.__send__("new_#{key}") - new_target.content = val.content - end - end - end - end - - def not_need_to_call_setup_maker_variables - %w(image textInput) - end - - class SkipDays < Element - include RSS09 - - [ - ["day", "*"] - ].each do |name, occurs| - install_have_children_element(name, "", occurs) - end - - class Day < Element - include RSS09 - - content_setup - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.content = args[0] - end - end - - end - - end - - class SkipHours < Element - include RSS09 - - [ - ["hour", "*"] - ].each do |name, occurs| - install_have_children_element(name, "", occurs) - end - - class Hour < Element - include RSS09 - - content_setup(:integer) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.content = args[0] - end - end - end - - end - - class Image < Element - - include RSS09 - - %w(url title link).each do |name| - install_text_element(name, "", nil) - end - [ - ["width", :integer], - ["height", :integer], - ["description"], - ].each do |name, type| - install_text_element(name, "", "?", name, type) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.url = args[0] - self.title = args[1] - self.link = args[2] - self.width = args[3] - self.height = args[4] - self.description = args[5] - end - end - - private - def maker_target(maker) - maker.image - end - end - - class Cloud < Element - - include RSS09 - - [ - ["domain", "", true], - ["port", "", true, :integer], - ["path", "", true], - ["registerProcedure", "", true], - ["protocol", "", true], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.domain = args[0] - self.port = args[1] - self.path = args[2] - self.registerProcedure = args[3] - self.protocol = args[4] - end - end - end - - class Item < Element - - include RSS09 - - [ - ["title", '?', :text], - ["link", '?', :text], - ["description", '?', :text], - ["category", '*', :have_children, "categories"], - ["source", '?', :have_child], - ["enclosure", '?', :have_child], - ].each do |tag, occurs, type, *args| - __send__("install_#{type}_element", tag, "", occurs, tag, *args) - end - - private - def maker_target(items) - if items.respond_to?("items") - # For backward compatibility - items = items.items - end - items.new_item - end - - def setup_maker_element(item) - super - @enclosure.setup_maker(item) if @enclosure - @source.setup_maker(item) if @source - end - - class Source < Element - - include RSS09 - - [ - ["url", "", true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required) - end - - content_setup - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.url = args[0] - self.content = args[1] - end - end - - private - def maker_target(item) - item.source - end - - def setup_maker_attributes(source) - source.url = url - source.content = content - end - end - - class Enclosure < Element - - include RSS09 - - [ - ["url", "", true], - ["length", "", true, :integer], - ["type", "", true], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.url = args[0] - self.length = args[1] - self.type = args[2] - end - end - - private - def maker_target(item) - item.enclosure - end - - def setup_maker_attributes(enclosure) - enclosure.url = url - enclosure.length = length - enclosure.type = type - end - end - - class Category < Element - - include RSS09 - - [ - ["domain", "", false] - ].each do |name, uri, required| - install_get_attribute(name, uri, required) - end - - content_setup - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.domain = args[0] - self.content = args[1] - end - end - - private - def maker_target(item) - item.new_category - end - - def setup_maker_attributes(category) - category.domain = domain - category.content = content - end - - end - - end - - class TextInput < Element - - include RSS09 - - %w(title description name link).each do |name| - install_text_element(name, "", nil) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.title = args[0] - self.description = args[1] - self.name = args[2] - self.link = args[3] - end - end - - private - def maker_target(maker) - maker.textinput - end - end - - end - - end - - RSS09::ELEMENTS.each do |name| - BaseListener.install_get_text_element("", name, name) - end - - module ListenerMixin - private - def initial_start_rss(tag_name, prefix, attrs, ns) - check_ns(tag_name, prefix, ns, "", false) - - @rss = Rss.new(attrs['version'], @version, @encoding, @standalone) - @rss.do_validate = @do_validate - @rss.xml_stylesheets = @xml_stylesheets - @last_element = @rss - pr = Proc.new do |text, tags| - @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate - end - @proc_stack.push(pr) - end - - end - -end diff --git a/ruby/lib/rss/1.0.rb b/ruby/lib/rss/1.0.rb deleted file mode 100644 index c8f92fb54..000000000 --- a/ruby/lib/rss/1.0.rb +++ /dev/null @@ -1,485 +0,0 @@ -# frozen_string_literal: false -require_relative "parser" - -module RSS - - ## - # = RSS 1.0 support - # - # RSS has three different versions. This module contains support for version - # 1.0[http://web.resource.org/rss/1.0/] - # - # == Producing RSS 1.0 - # - # Producing our own RSS feeds is easy as well. Let's make a very basic feed: - # - # require "rss" - # - # rss = RSS::Maker.make("1.0") do |maker| - # maker.channel.language = "en" - # maker.channel.author = "matz" - # maker.channel.about = "About my feed." - # maker.channel.updated = Time.now.to_s - # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss" - # maker.channel.title = "Example Feed" - # maker.channel.description = "A longer description of my feed." - # maker.items.new_item do |item| - # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" - # item.title = "Ruby 1.9.2-p136 is released" - # item.updated = Time.now.to_s - # end - # end - # - # puts rss - # - # As you can see, this is a very Builder-like DSL. This code will spit out an - # RSS 1.0 feed with one item. If we needed a second item, we'd make another - # block with maker.items.new_item and build a second one. - module RSS10 - NSPOOL = {} - ELEMENTS = [] - - def self.append_features(klass) - super - - klass.install_must_call_validator('', ::RSS::URI) - end - - end - - class RDF < Element - - include RSS10 - include RootElementMixin - - class << self - - def required_uri - URI - end - - end - - @tag_name = 'RDF' - - PREFIX = 'rdf' - URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" - - install_ns('', ::RSS::URI) - install_ns(PREFIX, URI) - - [ - ["channel", nil], - ["image", "?"], - ["item", "+", :children], - ["textinput", "?"], - ].each do |tag, occurs, type| - type ||= :child - __send__("install_have_#{type}_element", tag, ::RSS::URI, occurs) - end - - alias_method(:rss_version, :feed_version) - def initialize(version=nil, encoding=nil, standalone=nil) - super('1.0', version, encoding, standalone) - @feed_type = "rss" - end - - def full_name - tag_name_with_prefix(PREFIX) - end - - class Li < Element - - include RSS10 - - class << self - def required_uri - URI - end - end - - [ - ["resource", [URI, ""], true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.resource = args[0] - end - end - - def full_name - tag_name_with_prefix(PREFIX) - end - end - - class Seq < Element - - include RSS10 - - Li = ::RSS::RDF::Li - - class << self - def required_uri - URI - end - end - - @tag_name = 'Seq' - - install_have_children_element("li", URI, "*") - install_must_call_validator('rdf', ::RSS::RDF::URI) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - @li = args[0] if args[0] - end - end - - def full_name - tag_name_with_prefix(PREFIX) - end - - def setup_maker(target) - lis.each do |li| - target << li.resource - end - end - end - - class Bag < Element - - include RSS10 - - Li = ::RSS::RDF::Li - - class << self - def required_uri - URI - end - end - - @tag_name = 'Bag' - - install_have_children_element("li", URI, "*") - install_must_call_validator('rdf', URI) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - @li = args[0] if args[0] - end - end - - def full_name - tag_name_with_prefix(PREFIX) - end - - def setup_maker(target) - lis.each do |li| - target << li.resource - end - end - end - - class Channel < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - [ - ["about", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - [ - ['title', nil, :text], - ['link', nil, :text], - ['description', nil, :text], - ['image', '?', :have_child], - ['items', nil, :have_child], - ['textinput', '?', :have_child], - ].each do |tag, occurs, type| - __send__("install_#{type}_element", tag, ::RSS::URI, occurs) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - end - end - - private - def maker_target(maker) - maker.channel - end - - def setup_maker_attributes(channel) - channel.about = about - end - - class Image < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - [ - ["resource", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.resource = args[0] - end - end - end - - class Textinput < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - [ - ["resource", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.resource = args[0] - end - end - end - - class Items < Element - - include RSS10 - - Seq = ::RSS::RDF::Seq - - class << self - - def required_uri - ::RSS::URI - end - - end - - install_have_child_element("Seq", URI, nil) - install_must_call_validator('rdf', URI) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.Seq = args[0] - end - self.Seq ||= Seq.new - end - - def resources - if @Seq - @Seq.lis.collect do |li| - li.resource - end - else - [] - end - end - end - end - - class Image < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - [ - ["about", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - %w(title url link).each do |name| - install_text_element(name, ::RSS::URI, nil) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - end - end - - private - def maker_target(maker) - maker.image - end - end - - class Item < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - - [ - ["about", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - [ - ["title", nil], - ["link", nil], - ["description", "?"], - ].each do |tag, occurs| - install_text_element(tag, ::RSS::URI, occurs) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - end - end - - private - def maker_target(items) - if items.respond_to?("items") - # For backward compatibility - items = items.items - end - items.new_item - end - end - - class Textinput < Element - - include RSS10 - - class << self - - def required_uri - ::RSS::URI - end - - end - - [ - ["about", URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{PREFIX}:#{name}") - end - - %w(title description name link).each do |name| - install_text_element(name, ::RSS::URI, nil) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - end - end - - private - def maker_target(maker) - maker.textinput - end - end - - end - - RSS10::ELEMENTS.each do |name| - BaseListener.install_get_text_element(URI, name, name) - end - - module ListenerMixin - private - def initial_start_RDF(tag_name, prefix, attrs, ns) - check_ns(tag_name, prefix, ns, RDF::URI, false) - - @rss = RDF.new(@version, @encoding, @standalone) - @rss.do_validate = @do_validate - @rss.xml_stylesheets = @xml_stylesheets - @last_element = @rss - pr = Proc.new do |text, tags| - @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate - end - @proc_stack.push(pr) - end - end - -end diff --git a/ruby/lib/rss/2.0.rb b/ruby/lib/rss/2.0.rb deleted file mode 100644 index 13f9ade91..000000000 --- a/ruby/lib/rss/2.0.rb +++ /dev/null @@ -1,143 +0,0 @@ -# frozen_string_literal: false -require "rss/0.9" - -module RSS - - ## - # = RSS 2.0 support - # - # RSS has three different versions. This module contains support for version - # 2.0[http://www.rssboard.org/rss-specification] - # - # == Producing RSS 2.0 - # - # Producing our own RSS feeds is easy as well. Let's make a very basic feed: - # - # require "rss" - # - # rss = RSS::Maker.make("2.0") do |maker| - # maker.channel.language = "en" - # maker.channel.author = "matz" - # maker.channel.updated = Time.now.to_s - # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss" - # maker.channel.title = "Example Feed" - # maker.channel.description = "A longer description of my feed." - # maker.items.new_item do |item| - # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/" - # item.title = "Ruby 1.9.2-p136 is released" - # item.updated = Time.now.to_s - # end - # end - # - # puts rss - # - # As you can see, this is a very Builder-like DSL. This code will spit out an - # RSS 2.0 feed with one item. If we needed a second item, we'd make another - # block with maker.items.new_item and build a second one. - class Rss - - class Channel - - [ - ["generator"], - ["ttl", :integer], - ].each do |name, type| - install_text_element(name, "", "?", name, type) - end - - [ - %w(category categories), - ].each do |name, plural_name| - install_have_children_element(name, "", "*", name, plural_name) - end - - [ - ["image", "?"], - ["language", "?"], - ].each do |name, occurs| - install_model(name, "", occurs) - end - - Category = Item::Category - - class Item - - [ - ["comments", "?"], - ["author", "?"], - ].each do |name, occurs| - install_text_element(name, "", occurs) - end - - [ - ["pubDate", '?'], - ].each do |name, occurs| - install_date_element(name, "", occurs, name, 'rfc822') - end - alias date pubDate - alias date= pubDate= - - [ - ["guid", '?'], - ].each do |name, occurs| - install_have_child_element(name, "", occurs) - end - - private - alias _setup_maker_element setup_maker_element - def setup_maker_element(item) - _setup_maker_element(item) - @guid.setup_maker(item) if @guid - end - - class Guid < Element - - include RSS09 - - [ - ["isPermaLink", "", false, :boolean] - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - content_setup - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.isPermaLink = args[0] - self.content = args[1] - end - end - - alias_method :_PermaLink?, :PermaLink? - private :_PermaLink? - def PermaLink? - perma = _PermaLink? - perma or perma.nil? - end - - private - def maker_target(item) - item.guid - end - - def setup_maker_attributes(guid) - guid.isPermaLink = isPermaLink - guid.content = content - end - end - - end - - end - - end - - RSS09::ELEMENTS.each do |name| - BaseListener.install_get_text_element("", name, name) - end - -end diff --git a/ruby/lib/rss/atom.rb b/ruby/lib/rss/atom.rb deleted file mode 100644 index 48c27330d..000000000 --- a/ruby/lib/rss/atom.rb +++ /dev/null @@ -1,1025 +0,0 @@ -# frozen_string_literal: false -require_relative 'parser' - -module RSS - ## - # Atom is an XML-based document format that is used to describe 'feeds' of related information. - # A typical use is in a news feed where the information is periodically updated and which users - # can subscribe to. The Atom format is described in http://tools.ietf.org/html/rfc4287 - # - # The Atom module provides support in reading and creating feeds. - # - # See the RSS module for examples consuming and creating feeds. - module Atom - - ## - # The Atom URI W3C Namespace - - URI = "http://www.w3.org/2005/Atom" - - ## - # The XHTML URI W3C Namespace - - XHTML_URI = "http://www.w3.org/1999/xhtml" - - module CommonModel - NSPOOL = {} - ELEMENTS = [] - - def self.append_features(klass) - super - klass.install_must_call_validator("atom", URI) - [ - ["lang", :xml], - ["base", :xml], - ].each do |name, uri, required| - klass.install_get_attribute(name, uri, required, [nil, :inherit]) - end - klass.class_eval do - class << self - # Returns the Atom URI W3C Namespace - def required_uri - URI - end - - # Returns true - def need_parent? - true - end - end - end - end - end - - module ContentModel - module ClassMethods - def content_type - @content_type ||= nil - end - end - - class << self - def append_features(klass) - super - klass.extend(ClassMethods) - klass.content_setup(klass.content_type, klass.tag_name) - end - end - - def maker_target(target) - target - end - - private - def setup_maker_element_writer - "#{self.class.name.split(/::/).last.downcase}=" - end - - def setup_maker_element(target) - target.__send__(setup_maker_element_writer, content) - super - end - end - - module URIContentModel - class << self - def append_features(klass) - super - klass.class_eval do - @content_type = [nil, :uri] - include(ContentModel) - end - end - end - end - - # The TextConstruct module is used to define a Text construct Atom element, - # which is used to store small quantities of human-readable text. - # - # The TextConstruct has a type attribute, e.g. text, html, xhtml - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#text.constructs - module TextConstruct - def self.append_features(klass) - super - klass.class_eval do - [ - ["type", ""], - ].each do |name, uri, required| - install_get_attribute(name, uri, required, :text_type) - end - - content_setup - add_need_initialize_variable("xhtml") - - class << self - def xml_getter - "xhtml" - end - - def xml_setter - "xhtml=" - end - end - end - end - - attr_writer :xhtml - - # Returns or builds the XHTML content. - def xhtml - return @xhtml if @xhtml.nil? - if @xhtml.is_a?(XML::Element) and - [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI] - return @xhtml - end - - children = @xhtml - children = [children] unless children.is_a?(Array) - XML::Element.new("div", nil, XHTML_URI, - {"xmlns" => XHTML_URI}, children) - end - - # Returns true if type is "xhtml". - def have_xml_content? - @type == "xhtml" - end - - # Raises a MissingTagError or NotExpectedTagError - # if the element is not properly formatted. - def atom_validate(ignore_unknown_element, tags, uri) - if have_xml_content? - if @xhtml.nil? - raise MissingTagError.new("div", tag_name) - end - unless [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI] - raise NotExpectedTagError.new(@xhtml.name, @xhtml.uri, tag_name) - end - end - end - - private - def maker_target(target) - target.__send__(self.class.name.split(/::/).last.downcase) {|x| x} - end - - def setup_maker_attributes(target) - target.type = type - target.content = content - target.xml_content = @xhtml - end - end - - # The PersonConstruct module is used to define a person Atom element that can be - # used to describe a person, corporation or similar entity. - # - # The PersonConstruct has a Name, Uri and Email child elements. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#atomPersonConstruct - module PersonConstruct - - # Adds attributes for name, uri, and email to the +klass+ - def self.append_features(klass) - super - klass.class_eval do - [ - ["name", nil], - ["uri", "?"], - ["email", "?"], - ].each do |tag, occurs| - install_have_attribute_element(tag, URI, occurs, nil, :content) - end - end - end - - def maker_target(target) - target.__send__("new_#{self.class.name.split(/::/).last.downcase}") - end - - # The name of the person or entity. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.name - class Name < RSS::Element - include CommonModel - include ContentModel - end - - # The URI of the person or entity. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.uri - class Uri < RSS::Element - include CommonModel - include URIContentModel - end - - # The email of the person or entity. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.email - class Email < RSS::Element - include CommonModel - include ContentModel - end - end - - # Element used to describe an Atom date and time in the ISO 8601 format - # - # Examples: - # * 2013-03-04T15:30:02Z - # * 2013-03-04T10:30:02-05:00 - module DateConstruct - def self.append_features(klass) - super - klass.class_eval do - @content_type = :w3cdtf - include(ContentModel) - end - end - - # Raises NotAvailableValueError if element content is nil - def atom_validate(ignore_unknown_element, tags, uri) - raise NotAvailableValueError.new(tag_name, "") if content.nil? - end - end - - module DuplicateLinkChecker - # Checks if there are duplicate links with the same type and hreflang attributes - # that have an alternate (or empty) rel attribute - # - # Raises a TooMuchTagError if there are duplicates found - def validate_duplicate_links(links) - link_infos = {} - links.each do |link| - rel = link.rel || "alternate" - next unless rel == "alternate" - key = [link.hreflang, link.type] - if link_infos.has_key?(key) - raise TooMuchTagError.new("link", tag_name) - end - link_infos[key] = true - end - end - end - - # Defines the top-level element of an Atom Feed Document. - # It consists of a number of children Entry elements, - # and has the following attributes: - # - # * author - # * categories - # * category - # * content - # * contributor - # * entries (aliased as items) - # * entry - # * generator - # * icon - # * id - # * link - # * logo - # * rights - # * subtitle - # * title - # * updated - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.feed - class Feed < RSS::Element - include RootElementMixin - include CommonModel - include DuplicateLinkChecker - - install_ns('', URI) - - [ - ["author", "*", :children], - ["category", "*", :children, "categories"], - ["contributor", "*", :children], - ["generator", "?"], - ["icon", "?", nil, :content], - ["id", nil, nil, :content], - ["link", "*", :children], - ["logo", "?"], - ["rights", "?"], - ["subtitle", "?", nil, :content], - ["title", nil, nil, :content], - ["updated", nil, nil, :content], - ["entry", "*", :children, "entries"], - ].each do |tag, occurs, type, *args| - type ||= :child - __send__("install_have_#{type}_element", - tag, URI, occurs, tag, *args) - end - - # Creates a new Atom feed - def initialize(version=nil, encoding=nil, standalone=nil) - super("1.0", version, encoding, standalone) - @feed_type = "atom" - @feed_subtype = "feed" - end - - alias_method :items, :entries - - # Returns true if there are any authors for the feed or any of the Entry - # child elements have an author - def have_author? - authors.any? {|author| !author.to_s.empty?} or - entries.any? {|entry| entry.have_author?(false)} - end - - private - def atom_validate(ignore_unknown_element, tags, uri) - unless have_author? - raise MissingTagError.new("author", tag_name) - end - validate_duplicate_links(links) - end - - def have_required_elements? - super and have_author? - end - - def maker_target(maker) - maker.channel - end - - def setup_maker_element(channel) - prev_dc_dates = channel.dc_dates.to_a.dup - super - channel.about = id.content if id - channel.dc_dates.replace(prev_dc_dates) - end - - def setup_maker_elements(channel) - super - items = channel.maker.items - entries.each do |entry| - entry.setup_maker(items) - end - end - - # PersonConstruct that contains information regarding the author - # of a Feed or Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.author - class Author < RSS::Element - include CommonModel - include PersonConstruct - end - - # Contains information about a category associated with a Feed or Entry. - # It has the following attributes: - # - # * term - # * scheme - # * label - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.category - class Category < RSS::Element - include CommonModel - - [ - ["term", "", true], - ["scheme", "", false, [nil, :uri]], - ["label", ""], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - private - def maker_target(target) - target.new_category - end - end - - # PersonConstruct that contains information regarding the - # contributors of a Feed or Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.contributor - class Contributor < RSS::Element - include CommonModel - include PersonConstruct - end - - # Contains information on the agent used to generate the feed. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.generator - class Generator < RSS::Element - include CommonModel - include ContentModel - - [ - ["uri", "", false, [nil, :uri]], - ["version", ""], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - private - def setup_maker_attributes(target) - target.generator do |generator| - generator.uri = uri if uri - generator.version = version if version - end - end - end - - # Defines an image that provides a visual identification for a eed. - # The image should have an aspect ratio of 1:1. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.icon - class Icon < RSS::Element - include CommonModel - include URIContentModel - end - - # Defines the Universally Unique Identifier (UUID) for a Feed or Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.id - class Id < RSS::Element - include CommonModel - include URIContentModel - end - - # Defines a reference to a Web resource. It has the following - # attributes: - # - # * href - # * rel - # * type - # * hreflang - # * title - # * length - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.link - class Link < RSS::Element - include CommonModel - - [ - ["href", "", true, [nil, :uri]], - ["rel", ""], - ["type", ""], - ["hreflang", ""], - ["title", ""], - ["length", ""], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - private - def maker_target(target) - target.new_link - end - end - - # Defines an image that provides a visual identification for the Feed. - # The image should have an aspect ratio of 2:1 (horizontal:vertical). - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.logo - class Logo < RSS::Element - include CommonModel - include URIContentModel - - def maker_target(target) - target.maker.image - end - - private - def setup_maker_element_writer - "url=" - end - end - - # TextConstruct that contains copyright information regarding - # the content in an Entry or Feed. It should not be used to - # convey machine readable licensing information. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.rights - class Rights < RSS::Element - include CommonModel - include TextConstruct - end - - # TextConstruct that conveys a description or subtitle for a Feed. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.subtitle - class Subtitle < RSS::Element - include CommonModel - include TextConstruct - end - - # TextConstruct that conveys a description or title for a Feed or Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.title - class Title < RSS::Element - include CommonModel - include TextConstruct - end - - # DateConstruct indicating the most recent time when a Feed or - # Entry was modified in a way the publisher considers - # significant. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.updated - class Updated < RSS::Element - include CommonModel - include DateConstruct - end - - # Defines a child Atom Entry element of an Atom Feed element. - # It has the following attributes: - # - # * author - # * category - # * categories - # * content - # * contributor - # * id - # * link - # * published - # * rights - # * source - # * summary - # * title - # * updated - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry - class Entry < RSS::Element - include CommonModel - include DuplicateLinkChecker - - [ - ["author", "*", :children], - ["category", "*", :children, "categories"], - ["content", "?", :child], - ["contributor", "*", :children], - ["id", nil, nil, :content], - ["link", "*", :children], - ["published", "?", :child, :content], - ["rights", "?", :child], - ["source", "?"], - ["summary", "?", :child], - ["title", nil], - ["updated", nil, :child, :content], - ].each do |tag, occurs, type, *args| - type ||= :attribute - __send__("install_have_#{type}_element", - tag, URI, occurs, tag, *args) - end - - # Returns whether any of the following are true: - # - # * There are any authors in the feed - # * If the parent element has an author and the +check_parent+ - # parameter was given. - # * There is a source element that has an author - def have_author?(check_parent=true) - authors.any? {|author| !author.to_s.empty?} or - (check_parent and @parent and @parent.have_author?) or - (source and source.have_author?) - end - - private - def atom_validate(ignore_unknown_element, tags, uri) - unless have_author? - raise MissingTagError.new("author", tag_name) - end - validate_duplicate_links(links) - end - - def have_required_elements? - super and have_author? - end - - def maker_target(items) - if items.respond_to?("items") - # For backward compatibility - items = items.items - end - items.new_item - end - - # Feed::Author - Author = Feed::Author - # Feed::Category - Category = Feed::Category - - # Contains or links to the content of the Entry. - # It has the following attributes: - # - # * type - # * src - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.content - class Content < RSS::Element - include CommonModel - - class << self - def xml_setter - "xml=" - end - - def xml_getter - "xml" - end - end - - [ - ["type", ""], - ["src", "", false, [nil, :uri]], - ].each do |name, uri, required, type| - install_get_attribute(name, uri, required, type) - end - - content_setup - add_need_initialize_variable("xml") - - # Returns the element content in XML. - attr_writer :xml - - # Returns true if the element has inline XML content. - def have_xml_content? - inline_xhtml? or inline_other_xml? - end - - # Returns or builds the element content in XML. - def xml - return @xml unless inline_xhtml? - return @xml if @xml.nil? - if @xml.is_a?(XML::Element) and - [@xml.name, @xml.uri] == ["div", XHTML_URI] - return @xml - end - - children = @xml - children = [children] unless children.is_a?(Array) - XML::Element.new("div", nil, XHTML_URI, - {"xmlns" => XHTML_URI}, children) - end - - # Returns the element content in XHTML. - def xhtml - if inline_xhtml? - xml - else - nil - end - end - - # Raises a MissingAttributeError, NotAvailableValueError, - # MissingTagError or NotExpectedTagError if the element is - # not properly formatted. - def atom_validate(ignore_unknown_element, tags, uri) - if out_of_line? - raise MissingAttributeError.new(tag_name, "type") if @type.nil? - unless (content.nil? or content.empty?) - raise NotAvailableValueError.new(tag_name, content) - end - elsif inline_xhtml? - if @xml.nil? - raise MissingTagError.new("div", tag_name) - end - unless @xml.name == "div" and @xml.uri == XHTML_URI - raise NotExpectedTagError.new(@xml.name, @xml.uri, tag_name) - end - end - end - - # Returns true if the element contains inline content - # that has a text or HTML media type, or no media type at all. - def inline_text? - !out_of_line? and [nil, "text", "html"].include?(@type) - end - - # Returns true if the element contains inline content that - # has a HTML media type. - def inline_html? - return false if out_of_line? - @type == "html" or mime_split == ["text", "html"] - end - - # Returns true if the element contains inline content that - # has a XHTML media type. - def inline_xhtml? - !out_of_line? and @type == "xhtml" - end - - # Returns true if the element contains inline content that - # has a MIME media type. - def inline_other? - return false if out_of_line? - media_type, subtype = mime_split - return false if media_type.nil? or subtype.nil? - true - end - - # Returns true if the element contains inline content that - # has a text media type. - def inline_other_text? - return false unless inline_other? - return false if inline_other_xml? - - media_type, = mime_split - return true if "text" == media_type.downcase - false - end - - # Returns true if the element contains inline content that - # has a XML media type. - def inline_other_xml? - return false unless inline_other? - - media_type, subtype = mime_split - normalized_mime_type = "#{media_type}/#{subtype}".downcase - if /(?:\+xml|^xml)$/ =~ subtype or - %w(text/xml-external-parsed-entity - application/xml-external-parsed-entity - application/xml-dtd).find {|x| x == normalized_mime_type} - return true - end - false - end - - # Returns true if the element contains inline content - # encoded in base64. - def inline_other_base64? - inline_other? and !inline_other_text? and !inline_other_xml? - end - - # Returns true if the element contains linked content. - def out_of_line? - not @src.nil? - end - - # Splits the type attribute into an array, e.g. ["text", "xml"] - def mime_split - media_type = subtype = nil - if /\A\s*([a-z]+)\/([a-z\+]+)\s*(?:;.*)?\z/i =~ @type.to_s - media_type = $1.downcase - subtype = $2.downcase - end - [media_type, subtype] - end - - # Returns true if the content needs to be encoded in base64. - def need_base64_encode? - inline_other_base64? - end - - private - def empty_content? - out_of_line? or super - end - end - - # Feed::Contributor - Contributor = Feed::Contributor - # Feed::Id - Id = Feed::Id - # Feed::Link - Link = Feed::Link - - # DateConstruct that usually indicates the time of the initial - # creation of an Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.published - class Published < RSS::Element - include CommonModel - include DateConstruct - end - - # Feed::Rights - Rights = Feed::Rights - - # Defines a Atom Source element. It has the following attributes: - # - # * author - # * category - # * categories - # * content - # * contributor - # * generator - # * icon - # * id - # * link - # * logo - # * rights - # * subtitle - # * title - # * updated - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.source - class Source < RSS::Element - include CommonModel - - [ - ["author", "*", :children], - ["category", "*", :children, "categories"], - ["contributor", "*", :children], - ["generator", "?"], - ["icon", "?"], - ["id", "?", nil, :content], - ["link", "*", :children], - ["logo", "?"], - ["rights", "?"], - ["subtitle", "?"], - ["title", "?"], - ["updated", "?", nil, :content], - ].each do |tag, occurs, type, *args| - type ||= :attribute - __send__("install_have_#{type}_element", - tag, URI, occurs, tag, *args) - end - - # Returns true if the Source element has an author. - def have_author? - !author.to_s.empty? - end - - # Feed::Author - Author = Feed::Author - # Feed::Category - Category = Feed::Category - # Feed::Contributor - Contributor = Feed::Contributor - # Feed::Generator - Generator = Feed::Generator - # Feed::Icon - Icon = Feed::Icon - # Feed::Id - Id = Feed::Id - # Feed::Link - Link = Feed::Link - # Feed::Logo - Logo = Feed::Logo - # Feed::Rights - Rights = Feed::Rights - # Feed::Subtitle - Subtitle = Feed::Subtitle - # Feed::Title - Title = Feed::Title - # Feed::Updated - Updated = Feed::Updated - end - - # TextConstruct that describes a summary of the Entry. - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.summary - class Summary < RSS::Element - include CommonModel - include TextConstruct - end - - # Feed::Title - Title = Feed::Title - # Feed::Updated - Updated = Feed::Updated - end - end - - # Defines a top-level Atom Entry element, - # used as the document element of a stand-alone Atom Entry Document. - # It has the following attributes: - # - # * author - # * category - # * categories - # * content - # * contributor - # * id - # * link - # * published - # * rights - # * source - # * summary - # * title - # * updated - # - # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry] - class Entry < RSS::Element - include RootElementMixin - include CommonModel - include DuplicateLinkChecker - - [ - ["author", "*", :children], - ["category", "*", :children, "categories"], - ["content", "?"], - ["contributor", "*", :children], - ["id", nil, nil, :content], - ["link", "*", :children], - ["published", "?", :child, :content], - ["rights", "?"], - ["source", "?"], - ["summary", "?"], - ["title", nil], - ["updated", nil, nil, :content], - ].each do |tag, occurs, type, *args| - type ||= :attribute - __send__("install_have_#{type}_element", - tag, URI, occurs, tag, *args) - end - - # Creates a new Atom Entry element. - def initialize(version=nil, encoding=nil, standalone=nil) - super("1.0", version, encoding, standalone) - @feed_type = "atom" - @feed_subtype = "entry" - end - - # Returns the Entry in an array. - def items - [self] - end - - # Sets up the +maker+ for constructing Entry elements. - def setup_maker(maker) - maker = maker.maker if maker.respond_to?("maker") - super(maker) - end - - # Returns where there are any authors present or there is a - # source with an author. - def have_author? - authors.any? {|author| !author.to_s.empty?} or - (source and source.have_author?) - end - - private - def atom_validate(ignore_unknown_element, tags, uri) - unless have_author? - raise MissingTagError.new("author", tag_name) - end - validate_duplicate_links(links) - end - - def have_required_elements? - super and have_author? - end - - def maker_target(maker) - maker.items.new_item - end - - # Feed::Entry::Author - Author = Feed::Entry::Author - # Feed::Entry::Category - Category = Feed::Entry::Category - # Feed::Entry::Content - Content = Feed::Entry::Content - # Feed::Entry::Contributor - Contributor = Feed::Entry::Contributor - # Feed::Entry::Id - Id = Feed::Entry::Id - # Feed::Entry::Link - Link = Feed::Entry::Link - # Feed::Entry::Published - Published = Feed::Entry::Published - # Feed::Entry::Rights - Rights = Feed::Entry::Rights - # Feed::Entry::Source - Source = Feed::Entry::Source - # Feed::Entry::Summary - Summary = Feed::Entry::Summary - # Feed::Entry::Title - Title = Feed::Entry::Title - # Feed::Entry::Updated - Updated = Feed::Entry::Updated - end - end - - Atom::CommonModel::ELEMENTS.each do |name| - BaseListener.install_get_text_element(Atom::URI, name, "#{name}=") - end - - module ListenerMixin - private - def initial_start_feed(tag_name, prefix, attrs, ns) - check_ns(tag_name, prefix, ns, Atom::URI, false) - - @rss = Atom::Feed.new(@version, @encoding, @standalone) - @rss.do_validate = @do_validate - @rss.xml_stylesheets = @xml_stylesheets - @rss.lang = attrs["xml:lang"] - @rss.base = attrs["xml:base"] - @last_element = @rss - pr = Proc.new do |text, tags| - @rss.validate_for_stream(tags) if @do_validate - end - @proc_stack.push(pr) - end - - def initial_start_entry(tag_name, prefix, attrs, ns) - check_ns(tag_name, prefix, ns, Atom::URI, false) - - @rss = Atom::Entry.new(@version, @encoding, @standalone) - @rss.do_validate = @do_validate - @rss.xml_stylesheets = @xml_stylesheets - @rss.lang = attrs["xml:lang"] - @rss.base = attrs["xml:base"] - @last_element = @rss - pr = Proc.new do |text, tags| - @rss.validate_for_stream(tags) if @do_validate - end - @proc_stack.push(pr) - end - end -end diff --git a/ruby/lib/rss/content.rb b/ruby/lib/rss/content.rb deleted file mode 100644 index 78c18d103..000000000 --- a/ruby/lib/rss/content.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: false -require_relative "rss" - -module RSS - # The prefix for the Content XML namespace. - CONTENT_PREFIX = 'content' - # The URI of the Content specification. - CONTENT_URI = "http://purl.org/rss/1.0/modules/content/" - - module ContentModel - extend BaseModel - - ELEMENTS = ["#{CONTENT_PREFIX}_encoded"] - - def self.append_features(klass) - super - - klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI) - ELEMENTS.each do |full_name| - name = full_name[(CONTENT_PREFIX.size + 1)..-1] - klass.install_text_element(name, CONTENT_URI, "?", full_name) - end - end - end - - prefix_size = CONTENT_PREFIX.size + 1 - ContentModel::ELEMENTS.each do |full_name| - name = full_name[prefix_size..-1] - BaseListener.install_get_text_element(CONTENT_URI, name, full_name) - end -end - -require 'rss/content/1.0' -require 'rss/content/2.0' diff --git a/ruby/lib/rss/content/1.0.rb b/ruby/lib/rss/content/1.0.rb deleted file mode 100644 index 1367dfe09..000000000 --- a/ruby/lib/rss/content/1.0.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: false -require 'rss/1.0' - -module RSS - RDF.install_ns(CONTENT_PREFIX, CONTENT_URI) - - class RDF - class Item; include ContentModel; end - end -end diff --git a/ruby/lib/rss/content/2.0.rb b/ruby/lib/rss/content/2.0.rb deleted file mode 100644 index 3b468248a..000000000 --- a/ruby/lib/rss/content/2.0.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: false -require "rss/2.0" - -module RSS - Rss.install_ns(CONTENT_PREFIX, CONTENT_URI) - - class Rss - class Channel - class Item; include ContentModel; end - end - end -end diff --git a/ruby/lib/rss/converter.rb b/ruby/lib/rss/converter.rb deleted file mode 100644 index d372e0672..000000000 --- a/ruby/lib/rss/converter.rb +++ /dev/null @@ -1,171 +0,0 @@ -# frozen_string_literal: false -require_relative "utils" - -module RSS - - class Converter - - include Utils - - def initialize(to_enc, from_enc=nil) - if "".respond_to?(:encode) - @to_encoding = to_enc - return - end - normalized_to_enc = to_enc.downcase.gsub(/-/, '_') - from_enc ||= 'utf-8' - normalized_from_enc = from_enc.downcase.gsub(/-/, '_') - if normalized_to_enc == normalized_from_enc - def_same_enc() - else - def_diff_enc = "def_to_#{normalized_to_enc}_from_#{normalized_from_enc}" - if respond_to?(def_diff_enc) - __send__(def_diff_enc) - else - def_else_enc(to_enc, from_enc) - end - end - end - - def convert(value) - if value.is_a?(String) and value.respond_to?(:encode) - value.encode(@to_encoding) - else - value - end - end - - def def_convert(depth=0) - instance_eval(<<-EOC, *get_file_and_line_from_caller(depth)) - def convert(value) - if value.kind_of?(String) - #{yield('value')} - else - value - end - end - EOC - end - - def def_iconv_convert(to_enc, from_enc, depth=0) - begin - require "iconv" - @iconv = Iconv.new(to_enc, from_enc) - def_convert(depth+1) do |value| - <<-EOC - begin - @iconv.iconv(#{value}) - rescue Iconv::Failure - raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}") - end - EOC - end - rescue LoadError, ArgumentError, SystemCallError - raise UnknownConversionMethodError.new(to_enc, from_enc) - end - end - - def def_else_enc(to_enc, from_enc) - def_iconv_convert(to_enc, from_enc, 0) - end - - def def_same_enc() - def_convert do |value| - value - end - end - - def def_uconv_convert_if_can(meth, to_enc, from_enc, nkf_arg) - begin - require "uconv" - def_convert(1) do |value| - <<-EOC - begin - Uconv.#{meth}(#{value}) - rescue Uconv::Error - raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}") - end - EOC - end - rescue LoadError - require 'nkf' - if NKF.const_defined?(:UTF8) - def_convert(1) do |value| - "NKF.nkf(#{nkf_arg.dump}, #{value})" - end - else - def_iconv_convert(to_enc, from_enc, 1) - end - end - end - - def def_to_euc_jp_from_utf_8 - def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We') - end - - def def_to_utf_8_from_euc_jp - def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew') - end - - def def_to_shift_jis_from_utf_8 - def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws') - end - - def def_to_utf_8_from_shift_jis - def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw') - end - - def def_to_euc_jp_from_shift_jis - require "nkf" - def_convert do |value| - "NKF.nkf('-Se', #{value})" - end - end - - def def_to_shift_jis_from_euc_jp - require "nkf" - def_convert do |value| - "NKF.nkf('-Es', #{value})" - end - end - - def def_to_euc_jp_from_iso_2022_jp - require "nkf" - def_convert do |value| - "NKF.nkf('-Je', #{value})" - end - end - - def def_to_iso_2022_jp_from_euc_jp - require "nkf" - def_convert do |value| - "NKF.nkf('-Ej', #{value})" - end - end - - def def_to_utf_8_from_iso_8859_1 - def_convert do |value| - "#{value}.unpack('C*').pack('U*')" - end - end - - def def_to_iso_8859_1_from_utf_8 - def_convert do |value| - <<-EOC - array_utf8 = #{value}.unpack('U*') - array_enc = [] - array_utf8.each do |num| - if num <= 0xFF - array_enc << num - else - array_enc.concat "&\#\#{num};".unpack('C*') - end - end - array_enc.pack('C*') - EOC - end - end - - end - -end diff --git a/ruby/lib/rss/dublincore.rb b/ruby/lib/rss/dublincore.rb deleted file mode 100644 index 85b836d3b..000000000 --- a/ruby/lib/rss/dublincore.rb +++ /dev/null @@ -1,164 +0,0 @@ -# frozen_string_literal: false -require_relative "rss" - -module RSS - # The prefix for the Dublin Core XML namespace. - DC_PREFIX = 'dc' - # The URI of the Dublin Core specification. - DC_URI = "http://purl.org/dc/elements/1.1/" - - module BaseDublinCoreModel - def append_features(klass) - super - - return if klass.instance_of?(Module) - DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| - plural = plural_name || "#{name}s" - full_name = "#{DC_PREFIX}_#{name}" - full_plural_name = "#{DC_PREFIX}_#{plural}" - klass_name = "DublinCore#{Utils.to_class_name(name)}" - klass.install_must_call_validator(DC_PREFIX, DC_URI) - klass.install_have_children_element(name, DC_URI, "*", - full_name, full_plural_name) - klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0)) - remove_method :#{full_name} - remove_method :#{full_name}= - remove_method :set_#{full_name} - - def #{full_name} - @#{full_name}.first and @#{full_name}.first.value - end - - def #{full_name}=(new_value) - @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value) - end - alias set_#{full_name} #{full_name}= - EOC - end - klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0)) - if method_defined?(:date) - alias date_without_#{DC_PREFIX}_date= date= - - def date=(value) - self.date_without_#{DC_PREFIX}_date = value - self.#{DC_PREFIX}_date = value - end - else - alias date #{DC_PREFIX}_date - alias date= #{DC_PREFIX}_date= - end - - # For backward compatibility - alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list - EOC - end - end - - module DublinCoreModel - - extend BaseModel - extend BaseDublinCoreModel - - TEXT_ELEMENTS = { - "title" => nil, - "description" => nil, - "creator" => nil, - "subject" => nil, - "publisher" => nil, - "contributor" => nil, - "type" => nil, - "format" => nil, - "identifier" => nil, - "source" => nil, - "language" => nil, - "relation" => nil, - "coverage" => nil, - "rights" => "rights_list" - } - - DATE_ELEMENTS = { - "date" => "w3cdtf", - } - - ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a - DublinCoreModel::DATE_ELEMENTS.each do |name, | - ELEMENT_NAME_INFOS << [name, nil] - end - - ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys - - ELEMENTS.each do |name, plural_name| - module_eval(<<-EOC, *get_file_and_line_from_caller(0)) - class DublinCore#{Utils.to_class_name(name)} < Element - include RSS10 - - content_setup - - class << self - def required_prefix - DC_PREFIX - end - - def required_uri - DC_URI - end - end - - @tag_name = #{name.dump} - - alias_method(:value, :content) - alias_method(:value=, :content=) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.content = args[0] - end - end - - def full_name - tag_name_with_prefix(DC_PREFIX) - end - - def maker_target(target) - target.new_#{name} - end - - def setup_maker_attributes(#{name}) - #{name}.content = content - end - end - EOC - end - - DATE_ELEMENTS.each do |name, type| - tag_name = "#{DC_PREFIX}:#{name}" - module_eval(<<-EOC, *get_file_and_line_from_caller(0)) - class DublinCore#{Utils.to_class_name(name)} < Element - remove_method(:content=) - remove_method(:value=) - - date_writer("content", #{type.dump}, #{tag_name.dump}) - - alias_method(:value=, :content=) - end - EOC - end - end - - # For backward compatibility - DublincoreModel = DublinCoreModel - - DublinCoreModel::ELEMENTS.each do |name| - class_name = Utils.to_class_name(name) - BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}") - end - - DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"} -end - -require 'rss/dublincore/1.0' -require 'rss/dublincore/2.0' -require_relative 'dublincore/atom' diff --git a/ruby/lib/rss/dublincore/1.0.rb b/ruby/lib/rss/dublincore/1.0.rb deleted file mode 100644 index 1d96fab9b..000000000 --- a/ruby/lib/rss/dublincore/1.0.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: false -require "rss/1.0" - -module RSS - RDF.install_ns(DC_PREFIX, DC_URI) - - class RDF - class Channel; include DublinCoreModel; end - class Image; include DublinCoreModel; end - class Item; include DublinCoreModel; end - class Textinput; include DublinCoreModel; end - end -end diff --git a/ruby/lib/rss/dublincore/2.0.rb b/ruby/lib/rss/dublincore/2.0.rb deleted file mode 100644 index e3011fef6..000000000 --- a/ruby/lib/rss/dublincore/2.0.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: false -require "rss/2.0" - -module RSS - Rss.install_ns(DC_PREFIX, DC_URI) - - class Rss - class Channel - include DublinCoreModel - class Item; include DublinCoreModel; end - end - end -end diff --git a/ruby/lib/rss/dublincore/atom.rb b/ruby/lib/rss/dublincore/atom.rb deleted file mode 100644 index 1cfcdec67..000000000 --- a/ruby/lib/rss/dublincore/atom.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: false -require_relative "../atom" - -module RSS - module Atom - Feed.install_ns(DC_PREFIX, DC_URI) - - class Feed - include DublinCoreModel - class Entry; include DublinCoreModel; end - end - - class Entry - include DublinCoreModel - end - end -end diff --git a/ruby/lib/rss/image.rb b/ruby/lib/rss/image.rb deleted file mode 100644 index 837f7d18f..000000000 --- a/ruby/lib/rss/image.rb +++ /dev/null @@ -1,198 +0,0 @@ -# frozen_string_literal: false -require 'rss/1.0' -require_relative 'dublincore' - -module RSS - - # The prefix for the Image XML namespace. - IMAGE_PREFIX = 'image' - # The URI for the Image specification. - IMAGE_URI = 'http://purl.org/rss/1.0/modules/image/' - - RDF.install_ns(IMAGE_PREFIX, IMAGE_URI) - - # This constant holds strings which contain the names of - # image elements, with the appropriate prefix. - IMAGE_ELEMENTS = [] - - %w(item favicon).each do |name| - class_name = Utils.to_class_name(name) - BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}") - IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}" - end - - module ImageModelUtils - def validate_one_tag_name(ignore_unknown_element, name, tags) - if !ignore_unknown_element - invalid = tags.find {|tag| tag != name} - raise UnknownTagError.new(invalid, IMAGE_URI) if invalid - end - raise TooMuchTagError.new(name, tag_name) if tags.size > 1 - end - end - - module ImageItemModel - include ImageModelUtils - extend BaseModel - - def self.append_features(klass) - super - - klass.install_have_child_element("item", IMAGE_URI, "?", - "#{IMAGE_PREFIX}_item") - klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) - end - - class ImageItem < Element - include RSS10 - include DublinCoreModel - - @tag_name = "item" - - class << self - def required_prefix - IMAGE_PREFIX - end - - def required_uri - IMAGE_URI - end - end - - install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) - - [ - ["about", ::RSS::RDF::URI, true], - ["resource", ::RSS::RDF::URI, false], - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{::RSS::RDF::PREFIX}:#{name}") - end - - %w(width height).each do |tag| - full_name = "#{IMAGE_PREFIX}_#{tag}" - disp_name = "#{IMAGE_PREFIX}:#{tag}" - install_text_element(tag, IMAGE_URI, "?", - full_name, :integer, disp_name) - BaseListener.install_get_text_element(IMAGE_URI, tag, full_name) - end - - alias width= image_width= - alias width image_width - alias height= image_height= - alias height image_height - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - self.resource = args[1] - end - end - - def full_name - tag_name_with_prefix(IMAGE_PREFIX) - end - - private - def maker_target(target) - target.image_item - end - - def setup_maker_attributes(item) - item.about = self.about - item.resource = self.resource - end - end - end - - module ImageFaviconModel - include ImageModelUtils - extend BaseModel - - def self.append_features(klass) - super - - unless klass.class == Module - klass.install_have_child_element("favicon", IMAGE_URI, "?", - "#{IMAGE_PREFIX}_favicon") - klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI) - end - end - - class ImageFavicon < Element - include RSS10 - include DublinCoreModel - - @tag_name = "favicon" - - class << self - def required_prefix - IMAGE_PREFIX - end - - def required_uri - IMAGE_URI - end - end - - [ - ["about", ::RSS::RDF::URI, true, ::RSS::RDF::PREFIX], - ["size", IMAGE_URI, true, IMAGE_PREFIX], - ].each do |name, uri, required, prefix| - install_get_attribute(name, uri, required, nil, nil, - "#{prefix}:#{name}") - end - - AVAILABLE_SIZES = %w(small medium large) - alias_method :set_size, :size= - private :set_size - def size=(new_value) - if @do_validate and !new_value.nil? - new_value = new_value.strip - unless AVAILABLE_SIZES.include?(new_value) - attr_name = "#{IMAGE_PREFIX}:size" - raise NotAvailableValueError.new(full_name, new_value, attr_name) - end - end - set_size(new_value) - end - - alias image_size= size= - alias image_size size - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - self.size = args[1] - end - end - - def full_name - tag_name_with_prefix(IMAGE_PREFIX) - end - - private - def maker_target(target) - target.image_favicon - end - - def setup_maker_attributes(favicon) - favicon.about = self.about - favicon.size = self.size - end - end - - end - - class RDF - class Channel; include ImageFaviconModel; end - class Item; include ImageItemModel; end - end - -end diff --git a/ruby/lib/rss/itunes.rb b/ruby/lib/rss/itunes.rb deleted file mode 100644 index bc3e25448..000000000 --- a/ruby/lib/rss/itunes.rb +++ /dev/null @@ -1,425 +0,0 @@ -# frozen_string_literal: false -require 'rss/2.0' - -module RSS - # The prefix for the iTunes XML namespace. - ITUNES_PREFIX = 'itunes' - # The URI of the iTunes specification. - ITUNES_URI = 'http://www.itunes.com/dtds/podcast-1.0.dtd' - - Rss.install_ns(ITUNES_PREFIX, ITUNES_URI) - - module ITunesModelUtils - include Utils - - def def_class_accessor(klass, name, type, *args) - normalized_name = name.gsub(/-/, "_") - full_name = "#{ITUNES_PREFIX}_#{normalized_name}" - klass_name = "ITunes#{Utils.to_class_name(normalized_name)}" - - case type - when :element, :attribute - klass::ELEMENTS << full_name - def_element_class_accessor(klass, name, full_name, klass_name, *args) - when :elements - klass::ELEMENTS << full_name - def_elements_class_accessor(klass, name, full_name, klass_name, *args) - else - klass.install_must_call_validator(ITUNES_PREFIX, ITUNES_URI) - klass.install_text_element(normalized_name, ITUNES_URI, "?", - full_name, type, name) - end - end - - def def_element_class_accessor(klass, name, full_name, klass_name, - recommended_attribute_name=nil) - klass.install_have_child_element(name, ITUNES_PREFIX, "?", full_name) - end - - def def_elements_class_accessor(klass, name, full_name, klass_name, - plural_name, recommended_attribute_name=nil) - full_plural_name = "#{ITUNES_PREFIX}_#{plural_name}" - klass.install_have_children_element(name, ITUNES_PREFIX, "*", - full_name, full_plural_name) - end - end - - module ITunesBaseModel - extend ITunesModelUtils - - ELEMENTS = [] - - ELEMENT_INFOS = [["author"], - ["block", :yes_other], - ["explicit", :explicit_clean_other], - ["keywords", :csv], - ["subtitle"], - ["summary"]] - end - - module ITunesChannelModel - extend BaseModel - extend ITunesModelUtils - include ITunesBaseModel - - ELEMENTS = [] - - class << self - def append_features(klass) - super - - return if klass.instance_of?(Module) - ELEMENT_INFOS.each do |name, type, *additional_infos| - def_class_accessor(klass, name, type, *additional_infos) - end - end - end - - ELEMENT_INFOS = [ - ["category", :elements, "categories", "text"], - ["image", :attribute, "href"], - ["owner", :element], - ["new-feed-url"], - ] + ITunesBaseModel::ELEMENT_INFOS - - class ITunesCategory < Element - include RSS09 - - @tag_name = "category" - - class << self - def required_prefix - ITUNES_PREFIX - end - - def required_uri - ITUNES_URI - end - end - - [ - ["text", "", true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required) - end - - ITunesCategory = self - install_have_children_element("category", ITUNES_URI, "*", - "#{ITUNES_PREFIX}_category", - "#{ITUNES_PREFIX}_categories") - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.text = args[0] - end - end - - def full_name - tag_name_with_prefix(ITUNES_PREFIX) - end - - private - def maker_target(categories) - if text or !itunes_categories.empty? - categories.new_category - else - nil - end - end - - def setup_maker_attributes(category) - category.text = text if text - end - - def setup_maker_elements(category) - super(category) - itunes_categories.each do |sub_category| - sub_category.setup_maker(category) - end - end - end - - class ITunesImage < Element - include RSS09 - - @tag_name = "image" - - class << self - def required_prefix - ITUNES_PREFIX - end - - def required_uri - ITUNES_URI - end - end - - [ - ["href", "", true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required) - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.href = args[0] - end - end - - def full_name - tag_name_with_prefix(ITUNES_PREFIX) - end - - private - def maker_target(target) - if href - target.itunes_image {|image| image} - else - nil - end - end - - def setup_maker_attributes(image) - image.href = href - end - end - - class ITunesOwner < Element - include RSS09 - - @tag_name = "owner" - - class << self - def required_prefix - ITUNES_PREFIX - end - - def required_uri - ITUNES_URI - end - end - - install_must_call_validator(ITUNES_PREFIX, ITUNES_URI) - [ - ["name"], - ["email"], - ].each do |name,| - ITunesBaseModel::ELEMENT_INFOS << name - install_text_element(name, ITUNES_URI, nil, "#{ITUNES_PREFIX}_#{name}") - end - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.itunes_name = args[0] - self.itunes_email = args[1] - end - end - - def full_name - tag_name_with_prefix(ITUNES_PREFIX) - end - - private - def maker_target(target) - target.itunes_owner - end - - def setup_maker_element(owner) - super(owner) - owner.itunes_name = itunes_name - owner.itunes_email = itunes_email - end - end - end - - module ITunesItemModel - extend BaseModel - extend ITunesModelUtils - include ITunesBaseModel - - class << self - def append_features(klass) - super - - return if klass.instance_of?(Module) - ELEMENT_INFOS.each do |name, type| - def_class_accessor(klass, name, type) - end - end - end - - ELEMENT_INFOS = ITunesBaseModel::ELEMENT_INFOS + - [["duration", :element, "content"]] - - class ITunesDuration < Element - include RSS09 - - @tag_name = "duration" - - class << self - def required_prefix - ITUNES_PREFIX - end - - def required_uri - ITUNES_URI - end - - def parse(duration, do_validate=true) - if do_validate and /\A(?: - \d?\d:[0-5]\d:[0-5]\d| - [0-5]?\d:[0-5]\d| - \d+ - )\z/x !~ duration - raise ArgumentError, - "must be one of HH:MM:SS, H:MM:SS, MM:SS, M:SS, S+: " + - duration.inspect - end - - if duration.include?(':') - components = duration.split(':') - components[3..-1] = nil if components.size > 3 - - components.unshift("00") until components.size == 3 - components.collect do |component| - component.to_i - end - else - seconds_to_components(duration.to_i) - end - end - - def construct(hours, minutes, seconds) - components = [minutes, seconds] - if components.include?(nil) - nil - else - components.unshift(hours) if hours and hours > 0 - components.collect do |component| - "%02d" % component - end.join(':') - end - end - - private - def seconds_to_components(total_seconds) - hours = total_seconds / (60 * 60) - minutes = (total_seconds / 60) % 60 - seconds = total_seconds % 60 - [hours, minutes, seconds] - end - end - - content_setup - alias_method(:value, :content) - remove_method(:content=) - - attr_reader :hour, :minute, :second - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - args = args[0] if args.size == 1 and args[0].is_a?(Array) - if args.size == 1 - self.content = args[0] - elsif args.size > 3 - raise ArgumentError, - "must be (do_validate, params), (content), " + - "(minute, second), ([minute, second]), " + - "(hour, minute, second) or ([hour, minute, second]): " + - args.inspect - else - @second, @minute, @hour = args.reverse - update_content - end - end - end - - def content=(value) - if value.nil? - @content = nil - elsif value.is_a?(self.class) - self.content = value.content - else - begin - @hour, @minute, @second = self.class.parse(value, @do_validate) - rescue ArgumentError - raise NotAvailableValueError.new(tag_name, value) - end - @content = value - end - end - alias_method(:value=, :content=) - - def hour=(hour) - @hour = @do_validate ? Integer(hour) : hour.to_i - update_content - hour - end - - def minute=(minute) - @minute = @do_validate ? Integer(minute) : minute.to_i - update_content - minute - end - - def second=(second) - @second = @do_validate ? Integer(second) : second.to_i - update_content - second - end - - def full_name - tag_name_with_prefix(ITUNES_PREFIX) - end - - private - def update_content - @content = self.class.construct(hour, minute, second) - end - - def maker_target(target) - if @content - target.itunes_duration {|duration| duration} - else - nil - end - end - - def setup_maker_element(duration) - super(duration) - duration.content = @content - end - end - end - - class Rss - class Channel - include ITunesChannelModel - class Item; include ITunesItemModel; end - end - end - - element_infos = - ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS - element_infos.each do |name, type| - case type - when :element, :elements, :attribute - class_name = Utils.to_class_name(name) - BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}") - else - accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}" - BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base) - end - end -end diff --git a/ruby/lib/rss/maker.rb b/ruby/lib/rss/maker.rb deleted file mode 100644 index e32de8180..000000000 --- a/ruby/lib/rss/maker.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: false -require_relative "rss" - -module RSS - ## - # - # Provides a set of builders for various RSS objects - # - # * Feeds - # * RSS 0.91 - # * RSS 1.0 - # * RSS 2.0 - # * Atom 1.0 - # - # * Elements - # * Atom::Entry - - module Maker - - # Collection of supported makers - MAKERS = {} - - class << self - # Builder for an RSS object - # Creates an object of the type passed in +args+ - # - # Executes the +block+ to populate elements of the created RSS object - def make(version, &block) - self[version].make(&block) - end - - # Returns the maker for the +version+ - def [](version) - maker_info = maker(version) - raise UnsupportedMakerVersionError.new(version) if maker_info.nil? - maker_info[:maker] - end - - # Adds a maker to the set of supported makers - def add_maker(version, normalized_version, maker) - MAKERS[version] = {:maker => maker, :version => normalized_version} - end - - # Returns collection of supported maker versions - def versions - MAKERS.keys.uniq.sort - end - - # Returns collection of supported makers - def makers - MAKERS.values.collect { |info| info[:maker] }.uniq - end - - # Returns true if the version is supported - def supported?(version) - versions.include?(version) - end - - private - # Can I remove this method? - def maker(version) - MAKERS[version] - end - end - end -end - -require_relative "maker/1.0" -require_relative "maker/2.0" -require_relative "maker/feed" -require_relative "maker/entry" -require_relative "maker/content" -require_relative "maker/dublincore" -require_relative "maker/slash" -require_relative "maker/syndication" -require_relative "maker/taxonomy" -require_relative "maker/trackback" -require_relative "maker/image" -require_relative "maker/itunes" diff --git a/ruby/lib/rss/maker/0.9.rb b/ruby/lib/rss/maker/0.9.rb deleted file mode 100644 index eb35fc14e..000000000 --- a/ruby/lib/rss/maker/0.9.rb +++ /dev/null @@ -1,509 +0,0 @@ -# frozen_string_literal: false -require_relative "../0.9" - -require_relative "base" - -module RSS - module Maker - - class RSS09 < RSSBase - - def initialize(feed_version) - super - @feed_type = "rss" - end - - private - def make_feed - Rss.new(@feed_version, @version, @encoding, @standalone) - end - - def setup_elements(rss) - setup_channel(rss) - end - - class Channel < ChannelBase - def to_feed(rss) - channel = Rss::Channel.new - setup_values(channel) - _not_set_required_variables = not_set_required_variables - if _not_set_required_variables.empty? - rss.channel = channel - set_parent(channel, rss) - setup_items(rss) - setup_image(rss) - setup_textinput(rss) - setup_other_elements(rss, channel) - rss - else - raise NotSetError.new("maker.channel", _not_set_required_variables) - end - end - - private - def setup_items(rss) - @maker.items.to_feed(rss) - end - - def setup_image(rss) - @maker.image.to_feed(rss) - end - - def setup_textinput(rss) - @maker.textinput.to_feed(rss) - end - - def variables - super + ["pubDate"] - end - - def required_variable_names - %w(link language) - end - - def not_set_required_variables - vars = super - vars << "description" unless description {|d| d.have_required_values?} - vars << "title" unless title {|t| t.have_required_values?} - vars - end - - class SkipDays < SkipDaysBase - def to_feed(rss, channel) - unless @days.empty? - skipDays = Rss::Channel::SkipDays.new - channel.skipDays = skipDays - set_parent(skipDays, channel) - @days.each do |day| - day.to_feed(rss, skipDays.days) - end - end - end - - class Day < DayBase - def to_feed(rss, days) - day = Rss::Channel::SkipDays::Day.new - set = setup_values(day) - if set - days << day - set_parent(day, days) - setup_other_elements(rss, day) - end - end - - private - def required_variable_names - %w(content) - end - end - end - - class SkipHours < SkipHoursBase - def to_feed(rss, channel) - unless @hours.empty? - skipHours = Rss::Channel::SkipHours.new - channel.skipHours = skipHours - set_parent(skipHours, channel) - @hours.each do |hour| - hour.to_feed(rss, skipHours.hours) - end - end - end - - class Hour < HourBase - def to_feed(rss, hours) - hour = Rss::Channel::SkipHours::Hour.new - set = setup_values(hour) - if set - hours << hour - set_parent(hour, hours) - setup_other_elements(rss, hour) - end - end - - private - def required_variable_names - %w(content) - end - end - end - - class Cloud < CloudBase - def to_feed(*args) - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Links < LinksBase - def to_feed(rss, channel) - return if @links.empty? - @links.first.to_feed(rss, channel) - end - - class Link < LinkBase - def to_feed(rss, channel) - if have_required_values? - channel.link = href - else - raise NotSetError.new("maker.channel.link", - not_set_required_variables) - end - end - - private - def required_variable_names - %w(href) - end - end - end - - class Authors < AuthorsBase - def to_feed(rss, channel) - end - - class Author < AuthorBase - def to_feed(rss, channel) - end - end - end - - class Contributors < ContributorsBase - def to_feed(rss, channel) - end - - class Contributor < ContributorBase - end - end - - class Generator < GeneratorBase - def to_feed(rss, channel) - end - end - - class Copyright < CopyrightBase - def to_feed(rss, channel) - channel.copyright = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - - class Description < DescriptionBase - def to_feed(rss, channel) - channel.description = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - - class Title < TitleBase - def to_feed(rss, channel) - channel.title = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - end - - class Image < ImageBase - def to_feed(rss) - image = Rss::Channel::Image.new - set = setup_values(image) - if set - image.link = link - rss.channel.image = image - set_parent(image, rss.channel) - setup_other_elements(rss, image) - elsif required_element? - raise NotSetError.new("maker.image", not_set_required_variables) - end - end - - private - def required_variable_names - %w(url title link) - end - - def required_element? - true - end - end - - class Items < ItemsBase - def to_feed(rss) - if rss.channel - normalize.each do |item| - item.to_feed(rss) - end - setup_other_elements(rss, rss.items) - end - end - - class Item < ItemBase - def to_feed(rss) - item = Rss::Channel::Item.new - setup_values(item) - _not_set_required_variables = not_set_required_variables - if _not_set_required_variables.empty? - rss.items << item - set_parent(item, rss.channel) - setup_other_elements(rss, item) - elsif variable_is_set? - raise NotSetError.new("maker.items", _not_set_required_variables) - end - end - - private - def required_variable_names - [] - end - - def not_set_required_variables - vars = super - if @maker.feed_version == "0.91" - vars << "title" unless title {|t| t.have_required_values?} - vars << "link" unless link - end - vars - end - - class Guid < GuidBase - def to_feed(*args) - end - end - - class Enclosure < EnclosureBase - def to_feed(*args) - end - end - - class Source < SourceBase - def to_feed(*args) - end - - class Authors < AuthorsBase - def to_feed(*args) - end - - class Author < AuthorBase - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Contributors < ContributorsBase - def to_feed(*args) - end - - class Contributor < ContributorBase - end - end - - class Generator < GeneratorBase - def to_feed(*args) - end - end - - class Icon < IconBase - def to_feed(*args) - end - end - - class Links < LinksBase - def to_feed(*args) - end - - class Link < LinkBase - end - end - - class Logo < LogoBase - def to_feed(*args) - end - end - - class Rights < RightsBase - def to_feed(*args) - end - end - - class Subtitle < SubtitleBase - def to_feed(*args) - end - end - - class Title < TitleBase - def to_feed(*args) - end - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Authors < AuthorsBase - def to_feed(*args) - end - - class Author < AuthorBase - end - end - - class Links < LinksBase - def to_feed(rss, item) - return if @links.empty? - @links.first.to_feed(rss, item) - end - - class Link < LinkBase - def to_feed(rss, item) - if have_required_values? - item.link = href - else - raise NotSetError.new("maker.link", - not_set_required_variables) - end - end - - private - def required_variable_names - %w(href) - end - end - end - - class Contributors < ContributorsBase - def to_feed(rss, item) - end - - class Contributor < ContributorBase - end - end - - class Rights < RightsBase - def to_feed(rss, item) - end - end - - class Description < DescriptionBase - def to_feed(rss, item) - item.description = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - - class Content < ContentBase - def to_feed(rss, item) - end - end - - class Title < TitleBase - def to_feed(rss, item) - item.title = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - end - end - - class Textinput < TextinputBase - def to_feed(rss) - textInput = Rss::Channel::TextInput.new - set = setup_values(textInput) - if set - rss.channel.textInput = textInput - set_parent(textInput, rss.channel) - setup_other_elements(rss, textInput) - end - end - - private - def required_variable_names - %w(title description name link) - end - end - end - - class RSS091 < RSS09 - def initialize(feed_version="0.91") - super - end - - class Channel < RSS09::Channel - end - - class Items < RSS09::Items - class Item < RSS09::Items::Item - end - end - - class Image < RSS09::Image - end - - class Textinput < RSS09::Textinput - end - end - - class RSS092 < RSS09 - def initialize(feed_version="0.92") - super - end - - class Channel < RSS09::Channel - end - - class Items < RSS09::Items - class Item < RSS09::Items::Item - end - end - - class Image < RSS09::Image - end - - class Textinput < RSS09::Textinput - end - end - - add_maker("0.9", "0.92", RSS092) - add_maker("0.91", "0.91", RSS091) - add_maker("0.92", "0.92", RSS092) - add_maker("rss0.9", "0.92", RSS092) - add_maker("rss0.91", "0.91", RSS091) - add_maker("rss0.92", "0.92", RSS092) - end -end diff --git a/ruby/lib/rss/maker/1.0.rb b/ruby/lib/rss/maker/1.0.rb deleted file mode 100644 index 3934f9536..000000000 --- a/ruby/lib/rss/maker/1.0.rb +++ /dev/null @@ -1,436 +0,0 @@ -# frozen_string_literal: false -require_relative "../1.0" - -require_relative "base" - -module RSS - module Maker - - class RSS10 < RSSBase - - def initialize(feed_version="1.0") - super - @feed_type = "rss" - end - - private - def make_feed - RDF.new(@version, @encoding, @standalone) - end - - def setup_elements(rss) - setup_channel(rss) - setup_image(rss) - setup_items(rss) - setup_textinput(rss) - end - - class Channel < ChannelBase - include SetupDefaultLanguage - - def to_feed(rss) - set_default_values do - _not_set_required_variables = not_set_required_variables - if _not_set_required_variables.empty? - channel = RDF::Channel.new(@about) - setup_values(channel) - channel.dc_dates.clear - rss.channel = channel - set_parent(channel, rss) - setup_items(rss) - setup_image(rss) - setup_textinput(rss) - setup_other_elements(rss, channel) - else - raise NotSetError.new("maker.channel", _not_set_required_variables) - end - end - end - - private - def setup_items(rss) - items = RDF::Channel::Items.new - seq = items.Seq - set_parent(items, seq) - target_items = @maker.items.normalize - raise NotSetError.new("maker", ["items"]) if target_items.empty? - target_items.each do |item| - li = RDF::Channel::Items::Seq::Li.new(item.link) - seq.lis << li - set_parent(li, seq) - end - rss.channel.items = items - set_parent(rss.channel, items) - end - - def setup_image(rss) - if @maker.image.have_required_values? - image = RDF::Channel::Image.new(@maker.image.url) - rss.channel.image = image - set_parent(image, rss.channel) - end - end - - def setup_textinput(rss) - if @maker.textinput.have_required_values? - textinput = RDF::Channel::Textinput.new(@maker.textinput.link) - rss.channel.textinput = textinput - set_parent(textinput, rss.channel) - end - end - - def required_variable_names - %w(about link) - end - - def not_set_required_variables - vars = super - vars << "description" unless description {|d| d.have_required_values?} - vars << "title" unless title {|t| t.have_required_values?} - vars - end - - class SkipDays < SkipDaysBase - def to_feed(*args) - end - - class Day < DayBase - end - end - - class SkipHours < SkipHoursBase - def to_feed(*args) - end - - class Hour < HourBase - end - end - - class Cloud < CloudBase - def to_feed(*args) - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Links < LinksBase - def to_feed(rss, channel) - return if @links.empty? - @links.first.to_feed(rss, channel) - end - - class Link < LinkBase - def to_feed(rss, channel) - if have_required_values? - channel.link = href - else - raise NotSetError.new("maker.channel.link", - not_set_required_variables) - end - end - - private - def required_variable_names - %w(href) - end - end - end - - class Authors < AuthorsBase - def to_feed(rss, channel) - end - - class Author < AuthorBase - def to_feed(rss, channel) - end - end - end - - class Contributors < ContributorsBase - def to_feed(rss, channel) - end - - class Contributor < ContributorBase - end - end - - class Generator < GeneratorBase - def to_feed(rss, channel) - end - end - - class Copyright < CopyrightBase - def to_feed(rss, channel) - end - end - - class Description < DescriptionBase - def to_feed(rss, channel) - channel.description = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - - class Title < TitleBase - def to_feed(rss, channel) - channel.title = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - end - - class Image < ImageBase - def to_feed(rss) - if @url - image = RDF::Image.new(@url) - set = setup_values(image) - if set - rss.image = image - set_parent(image, rss) - setup_other_elements(rss, image) - end - end - end - - def have_required_values? - super and @maker.channel.have_required_values? - end - - private - def variables - super + ["link"] - end - - def required_variable_names - %w(url title link) - end - end - - class Items < ItemsBase - def to_feed(rss) - if rss.channel - normalize.each do |item| - item.to_feed(rss) - end - setup_other_elements(rss, rss.items) - end - end - - class Item < ItemBase - def to_feed(rss) - set_default_values do - item = RDF::Item.new(link) - set = setup_values(item) - if set - item.dc_dates.clear - rss.items << item - set_parent(item, rss) - setup_other_elements(rss, item) - elsif !have_required_values? - raise NotSetError.new("maker.item", not_set_required_variables) - end - end - end - - private - def required_variable_names - %w(link) - end - - def variables - super + %w(link) - end - - def not_set_required_variables - set_default_values do - vars = super - vars << "title" unless title {|t| t.have_required_values?} - vars - end - end - - class Guid < GuidBase - def to_feed(*args) - end - end - - class Enclosure < EnclosureBase - def to_feed(*args) - end - end - - class Source < SourceBase - def to_feed(*args) - end - - class Authors < AuthorsBase - def to_feed(*args) - end - - class Author < AuthorBase - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Contributors < ContributorsBase - def to_feed(*args) - end - - class Contributor < ContributorBase - end - end - - class Generator < GeneratorBase - def to_feed(*args) - end - end - - class Icon < IconBase - def to_feed(*args) - end - end - - class Links < LinksBase - def to_feed(*args) - end - - class Link < LinkBase - end - end - - class Logo < LogoBase - def to_feed(*args) - end - end - - class Rights < RightsBase - def to_feed(*args) - end - end - - class Subtitle < SubtitleBase - def to_feed(*args) - end - end - - class Title < TitleBase - def to_feed(*args) - end - end - end - - class Categories < CategoriesBase - def to_feed(*args) - end - - class Category < CategoryBase - end - end - - class Authors < AuthorsBase - def to_feed(*args) - end - - class Author < AuthorBase - end - end - - class Links < LinksBase - def to_feed(*args) - end - - class Link < LinkBase - end - end - - class Contributors < ContributorsBase - def to_feed(rss, item) - end - - class Contributor < ContributorBase - end - end - - class Rights < RightsBase - def to_feed(rss, item) - end - end - - class Description < DescriptionBase - def to_feed(rss, item) - item.description = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - - class Content < ContentBase - def to_feed(rss, item) - end - end - - class Title < TitleBase - def to_feed(rss, item) - item.title = content if have_required_values? - end - - private - def required_variable_names - %w(content) - end - end - end - end - - class Textinput < TextinputBase - def to_feed(rss) - if @link - textinput = RDF::Textinput.new(@link) - set = setup_values(textinput) - if set - rss.textinput = textinput - set_parent(textinput, rss) - setup_other_elements(rss, textinput) - end - end - end - - def have_required_values? - super and @maker.channel.have_required_values? - end - - private - def required_variable_names - %w(title description name link) - end - end - end - - add_maker("1.0", "1.0", RSS10) - add_maker("rss1.0", "1.0", RSS10) - end -end diff --git a/ruby/lib/rss/maker/2.0.rb b/ruby/lib/rss/maker/2.0.rb deleted file mode 100644 index 43d00226b..000000000 --- a/ruby/lib/rss/maker/2.0.rb +++ /dev/null @@ -1,224 +0,0 @@ -# frozen_string_literal: false -require_relative "../2.0" - -require_relative "0.9" - -module RSS - module Maker - - class RSS20 < RSS09 - - def initialize(feed_version="2.0") - super - end - - class Channel < RSS09::Channel - - private - def required_variable_names - %w(link) - end - - class SkipDays < RSS09::Channel::SkipDays - class Day < RSS09::Channel::SkipDays::Day - end - end - - class SkipHours < RSS09::Channel::SkipHours - class Hour < RSS09::Channel::SkipHours::Hour - end - end - - class Cloud < RSS09::Channel::Cloud - def to_feed(rss, channel) - cloud = Rss::Channel::Cloud.new - set = setup_values(cloud) - if set - channel.cloud = cloud - set_parent(cloud, channel) - setup_other_elements(rss, cloud) - end - end - - private - def required_variable_names - %w(domain port path registerProcedure protocol) - end - end - - class Categories < RSS09::Channel::Categories - def to_feed(rss, channel) - @categories.each do |category| - category.to_feed(rss, channel) - end - end - - class Category < RSS09::Channel::Categories::Category - def to_feed(rss, channel) - category = Rss::Channel::Category.new - set = setup_values(category) - if set - channel.categories << category - set_parent(category, channel) - setup_other_elements(rss, category) - end - end - - private - def required_variable_names - %w(content) - end - end - end - - class Generator < GeneratorBase - def to_feed(rss, channel) - channel.generator = content - end - - private - def required_variable_names - %w(content) - end - end - end - - class Image < RSS09::Image - private - def required_element? - false - end - end - - class Items < RSS09::Items - class Item < RSS09::Items::Item - private - def required_variable_names - [] - end - - def not_set_required_variables - vars = super - if !title {|t| t.have_required_values?} and - !description {|d| d.have_required_values?} - vars << "title or description" - end - vars - end - - def variables - super + ["pubDate"] - end - - class Guid < RSS09::Items::Item::Guid - def to_feed(rss, item) - guid = Rss::Channel::Item::Guid.new - set = setup_values(guid) - if set - item.guid = guid - set_parent(guid, item) - setup_other_elements(rss, guid) - end - end - - private - def required_variable_names - %w(content) - end - end - - class Enclosure < RSS09::Items::Item::Enclosure - def to_feed(rss, item) - enclosure = Rss::Channel::Item::Enclosure.new - set = setup_values(enclosure) - if set - item.enclosure = enclosure - set_parent(enclosure, item) - setup_other_elements(rss, enclosure) - end - end - - private - def required_variable_names - %w(url length type) - end - end - - class Source < RSS09::Items::Item::Source - def to_feed(rss, item) - source = Rss::Channel::Item::Source.new - set = setup_values(source) - if set - item.source = source - set_parent(source, item) - setup_other_elements(rss, source) - end - end - - private - def required_variable_names - %w(url content) - end - - class Links < RSS09::Items::Item::Source::Links - def to_feed(rss, source) - return if @links.empty? - @links.first.to_feed(rss, source) - end - - class Link < RSS09::Items::Item::Source::Links::Link - def to_feed(rss, source) - source.url = href - end - end - end - end - - class Categories < RSS09::Items::Item::Categories - def to_feed(rss, item) - @categories.each do |category| - category.to_feed(rss, item) - end - end - - class Category < RSS09::Items::Item::Categories::Category - def to_feed(rss, item) - category = Rss::Channel::Item::Category.new - set = setup_values(category) - if set - item.categories << category - set_parent(category, item) - setup_other_elements(rss) - end - end - - private - def required_variable_names - %w(content) - end - end - end - - class Authors < RSS09::Items::Item::Authors - def to_feed(rss, item) - return if @authors.empty? - @authors.first.to_feed(rss, item) - end - - class Author < RSS09::Items::Item::Authors::Author - def to_feed(rss, item) - item.author = name - end - end - end - end - end - - class Textinput < RSS09::Textinput - end - end - - add_maker("2.0", "2.0", RSS20) - add_maker("rss2.0", "2.0", RSS20) - end -end diff --git a/ruby/lib/rss/maker/atom.rb b/ruby/lib/rss/maker/atom.rb deleted file mode 100644 index cdd1d8753..000000000 --- a/ruby/lib/rss/maker/atom.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: false -require_relative "../atom" - -require_relative "base" - -module RSS - module Maker - module AtomPersons - module_function - def def_atom_persons(klass, name, maker_name, plural=nil) - plural ||= "#{name}s" - klass_name = Utils.to_class_name(name) - plural_klass_name = Utils.to_class_name(plural) - - klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) - class #{plural_klass_name} < #{plural_klass_name}Base - class #{klass_name} < #{klass_name}Base - def to_feed(feed, current) - #{name} = feed.class::#{klass_name}.new - set = setup_values(#{name}) - unless set - raise NotSetError.new(#{maker_name.dump}, - not_set_required_variables) - end - current.#{plural} << #{name} - set_parent(#{name}, current) - setup_other_elements(#{name}) - end - - private - def required_variable_names - %w(name) - end - end - end -EOC - end - end - - module AtomTextConstruct - class << self - def def_atom_text_construct(klass, name, maker_name, klass_name=nil, - atom_klass_name=nil) - klass_name ||= Utils.to_class_name(name) - atom_klass_name ||= Utils.to_class_name(name) - - klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) - class #{klass_name} < #{klass_name}Base - include #{self.name} - def to_feed(feed, current) - #{name} = current.class::#{atom_klass_name}.new - if setup_values(#{name}) - current.#{name} = #{name} - set_parent(#{name}, current) - setup_other_elements(feed) - elsif variable_is_set? - raise NotSetError.new(#{maker_name.dump}, - not_set_required_variables) - end - end - end - EOC - end - end - - private - def required_variable_names - if type == "xhtml" - %w(xml_content) - else - %w(content) - end - end - - def variables - if type == "xhtml" - super + %w(xhtml) - else - super - end - end - end - - module AtomCategory - def to_feed(feed, current) - category = feed.class::Category.new - set = setup_values(category) - if set - current.categories << category - set_parent(category, current) - setup_other_elements(feed) - else - raise NotSetError.new(self.class.not_set_name, - not_set_required_variables) - end - end - - private - def required_variable_names - %w(term) - end - - def variables - super + ["term", "scheme"] - end - end - - module AtomLink - def to_feed(feed, current) - link = feed.class::Link.new - set = setup_values(link) - if set - current.links << link - set_parent(link, current) - setup_other_elements(feed) - else - raise NotSetError.new(self.class.not_set_name, - not_set_required_variables) - end - end - - private - def required_variable_names - %w(href) - end - end - - module AtomGenerator - def to_feed(feed, current) - generator = current.class::Generator.new - if setup_values(generator) - current.generator = generator - set_parent(generator, current) - setup_other_elements(feed) - elsif variable_is_set? - raise NotSetError.new(self.class.not_set_name, - not_set_required_variables) - end - end - - private - def required_variable_names - %w(content) - end - end - - module AtomLogo - def to_feed(feed, current) - logo = current.class::Logo.new - class << logo - alias_method(:uri=, :content=) - end - set = setup_values(logo) - class << logo - remove_method(:uri=) - end - if set - current.logo = logo - set_parent(logo, current) - setup_other_elements(feed) - elsif variable_is_set? - raise NotSetError.new(self.class.not_set_name, - not_set_required_variables) - end - end - - private - def required_variable_names - %w(uri) - end - end - end -end diff --git a/ruby/lib/rss/maker/base.rb b/ruby/lib/rss/maker/base.rb deleted file mode 100644 index 17537b700..000000000 --- a/ruby/lib/rss/maker/base.rb +++ /dev/null @@ -1,945 +0,0 @@ -# frozen_string_literal: false -require 'forwardable' - -require_relative '../rss' - -module RSS - module Maker - class Base - extend Utils::InheritedReader - - OTHER_ELEMENTS = [] - NEED_INITIALIZE_VARIABLES = [] - - class << self - def other_elements - inherited_array_reader("OTHER_ELEMENTS") - end - def need_initialize_variables - inherited_array_reader("NEED_INITIALIZE_VARIABLES") - end - - def inherited_base - ::RSS::Maker::Base - end - - def inherited(subclass) - subclass.const_set(:OTHER_ELEMENTS, []) - subclass.const_set(:NEED_INITIALIZE_VARIABLES, []) - end - - def add_other_element(variable_name) - self::OTHER_ELEMENTS << variable_name - end - - def add_need_initialize_variable(variable_name, init_value=nil, - &init_block) - init_value ||= init_block - self::NEED_INITIALIZE_VARIABLES << [variable_name, init_value] - end - - def def_array_element(name, plural=nil, klass_name=nil) - include Enumerable - extend Forwardable - - plural ||= "#{name}s" - klass_name ||= Utils.to_class_name(name) - def_delegators("@#{plural}", :<<, :[], :[]=, :first, :last) - def_delegators("@#{plural}", :push, :pop, :shift, :unshift) - def_delegators("@#{plural}", :each, :size, :empty?, :clear) - - add_need_initialize_variable(plural) {[]} - - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def new_#{name} - #{name} = self.class::#{klass_name}.new(@maker) - @#{plural} << #{name} - if block_given? - yield #{name} - else - #{name} - end - end - alias new_child new_#{name} - - def to_feed(*args) - @#{plural}.each do |#{name}| - #{name}.to_feed(*args) - end - end - - def replace(elements) - @#{plural}.replace(elements.to_a) - end - EOC - end - - def def_classed_element_without_accessor(name, class_name=nil) - class_name ||= Utils.to_class_name(name) - add_other_element(name) - add_need_initialize_variable(name) do |object| - object.send("make_#{name}") - end - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - private - def setup_#{name}(feed, current) - @#{name}.to_feed(feed, current) - end - - def make_#{name} - self.class::#{class_name}.new(@maker) - end - EOC - end - - def def_classed_element(name, class_name=nil, attribute_name=nil) - def_classed_element_without_accessor(name, class_name) - if attribute_name - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name} - if block_given? - yield(@#{name}) - else - @#{name}.#{attribute_name} - end - end - - def #{name}=(new_value) - @#{name}.#{attribute_name} = new_value - end - EOC - else - attr_reader name - end - end - - def def_classed_elements(name, attribute, plural_class_name=nil, - plural_name=nil, new_name=nil) - plural_name ||= "#{name}s" - new_name ||= name - def_classed_element(plural_name, plural_class_name) - local_variable_name = "_#{name}" - new_value_variable_name = "new_value" - additional_setup_code = nil - if block_given? - additional_setup_code = yield(local_variable_name, - new_value_variable_name) - end - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name} - #{local_variable_name} = #{plural_name}.first - #{local_variable_name} ? #{local_variable_name}.#{attribute} : nil - end - - def #{name}=(#{new_value_variable_name}) - #{local_variable_name} = - #{plural_name}.first || #{plural_name}.new_#{new_name} - #{additional_setup_code} - #{local_variable_name}.#{attribute} = #{new_value_variable_name} - end - EOC - end - - def def_other_element(name) - attr_accessor name - def_other_element_without_accessor(name) - end - - def def_other_element_without_accessor(name) - add_need_initialize_variable(name) - add_other_element(name) - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def setup_#{name}(feed, current) - if !@#{name}.nil? and current.respond_to?(:#{name}=) - current.#{name} = @#{name} - end - end - EOC - end - - def def_csv_element(name, type=nil) - def_other_element_without_accessor(name) - attr_reader(name) - converter = "" - if type == :integer - converter = "{|v| Integer(v)}" - end - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name}=(value) - @#{name} = Utils::CSV.parse(value)#{converter} - end - EOC - end - end - - attr_reader :maker - def initialize(maker) - @maker = maker - @default_values_are_set = false - initialize_variables - end - - def have_required_values? - not_set_required_variables.empty? - end - - def variable_is_set? - variables.any? {|var| not __send__(var).nil?} - end - - private - def initialize_variables - self.class.need_initialize_variables.each do |variable_name, init_value| - if init_value.nil? - value = nil - else - if init_value.respond_to?(:call) - value = init_value.call(self) - elsif init_value.is_a?(String) - # just for backward compatibility - value = instance_eval(init_value, __FILE__, __LINE__) - else - value = init_value - end - end - instance_variable_set("@#{variable_name}", value) - end - end - - def setup_other_elements(feed, current=nil) - current ||= current_element(feed) - self.class.other_elements.each do |element| - __send__("setup_#{element}", feed, current) - end - end - - def current_element(feed) - feed - end - - def set_default_values(&block) - return yield if @default_values_are_set - - begin - @default_values_are_set = true - _set_default_values(&block) - ensure - @default_values_are_set = false - end - end - - def _set_default_values(&block) - yield - end - - def setup_values(target) - set = false - if have_required_values? - variables.each do |var| - setter = "#{var}=" - if target.respond_to?(setter) - value = __send__(var) - unless value.nil? - target.__send__(setter, value) - set = true - end - end - end - end - set - end - - def set_parent(target, parent) - target.parent = parent if target.class.need_parent? - end - - def variables - self.class.need_initialize_variables.find_all do |name, init| - # init == "nil" is just for backward compatibility - init.nil? or init == "nil" - end.collect do |name, init| - name - end - end - - def not_set_required_variables - required_variable_names.find_all do |var| - __send__(var).nil? - end - end - - def required_variables_are_set? - required_variable_names.each do |var| - return false if __send__(var).nil? - end - true - end - end - - module AtomPersonConstructBase - def self.append_features(klass) - super - - klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1) - %w(name uri email).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - EOC - end - end - - module AtomTextConstructBase - module EnsureXMLContent - class << self - def included(base) - super - base.class_eval do - %w(type content xml_content).each do |element| - attr_reader element - attr_writer element if element != "xml_content" - add_need_initialize_variable(element) - end - - alias_method(:xhtml, :xml_content) - end - end - end - - def ensure_xml_content(content) - xhtml_uri = ::RSS::Atom::XHTML_URI - unless content.is_a?(RSS::XML::Element) and - ["div", xhtml_uri] == [content.name, content.uri] - children = content - children = [children] unless content.is_a?(Array) - children = set_xhtml_uri_as_default_uri(children) - content = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - children) - end - content - end - - def xml_content=(content) - @xml_content = ensure_xml_content(content) - end - - def xhtml=(content) - self.xml_content = content - end - - private - def set_xhtml_uri_as_default_uri(children) - children.collect do |child| - if child.is_a?(RSS::XML::Element) and - child.prefix.nil? and child.uri.nil? - RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI, - child.attributes.dup, - set_xhtml_uri_as_default_uri(child.children)) - else - child - end - end - end - end - - def self.append_features(klass) - super - - klass.class_eval do - include EnsureXMLContent - end - end - end - - module SetupDefaultDate - private - def _set_default_values - keep = { - :date => date, - :dc_dates => dc_dates.to_a.dup, - } - _date = _parse_date_if_needed(date) - if _date and !dc_dates.any? {|dc_date| dc_date.value == _date} - dc_date = self.class::DublinCoreDates::DublinCoreDate.new(self) - dc_date.value = _date.dup - dc_dates.unshift(dc_date) - end - self.date ||= self.dc_date - super - ensure - self.date = keep[:date] - dc_dates.replace(keep[:dc_dates]) - end - - def _parse_date_if_needed(date_value) - date_value = Time.parse(date_value) if date_value.is_a?(String) - date_value - end - end - - module SetupDefaultLanguage - private - def _set_default_values - keep = { - :dc_languages => dc_languages.to_a.dup, - } - _language = language - if _language and - !dc_languages.any? {|dc_language| dc_language.value == _language} - dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self) - dc_language.value = _language.dup - dc_languages.unshift(dc_language) - end - super - ensure - dc_languages.replace(keep[:dc_languages]) - end - end - - class RSSBase < Base - class << self - def make(*args, &block) - new(*args).make(&block) - end - end - - %w(xml_stylesheets channel image items textinput).each do |element| - attr_reader element - add_need_initialize_variable(element) do |object| - object.send("make_#{element}") - end - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - private - def setup_#{element}(feed) - @#{element}.to_feed(feed) - end - - def make_#{element} - self.class::#{Utils.to_class_name(element)}.new(self) - end - EOC - end - - attr_reader :feed_version - alias_method(:rss_version, :feed_version) - attr_accessor :version, :encoding, :standalone - - def initialize(feed_version) - super(self) - @feed_type = nil - @feed_subtype = nil - @feed_version = feed_version - @version = "1.0" - @encoding = "UTF-8" - @standalone = nil - end - - def make - yield(self) - to_feed - end - - def to_feed - feed = make_feed - setup_xml_stylesheets(feed) - setup_elements(feed) - setup_other_elements(feed) - feed.validate - feed - end - - private - remove_method :make_xml_stylesheets - def make_xml_stylesheets - XMLStyleSheets.new(self) - end - end - - class XMLStyleSheets < Base - def_array_element("xml_stylesheet", nil, "XMLStyleSheet") - - class XMLStyleSheet < Base - - ::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute| - attr_accessor attribute - add_need_initialize_variable(attribute) - end - - def to_feed(feed) - xss = ::RSS::XMLStyleSheet.new - guess_type_if_need(xss) - set = setup_values(xss) - if set - feed.xml_stylesheets << xss - end - end - - private - def guess_type_if_need(xss) - if @type.nil? - xss.href = @href - @type = xss.type - end - end - - def required_variable_names - %w(href type) - end - end - end - - class ChannelBase < Base - include SetupDefaultDate - - %w(cloud categories skipDays skipHours).each do |name| - def_classed_element(name) - end - - %w(generator copyright description title).each do |name| - def_classed_element(name, nil, "content") - end - - [ - ["link", "href", Proc.new {|target,| "#{target}.href = 'self'"}], - ["author", "name"], - ["contributor", "name"], - ].each do |name, attribute, additional_setup_maker| - def_classed_elements(name, attribute, &additional_setup_maker) - end - - %w(id about language - managingEditor webMaster rating docs ttl).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - %w(date lastBuildDate).each do |date_element| - attr_reader date_element - add_need_initialize_variable(date_element) - end - - def date=(_date) - @date = _parse_date_if_needed(_date) - end - - def lastBuildDate=(_date) - @lastBuildDate = _parse_date_if_needed(_date) - end - - def pubDate - date - end - - def pubDate=(date) - self.date = date - end - - def updated - date - end - - def updated=(date) - self.date = date - end - - alias_method(:rights, :copyright) - alias_method(:rights=, :copyright=) - - alias_method(:subtitle, :description) - alias_method(:subtitle=, :description=) - - def icon - image_favicon.about - end - - def icon=(url) - image_favicon.about = url - end - - def logo - maker.image.url - end - - def logo=(url) - maker.image.url = url - end - - class SkipDaysBase < Base - def_array_element("day") - - class DayBase < Base - %w(content).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - end - - class SkipHoursBase < Base - def_array_element("hour") - - class HourBase < Base - %w(content).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - end - - class CloudBase < Base - %w(domain port path registerProcedure protocol).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - - class CategoriesBase < Base - def_array_element("category", "categories") - - class CategoryBase < Base - %w(domain content label).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - alias_method(:term, :domain) - alias_method(:term=, :domain=) - alias_method(:scheme, :content) - alias_method(:scheme=, :content=) - end - end - - class LinksBase < Base - def_array_element("link") - - class LinkBase < Base - %w(href rel type hreflang title length).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - end - - class AuthorsBase < Base - def_array_element("author") - - class AuthorBase < Base - include AtomPersonConstructBase - end - end - - class ContributorsBase < Base - def_array_element("contributor") - - class ContributorBase < Base - include AtomPersonConstructBase - end - end - - class GeneratorBase < Base - %w(uri version content).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - - class CopyrightBase < Base - include AtomTextConstructBase - end - - class DescriptionBase < Base - include AtomTextConstructBase - end - - class TitleBase < Base - include AtomTextConstructBase - end - end - - class ImageBase < Base - %w(title url width height description).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - def link - @maker.channel.link - end - end - - class ItemsBase < Base - def_array_element("item") - - attr_accessor :do_sort, :max_size - - def initialize(maker) - super - @do_sort = false - @max_size = -1 - end - - def normalize - if @max_size >= 0 - sort_if_need[0...@max_size] - else - sort_if_need[0..@max_size] - end - end - - private - def sort_if_need - if @do_sort.respond_to?(:call) - @items.sort do |x, y| - @do_sort.call(x, y) - end - elsif @do_sort - @items.sort do |x, y| - y <=> x - end - else - @items - end - end - - class ItemBase < Base - include SetupDefaultDate - - %w(guid enclosure source categories content).each do |name| - def_classed_element(name) - end - - %w(rights description title).each do |name| - def_classed_element(name, nil, "content") - end - - [ - ["author", "name"], - ["link", "href", Proc.new {|target,| "#{target}.href = 'alternate'"}], - ["contributor", "name"], - ].each do |name, attribute| - def_classed_elements(name, attribute) - end - - %w(comments id published).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - %w(date).each do |date_element| - attr_reader date_element - add_need_initialize_variable(date_element) - end - - def date=(_date) - @date = _parse_date_if_needed(_date) - end - - def pubDate - date - end - - def pubDate=(date) - self.date = date - end - - def updated - date - end - - def updated=(date) - self.date = date - end - - alias_method(:summary, :description) - alias_method(:summary=, :description=) - - def <=>(other) - _date = date || dc_date - _other_date = other.date || other.dc_date - if _date and _other_date - _date <=> _other_date - elsif _date - 1 - elsif _other_date - -1 - else - 0 - end - end - - class GuidBase < Base - %w(isPermaLink content).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - def permanent_link? - isPermaLink - end - - def permanent_link=(bool) - self.isPermaLink = bool - end - end - - class EnclosureBase < Base - %w(url length type).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - - class SourceBase < Base - include SetupDefaultDate - - %w(authors categories contributors generator icon - logo rights subtitle title).each do |name| - def_classed_element(name) - end - - [ - ["link", "href"], - ].each do |name, attribute| - def_classed_elements(name, attribute) - end - - %w(id content).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - - alias_method(:url, :link) - alias_method(:url=, :link=) - - %w(date).each do |date_element| - attr_reader date_element - add_need_initialize_variable(date_element) - end - - def date=(_date) - @date = _parse_date_if_needed(_date) - end - - def updated - date - end - - def updated=(date) - self.date = date - end - - private - AuthorsBase = ChannelBase::AuthorsBase - CategoriesBase = ChannelBase::CategoriesBase - ContributorsBase = ChannelBase::ContributorsBase - GeneratorBase = ChannelBase::GeneratorBase - - class IconBase < Base - %w(url).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - - LinksBase = ChannelBase::LinksBase - - class LogoBase < Base - %w(uri).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - - class RightsBase < Base - include AtomTextConstructBase - end - - class SubtitleBase < Base - include AtomTextConstructBase - end - - class TitleBase < Base - include AtomTextConstructBase - end - end - - CategoriesBase = ChannelBase::CategoriesBase - AuthorsBase = ChannelBase::AuthorsBase - LinksBase = ChannelBase::LinksBase - ContributorsBase = ChannelBase::ContributorsBase - - class RightsBase < Base - include AtomTextConstructBase - end - - class DescriptionBase < Base - include AtomTextConstructBase - end - - class ContentBase < Base - include AtomTextConstructBase::EnsureXMLContent - - %w(src).each do |element| - attr_accessor(element) - add_need_initialize_variable(element) - end - - def xml_content=(content) - content = ensure_xml_content(content) if inline_xhtml? - @xml_content = content - end - - alias_method(:xml, :xml_content) - alias_method(:xml=, :xml_content=) - - def inline_text? - [nil, "text", "html"].include?(@type) - end - - def inline_html? - @type == "html" - end - - def inline_xhtml? - @type == "xhtml" - end - - def inline_other? - !out_of_line? and ![nil, "text", "html", "xhtml"].include?(@type) - end - - def inline_other_text? - return false if @type.nil? or out_of_line? - /\Atext\//i.match(@type) ? true : false - end - - def inline_other_xml? - return false if @type.nil? or out_of_line? - /[\+\/]xml\z/i.match(@type) ? true : false - end - - def inline_other_base64? - return false if @type.nil? or out_of_line? - @type.include?("/") and !inline_other_text? and !inline_other_xml? - end - - def out_of_line? - not @src.nil? and @content.nil? - end - end - - class TitleBase < Base - include AtomTextConstructBase - end - end - end - - class TextinputBase < Base - %w(title description name link).each do |element| - attr_accessor element - add_need_initialize_variable(element) - end - end - end -end diff --git a/ruby/lib/rss/maker/content.rb b/ruby/lib/rss/maker/content.rb deleted file mode 100644 index b3f4e5036..000000000 --- a/ruby/lib/rss/maker/content.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: false -require_relative '../content' -require_relative '1.0' -require_relative '2.0' - -module RSS - module Maker - module ContentModel - def self.append_features(klass) - super - - ::RSS::ContentModel::ELEMENTS.each do |name| - klass.def_other_element(name) - end - end - end - - class ItemsBase - class ItemBase; include ContentModel; end - end - end -end diff --git a/ruby/lib/rss/maker/dublincore.rb b/ruby/lib/rss/maker/dublincore.rb deleted file mode 100644 index beea3134b..000000000 --- a/ruby/lib/rss/maker/dublincore.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: false -require_relative '../dublincore' -require_relative '1.0' - -module RSS - module Maker - module DublinCoreModel - def self.append_features(klass) - super - - ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| - plural_name ||= "#{name}s" - full_name = "#{RSS::DC_PREFIX}_#{name}" - full_plural_name = "#{RSS::DC_PREFIX}_#{plural_name}" - plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" - klass.def_classed_elements(full_name, "value", plural_klass_name, - full_plural_name, name) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def new_#{full_name}(value=nil) - _#{full_name} = #{full_plural_name}.new_#{name} - _#{full_name}.value = value - if block_given? - yield _#{full_name} - else - _#{full_name} - end - end - EOC - end - - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - # For backward compatibility - alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list - EOC - end - - ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| - plural_name ||= "#{name}s" - full_name ||= "#{DC_PREFIX}_#{name}" - full_plural_name ||= "#{DC_PREFIX}_#{plural_name}" - klass_name = Utils.to_class_name(name) - full_klass_name = "DublinCore#{klass_name}" - plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class #{plural_klass_name}Base < Base - def_array_element(#{name.dump}, #{full_plural_name.dump}, - #{full_klass_name.dump}) - - class #{full_klass_name}Base < Base - attr_accessor :value - add_need_initialize_variable("value") - alias_method(:content, :value) - alias_method(:content=, :value=) - - def have_required_values? - @value - end - - def to_feed(feed, current) - if value and current.respond_to?(:#{full_name}) - new_item = current.class::#{full_klass_name}.new(value) - current.#{full_plural_name} << new_item - end - end - end - #{klass_name}Base = #{full_klass_name}Base - end - EOC - end - - def self.install_dublin_core(klass) - ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| - plural_name ||= "#{name}s" - klass_name = Utils.to_class_name(name) - full_klass_name = "DublinCore#{klass_name}" - plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class #{plural_klass_name} < #{plural_klass_name}Base - class #{full_klass_name} < #{full_klass_name}Base - end - #{klass_name} = #{full_klass_name} - end -EOC - end - end - end - - class ChannelBase - include DublinCoreModel - end - - class ImageBase; include DublinCoreModel; end - class ItemsBase - class ItemBase - include DublinCoreModel - end - end - class TextinputBase; include DublinCoreModel; end - - makers.each do |maker| - maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class Channel - DublinCoreModel.install_dublin_core(self) - end - - class Image - DublinCoreModel.install_dublin_core(self) - end - - class Items - class Item - DublinCoreModel.install_dublin_core(self) - end - end - - class Textinput - DublinCoreModel.install_dublin_core(self) - end - EOC - end - end -end diff --git a/ruby/lib/rss/maker/entry.rb b/ruby/lib/rss/maker/entry.rb deleted file mode 100644 index ccdf9608a..000000000 --- a/ruby/lib/rss/maker/entry.rb +++ /dev/null @@ -1,164 +0,0 @@ -# frozen_string_literal: false -require_relative "atom" -require_relative "feed" - -module RSS - module Maker - module Atom - class Entry < RSSBase - def initialize(feed_version="1.0") - super - @feed_type = "atom" - @feed_subtype = "entry" - end - - private - def make_feed - ::RSS::Atom::Entry.new(@version, @encoding, @standalone) - end - - def setup_elements(entry) - setup_items(entry) - end - - class Channel < ChannelBase - class SkipDays < SkipDaysBase - class Day < DayBase - end - end - - class SkipHours < SkipHoursBase - class Hour < HourBase - end - end - - class Cloud < CloudBase - end - - Categories = Feed::Channel::Categories - Links = Feed::Channel::Links - Authors = Feed::Channel::Authors - Contributors = Feed::Channel::Contributors - - class Generator < GeneratorBase - include AtomGenerator - - def self.not_set_name - "maker.channel.generator" - end - end - - Copyright = Feed::Channel::Copyright - - class Description < DescriptionBase - end - - Title = Feed::Channel::Title - end - - class Image < ImageBase - end - - class Items < ItemsBase - def to_feed(entry) - (normalize.first || Item.new(@maker)).to_feed(entry) - end - - class Item < ItemBase - def to_feed(entry) - set_default_values do - setup_values(entry) - entry.dc_dates.clear - setup_other_elements(entry) - unless have_required_values? - raise NotSetError.new("maker.item", not_set_required_variables) - end - end - end - - private - def required_variable_names - %w(id updated) - end - - def variables - super + ["updated"] - end - - def variable_is_set? - super or !authors.empty? - end - - def not_set_required_variables - set_default_values do - vars = super - if authors.all? {|author| !author.have_required_values?} - vars << "author" - end - vars << "title" unless title {|t| t.have_required_values?} - vars - end - end - - def _set_default_values - keep = { - :authors => authors.to_a.dup, - :contributors => contributors.to_a.dup, - :categories => categories.to_a.dup, - :id => id, - :links => links.to_a.dup, - :rights => @rights, - :title => @title, - :updated => updated, - } - authors.replace(@maker.channel.authors) if keep[:authors].empty? - if keep[:contributors].empty? - contributors.replace(@maker.channel.contributors) - end - if keep[:categories].empty? - categories.replace(@maker.channel.categories) - end - self.id ||= link || @maker.channel.id - links.replace(@maker.channel.links) if keep[:links].empty? - unless keep[:rights].variable_is_set? - @maker.channel.rights {|r| @rights = r} - end - unless keep[:title].variable_is_set? - @maker.channel.title {|t| @title = t} - end - self.updated ||= @maker.channel.updated - super - ensure - authors.replace(keep[:authors]) - contributors.replace(keep[:contributors]) - categories.replace(keep[:categories]) - links.replace(keep[:links]) - self.id = keep[:id] - @rights = keep[:rights] - @title = keep[:title] - self.updated = keep[:updated] - end - - Guid = Feed::Items::Item::Guid - Enclosure = Feed::Items::Item::Enclosure - Source = Feed::Items::Item::Source - Categories = Feed::Items::Item::Categories - Authors = Feed::Items::Item::Authors - Contributors = Feed::Items::Item::Contributors - Links = Feed::Items::Item::Links - Rights = Feed::Items::Item::Rights - Description = Feed::Items::Item::Description - Title = Feed::Items::Item::Title - Content = Feed::Items::Item::Content - end - end - - class Textinput < TextinputBase - end - end - end - - add_maker("atom:entry", "1.0", Atom::Entry) - add_maker("atom1.0:entry", "1.0", Atom::Entry) - end -end diff --git a/ruby/lib/rss/maker/feed.rb b/ruby/lib/rss/maker/feed.rb deleted file mode 100644 index 72ee704d6..000000000 --- a/ruby/lib/rss/maker/feed.rb +++ /dev/null @@ -1,427 +0,0 @@ -# frozen_string_literal: false -require_relative "atom" - -module RSS - module Maker - module Atom - class Feed < RSSBase - def initialize(feed_version="1.0") - super - @feed_type = "atom" - @feed_subtype = "feed" - end - - private - def make_feed - ::RSS::Atom::Feed.new(@version, @encoding, @standalone) - end - - def setup_elements(feed) - setup_channel(feed) - setup_image(feed) - setup_items(feed) - end - - class Channel < ChannelBase - include SetupDefaultLanguage - - def to_feed(feed) - set_default_values do - setup_values(feed) - feed.dc_dates.clear - setup_other_elements(feed) - if image_favicon.about - icon = feed.class::Icon.new - icon.content = image_favicon.about - feed.icon = icon - end - unless have_required_values? - raise NotSetError.new("maker.channel", - not_set_required_variables) - end - end - end - - def have_required_values? - super and - (!authors.empty? or - @maker.items.any? {|item| !item.authors.empty?}) - end - - private - def required_variable_names - %w(id updated) - end - - def variables - super + %w(id updated) - end - - def variable_is_set? - super or !authors.empty? - end - - def not_set_required_variables - vars = super - if authors.empty? and - @maker.items.all? {|item| item.author.to_s.empty?} - vars << "author" - end - vars << "title" unless title {|t| t.have_required_values?} - vars - end - - def _set_default_values(&block) - keep = { - :id => id, - } - self.id ||= about - super(&block) - ensure - self.id = keep[:id] - end - - class SkipDays < SkipDaysBase - def to_feed(*args) - end - - class Day < DayBase - end - end - - class SkipHours < SkipHoursBase - def to_feed(*args) - end - - class Hour < HourBase - end - end - - class Cloud < CloudBase - def to_feed(*args) - end - end - - class Categories < CategoriesBase - class Category < CategoryBase - include AtomCategory - - def self.not_set_name - "maker.channel.category" - end - end - end - - class Links < LinksBase - class Link < LinkBase - include AtomLink - - def self.not_set_name - "maker.channel.link" - end - end - end - - AtomPersons.def_atom_persons(self, "author", "maker.channel.author") - AtomPersons.def_atom_persons(self, "contributor", - "maker.channel.contributor") - - class Generator < GeneratorBase - include AtomGenerator - - def self.not_set_name - "maker.channel.generator" - end - end - - AtomTextConstruct.def_atom_text_construct(self, "rights", - "maker.channel.copyright", - "Copyright") - AtomTextConstruct.def_atom_text_construct(self, "subtitle", - "maker.channel.description", - "Description") - AtomTextConstruct.def_atom_text_construct(self, "title", - "maker.channel.title") - end - - class Image < ImageBase - def to_feed(feed) - logo = feed.class::Logo.new - class << logo - alias_method(:url=, :content=) - end - set = setup_values(logo) - class << logo - remove_method(:url=) - end - if set - feed.logo = logo - set_parent(logo, feed) - setup_other_elements(feed, logo) - elsif variable_is_set? - raise NotSetError.new("maker.image", not_set_required_variables) - end - end - - private - def required_variable_names - %w(url) - end - end - - class Items < ItemsBase - def to_feed(feed) - normalize.each do |item| - item.to_feed(feed) - end - setup_other_elements(feed, feed.entries) - end - - class Item < ItemBase - def to_feed(feed) - set_default_values do - entry = feed.class::Entry.new - set = setup_values(entry) - entry.dc_dates.clear - setup_other_elements(feed, entry) - if set - feed.entries << entry - set_parent(entry, feed) - elsif variable_is_set? - raise NotSetError.new("maker.item", not_set_required_variables) - end - end - end - - def have_required_values? - set_default_values do - super and title {|t| t.have_required_values?} - end - end - - private - def required_variable_names - %w(id updated) - end - - def variables - super + ["updated"] - end - - def not_set_required_variables - vars = super - vars << "title" unless title {|t| t.have_required_values?} - vars - end - - def _set_default_values(&block) - keep = { - :id => id, - } - self.id ||= link - super(&block) - ensure - self.id = keep[:id] - end - - class Guid < GuidBase - def to_feed(feed, current) - end - end - - class Enclosure < EnclosureBase - def to_feed(feed, current) - end - end - - class Source < SourceBase - def to_feed(feed, current) - source = current.class::Source.new - setup_values(source) - current.source = source - set_parent(source, current) - setup_other_elements(feed, source) - current.source = nil if source.to_s == "" - end - - private - def required_variable_names - [] - end - - def variables - super + ["updated"] - end - - AtomPersons.def_atom_persons(self, "author", - "maker.item.source.author") - AtomPersons.def_atom_persons(self, "contributor", - "maker.item.source.contributor") - - class Categories < CategoriesBase - class Category < CategoryBase - include AtomCategory - - def self.not_set_name - "maker.item.source.category" - end - end - end - - class Generator < GeneratorBase - include AtomGenerator - - def self.not_set_name - "maker.item.source.generator" - end - end - - class Icon < IconBase - def to_feed(feed, current) - icon = current.class::Icon.new - class << icon - alias_method(:url=, :content=) - end - set = setup_values(icon) - class << icon - remove_method(:url=) - end - if set - current.icon = icon - set_parent(icon, current) - setup_other_elements(feed, icon) - elsif variable_is_set? - raise NotSetError.new("maker.item.source.icon", - not_set_required_variables) - end - end - - private - def required_variable_names - %w(url) - end - end - - class Links < LinksBase - class Link < LinkBase - include AtomLink - - def self.not_set_name - "maker.item.source.link" - end - end - end - - class Logo < LogoBase - include AtomLogo - - def self.not_set_name - "maker.item.source.logo" - end - end - - maker_name_base = "maker.item.source." - maker_name = "#{maker_name_base}rights" - AtomTextConstruct.def_atom_text_construct(self, "rights", - maker_name) - maker_name = "#{maker_name_base}subtitle" - AtomTextConstruct.def_atom_text_construct(self, "subtitle", - maker_name) - maker_name = "#{maker_name_base}title" - AtomTextConstruct.def_atom_text_construct(self, "title", - maker_name) - end - - class Categories < CategoriesBase - class Category < CategoryBase - include AtomCategory - - def self.not_set_name - "maker.item.category" - end - end - end - - AtomPersons.def_atom_persons(self, "author", "maker.item.author") - AtomPersons.def_atom_persons(self, "contributor", - "maker.item.contributor") - - class Links < LinksBase - class Link < LinkBase - include AtomLink - - def self.not_set_name - "maker.item.link" - end - end - end - - AtomTextConstruct.def_atom_text_construct(self, "rights", - "maker.item.rights") - AtomTextConstruct.def_atom_text_construct(self, "summary", - "maker.item.description", - "Description") - AtomTextConstruct.def_atom_text_construct(self, "title", - "maker.item.title") - - class Content < ContentBase - def to_feed(feed, current) - content = current.class::Content.new - if setup_values(content) - content.src = nil if content.src and content.content - current.content = content - set_parent(content, current) - setup_other_elements(feed, content) - elsif variable_is_set? - raise NotSetError.new("maker.item.content", - not_set_required_variables) - end - end - - alias_method(:xml, :xml_content) - - private - def required_variable_names - if out_of_line? - %w(type) - elsif xml_type? - %w(xml_content) - else - %w(content) - end - end - - def variables - if out_of_line? - super - elsif xml_type? - super + %w(xml) - else - super - end - end - - def xml_type? - _type = type - return false if _type.nil? - _type == "xhtml" or - /(?:\+xml|\/xml)$/i =~ _type or - %w(text/xml-external-parsed-entity - application/xml-external-parsed-entity - application/xml-dtd).include?(_type.downcase) - end - end - end - end - - class Textinput < TextinputBase - end - end - end - - add_maker("atom", "1.0", Atom::Feed) - add_maker("atom:feed", "1.0", Atom::Feed) - add_maker("atom1.0", "1.0", Atom::Feed) - add_maker("atom1.0:feed", "1.0", Atom::Feed) - end -end diff --git a/ruby/lib/rss/maker/image.rb b/ruby/lib/rss/maker/image.rb deleted file mode 100644 index e3e62d8b9..000000000 --- a/ruby/lib/rss/maker/image.rb +++ /dev/null @@ -1,112 +0,0 @@ -# frozen_string_literal: false -require_relative '../image' -require_relative '1.0' -require_relative 'dublincore' - -module RSS - module Maker - module ImageItemModel - def self.append_features(klass) - super - - name = "#{RSS::IMAGE_PREFIX}_item" - klass.def_classed_element(name) - end - - def self.install_image_item(klass) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class ImageItem < ImageItemBase - DublinCoreModel.install_dublin_core(self) - end -EOC - end - - class ImageItemBase < Base - include Maker::DublinCoreModel - - attr_accessor :about, :resource, :image_width, :image_height - add_need_initialize_variable("about") - add_need_initialize_variable("resource") - add_need_initialize_variable("image_width") - add_need_initialize_variable("image_height") - alias width= image_width= - alias width image_width - alias height= image_height= - alias height image_height - - def have_required_values? - @about - end - - def to_feed(feed, current) - if current.respond_to?(:image_item=) and have_required_values? - item = current.class::ImageItem.new - setup_values(item) - setup_other_elements(item) - current.image_item = item - end - end - end - end - - module ImageFaviconModel - def self.append_features(klass) - super - - name = "#{RSS::IMAGE_PREFIX}_favicon" - klass.def_classed_element(name) - end - - def self.install_image_favicon(klass) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class ImageFavicon < ImageFaviconBase - DublinCoreModel.install_dublin_core(self) - end - EOC - end - - class ImageFaviconBase < Base - include Maker::DublinCoreModel - - attr_accessor :about, :image_size - add_need_initialize_variable("about") - add_need_initialize_variable("image_size") - alias size image_size - alias size= image_size= - - def have_required_values? - @about and @image_size - end - - def to_feed(feed, current) - if current.respond_to?(:image_favicon=) and have_required_values? - favicon = current.class::ImageFavicon.new - setup_values(favicon) - setup_other_elements(favicon) - current.image_favicon = favicon - end - end - end - end - - class ChannelBase; include Maker::ImageFaviconModel; end - - class ItemsBase - class ItemBase; include Maker::ImageItemModel; end - end - - makers.each do |maker| - maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class Channel - ImageFaviconModel.install_image_favicon(self) - end - - class Items - class Item - ImageItemModel.install_image_item(self) - end - end - EOC - end - end -end diff --git a/ruby/lib/rss/maker/itunes.rb b/ruby/lib/rss/maker/itunes.rb deleted file mode 100644 index 28cca3202..000000000 --- a/ruby/lib/rss/maker/itunes.rb +++ /dev/null @@ -1,243 +0,0 @@ -# frozen_string_literal: false -require_relative '../itunes' -require_relative '2.0' - -module RSS - module Maker - module ITunesBaseModel - def def_class_accessor(klass, name, type, *args) - name = name.gsub(/-/, "_").gsub(/^itunes_/, '') - full_name = "#{RSS::ITUNES_PREFIX}_#{name}" - case type - when nil - klass.def_other_element(full_name) - when :yes_other - def_yes_other_accessor(klass, full_name) - when :explicit_clean_other - def_explicit_clean_other_accessor(klass, full_name) - when :csv - def_csv_accessor(klass, full_name) - when :element, :attribute - recommended_attribute_name, = *args - klass_name = "ITunes#{Utils.to_class_name(name)}" - klass.def_classed_element(full_name, klass_name, - recommended_attribute_name) - when :elements - plural_name, recommended_attribute_name = args - plural_name ||= "#{name}s" - full_plural_name = "#{RSS::ITUNES_PREFIX}_#{plural_name}" - klass_name = "ITunes#{Utils.to_class_name(name)}" - plural_klass_name = "ITunes#{Utils.to_class_name(plural_name)}" - def_elements_class_accessor(klass, name, full_name, full_plural_name, - klass_name, plural_klass_name, - recommended_attribute_name) - end - end - - def def_yes_other_accessor(klass, full_name) - klass.def_other_element(full_name) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{full_name}? - Utils::YesOther.parse(@#{full_name}) - end - EOC - end - - def def_explicit_clean_other_accessor(klass, full_name) - klass.def_other_element(full_name) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{full_name}? - Utils::ExplicitCleanOther.parse(#{full_name}) - end - EOC - end - - def def_csv_accessor(klass, full_name) - klass.def_csv_element(full_name) - end - - def def_elements_class_accessor(klass, name, full_name, full_plural_name, - klass_name, plural_klass_name, - recommended_attribute_name=nil) - if recommended_attribute_name - klass.def_classed_elements(full_name, recommended_attribute_name, - plural_klass_name, full_plural_name) - else - klass.def_classed_element(full_plural_name, plural_klass_name) - end - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def new_#{full_name}(text=nil) - #{full_name} = @#{full_plural_name}.new_#{name} - #{full_name}.text = text - if block_given? - yield #{full_name} - else - #{full_name} - end - end - EOC - end - end - - module ITunesChannelModel - extend ITunesBaseModel - - class << self - def append_features(klass) - super - - ::RSS::ITunesChannelModel::ELEMENT_INFOS.each do |name, type, *args| - def_class_accessor(klass, name, type, *args) - end - end - end - - class ITunesCategoriesBase < Base - def_array_element("category", "itunes_categories", - "ITunesCategory") - class ITunesCategoryBase < Base - attr_accessor :text - add_need_initialize_variable("text") - def_array_element("category", "itunes_categories", - "ITunesCategory") - - def have_required_values? - text - end - - alias_method :to_feed_for_categories, :to_feed - def to_feed(feed, current) - if text and current.respond_to?(:itunes_category) - new_item = current.class::ITunesCategory.new(text) - to_feed_for_categories(feed, new_item) - current.itunes_categories << new_item - end - end - end - end - - class ITunesImageBase < Base - add_need_initialize_variable("href") - attr_accessor("href") - - def to_feed(feed, current) - if @href and current.respond_to?(:itunes_image) - current.itunes_image ||= current.class::ITunesImage.new - current.itunes_image.href = @href - end - end - end - - class ITunesOwnerBase < Base - %w(itunes_name itunes_email).each do |name| - add_need_initialize_variable(name) - attr_accessor(name) - end - - def to_feed(feed, current) - if current.respond_to?(:itunes_owner=) - _not_set_required_variables = not_set_required_variables - if (required_variable_names - _not_set_required_variables).empty? - return - end - - unless have_required_values? - raise NotSetError.new("maker.channel.itunes_owner", - _not_set_required_variables) - end - current.itunes_owner ||= current.class::ITunesOwner.new - current.itunes_owner.itunes_name = @itunes_name - current.itunes_owner.itunes_email = @itunes_email - end - end - - private - def required_variable_names - %w(itunes_name itunes_email) - end - end - end - - module ITunesItemModel - extend ITunesBaseModel - - class << self - def append_features(klass) - super - - ::RSS::ITunesItemModel::ELEMENT_INFOS.each do |name, type, *args| - def_class_accessor(klass, name, type, *args) - end - end - end - - class ITunesDurationBase < Base - attr_reader :content - add_need_initialize_variable("content") - - %w(hour minute second).each do |name| - attr_reader(name) - add_need_initialize_variable(name, 0) - end - - def content=(content) - if content.nil? - @hour, @minute, @second, @content = nil - else - @hour, @minute, @second = - ::RSS::ITunesItemModel::ITunesDuration.parse(content) - @content = content - end - end - - def hour=(hour) - @hour = Integer(hour) - update_content - end - - def minute=(minute) - @minute = Integer(minute) - update_content - end - - def second=(second) - @second = Integer(second) - update_content - end - - def to_feed(feed, current) - if @content and current.respond_to?(:itunes_duration=) - current.itunes_duration ||= current.class::ITunesDuration.new - current.itunes_duration.content = @content - end - end - - private - def update_content - components = [@hour, @minute, @second] - @content = - ::RSS::ITunesItemModel::ITunesDuration.construct(*components) - end - end - end - - class ChannelBase - include Maker::ITunesChannelModel - class ITunesCategories < ITunesCategoriesBase - class ITunesCategory < ITunesCategoryBase - ITunesCategory = self - end - end - - class ITunesImage < ITunesImageBase; end - class ITunesOwner < ITunesOwnerBase; end - end - - class ItemsBase - class ItemBase - include Maker::ITunesItemModel - class ITunesDuration < ITunesDurationBase; end - end - end - end -end diff --git a/ruby/lib/rss/maker/slash.rb b/ruby/lib/rss/maker/slash.rb deleted file mode 100644 index 473991903..000000000 --- a/ruby/lib/rss/maker/slash.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: false -require_relative '../slash' -require_relative '1.0' - -module RSS - module Maker - module SlashModel - def self.append_features(klass) - super - - ::RSS::SlashModel::ELEMENT_INFOS.each do |name, type| - full_name = "#{RSS::SLASH_PREFIX}_#{name}" - case type - when :csv_integer - klass.def_csv_element(full_name, :integer) - else - klass.def_other_element(full_name) - end - end - - klass.module_eval do - alias_method(:slash_hit_parades, :slash_hit_parade) - alias_method(:slash_hit_parades=, :slash_hit_parade=) - end - end - end - - class ItemsBase - class ItemBase - include SlashModel - end - end - end -end diff --git a/ruby/lib/rss/maker/syndication.rb b/ruby/lib/rss/maker/syndication.rb deleted file mode 100644 index 9fd0efe99..000000000 --- a/ruby/lib/rss/maker/syndication.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: false -require_relative '../syndication' -require_relative '1.0' - -module RSS - module Maker - module SyndicationModel - def self.append_features(klass) - super - - ::RSS::SyndicationModel::ELEMENTS.each do |name| - klass.def_other_element(name) - end - end - end - - class ChannelBase; include SyndicationModel; end - end -end diff --git a/ruby/lib/rss/maker/taxonomy.rb b/ruby/lib/rss/maker/taxonomy.rb deleted file mode 100644 index f9858922d..000000000 --- a/ruby/lib/rss/maker/taxonomy.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: false -require_relative '../taxonomy' -require_relative '1.0' -require_relative 'dublincore' - -module RSS - module Maker - module TaxonomyTopicsModel - def self.append_features(klass) - super - - klass.def_classed_element("#{RSS::TAXO_PREFIX}_topics", - "TaxonomyTopics") - end - - def self.install_taxo_topics(klass) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class TaxonomyTopics < TaxonomyTopicsBase - def to_feed(feed, current) - if current.respond_to?(:taxo_topics) - topics = current.class::TaxonomyTopics.new - bag = topics.Bag - @resources.each do |resource| - bag.lis << RDF::Bag::Li.new(resource) - end - current.taxo_topics = topics - end - end - end -EOC - end - - class TaxonomyTopicsBase < Base - attr_reader :resources - def_array_element("resource") - remove_method :new_resource - end - end - - module TaxonomyTopicModel - def self.append_features(klass) - super - - class_name = "TaxonomyTopics" - klass.def_classed_elements("#{TAXO_PREFIX}_topic", "value", class_name) - end - - def self.install_taxo_topic(klass) - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class TaxonomyTopics < TaxonomyTopicsBase - class TaxonomyTopic < TaxonomyTopicBase - DublinCoreModel.install_dublin_core(self) - TaxonomyTopicsModel.install_taxo_topics(self) - - def to_feed(feed, current) - if current.respond_to?(:taxo_topics) - topic = current.class::TaxonomyTopic.new(value) - topic.taxo_link = value - taxo_topics.to_feed(feed, topic) if taxo_topics - current.taxo_topics << topic - setup_other_elements(feed, topic) - end - end - end - end -EOC - end - - class TaxonomyTopicsBase < Base - def_array_element("topic", nil, "TaxonomyTopic") - alias_method(:new_taxo_topic, :new_topic) # For backward compatibility - - class TaxonomyTopicBase < Base - include DublinCoreModel - include TaxonomyTopicsModel - - attr_accessor :value - add_need_initialize_variable("value") - alias_method(:taxo_link, :value) - alias_method(:taxo_link=, :value=) - - def have_required_values? - @value - end - end - end - end - - class RSSBase - include TaxonomyTopicModel - end - - class ChannelBase - include TaxonomyTopicsModel - end - - class ItemsBase - class ItemBase - include TaxonomyTopicsModel - end - end - - makers.each do |maker| - maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - TaxonomyTopicModel.install_taxo_topic(self) - - class Channel - TaxonomyTopicsModel.install_taxo_topics(self) - end - - class Items - class Item - TaxonomyTopicsModel.install_taxo_topics(self) - end - end - EOC - end - end -end diff --git a/ruby/lib/rss/maker/trackback.rb b/ruby/lib/rss/maker/trackback.rb deleted file mode 100644 index f78b4058f..000000000 --- a/ruby/lib/rss/maker/trackback.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: false -require_relative '../trackback' -require_relative '1.0' -require_relative '2.0' - -module RSS - module Maker - module TrackBackModel - def self.append_features(klass) - super - - klass.def_other_element("#{RSS::TRACKBACK_PREFIX}_ping") - klass.def_classed_elements("#{RSS::TRACKBACK_PREFIX}_about", "value", - "TrackBackAbouts") - end - - class TrackBackAboutsBase < Base - def_array_element("about", nil, "TrackBackAbout") - - class TrackBackAboutBase < Base - attr_accessor :value - add_need_initialize_variable("value") - - alias_method(:resource, :value) - alias_method(:resource=, :value=) - alias_method(:content, :value) - alias_method(:content=, :value=) - - def have_required_values? - @value - end - - def to_feed(feed, current) - if current.respond_to?(:trackback_abouts) and have_required_values? - about = current.class::TrackBackAbout.new - setup_values(about) - setup_other_elements(about) - current.trackback_abouts << about - end - end - end - end - end - - class ItemsBase - class ItemBase; include TrackBackModel; end - end - - makers.each do |maker| - maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - class Items - class Item - class TrackBackAbouts < TrackBackAboutsBase - class TrackBackAbout < TrackBackAboutBase - end - end - end - end - EOC - end - end -end diff --git a/ruby/lib/rss/parser.rb b/ruby/lib/rss/parser.rb deleted file mode 100644 index e1bcfc53e..000000000 --- a/ruby/lib/rss/parser.rb +++ /dev/null @@ -1,589 +0,0 @@ -# frozen_string_literal: false -require "forwardable" -require "open-uri" - -require_relative "rss" -require_relative "xml" - -module RSS - - class NotWellFormedError < Error - attr_reader :line, :element - - # Create a new NotWellFormedError for an error at +line+ - # in +element+. If a block is given the return value of - # the block ends up in the error message. - def initialize(line=nil, element=nil) - message = "This is not well formed XML" - if element or line - message << "\nerror occurred" - message << " in #{element}" if element - message << " at about #{line} line" if line - end - message << "\n#{yield}" if block_given? - super(message) - end - end - - class XMLParserNotFound < Error - def initialize - super("available XML parser was not found in " << - "#{AVAILABLE_PARSER_LIBRARIES.inspect}.") - end - end - - class NotValidXMLParser < Error - def initialize(parser) - super("#{parser} is not an available XML parser. " << - "Available XML parser" << - (AVAILABLE_PARSERS.size > 1 ? "s are " : " is ") << - "#{AVAILABLE_PARSERS.inspect}.") - end - end - - class NSError < InvalidRSSError - attr_reader :tag, :prefix, :uri - def initialize(tag, prefix, require_uri) - @tag, @prefix, @uri = tag, prefix, require_uri - super("prefix <#{prefix}> doesn't associate uri " << - "<#{require_uri}> in tag <#{tag}>") - end - end - - class Parser - - extend Forwardable - - class << self - - @@default_parser = nil - - def default_parser - @@default_parser || AVAILABLE_PARSERS.first - end - - # Set @@default_parser to new_value if it is one of the - # available parsers. Else raise NotValidXMLParser error. - def default_parser=(new_value) - if AVAILABLE_PARSERS.include?(new_value) - @@default_parser = new_value - else - raise NotValidXMLParser.new(new_value) - end - end - - def parse(rss, *args) - if args.last.is_a?(Hash) - options = args.pop - else - options = {} - end - do_validate = boolean_argument(args[0], options[:validate], true) - ignore_unknown_element = - boolean_argument(args[1], options[:ignore_unknown_element], true) - parser_class = args[2] || options[:parser_class] || default_parser - parser = new(rss, parser_class) - parser.do_validate = do_validate - parser.ignore_unknown_element = ignore_unknown_element - parser.parse - end - - private - def boolean_argument(positioned_value, option_value, default) - value = positioned_value - if value.nil? and not option_value.nil? - value = option_value - end - value = default if value.nil? - value - end - end - - def_delegators(:@parser, :parse, :rss, - :ignore_unknown_element, - :ignore_unknown_element=, :do_validate, - :do_validate=) - - def initialize(rss, parser_class=self.class.default_parser) - @parser = parser_class.new(normalize_rss(rss)) - end - - private - - # Try to get the XML associated with +rss+. - # Return +rss+ if it already looks like XML, or treat it as a URI, - # or a file to get the XML, - def normalize_rss(rss) - return rss if maybe_xml?(rss) - - uri = to_uri(rss) - - if uri.respond_to?(:read) - uri.read - elsif (RUBY_VERSION >= '2.7' || !rss.tainted?) and File.readable?(rss) - File.open(rss) {|f| f.read} - else - rss - end - end - - # maybe_xml? tests if source is a string that looks like XML. - def maybe_xml?(source) - source.is_a?(String) and / :xml}] - @tag_stack = [[]] - @text_stack = [''] - @proc_stack = [] - @last_element = nil - @version = @encoding = @standalone = nil - @xml_stylesheets = [] - @xml_child_mode = false - @xml_element = nil - @last_xml_element = nil - end - - # set instance vars for version, encoding, standalone - def xmldecl(version, encoding, standalone) - @version, @encoding, @standalone = version, encoding, standalone - end - - def instruction(name, content) - if name == "xml-stylesheet" - params = parse_pi_content(content) - if params.has_key?("href") - @xml_stylesheets << XMLStyleSheet.new(params) - end - end - end - - def tag_start(name, attributes) - @text_stack.push('') - - ns = @ns_stack.last.dup - attrs = {} - attributes.each do |n, v| - if /\Axmlns(?:\z|:)/ =~ n - ns[$POSTMATCH] = v - else - attrs[n] = v - end - end - @ns_stack.push(ns) - - prefix, local = split_name(name) - @tag_stack.last.push([_ns(ns, prefix), local]) - @tag_stack.push([]) - if @xml_child_mode - previous = @last_xml_element - element_attrs = attributes.dup - unless previous - ns.each do |ns_prefix, value| - next if ns_prefix == "xml" - key = ns_prefix.empty? ? "xmlns" : "xmlns:#{ns_prefix}" - element_attrs[key] ||= value - end - end - next_element = XML::Element.new(local, - prefix.empty? ? nil : prefix, - _ns(ns, prefix), - element_attrs) - previous << next_element if previous - @last_xml_element = next_element - pr = Proc.new do |text, tags| - if previous - @last_xml_element = previous - else - @xml_element = @last_xml_element - @last_xml_element = nil - end - end - @proc_stack.push(pr) - else - if @rss.nil? and respond_to?("initial_start_#{local}", true) - __send__("initial_start_#{local}", local, prefix, attrs, ns.dup) - elsif respond_to?("start_#{local}", true) - __send__("start_#{local}", local, prefix, attrs, ns.dup) - else - start_else_element(local, prefix, attrs, ns.dup) - end - end - end - - def tag_end(name) - if DEBUG - p "end tag #{name}" - p @tag_stack - end - text = @text_stack.pop - tags = @tag_stack.pop - pr = @proc_stack.pop - pr.call(text, tags) unless pr.nil? - @ns_stack.pop - end - - def text(data) - if @xml_child_mode - @last_xml_element << data if @last_xml_element - else - @text_stack.last << data - end - end - - private - def _ns(ns, prefix) - ns.fetch(prefix, "") - end - - CONTENT_PATTERN = /\s*([^=]+)=(["'])([^\2]+?)\2/ - # Extract the first name="value" pair from content. - # Works with single quotes according to the constant - # CONTENT_PATTERN. Return a Hash. - def parse_pi_content(content) - params = {} - content.scan(CONTENT_PATTERN) do |name, quote, value| - params[name] = value - end - params - end - - def start_else_element(local, prefix, attrs, ns) - class_name = self.class.class_name(_ns(ns, prefix), local) - current_class = @last_element.class - if known_class?(current_class, class_name) - next_class = current_class.const_get(class_name) - start_have_something_element(local, prefix, attrs, ns, next_class) - else - if !@do_validate or @ignore_unknown_element - @proc_stack.push(setup_next_element_in_unknown_element) - else - parent = "ROOT ELEMENT???" - if current_class.tag_name - parent = current_class.tag_name - end - raise NotExpectedTagError.new(local, _ns(ns, prefix), parent) - end - end - end - - if Module.method(:const_defined?).arity == -1 - def known_class?(target_class, class_name) - class_name and - (target_class.const_defined?(class_name, false) or - target_class.constants.include?(class_name.to_sym)) - end - else - def known_class?(target_class, class_name) - class_name and - (target_class.const_defined?(class_name) or - target_class.constants.include?(class_name)) - end - end - - NAMESPLIT = /^(?:([\w:][-\w.]*):)?([\w:][-\w.]*)/ - def split_name(name) - name =~ NAMESPLIT - [$1 || '', $2] - end - - def check_ns(tag_name, prefix, ns, require_uri, ignore_unknown_element=nil) - if _ns(ns, prefix) == require_uri - true - else - if ignore_unknown_element.nil? - ignore_unknown_element = @ignore_unknown_element - end - - if ignore_unknown_element - false - elsif @do_validate - raise NSError.new(tag_name, prefix, require_uri) - else - # Force bind required URI with prefix - @ns_stack.last[prefix] = require_uri - true - end - end - end - - def start_get_text_element(tag_name, prefix, ns, required_uri) - pr = Proc.new do |text, tags| - setter = self.class.setter(required_uri, tag_name) - if setter and @last_element.respond_to?(setter) - if @do_validate - getter = self.class.getter(required_uri, tag_name) - if @last_element.__send__(getter) - raise TooMuchTagError.new(tag_name, @last_element.tag_name) - end - end - @last_element.__send__(setter, text.to_s) - else - if @do_validate and !@ignore_unknown_element - raise NotExpectedTagError.new(tag_name, _ns(ns, prefix), - @last_element.tag_name) - end - end - end - @proc_stack.push(pr) - end - - def start_have_something_element(tag_name, prefix, attrs, ns, klass) - if check_ns(tag_name, prefix, ns, klass.required_uri) - attributes = collect_attributes(tag_name, prefix, attrs, ns, klass) - @proc_stack.push(setup_next_element(tag_name, klass, attributes)) - else - @proc_stack.push(setup_next_element_in_unknown_element) - end - end - - def collect_attributes(tag_name, prefix, attrs, ns, klass) - attributes = {} - klass.get_attributes.each do |a_name, a_uri, required, element_name| - if a_uri.is_a?(String) or !a_uri.respond_to?(:include?) - a_uri = [a_uri] - end - unless a_uri == [""] - for prefix, uri in ns - if a_uri.include?(uri) - val = attrs["#{prefix}:#{a_name}"] - break if val - end - end - end - if val.nil? and a_uri.include?("") - val = attrs[a_name] - end - - if @do_validate and required and val.nil? - unless a_uri.include?("") - for prefix, uri in ns - if a_uri.include?(uri) - a_name = "#{prefix}:#{a_name}" - end - end - end - raise MissingAttributeError.new(tag_name, a_name) - end - - attributes[a_name] = val - end - attributes - end - - def setup_next_element(tag_name, klass, attributes) - previous = @last_element - next_element = klass.new(@do_validate, attributes) - previous.set_next_element(tag_name, next_element) - @last_element = next_element - @last_element.parent = previous if klass.need_parent? - @xml_child_mode = @last_element.have_xml_content? - - Proc.new do |text, tags| - p(@last_element.class) if DEBUG - if @xml_child_mode - @last_element.content = @xml_element.to_s - xml_setter = @last_element.class.xml_setter - @last_element.__send__(xml_setter, @xml_element) - @xml_element = nil - @xml_child_mode = false - else - if klass.have_content? - if @last_element.need_base64_encode? - text = text.lstrip.unpack("m").first - end - @last_element.content = text - end - end - if @do_validate - @last_element.validate_for_stream(tags, @ignore_unknown_element) - end - @last_element = previous - end - end - - def setup_next_element_in_unknown_element - current_element, @last_element = @last_element, nil - Proc.new {@last_element = current_element} - end - end - - unless const_defined? :AVAILABLE_PARSER_LIBRARIES - # The list of all available libraries for parsing. - AVAILABLE_PARSER_LIBRARIES = [ - ["rss/xmlparser", :XMLParserParser], - ["rss/xmlscanner", :XMLScanParser], - ["rss/rexmlparser", :REXMLParser], - ] - end - - # The list of all available parsers, in constant form. - AVAILABLE_PARSERS = [] - - AVAILABLE_PARSER_LIBRARIES.each do |lib, parser| - begin - require lib - AVAILABLE_PARSERS.push(const_get(parser)) - rescue LoadError - end - end - - if AVAILABLE_PARSERS.empty? - raise XMLParserNotFound - end -end diff --git a/ruby/lib/rss/rexmlparser.rb b/ruby/lib/rss/rexmlparser.rb deleted file mode 100644 index ef0595e44..000000000 --- a/ruby/lib/rss/rexmlparser.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" -require "rexml/streamlistener" - -module RSS - - class REXMLParser < BaseParser - - class << self - def listener - REXMLListener - end - end - - private - def _parse - begin - REXML::Document.parse_stream(@rss, @listener) - rescue RuntimeError => e - raise NotWellFormedError.new{e.message} - rescue REXML::ParseException => e - context = e.context - line = context[0] if context - raise NotWellFormedError.new(line){e.message} - end - end - - end - - class REXMLListener < BaseListener - - include REXML::StreamListener - include ListenerMixin - - class << self - def raise_for_undefined_entity? - false - end - end - - def xmldecl(version, encoding, standalone) - super(version, encoding, standalone == "yes") - # Encoding is converted to UTF-8 when REXML parse XML. - @encoding = 'UTF-8' - end - - alias_method(:cdata, :text) - end - -end diff --git a/ruby/lib/rss/rss.gemspec b/ruby/lib/rss/rss.gemspec deleted file mode 100644 index 04f2b2f42..000000000 --- a/ruby/lib/rss/rss.gemspec +++ /dev/null @@ -1,80 +0,0 @@ -begin - require_relative "lib/rss/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "rss" - spec.version = RSS::VERSION - spec.authors = ["Kouhei Sutou"] - spec.email = ["kou@cozmixng.org"] - - spec.summary = %q{Family of libraries that support various formats of XML "feeds".} - spec.description = %q{Family of libraries that support various formats of XML "feeds".} - spec.homepage = "https://github.com/ruby/rss" - spec.license = "BSD-2-Clause" - - spec.files = [ - ".gitignore", - ".travis.yml", - "Gemfile", - "LICENSE.txt", - "NEWS.md", - "README.md", - "Rakefile", - "lib/rss.rb", - "lib/rss/0.9.rb", - "lib/rss/1.0.rb", - "lib/rss/2.0.rb", - "lib/rss/atom.rb", - "lib/rss/content.rb", - "lib/rss/content/1.0.rb", - "lib/rss/content/2.0.rb", - "lib/rss/converter.rb", - "lib/rss/dublincore.rb", - "lib/rss/dublincore/1.0.rb", - "lib/rss/dublincore/2.0.rb", - "lib/rss/dublincore/atom.rb", - "lib/rss/image.rb", - "lib/rss/itunes.rb", - "lib/rss/maker.rb", - "lib/rss/maker/0.9.rb", - "lib/rss/maker/1.0.rb", - "lib/rss/maker/2.0.rb", - "lib/rss/maker/atom.rb", - "lib/rss/maker/base.rb", - "lib/rss/maker/content.rb", - "lib/rss/maker/dublincore.rb", - "lib/rss/maker/entry.rb", - "lib/rss/maker/feed.rb", - "lib/rss/maker/image.rb", - "lib/rss/maker/itunes.rb", - "lib/rss/maker/slash.rb", - "lib/rss/maker/syndication.rb", - "lib/rss/maker/taxonomy.rb", - "lib/rss/maker/trackback.rb", - "lib/rss/parser.rb", - "lib/rss/rexmlparser.rb", - "lib/rss/rss.rb", - "lib/rss/slash.rb", - "lib/rss/syndication.rb", - "lib/rss/taxonomy.rb", - "lib/rss/trackback.rb", - "lib/rss/utils.rb", - "lib/rss/version.rb", - "lib/rss/xml-stylesheet.rb", - "lib/rss/xml.rb", - "lib/rss/xmlparser.rb", - "lib/rss/xmlscanner.rb", - "rss.gemspec", - ] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "test-unit" -end diff --git a/ruby/lib/rss/rss.rb b/ruby/lib/rss/rss.rb deleted file mode 100644 index daa0837e9..000000000 --- a/ruby/lib/rss/rss.rb +++ /dev/null @@ -1,1342 +0,0 @@ -# frozen_string_literal: false -require "time" - -class Time - class << self - unless respond_to?(:w3cdtf) - # This method converts a W3CDTF string date/time format to Time object. - # - # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime - # - # Time.w3cdtf('2003-02-15T13:50:05-05:00') - # # => 2003-02-15 10:50:05 -0800 - # Time.w3cdtf('2003-02-15T13:50:05-05:00').class - # # => Time - def w3cdtf(date) - if /\A\s* - (-?\d+)-(\d\d)-(\d\d) - (?:T - (\d\d):(\d\d)(?::(\d\d))? - (\.\d+)? - (Z|[+-]\d\d:\d\d)?)? - \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8)) - datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i] - usec = 0 - usec = $7.to_f * 1000000 if $7 - zone = $8 - if zone - off = zone_offset(zone, datetime[0]) - datetime = apply_offset(*(datetime + [off])) - datetime << usec - time = Time.utc(*datetime) - force_zone!(time, zone, off) - time - else - datetime << usec - Time.local(*datetime) - end - else - raise ArgumentError.new("invalid date: #{date.inspect}") - end - end - end - end - - unless method_defined?(:w3cdtf) - # This method converts a Time object to a String. The String contains the - # time in W3CDTF date/time format. - # - # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime - # - # Time.now.w3cdtf - # # => "2013-08-26T14:12:10.817124-07:00" - def w3cdtf - if usec.zero? - fraction_digits = 0 - else - fraction_digits = strftime('%6N').index(/0*\z/) - end - xmlschema(fraction_digits) - end - end -end - - -require "English" -require_relative "utils" -require_relative "converter" -require_relative "xml-stylesheet" - -module RSS - # The URI of the RSS 1.0 specification - URI = "http://purl.org/rss/1.0/" - - DEBUG = false # :nodoc: - - # The basic error all other RSS errors stem from. Rescue this error if you - # want to handle any given RSS error and you don't care about the details. - class Error < StandardError; end - - # RSS, being an XML-based format, has namespace support. If two namespaces are - # declared with the same name, an OverlappedPrefixError will be raised. - class OverlappedPrefixError < Error - attr_reader :prefix - def initialize(prefix) - @prefix = prefix - end - end - - # The InvalidRSSError error is the base class for a variety of errors - # related to a poorly-formed RSS feed. Rescue this error if you only - # care that a file could be invalid, but don't care how it is invalid. - class InvalidRSSError < Error; end - - # Since RSS is based on XML, it must have opening and closing tags that - # match. If they don't, a MissingTagError will be raised. - class MissingTagError < InvalidRSSError - attr_reader :tag, :parent - def initialize(tag, parent) - @tag, @parent = tag, parent - super("tag <#{tag}> is missing in tag <#{parent}>") - end - end - - # Some tags must only exist a specific number of times in a given RSS feed. - # If a feed has too many occurrences of one of these tags, a TooMuchTagError - # will be raised. - class TooMuchTagError < InvalidRSSError - attr_reader :tag, :parent - def initialize(tag, parent) - @tag, @parent = tag, parent - super("tag <#{tag}> is too much in tag <#{parent}>") - end - end - - # Certain attributes are required on specific tags in an RSS feed. If a feed - # is missing one of these attributes, a MissingAttributeError is raised. - class MissingAttributeError < InvalidRSSError - attr_reader :tag, :attribute - def initialize(tag, attribute) - @tag, @attribute = tag, attribute - super("attribute <#{attribute}> is missing in tag <#{tag}>") - end - end - - # RSS does not allow for free-form tag names, so if an RSS feed contains a - # tag that we don't know about, an UnknownTagError is raised. - class UnknownTagError < InvalidRSSError - attr_reader :tag, :uri - def initialize(tag, uri) - @tag, @uri = tag, uri - super("tag <#{tag}> is unknown in namespace specified by uri <#{uri}>") - end - end - - # Raised when an unexpected tag is encountered. - class NotExpectedTagError < InvalidRSSError - attr_reader :tag, :uri, :parent - def initialize(tag, uri, parent) - @tag, @uri, @parent = tag, uri, parent - super("tag <{#{uri}}#{tag}> is not expected in tag <#{parent}>") - end - end - # For backward compatibility :X - NotExceptedTagError = NotExpectedTagError # :nodoc: - - # Attributes are in key-value form, and if there's no value provided for an - # attribute, a NotAvailableValueError will be raised. - class NotAvailableValueError < InvalidRSSError - attr_reader :tag, :value, :attribute - def initialize(tag, value, attribute=nil) - @tag, @value, @attribute = tag, value, attribute - message = "value <#{value}> of " - message << "attribute <#{attribute}> of " if attribute - message << "tag <#{tag}> is not available." - super(message) - end - end - - # Raised when an unknown conversion error occurs. - class UnknownConversionMethodError < Error - attr_reader :to, :from - def initialize(to, from) - @to = to - @from = from - super("can't convert to #{to} from #{from}.") - end - end - # for backward compatibility - UnknownConvertMethod = UnknownConversionMethodError # :nodoc: - - # Raised when a conversion failure occurs. - class ConversionError < Error - attr_reader :string, :to, :from - def initialize(string, to, from) - @string = string - @to = to - @from = from - super("can't convert #{@string} to #{to} from #{from}.") - end - end - - # Raised when a required variable is not set. - class NotSetError < Error - attr_reader :name, :variables - def initialize(name, variables) - @name = name - @variables = variables - super("required variables of #{@name} are not set: #{@variables.join(', ')}") - end - end - - # Raised when a RSS::Maker attempts to use an unknown maker. - class UnsupportedMakerVersionError < Error - attr_reader :version - def initialize(version) - @version = version - super("Maker doesn't support version: #{@version}") - end - end - - module BaseModel - include Utils - - def install_have_child_element(tag_name, uri, occurs, name=nil, type=nil) - name ||= tag_name - add_need_initialize_variable(name) - install_model(tag_name, uri, occurs, name) - - writer_type, reader_type = type - def_corresponded_attr_writer name, writer_type - def_corresponded_attr_reader name, reader_type - install_element(name) do |n, elem_name| - <<-EOC - if @#{n} - "\#{@#{n}.to_s(need_convert, indent)}" - else - '' - end -EOC - end - end - alias_method(:install_have_attribute_element, :install_have_child_element) - - def install_have_children_element(tag_name, uri, occurs, name=nil, plural_name=nil) - name ||= tag_name - plural_name ||= "#{name}s" - add_have_children_element(name, plural_name) - add_plural_form(name, plural_name) - install_model(tag_name, uri, occurs, plural_name, true) - - def_children_accessor(name, plural_name) - install_element(name, "s") do |n, elem_name| - <<-EOC - rv = [] - @#{n}.each do |x| - value = "\#{x.to_s(need_convert, indent)}" - rv << value if /\\A\\s*\\z/ !~ value - end - rv.join("\n") -EOC - end - end - - def install_text_element(tag_name, uri, occurs, name=nil, type=nil, - disp_name=nil) - name ||= tag_name - disp_name ||= name - self::ELEMENTS << name unless self::ELEMENTS.include?(name) - add_need_initialize_variable(name) - install_model(tag_name, uri, occurs, name) - - def_corresponded_attr_writer(name, type, disp_name) - def_corresponded_attr_reader(name, type || :convert) - install_element(name) do |n, elem_name| - <<-EOC - if respond_to?(:#{n}_content) - content = #{n}_content - else - content = @#{n} - end - if content - rv = "\#{indent}<#{elem_name}>" - value = html_escape(content) - if need_convert - rv << convert(value) - else - rv << value - end - rv << "" - rv - else - '' - end -EOC - end - end - - def install_date_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil) - name ||= tag_name - type ||= :w3cdtf - disp_name ||= name - self::ELEMENTS << name - add_need_initialize_variable(name) - install_model(tag_name, uri, occurs, name) - - # accessor - convert_attr_reader name - date_writer(name, type, disp_name) - - install_element(name) do |n, elem_name| - <<-EOC - if @#{n} - rv = "\#{indent}<#{elem_name}>" - value = html_escape(@#{n}.#{type}) - if need_convert - rv << convert(value) - else - rv << value - end - rv << "" - rv - else - '' - end -EOC - end - - end - - private - def install_element(name, postfix="") - elem_name = name.sub('_', ':') - method_name = "#{name}_element#{postfix}" - add_to_element_method(method_name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{method_name}(need_convert=true, indent='') - #{yield(name, elem_name)} - end - private :#{method_name} -EOC - end - - def inherit_convert_attr_reader(*attrs) - attrs.each do |attr| - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{attr}_without_inherit - convert(@#{attr}) - end - - def #{attr} - if @#{attr} - #{attr}_without_inherit - elsif @parent - @parent.#{attr} - else - nil - end - end -EOC - end - end - - def uri_convert_attr_reader(*attrs) - attrs.each do |attr| - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{attr}_without_base - convert(@#{attr}) - end - - def #{attr} - value = #{attr}_without_base - return nil if value.nil? - if /\\A[a-z][a-z0-9+.\\-]*:/i =~ value - value - else - "\#{base}\#{value}" - end - end -EOC - end - end - - def convert_attr_reader(*attrs) - attrs.each do |attr| - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{attr} - convert(@#{attr}) - end -EOC - end - end - - def explicit_clean_other_attr_reader(*attrs) - attrs.each do |attr| - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - attr_reader(:#{attr}) - def #{attr}? - ExplicitCleanOther.parse(@#{attr}) - end - EOC - end - end - - def yes_other_attr_reader(*attrs) - attrs.each do |attr| - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - attr_reader(:#{attr}) - def #{attr}? - Utils::YesOther.parse(@#{attr}) - end - EOC - end - end - - def csv_attr_reader(*attrs) - separator = nil - if attrs.last.is_a?(Hash) - options = attrs.pop - separator = options[:separator] - end - separator ||= ", " - attrs.each do |attr| - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - attr_reader(:#{attr}) - def #{attr}_content - if @#{attr}.nil? - @#{attr} - else - @#{attr}.join(#{separator.dump}) - end - end - EOC - end - end - - def date_writer(name, type, disp_name=name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if new_value.nil? - @#{name} = new_value - elsif new_value.kind_of?(Time) - @#{name} = new_value.dup - else - if @do_validate - begin - @#{name} = Time.__send__('#{type}', new_value) - rescue ArgumentError - raise NotAvailableValueError.new('#{disp_name}', new_value) - end - else - @#{name} = nil - if /\\A\\s*\\z/ !~ new_value.to_s - begin - unless Date._parse(new_value, false).empty? - @#{name} = Time.parse(new_value) - end - rescue ArgumentError - end - end - end - end - - # Is it need? - if @#{name} - class << @#{name} - undef_method(:to_s) - alias_method(:to_s, :#{type}) - end - end - - end -EOC - end - - def integer_writer(name, disp_name=name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if new_value.nil? - @#{name} = new_value - else - if @do_validate - begin - @#{name} = Integer(new_value) - rescue ArgumentError - raise NotAvailableValueError.new('#{disp_name}', new_value) - end - else - @#{name} = new_value.to_i - end - end - end -EOC - end - - def positive_integer_writer(name, disp_name=name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if new_value.nil? - @#{name} = new_value - else - if @do_validate - begin - tmp = Integer(new_value) - raise ArgumentError if tmp <= 0 - @#{name} = tmp - rescue ArgumentError - raise NotAvailableValueError.new('#{disp_name}', new_value) - end - else - @#{name} = new_value.to_i - end - end - end -EOC - end - - def boolean_writer(name, disp_name=name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if new_value.nil? - @#{name} = new_value - else - if @do_validate and - ![true, false, "true", "false"].include?(new_value) - raise NotAvailableValueError.new('#{disp_name}', new_value) - end - if [true, false].include?(new_value) - @#{name} = new_value - else - @#{name} = new_value == "true" - end - end - end -EOC - end - - def text_type_writer(name, disp_name=name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if @do_validate and - !["text", "html", "xhtml", nil].include?(new_value) - raise NotAvailableValueError.new('#{disp_name}', new_value) - end - @#{name} = new_value - end -EOC - end - - def content_writer(name, disp_name=name) - klass_name = "self.class::#{Utils.to_class_name(name)}" - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{name}=(new_value) - if new_value.is_a?(#{klass_name}) - @#{name} = new_value - else - @#{name} = #{klass_name}.new - @#{name}.content = new_value - end - end -EOC - end - - def explicit_clean_other_writer(name, disp_name=name) - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name}=(value) - value = (value ? "yes" : "no") if [true, false].include?(value) - @#{name} = value - end - EOC - end - - def yes_other_writer(name, disp_name=name) - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name}=(new_value) - if [true, false].include?(new_value) - new_value = new_value ? "yes" : "no" - end - @#{name} = new_value - end - EOC - end - - def csv_writer(name, disp_name=name) - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name}=(new_value) - @#{name} = Utils::CSV.parse(new_value) - end - EOC - end - - def csv_integer_writer(name, disp_name=name) - module_eval(<<-EOC, __FILE__, __LINE__ + 1) - def #{name}=(new_value) - @#{name} = Utils::CSV.parse(new_value) {|v| Integer(v)} - end - EOC - end - - def def_children_accessor(accessor_name, plural_name) - module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{plural_name} - @#{accessor_name} - end - - def #{accessor_name}(*args) - if args.empty? - @#{accessor_name}.first - else - @#{accessor_name}[*args] - end - end - - def #{accessor_name}=(*args) - receiver = self.class.name - warn("Don't use `\#{receiver}\##{accessor_name} = XXX'/" \ - "`\#{receiver}\#set_#{accessor_name}(XXX)'. " \ - "Those APIs are not sense of Ruby. " \ - "Use `\#{receiver}\##{plural_name} << XXX' instead of them.", uplevel: 1) - if args.size == 1 - @#{accessor_name}.push(args[0]) - else - @#{accessor_name}.__send__("[]=", *args) - end - end - alias_method(:set_#{accessor_name}, :#{accessor_name}=) -EOC - end - end - - module SetupMaker - def setup_maker(maker) - target = maker_target(maker) - unless target.nil? - setup_maker_attributes(target) - setup_maker_element(target) - setup_maker_elements(target) - end - end - - private - def maker_target(maker) - nil - end - - def setup_maker_attributes(target) - end - - def setup_maker_element(target) - self.class.need_initialize_variables.each do |var| - value = __send__(var) - next if value.nil? - if value.respond_to?("setup_maker") and - !not_need_to_call_setup_maker_variables.include?(var) - value.setup_maker(target) - else - setter = "#{var}=" - if target.respond_to?(setter) - target.__send__(setter, value) - end - end - end - end - - def not_need_to_call_setup_maker_variables - [] - end - - def setup_maker_elements(parent) - self.class.have_children_elements.each do |name, plural_name| - if parent.respond_to?(plural_name) - target = parent.__send__(plural_name) - __send__(plural_name).each do |elem| - elem.setup_maker(target) - end - end - end - end - end - - class Element - extend BaseModel - include Utils - extend Utils::InheritedReader - include SetupMaker - - INDENT = " " - - MUST_CALL_VALIDATORS = {} - MODELS = [] - GET_ATTRIBUTES = [] - HAVE_CHILDREN_ELEMENTS = [] - TO_ELEMENT_METHODS = [] - NEED_INITIALIZE_VARIABLES = [] - PLURAL_FORMS = {} - - class << self - def must_call_validators - inherited_hash_reader("MUST_CALL_VALIDATORS") - end - def models - inherited_array_reader("MODELS") - end - def get_attributes - inherited_array_reader("GET_ATTRIBUTES") - end - def have_children_elements - inherited_array_reader("HAVE_CHILDREN_ELEMENTS") - end - def to_element_methods - inherited_array_reader("TO_ELEMENT_METHODS") - end - def need_initialize_variables - inherited_array_reader("NEED_INITIALIZE_VARIABLES") - end - def plural_forms - inherited_hash_reader("PLURAL_FORMS") - end - - def inherited_base - ::RSS::Element - end - - def inherited(klass) - klass.const_set(:MUST_CALL_VALIDATORS, {}) - klass.const_set(:MODELS, []) - klass.const_set(:GET_ATTRIBUTES, []) - klass.const_set(:HAVE_CHILDREN_ELEMENTS, []) - klass.const_set(:TO_ELEMENT_METHODS, []) - klass.const_set(:NEED_INITIALIZE_VARIABLES, []) - klass.const_set(:PLURAL_FORMS, {}) - - tag_name = klass.name.split(/::/).last - tag_name[0, 1] = tag_name[0, 1].downcase - klass.instance_variable_set(:@tag_name, tag_name) - klass.instance_variable_set(:@have_content, false) - end - - def install_must_call_validator(prefix, uri) - self::MUST_CALL_VALIDATORS[uri] = prefix - end - - def install_model(tag, uri, occurs=nil, getter=nil, plural=false) - getter ||= tag - if m = self::MODELS.find {|t, u, o, g, p| t == tag and u == uri} - m[2] = occurs - else - self::MODELS << [tag, uri, occurs, getter, plural] - end - end - - def install_get_attribute(name, uri, required=true, - type=nil, disp_name=nil, - element_name=nil) - disp_name ||= name - element_name ||= name - writer_type, reader_type = type - def_corresponded_attr_writer name, writer_type, disp_name - def_corresponded_attr_reader name, reader_type - if type == :boolean and /^is/ =~ name - alias_method "#{$POSTMATCH}?", name - end - self::GET_ATTRIBUTES << [name, uri, required, element_name] - add_need_initialize_variable(disp_name) - end - - def def_corresponded_attr_writer(name, type=nil, disp_name=nil) - disp_name ||= name - case type - when :integer - integer_writer name, disp_name - when :positive_integer - positive_integer_writer name, disp_name - when :boolean - boolean_writer name, disp_name - when :w3cdtf, :rfc822, :rfc2822 - date_writer name, type, disp_name - when :text_type - text_type_writer name, disp_name - when :content - content_writer name, disp_name - when :explicit_clean_other - explicit_clean_other_writer name, disp_name - when :yes_other - yes_other_writer name, disp_name - when :csv - csv_writer name - when :csv_integer - csv_integer_writer name - else - attr_writer name - end - end - - def def_corresponded_attr_reader(name, type=nil) - case type - when :inherit - inherit_convert_attr_reader name - when :uri - uri_convert_attr_reader name - when :explicit_clean_other - explicit_clean_other_attr_reader name - when :yes_other - yes_other_attr_reader name - when :csv - csv_attr_reader name - when :csv_integer - csv_attr_reader name, :separator => "," - else - convert_attr_reader name - end - end - - def content_setup(type=nil, disp_name=nil) - writer_type, reader_type = type - def_corresponded_attr_writer :content, writer_type, disp_name - def_corresponded_attr_reader :content, reader_type - @have_content = true - end - - def have_content? - @have_content - end - - def add_have_children_element(variable_name, plural_name) - self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name] - end - - def add_to_element_method(method_name) - self::TO_ELEMENT_METHODS << method_name - end - - def add_need_initialize_variable(variable_name) - self::NEED_INITIALIZE_VARIABLES << variable_name - end - - def add_plural_form(singular, plural) - self::PLURAL_FORMS[singular] = plural - end - - def required_prefix - nil - end - - def required_uri - "" - end - - def need_parent? - false - end - - def install_ns(prefix, uri) - if self::NSPOOL.has_key?(prefix) - raise OverlappedPrefixError.new(prefix) - end - self::NSPOOL[prefix] = uri - end - - def tag_name - @tag_name - end - end - - attr_accessor :parent, :do_validate - - def initialize(do_validate=true, attrs=nil) - @parent = nil - @converter = nil - if attrs.nil? and (do_validate.is_a?(Hash) or do_validate.is_a?(Array)) - do_validate, attrs = true, do_validate - end - @do_validate = do_validate - initialize_variables(attrs || {}) - end - - def tag_name - self.class.tag_name - end - - def full_name - tag_name - end - - def converter=(converter) - @converter = converter - targets = children.dup - self.class.have_children_elements.each do |variable_name, plural_name| - targets.concat(__send__(plural_name)) - end - targets.each do |target| - target.converter = converter unless target.nil? - end - end - - def convert(value) - if @converter - @converter.convert(value) - else - value - end - end - - def valid?(ignore_unknown_element=true) - validate(ignore_unknown_element) - true - rescue RSS::Error - false - end - - def validate(ignore_unknown_element=true) - do_validate = @do_validate - @do_validate = true - validate_attribute - __validate(ignore_unknown_element) - ensure - @do_validate = do_validate - end - - def validate_for_stream(tags, ignore_unknown_element=true) - validate_attribute - __validate(ignore_unknown_element, tags, false) - end - - def to_s(need_convert=true, indent='') - if self.class.have_content? - return "" if !empty_content? and !content_is_set? - rv = tag(indent) do |next_indent| - if empty_content? - "" - else - xmled_content - end - end - else - rv = tag(indent) do |next_indent| - self.class.to_element_methods.collect do |method_name| - __send__(method_name, false, next_indent) - end - end - end - rv = convert(rv) if need_convert - rv - end - - def have_xml_content? - false - end - - def need_base64_encode? - false - end - - def set_next_element(tag_name, next_element) - klass = next_element.class - prefix = "" - prefix << "#{klass.required_prefix}_" if klass.required_prefix - key = "#{prefix}#{tag_name.gsub(/-/, '_')}" - if self.class.plural_forms.has_key?(key) - ary = __send__("#{self.class.plural_forms[key]}") - ary << next_element - else - __send__("#{key}=", next_element) - end - end - - protected - def have_required_elements? - self.class::MODELS.all? do |tag, uri, occurs, getter| - if occurs.nil? or occurs == "+" - child = __send__(getter) - if child.is_a?(Array) - children = child - children.any? {|c| c.have_required_elements?} - else - not child.nil? - end - else - true - end - end - end - - private - def initialize_variables(attrs) - normalized_attrs = {} - attrs.each do |key, value| - normalized_attrs[key.to_s] = value - end - self.class.need_initialize_variables.each do |variable_name| - value = normalized_attrs[variable_name.to_s] - if value - __send__("#{variable_name}=", value) - else - instance_variable_set("@#{variable_name}", nil) - end - end - initialize_have_children_elements - @content = normalized_attrs["content"] if self.class.have_content? - end - - def initialize_have_children_elements - self.class.have_children_elements.each do |variable_name, plural_name| - instance_variable_set("@#{variable_name}", []) - end - end - - def tag(indent, additional_attrs={}, &block) - next_indent = indent + INDENT - - attrs = collect_attrs - return "" if attrs.nil? - - return "" unless have_required_elements? - - attrs.update(additional_attrs) - start_tag = make_start_tag(indent, next_indent, attrs.dup) - - if block - content = block.call(next_indent) - else - content = [] - end - - if content.is_a?(String) - content = [content] - start_tag << ">" - end_tag = "" - else - content = content.reject{|x| x.empty?} - if content.empty? - return "" if attrs.empty? - end_tag = "/>" - else - start_tag << ">\n" - end_tag = "\n#{indent}" - end - end - - start_tag + content.join("\n") + end_tag - end - - def make_start_tag(indent, next_indent, attrs) - start_tag = ["#{indent}<#{full_name}"] - unless attrs.empty? - start_tag << attrs.collect do |key, value| - %Q[#{h key}="#{h value}"] - end.join("\n#{next_indent}") - end - start_tag.join(" ") - end - - def collect_attrs - attrs = {} - _attrs.each do |name, required, alias_name| - value = __send__(alias_name || name) - return nil if required and value.nil? - next if value.nil? - return nil if attrs.has_key?(name) - attrs[name] = value - end - attrs - end - - def tag_name_with_prefix(prefix) - "#{prefix}:#{tag_name}" - end - - # For backward compatibility - def calc_indent - '' - end - - def children - rv = [] - self.class.models.each do |name, uri, occurs, getter| - value = __send__(getter) - next if value.nil? - value = [value] unless value.is_a?(Array) - value.each do |v| - rv << v if v.is_a?(Element) - end - end - rv - end - - def _tags - rv = [] - self.class.models.each do |name, uri, occurs, getter, plural| - value = __send__(getter) - next if value.nil? - if plural and value.is_a?(Array) - rv.concat([[uri, name]] * value.size) - else - rv << [uri, name] - end - end - rv - end - - def _attrs - self.class.get_attributes.collect do |name, uri, required, element_name| - [element_name, required, name] - end - end - - def __validate(ignore_unknown_element, tags=_tags, recursive=true) - if recursive - children.compact.each do |child| - child.validate - end - end - must_call_validators = self.class.must_call_validators - tags = tag_filter(tags.dup) - p tags if DEBUG - must_call_validators.each do |uri, prefix| - _validate(ignore_unknown_element, tags[uri], uri) - meth = "#{prefix}_validate" - if !prefix.empty? and respond_to?(meth, true) - __send__(meth, ignore_unknown_element, tags[uri], uri) - end - end - end - - def validate_attribute - _attrs.each do |a_name, required, alias_name| - value = instance_variable_get("@#{alias_name || a_name}") - if required and value.nil? - raise MissingAttributeError.new(tag_name, a_name) - end - __send__("#{alias_name || a_name}=", value) - end - end - - def _validate(ignore_unknown_element, tags, uri, models=self.class.models) - count = 1 - do_redo = false - not_shift = false - tag = nil - models = models.find_all {|model| model[1] == uri} - element_names = models.collect {|model| model[0]} - if tags - tags_size = tags.size - tags = tags.sort_by {|x| element_names.index(x) || tags_size} - end - - models.each_with_index do |model, i| - name, _, occurs, = model - - if DEBUG - p "before" - p tags - p model - end - - if not_shift - not_shift = false - elsif tags - tag = tags.shift - end - - if DEBUG - p "mid" - p count - end - - case occurs - when '?' - if count > 2 - raise TooMuchTagError.new(name, tag_name) - else - if name == tag - do_redo = true - else - not_shift = true - end - end - when '*' - if name == tag - do_redo = true - else - not_shift = true - end - when '+' - if name == tag - do_redo = true - else - if count > 1 - not_shift = true - else - raise MissingTagError.new(name, tag_name) - end - end - else - if name == tag - if models[i+1] and models[i+1][0] != name and - tags and tags.first == name - raise TooMuchTagError.new(name, tag_name) - end - else - raise MissingTagError.new(name, tag_name) - end - end - - if DEBUG - p "after" - p not_shift - p do_redo - p tag - end - - if do_redo - do_redo = false - count += 1 - redo - else - count = 1 - end - - end - - if !ignore_unknown_element and !tags.nil? and !tags.empty? - raise NotExpectedTagError.new(tags.first, uri, tag_name) - end - - end - - def tag_filter(tags) - rv = {} - tags.each do |tag| - rv[tag[0]] = [] unless rv.has_key?(tag[0]) - rv[tag[0]].push(tag[1]) - end - rv - end - - def empty_content? - false - end - - def content_is_set? - if have_xml_content? - __send__(self.class.xml_getter) - else - content - end - end - - def xmled_content - if have_xml_content? - __send__(self.class.xml_getter).to_s - else - _content = content - _content = [_content].pack("m0") if need_base64_encode? - h(_content) - end - end - end - - module RootElementMixin - - include XMLStyleSheetMixin - - attr_reader :output_encoding - attr_reader :feed_type, :feed_subtype, :feed_version - attr_accessor :version, :encoding, :standalone - def initialize(feed_version, version=nil, encoding=nil, standalone=nil) - super() - @feed_type = nil - @feed_subtype = nil - @feed_version = feed_version - @version = version || '1.0' - @encoding = encoding - @standalone = standalone - @output_encoding = nil - end - - def feed_info - [@feed_type, @feed_version, @feed_subtype] - end - - def output_encoding=(enc) - @output_encoding = enc - self.converter = Converter.new(@output_encoding, @encoding) - end - - def setup_maker(maker) - maker.version = version - maker.encoding = encoding - maker.standalone = standalone - - xml_stylesheets.each do |xss| - xss.setup_maker(maker) - end - - super - end - - def to_feed(type, &block) - Maker.make(type) do |maker| - setup_maker(maker) - block.call(maker) if block - end - end - - def to_rss(type, &block) - to_feed("rss#{type}", &block) - end - - def to_atom(type, &block) - to_feed("atom:#{type}", &block) - end - - def to_xml(type=nil, &block) - if type.nil? or same_feed_type?(type) - to_s - else - to_feed(type, &block).to_s - end - end - - private - def same_feed_type?(type) - if /^(atom|rss)?(\d+\.\d+)?(?::(.+))?$/i =~ type - feed_type = ($1 || @feed_type).downcase - feed_version = $2 || @feed_version - feed_subtype = $3 || @feed_subtype - [feed_type, feed_version, feed_subtype] == feed_info - else - false - end - end - - def tag(indent, attrs={}, &block) - rv = super(indent, ns_declarations.merge(attrs), &block) - return rv if rv.empty? - "#{xmldecl}#{xml_stylesheet_pi}#{rv}" - end - - def xmldecl - rv = %Q[\n" - rv - end - - def ns_declarations - decls = {} - self.class::NSPOOL.collect do |prefix, uri| - prefix = ":#{prefix}" unless prefix.empty? - decls["xmlns#{prefix}"] = uri - end - decls - end - - def maker_target(target) - target - end - end -end diff --git a/ruby/lib/rss/slash.rb b/ruby/lib/rss/slash.rb deleted file mode 100644 index 0055fc9f8..000000000 --- a/ruby/lib/rss/slash.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: false -require 'rss/1.0' - -module RSS - # The prefix for the Slash XML namespace. - SLASH_PREFIX = 'slash' - # The URI of the Slash specification. - SLASH_URI = "http://purl.org/rss/1.0/modules/slash/" - - RDF.install_ns(SLASH_PREFIX, SLASH_URI) - - module SlashModel - extend BaseModel - - ELEMENT_INFOS = \ - [ - ["section"], - ["department"], - ["comments", :positive_integer], - ["hit_parade", :csv_integer], - ] - - class << self - def append_features(klass) - super - - return if klass.instance_of?(Module) - klass.install_must_call_validator(SLASH_PREFIX, SLASH_URI) - ELEMENT_INFOS.each do |name, type, *additional_infos| - full_name = "#{SLASH_PREFIX}_#{name}" - klass.install_text_element(full_name, SLASH_URI, "?", - full_name, type, name) - end - - klass.module_eval do - alias_method(:slash_hit_parades, :slash_hit_parade) - undef_method(:slash_hit_parade) - alias_method(:slash_hit_parade, :slash_hit_parade_content) - end - end - end - end - - class RDF - class Item; include SlashModel; end - end - - SlashModel::ELEMENT_INFOS.each do |name, type| - accessor_base = "#{SLASH_PREFIX}_#{name}" - BaseListener.install_get_text_element(SLASH_URI, name, accessor_base) - end -end diff --git a/ruby/lib/rss/syndication.rb b/ruby/lib/rss/syndication.rb deleted file mode 100644 index 8f9620f9f..000000000 --- a/ruby/lib/rss/syndication.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: false -require "rss/1.0" - -module RSS - # The prefix for the Syndication XML namespace. - SY_PREFIX = 'sy' - # The URI of the Syndication specification. - SY_URI = "http://purl.org/rss/1.0/modules/syndication/" - - RDF.install_ns(SY_PREFIX, SY_URI) - - module SyndicationModel - - extend BaseModel - - ELEMENTS = [] - - def self.append_features(klass) - super - - klass.install_must_call_validator(SY_PREFIX, SY_URI) - klass.module_eval do - [ - ["updatePeriod"], - ["updateFrequency", :positive_integer] - ].each do |name, type| - install_text_element(name, SY_URI, "?", - "#{SY_PREFIX}_#{name}", type, - "#{SY_PREFIX}:#{name}") - end - - %w(updateBase).each do |name| - install_date_element(name, SY_URI, "?", - "#{SY_PREFIX}_#{name}", 'w3cdtf', - "#{SY_PREFIX}:#{name}") - end - end - - klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1) - alias_method(:_sy_updatePeriod=, :sy_updatePeriod=) - def sy_updatePeriod=(new_value) - new_value = new_value.strip - validate_sy_updatePeriod(new_value) if @do_validate - self._sy_updatePeriod = new_value - end - EOC - end - - private - SY_UPDATEPERIOD_AVAILABLE_VALUES = %w(hourly daily weekly monthly yearly) - def validate_sy_updatePeriod(value) # :nodoc: - unless SY_UPDATEPERIOD_AVAILABLE_VALUES.include?(value) - raise NotAvailableValueError.new("updatePeriod", value) - end - end - end - - class RDF - class Channel; include SyndicationModel; end - end - - prefix_size = SY_PREFIX.size + 1 - SyndicationModel::ELEMENTS.uniq! - SyndicationModel::ELEMENTS.each do |full_name| - name = full_name[prefix_size..-1] - BaseListener.install_get_text_element(SY_URI, name, full_name) - end - -end diff --git a/ruby/lib/rss/taxonomy.rb b/ruby/lib/rss/taxonomy.rb deleted file mode 100644 index 50688ee6c..000000000 --- a/ruby/lib/rss/taxonomy.rb +++ /dev/null @@ -1,148 +0,0 @@ -# frozen_string_literal: false -require "rss/1.0" -require_relative "dublincore" - -module RSS - # The prefix for the Taxonomy XML namespace. - TAXO_PREFIX = "taxo" - # The URI for the specification of the Taxonomy XML namespace. - TAXO_URI = "http://purl.org/rss/1.0/modules/taxonomy/" - - RDF.install_ns(TAXO_PREFIX, TAXO_URI) - - # The listing of all the taxonomy elements, with the appropriate namespace. - TAXO_ELEMENTS = [] - - %w(link).each do |name| - full_name = "#{TAXO_PREFIX}_#{name}" - BaseListener.install_get_text_element(TAXO_URI, name, full_name) - TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}" - end - - %w(topic topics).each do |name| - class_name = Utils.to_class_name(name) - BaseListener.install_class_name(TAXO_URI, name, "Taxonomy#{class_name}") - TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}" - end - - module TaxonomyTopicsModel - extend BaseModel - - def self.append_features(klass) - super - - klass.install_must_call_validator(TAXO_PREFIX, TAXO_URI) - %w(topics).each do |name| - klass.install_have_child_element(name, TAXO_URI, "?", - "#{TAXO_PREFIX}_#{name}") - end - end - - class TaxonomyTopics < Element - include RSS10 - - Bag = ::RSS::RDF::Bag - - class << self - def required_prefix - TAXO_PREFIX - end - - def required_uri - TAXO_URI - end - end - - @tag_name = "topics" - - install_have_child_element("Bag", RDF::URI, nil) - install_must_call_validator('rdf', RDF::URI) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.Bag = args[0] - end - self.Bag ||= Bag.new - end - - def full_name - tag_name_with_prefix(TAXO_PREFIX) - end - - def maker_target(target) - target.taxo_topics - end - - def resources - if @Bag - @Bag.lis.collect do |li| - li.resource - end - else - [] - end - end - end - end - - module TaxonomyTopicModel - extend BaseModel - - def self.append_features(klass) - super - var_name = "#{TAXO_PREFIX}_topic" - klass.install_have_children_element("topic", TAXO_URI, "*", var_name) - end - - class TaxonomyTopic < Element - include RSS10 - - include DublinCoreModel - include TaxonomyTopicsModel - - class << self - def required_prefix - TAXO_PREFIX - end - - def required_uri - TAXO_URI - end - end - - @tag_name = "topic" - - install_get_attribute("about", ::RSS::RDF::URI, true, nil, nil, - "#{RDF::PREFIX}:about") - install_text_element("link", TAXO_URI, "?", "#{TAXO_PREFIX}_link") - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.about = args[0] - end - end - - def full_name - tag_name_with_prefix(TAXO_PREFIX) - end - - def maker_target(target) - target.new_taxo_topic - end - end - end - - class RDF - include TaxonomyTopicModel - class Channel - include TaxonomyTopicsModel - end - class Item; include TaxonomyTopicsModel; end - end -end diff --git a/ruby/lib/rss/trackback.rb b/ruby/lib/rss/trackback.rb deleted file mode 100644 index 1a3c3849b..000000000 --- a/ruby/lib/rss/trackback.rb +++ /dev/null @@ -1,291 +0,0 @@ -# frozen_string_literal: false -# This file contains the implementation of trackbacks. It is entirely internal -# and not useful to outside developers. -require 'rss/1.0' -require 'rss/2.0' - -module RSS # :nodoc: all - - TRACKBACK_PREFIX = 'trackback' - TRACKBACK_URI = 'http://madskills.com/public/xml/rss/module/trackback/' - - RDF.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI) - Rss.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI) - - module TrackBackUtils - private - def trackback_validate(ignore_unknown_element, tags, uri) - return if tags.nil? - if tags.find {|tag| tag == "about"} and - !tags.find {|tag| tag == "ping"} - raise MissingTagError.new("#{TRACKBACK_PREFIX}:ping", tag_name) - end - end - end - - module BaseTrackBackModel - - ELEMENTS = %w(ping about) - - def append_features(klass) - super - - unless klass.class == Module - klass.module_eval {include TrackBackUtils} - - klass.install_must_call_validator(TRACKBACK_PREFIX, TRACKBACK_URI) - %w(ping).each do |name| - var_name = "#{TRACKBACK_PREFIX}_#{name}" - klass_name = "TrackBack#{Utils.to_class_name(name)}" - klass.install_have_child_element(name, TRACKBACK_URI, "?", var_name) - klass.module_eval(<<-EOC, __FILE__, __LINE__) - remove_method :#{var_name} - def #{var_name} - @#{var_name} and @#{var_name}.value - end - - remove_method :#{var_name}= - def #{var_name}=(value) - @#{var_name} = Utils.new_with_value_if_need(#{klass_name}, value) - end - EOC - end - - [%w(about s)].each do |name, postfix| - var_name = "#{TRACKBACK_PREFIX}_#{name}" - klass_name = "TrackBack#{Utils.to_class_name(name)}" - klass.install_have_children_element(name, TRACKBACK_URI, "*", - var_name) - klass.module_eval(<<-EOC, __FILE__, __LINE__) - remove_method :#{var_name} - def #{var_name}(*args) - if args.empty? - @#{var_name}.first and @#{var_name}.first.value - else - ret = @#{var_name}.__send__("[]", *args) - if ret.is_a?(Array) - ret.collect {|x| x.value} - else - ret.value - end - end - end - - remove_method :#{var_name}= - remove_method :set_#{var_name} - def #{var_name}=(*args) - if args.size == 1 - item = Utils.new_with_value_if_need(#{klass_name}, args[0]) - @#{var_name}.push(item) - else - new_val = args.last - if new_val.is_a?(Array) - new_val = new_value.collect do |val| - Utils.new_with_value_if_need(#{klass_name}, val) - end - else - new_val = Utils.new_with_value_if_need(#{klass_name}, new_val) - end - @#{var_name}.__send__("[]=", *(args[0..-2] + [new_val])) - end - end - alias set_#{var_name} #{var_name}= - EOC - end - end - end - end - - module TrackBackModel10 - extend BaseModel - extend BaseTrackBackModel - - class TrackBackPing < Element - include RSS10 - - class << self - - def required_prefix - TRACKBACK_PREFIX - end - - def required_uri - TRACKBACK_URI - end - - end - - @tag_name = "ping" - - [ - ["resource", ::RSS::RDF::URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{::RSS::RDF::PREFIX}:#{name}") - end - - alias_method(:value, :resource) - alias_method(:value=, :resource=) - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.resource = args[0] - end - end - - def full_name - tag_name_with_prefix(TRACKBACK_PREFIX) - end - end - - class TrackBackAbout < Element - include RSS10 - - class << self - - def required_prefix - TRACKBACK_PREFIX - end - - def required_uri - TRACKBACK_URI - end - - end - - @tag_name = "about" - - [ - ["resource", ::RSS::RDF::URI, true] - ].each do |name, uri, required| - install_get_attribute(name, uri, required, nil, nil, - "#{::RSS::RDF::PREFIX}:#{name}") - end - - alias_method(:value, :resource) - alias_method(:value=, :resource=) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.resource = args[0] - end - end - - def full_name - tag_name_with_prefix(TRACKBACK_PREFIX) - end - - private - def maker_target(abouts) - abouts.new_about - end - - def setup_maker_attributes(about) - about.resource = self.resource - end - - end - end - - module TrackBackModel20 - extend BaseModel - extend BaseTrackBackModel - - class TrackBackPing < Element - include RSS09 - - @tag_name = "ping" - - content_setup - - class << self - - def required_prefix - TRACKBACK_PREFIX - end - - def required_uri - TRACKBACK_URI - end - - end - - alias_method(:value, :content) - alias_method(:value=, :content=) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.content = args[0] - end - end - - def full_name - tag_name_with_prefix(TRACKBACK_PREFIX) - end - - end - - class TrackBackAbout < Element - include RSS09 - - @tag_name = "about" - - content_setup - - class << self - - def required_prefix - TRACKBACK_PREFIX - end - - def required_uri - TRACKBACK_URI - end - - end - - alias_method(:value, :content) - alias_method(:value=, :content=) - - def initialize(*args) - if Utils.element_initialize_arguments?(args) - super - else - super() - self.content = args[0] - end - end - - def full_name - tag_name_with_prefix(TRACKBACK_PREFIX) - end - - end - end - - class RDF - class Item; include TrackBackModel10; end - end - - class Rss - class Channel - class Item; include TrackBackModel20; end - end - end - - BaseTrackBackModel::ELEMENTS.each do |name| - class_name = Utils.to_class_name(name) - BaseListener.install_class_name(TRACKBACK_URI, name, - "TrackBack#{class_name}") - end - - BaseTrackBackModel::ELEMENTS.collect! {|name| "#{TRACKBACK_PREFIX}_#{name}"} -end diff --git a/ruby/lib/rss/utils.rb b/ruby/lib/rss/utils.rb deleted file mode 100644 index 9203df9a9..000000000 --- a/ruby/lib/rss/utils.rb +++ /dev/null @@ -1,200 +0,0 @@ -# frozen_string_literal: false -module RSS - - ## - # RSS::Utils is a module that holds various utility functions that are used - # across many parts of the rest of the RSS library. Like most modules named - # some variant of 'util', its methods are probably not particularly useful - # to those who aren't developing the library itself. - module Utils - module_function - - # Given a +name+ in a name_with_underscores or a name-with-dashes format, - # returns the CamelCase version of +name+. - # - # If the +name+ is already CamelCased, nothing happens. - # - # Examples: - # - # require 'rss/utils' - # - # RSS::Utils.to_class_name("sample_name") - # # => "SampleName" - # RSS::Utils.to_class_name("with-dashes") - # # => "WithDashes" - # RSS::Utils.to_class_name("CamelCase") - # # => "CamelCase" - def to_class_name(name) - name.split(/[_\-]/).collect do |part| - "#{part[0, 1].upcase}#{part[1..-1]}" - end.join("") - end - - # Returns an array of two elements: the filename where the calling method - # is located, and the line number where it is defined. - # - # Takes an optional argument +i+, which specifies how many callers up the - # stack to look. - # - # Examples: - # - # require 'rss/utils' - # - # def foo - # p RSS::Utils.get_file_and_line_from_caller - # p RSS::Utils.get_file_and_line_from_caller(1) - # end - # - # def bar - # foo - # end - # - # def baz - # bar - # end - # - # baz - # # => ["test.rb", 5] - # # => ["test.rb", 9] - # - # If +i+ is not given, or is the default value of 0, it attempts to figure - # out the correct value. This is useful when in combination with - # instance_eval. For example: - # - # require 'rss/utils' - # - # def foo - # p RSS::Utils.get_file_and_line_from_caller(1) - # end - # - # def bar - # foo - # end - # - # instance_eval <<-RUBY, *RSS::Utils.get_file_and_line_from_caller - # def baz - # bar - # end - # RUBY - # - # baz - # - # # => ["test.rb", 8] - def get_file_and_line_from_caller(i=0) - file, line, = caller[i].split(':') - line = line.to_i - line += 1 if i.zero? - [file, line] - end - - # Takes a string +s+ with some HTML in it, and escapes '&', '"', '<' and '>', by - # replacing them with the appropriate entities. - # - # This method is also aliased to h, for convenience. - # - # Examples: - # - # require 'rss/utils' - # - # RSS::Utils.html_escape("Dungeons & Dragons") - # # => "Dungeons & Dragons" - # RSS::Utils.h(">_>") - # # => ">_>" - def html_escape(s) - s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/ "text/xsl", - "css" => "text/css", - } - - attr_accessor(*ATTRIBUTES) - attr_accessor(:do_validate) - def initialize(*attrs) - if attrs.size == 1 and - (attrs.first.is_a?(Hash) or attrs.first.is_a?(Array)) - attrs = attrs.first - end - @do_validate = true - ATTRIBUTES.each do |attr| - __send__("#{attr}=", nil) - end - vars = ATTRIBUTES.dup - vars.unshift(:do_validate) - attrs.each do |name, value| - if vars.include?(name.to_s) - __send__("#{name}=", value) - end - end - end - - def to_s - rv = "" - if @href - rv << %Q[] - end - rv - end - - remove_method(:href=) - def href=(value) - @href = value - if @href and @type.nil? - @type = guess_type(@href) - end - @href - end - - remove_method(:alternate=) - def alternate=(value) - if value.nil? or /\A(?:yes|no)\z/ =~ value - @alternate = value - else - if @do_validate - args = ["?xml-stylesheet?", %Q[alternate="#{value}"]] - raise NotAvailableValueError.new(*args) - end - end - @alternate - end - - def setup_maker(maker) - xss = maker.xml_stylesheets.new_xml_stylesheet - ATTRIBUTES.each do |attr| - xss.__send__("#{attr}=", __send__(attr)) - end - end - - private - def guess_type(filename) - /\.([^.]+)$/ =~ filename - GUESS_TABLE[$1] - end - - end -end diff --git a/ruby/lib/rss/xml.rb b/ruby/lib/rss/xml.rb deleted file mode 100644 index b74630295..000000000 --- a/ruby/lib/rss/xml.rb +++ /dev/null @@ -1,72 +0,0 @@ -# frozen_string_literal: false -require_relative "utils" - -module RSS - module XML - class Element - include Enumerable - - attr_reader :name, :prefix, :uri, :attributes, :children - def initialize(name, prefix=nil, uri=nil, attributes={}, children=[]) - @name = name - @prefix = prefix - @uri = uri - @attributes = attributes - if children.is_a?(String) or !children.respond_to?(:each) - @children = [children] - else - @children = children - end - end - - def [](name) - @attributes[name] - end - - def []=(name, value) - @attributes[name] = value - end - - def <<(child) - @children << child - end - - def each(&block) - @children.each(&block) - end - - def ==(other) - other.kind_of?(self.class) and - @name == other.name and - @uri == other.uri and - @attributes == other.attributes and - @children == other.children - end - - def to_s - rv = "<#{full_name}" - attributes.each do |key, value| - rv << " #{Utils.html_escape(key)}=\"#{Utils.html_escape(value)}\"" - end - if children.empty? - rv << "/>" - else - rv << ">" - children.each do |child| - rv << child.to_s - end - rv << "" - end - rv - end - - def full_name - if @prefix - "#{@prefix}:#{@name}" - else - @name - end - end - end - end -end diff --git a/ruby/lib/rss/xmlparser.rb b/ruby/lib/rss/xmlparser.rb deleted file mode 100644 index cb2dd2afd..000000000 --- a/ruby/lib/rss/xmlparser.rb +++ /dev/null @@ -1,95 +0,0 @@ -# frozen_string_literal: false -begin - require "xml/parser" -rescue LoadError - require "xmlparser" -end - -begin - require "xml/encoding-ja" -rescue LoadError - require "xmlencoding-ja" - if defined?(Kconv) - module XMLEncoding_ja - class SJISHandler - include Kconv - end - end - end -end - -module XML - class Parser - unless defined?(Error) - # This error is legacy, so we just set it to the new one - Error = ::XMLParserError # :nodoc: - end - end -end - -module RSS - - class REXMLLikeXMLParser < ::XML::Parser - - include ::XML::Encoding_ja - - def listener=(listener) - @listener = listener - end - - def startElement(name, attrs) - @listener.tag_start(name, attrs) - end - - def endElement(name) - @listener.tag_end(name) - end - - def character(data) - @listener.text(data) - end - - def xmlDecl(version, encoding, standalone) - @listener.xmldecl(version, encoding, standalone == 1) - end - - def processingInstruction(target, content) - @listener.instruction(target, content) - end - - end - - class XMLParserParser < BaseParser - - class << self - def listener - XMLParserListener - end - end - - private - def _parse - begin - parser = REXMLLikeXMLParser.new - parser.listener = @listener - parser.parse(@rss) - rescue ::XML::Parser::Error => e - raise NotWellFormedError.new(parser.line){e.message} - end - end - - end - - class XMLParserListener < BaseListener - - include ListenerMixin - - def xmldecl(version, encoding, standalone) - super - # Encoding is converted to UTF-8 when XMLParser parses XML. - @encoding = 'UTF-8' - end - - end - -end diff --git a/ruby/lib/rss/xmlscanner.rb b/ruby/lib/rss/xmlscanner.rb deleted file mode 100644 index 6e3b13d2f..000000000 --- a/ruby/lib/rss/xmlscanner.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: false -require 'xmlscan/scanner' -require 'stringio' - -module RSS - - class XMLScanParser < BaseParser - - class << self - def listener - XMLScanListener - end - end - - private - def _parse - begin - if @rss.is_a?(String) - input = StringIO.new(@rss) - else - input = @rss - end - scanner = XMLScan::XMLScanner.new(@listener) - scanner.parse(input) - rescue XMLScan::Error => e - lineno = e.lineno || scanner.lineno || input.lineno - raise NotWellFormedError.new(lineno){e.message} - end - end - - end - - class XMLScanListener < BaseListener - - include XMLScan::Visitor - include ListenerMixin - - ENTITIES = { - 'lt' => '<', - 'gt' => '>', - 'amp' => '&', - 'quot' => '"', - 'apos' => '\'' - } - - def on_xmldecl_version(str) - @version = str - end - - def on_xmldecl_encoding(str) - @encoding = str - end - - def on_xmldecl_standalone(str) - @standalone = str - end - - def on_xmldecl_end - xmldecl(@version, @encoding, @standalone == "yes") - end - - alias_method(:on_pi, :instruction) - alias_method(:on_chardata, :text) - alias_method(:on_cdata, :text) - - def on_etag(name) - tag_end(name) - end - - def on_entityref(ref) - text(entity(ref)) - end - - def on_charref(code) - text([code].pack('U')) - end - - alias_method(:on_charref_hex, :on_charref) - - def on_stag(name) - @attrs = {} - end - - def on_attribute(name) - @attrs[name] = @current_attr = '' - end - - def on_attr_value(str) - @current_attr << str - end - - def on_attr_entityref(ref) - @current_attr << entity(ref) - end - - def on_attr_charref(code) - @current_attr << [code].pack('U') - end - - alias_method(:on_attr_charref_hex, :on_attr_charref) - - def on_stag_end(name) - tag_start(name, @attrs) - end - - def on_stag_end_empty(name) - tag_start(name, @attrs) - tag_end(name) - end - - private - def entity(ref) - ent = ENTITIES[ref] - if ent - ent - else - wellformed_error("undefined entity: #{ref}") - end - end - end - -end diff --git a/ruby/lib/ruby2_keywords.gemspec b/ruby/lib/ruby2_keywords.gemspec new file mode 100644 index 000000000..e2cd39753 --- /dev/null +++ b/ruby/lib/ruby2_keywords.gemspec @@ -0,0 +1,23 @@ +_VERSION = "0.0.5" +abort "Version must not reach 1" if _VERSION[/\d+/].to_i >= 1 + +Gem::Specification.new do |s| + s.name = "ruby2_keywords" + s.version = _VERSION + s.summary = "Shim library for Module#ruby2_keywords" + s.homepage = "https://github.com/ruby/ruby2_keywords" + s.licenses = ["Ruby", "BSD-2-Clause"] + s.authors = ["Nobuyoshi Nakada"] + s.require_paths = ["lib"] + s.rdoc_options = ["--main", "README.md"] + s.extra_rdoc_files = [ + "LICENSE", + "README.md", + "ChangeLog", + *Dir.glob("#{__dir__}/logs/ChangeLog-*[^~]").map {|path| path[(__dir__.size+1)..-1]}, + ] + s.files = [ + "lib/ruby2_keywords.rb", + ] + s.required_ruby_version = '>= 2.0.0' +end diff --git a/ruby/lib/rubygems.rb b/ruby/lib/rubygems.rb index 57cb70cc2..ee22e5405 100644 --- a/ruby/lib/rubygems.rb +++ b/ruby/lib/rubygems.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# -*- ruby -*- #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. @@ -9,15 +8,15 @@ require 'rbconfig' module Gem - VERSION = "3.1.2".freeze + VERSION = "3.3.7".freeze end # Must be first since it unloads the prelude from 1.9.2 -require 'rubygems/compatibility' +require_relative 'rubygems/compatibility' -require 'rubygems/defaults' -require 'rubygems/deprecate' -require 'rubygems/errors' +require_relative 'rubygems/defaults' +require_relative 'rubygems/deprecate' +require_relative 'rubygems/errors' ## # RubyGems is the Ruby standard for publishing and managing third party @@ -26,27 +25,27 @@ module Gem # For user documentation, see: # # * gem help and gem help [command] -# * {RubyGems User Guide}[http://guides.rubygems.org/] -# * {Frequently Asked Questions}[http://guides.rubygems.org/faqs] +# * {RubyGems User Guide}[https://guides.rubygems.org/] +# * {Frequently Asked Questions}[https://guides.rubygems.org/faqs] # # For gem developer documentation see: # -# * {Creating Gems}[http://guides.rubygems.org/make-your-own-gem] +# * {Creating Gems}[https://guides.rubygems.org/make-your-own-gem] # * Gem::Specification # * Gem::Version for version dependency notes # # Further RubyGems documentation can be found at: # -# * {RubyGems Guides}[http://guides.rubygems.org] -# * {RubyGems API}[http://www.rubydoc.info/github/rubygems/rubygems] (also available from +# * {RubyGems Guides}[https://guides.rubygems.org] +# * {RubyGems API}[https://www.rubydoc.info/github/rubygems/rubygems] (also available from # gem server) # # == RubyGems Plugins # -# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or +# RubyGems will load plugins in the latest version of each installed gem or # $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and -# placed at the root of your gem's #require_path. Plugins are discovered via -# Gem::find_files and then loaded. +# placed at the root of your gem's #require_path. Plugins are installed at a +# special location and loaded on boot. # # For an example plugin, see the {Graph gem}[https://github.com/seattlerb/graph] # which adds a `gem graph` command. @@ -120,6 +119,10 @@ module Gem # to avoid deprecation warnings in Ruby 2.7. UNTAINT = RUBY_VERSION < '2.7' ? :untaint.to_sym : proc{} + # When https://bugs.ruby-lang.org/issues/17259 is available, there is no need to override Kernel#warn + KERNEL_WARN_IGNORES_INTERNAL_ENTRIES = RUBY_ENGINE == "truffleruby" || + (RUBY_ENGINE == "ruby" && RUBY_VERSION >= '3.0') + ## # An Array of Regexps that match windows Ruby platforms. @@ -148,6 +151,7 @@ module Gem doc extensions gems + plugins specifications ].freeze @@ -159,22 +163,12 @@ module Gem specifications/default ].freeze - ## - # Exception classes used in a Gem.read_binary +rescue+ statement - - READ_BINARY_ERRORS = [Errno::EACCES, Errno::EROFS, Errno::ENOSYS, Errno::ENOTSUP].freeze - - ## - # Exception classes used in Gem.write_binary +rescue+ statement - - WRITE_BINARY_ERRORS = [Errno::ENOSYS, Errno::ENOTSUP].freeze - @@win_platform = nil @configuration = nil @gemdeps = nil @loaded_specs = {} - LOADED_SPECS_MUTEX = Mutex.new + LOADED_SPECS_MUTEX = Thread::Mutex.new @path_to_default_spec_map = {} @platforms = [] @ruby = nil @@ -189,6 +183,8 @@ module Gem @pre_reset_hooks ||= [] @post_reset_hooks ||= [] + @default_source_date_epoch = nil + ## # Try to activate a gem containing +path+. Returns true if # activation succeeded or wasn't needed because it was already @@ -243,9 +239,6 @@ def self.finish_resolve(request_set=Gem::RequestSet.new) # you to specify specific gem versions. def self.bin_path(name, exec_name = nil, *requirements) - # TODO: fails test_self_bin_path_bin_file_gone_in_latest - # Gem::Specification.find_by_name(name, *requirements).bin_file exec_name - requirements = Gem::Requirement.default if requirements.empty? @@ -269,9 +262,6 @@ def self.find_spec_for_exe(name, exec_name, requirements) unless spec = specs.first msg = "can't find gem #{dep} with executable #{exec_name}" - if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message - msg = bundler_message - end raise Gem::GemNotFoundException, msg end @@ -315,6 +305,13 @@ def self.bindir(install_dir=Gem.dir) Gem.default_bindir end + ## + # The path were rubygems plugins are to be installed. + + def self.plugindir(install_dir=Gem.dir) + File.join install_dir, 'plugins' + end + ## # Reset the +dir+ and +path+ values. The next time +dir+ or +path+ # is requested, the values will be calculated from scratch. This is @@ -327,13 +324,6 @@ def self.clear_paths Gem::Security.reset if defined?(Gem::Security) end - ## - # The path to standard location of the user's .gemrc file. - - def self.config_file - @config_file ||= File.join Gem.user_home, '.gemrc' - end - ## # The standard configuration object for gems. @@ -391,11 +381,11 @@ def self.paths=(env) target[k] = v when Array unless Gem::Deprecate.skip - warn <<-eowarn + warn <<-EOWARN Array values in the parameter to `Gem.paths=` are deprecated. Please use a String or nil. An Array (#{env.inspect}) was passed in from #{caller[3]} - eowarn + EOWARN end target[k] = v.join File::PATH_SEPARATOR end @@ -409,8 +399,6 @@ def self.paths=(env) ## # The path where gems are to be installed. - #-- - # FIXME deprecate these once everything else has been done -ebh def self.dir paths.home @@ -463,7 +451,10 @@ def self.ensure_subdirectories(dir, mode, subdirs) # :nodoc: subdirs.each do |name| subdir = File.join dir, name next if File.exist? subdir - FileUtils.mkdir_p subdir, **options rescue nil + begin + FileUtils.mkdir_p subdir, **options + rescue SystemCallError + end end ensure File.umask old_umask @@ -500,7 +491,7 @@ def self.find_files(glob, check_load_path=true) gem_specifications = @gemdeps ? Gem.loaded_specs.values : Gem::Specification.stubs - files.concat gem_specifications.map { |spec| + files.concat gem_specifications.map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten @@ -515,7 +506,7 @@ def self.find_files_from_load_path(glob) # :nodoc: glob_with_suffixes = "#{glob}#{Gem.suffix_pattern}" $LOAD_PATH.map do |load_path| Gem::Util.glob_files_in_dir(glob_with_suffixes, load_path) - end.flatten.select { |file| File.file? file.tap(&Gem::UNTAINT) } + end.flatten.select {|file| File.file? file.tap(&Gem::UNTAINT) } end ## @@ -535,7 +526,7 @@ def self.find_latest_files(glob, check_load_path=true) files = find_files_from_load_path glob if check_load_path - files.concat Gem::Specification.latest_specs(true).map { |spec| + files.concat Gem::Specification.latest_specs(true).map {|spec| spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}") }.flatten @@ -546,87 +537,16 @@ def self.find_latest_files(glob, check_load_path=true) return files end - ## - # Finds the user's home directory. - #-- - # Some comments from the ruby-talk list regarding finding the home - # directory: - # - # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems - # to be depending on HOME in those code samples. I propose that - # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at - # least on Win32). - #++ - #-- - # - #++ - - def self.find_home - Dir.home.dup - rescue - if Gem.win_platform? - File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/') - else - File.expand_path "/" - end - end - - private_class_method :find_home - - # TODO: remove in RubyGems 4.0 - - ## - # Zlib::GzipReader wrapper that unzips +data+. - - def self.gunzip(data) - Gem::Util.gunzip data - end - - class << self - - extend Gem::Deprecate - deprecate :gunzip, "Gem::Util.gunzip", 2018, 12 - - end - - ## - # Zlib::GzipWriter wrapper that zips +data+. - - def self.gzip(data) - Gem::Util.gzip data - end - - class << self - - extend Gem::Deprecate - deprecate :gzip, "Gem::Util.gzip", 2018, 12 - - end - - ## - # A Zlib::Inflate#inflate wrapper - - def self.inflate(data) - Gem::Util.inflate data - end - - class << self - - extend Gem::Deprecate - deprecate :inflate, "Gem::Util.inflate", 2018, 12 - - end - ## # Top level install helper method. Allows you to install gems interactively: # # % irb # >> Gem.install "minitest" - # Fetching: minitest-3.0.1.gem (100%) + # Fetching: minitest-5.14.0.gem (100%) # => [#] def self.install(name, version = Gem::Requirement.default, *options) - require "rubygems/dependency_installer" + require_relative "rubygems/dependency_installer" inst = Gem::DependencyInstaller.new(*options) inst.install name, version inst.installed_gems @@ -657,22 +577,25 @@ def self.load_path_insert_index index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir'] - index + index || 0 + end + + ## + # The number of paths in the `$LOAD_PATH` from activated gems. Used to + # prioritize `-I` and `ENV['RUBYLIB`]` entries during `require`. + + def self.activated_gem_paths + @activated_gem_paths ||= 0 end ## # Add a list of paths to the $LOAD_PATH at the proper place. def self.add_to_load_path(*paths) - insert_index = load_path_insert_index + @activated_gem_paths = activated_gem_paths + paths.size - if insert_index - # gem directories must come after -I and ENV['RUBYLIB'] - $LOAD_PATH.insert(insert_index, *paths) - else - # we are probably testing in core, -I and RUBYLIB don't apply - $LOAD_PATH.unshift(*paths) - end + # gem directories must come after -I and ENV['RUBYLIB'] + $LOAD_PATH.insert(Gem.load_path_insert_index, *paths) end @yaml_loaded = false @@ -682,37 +605,12 @@ def self.add_to_load_path(*paths) def self.load_yaml return if @yaml_loaded - return unless defined?(gem) - - begin - gem 'psych', '>= 2.0.0' - rescue Gem::LoadError - # It's OK if the user does not have the psych gem installed. We will - # attempt to require the stdlib version - end - begin - # Try requiring the gem version *or* stdlib version of psych. - require 'psych' - rescue ::LoadError - # If we can't load psych, thats fine, go on. - else - # If 'yaml' has already been required, then we have to - # be sure to switch it over to the newly loaded psych. - if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych" - YAML::ENGINE.yamler = "psych" - end + require 'psych' + require_relative 'rubygems/psych_additions' + require_relative 'rubygems/psych_tree' - require 'rubygems/psych_additions' - require 'rubygems/psych_tree' - end - - require 'yaml' - require 'rubygems/safe_yaml' - - # Now that we're sure some kind of yaml library is loaded, pull - # in our hack to deal with Syck's DefaultKey ugliness. - require 'rubygems/syck_hack' + require_relative 'rubygems/safe_yaml' @yaml_loaded = true end @@ -861,40 +759,42 @@ def self.refresh # Safely read a file in binary mode on all platforms. def self.read_binary(path) - File.open path, 'rb+' do |f| - f.flock(File::LOCK_EX) - f.read + open_file(path, 'rb+') do |io| + io.read end - rescue *READ_BINARY_ERRORS - File.open path, 'rb' do |f| - f.read - end - rescue Errno::ENOLCK # NFS - if Thread.main != Thread.current - raise - else - File.open path, 'rb' do |f| - f.read - end + rescue Errno::EACCES, Errno::EROFS + open_file(path, 'rb') do |io| + io.read end end ## # Safely write a file in binary mode on all platforms. def self.write_binary(path, data) - open(path, 'wb') do |io| - begin - io.flock(File::LOCK_EX) - rescue *WRITE_BINARY_ERRORS - end + open_file(path, 'wb') do |io| io.write data end + end + + ## + # Open a file with given flags, and on Windows protect access with flock + + def self.open_file(path, flags, &block) + File.open(path, flags) do |io| + if !java_platform? && win_platform? + begin + io.flock(File::LOCK_EX) + rescue Errno::ENOSYS, Errno::ENOTSUP + end + end + yield io + end rescue Errno::ENOLCK # NFS if Thread.main != Thread.current raise else - open(path, 'wb') do |io| - io.write data + File.open(path, flags) do |io| + yield io end end end @@ -904,8 +804,7 @@ def self.write_binary(path, data) def self.ruby if @ruby.nil? - @ruby = File.join(RbConfig::CONFIG['bindir'], - "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}") + @ruby = RbConfig.ruby @ruby = "\"#{@ruby}\"" if @ruby =~ /\s/ end @@ -937,7 +836,7 @@ def self.latest_spec_for(name) fetcher = Gem::SpecFetcher.fetcher spec_tuples, = fetcher.spec_for_dependency dependency - spec, = spec_tuples.first + spec, = spec_tuples.last spec end @@ -1018,21 +917,38 @@ def self.suffix_pattern @suffix_pattern ||= "{#{suffixes.join(',')}}" end + ## + # Regexp for require-able path suffixes. + def self.suffix_regexp @suffix_regexp ||= /#{Regexp.union(suffixes)}\z/ end + ## + # Glob pattern for require-able plugin suffixes. + + def self.plugin_suffix_pattern + @plugin_suffix_pattern ||= "_plugin#{suffix_pattern}" + end + + ## + # Regexp for require-able plugin suffixes. + + def self.plugin_suffix_regexp + @plugin_suffix_regexp ||= /_plugin#{suffix_regexp}\z/ + end + ## # Suffixes for require-able paths. def self.suffixes @suffixes ||= ['', '.rb', - *%w(DLEXT DLEXT2).map do |key| + *%w[DLEXT DLEXT2].map do |key| val = RbConfig::CONFIG[key] next unless val and not val.empty? ".#{val}" - end + end, ].compact.uniq end @@ -1056,7 +972,7 @@ def self.time(msg, width = 0, display = Gem.configuration.verbose) # Lazily loads DefaultUserInteraction and returns the default UI. def self.ui - require 'rubygems/user_interaction' + require_relative 'rubygems/user_interaction' Gem::DefaultUserInteraction.ui end @@ -1069,24 +985,17 @@ def self.use_paths(home, *paths) paths.flatten! paths.compact! hash = { "GEM_HOME" => home, "GEM_PATH" => paths.empty? ? home : paths.join(File::PATH_SEPARATOR) } - hash.delete_if { |_, v| v.nil? } + hash.delete_if {|_, v| v.nil? } self.paths = hash end - ## - # The home directory for the user. - - def self.user_home - @user_home ||= find_home.tap(&Gem::UNTAINT) - end - ## # Is this a windows platform? def self.win_platform? if @@win_platform.nil? ruby_platform = RbConfig::CONFIG['host_os'] - @@win_platform = !!WIN_PATTERNS.find { |r| ruby_platform =~ r } + @@win_platform = !!WIN_PATTERNS.find {|r| ruby_platform =~ r } end @@win_platform @@ -1099,6 +1008,13 @@ def self.java_platform? RUBY_PLATFORM == "java" end + ## + # Is this platform Solaris? + + def self.solaris_platform? + RUBY_PLATFORM =~ /solaris/ + end + ## # Load +plugins+ as Ruby files @@ -1120,15 +1036,11 @@ def self.load_plugin_files(plugins) # :nodoc: end ## - # Find the 'rubygems_plugin' files in the latest installed gems and load - # them + # Find rubygems plugin files in the standard location and load them def self.load_plugins - # Remove this env var by at least 3.0 - if ENV['RUBYGEMS_LOAD_ALL_PLUGINS'] - load_plugin_files find_files('rubygems_plugin', false) - else - load_plugin_files find_latest_files('rubygems_plugin', false) + Gem.path.each do |gem_path| + load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir(gem_path)) end end @@ -1136,19 +1048,7 @@ def self.load_plugins # Find all 'rubygems_plugin' files in $LOAD_PATH and load them def self.load_env_plugins - path = "rubygems_plugin" - - files = [] - glob = "#{path}#{Gem.suffix_pattern}" - $LOAD_PATH.each do |load_path| - globbed = Gem::Util.glob_files_in_dir(glob, load_path) - - globbed.each do |load_path_file| - files << load_path_file if File.file?(load_path_file.tap(&Gem::UNTAINT)) - end - end - - load_plugin_files files + load_plugin_files find_files_from_load_path("rubygems_plugin") end ## @@ -1181,7 +1081,7 @@ def self.use_gemdeps(path = nil) if path == "-" Gem::Util.traverse_parents Dir.pwd do |directory| - dep_file = GEM_DEP_FILES.find { |f| File.file?(f) } + dep_file = GEM_DEP_FILES.find {|f| File.file?(f) } next unless dep_file @@ -1199,63 +1099,74 @@ def self.use_gemdeps(path = nil) end ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path) - require 'rubygems/user_interaction' - Gem::DefaultUserInteraction.use_ui(ui) do - require "bundler" - begin - Bundler.ui.silence do - @gemdeps = Bundler.setup + require_relative 'rubygems/user_interaction' + require "bundler" + begin + Gem::DefaultUserInteraction.use_ui(ui) do + begin + Bundler.ui.silence do + @gemdeps = Bundler.setup + end + ensure + Gem::DefaultUserInteraction.ui.close end - ensure - Gem::DefaultUserInteraction.ui.close end - @gemdeps.requested_specs.map(&:to_spec).sort_by(&:name) - end - - rescue => e - case e - when Gem::LoadError, Gem::UnsatisfiableDependencyError, (defined?(Bundler::GemNotFound) ? Bundler::GemNotFound : Gem::LoadError) + rescue Bundler::BundlerError => e warn e.message - warn "You may need to `gem install -g` to install missing gems" + warn "You may need to `bundle install` to install missing gems" warn "" - else - raise end end - class << self + ## + # If the SOURCE_DATE_EPOCH environment variable is set, returns it's value. + # Otherwise, returns the time that `Gem.source_date_epoch_string` was + # first called in the same format as SOURCE_DATE_EPOCH. + # + # NOTE(@duckinator): The implementation is a tad weird because we want to: + # 1. Make builds reproducible by default, by having this function always + # return the same result during a given run. + # 2. Allow changing ENV['SOURCE_DATE_EPOCH'] at runtime, since multiple + # tests that set this variable will be run in a single process. + # + # If you simplify this function and a lot of tests fail, that is likely + # due to #2 above. + # + # Details on SOURCE_DATE_EPOCH: + # https://reproducible-builds.org/specs/source-date-epoch/ - ## - # TODO remove with RubyGems 4.0 + def self.source_date_epoch_string + # The value used if $SOURCE_DATE_EPOCH is not set. + @default_source_date_epoch ||= Time.now.to_i.to_s - alias detect_gemdeps use_gemdeps # :nodoc: + specified_epoch = ENV["SOURCE_DATE_EPOCH"] - extend Gem::Deprecate - deprecate :detect_gemdeps, "Gem.use_gemdeps", 2018, 12 + # If it's empty or just whitespace, treat it like it wasn't set at all. + specified_epoch = nil if !specified_epoch.nil? && specified_epoch.strip.empty? + epoch = specified_epoch || @default_source_date_epoch + + epoch.strip end ## - # The SOURCE_DATE_EPOCH environment variable (or, if that's not set, the current time), converted to Time object. - # This is used throughout RubyGems for enabling reproducible builds. - # - # If it is not set as an environment variable already, this also sets it. + # Returns the value of Gem.source_date_epoch_string, as a Time object. # - # Details on SOURCE_DATE_EPOCH: - # https://reproducible-builds.org/specs/source-date-epoch/ + # This is used throughout RubyGems for enabling reproducible builds. def self.source_date_epoch - if ENV["SOURCE_DATE_EPOCH"].nil? || ENV["SOURCE_DATE_EPOCH"].empty? - ENV["SOURCE_DATE_EPOCH"] = Time.now.to_i.to_s - end - - Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc.freeze + Time.at(self.source_date_epoch_string.to_i).utc.freeze end # FIX: Almost everywhere else we use the `def self.` way of defining class # methods, and then we switch over to `class << self` here. Pick one or the # other. class << self + ## + # RubyGems distributors (like operating system package managers) can + # disable RubyGems update by setting this to error message printed to + # end-users on gem update --system instead of actual update. + attr_accessor :disable_system_update_message ## # Hash of loaded Gem::Specification keyed by name @@ -1281,10 +1192,11 @@ class << self # def register_default_spec(spec) - new_format = spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } + extended_require_paths = spec.require_paths.map {|f| f + "/" } + new_format = extended_require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } if new_format - prefix_group = spec.require_paths.map {|f| f + "/"}.join("|") + prefix_group = extended_require_paths.join("|") prefix_pattern = /^(#{prefix_group})/ end @@ -1294,6 +1206,8 @@ def register_default_spec(spec) next unless $~ end + spec.activate if already_loaded?(file) + @path_to_default_spec_map[file] = spec @path_to_default_spec_map[file.sub(suffix_regexp, "")] = spec end @@ -1359,6 +1273,22 @@ def clear_default_specs attr_reader :pre_uninstall_hooks + private + + def already_loaded?(file) + $LOADED_FEATURES.any? do |feature_path| + feature_path.end_with?(file) && default_gem_load_paths.any? {|load_path_entry| feature_path == "#{load_path_entry}/#{file}" } + end + end + + def default_gem_load_paths + @default_gem_load_paths ||= $LOAD_PATH[load_path_insert_index..-1].map do |lp| + expanded = File.expand_path(lp) + next expanded unless File.exist?(expanded) + + File.realpath(expanded) + end + end end ## @@ -1366,28 +1296,26 @@ def clear_default_specs MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze - autoload :BundlerVersionFinder, 'rubygems/bundler_version_finder' - autoload :ConfigFile, 'rubygems/config_file' - autoload :Dependency, 'rubygems/dependency' - autoload :DependencyList, 'rubygems/dependency_list' - autoload :Installer, 'rubygems/installer' - autoload :Licenses, 'rubygems/util/licenses' - autoload :PathSupport, 'rubygems/path_support' - autoload :Platform, 'rubygems/platform' - autoload :RequestSet, 'rubygems/request_set' - autoload :Requirement, 'rubygems/requirement' - autoload :Resolver, 'rubygems/resolver' - autoload :Source, 'rubygems/source' - autoload :SourceList, 'rubygems/source_list' - autoload :SpecFetcher, 'rubygems/spec_fetcher' - autoload :Specification, 'rubygems/specification' - autoload :Util, 'rubygems/util' - autoload :Version, 'rubygems/version' - - require "rubygems/specification" + autoload :BundlerVersionFinder, File.expand_path('rubygems/bundler_version_finder', __dir__) + autoload :ConfigFile, File.expand_path('rubygems/config_file', __dir__) + autoload :Dependency, File.expand_path('rubygems/dependency', __dir__) + autoload :DependencyList, File.expand_path('rubygems/dependency_list', __dir__) + autoload :Installer, File.expand_path('rubygems/installer', __dir__) + autoload :Licenses, File.expand_path('rubygems/util/licenses', __dir__) + autoload :NameTuple, File.expand_path('rubygems/name_tuple', __dir__) + autoload :PathSupport, File.expand_path('rubygems/path_support', __dir__) + autoload :RequestSet, File.expand_path('rubygems/request_set', __dir__) + autoload :Resolver, File.expand_path('rubygems/resolver', __dir__) + autoload :Source, File.expand_path('rubygems/source', __dir__) + autoload :SourceList, File.expand_path('rubygems/source_list', __dir__) + autoload :SpecFetcher, File.expand_path('rubygems/spec_fetcher', __dir__) + autoload :SpecificationPolicy, File.expand_path('rubygems/specification_policy', __dir__) + autoload :Util, File.expand_path('rubygems/util', __dir__) + autoload :Version, File.expand_path('rubygems/version', __dir__) end -require 'rubygems/exceptions' +require_relative 'rubygems/exceptions' +require_relative 'rubygems/specification' # REFACTOR: This should be pulled out into some kind of hacks file. begin @@ -1396,6 +1324,14 @@ def clear_default_specs require 'rubygems/defaults/operating_system' rescue LoadError + # Ignored +rescue StandardError => e + msg = "#{e.message}\n" \ + "Loading the rubygems/defaults/operating_system.rb file caused an error. " \ + "This file is owned by your OS, not by rubygems upstream. " \ + "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \ + "the problem and ask for help." + raise e.class, msg end begin @@ -1410,8 +1346,6 @@ def clear_default_specs # Loads the default specs. Gem::Specification.load_defaults -require 'rubygems/core_ext/kernel_gem' -require 'rubygems/core_ext/kernel_require' -require 'rubygems/core_ext/kernel_warn' - -Gem.use_gemdeps +require_relative 'rubygems/core_ext/kernel_gem' +require_relative 'rubygems/core_ext/kernel_require' +require_relative 'rubygems/core_ext/kernel_warn' diff --git a/ruby/lib/rubygems/available_set.rb b/ruby/lib/rubygems/available_set.rb index 2e9d9496f..499483d9e 100644 --- a/ruby/lib/rubygems/available_set.rb +++ b/ruby/lib/rubygems/available_set.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true class Gem::AvailableSet - include Enumerable Tuple = Struct.new(:spec, :source) @@ -70,11 +69,11 @@ def empty? end def all_specs - @set.map { |t| t.spec } + @set.map {|t| t.spec } end def match_platform! - @set.reject! { |t| !Gem::Platform.match(t.spec.platform) } + @set.reject! {|t| !Gem::Platform.match_spec?(t.spec) } @sorted = nil self end @@ -91,7 +90,7 @@ def size end def source_for(spec) - f = @set.find { |t| t.spec == spec } + f = @set.find {|t| t.spec == spec } f.source end @@ -160,7 +159,6 @@ def remove_installed!(dep) end def inject_into_list(dep_list) - @set.each { |t| dep_list.add t.spec } + @set.each {|t| dep_list.add t.spec } end - end diff --git a/ruby/lib/rubygems/basic_specification.rb b/ruby/lib/rubygems/basic_specification.rb index c6d63ac47..b3b63b51a 100644 --- a/ruby/lib/rubygems/basic_specification.rb +++ b/ruby/lib/rubygems/basic_specification.rb @@ -4,7 +4,6 @@ # used by both Specification and StubSpecification. class Gem::BasicSpecification - ## # Allows installation of extensions for git: gems. @@ -39,10 +38,8 @@ def self.default_specifications_dir end class << self - extend Gem::Deprecate - deprecate :default_specifications_dir, "Gem.default_specifications_dir", 2020, 02 - + rubygems_deprecate :default_specifications_dir, "Gem.default_specifications_dir" end ## @@ -78,7 +75,7 @@ def contains_requirable_file?(file) elsif missing_extensions? @ignored = true - if RUBY_ENGINE == platform || Gem::Platform.local === platform + if Gem::Platform::RUBY == platform || Gem::Platform.local === platform warn "Ignoring #{full_name} because its extensions are not built. " + "Try: gem pristine #{name} --version #{version}" end @@ -274,10 +271,16 @@ def source_paths # Return all files in this gem that match for +glob+. def matches_for_glob(glob) # TODO: rename? - # TODO: do we need these?? Kill it glob = File.join(self.lib_dirs_glob, glob) - Dir[glob].map { |f| f.tap(&Gem::UNTAINT) } # FIX our tests are broken, run w/ SAFE=1 + Dir[glob].map {|f| f.tap(&Gem::UNTAINT) } # FIX our tests are broken, run w/ SAFE=1 + end + + ## + # Returns the list of plugins in this spec. + + def plugins + matches_for_glob("rubygems#{Gem.plugin_suffix_pattern}") end ## @@ -286,14 +289,14 @@ def matches_for_glob(glob) # TODO: rename? def lib_dirs_glob dirs = if self.raw_require_paths - if self.raw_require_paths.size > 1 - "{#{self.raw_require_paths.join(',')}}" - else - self.raw_require_paths.first - end - else - "lib" # default value for require_paths for bundler/inline - end + if self.raw_require_paths.size > 1 + "{#{self.raw_require_paths.join(',')}}" + else + self.raw_require_paths.first + end + else + "lib" # default value for require_paths for bundler/inline + end "#{self.full_gem_path}/#{dirs}".dup.tap(&Gem::UNTAINT) end @@ -329,15 +332,14 @@ def have_extensions?; !extensions.empty?; end def have_file?(file, suffixes) return true if raw_require_paths.any? do |path| base = File.join(gems_dir, full_name, path.tap(&Gem::UNTAINT), file).tap(&Gem::UNTAINT) - suffixes.any? { |suf| File.file? base + suf } + suffixes.any? {|suf| File.file? base + suf } end if have_extensions? base = File.join extension_dir, file - suffixes.any? { |suf| File.file? base + suf } + suffixes.any? {|suf| File.file? base + suf } else false end end - end diff --git a/ruby/lib/rubygems/bundler_version_finder.rb b/ruby/lib/rubygems/bundler_version_finder.rb index 38da7738a..f6fad0bd8 100644 --- a/ruby/lib/rubygems/bundler_version_finder.rb +++ b/ruby/lib/rubygems/bundler_version_finder.rb @@ -1,52 +1,20 @@ # frozen_string_literal: true -require "rubygems/util" - module Gem::BundlerVersionFinder def self.bundler_version - version, _ = bundler_version_with_reason - - return unless version + v = ENV["BUNDLER_VERSION"] - Gem::Version.new(version) - end + v ||= bundle_update_bundler_version + return if v == true - def self.bundler_version_with_reason - if v = ENV["BUNDLER_VERSION"] - return [v, "`$BUNDLER_VERSION`"] - end - if v = bundle_update_bundler_version - return if v == true - return [v, "`bundle update --bundler`"] - end - v, lockfile = lockfile_version - if v - return [v, "your #{lockfile}"] - end - end + v ||= lockfile_version + return unless v - def self.missing_version_message - return unless vr = bundler_version_with_reason - <<-EOS -Could not find 'bundler' (#{vr.first}) required by #{vr.last}. -To update to the latest version installed on your system, run `bundle update --bundler`. -To install the missing version, run `gem install bundler:#{vr.first}` - EOS + Gem::Version.new(v) end - def self.compatible?(spec) - return true unless spec.name == "bundler".freeze - return true unless bundler_version = self.bundler_version - - spec.version.segments.first == bundler_version.segments.first - end - - def self.filter!(specs) - return unless bundler_version = self.bundler_version - - specs.reject! { |spec| spec.version.segments.first != bundler_version.segments.first } - - exact_match_index = specs.find_index { |spec| spec.version == bundler_version } + def self.prioritize!(specs) + exact_match_index = specs.find_index {|spec| spec.version == bundler_version } return unless exact_match_index specs.unshift(specs.delete_at(exact_match_index)) @@ -70,35 +38,40 @@ def self.bundle_update_bundler_version private_class_method :bundle_update_bundler_version def self.lockfile_version - return unless lockfile = lockfile_contents - lockfile, contents = lockfile - lockfile ||= "lockfile" + return unless contents = lockfile_contents regexp = /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ return unless contents =~ regexp - [$1, lockfile] + $1 end private_class_method :lockfile_version def self.lockfile_contents gemfile = ENV["BUNDLE_GEMFILE"] gemfile = nil if gemfile && gemfile.empty? - Gem::Util.traverse_parents Dir.pwd do |directory| - next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.tap(&Gem::UNTAINT)) } - gemfile = File.join directory, gemfile - break - end unless gemfile + unless gemfile + begin + Gem::Util.traverse_parents(Dir.pwd) do |directory| + next unless gemfile = Gem::GEM_DEP_FILES.find {|f| File.file?(f.tap(&Gem::UNTAINT)) } + + gemfile = File.join directory, gemfile + break + end + rescue Errno::ENOENT + return + end + end return unless gemfile lockfile = case gemfile - when "gems.rb" then "gems.locked" - else "#{gemfile}.lock" - end.dup.tap(&Gem::UNTAINT) + when "gems.rb" then "gems.locked" + else "#{gemfile}.lock" + end.dup.tap(&Gem::UNTAINT) return unless File.file?(lockfile) - [lockfile, File.read(lockfile)] + File.read(lockfile) end private_class_method :lockfile_contents end diff --git a/ruby/lib/rubygems/command.rb b/ruby/lib/rubygems/command.rb index c1e5e13c5..f74cb419f 100644 --- a/ruby/lib/rubygems/command.rb +++ b/ruby/lib/rubygems/command.rb @@ -5,9 +5,9 @@ # See LICENSE.txt for permissions. #++ -require 'optparse' -require 'rubygems/requirement' -require 'rubygems/user_interaction' +require_relative 'optparse' +require_relative 'requirement' +require_relative 'user_interaction' ## # Base class for all Gem commands. When creating a new gem command, define @@ -17,10 +17,9 @@ # A very good example to look at is Gem::Commands::ContentsCommand class Gem::Command - include Gem::UserInteraction - OptionParser.accept Symbol do |value| + Gem::OptionParser.accept Symbol do |value| value.to_sym end @@ -77,7 +76,7 @@ def self.extra_args=(value) when Array @extra_args = value when String - @extra_args = value.split + @extra_args = value.split(' ') end end @@ -125,7 +124,7 @@ def initialize(command, summary=nil, defaults={}) @program_name = "gem #{command}" @defaults = defaults @options = defaults.dup - @option_groups = Hash.new { |h,k| h[k] = [] } + @option_groups = Hash.new {|h,k| h[k] = [] } @deprecated_options = { command => {} } @parser = nil @when_invoked = nil @@ -162,7 +161,7 @@ def show_lookup_failure(gem_name, version, errors, suppress_suggestions = false, if errors and !errors.empty? msg << ", here is why:\n" - errors.each { |x| msg << " #{x.wordy}\n" } + errors.each {|x| msg << " #{x.wordy}\n" } else if required_by and gem != required_by msg << " (required by #{required_by}) in any repository" @@ -174,8 +173,7 @@ def show_lookup_failure(gem_name, version, errors, suppress_suggestions = false, alert_error msg unless suppress_suggestions - suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name gem_name - + suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name(gem_name, :latest, 10) unless suggestions.empty? alert_error "Possible alternatives: #{suggestions.join(", ")}" end @@ -193,7 +191,7 @@ def get_all_gem_names "Please specify at least one gem name (e.g. gem build GEMNAME)" end - args.select { |arg| arg !~ /^-/ } + args.select {|arg| arg !~ /^-/ } end ## @@ -346,7 +344,7 @@ def when_invoked(&block) ## # Add a command-line option and handler to the command. # - # See OptionParser#make_switch for an explanation of +opts+. + # See Gem::OptionParser#make_switch for an explanation of +opts+. # # +handler+ will be called with two values, the value of the argument and # the options hash. @@ -357,6 +355,8 @@ def when_invoked(&block) def add_option(*opts, &handler) # :yields: value, options group_name = Symbol === opts.first ? opts.shift : :options + raise "Do not pass an empty string in opts" if opts.include?("") + @option_groups[group_name] << [opts, handler] end @@ -365,7 +365,7 @@ def add_option(*opts, &handler) # :yields: value, options def remove_option(name) @option_groups.each do |_, option_list| - option_list.reject! { |args, _| args.any? { |x| x.is_a?(String) && x =~ /^#{name}/ } } + option_list.reject! {|args, _| args.any? {|x| x.is_a?(String) && x =~ /^#{name}/ } } end end @@ -398,10 +398,10 @@ def check_deprecated_options(options) version_to_expire = deprecation["rg_version_to_expire"] deprecate_option_msg = if version_to_expire - "The \"#{option}\" option has been deprecated and will be removed in Rubygems #{version_to_expire}." - else - "The \"#{option}\" option has been deprecated and will be removed in future versions of Rubygems." - end + "The \"#{option}\" option has been deprecated and will be removed in Rubygems #{version_to_expire}." + else + "The \"#{option}\" option has been deprecated and will be removed in future versions of Rubygems." + end extra_msg = deprecation["extra_msg"] @@ -418,7 +418,7 @@ def check_deprecated_options(options) def merge_options(new_options) @options = @defaults.clone - new_options.each { |k,v| @options[k] = v } + new_options.each {|k,v| @options[k] = v } end ## @@ -457,7 +457,7 @@ def add_extra_args(args) until extra.empty? do ex = [] ex << extra.shift - ex << extra.shift if extra.first.to_s =~ /^[^-]/ + ex << extra.shift if extra.first.to_s =~ /^[^-]/ # rubocop:disable Performance/StartWith result << ex if handles?(ex) end @@ -466,6 +466,10 @@ def add_extra_args(args) result end + def deprecated? + false + end + private def option_is_deprecated?(option) @@ -493,7 +497,7 @@ def add_parser_options # :nodoc: configure_options "", regular_options - @option_groups.sort_by { |n,_| n.to_s }.each do |group_name, option_list| + @option_groups.sort_by {|n,_| n.to_s }.each do |group_name, option_list| @parser.separator nil configure_options group_name, option_list end @@ -536,7 +540,7 @@ def parser # command. def create_option_parser - @parser = OptionParser.new + @parser = Gem::OptionParser.new add_parser_options @@ -621,8 +625,7 @@ def wrap(text, width) # :doc: # :stopdoc: HELP = <<-HELP.freeze -RubyGems is a sophisticated package manager for Ruby. This is a -basic help message containing pointers to more information. +RubyGems is a package manager for Ruby. Usage: gem -h/--help @@ -633,6 +636,7 @@ def wrap(text, width) # :doc: gem install rake gem list --local gem build package.gemspec + gem push package-0.0.1.gem gem help install Further help: @@ -646,11 +650,10 @@ def wrap(text, width) # :doc: http://localhost:8808/ with info about installed gems Further information: - http://guides.rubygems.org + https://guides.rubygems.org HELP # :startdoc: - end ## diff --git a/ruby/lib/rubygems/command_manager.rb b/ruby/lib/rubygems/command_manager.rb index 8ad723be5..03cdd6a4b 100644 --- a/ruby/lib/rubygems/command_manager.rb +++ b/ruby/lib/rubygems/command_manager.rb @@ -5,9 +5,9 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/command' -require 'rubygems/user_interaction' -require 'rubygems/text' +require_relative 'command' +require_relative 'user_interaction' +require_relative 'text' ## # The command manager registers and installs all the individual sub-commands @@ -32,7 +32,6 @@ # See Gem::Command for instructions on writing gem commands. class Gem::CommandManager - include Gem::Text include Gem::UserInteraction @@ -74,7 +73,9 @@ class Gem::CommandManager ].freeze ALIAS_COMMANDS = { - 'i' => 'install' + 'i' => 'install', + 'login' => 'signin', + 'logout' => 'signout', }.freeze ## @@ -138,7 +139,7 @@ def [](command_name) # Return a sorted list of all command names as strings. def command_names - @commands.keys.collect {|key| key.to_s}.sort + @commands.keys.collect {|key| key.to_s }.sort end ## @@ -175,6 +176,7 @@ def process_args(args, build_args=nil) else cmd_name = args.shift.downcase cmd = find_command cmd_name + cmd.deprecation_warning if cmd.deprecated? cmd.invoke_with_build_args args, build_args end end @@ -188,7 +190,7 @@ def find_command(cmd_name) raise Gem::CommandLineError, "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]" elsif possibilities.empty? - raise Gem::CommandLineError, "Unknown command #{cmd_name}" + raise Gem::UnknownCommandError.new(cmd_name) end self[possibilities.first] @@ -202,9 +204,9 @@ def find_alias_command(cmd_name) def find_command_possibilities(cmd_name) len = cmd_name.length - found = command_names.select { |name| cmd_name == name[0, len] } + found = command_names.select {|name| cmd_name == name[0, len] } - exact = found.find { |name| name == cmd_name } + exact = found.find {|name| name == cmd_name } exact ? [exact] : found end @@ -230,5 +232,4 @@ def load_and_instantiate(command_name) ui.backtrace e end end - end diff --git a/ruby/lib/rubygems/commands/build_command.rb b/ruby/lib/rubygems/commands/build_command.rb index e2b5def1e..6d1a057df 100644 --- a/ruby/lib/rubygems/commands/build_command.rb +++ b/ruby/lib/rubygems/commands/build_command.rb @@ -1,12 +1,16 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/package' +require_relative '../command' +require_relative '../package' +require_relative '../version_option' class Gem::Commands::BuildCommand < Gem::Command + include Gem::VersionOption def initialize super 'build', 'Build a gem from a gemspec' + add_platform_option + add_option '--force', 'skip validation of the spec' do |value, options| options[:force] = true end @@ -19,7 +23,7 @@ def initialize options[:output] = value end - add_option '-C PATH', '', 'Run as if gem build was started in instead of the current working directory.' do |value, options| + add_option '-C PATH', 'Run as if gem build was started in instead of the current working directory.' do |value, options| options[:build_path] = value end end @@ -57,14 +61,18 @@ def usage # :nodoc: end def execute - gem_name = get_one_optional_argument || find_gemspec - build_gem(gem_name) + if build_path = options[:build_path] + Dir.chdir(build_path) { build_gem } + return + end + + build_gem end private - def find_gemspec - gemspecs = Dir.glob("*.gemspec").sort + def find_gemspec(glob = "*.gemspec") + gemspecs = Dir.glob(glob).sort if gemspecs.size > 1 alert_error "Multiple gemspecs found: #{gemspecs}, please specify one" @@ -74,28 +82,19 @@ def find_gemspec gemspecs.first end - def build_gem(gem_name) - gemspec = File.exist?(gem_name) ? gem_name : "#{gem_name}.gemspec" - - if File.exist?(gemspec) - spec = Gem::Specification.load(gemspec) - - if options[:build_path] - Dir.chdir(File.dirname(gemspec)) do - spec = Gem::Specification.load(File.basename(gemspec)) - build_package(spec) - end - else - build_package(spec) - end + def build_gem + gemspec = resolve_gem_name + if gemspec + build_package(gemspec) else - alert_error "Gemspec file not found: #{gemspec}" + alert_error error_message terminate_interaction(1) end end - def build_package(spec) + def build_package(gemspec) + spec = Gem::Specification.load(gemspec) if spec Gem::Package.build( spec, @@ -109,4 +108,25 @@ def build_package(spec) end end + def resolve_gem_name + return find_gemspec unless gem_name + + if File.exist?(gem_name) + gem_name + else + find_gemspec("#{gem_name}.gemspec") || find_gemspec(gem_name) + end + end + + def error_message + if gem_name + "Couldn't find a gemspec file matching '#{gem_name}' in #{Dir.pwd}" + else + "Couldn't find a gemspec file in #{Dir.pwd}" + end + end + + def gem_name + get_one_optional_argument + end end diff --git a/ruby/lib/rubygems/commands/cert_command.rb b/ruby/lib/rubygems/commands/cert_command.rb index 72400f3ed..b59564d57 100644 --- a/ruby/lib/rubygems/commands/cert_command.rb +++ b/ruby/lib/rubygems/commands/cert_command.rb @@ -1,50 +1,15 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/security' -begin - require 'openssl' -rescue LoadError => e - raise unless (e.respond_to?(:path) && e.path == 'openssl') || - e.message =~ / -- openssl$/ -end +require_relative '../command' +require_relative '../security' class Gem::Commands::CertCommand < Gem::Command - def initialize super 'cert', 'Manage RubyGems certificates and signing settings', :add => [], :remove => [], :list => [], :build => [], :sign => [] - OptionParser.accept OpenSSL::X509::Certificate do |certificate_file| - begin - certificate = OpenSSL::X509::Certificate.new File.read certificate_file - rescue Errno::ENOENT - raise OptionParser::InvalidArgument, "#{certificate_file}: does not exist" - rescue OpenSSL::X509::CertificateError - raise OptionParser::InvalidArgument, - "#{certificate_file}: invalid X509 certificate" - end - [certificate, certificate_file] - end - - OptionParser.accept OpenSSL::PKey::RSA do |key_file| - begin - passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] - key = OpenSSL::PKey::RSA.new File.read(key_file), passphrase - rescue Errno::ENOENT - raise OptionParser::InvalidArgument, "#{key_file}: does not exist" - rescue OpenSSL::PKey::RSAError - raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key" - end - - raise OptionParser::InvalidArgument, - "#{key_file}: private key not found" unless key.private? - - key - end - - add_option('-a', '--add CERT', OpenSSL::X509::Certificate, - 'Add a trusted certificate.') do |(cert, _), options| - options[:add] << cert + add_option('-a', '--add CERT', + 'Add a trusted certificate.') do |cert_file, options| + options[:add] << open_cert(cert_file) end add_option('-l', '--list [FILTER]', @@ -67,21 +32,26 @@ def initialize options[:build] << email_address end - add_option('-C', '--certificate CERT', OpenSSL::X509::Certificate, - 'Signing certificate for --sign') do |(cert, cert_file), options| - options[:issuer_cert] = cert + add_option('-C', '--certificate CERT', + 'Signing certificate for --sign') do |cert_file, options| + options[:issuer_cert] = open_cert(cert_file) options[:issuer_cert_file] = cert_file end - add_option('-K', '--private-key KEY', OpenSSL::PKey::RSA, - 'Key for --sign or --build') do |key, options| - options[:key] = key + add_option('-K', '--private-key KEY', + 'Key for --sign or --build') do |key_file, options| + options[:key] = open_private_key(key_file) + end + + add_option('-A', '--key-algorithm ALGORITHM', + 'Select which key algorithm to use for --build') do |algorithm, options| + options[:key_algorithm] = algorithm end add_option('-s', '--sign CERT', 'Signs CERT with the key from -K', 'and the certificate from -C') do |cert_file, options| - raise OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless + raise Gem::OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless File.file? cert_file options[:sign] << cert_file @@ -104,7 +74,39 @@ def add_certificate(certificate) # :nodoc: say "Added '#{certificate.subject}'" end + def check_openssl + return if Gem::HAVE_OPENSSL + + alert_error "OpenSSL library is required for the cert command" + terminate_interaction 1 + end + + def open_cert(certificate_file) + check_openssl + OpenSSL::X509::Certificate.new File.read certificate_file + rescue Errno::ENOENT + raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: does not exist" + rescue OpenSSL::X509::CertificateError + raise Gem::OptionParser::InvalidArgument, + "#{certificate_file}: invalid X509 certificate" + end + + def open_private_key(key_file) + check_openssl + passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] + key = OpenSSL::PKey.read File.read(key_file), passphrase + raise Gem::OptionParser::InvalidArgument, + "#{key_file}: private key not found" unless key.private? + key + rescue Errno::ENOENT + raise Gem::OptionParser::InvalidArgument, "#{key_file}: does not exist" + rescue OpenSSL::PKey::PKeyError, ArgumentError + raise Gem::OptionParser::InvalidArgument, "#{key_file}: invalid RSA, DSA, or EC key" + end + def execute + check_openssl + options[:add].each do |certificate| add_certificate certificate end @@ -173,7 +175,8 @@ def build_key # :nodoc: raise Gem::CommandLineError, "Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation - key = Gem::Security.create_key + algorithm = options[:key_algorithm] || Gem::Security::DEFAULT_KEY_ALGORITHM + key = Gem::Security.create_key(algorithm) key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase return key, key_path @@ -186,7 +189,7 @@ def certificates_matching(filter) subject = certificate.subject.to_s subject.downcase.index filter end.sort_by do |certificate, _| - certificate.subject.to_a.map { |name, data,| [name, data] } + certificate.subject.to_a.map {|name, data,| [name, data] } end.each do |certificate, path| yield certificate, path end @@ -258,13 +261,14 @@ def load_default_key key_file = File.join Gem.default_key_path key = File.read key_file passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE'] - options[:key] = OpenSSL::PKey::RSA.new key, passphrase + options[:key] = OpenSSL::PKey.read key, passphrase + rescue Errno::ENOENT alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem does not exist" terminate_interaction 1 - rescue OpenSSL::PKey::RSAError + rescue OpenSSL::PKey::PKeyError alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem is not valid" @@ -318,5 +322,4 @@ def valid_email?(email) # It's simple, but is all we need email =~ /\A.+@.+\z/ end - -end if defined?(OpenSSL::SSL) +end diff --git a/ruby/lib/rubygems/commands/check_command.rb b/ruby/lib/rubygems/commands/check_command.rb index 7905b8ab6..3b6b97ae3 100644 --- a/ruby/lib/rubygems/commands/check_command.rb +++ b/ruby/lib/rubygems/commands/check_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/version_option' -require 'rubygems/validator' -require 'rubygems/doctor' +require_relative '../command' +require_relative '../version_option' +require_relative '../validator' +require_relative '../doctor' class Gem::Commands::CheckCommand < Gem::Command - include Gem::VersionOption def initialize @@ -90,5 +89,4 @@ def description # :nodoc: def usage # :nodoc: "#{program_name} [OPTIONS] [GEMNAME ...]" end - end diff --git a/ruby/lib/rubygems/commands/cleanup_command.rb b/ruby/lib/rubygems/commands/cleanup_command.rb index fedaec844..dc181e4de 100644 --- a/ruby/lib/rubygems/commands/cleanup_command.rb +++ b/ruby/lib/rubygems/commands/cleanup_command.rb @@ -1,20 +1,25 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/dependency_list' -require 'rubygems/uninstaller' +require_relative '../command' +require_relative '../dependency_list' +require_relative '../uninstaller' class Gem::Commands::CleanupCommand < Gem::Command - def initialize super 'cleanup', 'Clean up old versions of installed gems', :force => false, :install_dir => Gem.dir, :check_dev => true - add_option('-n', '-d', '--dryrun', + add_option('-n', '-d', '--dry-run', + 'Do not uninstall gems') do |value, options| + options[:dryrun] = true + end + + add_option(:Deprecated, '--dryrun', 'Do not uninstall gems') do |value, options| options[:dryrun] = true end + deprecate_option('--dryrun', extra_msg: 'Use --dry-run instead') add_option('-D', '--[no-]check-development', 'Check development dependencies while uninstalling', @@ -42,7 +47,7 @@ def arguments # :nodoc: end def defaults_str # :nodoc: - "--no-dryrun" + "--no-dry-run" end def description # :nodoc: @@ -69,7 +74,7 @@ def execute until done do clean_gems - this_set = @gems_to_cleanup.map { |spec| spec.full_name }.sort + this_set = @gems_to_cleanup.map {|spec| spec.full_name }.sort done = this_set.empty? || last_set == this_set @@ -82,7 +87,7 @@ def execute say "Clean up complete" verbose do - skipped = @default_gems.map { |spec| spec.full_name } + skipped = @default_gems.map {|spec| spec.full_name } "Skipped default gems: #{skipped.join ', '}" end @@ -99,7 +104,7 @@ def clean_gems @full = Gem::DependencyList.from_specs deplist = Gem::DependencyList.new - @gems_to_cleanup.each { |spec| deplist.add spec } + @gems_to_cleanup.each {|spec| deplist.add spec } deps = deplist.strongly_connected_components.flatten @@ -112,12 +117,12 @@ def clean_gems def get_candidate_gems @candidate_gems = unless options[:args].empty? - options[:args].map do |gem_name| - Gem::Specification.find_all_by_name gem_name - end.flatten - else - Gem::Specification.to_a - end + options[:args].map do |gem_name| + Gem::Specification.find_all_by_name gem_name + end.flatten + else + Gem::Specification.to_a + end end def get_gems_to_cleanup @@ -181,5 +186,4 @@ def uninstall_dep(spec) # Restore path Gem::Uninstaller may have changed Gem.use_paths @original_home, *@original_path end - end diff --git a/ruby/lib/rubygems/commands/contents_command.rb b/ruby/lib/rubygems/commands/contents_command.rb index 26d6828fe..716022c45 100644 --- a/ruby/lib/rubygems/commands/contents_command.rb +++ b/ruby/lib/rubygems/commands/contents_command.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require 'English' -require 'rubygems/command' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../version_option' class Gem::Commands::ContentsCommand < Gem::Command - include Gem::VersionOption def initialize @@ -106,7 +104,8 @@ def files_in_default_gem(spec) spec.files.map do |file| case file when /\A#{spec.bindir}\// - [RbConfig::CONFIG['bindir'], $POSTMATCH] + # $' is POSTMATCH + [RbConfig::CONFIG['bindir'], $'] when /\.so\z/ [RbConfig::CONFIG['archdir'], file] else @@ -167,7 +166,7 @@ def show_files(files) end def spec_for(name) - spec = Gem::Specification.find_all_by_name(name, @version).last + spec = Gem::Specification.find_all_by_name(name, @version).first return spec if spec @@ -175,7 +174,7 @@ def spec_for(name) if Gem.configuration.verbose say "\nDirectories searched:" - @spec_dirs.sort.each { |dir| say dir } + @spec_dirs.sort.each {|dir| say dir } end return nil @@ -186,5 +185,4 @@ def specification_directories # :nodoc: [i, File.join(i, "specifications")] end.flatten end - end diff --git a/ruby/lib/rubygems/commands/dependency_command.rb b/ruby/lib/rubygems/commands/dependency_command.rb index 00ab19bed..d2fed022f 100644 --- a/ruby/lib/rubygems/commands/dependency_command.rb +++ b/ruby/lib/rubygems/commands/dependency_command.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../version_option' class Gem::Commands::DependencyCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::VersionOption @@ -54,45 +53,45 @@ def usage # :nodoc: "#{program_name} REGEXP" end - def fetch_remote_specs(dependency) # :nodoc: + def fetch_remote_specs(name, requirement, prerelease) # :nodoc: fetcher = Gem::SpecFetcher.fetcher - ss, = fetcher.spec_for_dependency dependency + specs_type = prerelease ? :complete : :released + + ss = if name.nil? + fetcher.detect(specs_type) { true } + else + fetcher.detect(specs_type) do |name_tuple| + name === name_tuple.name && requirement.satisfied_by?(name_tuple.version) + end + end - ss.map { |spec, _| spec } + ss.map {|tuple, source| source.fetch_spec(tuple) } end - def fetch_specs(name_pattern, dependency) # :nodoc: + def fetch_specs(name_pattern, requirement, prerelease) # :nodoc: specs = [] if local? - specs.concat Gem::Specification.stubs.find_all { |spec| - name_pattern =~ spec.name and - dependency.requirement.satisfied_by? spec.version + specs.concat Gem::Specification.stubs.find_all {|spec| + name_matches = name_pattern ? name_pattern =~ spec.name : true + version_matches = requirement.satisfied_by?(spec.version) + + name_matches and version_matches }.map(&:to_spec) end - specs.concat fetch_remote_specs dependency if remote? + specs.concat fetch_remote_specs name_pattern, requirement, prerelease if remote? ensure_specs specs specs.uniq.sort end - def gem_dependency(pattern, version, prerelease) # :nodoc: - dependency = Gem::Deprecate.skip_during do - Gem::Dependency.new pattern, version - end - - dependency.prerelease = prerelease - - dependency - end - def display_pipe(specs) # :nodoc: specs.each do |spec| unless spec.dependencies.empty? - spec.dependencies.sort_by { |dep| dep.name }.each do |dep| + spec.dependencies.sort_by {|dep| dep.name }.each do |dep| say "#{dep.name} --version '#{dep.requirement}'" end end @@ -120,11 +119,9 @@ def execute ensure_local_only_reverse_dependencies pattern = name_pattern options[:args] + requirement = Gem::Requirement.new options[:version] - dependency = - gem_dependency pattern, options[:version], options[:prerelease] - - specs = fetch_specs pattern, dependency + specs = fetch_specs pattern, requirement, options[:prerelease] reverse = reverse_dependencies specs @@ -156,23 +153,15 @@ def print_dependencies(spec, level = 0) # :nodoc: response = String.new response << ' ' * level + "Gem #{spec.full_name}\n" unless spec.dependencies.empty? - spec.dependencies.sort_by { |dep| dep.name }.each do |dep| + spec.dependencies.sort_by {|dep| dep.name }.each do |dep| response << ' ' * level + " #{dep}\n" end end response end - def remote_specs(dependency) # :nodoc: - fetcher = Gem::SpecFetcher.fetcher - - ss, _ = fetcher.spec_for_dependency dependency - - ss.map { |s,o| s } - end - def reverse_dependencies(specs) # :nodoc: - reverse = Hash.new { |h, k| h[k] = [] } + reverse = Hash.new {|h, k| h[k] = [] } return reverse unless options[:reverse_dependencies] @@ -206,7 +195,7 @@ def find_reverse_dependencies(spec) # :nodoc: private def name_pattern(args) - args << '' if args.empty? + return if args.empty? if args.length == 1 and args.first =~ /\A(.*)(i)?\z/m flags = $2 ? Regexp::IGNORECASE : nil @@ -215,5 +204,4 @@ def name_pattern(args) /\A#{Regexp.union(*args)}/ end end - end diff --git a/ruby/lib/rubygems/commands/environment_command.rb b/ruby/lib/rubygems/commands/environment_command.rb index c98a77ac2..b6eeb620b 100644 --- a/ruby/lib/rubygems/commands/environment_command.rb +++ b/ruby/lib/rubygems/commands/environment_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::EnvironmentCommand < Gem::Command - def initialize super 'environment', 'Display information about the RubyGems environment' end @@ -127,7 +126,7 @@ def show_environment # :nodoc: out << " - RUBYGEMS PLATFORMS:\n" Gem.platforms.each do |platform| - out << " - #{platform}\n" + out << " - #{platform}\n" end out << " - GEM PATHS:\n" @@ -172,5 +171,4 @@ def git_path return nil end - end diff --git a/ruby/lib/rubygems/commands/fetch_command.rb b/ruby/lib/rubygems/commands/fetch_command.rb index 66562d7fb..c8ecb0d48 100644 --- a/ruby/lib/rubygems/commands/fetch_command.rb +++ b/ruby/lib/rubygems/commands/fetch_command.rb @@ -1,15 +1,19 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../version_option' class Gem::Commands::FetchCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::VersionOption def initialize - super 'fetch', 'Download a gem and place it in the current directory' + defaults = { + :suggest_alternate => true, + :version => Gem::Requirement.default, + } + + super 'fetch', 'Download a gem and place it in the current directory', defaults add_bulk_threshold_option add_proxy_option @@ -19,6 +23,10 @@ def initialize add_version_option add_platform_option add_prerelease_option + + add_option '--[no-]suggestions', 'Suggest alternates when gems are not found' do |value, options| + options[:suggest_alternate] = value + end end def arguments # :nodoc: @@ -43,35 +51,44 @@ def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...]" end + def check_version # :nodoc: + if options[:version] != Gem::Requirement.default and + get_all_gem_names.size > 1 + alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \ + " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`" + terminate_interaction 1 + end + end + def execute - version = options[:version] || Gem::Requirement.default + check_version + version = options[:version] platform = Gem.platforms.last - gem_names = get_all_gem_names + gem_names = get_all_gem_names_and_versions - gem_names.each do |gem_name| - dep = Gem::Dependency.new gem_name, version + gem_names.each do |gem_name, gem_version| + gem_version ||= version + dep = Gem::Dependency.new gem_name, gem_version dep.prerelease = options[:prerelease] + suppress_suggestions = !options[:suggest_alternate] specs_and_sources, errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep if platform - filtered = specs_and_sources.select { |s,| s.platform == platform } + filtered = specs_and_sources.select {|s,| s.platform == platform } specs_and_sources = filtered unless filtered.empty? end - spec, source = specs_and_sources.max_by { |s,| s.version } + spec, source = specs_and_sources.max_by {|s,| s } if spec.nil? - show_lookup_failure gem_name, version, errors, options[:domain] + show_lookup_failure gem_name, gem_version, errors, suppress_suggestions, options[:domain] next end - source.download spec - say "Downloaded #{spec.full_name}" end end - end diff --git a/ruby/lib/rubygems/commands/generate_index_command.rb b/ruby/lib/rubygems/commands/generate_index_command.rb index 6dccdcb94..87200dab9 100644 --- a/ruby/lib/rubygems/commands/generate_index_command.rb +++ b/ruby/lib/rubygems/commands/generate_index_command.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/indexer' +require_relative '../command' +require_relative '../indexer' ## # Generates a index files for use as a gem server. @@ -8,7 +8,6 @@ # See `gem help generate_index` class Gem::Commands::GenerateIndexCommand < Gem::Command - def initialize super 'generate_index', 'Generates the index files for a gem server directory', @@ -83,5 +82,4 @@ def execute end end end - end diff --git a/ruby/lib/rubygems/commands/help_command.rb b/ruby/lib/rubygems/commands/help_command.rb index 9f14e22f9..7f3383c9f 100644 --- a/ruby/lib/rubygems/commands/help_command.rb +++ b/ruby/lib/rubygems/commands/help_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::HelpCommand < Gem::Command - # :stopdoc: EXAMPLES = <<-EOF.freeze Some examples of 'gem' usage. @@ -38,7 +37,7 @@ class Gem::Commands::HelpCommand < Gem::Command * Create a gem: - See http://guides.rubygems.org/make-your-own-gem/ + See https://guides.rubygems.org/make-your-own-gem/ * See information about RubyGems: @@ -324,7 +323,7 @@ def show_commands # :nodoc: margin_width = 4 - desc_width = @command_manager.command_names.map { |n| n.size }.max + 4 + desc_width = @command_manager.command_names.map {|n| n.size }.max + 4 summary_width = 80 - margin_width - desc_width wrap_indent = ' ' * (margin_width + desc_width) @@ -333,6 +332,8 @@ def show_commands # :nodoc: @command_manager.command_names.each do |cmd_name| command = @command_manager[cmd_name] + next if command.deprecated? + summary = if command command.summary @@ -370,5 +371,4 @@ def show_command_help(command_name) # :nodoc: alert_warning "Unknown command #{command_name}. Try: gem help commands" end end - end diff --git a/ruby/lib/rubygems/commands/info_command.rb b/ruby/lib/rubygems/commands/info_command.rb index 6a737b178..3f2dd4ae0 100644 --- a/ruby/lib/rubygems/commands/info_command.rb +++ b/ruby/lib/rubygems/commands/info_command.rb @@ -1,14 +1,18 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/commands/query_command' +require_relative '../command' +require_relative '../query_utils' -class Gem::Commands::InfoCommand < Gem::Commands::QueryCommand +class Gem::Commands::InfoCommand < Gem::Command + include Gem::QueryUtils def initialize - super "info", "Show information for the given gem" + super "info", "Show information for the given gem", + :name => //, :domain => :local, :details => false, :versions => true, + :installed => nil, :version => Gem::Requirement.default + + add_query_options - remove_option('--name-matches') remove_option('-d') defaults[:details] = true @@ -31,5 +35,4 @@ def arguments # :nodoc: def defaults_str "--local" end - end diff --git a/ruby/lib/rubygems/commands/install_command.rb b/ruby/lib/rubygems/commands/install_command.rb index 753ff33eb..adf2cdba8 100644 --- a/ruby/lib/rubygems/commands/install_command.rb +++ b/ruby/lib/rubygems/commands/install_command.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/install_update_options' -require 'rubygems/dependency_installer' -require 'rubygems/local_remote_options' -require 'rubygems/validator' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../install_update_options' +require_relative '../dependency_installer' +require_relative '../local_remote_options' +require_relative '../validator' +require_relative '../version_option' ## # Gem installer command line tool @@ -12,7 +12,6 @@ # See `gem help install` class Gem::Commands::InstallCommand < Gem::Command - attr_reader :installed_specs # :nodoc: include Gem::VersionOption @@ -28,6 +27,8 @@ def initialize :without_groups => [], }) + defaults.merge!(install_update_options) + super 'install', 'Install a gem into the local repository', defaults add_install_update_options @@ -44,8 +45,9 @@ def arguments # :nodoc: end def defaults_str # :nodoc: - "--both --version '#{Gem::Requirement.default}' --document --no-force\n" + - "--install-dir #{Gem.dir} --lock" + "--both --version '#{Gem::Requirement.default}' --no-force\n" + + "--install-dir #{Gem.dir} --lock\n" + + install_update_defaults_str end def description # :nodoc: @@ -128,7 +130,7 @@ def description # :nodoc: end def usage # :nodoc: - "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags" + "#{program_name} [options] GEMNAME [GEMNAME ...] -- --build-flags" end def check_install_dir # :nodoc: @@ -170,7 +172,7 @@ def execute end def install_from_gemdeps # :nodoc: - require 'rubygems/request_set' + require_relative '../request_set' rs = Gem::RequestSet.new specs = rs.install_from_gemdeps options do |req, inst| @@ -218,7 +220,7 @@ def install_gems # :nodoc: gem_version ||= options[:version] domain = options[:domain] domain = :local unless options[:suggest_alternate] - supress_suggestions = (domain == :local) + suppress_suggestions = (domain == :local) begin install_gem gem_name, gem_version @@ -226,11 +228,11 @@ def install_gems # :nodoc: alert_error "Error installing #{gem_name}:\n\t#{e.message}" exit_code |= 1 rescue Gem::GemNotFoundException => e - show_lookup_failure e.name, e.version, e.errors, supress_suggestions + show_lookup_failure e.name, e.version, e.errors, suppress_suggestions exit_code |= 2 rescue Gem::UnsatisfiableDependencyError => e - show_lookup_failure e.name, e.version, e.errors, supress_suggestions, + show_lookup_failure e.name, e.version, e.errors, suppress_suggestions, "'#{gem_name}' (#{gem_version})" exit_code |= 2 @@ -245,11 +247,11 @@ def install_gems # :nodoc: def load_hooks # :nodoc: if options[:install_as_default] - require 'rubygems/install_default_message' + require_relative '../install_default_message' else - require 'rubygems/install_message' + require_relative '../install_message' end - require 'rubygems/rdoc' + require_relative '../rdoc' end def show_install_errors(errors) # :nodoc: @@ -258,7 +260,8 @@ def show_install_errors(errors) # :nodoc: errors.each do |x| return unless Gem::SourceFetchProblem === x - msg = "Unable to pull data from '#{x.source.uri}': #{x.error.message}" + require_relative "../uri" + msg = "Unable to pull data from '#{Gem::Uri.new(x.source.uri).redacted}': #{x.error.message}" alert_warning msg end @@ -270,5 +273,4 @@ def show_installed # :nodoc: gems = @installed_specs.length == 1 ? 'gem' : 'gems' say "#{@installed_specs.length} #{gems} installed" end - end diff --git a/ruby/lib/rubygems/commands/list_command.rb b/ruby/lib/rubygems/commands/list_command.rb index cd2154353..010d968f9 100644 --- a/ruby/lib/rubygems/commands/list_command.rb +++ b/ruby/lib/rubygems/commands/list_command.rb @@ -1,17 +1,19 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/commands/query_command' +require_relative '../command' +require_relative '../query_utils' ## -# An alternate to Gem::Commands::QueryCommand that searches for gems starting -# with the supplied argument. +# Searches for gems starting with the supplied argument. -class Gem::Commands::ListCommand < Gem::Commands::QueryCommand +class Gem::Commands::ListCommand < Gem::Command + include Gem::QueryUtils def initialize - super 'list', 'Display local gems whose name matches REGEXP' + super 'list', 'Display local gems whose name matches REGEXP', + :domain => :local, :details => false, :versions => true, + :installed => nil, :version => Gem::Requirement.default - remove_option('--name-matches') + add_query_options end def arguments # :nodoc: @@ -36,5 +38,4 @@ def description # :nodoc: def usage # :nodoc: "#{program_name} [REGEXP ...]" end - end diff --git a/ruby/lib/rubygems/commands/lock_command.rb b/ruby/lib/rubygems/commands/lock_command.rb index ebb402a8b..cb6229a2c 100644 --- a/ruby/lib/rubygems/commands/lock_command.rb +++ b/ruby/lib/rubygems/commands/lock_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::LockCommand < Gem::Command - def initialize super 'lock', 'Generate a lockdown list of gems', :strict => false @@ -104,7 +103,6 @@ def spec_path(gem_full_name) File.join path, "specifications", "#{gem_full_name}.gemspec" end - gemspecs.find { |path| File.exist? path } + gemspecs.find {|path| File.exist? path } end - end diff --git a/ruby/lib/rubygems/commands/mirror_command.rb b/ruby/lib/rubygems/commands/mirror_command.rb index 4e2a41fa3..7daa47e2f 100644 --- a/ruby/lib/rubygems/commands/mirror_command.rb +++ b/ruby/lib/rubygems/commands/mirror_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' unless defined? Gem::Commands::MirrorCommand class Gem::Commands::MirrorCommand < Gem::Command - def initialize super('mirror', 'Mirror all gem files (requires rubygems-mirror)') begin @@ -22,6 +21,5 @@ def description # :nodoc: def execute alert_error "Install the rubygems-mirror gem for the mirror command" end - end end diff --git a/ruby/lib/rubygems/commands/open_command.rb b/ruby/lib/rubygems/commands/open_command.rb index 8eaeb64ba..1e616fd68 100644 --- a/ruby/lib/rubygems/commands/open_command.rb +++ b/ruby/lib/rubygems/commands/open_command.rb @@ -1,11 +1,8 @@ # frozen_string_literal: true -require 'English' -require 'rubygems/command' -require 'rubygems/version_option' -require 'rubygems/util' +require_relative '../command' +require_relative '../version_option' class Gem::Commands::OpenCommand < Gem::Command - include Gem::VersionOption def initialize @@ -39,7 +36,7 @@ def description # :nodoc: end def usage # :nodoc: - "#{program_name} GEMNAME [-e COMMAND]" + "#{program_name} [-e COMMAND] GEMNAME" end def get_env_editor @@ -84,5 +81,4 @@ def spec_for(name) say "Unable to find gem '#{name}'" end - end diff --git a/ruby/lib/rubygems/commands/outdated_command.rb b/ruby/lib/rubygems/commands/outdated_command.rb index 035eaffcb..162d33832 100644 --- a/ruby/lib/rubygems/commands/outdated_command.rb +++ b/ruby/lib/rubygems/commands/outdated_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/spec_fetcher' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../spec_fetcher' +require_relative '../version_option' class Gem::Commands::OutdatedCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::VersionOption @@ -30,5 +29,4 @@ def execute say "#{spec.name} (#{spec.version} < #{remote_version})" end end - end diff --git a/ruby/lib/rubygems/commands/owner_command.rb b/ruby/lib/rubygems/commands/owner_command.rb index f8e68c48e..0a5665228 100644 --- a/ruby/lib/rubygems/commands/owner_command.rb +++ b/ruby/lib/rubygems/commands/owner_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/gemcutter_utilities' -require 'rubygems/text' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../gemcutter_utilities' +require_relative '../text' class Gem::Commands::OwnerCommand < Gem::Command - include Gem::Text include Gem::LocalRemoteOptions include Gem::GemcutterUtilities @@ -54,7 +53,7 @@ def initialize def execute @host = options[:host] - sign_in + sign_in(scope: get_owner_scope) name = get_one_gem_name add_owners name, options[:add] @@ -103,11 +102,17 @@ def manage_owners(method, name, owners) private def send_owner_request(method, name, owner) - rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request| + rubygems_api_request method, "api/v1/gems/#{name}/owners", scope: get_owner_scope(method: method) do |request| request.set_form_data 'email' => owner request.add_field "Authorization", api_key - request.add_field "OTP", options[:otp] if options[:otp] end end + def get_owner_scope(method: nil) + if method == :post || options.any? && options[:add].any? + :add_owner + elsif method == :delete || options.any? && options[:remove].any? + :remove_owner + end + end end diff --git a/ruby/lib/rubygems/commands/pristine_command.rb b/ruby/lib/rubygems/commands/pristine_command.rb index 2248a821c..3cf496ba5 100644 --- a/ruby/lib/rubygems/commands/pristine_command.rb +++ b/ruby/lib/rubygems/commands/pristine_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/package' -require 'rubygems/installer' -require 'rubygems/version_option' +require_relative '../command' +require_relative '../package' +require_relative '../installer' +require_relative '../version_option' class Gem::Commands::PristineCommand < Gem::Command - include Gem::VersionOption def initialize @@ -40,12 +39,22 @@ def initialize options[:only_executables] = value end + add_option('--only-plugins', + 'Only restore plugins') do |value, options| + options[:only_plugins] = value + end + add_option('-E', '--[no-]env-shebang', 'Rewrite executables with a shebang', 'of /usr/bin/env') do |value, options| options[:env_shebang] = value end + add_option('-i', '--install-dir DIR', + 'Gem repository to get binstubs and plugins installed') do |value, options| + options[:install_dir] = File.expand_path(value) + end + add_option('-n', '--bindir DIR', 'Directory where executables are', 'located') do |value, options| @@ -89,20 +98,20 @@ def usage # :nodoc: def execute specs = if options[:all] - Gem::Specification.map + Gem::Specification.map - # `--extensions` must be explicitly given to pristine only gems - # with extensions. - elsif options[:extensions_set] and + # `--extensions` must be explicitly given to pristine only gems + # with extensions. + elsif options[:extensions_set] and options[:extensions] and options[:args].empty? - Gem::Specification.select do |spec| - spec.extensions and not spec.extensions.empty? - end - else - get_all_gem_names.sort.map do |gem_name| - Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse - end.flatten - end + Gem::Specification.select do |spec| + spec.extensions and not spec.extensions.empty? + end + else + get_all_gem_names.sort.map do |gem_name| + Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse + end.flatten + end specs = specs.select{|spec| RUBY_ENGINE == spec.platform || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY } @@ -126,15 +135,15 @@ def execute end end - unless spec.extensions.empty? or options[:extensions] or options[:only_executables] + unless spec.extensions.empty? or options[:extensions] or options[:only_executables] or options[:only_plugins] say "Skipped #{spec.full_name}, it needs to compile an extension" next end gem = spec.cache_file - unless File.exist? gem or options[:only_executables] - require 'rubygems/remote_fetcher' + unless File.exist? gem or options[:only_executables] or options[:only_plugins] + require_relative '../remote_fetcher' say "Cached gem for #{spec.full_name} not found, attempting to fetch..." @@ -159,19 +168,23 @@ def execute end bin_dir = options[:bin_dir] if options[:bin_dir] + install_dir = options[:install_dir] if options[:install_dir] installer_options = { :wrappers => true, :force => true, - :install_dir => spec.base_dir, + :install_dir => install_dir || spec.base_dir, :env_shebang => env_shebang, :build_args => spec.build_args, - :bin_dir => bin_dir + :bin_dir => bin_dir, } if options[:only_executables] installer = Gem::Installer.for_spec(spec, installer_options) installer.generate_bin + elsif options[:only_plugins] + installer = Gem::Installer.for_spec(spec, installer_options) + installer.generate_plugins else installer = Gem::Installer.at(gem, installer_options) installer.install @@ -180,5 +193,4 @@ def execute say "Restored #{spec.full_name}" end end - end diff --git a/ruby/lib/rubygems/commands/push_command.rb b/ruby/lib/rubygems/commands/push_command.rb index 41e6c7ec3..4d0d5a9f4 100644 --- a/ruby/lib/rubygems/commands/push_command.rb +++ b/ruby/lib/rubygems/commands/push_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/gemcutter_utilities' -require 'rubygems/package' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../gemcutter_utilities' +require_relative '../package' class Gem::Commands::PushCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::GemcutterUtilities @@ -52,26 +51,17 @@ def execute gem_name = get_one_gem_name default_gem_server, push_host = get_hosts_for(gem_name) - default_host = nil - user_defined_host = nil - - if @user_defined_host - user_defined_host = options[:host] + @host = if @user_defined_host + options[:host] + elsif default_gem_server + default_gem_server + elsif push_host + push_host else - default_host = options[:host] + options[:host] end - @host = if user_defined_host - user_defined_host - elsif default_gem_server - default_gem_server - elsif push_host - push_host - else - default_host - end - - sign_in @host + sign_in @host, scope: get_push_scope send_gem(gem_name) end @@ -79,36 +69,7 @@ def execute def send_gem(name) args = [:post, "api/v1/gems"] - latest_rubygems_version = Gem.latest_rubygems_version - - if latest_rubygems_version < Gem.rubygems_version and - Gem.rubygems_version.prerelease? and - Gem::Version.new('2.0.0.rc.2') != Gem.rubygems_version - alert_error <<-ERROR -You are using a beta release of RubyGems (#{Gem::VERSION}) which is not -allowed to push gems. Please downgrade or upgrade to a release version. - -The latest released RubyGems version is #{latest_rubygems_version} - -You can upgrade or downgrade to the latest release version with: - - gem update --system=#{latest_rubygems_version} - - ERROR - terminate_interaction 1 - end - - gem_data = Gem::Package.new(name) - - unless @host - @host = gem_data.spec.metadata['default_gem_server'] - end - - push_host = nil - - if gem_data.spec.metadata.has_key?('allowed_push_host') - push_host = gem_data.spec.metadata['allowed_push_host'] - end + _, push_host = get_hosts_for(name) @host ||= push_host @@ -125,12 +86,11 @@ def send_gem(name) private def send_push_request(name, args) - rubygems_api_request(*args) do |request| + rubygems_api_request(*args, scope: get_push_scope) do |request| request.body = Gem.read_binary name request.add_field "Content-Length", request.body.size request.add_field "Content-Type", "application/octet-stream" request.add_field "Authorization", api_key - request.add_field "OTP", options[:otp] if options[:otp] end end @@ -139,8 +99,11 @@ def get_hosts_for(name) [ gem_metadata["default_gem_server"], - gem_metadata["allowed_push_host"] + gem_metadata["allowed_push_host"], ] end + def get_push_scope + :push_rubygem + end end diff --git a/ruby/lib/rubygems/commands/query_command.rb b/ruby/lib/rubygems/commands/query_command.rb index 4fb23bc6c..442c4b19b 100644 --- a/ruby/lib/rubygems/commands/query_command.rb +++ b/ruby/lib/rubygems/commands/query_command.rb @@ -1,71 +1,35 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/spec_fetcher' -require 'rubygems/version_option' -require 'rubygems/text' +require_relative '../command' +require_relative '../query_utils' +require_relative '../deprecate' class Gem::Commands::QueryCommand < Gem::Command + extend Gem::Deprecate + rubygems_deprecate_command - include Gem::Text - include Gem::LocalRemoteOptions - include Gem::VersionOption + include Gem::QueryUtils + + alias warning_without_suggested_alternatives deprecation_warning + def deprecation_warning + warning_without_suggested_alternatives + + message = "It is recommended that you use `gem search` or `gem list` instead.\n" + alert_warning message unless Gem::Deprecate.skip + end def initialize(name = 'query', summary = 'Query gem information in local or remote repositories') super name, summary, - :name => //, :domain => :local, :details => false, :versions => true, + :domain => :local, :details => false, :versions => true, :installed => nil, :version => Gem::Requirement.default - add_option('-i', '--[no-]installed', - 'Check for installed gem') do |value, options| - options[:installed] = value - end - - add_option('-I', 'Equivalent to --no-installed') do |value, options| - options[:installed] = false - end - - add_version_option command, "for use with --installed" - add_option('-n', '--name-matches REGEXP', 'Name of gem(s) to query on matches the', 'provided REGEXP') do |value, options| options[:name] = /#{value}/i end - add_option('-d', '--[no-]details', - 'Display detailed information of gem(s)') do |value, options| - options[:details] = value - end - - add_option('--[no-]versions', - 'Display only gem names') do |value, options| - options[:versions] = value - options[:details] = false unless value - end - - add_option('-a', '--all', - 'Display all gem versions') do |value, options| - options[:all] = value - end - - add_option('-e', '--exact', - 'Name of gem(s) to query on matches the', - 'provided STRING') do |value, options| - options[:exact] = value - end - - add_option('--[no-]prerelease', - 'Display prerelease versions') do |value, options| - options[:prerelease] = value - end - - add_local_remote_options - end - - def defaults_str # :nodoc: - "--local --name-matches // --no-details --versions --no-installed" + add_query_options end def description # :nodoc: @@ -76,298 +40,4 @@ def description # :nodoc: is too hard to use. EOF end - - def execute - gem_names = Array(options[:name]) - - if !args.empty? - gem_names = options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i } - end - - terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems? - - gem_names.each { |n| show_gems(n) } - end - - private - - def check_installed_gems(gem_names) - exit_code = 0 - - if args.empty? && !gem_name? - alert_error "You must specify a gem name" - exit_code = 4 - elsif gem_names.count > 1 - alert_error "You must specify only ONE gem!" - exit_code = 4 - else - installed = installed?(gem_names.first, options[:version]) - installed = !installed unless options[:installed] - - say(installed) - exit_code = 1 if !installed - end - - exit_code - end - - def check_installed_gems? - !options[:installed].nil? - end - - def gem_name? - !options[:name].source.empty? - end - - def prerelease - options[:prerelease] - end - - def show_prereleases? - prerelease.nil? || prerelease - end - - def args - options[:args].to_a - end - - def display_header(type) - if (ui.outs.tty? and Gem.configuration.verbose) or both? - say - say "*** #{type} GEMS ***" - say - end - end - - #Guts of original execute - def show_gems(name) - show_local_gems(name) if local? - show_remote_gems(name) if remote? - end - - def show_local_gems(name, req = Gem::Requirement.default) - display_header("LOCAL") - - specs = Gem::Specification.find_all do |s| - s.name =~ name and req =~ s.version - end - - dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req } - specs.select! do |s| - dep.match?(s.name, s.version, show_prereleases?) - end - - spec_tuples = specs.map do |spec| - [spec.name_tuple, spec] - end - - output_query_results(spec_tuples) - end - - def show_remote_gems(name) - display_header("REMOTE") - - fetcher = Gem::SpecFetcher.fetcher - - spec_tuples = if name.respond_to?(:source) && name.source.empty? - fetcher.detect(specs_type) { true } - else - fetcher.detect(specs_type) do |name_tuple| - name === name_tuple.name - end - end - - output_query_results(spec_tuples) - end - - def specs_type - if options[:all] - if options[:prerelease] - :complete - else - :released - end - elsif options[:prerelease] - :prerelease - else - :latest - end - end - - ## - # Check if gem +name+ version +version+ is installed. - - def installed?(name, req = Gem::Requirement.default) - Gem::Specification.any? { |s| s.name =~ name and req =~ s.version } - end - - def output_query_results(spec_tuples) - output = [] - versions = Hash.new { |h,name| h[name] = [] } - - spec_tuples.each do |spec_tuple, source| - versions[spec_tuple.name] << [spec_tuple, source] - end - - versions = versions.sort_by do |(n,_),_| - n.downcase - end - - output_versions output, versions - - say output.join(options[:details] ? "\n\n" : "\n") - end - - def output_versions(output, versions) - versions.each do |gem_name, matching_tuples| - matching_tuples = matching_tuples.sort_by { |n,_| n.version }.reverse - - platforms = Hash.new { |h,version| h[version] = [] } - - matching_tuples.each do |n, _| - platforms[n.version] << n.platform if n.platform - end - - seen = {} - - matching_tuples.delete_if do |n,_| - if seen[n.version] - true - else - seen[n.version] = true - false - end - end - - output << clean_text(make_entry(matching_tuples, platforms)) - end - end - - def entry_details(entry, detail_tuple, specs, platforms) - return unless options[:details] - - name_tuple, spec = detail_tuple - - spec = spec.fetch_spec(name_tuple)if spec.respond_to?(:fetch_spec) - - entry << "\n" - - spec_platforms entry, platforms - spec_authors entry, spec - spec_homepage entry, spec - spec_license entry, spec - spec_loaded_from entry, spec, specs - spec_summary entry, spec - end - - def entry_versions(entry, name_tuples, platforms, specs) - return unless options[:versions] - - list = - if platforms.empty? or options[:details] - name_tuples.map { |n| n.version }.uniq - else - platforms.sort.reverse.map do |version, pls| - out = version.to_s - - if options[:domain] == :local - default = specs.any? do |s| - !s.is_a?(Gem::Source) && s.version == version && s.default_gem? - end - out = "default: #{out}" if default - end - - if pls != [Gem::Platform::RUBY] - platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact - out = platform_list.unshift(out).join(' ') - end - - out - end - end - - entry << " (#{list.join ', '})" - end - - def make_entry(entry_tuples, platforms) - detail_tuple = entry_tuples.first - - name_tuples, specs = entry_tuples.flatten.partition do |item| - Gem::NameTuple === item - end - - entry = [name_tuples.first.name] - - entry_versions(entry, name_tuples, platforms, specs) - entry_details(entry, detail_tuple, specs, platforms) - - entry.join - end - - def spec_authors(entry, spec) - authors = "Author#{spec.authors.length > 1 ? 's' : ''}: ".dup - authors << spec.authors.join(', ') - entry << format_text(authors, 68, 4) - end - - def spec_homepage(entry, spec) - return if spec.homepage.nil? or spec.homepage.empty? - - entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4) - end - - def spec_license(entry, spec) - return if spec.license.nil? or spec.license.empty? - - licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: ".dup - licenses << spec.licenses.join(', ') - entry << "\n" << format_text(licenses, 68, 4) - end - - def spec_loaded_from(entry, spec, specs) - return unless spec.loaded_from - - if specs.length == 1 - default = spec.default_gem? ? ' (default)' : nil - entry << "\n" << " Installed at#{default}: #{spec.base_dir}" - else - label = 'Installed at' - specs.each do |s| - version = s.version.to_s - version << ', default' if s.default_gem? - entry << "\n" << " #{label} (#{version}): #{s.base_dir}" - label = ' ' * label.length - end - end - end - - def spec_platforms(entry, platforms) - non_ruby = platforms.any? do |_, pls| - pls.any? { |pl| pl != Gem::Platform::RUBY } - end - - return unless non_ruby - - if platforms.length == 1 - title = platforms.values.length == 1 ? 'Platform' : 'Platforms' - entry << " #{title}: #{platforms.values.sort.join(', ')}\n" - else - entry << " Platforms:\n" - - sorted_platforms = platforms.sort_by { |version,| version } - - sorted_platforms.each do |version, pls| - label = " #{version}: " - data = format_text pls.sort.join(', '), 68, label.length - data[0, label.length] = label - entry << data << "\n" - end - end - end - - def spec_summary(entry, spec) - summary = truncate_text(spec.summary, "the summary for #{spec.full_name}") - entry << "\n\n" << format_text(summary, 68, 4) - end - end diff --git a/ruby/lib/rubygems/commands/rdoc_command.rb b/ruby/lib/rubygems/commands/rdoc_command.rb index ff9e1ffcf..7c5d6212f 100644 --- a/ruby/lib/rubygems/commands/rdoc_command.rb +++ b/ruby/lib/rubygems/commands/rdoc_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/version_option' -require 'rubygems/rdoc' +require_relative '../command' +require_relative '../version_option' +require_relative '../rdoc' require 'fileutils' class Gem::Commands::RdocCommand < Gem::Command - include Gem::VersionOption def initialize @@ -62,12 +61,12 @@ def usage # :nodoc: def execute specs = if options[:all] - Gem::Specification.to_a - else - get_all_gem_names.map do |name| - Gem::Specification.find_by_name name, options[:version] - end.flatten.uniq - end + Gem::Specification.to_a + else + get_all_gem_names.map do |name| + Gem::Specification.find_by_name name, options[:version] + end.flatten.uniq + end if specs.empty? alert_error 'No matching gems found' @@ -93,5 +92,4 @@ def execute end end end - end diff --git a/ruby/lib/rubygems/commands/search_command.rb b/ruby/lib/rubygems/commands/search_command.rb index c9cb1f2d4..75d99986f 100644 --- a/ruby/lib/rubygems/commands/search_command.rb +++ b/ruby/lib/rubygems/commands/search_command.rb @@ -1,15 +1,16 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/commands/query_command' +require_relative '../command' +require_relative '../query_utils' -class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand +class Gem::Commands::SearchCommand < Gem::Command + include Gem::QueryUtils def initialize - super 'search', 'Display remote gems whose name matches REGEXP' + super 'search', 'Display remote gems whose name matches REGEXP', + :domain => :remote, :details => false, :versions => true, + :installed => nil, :version => Gem::Requirement.default - remove_option '--name-matches' - - defaults[:domain] = :remote + add_query_options end def arguments # :nodoc: @@ -36,5 +37,4 @@ def description # :nodoc: def usage # :nodoc: "#{program_name} [REGEXP]" end - end diff --git a/ruby/lib/rubygems/commands/server_command.rb b/ruby/lib/rubygems/commands/server_command.rb index e91a8e517..f8cad3b5d 100644 --- a/ruby/lib/rubygems/commands/server_command.rb +++ b/ruby/lib/rubygems/commands/server_command.rb @@ -1,86 +1,25 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/server' - -class Gem::Commands::ServerCommand < Gem::Command - - def initialize - super 'server', 'Documentation and gem repository HTTP server', - :port => 8808, :gemdir => [], :daemon => false - - OptionParser.accept :Port do |port| - if port =~ /\A\d+\z/ - port = Integer port - raise OptionParser::InvalidArgument, "#{port}: not a port number" if - port > 65535 - - port - else - begin - Socket.getservbyname port - rescue SocketError - raise OptionParser::InvalidArgument, "#{port}: no such named service" - end +require_relative '../command' + +unless defined? Gem::Commands::ServerCommand + class Gem::Commands::ServerCommand < Gem::Command + def initialize + super('server', 'Starts up a web server that hosts the RDoc (requires rubygems-server)') + begin + Gem::Specification.find_by_name('rubygems-server').activate + rescue Gem::LoadError + # no-op end end - add_option '-p', '--port=PORT', :Port, - 'port to listen on' do |port, options| - options[:port] = port - end - - add_option '-d', '--dir=GEMDIR', - 'directories from which to serve gems', - 'multiple directories may be provided' do |gemdir, options| - options[:gemdir] << File.expand_path(gemdir) + def description # :nodoc: + <<-EOF +The server command has been moved to the rubygems-server gem. + EOF end - add_option '--[no-]daemon', 'run as a daemon' do |daemon, options| - options[:daemon] = daemon + def execute + alert_error "Install the rubygems-server gem for the server command" end - - add_option '-b', '--bind=HOST,HOST', - 'addresses to bind', Array do |address, options| - options[:addresses] ||= [] - options[:addresses].push(*address) - end - - add_option '-l', '--launch[=COMMAND]', - 'launches a browser window', - "COMMAND defaults to 'start' on Windows", - "and 'open' on all other platforms" do |launch, options| - launch ||= Gem.win_platform? ? 'start' : 'open' - options[:launch] = launch - end - end - - def defaults_str # :nodoc: - "--port 8808 --dir #{Gem.dir} --no-daemon" end - - def description # :nodoc: - <<-EOF -The server command starts up a web server that hosts the RDoc for your -installed gems and can operate as a server for installation of gems on other -machines. - -The cache files for installed gems must exist to use the server as a source -for gem installation. - -To install gems from a running server, use `gem install GEMNAME --source -http://gem_server_host:8808` - -You can set up a shortcut to gem server documentation using the URL: - - http://localhost:8808/rdoc?q=%s - Firefox - http://localhost:8808/rdoc?q=* - LaunchBar - - EOF - end - - def execute - options[:gemdir] = Gem.path if options[:gemdir].empty? - Gem::Server.run options - end - end diff --git a/ruby/lib/rubygems/commands/setup_command.rb b/ruby/lib/rubygems/commands/setup_command.rb index 579776df7..01714f034 100644 --- a/ruby/lib/rubygems/commands/setup_command.rb +++ b/ruby/lib/rubygems/commands/setup_command.rb @@ -1,26 +1,24 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' ## # Installs RubyGems itself. This command is ordinarily only available from a # RubyGems checkout or tarball. class Gem::Commands::SetupCommand < Gem::Command - - HISTORY_HEADER = /^===\s*[\d.a-zA-Z]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze - VERSION_MATCHER = /^===\s*([\d.a-zA-Z]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze + HISTORY_HEADER = /^#\s*[\d.a-zA-Z]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze + VERSION_MATCHER = /^#\s*([\d.a-zA-Z]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze ENV_PATHS = %w[/usr/bin/env /bin/env].freeze def initialize - require 'tmpdir' - super 'setup', 'Install RubyGems', - :format_executable => true, :document => %w[ri], + :format_executable => false, :document => %w[ri], :force => true, :site_or_vendor => 'sitelibdir', :destdir => '', :prefix => '', :previous_version => '', - :regenerate_binstubs => true + :regenerate_binstubs => true, + :regenerate_plugins => true add_option '--previous-version=VERSION', 'Previous version of RubyGems', @@ -56,10 +54,10 @@ def initialize 'List the documentation types you wish to', 'generate. For example: rdoc,ri' do |value, options| options[:document] = case value - when nil then %w[rdoc ri] - when false then [] - else value - end + when nil then %w[rdoc ri] + when false then [] + else value + end end add_option '--[no-]rdoc', @@ -89,6 +87,11 @@ def initialize options[:regenerate_binstubs] = value end + add_option '--[no-]regenerate-plugins', + 'Regenerate gem plugins' do |value, options| + options[:regenerate_plugins] = value + end + add_option '-f', '--[no-]force', 'Forcefully overwrite binstubs' do |value, options| options[:force] = value @@ -144,13 +147,6 @@ def mkdir_p(path, **opts) def execute @verbose = Gem.configuration.really_verbose - install_destdir = options[:destdir] - - unless install_destdir.empty? - ENV['GEM_HOME'] ||= File.join(install_destdir, - Gem.default_dir.gsub(/^[a-zA-Z]:/, '')) - end - check_ruby_version require 'fileutils' @@ -161,7 +157,8 @@ def execute end extend MakeDirs - lib_dir, bin_dir = make_destination_dirs install_destdir + lib_dir, bin_dir = make_destination_dirs + man_dir = generate_default_man_dir install_lib lib_dir @@ -171,6 +168,9 @@ def execute remove_old_lib_files lib_dir + # Can be removed one we drop support for bundler 2.2.3 (the last version installing man files to man_dir) + remove_old_man_files man_dir if man_dir && File.exist?(man_dir) + install_default_bundler_gem bin_dir if mode = options[:dir_mode] @@ -180,7 +180,8 @@ def execute say "RubyGems #{Gem::VERSION} installed" - regenerate_binstubs if options[:regenerate_binstubs] + regenerate_binstubs(bin_dir) if options[:regenerate_binstubs] + regenerate_plugins(bin_dir) if options[:regenerate_plugins] uninstall_old_gemcutter @@ -205,7 +206,7 @@ def execute say say "RubyGems installed the following executables:" - say bin_file_names.map { |name| "\t#{name}\n" } + say bin_file_names.map {|name| "\t#{name}\n" } say unless bin_file_names.grep(/#{File::SEPARATOR}gem$/) @@ -248,35 +249,34 @@ def install_executables(bin_dir) say "Installing #{tool} executable" if @verbose Dir.chdir path do - bin_files = Dir['*'] - - bin_files -= %w[update_rubygems] + bin_file = "gem" - bin_files.each do |bin_file| - dest_file = target_bin_path(bin_dir, bin_file) - bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}" + require 'tmpdir' - begin - bin = File.readlines bin_file - bin[0] = shebang + dest_file = target_bin_path(bin_dir, bin_file) + bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}" - File.open bin_tmp_file, 'w' do |fp| - fp.puts bin.join - end + begin + bin = File.readlines bin_file + bin[0] = shebang - install bin_tmp_file, dest_file, :mode => prog_mode - bin_file_names << dest_file - ensure - rm bin_tmp_file + File.open bin_tmp_file, 'w' do |fp| + fp.puts bin.join end - next unless Gem.win_platform? + install bin_tmp_file, dest_file, :mode => prog_mode + bin_file_names << dest_file + ensure + rm bin_tmp_file + end + + next unless Gem.win_platform? - begin - bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat" + begin + bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat" - File.open bin_cmd_file, 'w' do |file| - file.puts <<-TEXT + File.open bin_cmd_file, 'w' do |file| + file.puts <<-TEXT @ECHO OFF IF NOT "%~f0" == "~f0" GOTO :WinNT @"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9 @@ -284,12 +284,11 @@ def install_executables(bin_dir) :WinNT @"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %* TEXT - end - - install bin_cmd_file, "#{dest_file}.bat", :mode => prog_mode - ensure - rm bin_cmd_file end + + install bin_cmd_file, "#{dest_file}.bat", :mode => prog_mode + ensure + rm bin_cmd_file end end end @@ -305,35 +304,16 @@ def shebang end end - def install_file(file, dest_dir) - dest_file = File.join dest_dir, file - dest_dir = File.dirname dest_file - unless File.directory? dest_dir - mkdir_p dest_dir, :mode => 0755 - end - - install file, dest_file, :mode => options[:data_mode] || 0644 - end - def install_lib(lib_dir) libs = { 'RubyGems' => 'lib' } libs['Bundler'] = 'bundler/lib' libs.each do |tool, path| say "Installing #{tool}" if @verbose - lib_files = rb_files_in path - lib_files.concat(template_files) if tool == 'Bundler' - - pem_files = pem_files_in path + lib_files = files_in path Dir.chdir path do - lib_files.each do |lib_file| - install_file lib_file, lib_dir - end - - pem_files.each do |pem_file| - install_file pem_file, lib_dir - end + install_file_list(lib_files, lib_dir) end end end @@ -357,7 +337,7 @@ def install_rdoc rm_rf dir end - require 'rubygems/rdoc' + require_relative '../rdoc' fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION def fake_spec.full_gem_path @@ -380,17 +360,10 @@ def fake_spec.full_gem_path end def install_default_bundler_gem(bin_dir) - specs_dir = Gem.default_specifications_dir - specs_dir = File.join(options[:destdir], specs_dir) unless Gem.win_platform? + specs_dir = File.join(default_dir, "specifications", "default") mkdir_p specs_dir, :mode => 0755 - # Workaround for non-git environment. - gemspec = File.open('bundler/bundler.gemspec', 'rb'){|f| f.read.gsub(/`git ls-files -z`/, "''") } - File.open('bundler/bundler.gemspec', 'w'){|f| f.write gemspec } - - bundler_spec = Gem::Specification.load("bundler/bundler.gemspec") - bundler_spec.files = Dir.chdir("bundler") { Dir["{*.md,{lib,exe,man}/**/*}"] } - bundler_spec.executables -= %w[bundler bundle_ruby] + bundler_spec = Dir.chdir("bundler") { Gem::Specification.load("bundler.gemspec") } # Remove bundler-*.gemspec in default specification directory. Dir.entries(specs_dir). @@ -402,8 +375,20 @@ def install_default_bundler_gem(bin_dir) bundler_spec = Gem::Specification.load(default_spec_path) + # The base_dir value for a specification is inferred by walking up from the + # folder where the spec was `loaded_from`. In the case of default gems, we + # walk up two levels, because they live at `specifications/default/`, whereas + # in the case of regular gems we walk up just one level because they live at + # `specifications/`. However, in this case, the gem we are installing is + # misdetected as a regular gem, when it's a default gem in reality. This is + # because when there's a `:destdir`, the `loaded_from` path has changed and + # doesn't match `Gem.default_specifications_dir` which is the criteria to + # tag a gem as a default gem. So, in that case, write the correct + # `@base_dir` directly. + bundler_spec.instance_variable_set(:@base_dir, File.dirname(File.dirname(specs_dir))) + # Remove gemspec that was same version of vendored bundler. - normal_gemspec = File.join(Gem.default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec") + normal_gemspec = File.join(default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec") if File.file? normal_gemspec File.delete normal_gemspec end @@ -416,19 +401,26 @@ def install_default_bundler_gem(bin_dir) end bundler_bin_dir = bundler_spec.bin_dir - bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform? mkdir_p bundler_bin_dir, :mode => 0755 bundler_spec.executables.each do |e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e) end - require 'rubygems/installer' + require_relative '../installer' Dir.chdir("bundler") do built_gem = Gem::Package.build(bundler_spec) begin - installer = Gem::Installer.at(built_gem, env_shebang: options[:env_shebang], format_executable: options[:format_executable], force: options[:force], install_as_default: true, bin_dir: bin_dir, wrappers: true) - installer.install + Gem::Installer.at( + built_gem, + env_shebang: options[:env_shebang], + format_executable: options[:format_executable], + force: options[:force], + install_as_default: true, + bin_dir: bin_dir, + install_dir: default_dir, + wrappers: true + ).install ensure FileUtils.rm_f built_gem end @@ -439,11 +431,11 @@ def install_default_bundler_gem(bin_dir) say "Bundler #{bundler_spec.version} installed" end - def make_destination_dirs(install_destdir) + def make_destination_dirs lib_dir, bin_dir = Gem.default_rubygems_dirs unless lib_dir - lib_dir, bin_dir = generate_default_dirs(install_destdir) + lib_dir, bin_dir = generate_default_dirs end mkdir_p lib_dir, :mode => 0755 @@ -452,63 +444,38 @@ def make_destination_dirs(install_destdir) return lib_dir, bin_dir end - def generate_default_dirs(install_destdir) + def generate_default_man_dir prefix = options[:prefix] - site_or_vendor = options[:site_or_vendor] if prefix.empty? - lib_dir = RbConfig::CONFIG[site_or_vendor] - bin_dir = RbConfig::CONFIG['bindir'] + man_dir = RbConfig::CONFIG['mandir'] + return unless man_dir else - # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets - # confused about installation location, so switch back to - # sitelibdir/vendorlibdir. - if defined?(APPLE_GEM_HOME) and - # just in case Apple and RubyGems don't get this patched up proper. - (prefix == RbConfig::CONFIG['libdir'] or - # this one is important - prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby')) - lib_dir = RbConfig::CONFIG[site_or_vendor] - bin_dir = RbConfig::CONFIG['bindir'] - else - lib_dir = File.join prefix, 'lib' - bin_dir = File.join prefix, 'bin' - end + man_dir = File.join prefix, 'man' end - unless install_destdir.empty? - lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '') - bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '') - end - - [lib_dir, bin_dir] + prepend_destdir_if_present(man_dir) end - def pem_files_in(dir) - Dir.chdir dir do - Dir[File.join('**', '*pem')] - end - end + def generate_default_dirs + prefix = options[:prefix] + site_or_vendor = options[:site_or_vendor] - def rb_files_in(dir) - Dir.chdir dir do - Dir[File.join('**', '*rb')] + if prefix.empty? + lib_dir = RbConfig::CONFIG[site_or_vendor] + bin_dir = RbConfig::CONFIG['bindir'] + else + lib_dir = File.join prefix, 'lib' + bin_dir = File.join prefix, 'bin' end - end - # for installation of bundler as default gems - def template_files - Dir.chdir "bundler/lib" do - (Dir[File.join('bundler', 'templates', '**', '{*,.*}')]). - select{|f| !File.directory?(f)} - end + [prepend_destdir_if_present(lib_dir), prepend_destdir_if_present(bin_dir)] end - # for cleanup old bundler files - def template_files_in(dir) + def files_in(dir) Dir.chdir dir do - (Dir[File.join('templates', '**', '{*,.*}')]). - select{|f| !File.directory?(f)} + Dir.glob(File.join('**', '*'), File::FNM_DOTMATCH). + select{|f| !File.directory?(f) } end end @@ -539,7 +506,7 @@ def remove_old_bin_files(bin_dir) next unless Gem.win_platform? File.open "#{old_bin_path}.bat", 'w' do |fp| - fp.puts %{@ECHO.#{deprecation_message}} + fp.puts %(@ECHO.#{deprecation_message}) end end end @@ -548,31 +515,43 @@ def remove_old_lib_files(lib_dir) lib_dirs = { File.join(lib_dir, 'rubygems') => 'lib/rubygems' } lib_dirs[File.join(lib_dir, 'bundler')] = 'bundler/lib/bundler' lib_dirs.each do |old_lib_dir, new_lib_dir| - lib_files = rb_files_in(new_lib_dir) - lib_files.concat(template_files_in(new_lib_dir)) if new_lib_dir =~ /bundler/ + lib_files = files_in(new_lib_dir) - old_lib_files = rb_files_in(old_lib_dir) - old_lib_files.concat(template_files_in(old_lib_dir)) if old_lib_dir =~ /bundler/ + old_lib_files = files_in(old_lib_dir) to_remove = old_lib_files - lib_files + gauntlet_rubygems = File.join(lib_dir, 'gauntlet_rubygems.rb') + to_remove << gauntlet_rubygems if File.exist? gauntlet_rubygems + to_remove.delete_if do |file| file.start_with? 'defaults' end - Dir.chdir old_lib_dir do - to_remove.each do |file| - FileUtils.rm_f file + remove_file_list(to_remove, old_lib_dir) + end + end - warn "unable to remove old file #{file} please remove it by hand" if - File.exist? file - end - end + def remove_old_man_files(old_man_dir) + old_man1_dir = "#{old_man_dir}/man1" + + if File.exist?(old_man1_dir) + man1_to_remove = Dir.chdir(old_man1_dir) { Dir["bundle*.1{,.txt,.ronn}"] } + + remove_file_list(man1_to_remove, old_man1_dir) + end + + old_man5_dir = "#{old_man_dir}/man5" + + if File.exist?(old_man5_dir) + man5_to_remove = Dir.chdir(old_man5_dir) { Dir["gemfile.5{,.txt,.ronn}"] } + + remove_file_list(man5_to_remove, old_man5_dir) end end def show_release_notes - release_notes = File.join Dir.pwd, 'History.txt' + release_notes = File.join Dir.pwd, 'CHANGELOG.md' release_notes = if File.exist? release_notes @@ -580,8 +559,6 @@ def show_release_notes history.force_encoding Encoding::UTF_8 - history = history.sub(/^# coding:.*?(?=^=)/m, '') - text = history.split(HISTORY_HEADER) text.shift # correct an off-by-one generated by split version_lines = history.scan(HISTORY_HEADER) @@ -605,7 +582,7 @@ def show_release_notes end def uninstall_old_gemcutter - require 'rubygems/uninstaller' + require_relative '../uninstaller' ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true, :version => '< 0.4') @@ -613,11 +590,12 @@ def uninstall_old_gemcutter rescue Gem::InstallError end - def regenerate_binstubs - require "rubygems/commands/pristine_command" + def regenerate_binstubs(bindir) + require_relative "pristine_command" say "Regenerating binstubs" args = %w[--all --only-executables --silent] + args << "--bindir=#{bindir}" if options[:env_shebang] args << "--env-shebang" end @@ -626,19 +604,76 @@ def regenerate_binstubs command.invoke(*args) end + def regenerate_plugins(bindir) + require_relative "pristine_command" + say "Regenerating plugins" + + args = %w[--all --only-plugins --silent] + args << "--bindir=#{bindir}" + args << "--install-dir=#{default_dir}" + + command = Gem::Commands::PristineCommand.new + command.invoke(*args) + end + private + def default_dir + prefix = options[:prefix] + + if prefix.empty? + dir = Gem.default_dir + else + dir = prefix + end + + prepend_destdir_if_present(dir) + end + + def prepend_destdir_if_present(path) + destdir = options[:destdir] + return path if destdir.empty? + + File.join(options[:destdir], path.gsub(/^[a-zA-Z]:/, '')) + end + + def install_file_list(files, dest_dir) + files.each do |file| + install_file file, dest_dir + end + end + + def install_file(file, dest_dir) + dest_file = File.join dest_dir, file + dest_dir = File.dirname dest_file + unless File.directory? dest_dir + mkdir_p dest_dir, :mode => 0755 + end + + install file, dest_file, :mode => options[:data_mode] || 0644 + end + + def remove_file_list(files, dir) + Dir.chdir dir do + files.each do |file| + FileUtils.rm_f file + + warn "unable to remove old file #{file} please remove it by hand" if + File.exist? file + end + end + end + def target_bin_path(bin_dir, bin_file) bin_file_formatted = if options[:format_executable] - Gem.default_exec_format % bin_file - else - bin_file - end + Gem.default_exec_format % bin_file + else + bin_file + end File.join bin_dir, bin_file_formatted end def bin_file_names @bin_file_names ||= [] end - end diff --git a/ruby/lib/rubygems/commands/signin_command.rb b/ruby/lib/rubygems/commands/signin_command.rb index 7c4b5ceb6..23bb2f937 100644 --- a/ruby/lib/rubygems/commands/signin_command.rb +++ b/ruby/lib/rubygems/commands/signin_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/gemcutter_utilities' +require_relative '../command' +require_relative '../gemcutter_utilities' class Gem::Commands::SigninCommand < Gem::Command - include Gem::GemcutterUtilities def initialize @@ -31,5 +30,4 @@ def usage # :nodoc: def execute sign_in options[:host] end - end diff --git a/ruby/lib/rubygems/commands/signout_command.rb b/ruby/lib/rubygems/commands/signout_command.rb index 2d7329c59..c9485e0c1 100644 --- a/ruby/lib/rubygems/commands/signout_command.rb +++ b/ruby/lib/rubygems/commands/signout_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::SignoutCommand < Gem::Command - def initialize super 'signout', 'Sign out from all the current sessions.' end @@ -29,5 +28,4 @@ def execute say 'You have successfully signed out from all sessions.' end end - end diff --git a/ruby/lib/rubygems/commands/sources_command.rb b/ruby/lib/rubygems/commands/sources_command.rb index feab23237..9e74f3c47 100644 --- a/ruby/lib/rubygems/commands/sources_command.rb +++ b/ruby/lib/rubygems/commands/sources_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/remote_fetcher' -require 'rubygems/spec_fetcher' -require 'rubygems/local_remote_options' +require_relative '../command' +require_relative '../remote_fetcher' +require_relative '../spec_fetcher' +require_relative '../local_remote_options' class Gem::Commands::SourcesCommand < Gem::Command - include Gem::LocalRemoteOptions def initialize @@ -35,6 +34,10 @@ def initialize options[:update] = value end + add_option '-f', '--[no-]force', "Do not show any confirmation prompts and behave as if 'yes' was always answered" do |value, options| + options[:force] = value + end + add_proxy_option end @@ -72,7 +75,7 @@ def check_typo_squatting(source) Do you want to add this source? QUESTION - terminate_interaction 1 unless ask_yes_no question + terminate_interaction 1 unless options[:force] || ask_yes_no(question) end end @@ -87,7 +90,7 @@ def check_rubygems_https(source_uri) # :nodoc: Do you want to add this insecure source? QUESTION - terminate_interaction 1 unless ask_yes_no question + terminate_interaction 1 unless options[:force] || ask_yes_no(question) end end @@ -136,7 +139,7 @@ def description # :nodoc: its history: * http://gems.rubyforge.org (RubyGems 1.3.6 and earlier) -* http://rubygems.org (RubyGems 1.3.7 through 1.8.25) +* https://rubygems.org/ (RubyGems 1.3.7 through 1.8.25) * https://rubygems.org (RubyGems 2.0.1 and newer) Since all of these sources point to the same set of gems you only need one @@ -153,8 +156,8 @@ def description # :nodoc: To remove a source use the --remove argument: - $ gem sources --remove http://rubygems.org - http://rubygems.org removed from sources + $ gem sources --remove https://rubygems.org/ + https://rubygems.org/ removed from sources EOF end @@ -220,5 +223,4 @@ def remove_cache_file(desc, path) # :nodoc: say "*** Unable to remove #{desc} source cache ***" end end - end diff --git a/ruby/lib/rubygems/commands/specification_command.rb b/ruby/lib/rubygems/commands/specification_command.rb index 7326822ad..6f2478796 100644 --- a/ruby/lib/rubygems/commands/specification_command.rb +++ b/ruby/lib/rubygems/commands/specification_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/version_option' -require 'rubygems/package' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../version_option' +require_relative '../package' class Gem::Commands::SpecificationCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::VersionOption @@ -119,7 +118,7 @@ def execute dep.prerelease = options[:prerelease] found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep - specs.push(*found.map { |spec,| spec }) + specs.push(*found.map {|spec,| spec }) end if specs.empty? @@ -127,21 +126,26 @@ def execute terminate_interaction 1 end + platform = get_platform_from_requirements(options) + + if platform + specs = specs.select{|s| s.platform.to_s == platform } + end + unless options[:all] - specs = [specs.max_by { |s| s.version }] + specs = [specs.max_by {|s| s.version }] end specs.each do |s| s = s.send field if field say case options[:format] - when :ruby then s.to_ruby - when :marshal then Marshal.dump s - else s.to_yaml - end + when :ruby then s.to_ruby + when :marshal then Marshal.dump s + else s.to_yaml + end say "\n" end end - end diff --git a/ruby/lib/rubygems/commands/stale_command.rb b/ruby/lib/rubygems/commands/stale_command.rb index 89bafeae9..62a97966f 100644 --- a/ruby/lib/rubygems/commands/stale_command.rb +++ b/ruby/lib/rubygems/commands/stale_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::StaleCommand < Gem::Command - def initialize super('stale', 'List gems along with access times') end @@ -33,9 +32,8 @@ def execute end end - gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime| + gem_to_atime.sort_by {|_, atime| atime }.each do |name, atime| say "#{name} at #{atime.strftime '%c'}" end end - end diff --git a/ruby/lib/rubygems/commands/uninstall_command.rb b/ruby/lib/rubygems/commands/uninstall_command.rb index 68e048c01..467c8bf7e 100644 --- a/ruby/lib/rubygems/commands/uninstall_command.rb +++ b/ruby/lib/rubygems/commands/uninstall_command.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/version_option' -require 'rubygems/uninstaller' +require_relative '../command' +require_relative '../version_option' +require_relative '../uninstaller' require 'fileutils' ## @@ -10,7 +10,6 @@ # See `gem help uninstall` class Gem::Commands::UninstallCommand < Gem::Command - include Gem::VersionOption def initialize @@ -82,7 +81,7 @@ def initialize 'Uninstall gem from the vendor directory.', 'Only for use by gem repackagers.') do |value, options| unless Gem.vendor_dir - raise OptionParser::InvalidOption.new 'your platform is not supported' + raise Gem::OptionParser::InvalidOption.new 'your platform is not supported' end alert_warning 'Use your OS package manager to uninstall vendor gems' @@ -136,14 +135,14 @@ def execute end def uninstall_all - specs = Gem::Specification.reject { |spec| spec.default_gem? } + specs = Gem::Specification.reject {|spec| spec.default_gem? } specs.each do |spec| options[:version] = spec.version uninstall_gem spec.name end - alert "Uninstalled all gems in #{options[:install_dir]}" + alert "Uninstalled all gems in #{options[:install_dir] || Gem.dir}" end def uninstall_specific @@ -195,5 +194,4 @@ def uninstall_gem(gem_name) def uninstall(gem_name) Gem::Uninstaller.new(gem_name, options).uninstall end - end diff --git a/ruby/lib/rubygems/commands/unpack_command.rb b/ruby/lib/rubygems/commands/unpack_command.rb index 09829d873..3f1708375 100644 --- a/ruby/lib/rubygems/commands/unpack_command.rb +++ b/ruby/lib/rubygems/commands/unpack_command.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/version_option' -require 'rubygems/security_option' -require 'rubygems/remote_fetcher' -require 'rubygems/package' +require_relative '../command' +require_relative '../version_option' +require_relative '../security_option' +require_relative '../remote_fetcher' +require_relative '../package' # forward-declare @@ -13,7 +13,6 @@ class Policy # :nodoc: end class Gem::Commands::UnpackCommand < Gem::Command - include Gem::VersionOption include Gem::SecurityOption @@ -157,7 +156,7 @@ def get_path(dependency) specs = dependency.matching_specs - selected = specs.max_by { |s| s.version } + selected = specs.max_by {|s| s.version } return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless selected @@ -173,5 +172,4 @@ def get_path(dependency) path end - end diff --git a/ruby/lib/rubygems/commands/update_command.rb b/ruby/lib/rubygems/commands/update_command.rb index e8031a259..42d6f6046 100644 --- a/ruby/lib/rubygems/commands/update_command.rb +++ b/ruby/lib/rubygems/commands/update_command.rb @@ -1,16 +1,15 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/command_manager' -require 'rubygems/dependency_installer' -require 'rubygems/install_update_options' -require 'rubygems/local_remote_options' -require 'rubygems/spec_fetcher' -require 'rubygems/version_option' -require 'rubygems/install_message' # must come before rdoc for messaging -require 'rubygems/rdoc' +require_relative '../command' +require_relative '../command_manager' +require_relative '../dependency_installer' +require_relative '../install_update_options' +require_relative '../local_remote_options' +require_relative '../spec_fetcher' +require_relative '../version_option' +require_relative '../install_message' # must come before rdoc for messaging +require_relative '../rdoc' class Gem::Commands::UpdateCommand < Gem::Command - include Gem::InstallUpdateOptions include Gem::LocalRemoteOptions include Gem::VersionOption @@ -20,13 +19,17 @@ class Gem::Commands::UpdateCommand < Gem::Command attr_reader :updated # :nodoc: def initialize - super 'update', 'Update installed gems to the latest version', - :document => %w[rdoc ri], - :force => false + options = { + :force => false, + } + + options.merge!(install_update_options) + + super 'update', 'Update installed gems to the latest version', options add_install_update_options - OptionParser.accept Gem::Version do |value| + Gem::OptionParser.accept Gem::Version do |value| Gem::Version.new value value @@ -52,7 +55,8 @@ def arguments # :nodoc: end def defaults_str # :nodoc: - "--document --no-force --install-dir #{Gem.dir}" + "--no-force --install-dir #{Gem.dir}\n" + + install_update_defaults_str end def description # :nodoc: @@ -73,8 +77,13 @@ def check_latest_rubygems(version) # :nodoc: say "Latest version already installed. Done." terminate_interaction end + end - options[:user_install] = false + def check_oldest_rubygems(version) # :nodoc: + if oldest_supported_version > version + alert_error "rubygems #{version} is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is #{oldest_supported_version}" + terminate_interaction 1 + end end def check_update_arguments # :nodoc: @@ -90,9 +99,10 @@ def execute return end - hig = highest_installed_gems - - gems_to_update = which_to_update hig, options[:args].uniq + gems_to_update = which_to_update( + highest_installed_gems, + options[:args].uniq + ) if options[:explain] say "Gems to update:" @@ -108,7 +118,7 @@ def execute updated = update_gems gems_to_update - updated_names = updated.map { |spec| spec.name } + updated_names = updated.map {|spec| spec.name } not_updated_names = options[:args].uniq - updated_names if updated.empty? @@ -127,7 +137,7 @@ def fetch_remote_gems(spec) # :nodoc: spec_tuples, errors = fetcher.search_for_dependency dependency - error = errors.find { |e| e.respond_to? :exception } + error = errors.find {|e| e.respond_to? :exception } raise error if error @@ -137,6 +147,9 @@ def fetch_remote_gems(spec) # :nodoc: def highest_installed_gems # :nodoc: hig = {} # highest installed gems + # Get only gem specifications installed as --user-install + Gem::Specification.dirs = Gem.user_dir if options[:user_install] + Gem::Specification.each do |spec| if hig[spec.name].nil? or hig[spec.name].version < spec.version hig[spec.name] = spec @@ -166,10 +179,33 @@ def install_rubygems(version) # :nodoc: update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}" Dir.chdir update_dir do - say "Installing RubyGems #{version}" + say "Installing RubyGems #{version}" unless options[:silent] + + installed = preparing_gem_layout_for(version) do + system Gem.ruby, '--disable-gems', 'setup.rb', *args + end - installed = system Gem.ruby, '--disable-gems', 'setup.rb', *args - say "RubyGems system software updated" if installed + say "RubyGems system software updated" if installed unless options[:silent] + end + end + + def preparing_gem_layout_for(version) + if Gem::Version.new(version) >= Gem::Version.new("3.2.a") + yield + else + require "tmpdir" + tmpdir = Dir.mktmpdir + FileUtils.mv Gem.plugindir, tmpdir + + status = yield + + if status + FileUtils.rm_rf tmpdir + else + FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugindir + end + + status end end @@ -190,30 +226,30 @@ def rubygems_target_version rubygems_update.version = version hig = { - 'rubygems-update' => rubygems_update + 'rubygems-update' => rubygems_update, } gems_to_update = which_to_update hig, options[:args], :system up_ver = gems_to_update.first.version target = if update_latest - up_ver - else - version - end + up_ver + else + version + end return target, requirement end def update_gem(name, version = Gem::Requirement.default) - return if @updated.any? { |spec| spec.name == name } + return if @updated.any? {|spec| spec.name == name } update_options = options.dup update_options[:prerelease] = version.prerelease? @installer = Gem::DependencyInstaller.new update_options - say "Updating #{name}" + say "Updating #{name}" unless options[:system] && options[:silent] begin @installer.install name, Gem::Requirement.new(version) rescue Gem::InstallError, Gem::DependencyError => e @@ -237,22 +273,31 @@ def update_gems(gems_to_update) # Update RubyGems software to the latest version. def update_rubygems + if Gem.disable_system_update_message + alert_error Gem.disable_system_update_message + terminate_interaction 1 + end + check_update_arguments version, requirement = rubygems_target_version check_latest_rubygems version - update_gem 'rubygems-update', version + check_oldest_rubygems version installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement - version = installed_gems.first.version + installed_gems = update_gem('rubygems-update', version) if installed_gems.empty? || installed_gems.first.version != version + return if installed_gems.empty? + + version = installed_gems.first.version install_rubygems version end def update_rubygems_arguments # :nodoc: args = [] + args << '--silent' if options[:silent] args << '--prefix' << Gem.prefix if Gem.prefix args << '--no-document' unless options[:document].include?('rdoc') || options[:document].include?('ri') args << '--no-format-executable' if options[:no_format_executable] @@ -267,7 +312,7 @@ def which_to_update(highest_installed_gems, gem_names, system = false) highest_installed_gems.each do |l_name, l_spec| next if not gem_names.empty? and - gem_names.none? { |name| name == l_spec.name } + gem_names.none? {|name| name == l_spec.name } highest_remote_tup = highest_remote_name_tuple l_spec highest_remote_ver = highest_remote_tup.version @@ -281,4 +326,30 @@ def which_to_update(highest_installed_gems, gem_names, system = false) result end + private + + # + # Oldest version we support downgrading to. This is the version that + # originally ships with the first patch version of each ruby, because we never + # test each ruby against older rubygems, so we can't really guarantee it + # works. Version list can be checked here: https://stdgems.org/rubygems + # + def oldest_supported_version + @oldest_supported_version ||= + if Gem.ruby_version > Gem::Version.new("3.1.a") + Gem::Version.new("3.3.3") + elsif Gem.ruby_version > Gem::Version.new("3.0.a") + Gem::Version.new("3.2.3") + elsif Gem.ruby_version > Gem::Version.new("2.7.a") + Gem::Version.new("3.1.2") + elsif Gem.ruby_version > Gem::Version.new("2.6.a") + Gem::Version.new("3.0.1") + elsif Gem.ruby_version > Gem::Version.new("2.5.a") + Gem::Version.new("2.7.3") + elsif Gem.ruby_version > Gem::Version.new("2.4.a") + Gem::Version.new("2.6.8") + else + Gem::Version.new("2.5.2") + end + end end diff --git a/ruby/lib/rubygems/commands/which_command.rb b/ruby/lib/rubygems/commands/which_command.rb index fca463a1e..44e87a2b9 100644 --- a/ruby/lib/rubygems/commands/which_command.rb +++ b/ruby/lib/rubygems/commands/which_command.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/command' +require_relative '../command' class Gem::Commands::WhichCommand < Gem::Command - def initialize super 'which', 'Find the location of a library file you can require', :search_gems_first => false, :show_all => false @@ -85,5 +84,4 @@ def find_paths(package_name, dirs) def usage # :nodoc: "#{program_name} FILE [FILE ...]" end - end diff --git a/ruby/lib/rubygems/commands/yank_command.rb b/ruby/lib/rubygems/commands/yank_command.rb index 3ca05756f..cad78aec5 100644 --- a/ruby/lib/rubygems/commands/yank_command.rb +++ b/ruby/lib/rubygems/commands/yank_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/command' -require 'rubygems/local_remote_options' -require 'rubygems/version_option' -require 'rubygems/gemcutter_utilities' +require_relative '../command' +require_relative '../local_remote_options' +require_relative '../version_option' +require_relative '../gemcutter_utilities' class Gem::Commands::YankCommand < Gem::Command - include Gem::LocalRemoteOptions include Gem::VersionOption include Gem::GemcutterUtilities @@ -25,7 +24,7 @@ def arguments # :nodoc: end def usage # :nodoc: - "#{program_name} GEM -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST]" + "#{program_name} -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST] GEM" end def initialize @@ -48,7 +47,7 @@ def initialize def execute @host = options[:host] - sign_in @host + sign_in @host, scope: get_yank_scope version = get_version_from_requirements(options[:version]) platform = get_platform_from_requirements(options) @@ -73,9 +72,8 @@ def yank_gem(version, platform) def yank_api_request(method, version, platform, api) name = get_one_gem_name - response = rubygems_api_request(method, api, host) do |request| + response = rubygems_api_request(method, api, host, scope: get_yank_scope) do |request| request.add_field("Authorization", api_key) - request.add_field("OTP", options[:otp]) if options[:otp] data = { 'gem_name' => name, @@ -94,8 +92,7 @@ def get_version_from_requirements(requirements) nil end - def get_platform_from_requirements(requirements) - Gem.platforms[1].to_s if requirements.key? :added_platform + def get_yank_scope + :yank_rubygem end - end diff --git a/ruby/lib/rubygems/config_file.rb b/ruby/lib/rubygems/config_file.rb index 54d8a9c15..5dd2bfe88 100644 --- a/ruby/lib/rubygems/config_file.rb +++ b/ruby/lib/rubygems/config_file.rb @@ -5,7 +5,7 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/user_interaction' +require_relative 'user_interaction' require 'rbconfig' ## @@ -37,7 +37,6 @@ # - per environment (gemrc files listed in the GEMRC environment variable) class Gem::ConfigFile - include Gem::UserInteraction DEFAULT_BACKTRACE = false @@ -46,6 +45,7 @@ class Gem::ConfigFile DEFAULT_UPDATE_SOURCES = true DEFAULT_CONCURRENT_DOWNLOADS = 8 DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365 + DEFAULT_IPV4_FALLBACK_ENABLED = false ## # For Ruby packagers to set configuration defaults. Set in @@ -141,6 +141,12 @@ class Gem::ConfigFile attr_accessor :cert_expiration_length_days + ## + # == Experimental == + # Fallback to IPv4 when IPv6 is not reachable or slow (default: false) + + attr_accessor :ipv4_fallback_enabled + ## # Path name of directory or file of openssl client certificate, used for remote https connection with client authentication @@ -176,6 +182,7 @@ def initialize(args) @update_sources = DEFAULT_UPDATE_SOURCES @concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS @cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS + @ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS) platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS) @@ -204,6 +211,7 @@ def initialize(args) @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server @sources = @hash[:sources] if @hash.key? :sources @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days + @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert @@ -261,17 +269,22 @@ def check_credentials_permissions # Location of RubyGems.org credentials def credentials_path - File.join Gem.user_home, '.gem', 'credentials' + credentials = File.join Gem.user_home, '.gem', 'credentials' + if File.exist? credentials + credentials + else + File.join Gem.data_home, "gem", "credentials" + end end def load_api_keys check_credentials_permissions @api_keys = if File.exist? credentials_path - load_file(credentials_path) - else - @hash - end + load_file(credentials_path) + else + @hash + end if @api_keys.key? :rubygems_api_key @rubygems_api_key = @api_keys[:rubygems_api_key] @@ -307,7 +320,8 @@ def set_api_key(host, api_key) config = load_file(credentials_path).merge(host => api_key) dirname = File.dirname credentials_path - Dir.mkdir(dirname) unless File.exist? dirname + require 'fileutils' + FileUtils.mkdir_p(dirname) Gem.load_yaml @@ -429,7 +443,7 @@ def to_yaml # :nodoc: yaml_hash[:ssl_client_cert] = @hash[:ssl_client_cert] if @hash.key? :ssl_client_cert - keys = yaml_hash.keys.map { |key| key.to_s } + keys = yaml_hash.keys.map {|key| key.to_s } keys << 'debug' re = Regexp.union(*keys) @@ -444,6 +458,9 @@ def to_yaml # :nodoc: # Writes out this config file, replacing its source. def write + require 'fileutils' + FileUtils.mkdir_p File.dirname(config_file_name) + File.open config_file_name, 'w' do |io| io.write to_yaml end @@ -488,5 +505,4 @@ def set_config_file_name(args) end end end - end diff --git a/ruby/lib/rubygems/core_ext/kernel_require.rb b/ruby/lib/rubygems/core_ext/kernel_require.rb index 60f4d1871..4b867c55e 100644 --- a/ruby/lib/rubygems/core_ext/kernel_require.rb +++ b/ruby/lib/rubygems/core_ext/kernel_require.rb @@ -17,6 +17,8 @@ module Kernel private :gem_original_require end + file = Gem::KERNEL_WARN_IGNORES_INTERNAL_ENTRIES ? "" : __FILE__ + module_eval <<'RUBY', file, __LINE__ + 1 ## # When RubyGems is required, Kernel#require is replaced with our own which # is capable of loading gems on demand. @@ -39,49 +41,40 @@ def require(path) path = path.to_path if path.respond_to? :to_path - # Ensure -I beats a default gem - # https://github.com/rubygems/rubygems/pull/1868 - resolved_path = begin - rp = nil - $LOAD_PATH[0...Gem.load_path_insert_index || -1].each do |lp| - safe_lp = lp.dup.tap(&Gem::UNTAINT) - begin - if File.symlink? safe_lp # for backward compatibility - next - end - rescue SecurityError - RUBYGEMS_ACTIVATION_MONITOR.exit - raise - end - + if spec = Gem.find_unresolved_default_spec(path) + # Ensure -I beats a default gem + resolved_path = begin + rp = nil + load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths Gem.suffixes.each do |s| - full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}")) - if File.file?(full_path) - rp = full_path - break + $LOAD_PATH[0...load_path_check_index].each do |lp| + safe_lp = lp.dup.tap(&Gem::UNTAINT) + begin + if File.symlink? safe_lp # for backward compatibility + next + end + rescue SecurityError + RUBYGEMS_ACTIVATION_MONITOR.exit + raise + end + + full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}")) + if File.file?(full_path) + rp = full_path + break + end end + break if rp end - break if rp - end - rp - end - - if resolved_path - begin - RUBYGEMS_ACTIVATION_MONITOR.exit - return gem_original_require(resolved_path) - rescue LoadError - RUBYGEMS_ACTIVATION_MONITOR.enter + rp end - end - if spec = Gem.find_unresolved_default_spec(path) begin Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) rescue Exception RUBYGEMS_ACTIVATION_MONITOR.exit raise - end + end unless resolved_path end # If there are no unresolved deps, then we can use just try @@ -139,7 +132,7 @@ def require(path) # Ok, now find a gem that has no conflicts, starting # at the highest version. - valid = found_specs.find { |s| !s.has_conflicts? } + valid = found_specs.find {|s| !s.has_conflicts? } unless valid le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" @@ -157,8 +150,7 @@ def require(path) RUBYGEMS_ACTIVATION_MONITOR.enter begin - if load_error.message.start_with?("Could not find") or - (load_error.message.end_with?(path) and Gem.try_activate(path)) + if load_error.path == path and Gem.try_activate(path) require_again = true end ensure @@ -176,6 +168,7 @@ def require(path) end end end +RUBY private :require diff --git a/ruby/lib/rubygems/core_ext/kernel_warn.rb b/ruby/lib/rubygems/core_ext/kernel_warn.rb index dfc577df0..3373cfdd3 100644 --- a/ruby/lib/rubygems/core_ext/kernel_warn.rb +++ b/ruby/lib/rubygems/core_ext/kernel_warn.rb @@ -1,27 +1,25 @@ # frozen_string_literal: true # `uplevel` keyword argument of Kernel#warn is available since ruby 2.5. -if RUBY_VERSION >= "2.5" +if RUBY_VERSION >= "2.5" && !Gem::KERNEL_WARN_IGNORES_INTERNAL_ENTRIES module Kernel - path = "#{__dir__}/" # Frames to be skipped start with this path. + rubygems_path = "#{__dir__}/" # Frames to be skipped start with this path. - original_warn = method(:warn) + original_warn = instance_method(:warn) remove_method :warn class << self - remove_method :warn - end module_function define_method(:warn) {|*messages, **kw| unless uplevel = kw[:uplevel] if Gem.java_platform? - return original_warn.call(*messages) + return original_warn.bind(self).call(*messages) else - return original_warn.call(*messages, **kw) + return original_warn.bind(self).call(*messages, **kw) end end @@ -40,16 +38,17 @@ class << self start += 1 - unless loc.path.start_with?(path) - # Non-rubygems frames - uplevel -= 1 + if path = loc.path + unless path.start_with?(rubygems_path) or path.start_with?(' 0 + cond_var.wait(mutex, remaining_time) + end + + host = addrs.shift unless addrs.empty? + end + + threads.each {|t| t.kill.join if t.alive? } + + super(host, serv, *rest) + end + end + end +end + +TCPSocket.prepend CoreExtensions::TCPSocketExt diff --git a/ruby/lib/rubygems/defaults.rb b/ruby/lib/rubygems/defaults.rb index d4ff4a262..39b69ddb1 100644 --- a/ruby/lib/rubygems/defaults.rb +++ b/ruby/lib/rubygems/defaults.rb @@ -20,7 +20,13 @@ def self.default_sources # specified in the environment def self.default_spec_cache_dir - File.join Gem.user_home, '.gem', 'specs' + default_spec_cache_dir = File.join Gem.user_home, '.gem', 'specs' + + unless File.exist?(default_spec_cache_dir) + default_spec_cache_dir = File.join Gem.data_home, 'gem', 'specs' + end + + default_spec_cache_dir end ## @@ -28,21 +34,7 @@ def self.default_spec_cache_dir # specified in the environment def self.default_dir - path = if defined? RUBY_FRAMEWORK_VERSION - [ - File.dirname(RbConfig::CONFIG['sitedir']), - 'Gems', - RbConfig::CONFIG['ruby_version'] - ] - else - [ - RbConfig::CONFIG['rubylibprefix'], - 'gems', - RbConfig::CONFIG['ruby_version'] - ] - end - - @default_dir ||= File.join(*path) + @default_dir ||= File.join(RbConfig::CONFIG['rubylibprefix'], 'gems', RbConfig::CONFIG['ruby_version']) end ## @@ -67,18 +59,94 @@ def self.default_rubygems_dirs # Path to specification files of default gems. def self.default_specifications_dir - File.join(Gem.default_dir, "specifications", "default") + @default_specifications_dir ||= File.join(Gem.default_dir, "specifications", "default") + end + + ## + # Finds the user's home directory. + #-- + # Some comments from the ruby-talk list regarding finding the home + # directory: + # + # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems + # to be depending on HOME in those code samples. I propose that + # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at + # least on Win32). + #++ + #-- + # + #++ + + def self.find_home + Dir.home.dup + rescue + if Gem.win_platform? + File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/') + else + File.expand_path "/" + end + end + + private_class_method :find_home + + ## + # The home directory for the user. + + def self.user_home + @user_home ||= find_home.tap(&Gem::UNTAINT) end ## # Path for gems in the user's home directory def self.user_dir - parts = [Gem.user_home, '.gem', ruby_engine] + gem_dir = File.join(Gem.user_home, ".gem") + gem_dir = File.join(Gem.data_home, "gem") unless File.exist?(gem_dir) + parts = [gem_dir, ruby_engine] parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? File.join parts end + ## + # The path to standard location of the user's configuration directory. + + def self.config_home + @config_home ||= (ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, '.config')) + end + + ## + # Finds the user's config file + + def self.find_config_file + gemrc = File.join Gem.user_home, '.gemrc' + if File.exist? gemrc + gemrc + else + File.join Gem.config_home, "gem", "gemrc" + end + end + + ## + # The path to standard location of the user's .gemrc file. + + def self.config_file + @config_file ||= find_config_file.tap(&Gem::UNTAINT) + end + + ## + # The path to standard location of the user's cache directory. + + def self.cache_home + @cache_home ||= (ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, '.cache')) + end + + ## + # The path to standard location of the user's data directory. + + def self.data_home + @data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, '.local', 'share')) + end + ## # How String Gem paths should be split. Overridable for esoteric platforms. @@ -115,11 +183,7 @@ def self.default_exec_format # The default directory for binaries def self.default_bindir - if defined? RUBY_FRAMEWORK_VERSION # mac framework support - '/usr/bin' - else # generic install - RbConfig::CONFIG['bindir'] - end + RbConfig::CONFIG['bindir'] end def self.ruby_engine @@ -130,14 +194,26 @@ def self.ruby_engine # The default signing key path def self.default_key_path - File.join Gem.user_home, ".gem", "gem-private_key.pem" + default_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem" + + unless File.exist?(default_key_path) + default_key_path = File.join Gem.data_home, "gem", "gem-private_key.pem" + end + + default_key_path end ## # The default signing certificate chain path def self.default_cert_path - File.join Gem.user_home, ".gem", "gem-public_cert.pem" + default_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem" + + unless File.exist?(default_cert_path) + default_cert_path = File.join Gem.data_home, "gem", "gem-public_cert.pem" + end + + default_cert_path end ## diff --git a/ruby/lib/rubygems/dependency.rb b/ruby/lib/rubygems/dependency.rb index 0c58815c8..364036236 100644 --- a/ruby/lib/rubygems/dependency.rb +++ b/ruby/lib/rubygems/dependency.rb @@ -2,11 +2,7 @@ ## # The Dependency class holds a Gem name and a Gem::Requirement. -require "rubygems/bundler_version_finder" -require "rubygems/requirement" - class Gem::Dependency - ## # Valid dependency types. #-- @@ -281,11 +277,11 @@ def matching_specs(platform_only = false) requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version) end.map(&:to_spec) - Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze && !requirement.specific? + Gem::BundlerVersionFinder.prioritize!(matches) if prioritizes_bundler? if platform_only matches.reject! do |spec| - spec.nil? || !Gem::Platform.match(spec.platform) + spec.nil? || !Gem::Platform.match_spec?(spec) end end @@ -299,6 +295,10 @@ def specific? @requirement.specific? end + def prioritizes_bundler? + name == "bundler".freeze && !specific? + end + def to_specs matches = matching_specs true @@ -322,14 +322,14 @@ def to_specs def to_spec matches = self.to_specs.compact - active = matches.find { |spec| spec.activated? } + active = matches.find {|spec| spec.activated? } return active if active - return matches.first if prerelease? - - # Move prereleases to the end of the list for >= 0 requirements - pre, matches = matches.partition { |spec| spec.version.prerelease? } - matches += pre if requirement == Gem::Requirement.default + unless prerelease? + # Move prereleases to the end of the list for >= 0 requirements + pre, matches = matches.partition {|spec| spec.version.prerelease? } + matches += pre if requirement == Gem::Requirement.default + end matches.first end @@ -347,5 +347,4 @@ def identity :released end end - end diff --git a/ruby/lib/rubygems/dependency_installer.rb b/ruby/lib/rubygems/dependency_installer.rb index 6d4568888..913bba32e 100644 --- a/ruby/lib/rubygems/dependency_installer.rb +++ b/ruby/lib/rubygems/dependency_installer.rb @@ -1,19 +1,17 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/dependency_list' -require 'rubygems/package' -require 'rubygems/installer' -require 'rubygems/spec_fetcher' -require 'rubygems/user_interaction' -require 'rubygems/source' -require 'rubygems/available_set' -require 'rubygems/deprecate' +require_relative '../rubygems' +require_relative 'dependency_list' +require_relative 'package' +require_relative 'installer' +require_relative 'spec_fetcher' +require_relative 'user_interaction' +require_relative 'available_set' +require_relative 'deprecate' ## # Installs a gem along with all its dependencies from local and remote gems. class Gem::DependencyInstaller - include Gem::UserInteraction extend Gem::Deprecate @@ -29,7 +27,7 @@ class Gem::DependencyInstaller :wrappers => true, :build_args => nil, :build_docs_in_background => false, - :install_as_default => false + :install_as_default => false, }.freeze ## @@ -106,27 +104,6 @@ def initialize(options = {}) @errors = [] end - ## - # Creates an AvailableSet to install from based on +dep_or_name+ and - # +version+ - - def available_set_for(dep_or_name, version) # :nodoc: - if String === dep_or_name - Gem::Deprecate.skip_during do - find_spec_by_name_and_version dep_or_name, version, @prerelease - end - else - dep = dep_or_name.dup - dep.prerelease = @prerelease - @available = Gem::Deprecate.skip_during do - find_gems_with_sources dep - end - end - - @available.pick_best! - end - deprecate :available_set_for, :none, 2019, 12 - ## # Indicated, based on the requested domain, if local # gems should be considered. @@ -216,57 +193,7 @@ def find_gems_with_sources(dep, best_only=false) # :nodoc: set end - deprecate :find_gems_with_sources, :none, 2019, 12 - - ## - # Finds a spec and the source_uri it came from for gem +gem_name+ and - # +version+. Returns an Array of specs and sources required for - # installation of the gem. - - def find_spec_by_name_and_version(gem_name, - version = Gem::Requirement.default, - prerelease = false) - set = Gem::AvailableSet.new - - if consider_local? - if gem_name =~ /\.gem$/ and File.file? gem_name - src = Gem::Source::SpecificFile.new(gem_name) - set.add src.spec, src - elsif gem_name =~ /\.gem$/ - Dir[gem_name].each do |name| - begin - src = Gem::Source::SpecificFile.new name - set.add src.spec, src - rescue Gem::Package::FormatError - end - end - else - local = Gem::Source::Local.new - - if s = local.find_gem(gem_name, version) - set.add s, local - end - end - end - - if set.empty? - dep = Gem::Dependency.new gem_name, version - dep.prerelease = true if prerelease - - set = Gem::Deprecate.skip_during do - find_gems_with_sources(dep, true) - end - - set.match_platform! - end - - if set.empty? - raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors) - end - - @available = set - end - deprecate :find_spec_by_name_and_version, :none, 2019, 12 + rubygems_deprecate :find_gems_with_sources def in_background(what) # :nodoc: fork_happened = false @@ -356,10 +283,10 @@ def resolve_dependencies(dep_or_name, version) # :nodoc: request_set.development_shallow = @dev_shallow request_set.soft_missing = @force request_set.prerelease = @prerelease - request_set.remote = false unless consider_remote? installer_set = Gem::Resolver::InstallerSet.new @domain - installer_set.ignore_installed = @only_install_dir + installer_set.ignore_installed = (@minimal_deps == false) || @only_install_dir + installer_set.force = @force if consider_local? if dep_or_name =~ /\.gem$/ and File.file? dep_or_name @@ -380,6 +307,7 @@ def resolve_dependencies(dep_or_name, version) # :nodoc: dependency = if spec = installer_set.local?(dep_or_name) + installer_set.remote = nil if spec.dependencies.none? Gem::Dependency.new spec.name, version elsif String === dep_or_name Gem::Dependency.new dep_or_name, version @@ -394,6 +322,7 @@ def resolve_dependencies(dep_or_name, version) # :nodoc: installer_set.add_always_install dependency request_set.always_install = installer_set.always_install + request_set.remote = installer_set.consider_remote? if @ignore_dependencies installer_set.ignore_dependencies = true @@ -407,5 +336,4 @@ def resolve_dependencies(dep_or_name, version) # :nodoc: request_set end - end diff --git a/ruby/lib/rubygems/dependency_list.rb b/ruby/lib/rubygems/dependency_list.rb index db7a2f5ad..10e08fc70 100644 --- a/ruby/lib/rubygems/dependency_list.rb +++ b/ruby/lib/rubygems/dependency_list.rb @@ -5,8 +5,8 @@ # See LICENSE.txt for permissions. #++ -require 'tsort' -require 'rubygems/deprecate' +require_relative 'tsort' +require_relative 'deprecate' ## # Gem::DependencyList is used for installing and uninstalling gems in the @@ -17,11 +17,10 @@ # this class necessary anymore? Especially #ok?, #why_not_ok? class Gem::DependencyList - attr_reader :specs include Enumerable - include TSort + include Gem::TSort ## # Allows enabling/disabling use of development dependencies @@ -101,11 +100,11 @@ def each(&block) end def find_name(full_name) - @specs.find { |spec| spec.full_name == full_name } + @specs.find {|spec| spec.full_name == full_name } end def inspect # :nodoc: - "%s %p>" % [super[0..-2], map { |s| s.full_name }] + "%s %p>" % [super[0..-2], map {|s| s.full_name }] end ## @@ -116,7 +115,7 @@ def ok? end def why_not_ok?(quick = false) - unsatisfied = Hash.new { |h,k| h[k] = [] } + unsatisfied = Hash.new {|h,k| h[k] = [] } each do |spec| spec.runtime_dependencies.each do |dep| inst = Gem::Specification.any? do |installed_spec| @@ -124,7 +123,7 @@ def why_not_ok?(quick = false) dep.requirement.satisfied_by? installed_spec.version end - unless inst or @specs.find { |s| s.satisfies_requirement? dep } + unless inst or @specs.find {|s| s.satisfies_requirement? dep } unsatisfied[spec.name] << dep return unsatisfied if quick end @@ -184,7 +183,7 @@ def remove_specs_unsatisfied_by(dependencies) # Removes the gemspec matching +full_name+ from the dependency list def remove_by_name(full_name) - @specs.delete_if { |spec| spec.full_name == full_name } + @specs.delete_if {|spec| spec.full_name == full_name } end ## @@ -192,7 +191,7 @@ def remove_by_name(full_name) # gemspecs that have a dependency satisfied by the named gemspec. def spec_predecessors - result = Hash.new { |h,k| h[k] = [] } + result = Hash.new {|h,k| h[k] = [] } specs = @specs.sort.reverse @@ -238,7 +237,6 @@ def tsort_each_child(node) # +ignored+. def active_count(specs, ignored) - specs.count { |spec| ignored[spec.full_name].nil? } + specs.count {|spec| ignored[spec.full_name].nil? } end - end diff --git a/ruby/lib/rubygems/deprecate.rb b/ruby/lib/rubygems/deprecate.rb index 8accfb617..5fe0afb6b 100644 --- a/ruby/lib/rubygems/deprecate.rb +++ b/ruby/lib/rubygems/deprecate.rb @@ -1,23 +1,70 @@ # frozen_string_literal: true ## -# Provides a single method +deprecate+ to be used to declare when -# something is going away. +# Provides 3 methods for declaring when something is going away. +# +# +deprecate(name, repl, year, month)+: +# Indicate something may be removed on/after a certain date. +# +# +rubygems_deprecate(name, replacement=:none)+: +# Indicate something will be removed in the next major RubyGems version, +# and (optionally) a replacement for it. +# +# +rubygems_deprecate_command+: +# Indicate a RubyGems command (in +lib/rubygems/commands/*.rb+) will be +# removed in the next RubyGems version. +# +# Also provides +skip_during+ for temporarily turning off deprecation warnings. +# This is intended to be used in the test suite, so deprecation warnings +# don't cause test failures if you need to make sure stderr is otherwise empty. +# +# +# Example usage of +deprecate+ and +rubygems_deprecate+: # # class Legacy -# def self.klass_method +# def self.some_class_method # # ... # end # -# def instance_method +# def some_instance_method +# # ... +# end +# +# def some_old_method # # ... # end # # extend Gem::Deprecate -# deprecate :instance_method, "X.z", 2011, 4 +# deprecate :some_instance_method, "X.z", 2011, 4 +# rubygems_deprecate :some_old_method, "Modern#some_new_method" # # class << self # extend Gem::Deprecate -# deprecate :klass_method, :none, 2011, 4 +# deprecate :some_class_method, :none, 2011, 4 +# end +# end +# +# +# Example usage of +rubygems_deprecate_command+: +# +# class Gem::Commands::QueryCommand < Gem::Command +# extend Gem::Deprecate +# rubygems_deprecate_command +# +# # ... +# end +# +# +# Example usage of +skip_during+: +# +# class TestSomething < Gem::Testcase +# def test_some_thing_with_deprecations +# Gem::Deprecate.skip_during do +# actual_stdout, actual_stderr = capture_output do +# Gem.something_deprecated +# end +# assert_empty actual_stdout +# assert_equal(expected, actual_stderr) +# end # end # end @@ -41,6 +88,10 @@ def skip_during Gem::Deprecate.skip = original end + def self.next_rubygems_major_version # :nodoc: + Gem::Version.new(Gem.rubygems_version.segments.first).bump + end + ## # Simple deprecation method that deprecates +name+ by wrapping it up # in a dummy method. It warns on each call to the dummy method @@ -56,15 +107,58 @@ def deprecate(name, repl, year, month) target = klass ? "#{self}." : "#{self.class}#" msg = [ "NOTE: #{target}#{name} is deprecated", repl == :none ? " with no replacement" : "; use #{repl} instead", - ". It will be removed on or after %4d-%02d-01." % [year, month], + ". It will be removed on or after %4d-%02d." % [year, month], "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}", ] warn "#{msg.join}." unless Gem::Deprecate.skip send old, *args, &block end + ruby2_keywords name if respond_to?(:ruby2_keywords, true) + end + end + + ## + # Simple deprecation method that deprecates +name+ by wrapping it up + # in a dummy method. It warns on each call to the dummy method + # telling the user of +repl+ (unless +repl+ is :none) and the + # Rubygems version that it is planned to go away. + + def rubygems_deprecate(name, replacement=:none) + class_eval do + old = "_deprecated_#{name}" + alias_method old, name + define_method name do |*args, &block| + klass = self.kind_of? Module + target = klass ? "#{self}." : "#{self.class}#" + msg = [ "NOTE: #{target}#{name} is deprecated", + replacement == :none ? " with no replacement" : "; use #{replacement} instead", + ". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}", + "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}", + ] + warn "#{msg.join}." unless Gem::Deprecate.skip + send old, *args, &block + end + ruby2_keywords name if respond_to?(:ruby2_keywords, true) + end + end + + # Deprecation method to deprecate Rubygems commands + def rubygems_deprecate_command + class_eval do + define_method "deprecated?" do + true + end + + define_method "deprecation_warning" do + msg = [ "#{self.command} command is deprecated", + ". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}.\n", + ] + + alert_warning "#{msg.join}" unless Gem::Deprecate.skip + end end end - module_function :deprecate, :skip_during + module_function :rubygems_deprecate, :rubygems_deprecate_command, :skip_during end diff --git a/ruby/lib/rubygems/doctor.rb b/ruby/lib/rubygems/doctor.rb index 661ae5a4e..d14c64a16 100644 --- a/ruby/lib/rubygems/doctor.rb +++ b/ruby/lib/rubygems/doctor.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/user_interaction' +require_relative '../rubygems' +require_relative 'user_interaction' ## # Cleans up after a partially-failed uninstall or for an invalid @@ -12,7 +12,6 @@ # removing the bogus specification. class Gem::Doctor - include Gem::UserInteraction ## @@ -26,11 +25,12 @@ class Gem::Doctor ['doc', ''], ['extensions', ''], ['gems', ''], + ['plugins', ''], ].freeze missing = Gem::REPOSITORY_SUBDIRECTORIES.sort - - REPOSITORY_EXTENSION_MAP.map { |(k,_)| k }.sort + REPOSITORY_EXTENSION_MAP.map {|(k,_)| k }.sort raise "Update REPOSITORY_EXTENSION_MAP, missing: #{missing.join ', '}" unless missing.empty? @@ -52,7 +52,7 @@ def initialize(gem_repository, dry_run = false) # Specs installed in this gem repository def installed_specs # :nodoc: - @installed_specs ||= Gem::Specification.map { |s| s.full_name } + @installed_specs ||= Gem::Specification.map {|s| s.full_name } end ## @@ -112,20 +112,20 @@ def doctor_child(sub_directory, extension) # :nodoc: next if installed_specs.include? basename next if /^rubygems-\d/ =~ basename next if 'specifications' == sub_directory and 'default' == basename + next if 'plugins' == sub_directory and Gem.plugin_suffix_regexp =~ basename type = File.directory?(child) ? 'directory' : 'file' action = if @dry_run - 'Extra' - else - FileUtils.rm_r(child) - 'Removed' - end + 'Extra' + else + FileUtils.rm_r(child) + 'Removed' + end say "#{action} #{type} #{sub_directory}/#{File.basename(child)}" end rescue Errno::ENOENT # ignore end - end diff --git a/ruby/lib/rubygems/errors.rb b/ruby/lib/rubygems/errors.rb index 2cd18e2e2..f115ce23d 100644 --- a/ruby/lib/rubygems/errors.rb +++ b/ruby/lib/rubygems/errors.rb @@ -13,13 +13,11 @@ module Gem # already activated gems or that RubyGems is otherwise unable to activate. class LoadError < ::LoadError - # Name of gem attr_accessor :name # Version requirement of gem attr_accessor :requirement - end ## @@ -27,15 +25,15 @@ class LoadError < ::LoadError # system. Instead of rescuing from this class, make sure to rescue from the # superclass Gem::LoadError to catch all types of load errors. class MissingSpecError < Gem::LoadError - - def initialize(name, requirement) + def initialize(name, requirement, extra_message=nil) @name = name @requirement = requirement + @extra_message = extra_message end def message # :nodoc: build_message + - "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}', execute `gem env` for more information" + "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}' #{@extra_message}, execute `gem env` for more information" end private @@ -44,7 +42,6 @@ def build_message total = Gem::Specification.stubs.size "Could not find '#{name}' (#{requirement}) among #{total} total gem(s)\n" end - end ## @@ -52,7 +49,6 @@ def build_message # not the requested version. Instead of rescuing from this class, make sure to # rescue from the superclass Gem::LoadError to catch all types of load errors. class MissingSpecVersionError < MissingSpecError - attr_reader :specs def initialize(name, requirement, specs) @@ -63,19 +59,14 @@ def initialize(name, requirement, specs) private def build_message - if name == "bundler" && message = Gem::BundlerVersionFinder.missing_version_message - return message - end names = specs.map(&:full_name) "Could not find '#{name}' (#{requirement}) - did find: [#{names.join ','}]\n" end - end # Raised when there are conflicting gem specs loaded class ConflictError < LoadError - ## # A Hash mapping conflicting specifications to the dependencies that # caused the conflict @@ -100,7 +91,6 @@ def initialize(target, conflicts) super("Unable to activate #{target.full_name}, because #{reason}") end - end class ErrorReason; end @@ -112,7 +102,6 @@ class ErrorReason; end # in figuring out why a gem couldn't be installed. # class PlatformMismatch < ErrorReason - ## # the name of the gem attr_reader :name @@ -150,7 +139,6 @@ def wordy @platforms.size == 1 ? '' : 's', @platforms.join(' ,')] end - end ## @@ -158,7 +146,6 @@ def wordy # data from a source class SourceFetchProblem < ErrorReason - ## # Creates a new SourceFetchProblem for the given +source+ and +error+. @@ -181,14 +168,12 @@ def initialize(source, error) # An English description of the error. def wordy - @source.uri.password = 'REDACTED' unless @source.uri.password.nil? - "Unable to download data from #{@source.uri} - #{@error.message}" + "Unable to download data from #{Gem::Uri.new(@source.uri).redacted} - #{@error.message}" end ## # The "exception" alias allows you to call raise on a SourceFetchProblem. alias exception error - end end diff --git a/ruby/lib/rubygems/exceptions.rb b/ruby/lib/rubygems/exceptions.rb index 3924f9dde..180686909 100644 --- a/ruby/lib/rubygems/exceptions.rb +++ b/ruby/lib/rubygems/exceptions.rb @@ -1,24 +1,42 @@ # frozen_string_literal: true -require 'rubygems/deprecate' +require_relative 'deprecate' +require_relative 'unknown_command_spell_checker' ## # Base exception class for RubyGems. All exception raised by RubyGems are a # subclass of this one. -class Gem::Exception < RuntimeError +class Gem::Exception < RuntimeError; end - ## - #-- - # TODO: remove in RubyGems 4, nobody sets this +class Gem::CommandLineError < Gem::Exception; end - attr_accessor :source_exception # :nodoc: +class Gem::UnknownCommandError < Gem::Exception + attr_reader :unknown_command - extend Gem::Deprecate - deprecate :source_exception, :none, 2018, 12 + def initialize(unknown_command) + self.class.attach_correctable -end + @unknown_command = unknown_command + super("Unknown command #{unknown_command}") + end -class Gem::CommandLineError < Gem::Exception; end + def self.attach_correctable + return if defined?(@attached) + + if defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable) + if DidYouMean.respond_to?(:correct_error) + DidYouMean.correct_error(Gem::UnknownCommandError, Gem::UnknownCommandSpellChecker) + else + DidYouMean::SPELL_CHECKERS['Gem::UnknownCommandError'] = + Gem::UnknownCommandSpellChecker + + prepend DidYouMean::Correctable + end + end + + @attached = true + end +end class Gem::DependencyError < Gem::Exception; end @@ -30,7 +48,6 @@ class Gem::DependencyRemovalException < Gem::Exception; end # and #conflicting_dependencies class Gem::DependencyResolutionError < Gem::DependencyError - attr_reader :conflict def initialize(conflict) @@ -43,25 +60,20 @@ def initialize(conflict) def conflicting_dependencies @conflict.conflicting_dependencies end - end ## # Raised when attempting to uninstall a gem that isn't in GEM_HOME. class Gem::GemNotInHomeException < Gem::Exception - attr_accessor :spec - end ### # Raised when removing a gem with the uninstall command fails class Gem::UninstallError < Gem::Exception - attr_accessor :spec - end class Gem::DocumentError < Gem::Exception; end @@ -75,7 +87,6 @@ class Gem::EndOfYAMLException < Gem::Exception; end # operating on the given directory. class Gem::FilePermissionError < Gem::Exception - attr_reader :directory def initialize(directory) @@ -83,15 +94,12 @@ def initialize(directory) super "You don't have write permissions for the #{directory} directory." end - end ## # Used to raise parsing and loading errors class Gem::FormatException < Gem::Exception - attr_accessor :file_path - end class Gem::GemNotFoundException < Gem::Exception; end @@ -100,7 +108,6 @@ class Gem::GemNotFoundException < Gem::Exception; end # Raised by the DependencyInstaller when a specific gem cannot be found class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException - ## # Creates a new SpecificGemNotFoundException for a gem with the given +name+ # and +version+. Any +errors+ encountered when attempting to find the gem @@ -128,7 +135,6 @@ def initialize(name, version, errors=nil) # Errors encountered attempting to find the gem. attr_reader :errors - end ## @@ -136,7 +142,6 @@ def initialize(name, version, errors=nil) # inability to find a valid possible spec for a request. class Gem::ImpossibleDependenciesError < Gem::Exception - attr_reader :conflicts attr_reader :request @@ -164,17 +169,14 @@ def build_message # :nodoc: def dependency @request.dependency end - end class Gem::InstallError < Gem::Exception; end class Gem::RuntimeRequirementNotMetError < Gem::InstallError - attr_accessor :suggestion def message [suggestion, super].compact.join("\n\t") end - end ## @@ -216,7 +218,6 @@ class Gem::VerificationError < Gem::Exception; end # exit_code class Gem::SystemExitException < SystemExit - ## # The exit code for the process @@ -228,9 +229,8 @@ class Gem::SystemExitException < SystemExit def initialize(exit_code) @exit_code = exit_code - super "Exiting RubyGems with exit_code #{exit_code}" + super exit_code, "Exiting RubyGems with exit_code #{exit_code}" end - end ## @@ -238,7 +238,6 @@ def initialize(exit_code) # there is no spec. class Gem::UnsatisfiableDependencyError < Gem::DependencyError - ## # The unsatisfiable dependency. This is a # Gem::Resolver::DependencyRequest, not a Gem::Dependency @@ -256,7 +255,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError def initialize(dep, platform_mismatch=nil) if platform_mismatch and !platform_mismatch.empty? - plats = platform_mismatch.map { |x| x.platform.to_s }.sort.uniq + plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(', ')}" else if dep.explicit? @@ -283,10 +282,10 @@ def name def version @dependency.requirement end - end ## # Backwards compatible typo'd exception class for early RubyGems 2.0.x Gem::UnsatisfiableDepedencyError = Gem::UnsatisfiableDependencyError # :nodoc: +Gem.deprecate_constant :UnsatisfiableDepedencyError diff --git a/ruby/lib/rubygems/ext.rb b/ruby/lib/rubygems/ext.rb index 35a486606..bdd5bd9d8 100644 --- a/ruby/lib/rubygems/ext.rb +++ b/ruby/lib/rubygems/ext.rb @@ -10,9 +10,9 @@ module Gem::Ext; end -require 'rubygems/ext/build_error' -require 'rubygems/ext/builder' -require 'rubygems/ext/configure_builder' -require 'rubygems/ext/ext_conf_builder' -require 'rubygems/ext/rake_builder' -require 'rubygems/ext/cmake_builder' +require_relative 'ext/build_error' +require_relative 'ext/builder' +require_relative 'ext/configure_builder' +require_relative 'ext/ext_conf_builder' +require_relative 'ext/rake_builder' +require_relative 'ext/cmake_builder' diff --git a/ruby/lib/rubygems/ext/build_error.rb b/ruby/lib/rubygems/ext/build_error.rb index 6dffddb5c..8ef57ed91 100644 --- a/ruby/lib/rubygems/ext/build_error.rb +++ b/ruby/lib/rubygems/ext/build_error.rb @@ -2,5 +2,7 @@ ## # Raised when there is an error while building extensions. +require_relative '../exceptions' + class Gem::Ext::BuildError < Gem::InstallError end diff --git a/ruby/lib/rubygems/ext/builder.rb b/ruby/lib/rubygems/ext/builder.rb index 2fc1074d9..6d32be651 100644 --- a/ruby/lib/rubygems/ext/builder.rb +++ b/ruby/lib/rubygems/ext/builder.rb @@ -5,20 +5,11 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/user_interaction' +require_relative '../user_interaction' class Gem::Ext::Builder - include Gem::UserInteraction - ## - # The builder shells-out to run various commands after changing the - # directory. This means multiple installations cannot be allowed to build - # extensions in parallel as they may change each other's directories leading - # to broken extensions or failed installations. - - CHDIR_MUTEX = Mutex.new # :nodoc: - attr_accessor :build_args # :nodoc: def self.class_name @@ -26,56 +17,63 @@ def self.class_name $1.downcase end - def self.make(dest_path, results) - unless File.exist? 'Makefile' + def self.make(dest_path, results, make_dir = Dir.pwd) + unless File.exist? File.join(make_dir, 'Makefile') raise Gem::InstallError, 'Makefile not found' end # try to find make program from Ruby configure arguments first RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/ - make_program = ENV['MAKE'] || ENV['make'] || $1 - unless make_program - make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make' + make_program_name = ENV['MAKE'] || ENV['make'] || $1 + unless make_program_name + make_program_name = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make' end + make_program = Shellwords.split(make_program_name) - destdir = '"DESTDIR=%s"' % ENV['DESTDIR'] + # The installation of the bundled gems is failed when DESTDIR is empty in mswin platform. + destdir = (/\bnmake/i !~ make_program_name || ENV['DESTDIR'] && ENV['DESTDIR'] != "") ? 'DESTDIR=%s' % ENV['DESTDIR'] : '' ['clean', '', 'install'].each do |target| # Pass DESTDIR via command line to override what's in MAKEFLAGS cmd = [ - make_program, + *make_program, destdir, - target - ].join(' ').rstrip + target, + ].reject(&:empty?) begin - run(cmd, results, "make #{target}".rstrip) + run(cmd, results, "make #{target}".rstrip, make_dir) rescue Gem::InstallError raise unless target == 'clean' # ignore clean failure end end end - def self.run(command, results, command_name = nil) + def self.run(command, results, command_name = nil, dir = Dir.pwd) verbose = Gem.configuration.really_verbose begin rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil if verbose - puts("current directory: #{Dir.pwd}") + puts("current directory: #{dir}") p(command) end - results << "current directory: #{Dir.pwd}" - results << (command.respond_to?(:shelljoin) ? command.shelljoin : command) + results << "current directory: #{dir}" + require "shellwords" + results << command.shelljoin require "open3" - output, status = Open3.capture2e(*command) + # Set $SOURCE_DATE_EPOCH for the subprocess. + env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string} + output, status = begin + Open3.capture2e(env, *command, :chdir => dir) + rescue => error + raise Gem::InstallError, "#{command_name || class_name} failed#{error.message}" + end if verbose puts output else results << output end - rescue => error - raise Gem::InstallError, "#{command_name || class_name} failed#{error.message}" ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end @@ -160,22 +158,10 @@ def build_extension(extension, dest_path) # :nodoc: begin FileUtils.mkdir_p dest_path - CHDIR_MUTEX.synchronize do - pwd = Dir.getwd - Dir.chdir extension_dir - begin - results = builder.build(extension, dest_path, - results, @build_args, lib_dir) - - verbose { results.join("\n") } - ensure - begin - Dir.chdir pwd - rescue SystemCallError - Dir.chdir dest_path - end - end - end + results = builder.build(extension, dest_path, + results, @build_args, lib_dir, extension_dir) + + verbose { results.join("\n") } write_gem_make_out results.join "\n" rescue => e @@ -200,6 +186,7 @@ def build_extensions dest_path = @spec.extension_dir + require "fileutils" FileUtils.rm_f @spec.gem_build_complete_path @spec.extensions.each do |extension| @@ -225,5 +212,4 @@ def write_gem_make_out(output) # :nodoc: destination end - end diff --git a/ruby/lib/rubygems/ext/cmake_builder.rb b/ruby/lib/rubygems/ext/cmake_builder.rb index 829b88d1b..e47cabef8 100644 --- a/ruby/lib/rubygems/ext/cmake_builder.rb +++ b/ruby/lib/rubygems/ext/cmake_builder.rb @@ -1,19 +1,16 @@ # frozen_string_literal: true -require 'rubygems/command' class Gem::Ext::CmakeBuilder < Gem::Ext::Builder + def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd) + unless File.exist?(File.join(cmake_dir, 'Makefile')) + require_relative '../command' + cmd = ["cmake", ".", "-DCMAKE_INSTALL_PREFIX=#{dest_path}", *Gem::Command.build_args] - def self.build(extension, dest_path, results, args=[], lib_dir=nil) - unless File.exist?('Makefile') - cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}" - cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty? - - run cmd, results + run cmd, results, class_name, cmake_dir end - make dest_path, results + make dest_path, results, cmake_dir results end - end diff --git a/ruby/lib/rubygems/ext/configure_builder.rb b/ruby/lib/rubygems/ext/configure_builder.rb index 7d105c9bd..eb2f9fce6 100644 --- a/ruby/lib/rubygems/ext/configure_builder.rb +++ b/ruby/lib/rubygems/ext/configure_builder.rb @@ -6,18 +6,15 @@ #++ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder + def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd) + unless File.exist?(File.join(configure_dir, 'Makefile')) + cmd = ["sh", "./configure", "--prefix=#{dest_path}", *args] - def self.build(extension, dest_path, results, args=[], lib_dir=nil) - unless File.exist?('Makefile') - cmd = "sh ./configure --prefix=#{dest_path}" - cmd << " #{args.join ' '}" unless args.empty? - - run cmd, results + run cmd, results, class_name, configure_dir end - make dest_path, results + make dest_path, results, configure_dir results end - end diff --git a/ruby/lib/rubygems/ext/ext_conf_builder.rb b/ruby/lib/rubygems/ext/ext_conf_builder.rb index 88be7ecfe..3ca346361 100644 --- a/ruby/lib/rubygems/ext/ext_conf_builder.rb +++ b/ruby/lib/rubygems/ext/ext_conf_builder.rb @@ -5,16 +5,12 @@ # See LICENSE.txt for permissions. #++ -require 'fileutils' -require 'tempfile' -require 'shellwords' - class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder + def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd) + require 'fileutils' + require 'tempfile' - FileEntry = FileUtils::Entry_ # :nodoc: - - def self.build(extension, dest_path, results, args=[], lib_dir=nil) - tmp_dest = Dir.mktmpdir(".gem.", ".") + tmp_dest = Dir.mktmpdir(".gem.", extension_dir) # Some versions of `mktmpdir` return absolute paths, which will break make # if the paths contain spaces. However, on Ruby 1.9.x on Windows, relative @@ -25,11 +21,11 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil) # spaces do not work. # # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940 - tmp_dest = get_relative_path(tmp_dest) + tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir) - Tempfile.open %w"siteconf .rb", "." do |siteconf| + Tempfile.open %w[siteconf .rb], extension_dir do |siteconf| siteconf.puts "require 'rbconfig'" - siteconf.puts "dest_path = #{tmp_dest.dump}" + siteconf.puts "dest_path = #{tmp_dest_relative.dump}" %w[sitearchdir sitelibdir].each do |dir| siteconf.puts "RbConfig::MAKEFILE_CONFIG['#{dir}'] = dest_path" siteconf.puts "RbConfig::CONFIG['#{dir}'] = dest_path" @@ -40,19 +36,23 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil) destdir = ENV["DESTDIR"] begin + # workaround for https://github.com/oracle/truffleruby/issues/2115 + siteconf_path = RUBY_ENGINE == "truffleruby" ? siteconf.path.dup : siteconf.path + require "shellwords" cmd = Gem.ruby.shellsplit << "-I" << File.expand_path("../../..", __FILE__) << - "-r" << get_relative_path(siteconf.path) << File.basename(extension) + "-r" << get_relative_path(siteconf_path, extension_dir) << File.basename(extension) cmd.push(*args) begin - run(cmd, results) do |s, r| - if File.exist? 'mkmf.log' + run(cmd, results, class_name, extension_dir) do |s, r| + mkmf_log = File.join(extension_dir, 'mkmf.log') + if File.exist? mkmf_log unless s.success? r << "To see why this extension failed to compile, please check" \ " the mkmf.log which can be found here:\n" r << " " + File.join(dest_path, 'mkmf.log') + "\n" end - FileUtils.mv 'mkmf.log', dest_path + FileUtils.mv mkmf_log, dest_path end end siteconf.unlink @@ -60,18 +60,20 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil) ENV["DESTDIR"] = nil - make dest_path, results + make dest_path, results, extension_dir + + if tmp_dest_relative + full_tmp_dest = File.join(extension_dir, tmp_dest_relative) - if tmp_dest # TODO remove in RubyGems 3 if Gem.install_extension_in_lib and lib_dir FileUtils.mkdir_p lib_dir - entries = Dir.entries(tmp_dest) - %w[. ..] - entries = entries.map { |entry| File.join tmp_dest, entry } + entries = Dir.entries(full_tmp_dest) - %w[. ..] + entries = entries.map {|entry| File.join full_tmp_dest, entry } FileUtils.cp_r entries, lib_dir, :remove_destination => true end - FileEntry.new(tmp_dest).traverse do |ent| + FileUtils::Entry_.new(full_tmp_dest).traverse do |ent| destent = ent.class.new(dest_path, ent.rel) destent.exist? or FileUtils.mv(ent.path, destent.path) end @@ -89,9 +91,8 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil) private - def self.get_relative_path(path) - path[0..Dir.pwd.length - 1] = '.' if path.start_with?(Dir.pwd) + def self.get_relative_path(path, base) + path[0..base.length - 1] = '.' if path.start_with?(base) path end - end diff --git a/ruby/lib/rubygems/ext/rake_builder.rb b/ruby/lib/rubygems/ext/rake_builder.rb index 077f080c0..fed98e741 100644 --- a/ruby/lib/rubygems/ext/rake_builder.rb +++ b/ruby/lib/rubygems/ext/rake_builder.rb @@ -5,31 +5,28 @@ # See LICENSE.txt for permissions. #++ -require "shellwords" - class Gem::Ext::RakeBuilder < Gem::Ext::Builder - - def self.build(extension, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd) if File.basename(extension) =~ /mkrf_conf/i - run([Gem.ruby, File.basename(extension), *args], results) + run([Gem.ruby, File.basename(extension), *args], results, class_name, extension_dir) end rake = ENV['rake'] if rake + require "shellwords" rake = rake.shellsplit else begin - rake = [Gem.ruby, "-I#{File.expand_path("..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')] + rake = [Gem.ruby, "-I#{File.expand_path("../..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')] rescue Gem::Exception rake = [Gem.default_exec_format % 'rake'] end end rake_args = ["RUBYARCHDIR=#{dest_path}", "RUBYLIBDIR=#{dest_path}", *args] - run(rake + rake_args, results) + run(rake + rake_args, results, class_name, extension_dir) results end - end diff --git a/ruby/lib/rubygems/gem_runner.rb b/ruby/lib/rubygems/gem_runner.rb index 4159d8138..89b23b26a 100644 --- a/ruby/lib/rubygems/gem_runner.rb +++ b/ruby/lib/rubygems/gem_runner.rb @@ -5,10 +5,9 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems' -require 'rubygems/command_manager' -require 'rubygems/config_file' -require 'rubygems/deprecate' +require_relative '../rubygems' +require_relative 'command_manager' +require_relative 'deprecate' ## # Load additional plugins from $LOAD_PATH @@ -25,14 +24,9 @@ # classes they call directly. class Gem::GemRunner - - def initialize(options={}) - if !options.empty? && !Gem::Deprecate.skip - Kernel.warn "NOTE: passing options to Gem::GemRunner.new is deprecated with no replacement. It will be removed on or after 2016-10-01." - end - - @command_manager_class = options[:command_manager] || Gem::CommandManager - @config_file_class = options[:config_file] || Gem::ConfigFile + def initialize + @command_manager_class = Gem::CommandManager + @config_file_class = Gem::ConfigFile end ## @@ -48,11 +42,11 @@ def run(args) cmd.command_names.each do |command_name| config_args = Gem.configuration[command_name] config_args = case config_args - when String - config_args.split ' ' - else - Array(config_args) - end + when String + config_args.split ' ' + else + Array(config_args) + end Gem::Command.add_specific_extra_args command_name, config_args end @@ -80,7 +74,6 @@ def do_configuration(args) Gem.use_paths Gem.configuration[:gemhome], Gem.configuration[:gempath] Gem::Command.extra_args = Gem.configuration[:gem] end - end Gem.load_plugins diff --git a/ruby/lib/rubygems/gemcutter_utilities.rb b/ruby/lib/rubygems/gemcutter_utilities.rb index 2950d94dc..0968e1a6f 100644 --- a/ruby/lib/rubygems/gemcutter_utilities.rb +++ b/ruby/lib/rubygems/gemcutter_utilities.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rubygems/remote_fetcher' -require 'rubygems/text' +require_relative 'remote_fetcher' +require_relative 'text' ## # Utility methods for using the RubyGems API. @@ -8,10 +8,12 @@ module Gem::GemcutterUtilities ERROR_CODE = 1 + API_SCOPES = %i[index_rubygems push_rubygem yank_rubygem add_owner remove_owner access_webhooks show_dashboard].freeze include Gem::Text attr_writer :host + attr_writer :scope ## # Add the --key option @@ -19,7 +21,7 @@ module Gem::GemcutterUtilities def add_key_option add_option('-k', '--key KEYNAME', Symbol, 'Use the given API key', - 'from ~/.gem/credentials') do |value,options| + "from #{Gem.configuration.credentials_path}") do |value,options| options[:key] = value end end @@ -29,7 +31,8 @@ def add_key_option def add_otp_option add_option('--otp CODE', - 'Digit code for multifactor authentication') do |value, options| + 'Digit code for multifactor authentication', + 'You can also use the environment variable GEM_HOST_OTP_CODE') do |value, options| options[:otp] = value end end @@ -49,6 +52,13 @@ def api_key end end + ## + # The OTP code from the command options or from the user's configuration. + + def otp + options[:otp] || ENV["GEM_HOST_OTP_CODE"] + end + ## # The host to connect to either from the RUBYGEMS_HOST environment variable # or from the user's configuration @@ -72,7 +82,7 @@ def host # # If +allowed_push_host+ metadata is present, then it will only allow that host. - def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, &block) + def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scope: nil, &block) require 'net/http' self.host = host if host @@ -92,14 +102,18 @@ def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, &blo end uri = URI.parse "#{self.host}/#{path}" + response = request_with_otp(method, uri, &block) - request_method = Net::HTTP.const_get method.to_s.capitalize - response = Gem::RemoteFetcher.fetcher.request(uri, request_method, &block) - return response unless mfa_unauthorized?(response) + if mfa_unauthorized?(response) + ask_otp + response = request_with_otp(method, uri, &block) + end - Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req| - req.add_field "OTP", get_otp - block.call(req) + if api_key_forbidden?(response) + update_scope(scope) + request_with_otp(method, uri, &block) + else + response end end @@ -107,24 +121,37 @@ def mfa_unauthorized?(response) response.kind_of?(Net::HTTPUnauthorized) && response.body.start_with?('You have enabled multifactor authentication') end - def get_otp - say 'You have enabled multi-factor authentication. Please enter OTP code.' - ask 'Code: ' + def update_scope(scope) + sign_in_host = self.host + pretty_host = pretty_host(sign_in_host) + update_scope_params = { scope => true } + + say "The existing key doesn't have access of #{scope} on #{pretty_host}. Please sign in to update access." + + email = ask " Email: " + password = ask_for_password "Password: " + + response = rubygems_api_request(:put, "api/v1/api_key", + sign_in_host, scope: scope) do |request| + request.basic_auth email, password + request["OTP"] = otp if otp + request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params)) + end + + with_response response do |resp| + say "Added #{scope} scope to the existing API key" + end end ## # Signs in with the RubyGems API at +sign_in_host+ and sets the rubygems API # key. - def sign_in(sign_in_host = nil) + def sign_in(sign_in_host = nil, scope: nil) sign_in_host ||= self.host return if api_key - pretty_host = if Gem::DEFAULT_HOST == sign_in_host - 'RubyGems.org' - else - sign_in_host - end + pretty_host = pretty_host(sign_in_host) say "Enter your #{pretty_host} credentials." say "Don't have an account yet? " + @@ -134,14 +161,18 @@ def sign_in(sign_in_host = nil) password = ask_for_password "Password: " say "\n" - response = rubygems_api_request(:get, "api/v1/api_key", - sign_in_host) do |request| + key_name = get_key_name(scope) + scope_params = get_scope_params(scope) + + response = rubygems_api_request(:post, "api/v1/api_key", + sign_in_host, scope: scope) do |request| request.basic_auth email, password - request.add_field "OTP", options[:otp] if options[:otp] + request["OTP"] = otp if otp + request.body = URI.encode_www_form({ name: key_name }.merge(scope_params)) end with_response response do |resp| - say "Signed in." + say "Signed in with API key: #{key_name}." set_api_key host, resp.body end end @@ -195,4 +226,62 @@ def set_api_key(host, key) end end + private + + def request_with_otp(method, uri, &block) + request_method = Net::HTTP.const_get method.to_s.capitalize + + Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req| + req["OTP"] = otp if otp + block.call(req) + end + end + + def ask_otp + say 'You have enabled multi-factor authentication. Please enter OTP code.' + options[:otp] = ask 'Code: ' + end + + def pretty_host(host) + if Gem::DEFAULT_HOST == host + 'RubyGems.org' + else + host + end + end + + def get_scope_params(scope) + scope_params = {} + + if scope + scope_params = { scope => true } + else + say "Please select scopes you want to enable for the API key (y/n)" + API_SCOPES.each do |scope| + selected = ask "#{scope} [y/N]: " + scope_params[scope] = true if selected =~ /^[yY](es)?$/ + end + say "\n" + end + + scope_params + end + + def get_key_name(scope) + hostname = Socket.gethostname || "unknown-host" + user = ENV["USER"] || ENV["USERNAME"] || "unknown-user" + ts = Time.now.strftime("%Y%m%d%H%M%S") + default_key_name = "#{hostname}-#{user}-#{ts}" + + key_name = ask "API Key name [#{default_key_name}]: " unless scope + if key_name.nil? || key_name.empty? + default_key_name + else + key_name + end + end + + def api_key_forbidden?(response) + response.kind_of?(Net::HTTPForbidden) && response.body.start_with?("The API key doesn't have access") + end end diff --git a/ruby/lib/rubygems/indexer.rb b/ruby/lib/rubygems/indexer.rb index 4d199868f..6e8dade64 100644 --- a/ruby/lib/rubygems/indexer.rb +++ b/ruby/lib/rubygems/indexer.rb @@ -1,27 +1,12 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/package' -require 'time' +require_relative '../rubygems' +require_relative 'package' require 'tmpdir' -rescue_exceptions = [LoadError] -begin - require 'bundler/errors' -rescue LoadError # this rubygems + old ruby -else # this rubygems + ruby trunk with bundler - rescue_exceptions << Bundler::GemfileNotFound -end -begin - gem 'builder' - require 'builder/xchar' -rescue *rescue_exceptions -end - ## # Top level class for building the gem repository index. class Gem::Indexer - include Gem::UserInteraction ## @@ -62,11 +47,6 @@ def initialize(directory, options = {}) require 'tmpdir' require 'zlib' - unless defined?(Builder::XChar) - raise "Gem::Indexer requires that the XML Builder library be installed:" + - "\n\tgem install builder" - end - options = { :build_modern => true }.merge options @build_modern = options[:build_modern] @@ -156,7 +136,7 @@ def build_modern_index(index, file, name) say "Generating #{name} index" Gem.time "Generated #{name} index" do - open(file, 'wb') do |io| + File.open(file, 'wb') do |io| specs = index.map do |*spec| # We have to splat here because latest_specs is an array, while the # others are hashes. @@ -383,7 +363,7 @@ def update_index end specs = map_gems_to_specs updated_gems - prerelease, released = specs.partition { |s| s.version.prerelease? } + prerelease, released = specs.partition {|s| s.version.prerelease? } files = build_marshal_gemspecs specs @@ -442,5 +422,4 @@ def update_specs_index(index, source, dest) Marshal.dump specs_index, io end end - end diff --git a/ruby/lib/rubygems/install_default_message.rb b/ruby/lib/rubygems/install_default_message.rb index f68fd2fd0..052ef528e 100644 --- a/ruby/lib/rubygems/install_default_message.rb +++ b/ruby/lib/rubygems/install_default_message.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/user_interaction' +require_relative '../rubygems' +require_relative 'user_interaction' ## # A post-install hook that displays "Successfully installed diff --git a/ruby/lib/rubygems/install_message.rb b/ruby/lib/rubygems/install_message.rb index 3c13888a8..861ead377 100644 --- a/ruby/lib/rubygems/install_message.rb +++ b/ruby/lib/rubygems/install_message.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/user_interaction' +require_relative '../rubygems' +require_relative 'user_interaction' ## # A default post-install hook that displays "Successfully installed diff --git a/ruby/lib/rubygems/install_update_options.rb b/ruby/lib/rubygems/install_update_options.rb index 38a068295..454104435 100644 --- a/ruby/lib/rubygems/install_update_options.rb +++ b/ruby/lib/rubygems/install_update_options.rb @@ -5,8 +5,8 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems' -require 'rubygems/security_option' +require_relative '../rubygems' +require_relative 'security_option' ## # Mixin methods for install and update options for Gem::Commands @@ -25,20 +25,20 @@ def add_install_update_options end add_option(:"Install/Update", '-n', '--bindir DIR', - 'Directory where executables are', - 'located') do |value, options| + 'Directory where executables will be', + 'placed when the gem is installed') do |value, options| options[:bin_dir] = File.expand_path(value) end - add_option(:"Install/Update", '--document [TYPES]', Array, + add_option(:"Install/Update", '--document [TYPES]', Array, 'Generate documentation for installed gems', 'List the documentation types you wish to', 'generate. For example: rdoc,ri') do |value, options| options[:document] = case value - when nil then %w[ri] - when false then [] - else value - end + when nil then %w[ri] + when false then [] + else value + end end add_option(:"Install/Update", '--build-root DIR', @@ -51,7 +51,7 @@ def add_install_update_options 'Install gem into the vendor directory.', 'Only for use by gem repackagers.') do |value, options| unless Gem.vendor_dir - raise OptionParser::InvalidOption.new 'your platform is not supported' + raise Gem::OptionParser::InvalidOption.new 'your platform is not supported' end options[:vendor] = true @@ -88,7 +88,7 @@ def add_install_update_options options[:ignore_dependencies] = value end - add_option(:"Install/Update", '--[no-]format-executable', + add_option(:"Install/Update", '--[no-]format-executable', 'Make installed executable names match Ruby.', 'If Ruby is ruby18, foo_exec will be', 'foo_exec18') do |value, options| @@ -122,10 +122,10 @@ def add_install_update_options options[:minimal_deps] = true end - add_option(:"Install/Update", "--minimal-deps", + add_option(:"Install/Update", "--[no-]minimal-deps", "Don't upgrade any dependencies that already", "meet version requirements") do |value, options| - options[:minimal_deps] = true + options[:minimal_deps] = value end add_option(:"Install/Update", "--[no-]post-install-message", @@ -143,7 +143,7 @@ def add_install_update_options unless v message = v ? v : "(tried #{Gem::GEM_DEP_FILES.join ', '})" - raise OptionParser::InvalidArgument, + raise Gem::OptionParser::InvalidArgument, "cannot find gem dependencies file #{message}" end @@ -154,7 +154,7 @@ def add_install_update_options 'Omit the named groups (comma separated)', 'when installing from a gem dependencies', 'file') do |v,o| - options[:without_groups].concat v.map { |without| without.intern } + options[:without_groups].concat v.map {|without| without.intern } end add_option(:"Install/Update", '--default', @@ -181,10 +181,19 @@ def add_install_update_options end ## - # Default options for the gem install command. + # Default options for the gem install and update commands. + + def install_update_options + { + :document => %w[ri], + } + end + + ## + # Default description for the gem install and update commands. def install_update_defaults_str - '--document=rdoc,ri --wrappers' + '--document=ri' end end diff --git a/ruby/lib/rubygems/installer.rb b/ruby/lib/rubygems/installer.rb index ad39ec81b..4cda09f20 100644 --- a/ruby/lib/rubygems/installer.rb +++ b/ruby/lib/rubygems/installer.rb @@ -5,13 +5,12 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/command' -require 'rubygems/exceptions' -require 'rubygems/deprecate' -require 'rubygems/package' -require 'rubygems/ext' -require 'rubygems/user_interaction' -require 'fileutils' +require_relative 'installer_uninstaller_utils' +require_relative 'exceptions' +require_relative 'deprecate' +require_relative 'package' +require_relative 'ext' +require_relative 'user_interaction' ## # The installer installs the files contained in the .gem into the Gem.home. @@ -27,7 +26,6 @@ # file. See Gem.pre_install and Gem.post_install for details. class Gem::Installer - extend Gem::Deprecate ## @@ -43,10 +41,7 @@ class Gem::Installer include Gem::UserInteraction - ## - # Filename of the gem being installed. - - attr_reader :gem + include Gem::InstallerUninstallerUtils ## # The directory a gem's executables will be installed into @@ -72,20 +67,28 @@ class Gem::Installer @path_warning = false - @install_lock = Mutex.new - class << self + # + # Changes in rubygems to lazily loading `rubygems/command` (in order to + # lazily load `optparse` as a side effect) affect bundler's custom installer + # which uses `Gem::Command` without requiring it (up until bundler 2.2.29). + # This hook is to compensate for that missing require. + # + # TODO: Remove when rubygems no longer supports running on bundler older + # than 2.2.29. - ## - # True if we've warned about PATH not including Gem.bindir + def inherited(klass) + if klass.name == "Bundler::RubyGemsGemInstaller" + require "rubygems/command" + end - attr_accessor :path_warning + super(klass) + end ## - # Certain aspects of the install process are not thread-safe. This lock is - # used to allow multiple threads to install Gems at the same time. + # True if we've warned about PATH not including Gem.bindir - attr_reader :install_lock + attr_accessor :path_warning ## # Overrides the executable format. @@ -100,7 +103,6 @@ class << self def exec_format @exec_format ||= Gem.default_exec_format end - end ## @@ -113,7 +115,6 @@ def self.at(path, options = {}) end class FakePackage - attr_accessor :spec attr_accessor :dir_mode @@ -139,7 +140,6 @@ def extract_files(destination_dir, pattern = '*') def copy_to(path) end - end ## @@ -180,15 +180,7 @@ def initialize(package, options={}) require 'fileutils' @options = options - if package.is_a? String - security_policy = options[:security_policy] - @package = Gem::Package.new package, security_policy - if $VERBOSE - warn "constructing an Installer object with a string is deprecated. Please use Gem::Installer.at (called from: #{caller.first})" - end - else - @package = package - end + @package = package process_options @@ -199,6 +191,7 @@ def initialize(package, options={}) if options[:user_install] @gem_home = Gem.user_dir @bin_dir = Gem.bindir gem_home unless options[:bin_dir] + @plugins_dir = Gem.plugindir(gem_home) check_that_user_bin_dir_is_in_path end end @@ -208,8 +201,8 @@ def initialize(package, options={}) # # If +@force+ is set +filename+ is overwritten. # - # If +filename+ exists and is a RubyGems wrapper for different gem the user - # is consulted. + # If +filename+ exists and it is a RubyGems wrapper for a different gem, then + # the user is consulted. # # If +filename+ exists and +@bin_dir+ is Gem.default_bindir (/usr/local) the # user is consulted. @@ -227,7 +220,17 @@ def check_executable_overwrite(filename) # :nodoc: existing = nil File.open generated_bin, 'rb' do |io| - next unless io.gets =~ /^#!/ # shebang + line = io.gets + shebang = /^#!.*ruby/ + + if load_relative_enabled? + until line.nil? || line =~ shebang do + line = io.gets + end + end + + next unless line =~ shebang + io.gets # blankline # TODO detect a specially formatted comment instead of trying @@ -300,8 +303,6 @@ def spec def install pre_install_checks - FileUtils.rm_f File.join gem_home, 'specifications', spec.spec_name - run_pre_install_hooks # Set loaded_from to ensure extension_dir is correct @@ -330,6 +331,7 @@ def install end generate_bin + generate_plugins unless @options[:install_as_default] write_spec @@ -340,7 +342,7 @@ def install say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil? - Gem::Installer.install_lock.synchronize { Gem::Specification.reset } + Gem::Specification.reset run_post_install_hooks @@ -419,7 +421,7 @@ def ensure_dependency(spec, dependency) def installation_satisfies_dependency?(dependency) return true if @options[:development] and dependency.type == :development - return true if installed_specs.detect { |s| dependency.matches_spec? s } + return true if installed_specs.detect {|s| dependency.matches_spec? s } return false if @only_install_dir not dependency.matching_specs.empty? end @@ -431,7 +433,7 @@ def unpack(directory) @gem_dir = directory extract_files end - deprecate :unpack, :none, 2020, 04 + rubygems_deprecate :unpack ## # The location of the spec file that is installed. @@ -446,7 +448,7 @@ def spec_file # def default_spec_file - File.join Gem.default_specifications_dir, "#{spec.full_name}.gemspec" + File.join gem_home, "specifications", "default", "#{spec.full_name}.gemspec" end ## @@ -454,13 +456,9 @@ def default_spec_file # specifications directory. def write_spec - File.open spec_file, 'w' do |file| - spec.installed_by_version = Gem.rubygems_version - - file.puts spec.to_ruby_for_cache + spec.installed_by_version = Gem.rubygems_version - file.fsync rescue nil # for filesystems without fsync(2) - end + Gem.write_binary(spec_file, spec.to_ruby_for_cache) end ## @@ -468,9 +466,7 @@ def write_spec # specifications/default directory. def write_default_spec - File.open(default_spec_file, "w") do |file| - file.puts spec.to_ruby - end + Gem.write_binary(default_spec_file, spec.to_ruby) end ## @@ -491,27 +487,28 @@ def generate_windows_script(filename, bindir) def generate_bin # :nodoc: return if spec.executables.nil? or spec.executables.empty? - begin - Dir.mkdir @bin_dir, *[options[:dir_mode] && 0755].compact - rescue SystemCallError - raise unless File.directory? @bin_dir - end - - raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir + ensure_writable_dir @bin_dir spec.executables.each do |filename| filename.tap(&Gem::UNTAINT) bin_path = File.join gem_dir, spec.bindir, filename unless File.exist? bin_path - # TODO change this to a more useful warning - warn "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?" + if File.symlink? bin_path + alert_warning "`#{bin_path}` is dangling symlink pointing to `#{File.readlink bin_path}`" + else + alert_warning "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?" + end next end mode = File.stat(bin_path).mode dir_mode = options[:prog_mode] || (mode | 0111) - FileUtils.chmod dir_mode, bin_path unless dir_mode == mode + + unless dir_mode == mode + require 'fileutils' + FileUtils.chmod dir_mode, bin_path + end check_executable_overwrite filename @@ -520,7 +517,19 @@ def generate_bin # :nodoc: else generate_bin_symlink filename, @bin_dir end + end + end + def generate_plugins # :nodoc: + latest = Gem::Specification.latest_spec_for(spec.name) + return if latest && latest.version > spec.version + + ensure_writable_dir @plugins_dir + + if spec.plugins.empty? + remove_plugins_for(spec, @plugins_dir) + else + regenerate_plugins_for(spec, @plugins_dir) end end @@ -534,6 +543,7 @@ def generate_bin # :nodoc: def generate_bin_script(filename, bindir) bin_script_path = File.join bindir, formatted_program_filename(filename) + require 'fileutils' FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers File.open bin_script_path, 'wb', 0755 do |file| @@ -585,11 +595,10 @@ def generate_bin_symlink(filename, bindir) # def shebang(bin_file_name) - ruby_name = RbConfig::CONFIG['ruby_install_name'] if @env_shebang path = File.join gem_dir, spec.bindir, bin_file_name - first_line = File.open(path, "rb") {|file| file.gets} + first_line = File.open(path, "rb") {|file| file.gets } || "" - if /\A#!/ =~ first_line + if first_line.start_with?("#!") # Preserve extra words on shebang line, like "-w". Thanks RPA. shebang = first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/, "#!#{Gem.ruby}") opts = $1 @@ -598,7 +607,7 @@ def shebang(bin_file_name) if which = Gem.configuration[:custom_shebang] # replace bin_file_name with "ruby" to avoid endless loops - which = which.gsub(/ #{bin_file_name}$/," #{RbConfig::CONFIG['ruby_install_name']}") + which = which.gsub(/ #{bin_file_name}$/," #{ruby_install_name}") which = which.gsub(/\$(\w+)/) do case $1 @@ -614,14 +623,12 @@ def shebang(bin_file_name) end "#!#{which}" - elsif not ruby_name - "#!#{Gem.ruby}#{opts}" - elsif opts - "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}" - else + elsif @env_shebang # Create a plain shebang line. @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } - "#!#{@env_path} #{ruby_name}" + "#!#{@env_path} #{ruby_install_name}" + else + "#{bash_prolog_script}#!#{Gem.ruby}#{opts}" end end @@ -641,27 +648,6 @@ def ensure_loadable_spec end end - def ensure_required_ruby_version_met # :nodoc: - if rrv = spec.required_ruby_version - ruby_version = Gem.ruby_version - unless rrv.satisfied_by? ruby_version - raise Gem::RuntimeRequirementNotMetError, - "#{spec.name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}." - end - end - end - - def ensure_required_rubygems_version_met # :nodoc: - if rrgv = spec.required_rubygems_version - unless rrgv.satisfied_by? Gem.rubygems_version - rg_version = Gem::VERSION - raise Gem::RuntimeRequirementNotMetError, - "#{spec.name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " + - "Try 'gem update --system' to update RubyGems itself." - end - end - end - def ensure_dependencies_met # :nodoc: deps = spec.runtime_dependencies deps |= spec.development_dependencies if @development @@ -677,13 +663,14 @@ def process_options # :nodoc: :env_shebang => false, :force => false, :only_install_dir => false, - :post_install_message => true + :post_install_message => true, }.merge options @env_shebang = options[:env_shebang] @force = options[:force] @install_dir = options[:install_dir] @gem_home = options[:install_dir] || Gem.dir + @plugins_dir = Gem.plugindir(@gem_home) @ignore_dependencies = options[:ignore_dependencies] @format_executable = options[:format_executable] @wrappers = options[:wrappers] @@ -696,23 +683,25 @@ def process_options # :nodoc: @development = options[:development] @build_root = options[:build_root] - @build_args = options[:build_args] || Gem::Command.build_args + @build_args = options[:build_args] unless @build_root.nil? - require 'pathname' - @build_root = Pathname.new(@build_root).expand_path - @bin_dir = File.join(@build_root, options[:bin_dir] || Gem.bindir(@gem_home)) - @gem_home = File.join(@build_root, @gem_home) - alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}" + @bin_dir = File.join(@build_root, @bin_dir.gsub(/^[a-zA-Z]:/, '')) + @gem_home = File.join(@build_root, @gem_home.gsub(/^[a-zA-Z]:/, '')) + @plugins_dir = File.join(@build_root, @plugins_dir.gsub(/^[a-zA-Z]:/, '')) + alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}\n Plugins dir: #{@plugins_dir}" end end def check_that_user_bin_dir_is_in_path # :nodoc: + return if self.class.path_warning + user_bin_dir = @bin_dir || Gem.bindir(gem_home) - user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if - File::ALT_SEPARATOR + user_bin_dir = user_bin_dir.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR path = ENV['PATH'] + path = path.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR + if Gem.win_platform? path = path.downcase user_bin_dir = user_bin_dir.downcase @@ -722,10 +711,8 @@ def check_that_user_bin_dir_is_in_path # :nodoc: unless path.include? user_bin_dir unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~')) - unless self.class.path_warning - alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run." - self.class.path_warning = true - end + alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run." + self.class.path_warning = true end end end @@ -748,6 +735,10 @@ def verify_spec raise Gem::InstallError, "#{spec} has an invalid extensions" end + if spec.platform.to_s =~ /\R/ + raise Gem::InstallError, "#{spec.platform} is an invalid platform" + end + unless spec.specification_version.to_s =~ /\A\d+\z/ raise Gem::InstallError, "#{spec} has an invalid specification_version" end @@ -777,14 +768,14 @@ def app_script_text(bin_file_name) # require 'rubygems' - +#{gemdeps_load(spec.name)} version = "#{Gem::Requirement.default_prerelease}" str = ARGV.first if str str = str.b[/\\A_(.*)_\\z/, 1] if str and Gem::Version.correct?(str) - version = str + #{explicit_version_requirement(spec.name)} ARGV.shift end end @@ -798,11 +789,29 @@ def app_script_text(bin_file_name) TEXT end + def gemdeps_load(name) + return '' if name == "bundler" + + <<-TEXT + +Gem.use_gemdeps +TEXT + end + + def explicit_version_requirement(name) + code = "version = str" + return code unless name == "bundler" + + code += <<-TEXT + + ENV['BUNDLER_VERSION'] = str +TEXT + end + ## # return the stub script text used to launch the true Ruby script def windows_stub_script(bindir, bin_file_name) - rb_config = RbConfig::CONFIG rb_topdir = RbConfig::TOPDIR || File.dirname(rb_config["bindir"]) # get ruby executable file name from RbConfig @@ -810,7 +819,7 @@ def windows_stub_script(bindir, bin_file_name) ruby_exe = "ruby.exe" if ruby_exe.empty? if File.exist?(File.join bindir, ruby_exe) - # stub & ruby.exe withing same folder. Portable + # stub & ruby.exe within same folder. Portable <<-TEXT @ECHO OFF @"%~dp0#{ruby_exe}" "%~dpn0" %* @@ -839,23 +848,11 @@ def windows_stub_script(bindir, bin_file_name) # configure scripts and rakefiles or mkrf_conf files. def build_extensions - builder = Gem::Ext::Builder.new spec, @build_args + builder = Gem::Ext::Builder.new spec, build_args builder.build_extensions end - ## - # Logs the build +output+ in +build_dir+, then raises Gem::Ext::BuildError. - # - # TODO: Delete this for RubyGems 4. It remains for API compatibility - - def extension_build_error(build_dir, output, backtrace = nil) # :nodoc: - builder = Gem::Ext::Builder.new spec, @build_args - - builder.build_error build_dir, output, backtrace - end - deprecate :extension_build_error, :none, 2018, 12 - ## # Reads the file index and extracts each file into the gem directory. # @@ -895,6 +892,13 @@ def dir gem_dir.to_s end + ## + # Filename of the gem being installed. + + def gem + @package.gem.path + end + ## # Performs various checks before installing the gem such as the install # repository is writable and its directories exist, required Ruby and @@ -921,8 +925,6 @@ def pre_install_checks return true if @force - ensure_required_ruby_version_met - ensure_required_rubygems_version_met ensure_dependencies_met unless @ignore_dependencies true @@ -933,7 +935,7 @@ def pre_install_checks # extensions. def write_build_info_file - return if @build_args.empty? + return if build_args.empty? build_info_dir = File.join gem_home, 'build_info' @@ -943,7 +945,7 @@ def write_build_info_file build_info_file = File.join build_info_dir, "#{spec.full_name}.info" File.open build_info_file, 'w' do |io| - @build_args.each do |arg| + build_args.each do |arg| io.puts arg end end @@ -959,4 +961,55 @@ def write_cache_file @package.copy_to cache_file end + def ensure_writable_dir(dir) # :nodoc: + begin + Dir.mkdir dir, *[options[:dir_mode] && 0755].compact + rescue SystemCallError + raise unless File.directory? dir + end + + raise Gem::FilePermissionError.new(dir) unless File.writable? dir + end + + private + + def build_args + @build_args ||= begin + require_relative "command" + Gem::Command.build_args + end + end + + def rb_config + RbConfig::CONFIG + end + + def ruby_install_name + rb_config["ruby_install_name"] + end + + def load_relative_enabled? + rb_config["LIBRUBY_RELATIVE"] == 'yes' + end + + def bash_prolog_script + if load_relative_enabled? + script = +<<~EOS + bindir="${0%/*}" + EOS + + script << %Q(exec "$bindir/#{ruby_install_name}" "-x" "$0" "$@"\n) + + <<~EOS + #!/bin/sh + # -*- ruby -*- + _=_\\ + =begin + #{script.chomp} + =end + EOS + else + "" + end + end end diff --git a/ruby/lib/rubygems/installer_uninstaller_utils.rb b/ruby/lib/rubygems/installer_uninstaller_utils.rb new file mode 100644 index 000000000..2c8b7c635 --- /dev/null +++ b/ruby/lib/rubygems/installer_uninstaller_utils.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +## +# Helper methods for both Gem::Installer and Gem::Uninstaller + +module Gem::InstallerUninstallerUtils + + def regenerate_plugins_for(spec, plugins_dir) + plugins = spec.plugins + return if plugins.empty? + + require 'pathname' + + spec.plugins.each do |plugin| + plugin_script_path = File.join plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}" + + File.open plugin_script_path, 'wb' do |file| + file.puts "require_relative '#{Pathname.new(plugin).relative_path_from(Pathname.new(plugins_dir))}'" + end + + verbose plugin_script_path + end + end + + def remove_plugins_for(spec, plugins_dir) + FileUtils.rm_f Gem::Util.glob_files_in_dir("#{spec.name}#{Gem.plugin_suffix_pattern}", plugins_dir) + end + +end diff --git a/ruby/lib/rubygems/local_remote_options.rb b/ruby/lib/rubygems/local_remote_options.rb index c940f50ad..0b8b0ee1a 100644 --- a/ruby/lib/rubygems/local_remote_options.rb +++ b/ruby/lib/rubygems/local_remote_options.rb @@ -6,7 +6,7 @@ #++ require 'uri' -require 'rubygems' +require_relative '../rubygems' ## # Mixin methods for local and remote Gem::Command options. @@ -14,19 +14,19 @@ module Gem::LocalRemoteOptions ## - # Allows OptionParser to handle HTTP URIs. + # Allows Gem::OptionParser to handle HTTP URIs. def accept_uri_http - OptionParser.accept URI::HTTP do |value| + Gem::OptionParser.accept URI::HTTP do |value| begin uri = URI.parse value rescue URI::InvalidURIError - raise OptionParser::InvalidArgument, value + raise Gem::OptionParser::InvalidArgument, value end valid_uri_schemes = ["http", "https", "file", "s3"] unless valid_uri_schemes.include?(uri.scheme) - msg = "Invalid uri scheme for #{value}\nPreface URLs with one of #{valid_uri_schemes.map{|s| "#{s}://"}}" + msg = "Invalid uri scheme for #{value}\nPreface URLs with one of #{valid_uri_schemes.map{|s| "#{s}://" }}" raise ArgumentError, msg end diff --git a/ruby/lib/rubygems/mock_gem_ui.rb b/ruby/lib/rubygems/mock_gem_ui.rb index 9ece75881..914ecb9a7 100644 --- a/ruby/lib/rubygems/mock_gem_ui.rb +++ b/ruby/lib/rubygems/mock_gem_ui.rb @@ -1,32 +1,27 @@ # frozen_string_literal: true -require 'rubygems/user_interaction' +require_relative 'user_interaction' ## # This Gem::StreamUI subclass records input and output to StringIO for # retrieval during tests. class Gem::MockGemUi < Gem::StreamUI - ## # Raised when you haven't provided enough input to your MockGemUi class InputEOFError < RuntimeError - def initialize(question) super "Out of input for MockGemUi on #{question.inspect}" end - end class TermError < RuntimeError - attr_reader :exit_code def initialize(exit_code) super @exit_code = exit_code end - end class SystemExitException < RuntimeError; end @@ -87,5 +82,4 @@ def terminate_interaction(status=0) raise TermError, status if status != 0 raise SystemExitException end - end diff --git a/ruby/lib/rubygems/name_tuple.rb b/ruby/lib/rubygems/name_tuple.rb index dc1a1bbaa..c732d7f96 100644 --- a/ruby/lib/rubygems/name_tuple.rb +++ b/ruby/lib/rubygems/name_tuple.rb @@ -4,10 +4,7 @@ # Represents a gem of name +name+ at +version+ of +platform+. These # wrap the data returned from the indexes. -require 'rubygems/platform' - class Gem::NameTuple - def initialize(name, version, platform="ruby") @name = name @version = version @@ -26,7 +23,7 @@ def initialize(name, version, platform="ruby") # NameTuple objects. def self.from_list(list) - list.map { |t| new(*t) } + list.map {|t| new(*t) } end ## @@ -34,7 +31,7 @@ def self.from_list(list) # [name, version, platform] tuples. def self.to_basic(list) - list.map { |t| t.to_a } + list.map {|t| t.to_a } end ## @@ -62,7 +59,7 @@ def full_name # Indicate if this NameTuple matches the current platform. def match_platform? - Gem::Platform.match @platform + Gem::Platform.match_gem? @platform, @name end ## @@ -92,9 +89,8 @@ def inspect # :nodoc: alias to_s inspect # :nodoc: def <=>(other) - [@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1] <=> - [other.name, other.version, - other.platform == Gem::Platform::RUBY ? -1 : 1] + [@name, @version, Gem::Platform.sort_priority(@platform)] <=> + [other.name, other.version, Gem::Platform.sort_priority(other.platform)] end include Comparable @@ -121,5 +117,4 @@ def ==(other) def hash to_a.hash end - end diff --git a/ruby/lib/rubygems/openssl.rb b/ruby/lib/rubygems/openssl.rb new file mode 100644 index 000000000..c44f619c4 --- /dev/null +++ b/ruby/lib/rubygems/openssl.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +autoload :OpenSSL, "openssl" + +module Gem + HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc: +end diff --git a/ruby/lib/rubygems/optparse.rb b/ruby/lib/rubygems/optparse.rb new file mode 100644 index 000000000..65be9f6b7 --- /dev/null +++ b/ruby/lib/rubygems/optparse.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative 'optparse/lib/optparse' diff --git a/ruby/lib/rubygems/optparse/.document b/ruby/lib/rubygems/optparse/.document new file mode 100644 index 000000000..0c43bbd6b --- /dev/null +++ b/ruby/lib/rubygems/optparse/.document @@ -0,0 +1 @@ +# Vendored files do not need to be documented diff --git a/ruby/lib/rubygems/optparse/lib/optionparser.rb b/ruby/lib/rubygems/optparse/lib/optionparser.rb new file mode 100644 index 000000000..4b9b40d82 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optionparser.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: false +require_relative 'optparse' diff --git a/ruby/lib/rubygems/optparse/lib/optparse.rb b/ruby/lib/rubygems/optparse/lib/optparse.rb new file mode 100644 index 000000000..e4b1c61f7 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse.rb @@ -0,0 +1,2230 @@ +# frozen_string_literal: true +# +# optparse.rb - command-line option analysis with the Gem::OptionParser class. +# +# Author:: Nobu Nakada +# Documentation:: Nobu Nakada and Gavin Sinclair. +# +# See Gem::OptionParser for documentation. +# + + +#-- +# == Developer Documentation (not for RDoc output) +# +# === Class tree +# +# - Gem::OptionParser:: front end +# - Gem::OptionParser::Switch:: each switches +# - Gem::OptionParser::List:: options list +# - Gem::OptionParser::ParseError:: errors on parsing +# - Gem::OptionParser::AmbiguousOption +# - Gem::OptionParser::NeedlessArgument +# - Gem::OptionParser::MissingArgument +# - Gem::OptionParser::InvalidOption +# - Gem::OptionParser::InvalidArgument +# - Gem::OptionParser::AmbiguousArgument +# +# === Object relationship diagram +# +# +--------------+ +# | Gem::OptionParser |<>-----+ +# +--------------+ | +--------+ +# | ,-| Switch | +# on_head -------->+---------------+ / +--------+ +# accept/reject -->| List |<|>- +# | |<|>- +----------+ +# on ------------->+---------------+ `-| argument | +# : : | class | +# +---------------+ |==========| +# on_tail -------->| | |pattern | +# +---------------+ |----------| +# Gem::OptionParser.accept ->| DefaultList | |converter | +# reject |(shared between| +----------+ +# | all instances)| +# +---------------+ +# +#++ +# +# == Gem::OptionParser +# +# === New to \Gem::OptionParser? +# +# See the {Tutorial}[./doc/optparse/tutorial_rdoc.html]. +# +# === Introduction +# +# Gem::OptionParser is a class for command-line option analysis. It is much more +# advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented +# solution. +# +# === Features +# +# 1. The argument specification and the code to handle it are written in the +# same place. +# 2. It can output an option summary; you don't need to maintain this string +# separately. +# 3. Optional and mandatory arguments are specified very gracefully. +# 4. Arguments can be automatically converted to a specified class. +# 5. Arguments can be restricted to a certain set. +# +# All of these features are demonstrated in the examples below. See +# #make_switch for full documentation. +# +# === Minimal example +# +# require 'rubygems/optparse/lib/optparse' +# +# options = {} +# Gem::OptionParser.new do |parser| +# parser.banner = "Usage: example.rb [options]" +# +# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| +# options[:verbose] = v +# end +# end.parse! +# +# p options +# p ARGV +# +# === Generating Help +# +# Gem::OptionParser can be used to automatically generate help for the commands you +# write: +# +# require 'rubygems/optparse/lib/optparse' +# +# Options = Struct.new(:name) +# +# class Parser +# def self.parse(options) +# args = Options.new("world") +# +# opt_parser = Gem::OptionParser.new do |parser| +# parser.banner = "Usage: example.rb [options]" +# +# parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| +# args.name = n +# end +# +# parser.on("-h", "--help", "Prints this help") do +# puts parser +# exit +# end +# end +# +# opt_parser.parse!(options) +# return args +# end +# end +# options = Parser.parse %w[--help] +# +# #=> +# # Usage: example.rb [options] +# # -n, --name=NAME Name to say hello to +# # -h, --help Prints this help +# +# === Required Arguments +# +# For options that require an argument, option specification strings may include an +# option name in all caps. If an option is used without the required argument, +# an exception will be raised. +# +# require 'rubygems/optparse/lib/optparse' +# +# options = {} +# Gem::OptionParser.new do |parser| +# parser.on("-r", "--require LIBRARY", +# "Require the LIBRARY before executing your script") do |lib| +# puts "You required #{lib}!" +# end +# end.parse! +# +# Used: +# +# $ ruby optparse-test.rb -r +# optparse-test.rb:9:in `
': missing argument: -r (Gem::OptionParser::MissingArgument) +# $ ruby optparse-test.rb -r my-library +# You required my-library! +# +# === Type Coercion +# +# Gem::OptionParser supports the ability to coerce command line arguments +# into objects for us. +# +# Gem::OptionParser comes with a few ready-to-use kinds of type +# coercion. They are: +# +# - Date -- Anything accepted by +Date.parse+ +# - DateTime -- Anything accepted by +DateTime.parse+ +# - Time -- Anything accepted by +Time.httpdate+ or +Time.parse+ +# - URI -- Anything accepted by +URI.parse+ +# - Shellwords -- Anything accepted by +Shellwords.shellwords+ +# - String -- Any non-empty string +# - Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040) +# - Float -- Any float. (e.g. 10, 3.14, -100E+13) +# - Numeric -- Any integer, float, or rational (1, 3.4, 1/3) +# - DecimalInteger -- Like +Integer+, but no octal format. +# - OctalInteger -- Like +Integer+, but no decimal format. +# - DecimalNumeric -- Decimal integer or float. +# - TrueClass -- Accepts '+, yes, true, -, no, false' and +# defaults as +true+ +# - FalseClass -- Same as +TrueClass+, but defaults to +false+ +# - Array -- Strings separated by ',' (e.g. 1,2,3) +# - Regexp -- Regular expressions. Also includes options. +# +# We can also add our own coercions, which we will cover below. +# +# ==== Using Built-in Conversions +# +# As an example, the built-in +Time+ conversion is used. The other built-in +# conversions behave in the same way. +# Gem::OptionParser will attempt to parse the argument +# as a +Time+. If it succeeds, that time will be passed to the +# handler block. Otherwise, an exception will be raised. +# +# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/optparse/lib/optparse/time' +# Gem::OptionParser.new do |parser| +# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| +# p time +# end +# end.parse! +# +# Used: +# +# $ ruby optparse-test.rb -t nonsense +# ... invalid argument: -t nonsense (Gem::OptionParser::InvalidArgument) +# $ ruby optparse-test.rb -t 10-11-12 +# 2010-11-12 00:00:00 -0500 +# $ ruby optparse-test.rb -t 9:30 +# 2014-08-13 09:30:00 -0400 +# +# ==== Creating Custom Conversions +# +# The +accept+ method on Gem::OptionParser may be used to create converters. +# It specifies which conversion block to call whenever a class is specified. +# The example below uses it to fetch a +User+ object before the +on+ handler receives it. +# +# require 'rubygems/optparse/lib/optparse' +# +# User = Struct.new(:id, :name) +# +# def find_user id +# not_found = ->{ raise "No User Found for id #{id}" } +# [ User.new(1, "Sam"), +# User.new(2, "Gandalf") ].find(not_found) do |u| +# u.id == id +# end +# end +# +# op = Gem::OptionParser.new +# op.accept(User) do |user_id| +# find_user user_id.to_i +# end +# +# op.on("--user ID", User) do |user| +# puts user +# end +# +# op.parse! +# +# Used: +# +# $ ruby optparse-test.rb --user 1 +# # +# $ 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) +# +# === Store options to a Hash +# +# The +into+ option of +order+, +parse+ and so on methods stores command line options into a Hash. +# +# require 'rubygems/optparse/lib/optparse' +# +# options = {} +# Gem::OptionParser.new do |parser| +# parser.on('-a') +# parser.on('-b NUM', Integer) +# parser.on('-v', '--verbose') +# end.parse!(into: options) +# +# p options +# +# Used: +# +# $ ruby optparse-test.rb -a +# {:a=>true} +# $ ruby optparse-test.rb -a -v +# {:a=>true, :verbose=>true} +# $ ruby optparse-test.rb -a -b 100 +# {:a=>true, :b=>100} +# +# === Complete example +# +# The following example is a complete Ruby program. You can run it and see the +# effect of specifying various options. This is probably the best way to learn +# the features of +optparse+. +# +# require 'rubygems/optparse/lib/optparse' +# require 'rubygems/optparse/lib/optparse/time' +# require 'ostruct' +# require 'pp' +# +# class OptparseExample +# Version = '1.0.0' +# +# CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary] +# CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } +# +# class ScriptOptions +# attr_accessor :library, :inplace, :encoding, :transfer_type, +# :verbose, :extension, :delay, :time, :record_separator, +# :list +# +# def initialize +# self.library = [] +# self.inplace = false +# self.encoding = "utf8" +# self.transfer_type = :auto +# self.verbose = false +# end +# +# def define_options(parser) +# parser.banner = "Usage: example.rb [options]" +# parser.separator "" +# parser.separator "Specific options:" +# +# # add additional options +# perform_inplace_option(parser) +# delay_execution_option(parser) +# execute_at_time_option(parser) +# specify_record_separator_option(parser) +# list_example_option(parser) +# specify_encoding_option(parser) +# optional_option_argument_with_keyword_completion_option(parser) +# boolean_verbose_option(parser) +# +# parser.separator "" +# parser.separator "Common options:" +# # No argument, shows at tail. This will print an options summary. +# # Try it and see! +# parser.on_tail("-h", "--help", "Show this message") do +# puts parser +# exit +# end +# # Another typical switch to print the version. +# parser.on_tail("--version", "Show version") do +# puts Version +# exit +# end +# end +# +# def perform_inplace_option(parser) +# # Specifies an optional option argument +# parser.on("-i", "--inplace [EXTENSION]", +# "Edit ARGV files in place", +# "(make backup if EXTENSION supplied)") do |ext| +# self.inplace = true +# self.extension = ext || '' +# self.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot. +# end +# end +# +# def delay_execution_option(parser) +# # Cast 'delay' argument to a Float. +# parser.on("--delay N", Float, "Delay N seconds before executing") do |n| +# self.delay = n +# end +# end +# +# def execute_at_time_option(parser) +# # Cast 'time' argument to a Time object. +# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| +# self.time = time +# end +# end +# +# def specify_record_separator_option(parser) +# # Cast to octal integer. +# parser.on("-F", "--irs [OCTAL]", Gem::OptionParser::OctalInteger, +# "Specify record separator (default \\0)") do |rs| +# self.record_separator = rs +# end +# end +# +# def list_example_option(parser) +# # List of arguments. +# parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list| +# self.list = list +# end +# end +# +# def specify_encoding_option(parser) +# # Keyword completion. We are specifying a specific set of arguments (CODES +# # and CODE_ALIASES - notice the latter is a Hash), and the user may provide +# # the shortest unambiguous text. +# code_list = (CODE_ALIASES.keys + CODES).join(', ') +# parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding", +# "(#{code_list})") do |encoding| +# self.encoding = encoding +# end +# end +# +# def optional_option_argument_with_keyword_completion_option(parser) +# # Optional '--type' option argument with keyword completion. +# parser.on("--type [TYPE]", [:text, :binary, :auto], +# "Select transfer type (text, binary, auto)") do |t| +# self.transfer_type = t +# end +# end +# +# def boolean_verbose_option(parser) +# # Boolean switch. +# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| +# self.verbose = v +# end +# end +# end +# +# # +# # Return a structure describing the options. +# # +# def parse(args) +# # The options specified on the command line will be collected in +# # *options*. +# +# @options = ScriptOptions.new +# @args = Gem::OptionParser.new do |parser| +# @options.define_options(parser) +# parser.parse!(args) +# end +# @options +# end +# +# attr_reader :parser, :options +# end # class OptparseExample +# +# example = OptparseExample.new +# options = example.parse(ARGV) +# pp options # example.options +# pp ARGV +# +# === Shell Completion +# +# For modern shells (e.g. bash, zsh, etc.), you can use shell +# completion for command line options. +# +# === Further documentation +# +# The above examples, along with the accompanying +# {Tutorial}[./doc/optparse/tutorial_rdoc.html], +# should be enough to learn how to use this class. +# If you have any questions, file a ticket at http://bugs.ruby-lang.org. +# +class Gem::OptionParser + Gem::OptionParser::Version = "0.2.0" + + # :stopdoc: + NoArgument = [NO_ARGUMENT = :NONE, nil].freeze + RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze + OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze + # :startdoc: + + # + # Keyword completion module. This allows partial arguments to be specified + # and resolved against a list of acceptable values. + # + module Completion + def self.regexp(key, icase) + Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase) + end + + def self.candidate(key, icase = false, pat = nil, &block) + pat ||= Completion.regexp(key, icase) + candidates = [] + block.call do |k, *v| + (if Regexp === k + kn = "" + k === key + else + kn = defined?(k.id2name) ? k.id2name : k + pat === kn + end) or next + v << k if v.empty? + candidates << [k, v, kn] + end + candidates + end + + def candidate(key, icase = false, pat = nil) + Completion.candidate(key, icase, pat, &method(:each)) + end + + public + def complete(key, icase = false, pat = nil) + candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size} + if candidates.size == 1 + canon, sw, * = candidates[0] + elsif candidates.size > 1 + canon, sw, cn = candidates.shift + candidates.each do |k, v, kn| + next if sw == v + if String === cn and String === kn + if cn.rindex(kn, 0) + canon, sw, cn = k, v, kn + next + elsif kn.rindex(cn, 0) + next + end + end + throw :ambiguous, key + end + end + if canon + block_given? or return key, *sw + yield(key, *sw) + end + end + + def convert(opt = nil, val = nil, *) + val + end + end + + + # + # Map from option/keyword string to object with completion. + # + class OptionMap < Hash + include Completion + end + + + # + # Individual switch class. Not important to the user. + # + # Defined within Switch are several Switch-derived classes: NoArgument, + # RequiredArgument, etc. + # + class Switch + attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block + + # + # Guesses argument style from +arg+. Returns corresponding + # Gem::OptionParser::Switch class (OptionalArgument, etc.). + # + def self.guess(arg) + case arg + when "" + t = self + when /\A=?\[/ + t = Switch::OptionalArgument + when /\A\s+\[/ + t = Switch::PlacedArgument + else + t = Switch::RequiredArgument + end + self >= t or incompatible_argument_styles(arg, t) + t + end + + def self.incompatible_argument_styles(arg, t) + raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}", + ParseError.filter_backtrace(caller(2))) + end + + def self.pattern + NilClass + end + + def initialize(pattern = nil, conv = nil, + short = nil, long = nil, arg = nil, + desc = ([] if short or long), block = nil, &_block) + raise if Array === pattern + block ||= _block + @pattern, @conv, @short, @long, @arg, @desc, @block = + pattern, conv, short, long, arg, desc, block + end + + # + # Parses +arg+ and returns rest of +arg+ and matched portion to the + # argument pattern. Yields when the pattern doesn't match substring. + # + def parse_arg(arg) # :nodoc: + pattern or return nil, [arg] + unless m = pattern.match(arg) + yield(InvalidArgument, arg) + return arg, [] + end + if String === m + m = [s = m] + else + m = m.to_a + s = m[0] + return nil, m unless String === s + end + raise InvalidArgument, arg unless arg.rindex(s, 0) + return nil, m if s.length == arg.length + yield(InvalidArgument, arg) # didn't match whole arg + return arg[s.length..-1], m + end + private :parse_arg + + # + # Parses argument, converts and returns +arg+, +block+ and result of + # conversion. Yields at semi-error condition instead of raising an + # exception. + # + def conv_arg(arg, val = []) # :nodoc: + if conv + val = conv.call(*val) + else + val = proc {|v| v}.call(*val) + end + return arg, block, val + end + private :conv_arg + + # + # Produces the summary text. Each line of the summary is yielded to the + # block (without newline). + # + # +sdone+:: Already summarized short style options keyed hash. + # +ldone+:: Already summarized long style options keyed hash. + # +width+:: Width of left side (option part). In other words, the right + # side (description part) starts after +width+ columns. + # +max+:: Maximum width of left side -> the options are filled within + # +max+ columns. + # +indent+:: Prefix string indents all summarized lines. + # + def summarize(sdone = {}, ldone = {}, width = 1, max = width - 1, indent = "") + sopts, lopts = [], [], nil + @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short + @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long + return if sopts.empty? and lopts.empty? # completely hidden + + left = [sopts.join(', ')] + right = desc.dup + + while s = lopts.shift + l = left[-1].length + s.length + l += arg.length if left.size == 1 && arg + l < max or sopts.empty? or left << +'' + left[-1] << (left[-1].empty? ? ' ' * 4 : ', ') << s + end + + if arg + left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg) + end + mlen = left.collect {|ss| ss.length}.max.to_i + while mlen > width and l = left.shift + mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen + if l.length < width and (r = right[0]) and !r.empty? + l = l.to_s.ljust(width) + ' ' + r + right.shift + end + yield(indent + l) + end + + while begin l = left.shift; r = right.shift; l or r end + l = l.to_s.ljust(width) + ' ' + r if r and !r.empty? + yield(indent + l) + end + + self + end + + def add_banner(to) # :nodoc: + unless @short or @long + s = desc.join + to << " [" + s + "]..." unless s.empty? + end + to + end + + def match_nonswitch?(str) # :nodoc: + @pattern =~ str unless @short or @long + end + + # + # Main name of the switch. + # + def switch_name + (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '') + end + + def compsys(sdone, ldone) # :nodoc: + sopts, lopts = [], [] + @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short + @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long + return if sopts.empty? and lopts.empty? # completely hidden + + (sopts+lopts).each do |opt| + # "(-x -c -r)-l[left justify]" + if /^--\[no-\](.+)$/ =~ opt + o = $1 + yield("--#{o}", desc.join("")) + yield("--no-#{o}", desc.join("")) + else + yield("#{opt}", desc.join("")) + end + end + end + + # + # Switch that takes no arguments. + # + class NoArgument < self + + # + # Raises an exception if any arguments given. + # + def parse(arg, argv) + yield(NeedlessArgument, arg) if arg + conv_arg(arg) + end + + def self.incompatible_argument_styles(*) + end + + def self.pattern + Object + end + end + + # + # Switch that takes an argument. + # + class RequiredArgument < self + + # + # Raises an exception if argument is not present. + # + def parse(arg, argv) + unless arg + raise MissingArgument if argv.empty? + arg = argv.shift + end + conv_arg(*parse_arg(arg, &method(:raise))) + end + end + + # + # Switch that can omit argument. + # + class OptionalArgument < self + + # + # Parses argument if given, or uses default value. + # + def parse(arg, argv, &error) + if arg + conv_arg(*parse_arg(arg, &error)) + else + conv_arg(arg) + end + end + end + + # + # Switch that takes an argument, which does not begin with '-'. + # + class PlacedArgument < self + + # + # Returns nil if argument is not present or begins with '-'. + # + def parse(arg, argv, &error) + if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0])) + return nil, block, nil + end + opt = (val = parse_arg(val, &error))[1] + val = conv_arg(*val) + if opt and !arg + argv.shift + else + val[0] = nil + end + val + end + end + end + + # + # Simple option list providing mapping from short and/or long option + # string to Gem::OptionParser::Switch and mapping from acceptable argument to + # matching pattern and converter pair. Also provides summary feature. + # + class List + # Map from acceptable argument types to pattern and converter pairs. + attr_reader :atype + + # Map from short style option switches to actual switch objects. + attr_reader :short + + # Map from long style option switches to actual switch objects. + attr_reader :long + + # List of all switches and summary string. + attr_reader :list + + # + # Just initializes all instance variables. + # + def initialize + @atype = {} + @short = OptionMap.new + @long = OptionMap.new + @list = [] + end + + # + # See Gem::OptionParser.accept. + # + def accept(t, pat = /.*/m, &block) + if pat + pat.respond_to?(:match) or + raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2)) + else + pat = t if t.respond_to?(:match) + end + unless block + block = pat.method(:convert).to_proc if pat.respond_to?(:convert) + end + @atype[t] = [pat, block] + end + + # + # See Gem::OptionParser.reject. + # + def reject(t) + @atype.delete(t) + end + + # + # Adds +sw+ according to +sopts+, +lopts+ and +nlopts+. + # + # +sw+:: Gem::OptionParser::Switch instance to be added. + # +sopts+:: Short style option list. + # +lopts+:: Long style option list. + # +nlopts+:: Negated long style options list. + # + def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc: + sopts.each {|o| @short[o] = sw} if sopts + lopts.each {|o| @long[o] = sw} if lopts + nlopts.each {|o| @long[o] = nsw} if nsw and nlopts + used = @short.invert.update(@long.invert) + @list.delete_if {|o| Switch === o and !used[o]} + end + private :update + + # + # Inserts +switch+ at the head of the list, and associates short, long + # and negated long options. Arguments are: + # + # +switch+:: Gem::OptionParser::Switch instance to be inserted. + # +short_opts+:: List of short style options. + # +long_opts+:: List of long style options. + # +nolong_opts+:: List of long style options with "no-" prefix. + # + # prepend(switch, short_opts, long_opts, nolong_opts) + # + def prepend(*args) + update(*args) + @list.unshift(args[0]) + end + + # + # Appends +switch+ at the tail of the list, and associates short, long + # and negated long options. Arguments are: + # + # +switch+:: Gem::OptionParser::Switch instance to be inserted. + # +short_opts+:: List of short style options. + # +long_opts+:: List of long style options. + # +nolong_opts+:: List of long style options with "no-" prefix. + # + # append(switch, short_opts, long_opts, nolong_opts) + # + def append(*args) + update(*args) + @list.push(args[0]) + end + + # + # Searches +key+ in +id+ list. The result is returned or yielded if a + # block is given. If it isn't found, nil is returned. + # + def search(id, key) + if list = __send__(id) + val = list.fetch(key) {return nil} + block_given? ? yield(val) : val + end + end + + # + # Searches list +id+ for +opt+ and the optional patterns for completion + # +pat+. If +icase+ is true, the search is case insensitive. The result + # is returned or yielded if a block is given. If it isn't found, nil is + # returned. + # + def complete(id, opt, icase = false, *pat, &block) + __send__(id).complete(opt, icase, *pat, &block) + end + + def get_candidates(id) + yield __send__(id).keys + end + + # + # Iterates over each option, passing the option to the +block+. + # + def each_option(&block) + list.each(&block) + end + + # + # Creates the summary table, passing each line to the +block+ (without + # newline). The arguments +args+ are passed along to the summarize + # method which is called on every option. + # + def summarize(*args, &block) + sum = [] + list.reverse_each do |opt| + if opt.respond_to?(:summarize) # perhaps Gem::OptionParser::Switch + s = [] + opt.summarize(*args) {|l| s << l} + sum.concat(s.reverse) + elsif !opt or opt.empty? + sum << "" + elsif opt.respond_to?(:each_line) + sum.concat([*opt.each_line].reverse) + else + sum.concat([*opt.each].reverse) + end + end + sum.reverse_each(&block) + end + + def add_banner(to) # :nodoc: + list.each do |opt| + if opt.respond_to?(:add_banner) + opt.add_banner(to) + end + end + to + end + + def compsys(*args, &block) # :nodoc: + list.each do |opt| + if opt.respond_to?(:compsys) + opt.compsys(*args, &block) + end + end + end + end + + # + # Hash with completion search feature. See Gem::OptionParser::Completion. + # + class CompletingHash < Hash + include Completion + + # + # Completion for hash key. + # + def match(key) + *values = fetch(key) { + raise AmbiguousArgument, catch(:ambiguous) {return complete(key)} + } + return key, *values + end + end + + # :stopdoc: + + # + # Enumeration of acceptable argument styles. Possible values are: + # + # NO_ARGUMENT:: The switch takes no arguments. (:NONE) + # REQUIRED_ARGUMENT:: The switch requires an argument. (:REQUIRED) + # OPTIONAL_ARGUMENT:: The switch requires an optional argument. (:OPTIONAL) + # + # Use like --switch=argument (long style) or -Xargument (short style). For + # short style, only portion matched to argument pattern is treated as + # argument. + # + ArgumentStyle = {} + NoArgument.each {|el| ArgumentStyle[el] = Switch::NoArgument} + RequiredArgument.each {|el| ArgumentStyle[el] = Switch::RequiredArgument} + OptionalArgument.each {|el| ArgumentStyle[el] = Switch::OptionalArgument} + ArgumentStyle.freeze + + # + # Switches common used such as '--', and also provides default + # argument classes + # + DefaultList = List.new + DefaultList.short['-'] = Switch::NoArgument.new {} + DefaultList.long[''] = Switch::NoArgument.new {throw :terminate} + + + COMPSYS_HEADER = <<'XXX' # :nodoc: + +typeset -A opt_args +local context state line + +_arguments -s -S \ +XXX + + 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 << " '*:file:_files' && return 0\n" + end + + # + # Default options for ARGV, which never appear in option summary. + # + Officious = {} + + # + # --help + # Shows option summary. + # + Officious['help'] = proc do |parser| + Switch::NoArgument.new do |arg| + puts parser.help + exit + end + end + + # + # --*-completion-bash=WORD + # Shows candidates for command line completion. + # + Officious['*-completion-bash'] = proc do |parser| + Switch::RequiredArgument.new do |arg| + puts parser.candidate(arg) + exit + end + end + + # + # --*-completion-zsh[=NAME:FILE] + # Creates zsh completion file. + # + Officious['*-completion-zsh'] = proc do |parser| + Switch::OptionalArgument.new do |arg| + parser.compsys(STDOUT, arg) + exit + end + end + + # + # --version + # Shows version string if Version is defined. + # + Officious['version'] = proc do |parser| + Switch::OptionalArgument.new do |pkg| + if pkg + begin + require 'rubygems/optparse/lib/optparse/version' + rescue LoadError + else + show_version(*pkg.split(/,/)) or + abort("#{parser.program_name}: no version found in package #{pkg}") + exit + end + end + v = parser.ver or abort("#{parser.program_name}: version unknown") + puts v + exit + end + end + + # :startdoc: + + # + # Class methods + # + + # + # Initializes a new instance and evaluates the optional block in context + # of the instance. Arguments +args+ are passed to #new, see there for + # description of parameters. + # + # This method is *deprecated*, its behavior corresponds to the older #new + # method. + # + def self.with(*args, &block) + opts = new(*args) + opts.instance_eval(&block) + opts + end + + # + # Returns an incremented value of +default+ according to +arg+. + # + def self.inc(arg, default = nil) + case arg + when Integer + arg.nonzero? + when nil + default.to_i + 1 + end + end + def inc(*args) + self.class.inc(*args) + end + + # + # Initializes the instance and yields itself if called with a block. + # + # +banner+:: Banner message. + # +width+:: Summary width. + # +indent+:: Summary indent. + # + def initialize(banner = nil, width = 32, indent = ' ' * 4) + @stack = [DefaultList, List.new, List.new] + @program_name = nil + @banner = banner + @summary_width = width + @summary_indent = indent + @default_argv = ARGV + @require_exact = false + add_officious + yield self if block_given? + end + + def add_officious # :nodoc: + list = base() + Officious.each do |opt, block| + list.long[opt] ||= block.call(self) + end + end + + # + # Terminates option parsing. Optional parameter +arg+ is a string pushed + # back to be the first non-option argument. + # + def terminate(arg = nil) + self.class.terminate(arg) + end + def self.terminate(arg = nil) + throw :terminate, arg + end + + @stack = [DefaultList] + def self.top() DefaultList end + + # + # Directs to accept specified class +t+. The argument string is passed to + # the block in which it should be converted to the desired class. + # + # +t+:: Argument class specifier, any object including Class. + # +pat+:: Pattern for argument, defaults to +t+ if it responds to match. + # + # accept(t, pat, &block) + # + def accept(*args, &blk) top.accept(*args, &blk) end + # + # See #accept. + # + def self.accept(*args, &blk) top.accept(*args, &blk) end + + # + # Directs to reject specified class argument. + # + # +t+:: Argument class specifier, any object including Class. + # + # reject(t) + # + def reject(*args, &blk) top.reject(*args, &blk) end + # + # See #reject. + # + def self.reject(*args, &blk) top.reject(*args, &blk) end + + # + # Instance methods + # + + # Heading banner preceding summary. + attr_writer :banner + + # Program name to be emitted in error message and default banner, + # defaults to $0. + attr_writer :program_name + + # Width for option list portion of summary. Must be Numeric. + attr_accessor :summary_width + + # Indentation for summary. Must be String (or have + String method). + attr_accessor :summary_indent + + # Strings to be parsed in default. + attr_accessor :default_argv + + # Whether to require that options match exactly (disallows providing + # abbreviated long option as short option). + attr_accessor :require_exact + + # + # Heading banner preceding summary. + # + def banner + unless @banner + @banner = +"Usage: #{program_name} [options]" + visit(:add_banner, @banner) + end + @banner + end + + # + # Program name to be emitted in error message and default banner, defaults + # to $0. + # + def program_name + @program_name || File.basename($0, '.*') + end + + # for experimental cascading :-) + alias set_banner banner= + alias set_program_name program_name= + alias set_summary_width summary_width= + alias set_summary_indent summary_indent= + + # Version + attr_writer :version + # Release code + attr_writer :release + + # + # Version + # + def version + (defined?(@version) && @version) || (defined?(::Version) && ::Version) + end + + # + # Release code + # + def release + (defined?(@release) && @release) || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE) + end + + # + # Returns version string from program_name, version and release. + # + def ver + if v = version + str = +"#{program_name} #{[v].join('.')}" + str << " (#{v})" if v = release + str + end + end + + def warn(mesg = $!) + super("#{program_name}: #{mesg}") + end + + def abort(mesg = $!) + super("#{program_name}: #{mesg}") + end + + # + # Subject of #on / #on_head, #accept / #reject + # + def top + @stack[-1] + end + + # + # Subject of #on_tail. + # + def base + @stack[1] + end + + # + # Pushes a new List. + # + def new + @stack.push(List.new) + if block_given? + yield self + else + self + end + end + + # + # Removes the last List. + # + def remove + @stack.pop + end + + # + # Puts option summary into +to+ and returns +to+. Yields each line if + # a block is given. + # + # +to+:: Output destination, which must have method <<. Defaults to []. + # +width+:: Width of left side, defaults to @summary_width. + # +max+:: Maximum length allowed for left side, defaults to +width+ - 1. + # +indent+:: Indentation, defaults to @summary_indent. + # + def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk) + nl = "\n" + blk ||= proc {|l| to << (l.index(nl, -1) ? l : l + nl)} + visit(:summarize, {}, {}, width, max, indent, &blk) + to + end + + # + # Returns option summary string. + # + def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end + alias to_s help + + # + # Returns option summary list. + # + def to_a; summarize("#{banner}".split(/^/)) end + + # + # Checks if an argument is given twice, in which case an ArgumentError is + # raised. Called from Gem::OptionParser#switch only. + # + # +obj+:: New argument. + # +prv+:: Previously specified argument. + # +msg+:: Exception message. + # + def notwice(obj, prv, msg) # :nodoc: + unless !prv or prv == obj + raise(ArgumentError, "argument #{msg} given twice: #{obj}", + ParseError.filter_backtrace(caller(2))) + end + obj + end + private :notwice + + SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc: + + # :call-seq: + # make_switch(params, block = nil) + # + # :include: ../doc/optparse/creates_option.rdoc + # + def make_switch(opts, block = nil) + short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], [] + ldesc, sdesc, desc, arg = [], [], [] + default_style = Switch::NoArgument + default_pattern = nil + klass = nil + q, a = nil + has_arg = false + + opts.each do |o| + # argument class + next if search(:atype, o) do |pat, c| + klass = notwice(o, klass, 'type') + if not_style and not_style != Switch::NoArgument + not_pattern, not_conv = pat, c + else + default_pattern, conv = pat, c + end + end + + # directly specified pattern(any object possible to match) + if (!(String === o || Symbol === o)) and o.respond_to?(:match) + pattern = notwice(o, pattern, 'pattern') + if pattern.respond_to?(:convert) + conv = pattern.method(:convert).to_proc + else + conv = SPLAT_PROC + end + next + end + + # anything others + case o + when Proc, Method + block = notwice(o, block, 'block') + when Array, Hash + case pattern + when CompletingHash + when nil + pattern = CompletingHash.new + conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert) + else + raise ArgumentError, "argument pattern given twice" + end + o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}} + 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]*)(.+)?/ + q, a = $1, $2 + o = notwice(a ? Object : TrueClass, klass, 'type') + not_pattern, not_conv = search(:atype, o) unless not_style + not_style = (not_style || default_style).guess(arg = a) if a + default_style = Switch::NoArgument + default_pattern, conv = search(:atype, FalseClass) unless default_pattern + ldesc << "--no-#{q}" + (q = q.downcase).tr!('_', '-') + long << "no-#{q}" + nolong << q + when /^--\[no-\]([^\[\]=\s]*)(.+)?/ + q, a = $1, $2 + o = notwice(a ? Object : TrueClass, klass, 'type') + if a + default_style = default_style.guess(arg = a) + default_pattern, conv = search(:atype, o) unless default_pattern + end + ldesc << "--[no-]#{q}" + (o = q.downcase).tr!('_', '-') + long << o + not_pattern, not_conv = search(:atype, FalseClass) unless not_style + not_style = Switch::NoArgument + nolong << "no-#{o}" + when /^--([^\[\]=\s]*)(.+)?/ + q, a = $1, $2 + if a + o = notwice(NilClass, klass, 'type') + default_style = default_style.guess(arg = a) + default_pattern, conv = search(:atype, o) unless default_pattern + end + ldesc << "--#{q}" + (o = q.downcase).tr!('_', '-') + long << o + when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ + q, a = $1, $2 + o = notwice(Object, klass, 'type') + if a + default_style = default_style.guess(arg = a) + default_pattern, conv = search(:atype, o) unless default_pattern + else + has_arg = true + end + sdesc << "-#{q}" + short << Regexp.new(q) + when /^-(.)(.+)?/ + q, a = $1, $2 + if a + o = notwice(NilClass, klass, 'type') + default_style = default_style.guess(arg = a) + default_pattern, conv = search(:atype, o) unless default_pattern + end + sdesc << "-#{q}" + short << q + when /^=/ + style = notwice(default_style.guess(arg = o), style, 'style') + default_pattern, conv = search(:atype, Object) unless default_pattern + else + desc.push(o) + end + end + + default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern + 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) + elsif !block + if style or pattern + raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller) + end + s = desc + else + short << pattern + s = (style || default_style).new(pattern, + conv, nil, nil, arg, desc, block) + end + return s, short, long, + (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style), + nolong + end + + # :call-seq: + # define(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + def define(*opts, &block) + top.append(*(sw = make_switch(opts, block))) + sw[0] + end + + # :call-seq: + # on(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + def on(*opts, &block) + define(*opts, &block) + self + end + alias def_option define + + # :call-seq: + # define_head(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + def define_head(*opts, &block) + top.prepend(*(sw = make_switch(opts, block))) + sw[0] + end + + # :call-seq: + # on_head(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + # The new option is added at the head of the summary. + # + def on_head(*opts, &block) + define_head(*opts, &block) + self + end + alias def_head_option define_head + + # :call-seq: + # define_tail(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + def define_tail(*opts, &block) + base.append(*(sw = make_switch(opts, block))) + sw[0] + end + + # + # :call-seq: + # on_tail(*params, &block) + # + # :include: ../doc/optparse/creates_option.rdoc + # + # The new option is added at the tail of the summary. + # + def on_tail(*opts, &block) + define_tail(*opts, &block) + self + end + alias def_tail_option define_tail + + # + # Add separator in summary. + # + def separator(string) + top.append(string, nil, nil) + end + + # + # Parses command line arguments +argv+ in order. When a block is given, + # each non-option argument is yielded. When optional +into+ keyword + # argument is provided, the parsed option values are stored there via + # []= method (so it can be Hash, or OpenStruct, or other + # similar object). + # + # Returns the rest of +argv+ left unparsed. + # + def order(*argv, into: nil, &nonopt) + argv = argv[0].dup if argv.size == 1 and Array === argv[0] + order!(argv, into: into, &nonopt) + end + + # + # Same as #order, but removes switches destructively. + # Non-option arguments remain in +argv+. + # + def order!(argv = default_argv, into: nil, &nonopt) + setter = ->(name, val) {into[name.to_sym] = val} if into + parse_in_order(argv, setter, &nonopt) + end + + def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: + opt, arg, val, rest = nil + nonopt ||= proc {|a| throw :terminate, a} + argv.unshift(arg) if arg = catch(:terminate) { + while arg = argv.shift + case arg + # long option + when /\A--([^=]*)(?:=(.*))?/m + opt, rest = $1, $2 + opt.tr!('_', '-') + begin + sw, = complete(:long, opt, true) + if require_exact && !sw.long.include?(arg) + raise InvalidOption, arg + end + rescue ParseError + raise $!.set_option(arg, true) + 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 + rescue ParseError + raise $!.set_option(arg, rest) + end + + # short option + when /\A-(.)((=).*|.+)?/m + eq, rest, opt = $3, $2, $1 + has_arg, val = eq, rest + begin + sw, = search(:short, opt) + unless sw + begin + sw, = complete(:short, opt) + # short option matched. + val = arg.delete_prefix('-') + has_arg = true + rescue InvalidOption + raise if require_exact + # if no short options match, try completion with long + # options. + sw, = complete(:long, opt) + eq ||= !rest + end + end + rescue ParseError + raise $!.set_option(arg, true) + end + begin + opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq} + rescue ParseError + raise $!.set_option(arg, arg.length > 2) + else + raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}" + 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 + rescue ParseError + raise $!.set_option(arg, arg.length > 2) + end + + # non-option argument + else + catch(:prune) do + visit(:each_option) do |sw0| + sw = sw0 + sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg) + end + nonopt.call(arg) + end + end + end + + nil + } + + visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern} + + argv + end + private :parse_in_order + + # + # Parses command line arguments +argv+ in permutation mode and returns + # list of non-option arguments. When optional +into+ keyword + # argument is provided, the parsed option values are stored there via + # []= method (so it can be Hash, or OpenStruct, or other + # similar object). + # + def permute(*argv, into: nil) + argv = argv[0].dup if argv.size == 1 and Array === argv[0] + permute!(argv, into: into) + end + + # + # Same as #permute, but removes switches destructively. + # Non-option arguments remain in +argv+. + # + def permute!(argv = default_argv, into: nil) + nonopts = [] + order!(argv, into: into, &nonopts.method(:<<)) + argv[0, 0] = nonopts + argv + end + + # + # Parses command line arguments +argv+ in order when environment variable + # POSIXLY_CORRECT is set, and in permutation mode otherwise. + # When optional +into+ keyword argument is provided, the parsed option + # values are stored there via []= method (so it can be Hash, + # or OpenStruct, or other similar object). + # + def parse(*argv, into: nil) + argv = argv[0].dup if argv.size == 1 and Array === argv[0] + parse!(argv, into: into) + end + + # + # Same as #parse, but removes switches destructively. + # Non-option arguments remain in +argv+. + # + def parse!(argv = default_argv, into: nil) + if ENV.include?('POSIXLY_CORRECT') + order!(argv, into: into) + else + permute!(argv, into: into) + end + end + + # + # Wrapper method for getopts.rb. + # + # params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option") + # # params["a"] = true # -a + # # params["b"] = "1" # -b1 + # # params["foo"] = "1" # --foo + # # params["bar"] = "x" # --bar x + # # params["zot"] = "z" # --zot Z + # + def getopts(*args) + argv = Array === args.first ? args.shift : default_argv + single_options, *long_options = *args + + result = {} + + single_options.scan(/(.)(:)?/) do |opt, val| + if val + result[opt] = nil + define("-#{opt} VAL") + else + result[opt] = false + define("-#{opt}") + end + end if single_options + + long_options.each do |arg| + arg, desc = arg.split(';', 2) + opt, val = arg.split(':', 2) + if val + result[opt] = val.empty? ? nil : val + define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact) + else + result[opt] = false + define("--#{opt}", *[desc].compact) + end + end + + parse_in_order(argv, result.method(:[]=)) + result + end + + # + # See #getopts. + # + def self.getopts(*args) + new.getopts(*args) + end + + # + # Traverses @stack, sending each element method +id+ with +args+ and + # +block+. + # + def visit(id, *args, &block) # :nodoc: + @stack.reverse_each do |el| + el.__send__(id, *args, &block) + end + nil + end + private :visit + + # + # Searches +key+ in @stack for +id+ hash and returns or yields the result. + # + def search(id, key) # :nodoc: + block_given = block_given? + visit(:search, id, key) do |k| + return block_given ? yield(k) : k + end + end + private :search + + # + # Completes shortened long style option switch and returns pair of + # canonical switch and switch descriptor Gem::OptionParser::Switch. + # + # +typ+:: Searching table. + # +opt+:: Searching key. + # +icase+:: Search case insensitive if true. + # +pat+:: Optional pattern for completion. + # + def complete(typ, opt, icase = false, *pat) # :nodoc: + if pat.empty? + search(typ, opt) {|sw| return [sw, opt]} # exact match or... + end + ambiguous = catch(:ambiguous) { + visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw} + } + exc = ambiguous ? AmbiguousOption : InvalidOption + raise exc.new(opt, additional: self.method(:additional_message).curry[typ]) + end + private :complete + + # + # Returns additional info. + # + def additional_message(typ, opt) + return unless typ and opt and defined?(DidYouMean::SpellChecker) + all_candidates = [] + visit(:get_candidates, typ) do |candidates| + all_candidates.concat(candidates) + end + all_candidates.select! {|cand| cand.is_a?(String) } + checker = DidYouMean::SpellChecker.new(dictionary: all_candidates) + suggestions = all_candidates & checker.correct(opt) + if DidYouMean.respond_to?(:formatter) + DidYouMean.formatter.message_for(suggestions) + else + "\nDid you mean? #{suggestions.join("\n ")}" + end + end + + def candidate(word) + list = [] + case word + when '-' + long = short = true + when /\A--/ + word, arg = word.split(/=/, 2) + argpat = Completion.regexp(arg, false) if arg and !arg.empty? + long = true + when /\A-/ + short = true + end + pat = Completion.regexp(word, long) + visit(:each_option) do |opt| + next unless Switch === opt + opts = (long ? opt.long : []) + (short ? opt.short : []) + opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat + if /\A=/ =~ opt.arg + opts.map! {|sw| sw + "="} + if arg and CompletingHash === opt.pattern + if opts = opt.pattern.candidate(arg, false, argpat) + opts.map!(&:last) + end + end + end + list.concat(opts) + end + list + end + + # + # Loads options from file names as +filename+. Does nothing when the file + # is not present. Returns whether successfully loaded. + # + # +filename+ defaults to basename of the program without suffix in a + # directory ~/.options, then the basename with '.options' suffix + # under XDG and Haiku standard places. + # + def load(filename = nil) + unless filename + basename = File.basename($0, '.*') + return true if load(File.expand_path(basename, '~/.options')) rescue nil + basename << ".options" + return [ + # XDG + ENV['XDG_CONFIG_HOME'], + '~/.config', + *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR), + + # Haiku + '~/config/settings', + ].any? {|dir| + next if !dir or dir.empty? + load(File.expand_path(basename, dir)) rescue nil + } + end + begin + parse(*IO.readlines(filename).each {|s| s.chomp!}) + true + rescue Errno::ENOENT, Errno::ENOTDIR + false + end + end + + # + # Parses environment variable +env+ or its uppercase with splitting like a + # shell. + # + # +env+ defaults to the basename of the program. + # + def environment(env = File.basename($0, '.*')) + env = ENV[env] || ENV[env.upcase] or return + require 'shellwords' + parse(*Shellwords.shellwords(env)) + end + + # + # Acceptable argument classes + # + + # + # Any string and no conversion. This is fall-back. + # + accept(Object) {|s,|s or s.nil?} + + accept(NilClass) {|s,|s} + + # + # Any non-empty string, and no conversion. + # + accept(String, /.+/m) {|s,*|s} + + # + # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal + # for 0x, and decimal for others; with optional sign prefix. Converts to + # Integer. + # + decimal = '\d+(?:_\d+)*' + binary = 'b[01]+(?:_[01]+)*' + hex = 'x[\da-f]+(?:_[\da-f]+)*' + octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?" + integer = "#{octal}|#{decimal}" + + accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,| + begin + Integer(s) + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end if s + } + + # + # Float number format, and converts to Float. + # + float = "(?:#{decimal}(?=(.)?)(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?" + floatpat = %r"\A[-+]?#{float}\z"io + accept(Float, floatpat) {|s,| s.to_f if s} + + # + # Generic numeric format, converts to Integer for integer format, Float + # for float format, and Rational for rational format. + # + real = "[-+]?(?:#{octal}|#{float})" + accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, f, n,| + if n + Rational(d, n) + elsif f + Float(s) + else + Integer(s) + end + } + + # + # Decimal integer format, to be converted to Integer. + # + DecimalInteger = /\A[-+]?#{decimal}\z/io + accept(DecimalInteger, DecimalInteger) {|s,| + begin + Integer(s, 10) + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end if s + } + + # + # Ruby/C like octal/hexadecimal/binary integer format, to be converted to + # Integer. + # + OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io + accept(OctalInteger, OctalInteger) {|s,| + begin + Integer(s, 8) + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end if s + } + + # + # Decimal integer/float number format, to be converted to Integer for + # integer format, Float for float format. + # + DecimalNumeric = floatpat # decimal integer is allowed as float also. + accept(DecimalNumeric, floatpat) {|s, f| + begin + if f + Float(s) + else + Integer(s) + end + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end if s + } + + # + # Boolean switch, which means whether it is present or not, whether it is + # absent or not with prefix no-, or it takes an argument + # yes/no/true/false/+/-. + # + yesno = CompletingHash.new + %w[- no false].each {|el| yesno[el] = false} + %w[+ yes true].each {|el| yesno[el] = true} + yesno['nil'] = false # should be nil? + accept(TrueClass, yesno) {|arg, val| val == nil or val} + # + # Similar to TrueClass, but defaults to false. + # + accept(FalseClass, yesno) {|arg, val| val != nil and val} + + # + # List of strings separated by ",". + # + accept(Array) do |s, | + if s + s = s.split(',').collect {|ss| ss unless ss.empty?} + end + s + end + + # + # Regular expression with options. + # + accept(Regexp, %r"\A/((?:\\.|[^\\])*)/([[:alpha:]]+)?\z|.*") do |all, s, o| + f = 0 + if o + f |= Regexp::IGNORECASE if /i/ =~ o + f |= Regexp::MULTILINE if /m/ =~ o + f |= Regexp::EXTENDED if /x/ =~ o + k = o.delete("imx") + k = nil if k.empty? + end + Regexp.new(s || all, f, k) + end + + # + # Exceptions + # + + # + # Base class of exceptions from Gem::OptionParser. + # + class ParseError < RuntimeError + # Reason which caused the error. + Reason = 'parse error' + + def initialize(*args, additional: nil) + @additional = additional + @arg0, = args + @args = args + @reason = nil + end + + attr_reader :args + attr_writer :reason + attr_accessor :additional + + # + # Pushes back erred argument(s) to +argv+. + # + def recover(argv) + argv[0, 0] = @args + argv + end + + def self.filter_backtrace(array) + unless $DEBUG + array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~)) + end + array + end + + def set_backtrace(array) + super(self.class.filter_backtrace(array)) + end + + def set_option(opt, eq) + if eq + @args[0] = opt + else + @args.unshift(opt) + end + self + end + + # + # Returns error reason. Override this for I18N. + # + def reason + @reason || self.class::Reason + end + + def inspect + "#<#{self.class}: #{args.join(' ')}>" + end + + # + # Default stringizing method to emit standard error message. + # + def message + "#{reason}: #{args.join(' ')}#{additional[@arg0] if additional}" + end + + alias to_s message + end + + # + # Raises when ambiguously completable string is encountered. + # + class AmbiguousOption < ParseError + const_set(:Reason, 'ambiguous option') + end + + # + # Raises when there is an argument for a switch which takes no argument. + # + class NeedlessArgument < ParseError + const_set(:Reason, 'needless argument') + end + + # + # Raises when a switch with mandatory argument has no argument. + # + class MissingArgument < ParseError + const_set(:Reason, 'missing argument') + end + + # + # Raises when switch is undefined. + # + class InvalidOption < ParseError + const_set(:Reason, 'invalid option') + end + + # + # Raises when the given argument does not match required format. + # + class InvalidArgument < ParseError + const_set(:Reason, 'invalid argument') + end + + # + # Raises when the given argument word can't be completed uniquely. + # + class AmbiguousArgument < InvalidArgument + const_set(:Reason, 'ambiguous argument') + end + + # + # Miscellaneous + # + + # + # Extends command line arguments array (ARGV) to parse itself. + # + module Arguable + + # + # Sets Gem::OptionParser object, when +opt+ is +false+ or +nil+, methods + # Gem::OptionParser::Arguable#options and Gem::OptionParser::Arguable#options= are + # undefined. Thus, there is no ways to access the Gem::OptionParser object + # via the receiver object. + # + def options=(opt) + unless @optparse = opt + class << self + undef_method(:options) + undef_method(:options=) + end + end + end + + # + # Actual Gem::OptionParser object, automatically created if nonexistent. + # + # If called with a block, yields the Gem::OptionParser object and returns the + # result of the block. If an Gem::OptionParser::ParseError exception occurs + # in the block, it is rescued, a error message printed to STDERR and + # +nil+ returned. + # + def options + @optparse ||= Gem::OptionParser.new + @optparse.default_argv = self + block_given? or return @optparse + begin + yield @optparse + rescue ParseError + @optparse.warn $! + nil + end + end + + # + # Parses +self+ destructively in order and returns +self+ containing the + # rest arguments left unparsed. + # + def order!(&blk) options.order!(self, &blk) end + + # + # Parses +self+ destructively in permutation mode and returns +self+ + # containing the rest arguments left unparsed. + # + def permute!() options.permute!(self) end + + # + # Parses +self+ destructively and returns +self+ containing the + # rest arguments left unparsed. + # + def parse!() options.parse!(self) end + + # + # Substitution of getopts is possible as follows. Also see + # Gem::OptionParser#getopts. + # + # def getopts(*args) + # ($OPT = ARGV.getopts(*args)).each do |opt, val| + # eval "$OPT_#{opt.gsub(/[^A-Za-z0-9_]/, '_')} = val" + # end + # rescue Gem::OptionParser::ParseError + # end + # + def getopts(*args) + options.getopts(self, *args) + end + + # + # Initializes instance variable. + # + def self.extend_object(obj) + super + obj.instance_eval {@optparse = nil} + end + def initialize(*args) + super + @optparse = nil + end + end + + # + # Acceptable argument classes. Now contains DecimalInteger, OctalInteger + # and DecimalNumeric. See Acceptable argument classes (in source code). + # + module Acceptables + const_set(:DecimalInteger, Gem::OptionParser::DecimalInteger) + const_set(:OctalInteger, Gem::OptionParser::OctalInteger) + const_set(:DecimalNumeric, Gem::OptionParser::DecimalNumeric) + end +end + +# ARGV is arguable by Gem::OptionParser +ARGV.extend(Gem::OptionParser::Arguable) diff --git a/ruby/lib/rubygems/optparse/lib/optparse/ac.rb b/ruby/lib/rubygems/optparse/lib/optparse/ac.rb new file mode 100644 index 000000000..ff2f4c2dc --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/ac.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: false +require 'rubygems/optparse/lib/optparse' + +class Gem::OptionParser::AC < Gem::OptionParser + private + + def _check_ac_args(name, block) + unless /\A\w[-\w]*\z/ =~ name + raise ArgumentError, name + end + unless block + raise ArgumentError, "no block given", ParseError.filter_backtrace(caller) + end + end + + ARG_CONV = proc {|val| val.nil? ? true : val} + + def _ac_arg_enable(prefix, name, help_string, block) + _check_ac_args(name, block) + + sdesc = [] + ldesc = ["--#{prefix}-#{name}"] + desc = [help_string] + q = name.downcase + ac_block = proc {|val| block.call(ARG_CONV.call(val))} + enable = Switch::PlacedArgument.new(nil, ARG_CONV, sdesc, ldesc, nil, desc, ac_block) + disable = Switch::NoArgument.new(nil, proc {false}, sdesc, ldesc, nil, desc, ac_block) + top.append(enable, [], ["enable-" + q], disable, ['disable-' + q]) + enable + end + + public + + def ac_arg_enable(name, help_string, &block) + _ac_arg_enable("enable", name, help_string, block) + end + + def ac_arg_disable(name, help_string, &block) + _ac_arg_enable("disable", name, help_string, block) + end + + def ac_arg_with(name, help_string, &block) + _check_ac_args(name, block) + + sdesc = [] + ldesc = ["--with-#{name}"] + desc = [help_string] + q = name.downcase + with = Switch::PlacedArgument.new(*search(:atype, String), sdesc, ldesc, nil, desc, block) + without = Switch::NoArgument.new(nil, proc {}, sdesc, ldesc, nil, desc, block) + top.append(with, [], ["with-" + q], without, ['without-' + q]) + with + end +end diff --git a/ruby/lib/rubygems/optparse/lib/optparse/date.rb b/ruby/lib/rubygems/optparse/lib/optparse/date.rb new file mode 100644 index 000000000..11131e92c --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/date.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: false +require 'rubygems/optparse/lib/optparse' +require 'date' + +Gem::OptionParser.accept(DateTime) do |s,| + begin + DateTime.parse(s) if s + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end +end +Gem::OptionParser.accept(Date) do |s,| + begin + Date.parse(s) if s + rescue ArgumentError + raise Gem::OptionParser::InvalidArgument, s + end +end diff --git a/ruby/lib/rubygems/optparse/lib/optparse/kwargs.rb b/ruby/lib/rubygems/optparse/lib/optparse/kwargs.rb new file mode 100644 index 000000000..9290344c3 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/kwargs.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +require 'rubygems/optparse/lib/optparse' + +class Gem::OptionParser + # :call-seq: + # define_by_keywords(options, method, **params) + # + # :include: ../../doc/optparse/creates_option.rdoc + # + def define_by_keywords(options, meth, **opts) + meth.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| + options[name] = o + end + end + end + options + end +end diff --git a/ruby/lib/rubygems/optparse/lib/optparse/shellwords.rb b/ruby/lib/rubygems/optparse/lib/optparse/shellwords.rb new file mode 100644 index 000000000..60dd91990 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/shellwords.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: false +# -*- ruby -*- + +require 'shellwords' +require 'rubygems/optparse/lib/optparse' + +Gem::OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)} diff --git a/ruby/lib/rubygems/optparse/lib/optparse/time.rb b/ruby/lib/rubygems/optparse/lib/optparse/time.rb new file mode 100644 index 000000000..cb19f6e99 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/time.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: false +require 'rubygems/optparse/lib/optparse' +require 'time' + +Gem::OptionParser.accept(Time) do |s,| + begin + (Time.httpdate(s) rescue Time.parse(s)) if s + rescue + raise Gem::OptionParser::InvalidArgument, s + end +end diff --git a/ruby/lib/rubygems/optparse/lib/optparse/uri.rb b/ruby/lib/rubygems/optparse/lib/optparse/uri.rb new file mode 100644 index 000000000..088f30999 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/uri.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: false +# -*- ruby -*- + +require 'rubygems/optparse/lib/optparse' +require 'uri' + +Gem::OptionParser.accept(URI) {|s,| URI.parse(s) if s} diff --git a/ruby/lib/rubygems/optparse/lib/optparse/version.rb b/ruby/lib/rubygems/optparse/lib/optparse/version.rb new file mode 100644 index 000000000..5d79e9db4 --- /dev/null +++ b/ruby/lib/rubygems/optparse/lib/optparse/version.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: false +# Gem::OptionParser internal utility + +class << Gem::OptionParser + def show_version(*pkgs) + progname = ARGV.options.program_name + result = false + show = proc do |klass, cname, version| + str = "#{progname}" + unless klass == ::Object and cname == :VERSION + version = version.join(".") if Array === version + str << ": #{klass}" unless klass == Object + str << " version #{version}" + end + [:Release, :RELEASE].find do |rel| + if klass.const_defined?(rel) + str << " (#{klass.const_get(rel)})" + end + end + puts str + result = true + end + if pkgs.size == 1 and pkgs[0] == "all" + self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version| + unless cname[1] == ?e and klass.const_defined?(:Version) + show.call(klass, cname.intern, version) + end + end + else + pkgs.each do |pkg| + begin + pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)} + v = case + when pkg.const_defined?(:Version) + pkg.const_get(n = :Version) + when pkg.const_defined?(:VERSION) + pkg.const_get(n = :VERSION) + else + n = nil + "unknown" + end + show.call(pkg, n, v) + rescue NameError + end + end + end + result + end + + def each_const(path, base = ::Object) + path.split(/::|\//).inject(base) do |klass, name| + raise NameError, path unless Module === klass + klass.constants.grep(/#{name}/i) do |c| + klass.const_defined?(c) or next + klass.const_get(c) + end + end + end + + def search_const(klass, name) + klasses = [klass] + while klass = klasses.shift + klass.constants.each do |cname| + klass.const_defined?(cname) or next + const = klass.const_get(cname) + yield klass, cname, const if name === cname + klasses << const if Module === const and const != ::Object + end + end + end +end diff --git a/ruby/lib/rubygems/package.rb b/ruby/lib/rubygems/package.rb index 813ab9da3..a81c5f307 100644 --- a/ruby/lib/rubygems/package.rb +++ b/ruby/lib/rubygems/package.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: true #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier @@ -8,7 +7,8 @@ # Example using a Gem::Package # # Builds a .gem file given a Gem::Specification. A .gem file is a tarball -# which contains a data.tar.gz and metadata.gz, and possibly signatures. +# which contains a data.tar.gz, metadata.gz, checksums.yaml.gz and possibly +# signatures. # # require 'rubygems' # require 'rubygems/package' @@ -41,19 +41,16 @@ # #files are the files in the .gem tar file, not the Ruby files in the gem # #extract_files and #contents automatically call #verify -require 'rubygems/security' -require 'rubygems/specification' -require 'rubygems/user_interaction' -require 'zlib' +require_relative "../rubygems" +require_relative 'security' +require_relative 'user_interaction' class Gem::Package - include Gem::UserInteraction class Error < Gem::Exception; end class FormatError < Error - attr_reader :path def initialize(message, source = nil) @@ -65,16 +62,20 @@ def initialize(message, source = nil) super message end - end class PathError < Error - def initialize(destination, destination_dir) super "installing into parent path %s of %s is not allowed" % [destination, destination_dir] end + end + class SymlinkError < Error + def initialize(name, destination, destination_dir) + super "installing symlink '%s' pointing to parent path %s of %s is not allowed" % + [name, destination, destination_dir] + end end class NonSeekableIO < Error; end @@ -145,12 +146,12 @@ def self.build(spec, skip_validation = false, strict_validation = false, file_na def self.new(gem, security_policy = nil) gem = if gem.is_a?(Gem::Package::Source) - gem - elsif gem.respond_to? :read - Gem::Package::IOSource.new gem - else - Gem::Package::FileSource.new gem - end + gem + elsif gem.respond_to? :read + Gem::Package::IOSource.new gem + else + Gem::Package::FileSource.new gem + end return super unless Gem::Package == self return super unless gem.present? @@ -191,12 +192,14 @@ def self.raw_spec(path, security_policy = nil) # Creates a new package that will read or write to the file +gem+. def initialize(gem, security_policy) # :notnew: + require 'zlib' + @gem = gem @build_time = Gem.source_date_epoch @checksums = {} @contents = nil - @digests = Hash.new { |h, algorithm| h[algorithm] = {} } + @digests = Hash.new {|h, algorithm| h[algorithm] = {} } @files = nil @security_policy = security_policy @signatures = {} @@ -217,7 +220,7 @@ def copy_to(path) def add_checksums(tar) Gem.load_yaml - checksums_by_algorithm = Hash.new { |h, algorithm| h[algorithm] = {} } + checksums_by_algorithm = Hash.new {|h, algorithm| h[algorithm] = {} } @checksums.each do |name, digests| digests.each do |algorithm, digest| @@ -227,7 +230,7 @@ def add_checksums(tar) tar.add_file_signed 'checksums.yaml.gz', 0444, @signer do |io| gzip_to io do |gz_io| - YAML.dump checksums_by_algorithm, gz_io + Psych.dump checksums_by_algorithm, gz_io end end end @@ -256,14 +259,7 @@ def add_files(tar) # :nodoc: stat = File.lstat file if stat.symlink? - target_path = File.readlink(file) - - unless target_path.start_with? '.' - relative_dir = File.dirname(file).sub("#{Dir.pwd}/", '') - target_path = File.join(relative_dir, target_path) - end - - tar.add_symlink file, target_path, stat.mode + tar.add_symlink file, File.readlink(file), stat.mode end next unless stat.file? @@ -302,7 +298,7 @@ def build(skip_validation = false, strict_validation = false) setup_signer( signer_options: { - expiration_length_days: Gem.configuration.cert_expiration_length_days + expiration_length_days: Gem.configuration.cert_expiration_length_days, } ) @@ -357,18 +353,13 @@ def contents def digest(entry) # :nodoc: algorithms = if @checksums - @checksums.keys - else - [Gem::Security::DIGEST_NAME].compact - end + @checksums.keys + else + [Gem::Security::DIGEST_NAME].compact + end algorithms.each do |algorithm| - digester = - if defined?(OpenSSL::Digest) - OpenSSL::Digest.new algorithm - else - Digest.const_get(algorithm).new - end + digester = Gem::Security.create_digest(algorithm) digester << entry.read(16384) until entry.eof? @@ -416,13 +407,21 @@ def extract_files(destination_dir, pattern = "*") # extracted. def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: - directories = [] if dir_mode + directories = [] open_tar_gz io do |tar| tar.each do |entry| next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH destination = install_location entry.full_name, destination_dir + if entry.symlink? + link_target = entry.header.linkname + real_destination = link_target.start_with?("/") ? link_target : File.expand_path(link_target, File.dirname(destination)) + + raise Gem::Package::SymlinkError.new(entry.full_name, real_destination, destination_dir) unless + normalize_path(real_destination).start_with? normalize_path(destination_dir + '/') + end + FileUtils.rm_rf destination mkdir_options = {} @@ -433,9 +432,11 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: else File.dirname destination end - directories << mkdir if directories - mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name + unless directories.include?(mkdir) + FileUtils.mkdir_p mkdir, **mkdir_options + directories << mkdir + end File.open destination, 'wb' do |out| out.write entry.read @@ -448,8 +449,7 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: end end - if directories - directories.uniq! + if dir_mode File.chmod(dir_mode, *directories) end end @@ -482,21 +482,11 @@ def install_location(filename, destination_dir) # :nodoc: raise Gem::Package::PathError.new(filename, destination_dir) if filename.start_with? '/' - destination_dir = File.expand_path(File.realpath(destination_dir)) - destination = File.expand_path(File.join(destination_dir, filename)) + destination_dir = File.realpath(destination_dir) + destination = File.expand_path(filename, destination_dir) raise Gem::Package::PathError.new(destination, destination_dir) unless - destination.start_with? destination_dir + '/' - - begin - real_destination = File.expand_path(File.realpath(destination)) - rescue - # it's fine if the destination doesn't exist, because rm -rf'ing it can't cause any damage - nil - else - raise Gem::Package::PathError.new(real_destination, destination_dir) unless - real_destination.start_with? destination_dir + '/' - end + normalize_path(destination).start_with? normalize_path(destination_dir + '/') destination.tap(&Gem::UNTAINT) destination @@ -510,22 +500,6 @@ def normalize_path(pathname) end end - def mkdir_p_safe(mkdir, mkdir_options, destination_dir, file_name) - destination_dir = File.realpath(File.expand_path(destination_dir)) - parts = mkdir.split(File::SEPARATOR) - parts.reduce do |path, basename| - path = File.realpath(path) unless path == "" - path = File.expand_path(path + File::SEPARATOR + basename) - lstat = File.lstat path rescue nil - if !lstat || !lstat.directory? - unless normalize_path(path).start_with? normalize_path(destination_dir) and (FileUtils.mkdir path, **mkdir_options rescue false) - raise Gem::Package::PathError.new(file_name, destination_dir) - end - end - path - end - end - ## # Loads a Gem::Specification from the TarEntry +entry+ @@ -580,10 +554,10 @@ def setup_signer(signer_options: {}) ) @spec.signing_key = nil - @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s } + @spec.cert_chain = @signer.cert_chain.map {|cert| cert.to_s } else @signer = Gem::Security::Signer.new nil, nil, passphrase - @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if + @spec.cert_chain = @signer.cert_chain.map {|cert| cert.to_pem } if @signer.cert_chain end end @@ -679,10 +653,9 @@ def verify_entry(entry) when 'data.tar.gz' then verify_gz entry end - rescue => e - message = "package is corrupt, exception while verifying: " + - "#{e.message} (#{e.class})" - raise Gem::Package::FormatError.new message, @gem + rescue + warn "Exception while verifying #{@gem.path}" + raise end ## @@ -717,15 +690,14 @@ def verify_gz(entry) # :nodoc: rescue Zlib::GzipFile::Error => e raise Gem::Package::FormatError.new(e.message, entry.full_name) end - end -require 'rubygems/package/digest_io' -require 'rubygems/package/source' -require 'rubygems/package/file_source' -require 'rubygems/package/io_source' -require 'rubygems/package/old' -require 'rubygems/package/tar_header' -require 'rubygems/package/tar_reader' -require 'rubygems/package/tar_reader/entry' -require 'rubygems/package/tar_writer' +require_relative 'package/digest_io' +require_relative 'package/source' +require_relative 'package/file_source' +require_relative 'package/io_source' +require_relative 'package/old' +require_relative 'package/tar_header' +require_relative 'package/tar_reader' +require_relative 'package/tar_reader/entry' +require_relative 'package/tar_writer' diff --git a/ruby/lib/rubygems/package/digest_io.rb b/ruby/lib/rubygems/package/digest_io.rb index d9e6c3c02..4736f76d9 100644 --- a/ruby/lib/rubygems/package/digest_io.rb +++ b/ruby/lib/rubygems/package/digest_io.rb @@ -3,7 +3,6 @@ # IO wrapper that creates digests of contents written to the IO it wraps. class Gem::Package::DigestIO - ## # Collected digests for wrapped writes. # @@ -60,5 +59,4 @@ def write(data) result end - end diff --git a/ruby/lib/rubygems/package/file_source.rb b/ruby/lib/rubygems/package/file_source.rb index 8a4f9da6f..114a950c7 100644 --- a/ruby/lib/rubygems/package/file_source.rb +++ b/ruby/lib/rubygems/package/file_source.rb @@ -7,7 +7,6 @@ # object to `Gem::Package.new`. class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all - attr_reader :path def initialize(path) @@ -29,5 +28,4 @@ def with_write_io(&block) def with_read_io(&block) File.open path, 'rb', &block end - end diff --git a/ruby/lib/rubygems/package/io_source.rb b/ruby/lib/rubygems/package/io_source.rb index 669a859d0..03d771452 100644 --- a/ruby/lib/rubygems/package/io_source.rb +++ b/ruby/lib/rubygems/package/io_source.rb @@ -8,7 +8,6 @@ # object to `Gem::Package.new`. class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all - attr_reader :io def initialize(io) @@ -33,13 +32,16 @@ def present? def with_read_io yield io + ensure + io.rewind end def with_write_io yield io + ensure + io.rewind end def path end - end diff --git a/ruby/lib/rubygems/package/old.rb b/ruby/lib/rubygems/package/old.rb index f574b989a..301d40341 100644 --- a/ruby/lib/rubygems/package/old.rb +++ b/ruby/lib/rubygems/package/old.rb @@ -12,7 +12,6 @@ # Please pretend this doesn't exist. class Gem::Package::Old < Gem::Package - undef_method :spec= ## @@ -42,7 +41,7 @@ def contents read_until_dashes io # spec header = file_list io - @contents = header.map { |file| file['path'] } + @contents = header.map {|file| file['path'] } end end @@ -146,7 +145,7 @@ def spec begin @spec = Gem::Specification.from_yaml yaml - rescue YAML::SyntaxError + rescue Psych::SyntaxError raise Gem::Exception, "Failed to parse gem specification out of gem file" end rescue ArgumentError @@ -166,5 +165,4 @@ def verify true end - end diff --git a/ruby/lib/rubygems/package/tar_header.rb b/ruby/lib/rubygems/package/tar_header.rb index c37612772..ce9b49e3e 100644 --- a/ruby/lib/rubygems/package/tar_header.rb +++ b/ruby/lib/rubygems/package/tar_header.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: true #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier @@ -29,7 +28,6 @@ # A header for a tar file class Gem::Package::TarHeader - ## # Fields in the tar header @@ -126,7 +124,8 @@ def self.from(stream) end def self.strict_oct(str) - return str.oct if str =~ /\A[0-7]*\z/ + return str.strip.oct if str.strip =~ /\A[0-7]*\z/ + raise ArgumentError, "#{str.inspect} is not an octal string" end @@ -209,7 +208,7 @@ def update_checksum private def calculate_checksum(header) - header.unpack("C*").inject { |a, b| a + b } + header.unpack("C*").inject {|a, b| a + b } end def header(checksum = @checksum) @@ -230,7 +229,7 @@ def header(checksum = @checksum) gname, oct(devmajor, 7), oct(devminor, 7), - prefix + prefix, ] header = header.pack PACK_FORMAT @@ -241,5 +240,4 @@ def header(checksum = @checksum) def oct(num, len) "%0#{len}o" % num end - end diff --git a/ruby/lib/rubygems/package/tar_reader.rb b/ruby/lib/rubygems/package/tar_reader.rb index aa31ea27d..41121f3bf 100644 --- a/ruby/lib/rubygems/package/tar_reader.rb +++ b/ruby/lib/rubygems/package/tar_reader.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: true #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier @@ -9,7 +8,6 @@ # TarReader reads tar files and allows iteration over their items class Gem::Package::TarReader - include Enumerable ## @@ -121,7 +119,6 @@ def seek(name) # :yields: entry ensure rewind end - end -require 'rubygems/package/tar_reader/entry' +require_relative 'tar_reader/entry' diff --git a/ruby/lib/rubygems/package/tar_reader/entry.rb b/ruby/lib/rubygems/package/tar_reader/entry.rb index 19054c163..5865599d3 100644 --- a/ruby/lib/rubygems/package/tar_reader/entry.rb +++ b/ruby/lib/rubygems/package/tar_reader/entry.rb @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: true #++ # Copyright (C) 2004 Mauricio Julio Fernández Pradier @@ -9,7 +8,6 @@ # Class for reading entries out of a tar file class Gem::Package::TarReader::Entry - ## # Header for this tar entry @@ -166,5 +164,4 @@ def rewind @io.pos = @orig_pos @read = 0 end - end diff --git a/ruby/lib/rubygems/package/tar_writer.rb b/ruby/lib/rubygems/package/tar_writer.rb index 96d8184e8..877cc167c 100644 --- a/ruby/lib/rubygems/package/tar_writer.rb +++ b/ruby/lib/rubygems/package/tar_writer.rb @@ -1,24 +1,19 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: true #-- # Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #++ -require 'digest' - ## # Allows writing of tar files class Gem::Package::TarWriter - class FileOverflow < StandardError; end ## # IO wrapper that allows writing a limited amount of data class BoundedStream - ## # Maximum number of bytes that can be written @@ -50,14 +45,12 @@ def write(data) @written += data.bytesize data.bytesize end - end ## # IO wrapper that provides only #write class RestrictedStream - ## # Creates a new RestrictedStream wrapping +io+ @@ -71,7 +64,6 @@ def initialize(io) def write(data) @io.write data end - end ## @@ -146,8 +138,7 @@ def add_file_digest(name, mode, digest_algorithms) # :yields: io if digest.respond_to? :name digest.name else - /::([^:]+)$/ =~ digest_algorithm.name - $1 + digest_algorithm.class.name[/::([^:]+)\z/, 1] end [digest_name, digest] @@ -175,7 +166,7 @@ def add_file_digest(name, mode, digest_algorithms) # :yields: io def add_file_signed(name, mode, signer) digest_algorithms = [ signer.digest_algorithm, - Digest::SHA512, + Gem::Security.create_digest('SHA512'), ].compact.uniq digests = add_file_digest name, mode, digest_algorithms do |io| @@ -334,5 +325,4 @@ def split_name(name) # :nodoc: return name, prefix end - end diff --git a/ruby/lib/rubygems/package_task.rb b/ruby/lib/rubygems/package_task.rb index a11d09fb2..bb48616b0 100644 --- a/ruby/lib/rubygems/package_task.rb +++ b/ruby/lib/rubygems/package_task.rb @@ -20,13 +20,8 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -require 'rubygems' -require 'rubygems/package' -begin - gem 'rake' -rescue Gem::LoadError -end - +require_relative '../rubygems' +require_relative 'package' require 'rake/packagetask' ## @@ -62,7 +57,6 @@ # end class Gem::PackageTask < Rake::PackageTask - ## # Ruby Gem::Specification containing the metadata for this package. The # name, version and package_files are automatically determined from the @@ -88,6 +82,7 @@ def init(gem) super gem.full_name, :noversion @gem_spec = gem @package_files += gem_spec.files if gem_spec.files + @fileutils_output = $stdout end ## @@ -124,5 +119,4 @@ def define end end end - end diff --git a/ruby/lib/rubygems/path_support.rb b/ruby/lib/rubygems/path_support.rb index 130d40006..d601e653c 100644 --- a/ruby/lib/rubygems/path_support.rb +++ b/ruby/lib/rubygems/path_support.rb @@ -5,7 +5,6 @@ # to the rest of RubyGems. # class Gem::PathSupport - ## # The default system path for managing Gems. attr_reader :home @@ -26,13 +25,6 @@ class Gem::PathSupport def initialize(env) @home = env["GEM_HOME"] || Gem.default_dir - # --------- [Enclose.IO Hack start] --------- - # WE DO NOT ACCEPT OUTSIDE GEM PATHS - unless env['ENCLOSE_IO_RUBYC_1ST_PASS'] - @home = Gem.default_dir unless 0 == @home.index('/__enclose_io_memfs__') - end - # --------- [Enclose.IO Hack end] --------- - if File::ALT_SEPARATOR @home = @home.gsub(File::ALT_SEPARATOR, File::SEPARATOR) end @@ -41,15 +33,6 @@ def initialize(env) @path = split_gem_path env["GEM_PATH"], @home - # --------- [Enclose.IO Hack start] --------- - # WE DO NOT ACCEPT OUTSIDE GEM PATHS - unless env['ENCLOSE_IO_RUBYC_1ST_PASS'] - @path.keep_if do |x| - 0 == x.index('/__enclose_io_memfs__') - end - end - # --------- [Enclose.IO Hack end] --------- - @spec_cache_dir = env["GEM_SPEC_CACHE"] || Gem.default_spec_cache_dir @spec_cache_dir = @spec_cache_dir.dup.tap(&Gem::UNTAINT) @@ -84,17 +67,12 @@ def split_gem_path(gpaths, home) gem_path = default_path end - gem_path.map { |path| expand(path) }.uniq + gem_path.map {|path| expand(path) }.uniq end # Return the default Gem path def default_path - gem_path = Gem.default_path + [@home] - - if defined?(APPLE_GEM_HOME) - gem_path << APPLE_GEM_HOME - end - gem_path + Gem.default_path + [@home] end def expand(path) @@ -104,5 +82,4 @@ def expand(path) path end end - end diff --git a/ruby/lib/rubygems/platform.rb b/ruby/lib/rubygems/platform.rb index 521c552be..f48f4bdc7 100644 --- a/ruby/lib/rubygems/platform.rb +++ b/ruby/lib/rubygems/platform.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "rubygems/deprecate" +require_relative "deprecate" ## # Available list of platforms for targeting Gem installations. @@ -7,14 +7,9 @@ # See `gem help platform` for information on platform matching. class Gem::Platform - @local = nil - attr_accessor :cpu - - attr_accessor :os - - attr_accessor :version + attr_accessor :cpu, :os, :version def self.local arch = RbConfig::CONFIG['arch'] @@ -23,18 +18,37 @@ def self.local end def self.match(platform) - Gem.platforms.any? do |local_platform| + match_platforms?(platform, Gem.platforms) + end + + def self.match_platforms?(platform, platforms) + platforms.any? do |local_platform| platform.nil? or local_platform == platform or (local_platform != Gem::Platform::RUBY and local_platform =~ platform) end end + private_class_method :match_platforms? + + def self.match_spec?(spec) + match_gem?(spec.platform, spec.name) + end + + def self.match_gem?(platform, gem_name) + # Note: this method might be redefined by Ruby implementations to + # customize behavior per RUBY_ENGINE, gem_name or other criteria. + match_platforms?(platform, Gem.platforms) + end + + def self.sort_priority(platform) + platform == Gem::Platform::RUBY ? -1 : 1 + end def self.installable?(spec) if spec.respond_to? :installable_platform? spec.installable_platform? else - match spec.platform + match_spec? spec end end @@ -56,7 +70,7 @@ def initialize(arch) when String then arch = arch.split '-' - if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu + if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu extra = arch.pop arch.last << "-#{extra}" end @@ -64,11 +78,11 @@ def initialize(arch) cpu = arch.shift @cpu = case cpu - when /i\d86/ then 'x86' - else cpu - end + when /i\d86/ then 'x86' + else cpu + end - if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line + if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line @os, @version = arch return end @@ -77,31 +91,32 @@ def initialize(arch) @cpu, os = nil, cpu if os.nil? # legacy jruby @os, @version = case os - when /aix(\d+)?/ then [ 'aix', $1 ] - when /cygwin/ then [ 'cygwin', nil ] - when /darwin(\d+)?/ then [ 'darwin', $1 ] - when /^macruby$/ then [ 'macruby', nil ] - when /freebsd(\d+)?/ then [ 'freebsd', $1 ] - when /hpux(\d+)?/ then [ 'hpux', $1 ] - when /^java$/, /^jruby$/ then [ 'java', nil ] - when /^java([\d.]*)/ then [ 'java', $1 ] - when /^dalvik(\d+)?$/ then [ 'dalvik', $1 ] - when /^dotnet$/ then [ 'dotnet', nil ] - when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ] - when /linux-?((?!gnu)\w+)?/ then [ 'linux', $1 ] - when /mingw32/ then [ 'mingw32', nil ] - when /(mswin\d+)(\_(\d+))?/ then - os, version = $1, $3 - @cpu = 'x86' if @cpu.nil? and os =~ /32$/ - [os, version] - when /netbsdelf/ then [ 'netbsdelf', nil ] - when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ] - when /bitrig(\d+\.\d+)?/ then [ 'bitrig', $1 ] - when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ] - # test - when /^(\w+_platform)(\d+)?/ then [ $1, $2 ] - else [ 'unknown', nil ] - end + when /aix(\d+)?/ then [ 'aix', $1 ] + when /cygwin/ then [ 'cygwin', nil ] + when /darwin(\d+)?/ then [ 'darwin', $1 ] + when /^macruby$/ then [ 'macruby', nil ] + when /freebsd(\d+)?/ then [ 'freebsd', $1 ] + when /hpux(\d+)?/ then [ 'hpux', $1 ] + when /^java$/, /^jruby$/ then [ 'java', nil ] + when /^java([\d.]*)/ then [ 'java', $1 ] + when /^dalvik(\d+)?$/ then [ 'dalvik', $1 ] + when /^dotnet$/ then [ 'dotnet', nil ] + when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ] + when /linux-?((?!gnu)\w+)?/ then [ 'linux', $1 ] + when /mingw32/ then [ 'mingw32', nil ] + when /mingw-?(\w+)?/ then [ 'mingw', $1 ] + when /(mswin\d+)(\_(\d+))?/ then + os, version = $1, $3 + @cpu = 'x86' if @cpu.nil? and os =~ /32$/ + [os, version] + when /netbsdelf/ then [ 'netbsdelf', nil ] + when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ] + when /bitrig(\d+\.\d+)?/ then [ 'bitrig', $1 ] + when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ] + # test + when /^(\w+_platform)(\d+)?/ then [ $1, $2 ] + else [ 'unknown', nil ] + end when Gem::Platform then @cpu = arch.cpu @os = arch.os @@ -111,10 +126,6 @@ def initialize(arch) end end - def inspect - "%s @cpu=%p, @os=%p, @version=%p>" % [super[0..-2], *to_a] - end - def to_a [@cpu, @os, @version] end @@ -150,7 +161,7 @@ def ===(other) # cpu ([nil,'universal'].include?(@cpu) or [nil, 'universal'].include?(other.cpu) or @cpu == other.cpu or - (@cpu == 'arm' and other.cpu =~ /\Aarm/)) and + (@cpu == 'arm' and other.cpu.start_with?("arm"))) and # os @os == other.os and @@ -169,19 +180,19 @@ def =~(other) when String then # This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007 other = case other - when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ] - when /^i\d86-linux/ then ['x86', 'linux', nil ] - when 'java', 'jruby' then [nil, 'java', nil ] - when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ] - when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ] - when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ] - when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ] - when 'powerpc-darwin' then ['powerpc', 'darwin', nil ] - when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ] - when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ] - when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ] - else other - end + when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ] + when /^i\d86-linux/ then ['x86', 'linux', nil ] + when 'java', 'jruby' then [nil, 'java', nil ] + when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ] + when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ] + when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ] + when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ] + when 'powerpc-darwin' then ['powerpc', 'darwin', nil ] + when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ] + when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ] + when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ] + else other + end other = Gem::Platform.new other else @@ -202,5 +213,4 @@ def =~(other) # This will be replaced with Gem::Platform::local. CURRENT = 'current'.freeze - end diff --git a/ruby/lib/rubygems/psych_additions.rb b/ruby/lib/rubygems/psych_additions.rb index 1ddd74421..a13c1ec67 100644 --- a/ruby/lib/rubygems/psych_additions.rb +++ b/ruby/lib/rubygems/psych_additions.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true # This exists just to satisfy bugs in marshal'd gemspecs that -# contain a reference to YAML::PrivateType. We prune these out +# contain a reference to Psych::PrivateType. We prune these out # in Specification._load, but if we don't have the constant, Marshal # blows up. diff --git a/ruby/lib/rubygems/psych_tree.rb b/ruby/lib/rubygems/psych_tree.rb index b4eebf1dc..6f399a289 100644 --- a/ruby/lib/rubygems/psych_tree.rb +++ b/ruby/lib/rubygems/psych_tree.rb @@ -2,7 +2,6 @@ module Gem if defined? ::Psych::Visitors class NoAliasYAMLTree < Psych::Visitors::YAMLTree - def self.create new({}) end unless respond_to? :create @@ -28,7 +27,6 @@ def format_time(time) end private :format_time - end end end diff --git a/ruby/lib/rubygems/query_utils.rb b/ruby/lib/rubygems/query_utils.rb new file mode 100644 index 000000000..f4cfea308 --- /dev/null +++ b/ruby/lib/rubygems/query_utils.rb @@ -0,0 +1,351 @@ +# frozen_string_literal: true + +require_relative 'local_remote_options' +require_relative 'spec_fetcher' +require_relative 'version_option' +require_relative 'text' + +module Gem::QueryUtils + + include Gem::Text + include Gem::LocalRemoteOptions + include Gem::VersionOption + + def add_query_options + add_option('-i', '--[no-]installed', + 'Check for installed gem') do |value, options| + options[:installed] = value + end + + add_option('-I', 'Equivalent to --no-installed') do |value, options| + options[:installed] = false + end + + add_version_option command, "for use with --installed" + + add_option('-d', '--[no-]details', + 'Display detailed information of gem(s)') do |value, options| + options[:details] = value + end + + add_option('--[no-]versions', + 'Display only gem names') do |value, options| + options[:versions] = value + options[:details] = false unless value + end + + add_option('-a', '--all', + 'Display all gem versions') do |value, options| + options[:all] = value + end + + add_option('-e', '--exact', + 'Name of gem(s) to query on matches the', + 'provided STRING') do |value, options| + options[:exact] = value + end + + add_option('--[no-]prerelease', + 'Display prerelease versions') do |value, options| + options[:prerelease] = value + end + + add_local_remote_options + end + + def defaults_str # :nodoc: + "--local --no-details --versions --no-installed" + end + + def execute + gem_names = if args.empty? + [options[:name]] + else + options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i } + end + + terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems? + + gem_names.each {|n| show_gems(n) } + end + + private + + def check_installed_gems(gem_names) + exit_code = 0 + + if args.empty? && !gem_name? + alert_error "You must specify a gem name" + exit_code = 4 + elsif gem_names.count > 1 + alert_error "You must specify only ONE gem!" + exit_code = 4 + else + installed = installed?(gem_names.first, options[:version]) + installed = !installed unless options[:installed] + + say(installed) + exit_code = 1 if !installed + end + + exit_code + end + + def check_installed_gems? + !options[:installed].nil? + end + + def gem_name? + !options[:name].nil? + end + + def prerelease + options[:prerelease] + end + + def show_prereleases? + prerelease.nil? || prerelease + end + + def args + options[:args].to_a + end + + def display_header(type) + if (ui.outs.tty? and Gem.configuration.verbose) or both? + say + say "*** #{type} GEMS ***" + say + end + end + + #Guts of original execute + def show_gems(name) + show_local_gems(name) if local? + show_remote_gems(name) if remote? + end + + def show_local_gems(name, req = Gem::Requirement.default) + display_header("LOCAL") + + specs = Gem::Specification.find_all do |s| + name_matches = name ? s.name =~ name : true + version_matches = show_prereleases? || !s.version.prerelease? + + name_matches and version_matches + end + + spec_tuples = specs.map do |spec| + [spec.name_tuple, spec] + end + + output_query_results(spec_tuples) + end + + def show_remote_gems(name) + display_header("REMOTE") + + fetcher = Gem::SpecFetcher.fetcher + + spec_tuples = if name.nil? + fetcher.detect(specs_type) { true } + else + fetcher.detect(specs_type) do |name_tuple| + name === name_tuple.name + end + end + + output_query_results(spec_tuples) + end + + def specs_type + if options[:all] + if options[:prerelease] + :complete + else + :released + end + elsif options[:prerelease] + :prerelease + else + :latest + end + end + + ## + # Check if gem +name+ version +version+ is installed. + + def installed?(name, req = Gem::Requirement.default) + Gem::Specification.any? {|s| s.name =~ name and req =~ s.version } + end + + def output_query_results(spec_tuples) + output = [] + versions = Hash.new {|h,name| h[name] = [] } + + spec_tuples.each do |spec_tuple, source| + versions[spec_tuple.name] << [spec_tuple, source] + end + + versions = versions.sort_by do |(n,_),_| + n.downcase + end + + output_versions output, versions + + say output.join(options[:details] ? "\n\n" : "\n") + end + + def output_versions(output, versions) + versions.each do |gem_name, matching_tuples| + matching_tuples = matching_tuples.sort_by {|n,_| n.version }.reverse + + platforms = Hash.new {|h,version| h[version] = [] } + + matching_tuples.each do |n, _| + platforms[n.version] << n.platform if n.platform + end + + seen = {} + + matching_tuples.delete_if do |n,_| + if seen[n.version] + true + else + seen[n.version] = true + false + end + end + + output << clean_text(make_entry(matching_tuples, platforms)) + end + end + + def entry_details(entry, detail_tuple, specs, platforms) + return unless options[:details] + + name_tuple, spec = detail_tuple + + spec = spec.fetch_spec(name_tuple)if spec.respond_to?(:fetch_spec) + + entry << "\n" + + spec_platforms entry, platforms + spec_authors entry, spec + spec_homepage entry, spec + spec_license entry, spec + spec_loaded_from entry, spec, specs + spec_summary entry, spec + end + + def entry_versions(entry, name_tuples, platforms, specs) + return unless options[:versions] + + list = + if platforms.empty? or options[:details] + name_tuples.map {|n| n.version }.uniq + else + platforms.sort.reverse.map do |version, pls| + out = version.to_s + + if options[:domain] == :local + default = specs.any? do |s| + !s.is_a?(Gem::Source) && s.version == version && s.default_gem? + end + out = "default: #{out}" if default + end + + if pls != [Gem::Platform::RUBY] + platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact + out = platform_list.unshift(out).join(' ') + end + + out + end + end + + entry << " (#{list.join ', '})" + end + + def make_entry(entry_tuples, platforms) + detail_tuple = entry_tuples.first + + name_tuples, specs = entry_tuples.flatten.partition do |item| + Gem::NameTuple === item + end + + entry = [name_tuples.first.name] + + entry_versions(entry, name_tuples, platforms, specs) + entry_details(entry, detail_tuple, specs, platforms) + + entry.join + end + + def spec_authors(entry, spec) + authors = "Author#{spec.authors.length > 1 ? 's' : ''}: ".dup + authors << spec.authors.join(', ') + entry << format_text(authors, 68, 4) + end + + def spec_homepage(entry, spec) + return if spec.homepage.nil? or spec.homepage.empty? + + entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4) + end + + def spec_license(entry, spec) + return if spec.license.nil? or spec.license.empty? + + licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: ".dup + licenses << spec.licenses.join(', ') + entry << "\n" << format_text(licenses, 68, 4) + end + + def spec_loaded_from(entry, spec, specs) + return unless spec.loaded_from + + if specs.length == 1 + default = spec.default_gem? ? ' (default)' : nil + entry << "\n" << " Installed at#{default}: #{spec.base_dir}" + else + label = 'Installed at' + specs.each do |s| + version = s.version.to_s + version << ', default' if s.default_gem? + entry << "\n" << " #{label} (#{version}): #{s.base_dir}" + label = ' ' * label.length + end + end + end + + def spec_platforms(entry, platforms) + non_ruby = platforms.any? do |_, pls| + pls.any? {|pl| pl != Gem::Platform::RUBY } + end + + return unless non_ruby + + if platforms.length == 1 + title = platforms.values.length == 1 ? 'Platform' : 'Platforms' + entry << " #{title}: #{platforms.values.sort.join(', ')}\n" + else + entry << " Platforms:\n" + + sorted_platforms = platforms.sort_by {|version,| version } + + sorted_platforms.each do |version, pls| + label = " #{version}: " + data = format_text pls.sort.join(', '), 68, label.length + data[0, label.length] = label + entry << data << "\n" + end + end + end + + def spec_summary(entry, spec) + summary = truncate_text(spec.summary, "the summary for #{spec.full_name}") + entry << "\n\n" << format_text(summary, 68, 4) + end + +end diff --git a/ruby/lib/rubygems/rdoc.rb b/ruby/lib/rubygems/rdoc.rb index 4e16fbb86..ac5e8f082 100644 --- a/ruby/lib/rubygems/rdoc.rb +++ b/ruby/lib/rubygems/rdoc.rb @@ -1,17 +1,5 @@ # frozen_string_literal: true -require 'rubygems' - -begin - gem 'rdoc' -rescue Gem::LoadError - # swallow -else - # This will force any deps that 'rdoc' might have - # (such as json) that are ambiguous to be activated, which - # is important because we end up using Specification.reset - # and we don't want the warning it pops out. - Gem.finish_resolve -end +require_relative '../rubygems' begin require 'rdoc/rubygems_hook' diff --git a/ruby/lib/rubygems/remote_fetcher.rb b/ruby/lib/rubygems/remote_fetcher.rb index 2ed619f1b..b8f9f90ce 100644 --- a/ruby/lib/rubygems/remote_fetcher.rb +++ b/ruby/lib/rubygems/remote_fetcher.rb @@ -1,52 +1,41 @@ # frozen_string_literal: true -require 'rubygems' -require 'rubygems/request' -require 'rubygems/request/connection_pools' -require 'rubygems/s3_uri_signer' -require 'rubygems/uri_formatter' -require 'rubygems/uri_parsing' -require 'rubygems/user_interaction' -require 'resolv' -require 'rubygems/deprecate' +require_relative '../rubygems' +require_relative 'request' +require_relative 'request/connection_pools' +require_relative 's3_uri_signer' +require_relative 'uri_formatter' +require_relative 'uri' +require_relative 'user_interaction' ## # RemoteFetcher handles the details of fetching gems and gem information from # a remote source. class Gem::RemoteFetcher - include Gem::UserInteraction - extend Gem::Deprecate - - include Gem::UriParsing ## # A FetchError exception wraps up the various possible IO and HTTP failures # that could happen while downloading from the internet. class FetchError < Gem::Exception - - include Gem::UriParsing - ## # The URI which was being accessed when the exception happened. - attr_accessor :uri + attr_accessor :uri, :original_uri def initialize(message, uri) - super message - - uri = parse_uri(uri) + uri = Gem::Uri.new(uri) - uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password + super uri.redact_credentials_from(message) - @uri = uri.to_s + @original_uri = uri.to_s + @uri = uri.redacted.to_s end def to_s # :nodoc: "#{super} (#{uri})" end - end ## @@ -55,6 +44,7 @@ def to_s # :nodoc: class UnknownHostError < FetchError end + deprecate_constant(:UnknownHostError) @fetcher = nil @@ -82,16 +72,16 @@ def self.fetcher # fetching the gem. def initialize(proxy=nil, dns=nil, headers={}) + require_relative 'core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled require 'net/http' require 'stringio' - require 'time' require 'uri' Socket.do_not_reverse_lookup = true @proxy = proxy @pools = {} - @pool_lock = Mutex.new + @pool_lock = Thread::Mutex.new @cert_files = Gem::Request.get_cert_files @headers = headers @@ -109,7 +99,7 @@ def download_to_cache(dependency) return if found.empty? - spec, source = found.max_by { |(s,_)| s.version } + spec, source = found.max_by {|(s,_)| s.version } download spec, source.uri end @@ -120,11 +110,12 @@ def download_to_cache(dependency) # always replaced. def download(spec, source_uri, install_dir = Gem.dir) + install_cache_dir = File.join install_dir, "cache" cache_dir = - if Dir.pwd == install_dir # see fetch_command + if Dir.pwd == install_dir # see fetch_command install_dir - elsif File.writable? install_dir - File.join install_dir, "cache" + elsif File.writable?(install_cache_dir) || (File.writable?(install_dir) && (not File.exist?(install_cache_dir))) + install_cache_dir else File.join Gem.user_dir, "cache" end @@ -132,9 +123,10 @@ def download(spec, source_uri, install_dir = Gem.dir) gem_file_name = File.basename spec.cache_file local_gem_path = File.join cache_dir, gem_file_name + require "fileutils" FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir - source_uri = parse_uri(source_uri) + source_uri = Gem::Uri.new(source_uri) scheme = source_uri.scheme @@ -180,10 +172,10 @@ def download(spec, source_uri, install_dir = Gem.dir) when nil then # TODO test for local overriding cache source_path = if Gem.win_platform? && source_uri.scheme && !source_uri.path.include?(':') - "#{source_uri.scheme}:#{source_uri.path}" - else - source_uri.path - end + "#{source_uri.scheme}:#{source_uri.path}" + else + source_uri.path + end source_path = Gem::UriFormatter.new(source_path).unescape @@ -215,12 +207,12 @@ def fetch_file(uri, *_) def fetch_http(uri, last_modified = nil, head = false, depth = 0) fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get response = request uri, fetch_type, last_modified do |req| - headers.each { |k,v| req.add_field(k,v) } + headers.each {|k,v| req.add_field(k,v) } end case response when Net::HTTPOK, Net::HTTPNotModified then - response.uri = uri if response.respond_to? :uri + response.uri = uri head ? response : response.body when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther, Net::HTTPTemporaryRedirect then @@ -229,7 +221,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) unless location = response['Location'] raise FetchError.new("redirecting but no redirect location was given", uri) end - location = parse_uri location + location = Gem::Uri.new location if https?(uri) && !https?(location) raise FetchError.new("redirecting to non-https resource: #{location}", uri) @@ -247,7 +239,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - uri = parse_uri uri + uri = Gem::Uri.new uri unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" @@ -255,7 +247,7 @@ def fetch_path(uri, mtime = nil, head = false) data = send "fetch_#{uri.scheme}", uri, mtime, head - if data and !head and uri.to_s =~ /\.gz$/ + if data and !head and uri.to_s.end_with?(".gz") begin data = Gem::Util.gunzip data rescue Zlib::GzipFile::Error @@ -264,15 +256,9 @@ def fetch_path(uri, mtime = nil, head = false) end data - rescue Timeout::Error - raise UnknownHostError.new('timed out', uri) - rescue IOError, SocketError, SystemCallError, - *(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e - if e.message =~ /getaddrinfo/ - raise UnknownHostError.new('no such name', uri) - else - raise FetchError.new("#{e.class}: #{e}", uri) - end + rescue Timeout::Error, IOError, SocketError, SystemCallError, + *(OpenSSL::SSL::SSLError if Gem::HAVE_OPENSSL) => e + raise FetchError.new("#{e.class}: #{e}", uri) end def fetch_s3(uri, mtime = nil, head = false) @@ -298,7 +284,7 @@ def cache_update_path(uri, path = nil, update = true) data = fetch_path(uri, mtime) - if data == nil # indicates the server returned 304 Not Modified + if data.nil? # indicates the server returned 304 Not Modified return Gem.read_binary(path) end @@ -309,17 +295,6 @@ def cache_update_path(uri, path = nil, update = true) data end - ## - # Returns the size of +uri+ in bytes. - - def fetch_size(uri) - response = fetch_path(uri, nil, true) - - response['content-length'].to_i - end - - deprecate :fetch_size, :none, 2019, 12 - ## # Performs a Net::HTTP request of type +request_class+ on +uri+ returning # a Net::HTTP response object. request maintains a table of persistent @@ -341,7 +316,7 @@ def https?(uri) end def close_all - @pools.each_value {|pool| pool.close_all} + @pools.each_value {|pool| pool.close_all } end private @@ -355,5 +330,4 @@ def pools_for(proxy) @pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files end end - end diff --git a/ruby/lib/rubygems/request.rb b/ruby/lib/rubygems/request.rb index b5a14ec34..d6100c914 100644 --- a/ruby/lib/rubygems/request.rb +++ b/ruby/lib/rubygems/request.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true require 'net/http' -require 'time' -require 'rubygems/user_interaction' +require_relative 'user_interaction' class Gem::Request - extend Gem::UserInteraction include Gem::UserInteraction @@ -46,7 +44,8 @@ def self.get_cert_files end def self.configure_connection_for_https(connection, cert_files) - require 'net/https' + raise Gem::Exception.new('OpenSSL is not available. Install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources') unless Gem::HAVE_OPENSSL + connection.use_ssl = true connection.verify_mode = Gem.configuration.ssl_verify_mode || OpenSSL::SSL::VERIFY_PEER @@ -78,12 +77,6 @@ def self.configure_connection_for_https(connection, cert_files) end connection - rescue LoadError => e - raise unless (e.respond_to?(:path) && e.path == 'openssl') || - e.message =~ / -- openssl$/ - - raise Gem::Exception.new( - 'Unable to require openssl, install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources') end def self.verify_certificate(store_context) @@ -103,8 +96,10 @@ def self.verify_certificate_message(error_number, cert) return unless cert case error_number when OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED then + require 'time' "Certificate #{cert.subject} expired at #{cert.not_after.iso8601}" when OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID then + require 'time' "Certificate #{cert.subject} not valid until #{cert.not_before.iso8601}" when OpenSSL::X509::V_ERR_CERT_REJECTED then "Certificate #{cert.subject} is rejected" @@ -132,7 +127,7 @@ def self.verify_certificate_message(error_number, cert) def connection_for(uri) @connection_pool.checkout - rescue defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN, + rescue Gem::HAVE_OPENSSL ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN, Errno::EHOSTDOWN => e raise Gem::RemoteFetcher::FetchError.new(e.message, uri) end @@ -150,6 +145,7 @@ def fetch request.add_field 'Keep-Alive', '30' if @last_modified + require 'time' request.add_field 'If-Modified-Since', @last_modified.httpdate end @@ -197,7 +193,7 @@ def perform_request(request) # :nodoc: begin @requests[connection.object_id] += 1 - verbose "#{request.method} #{@uri}" + verbose "#{request.method} #{Gem::Uri.new(@uri).redacted}" file_name = File.basename(@uri.path) # perform download progress reporter only for gems @@ -291,9 +287,8 @@ def user_agent ua end - end -require 'rubygems/request/http_pool' -require 'rubygems/request/https_pool' -require 'rubygems/request/connection_pools' +require_relative 'request/http_pool' +require_relative 'request/https_pool' +require_relative 'request/connection_pools' diff --git a/ruby/lib/rubygems/request/connection_pools.rb b/ruby/lib/rubygems/request/connection_pools.rb index 9444239b2..a4c2929b3 100644 --- a/ruby/lib/rubygems/request/connection_pools.rb +++ b/ruby/lib/rubygems/request/connection_pools.rb @@ -1,20 +1,17 @@ # frozen_string_literal: true class Gem::Request::ConnectionPools # :nodoc: - @client = Net::HTTP class << self - attr_accessor :client - end def initialize(proxy_uri, cert_files) @proxy_uri = proxy_uri @cert_files = cert_files @pools = {} - @pool_mutex = Mutex.new + @pool_mutex = Thread::Mutex.new end def pool_for(uri) @@ -31,7 +28,7 @@ def pool_for(uri) end def close_all - @pools.each_value {|pool| pool.close_all} + @pools.each_value {|pool| pool.close_all } end private @@ -95,5 +92,4 @@ def net_http_args(uri, proxy_uri) net_http_args end end - end diff --git a/ruby/lib/rubygems/request/http_pool.rb b/ruby/lib/rubygems/request/http_pool.rb index 058094a20..f028516db 100644 --- a/ruby/lib/rubygems/request/http_pool.rb +++ b/ruby/lib/rubygems/request/http_pool.rb @@ -6,14 +6,13 @@ # use it. class Gem::Request::HTTPPool # :nodoc: - attr_reader :cert_files, :proxy_uri def initialize(http_args, cert_files, proxy_uri) @http_args = http_args @cert_files = cert_files @proxy_uri = proxy_uri - @queue = SizedQueue.new 1 + @queue = Thread::SizedQueue.new 1 @queue << nil end @@ -44,5 +43,4 @@ def setup_connection(connection) connection.start connection end - end diff --git a/ruby/lib/rubygems/request/https_pool.rb b/ruby/lib/rubygems/request/https_pool.rb index 1236079b7..50f42d9e0 100644 --- a/ruby/lib/rubygems/request/https_pool.rb +++ b/ruby/lib/rubygems/request/https_pool.rb @@ -1,11 +1,9 @@ # frozen_string_literal: true class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc: - private def setup_connection(connection) Gem::Request.configure_connection_for_https(connection, @cert_files) super end - end diff --git a/ruby/lib/rubygems/request_set.rb b/ruby/lib/rubygems/request_set.rb index d6fb41f51..01b01599a 100644 --- a/ruby/lib/rubygems/request_set.rb +++ b/ruby/lib/rubygems/request_set.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'tsort' +require_relative 'tsort' ## # A RequestSet groups a request to activate a set of dependencies. @@ -15,8 +15,7 @@ # #=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"] class Gem::RequestSet - - include TSort + include Gem::TSort ## # Array of gems to install even if already installed @@ -152,7 +151,7 @@ def install(options, &block) # :yields: request, installer @prerelease = options[:prerelease] requests = [] - download_queue = Queue.new + download_queue = Thread::Queue.new # Create a thread-safe list of gems to download sorted_requests.each do |req| @@ -184,7 +183,7 @@ def install(options, &block) # :yields: request, installer if req.installed? req.spec.spec.build_extensions - if @always_install.none? { |spec| spec == req.spec.spec } + if @always_install.none? {|spec| spec == req.spec.spec } yield req, nil if block_given? next end @@ -196,19 +195,8 @@ def install(options, &block) # :yields: request, installer yield req, installer if block_given? end rescue Gem::RuntimeRequirementNotMetError => e - recent_match = req.spec.set.find_all(req.request).sort_by(&:version).reverse_each.find do |s| - s = s.spec - s.required_ruby_version.satisfied_by?(Gem.ruby_version) && - s.required_rubygems_version.satisfied_by?(Gem.rubygems_version) && - Gem::Platform.installable?(s) - end - if recent_match - suggestion = "The last version of #{req.request} to support your Ruby & RubyGems was #{recent_match.version}. Try installing it with `gem install #{recent_match.name} -v #{recent_match.version}`" - suggestion += " and then running the current command again" unless @always_install.include?(req.spec.spec) - else - suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems" - suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec) - end + suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems" + suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec) e.suggestion = suggestion raise end @@ -269,7 +257,7 @@ def install_into(dir, force = true, options = {}) gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir existing = force ? [] : specs_in(dir) - existing.delete_if { |s| @always_install.include? s } + existing.delete_if {|s| @always_install.include? s } dir = File.expand_path dir @@ -283,7 +271,7 @@ def install_into(dir, force = true, options = {}) sorted_requests.each do |request| spec = request.spec - if existing.find { |s| s.full_name == spec.full_name } + if existing.find {|s| s.full_name == spec.full_name } yield request, nil if block_given? next end @@ -315,7 +303,7 @@ def install_hooks(requests, options) end end - require "rubygems/dependency_installer" + require_relative "dependency_installer" inst = Gem::DependencyInstaller.new options inst.installed_gems.replace specs @@ -386,7 +374,7 @@ def pretty_print(q) # :nodoc: q.text 'sets:' q.breakable - q.pp @sets.map { |set| set.class } + q.pp @sets.map {|set| set.class } end end @@ -440,7 +428,7 @@ def sorted_requests end def specs - @specs ||= @requests.map { |r| r.full_spec } + @specs ||= @requests.map {|r| r.full_spec } end def specs_in(dir) @@ -471,9 +459,8 @@ def tsort_each_child(node) # :nodoc: yield match end end - end -require 'rubygems/request_set/gem_dependency_api' -require 'rubygems/request_set/lockfile' -require 'rubygems/request_set/lockfile/tokenizer' +require_relative 'request_set/gem_dependency_api' +require_relative 'request_set/lockfile' +require_relative 'request_set/lockfile/tokenizer' diff --git a/ruby/lib/rubygems/request_set/gem_dependency_api.rb b/ruby/lib/rubygems/request_set/gem_dependency_api.rb index b7a8ee6f4..7188b0734 100644 --- a/ruby/lib/rubygems/request_set/gem_dependency_api.rb +++ b/ruby/lib/rubygems/request_set/gem_dependency_api.rb @@ -31,7 +31,6 @@ # See `gem help install` and `gem help gem_dependencies` for further details. class Gem::RequestSet::GemDependencyAPI - ENGINE_MAP = { # :nodoc: :jruby => %w[jruby], :jruby_18 => %w[jruby], @@ -89,7 +88,7 @@ class Gem::RequestSet::GemDependencyAPI :truffleruby => Gem::Platform::RUBY, :x64_mingw => x64_mingw, :x64_mingw_20 => x64_mingw, - :x64_mingw_21 => x64_mingw + :x64_mingw_21 => x64_mingw, }.freeze gt_eq_0 = Gem::Requirement.new '>= 0' @@ -206,7 +205,7 @@ def initialize(set, path) @git_set = @set.git_set @git_sources = {} @installing = false - @requires = Hash.new { |h, name| h[name] = [] } + @requires = Hash.new {|h, name| h[name] = [] } @vendor_set = @set.vendor_set @source_set = @set.source_set @gem_sources = {} @@ -235,7 +234,7 @@ def add_dependencies(groups, dependencies) # :nodoc: return unless (groups & @without_groups).empty? dependencies.each do |dep| - @set.gem dep.name, *dep.requirement + @set.gem dep.name, *dep.requirement.as_list end end @@ -380,7 +379,7 @@ def gem(name, *requirements) Gem::Requirement.create requirements end - return unless gem_platforms options + return unless gem_platforms name, options groups = gem_group name, options @@ -533,7 +532,7 @@ def gem_source(name, options) # :nodoc: # Handles the platforms: option from +options+. Returns true if the # platform matches the current platform. - def gem_platforms(options) # :nodoc: + def gem_platforms(name, options) # :nodoc: platform_names = Array(options.delete :platform) platform_names.concat Array(options.delete :platforms) platform_names.concat @current_platforms if @current_platforms @@ -544,7 +543,7 @@ def gem_platforms(options) # :nodoc: raise ArgumentError, "unknown platform #{platform_name.inspect}" unless platform = PLATFORM_MAP[platform_name] - next false unless Gem::Platform.match platform + next false unless Gem::Platform.match_gem? platform, name if engines = ENGINE_MAP[platform_name] next false unless engines.include? Gem.ruby_engine @@ -842,5 +841,4 @@ def source(url) Gem.sources << url end - end diff --git a/ruby/lib/rubygems/request_set/lockfile.rb b/ruby/lib/rubygems/request_set/lockfile.rb index 5423f2c14..684d3fc7f 100644 --- a/ruby/lib/rubygems/request_set/lockfile.rb +++ b/ruby/lib/rubygems/request_set/lockfile.rb @@ -5,12 +5,10 @@ # constructed. class Gem::RequestSet::Lockfile - ## # Raised when a lockfile cannot be parsed class ParseError < Gem::Exception - ## # The column where the error was encountered @@ -36,7 +34,6 @@ def initialize(message, column, line, path) @path = path super "#{message} (at line #{line} column #{column})" end - end ## @@ -59,10 +56,10 @@ def self.requests_to_deps(requests) # :nodoc: deps[name] = if [Gem::Resolver::VendorSpecification, Gem::Resolver::GitSpecification].include? spec.class - Gem::Requirement.source_set - else - requirement - end + Gem::Requirement.source_set + else + requirement + end end deps @@ -89,7 +86,7 @@ def initialize(request_set, gem_deps_file, dependencies) def add_DEPENDENCIES(out) # :nodoc: out << "DEPENDENCIES" - out.concat @dependencies.sort_by { |name,| name }.map { |name, requirement| + out.concat @dependencies.sort_by {|name,| name }.map {|name, requirement| " #{name}#{requirement.for_lockfile}" } @@ -103,12 +100,12 @@ def add_GEM(out, spec_groups) # :nodoc: request.spec.source.uri end - source_groups.sort_by { |group,| group.to_s }.map do |group, requests| + source_groups.sort_by {|group,| group.to_s }.map do |group, requests| out << "GEM" out << " remote: #{group}" out << " specs:" - requests.sort_by { |request| request.name }.each do |request| + requests.sort_by {|request| request.name }.each do |request| next if request.spec.name == 'bundler' platform = "-#{request.spec.platform}" unless Gem::Platform::RUBY == request.spec.platform @@ -140,10 +137,10 @@ def add_GIT(out, git_requests) out << " revision: #{revision}" out << " specs:" - requests.sort_by { |request| request.name }.each do |request| + requests.sort_by {|request| request.name }.each do |request| out << " #{request.name} (#{request.version})" - dependencies = request.spec.dependencies.sort_by { |dep| dep.name } + dependencies = request.spec.dependencies.sort_by {|dep| dep.name } dependencies.each do |dep| out << " #{dep.name}#{dep.requirement.for_lockfile}" end @@ -185,9 +182,9 @@ def add_PATH(out, path_requests) # :nodoc: def add_PLATFORMS(out) # :nodoc: out << "PLATFORMS" - platforms = requests.map { |request| request.spec.platform }.uniq + platforms = requests.map {|request| request.spec.platform }.uniq - platforms = platforms.sort_by { |platform| platform.to_s } + platforms = platforms.sort_by {|platform| platform.to_s } platforms.each do |platform| out << " #{platform}" @@ -197,7 +194,7 @@ def add_PLATFORMS(out) # :nodoc: end def spec_groups - requests.group_by { |request| request.spec.class } + requests.group_by {|request| request.spec.class } end ## @@ -237,7 +234,6 @@ def write def requests @set.sorted_requests end - end -require 'rubygems/request_set/lockfile/tokenizer' +require_relative 'lockfile/tokenizer' diff --git a/ruby/lib/rubygems/request_set/lockfile/parser.rb b/ruby/lib/rubygems/request_set/lockfile/parser.rb index 1e9d2b12d..8c12b435a 100644 --- a/ruby/lib/rubygems/request_set/lockfile/parser.rb +++ b/ruby/lib/rubygems/request_set/lockfile/parser.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true class Gem::RequestSet::Lockfile::Parser - ### # Parses lockfiles @@ -341,5 +340,4 @@ def pinned_requirement(name) # :nodoc: def unget(token) # :nodoc: @tokens.unshift token end - end diff --git a/ruby/lib/rubygems/request_set/lockfile/tokenizer.rb b/ruby/lib/rubygems/request_set/lockfile/tokenizer.rb index 97396ec19..cb8030c14 100644 --- a/ruby/lib/rubygems/request_set/lockfile/tokenizer.rb +++ b/ruby/lib/rubygems/request_set/lockfile/tokenizer.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/request_set/lockfile/parser' +require_relative 'parser' class Gem::RequestSet::Lockfile::Tokenizer - Token = Struct.new :type, :value, :column, :line EOF = Token.new :EOF @@ -23,7 +22,7 @@ def make_parser(set, platforms) end def to_a - @tokens.map { |token| [token.type, token.value, token.column, token.line] } + @tokens.map {|token| [token.type, token.value, token.column, token.line] } end def skip(type) @@ -110,5 +109,4 @@ def tokenize(input) @tokens end - end diff --git a/ruby/lib/rubygems/requirement.rb b/ruby/lib/rubygems/requirement.rb index 1e17fc2dc..9edd6aa7d 100644 --- a/ruby/lib/rubygems/requirement.rb +++ b/ruby/lib/rubygems/requirement.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "rubygems/version" -require "rubygems/deprecate" +require_relative "version" ## # A Requirement is a set of one or more version restrictions. It supports a @@ -10,20 +9,19 @@ # together in RubyGems. class Gem::Requirement - OPS = { #:nodoc: - "=" => lambda { |v, r| v == r }, - "!=" => lambda { |v, r| v != r }, - ">" => lambda { |v, r| v > r }, - "<" => lambda { |v, r| v < r }, - ">=" => lambda { |v, r| v >= r }, - "<=" => lambda { |v, r| v <= r }, - "~>" => lambda { |v, r| v >= r && v.release < r.bump } + "=" => lambda {|v, r| v == r }, + "!=" => lambda {|v, r| v != r }, + ">" => lambda {|v, r| v > r }, + "<" => lambda {|v, r| v < r }, + ">=" => lambda {|v, r| v >= r }, + "<=" => lambda {|v, r| v <= r }, + "~>" => lambda {|v, r| v >= r && v.release < r.bump }, }.freeze SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc: - quoted = OPS.keys.map { |k| Regexp.quote k }.join "|" + quoted = OPS.keys.map {|k| Regexp.quote k }.join "|" PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc: ## @@ -113,7 +111,7 @@ def self.parse(obj) elsif $1 == ">=" && $2 == "0.a" DefaultPrereleaseRequirement else - [$1 || "=", Gem::Version.new($2)] + [-($1 || "="), Gem::Version.new($2)] end end @@ -137,7 +135,7 @@ def initialize(*requirements) if requirements.empty? @requirements = [DefaultRequirement] else - @requirements = requirements.map! { |r| self.class.parse r } + @requirements = requirements.map! {|r| self.class.parse r } end end @@ -148,7 +146,7 @@ def concat(new) new = new.flatten new.compact! new.uniq! - new = new.map { |r| self.class.parse r } + new = new.map {|r| self.class.parse r } @requirements.concat new end @@ -188,32 +186,27 @@ def exact? end def as_list # :nodoc: - requirements.map { |op, version| "#{op} #{version}" } + requirements.map {|op, version| "#{op} #{version}" } end def hash # :nodoc: - requirements.sort.hash + requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash end def marshal_dump # :nodoc: - fix_syck_default_key_in_requirements - [@requirements] end def marshal_load(array) # :nodoc: @requirements = array[0] - fix_syck_default_key_in_requirements + raise TypeError, "wrong @requirements" unless Array === @requirements end def yaml_initialize(tag, vals) # :nodoc: vals.each do |ivar, val| instance_variable_set "@#{ivar}", val end - - Gem.load_yaml - fix_syck_default_key_in_requirements end def init_with(coder) # :nodoc: @@ -233,7 +226,7 @@ def encode_with(coder) # :nodoc: # are prereleases def prerelease? - requirements.any? { |r| r.last.prerelease? } + requirements.any? {|r| r.last.prerelease? } end def pretty_print(q) # :nodoc: @@ -248,8 +241,7 @@ def pretty_print(q) # :nodoc: def satisfied_by?(version) raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless Gem::Version === version - # #28965: syck has a bug with unquoted '=' YAML.loading as YAML::DefaultKey - requirements.all? { |op, rv| (OPS[op] || OPS["="]).call version, rv } + requirements.all? {|op, rv| OPS[op].call version, rv } end alias :=== :satisfied_by? @@ -272,7 +264,7 @@ def ==(other) # :nodoc: return unless Gem::Requirement === other # An == check is always necessary - return false unless requirements == other.requirements + return false unless _sorted_requirements == other._sorted_requirements # An == check is sufficient unless any requirements use ~> return true unless _tilde_requirements.any? @@ -284,30 +276,18 @@ def ==(other) # :nodoc: protected - def _tilde_requirements - requirements.select { |r| r.first == "~>" } + def _sorted_requirements + @_sorted_requirements ||= requirements.sort_by(&:to_s) end - private - - def fix_syck_default_key_in_requirements # :nodoc: - Gem.load_yaml - - # Fixup the Syck DefaultKey bug - @requirements.each do |r| - if r[0].kind_of? Gem::SyckDefaultKey - r[0] = "=" - end - end + def _tilde_requirements + @_tilde_requirements ||= _sorted_requirements.select {|r| r.first == "~>" } end - end class Gem::Version - # This is needed for compatibility with older yaml # gemspecs. Requirement = Gem::Requirement # :nodoc: - end diff --git a/ruby/lib/rubygems/resolver.rb b/ruby/lib/rubygems/resolver.rb index ea9687bdb..51a11fed4 100644 --- a/ruby/lib/rubygems/resolver.rb +++ b/ruby/lib/rubygems/resolver.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/dependency' -require 'rubygems/exceptions' -require 'rubygems/util' -require 'rubygems/util/list' +require_relative 'dependency' +require_relative 'exceptions' +require_relative 'util/list' ## # Given a set of Gem::Dependency objects as +needed+ and a way to query the @@ -11,8 +10,7 @@ # all the requirements. class Gem::Resolver - - require 'rubygems/resolver/molinillo' + require_relative 'resolver/molinillo' ## # If the DEBUG_RESOLVER environment variable is set then debugging mode is @@ -116,7 +114,7 @@ def initialize(needed, set = nil) def explain(stage, *data) # :nodoc: return unless DEBUG_RESOLVER - d = data.map { |x| x.pretty_inspect }.join(", ") + d = data.map {|x| x.pretty_inspect }.join(", ") $stderr.printf "%10s %s\n", stage.to_s.upcase, d end @@ -189,7 +187,7 @@ def debug? def resolve locking_dg = Molinillo::DependencyGraph.new - Molinillo::Resolver.new(self, self).resolve(@needed.map { |d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact + Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact rescue Molinillo::VersionConflict => e conflict = e.conflicts.values.first raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement) @@ -206,7 +204,7 @@ def find_possible(dependency) # :nodoc: if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty? matching = all.select do |api_spec| - skip_dep_gems.any? { |s| api_spec.version == s.version } + skip_dep_gems.any? {|s| api_spec.version == s.version } end all = matching unless matching.empty? @@ -235,7 +233,7 @@ def search_for(dependency) raise exc end - groups = Hash.new { |hash, key| hash[key] = [] } + groups = Hash.new {|hash, key| hash[key] = [] } # create groups & sources in the same loop sources = possibles.map do |spec| @@ -248,9 +246,9 @@ def search_for(dependency) sources.each do |source| groups[source]. - sort_by { |spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }. - map { |spec| ActivationRequest.new spec, dependency }. - each { |activation_request| activation_requests << activation_request } + sort_by {|spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }. + map {|spec| ActivationRequest.new spec, dependency }. + each {|activation_request| activation_requests << activation_request } end activation_requests @@ -263,7 +261,12 @@ def dependencies_for(specification) end def requirement_satisfied_by?(requirement, activated, spec) - requirement.matches_spec? spec + matches_spec = requirement.matches_spec? spec + return matches_spec if @soft_missing + + matches_spec && + spec.spec.required_ruby_version.satisfied_by?(Gem.ruby_version) && + spec.spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version) end def name_for(dependency) @@ -283,7 +286,7 @@ def sort_dependencies(dependencies, activated, conflicts) amount_constrained(dependency), conflicts[name] ? 0 : 1, activated.vertex_named(name).payload ? 0 : search_for(dependency).count, - i # for stable sort + i, # for stable sort ] end end @@ -313,33 +316,32 @@ def amount_constrained(dependency) end end private :amount_constrained - end -require 'rubygems/resolver/activation_request' -require 'rubygems/resolver/conflict' -require 'rubygems/resolver/dependency_request' -require 'rubygems/resolver/requirement_list' -require 'rubygems/resolver/stats' - -require 'rubygems/resolver/set' -require 'rubygems/resolver/api_set' -require 'rubygems/resolver/composed_set' -require 'rubygems/resolver/best_set' -require 'rubygems/resolver/current_set' -require 'rubygems/resolver/git_set' -require 'rubygems/resolver/index_set' -require 'rubygems/resolver/installer_set' -require 'rubygems/resolver/lock_set' -require 'rubygems/resolver/vendor_set' -require 'rubygems/resolver/source_set' - -require 'rubygems/resolver/specification' -require 'rubygems/resolver/spec_specification' -require 'rubygems/resolver/api_specification' -require 'rubygems/resolver/git_specification' -require 'rubygems/resolver/index_specification' -require 'rubygems/resolver/installed_specification' -require 'rubygems/resolver/local_specification' -require 'rubygems/resolver/lock_specification' -require 'rubygems/resolver/vendor_specification' +require_relative 'resolver/activation_request' +require_relative 'resolver/conflict' +require_relative 'resolver/dependency_request' +require_relative 'resolver/requirement_list' +require_relative 'resolver/stats' + +require_relative 'resolver/set' +require_relative 'resolver/api_set' +require_relative 'resolver/composed_set' +require_relative 'resolver/best_set' +require_relative 'resolver/current_set' +require_relative 'resolver/git_set' +require_relative 'resolver/index_set' +require_relative 'resolver/installer_set' +require_relative 'resolver/lock_set' +require_relative 'resolver/vendor_set' +require_relative 'resolver/source_set' + +require_relative 'resolver/specification' +require_relative 'resolver/spec_specification' +require_relative 'resolver/api_specification' +require_relative 'resolver/git_specification' +require_relative 'resolver/index_specification' +require_relative 'resolver/installed_specification' +require_relative 'resolver/local_specification' +require_relative 'resolver/lock_specification' +require_relative 'resolver/vendor_specification' diff --git a/ruby/lib/rubygems/resolver/activation_request.rb b/ruby/lib/rubygems/resolver/activation_request.rb index 2a8d6032f..ae35681db 100644 --- a/ruby/lib/rubygems/resolver/activation_request.rb +++ b/ruby/lib/rubygems/resolver/activation_request.rb @@ -4,7 +4,6 @@ # dependency that was used to introduce this activation. class Gem::Resolver::ActivationRequest - ## # The parent request for this activation request. @@ -29,12 +28,20 @@ def ==(other) # :nodoc: when Gem::Specification @spec == other when Gem::Resolver::ActivationRequest - @spec == other.spec && @request == other.request + @spec == other.spec else false end end + def eql?(other) + self == other + end + + def hash + @spec.hash + end + ## # Is this activation request for a development dependency? @@ -152,5 +159,4 @@ def platform def name_tuple @name_tuple ||= Gem::NameTuple.new(name, version, platform) end - end diff --git a/ruby/lib/rubygems/resolver/api_set.rb b/ruby/lib/rubygems/resolver/api_set.rb index 6fd91e3b7..21c9b8920 100644 --- a/ruby/lib/rubygems/resolver/api_set.rb +++ b/ruby/lib/rubygems/resolver/api_set.rb @@ -4,6 +4,7 @@ # Returns instances of APISpecification. class Gem::Resolver::APISet < Gem::Resolver::Set + autoload :GemParser, File.expand_path("api_set/gem_parser", __dir__) ## # The URI for the dependency API this APISet uses. @@ -23,17 +24,17 @@ class Gem::Resolver::APISet < Gem::Resolver::Set ## # Creates a new APISet that will retrieve gems from +uri+ using the RubyGems # API URL +dep_uri+ which is described at - # http://guides.rubygems.org/rubygems-org-api + # https://guides.rubygems.org/rubygems-org-api - def initialize(dep_uri = 'https://rubygems.org/api/v1/dependencies') + def initialize(dep_uri = 'https://index.rubygems.org/info/') super() - dep_uri = URI dep_uri unless URI === dep_uri # for ruby 1.8 + dep_uri = URI dep_uri unless URI === dep_uri @dep_uri = dep_uri - @uri = dep_uri + '../..' + @uri = dep_uri + '..' - @data = Hash.new { |h,k| h[k] = [] } + @data = Hash.new {|h,k| h[k] = [] } @source = Gem::Source.new @uri @to_fetch = [] @@ -53,7 +54,7 @@ def find_all(req) end versions(req.name).each do |ver| - if req.dependency.match? req.name, ver[:number] + if req.dependency.match? req.name, ver[:number], @prerelease res << Gem::Resolver::APISpecification.new(self, ver) end end @@ -67,7 +68,7 @@ def find_all(req) def prefetch(reqs) return unless @remote - names = reqs.map { |r| r.dependency.name } + names = reqs.map {|r| r.dependency.name } needed = names - @data.keys - @to_fetch @to_fetch += needed @@ -76,20 +77,8 @@ def prefetch(reqs) def prefetch_now # :nodoc: needed, @to_fetch = @to_fetch, [] - uri = @dep_uri + "?gems=#{needed.sort.join ','}" - str = Gem::RemoteFetcher.fetcher.fetch_path uri - - loaded = [] - - Marshal.load(str).each do |ver| - name = ver[:name] - - @data[name] << ver - loaded << name - end - - (needed - loaded).each do |missing| - @data[missing] = [] + needed.sort.each do |name| + versions(name) end end @@ -112,14 +101,32 @@ def versions(name) # :nodoc: return @data[name] end - uri = @dep_uri + "?gems=#{name}" + uri = @dep_uri + name str = Gem::RemoteFetcher.fetcher.fetch_path uri - Marshal.load(str).each do |ver| - @data[ver[:name]] << ver + lines(str).each do |ver| + number, platform, dependencies, requirements = parse_gem(ver) + + platform ||= "ruby" + dependencies = dependencies.map {|dep_name, reqs| [dep_name, reqs.join(", ")] } + requirements = requirements.map {|req_name, reqs| [req_name.to_sym, reqs] }.to_h + + @data[name] << { name: name, number: number, platform: platform, dependencies: dependencies, requirements: requirements } end @data[name] end + private + + def lines(str) + lines = str.split("\n") + header = lines.index("---") + header ? lines[header + 1..-1] : lines + end + + def parse_gem(string) + @gem_parser ||= GemParser.new + @gem_parser.parse(string) + end end diff --git a/ruby/lib/rubygems/resolver/api_set/gem_parser.rb b/ruby/lib/rubygems/resolver/api_set/gem_parser.rb new file mode 100644 index 000000000..685c39558 --- /dev/null +++ b/ruby/lib/rubygems/resolver/api_set/gem_parser.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Gem::Resolver::APISet::GemParser + def parse(line) + version_and_platform, rest = line.split(" ", 2) + version, platform = version_and_platform.split("-", 2) + dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest + dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : [] + requirements = requirements ? requirements.map {|d| parse_dependency(d) } : [] + [version, platform, dependencies, requirements] + end + + private + + def parse_dependency(string) + dependency = string.split(":") + dependency[-1] = dependency[-1].split("&") if dependency.size > 1 + dependency + end +end diff --git a/ruby/lib/rubygems/resolver/api_specification.rb b/ruby/lib/rubygems/resolver/api_specification.rb index 9bbc09578..b5aa0b71d 100644 --- a/ruby/lib/rubygems/resolver/api_specification.rb +++ b/ruby/lib/rubygems/resolver/api_specification.rb @@ -6,12 +6,22 @@ # is the name, version, and dependencies. class Gem::Resolver::APISpecification < Gem::Resolver::Specification + ## + # We assume that all instances of this class are immutable; + # so avoid duplicated generation for performance. + @@cache = {} + def self.new(set, api_data) + cache_key = [set, api_data] + cache = @@cache[cache_key] + return cache if cache + @@cache[cache_key] = super + end ## # Creates an APISpecification for the given +set+ from the rubygems.org # +api_data+. # - # See http://guides.rubygems.org/rubygems-org-api/#misc_methods for the + # See https://guides.rubygems.org/rubygems-org-api/#misc_methods for the # format of the +api_data+. def initialize(set, api_data) @@ -19,12 +29,14 @@ def initialize(set, api_data) @set = set @name = api_data[:name] - @version = Gem::Version.new api_data[:number] - @platform = Gem::Platform.new api_data[:platform] - @original_platform = api_data[:platform] + @version = Gem::Version.new(api_data[:number]).freeze + @platform = Gem::Platform.new(api_data[:platform]).freeze + @original_platform = api_data[:platform].freeze @dependencies = api_data[:dependencies].map do |name, ver| - Gem::Dependency.new name, ver.split(/\s*,\s*/) - end + Gem::Dependency.new(name, ver.split(/\s*,\s*/)).freeze + end.freeze + @required_ruby_version = Gem::Requirement.new(api_data.dig(:requirements, :ruby)).freeze + @required_rubygems_version = Gem::Requirement.new(api_data.dig(:requirements, :rubygems)).freeze end def ==(other) # :nodoc: @@ -32,8 +44,11 @@ def ==(other) # :nodoc: @set == other.set and @name == other.name and @version == other.version and - @platform == other.platform and - @dependencies == other.dependencies + @platform == other.platform + end + + def hash + @set.hash ^ @name.hash ^ @version.hash ^ @platform.hash end def fetch_development_dependencies # :nodoc: @@ -43,7 +58,7 @@ def fetch_development_dependencies # :nodoc: end def installable_platform? # :nodoc: - Gem::Platform.match @platform + Gem::Platform.match_gem? @platform, @name end def pretty_print(q) # :nodoc: @@ -86,5 +101,4 @@ def spec # :nodoc: def source # :nodoc: @set.source end - end diff --git a/ruby/lib/rubygems/resolver/best_set.rb b/ruby/lib/rubygems/resolver/best_set.rb index 8a8c15d9a..300ea8015 100644 --- a/ruby/lib/rubygems/resolver/best_set.rb +++ b/ruby/lib/rubygems/resolver/best_set.rb @@ -5,7 +5,6 @@ # It combines IndexSet and APISet class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet - ## # Creates a BestSet for the given +sources+ or Gem::sources if none are # specified. +sources+ must be a Gem::SourceList. @@ -59,9 +58,9 @@ def pretty_print(q) # :nodoc: # The calling method must retry the exception to repeat the lookup. def replace_failed_api_set(error) # :nodoc: - uri = error.uri + uri = error.original_uri uri = URI uri unless URI === uri - uri.query = nil + uri = uri + "." raise error unless api_set = @sets.find do |set| Gem::Resolver::APISet === set and set.dep_uri == uri @@ -74,5 +73,4 @@ def replace_failed_api_set(error) # :nodoc: index_set end end - end diff --git a/ruby/lib/rubygems/resolver/composed_set.rb b/ruby/lib/rubygems/resolver/composed_set.rb index 4baac9c75..226da1e1e 100644 --- a/ruby/lib/rubygems/resolver/composed_set.rb +++ b/ruby/lib/rubygems/resolver/composed_set.rb @@ -9,7 +9,6 @@ # This method will eliminate nesting of composed sets. class Gem::Resolver::ComposedSet < Gem::Resolver::Set - attr_reader :sets # :nodoc: ## @@ -40,11 +39,11 @@ def prerelease=(allow_prerelease) def remote=(remote) super - @sets.each { |set| set.remote = remote } + @sets.each {|set| set.remote = remote } end def errors - @errors + @sets.map { |set| set.errors }.flatten + @errors + @sets.map {|set| set.errors }.flatten end ## @@ -60,7 +59,6 @@ def find_all(req) # Prefetches +reqs+ in all sets. def prefetch(reqs) - @sets.each { |s| s.prefetch(reqs) } + @sets.each {|s| s.prefetch(reqs) } end - end diff --git a/ruby/lib/rubygems/resolver/conflict.rb b/ruby/lib/rubygems/resolver/conflict.rb index 2b337db33..4c4588d7e 100644 --- a/ruby/lib/rubygems/resolver/conflict.rb +++ b/ruby/lib/rubygems/resolver/conflict.rb @@ -4,7 +4,6 @@ # with a spec that would be activated. class Gem::Resolver::Conflict - ## # The specification that was activated prior to the conflict @@ -55,7 +54,7 @@ def explanation activated = @activated.spec.full_name dependency = @failed_dep.dependency requirement = dependency.requirement - alternates = dependency.matching_specs.map { |spec| spec.full_name } + alternates = dependency.matching_specs.map {|spec| spec.full_name } unless alternates.empty? matching = <<-MATCHING.chomp @@ -86,7 +85,7 @@ def explanation activated, requirement, request_path(@activated).reverse.join(", depends on\n "), request_path(@failed_dep).reverse.join(", depends on\n "), - matching, + matching ] end @@ -151,5 +150,4 @@ def request_path(current) def requester @failed_dep.requester end - end diff --git a/ruby/lib/rubygems/resolver/current_set.rb b/ruby/lib/rubygems/resolver/current_set.rb index d60e46389..c3aa3a2c3 100644 --- a/ruby/lib/rubygems/resolver/current_set.rb +++ b/ruby/lib/rubygems/resolver/current_set.rb @@ -5,9 +5,7 @@ # for installed gems. class Gem::Resolver::CurrentSet < Gem::Resolver::Set - def find_all(req) req.dependency.matching_specs end - end diff --git a/ruby/lib/rubygems/resolver/dependency_request.rb b/ruby/lib/rubygems/resolver/dependency_request.rb index 1984aa9dd..356aadb3b 100644 --- a/ruby/lib/rubygems/resolver/dependency_request.rb +++ b/ruby/lib/rubygems/resolver/dependency_request.rb @@ -4,7 +4,6 @@ # contained the Dependency. class Gem::Resolver::DependencyRequest - ## # The wrapped Gem::Dependency @@ -29,7 +28,7 @@ def ==(other) # :nodoc: when Gem::Dependency @dependency == other when Gem::Resolver::DependencyRequest - @dependency == other.dependency && @requester == other.requester + @dependency == other.dependency else false end @@ -116,5 +115,4 @@ def requirement def to_s # :nodoc: @dependency.to_s end - end diff --git a/ruby/lib/rubygems/resolver/git_set.rb b/ruby/lib/rubygems/resolver/git_set.rb index 6340b92fa..eac51f15a 100644 --- a/ruby/lib/rubygems/resolver/git_set.rb +++ b/ruby/lib/rubygems/resolver/git_set.rb @@ -10,7 +10,6 @@ # set.add_git_gem 'rake', 'git://example/rake.git', tag: 'rake-10.1.0' class Gem::Resolver::GitSet < Gem::Resolver::Set - ## # The root directory for git gems in this set. This is usually Gem.dir, the # installation directory for regular gems. @@ -118,5 +117,4 @@ def pretty_print(q) # :nodoc: end end end - end diff --git a/ruby/lib/rubygems/resolver/git_specification.rb b/ruby/lib/rubygems/resolver/git_specification.rb index f43cfba85..ee47080ab 100644 --- a/ruby/lib/rubygems/resolver/git_specification.rb +++ b/ruby/lib/rubygems/resolver/git_specification.rb @@ -5,7 +5,6 @@ # option. class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification - def ==(other) # :nodoc: self.class === other and @set == other.set and @@ -22,7 +21,7 @@ def add_dependency(dependency) # :nodoc: # the executables. def install(options = {}) - require 'rubygems/installer' + require_relative '../installer' installer = Gem::Installer.for_spec spec, options @@ -54,5 +53,4 @@ def pretty_print(q) # :nodoc: q.pp @source end end - end diff --git a/ruby/lib/rubygems/resolver/index_set.rb b/ruby/lib/rubygems/resolver/index_set.rb index e32e1fa5b..9390e3425 100644 --- a/ruby/lib/rubygems/resolver/index_set.rb +++ b/ruby/lib/rubygems/resolver/index_set.rb @@ -4,7 +4,6 @@ # source index. class Gem::Resolver::IndexSet < Gem::Resolver::Set - def initialize(source = nil) # :nodoc: super() @@ -17,7 +16,7 @@ def initialize(source = nil) # :nodoc: Gem::SpecFetcher.fetcher end - @all = Hash.new { |h,k| h[k] = [] } + @all = Hash.new {|h,k| h[k] = [] } list, errors = @f.available_specs :complete @@ -76,5 +75,4 @@ def pretty_print(q) # :nodoc: end end end - end diff --git a/ruby/lib/rubygems/resolver/index_specification.rb b/ruby/lib/rubygems/resolver/index_specification.rb index ed9423791..9ea76f40b 100644 --- a/ruby/lib/rubygems/resolver/index_specification.rb +++ b/ruby/lib/rubygems/resolver/index_specification.rb @@ -5,7 +5,6 @@ # and +version+ are needed. class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification - ## # An IndexSpecification is created from the index format described in `gem # help generate_index`. @@ -34,6 +33,38 @@ def dependencies spec.dependencies end + ## + # The required_ruby_version constraint for this specification + # + # A fallback is included because when generated, some marshalled specs have it + # set to +nil+. + + def required_ruby_version + spec.required_ruby_version || Gem::Requirement.default + end + + ## + # The required_rubygems_version constraint for this specification + # + # A fallback is included because the original version of the specification + # API didn't include that field, so some marshalled specs in the index have it + # set to +nil+. + + def required_rubygems_version + spec.required_rubygems_version || Gem::Requirement.default + end + + def ==(other) + self.class === other && + @name == other.name && + @version == other.version && + @platform == other.platform + end + + def hash + @name.hash ^ @version.hash ^ @platform.hash + end + def inspect # :nodoc: '#<%s %s source %s>' % [self.class, full_name, @source] end @@ -65,5 +96,4 @@ def spec # :nodoc: @source.fetch_spec tuple end end - end diff --git a/ruby/lib/rubygems/resolver/installed_specification.rb b/ruby/lib/rubygems/resolver/installed_specification.rb index 9d996fc1d..167ba1439 100644 --- a/ruby/lib/rubygems/resolver/installed_specification.rb +++ b/ruby/lib/rubygems/resolver/installed_specification.rb @@ -4,7 +4,6 @@ # locally. class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification - def ==(other) # :nodoc: self.class === other and @set == other.set and @@ -54,5 +53,4 @@ def pretty_print(q) # :nodoc: def source @source ||= Gem::Source::Installed.new end - end diff --git a/ruby/lib/rubygems/resolver/installer_set.rb b/ruby/lib/rubygems/resolver/installer_set.rb index ba14ee945..45252ed24 100644 --- a/ruby/lib/rubygems/resolver/installer_set.rb +++ b/ruby/lib/rubygems/resolver/installer_set.rb @@ -4,7 +4,6 @@ # files class Gem::Resolver::InstallerSet < Gem::Resolver::Set - ## # List of Gem::Specification objects that must always be installed. @@ -26,6 +25,12 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set attr_reader :remote_set # :nodoc: + ## + # Ignore ruby & rubygems specification constraints. + # + + attr_accessor :force # :nodoc: + ## # Creates a new InstallerSet that will look for gems in +domain+. @@ -33,7 +38,6 @@ def initialize(domain) super() @domain = domain - @remote = consider_remote? @f = Gem::SpecFetcher.fetcher @@ -43,6 +47,7 @@ def initialize(domain) @local = {} @local_source = Gem::Source::Local.new @remote_set = Gem::Resolver::BestSet.new + @force = false @specs = {} end @@ -65,15 +70,30 @@ def add_always_install(dependency) Gem::Platform.local === s.platform end - if found.empty? + found = found.sort_by do |s| + [s.version, Gem::Platform.sort_priority(s.platform)] + end + + newest = found.last + + unless newest exc = Gem::UnsatisfiableDependencyError.new request exc.errors = errors raise exc end - newest = found.max_by do |s| - [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1] + unless @force + found_matching_metadata = found.reverse.find do |spec| + metadata_satisfied?(spec) + end + + if found_matching_metadata.nil? + ensure_required_ruby_version_met(newest.spec) + ensure_required_rubygems_version_met(newest.spec) + else + newest = found_matching_metadata + end end @always_install << newest.spec @@ -118,12 +138,12 @@ def find_all(req) dep = req.dependency return res if @ignore_dependencies and - @always_install.none? { |spec| dep.match? spec } + @always_install.none? {|spec| dep.match? spec } name = dep.name dep.matching_specs.each do |gemspec| - next if @always_install.any? { |spec| spec.name == gemspec.name } + next if @always_install.any? {|spec| spec.name == gemspec.name } res << Gem::Resolver::InstalledSpecification.new(self, gemspec) end unless @ignore_installed @@ -168,10 +188,10 @@ def prerelease=(allow_prerelease) end def inspect # :nodoc: - always_install = @always_install.map { |s| s.full_name } + always_install = @always_install.map {|s| s.full_name } '#<%s domain: %s specs: %p always install: %p>' % [ - self.class, @domain, @specs.keys, always_install, + self.class, @domain, @specs.keys, always_install ] end @@ -224,4 +244,31 @@ def remote=(remote) # :nodoc: end end + private + + def metadata_satisfied?(spec) + spec.required_ruby_version.satisfied_by?(Gem.ruby_version) && + spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version) + end + + def ensure_required_ruby_version_met(spec) # :nodoc: + if rrv = spec.required_ruby_version + ruby_version = Gem.ruby_version + unless rrv.satisfied_by? ruby_version + raise Gem::RuntimeRequirementNotMetError, + "#{spec.full_name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}." + end + end + end + + def ensure_required_rubygems_version_met(spec) # :nodoc: + if rrgv = spec.required_rubygems_version + unless rrgv.satisfied_by? Gem.rubygems_version + rg_version = Gem::VERSION + raise Gem::RuntimeRequirementNotMetError, + "#{spec.full_name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " + + "Try 'gem update --system' to update RubyGems itself." + end + end + end end diff --git a/ruby/lib/rubygems/resolver/local_specification.rb b/ruby/lib/rubygems/resolver/local_specification.rb index 7418cfcc8..9c69c4ab7 100644 --- a/ruby/lib/rubygems/resolver/local_specification.rb +++ b/ruby/lib/rubygems/resolver/local_specification.rb @@ -3,7 +3,6 @@ # A LocalSpecification comes from a .gem file on the local filesystem. class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification - ## # Returns +true+ if this gem is installable for the current platform. @@ -37,5 +36,4 @@ def pretty_print(q) # :nodoc: q.text "source: #{@source.path}" end end - end diff --git a/ruby/lib/rubygems/resolver/lock_set.rb b/ruby/lib/rubygems/resolver/lock_set.rb index 4134b4dca..eabf217ab 100644 --- a/ruby/lib/rubygems/resolver/lock_set.rb +++ b/ruby/lib/rubygems/resolver/lock_set.rb @@ -3,7 +3,6 @@ # A set of gems from a gem dependencies lockfile. class Gem::Resolver::LockSet < Gem::Resolver::Set - attr_reader :specs # :nodoc: ## @@ -29,7 +28,7 @@ def initialize(sources) def add(name, version, platform) # :nodoc: version = Gem::Version.new version specs = [ - Gem::Resolver::LockSpecification.new(self, name, version, @sources, platform) + Gem::Resolver::LockSpecification.new(self, name, version, @sources, platform), ] @specs.concat specs @@ -75,8 +74,7 @@ def pretty_print(q) # :nodoc: q.text 'specs:' q.breakable - q.pp @specs.map { |spec| spec.full_name } + q.pp @specs.map {|spec| spec.full_name } end end - end diff --git a/ruby/lib/rubygems/resolver/lock_specification.rb b/ruby/lib/rubygems/resolver/lock_specification.rb index 5954507db..cdb8e4e42 100644 --- a/ruby/lib/rubygems/resolver/lock_specification.rb +++ b/ruby/lib/rubygems/resolver/lock_specification.rb @@ -6,7 +6,6 @@ # lockfile. class Gem::Resolver::LockSpecification < Gem::Resolver::Specification - attr_reader :sources def initialize(set, name, version, sources, platform) @@ -83,5 +82,4 @@ def spec s.dependencies.concat @dependencies end end - end diff --git a/ruby/lib/rubygems/resolver/molinillo.rb b/ruby/lib/rubygems/resolver/molinillo.rb index 2357f41be..12ca740e5 100644 --- a/ruby/lib/rubygems/resolver/molinillo.rb +++ b/ruby/lib/rubygems/resolver/molinillo.rb @@ -1,2 +1,2 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo' +require_relative 'molinillo/lib/molinillo' diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo.rb index 0ae4b6a91..f67badbde 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/gem_metadata' -require 'rubygems/resolver/molinillo/lib/molinillo/errors' -require 'rubygems/resolver/molinillo/lib/molinillo/resolver' -require 'rubygems/resolver/molinillo/lib/molinillo/modules/ui' -require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider' + +require_relative 'molinillo/gem_metadata' +require_relative 'molinillo/errors' +require_relative 'molinillo/resolver' +require_relative 'molinillo/modules/ui' +require_relative 'molinillo/modules/specification_provider' # Gem::Resolver::Molinillo is a generic dependency resolution algorithm. module Gem::Resolver::Molinillo diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb index 1bbc72c1f..d540d3baf 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo # @!visibility private module Delegates @@ -45,6 +46,12 @@ def conflicts current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty current_state.conflicts end + + # (see Gem::Resolver::Molinillo::ResolutionState#unused_unwind_options) + def unused_unwind_options + current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty + current_state.unused_unwind_options + end end end end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb index 71903c7e8..b765226fb 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo module Delegates # Delegates all {Gem::Resolver::Molinillo::SpecificationProvider} methods to a @@ -25,6 +26,13 @@ def requirement_satisfied_by?(requirement, activated, spec) end end + # (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_equal?) + def dependencies_equal?(dependencies, other_dependencies) + with_no_such_dependency_error_handling do + specification_provider.dependencies_equal?(dependencies, other_dependencies) + end + end + # (see Gem::Resolver::Molinillo::SpecificationProvider#name_for) def name_for(dependency) with_no_such_dependency_error_handling do diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb index b413e3ab6..95f8416b9 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'set' -require 'tsort' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex' +require_relative '../../../../tsort' + +require_relative 'dependency_graph/log' +require_relative 'dependency_graph/vertex' module Gem::Resolver::Molinillo # A directed acyclic graph that is tuned to hold named dependencies @@ -17,7 +17,7 @@ def each vertices.values.each { |v| yield v } end - include TSort + include Gem::TSort # @!visibility private alias tsort_each_node each @@ -123,6 +123,7 @@ def to_dot(options = {}) dot.join("\n") end + # @param [DependencyGraph] other # @return [Boolean] whether the two dependency graphs are equal, determined # by a recursive traversal of each {#root_vertices} and its # {Vertex#successors} @@ -147,8 +148,8 @@ def add_child_vertex(name, payload, parent_names, requirement) vertex = add_vertex(name, payload, root) vertex.explicit_requirements << requirement if root parent_names.each do |parent_name| - parent_node = vertex_named(parent_name) - add_edge(parent_node, vertex, requirement) + parent_vertex = vertex_named(parent_name) + add_edge(parent_vertex, vertex, requirement) end vertex end @@ -189,7 +190,7 @@ def root_vertex_named(name) # @return [Edge] the added edge def add_edge(origin, destination, requirement) if destination.path_to?(origin) - raise CircularDependencyError.new([origin, destination]) + raise CircularDependencyError.new(path(destination, origin)) end add_edge_no_circular(origin, destination, requirement) end @@ -218,5 +219,37 @@ def set_payload(name, payload) def add_edge_no_circular(origin, destination, requirement) log.add_edge_no_circular(self, origin.name, destination.name, requirement) end + + # Returns the path between two vertices + # @raise [ArgumentError] if there is no path between the vertices + # @param [Vertex] from + # @param [Vertex] to + # @return [Array] the shortest path from `from` to `to` + def path(from, to) + distances = Hash.new(vertices.size + 1) + distances[from.name] = 0 + predecessors = {} + each do |vertex| + vertex.successors.each do |successor| + if distances[successor.name] > distances[vertex.name] + 1 + distances[successor.name] = distances[vertex.name] + 1 + predecessors[successor] = vertex + end + end + end + + path = [to] + while before = predecessors[to] + path << before + to = before + break if to == from + end + + unless path.last.equal?(from) + raise ArgumentError, "There is no path from #{from.name} to #{to.name}" + end + + path.reverse + end end end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb index eeedabb06..cc140031b 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo class DependencyGraph # An action that modifies a {DependencyGraph} that is reversible. diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb index e994e59d0..557048325 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb index 6cde93308..f1411d5ef 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb index d44aaf1f0..3b48d77a5 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb index fa03e2d36..92f60d5be 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb index 5cdd84b5c..7aeb8847e 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload' -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag' + +require_relative 'add_edge_no_circular' +require_relative 'add_vertex' +require_relative 'delete_edge' +require_relative 'detach_vertex_named' +require_relative 'set_payload' +require_relative 'tag' module Gem::Resolver::Molinillo class DependencyGraph diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb index 02cfba64a..726292a2c 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb index 0cb08075c..bfe6fd31f 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action' + +require_relative 'action' module Gem::Resolver::Molinillo class DependencyGraph # @!visibility private @@ -13,11 +14,11 @@ def self.action_name end # (see Action#up) - def up(_graph) + def up(graph) end # (see Action#down) - def down(_graph) + def down(graph) end # @!group Tag diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb index cebd9cafd..77114951b 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo class DependencyGraph # A vertex in a {DependencyGraph} that encapsulates a {#name} and a @@ -32,7 +33,7 @@ def initialize(name, payload) # @return [Array] all of the requirements that required # this vertex def requirements - incoming_edges.map(&:requirement) + explicit_requirements + (incoming_edges.map(&:requirement) + explicit_requirements).uniq end # @return [Array] the edges of {#graph} that have `self` as their @@ -49,14 +50,25 @@ def predecessors incoming_edges.map(&:origin) end - # @return [Array] the vertices of {#graph} where `self` is a + # @return [Set] the vertices of {#graph} where `self` is a # {#descendent?} def recursive_predecessors - vertices = predecessors - vertices += vertices.map(&:recursive_predecessors).flatten(1) - vertices.uniq! + _recursive_predecessors + end + + # @param [Set] vertices the set to add the predecessors to + # @return [Set] the vertices of {#graph} where `self` is a + # {#descendent?} + def _recursive_predecessors(vertices = new_vertex_set) + incoming_edges.each do |edge| + vertex = edge.origin + next unless vertices.add?(vertex) + vertex._recursive_predecessors(vertices) + end + vertices end + protected :_recursive_predecessors # @return [Array] the vertices of {#graph} that have an edge with # `self` as their {Edge#origin} @@ -64,14 +76,25 @@ def successors outgoing_edges.map(&:destination) end - # @return [Array] the vertices of {#graph} where `self` is an + # @return [Set] the vertices of {#graph} where `self` is an # {#ancestor?} def recursive_successors - vertices = successors - vertices += vertices.map(&:recursive_successors).flatten(1) - vertices.uniq! + _recursive_successors + end + + # @param [Set] vertices the set to add the successors to + # @return [Set] the vertices of {#graph} where `self` is an + # {#ancestor?} + def _recursive_successors(vertices = new_vertex_set) + outgoing_edges.each do |edge| + vertex = edge.destination + next unless vertices.add?(vertex) + vertex._recursive_successors(vertices) + end + vertices end + protected :_recursive_successors # @return [String] a string suitable for debugging def inspect @@ -105,21 +128,37 @@ def hash # Is there a path from `self` to `other` following edges in the # dependency graph? - # @return true iff there is a path following edges within this {#graph} + # @return whether there is a path following edges within this {#graph} def path_to?(other) - equal?(other) || successors.any? { |v| v.path_to?(other) } + _path_to?(other) end alias descendent? path_to? + # @param [Vertex] other the vertex to check if there's a path to + # @param [Set] visited the vertices of {#graph} that have been visited + # @return [Boolean] whether there is a path to `other` from `self` + def _path_to?(other, visited = new_vertex_set) + return false unless visited.add?(self) + return true if equal?(other) + successors.any? { |v| v._path_to?(other, visited) } + end + protected :_path_to? + # Is there a path from `other` to `self` following edges in the # dependency graph? - # @return true iff there is a path following edges within this {#graph} + # @return whether there is a path following edges within this {#graph} def ancestor?(other) other.path_to?(self) end alias is_reachable_from? ancestor? + + def new_vertex_set + require 'set' + Set.new + end + private :new_vertex_set end end end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb index 129246bf4..ada03a901 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo # An error that occurred during the resolution process class ResolverError < StandardError; end @@ -17,7 +18,7 @@ class NoSuchDependencyError < ResolverError # @param [Array] required_by @see {#required_by} def initialize(dependency, required_by = []) @dependency = dependency - @required_by = required_by + @required_by = required_by.uniq super() end @@ -33,7 +34,7 @@ def message # An error caused by attempting to fulfil a dependency that was circular # - # @note This exception will be thrown iff a {Vertex} is added to a + # @note This exception will be thrown if and only if a {Vertex} is added to a # {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an # existing {DependencyGraph::Vertex} class CircularDependencyError < ResolverError @@ -41,11 +42,11 @@ class CircularDependencyError < ResolverError attr_reader :dependencies # Initializes a new error with the given circular vertices. - # @param [Array] nodes the nodes in the dependency + # @param [Array] vertices the vertices in the dependency # that caused the error - def initialize(nodes) - super "There is a circular dependency between #{nodes.map(&:name).join(' and ')}" - @dependencies = nodes.map(&:payload).to_set + def initialize(vertices) + super "There is a circular dependency between #{vertices.map(&:name).join(' and ')}" + @dependencies = vertices.map { |vertex| vertex.payload.possibilities.last }.to_set end end @@ -55,11 +56,16 @@ class VersionConflict < ResolverError # resolution to fail attr_reader :conflicts + # @return [SpecificationProvider] the specification provider used during + # resolution + attr_reader :specification_provider + # Initializes a new error with the given version conflicts. # @param [{String => Resolution::Conflict}] conflicts see {#conflicts} - def initialize(conflicts) + # @param [SpecificationProvider] specification_provider see {#specification_provider} + def initialize(conflicts, specification_provider) pairs = [] - conflicts.values.flatten.map(&:requirements).flatten.each do |conflicting| + conflicts.values.flat_map(&:requirements).each do |conflicting| conflicting.each do |source, conflict_requirements| conflict_requirements.each do |c| pairs << [c, source] @@ -69,7 +75,69 @@ def initialize(conflicts) super "Unable to satisfy the following requirements:\n\n" \ "#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}" + @conflicts = conflicts + @specification_provider = specification_provider + end + + require_relative 'delegates/specification_provider' + include Delegates::SpecificationProvider + + # @return [String] An error message that includes requirement trees, + # which is much more detailed & customizable than the default message + # @param [Hash] opts the options to create a message with. + # @option opts [String] :solver_name The user-facing name of the solver + # @option opts [String] :possibility_type The generic name of a possibility + # @option opts [Proc] :reduce_trees A proc that reduced the list of requirement trees + # @option opts [Proc] :printable_requirement A proc that pretty-prints requirements + # @option opts [Proc] :additional_message_for_conflict A proc that appends additional + # messages for each conflict + # @option opts [Proc] :version_for_spec A proc that returns the version number for a + # possibility + def message_with_trees(opts = {}) + solver_name = opts.delete(:solver_name) { self.class.name.split('::').first } + possibility_type = opts.delete(:possibility_type) { 'possibility named' } + reduce_trees = opts.delete(:reduce_trees) { proc { |trees| trees.uniq.sort_by(&:to_s) } } + printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } } + additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc {} } + version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) } + incompatible_version_message_for_conflict = opts.delete(:incompatible_version_message_for_conflict) do + proc do |name, _conflict| + %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":) + end + end + + conflicts.sort.reduce(''.dup) do |o, (name, conflict)| + o << "\n" << incompatible_version_message_for_conflict.call(name, conflict) << "\n" + if conflict.locked_requirement + o << %( In snapshot (#{name_for_locking_dependency_source}):\n) + o << %( #{printable_requirement.call(conflict.locked_requirement)}\n) + o << %(\n) + end + o << %( In #{name_for_explicit_dependency_source}:\n) + trees = reduce_trees.call(conflict.requirement_trees) + + o << trees.map do |tree| + t = ''.dup + depth = 2 + tree.each do |req| + t << ' ' * depth << printable_requirement.call(req) + unless tree.last == req + if spec = conflict.activated_by_name[name_for(req)] + t << %( was resolved to #{version_for_spec.call(spec)}, which) + end + t << %( depends on) + end + t << %(\n) + depth += 1 + end + t + end.join("\n") + + additional_message_for_conflict.call(o, name, conflict) + + o + end.strip end end end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb index c5b5bd729..6b5ada7ad 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo # The version of Gem::Resolver::Molinillo. - VERSION = '0.5.7'.freeze + VERSION = '0.7.0'.freeze end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb index 916345b12..1067bf743 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo - # Provides information about specifcations and dependencies to the resolver, + # Provides information about specifications and dependencies to the resolver, # allowing the {Resolver} class to remain generic while still providing power # and flexibility. # @@ -44,6 +45,17 @@ def requirement_satisfied_by?(requirement, activated, spec) true end + # Determines whether two arrays of dependencies are equal, and thus can be + # grouped. + # + # @param [Array] dependencies + # @param [Array] other_dependencies + # @return [Boolean] whether `dependencies` and `other_dependencies` should + # be considered equal. + def dependencies_equal?(dependencies, other_dependencies) + dependencies == other_dependencies + end + # Returns the name for the given `dependency`. # @note This method should be 'pure', i.e. the return value should depend # only on the `dependency` parameter. diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb index dbc4e000e..a810fd519 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo # Conveys information about the resolution process to a user. module UI @@ -48,7 +49,8 @@ def debug(depth = 0) if debug? debug_info = yield debug_info = debug_info.inspect unless debug_info.is_a?(String) - output.puts debug_info.split("\n").map { |s| ' ' * depth + s } + debug_info = debug_info.split("\n").map { |s| ":#{depth.to_s.rjust 4}: #{s}" } + output.puts debug_info end end diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb index 73a424215..8b40e59e4 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo class Resolver # A specific resolution from a given {Resolver} @@ -8,22 +9,125 @@ class Resolution # @attr [{String,Nil=>[Object]}] requirements the requirements that caused the conflict # @attr [Object, nil] existing the existing spec that was in conflict with # the {#possibility} - # @attr [Object] possibility the spec that was unable to be activated due - # to a conflict + # @attr [Object] possibility_set the set of specs that was unable to be + # activated due to a conflict. # @attr [Object] locked_requirement the relevant locking requirement. # @attr [Array>] requirement_trees the different requirement # trees that led to every requirement for the conflicting name. # @attr [{String=>Object}] activated_by_name the already-activated specs. + # @attr [Object] underlying_error an error that has occurred during resolution, and + # will be raised at the end of it if no resolution is found. Conflict = Struct.new( :requirement, :requirements, :existing, - :possibility, + :possibility_set, :locked_requirement, :requirement_trees, - :activated_by_name + :activated_by_name, + :underlying_error ) + class Conflict + # @return [Object] a spec that was unable to be activated due to a conflict + def possibility + possibility_set && possibility_set.latest_version + end + end + + # A collection of possibility states that share the same dependencies + # @attr [Array] dependencies the dependencies for this set of possibilities + # @attr [Array] possibilities the possibilities + PossibilitySet = Struct.new(:dependencies, :possibilities) + + class PossibilitySet + # String representation of the possibility set, for debugging + def to_s + "[#{possibilities.join(', ')}]" + end + + # @return [Object] most up-to-date dependency in the possibility set + def latest_version + possibilities.last + end + end + + # Details of the state to unwind to when a conflict occurs, and the cause of the unwind + # @attr [Integer] state_index the index of the state to unwind to + # @attr [Object] state_requirement the requirement of the state we're unwinding to + # @attr [Array] requirement_tree for the requirement we're relaxing + # @attr [Array] conflicting_requirements the requirements that combined to cause the conflict + # @attr [Array] requirement_trees for the conflict + # @attr [Array] requirements_unwound_to_instead array of unwind requirements that were chosen over this unwind + UnwindDetails = Struct.new( + :state_index, + :state_requirement, + :requirement_tree, + :conflicting_requirements, + :requirement_trees, + :requirements_unwound_to_instead + ) + + class UnwindDetails + include Comparable + + # We compare UnwindDetails when choosing which state to unwind to. If + # two options have the same state_index we prefer the one most + # removed from a requirement that caused the conflict. Both options + # would unwind to the same state, but a `grandparent` option will + # filter out fewer of its possibilities after doing so - where a state + # is both a `parent` and a `grandparent` to requirements that have + # caused a conflict this is the correct behaviour. + # @param [UnwindDetail] other UnwindDetail to be compared + # @return [Integer] integer specifying ordering + def <=>(other) + if state_index > other.state_index + 1 + elsif state_index == other.state_index + reversed_requirement_tree_index <=> other.reversed_requirement_tree_index + else + -1 + end + end + + # @return [Integer] index of state requirement in reversed requirement tree + # (the conflicting requirement itself will be at position 0) + def reversed_requirement_tree_index + @reversed_requirement_tree_index ||= + if state_requirement + requirement_tree.reverse.index(state_requirement) + else + 999_999 + end + end + + # @return [Boolean] where the requirement of the state we're unwinding + # to directly caused the conflict. Note: in this case, it is + # impossible for the state we're unwinding to to be a parent of + # any of the other conflicting requirements (or we would have + # circularity) + def unwinding_to_primary_requirement? + requirement_tree.last == state_requirement + end + + # @return [Array] array of sub-dependencies to avoid when choosing a + # new possibility for the state we've unwound to. Only relevant for + # non-primary unwinds + def sub_dependencies_to_avoid + @requirements_to_avoid ||= + requirement_trees.map do |tree| + index = tree.index(state_requirement) + tree[index + 1] if index + end.compact + end + + # @return [Array] array of all the requirements that led to the need for + # this unwind + def all_requirements + @all_requirements ||= requirement_trees.flatten(1) + end + end + # @return [SpecificationProvider] the provider that knows about # dependencies, requirements, specifications, versions, etc. attr_reader :specification_provider @@ -64,7 +168,7 @@ def resolve start_resolution while state - break unless state.requirements.any? || state.requirement + break if !state.requirement && state.requirements.empty? indicate_progress if state.respond_to?(:pop_possibility_state) # DependencyState debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" } @@ -78,7 +182,7 @@ def resolve process_topmost_state end - activated.freeze + resolve_activated_specs ensure end_resolution end @@ -103,12 +207,25 @@ def resolve def start_resolution @started_at = Time.now - handle_missing_or_push_dependency_state(initial_state) + push_initial_state debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" } resolver_ui.before_resolution end + def resolve_activated_specs + activated.vertices.each do |_, vertex| + next unless vertex.payload + + latest_version = vertex.payload.possibilities.reverse_each.find do |possibility| + vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) } + end + + activated.set_payload(vertex.name, latest_version) + end + activated.freeze + end + # Ends the resolution process # @return [void] def end_resolution @@ -121,11 +238,11 @@ def end_resolution debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state end - require 'rubygems/resolver/molinillo/lib/molinillo/state' - require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider' + require_relative 'state' + require_relative 'modules/specification_provider' - require 'rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state' - require 'rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider' + require_relative 'delegates/resolution_state' + require_relative 'delegates/specification_provider' include Gem::Resolver::Molinillo::Delegates::ResolutionState include Gem::Resolver::Molinillo::Delegates::SpecificationProvider @@ -136,9 +253,12 @@ def process_topmost_state if possibility attempt_to_activate else - create_conflict if state.is_a? PossibilityState - unwind_for_conflict until possibility && state.is_a?(DependencyState) + create_conflict + unwind_for_conflict end + rescue CircularDependencyError => underlying_error + create_conflict(underlying_error) + unwind_for_conflict end # @return [Object] the current possibility that the resolution is trying @@ -153,63 +273,296 @@ def state states.last end - # Creates the initial state for the resolution, based upon the + # Creates and pushes the initial state for the resolution, based upon the # {#requested} dependencies - # @return [DependencyState] the initial state for the resolution - def initial_state + # @return [void] + def push_initial_state graph = DependencyGraph.new.tap do |dg| - original_requested.each { |r| dg.add_vertex(name_for(r), nil, true).tap { |v| v.explicit_requirements << r } } + original_requested.each do |requested| + vertex = dg.add_vertex(name_for(requested), nil, true) + vertex.explicit_requirements << requested + end dg.tag(:initial_state) end - requirements = sort_dependencies(original_requested, graph, {}) - initial_requirement = requirements.shift - DependencyState.new( - initial_requirement && name_for(initial_requirement), - requirements, - graph, - initial_requirement, - initial_requirement && search_for(initial_requirement), - 0, - {} - ) + push_state_for_requirements(original_requested, true, graph) end # Unwinds the states stack because a conflict has been encountered # @return [void] def unwind_for_conflict - debug(depth) { "Unwinding for conflict: #{requirement} to #{state_index_for_unwind / 2}" } + details_for_unwind = build_details_for_unwind + unwind_options = unused_unwind_options + debug(depth) { "Unwinding for conflict: #{requirement} to #{details_for_unwind.state_index / 2}" } conflicts.tap do |c| - sliced_states = states.slice!((state_index_for_unwind + 1)..-1) - raise VersionConflict.new(c) unless state + sliced_states = states.slice!((details_for_unwind.state_index + 1)..-1) + raise_error_unless_state(c) activated.rewind_to(sliced_states.first || :initial_state) if sliced_states state.conflicts = c + state.unused_unwind_options = unwind_options + filter_possibilities_after_unwind(details_for_unwind) index = states.size - 1 @parents_of.each { |_, a| a.reject! { |i| i >= index } } + state.unused_unwind_options.reject! { |uw| uw.state_index >= index } + end + end + + # Raises a VersionConflict error, or any underlying error, if there is no + # current state + # @return [void] + def raise_error_unless_state(conflicts) + return if state + + error = conflicts.values.map(&:underlying_error).compact.first + raise error || VersionConflict.new(conflicts, specification_provider) + end + + # @return [UnwindDetails] Details of the nearest index to which we could unwind + def build_details_for_unwind + # Get the possible unwinds for the current conflict + current_conflict = conflicts[name] + binding_requirements = binding_requirements_for_conflict(current_conflict) + unwind_details = unwind_options_for_requirements(binding_requirements) + + last_detail_for_current_unwind = unwind_details.sort.last + current_detail = last_detail_for_current_unwind + + # Look for past conflicts that could be unwound to affect the + # requirement tree for the current conflict + all_reqs = last_detail_for_current_unwind.all_requirements + all_reqs_size = all_reqs.size + relevant_unused_unwinds = unused_unwind_options.select do |alternative| + diff_reqs = all_reqs - alternative.requirements_unwound_to_instead + next if diff_reqs.size == all_reqs_size + # Find the highest index unwind whilst looping through + current_detail = alternative if alternative > current_detail + alternative + end + + # Add the current unwind options to the `unused_unwind_options` array. + # The "used" option will be filtered out during `unwind_for_conflict`. + state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 } + + # Update the requirements_unwound_to_instead on any relevant unused unwinds + relevant_unused_unwinds.each do |d| + (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq! + end + unwind_details.each do |d| + (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq! + end + + current_detail + end + + # @param [Array] binding_requirements array of requirements that combine to create a conflict + # @return [Array] array of UnwindDetails that have a chance + # of resolving the passed requirements + def unwind_options_for_requirements(binding_requirements) + unwind_details = [] + + trees = [] + binding_requirements.reverse_each do |r| + partial_tree = [r] + trees << partial_tree + unwind_details << UnwindDetails.new(-1, nil, partial_tree, binding_requirements, trees, []) + + # If this requirement has alternative possibilities, check if any would + # satisfy the other requirements that created this conflict + requirement_state = find_state_for(r) + if conflict_fixing_possibilities?(requirement_state, binding_requirements) + unwind_details << UnwindDetails.new( + states.index(requirement_state), + r, + partial_tree, + binding_requirements, + trees, + [] + ) + end + + # Next, look at the parent of this requirement, and check if the requirement + # could have been avoided if an alternative PossibilitySet had been chosen + parent_r = parent_of(r) + next if parent_r.nil? + partial_tree.unshift(parent_r) + requirement_state = find_state_for(parent_r) + if requirement_state.possibilities.any? { |set| !set.dependencies.include?(r) } + unwind_details << UnwindDetails.new( + states.index(requirement_state), + parent_r, + partial_tree, + binding_requirements, + trees, + [] + ) + end + + # Finally, look at the grandparent and up of this requirement, looking + # for any possibilities that wouldn't create their parent requirement + grandparent_r = parent_of(parent_r) + until grandparent_r.nil? + partial_tree.unshift(grandparent_r) + requirement_state = find_state_for(grandparent_r) + if requirement_state.possibilities.any? { |set| !set.dependencies.include?(parent_r) } + unwind_details << UnwindDetails.new( + states.index(requirement_state), + grandparent_r, + partial_tree, + binding_requirements, + trees, + [] + ) + end + parent_r = grandparent_r + grandparent_r = parent_of(parent_r) + end + end + + unwind_details + end + + # @param [DependencyState] state + # @param [Array] binding_requirements array of requirements + # @return [Boolean] whether or not the given state has any possibilities + # that could satisfy the given requirements + def conflict_fixing_possibilities?(state, binding_requirements) + return false unless state + + state.possibilities.any? do |possibility_set| + possibility_set.possibilities.any? do |poss| + possibility_satisfies_requirements?(poss, binding_requirements) + end + end + end + + # Filter's a state's possibilities to remove any that would not fix the + # conflict we've just rewound from + # @param [UnwindDetails] unwind_details details of the conflict just + # unwound from + # @return [void] + def filter_possibilities_after_unwind(unwind_details) + return unless state && !state.possibilities.empty? + + if unwind_details.unwinding_to_primary_requirement? + filter_possibilities_for_primary_unwind(unwind_details) + else + filter_possibilities_for_parent_unwind(unwind_details) end end - # @return [Integer] The index to which the resolution should unwind in the - # case of conflict. - def state_index_for_unwind - current_requirement = requirement - existing_requirement = requirement_for_existing_name(name) - index = -1 - [current_requirement, existing_requirement].each do |r| - until r.nil? - current_state = find_state_for(r) - if state_any?(current_state) - current_index = states.index(current_state) - index = current_index if current_index > index - break + # Filter's a state's possibilities to remove any that would not satisfy + # the requirements in the conflict we've just rewound from + # @param [UnwindDetails] unwind_details details of the conflict just unwound from + # @return [void] + def filter_possibilities_for_primary_unwind(unwind_details) + unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } + unwinds_to_state << unwind_details + unwind_requirement_sets = unwinds_to_state.map(&:conflicting_requirements) + + state.possibilities.reject! do |possibility_set| + possibility_set.possibilities.none? do |poss| + unwind_requirement_sets.any? do |requirements| + possibility_satisfies_requirements?(poss, requirements) end - r = parent_of(r) end end + end + + # @param [Object] possibility a single possibility + # @param [Array] requirements an array of requirements + # @return [Boolean] whether the possibility satisfies all of the + # given requirements + def possibility_satisfies_requirements?(possibility, requirements) + name = name_for(possibility) + + activated.tag(:swap) + activated.set_payload(name, possibility) if activated.vertex_named(name) + satisfied = requirements.all? { |r| requirement_satisfied_by?(r, activated, possibility) } + activated.rewind_to(:swap) + + satisfied + end + + # Filter's a state's possibilities to remove any that would (eventually) + # create a requirement in the conflict we've just rewound from + # @param [UnwindDetails] unwind_details details of the conflict just unwound from + # @return [void] + def filter_possibilities_for_parent_unwind(unwind_details) + unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } + unwinds_to_state << unwind_details + + primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq + parent_unwinds = unwinds_to_state.uniq - primary_unwinds + + allowed_possibility_sets = primary_unwinds.flat_map do |unwind| + states[unwind.state_index].possibilities.select do |possibility_set| + possibility_set.possibilities.any? do |poss| + possibility_satisfies_requirements?(poss, unwind.conflicting_requirements) + end + end + end + + requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid) + + state.possibilities.reject! do |possibility_set| + !allowed_possibility_sets.include?(possibility_set) && + (requirements_to_avoid - possibility_set.dependencies).empty? + end + end + + # @param [Conflict] conflict + # @return [Array] minimal array of requirements that would cause the passed + # conflict to occur. + def binding_requirements_for_conflict(conflict) + return [conflict.requirement] if conflict.possibility.nil? + + possible_binding_requirements = conflict.requirements.values.flatten(1).uniq + + # When there's a `CircularDependency` error the conflicting requirement + # (the one causing the circular) won't be `conflict.requirement` + # (which won't be for the right state, because we won't have created it, + # because it's circular). + # We need to make sure we have that requirement in the conflict's list, + # otherwise we won't be able to unwind properly, so we just return all + # the requirements for the conflict. + return possible_binding_requirements if conflict.underlying_error + + possibilities = search_for(conflict.requirement) + + # If all the requirements together don't filter out all possibilities, + # then the only two requirements we need to consider are the initial one + # (where the dependency's version was first chosen) and the last + if binding_requirement_in_set?(nil, possible_binding_requirements, possibilities) + return [conflict.requirement, requirement_for_existing_name(name_for(conflict.requirement))].compact + end + + # Loop through the possible binding requirements, removing each one + # that doesn't bind. Use a `reverse_each` as we want the earliest set of + # binding requirements, and don't use `reject!` as we wish to refine the + # array *on each iteration*. + binding_requirements = possible_binding_requirements.dup + possible_binding_requirements.reverse_each do |req| + next if req == conflict.requirement + unless binding_requirement_in_set?(req, binding_requirements, possibilities) + binding_requirements -= [req] + end + end + + binding_requirements + end - index + # @param [Object] requirement we wish to check + # @param [Array] possible_binding_requirements array of requirements + # @param [Array] possibilities array of possibilities the requirements will be used to filter + # @return [Boolean] whether or not the given requirement is required to filter + # out all elements of the array of possibilities. + def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities) + possibilities.any? do |poss| + possibility_satisfies_requirements?(poss, possible_binding_requirements - [requirement]) + end end + # @param [Object] requirement # @return [Object] the requirement that led to `requirement` being added # to the list of requirements. def parent_of(requirement) @@ -219,29 +572,27 @@ def parent_of(requirement) parent_state.requirement end + # @param [String] name # @return [Object] the requirement that led to a version of a possibility # with the given name being activated. def requirement_for_existing_name(name) - return nil unless activated.vertex_named(name).payload + return nil unless vertex = activated.vertex_named(name) + return nil unless vertex.payload states.find { |s| s.name == name }.requirement end + # @param [Object] requirement # @return [ResolutionState] the state whose `requirement` is the given # `requirement`. def find_state_for(requirement) return nil unless requirement - states.reverse_each.find { |i| requirement == i.requirement && i.is_a?(DependencyState) } - end - - # @return [Boolean] whether or not the given state has any possibilities - # left. - def state_any?(state) - state && state.possibilities.any? + states.find { |i| requirement == i.requirement } end + # @param [Object] underlying_error # @return [Conflict] a {Conflict} that reflects the failure to activate # the {#possibility} in conjunction with the current {#state} - def create_conflict + def create_conflict(underlying_error = nil) vertex = activated.vertex_named(name) locked_requirement = locked_requirement_named(name) @@ -250,18 +601,21 @@ def create_conflict requirements[name_for_explicit_dependency_source] = vertex.explicit_requirements end requirements[name_for_locking_dependency_source] = [locked_requirement] if locked_requirement - vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(edge.requirement) } + vertex.incoming_edges.each do |edge| + (requirements[edge.origin.payload.latest_version] ||= []).unshift(edge.requirement) + end activated_by_name = {} - activated.each { |v| activated_by_name[v.name] = v.payload if v.payload } + activated.each { |v| activated_by_name[v.name] = v.payload.latest_version if v.payload } conflicts[name] = Conflict.new( requirement, requirements, - vertex.payload, + vertex.payload && vertex.payload.latest_version, possibility, locked_requirement, requirement_trees, - activated_by_name + activated_by_name, + underlying_error ) end @@ -272,6 +626,7 @@ def requirement_trees vertex.requirements.map { |r| requirement_tree_for(r) } end + # @param [Object] requirement # @return [Array] the list of requirements that led to # `requirement` being required. def requirement_tree_for(requirement) @@ -311,116 +666,47 @@ def debug(depth = 0, &block) # @return [void] def attempt_to_activate debug(depth) { 'Attempting to activate ' + possibility.to_s } - existing_node = activated.vertex_named(name) - if existing_node.payload - debug(depth) { "Found existing spec (#{existing_node.payload})" } - attempt_to_activate_existing_spec(existing_node) + existing_vertex = activated.vertex_named(name) + if existing_vertex.payload + debug(depth) { "Found existing spec (#{existing_vertex.payload})" } + attempt_to_filter_existing_spec(existing_vertex) else - attempt_to_activate_new_spec - end - end - - # Attempts to activate the current {#possibility} (given that it has - # already been activated) - # @return [void] - def attempt_to_activate_existing_spec(existing_node) - existing_spec = existing_node.payload - if requirement_satisfied_by?(requirement, activated, existing_spec) - new_requirements = requirements.dup - push_state_for_requirements(new_requirements, false) - else - return if attempt_to_swap_possibility - create_conflict - debug(depth) { "Unsatisfied by existing spec (#{existing_node.payload})" } - unwind_for_conflict - end - end - - # Attempts to swp the current {#possibility} with the already-activated - # spec with the given name - # @return [Boolean] Whether the possibility was swapped into {#activated} - def attempt_to_swap_possibility - activated.tag(:swap) - vertex = activated.vertex_named(name) - activated.set_payload(name, possibility) - if !vertex.requirements. - all? { |r| requirement_satisfied_by?(r, activated, possibility) } || - !new_spec_satisfied? - activated.rewind_to(:swap) - return - end - fixup_swapped_children(vertex) - activate_spec - end - - # Ensures there are no orphaned successors to the given {vertex}. - # @param [DependencyGraph::Vertex] vertex the vertex to fix up. - # @return [void] - def fixup_swapped_children(vertex) # rubocop:disable Metrics/CyclomaticComplexity - payload = vertex.payload - deps = dependencies_for(payload).group_by(&method(:name_for)) - vertex.outgoing_edges.each do |outgoing_edge| - requirement = outgoing_edge.requirement - parent_index = @parents_of[requirement].last - succ = outgoing_edge.destination - matching_deps = Array(deps[succ.name]) - dep_matched = matching_deps.include?(requirement) - - # only push the current index when it was originally required by the - # same named spec - if parent_index && states[parent_index].name == name - @parents_of[requirement].push(states.size - 1) + latest = possibility.latest_version + possibility.possibilities.select! do |possibility| + requirement_satisfied_by?(requirement, activated, possibility) end - - if matching_deps.empty? && !succ.root? && succ.predecessors.to_a == [vertex] - debug(depth) { "Removing orphaned spec #{succ.name} after swapping #{name}" } - succ.requirements.each { |r| @parents_of.delete(r) } - - removed_names = activated.detach_vertex_named(succ.name).map(&:name) - requirements.delete_if do |r| - # the only removed vertices are those with no other requirements, - # so it's safe to delete only based upon name here - removed_names.include?(name_for(r)) - end - elsif !dep_matched - debug(depth) { "Removing orphaned dependency #{requirement} after swapping #{name}" } - # also reset if we're removing the edge, but only if its parent has - # already been fixed up - @parents_of[requirement].push(states.size - 1) if @parents_of[requirement].empty? - - activated.delete_edge(outgoing_edge) - requirements.delete(requirement) + if possibility.latest_version.nil? + # ensure there's a possibility for better error messages + possibility.possibilities << latest if latest + create_conflict + unwind_for_conflict + else + activate_new_spec end end end - # Attempts to activate the current {#possibility} (given that it hasn't - # already been activated) + # Attempts to update the existing vertex's `PossibilitySet` with a filtered version # @return [void] - def attempt_to_activate_new_spec - if new_spec_satisfied? - activate_spec + def attempt_to_filter_existing_spec(vertex) + filtered_set = filtered_possibility_set(vertex) + if !filtered_set.possibilities.empty? + activated.set_payload(name, filtered_set) + new_requirements = requirements.dup + push_state_for_requirements(new_requirements, false) else create_conflict + debug(depth) { "Unsatisfied by existing spec (#{vertex.payload})" } unwind_for_conflict end end - # @return [Boolean] whether the current spec is satisfied as a new - # possibility. - def new_spec_satisfied? - unless requirement_satisfied_by?(requirement, activated, possibility) - debug(depth) { 'Unsatisfied by requested spec' } - return false - end - - locked_requirement = locked_requirement_named(name) - - locked_spec_satisfied = !locked_requirement || - requirement_satisfied_by?(locked_requirement, activated, possibility) - debug(depth) { 'Unsatisfied by locked spec' } unless locked_spec_satisfied - - locked_spec_satisfied + # Generates a filtered version of the existing vertex's `PossibilitySet` using the + # current state's `requirement` + # @param [Object] vertex existing vertex + # @return [PossibilitySet] filtered possibility set + def filtered_possibility_set(vertex) + PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities) end # @param [String] requirement_name the spec name to search for @@ -434,7 +720,7 @@ def locked_requirement_named(requirement_name) # Add the current {#possibility} to the dependency graph of the current # {#state} # @return [void] - def activate_spec + def activate_new_spec conflicts.delete(name) debug(depth) { "Activated #{name} at #{possibility}" } activated.set_payload(name, possibility) @@ -442,14 +728,14 @@ def activate_spec end # Requires the dependencies that the recently activated spec has - # @param [Object] activated_spec the specification that has just been + # @param [Object] possibility_set the PossibilitySet that has just been # activated # @return [void] - def require_nested_dependencies_for(activated_spec) - nested_dependencies = dependencies_for(activated_spec) + def require_nested_dependencies_for(possibility_set) + nested_dependencies = dependencies_for(possibility_set.latest_version) debug(depth) { "Requiring nested dependencies (#{nested_dependencies.join(', ')})" } nested_dependencies.each do |d| - activated.add_child_vertex(name_for(d), nil, [name_for(activated_spec)], d) + activated.add_child_vertex(name_for(d), nil, [name_for(possibility_set.latest_version)], d) parent_index = states.size - 1 parents = @parents_of[d] parents << parent_index if parents.empty? @@ -461,23 +747,82 @@ def require_nested_dependencies_for(activated_spec) # Pushes a new {DependencyState} that encapsulates both existing and new # requirements # @param [Array] new_requirements + # @param [Boolean] requires_sort + # @param [Object] new_activated # @return [void] def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated) new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort - new_requirement = new_requirements.shift + new_requirement = nil + loop do + new_requirement = new_requirements.shift + break if new_requirement.nil? || states.none? { |s| s.requirement == new_requirement } + end new_name = new_requirement ? name_for(new_requirement) : ''.freeze - possibilities = new_requirement ? search_for(new_requirement) : [] + possibilities = possibilities_for_requirement(new_requirement) handle_missing_or_push_dependency_state DependencyState.new( new_name, new_requirements, new_activated, - new_requirement, possibilities, depth, conflicts.dup + new_requirement, possibilities, depth, conflicts.dup, unused_unwind_options.dup ) end + # Checks a proposed requirement with any existing locked requirement + # before generating an array of possibilities for it. + # @param [Object] requirement the proposed requirement + # @param [Object] activated + # @return [Array] possibilities + def possibilities_for_requirement(requirement, activated = self.activated) + return [] unless requirement + if locked_requirement_named(name_for(requirement)) + return locked_requirement_possibility_set(requirement, activated) + end + + group_possibilities(search_for(requirement)) + end + + # @param [Object] requirement the proposed requirement + # @param [Object] activated + # @return [Array] possibility set containing only the locked requirement, if any + def locked_requirement_possibility_set(requirement, activated = self.activated) + all_possibilities = search_for(requirement) + locked_requirement = locked_requirement_named(name_for(requirement)) + + # Longwinded way to build a possibilities array with either the locked + # requirement or nothing in it. Required, since the API for + # locked_requirement isn't guaranteed. + locked_possibilities = all_possibilities.select do |possibility| + requirement_satisfied_by?(locked_requirement, activated, possibility) + end + + group_possibilities(locked_possibilities) + end + + # Build an array of PossibilitySets, with each element representing a group of + # dependency versions that all have the same sub-dependency version constraints + # and are contiguous. + # @param [Array] possibilities an array of possibilities + # @return [Array] an array of possibility sets + def group_possibilities(possibilities) + possibility_sets = [] + current_possibility_set = nil + + possibilities.reverse_each do |possibility| + dependencies = dependencies_for(possibility) + if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies) + current_possibility_set.possibilities.unshift(possibility) + else + possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility])) + current_possibility_set = possibility_sets.first + end + end + + possibility_sets + end + # Pushes a new {DependencyState}. # If the {#specification_provider} says to # {SpecificationProvider#allow_missing?} that particular requirement, and # there are no possibilities for that requirement, then `state` is not - # pushed, and the node in {#activated} is removed, and we continue + # pushed, and the vertex in {#activated} is removed, and we continue # resolving the remaining requirements. # @param [DependencyState] state # @return [void] diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb index 5c59a45c3..d43121f8c 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph' + +require_relative 'dependency_graph' module Gem::Resolver::Molinillo # This class encapsulates a dependency resolver. @@ -8,7 +9,7 @@ module Gem::Resolver::Molinillo # # class Resolver - require 'rubygems/resolver/molinillo/lib/molinillo/resolution' + require_relative 'resolution' # @return [SpecificationProvider] the specification provider used # in the resolution process diff --git a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb index c20de9885..6e7c715fc 100644 --- a/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +++ b/ruby/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Gem::Resolver::Molinillo # A state that a {Resolution} can be in # @attr [String] name the name of the current requirement @@ -7,7 +8,8 @@ module Gem::Resolver::Molinillo # @attr [Object] requirement the current requirement # @attr [Object] possibilities the possibilities to satisfy the current requirement # @attr [Integer] depth the depth of the resolution - # @attr [Set] conflicts unresolved conflicts + # @attr [Hash] conflicts unresolved conflicts, indexed by dependency name + # @attr [Array] unused_unwind_options unwinds for previous conflicts that weren't explored ResolutionState = Struct.new( :name, :requirements, @@ -15,14 +17,15 @@ module Gem::Resolver::Molinillo :requirement, :possibilities, :depth, - :conflicts + :conflicts, + :unused_unwind_options ) class ResolutionState # Returns an empty resolution state # @return [ResolutionState] an empty state def self.empty - new(nil, [], DependencyGraph.new, nil, nil, 0, Set.new) + new(nil, [], DependencyGraph.new, nil, nil, 0, {}, []) end end @@ -40,7 +43,8 @@ def pop_possibility_state requirement, [possibilities.pop], depth + 1, - conflicts.dup + conflicts.dup, + unused_unwind_options.dup ).tap do |state| state.activated.tag(state) end diff --git a/ruby/lib/rubygems/resolver/requirement_list.rb b/ruby/lib/rubygems/resolver/requirement_list.rb index cf0014b0b..5b51493c9 100644 --- a/ruby/lib/rubygems/resolver/requirement_list.rb +++ b/ruby/lib/rubygems/resolver/requirement_list.rb @@ -7,7 +7,6 @@ # first. class Gem::Resolver::RequirementList - include Enumerable ## @@ -79,5 +78,4 @@ def next5 x = @exact[0,5] x + @list[0,5 - x.size] end - end diff --git a/ruby/lib/rubygems/resolver/set.rb b/ruby/lib/rubygems/resolver/set.rb index 242f9cd3d..5d8dd51ea 100644 --- a/ruby/lib/rubygems/resolver/set.rb +++ b/ruby/lib/rubygems/resolver/set.rb @@ -4,7 +4,6 @@ # dependencies) used in resolution. This set is abstract. class Gem::Resolver::Set - ## # Set to true to disable network access for this set @@ -21,7 +20,6 @@ class Gem::Resolver::Set attr_accessor :prerelease def initialize # :nodoc: - require 'uri' @prerelease = false @remote = true @errors = [] @@ -53,5 +51,4 @@ def prefetch(reqs) def remote? # :nodoc: @remote end - end diff --git a/ruby/lib/rubygems/resolver/source_set.rb b/ruby/lib/rubygems/resolver/source_set.rb index 8e799514f..bf8c23184 100644 --- a/ruby/lib/rubygems/resolver/source_set.rb +++ b/ruby/lib/rubygems/resolver/source_set.rb @@ -4,7 +4,6 @@ # Kind off like BestSet but filters the sources for gems class Gem::Resolver::SourceSet < Gem::Resolver::Set - ## # Creates a SourceSet for the given +sources+ or Gem::sources if none are # specified. +sources+ must be a Gem::SourceList. @@ -43,5 +42,4 @@ def get_set(name) link = @links[name] @sets[link] ||= Gem::Source.new(link).dependency_resolver_set if link end - end diff --git a/ruby/lib/rubygems/resolver/spec_specification.rb b/ruby/lib/rubygems/resolver/spec_specification.rb index d0e744f3a..7b665fe87 100644 --- a/ruby/lib/rubygems/resolver/spec_specification.rb +++ b/ruby/lib/rubygems/resolver/spec_specification.rb @@ -4,7 +4,6 @@ # Resolver specifications that are backed by a Gem::Specification. class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification - ## # A SpecSpecification is created for a +set+ for a Gem::Specification in # +spec+. The +source+ is either where the +spec+ came from, or should be @@ -23,6 +22,20 @@ def dependencies spec.dependencies end + ## + # The required_ruby_version constraint for this specification + + def required_ruby_version + spec.required_ruby_version + end + + ## + # The required_rubygems_version constraint for this specification + + def required_rubygems_version + spec.required_rubygems_version + end + ## # The name and version of the specification. # @@ -52,5 +65,4 @@ def platform def version spec.version end - end diff --git a/ruby/lib/rubygems/resolver/specification.rb b/ruby/lib/rubygems/resolver/specification.rb index e859d6659..dfcb7eb05 100644 --- a/ruby/lib/rubygems/resolver/specification.rb +++ b/ruby/lib/rubygems/resolver/specification.rb @@ -5,7 +5,6 @@ # dependency resolution in the resolver is included. class Gem::Resolver::Specification - ## # The dependencies of the gem for this specification @@ -44,6 +43,16 @@ class Gem::Resolver::Specification attr_reader :version + ## + # The required_ruby_version constraint for this specification. + + attr_reader :required_ruby_version + + ## + # The required_ruby_version constraint for this specification. + + attr_reader :required_rubygems_version + ## # Sets default instance variables for the specification. @@ -54,6 +63,8 @@ def initialize @set = nil @source = nil @version = nil + @required_ruby_version = Gem::Requirement.default + @required_rubygems_version = Gem::Requirement.default end ## @@ -82,7 +93,7 @@ def full_name # specification. def install(options = {}) - require 'rubygems/installer' + require_relative '../installer' gem = download options @@ -105,11 +116,10 @@ def download(options) # Returns true if this specification is installable on this platform. def installable_platform? - Gem::Platform.match spec.platform + Gem::Platform.match_spec? spec end def local? # :nodoc: false end - end diff --git a/ruby/lib/rubygems/resolver/stats.rb b/ruby/lib/rubygems/resolver/stats.rb index 5f41940b1..64b458f50 100644 --- a/ruby/lib/rubygems/resolver/stats.rb +++ b/ruby/lib/rubygems/resolver/stats.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true class Gem::Resolver::Stats - def initialize @max_depth = 0 @max_requirements = 0 @@ -43,5 +42,4 @@ def display $stdout.printf PATTERN, "Backtracking #", @backtracking $stdout.printf PATTERN, "Iteration #", @iterations end - end diff --git a/ruby/lib/rubygems/resolver/vendor_set.rb b/ruby/lib/rubygems/resolver/vendor_set.rb index 7e2e917d5..48c640d8c 100644 --- a/ruby/lib/rubygems/resolver/vendor_set.rb +++ b/ruby/lib/rubygems/resolver/vendor_set.rb @@ -15,7 +15,6 @@ # rake.gemspec (watching the given name). class Gem::Resolver::VendorSet < Gem::Resolver::Set - ## # The specifications for this set. @@ -83,5 +82,4 @@ def pretty_print(q) # :nodoc: end end end - end diff --git a/ruby/lib/rubygems/resolver/vendor_specification.rb b/ruby/lib/rubygems/resolver/vendor_specification.rb index 56f2e6eb2..8dfe5940f 100644 --- a/ruby/lib/rubygems/resolver/vendor_specification.rb +++ b/ruby/lib/rubygems/resolver/vendor_specification.rb @@ -5,7 +5,6 @@ # option. class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification - def ==(other) # :nodoc: self.class === other and @set == other.set and @@ -20,5 +19,4 @@ def ==(other) # :nodoc: def install(options = {}) yield nil end - end diff --git a/ruby/lib/rubygems/s3_uri_signer.rb b/ruby/lib/rubygems/s3_uri_signer.rb index 534b8676a..4d1deee99 100644 --- a/ruby/lib/rubygems/s3_uri_signer.rb +++ b/ruby/lib/rubygems/s3_uri_signer.rb @@ -1,14 +1,10 @@ -require 'base64' -require 'digest' -require 'openssl' +require_relative 'openssl' ## # S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems # More on AWS SigV4: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html class Gem::S3URISigner - class ConfigurationError < Gem::Exception - def initialize(message) super message end @@ -16,11 +12,9 @@ def initialize(message) def to_s # :nodoc: "#{super}" end - end class InstanceProfileError < Gem::Exception - def initialize(message) super message end @@ -28,7 +22,6 @@ def initialize(message) def to_s # :nodoc: "#{super}" end - end attr_accessor :uri @@ -93,7 +86,7 @@ def generate_string_to_sign(date_time, credential_info, canonical_request) "AWS4-HMAC-SHA256", date_time, credential_info, - Digest::SHA256.hexdigest(canonical_request) + OpenSSL::Digest::SHA256.hexdigest(canonical_request), ].join("\n") end @@ -146,8 +139,8 @@ def base64_uri_escape(str) def ec2_metadata_credentials_json require 'net/http' - require 'rubygems/request' - require 'rubygems/request/connection_pools' + require_relative 'request' + require_relative 'request/connection_pools' require 'json' iam_info = ec2_metadata_request(EC2_IAM_INFO) @@ -179,5 +172,4 @@ def create_request_pool(uri) BASE64_URI_TRANSLATE = { "+" => "%2B", "/" => "%2F", "=" => "%3D", "\n" => "" }.freeze EC2_IAM_INFO = "http://169.254.169.254/latest/meta-data/iam/info".freeze EC2_IAM_SECURITY_CREDENTIALS = "http://169.254.169.254/latest/meta-data/iam/security-credentials/".freeze - end diff --git a/ruby/lib/rubygems/safe_yaml.rb b/ruby/lib/rubygems/safe_yaml.rb index 3540fd74d..81f99ee26 100644 --- a/ruby/lib/rubygems/safe_yaml.rb +++ b/ruby/lib/rubygems/safe_yaml.rb @@ -7,7 +7,7 @@ module Gem # Psych.safe_load module SafeYAML - PERMITTED_CLASSES = %w( + PERMITTED_CLASSES = %w[ Symbol Time Date @@ -17,42 +17,40 @@ module SafeYAML Gem::Specification Gem::Version Gem::Version::Requirement - YAML::Syck::DefaultKey - Syck::DefaultKey - ).freeze + ].freeze - PERMITTED_SYMBOLS = %w( + PERMITTED_SYMBOLS = %w[ development runtime - ).freeze + ].freeze - if ::YAML.respond_to? :safe_load + if ::Psych.respond_to? :safe_load def self.safe_load(input) if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1') - ::YAML.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true) + ::Psych.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true) else - ::YAML.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true) + ::Psych.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true) end end def self.load(input) if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1') - ::YAML.safe_load(input, permitted_classes: [::Symbol]) + ::Psych.safe_load(input, permitted_classes: [::Symbol]) else - ::YAML.safe_load(input, [::Symbol]) + ::Psych.safe_load(input, [::Symbol]) end end else unless Gem::Deprecate.skip - warn "YAML safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)." + warn "Psych safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)." end def self.safe_load(input, *args) - ::YAML.load input + ::Psych.load input end def self.load(input) - ::YAML.load input + ::Psych.load input end end end diff --git a/ruby/lib/rubygems/security.rb b/ruby/lib/rubygems/security.rb index 7b0a0b3c6..fc23c1c48 100644 --- a/ruby/lib/rubygems/security.rb +++ b/ruby/lib/rubygems/security.rb @@ -5,15 +5,8 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/exceptions' -require 'fileutils' - -begin - require 'openssl' -rescue LoadError => e - raise unless (e.respond_to?(:path) && e.path == 'openssl') || - e.message =~ / -- openssl$/ -end +require_relative 'exceptions' +require_relative 'openssl' ## # = Signing gems @@ -62,11 +55,11 @@ # # $ tar tf your-gem-1.0.gem # metadata.gz -# metadata.gz.sum # metadata.gz.sig # metadata signature # data.tar.gz -# data.tar.gz.sum # data.tar.gz.sig # data signature +# checksums.yaml.gz +# checksums.yaml.gz.sig # checksums signature # # === Manually signing gems # @@ -159,8 +152,11 @@ # certificate for EMAIL_ADDR # -C, --certificate CERT Signing certificate for --sign # -K, --private-key KEY Key for --sign or --build +# -A, --key-algorithm ALGORITHM Select key algorithm for --build from RSA, DSA, or EC. Defaults to RSA. # -s, --sign CERT Signs CERT with the key from -K # and the certificate from -C +# -d, --days NUMBER_OF_DAYS Days before the certificate expires +# -R, --re-sign Re-signs the certificate from -C with the key from -K # # We've already covered the --build option, and the # --add, --list, and --remove commands @@ -265,7 +261,7 @@ # 2. Grab the public key from the gemspec # # gem spec some_signed_gem-1.0.gem cert_chain | \ -# ruby -ryaml -e 'puts YAML.load_documents($stdin)' > public_key.crt +# ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt # # 3. Generate a SHA1 hash of the data.tar.gz # @@ -322,7 +318,6 @@ # * Honor extension restrictions # * Might be better to store the certificate chain as a PKCS#7 or PKCS#12 # file, instead of an array embedded in the metadata. -# * Flexible signature and key algorithms, not hard-coded to RSA and SHA1. # # == Original author # @@ -337,40 +332,24 @@ module Gem::Security class Exception < Gem::Exception; end ## - # Digest algorithm used to sign gems - - DIGEST_ALGORITHM = - if defined?(OpenSSL::Digest::SHA256) - OpenSSL::Digest::SHA256 - elsif defined?(OpenSSL::Digest::SHA1) - OpenSSL::Digest::SHA1 - else - require 'digest' - Digest::SHA512 - end + # Used internally to select the signing digest from all computed digests + + DIGEST_NAME = 'SHA256' # :nodoc: ## - # Used internally to select the signing digest from all computed digests + # Length of keys created by RSA and DSA keys - DIGEST_NAME = # :nodoc: - if DIGEST_ALGORITHM.method_defined? :name - DIGEST_ALGORITHM.new.name - else - DIGEST_ALGORITHM.name[/::([^:]+)\z/, 1] - end + RSA_DSA_KEY_LENGTH = 3072 ## - # Algorithm for creating the key pair used to sign gems + # Default algorithm to use when building a key pair - KEY_ALGORITHM = - if defined?(OpenSSL::PKey::RSA) - OpenSSL::PKey::RSA - end + DEFAULT_KEY_ALGORITHM = 'RSA' ## - # Length of keys created by KEY_ALGORITHM + # Named curve used for Elliptic Curve - KEY_LENGTH = 3072 + EC_NAME = 'secp384r1' ## # Cipher used to encrypt the key pair used to sign gems. @@ -423,7 +402,7 @@ def self.create_cert(subject, key, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1) cert = OpenSSL::X509::Certificate.new - cert.public_key = key.public_key + cert.public_key = get_public_key(key) cert.version = 2 cert.serial = serial @@ -441,6 +420,26 @@ def self.create_cert(subject, key, age = ONE_YEAR, extensions = EXTENSIONS, cert end + ## + # Gets the right public key from a PKey instance + + def self.get_public_key(key) + # Ruby 3.0 (Ruby/OpenSSL 2.2) or later + return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der) + return key.public_key unless key.is_a?(OpenSSL::PKey::EC) + + ec_key = OpenSSL::PKey::EC.new(key.group.curve_name) + ec_key.public_key = key.public_key + ec_key + end + + ## + # In Ruby 2.3 EC doesn't implement the private_key? but not the private? method + + if defined?(OpenSSL::PKey::EC) && Gem::Version.new(String.new(RUBY_VERSION)) < Gem::Version.new("2.4.0") + OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?) + end + ## # Creates a self-signed certificate with an issuer and subject from +email+, # a subject alternative name of +email+ and the given +extensions+ for the @@ -466,11 +465,45 @@ def self.create_cert_self_signed(subject, key, age = ONE_YEAR, end ## - # Creates a new key pair of the specified +length+ and +algorithm+. The - # default is a 3072 bit RSA key. + # Creates a new digest instance using the specified +algorithm+. The default + # is SHA256. - def self.create_key(length = KEY_LENGTH, algorithm = KEY_ALGORITHM) - algorithm.new length + if defined?(OpenSSL::Digest) + def self.create_digest(algorithm = DIGEST_NAME) + OpenSSL::Digest.new(algorithm) + end + else + require 'digest' + + def self.create_digest(algorithm = DIGEST_NAME) + Digest.const_get(algorithm).new + end + end + + ## + # Creates a new key pair of the specified +algorithm+. RSA, DSA, and EC + # are supported. + + def self.create_key(algorithm) + if defined?(OpenSSL::PKey) + case algorithm.downcase + when 'dsa' + OpenSSL::PKey::DSA.new(RSA_DSA_KEY_LENGTH) + when 'rsa' + OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH) + when 'ec' + if RUBY_VERSION >= "2.4.0" + OpenSSL::PKey::EC.generate(EC_NAME) + else + domain_key = OpenSSL::PKey::EC.new(EC_NAME) + domain_key.generate_key + domain_key + end + else + raise Gem::Security::Exception, + "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported." + end + end end ## @@ -483,9 +516,10 @@ def self.email_to_name(email_address) dcs = dcs.split '.' - name = "CN=#{cn}/#{dcs.map { |dc| "DC=#{dc}" }.join '/'}" - - OpenSSL::X509::Name.parse name + OpenSSL::X509::Name.new([ + ["CN", cn], + *dcs.map {|dc| ["DC", dc] }, + ]) end ## @@ -499,7 +533,7 @@ def self.re_sign(expired_certificate, private_key, age = ONE_YEAR, raise Gem::Security::Exception, "incorrect signing key for re-signing " + "#{expired_certificate.subject}" unless - expired_certificate.public_key.to_pem == private_key.public_key.to_pem + expired_certificate.check_private_key(private_key) unless expired_certificate.subject.to_s == expired_certificate.issuer.to_s @@ -526,7 +560,7 @@ def self.reset ## # Sign the public key from +certificate+ with the +signing_key+ and - # +signing_cert+, using the Gem::Security::DIGEST_ALGORITHM. Uses the + # +signing_cert+, using the Gem::Security::DIGEST_NAME. Uses the # default certificate validity range and extensions. # # Returns the newly signed certificate. @@ -553,7 +587,7 @@ def self.sign(certificate, signing_key, signing_cert, signed = create_cert signee_subject, signee_key, age, extensions, serial signed.issuer = signing_cert.subject - signed.sign signing_key, Gem::Security::DIGEST_ALGORITHM.new + signed.sign signing_key, Gem::Security::DIGEST_NAME end ## @@ -598,10 +632,10 @@ def self.write(pemmable, path, permissions = 0600, passphrase = nil, cipher = KE end -if defined?(OpenSSL::SSL) - require 'rubygems/security/policy' - require 'rubygems/security/policies' - require 'rubygems/security/trust_dir' +if Gem::HAVE_OPENSSL + require_relative 'security/policy' + require_relative 'security/policies' + require_relative 'security/trust_dir' end -require 'rubygems/security/signer' +require_relative 'security/signer' diff --git a/ruby/lib/rubygems/security/policy.rb b/ruby/lib/rubygems/security/policy.rb index 1aa6eab18..06eae073f 100644 --- a/ruby/lib/rubygems/security/policy.rb +++ b/ruby/lib/rubygems/security/policy.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rubygems/user_interaction' +require_relative '../user_interaction' ## # A Gem::Security::Policy object encapsulates the settings for verifying @@ -8,7 +8,6 @@ # Gem::Security::Policies. class Gem::Security::Policy - include Gem::UserInteraction attr_reader :name @@ -25,8 +24,6 @@ class Gem::Security::Policy # options. def initialize(name, policy = {}, opt = {}) - require 'openssl' - @name = name @opt = opt @@ -76,7 +73,7 @@ def check_chain(chain, time) def check_data(public_key, digest, signature, data) raise Gem::Security::Exception, "invalid signature" unless - public_key.verify digest.new, signature, data.digest + public_key.verify digest, signature, data.digest true end @@ -120,7 +117,7 @@ def check_key(signer, key) raise Gem::Security::Exception, "certificate #{signer.subject} does not match the signing key" unless - signer.public_key.to_pem == key.public_key.to_pem + signer.check_private_key(key) true end @@ -139,7 +136,7 @@ def check_root(chain, time) raise Gem::Security::Exception, "root certificate #{root.subject} is not self-signed " + "(issuer #{root.issuer})" if - root.issuer.to_s != root.subject.to_s # HACK to_s is for ruby 1.8 + root.issuer != root.subject check_cert root, root, time end @@ -167,9 +164,9 @@ def check_trust(chain, digester, trust_dir) end save_cert = OpenSSL::X509::Certificate.new File.read path - save_dgst = digester.digest save_cert.public_key.to_s + save_dgst = digester.digest save_cert.public_key.to_pem - pkey_str = root.public_key.to_s + pkey_str = root.public_key.to_pem cert_dgst = digester.digest pkey_str raise Gem::Security::Exception, @@ -197,7 +194,7 @@ def inspect # :nodoc: ("[Policy: %s - data: %p signer: %p chain: %p root: %p " + "signed-only: %p trusted-only: %p]") % [ @name, @verify_chain, @verify_data, @verify_root, @verify_signer, - @only_signed, @only_trusted, + @only_signed, @only_trusted ] end @@ -224,7 +221,7 @@ def verify(chain, key = nil, digests = {}, signatures = {}, end opt = @opt - digester = Gem::Security::DIGEST_ALGORITHM + digester = Gem::Security.create_digest trust_dir = opt[:trust_dir] time = Time.now @@ -291,5 +288,4 @@ def verify_signatures(spec, digests, signatures) end alias to_s name # :nodoc: - end diff --git a/ruby/lib/rubygems/security/signer.rb b/ruby/lib/rubygems/security/signer.rb index 5e4ba6ebb..968cf8897 100644 --- a/ruby/lib/rubygems/security/signer.rb +++ b/ruby/lib/rubygems/security/signer.rb @@ -2,10 +2,9 @@ ## # Basic OpenSSL-based package signing class. -require "rubygems/user_interaction" +require_relative "../user_interaction" class Gem::Security::Signer - include Gem::UserInteraction ## @@ -35,11 +34,11 @@ class Gem::Security::Signer attr_reader :options DEFAULT_OPTIONS = { - expiration_length_days: 365 + expiration_length_days: 365, }.freeze ## - # Attemps to re-sign an expired cert with a given private key + # Attempts to re-sign an expired cert with a given private key def self.re_sign_cert(expired_cert, expired_cert_path, private_key) return unless expired_cert.not_after < Time.now @@ -81,11 +80,11 @@ def initialize(key, cert_chain, passphrase = nil, options = {}) @cert_chain = [default_cert] if File.exist? default_cert end - @digest_algorithm = Gem::Security::DIGEST_ALGORITHM @digest_name = Gem::Security::DIGEST_NAME + @digest_algorithm = Gem::Security.create_digest(@digest_name) - if @key && !@key.is_a?(OpenSSL::PKey::RSA) - @key = OpenSSL::PKey::RSA.new(File.read(@key), @passphrase) + if @key && !@key.is_a?(OpenSSL::PKey::PKey) + @key = OpenSSL::PKey.read(File.read(@key), @passphrase) end if @cert_chain @@ -106,10 +105,10 @@ def initialize(key, cert_chain, passphrase = nil, options = {}) # this value is preferred, otherwise the subject is used. def extract_name(cert) # :nodoc: - subject_alt_name = cert.extensions.find { |e| 'subjectAltName' == e.oid } + subject_alt_name = cert.extensions.find {|e| 'subjectAltName' == e.oid } if subject_alt_name - /\Aemail:/ =~ subject_alt_name.value + /\Aemail:/ =~ subject_alt_name.value # rubocop:disable Performance/StartWith $' || subject_alt_name.value else @@ -178,8 +177,7 @@ def re_sign_key(expiration_length: Gem::Security::ONE_YEAR) # :nodoc: disk_cert = File.read(disk_cert_path) rescue nil disk_key_path = File.join(Gem.default_key_path) - disk_key = - OpenSSL::PKey::RSA.new(File.read(disk_key_path), @passphrase) rescue nil + disk_key = OpenSSL::PKey.read(File.read(disk_key_path), @passphrase) rescue nil return unless disk_key @@ -202,5 +200,4 @@ def re_sign_key(expiration_length: Gem::Security::ONE_YEAR) # :nodoc: end end end - end diff --git a/ruby/lib/rubygems/security/trust_dir.rb b/ruby/lib/rubygems/security/trust_dir.rb index 98031ea22..456947274 100644 --- a/ruby/lib/rubygems/security/trust_dir.rb +++ b/ruby/lib/rubygems/security/trust_dir.rb @@ -4,7 +4,6 @@ # verification. class Gem::Security::TrustDir - ## # Default permissions for the trust directory and its contents @@ -26,7 +25,7 @@ def initialize(dir, permissions = DEFAULT_PERMISSIONS) @dir = dir @permissions = permissions - @digester = Gem::Security::DIGEST_ALGORITHM + @digester = Gem::Security.create_digest end ## @@ -105,6 +104,7 @@ def trust_cert(certificate) # permissions. def verify + require 'fileutils' if File.exist? @dir raise Gem::Security::Exception, "trust directory #{@dir} is not a directory" unless @@ -115,5 +115,4 @@ def verify FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir] end end - end diff --git a/ruby/lib/rubygems/security_option.rb b/ruby/lib/rubygems/security_option.rb index 3403aaaf0..a4c570ded 100644 --- a/ruby/lib/rubygems/security_option.rb +++ b/ruby/lib/rubygems/security_option.rb @@ -5,7 +5,7 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems' +require_relative '../rubygems' # forward-declare @@ -19,16 +19,16 @@ class Policy # :nodoc: module Gem::SecurityOption def add_security_option - OptionParser.accept Gem::Security::Policy do |value| - require 'rubygems/security' + Gem::OptionParser.accept Gem::Security::Policy do |value| + require_relative 'security' - raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless + raise Gem::OptionParser::InvalidArgument, 'OpenSSL not installed' unless defined?(Gem::Security::HighSecurity) policy = Gem::Security::Policies[value] unless policy valid = Gem::Security::Policies.keys.sort - raise OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)" + raise Gem::OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)" end policy end diff --git a/ruby/lib/rubygems/server.rb b/ruby/lib/rubygems/server.rb deleted file mode 100644 index 97923ef69..000000000 --- a/ruby/lib/rubygems/server.rb +++ /dev/null @@ -1,879 +0,0 @@ -# frozen_string_literal: true -require 'webrick' -require 'zlib' -require 'erb' -require 'uri' - -require 'rubygems' -require 'rubygems/rdoc' - -## -# Gem::Server and allows users to serve gems for consumption by -# `gem --remote-install`. -# -# gem_server starts an HTTP server on the given port and serves the following: -# * "/" - Browsing of gem spec files for installed gems -# * "/specs.#{Gem.marshal_version}.gz" - specs name/version/platform index -# * "/latest_specs.#{Gem.marshal_version}.gz" - latest specs -# name/version/platform index -# * "/quick/" - Individual gemspecs -# * "/gems" - Direct access to download the installable gems -# * "/rdoc?q=" - Search for installed rdoc documentation -# -# == Usage -# -# gem_server = Gem::Server.new Gem.dir, 8089, false -# gem_server.run -# -#-- -# TODO Refactor into a real WEBrick servlet to remove code duplication. - -class Gem::Server - - attr_reader :spec_dirs - - include ERB::Util - include Gem::UserInteraction - - SEARCH = <<-ERB.freeze -
- -
- ERB - - DOC_TEMPLATE = <<-'ERB'.freeze - - - - - - RubyGems Documentation Index - - - -
-<%= SEARCH %> -

RubyGems Documentation Index

-
- - -
-
-
-

Summary

-

There are <%=values["gem_count"]%> gems installed:

-

- <%= values["specs"].map { |v| "#{h v["name"]}" }.join ', ' %>. -

Gems

- -
- <% values["specs"].each do |spec| %> -
- <% if spec["first_name_entry"] then %> - "> - <% end %> - - <%=h spec["name"]%> <%=h spec["version"]%> - - <% if spec["ri_installed"] || spec["rdoc_installed"] then %> - ">[rdoc] - <% else %> - [rdoc] - <% end %> - - <% if spec["homepage"] then %> - " title="<%=h spec["homepage"]%>">[www] - <% else %> - [www] - <% end %> - - <% if spec["has_deps"] then %> - - depends on - <%= spec["dependencies"].map { |v| "#{h v["name"]}" }.join ', ' %>. - <% end %> -
-
- <%=spec["summary"]%> - <% if spec["executables"] then %> -
- - <% if spec["only_one_executable"] then %> - Executable is - <% else %> - Executables are - <%end%> - - <%= spec["executables"].map { |v| "#{h v["executable"]}"}.join ', ' %>. - - <%end%> -
-
-
- <% end %> -
- -
-
-
- - - - ERB - - # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108 - RDOC_CSS = <<-CSS.freeze -body { - font-family: Verdana,Arial,Helvetica,sans-serif; - font-size: 90%; - margin: 0; - margin-left: 40px; - padding: 0; - background: white; -} - -h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } -h1 { font-size: 150%; } -h2,h3,h4 { margin-top: 1em; } - -a { background: #eef; color: #039; text-decoration: none; } -a:hover { background: #039; color: #eef; } - -/* Override the base stylesheets Anchor inside a table cell */ -td > a { - background: transparent; - color: #039; - text-decoration: none; -} - -/* and inside a section title */ -.section-title > a { - background: transparent; - color: #eee; - text-decoration: none; -} - -/* === Structural elements =================================== */ - -div#index { - margin: 0; - margin-left: -40px; - padding: 0; - font-size: 90%; -} - - -div#index a { - margin-left: 0.7em; -} - -div#index .section-bar { - margin-left: 0px; - padding-left: 0.7em; - background: #ccc; - font-size: small; -} - - -div#classHeader, div#fileHeader { - width: auto; - color: white; - padding: 0.5em 1.5em 0.5em 1.5em; - margin: 0; - margin-left: -40px; - border-bottom: 3px solid #006; -} - -div#classHeader a, div#fileHeader a { - background: inherit; - color: white; -} - -div#classHeader td, div#fileHeader td { - background: inherit; - color: white; -} - - -div#fileHeader { - background: #057; -} - -div#classHeader { - background: #048; -} - - -.class-name-in-header { - font-size: 180%; - font-weight: bold; -} - - -div#bodyContent { - padding: 0 1.5em 0 1.5em; -} - -div#description { - padding: 0.5em 1.5em; - background: #efefef; - border: 1px dotted #999; -} - -div#description h1,h2,h3,h4,h5,h6 { - color: #125;; - background: transparent; -} - -div#validator-badges { - text-align: center; -} -div#validator-badges img { border: 0; } - -div#copyright { - color: #333; - background: #efefef; - font: 0.75em sans-serif; - margin-top: 5em; - margin-bottom: 0; - padding: 0.5em 2em; -} - - -/* === Classes =================================== */ - -table.header-table { - color: white; - font-size: small; -} - -.type-note { - font-size: small; - color: #DEDEDE; -} - -.xxsection-bar { - background: #eee; - color: #333; - padding: 3px; -} - -.section-bar { - color: #333; - border-bottom: 1px solid #999; - margin-left: -20px; -} - - -.section-title { - background: #79a; - color: #eee; - padding: 3px; - margin-top: 2em; - margin-left: -30px; - border: 1px solid #999; -} - -.top-aligned-row { vertical-align: top } -.bottom-aligned-row { vertical-align: bottom } - -/* --- Context section classes ----------------------- */ - -.context-row { } -.context-item-name { font-family: monospace; font-weight: bold; color: black; } -.context-item-value { font-size: small; color: #448; } -.context-item-desc { color: #333; padding-left: 2em; } - -/* --- Method classes -------------------------- */ -.method-detail { - background: #efefef; - padding: 0; - margin-top: 0.5em; - margin-bottom: 1em; - border: 1px dotted #ccc; -} -.method-heading { - color: black; - background: #ccc; - border-bottom: 1px solid #666; - padding: 0.2em 0.5em 0 0.5em; -} -.method-signature { color: black; background: inherit; } -.method-name { font-weight: bold; } -.method-args { font-style: italic; } -.method-description { padding: 0 0.5em 0 0.5em; } - -/* --- Source code sections -------------------- */ - -a.source-toggle { font-size: 90%; } -div.method-source-code { - background: #262626; - color: #ffdead; - margin: 1em; - padding: 0.5em; - border: 1px dashed #999; - overflow: hidden; -} - -div.method-source-code pre { color: #ffdead; overflow: hidden; } - -/* --- Ruby keyword styles --------------------- */ - -.standalone-code { background: #221111; color: #ffdead; overflow: hidden; } - -.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: #b22222; font-weight: bold; background: transparent; } -.ruby-regexp { color: #ffa07a; background: transparent; } -.ruby-value { color: #7fffd4; background: transparent; } - CSS - - RDOC_NO_DOCUMENTATION = <<-'ERB'.freeze - - - - - Found documentation - - - -
-<%= SEARCH %> -

No documentation found

-
- -
-
-
-

No gems matched <%= h query.inspect %>

- -

- Back to complete gem index -

- -
-
-
- - - - ERB - - RDOC_SEARCH_TEMPLATE = <<-'ERB'.freeze - - - - - Found documentation - - - -
-<%= SEARCH %> -

Found documentation

-
- - -
-
-
-

Summary

-

<%=doc_items.length%> documentation topics found.

-

Topics

- -
- <% doc_items.each do |doc_item| %> -
- <%=doc_item[:name]%> - [rdoc] -
-
- <%=h doc_item[:summary]%> -
-
-
- <% end %> -
- -

- Back to complete gem index -

- -
-
-
- - - - ERB - - def self.run(options) - new(options[:gemdir], options[:port], options[:daemon], - options[:launch], options[:addresses]).run - end - - def initialize(gem_dirs, port, daemon, launch = nil, addresses = nil) - Gem::RDoc.load_rdoc - Socket.do_not_reverse_lookup = true - - @gem_dirs = Array gem_dirs - @port = port - @daemon = daemon - @launch = launch - @addresses = addresses - - logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL - @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger - - @spec_dirs = @gem_dirs.map { |gem_dir| File.join gem_dir, 'specifications' } - @spec_dirs.reject! { |spec_dir| !File.directory? spec_dir } - - reset_gems - - @have_rdoc_4_plus = nil - end - - def add_date(res) - res['date'] = @spec_dirs.map do |spec_dir| - File.stat(spec_dir).mtime - end.max - end - - def uri_encode(str) - str.gsub(URI::UNSAFE) do |match| - match.each_byte.map { |c| sprintf('%%%02X', c.ord) }.join - end - end - - def doc_root(gem_name) - if have_rdoc_4_plus? - "/doc_root/#{u gem_name}/" - else - "/doc_root/#{u gem_name}/rdoc/index.html" - end - end - - def have_rdoc_4_plus? - @have_rdoc_4_plus ||= - Gem::Requirement.new('>= 4.0.0.preview2').satisfied_by? Gem::RDoc.rdoc_version - end - - def latest_specs(req, res) - reset_gems - - res['content-type'] = 'application/x-gzip' - - add_date res - - latest_specs = Gem::Specification.latest_specs - - specs = latest_specs.sort.map do |spec| - platform = spec.original_platform || Gem::Platform::RUBY - [spec.name, spec.version, platform] - end - - specs = Marshal.dump specs - - if req.path =~ /\.gz$/ - specs = Gem::Util.gzip specs - res['content-type'] = 'application/x-gzip' - else - res['content-type'] = 'application/octet-stream' - end - - if req.request_method == 'HEAD' - res['content-length'] = specs.length - else - res.body << specs - end - end - - ## - # Creates server sockets based on the addresses option. If no addresses - # were given a server socket for all interfaces is created. - - def listen(addresses = @addresses) - addresses = [nil] unless addresses - - listeners = 0 - - addresses.each do |address| - begin - @server.listen address, @port - @server.listeners[listeners..-1].each do |listener| - host, port = listener.addr.values_at 2, 1 - host = "[#{host}]" if host =~ /:/ # we don't reverse lookup - say "Server started at http://#{host}:#{port}" - end - - listeners = @server.listeners.length - rescue SystemCallError - next - end - end - - if @server.listeners.empty? - say "Unable to start a server." - say "Check for running servers or your --bind and --port arguments" - terminate_interaction 1 - end - end - - def prerelease_specs(req, res) - reset_gems - - res['content-type'] = 'application/x-gzip' - - add_date res - - specs = Gem::Specification.select do |spec| - spec.version.prerelease? - end.sort.map do |spec| - platform = spec.original_platform || Gem::Platform::RUBY - [spec.name, spec.version, platform] - end - - specs = Marshal.dump specs - - if req.path =~ /\.gz$/ - specs = Gem::Util.gzip specs - res['content-type'] = 'application/x-gzip' - else - res['content-type'] = 'application/octet-stream' - end - - if req.request_method == 'HEAD' - res['content-length'] = specs.length - else - res.body << specs - end - end - - def quick(req, res) - reset_gems - - res['content-type'] = 'text/plain' - add_date res - - case req.request_uri.path - when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)\.gemspec\.rz$| then - marshal_format, full_name = $1, $2 - specs = Gem::Specification.find_all_by_full_name(full_name) - - selector = full_name.inspect - - if specs.empty? - res.status = 404 - res.body = "No gems found matching #{selector}" - elsif specs.length > 1 - res.status = 500 - res.body = "Multiple gems found matching #{selector}" - elsif marshal_format - res['content-type'] = 'application/x-deflate' - res.body << Gem.deflate(Marshal.dump(specs.first)) - end - else - raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." - end - end - - def root(req, res) - reset_gems - - add_date res - - raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless - req.path == '/' - - specs = [] - total_file_count = 0 - - Gem::Specification.each do |spec| - total_file_count += spec.files.size - deps = spec.dependencies.map do |dep| - { - "name" => dep.name, - "type" => dep.type, - "version" => dep.requirement.to_s, - } - end - - deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] } - deps.last["is_last"] = true unless deps.empty? - - # executables - executables = spec.executables.sort.collect { |exec| {"executable" => exec} } - executables = nil if executables.empty? - executables.last["is_last"] = true if executables - - # Pre-process spec homepage for safety reasons - begin - homepage_uri = URI.parse(spec.homepage) - if [URI::HTTP, URI::HTTPS].member? homepage_uri.class - homepage_uri = spec.homepage - else - homepage_uri = "." - end - rescue URI::InvalidURIError - homepage_uri = "." - end - - specs << { - "authors" => spec.authors.sort.join(", "), - "date" => spec.date.to_s, - "dependencies" => deps, - "doc_path" => doc_root(spec.full_name), - "executables" => executables, - "only_one_executable" => (executables && executables.size == 1), - "full_name" => spec.full_name, - "has_deps" => !deps.empty?, - "homepage" => homepage_uri, - "name" => spec.name, - "rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?, - "ri_installed" => Gem::RDoc.new(spec).ri_installed?, - "summary" => spec.summary, - "version" => spec.version.to_s, - } - end - - specs << { - "authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others", - "dependencies" => [], - "doc_path" => doc_root("rubygems-#{Gem::VERSION}"), - "executables" => [{"executable" => 'gem', "is_last" => true}], - "only_one_executable" => true, - "full_name" => "rubygems-#{Gem::VERSION}", - "has_deps" => false, - "homepage" => "http://guides.rubygems.org/", - "name" => 'rubygems', - "ri_installed" => true, - "summary" => "RubyGems itself", - "version" => Gem::VERSION, - } - - specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] } - specs.last["is_last"] = true - - # tag all specs with first_name_entry - last_spec = nil - specs.each do |spec| - is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase) - spec["first_name_entry"] = is_first - last_spec = spec - end - - # create page from template - template = ERB.new(DOC_TEMPLATE) - res['content-type'] = 'text/html' - - values = { "gem_count" => specs.size.to_s, "specs" => specs, - "total_file_count" => total_file_count.to_s } - - # suppress 1.9.3dev warning about unused variable - values = values - - result = template.result binding - res.body = result - end - - ## - # Can be used for quick navigation to the rdoc documentation. You can then - # define a search shortcut for your browser. E.g. in Firefox connect - # 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can - # directly open the ActionPack documentation by typing 'rdoc actionp'. If - # there are multiple hits for the search term, they are presented as a list - # with links. - # - # Search algorithm aims for an intuitive search: - # 1. first try to find the gems and documentation folders which name - # starts with the search term - # 2. search for entries, that *contain* the search term - # 3. show all the gems - # - # If there is only one search hit, user is immediately redirected to the - # documentation for the particular gem, otherwise a list with results is - # shown. - # - # === Additional trick - install documentation for Ruby core - # - # Note: please adjust paths accordingly use for example 'locate yaml.rb' and - # 'gem environment' to identify directories, that are specific for your - # local installation - # - # 1. install Ruby sources - # cd /usr/src - # sudo apt-get source ruby - # - # 2. generate documentation - # rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \ - # /usr/lib/ruby/1.8 ruby1.8-1.8.7.72 - # - # By typing 'rdoc core' you can now access the core documentation - - def rdoc(req, res) - query = req.query['q'] - show_rdoc_for_pattern("#{query}*", res) && return - show_rdoc_for_pattern("*#{query}*", res) && return - - template = ERB.new RDOC_NO_DOCUMENTATION - - res['content-type'] = 'text/html' - res.body = template.result binding - end - - ## - # Updates the server to use the latest installed gems. - - def reset_gems # :nodoc: - Gem::Specification.dirs = @gem_dirs - end - - ## - # Returns true and prepares http response, if rdoc for the requested gem - # name pattern was found. - # - # The search is based on the file system content, not on the gems metadata. - # This allows additional documentation folders like 'core' for the Ruby core - # documentation - just put it underneath the main doc folder. - - def show_rdoc_for_pattern(pattern, res) - found_gems = Dir.glob("{#{@gem_dirs.join ','}}/doc/#{pattern}").select do |path| - File.exist? File.join(path, 'rdoc/index.html') - end - case found_gems.length - when 0 - return false - when 1 - new_path = File.basename(found_gems[0]) - res.status = 302 - res['Location'] = doc_root new_path - return true - else - doc_items = [] - found_gems.each do |file_name| - base_name = File.basename(file_name) - doc_items << { - :name => base_name, - :url => doc_root(new_path), - :summary => '' - } - end - - template = ERB.new(RDOC_SEARCH_TEMPLATE) - res['content-type'] = 'text/html' - result = template.result binding - res.body = result - return true - end - end - - def run - listen - - WEBrick::Daemon.start if @daemon - - @server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs) - @server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs) - - @server.mount_proc "/latest_specs.#{Gem.marshal_version}", - method(:latest_specs) - @server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz", - method(:latest_specs) - - @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}", - method(:prerelease_specs) - @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}.gz", - method(:prerelease_specs) - - @server.mount_proc "/quick/", method(:quick) - - @server.mount_proc("/gem-server-rdoc-style.css") do |req, res| - res['content-type'] = 'text/css' - add_date res - res.body << RDOC_CSS - end - - @server.mount_proc "/", method(:root) - - @server.mount_proc "/rdoc", method(:rdoc) - - file_handlers = { - '/gems' => '/cache/', - } - - if have_rdoc_4_plus? - @server.mount '/doc_root', RDoc::Servlet, '/doc_root' - else - file_handlers['/doc_root'] = '/doc/' - end - - @gem_dirs.each do |gem_dir| - file_handlers.each do |mount_point, mount_dir| - @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler, - File.join(gem_dir, mount_dir), true) - end - end - - trap("INT") { @server.shutdown; exit! } - trap("TERM") { @server.shutdown; exit! } - - launch if @launch - - @server.start - end - - def specs(req, res) - reset_gems - - add_date res - - specs = Gem::Specification.sort_by(&:sort_obj).map do |spec| - platform = spec.original_platform || Gem::Platform::RUBY - [spec.name, spec.version, platform] - end - - specs = Marshal.dump specs - - if req.path =~ /\.gz$/ - specs = Gem::Util.gzip specs - res['content-type'] = 'application/x-gzip' - else - res['content-type'] = 'application/octet-stream' - end - - if req.request_method == 'HEAD' - res['content-length'] = specs.length - else - res.body << specs - end - end - - def launch - listeners = @server.listeners.map{|l| l.addr[2] } - - # TODO: 0.0.0.0 == any, not localhost. - host = listeners.any?{|l| l == '0.0.0.0'} ? 'localhost' : listeners.first - - say "Launching browser to http://#{host}:#{@port}" - - system("#{@launch} http://#{host}:#{@port}") - end - -end diff --git a/ruby/lib/rubygems/source.rb b/ruby/lib/rubygems/source.rb index 8572cb180..85c300a8f 100644 --- a/ruby/lib/rubygems/source.rb +++ b/ruby/lib/rubygems/source.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -autoload :FileUtils, 'fileutils' -require "rubygems/text" +require_relative "text" ## # A Source knows how to list and fetch gems from a RubyGems marshal index. # @@ -9,7 +8,6 @@ # bundler dependency API and so-forth. class Gem::Source - include Comparable include Gem::Text @@ -37,6 +35,7 @@ def initialize(uri) end @uri = uri + @update_cache = nil end ## @@ -81,7 +80,15 @@ def ==(other) # :nodoc: def dependency_resolver_set # :nodoc: return Gem::Resolver::IndexSet.new self if 'file' == uri.scheme - bundler_api_uri = uri + './api/v1/dependencies' + fetch_uri = if uri.host == "rubygems.org" + index_uri = uri.dup + index_uri.host = "index.rubygems.org" + index_uri + else + uri + end + + bundler_api_uri = enforce_trailing_slash(fetch_uri) begin fetcher = Gem::RemoteFetcher.fetcher @@ -89,11 +96,7 @@ def dependency_resolver_set # :nodoc: rescue Gem::RemoteFetcher::FetchError Gem::Resolver::IndexSet.new self else - if response.respond_to? :uri - Gem::Resolver::APISet.new response.uri - else - Gem::Resolver::APISet.new bundler_api_uri - end + Gem::Resolver::APISet.new response.uri + "./info/" end end @@ -116,7 +119,8 @@ def cache_dir(uri) # Returns true when it is possible and safe to update the cache directory. def update_cache? - @update_cache ||= + return @update_cache unless @update_cache.nil? + @update_cache = begin File.stat(Gem.user_home).uid == Process.uid rescue Errno::ENOENT @@ -132,7 +136,7 @@ def fetch_spec(name_tuple) spec_file_name = name_tuple.spec_name - source_uri = uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}" + source_uri = enforce_trailing_slash(uri) + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}" cache_dir = cache_dir source_uri @@ -150,6 +154,7 @@ def fetch_spec(name_tuple) spec = Gem::Util.inflate spec if update_cache? + require "fileutils" FileUtils.mkdir_p cache_dir File.open local_spec, 'wb' do |io| @@ -176,12 +181,15 @@ def load_specs(type) file = FILES[type] fetcher = Gem::RemoteFetcher.fetcher file_name = "#{file}.#{Gem.marshal_version}" - spec_path = uri + "#{file_name}.gz" + spec_path = enforce_trailing_slash(uri) + "#{file_name}.gz" cache_dir = cache_dir spec_path local_file = File.join(cache_dir, file_name) retried = false - FileUtils.mkdir_p cache_dir if update_cache? + if update_cache? + require "fileutils" + FileUtils.mkdir_p cache_dir + end spec_dump = fetcher.cache_update_path spec_path, local_file, update_cache? @@ -222,14 +230,19 @@ def pretty_print(q) # :nodoc: def typo_squatting?(host, distance_threshold=4) return if @uri.host.nil? - levenshtein_distance(@uri.host, host) <= distance_threshold + levenshtein_distance(@uri.host, host).between? 1, distance_threshold end + private + + def enforce_trailing_slash(uri) + uri.merge(uri.path.gsub(/\/+$/, '') + '/') + end end -require 'rubygems/source/git' -require 'rubygems/source/installed' -require 'rubygems/source/specific_file' -require 'rubygems/source/local' -require 'rubygems/source/lock' -require 'rubygems/source/vendor' +require_relative 'source/git' +require_relative 'source/installed' +require_relative 'source/specific_file' +require_relative 'source/local' +require_relative 'source/lock' +require_relative 'source/vendor' diff --git a/ruby/lib/rubygems/source/git.rb b/ruby/lib/rubygems/source/git.rb index 0b8a4339c..cda5aa807 100644 --- a/ruby/lib/rubygems/source/git.rb +++ b/ruby/lib/rubygems/source/git.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'rubygems/util' ## # A git gem for use in a gem dependencies file. @@ -12,7 +11,6 @@ # source.specs class Gem::Source::Git < Gem::Source - ## # The name of the gem created by this git gem. @@ -103,9 +101,11 @@ def checkout # :nodoc: success = system @git, 'reset', '--quiet', '--hard', rev_parse - success &&= - Gem::Util.silent_system @git, 'submodule', 'update', - '--quiet', '--init', '--recursive' if @need_submodules + if @need_submodules + _, status = Open3.capture2e(@git, 'submodule', 'update', '--quiet', '--init', '--recursive') + + success &&= status.success? + end success end @@ -225,17 +225,16 @@ def specs # A hash for the git gem based on the git repository URI. def uri_hash # :nodoc: - require 'digest' # required here to avoid deadlocking in Gem.activate_bin_path (because digest is a gem on 2.5+) + require_relative '../openssl' normalized = - if @repository =~ %r%^\w+://(\w+@)?% - uri = URI(@repository).normalize.to_s.sub %r%/$%,'' + if @repository =~ %r{^\w+://(\w+@)?} + uri = URI(@repository).normalize.to_s.sub %r{/$},'' uri.sub(/\A(\w+)/) { $1.downcase } else @repository end - Digest::SHA1.hexdigest normalized + OpenSSL::Digest::SHA1.hexdigest normalized end - end diff --git a/ruby/lib/rubygems/source/installed.rb b/ruby/lib/rubygems/source/installed.rb index 8e20cbd76..7e1dd7af5 100644 --- a/ruby/lib/rubygems/source/installed.rb +++ b/ruby/lib/rubygems/source/installed.rb @@ -3,7 +3,6 @@ # Represents an installed gem. This is used for dependency resolution. class Gem::Source::Installed < Gem::Source - def initialize # :nodoc: @uri = nil end @@ -36,5 +35,4 @@ def download(spec, path) def pretty_print(q) # :nodoc: q.text '[Installed]' end - end diff --git a/ruby/lib/rubygems/source/local.rb b/ruby/lib/rubygems/source/local.rb index 875e992d8..078b06203 100644 --- a/ruby/lib/rubygems/source/local.rb +++ b/ruby/lib/rubygems/source/local.rb @@ -4,7 +4,6 @@ # dependencies. class Gem::Source::Local < Gem::Source - def initialize # :nodoc: @specs = nil @api_uri = nil @@ -61,7 +60,7 @@ def load_specs(type) # :nodoc: when :latest tup = pkg.spec.name_tuple - cur = names.find { |x| x.name == tup.name } + cur = names.find {|x| x.name == tup.name } if !cur names << tup elsif cur.version < tup.version @@ -98,7 +97,7 @@ def find_gem(gem_name, version = Gem::Requirement.default, # :nodoc: end end - found.max_by { |s| s.version } + found.max_by {|s| s.version } end def fetch_spec(name) # :nodoc: @@ -129,5 +128,4 @@ def pretty_print(q) # :nodoc: end end end - end diff --git a/ruby/lib/rubygems/source/lock.rb b/ruby/lib/rubygems/source/lock.rb index 3b3f49175..49f097467 100644 --- a/ruby/lib/rubygems/source/lock.rb +++ b/ruby/lib/rubygems/source/lock.rb @@ -5,7 +5,6 @@ # dependency lock files. class Gem::Source::Lock < Gem::Source - ## # The wrapped Gem::Source @@ -48,5 +47,4 @@ def fetch_spec(name_tuple) def uri # :nodoc: @wrapped.uri end - end diff --git a/ruby/lib/rubygems/source/specific_file.rb b/ruby/lib/rubygems/source/specific_file.rb index a22772b9c..24db1440d 100644 --- a/ruby/lib/rubygems/source/specific_file.rb +++ b/ruby/lib/rubygems/source/specific_file.rb @@ -4,7 +4,6 @@ # local gems. class Gem::Source::SpecificFile < Gem::Source - ## # The path to the gem for this specific file. @@ -69,5 +68,4 @@ def <=>(other) super end end - end diff --git a/ruby/lib/rubygems/source/vendor.rb b/ruby/lib/rubygems/source/vendor.rb index a87fa6333..543acf138 100644 --- a/ruby/lib/rubygems/source/vendor.rb +++ b/ruby/lib/rubygems/source/vendor.rb @@ -3,7 +3,6 @@ # This represents a vendored source that is similar to an installed gem. class Gem::Source::Vendor < Gem::Source::Installed - ## # Creates a new Vendor source for a gem that was unpacked at +path+. @@ -23,5 +22,4 @@ def <=>(other) nil end end - end diff --git a/ruby/lib/rubygems/source_list.rb b/ruby/lib/rubygems/source_list.rb index b1d1f2c36..16e90e1ef 100644 --- a/ruby/lib/rubygems/source_list.rb +++ b/ruby/lib/rubygems/source_list.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'rubygems/source' ## # The SourceList represents the sources rubygems has been configured to use. @@ -15,7 +14,6 @@ # The most common way to get a SourceList is Gem.sources. class Gem::SourceList - include Enumerable ## @@ -53,13 +51,13 @@ def <<(obj) require "uri" src = case obj - when URI - Gem::Source.new(obj) - when Gem::Source - obj - else - Gem::Source.new(URI.parse(obj)) - end + when URI + Gem::Source.new(obj) + when Gem::Source + obj + else + Gem::Source.new(URI.parse(obj)) + end @sources << src unless @sources.include?(src) src @@ -90,7 +88,7 @@ def clear # Yields each source URI in the list. def each - @sources.each { |s| yield s.uri.to_s } + @sources.each {|s| yield s.uri.to_s } end ## @@ -115,7 +113,7 @@ def ==(other) # :nodoc: # Returns an Array of source URI Strings. def to_a - @sources.map { |x| x.uri.to_s } + @sources.map {|x| x.uri.to_s } end alias_method :to_ary, :to_a @@ -135,7 +133,7 @@ def include?(other) if other.kind_of? Gem::Source @sources.include? other else - @sources.find { |x| x.uri.to_s == other.to_s } + @sources.find {|x| x.uri.to_s == other.to_s } end end @@ -146,8 +144,7 @@ def delete(source) if source.kind_of? Gem::Source @sources.delete source else - @sources.delete_if { |x| x.uri.to_s == source.to_s } + @sources.delete_if {|x| x.uri.to_s == source.to_s } end end - end diff --git a/ruby/lib/rubygems/source_local.rb b/ruby/lib/rubygems/source_local.rb deleted file mode 100644 index 5107069fd..000000000 --- a/ruby/lib/rubygems/source_local.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true -require 'rubygems/source' -require 'rubygems/source_local' - -unless Gem::Deprecate.skip - Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_local is deprecated; please use rubygems/source/local instead." -end diff --git a/ruby/lib/rubygems/source_specific_file.rb b/ruby/lib/rubygems/source_specific_file.rb deleted file mode 100644 index b676b1d3a..000000000 --- a/ruby/lib/rubygems/source_specific_file.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true -require 'rubygems/source/specific_file' - -unless Gem::Deprecate.skip - Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_specific_file is deprecated; please use rubygems/source/specific_file instead." -end diff --git a/ruby/lib/rubygems/spec_fetcher.rb b/ruby/lib/rubygems/spec_fetcher.rb index cf86b7218..15bfbb6f8 100644 --- a/ruby/lib/rubygems/spec_fetcher.rb +++ b/ruby/lib/rubygems/spec_fetcher.rb @@ -1,15 +1,14 @@ # frozen_string_literal: true -require 'rubygems/remote_fetcher' -require 'rubygems/user_interaction' -require 'rubygems/errors' -require 'rubygems/text' -require 'rubygems/name_tuple' +require_relative 'remote_fetcher' +require_relative 'user_interaction' +require_relative 'errors' +require_relative 'text' +require_relative 'name_tuple' ## # SpecFetcher handles metadata updates from remote gem repositories. class Gem::SpecFetcher - include Gem::UserInteraction include Gem::Text @@ -92,14 +91,14 @@ def search_for_dependency(dependency, matching_platform=true) list.each do |source, specs| if dependency.name.is_a?(String) && specs.respond_to?(:bsearch) - start_index = (0 ... specs.length).bsearch{ |i| specs[i].name >= dependency.name } - end_index = (0 ... specs.length).bsearch{ |i| specs[i].name > dependency.name } + start_index = (0 ... specs.length).bsearch{|i| specs[i].name >= dependency.name } + end_index = (0 ... specs.length).bsearch{|i| specs[i].name > dependency.name } specs = specs[start_index ... end_index] if start_index && end_index end found[source] = specs.select do |tup| if dependency.match?(tup) - if matching_platform and !Gem::Platform.match(tup.platform) + if matching_platform and !Gem::Platform.match_gem?(tup.platform, tup.name) pm = ( rejected_specs[dependency] ||= \ Gem::PlatformMismatch.new(tup.name, tup.version)) @@ -122,7 +121,7 @@ def search_for_dependency(dependency, matching_platform=true) end end - tuples = tuples.sort_by { |x| x[0] } + tuples = tuples.sort_by {|x| x[0].version } return [tuples, errors] end @@ -171,30 +170,33 @@ def spec_for_dependency(dependency, matching_platform=true) # Suggests gems based on the supplied +gem_name+. Returns an array of # alternative gem names. - def suggest_gems_from_name(gem_name, type = :latest) + def suggest_gems_from_name(gem_name, type = :latest, num_results = 5) gem_name = gem_name.downcase.tr('_-', '') max = gem_name.size / 2 names = available_specs(type).first.values.flatten(1) matches = names.map do |n| next unless n.match_platform? - - distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '') - - next if distance >= max - - return [n.name] if distance == 0 - - [n.name, distance] + [n.name, 0] if n.name.downcase.tr('_-', '').include?(gem_name) end.compact + if matches.length < num_results + matches += names.map do |n| + next unless n.match_platform? + distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '') + next if distance >= max + return [n.name] if distance == 0 + [n.name, distance] + end.compact + end + matches = if matches.empty? && type != :prerelease - suggest_gems_from_name gem_name, :prerelease - else - matches.uniq.sort_by { |name, dist| dist } - end + suggest_gems_from_name gem_name, :prerelease + else + matches.uniq.sort_by {|name, dist| dist } + end - matches.first(5).map { |name, dist| name } + matches.map {|name, dist| name }.uniq.first(num_results) end ## @@ -214,27 +216,27 @@ def available_specs(type) @sources.each_source do |source| begin names = case type - when :latest - tuples_for source, :latest - when :released - tuples_for source, :released - when :complete - names = - tuples_for(source, :prerelease, true) + - tuples_for(source, :released) - - names.sort - when :abs_latest - names = - tuples_for(source, :prerelease, true) + - tuples_for(source, :latest) - - names.sort - when :prerelease - tuples_for(source, :prerelease) - else - raise Gem::Exception, "Unknown type - :#{type}" - end + when :latest + tuples_for source, :latest + when :released + tuples_for source, :released + when :complete + names = + tuples_for(source, :prerelease, true) + + tuples_for(source, :released) + + names.sort + when :abs_latest + names = + tuples_for(source, :prerelease, true) + + tuples_for(source, :latest) + + names.sort + when :prerelease + tuples_for(source, :prerelease) + else + raise Gem::Exception, "Unknown type - :#{type}" + end rescue Gem::RemoteFetcher::FetchError => e errors << Gem::SourceFetchProblem.new(source, e) else @@ -251,10 +253,9 @@ def available_specs(type) def tuples_for(source, type, gracefully_ignore=false) # :nodoc: @caches[type][source.uri] ||= - source.load_specs(type).sort_by { |tup| tup.name } + source.load_specs(type).sort_by {|tup| tup.name } rescue Gem::RemoteFetcher::FetchError raise unless gracefully_ignore [] end - end diff --git a/ruby/lib/rubygems/specification.rb b/ruby/lib/rubygems/specification.rb index 5321edfcc..0d72cee51 100644 --- a/ruby/lib/rubygems/specification.rb +++ b/ruby/lib/rubygems/specification.rb @@ -1,19 +1,17 @@ # frozen_string_literal: true -# -*- coding: utf-8 -*- +# #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ -require 'rubygems/version' -require 'rubygems/requirement' -require 'rubygems/platform' -require 'rubygems/deprecate' -require 'rubygems/basic_specification' -require 'rubygems/stub_specification' -require 'rubygems/specification_policy' -require 'rubygems/util/list' +require_relative 'deprecate' +require_relative 'basic_specification' +require_relative 'stub_specification' +require_relative 'platform' +require_relative 'requirement' +require_relative 'util/list' ## # The Specification class contains the information for a gem. Typically @@ -37,7 +35,6 @@ # items you may add to a specification. class Gem::Specification < Gem::BasicSpecification - extend Gem::Deprecate # REFACTOR: Consider breaking out this version stuff into a separate @@ -81,18 +78,18 @@ class Gem::Specification < Gem::BasicSpecification -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'], 1 => [ 'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"', - '"test_file=x" is a shortcut for "test_files=[x]"' + '"test_file=x" is a shortcut for "test_files=[x]"', ], 2 => [ 'Added "required_rubygems_version"', 'Now forward-compatible with future versions', ], 3 => [ - 'Added Fixnum validation to the specification_version' + 'Added Fixnum validation to the specification_version', ], 4 => [ - 'Added sandboxed freeform metadata to the specification version.' - ] + 'Added sandboxed freeform metadata to the specification version.', + ], }.freeze MARSHAL_FIELDS = { # :nodoc: @@ -106,12 +103,8 @@ class Gem::Specification < Gem::BasicSpecification today = Time.now.utc TODAY = Time.utc(today.year, today.month, today.day) # :nodoc: - # rubocop:disable Style/MutableConstant - LOAD_CACHE = {} # :nodoc: - # rubocop:enable Style/MutableConstant - LOAD_CACHE_MUTEX = Mutex.new - - private_constant :LOAD_CACHE if defined? private_constant + @load_cache = {} # :nodoc: + @load_cache_mutex = Thread::Mutex.new VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/.freeze # :nodoc: @@ -169,29 +162,42 @@ class Gem::Specification < Gem::BasicSpecification @@default_value.each do |k,v| INITIALIZE_CODE_FOR_DEFAULTS[k] = case v - when [], {}, true, false, nil, Numeric, Symbol - v.inspect - when String - v.dump - when Numeric - "default_value(:#{k})" - else - "default_value(:#{k}).dup" - end - end - - @@attributes = @@default_value.keys.sort_by { |s| s.to_s } - @@array_attributes = @@default_value.reject { |k,v| v != [] }.keys + when [], {}, true, false, nil, Numeric, Symbol + v.inspect + when String + v.dump + when Numeric + "default_value(:#{k})" + else + "default_value(:#{k}).dup" + end + end + + @@attributes = @@default_value.keys.sort_by {|s| s.to_s } + @@array_attributes = @@default_value.reject {|k,v| v != [] }.keys @@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k| @@default_value[k].nil? end - @@stubs_by_name = {} + def self.clear_specs # :nodoc: + @@all = nil + @@stubs = nil + @@stubs_by_name = {} + @@spec_with_requirable_file = {} + @@active_stub_with_requirable_file = {} + end + private_class_method :clear_specs + + clear_specs # Sentinel object to represent "not found" stubs NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc: - @@spec_with_requirable_file = {} - @@active_stub_with_requirable_file = {} + + # Tracking removed method calls to warn users during build time. + REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc: + def removed_method_calls + @removed_method_calls ||= [] + end ###################################################################### # :section: Required gemspec attributes @@ -219,7 +225,7 @@ class Gem::Specification < Gem::BasicSpecification attr_reader :version ## - # A short summary of this gem's description. Displayed in `gem list -d`. + # A short summary of this gem's description. Displayed in gem list -d. # # The #description should be more detailed than the summary. # @@ -243,12 +249,11 @@ class Gem::Specification < Gem::BasicSpecification # require 'rake' # spec.files = FileList['lib/**/*.rb', # 'bin/*', - # '[A-Z]*', - # 'test/**/*'].to_a + # '[A-Z]*'].to_a # # # or without Rake... # spec.files = Dir['lib/**/*.rb'] + Dir['bin/*'] - # spec.files += Dir['[A-Z]*'] + Dir['test/**/*'] + # spec.files += Dir['[A-Z]*'] # spec.files.reject! { |fn| fn.include? "CVS" } def files @@ -266,7 +271,7 @@ def files # A list of authors for this gem. # # Alternatively, a single author can be specified by assigning a string to - # `spec.author` + # +spec.author+ # # Usage: # @@ -279,6 +284,15 @@ def authors=(value) ###################################################################### # :section: Recommended gemspec attributes + ## + # The version of Ruby required by this gem + # + # Usage: + # + # spec.required_ruby_version = '>= 2.7.0' + + attr_reader :required_ruby_version + ## # A long description of this gem # @@ -322,17 +336,21 @@ def authors=(value) # This should just be the name of your license. The full text of the license # should be inside of the gem (at the top level) when you build it. # - # The simplest way, is to specify the standard SPDX ID + # The simplest way is to specify the standard SPDX ID # https://spdx.org/licenses/ for the license. - # Ideally you should pick one that is OSI (Open Source Initiative) + # Ideally, you should pick one that is OSI (Open Source Initiative) # http://opensource.org/licenses/alphabetical approved. # - # The most commonly used OSI approved licenses are MIT and Apache-2.0. + # The most commonly used OSI-approved licenses are MIT and Apache-2.0. # GitHub also provides a license picker at http://choosealicense.com/. # + # You can also use a custom license file along with your gemspec and specify + # a LicenseRef-, where idstring is the name of the file containing + # the license text. + # # You should specify a license for your gem so that people know how they are - # permitted to use it, and any restrictions you're placing on it. Not - # specifying a license means all rights are reserved; others have no rights + # permitted to use it and any restrictions you're placing on it. Not + # specifying a license means all rights are reserved; others have no right # to use the code for any purpose. # # You can set multiple licenses with #licenses= @@ -384,6 +402,7 @@ def licenses=(licenses) # "mailing_list_uri" => "https://groups.example.com/bestgemever", # "source_code_uri" => "https://example.com/user/bestgemever", # "wiki_uri" => "https://example.com/user/bestgemever/wiki" + # "funding_uri" => "https://example.com/donate" # } # # These links will be used on your gem's page on rubygems.org and must pass @@ -509,11 +528,6 @@ def require_paths=(val) @require_paths = Array(val) end - ## - # The version of Ruby required by this gem - - attr_reader :required_ruby_version - ## # The RubyGems version required by this gem @@ -554,6 +568,10 @@ def add_development_dependency(gem, *requirements) # spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4' def add_runtime_dependency(gem, *requirements) + if requirements.uniq.size != requirements.size + warn "WARNING: duplicated #{gem} dependency #{requirements}" + end + add_dependency_with_type(gem, :runtime, requirements) end @@ -659,6 +677,9 @@ def rdoc_options # # # Only prereleases or final releases after 2.6.0.preview2 # spec.required_ruby_version = '> 2.6.0.preview2' + # + # # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0 + # spec.required_ruby_version = '>= 2.3', '< 4' def required_ruby_version=(req) @required_ruby_version = Gem::Requirement.create req @@ -719,21 +740,13 @@ def test_files=(files) # :nodoc: # Deprecated: You must now specify the executable name to Gem.bin_path. attr_writer :default_executable - deprecate :default_executable=, :none, 2018, 12 + rubygems_deprecate :default_executable= ## # Allows deinstallation of gems with legacy platforms. attr_writer :original_platform # :nodoc: - ## - # Deprecated and ignored. - # - # Formerly used to set rubyforge project. - - attr_writer :rubyforge_project - deprecate :rubyforge_project=, :none, 2019, 12 - ## # The Gem::Specification version of this gemspec. # @@ -742,23 +755,15 @@ def test_files=(files) # :nodoc: attr_accessor :specification_version def self._all # :nodoc: - unless defined?(@@all) && @@all - @@all = stubs.map(&:to_spec) - - # After a reset, make sure already loaded specs - # are still marked as activated. - specs = {} - Gem.loaded_specs.each_value{|s| specs[s] = true} - @@all.each{|s| s.activated = true if specs[s]} - end - @@all + @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) end - def self._clear_load_cache # :nodoc: - LOAD_CACHE_MUTEX.synchronize do - LOAD_CACHE.clear + def self.clear_load_cache # :nodoc: + @load_cache_mutex.synchronize do + @load_cache.clear end end + private_class_method :clear_load_cache def self.each_gemspec(dirs) # :nodoc: dirs.each do |dir| @@ -769,7 +774,7 @@ def self.each_gemspec(dirs) # :nodoc: end def self.gemspec_stubs_in(dir, pattern) - Gem::Util.glob_files_in_dir(pattern, dir).map { |path| yield path }.select(&:valid?) + Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?) end private_class_method :gemspec_stubs_in @@ -784,21 +789,11 @@ def self.map_stubs(dirs, pattern) # :nodoc: dirs.flat_map do |dir| base_dir = File.dirname dir gems_dir = File.join base_dir, "gems" - gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir } + gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir } end end private_class_method :map_stubs - def self.uniq_by(list, &block) # :nodoc: - list.uniq(&block) - end - private_class_method :uniq_by - - def self.sort_by!(list, &block) - list.sort_by!(&block) - end - private_class_method :sort_by! - def self.each_spec(dirs) # :nodoc: each_gemspec(dirs) do |path| spec = self.load path @@ -812,11 +807,9 @@ def self.each_spec(dirs) # :nodoc: def self.stubs @@stubs ||= begin pattern = "*.gemspec" - stubs = Gem.loaded_specs.values + installed_stubs(dirs, pattern) + default_stubs(pattern) - stubs = uniq_by(stubs) { |stub| stub.full_name } + stubs = stubs_for_pattern(pattern, false) - _resort!(stubs) - @@stubs_by_name = stubs.select { |s| Gem::Platform.match s.platform }.group_by(&:name) + @@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name) stubs end end @@ -832,8 +825,6 @@ def self.default_stubs(pattern = "*.gemspec") end end - EMPTY = [].freeze # :nodoc: - ## # Returns a Gem::StubSpecification for installed gem named +name+ # only returns stubs that match Gem.platforms @@ -842,23 +833,32 @@ def self.stubs_for(name) if @@stubs @@stubs_by_name[name] || [] else - pattern = "#{name}-*.gemspec" - stubs = Gem.loaded_specs.values + - installed_stubs(dirs, pattern).select { |s| Gem::Platform.match s.platform } + - default_stubs(pattern) - stubs = uniq_by(stubs) { |stub| stub.full_name }.group_by(&:name) - stubs.each_value { |v| _resort!(v) } - - @@stubs_by_name.merge! stubs - @@stubs_by_name[name] ||= EMPTY + @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s| + s.name == name + end end end + ## + # Finds stub specifications matching a pattern from the standard locations, + # optionally filtering out specs not matching the current platform + # + def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc: + installed_stubs = installed_stubs(Gem::Specification.dirs, pattern) + installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform + stubs = installed_stubs + default_stubs(pattern) + stubs = stubs.uniq {|stub| stub.full_name } + _resort!(stubs) + stubs + end + def self._resort!(specs) # :nodoc: specs.sort! do |a, b| names = a.name <=> b.name next names if names.nonzero? - b.version <=> a.version + versions = b.version <=> a.version + next versions if versions.nonzero? + Gem::Platform.sort_priority(b.platform) end end @@ -941,7 +941,7 @@ def self.dirs def self.dirs=(dirs) self.reset - @@dirs = Array(dirs).map { |dir| File.join dir, "specifications" } + @@dirs = Array(dirs).map {|dir| File.join dir, "specifications" } end extend Enumerable @@ -994,7 +994,6 @@ def self.find_by_name(name, *requirements) def self.find_by_path(path) path = path.dup.freeze spec = @@spec_with_requirable_file[path] ||= (stubs.find do |s| - next unless Gem::BundlerVersionFinder.compatible?(s) s.contains_requirable_file? path end || NOT_FOUND) spec.to_spec @@ -1007,7 +1006,6 @@ def self.find_by_path(path) def self.find_inactive_by_path(path) stub = stubs.find do |s| next if s.activated? - next unless Gem::BundlerVersionFinder.compatible?(s) s.contains_requirable_file? path end stub && stub.to_spec @@ -1024,10 +1022,7 @@ def self.find_active_stub_by_path(path) # Return currently unresolved specs that contain the file matching +path+. def self.find_in_unresolved(path) - # TODO: do we need these?? Kill it - specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten - - specs.find_all { |spec| spec.contains_requirable_file? path } + unresolved_specs.find_all {|spec| spec.contains_requirable_file? path } end ## @@ -1035,9 +1030,7 @@ def self.find_in_unresolved(path) # specs that contain the file matching +path+. def self.find_in_unresolved_tree(path) - specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten - - specs.each do |spec| + unresolved_specs.each do |spec| spec.traverse do |from_spec, dep, to_spec, trail| if to_spec.has_conflicts? || to_spec.conficts_when_loaded_with?(trail) :next @@ -1050,6 +1043,11 @@ def self.find_in_unresolved_tree(path) [] end + def self.unresolved_specs + unresolved_deps.values.map {|dep| dep.to_specs }.flatten + end + private_class_method :unresolved_specs + ## # Special loader for YAML files. When a Specification object is loaded # from a YAML file, it bypasses the normal Ruby object initialization @@ -1083,24 +1081,26 @@ def self.from_yaml(input) # +prerelease+ is true. def self.latest_specs(prerelease = false) - _latest_specs Gem::Specification._all, prerelease + _latest_specs Gem::Specification.stubs, prerelease + end + + ## + # Return the latest installed spec for gem +name+. + + def self.latest_spec_for(name) + latest_specs(true).find {|installed_spec| installed_spec.name == name } end def self._latest_specs(specs, prerelease = false) # :nodoc: - result = Hash.new { |h,k| h[k] = {} } - native = {} + result = {} specs.reverse_each do |spec| next if spec.version.prerelease? unless prerelease - native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY - result[spec.name][spec.platform] = spec + result[spec.name] = spec end - result.map(&:last).map(&:values).flatten.reject do |spec| - minimum = native[spec.name] - minimum && spec.version < minimum - end.sort_by{ |tup| tup.name } + result.map(&:last).flatten.sort_by{|tup| tup.name } end ## @@ -1109,13 +1109,13 @@ def self._latest_specs(specs, prerelease = false) # :nodoc: def self.load(file) return unless file - _spec = LOAD_CACHE_MUTEX.synchronize { LOAD_CACHE[file] } + _spec = @load_cache_mutex.synchronize { @load_cache[file] } return _spec if _spec file = file.dup.tap(&Gem::UNTAINT) return unless File.file?(file) - code = File.read file, :mode => 'r:UTF-8:-' + code = Gem.open_file(file, 'r:UTF-8:-', &:read) code.tap(&Gem::UNTAINT) @@ -1124,12 +1124,12 @@ def self.load(file) if Gem::Specification === _spec _spec.loaded_from = File.expand_path file.to_s - LOAD_CACHE_MUTEX.synchronize do - prev = LOAD_CACHE[file] + @load_cache_mutex.synchronize do + prev = @load_cache[file] if prev _spec = prev else - LOAD_CACHE[file] = _spec + @load_cache[file] = _spec end end return _spec @@ -1157,7 +1157,7 @@ def self.non_nil_attributes def self.normalize_yaml_input(input) result = input.respond_to?(:read) ? input.read : input - result = "--- " + result unless result =~ /\A--- / + result = "--- " + result unless result.start_with?("--- ") result = result.dup result.gsub!(/ !!null \n/, " \n") # date: 2011-04-26 00:00:00.000000000Z @@ -1174,7 +1174,7 @@ def self.normalize_yaml_input(input) # version as well. def self.outdated - outdated_and_latest_version.map { |local, _| local.name } + outdated_and_latest_version.map {|local, _| local.name } end ## @@ -1195,7 +1195,7 @@ def self.outdated_and_latest_version Gem::Dependency.new local_spec.name, ">= #{local_spec.version}" remotes, = fetcher.search_for_dependency dependency - remotes = remotes.map { |n, _| n.version } + remotes = remotes.map {|n, _| n.version } latest_remote = remotes.sort.last @@ -1226,13 +1226,9 @@ def self.required_attributes def self.reset @@dirs = nil - Gem.pre_reset_hooks.each { |hook| hook.call } - @@all = nil - @@stubs = nil - @@stubs_by_name = {} - @@spec_with_requirable_file = {} - @@active_stub_with_requirable_file = {} - _clear_load_cache + Gem.pre_reset_hooks.each {|hook| hook.call } + clear_specs + clear_load_cache unresolved = unresolved_deps unless unresolved.empty? w = "W" + "ARN" @@ -1243,19 +1239,19 @@ def self.reset versions = find_all_by_name(dep.name) unless versions.empty? warn " Available/installed versions of this gem:" - versions.each { |s| warn " - #{s.version}" } + versions.each {|s| warn " - #{s.version}" } end end warn "#{w}: Clearing out unresolved specs. Try 'gem cleanup '" warn "Please report a bug if this causes problems." unresolved.clear end - Gem.post_reset_hooks.each { |hook| hook.call } + Gem.post_reset_hooks.each {|hook| hook.call } end # DOC: This method needs documented or nodoc'd def self.unresolved_deps - @unresolved_deps ||= Hash.new { |h, n| h[n] = Gem::Dependency.new n } + @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n } end ## @@ -1272,21 +1268,21 @@ def self._load(str) current_version = CURRENT_SPECIFICATION_VERSION field_count = if spec.specification_version > current_version - spec.instance_variable_set :@specification_version, - current_version - MARSHAL_FIELDS[current_version] - else - MARSHAL_FIELDS[spec.specification_version] - end + spec.instance_variable_set :@specification_version, + current_version + MARSHAL_FIELDS[current_version] + else + MARSHAL_FIELDS[spec.specification_version] + end if array.size < field_count raise TypeError, "invalid Gem::Specification format #{array.inspect}" end - # Cleanup any YAML::PrivateType. They only show up for an old bug + # Cleanup any Psych::PrivateType. They only show up for an old bug # where nil => null, so just convert them to nil based on the type. - array.map! { |e| e.kind_of?(YAML::PrivateType) ? nil : e } + array.map! {|e| e.kind_of?(Psych::PrivateType) ? nil : e } spec.instance_variable_set :@rubygems_version, array[0] # spec version @@ -1351,7 +1347,7 @@ def _dump(limit) true, # has_rdoc @new_platform, @licenses, - @metadata + @metadata, ] end @@ -1399,7 +1395,11 @@ def activate_dependencies raise e end - specs = spec_dep.to_specs + begin + specs = spec_dep.to_specs + rescue Gem::MissingSpecError => e + raise Gem::MissingSpecError.new(e.name, e.requirement, "at: #{self.spec_file}") + end if specs.size == 1 specs.first.activate @@ -1435,7 +1435,7 @@ def sanitize self.summary = sanitize_string(summary) self.description = sanitize_string(description) self.post_install_message = sanitize_string(post_install_message) - self.authors = authors.collect { |a| sanitize_string(a) } + self.authors = authors.collect {|a| sanitize_string(a) } end ## @@ -1447,13 +1447,7 @@ def sanitize_string(string) # HACK the #to_s is in here because RSpec has an Array of Arrays of # Strings for authors. Need a way to disallow bad values on gemspec # generation. (Probably won't happen.) - string = string.to_s - - begin - Builder::XChar.encode string - rescue NameError, NoMethodError - string.to_xs - end + string.to_s end ## @@ -1464,7 +1458,7 @@ def add_bindir(executables) return nil if executables.nil? if @bindir - Array(executables).map { |e| File.join(@bindir, e) } + Array(executables).map {|e| File.join(@bindir, e) } else executables end @@ -1479,10 +1473,10 @@ def add_bindir(executables) def add_dependency_with_type(dependency, type, requirements) requirements = if requirements.empty? - Gem::Requirement.default - else - requirements.flatten - end + Gem::Requirement.default + else + requirements.flatten + end unless dependency.respond_to?(:name) && dependency.respond_to?(:requirement) @@ -1546,7 +1540,7 @@ def bin_file(name) def build_args if File.exist? build_info_file build_info = File.readlines build_info_file - build_info = build_info.map { |x| x.strip } + build_info = build_info.map {|x| x.strip } build_info.delete "" build_info else @@ -1559,9 +1553,8 @@ def build_args # the gem.build_complete file is missing. def build_extensions # :nodoc: - return if default_gem? return if extensions.empty? - return if installed_by_version < Gem::Version.new('2.2.0.preview.2') + return if default_gem? return if File.exist? gem_build_complete_path return if !File.writable?(base_dir) return if !File.exist?(File.join(base_dir, 'extensions')) @@ -1572,9 +1565,9 @@ def build_extensions # :nodoc: unresolved_deps = Gem::Specification.unresolved_deps.dup Gem::Specification.unresolved_deps.clear - require 'rubygems/config_file' - require 'rubygems/ext' - require 'rubygems/user_interaction' + require_relative 'config_file' + require_relative 'ext' + require_relative 'user_interaction' ui = Gem::SilentUI.new Gem::DefaultUserInteraction.use_ui ui do @@ -1638,7 +1631,7 @@ def conflicts def conficts_when_loaded_with?(list_of_specs) # :nodoc: result = list_of_specs.any? do |spec| - spec.dependencies.any? { |dep| dep.runtime? && (dep.name == name) && !satisfies_requirement?(dep) } + spec.dependencies.any? {|dep| dep.runtime? && (dep.name == name) && !satisfies_requirement?(dep) } end result end @@ -1691,24 +1684,18 @@ def date=(date) # This is the cleanest, most-readable, faster-than-using-Date # way to do it. @date = case date - when String then - if DateTimeFormat =~ date - Time.utc($1.to_i, $2.to_i, $3.to_i) - - # Workaround for where the date format output from psych isn't - # parsed as a Time object by syck and thus comes through as a - # string. - elsif /\A(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}\.\d+?Z\z/ =~ date - Time.utc($1.to_i, $2.to_i, $3.to_i) - else - raise(Gem::InvalidSpecificationException, - "invalid date format in specification: #{date.inspect}") - end - when Time, DateLike then - Time.utc(date.year, date.month, date.day) - else - TODAY - end + when String then + if DateTimeFormat =~ date + Time.utc($1.to_i, $2.to_i, $3.to_i) + else + raise(Gem::InvalidSpecificationException, + "invalid date format in specification: #{date.inspect}") + end + when Time, DateLike then + Time.utc(date.year, date.month, date.day) + else + TODAY + end end ## @@ -1727,7 +1714,7 @@ def default_executable # :nodoc: end result end - deprecate :default_executable, :none, 2018, 12 + rubygems_deprecate :default_executable ## # The default value for specification attribute +name+ @@ -1752,10 +1739,11 @@ def dependencies # # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]] - def dependent_gems + def dependent_gems(check_dev=true) out = [] Gem::Specification.each do |spec| - spec.dependencies.each do |dep| + deps = check_dev ? spec.dependencies : spec.runtime_dependencies + deps.each do |dep| if self.satisfies_requirement?(dep) sats = [] find_all_satisfiers(dep) do |sat| @@ -1772,7 +1760,7 @@ def dependent_gems # Returns all specs that matches this spec's runtime dependencies. def dependent_specs - runtime_dependencies.map { |dep| dep.to_specs }.flatten + runtime_dependencies.map {|dep| dep.to_specs }.flatten end ## @@ -1786,7 +1774,7 @@ def description=(str) # List of dependencies that are used for development def development_dependencies - dependencies.select { |d| d.type == :development } + dependencies.select {|d| d.type == :development } end ## @@ -1813,13 +1801,13 @@ def encode_with(coder) # :nodoc: coder.add 'name', @name coder.add 'version', @version platform = case @original_platform - when nil, '' then - 'ruby' - when String then - @original_platform - else - @original_platform.to_s - end + when nil, '' then + 'ruby' + when String then + @original_platform + else + @original_platform.to_s + end coder.add 'platform', platform attributes = @@attributes.map(&:to_s) - %w[name version platform] @@ -1847,29 +1835,23 @@ def executable=(o) end ## - # Sets executables to +value+, ensuring it is an array. Don't - # use this, push onto the array instead. + # Sets executables to +value+, ensuring it is an array. def executables=(value) - # TODO: warn about setting instead of pushing @executables = Array(value) end ## - # Sets extensions to +extensions+, ensuring it is an array. Don't - # use this, push onto the array instead. + # Sets extensions to +extensions+, ensuring it is an array. def extensions=(extensions) - # TODO: warn about setting instead of pushing @extensions = Array extensions end ## - # Sets extra_rdoc_files to +files+, ensuring it is an array. Don't - # use this, push onto the array instead. + # Sets extra_rdoc_files to +files+, ensuring it is an array. def extra_rdoc_files=(files) - # TODO: warn about setting instead of pushing @extra_rdoc_files = Array files end @@ -1935,7 +1917,7 @@ def gems_dir def has_rdoc # :nodoc: true end - deprecate :has_rdoc, :none, 2018, 12 + rubygems_deprecate :has_rdoc ## # Deprecated and ignored. @@ -1945,10 +1927,10 @@ def has_rdoc # :nodoc: def has_rdoc=(ignored) # :nodoc: @has_rdoc = true end - deprecate :has_rdoc=, :none, 2018, 12 + rubygems_deprecate :has_rdoc= alias :has_rdoc? :has_rdoc # :nodoc: - deprecate :has_rdoc?, :none, 2018, 12 + rubygems_deprecate :has_rdoc? ## # True if this gem has files in test_files @@ -1970,7 +1952,9 @@ def init_with(coder) # :nodoc: yaml_initialize coder.tag, coder.map end - eval <<-RB, binding, __FILE__, __LINE__ + 1 + eval <<-RUBY, binding, __FILE__, __LINE__ + 1 + # frozen_string_literal: true + def set_nil_attributes_to_nil #{@@nil_attributes.map {|key| "@#{key} = nil" }.join "; "} end @@ -1980,7 +1964,7 @@ def set_not_nil_attributes_to_default_values #{@@non_nil_attributes.map {|key| "@#{key} = #{INITIALIZE_CODE_FOR_DEFAULTS[key]}" }.join ";"} end private :set_not_nil_attributes_to_default_values - RB + RUBY ## # Specification constructor. Assigns the default values to the attributes @@ -2005,6 +1989,10 @@ def initialize(name = nil, version = nil) self.name = name if name self.version = version if version + if platform = Gem.platforms.last and platform != Gem::Platform::RUBY and platform != Gem::Platform.local + self.platform = platform + end + yield self if block_given? end @@ -2036,10 +2024,10 @@ def initialize_copy(other_spec) def base_dir return Gem.dir unless loaded_from @base_dir ||= if default_gem? - File.dirname File.dirname File.dirname loaded_from - else - File.dirname File.dirname loaded_from - end + File.dirname File.dirname File.dirname loaded_from + else + File.dirname File.dirname loaded_from + end end ## @@ -2107,11 +2095,17 @@ def mark_version end ## + # Track removed method calls to warn about during build time. # Warn about unknown attributes while loading a spec. def method_missing(sym, *a, &b) # :nodoc: + if REMOVED_METHODS.include?(sym) + removed_method_calls << sym + return + end + if @specification_version > CURRENT_SPECIFICATION_VERSION and - sym.to_s =~ /=$/ + sym.to_s.end_with?("=") warn "ignoring #{sym} loading #{full_name}" if $DEBUG else super @@ -2123,9 +2117,8 @@ def method_missing(sym, *a, &b) # :nodoc: # probably want to build_extensions def missing_extensions? - return false if default_gem? return false if extensions.empty? - return false if installed_by_version < Gem::Version.new('2.2.0.preview.2') + return false if default_gem? return false if File.exist? gem_build_complete_path true @@ -2195,7 +2188,7 @@ def pretty_print(q) # :nodoc: attributes.each do |attr_name| current_value = self.send attr_name - current_value = current_value.sort if %i(files test_files).include? attr_name + current_value = current_value.sort if %i[files test_files].include? attr_name if current_value != default_value(attr_name) or self.class.required_attribute? attr_name @@ -2245,11 +2238,9 @@ def raise_if_conflicts # :nodoc: end ## - # Sets rdoc_options to +value+, ensuring it is an array. Don't - # use this, push onto the array instead. + # Sets rdoc_options to +value+, ensuring it is an array. def rdoc_options=(options) - # TODO: warn about setting instead of pushing @rdoc_options = Array options end @@ -2268,11 +2259,9 @@ def require_path=(path) end ## - # Set requirements to +req+, ensuring it is an array. Don't - # use this, push onto the array instead. + # Set requirements to +req+, ensuring it is an array. def requirements=(req) - # TODO: warn about setting instead of pushing @requirements = Array req end @@ -2294,9 +2283,9 @@ def ri_dir def ruby_code(obj) case obj when String then obj.dump + ".freeze" - when Array then '[' + obj.map { |x| ruby_code x }.join(", ") + ']' + when Array then '[' + obj.map {|x| ruby_code x }.join(", ") + ']' when Hash then - seg = obj.keys.sort.map { |k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" } + seg = obj.keys.sort.map {|k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" } "{ #{seg.join(', ')} }" when Gem::Version then obj.to_s.dump when DateLike then obj.strftime('%Y-%m-%d').dump @@ -2324,7 +2313,7 @@ def runtime_dependencies # True if this gem has the same attributes as +other+. def same_attributes?(spec) - @@attributes.all? { |name, default| self.send(name) == spec.send(name) } + @@attributes.all? {|name, default| self.send(name) == spec.send(name) } end private :same_attributes? @@ -2341,7 +2330,7 @@ def satisfies_requirement?(dependency) # Returns an object you can use to sort specifications in #sort_by. def sort_obj - [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1] + [@name, @version, Gem::Platform.sort_priority(@new_platform)] end ## @@ -2423,7 +2412,6 @@ def test_files # :nodoc: # still have their default values are omitted. def to_ruby - require 'openssl' mark_version result = [] result << "# -*- encoding: utf-8 -*-" @@ -2456,17 +2444,22 @@ def to_ruby :version, :has_rdoc, :default_executable, - :metadata + :metadata, + :signing_key, ] @@attributes.each do |attr_name| next if handled.include? attr_name current_value = self.send(attr_name) if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name) - result << " s.#{attr_name} = #{ruby_code current_value}" unless current_value.is_a?(OpenSSL::PKey::RSA) + result << " s.#{attr_name} = #{ruby_code current_value}" end end + if String === signing_key + result << " s.signing_key = #{signing_key.dump}.freeze" + end + if @installed_by_version result << nil result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version" @@ -2529,7 +2522,7 @@ def to_yaml(opts = {}) # :nodoc: # back, we have to check again here to make sure that our # psych code was properly loaded, and load it if not. unless Gem.const_defined?(:NoAliasYAMLTree) - require 'rubygems/psych_tree' + require_relative 'psych_tree' end builder = Gem::NoAliasYAMLTree.create @@ -2554,7 +2547,7 @@ def traverse(trail = [], visited = {}, &block) begin dependencies.each do |dep| next unless dep.runtime? - dep.to_specs.each do |dep_spec| + dep.matching_specs(true).each do |dep_spec| next if visited.has_key?(dep_spec) visited[dep_spec] = true trail.push(dep_spec) @@ -2566,7 +2559,7 @@ def traverse(trail = [], visited = {}, &block) unless result == :next spec_name = dep_spec.name dep_spec.traverse(trail, visited, &block) unless - trail.any? { |s| s.name == spec_name } + trail.any? {|s| s.name == spec_name } end end end @@ -2591,30 +2584,27 @@ def validate(packaging = true, strict = false) end def keep_only_files_and_directories - @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) } - @extensions.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @test_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } + @executables.delete_if {|x| File.directory?(File.join(@bindir, x)) } + @extensions.delete_if {|x| File.directory?(x) && !File.symlink?(x) } + @extra_rdoc_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) } + @files.delete_if {|x| File.directory?(x) && !File.symlink?(x) } + @test_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) } end def validate_metadata Gem::SpecificationPolicy.new(self).validate_metadata end + rubygems_deprecate :validate_metadata - ## - # Checks that dependencies use requirements as we recommend. Warnings are - # issued when dependencies are open-ended or overly strict for semantic - # versioning. def validate_dependencies Gem::SpecificationPolicy.new(self).validate_dependencies end + rubygems_deprecate :validate_dependencies - ## - # Checks to see if the files to be packaged are world-readable. def validate_permissions Gem::SpecificationPolicy.new(self).validate_permissions end + rubygems_deprecate :validate_permissions ## # Set the version to +version+, potentially also setting @@ -2664,9 +2654,9 @@ def reset_nil_attributes_to_default default = self.default_value attribute value = case default - when Time, Numeric, Symbol, true, false, nil then default - else default.dup - end + when Time, Numeric, Symbol, true, false, nil then default + else default.dup + end instance_variable_set "@#{attribute}", value end @@ -2677,8 +2667,4 @@ def reset_nil_attributes_to_default def raw_require_paths # :nodoc: @require_paths end - end - -# DOC: What is this and why is it here, randomly, at the end of this file? -Gem.clear_paths diff --git a/ruby/lib/rubygems/specification_policy.rb b/ruby/lib/rubygems/specification_policy.rb index c3c496db9..002b3c20c 100644 --- a/ruby/lib/rubygems/specification_policy.rb +++ b/ruby/lib/rubygems/specification_policy.rb @@ -1,14 +1,13 @@ -require 'rubygems/user_interaction' +require_relative 'user_interaction' class Gem::SpecificationPolicy - include Gem::UserInteraction VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/.freeze # :nodoc: SPECIAL_CHARACTERS = /\A[#{Regexp.escape('.-_')}]+/.freeze # :nodoc: - VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}.freeze # :nodoc: + VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}.freeze # :nodoc: METADATA_LINK_KEYS = %w[ bug_tracker_uri @@ -18,6 +17,7 @@ class Gem::SpecificationPolicy mailing_list_uri source_code_uri wiki_uri + funding_uri ].freeze # :nodoc: def initialize(specification) @@ -32,13 +32,32 @@ def initialize(specification) attr_accessor :packaging ## - # Checks that the specification contains all required fields, and does a - # very basic sanity check. + # Does a sanity check on the specification. # # Raises InvalidSpecificationException if the spec does not pass the # checks. + # + # It also performs some validations that do not raise but print warning + # messages instead. def validate(strict = false) + validate_required! + + validate_optional(strict) if packaging || strict + + true + end + + ## + # Does a sanity check on the specification. + # + # Raises InvalidSpecificationException if the spec does not pass the + # checks. + # + # Only runs checks that are considered necessary for the specification to be + # functional. + + def validate_required! validate_nil_attributes validate_rubygems_version @@ -65,16 +84,26 @@ def validate(strict = false) validate_metadata + validate_licenses_length + + validate_lazy_metadata + + validate_duplicate_dependencies + end + + def validate_optional(strict) validate_licenses validate_permissions - validate_lazy_metadata - validate_values validate_dependencies + validate_extensions + + validate_removed_attributes + if @warnings > 0 if strict error "specification has warnings" @@ -82,8 +111,6 @@ def validate(strict = false) alert_warning help_text end end - - true end ## @@ -97,39 +124,39 @@ def validate_metadata end metadata.each do |key, value| + entry = "metadata['#{key}']" if !key.kind_of?(String) error "metadata keys must be a String" end if key.size > 128 - error "metadata key too large (#{key.size} > 128)" + error "metadata key is too large (#{key.size} > 128)" end if !value.kind_of?(String) - error "metadata values must be a String" + error "#{entry} value must be a String" end if value.size > 1024 - error "metadata value too large (#{value.size} > 1024)" + error "#{entry} value is too large (#{value.size} > 1024)" end if METADATA_LINK_KEYS.include? key if value !~ VALID_URI_PATTERN - error "metadata['#{key}'] has invalid link: #{value.inspect}" + error "#{entry} has invalid link: #{value.inspect}" end end end end ## - # Implementation for Specification#validate_dependencies + # Checks that no duplicate dependencies are specified. - def validate_dependencies # :nodoc: + def validate_duplicate_dependencies # :nodoc: # NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle - seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) } + seen = Gem::Dependency::TYPES.inject({}) {|types, type| types.merge({ type => {}}) } error_messages = [] - warning_messages = [] @specification.dependencies.each do |dep| if prev = seen[dep.type][dep.name] error_messages << <<-MESSAGE @@ -139,7 +166,20 @@ def validate_dependencies # :nodoc: end seen[dep.type][dep.name] = dep + end + if error_messages.any? + error error_messages.join + end + end + + ## + # Checks that dependencies use requirements as we recommend. Warnings are + # issued when dependencies are open-ended or overly strict for semantic + # versioning. + def validate_dependencies # :nodoc: + warning_messages = [] + @specification.dependencies.each do |dep| prerelease_dep = dep.requirements_list.any? do |req| Gem::Requirement.new(req).prerelease? end @@ -159,26 +199,23 @@ def validate_dependencies # :nodoc: base = segments.first 2 recommendation = if (op == '>' || op == '>=') && segments == [0] - " use a bounded requirement, such as '~> x.y'" - else - bugfix = if op == '>' - ", '> #{dep_version}'" - elsif op == '>=' and base != segments - ", '>= #{dep_version}'" - end - - " if #{dep.name} is semantically versioned, use:\n" \ - " add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}" - end + " use a bounded requirement, such as '~> x.y'" + else + bugfix = if op == '>' + ", '> #{dep_version}'" + elsif op == '>=' and base != segments + ", '>= #{dep_version}'" + end + + " if #{dep.name} is semantically versioned, use:\n" \ + " add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}" + end warning_messages << ["open-ended dependency on #{dep} is not recommended", recommendation].join("\n") + "\n" end end - if error_messages.any? - error error_messages.join - end if warning_messages.any? - warning_messages.each { |warning_message| warning warning_message } + warning_messages.each {|warning_message| warning warning_message } end end @@ -255,7 +292,7 @@ def validate_require_paths def validate_non_files return unless packaging - non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x)} + non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x) } unless non_files.empty? error "[\"#{non_files.join "\", \""}\"] are not files" @@ -280,7 +317,7 @@ def validate_platform platform = @specification.platform case platform - when Gem::Platform, Gem::Platform::RUBY # ok + when Gem::Platform, Gem::Platform::RUBY # ok else error "invalid platform #{platform.inspect}, see Gem::Platform" end @@ -295,15 +332,14 @@ def validate_array_attributes def validate_array_attribute(field) val = @specification.send(field) klass = case field - when :dependencies then - Gem::Dependency - else - String - end - - unless Array === val and val.all? {|x| x.kind_of?(klass)} - raise(Gem::InvalidSpecificationException, - "#{field} must be an Array of #{klass}") + when :dependencies then + Gem::Dependency + else + String + end + + unless Array === val and val.all? {|x| x.kind_of?(klass) } + error "#{field} must be an Array of #{klass}" end end @@ -313,33 +349,39 @@ def validate_authors_field error "authors may not be empty" end - def validate_licenses + def validate_licenses_length licenses = @specification.licenses licenses.each do |license| if license.length > 64 error "each license must be 64 characters or less" end + end + end + def validate_licenses + licenses = @specification.licenses + + licenses.each do |license| if !Gem::Licenses.match?(license) suggestions = Gem::Licenses.suggestions(license) - message = <<-warning + message = <<-WARNING license value '#{license}' is invalid. Use a license identifier from http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. - warning - message += "Did you mean #{suggestions.map { |s| "'#{s}'"}.join(', ')}?\n" unless suggestions.nil? + WARNING + message += "Did you mean #{suggestions.map {|s| "'#{s}'" }.join(', ')}?\n" unless suggestions.nil? warning(message) end end - warning <<-warning if licenses.empty? + warning <<-WARNING if licenses.empty? licenses is empty, but is recommended. Use a license identifier from http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. - warning + WARNING end LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '') - LAZY_PATTERN = /FI XME|TO DO/x.freeze + LAZY_PATTERN = /\AFI XME|\ATO DO/x.freeze HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze def validate_lazy_metadata @@ -391,7 +433,7 @@ def validate_values validate_shebang_line_in(executable) end - @specification.files.select { |f| File.symlink?(f) }.each do |file| + @specification.files.select {|f| File.symlink?(f) }.each do |file| warning "#{file} is a symlink, which is not supported on all platforms" end end @@ -408,6 +450,24 @@ def validate_shebang_line_in(executable) warning "#{executable_path} is missing #! line" end + def validate_removed_attributes # :nodoc: + @specification.removed_method_calls.each do |attr| + warning("#{attr} is deprecated and ignored. Please remove this from your gemspec to ensure that your gem continues to build in the future.") + end + end + + def validate_extensions # :nodoc: + require_relative 'ext' + builder = Gem::Ext::Builder.new(@specification) + + rake_extension = @specification.extensions.any? {|s| builder.builder_for(s) == Gem::Ext::RakeBuilder } + rake_dependency = @specification.dependencies.any? {|d| d.name == 'rake' } + + warning <<-WARNING if rake_extension && !rake_dependency +You have specified rake based extension, but rake is not added as dependency. It is recommended to add rake as a dependency in gemspec since there's no guarantee rake will be already installed. + WARNING + end + def warning(statement) # :nodoc: @warnings += 1 @@ -421,7 +481,6 @@ def error(statement) # :nodoc: end def help_text # :nodoc: - "See http://guides.rubygems.org/specification-reference/ for help" + "See https://guides.rubygems.org/specification-reference/ for help" end - end diff --git a/ruby/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem b/ruby/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem deleted file mode 100644 index 9e6810ab7..000000000 --- a/ruby/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- diff --git a/ruby/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem b/ruby/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem deleted file mode 100644 index 20585f1c0..000000000 --- a/ruby/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- diff --git a/ruby/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem b/ruby/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem similarity index 100% rename from ruby/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem rename to ruby/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem diff --git a/ruby/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem b/ruby/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem new file mode 100644 index 000000000..8afb21905 --- /dev/null +++ b/ruby/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- diff --git a/ruby/lib/rubygems/stub_specification.rb b/ruby/lib/rubygems/stub_specification.rb index 959030fd5..b1dd7397a 100644 --- a/ruby/lib/rubygems/stub_specification.rb +++ b/ruby/lib/rubygems/stub_specification.rb @@ -5,7 +5,6 @@ # information. class Gem::StubSpecification < Gem::BasicSpecification - # :nodoc: PREFIX = "# stub: ".freeze @@ -13,7 +12,6 @@ class Gem::StubSpecification < Gem::BasicSpecification OPEN_MODE = 'r:UTF-8:-'.freeze class StubLine # :nodoc: all - attr_reader :name, :version, :platform, :require_paths, :extensions, :full_name @@ -31,32 +29,31 @@ class StubLine # :nodoc: all # in their require paths, so lets take advantage of that by pre-allocating # a require path list for that case. REQUIRE_PATH_LIST = { # :nodoc: - 'lib' => ['lib'].freeze + 'lib' => ['lib'].freeze, }.freeze def initialize(data, extensions) parts = data[PREFIX.length..-1].split(" ".freeze, 4) @name = parts[0].freeze @version = if Gem::Version.correct?(parts[1]) - Gem::Version.new(parts[1]) - else - Gem::Version.new(0) - end + Gem::Version.new(parts[1]) + else + Gem::Version.new(0) + end @platform = Gem::Platform.new parts[2] @extensions = extensions @full_name = if platform == Gem::Platform::RUBY - "#{name}-#{version}" - else - "#{name}-#{version}-#{platform}" - end + "#{name}-#{version}" + else + "#{name}-#{version}-#{platform}" + end path_list = parts.last @require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0".freeze).map! do |x| REQUIRE_PATHS[x] || x end end - end def self.default_gemspec_stub(filename, base_dir, gems_dir) @@ -113,16 +110,16 @@ def data begin saved_lineno = $. - File.open loaded_from, OPEN_MODE do |file| + Gem.open_file loaded_from, OPEN_MODE do |file| begin file.readline # discard encoding line stubline = file.readline.chomp if stubline.start_with?(PREFIX) extensions = if /\A#{PREFIX}/ =~ file.readline.chomp - $'.split "\0" - else - StubLine::NO_EXTENSIONS - end + $'.split "\0" + else + StubLine::NO_EXTENSIONS + end @data = StubLine.new stubline, extensions end @@ -188,14 +185,11 @@ def full_name def to_spec @spec ||= if @data - loaded = Gem.loaded_specs[name] - loaded if loaded && loaded.version == version - end + loaded = Gem.loaded_specs[name] + loaded if loaded && loaded.version == version + end @spec ||= Gem::Specification.load(loaded_from) - @spec.ignored = @ignored if @spec - - @spec end ## @@ -212,5 +206,4 @@ def valid? def stubbed? data.is_a? StubLine end - end diff --git a/ruby/lib/rubygems/syck_hack.rb b/ruby/lib/rubygems/syck_hack.rb deleted file mode 100644 index 0d87c71df..000000000 --- a/ruby/lib/rubygems/syck_hack.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: true -# :stopdoc: - -# Hack to handle syck's DefaultKey bug -# -# This file is always loaded AFTER either syck or psych are already -# loaded. It then looks at what constants are available and creates -# a consistent view on all rubys. -# -# All this is so that there is always a YAML::Syck::DefaultKey -# class no matter if the full yaml library has loaded or not. -# - -module YAML # :nodoc: - # In newer 1.9.2, there is a Syck toplevel constant instead of it - # being underneath YAML. If so, reference it back under YAML as - # well. - if defined? ::Syck - # for tests that change YAML::ENGINE - # 1.8 does not support the second argument to const_defined? - remove_const :Syck rescue nil - - Syck = ::Syck - - # JRuby's "Syck" is called "Yecht" - elsif defined? YAML::Yecht - Syck = YAML::Yecht - - # Otherwise, if there is no YAML::Syck, then we've got just psych - # loaded, so lets define a stub for DefaultKey. - elsif !defined? YAML::Syck - module Syck - class DefaultKey # :nodoc: - end - end - end - - # Now that we've got something that is always here, define #to_s - # so when code tries to use this, it at least just shows up like it - # should. - module Syck - class DefaultKey - - remove_method :to_s rescue nil - - def to_s - '=' - end - - end - end - - SyntaxError = Error unless defined? SyntaxError -end - -# Sometime in the 1.9 dev cycle, the Syck constant was moved from under YAML -# to be a toplevel constant. So gemspecs created under these versions of Syck -# will have references to Syck::DefaultKey. -# -# So we need to be sure that we reference Syck at the toplevel too so that -# we can always load these kind of gemspecs. -# -if !defined?(Syck) - Syck = YAML::Syck -end - -# Now that we've got Syck setup in all the right places, store -# a reference to the DefaultKey class inside Gem. We do this so that -# if later on YAML, etc are redefined, we've still got a consistent -# place to find the DefaultKey class for comparison. - -module Gem - # for tests that change YAML::ENGINE - remove_const :SyckDefaultKey if const_defined? :SyckDefaultKey - - SyckDefaultKey = YAML::Syck::DefaultKey -end - -# :startdoc: diff --git a/ruby/lib/rubygems/test_case.rb b/ruby/lib/rubygems/test_case.rb deleted file mode 100644 index 206497c65..000000000 --- a/ruby/lib/rubygems/test_case.rb +++ /dev/null @@ -1,1537 +0,0 @@ -# frozen_string_literal: true - -require 'rubygems' - -# If bundler gemspec exists, add to stubs -bundler_gemspec = File.expand_path("../../../bundler/bundler.gemspec", __FILE__) -if File.exist?(bundler_gemspec) - Gem::Specification.dirs.unshift File.dirname(bundler_gemspec) - Gem::Specification.class_variable_set :@@stubs, nil - Gem::Specification.stubs - Gem::Specification.dirs.shift -end - -begin - gem 'minitest', '~> 5.0' -rescue Gem::LoadError -end - -begin - require 'simplecov' - SimpleCov.start do - add_filter "/test/" - add_filter "/bundler/" - add_filter "/lib/rubygems/resolver/molinillo" - end -rescue LoadError -end - -require 'bundler' - -require 'minitest/autorun' - -require 'rubygems/deprecate' - -require 'fileutils' -require 'pathname' -require 'pp' -require 'rubygems/package' -require 'shellwords' -require 'tmpdir' -require 'uri' -require 'zlib' -require 'benchmark' # stdlib -require 'rubygems/mock_gem_ui' - -module Gem - - ## - # Allows setting the gem path searcher. This method is available when - # requiring 'rubygems/test_case' - - def self.searcher=(searcher) - @searcher = searcher - end - - ## - # Allows toggling Windows behavior. This method is available when requiring - # 'rubygems/test_case' - - def self.win_platform=(val) - @@win_platform = val - end - - ## - # Allows setting path to Ruby. This method is available when requiring - # 'rubygems/test_case' - - def self.ruby=(ruby) - @ruby = ruby - end - - ## - # When rubygems/test_case is required the default user interaction is a - # MockGemUi. - - module DefaultUserInteraction - @ui = Gem::MockGemUi.new - end -end - -## -# RubyGemTestCase provides a variety of methods for testing rubygems and -# gem-related behavior in a sandbox. Through RubyGemTestCase you can install -# and uninstall gems, fetch remote gems through a stub fetcher and be assured -# your normal set of gems is not affected. - -class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Unit::TestCase) - - extend Gem::Deprecate - - attr_accessor :fetcher # :nodoc: - - attr_accessor :gem_repo # :nodoc: - - attr_accessor :uri # :nodoc: - - TEST_PATH = ENV.fetch('RUBYGEMS_TEST_PATH', File.expand_path('../../../test/rubygems', __FILE__)) - - def assert_activate(expected, *specs) - specs.each do |spec| - case spec - when String then - Gem::Specification.find_by_name(spec).activate - when Gem::Specification then - spec.activate - else - flunk spec.inspect - end - end - - loaded = Gem.loaded_specs.values.map(&:full_name) - - assert_equal expected.sort, loaded.sort if expected - end - - # TODO: move to minitest - def assert_path_exists(path, msg = nil) - msg = message(msg) { "Expected path '#{path}' to exist" } - assert File.exist?(path), msg - end - - def assert_directory_exists(path, msg = nil) - msg = message(msg) { "Expected path '#{path}' to be a directory" } - assert_path_exists path - assert File.directory?(path), msg - end - - ## - # Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores - # the original value when the block ends - - def enable_shared(value) - enable_shared = RbConfig::CONFIG['ENABLE_SHARED'] - RbConfig::CONFIG['ENABLE_SHARED'] = value - - yield - ensure - if enable_shared - RbConfig::CONFIG['enable_shared'] = enable_shared - else - RbConfig::CONFIG.delete 'enable_shared' - end - end - - ## - # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the - # original value when the block ends - # - def vendordir(value) - vendordir = RbConfig::CONFIG['vendordir'] - - if value - RbConfig::CONFIG['vendordir'] = value - else - RbConfig::CONFIG.delete 'vendordir' - end - - yield - ensure - if vendordir - RbConfig::CONFIG['vendordir'] = vendordir - else - RbConfig::CONFIG.delete 'vendordir' - end - end - - ## - # Sets the bindir entry in RbConfig::CONFIG to +value+ and restores the - # original value when the block ends - # - def bindir(value) - bindir = RbConfig::CONFIG['bindir'] - - if value - RbConfig::CONFIG['bindir'] = value - else - RbConfig::CONFIG.delete 'bindir' - end - - yield - ensure - if bindir - RbConfig::CONFIG['bindir'] = bindir - else - RbConfig::CONFIG.delete 'bindir' - end - end - - ## - # Sets the EXEEXT entry in RbConfig::CONFIG to +value+ and restores the - # original value when the block ends - # - def exeext(value) - exeext = RbConfig::CONFIG['EXEEXT'] - - if value - RbConfig::CONFIG['EXEEXT'] = value - else - RbConfig::CONFIG.delete 'EXEEXT' - end - - yield - ensure - if exeext - RbConfig::CONFIG['EXEEXT'] = exeext - else - RbConfig::CONFIG.delete 'EXEEXT' - end - end - - # TODO: move to minitest - def refute_path_exists(path, msg = nil) - msg = message(msg) { "Expected path '#{path}' to not exist" } - refute File.exist?(path), msg - end - - def scan_make_command_lines(output) - output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/) - end - - def parse_make_command_line(line) - command, *args = line.shellsplit - - targets = [] - macros = {} - - args.each do |arg| - case arg - when /\A(\w+)=/ - macros[$1] = $' - else - targets << arg - end - end - - targets << '' if targets.empty? - - { - :command => command, - :targets => targets, - :macros => macros, - } - end - - def assert_contains_make_command(target, output, msg = nil) - if output.match(/\n/) - msg = message(msg) do - 'Expected output containing make command "%s": %s' % [ - ('%s %s' % [make_command, target]).rstrip, - output.inspect - ] - end - else - msg = message(msg) do - 'Expected make command "%s": %s' % [ - ('%s %s' % [make_command, target]).rstrip, - output.inspect - ] - end - end - - assert scan_make_command_lines(output).any? { |line| - make = parse_make_command_line(line) - - if make[:targets].include?(target) - yield make, line if block_given? - true - else - false - end - }, msg - end - - include Gem::DefaultUserInteraction - - undef_method :default_test if instance_methods.include? 'default_test' or - instance_methods.include? :default_test - - ## - # #setup prepares a sandboxed location to install gems. All installs are - # directed to a temporary directory. All install plugins are removed. - # - # If the +RUBY+ environment variable is set the given path is used for - # Gem::ruby. The local platform is set to i386-mswin32 for Windows - # or i686-darwin8.10.1 otherwise. - - def setup - super - - @orig_env = ENV.to_hash - - ENV['GEM_VENDOR'] = nil - ENV['GEMRC'] = nil - ENV['SOURCE_DATE_EPOCH'] = nil - - @current_dir = Dir.pwd - @fetcher = nil - - @back_ui = Gem::DefaultUserInteraction.ui - @ui = Gem::MockGemUi.new - # This needs to be a new instance since we call use_ui(@ui) when we want to - # capture output - Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new - - tmpdir = File.realpath Dir.tmpdir - tmpdir.tap(&Gem::UNTAINT) - - @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") - @tempdir.tap(&Gem::UNTAINT) - - FileUtils.mkdir_p @tempdir - - # This makes the tempdir consistent on Windows. - # Dir.tmpdir may return short path name, but Dir[Dir.tmpdir] returns long - # path name. https://bugs.ruby-lang.org/issues/10819 - # File.expand_path or File.realpath doesn't convert path name to long path - # name. Only Dir[] (= Dir.glob) works. - # Short and long path name is specific to Windows filesystem. - if win_platform? - @tempdir = Dir[@tempdir][0] - @tempdir.tap(&Gem::UNTAINT) - end - - @gemhome = File.join @tempdir, 'gemhome' - @userhome = File.join @tempdir, 'userhome' - ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache' - - @orig_ruby = if ENV['RUBY'] - ruby = Gem.ruby - Gem.ruby = ENV['RUBY'] - ruby - end - - @git = ENV['GIT'] || 'git' - - Gem.ensure_gem_subdirectories @gemhome - - @orig_LOAD_PATH = $LOAD_PATH.dup - $LOAD_PATH.map! do |s| - expand_path = File.realpath(s) rescue File.expand_path(s) - if expand_path != s - expand_path.tap(&Gem::UNTAINT) - if s.instance_variable_defined?(:@gem_prelude_index) - expand_path.instance_variable_set(:@gem_prelude_index, expand_path) - end - expand_path.freeze if s.frozen? - s = expand_path - end - s - end - - Dir.chdir @tempdir - - ENV['HOME'] = @userhome - Gem.instance_variable_set :@user_home, nil - Gem.instance_variable_set :@gemdeps, nil - Gem.instance_variable_set :@env_requirements_by_name, nil - Gem.send :remove_instance_variable, :@ruby_version if - Gem.instance_variables.include? :@ruby_version - - FileUtils.mkdir_p @gemhome - FileUtils.mkdir_p @userhome - - ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE - - @default_dir = File.join @tempdir, 'default' - @default_spec_dir = File.join @default_dir, "specifications", "default" - if Gem.java_platform? - @orig_default_gem_home = RbConfig::CONFIG['default_gem_home'] - RbConfig::CONFIG['default_gem_home'] = @default_dir - else - Gem.instance_variable_set(:@default_dir, @default_dir) - end - FileUtils.mkdir_p @default_spec_dir - - Gem::Specification.unresolved_deps.clear - Gem.use_paths(@gemhome) - - Gem::Security.reset - - Gem.loaded_specs.clear - Gem.clear_default_specs - Bundler.reset! - - Gem.configuration.verbose = true - Gem.configuration.update_sources = true - - Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new - - @gem_repo = "http://gems.example.com/" - @uri = URI.parse @gem_repo - Gem.sources.replace [@gem_repo] - - Gem.searcher = nil - Gem::SpecFetcher.fetcher = nil - - @orig_arch = RbConfig::CONFIG['arch'] - - if win_platform? - util_set_arch 'i386-mswin32' - else - util_set_arch 'i686-darwin8.10.1' - end - - @orig_hooks = {} - %w[post_install_hooks done_installing_hooks post_uninstall_hooks pre_uninstall_hooks pre_install_hooks pre_reset_hooks post_reset_hooks post_build_hooks].each do |name| - @orig_hooks[name] = Gem.send(name).dup - end - - @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" - @orig_LOADED_FEATURES = $LOADED_FEATURES.dup - end - - ## - # #teardown restores the process to its original state and removes the - # tempdir - - def teardown - $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH - if @orig_LOADED_FEATURES - if @orig_LOAD_PATH - paths = @orig_LOAD_PATH.map {|path| File.join(File.expand_path(path), "/")} - ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat| - unless paths.any? {|path| feat.start_with?(path)} - $LOADED_FEATURES.delete(feat) - end - end - else - $LOADED_FEATURES.replace @orig_LOADED_FEATURES - end - end - - RbConfig::CONFIG['arch'] = @orig_arch - - if defined? Gem::RemoteFetcher - Gem::RemoteFetcher.fetcher = nil - end - - Dir.chdir @current_dir - - FileUtils.rm_rf @tempdir - - ENV.replace(@orig_env) - - Gem.ruby = @orig_ruby if @orig_ruby - - if Gem.java_platform? - RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home - else - Gem.instance_variable_set :@default_dir, nil - end - - Gem::Specification._clear_load_cache - Gem::Specification.unresolved_deps.clear - Gem::refresh - - @orig_hooks.each do |name, hooks| - Gem.send(name).replace hooks - end - - @back_ui.close - end - - def common_installer_setup - common_installer_teardown - - Gem.post_build do |installer| - @post_build_hook_arg = installer - true - end - - Gem.post_install do |installer| - @post_install_hook_arg = installer - end - - Gem.post_uninstall do |uninstaller| - @post_uninstall_hook_arg = uninstaller - end - - Gem.pre_install do |installer| - @pre_install_hook_arg = installer - true - end - - Gem.pre_uninstall do |uninstaller| - @pre_uninstall_hook_arg = uninstaller - end - end - - def common_installer_teardown - Gem.post_build_hooks.clear - Gem.post_install_hooks.clear - Gem.done_installing_hooks.clear - Gem.post_reset_hooks.clear - Gem.post_uninstall_hooks.clear - Gem.pre_install_hooks.clear - Gem.pre_reset_hooks.clear - Gem.pre_uninstall_hooks.clear - end - - ## - # A git_gem is used with a gem dependencies file. The gem created here - # has no files, just a gem specification for the given +name+ and +version+. - # - # Yields the +specification+ to the block, if given - - def git_gem(name = 'a', version = 1) - have_git? - - directory = File.join 'git', name - directory = File.expand_path directory - - git_spec = Gem::Specification.new name, version do |specification| - yield specification if block_given? - end - - FileUtils.mkdir_p directory - - gemspec = "#{name}.gemspec" - - File.open File.join(directory, gemspec), 'w' do |io| - io.write git_spec.to_ruby - end - - head = nil - - Dir.chdir directory do - unless File.exist? '.git' - system @git, 'init', '--quiet' - system @git, 'config', 'user.name', 'RubyGems Tests' - system @git, 'config', 'user.email', 'rubygems@example' - end - - system @git, 'add', gemspec - system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet' - head = Gem::Util.popen(@git, 'rev-parse', 'master').strip - end - - return name, git_spec.version, directory, head - end - - ## - # Skips this test unless you have a git executable - - def have_git? - return if in_path? @git - - skip 'cannot find git executable, use GIT environment variable to set' - end - - def in_path?(executable) # :nodoc: - return true if %r%\A([A-Z]:|/)% =~ executable and File.exist? executable - - ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| - File.exist? File.join directory, executable - end - end - - ## - # Builds and installs the Gem::Specification +spec+ - - def install_gem(spec, options = {}) - require 'rubygems/installer' - - gem = File.join @tempdir, "gems", "#{spec.full_name}.gem" - - unless File.exist? gem - use_ui Gem::MockGemUi.new do - Dir.chdir @tempdir do - Gem::Package.build spec - end - end - - gem = File.join(@tempdir, File.basename(spec.cache_file)).tap(&Gem::UNTAINT) - end - - Gem::Installer.at(gem, options.merge({:wrappers => true})).install - end - - ## - # Builds and installs the Gem::Specification +spec+ into the user dir - - def install_gem_user(spec) - install_gem spec, :user_install => true - end - - ## - # Uninstalls the Gem::Specification +spec+ - def uninstall_gem(spec) - require 'rubygems/uninstaller' - - Class.new(Gem::Uninstaller) do - def ask_if_ok(spec) - true - end - end.new(spec.name, :executables => true, :user_install => true).uninstall - end - - ## - # Enables pretty-print for all tests - - def mu_pp(obj) - s = String.new - s = PP.pp obj, s - s = s.force_encoding(Encoding.default_external) - s.chomp - end - - ## - # Reads a Marshal file at +path+ - - def read_cache(path) - File.open path.dup.tap(&Gem::UNTAINT), 'rb' do |io| - Marshal.load io.read - end - end - - ## - # Reads a binary file at +path+ - - def read_binary(path) - Gem.read_binary path - end - - ## - # Writes a binary file to +path+ which is relative to +@gemhome+ - - def write_file(path) - path = File.join @gemhome, path unless Pathname.new(path).absolute? - dir = File.dirname path - FileUtils.mkdir_p dir unless File.directory? dir - - File.open path, 'wb' do |io| - yield io if block_given? - end - - path - end - - def all_spec_names - Gem::Specification.map(&:full_name) - end - - ## - # Creates a Gem::Specification with a minimum of extra work. +name+ and - # +version+ are the gem's name and version, platform, author, email, - # homepage, summary and description are defaulted. The specification is - # yielded for customization. - # - # The gem is added to the installed gems in +@gemhome+ and the runtime. - # - # Use this with #write_file to build an installed gem. - - def quick_gem(name, version='2') - require 'rubygems/specification' - - spec = Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = name - s.version = version - s.author = 'A User' - s.email = 'example@example.com' - s.homepage = 'http://example.com' - s.summary = "this is a summary" - s.description = "This is a test description" - - yield(s) if block_given? - end - - Gem::Specification.map # HACK: force specs to (re-)load before we write - - written_path = write_file spec.spec_file do |io| - io.write spec.to_ruby_for_cache - end - - spec.loaded_from = written_path - - Gem::Specification.reset - - return spec - end - - ## - # Builds a gem from +spec+ and places it in File.join @gemhome, - # 'cache'. Automatically creates files based on +spec.files+ - - def util_build_gem(spec) - dir = spec.gem_dir - FileUtils.mkdir_p dir - - Dir.chdir dir do - spec.files.each do |file| - next if File.exist? file - FileUtils.mkdir_p File.dirname(file) - - File.open file, 'w' do |fp| - fp.puts "# #{file}" - end - end - - use_ui Gem::MockGemUi.new do - Gem::Package.build spec - end - - cache = spec.cache_file - FileUtils.mv File.basename(cache), cache - end - end - - def util_remove_gem(spec) - FileUtils.rm_rf spec.cache_file - FileUtils.rm_rf spec.spec_file - end - - ## - # Removes all installed gems from +@gemhome+. - - def util_clear_gems - FileUtils.rm_rf File.join(@gemhome, "gems") - FileUtils.mkdir File.join(@gemhome, "gems") - FileUtils.rm_rf File.join(@gemhome, "specifications") - FileUtils.mkdir File.join(@gemhome, "specifications") - Gem::Specification.reset - end - - ## - # Install the provided specs - - def install_specs(*specs) - specs.each do |spec| - Gem::Installer.for_spec(spec).install - end - - Gem.searcher = nil - end - - ## - # Installs the provided default specs including writing the spec file - - def install_default_gems(*specs) - install_default_specs(*specs) - - specs.each do |spec| - File.open spec.loaded_from, 'w' do |io| - io.write spec.to_ruby_for_cache - end - end - end - - ## - # Install the provided default specs - - def install_default_specs(*specs) - specs.each do |spec| - installer = Gem::Installer.for_spec(spec, :install_as_default => true) - installer.install - Gem.register_default_spec(spec) - end - end - - def loaded_spec_names - Gem.loaded_specs.values.map(&:full_name).sort - end - - def unresolved_names - Gem::Specification.unresolved_deps.values.map(&:to_s).sort - end - - def save_loaded_features - old_loaded_features = $LOADED_FEATURES.dup - yield - ensure - prefix = File.dirname(__FILE__) + "/" - new_features = ($LOADED_FEATURES - old_loaded_features) - old_loaded_features.concat(new_features.select {|f| f.rindex(prefix, 0)}) - $LOADED_FEATURES.replace old_loaded_features - end - - def new_default_spec(name, version, deps = nil, *files) - spec = util_spec name, version, deps - - spec.loaded_from = File.join(@default_spec_dir, spec.spec_name) - spec.files = files - - lib_dir = File.join(@tempdir, "default_gems", "lib") - lib_dir.instance_variable_set(:@gem_prelude_index, lib_dir) - $LOAD_PATH.unshift(lib_dir) - files.each do |file| - rb_path = File.join(lib_dir, file) - FileUtils.mkdir_p(File.dirname(rb_path)) - File.open(rb_path, "w") do |rb| - rb << "# #{file}" - end - end - - spec - end - - ## - # Creates a spec with +name+, +version+. +deps+ can specify the dependency - # or a +block+ can be given for full customization of the specification. - - def util_spec(name, version = 2, deps = nil, *files) # :yields: specification - raise "deps or block, not both" if deps and block_given? - - spec = Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = name - s.version = version - s.author = 'A User' - s.email = 'example@example.com' - s.homepage = 'http://example.com' - s.summary = "this is a summary" - s.description = "This is a test description" - - s.files.push(*files) unless files.empty? - - yield s if block_given? - end - - if deps - # Since Hash#each is unordered in 1.8, sort the keys and iterate that - # way so the tests are deterministic on all implementations. - deps.keys.sort.each do |n| - spec.add_dependency n, (deps[n] || '>= 0') - end - end - - unless files.empty? - write_file spec.spec_file do |io| - io.write spec.to_ruby_for_cache - end - - util_build_gem spec - - cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" - FileUtils.mkdir_p File.dirname cache_file - FileUtils.mv spec.cache_file, cache_file - FileUtils.rm spec.spec_file - end - - return spec - end - - ## - # Creates a gem with +name+, +version+ and +deps+. The specification will - # be yielded before gem creation for customization. The gem will be placed - # in File.join @tempdir, 'gems'. The specification and .gem file - # location are returned. - - def util_gem(name, version, deps = nil, &block) - if deps - block = proc do |s| - # Since Hash#each is unordered in 1.8, sort - # the keys and iterate that way so the tests are - # deterministic on all implementations. - deps.keys.sort.each do |n| - s.add_dependency n, (deps[n] || '>= 0') - end - end - end - - spec = quick_gem(name, version, &block) - - util_build_gem spec - - cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" - FileUtils.mkdir_p File.dirname cache_file - FileUtils.mv spec.cache_file, cache_file - FileUtils.rm spec.spec_file - - spec.loaded_from = nil - - [spec, cache_file] - end - - ## - # Gzips +data+. - - def util_gzip(data) - out = StringIO.new - - Zlib::GzipWriter.wrap out do |io| - io.write data - end - - out.string - end - - ## - # Creates several default gems which all have a lib/code.rb file. The gems - # are not installed but are available in the cache dir. - # - # +@a1+:: gem a version 1, this is the best-described gem. - # +@a2+:: gem a version 2 - # +@a3a:: gem a version 3.a - # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems - # don't collide with a. - # +@b2+:: gem b version 2 - # +@c1_2+:: gem c version 1.2 - # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux. - # - # Additional +prerelease+ gems may also be created: - # - # +@a2_pre+:: gem a version 2.a - # TODO: nuke this and fix tests. this should speed up a lot - - def util_make_gems(prerelease = false) - @a1 = quick_gem 'a', '1' do |s| - s.files = %w[lib/code.rb] - s.require_paths = %w[lib] - s.date = Gem::Specification::TODAY - 86400 - s.homepage = 'http://a.example.com' - s.email = %w[example@example.com example2@example.com] - s.authors = %w[Example Example2] - s.description = <<-DESC -This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed. - -Also, a list: - * An entry that\'s actually kind of sort - * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters. - DESC - end - - init = proc do |s| - s.files = %w[lib/code.rb] - s.require_paths = %w[lib] - end - - @a2 = quick_gem('a', '2', &init) - @a3a = quick_gem('a', '3.a', &init) - @a_evil9 = quick_gem('a_evil', '9', &init) - @b2 = quick_gem('b', '2', &init) - @c1_2 = quick_gem('c', '1.2', &init) - @x = quick_gem('x', '1', &init) - @dep_x = quick_gem('dep_x', '1') do |s| - s.files = %w[lib/code.rb] - s.require_paths = %w[lib] - s.add_dependency 'x', '>= 1' - end - - @pl1 = quick_gem 'pl', '1' do |s| # l for legacy - s.files = %w[lib/code.rb] - s.require_paths = %w[lib] - s.platform = Gem::Platform.new 'i386-linux' - s.instance_variable_set :@original_platform, 'i386-linux' - end - - if prerelease - @a2_pre = quick_gem('a', '2.a', &init) - write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) - util_build_gem @a2_pre - end - - write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) - - [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec| - util_build_gem spec - end - - FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name) - end - - ## - # Set the platform to +arch+ - - def util_set_arch(arch) - RbConfig::CONFIG['arch'] = arch - platform = Gem::Platform.new arch - - Gem.instance_variable_set :@platforms, nil - Gem::Platform.instance_variable_set :@local, nil - - yield if block_given? - - platform - end - - ## - # Add +spec+ to +@fetcher+ serving the data in the file +path+. - # +repo+ indicates which repo to make +spec+ appear to be in. - - def add_to_fetcher(spec, path=nil, repo=@gem_repo) - path ||= spec.cache_file - @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) - end - - ## - # Sets up Gem::SpecFetcher to return information from the gems in +specs+. - - def util_setup_spec_fetcher(*specs) - all_specs = Gem::Specification.to_a + specs - Gem::Specification._resort! all_specs - - spec_fetcher = Gem::SpecFetcher.fetcher - - prerelease, all = all_specs.partition { |spec| spec.version.prerelease? } - latest = Gem::Specification._latest_specs all_specs - - spec_fetcher.specs[@uri] = [] - all.each do |spec| - spec_fetcher.specs[@uri] << spec.name_tuple - end - - spec_fetcher.latest_specs[@uri] = [] - latest.each do |spec| - spec_fetcher.latest_specs[@uri] << spec.name_tuple - end - - spec_fetcher.prerelease_specs[@uri] = [] - prerelease.each do |spec| - spec_fetcher.prerelease_specs[@uri] << spec.name_tuple - end - - # HACK for test_download_to_cache - unless Gem::RemoteFetcher === @fetcher - v = Gem.marshal_version - - specs = all.map { |spec| spec.name_tuple } - s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs - - latest_specs = latest.map do |spec| - spec.name_tuple - end - - l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs - - prerelease_specs = prerelease.map { |spec| spec.name_tuple } - p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs - - @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip - @fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip - @fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip - - v = Gem.marshal_version - - all_specs.each do |spec| - path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz" - data = Marshal.dump spec - data_deflate = Zlib::Deflate.deflate data - @fetcher.data[path] = data_deflate - end - end - - nil # force errors - end - - ## - # Deflates +data+ - - def util_zip(data) - Zlib::Deflate.deflate data - end - - def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil) - if Gem.instance_variables.include? :@ruby_version - Gem.send :remove_instance_variable, :@ruby_version - end - - @RUBY_VERSION = RUBY_VERSION - @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) - @RUBY_DESCRIPTION = RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) - @RUBY_ENGINE = RUBY_ENGINE - @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) - - util_clear_RUBY_VERSION - - Object.const_set :RUBY_VERSION, version - Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel - Object.const_set :RUBY_REVISION, revision if revision - Object.const_set :RUBY_DESCRIPTION, description if description - Object.const_set :RUBY_ENGINE, engine - Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version - end - - def util_restore_RUBY_VERSION - util_clear_RUBY_VERSION - - Object.const_set :RUBY_VERSION, @RUBY_VERSION - Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if - defined?(@RUBY_PATCHLEVEL) - Object.const_set :RUBY_REVISION, @RUBY_REVISION if - defined?(@RUBY_REVISION) - Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION if - defined?(@RUBY_DESCRIPTION) - Object.const_set :RUBY_ENGINE, @RUBY_ENGINE - Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if - defined?(@RUBY_ENGINE_VERSION) - end - - def util_clear_RUBY_VERSION - Object.send :remove_const, :RUBY_VERSION - Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) - Object.send :remove_const, :RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) - end - - ## - # Is this test being run on a Windows platform? - - def self.win_platform? - Gem.win_platform? - end - - ## - # Is this test being run on a Windows platform? - - def win_platform? - Gem.win_platform? - end - - ## - # Is this test being run on a Java platform? - - def self.java_platform? - Gem.java_platform? - end - - ## - # Is this test being run on a Java platform? - - def java_platform? - Gem.java_platform? - end - - ## - # Returns whether or not we're on a version of Ruby built with VC++ (or - # Borland) versus Cygwin, Mingw, etc. - - def self.vc_windows? - RUBY_PLATFORM.match('mswin') - end - - ## - # Returns whether or not we're on a version of Ruby built with VC++ (or - # Borland) versus Cygwin, Mingw, etc. - - def vc_windows? - RUBY_PLATFORM.match('mswin') - end - - ## - # Returns the make command for the current platform. For versions of Ruby - # built on MS Windows with VC++ or Borland it will return 'nmake'. On all - # other platforms, including Cygwin, it will return 'make'. - - def self.make_command - ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make') - end - - ## - # Returns the make command for the current platform. For versions of Ruby - # built on MS Windows with VC++ or Borland it will return 'nmake'. On all - # other platforms, including Cygwin, it will return 'make'. - - def make_command - ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make') - end - - ## - # Returns whether or not the nmake command could be found. - - def nmake_found? - system('nmake /? 1>NUL 2>&1') - end - - # In case we're building docs in a background process, this method waits for - # that process to exit (or if it's already been reaped, or never happened, - # swallows the Errno::ECHILD error). - def wait_for_child_process_to_exit - Process.wait if Process.respond_to?(:fork) - rescue Errno::ECHILD - end - - ## - # Allows tests to use a random (but controlled) port number instead of - # a hardcoded one. This helps CI tools when running parallels builds on - # the same builder slave. - - def self.process_based_port - @@process_based_port ||= 8000 + $$ % 1000 - end - - ## - # See ::process_based_port - - def process_based_port - self.class.process_based_port - end - - ## - # Allows the proper version of +rake+ to be used for the test. - - def build_rake_in(good=true) - gem_ruby = Gem.ruby - Gem.ruby = @@ruby - env_rake = ENV["rake"] - rake = (good ? @@good_rake : @@bad_rake) - ENV["rake"] = rake - yield rake - ensure - Gem.ruby = gem_ruby - if env_rake - ENV["rake"] = env_rake - else - ENV.delete("rake") - end - end - - ## - # Finds the path to the Ruby executable - - def self.rubybin - ruby = ENV["RUBY"] - return ruby if ruby - ruby = "ruby" - rubyexe = "#{ruby}.exe" - - 3.times do - if File.exist? ruby and File.executable? ruby and !File.directory? ruby - return File.expand_path(ruby) - end - if File.exist? rubyexe and File.executable? rubyexe - return File.expand_path(rubyexe) - end - ruby = File.join("..", ruby) - end - - begin - require "rbconfig" - File.join(RbConfig::CONFIG["bindir"], - RbConfig::CONFIG["ruby_install_name"] + - RbConfig::CONFIG["EXEEXT"]) - rescue LoadError - "ruby" - end - end - - class << self - - # :nodoc: - ## - # Return the join path, with escaping backticks, dollars, and - # double-quotes. Unlike `shellescape`, equal-sign is not escaped. - private - - def escape_path(*path) - path = File.join(*path) - if %r'\A[-+:/=@,.\w]+\z' =~ path - path - else - "\"#{path.gsub(/[`$"]/, '\\&')}\"" - end - end - - end - - @@ruby = rubybin - @@good_rake = "#{rubybin} #{escape_path(TEST_PATH, 'good_rake.rb')}" - @@bad_rake = "#{rubybin} #{escape_path(TEST_PATH, 'bad_rake.rb')}" - - ## - # Construct a new Gem::Dependency. - - def dep(name, *requirements) - Gem::Dependency.new name, *requirements - end - - ## - # Constructs a Gem::Resolver::DependencyRequest from a - # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the - # dependency and a +parent+ DependencyRequest - - def dependency_request(dep, from_name, from_version, parent = nil) - remote = Gem::Source.new @uri - - unless parent - parent_dep = dep from_name, from_version - parent = Gem::Resolver::DependencyRequest.new parent_dep, nil - end - - spec = Gem::Resolver::IndexSpecification.new \ - nil, from_name, from_version, remote, Gem::Platform::RUBY - activation = Gem::Resolver::ActivationRequest.new spec, parent - - Gem::Resolver::DependencyRequest.new dep, activation - end - - ## - # Constructs a new Gem::Requirement. - - def req(*requirements) - return requirements.first if Gem::Requirement === requirements.first - Gem::Requirement.create requirements - end - - ## - # Constructs a new Gem::Specification. - - def spec(name, version, &block) - Gem::Specification.new name, v(version), &block - end - - ## - # Creates a SpecFetcher pre-filled with the gems or specs defined in the - # block. - # - # Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds - # a specification to the SpecFetcher while +gem+ adds both a specification - # and the gem data to the RemoteFetcher so the built gem can be downloaded. - # - # If only the a-3 gem is supposed to be downloaded you can save setup - # time by creating only specs for the other versions: - # - # spec_fetcher do |fetcher| - # fetcher.spec 'a', 1 - # fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3 - # fetcher.gem 'a', 3 do |spec| - # # spec is a Gem::Specification - # # ... - # end - # end - - def spec_fetcher(repository = @gem_repo) - Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup| - yield spec_fetcher_setup if block_given? - end - end - - ## - # Construct a new Gem::Version. - - def v(string) - Gem::Version.create string - end - - ## - # A vendor_gem is used with a gem dependencies file. The gem created here - # has no files, just a gem specification for the given +name+ and +version+. - # - # Yields the +specification+ to the block, if given - - def vendor_gem(name = 'a', version = 1) - directory = File.join 'vendor', name - - FileUtils.mkdir_p directory - - save_gemspec name, version, directory - end - - ## - # create_gemspec creates gem specification in given +directory+ or '.' - # for the given +name+ and +version+. - # - # Yields the +specification+ to the block, if given - - def save_gemspec(name = 'a', version = 1, directory = '.') - vendor_spec = Gem::Specification.new name, version do |specification| - yield specification if block_given? - end - - File.open File.join(directory, "#{name}.gemspec"), 'w' do |io| - io.write vendor_spec.to_ruby - end - - return name, vendor_spec.version, directory - end - - ## - # The StaticSet is a static set of gem specifications used for testing only. - # It is available by requiring Gem::TestCase. - - class StaticSet < Gem::Resolver::Set - - ## - # A StaticSet ignores remote because it has a fixed set of gems. - - attr_accessor :remote - - ## - # Creates a new StaticSet for the given +specs+ - - def initialize(specs) - super() - - @specs = specs - - @remote = true - end - - ## - # Adds +spec+ to this set. - - def add(spec) - @specs << spec - end - - ## - # Finds +dep+ in this set. - - def find_spec(dep) - @specs.reverse_each do |s| - return s if dep.matches_spec? s - end - end - - ## - # Finds all gems matching +dep+ in this set. - - def find_all(dep) - @specs.find_all { |s| dep.match? s, @prerelease } - end - - ## - # Loads a Gem::Specification from this set which has the given +name+, - # version +ver+, +platform+. The +source+ is ignored. - - def load_spec(name, ver, platform, source) - dep = Gem::Dependency.new name, ver - spec = find_spec dep - - Gem::Specification.new spec.name, spec.version do |s| - s.platform = spec.platform - end - end - - def prefetch(reqs) # :nodoc: - end - - end - - ## - # Loads certificate named +cert_name+ from test/rubygems/. - - def self.load_cert(cert_name) - cert_file = cert_path cert_name - - cert = File.read cert_file - - OpenSSL::X509::Certificate.new cert - end - - ## - # Returns the path to the certificate named +cert_name+ from - # test/rubygems/. - - def self.cert_path(cert_name) - if 32 == (Time.at(2**32) rescue 32) - cert_file = "#{TEST_PATH}/#{cert_name}_cert_32.pem" - - return cert_file if File.exist? cert_file - end - - "#{TEST_PATH}/#{cert_name}_cert.pem" - end - - ## - # Loads an RSA private key named +key_name+ with +passphrase+ in test/rubygems/ - - def self.load_key(key_name, passphrase = nil) - key_file = key_path key_name - - key = File.read key_file - - OpenSSL::PKey::RSA.new key, passphrase - end - - ## - # Returns the path to the key named +key_name+ from test/rubygems - - def self.key_path(key_name) - "#{TEST_PATH}/#{key_name}_key.pem" - end - - # :stopdoc: - # only available in RubyGems tests - - PRIVATE_KEY_PASSPHRASE = 'Foo bar'.freeze - - begin - PRIVATE_KEY = load_key 'private' - PRIVATE_KEY_PATH = key_path 'private' - - # ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE - ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE - ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private' - - PUBLIC_KEY = PRIVATE_KEY.public_key - - PUBLIC_CERT = load_cert 'public' - PUBLIC_CERT_PATH = cert_path 'public' - rescue Errno::ENOENT - PRIVATE_KEY = nil - PUBLIC_KEY = nil - PUBLIC_CERT = nil - end if defined?(OpenSSL::SSL) - -end - -# require dependencies that are not discoverable once GEM_HOME and GEM_PATH -# are wiped -begin - gem 'rake' -rescue Gem::LoadError -end - -begin - require 'rake/packagetask' -rescue LoadError -end - -begin - gem 'rdoc' - require 'rdoc' - - require 'rubygems/rdoc' -rescue LoadError, Gem::LoadError -end - -begin - gem 'builder' - require 'builder/xchar' -rescue LoadError, Gem::LoadError -end - -require 'rubygems/test_utilities' diff --git a/ruby/lib/rubygems/test_utilities.rb b/ruby/lib/rubygems/test_utilities.rb deleted file mode 100644 index 69ff05370..000000000 --- a/ruby/lib/rubygems/test_utilities.rb +++ /dev/null @@ -1,380 +0,0 @@ -# frozen_string_literal: true -require 'tempfile' -require 'rubygems' -require 'rubygems/remote_fetcher' - -## -# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP -# requests when testing code that uses RubyGems. -# -# Example: -# -# @fetcher = Gem::FakeFetcher.new -# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml -# Gem::RemoteFetcher.fetcher = @fetcher -# -# use nested array if multiple response is needed -# -# @fetcher.data['http://gems.example.com/sequence'] = [['Success', 200, 'OK'], ['Failed', 401, 'Unauthorized']] -# -# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Success', 200, 'OK'] -# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Failed', 401, 'Unauthorized'] -# -# # invoke RubyGems code -# -# paths = @fetcher.paths -# assert_equal 'http://gems.example.com/yaml', paths.shift -# assert paths.empty?, paths.join(', ') -# -# See RubyGems' tests for more examples of FakeFetcher. - -class Gem::FakeFetcher - - attr_reader :data - attr_reader :last_request - attr_accessor :paths - - def initialize - @data = {} - @paths = [] - end - - def find_data(path, nargs = 3) - return File.read path.path if URI === path and 'file' == path.scheme - - if URI === path and "URI::#{path.scheme.upcase}" != path.class.name - raise ArgumentError, - "mismatch for scheme #{path.scheme} and class #{path.class}" - end - - path = path.to_s - @paths << path - raise ArgumentError, 'need full URI' unless path =~ %r'^https?://' - - unless @data.key? path - raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) - end - - data = @data[path] - - data.flatten! and return data.shift(nargs) if data.respond_to?(:flatten!) - data - end - - def fetch_path(path, mtime = nil, head = false) - data = find_data(path) - - if data.respond_to?(:call) - data.call - else - if path.to_s =~ /gz$/ and not data.nil? and not data.empty? - data = Gem::Util.gunzip data - end - data - end - end - - def cache_update_path(uri, path = nil, update = true) - if data = fetch_path(uri) - open(path, 'wb') { |io| io.write data } if path and update - data - else - Gem.read_binary(path) if path - end - end - - # Thanks, FakeWeb! - def open_uri_or_path(path) - data = find_data(path) - body, code, msg = data - - response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) - response.instance_variable_set(:@body, body) - response.instance_variable_set(:@read, true) - response - end - - def request(uri, request_class, last_modified = nil) - data = find_data(uri) - body, code, msg = (data.respond_to?(:call) ? data.call : data) - - @last_request = request_class.new uri.request_uri - yield @last_request if block_given? - - response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) - response.instance_variable_set(:@body, body) - response.instance_variable_set(:@read, true) - response - end - - def pretty_print(q) # :nodoc: - q.group 2, '[FakeFetcher', ']' do - q.breakable - q.text 'URIs:' - - q.breakable - q.pp @data.keys - end - end - - def fetch_size(path) - path = path.to_s - @paths << path - - raise ArgumentError, 'need full URI' unless path =~ %r'^http://' - - unless @data.key? path - raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) - end - - data = @data[path] - - data.respond_to?(:call) ? data.call : data.length - end - - def download(spec, source_uri, install_dir = Gem.dir) - name = File.basename spec.cache_file - path = if Dir.pwd == install_dir # see fetch_command - install_dir - else - File.join install_dir, "cache" - end - - path = File.join path, name - - if source_uri =~ /^http/ - File.open(path, "wb") do |f| - f.write fetch_path(File.join(source_uri, "gems", name)) - end - else - FileUtils.cp source_uri, path - end - - path - end - - def download_to_cache(dependency) - found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency - - return if found.empty? - - spec, source = found.first - - download spec, source.uri.to_s - end - -end - -# :stopdoc: -class Gem::RemoteFetcher - - def self.fetcher=(fetcher) - @fetcher = fetcher - end - -end -# :startdoc: - -## -# The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests: -# -# spec_fetcher do |f| -# f.gem 'a', 1 -# f.spec 'a', 2 -# f.gem 'b', 1' 'a' => '~> 1.0' -# end -# -# The above declaration creates two gems, a-1 and b-1, with a dependency from -# b to a. The declaration creates an additional spec a-2, but no gem for it -# (so it cannot be installed). -# -# After the gems are created they are removed from Gem.dir. - -class Gem::TestCase::SpecFetcherSetup - - ## - # Executes a SpecFetcher setup block. Yields an instance then creates the - # gems and specifications defined in the instance. - - def self.declare(test, repository) - setup = new test, repository - - yield setup - - setup.execute - end - - def initialize(test, repository) # :nodoc: - @test = test - @repository = repository - - @gems = {} - @downloaded = [] - @installed = [] - @operations = [] - end - - ## - # Returns a Hash of created Specification full names and the corresponding - # Specification. - - def created_specs - created = {} - - @gems.keys.each do |spec| - created[spec.full_name] = spec - end - - created - end - - ## - # Creates any defined gems or specifications - - def execute # :nodoc: - execute_operations - - setup_fetcher - - created_specs - end - - def execute_operations # :nodoc: - @operations.each do |operation, *arguments| - block = arguments.pop - case operation - when :gem then - spec, gem = @test.util_gem(*arguments, &block) - - write_spec spec - - @gems[spec] = gem - @installed << spec - when :download then - spec, gem = @test.util_gem(*arguments, &block) - - @gems[spec] = gem - @downloaded << spec - when :spec then - spec = @test.util_spec(*arguments, &block) - - write_spec spec - - @gems[spec] = nil - @installed << spec - end - end - end - - ## - # Creates a gem with +name+, +version+ and +deps+. The created gem can be - # downloaded and installed. - # - # The specification will be yielded before gem creation for customization, - # but only the block or the dependencies may be set, not both. - - def gem(name, version, dependencies = nil, &block) - @operations << [:gem, name, version, dependencies, block] - end - - ## - # Creates a gem with +name+, +version+ and +deps+. The created gem is - # downloaded in to the cache directory but is not installed - # - # The specification will be yielded before gem creation for customization, - # but only the block or the dependencies may be set, not both. - - def download(name, version, dependencies = nil, &block) - @operations << [:download, name, version, dependencies, block] - end - - ## - # Creates a legacy platform spec with the name 'pl' and version 1 - - def legacy_platform - spec 'pl', 1 do |s| - s.platform = Gem::Platform.new 'i386-linux' - s.instance_variable_set :@original_platform, 'i386-linux' - end - end - - def setup_fetcher # :nodoc: - require 'zlib' - require 'socket' - require 'rubygems/remote_fetcher' - - unless @test.fetcher - @test.fetcher = Gem::FakeFetcher.new - Gem::RemoteFetcher.fetcher = @test.fetcher - end - - Gem::Specification.reset - - begin - gem_repo, @test.gem_repo = @test.gem_repo, @repository - @test.uri = URI @repository - - @test.util_setup_spec_fetcher(*@downloaded) - ensure - @test.gem_repo = gem_repo - @test.uri = URI gem_repo - end - - @gems.each do |spec, gem| - next unless gem - - @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] = - Gem.read_binary(gem) - - FileUtils.cp gem, spec.cache_file - end - end - - ## - # Creates a spec with +name+, +version+ and +deps+. The created gem can be - # downloaded and installed. - # - # The specification will be yielded before creation for customization, - # but only the block or the dependencies may be set, not both. - - def spec(name, version, dependencies = nil, &block) - @operations << [:spec, name, version, dependencies, block] - end - - def write_spec(spec) # :nodoc: - File.open spec.spec_file, 'w' do |io| - io.write spec.to_ruby_for_cache - end - end - -end - -## -# A StringIO duck-typed class that uses Tempfile instead of String as the -# backing store. -# -# This is available when rubygems/test_utilities is required. -#-- -# This class was added to flush out problems in Rubinius' IO implementation. - -class TempIO < Tempfile - - ## - # Creates a new TempIO that will be initialized to contain +string+. - - def initialize(string = '') - super "TempIO" - binmode - write string - rewind - end - - ## - # The content of the TempIO as a String. - - def string - flush - Gem.read_binary path - end - -end diff --git a/ruby/lib/rubygems/text.rb b/ruby/lib/rubygems/text.rb index 667811192..acf25a0bc 100644 --- a/ruby/lib/rubygems/text.rb +++ b/ruby/lib/rubygems/text.rb @@ -49,37 +49,38 @@ def min3(a, b, c) # :nodoc: end end - # This code is based directly on the Text gem implementation # Returns a value representing the "cost" of transforming str1 into str2 + # Vendored version of DidYouMean::Levenshtein.distance from the ruby/did_you_mean gem @ 1.4.0 + # https://git.io/JJgZI def levenshtein_distance(str1, str2) - s = str1 - t = str2 - n = s.length - m = t.length - - return m if (0 == n) - return n if (0 == m) + n = str1.length + m = str2.length + return m if n.zero? + return n if m.zero? d = (0..m).to_a x = nil - str1.each_char.each_with_index do |char1,i| - e = i + 1 + # to avoid duplicating an enumerable object, create it outside of the loop + str2_codepoints = str2.codepoints - str2.each_char.each_with_index do |char2,j| - cost = (char1 == char2) ? 0 : 1 + str1.each_codepoint.with_index(1) do |char1, i| + j = 0 + while j < m + cost = (char1 == str2_codepoints[j]) ? 0 : 1 x = min3( - d[j + 1] + 1, # insertion - e + 1, # deletion - d[j] + cost # substitution - ) - d[j] = e - e = x + d[j + 1] + 1, # insertion + i + 1, # deletion + d[j] + cost # substitution + ) + d[j] = i + i = x + + j += 1 end - d[m] = x end - return x + x end end diff --git a/ruby/lib/rubygems/tsort.rb b/ruby/lib/rubygems/tsort.rb new file mode 100644 index 000000000..ebe7c3364 --- /dev/null +++ b/ruby/lib/rubygems/tsort.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative 'tsort/lib/tsort' diff --git a/ruby/lib/rubygems/tsort/.document b/ruby/lib/rubygems/tsort/.document new file mode 100644 index 000000000..0c43bbd6b --- /dev/null +++ b/ruby/lib/rubygems/tsort/.document @@ -0,0 +1 @@ +# Vendored files do not need to be documented diff --git a/ruby/lib/rubygems/tsort/lib/tsort.rb b/ruby/lib/rubygems/tsort/lib/tsort.rb new file mode 100644 index 000000000..f68c5947d --- /dev/null +++ b/ruby/lib/rubygems/tsort/lib/tsort.rb @@ -0,0 +1,454 @@ +# frozen_string_literal: true + +#-- +# tsort.rb - provides a module for topological sorting and strongly connected components. +#++ +# + +# +# Gem::TSort implements topological sorting using Tarjan's algorithm for +# strongly connected components. +# +# Gem::TSort is designed to be able to be used with any object which can be +# interpreted as a directed graph. +# +# Gem::TSort requires two methods to interpret an object as a graph, +# tsort_each_node and tsort_each_child. +# +# * tsort_each_node is used to iterate for all nodes over a graph. +# * tsort_each_child is used to iterate for child nodes of a given node. +# +# The equality of nodes are defined by eql? and hash since +# Gem::TSort uses Hash internally. +# +# == A Simple Example +# +# The following example demonstrates how to mix the Gem::TSort module into an +# existing class (in this case, Hash). Here, we're treating each key in +# the hash as a node in the graph, and so we simply alias the required +# #tsort_each_node method to Hash's #each_key method. For each key in the +# hash, the associated value is an array of the node's child nodes. This +# choice in turn leads to our implementation of the required #tsort_each_child +# method, which fetches the array of child nodes and then iterates over that +# array using the user-supplied block. +# +# require 'rubygems/tsort/lib/tsort' +# +# class Hash +# include Gem::TSort +# alias tsort_each_node each_key +# def tsort_each_child(node, &block) +# fetch(node).each(&block) +# end +# end +# +# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort +# #=> [3, 2, 1, 4] +# +# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components +# #=> [[4], [2, 3], [1]] +# +# == A More Realistic Example +# +# A very simple `make' like tool can be implemented as follows: +# +# require 'rubygems/tsort/lib/tsort' +# +# class Make +# def initialize +# @dep = {} +# @dep.default = [] +# end +# +# def rule(outputs, inputs=[], &block) +# triple = [outputs, inputs, block] +# outputs.each {|f| @dep[f] = [triple]} +# @dep[triple] = inputs +# end +# +# def build(target) +# each_strongly_connected_component_from(target) {|ns| +# if ns.length != 1 +# fs = ns.delete_if {|n| Array === n} +# raise Gem::TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}") +# end +# n = ns.first +# if Array === n +# outputs, inputs, block = n +# inputs_time = inputs.map {|f| File.mtime f}.max +# begin +# outputs_time = outputs.map {|f| File.mtime f}.min +# rescue Errno::ENOENT +# outputs_time = nil +# end +# if outputs_time == nil || +# inputs_time != nil && outputs_time <= inputs_time +# sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i +# block.call +# end +# end +# } +# end +# +# def tsort_each_child(node, &block) +# @dep[node].each(&block) +# end +# include Gem::TSort +# end +# +# def command(arg) +# print arg, "\n" +# system arg +# end +# +# m = Make.new +# m.rule(%w[t1]) { command 'date > t1' } +# m.rule(%w[t2]) { command 'date > t2' } +# m.rule(%w[t3]) { command 'date > t3' } +# m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' } +# m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' } +# m.build('t5') +# +# == Bugs +# +# * 'tsort.rb' is wrong name because this library uses +# Tarjan's algorithm for strongly connected components. +# Although 'strongly_connected_components.rb' is correct but too long. +# +# == References +# +# R. E. Tarjan, "Depth First Search and Linear Graph Algorithms", +# SIAM Journal on Computing, Vol. 1, No. 2, pp. 146-160, June 1972. +# + +module Gem + module TSort + class Cyclic < StandardError + end + + # Returns a topologically sorted array of nodes. + # The array is sorted from children to parents, i.e. + # the first element has no child and the last node has no parent. + # + # If there is a cycle, Gem::TSort::Cyclic is raised. + # + # class G + # include Gem::TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # p graph.tsort #=> [4, 2, 3, 1] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # p graph.tsort # raises Gem::TSort::Cyclic + # + def tsort + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + Gem::TSort.tsort(each_node, each_child) + end + + # Returns a topologically sorted array of nodes. + # The array is sorted from children to parents, i.e. + # the first element has no child and the last node has no parent. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # If there is a cycle, Gem::TSort::Cyclic is raised. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p Gem::TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p Gem::TSort.tsort(each_node, each_child) # raises Gem::TSort::Cyclic + # + def TSort.tsort(each_node, each_child) + Gem::TSort.tsort_each(each_node, each_child).to_a + end + + # The iterator version of the #tsort method. + # obj.tsort_each is similar to obj.tsort.each, but + # modification of _obj_ during the iteration may lead to unexpected results. + # + # #tsort_each returns +nil+. + # If there is a cycle, Gem::TSort::Cyclic is raised. + # + # class G + # include Gem::TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.tsort_each {|n| p n } + # #=> 4 + # # 2 + # # 3 + # # 1 + # + def tsort_each(&block) # :yields: node + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + Gem::TSort.tsort_each(each_node, each_child, &block) + end + + # The iterator version of the Gem::TSort.tsort method. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # Gem::TSort.tsort_each(each_node, each_child) {|n| p n } + # #=> 4 + # # 2 + # # 3 + # # 1 + # + def TSort.tsort_each(each_node, each_child) # :yields: node + return to_enum(__method__, each_node, each_child) unless block_given? + + Gem::TSort.each_strongly_connected_component(each_node, each_child) {|component| + if component.size == 1 + yield component.first + else + raise Cyclic.new("topological sort failed: #{component.inspect}") + end + } + end + + # Returns strongly connected components as an array of arrays of nodes. + # The array is sorted from children to parents. + # Each elements of the array represents a strongly connected component. + # + # class G + # include Gem::TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # p graph.strongly_connected_components #=> [[4], [2], [3], [1]] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # p graph.strongly_connected_components #=> [[4], [2, 3], [1]] + # + def strongly_connected_components + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + Gem::TSort.strongly_connected_components(each_node, each_child) + end + + # Returns strongly connected components as an array of arrays of nodes. + # The array is sorted from children to parents. + # Each elements of the array represents a strongly connected component. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p Gem::TSort.strongly_connected_components(each_node, each_child) + # #=> [[4], [2], [3], [1]] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # p Gem::TSort.strongly_connected_components(each_node, each_child) + # #=> [[4], [2, 3], [1]] + # + def TSort.strongly_connected_components(each_node, each_child) + Gem::TSort.each_strongly_connected_component(each_node, each_child).to_a + end + + # The iterator version of the #strongly_connected_components method. + # obj.each_strongly_connected_component is similar to + # obj.strongly_connected_components.each, but + # modification of _obj_ during the iteration may lead to unexpected results. + # + # #each_strongly_connected_component returns +nil+. + # + # class G + # include Gem::TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.each_strongly_connected_component {|scc| p scc } + # #=> [4] + # # [2] + # # [3] + # # [1] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # graph.each_strongly_connected_component {|scc| p scc } + # #=> [4] + # # [2, 3] + # # [1] + # + def each_strongly_connected_component(&block) # :yields: nodes + each_node = method(:tsort_each_node) + each_child = method(:tsort_each_child) + Gem::TSort.each_strongly_connected_component(each_node, each_child, &block) + end + + # The iterator version of the Gem::TSort.strongly_connected_components method. + # + # The graph is represented by _each_node_ and _each_child_. + # _each_node_ should have +call+ method which yields for each node in the graph. + # _each_child_ should have +call+ method which takes a node argument and yields for each child node. + # + # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } + # #=> [4] + # # [2] + # # [3] + # # [1] + # + # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_node = lambda {|&b| g.each_key(&b) } + # each_child = lambda {|n, &b| g[n].each(&b) } + # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc } + # #=> [4] + # # [2, 3] + # # [1] + # + def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes + return to_enum(__method__, each_node, each_child) unless block_given? + + id_map = {} + stack = [] + each_node.call {|node| + unless id_map.include? node + Gem::TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c| + yield c + } + end + } + nil + end + + # Iterates over strongly connected component in the subgraph reachable from + # _node_. + # + # Return value is unspecified. + # + # #each_strongly_connected_component_from doesn't call #tsort_each_node. + # + # class G + # include Gem::TSort + # def initialize(g) + # @g = g + # end + # def tsort_each_child(n, &b) @g[n].each(&b) end + # def tsort_each_node(&b) @g.each_key(&b) end + # end + # + # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}) + # graph.each_strongly_connected_component_from(2) {|scc| p scc } + # #=> [4] + # # [2] + # + # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}) + # graph.each_strongly_connected_component_from(2) {|scc| p scc } + # #=> [4] + # # [2, 3] + # + def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes + Gem::TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block) + end + + # Iterates over strongly connected components in a graph. + # The graph is represented by _node_ and _each_child_. + # + # _node_ is the first node. + # _each_child_ should have +call+ method which takes a node argument + # and yields for each child node. + # + # Return value is unspecified. + # + # #Gem::TSort.each_strongly_connected_component_from is a class method and + # it doesn't need a class to represent a graph which includes Gem::TSort. + # + # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]} + # each_child = lambda {|n, &b| graph[n].each(&b) } + # Gem::TSort.each_strongly_connected_component_from(1, each_child) {|scc| + # p scc + # } + # #=> [4] + # # [2, 3] + # # [1] + # + def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes + return to_enum(__method__, node, each_child, id_map, stack) unless block_given? + + minimum_id = node_id = id_map[node] = id_map.size + stack_length = stack.length + stack << node + + each_child.call(node) {|child| + if id_map.include? child + child_id = id_map[child] + minimum_id = child_id if child_id && child_id < minimum_id + else + sub_minimum_id = + Gem::TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c| + yield c + } + minimum_id = sub_minimum_id if sub_minimum_id < minimum_id + end + } + + if node_id == minimum_id + component = stack.slice!(stack_length .. -1) + component.each {|n| id_map[n] = nil} + yield component + end + + minimum_id + end + + # Should be implemented by a extended class. + # + # #tsort_each_node is used to iterate for all nodes over a graph. + # + def tsort_each_node # :yields: node + raise NotImplementedError.new + end + + # Should be implemented by a extended class. + # + # #tsort_each_child is used to iterate for child nodes of _node_. + # + def tsort_each_child(node) # :yields: child + raise NotImplementedError.new + end + end +end diff --git a/ruby/lib/rubygems/uninstaller.rb b/ruby/lib/rubygems/uninstaller.rb index 20b437d47..a36c5cbe2 100644 --- a/ruby/lib/rubygems/uninstaller.rb +++ b/ruby/lib/rubygems/uninstaller.rb @@ -6,10 +6,11 @@ #++ require 'fileutils' -require 'rubygems' -require 'rubygems/dependency_list' -require 'rubygems/rdoc' -require 'rubygems/user_interaction' +require_relative '../rubygems' +require_relative 'installer_uninstaller_utils' +require_relative 'dependency_list' +require_relative 'rdoc' +require_relative 'user_interaction' ## # An Uninstaller. @@ -20,9 +21,10 @@ # file. See Gem.pre_uninstall and Gem.post_uninstall for details. class Gem::Uninstaller - include Gem::UserInteraction + include Gem::InstallerUninstallerUtils + ## # The directory a gem's executables will be installed into @@ -47,6 +49,7 @@ def initialize(gem, options = {}) @gem = gem @version = options[:version] || Gem::Requirement.default @gem_home = File.realpath(options[:install_dir] || Gem.dir) + @plugins_dir = Gem.plugindir(@gem_home) @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @@ -67,6 +70,9 @@ def initialize(gem, options = {}) # only add user directory if install_dir is not set @user_install = false @user_install = options[:user_install] unless options[:install_dir] + + # Optimization: populated during #uninstall + @default_specs_matching_uninstall_params = [] end ## @@ -95,10 +101,8 @@ def uninstall default_specs, list = list.partition do |spec| spec.default_gem? end - - default_specs.each do |default_spec| - say "Gem #{default_spec.full_name} cannot be uninstalled because it is a default gem" - end + warn_cannot_uninstall_default_gems(default_specs - list) + @default_specs_matching_uninstall_params = default_specs list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir or @@ -110,10 +114,10 @@ def uninstall if list.empty? return unless other_repo_specs.any? - other_repos = other_repo_specs.map { |spec| spec.base_dir }.uniq + other_repos = other_repo_specs.map {|spec| spec.base_dir }.uniq message = ["#{@gem} is not installed in GEM_HOME, try:"] - message.concat other_repos.map { |repo| + message.concat other_repos.map {|repo| "\tgem uninstall -i #{repo} #{@gem}" } @@ -122,7 +126,7 @@ def uninstall remove_all list elsif list.size > 1 - gem_names = list.map { |gem| gem.full_name } + gem_names = list.map {|gem| gem.full_name } gem_names << "All versions" say @@ -158,8 +162,11 @@ def uninstall_gem(spec) end remove_executables @spec + remove_plugins @spec remove @spec + regenerate_plugins + Gem.post_uninstall_hooks.each do |hook| hook.call self end @@ -168,11 +175,10 @@ def uninstall_gem(spec) end ## - # Removes installed executables and batch files (windows only) for - # +gemspec+. + # Removes installed executables and batch files (windows only) for +spec+. def remove_executables(spec) - return if spec.nil? or spec.executables.empty? + return if spec.executables.empty? executables = spec.executables.clone @@ -191,16 +197,16 @@ def remove_executables(spec) return if executables.empty? - executables = executables.map { |exec| formatted_program_filename exec } + executables = executables.map {|exec| formatted_program_filename exec } remove = if @force_executables.nil? - ask_yes_no("Remove executables:\n" + - "\t#{executables.join ', '}\n\n" + - "in addition to the gem?", - true) - else - @force_executables - end + ask_yes_no("Remove executables:\n" + + "\t#{executables.join ', '}\n\n" + + "in addition to the gem?", + true) + else + @force_executables + end if remove bin_dir = @bin_dir || Gem.bindir(spec.base_dir) @@ -226,15 +232,11 @@ def remove_executables(spec) # NOTE: removes uninstalled gems from +list+. def remove_all(list) - list.each { |spec| uninstall_gem spec } + list.each {|spec| uninstall_gem spec } end ## # spec:: the spec of the gem to be uninstalled - # list:: the list of all such gems - # - # Warning: this method modifies the +list+ parameter. Once it has - # uninstalled a gem, it is removed from that list. def remove(spec) unless path_ok?(@gem_home, spec) or @@ -260,7 +262,10 @@ def remove(spec) safe_delete { FileUtils.rm_r gem } - Gem::RDoc.new(spec).remove + begin + Gem::RDoc.new(spec).remove + rescue NameError + end gemspec = spec.spec_file @@ -269,11 +274,30 @@ def remove(spec) end safe_delete { FileUtils.rm_r gemspec } - say "Successfully uninstalled #{spec.full_name}" + announce_deletion_of(spec) Gem::Specification.reset end + ## + # Remove any plugin wrappers for +spec+. + + def remove_plugins(spec) # :nodoc: + return if spec.plugins.empty? + + remove_plugins_for(spec, @plugins_dir) + end + + ## + # Regenerates plugin wrappers after removal. + + def regenerate_plugins + latest = Gem::Specification.latest_spec_for(@spec.name) + return if latest.nil? + + regenerate_plugins_for(latest, @plugins_dir) + end + ## # Is +spec+ in +gem_dir+? @@ -317,8 +341,8 @@ def ask_if_ok(spec) # :nodoc: s.name == spec.name && s.full_name != spec.full_name end - spec.dependent_gems.each do |dep_spec, dep, satlist| - unless siblings.any? { |s| s.satisfies_requirement? dep } + spec.dependent_gems(@check_dev).each do |dep_spec, dep, satlist| + unless siblings.any? {|s| s.satisfies_requirement? dep } msg << "#{dep_spec.name}-#{dep_spec.version} depends on #{dep}" end end @@ -336,7 +360,7 @@ def formatted_program_filename(filename) # :nodoc: # of what it did for us to find rather than trying to recreate # it again. if @format_executable - require 'rubygems/installer' + require_relative 'installer' Gem::Installer.exec_format % File.basename(filename) else filename @@ -354,4 +378,33 @@ def safe_delete(&block) raise e end + private + + def announce_deletion_of(spec) + name = spec.full_name + say "Successfully uninstalled #{name}" + if default_spec_matches?(spec) + say( + "There was both a regular copy and a default copy of #{name}. The " \ + "regular copy was successfully uninstalled, but the default copy " \ + "was left around because default gems can't be removed." + ) + end + end + + # @return true if the specs of any default gems are `==` to the given `spec`. + def default_spec_matches?(spec) + !default_specs_that_match(spec).empty? + end + + # @return [Array] specs of default gems that are `==` to the given `spec`. + def default_specs_that_match(spec) + @default_specs_matching_uninstall_params.select {|default_spec| spec == default_spec } + end + + def warn_cannot_uninstall_default_gems(specs) + specs.each do |spec| + say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem" + end + end end diff --git a/ruby/lib/rubygems/unknown_command_spell_checker.rb b/ruby/lib/rubygems/unknown_command_spell_checker.rb new file mode 100644 index 000000000..ee5c2fbe0 --- /dev/null +++ b/ruby/lib/rubygems/unknown_command_spell_checker.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class Gem::UnknownCommandSpellChecker + attr_reader :error + + def initialize(error) + @error = error + end + + def corrections + @corrections ||= + spell_checker.correct(error.unknown_command).map(&:inspect) + end + + private + + def spell_checker + dictionary = Gem::CommandManager.instance.command_names + DidYouMean::SpellChecker.new(dictionary: dictionary) + end +end diff --git a/ruby/lib/rubygems/uri.rb b/ruby/lib/rubygems/uri.rb new file mode 100644 index 000000000..ba30fac2f --- /dev/null +++ b/ruby/lib/rubygems/uri.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +## +# The Uri handles rubygems source URIs. +# + +class Gem::Uri + def initialize(source_uri) + @parsed_uri = parse(source_uri) + end + + def redacted + return self unless valid_uri? + + if token? || oauth_basic? + with_redacted_user + elsif password? + with_redacted_password + else + self + end + end + + def to_s + @parsed_uri.to_s + end + + def redact_credentials_from(text) + return text unless valid_uri? && password? + + text.sub(password, 'REDACTED') + end + + def method_missing(method_name, *args, &blk) + if @parsed_uri.respond_to?(method_name) + @parsed_uri.send(method_name, *args, &blk) + else + super + end + end + + def respond_to_missing?(method_name, include_private = false) + @parsed_uri.respond_to?(method_name, include_private) || super + end + + protected + + # Add a protected reader for the cloned instance to access the original object's parsed uri + attr_reader :parsed_uri + + private + + ## + # Parses the #uri, raising if it's invalid + + def parse!(uri) + require "uri" + + raise URI::InvalidURIError unless uri + + # Always escape URI's to deal with potential spaces and such + # It should also be considered that source_uri may already be + # a valid URI with escaped characters. e.g. "{DESede}" is encoded + # as "%7BDESede%7D". If this is escaped again the percentage + # symbols will be escaped. + begin + URI.parse(uri) + rescue URI::InvalidURIError + URI.parse(URI::DEFAULT_PARSER.escape(uri)) + end + end + + ## + # Parses the #uri, returning the original uri if it's invalid + + def parse(uri) + return uri unless uri.is_a?(String) + + parse!(uri) + rescue URI::InvalidURIError + uri + end + + def with_redacted_user + clone.tap {|uri| uri.user = 'REDACTED' } + end + + def with_redacted_password + clone.tap {|uri| uri.password = 'REDACTED' } + end + + def valid_uri? + !@parsed_uri.is_a?(String) + end + + def password? + !!password + end + + def oauth_basic? + password == 'x-oauth-basic' + end + + def token? + !user.nil? && password.nil? + end + + def initialize_copy(original) + @parsed_uri = original.parsed_uri.clone + end +end diff --git a/ruby/lib/rubygems/uri_formatter.rb b/ruby/lib/rubygems/uri_formatter.rb index f3d510470..3bda89687 100644 --- a/ruby/lib/rubygems/uri_formatter.rb +++ b/ruby/lib/rubygems/uri_formatter.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'cgi' ## # The UriFormatter handles URIs from user-input and escaping. @@ -9,7 +8,6 @@ # p uf.normalize #=> 'http://example.com' class Gem::UriFormatter - ## # The URI to be formatted. @@ -19,6 +17,8 @@ class Gem::UriFormatter # Creates a new URI formatter for +uri+. def initialize(uri) + require 'cgi' + @uri = uri end @@ -44,5 +44,4 @@ def unescape return unless @uri CGI.unescape @uri end - end diff --git a/ruby/lib/rubygems/uri_parser.rb b/ruby/lib/rubygems/uri_parser.rb deleted file mode 100644 index 5c7cabc43..000000000 --- a/ruby/lib/rubygems/uri_parser.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -## -# The UriParser handles parsing URIs. -# - -class Gem::UriParser - - ## - # Parses the #uri, raising if it's invalid - - def parse!(uri) - raise URI::InvalidURIError unless uri - - # Always escape URI's to deal with potential spaces and such - # It should also be considered that source_uri may already be - # a valid URI with escaped characters. e.g. "{DESede}" is encoded - # as "%7BDESede%7D". If this is escaped again the percentage - # symbols will be escaped. - begin - URI.parse(uri) - rescue URI::InvalidURIError - URI.parse(URI::DEFAULT_PARSER.escape(uri)) - end - end - - ## - # Parses the #uri, returning the original uri if it's invalid - - def parse(uri) - parse!(uri) - rescue URI::InvalidURIError - uri - end - -end diff --git a/ruby/lib/rubygems/uri_parsing.rb b/ruby/lib/rubygems/uri_parsing.rb deleted file mode 100644 index 941d7e023..000000000 --- a/ruby/lib/rubygems/uri_parsing.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require "rubygems/uri_parser" - -module Gem::UriParsing - - def parse_uri(source_uri) - return source_uri unless source_uri.is_a?(String) - - uri_parser.parse(source_uri) - end - - private :parse_uri - - def uri_parser - require "uri" - - Gem::UriParser.new - end - - private :uri_parser - -end diff --git a/ruby/lib/rubygems/user_interaction.rb b/ruby/lib/rubygems/user_interaction.rb index 93f528a76..e632f418a 100644 --- a/ruby/lib/rubygems/user_interaction.rb +++ b/ruby/lib/rubygems/user_interaction.rb @@ -5,9 +5,8 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/util' -require 'rubygems/deprecate' -require 'rubygems/text' +require_relative 'deprecate' +require_relative 'text' ## # Module that defines the default UserInteraction. Any class including this @@ -173,7 +172,6 @@ def verbose(msg = nil) # Gem::StreamUI implements a simple stream based user interface. class Gem::StreamUI - extend Gem::Deprecate ## @@ -260,23 +258,23 @@ def ask_yes_no(question, default=nil) end default_answer = case default - when nil - 'yn' - when true - 'Yn' - else - 'yN' - end + when nil + 'yn' + when true + 'Yn' + else + 'yN' + end result = nil while result.nil? do result = case ask "#{question} [#{default_answer}]" - when /^y/i then true - when /^n/i then false - when /^$/ then default - else nil - end + when /^y/i then true + when /^n/i then false + when /^$/ then default + else nil + end end return result @@ -323,7 +321,7 @@ def require_io_console def _gets_noecho require_io_console - @ins.noecho {@ins.gets} + @ins.noecho { @ins.gets } end ## @@ -358,14 +356,6 @@ def alert_error(statement, question=nil) ask(question) if question end - ## - # Display a debug message on the same location as error messages. - - def debug(statement) - @errs.puts statement - end - deprecate :debug, :none, 2018, 12 - ## # Terminate the application with exit code +status+, running any exit # handlers that might have been defined. @@ -396,7 +386,6 @@ def progress_reporter(*args) # An absolutely silent progress reporter. class SilentProgressReporter - ## # The count of items is never updated for the silent progress reporter. @@ -421,14 +410,12 @@ def updated(message) def done end - end ## # A basic dotted progress reporter. class SimpleProgressReporter - include Gem::DefaultUserInteraction ## @@ -466,14 +453,12 @@ def updated(message) def done @out.puts "\n#{@terminal_message}" end - end ## # A progress reporter that prints out messages about the current progress. class VerboseProgressReporter - include Gem::DefaultUserInteraction ## @@ -510,7 +495,6 @@ def updated(message) def done @out.puts @terminal_message end - end ## @@ -528,7 +512,6 @@ def download_reporter(*args) # An absolutely silent download reporter. class SilentDownloadReporter - ## # The silent download reporter ignores all arguments @@ -554,15 +537,13 @@ def update(current) def done end - end ## # A progress reporter that behaves nicely with threaded downloading. class ThreadedDownloadReporter - - MUTEX = Mutex.new + MUTEX = Thread::Mutex.new ## # The current file name being displayed @@ -610,9 +591,7 @@ def locked_puts(message) @out.puts message end end - end - end ## @@ -620,7 +599,6 @@ def locked_puts(message) # STDOUT, and STDERR. class Gem::ConsoleUI < Gem::StreamUI - ## # The Console UI has no arguments as it defaults to reading input from # stdin, output to stdout and warnings or errors to stderr. @@ -628,14 +606,12 @@ class Gem::ConsoleUI < Gem::StreamUI def initialize super STDIN, STDOUT, STDERR, true end - end ## # SilentUI is a UI choice that is absolutely silent. class Gem::SilentUI < Gem::StreamUI - ## # The SilentUI has no arguments as it does not use any stream. @@ -661,5 +637,4 @@ def download_reporter(*args) # :nodoc: def progress_reporter(*args) # :nodoc: SilentProgressReporter.new(@outs, *args) end - end diff --git a/ruby/lib/rubygems/util.rb b/ruby/lib/rubygems/util.rb index b5f140840..4363c5adc 100644 --- a/ruby/lib/rubygems/util.rb +++ b/ruby/lib/rubygems/util.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true +require_relative 'deprecate' + ## # This module contains various utility methods as module methods. module Gem::Util - @silent_mutex = nil - ## # Zlib::GzipReader wrapper that unzips +data+. @@ -14,7 +14,13 @@ def self.gunzip(data) require 'stringio' data = StringIO.new(data, 'r') - unzipped = Zlib::GzipReader.new(data).read + gzip_reader = begin + Zlib::GzipReader.new(data) + rescue Zlib::GzipFile::Error => e + raise e.class, e.inspect, e.backtrace + end + + unzipped = gzip_reader.read unzipped.force_encoding Encoding::BINARY unzipped end @@ -64,6 +70,12 @@ def self.silent_system(*command) system(*(cmds << opt)) end + class << self + extend Gem::Deprecate + + rubygems_deprecate :silent_system + end + ## # Enumerates the parents of +directory+. diff --git a/ruby/lib/rubygems/util/licenses.rb b/ruby/lib/rubygems/util/licenses.rb index f23be157b..3f4178c6e 100644 --- a/ruby/lib/rubygems/util/licenses.rb +++ b/ruby/lib/rubygems/util/licenses.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true -require 'rubygems/text' +require_relative '../text' class Gem::Licenses - extend Gem::Text NONSTANDARD = 'Nonstandard'.freeze + LICENSE_REF = 'LicenseRef-.+'.freeze # Software Package Data Exchange (SPDX) standard open-source software # license identifiers - LICENSE_IDENTIFIERS = %w( + LICENSE_IDENTIFIERS = %w[ 0BSD AAL ADSL @@ -19,6 +19,8 @@ class Gem::Licenses AFL-2.1 AFL-3.0 AGPL-1.0 + AGPL-1.0-only + AGPL-1.0-or-later AGPL-3.0 AGPL-3.0-only AGPL-3.0-or-later @@ -26,6 +28,7 @@ class Gem::Licenses AML AMPAS ANTLR-PD + ANTLR-PD-fallback APAFML APL-1.0 APSL-1.0 @@ -49,29 +52,41 @@ class Gem::Licenses BSD-2-Clause-FreeBSD BSD-2-Clause-NetBSD BSD-2-Clause-Patent + BSD-2-Clause-Views BSD-3-Clause BSD-3-Clause-Attribution BSD-3-Clause-Clear BSD-3-Clause-LBNL + BSD-3-Clause-Modification + BSD-3-Clause-No-Military-License BSD-3-Clause-No-Nuclear-License BSD-3-Clause-No-Nuclear-License-2014 BSD-3-Clause-No-Nuclear-Warranty + BSD-3-Clause-Open-MPI BSD-4-Clause + BSD-4-Clause-Shortened BSD-4-Clause-UC BSD-Protection BSD-Source-Code BSL-1.0 + BUSL-1.1 Bahyph Barr Beerware BitTorrent-1.0 BitTorrent-1.1 + BlueOak-1.0.0 Borceux + C-UDA-1.0 + CAL-1.0 + CAL-1.0-Combined-Work-Exception CATOSL-1.1 CC-BY-1.0 CC-BY-2.0 CC-BY-2.5 CC-BY-3.0 + CC-BY-3.0-AT + CC-BY-3.0-US CC-BY-4.0 CC-BY-NC-1.0 CC-BY-NC-2.0 @@ -82,6 +97,7 @@ class Gem::Licenses CC-BY-NC-ND-2.0 CC-BY-NC-ND-2.5 CC-BY-NC-ND-3.0 + CC-BY-NC-ND-3.0-IGO CC-BY-NC-ND-4.0 CC-BY-NC-SA-1.0 CC-BY-NC-SA-2.0 @@ -95,12 +111,17 @@ class Gem::Licenses CC-BY-ND-4.0 CC-BY-SA-1.0 CC-BY-SA-2.0 + CC-BY-SA-2.0-UK + CC-BY-SA-2.1-JP CC-BY-SA-2.5 CC-BY-SA-3.0 + CC-BY-SA-3.0-AT CC-BY-SA-4.0 + CC-PDDC CC0-1.0 CDDL-1.0 CDDL-1.1 + CDL-1.0 CDLA-Permissive-1.0 CDLA-Sharing-1.0 CECILL-1.0 @@ -109,6 +130,11 @@ class Gem::Licenses CECILL-2.1 CECILL-B CECILL-C + CERN-OHL-1.1 + CERN-OHL-1.2 + CERN-OHL-P-2.0 + CERN-OHL-S-2.0 + CERN-OHL-W-2.0 CNRI-Jython CNRI-Python CNRI-Python-GPL-Compatible @@ -124,12 +150,14 @@ class Gem::Licenses Cube D-FSL-1.0 DOC + DRL-1.0 DSDP Dotseqn ECL-1.0 ECL-2.0 EFL-1.0 EFL-2.0 + EPICS EPL-1.0 EPL-2.0 EUDatagrid @@ -145,17 +173,32 @@ class Gem::Licenses FTL Fair Frameworx-1.0 + FreeBSD-DOC FreeImage + GD GFDL-1.1 + GFDL-1.1-invariants-only + GFDL-1.1-invariants-or-later + GFDL-1.1-no-invariants-only + GFDL-1.1-no-invariants-or-later GFDL-1.1-only GFDL-1.1-or-later GFDL-1.2 + GFDL-1.2-invariants-only + GFDL-1.2-invariants-or-later + GFDL-1.2-no-invariants-only + GFDL-1.2-no-invariants-or-later GFDL-1.2-only GFDL-1.2-or-later GFDL-1.3 + GFDL-1.3-invariants-only + GFDL-1.3-invariants-or-later + GFDL-1.3-no-invariants-only + GFDL-1.3-no-invariants-or-later GFDL-1.3-only GFDL-1.3-or-later GL2PS + GLWTPL GPL-1.0 GPL-1.0+ GPL-1.0-only @@ -179,7 +222,10 @@ class Gem::Licenses Glide Glulxe HPND + HPND-sell-variant + HTMLTIDY HaskellReport + Hippocratic-2.1 IBM-pibs ICU IJG @@ -192,6 +238,7 @@ class Gem::Licenses Intel Intel-ACPI Interbase-1.0 + JPNIC JSON JasPer-2.0 LAL-1.2 @@ -222,11 +269,15 @@ class Gem::Licenses LiLiQ-R-1.1 LiLiQ-Rplus-1.1 Libpng + Linux-OpenIB MIT + MIT-0 MIT-CMU + MIT-Modern-Variant MIT-advertising MIT-enna MIT-feh + MIT-open-group MITNFA MPL-1.0 MPL-1.1 @@ -238,12 +289,18 @@ class Gem::Licenses MakeIndex MirOS Motosoto + MulanPSL-1.0 + MulanPSL-2.0 Multics Mup + NAIST-2003 NASA-1.3 NBPL-1.0 + NCGL-UK-2.0 NCSA NGPL + NIST-PD + NIST-PD-fallback NLOD-1.0 NLPL NOSL @@ -252,6 +309,7 @@ class Gem::Licenses NPOSL-3.0 NRL NTP + NTP-0 Naumen Net-SNMP NetCDF @@ -259,11 +317,23 @@ class Gem::Licenses Nokia Noweb Nunit + O-UDA-1.0 OCCT-PL OCLC-2.0 + ODC-By-1.0 ODbL-1.0 OFL-1.0 + OFL-1.0-RFN + OFL-1.0-no-RFN OFL-1.1 + OFL-1.1-RFN + OFL-1.1-no-RFN + OGC-1.0 + OGDL-Taiwan-1.0 + OGL-Canada-2.0 + OGL-UK-1.0 + OGL-UK-2.0 + OGL-UK-3.0 OGTSL OLDAP-1.1 OLDAP-1.2 @@ -293,7 +363,12 @@ class Gem::Licenses PDDL-1.0 PHP-3.0 PHP-3.01 + PSF-2.0 + Parity-6.0.0 + Parity-7.0.0 Plexus + PolyForm-Noncommercial-1.0.0 + PolyForm-Small-Business-1.0.0 PostgreSQL Python-2.0 QPL-1.0 @@ -311,15 +386,21 @@ class Gem::Licenses SGI-B-1.0 SGI-B-1.1 SGI-B-2.0 + SHL-0.5 + SHL-0.51 SISSL SISSL-1.2 SMLNJ SMPPL SNIA SPL-1.0 + SSH-OpenSSH + SSH-short + SSPL-1.0 SWL Saxpath Sendmail + Sendmail-8.23 SimPL-2.0 Sleepycat Spencer-86 @@ -327,11 +408,15 @@ class Gem::Licenses Spencer-99 StandardML-NJ SugarCRM-1.1.3 + TAPR-OHL-1.0 TCL TCP-wrappers TMate TORQUE-1.1 TOSL + TU-Berlin-1.0 + TU-Berlin-2.0 + UCL-1.0 UPL-1.0 Unicode-DFS-2015 Unicode-DFS-2016 @@ -361,16 +446,22 @@ class Gem::Licenses Zimbra-1.3 Zimbra-1.4 Zlib + blessing bzip2-1.0.5 bzip2-1.0.6 + copyleft-next-0.3.0 + copyleft-next-0.3.1 curl diffmark dvipdfm eCos-2.0 eGenix + etalab-2.0 gSOAP-1.3b gnuplot iMatix + libpng-2.0 + libselinux-1.0 libtiff mpich2 psfrag @@ -379,10 +470,10 @@ class Gem::Licenses xinetd xpp zlib-acknowledgement - ).freeze + ].freeze # exception identifiers - EXCEPTION_IDENTIFIERS = %w( + EXCEPTION_IDENTIFIERS = %w[ 389-exception Autoconf-exception-2.0 Autoconf-exception-3.0 @@ -396,12 +487,26 @@ class Gem::Licenses Font-exception-2.0 GCC-exception-2.0 GCC-exception-3.1 + GPL-3.0-linking-exception + GPL-3.0-linking-source-exception + GPL-CC-1.0 + LGPL-3.0-linking-exception + LLVM-exception LZMA-exception Libtool-exception Linux-syscall-note Nokia-Qt-exception-1.1 OCCT-exception-1.0 + OCaml-LGPL-linking-exception + OpenJDK-assembly-exception-1.0 + PS-or-PDF-font-exception-20170817 + Qt-GPL-exception-1.0 + Qt-LGPL-exception-1.1 Qwt-exception-1.0 + SHL-2.0 + SHL-2.1 + Swift-exception + Universal-FOSS-exception-1.0 WxWindows-exception-3.1 eCos-exception-2.0 freertos-exception-2.0 @@ -410,15 +515,16 @@ class Gem::Licenses mif-exception openvpn-openssl-exception u-boot-exception-2.0 - ).freeze + ].freeze REGEXP = %r{ \A - ( + (?: #{Regexp.union(LICENSE_IDENTIFIERS)} \+? - (\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})? + (?:\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})? | #{NONSTANDARD} + | #{LICENSE_REF} ) \Z }ox.freeze @@ -435,5 +541,4 @@ def self.suggestions(license) return unless lowest < license.size by_distance[lowest] end - end diff --git a/ruby/lib/rubygems/util/list.rb b/ruby/lib/rubygems/util/list.rb index 7e4d6b5de..33c40af4b 100644 --- a/ruby/lib/rubygems/util/list.rb +++ b/ruby/lib/rubygems/util/list.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Gem class List - include Enumerable attr_accessor :value, :tail @@ -34,6 +33,5 @@ def self.prepend(list, value) return List.new(value) unless list List.new value, list end - end end diff --git a/ruby/lib/rubygems/validator.rb b/ruby/lib/rubygems/validator.rb index 7ed0a1f80..728595e77 100644 --- a/ruby/lib/rubygems/validator.rb +++ b/ruby/lib/rubygems/validator.rb @@ -5,14 +5,13 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems/package' -require 'rubygems/installer' +require_relative 'package' +require_relative 'installer' ## # Validator performs various gem file and gem database validation class Gem::Validator - include Gem::UserInteraction def initialize # :nodoc: @@ -60,7 +59,7 @@ def <=>(other) # :nodoc: # TODO needs further cleanup def alien(gems=[]) - errors = Hash.new { |h,k| h[k] = {} } + errors = Hash.new {|h,k| h[k] = {} } Gem::Specification.each do |spec| next unless gems.include? spec.name unless gems.empty? @@ -141,5 +140,4 @@ def alien(gems=[]) errors end - end diff --git a/ruby/lib/rubygems/version.rb b/ruby/lib/rubygems/version.rb index 6524faf5c..c59501ad5 100644 --- a/ruby/lib/rubygems/version.rb +++ b/ruby/lib/rubygems/version.rb @@ -1,4 +1,7 @@ # frozen_string_literal: true + +require_relative "deprecate" + ## # The Version class processes string versions into comparable # values. A version string should normally be a series of numbers @@ -150,8 +153,7 @@ # a zero to give a sensible result. class Gem::Version - - autoload :Requirement, 'rubygems/requirement' + autoload :Requirement, File.expand_path('requirement', __dir__) include Comparable @@ -187,7 +189,7 @@ def self.correct?(version) # ver3 = Version.create(nil) # -> nil def self.create(input) - if self === input # check yourself before you wreck yourself + if self === input # check yourself before you wreck yourself input elsif input.nil? nil @@ -231,7 +233,7 @@ def initialize(version) def bump @@bump[self] ||= begin segments = self.segments - segments.pop while segments.any? { |s| String === s } + segments.pop while segments.any? {|s| String === s } segments.pop if segments.size > 1 segments[-1] = segments[-1].succ @@ -309,12 +311,12 @@ def pretty_print(q) # :nodoc: def release @@release[self] ||= if prerelease? - segments = self.segments - segments.pop while segments.any? { |s| String === s } - self.class.new segments.join('.') - else - self - end + segments = self.segments + segments.pop while segments.any? {|s| String === s } + self.class.new segments.join('.') + else + self + end end def segments # :nodoc: @@ -327,7 +329,7 @@ def segments # :nodoc: def approximate_recommendation segments = self.segments - segments.pop while segments.any? { |s| String === s } + segments.pop while segments.any? {|s| String === s } segments.pop while segments.size > 2 segments.push 0 while segments.size < 2 @@ -340,9 +342,11 @@ def approximate_recommendation # Compares this version with +other+ returning -1, 0, or 1 if the # other version is larger, the same, or smaller than this # one. Attempts to compare to something that's not a - # Gem::Version return +nil+. + # Gem::Version or a valid version String return +nil+. def <=>(other) + return self <=> self.class.new(other) if (String === other) && self.class.correct?(other) + return unless Gem::Version === other return 0 if @version == other._version || canonical_segments == other.canonical_segments @@ -404,5 +408,4 @@ def _split_segments numeric_segments = string_segments.slice!(0, string_start || string_segments.size) return numeric_segments, string_segments end - end diff --git a/ruby/lib/rubygems/version_option.rb b/ruby/lib/rubygems/version_option.rb index 458a7a660..1db382fa7 100644 --- a/ruby/lib/rubygems/version_option.rb +++ b/ruby/lib/rubygems/version_option.rb @@ -5,7 +5,7 @@ # See LICENSE.txt for permissions. #++ -require 'rubygems' +require_relative '../rubygems' ## # Mixin methods for --version and --platform Gem::Command options. @@ -16,7 +16,7 @@ module Gem::VersionOption # Add the --platform option to the option parser. def add_platform_option(task = command, *wrap) - OptionParser.accept Gem::Platform do |value| + Gem::OptionParser.accept Gem::Platform do |value| if value == Gem::Platform::RUBY value else @@ -51,7 +51,7 @@ def add_prerelease_option(*wrap) # Add the --version option to the option parser. def add_version_option(task = command, *wrap) - OptionParser.accept Gem::Requirement do |value| + Gem::OptionParser.accept Gem::Requirement do |value| Gem::Requirement.new(*value.split(/\s*,\s*/)) end @@ -73,4 +73,10 @@ def add_version_option(task = command, *wrap) end end + ## + # Extract platform given on the command line + + def get_platform_from_requirements(requirements) + Gem.platforms[1].to_s if requirements.key? :added_platform + end end diff --git a/ruby/lib/securerandom.gemspec b/ruby/lib/securerandom.gemspec new file mode 100644 index 000000000..b8f019f9a --- /dev/null +++ b/ruby/lib/securerandom.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "securerandom" + spec.version = "0.1.1" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Interface for secure random number generator.} + spec.description = %q{Interface for secure random number generator.} + spec.homepage = "https://github.com/ruby/securerandom" + spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0") + spec.licenses = ["Ruby", "BSD-2-Clause"] + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + + 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/ruby/lib/securerandom.rb b/ruby/lib/securerandom.rb index 205cb70be..9cbf4ea78 100644 --- a/ruby/lib/securerandom.rb +++ b/ruby/lib/securerandom.rb @@ -1,6 +1,8 @@ # -*- coding: us-ascii -*- # frozen_string_literal: true +require 'random/formatter' + # == Secure random number generator interface. # # This library is an interface to secure random number generators which are @@ -31,77 +33,17 @@ # * uuid # # These methods are usable as class methods of SecureRandom such as -# `SecureRandom.hex`. -# -# === Examples -# -# Generate random hexadecimal strings: -# -# require 'securerandom' -# -# SecureRandom.hex(10) #=> "52750b30ffbc7de3b362" -# SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559" -# SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23" -# -# Generate random base64 strings: -# -# SecureRandom.base64(10) #=> "EcmTPZwWRAozdA==" -# SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg==" -# SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8" -# -# Generate random binary strings: -# -# SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301" -# SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337" -# -# Generate alphanumeric strings: -# -# SecureRandom.alphanumeric(10) #=> "S8baxMJnPl" -# SecureRandom.alphanumeric(10) #=> "aOxAg8BAJe" -# -# Generate UUIDs: -# -# SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594" -# SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab" +# +SecureRandom.hex+. # +# If a secure random number generator is not available, +# +NotImplementedError+ is raised. module SecureRandom - @rng_chooser = Mutex.new # :nodoc: - class << self def bytes(n) return gen_random(n) end - def gen_random(n) - ret = Random.urandom(1) - if ret.nil? - begin - require 'openssl' - rescue NoMethodError - raise NotImplementedError, "No random device" - else - @rng_chooser.synchronize do - class << self - remove_method :gen_random - alias gen_random gen_random_openssl - public :gen_random - end - end - return gen_random(n) - end - else - @rng_chooser.synchronize do - class << self - remove_method :gen_random - alias gen_random gen_random_urandom - public :gen_random - end - end - return gen_random(n) - end - end - private def gen_random_openssl(n) @@ -129,204 +71,21 @@ def gen_random_urandom(n) end ret end - end -end - -module Random::Formatter - - # SecureRandom.random_bytes generates a random binary string. - # - # The argument _n_ specifies the length of the result string. - # - # If _n_ is not specified or is nil, 16 is assumed. - # It may be larger in future. - # - # The result may contain any byte: "\x00" - "\xff". - # - # require 'securerandom' - # - # SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6" - # SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - def random_bytes(n=nil) - n = n ? n.to_int : 16 - gen_random(n) - end - - # SecureRandom.hex generates a random hexadecimal string. - # - # The argument _n_ specifies the length, in bytes, of the random number to be generated. - # The length of the resulting hexadecimal string is twice of _n_. - # - # If _n_ is not specified or is nil, 16 is assumed. - # It may be larger in the future. - # - # The result may contain 0-9 and a-f. - # - # require 'securerandom' - # - # SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485" - # SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - def hex(n=nil) - random_bytes(n).unpack("H*")[0] - end - - # SecureRandom.base64 generates a random base64 string. - # - # The argument _n_ specifies the length, in bytes, of the random number - # to be generated. The length of the result string is about 4/3 of _n_. - # - # If _n_ is not specified or is nil, 16 is assumed. - # It may be larger in the future. - # - # The result may contain A-Z, a-z, 0-9, "+", "/" and "=". - # - # require 'securerandom' - # - # SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A==" - # SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ==" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - # - # See RFC 3548 for the definition of base64. - def base64(n=nil) - [random_bytes(n)].pack("m0") - end - # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string. - # - # The argument _n_ specifies the length, in bytes, of the random number - # to be generated. The length of the result string is about 4/3 of _n_. - # - # If _n_ is not specified or is nil, 16 is assumed. - # It may be larger in the future. - # - # The boolean argument _padding_ specifies the padding. - # If it is false or nil, padding is not generated. - # Otherwise padding is generated. - # By default, padding is not generated because "=" may be used as a URL delimiter. - # - # The result may contain A-Z, a-z, 0-9, "-" and "_". - # "=" is also used if _padding_ is true. - # - # require 'securerandom' - # - # SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg" - # SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg" - # - # SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ==" - # SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg==" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - # - # See RFC 3548 for the definition of URL-safe base64. - def urlsafe_base64(n=nil, padding=false) - s = [random_bytes(n)].pack("m0") - s.tr!("+/", "-_") - s.delete!("=") unless padding - s - end - - # SecureRandom.uuid generates a random v4 UUID (Universally Unique IDentifier). - # - # require 'securerandom' - # - # SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594" - # SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab" - # SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b" - # - # The version 4 UUID is purely random (except the version). - # It doesn't contain meaningful information such as MAC addresses, timestamps, etc. - # - # The result contains 122 random bits (15.25 random bytes). - # - # See RFC 4122 for details of UUID. - # - 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 - end - - private def gen_random(n) - self.bytes(n) - end - - # SecureRandom.choose generates a string that randomly draws from a - # source array of characters. - # - # The argument _source_ specifies the array of characters from which - # to generate the string. - # The argument _n_ specifies the length, in characters, of the string to be - # generated. - # - # The result may contain whatever characters are in the source array. - # - # require 'securerandom' - # - # SecureRandom.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron" - # SecureRandom.choose([*'0'..'9'], 5) #=> "27309" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - private def choose(source, n) - size = source.size - m = 1 - limit = size - while limit * size <= 0x100000000 - limit *= size - m += 1 - end - result = ''.dup - while m <= n - rs = random_number(limit) - is = rs.digits(size) - (m-is.length).times { is << 0 } - result << source.values_at(*is).join('') - n -= m - end - if 0 < n - rs = random_number(limit) - is = rs.digits(size) - if is.length < n - (n-is.length).times { is << 0 } + ret = Random.urandom(1) + if ret.nil? + begin + require 'openssl' + rescue NoMethodError + raise NotImplementedError, "No random device" else - is.pop while n < is.length + alias gen_random gen_random_openssl end - result.concat source.values_at(*is).join('') + else + alias gen_random gen_random_urandom end - result - end - ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'] - # SecureRandom.alphanumeric generates a random alphanumeric string. - # - # The argument _n_ specifies the length, in characters, of the alphanumeric - # string to be generated. - # - # If _n_ is not specified or is nil, 16 is assumed. - # It may be larger in the future. - # - # The result may contain A-Z, a-z and 0-9. - # - # require 'securerandom' - # - # SecureRandom.alphanumeric #=> "2BuBuLf3WfSKyQbR" - # SecureRandom.alphanumeric(10) #=> "i6K93NdqiH" - # - # If a secure random number generator is not available, - # +NotImplementedError+ is raised. - def alphanumeric(n=nil) - n = 16 if n.nil? - choose(ALPHANUMERIC, n) + public :gen_random end end diff --git a/ruby/lib/set.rb b/ruby/lib/set.rb index 5a96c8183..7832c848c 100644 --- a/ruby/lib/set.rb +++ b/ruby/lib/set.rb @@ -1,38 +1,31 @@ -#-- # frozen_string_literal: true +# :markup: markdown # # set.rb - defines the Set class -#++ -# Copyright (c) 2002-2016 Akinori MUSHA +# +# Copyright (c) 2002-2020 Akinori MUSHA # # Documentation by Akinori MUSHA and Gavin Sinclair. # # All rights reserved. You can redistribute and/or modify it under the same # terms as Ruby. -# -# $Id$ -# -# == Overview -# + + +## # This library provides the Set class, which deals with a collection # of unordered values with no duplicates. It is a hybrid of Array's -# intuitive inter-operation facilities and Hash's fast lookup. If you -# need to keep values sorted in some order, use the SortedSet class. -# -# The method +to_set+ is added to Enumerable for convenience. +# intuitive inter-operation facilities and Hash's fast lookup. # -# See the Set and SortedSet documentation for examples of usage. - - +# The method `to_set` is added to Enumerable for convenience. # # Set implements a collection of unordered values with no duplicates. # This is a hybrid of Array's intuitive inter-operation facilities and # Hash's fast lookup. # -# Set is easy to use with Enumerable objects (implementing +each+). +# Set is easy to use with Enumerable objects (implementing `each`). # Most of the initializer methods and binary operators accept generic # Enumerable objects besides sets and arrays. An Enumerable object -# can be converted to Set using the +to_set+ method. +# can be converted to Set using the `to_set` method. # # Set uses Hash as storage, so you must note the following points: # @@ -45,27 +38,186 @@ # * When a string is to be stored, a frozen copy of the string is # stored instead unless the original string is already frozen. # -# == Comparison -# -# The comparison operators <, >, <=, and >= are implemented as -# shorthand for the {proper_,}{subset?,superset?} methods. However, -# the <=> operator is intentionally left out because not every pair of -# sets is comparable ({x, y} vs. {x, z} for example). -# -# == Example -# -# require 'set' -# s1 = Set[1, 2] #=> # -# s2 = [1, 2].to_set #=> # -# s1 == s2 #=> true -# s1.add("foo") #=> # -# s1.merge([2, 6]) #=> # -# s1.subset?(s2) #=> false -# s2.subset?(s1) #=> true -# -# == Contact -# -# - Akinori MUSHA (current maintainer) +# ## Comparison +# +# The comparison operators `<`, `>`, `<=`, and `>=` are implemented as +# shorthand for the {proper_,}{subset?,superset?} methods. The `<=>` +# operator reflects this order, or return `nil` for sets that both +# have distinct elements (`{x, y}` vs. `{x, z}` for example). +# +# ## Example +# +# ```ruby +# require 'set' +# s1 = Set[1, 2] #=> # +# s2 = [1, 2].to_set #=> # +# s1 == s2 #=> true +# s1.add("foo") #=> # +# s1.merge([2, 6]) #=> # +# s1.subset?(s2) #=> false +# s2.subset?(s1) #=> true +# ``` +# +# ## Contact +# +# - Akinori MUSHA <> (current maintainer) +# +# ## What's Here +# +# First, what's elsewhere. \Class \Set: +# +# - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-Object-label-What-27s+Here]. +# - Includes {module Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-What-27s+Here], +# which provides dozens of additional methods. +# +# In particular, class \Set does not have many methods of its own +# for fetching or for iterating. +# Instead, it relies on those in \Enumerable. +# +# Here, class \Set provides methods that are useful for: +# +# - [Creating a Set](#class-Set-label-Methods+for+Creating+a+Set) +# - [Set Operations](#class-Set-label-Methods+for+Set+Operations) +# - [Comparing](#class-Set-label-Methods+for+Comparing) +# - [Querying](#class-Set-label-Methods+for+Querying) +# - [Assigning](#class-Set-label-Methods+for+Assigning) +# - [Deleting](#class-Set-label-Methods+for+Deleting) +# - [Converting](#class-Set-label-Methods+for+Converting) +# - [Iterating](#class-Set-label-Methods+for+Iterating) +# - [And more....](#class-Set-label-Other+Methods) +# +# ### Methods for Creating a \Set +# +# - ::[] - +# Returns a new set containing the given objects. +# - ::new - +# Returns a new set containing either the given objects +# (if no block given) or the return values from the called block +# (if a block given). +# +# ### Methods for \Set Operations +# +# - [|](#method-i-7C) (aliased as #union and #+) - +# Returns a new set containing all elements from +self+ +# and all elements from a given enumerable (no duplicates). +# - [&](#method-i-26) (aliased as #intersection) - +# Returns a new set containing all elements common to +self+ +# and a given enumerable. +# - [-](#method-i-2D) (aliased as #difference) - +# Returns a copy of +self+ with all elements +# in a given enumerable removed. +# - [\^](#method-i-5E) - +# Returns a new set containing all elements from +self+ +# and a given enumerable except those common to both. +# +# ### Methods for Comparing +# +# - [<=>](#method-i-3C-3D-3E) - +# Returns -1, 0, or 1 as +self+ is less than, equal to, +# or greater than a given object. +# - [==](#method-i-3D-3D) - +# Returns whether +self+ and a given enumerable are equal, +# as determined by Object#eql?. +# - \#compare_by_identity? - +# Returns whether the set considers only identity +# when comparing elements. +# +# ### Methods for Querying +# +# - \#length (aliased as #size) - +# Returns the count of elements. +# - \#empty? - +# Returns whether the set has no elements. +# - \#include? (aliased as #member? and #===) - +# Returns whether a given object is an element in the set. +# - \#subset? (aliased as [<=](#method-i-3C-3D)) - +# Returns whether a given object is a subset of the set. +# - \#proper_subset? (aliased as [<](#method-i-3C)) - +# Returns whether a given enumerable is a proper subset of the set. +# - \#superset? (aliased as [<=](#method-i-3E-3D])) - +# Returns whether a given enumerable is a superset of the set. +# - \#proper_superset? (aliased as [>](#method-i-3E)) - +# Returns whether a given enumerable is a proper superset of the set. +# - \#disjoint? - +# Returns +true+ if the set and a given enumerable +# have no common elements, +false+ otherwise. +# - \#intersect? - +# Returns +true+ if the set and a given enumerable - +# have any common elements, +false+ otherwise. +# - \#compare_by_identity? - +# Returns whether the set considers only identity +# when comparing elements. +# +# ### Methods for Assigning +# +# - \#add (aliased as #<<) - +# Adds a given object to the set; returns +self+. +# - \#add? - +# If the given object is not an element in the set, +# adds it and returns +self+; otherwise, returns +nil+. +# - \#merge - +# Adds each given object to the set; returns +self+. +# - \#replace - +# Replaces the contents of the set with the contents +# of a given enumerable. +# +# ### Methods for Deleting +# +# - \#clear - +# Removes all elements in the set; returns +self+. +# - \#delete - +# Removes a given object from the set; returns +self+. +# - \#delete? - +# If the given object is an element in the set, +# removes it and returns +self+; otherwise, returns +nil+. +# - \#subtract - +# Removes each given object from the set; returns +self+. +# - \#delete_if - Removes elements specified by a given block. +# - \#select! (aliased as #filter!) - +# Removes elements not specified by a given block. +# - \#keep_if - +# Removes elements not specified by a given block. +# - \#reject! +# Removes elements specified by a given block. +# +# ### Methods for Converting +# +# - \#classify - +# Returns a hash that classifies the elements, +# as determined by the given block. +# - \#collect! (aliased as #map!) - +# Replaces each element with a block return-value. +# - \#divide - +# Returns a hash that classifies the elements, +# as determined by the given block; +# differs from #classify in that the block may accept +# either one or two arguments. +# - \#flatten - +# Returns a new set that is a recursive flattening of +self+. +# \#flatten! - +# Replaces each nested set in +self+ with the elements from that set. +# - \#inspect (aliased as #to_s) - +# Returns a string displaying the elements. +# - \#join - +# Returns a string containing all elements, converted to strings +# as needed, and joined by the given record separator. +# - \#to_a - +# Returns an array containing all set elements. +# - \#to_set - +# Returns +self+ if given no arguments and no block; +# with a block given, returns a new set consisting of block +# return values. +# +# ### Methods for Iterating +# +# - \#each - +# Calls the block with each successive element; returns +self+. +# +# ### Other Methods +# +# - \#reset - +# Resets the internal state; useful if an object +# has been modified while an element in the set. # class Set include Enumerable @@ -136,10 +288,18 @@ def initialize_dup(orig) @hash = orig.instance_variable_get(:@hash).dup end - # Clone internal hash. - def initialize_clone(orig) - super - @hash = orig.instance_variable_get(:@hash).clone + if Kernel.instance_method(:initialize_clone).arity != 1 + # Clone internal hash. + def initialize_clone(orig, **options) + super + @hash = orig.instance_variable_get(:@hash).clone(**options) + end + else + # Clone internal hash. + def initialize_clone(orig) + super + @hash = orig.instance_variable_get(:@hash).clone + end end def freeze # :nodoc: @@ -194,9 +354,9 @@ def to_a end # Returns self if no arguments are given. Otherwise, converts the - # set to another with klass.new(self, *args, &block). + # set to another with `klass.new(self, *args, &block)`. # - # In subclasses, returns klass.new(self, *args, &block) unless + # In subclasses, returns `klass.new(self, *args, &block)` unless # overridden. def to_set(klass = Set, *args, &block) return self if instance_of?(Set) && klass == Set && block.nil? && args.empty? @@ -297,25 +457,48 @@ def proper_subset?(set) end alias < proper_subset? - # Returns true if the set and the given set have at least one + # Returns 0 if the set are equal, + # -1 / +1 if the set is a proper subset / superset of the given set, + # or nil if they both have unique elements. + def <=>(set) + return unless set.is_a?(Set) + + case size <=> set.size + when -1 then -1 if proper_subset?(set) + when +1 then +1 if proper_superset?(set) + else 0 if self.==(set) + end + end + + # Returns true if the set and the given enumerable have at least one # element in common. # - # Set[1, 2, 3].intersect? Set[4, 5] #=> false - # Set[1, 2, 3].intersect? Set[3, 4] #=> true + # Set[1, 2, 3].intersect? Set[4, 5] #=> false + # Set[1, 2, 3].intersect? Set[3, 4] #=> true + # Set[1, 2, 3].intersect? 4..5 #=> false + # Set[1, 2, 3].intersect? [3, 4] #=> true def intersect?(set) - set.is_a?(Set) or raise ArgumentError, "value must be a set" - if size < set.size - any? { |o| set.include?(o) } - else + case set + when Set + if size < set.size + any? { |o| set.include?(o) } + else + set.any? { |o| include?(o) } + end + when Enumerable set.any? { |o| include?(o) } + else + raise ArgumentError, "value must be enumerable" end end - # Returns true if the set and the given set have no element in - # common. This method is the opposite of +intersect?+. + # Returns true if the set and the given enumerable have + # no element in common. This method is the opposite of `intersect?`. # - # Set[1, 2, 3].disjoint? Set[3, 4] #=> false - # Set[1, 2, 3].disjoint? Set[4, 5] #=> true + # Set[1, 2, 3].disjoint? Set[3, 4] #=> false + # Set[1, 2, 3].disjoint? Set[4, 5] #=> true + # Set[1, 2, 3].disjoint? [3, 4] #=> false + # Set[1, 2, 3].disjoint? 4..5 #=> true def disjoint?(set) !intersect?(set) end @@ -329,7 +512,7 @@ def each(&block) self end - # Adds the given object to the set and returns self. Use +merge+ to + # Adds the given object to the set and returns self. Use `merge` to # add many elements at once. # # Set[1, 2].add(3) #=> # @@ -351,8 +534,8 @@ def add?(o) add(o) unless include?(o) end - # Deletes the given object from the set and returns self. Use +subtract+ to - # delete many items at once. + # Deletes the given object from the set and returns self. Use + # `subtract` to delete many items at once. def delete(o) @hash.delete(o) self @@ -386,7 +569,7 @@ def keep_if self end - # Replaces the elements with ones returned by collect(). + # Replaces the elements with ones returned by `collect()`. # Returns an enumerator if no block is given. def collect! block_given? or return enum_for(__method__) { size } @@ -464,14 +647,22 @@ def -(enum) # Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> # def &(enum) n = self.class.new - do_with_enum(enum) { |o| n.add(o) if include?(o) } + if enum.is_a?(Set) + if enum.size > size + each { |o| n.add(o) if enum.include?(o) } + else + enum.each { |o| n.add(o) if include?(o) } + end + else + do_with_enum(enum) { |o| n.add(o) if include?(o) } + end n end alias intersection & # Returns a new set containing elements exclusive between the set - # and the given enumerable object. (set ^ enum) is equivalent to - # ((set | enum) - (set & enum)). + # and the given enumerable object. `(set ^ enum)` is equivalent to + # `((set | enum) - (set & enum))`. # # Set[1, 2] ^ Set[2, 3] #=> # # Set[1, 'b', 'c'] ^ ['b', 'd'] #=> # @@ -527,20 +718,20 @@ def reset # # Used in case statements: # - # require 'set' + # require 'set' # - # case :apple - # when Set[:potato, :carrot] - # "vegetable" - # when Set[:apple, :banana] - # "fruit" - # end - # # => "fruit" + # case :apple + # when Set[:potato, :carrot] + # "vegetable" + # when Set[:apple, :banana] + # "fruit" + # end + # # => "fruit" # # Or by itself: # - # Set[1, 2, 3] === 2 #=> true - # Set[1, 2, 3] === 4 #=> false + # Set[1, 2, 3] === 2 #=> true + # Set[1, 2, 3] === 4 #=> false # alias === include? @@ -549,12 +740,12 @@ def reset # called once for each element of the set, passing the element as # parameter. # - # require 'set' - # files = Set.new(Dir.glob("*.rb")) - # hash = files.classify { |f| File.mtime(f).year } - # hash #=> {2000=>#, - # # 2001=>#, - # # 2002=>#} + # require 'set' + # files = Set.new(Dir.glob("*.rb")) + # hash = files.classify { |f| File.mtime(f).year } + # hash #=> {2000=>#, + # # 2001=>#, + # # 2002=>#} # # Returns an enumerator if no block is given. def classify # :yields: o @@ -576,13 +767,13 @@ def classify # :yields: o # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are # in common if block.call(o1) == block.call(o2). # - # require 'set' - # numbers = Set[1, 3, 4, 6, 9, 10, 11] - # set = numbers.divide { |i,j| (i - j).abs == 1 } - # set #=> #, - # # #, - # # #, - # # #}> + # require 'set' + # numbers = Set[1, 3, 4, 6, 9, 10, 11] + # set = numbers.divide { |i,j| (i - j).abs == 1 } + # set #=> #, + # # #, + # # #, + # # #}> # # Returns an enumerator if no block is given. def divide(&func) @@ -615,6 +806,12 @@ def tsort_each_child(node, &block) end end + # Returns a string created by converting each element of the set to a string + # See also: Array#join + def join(separator=nil) + to_a.join(separator) + end + InspectKey = :__inspect_key__ # :nodoc: # Returns a string containing a human-readable representation of the @@ -637,13 +834,14 @@ def inspect alias to_s inspect def pretty_print(pp) # :nodoc: - pp.text sprintf('#<%s: {', self.class.name) - pp.nest(1) { - pp.seplist(self) { |o| - pp.pp o + pp.group(1, sprintf('#<%s:', self.class.name), '>') { + pp.breakable + pp.group(1, '{', '}') { + pp.seplist(self) { |o| + pp.pp o + } } } - pp.text "}>" end def pretty_print_cycle(pp) # :nodoc: @@ -651,252 +849,12 @@ def pretty_print_cycle(pp) # :nodoc: end end -# -# SortedSet implements a Set that guarantees that its elements are -# yielded in sorted order (according to the return values of their -# #<=> methods) when iterating over them. -# -# All elements that are added to a SortedSet must respond to the <=> -# method for comparison. -# -# Also, all elements must be mutually comparable: el1 <=> -# el2 must not return nil for any elements el1 -# and el2, else an ArgumentError will be raised when -# iterating over the SortedSet. -# -# == Example -# -# require "set" -# -# set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3]) -# ary = [] -# -# set.each do |obj| -# ary << obj -# end -# -# p ary # => [1, 2, 3, 4, 5, 6] -# -# set2 = SortedSet.new([1, 2, "3"]) -# set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed -# -class SortedSet < Set - @@setup = false - @@mutex = Mutex.new - - class << self - def [](*ary) # :nodoc: - new(ary) - end - - def setup # :nodoc: - @@setup and return - - @@mutex.synchronize do - # a hack to shut up warning - alias_method :old_init, :initialize - - begin - require 'rbtree' - - module_eval <<-END, __FILE__, __LINE__+1 - def initialize(*args) - @hash = RBTree.new - super - end - - def add(o) - o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" - super - end - alias << add - END - rescue LoadError - module_eval <<-END, __FILE__, __LINE__+1 - def initialize(*args) - @keys = nil - super - end - - def clear - @keys = nil - super - end - - def replace(enum) - @keys = nil - super - end - - def add(o) - o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" - @keys = nil - super - end - alias << add - - def delete(o) - @keys = nil - @hash.delete(o) - self - end - - def delete_if - block_given? or return enum_for(__method__) { size } - n = @hash.size - super - @keys = nil if @hash.size != n - self - end - - def keep_if - block_given? or return enum_for(__method__) { size } - n = @hash.size - super - @keys = nil if @hash.size != n - self - end - - def merge(enum) - @keys = nil - super - end - - def each(&block) - block or return enum_for(__method__) { size } - to_a.each(&block) - self - end - - def to_a - (@keys = @hash.keys).sort! unless @keys - @keys - end - - def freeze - to_a - super - end - - def rehash - @keys = nil - super - end - END - end - # a hack to shut up warning - remove_method :old_init - - @@setup = true - end - end - end - - def initialize(*args, &block) # :nodoc: - SortedSet.setup - @keys = nil - super - end -end - module Enumerable # Makes a set from the enumerable object with given arguments. - # Needs to +require "set"+ to use this method. + # Needs to `require "set"` to use this method. def to_set(klass = Set, *args, &block) klass.new(self, *args, &block) end end -# =begin -# == RestricedSet class -# RestricedSet implements a set with restrictions defined by a given -# block. -# -# === Super class -# Set -# -# === Class Methods -# --- RestricedSet::new(enum = nil) { |o| ... } -# --- RestricedSet::new(enum = nil) { |rset, o| ... } -# Creates a new restricted set containing the elements of the given -# enumerable object. Restrictions are defined by the given block. -# -# If the block's arity is 2, it is called with the RestrictedSet -# itself and an object to see if the object is allowed to be put in -# the set. -# -# Otherwise, the block is called with an object to see if the object -# is allowed to be put in the set. -# -# === Instance Methods -# --- restriction_proc -# Returns the restriction procedure of the set. -# -# =end -# -# class RestricedSet < Set -# def initialize(*args, &block) -# @proc = block or raise ArgumentError, "missing a block" -# -# if @proc.arity == 2 -# instance_eval %{ -# def add(o) -# @hash[o] = true if @proc.call(self, o) -# self -# end -# alias << add -# -# def add?(o) -# if include?(o) || !@proc.call(self, o) -# nil -# else -# @hash[o] = true -# self -# end -# end -# -# def replace(enum) -# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" -# clear -# enum.each_entry { |o| add(o) } -# -# self -# end -# -# def merge(enum) -# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" -# enum.each_entry { |o| add(o) } -# -# self -# end -# } -# else -# instance_eval %{ -# def add(o) -# if @proc.call(o) -# @hash[o] = true -# end -# self -# end -# alias << add -# -# def add?(o) -# if include?(o) || !@proc.call(o) -# nil -# else -# @hash[o] = true -# self -# end -# end -# } -# end -# -# super(*args) -# end -# -# def restriction_proc -# @proc -# end -# end - -# Tests have been moved to test/test_set.rb. +autoload :SortedSet, "#{__dir__}/set/sorted_set" diff --git a/ruby/lib/set/set.gemspec b/ruby/lib/set/set.gemspec new file mode 100644 index 000000000..83100df78 --- /dev/null +++ b/ruby/lib/set/set.gemspec @@ -0,0 +1,23 @@ +Gem::Specification.new do |spec| + spec.name = "set" + spec.version = "1.0.2" + spec.authors = ["Akinori MUSHA"] + spec.email = ["knu@idaemons.org"] + + spec.summary = %q{Provides a class to deal with collections of unordered, unique values} + spec.description = %q{Provides a class to deal with collections of unordered, unique values} + spec.homepage = "https://github.com/ruby/set" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = "https://github.com/ruby/set/blob/v#{spec.version}/CHANGELOG.md" + + # 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.require_paths = ["lib"] +end diff --git a/ruby/lib/set/sorted_set.rb b/ruby/lib/set/sorted_set.rb new file mode 100644 index 000000000..bc07bc1fb --- /dev/null +++ b/ruby/lib/set/sorted_set.rb @@ -0,0 +1,6 @@ +begin + require 'sorted_set' +rescue ::LoadError + raise "The `SortedSet` class has been extracted from the `set` library. " \ + "You must use the `sorted_set` gem or other alternatives." +end diff --git a/ruby/lib/shellwords.gemspec b/ruby/lib/shellwords.gemspec new file mode 100644 index 000000000..8ae87b230 --- /dev/null +++ b/ruby/lib/shellwords.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "shellwords" + spec.version = "0.1.0" + spec.authors = ["Akinori MUSHA"] + spec.email = ["knu@idaemons.org"] + + spec.summary = %q{Manipulates strings with word parsing rules of UNIX Bourne shell.} + spec.description = %q{Manipulates strings with word parsing rules of UNIX Bourne shell.} + spec.homepage = "https://github.com/ruby/shellwords" + 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 + + 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/ruby/lib/shellwords.rb b/ruby/lib/shellwords.rb index 1eaddce7b..4368a53ea 100644 --- a/ruby/lib/shellwords.rb +++ b/ruby/lib/shellwords.rb @@ -24,28 +24,37 @@ # argv = "see how they run".shellsplit # argv #=> ["see", "how", "they", "run"] # -# Be careful you don't leave a quote unmatched. +# They treat quotes as special characters, so an unmatched quote will +# cause an ArgumentError. # # argv = "they all ran after the farmer's wife".shellsplit -# #=> ArgumentError: Unmatched double quote: ... +# #=> ArgumentError: Unmatched quote: ... # -# In this case, you might want to use Shellwords.escape, or its alias -# String#shellescape. +# Shellwords also provides methods that do the opposite. +# Shellwords.escape, or its alias, String#shellescape, escapes +# shell metacharacters in a string for use in a command line. # -# This method will escape the String for you to safely use with a Bourne shell. +# filename = "special's.txt" # -# argv = Shellwords.escape("special's.txt") -# argv #=> "special\\'s.txt" -# system("cat " + argv) +# system("cat -- #{filename.shellescape}") +# # runs "cat -- special\\'s.txt" +# +# Note the '--'. Without it, cat(1) will treat the following argument +# as a command line option if it starts with '-'. It is guaranteed +# that Shellwords.escape converts a string to a form that a Bourne +# shell will parse back to the original string, but it is the +# programmer's responsibility to make sure that passing an arbitrary +# argument to a command does no harm. # # Shellwords also comes with a core extension for Array, Array#shelljoin. # -# argv = %w{ls -lta lib} -# system(argv.shelljoin) +# dir = "Funny GIFs" +# argv = %W[ls -lta -- #{dir}] +# system(argv.shelljoin + " | less") +# # runs "ls -lta -- Funny\\ GIFs | less" # -# You can use this method to create an escaped string out of an array of tokens -# separated by a space. In this example we used the literal shortcut for -# Array.new. +# You can use this method to build a complete command line out of an +# array of arguments. # # === Authors # * Wakou Aoyama @@ -81,7 +90,7 @@ def shellsplit(line) field = String.new line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do |word, sq, dq, esc, garbage, sep| - raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage + raise ArgumentError, "Unmatched quote: #{line.inspect}" if garbage # 2.2.3 Double-Quotes: # # The shall retain its special meaning as an @@ -123,7 +132,7 @@ class << self # # # Search files in lib for method definitions # pattern = "^[ \t]*def " - # open("| grep -Ern #{pattern.shellescape} lib") { |grep| + # open("| grep -Ern -e #{pattern.shellescape} lib") { |grep| # grep.each_line { |line| # file, lineno, matched_line = line.split(':', 3) # # ... diff --git a/ruby/lib/singleton.rb b/ruby/lib/singleton.rb index 8e8a779a2..07420d2ea 100644 --- a/ruby/lib/singleton.rb +++ b/ruby/lib/singleton.rb @@ -13,7 +13,7 @@ # # This ensures that only one instance of Klass can be created. # -# a,b = Klass.instance, Klass.instance +# a,b = Klass.instance, Klass.instance # # a == b # # => true @@ -92,6 +92,8 @@ # p a.strip # => nil # module Singleton + VERSION = "0.1.1" + # Raises a TypeError to prevent cloning. def clone raise TypeError, "can't clone instance of singleton #{self.class}" diff --git a/ruby/lib/singleton/singleton.gemspec b/ruby/lib/singleton/singleton.gemspec index c6a273a83..88d3111b6 100644 --- a/ruby/lib/singleton/singleton.gemspec +++ b/ruby/lib/singleton/singleton.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/singleton/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "singleton" - spec.version = Singleton::VERSION + spec.name = name + spec.version = version spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{The Singleton module implements the Singleton pattern.} spec.description = spec.summary spec.homepage = "https://github.com/ruby/singleton" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/lib/singleton/version.rb b/ruby/lib/singleton/version.rb deleted file mode 100644 index 01ab1eb5f..000000000 --- a/ruby/lib/singleton/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Singleton - VERSION = "0.1.0" -end diff --git a/ruby/lib/tempfile.gemspec b/ruby/lib/tempfile.gemspec new file mode 100644 index 000000000..c4f28b2ef --- /dev/null +++ b/ruby/lib/tempfile.gemspec @@ -0,0 +1,24 @@ +Gem::Specification.new do |spec| + spec.name = "tempfile" + spec.version = "0.1.2" + spec.authors = ["Yukihiro Matsumoto"] + spec.email = ["matz@ruby-lang.org"] + + spec.summary = %q{A utility class for managing temporary files.} + spec.description = %q{A utility class for managing temporary files.} + spec.homepage = "https://github.com/ruby/tempfile" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") + + 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>/dev/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/ruby/lib/tempfile.rb b/ruby/lib/tempfile.rb index efb0b1bcd..c1b696c4c 100644 --- a/ruby/lib/tempfile.rb +++ b/ruby/lib/tempfile.rb @@ -36,9 +36,9 @@ # # When a Tempfile object is garbage collected, or when the Ruby interpreter # exits, its associated temporary file is automatically deleted. This means -# that's it's unnecessary to explicitly delete a Tempfile after use, though -# it's good practice to do so: not explicitly deleting unused Tempfiles can -# potentially leave behind large amounts of tempfiles on the filesystem +# that it's unnecessary to explicitly delete a Tempfile after use, though +# it's a good practice to do so: not explicitly deleting unused Tempfiles can +# potentially leave behind a large number of temp files on the filesystem # until they're garbage collected. The existence of these temp files can make # it harder to determine a new Tempfile filename. # @@ -53,6 +53,14 @@ # file.unlink # deletes the temp file # end # +# Tempfile.create { ... } exists for this purpose and is more convenient to use. +# Note that Tempfile.create returns a File instance instead of a Tempfile, which +# also avoids the overhead and complications of delegation. +# +# Tempfile.open('foo') do |file| +# # ...do something with file... +# end +# # === Unlink after creation # # On POSIX systems, it's possible to unlink a file right after creating it, @@ -82,6 +90,10 @@ class Tempfile < DelegateClass(File) # Creates a temporary file with permissions 0600 (= only readable and # writable by the owner) and opens it with mode "w+". # + # It is recommended to use Tempfile.create { ... } instead when possible, + # because that method avoids the cost of delegation and does not rely on a + # finalizer to close and unlink the file, which is unreliable. + # # The +basename+ parameter is used to determine the name of the # temporary file. You can either pass a String or an Array with # 2 String elements. In the former form, the temporary file's base @@ -263,11 +275,25 @@ class << self # Creates a new Tempfile. # + # This method is not recommended and exists mostly for backward compatibility. + # Please use Tempfile.create instead, which avoids the cost of delegation, + # does not rely on a finalizer, and also unlinks the file when given a block. + # + # Tempfile.open is still appropriate if you need the Tempfile to be unlinked + # by a finalizer and you cannot explicitly know where in the program the + # Tempfile can be unlinked safely. + # # If no block is given, this is a synonym for Tempfile.new. # # If a block is given, then a Tempfile object will be constructed, - # and the block is run with said object as argument. The Tempfile + # and the block is run with the Tempfile object as argument. The Tempfile # object will be automatically closed after the block terminates. + # However, the file will *not* be unlinked and needs to be manually unlinked + # with Tempfile#close! or Tempfile#unlink. The finalizer will try to unlink + # but should not be relied upon as it can keep the file on the disk much + # longer than intended. For instance, on CRuby, finalizers can be delayed + # due to conservative stack scanning and references left in unused memory. + # # The call returns the value of the block. # # In any case, all arguments (*args) will be passed to Tempfile.new. @@ -299,22 +325,22 @@ def open(*args, **kw) end end -# Creates a temporary file as usual File object (not Tempfile). -# It doesn't use finalizer and delegation. +# Creates a temporary file as a usual File object (not a Tempfile). +# It does not use finalizer and delegation, which makes it more efficient and reliable. # # If no block is given, this is similar to Tempfile.new except -# creating File instead of Tempfile. -# The created file is not removed automatically. -# You should use File.unlink to remove it. +# creating File instead of Tempfile. In that case, the created file is +# not removed automatically. You should use File.unlink to remove it. # # If a block is given, then a File object will be constructed, # and the block is invoked with the object as the argument. # The File object will be automatically closed and -# the temporary file is removed after the block terminates. +# the temporary file is removed after the block terminates, +# releasing all resources that the block created. # The call returns the value of the block. # # In any case, all arguments (+basename+, +tmpdir+, +mode+, and -# **options) will be treated as Tempfile.new. +# **options) will be treated the same as for Tempfile.new. # # Tempfile.create('foo', '/home/temp') do |f| # # ... do something with f ... diff --git a/ruby/lib/time.gemspec b/ruby/lib/time.gemspec new file mode 100644 index 000000000..72fba3420 --- /dev/null +++ b/ruby/lib/time.gemspec @@ -0,0 +1,24 @@ +Gem::Specification.new do |spec| + spec.name = "time" + spec.version = "0.2.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Extends the Time class with methods for parsing and conversion.} + spec.description = %q{Extends the Time class with methods for parsing and conversion.} + spec.homepage = "https://github.com/ruby/time" + 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 + + 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.add_dependency "date" +end diff --git a/ruby/lib/time.rb b/ruby/lib/time.rb index f27bacde6..bd20a1a8e 100644 --- a/ruby/lib/time.rb +++ b/ruby/lib/time.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# shareable_constant_value: literal require 'date' @@ -92,6 +93,7 @@ def zone_offset(zone, year=self.now.year) off end + # :stopdoc: def zone_utc?(zone) # * +0000 # In RFC 2822, +0000 indicate a time zone at Universal Time. @@ -267,11 +269,17 @@ def make_time(date, year, yday, mon, day, hour, min, sec, sec_fraction, zone, no end end private :make_time + # :startdoc: # # Takes a string representation of a Time and attempts to parse it # using a heuristic. # + # This method **does not** function as a validator. If the input + # string does not match valid formats strictly, you may get a + # cryptic result. Should consider to use `Time.strptime` instead + # of this method as possible. + # # require 'time' # # Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500 @@ -590,12 +598,12 @@ def httpdate(date) end # - # Parses +date+ as a dateTime defined by the XML Schema and converts it to + # Parses +time+ as a dateTime defined by the XML Schema and converts it to # a Time object. The format is a restricted version of the format defined # by ISO 8601. # - # ArgumentError is raised if +date+ is not compliant with the format or if - # the Time class cannot represent specified date. + # ArgumentError is raised if +time+ is not compliant with the format or if + # the Time class cannot represent the specified time. # # See #xmlschema for more information on this format. # @@ -606,14 +614,14 @@ def httpdate(date) # # You must require 'time' to use this method. # - def xmlschema(date) + def xmlschema(time) if /\A\s* (-?\d+)-(\d\d)-(\d\d) T (\d\d):(\d\d):(\d\d) (\.\d+)? (Z|[+-]\d\d(?::?\d\d)?)? - \s*\z/ix =~ date + \s*\z/ix =~ time year = $1.to_i mon = $2.to_i day = $3.to_i @@ -636,7 +644,7 @@ def xmlschema(date) self.local(year, mon, day, hour, min, sec, usec) end else - raise ArgumentError.new("invalid date: #{date.inspect}") + raise ArgumentError.new("invalid xmlschema format: #{time.inspect}") end end alias iso8601 xmlschema @@ -659,30 +667,10 @@ def xmlschema(date) # You must require 'time' to use this method. # def rfc2822 - sprintf('%s, %02d %s %0*d %02d:%02d:%02d ', - RFC2822_DAY_NAME[wday], - day, RFC2822_MONTH_NAME[mon-1], year < 0 ? 5 : 4, year, - hour, min, sec) << - if utc? - '-0000' - else - off = utc_offset - sign = off < 0 ? '-' : '+' - sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60)) - end + strftime('%a, %d %b %Y %T ') << (utc? ? '-0000' : strftime('%z')) end alias rfc822 rfc2822 - - RFC2822_DAY_NAME = [ # :nodoc: - 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' - ] - - RFC2822_MONTH_NAME = [ # :nodoc: - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' - ] - # # Returns a string which represents the time as RFC 1123 date of HTTP-date # defined by RFC 2616: @@ -699,11 +687,7 @@ def rfc2822 # You must require 'time' to use this method. # def httpdate - t = dup.utc - sprintf('%s, %02d %s %0*d %02d:%02d:%02d GMT', - RFC2822_DAY_NAME[t.wday], - t.day, RFC2822_MONTH_NAME[t.mon-1], t.year < 0 ? 5 : 4, t.year, - t.hour, t.min, t.sec) + getutc.strftime('%a, %d %b %Y %T GMT') end # diff --git a/ruby/lib/timeout.rb b/ruby/lib/timeout.rb index 62a35169a..f50e706d4 100644 --- a/ruby/lib/timeout.rb +++ b/ruby/lib/timeout.rb @@ -23,6 +23,8 @@ # Copyright:: (C) 2000 Information-technology Promotion Agency, Japan module Timeout + VERSION = "0.2.0".freeze + # Raised by Timeout.timeout when the block times out. class Error < RuntimeError attr_reader :thread @@ -30,6 +32,7 @@ class Error < RuntimeError def self.catch(*args) exc = new(*args) exc.instance_variable_set(:@thread, Thread.current) + exc.instance_variable_set(:@catch_value, exc) ::Kernel.catch(exc) {yield exc} end @@ -38,11 +41,11 @@ def exception(*) if self.thread == Thread.current bt = caller begin - throw(self, bt) + throw(@catch_value, bt) rescue UncaughtThrowError end end - self + super end end @@ -71,12 +74,21 @@ def exception(*) # ensure to prevent the handling of the exception. For that reason, this # method cannot be relied on to enforce timeouts for untrusted blocks. # + # If a scheduler is defined, it will be used to handle the timeout by invoking + # Scheduler#timeout_after. + # # Note that this is both a method of module Timeout, so you can include # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). - def timeout(sec, klass = nil, message = nil) #:yield: +sec+ + def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? + message ||= "execution expired".freeze + + if Fiber.respond_to?(:current_scheduler) && (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after) + return scheduler.timeout_after(sec, klass || Error, message, &block) + end + from = "from #{caller_locations(1, 1)[0]}" if $DEBUG e = Error bl = proc do |exception| @@ -104,6 +116,7 @@ def timeout(sec, klass = nil, message = nil) #:yield: +sec+ begin bl.call(klass) rescue klass => e + message = e.message bt = e.backtrace end else @@ -118,15 +131,3 @@ def timeout(sec, klass = nil, message = nil) #:yield: +sec+ module_function :timeout end - -def timeout(*args, &block) - warn "Object##{__method__} is deprecated, use Timeout.timeout instead.", uplevel: 1 - Timeout.timeout(*args, &block) -end - -# Another name for Timeout::Error, defined for backwards compatibility with -# earlier versions of timeout.rb. -TimeoutError = Timeout::Error -class Object - deprecate_constant :TimeoutError -end diff --git a/ruby/lib/timeout/timeout.gemspec b/ruby/lib/timeout/timeout.gemspec index 7b650bdc3..3dc37f876 100644 --- a/ruby/lib/timeout/timeout.gemspec +++ b/ruby/lib/timeout/timeout.gemspec @@ -1,19 +1,22 @@ -begin - require_relative "lib/timeout/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" +# 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 = "timeout" - spec.version = Timeout::VERSION + spec.name = name + spec.version = version spec.authors = ["Yukihiro Matsumoto"] spec.email = ["matz@ruby-lang.org"] spec.summary = %q{Auto-terminate potentially long-running operations in Ruby.} spec.description = %q{Auto-terminate potentially long-running operations in Ruby.} spec.homepage = "https://github.com/ruby/timeout" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/lib/timeout/version.rb b/ruby/lib/timeout/version.rb deleted file mode 100644 index 39fc6eec5..000000000 --- a/ruby/lib/timeout/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Timeout - VERSION = "0.1.0" -end diff --git a/ruby/lib/tmpdir.gemspec b/ruby/lib/tmpdir.gemspec new file mode 100644 index 000000000..7b7640300 --- /dev/null +++ b/ruby/lib/tmpdir.gemspec @@ -0,0 +1,26 @@ +Gem::Specification.new do |spec| + spec.name = "tmpdir" + spec.version = "0.1.2" + spec.authors = ["Yukihiro Matsumoto"] + spec.email = ["matz@ruby-lang.org"] + + spec.summary = %q{Extends the Dir class to manage the OS temporary file path.} + spec.description = %q{Extends the Dir class to manage the OS temporary file path.} + spec.homepage = "https://github.com/ruby/tmpdir" + spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") + + 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>/dev/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"] + + spec.add_dependency "fileutils" +end diff --git a/ruby/lib/tmpdir.rb b/ruby/lib/tmpdir.rb index ea1d380ef..3b6716403 100644 --- a/ruby/lib/tmpdir.rb +++ b/ruby/lib/tmpdir.rb @@ -20,14 +20,21 @@ class Dir def self.tmpdir tmp = nil - [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp', '.'].each do |dir| + ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', @@systmpdir], ['/tmp']*2, ['.']*2].each do |name, dir = ENV[name]| next if !dir dir = File.expand_path(dir) - if stat = File.stat(dir) and stat.directory? and stat.writable? and - (!stat.world_writable? or stat.sticky?) + stat = File.stat(dir) rescue next + case + when !stat.directory? + warn "#{name} is not a directory: #{dir}" + when !stat.writable? + warn "#{name} is not writable: #{dir}" + when stat.world_writable? && !stat.sticky? + warn "#{name} is world-writable: #{dir}" + else tmp = dir break - end rescue nil + end end raise ArgumentError, "could not find a temporary directory" unless tmp tmp @@ -62,7 +69,7 @@ def self.tmpdir # # Dir.mktmpdir {|dir| # # use the directory... - # open("#{dir}/foo", "w") { ... } + # open("#{dir}/foo", "w") { something using the file } # } # # If a block is not given, @@ -72,7 +79,7 @@ def self.tmpdir # dir = Dir.mktmpdir # begin # # use the directory... - # open("#{dir}/foo", "w") { ... } + # open("#{dir}/foo", "w") { something using the file } # ensure # # remove the directory. # FileUtils.remove_entry dir @@ -86,7 +93,7 @@ def self.mktmpdir(prefix_suffix=nil, *rest, **options) } if block_given? begin - yield path + yield path.dup ensure unless base stat = File.stat(File.dirname(path)) @@ -108,7 +115,15 @@ def tmpdir Dir.tmpdir end - UNUSABLE_CHARS = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR, ":"].uniq.join("").freeze + UNUSABLE_CHARS = "^,-.0-9A-Z_a-z~" + + class << (RANDOM = Random.new) + MAX = 36**6 # < 0x100000000 + def next + rand(MAX).to_s(36) + end + end + private_constant :RANDOM def create(basename, tmpdir=nil, max_try: nil, **opts) origdir = tmpdir @@ -123,7 +138,7 @@ def create(basename, tmpdir=nil, max_try: nil, **opts) suffix &&= suffix.delete(UNUSABLE_CHARS) begin t = Time.now.strftime("%Y%m%d") - path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"\ + path = "#{prefix}#{t}-#{$$}-#{RANDOM.next}"\ "#{n ? %[-#{n}] : ''}#{suffix||''}" path = File.join(tmpdir, path) yield(path, n, opts, origdir) diff --git a/ruby/lib/tracer.rb b/ruby/lib/tracer.rb deleted file mode 100644 index c1540b8d2..000000000 --- a/ruby/lib/tracer.rb +++ /dev/null @@ -1,291 +0,0 @@ -# frozen_string_literal: false -#-- -# $Release Version: 0.3$ -# $Revision: 1.12 $ - -## -# Outputs a source level execution trace of a Ruby program. -# -# It does this by registering an event handler with Kernel#set_trace_func for -# processing incoming events. It also provides methods for filtering unwanted -# trace output (see Tracer.add_filter, Tracer.on, and Tracer.off). -# -# == Example -# -# Consider the following Ruby script -# -# class A -# def square(a) -# return a*a -# end -# end -# -# a = A.new -# a.square(5) -# -# Running the above script using ruby -r tracer example.rb will -# output the following trace to STDOUT (Note you can also explicitly -# require 'tracer') -# -# #0::38:Kernel:<: - -# #0:example.rb:3::-: class A -# #0:example.rb:3::C: class A -# #0:example.rb:4::-: def square(a) -# #0:example.rb:7::E: end -# #0:example.rb:9::-: a = A.new -# #0:example.rb:10::-: a.square(5) -# #0:example.rb:4:A:>: def square(a) -# #0:example.rb:5:A:-: return a*a -# #0:example.rb:6:A:<: end -# | | | | | -# | | | | ---------------------+ event -# | | | ------------------------+ class -# | | --------------------------+ line -# | ------------------------------------+ filename -# ---------------------------------------+ thread -# -# Symbol table used for displaying incoming events: -# -# +}+:: call a C-language routine -# +{+:: return from a C-language routine -# +>+:: call a Ruby method -# +C+:: start a class or module definition -# +E+:: finish a class or module definition -# +-+:: execute code on a new line -# +^+:: raise an exception -# +<+:: return from a Ruby method -# -# == Copyright -# -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# -class Tracer - - class << self - # display additional debug information (defaults to false) - attr_accessor :verbose - alias verbose? verbose - - # output stream used to output trace (defaults to STDOUT) - attr_accessor :stdout - - # mutex lock used by tracer for displaying trace output - attr_reader :stdout_mutex - - # display process id in trace output (defaults to false) - attr_accessor :display_process_id - alias display_process_id? display_process_id - - # display thread id in trace output (defaults to true) - attr_accessor :display_thread_id - alias display_thread_id? display_thread_id - - # display C-routine calls in trace output (defaults to false) - attr_accessor :display_c_call - alias display_c_call? display_c_call - end - - Tracer::stdout = STDOUT - Tracer::verbose = false - Tracer::display_process_id = false - Tracer::display_thread_id = true - Tracer::display_c_call = false - - @stdout_mutex = Thread::Mutex.new - - # Symbol table used for displaying trace information - EVENT_SYMBOL = { - "line" => "-", - "call" => ">", - "return" => "<", - "class" => "C", - "end" => "E", - "raise" => "^", - "c-call" => "}", - "c-return" => "{", - "unknown" => "?" - } - - def initialize # :nodoc: - @threads = Hash.new - if defined? Thread.main - @threads[Thread.main.object_id] = 0 - else - @threads[Thread.current.object_id] = 0 - end - - @get_line_procs = {} - - @filters = [] - end - - def stdout # :nodoc: - Tracer.stdout - end - - def on # :nodoc: - if block_given? - on - begin - yield - ensure - off - end - else - set_trace_func method(:trace_func).to_proc - stdout.print "Trace on\n" if Tracer.verbose? - end - end - - def off # :nodoc: - set_trace_func nil - stdout.print "Trace off\n" if Tracer.verbose? - end - - def add_filter(p = nil, &b) # :nodoc: - p ||= b - @filters.push p - end - - def set_get_line_procs(file, p = nil, &b) # :nodoc: - p ||= b - @get_line_procs[file] = p - end - - def get_line(file, line) # :nodoc: - if p = @get_line_procs[file] - return p.call(line) - end - - unless list = SCRIPT_LINES__[file] - list = File.readlines(file) rescue [] - SCRIPT_LINES__[file] = list - end - - if l = list[line - 1] - l - else - "-\n" - end - end - - def get_thread_no # :nodoc: - if no = @threads[Thread.current.object_id] - no - else - @threads[Thread.current.object_id] = @threads.size - end - end - - def trace_func(event, file, line, id, binding, klass, *) # :nodoc: - return if file == __FILE__ - - for p in @filters - return unless p.call event, file, line, id, binding, klass - end - - return unless Tracer::display_c_call? or - event != "c-call" && event != "c-return" - - Tracer::stdout_mutex.synchronize do - if EVENT_SYMBOL[event] - stdout.printf("<%d>", $$) if Tracer::display_process_id? - stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id? - if line == 0 - source = "?\n" - else - source = get_line(file, line) - end - stdout.printf("%s:%d:%s:%s: %s", - file, - line, - klass || '', - EVENT_SYMBOL[event], - source) - end - end - - end - - # Reference to singleton instance of Tracer - Single = new - - ## - # Start tracing - # - # === Example - # - # Tracer.on - # # code to trace here - # Tracer.off - # - # You can also pass a block: - # - # Tracer.on { - # # trace everything in this block - # } - - def Tracer.on - if block_given? - Single.on{yield} - else - Single.on - end - end - - ## - # Disable tracing - - def Tracer.off - Single.off - end - - ## - # Register an event handler p which is called every time a line - # in +file_name+ is executed. - # - # Example: - # - # Tracer.set_get_line_procs("example.rb", lambda { |line| - # puts "line number executed is #{line}" - # }) - - def Tracer.set_get_line_procs(file_name, p = nil, &b) - p ||= b - Single.set_get_line_procs(file_name, p) - end - - ## - # Used to filter unwanted trace output - # - # Example which only outputs lines of code executed within the Kernel class: - # - # Tracer.add_filter do |event, file, line, id, binding, klass, *rest| - # "Kernel" == klass.to_s - # end - - def Tracer.add_filter(p = nil, &b) - p ||= b - Single.add_filter(p) - end -end - -# :stopdoc: -SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ - -if $0 == __FILE__ - # direct call - - $0 = ARGV[0] - ARGV.shift - Tracer.on - require $0 -else - # call Tracer.on only if required by -r command-line option - count = caller.count {|bt| %r%/rubygems/core_ext/kernel_require\.rb:% !~ bt} - if (defined?(Gem) and count == 0) or - (!defined?(Gem) and count <= 1) - Tracer.on - end -end -# :startdoc: diff --git a/ruby/lib/tracer/tracer.gemspec b/ruby/lib/tracer/tracer.gemspec deleted file mode 100644 index 9eab333f7..000000000 --- a/ruby/lib/tracer/tracer.gemspec +++ /dev/null @@ -1,23 +0,0 @@ -begin - require_relative "lib/tracer/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "tracer" - spec.version = Tracer::VERSION - spec.authors = ["Keiju ISHITSUKA"] - spec.email = ["keiju@ruby-lang.org"] - - spec.summary = %q{Outputs a source level execution trace of a Ruby program.} - spec.description = %q{Outputs a source level execution trace of a Ruby program.} - spec.homepage = "https://github.com/ruby/tracer" - spec.license = "BSD-2-Clause" - - spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/tracer.rb", "lib/tracer/version.rb", "tracer.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/ruby/lib/tracer/version.rb b/ruby/lib/tracer/version.rb deleted file mode 100644 index f1b6dcd09..000000000 --- a/ruby/lib/tracer/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class Tracer - VERSION = "0.1.0" -end diff --git a/ruby/lib/tsort.gemspec b/ruby/lib/tsort.gemspec new file mode 100644 index 000000000..4656d0b84 --- /dev/null +++ b/ruby/lib/tsort.gemspec @@ -0,0 +1,22 @@ +Gem::Specification.new do |spec| + spec.name = "tsort" + spec.version = "0.1.0" + spec.authors = ["Tanaka Akira"] + spec.email = ["akr@fsij.org"] + + spec.summary = %q{Topological sorting using Tarjan's algorithm} + spec.description = %q{Topological sorting using Tarjan's algorithm} + spec.homepage = "https://github.com/ruby/tsort" + 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 + + 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/ruby/lib/un.gemspec b/ruby/lib/un.gemspec new file mode 100644 index 000000000..de8e6ec31 --- /dev/null +++ b/ruby/lib/un.gemspec @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = "un" + spec.version = "0.2.0" + spec.authors = ["WATANABE Hirofumi"] + spec.email = ["eban@ruby-lang.org"] + + spec.summary = "Utilities to replace common UNIX commands" + spec.description = spec.summary + spec.homepage = "https://github.com/ruby/un" + 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 + + spec.files = Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) } + end + spec.bindir = "exe" + spec.executables = [] + spec.require_paths = ["lib"] +end diff --git a/ruby/lib/un.rb b/ruby/lib/un.rb index 4a15a3739..5feac9212 100644 --- a/ruby/lib/un.rb +++ b/ruby/lib/un.rb @@ -22,7 +22,8 @@ # ruby -run -e touch -- [OPTION] FILE # ruby -run -e wait_writable -- [OPTION] FILE # ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION] -# ruby -run -e httpd -- [OPTION] DocumentRoot +# ruby -run -e httpd -- [OPTION] [DocumentRoot] +# ruby -run -e colorize -- [FILE] # ruby -run -e help [COMMAND] require "fileutils" @@ -88,7 +89,7 @@ def cp options[:preserve] = true if options.delete :p dest = argv.pop argv = argv[0] if argv.size == 1 - FileUtils.send cmd, argv, dest, **options + FileUtils.__send__ cmd, argv, dest, **options end end @@ -109,7 +110,7 @@ def ln options[:force] = true if options.delete :f dest = argv.pop argv = argv[0] if argv.size == 1 - FileUtils.send cmd, argv, dest, **options + FileUtils.__send__ cmd, argv, dest, **options end end @@ -144,7 +145,7 @@ def rm cmd = "rm" cmd += "_r" if options.delete :r options[:force] = true if options.delete :f - FileUtils.send cmd, argv, **options + FileUtils.__send__ cmd, argv, **options end end @@ -161,7 +162,7 @@ def mkdir setup("p") do |argv, options| cmd = "mkdir" cmd += "_p" if options.delete :p - FileUtils.send cmd, argv, **options + FileUtils.__send__ cmd, argv, **options end end @@ -304,7 +305,7 @@ def mkmf ## # Run WEBrick HTTP server. # -# ruby -run -e httpd -- [OPTION] DocumentRoot +# ruby -run -e httpd -- [OPTION] [DocumentRoot] # # --bind-address=ADDR address to bind # --port=NUM listening port number @@ -326,7 +327,11 @@ def httpd "ServerName=NAME", "ServerSoftware=NAME", "SSLCertificate=CERT", "SSLPrivateKey=KEY") do |argv, options| - require 'webrick' + begin + require 'webrick' + rescue LoadError + abort "webrick is not found. You may need to `gem install webrick` to install webrick." + end opt = options[:RequestTimeout] and options[:RequestTimeout] = opt.to_i [:Port, :MaxClients].each do |name| opt = options[name] and (options[name] = Integer(opt)) rescue nil @@ -342,6 +347,21 @@ def httpd end options[:Port] ||= 8080 # HTTP Alternate options[:DocumentRoot] = argv.shift || '.' + s = nil + options[:StartCallback] = proc { + logger = s.logger + logger.info("To access this server, open this URL in a browser:") + s.listeners.each do |listener| + if options[:SSLEnable] + addr = listener.addr + addr[3] = "127.0.0.1" if addr[3] == "0.0.0.0" + addr[3] = "::1" if addr[3] == "::" + logger.info(" https://#{Addrinfo.new(addr).inspect_sockaddr}") + else + logger.info(" http://#{listener.connect_address.inspect_sockaddr}") + end + end + } s = WEBrick::HTTPServer.new(options) shut = proc {s.shutdown} siglist = %w"TERM QUIT" @@ -354,6 +374,29 @@ def httpd end end +## +# Colorize ruby code. +# +# ruby -run -e colorize -- [FILE] +# + +def colorize + begin + require "irb/color" + rescue LoadError + raise "colorize requires irb 1.1.0 or later" + end + setup do |argv, | + if argv.empty? + puts IRB::Color.colorize_code STDIN.read + return + end + argv.each do |file| + puts IRB::Color.colorize_code File.read(file) + end + end +end + ## # Display help message. # diff --git a/ruby/lib/unicode_normalize/tables.rb b/ruby/lib/unicode_normalize/tables.rb index a36daa84e..a7a387d13 100644 --- a/ruby/lib/unicode_normalize/tables.rb +++ b/ruby/lib/unicode_normalize/tables.rb @@ -94,6 +94,7 @@ module UnicodeNormalize # :nodoc: "\u1A75-\u1A7C" \ "\u1A7F" \ "\u1AB0-\u1ABD" \ + "\u1ABF\u1AC0" \ "\u1B34\u1B35" \ "\u1B44" \ "\u1B6B-\u1B73" \ @@ -122,6 +123,7 @@ module UnicodeNormalize # :nodoc: "\uA69E\uA69F" \ "\uA6F0\uA6F1" \ "\uA806" \ + "\uA82C" \ "\uA8C4" \ "\uA8E0-\uA8F1" \ "\uA92B-\uA92D" \ @@ -146,6 +148,7 @@ module UnicodeNormalize # :nodoc: "\u{10A3F}" \ "\u{10AE5}\u{10AE6}" \ "\u{10D24}-\u{10D27}" \ + "\u{10EAB}\u{10EAC}" \ "\u{10F46}-\u{10F50}" \ "\u{11046}" \ "\u{1107F}" \ @@ -177,6 +180,9 @@ module UnicodeNormalize # :nodoc: "\u{116B6}\u{116B7}" \ "\u{1172B}" \ "\u{11839}\u{1183A}" \ + "\u{11930}" \ + "\u{1193D}\u{1193E}" \ + "\u{11943}" \ "\u{119E0}" \ "\u{11A34}" \ "\u{11A47}" \ @@ -187,6 +193,7 @@ module UnicodeNormalize # :nodoc: "\u{11D97}" \ "\u{16AF0}-\u{16AF4}" \ "\u{16B30}-\u{16B36}" \ + "\u{16FF0}\u{16FF1}" \ "\u{1BC9E}" \ "\u{1D165}-\u{1D169}" \ "\u{1D16D}-\u{1D172}" \ @@ -434,6 +441,7 @@ module UnicodeNormalize # :nodoc: "\u{114BB}\u{114BC}" \ "\u{114BE}" \ "\u{115BA}\u{115BB}" \ + "\u{11938}" \ "\u{1D15E}-\u{1D164}" \ "\u{1D1BB}-\u{1D1C0}" \ "\u{2F800}-\u{2FA1D}" \ @@ -604,6 +612,7 @@ module UnicodeNormalize # :nodoc: "\u{11347}" \ "\u{114B9}" \ "\u{115B8}\u{115B9}" \ + "\u{11935}" \ "]?#{accents}+" \ "|#{'' # precomposed Hangul syllables }" \ @@ -885,6 +894,8 @@ module UnicodeNormalize # :nodoc: "\u{114BB}\u{114BC}" \ "\u{114BE}" \ "\u{115B8}-\u{115BB}" \ + "\u{11935}" \ + "\u{11938}" \ "]?#{accents}+" \ "|#{'' # Hangul syllables with separate trailer }" \ @@ -1393,6 +1404,7 @@ module UnicodeNormalize # :nodoc: "\uA770" \ "\uA7F8\uA7F9" \ "\uAB5C-\uAB5F" \ + "\uAB69" \ "\uFB00-\uFB06" \ "\uFB13-\uFB17" \ "\uFB20-\uFB29" \ @@ -1479,6 +1491,7 @@ module UnicodeNormalize # :nodoc: "\u{1F210}-\u{1F23B}" \ "\u{1F240}-\u{1F248}" \ "\u{1F250}\u{1F251}" \ + "\u{1FBF0}-\u{1FBF9}" \ "]" class_table = { @@ -1906,6 +1919,8 @@ module UnicodeNormalize # :nodoc: "\u1ABB"=>230, "\u1ABC"=>230, "\u1ABD"=>220, + "\u1ABF"=>220, + "\u1AC0"=>220, "\u1B34"=>7, "\u1B44"=>9, "\u1B6B"=>230, @@ -2099,6 +2114,7 @@ module UnicodeNormalize # :nodoc: "\uA6F0"=>230, "\uA6F1"=>230, "\uA806"=>9, + "\uA82C"=>9, "\uA8C4"=>9, "\uA8E0"=>230, "\uA8E1"=>230, @@ -2171,6 +2187,8 @@ module UnicodeNormalize # :nodoc: "\u{10D25}"=>230, "\u{10D26}"=>230, "\u{10D27}"=>230, + "\u{10EAB}"=>230, + "\u{10EAC}"=>230, "\u{10F46}"=>220, "\u{10F47}"=>220, "\u{10F48}"=>230, @@ -2226,6 +2244,9 @@ module UnicodeNormalize # :nodoc: "\u{1172B}"=>9, "\u{11839}"=>9, "\u{1183A}"=>7, + "\u{1193D}"=>9, + "\u{1193E}"=>9, + "\u{11943}"=>7, "\u{119E0}"=>9, "\u{11A34}"=>9, "\u{11A47}"=>9, @@ -2247,6 +2268,8 @@ module UnicodeNormalize # :nodoc: "\u{16B34}"=>230, "\u{16B35}"=>230, "\u{16B36}"=>230, + "\u{16FF0}"=>6, + "\u{16FF1}"=>6, "\u{1BC9E}"=>1, "\u{1D165}"=>216, "\u{1D166}"=>216, @@ -3854,6 +3877,7 @@ module UnicodeNormalize # :nodoc: "\u{114BE}"=>"\u{114B9}\u{114BD}", "\u{115BA}"=>"\u{115B8}\u{115AF}", "\u{115BB}"=>"\u{115B9}\u{115AF}", + "\u{11938}"=>"\u{11935}\u{11930}", "\u{1D15E}"=>"\u{1D157}\u{1D165}", "\u{1D15F}"=>"\u{1D158}\u{1D165}", "\u{1D160}"=>"\u{1D158}\u{1D165}\u{1D16E}", @@ -5758,6 +5782,7 @@ module UnicodeNormalize # :nodoc: "\uAB5D"=>"\uAB37", "\uAB5E"=>"\u026B", "\uAB5F"=>"\uAB52", + "\uAB69"=>"\u028D", "\uFB00"=>"ff", "\uFB01"=>"fi", "\uFB02"=>"fl", @@ -8076,6 +8101,16 @@ module UnicodeNormalize # :nodoc: "\u{1F248}"=>"\u3014\u6557\u3015", "\u{1F250}"=>"\u5F97", "\u{1F251}"=>"\u53EF", + "\u{1FBF0}"=>"0", + "\u{1FBF1}"=>"1", + "\u{1FBF2}"=>"2", + "\u{1FBF3}"=>"3", + "\u{1FBF4}"=>"4", + "\u{1FBF5}"=>"5", + "\u{1FBF6}"=>"6", + "\u{1FBF7}"=>"7", + "\u{1FBF8}"=>"8", + "\u{1FBF9}"=>"9", "\u0385"=>" \u0308\u0301", "\u03D3"=>"\u03A5\u0301", "\u03D4"=>"\u03A5\u0308", @@ -9035,5 +9070,6 @@ module UnicodeNormalize # :nodoc: "\u{114B9}\u{114BD}"=>"\u{114BE}", "\u{115B8}\u{115AF}"=>"\u{115BA}", "\u{115B9}\u{115AF}"=>"\u{115BB}", + "\u{11935}\u{11930}"=>"\u{11938}", }.freeze end diff --git a/ruby/lib/uri.rb b/ruby/lib/uri.rb index ea8ea3e18..394c156ac 100644 --- a/ruby/lib/uri.rb +++ b/ruby/lib/uri.rb @@ -30,7 +30,7 @@ # class RSYNC < Generic # DEFAULT_PORT = 873 # end -# @@schemes['RSYNC'] = RSYNC +# register_scheme 'RSYNC', RSYNC # end # #=> URI::RSYNC # @@ -70,7 +70,6 @@ # - URI::REGEXP - (in uri/common.rb) # - URI::REGEXP::PATTERN - (in uri/common.rb) # - URI::Util - (in uri/common.rb) -# - URI::Escape - (in uri/common.rb) # - URI::Error - (in uri/common.rb) # - URI::InvalidURIError - (in uri/common.rb) # - URI::InvalidComponentError - (in uri/common.rb) @@ -86,19 +85,19 @@ # License:: # Copyright (c) 2001 akira yamada # You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # module URI end -require 'uri/version' -require 'uri/common' -require 'uri/generic' -require 'uri/file' -require 'uri/ftp' -require 'uri/http' -require 'uri/https' -require 'uri/ldap' -require 'uri/ldaps' -require 'uri/mailto' +require_relative 'uri/version' +require_relative 'uri/common' +require_relative 'uri/generic' +require_relative 'uri/file' +require_relative 'uri/ftp' +require_relative 'uri/http' +require_relative 'uri/https' +require_relative 'uri/ldap' +require_relative 'uri/ldaps' +require_relative 'uri/mailto' +require_relative 'uri/ws' diff --git a/ruby/lib/uri/common.rb b/ruby/lib/uri/common.rb index b886923c9..26b179add 100644 --- a/ruby/lib/uri/common.rb +++ b/ruby/lib/uri/common.rb @@ -3,7 +3,6 @@ # = uri/common.rb # # Author:: Akira Yamada -# Revision:: $Id$ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # @@ -17,6 +16,7 @@ module URI REGEXP = RFC2396_REGEXP Parser = RFC2396_Parser RFC3986_PARSER = RFC3986_Parser.new + Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor) # URI::Parser.new DEFAULT_PARSER = Parser.new @@ -28,6 +28,7 @@ module URI DEFAULT_PARSER.regexp.each_pair do |sym, str| const_set(sym, str) end + Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor) module Util # :nodoc: def make_components_hash(klass, array_hash) @@ -61,88 +62,41 @@ def make_components_hash(klass, array_hash) module_function :make_components_hash end - # Module for escaping unsafe characters with codes. - module Escape - # - # == Synopsis - # - # URI.escape(str [, unsafe]) - # - # == Args - # - # +str+:: - # String to replaces in. - # +unsafe+:: - # Regexp that matches all symbols that must be replaced with codes. - # By default uses UNSAFE. - # When this argument is a String, it represents a character set. - # - # == Description - # - # Escapes the string, replacing all unsafe characters with codes. - # - # This method is obsolete and should not be used. Instead, use - # CGI.escape, URI.encode_www_form or URI.encode_www_form_component - # depending on your specific use case. - # - # == Usage - # - # require 'uri' - # - # enc_uri = URI.escape("http://example.com/?a=\11\15") - # # => "http://example.com/?a=%09%0D" - # - # URI.unescape(enc_uri) - # # => "http://example.com/?a=\t\r" - # - # URI.escape("@?@!", "!?") - # # => "@%3F@%21" - # - def escape(*arg) - warn "URI.escape is obsolete", uplevel: 1 - DEFAULT_PARSER.escape(*arg) - end - alias encode escape - # - # == Synopsis - # - # URI.unescape(str) - # - # == Args - # - # +str+:: - # String to unescape. - # - # == Description - # - # This method is obsolete and should not be used. Instead, use - # CGI.unescape, URI.decode_www_form or URI.decode_www_form_component - # depending on your specific use case. - # - # == Usage - # - # require 'uri' - # - # enc_uri = URI.escape("http://example.com/?a=\11\15") - # # => "http://example.com/?a=%09%0D" - # - # URI.unescape(enc_uri) - # # => "http://example.com/?a=\t\r" - # - def unescape(*arg) - warn "URI.unescape is obsolete", uplevel: 1 - DEFAULT_PARSER.unescape(*arg) - end - alias decode unescape - end # module Escape - - extend Escape include REGEXP - @@schemes = {} + module Schemes + end + private_constant :Schemes + + def self.register_scheme(scheme, klass) + Schemes.const_set(scheme, klass) + end + # Returns a Hash of the defined schemes. def self.scheme_list - @@schemes + Schemes.constants.map { |name| + [name.to_s.upcase, Schemes.const_get(name)] + }.to_h + end + + INITIAL_SCHEMES = scheme_list + private_constant :INITIAL_SCHEMES + Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor) + + # + # Construct a URI instance, using the scheme to detect the appropriate class + # from +URI.scheme_list+. + # + def self.for(scheme, *arguments, default: Generic) + const_name = scheme.to_s.upcase + + uri_class = INITIAL_SCHEMES[const_name] + uri_class ||= if /\A[A-Z]\w*\z/.match?(const_name) && Schemes.const_defined?(const_name, false) + Schemes.const_get(const_name, false) + end + uri_class ||= default + + return uri_class.new(scheme, *arguments) end # @@ -315,7 +269,7 @@ def self.extract(str, schemes = nil, &block) # # Returns a Regexp object which matches to URI-like strings. # The Regexp object returned by this method includes arbitrary - # number of capture group (parentheses). Never rely on it's number. + # number of capture group (parentheses). Never rely on its number. # # == Usage # @@ -362,7 +316,7 @@ def self.regexp(schemes = nil) # If +enc+ is given, convert +str+ to the encoding before percent encoding. # # This is an implementation of - # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data. + # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data. # # See URI.decode_www_form_component, URI.encode_www_form. def self.encode_www_form_component(str, enc=nil) @@ -384,7 +338,7 @@ def self.encode_www_form_component(str, enc=nil) # # See URI.encode_www_form_component, URI.decode_www_form. def self.decode_www_form_component(str, enc=Encoding::UTF_8) - raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str + raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str) str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc) end @@ -403,7 +357,7 @@ def self.decode_www_form_component(str, enc=Encoding::UTF_8) # This method doesn't handle files. When you send a file, use # multipart/form-data. # - # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer + # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer # # URI.encode_www_form([["q", "ruby"], ["lang", "en"]]) # #=> "q=ruby&lang=en" @@ -716,6 +670,7 @@ def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_ "utf-16"=>"utf-16le", "utf-16le"=>"utf-16le", } # :nodoc: + Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor) # :nodoc: # return encoding or nil diff --git a/ruby/lib/uri/file.rb b/ruby/lib/uri/file.rb index 561ec703c..7671ad647 100644 --- a/ruby/lib/uri/file.rb +++ b/ruby/lib/uri/file.rb @@ -90,5 +90,5 @@ def set_password(v) end end - @@schemes['FILE'] = File + register_scheme 'FILE', File end diff --git a/ruby/lib/uri/ftp.rb b/ruby/lib/uri/ftp.rb index f57b4b7df..abad613c3 100644 --- a/ruby/lib/uri/ftp.rb +++ b/ruby/lib/uri/ftp.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -263,5 +262,6 @@ def to_s return str end end - @@schemes['FTP'] = FTP + + register_scheme 'FTP', FTP end diff --git a/ruby/lib/uri/generic.rb b/ruby/lib/uri/generic.rb index c672d15eb..cfa0de6b7 100644 --- a/ruby/lib/uri/generic.rb +++ b/ruby/lib/uri/generic.rb @@ -4,7 +4,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -644,7 +643,7 @@ def host=(v) # def hostname v = self.host - /\A\[(.*)\]\z/ =~ v ? $1 : v + v&.start_with?('[') && v.end_with?(']') ? v[1..-2] : v end # Sets the host part of the URI as the argument with brackets for IPv6 addresses. @@ -660,7 +659,7 @@ def hostname # it is wrapped with brackets. # def hostname=(v) - v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v + v = "[#{v}]" if !(v&.start_with?('[') && v&.end_with?(']')) && v&.index(':') self.host = v end @@ -1098,7 +1097,7 @@ def merge!(oth) # # => "http://my.example.com/main.rbx?page=1" # def merge(oth) - rel = parser.send(:convert_to_uri, oth) + rel = parser.__send__(:convert_to_uri, oth) if rel.absolute? #raise BadURIError, "both URI are absolute" if absolute? @@ -1183,7 +1182,7 @@ def route_from_path(src, dst) # :stopdoc: def route_from0(oth) - oth = parser.send(:convert_to_uri, oth) + oth = parser.__send__(:convert_to_uri, oth) if self.relative? raise BadURIError, "relative URI: #{self}" @@ -1291,7 +1290,7 @@ def route_from(oth) # #=> # # def route_to(oth) - parser.send(:convert_to_uri, oth).route_from(self) + parser.__send__(:convert_to_uri, oth).route_from(self) end # @@ -1405,7 +1404,7 @@ def eql?(oth) # Returns an Array of the components defined from the COMPONENT Array. def component_ary component.collect do |x| - self.send(x) + self.__send__(x) end end protected :component_ary @@ -1430,7 +1429,7 @@ def component_ary def select(*components) components.collect do |c| if component.include?(c) - self.send(c) + self.__send__(c) else raise ArgumentError, "expected of components of #{self.class} (#{self.class.component.join(', ')})" @@ -1515,9 +1514,19 @@ def find_proxy(env=ENV) proxy_uri = env["CGI_#{name.upcase}"] end elsif name == 'http_proxy' - unless proxy_uri = env[name] - if proxy_uri = env[name.upcase] - warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1 + if RUBY_ENGINE == 'jruby' && p_addr = ENV_JAVA['http.proxyHost'] + p_port = ENV_JAVA['http.proxyPort'] + if p_user = ENV_JAVA['http.proxyUser'] + p_pass = ENV_JAVA['http.proxyPass'] + proxy_uri = "http://#{p_user}:#{p_pass}@#{p_addr}:#{p_port}" + else + proxy_uri = "http://#{p_addr}:#{p_port}" + end + else + unless proxy_uri = env[name] + if proxy_uri = env[name.upcase] + warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1 + end end end else diff --git a/ruby/lib/uri/http.rb b/ruby/lib/uri/http.rb index 2e2ebcc1d..306daf196 100644 --- a/ruby/lib/uri/http.rb +++ b/ruby/lib/uri/http.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -81,8 +80,46 @@ def request_uri url = @query ? "#@path?#@query" : @path.dup url.start_with?(?/.freeze) ? url : ?/ + url end - end - @@schemes['HTTP'] = HTTP + # + # == Description + # + # Returns the authority for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2. + # + # + # Example: + # + # URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').authority #=> "www.example.com" + # URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').authority #=> "www.example.com:8000" + # URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').authority #=> "www.example.com" + # + def authority + if port == default_port + host + else + "#{host}:#{port}" + end + end + + # + # == Description + # + # Returns the origin for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc6454. + # + # + # Example: + # + # URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').origin #=> "http://www.example.com" + # URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').origin #=> "http://www.example.com:8000" + # URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').origin #=> "http://www.example.com" + # URI::HTTPS.build(host: 'www.example.com', path: '/foo/bar').origin #=> "https://www.example.com" + # + def origin + "#{scheme}://#{authority}" + end + end + register_scheme 'HTTP', HTTP end diff --git a/ruby/lib/uri/https.rb b/ruby/lib/uri/https.rb index 4780ee0a4..50a5cabaf 100644 --- a/ruby/lib/uri/https.rb +++ b/ruby/lib/uri/https.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -19,5 +18,6 @@ class HTTPS < HTTP # A Default port of 443 for URI::HTTPS DEFAULT_PORT = 443 end - @@schemes['HTTPS'] = HTTPS + + register_scheme 'HTTPS', HTTPS end diff --git a/ruby/lib/uri/ldap.rb b/ruby/lib/uri/ldap.rb index 228c793cb..4544349f1 100644 --- a/ruby/lib/uri/ldap.rb +++ b/ruby/lib/uri/ldap.rb @@ -7,7 +7,6 @@ # License:: # URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada. # You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -119,6 +118,7 @@ def initialize(*arg) # Private method to cleanup +dn+ from using the +path+ component attribute. def parse_dn + raise InvalidURIError, 'bad LDAP URL' unless @path @dn = @path[1..-1] end private :parse_dn @@ -257,5 +257,5 @@ def hierarchical? end end - @@schemes['LDAP'] = LDAP + register_scheme 'LDAP', LDAP end diff --git a/ruby/lib/uri/ldaps.rb b/ruby/lib/uri/ldaps.rb index 227e7fab3..58228f589 100644 --- a/ruby/lib/uri/ldaps.rb +++ b/ruby/lib/uri/ldaps.rb @@ -17,5 +17,6 @@ class LDAPS < LDAP # A Default port of 636 for URI::LDAPS DEFAULT_PORT = 636 end - @@schemes['LDAPS'] = LDAPS + + register_scheme 'LDAPS', LDAPS end diff --git a/ruby/lib/uri/mailto.rb b/ruby/lib/uri/mailto.rb index 9c06871c7..87cb99656 100644 --- a/ruby/lib/uri/mailto.rb +++ b/ruby/lib/uri/mailto.rb @@ -3,7 +3,6 @@ # # Author:: Akira Yamada # License:: You can redistribute it and/or modify it under the same term as Ruby. -# Revision:: $Id$ # # See URI for general documentation # @@ -290,5 +289,5 @@ def to_mailtext alias to_rfc822text to_mailtext end - @@schemes['MAILTO'] = MailTo + register_scheme 'MAILTO', MailTo end diff --git a/ruby/lib/uri/rfc2396_parser.rb b/ruby/lib/uri/rfc2396_parser.rb index 556da20aa..76a8f99fd 100644 --- a/ruby/lib/uri/rfc2396_parser.rb +++ b/ruby/lib/uri/rfc2396_parser.rb @@ -3,7 +3,6 @@ # = uri/common.rb # # Author:: Akira Yamada -# Revision:: $Id$ # License:: # You can redistribute it and/or modify it under the same term as Ruby. # @@ -117,7 +116,7 @@ def initialize(opts = {}) # See also URI::Parser.initialize_regexp. attr_reader :regexp - # Returns a split URI against regexp[:ABS_URI]. + # Returns a split URI against +regexp[:ABS_URI]+. def split(uri) case uri when '' @@ -208,21 +207,9 @@ def split(uri) # #=> # # def parse(uri) - scheme, userinfo, host, port, - registry, path, opaque, query, fragment = self.split(uri) - - if scheme && URI.scheme_list.include?(scheme.upcase) - URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - else - Generic.new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - end + URI.for(*self.split(uri), self) end - # # == Args # @@ -270,8 +257,8 @@ def extract(str, schemes = nil) end end - # Returns Regexp that is default self.regexp[:ABS_URI_REF], - # unless +schemes+ is provided. Then it is a Regexp.union with self.pattern[:X_ABS_URI]. + # Returns Regexp that is default +self.regexp[:ABS_URI_REF]+, + # unless +schemes+ is provided. Then it is a Regexp.union with +self.pattern[:X_ABS_URI]+. def make_regexp(schemes = nil) unless schemes @regexp[:ABS_URI_REF] @@ -290,7 +277,7 @@ def make_regexp(schemes = nil) # +str+:: # String to make safe # +unsafe+:: - # Regexp to apply. Defaults to self.regexp[:UNSAFE] + # Regexp to apply. Defaults to +self.regexp[:UNSAFE]+ # # == Description # @@ -322,7 +309,7 @@ def escape(str, unsafe = @regexp[:UNSAFE]) # +str+:: # String to remove escapes from # +escaped+:: - # Regexp to apply. Defaults to self.regexp[:ESCAPED] + # Regexp to apply. Defaults to +self.regexp[:ESCAPED]+ # # == Description # @@ -335,8 +322,14 @@ def unescape(str, escaped = @regexp[:ESCAPED]) end @@to_s = Kernel.instance_method(:to_s) - def inspect - @@to_s.bind_call(self) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end end private diff --git a/ruby/lib/uri/rfc3986_parser.rb b/ruby/lib/uri/rfc3986_parser.rb index 08539f069..3e07de480 100644 --- a/ruby/lib/uri/rfc3986_parser.rb +++ b/ruby/lib/uri/rfc3986_parser.rb @@ -69,18 +69,7 @@ def split(uri) #:nodoc: end def parse(uri) # :nodoc: - scheme, userinfo, host, port, - registry, path, opaque, query, fragment = self.split(uri) - scheme_list = URI.scheme_list - if scheme && scheme_list.include?(uc = scheme.upcase) - scheme_list[uc].new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - else - Generic.new(scheme, userinfo, host, port, - registry, path, opaque, query, - fragment, self) - end + URI.for(*self.split(uri), self) end @@ -90,8 +79,14 @@ def join(*uris) # :nodoc: end @@to_s = Kernel.instance_method(:to_s) - def inspect - @@to_s.bind_call(self) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end end private diff --git a/ruby/lib/uri/uri.gemspec b/ruby/lib/uri/uri.gemspec index 95cb8e2d4..584a4faa1 100644 --- a/ruby/lib/uri/uri.gemspec +++ b/ruby/lib/uri/uri.gemspec @@ -13,7 +13,9 @@ Gem::Specification.new do |spec| spec.summary = %q{URI is a module providing classes to handle Uniform Resource Identifiers} spec.description = spec.summary spec.homepage = "https://github.com/ruby/uri" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + spec.required_ruby_version = '>= 2.4' spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/lib/uri/version.rb b/ruby/lib/uri/version.rb index 4f5411339..82188e25a 100644 --- a/ruby/lib/uri/version.rb +++ b/ruby/lib/uri/version.rb @@ -1,6 +1,6 @@ module URI # :stopdoc: - VERSION_CODE = '001000'.freeze + VERSION_CODE = '001100'.freeze VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze # :startdoc: end diff --git a/ruby/lib/uri/ws.rb b/ruby/lib/uri/ws.rb new file mode 100644 index 000000000..ff3c55448 --- /dev/null +++ b/ruby/lib/uri/ws.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: false +# = uri/ws.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See URI for general documentation +# + +require_relative 'generic' + +module URI + + # + # The syntax of WS URIs is defined in RFC6455 section 3. + # + # Note that the Ruby URI library allows WS URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See . + # + class WS < Generic + # A Default port of 80 for URI::WS. + DEFAULT_PORT = 80 + + # An Array of the available components for URI::WS. + COMPONENT = %i[ + scheme + userinfo host port + path + query + ].freeze + + # + # == Description + # + # Creates a new URI::WS object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, and query. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [userinfo, host, port, path, query]. + # + # Example: + # + # uri = URI::WS.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = URI::WS.build([nil, "www.example.com", nil, "/path", "query"]) + # + # Currently, if passed userinfo components this method generates + # invalid WS URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for a WS URI, as required by Net::HTTP::Get. + # + # If the URI contains a query, the full path is URI#path + '?' + URI#query. + # Otherwise, the path is simply URI#path. + # + # Example: + # + # uri = URI::WS.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + end + + register_scheme 'WS', WS +end diff --git a/ruby/lib/uri/wss.rb b/ruby/lib/uri/wss.rb new file mode 100644 index 000000000..7cea9d773 --- /dev/null +++ b/ruby/lib/uri/wss.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: false +# = uri/wss.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See URI for general documentation +# + +require_relative 'ws' + +module URI + + # The default port for WSS URIs is 443, and the scheme is 'wss:' rather + # than 'ws:'. Other than that, WSS URIs are identical to WS URIs; + # see URI::WS. + class WSS < WS + # A Default port of 443 for URI::WSS + DEFAULT_PORT = 443 + end + + register_scheme 'WSS', WSS +end diff --git a/ruby/lib/weakref.rb b/ruby/lib/weakref.rb index 824d4016e..fbd5d8fa8 100644 --- a/ruby/lib/weakref.rb +++ b/ruby/lib/weakref.rb @@ -17,6 +17,7 @@ # class WeakRef < Delegator + VERSION = "0.1.1" ## # RefError is raised when a referenced object has been recycled by the diff --git a/ruby/lib/weakref/weakref.gemspec b/ruby/lib/weakref/weakref.gemspec new file mode 100644 index 000000000..96a976507 --- /dev/null +++ b/ruby/lib/weakref/weakref.gemspec @@ -0,0 +1,34 @@ +# 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{Allows a referenced object to be garbage-collected.} + spec.description = %q{Allows a referenced object to be garbage-collected.} + spec.homepage = "https://github.com/ruby/weakref" + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = "https://github.com/ruby/weakref" + spec.licenses = ["Ruby", "BSD-2-Clause"] + + # 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>/dev/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"] + + spec.add_dependency "delegate" +end diff --git a/ruby/lib/webrick/httpproxy.rb b/ruby/lib/webrick/httpproxy.rb deleted file mode 100644 index d05d59514..000000000 --- a/ruby/lib/webrick/httpproxy.rb +++ /dev/null @@ -1,350 +0,0 @@ -# frozen_string_literal: false -# -# httpproxy.rb -- HTTPProxy Class -# -# Author: IPR -- Internet Programming with Ruby -- writers -# Copyright (c) 2002 GOTO Kentaro -# Copyright (c) 2002 Internet Programming with Ruby writers. All rights -# reserved. -# -# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $ -# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $ - -require_relative "httpserver" -require "net/http" - -module WEBrick - - NullReader = Object.new # :nodoc: - class << NullReader # :nodoc: - def read(*args) - nil - end - alias gets read - end - - FakeProxyURI = Object.new # :nodoc: - class << FakeProxyURI # :nodoc: - def method_missing(meth, *args) - if %w(scheme host port path query userinfo).member?(meth.to_s) - return nil - end - super - end - end - - # :startdoc: - - ## - # An HTTP Proxy server which proxies GET, HEAD and POST requests. - # - # To create a simple proxy server: - # - # require 'webrick' - # require 'webrick/httpproxy' - # - # proxy = WEBrick::HTTPProxyServer.new Port: 8000 - # - # trap 'INT' do proxy.shutdown end - # trap 'TERM' do proxy.shutdown end - # - # proxy.start - # - # See ::new for proxy-specific configuration items. - # - # == Modifying proxied responses - # - # To modify content the proxy server returns use the +:ProxyContentHandler+ - # option: - # - # handler = proc do |req, res| - # if res['content-type'] == 'text/plain' then - # res.body << "\nThis content was proxied!\n" - # end - # end - # - # proxy = - # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler - - class HTTPProxyServer < HTTPServer - - ## - # Proxy server configurations. The proxy server handles the following - # configuration items in addition to those supported by HTTPServer: - # - # :ProxyAuthProc:: Called with a request and response to authorize a - # request - # :ProxyVia:: Appended to the via header - # :ProxyURI:: The proxy server's URI - # :ProxyContentHandler:: Called with a request and response and allows - # modification of the response - # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60 - # seconds for read operations - - def initialize(config={}, default=Config::HTTP) - super(config, default) - c = @config - @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}" - end - - # :stopdoc: - def service(req, res) - if req.request_method == "CONNECT" - do_CONNECT(req, res) - elsif req.unparsed_uri =~ %r!^http://! - proxy_service(req, res) - else - super(req, res) - end - end - - def proxy_auth(req, res) - if proc = @config[:ProxyAuthProc] - proc.call(req, res) - end - req.header.delete("proxy-authorization") - end - - def proxy_uri(req, res) - # should return upstream proxy server's URI - return @config[:ProxyURI] - end - - def proxy_service(req, res) - # Proxy Authentication - proxy_auth(req, res) - - begin - self.send("do_#{req.request_method}", req, res) - rescue NoMethodError - raise HTTPStatus::MethodNotAllowed, - "unsupported method `#{req.request_method}'." - rescue => err - logger.debug("#{err.class}: #{err.message}") - raise HTTPStatus::ServiceUnavailable, err.message - end - - # Process contents - if handler = @config[:ProxyContentHandler] - handler.call(req, res) - end - end - - def do_CONNECT(req, res) - # Proxy Authentication - proxy_auth(req, res) - - ua = Thread.current[:WEBrickSocket] # User-Agent - raise HTTPStatus::InternalServerError, - "[BUG] cannot get socket" unless ua - - host, port = req.unparsed_uri.split(":", 2) - # Proxy authentication for upstream proxy server - if proxy = proxy_uri(req, res) - proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0" - if proxy.userinfo - credentials = "Basic " + [proxy.userinfo].pack("m0") - end - host, port = proxy.host, proxy.port - end - - begin - @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.") - os = TCPSocket.new(host, port) # origin server - - if proxy - @logger.debug("CONNECT: sending a Request-Line") - os << proxy_request_line << CRLF - @logger.debug("CONNECT: > #{proxy_request_line}") - if credentials - @logger.debug("CONNECT: sending credentials") - os << "Proxy-Authorization: " << credentials << CRLF - end - os << CRLF - proxy_status_line = os.gets(LF) - @logger.debug("CONNECT: read Status-Line from the upstream server") - @logger.debug("CONNECT: < #{proxy_status_line}") - if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line - while line = os.gets(LF) - break if /\A(#{CRLF}|#{LF})\z/om =~ line - end - else - raise HTTPStatus::BadGateway - end - end - @logger.debug("CONNECT #{host}:#{port}: succeeded") - res.status = HTTPStatus::RC_OK - rescue => ex - @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'") - res.set_error(ex) - raise HTTPStatus::EOFError - ensure - if handler = @config[:ProxyContentHandler] - handler.call(req, res) - end - res.send_response(ua) - access_log(@config, req, res) - - # Should clear request-line not to send the response twice. - # see: HTTPServer#run - req.parse(NullReader) rescue nil - end - - begin - while fds = IO::select([ua, os]) - if fds[0].member?(ua) - buf = ua.readpartial(1024); - @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent") - os.write(buf) - elsif fds[0].member?(os) - buf = os.readpartial(1024); - @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}") - ua.write(buf) - end - end - rescue - os.close - @logger.debug("CONNECT #{host}:#{port}: closed") - end - - raise HTTPStatus::EOFError - end - - def do_GET(req, res) - perform_proxy_request(req, res, Net::HTTP::Get) - end - - def do_HEAD(req, res) - perform_proxy_request(req, res, Net::HTTP::Head) - end - - def do_POST(req, res) - perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader) - end - - def do_OPTIONS(req, res) - res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT" - end - - private - - # Some header fields should not be transferred. - HopByHop = %w( connection keep-alive proxy-authenticate upgrade - proxy-authorization te trailers transfer-encoding ) - ShouldNotTransfer = %w( set-cookie proxy-connection ) - def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end - - def choose_header(src, dst) - connections = split_field(src['connection']) - src.each{|key, value| - key = key.downcase - if HopByHop.member?(key) || # RFC2616: 13.5.1 - connections.member?(key) || # RFC2616: 14.10 - ShouldNotTransfer.member?(key) # pragmatics - @logger.debug("choose_header: `#{key}: #{value}'") - next - end - dst[key] = value - } - end - - # Net::HTTP is stupid about the multiple header fields. - # Here is workaround: - def set_cookie(src, dst) - if str = src['set-cookie'] - cookies = [] - str.split(/,\s*/).each{|token| - if /^[^=]+;/o =~ token - cookies[-1] << ", " << token - elsif /=/o =~ token - cookies << token - else - cookies[-1] << ", " << token - end - } - dst.cookies.replace(cookies) - end - end - - def set_via(h) - if @config[:ProxyVia] - if h['via'] - h['via'] << ", " << @via - else - h['via'] = @via - end - end - end - - def setup_proxy_header(req, res) - # Choose header fields to transfer - header = Hash.new - choose_header(req, header) - set_via(header) - return header - end - - def setup_upstream_proxy_authentication(req, res, header) - if upstream = proxy_uri(req, res) - if upstream.userinfo - header['proxy-authorization'] = - "Basic " + [upstream.userinfo].pack("m0") - end - return upstream - end - return FakeProxyURI - end - - def perform_proxy_request(req, res, req_class, body_stream = nil) - uri = req.request_uri - path = uri.path.dup - path << "?" << uri.query if uri.query - header = setup_proxy_header(req, res) - upstream = setup_upstream_proxy_authentication(req, res, header) - - body_tmp = [] - http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port) - req_fib = Fiber.new do - http.start do - if @config[:ProxyTimeout] - ################################## these issues are - http.open_timeout = 30 # secs # necessary (maybe because - http.read_timeout = 60 # secs # Ruby's bug, but why?) - ################################## - end - if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i - header['Transfer-Encoding'] = 'chunked' - end - http_req = req_class.new(path, header) - http_req.body_stream = body_stream if body_stream - http.request(http_req) do |response| - # Persistent connection requirements are mysterious for me. - # So I will close the connection in every response. - res['proxy-connection'] = "close" - res['connection'] = "close" - - # stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse - res.status = response.code.to_i - res.chunked = response.chunked? - choose_header(response, res) - set_cookie(response, res) - set_via(res) - response.read_body do |buf| - body_tmp << buf - Fiber.yield # wait for res.body Proc#call - end - end # http.request - end - end - req_fib.resume # read HTTP response headers and first chunk of the body - res.body = ->(socket) do - while buf = body_tmp.shift - socket.write(buf) - buf.clear - req_fib.resume # continue response.read_body - end - end - end - # :stopdoc: - end -end diff --git a/ruby/lib/webrick/server.rb b/ruby/lib/webrick/server.rb deleted file mode 100644 index 4a6e74c4f..000000000 --- a/ruby/lib/webrick/server.rb +++ /dev/null @@ -1,378 +0,0 @@ -# frozen_string_literal: false -# -# server.rb -- GenericServer Class -# -# Author: IPR -- Internet Programming with Ruby -- writers -# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou -# Copyright (c) 2002 Internet Programming with Ruby writers. All rights -# reserved. -# -# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $ - -require 'socket' -require_relative 'config' -require_relative 'log' - -module WEBrick - - ## - # Server error exception - - class ServerError < StandardError; end - - ## - # Base server class - - class SimpleServer - - ## - # A SimpleServer only yields when you start it - - def SimpleServer.start - yield - end - end - - ## - # A generic module for daemonizing a process - - class Daemon - - ## - # Performs the standard operations for daemonizing a process. Runs a - # block, if given. - - def Daemon.start - Process.daemon - File.umask(0) - yield if block_given? - end - end - - ## - # Base TCP server class. You must subclass GenericServer and provide a #run - # method. - - class GenericServer - - ## - # The server status. One of :Stop, :Running or :Shutdown - - attr_reader :status - - ## - # The server configuration - - attr_reader :config - - ## - # The server logger. This is independent from the HTTP access log. - - attr_reader :logger - - ## - # Tokens control the number of outstanding clients. The - # :MaxClients configuration sets this. - - attr_reader :tokens - - ## - # Sockets listening for connections. - - attr_reader :listeners - - ## - # Creates a new generic server from +config+. The default configuration - # comes from +default+. - - def initialize(config={}, default=Config::General) - @config = default.dup.update(config) - @status = :Stop - @config[:Logger] ||= Log::new - @logger = @config[:Logger] - - @tokens = Thread::SizedQueue.new(@config[:MaxClients]) - @config[:MaxClients].times{ @tokens.push(nil) } - - webrickv = WEBrick::VERSION - rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" - @logger.info("WEBrick #{webrickv}") - @logger.info("ruby #{rubyv}") - - @listeners = [] - @shutdown_pipe = nil - unless @config[:DoNotListen] - if @config[:Listen] - warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1) - end - listen(@config[:BindAddress], @config[:Port]) - if @config[:Port] == 0 - @config[:Port] = @listeners[0].addr[1] - end - end - end - - ## - # Retrieves +key+ from the configuration - - def [](key) - @config[key] - end - - ## - # Adds listeners from +address+ and +port+ to the server. See - # WEBrick::Utils::create_listeners for details. - - def listen(address, port) - @listeners += Utils::create_listeners(address, port) - end - - ## - # Starts the server and runs the +block+ for each connection. This method - # does not return until the server is stopped from a signal handler or - # another thread using #stop or #shutdown. - # - # If the block raises a subclass of StandardError the exception is logged - # and ignored. If an IOError or Errno::EBADF exception is raised the - # exception is ignored. If an Exception subclass is raised the exception - # is logged and re-raised which stops the server. - # - # To completely shut down a server call #shutdown from ensure: - # - # server = WEBrick::GenericServer.new - # # or WEBrick::HTTPServer.new - # - # begin - # server.start - # ensure - # server.shutdown - # end - - def start(&block) - raise ServerError, "already started." if @status != :Stop - server_type = @config[:ServerType] || SimpleServer - - setup_shutdown_pipe - - server_type.start{ - @logger.info \ - "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" - @status = :Running - call_callback(:StartCallback) - - shutdown_pipe = @shutdown_pipe - - thgroup = ThreadGroup.new - begin - while @status == :Running - begin - sp = shutdown_pipe[0] - if svrs = IO.select([sp, *@listeners]) - if svrs[0].include? sp - # swallow shutdown pipe - buf = String.new - nil while String === - sp.read_nonblock([sp.nread, 8].max, buf, exception: false) - break - end - svrs[0].each{|svr| - @tokens.pop # blocks while no token is there. - if sock = accept_client(svr) - unless config[:DoNotReverseLookup].nil? - sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup] - end - th = start_thread(sock, &block) - th[:WEBrickThread] = true - thgroup.add(th) - else - @tokens.push(nil) - end - } - end - rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex - # if the listening socket was closed in GenericServer#shutdown, - # IO::select raise it. - rescue StandardError => ex - msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" - @logger.error msg - rescue Exception => ex - @logger.fatal ex - raise - end - end - ensure - cleanup_shutdown_pipe(shutdown_pipe) - cleanup_listener - @status = :Shutdown - @logger.info "going to shutdown ..." - thgroup.list.each{|th| th.join if th[:WEBrickThread] } - call_callback(:StopCallback) - @logger.info "#{self.class}#start done." - @status = :Stop - end - } - end - - ## - # Stops the server from accepting new connections. - - def stop - if @status == :Running - @status = :Shutdown - end - - alarm_shutdown_pipe {|f| f.write_nonblock("\0")} - end - - ## - # Shuts down the server and all listening sockets. New listeners must be - # provided to restart the server. - - def shutdown - stop - - alarm_shutdown_pipe(&:close) - end - - ## - # You must subclass GenericServer and implement \#run which accepts a TCP - # client socket - - def run(sock) - @logger.fatal "run() must be provided by user." - end - - private - - # :stopdoc: - - ## - # Accepts a TCP client socket from the TCP server socket +svr+ and returns - # the client socket. - - def accept_client(svr) - case sock = svr.to_io.accept_nonblock(exception: false) - when :wait_readable - nil - else - if svr.respond_to?(:start_immediately) - sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context) - sock.sync_close = true - # we cannot do OpenSSL::SSL::SSLSocket#accept here because - # a slow client can prevent us from accepting connections - # from other clients - end - sock - end - rescue Errno::ECONNRESET, Errno::ECONNABORTED, - Errno::EPROTO, Errno::EINVAL - nil - rescue StandardError => ex - msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" - @logger.error msg - nil - end - - ## - # Starts a server thread for the client socket +sock+ that runs the given - # +block+. - # - # Sets the socket to the :WEBrickSocket thread local variable - # in the thread. - # - # If any errors occur in the block they are logged and handled. - - def start_thread(sock, &block) - Thread.start{ - begin - Thread.current[:WEBrickSocket] = sock - begin - addr = sock.peeraddr - @logger.debug "accept: #{addr[3]}:#{addr[1]}" - rescue SocketError - @logger.debug "accept:
" - raise - end - if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately] - WEBrick::Utils.timeout(@config[:RequestTimeout]) do - begin - sock.accept # OpenSSL::SSL::SSLSocket#accept - rescue Errno::ECONNRESET, Errno::ECONNABORTED, - Errno::EPROTO, Errno::EINVAL - Thread.exit - end - end - end - call_callback(:AcceptCallback, sock) - block ? block.call(sock) : run(sock) - rescue Errno::ENOTCONN - @logger.debug "Errno::ENOTCONN raised" - rescue ServerError => ex - msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" - @logger.error msg - rescue Exception => ex - @logger.error ex - ensure - @tokens.push(nil) - Thread.current[:WEBrickSocket] = nil - if addr - @logger.debug "close: #{addr[3]}:#{addr[1]}" - else - @logger.debug "close:
" - end - sock.close - end - } - end - - ## - # Calls the callback +callback_name+ from the configuration with +args+ - - def call_callback(callback_name, *args) - @config[callback_name]&.call(*args) - end - - def setup_shutdown_pipe - return @shutdown_pipe ||= IO.pipe - end - - def cleanup_shutdown_pipe(shutdown_pipe) - @shutdown_pipe = nil - shutdown_pipe&.each(&:close) - end - - def alarm_shutdown_pipe - _, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe. - if pipe - if !pipe.closed? - begin - yield pipe - rescue IOError # closed by another thread. - end - end - end - end - - def cleanup_listener - @listeners.each{|s| - if @logger.debug? - addr = s.addr - @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})") - end - begin - s.shutdown - rescue Errno::ENOTCONN - # when `Errno::ENOTCONN: Socket is not connected' on some platforms, - # call #close instead of #shutdown. - # (ignore @config[:ShutdownSocketWithoutClose]) - s.close - else - unless @config[:ShutdownSocketWithoutClose] - s.close - end - end - } - @listeners.clear - end - end # end of GenericServer -end diff --git a/ruby/lib/webrick/utils.rb b/ruby/lib/webrick/utils.rb deleted file mode 100644 index 07044876b..000000000 --- a/ruby/lib/webrick/utils.rb +++ /dev/null @@ -1,270 +0,0 @@ -# frozen_string_literal: false -# -# utils.rb -- Miscellaneous utilities -# -# Author: IPR -- Internet Programming with Ruby -- writers -# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou -# Copyright (c) 2002 Internet Programming with Ruby writers. All rights -# reserved. -# -# $IPR: utils.rb,v 1.10 2003/02/16 22:22:54 gotoyuzo Exp $ - -require 'socket' -require 'io/nonblock' -require 'etc' - -module WEBrick - module Utils - ## - # Sets IO operations on +io+ to be non-blocking - def set_non_blocking(io) - io.nonblock = true if io.respond_to?(:nonblock=) - end - module_function :set_non_blocking - - ## - # Sets the close on exec flag for +io+ - def set_close_on_exec(io) - io.close_on_exec = true if io.respond_to?(:close_on_exec=) - end - module_function :set_close_on_exec - - ## - # Changes the process's uid and gid to the ones of +user+ - def su(user) - if pw = Etc.getpwnam(user) - Process::initgroups(user, pw.gid) - Process::Sys::setgid(pw.gid) - Process::Sys::setuid(pw.uid) - else - warn("WEBrick::Utils::su doesn't work on this platform", uplevel: 1) - end - end - module_function :su - - ## - # The server hostname - def getservername - host = Socket::gethostname - begin - Socket::gethostbyname(host)[0] - rescue - host - end - end - module_function :getservername - - ## - # Creates TCP server sockets bound to +address+:+port+ and returns them. - # - # It will create IPV4 and IPV6 sockets on all interfaces. - def create_listeners(address, port) - unless port - raise ArgumentError, "must specify port" - end - sockets = Socket.tcp_server_sockets(address, port) - sockets = sockets.map {|s| - s.autoclose = false - ts = TCPServer.for_fd(s.fileno) - s.close - ts - } - return sockets - end - module_function :create_listeners - - ## - # Characters used to generate random strings - RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "0123456789" + - "abcdefghijklmnopqrstuvwxyz" - - ## - # Generates a random string of length +len+ - def random_string(len) - rand_max = RAND_CHARS.bytesize - ret = "" - len.times{ ret << RAND_CHARS[rand(rand_max)] } - ret - end - module_function :random_string - - ########### - - require "timeout" - require "singleton" - - ## - # Class used to manage timeout handlers across multiple threads. - # - # Timeout handlers should be managed by using the class methods which are - # synchronized. - # - # id = TimeoutHandler.register(10, Timeout::Error) - # begin - # sleep 20 - # puts 'foo' - # ensure - # TimeoutHandler.cancel(id) - # end - # - # will raise Timeout::Error - # - # id = TimeoutHandler.register(10, Timeout::Error) - # begin - # sleep 5 - # puts 'foo' - # ensure - # TimeoutHandler.cancel(id) - # end - # - # will print 'foo' - # - class TimeoutHandler - include Singleton - - ## - # Mutex used to synchronize access across threads - TimeoutMutex = Thread::Mutex.new # :nodoc: - - ## - # Registers a new timeout handler - # - # +time+:: Timeout in seconds - # +exception+:: Exception to raise when timeout elapsed - def TimeoutHandler.register(seconds, exception) - at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds - instance.register(Thread.current, at, exception) - end - - ## - # Cancels the timeout handler +id+ - def TimeoutHandler.cancel(id) - instance.cancel(Thread.current, id) - end - - def self.terminate - instance.terminate - end - - ## - # Creates a new TimeoutHandler. You should use ::register and ::cancel - # instead of creating the timeout handler directly. - def initialize - TimeoutMutex.synchronize{ - @timeout_info = Hash.new - } - @queue = Thread::Queue.new - @watcher = nil - end - - # :nodoc: - private \ - def watch - to_interrupt = [] - while true - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - wakeup = nil - to_interrupt.clear - TimeoutMutex.synchronize{ - @timeout_info.each {|thread, ary| - next unless ary - ary.each{|info| - time, exception = *info - if time < now - to_interrupt.push [thread, info.object_id, exception] - elsif !wakeup || time < wakeup - wakeup = time - end - } - } - } - to_interrupt.each {|arg| interrupt(*arg)} - if !wakeup - @queue.pop - elsif (wakeup -= now) > 0 - begin - (th = Thread.start {@queue.pop}).join(wakeup) - ensure - th&.kill&.join - end - end - @queue.clear - end - end - - # :nodoc: - private \ - def watcher - (w = @watcher)&.alive? and return w # usual case - TimeoutMutex.synchronize{ - (w = @watcher)&.alive? and next w # pathological check - @watcher = Thread.start(&method(:watch)) - } - end - - ## - # Interrupts the timeout handler +id+ and raises +exception+ - def interrupt(thread, id, exception) - if cancel(thread, id) && thread.alive? - thread.raise(exception, "execution timeout") - end - end - - ## - # Registers a new timeout handler - # - # +time+:: Timeout in seconds - # +exception+:: Exception to raise when timeout elapsed - def register(thread, time, exception) - info = nil - TimeoutMutex.synchronize{ - (@timeout_info[thread] ||= []) << (info = [time, exception]) - } - @queue.push nil - watcher - return info.object_id - end - - ## - # Cancels the timeout handler +id+ - def cancel(thread, id) - TimeoutMutex.synchronize{ - if ary = @timeout_info[thread] - ary.delete_if{|info| info.object_id == id } - if ary.empty? - @timeout_info.delete(thread) - end - return true - end - return false - } - end - - ## - def terminate - TimeoutMutex.synchronize{ - @timeout_info.clear - @watcher&.kill&.join - } - end - end - - ## - # Executes the passed block and raises +exception+ if execution takes more - # than +seconds+. - # - # If +seconds+ is zero or nil, simply executes the block - def timeout(seconds, exception=Timeout::Error) - return yield if seconds.nil? or seconds.zero? - # raise ThreadError, "timeout within critical session" if Thread.critical - id = TimeoutHandler.register(seconds, exception) - begin - yield(seconds) - ensure - TimeoutHandler.cancel(id) - end - end - module_function :timeout - end -end diff --git a/ruby/lib/webrick/version.rb b/ruby/lib/webrick/version.rb deleted file mode 100644 index 5a21f82d9..000000000 --- a/ruby/lib/webrick/version.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: false -#-- -# version.rb -- version and release date -# -# Author: IPR -- Internet Programming with Ruby -- writers -# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU -# Copyright (c) 2003 Internet Programming with Ruby writers. All rights -# reserved. -# -# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $ - -module WEBrick - - ## - # The WEBrick version - - VERSION = "1.6.0" -end diff --git a/ruby/lib/webrick/webrick.gemspec b/ruby/lib/webrick/webrick.gemspec deleted file mode 100644 index 549050253..000000000 --- a/ruby/lib/webrick/webrick.gemspec +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'lib/webrick/version' -rescue LoadError - # for Ruby core repository - require_relative 'version' -end - -Gem::Specification.new do |s| - s.name = "webrick" - s.version = WEBrick::VERSION - s.summary = "HTTP server toolkit" - s.description = "WEBrick is an HTTP server toolkit that can be configured as an HTTPS server, a proxy server, and a virtual-host server." - - s.require_path = %w{lib} - s.files = [ - "Gemfile", - "LICENSE.txt", - "README.md", - "Rakefile", - "bin/console", - "bin/setup", - "lib/webrick.rb", - "lib/webrick/accesslog.rb", - "lib/webrick/cgi.rb", - "lib/webrick/compat.rb", - "lib/webrick/config.rb", - "lib/webrick/cookie.rb", - "lib/webrick/htmlutils.rb", - "lib/webrick/httpauth.rb", - "lib/webrick/httpauth/authenticator.rb", - "lib/webrick/httpauth/basicauth.rb", - "lib/webrick/httpauth/digestauth.rb", - "lib/webrick/httpauth/htdigest.rb", - "lib/webrick/httpauth/htgroup.rb", - "lib/webrick/httpauth/htpasswd.rb", - "lib/webrick/httpauth/userdb.rb", - "lib/webrick/httpproxy.rb", - "lib/webrick/httprequest.rb", - "lib/webrick/httpresponse.rb", - "lib/webrick/https.rb", - "lib/webrick/httpserver.rb", - "lib/webrick/httpservlet.rb", - "lib/webrick/httpservlet/abstract.rb", - "lib/webrick/httpservlet/cgi_runner.rb", - "lib/webrick/httpservlet/cgihandler.rb", - "lib/webrick/httpservlet/erbhandler.rb", - "lib/webrick/httpservlet/filehandler.rb", - "lib/webrick/httpservlet/prochandler.rb", - "lib/webrick/httpstatus.rb", - "lib/webrick/httputils.rb", - "lib/webrick/httpversion.rb", - "lib/webrick/log.rb", - "lib/webrick/server.rb", - "lib/webrick/ssl.rb", - "lib/webrick/utils.rb", - "lib/webrick/version.rb", - "webrick.gemspec", - ] - s.required_ruby_version = ">= 2.3.0" - - s.authors = ["TAKAHASHI Masayoshi", "GOTOU YUUZOU", "Eric Wong"] - s.email = [nil, nil, 'normal@ruby-lang.org'] - s.homepage = "https://www.ruby-lang.org" - s.license = "BSD-2-Clause" - - if s.respond_to?(:metadata=) - s.metadata = { - "bug_tracker_uri" => "https://bugs.ruby-lang.org/projects/ruby-trunk/issues", - "homepage_uri" => "https://www.ruby-lang.org", - "source_code_uri" => "https://git.ruby-lang.org/ruby.git/" - } - end - - s.add_development_dependency "rake" -end diff --git a/ruby/lib/yaml.rb b/ruby/lib/yaml.rb index cec7808f0..17b27e802 100644 --- a/ruby/lib/yaml.rb +++ b/ruby/lib/yaml.rb @@ -40,7 +40,7 @@ # # == History # -# Syck was the original for YAML implementation in Ruby's standard library +# Syck was the original YAML implementation in Ruby's standard library # developed by why the lucky stiff. # # You can still use Syck, if you prefer, for parsing and emitting YAML, but you diff --git a/ruby/lib/yaml/store.rb b/ruby/lib/yaml/store.rb index 3c9b8817e..f8650b942 100644 --- a/ruby/lib/yaml/store.rb +++ b/ruby/lib/yaml/store.rb @@ -65,7 +65,7 @@ def dump(table) end def load(content) - table = YAML.load(content) + table = YAML.unsafe_load(content) if table == false {} else diff --git a/ruby/lib/yaml/yaml.gemspec b/ruby/lib/yaml/yaml.gemspec index ba5027a9b..e8f20b8c2 100644 --- a/ruby/lib/yaml/yaml.gemspec +++ b/ruby/lib/yaml/yaml.gemspec @@ -1,13 +1,13 @@ Gem::Specification.new do |spec| spec.name = "yaml" - spec.version = "0.1.0" + spec.version = "0.2.0" spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"] spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"] spec.summary = "YAML Ain't Markup Language" spec.description = spec.summary spec.homepage = "https://github.com/ruby/yaml" - spec.license = "BSD-2-Clause" + spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ruby/libexec/bundle b/ruby/libexec/bundle index b3b1b691d..b8bf0d699 100755 --- a/ruby/libexec/bundle +++ b/ruby/libexec/bundle @@ -15,14 +15,16 @@ else require "bundler" end -# Check if an older version of bundler is installed -$LOAD_PATH.each do |path| - next unless path =~ %r{/bundler-0\.(\d+)} && $1.to_i < 9 - err = String.new - err << "Looks like you have a version of bundler that's older than 0.9.\n" - err << "Please remove your old versions.\n" - err << "An easy way to do this is by running `gem cleanup bundler`." - abort(err) +# Workaround for non-activated bundler spec due to missing https://github.com/rubygems/rubygems/commit/4e306d7bcdee924b8d80ca9db6125aa59ee4e5a3 +gem "bundler", Bundler::VERSION if Gem.rubygems_version < Gem::Version.new("2.6.2") + +if Gem.rubygems_version < Gem::Version.new("3.2.3") && Gem.ruby_version < Gem::Version.new("2.6.a") && !ENV["BUNDLER_NO_OLD_RUBYGEMS_WARNING"] + Bundler.ui.warn \ + "Your RubyGems version (#{Gem::VERSION})) has a bug that prevents " \ + "`required_ruby_version` from working for Bundler. Any scripts that use " \ + "`gem install bundler` will break as soon as Bundler drops support for " \ + "your Ruby version. Please upgrade RubyGems to avoid future breakage " \ + "and silence this warning by running `gem update --system 3.2.3`" end if File.exist?(base_path) diff --git a/ruby/bin/erb b/ruby/libexec/erb similarity index 99% rename from ruby/bin/erb rename to ruby/libexec/erb index 2435224fe..ded76991d 100755 --- a/ruby/bin/erb +++ b/ruby/libexec/erb @@ -171,6 +171,4 @@ EOU end end -if __FILE__ == $0 - ERB::Main.run -end +ERB::Main.run diff --git a/ruby/libexec/racc b/ruby/libexec/racc index 5656b25e4..4507d0496 100755 --- a/ruby/libexec/racc +++ b/ruby/libexec/racc @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -# $Id$ +# # # Copyright (c) 1999-2006 Minero Aoki # @@ -51,7 +51,7 @@ def main logfilename = path } parser.on('-e', '--executable [RUBYPATH]', 'Makes executable parser.') {|path| - executable = true + make_executable = true rubypath = (path == 'ruby' ? nil : path) } parser.on('-E', '--embedded', "Embeds Racc runtime in output.") { @@ -71,10 +71,6 @@ def main 'Uses CLASSNAME instead of Racc::Parser.') {|name| superclass = name } - parser.on('--runtime=FEATURE', - "Uses FEATURE instead of 'racc/parser'") {|feat| - runtime = feature - } parser.on('-C', '--check-only', 'Checks syntax and quit immediately.') {|fl| check_only = fl } @@ -88,24 +84,21 @@ def main debug_flags = Racc::DebugFlags.parse_option_string(flags) } #parser.on('--no-extensions', 'Run Racc without any Ruby extension.') { - # Racc.const_set :Racc_No_Extentions, true + # Racc.const_set :Racc_No_Extensions, true #} parser.on('--version', 'Prints version and quit.') { puts "racc version #{Racc::Version}" exit 0 } parser.on('--runtime-version', 'Prints runtime version and quit.') { - printf "racc runtime version %s (rev. %s); %s\n", + printf "racc runtime version %s; %s\n", Racc::Parser::Racc_Runtime_Version, - Racc::Parser::Racc_Runtime_Revision, if Racc::Parser.racc_runtime_type == 'ruby' - sprintf('ruby core version %s (rev. %s)', - Racc::Parser::Racc_Runtime_Core_Version_R, - Racc::Parser::Racc_Runtime_Core_Revision_R) + sprintf('ruby core version %s', + Racc::Parser::Racc_Runtime_Core_Version_R) else - sprintf('c core version %s (rev. %s)', - Racc::Parser::Racc_Runtime_Core_Version_C, - Racc::Parser::Racc_Runtime_Core_Revision_C) + sprintf('c core version %s', + Racc::Parser::Racc_Runtime_Core_Version_C) end exit 0 } @@ -187,8 +180,12 @@ def main log_useless states.grammar log_conflict states else - report_useless states.grammar - report_conflict states + has_useless = report_useless states.grammar + has_conflicts = report_conflict states + if has_useless || has_conflicts + preamble = make_logfile ? 'C' : 'Turn on logging with "-v" and c' + $stderr.puts %Q{#{preamble}heck ".output" file for details} + end end profiler.report @@ -204,13 +201,29 @@ def make_filename(path, suffix) path.sub(/(?:\..*?)?\z/, suffix) end +LIST_LIMIT = 10 +def report_list(enum, label) + c = enum.count + if c > 0 + $stderr.puts "#{c} #{label}:" + enum.first(LIST_LIMIT).each do |item| + $stderr.puts " #{yield item}" + end + $stderr.puts " ..." if c > LIST_LIMIT + end +end + +# @return [Boolean] if anything was reported def report_conflict(states) if states.should_report_srconflict? + reported = true $stderr.puts "#{states.n_srconflicts} shift/reduce conflicts" end if states.rrconflict_exist? + reported = true $stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts" end + reported end def log_conflict(states) @@ -225,16 +238,17 @@ def log_conflict(states) } end +# @return [Boolean] if anything was reported def report_useless(grammar) - if grammar.useless_nonterminal_exist? - $stderr.puts "#{grammar.n_useless_nonterminals} useless nonterminals" - end - if grammar.useless_rule_exist? - $stderr.puts "#{grammar.n_useless_rules} useless rules" - end + reported = report_list(grammar.each_useless_nonterminal, 'useless nonterminals', &:to_s) + + reported ||= report_list(grammar.each_useless_rule, 'useless rules') { |r| "##{r.ident} (#{r.target})" } + if grammar.start.useless? $stderr.puts 'fatal: start symbol does not derive any sentence' + reported = true end + reported end def log_useless(grammar) diff --git a/ruby/libexec/racc2y b/ruby/libexec/racc2y deleted file mode 100755 index f88d73ed2..000000000 --- a/ruby/libexec/racc2y +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/local/bin/ruby -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is feee software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the LGPL, see the file "COPYING". -# - -require 'racc/grammarfileparser' -require 'racc/info' -require 'optparse' - -def main - @with_action = true - with_header = false - with_inner = false - with_footer = false - output = nil - parser = OptionParser.new - parser.banner = "Usage: #{File.basename($0)} [-AHIF] [-oFILENAME] GRAMMARFILE" - parser.on('-o', '--output=FILENAME', 'output file name [.yacc]') {|name| - output = name - } - parser.on('-A', '--without-action', 'Does not include actions.') { - @with_action = false - } - parser.on('-H', '--with-header', 'Includes header part.') { - with_header = true - } - parser.on('-I', '--with-inner', 'Includes inner part.') { - with_inner = true - } - parser.on('-F', '--with-footer', 'Includes footer part.') { - with_footer = true - } - parser.on('--version', 'Prints version and quit.') { - puts "racc2y version #{Racc::Version}" - exit 0 - } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 - } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help - exit 1 - } - begin - parser.parse! - rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 - end - if ARGV.empty? - $stderr.puts "no input file" - exit 1 - end - unless ARGV.size == 1 - $stderr.puts "too many inputs" - exit 1 - end - input = ARGV[0] - - begin - result = Racc::GrammarFileParser.parse_file(input) - result.grammar.init - File.open(output || "#{input}.yacc", 'w') {|f| - f.puts "/* generated from #{input} */" - if with_header - f.puts - f.puts '%{' - print_user_codes f, result.params.header - f.puts '%}' - end - f.puts - print_terminals f, result.grammar - f.puts - print_precedence_table f, precedence_table(result.grammar) - f.puts - f.puts '%%' - print_grammar f, result.grammar - f.puts '%%' - if with_inner - f.puts '/*---- inner ----*/' - print_user_codes f, result.params.inner - end - if with_footer - f.puts '/*---- footer ----*/' - print_user_codes f, result.params.footer - end - } - rescue SystemCallError => err - $stderr.puts err.message - exit 1 - end -end - -def print_terminals(f, grammar) - init_indent = '%token'.size - f.print '%token' - columns = init_indent - grammar.symboltable.each_terminal do |t| - next unless t.terminal? - next if t.dummy? - next if t == grammar.symboltable.anchor - next if t == grammar.symboltable.error - unless t.value.kind_of?(String) - if columns > 60 - f.puts - f.print ' ' * init_indent - columns = init_indent - end - columns += f.write(" #{yacc_symbol(t)}") - end - end - f.puts -end - -def precedence_table(grammar) - table = [] - grammar.symboltable.select {|sym| sym.precedence }.each do |sym| - (table[sym.prec] ||= [sym.assoc]).push sym - end - table.compact -end - -def print_precedence_table(f, table) - return if table.empty? - f.puts '/* precedance table */' - table.each do |syms| - assoc = syms.shift - f.printf '%%%-8s ', assoc.to_s.downcase - f.puts syms.map {|s| yacc_symbol(s) }.join(' ') - end - f.puts -end - -def print_grammar(f, grammar) - prev_target = nil - indent = 10 - embactions = [] - grammar.each do |rule| - if rule.target.dummy? - embactions.push rule.action unless rule.action.empty? - next - end - if rule.target == prev_target - f.print ' ' * indent, '|' - else - prev_target = rule.target - f.printf "\n%-10s:", yacc_symbol(prev_target) - end - rule.symbols.each do |s| - if s.dummy? # target of dummy rule for embedded action - f.puts - print_action f, embactions.shift, indent - f.print ' ' * (indent + 1) - else - f.print ' ', yacc_symbol(s) - end - end - if rule.specified_prec - f.print ' %prec ', yacc_symbol(rule.specified_prec) - end - f.puts - unless rule.action.empty? - print_action f, rule.action, indent - end - end -end - -def print_action(f, action, indent) - return unless @with_action - f.print ' ' * (indent + 4), "{\n" - f.print ' ' * (indent + 6), action.source.text.strip, "\n" - f.print ' ' * (indent + 4) , "}\n" -end - -def print_user_codes(f, srcs) - return if srcs.empty? - srcs.each do |src| - f.puts src.text - end -end - -def yacc_symbol(s) - s.to_s.gsub('"', "'") -end - -main diff --git a/ruby/libexec/y2racc b/ruby/libexec/y2racc deleted file mode 100755 index 7933f9415..000000000 --- a/ruby/libexec/y2racc +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/local/bin/ruby -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -require 'racc/info' -require 'strscan' -require 'forwardable' -require 'optparse' - -def main - @with_action = true - @with_header = false - @with_usercode = false - cname = 'MyParser' - input = nil - output = nil - parser = OptionParser.new - parser.banner = "Usage: #{File.basename($0)} [-Ahu] [-c ] [-o ] " - parser.on('-o', '--output=FILENAME', 'output file name [.racc]') {|name| - output = name - } - parser.on('-c', '--classname=NAME', "Name of the parser class. [#{cname}]") {|name| - cname = name - } - parser.on('-A', '--without-action', 'Does not include actions.') { - @with_action = false - } - parser.on('-h', '--with-header', 'Includes header (%{...%}).') { - @with_header = true - } - parser.on('-u', '--with-user-code', 'Includes user code.') { - @with_usercode = true - } - parser.on('--version', 'Prints version and quit.') { - puts "y2racc version #{Racc::Version}" - exit 0 - } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 - } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help - exit 1 - } - begin - parser.parse! - rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 - end - if ARGV.empty? - $stderr.puts 'no input' - exit 1 - end - if ARGV.size > 1 - $stderr.puts 'too many input' - exit 1 - end - input = ARGV[0] - - begin - result = YaccFileParser.parse_file(input) - File.open(output || "#{input}.racc", 'w') {|f| - convert cname, result, f - } - rescue SystemCallError => err - $stderr.puts err.message - exit 1 - end -end - -def convert(classname, result, f) - init_indent = 'token'.size - f.puts %<# Converted from "#{result.filename}" by y2racc version #{Racc::Version}> - f.puts - f.puts "class #{classname}" - unless result.terminals.empty? - f.puts - f.print 'token' - columns = init_indent - result.terminals.each do |t| - if columns > 60 - f.puts - f.print ' ' * init_indent - columns = init_indent - end - columns += f.write(" #{t}") - end - f.puts - end - unless result.precedence_table.empty? - f.puts - f.puts 'preclow' - result.precedence_table.each do |assoc, toks| - f.printf " %-8s %s\n", assoc, toks.join(' ') unless toks.empty? - end - f.puts 'prechigh' - end - if result.start - f.puts - f.puts "start #{@start}" - end - - f.puts - f.puts 'rule' - texts = @with_action ? result.grammar : result.grammar_without_actions - texts.each do |text| - f.print text - end - - if @with_header and result.header - f.puts - f.puts '---- header' - f.puts result.header - end - if @with_usercode and result.usercode - f.puts - f.puts '---- footer' - f.puts result.usercode - end -end - -class ParseError < StandardError; end - -class StringScanner_withlineno - def initialize(src) - @s = StringScanner.new(src) - @lineno = 1 - end - - extend Forwardable - def_delegator "@s", :eos? - def_delegator "@s", :rest - - attr_reader :lineno - - def scan(re) - advance_lineno(@s.scan(re)) - end - - def scan_until(re) - advance_lineno(@s.scan_until(re)) - end - - def skip(re) - str = advance_lineno(@s.scan(re)) - str ? str.size : nil - end - - def getch - advance_lineno(@s.getch) - end - - private - - def advance_lineno(str) - @lineno += str.count("\n") if str - str - end -end - -class YaccFileParser - - Result = Struct.new(:terminals, :precedence_table, :start, - :header, :grammar, :usercode, :filename) - class Result # reopen - def initialize - super - self.terminals = [] - self.precedence_table = [] - self.start = nil - self.grammar = [] - self.header = nil - self.usercode = nil - self.filename = nil - end - - def grammar_without_actions - grammar().map {|text| text[0,1] == '{' ? '{}' : text } - end - end - - def YaccFileParser.parse_file(filename) - new().parse(File.read(filename), filename) - end - - def parse(src, filename = '-') - @result = Result.new - @filename = filename - @result.filename = filename - s = StringScanner_withlineno.new(src) - parse_header s - parse_grammar s - @result - end - - private - - COMMENT = %r - CHAR = /'((?:[^'\\]+|\\.)*)'/ - STRING = /"((?:[^"\\]+|\\.)*)"/ - - def parse_header(s) - skip_until_percent s - until s.eos? - case - when t = s.scan(/left/) - @result.precedence_table.push ['left', scan_symbols(s)] - when t = s.scan(/right/) - @result.precedence_table.push ['right', scan_symbols(s)] - when t = s.scan(/nonassoc/) - @result.precedence_table.push ['nonassoc', scan_symbols(s)] - when t = s.scan(/token/) - list = scan_symbols(s) - list.shift if /\A<(.*)>\z/ =~ list[0] - @result.terminals.concat list - when t = s.scan(/start/) - @result.start = scan_symbols(s)[0] - when s.skip(%r<(?: - type | union | expect | thong | binary | - semantic_parser | pure_parser | no_lines | - raw | token_table - )\b>x) - skip_until_percent s - when s.skip(/\{/) # header (%{...%}) - str = s.scan_until(/\%\}/) - str.chop! - str.chop! - @result.header = str - skip_until_percent s - when s.skip(/\%/) # grammar (%%...) - return - else - raise ParseError, "#{@filename}:#{s.lineno}: scan error" - end - end - end - - def skip_until_percent(s) - until s.eos? - s.skip /[^\%\/]+/ - next if s.skip(COMMENT) - return if s.getch == '%' - end - end - - def scan_symbols(s) - list = [] - until s.eos? - s.skip /\s+/ - if s.skip(COMMENT) - ; - elsif t = s.scan(CHAR) - list.push t - elsif t = s.scan(STRING) - list.push t - elsif s.skip(/\%/) - break - elsif t = s.scan(/\S+/) - list.push t - else - raise ParseError, "#{@filename}:#{@lineno}: scan error" - end - end - list - end - - def parse_grammar(s) - buf = [] - until s.eos? - if t = s.scan(/[^%'"{\/]+/) - buf.push t - break if s.eos? - end - if s.skip(/\{/) - buf.push scan_action(s) - elsif t = s.scan(/'(?:[^'\\]+|\\.)*'/) then buf.push t - elsif t = s.scan(/"(?:[^"\\]+|\\.)*"/) then buf.push t - elsif t = s.scan(COMMENT) then buf.push t - elsif s.skip(/%prec\b/) then buf.push '=' - elsif s.skip(/%%/) - @result.usercode = s.rest - break - else - buf.push s.getch - end - end - @result.grammar = buf - end - - def scan_action(s) - buf = '{' - nest = 1 - until s.eos? - if t = s.scan(%r<[^/{}'"]+>) - buf << t - break if s.eos? - elsif t = s.scan(COMMENT) - buf << t - elsif t = s.scan(CHAR) - buf << t - elsif t = s.scan(STRING) - buf << t - else - c = s.getch - buf << c - case c - when '{' - nest += 1 - when '}' - nest -= 1 - return buf if nest == 0 - end - end - end - $stderr.puts "warning: unterminated action in #{@filename}" - buf - end - -end - -unless Object.method_defined?(:funcall) - class Object - alias funcall __send__ - end -end - - -main diff --git a/ruby/load.c b/ruby/load.c index 07acc9ac7..812fe2fe9 100644 --- a/ruby/load.c +++ b/ruby/load.c @@ -2,29 +2,34 @@ * load methods from eval.c */ -#include "ruby/encoding.h" -#include "ruby/util.h" -#include "internal.h" #include "dln.h" #include "eval_intern.h" -#include "probes.h" +#include "internal.h" +#include "internal/dir.h" +#include "internal/error.h" +#include "internal/file.h" +#include "internal/load.h" +#include "internal/parse.h" +#include "internal/thread.h" +#include "internal/variable.h" #include "iseq.h" +#include "probes.h" +#include "ruby/encoding.h" +#include "ruby/util.h" static VALUE ruby_dln_librefs; #define IS_RBEXT(e) (strcmp((e), ".rb") == 0) #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0) -#ifdef DLEXT2 -#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0) -#else #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) -#endif static const char *const loadable_ext[] = { ".rb", DLEXT, -#ifdef DLEXT2 - DLEXT2, -#endif + 0 +}; + +static const char *const ruby_ext[] = { + ".rb", 0 }; @@ -41,9 +46,8 @@ enum expand_type { string objects in $LOAD_PATH are frozen. */ static void -rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *has_non_cache) +rb_construct_expanded_load_path(rb_vm_t *vm, enum expand_type type, int *has_relative, int *has_non_cache) { - rb_vm_t *vm = GET_VM(); VALUE load_path = vm->load_path; VALUE expanded_load_path = vm->expanded_load_path; VALUE ary; @@ -88,16 +92,15 @@ rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *h rb_ary_replace(vm->load_path_snapshot, vm->load_path); } -VALUE -rb_get_expanded_load_path(void) +static VALUE +get_expanded_load_path(rb_vm_t *vm) { - rb_vm_t *vm = GET_VM(); const VALUE non_cache = Qtrue; if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { /* The load path was modified. Rebuild the expanded load path. */ int has_relative = 0, has_non_cache = 0; - rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); + rb_construct_expanded_load_path(vm, EXPAND_ALL, &has_relative, &has_non_cache); if (has_relative) { vm->load_path_check_cache = rb_dir_getwd_ospath(); } @@ -112,7 +115,7 @@ rb_get_expanded_load_path(void) else if (vm->load_path_check_cache == non_cache) { int has_relative = 1, has_non_cache = 1; /* Expand only non-cacheable objects. */ - rb_construct_expanded_load_path(EXPAND_NON_CACHE, + rb_construct_expanded_load_path(vm, EXPAND_NON_CACHE, &has_relative, &has_non_cache); } else if (vm->load_path_check_cache) { @@ -122,18 +125,24 @@ rb_get_expanded_load_path(void) /* Current working directory or filesystem encoding was changed. Expand relative load path and non-cacheable objects again. */ vm->load_path_check_cache = cwd; - rb_construct_expanded_load_path(EXPAND_RELATIVE, + rb_construct_expanded_load_path(vm, EXPAND_RELATIVE, &has_relative, &has_non_cache); } else { /* Expand only tilde (User HOME) and non-cacheable objects. */ - rb_construct_expanded_load_path(EXPAND_HOME, + rb_construct_expanded_load_path(vm, EXPAND_HOME, &has_relative, &has_non_cache); } } return vm->expanded_load_path; } +VALUE +rb_get_expanded_load_path(void) +{ + return get_expanded_load_path(GET_VM()); +} + static VALUE load_path_getter(ID id, VALUE * p) { @@ -142,34 +151,39 @@ load_path_getter(ID id, VALUE * p) } static VALUE -get_loaded_features(void) +get_loaded_features(rb_vm_t *vm) { - return GET_VM()->loaded_features; + return vm->loaded_features; +} + +static VALUE +get_loaded_features_realpaths(rb_vm_t *vm) +{ + return vm->loaded_features_realpaths; } static VALUE get_LOADED_FEATURES(ID _x, VALUE *_y) { - return get_loaded_features(); + return get_loaded_features(GET_VM()); } static void -reset_loaded_features_snapshot(void) +reset_loaded_features_snapshot(rb_vm_t *vm) { - rb_vm_t *vm = GET_VM(); rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); } static struct st_table * -get_loaded_features_index_raw(void) +get_loaded_features_index_raw(rb_vm_t *vm) { - return GET_VM()->loaded_features_index; + return vm->loaded_features_index; } static st_table * -get_loading_table(void) +get_loading_table(rb_vm_t *vm) { - return GET_VM()->loading_table; + return vm->loading_table; } static st_data_t @@ -178,34 +192,69 @@ feature_key(const char *str, size_t len) return st_hash(str, len, 0xfea7009e); } +static bool +is_rbext_path(VALUE feature_path) +{ + long len = RSTRING_LEN(feature_path); + long rbext_len = rb_strlen_lit(".rb"); + if (len <= rbext_len) return false; + return IS_RBEXT(RSTRING_PTR(feature_path) + len - rbext_len); +} + static void -features_index_add_single(const char* str, size_t len, VALUE offset) +features_index_add_single(rb_vm_t *vm, const char* str, size_t len, VALUE offset, bool rb) { struct st_table *features_index; VALUE this_feature_index = Qnil; st_data_t short_feature_key; + st_data_t data; Check_Type(offset, T_FIXNUM); short_feature_key = feature_key(str, len); - features_index = get_loaded_features_index_raw(); - st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index); - - if (NIL_P(this_feature_index)) { + features_index = get_loaded_features_index_raw(vm); + if (!st_lookup(features_index, short_feature_key, &data) || + NIL_P(this_feature_index = (VALUE)data)) { st_insert(features_index, short_feature_key, (st_data_t)offset); } - else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) { + else if (FIXNUM_P(this_feature_index)) { + VALUE loaded_features = get_loaded_features(vm); + VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(this_feature_index)); VALUE feature_indexes[2]; - feature_indexes[0] = this_feature_index; - feature_indexes[1] = offset; + int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0; + feature_indexes[top^0] = this_feature_index; + feature_indexes[top^1] = offset; this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray)); RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */ rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes)); st_insert(features_index, short_feature_key, (st_data_t)this_feature_index); } else { + long pos = -1; + Check_Type(this_feature_index, T_ARRAY); + if (rb) { + VALUE loaded_features = get_loaded_features(vm); + for (long i = 0; i < RARRAY_LEN(this_feature_index); ++i) { + VALUE idx = RARRAY_AREF(this_feature_index, i); + VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(idx)); + Check_Type(this_feature_path, T_STRING); + if (!is_rbext_path(this_feature_path)) { + /* as this_feature_index is a fake VALUE, `push` (which + * doesn't wb_unprotect like as rb_ary_splice) first, + * then rotate partially. */ + pos = i; + break; + } + } + } rb_ary_push(this_feature_index, offset); + if (pos >= 0) { + VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(this_feature_index); + long len = RARRAY_LEN(this_feature_index); + MEMMOVE(ptr + pos, ptr + pos + 1, VALUE, len - pos - 1); + ptr[pos] = offset; + } } } @@ -218,9 +267,10 @@ features_index_add_single(const char* str, size_t len, VALUE offset) relies on for its fast lookup. */ static void -features_index_add(VALUE feature, VALUE offset) +features_index_add(rb_vm_t *vm, VALUE feature, VALUE offset) { const char *feature_str, *feature_end, *ext, *p; + bool rb = false; feature_str = StringValuePtr(feature); feature_end = feature_str + RSTRING_LEN(feature); @@ -230,6 +280,8 @@ features_index_add(VALUE feature, VALUE offset) break; if (*ext != '.') ext = NULL; + else + rb = IS_RBEXT(ext); /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is at the end of `feature`, or is NULL if there is no such string. */ @@ -241,14 +293,14 @@ features_index_add(VALUE feature, VALUE offset) if (p < feature_str) break; /* Now *p == '/'. We reach this point for every '/' in `feature`. */ - features_index_add_single(p + 1, feature_end - p - 1, offset); + features_index_add_single(vm, p + 1, feature_end - p - 1, offset, false); if (ext) { - features_index_add_single(p + 1, ext - p - 1, offset); + features_index_add_single(vm, p + 1, ext - p - 1, offset, rb); } } - features_index_add_single(feature_str, feature_end - feature_str, offset); + features_index_add_single(vm, feature_str, feature_end - feature_str, offset, false); if (ext) { - features_index_add_single(feature_str, ext - feature_str, offset); + features_index_add_single(vm, feature_str, ext - feature_str, offset, rb); } } @@ -264,16 +316,18 @@ loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg) } static st_table * -get_loaded_features_index(void) +get_loaded_features_index(rb_vm_t *vm) { VALUE features; int i; - rb_vm_t *vm = GET_VM(); if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { /* The sharing was broken; something (other than us in rb_provide_feature()) modified loaded_features. Rebuild the index. */ st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0); + + VALUE realpaths = vm->loaded_features_realpaths; + rb_hash_clear(realpaths); features = vm->loaded_features; for (i = 0; i < RARRAY_LEN(features); i++) { VALUE entry, as_str; @@ -282,9 +336,18 @@ get_loaded_features_index(void) as_str = rb_fstring(rb_str_freeze(as_str)); if (as_str != entry) rb_ary_store(features, i, as_str); - features_index_add(as_str, INT2FIX(i)); + features_index_add(vm, as_str, INT2FIX(i)); } - reset_loaded_features_snapshot(); + reset_loaded_features_snapshot(vm); + + features = rb_ary_dup(vm->loaded_features_snapshot); + long j = RARRAY_LEN(features); + for (i = 0; i < j; i++) { + VALUE as_str = rb_ary_entry(features, i); + VALUE realpath = rb_check_realpath(Qnil, as_str, NULL); + if (NIL_P(realpath)) realpath = as_str; + rb_hash_aset(realpaths, rb_fstring(realpath), Qtrue); + } } return vm->loaded_features_index; } @@ -365,7 +428,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) } static int -rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) +rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn) { VALUE features, this_feature_index = Qnil, v, p, load_path = 0; const char *f, *e; @@ -386,11 +449,10 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c elen = 0; type = 0; } - features = get_loaded_features(); - features_index = get_loaded_features_index(); + features = get_loaded_features(vm); + features_index = get_loaded_features_index(vm); key = feature_key(feature, strlen(feature)); - st_lookup(features_index, key, (st_data_t *)&this_feature_index); /* We search `features` for an entry such that either "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" for some j, or @@ -417,7 +479,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c or ends in '/'. This includes both match forms above, as well as any distractors, so we may ignore all other entries in `features`. */ - if (!NIL_P(this_feature_index)) { + if (st_lookup(features_index, key, &data) && !NIL_P(this_feature_index = (VALUE)data)) { for (i = 0; ; i++) { VALUE entry; long index; @@ -436,7 +498,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c if ((n = RSTRING_LEN(v)) < len) continue; if (strncmp(f, feature, len) != 0) { if (expanded) continue; - if (!load_path) load_path = rb_get_expanded_load_path(); + if (!load_path) load_path = get_expanded_load_path(vm); if (!(p = loaded_feature_path(f, n, feature, len, type, load_path))) continue; expanded = 1; @@ -456,14 +518,14 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c } } - loading_tbl = get_loading_table(); + loading_tbl = get_loading_table(vm); f = 0; if (!expanded) { struct loaded_feature_searching fs; fs.name = feature; fs.len = len; fs.type = type; - fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); + fs.load_path = load_path ? load_path : get_expanded_load_path(vm); fs.result = 0; st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); if ((f = fs.result) != 0) { @@ -473,9 +535,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c } if (st_get_key(loading_tbl, (st_data_t)feature, &data)) { if (fn) *fn = (const char*)data; - loading: - if (!ext) return 'u'; - return !IS_RBEXT(ext) ? 's' : 'r'; + goto loading; } else { VALUE bufstr; @@ -507,6 +567,10 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c rb_str_resize(bufstr, 0); } return 0; + + loading: + if (!ext) return 'u'; + return !IS_RBEXT(ext) ? 's' : 'r'; } int @@ -515,8 +579,8 @@ rb_provided(const char *feature) return rb_feature_provided(feature, 0); } -int -rb_feature_provided(const char *feature, const char **loading) +static int +feature_provided(rb_vm_t *vm, const char *feature, const char **loading) { const char *ext = strrchr(feature, '.'); VALUE fullpath = 0; @@ -528,41 +592,48 @@ rb_feature_provided(const char *feature, const char **loading) } if (ext && !strchr(ext, '/')) { if (IS_RBEXT(ext)) { - if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE; + if (rb_feature_p(vm, feature, ext, TRUE, FALSE, loading)) return TRUE; return FALSE; } else if (IS_SOEXT(ext) || IS_DLEXT(ext)) { - if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE; + if (rb_feature_p(vm, feature, ext, FALSE, FALSE, loading)) return TRUE; return FALSE; } } - if (rb_feature_p(feature, 0, TRUE, FALSE, loading)) + if (rb_feature_p(vm, feature, 0, TRUE, FALSE, loading)) return TRUE; RB_GC_GUARD(fullpath); return FALSE; } +int +rb_feature_provided(const char *feature, const char **loading) +{ + return feature_provided(GET_VM(), feature, loading); +} + static void -rb_provide_feature(VALUE feature) +rb_provide_feature(rb_vm_t *vm, VALUE feature) { VALUE features; - features = get_loaded_features(); + features = get_loaded_features(vm); if (OBJ_FROZEN(features)) { rb_raise(rb_eRuntimeError, "$LOADED_FEATURES is frozen; cannot append feature"); } rb_str_freeze(feature); + get_loaded_features_index(vm); rb_ary_push(features, rb_fstring(feature)); - features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); - reset_loaded_features_snapshot(); + features_index_add(vm, feature, INT2FIX(RARRAY_LEN(features)-1)); + reset_loaded_features_snapshot(vm); } void rb_provide(const char *feature) { - rb_provide_feature(rb_fstring_cstr(feature)); + rb_provide_feature(GET_VM(), rb_fstring_cstr(feature)); } NORETURN(static void load_failed(VALUE)); @@ -586,7 +657,7 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) } static inline enum ruby_tag_type -load_wrapping(rb_execution_context_t *ec, VALUE fname) +load_wrapping(rb_execution_context_t *ec, VALUE fname, VALUE load_wrapper) { enum ruby_tag_type state; rb_thread_t *th = rb_ec_thread_ptr(ec); @@ -598,9 +669,9 @@ load_wrapping(rb_execution_context_t *ec, VALUE fname) ec->errinfo = Qnil; /* ensure */ - /* load in anonymous module as toplevel */ + /* load in module as toplevel */ th->top_self = rb_obj_clone(rb_vm_top_self()); - th->top_wrapper = rb_module_new(); + th->top_wrapper = load_wrapper; rb_extend_object(th->top_self, th->top_wrapper); EC_PUSH_TAG(ec); @@ -632,12 +703,15 @@ raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state) } static void -rb_load_internal(VALUE fname, int wrap) +rb_load_internal(VALUE fname, VALUE wrap) { rb_execution_context_t *ec = GET_EC(); enum ruby_tag_type state = TAG_NONE; - if (wrap) { - state = load_wrapping(ec, fname); + if (RTEST(wrap)) { + if (!RB_TYPE_P(wrap, T_MODULE)) { + wrap = rb_module_new(); + } + state = load_wrapping(ec, fname, wrap); } else { load_iseq_eval(ec, fname); @@ -650,7 +724,7 @@ rb_load(VALUE fname, int wrap) { VALUE tmp = rb_find_file(FilePathValue(fname)); if (!tmp) load_failed(fname); - rb_load_internal(tmp, wrap); + rb_load_internal(tmp, RBOOL(wrap)); } void @@ -671,14 +745,31 @@ rb_load_protect(VALUE fname, int wrap, int *pstate) * call-seq: * load(filename, wrap=false) -> true * - * Loads and executes the Ruby - * program in the file _filename_. If the filename does not - * resolve to an absolute path, the file is searched for in the library - * directories listed in $:. If the optional _wrap_ - * parameter is +true+, the loaded script will be executed - * under an anonymous module, protecting the calling program's global - * namespace. In no circumstance will any local variables in the loaded - * file be propagated to the loading environment. + * Loads and executes the Ruby program in the file _filename_. + * + * If the filename is an absolute path (e.g. starts with '/'), the file + * will be loaded directly using the absolute path. + * + * If the filename is an explicit relative path (e.g. starts with './' or + * '../'), the file will be loaded using the relative path from the current + * directory. + * + * Otherwise, the file will be searched for in the library + * directories listed in $LOAD_PATH ($:). + * If the file is found in a directory, it will attempt to load the file + * relative to that directory. If the file is not found in any of the + * directories in $LOAD_PATH, the file will be loaded using + * the relative path from the current directory. + * + * If the file doesn't exist when there is an attempt to load it, a + * LoadError will be raised. + * + * If the optional _wrap_ parameter is +true+, the loaded script will + * be executed under an anonymous module, protecting the calling + * program's global namespace. If the optional _wrap_ parameter is a + * module, the loaded script will be executed under the given module. + * In no circumstance will any local variables in the loaded file be + * propagated to the loading environment. */ static VALUE @@ -698,7 +789,7 @@ rb_f_load(int argc, VALUE *argv, VALUE _) load_failed(orig_fname); path = fname; } - rb_load_internal(path, RTEST(wrap)); + rb_load_internal(path, wrap); RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname)); @@ -706,10 +797,10 @@ rb_f_load(int argc, VALUE *argv, VALUE _) } static char * -load_lock(const char *ftptr) +load_lock(rb_vm_t *vm, const char *ftptr, bool warn) { st_data_t data; - st_table *loading_tbl = get_loading_table(); + st_table *loading_tbl = get_loading_table(vm); if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) { /* partial state */ @@ -726,7 +817,7 @@ load_lock(const char *ftptr) (*init)(); return (char *)""; } - if (RTEST(ruby_verbose)) { + if (warn) { VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr); rb_backtrace_each(rb_str_append, warning); rb_warning("%"PRIsVALUE, warning); @@ -758,11 +849,11 @@ release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int exis } static void -load_unlock(const char *ftptr, int done) +load_unlock(rb_vm_t *vm, const char *ftptr, int done) { if (ftptr) { st_data_t key = (st_data_t)ftptr; - st_table *loading_tbl = get_loading_table(); + st_table *loading_tbl = get_loading_table(vm); st_update(loading_tbl, key, release_thread_shield, done); } @@ -776,8 +867,10 @@ load_unlock(const char *ftptr, int done) * Loads the given +name+, returning +true+ if successful and +false+ if the * feature is already loaded. * - * If the filename does not resolve to an absolute path, it will be searched - * for in the directories listed in $LOAD_PATH ($:). + * If the filename neither resolves to an absolute path nor starts with + * './' or '../', the file will be searched for in the library + * directories listed in $LOAD_PATH ($:). + * If the filename starts with './' or '../', resolution is based on Dir.pwd. * * If the filename has the extension ".rb", it is loaded as a source file; if * the extension is ".so", ".o", or ".dll", or the default shared library @@ -830,10 +923,10 @@ rb_f_require_relative(VALUE obj, VALUE fname) return rb_require_string(rb_file_absolute_path(fname, base)); } -typedef int (*feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn); +typedef int (*feature_func)(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn); static int -search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p) +search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_feature_p) { VALUE tmp; char *ext, *ftptr; @@ -844,83 +937,75 @@ search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p) ext = strrchr(ftptr = RSTRING_PTR(fname), '.'); if (ext && !strchr(ext, '/')) { if (IS_RBEXT(ext)) { - if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) { + if (rb_feature_p(vm, ftptr, ext, TRUE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 'r'; } if ((tmp = rb_find_file(fname)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); - if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) + if (!rb_feature_p(vm, ftptr, ext, TRUE, TRUE, &loading) || loading) *path = tmp; return 'r'; } return 0; } else if (IS_SOEXT(ext)) { - if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { + if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 's'; } tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname)); -#ifdef DLEXT2 - OBJ_FREEZE(tmp); - if (rb_find_file_ext(&tmp, loadable_ext + 1)) { - ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); - if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) - *path = tmp; - return 's'; - } -#else rb_str_cat2(tmp, DLEXT); OBJ_FREEZE(tmp); if ((tmp = rb_find_file(tmp)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); - if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) + if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading) *path = tmp; return 's'; } -#endif } else if (IS_DLEXT(ext)) { - if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { + if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 's'; } if ((tmp = rb_find_file(fname)) != 0) { ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); - if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) + if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading) *path = tmp; return 's'; } } } - else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') { + else if ((ft = rb_feature_p(vm, ftptr, 0, FALSE, FALSE, &loading)) == 'r') { if (loading) *path = rb_filesystem_str_new_cstr(loading); return 'r'; } tmp = fname; - type = rb_find_file_ext(&tmp, loadable_ext); + type = rb_find_file_ext(&tmp, ft == 's' ? ruby_ext : loadable_ext); switch (type) { case 0: if (ft) goto statically_linked; ftptr = RSTRING_PTR(tmp); - return rb_feature_p(ftptr, 0, FALSE, TRUE, 0); + return rb_feature_p(vm, ftptr, 0, FALSE, TRUE, 0); default: if (ft) { - statically_linked: - if (loading) *path = rb_filesystem_str_new_cstr(loading); - return ft; + goto statically_linked; } /* fall through */ case 1: ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); - if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading) + if (rb_feature_p(vm, ftptr, ext, !--type, TRUE, &loading) && !loading) break; *path = tmp; } return type ? 's' : 'r'; + + statically_linked: + if (loading) *path = rb_filesystem_str_new_cstr(loading); + return ft; } static void @@ -937,7 +1022,7 @@ load_ext(VALUE path) } static int -no_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) +no_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn) { return 0; } @@ -952,7 +1037,7 @@ rb_resolve_feature_path(VALUE klass, VALUE fname) fname = rb_get_path(fname); path = rb_str_encode_ospath(fname); - found = search_required(path, &path, no_feature_p); + found = search_required(GET_VM(), path, &path, no_feature_p); switch (found) { case 'r': @@ -962,12 +1047,31 @@ rb_resolve_feature_path(VALUE klass, VALUE fname) sym = ID2SYM(rb_intern("so")); break; default: - load_failed(fname); + return Qnil; } return rb_ary_new_from_args(2, sym, path); } +static void +ext_config_push(rb_thread_t *th, struct rb_ext_config *prev) +{ + *prev = th->ext_config; + th->ext_config = (struct rb_ext_config){0}; +} + +static void +ext_config_pop(rb_thread_t *th, struct rb_ext_config *prev) +{ + th->ext_config = *prev; +} + +void +rb_ext_ractor_safe(bool flag) +{ + GET_THREAD()->ext_config.ractor_safe = flag; +} + /* * returns * 0: if already loaded (false) @@ -976,20 +1080,28 @@ rb_resolve_feature_path(VALUE klass, VALUE fname) * >1: exception */ static int -require_internal(rb_execution_context_t *ec, VALUE fname, int exception) +require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool warn) { volatile int result = -1; rb_thread_t *th = rb_ec_thread_ptr(ec); - volatile VALUE wrapper = th->top_wrapper; - volatile VALUE self = th->top_self; - volatile VALUE errinfo = ec->errinfo; + volatile const struct { + VALUE wrapper, self, errinfo; + } saved = { + th->top_wrapper, th->top_self, ec->errinfo, + }; enum ruby_tag_type state; char *volatile ftptr = 0; VALUE path; + volatile VALUE saved_path; + volatile VALUE realpath = 0; + VALUE realpaths = get_loaded_features_realpaths(th->vm); + volatile bool reset_ext_config = false; + struct rb_ext_config prev_ext_config; fname = rb_get_path(fname); path = rb_str_encode_ospath(fname); RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname)); + saved_path = path; EC_PUSH_TAG(ec); ec->errinfo = Qnil; /* ensure */ @@ -999,16 +1111,21 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception) int found; RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname)); - found = search_required(path, &path, rb_feature_p); + found = search_required(th->vm, path, &saved_path, rb_feature_p); RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname)); + path = saved_path; if (found) { - if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { + if (!path || !(ftptr = load_lock(th->vm, RSTRING_PTR(path), warn))) { result = 0; } else if (!*ftptr) { result = TAG_RETURN; } + else if (RTEST(rb_hash_aref(realpaths, + realpath = rb_realpath_internal(Qnil, path, 1)))) { + result = 0; + } else { switch (found) { case 'r': @@ -1016,6 +1133,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception) break; case 's': + reset_ext_config = true; + ext_config_push(th, &prev_ext_config); handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, path, VM_BLOCK_HANDLER_NONE, path); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); @@ -1026,13 +1145,17 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception) } } EC_POP_TAG(); - th = rb_ec_thread_ptr(ec); - th->top_self = self; - th->top_wrapper = wrapper; - if (ftptr) load_unlock(RSTRING_PTR(path), !state); + + rb_thread_t *th2 = rb_ec_thread_ptr(ec); + th2->top_self = saved.self; + th2->top_wrapper = saved.wrapper; + if (reset_ext_config) ext_config_pop(th2, &prev_ext_config); + + path = saved_path; + if (ftptr) load_unlock(th2->vm, RSTRING_PTR(path), !state); if (state) { - if (state == TAG_FATAL) { + if (state == TAG_FATAL || state == TAG_THROW) { EC_JUMP_TAG(ec, state); } else if (exception) { @@ -1054,19 +1177,32 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception) rb_exc_raise(ec->errinfo); } - if (result == TAG_RETURN) rb_provide_feature(path); - ec->errinfo = errinfo; + if (result == TAG_RETURN) { + rb_provide_feature(th2->vm, path); + VALUE real = realpath; + if (real) { + rb_hash_aset(realpaths, rb_fstring(real), Qtrue); + } + } + ec->errinfo = saved.errinfo; RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname)); return result; } +int +rb_require_internal_silent(VALUE fname) +{ + rb_execution_context_t *ec = GET_EC(); + return require_internal(ec, fname, 1, false); +} + int rb_require_internal(VALUE fname) { rb_execution_context_t *ec = GET_EC(); - return require_internal(ec, fname, 1); + return require_internal(ec, fname, 1, RTEST(ruby_verbose)); } int @@ -1075,33 +1211,16 @@ ruby_require_internal(const char *fname, unsigned int len) struct RString fake; VALUE str = rb_setup_fake_str(&fake, fname, len, 0); rb_execution_context_t *ec = GET_EC(); - int result = require_internal(ec, str, 0); + int result = require_internal(ec, str, 0, RTEST(ruby_verbose)); rb_set_errinfo(Qnil); return result == TAG_RETURN ? 1 : result ? -1 : 0; } -VALUE -rb_require_safe(VALUE fname, int safe) -{ - rb_warn("rb_require_safe will be removed in Ruby 3.0"); - rb_execution_context_t *ec = GET_EC(); - int result = require_internal(ec, fname, 1); - - if (result > TAG_RETURN) { - EC_JUMP_TAG(ec, result); - } - if (result < 0) { - load_failed(fname); - } - - return result ? Qtrue : Qfalse; -} - VALUE rb_require_string(VALUE fname) { rb_execution_context_t *ec = GET_EC(); - int result = require_internal(ec, fname, 1); + int result = require_internal(ec, fname, 1, RTEST(ruby_verbose)); if (result > TAG_RETURN) { EC_JUMP_TAG(ec, result); @@ -1110,7 +1229,7 @@ rb_require_string(VALUE fname) load_failed(fname); } - return result ? Qtrue : Qfalse; + return RBOOL(result); } VALUE @@ -1137,9 +1256,10 @@ register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void (*init)(void)) { - st_table *loading_tbl = get_loading_table(); + rb_vm_t *vm = GET_VM(); + st_table *loading_tbl = get_loading_table(vm); - if (rb_provided(name)) + if (feature_provided(vm, name, 0)) return; st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init); } @@ -1222,7 +1342,7 @@ static VALUE rb_f_autoload(VALUE obj, VALUE sym, VALUE file) { VALUE klass = rb_class_real(rb_vm_cbase()); - if (NIL_P(klass)) { + if (!klass) { rb_raise(rb_eTypeError, "Can not set autoload on singleton class"); } return rb_mod_autoload(klass, sym, file); @@ -1253,15 +1373,13 @@ rb_f_autoload_p(int argc, VALUE *argv, VALUE obj) void Init_load(void) { -#undef rb_intern -#define rb_intern(str) rb_intern2((str), strlen(str)) rb_vm_t *vm = GET_VM(); static const char var_load_path[] = "$:"; ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1); rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter); - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); + rb_alias_variable(rb_intern_const("$-I"), id_load_path); + rb_alias_variable(rb_intern_const("$LOAD_PATH"), id_load_path); vm->load_path = rb_ary_new(); vm->expanded_load_path = rb_ary_tmp_new(0); vm->load_path_snapshot = rb_ary_tmp_new(0); @@ -1273,6 +1391,8 @@ Init_load(void) vm->loaded_features = rb_ary_new(); vm->loaded_features_snapshot = rb_ary_tmp_new(0); vm->loaded_features_index = st_init_numtable(); + vm->loaded_features_realpaths = rb_hash_new(); + rb_obj_hide(vm->loaded_features_realpaths); rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("require", rb_f_require, 1); diff --git a/ruby/localeinit.c b/ruby/localeinit.c index bec29a6d4..bbcbac832 100644 --- a/ruby/localeinit.c +++ b/ruby/localeinit.c @@ -123,8 +123,9 @@ Init_enc_set_filesystem_encoding(void) idx = ENCINDEX_US_ASCII; #elif defined _WIN32 char cp[SIZEOF_CP_NAME]; - const UINT codepage = ruby_w32_codepage[1] ? ruby_w32_codepage[1] : - AreFileApisANSI() ? GetACP() : GetOEMCP(); + const UINT codepage = ruby_w32_codepage[1]; + if (!codepage) return ENCINDEX_UTF_8; + /* for debugging */ CP_FORMAT(cp, codepage); idx = rb_enc_find_index(cp); if (idx < 0) idx = ENCINDEX_ASCII; diff --git a/ruby/main.c b/ruby/main.c index c1c5b7914..d81cfce87 100644 --- a/ruby/main.c +++ b/ruby/main.c @@ -29,121 +29,10 @@ #if defined RUBY_DEBUG_ENV && !RUBY_DEBUG_ENV # undef RUBY_DEBUG_ENV #endif -#ifdef RUBY_DEBUG_ENV -#include -#endif - -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -#ifdef _WIN32 -#include -#include -#else // ifdef _WIN32 -#include -extern uint8_t _binary_enclose_io_memfs_squashfs_start[]; -#endif // ifdef _WIN32 -extern SQUASH_OS_PATH mkdir_workdir; -extern char *enclose_io_mkdir_scope; -// --------- [Enclose.IO Hack end] --------- int main(int argc, char **argv) { -// --------- [Enclose.IO Hack start] --------- - const uint8_t *enclose_io_memfs = NULL; - int ret; - sqfs_err enclose_io_ret; -#ifdef _WIN32 - BOOL bool_ret; - HRSRC myResource; - HGLOBAL myResourceData; -#else // ifdef _WIN32 - int new_argc; - char **new_argv; - char *argv_memory; - size_t i; - size_t total_argv_size; -#endif // ifdef _WIN32 - -#ifdef _WIN32 - myResource = FindResource(NULL, MAKEINTRESOURCE(101), RT_RCDATA); - assert(NULL != myResource); - myResourceData = LoadResource(NULL, myResource); - assert(NULL != myResourceData); - enclose_io_memfs = (const uint8_t *)(LockResource(myResourceData)); - assert(NULL != enclose_io_memfs); - enclose_io_ret = squash_start(); - assert(SQFS_OK == enclose_io_ret); - enclose_io_fs = malloc(sizeof(sqfs)); - assert(NULL != enclose_io_fs); - memset(enclose_io_fs, 0, sizeof(sqfs)); - enclose_io_ret = sqfs_open_image(enclose_io_fs, enclose_io_memfs, 0); - assert(SQFS_OK == enclose_io_ret); - if (NULL == getenv("ENCLOSE_IO_USE_ORIGINAL_RUBY")) { -#ifdef ENCLOSE_IO_GEMFILE - bool_ret = SetEnvironmentVariable("BUNDLE_GEMFILE", "/__enclose_io_memfs__/local/Gemfile"); - assert(0 != bool_ret); -#endif // ifdef ENCLOSE_IO_GEMFILE -#ifdef ENCLOSE_IO_RAILS - assert(NULL == mkdir_workdir); - enclose_io_mkdir_scope = "/__enclose_io_memfs__/local"; - bool_ret = SetEnvironmentVariable("ENCLOSE_IO_RAILS", "1"); - assert(0 != bool_ret); -#endif // ifdef ENCLOSE_IO_RAILS - } -#else // ifdef _WIN32 - enclose_io_memfs = (const uint8_t *)(_binary_enclose_io_memfs_squashfs_start); - assert(NULL != enclose_io_memfs); - enclose_io_ret = squash_start(); - assert(SQFS_OK == enclose_io_ret); - enclose_io_fs = malloc(sizeof(sqfs)); - assert(NULL != enclose_io_fs); - memset(enclose_io_fs, 0, sizeof(sqfs)); - enclose_io_ret = sqfs_open_image(enclose_io_fs, enclose_io_memfs, 0); - assert(SQFS_OK == enclose_io_ret); -#ifdef ENCLOSE_IO_ENTRANCE - new_argc = argc; - new_argv = argv; - argv_memory = NULL; - if (NULL == getenv("ENCLOSE_IO_USE_ORIGINAL_RUBY")) { -#ifdef ENCLOSE_IO_GEMFILE - ret = setenv("BUNDLE_GEMFILE", "/__enclose_io_memfs__/local/Gemfile", 1); - assert(0 == ret); -#endif // ifdef ENCLOSE_IO_GEMFILE -#ifdef ENCLOSE_IO_RAILS - assert(NULL == mkdir_workdir); - enclose_io_mkdir_scope = "/__enclose_io_memfs__/local"; - ret = setenv("ENCLOSE_IO_RAILS", "1", 1); - assert(0 == ret); -#endif // ifdef ENCLOSE_IO_RAILS - new_argv = (char **)malloc( (argc + 1) * sizeof(char *)); - assert(new_argv); - new_argv[0] = argv[0]; - new_argv[1] = ENCLOSE_IO_ENTRANCE; - for (i = 1; i < argc; ++i) { - new_argv[2 + i - 1] = argv[i]; - } - new_argc = argc + 1; - /* argv memory should be adjacent. */ - total_argv_size = 0; - for (i = 0; i < new_argc; ++i) { - total_argv_size += strlen(new_argv[i]) + 1; - } - argv_memory = (char *)malloc( (total_argv_size) * sizeof(char)); - assert(argv_memory); - for (i = 0; i < new_argc; ++i) { - memcpy(argv_memory, new_argv[i], strlen(new_argv[i]) + 1); - new_argv[i] = argv_memory; - argv_memory += strlen(new_argv[i]) + 1; - } - assert(argv_memory - new_argv[0] == total_argv_size); - argc = new_argc; - argv = new_argv; - } -#endif // ifdef ENCLOSE_IO_ENTRANCE -#endif // ifdef _WIN32 -// --------- [Enclose.IO Hack end] --------- - #ifdef RUBY_DEBUG_ENV ruby_set_debug_option(getenv("RUBY_DEBUG")); #endif @@ -157,4 +46,4 @@ main(int argc, char **argv) ruby_init(); return ruby_run_node(ruby_options(argc, argv)); } -} \ No newline at end of file +} diff --git a/ruby/man/bundle-add.1.txt b/ruby/man/bundle-add.1.txt deleted file mode 100644 index dcd76df4a..000000000 --- a/ruby/man/bundle-add.1.txt +++ /dev/null @@ -1,58 +0,0 @@ -BUNDLE-ADD(1) BUNDLE-ADD(1) - - - -NAME - bundle-add - Add gem to the Gemfile and run bundle install - -SYNOPSIS - bundle add GEM_NAME [--group=GROUP] [--version=VERSION] - [--source=SOURCE] [--git=GIT] [--branch=BRANCH] [--skip-install] - [--strict] [--optimistic] - -DESCRIPTION - Adds the named gem to the Gemfile and run bundle install. bundle - install can be avoided by using the flag --skip-install. - - Example: - - bundle add rails - - bundle add rails --version "< 3.0, > 1.1" - - bundle add rails --version "~> 5.0.0" --source "https://gems.exam- - ple.com" --group "development" - - bundle add rails --skip-install - - bundle add rails --group "development, test" - -OPTIONS - --version, -v - Specify version requirements(s) for the added gem. - - --group, -g - Specify the group(s) for the added gem. Multiple groups should - be separated by commas. - - --source, , -s - Specify the source for the added gem. - - --git Specify the git source for the added gem. - - --branch - Specify the git branch for the added gem. - - --skip-install - Adds the gem to the Gemfile but does not install it. - - --optimistic - Adds optimistic declaration of version - - --strict - Adds strict declaration of version - - - - - January 2020 BUNDLE-ADD(1) diff --git a/ruby/man/bundle-add.ronn b/ruby/man/bundle-add.ronn deleted file mode 100644 index 26cbe5564..000000000 --- a/ruby/man/bundle-add.ronn +++ /dev/null @@ -1,46 +0,0 @@ -bundle-add(1) -- Add gem to the Gemfile and run bundle install -================================================================ - -## SYNOPSIS - -`bundle add` [--group=GROUP] [--version=VERSION] [--source=SOURCE] [--git=GIT] [--branch=BRANCH] [--skip-install] [--strict] [--optimistic] - -## DESCRIPTION -Adds the named gem to the Gemfile and run `bundle install`. `bundle install` can be avoided by using the flag `--skip-install`. - -Example: - -bundle add rails - -bundle add rails --version "< 3.0, > 1.1" - -bundle add rails --version "~> 5.0.0" --source "https://gems.example.com" --group "development" - -bundle add rails --skip-install - -bundle add rails --group "development, test" - -## OPTIONS -* `--version`, `-v`: - Specify version requirements(s) for the added gem. - -* `--group`, `-g`: - Specify the group(s) for the added gem. Multiple groups should be separated by commas. - -* `--source`, , `-s`: - Specify the source for the added gem. - -* `--git`: - Specify the git source for the added gem. - -* `--branch`: - Specify the git branch for the added gem. - -* `--skip-install`: - Adds the gem to the Gemfile but does not install it. - -* `--optimistic`: - Adds optimistic declaration of version - -* `--strict`: - Adds strict declaration of version diff --git a/ruby/man/bundle-binstubs.1.txt b/ruby/man/bundle-binstubs.1.txt deleted file mode 100644 index cbd2b12da..000000000 --- a/ruby/man/bundle-binstubs.1.txt +++ /dev/null @@ -1,48 +0,0 @@ -BUNDLE-BINSTUBS(1) BUNDLE-BINSTUBS(1) - - - -NAME - bundle-binstubs - Install the binstubs of the listed gems - -SYNOPSIS - bundle binstubs GEM_NAME [--force] [--path PATH] [--standalone] - -DESCRIPTION - Binstubs are scripts that wrap around executables. Bundler creates a - small Ruby file (a binstub) that loads Bundler, runs the command, and - puts it into bin/. Binstubs are a shortcut-or alternative- to always - using bundle exec. This gives you a file that can be run directly, and - one that will always run the correct gem version used by the applica- - tion. - - For example, if you run bundle binstubs rspec-core, Bundler will create - the file bin/rspec. That file will contain enough code to load Bundler, - tell it to load the bundled gems, and then run rspec. - - This command generates binstubs for executables in GEM_NAME. Binstubs - are put into bin, or the --path directory if one has been set. Calling - binstubs with [GEM [GEM]] will create binstubs for all given gems. - -OPTIONS - --force - Overwrite existing binstubs if they exist. - - --path The location to install the specified binstubs to. This defaults - to bin. - - --standalone - Makes binstubs that can work without depending on Rubygems or - Bundler at runtime. - - --shebang - Specify a different shebang executable name than the default - (default 'ruby') - -BUNDLE INSTALL --BINSTUBS - To create binstubs for all the gems in the bundle you can use the - --binstubs flag in bundle install(1) bundle-install.1.html. - - - - January 2020 BUNDLE-BINSTUBS(1) diff --git a/ruby/man/bundle-binstubs.ronn b/ruby/man/bundle-binstubs.ronn deleted file mode 100644 index 8909fdc3d..000000000 --- a/ruby/man/bundle-binstubs.ronn +++ /dev/null @@ -1,43 +0,0 @@ -bundle-binstubs(1) -- Install the binstubs of the listed gems -============================================================= - -## SYNOPSIS - -`bundle binstubs` [--force] [--path PATH] [--standalone] - -## DESCRIPTION - -Binstubs are scripts that wrap around executables. Bundler creates a -small Ruby file (a binstub) that loads Bundler, runs the command, -and puts it into `bin/`. Binstubs are a shortcut-or alternative- -to always using `bundle exec`. This gives you a file that can be run -directly, and one that will always run the correct gem version -used by the application. - -For example, if you run `bundle binstubs rspec-core`, Bundler will create -the file `bin/rspec`. That file will contain enough code to load Bundler, -tell it to load the bundled gems, and then run rspec. - -This command generates binstubs for executables in `GEM_NAME`. -Binstubs are put into `bin`, or the `--path` directory if one has been set. -Calling binstubs with [GEM [GEM]] will create binstubs for all given gems. - -## OPTIONS - -* `--force`: - Overwrite existing binstubs if they exist. - -* `--path`: - The location to install the specified binstubs to. This defaults to `bin`. - -* `--standalone`: - Makes binstubs that can work without depending on Rubygems or Bundler at - runtime. - -* `--shebang`: - Specify a different shebang executable name than the default (default 'ruby') - -## BUNDLE INSTALL --BINSTUBS - -To create binstubs for all the gems in the bundle you can use the `--binstubs` -flag in [bundle install(1)](bundle-install.1.html). diff --git a/ruby/man/bundle-cache.1.txt b/ruby/man/bundle-cache.1.txt deleted file mode 100644 index c0b8b5bf0..000000000 --- a/ruby/man/bundle-cache.1.txt +++ /dev/null @@ -1,78 +0,0 @@ -BUNDLE-CACHE(1) BUNDLE-CACHE(1) - - - -NAME - bundle-cache - Package your needed .gem files into your application - -SYNOPSIS - bundle cache - -DESCRIPTION - Copy all of the .gem files needed to run the application into the ven- - dor/cache directory. In the future, when running [bundle - install(1)][bundle-install], use the gems in the cache in preference to - the ones on rubygems.org. - -GIT AND PATH GEMS - The bundle cache command can also package :git and :path dependencies - besides .gem files. This needs to be explicitly enabled via the --all - option. Once used, the --all option will be remembered. - -SUPPORT FOR MULTIPLE PLATFORMS - When using gems that have different packages for different platforms, - Bundler supports caching of gems for other platforms where the Gemfile - has been resolved (i.e. present in the lockfile) in vendor/cache. This - needs to be enabled via the --all-platforms option. This setting will - be remembered in your local bundler configuration. - -REMOTE FETCHING - By default, if you run bundle install(1)](bundle-install.1.html) after - running bundle cache(1) bundle-cache.1.html, bundler will still connect - to rubygems.org to check whether a platform-specific gem exists for any - of the gems in vendor/cache. - - For instance, consider this Gemfile(5): - - - - source "https://rubygems.org" - - gem "nokogiri" - - - - If you run bundle cache under C Ruby, bundler will retrieve the version - of nokogiri for the "ruby" platform. If you deploy to JRuby and run - bundle install, bundler is forced to check to see whether a "java" - platformed nokogiri exists. - - Even though the nokogiri gem for the Ruby platform is technically - acceptable on JRuby, it has a C extension that does not run on JRuby. - As a result, bundler will, by default, still connect to rubygems.org to - check whether it has a version of one of your gems more specific to - your platform. - - This problem is also not limited to the "java" platform. A similar - (common) problem can happen when developing on Windows and deploying to - Linux, or even when developing on OSX and deploying to Linux. - - If you know for sure that the gems packaged in vendor/cache are appro- - priate for the platform you are on, you can run bundle install --local - to skip checking for more appropriate gems, and use the ones in ven- - dor/cache. - - One way to be sure that you have the right platformed versions of all - your gems is to run bundle cache on an identical machine and check in - the gems. For instance, you can run bundle cache on an identical stag- - ing box during your staging process, and check in the vendor/cache - before deploying to production. - - By default, bundle cache(1) bundle-cache.1.html fetches and also - installs the gems to the default location. To package the dependencies - to vendor/cache without installing them to the local install location, - you can run bundle cache --no-install. - - - - January 2020 BUNDLE-CACHE(1) diff --git a/ruby/man/bundle-check.1.txt b/ruby/man/bundle-check.1.txt deleted file mode 100644 index cca5fae9e..000000000 --- a/ruby/man/bundle-check.1.txt +++ /dev/null @@ -1,33 +0,0 @@ -BUNDLE-CHECK(1) BUNDLE-CHECK(1) - - - -NAME - bundle-check - Verifies if dependencies are satisfied by installed gems - -SYNOPSIS - bundle check [--dry-run] [--gemfile=FILE] [--path=PATH] - -DESCRIPTION - check searches the local machine for each of the gems requested in the - Gemfile. If all gems are found, Bundler prints a success message and - exits with a status of 0. - - If not, the first missing gem is listed and Bundler exits status 1. - -OPTIONS - --dry-run - Locks the [Gemfile(5)][Gemfile(5)] before running the command. - - --gemfile - Use the specified gemfile instead of the [Gemfile(5)][Gem- - file(5)]. - - --path Specify a different path than the system default ($BUNDLE_PATH - or $GEM_HOME). Bundler will remember this value for future - installs on this machine. - - - - - January 2020 BUNDLE-CHECK(1) diff --git a/ruby/man/bundle-clean.1.txt b/ruby/man/bundle-clean.1.txt deleted file mode 100644 index 300d0c0b5..000000000 --- a/ruby/man/bundle-clean.1.txt +++ /dev/null @@ -1,26 +0,0 @@ -BUNDLE-CLEAN(1) BUNDLE-CLEAN(1) - - - -NAME - bundle-clean - Cleans up unused gems in your bundler directory - -SYNOPSIS - bundle clean [--dry-run] [--force] - -DESCRIPTION - This command will remove all unused gems in your bundler directory. - This is useful when you have made many changes to your gem dependen- - cies. - -OPTIONS - --dry-run - Print the changes, but do not clean the unused gems. - - --force - Force a clean even if --path is not set. - - - - - January 2020 BUNDLE-CLEAN(1) diff --git a/ruby/man/bundle-config.1.txt b/ruby/man/bundle-config.1.txt deleted file mode 100644 index f5fc0ce12..000000000 --- a/ruby/man/bundle-config.1.txt +++ /dev/null @@ -1,528 +0,0 @@ -BUNDLE-CONFIG(1) BUNDLE-CONFIG(1) - - - -NAME - bundle-config - Set bundler configuration options - -SYNOPSIS - bundle config [list|get|set|unset] [name [value]] - -DESCRIPTION - This command allows you to interact with Bundler's configuration sys- - tem. - - Bundler loads configuration settings in this order: - - 1. Local config (app/.bundle/config) - - 2. Environmental variables (ENV) - - 3. Global config (~/.bundle/config) - - 4. Bundler default config - - - - Executing bundle config list with will print a list of all bundler con- - figuration for the current bundle, and where that configuration was - set. - - Executing bundle config get will print the value of that config- - uration setting, and where it was set. - - Executing bundle config set will set that configuration - to the value specified for all bundles executed as the current user. - The configuration will be stored in ~/.bundle/config. If name already - is set, name will be overridden and user will be warned. - - Executing bundle config set --global works the same as - above. - - Executing bundle config set --local will set that con- - figuration to the local application. The configuration will be stored - in app/.bundle/config. - - Executing bundle config unset will delete the configuration in - both local and global sources. - - Executing bundle config unset --global will delete the configu- - ration only from the user configuration. - - Executing bundle config unset --local will delete the - configuration only from the local application. - - Executing bundle with the BUNDLE_IGNORE_CONFIG environment variable set - will cause it to ignore all configuration. - - Executing bundle config set disable_multisource true upgrades the warn- - ing about the Gemfile containing multiple primary sources to an error. - Executing bundle config unset disable_multisource downgrades this error - to a warning. - -REMEMBERING OPTIONS - Flags passed to bundle install or the Bundler runtime, such as --path - foo or --without production, are remembered between commands and saved - to your local application's configuration (normally, ./.bundle/config). - - However, this will be changed in bundler 3, so it's better not to rely - on this behavior. If these options must be remembered, it's better to - set them using bundle config (e.g., bundle config set path foo). - - The options that can be configured are: - - bin Creates a directory (defaults to ~/bin) and place any executa- - bles from the gem there. These executables run in Bundler's con- - text. If used, you might add this directory to your environ- - ment's PATH variable. For instance, if the rails gem comes with - a rails executable, this flag will create a bin/rails executable - that ensures that all referred dependencies will be resolved - using the bundled gems. - - deployment - In deployment mode, Bundler will 'roll-out' the bundle for pro- - duction use. Please check carefully if you want to have this - option enabled in development or test environments. - - path The location to install the specified gems to. This defaults to - Rubygems' setting. Bundler shares this location with Rubygems, - gem install ... will have gem installed there, too. Therefore, - gems installed without a --path ... setting will show up by - calling gem list. Accordingly, gems installed to other locations - will not get listed. - - without - A space-separated list of groups referencing gems to skip during - installation. - - with A space-separated list of groups referencing gems to include - during installation. - -BUILD OPTIONS - You can use bundle config to give Bundler the flags to pass to the gem - installer every time bundler tries to install a particular gem. - - A very common example, the mysql gem, requires Snow Leopard users to - pass configuration flags to gem install to specify where to find the - mysql_config executable. - - - - gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config - - - - Since the specific location of that executable can change from machine - to machine, you can specify these flags on a per-machine basis. - - - - bundle config set build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config - - - - After running this command, every time bundler needs to install the - mysql gem, it will pass along the flags you specified. - -CONFIGURATION KEYS - Configuration keys in bundler have two forms: the canonical form and - the environment variable form. - - For instance, passing the --without flag to bundle install(1) bun- - dle-install.1.html prevents Bundler from installing certain groups - specified in the Gemfile(5). Bundler persists this value in app/.bun- - dle/config so that calls to Bundler.setup do not try to find gems from - the Gemfile that you didn't install. Additionally, subsequent calls to - bundle install(1) bundle-install.1.html remember this setting and skip - those groups. - - The canonical form of this configuration is "without". To convert the - canonical form to the environment variable form, capitalize it, and - prepend BUNDLE_. The environment variable form of "without" is BUN- - DLE_WITHOUT. - - Any periods in the configuration keys must be replaced with two under- - scores when setting it via environment variables. The configuration key - local.rack becomes the environment variable BUNDLE_LOCAL__RACK. - -LIST OF AVAILABLE KEYS - The following is a list of all configuration keys and their purpose. - You can learn more about their operation in bundle install(1) bun- - dle-install.1.html. - - o allow_bundler_dependency_conflicts (BUNDLE_ALLOW_BUNDLER_DEPEN- - DENCY_CONFLICTS): Allow resolving to specifications that have - dependencies on bundler that are incompatible with the running - Bundler version. - - o allow_deployment_source_credential_changes (BUNDLE_ALLOW_DEPLOY- - MENT_SOURCE_CREDENTIAL_CHANGES): When in deployment mode, allow - changing the credentials to a gem's source. Ex: - https://some.host.com/gems/path/ -> https://user_name:pass- - word@some.host.com/gems/path - - o allow_offline_install (BUNDLE_ALLOW_OFFLINE_INSTALL): Allow Bundler - to use cached data when installing without network access. - - o auto_clean_without_path (BUNDLE_AUTO_CLEAN_WITHOUT_PATH): Automati- - cally run bundle clean after installing when an explicit path has - not been set and Bundler is not installing into the system gems. - - o auto_install (BUNDLE_AUTO_INSTALL): Automatically run bundle - install when gems are missing. - - o bin (BUNDLE_BIN): Install executables from gems in the bundle to - the specified directory. Defaults to false. - - o cache_all (BUNDLE_CACHE_ALL): Cache all gems, including path and - git gems. - - o cache_all_platforms (BUNDLE_CACHE_ALL_PLATFORMS): Cache gems for - all platforms. - - o cache_path (BUNDLE_CACHE_PATH): The directory that bundler will - place cached gems in when running bundle package, and that bundler - will look in when installing gems. Defaults to vendor/cache. - - o clean (BUNDLE_CLEAN): Whether Bundler should run bundle clean auto- - matically after bundle install. - - o console (BUNDLE_CONSOLE): The console that bundle console starts. - Defaults to irb. - - o default_install_uses_path (BUNDLE_DEFAULT_INSTALL_USES_PATH): - Whether a bundle install without an explicit --path argument - defaults to installing gems in .bundle. - - o deployment (BUNDLE_DEPLOYMENT): Disallow changes to the Gemfile. - When the Gemfile is changed and the lockfile has not been updated, - running Bundler commands will be blocked. - - o disable_checksum_validation (BUNDLE_DISABLE_CHECKSUM_VALIDATION): - Allow installing gems even if they do not match the checksum pro- - vided by RubyGems. - - o disable_exec_load (BUNDLE_DISABLE_EXEC_LOAD): Stop Bundler from - using load to launch an executable in-process in bundle exec. - - o disable_local_branch_check (BUNDLE_DISABLE_LOCAL_BRANCH_CHECK): - Allow Bundler to use a local git override without a branch speci- - fied in the Gemfile. - - o disable_multisource (BUNDLE_DISABLE_MULTISOURCE): When set, Gem- - files containing multiple sources will produce errors instead of - warnings. Use bundle config unset disable_multisource to unset. - - o disable_platform_warnings (BUNDLE_DISABLE_PLATFORM_WARNINGS): Dis- - able warnings during bundle install when a dependency is unused on - the current platform. - - o disable_shared_gems (BUNDLE_DISABLE_SHARED_GEMS): Stop Bundler from - accessing gems installed to RubyGems' normal location. - - o disable_version_check (BUNDLE_DISABLE_VERSION_CHECK): Stop Bundler - from checking if a newer Bundler version is available on - rubygems.org. - - o force_ruby_platform (BUNDLE_FORCE_RUBY_PLATFORM): Ignore the cur- - rent machine's platform and install only ruby platform gems. As a - result, gems with native extensions will be compiled from source. - - o frozen (BUNDLE_FROZEN): Disallow changes to the Gemfile. When the - Gemfile is changed and the lockfile has not been updated, running - Bundler commands will be blocked. Defaults to true when --deploy- - ment is used. - - o gem.push_key (BUNDLE_GEM__PUSH_KEY): Sets the --key parameter for - gem push when using the rake release command with a private gem- - stash server. - - o gemfile (BUNDLE_GEMFILE): The name of the file that bundler should - use as the Gemfile. This location of this file also sets the root - of the project, which is used to resolve relative paths in the Gem- - file, among other things. By default, bundler will search up from - the current working directory until it finds a Gemfile. - - o global_gem_cache (BUNDLE_GLOBAL_GEM_CACHE): Whether Bundler should - cache all gems globally, rather than locally to the installing Ruby - installation. - - o ignore_messages (BUNDLE_IGNORE_MESSAGES): When set, no post install - messages will be printed. To silence a single gem, use dot notation - like ignore_messages.httparty true. - - o init_gems_rb (BUNDLE_INIT_GEMS_RB) Generate a gems.rb instead of a - Gemfile when running bundle init. - - o jobs (BUNDLE_JOBS): The number of gems Bundler can install in par- - allel. Defaults to 1. - - o no_install (BUNDLE_NO_INSTALL): Whether bundle package should skip - installing gems. - - o no_prune (BUNDLE_NO_PRUNE): Whether Bundler should leave outdated - gems unpruned when caching. - - o only_update_to_newer_versions (BUNDLE_ONLY_UPDATE_TO_NEWER_VER- - SIONS): During bundle update, only resolve to newer versions of the - gems in the lockfile. - - o path (BUNDLE_PATH): The location on disk where all gems in your - bundle will be located regardless of $GEM_HOME or $GEM_PATH values. - Bundle gems not found in this location will be installed by bundle - install. Defaults to Gem.dir. When --deployment is used, defaults - to vendor/bundle. - - o path.system (BUNDLE_PATH__SYSTEM): Whether Bundler will install - gems into the default system path (Gem.dir). - - o path_relative_to_cwd (BUNDLE_PATH_RELATIVE_TO_CWD) Makes --path - relative to the CWD instead of the Gemfile. - - o plugins (BUNDLE_PLUGINS): Enable Bundler's experimental plugin sys- - tem. - - o prefer_patch (BUNDLE_PREFER_PATCH): Prefer updating only to next - patch version during updates. Makes bundle update calls equivalent - to bundler update --patch. - - o print_only_version_number (BUNDLE_PRINT_ONLY_VERSION_NUMBER) Print - only version number from bundler --version. - - o redirect (BUNDLE_REDIRECT): The number of redirects allowed for - network requests. Defaults to 5. - - o retry (BUNDLE_RETRY): The number of times to retry failed network - requests. Defaults to 3. - - o setup_makes_kernel_gem_public (BUNDLE_SETUP_MAKES_KERNEL_GEM_PUB- - LIC): Have Bundler.setup make the Kernel#gem method public, even - though RubyGems declares it as private. - - o shebang (BUNDLE_SHEBANG): The program name that should be invoked - for generated binstubs. Defaults to the ruby install name used to - generate the binstub. - - o silence_deprecations (BUNDLE_SILENCE_DEPRECATIONS): Whether Bundler - should silence deprecation warnings for behavior that will be - changed in the next major version. - - o silence_root_warning (BUNDLE_SILENCE_ROOT_WARNING): Silence the - warning Bundler prints when installing gems as root. - - o skip_default_git_sources (BUNDLE_SKIP_DEFAULT_GIT_SOURCES): Whether - Bundler should skip adding default git source shortcuts to the Gem- - file DSL. - - o specific_platform (BUNDLE_SPECIFIC_PLATFORM): Allow bundler to - resolve for the specific running platform and store it in the lock- - file, instead of only using a generic platform. A specific platform - is the exact platform triple reported by Gem::Platform.local, such - as x86_64-darwin-16 or universal-java-1.8. On the other hand, - generic platforms are those such as ruby, mswin, or java. In this - example, x86_64-darwin-16 would map to ruby and universal-java-1.8 - to java. - - o ssl_ca_cert (BUNDLE_SSL_CA_CERT): Path to a designated CA certifi- - cate file or folder containing multiple certificates for trusted - CAs in PEM format. - - o ssl_client_cert (BUNDLE_SSL_CLIENT_CERT): Path to a designated file - containing a X.509 client certificate and key in PEM format. - - o ssl_verify_mode (BUNDLE_SSL_VERIFY_MODE): The SSL verification mode - Bundler uses when making HTTPS requests. Defaults to verify peer. - - o suppress_install_using_messages (BUNDLE_SUPPRESS_INSTALL_USING_MES- - SAGES): Avoid printing Using ... messages during installation when - the version of a gem has not changed. - - o system_bindir (BUNDLE_SYSTEM_BINDIR): The location where RubyGems - installs binstubs. Defaults to Gem.bindir. - - o timeout (BUNDLE_TIMEOUT): The seconds allowed before timing out for - network requests. Defaults to 10. - - o unlock_source_unlocks_spec (BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC): - Whether running bundle update --source NAME unlocks a gem with the - given name. Defaults to true. - - o update_requires_all_flag (BUNDLE_UPDATE_REQUIRES_ALL_FLAG) Require - passing --all to bundle update when everything should be updated, - and disallow passing no options to bundle update. - - o user_agent (BUNDLE_USER_AGENT): The custom user agent fragment - Bundler includes in API requests. - - o with (BUNDLE_WITH): A :-separated list of groups whose gems bundler - should install. - - o without (BUNDLE_WITHOUT): A :-separated list of groups whose gems - bundler should not install. - - - - In general, you should set these settings per-application by using the - applicable flag to the bundle install(1) bundle-install.1.html or bun- - dle package(1) bundle-package.1.html command. - - You can set them globally either via environment variables or bundle - config, whichever is preferable for your setup. If you use both, envi- - ronment variables will take preference over global settings. - -LOCAL GIT REPOS - Bundler also allows you to work against a git repository locally - instead of using the remote version. This can be achieved by setting up - a local override: - - - - bundle config set local.GEM_NAME /path/to/local/git/repository - - - - For example, in order to use a local Rack repository, a developer could - call: - - - - bundle config set local.rack ~/Work/git/rack - - - - Now instead of checking out the remote git repository, the local over- - ride will be used. Similar to a path source, every time the local git - repository change, changes will be automatically picked up by Bundler. - This means a commit in the local git repo will update the revision in - the Gemfile.lock to the local git repo revision. This requires the same - attention as git submodules. Before pushing to the remote, you need to - ensure the local override was pushed, otherwise you may point to a com- - mit that only exists in your local machine. You'll also need to CGI - escape your usernames and passwords as well. - - Bundler does many checks to ensure a developer won't work with invalid - references. Particularly, we force a developer to specify a branch in - the Gemfile in order to use this feature. If the branch specified in - the Gemfile and the current branch in the local git repository do not - match, Bundler will abort. This ensures that a developer is always - working against the correct branches, and prevents accidental locking - to a different branch. - - Finally, Bundler also ensures that the current revision in the Gem- - file.lock exists in the local git repository. By doing this, Bundler - forces you to fetch the latest changes in the remotes. - -MIRRORS OF GEM SOURCES - Bundler supports overriding gem sources with mirrors. This allows you - to configure rubygems.org as the gem source in your Gemfile while still - using your mirror to fetch gems. - - - - bundle config set mirror.SOURCE_URL MIRROR_URL - - - - For example, to use a mirror of rubygems.org hosted at rubygems-mir- - ror.org: - - - - bundle config set mirror.http://rubygems.org http://rubygems-mirror.org - - - - Each mirror also provides a fallback timeout setting. If the mirror - does not respond within the fallback timeout, Bundler will try to use - the original server instead of the mirror. - - - - bundle config set mirror.SOURCE_URL.fallback_timeout TIMEOUT - - - - For example, to fall back to rubygems.org after 3 seconds: - - - - bundle config set mirror.https://rubygems.org.fallback_timeout 3 - - - - The default fallback timeout is 0.1 seconds, but the setting can cur- - rently only accept whole seconds (for example, 1, 15, or 30). - -CREDENTIALS FOR GEM SOURCES - Bundler allows you to configure credentials for any gem source, which - allows you to avoid putting secrets into your Gemfile. - - - - bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD - - - - For example, to save the credentials of user claudette for the gem - source at gems.longerous.com, you would run: - - - - bundle config set gems.longerous.com claudette:s00pers3krit - - - - Or you can set the credentials as an environment variable like this: - - - - export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit" - - - - For gems with a git source with HTTP(S) URL you can specify credentials - like so: - - - - bundle config set https://github.com/bundler/bundler.git username:password - - - - Or you can set the credentials as an environment variable like so: - - - - export BUNDLE_GITHUB__COM=username:password - - - - This is especially useful for private repositories on hosts such as - Github, where you can use personal OAuth tokens: - - - - export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic - - - -CONFIGURE BUNDLER DIRECTORIES - Bundler's home, config, cache and plugin directories are able to be - configured through environment variables. The default location for - Bundler's home directory is ~/.bundle, which all directories inherit - from by default. The following outlines the available environment vari- - ables and their default values - - - - BUNDLE_USER_HOME : $HOME/.bundle - BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache - BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config - BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin - - - - - - - January 2020 BUNDLE-CONFIG(1) diff --git a/ruby/man/bundle-config.ronn b/ruby/man/bundle-config.ronn deleted file mode 100644 index 75b389e7e..000000000 --- a/ruby/man/bundle-config.ronn +++ /dev/null @@ -1,399 +0,0 @@ -bundle-config(1) -- Set bundler configuration options -===================================================== - -## SYNOPSIS - -`bundle config` [list|get|set|unset] [ []] - -## DESCRIPTION - -This command allows you to interact with Bundler's configuration system. - -Bundler loads configuration settings in this order: - -1. Local config (`app/.bundle/config`) -2. Environmental variables (`ENV`) -3. Global config (`~/.bundle/config`) -4. Bundler default config - -Executing `bundle config list` with will print a list of all bundler -configuration for the current bundle, and where that configuration -was set. - -Executing `bundle config get ` will print the value of that configuration -setting, and where it was set. - -Executing `bundle config set ` will set that configuration to the -value specified for all bundles executed as the current user. The configuration -will be stored in `~/.bundle/config`. If already is set, will be -overridden and user will be warned. - -Executing `bundle config set --global ` works the same as above. - -Executing `bundle config set --local ` will set that configuration to -the local application. The configuration will be stored in `app/.bundle/config`. - -Executing `bundle config unset ` will delete the configuration in both -local and global sources. - -Executing `bundle config unset --global ` will delete the configuration -only from the user configuration. - -Executing `bundle config unset --local ` will delete the -configuration only from the local application. - -Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will -cause it to ignore all configuration. - -Executing `bundle config set disable_multisource true` upgrades the warning about -the Gemfile containing multiple primary sources to an error. Executing `bundle -config unset disable_multisource` downgrades this error to a warning. - -## REMEMBERING OPTIONS - -Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or -`--without production`, are remembered between commands and saved to your local -application's configuration (normally, `./.bundle/config`). - -However, this will be changed in bundler 3, so it's better not to rely on this -behavior. If these options must be remembered, it's better to set them using -`bundle config` (e.g., `bundle config set path foo`). - -The options that can be configured are: - -* `bin`: - Creates a directory (defaults to `~/bin`) and place any executables from the - gem there. These executables run in Bundler's context. If used, you might add - this directory to your environment's `PATH` variable. For instance, if the - `rails` gem comes with a `rails` executable, this flag will create a - `bin/rails` executable that ensures that all referred dependencies will be - resolved using the bundled gems. - -* `deployment`: - In deployment mode, Bundler will 'roll-out' the bundle for - `production` use. Please check carefully if you want to have this option - enabled in `development` or `test` environments. - -* `path`: - The location to install the specified gems to. This defaults to Rubygems' - setting. Bundler shares this location with Rubygems, `gem install ...` will - have gem installed there, too. Therefore, gems installed without a - `--path ...` setting will show up by calling `gem list`. Accordingly, gems - installed to other locations will not get listed. - -* `without`: - A space-separated list of groups referencing gems to skip during installation. - -* `with`: - A space-separated list of groups referencing gems to include during installation. - -## BUILD OPTIONS - -You can use `bundle config` to give Bundler the flags to pass to the gem -installer every time bundler tries to install a particular gem. - -A very common example, the `mysql` gem, requires Snow Leopard users to -pass configuration flags to `gem install` to specify where to find the -`mysql_config` executable. - - gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config - -Since the specific location of that executable can change from machine -to machine, you can specify these flags on a per-machine basis. - - bundle config set build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config - -After running this command, every time bundler needs to install the -`mysql` gem, it will pass along the flags you specified. - -## CONFIGURATION KEYS - -Configuration keys in bundler have two forms: the canonical form and the -environment variable form. - -For instance, passing the `--without` flag to [bundle install(1)](bundle-install.1.html) -prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler -persists this value in `app/.bundle/config` so that calls to `Bundler.setup` -do not try to find gems from the `Gemfile` that you didn't install. Additionally, -subsequent calls to [bundle install(1)](bundle-install.1.html) remember this setting -and skip those groups. - -The canonical form of this configuration is `"without"`. To convert the canonical -form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The -environment variable form of `"without"` is `BUNDLE_WITHOUT`. - -Any periods in the configuration keys must be replaced with two underscores when -setting it via environment variables. The configuration key `local.rack` becomes -the environment variable `BUNDLE_LOCAL__RACK`. - -## LIST OF AVAILABLE KEYS - -The following is a list of all configuration keys and their purpose. You can -learn more about their operation in [bundle install(1)](bundle-install.1.html). - -* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`): - Allow resolving to specifications that have dependencies on `bundler` that - are incompatible with the running Bundler version. -* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`): - When in deployment mode, allow changing the credentials to a gem's source. - Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path` -* `allow_offline_install` (`BUNDLE_ALLOW_OFFLINE_INSTALL`): - Allow Bundler to use cached data when installing without network access. -* `auto_clean_without_path` (`BUNDLE_AUTO_CLEAN_WITHOUT_PATH`): - Automatically run `bundle clean` after installing when an explicit `path` - has not been set and Bundler is not installing into the system gems. -* `auto_install` (`BUNDLE_AUTO_INSTALL`): - Automatically run `bundle install` when gems are missing. -* `bin` (`BUNDLE_BIN`): - Install executables from gems in the bundle to the specified directory. - Defaults to `false`. -* `cache_all` (`BUNDLE_CACHE_ALL`): - Cache all gems, including path and git gems. -* `cache_all_platforms` (`BUNDLE_CACHE_ALL_PLATFORMS`): - Cache gems for all platforms. -* `cache_path` (`BUNDLE_CACHE_PATH`): - The directory that bundler will place cached gems in when running - bundle package, and that bundler will look in when installing gems. - Defaults to `vendor/cache`. -* `clean` (`BUNDLE_CLEAN`): - Whether Bundler should run `bundle clean` automatically after - `bundle install`. -* `console` (`BUNDLE_CONSOLE`): - The console that `bundle console` starts. Defaults to `irb`. -* `default_install_uses_path` (`BUNDLE_DEFAULT_INSTALL_USES_PATH`): - Whether a `bundle install` without an explicit `--path` argument defaults - to installing gems in `.bundle`. -* `deployment` (`BUNDLE_DEPLOYMENT`): - Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the - lockfile has not been updated, running Bundler commands will be blocked. -* `disable_checksum_validation` (`BUNDLE_DISABLE_CHECKSUM_VALIDATION`): - Allow installing gems even if they do not match the checksum provided by - RubyGems. -* `disable_exec_load` (`BUNDLE_DISABLE_EXEC_LOAD`): - Stop Bundler from using `load` to launch an executable in-process in - `bundle exec`. -* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`): - Allow Bundler to use a local git override without a branch specified in the - Gemfile. -* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`): - When set, Gemfiles containing multiple sources will produce errors - instead of warnings. - Use `bundle config unset disable_multisource` to unset. -* `disable_platform_warnings` (`BUNDLE_DISABLE_PLATFORM_WARNINGS`): - Disable warnings during bundle install when a dependency is unused on the current platform. -* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`): - Stop Bundler from accessing gems installed to RubyGems' normal location. -* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`): - Stop Bundler from checking if a newer Bundler version is available on - rubygems.org. -* `force_ruby_platform` (`BUNDLE_FORCE_RUBY_PLATFORM`): - Ignore the current machine's platform and install only `ruby` platform gems. - As a result, gems with native extensions will be compiled from source. -* `frozen` (`BUNDLE_FROZEN`): - Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the - lockfile has not been updated, running Bundler commands will be blocked. - Defaults to `true` when `--deployment` is used. -* `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`): - Sets the `--key` parameter for `gem push` when using the `rake release` - command with a private gemstash server. -* `gemfile` (`BUNDLE_GEMFILE`): - The name of the file that bundler should use as the `Gemfile`. This location - of this file also sets the root of the project, which is used to resolve - relative paths in the `Gemfile`, among other things. By default, bundler - will search up from the current working directory until it finds a - `Gemfile`. -* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`): - Whether Bundler should cache all gems globally, rather than locally to the - installing Ruby installation. -* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`): When set, no post install - messages will be printed. To silence a single gem, use dot notation like - `ignore_messages.httparty true`. -* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`) - Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`. -* `jobs` (`BUNDLE_JOBS`): - The number of gems Bundler can install in parallel. Defaults to 1. -* `no_install` (`BUNDLE_NO_INSTALL`): - Whether `bundle package` should skip installing gems. -* `no_prune` (`BUNDLE_NO_PRUNE`): - Whether Bundler should leave outdated gems unpruned when caching. -* `only_update_to_newer_versions` (`BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS`): - During `bundle update`, only resolve to newer versions of the gems in the - lockfile. -* `path` (`BUNDLE_PATH`): - The location on disk where all gems in your bundle will be located regardless - of `$GEM_HOME` or `$GEM_PATH` values. Bundle gems not found in this location - will be installed by `bundle install`. Defaults to `Gem.dir`. When --deployment - is used, defaults to vendor/bundle. -* `path.system` (`BUNDLE_PATH__SYSTEM`): - Whether Bundler will install gems into the default system path (`Gem.dir`). -* `path_relative_to_cwd` (`BUNDLE_PATH_RELATIVE_TO_CWD`) - Makes `--path` relative to the CWD instead of the `Gemfile`. -* `plugins` (`BUNDLE_PLUGINS`): - Enable Bundler's experimental plugin system. -* `prefer_patch` (BUNDLE_PREFER_PATCH): - Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`. -* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`) - Print only version number from `bundler --version`. -* `redirect` (`BUNDLE_REDIRECT`): - The number of redirects allowed for network requests. Defaults to `5`. -* `retry` (`BUNDLE_RETRY`): - The number of times to retry failed network requests. Defaults to `3`. -* `setup_makes_kernel_gem_public` (`BUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC`): - Have `Bundler.setup` make the `Kernel#gem` method public, even though - RubyGems declares it as private. -* `shebang` (`BUNDLE_SHEBANG`): - The program name that should be invoked for generated binstubs. Defaults to - the ruby install name used to generate the binstub. -* `silence_deprecations` (`BUNDLE_SILENCE_DEPRECATIONS`): - Whether Bundler should silence deprecation warnings for behavior that will - be changed in the next major version. -* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`): - Silence the warning Bundler prints when installing gems as root. -* `skip_default_git_sources` (`BUNDLE_SKIP_DEFAULT_GIT_SOURCES`): - Whether Bundler should skip adding default git source shortcuts to the - Gemfile DSL. -* `specific_platform` (`BUNDLE_SPECIFIC_PLATFORM`): - Allow bundler to resolve for the specific running platform and store it in - the lockfile, instead of only using a generic platform. - A specific platform is the exact platform triple reported by - `Gem::Platform.local`, such as `x86_64-darwin-16` or `universal-java-1.8`. - On the other hand, generic platforms are those such as `ruby`, `mswin`, or - `java`. In this example, `x86_64-darwin-16` would map to `ruby` and - `universal-java-1.8` to `java`. -* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`): - Path to a designated CA certificate file or folder containing multiple - certificates for trusted CAs in PEM format. -* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`): - Path to a designated file containing a X.509 client certificate - and key in PEM format. -* `ssl_verify_mode` (`BUNDLE_SSL_VERIFY_MODE`): - The SSL verification mode Bundler uses when making HTTPS requests. - Defaults to verify peer. -* `suppress_install_using_messages` (`BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES`): - Avoid printing `Using ...` messages during installation when the version of - a gem has not changed. -* `system_bindir` (`BUNDLE_SYSTEM_BINDIR`): - The location where RubyGems installs binstubs. Defaults to `Gem.bindir`. -* `timeout` (`BUNDLE_TIMEOUT`): - The seconds allowed before timing out for network requests. Defaults to `10`. -* `unlock_source_unlocks_spec` (`BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC`): - Whether running `bundle update --source NAME` unlocks a gem with the given - name. Defaults to `true`. -* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`) - Require passing `--all` to `bundle update` when everything should be updated, - and disallow passing no options to `bundle update`. -* `user_agent` (`BUNDLE_USER_AGENT`): - The custom user agent fragment Bundler includes in API requests. -* `with` (`BUNDLE_WITH`): - A `:`-separated list of groups whose gems bundler should install. -* `without` (`BUNDLE_WITHOUT`): - A `:`-separated list of groups whose gems bundler should not install. - -In general, you should set these settings per-application by using the applicable -flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command. - -You can set them globally either via environment variables or `bundle config`, -whichever is preferable for your setup. If you use both, environment variables -will take preference over global settings. - -## LOCAL GIT REPOS - -Bundler also allows you to work against a git repository locally -instead of using the remote version. This can be achieved by setting -up a local override: - - bundle config set local.GEM_NAME /path/to/local/git/repository - -For example, in order to use a local Rack repository, a developer could call: - - bundle config set local.rack ~/Work/git/rack - -Now instead of checking out the remote git repository, the local -override will be used. Similar to a path source, every time the local -git repository change, changes will be automatically picked up by -Bundler. This means a commit in the local git repo will update the -revision in the `Gemfile.lock` to the local git repo revision. This -requires the same attention as git submodules. Before pushing to -the remote, you need to ensure the local override was pushed, otherwise -you may point to a commit that only exists in your local machine. -You'll also need to CGI escape your usernames and passwords as well. - -Bundler does many checks to ensure a developer won't work with -invalid references. Particularly, we force a developer to specify -a branch in the `Gemfile` in order to use this feature. If the branch -specified in the `Gemfile` and the current branch in the local git -repository do not match, Bundler will abort. This ensures that -a developer is always working against the correct branches, and prevents -accidental locking to a different branch. - -Finally, Bundler also ensures that the current revision in the -`Gemfile.lock` exists in the local git repository. By doing this, Bundler -forces you to fetch the latest changes in the remotes. - -## MIRRORS OF GEM SOURCES - -Bundler supports overriding gem sources with mirrors. This allows you to -configure rubygems.org as the gem source in your Gemfile while still using your -mirror to fetch gems. - - bundle config set mirror.SOURCE_URL MIRROR_URL - -For example, to use a mirror of rubygems.org hosted at rubygems-mirror.org: - - bundle config set mirror.http://rubygems.org http://rubygems-mirror.org - -Each mirror also provides a fallback timeout setting. If the mirror does not -respond within the fallback timeout, Bundler will try to use the original -server instead of the mirror. - - bundle config set mirror.SOURCE_URL.fallback_timeout TIMEOUT - -For example, to fall back to rubygems.org after 3 seconds: - - bundle config set mirror.https://rubygems.org.fallback_timeout 3 - -The default fallback timeout is 0.1 seconds, but the setting can currently -only accept whole seconds (for example, 1, 15, or 30). - -## CREDENTIALS FOR GEM SOURCES - -Bundler allows you to configure credentials for any gem source, which allows -you to avoid putting secrets into your Gemfile. - - bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD - -For example, to save the credentials of user `claudette` for the gem source at -`gems.longerous.com`, you would run: - - bundle config set gems.longerous.com claudette:s00pers3krit - -Or you can set the credentials as an environment variable like this: - - export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit" - -For gems with a git source with HTTP(S) URL you can specify credentials like so: - - bundle config set https://github.com/bundler/bundler.git username:password - -Or you can set the credentials as an environment variable like so: - - export BUNDLE_GITHUB__COM=username:password - -This is especially useful for private repositories on hosts such as Github, -where you can use personal OAuth tokens: - - export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic - - -## CONFIGURE BUNDLER DIRECTORIES - -Bundler's home, config, cache and plugin directories are able to be configured -through environment variables. The default location for Bundler's home directory is -`~/.bundle`, which all directories inherit from by default. The following -outlines the available environment variables and their default values - - BUNDLE_USER_HOME : $HOME/.bundle - BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache - BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config - BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin - diff --git a/ruby/man/bundle-doctor.1.txt b/ruby/man/bundle-doctor.1.txt deleted file mode 100644 index 595ba9963..000000000 --- a/ruby/man/bundle-doctor.1.txt +++ /dev/null @@ -1,44 +0,0 @@ -BUNDLE-DOCTOR(1) BUNDLE-DOCTOR(1) - - - -NAME - bundle-doctor - Checks the bundle for common problems - -SYNOPSIS - bundle doctor [--quiet] [--gemfile=GEMFILE] - -DESCRIPTION - Checks your Gemfile and gem environment for common problems. If issues - are detected, Bundler prints them and exits status 1. Otherwise, - Bundler prints a success message and exits status 0. - - Examples of common problems caught by bundle-doctor include: - - o Invalid Bundler settings - - o Mismatched Ruby versions - - o Mismatched platforms - - o Uninstalled gems - - o Missing dependencies - - - -OPTIONS - --quiet - Only output warnings and errors. - - --gemfile= - The location of the Gemfile(5) which Bundler should use. This - defaults to a Gemfile(5) in the current working directory. In - general, Bundler will assume that the location of the Gemfile(5) - is also the project's root and will try to find Gemfile.lock and - vendor/cache relative to this location. - - - - - January 2020 BUNDLE-DOCTOR(1) diff --git a/ruby/man/bundle-exec.1.txt b/ruby/man/bundle-exec.1.txt deleted file mode 100644 index ebdc2fda7..000000000 --- a/ruby/man/bundle-exec.1.txt +++ /dev/null @@ -1,178 +0,0 @@ -BUNDLE-EXEC(1) BUNDLE-EXEC(1) - - - -NAME - bundle-exec - Execute a command in the context of the bundle - -SYNOPSIS - bundle exec [--keep-file-descriptors] command - -DESCRIPTION - This command executes the command, making all gems specified in the - [Gemfile(5)][Gemfile(5)] available to require in Ruby programs. - - Essentially, if you would normally have run something like rspec - spec/my_spec.rb, and you want to use the gems specified in the [Gem- - file(5)][Gemfile(5)] and installed via bundle install(1) bun- - dle-install.1.html, you should run bundle exec rspec spec/my_spec.rb. - - Note that bundle exec does not require that an executable is available - on your shell's $PATH. - -OPTIONS - --keep-file-descriptors - Exec in Ruby 2.0 began discarding non-standard file descriptors. - When this flag is passed, exec will revert to the 1.9 behaviour - of passing all file descriptors to the new process. - -BUNDLE INSTALL --BINSTUBS - If you use the --binstubs flag in bundle install(1) bun- - dle-install.1.html, Bundler will automatically create a directory - (which defaults to app_root/bin) containing all of the executables - available from gems in the bundle. - - After using --binstubs, bin/rspec spec/my_spec.rb is identical to bun- - dle exec rspec spec/my_spec.rb. - -ENVIRONMENT MODIFICATIONS - bundle exec makes a number of changes to the shell environment, then - executes the command you specify in full. - - o make sure that it's still possible to shell out to bundle from - inside a command invoked by bundle exec (using $BUNDLE_BIN_PATH) - - o put the directory containing executables (like rails, rspec, - rackup) for your bundle on $PATH - - o make sure that if bundler is invoked in the subshell, it uses the - same Gemfile (by setting BUNDLE_GEMFILE) - - o add -rbundler/setup to $RUBYOPT, which makes sure that Ruby pro- - grams invoked in the subshell can see the gems in the bundle - - - - It also modifies Rubygems: - - o disallow loading additional gems not in the bundle - - o modify the gem method to be a no-op if a gem matching the require- - ments is in the bundle, and to raise a Gem::LoadError if it's not - - o Define Gem.refresh to be a no-op, since the source index is always - frozen when using bundler, and to prevent gems from the system - leaking into the environment - - o Override Gem.bin_path to use the gems in the bundle, making system - executables work - - o Add all gems in the bundle into Gem.loaded_specs - - - - Finally, bundle exec also implicitly modifies Gemfile.lock if the lock- - file and the Gemfile do not match. Bundler needs the Gemfile to deter- - mine things such as a gem's groups, autorequire, and platforms, etc., - and that information isn't stored in the lockfile. The Gemfile and - lockfile must be synced in order to bundle exec successfully, so bundle - exec updates the lockfile beforehand. - - Loading - By default, when attempting to bundle exec to a file with a ruby she- - bang, Bundler will Kernel.load that file instead of using Kernel.exec. - For the vast majority of cases, this is a performance improvement. In a - rare few cases, this could cause some subtle side-effects (such as - dependence on the exact contents of $0 or __FILE__) and the optimiza- - tion can be disabled by enabling the disable_exec_load setting. - - Shelling out - Any Ruby code that opens a subshell (like system, backticks, or %x{}) - will automatically use the current Bundler environment. If you need to - shell out to a Ruby command that is not part of your current bundle, - use the with_clean_env method with a block. Any subshells created - inside the block will be given the environment present before Bundler - was activated. For example, Homebrew commands run Ruby, but don't work - inside a bundle: - - - - Bundler.with_clean_env do - `brew install wget` - end - - - - Using with_clean_env is also necessary if you are shelling out to a - different bundle. Any Bundler commands run in a subshell will inherit - the current Gemfile, so commands that need to run in the context of a - different bundle also need to use with_clean_env. - - - - Bundler.with_clean_env do - Dir.chdir "/other/bundler/project" do - `bundle exec ./script` - end - end - - - - Bundler provides convenience helpers that wrap system and exec, and - they can be used like this: - - - - Bundler.clean_system('brew install wget') - Bundler.clean_exec('brew install wget') - - - -RUBYGEMS PLUGINS - At present, the Rubygems plugin system requires all files named - rubygems_plugin.rb on the load path of any installed gem when any Ruby - code requires rubygems.rb. This includes executables installed into the - system, like rails, rackup, and rspec. - - Since Rubygems plugins can contain arbitrary Ruby code, they commonly - end up activating themselves or their dependencies. - - For instance, the gemcutter 0.5 gem depended on json_pure. If you had - that version of gemcutter installed (even if you also had a newer ver- - sion without this problem), Rubygems would activate gemcutter 0.5 and - json_pure . - - If your Gemfile(5) also contained json_pure (or a gem with a dependency - on json_pure), the latest version on your system might conflict with - the version in your Gemfile(5), or the snapshot version in your Gem- - file.lock. - - If this happens, bundler will say: - - - - You have already activated json_pure 1.4.6 but your Gemfile - requires json_pure 1.4.3. Consider using bundle exec. - - - - In this situation, you almost certainly want to remove the underlying - gem with the problematic gem plugin. In general, the authors of these - plugins (in this case, the gemcutter gem) have released newer versions - that are more careful in their plugins. - - You can find a list of all the gems containing gem plugins by running - - - - ruby -rrubygems -e "puts Gem.find_files('rubygems_plugin.rb')" - - - - At the very least, you should remove all but the newest version of each - gem plugin, and also remove all gem plugins that you aren't using (gem - uninstall gem_name). - - - - January 2020 BUNDLE-EXEC(1) diff --git a/ruby/man/bundle-gem.1 b/ruby/man/bundle-gem.1 deleted file mode 100644 index baed185e7..000000000 --- a/ruby/man/bundle-gem.1 +++ /dev/null @@ -1,80 +0,0 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "BUNDLE\-GEM" "1" "January 2020" "" "" -. -.SH "NAME" -\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem -. -.SH "SYNOPSIS" -\fBbundle gem\fR \fIGEM_NAME\fR \fIOPTIONS\fR -. -.SH "DESCRIPTION" -Generates a directory named \fBGEM_NAME\fR with a \fBRakefile\fR, \fBGEM_NAME\.gemspec\fR, and other supporting files and directories that can be used to develop a rubygem with that name\. -. -.P -Run \fBrake \-T\fR in the resulting project for a list of Rake tasks that can be used to test and publish the gem to rubygems\.org\. -. -.P -The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler\'s global configuration file using the following names: -. -.IP "\(bu" 4 -\fBgem\.coc\fR -. -.IP "\(bu" 4 -\fBgem\.mit\fR -. -.IP "\(bu" 4 -\fBgem\.test\fR -. -.IP "" 0 -. -.SH "OPTIONS" -. -.TP -\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR -Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\. -. -.TP -\fB\-\-no\-exe\fR -Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\. -. -.TP -\fB\-\-coc\fR -Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. -. -.TP -\fB\-\-no\-coc\fR -Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\. -. -.TP -\fB\-\-ext\fR -Add boilerplate for C extension code to the generated project\. This behavior is disabled by default\. -. -.TP -\fB\-\-no\-ext\fR -Do not add C extension code (overrides \fB\-\-ext\fR specified in the global config)\. -. -.TP -\fB\-\-mit\fR -Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. -. -.TP -\fB\-\-no\-mit\fR -Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\. -. -.TP -\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR -Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR and \fBrspec\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. If no option is specified, the default testing framework is RSpec\. -. -.TP -\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR -Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\. -. -.SH "SEE ALSO" -. -.IP "\(bu" 4 -bundle config(1) \fIbundle\-config\.1\.html\fR -. -.IP "" 0 - diff --git a/ruby/man/bundle-gem.1.txt b/ruby/man/bundle-gem.1.txt deleted file mode 100644 index 554bb1a41..000000000 --- a/ruby/man/bundle-gem.1.txt +++ /dev/null @@ -1,91 +0,0 @@ -BUNDLE-GEM(1) BUNDLE-GEM(1) - - - -NAME - bundle-gem - Generate a project skeleton for creating a rubygem - -SYNOPSIS - bundle gem GEM_NAME OPTIONS - -DESCRIPTION - Generates a directory named GEM_NAME with a Rakefile, GEM_NAME.gemspec, - and other supporting files and directories that can be used to develop - a rubygem with that name. - - Run rake -T in the resulting project for a list of Rake tasks that can - be used to test and publish the gem to rubygems.org. - - The generated project skeleton can be customized with OPTIONS, as - explained below. Note that these options can also be specified via - Bundler's global configuration file using the following names: - - o gem.coc - - o gem.mit - - o gem.test - - - -OPTIONS - --exe or -b or --bin - Specify that Bundler should create a binary executable (as - exe/GEM_NAME) in the generated rubygem project. This binary will - also be added to the GEM_NAME.gemspec manifest. This behavior is - disabled by default. - - --no-exe - Do not create a binary (overrides --exe specified in the global - config). - - --coc Add a CODE_OF_CONDUCT.md file to the root of the generated - project. If this option is unspecified, an interactive prompt - will be displayed and the answer will be saved in Bundler's - global config for future bundle gem use. - - --no-coc - Do not create a CODE_OF_CONDUCT.md (overrides --coc specified in - the global config). - - --ext Add boilerplate for C extension code to the generated project. - This behavior is disabled by default. - - --no-ext - Do not add C extension code (overrides --ext specified in the - global config). - - --mit Add an MIT license to a LICENSE.txt file in the root of the gen- - erated project. Your name from the global git config is used for - the copyright statement. If this option is unspecified, an - interactive prompt will be displayed and the answer will be - saved in Bundler's global config for future bundle gem use. - - --no-mit - Do not create a LICENSE.txt (overrides --mit specified in the - global config). - - -t, --test=minitest, --test=rspec - Specify the test framework that Bundler should use when generat- - ing the project. Acceptable values are minitest and rspec. The - GEM_NAME.gemspec will be configured and a skeleton test/spec - directory will be created based on this option. If this option - is unspecified, an interactive prompt will be displayed and the - answer will be saved in Bundler's global config for future bun- - dle gem use. If no option is specified, the default testing - framework is RSpec. - - -e, --edit[=EDITOR] - Open the resulting GEM_NAME.gemspec in EDITOR, or the default - editor if not specified. The default is $BUNDLER_EDITOR, $VIS- - UAL, or $EDITOR. - -SEE ALSO - o bundle config(1) bundle-config.1.html - - - - - - - January 2020 BUNDLE-GEM(1) diff --git a/ruby/man/bundle-gem.ronn b/ruby/man/bundle-gem.ronn deleted file mode 100644 index cf3d037df..000000000 --- a/ruby/man/bundle-gem.ronn +++ /dev/null @@ -1,78 +0,0 @@ -bundle-gem(1) -- Generate a project skeleton for creating a rubygem -==================================================================== - -## SYNOPSIS - -`bundle gem` [OPTIONS] - -## DESCRIPTION - -Generates a directory named `GEM_NAME` with a `Rakefile`, `GEM_NAME.gemspec`, -and other supporting files and directories that can be used to develop a -rubygem with that name. - -Run `rake -T` in the resulting project for a list of Rake tasks that can be used -to test and publish the gem to rubygems.org. - -The generated project skeleton can be customized with OPTIONS, as explained -below. Note that these options can also be specified via Bundler's global -configuration file using the following names: - -* `gem.coc` -* `gem.mit` -* `gem.test` - -## OPTIONS - -* `--exe` or `-b` or `--bin`: - Specify that Bundler should create a binary executable (as `exe/GEM_NAME`) - in the generated rubygem project. This binary will also be added to the - `GEM_NAME.gemspec` manifest. This behavior is disabled by default. - -* `--no-exe`: - Do not create a binary (overrides `--exe` specified in the global config). - -* `--coc`: - Add a `CODE_OF_CONDUCT.md` file to the root of the generated project. If - this option is unspecified, an interactive prompt will be displayed and the - answer will be saved in Bundler's global config for future `bundle gem` use. - -* `--no-coc`: - Do not create a `CODE_OF_CONDUCT.md` (overrides `--coc` specified in the - global config). - -* `--ext`: - Add boilerplate for C extension code to the generated project. This behavior - is disabled by default. - -* `--no-ext`: - Do not add C extension code (overrides `--ext` specified in the global - config). - -* `--mit`: - Add an MIT license to a `LICENSE.txt` file in the root of the generated - project. Your name from the global git config is used for the copyright - statement. If this option is unspecified, an interactive prompt will be - displayed and the answer will be saved in Bundler's global config for future - `bundle gem` use. - -* `--no-mit`: - Do not create a `LICENSE.txt` (overrides `--mit` specified in the global - config). - -* `-t`, `--test=minitest`, `--test=rspec`: - Specify the test framework that Bundler should use when generating the - project. Acceptable values are `minitest` and `rspec`. The `GEM_NAME.gemspec` - will be configured and a skeleton test/spec directory will be created based - on this option. If this option is unspecified, an interactive prompt will be - displayed and the answer will be saved in Bundler's global config for future - `bundle gem` use. - If no option is specified, the default testing framework is RSpec. - -* `-e`, `--edit[=EDITOR]`: - Open the resulting GEM_NAME.gemspec in EDITOR, or the default editor if not - specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`. - -## SEE ALSO - -* [bundle config(1)](bundle-config.1.html) diff --git a/ruby/man/bundle-info.1.txt b/ruby/man/bundle-info.1.txt deleted file mode 100644 index 67563aa19..000000000 --- a/ruby/man/bundle-info.1.txt +++ /dev/null @@ -1,21 +0,0 @@ -BUNDLE-INFO(1) BUNDLE-INFO(1) - - - -NAME - bundle-info - Show information for the given gem in your bundle - -SYNOPSIS - bundle info [GEM] [--path] - -DESCRIPTION - Print the basic information about the provided GEM such as homepage, - version, path and summary. - -OPTIONS - --path Print the path of the given gem - - - - - January 2020 BUNDLE-INFO(1) diff --git a/ruby/man/bundle-init.1.txt b/ruby/man/bundle-init.1.txt deleted file mode 100644 index 2565edbec..000000000 --- a/ruby/man/bundle-init.1.txt +++ /dev/null @@ -1,34 +0,0 @@ -BUNDLE-INIT(1) BUNDLE-INIT(1) - - - -NAME - bundle-init - Generates a Gemfile into the current working directory - -SYNOPSIS - bundle init [--gemspec=FILE] - -DESCRIPTION - Init generates a default [Gemfile(5)][Gemfile(5)] in the current work- - ing directory. When adding a [Gemfile(5)][Gemfile(5)] to a gem with a - gemspec, the --gemspec option will automatically add each dependency - listed in the gemspec file to the newly created [Gemfile(5)][Gem- - file(5)]. - -OPTIONS - --gemspec - Use the specified .gemspec to create the [Gemfile(5)][Gem- - file(5)] - -FILES - Included in the default [Gemfile(5)][Gemfile(5)] generated is the line - # frozen_string_literal: true. This is a magic comment supported for - the first time in Ruby 2.3. The presence of this line results in all - string literals in the file being implicitly frozen. - -SEE ALSO - Gemfile(5) https://bundler.io/man/gemfile.5.html - - - - January 2020 BUNDLE-INIT(1) diff --git a/ruby/man/bundle-inject.1.txt b/ruby/man/bundle-inject.1.txt deleted file mode 100644 index 4707b99e5..000000000 --- a/ruby/man/bundle-inject.1.txt +++ /dev/null @@ -1,32 +0,0 @@ -BUNDLE-INJECT(1) BUNDLE-INJECT(1) - - - -NAME - bundle-inject - Add named gem(s) with version requirements to Gemfile - -SYNOPSIS - bundle inject [GEM] [VERSION] - -DESCRIPTION - Adds the named gem(s) with their version requirements to the resolved - [Gemfile(5)][Gemfile(5)]. - - This command will add the gem to both your [Gemfile(5)][Gemfile(5)] and - Gemfile.lock if it isn't listed yet. - - Example: - - - - bundle install - bundle inject 'rack' '> 0' - - - - This will inject the 'rack' gem with a version greater than 0 in your - [Gemfile(5)][Gemfile(5)] and Gemfile.lock - - - - January 2020 BUNDLE-INJECT(1) diff --git a/ruby/man/bundle-install.1.txt b/ruby/man/bundle-install.1.txt deleted file mode 100644 index b1a9ad1eb..000000000 --- a/ruby/man/bundle-install.1.txt +++ /dev/null @@ -1,401 +0,0 @@ -BUNDLE-INSTALL(1) BUNDLE-INSTALL(1) - - - -NAME - bundle-install - Install the dependencies specified in your Gemfile - -SYNOPSIS - bundle install [--binstubs[=DIRECTORY]] [--clean] [--deployment] - [--frozen] [--full-index] [--gemfile=GEMFILE] [--jobs=NUMBER] [--local] - [--no-cache] [--no-prune] [--path PATH] [--quiet] [--redownload] - [--retry=NUMBER] [--shebang] [--standalone[=GROUP[ GROUP...]]] [--sys- - tem] [--trust-policy=POLICY] [--with=GROUP[ GROUP...]] [--with- - out=GROUP[ GROUP...]] - -DESCRIPTION - Install the gems specified in your Gemfile(5). If this is the first - time you run bundle install (and a Gemfile.lock does not exist), - Bundler will fetch all remote sources, resolve dependencies and install - all needed gems. - - If a Gemfile.lock does exist, and you have not updated your Gemfile(5), - Bundler will fetch all remote sources, but use the dependencies speci- - fied in the Gemfile.lock instead of resolving dependencies. - - If a Gemfile.lock does exist, and you have updated your Gemfile(5), - Bundler will use the dependencies in the Gemfile.lock for all gems that - you did not update, but will re-resolve the dependencies of gems that - you did update. You can find more information about this update process - below under CONSERVATIVE UPDATING. - -OPTIONS - To apply any of --binstubs, --deployment, --path, or --without every - time bundle install is run, use bundle config (see bundle-config(1)). - - --binstubs[=] - Binstubs are scripts that wrap around executables. Bundler cre- - ates a small Ruby file (a binstub) that loads Bundler, runs the - command, and puts it in bin/. This lets you link the binstub - inside of an application to the exact gem version the applica- - tion needs. - - Creates a directory (defaults to ~/bin) and places any executa- - bles from the gem there. These executables run in Bundler's con- - text. If used, you might add this directory to your environ- - ment's PATH variable. For instance, if the rails gem comes with - a rails executable, this flag will create a bin/rails executable - that ensures that all referred dependencies will be resolved - using the bundled gems. - - --clean - On finishing the installation Bundler is going to remove any - gems not present in the current Gemfile(5). Don't worry, gems - currently in use will not be removed. - - --deployment - In deployment mode, Bundler will 'roll-out' the bundle for pro- - duction or CI use. Please check carefully if you want to have - this option enabled in your development environment. - - --redownload - Force download every gem, even if the required versions are - already available locally. - - --frozen - Do not allow the Gemfile.lock to be updated after this install. - Exits non-zero if there are going to be changes to the Gem- - file.lock. - - --full-index - Bundler will not call Rubygems' API endpoint (default) but down- - load and cache a (currently big) index file of all gems. Perfor- - mance can be improved for large bundles that seldom change by - enabling this option. - - --gemfile= - The location of the Gemfile(5) which Bundler should use. This - defaults to a Gemfile(5) in the current working directory. In - general, Bundler will assume that the location of the Gemfile(5) - is also the project's root and will try to find Gemfile.lock and - vendor/cache relative to this location. - - --jobs=[], -j[] - The maximum number of parallel download and install jobs. The - default is 1. - - --local - Do not attempt to connect to rubygems.org. Instead, Bundler will - use the gems already present in Rubygems' cache or in ven- - dor/cache. Note that if a appropriate platform-specific gem - exists on rubygems.org it will not be found. - - --no-cache - Do not update the cache in vendor/cache with the newly bundled - gems. This does not remove any gems in the cache but keeps the - newly bundled gems from being cached during the install. - - --no-prune - Don't remove stale gems from the cache when the installation - finishes. - - --path= - The location to install the specified gems to. This defaults to - Rubygems' setting. Bundler shares this location with Rubygems, - gem install ... will have gem installed there, too. Therefore, - gems installed without a --path ... setting will show up by - calling gem list. Accordingly, gems installed to other locations - will not get listed. - - --quiet - Do not print progress information to the standard output. - Instead, Bundler will exit using a status code ($?). - - --retry=[] - Retry failed network or git requests for number times. - - --shebang= - Uses the specified ruby executable (usually ruby) to execute the - scripts created with --binstubs. In addition, if you use --bin- - stubs together with --shebang jruby these executables will be - changed to execute jruby instead. - - --standalone[=] - Makes a bundle that can work without depending on Rubygems or - Bundler at runtime. A space separated list of groups to install - has to be specified. Bundler creates a directory named bundle - and installs the bundle there. It also generates a bun- - dle/bundler/setup.rb file to replace Bundler's own setup in the - manner required. Using this option implicitly sets path, which - is a [remembered option][REMEMBERED OPTIONS]. - - --system - Installs the gems specified in the bundle to the system's - Rubygems location. This overrides any previous configuration of - --path. - - --trust-policy=[] - Apply the Rubygems security policy policy, where policy is one - of HighSecurity, MediumSecurity, LowSecurity, AlmostNoSecurity, - or NoSecurity. For more details, please see the Rubygems signing - documentation linked below in SEE ALSO. - - --with= - A space-separated list of groups referencing gems to install. If - an optional group is given it is installed. If a group is given - that is in the remembered list of groups given to --without, it - is removed from that list. - - --without= - A space-separated list of groups referencing gems to skip during - installation. If a group is given that is in the remembered list - of groups given to --with, it is removed from that list. - -DEPLOYMENT MODE - Bundler's defaults are optimized for development. To switch to defaults - optimized for deployment and for CI, use the --deployment flag. Do not - activate deployment mode on development machines, as it will cause an - error when the Gemfile(5) is modified. - - 1. A Gemfile.lock is required. - - To ensure that the same versions of the gems you developed with and - tested with are also used in deployments, a Gemfile.lock is - required. - - This is mainly to ensure that you remember to check your Gem- - file.lock into version control. - - 2. The Gemfile.lock must be up to date - - In development, you can modify your Gemfile(5) and re-run bundle - install to conservatively update your Gemfile.lock snapshot. - - In deployment, your Gemfile.lock should be up-to-date with changes - made in your Gemfile(5). - - 3. Gems are installed to vendor/bundle not your default system loca- - tion - - In development, it's convenient to share the gems used in your - application with other applications and other scripts that run on - the system. - - In deployment, isolation is a more important default. In addition, - the user deploying the application may not have permission to - install gems to the system, or the web server may not have permis- - sion to read them. - - As a result, bundle install --deployment installs gems to the ven- - dor/bundle directory in the application. This may be overridden - using the --path option. - - - -SUDO USAGE - By default, Bundler installs gems to the same location as gem install. - - In some cases, that location may not be writable by your Unix user. In - that case, Bundler will stage everything in a temporary directory, then - ask you for your sudo password in order to copy the gems into their - system location. - - From your perspective, this is identical to installing the gems - directly into the system. - - You should never use sudo bundle install. This is because several other - steps in bundle install must be performed as the current user: - - o Updating your Gemfile.lock - - o Updating your vendor/cache, if necessary - - o Checking out private git repositories using your user's SSH keys - - - - Of these three, the first two could theoretically be performed by - chowning the resulting files to $SUDO_USER. The third, however, can - only be performed by invoking the git command as the current user. - Therefore, git gems are downloaded and installed into ~/.bundle rather - than $GEM_HOME or $BUNDLE_PATH. - - As a result, you should run bundle install as the current user, and - Bundler will ask for your password if it is needed to put the gems into - their final location. - -INSTALLING GROUPS - By default, bundle install will install all gems in all groups in your - Gemfile(5), except those declared for a different platform. - - However, you can explicitly tell Bundler to skip installing certain - groups with the --without option. This option takes a space-separated - list of groups. - - While the --without option will skip installing the gems in the speci- - fied groups, it will still download those gems and use them to resolve - the dependencies of every gem in your Gemfile(5). - - This is so that installing a different set of groups on another machine - (such as a production server) will not change the gems and versions - that you have already developed and tested against. - - Bundler offers a rock-solid guarantee that the third-party code you are - running in development and testing is also the third-party code you are - running in production. You can choose to exclude some of that code in - different environments, but you will never be caught flat-footed by - different versions of third-party code being used in different environ- - ments. - - For a simple illustration, consider the following Gemfile(5): - - - - source 'https://rubygems.org' - - gem 'sinatra' - - group :production do - gem 'rack-perftools-profiler' - end - - - - In this case, sinatra depends on any version of Rack (>= 1.0), while - rack-perftools-profiler depends on 1.x (~> 1.0). - - When you run bundle install --without production in development, we - look at the dependencies of rack-perftools-profiler as well. That way, - you do not spend all your time developing against Rack 2.0, using new - APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2 - when the production group is used. - - This should not cause any problems in practice, because we do not - attempt to install the gems in the excluded groups, and only evaluate - as part of the dependency resolution process. - - This also means that you cannot include different versions of the same - gem in different groups, because doing so would result in different - sets of dependencies used in development and production. Because of the - vagaries of the dependency resolution process, this usually affects - more than the gems you list in your Gemfile(5), and can (surprisingly) - radically change the gems you are using. - -THE GEMFILE.LOCK - When you run bundle install, Bundler will persist the full names and - versions of all gems that you used (including dependencies of the gems - specified in the Gemfile(5)) into a file called Gemfile.lock. - - Bundler uses this file in all subsequent calls to bundle install, which - guarantees that you always use the same exact code, even as your appli- - cation moves across machines. - - Because of the way dependency resolution works, even a seemingly small - change (for instance, an update to a point-release of a dependency of a - gem in your Gemfile(5)) can result in radically different gems being - needed to satisfy all dependencies. - - As a result, you SHOULD check your Gemfile.lock into version control, - in both applications and gems. If you do not, every machine that checks - out your repository (including your production server) will resolve all - dependencies again, which will result in different versions of - third-party code being used if any of the gems in the Gemfile(5) or any - of their dependencies have been updated. - - When Bundler first shipped, the Gemfile.lock was included in the .git- - ignore file included with generated gems. Over time, however, it became - clear that this practice forces the pain of broken dependencies onto - new contributors, while leaving existing contributors potentially - unaware of the problem. Since bundle install is usually the first step - towards a contribution, the pain of broken dependencies would discour- - age new contributors from contributing. As a result, we have revised - our guidance for gem authors to now recommend checking in the lock for - gems. - -CONSERVATIVE UPDATING - When you make a change to the Gemfile(5) and then run bundle install, - Bundler will update only the gems that you modified. - - In other words, if a gem that you did not modify worked before you - called bundle install, it will continue to use the exact same versions - of all dependencies as it used before the update. - - Let's take a look at an example. Here's your original Gemfile(5): - - - - source 'https://rubygems.org' - - gem 'actionpack', '2.3.8' - gem 'activemerchant' - - - - In this case, both actionpack and activemerchant depend on activesup- - port. The actionpack gem depends on activesupport 2.3.8 and rack ~> - 1.1.0, while the activemerchant gem depends on activesupport >= 2.3.2, - braintree >= 2.0.0, and builder >= 2.0.0. - - When the dependencies are first resolved, Bundler will select - activesupport 2.3.8, which satisfies the requirements of both gems in - your Gemfile(5). - - Next, you modify your Gemfile(5) to: - - - - source 'https://rubygems.org' - - gem 'actionpack', '3.0.0.rc' - gem 'activemerchant' - - - - The actionpack 3.0.0.rc gem has a number of new dependencies, and - updates the activesupport dependency to = 3.0.0.rc and the rack depen- - dency to ~> 1.2.1. - - When you run bundle install, Bundler notices that you changed the - actionpack gem, but not the activemerchant gem. It evaluates the gems - currently being used to satisfy its requirements: - - activesupport 2.3.8 - also used to satisfy a dependency in activemerchant, which is - not being updated - - rack ~> 1.1.0 - not currently being used to satisfy another dependency - - Because you did not explicitly ask to update activemerchant, you would - not expect it to suddenly stop working after updating actionpack. How- - ever, satisfying the new activesupport 3.0.0.rc dependency of action- - pack requires updating one of its dependencies. - - Even though activemerchant declares a very loose dependency that theo- - retically matches activesupport 3.0.0.rc, Bundler treats gems in your - Gemfile(5) that have not changed as an atomic unit together with their - dependencies. In this case, the activemerchant dependency is treated as - activemerchant 1.7.1 + activesupport 2.3.8, so bundle install will - report that it cannot update actionpack. - - To explicitly update actionpack, including its dependencies which other - gems in the Gemfile(5) still depend on, run bundle update actionpack - (see bundle update(1)). - - Summary: In general, after making a change to the Gemfile(5) , you - should first try to run bundle install, which will guarantee that no - other gem in the Gemfile(5) is impacted by the change. If that does not - work, run bundle update(1) bundle-update.1.html. - -SEE ALSO - o Gem install docs - http://guides.rubygems.org/rubygems-basics/#installing-gems - - o Rubygems signing docs http://guides.rubygems.org/security/ - - - - - - - January 2020 BUNDLE-INSTALL(1) diff --git a/ruby/man/bundle-install.ronn b/ruby/man/bundle-install.ronn deleted file mode 100644 index 2ba82f27a..000000000 --- a/ruby/man/bundle-install.ronn +++ /dev/null @@ -1,383 +0,0 @@ -bundle-install(1) -- Install the dependencies specified in your Gemfile -======================================================================= - -## SYNOPSIS - -`bundle install` [--binstubs[=DIRECTORY]] - [--clean] - [--deployment] - [--frozen] - [--full-index] - [--gemfile=GEMFILE] - [--jobs=NUMBER] - [--local] - [--no-cache] - [--no-prune] - [--path PATH] - [--quiet] - [--redownload] - [--retry=NUMBER] - [--shebang] - [--standalone[=GROUP[ GROUP...]]] - [--system] - [--trust-policy=POLICY] - [--with=GROUP[ GROUP...]] - [--without=GROUP[ GROUP...]] - -## DESCRIPTION - -Install the gems specified in your Gemfile(5). If this is the first -time you run bundle install (and a `Gemfile.lock` does not exist), -Bundler will fetch all remote sources, resolve dependencies and -install all needed gems. - -If a `Gemfile.lock` does exist, and you have not updated your Gemfile(5), -Bundler will fetch all remote sources, but use the dependencies -specified in the `Gemfile.lock` instead of resolving dependencies. - -If a `Gemfile.lock` does exist, and you have updated your Gemfile(5), -Bundler will use the dependencies in the `Gemfile.lock` for all gems -that you did not update, but will re-resolve the dependencies of -gems that you did update. You can find more information about this -update process below under [CONSERVATIVE UPDATING][]. - -## OPTIONS - -To apply any of `--binstubs`, `--deployment`, `--path`, or `--without` every -time `bundle install` is run, use `bundle config` (see bundle-config(1)). - -* `--binstubs[=]`: - Binstubs are scripts that wrap around executables. Bundler creates a small Ruby - file (a binstub) that loads Bundler, runs the command, and puts it in `bin/`. - This lets you link the binstub inside of an application to the exact gem - version the application needs. - - Creates a directory (defaults to `~/bin`) and places any executables from the - gem there. These executables run in Bundler's context. If used, you might add - this directory to your environment's `PATH` variable. For instance, if the - `rails` gem comes with a `rails` executable, this flag will create a - `bin/rails` executable that ensures that all referred dependencies will be - resolved using the bundled gems. - -* `--clean`: - On finishing the installation Bundler is going to remove any gems not present - in the current Gemfile(5). Don't worry, gems currently in use will not be - removed. - -* `--deployment`: - In [deployment mode][DEPLOYMENT MODE], Bundler will 'roll-out' the bundle for - production or CI use. Please check carefully if you want to have this option - enabled in your development environment. - -* `--redownload`: - Force download every gem, even if the required versions are already available - locally. - -* `--frozen`: - Do not allow the Gemfile.lock to be updated after this install. Exits - non-zero if there are going to be changes to the Gemfile.lock. - -* `--full-index`: - Bundler will not call Rubygems' API endpoint (default) but download and cache - a (currently big) index file of all gems. Performance can be improved for - large bundles that seldom change by enabling this option. - -* `--gemfile=`: - The location of the Gemfile(5) which Bundler should use. This defaults - to a Gemfile(5) in the current working directory. In general, Bundler - will assume that the location of the Gemfile(5) is also the project's - root and will try to find `Gemfile.lock` and `vendor/cache` relative - to this location. - -* `--jobs=[]`, `-j[]`: - The maximum number of parallel download and install jobs. The default - is `1`. - -* `--local`: - Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the - gems already present in Rubygems' cache or in `vendor/cache`. Note that if a - appropriate platform-specific gem exists on `rubygems.org` it will not be - found. - -* `--no-cache`: - Do not update the cache in `vendor/cache` with the newly bundled gems. This - does not remove any gems in the cache but keeps the newly bundled gems from - being cached during the install. - -* `--no-prune`: - Don't remove stale gems from the cache when the installation finishes. - -* `--path=`: - The location to install the specified gems to. This defaults to Rubygems' - setting. Bundler shares this location with Rubygems, `gem install ...` will - have gem installed there, too. Therefore, gems installed without a - `--path ...` setting will show up by calling `gem list`. Accordingly, gems - installed to other locations will not get listed. - -* `--quiet`: - Do not print progress information to the standard output. Instead, Bundler - will exit using a status code (`$?`). - -* `--retry=[]`: - Retry failed network or git requests for times. - -* `--shebang=`: - Uses the specified ruby executable (usually `ruby`) to execute the scripts - created with `--binstubs`. In addition, if you use `--binstubs` together with - `--shebang jruby` these executables will be changed to execute `jruby` - instead. - -* `--standalone[=]`: - Makes a bundle that can work without depending on Rubygems or Bundler at - runtime. A space separated list of groups to install has to be specified. - Bundler creates a directory named `bundle` and installs the bundle there. It - also generates a `bundle/bundler/setup.rb` file to replace Bundler's own setup - in the manner required. Using this option implicitly sets `path`, which is a - [remembered option][REMEMBERED OPTIONS]. - -* `--system`: - Installs the gems specified in the bundle to the system's Rubygems location. - This overrides any previous configuration of `--path`. - -* `--trust-policy=[]`: - Apply the Rubygems security policy , where policy is one of - `HighSecurity`, `MediumSecurity`, `LowSecurity`, `AlmostNoSecurity`, or - `NoSecurity`. For more details, please see the Rubygems signing documentation - linked below in [SEE ALSO][]. - -* `--with=`: - A space-separated list of groups referencing gems to install. If an - optional group is given it is installed. If a group is given that is - in the remembered list of groups given to --without, it is removed - from that list. - -* `--without=`: - A space-separated list of groups referencing gems to skip during installation. - If a group is given that is in the remembered list of groups given - to --with, it is removed from that list. - -## DEPLOYMENT MODE - -Bundler's defaults are optimized for development. To switch to -defaults optimized for deployment and for CI, use the `--deployment` -flag. Do not activate deployment mode on development machines, as it -will cause an error when the Gemfile(5) is modified. - -1. A `Gemfile.lock` is required. - - To ensure that the same versions of the gems you developed with - and tested with are also used in deployments, a `Gemfile.lock` - is required. - - This is mainly to ensure that you remember to check your - `Gemfile.lock` into version control. - -2. The `Gemfile.lock` must be up to date - - In development, you can modify your Gemfile(5) and re-run - `bundle install` to [conservatively update][CONSERVATIVE UPDATING] - your `Gemfile.lock` snapshot. - - In deployment, your `Gemfile.lock` should be up-to-date with - changes made in your Gemfile(5). - -3. Gems are installed to `vendor/bundle` not your default system location - - In development, it's convenient to share the gems used in your - application with other applications and other scripts that run on - the system. - - In deployment, isolation is a more important default. In addition, - the user deploying the application may not have permission to install - gems to the system, or the web server may not have permission to - read them. - - As a result, `bundle install --deployment` installs gems to - the `vendor/bundle` directory in the application. This may be - overridden using the `--path` option. - -## SUDO USAGE - -By default, Bundler installs gems to the same location as `gem install`. - -In some cases, that location may not be writable by your Unix user. In -that case, Bundler will stage everything in a temporary directory, -then ask you for your `sudo` password in order to copy the gems into -their system location. - -From your perspective, this is identical to installing the gems -directly into the system. - -You should never use `sudo bundle install`. This is because several -other steps in `bundle install` must be performed as the current user: - -* Updating your `Gemfile.lock` -* Updating your `vendor/cache`, if necessary -* Checking out private git repositories using your user's SSH keys - -Of these three, the first two could theoretically be performed by -`chown`ing the resulting files to `$SUDO_USER`. The third, however, -can only be performed by invoking the `git` command as -the current user. Therefore, git gems are downloaded and installed -into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH. - -As a result, you should run `bundle install` as the current user, -and Bundler will ask for your password if it is needed to put the -gems into their final location. - -## INSTALLING GROUPS - -By default, `bundle install` will install all gems in all groups -in your Gemfile(5), except those declared for a different platform. - -However, you can explicitly tell Bundler to skip installing -certain groups with the `--without` option. This option takes -a space-separated list of groups. - -While the `--without` option will skip _installing_ the gems in the -specified groups, it will still _download_ those gems and use them to -resolve the dependencies of every gem in your Gemfile(5). - -This is so that installing a different set of groups on another - machine (such as a production server) will not change the -gems and versions that you have already developed and tested against. - -`Bundler offers a rock-solid guarantee that the third-party -code you are running in development and testing is also the -third-party code you are running in production. You can choose -to exclude some of that code in different environments, but you -will never be caught flat-footed by different versions of -third-party code being used in different environments.` - -For a simple illustration, consider the following Gemfile(5): - - source 'https://rubygems.org' - - gem 'sinatra' - - group :production do - gem 'rack-perftools-profiler' - end - -In this case, `sinatra` depends on any version of Rack (`>= 1.0`), while -`rack-perftools-profiler` depends on 1.x (`~> 1.0`). - -When you run `bundle install --without production` in development, we -look at the dependencies of `rack-perftools-profiler` as well. That way, -you do not spend all your time developing against Rack 2.0, using new -APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2 -when the `production` group _is_ used. - -This should not cause any problems in practice, because we do not -attempt to `install` the gems in the excluded groups, and only evaluate -as part of the dependency resolution process. - -This also means that you cannot include different versions of the same -gem in different groups, because doing so would result in different -sets of dependencies used in development and production. Because of -the vagaries of the dependency resolution process, this usually -affects more than the gems you list in your Gemfile(5), and can -(surprisingly) radically change the gems you are using. - -## THE GEMFILE.LOCK - -When you run `bundle install`, Bundler will persist the full names -and versions of all gems that you used (including dependencies of -the gems specified in the Gemfile(5)) into a file called `Gemfile.lock`. - -Bundler uses this file in all subsequent calls to `bundle install`, -which guarantees that you always use the same exact code, even -as your application moves across machines. - -Because of the way dependency resolution works, even a -seemingly small change (for instance, an update to a point-release -of a dependency of a gem in your Gemfile(5)) can result in radically -different gems being needed to satisfy all dependencies. - -As a result, you `SHOULD` check your `Gemfile.lock` into version -control, in both applications and gems. If you do not, every machine that -checks out your repository (including your production server) will resolve all -dependencies again, which will result in different versions of -third-party code being used if `any` of the gems in the Gemfile(5) -or any of their dependencies have been updated. - -When Bundler first shipped, the `Gemfile.lock` was included in the `.gitignore` -file included with generated gems. Over time, however, it became clear that -this practice forces the pain of broken dependencies onto new contributors, -while leaving existing contributors potentially unaware of the problem. Since -`bundle install` is usually the first step towards a contribution, the pain of -broken dependencies would discourage new contributors from contributing. As a -result, we have revised our guidance for gem authors to now recommend checking -in the lock for gems. - -## CONSERVATIVE UPDATING - -When you make a change to the Gemfile(5) and then run `bundle install`, -Bundler will update only the gems that you modified. - -In other words, if a gem that you `did not modify` worked before -you called `bundle install`, it will continue to use the exact -same versions of all dependencies as it used before the update. - -Let's take a look at an example. Here's your original Gemfile(5): - - source 'https://rubygems.org' - - gem 'actionpack', '2.3.8' - gem 'activemerchant' - -In this case, both `actionpack` and `activemerchant` depend on -`activesupport`. The `actionpack` gem depends on `activesupport 2.3.8` -and `rack ~> 1.1.0`, while the `activemerchant` gem depends on -`activesupport >= 2.3.2`, `braintree >= 2.0.0`, and `builder >= 2.0.0`. - -When the dependencies are first resolved, Bundler will select -`activesupport 2.3.8`, which satisfies the requirements of both -gems in your Gemfile(5). - -Next, you modify your Gemfile(5) to: - - source 'https://rubygems.org' - - gem 'actionpack', '3.0.0.rc' - gem 'activemerchant' - -The `actionpack 3.0.0.rc` gem has a number of new dependencies, -and updates the `activesupport` dependency to `= 3.0.0.rc` and -the `rack` dependency to `~> 1.2.1`. - -When you run `bundle install`, Bundler notices that you changed -the `actionpack` gem, but not the `activemerchant` gem. It -evaluates the gems currently being used to satisfy its requirements: - - * `activesupport 2.3.8`: - also used to satisfy a dependency in `activemerchant`, - which is not being updated - * `rack ~> 1.1.0`: - not currently being used to satisfy another dependency - -Because you did not explicitly ask to update `activemerchant`, -you would not expect it to suddenly stop working after updating -`actionpack`. However, satisfying the new `activesupport 3.0.0.rc` -dependency of actionpack requires updating one of its dependencies. - -Even though `activemerchant` declares a very loose dependency -that theoretically matches `activesupport 3.0.0.rc`, Bundler treats -gems in your Gemfile(5) that have not changed as an atomic unit -together with their dependencies. In this case, the `activemerchant` -dependency is treated as `activemerchant 1.7.1 + activesupport 2.3.8`, -so `bundle install` will report that it cannot update `actionpack`. - -To explicitly update `actionpack`, including its dependencies -which other gems in the Gemfile(5) still depend on, run -`bundle update actionpack` (see `bundle update(1)`). - -`Summary`: In general, after making a change to the Gemfile(5) , you -should first try to run `bundle install`, which will guarantee that no -other gem in the Gemfile(5) is impacted by the change. If that -does not work, run [bundle update(1)](bundle-update.1.html). - -## SEE ALSO - -* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems) -* [Rubygems signing docs](http://guides.rubygems.org/security/) diff --git a/ruby/man/bundle-list.1 b/ruby/man/bundle-list.1 deleted file mode 100644 index 72bc391ac..000000000 --- a/ruby/man/bundle-list.1 +++ /dev/null @@ -1,50 +0,0 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "BUNDLE\-LIST" "1" "January 2020" "" "" -. -.SH "NAME" -\fBbundle\-list\fR \- List all the gems in the bundle -. -.SH "SYNOPSIS" -\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP] [\-\-only\-group=GROUP] -. -.SH "DESCRIPTION" -Prints a list of all the gems in the bundle including their version\. -. -.P -Example: -. -.P -bundle list \-\-name\-only -. -.P -bundle list \-\-paths -. -.P -bundle list \-\-without\-group test -. -.P -bundle list \-\-only\-group dev -. -.P -bundle list \-\-only\-group dev \-\-paths -. -.SH "OPTIONS" -. -.TP -\fB\-\-name\-only\fR -Print only the name of each gem\. -. -.TP -\fB\-\-paths\fR -Print the path to each gem in the bundle\. -. -.TP -\fB\-\-without\-group\fR -Print all gems expect from a group\. -. -.TP -\fB\-\-only\-group\fR -Print gems from a particular group\. - diff --git a/ruby/man/bundle-list.1.txt b/ruby/man/bundle-list.1.txt deleted file mode 100644 index 645e62e45..000000000 --- a/ruby/man/bundle-list.1.txt +++ /dev/null @@ -1,43 +0,0 @@ -BUNDLE-LIST(1) BUNDLE-LIST(1) - - - -NAME - bundle-list - List all the gems in the bundle - -SYNOPSIS - bundle list [--name-only] [--paths] [--without-group=GROUP] - [--only-group=GROUP] - -DESCRIPTION - Prints a list of all the gems in the bundle including their version. - - Example: - - bundle list --name-only - - bundle list --paths - - bundle list --without-group test - - bundle list --only-group dev - - bundle list --only-group dev --paths - -OPTIONS - --name-only - Print only the name of each gem. - - --paths - Print the path to each gem in the bundle. - - --without-group - Print all gems expect from a group. - - --only-group - Print gems from a particular group. - - - - - January 2020 BUNDLE-LIST(1) diff --git a/ruby/man/bundle-list.ronn b/ruby/man/bundle-list.ronn deleted file mode 100644 index 120cf5e30..000000000 --- a/ruby/man/bundle-list.ronn +++ /dev/null @@ -1,33 +0,0 @@ -bundle-list(1) -- List all the gems in the bundle -========================================================================= - -## SYNOPSIS - -`bundle list` [--name-only] [--paths] [--without-group=GROUP] [--only-group=GROUP] - -## DESCRIPTION - -Prints a list of all the gems in the bundle including their version. - -Example: - -bundle list --name-only - -bundle list --paths - -bundle list --without-group test - -bundle list --only-group dev - -bundle list --only-group dev --paths - -## OPTIONS - -* `--name-only`: - Print only the name of each gem. -* `--paths`: - Print the path to each gem in the bundle. -* `--without-group`: - Print all gems expect from a group. -* `--only-group`: - Print gems from a particular group. diff --git a/ruby/man/bundle-lock.1.txt b/ruby/man/bundle-lock.1.txt deleted file mode 100644 index 80dcada5b..000000000 --- a/ruby/man/bundle-lock.1.txt +++ /dev/null @@ -1,93 +0,0 @@ -BUNDLE-LOCK(1) BUNDLE-LOCK(1) - - - -NAME - bundle-lock - Creates / Updates a lockfile without installing - -SYNOPSIS - bundle lock [--update] [--local] [--print] [--lockfile=PATH] - [--full-index] [--add-platform] [--remove-platform] [--patch] [--minor] - [--major] [--strict] [--conservative] - -DESCRIPTION - Lock the gems specified in Gemfile. - -OPTIONS - --update=<*gems> - Ignores the existing lockfile. Resolve then updates lockfile. - Taking a list of gems or updating all gems if no list is given. - - --local - Do not attempt to connect to rubygems.org. Instead, Bundler will - use the gems already present in Rubygems' cache or in ven- - dor/cache. Note that if a appropriate platform-specific gem - exists on rubygems.org it will not be found. - - --print - Prints the lockfile to STDOUT instead of writing to the file - system. - - --lockfile= - The path where the lockfile should be written to. - - --full-index - Fall back to using the single-file index of all gems. - - --add-platform - Add a new platform to the lockfile, re-resolving for the addi- - tion of that platform. - - --remove-platform - Remove a platform from the lockfile. - - --patch - If updating, prefer updating only to next patch version. - - --minor - If updating, prefer updating only to next minor version. - - --major - If updating, prefer updating to next major version (default). - - --strict - If updating, do not allow any gem to be updated past latest - --patch | --minor | --major. - - --conservative - If updating, use bundle install conservative update behavior and - do not allow shared dependencies to be updated. - -UPDATING ALL GEMS - If you run bundle lock with --update option without list of gems, - bundler will ignore any previously installed gems and resolve all - dependencies again based on the latest versions of all gems available - in the sources. - -UPDATING A LIST OF GEMS - Sometimes, you want to update a single gem in the Gemfile(5), and leave - the rest of the gems that you specified locked to the versions in the - Gemfile.lock. - - For instance, you only want to update nokogiri, run bundle lock - --update nokogiri. - - Bundler will update nokogiri and any of its dependencies, but leave the - rest of the gems that you specified locked to the versions in the Gem- - file.lock. - -SUPPORTING OTHER PLATFORMS - If you want your bundle to support platforms other than the one you're - running locally, you can run bundle lock --add-platform PLATFORM to add - PLATFORM to the lockfile, force bundler to re-resolve and consider the - new platform when picking gems, all without needing to have a machine - that matches PLATFORM handy to install those platform-specific gems on. - - For a full explanation of gem platforms, see gem help platform. - -PATCH LEVEL OPTIONS - See bundle update(1) bundle-update.1.html for details. - - - - January 2020 BUNDLE-LOCK(1) diff --git a/ruby/man/bundle-open.1.txt b/ruby/man/bundle-open.1.txt deleted file mode 100644 index 288bbce0e..000000000 --- a/ruby/man/bundle-open.1.txt +++ /dev/null @@ -1,29 +0,0 @@ -BUNDLE-OPEN(1) BUNDLE-OPEN(1) - - - -NAME - bundle-open - Opens the source directory for a gem in your bundle - -SYNOPSIS - bundle open [GEM] - -DESCRIPTION - Opens the source directory of the provided GEM in your editor. - - For this to work the EDITOR or BUNDLER_EDITOR environment variable has - to be set. - - Example: - - - - bundle open 'rack' - - - - Will open the source directory for the 'rack' gem in your bundle. - - - - January 2020 BUNDLE-OPEN(1) diff --git a/ruby/man/bundle-outdated.1.txt b/ruby/man/bundle-outdated.1.txt deleted file mode 100644 index c938e0a4a..000000000 --- a/ruby/man/bundle-outdated.1.txt +++ /dev/null @@ -1,131 +0,0 @@ -BUNDLE-OUTDATED(1) BUNDLE-OUTDATED(1) - - - -NAME - bundle-outdated - List installed gems with newer versions available - -SYNOPSIS - bundle outdated [GEM] [--local] [--pre] [--source] [--strict] - [--parseable | --porcelain] [--group=GROUP] [--groups] - [--update-strict] [--patch|--minor|--major] [--filter-major] [--fil- - ter-minor] [--filter-patch] [--only-explicit] - -DESCRIPTION - Outdated lists the names and versions of gems that have a newer version - available in the given source. Calling outdated with [GEM [GEM]] will - only check for newer versions of the given gems. Prerelease gems are - ignored by default. If your gems are up to date, Bundler will exit with - a status of 0. Otherwise, it will exit 1. - -OPTIONS - --local - Do not attempt to fetch gems remotely and use the gem cache - instead. - - --pre Check for newer pre-release gems. - - --source - Check against a specific source. - - --strict - Only list newer versions allowed by your Gemfile requirements. - - --parseable, --porcelain - Use minimal formatting for more parseable output. - - --group - List gems from a specific group. - - --groups - List gems organized by groups. - - --update-strict - Strict conservative resolution, do not allow any gem to be - updated past latest --patch | --minor| --major. - - --minor - Prefer updating only to next minor version. - - --major - Prefer updating to next major version (default). - - --patch - Prefer updating only to next patch version. - - --filter-major - Only list major newer versions. - - --filter-minor - Only list minor newer versions. - - --filter-patch - Only list patch newer versions. - - --only-explicit - Only list gems specified in your Gemfile, not their dependen- - cies. - -PATCH LEVEL OPTIONS - See bundle update(1) bundle-update.1.html for details. - - One difference between the patch level options in bundle update and - here is the --strict option. --strict was already an option on outdated - before the patch level options were added. --strict wasn't altered, and - the --update-strict option on outdated reflects what --strict does on - bundle update. - -FILTERING OUTPUT - The 3 filtering options do not affect the resolution of versions, - merely what versions are shown in the output. - - If the regular output shows the following: - - - - * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test" - * hashie (newest 3.4.6, installed 1.2.0, requested = 1.2.0) in groups "default" - * headless (newest 2.3.1, installed 2.2.3) in groups "test" - - - - --filter-major would only show: - - - - * hashie (newest 3.4.6, installed 1.2.0, requested = 1.2.0) in groups "default" - - - - --filter-minor would only show: - - - - * headless (newest 2.3.1, installed 2.2.3) in groups "test" - - - - --filter-patch would only show: - - - - * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test" - - - - Filter options can be combined. --filter-minor and --filter-patch would - show: - - - - * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test" - * headless (newest 2.3.1, installed 2.2.3) in groups "test" - - - - Combining all three filter options would be the same result as provid- - ing none of them. - - - - January 2020 BUNDLE-OUTDATED(1) diff --git a/ruby/man/bundle-package.1 b/ruby/man/bundle-package.1 deleted file mode 100644 index 142f298cf..000000000 --- a/ruby/man/bundle-package.1 +++ /dev/null @@ -1,55 +0,0 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "BUNDLE\-PACKAGE" "1" "September 2019" "" "" -. -.SH "NAME" -\fBbundle\-package\fR \- Package your needed \fB\.gem\fR files into your application -. -.SH "SYNOPSIS" -\fBbundle package\fR -. -.SH "DESCRIPTION" -Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\. -. -.SH "GIT AND PATH GEMS" -Since Bundler 1\.2, the \fBbundle package\fR command can also package \fB:git\fR and \fB:path\fR dependencies besides \.gem files\. This needs to be explicitly enabled via the \fB\-\-all\fR option\. Once used, the \fB\-\-all\fR option will be remembered\. -. -.SH "SUPPORT FOR MULTIPLE PLATFORMS" -When using gems that have different packages for different platforms, Bundler 1\.8 and newer support caching of gems for other platforms where the Gemfile has been resolved (i\.e\. present in the lockfile) in \fBvendor/cache\fR\. This needs to be enabled via the \fB\-\-all\-platforms\fR option\. This setting will be remembered in your local bundler configuration\. -. -.SH "REMOTE FETCHING" -By default, if you run \fBbundle install(1)\fR](bundle\-install\.1\.html) after running bundle package(1) \fIbundle\-package\.1\.html\fR, bundler will still connect to \fBrubygems\.org\fR to check whether a platform\-specific gem exists for any of the gems in \fBvendor/cache\fR\. -. -.P -For instance, consider this Gemfile(5): -. -.IP "" 4 -. -.nf - -source "https://rubygems\.org" - -gem "nokogiri" -. -.fi -. -.IP "" 0 -. -.P -If you run \fBbundle package\fR under C Ruby, bundler will retrieve the version of \fBnokogiri\fR for the \fB"ruby"\fR platform\. If you deploy to JRuby and run \fBbundle install\fR, bundler is forced to check to see whether a \fB"java"\fR platformed \fBnokogiri\fR exists\. -. -.P -Even though the \fBnokogiri\fR gem for the Ruby platform is \fItechnically\fR acceptable on JRuby, it has a C extension that does not run on JRuby\. As a result, bundler will, by default, still connect to \fBrubygems\.org\fR to check whether it has a version of one of your gems more specific to your platform\. -. -.P -This problem is also not limited to the \fB"java"\fR platform\. A similar (common) problem can happen when developing on Windows and deploying to Linux, or even when developing on OSX and deploying to Linux\. -. -.P -If you know for sure that the gems packaged in \fBvendor/cache\fR are appropriate for the platform you are on, you can run \fBbundle install \-\-local\fR to skip checking for more appropriate gems, and use the ones in \fBvendor/cache\fR\. -. -.P -One way to be sure that you have the right platformed versions of all your gems is to run \fBbundle package\fR on an identical machine and check in the gems\. For instance, you can run \fBbundle package\fR on an identical staging box during your staging process, and check in the \fBvendor/cache\fR before deploying to production\. -. -.P -By default, bundle package(1) \fIbundle\-package\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle package \-\-no\-install\fR\. diff --git a/ruby/man/bundle-package.1.txt b/ruby/man/bundle-package.1.txt deleted file mode 100644 index ff4068b3b..000000000 --- a/ruby/man/bundle-package.1.txt +++ /dev/null @@ -1,79 +0,0 @@ -BUNDLE-PACKAGE(1) BUNDLE-PACKAGE(1) - - - -NAME - bundle-package - Package your needed .gem files into your application - -SYNOPSIS - bundle package - -DESCRIPTION - Copy all of the .gem files needed to run the application into the ven- - dor/cache directory. In the future, when running [bundle - install(1)][bundle-install], use the gems in the cache in preference to - the ones on rubygems.org. - -GIT AND PATH GEMS - Since Bundler 1.2, the bundle package command can also package :git and - :path dependencies besides .gem files. This needs to be explicitly - enabled via the --all option. Once used, the --all option will be - remembered. - -SUPPORT FOR MULTIPLE PLATFORMS - When using gems that have different packages for different platforms, - Bundler 1.8 and newer support caching of gems for other platforms where - the Gemfile has been resolved (i.e. present in the lockfile) in ven- - dor/cache. This needs to be enabled via the --all-platforms option. - This setting will be remembered in your local bundler configuration. - -REMOTE FETCHING - By default, if you run bundle install(1)](bundle-install.1.html) after - running bundle package(1) bundle-package.1.html, bundler will still - connect to rubygems.org to check whether a platform-specific gem exists - for any of the gems in vendor/cache. - - For instance, consider this Gemfile(5): - - - - source "https://rubygems.org" - - gem "nokogiri" - - - - If you run bundle package under C Ruby, bundler will retrieve the ver- - sion of nokogiri for the "ruby" platform. If you deploy to JRuby and - run bundle install, bundler is forced to check to see whether a "java" - platformed nokogiri exists. - - Even though the nokogiri gem for the Ruby platform is technically - acceptable on JRuby, it has a C extension that does not run on JRuby. - As a result, bundler will, by default, still connect to rubygems.org to - check whether it has a version of one of your gems more specific to - your platform. - - This problem is also not limited to the "java" platform. A similar - (common) problem can happen when developing on Windows and deploying to - Linux, or even when developing on OSX and deploying to Linux. - - If you know for sure that the gems packaged in vendor/cache are appro- - priate for the platform you are on, you can run bundle install --local - to skip checking for more appropriate gems, and use the ones in ven- - dor/cache. - - One way to be sure that you have the right platformed versions of all - your gems is to run bundle package on an identical machine and check in - the gems. For instance, you can run bundle package on an identical - staging box during your staging process, and check in the vendor/cache - before deploying to production. - - By default, bundle package(1) bundle-package.1.html fetches and also - installs the gems to the default location. To package the dependencies - to vendor/cache without installing them to the local install location, - you can run bundle package --no-install. - - - - September 2019 BUNDLE-PACKAGE(1) diff --git a/ruby/man/bundle-package.ronn b/ruby/man/bundle-package.ronn deleted file mode 100644 index bc137374d..000000000 --- a/ruby/man/bundle-package.ronn +++ /dev/null @@ -1,72 +0,0 @@ -bundle-package(1) -- Package your needed `.gem` files into your application -=========================================================================== - -## SYNOPSIS - -`bundle package` - -## DESCRIPTION - -Copy all of the `.gem` files needed to run the application into the -`vendor/cache` directory. In the future, when running [bundle install(1)][bundle-install], -use the gems in the cache in preference to the ones on `rubygems.org`. - -## GIT AND PATH GEMS - -Since Bundler 1.2, the `bundle package` command can also package `:git` and -`:path` dependencies besides .gem files. This needs to be explicitly enabled -via the `--all` option. Once used, the `--all` option will be remembered. - -## SUPPORT FOR MULTIPLE PLATFORMS - -When using gems that have different packages for different platforms, Bundler -1.8 and newer support caching of gems for other platforms where the Gemfile -has been resolved (i.e. present in the lockfile) in `vendor/cache`. This needs -to be enabled via the `--all-platforms` option. This setting will be remembered -in your local bundler configuration. - -## REMOTE FETCHING - -By default, if you run `bundle install(1)`](bundle-install.1.html) after running -[bundle package(1)](bundle-package.1.html), bundler will still connect to `rubygems.org` -to check whether a platform-specific gem exists for any of the gems -in `vendor/cache`. - -For instance, consider this Gemfile(5): - - source "https://rubygems.org" - - gem "nokogiri" - -If you run `bundle package` under C Ruby, bundler will retrieve -the version of `nokogiri` for the `"ruby"` platform. If you deploy -to JRuby and run `bundle install`, bundler is forced to check to -see whether a `"java"` platformed `nokogiri` exists. - -Even though the `nokogiri` gem for the Ruby platform is -_technically_ acceptable on JRuby, it has a C extension -that does not run on JRuby. As a result, bundler will, by default, -still connect to `rubygems.org` to check whether it has a version -of one of your gems more specific to your platform. - -This problem is also not limited to the `"java"` platform. -A similar (common) problem can happen when developing on Windows -and deploying to Linux, or even when developing on OSX and -deploying to Linux. - -If you know for sure that the gems packaged in `vendor/cache` -are appropriate for the platform you are on, you can run -`bundle install --local` to skip checking for more appropriate -gems, and use the ones in `vendor/cache`. - -One way to be sure that you have the right platformed versions -of all your gems is to run `bundle package` on an identical -machine and check in the gems. For instance, you can run -`bundle package` on an identical staging box during your -staging process, and check in the `vendor/cache` before -deploying to production. - -By default, [bundle package(1)](bundle-package.1.html) fetches and also -installs the gems to the default location. To package the -dependencies to `vendor/cache` without installing them to the -local install location, you can run `bundle package --no-install`. diff --git a/ruby/man/bundle-platform.1.txt b/ruby/man/bundle-platform.1.txt deleted file mode 100644 index f9dc8ccc1..000000000 --- a/ruby/man/bundle-platform.1.txt +++ /dev/null @@ -1,57 +0,0 @@ -BUNDLE-PLATFORM(1) BUNDLE-PLATFORM(1) - - - -NAME - bundle-platform - Displays platform compatibility information - -SYNOPSIS - bundle platform [--ruby] - -DESCRIPTION - platform will display information from your Gemfile, Gemfile.lock, and - Ruby VM about your platform. - - For instance, using this Gemfile(5): - - - - source "https://rubygems.org" - - ruby "1.9.3" - - gem "rack" - - - - If you run bundle platform on Ruby 1.9.3, it will display the following - output: - - - - Your platform is: x86_64-linux - - Your app has gems that work on these platforms: - * ruby - - Your Gemfile specifies a Ruby version requirement: - * ruby 1.9.3 - - Your current platform satisfies the Ruby version requirement. - - - - platform will list all the platforms in your Gemfile.lock as well as - the ruby directive if applicable from your Gemfile(5). It will also let - you know if the ruby directive requirement has been met. If ruby direc- - tive doesn't match the running Ruby VM, it will tell you what part does - not. - -OPTIONS - --ruby It will display the ruby directive information, so you don't - have to parse it from the Gemfile(5). - - - - - January 2020 BUNDLE-PLATFORM(1) diff --git a/ruby/man/bundle-pristine.1.txt b/ruby/man/bundle-pristine.1.txt deleted file mode 100644 index 8d474fe49..000000000 --- a/ruby/man/bundle-pristine.1.txt +++ /dev/null @@ -1,44 +0,0 @@ -BUNDLE-PRISTINE(1) BUNDLE-PRISTINE(1) - - - -NAME - bundle-pristine - Restores installed gems to their pristine condition - -SYNOPSIS - bundle pristine - -DESCRIPTION - pristine restores the installed gems in the bundle to their pristine - condition using the local gem cache from RubyGems. For git gems, a - forced checkout will be performed. - - For further explanation, bundle pristine ignores unpacked files on - disk. In other words, this command utilizes the local .gem cache or the - gem's git repository as if one were installing from scratch. - - Note: the Bundler gem cannot be restored to its original state with - pristine. One also cannot use bundle pristine on gems with a 'path' - option in the Gemfile, because bundler has no original copy it can - restore from. - - When is it practical to use bundle pristine? - - It comes in handy when a developer is debugging a gem. bundle pristine - is a great way to get rid of experimental changes to a gem that one may - not want. - - Why use bundle pristine over gem pristine --all? - - Both commands are very similar. For context: bundle pristine, without - arguments, cleans all gems from the lockfile. Meanwhile, gem pristine - --all cleans all installed gems for that Ruby version. - - If a developer forgets which gems in their project they might have been - debugging, the Rubygems gem pristine [GEMNAME] command may be inconve- - nient. One can avoid waiting for gem pristine --all, and instead run - bundle pristine. - - - - January 2020 BUNDLE-PRISTINE(1) diff --git a/ruby/man/bundle-remove.1.txt b/ruby/man/bundle-remove.1.txt deleted file mode 100644 index 7203422f3..000000000 --- a/ruby/man/bundle-remove.1.txt +++ /dev/null @@ -1,34 +0,0 @@ -BUNDLE-REMOVE(1) BUNDLE-REMOVE(1) - - - -NAME - bundle-remove - Removes gems from the Gemfile - -SYNOPSIS - bundle remove [GEM [GEM ...]] [--install] - -DESCRIPTION - Removes the given gems from the Gemfile while ensuring that the result- - ing Gemfile is still valid. If a gem cannot be removed, a warning is - printed. If a gem is already absent from the Gemfile, and error is - raised. - -OPTIONS - --install - Runs bundle install after the given gems have been removed from - the Gemfile, which ensures that both the lockfile and the - installed gems on disk are also updated to remove the given - gem(s). - - Example: - - bundle remove rails - - bundle remove rails rack - - bundle remove rails rack --install - - - - January 2020 BUNDLE-REMOVE(1) diff --git a/ruby/man/bundle-show.1.txt b/ruby/man/bundle-show.1.txt deleted file mode 100644 index 58f162016..000000000 --- a/ruby/man/bundle-show.1.txt +++ /dev/null @@ -1,27 +0,0 @@ -BUNDLE-SHOW(1) BUNDLE-SHOW(1) - - - -NAME - bundle-show - Shows all the gems in your bundle, or the path to a gem - -SYNOPSIS - bundle show [GEM] [--paths] - -DESCRIPTION - Without the [GEM] option, show will print a list of the names and ver- - sions of all gems that are required by your [Gemfile(5)][Gemfile(5)], - sorted by name. - - Calling show with [GEM] will list the exact location of that gem on - your machine. - -OPTIONS - --paths - List the paths of all gems that are required by your [Gem- - file(5)][Gemfile(5)], sorted by gem name. - - - - - January 2020 BUNDLE-SHOW(1) diff --git a/ruby/man/bundle-update.1.txt b/ruby/man/bundle-update.1.txt deleted file mode 100644 index b8208c75d..000000000 --- a/ruby/man/bundle-update.1.txt +++ /dev/null @@ -1,390 +0,0 @@ -BUNDLE-UPDATE(1) BUNDLE-UPDATE(1) - - - -NAME - bundle-update - Update your gems to the latest available versions - -SYNOPSIS - bundle update *gems [--all] [--group=NAME] [--source=NAME] [--local] - [--ruby] [--bundler[=VERSION]] [--full-index] [--jobs=JOBS] [--quiet] - [--patch|--minor|--major] [--redownload] [--strict] [--conservative] - -DESCRIPTION - Update the gems specified (all gems, if --all flag is used), ignoring - the previously installed gems specified in the Gemfile.lock. In gen- - eral, you should use bundle install(1) bundle-install.1.html to install - the same exact gems and versions across machines. - - You would use bundle update to explicitly update the version of a gem. - -OPTIONS - --all Update all gems specified in Gemfile. - - --group=, -g=[] - Only update the gems in the specified group. For instance, you - can update all gems in the development group with bundle update - --group development. You can also call bundle update rails - --group test to update the rails gem and all gems in the test - group, for example. - - --source= - The name of a :git or :path source used in the Gemfile(5). For - instance, with a :git source of - http://github.com/rails/rails.git, you would call bundle update - --source rails - - --local - Do not attempt to fetch gems remotely and use the gem cache - instead. - - --ruby Update the locked version of Ruby to the current version of - Ruby. - - --bundler - Update the locked version of bundler to the invoked bundler ver- - sion. - - --full-index - Fall back to using the single-file index of all gems. - - --jobs=[], -j[] - Specify the number of jobs to run in parallel. The default is 1. - - --retry=[] - Retry failed network or git requests for number times. - - --quiet - Only output warnings and errors. - - --redownload - Force downloading every gem. - - --patch - Prefer updating only to next patch version. - - --minor - Prefer updating only to next minor version. - - --major - Prefer updating to next major version (default). - - --strict - Do not allow any gem to be updated past latest --patch | --minor - | --major. - - --conservative - Use bundle install conservative update behavior and do not allow - shared dependencies to be updated. - -UPDATING ALL GEMS - If you run bundle update --all, bundler will ignore any previously - installed gems and resolve all dependencies again based on the latest - versions of all gems available in the sources. - - Consider the following Gemfile(5): - - - - source "https://rubygems.org" - - gem "rails", "3.0.0.rc" - gem "nokogiri" - - - - When you run bundle install(1) bundle-install.1.html the first time, - bundler will resolve all of the dependencies, all the way down, and - install what you need: - - - - Fetching gem metadata from https://rubygems.org/......... - Resolving dependencies... - Installing builder 2.1.2 - Installing abstract 1.0.0 - Installing rack 1.2.8 - Using bundler 1.7.6 - Installing rake 10.4.0 - Installing polyglot 0.3.5 - Installing mime-types 1.25.1 - Installing i18n 0.4.2 - Installing mini_portile 0.6.1 - Installing tzinfo 0.3.42 - Installing rack-mount 0.6.14 - Installing rack-test 0.5.7 - Installing treetop 1.4.15 - Installing thor 0.14.6 - Installing activesupport 3.0.0.rc - Installing erubis 2.6.6 - Installing activemodel 3.0.0.rc - Installing arel 0.4.0 - Installing mail 2.2.20 - Installing activeresource 3.0.0.rc - Installing actionpack 3.0.0.rc - Installing activerecord 3.0.0.rc - Installing actionmailer 3.0.0.rc - Installing railties 3.0.0.rc - Installing rails 3.0.0.rc - Installing nokogiri 1.6.5 - - Bundle complete! 2 Gemfile dependencies, 26 gems total. - Use `bundle show [gemname]` to see where a bundled gem is installed. - - - - As you can see, even though you have two gems in the Gemfile(5), your - application needs 26 different gems in order to run. Bundler remembers - the exact versions it installed in Gemfile.lock. The next time you run - bundle install(1) bundle-install.1.html, bundler skips the dependency - resolution and installs the same gems as it installed last time. - - After checking in the Gemfile.lock into version control and cloning it - on another machine, running bundle install(1) bundle-install.1.html - will still install the gems that you installed last time. You don't - need to worry that a new release of erubis or mail changes the gems you - use. - - However, from time to time, you might want to update the gems you are - using to the newest versions that still match the gems in your Gem- - file(5). - - To do this, run bundle update --all, which will ignore the Gem- - file.lock, and resolve all the dependencies again. Keep in mind that - this process can result in a significantly different set of the 25 - gems, based on the requirements of new gems that the gem authors - released since the last time you ran bundle update --all. - -UPDATING A LIST OF GEMS - Sometimes, you want to update a single gem in the Gemfile(5), and leave - the rest of the gems that you specified locked to the versions in the - Gemfile.lock. - - For instance, in the scenario above, imagine that nokogiri releases - version 1.4.4, and you want to update it without updating Rails and all - of its dependencies. To do this, run bundle update nokogiri. - - Bundler will update nokogiri and any of its dependencies, but leave - alone Rails and its dependencies. - -OVERLAPPING DEPENDENCIES - Sometimes, multiple gems declared in your Gemfile(5) are satisfied by - the same second-level dependency. For instance, consider the case of - thin and rack-perftools-profiler. - - - - source "https://rubygems.org" - - gem "thin" - gem "rack-perftools-profiler" - - - - The thin gem depends on rack >= 1.0, while rack-perftools-profiler - depends on rack ~> 1.0. If you run bundle install, you get: - - - - Fetching source index for https://rubygems.org/ - Installing daemons (1.1.0) - Installing eventmachine (0.12.10) with native extensions - Installing open4 (1.0.1) - Installing perftools.rb (0.4.7) with native extensions - Installing rack (1.2.1) - Installing rack-perftools_profiler (0.0.2) - Installing thin (1.2.7) with native extensions - Using bundler (1.0.0.rc.3) - - - - In this case, the two gems have their own set of dependencies, but they - share rack in common. If you run bundle update thin, bundler will - update daemons, eventmachine and rack, which are dependencies of thin, - but not open4 or perftools.rb, which are dependencies of - rack-perftools_profiler. Note that bundle update thin will update rack - even though it's also a dependency of rack-perftools_profiler. - - In short, by default, when you update a gem using bundle update, - bundler will update all dependencies of that gem, including those that - are also dependencies of another gem. - - To prevent updating shared dependencies, prior to version 1.14 the only - option was the CONSERVATIVE UPDATING behavior in bundle install(1) bun- - dle-install.1.html: - - In this scenario, updating the thin version manually in the Gemfile(5), - and then running bundle install(1) bundle-install.1.html will only - update daemons and eventmachine, but not rack. For more information, - see the CONSERVATIVE UPDATING section of bundle install(1) bun- - dle-install.1.html. - - Starting with 1.14, specifying the --conservative option will also pre- - vent shared dependencies from being updated. - -PATCH LEVEL OPTIONS - Version 1.14 introduced 4 patch-level options that will influence how - gem versions are resolved. One of the following options can be used: - --patch, --minor or --major. --strict can be added to further influence - resolution. - - --patch - Prefer updating only to next patch version. - - --minor - Prefer updating only to next minor version. - - --major - Prefer updating to next major version (default). - - --strict - Do not allow any gem to be updated past latest --patch | --minor - | --major. - - When Bundler is resolving what versions to use to satisfy declared - requirements in the Gemfile or in parent gems, it looks up all avail- - able versions, filters out any versions that don't satisfy the require- - ment, and then, by default, sorts them from newest to oldest, consider- - ing them in that order. - - Providing one of the patch level options (e.g. --patch) changes the - sort order of the satisfying versions, causing Bundler to consider the - latest --patch or --minor version available before other versions. Note - that versions outside the stated patch level could still be resolved to - if necessary to find a suitable dependency graph. - - For example, if gem 'foo' is locked at 1.0.2, with no gem requirement - defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 - all exist, the default order of preference by default (--major) will be - "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2". - - If the --patch option is used, the order of preference will change to - "1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0". - - If the --minor option is used, the order of preference will change to - "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0". - - Combining the --strict option with any of the patch level options will - remove any versions beyond the scope of the patch level option, to - ensure that no gem is updated that far. - - To continue the previous example, if both --patch and --strict options - are used, the available versions for resolution would be "1.0.4, 1.0.3, - 1.0.2". If --minor and --strict are used, it would be "1.1.1, 1.1.0, - 1.0.4, 1.0.3, 1.0.2". - - Gem requirements as defined in the Gemfile will still be the first - determining factor for what versions are available. If the gem require- - ment for foo in the Gemfile is '~> 1.0', that will accomplish the same - thing as providing the --minor and --strict options. - -PATCH LEVEL EXAMPLES - Given the following gem specifications: - - - - foo 1.4.3, requires: ~> bar 2.0 - foo 1.4.4, requires: ~> bar 2.0 - foo 1.4.5, requires: ~> bar 2.1 - foo 1.5.0, requires: ~> bar 2.1 - foo 1.5.1, requires: ~> bar 3.0 - bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0 - - - - Gemfile: - - - - gem 'foo' - - - - Gemfile.lock: - - - - foo (1.4.3) - bar (~> 2.0) - bar (2.0.3) - - - - Cases: - - - - # Command Line Result - ------------------------------------------------------------ - 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1' - 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1' - 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0' - 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1' - 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4' - - - - In case 1, bar is upgraded to 2.1.1, a minor version increase, because - the dependency from foo 1.4.5 required it. - - In case 2, only foo is requested to be unlocked, but bar is also - allowed to move because it's not a declared dependency in the Gemfile. - - In case 3, bar goes up a whole major release, because a minor increase - is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0 - of bar. - - In case 4, foo is preferred up to a minor version, but 1.5.1 won't work - because the --strict flag removes bar 3.0.0 from consideration since - it's a major increment. - - In case 5, both foo and bar have any minor or major increments removed - from consideration because of the --strict flag, so the most they can - move is up to 1.4.4 and 2.0.4. - -RECOMMENDED WORKFLOW - In general, when working with an application managed with bundler, you - should use the following workflow: - - o After you create your Gemfile(5) for the first time, run - - $ bundle install - - o Check the resulting Gemfile.lock into version control - - $ git add Gemfile.lock - - o When checking out this repository on another development machine, - run - - $ bundle install - - o When checking out this repository on a deployment machine, run - - $ bundle install --deployment - - o After changing the Gemfile(5) to reflect a new or update depen- - dency, run - - $ bundle install - - o Make sure to check the updated Gemfile.lock into version control - - $ git add Gemfile.lock - - o If bundle install(1) bundle-install.1.html reports a conflict, man- - ually update the specific gems that you changed in the Gemfile(5) - - $ bundle update rails thin - - o If you want to update all the gems to the latest possible versions - that still match the gems listed in the Gemfile(5), run - - $ bundle update --all - - - - - - - January 2020 BUNDLE-UPDATE(1) diff --git a/ruby/man/bundle-update.ronn b/ruby/man/bundle-update.ronn deleted file mode 100644 index 397fecadc..000000000 --- a/ruby/man/bundle-update.ronn +++ /dev/null @@ -1,350 +0,0 @@ -bundle-update(1) -- Update your gems to the latest available versions -===================================================================== - -## SYNOPSIS - -`bundle update` <*gems> [--all] - [--group=NAME] - [--source=NAME] - [--local] - [--ruby] - [--bundler[=VERSION]] - [--full-index] - [--jobs=JOBS] - [--quiet] - [--patch|--minor|--major] - [--redownload] - [--strict] - [--conservative] - -## DESCRIPTION - -Update the gems specified (all gems, if `--all` flag is used), ignoring -the previously installed gems specified in the `Gemfile.lock`. In -general, you should use [bundle install(1)](bundle-install.1.html) to install the same exact -gems and versions across machines. - -You would use `bundle update` to explicitly update the version of a -gem. - -## OPTIONS - -* `--all`: - Update all gems specified in Gemfile. - -* `--group=`, `-g=[]`: - Only update the gems in the specified group. For instance, you can update all gems - in the development group with `bundle update --group development`. You can also - call `bundle update rails --group test` to update the rails gem and all gems in - the test group, for example. - -* `--source=`: - The name of a `:git` or `:path` source used in the Gemfile(5). For - instance, with a `:git` source of `http://github.com/rails/rails.git`, - you would call `bundle update --source rails` - -* `--local`: - Do not attempt to fetch gems remotely and use the gem cache instead. - -* `--ruby`: - Update the locked version of Ruby to the current version of Ruby. - -* `--bundler`: - Update the locked version of bundler to the invoked bundler version. - -* `--full-index`: - Fall back to using the single-file index of all gems. - -* `--jobs=[]`, `-j[]`: - Specify the number of jobs to run in parallel. The default is `1`. - -* `--retry=[]`: - Retry failed network or git requests for times. - -* `--quiet`: - Only output warnings and errors. - -* `--redownload`: - Force downloading every gem. - -* `--patch`: - Prefer updating only to next patch version. - -* `--minor`: - Prefer updating only to next minor version. - -* `--major`: - Prefer updating to next major version (default). - -* `--strict`: - Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`. - -* `--conservative`: - Use bundle install conservative update behavior and do not allow shared dependencies to be updated. - -## UPDATING ALL GEMS - -If you run `bundle update --all`, bundler will ignore -any previously installed gems and resolve all dependencies again -based on the latest versions of all gems available in the sources. - -Consider the following Gemfile(5): - - source "https://rubygems.org" - - gem "rails", "3.0.0.rc" - gem "nokogiri" - -When you run [bundle install(1)](bundle-install.1.html) the first time, bundler will resolve -all of the dependencies, all the way down, and install what you need: - - Fetching gem metadata from https://rubygems.org/......... - Resolving dependencies... - Installing builder 2.1.2 - Installing abstract 1.0.0 - Installing rack 1.2.8 - Using bundler 1.7.6 - Installing rake 10.4.0 - Installing polyglot 0.3.5 - Installing mime-types 1.25.1 - Installing i18n 0.4.2 - Installing mini_portile 0.6.1 - Installing tzinfo 0.3.42 - Installing rack-mount 0.6.14 - Installing rack-test 0.5.7 - Installing treetop 1.4.15 - Installing thor 0.14.6 - Installing activesupport 3.0.0.rc - Installing erubis 2.6.6 - Installing activemodel 3.0.0.rc - Installing arel 0.4.0 - Installing mail 2.2.20 - Installing activeresource 3.0.0.rc - Installing actionpack 3.0.0.rc - Installing activerecord 3.0.0.rc - Installing actionmailer 3.0.0.rc - Installing railties 3.0.0.rc - Installing rails 3.0.0.rc - Installing nokogiri 1.6.5 - - Bundle complete! 2 Gemfile dependencies, 26 gems total. - Use `bundle show [gemname]` to see where a bundled gem is installed. - -As you can see, even though you have two gems in the Gemfile(5), your application -needs 26 different gems in order to run. Bundler remembers the exact versions -it installed in `Gemfile.lock`. The next time you run [bundle install(1)](bundle-install.1.html), bundler skips -the dependency resolution and installs the same gems as it installed last time. - -After checking in the `Gemfile.lock` into version control and cloning it on another -machine, running [bundle install(1)](bundle-install.1.html) will _still_ install the gems that you installed -last time. You don't need to worry that a new release of `erubis` or `mail` changes -the gems you use. - -However, from time to time, you might want to update the gems you are using to the -newest versions that still match the gems in your Gemfile(5). - -To do this, run `bundle update --all`, which will ignore the `Gemfile.lock`, and resolve -all the dependencies again. Keep in mind that this process can result in a significantly -different set of the 25 gems, based on the requirements of new gems that the gem -authors released since the last time you ran `bundle update --all`. - -## UPDATING A LIST OF GEMS - -Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the -gems that you specified locked to the versions in the `Gemfile.lock`. - -For instance, in the scenario above, imagine that `nokogiri` releases version `1.4.4`, and -you want to update it _without_ updating Rails and all of its dependencies. To do this, -run `bundle update nokogiri`. - -Bundler will update `nokogiri` and any of its dependencies, but leave alone Rails and -its dependencies. - -## OVERLAPPING DEPENDENCIES - -Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same -second-level dependency. For instance, consider the case of `thin` and -`rack-perftools-profiler`. - - source "https://rubygems.org" - - gem "thin" - gem "rack-perftools-profiler" - -The `thin` gem depends on `rack >= 1.0`, while `rack-perftools-profiler` depends -on `rack ~> 1.0`. If you run bundle install, you get: - - Fetching source index for https://rubygems.org/ - Installing daemons (1.1.0) - Installing eventmachine (0.12.10) with native extensions - Installing open4 (1.0.1) - Installing perftools.rb (0.4.7) with native extensions - Installing rack (1.2.1) - Installing rack-perftools_profiler (0.0.2) - Installing thin (1.2.7) with native extensions - Using bundler (1.0.0.rc.3) - -In this case, the two gems have their own set of dependencies, but they share -`rack` in common. If you run `bundle update thin`, bundler will update `daemons`, -`eventmachine` and `rack`, which are dependencies of `thin`, but not `open4` or -`perftools.rb`, which are dependencies of `rack-perftools_profiler`. Note that -`bundle update thin` will update `rack` even though it's _also_ a dependency of -`rack-perftools_profiler`. - -In short, by default, when you update a gem using `bundle update`, bundler will -update all dependencies of that gem, including those that are also dependencies -of another gem. - -To prevent updating shared dependencies, prior to version 1.14 the only option -was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html): - -In this scenario, updating the `thin` version manually in the Gemfile(5), -and then running [bundle install(1)](bundle-install.1.html) will only update `daemons` and `eventmachine`, -but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section -of [bundle install(1)](bundle-install.1.html). - -Starting with 1.14, specifying the `--conservative` option will also prevent shared -dependencies from being updated. - -## PATCH LEVEL OPTIONS - -Version 1.14 introduced 4 patch-level options that will influence how gem -versions are resolved. One of the following options can be used: `--patch`, -`--minor` or `--major`. `--strict` can be added to further influence resolution. - -* `--patch`: - Prefer updating only to next patch version. - -* `--minor`: - Prefer updating only to next minor version. - -* `--major`: - Prefer updating to next major version (default). - -* `--strict`: - Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`. - -When Bundler is resolving what versions to use to satisfy declared -requirements in the Gemfile or in parent gems, it looks up all -available versions, filters out any versions that don't satisfy -the requirement, and then, by default, sorts them from newest to -oldest, considering them in that order. - -Providing one of the patch level options (e.g. `--patch`) changes the -sort order of the satisfying versions, causing Bundler to consider the -latest `--patch` or `--minor` version available before other versions. -Note that versions outside the stated patch level could still be -resolved to if necessary to find a suitable dependency graph. - -For example, if gem 'foo' is locked at 1.0.2, with no gem requirement -defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 -all exist, the default order of preference by default (`--major`) will -be "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2". - -If the `--patch` option is used, the order of preference will change to -"1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0". - -If the `--minor` option is used, the order of preference will change to -"1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0". - -Combining the `--strict` option with any of the patch level options -will remove any versions beyond the scope of the patch level option, -to ensure that no gem is updated that far. - -To continue the previous example, if both `--patch` and `--strict` -options are used, the available versions for resolution would be -"1.0.4, 1.0.3, 1.0.2". If `--minor` and `--strict` are used, it would -be "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2". - -Gem requirements as defined in the Gemfile will still be the first -determining factor for what versions are available. If the gem -requirement for `foo` in the Gemfile is '~> 1.0', that will accomplish -the same thing as providing the `--minor` and `--strict` options. - -## PATCH LEVEL EXAMPLES - -Given the following gem specifications: - - foo 1.4.3, requires: ~> bar 2.0 - foo 1.4.4, requires: ~> bar 2.0 - foo 1.4.5, requires: ~> bar 2.1 - foo 1.5.0, requires: ~> bar 2.1 - foo 1.5.1, requires: ~> bar 3.0 - bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0 - -Gemfile: - - gem 'foo' - -Gemfile.lock: - - foo (1.4.3) - bar (~> 2.0) - bar (2.0.3) - -Cases: - - # Command Line Result - ------------------------------------------------------------ - 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1' - 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1' - 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0' - 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1' - 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4' - -In case 1, bar is upgraded to 2.1.1, a minor version increase, because -the dependency from foo 1.4.5 required it. - -In case 2, only foo is requested to be unlocked, but bar is also -allowed to move because it's not a declared dependency in the Gemfile. - -In case 3, bar goes up a whole major release, because a minor increase -is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0 -of bar. - -In case 4, foo is preferred up to a minor version, but 1.5.1 won't work -because the --strict flag removes bar 3.0.0 from consideration since -it's a major increment. - -In case 5, both foo and bar have any minor or major increments removed -from consideration because of the --strict flag, so the most they can -move is up to 1.4.4 and 2.0.4. - -## RECOMMENDED WORKFLOW - -In general, when working with an application managed with bundler, you should -use the following workflow: - -* After you create your Gemfile(5) for the first time, run - - $ bundle install - -* Check the resulting `Gemfile.lock` into version control - - $ git add Gemfile.lock - -* When checking out this repository on another development machine, run - - $ bundle install - -* When checking out this repository on a deployment machine, run - - $ bundle install --deployment - -* After changing the Gemfile(5) to reflect a new or update dependency, run - - $ bundle install - -* Make sure to check the updated `Gemfile.lock` into version control - - $ git add Gemfile.lock - -* If [bundle install(1)](bundle-install.1.html) reports a conflict, manually update the specific - gems that you changed in the Gemfile(5) - - $ bundle update rails thin - -* If you want to update all the gems to the latest possible versions that - still match the gems listed in the Gemfile(5), run - - $ bundle update --all diff --git a/ruby/man/bundle-viz.1.txt b/ruby/man/bundle-viz.1.txt deleted file mode 100644 index c934b4cf5..000000000 --- a/ruby/man/bundle-viz.1.txt +++ /dev/null @@ -1,39 +0,0 @@ -BUNDLE-VIZ(1) BUNDLE-VIZ(1) - - - -NAME - bundle-viz - Generates a visual dependency graph for your Gemfile - -SYNOPSIS - bundle viz [--file=FILE] [--format=FORMAT] [--requirements] [--version] - [--without=GROUP GROUP] - -DESCRIPTION - viz generates a PNG file of the current Gemfile(5) as a dependency - graph. viz requires the ruby-graphviz gem (and its dependencies). - - The associated gems must also be installed via bundle install(1) bun- - dle-install.1.html. - -OPTIONS - --file, -f - The name to use for the generated file. See --format option - - --format, -F - This is output format option. Supported format is png, jpg, svg, - dot ... - - --requirements, -R - Set to show the version of each required dependency. - - --version, -v - Set to show each gem version. - - --without, -W - Exclude gems that are part of the specified named group. - - - - - January 2020 BUNDLE-VIZ(1) diff --git a/ruby/man/bundle.1.txt b/ruby/man/bundle.1.txt deleted file mode 100644 index e7eb35aa1..000000000 --- a/ruby/man/bundle.1.txt +++ /dev/null @@ -1,116 +0,0 @@ -BUNDLE(1) BUNDLE(1) - - - -NAME - bundle - Ruby Dependency Management - -SYNOPSIS - bundle COMMAND [--no-color] [--verbose] [ARGS] - -DESCRIPTION - Bundler manages an application's dependencies through its entire life - across many machines systematically and repeatably. - - See the bundler website https://bundler.io for information on getting - started, and Gemfile(5) for more information on the Gemfile format. - -OPTIONS - --no-color - Print all output without color - - --retry, -r - Specify the number of times you wish to attempt network commands - - --verbose, -V - Print out additional logging information - -BUNDLE COMMANDS - We divide bundle subcommands into primary commands and utilities: - -PRIMARY COMMANDS - bundle install(1) bundle-install.1.html - Install the gems specified by the Gemfile or Gemfile.lock - - bundle update(1) bundle-update.1.html - Update dependencies to their latest versions - - bundle package(1) bundle-package.1.html - Package the .gem files required by your application into the - vendor/cache directory - - bundle exec(1) bundle-exec.1.html - Execute a script in the current bundle - - bundle config(1) bundle-config.1.html - Specify and read configuration options for Bundler - - bundle help(1) - Display detailed help for each subcommand - -UTILITIES - bundle add(1) bundle-add.1.html - Add the named gem to the Gemfile and run bundle install - - bundle binstubs(1) bundle-binstubs.1.html - Generate binstubs for executables in a gem - - bundle check(1) bundle-check.1.html - Determine whether the requirements for your application are - installed and available to Bundler - - bundle show(1) bundle-show.1.html - Show the source location of a particular gem in the bundle - - bundle outdated(1) bundle-outdated.1.html - Show all of the outdated gems in the current bundle - - bundle console(1) - Start an IRB session in the current bundle - - bundle open(1) bundle-open.1.html - Open an installed gem in the editor - - bundle lock(1) bundle-lock.1.html - Generate a lockfile for your dependencies - - bundle viz(1) bundle-viz.1.html - Generate a visual representation of your dependencies - - bundle init(1) bundle-init.1.html - Generate a simple Gemfile, placed in the current directory - - bundle gem(1) bundle-gem.1.html - Create a simple gem, suitable for development with Bundler - - bundle platform(1) bundle-platform.1.html - Display platform compatibility information - - bundle clean(1) bundle-clean.1.html - Clean up unused gems in your Bundler directory - - bundle doctor(1) bundle-doctor.1.html - Display warnings about common problems - - bundle remove(1) bundle-remove.1.html - Removes gems from the Gemfile - -PLUGINS - When running a command that isn't listed in PRIMARY COMMANDS or UTILI- - TIES, Bundler will try to find an executable on your path named - bundler- and execute it, passing down any extra arguments to - it. - -OBSOLETE - These commands are obsolete and should no longer be used: - - o bundle cache(1) - - o bundle show(1) - - - - - - - January 2020 BUNDLE(1) diff --git a/ruby/man/gemfile.5.txt b/ruby/man/gemfile.5.txt deleted file mode 100644 index 71d251327..000000000 --- a/ruby/man/gemfile.5.txt +++ /dev/null @@ -1,649 +0,0 @@ -GEMFILE(5) GEMFILE(5) - - - -NAME - Gemfile - A format for describing gem dependencies for Ruby programs - -SYNOPSIS - A Gemfile describes the gem dependencies required to execute associated - Ruby code. - - Place the Gemfile in the root of the directory containing the associ- - ated code. For instance, in a Rails application, place the Gemfile in - the same directory as the Rakefile. - -SYNTAX - A Gemfile is evaluated as Ruby code, in a context which makes available - a number of methods used to describe the gem requirements. - -GLOBAL SOURCES - At the top of the Gemfile, add a line for the Rubygems source that con- - tains the gems listed in the Gemfile. - - - - source "https://rubygems.org" - - - - It is possible, but not recommended as of Bundler 1.7, to add multiple - global source lines. Each of these sources MUST be a valid Rubygems - repository. - - Sources are checked for gems following the heuristics described in - SOURCE PRIORITY. If a gem is found in more than one global source, - Bundler will print a warning after installing the gem indicating which - source was used, and listing the other sources where the gem is avail- - able. A specific source can be selected for gems that need to use a - non-standard repository, suppressing this warning, by using the :source - option or a source block. - - CREDENTIALS - Some gem sources require a username and password. Use bundle config(1) - bundle-config.1.html to set the username and password for any of the - sources that need it. The command must be run once on each computer - that will install the Gemfile, but this keeps the credentials from - being stored in plain text in version control. - - - - bundle config gems.example.com user:password - - - - For some sources, like a company Gemfury account, it may be easier to - include the credentials in the Gemfile as part of the source URL. - - - - source "https://user:password@gems.example.com" - - - - Credentials in the source URL will take precedence over credentials set - using config. - -RUBY - If your application requires a specific Ruby version or engine, specify - your requirements using the ruby method, with the following arguments. - All parameters are OPTIONAL unless otherwise specified. - - VERSION (required) - The version of Ruby that your application requires. If your application - requires an alternate Ruby engine, such as JRuby, Rubinius or Truf- - fleRuby, this should be the Ruby version that the engine is compatible - with. - - - - ruby "1.9.3" - - - - ENGINE - Each application may specify a Ruby engine. If an engine is specified, - an engine version must also be specified. - - What exactly is an Engine? - A Ruby engine is an implementation of the - Ruby language. - - o For background: the reference or original implementation of the - Ruby programming language is called Matz's Ruby Interpreter - https://en.wikipedia.org/wiki/Ruby_MRI, or MRI for short. This is - named after Ruby creator Yukihiro Matsumoto, also known as Matz. - MRI is also known as CRuby, because it is written in C. MRI is the - most widely used Ruby engine. - - o Other implementations https://www.ruby-lang.org/en/about/ of Ruby - exist. Some of the more well-known implementations include Rubinius - https://rubinius.com/, and JRuby http://jruby.org/. Rubinius is an - alternative implementation of Ruby written in Ruby. JRuby is an - implementation of Ruby on the JVM, short for Java Virtual Machine. - - - - ENGINE VERSION - Each application may specify a Ruby engine version. If an engine ver- - sion is specified, an engine must also be specified. If the engine is - "ruby" the engine version specified must match the Ruby version. - - - - ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7" - - - - PATCHLEVEL - Each application may specify a Ruby patchlevel. - - - - ruby "2.0.0", :patchlevel => "247" - - - -GEMS - Specify gem requirements using the gem method, with the following argu- - ments. All parameters are OPTIONAL unless otherwise specified. - - NAME (required) - For each gem requirement, list a single gem line. - - - - gem "nokogiri" - - - - VERSION - Each gem MAY have one or more version specifiers. - - - - gem "nokogiri", ">= 1.4.2" - gem "RedCloth", ">= 4.1.0", "< 4.2.0" - - - - REQUIRE AS - Each gem MAY specify files that should be used when autorequiring via - Bundler.require. You may pass an array with multiple files or true if - file you want required has same name as gem or false to prevent any - file from being autorequired. - - - - gem "redis", :require => ["redis/connection/hiredis", "redis"] - gem "webmock", :require => false - gem "byebug", :require => true - - - - The argument defaults to the name of the gem. For example, these are - identical: - - - - gem "nokogiri" - gem "nokogiri", :require => "nokogiri" - gem "nokogiri", :require => true - - - - GROUPS - Each gem MAY specify membership in one or more groups. Any gem that - does not specify membership in any group is placed in the default - group. - - - - gem "rspec", :group => :test - gem "wirble", :groups => [:development, :test] - - - - The Bundler runtime allows its two main methods, Bundler.setup and - Bundler.require, to limit their impact to particular groups. - - - - # setup adds gems to Ruby's load path - Bundler.setup # defaults to all groups - require "bundler/setup" # same as Bundler.setup - Bundler.setup(:default) # only set up the _default_ group - Bundler.setup(:test) # only set up the _test_ group (but `not` _default_) - Bundler.setup(:default, :test) # set up the _default_ and _test_ groups, but no others - - # require requires all of the gems in the specified groups - Bundler.require # defaults to the _default_ group - Bundler.require(:default) # identical - Bundler.require(:default, :test) # requires the _default_ and _test_ groups - Bundler.require(:test) # requires the _test_ group - - - - The Bundler CLI allows you to specify a list of groups whose gems bun- - dle install should not install with the without configuration. - - To specify multiple groups to ignore, specify a list of groups sepa- - rated by spaces. - - - - bundle config set without test - bundle config set without development test - - - - Also, calling Bundler.setup with no parameters, or calling require - "bundler/setup" will setup all groups except for the ones you excluded - via --without (since they are not available). - - Note that on bundle install, bundler downloads and evaluates all gems, - in order to create a single canonical list of all of the required gems - and their dependencies. This means that you cannot list different ver- - sions of the same gems in different groups. For more details, see - Understanding Bundler https://bundler.io/rationale.html. - - PLATFORMS - If a gem should only be used in a particular platform or set of plat- - forms, you can specify them. Platforms are essentially identical to - groups, except that you do not need to use the --without install-time - flag to exclude groups of gems for other platforms. - - There are a number of Gemfile platforms: - - ruby C Ruby (MRI), Rubinius or TruffleRuby, but NOT Windows - - mri Same as ruby, but only C Ruby (MRI) - - mingw Windows 32 bit 'mingw32' platform (aka RubyInstaller) - - x64_mingw - Windows 64 bit 'mingw32' platform (aka RubyInstaller x64) - - rbx Rubinius - - jruby JRuby - - truffleruby - TruffleRuby - - mswin Windows - - You can restrict further by platform and version for all platforms - except for rbx, jruby, truffleruby and mswin. - - To specify a version in addition to a platform, append the version num- - ber without the delimiter to the platform. For example, to specify that - a gem should only be used on platforms with Ruby 2.3, use: - - - - ruby_23 - - - - The full list of platforms and supported versions includes: - - ruby 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6 - - mri 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6 - - mingw 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6 - - x64_mingw - 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6 - - As with groups, you can specify one or more platforms: - - - - gem "weakling", :platforms => :jruby - gem "ruby-debug", :platforms => :mri_18 - gem "nokogiri", :platforms => [:mri_18, :jruby] - - - - All operations involving groups (bundle install bundle-install.1.html, - Bundler.setup, Bundler.require) behave exactly the same as if any - groups not matching the current platform were explicitly excluded. - - SOURCE - You can select an alternate Rubygems repository for a gem using the - ':source' option. - - - - gem "some_internal_gem", :source => "https://gems.example.com" - - - - This forces the gem to be loaded from this source and ignores any - global sources declared at the top level of the file. If the gem does - not exist in this source, it will not be installed. - - Bundler will search for child dependencies of this gem by first looking - in the source selected for the parent, but if they are not found there, - it will fall back on global sources using the ordering described in - SOURCE PRIORITY. - - Selecting a specific source repository this way also suppresses the - ambiguous gem warning described above in GLOBAL SOURCES (#source). - - Using the :source option for an individual gem will also make that - source available as a possible global source for any other gems which - do not specify explicit sources. Thus, when adding gems with explicit - sources, it is recommended that you also ensure all other gems in the - Gemfile are using explicit sources. - - GIT - If necessary, you can specify that a gem is located at a particular git - repository using the :git parameter. The repository can be accessed via - several protocols: - - HTTP(S) - gem "rails", :git => "https://github.com/rails/rails.git" - - SSH gem "rails", :git => "git@github.com:rails/rails.git" - - git gem "rails", :git => "git://github.com/rails/rails.git" - - If using SSH, the user that you use to run bundle install MUST have the - appropriate keys available in their $HOME/.ssh. - - NOTE: http:// and git:// URLs should be avoided if at all possible. - These protocols are unauthenticated, so a man-in-the-middle attacker - can deliver malicious code and compromise your system. HTTPS and SSH - are strongly preferred. - - The group, platforms, and require options are available and behave - exactly the same as they would for a normal gem. - - A git repository SHOULD have at least one file, at the root of the - directory containing the gem, with the extension .gemspec. This file - MUST contain a valid gem specification, as expected by the gem build - command. - - If a git repository does not have a .gemspec, bundler will attempt to - create one, but it will not contain any dependencies, executables, or C - extension compilation instructions. As a result, it may fail to prop- - erly integrate into your application. - - If a git repository does have a .gemspec for the gem you attached it - to, a version specifier, if provided, means that the git repository is - only valid if the .gemspec specifies a version matching the version - specifier. If not, bundler will print a warning. - - - - gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git" - # bundle install will fail, because the .gemspec in the rails - # repository's master branch specifies version 3.0.0 - - - - If a git repository does not have a .gemspec for the gem you attached - it to, a version specifier MUST be provided. Bundler will use this ver- - sion in the simple .gemspec it creates. - - Git repositories support a number of additional options. - - branch, tag, and ref - You MUST only specify at most one of these options. The default - is :branch => "master". For example: - - gem "rails", :git => "https://github.com/rails/rails.git", - :branch => "5-0-stable" - - gem "rails", :git => "https://github.com/rails/rails.git", :tag - => "v5.0.0" - - gem "rails", :git => "https://github.com/rails/rails.git", :ref - => "4aded" - - submodules - For reference, a git submodule - https://git-scm.com/book/en/v2/Git-Tools-Submodules lets you - have another git repository within a subfolder of your reposi- - tory. Specify :submodules => true to cause bundler to expand any - submodules included in the git repository - - If a git repository contains multiple .gemspecs, each .gemspec repre- - sents a gem located at the same place in the file system as the .gem- - spec. - - - - |~rails [git root] - | |-rails.gemspec [rails gem located here] - |~actionpack - | |-actionpack.gemspec [actionpack gem located here] - |~activesupport - | |-activesupport.gemspec [activesupport gem located here] - |... - - - - To install a gem located in a git repository, bundler changes to the - directory containing the gemspec, runs gem build name.gemspec and then - installs the resulting gem. The gem build command, which comes standard - with Rubygems, evaluates the .gemspec in the context of the directory - in which it is located. - - GIT SOURCE - A custom git source can be defined via the git_source method. Provide - the source's name as an argument, and a block which receives a single - argument and interpolates it into a string to return the full repo - address: - - - - git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" } - gem 'rails', :stash => 'forks/rails' - - - - In addition, if you wish to choose a specific branch: - - - - gem "rails", :stash => "forks/rails", :branch => "branch_name" - - - - GITHUB - NOTE: This shorthand should be avoided until Bundler 2.0, since it cur- - rently expands to an insecure git:// URL. This allows a man-in-the-mid- - dle attacker to compromise your system. - - If the git repository you want to use is hosted on GitHub and is pub- - lic, you can use the :github shorthand to specify the github username - and repository name (without the trailing ".git"), separated by a - slash. If both the username and repository name are the same, you can - omit one. - - - - gem "rails", :github => "rails/rails" - gem "rails", :github => "rails" - - - - Are both equivalent to - - - - gem "rails", :git => "git://github.com/rails/rails.git" - - - - Since the github method is a specialization of git_source, it accepts a - :branch named argument. - - GIST - If the git repository you want to use is hosted as a Github Gist and is - public, you can use the :gist shorthand to specify the gist identifier - (without the trailing ".git"). - - - - gem "the_hatch", :gist => "4815162342" - - - - Is equivalent to: - - - - gem "the_hatch", :git => "https://gist.github.com/4815162342.git" - - - - Since the gist method is a specialization of git_source, it accepts a - :branch named argument. - - BITBUCKET - If the git repository you want to use is hosted on Bitbucket and is - public, you can use the :bitbucket shorthand to specify the bitbucket - username and repository name (without the trailing ".git"), separated - by a slash. If both the username and repository name are the same, you - can omit one. - - - - gem "rails", :bitbucket => "rails/rails" - gem "rails", :bitbucket => "rails" - - - - Are both equivalent to - - - - gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git" - - - - Since the bitbucket method is a specialization of git_source, it - accepts a :branch named argument. - - PATH - You can specify that a gem is located in a particular location on the - file system. Relative paths are resolved relative to the directory con- - taining the Gemfile. - - Similar to the semantics of the :git option, the :path option requires - that the directory in question either contains a .gemspec for the gem, - or that you specify an explicit version that bundler should use. - - Unlike :git, bundler does not compile C extensions for gems specified - as paths. - - - - gem "rails", :path => "vendor/rails" - - - - If you would like to use multiple local gems directly from the filesys- - tem, you can set a global path option to the path containing the gem's - files. This will automatically load gemspec files from subdirectories. - - - - path 'components' do - gem 'admin_ui' - gem 'public_ui' - end - - - -BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS - The :source, :git, :path, :group, and :platforms options may be applied - to a group of gems by using block form. - - - - source "https://gems.example.com" do - gem "some_internal_gem" - gem "another_internal_gem" - end - - git "https://github.com/rails/rails.git" do - gem "activesupport" - gem "actionpack" - end - - platforms :ruby do - gem "ruby-debug" - gem "sqlite3" - end - - group :development, :optional => true do - gem "wirble" - gem "faker" - end - - - - In the case of the group block form the :optional option can be given - to prevent a group from being installed unless listed in the --with - option given to the bundle install command. - - In the case of the git block form, the :ref, :branch, :tag, and :sub- - modules options may be passed to the git method, and all gems in the - block will inherit those options. - - The presence of a source block in a Gemfile also makes that source - available as a possible global source for any other gems which do not - specify explicit sources. Thus, when defining source blocks, it is rec- - ommended that you also ensure all other gems in the Gemfile are using - explicit sources, either via source blocks or :source directives on - individual gems. - -INSTALL_IF - The install_if method allows gems to be installed based on a proc or - lambda. This is especially useful for optional gems that can only be - used if certain software is installed or some other conditions are met. - - - - install_if -> { RUBY_PLATFORM =~ /darwin/ } do - gem "pasteboard" - end - - - -GEMSPEC - The .gemspec http://guides.rubygems.org/specification-reference/ file - is where you provide metadata about your gem to Rubygems. Some required - Gemspec attributes include the name, description, and homepage of your - gem. This is also where you specify the dependencies your gem needs to - run. - - If you wish to use Bundler to help install dependencies for a gem while - it is being developed, use the gemspec method to pull in the dependen- - cies listed in the .gemspec file. - - The gemspec method adds any runtime dependencies as gem requirements in - the default group. It also adds development dependencies as gem - requirements in the development group. Finally, it adds a gem require- - ment on your project (:path => '.'). In conjunction with Bundler.setup, - this allows you to require project files in your test code as you would - if the project were installed as a gem; you need not manipulate the - load path manually or require project files via relative paths. - - The gemspec method supports optional :path, :glob, :name, and :develop- - ment_group options, which control where bundler looks for the .gemspec, - the glob it uses to look for the gemspec (defaults to: "{,,/*}.gem- - spec"), what named .gemspec it uses (if more than one is present), and - which group development dependencies are included in. - - When a gemspec dependency encounters version conflicts during resolu- - tion, the local version under development will always be selected -- - even if there are remote versions that better match other requirements - for the gemspec gem. - -SOURCE PRIORITY - When attempting to locate a gem to satisfy a gem requirement, bundler - uses the following priority order: - - 1. The source explicitly attached to the gem (using :source, :path, or - :git) - - 2. For implicit gems (dependencies of explicit gems), any source, git, - or path repository declared on the parent. This results in bundler - prioritizing the ActiveSupport gem from the Rails git repository - over ones from rubygems.org - - 3. The sources specified via global source lines, searching each - source in your Gemfile from last added to first added. - - - - - - - January 2020 GEMFILE(5) diff --git a/ruby/man/irb.1 b/ruby/man/irb.1 index f0a720fbd..50db89917 100644 --- a/ruby/man/irb.1 +++ b/ruby/man/irb.1 @@ -18,6 +18,7 @@ .Op Fl - Ns Oo no Oc Ns singleline .Op Fl - Ns Oo no Oc Ns echo .Op Fl - Ns Oo no Oc Ns colorize +.Op Fl - Ns Oo no Oc Ns autocomplete .Op Fl - Ns Oo no Oc Ns verbose .Op Fl -prompt Ar mode .Op Fl -prompt-mode Ar mode @@ -104,13 +105,27 @@ Uses singleline editor module. Doesn't use singleline editor module. .Pp .Pp +.It Fl -extra-doc-dir +Add an extra doc dir for the doc dialog. +.Pp +.Pp .It Fl -echo -Show result(default). +Show result (default). .Pp .It Fl -noecho Don't show result. .Pp .Pp +.It Fl -echo-on-assignment +Show result on assignment. +.Pp +.It Fl -noecho-on-assignment +Don't show result on assignment. +.Pp +.It Fl -truncate-echo-on-assignment +Show truncated result on assignment (default). +.Pp +.Pp .It Fl -colorize Use colorization. .Pp @@ -118,6 +133,13 @@ Use colorization. Don't use colorization. .Pp .Pp +.It Fl -autocomplete +Use autocompletion. +.Pp +.It Fl -noautocomplete +Don't use autocompletion. +.Pp +.Pp .It Fl -verbose Show details. .Pp diff --git a/ruby/man/ruby.1 b/ruby/man/ruby.1 index 1888312d2..944844b63 100644 --- a/ruby/man/ruby.1 +++ b/ruby/man/ruby.1 @@ -257,7 +257,7 @@ Verbose mode is "verbose". It sets the .Li "$VERBOSE" to true. .Fl W Ns -2 is same as +2 is the same as .Fl w . .El @@ -313,7 +313,7 @@ Enables automatic line-ending processing, which means to firstly set to the value of .Li "$/" , and secondly chops every line read using -.Li chop! . +.Li chomp! . .Pp .It Fl n Causes Ruby to assume the following loop around your script, which @@ -618,7 +618,7 @@ All values are specified in bytes. .Bl -hang -compact -width "RUBY_THREAD_MACHINE_STACK_SIZE" .It Ev RUBY_THREAD_VM_STACK_SIZE VM stack size used at thread creation. -default: 131072 (32-bit CPU) or 262144 (64-bit) +default: 524288 (32-bit CPU) or 1048575 (64-bit) .Pp .It Ev RUBY_THREAD_MACHINE_STACK_SIZE Machine stack size used at thread creation. diff --git a/ruby/marshal.c b/ruby/marshal.c index df8da10b2..c5327fca6 100644 --- a/ruby/marshal.c +++ b/ruby/marshal.c @@ -9,13 +9,7 @@ **********************************************************************/ -#include "ruby/ruby.h" -#include "ruby/io.h" -#include "internal.h" -#include "ruby/st.h" -#include "ruby/util.h" -#include "encindex.h" -#include "id_table.h" +#include "ruby/internal/config.h" #include #ifdef HAVE_FLOAT_H @@ -25,6 +19,26 @@ #include #endif +#include "encindex.h" +#include "id_table.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/bignum.h" +#include "internal/class.h" +#include "internal/encoding.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/struct.h" +#include "internal/symbol.h" +#include "internal/util.h" +#include "internal/vm.h" +#include "ruby/io.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "builtin.h" + #define BITSPERSHORT (2*CHAR_BIT) #define SHORTMASK ((1<klass); - w_byte(TYPE_EXTENDED, arg); - w_unique(path, arg); - klass = RCLASS_SUPER(klass); + if (!FL_TEST(klass, RICLASS_IS_ORIGIN) || + BUILTIN_TYPE(RBASIC(klass)->klass) != T_MODULE) { + VALUE path = rb_class_name(RBASIC(klass)->klass); + w_byte(TYPE_EXTENDED, arg); + w_unique(path, arg); + } + klass = RCLASS_SUPER(klass); } } @@ -557,7 +575,26 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) } } -#define to_be_skipped_id(id) (id == rb_id_encoding() || id == s_encoding_short || !rb_id2str(id)) +static bool +rb_hash_ruby2_keywords_p(VALUE obj) +{ + return (RHASH(obj)->basic.flags & RHASH_PASS_AS_KEYWORDS) != 0; +} + +static void +rb_hash_ruby2_keywords(VALUE obj) +{ + RHASH(obj)->basic.flags |= RHASH_PASS_AS_KEYWORDS; +} + +static inline bool +to_be_skipped_id(const ID id) +{ + if (id == s_encoding_short) return true; + if (id == s_ruby2_keywords_flag) return true; + if (id == rb_id_encoding()) return true; + return !rb_id2str(id); +} struct w_ivar_arg { struct dump_call_arg *dump; @@ -574,7 +611,11 @@ w_obj_each(st_data_t key, st_data_t val, st_data_t a) if (to_be_skipped_id(id)) { if (id == s_encoding_short) { - rb_warn("instance variable `E' on class %"PRIsVALUE" is not dumped", + rb_warn("instance variable `"name_s_encoding_short"' on class %"PRIsVALUE" is not dumped", + CLASS_OF(arg->obj)); + } + if (id == s_ruby2_keywords_flag) { + rb_warn("instance variable `"name_s_ruby2_keywords_flag"' on class %"PRIsVALUE" is not dumped", CLASS_OF(arg->obj)); } return ST_CONTINUE; @@ -593,7 +634,9 @@ static int obj_count_ivars(st_data_t key, st_data_t val, st_data_t a) { ID id = (ID)key; - if (!to_be_skipped_id(id)) ++*(st_index_t *)a; + if (!to_be_skipped_id(id) && UNLIKELY(!++*(st_index_t *)a)) { + rb_raise(rb_eRuntimeError, "too many instance variables"); + } return ST_CONTINUE; } @@ -652,8 +695,7 @@ w_encoding(VALUE encname, struct dump_call_arg *arg) static st_index_t has_ivars(VALUE obj, VALUE encname, VALUE *ivobj) { - st_index_t enc = !NIL_P(encname); - st_index_t num = 0; + st_index_t num = !NIL_P(encname); if (SPECIAL_CONST_P(obj)) goto generic; switch (BUILTIN_TYPE(obj)) { @@ -661,13 +703,16 @@ has_ivars(VALUE obj, VALUE encname, VALUE *ivobj) case T_CLASS: case T_MODULE: break; /* counted elsewhere */ + case T_HASH: + if (rb_hash_ruby2_keywords_p(obj)) ++num; + /* fall through */ default: generic: rb_ivar_foreach(obj, obj_count_ivars, (st_data_t)&num); if (num) *ivobj = obj; } - return num + enc; + return num; } static void @@ -687,7 +732,14 @@ w_ivar(st_index_t num, VALUE ivobj, VALUE encname, struct dump_call_arg *arg) { w_long(num, arg->arg); num -= w_encoding(encname, arg); - if (ivobj != Qundef) { + if (RB_TYPE_P(ivobj, T_HASH) && rb_hash_ruby2_keywords_p(ivobj)) { + int limit = arg->limit; + if (limit >= 0) ++limit; + w_symbol(ID2SYM(s_ruby2_keywords_flag), arg->arg); + w_object(Qtrue, arg->arg, limit); + num--; + } + if (ivobj != Qundef && num) { w_ivar_each(ivobj, num, arg); } } @@ -726,7 +778,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) return; } - if (obj == Qnil) { + if (NIL_P(obj)) { w_byte(TYPE_NIL, arg); } else if (obj == Qtrue) { @@ -916,6 +968,10 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) case T_HASH: w_uclass(obj, rb_cHash, arg); + if (rb_hash_compare_by_id_p(obj)) { + w_byte(TYPE_UCLASS, arg); + w_symbol(rb_sym_intern_ascii_cstr("Hash"), arg); + } if (NIL_P(RHASH_IFNONE(obj))) { w_byte(TYPE_HASH, arg); } @@ -1106,8 +1162,10 @@ struct load_arg { long offset; st_table *symbols; st_table *data; + st_table *partial_objects; VALUE proc; st_table *compat_tbl; + bool freeze; }; static VALUE @@ -1132,6 +1190,7 @@ mark_load_arg(void *ptr) return; rb_mark_tbl(p->symbols); rb_mark_tbl(p->data); + rb_mark_tbl(p->partial_objects); rb_mark_hash(p->compat_tbl); } @@ -1155,10 +1214,8 @@ static const rb_data_type_t load_arg_data = { }; #define r_entry(v, arg) r_entry0((v), (arg)->data->num_entries, (arg)) -static VALUE r_entry0(VALUE v, st_index_t num, struct load_arg *arg); static VALUE r_object(struct load_arg *arg); static VALUE r_symbol(struct load_arg *arg); -static VALUE path2class(VALUE path); NORETURN(static void too_short(void)); static void @@ -1360,6 +1417,13 @@ r_bytes0(long len, struct load_arg *arg) return str; } +static inline int +name_equal(const char *name, size_t nlen, const char *p, long l) +{ + if ((size_t)l != nlen || *p != *name) return 0; + return nlen == 1 || memcmp(p+1, name+1, nlen-1) == 0; +} + static int sym2encidx(VALUE sym, VALUE val) { @@ -1369,12 +1433,11 @@ sym2encidx(VALUE sym, VALUE val) if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return -1; RSTRING_GETMEM(sym, p, l); if (l <= 0) return -1; - if (l == sizeof(name_encoding) && - memcmp(p, name_encoding, sizeof(name_encoding)) == 0) { + if (name_equal(name_encoding, sizeof(name_encoding), p, l)) { int idx = rb_enc_find_index(StringValueCStr(val)); return idx; } - else if (l == 1 && *p == 'E') { + if (name_equal(name_s_encoding_short, rb_strlen_lit(name_s_encoding_short), p, l)) { if (val == Qfalse) return rb_usascii_encindex(); else if (val == Qtrue) return rb_utf8_encindex(); /* bogus ignore */ @@ -1382,6 +1445,22 @@ sym2encidx(VALUE sym, VALUE val) return -1; } +static int +symname_equal(VALUE sym, const char *name, size_t nlen) +{ + const char *p; + long l; + if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return 0; + RSTRING_GETMEM(sym, p, l); + return name_equal(name, nlen, p, l); +} + +#define BUILD_ASSERT_POSITIVE(n) \ + /* make 0 negative to workaround the "zero size array" GCC extension, */ \ + ((sizeof(char [2*(ssize_t)(n)-1])+1)/2) /* assuming no overflow */ +#define symname_equal_lit(sym, sym_name) \ + symname_equal(sym, sym_name, BUILD_ASSERT_POSITIVE(rb_strlen_lit(sym_name))) + static VALUE r_symlink(struct load_arg *arg) { @@ -1411,7 +1490,13 @@ r_symreal(struct load_arg *arg, int ivar) idx = sym2encidx(sym, r_object(arg)); } } - if (idx > 0) rb_enc_associate_index(s, idx); + if (idx > 0) { + rb_enc_associate_index(s, idx); + if (rb_enc_str_coderange(s) == ENC_CODERANGE_BROKEN) { + rb_raise(rb_eArgError, "invalid byte sequence in %s: %+"PRIsVALUE, + rb_enc_name(rb_enc_from_index(idx)), s); + } + } return s; } @@ -1453,13 +1538,13 @@ r_string(struct load_arg *arg) static VALUE r_entry0(VALUE v, st_index_t num, struct load_arg *arg) { - st_data_t real_obj = (VALUE)Qundef; - if (arg->compat_tbl && st_lookup(arg->compat_tbl, v, &real_obj)) { - st_insert(arg->data, num, (st_data_t)real_obj); - } - else { - st_insert(arg->data, num, (st_data_t)v); + st_data_t real_obj = (st_data_t)v; + if (arg->compat_tbl) { + /* real_obj is kept if not found */ + st_lookup(arg->compat_tbl, v, &real_obj); } + st_insert(arg->data, num, real_obj); + st_insert(arg->partial_objects, (st_data_t)real_obj, Qtrue); return v; } @@ -1490,10 +1575,26 @@ r_post_proc(VALUE v, struct load_arg *arg) } static VALUE -r_leave(VALUE v, struct load_arg *arg) +r_leave(VALUE v, struct load_arg *arg, bool partial) { v = r_fixup_compat(v, arg); - v = r_post_proc(v, arg); + if (!partial) { + st_data_t data; + st_data_t key = (st_data_t)v; + st_delete(arg->partial_objects, &key, &data); + if (arg->freeze) { + if (RB_TYPE_P(v, T_MODULE) || RB_TYPE_P(v, T_CLASS)) { + // noop + } + else if (RB_TYPE_P(v, T_STRING)) { + v = rb_str_to_interned_str(v); + } + else { + OBJ_FREEZE(v); + } + } + v = r_post_proc(v, arg); + } return v; } @@ -1535,8 +1636,16 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg) } if (has_encoding) *has_encoding = TRUE; } - else { - rb_ivar_set(obj, rb_intern_str(sym), val); + else if (symname_equal_lit(sym, name_s_ruby2_keywords_flag)) { + if (RB_TYPE_P(obj, T_HASH)) { + rb_hash_ruby2_keywords(obj); + } + else { + rb_raise(rb_eArgError, "ruby2_keywords flag is given but %"PRIsVALUE" is not a Hash", obj); + } + } + else { + rb_ivar_set(obj, rb_intern_str(sym), val); } } while (--len > 0); } @@ -1611,11 +1720,20 @@ append_extmod(VALUE obj, VALUE extmod) (str)); \ } while (0) +static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type); + static VALUE -r_object0(struct load_arg *arg, int *ivp, VALUE extmod) +r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod) { - VALUE v = Qnil; int type = r_byte(arg); + return r_object_for(arg, partial, ivp, extmod, type); +} + +static VALUE +r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type) +{ + VALUE (*hash_new_with_size)(st_index_t) = rb_hash_new_with_size; + VALUE v = Qnil; long id; st_data_t link; @@ -1626,15 +1744,18 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) rb_raise(rb_eArgError, "dump format error (unlinked)"); } v = (VALUE)link; - v = r_post_proc(v, arg); + if (!st_lookup(arg->partial_objects, (st_data_t)v, &link)) { + v = r_post_proc(v, arg); + } break; case TYPE_IVAR: { int ivar = TRUE; - v = r_object0(arg, &ivar, extmod); + v = r_object0(arg, true, &ivar, extmod); if (ivar) r_ivar(v, NULL, arg); + v = r_leave(v, arg, partial); } break; @@ -1647,7 +1768,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) if (RB_TYPE_P(m, T_CLASS)) { /* prepended */ VALUE c; - v = r_object0(arg, 0, Qnil); + v = r_object0(arg, true, 0, Qnil); c = CLASS_OF(v); if (c != m || FL_TEST(c, FL_SINGLETON)) { rb_raise(rb_eArgError, @@ -1664,7 +1785,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) must_be_module(m, path); rb_ary_push(extmod, m); - v = r_object0(arg, 0, extmod); + v = r_object0(arg, true, 0, extmod); while (RARRAY_LEN(extmod) > 0) { m = rb_ary_pop(extmod); rb_extend_object(v, m); @@ -1680,10 +1801,16 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) if (FL_TEST(c, FL_SINGLETON)) { rb_raise(rb_eTypeError, "singleton can't be loaded"); } - v = r_object0(arg, 0, extmod); + type = r_byte(arg); + if ((c == rb_cHash) && + /* Hack for compare_by_identify */ + (type == TYPE_HASH || type == TYPE_HASH_DEF)) { + hash_new_with_size = rb_ident_hash_new_with_size; + goto type_hash; + } + v = r_object_for(arg, partial, 0, extmod, type); if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) { - format_error: - rb_raise(rb_eArgError, "dump format error (user class)"); + goto format_error; } if (RB_TYPE_P(v, T_MODULE) || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) { VALUE tmp = rb_obj_alloc(c); @@ -1694,19 +1821,22 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } break; + format_error: + rb_raise(rb_eArgError, "dump format error (user class)"); + case TYPE_NIL: v = Qnil; - v = r_leave(v, arg); + v = r_leave(v, arg, false); break; case TYPE_TRUE: v = Qtrue; - v = r_leave(v, arg); + v = r_leave(v, arg, false); break; case TYPE_FALSE: v = Qfalse; - v = r_leave(v, arg); + v = r_leave(v, arg, false); break; case TYPE_FIXNUM: @@ -1714,7 +1844,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) long i = r_long(arg); v = LONG2FIX(i); } - v = r_leave(v, arg); + v = r_leave(v, arg, false); break; case TYPE_FLOAT: @@ -1739,7 +1869,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } v = DBL2NUM(d); v = r_entry(v, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, false); } break; @@ -1756,13 +1886,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) INTEGER_PACK_LITTLE_ENDIAN | (sign == '-' ? INTEGER_PACK_NEGATIVE : 0)); rb_str_resize(data, 0L); v = r_entry(v, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, false); } break; case TYPE_STRING: v = r_entry(r_string(arg), arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); break; case TYPE_REGEXP: @@ -1797,7 +1927,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) rb_str_set_len(str, dst - ptr); } v = r_entry0(rb_reg_new_str(str, options), idx, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -1812,17 +1942,18 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) rb_ary_push(v, r_object(arg)); arg->readable--; } - v = r_leave(v, arg); + v = r_leave(v, arg, partial); arg->readable++; } break; case TYPE_HASH: case TYPE_HASH_DEF: + type_hash: { long len = r_long(arg); - v = rb_hash_new_with_size(len); + v = hash_new_with_size(len); v = r_entry(v, arg); arg->readable += (len - 1) * 2; while (len--) { @@ -1835,7 +1966,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) if (type == TYPE_HASH_DEF) { RHASH_SET_IFNONE(v, r_object(arg)); } - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -1887,7 +2018,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } } rb_struct_initialize(v, values); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); arg->readable += 2; } break; @@ -1914,7 +2045,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) marshal_compat_t *compat = (marshal_compat_t*)d; v = compat->loader(klass, v); } - v = r_post_proc(v, arg); + if (!partial) v = r_post_proc(v, arg); } break; @@ -1956,7 +2087,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } v = r_entry0(v, idx, arg); r_ivar(v, NULL, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -1977,9 +2108,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) "class %"PRIsVALUE" needs to have instance method `_load_data'", name); } - r = r_object0(arg, 0, extmod); + r = r_object0(arg, partial, 0, extmod); load_funcall(arg, v, s_load_data, 1, &r); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -1990,7 +2121,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = rb_path_to_class(str); prohibit_ivar("class/module", str); v = r_entry(v, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -2001,7 +2132,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = path2class(str); prohibit_ivar("class", str); v = r_entry(v, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -2012,7 +2143,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = path2module(str); prohibit_ivar("module", str); v = r_entry(v, arg); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); } break; @@ -2025,7 +2156,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = r_symreal(arg, 0); } v = rb_str_intern(v); - v = r_leave(v, arg); + v = r_leave(v, arg, partial); break; case TYPE_SYMLINK: @@ -2047,7 +2178,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) static VALUE r_object(struct load_arg *arg) { - return r_object0(arg, 0, Qnil); + return r_object0(arg, false, 0, Qnil); } static void @@ -2065,39 +2196,16 @@ clear_load_arg(struct load_arg *arg) arg->symbols = 0; st_free_table(arg->data); arg->data = 0; + st_free_table(arg->partial_objects); + arg->partial_objects = 0; if (arg->compat_tbl) { st_free_table(arg->compat_tbl); arg->compat_tbl = 0; } } -/* - * call-seq: - * load( source [, proc] ) -> obj - * restore( source [, proc] ) -> obj - * - * Returns the result of converting the serialized data in source into a - * Ruby object (possibly with associated subordinate objects). source - * may be either an instance of IO or an object that responds to - * to_str. If proc is specified, each object will be passed to the proc, as the object - * is being deserialized. - * - * Never pass untrusted data (including user supplied input) to this method. - * Please see the overview for further details. - */ -static VALUE -marshal_load(int argc, VALUE *argv, VALUE _) -{ - VALUE port, proc; - - rb_check_arity(argc, 1, 2); - port = argv[0]; - proc = argc > 1 ? argv[1] : Qnil; - return rb_marshal_load_with_proc(port, proc); -} - VALUE -rb_marshal_load_with_proc(VALUE port, VALUE proc) +rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze) { int major, minor; VALUE v; @@ -2119,9 +2227,11 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc) arg->offset = 0; arg->symbols = st_init_numtable(); arg->data = rb_init_identtable(); + arg->partial_objects = rb_init_identtable(); arg->compat_tbl = 0; arg->proc = 0; arg->readable = 0; + arg->freeze = freeze; if (NIL_P(v)) arg->buf = xmalloc(BUFSIZ); @@ -2150,6 +2260,13 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc) return v; } +static VALUE marshal_load(rb_execution_context_t *ec, VALUE mod, VALUE source, VALUE proc, VALUE freeze) +{ + return rb_marshal_load_with_proc(source, proc, RTEST(freeze)); +} + +#include "marshal.rbinc" + /* * The marshaling library converts collections of Ruby objects into a * byte stream, allowing them to be stored outside the currently @@ -2264,9 +2381,6 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc) void Init_marshal(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - VALUE rb_mMarshal = rb_define_module("Marshal"); #define set_id(sym) sym = rb_intern_const(name_##sym) set_id(s_dump); @@ -2282,10 +2396,9 @@ Init_marshal(void) set_id(s_write); set_id(s_binmode); set_id(s_encoding_short); + set_id(s_ruby2_keywords_flag); rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1); - rb_define_module_function(rb_mMarshal, "load", marshal_load, -1); - rb_define_module_function(rb_mMarshal, "restore", marshal_load, -1); /* major version */ rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR)); @@ -2315,5 +2428,5 @@ rb_marshal_dump(VALUE obj, VALUE port) VALUE rb_marshal_load(VALUE port) { - return rb_marshal_load_with_proc(port, Qnil); + return rb_marshal_load_with_proc(port, Qnil, false); } diff --git a/ruby/marshal.rb b/ruby/marshal.rb new file mode 100644 index 000000000..9ff74dd8b --- /dev/null +++ b/ruby/marshal.rb @@ -0,0 +1,40 @@ +module Marshal + # call-seq: + # load(source, proc = nil, freeze: false) -> obj + # restore(source, proc = nil, freeze: false) -> obj + # + # Returns the result of converting the serialized data in source into a + # Ruby object (possibly with associated subordinate objects). source + # may be either an instance of IO or an object that responds to + # to_str. If proc is specified, each object will be passed to the proc, as the object + # is being deserialized. + # + # Never pass untrusted data (including user supplied input) to this method. + # Please see the overview for further details. + # + # If the freeze: true argument is passed, deserialized object would + # be deeply frozen. Note that it may lead to more efficient memory usage due to + # frozen strings deduplication: + # + # serialized = Marshal.dump(['value1', 'value2', 'value1', 'value2']) + # + # deserialized = Marshal.load(serialized) + # deserialized.map(&:frozen?) + # # => [false, false, false, false] + # deserialized.map(&:object_id) + # # => [1023900, 1023920, 1023940, 1023960] -- 4 different objects + # + # deserialized = Marshal.load(serialized, freeze: true) + # deserialized.map(&:frozen?) + # # => [true, true, true, true] + # deserialized.map(&:object_id) + # # => [1039360, 1039380, 1039360, 1039380] -- only 2 different objects, object_ids repeating + # + def self.load(source, proc = nil, freeze: false) + Primitive.marshal_load(source, proc, freeze) + end + + class << self + alias restore load + end +end diff --git a/ruby/math.c b/ruby/math.c index d98467ca0..cce29b526 100644 --- a/ruby/math.c +++ b/ruby/math.c @@ -9,20 +9,22 @@ **********************************************************************/ +#include "ruby/internal/config.h" + #ifdef _MSC_VER # define _USE_MATH_DEFINES 1 #endif -#include "internal.h" + +#include #include #include -#include - -#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \ - !defined(signbit) - extern int signbit(double); -#endif -#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM) +#include "internal.h" +#include "internal/bignum.h" +#include "internal/complex.h" +#include "internal/math.h" +#include "internal/object.h" +#include "internal/vm.h" VALUE rb_mMath; VALUE rb_eMathDomainError; @@ -30,7 +32,11 @@ VALUE rb_eMathDomainError; #define Get_Double(x) rb_num_to_dbl(x) #define domain_error(msg) \ - rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg) + rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " msg) +#define domain_check_min(val, min, msg) \ + ((val) < (min) ? domain_error(msg) : (void)0) +#define domain_check_range(val, min, max, msg) \ + ((val) < (min) || (max) < (val) ? domain_error(msg) : (void)0) /* * call-seq: @@ -175,8 +181,7 @@ math_acos(VALUE unused_obj, VALUE x) double d; d = Get_Double(x); - /* check for domain error */ - if (d < -1.0 || 1.0 < d) domain_error("acos"); + domain_check_range(d, -1.0, 1.0, "acos"); return DBL2NUM(acos(d)); } @@ -199,8 +204,7 @@ math_asin(VALUE unused_obj, VALUE x) double d; d = Get_Double(x); - /* check for domain error */ - if (d < -1.0 || 1.0 < d) domain_error("asin"); + domain_check_range(d, -1.0, 1.0, "asin"); return DBL2NUM(asin(d)); } @@ -334,8 +338,7 @@ math_acosh(VALUE unused_obj, VALUE x) double d; d = Get_Double(x); - /* check for domain error */ - if (d < 1.0) domain_error("acosh"); + domain_check_min(d, 1.0, "acosh"); return DBL2NUM(acosh(d)); } @@ -379,8 +382,7 @@ math_atanh(VALUE unused_obj, VALUE x) double d; d = Get_Double(x); - /* check for domain error */ - if (d < -1.0 || +1.0 < d) domain_error("atanh"); + domain_check_range(d, -1.0, +1.0, "atanh"); /* check for pole error */ if (d == -1.0) return DBL2NUM(-HUGE_VAL); if (d == +1.0) return DBL2NUM(+HUGE_VAL); @@ -492,8 +494,7 @@ math_log1(VALUE x) size_t numbits; double d = get_double_rshift(x, &numbits); - /* check for domain error */ - if (d < 0.0) domain_error("log"); + domain_check_min(d, 0.0, "log"); /* check for pole error */ if (d == 0.0) return -HUGE_VAL; @@ -535,8 +536,7 @@ math_log2(VALUE unused_obj, VALUE x) size_t numbits; double d = get_double_rshift(x, &numbits); - /* check for domain error */ - if (d < 0.0) domain_error("log2"); + domain_check_min(d, 0.0, "log2"); /* check for pole error */ if (d == 0.0) return DBL2NUM(-HUGE_VAL); @@ -565,8 +565,7 @@ math_log10(VALUE unused_obj, VALUE x) size_t numbits; double d = get_double_rshift(x, &numbits); - /* check for domain error */ - if (d < 0.0) domain_error("log10"); + domain_check_min(d, 0.0, "log10"); /* check for pole error */ if (d == 0.0) return DBL2NUM(-HUGE_VAL); @@ -614,20 +613,19 @@ math_sqrt(VALUE unused_obj, VALUE x) return rb_math_sqrt(x); } -#define f_boolcast(x) ((x) ? Qtrue : Qfalse) inline static VALUE f_negative_p(VALUE x) { if (FIXNUM_P(x)) - return f_boolcast(FIX2LONG(x) < 0); + return RBOOL(FIX2LONG(x) < 0); return rb_funcall(x, '<', 1, INT2FIX(0)); } inline static VALUE f_signbit(VALUE x) { - if (RB_TYPE_P(x, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(x)) { double f = RFLOAT_VALUE(x); - return f_boolcast(!isnan(f) && signbit(f)); + return RBOOL(!isnan(f) && signbit(f)); } return f_negative_p(x); } @@ -647,8 +645,7 @@ rb_math_sqrt(VALUE x) return rb_complex_new(DBL2NUM(re), DBL2NUM(im)); } d = Get_Double(x); - /* check for domain error */ - if (d < 0.0) domain_error("sqrt"); + domain_check_min(d, 0.0, "sqrt"); if (d == 0.0) return DBL2NUM(0.0); return DBL2NUM(sqrt(d)); } @@ -694,7 +691,7 @@ math_cbrt(VALUE unused_obj, VALUE x) double f = Get_Double(x); double r = cbrt(f); #if defined __GLIBC__ - if (isfinite(r)) { + if (isfinite(r) && !(f == 0.0 && r == 0.0)) { r = (2.0 * r + (f / r / r)) / 3.0; } #endif @@ -800,7 +797,7 @@ math_erfc(VALUE unused_obj, VALUE x) * * Calculates the gamma function of x. * - * Note that gamma(n) is same as fact(n-1) for integer n > 0. + * Note that gamma(n) is the same as fact(n-1) for integer n > 0. * However gamma(n) returns float and can be an approximation. * * def fact(n) (1..n).inject(1) {|r,i| r*i } end @@ -877,7 +874,7 @@ math_gamma(VALUE unused_obj, VALUE x) return signbit(d) ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); } if (d == floor(d)) { - if (d < 0.0) domain_error("gamma"); + domain_check_min(d, 0.0, "gamma"); if (1.0 <= d && d <= (double)NFACT_TABLE) { return DBL2NUM(fact_table[(int)d - 1]); } @@ -891,9 +888,9 @@ math_gamma(VALUE unused_obj, VALUE x) * * Calculates the logarithmic gamma of +x+ and the sign of gamma of +x+. * - * Math.lgamma(x) is same as + * Math.lgamma(x) is the same as * [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1] - * but avoid overflow by Math.gamma(x) for large x. + * but avoids overflow by Math.gamma(x) for large x. * * Math.lgamma(0) #=> [Infinity, 1] * diff --git a/ruby/memory_view.c b/ruby/memory_view.c new file mode 100644 index 000000000..637d427e8 --- /dev/null +++ b/ruby/memory_view.c @@ -0,0 +1,872 @@ +/********************************************************************** + + memory_view.c - Memory View + + Copyright (C) 2020 Kenta Murata + +**********************************************************************/ + +#include "internal.h" +#include "internal/hash.h" +#include "internal/variable.h" +#include "ruby/memory_view.h" +#include "ruby/util.h" +#include "vm_sync.h" + +#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 + + +#define STRUCT_ALIGNOF(T, result) do { \ + (result) = RUBY_ALIGNOF(T); \ +} while(0) + +// Exported Object Registry + +static st_table *exported_object_table = NULL; +VALUE rb_memory_view_exported_object_registry = Qundef; + +static int +exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t data) +{ + rb_gc_mark(key); + return ST_CONTINUE; +} + +static void +exported_object_registry_mark(void *ptr) +{ + // Don't use RB_VM_LOCK_ENTER here. It is unnecessary during GC. + st_foreach(exported_object_table, exported_object_registry_mark_key_i, 0); +} + +static void +exported_object_registry_free(void *ptr) +{ + RB_VM_LOCK_ENTER(); + st_clear(exported_object_table); + st_free_table(exported_object_table); + exported_object_table = NULL; + RB_VM_LOCK_LEAVE(); +} + +const rb_data_type_t rb_memory_view_exported_object_registry_data_type = { + "memory_view/exported_object_registry", + { + exported_object_registry_mark, + exported_object_registry_free, + 0, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static int +exported_object_add_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing) +{ + ASSERT_vm_locking(); + + if (existing) { + *val += 1; + } + else { + *val = 1; + } + return ST_CONTINUE; +} + +static int +exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing) +{ + ASSERT_vm_locking(); + + if (existing) { + *val -= 1; + if (*val == 0) { + return ST_DELETE; + } + } + return ST_CONTINUE; +} + +static void +register_exported_object(VALUE obj) +{ + RB_VM_LOCK_ENTER(); + st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0); + RB_VM_LOCK_LEAVE(); +} + +static void +unregister_exported_object(VALUE obj) +{ + RB_VM_LOCK_ENTER(); + if (exported_object_table) + st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0); + RB_VM_LOCK_LEAVE(); +} + +// MemoryView + +static ID id_memory_view; + +static const rb_data_type_t memory_view_entry_data_type = { + "memory_view/entry", + { + 0, + 0, + 0, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +/* Register memory view functions for the given class */ +bool +rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry) +{ + Check_Type(klass, T_CLASS); + VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil); + if (! NIL_P(entry_obj)) { + rb_warning("Duplicated registration of memory view to %"PRIsVALUE, klass); + return false; + } + else { + entry_obj = TypedData_Wrap_Struct(0, &memory_view_entry_data_type, (void *)entry); + rb_ivar_set(klass, id_memory_view, entry_obj); + return true; + } +} + +/* Examine whether the given memory view has row-major order strides. */ +bool +rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view) +{ + const ssize_t ndim = view->ndim; + const ssize_t *shape = view->shape; + const ssize_t *strides = view->strides; + ssize_t n = view->item_size; + ssize_t i; + for (i = ndim - 1; i >= 0; --i) { + if (strides[i] != n) return false; + n *= shape[i]; + } + return true; +} + +/* Examine whether the given memory view has column-major order strides. */ +bool +rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view) +{ + const ssize_t ndim = view->ndim; + const ssize_t *shape = view->shape; + const ssize_t *strides = view->strides; + ssize_t n = view->item_size; + ssize_t i; + for (i = 0; i < ndim; ++i) { + if (strides[i] != n) return false; + n *= shape[i]; + } + return true; +} + +/* Initialize strides array to represent the specified contiguous array. */ +void +rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides) +{ + ssize_t i, n = item_size; + if (row_major_p) { + for (i = ndim - 1; i >= 0; --i) { + strides[i] = n; + n *= shape[i]; + } + } + else { // column-major + for (i = 0; i < ndim; ++i) { + strides[i] = n; + n *= shape[i]; + } + } +} + +/* Initialize view to expose a simple byte array */ +bool +rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly) +{ + view->obj = obj; + view->data = data; + view->byte_size = len; + view->readonly = readonly; + view->format = NULL; + view->item_size = 1; + view->item_desc.components = NULL; + view->item_desc.length = 0; + view->ndim = 1; + view->shape = NULL; + view->strides = NULL; + view->sub_offsets = NULL; + view->private_data = NULL; + + return true; +} + +#ifdef HAVE_TRUE_LONG_LONG +static const char native_types[] = "sSiIlLqQjJ"; +#else +static const char native_types[] = "sSiIlLjJ"; +#endif +static const char endianness_types[] = "sSiIlLqQjJ"; + +typedef enum { + ENDIANNESS_NATIVE, + ENDIANNESS_LITTLE, + ENDIANNESS_BIG +} endianness_t; + +static ssize_t +get_format_size(const char *format, bool *native_p, ssize_t *alignment, endianness_t *endianness, ssize_t *count, const char **next_format, VALUE *error) +{ + RUBY_ASSERT(format != NULL); + RUBY_ASSERT(native_p != NULL); + RUBY_ASSERT(endianness != NULL); + RUBY_ASSERT(count != NULL); + RUBY_ASSERT(next_format != NULL); + + *native_p = false; + *endianness = ENDIANNESS_NATIVE; + *count = 1; + + const int type_char = *format; + + int i = 1; + while (format[i]) { + switch (format[i]) { + case '!': + case '_': + if (strchr(native_types, type_char)) { + *native_p = true; + ++i; + } + else { + if (error) { + *error = rb_exc_new_str(rb_eArgError, + rb_sprintf("Unable to specify native size for '%c'", type_char)); + } + return -1; + } + continue; + + case '<': + case '>': + if (!strchr(endianness_types, type_char)) { + if (error) { + *error = rb_exc_new_str(rb_eArgError, + rb_sprintf("Unable to specify endianness for '%c'", type_char)); + } + return -1; + } + if (*endianness != ENDIANNESS_NATIVE) { + *error = rb_exc_new_cstr(rb_eArgError, "Unable to use both '<' and '>' multiple times"); + return -1; + } + *endianness = (format[i] == '<') ? ENDIANNESS_LITTLE : ENDIANNESS_BIG; + ++i; + continue; + + default: + break; + } + + break; + } + + // parse count + int ch = format[i]; + if ('0' <= ch && ch <= '9') { + ssize_t n = 0; + while ('0' <= (ch = format[i]) && ch <= '9') { + n = 10*n + ruby_digit36_to_number_table[ch]; + ++i; + } + *count = n; + } + + *next_format = &format[i]; + + switch (type_char) { + case 'x': // padding + return 1; + + case 'c': // signed char + case 'C': // unsigned char + return sizeof(char); + + case 's': // s for int16_t, s! for signed short + case 'S': // S for uint16_t, S! for unsigned short + if (*native_p) { + STRUCT_ALIGNOF(short, *alignment); + return sizeof(short); + } + // fall through + + case 'n': // n for big-endian 16bit unsigned integer + case 'v': // v for little-endian 16bit unsigned integer + STRUCT_ALIGNOF(int16_t, *alignment); + return 2; + + case 'i': // i and i! for signed int + case 'I': // I and I! for unsigned int + STRUCT_ALIGNOF(int, *alignment); + return sizeof(int); + + case 'l': // l for int32_t, l! for signed long + case 'L': // L for uint32_t, L! for unsigned long + if (*native_p) { + STRUCT_ALIGNOF(long, *alignment); + return sizeof(long); + } + // fall through + + case 'N': // N for big-endian 32bit unsigned integer + case 'V': // V for little-endian 32bit unsigned integer + STRUCT_ALIGNOF(int32_t, *alignment); + return 4; + + case 'f': // f for native float + case 'e': // e for little-endian float + case 'g': // g for big-endian float + STRUCT_ALIGNOF(float, *alignment); + return sizeof(float); + + case 'q': // q for int64_t, q! for signed long long + case 'Q': // Q for uint64_t, Q! for unsigned long long + if (*native_p) { + STRUCT_ALIGNOF(LONG_LONG, *alignment); + return sizeof(LONG_LONG); + } + STRUCT_ALIGNOF(int64_t, *alignment); + return 8; + + case 'd': // d for native double + case 'E': // E for little-endian double + case 'G': // G for big-endian double + STRUCT_ALIGNOF(double, *alignment); + return sizeof(double); + + case 'j': // j for intptr_t + case 'J': // J for uintptr_t + STRUCT_ALIGNOF(intptr_t, *alignment); + return sizeof(intptr_t); + + default: + *alignment = -1; + if (error) { + *error = rb_exc_new_str(rb_eArgError, rb_sprintf("Invalid type character '%c'", type_char)); + } + return -1; + } +} + +static inline ssize_t +calculate_padding(ssize_t total, ssize_t alignment_size) +{ + if (alignment_size > 1) { + ssize_t res = total % alignment_size; + if (res > 0) { + return alignment_size - res; + } + } + return 0; +} + +ssize_t +rb_memory_view_parse_item_format(const char *format, + rb_memory_view_item_component_t **members, + size_t *n_members, const char **err) +{ + if (format == NULL) return 1; + + VALUE error = Qnil; + ssize_t total = 0; + size_t len = 0; + bool alignment = false; + ssize_t max_alignment_size = 0; + + const char *p = format; + if (*p == '|') { // alignment specifier + alignment = true; + ++format; + ++p; + } + while (*p) { + const char *q = p; + + // ignore spaces + if (ISSPACE(*p)) { + while (ISSPACE(*p)) ++p; + continue; + } + + bool native_size_p = false; + ssize_t alignment_size = 0; + endianness_t endianness = ENDIANNESS_NATIVE; + ssize_t count = 0; + const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, &error); + if (size < 0) { + if (err) *err = q; + return -1; + } + if (max_alignment_size < alignment_size) { + max_alignment_size = alignment_size; + } + + const ssize_t padding = alignment ? calculate_padding(total, alignment_size) : 0; + total += padding + size * count; + + if (*q != 'x') { + ++len; + } + } + + // adjust total size with the alignment size of the largest element + if (alignment && max_alignment_size > 0) { + const ssize_t padding = calculate_padding(total, max_alignment_size); + total += padding; + } + + if (members && n_members) { + rb_memory_view_item_component_t *buf = ALLOC_N(rb_memory_view_item_component_t, len); + + ssize_t i = 0, offset = 0; + const char *p = format; + while (*p) { + const int type_char = *p; + + bool native_size_p; + ssize_t alignment_size = 0; + endianness_t endianness = ENDIANNESS_NATIVE; + ssize_t count = 0; + const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, NULL); + + const ssize_t padding = alignment ? calculate_padding(offset, alignment_size) : 0; + offset += padding; + + if (type_char != 'x') { +#ifdef WORDS_BIGENDIAN + bool little_endian_p = (endianness == ENDIANNESS_LITTLE); +#else + bool little_endian_p = (endianness != ENDIANNESS_BIG); +#endif + + switch (type_char) { + case 'e': + case 'E': + case 'v': + case 'V': + little_endian_p = true; + break; + case 'g': + case 'G': + case 'n': + case 'N': + little_endian_p = false; + break; + default: + break; + } + + buf[i++] = (rb_memory_view_item_component_t){ + .format = type_char, + .native_size_p = native_size_p, + .little_endian_p = little_endian_p, + .offset = offset, + .size = size, + .repeat = count + }; + } + + offset += size * count; + } + + *members = buf; + *n_members = len; + } + + return total; +} + +/* Return the item size. */ +ssize_t +rb_memory_view_item_size_from_format(const char *format, const char **err) +{ + return rb_memory_view_parse_item_format(format, NULL, NULL, err); +} + +/* Return the pointer to the item located by the given indices. */ +void * +rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices) +{ + uint8_t *ptr = view->data; + + if (view->ndim == 1) { + ssize_t stride = view->strides != NULL ? view->strides[0] : view->item_size; + return ptr + indices[0] * stride; + } + + assert(view->shape != NULL); + + ssize_t i; + if (view->strides == NULL) { + // row-major contiguous array + ssize_t stride = view->item_size; + for (i = 0; i < view->ndim; ++i) { + stride *= view->shape[i]; + } + for (i = 0; i < view->ndim; ++i) { + stride /= view->shape[i]; + ptr += indices[i] * stride; + } + } + else if (view->sub_offsets == NULL) { + // flat strided array + for (i = 0; i < view->ndim; ++i) { + ptr += indices[i] * view->strides[i]; + } + } + else { + // indirect strided array + for (i = 0; i < view->ndim; ++i) { + ptr += indices[i] * view->strides[i]; + if (view->sub_offsets[i] >= 0) { + ptr = *(uint8_t **)ptr + view->sub_offsets[i]; + } + } + } + + return ptr; +} + +static void +switch_endianness(uint8_t *buf, ssize_t len) +{ + RUBY_ASSERT(buf != NULL); + RUBY_ASSERT(len >= 0); + + uint8_t *p = buf; + uint8_t *q = buf + len - 1; + + while (q - p > 0) { + uint8_t t = *p; + *p = *q; + *q = t; + ++p; + --q; + } +} + +static inline VALUE +extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *member, const size_t i) +{ + RUBY_ASSERT(ptr != NULL); + RUBY_ASSERT(member != NULL); + RUBY_ASSERT(i < member->repeat); + +#ifdef WORDS_BIGENDIAN + const bool native_endian_p = !member->little_endian_p; +#else + const bool native_endian_p = member->little_endian_p; +#endif + + const uint8_t *p = ptr + member->offset + i * member->size; + + if (member->format == 'c') { + return INT2FIX(*(char *)p); + } + else if (member->format == 'C') { + return INT2FIX(*(unsigned char *)p); + } + + union { + short s; + unsigned short us; + int i; + unsigned int ui; + long l; + unsigned long ul; + LONG_LONG ll; + unsigned LONG_LONG ull; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; + intptr_t iptr; + uintptr_t uptr; + float f; + double d; + } val; + + if (!native_endian_p) { + MEMCPY(&val, p, uint8_t, member->size); + switch_endianness((uint8_t *)&val, member->size); + } + else { + MEMCPY(&val, p, uint8_t, member->size); + } + + switch (member->format) { + case 's': + if (member->native_size_p) { + return INT2FIX(val.s); + } + else { + return INT2FIX(val.i16); + } + + case 'S': + case 'n': + case 'v': + if (member->native_size_p) { + return UINT2NUM(val.us); + } + else { + return INT2FIX(val.u16); + } + + case 'i': + return INT2NUM(val.i); + + case 'I': + return UINT2NUM(val.ui); + + case 'l': + if (member->native_size_p) { + return LONG2NUM(val.l); + } + else { + return LONG2NUM(val.i32); + } + + case 'L': + case 'N': + case 'V': + if (member->native_size_p) { + return ULONG2NUM(val.ul); + } + else { + return ULONG2NUM(val.u32); + } + + case 'f': + case 'e': + case 'g': + return DBL2NUM(val.f); + + case 'q': + if (member->native_size_p) { + return LL2NUM(val.ll); + } + else { +#if SIZEOF_INT64_T == SIZEOF_LONG + return LONG2NUM(val.i64); +#else + return LL2NUM(val.i64); +#endif + } + + case 'Q': + if (member->native_size_p) { + return ULL2NUM(val.ull); + } + else { +#if SIZEOF_UINT64_T == SIZEOF_LONG + return ULONG2NUM(val.u64); +#else + return ULL2NUM(val.u64); +#endif + } + + case 'd': + case 'E': + case 'G': + return DBL2NUM(val.d); + + case 'j': + return INTPTR2NUM(val.iptr); + + case 'J': + return UINTPTR2NUM(val.uptr); + + default: + UNREACHABLE_RETURN(Qnil); + } +} + +/* Return a value of the extracted member. */ +VALUE +rb_memory_view_extract_item_member(const void *ptr, const rb_memory_view_item_component_t *member, const size_t i) +{ + if (ptr == NULL) return Qnil; + if (member == NULL) return Qnil; + if (i >= member->repeat) return Qnil; + + return extract_item_member(ptr, member, i); +} + +/* Return a value that consists of item members. + * When an item is a single member, the return value is a single value. + * When an item consists of multiple members, an array will be returned. */ +VALUE +rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members) +{ + if (ptr == NULL) return Qnil; + if (members == NULL) return Qnil; + if (n_members == 0) return Qnil; + + if (n_members == 1 && members[0].repeat == 1) { + return rb_memory_view_extract_item_member(ptr, members, 0); + } + + size_t i, j; + VALUE item = rb_ary_new(); + for (i = 0; i < n_members; ++i) { + for (j = 0; j < members[i].repeat; ++j) { + VALUE v = extract_item_member(ptr, &members[i], j); + rb_ary_push(item, v); + } + } + + return item; +} + +void +rb_memory_view_prepare_item_desc(rb_memory_view_t *view) +{ + if (view->item_desc.components == NULL) { + const char *err; + rb_memory_view_item_component_t **p_components = + (rb_memory_view_item_component_t **)&view->item_desc.components; + ssize_t n = rb_memory_view_parse_item_format(view->format, p_components, &view->item_desc.length, &err); + if (n < 0) { + rb_raise(rb_eRuntimeError, + "Unable to parse item format at %"PRIdSIZE" in \"%s\"", + (err - view->format), view->format); + } + } +} + +/* Return a value that consists of item members in the given memory view. */ +VALUE +rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices) +{ + void *ptr = rb_memory_view_get_item_pointer(view, indices); + + if (view->format == NULL) { + return INT2FIX(*(uint8_t *)ptr); + } + + if (view->item_desc.components == NULL) { + rb_memory_view_prepare_item_desc(view); + } + + return rb_memory_view_extract_item_members(ptr, view->item_desc.components, view->item_desc.length); +} + +static const rb_memory_view_entry_t * +lookup_memory_view_entry(VALUE klass) +{ + VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil); + while (NIL_P(entry_obj)) { + klass = rb_class_get_superclass(klass); + + if (klass == rb_cBasicObject || klass == rb_cObject) + return NULL; + + entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil); + } + + if (! rb_typeddata_is_kind_of(entry_obj, &memory_view_entry_data_type)) + return NULL; + + return (const rb_memory_view_entry_t *)RTYPEDDATA_DATA(entry_obj); +} + +/* Examine whether the given object supports memory view. */ +bool +rb_memory_view_available_p(VALUE obj) +{ + VALUE klass = CLASS_OF(obj); + const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass); + if (entry) + return (* entry->available_p_func)(obj); + else + return false; +} + +/* Obtain a memory view from obj, and substitute the information to view. */ +bool +rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags) +{ + VALUE klass = CLASS_OF(obj); + const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass); + if (entry) { + if (!(*entry->available_p_func)(obj)) { + return false; + } + + bool rv = (*entry->get_func)(obj, view, flags); + if (rv) { + view->_memory_view_entry = entry; + register_exported_object(view->obj); + } + return rv; + } + else + return false; +} + +/* Release the memory view obtained from obj. */ +bool +rb_memory_view_release(rb_memory_view_t* view) +{ + const rb_memory_view_entry_t *entry = view->_memory_view_entry; + if (entry) { + bool rv = true; + if (entry->release_func) { + rv = (*entry->release_func)(view->obj, view); + } + if (rv) { + unregister_exported_object(view->obj); + view->obj = Qnil; + if (view->item_desc.components) { + xfree((void *)view->item_desc.components); + } + } + return rv; + } + else + return false; +} + +void +Init_MemoryView(void) +{ + exported_object_table = rb_init_identtable(); + + // exported_object_table is referred through rb_memory_view_exported_object_registry + // in -test-/memory_view extension. + VALUE obj = TypedData_Wrap_Struct( + 0, &rb_memory_view_exported_object_registry_data_type, + exported_object_table); + rb_gc_register_mark_object(obj); + rb_memory_view_exported_object_registry = obj; + + id_memory_view = rb_intern_const("__memory_view__"); +} diff --git a/ruby/method.h b/ruby/method.h index b26caaa92..2f4504bfe 100644 --- a/ruby/method.h +++ b/ruby/method.h @@ -1,3 +1,5 @@ +#ifndef RUBY_METHOD_H +#define RUBY_METHOD_H 1 /********************************************************************** method.h - @@ -8,10 +10,11 @@ Copyright (C) 2009 Koichi Sasada **********************************************************************/ -#ifndef RUBY_METHOD_H -#define RUBY_METHOD_H 1 #include "internal.h" +#include "internal/imemo.h" +#include "internal/compilers.h" +#include "internal/static_assert.h" #ifndef END_OF_ENUMERATION # if defined(__GNUC__) &&! defined(__STRICT_ANSI__) @@ -41,7 +44,7 @@ typedef struct rb_scope_visi_struct { typedef struct rb_cref_struct { VALUE flags; VALUE refinements; - VALUE klass; + VALUE klass_or_self; struct rb_cref_struct * next; const rb_scope_visibility_t scope_visi; } rb_cref_t; @@ -66,8 +69,13 @@ typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_e #define METHOD_ENTRY_VISI(me) (rb_method_visibility_t)(((me)->flags & (IMEMO_FL_USER0 | IMEMO_FL_USER1)) >> (IMEMO_FL_USHIFT+0)) #define METHOD_ENTRY_BASIC(me) (int) (((me)->flags & (IMEMO_FL_USER2 )) >> (IMEMO_FL_USHIFT+2)) -#define METHOD_ENTRY_COMPLEMENTED(me) ((me)->flags & IMEMO_FL_USER3) -#define METHOD_ENTRY_COMPLEMENTED_SET(me) ((me)->flags = (me)->flags | IMEMO_FL_USER3) +#define METHOD_ENTRY_COMPLEMENTED(me) ((me)->flags & IMEMO_FL_USER3) +#define METHOD_ENTRY_COMPLEMENTED_SET(me) ((me)->flags |= IMEMO_FL_USER3) +#define METHOD_ENTRY_CACHED(me) ((me)->flags & IMEMO_FL_USER4) +#define METHOD_ENTRY_CACHED_SET(me) ((me)->flags |= IMEMO_FL_USER4) +#define METHOD_ENTRY_INVALIDATED(me) ((me)->flags & IMEMO_FL_USER5) +#define METHOD_ENTRY_INVALIDATED_SET(me) ((me)->flags |= IMEMO_FL_USER5) +#define METHOD_ENTRY_CACHEABLE(me) !(METHOD_ENTRY_VISI(me) == METHOD_VISI_PROTECTED) static inline void METHOD_ENTRY_VISI_SET(rb_method_entry_t *me, rb_method_visibility_t visi) @@ -124,7 +132,7 @@ typedef struct rb_iseq_struct rb_iseq_t; #endif typedef struct rb_method_iseq_struct { - rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */ + const rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */ rb_cref_t * cref; /*!< class reference, should be marked */ } rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */ @@ -151,19 +159,29 @@ typedef struct rb_method_refined_struct { typedef struct rb_method_bmethod_struct { VALUE proc; /* should be marked */ struct rb_hook_list_struct *hooks; + VALUE defined_ractor; } rb_method_bmethod_t; enum method_optimized_type { OPTIMIZED_METHOD_TYPE_SEND, OPTIMIZED_METHOD_TYPE_CALL, OPTIMIZED_METHOD_TYPE_BLOCK_CALL, + OPTIMIZED_METHOD_TYPE_STRUCT_AREF, + OPTIMIZED_METHOD_TYPE_STRUCT_ASET, OPTIMIZED_METHOD_TYPE__MAX }; +typedef struct rb_method_optimized { + enum method_optimized_type type; + unsigned int index; +} rb_method_optimized_t; + struct rb_method_definition_struct { BITFIELD(rb_method_type_t, type, VM_METHOD_TYPE_MINIMUM_BITS); - int alias_count : 28; + unsigned int iseq_overload: 1; + int alias_count : 27; int complemented_count : 28; + unsigned int no_redef_warning: 1; union { rb_method_iseq_t iseq; @@ -172,14 +190,15 @@ struct rb_method_definition_struct { rb_method_alias_t alias; rb_method_refined_t refined; rb_method_bmethod_t bmethod; - - enum method_optimized_type optimize_type; + rb_method_optimized_t optimized; } body; ID original_id; uintptr_t method_serial; }; +struct rb_id_table; + typedef struct rb_method_definition_struct rb_method_definition_t; STATIC_ASSERT(sizeof_method_def, offsetof(rb_method_definition_t, body)==8); @@ -188,10 +207,11 @@ STATIC_ASSERT(sizeof_method_def, offsetof(rb_method_definition_t, body)==8); ((def)->type == VM_METHOD_TYPE_REFINED && \ UNDEFINED_METHOD_ENTRY_P((def)->body.refined.orig_me)) +void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi); void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi); void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi); +void rb_add_method_optimized(VALUE klass, ID mid, enum method_optimized_type, unsigned int index, rb_method_visibility_t visi); void rb_add_refined_method_entry(VALUE refined_class, ID mid); -void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi); rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_visibility_t noex); rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def); @@ -222,8 +242,13 @@ const rb_method_entry_t *rb_method_entry_clone(const rb_method_entry_t *me); const rb_callable_method_entry_t *rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class); void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src); +void rb_method_table_insert(VALUE klass, struct rb_id_table *table, ID method_id, const rb_method_entry_t *me); + void rb_scope_visibility_set(rb_method_visibility_t); VALUE rb_unnamed_parameters(int arity); +void rb_clear_method_cache(VALUE klass_or_module, ID mid); +void rb_clear_method_cache_all(void); + #endif /* RUBY_METHOD_H */ diff --git a/ruby/mini_builtin.c b/ruby/mini_builtin.c index ad289bf89..8c8cf6626 100644 --- a/ruby/mini_builtin.c +++ b/ruby/mini_builtin.c @@ -1,6 +1,7 @@ #include "internal.h" -#include "vm_core.h" +#include "internal/array.h" #include "iseq.h" +#include "vm_core.h" #include "builtin.h" #include "miniprelude.c" @@ -22,7 +23,20 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta vm->builtin_function_table = table; vm->builtin_inline_index = 0; - const rb_iseq_t *iseq = rb_iseq_new(&ast->body, name_str, name_str, Qnil, NULL, ISEQ_TYPE_TOP); + static const rb_compile_option_t optimization = { + TRUE, /* int inline_const_cache; */ + TRUE, /* int peephole_optimization; */ + FALSE,/* int tailcall_optimization; */ + TRUE, /* int specialized_instruction; */ + TRUE, /* int operands_unification; */ + TRUE, /* int instructions_unification; */ + TRUE, /* int stack_caching; */ + TRUE, /* int frozen_string_literal; */ + FALSE, /* int debug_frozen_string_literal; */ + FALSE, /* unsigned int coverage_enabled; */ + 0, /* int debug_level; */ + }; + const rb_iseq_t *iseq = rb_iseq_new_with_opt(&ast->body, name_str, name_str, Qnil, INT2FIX(0), NULL, 0, ISEQ_TYPE_TOP, &optimization); GET_VM()->builtin_function_table = NULL; rb_ast_dispose(ast); diff --git a/ruby/miniprelude.c b/ruby/miniprelude.c index ae9ffe9f3..0c640edb3 100644 --- a/ruby/miniprelude.c +++ b/ruby/miniprelude.c @@ -3,16 +3,17 @@ sources: ./ast, ./gc, ./io, ./pack, ./trace_point, ./warning, ./prelude, ./gem_prelude */ -#include "ruby/ruby.h" #include "internal.h" -#include "vm_core.h" +#include "internal/warnings.h" #include "iseq.h" +#include "ruby/ruby.h" +#include "vm_core.h" static const char prelude_name0[] = ""; static const struct { - char L0[505]; /* 1..104 */ - char L104[361]; /* 105..145 */ + char L0[507]; /* 1..106 */ + char L106[361]; /* 107..147 */ } prelude_code0 = { #line 1 "ast.rb" "\n"/* for ast.c */ @@ -100,7 +101,9 @@ static const struct { "\n"/* */ "\n"/* root = RubyVM::AbstractSyntaxTree.parse(\"x = 1 + 2\") */ "\n"/* root.type # => :SCOPE */ -"\n"/* call = root.children[2] */ +"\n"/* lasgn = root.children[2] */ +"\n"/* lasgn.type # => :LASGN */ +"\n"/* call = lasgn.children[1] */ "\n"/* call.type # => :OPCALL */ " def type\n" " __builtin_ast_node_type\n" @@ -120,7 +123,7 @@ static const struct { "\n"/* The column number in the source code where this AST's text began. */ " def first_column\n" , -#line 105 "ast.rb" +#line 107 "ast.rb" " __builtin_ast_node_first_column\n" " end\n" "\n" @@ -161,14 +164,14 @@ static const struct { " end\n" " end\n" "end\n" -#line 165 "miniprelude.c" +#line 168 "miniprelude.c" }; static const char prelude_name1[] = ""; static const struct { char L0[506]; /* 1..71 */ - char L71[463]; /* 72..163 */ - char L163[204]; /* 164..170 */ + char L71[471]; /* 72..171 */ + char L171[204]; /* 172..178 */ } prelude_code1 = { #line 1 "gc.rb" "\n"/* for gc.c */ @@ -315,6 +318,10 @@ static const struct { "\n"/* The contents of the hash are implementation specific and may be changed in */ "\n"/* the future. */ "\n"/* */ +"\n"/* If the optional argument, hash, is given, */ +"\n"/* it is overwritten and returned. */ +"\n"/* This is intended to avoid probe effect. */ +"\n"/* */ "\n"/* This method is only expected to work on C Ruby. */ " def self.stat hash_or_key = nil\n" " __builtin_gc_stat hash_or_key\n" @@ -326,6 +333,10 @@ static const struct { "\n"/* GC.latest_gc_info(:major_by) -> :malloc */ "\n"/* */ "\n"/* Returns information about the most recent garbage collection. */ +"\n"/* */ +"\n"/* If the optional argument, hash, is given, */ +"\n"/* it is overwritten and returned. */ +"\n"/* This is intended to avoid probe effect. */ " def self.latest_gc_info hash_or_key = nil\n" " __builtin_gc_latest_gc_info hash_or_key\n" " end\n" @@ -337,14 +348,14 @@ static const struct { "\n" "module ObjectSpace\n" , -#line 164 "gc.rb" +#line 172 "gc.rb" " def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true\n" " __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep\n" " end\n" "\n" " module_function :garbage_collect\n" "end\n" -#line 348 "miniprelude.c" +#line 359 "miniprelude.c" }; static const char prelude_name2[] = ""; @@ -475,7 +486,7 @@ static const struct { " __builtin_io_write_nonblock(buf, exception)\n" " end\n" "end\n" -#line 479 "miniprelude.c" +#line 490 "miniprelude.c" }; static const char prelude_name3[] = ""; @@ -766,7 +777,7 @@ static const struct { " __builtin_pack_unpack1(fmt)\n" " end\n" "end\n" -#line 770 "miniprelude.c" +#line 781 "miniprelude.c" }; static const char prelude_name4[] = ""; @@ -962,7 +973,7 @@ static const struct { "\n"/* t.enable(target: method(:m1)) */ "\n"/* */ "\n"/* m1 */ -"\n"/* # prints # */ +"\n"/* # prints # */ "\n"/* m2 */ "\n"/* # prints nothing */ "\n"/* */ @@ -1131,7 +1142,7 @@ static const struct { " __builtin_tracepoint_attr_instruction_sequence\n" " end\n" "end\n" -#line 1135 "miniprelude.c" +#line 1146 "miniprelude.c" }; static const char prelude_name5[] = ""; @@ -1140,7 +1151,7 @@ static const struct { } prelude_code5 = { #line 1 "warning.rb" "\n"/* encoding: utf-8 */ -"\n"/* fronzen-string-literal: true */ +"\n"/* frozen-string-literal: true */ "\n" "module Kernel\n" " module_function\n" @@ -1184,7 +1195,7 @@ static const struct { " __builtin_rb_warn_m(msgs, uplevel)\n" " end\n" "end\n" -#line 1188 "miniprelude.c" +#line 1199 "miniprelude.c" }; static const char prelude_name6[] = ""; @@ -1229,7 +1240,7 @@ static const struct { "\n" " private :pp\n" "end\n" -#line 1233 "miniprelude.c" +#line 1244 "miniprelude.c" }; static const char prelude_name7[] = ""; @@ -1239,7 +1250,7 @@ static const struct { #line 1 "gem_prelude.rb" "require 'rubygems.rb' if defined?(Gem)\n" "require 'did_you_mean' if defined?(DidYouMean)\n" -#line 1243 "miniprelude.c" +#line 1254 "miniprelude.c" }; #define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1) diff --git a/ruby/misc/expand_tabs.rb b/ruby/misc/expand_tabs.rb index 7b3bff78f..a94eea504 100755 --- a/ruby/misc/expand_tabs.rb +++ b/ruby/misc/expand_tabs.rb @@ -59,46 +59,85 @@ def with_clean_env end DEFAULT_GEM_LIBS = %w[ + abbrev + base64 + benchmark bundler cmath csv - e2mmap + debug + delegate + did_you_mean + drb + english + erb fileutils + find forwardable + getoptlong ipaddr irb logger - matrix mutex_m + net-http + net-protocol + observer + open3 + open-uri + optparse ostruct + pp + prettyprint prime - racc + pstore rdoc + readline + reline + resolv + resolv-replace rexml + rinda rss + rubygems scanf - shell - sync + securerandom + set + shellwords + singleton + tempfile thwait - tracer - webrick + time + timeout + tmpdir + un + tsort + uri + weakref + yaml ] DEFAULT_GEM_EXTS = %w[ bigdecimal + cgi date - dbm + digest etc fcntl fiddle - gdbm - io/console + io-console + io-nonblock + io-wait json + nkf openssl + pathname psych - sdbm + racc + readline-ext stringio strscan + syslog + win32ole zlib ] diff --git a/ruby/misc/lldb_cruby.py b/ruby/misc/lldb_cruby.py index a582b7dde..53e42b711 100755 --- a/ruby/misc/lldb_cruby.py +++ b/ruby/misc/lldb_cruby.py @@ -11,6 +11,154 @@ import os import shlex +HEAP_PAGE_ALIGN_LOG = 14 +HEAP_PAGE_ALIGN_MASK = (~(~0 << HEAP_PAGE_ALIGN_LOG)) +HEAP_PAGE_ALIGN = (1 << HEAP_PAGE_ALIGN_LOG) +HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN + +class BackTrace: + VM_FRAME_MAGIC_METHOD = 0x11110001 + VM_FRAME_MAGIC_BLOCK = 0x22220001 + VM_FRAME_MAGIC_CLASS = 0x33330001 + VM_FRAME_MAGIC_TOP = 0x44440001 + VM_FRAME_MAGIC_CFUNC = 0x55550001 + VM_FRAME_MAGIC_IFUNC = 0x66660001 + VM_FRAME_MAGIC_EVAL = 0x77770001 + VM_FRAME_MAGIC_RESCUE = 0x78880001 + VM_FRAME_MAGIC_DUMMY = 0x79990001 + + VM_FRAME_MAGIC_MASK = 0x7fff0001 + + VM_FRAME_MAGIC_NAME = { + VM_FRAME_MAGIC_TOP: "TOP", + VM_FRAME_MAGIC_METHOD: "METHOD", + VM_FRAME_MAGIC_CLASS: "CLASS", + VM_FRAME_MAGIC_BLOCK: "BLOCK", + VM_FRAME_MAGIC_CFUNC: "CFUNC", + VM_FRAME_MAGIC_IFUNC: "IFUNC", + VM_FRAME_MAGIC_EVAL: "EVAL", + VM_FRAME_MAGIC_RESCUE: "RESCUE", + 0: "-----" + } + + def __init__(self, debugger, command, result, internal_dict): + self.debugger = debugger + self.command = command + self.result = result + + self.target = debugger.GetSelectedTarget() + self.process = self.target.GetProcess() + self.thread = self.process.GetSelectedThread() + self.frame = self.thread.GetSelectedFrame() + self.tRString = self.target.FindFirstType("struct RString").GetPointerType() + self.tRArray = self.target.FindFirstType("struct RArray").GetPointerType() + + rb_cft_len = len("rb_control_frame_t") + method_type_length = sorted(map(len, self.VM_FRAME_MAGIC_NAME.values()), reverse=True)[0] + # cfp address, method type, function name + self.fmt = "%%-%ds %%-%ds %%s" % (rb_cft_len, method_type_length) + + def vm_frame_magic(self, cfp): + ep = cfp.GetValueForExpressionPath("->ep") + frame_type = ep.GetChildAtIndex(0).GetValueAsUnsigned() & self.VM_FRAME_MAGIC_MASK + return self.VM_FRAME_MAGIC_NAME.get(frame_type, "(none)") + + def rb_iseq_path_str(self, iseq): + tRBasic = self.target.FindFirstType("struct RBasic").GetPointerType() + + pathobj = iseq.GetValueForExpressionPath("->body->location.pathobj") + pathobj = pathobj.Cast(tRBasic) + flags = pathobj.GetValueForExpressionPath("->flags").GetValueAsUnsigned() + flType = flags & RUBY_T_MASK + + if flType == RUBY_T_ARRAY: + pathobj = pathobj.Cast(self.tRArray) + + if flags & RUBY_FL_USER1: + len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3)) + ptr = pathobj.GetValueForExpressionPath("->as.ary") + else: + len = pathobj.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned() + ptr = pathobj.GetValueForExpressionPath("->as.heap.ptr") + + pathobj = ptr.GetChildAtIndex(0) + + pathobj = pathobj.Cast(self.tRString) + ptr, len = string2cstr(pathobj) + err = lldb.SBError() + path = self.target.process.ReadMemory(ptr, len, err) + if err.Success(): + return path.decode("utf-8") + else: + return "unknown" + + def dump_iseq_frame(self, cfp, iseq): + m = self.vm_frame_magic(cfp) + + if iseq.GetValueAsUnsigned(): + iseq_label = iseq.GetValueForExpressionPath("->body->location.label") + path = self.rb_iseq_path_str(iseq) + ptr, len = string2cstr(iseq_label.Cast(self.tRString)) + + err = lldb.SBError() + iseq_name = self.target.process.ReadMemory(ptr, len, err) + if err.Success(): + iseq_name = iseq_name.decode("utf-8") + else: + iseq_name = "error!!" + + else: + print("No iseq", file=self.result) + + print(self.fmt % (("%0#12x" % cfp.GetAddress().GetLoadAddress(self.target)), m, "%s %s" % (path, iseq_name)), file=self.result) + + def dump_cfunc_frame(self, cfp): + print(self.fmt % ("%0#12x" % (cfp.GetAddress().GetLoadAddress(self.target)), "CFUNC", ""), file=self.result) + + def print_bt(self, ec): + tRbExecutionContext_t = self.target.FindFirstType("rb_execution_context_t") + ec = ec.Cast(tRbExecutionContext_t.GetPointerType()) + vm_stack = ec.GetValueForExpressionPath("->vm_stack") + vm_stack_size = ec.GetValueForExpressionPath("->vm_stack_size") + + last_cfp_frame = ec.GetValueForExpressionPath("->cfp") + cfp_type_p = last_cfp_frame.GetType() + + stack_top = vm_stack.GetValueAsUnsigned() + ( + vm_stack_size.GetValueAsUnsigned() * vm_stack.GetType().GetByteSize()) + + cfp_frame_size = cfp_type_p.GetPointeeType().GetByteSize() + + start_cfp = stack_top + # Skip dummy frames + start_cfp -= cfp_frame_size + start_cfp -= cfp_frame_size + + last_cfp = last_cfp_frame.GetValueAsUnsigned() + + size = ((start_cfp - last_cfp) / cfp_frame_size) + 1 + + print(self.fmt % ("rb_control_frame_t", "TYPE", ""), file=self.result) + + curr_addr = start_cfp + + while curr_addr >= last_cfp: + cfp = self.target.CreateValueFromAddress("cfp", lldb.SBAddress(curr_addr, self.target), cfp_type_p.GetPointeeType()) + ep = cfp.GetValueForExpressionPath("->ep") + iseq = cfp.GetValueForExpressionPath("->iseq") + + frame_type = ep.GetChildAtIndex(0).GetValueAsUnsigned() & self.VM_FRAME_MAGIC_MASK + + if iseq.GetValueAsUnsigned(): + pc = cfp.GetValueForExpressionPath("->pc") + if pc.GetValueAsUnsigned(): + self.dump_iseq_frame(cfp, iseq) + else: + if frame_type == self.VM_FRAME_MAGIC_CFUNC: + self.dump_cfunc_frame(cfp) + + curr_addr -= cfp_frame_size + def lldb_init(debugger): target = debugger.GetSelectedTarget() global SIZEOF_VALUE @@ -42,7 +190,8 @@ def string2cstr(rstring): cptr = int(rstring.GetValueForExpressionPath(".as.heap.ptr").value, 0) clen = int(rstring.GetValueForExpressionPath(".as.heap.len").value, 0) else: - cptr = int(rstring.GetValueForExpressionPath(".as.ary").location, 0) + cptr = int(rstring.GetValueForExpressionPath(".as.embed.ary").location, 0) + # clen = int(rstring.GetValueForExpressionPath(".as.embed.len").value, 0) clen = (flags & RSTRING_EMBED_LEN_MASK) >> RSTRING_EMBED_LEN_SHIFT return cptr, clen @@ -110,9 +259,18 @@ def lldb_inspect(debugger, target, result, val): print('immediate(%x)' % num, file=result) else: tRBasic = target.FindFirstType("struct RBasic").GetPointerType() + tRValue = target.FindFirstType("struct RVALUE") + val = val.Cast(tRBasic) flags = val.GetValueForExpressionPath("->flags").GetValueAsUnsigned() flaginfo = "" + + page = get_page(lldb, target, val) + page_type = target.FindFirstType("struct heap_page").GetPointerType() + page.Cast(page_type) + + dump_bits(target, result, page, val.GetValueAsUnsigned()) + if (flags & RUBY_FL_PROMOTED) == RUBY_FL_PROMOTED: flaginfo += "[PROMOTED] " if (flags & RUBY_FL_FREEZE) == RUBY_FL_FREEZE: @@ -130,9 +288,18 @@ def lldb_inspect(debugger, target, result, val): append_command_output(debugger, "print *(struct RClass*)%0#x" % val.GetValueAsUnsigned(), result) elif flType == RUBY_T_STRING: result.write('T_STRING: %s' % flaginfo) + encidx = ((flags & RUBY_ENCODING_MASK)>>RUBY_ENCODING_SHIFT) + encname = target.FindFirstType("enum ruby_preserved_encindex").GetEnumMembers().GetTypeEnumMemberAtIndex(encidx).GetName() + if encname is not None: + result.write('[%s] ' % encname[14:]) + else: + result.write('[enc=%d] ' % encidx) tRString = target.FindFirstType("struct RString").GetPointerType() ptr, len = string2cstr(val.Cast(tRString)) - append_command_output(debugger, "print *(const char (*)[%d])%0#x" % (len, ptr), result) + if len == 0: + result.write("(empty)\n") + else: + append_command_output(debugger, "print *(const char (*)[%d])%0#x" % (len, ptr), result) elif flType == RUBY_T_SYMBOL: result.write('T_SYMBOL: %s' % flaginfo) tRSymbol = target.FindFirstType("struct RSymbol").GetPointerType() @@ -149,7 +316,6 @@ def lldb_inspect(debugger, target, result, val): else: len = val.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned() ptr = val.GetValueForExpressionPath("->as.heap.ptr") - #print(val.GetValueForExpressionPath("->as.heap"), file=result) result.write("T_ARRAY: %slen=%d" % (flaginfo, len)) if flags & RUBY_FL_USER1: result.write(" (embed)") @@ -173,20 +339,19 @@ def lldb_inspect(debugger, target, result, val): elif flType == RUBY_T_BIGNUM: tRBignum = target.FindFirstType("struct RBignum").GetPointerType() val = val.Cast(tRBignum) + sign = '+' if (flags & RUBY_FL_USER1) != 0 else '-' if flags & RUBY_FL_USER2: len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5)) >> (RUBY_FL_USHIFT+3)) - print("T_BIGNUM: len=%d (embed)" % len, file=result) + print("T_BIGNUM: sign=%s len=%d (embed)" % (sign, len), file=result) append_command_output(debugger, "print ((struct RBignum *) %0#x)->as.ary" % val.GetValueAsUnsigned(), result) else: len = val.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned() - print("T_BIGNUM: len=%d" % len, file=result) + print("T_BIGNUM: sign=%s len=%d" % (sign, len), file=result) print(val.Dereference(), file=result) append_command_output(debugger, "expression -Z %x -fx -- (const BDIGIT*)((struct RBignum*)%d)->as.heap.digits" % (len, val.GetValueAsUnsigned()), result) # append_command_output(debugger, "x ((struct RBignum *) %0#x)->as.heap.digits / %d" % (val.GetValueAsUnsigned(), len), result) elif flType == RUBY_T_FLOAT: - tRFloat = target.FindFirstType("struct RFloat").GetPointerType() - val = val.Cast(tRFloat) - append_command_output(debugger, "p *(double *)%0#x" % val.GetValueForExpressionPath("->float_value").GetAddress(), result) + append_command_output(debugger, "print ((struct RFloat *)%d)->float_value" % val.GetValueAsUnsigned(), result) elif flType == RUBY_T_RATIONAL: tRRational = target.FindFirstType("struct RRational").GetPointerType() val = val.Cast(tRRational) @@ -229,6 +394,24 @@ def lldb_inspect(debugger, target, result, val): append_command_output(debugger, "p (node_type) %d" % nd_type, result) val = val.Cast(tRTypedData) append_command_output(debugger, "p *(struct RNode *) %0#x" % val.GetValueAsUnsigned(), result) + elif flType == RUBY_T_MOVED: + tRTypedData = target.FindFirstType("struct RMoved").GetPointerType() + val = val.Cast(tRTypedData) + append_command_output(debugger, "p *(struct RMoved *) %0#x" % val.GetValueAsUnsigned(), result) + elif flType == RUBY_T_MATCH: + tRTypedData = target.FindFirstType("struct RMatch").GetPointerType() + val = val.Cast(tRTypedData) + append_command_output(debugger, "p *(struct RMatch *) %0#x" % val.GetValueAsUnsigned(), result) + elif flType == RUBY_T_IMEMO: + # I'm not sure how to get IMEMO_MASK out of lldb. It's not in globals() + imemo_type = (flags >> RUBY_FL_USHIFT) & 0x0F # IMEMO_MASK + print("T_IMEMO: ", file=result) + append_command_output(debugger, "p (enum imemo_type) %d" % imemo_type, result) + append_command_output(debugger, "p *(struct MEMO *) %0#x" % val.GetValueAsUnsigned(), result) + elif flType == RUBY_T_ZOMBIE: + tRZombie = target.FindFirstType("struct RZombie").GetPointerType() + val = val.Cast(tRZombie) + append_command_output(debugger, "p *(struct RZombie *) %0#x" % val.GetValueAsUnsigned(), result) else: print("Not-handled type %0#x" % flType, file=result) print(val, file=result) @@ -261,6 +444,49 @@ def count_objects(debugger, command, ctx, result, internal_dict): def stack_dump_raw(debugger, command, ctx, result, internal_dict): ctx.frame.EvaluateExpression("rb_vmdebug_stack_dump_raw_current()") +def check_bits(page, bitmap_name, bitmap_index, bitmap_bit, v): + bits = page.GetChildMemberWithName(bitmap_name) + plane = bits.GetChildAtIndex(bitmap_index).GetValueAsUnsigned() + if (plane & bitmap_bit) != 0: + return v + else: + return ' ' + +def heap_page(debugger, command, ctx, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + val = frame.EvaluateExpression(command) + page = get_page(lldb, target, val) + page_type = target.FindFirstType("struct heap_page").GetPointerType() + page.Cast(page_type) + append_command_output(debugger, "p (struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result) + append_command_output(debugger, "p *(struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result) + +def heap_page_body(debugger, command, ctx, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + val = frame.EvaluateExpression(command) + page = get_page_body(lldb, target, val) + print("Page body address: ", page.GetAddress(), file=result) + print(page, file=result) + +def get_page_body(lldb, target, val): + tHeapPageBody = target.FindFirstType("struct heap_page_body") + addr = val.GetValueAsUnsigned() + page_addr = addr & ~(HEAP_PAGE_ALIGN_MASK) + address = lldb.SBAddress(page_addr, target) + return target.CreateValueFromAddress("page", address, tHeapPageBody) + +def get_page(lldb, target, val): + body = get_page_body(lldb, target, val) + return body.GetValueForExpressionPath("->header.page") + def dump_node(debugger, command, ctx, result, internal_dict): args = shlex.split(command) if not args: @@ -270,10 +496,223 @@ def dump_node(debugger, command, ctx, result, internal_dict): dump = ctx.frame.EvaluateExpression("(struct RString*)rb_parser_dump_tree((NODE*)(%s), 0)" % node) output_string(ctx, result, dump) +def rb_backtrace(debugger, command, result, internal_dict): + bt = BackTrace(debugger, command, result, internal_dict) + frame = bt.frame + + if command: + if frame.IsValid(): + val = frame.EvaluateExpression(command) + else: + val = target.EvaluateExpression(command) + + error = val.GetError() + if error.Fail(): + print >> result, error + return + else: + print("Need an EC for now") + + bt.print_bt(val) + +def dump_bits(target, result, page, object_address, end = "\n"): + tRValue = target.FindFirstType("struct RVALUE") + tUintPtr = target.FindFirstType("uintptr_t") # bits_t + + num_in_page = (object_address & HEAP_PAGE_ALIGN_MASK) // tRValue.GetByteSize(); + bits_bitlength = tUintPtr.GetByteSize() * 8 + bitmap_index = num_in_page // bits_bitlength + bitmap_offset = num_in_page & (bits_bitlength - 1) + bitmap_bit = 1 << bitmap_offset + + print("bits: [%s%s%s%s%s]" % ( + check_bits(page, "uncollectible_bits", bitmap_index, bitmap_bit, "L"), + check_bits(page, "mark_bits", bitmap_index, bitmap_bit, "M"), + check_bits(page, "pinned_bits", bitmap_index, bitmap_bit, "P"), + check_bits(page, "marking_bits", bitmap_index, bitmap_bit, "R"), + check_bits(page, "wb_unprotected_bits", bitmap_index, bitmap_bit, "U"), + ), end=end, file=result) + +class HeapPageIter: + def __init__(self, page, target): + self.page = page + self.target = target + self.start = page.GetChildMemberWithName('start').GetValueAsUnsigned(); + self.num_slots = page.GetChildMemberWithName('total_slots').unsigned + self.slot_size = page.GetChildMemberWithName('size_pool').GetChildMemberWithName('slot_size').unsigned + self.counter = 0 + self.tRBasic = target.FindFirstType("struct RBasic") + self.tRValue = target.FindFirstType("struct RVALUE") + + def is_valid(self): + heap_page_header_size = self.target.FindFirstType("struct heap_page_header").GetByteSize() + rvalue_size = self.slot_size + heap_page_obj_limit = int((HEAP_PAGE_SIZE - heap_page_header_size) / self.slot_size) + + return (heap_page_obj_limit - 1) <= self.num_slots <= heap_page_obj_limit + + def __iter__(self): + return self + + def __next__(self): + if self.counter < self.num_slots: + obj_addr_i = self.start + (self.counter * self.slot_size) + obj_addr = lldb.SBAddress(obj_addr_i, self.target) + slot_info = (self.counter, obj_addr_i, self.target.CreateValueFromAddress("object", obj_addr, self.tRBasic)) + self.counter += 1 + + return slot_info + else: + raise StopIteration + + +def dump_page_internal(page, target, process, thread, frame, result, debugger, highlight=None): + if not ('RUBY_Qfalse' in globals()): + lldb_init(debugger) + + ruby_type_map = ruby_types(debugger) + + freelist = [] + fl_start = page.GetChildMemberWithName('freelist').GetValueAsUnsigned() + tRVALUE = target.FindFirstType("struct RVALUE") + + while fl_start > 0: + freelist.append(fl_start) + obj_addr = lldb.SBAddress(fl_start, target) + obj = target.CreateValueFromAddress("object", obj_addr, tRVALUE) + fl_start = obj.GetChildMemberWithName("as").GetChildMemberWithName("free").GetChildMemberWithName("next").GetValueAsUnsigned() + + + page_iter = HeapPageIter(page, target) + if page_iter.is_valid(): + for (page_index, obj_addr, obj) in page_iter: + dump_bits(target, result, page, obj_addr, end= " ") + flags = obj.GetChildMemberWithName('flags').GetValueAsUnsigned() + flType = flags & RUBY_T_MASK + + flidx = ' ' + if flType == RUBY_T_NONE: + try: + flidx = "%3d" % freelist.index(obj_addr) + except ValueError: + flidx = ' ' + + result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags) + + if highlight == obj_addr: + result_str = ' '.join([result_str, "<<<<<"]) + + print(result_str, file=result) + else: + print("%s is not a valid heap page" % page, file=result) + + + +def dump_page(debugger, command, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + tHeapPageP = target.FindFirstType("struct heap_page").GetPointerType() + page = frame.EvaluateExpression(command) + page = page.Cast(tHeapPageP) + + dump_page_internal(page, target, process, thread, frame, result, debugger) + + +def dump_page_rvalue(debugger, command, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + val = frame.EvaluateExpression(command) + page = get_page(lldb, target, val) + page_type = target.FindFirstType("struct heap_page").GetPointerType() + page.Cast(page_type) + + dump_page_internal(page, target, process, thread, frame, result, debugger, highlight=val.GetValueAsUnsigned()) + + + +def rb_type(flags, ruby_types): + flType = flags & RUBY_T_MASK + return "%-10s" % (ruby_types.get(flType, ("%0#x" % flType))) + +def ruby_types(debugger): + target = debugger.GetSelectedTarget() + + types = {} + for enum in target.FindFirstGlobalVariable('ruby_dummy_gdb_enums'): + enum = enum.GetType() + members = enum.GetEnumMembers() + for i in range(0, members.GetSize()): + member = members.GetTypeEnumMemberAtIndex(i) + name = member.GetName() + value = member.GetValueAsUnsigned() + + if name.startswith('RUBY_T_'): + types[value] = name.replace('RUBY_', '') + + return types + +def rb_ary_entry(target, ary, idx, result): + tRArray = target.FindFirstType("struct RArray").GetPointerType() + ary = ary.Cast(tRArray) + flags = ary.GetValueForExpressionPath("->flags").GetValueAsUnsigned() + + if flags & RUBY_FL_USER1: + ptr = ary.GetValueForExpressionPath("->as.ary") + else: + ptr = ary.GetValueForExpressionPath("->as.heap.ptr") + + ptr_addr = ptr.GetValueAsUnsigned() + (idx * ptr.GetType().GetByteSize()) + return target.CreateValueFromAddress("ary_entry[%d]" % idx, lldb.SBAddress(ptr_addr, target), ptr.GetType().GetPointeeType()) + +def rb_id_to_serial(id_val): + if id_val > tLAST_OP_ID: + return id_val >> RUBY_ID_SCOPE_SHIFT + else: + return id_val + +def rb_id2str(debugger, command, result, internal_dict): + if not ('RUBY_Qfalse' in globals()): + lldb_init(debugger) + + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + global_symbols = target.FindFirstGlobalVariable("ruby_global_symbols") + + id_val = frame.EvaluateExpression(command).GetValueAsUnsigned() + num = rb_id_to_serial(id_val) + + last_id = global_symbols.GetChildMemberWithName("last_id").GetValueAsUnsigned() + ID_ENTRY_SIZE = 2 + ID_ENTRY_UNIT = int(target.FindFirstGlobalVariable("ID_ENTRY_UNIT").GetValue()) + + ids = global_symbols.GetChildMemberWithName("ids") + + if (num <= last_id): + idx = num // ID_ENTRY_UNIT + ary = rb_ary_entry(target, ids, idx, result) + pos = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE + id_str = rb_ary_entry(target, ary, pos, result) + lldb_inspect(debugger, target, result, id_str) + def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand("command script add -f lldb_cruby.lldb_rp rp") debugger.HandleCommand("command script add -f lldb_cruby.count_objects rb_count_objects") debugger.HandleCommand("command script add -f lldb_cruby.stack_dump_raw SDR") debugger.HandleCommand("command script add -f lldb_cruby.dump_node dump_node") + debugger.HandleCommand("command script add -f lldb_cruby.heap_page heap_page") + debugger.HandleCommand("command script add -f lldb_cruby.heap_page_body heap_page_body") + debugger.HandleCommand("command script add -f lldb_cruby.rb_backtrace rbbt") + debugger.HandleCommand("command script add -f lldb_cruby.dump_page dump_page") + debugger.HandleCommand("command script add -f lldb_cruby.dump_page_rvalue dump_page_rvalue") + debugger.HandleCommand("command script add -f lldb_cruby.rb_id2str rb_id2str") + lldb_init(debugger) print("lldb scripts for ruby has been installed.") diff --git a/ruby/misc/lldb_disasm.py b/ruby/misc/lldb_disasm.py new file mode 100644 index 000000000..c02af52bc --- /dev/null +++ b/ruby/misc/lldb_disasm.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +#coding: utf-8 +# +# Usage: run `command script import -r misc/lldb_disasm.py` on LLDB +# +# +# (lldb) p iseq +# (rb_iseq_t *) $147 = 0x0000000101068400 +# (lldb) rbdisasm iseq +# 0000 putspecialobject( 3 ) +# 0002 putnil +# 0003 defineclass( ID: 0x560b, (rb_iseq_t *)0x1010681d0, 2 ) +# 0007 pop +# 0008 putspecialobject( 3 ) +# 0010 putnil +# 0011 defineclass( ID: 0x56eb, (rb_iseq_t *)0x101063b58, 2 ) +# 0015 leave + + +import lldb +import os +import shlex + +class IseqDisassembler: + TS_VARIABLE = b'.'[0] + TS_CALLDATA = b'C'[0] + TS_CDHASH = b'H'[0] + TS_IC = b'K'[0] + TS_IVC = b'A'[0] + TS_ID = b'I'[0] + TS_ISE = b'T'[0] + TS_ISEQ = b'S'[0] + TS_OFFSET = b'O'[0] + TS_VALUE = b'V'[0] + TS_LINDEX = b'L'[0] + TS_FUNCPTR = b'F'[0] + TS_NUM = b'N'[0] + TS_BUILTIN = b'R'[0] + + ISEQ_OPT_DISPATCH = { + TS_BUILTIN: "(rb_builtin_function *)%0#x", + TS_NUM: "%d", + TS_FUNCPTR: "(rb_insn_func_t) %0#x", + TS_LINDEX: "%d", + TS_VALUE: "(VALUE)%0#x", + TS_OFFSET: "%d", + TS_ISEQ: "(rb_iseq_t *)%0#x", + TS_ISE: "(iseq_inline_storage_entry *)%0#x", + TS_ID: "ID: %0#x", + TS_IVC: "(struct iseq_inline_iv_cache_entry *)%0#x", + TS_IC: "(struct iseq_inline_cache_entry *)%0#x", + TS_CDHASH: "CDHASH (VALUE)%0#x", + TS_CALLDATA: "(struct rb_call_data *)%0#x", + TS_VARIABLE: "VARIABLE %0#x", + } + + def __init__(self, debugger, command, result, internal_dict): + self.debugger = debugger + self.command = command + self.result = result + self.internal_dict = internal_dict + + self.target = debugger.GetSelectedTarget() + self.process = self.target.GetProcess() + self.thread = self.process.GetSelectedThread() + self.frame = self.thread.GetSelectedFrame() + self.addr2insn = self.build_addr2insn(self.target) + self.tChar = self.target.FindFirstType("char") + + def disasm(self, val): + tRbISeq = self.target.FindFirstType("struct rb_iseq_struct").GetPointerType() + val = val.Cast(tRbISeq) + iseq_size = val.GetValueForExpressionPath("->body->iseq_size").GetValueAsUnsigned() + iseqs = val.GetValueForExpressionPath("->body->iseq_encoded") + idx = 0 + print("PC IDX insn_name(operands) ", file=self.result) + while idx < iseq_size: + m = self.iseq_extract_values(self.debugger, self.target, self.process, self.result, iseqs, idx) + if m < 1: + print("Error decoding", file=self.result) + return + else: + idx += m + + def build_addr2insn(self, target): + tIntPtr = target.FindFirstType("intptr_t") + size = target.EvaluateExpression('ruby_vminsn_type::VM_INSTRUCTION_SIZE').unsigned + sizeOfIntPtr = tIntPtr.GetByteSize() + addr_of_table = target.FindSymbols("vm_exec_core.insns_address_table")[0].GetSymbol().GetStartAddress().GetLoadAddress(target) + + my_dict = {} + + for insn in range(size): + addr_in_table = addr_of_table + (insn * sizeOfIntPtr) + addr = lldb.SBAddress(addr_in_table, target) + machine_insn = target.CreateValueFromAddress("insn", addr, tIntPtr).GetValueAsUnsigned() + my_dict[machine_insn] = insn + + return my_dict + + def rb_vm_insn_addr2insn2(self, target, result, wanted_addr): + return self.addr2insn.get(wanted_addr) + + def iseq_extract_values(self, debugger, target, process, result, iseqs, n): + tValueP = target.FindFirstType("VALUE") + sizeofValueP = tValueP.GetByteSize() + pc = iseqs.unsigned + (n * sizeofValueP) + insn = target.CreateValueFromAddress("i", lldb.SBAddress(pc, target), tValueP) + addr = insn.GetValueAsUnsigned() + orig_insn = self.rb_vm_insn_addr2insn2(target, result, addr) + + name = self.insn_name(target, process, result, orig_insn) + length = self.insn_len(target, orig_insn) + op_str = self.insn_op_types(target, process, result, orig_insn) + op_types = bytes(op_str, 'utf-8') + + if length != (len(op_types) + 1): + print("error decoding iseqs", file=result) + return -1 + + print("%0#14x %04d %s" % (pc, n, name), file=result, end="") + + if length == 1: + print("", file=result) + return length + + print("(", end="", file=result) + for idx, op_type in enumerate(op_types): + if idx == 0: + print(" ", end="", file=result) + else: + print(", ", end="", file=result) + + opAddr = lldb.SBAddress(iseqs.unsigned + ((n + idx + 1) * sizeofValueP), target) + opValue = target.CreateValueFromAddress("op", opAddr, tValueP) + op = opValue.GetValueAsUnsigned() + print(self.ISEQ_OPT_DISPATCH.get(op_type) % op, end="", file=result) + + print(" )", file=result) + return length + + def insn_len(self, target, offset): + size_of_char = self.tChar.GetByteSize() + + symbol = target.FindSymbols("insn_len.t")[0].GetSymbol() + section = symbol.GetStartAddress().GetSection() + addr_of_table = symbol.GetStartAddress().GetOffset() + + error = lldb.SBError() + length = section.GetSectionData().GetUnsignedInt8(error, addr_of_table + (offset * size_of_char)) + + if error.Success(): + return length + else: + print("error getting length: ", error) + + def insn_op_types(self, target, process, result, insn): + tUShort = target.FindFirstType("unsigned short") + + size_of_short = tUShort.GetByteSize() + size_of_char = self.tChar.GetByteSize() + + symbol = target.FindSymbols("insn_op_types.y")[0].GetSymbol() + section = symbol.GetStartAddress().GetSection() + addr_of_table = symbol.GetStartAddress().GetOffset() + + addr_in_table = addr_of_table + (insn * size_of_short) + + error = lldb.SBError() + offset = section.GetSectionData().GetUnsignedInt16(error, addr_in_table) + + if not error.Success(): + print("error getting op type offset: ", error) + + symbol = target.FindSymbols("insn_op_types.x")[0].GetSymbol() + section = symbol.GetStartAddress().GetSection() + addr_of_table = symbol.GetStartAddress().GetOffset() + addr_in_name_table = addr_of_table + (offset * size_of_char) + + error = lldb.SBError() + types = section.GetSectionData().GetString(error, addr_in_name_table) + if error.Success(): + return types + else: + print("error getting op types: ", error) + + def insn_name_table_offset(self, target, offset): + tUShort = target.FindFirstType("unsigned short") + size_of_short = tUShort.GetByteSize() + + symbol = target.FindSymbols("insn_name.y")[0].GetSymbol() + section = symbol.GetStartAddress().GetSection() + table_offset = symbol.GetStartAddress().GetOffset() + + table_offset = table_offset + (offset * size_of_short) + + error = lldb.SBError() + offset = section.GetSectionData().GetUnsignedInt16(error, table_offset) + + if error.Success(): + return offset + else: + print("error getting insn name table offset: ", error) + + def insn_name(self, target, process, result, offset): + symbol = target.FindSymbols("insn_name.x")[0].GetSymbol() + section = symbol.GetStartAddress().GetSection() + addr_of_table = symbol.GetStartAddress().GetOffset() + + name_table_offset = self.insn_name_table_offset(target, offset) + addr_in_name_table = addr_of_table + name_table_offset + + error = lldb.SBError() + name = section.GetSectionData().GetString(error, addr_in_name_table) + + if error.Success(): + return name + else: + print('error getting insn name', error) + +def disasm(debugger, command, result, internal_dict): + disassembler = IseqDisassembler(debugger, command, result, internal_dict) + frame = disassembler.frame + + if frame.IsValid(): + val = frame.EvaluateExpression(command) + else: + val = target.EvaluateExpression(command) + error = val.GetError() + if error.Fail(): + print >> result, error + return + + disassembler.disasm(val); + + +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand("command script add -f lldb_disasm.disasm rbdisasm") + print("lldb Ruby disasm installed.") diff --git a/ruby/misc/lldb_yjit.py b/ruby/misc/lldb_yjit.py new file mode 100644 index 000000000..cc37b990e --- /dev/null +++ b/ruby/misc/lldb_yjit.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +#coding: utf-8 +# +# Usage: run `command script import -r misc/lldb_yjit.py` on LLDB +# + +from __future__ import print_function +import lldb +import os +import shlex + +def list_comments(debugger, command, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + # Get the different types we need + rb_darray_meta_t = target.FindFirstType("rb_darray_meta_t") + codeblock_t = target.FindFirstType("codeblock_t") + yjit_comment = target.FindFirstType("yjit_comment") + + # Get the global variables we need + comments = target.FindFirstGlobalVariable("yjit_code_comments") + cb = target.FindFirstGlobalVariable("cb").Cast(codeblock_t.GetPointerType()) + + # Get the address of the memory block we're using + mem_addr = cb.GetChildMemberWithName("mem_block").GetValueAsUnsigned() + + # Find the size of the darray comment list + meta = comments.Cast(rb_darray_meta_t.GetPointerType()) + size = meta.GetChildMemberWithName("size").GetValueAsUnsigned() + + # Get the address of the block following the metadata header + t_offset = comments.GetValueAsUnsigned() + rb_darray_meta_t.GetByteSize() + + # Loop through each comment and print + for t in range(0, size): + addr = lldb.SBAddress(t_offset + (t * yjit_comment.GetByteSize()), target) + comment = target.CreateValueFromAddress("yjit_comment", addr, yjit_comment) + string = comment.GetChildMemberWithName("comment") + comment_offset = mem_addr + comment.GetChildMemberWithName("offset").GetValueAsUnsigned() + print("%0#x %s" % (comment_offset, string.GetSummary()), file = result) + + +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand("command script add -f lldb_yjit.list_comments lc") diff --git a/ruby/misc/rb_optparse.bash b/ruby/misc/rb_optparse.bash index 8a59ec2dd..f77d937c8 100644 --- a/ruby/misc/rb_optparse.bash +++ b/ruby/misc/rb_optparse.bash @@ -1,4 +1,5 @@ -#! /bin/bash +# -*- bash -*- +# # Completion for bash: # # (1) install this file, @@ -16,5 +17,5 @@ _rb_optparse() { } rb_optparse () { - [ $# = 0 ] || complete -o default -F _rb_optparse "$@" + [ $# = 0 ] || complete -o default -F _rb_optparse "$@" } diff --git a/ruby/misc/rb_optparse.zsh b/ruby/misc/rb_optparse.zsh old mode 100755 new mode 100644 index 7407e87c0..258d4f856 --- a/ruby/misc/rb_optparse.zsh +++ b/ruby/misc/rb_optparse.zsh @@ -1,4 +1,5 @@ -#!/bin/zsh +# -*- zsh -*- +# # Completion for zsh: # (based on ) # @@ -7,9 +8,9 @@ # cp rb_optparse.zsh ~/.zsh.d/rb_optparse.zsh # # (2) load the script, and add a directory to fpath before compinit. -# echo '. ~/.zsh.d/rb_optparse.zsh' >> ~/.zshrc -# echo 'fpath=(~/.zsh.d/Completion $fpath)' >> ~/.zshrc -# echo 'autoload -U compinit; compinit' >> ~/.zshrc +# echo '. ~/.zsh.d/rb_optparse.zsh' >> "${ZDOTDIR:-~}/.zshrc" +# echo 'fpath=(~/.zsh.d/Completion $fpath)' >> "${ZDOTDIR:-~}/.zshrc" +# echo 'autoload -U compinit; compinit' >> "${ZDOTDIR:-~}/.zshrc" # # (3) restart zsh. # @@ -24,8 +25,8 @@ generate-complete-function/ruby/optparse () mkdir -p "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}" $1 "--*-completion-zsh=${1:t}" >! "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}/$cmpl" if [[ $(type -w "$cmpl") == "${cmpl}: function" ]]; then - unfunction "$cmpl" - autoload -U "$cmpl" + unfunction "$cmpl" + autoload -U "$cmpl" else compinit "$cmpl" fi diff --git a/ruby/misc/test_yjit_asm.sh b/ruby/misc/test_yjit_asm.sh new file mode 100755 index 000000000..e09d83f0f --- /dev/null +++ b/ruby/misc/test_yjit_asm.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e +set -x + +clang -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wshorten-64-to-32 -I "${0%/*/*}" "${0%/*}/yjit_asm_tests.c" -o asm_test + +./asm_test + +rm asm_test diff --git a/ruby/misc/yjit_asm_tests.c b/ruby/misc/yjit_asm_tests.c new file mode 100644 index 000000000..ccf8822bb --- /dev/null +++ b/ruby/misc/yjit_asm_tests.c @@ -0,0 +1,443 @@ +// For MAP_ANONYMOUS on GNU/Linux +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include + +// This test executable doesn't compile with the rest of Ruby +// so we need to define a rb_bug(). +_Noreturn +static void rb_bug(const char *message, ...) +{ + va_list args; + va_start(args, message); + vfprintf(stderr, message, args); + va_end(args); + abort(); +} + +#include "yjit_asm.c" + +// Print the bytes in a code block +void print_bytes(codeblock_t* cb) +{ + for (uint32_t i = 0; i < cb->write_pos; ++i) + { + printf("%02X", (int)*cb_get_ptr(cb, i)); + } + + printf("\n"); +} + +// Check that the code block contains the given sequence of bytes +void check_bytes(codeblock_t* cb, const char* bytes) +{ + printf("checking encoding: %s\n", bytes); + + size_t len = strlen(bytes); + assert (len % 2 == 0); + size_t num_bytes = len / 2; + + if (cb->write_pos != num_bytes) + { + fprintf(stderr, "incorrect encoding length, expected %ld, got %d\n", + num_bytes, + cb->write_pos + ); + printf("%s\n", bytes); + print_bytes(cb); + exit(-1); + } + + for (uint32_t i = 0; i < num_bytes; ++i) + { + char byte_str[] = {0, 0, 0, 0}; + strncpy(byte_str, bytes + (2 * i), 2); + char* endptr; + long int byte = strtol(byte_str, &endptr, 16); + + uint8_t cb_byte = *cb_get_ptr(cb, i); + + if (cb_byte != byte) + { + fprintf(stderr, "incorrect encoding at position %d, expected %02X, got %02X\n", + i, + (int)byte, + (int)cb_byte + ); + printf("%s\n", bytes); + print_bytes(cb); + exit(-1); + } + } +} + +void run_assembler_tests(void) +{ + printf("Running assembler tests\n"); + + codeblock_t cb_obj; + codeblock_t* cb = &cb_obj; + uint8_t* mem_block = alloc_exec_mem(4096); + cb_init(cb, mem_block, 4096); + + // add + cb_set_pos(cb, 0); add(cb, CL, imm_opnd(3)); check_bytes(cb, "80C103"); + cb_set_pos(cb, 0); add(cb, CL, BL); check_bytes(cb, "00D9"); + cb_set_pos(cb, 0); add(cb, CL, SPL); check_bytes(cb, "4000E1"); + cb_set_pos(cb, 0); add(cb, CX, BX); check_bytes(cb, "6601D9"); + cb_set_pos(cb, 0); add(cb, RAX, RBX); check_bytes(cb, "4801D8"); + cb_set_pos(cb, 0); add(cb, ECX, EDX); check_bytes(cb, "01D1"); + cb_set_pos(cb, 0); add(cb, RDX, R14); check_bytes(cb, "4C01F2"); + cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 0), RDX); check_bytes(cb, "480110"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 0)); check_bytes(cb, "480310"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 8)); check_bytes(cb, "48035008"); + cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 255)); check_bytes(cb, "480390FF000000"); + cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 127), imm_opnd(255)); check_bytes(cb, "4881407FFF000000"); + cb_set_pos(cb, 0); add(cb, mem_opnd(32, RAX, 0), EDX); check_bytes(cb, "0110"); + cb_set_pos(cb, 0); add(cb, RSP, imm_opnd(8)); check_bytes(cb, "4883C408"); + cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(8)); check_bytes(cb, "83C108"); + cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(255)); check_bytes(cb, "81C1FF000000"); + + // and + cb_set_pos(cb, 0); and(cb, EBP, R12D); check_bytes(cb, "4421E5"); + cb_set_pos(cb, 0); and(cb, mem_opnd(64, RAX, 0), imm_opnd(0x08)); check_bytes(cb, "48832008"); + + // call + { + cb_set_pos(cb, 0); + uint32_t fn_label = cb_new_label(cb, "foo"); + call_label(cb, fn_label); + cb_link_labels(cb); + check_bytes(cb, "E8FBFFFFFF"); + } + cb_set_pos(cb, 0); call(cb, RAX); check_bytes(cb, "FFD0"); + cb_set_pos(cb, 0); call(cb, mem_opnd(64, RSP, 8)); check_bytes(cb, "FF542408"); + + // cmovcc + cb_set_pos(cb, 0); cmovg(cb, ESI, EDI); check_bytes(cb, "0F4FF7"); + cb_set_pos(cb, 0); cmovg(cb, ESI, mem_opnd(32, RBP, 12)); check_bytes(cb, "0F4F750C"); + cb_set_pos(cb, 0); cmovl(cb, EAX, ECX); check_bytes(cb, "0F4CC1"); + cb_set_pos(cb, 0); cmovl(cb, RBX, RBP); check_bytes(cb, "480F4CDD"); + cb_set_pos(cb, 0); cmovle(cb, ESI, mem_opnd(32, RSP, 4)); check_bytes(cb, "0F4E742404"); + + // cmp + cb_set_pos(cb, 0); cmp(cb, CL, DL); check_bytes(cb, "38D1"); + cb_set_pos(cb, 0); cmp(cb, ECX, EDI); check_bytes(cb, "39F9"); + cb_set_pos(cb, 0); cmp(cb, RDX, mem_opnd(64, R12, 0)); check_bytes(cb, "493B1424"); + cb_set_pos(cb, 0); cmp(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883F802"); + + // cqo + cb_set_pos(cb, 0); cqo(cb); check_bytes(cb, "4899"); + + // div + /* + test( + delegate void (CodeBlock cb) { cb.div(X86Opnd(EDX)); }, + "F7F2" + ); + test( + delegate void (CodeBlock cb) { cb.div(X86Opnd(32, RSP, -12)); }, + "F77424F4" + ); + */ + + // jcc to label + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jge_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "0F8DFAFFFFFF"); + } + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jo_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "0F80FAFFFFFF"); + } + + // jmp to label + { + cb_set_pos(cb, 0); + uint32_t loop_label = cb_new_label(cb, "loop"); + jmp_label(cb, loop_label); + cb_link_labels(cb); + check_bytes(cb, "E9FBFFFFFF"); + } + + // jmp with RM operand + cb_set_pos(cb, 0); jmp_rm(cb, R12); check_bytes(cb, "41FFE4"); + + // lea + cb_set_pos(cb, 0); lea(cb, RDX, mem_opnd(64, RCX, 8)); check_bytes(cb, "488D5108"); + cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 0)); check_bytes(cb, "488D0500000000"); + cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D0505000000"); + cb_set_pos(cb, 0); lea(cb, RDI, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D3D05000000"); + + // mov + cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(7)); check_bytes(cb, "B807000000"); + cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(-3)); check_bytes(cb, "B8FDFFFFFF"); + cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "41BF03000000"); + cb_set_pos(cb, 0); mov(cb, EAX, EBX); check_bytes(cb, "89D8"); + cb_set_pos(cb, 0); mov(cb, EAX, ECX); check_bytes(cb, "89C8"); + cb_set_pos(cb, 0); mov(cb, EDX, mem_opnd(32, RBX, 128)); check_bytes(cb, "8B9380000000"); + + // Test `mov rax, 3` => `mov eax, 3` optimization + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x34)); check_bytes(cb, "41B834000000"); + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x80000000)); check_bytes(cb, "49B80000008000000000"); + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(-1)); check_bytes(cb, "49B8FFFFFFFFFFFFFFFF"); + + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x34)); check_bytes(cb, "B834000000"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x80000000)); check_bytes(cb, "48B80000008000000000"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-52)); check_bytes(cb, "48B8CCFFFFFFFFFFFFFF"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-1)); check_bytes(cb, "48B8FFFFFFFFFFFFFFFF"); + /* + test( + delegate void (CodeBlock cb) { cb.mov(X86Opnd(AL), X86Opnd(8, RCX, 0, 1, RDX)); }, + "8A0411" + ); + */ + cb_set_pos(cb, 0); mov(cb, CL, R9B); check_bytes(cb, "4488C9"); + cb_set_pos(cb, 0); mov(cb, RBX, RAX); check_bytes(cb, "4889C3"); + cb_set_pos(cb, 0); mov(cb, RDI, RBX); check_bytes(cb, "4889DF"); + cb_set_pos(cb, 0); mov(cb, SIL, imm_opnd(11)); check_bytes(cb, "40B60B"); + cb_set_pos(cb, 0); mov(cb, mem_opnd(8, RSP, 0), imm_opnd(-3)); check_bytes(cb, "C60424FD"); + cb_set_pos(cb, 0); mov(cb, mem_opnd(64, RDI, 8), imm_opnd(1)); check_bytes(cb, "48C7470801000000"); + + // movsx + cb_set_pos(cb, 0); movsx(cb, AX, AL); check_bytes(cb, "660FBEC0"); + cb_set_pos(cb, 0); movsx(cb, EDX, AL); check_bytes(cb, "0FBED0"); + cb_set_pos(cb, 0); movsx(cb, RAX, BL); check_bytes(cb, "480FBEC3"); + cb_set_pos(cb, 0); movsx(cb, ECX, AX); check_bytes(cb, "0FBFC8"); + cb_set_pos(cb, 0); movsx(cb, R11, CL); check_bytes(cb, "4C0FBED9"); + cb_set_pos(cb, 0); movsx(cb, R10, mem_opnd(32, RSP, 12)); check_bytes(cb, "4C6354240C"); + cb_set_pos(cb, 0); movsx(cb, RAX, mem_opnd(8, RSP, 0)); check_bytes(cb, "480FBE0424"); + + // neg + cb_set_pos(cb, 0); neg(cb, RAX); check_bytes(cb, "48F7D8"); + + // nop + cb_set_pos(cb, 0); nop(cb, 1); check_bytes(cb, "90"); + + // not + cb_set_pos(cb, 0); not(cb, AX); check_bytes(cb, "66F7D0"); + cb_set_pos(cb, 0); not(cb, EAX); check_bytes(cb, "F7D0"); + cb_set_pos(cb, 0); not(cb, mem_opnd(64, R12, 0)); check_bytes(cb, "49F71424"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 301)); check_bytes(cb, "F794242D010000"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 0)); check_bytes(cb, "F71424"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 3)); check_bytes(cb, "F7542403"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 0)); check_bytes(cb, "F75500"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 13)); check_bytes(cb, "F7550D"); + cb_set_pos(cb, 0); not(cb, RAX); check_bytes(cb, "48F7D0"); + cb_set_pos(cb, 0); not(cb, R11); check_bytes(cb, "49F7D3"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RAX, 0)); check_bytes(cb, "F710"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSI, 0)); check_bytes(cb, "F716"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDI, 0)); check_bytes(cb, "F717"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 55)); check_bytes(cb, "F75237"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 1337)); check_bytes(cb, "F79239050000"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -55)); check_bytes(cb, "F752C9"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -555)); check_bytes(cb, "F792D5FDFFFF"); + /* + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, RBX)); }, + "F71418" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, R12)); }, + "42F71420" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 0, 1, R12)); }, + "43F71427" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 1, R12)); }, + "43F7542705" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R12)); }, + "43F754E705" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R13)); }, + "43F754EF05" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 5, 4, R9)); }, + "43F7548C05" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 301, 4, R9)); }, + "43F7948C2D010000" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 5, 4, RDX)); }, + "F7549005" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(64, RAX, 0, 2, RDX)); }, + "48F71450" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 0, 1, RBX)); }, + "F7141C" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 3, 1, RBX)); }, + "F7541C03" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RBP, 13, 1, RDX)); }, + "F754150D" + ); + */ + + // or + cb_set_pos(cb, 0); or(cb, EDX, ESI); check_bytes(cb, "09F2"); + + // pop + cb_set_pos(cb, 0); pop(cb, RAX); check_bytes(cb, "58"); + cb_set_pos(cb, 0); pop(cb, RBX); check_bytes(cb, "5B"); + cb_set_pos(cb, 0); pop(cb, RSP); check_bytes(cb, "5C"); + cb_set_pos(cb, 0); pop(cb, RBP); check_bytes(cb, "5D"); + cb_set_pos(cb, 0); pop(cb, R12); check_bytes(cb, "415C"); + cb_set_pos(cb, 0); pop(cb, mem_opnd(64, RAX, 0)); check_bytes(cb, "8F00"); + cb_set_pos(cb, 0); pop(cb, mem_opnd(64, R8, 0)); check_bytes(cb, "418F00"); + cb_set_pos(cb, 0); pop(cb, mem_opnd(64, R8, 3)); check_bytes(cb, "418F4003"); + cb_set_pos(cb, 0); pop(cb, mem_opnd_sib(64, RAX, RCX, 8, 3)); check_bytes(cb, "8F44C803"); + cb_set_pos(cb, 0); pop(cb, mem_opnd_sib(64, R8, RCX, 8, 3)); check_bytes(cb, "418F44C803"); + + // push + cb_set_pos(cb, 0); push(cb, RAX); check_bytes(cb, "50"); + cb_set_pos(cb, 0); push(cb, RBX); check_bytes(cb, "53"); + cb_set_pos(cb, 0); push(cb, R12); check_bytes(cb, "4154"); + cb_set_pos(cb, 0); push(cb, mem_opnd(64, RAX, 0)); check_bytes(cb, "FF30"); + cb_set_pos(cb, 0); push(cb, mem_opnd(64, R8, 0)); check_bytes(cb, "41FF30"); + cb_set_pos(cb, 0); push(cb, mem_opnd(64, R8, 3)); check_bytes(cb, "41FF7003"); + cb_set_pos(cb, 0); push(cb, mem_opnd_sib(64, RAX, RCX, 8, 3)); check_bytes(cb, "FF74C803"); + cb_set_pos(cb, 0); push(cb, mem_opnd_sib(64, R8, RCX, 8, 3)); check_bytes(cb, "41FF74C803"); + + // ret + cb_set_pos(cb, 0); ret(cb); check_bytes(cb, "C3"); + + // sal + cb_set_pos(cb, 0); sal(cb, CX, imm_opnd(1)); check_bytes(cb, "66D1E1"); + cb_set_pos(cb, 0); sal(cb, ECX, imm_opnd(1)); check_bytes(cb, "D1E1"); + cb_set_pos(cb, 0); sal(cb, EBP, imm_opnd(5)); check_bytes(cb, "C1E505"); + cb_set_pos(cb, 0); sal(cb, mem_opnd(32, RSP, 68), imm_opnd(1)); check_bytes(cb, "D1642444"); + + // sar + cb_set_pos(cb, 0); sar(cb, EDX, imm_opnd(1)); check_bytes(cb, "D1FA"); + + // shr + cb_set_pos(cb, 0); shr(cb, R14, imm_opnd(7)); check_bytes(cb, "49C1EE07"); + + /* + // sqrtsd + test( + delegate void (CodeBlock cb) { cb.sqrtsd(X86Opnd(XMM2), X86Opnd(XMM6)); }, + "F20F51D6" + ); + */ + + // sub + cb_set_pos(cb, 0); sub(cb, EAX, imm_opnd(1)); check_bytes(cb, "83E801"); + cb_set_pos(cb, 0); sub(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883E802"); + + // test + cb_set_pos(cb, 0); test(cb, AL, AL); check_bytes(cb, "84C0"); + cb_set_pos(cb, 0); test(cb, AX, AX); check_bytes(cb, "6685C0"); + cb_set_pos(cb, 0); test(cb, CL, imm_opnd(8)); check_bytes(cb, "F6C108"); + cb_set_pos(cb, 0); test(cb, DL, imm_opnd(7)); check_bytes(cb, "F6C207"); + cb_set_pos(cb, 0); test(cb, RCX, imm_opnd(8)); check_bytes(cb, "F6C108"); + cb_set_pos(cb, 0); test(cb, mem_opnd(8, RDX, 8), imm_opnd(8)); check_bytes(cb, "F6420808"); + cb_set_pos(cb, 0); test(cb, mem_opnd(8, RDX, 8), imm_opnd(255)); check_bytes(cb, "F64208FF"); + cb_set_pos(cb, 0); test(cb, DX, imm_opnd(0xFFFF)); check_bytes(cb, "66F7C2FFFF"); + cb_set_pos(cb, 0); test(cb, mem_opnd(16, RDX, 8), imm_opnd(0xFFFF)); check_bytes(cb, "66F74208FFFF"); + cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 0), imm_opnd(1)); check_bytes(cb, "F60601"); + cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 16), imm_opnd(1)); check_bytes(cb, "F6461001"); + cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, -16), imm_opnd(1)); check_bytes(cb, "F646F001"); + cb_set_pos(cb, 0); test(cb, mem_opnd(32, RSI, 64), EAX); check_bytes(cb, "854640"); + cb_set_pos(cb, 0); test(cb, mem_opnd(64, RDI, 42), RAX); check_bytes(cb, "4885472A"); + cb_set_pos(cb, 0); test(cb, RAX, RAX); check_bytes(cb, "4885C0"); + cb_set_pos(cb, 0); test(cb, RAX, RSI); check_bytes(cb, "4885F0"); + cb_set_pos(cb, 0); test(cb, mem_opnd(64, RSI, 64), imm_opnd(~0x08)); check_bytes(cb, "48F74640F7FFFFFF"); + + // xchg + cb_set_pos(cb, 0); xchg(cb, RAX, RCX); check_bytes(cb, "4891"); + cb_set_pos(cb, 0); xchg(cb, RAX, R13); check_bytes(cb, "4995"); + cb_set_pos(cb, 0); xchg(cb, RCX, RBX); check_bytes(cb, "4887D9"); + cb_set_pos(cb, 0); xchg(cb, R9, R15); check_bytes(cb, "4D87F9"); + + // xor + cb_set_pos(cb, 0); xor(cb, EAX, EAX); check_bytes(cb, "31C0"); + + printf("Assembler tests done\n"); +} + +void assert_equal(int expected, int actual) +{ + if (expected != actual) { + fprintf(stderr, "expected %d, got %d\n", expected, actual); + exit(-1); + } +} + +void run_runtime_tests(void) +{ + printf("Running runtime tests\n"); + + codeblock_t codeblock; + codeblock_t* cb = &codeblock; + + uint8_t* mem_block = alloc_exec_mem(4096); + cb_init(cb, mem_block, 4096); + + int (*function)(void); + function = (int (*)(void))mem_block; + + #define TEST(BODY) cb_set_pos(cb, 0); BODY ret(cb); cb_mark_all_executable(cb); assert_equal(7, function()); + + // add + TEST({ mov(cb, RAX, imm_opnd(0)); add(cb, RAX, imm_opnd(7)); }) + TEST({ mov(cb, RAX, imm_opnd(0)); mov(cb, RCX, imm_opnd(7)); add(cb, RAX, RCX); }) + + // and + TEST({ mov(cb, RAX, imm_opnd(31)); and(cb, RAX, imm_opnd(7)); }) + TEST({ mov(cb, RAX, imm_opnd(31)); mov(cb, RCX, imm_opnd(7)); and(cb, RAX, RCX); }) + + // or + TEST({ mov(cb, RAX, imm_opnd(3)); or(cb, RAX, imm_opnd(4)); }) + TEST({ mov(cb, RAX, imm_opnd(3)); mov(cb, RCX, imm_opnd(4)); or(cb, RAX, RCX); }) + + // push/pop + TEST({ mov(cb, RCX, imm_opnd(7)); push(cb, RCX); pop(cb, RAX); }) + + // shr + TEST({ mov(cb, RAX, imm_opnd(31)); shr(cb, RAX, imm_opnd(2)); }) + + // sub + TEST({ mov(cb, RAX, imm_opnd(12)); sub(cb, RAX, imm_opnd(5)); }) + TEST({ mov(cb, RAX, imm_opnd(12)); mov(cb, RCX, imm_opnd(5)); sub(cb, RAX, RCX); }) + + // xor + TEST({ mov(cb, RAX, imm_opnd(13)); xor(cb, RAX, imm_opnd(10)); }) + TEST({ mov(cb, RAX, imm_opnd(13)); mov(cb, RCX, imm_opnd(10)); xor(cb, RAX, RCX); }) + + #undef TEST + + printf("Runtime tests done\n"); +} + +int main(int argc, char** argv) +{ + run_assembler_tests(); + run_runtime_tests(); + + return 0; +} diff --git a/ruby/missing/alloca.c b/ruby/missing/alloca.c index 96121f764..d039dfc2c 100644 --- a/ruby/missing/alloca.c +++ b/ruby/missing/alloca.c @@ -29,7 +29,7 @@ static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */ #endif -#include "ruby/config.h" +#include "ruby/internal/config.h" #define X3J11 1 /* config.h should contain void if needed */ #ifdef C_ALLOCA diff --git a/ruby/missing/crypt.h b/ruby/missing/crypt.h index 7c2642f59..ff135eee9 100644 --- a/ruby/missing/crypt.h +++ b/ruby/missing/crypt.h @@ -1,3 +1,5 @@ +#ifndef CRYPT_H +#define CRYPT_H 1 /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -30,9 +32,6 @@ * SUCH DAMAGE. */ -#ifndef CRYPT_H -#define CRYPT_H 1 - /* ===== Configuration ==================== */ #ifdef CHAR_BITS diff --git a/ruby/missing/dtoa.c b/ruby/missing/dtoa.c index cbee13ee8..b7a830287 100644 --- a/ruby/missing/dtoa.c +++ b/ruby/missing/dtoa.c @@ -183,12 +183,16 @@ #undef Long #undef ULong -#if SIZEOF_INT == 4 +#include + +#if (INT_MAX >> 30) && !(INT_MAX >> 31) #define Long int #define ULong unsigned int -#elif SIZEOF_LONG == 4 +#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 @@ -202,6 +206,11 @@ #define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);} #endif +#ifndef ISDIGIT +#include +#define ISDIGIT(c) isdigit(c) +#endif +#include #include #include @@ -219,6 +228,9 @@ 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 @@ -280,7 +292,7 @@ extern "C" { #endif #ifndef hexdigit -static const char hexdigits[] = "0123456789abcdef0123456789ABCDEF"; +static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; #endif #if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1 @@ -489,6 +501,19 @@ extern double rnd_prod(double, double), rnd_quot(double, double); #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 { @@ -501,6 +526,8 @@ typedef struct Bigint Bigint; static Bigint *freelist[Kmax+1]; +#define BLOCKING_BIGINT ((Bigint *)(-1)) + static Bigint * Balloc(int k) { @@ -510,22 +537,41 @@ Balloc(int k) size_t len; #endif + rv = 0; ACQUIRE_DTOA_LOCK(0); - if (k <= Kmax && (rv = freelist[k]) != 0) { - freelist[k] = rv->next; + if (k <= Kmax) { + rv = freelist[k]; + while (rv) { + Bigint *rvn = rv; + rv = ATOMIC_PTR_CAS(freelist[k], rv, BLOCKING_BIGINT); + if (LIKELY(rv != BLOCKING_BIGINT && rvn == rv)) { + rvn = ATOMIC_PTR_CAS(freelist[k], BLOCKING_BIGINT, rv->next); + assert(rvn == BLOCKING_BIGINT); + ASSUME(rv); + break; + } + } } - else { + 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 && pmem_next - private_mem + len <= PRIVATE_mem) { - rv = (Bigint*)pmem_next; - pmem_next += len; + 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; + } + } } - else + if (!rv) rv = (Bigint*)MALLOC(len*sizeof(double)); #endif rv->k = k; @@ -539,14 +585,19 @@ Balloc(int k) static void Bfree(Bigint *v) { + Bigint *vn; if (v) { if (v->k > Kmax) { FREE(v); return; } ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; + do { + do { + vn = ATOMIC_PTR_CAS(freelist[v->k], 0, 0); + } while (UNLIKELY(vn == BLOCKING_BIGINT)); + v->next = vn; + } while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn)); FREE_DTOA_LOCK(0); } } @@ -829,8 +880,9 @@ static Bigint * pow5mult(Bigint *b, int k) { Bigint *b1, *p5, *p51; + Bigint *p5tmp; int i; - static int p05[3] = { 5, 25, 125 }; + static const int p05[3] = { 5, 25, 125 }; if ((i = k & 3) != 0) b = multadd(b, p05[i-1], 0); @@ -839,17 +891,17 @@ pow5mult(Bigint *b, int k) return b; if (!(p5 = p5s)) { /* first time */ -#ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p5 = p5s)) { - p5 = p5s = i2b(625); + p5 = i2b(625); p5->next = 0; + p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5); + if (UNLIKELY(p5tmp)) { + Bfree(p5); + p5 = p5tmp; + } } FREE_DTOA_LOCK(1); -#else - p5 = p5s = i2b(625); - p5->next = 0; -#endif } for (;;) { if (k & 1) { @@ -860,17 +912,17 @@ pow5mult(Bigint *b, int k) if (!(k >>= 1)) break; if (!(p51 = p5->next)) { -#ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p51 = p5->next)) { - p51 = p5->next = mult(p5,p5); + 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); -#else - p51 = p5->next = mult(p5,p5); - p51->next = 0; -#endif } p5 = p51; } @@ -1500,6 +1552,7 @@ strtod(const char *s00, char **se) if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; if (*s == '0') { while (*++s == '0'); + if (!*s) goto ret; s1 = strchr(hexdigit, *s); } if (s1 != NULL) { @@ -1522,7 +1575,7 @@ strtod(const char *s00, char **se) for (; *s && (s1 = strchr(hexdigit, *s)); ++s) { adj += aadj * ((s1 - hexdigit) & 15); if ((aadj /= 16) == 0.0) { - while (strchr(hexdigit, *++s)); + while (*++s && strchr(hexdigit, *s)); break; } } @@ -2520,10 +2573,10 @@ static char *dtoa_result; static char * rv_alloc(int i) { - return dtoa_result = xmalloc(i); + return dtoa_result = MALLOC(i); } #else -#define rv_alloc(i) xmalloc(i) +#define rv_alloc(i) MALLOC(i) #endif static char * @@ -2550,7 +2603,7 @@ nrv_alloc(const char *s, char **rve, size_t n) static void freedtoa(char *s) { - xfree(s); + FREE(s); } #endif diff --git a/ruby/missing/dup2.c b/ruby/missing/dup2.c deleted file mode 100644 index 7554084c5..000000000 --- a/ruby/missing/dup2.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Public domain dup2() lookalike - * by Curtis Jackson @ AT&T Technologies, Burlington, NC - * electronic address: burl!rcj - * - * dup2 performs the following functions: - * - * Check to make sure that fd1 is a valid open file descriptor. - * Check to see if fd2 is already open; if so, close it. - * Duplicate fd1 onto fd2; checking to make sure fd2 is a valid fd. - * Return fd2 if all went well; return BADEXIT otherwise. - */ - -#include "ruby/config.h" - -#if defined(HAVE_FCNTL) -# include -#endif - -#if !defined(HAVE_FCNTL) || !defined(F_DUPFD) -# include -#endif - -#define BADEXIT -1 - -int -dup2(int fd1, int fd2) -{ -#if defined(HAVE_FCNTL) && defined(F_DUPFD) - if (fd1 != fd2) { -#ifdef F_GETFL - if (fcntl(fd1, F_GETFL) < 0) - return BADEXIT; - if (fcntl(fd2, F_GETFL) >= 0) - close(fd2); -#else - close(fd2); -#endif - if (fcntl(fd1, F_DUPFD, fd2) < 0) - return BADEXIT; - } - return fd2; -#else - extern int errno; - int i, fd, fds[256]; - - if (fd1 == fd2) return 0; - close(fd2); - for (i=0; i<256; i++) { - fd = fds[i] = dup(fd1); - if (fd == fd2) break; - } - while (i) { - close(fds[i--]); - } - if (fd == fd2) return 0; - errno = EMFILE; - return BADEXIT; -#endif -} diff --git a/ruby/missing/erf.c b/ruby/missing/erf.c index d72c4eaf4..c2c9d5f7e 100644 --- a/ruby/missing/erf.c +++ b/ruby/missing/erf.c @@ -7,21 +7,6 @@ reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten #include #include -#ifdef _WIN32 -# include -# if !defined __MINGW32__ || defined __NO_ISOCEXT -# ifndef isnan -# define isnan(x) _isnan(x) -# endif -# ifndef isinf -# define isinf(x) (!_finite(x) && !_isnan(x)) -# endif -# ifndef finite -# define finite(x) _finite(x) -# endif -# endif -#endif - static double q_gamma(double, double, double); /* Incomplete gamma function diff --git a/ruby/missing/explicit_bzero.c b/ruby/missing/explicit_bzero.c index 1804cdd42..1220e5f9a 100644 --- a/ruby/missing/explicit_bzero.c +++ b/ruby/missing/explicit_bzero.c @@ -17,9 +17,9 @@ /* OS support note: * BSDs have explicit_bzero(). - * OS-X has memset_s(). + * macOS has memset_s(). * Windows has SecureZeroMemory() since XP. - * Linux has none. *Sigh* + * Linux has explicit_bzero() since glibc 2.25, musl libc 1.1.20. */ /* diff --git a/ruby/missing/file.h b/ruby/missing/file.h index 241d71656..5e25c4761 100644 --- a/ruby/missing/file.h +++ b/ruby/missing/file.h @@ -1,7 +1,6 @@ -/* This is file FILE.H */ - #ifndef _FILE_H_ #define _FILE_H_ +/* This is file FILE.H */ #include diff --git a/ruby/missing/fileblocks.c b/ruby/missing/fileblocks.c deleted file mode 100644 index ccb8d667b..000000000 --- a/ruby/missing/fileblocks.c +++ /dev/null @@ -1 +0,0 @@ -/* dummy for autoconf */ diff --git a/ruby/missing/finite.c b/ruby/missing/finite.c deleted file mode 100644 index ab7686317..000000000 --- a/ruby/missing/finite.c +++ /dev/null @@ -1,9 +0,0 @@ -/* public domain rewrite of finite(3) */ - -#include "ruby/missing.h" - -int -finite(double n) -{ - return !isnan(n) && !isinf(n); -} diff --git a/ruby/missing/flock.c b/ruby/missing/flock.c index 71c5e7421..c0b3f8060 100644 --- a/ruby/missing/flock.c +++ b/ruby/missing/flock.c @@ -1,4 +1,4 @@ -#include "ruby/config.h" +#include "ruby/internal/config.h" #include "ruby/ruby.h" #if defined _WIN32 diff --git a/ruby/missing/isinf.c b/ruby/missing/isinf.c deleted file mode 100644 index 55187adc6..000000000 --- a/ruby/missing/isinf.c +++ /dev/null @@ -1,69 +0,0 @@ -/* public domain rewrite of isinf(3) */ - -#ifdef __osf__ - -#define _IEEE 1 -#include - -int -isinf(double n) -{ - if (IsNANorINF(n) && IsINF(n)) { - return 1; - } - else { - return 0; - } -} - -#else - -#include "ruby/config.h" - -#if defined(HAVE_FINITE) && defined(HAVE_ISNAN) - -#include -#ifdef HAVE_IEEEFP_H -#include -#endif - -/* - * isinf may be provided only as a macro. - * ex. HP-UX, Solaris 10 - * http://www.gnu.org/software/automake/manual/autoconf/Function-Portability.html - */ -#ifndef isinf -int -isinf(double n) -{ - return (!finite(n) && !isnan(n)); -} -#endif - -#else - -#ifdef HAVE_STRING_H -# include -#else -# include -#endif - -static double zero(void) { return 0.0; } -static double one (void) { return 1.0; } -static double inf (void) { return one() / zero(); } - -int -isinf(double n) -{ - static double pinf = 0.0; - static double ninf = 0.0; - - if (pinf == 0.0) { - pinf = inf(); - ninf = -pinf; - } - return memcmp(&n, &pinf, sizeof n) == 0 - || memcmp(&n, &ninf, sizeof n) == 0; -} -#endif -#endif diff --git a/ruby/missing/isnan.c b/ruby/missing/isnan.c deleted file mode 100644 index ed10bf5cd..000000000 --- a/ruby/missing/isnan.c +++ /dev/null @@ -1,32 +0,0 @@ -/* public domain rewrite of isnan(3) */ - -#include "ruby/missing.h" - -/* - * isnan() may be a macro, a function or both. - * (The C99 standard defines that isnan() is a macro, though.) - * http://www.gnu.org/software/automake/manual/autoconf/Function-Portability.html - * - * macro only: uClibc - * both: GNU libc - * - * This file is compile if no isnan() function is available. - * (autoconf AC_REPLACE_FUNCS detects only the function.) - * The macro is detected by following #ifndef. - */ - -#ifndef isnan -static int double_ne(double n1, double n2); - -int -isnan(double n) -{ - return double_ne(n, n); -} - -static int -double_ne(double n1, double n2) -{ - return n1 != n2; -} -#endif diff --git a/ruby/missing/langinfo.c b/ruby/missing/langinfo.c index 9ba06b15f..0274a378f 100644 --- a/ruby/missing/langinfo.c +++ b/ruby/missing/langinfo.c @@ -140,7 +140,7 @@ char *nl_langinfo(nl_item item) #ifdef TEST #include -int main() +int main(void) { printf("%s\n", nl_langinfo(CODESET)); return 0; diff --git a/ruby/missing/signbit.c b/ruby/missing/signbit.c deleted file mode 100644 index 2f7ce8c60..000000000 --- a/ruby/missing/signbit.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include "ruby.h" - -int -signbit(double x) -{ - enum {double_per_long = sizeof(double) / sizeof(long)}; - enum {long_msb = sizeof(long) * CHAR_BIT - 1}; - union {double d; unsigned long i[double_per_long];} u; - unsigned long l; - - u.d = x; -#ifdef WORDS_BIGENDIAN - l = u.i[0]; -#else - l = u.i[double_per_long - 1]; -#endif - return (int)(l >> long_msb); -} diff --git a/ruby/missing/stdbool.h b/ruby/missing/stdbool.h deleted file mode 100644 index f370e01e9..000000000 --- a/ruby/missing/stdbool.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * missing/stdbool.h: Quick alternative of C99 stdbool.h - */ - -#ifndef _MISSING_STDBOOL_H_ -#define _MISSING_STDBOOL_H_ - -#ifndef __bool_true_false_are_defined -# ifndef __cplusplus -# undef bool -# undef false -# undef true -# define bool signed char -# define false 0 -# define true 1 -# define __bool_true_false_are_defined 1 -# endif -#endif - -#endif /* _MISSING_STDBOOL_H_ */ diff --git a/ruby/missing/tgamma.c b/ruby/missing/tgamma.c index 6260e4f51..82d614d75 100644 --- a/ruby/missing/tgamma.c +++ b/ruby/missing/tgamma.c @@ -9,26 +9,11 @@ reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten /*********************************************************** gamma.c -- Gamma function ***********************************************************/ -#include "ruby/config.h" +#include "ruby/internal/config.h" #include "ruby/missing.h" #include #include -#ifdef _WIN32 -# include -# if !defined __MINGW32__ || defined __NO_ISOCEXT -# ifndef isnan -# define isnan(x) _isnan(x) -# endif -# ifndef isinf -# define isinf(x) (!_finite(x) && !_isnan(x)) -# endif -# ifndef finite -# define finite(x) _finite(x) -# endif -# endif -#endif - #ifndef HAVE_LGAMMA_R #include diff --git a/ruby/mjit.c b/ruby/mjit.c index 4dc6ad80b..89f50cbda 100644 --- a/ruby/mjit.c +++ b/ruby/mjit.c @@ -11,60 +11,21 @@ // To share variables privately, include mjit_worker.c instead of linking. -#include "internal.h" +#include "ruby/internal/config.h" // defines USE_MJIT #if USE_MJIT -#include "mjit_worker.c" - #include "constant.h" #include "id_table.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/cont.h" +#include "internal/file.h" +#include "internal/hash.h" +#include "internal/warnings.h" +#include "vm_sync.h" -// Copy ISeq's states so that race condition does not happen on compilation. -static void -mjit_copy_job_handler(void *data) -{ - mjit_copy_job_t *job = data; - if (stop_worker_p) { // check if mutex is still alive, before calling CRITICAL_SECTION_START. - return; - } - - CRITICAL_SECTION_START(3, "in mjit_copy_job_handler"); - // Make sure that this job is never executed when: - // 1. job is being modified - // 2. alloca memory inside job is expired - // 3. ISeq is GC-ed - if (job->finish_p) { - CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler"); - return; - } - else if (job->iseq == NULL) { // ISeq GC notified in mjit_mark_iseq - job->finish_p = true; - CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler"); - return; - } - - const struct rb_iseq_constant_body *body = job->iseq->body; - if (job->cc_entries) { - unsigned int i; - struct rb_call_cache *sink = job->cc_entries; - const struct rb_call_data *calls = body->call_data; - const struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size]; - for (i = 0; i < body->ci_size; i++) { - *sink++ = calls[i].cc; - } - for (i = 0; i < body->ci_kw_size; i++) { - *sink++ = kw_calls[i].cc; - } - } - if (job->is_entries) { - memcpy(job->is_entries, body->is_entries, sizeof(union iseq_inline_storage_entry) * body->is_size); - } - - job->finish_p = true; - rb_native_cond_broadcast(&mjit_worker_wakeup); - CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler"); -} +#include "mjit_worker.c" extern int rb_thread_create_mjit_thread(void (*worker_func)(void)); @@ -101,7 +62,7 @@ mjit_gc_start_hook(void) rb_native_cond_wait(&mjit_client_wakeup, &mjit_engine_mutex); verbose(4, "Getting wakeup from a worker for GC"); } - in_gc = true; + in_gc++; CRITICAL_SECTION_FINISH(4, "mjit_gc_start_hook"); } @@ -113,12 +74,28 @@ mjit_gc_exit_hook(void) if (!mjit_enabled) return; CRITICAL_SECTION_START(4, "mjit_gc_exit_hook"); - in_gc = false; - verbose(4, "Sending wakeup signal to workers after GC"); - rb_native_cond_broadcast(&mjit_gc_wakeup); + in_gc--; + RUBY_ASSERT_ALWAYS(in_gc >= 0); + if (!in_gc) { + verbose(4, "Sending wakeup signal to workers after GC"); + rb_native_cond_broadcast(&mjit_gc_wakeup); + } CRITICAL_SECTION_FINISH(4, "mjit_gc_exit_hook"); } +// Prohibit calling JIT-ed code and let existing JIT-ed frames exit before the next insn. +void +mjit_cancel_all(const char *reason) +{ + if (!mjit_enabled) + return; + + mjit_call_p = false; + if (mjit_opts.warnings || mjit_opts.verbose) { + fprintf(stderr, "JIT cancel: Disabled JIT-ed code because %s\n", reason); + } +} + // Deal with ISeq movement from compactor void mjit_update_references(const rb_iseq_t *iseq) @@ -132,7 +109,7 @@ mjit_update_references(const rb_iseq_t *iseq) // We need to invalidate JIT-ed code for the ISeq because it embeds pointer addresses. // To efficiently do that, we use the same thing as TracePoint and thus everything is cancelled for now. // See mjit.h and tool/ruby_vm/views/_mjit_compile_insn.erb for how `mjit_call_p` is used. - mjit_call_p = false; // TODO: instead of cancelling all, invalidate only this one and recompile it with some threshold. + mjit_cancel_all("GC.compact is used"); // TODO: instead of cancelling all, invalidate only this one and recompile it with some threshold. } // Units in stale_units (list of over-speculated and invalidated code) are not referenced from @@ -156,9 +133,8 @@ mjit_free_iseq(const rb_iseq_t *iseq) return; CRITICAL_SECTION_START(4, "mjit_free_iseq"); - if (mjit_copy_job.iseq == iseq) { - mjit_copy_job.iseq = NULL; - } + RUBY_ASSERT_ALWAYS(in_gc); + RUBY_ASSERT_ALWAYS(!in_jit); if (iseq->body->jit_unit) { // jit_unit is not freed here because it may be referred by multiple // lists of units. `get_from_list` and `mjit_finish` do the job. @@ -196,7 +172,7 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p) if (unit->handle && dlclose(unit->handle)) { mjit_warning("failed to close handle for u%d: %s", unit->id, dlerror()); } - clean_object_files(unit); + clean_temp_files(unit); free(unit); } else { @@ -206,16 +182,6 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p) list->length = 0; } -// MJIT info related to an existing continutaion. -struct mjit_cont { - rb_execution_context_t *ec; // continuation ec - struct mjit_cont *prev, *next; // used to form lists -}; - -// Double linked list of registered continuations. This is used to detect -// units which are in use in unload_units. -static struct mjit_cont *first_cont; - // Register a new continuation with execution context `ec`. Return MJIT info about // the continuation. struct mjit_cont * @@ -223,7 +189,12 @@ mjit_cont_new(rb_execution_context_t *ec) { struct mjit_cont *cont; - cont = ZALLOC(struct mjit_cont); + // We need to use calloc instead of something like ZALLOC to avoid triggering GC here. + // When this function is called from rb_thread_alloc through rb_threadptr_root_fiber_setup, + // the thread is still being prepared and marking it causes SEGV. + cont = calloc(1, sizeof(struct mjit_cont)); + if (cont == NULL) + rb_memerror(); cont->ec = ec; CRITICAL_SECTION_START(3, "in mjit_cont_new"); @@ -258,7 +229,7 @@ mjit_cont_free(struct mjit_cont *cont) } CRITICAL_SECTION_FINISH(3, "in mjit_cont_new"); - xfree(cont); + free(cont); } // Finish work with continuation info. @@ -273,13 +244,13 @@ finish_conts(void) } } -// Create unit for `iseq`. +// Create unit for `iseq`. This function may be called from an MJIT worker. static void create_unit(const rb_iseq_t *iseq) { struct rb_mjit_unit *unit; - unit = ZALLOC(struct rb_mjit_unit); + unit = calloc(1, sizeof(struct rb_mjit_unit)); if (unit == NULL) return; @@ -288,100 +259,37 @@ create_unit(const rb_iseq_t *iseq) iseq->body->jit_unit = unit; } -// Set up field `used_code_p` for unit iseqs whose iseq on the stack of ec. -static void -mark_ec_units(rb_execution_context_t *ec) +// Return true if given ISeq body should be compiled by MJIT +static inline int +mjit_target_iseq_p(struct rb_iseq_constant_body *body) { - const rb_control_frame_t *cfp; - - if (ec->vm_stack == NULL) - return; - for (cfp = RUBY_VM_END_CONTROL_FRAME(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 - && (iseq->body->jit_unit) != NULL) { - iseq->body->jit_unit->used_code_p = TRUE; - } - - if (cfp == ec->cfp) - break; // reached the most recent cfp - } + return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK) + && !body->builtin_inline_p; } -// Unload JIT code of some units to satisfy the maximum permitted -// number of units with a loaded code. +// If recompile_p is true, the call is initiated by mjit_recompile. +// This assumes the caller holds CRITICAL_SECTION when recompile_p is true. static void -unload_units(void) +mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool recompile_p) { - rb_vm_t *vm = GET_THREAD()->vm; - rb_thread_t *th = NULL; - struct rb_mjit_unit *unit = 0, *next, *worst; - struct mjit_cont *cont; - int delete_num, units_num = active_units.length; - - // For now, we don't unload units when ISeq is GCed. We should - // unload such ISeqs first here. - list_for_each_safe(&active_units.head, unit, next, unode) { - if (unit->iseq == NULL) { // ISeq is GCed. - remove_from_list(unit, &active_units); - free_unit(unit); - } - } - - // Detect units which are in use and can't be unloaded. - list_for_each(&active_units.head, unit, unode) { - assert(unit->iseq != NULL && unit->handle != NULL); - unit->used_code_p = FALSE; - } - list_for_each(&vm->living_threads, th, vmlt_node) { - mark_ec_units(th->ec); - } - for (cont = first_cont; cont != NULL; cont = cont->next) { - mark_ec_units(cont->ec); + if (!mjit_enabled || pch_status == PCH_FAILED) + return; + if (!mjit_target_iseq_p(iseq->body)) { + iseq->body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; // skip mjit_wait + return; } - // TODO: check slale_units and unload unused ones! (note that the unit is not associated to ISeq anymore) - - // Remove 1/10 units more to decrease unloading calls. - // TODO: Calculate max total_calls in unit_queue and don't unload units - // whose total_calls are larger than the max. - delete_num = active_units.length / 10; - for (; active_units.length > mjit_opts.max_cache_size - delete_num;) { - // Find one unit that has the minimum total_calls. - worst = NULL; - list_for_each(&active_units.head, unit, unode) { - if (unit->used_code_p) // We can't unload code on stack. - continue; - - if (worst == NULL || worst->iseq->body->total_calls > unit->iseq->body->total_calls) { - worst = unit; - } - } - if (worst == NULL) - break; - // Unload the worst node. - verbose(2, "Unloading unit %d (calls=%lu)", worst->id, worst->iseq->body->total_calls); - assert(worst->handle != NULL); - remove_from_list(worst, &active_units); - free_unit(worst); - } + if (!recompile_p) { + CRITICAL_SECTION_START(3, "in add_iseq_to_process"); - if (units_num == active_units.length && mjit_opts.wait) { - mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing. - verbose(1, "No units can be unloaded -- incremented max-cache-size to %d for --jit-wait", mjit_opts.max_cache_size); - } - else { - verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length); + // This prevents multiple Ractors from enqueueing the same ISeq twice. + if (rb_multi_ractor_p() && (uintptr_t)iseq->body->jit_func != NOT_ADDED_JIT_ISEQ_FUNC) { + CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process"); + return; + } } -} - -static void -mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info) -{ - if (!mjit_enabled || pch_status == PCH_FAILED) - return; + RB_DEBUG_COUNTER_INC(mjit_add_iseq_to_process); iseq->body->jit_func = (mjit_func_t)NOT_READY_JIT_ISEQ_FUNC; create_unit(iseq); if (iseq->body->jit_unit == NULL) @@ -389,15 +297,16 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf return; if (compile_info != NULL) iseq->body->jit_unit->compile_info = *compile_info; - - CRITICAL_SECTION_START(3, "in add_iseq_to_process"); add_to_list(iseq->body->jit_unit, &unit_queue); if (active_units.length >= mjit_opts.max_cache_size) { - unload_units(); + unload_requests++; + } + + if (!recompile_p) { + verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process"); + rb_native_cond_broadcast(&mjit_worker_wakeup); + CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process"); } - verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process"); - rb_native_cond_broadcast(&mjit_worker_wakeup); - CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process"); } // Add ISEQ to be JITed in parallel with the current thread. @@ -405,7 +314,7 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq) { - mjit_add_iseq_to_process(iseq, NULL); + mjit_add_iseq_to_process(iseq, NULL, false); } // For this timeout seconds, --jit-wait will wait for JIT compilation finish. @@ -440,6 +349,9 @@ mjit_wait(struct rb_iseq_constant_body *body) VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body) { + if (worker_stopped) + return Qundef; + mjit_wait(body); if ((uintptr_t)body->jit_func <= (uintptr_t)LAST_JIT_ISEQ_FUNC) { return Qundef; @@ -454,25 +366,74 @@ rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body) return &body->jit_unit->compile_info; } -void -rb_mjit_recompile_iseq(const rb_iseq_t *iseq) +static void +mjit_recompile(const rb_iseq_t *iseq) { if ((uintptr_t)iseq->body->jit_func <= (uintptr_t)LAST_JIT_ISEQ_FUNC) return; verbose(1, "JIT recompile: %s@%s:%d", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno)); + assert(iseq->body->jit_unit != NULL); - CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq"); - remove_from_list(iseq->body->jit_unit, &active_units); - iseq->body->jit_func = (void *)NOT_ADDED_JIT_ISEQ_FUNC; - add_to_list(iseq->body->jit_unit, &stale_units); - CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq"); - - mjit_add_iseq_to_process(iseq, &iseq->body->jit_unit->compile_info); if (UNLIKELY(mjit_opts.wait)) { + CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq"); + remove_from_list(iseq->body->jit_unit, &active_units); + add_to_list(iseq->body->jit_unit, &stale_units); + mjit_add_iseq_to_process(iseq, &iseq->body->jit_unit->compile_info, true); + CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq"); mjit_wait(iseq->body); } + else { + // Lazily move active_units to stale_units to avoid race conditions around active_units with compaction. + // Also, it's lazily moved to unit_queue as well because otherwise it won't be added to stale_units properly. + // It's good to avoid a race condition between mjit_add_iseq_to_process and mjit_compile around jit_unit as well. + CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq"); + iseq->body->jit_unit->stale_p = true; + iseq->body->jit_func = (mjit_func_t)NOT_READY_JIT_ISEQ_FUNC; + pending_stale_p = true; + CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq"); + } +} + +// Recompile iseq, disabling send optimization +void +rb_mjit_recompile_send(const rb_iseq_t *iseq) +{ + rb_mjit_iseq_compile_info(iseq->body)->disable_send_cache = true; + mjit_recompile(iseq); +} + +// Recompile iseq, disabling ivar optimization +void +rb_mjit_recompile_ivar(const rb_iseq_t *iseq) +{ + rb_mjit_iseq_compile_info(iseq->body)->disable_ivar_cache = true; + mjit_recompile(iseq); +} + +// Recompile iseq, disabling exivar optimization +void +rb_mjit_recompile_exivar(const rb_iseq_t *iseq) +{ + rb_mjit_iseq_compile_info(iseq->body)->disable_exivar_cache = true; + mjit_recompile(iseq); +} + +// Recompile iseq, disabling method inlining +void +rb_mjit_recompile_inlining(const rb_iseq_t *iseq) +{ + rb_mjit_iseq_compile_info(iseq->body)->disable_inlining = true; + mjit_recompile(iseq); +} + +// Recompile iseq, disabling getconstant inlining +void +rb_mjit_recompile_const(const rb_iseq_t *iseq) +{ + rb_mjit_iseq_compile_info(iseq->body)->disable_const_cache = true; + mjit_recompile(iseq); } extern VALUE ruby_archlibdir_path, ruby_prefix_path; @@ -591,19 +552,6 @@ init_header_filename(void) return true; } -static enum rb_id_table_iterator_result -valid_class_serials_add_i(ID key, VALUE v, void *unused) -{ - rb_const_entry_t *ce = (rb_const_entry_t *)v; - VALUE value = ce->value; - - if (!rb_is_const_id(key)) return ID_TABLE_CONTINUE; - if (RB_TYPE_P(value, T_MODULE) || RB_TYPE_P(value, T_CLASS)) { - mjit_add_class_serial(RCLASS_SERIAL(value)); - } - return ID_TABLE_CONTINUE; -} - #ifdef _WIN32 UINT rb_w32_system_tmpdir(WCHAR *path, UINT len); #endif @@ -683,7 +631,7 @@ system_tmpdir(void) // Minimum value for JIT cache size. #define MIN_CACHE_SIZE 10 // Default permitted number of units with a JIT code kept in memory. -#define DEFAULT_MAX_CACHE_SIZE 100 +#define DEFAULT_MAX_CACHE_SIZE 10000 // A default threshold used to add iseq to JIT. #define DEFAULT_MIN_CALLS_TO_ADD 10000 @@ -801,19 +749,13 @@ mjit_init(const struct mjit_options *opts) rb_native_cond_initialize(&mjit_worker_wakeup); rb_native_cond_initialize(&mjit_gc_wakeup); - // Make sure root_fiber's saved_ec is scanned by mark_ec_units + // Make sure the saved_ec of the initial thread's root_fiber is scanned by mark_ec_units. + // + // rb_threadptr_root_fiber_setup for the initial thread is called before mjit_init, + // meaning mjit_cont_new is skipped for the root_fiber. Therefore we need to call + // rb_fiber_init_mjit_cont again with mjit_enabled=true to set the root_fiber's mjit_cont. rb_fiber_init_mjit_cont(GET_EC()->fiber_ptr); - // Initialize class_serials cache for compilation - valid_class_serials = rb_hash_new(); - rb_obj_hide(valid_class_serials); - rb_gc_register_mark_object(valid_class_serials); - mjit_add_class_serial(RCLASS_SERIAL(rb_cObject)); - mjit_add_class_serial(RCLASS_SERIAL(CLASS_OF(rb_vm_top_self()))); - if (RCLASS_CONST_TBL(rb_cObject)) { - rb_id_table_foreach(RCLASS_CONST_TBL(rb_cObject), valid_class_serials_add_i, NULL); - } - // Initialize worker thread start_worker(); } @@ -879,7 +821,7 @@ mjit_resume(void) return Qtrue; } -// Skip calling `clean_object_files` for units which currently exist in the list. +// Skip calling `clean_temp_files` for units which currently exist in the list. static void skip_cleaning_object_files(struct rb_mjit_unit_list *list) { @@ -887,10 +829,6 @@ skip_cleaning_object_files(struct rb_mjit_unit_list *list) // No mutex for list, assuming MJIT worker does not exist yet since it's immediately after fork. list_for_each_safe(&list->head, unit, next, unode) { -#ifndef _MSC_VER // Actually mswin does not reach here since it doesn't have fork - if (unit->o_file) unit->o_file_inherited_p = true; -#endif - #if defined(_WIN32) // mswin doesn't reach here either. This is for MinGW. if (unit->so_file) unit->so_file = NULL; #endif @@ -926,6 +864,22 @@ mjit_child_after_fork(void) start_worker(); } +// Edit 0 to 1 to enable this feature for investigating hot methods +#define MJIT_COUNTER 0 +#if MJIT_COUNTER +static void +mjit_dump_total_calls(void) +{ + struct rb_mjit_unit *unit; + fprintf(stderr, "[MJIT_COUNTER] total_calls of active_units:\n"); + list_for_each(&active_units.head, unit, unode) { + const rb_iseq_t *iseq = unit->iseq; + fprintf(stderr, "%8ld: %s@%s:%d\n", iseq->body->total_calls, RSTRING_PTR(iseq->body->location.label), + RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno)); + } +} +#endif + // Finish the threads processing units and creating PCH, finalize // and free MJIT data. It should be called last during MJIT // life. @@ -961,6 +915,10 @@ mjit_finish(bool close_handle_p) rb_native_cond_destroy(&mjit_worker_wakeup); rb_native_cond_destroy(&mjit_gc_wakeup); +#if MJIT_COUNTER + mjit_dump_total_calls(); +#endif + #ifndef _MSC_VER // mswin has prebuilt precompiled header if (!mjit_opts.save_temps && getpid() == pch_owner_pid) remove_file(pch_file); @@ -985,6 +943,13 @@ mjit_finish(bool close_handle_p) verbose(1, "Successful MJIT finish"); } +// Called by rb_vm_mark(). +// +// Mark an ISeq being compiled to prevent its CCs from being GC-ed, which +// an MJIT worker may concurrently see. +// +// Also mark active_units so that we do not GC ISeq which may still be +// referred to by mjit_recompile() or compact_all_jit_code(). void mjit_mark(void) { @@ -992,55 +957,59 @@ mjit_mark(void) return; RUBY_MARK_ENTER("mjit"); + // We need to release a lock when calling rb_gc_mark to avoid doubly acquiring + // a lock by by mjit_gc_start_hook inside rb_gc_mark. + // + // Because an MJIT worker may modify active_units anytime, we need to convert + // the linked list to an array to safely loop its ISeqs without keeping a lock. CRITICAL_SECTION_START(4, "mjit_mark"); - VALUE iseq = (VALUE)mjit_copy_job.iseq; - CRITICAL_SECTION_FINISH(4, "mjit_mark"); - - // Don't wrap critical section with this. This may trigger GC, - // and in that case mjit_gc_start_hook causes deadlock. - if (iseq) rb_gc_mark(iseq); + int length = 0; + if (compiling_iseqs != NULL) { + while (compiling_iseqs[length]) length++; + } + length += active_units.length; + const rb_iseq_t **iseqs = ALLOCA_N(const rb_iseq_t *, length); struct rb_mjit_unit *unit = NULL; - CRITICAL_SECTION_START(4, "mjit_mark"); - list_for_each(&unit_queue.head, unit, unode) { - if (unit->iseq) { // ISeq is still not GCed - iseq = (VALUE)unit->iseq; - CRITICAL_SECTION_FINISH(4, "mjit_mark rb_gc_mark"); - - // Don't wrap critical section with this. This may trigger GC, - // and in that case mjit_gc_start_hook causes deadlock. - rb_gc_mark(iseq); - - CRITICAL_SECTION_START(4, "mjit_mark rb_gc_mark"); + int i = 0; + if (compiling_iseqs != NULL) { + while (compiling_iseqs[i]) { + iseqs[i] = compiling_iseqs[i]; + i++; } } + list_for_each(&active_units.head, unit, unode) { + iseqs[i] = unit->iseq; + i++; + } + assert(i == length); CRITICAL_SECTION_FINISH(4, "mjit_mark"); - RUBY_MARK_LEAVE("mjit"); -} - -// A hook to update valid_class_serials. -void -mjit_add_class_serial(rb_serial_t class_serial) -{ - if (!mjit_enabled) - return; + for (i = 0; i < length; i++) { + if (iseqs[i] == NULL) // ISeq is GC-ed + continue; + rb_gc_mark((VALUE)iseqs[i]); + } - // Do not wrap CRITICAL_SECTION here. This function is only called in main thread - // and guarded by GVL, and `rb_hash_aset` may cause GC and deadlock in it. - rb_hash_aset(valid_class_serials, LONG2FIX(class_serial), Qtrue); + RUBY_MARK_LEAVE("mjit"); } -// A hook to update valid_class_serials. +// Called by rb_iseq_mark() to mark cc_entries captured for MJIT void -mjit_remove_class_serial(rb_serial_t class_serial) -{ - if (!mjit_enabled) - return; - - CRITICAL_SECTION_START(3, "in mjit_remove_class_serial"); - rb_hash_delete_entry(valid_class_serials, LONG2FIX(class_serial)); - CRITICAL_SECTION_FINISH(3, "in mjit_remove_class_serial"); +mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body) +{ + const struct rb_callcache **cc_entries; + if (body->jit_unit && (cc_entries = body->jit_unit->cc_entries) != NULL) { + // It must be `body->jit_unit->cc_entries_size` instead of `body->ci_size` to mark children's cc_entries + for (unsigned int i = 0; i < body->jit_unit->cc_entries_size; i++) { + const struct rb_callcache *cc = cc_entries[i]; + if (cc != NULL && vm_cc_markable(cc)) { + // Pin `cc` and `cc->cme` against GC.compact as their addresses may be written in JIT-ed code. + rb_gc_mark((VALUE)cc); + rb_gc_mark((VALUE)vm_cc_cme(cc)); + } + } + } } -#endif +#endif // USE_MJIT diff --git a/ruby/mjit.h b/ruby/mjit.h index 256bf65a2..4e91decb0 100644 --- a/ruby/mjit.h +++ b/ruby/mjit.h @@ -1,3 +1,5 @@ +#ifndef RUBY_MJIT_H +#define RUBY_MJIT_H 1 /********************************************************************** mjit.h - Interface to MRI method JIT compiler for Ruby's main thread @@ -6,18 +8,21 @@ **********************************************************************/ -#ifndef RUBY_MJIT_H -#define RUBY_MJIT_H 1 +#include "ruby/internal/config.h" // defines USE_MJIT +#include "ruby/internal/stdbool.h" +#include "vm_core.h" -#include "ruby.h" -#include "debug_counter.h" +# if USE_MJIT -#if USE_MJIT +#include "debug_counter.h" +#include "ruby.h" +#include "vm_core.h" +#include "yjit.h" // Special address values of a function generated from the // corresponding iseq by MJIT: enum rb_mjit_iseq_func { - // ISEQ was not queued yet for the machine code generation + // ISEQ has never been enqueued to unit_queue yet NOT_ADDED_JIT_ISEQ_FUNC = 0, // ISEQ is already queued for the machine code generation but the // code is not ready yet for the execution @@ -59,12 +64,16 @@ struct mjit_options { // State of optimization switches struct rb_mjit_compile_info { - // Disable getinstancevariable/setinstancevariable optimizations based on inline cache + // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (T_OBJECT) bool disable_ivar_cache; + // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (FL_EXIVAR) + bool disable_exivar_cache; // Disable send/opt_send_without_block optimizations based on inline cache bool disable_send_cache; // Disable method inlining bool disable_inlining; + // Disable opt_getinlinecache inlining + bool disable_const_cache; }; typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *); @@ -76,10 +85,15 @@ RUBY_EXTERN bool mjit_call_p; extern void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq); extern VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body); extern struct rb_mjit_compile_info* rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body); -extern void rb_mjit_recompile_iseq(const rb_iseq_t *iseq); +extern void rb_mjit_recompile_send(const rb_iseq_t *iseq); +extern void rb_mjit_recompile_ivar(const rb_iseq_t *iseq); +extern void rb_mjit_recompile_exivar(const rb_iseq_t *iseq); +extern void rb_mjit_recompile_inlining(const rb_iseq_t *iseq); +extern void rb_mjit_recompile_const(const rb_iseq_t *iseq); RUBY_SYMBOL_EXPORT_END -extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname); +extern void mjit_cancel_all(const char *reason); +extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id); extern void mjit_init(const struct mjit_options *opts); extern void mjit_gc_start_hook(void); extern void mjit_gc_exit_hook(void); @@ -88,90 +102,130 @@ extern void mjit_update_references(const rb_iseq_t *iseq); extern void mjit_mark(void); extern struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec); extern void mjit_cont_free(struct mjit_cont *cont); -extern void mjit_add_class_serial(rb_serial_t class_serial); -extern void mjit_remove_class_serial(rb_serial_t class_serial); - -// A threshold used to reject long iseqs from JITting as such iseqs -// takes too much time to be compiled. -#define JIT_ISEQ_SIZE_THRESHOLD 1000 - -// Return TRUE if given ISeq body should be compiled by MJIT -static inline int -mjit_target_iseq_p(struct rb_iseq_constant_body *body) +extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body); + +# ifdef MJIT_HEADER +NOINLINE(static COLDFUNC VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body)); +# else +static inline VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body); +# endif +static VALUE +mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body) { - return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK) - && body->iseq_size < JIT_ISEQ_SIZE_THRESHOLD; + uintptr_t func_i = (uintptr_t)(body->jit_func); + ASSUME(func_i <= LAST_JIT_ISEQ_FUNC); + switch ((enum rb_mjit_iseq_func)func_i) { + case NOT_ADDED_JIT_ISEQ_FUNC: + RB_DEBUG_COUNTER_INC(mjit_exec_not_added); + if (body->total_calls == mjit_opts.min_calls) { + rb_mjit_add_iseq_to_process(iseq); + if (UNLIKELY(mjit_opts.wait)) { + return rb_mjit_wait_call(ec, body); + } + } + break; + case NOT_READY_JIT_ISEQ_FUNC: + RB_DEBUG_COUNTER_INC(mjit_exec_not_ready); + break; + case NOT_COMPILED_JIT_ISEQ_FUNC: + RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled); + break; + default: // to avoid warning with LAST_JIT_ISEQ_FUNC + break; + } + return Qundef; } // Try to execute the current iseq in ec. Use JIT code if it is ready. -// If it is not, add ISEQ to the compilation queue and return Qundef. +// If it is not, add ISEQ to the compilation queue and return Qundef for MJIT. +// YJIT compiles on the thread running the iseq. static inline VALUE mjit_exec(rb_execution_context_t *ec) { - const rb_iseq_t *iseq; - struct rb_iseq_constant_body *body; - long unsigned total_calls; - mjit_func_t func; + const rb_iseq_t *iseq = ec->cfp->iseq; + struct rb_iseq_constant_body *body = iseq->body; + bool yjit_enabled = false; +#ifndef MJIT_HEADER + // Don't want to compile with YJIT or use code generated by YJIT + // when running inside code generated by MJIT. + yjit_enabled = rb_yjit_enabled_p(); +#endif + + if (mjit_call_p || yjit_enabled) { + body->total_calls++; + } + +#ifndef MJIT_HEADER + if (yjit_enabled && !mjit_call_p && body->total_calls == rb_yjit_call_threshold()) { + // If we couldn't generate any code for this iseq, then return + // Qundef so the interpreter will handle the call. + if (!rb_yjit_compile_iseq(iseq, ec)) { + return Qundef; + } + } +#endif - if (!mjit_call_p) + if (!(mjit_call_p || yjit_enabled)) return Qundef; + RB_DEBUG_COUNTER_INC(mjit_exec); - iseq = ec->cfp->iseq; - body = iseq->body; - total_calls = ++body->total_calls; + mjit_func_t func = body->jit_func; - func = body->jit_func; - if (UNLIKELY((uintptr_t)func <= (uintptr_t)LAST_JIT_ISEQ_FUNC)) { -# ifdef MJIT_HEADER + // YJIT tried compiling this function once before and couldn't do + // it, so return Qundef so the interpreter handles it. + if (yjit_enabled && func == 0) { + return Qundef; + } + + if (UNLIKELY((uintptr_t)func <= LAST_JIT_ISEQ_FUNC)) { +# ifdef MJIT_HEADER RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM); -# else +# else RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM); -# endif - switch ((enum rb_mjit_iseq_func)func) { - case NOT_ADDED_JIT_ISEQ_FUNC: - RB_DEBUG_COUNTER_INC(mjit_exec_not_added); - if (total_calls == mjit_opts.min_calls && mjit_target_iseq_p(body)) { - RB_DEBUG_COUNTER_INC(mjit_exec_not_added_add_iseq); - rb_mjit_add_iseq_to_process(iseq); - if (UNLIKELY(mjit_opts.wait)) { - return rb_mjit_wait_call(ec, body); - } - } - return Qundef; - case NOT_READY_JIT_ISEQ_FUNC: - RB_DEBUG_COUNTER_INC(mjit_exec_not_ready); - return Qundef; - case NOT_COMPILED_JIT_ISEQ_FUNC: - RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled); - return Qundef; - default: // to avoid warning with LAST_JIT_ISEQ_FUNC - break; - } +# endif + return mjit_exec_slowpath(ec, iseq, body); } -# ifdef MJIT_HEADER - RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT); -# else - RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT); -# endif +# ifdef MJIT_HEADER + RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT); +# else + RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT); +# endif RB_DEBUG_COUNTER_INC(mjit_exec_call_func); + // Under SystemV x64 calling convention + // ec -> RDI + // cfp -> RSI return func(ec, ec->cfp); } void mjit_child_after_fork(void); -#else // USE_MJIT +# ifdef MJIT_HEADER +#define mjit_enabled true +# else // MJIT_HEADER +extern bool mjit_enabled; +# endif // MJIT_HEADER +VALUE mjit_pause(bool wait_p); +VALUE mjit_resume(void); +void mjit_finish(bool close_handle_p); + +# else // USE_MJIT + +static inline void mjit_cancel_all(const char *reason){} static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;} static inline void mjit_cont_free(struct mjit_cont *cont){} static inline void mjit_gc_start_hook(void){} static inline void mjit_gc_exit_hook(void){} static inline void mjit_free_iseq(const rb_iseq_t *iseq){} static inline void mjit_mark(void){} -static inline void mjit_add_class_serial(rb_serial_t class_serial){} -static inline void mjit_remove_class_serial(rb_serial_t class_serial){} static inline VALUE mjit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ } static inline void mjit_child_after_fork(void){} -#endif // USE_MJIT +#define mjit_enabled false +static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable +static inline VALUE mjit_resume(void){ return Qnil; } // unreachable +static inline void mjit_finish(bool close_handle_p){} + +# endif // USE_MJIT #endif // RUBY_MJIT_H diff --git a/ruby/mjit_compile.c b/ruby/mjit_compile.c index f379a896a..946edc0ec 100644 --- a/ruby/mjit_compile.c +++ b/ruby/mjit_compile.c @@ -10,43 +10,35 @@ // call Ruby methods (C functions that may call rb_funcall) or trigger // GC (using ZALLOC, xmalloc, xfree, etc.) in this file. -#include "internal.h" +#include "ruby/internal/config.h" // defines USE_MJIT #if USE_MJIT +#include "internal.h" +#include "internal/compile.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/variable.h" +#include "mjit.h" #include "vm_core.h" +#include "vm_callinfo.h" #include "vm_exec.h" -#include "mjit.h" +#include "vm_insnhelper.h" + #include "builtin.h" #include "insns.inc" #include "insns_info.inc" -#include "vm_insnhelper.h" // Macros to check if a position is already compiled using compile_status.stack_size_for_pos #define NOT_COMPILED_STACK_SIZE -1 #define ALREADY_COMPILED_P(status, pos) (status->stack_size_for_pos[pos] != NOT_COMPILED_STACK_SIZE) -static size_t -call_data_index(CALL_DATA cd, const struct rb_iseq_constant_body *body) -{ - const struct rb_kwarg_call_data *kw_calls = (const struct rb_kwarg_call_data *)&body->call_data[body->ci_size]; - const struct rb_kwarg_call_data *kw_cd = (const struct rb_kwarg_call_data *)cd; - - VM_ASSERT(cd >= body->call_data && kw_cd < (kw_calls + body->ci_kw_size)); - if (kw_cd < kw_calls) { - return cd - body->call_data; - } - else { - return kw_cd - kw_calls + body->ci_size; - } -} - // For propagating information needed for lazily pushing a frame. struct inlined_call_context { int orig_argc; // ci->orig_argc - VALUE me; // cc->me - int param_size; // def_iseq_ptr(cc->me->def)->body->param.size - int local_size; // def_iseq_ptr(cc->me->def)->body->local_table_size + VALUE me; // vm_cc_cme(cc) + int param_size; // def_iseq_ptr(vm_cc_cme(cc)->def)->body->param.size + int local_size; // def_iseq_ptr(vm_cc_cme(cc)->def)->body->local_table_size }; // Storage to keep compiler's status. This should have information @@ -58,11 +50,18 @@ struct compile_status { // If true, JIT-ed code will use local variables to store pushed values instead of // using VM's stack and moving stack pointer. bool local_stack_p; - // Safely-accessible cache entries copied from main thread. + // Safely-accessible ivar cache entries copied from main thread. union iseq_inline_storage_entry *is_entries; - struct rb_call_cache *cc_entries; + // Index of call cache entries captured to compiled_iseq to be marked on GC + int cc_entries_index; + // A pointer to root (i.e. not inlined) iseq being compiled. + const struct rb_iseq_constant_body *compiled_iseq; + int compiled_id; // Just a copy of compiled_iseq->jit_unit->id // Mutated optimization levels struct rb_mjit_compile_info *compile_info; + bool merge_ivar_guards_p; // If true, merge guards of ivar accesses + rb_serial_t ivar_serial; // ic_serial of IVC in is_entries (used only when merge_ivar_guards_p) + size_t max_ivar_index; // Max IVC index in is_entries (used only when merge_ivar_guards_p) // If `inlined_iseqs[pos]` is not NULL, `mjit_compile_body` tries to inline ISeq there. const struct rb_iseq_constant_body **inlined_iseqs; struct inlined_call_context inline_context; @@ -82,13 +81,38 @@ struct case_dispatch_var { VALUE last_value; }; -// Returns true if call cache is still not obsoleted and cc->me->def->type is available. +static size_t +call_data_index(CALL_DATA cd, const struct rb_iseq_constant_body *body) +{ + return cd - body->call_data; +} + +const struct rb_callcache ** mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body); + +// Using this function to refer to cc_entries allocated by `mjit_capture_cc_entries` +// instead of storing cc_entries in status directly so that we always refer to a new address +// returned by `realloc` inside it. +static const struct rb_callcache ** +captured_cc_entries(const struct compile_status *status) +{ + VM_ASSERT(status->cc_entries_index != -1); + return mjit_iseq_cc_entries(status->compiled_iseq) + status->cc_entries_index; +} + +// Returns true if call cache is still not obsoleted and vm_cc_cme(cc)->def->type is available. static bool has_valid_method_type(CALL_CACHE cc) { - extern bool mjit_valid_class_serial_p(rb_serial_t class_serial); - return GET_GLOBAL_METHOD_STATE() == cc->method_state - && mjit_valid_class_serial_p(cc->class_serial[0]) && cc->me; + return vm_cc_cme(cc) != NULL; +} + +// Returns true if MJIT thinks this cc's opt_* insn may fallback to opt_send_without_block. +static bool +has_cache_for_send(CALL_CACHE cc, int insn) +{ + extern bool rb_vm_opt_cfunc_p(CALL_CACHE cc, int insn); + return has_valid_method_type(cc) && + !(vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_CFUNC && rb_vm_opt_cfunc_p(cc, insn)); } // Returns true if iseq can use fastpath for setup, otherwise NULL. This becomes true in the same condition @@ -98,11 +122,23 @@ fastpath_applied_iseq_p(const CALL_INFO ci, const CALL_CACHE cc, const rb_iseq_t { extern bool rb_simple_iseq_p(const rb_iseq_t *iseq); return iseq != NULL - && !(ci->flag & VM_CALL_KW_SPLAT) && rb_simple_iseq_p(iseq) // Top of vm_callee_setup_arg. In this case, opt_pc is 0. - && ci->orig_argc == iseq->body->param.lead_num // exclude argument_arity_error (assumption: `calling->argc == ci->orig_argc` in send insns) + && !(vm_ci_flag(ci) & VM_CALL_KW_SPLAT) && rb_simple_iseq_p(iseq) // Top of vm_callee_setup_arg. In this case, opt_pc is 0. + && vm_ci_argc(ci) == (unsigned int)iseq->body->param.lead_num // exclude argument_arity_error (assumption: `calling->argc == ci->orig_argc` in send insns) && vm_call_iseq_optimizable_p(ci, cc); // CC_SET_FASTPATH condition } +// Return true if an object of the klass may be a special const. See: rb_class_of +static bool +maybe_special_const_class_p(const VALUE klass) +{ + return klass == rb_cFalseClass + || klass == rb_cNilClass + || klass == rb_cTrueClass + || klass == rb_cInteger + || klass == rb_cSymbol + || klass == rb_cFloat; +} + static int compile_case_dispatch_each(VALUE key, VALUE value, VALUE arg) { @@ -186,18 +222,13 @@ static void compile_insns(FILE *f, const struct rb_iseq_constant_body *body, unsigned int stack_size, unsigned int pos, struct compile_status *status) { - int insn; struct compile_branch branch; branch.stack_size = stack_size; branch.finish_p = false; while (pos < body->iseq_size && !ALREADY_COMPILED_P(status, pos) && !branch.finish_p) { -#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]); -#else - insn = (int)body->iseq_encoded[pos]; -#endif + int insn = rb_vm_insn_decode(body->iseq_encoded[pos]); status->stack_size_for_pos[pos] = (int)branch.stack_size; fprintf(f, "\nlabel_%d: /* %s */\n", pos, insn_name(insn)); @@ -218,12 +249,11 @@ compile_inlined_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body { fprintf(f, "\ncancel:\n"); fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel);\n"); - fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_inlining = true;\n"); - fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n"); + fprintf(f, " rb_mjit_recompile_inlining(original_iseq);\n"); // Swap pc/sp set on cancel with original pc/sp. - fprintf(f, " const VALUE current_pc = reg_cfp->pc;\n"); - fprintf(f, " const VALUE current_sp = reg_cfp->sp;\n"); + fprintf(f, " const VALUE *current_pc = reg_cfp->pc;\n"); + fprintf(f, " VALUE *current_sp = reg_cfp->sp;\n"); fprintf(f, " reg_cfp->pc = orig_pc;\n"); fprintf(f, " reg_cfp->sp = orig_sp;\n\n"); @@ -245,7 +275,7 @@ compile_inlined_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body } // We're not just returning Qundef here so that caller's normal cancel handler can // push back `stack` to `cfp->sp`. - fprintf(f, " return vm_exec(ec, ec->cfp);\n"); + fprintf(f, " return vm_exec(ec, false);\n"); } // Print the block to cancel JIT execution. @@ -259,14 +289,21 @@ compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct fprintf(f, "\nsend_cancel:\n"); fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_send_inline);\n"); - fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_send_cache = true;\n"); - fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n"); + fprintf(f, " rb_mjit_recompile_send(original_iseq);\n"); fprintf(f, " goto cancel;\n"); fprintf(f, "\nivar_cancel:\n"); fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_ivar_inline);\n"); - fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_ivar_cache = true;\n"); - fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n"); + fprintf(f, " rb_mjit_recompile_ivar(original_iseq);\n"); + fprintf(f, " goto cancel;\n"); + + fprintf(f, "\nexivar_cancel:\n"); + fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_exivar_inline);\n"); + fprintf(f, " rb_mjit_recompile_exivar(original_iseq);\n"); + fprintf(f, " goto cancel;\n"); + + fprintf(f, "\nconst_cancel:\n"); + fprintf(f, " rb_mjit_recompile_const(original_iseq);\n"); fprintf(f, " goto cancel;\n"); fprintf(f, "\ncancel:\n"); @@ -279,7 +316,19 @@ compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct fprintf(f, " return Qundef;\n"); } -extern bool mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc_entries, union iseq_inline_storage_entry *is_entries); +extern int +mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq); + +// Copy current is_entries and use it throughout the current compilation consistently. +// While ic->entry has been immutable since https://github.com/ruby/ruby/pull/3662, +// we still need this to avoid a race condition between entries and ivar_serial/max_ivar_index. +static void +mjit_capture_is_entries(const struct rb_iseq_constant_body *body, union iseq_inline_storage_entry *is_entries) +{ + if (is_entries == NULL) + return; + memcpy(is_entries, body->is_entries, sizeof(union iseq_inline_storage_entry) * body->is_size); +} static bool mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status) @@ -298,6 +347,23 @@ mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status) fprintf(f, " static const rb_iseq_t *original_iseq = (const rb_iseq_t *)0x%"PRIxVALUE";\n", (VALUE)iseq); fprintf(f, " static const VALUE *const original_body_iseq = (VALUE *)0x%"PRIxVALUE";\n", (VALUE)body->iseq_encoded); + fprintf(f, " VALUE cfp_self = reg_cfp->self;\n"); // cache self across the method + fprintf(f, "#undef GET_SELF\n"); + fprintf(f, "#define GET_SELF() cfp_self\n"); + + // Generate merged ivar guards first if needed + if (!status->compile_info->disable_ivar_cache && status->merge_ivar_guards_p) { + fprintf(f, " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT) && (rb_serial_t)%"PRI_SERIALT_PREFIX"u == RCLASS_SERIAL(RBASIC(GET_SELF())->klass) &&", status->ivar_serial); + if (status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX) { + fprintf(f, "%"PRIuSIZE" < ROBJECT_NUMIV(GET_SELF())", status->max_ivar_index); // index < ROBJECT_NUMIV(obj) && !RB_FL_ANY_RAW(obj, ROBJECT_EMBED) + } + else { + fprintf(f, "ROBJECT_EMBED_LEN_MAX == ROBJECT_NUMIV(GET_SELF())"); // index < ROBJECT_NUMIV(obj) && RB_FL_ANY_RAW(obj, ROBJECT_EMBED) + } + fprintf(f, "))) {\n"); + fprintf(f, " goto ivar_cancel;\n"); + fprintf(f, " }\n"); + } // Simulate `opt_pc` in setup_parameters_complex. Other PCs which may be passed by catch tables // are not considered since vm_exec doesn't call mjit_exec for catch tables. @@ -315,6 +381,7 @@ mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status) compile_insns(f, body, 0, 0, status); compile_cancel_handler(f, body, status); + fprintf(f, "#undef GET_SELF"); return status->success; } @@ -335,17 +402,18 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body) unsigned int pos = 0; while (pos < body->iseq_size) { -#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - int insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]); -#else - int insn = (int)body->iseq_encoded[pos]; -#endif + int insn = rb_vm_insn_decode(body->iseq_encoded[pos]); // All insns in the ISeq except `leave` (to be overridden in the inlined code) // should meet following strong assumptions: // * Do not require `cfp->sp` motion // * Do not move `cfp->pc` // * Do not read any `cfp->pc` - if (insn != BIN(leave) && insn_may_depend_on_sp_or_pc(insn, body->iseq_encoded + (pos + 1))) + if (insn == BIN(invokebuiltin) || insn == BIN(opt_invokebuiltin_delegate) || insn == BIN(opt_invokebuiltin_delegate_leave)) { + // builtin insn's inlinability is handled by `Primitive.attr! 'inline'` per iseq + if (!body->builtin_inline_p) + return false; + } + else if (insn != BIN(leave) && insn_may_depend_on_sp_or_pc(insn, body->iseq_encoded + (pos + 1))) return false; // At this moment, `cfp->ep` in an inlined method is not working. switch (insn) { @@ -365,16 +433,71 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body) return true; } +// Return an iseq pointer if cc has inlinable iseq. +const rb_iseq_t * +rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc) +{ + const rb_iseq_t *iseq; + if (has_valid_method_type(cc) && + !(vm_ci_flag(ci) & VM_CALL_TAILCALL) && // inlining only non-tailcall path + vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_ISEQ && + fastpath_applied_iseq_p(ci, cc, iseq = def_iseq_ptr(vm_cc_cme(cc)->def)) && + // CC_SET_FASTPATH in vm_callee_setup_arg + inlinable_iseq_p(iseq->body)) { + return iseq; + } + return NULL; +} + +static void +init_ivar_compile_status(const struct rb_iseq_constant_body *body, struct compile_status *status) +{ + mjit_capture_is_entries(body, status->is_entries); + + int num_ivars = 0; + unsigned int pos = 0; + status->max_ivar_index = 0; + status->ivar_serial = 0; + + while (pos < body->iseq_size) { + int insn = rb_vm_insn_decode(body->iseq_encoded[pos]); + if (insn == BIN(getinstancevariable) || insn == BIN(setinstancevariable)) { + IVC ic = (IVC)body->iseq_encoded[pos+2]; + IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache; + if (ic_copy->entry) { // Only initialized (ic_serial > 0) IVCs are optimized + num_ivars++; + + if (status->max_ivar_index < ic_copy->entry->index) { + status->max_ivar_index = ic_copy->entry->index; + } + + if (status->ivar_serial == 0) { + status->ivar_serial = ic_copy->entry->class_serial; + } + else if (status->ivar_serial != ic_copy->entry->class_serial) { + // Multiple classes have used this ISeq. Give up assuming one serial. + status->merge_ivar_guards_p = false; + return; + } + } + } + pos += insn_len(insn); + } + status->merge_ivar_guards_p = status->ivar_serial > 0 && num_ivars >= 2; +} + // This needs to be macro instead of a function because it's using `alloca`. #define INIT_COMPILE_STATUS(status, body, compile_root_p) do { \ status = (struct compile_status){ \ .stack_size_for_pos = (int *)alloca(sizeof(int) * body->iseq_size), \ .inlined_iseqs = compile_root_p ? \ alloca(sizeof(const struct rb_iseq_constant_body *) * body->iseq_size) : NULL, \ - .cc_entries = (body->ci_size + body->ci_kw_size) > 0 ? \ - alloca(sizeof(struct rb_call_cache) * (body->ci_size + body->ci_kw_size)) : NULL, \ .is_entries = (body->is_size > 0) ? \ alloca(sizeof(union iseq_inline_storage_entry) * body->is_size) : NULL, \ + .cc_entries_index = (body->ci_size > 0) ? \ + mjit_capture_cc_entries(status.compiled_iseq, body) : -1, \ + .compiled_id = status.compiled_id, \ + .compiled_iseq = status.compiled_iseq, \ .compile_info = compile_root_p ? \ rb_mjit_iseq_compile_info(body) : alloca(sizeof(struct rb_mjit_compile_info)) \ }; \ @@ -385,6 +508,33 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body) memset(status.compile_info, 0, sizeof(struct rb_mjit_compile_info)); \ } while (0) +static bool +precompile_inlinable_child_iseq(FILE *f, const rb_iseq_t *child_iseq, struct compile_status *status, + const struct rb_callinfo *ci, const struct rb_callcache *cc, unsigned int pos) +{ + struct compile_status child_status = { .compiled_iseq = status->compiled_iseq, .compiled_id = status->compiled_id }; + INIT_COMPILE_STATUS(child_status, child_iseq->body, false); + child_status.inline_context = (struct inlined_call_context){ + .orig_argc = vm_ci_argc(ci), + .me = (VALUE)vm_cc_cme(cc), + .param_size = child_iseq->body->param.size, + .local_size = child_iseq->body->local_table_size + }; + if (child_iseq->body->ci_size > 0 && child_status.cc_entries_index == -1) { + return false; + } + init_ivar_compile_status(child_iseq->body, &child_status); + + fprintf(f, "ALWAYS_INLINE(static VALUE _mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n", status->compiled_id, pos); + fprintf(f, "static inline VALUE\n_mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n", status->compiled_id, pos); + fprintf(f, " const VALUE *orig_pc = reg_cfp->pc;\n"); + fprintf(f, " VALUE *orig_sp = reg_cfp->sp;\n"); + bool success = mjit_compile_body(f, child_iseq, &child_status); + fprintf(f, "\n} /* end of _mjit%d_inlined_%d */\n\n", status->compiled_id, pos); + + return success; +} + // Compile inlinable ISeqs to C code in `f`. It returns true if it succeeds to compile them. static bool precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status *status) @@ -392,51 +542,24 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status const struct rb_iseq_constant_body *body = iseq->body; unsigned int pos = 0; while (pos < body->iseq_size) { -#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - int insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]); -#else - int insn = (int)body->iseq_encoded[pos]; -#endif - - if (insn == BIN(opt_send_without_block)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block` + int insn = rb_vm_insn_decode(body->iseq_encoded[pos]); + if (insn == BIN(opt_send_without_block) || insn == BIN(opt_size)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block` CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1]; - CALL_INFO ci = &cd->ci; - CALL_CACHE cc_copy = status->cc_entries + call_data_index(cd, body); // use copy to avoid race condition + const struct rb_callinfo *ci = cd->ci; + const struct rb_callcache *cc = captured_cc_entries(status)[call_data_index(cd, body)]; // use copy to avoid race condition + extern bool rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq); const rb_iseq_t *child_iseq; - if (has_valid_method_type(cc_copy) && - !(ci->flag & VM_CALL_TAILCALL) && // inlining only non-tailcall path - cc_copy->me->def->type == VM_METHOD_TYPE_ISEQ && fastpath_applied_iseq_p(ci, cc_copy, child_iseq = def_iseq_ptr(cc_copy->me->def)) && // CC_SET_FASTPATH in vm_callee_setup_arg - inlinable_iseq_p(child_iseq->body)) { + if ((child_iseq = rb_mjit_inlinable_iseq(ci, cc)) != NULL && rb_mjit_compiling_iseq_p(child_iseq)) { status->inlined_iseqs[pos] = child_iseq->body; if (mjit_opts.verbose >= 1) // print beforehand because ISeq may be GCed during copy job. fprintf(stderr, "JIT inline: %s@%s:%d => %s@%s:%d\n", - RSTRING_PTR(iseq->body->location.label), - RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno), RSTRING_PTR(child_iseq->body->location.label), - RSTRING_PTR(rb_iseq_path(child_iseq)), FIX2INT(child_iseq->body->location.first_lineno)); - - struct compile_status child_status; - INIT_COMPILE_STATUS(child_status, child_iseq->body, false); - child_status.inline_context = (struct inlined_call_context){ - .orig_argc = ci->orig_argc, - .me = (VALUE)cc_copy->me, - .param_size = child_iseq->body->param.size, - .local_size = child_iseq->body->local_table_size - }; - if ((child_status.cc_entries != NULL || child_status.is_entries != NULL) - && !mjit_copy_cache_from_main_thread(child_iseq, child_status.cc_entries, child_status.is_entries)) - return false; - - fprintf(f, "ALWAYS_INLINE(static VALUE _mjit_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n", pos); - fprintf(f, "static inline VALUE\n_mjit_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n", pos); - fprintf(f, " const VALUE *orig_pc = reg_cfp->pc;\n"); - fprintf(f, " const VALUE *orig_sp = reg_cfp->sp;\n"); - bool success = mjit_compile_body(f, child_iseq, &child_status); - fprintf(f, "\n} /* end of _mjit_inlined_%d */\n\n", pos); - - if (!success) + RSTRING_PTR(rb_iseq_path(child_iseq)), FIX2INT(child_iseq->body->location.first_lineno), + RSTRING_PTR(iseq->body->location.label), + RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno)); + if (!precompile_inlinable_child_iseq(f, child_iseq, status, ci, cc, pos)) return false; } } @@ -447,19 +570,14 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status // Compile ISeq to C code in `f`. It returns true if it succeeds to compile. bool -mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname) +mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id) { - // For performance, we verify stack size only on compilation time (mjit_compile.inc.erb) without --jit-debug - if (!mjit_opts.debug) { - fprintf(f, "#undef OPT_CHECKED_RUN\n"); - fprintf(f, "#define OPT_CHECKED_RUN 0\n\n"); - } - - struct compile_status status; + struct compile_status status = { .compiled_iseq = iseq->body, .compiled_id = id }; INIT_COMPILE_STATUS(status, iseq->body, true); - if ((status.cc_entries != NULL || status.is_entries != NULL) - && !mjit_copy_cache_from_main_thread(iseq, status.cc_entries, status.is_entries)) + if (iseq->body->ci_size > 0 && status.cc_entries_index == -1) { return false; + } + init_ivar_compile_status(iseq->body, &status); if (!status.compile_info->disable_send_cache && !status.compile_info->disable_inlining) { if (!precompile_inlinable_iseqs(f, iseq, &status)) diff --git a/ruby/mjit_compile.inc b/ruby/mjit_compile.inc index 1f0141f65..a17160513 100644 --- a/ruby/mjit_compile.inc +++ b/ruby/mjit_compile.inc @@ -2873,12 +2873,7 @@ switch (insn) { b->stack_size += attr_sp_inc_branchif(dst); } fprintf(f, "}\n"); - if (ALREADY_COMPILED_P(status, pos + insn_len(insn))) { - fprintf(f, "goto label_%d;\n", pos + insn_len(insn)); - } - else { - compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); - } + compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); break; case BIN(branchunless): fprintf(f, "{\n"); @@ -2921,12 +2916,7 @@ switch (insn) { b->stack_size += attr_sp_inc_branchunless(dst); } fprintf(f, "}\n"); - if (ALREADY_COMPILED_P(status, pos + insn_len(insn))) { - fprintf(f, "goto label_%d;\n", pos + insn_len(insn)); - } - else { - compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); - } + compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); break; case BIN(branchnil): fprintf(f, "{\n"); @@ -2969,12 +2959,7 @@ switch (insn) { b->stack_size += attr_sp_inc_branchnil(dst); } fprintf(f, "}\n"); - if (ALREADY_COMPILED_P(status, pos + insn_len(insn))) { - fprintf(f, "goto label_%d;\n", pos + insn_len(insn)); - } - else { - compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); - } + compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); break; case BIN(opt_getinlinecache): fprintf(f, "{\n"); @@ -3017,12 +3002,7 @@ switch (insn) { b->stack_size += attr_sp_inc_opt_getinlinecache(dst, ic); } fprintf(f, "}\n"); - if (ALREADY_COMPILED_P(status, pos + insn_len(insn))) { - fprintf(f, "goto label_%d;\n", pos + insn_len(insn)); - } - else { - compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); - } + compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); break; case BIN(opt_setinlinecache): fprintf(f, "{\n"); @@ -3153,12 +3133,7 @@ switch (insn) { b->stack_size += attr_sp_inc_opt_case_dispatch(hash, else_offset); } fprintf(f, "}\n"); - if (ALREADY_COMPILED_P(status, pos + insn_len(insn))) { - fprintf(f, "goto label_%d;\n", pos + insn_len(insn)); - } - else { - compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); - } + compile_insns(f, body, b->stack_size, pos + insn_len(insn), status); break; case BIN(opt_plus): if (has_valid_method_type(status->cc_entries + call_data_index((CALL_DATA)operands[0], body))) { diff --git a/ruby/mjit_worker.c b/ruby/mjit_worker.c index ce8133ac7..879237eac 100644 --- a/ruby/mjit_worker.c +++ b/ruby/mjit_worker.c @@ -10,6 +10,19 @@ // call Ruby methods (C functions that may call rb_funcall) or trigger // GC (using ZALLOC, xmalloc, xfree, etc.) in this file. +/* However, note that calling `free` for resources `xmalloc`-ed in mjit.c, + which is currently done in some places, is sometimes problematic in the + following situations: + + * malloc library could be different between interpreter and extensions + on Windows (perhaps not applicable to MJIT because CC is the same) + * xmalloc -> free leaks extra space used for USE_GC_MALLOC_OBJ_INFO_DETAILS + (not enabled by default) + + ...in short, it's usually not a problem in MJIT. But maybe it's worth + fixing for consistency or for USE_GC_MALLOC_OBJ_INFO_DETAILS support. +*/ + /* We utilize widely used C compilers (GCC and LLVM Clang) to implement MJIT. We feed them a C code generated from ISEQ. The industrial C compilers are slower than regular JIT engines. @@ -73,11 +86,17 @@ #endif #include "vm_core.h" +#include "vm_callinfo.h" #include "mjit.h" #include "gc.h" #include "ruby_assert.h" #include "ruby/debug.h" #include "ruby/thread.h" +#include "ruby/version.h" +#include "builtin.h" +#include "insns.inc" +#include "insns_info.inc" +#include "internal/compile.h" #ifdef _WIN32 #include @@ -122,30 +141,36 @@ typedef intptr_t pid_t; #define MJIT_TMP_PREFIX "_ruby_mjit_" +// JIT compaction requires the header transformation because linking multiple .o files +// doesn't work without having `static` in the same function definitions. We currently +// don't support transforming the MJIT header on Windows. +#ifdef _WIN32 +# define USE_JIT_COMPACTION 0 +#else +# define USE_JIT_COMPACTION 1 +#endif + // The unit structure that holds metadata of ISeq for MJIT. struct rb_mjit_unit { + struct list_node unode; // Unique order number of unit. int id; // Dlopen handle of the loaded object file. void *handle; rb_iseq_t *iseq; -#ifndef _MSC_VER - // This value is always set for `compact_all_jit_code`. Also used for lazy deletion. - char *o_file; - // true if it's inherited from parent Ruby process and lazy deletion should be skipped. - // `o_file = NULL` can't be used to skip lazy deletion because `o_file` could be used - // by child for `compact_all_jit_code`. - bool o_file_inherited_p; -#endif #if defined(_WIN32) // DLL cannot be removed while loaded on Windows. If this is set, it'll be lazily deleted. char *so_file; #endif // Only used by unload_units. Flag to check this unit is currently on stack or not. - char used_code_p; - struct list_node unode; + bool used_code_p; + // True if this is still in active_units but it's to be lazily removed + bool stale_p; // mjit_compile's optimization switches struct rb_mjit_compile_info compile_info; + // captured CC values, they should be marked with iseq. + const struct rb_callcache **cc_entries; + unsigned int cc_entries_size; // iseq->body->ci_size + ones of inlined iseqs }; // Linked list of struct rb_mjit_unit. @@ -202,26 +227,29 @@ static rb_nativethread_cond_t mjit_client_wakeup; static rb_nativethread_cond_t mjit_worker_wakeup; // A thread conditional to wake up workers if at the end of GC. static rb_nativethread_cond_t mjit_gc_wakeup; -// True when GC is working. -static bool in_gc; +// Greater than 0 when GC is working. +static int in_gc = 0; // True when JIT is working. -static bool in_jit; +static bool in_jit = false; +// True when active_units has at least one stale_p=true unit. +static bool pending_stale_p = false; +// The times when unload_units is requested. unload_units is called after some requests. +static int unload_requests = 0; +// The total number of unloaded units. +static int total_unloads = 0; // Set to true to stop worker. static bool stop_worker_p; // Set to true if worker is stopped. -static bool worker_stopped; +static bool worker_stopped = true; // Path of "/tmp", which can be changed to $TMP in MinGW. static char *tmp_dir; -// Hash like { 1 => true, 2 => true, ... } whose keys are valid `class_serial`s. -// This is used to invalidate obsoleted CALL_CACHE. -static VALUE valid_class_serials; // Used C compiler path. static const char *cc_path; // Used C compiler flags. static const char **cc_common_args; -// Used C compiler flags added by --jit-debug=... +// Used C compiler flags added by --mjit-debug=... static char **cc_added_args; // Name of the precompiled header file. static char *pch_file; @@ -368,23 +396,10 @@ remove_file(const char *filename) } } -// Lazily delete .o and/or .so files. +// Lazily delete .so files. static void -clean_object_files(struct rb_mjit_unit *unit) +clean_temp_files(struct rb_mjit_unit *unit) { -#ifndef _MSC_VER - if (unit->o_file) { - char *o_file = unit->o_file; - - unit->o_file = NULL; - // For compaction, unit->o_file is always set when compilation succeeds. - // So save_temps needs to be checked here. - if (!mjit_opts.save_temps && !unit->o_file_inherited_p) - remove_file(o_file); - free(o_file); - } -#endif - #if defined(_WIN32) if (unit->so_file) { char *so_file = unit->so_file; @@ -412,10 +427,14 @@ free_unit(struct rb_mjit_unit *unit) unit->iseq->body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; unit->iseq->body->jit_unit = NULL; } + if (unit->cc_entries) { + void *entries = (void *)unit->cc_entries; + free(entries); + } if (unit->handle && dlclose(unit->handle)) { // handle is NULL if it's in queue mjit_warning("failed to close handle for u%d: %s", unit->id, dlerror()); } - clean_object_files(unit); + clean_temp_files(unit); free(unit); } @@ -470,25 +489,20 @@ real_ms_time(void) } #endif -// Return true if class_serial is not obsoleted. This is used by mjit_compile.c. -bool -mjit_valid_class_serial_p(rb_serial_t class_serial) -{ - CRITICAL_SECTION_START(3, "in valid_class_serial_p"); - bool found_p = rb_hash_stlike_lookup(valid_class_serials, LONG2FIX(class_serial), NULL); - CRITICAL_SECTION_FINISH(3, "in valid_class_serial_p"); - return found_p; -} - // Return the best unit from list. The best is the first // high priority unit or the unit whose iseq has the biggest number // of calls so far. static struct rb_mjit_unit * get_from_list(struct rb_mjit_unit_list *list) { - struct rb_mjit_unit *unit = NULL, *next, *best = NULL; + while (in_gc) { + verbose(3, "Waiting wakeup from GC"); + rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex); + } + in_jit = true; // Lock GC // Find iseq with max total_calls + struct rb_mjit_unit *unit = NULL, *next, *best = NULL; list_for_each_safe(&list->head, unit, next, unode) { if (unit->iseq == NULL) { // ISeq is GCed. remove_from_list(unit, list); @@ -500,6 +514,11 @@ get_from_list(struct rb_mjit_unit_list *list) best = unit; } } + + in_jit = false; // Unlock GC + verbose(3, "Sending wakeup signal to client in a mjit-worker for GC"); + rb_native_cond_signal(&mjit_client_wakeup); + if (best) { remove_from_list(best, list); } @@ -546,7 +565,7 @@ form_args(int num, ...) } COMPILER_WARNING_PUSH -#ifdef __GNUC__ +#if __has_warning("-Wdeprecated-declarations") || RBIMPL_COMPILER_IS(GCC) COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) #endif // Start an OS process of absolute executable path with arguments `argv`. @@ -659,7 +678,7 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit) { #if defined(_WIN32) // Windows can't remove files while it's used. - unit->so_file = strdup(so_file); // lazily delete on `clean_object_files()` + unit->so_file = strdup(so_file); // lazily delete on `clean_temp_files()` if (unit->so_file == NULL) mjit_warning("failed to allocate memory to lazily remove '%s': %s", so_file, strerror(errno)); #else @@ -667,6 +686,99 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit) #endif } +// Print _mjitX, but make a human-readable funcname when --mjit-debug is used +static void +sprint_funcname(char *funcname, const struct rb_mjit_unit *unit) +{ + const rb_iseq_t *iseq = unit->iseq; + if (iseq == NULL || (!mjit_opts.debug && !mjit_opts.debug_flags)) { + sprintf(funcname, "_mjit%d", unit->id); + return; + } + + // Generate a short path + const char *path = RSTRING_PTR(rb_iseq_path(iseq)); + const char *lib = "/lib/"; + const char *version = "/" STRINGIZE(RUBY_API_VERSION_MAJOR) "." STRINGIZE(RUBY_API_VERSION_MINOR) "." STRINGIZE(RUBY_API_VERSION_TEENY) "/"; + while (strstr(path, lib)) // skip "/lib/" + path = strstr(path, lib) + strlen(lib); + while (strstr(path, version)) // skip "/x.y.z/" + path = strstr(path, version) + strlen(version); + + // Annotate all-normalized method names + const char *method = RSTRING_PTR(iseq->body->location.label); + if (!strcmp(method, "[]")) method = "AREF"; + if (!strcmp(method, "[]=")) method = "ASET"; + + // Print and normalize + sprintf(funcname, "_mjit%d_%s_%s", unit->id, path, method); + for (size_t i = 0; i < strlen(funcname); i++) { + char c = funcname[i]; + if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_')) { + funcname[i] = '_'; + } + } +} + +static const rb_iseq_t **compiling_iseqs = NULL; + +static bool +set_compiling_iseqs(const rb_iseq_t *iseq) +{ + compiling_iseqs = calloc(iseq->body->iseq_size + 2, sizeof(rb_iseq_t *)); // 2: 1 (unit->iseq) + 1 (NULL end) + if (compiling_iseqs == NULL) + return false; + + compiling_iseqs[0] = iseq; + int i = 1; + + unsigned int pos = 0; + while (pos < iseq->body->iseq_size) { + int insn = rb_vm_insn_decode(iseq->body->iseq_encoded[pos]); + if (insn == BIN(opt_send_without_block) || insn == BIN(opt_size)) { + CALL_DATA cd = (CALL_DATA)iseq->body->iseq_encoded[pos + 1]; + extern const rb_iseq_t *rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc); + const rb_iseq_t *iseq = rb_mjit_inlinable_iseq(cd->ci, cd->cc); + if (iseq != NULL) { + compiling_iseqs[i] = iseq; + i++; + } + } + pos += insn_len(insn); + } + return true; +} + +static void +free_compiling_iseqs(void) +{ + RBIMPL_WARNING_PUSH(); +#ifdef _MSC_VER + RBIMPL_WARNING_IGNORED(4090); /* suppress false warning by MSVC */ +#endif + free(compiling_iseqs); + RBIMPL_WARNING_POP(); + compiling_iseqs = NULL; +} + +bool +rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq) +{ + assert(compiling_iseqs != NULL); + int i = 0; + while (compiling_iseqs[i]) { + if (compiling_iseqs[i] == iseq) return true; + i++; + } + return false; +} + +static const int c_file_access_mode = +#ifdef O_BINARY + O_BINARY| +#endif + O_WRONLY|O_EXCL|O_CREAT; + #define append_str2(p, str, len) ((char *)memcpy((p), str, (len))+(len)) #define append_str(p, str) append_str2(p, str, sizeof(str)-1) #define append_lit(p, str) append_str2(p, str, rb_strlen_lit(str)) @@ -676,7 +788,7 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit) static bool compile_c_to_so(const char *c_file, const char *so_file) { - const char *files[] = { NULL, NULL, NULL, NULL, NULL, NULL, "-link", libruby_pathflag, NULL }; + const char *files[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-link", libruby_pathflag, NULL }; char *p; // files[0] = "-Fe*.dll" @@ -712,12 +824,19 @@ compile_c_to_so(const char *c_file, const char *so_file) *p = '\0'; // files[5] = "-Fd*.pdb" - files[5] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fd") + strlen(pch_file) + 1)); + // Generate .pdb file in temporary directory instead of cwd. + files[5] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fd") + strlen(so_file) - rb_strlen_lit(DLEXT) + rb_strlen_lit(".pdb") + 1)); p = append_lit(p, "-Fd"); - p = append_str2(p, pch_file, strlen(pch_file) - rb_strlen_lit(".pch")); + p = append_str2(p, so_file, strlen(so_file) - rb_strlen_lit(DLEXT)); p = append_lit(p, ".pdb"); *p = '\0'; + // files[6] = "-Z7" + // Put this last to override any debug options that came previously. + files[6] = p = alloca(sizeof(char) * rb_strlen_lit("-Z7") + 1); + p = append_lit(p, "-Z7"); + *p = '\0'; + char **args = form_args(5, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, files, CC_LIBS, CC_DLDFLAGS_ARGS); if (args == NULL) @@ -752,6 +871,7 @@ make_pch(void) const char *rest_args[] = { # ifdef __clang__ "-emit-pch", + "-c", # endif // -nodefaultlibs is a linker flag, but it may affect cc1 behavior on Gentoo, which should NOT be changed on pch: // https://gitweb.gentoo.org/proj/gcc-patches.git/tree/7.3.0/gentoo/13_all_default-ssp-fix.patch @@ -786,92 +906,163 @@ make_pch(void) CRITICAL_SECTION_FINISH(3, "in make_pch"); } -// Compile .c file to .o file. It returns true if it succeeds. (non-mswin) +// Compile .c file to .so file. It returns true if it succeeds. (non-mswin) +// Not compiling .c to .so directly because it fails on MinGW, and this helps +// to generate no .dSYM on macOS. static bool -compile_c_to_o(const char *c_file, const char *o_file) +compile_c_to_so(const char *c_file, const char *so_file) { - const char *files[] = { + char* o_file = alloca(strlen(c_file) + 1); + strcpy(o_file, c_file); + o_file[strlen(c_file) - 1] = 'o'; + + const char *o_args[] = { "-o", o_file, c_file, # ifdef __clang__ "-include-pch", pch_file, # endif "-c", NULL }; - - char **args = form_args(5, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, files, CC_LINKER_ARGS); - if (args == NULL) - return false; - + char **args = form_args(5, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, o_args, CC_LINKER_ARGS); + if (args == NULL) return false; int exit_code = exec_process(cc_path, args); free(args); + if (exit_code != 0) { + verbose(2, "compile_c_to_so: failed to compile .c to .o: %d", exit_code); + return false; + } - if (exit_code != 0) - verbose(2, "compile_c_to_o: compile error: %d", exit_code); - return exit_code == 0; -} - -// Link .o files to .so file. It returns true if it succeeds. (non-mswin) -static bool -link_o_to_so(const char **o_files, const char *so_file) -{ - const char *options[] = { + const char *so_args[] = { "-o", so_file, # ifdef _WIN32 libruby_pathflag, # endif - NULL + o_file, NULL }; + args = form_args(6, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, so_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS); + if (args == NULL) return false; + exit_code = exec_process(cc_path, args); + free(args); + if (!mjit_opts.save_temps) remove_file(o_file); + if (exit_code != 0) { + verbose(2, "compile_c_to_so: failed to link .o to .so: %d", exit_code); + } + return exit_code == 0; +} +#endif // _MSC_VER - char **args = form_args(7, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, - options, o_files, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS); - if (args == NULL) +#if USE_JIT_COMPACTION +static void compile_prelude(FILE *f); + +static bool +compile_compact_jit_code(char* c_file) +{ + FILE *f; + int fd = rb_cloexec_open(c_file, c_file_access_mode, 0600); + if (fd < 0 || (f = fdopen(fd, "w")) == NULL) { + int e = errno; + if (fd >= 0) (void)close(fd); + verbose(1, "Failed to fopen '%s', giving up JIT for it (%s)", c_file, strerror(e)); return false; + } - int exit_code = exec_process(cc_path, args); - free(args); + compile_prelude(f); - if (exit_code != 0) - verbose(2, "link_o_to_so: link error: %d", exit_code); - return exit_code == 0; + // wait until mjit_gc_exit_hook is called + CRITICAL_SECTION_START(3, "before mjit_compile to wait GC finish"); + while (in_gc) { + verbose(3, "Waiting wakeup from GC"); + rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex); + } + // We need to check again here because we could've waited on GC above + bool iseq_gced = false; + struct rb_mjit_unit *child_unit = 0, *next; + list_for_each_safe(&active_units.head, child_unit, next, unode) { + if (child_unit->iseq == NULL) { // ISeq is GC-ed + iseq_gced = true; + verbose(1, "JIT compaction: A method for JIT code u%d is obsoleted. Compaction will be skipped.", child_unit->id); + remove_from_list(child_unit, &active_units); + free_unit(child_unit); // unload it without waiting for throttled unload_units to retry compaction quickly + } + } + in_jit = !iseq_gced; + CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish"); + if (!in_jit) { + fclose(f); + if (!mjit_opts.save_temps) + remove_file(c_file); + return false; + } + + // This entire loop lock GC so that we do not need to consider a case that + // ISeq is GC-ed in a middle of re-compilation. It takes 3~4ms with 100 methods + // on my machine. It's not too bad compared to compilation time of C (7200~8000ms), + // but it might be larger if we use a larger --jit-max-cache. + // + // TODO: Consider using a more granular lock after we implement inlining across + // compacted functions (not done yet). + bool success = true; + list_for_each(&active_units.head, child_unit, unode) { + CRITICAL_SECTION_START(3, "before set_compiling_iseqs"); + success &= set_compiling_iseqs(child_unit->iseq); + CRITICAL_SECTION_FINISH(3, "after set_compiling_iseqs"); + if (!success) continue; + + char funcname[MAXPATHLEN]; + sprint_funcname(funcname, child_unit); + + long iseq_lineno = 0; + if (FIXNUM_P(child_unit->iseq->body->location.first_lineno)) + // FIX2INT may fallback to rb_num2long(), which is a method call and dangerous in MJIT worker. So using only FIX2LONG. + iseq_lineno = FIX2LONG(child_unit->iseq->body->location.first_lineno); + const char *sep = "@"; + const char *iseq_label = RSTRING_PTR(child_unit->iseq->body->location.label); + const char *iseq_path = RSTRING_PTR(rb_iseq_path(child_unit->iseq)); + if (!iseq_label) iseq_label = sep = ""; + fprintf(f, "\n/* %s%s%s:%ld */\n", iseq_label, sep, iseq_path, iseq_lineno); + success &= mjit_compile(f, child_unit->iseq, funcname, child_unit->id); + + CRITICAL_SECTION_START(3, "before compiling_iseqs free"); + free_compiling_iseqs(); + CRITICAL_SECTION_FINISH(3, "after compiling_iseqs free"); + } + + // release blocking mjit_gc_start_hook + CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC"); + in_jit = false; + verbose(3, "Sending wakeup signal to client in a mjit-worker for GC"); + rb_native_cond_signal(&mjit_client_wakeup); + CRITICAL_SECTION_FINISH(3, "in worker to wakeup client for GC"); + + fclose(f); + return success; } -// Link all cached .o files and build a .so file. Reload all JIT func from it. This -// allows to avoid JIT code fragmentation and improve performance to call JIT-ed code. +// Compile all cached .c files and build a single .so file. Reload all JIT func from it. +// This improves the code locality for better performance in terms of iTLB and iCache. static void compact_all_jit_code(void) { -# ifndef _WIN32 // This requires header transformation but we don't transform header on Windows for now struct rb_mjit_unit *unit, *cur = 0; - double start_time, end_time; + static const char c_ext[] = ".c"; static const char so_ext[] = DLEXT; - char so_file[MAXPATHLEN]; - const char **o_files; - int i = 0; + char c_file[MAXPATHLEN], so_file[MAXPATHLEN]; // Abnormal use case of rb_mjit_unit that doesn't have ISeq unit = calloc(1, sizeof(struct rb_mjit_unit)); // To prevent GC, don't use ZALLOC if (unit == NULL) return; unit->id = current_unit_num++; + sprint_uniq_filename(c_file, (int)sizeof(c_file), unit->id, MJIT_TMP_PREFIX, c_ext); sprint_uniq_filename(so_file, (int)sizeof(so_file), unit->id, MJIT_TMP_PREFIX, so_ext); - // NULL-ending for form_args - o_files = alloca(sizeof(char *) * (active_units.length + 1)); - o_files[active_units.length] = NULL; - CRITICAL_SECTION_START(3, "in compact_all_jit_code to keep .o files"); - list_for_each(&active_units.head, cur, unode) { - o_files[i] = cur->o_file; - i++; + bool success = compile_compact_jit_code(c_file); + double start_time = real_ms_time(); + if (success) { + success = compile_c_to_so(c_file, so_file); + if (!mjit_opts.save_temps) + remove_file(c_file); } - - start_time = real_ms_time(); - bool success = link_o_to_so(o_files, so_file); - end_time = real_ms_time(); - - // TODO: Shrink this big critical section. For now, this is needed to prevent failure by missing .o files. - // This assumes that o -> so link doesn't take long time because the bottleneck, which is compiler optimization, - // is already done. But actually it takes about 500ms for 5,000 methods on my Linux machine, so it's better to - // finish this critical section before link_o_to_so by disabling unload_units. - CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to keep .o files"); + double end_time = real_ms_time(); if (success) { void *handle = dlopen(so_file, RTLD_NOW); @@ -891,8 +1082,8 @@ compact_all_jit_code(void) CRITICAL_SECTION_START(3, "in compact_all_jit_code to read list"); list_for_each(&active_units.head, cur, unode) { void *func; - char funcname[35]; // TODO: reconsider `35` - sprintf(funcname, "_mjit%d", cur->id); + char funcname[MAXPATHLEN]; + sprint_funcname(funcname, cur); if ((func = dlsym(handle, funcname)) == NULL) { mjit_warning("skipping to reload '%s' from '%s': %s", funcname, so_file, dlerror()); @@ -905,16 +1096,14 @@ compact_all_jit_code(void) } } CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to read list"); - verbose(1, "JIT compaction (%.1fms): Compacted %d methods -> %s", end_time - start_time, active_units.length, so_file); + verbose(1, "JIT compaction (%.1fms): Compacted %d methods %s -> %s", end_time - start_time, active_units.length, c_file, so_file); } else { free(unit); verbose(1, "JIT compaction failure (%.1fms): Failed to compact methods", end_time - start_time); } -# endif // _WIN32 } - -#endif // _MSC_VER +#endif // USE_JIT_COMPACTION static void * load_func_from_so(const char *so_file, const char *funcname, struct rb_mjit_unit *unit) @@ -924,7 +1113,7 @@ load_func_from_so(const char *so_file, const char *funcname, struct rb_mjit_unit handle = dlopen(so_file, RTLD_NOW); if (handle == NULL) { mjit_warning("failure in loading code from '%s': %s", so_file, dlerror()); - return (void *)NOT_ADDED_JIT_ISEQ_FUNC; + return (void *)NOT_COMPILED_JIT_ISEQ_FUNC; } func = dlsym(handle, funcname); @@ -960,7 +1149,7 @@ compile_prelude(FILE *f) fprintf(f, "#include \""); // print pch_file except .gch for gcc, but keep .pch for mswin for (; s < e; s++) { - switch(*s) { + switch (*s) { case '\\': case '"': fputc('\\', f); } @@ -980,44 +1169,16 @@ compile_prelude(FILE *f) static mjit_func_t convert_unit_to_func(struct rb_mjit_unit *unit) { - char c_file_buff[MAXPATHLEN], *c_file = c_file_buff, *so_file, funcname[35]; // TODO: reconsider `35` - int fd; - FILE *f; - void *func; - double start_time, end_time; - int c_file_len = (int)sizeof(c_file_buff); static const char c_ext[] = ".c"; static const char so_ext[] = DLEXT; - const int access_mode = -#ifdef O_BINARY - O_BINARY| -#endif - O_WRONLY|O_EXCL|O_CREAT; -#ifndef _MSC_VER - static const char o_ext[] = ".o"; - char *o_file; -#endif - - c_file_len = sprint_uniq_filename(c_file_buff, c_file_len, unit->id, MJIT_TMP_PREFIX, c_ext); - if (c_file_len >= (int)sizeof(c_file_buff)) { - ++c_file_len; - c_file = alloca(c_file_len); - c_file_len = sprint_uniq_filename(c_file, c_file_len, unit->id, MJIT_TMP_PREFIX, c_ext); - } - ++c_file_len; + char c_file[MAXPATHLEN], so_file[MAXPATHLEN], funcname[MAXPATHLEN]; -#ifndef _MSC_VER - o_file = alloca(c_file_len - sizeof(c_ext) + sizeof(o_ext)); - memcpy(o_file, c_file, c_file_len - sizeof(c_ext)); - memcpy(&o_file[c_file_len - sizeof(c_ext)], o_ext, sizeof(o_ext)); -#endif - so_file = alloca(c_file_len - sizeof(c_ext) + sizeof(so_ext)); - memcpy(so_file, c_file, c_file_len - sizeof(c_ext)); - memcpy(&so_file[c_file_len - sizeof(c_ext)], so_ext, sizeof(so_ext)); - - sprintf(funcname, "_mjit%d", unit->id); + sprint_uniq_filename(c_file, (int)sizeof(c_file), unit->id, MJIT_TMP_PREFIX, c_ext); + sprint_uniq_filename(so_file, (int)sizeof(so_file), unit->id, MJIT_TMP_PREFIX, so_ext); + sprint_funcname(funcname, unit); - fd = rb_cloexec_open(c_file, access_mode, 0600); + FILE *f; + int fd = rb_cloexec_open(c_file, c_file_access_mode, 0600); if (fd < 0 || (f = fdopen(fd, "w")) == NULL) { int e = errno; if (fd >= 0) (void)close(fd); @@ -1034,19 +1195,15 @@ convert_unit_to_func(struct rb_mjit_unit *unit) verbose(3, "Waiting wakeup from GC"); rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex); } - // We need to check again here because we could've waited on GC above - if (unit->iseq == NULL) { + in_jit = (unit->iseq != NULL); + if (in_jit) + in_jit &= set_compiling_iseqs(unit->iseq); + CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish"); + if (!in_jit) { fclose(f); if (!mjit_opts.save_temps) remove_file(c_file); - in_jit = false; // just being explicit for return - } - else { - in_jit = true; - } - CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish"); - if (!in_jit) { return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; } @@ -1062,10 +1219,11 @@ convert_unit_to_func(struct rb_mjit_unit *unit) verbose(2, "start compilation: %s@%s:%ld -> %s", iseq_label, iseq_path, iseq_lineno, c_file); fprintf(f, "/* %s@%s:%ld */\n\n", iseq_label, iseq_path, iseq_lineno); - bool success = mjit_compile(f, unit->iseq, funcname); + bool success = mjit_compile(f, unit->iseq, funcname, unit->id); // release blocking mjit_gc_start_hook CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC"); + free_compiling_iseqs(); in_jit = false; verbose(3, "Sending wakeup signal to client in a mjit-worker for GC"); rb_native_cond_signal(&mjit_client_wakeup); @@ -1079,32 +1237,18 @@ convert_unit_to_func(struct rb_mjit_unit *unit) return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; } - start_time = real_ms_time(); -#ifdef _MSC_VER + double start_time = real_ms_time(); success = compile_c_to_so(c_file, so_file); -#else - // splitting .c -> .o step and .o -> .so step, to cache .o files in the future - if ((success = compile_c_to_o(c_file, o_file)) != false) { - success = link_o_to_so((const char *[]){ o_file, NULL }, so_file); - - // Always set o_file for compaction. The value is also used for lazy deletion. - unit->o_file = strdup(o_file); - if (unit->o_file == NULL) { - mjit_warning("failed to allocate memory to remember '%s' (%s), removing it...", o_file, strerror(errno)); - remove_file(o_file); - } - } -#endif - end_time = real_ms_time(); - if (!mjit_opts.save_temps) remove_file(c_file); + double end_time = real_ms_time(); + if (!success) { verbose(2, "Failed to generate so: %s", so_file); return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; } - func = load_func_from_so(so_file, funcname, unit); + void *func = load_func_from_so(so_file, funcname, unit); if (!mjit_opts.save_temps) remove_so_file(so_file, unit); @@ -1115,84 +1259,167 @@ convert_unit_to_func(struct rb_mjit_unit *unit) return (mjit_func_t)func; } -typedef struct { - const rb_iseq_t *iseq; - struct rb_call_cache *cc_entries; - union iseq_inline_storage_entry *is_entries; - bool finish_p; -} mjit_copy_job_t; +// To see cc_entries using index returned by `mjit_capture_cc_entries` in mjit_compile.c +const struct rb_callcache ** +mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body) +{ + return body->jit_unit->cc_entries; +} -// Singleton MJIT copy job. This is made global since it needs to be durable even when MJIT worker thread is stopped. -// (ex: register job -> MJIT pause -> MJIT resume -> dispatch job. Actually this should be just cancelled by finish_p check) -static mjit_copy_job_t mjit_copy_job = { .iseq = NULL, .finish_p = true }; +// Capture cc entries of `captured_iseq` and append them to `compiled_iseq->jit_unit->cc_entries`. +// This is needed when `captured_iseq` is inlined by `compiled_iseq` and GC needs to mark inlined cc. +// +// Index to refer to `compiled_iseq->jit_unit->cc_entries` is returned instead of the address +// because old addresses may be invalidated by `realloc` later. -1 is returned on failure. +// +// This assumes that it's safe to reference cc without acquiring GVL. +int +mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq) +{ + struct rb_mjit_unit *unit = compiled_iseq->jit_unit; + unsigned int new_entries_size = unit->cc_entries_size + captured_iseq->ci_size; + VM_ASSERT(captured_iseq->ci_size > 0); + + // Allocate new cc_entries and append them to unit->cc_entries + const struct rb_callcache **cc_entries; + int cc_entries_index = unit->cc_entries_size; + if (unit->cc_entries_size == 0) { + VM_ASSERT(unit->cc_entries == NULL); + unit->cc_entries = cc_entries = malloc(sizeof(struct rb_callcache *) * new_entries_size); + if (cc_entries == NULL) return -1; + } + else { + void *cc_ptr = (void *)unit->cc_entries; // get rid of bogus warning by VC + cc_entries = realloc(cc_ptr, sizeof(struct rb_callcache *) * new_entries_size); + if (cc_entries == NULL) return -1; + unit->cc_entries = cc_entries; + cc_entries += cc_entries_index; + } + unit->cc_entries_size = new_entries_size; -static void mjit_copy_job_handler(void *data); + // Capture cc to cc_enties + for (unsigned int i = 0; i < captured_iseq->ci_size; i++) { + cc_entries[i] = captured_iseq->call_data[i].cc; + } -// vm_trace.c -int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t , void *); + return cc_entries_index; +} -// Copy inline cache values of `iseq` to `cc_entries` and `is_entries`. -// These buffers should be pre-allocated properly prior to calling this function. -// Return true if copy succeeds or is not needed. -// -// We're lazily copying cache values from main thread because these cache values -// could be different between ones on enqueue timing and ones on dequeue timing. -bool -mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc_entries, union iseq_inline_storage_entry *is_entries) +// Set up field `used_code_p` for unit iseqs whose iseq on the stack of ec. +static void +mark_ec_units(rb_execution_context_t *ec) { - mjit_copy_job_t *job = &mjit_copy_job; // just a short hand + const rb_control_frame_t *cfp; - CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread"); - job->finish_p = true; // disable dispatching this job in mjit_copy_job_handler while it's being modified - CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread"); + if (ec->vm_stack == NULL) + return; + for (cfp = RUBY_VM_END_CONTROL_FRAME(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 + && (iseq->body->jit_unit) != NULL) { + iseq->body->jit_unit->used_code_p = true; + } - job->cc_entries = cc_entries; - job->is_entries = is_entries; + if (cfp == ec->cfp) + break; // reached the most recent cfp + } +} - CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread"); - job->iseq = iseq; // Prevernt GC of this ISeq from here - VM_ASSERT(in_jit); - in_jit = false; // To avoid deadlock, allow running GC while waiting for copy job - rb_native_cond_signal(&mjit_client_wakeup); // Unblock main thread waiting in `mjit_gc_start_hook` +// MJIT info related to an existing continutaion. +struct mjit_cont { + rb_execution_context_t *ec; // continuation ec + struct mjit_cont *prev, *next; // used to form lists +}; - job->finish_p = false; // allow dispatching this job in mjit_copy_job_handler - CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread"); +// Double linked list of registered continuations. This is used to detect +// units which are in use in unload_units. +static struct mjit_cont *first_cont; - if (UNLIKELY(mjit_opts.wait)) { - mjit_copy_job_handler((void *)job); +// Unload JIT code of some units to satisfy the maximum permitted +// number of units with a loaded code. +static void +unload_units(void) +{ + struct rb_mjit_unit *unit = 0, *next; + struct mjit_cont *cont; + int units_num = active_units.length; + + // For now, we don't unload units when ISeq is GCed. We should + // unload such ISeqs first here. + list_for_each_safe(&active_units.head, unit, next, unode) { + if (unit->iseq == NULL) { // ISeq is GCed. + remove_from_list(unit, &active_units); + free_unit(unit); + } } - else if (rb_workqueue_register(0, mjit_copy_job_handler, (void *)job)) { - CRITICAL_SECTION_START(3, "in MJIT copy job wait"); - // checking `stop_worker_p` too because `RUBY_VM_CHECK_INTS(ec)` may not - // lush mjit_copy_job_handler when EC_EXEC_TAG() is not TAG_NONE, and then - // `stop_worker()` could dead lock with this function. - while (!job->finish_p && !stop_worker_p) { - rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex); - verbose(3, "Getting wakeup from client"); + + // Detect units which are in use and can't be unloaded. + list_for_each(&active_units.head, unit, unode) { + assert(unit->iseq != NULL && unit->handle != NULL); + unit->used_code_p = false; + } + // All threads have a root_fiber which has a mjit_cont. Other normal fibers also + // have a mjit_cont. Thus we can check ISeqs in use by scanning ec of mjit_conts. + for (cont = first_cont; cont != NULL; cont = cont->next) { + mark_ec_units(cont->ec); + } + // TODO: check stale_units and unload unused ones! (note that the unit is not associated to ISeq anymore) + + // Unload units whose total_calls is smaller than any total_calls in unit_queue. + // TODO: make the algorithm more efficient + long unsigned prev_queue_calls = -1; + while (true) { + // Calculate the next max total_calls in unit_queue + long unsigned max_queue_calls = 0; + list_for_each(&unit_queue.head, unit, unode) { + if (unit->iseq != NULL && max_queue_calls < unit->iseq->body->total_calls + && unit->iseq->body->total_calls < prev_queue_calls) { + max_queue_calls = unit->iseq->body->total_calls; + } } - CRITICAL_SECTION_FINISH(3, "in MJIT copy job wait"); + prev_queue_calls = max_queue_calls; + + bool unloaded_p = false; + list_for_each_safe(&active_units.head, unit, next, unode) { + if (unit->used_code_p) // We can't unload code on stack. + continue; + + if (max_queue_calls > unit->iseq->body->total_calls) { + verbose(2, "Unloading unit %d (calls=%lu, threshold=%lu)", + unit->id, unit->iseq->body->total_calls, max_queue_calls); + assert(unit->handle != NULL); + remove_from_list(unit, &active_units); + free_unit(unit); + unloaded_p = true; + } + } + if (!unloaded_p) break; } - CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread"); - bool success_p = job->finish_p; - // Disable dispatching this job in mjit_copy_job_handler while memory allocated by alloca - // could be expired after finishing this function. - job->finish_p = true; - - in_jit = true; // Prohibit GC during JIT compilation - if (job->iseq == NULL) // ISeq GC is notified in mjit_mark_iseq - success_p = false; - job->iseq = NULL; // Allow future GC of this ISeq from here - CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread"); - return success_p; + if (units_num > active_units.length) { + verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length); + total_unloads += units_num - active_units.length; + } } +static void mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool worker_p); + // The function implementing a worker. It is executed in a separate // thread by rb_thread_create_mjit_thread. It compiles precompiled header // and then compiles requested ISeqs. void mjit_worker(void) { + // Allow only `max_cache_size / 100` times (default: 100) of compaction. + // Note: GC of compacted code has not been implemented yet. + int max_compact_size = mjit_opts.max_cache_size / 100; + if (max_compact_size < 10) max_compact_size = 10; + + // Run unload_units after it's requested `max_cache_size / 10` (default: 10) times. + // This throttles the call to mitigate locking in unload_units. It also throttles JIT compaction. + int throttle_threshold = mjit_opts.max_cache_size / 10; + #ifndef _MSC_VER if (pch_status == PCH_NOT_READY) { make_pch(); @@ -1212,11 +1439,47 @@ mjit_worker(void) while (!stop_worker_p) { struct rb_mjit_unit *unit; - // wait until unit is available + // Wait until a unit becomes available CRITICAL_SECTION_START(3, "in worker dequeue"); while ((list_empty(&unit_queue.head) || active_units.length >= mjit_opts.max_cache_size) && !stop_worker_p) { rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex); verbose(3, "Getting wakeup from client"); + + // Lazily move active_units to stale_units to avoid race conditions around active_units with compaction + if (pending_stale_p) { + pending_stale_p = false; + struct rb_mjit_unit *next; + list_for_each_safe(&active_units.head, unit, next, unode) { + if (unit->stale_p) { + unit->stale_p = false; + remove_from_list(unit, &active_units); + add_to_list(unit, &stale_units); + // Lazily put it to unit_queue as well to avoid race conditions on jit_unit with mjit_compile. + mjit_add_iseq_to_process(unit->iseq, &unit->iseq->body->jit_unit->compile_info, true); + } + } + } + + // Unload some units as needed + if (unload_requests >= throttle_threshold) { + while (in_gc) { + verbose(3, "Waiting wakeup from GC"); + rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex); + } + in_jit = true; // Lock GC + + RB_DEBUG_COUNTER_INC(mjit_unload_units); + unload_units(); + unload_requests = 0; + + in_jit = false; // Unlock GC + verbose(3, "Sending wakeup signal to client in a mjit-worker for GC"); + rb_native_cond_signal(&mjit_client_wakeup); + } + if (active_units.length == mjit_opts.max_cache_size && mjit_opts.wait) { // Sometimes all methods may be in use + mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing. + verbose(1, "No units can be unloaded -- incremented max-cache-size to %d for --jit-wait", mjit_opts.max_cache_size); + } } unit = get_from_list(&unit_queue); CRITICAL_SECTION_FINISH(3, "in worker dequeue"); @@ -1243,10 +1506,11 @@ mjit_worker(void) } CRITICAL_SECTION_FINISH(3, "in jit func replace"); -#ifndef _MSC_VER - // Combine .o files to one .so and reload all jit_func to improve memory locality - if ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1) - || active_units.length == mjit_opts.max_cache_size) { +#if USE_JIT_COMPACTION + // Combine .o files to one .so and reload all jit_func to improve memory locality. + if (compact_units.length < max_compact_size + && ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1) + || (active_units.length == mjit_opts.max_cache_size && compact_units.length * throttle_threshold <= total_unloads))) { // throttle compaction by total_unloads compact_all_jit_code(); } #endif diff --git a/ruby/nilclass.rb b/ruby/nilclass.rb new file mode 100644 index 000000000..5a2e19680 --- /dev/null +++ b/ruby/nilclass.rb @@ -0,0 +1,25 @@ +class NilClass + # + # call-seq: + # nil.to_i -> 0 + # + # Always returns zero. + # + # nil.to_i #=> 0 + # + def to_i + return 0 + end + + # + # call-seq: + # nil.to_f -> 0.0 + # + # Always returns zero. + # + # nil.to_f #=> 0.0 + # + def to_f + return 0.0 + end +end diff --git a/ruby/node.c b/ruby/node.c index 3514060ec..d8c1da95e 100644 --- a/ruby/node.c +++ b/ruby/node.c @@ -9,6 +9,9 @@ **********************************************************************/ +#include "internal.h" +#include "internal/hash.h" +#include "internal/variable.h" #include "ruby/ruby.h" #include "vm_core.h" @@ -23,10 +26,10 @@ #define A_ID(id) add_id(buf, (id)) #define A_INT(val) rb_str_catf(buf, "%d", (val)) #define A_LONG(val) rb_str_catf(buf, "%ld", (val)) -#define A_LIT(lit) AR(rb_inspect(lit)) +#define A_LIT(lit) AR(rb_dump_literal(lit)) #define A_NODE_HEADER(node, term) \ - rb_str_catf(buf, "@ %s (line: %d, location: (%d,%d)-(%d,%d))%s"term, \ - ruby_node_name(nd_type(node)), nd_line(node), \ + rb_str_catf(buf, "@ %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))%s"term, \ + 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), \ (node->flags & NODE_FL_NEWLINE ? "*" : "")) @@ -60,7 +63,7 @@ #define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann)) #define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann) #define F_ID(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name) -#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID((node->name)->id) +#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name) #define F_INT(name, ann) SIMPLE_FIELD1(#name, ann) A_INT(node->name) #define F_LONG(name, ann) SIMPLE_FIELD1(#name, ann) A_LONG(node->name) #define F_LIT(name, ann) SIMPLE_FIELD1(#name, ann) A_LIT(node->name) @@ -76,6 +79,25 @@ #define LAST_NODE (next_indent = " ") +VALUE +rb_dump_literal(VALUE lit) +{ + if (!RB_SPECIAL_CONST_P(lit)) { + VALUE str; + switch (RB_BUILTIN_TYPE(lit)) { + case T_CLASS: case T_MODULE: case T_ICLASS: + str = rb_class_path(lit); + if (FL_TEST(lit, FL_SINGLETON)) { + str = rb_sprintf("<%"PRIsVALUE">", str); + } + return str; + default: + break; + } + } + return rb_inspect(lit); +} + static void add_indent(VALUE buf, VALUE indent) { @@ -114,7 +136,7 @@ dump_array(VALUE buf, VALUE indent, int comment, const NODE *node) const char *next_indent = default_indent; F_LONG(nd_alen, "length"); F_NODE(nd_head, "element"); - while (node->nd_next && nd_type(node->nd_next) == NODE_LIST) { + while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) { node = node->nd_next; F_NODE(nd_head, "element"); } @@ -153,7 +175,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) dump_node(buf, indent, comment, node->nd_head); D_DEDENT; } while (node->nd_next && - nd_type(node->nd_next) == NODE_BLOCK && + nd_type_p(node->nd_next, NODE_BLOCK) && (node = node->nd_next, 1)); if (node->nd_next) { LAST_NODE; @@ -348,7 +370,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) andor: while (1) { F_NODE(nd_1st, "left expr"); - if (!node->nd_2nd || nd_type(node->nd_2nd) != (int)type) + if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type)) break; node = node->nd_2nd; } @@ -385,16 +407,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) } return; case NODE_DASGN: - ANN("dynamic variable assignment (out of current scope)"); + ANN("dynamic variable assignment"); ANN("format: [nd_vid](dvar) = [nd_value]"); ANN("example: x = nil; 1.times { x = foo }"); - F_ID(nd_vid, "local variable"); - LAST_NODE; - F_NODE(nd_value, "rvalue"); - return; - case NODE_DASGN_CURR: - ANN("dynamic variable assignment (in current scope)"); - ANN("format: [nd_vid](current dvar) = [nd_value]"); ANN("example: 1.times { x = foo }"); F_ID(nd_vid, "local variable"); if (NODE_REQUIRED_KEYWORD_P(node)) { @@ -655,10 +670,8 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) ANN("format: $[nd_nth]"); ANN("example: $&, $`, $', $+"); F_CUSTOM1(nd_nth, "variable") { - char name[3]; - name[0] = '$'; + char name[3] = "$ "; name[1] = (char)node->nd_nth; - name[2] = '\0'; A(name); } return; @@ -738,6 +751,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) ANN("example: :\"foo#{ bar }baz\""); dlit: F_LIT(nd_lit, "preceding string"); + if (!node->nd_next) return; F_NODE(nd_next->nd_head, "interpolation"); LAST_NODE; F_NODE(nd_next->nd_next, "tailing strings"); @@ -996,8 +1010,8 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) case NODE_ARGS: ANN("method parameters"); - ANN("format: def method_name(.., [nd_opt=some], *[nd_rest], [nd_pid], .., &[nd_body])"); - ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, &blk); end"); + ANN("format: def method_name(.., [nd_ainfo->nd_optargs], *[nd_ainfo->rest_arg], [nd_ainfo->first_post_arg], .., [nd_ainfo->kw_args], **[nd_ainfo->kw_rest_arg], &[nd_ainfo->block_arg])"); + ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, kw: 1, **kwrest, &blk); end"); F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments"); F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments"); F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments"); @@ -1022,12 +1036,12 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) ANN("new scope"); ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body"); F_CUSTOM1(nd_tbl, "local table") { - ID *tbl = node->nd_tbl; + rb_ast_id_table_t *tbl = node->nd_tbl; int i; - int size = tbl ? (int)*tbl++ : 0; + int size = tbl ? tbl->size : 0; if (size == 0) A("(empty)"); for (i = 0; i < size; i++) { - A_ID(tbl[i]); if (i < size - 1) A(","); + A_ID(tbl->ids[i]); if (i < size - 1) A(","); } } F_NODE(nd_args, "arguments"); @@ -1050,6 +1064,27 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_NODE(nd_apinfo->post_args, "post arguments"); return; + case NODE_FNDPTN: + ANN("find pattern"); + ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])"); + F_NODE(nd_pconst, "constant"); + if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) { + F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument"); + } + else { + F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)"); + } + F_NODE(nd_fpinfo->args, "arguments"); + + LAST_NODE; + if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) { + F_NODE(nd_fpinfo->post_rest_arg, "post rest argument"); + } + else { + F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)"); + } + return; + case NODE_HSHPTN: ANN("hash pattern"); ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])"); @@ -1095,7 +1130,7 @@ void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2) { n->flags = T_NODE; - nd_set_type(n, type); + nd_init_type(n, type); n->u1.value = a0; n->u2.value = a1; n->u3.value = a2; @@ -1120,6 +1155,7 @@ typedef struct { struct node_buffer_struct { node_buffer_list_t unmarkable; node_buffer_list_t markable; + struct rb_ast_local_table_link *local_tables; VALUE mark_hash; }; @@ -1145,6 +1181,7 @@ rb_node_buffer_new(void) node_buffer_t *nb = ruby_xmalloc(alloc_size); init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]); init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size)); + nb->local_tables = 0; nb->mark_hash = Qnil; return nb; } @@ -1161,11 +1198,25 @@ node_buffer_list_free(node_buffer_list_t * nb) } } +struct rb_ast_local_table_link { + struct rb_ast_local_table_link *next; + // struct rb_ast_id_table { + int size; + ID ids[FLEX_ARY_LEN]; + // } +}; + static void rb_node_buffer_free(node_buffer_t *nb) { node_buffer_list_free(&nb->unmarkable); node_buffer_list_free(&nb->markable); + struct rb_ast_local_table_link *local_table = nb->local_tables; + while (local_table) { + struct rb_ast_local_table_link *next_table = local_table->next; + xfree(local_table); + local_table = next_table; + } xfree(nb); } @@ -1185,10 +1236,10 @@ ast_newnode_in_bucket(node_buffer_list_t *nb) return &nb->head->buf[nb->idx++]; } -NODE * -rb_ast_newnode(rb_ast_t *ast, enum node_type type) +RBIMPL_ATTR_PURE() +static bool +nodetype_markable_p(enum node_type type) { - node_buffer_t *nb = ast->node_buffer; switch (type) { case NODE_MATCH: case NODE_LIT: @@ -1199,14 +1250,57 @@ rb_ast_newnode(rb_ast_t *ast, enum node_type type) case NODE_DREGX: case NODE_DSYM: case NODE_ARGS: - case NODE_SCOPE: case NODE_ARYPTN: - return ast_newnode_in_bucket(&nb->markable); + case NODE_FNDPTN: + return true; default: - return ast_newnode_in_bucket(&nb->unmarkable); + return false; + } +} + +NODE * +rb_ast_newnode(rb_ast_t *ast, enum node_type type) +{ + node_buffer_t *nb = ast->node_buffer; + node_buffer_list_t *bucket = + (nodetype_markable_p(type) ? &nb->markable : &nb->unmarkable); + return ast_newnode_in_bucket(bucket); +} + +void +rb_ast_node_type_change(NODE *n, enum node_type type) +{ + enum node_type old_type = nd_type(n); + if (nodetype_markable_p(old_type) != nodetype_markable_p(type)) { + rb_bug("node type changed: %s -> %s", + ruby_node_name(old_type), ruby_node_name(type)); } } +rb_ast_id_table_t * +rb_ast_new_local_table(rb_ast_t *ast, int size) +{ + size_t alloc_size = sizeof(struct rb_ast_local_table_link) + size * sizeof(ID); + struct rb_ast_local_table_link *link = ruby_xmalloc(alloc_size); + link->next = ast->node_buffer->local_tables; + ast->node_buffer->local_tables = link; + link->size = size; + + return (rb_ast_id_table_t *) &link->size; +} + +rb_ast_id_table_t * +rb_ast_resize_latest_local_table(rb_ast_t *ast, int size) +{ + struct rb_ast_local_table_link *link = ast->node_buffer->local_tables; + size_t alloc_size = sizeof(struct rb_ast_local_table_link) + size * sizeof(ID); + link = ruby_xrealloc(link, alloc_size); + ast->node_buffer->local_tables = link; + link->size = size; + + return (rb_ast_id_table_t *) &link->size; +} + void rb_ast_delete_node(rb_ast_t *ast, NODE *n) { @@ -1253,21 +1347,6 @@ static void mark_ast_value(void *ctx, NODE * node) { switch (nd_type(node)) { - case NODE_SCOPE: - { - ID *buf = node->nd_tbl; - if (buf) { - unsigned int size = (unsigned int)*buf; - rb_gc_mark_movable((VALUE)buf[size + 1]); - } - break; - } - case NODE_ARYPTN: - { - struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - rb_gc_mark_movable(apinfo->imemo); - break; - } case NODE_ARGS: { struct rb_args_info *args = node->nd_ainfo; @@ -1284,6 +1363,10 @@ mark_ast_value(void *ctx, NODE * node) case NODE_DSYM: rb_gc_mark_movable(node->nd_lit); break; + case NODE_ARYPTN: + case NODE_FNDPTN: + rb_gc_mark_movable(node->nd_rval); + break; default: rb_bug("unreachable node %s", ruby_node_name(nd_type(node))); } @@ -1293,27 +1376,13 @@ static void update_ast_value(void *ctx, NODE * node) { switch (nd_type(node)) { - case NODE_SCOPE: - { - ID *buf = node->nd_tbl; - if (buf) { - unsigned int size = (unsigned int)*buf; - buf[size + 1] = rb_gc_location((VALUE)buf[size + 1]); - } - break; - } - case NODE_ARYPTN: - { - struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - apinfo->imemo = rb_gc_location(apinfo->imemo); - break; - } case NODE_ARGS: { struct rb_args_info *args = node->nd_ainfo; args->imemo = rb_gc_location(args->imemo); break; } + case NODE_MATCH: case NODE_LIT: case NODE_STR: case NODE_XSTR: @@ -1323,6 +1392,10 @@ update_ast_value(void *ctx, NODE * node) case NODE_DSYM: node->nd_lit = rb_gc_location(node->nd_lit); break; + case NODE_ARYPTN: + case NODE_FNDPTN: + node->nd_rval = rb_gc_location(node->nd_rval); + break; default: rb_bug("unreachable"); } @@ -1348,6 +1421,7 @@ rb_ast_mark(rb_ast_t *ast) iterate_node_values(&nb->markable, mark_ast_value, NULL); } + if (ast->body.script_lines) rb_gc_mark(ast->body.script_lines); } void diff --git a/ruby/node.h b/ruby/node.h index 217b34455..ebe82b85b 100644 --- a/ruby/node.h +++ b/ruby/node.h @@ -1,3 +1,5 @@ +#ifndef RUBY_NODE_H +#define RUBY_NODE_H 1 /********************************************************************** node.h - @@ -9,8 +11,7 @@ **********************************************************************/ -#ifndef RUBY_NODE_H -#define RUBY_NODE_H 1 +#include "internal/compilers.h" #if defined(__cplusplus) extern "C" { @@ -47,7 +48,6 @@ enum node_type { NODE_MASGN, NODE_LASGN, NODE_DASGN, - NODE_DASGN_CURR, NODE_GASGN, NODE_IASGN, NODE_CDECL, @@ -124,6 +124,7 @@ enum node_type { NODE_LAMBDA, NODE_ARYPTN, NODE_HSHPTN, + NODE_FNDPTN, NODE_LAST }; @@ -138,7 +139,7 @@ typedef struct rb_code_location_struct { } rb_code_location_t; static inline rb_code_location_t -code_loc_gen(rb_code_location_t *loc1, rb_code_location_t *loc2) +code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2) { rb_code_location_t loc; loc.beg_pos = loc1->beg_pos; @@ -146,13 +147,18 @@ code_loc_gen(rb_code_location_t *loc1, rb_code_location_t *loc2) return loc; } +typedef struct rb_ast_id_table { + int size; + ID ids[FLEX_ARY_LEN]; +} rb_ast_id_table_t; + typedef struct RNode { VALUE flags; union { struct RNode *node; ID id; VALUE value; - ID *tbl; + rb_ast_id_table_t *tbl; } u1; union { struct RNode *node; @@ -164,16 +170,16 @@ typedef struct RNode { struct RNode *node; ID id; long state; - struct rb_global_entry *entry; struct rb_args_info *args; - struct rb_ary_pattern_info *apinfo; + struct rb_ary_pattern_info *apinfo; + struct rb_fnd_pattern_info *fpinfo; VALUE value; } u3; rb_code_location_t nd_loc; int node_id; } NODE; -#define RNODE(obj) (R_CAST(RNode)(obj)) +#define RNODE(obj) ((struct RNode *)(obj)) /* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */ /* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: NODE_FL_NEWLINE, @@ -187,6 +193,8 @@ typedef struct RNode { #define nd_type(n) ((int) (((n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT)) #define nd_set_type(n,t) \ + rb_node_set_type(n, t) +#define nd_init_type(n,t) \ (n)->flags=(((n)->flags&~NODE_TYPEMASK)|((((unsigned long)(t))< #include #include @@ -26,13 +24,28 @@ #include #endif +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compilers.h" +#include "internal/complex.h" +#include "internal/enumerator.h" +#include "internal/gc.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/rational.h" +#include "internal/string.h" +#include "internal/util.h" +#include "internal/variable.h" +#include "ruby/encoding.h" +#include "ruby/util.h" +#include "builtin.h" + /* use IEEE 64bit values if not defined */ #ifndef FLT_RADIX #define FLT_RADIX 2 #endif -#ifndef FLT_ROUNDS -#define FLT_ROUNDS 1 -#endif #ifndef DBL_MIN #define DBL_MIN 2.2250738585072014e-308 #endif @@ -158,15 +171,11 @@ round_half_even(double x, double s) return x; } -static VALUE fix_uminus(VALUE num); -static VALUE fix_mul(VALUE x, VALUE y); static VALUE fix_lshift(long, unsigned long); static VALUE fix_rshift(long, unsigned long); static VALUE int_pow(long x, unsigned long y); -static VALUE int_even_p(VALUE x); -static int int_round_zero_p(VALUE num, int ndigits); -VALUE rb_int_floor(VALUE num, int ndigits); -VALUE rb_int_ceil(VALUE num, int ndigits); +static VALUE rb_int_floor(VALUE num, int ndigits); +static VALUE rb_int_ceil(VALUE num, int ndigits); static VALUE flo_to_i(VALUE num); static int float_round_overflow(int ndigits, int binexp); static int float_round_underflow(int ndigits, int binexp); @@ -181,9 +190,6 @@ static ID id_coerce; VALUE rb_cNumeric; VALUE rb_cFloat; VALUE rb_cInteger; -#ifndef RUBY_INTEGER_UNIFICATION -VALUE rb_cFixnum; -#endif VALUE rb_eZeroDivError; VALUE rb_eFloatDomainError; @@ -219,6 +225,7 @@ rb_num_get_rounding_option(VALUE opts) str = rb_check_string_type(rounding); if (NIL_P(str)) goto invalid; } + rb_must_asciicompat(str); s = RSTRING_PTR(str); switch (RSTRING_LEN(str)) { case 2: @@ -256,7 +263,7 @@ rb_num_to_uint(VALUE val, unsigned int *ret) return 0; } - if (RB_TYPE_P(val, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(val)) { if (BIGNUM_NEGATIVE_P(val)) return NUMERR_NEGATIVE; #if SIZEOF_INT < SIZEOF_LONG /* long is 64bit */ @@ -279,7 +286,7 @@ int_pos_p(VALUE num) if (FIXNUM_P(num)) { return FIXNUM_POSITIVE_P(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return BIGNUM_POSITIVE_P(num); } rb_raise(rb_eTypeError, "not an Integer"); @@ -291,7 +298,7 @@ int_neg_p(VALUE num) if (FIXNUM_P(num)) { return FIXNUM_NEGATIVE_P(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return BIGNUM_NEGATIVE_P(num); } rb_raise(rb_eTypeError, "not an Integer"); @@ -381,19 +388,37 @@ num_funcall1(VALUE x, ID func, VALUE y) /* * call-seq: - * num.coerce(numeric) -> array + * coerce(other) -> array + * + * Returns a 2-element array containing two numeric elements, + * formed from the two operands +self+ and +other+, + * of a common compatible type. + * + * Of the Core and Standard Library classes, + * Integer, Rational, and Complex use this implementation. + * + * Examples: + * + * i = 2 # => 2 + * i.coerce(3) # => [3, 2] + * i.coerce(3.0) # => [3.0, 2.0] + * i.coerce(Rational(1, 2)) # => [0.5, 2.0] + * i.coerce(Complex(3, 4)) # Raises RangeError. * - * If +numeric+ is the same type as +num+, returns an array - * [numeric, num]. Otherwise, returns an array with both - * +numeric+ and +num+ represented as Float objects. + * r = Rational(5, 2) # => (5/2) + * r.coerce(2) # => [(2/1), (5/2)] + * r.coerce(2.0) # => [2.0, 2.5] + * r.coerce(Rational(2, 3)) # => [(2/3), (5/2)] + * r.coerce(Complex(3, 4)) # => [(3+4i), ((5/2)+0i)] * - * This coercion mechanism is used by Ruby to handle mixed-type numeric - * operations: it is intended to find a compatible common type between the two - * operands of the operator. + * c = Complex(2, 3) # => (2+3i) + * c.coerce(2) # => [(2+0i), (2+3i)] + * c.coerce(2.0) # => [(2.0+0i), (2+3i)] + * c.coerce(Rational(1, 2)) # => [((1/2)+0i), (2+3i)] + * c.coerce(Complex(3, 4)) # => [(3+4i), (2+3i)] + * + * Raises an exception if any type conversion fails. * - * 1.coerce(2.5) #=> [2.5, 1.0] - * 1.2.coerce(3) #=> [3.0, 1.2] - * 1.coerce(2) #=> [2, 1] */ static VALUE @@ -457,19 +482,27 @@ rb_num_coerce_cmp(VALUE x, VALUE y, ID func) return Qnil; } +static VALUE +ensure_cmp(VALUE c, VALUE x, VALUE y) +{ + if (NIL_P(c)) rb_cmperr(x, y); + return c; +} + VALUE rb_num_coerce_relop(VALUE x, VALUE y, ID func) { - VALUE c, x0 = x, y0 = y; + VALUE x0 = x, y0 = y; - if (!do_coerce(&x, &y, FALSE) || - NIL_P(c = rb_funcall(x, func, 1, y))) { + if (!do_coerce(&x, &y, FALSE)) { rb_cmperr(x0, y0); - return Qnil; /* not reached */ + UNREACHABLE_RETURN(Qnil); } - return c; + return ensure_cmp(rb_funcall(x, func, 1, y), x0, y0); } +NORETURN(static VALUE num_sadded(VALUE x, VALUE name)); + /* * :nodoc: * @@ -495,9 +528,14 @@ num_sadded(VALUE x, VALUE name) #if 0 /* * call-seq: - * num.clone(freeze: true) -> num + * clone(freeze: true) -> self + * + * Returns +self+. + * + * Raises an exception if the value for +freeze+ is neither +true+ nor +nil+. + * + * Related: Numeric#dup. * - * Returns the receiver. +freeze+ cannot be +false+. */ static VALUE num_clone(int argc, VALUE *argv, VALUE x) @@ -511,9 +549,12 @@ num_clone(int argc, VALUE *argv, VALUE x) #if 0 /* * call-seq: - * num.dup -> num + * dup -> self + * + * Returns +self+. + * + * Related: Numeric#clone. * - * Returns the receiver. */ static VALUE num_dup(VALUE x) @@ -526,9 +567,10 @@ num_dup(VALUE x) /* * call-seq: - * +num -> num + * +self -> self + * + * Returns +self+. * - * Unary Plus---Returns the receiver. */ static VALUE @@ -539,13 +581,16 @@ num_uplus(VALUE num) /* * call-seq: - * num.i -> Complex(0, num) + * i -> complex * - * Returns the corresponding imaginary number. - * Not available for complex numbers. + * Returns Complex(0, self): + * + * 2.i # => (0+2i) + * -2.i # => (0-2i) + * 2.0.i # => (0+2.0i) + * Rational(1, 2).i # => (0+(1/2)*i) + * Complex(3, 4).i # Raises NoMethodError. * - * -42.i #=> (0-42i) - * 2.0.i #=> (0+2.0i) */ static VALUE @@ -556,7 +601,7 @@ num_imaginary(VALUE num) /* * call-seq: - * -num -> numeric + * -self -> numeric * * Unary Minus---Returns the receiver, negated. */ @@ -574,9 +619,15 @@ num_uminus(VALUE num) /* * call-seq: - * num.fdiv(numeric) -> float + * fdiv(other) -> float + * + * Returns the quotient self/other as a float, + * using method +/+ in the derived class of +self+. + * (\Numeric itself does not define method +/+.) + * + * Of the Core and Standard Library classes, + * only BigDecimal uses this implementation. * - * Returns float division. */ static VALUE @@ -587,14 +638,15 @@ num_fdiv(VALUE x, VALUE y) /* * call-seq: - * num.div(numeric) -> integer + * div(other) -> integer * - * Uses +/+ to perform division, then converts the result to an integer. - * Numeric does not define the +/+ operator; this is left to subclasses. + * Returns the quotient self/other as an integer (via +floor+), + * using method +/+ in the derived class of +self+. + * (\Numeric itself does not define method +/+.) * - * Equivalent to num.divmod(numeric)[0]. + * Of the Core and Standard Library classes, + * Float, Rational, and Complex use this implementation. * - * See Numeric#divmod. */ static VALUE @@ -606,13 +658,38 @@ num_div(VALUE x, VALUE y) /* * call-seq: - * num.modulo(numeric) -> real + * self % other -> real_numeric + * + * Returns +self+ modulo +other+ as a real number. + * + * Of the Core and Standard Library classes, + * only Rational uses this implementation. * - * x.modulo(y) means x-y*(x/y).floor. + * For \Rational +r+ and real number +n+, these expressions are equivalent: * - * Equivalent to num.divmod(numeric)[1]. + * c % n + * c-n*(c/n).floor + * c.divmod(n)[1] * * See Numeric#divmod. + * + * Examples: + * + * r = Rational(1, 2) # => (1/2) + * r2 = Rational(2, 3) # => (2/3) + * r % r2 # => (1/2) + * r % 2 # => (1/2) + * r % 2.0 # => 0.5 + * + * r = Rational(301,100) # => (301/100) + * r2 = Rational(7,5) # => (7/5) + * r % r2 # => (21/100) + * r % -r2 # => (-119/100) + * (-r) % r2 # => (119/100) + * (-r) %-r2 # => (-21/100) + * + * Numeric#modulo is an alias for Numeric#%. + * */ static VALUE @@ -625,11 +702,33 @@ num_modulo(VALUE x, VALUE y) /* * call-seq: - * num.remainder(numeric) -> real + * remainder(other) -> real_number * - * x.remainder(y) means x-y*(x/y).truncate. + * Returns the remainder after dividing +self+ by +other+. + * + * Of the Core and Standard Library classes, + * only Float and Rational use this implementation. + * + * Examples: + * + * 11.0.remainder(4) # => 3.0 + * 11.0.remainder(-4) # => 3.0 + * -11.0.remainder(4) # => -3.0 + * -11.0.remainder(-4) # => -3.0 + * + * 12.0.remainder(4) # => 0.0 + * 12.0.remainder(-4) # => 0.0 + * -12.0.remainder(4) # => -0.0 + * -12.0.remainder(-4) # => -0.0 + * + * 13.0.remainder(4.0) # => 1.0 + * 13.0.remainder(Rational(4, 1)) # => 1.0 + * + * Rational(13, 1).remainder(4) # => (1/1) + * Rational(13, 1).remainder(-4) # => (1/1) + * Rational(-13, 1).remainder(4) # => (-1/1) + * Rational(-13, 1).remainder(-4) # => (-1/1) * - * See Numeric#divmod. */ static VALUE @@ -642,6 +741,11 @@ num_remainder(VALUE x, VALUE y) rb_num_positive_int_p(y)) || (rb_num_positive_int_p(x) && rb_num_negative_int_p(y)))) { + if (RB_FLOAT_TYPE_P(y)) { + if (isinf(RFLOAT_VALUE(y))) { + return x; + } + } return rb_funcall(z, '-', 1, y); } return z; @@ -649,94 +753,50 @@ num_remainder(VALUE x, VALUE y) /* * call-seq: - * num.divmod(numeric) -> array - * - * Returns an array containing the quotient and modulus obtained by dividing - * +num+ by +numeric+. - * - * If q, r = x.divmod(y), then - * - * q = floor(x/y) - * x = q*y + r - * - * The quotient is rounded toward negative infinity, as shown in the - * following table: - * - * a | b | a.divmod(b) | a/b | a.modulo(b) | a.remainder(b) - * ------+-----+---------------+---------+-------------+--------------- - * 13 | 4 | 3, 1 | 3 | 1 | 1 - * ------+-----+---------------+---------+-------------+--------------- - * 13 | -4 | -4, -3 | -4 | -3 | 1 - * ------+-----+---------------+---------+-------------+--------------- - * -13 | 4 | -4, 3 | -4 | 3 | -1 - * ------+-----+---------------+---------+-------------+--------------- - * -13 | -4 | 3, -1 | 3 | -1 | -1 - * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5 - * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5 - * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5 - * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | -4 | 2, -3.5 | 2.875 | -3.5 | -3.5 - * - * - * Examples - * - * 11.divmod(3) #=> [3, 2] - * 11.divmod(-3) #=> [-4, -1] - * 11.divmod(3.5) #=> [3, 0.5] - * (-11).divmod(3.5) #=> [-4, 3.0] - * 11.5.divmod(3.5) #=> [3, 1.0] - */ - -static VALUE -num_divmod(VALUE x, VALUE y) -{ - return rb_assoc_new(num_div(x, y), num_modulo(x, y)); -} - -/* - * call-seq: - * num.real? -> true or false + * divmod(other) -> array * - * Returns +true+ if +num+ is a real number (i.e. not Complex). - */ - -static VALUE -num_real_p(VALUE num) -{ - return Qtrue; -} - -/* - * call-seq: - * num.integer? -> true or false + * Returns a 2-element array [q, r], where + * + * q = (self/other).floor # Quotient + * r = self % other # Remainder + * + * Of the Core and Standard Library classes, + * only Rational uses this implementation. + * + * Examples: + * + * Rational(11, 1).divmod(4) # => [2, (3/1)] + * Rational(11, 1).divmod(-4) # => [-3, (-1/1)] + * Rational(-11, 1).divmod(4) # => [-3, (1/1)] + * Rational(-11, 1).divmod(-4) # => [2, (-3/1)] * - * Returns +true+ if +num+ is an Integer. + * Rational(12, 1).divmod(4) # => [3, (0/1)] + * Rational(12, 1).divmod(-4) # => [-3, (0/1)] + * Rational(-12, 1).divmod(4) # => [-3, (0/1)] + * Rational(-12, 1).divmod(-4) # => [3, (0/1)] * - * 1.0.integer? #=> false - * 1.integer? #=> true + * Rational(13, 1).divmod(4.0) # => [3, 1.0] + * Rational(13, 1).divmod(Rational(4, 11)) # => [35, (3/11)] */ static VALUE -num_int_p(VALUE num) +num_divmod(VALUE x, VALUE y) { - return Qfalse; + return rb_assoc_new(num_div(x, y), num_modulo(x, y)); } /* * call-seq: - * num.abs -> numeric - * num.magnitude -> numeric + * abs -> numeric * - * Returns the absolute value of +num+. + * Returns the absolute value of +self+. * - * 12.abs #=> 12 - * (-34.56).abs #=> 34.56 - * -34.56.abs #=> 34.56 + * 12.abs #=> 12 + * (-34.56).abs #=> 34.56 + * -34.56.abs #=> 34.56 * * Numeric#magnitude is an alias for Numeric#abs. + * */ static VALUE @@ -750,42 +810,53 @@ num_abs(VALUE num) /* * call-seq: - * num.zero? -> true or false + * zero? -> true or false + * + * Returns +true+ if +zero+ has a zero value, +false+ otherwise. + * + * Of the Core and Standard Library classes, + * only Rational and Complex use this implementation. * - * Returns +true+ if +num+ has a zero value. */ static VALUE num_zero_p(VALUE num) +{ + return rb_equal(num, INT2FIX(0)); +} + +static VALUE +int_zero_p(VALUE num) { if (FIXNUM_P(num)) { - if (FIXNUM_ZERO_P(num)) { - return Qtrue; - } - } - else if (RB_TYPE_P(num, T_BIGNUM)) { - if (rb_bigzero_p(num)) { - /* this should not happen usually */ - return Qtrue; - } - } - else if (rb_equal(num, INT2FIX(0))) { - return Qtrue; + return RBOOL(FIXNUM_ZERO_P(num)); } - return Qfalse; + assert(RB_BIGNUM_TYPE_P(num)); + return RBOOL(rb_bigzero_p(num)); +} + +VALUE +rb_int_zero_p(VALUE num) +{ + return int_zero_p(num); } /* * call-seq: - * num.nonzero? -> self or nil + * nonzero? -> self or nil + * + * Returns +self+ if +self+ is not a zero value, +nil+ otherwise; + * uses method zero? for the evaluation. * - * Returns +self+ if +num+ is not zero, +nil+ otherwise. + * The returned +self+ allows the method to be chained: * - * This behavior is useful when chaining comparisons: + * a = %w[z Bb bB bb BB a aA Aa AA A] + * a.sort {|a, b| (a.downcase <=> b.downcase).nonzero? || a <=> b } + * # => ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"] + * + * Of the Core and Standard Library classes, + * Integer, Float, Rational, and Complex use this implementation. * - * a = %w( z Bb bB bb BB a aA Aa AA A ) - * b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b } - * b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"] */ static VALUE @@ -799,38 +870,21 @@ num_nonzero_p(VALUE num) /* * call-seq: - * num.finite? -> true or false + * to_int -> integer * - * Returns +true+ if +num+ is a finite number, otherwise returns +false+. - */ -static VALUE -num_finite_p(VALUE num) -{ - return Qtrue; -} - -/* - * call-seq: - * num.infinite? -> -1, 1, or nil + * Returns +self+ as an integer; + * converts using method +to_i+ in the derived class. * - * Returns +nil+, -1, or 1 depending on whether the value is - * finite, -Infinity, or +Infinity. - */ -static VALUE -num_infinite_p(VALUE num) -{ - return Qnil; -} - -/* - * call-seq: - * num.to_int -> integer + * Of the Core and Standard Library classes, + * only Rational and Complex use this implementation. * - * Invokes the child class's +to_i+ method to convert +num+ to an integer. + * Examples: + * + * Rational(1, 2).to_int # => 0 + * Rational(2, 1).to_int # => 2 + * Complex(2, 0).to_int # => 2 + * Complex(2, 1) # Raises RangeError (non-zero imaginary part) * - * 1.0.class #=> Float - * 1.0.to_int.class #=> Integer - * 1.0.to_i.class #=> Integer */ static VALUE @@ -841,9 +895,10 @@ num_to_int(VALUE num) /* * call-seq: - * num.positive? -> true or false + * positive? -> true or false + * + * Returns +true+ if +self+ is greater than 0, +false+ otherwise. * - * Returns +true+ if +num+ is greater than 0. */ static VALUE @@ -853,42 +908,108 @@ num_positive_p(VALUE num) if (FIXNUM_P(num)) { if (method_basic_p(rb_cInteger)) - return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0) ? Qtrue : Qfalse; + return RBOOL((SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0)); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { if (method_basic_p(rb_cInteger)) - return BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num) ? Qtrue : Qfalse; + return RBOOL(BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num)); } return rb_num_compare_with_zero(num, mid); } /* * call-seq: - * num.negative? -> true or false + * negative? -> true or false + * + * Returns +true+ if +self+ is less than 0, +false+ otherwise. * - * Returns +true+ if +num+ is less than 0. */ static VALUE num_negative_p(VALUE num) { - return rb_num_negative_int_p(num) ? Qtrue : Qfalse; + return RBOOL(rb_num_negative_int_p(num)); } /******************************************************************** * - * Document-class: Float + * Document-class: Float * - * Float objects represent inexact real numbers using the native + * A \Float object represents a sometimes-inexact real number using the native * architecture's double-precision floating point representation. * * Floating point has a different arithmetic and is an inexact number. * So you should know its esoteric system. See following: * - * - http://docs.sun.com/source/806-3568/ncg_goldberg.html + * - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html * - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#floats_imprecise - * - http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems + * - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems + * + * You can create a \Float object explicitly with: + * + * - A {floating-point literal}[doc/syntax/literals_rdoc.html#label-Float+Literals]. + * + * You can convert certain objects to Floats with: + * + * - \Method {Float}[Kernel.html#method-i-Float]. + * + * == What's Here + * + * First, what's elsewhere. \Class \Float: + * + * - Inherits from {class Numeric}[Numeric.html#class-Numeric-label-What-27s+Here]. + * + * Here, class \Float provides methods for: + * + * - {Querying}[#class-Float-label-Querying] + * - {Comparing}[#class-Float-label-Comparing] + * - {Converting}[#class-Float-label-Converting] + * + * === Querying + * + * - #finite?:: Returns whether +self+ is finite. + * - #hash:: Returns the integer hash code for +self+. + * - #infinite?:: Returns whether +self+ is infinite. + * - #nan?:: Returns whether +self+ is a NaN (not-a-number). + * + * === Comparing + * + * - {<}[#method-i-3C]:: Returns whether +self+ is less than the given value. + * - {<=}[#method-i-3C-3D]:: Returns whether +self+ is less than + * or equal to the given value. + * - {<=>}[#method-i-3C-3D-3E]:: Returns a number indicating whether +self+ is less than, + * equal to, or greater than the given value. + * - {==}[#method-i-3D-3D] (aliased as #=== and #eql>):: Returns whether +self+ is + * equal to the given value. + * - {>}[#method-i-3E]:: Returns whether +self+ is greater than the given value. + * - {>=}[#method-i-3E-3D]:: Returns whether +self+ is greater than + * or equal to the given value. + * + * === Converting + * + * - #% (aliased as #modulo):: Returns +self+ modulo the given value. + * - #*:: Returns the product of +self+ and the given value. + * - {**}[#method-i-2A-2A]:: Returns the value of +self+ raised to the power of the given value. + * - #+:: Returns the sum of +self+ and the given value. + * - #-:: Returns the difference of +self+ and the given value. + * - {/}[#method-i-2F]:: Returns the quotient of +self+ and the given value. + * - #ceil:: Returns the smallest number greater than or equal to +self+. + * - #coerce:: Returns a 2-element array containing the given value converted to a \Float + and +self+ + * - #divmod:: Returns a 2-element array containing the quotient and remainder + * results of dividing +self+ by the given value. + * - #fdiv:: Returns the Float result of dividing +self+ by the given value. + * - #floor:: Returns the greatest number smaller than or equal to +self+. + * - #next_float:: Returns the next-larger representable \Float. + * - #prev_float:: Returns the next-smaller representable \Float. + * - #quo:: Returns the quotient from dividing +self+ by the given value. + * - #round:: Returns +self+ rounded to the nearest value, to a given precision. + * - #to_i (aliased as #to_int):: Returns +self+ truncated to an Integer. + * - #to_s (aliased as #inspect):: Returns a string containing the place-value + * representation of +self+ in the given radix. + * - #truncate:: Returns +self+ truncated to a given precision. + * */ VALUE @@ -896,18 +1017,39 @@ rb_float_new_in_heap(double d) { NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0)); +#if SIZEOF_DOUBLE <= SIZEOF_VALUE flt->float_value = d; - OBJ_FREEZE(flt); +#else + union { + double d; + rb_float_value_type v; + } u = {d}; + flt->float_value = u.v; +#endif + OBJ_FREEZE((VALUE)flt); return (VALUE)flt; } /* * call-seq: - * float.to_s -> string + * to_s -> string + * + * Returns a string containing a representation of +self+; + * depending of the value of +self+, the string representation + * may contain: + * + * - A fixed-point number. + * - A number in "scientific notation" (containing an exponent). + * - 'Infinity'. + * - '-Infinity'. + * - 'NaN' (indicating not-a-number). + * + * 3.14.to_s # => "3.14" + * (10.1**50).to_s # => "1.644631821843879e+50" + * (10.1**500).to_s # => "Infinity" + * (-10.1**500).to_s # => "-Infinity" + * (0.0/0.0).to_s # => "NaN" * - * Returns a string containing a representation of +self+. - * As well as a fixed or exponential form of the +float+, - * the call may return +NaN+, +Infinity+, and +-Infinity+. */ static VALUE @@ -966,32 +1108,39 @@ flo_to_s(VALUE flt) memcpy(ptr -= decpt, buf, digs); } else { - exp: - if (digs > 1) { - memmove(buf + 2, buf + 1, digs - 1); - } - else { - buf[2] = '0'; - digs++; - } - buf[1] = '.'; - rb_str_cat(s, buf, digs + 1); - rb_str_catf(s, "e%+03d", decpt - 1); + goto exp; + } + return s; + + exp: + if (digs > 1) { + memmove(buf + 2, buf + 1, digs - 1); + } + else { + buf[2] = '0'; + digs++; } + buf[1] = '.'; + rb_str_cat(s, buf, digs + 1); + rb_str_catf(s, "e%+03d", decpt - 1); return s; } /* * call-seq: - * float.coerce(numeric) -> array + * coerce(other) -> array * - * Returns an array with both +numeric+ and +float+ represented as Float - * objects. + * Returns a 2-element array containing +other+ converted to a \Float + * and +self+: * - * This is achieved by converting +numeric+ to a Float. + * f = 3.14 # => 3.14 + * f.coerce(2) # => [2.0, 3.14] + * f.coerce(2.0) # => [2.0, 3.14] + * f.coerce(Rational(1, 2)) # => [0.5, 3.14] + * f.coerce(Complex(1, 0)) # => [1.0, 3.14] + * + * Raises an exception if a type conversion fails. * - * 1.2.coerce(3) #=> [3.0, 1.2] - * 2.5.coerce(1.1) #=> [1.1, 2.5] */ static VALUE @@ -1000,36 +1149,36 @@ flo_coerce(VALUE x, VALUE y) return rb_assoc_new(rb_Float(y), x); } -/* - * call-seq: - * -float -> float - * - * Returns +float+, negated. - */ - -VALUE +MJIT_FUNC_EXPORTED VALUE rb_float_uminus(VALUE flt) { return DBL2NUM(-RFLOAT_VALUE(flt)); } /* - * call-seq: - * float + other -> float + * call-seq: + * self + other -> numeric + * + * Returns a new \Float which is the sum of +self+ and +other+: + * + * f = 3.14 + * f + 1 # => 4.140000000000001 + * f + 1.0 # => 4.140000000000001 + * f + Rational(1, 1) # => 4.140000000000001 + * f + Complex(1, 0) # => (4.140000000000001+0i) * - * Returns a new Float which is the sum of +float+ and +other+. */ VALUE rb_float_plus(VALUE x, VALUE y) { - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y)); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y)); } else { @@ -1038,22 +1187,29 @@ rb_float_plus(VALUE x, VALUE y) } /* - * call-seq: - * float - other -> float + * call-seq: + * self - other -> numeric + * + * Returns a new \Float which is the difference of +self+ and +other+: + * + * f = 3.14 + * f - 1 # => 2.14 + * f - 1.0 # => 2.14 + * f - Rational(1, 1) # => 2.14 + * f - Complex(1, 0) # => (2.14+0i) * - * Returns a new Float which is the difference of +float+ and +other+. */ -static VALUE -flo_minus(VALUE x, VALUE y) +VALUE +rb_float_minus(VALUE x, VALUE y) { - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y)); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y)); } else { @@ -1062,22 +1218,28 @@ flo_minus(VALUE x, VALUE y) } /* - * call-seq: - * float * other -> float + * call-seq: + * self * other -> numeric * - * Returns a new Float which is the product of +float+ and +other+. + * Returns a new \Float which is the product of +self+ and +other+: + * + * f = 3.14 + * f * 2 # => 6.28 + * f * 2.0 # => 6.28 + * f * Rational(1, 2) # => 1.57 + * f * Complex(2, 0) # => (6.28+0.0i) */ VALUE rb_float_mul(VALUE x, VALUE y) { - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y)); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y)); } else { @@ -1085,12 +1247,6 @@ rb_float_mul(VALUE x, VALUE y) } } -static bool -flo_iszero(VALUE f) -{ - return FLOAT_ZERO_P(f); -} - static double double_div_double(double x, double y) { @@ -1116,10 +1272,17 @@ rb_flo_div_flo(VALUE x, VALUE y) } /* - * call-seq: - * float / other -> float + * call-seq: + * self / other -> numeric + * + * Returns a new \Float which is the result of dividing +self+ by +other+: + * + * f = 3.14 + * f / 2 # => 1.57 + * f / 2.0 # => 1.57 + * f / Rational(2, 1) # => 1.57 + * f / Complex(2, 0) # => (1.57+0.0i) * - * Returns a new Float which is the result of dividing +float+ by +other+. */ VALUE @@ -1129,13 +1292,13 @@ rb_float_div(VALUE x, VALUE y) double den; double ret; - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { den = FIX2LONG(y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { den = rb_big2dbl(y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { den = RFLOAT_VALUE(y); } else { @@ -1148,10 +1311,18 @@ rb_float_div(VALUE x, VALUE y) /* * call-seq: - * float.fdiv(numeric) -> float - * float.quo(numeric) -> float + * quo(other) -> numeric + * + * Returns the quotient from dividing +self+ by +other+: + * + * f = 3.14 + * f.quo(2) # => 1.57 + * f.quo(-2) # => -1.57 + * f.quo(Rational(2, 1)) # => 1.57 + * f.quo(Complex(2, 0)) # => (1.57+0.0i) + * + * Float#fdiv is an alias for Float#quo. * - * Returns float / numeric, same as Float#/. */ static VALUE @@ -1188,11 +1359,11 @@ flodivmod(double x, double y, double *divp, double *modp) div = x; else { div = (x - mod) / y; - if (modp && divp) div = round(div); + if (modp && divp) div = round(div); } if (y*mod < 0) { - mod += y; - div -= 1.0; + mod += y; + div -= 1.0; } if (modp) *modp = mod; if (divp) *divp = div; @@ -1213,13 +1384,33 @@ ruby_float_mod(double x, double y) /* * call-seq: - * float % other -> float - * float.modulo(other) -> float + * self % other -> float + * + * Returns +self+ modulo +other+ as a float. * - * Returns the modulo after division of +float+ by +other+. + * For float +f+ and real number +r+, these expressions are equivalent: + * + * f % r + * f-r*(f/r).floor + * f.divmod(r)[1] + * + * See Numeric#divmod. + * + * Examples: + * + * 10.0 % 2 # => 0.0 + * 10.0 % 3 # => 1.0 + * 10.0 % 4 # => 2.0 + * + * 10.0 % -2 # => 0.0 + * 10.0 % -3 # => -2.0 + * 10.0 % -4 # => -2.0 + * + * 10.0 % 4.0 # => 2.0 + * 10.0 % Rational(4, 1) # => 2.0 + * + * Float#modulo is an alias for Float#%. * - * 6543.21.modulo(137) #=> 104.21000000000004 - * 6543.21.modulo(137.24) #=> 92.92999999999961 */ static VALUE @@ -1227,13 +1418,13 @@ flo_mod(VALUE x, VALUE y) { double fy; - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { fy = (double)FIX2LONG(y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { fy = rb_big2dbl(y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { fy = RFLOAT_VALUE(y); } else { @@ -1253,12 +1444,28 @@ dbl2ival(double d) /* * call-seq: - * float.divmod(numeric) -> array + * divmod(other) -> array * - * See Numeric#divmod. + * Returns a 2-element array [q, r], where + * + * q = (self/other).floor # Quotient + * r = self % other # Remainder + * + * Examples: + * + * 11.0.divmod(4) # => [2, 3.0] + * 11.0.divmod(-4) # => [-3, -1.0] + * -11.0.divmod(4) # => [-3, 1.0] + * -11.0.divmod(-4) # => [2, -3.0] + * + * 12.0.divmod(4) # => [3, 0.0] + * 12.0.divmod(-4) # => [-3, 0.0] + * -12.0.divmod(4) # => [-3, -0.0] + * -12.0.divmod(-4) # => [3, -0.0] + * + * 13.0.divmod(4.0) # => [3, 1.0] + * 13.0.divmod(Rational(4, 1)) # => [3, 1.0] * - * 42.0.divmod(6) #=> [7, 0.0] - * 42.0.divmod(5) #=> [8, 2.0] */ static VALUE @@ -1267,13 +1474,13 @@ flo_divmod(VALUE x, VALUE y) double fy, div, mod; volatile VALUE a, b; - if (RB_TYPE_P(y, T_FIXNUM)) { + if (FIXNUM_P(y)) { fy = (double)FIX2LONG(y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { fy = rb_big2dbl(y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { fy = RFLOAT_VALUE(y); } else { @@ -1286,27 +1493,37 @@ flo_divmod(VALUE x, VALUE y) } /* - * call-seq: - * float ** other -> float + * call-seq: + * self ** other -> numeric * - * Raises +float+ to the power of +other+. + * Raises +self+ to the power of +other+: + * + * f = 3.14 + * f ** 2 # => 9.8596 + * f ** -2 # => 0.1014239928597509 + * f ** 2.1 # => 11.054834900588839 + * f ** Rational(2, 1) # => 9.8596 + * f ** Complex(2, 0) # => (9.8596+0i) * - * 2.0**3 #=> 8.0 */ VALUE rb_float_pow(VALUE x, VALUE y) { double dx, dy; - if (RB_TYPE_P(y, T_FIXNUM)) { + if (y == INT2FIX(2)) { + dx = RFLOAT_VALUE(x); + return DBL2NUM(dx * dx); + } + else if (FIXNUM_P(y)) { dx = RFLOAT_VALUE(x); dy = (double)FIX2LONG(y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { dx = RFLOAT_VALUE(x); dy = rb_big2dbl(y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { dx = RFLOAT_VALUE(x); dy = RFLOAT_VALUE(y); if (dx < 0 && dy != round(dy)) @@ -1320,14 +1537,23 @@ rb_float_pow(VALUE x, VALUE y) /* * call-seq: - * num.eql?(numeric) -> true or false + * eql?(other) -> true or false + * + * Returns +true+ if +self+ and +other+ are the same type and have equal values. + * + * Of the Core and Standard Library classes, + * only Integer, Rational, and Complex use this implementation. + * + * Examples: * - * Returns +true+ if +num+ and +numeric+ are the same type and have equal - * values. Contrast this with Numeric#==, which performs type conversions. + * 1.eql?(1) # => true + * 1.eql?(1.0) # => false + * 1.eql?(Rational(1, 1)) # => false + * 1.eql?(Complex(1, 0)) # => false + * + * \Method +eql?+ is different from +==+ in that +eql?+ requires matching types, + * while +==+ does not. * - * 1 == 1.0 #=> true - * 1.eql?(1.0) #=> false - * 1.0.eql?(1.0) #=> true */ static VALUE @@ -1335,7 +1561,7 @@ num_eql(VALUE x, VALUE y) { if (TYPE(x) != TYPE(y)) return Qfalse; - if (RB_TYPE_P(x, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(x)) { return rb_big_eql(x, y); } @@ -1344,9 +1570,12 @@ num_eql(VALUE x, VALUE y) /* * call-seq: - * number <=> other -> 0 or nil + * self <=> other -> zero or nil + * + * Returns zero if +self+ is the same as +other+, +nil+ otherwise. + * + * No subclass in the Ruby Core or Standard Library uses this implementation. * - * Returns zero if +number+ equals +other+, otherwise returns +nil+. */ static VALUE @@ -1362,21 +1591,24 @@ num_equal(VALUE x, VALUE y) VALUE result; if (x == y) return Qtrue; result = num_funcall1(y, id_eq, x); - if (RTEST(result)) return Qtrue; - return Qfalse; + return RBOOL(RTEST(result)); } /* * call-seq: - * float == obj -> true or false + * self == other -> true or false * - * Returns +true+ only if +obj+ has the same value as +float+. - * Contrast this with Float#eql?, which requires +obj+ to be a Float. + * Returns +true+ if +other+ has the same value as +self+, +false+ otherwise: * - * 1.0 == 1 #=> true + * 2.0 == 2 # => true + * 2.0 == 2.0 # => true + * 2.0 == Rational(2, 1) # => true + * 2.0 == Complex(2, 0) # => true + * + * Float::NAN == Float::NAN returns an implementation-dependent value. + * + * Related: Float#eql? (requires +other+ to be a \Float). * - * The result of NaN == NaN is undefined, - * so an implementation-dependent value is returned. */ MJIT_FUNC_EXPORTED VALUE @@ -1384,12 +1616,12 @@ rb_float_equal(VALUE x, VALUE y) { volatile double a, b; - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_INTEGER_TYPE_P(y)) { return rb_integer_float_eq(y, x); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(b)) return Qfalse; #endif } @@ -1397,10 +1629,10 @@ rb_float_equal(VALUE x, VALUE y) return num_equal(x, y); } a = RFLOAT_VALUE(x); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a)) return Qfalse; #endif - return (a == b)?Qtrue:Qfalse; + return RBOOL(a == b); } #define flo_eq rb_float_equal @@ -1408,9 +1640,9 @@ static VALUE rb_dbl_hash(double d); /* * call-seq: - * float.hash -> integer + * hash -> integer * - * Returns a hash code for this float. + * Returns the integer hash value for +self+. * * See also Object#hash. */ @@ -1424,7 +1656,7 @@ flo_hash(VALUE num) static VALUE rb_dbl_hash(double d) { - return LONG2FIX(rb_dbl_long_hash(d)); + return ST2FIX(rb_dbl_long_hash(d)); } VALUE @@ -1439,16 +1671,30 @@ rb_dbl_cmp(double a, double b) /* * call-seq: - * float <=> real -> -1, 0, +1, or nil + * self <=> other -> -1, 0, +1, or nil + * + * Returns a value that depends on the numeric relation + * between +self+ and +other+: + * + * - -1, if +self+ is less than +other+. + * - 0, if +self+ is equal to +other+. + * - 1, if +self+ is greater than +other+. + * - +nil+, if the two values are incommensurate. + * + * Examples: + * + * 2.0 <=> 2 # => 0 + 2.0 <=> 2.0 # => 0 + 2.0 <=> Rational(2, 1) # => 0 + 2.0 <=> Complex(2, 0) # => 0 + 2.0 <=> 1.9 # => 1 + 2.0 <=> 2.1 # => -1 + 2.0 <=> 'foo' # => nil * - * Returns -1, 0, or +1 depending on whether +float+ is - * less than, equal to, or greater than +real+. * This is the basis for the tests in the Comparable module. * - * The result of NaN <=> NaN is undefined, - * so an implementation-dependent value is returned. + * Float::NAN <=> Float::NAN returns an implementation-dependent value. * - * +nil+ is returned if the two values are incomparable. */ static VALUE @@ -1459,13 +1705,13 @@ flo_cmp(VALUE x, VALUE y) a = RFLOAT_VALUE(x); if (isnan(a)) return Qnil; - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_INTEGER_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(y, x); if (FIXNUM_P(rel)) return LONG2FIX(-FIX2LONG(rel)); return rel; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); } else { @@ -1486,17 +1732,22 @@ flo_cmp(VALUE x, VALUE y) MJIT_FUNC_EXPORTED int rb_float_cmp(VALUE x, VALUE y) { - return NUM2INT(flo_cmp(x, y)); + return NUM2INT(ensure_cmp(flo_cmp(x, y), x, y)); } /* - * call-seq: - * float > real -> true or false + * call-seq: + * self > other -> true or false * - * Returns +true+ if +float+ is greater than +real+. + * Returns +true+ if +self+ is numerically greater than +other+: + * + * 2.0 > 1 # => true + * 2.0 > 1.0 # => true + * 2.0 > Rational(1, 2) # => true + * 2.0 > 2.0 # => false + * + * Float::NAN > Float::NAN returns an implementation-dependent value. * - * The result of NaN > NaN is undefined, - * so an implementation-dependent value is returned. */ VALUE @@ -1505,35 +1756,41 @@ rb_float_gt(VALUE x, VALUE y) double a, b; a = RFLOAT_VALUE(x); - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_INTEGER_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(y, x); if (FIXNUM_P(rel)) - return -FIX2LONG(rel) > 0 ? Qtrue : Qfalse; + return RBOOL(-FIX2LONG(rel) > 0); return Qfalse; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(b)) return Qfalse; #endif } else { return rb_num_coerce_relop(x, y, '>'); } -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a)) return Qfalse; #endif - return (a > b)?Qtrue:Qfalse; + return RBOOL(a > b); } /* - * call-seq: - * float >= real -> true or false + * call-seq: + * self >= other -> true or false * - * Returns +true+ if +float+ is greater than or equal to +real+. + * Returns +true+ if +self+ is numerically greater than or equal to +other+: + * + * 2.0 >= 1 # => true + * 2.0 >= 1.0 # => true + * 2.0 >= Rational(1, 2) # => true + * 2.0 >= 2.0 # => true + * 2.0 >= 2.1 # => false + * + * Float::NAN >= Float::NAN returns an implementation-dependent value. * - * The result of NaN >= NaN is undefined, - * so an implementation-dependent value is returned. */ static VALUE @@ -1542,35 +1799,40 @@ flo_ge(VALUE x, VALUE y) double a, b; a = RFLOAT_VALUE(x); - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_TYPE_P(y, T_FIXNUM) || RB_BIGNUM_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(y, x); if (FIXNUM_P(rel)) - return -FIX2LONG(rel) >= 0 ? Qtrue : Qfalse; + return RBOOL(-FIX2LONG(rel) >= 0); return Qfalse; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(b)) return Qfalse; #endif } else { return rb_num_coerce_relop(x, y, idGE); } -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a)) return Qfalse; #endif - return (a >= b)?Qtrue:Qfalse; + return RBOOL(a >= b); } /* - * call-seq: - * float < real -> true or false + * call-seq: + * self < other -> true or false * - * Returns +true+ if +float+ is less than +real+. + * Returns +true+ if +self+ is numerically less than +other+: + * + * 2.0 < 3 # => true + * 2.0 < 3.0 # => true + * 2.0 < Rational(3, 1) # => true + * 2.0 < 2.0 # => false + * + * Float::NAN < Float::NAN returns an implementation-dependent value. * - * The result of NaN < NaN is undefined, - * so an implementation-dependent value is returned. */ static VALUE @@ -1579,35 +1841,41 @@ flo_lt(VALUE x, VALUE y) double a, b; a = RFLOAT_VALUE(x); - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_INTEGER_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(y, x); if (FIXNUM_P(rel)) - return -FIX2LONG(rel) < 0 ? Qtrue : Qfalse; + return RBOOL(-FIX2LONG(rel) < 0); return Qfalse; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(b)) return Qfalse; #endif } else { return rb_num_coerce_relop(x, y, '<'); } -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a)) return Qfalse; #endif - return (a < b)?Qtrue:Qfalse; + return RBOOL(a < b); } /* - * call-seq: - * float <= real -> true or false + * call-seq: + * self <= other -> true or false * - * Returns +true+ if +float+ is less than or equal to +real+. + * Returns +true+ if +self+ is numerically less than or equal to +other+: + * + * 2.0 <= 3 # => true + * 2.0 <= 3.0 # => true + * 2.0 <= Rational(3, 1) # => true + * 2.0 <= 2.0 # => true + * 2.0 <= 1.0 # => false + * + * Float::NAN <= Float::NAN returns an implementation-dependent value. * - * The result of NaN <= NaN is undefined, - * so an implementation-dependent value is returned. */ static VALUE @@ -1616,154 +1884,139 @@ flo_le(VALUE x, VALUE y) double a, b; a = RFLOAT_VALUE(x); - if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) { + if (RB_INTEGER_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(y, x); if (FIXNUM_P(rel)) - return -FIX2LONG(rel) <= 0 ? Qtrue : Qfalse; + return RBOOL(-FIX2LONG(rel) <= 0); return Qfalse; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(b)) return Qfalse; #endif } else { return rb_num_coerce_relop(x, y, idLE); } -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a)) return Qfalse; #endif - return (a <= b)?Qtrue:Qfalse; + return RBOOL(a <= b); } /* * call-seq: - * float.eql?(obj) -> true or false + * eql?(other) -> true or false * - * Returns +true+ only if +obj+ is a Float with the same value as +float+. - * Contrast this with Float#==, which performs type conversions. + * Returns +true+ if +other+ is a \Float with the same value as +self+, + * +false+ otherwise: * - * 1.0.eql?(1) #=> false + * 2.0.eql?(2.0) # => true + * 2.0.eql?(1.0) # => false + * 2.0.eql?(1) # => false + * 2.0.eql?(Rational(2, 1)) # => false + * 2.0.eql?(Complex(2, 0)) # => false * - * The result of NaN.eql?(NaN) is undefined, - * so an implementation-dependent value is returned. + * Float::NAN.eql?(Float::NAN) returns an implementation-dependent value. + * + * Related: Float#== (performs type conversions). */ MJIT_FUNC_EXPORTED VALUE rb_float_eql(VALUE x, VALUE y) { - if (RB_TYPE_P(y, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(y)) { double a = RFLOAT_VALUE(x); double b = RFLOAT_VALUE(y); -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) if (isnan(a) || isnan(b)) return Qfalse; #endif - if (a == b) - return Qtrue; + return RBOOL(a == b); } return Qfalse; } #define flo_eql rb_float_eql +MJIT_FUNC_EXPORTED VALUE +rb_float_abs(VALUE flt) +{ + double val = fabs(RFLOAT_VALUE(flt)); + return DBL2NUM(val); +} + /* - * call-seq: - * float.to_f -> self + * call-seq: + * nan? -> true or false * - * Since +float+ is already a Float, returns +self+. + * Returns +true+ if +self+ is a NaN, +false+ otherwise. + * + * f = -1.0 #=> -1.0 + * f.nan? #=> false + * f = 0.0/0.0 #=> NaN + * f.nan? #=> true */ static VALUE -flo_to_f(VALUE num) +flo_is_nan_p(VALUE num) { - return num; + double value = RFLOAT_VALUE(num); + + return RBOOL(isnan(value)); } /* * call-seq: - * float.abs -> float - * float.magnitude -> float + * infinite? -> -1, 1, or nil + * + * Returns: * - * Returns the absolute value of +float+. + * - 1, if +self+ is Infinity. + * - -1 if +self+ is -Infinity. + * - +nil+, otherwise. * - * (-34.56).abs #=> 34.56 - * -34.56.abs #=> 34.56 - * 34.56.abs #=> 34.56 + * Examples: + * + * f = 1.0/0.0 # => Infinity + * f.infinite? # => 1 + * f = -1.0/0.0 # => -Infinity + * f.infinite? # => -1 + * f = 1.0 # => 1.0 + * f.infinite? # => nil + * f = 0.0/0.0 # => NaN + * f.infinite? # => nil * - * Float#magnitude is an alias for Float#abs. */ VALUE -rb_float_abs(VALUE flt) +rb_flo_is_infinite_p(VALUE num) { - double val = fabs(RFLOAT_VALUE(flt)); - return DBL2NUM(val); + double value = RFLOAT_VALUE(num); + + if (isinf(value)) { + return INT2FIX( value < 0 ? -1 : 1 ); + } + + return Qnil; } /* * call-seq: - * float.zero? -> true or false + * finite? -> true or false + * + * Returns +true+ if +self+ is not +Infinity+, +-Infinity+, or +Nan+, + * +false+ otherwise: + * + * f = 2.0 # => 2.0 + * f.finite? # => true + * f = 1.0/0.0 # => Infinity + * f.finite? # => false + * f = -1.0/0.0 # => -Infinity + * f.finite? # => false + * f = 0.0/0.0 # => NaN + * f.finite? # => false * - * Returns +true+ if +float+ is 0.0. - */ - -static VALUE -flo_zero_p(VALUE num) -{ - return flo_iszero(num) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * float.nan? -> true or false - * - * Returns +true+ if +float+ is an invalid IEEE floating point number. - * - * a = -1.0 #=> -1.0 - * a.nan? #=> false - * a = 0.0/0.0 #=> NaN - * a.nan? #=> true - */ - -static VALUE -flo_is_nan_p(VALUE num) -{ - double value = RFLOAT_VALUE(num); - - return isnan(value) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * float.infinite? -> -1, 1, or nil - * - * Returns +nil+, -1, or 1 depending on whether the value is - * finite, -Infinity, or +Infinity. - * - * (0.0).infinite? #=> nil - * (-1.0/0.0).infinite? #=> -1 - * (+1.0/0.0).infinite? #=> 1 - */ - -VALUE -rb_flo_is_infinite_p(VALUE num) -{ - double value = RFLOAT_VALUE(num); - - if (isinf(value)) { - return INT2FIX( value < 0 ? -1 : 1 ); - } - - return Qnil; -} - -/* - * call-seq: - * float.finite? -> true or false - * - * Returns +true+ if +float+ is a valid IEEE floating point number, - * i.e. it is not infinite and Float#nan? is +false+. */ VALUE @@ -1771,190 +2024,130 @@ rb_flo_is_finite_p(VALUE num) { double value = RFLOAT_VALUE(num); -#ifdef HAVE_ISFINITE - if (!isfinite(value)) - return Qfalse; -#else - if (isinf(value) || isnan(value)) - return Qfalse; -#endif - - return Qtrue; + return RBOOL(isfinite(value)); } -/* - * call-seq: - * float.next_float -> float - * - * Returns the next representable floating point number. - * - * Float::MAX.next_float and Float::INFINITY.next_float is Float::INFINITY. - * - * Float::NAN.next_float is Float::NAN. - * - * For example: - * - * 0.01.next_float #=> 0.010000000000000002 - * 1.0.next_float #=> 1.0000000000000002 - * 100.0.next_float #=> 100.00000000000001 - * - * 0.01.next_float - 0.01 #=> 1.734723475976807e-18 - * 1.0.next_float - 1.0 #=> 2.220446049250313e-16 - * 100.0.next_float - 100.0 #=> 1.4210854715202004e-14 - * - * f = 0.01; 20.times { printf "%-20a %s\n", f, f.to_s; f = f.next_float } - * #=> 0x1.47ae147ae147bp-7 0.01 - * # 0x1.47ae147ae147cp-7 0.010000000000000002 - * # 0x1.47ae147ae147dp-7 0.010000000000000004 - * # 0x1.47ae147ae147ep-7 0.010000000000000005 - * # 0x1.47ae147ae147fp-7 0.010000000000000007 - * # 0x1.47ae147ae148p-7 0.010000000000000009 - * # 0x1.47ae147ae1481p-7 0.01000000000000001 - * # 0x1.47ae147ae1482p-7 0.010000000000000012 - * # 0x1.47ae147ae1483p-7 0.010000000000000014 - * # 0x1.47ae147ae1484p-7 0.010000000000000016 - * # 0x1.47ae147ae1485p-7 0.010000000000000018 - * # 0x1.47ae147ae1486p-7 0.01000000000000002 - * # 0x1.47ae147ae1487p-7 0.010000000000000021 - * # 0x1.47ae147ae1488p-7 0.010000000000000023 - * # 0x1.47ae147ae1489p-7 0.010000000000000024 - * # 0x1.47ae147ae148ap-7 0.010000000000000026 - * # 0x1.47ae147ae148bp-7 0.010000000000000028 - * # 0x1.47ae147ae148cp-7 0.01000000000000003 - * # 0x1.47ae147ae148dp-7 0.010000000000000031 - * # 0x1.47ae147ae148ep-7 0.010000000000000033 - * - * f = 0.0 - * 100.times { f += 0.1 } - * f #=> 9.99999999999998 # should be 10.0 in the ideal world. - * 10-f #=> 1.9539925233402755e-14 # the floating point error. - * 10.0.next_float-10 #=> 1.7763568394002505e-15 # 1 ulp (unit in the last place). - * (10-f)/(10.0.next_float-10) #=> 11.0 # the error is 11 ulp. - * (10-f)/(10*Float::EPSILON) #=> 8.8 # approximation of the above. - * "%a" % 10 #=> "0x1.4p+3" - * "%a" % f #=> "0x1.3fffffffffff5p+3" # the last hex digit is 5. 16 - 5 = 11 ulp. - */ static VALUE -flo_next_float(VALUE vx) +flo_nextafter(VALUE flo, double value) { double x, y; - x = NUM2DBL(vx); - y = nextafter(x, HUGE_VAL); + x = NUM2DBL(flo); + y = nextafter(x, value); return DBL2NUM(y); } /* * call-seq: - * float.prev_float -> float + * next_float -> float + * + * Returns the next-larger representable \Float. + * + * These examples show the internally stored values (64-bit hexadecimal) + * for each \Float +f+ and for the corresponding f.next_float: + * + * f = 0.0 # 0x0000000000000000 + * f.next_float # 0x0000000000000001 + * + * f = 0.01 # 0x3f847ae147ae147b + * f.next_float # 0x3f847ae147ae147c + * + * In the remaining examples here, the output is shown in the usual way + * (result +to_s+): + * + * 0.01.next_float # => 0.010000000000000002 + * 1.0.next_float # => 1.0000000000000002 + * 100.0.next_float # => 100.00000000000001 + * + * f = 0.01 + * (0..3).each_with_index {|i| printf "%2d %-20a %s\n", i, f, f.to_s; f = f.next_float } + * + * Output: + * + * 0 0x1.47ae147ae147bp-7 0.01 + * 1 0x1.47ae147ae147cp-7 0.010000000000000002 + * 2 0x1.47ae147ae147dp-7 0.010000000000000004 + * 3 0x1.47ae147ae147ep-7 0.010000000000000005 + * + * f = 0.0; 100.times { f += 0.1 } + * f # => 9.99999999999998 # should be 10.0 in the ideal world. + * 10-f # => 1.9539925233402755e-14 # the floating point error. + * 10.0.next_float-10 # => 1.7763568394002505e-15 # 1 ulp (unit in the last place). + * (10-f)/(10.0.next_float-10) # => 11.0 # the error is 11 ulp. + * (10-f)/(10*Float::EPSILON) # => 8.8 # approximation of the above. + * "%a" % 10 # => "0x1.4p+3" + * "%a" % f # => "0x1.3fffffffffff5p+3" # the last hex digit is 5. 16 - 5 = 11 ulp. + * + * Related: Float#prev_float * - * Returns the previous representable floating point number. - * - * (-Float::MAX).prev_float and (-Float::INFINITY).prev_float is -Float::INFINITY. - * - * Float::NAN.prev_float is Float::NAN. - * - * For example: - * - * 0.01.prev_float #=> 0.009999999999999998 - * 1.0.prev_float #=> 0.9999999999999999 - * 100.0.prev_float #=> 99.99999999999999 - * - * 0.01 - 0.01.prev_float #=> 1.734723475976807e-18 - * 1.0 - 1.0.prev_float #=> 1.1102230246251565e-16 - * 100.0 - 100.0.prev_float #=> 1.4210854715202004e-14 - * - * f = 0.01; 20.times { printf "%-20a %s\n", f, f.to_s; f = f.prev_float } - * #=> 0x1.47ae147ae147bp-7 0.01 - * # 0x1.47ae147ae147ap-7 0.009999999999999998 - * # 0x1.47ae147ae1479p-7 0.009999999999999997 - * # 0x1.47ae147ae1478p-7 0.009999999999999995 - * # 0x1.47ae147ae1477p-7 0.009999999999999993 - * # 0x1.47ae147ae1476p-7 0.009999999999999992 - * # 0x1.47ae147ae1475p-7 0.00999999999999999 - * # 0x1.47ae147ae1474p-7 0.009999999999999988 - * # 0x1.47ae147ae1473p-7 0.009999999999999986 - * # 0x1.47ae147ae1472p-7 0.009999999999999985 - * # 0x1.47ae147ae1471p-7 0.009999999999999983 - * # 0x1.47ae147ae147p-7 0.009999999999999981 - * # 0x1.47ae147ae146fp-7 0.00999999999999998 - * # 0x1.47ae147ae146ep-7 0.009999999999999978 - * # 0x1.47ae147ae146dp-7 0.009999999999999976 - * # 0x1.47ae147ae146cp-7 0.009999999999999974 - * # 0x1.47ae147ae146bp-7 0.009999999999999972 - * # 0x1.47ae147ae146ap-7 0.00999999999999997 - * # 0x1.47ae147ae1469p-7 0.009999999999999969 - * # 0x1.47ae147ae1468p-7 0.009999999999999967 */ static VALUE -flo_prev_float(VALUE vx) +flo_next_float(VALUE vx) { - double x, y; - x = NUM2DBL(vx); - y = nextafter(x, -HUGE_VAL); - return DBL2NUM(y); + return flo_nextafter(vx, HUGE_VAL); } /* * call-seq: - * float.floor([ndigits]) -> integer or float + * float.prev_float -> float * - * Returns the largest number less than or equal to +float+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the next-smaller representable \Float. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. - * - * Returns a floating point number when +ndigits+ is positive, - * otherwise returns an integer. - * - * 1.2.floor #=> 1 - * 2.0.floor #=> 2 - * (-1.2).floor #=> -2 - * (-2.0).floor #=> -2 - * - * 1.234567.floor(2) #=> 1.23 - * 1.234567.floor(3) #=> 1.234 - * 1.234567.floor(4) #=> 1.2345 - * 1.234567.floor(5) #=> 1.23456 - * - * 34567.89.floor(-5) #=> 0 - * 34567.89.floor(-4) #=> 30000 - * 34567.89.floor(-3) #=> 34000 - * 34567.89.floor(-2) #=> 34500 - * 34567.89.floor(-1) #=> 34560 - * 34567.89.floor(0) #=> 34567 - * 34567.89.floor(1) #=> 34567.8 - * 34567.89.floor(2) #=> 34567.89 - * 34567.89.floor(3) #=> 34567.89 - * - * Note that the limited precision of floating point arithmetic - * might lead to surprising results: + * These examples show the internally stored values (64-bit hexadecimal) + * for each \Float +f+ and for the corresponding f.pev_float: + * + * f = 5e-324 # 0x0000000000000001 + * f.prev_float # 0x0000000000000000 + * + * f = 0.01 # 0x3f847ae147ae147b + * f.prev_float # 0x3f847ae147ae147a + * + * In the remaining examples here, the output is shown in the usual way + * (result +to_s+): + * + * 0.01.prev_float # => 0.009999999999999998 + * 1.0.prev_float # => 0.9999999999999999 + * 100.0.prev_float # => 99.99999999999999 + * + * f = 0.01 + * (0..3).each_with_index {|i| printf "%2d %-20a %s\n", i, f, f.to_s; f = f.prev_float } + * + * Output: + * + * 0 0x1.47ae147ae147bp-7 0.01 + * 1 0x1.47ae147ae147ap-7 0.009999999999999998 + * 2 0x1.47ae147ae1479p-7 0.009999999999999997 + * 3 0x1.47ae147ae1478p-7 0.009999999999999995 + * + * Related: Float#next_float. * - * (0.3 / 0.1).floor #=> 2 (!) */ - static VALUE -flo_floor(int argc, VALUE *argv, VALUE num) +flo_prev_float(VALUE vx) { - double number, f; - int ndigits = 0; + return flo_nextafter(vx, -HUGE_VAL); +} - if (rb_check_arity(argc, 0, 1)) { - ndigits = NUM2INT(argv[0]); - } +VALUE +rb_float_floor(VALUE num, int ndigits) +{ + double number; number = RFLOAT_VALUE(num); if (number == 0.0) { return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0); } if (ndigits > 0) { int binexp; + double f, mul, res; frexp(number, &binexp); if (float_round_overflow(ndigits, binexp)) return num; if (number > 0.0 && float_round_underflow(ndigits, binexp)) return DBL2NUM(0.0); f = pow(10, ndigits); - f = floor(number * f) / f; - return DBL2NUM(f); + mul = floor(number * f); + res = (mul + 1) / f; + if (res > number) + res = mul / f; + return DBL2NUM(res); } else { num = dbl2ival(floor(number)); @@ -1963,53 +2156,98 @@ flo_floor(int argc, VALUE *argv, VALUE num) } } +static int +flo_ndigits(int argc, VALUE *argv) +{ + if (rb_check_arity(argc, 0, 1)) { + return NUM2INT(argv[0]); + } + return 0; +} + /* * call-seq: - * float.ceil([ndigits]) -> integer or float + * floor(ndigits = 0) -> float or integer * - * Returns the smallest number greater than or equal to +float+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the largest number less than or equal to +self+ with + * a precision of +ndigits+ decimal digits. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. - * - * Returns a floating point number when +ndigits+ is positive, - * otherwise returns an integer. - * - * 1.2.ceil #=> 2 - * 2.0.ceil #=> 2 - * (-1.2).ceil #=> -1 - * (-2.0).ceil #=> -2 - * - * 1.234567.ceil(2) #=> 1.24 - * 1.234567.ceil(3) #=> 1.235 - * 1.234567.ceil(4) #=> 1.2346 - * 1.234567.ceil(5) #=> 1.23457 - * - * 34567.89.ceil(-5) #=> 100000 - * 34567.89.ceil(-4) #=> 40000 - * 34567.89.ceil(-3) #=> 35000 - * 34567.89.ceil(-2) #=> 34600 - * 34567.89.ceil(-1) #=> 34570 - * 34567.89.ceil(0) #=> 34568 - * 34567.89.ceil(1) #=> 34567.9 - * 34567.89.ceil(2) #=> 34567.89 - * 34567.89.ceil(3) #=> 34567.89 - * - * Note that the limited precision of floating point arithmetic - * might lead to surprising results: + * When +ndigits+ is positive, returns a float with +ndigits+ + * digits after the decimal point (as available): + * + * f = 12345.6789 + * f.floor(1) # => 12345.6 + * f.floor(3) # => 12345.678 + * f = -12345.6789 + * f.floor(1) # => -12345.7 + * f.floor(3) # => -12345.679 + * + * When +ndigits+ is non-positive, returns an integer with at least + * ndigits.abs trailing zeros: + * + * f = 12345.6789 + * f.floor(0) # => 12345 + * f.floor(-3) # => 12000 + * f = -12345.6789 + * f.floor(0) # => -12346 + * f.floor(-3) # => -13000 + * + * Note that the limited precision of floating-point arithmetic + * may lead to surprising results: + * + * (0.3 / 0.1).floor #=> 2 (!) + * + * Related: Float#ceil. + * + */ + +static VALUE +flo_floor(int argc, VALUE *argv, VALUE num) +{ + int ndigits = flo_ndigits(argc, argv); + return rb_float_floor(num, ndigits); +} + +/* + * call-seq: + * ceil(ndigits = 0) -> float or integer + * + * Returns the smallest number greater than or equal to +self+ with + * a precision of +ndigits+ decimal digits. + * + * When +ndigits+ is positive, returns a float with +ndigits+ + * digits after the decimal point (as available): + * + * f = 12345.6789 + * f.ceil(1) # => 12345.7 + * f.ceil(3) # => 12345.679 + * f = -12345.6789 + * f.ceil(1) # => -12345.6 + * f.ceil(3) # => -12345.678 + * + * When +ndigits+ is non-positive, returns an integer with at least + * ndigits.abs trailing zeros: + * + * f = 12345.6789 + * f.ceil(0) # => 12346 + * f.ceil(-3) # => 13000 + * f = -12345.6789 + * f.ceil(0) # => -12345 + * f.ceil(-3) # => -12000 + * + * Note that the limited precision of floating-point arithmetic + * may lead to surprising results: * * (2.1 / 0.7).ceil #=> 4 (!) + * + * Related: Float#floor. + * */ static VALUE flo_ceil(int argc, VALUE *argv, VALUE num) { - int ndigits = 0; - - if (rb_check_arity(argc, 0, 1)) { - ndigits = NUM2INT(argv[0]); - } + int ndigits = flo_ndigits(argc, argv); return rb_float_ceil(num, ndigits); } @@ -2048,7 +2286,7 @@ int_round_zero_p(VALUE num, int ndigits) if (FIXNUM_P(num)) { bytes = sizeof(long); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { bytes = rb_big_size(num); } else { @@ -2118,7 +2356,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode) if (neg) x = -x; return LONG2NUM(x); } - if (RB_TYPE_P(f, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(f)) { /* then int_pow overflow */ return INT2FIX(0); } @@ -2133,7 +2371,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode) return n; } -VALUE +static VALUE rb_int_floor(VALUE num, int ndigits) { VALUE f; @@ -2149,14 +2387,14 @@ rb_int_floor(VALUE num, int ndigits) if (neg) x = -x; return LONG2NUM(x); } - if (RB_TYPE_P(f, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(f)) { /* then int_pow overflow */ return INT2FIX(0); } return rb_int_minus(num, rb_int_modulo(num, f)); } -VALUE +static VALUE rb_int_ceil(VALUE num, int ndigits) { VALUE f; @@ -2173,7 +2411,7 @@ rb_int_ceil(VALUE num, int ndigits) if (neg) x = -x; return LONG2NUM(x); } - if (RB_TYPE_P(f, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(f)) { /* then int_pow overflow */ return INT2FIX(0); } @@ -2197,7 +2435,7 @@ rb_int_truncate(VALUE num, int ndigits) if (neg) x = -x; return LONG2NUM(x); } - if (RB_TYPE_P(f, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(f)) { /* then int_pow overflow */ return INT2FIX(0); } @@ -2212,54 +2450,57 @@ rb_int_truncate(VALUE num, int ndigits) /* * call-seq: - * float.round([ndigits] [, half: mode]) -> integer or float + * round(ndigits = 0, half: :up]) -> integer or float * - * Returns +float+ rounded to the nearest value with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ rounded to the nearest value with + * a precision of +ndigits+ decimal digits. + * + * When +ndigits+ is non-negative, returns a float with +ndigits+ + * after the decimal point (as available): + * + * f = 12345.6789 + * f.round(1) # => 12345.7 + * f.round(3) # => 12345.679 + * f = -12345.6789 + * f.round(1) # => -12345.7 + * f.round(3) # => -12345.679 + * + * When +ndigits+ is negative, returns an integer + * with at least ndigits.abs trailing zeros: + * + * f = 12345.6789 + * f.round(0) # => 12346 + * f.round(-3) # => 12000 + * f = -12345.6789 + * f.round(0) # => -12346 + * f.round(-3) # => -12000 + * + * If keyword argument +half+ is given, + * and +self+ is equidistant from the two candidate values, + * the rounding is according to the given +half+ value: + * + * - +:up+ or +nil+: round away from zero: + * + * 2.5.round(half: :up) # => 3 + * 3.5.round(half: :up) # => 4 + * (-2.5).round(half: :up) # => -3 + * + * - +:down+: round toward zero: + * + * 2.5.round(half: :down) # => 2 + * 3.5.round(half: :down) # => 3 + * (-2.5).round(half: :down) # => -2 + * + * - +:even+: round toward the candidate whose last nonzero digit is even: + * + * 2.5.round(half: :even) # => 2 + * 3.5.round(half: :even) # => 4 + * (-2.5).round(half: :even) # => -2 + * + * Raises and exception if the value for +half+ is invalid. + * + * Related: Float#truncate. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. - * - * Returns a floating point number when +ndigits+ is positive, - * otherwise returns an integer. - * - * 1.4.round #=> 1 - * 1.5.round #=> 2 - * 1.6.round #=> 2 - * (-1.5).round #=> -2 - * - * 1.234567.round(2) #=> 1.23 - * 1.234567.round(3) #=> 1.235 - * 1.234567.round(4) #=> 1.2346 - * 1.234567.round(5) #=> 1.23457 - * - * 34567.89.round(-5) #=> 0 - * 34567.89.round(-4) #=> 30000 - * 34567.89.round(-3) #=> 35000 - * 34567.89.round(-2) #=> 34600 - * 34567.89.round(-1) #=> 34570 - * 34567.89.round(0) #=> 34568 - * 34567.89.round(1) #=> 34567.9 - * 34567.89.round(2) #=> 34567.89 - * 34567.89.round(3) #=> 34567.89 - * - * If the optional +half+ keyword argument is given, - * numbers that are half-way between two possible rounded values - * will be rounded according to the specified tie-breaking +mode+: - * - * * :up or +nil+: round half away from zero (default) - * * :down: round half toward zero - * * :even: round half toward the nearest even number - * - * 2.5.round(half: :up) #=> 3 - * 2.5.round(half: :down) #=> 2 - * 2.5.round(half: :even) #=> 2 - * 3.5.round(half: :up) #=> 4 - * 3.5.round(half: :down) #=> 3 - * 3.5.round(half: :even) #=> 4 - * (-2.5).round(half: :up) #=> -3 - * (-2.5).round(half: :down) #=> -2 - * (-2.5).round(half: :even) #=> -2 */ static VALUE @@ -2290,6 +2531,10 @@ flo_round(int argc, VALUE *argv, VALUE num) frexp(number, &binexp); if (float_round_overflow(ndigits, binexp)) return num; if (float_round_underflow(ndigits, binexp)) return DBL2NUM(0); + if (ndigits > 14) { + /* In this case, pow(10, ndigits) may not be accurate. */ + return rb_flo_round_by_rational(argc, argv, num); + } f = pow(10, ndigits); x = ROUND_CALL(mode, round, (number, f)); return DBL2NUM(x / f); @@ -2336,20 +2581,19 @@ float_round_underflow(int ndigits, int binexp) /* * call-seq: - * float.to_i -> integer - * float.to_int -> integer + * to_i -> integer * - * Returns the +float+ truncated to an Integer. + * Returns +self+ truncated to an Integer. * - * 1.2.to_i #=> 1 - * (-1.2).to_i #=> -1 + * 1.2.to_i # => 1 + * (-1.2).to_i # => -1 * - * Note that the limited precision of floating point arithmetic - * might lead to surprising results: + * Note that the limited precision of floating-point arithmetic + * may lead to surprising results: * - * (0.3 / 0.1).to_i #=> 2 (!) + * (0.3 / 0.1).to_i # => 2 (!) * - * #to_int is an alias for #to_i. + * Float#to_int is an alias for Float#to_i. */ static VALUE @@ -2365,26 +2609,38 @@ flo_to_i(VALUE num) /* * call-seq: - * float.truncate([ndigits]) -> integer or float + * truncate(ndigits = 0) -> float or integer * - * Returns +float+ truncated (toward zero) to - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ truncated (toward zero) to + * a precision of +ndigits+ decimal digits. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. + * When +ndigits+ is positive, returns a float with +ndigits+ digits + * after the decimal point (as available): * - * Returns a floating point number when +ndigits+ is positive, - * otherwise returns an integer. + * f = 12345.6789 + * f.truncate(1) # => 12345.6 + * f.truncate(3) # => 12345.678 + * f = -12345.6789 + * f.truncate(1) # => -12345.6 + * f.truncate(3) # => -12345.678 * - * 2.8.truncate #=> 2 - * (-2.8).truncate #=> -2 - * 1.234567.truncate(2) #=> 1.23 - * 34567.89.truncate(-2) #=> 34500 + * When +ndigits+ is negative, returns an integer + * with at least ndigits.abs trailing zeros: * - * Note that the limited precision of floating point arithmetic - * might lead to surprising results: + * f = 12345.6789 + * f.truncate(0) # => 12345 + * f.truncate(-3) # => 12000 + * f = -12345.6789 + * f.truncate(0) # => -12345 + * f.truncate(-3) # => -12000 + * + * Note that the limited precision of floating-point arithmetic + * may lead to surprising results: * * (0.3 / 0.1).truncate #=> 2 (!) + * + * Related: Float#round. + * */ static VALUE flo_truncate(int argc, VALUE *argv, VALUE num) @@ -2397,40 +2653,12 @@ flo_truncate(int argc, VALUE *argv, VALUE num) /* * call-seq: - * float.positive? -> true or false - * - * Returns +true+ if +float+ is greater than 0. - */ - -static VALUE -flo_positive_p(VALUE num) -{ - double f = RFLOAT_VALUE(num); - return f > 0.0 ? Qtrue : Qfalse; -} - -/* - * call-seq: - * float.negative? -> true or false + * floor(digits = 0) -> integer or float * - * Returns +true+ if +float+ is less than 0. - */ - -static VALUE -flo_negative_p(VALUE num) -{ - double f = RFLOAT_VALUE(num); - return f < 0.0 ? Qtrue : Qfalse; -} - -/* - * call-seq: - * num.floor([ndigits]) -> integer or float - * - * Returns the largest number less than or equal to +num+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the largest number that is less than or equal to +self+ with + * a precision of +digits+ decimal digits. * - * Numeric implements this by converting its value to a Float and + * \Numeric implements this by converting +self+ to a Float and * invoking Float#floor. */ @@ -2442,12 +2670,12 @@ num_floor(int argc, VALUE *argv, VALUE num) /* * call-seq: - * num.ceil([ndigits]) -> integer or float + * ceil(digits = 0) -> integer or float * - * Returns the smallest number greater than or equal to +num+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the smallest number that is greater than or equal to +self+ with + * a precision of +digits+ decimal digits. * - * Numeric implements this by converting its value to a Float and + * \Numeric implements this by converting +self+ to a Float and * invoking Float#ceil. */ @@ -2459,12 +2687,12 @@ num_ceil(int argc, VALUE *argv, VALUE num) /* * call-seq: - * num.round([ndigits]) -> integer or float + * round(digits = 0) -> integer or float * - * Returns +num+ rounded to the nearest value with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ rounded to the nearest value with + * a precision of +digits+ decimal digits. * - * Numeric implements this by converting its value to a Float and + * \Numeric implements this by converting +self+ to a Float and * invoking Float#round. */ @@ -2476,12 +2704,12 @@ num_round(int argc, VALUE* argv, VALUE num) /* * call-seq: - * num.truncate([ndigits]) -> integer or float + * truncate(digits = 0) -> integer or float * - * Returns +num+ truncated (toward zero) to - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ truncated (toward zero) to + * a precision of +digits+ decimal digits. * - * Numeric implements this by converting its value to a Float and + * \Numeric implements this by converting +self+ to a Float and * invoking Float#truncate. */ @@ -2495,16 +2723,16 @@ double ruby_float_step_size(double beg, double end, double unit, int excl) { const double epsilon = DBL_EPSILON; - double n, err; + double d, n, err; if (unit == 0) { return HUGE_VAL; } - n= (end - beg)/unit; - err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; if (isinf(unit)) { return unit > 0 ? beg <= end : beg >= end; } + n= (end - beg)/unit; + err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; if (err>0.5) err=0.5; if (excl) { if (n<=0) return 0; @@ -2512,10 +2740,28 @@ ruby_float_step_size(double beg, double end, double unit, int excl) n = 0; else n = floor(n - err); + d = +((n + 1) * unit) + beg; + if (beg < end) { + if (d < end) + n++; + } + else if (beg > end) { + if (d > end) + n++; + } } else { if (n<0) return 0; n = floor(n + err); + d = +((n + 1) * unit) + beg; + if (beg < end) { + if (d <= end) + n++; + } + else if (beg > end) { + if (d >= end) + n++; + } } return n+1; } @@ -2523,7 +2769,7 @@ ruby_float_step_size(double beg, double end, double unit, int excl) int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless) { - if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) { + if (RB_FLOAT_TYPE_P(from) || RB_FLOAT_TYPE_P(to) || RB_FLOAT_TYPE_P(step)) { double unit = NUM2DBL(step); double beg = NUM2DBL(from); double end = (allow_endless && NIL_P(to)) ? (unit < 0 ? -1 : 1)*HUGE_VAL : NUM2DBL(to); @@ -2574,11 +2820,11 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl) } return ULONG2NUM(delta / diff + 1UL); } - else if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(from) || RB_FLOAT_TYPE_P(to) || RB_FLOAT_TYPE_P(step)) { double n = ruby_float_step_size(NUM2DBL(from), NUM2DBL(to), NUM2DBL(step), excl); if (isinf(n)) return DBL2NUM(n); - if (POSFIXABLE(n)) return LONG2FIX(n); + if (POSFIXABLE(n)) return LONG2FIX((long)n); return rb_dbl2big(n); } else { @@ -2608,7 +2854,7 @@ num_step_negative_p(VALUE num) if (method_basic_p(rb_cInteger)) return (SIGNED_VALUE)num < 0; } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { if (method_basic_p(rb_cInteger)) return BIGNUM_NEGATIVE_P(num); } @@ -2657,9 +2903,9 @@ num_step_check_fix_args(int argc, VALUE *to, VALUE *step, VALUE by, int fix_nil, if (argc > 1 && NIL_P(*step)) { rb_raise(rb_eTypeError, "step must be numeric"); } - if (!allow_zero_step && rb_equal(*step, INT2FIX(0))) { - rb_raise(rb_eArgError, "step can't be 0"); - } + } + if (!allow_zero_step && rb_equal(*step, INT2FIX(0))) { + rb_raise(rb_eArgError, "step can't be 0"); } if (NIL_P(*step)) { *step = INT2FIX(1); @@ -2693,25 +2939,89 @@ num_step_size(VALUE from, VALUE args, VALUE eobj) /* * call-seq: - * num.step(by: step, to: limit) {|i| block } -> self - * num.step(by: step, to: limit) -> an_enumerator - * num.step(by: step, to: limit) -> an_arithmetic_sequence - * num.step(limit=nil, step=1) {|i| block } -> self - * num.step(limit=nil, step=1) -> an_enumerator - * num.step(limit=nil, step=1) -> an_arithmetic_sequence - * - * Invokes the given block with the sequence of numbers starting at +num+, - * incremented by +step+ (defaulted to +1+) on each call. - * - * The loop finishes when the value to be passed to the block is greater than - * +limit+ (if +step+ is positive) or less than +limit+ (if +step+ is - * negative), where +limit+ is defaulted to infinity. - * - * In the recommended keyword argument style, either or both of - * +step+ and +limit+ (default infinity) can be omitted. In the - * fixed position argument style, zero as a step - * (i.e. num.step(limit, 0)) is not allowed for historical - * compatibility reasons. + * step(to = nil, by = 1) {|n| ... } -> self + * step(to = nil, by = 1) -> enumerator + * step(to = nil, by: 1) {|n| ... } -> self + * step(to = nil, by: 1) -> enumerator + * step(by: 1, to: ) {|n| ... } -> self + * step(by: 1, to: ) -> enumerator + * step(by: , to: nil) {|n| ... } -> self + * step(by: , to: nil) -> enumerator + * + * Generates a sequence of numbers; with a block given, traverses the sequence. + * + * Of the Core and Standard Library classes, + * Integer, Float, and Rational use this implementation. + * + * A quick example: + * + * squares = [] + * 1.step(by: 2, to: 10) {|i| squares.push(i*i) } + * squares # => [1, 9, 25, 49, 81] + * + * The generated sequence: + * + * - Begins with +self+. + * - Continues at intervals of +step+ (which may not be zero). + * - Ends with the last number that is within or equal to +limit+; + * that is, less than or equal to +limit+ if +step+ is positive, + * greater than or equal to +limit+ if +step+ is negative. + * If +limit+ is not given, the sequence is of infinite length. + * + * If a block is given, calls the block with each number in the sequence; + * returns +self+. If no block is given, returns an Enumerator::ArithmeticSequence. + * + * Keyword Arguments + * + * With keyword arguments +by+ and +to+, + * their values (or defaults) determine the step and limit: + * + * # Both keywords given. + * squares = [] + * 4.step(by: 2, to: 10) {|i| squares.push(i*i) } # => 4 + * squares # => [16, 36, 64, 100] + * cubes = [] + * 3.step(by: -1.5, to: -3) {|i| cubes.push(i*i*i) } # => 3 + * cubes # => [27.0, 3.375, 0.0, -3.375, -27.0] + * squares = [] + * 1.2.step(by: 0.2, to: 2.0) {|f| squares.push(f*f) } + * squares # => [1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0] + * + * squares = [] + * Rational(6/5).step(by: 0.2, to: 2.0) {|r| squares.push(r*r) } + * squares # => [1.0, 1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0] + * + * # Only keyword to given. + * squares = [] + * 4.step(to: 10) {|i| squares.push(i*i) } # => 4 + * squares # => [16, 25, 36, 49, 64, 81, 100] + * # Only by given. + * + * # Only keyword by given + * squares = [] + * 4.step(by:2) {|i| squares.push(i*i); break if i > 10 } + * squares # => [16, 36, 64, 100, 144] + * + * # No block given. + * e = 3.step(by: -1.5, to: -3) # => (3.step(by: -1.5, to: -3)) + * e.class # => Enumerator::ArithmeticSequence + * + * Positional Arguments + * + * With optional positional arguments +limit+ and +step+, + * their values (or defaults) determine the step and limit: + * + * squares = [] + * 4.step(10, 2) {|i| squares.push(i*i) } # => 4 + * squares # => [16, 36, 64, 100] + * squares = [] + * 4.step(10) {|i| squares.push(i*i) } + * squares # => [16, 25, 36, 49, 64, 81, 100] + * squares = [] + * 4.step {|i| squares.push(i*i); break if i > 10 } # => nil + * squares # => [16, 25, 36, 49, 64, 81, 100, 121] + * + * Implementation Notes * * If all the arguments are integers, the loop operates using an integer * counter. @@ -2719,32 +3029,8 @@ num_step_size(VALUE from, VALUE args, VALUE eobj) * If any of the arguments are floating point numbers, all are converted * to floats, and the loop is executed * floor(n + n*Float::EPSILON) + 1 times, - * where n = (limit - num)/step. - * - * Otherwise, the loop starts at +num+, uses either the - * less-than (<) or greater-than (>) operator - * to compare the counter against +limit+, - * and increments itself using the + operator. - * - * If no block is given, an Enumerator is returned instead. - * Especially, the enumerator is an Enumerator::ArithmeticSequence - * if both +limit+ and +step+ are kind of Numeric or nil. - * - * For example: + * where n = (limit - self)/step. * - * p 1.step.take(4) - * p 10.step(by: -1).take(4) - * 3.step(to: 5) {|i| print i, " " } - * 1.step(10, 2) {|i| print i, " " } - * Math::E.step(to: Math::PI, by: 0.2) {|f| print f, " " } - * - * Will produce: - * - * [1, 2, 3, 4] - * [10, 9, 8, 7] - * 3 4 5 - * 1 3 5 7 9 - * 2.718281828459045 2.9182818284590453 3.118281828459045 */ static VALUE @@ -2763,6 +3049,9 @@ num_step(int argc, VALUE *argv, VALUE from) if (NIL_P(step)) { step = INT2FIX(1); } + else if (rb_equal(step, INT2FIX(0))) { + rb_raise(rb_eArgError, "step can't be 0"); + } if ((NIL_P(to) || rb_obj_is_kind_of(to, rb_cNumeric)) && rb_obj_is_kind_of(step, rb_cNumeric)) { return rb_arith_seq_new(from, ID2SYM(rb_frame_this_func()), argc, argv, @@ -2776,7 +3065,7 @@ num_step(int argc, VALUE *argv, VALUE from) if (rb_equal(step, INT2FIX(0))) { inf = 1; } - else if (RB_TYPE_P(to, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(to)) { double f = RFLOAT_VALUE(to); inf = isinf(f) && (signbit(f) ? desc : !desc); } @@ -2855,7 +3144,7 @@ rb_num2long(VALUE val) if (FIXNUM_P(val)) return FIX2LONG(val); - else if (RB_TYPE_P(val, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(val)) { if (RFLOAT_VALUE(val) < LONG_MAX_PLUS_ONE && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) { return (long)RFLOAT_VALUE(val); @@ -2864,7 +3153,7 @@ rb_num2long(VALUE val) FLOAT_OUT_OF_RANGE(val, "integer"); } } - else if (RB_TYPE_P(val, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(val)) { return rb_big2long(val); } else { @@ -2887,7 +3176,7 @@ rb_num2ulong_internal(VALUE val, int *wrap_p) *wrap_p = l < 0; return (unsigned long)l; } - else if (RB_TYPE_P(val, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(val)) { double d = RFLOAT_VALUE(val); if (d < ULONG_MAX_PLUS_ONE && LONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) { if (wrap_p) @@ -2900,7 +3189,7 @@ rb_num2ulong_internal(VALUE val, int *wrap_p) FLOAT_OUT_OF_RANGE(val, "integer"); } } - else if (RB_TYPE_P(val, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(val)) { { unsigned long ul = rb_big2ulong(val); if (wrap_p) @@ -2920,7 +3209,6 @@ rb_num2ulong(VALUE val) return rb_num2ulong_internal(val, NULL); } -#if SIZEOF_INT < SIZEOF_LONG void rb_out_of_int(SIGNED_VALUE num) { @@ -2928,6 +3216,7 @@ rb_out_of_int(SIGNED_VALUE num) num, num < 0 ? "small" : "big"); } +#if SIZEOF_INT < SIZEOF_LONG static void check_int(long num) { @@ -2989,7 +3278,7 @@ rb_fix2uint(VALUE val) } num = FIX2ULONG(val); - check_uint(num, rb_num_negative_int_p(val)); + check_uint(num, FIXNUM_NEGATIVE_P(val)); return num; } #else @@ -3004,6 +3293,18 @@ rb_fix2int(VALUE val) { return FIX2INT(val); } + +unsigned long +rb_num2uint(VALUE val) +{ + return rb_num2ulong(val); +} + +unsigned long +rb_fix2uint(VALUE val) +{ + return RB_FIX2ULONG(val); +} #endif NORETURN(static void rb_out_of_short(SIGNED_VALUE num)); @@ -3075,7 +3376,7 @@ rb_fix2ushort(VALUE val) } num = FIX2ULONG(val); - check_ushort(num, rb_num_negative_int_p(val)); + check_ushort(num, FIXNUM_NEGATIVE_P(val)); return num; } @@ -3114,7 +3415,7 @@ rb_num2ll(VALUE val) if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val); - else if (RB_TYPE_P(val, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(val)) { double d = RFLOAT_VALUE(val); if (d < LLONG_MAX_PLUS_ONE && (LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d))) { return (LONG_LONG)d; @@ -3123,7 +3424,7 @@ rb_num2ll(VALUE val) FLOAT_OUT_OF_RANGE(val, "long long"); } } - else if (RB_TYPE_P(val, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(val)) { return rb_big2ll(val); } else if (RB_TYPE_P(val, T_STRING)) { @@ -3140,13 +3441,13 @@ rb_num2ll(VALUE val) unsigned LONG_LONG rb_num2ull(VALUE val) { - if (RB_TYPE_P(val, T_NIL)) { + if (NIL_P(val)) { rb_raise(rb_eTypeError, "no implicit conversion from nil"); } - else if (RB_TYPE_P(val, T_FIXNUM)) { + else if (FIXNUM_P(val)) { return (LONG_LONG)FIX2LONG(val); /* this is FIX2LONG, intended */ } - else if (RB_TYPE_P(val, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(val)) { double d = RFLOAT_VALUE(val); if (d < ULLONG_MAX_PLUS_ONE && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) { if (0 <= d) @@ -3157,7 +3458,7 @@ rb_num2ull(VALUE val) FLOAT_OUT_OF_RANGE(val, "unsigned long long"); } } - else if (RB_TYPE_P(val, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(val)) { return rb_big2ull(val); } else if (RB_TYPE_P(val, T_STRING)) { @@ -3177,93 +3478,149 @@ rb_num2ull(VALUE val) * * Document-class: Integer * - * Holds Integer values. You cannot add a singleton method to an - * Integer object, any attempt to do so will raise a TypeError. - * - */ - -/* - * call-seq: - * int.to_i -> integer - * int.to_int -> integer - * - * Since +int+ is already an Integer, returns +self+. + * An \Integer object represents an integer value. + * + * You can create an \Integer object explicitly with: + * + * - An {integer literal}[doc/syntax/literals_rdoc.html#label-Integer+Literals]. + * + * You can convert certain objects to Integers with: + * + * - \Method {Integer}[Kernel.html#method-i-Integer]. + * + * An attempt to add a singleton method to an instance of this class + * causes an exception to be raised. + * + * == What's Here + * + * First, what's elsewhere. \Class \Integer: + * + * - Inherits from {class Numeric}[Numeric.html#class-Numeric-label-What-27s+Here]. + * + * Here, class \Integer provides methods for: + * + * - {Querying}[#class-Integer-label-Querying] + * - {Comparing}[#class-Integer-label-Comparing] + * - {Converting}[#class-Integer-label-Converting] + * - {Other}[#class-Integer-label-Other] + * + * === Querying + * + * - #allbits?:: Returns whether all bits in +self+ are set. + * - #anybits?:: Returns whether any bits in +self+ are set. + * - #nobits?:: Returns whether no bits in +self+ are set. + * + * === Comparing + * + * - {<}[#method-i-3C]:: Returns whether +self+ is less than the given value. + * - {<=}[#method-i-3C-3D]:: Returns whether +self+ is less than + * or equal to the given value. + * - {<=>}[#method-i-3C-3D-3E]:: Returns a number indicating whether +self+ is less than, + * equal to, or greater than the given value. + * - {==}[#method-i-3D-3D] (aliased as #===):: Returns whether +self+ is + * equal to the given value. + * - {>}[#method-i-3E]:: Returns whether +self+ is greater than the given value. + * - {>=}[#method-i-3E-3D]:: Returns whether +self+ is greater than + * or equal to the given value. + * + * === Converting + * + * - ::sqrt:: Returns the integer square root of the given value. + * - ::try_convert:: Returns the given value converted to an \Integer. + * - #% (aliased as #modulo):: Returns +self+ modulo the given value. + * - {&}[#method-i-26]:: Returns the bitwise AND of +self+ and the given value. + * - #*:: Returns the product of +self+ and the given value. + * - {**}[#method-i-2A-2A]:: Returns the value of +self+ raised to the power of the given value. + * - #+:: Returns the sum of +self+ and the given value. + * - #-:: Returns the difference of +self+ and the given value. + * - {/}[#method-i-2F]:: Returns the quotient of +self+ and the given value. + * - #<<:: Returns the value of +self+ after a leftward bit-shift. + * - #>>:: Returns the value of +self+ after a rightward bit-shift. + * - #[]:: Returns a slice of bits from +self+. + * - {^}[#method-i-5E]:: Returns the bitwise EXCLUSIVE OR of +self+ and the given value. + * - #ceil:: Returns the smallest number greater than or equal to +self+. + * - #chr:: Returns a 1-character string containing the character + * represented by the value of +self+. + * - #digits:: Returns an array of integers representing the base-radix digits + * of +self+. + * - #div:: Returns the integer result of dividing +self+ by the given value. + * - #divmod:: Returns a 2-element array containing the quotient and remainder + * results of dividing +self+ by the given value. + * - #fdiv:: Returns the Float result of dividing +self+ by the given value. + * - #floor:: Returns the greatest number smaller than or equal to +self+. + * - #pow:: Returns the modular exponentiation of +self+. + * - #pred:: Returns the integer predecessor of +self+. + * - #remainder:: Returns the remainder after dividing +self+ by the given value. + * - #round:: Returns +self+ rounded to the nearest value with the given precision. + * - #succ (aliased as #next):: Returns the integer successor of +self+. + * - #to_f:: Returns +self+ converted to a Float. + * - #to_s (aliased as #inspect):: Returns a string containing the place-value + * representation of +self+ in the given radix. + * - #truncate:: Returns +self+ truncated to the given precision. + * - {/}[#method-i-7C]:: Returns the bitwise OR of +self+ and the given value. + * + * === Other + * + * - #downto:: Calls the given block with each integer value from +self+ + * down to the given value. + * - #times:: Calls the given block +self+ times with each integer + * in (0..self-1). + * - #upto:: Calls the given block with each integer value from +self+ + * up to the given value. * - * #to_int is an alias for #to_i. - */ - -static VALUE -int_to_i(VALUE num) -{ - return num; -} - -/* - * call-seq: - * int.integer? -> true - * - * Since +int+ is already an Integer, this always returns +true+. - */ - -static VALUE -int_int_p(VALUE num) -{ - return Qtrue; -} - -/* - * call-seq: - * int.odd? -> true or false - * - * Returns +true+ if +int+ is an odd number. */ VALUE rb_int_odd_p(VALUE num) { if (FIXNUM_P(num)) { - if (num & 2) { - return Qtrue; - } + return RBOOL(num & 2); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else { + assert(RB_BIGNUM_TYPE_P(num)); return rb_big_odd_p(num); } - else if (rb_funcall(num, '%', 1, INT2FIX(2)) != INT2FIX(0)) { - return Qtrue; - } - return Qfalse; } -/* - * call-seq: - * int.even? -> true or false - * - * Returns +true+ if +int+ is an even number. - */ - static VALUE int_even_p(VALUE num) { if (FIXNUM_P(num)) { - if ((num & 2) == 0) { - return Qtrue; - } + return RBOOL((num & 2) == 0); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else { + assert(RB_BIGNUM_TYPE_P(num)); return rb_big_even_p(num); } - else if (rb_funcall(num, '%', 1, INT2FIX(2)) == INT2FIX(0)) { - return Qtrue; - } - return Qfalse; +} + +VALUE +rb_int_even_p(VALUE num) +{ + return int_even_p(num); } /* * call-seq: - * int.allbits?(mask) -> true or false + * allbits?(mask) -> true or false + * + * Returns +true+ if all bits that are set (=1) in +mask+ + * are also set in +self+; returns +false+ otherwise. + * + * Example values: + * + * 0b1010101 self + * 0b1010100 mask + * 0b1010100 self & mask + * true self.allbits?(mask) + * + * 0b1010100 self + * 0b1010101 mask + * 0b1010100 self & mask + * false self.allbits?(mask) + * + * Related: Integer#anybits?, Integer#nobits?. * - * Returns +true+ if all bits of +int+ & +mask+ are 1. */ static VALUE @@ -3275,46 +3632,76 @@ int_allbits_p(VALUE num, VALUE mask) /* * call-seq: - * int.anybits?(mask) -> true or false + * anybits?(mask) -> true or false + * + * Returns +true+ if any bit that is set (=1) in +mask+ + * is also set in +self+; returns +false+ otherwise. + * + * Example values: + * + * 0b10000010 self + * 0b11111111 mask + * 0b10000010 self & mask + * true self.anybits?(mask) + * + * 0b00000000 self + * 0b11111111 mask + * 0b00000000 self & mask + * false self.anybits?(mask) + * + * Related: Integer#allbits?, Integer#nobits?. * - * Returns +true+ if any bits of +int+ & +mask+ are 1. */ static VALUE int_anybits_p(VALUE num, VALUE mask) { mask = rb_to_int(mask); - return num_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue; + return int_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue; } /* * call-seq: - * int.nobits?(mask) -> true or false + * nobits?(mask) -> true or false + * + * Returns +true+ if no bit that is set (=1) in +mask+ + * is also set in +self+; returns +false+ otherwise. + * + * Example values: + * + * 0b11110000 self + * 0b00001111 mask + * 0b00000000 self & mask + * true self.nobits?(mask) + * + * 0b00000001 self + * 0b11111111 mask + * 0b00000001 self & mask + * false self.nobits?(mask) + * + * Related: Integer#allbits?, Integer#anybits?. * - * Returns +true+ if no bits of +int+ & +mask+ are 1. */ static VALUE int_nobits_p(VALUE num, VALUE mask) { mask = rb_to_int(mask); - return num_zero_p(rb_int_and(num, mask)); + return int_zero_p(rb_int_and(num, mask)); } /* - * Document-method: Integer#succ - * Document-method: Integer#next * call-seq: - * int.next -> integer - * int.succ -> integer + * succ -> next_integer + * + * Returns the successor integer of +self+ (equivalent to self + 1): + * + * 1.succ #=> 2 + * -1.succ #=> 0 * - * Returns the successor of +int+, - * i.e. the Integer equal to int+1. + * Integer#next is an alias for Integer#succ. * - * 1.next #=> 2 - * (-1).next #=> 0 - * 1.succ #=> 2 - * (-1).succ #=> 0 + * Related: Integer#pred (predecessor value). */ VALUE @@ -3324,7 +3711,7 @@ rb_int_succ(VALUE num) long i = FIX2LONG(num) + 1; return LONG2NUM(i); } - if (RB_TYPE_P(num, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(num)) { return rb_big_plus(num, INT2FIX(1)); } return num_funcall1(num, '+', INT2FIX(1)); @@ -3334,13 +3721,15 @@ rb_int_succ(VALUE num) /* * call-seq: - * int.pred -> integer + * pred -> next_integer * - * Returns the predecessor of +int+, - * i.e. the Integer equal to int-1. + * Returns the predecessor of +self+ (equivalent to self - 1): + * + * 1.pred #=> 0 + * -1.pred #=> -2 + * + * Related: Integer#succ (successor value). * - * 1.pred #=> 0 - * (-1).pred #=> -2 */ static VALUE @@ -3350,7 +3739,7 @@ rb_int_pred(VALUE num) long i = FIX2LONG(num) - 1; return LONG2NUM(i); } - if (RB_TYPE_P(num, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(num)) { return rb_big_minus(num, INT2FIX(1)); } return num_funcall1(num, '-', INT2FIX(1)); @@ -3358,19 +3747,6 @@ rb_int_pred(VALUE num) #define int_pred rb_int_pred -/* - * Document-method: Integer#chr - * call-seq: - * int.chr([encoding]) -> string - * - * Returns a string containing the character represented by the +int+'s value - * according to +encoding+. - * - * 65.chr #=> "A" - * 230.chr #=> "\xE6" - * 255.chr(Encoding::UTF_8) #=> "\u00FF" - */ - VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc) { @@ -3393,6 +3769,25 @@ rb_enc_uint_chr(unsigned int code, rb_encoding *enc) return str; } +/* call-seq: + * chr -> string + * chr(encoding) -> string + * + * Returns a 1-character string containing the character + * represented by the value of +self+, according to the given +encoding+. + * + * 65.chr # => "A" + * 0..chr # => "\x00" + * 255.chr # => "\xFF" + * string = 255.chr(Encoding::UTF_8) + * string.encoding # => Encoding::UTF_8 + * + * Raises an exception if +self+ is negative. + * + * Related: Integer#ord. + * + */ + static VALUE int_chr(int argc, VALUE *argv, VALUE num) { @@ -3414,7 +3809,7 @@ int_chr(int argc, VALUE *argv, VALUE num) if (0xff < i) { enc = rb_default_internal_encoding(); if (!enc) { - rb_raise(rb_eRangeError, "%d out of char range", i); + rb_raise(rb_eRangeError, "%u out of char range", i); } goto decode; } @@ -3436,39 +3831,10 @@ int_chr(int argc, VALUE *argv, VALUE num) return rb_enc_uint_chr(i, enc); } -/* - * call-seq: - * int.ord -> self - * - * Returns the +int+ itself. - * - * 97.ord #=> 97 - * - * This method is intended for compatibility to character literals - * in Ruby 1.9. - * - * For example, ?a.ord returns 97 both in 1.8 and 1.9. - */ - -static VALUE -int_ord(VALUE num) -{ - return num; -} - /* * Fixnum */ - -/* - * Document-method: Integer#-@ - * call-seq: - * -int -> integer - * - * Returns +int+, negated. - */ - static VALUE fix_uminus(VALUE num) { @@ -3481,29 +3847,12 @@ rb_int_uminus(VALUE num) if (FIXNUM_P(num)) { return fix_uminus(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else { + assert(RB_BIGNUM_TYPE_P(num)); return rb_big_uminus(num); } - return num_funcall0(num, idUMinus); } -/* - * Document-method: Integer#to_s - * call-seq: - * int.to_s(base=10) -> string - * - * Returns a string containing the place-value representation of +int+ - * with radix +base+ (between 2 and 36). - * - * 12345.to_s #=> "12345" - * 12345.to_s(2) #=> "11000000111001" - * 12345.to_s(8) #=> "30071" - * 12345.to_s(10) #=> "12345" - * 12345.to_s(16) #=> "3039" - * 12345.to_s(36) #=> "9ix" - * 78546939656932.to_s(36) #=> "rubyrules" - */ - VALUE rb_fix2str(VALUE x, int base) { @@ -3546,8 +3895,41 @@ rb_fix2str(VALUE x, int base) return rb_usascii_str_new(b, e - b); } -static VALUE -int_to_s(int argc, VALUE *argv, VALUE x) +static VALUE rb_fix_to_s_static[10]; + +MJIT_FUNC_EXPORTED VALUE +rb_fix_to_s(VALUE x) +{ + long i = FIX2LONG(x); + if (i >= 0 && i < 10) { + return rb_fix_to_s_static[i]; + } + return rb_fix2str(x, 10); +} + +/* + * call-seq: + * to_s(base = 10) -> string + * + * Returns a string containing the place-value representation of +self+ + * in radix +base+ (in 2..36). + * + * 12345.to_s # => "12345" + * 12345.to_s(2) # => "11000000111001" + * 12345.to_s(8) # => "30071" + * 12345.to_s(10) # => "12345" + * 12345.to_s(16) # => "3039" + * 12345.to_s(36) # => "9ix" + * 78546939656932.to_s(36) # => "rubyrules" + * + * Raises an exception if +base+ is out of range. + * + * Integer#inspect is an alias for Integer#to_s. + * + */ + +MJIT_FUNC_EXPORTED VALUE +rb_int_to_s(int argc, VALUE *argv, VALUE x) { int base; @@ -3564,32 +3946,23 @@ rb_int2str(VALUE x, int base) if (FIXNUM_P(x)) { return rb_fix2str(x, base); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big2str(x, base); } return rb_any_to_s(x); } -/* - * Document-method: Integer#+ - * call-seq: - * int + numeric -> numeric_result - * - * Performs addition: the class of the resulting object depends on - * the class of +numeric+. - */ - static VALUE fix_plus(VALUE x, VALUE y) { if (FIXNUM_P(y)) { return rb_fix_plus_fix(x, y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return rb_big_plus(y, x); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y)); } else if (RB_TYPE_P(y, T_COMPLEX)) { @@ -3606,38 +3979,44 @@ rb_fix_plus(VALUE x, VALUE y) return fix_plus(x, y); } +/* + * call-seq: + * self + numeric -> numeric_result + * + * Performs addition: + * + * 2 + 2 # => 4 + * -2 + 2 # => 0 + * -2 + -2 # => -4 + * 2 + 2.0 # => 4.0 + * 2 + Rational(2, 1) # => (4/1) + * 2 + Complex(2, 0) # => (4+0i) + * + */ + VALUE rb_int_plus(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_plus(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_plus(x, y); } return rb_num_coerce_bin(x, y, '+'); } -/* - * Document-method: Integer#- - * call-seq: - * int - numeric -> numeric_result - * - * Performs subtraction: the class of the resulting object depends on - * the class of +numeric+. - */ - static VALUE fix_minus(VALUE x, VALUE y) { if (FIXNUM_P(y)) { return rb_fix_minus_fix(x, y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { x = rb_int2big(FIX2LONG(x)); return rb_big_minus(x, y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y)); } else { @@ -3645,13 +4024,28 @@ fix_minus(VALUE x, VALUE y) } } +/* + * call-seq: + * self - numeric -> numeric_result + * + * Performs subtraction: + * + * 4 - 2 # => 2 + * -4 - 2 # => -6 + * -4 - -2 # => -2 + * 4 - 2.0 # => 2.0 + * 4 - Rational(2, 1) # => (2/1) + * 4 - Complex(2, 0) # => (2+0i) + * + */ + VALUE rb_int_minus(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_minus(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_minus(x, y); } return rb_num_coerce_bin(x, y, '-'); @@ -3662,29 +4056,20 @@ rb_int_minus(VALUE x, VALUE y) /*tests if N*N would overflow*/ #define FIT_SQRT_LONG(n) (((n)=-SQRT_LONG_MAX)) -/* - * Document-method: Integer#* - * call-seq: - * int * numeric -> numeric_result - * - * Performs multiplication: the class of the resulting object depends on - * the class of +numeric+. - */ - static VALUE fix_mul(VALUE x, VALUE y) { if (FIXNUM_P(y)) { return rb_fix_mul_fix(x, y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { switch (x) { case INT2FIX(0): return x; case INT2FIX(1): return y; } return rb_big_mul(y, x); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y)); } else if (RB_TYPE_P(y, T_COMPLEX)) { @@ -3695,13 +4080,27 @@ fix_mul(VALUE x, VALUE y) } } +/* + * call-seq: + * self * numeric -> numeric_result + * + * Performs multiplication: + * + * 4 * 2 # => 8 + * 4 * -2 # => -8 + * -4 * 2 # => -8 + * 4 * 2.0 # => 8.0 + * 4 * Rational(1, 3) # => (4/3) + * 4 * Complex(2, 0) # => (8+0i) + */ + VALUE rb_int_mul(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_mul(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_mul(x, y); } return rb_num_coerce_bin(x, y, '*'); @@ -3713,10 +4112,10 @@ fix_fdiv_double(VALUE x, VALUE y) if (FIXNUM_P(y)) { return double_div_double(FIX2LONG(x), FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return double_div_double(FIX2LONG(x), RFLOAT_VALUE(y)); } else { @@ -3737,7 +4136,7 @@ rb_int_fdiv_double(VALUE x, VALUE y) if (FIXNUM_P(x)) { return fix_fdiv_double(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_fdiv_double(x, y); } else { @@ -3746,15 +4145,19 @@ rb_int_fdiv_double(VALUE x, VALUE y) } /* - * Document-method: Integer#fdiv * call-seq: - * int.fdiv(numeric) -> float + * fdiv(numeric) -> float + * + * Returns the Float result of dividing +self+ by +numeric+: + * + * 4.fdiv(2) # => 2.0 + * 4.fdiv(-2) # => -2.0 + * -4.fdiv(2) # => -2.0 + * 4.fdiv(2.0) # => 2.0 + * 4.fdiv(Rational(3, 4)) # => 5.333333333333333 * - * Returns the floating point result of dividing +int+ by +numeric+. + * Raises an exception if +numeric+ cannot be converted to a Float. * - * 654321.fdiv(13731) #=> 47.652829364212366 - * 654321.fdiv(13731.24) #=> 47.65199646936475 - * -654321.fdiv(13731) #=> -47.652829364212366 */ VALUE @@ -3766,15 +4169,6 @@ rb_int_fdiv(VALUE x, VALUE y) return Qnil; } -/* - * Document-method: Integer#/ - * call-seq: - * int / numeric -> numeric_result - * - * Performs division: the class of the resulting object depends on - * the class of +numeric+. - */ - static VALUE fix_divide(VALUE x, VALUE y, ID op) { @@ -3782,11 +4176,11 @@ fix_divide(VALUE x, VALUE y, ID op) if (FIXNUM_ZERO_P(y)) rb_num_zerodiv(); return rb_fix_div_fix(x, y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { x = rb_int2big(FIX2LONG(x)); return rb_big_div(x, y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { if (op == '/') { double d = FIX2LONG(x); return rb_flo_div_flo(DBL2NUM(d), y); @@ -3812,57 +4206,73 @@ fix_div(VALUE x, VALUE y) return fix_divide(x, y, '/'); } +/* + * call-seq: + * self / numeric -> numeric_result + * + * Performs division; for integer +numeric+, truncates the result to an integer: + * + * 4 / 3 # => 1 + * 4 / -3 # => -2 + * -4 / 3 # => -2 + * -4 / -3 # => 1 + * + * For other +numeric+, returns non-integer result: + * + * 4 / 3.0 # => 1.3333333333333333 + * 4 / Rational(3, 1) # => (4/3) + * 4 / Complex(3, 0) # => ((4/3)+0i) + * + */ + VALUE rb_int_div(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_div(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_div(x, y); } return Qnil; } -/* - * Document-method: Integer#div - * call-seq: - * int.div(numeric) -> integer - * - * Performs integer division: returns the integer result of dividing +int+ - * by +numeric+. - */ - static VALUE fix_idiv(VALUE x, VALUE y) { return fix_divide(x, y, id_div); } +/* + * call-seq: + * div(numeric) -> integer + * + * Performs integer division; returns the integer result of dividing +self+ + * by +numeric+: + * + * 4.div(3) # => 1 + * 4.div(-3) # => -2 + * -4.div(3) # => -2 + * -4.div(-3) # => 1 + * 4.div(3.0) # => 1 + * 4.div(Rational(3, 1)) # => 1 + * + * Raises an exception if +numeric+ does not have method +div+. + * + */ + VALUE rb_int_idiv(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_idiv(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_idiv(x, y); } return num_div(x, y); } -/* - * Document-method: Integer#% - * Document-method: Integer#modulo - * call-seq: - * int % other -> real - * int.modulo(other) -> real - * - * Returns +int+ modulo +other+. - * - * See Numeric#divmod for more information. - */ - static VALUE fix_mod(VALUE x, VALUE y) { @@ -3870,11 +4280,11 @@ fix_mod(VALUE x, VALUE y) if (FIXNUM_ZERO_P(y)) rb_num_zerodiv(); return rb_fix_mod_fix(x, y); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { x = rb_int2big(FIX2LONG(x)); return rb_big_modulo(x, y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y))); } else { @@ -3882,13 +4292,43 @@ fix_mod(VALUE x, VALUE y) } } +/* + * call-seq: + * self % other -> real_number + * + * Returns +self+ modulo +other+ as a real number. + * + * For integer +n+ and real number +r+, these expressions are equivalent: + * + * n % r + * n-r*(n/r).floor + * n.divmod(r)[1] + * + * See Numeric#divmod. + * + * Examples: + * + * 10 % 2 # => 0 + * 10 % 3 # => 1 + * 10 % 4 # => 2 + * + * 10 % -2 # => 0 + * 10 % -3 # => -2 + * 10 % -4 # => -2 + * + * 10 % 3.0 # => 1.0 + * 10 % Rational(3, 1) # => (1/1) + * + * Integer#modulo is an alias for Integer#%. + * + */ VALUE rb_int_modulo(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_mod(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_modulo(x, y); } return num_modulo(x, y); @@ -3896,19 +4336,25 @@ rb_int_modulo(VALUE x, VALUE y) /* * call-seq: - * int.remainder(numeric) -> real + * remainder(other) -> real_number * - * Returns the remainder after dividing +int+ by +numeric+. + * Returns the remainder after dividing +self+ by +other+. * - * x.remainder(y) means x-y*(x/y).truncate. + * Examples: * - * 5.remainder(3) #=> 2 - * -5.remainder(3) #=> -2 - * 5.remainder(-3) #=> 2 - * -5.remainder(-3) #=> -2 - * 5.remainder(1.5) #=> 0.5 + * 11.remainder(4) # => 3 + * 11.remainder(-4) # => 3 + * -11.remainder(4) # => -3 + * -11.remainder(-4) # => -3 + * + * 12.remainder(4) # => 0 + * 12.remainder(-4) # => 0 + * -12.remainder(4) # => 0 + * -12.remainder(-4) # => 0 + * + * 13.remainder(4.0) # => 1.0 + * 13.remainder(Rational(4, 1)) # => (1/1) * - * See Numeric#divmod. */ static VALUE @@ -3917,19 +4363,12 @@ int_remainder(VALUE x, VALUE y) if (FIXNUM_P(x)) { return num_remainder(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_remainder(x, y); } return Qnil; } -/* - * Document-method: Integer#divmod - * call-seq: - * int.divmod(numeric) -> array - * - * See Numeric#divmod. - */ static VALUE fix_divmod(VALUE x, VALUE y) { @@ -3939,11 +4378,11 @@ fix_divmod(VALUE x, VALUE y) rb_fix_divmod_fix(x, y, &div, &mod); return rb_assoc_new(div, mod); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { x = rb_int2big(FIX2LONG(x)); return rb_big_divmod(x, y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { { double div, mod; volatile VALUE a, b; @@ -3959,35 +4398,57 @@ fix_divmod(VALUE x, VALUE y) } } +/* + * call-seq: + * divmod(other) -> array + * + * Returns a 2-element array [q, r], where + * + * q = (self/other).floor # Quotient + * r = self % other # Remainder + * + * Examples: + * + * 11.divmod(4) # => [2, 3] + * 11.divmod(-4) # => [-3, -1] + * -11.divmod(4) # => [-3, 1] + * -11.divmod(-4) # => [2, -3] + * + * 12.divmod(4) # => [3, 0] + * 12.divmod(-4) # => [-3, 0] + * -12.divmod(4) # => [-3, 0] + * -12.divmod(-4) # => [3, 0] + * + * 13.divmod(4.0) # => [3, 1.0] + * 13.divmod(Rational(4, 1)) # => [3, (1/1)] + * + */ VALUE rb_int_divmod(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_divmod(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_divmod(x, y); } return Qnil; } /* - * Document-method: Integer#** * call-seq: - * int ** numeric -> numeric_result + * self ** numeric -> numeric_result * - * Raises +int+ to the power of +numeric+, which may be negative or - * fractional. - * The result may be an Integer, a Float, a Rational, or a complex number. + * Raises +self+ to the power of +numeric+: * - * 2 ** 3 #=> 8 - * 2 ** -1 #=> (1/2) - * 2 ** 0.5 #=> 1.4142135623730951 - * (-1) ** 0.5 #=> (0.0+1.0i) + * 2 ** 3 # => 8 + * 2 ** -3 # => (1/8) + * -2 ** 3 # => -8 + * -2 ** -3 # => (-1/8) + * 2 ** 3.3 # => 9.849155306759329 + * 2 ** Rational(3, 1) # => (8/1) + * 2 ** Complex(3, 0) # => (8+0i) * - * 123456789 ** 2 #=> 15241578750190521 - * 123456789 ** 1.2 #=> 5126464716.0993185 - * 123456789 ** -2 #=> (1/15241578750190521) */ static VALUE @@ -4007,13 +4468,7 @@ int_pow(long x, unsigned long y) do { while (y % 2 == 0) { if (!FIT_SQRT_LONG(x)) { - VALUE v; - bignum: - v = rb_big_pow(rb_int2big(x), LONG2NUM(y)); - if (RB_FLOAT_TYPE_P(v)) /* infinity due to overflow */ - return v; - if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v); - return v; + goto bignum; } x = x * x; y >>= 1; @@ -4027,6 +4482,14 @@ int_pow(long x, unsigned long y) } while (--y); if (neg) z = -z; return LONG2NUM(z); + + VALUE v; + bignum: + v = rb_big_pow(rb_int2big(x), LONG2NUM(y)); + if (RB_FLOAT_TYPE_P(v)) /* infinity due to overflow */ + return v; + if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v); + return v; } VALUE @@ -4035,6 +4498,26 @@ rb_int_positive_pow(long x, unsigned long y) return int_pow(x, y); } +static VALUE +fix_pow_inverted(VALUE x, VALUE minusb) +{ + if (x == INT2FIX(0)) { + rb_num_zerodiv(); + UNREACHABLE_RETURN(Qundef); + } + else { + VALUE y = rb_int_pow(x, minusb); + + if (RB_FLOAT_TYPE_P(y)) { + double d = pow((double)FIX2LONG(x), RFLOAT_VALUE(y)); + return DBL2NUM(1.0 / d); + } + else { + return rb_rational_raw(INT2FIX(1), y); + } + } +} + static VALUE fix_pow(VALUE x, VALUE y) { @@ -4044,71 +4527,59 @@ fix_pow(VALUE x, VALUE y) long b = FIX2LONG(y); if (a == 1) return INT2FIX(1); - if (a == -1) { - if (b % 2 == 0) - return INT2FIX(1); - else - return INT2FIX(-1); - } - if (b < 0) { - if (a == 0) rb_num_zerodiv(); - y = rb_int_pow(x, LONG2NUM(-b)); - goto inverted; - } - + if (a == -1) return INT2FIX(b % 2 ? -1 : 1); + if (b < 0) return fix_pow_inverted(x, fix_uminus(y)); if (b == 0) return INT2FIX(1); if (b == 1) return x; - if (a == 0) { - if (b > 0) return INT2FIX(0); - return DBL2NUM(HUGE_VAL); - } + if (a == 0) return INT2FIX(0); return int_pow(a, b); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { if (a == 1) return INT2FIX(1); - if (a == -1) { - if (int_even_p(y)) return INT2FIX(1); - else return INT2FIX(-1); - } - if (BIGNUM_NEGATIVE_P(y)) { - if (a == 0) rb_num_zerodiv(); - y = rb_int_pow(x, rb_big_uminus(y)); - inverted: - if (RB_FLOAT_TYPE_P(y)) { - double d = pow((double)a, RFLOAT_VALUE(y)); - return DBL2NUM(1.0 / d); - } - return rb_rational_raw(INT2FIX(1), y); - } + if (a == -1) return INT2FIX(int_even_p(y) ? 1 : -1); + if (BIGNUM_NEGATIVE_P(y)) return fix_pow_inverted(x, rb_big_uminus(y)); if (a == 0) return INT2FIX(0); x = rb_int2big(FIX2LONG(x)); return rb_big_pow(x, y); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { double dy = RFLOAT_VALUE(y); if (dy == 0.0) return DBL2NUM(1.0); if (a == 0) { return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0); } if (a == 1) return DBL2NUM(1.0); - { - if (a < 0 && dy != round(dy)) - return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy); - return DBL2NUM(pow((double)a, dy)); - } + if (a < 0 && dy != round(dy)) + return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy); + return DBL2NUM(pow((double)a, dy)); } else { return rb_num_coerce_bin(x, y, idPow); } } +/* + * call-seq: + * self ** numeric -> numeric_result + * + * Raises +self+ to the power of +numeric+: + * + * 2 ** 3 # => 8 + * 2 ** -3 # => (1/8) + * -2 ** 3 # => -8 + * -2 ** -3 # => (-1/8) + * 2 ** 3.3 # => 9.849155306759329 + * 2 ** Rational(3, 1) # => (8/1) + * 2 ** Complex(3, 0) # => (8+0i) + * + */ VALUE rb_int_pow(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_pow(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_pow(x, y); } return Qnil; @@ -4126,32 +4597,21 @@ rb_num_pow(VALUE x, VALUE y) return rb_complex_pow(x, y); case T_RATIONAL: return rb_rational_pow(x, y); + default: + break; } return Qnil; } -/* - * Document-method: Integer#== - * Document-method: Integer#=== - * call-seq: - * int == other -> true or false - * - * Returns +true+ if +int+ equals +other+ numerically. - * Contrast this with Integer#eql?, which requires +other+ to be an Integer. - * - * 1 == 2 #=> false - * 1 == 1.0 #=> true - */ - static VALUE fix_equal(VALUE x, VALUE y) { if (x == y) return Qtrue; if (FIXNUM_P(y)) return Qfalse; - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { return rb_big_eq(y, x); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return rb_integer_float_eq(x, y); } else { @@ -4159,31 +4619,33 @@ fix_equal(VALUE x, VALUE y) } } +/* + * call-seq: + * self == other -> true or false + * + * Returns +true+ if +self+ is numerically equal to +other+; +false+ otherwise. + * + * 1 == 2 #=> false + * 1 == 1.0 #=> true + * + * Related: Integer#eql? (requires +other+ to be an \Integer). + * + * Integer#=== is an alias for Integer#==. + * + */ + VALUE rb_int_equal(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_equal(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_eq(x, y); } return Qnil; } -/* - * Document-method: Integer#<=> - * call-seq: - * int <=> numeric -> -1, 0, +1, or nil - * - * Comparison---Returns -1, 0, or +1 depending on whether +int+ is - * less than, equal to, or greater than +numeric+. - * - * This is the basis for the tests in the Comparable module. - * - * +nil+ is returned if the two values are incomparable. - */ - static VALUE fix_cmp(VALUE x, VALUE y) { @@ -4192,7 +4654,7 @@ fix_cmp(VALUE x, VALUE y) if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1); return INT2FIX(-1); } - else if (RB_TYPE_P(y, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(y)) { VALUE cmp = rb_big_cmp(y, x); switch (cmp) { case INT2FIX(+1): return INT2FIX(-1); @@ -4200,7 +4662,7 @@ fix_cmp(VALUE x, VALUE y) } return cmp; } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { return rb_integer_float_cmp(x, y); } else { @@ -4208,13 +4670,39 @@ fix_cmp(VALUE x, VALUE y) } } +/* + * call-seq: + * self <=> other -> -1, 0, +1, or nil + * + * Returns: + * + * - -1, if +self+ is less than +other+. + * - 0, if +self+ is equal to +other+. + * - 1, if +self+ is greater then +other+. + * - +nil+, if +self+ and +other+ are incomparable. + * + * Examples: + * + * 1 <=> 2 # => -1 + * 1 <=> 1 # => 0 + * 1 <=> 0 # => 1 + * 1 <=> 'foo' # => nil + * + * 1 <=> 1.0 # => 0 + * 1 <=> Rational(1, 1) # => 0 + * 1 <=> Complex(1, 0) # => 0 + * + * This method is the basis for comparisons in module Comparable. + * + */ + VALUE rb_int_cmp(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_cmp(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_cmp(x, y); } else { @@ -4222,190 +4710,203 @@ rb_int_cmp(VALUE x, VALUE y) } } -/* - * Document-method: Integer#> - * call-seq: - * int > real -> true or false - * - * Returns +true+ if the value of +int+ is greater than that of +real+. - */ - static VALUE fix_gt(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue; - return Qfalse; + return RBOOL(FIX2LONG(x) > FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { - return rb_big_cmp(y, x) == INT2FIX(-1) ? Qtrue : Qfalse; + else if (RB_BIGNUM_TYPE_P(y)) { + return RBOOL(rb_big_cmp(y, x) == INT2FIX(-1)); } - else if (RB_TYPE_P(y, T_FLOAT)) { - return rb_integer_float_cmp(x, y) == INT2FIX(1) ? Qtrue : Qfalse; + else if (RB_FLOAT_TYPE_P(y)) { + return RBOOL(rb_integer_float_cmp(x, y) == INT2FIX(1)); } else { return rb_num_coerce_relop(x, y, '>'); } } +/* + * call-seq: + * self > other -> true or false + * + * Returns +true+ if the value of +self+ is greater than that of +other+: + * + * 1 > 0 # => true + * 1 > 1 # => false + * 1 > 2 # => false + * 1 > 0.5 # => true + * 1 > Rational(1, 2) # => true + * + * Raises an exception if the comparison cannot be made. + * + */ + VALUE rb_int_gt(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_gt(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_gt(x, y); } return Qnil; } -/* - * Document-method: Integer#>= - * call-seq: - * int >= real -> true or false - * - * Returns +true+ if the value of +int+ is greater than or equal to that of - * +real+. - */ - static VALUE fix_ge(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue; - return Qfalse; + return RBOOL(FIX2LONG(x) >= FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { - return rb_big_cmp(y, x) != INT2FIX(+1) ? Qtrue : Qfalse; + else if (RB_BIGNUM_TYPE_P(y)) { + return RBOOL(rb_big_cmp(y, x) != INT2FIX(+1)); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(x, y); - return rel == INT2FIX(1) || rel == INT2FIX(0) ? Qtrue : Qfalse; + return RBOOL(rel == INT2FIX(1) || rel == INT2FIX(0)); } else { return rb_num_coerce_relop(x, y, idGE); } } +/* + * call-seq: + * self >= real -> true or false + * + * Returns +true+ if the value of +self+ is greater than or equal to + * that of +other+: + * + * 1 >= 0 # => true + * 1 >= 1 # => true + * 1 >= 2 # => false + * 1 >= 0.5 # => true + * 1 >= Rational(1, 2) # => true + * + * Raises an exception if the comparison cannot be made. + * + */ + VALUE rb_int_ge(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_ge(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_ge(x, y); } return Qnil; } -/* - * Document-method: Integer#< - * call-seq: - * int < real -> true or false - * - * Returns +true+ if the value of +int+ is less than that of +real+. - */ - static VALUE fix_lt(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue; - return Qfalse; + return RBOOL(FIX2LONG(x) < FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { - return rb_big_cmp(y, x) == INT2FIX(+1) ? Qtrue : Qfalse; + else if (RB_BIGNUM_TYPE_P(y)) { + return RBOOL(rb_big_cmp(y, x) == INT2FIX(+1)); } - else if (RB_TYPE_P(y, T_FLOAT)) { - return rb_integer_float_cmp(x, y) == INT2FIX(-1) ? Qtrue : Qfalse; + else if (RB_FLOAT_TYPE_P(y)) { + return RBOOL(rb_integer_float_cmp(x, y) == INT2FIX(-1)); } else { return rb_num_coerce_relop(x, y, '<'); } } +/* + * call-seq: + * self < other -> true or false + * + * Returns +true+ if the value of +self+ is less than that of +other+: + * + * 1 < 0 # => false + * 1 < 1 # => false + * 1 < 2 # => true + * 1 < 0.5 # => false + * 1 < Rational(1, 2) # => false + * + * Raises an exception if the comparison cannot be made. + * + */ + static VALUE int_lt(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_lt(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_lt(x, y); } return Qnil; } -/* - * Document-method: Integer#<= - * call-seq: - * int <= real -> true or false - * - * Returns +true+ if the value of +int+ is less than or equal to that of - * +real+. - */ - static VALUE fix_le(VALUE x, VALUE y) { if (FIXNUM_P(y)) { - if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue; - return Qfalse; + return RBOOL(FIX2LONG(x) <= FIX2LONG(y)); } - else if (RB_TYPE_P(y, T_BIGNUM)) { - return rb_big_cmp(y, x) != INT2FIX(-1) ? Qtrue : Qfalse; + else if (RB_BIGNUM_TYPE_P(y)) { + return RBOOL(rb_big_cmp(y, x) != INT2FIX(-1)); } - else if (RB_TYPE_P(y, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(y)) { VALUE rel = rb_integer_float_cmp(x, y); - return rel == INT2FIX(-1) || rel == INT2FIX(0) ? Qtrue : Qfalse; + return RBOOL(rel == INT2FIX(-1) || rel == INT2FIX(0)); } else { return rb_num_coerce_relop(x, y, idLE); } } +/* + * call-seq: + * self <= real -> true or false + * + * Returns +true+ if the value of +self+ is less than or equal to + * that of +other+: + * + * 1 <= 0 # => false + * 1 <= 1 # => true + * 1 <= 2 # => true + * 1 <= 0.5 # => false + * 1 <= Rational(1, 2) # => false + * + * Raises an exception if the comparison cannot be made. + * + */ + static VALUE int_le(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_le(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_le(x, y); } return Qnil; } -/* - * Document-method: Integer#~ - * call-seq: - * ~int -> integer - * - * One's complement: returns a number where each bit is flipped. - * - * Inverts the bits in an Integer. As integers are conceptually of - * infinite length, the result acts as if it had an infinite number of - * one bits to the left. In hex representations, this is displayed - * as two periods to the left of the digits. - * - * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA" - */ - static VALUE fix_comp(VALUE num) { return ~num | FIXNUM_FLAG; } -static VALUE -int_comp(VALUE num) +VALUE +rb_int_comp(VALUE num) { if (FIXNUM_P(num)) { return fix_comp(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return rb_big_comp(num); } return Qnil; @@ -4440,14 +4941,6 @@ rb_num_coerce_bit(VALUE x, VALUE y, ID func) return ret; } -/* - * Document-method: Integer#& - * call-seq: - * int & other_int -> integer - * - * Bitwise AND. - */ - static VALUE fix_and(VALUE x, VALUE y) { @@ -4456,33 +4949,40 @@ fix_and(VALUE x, VALUE y) return LONG2NUM(val); } - if (RB_TYPE_P(y, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(y)) { return rb_big_and(y, x); } return rb_num_coerce_bit(x, y, '&'); } +/* + * call-seq: + * self & other -> integer + * + * Bitwise AND; each bit in the result is 1 if both corresponding bits + * in +self+ and +other+ are 1, 0 otherwise: + * + * "%04b" % (0b0101 & 0b0110) # => "0100" + * + * Raises an exception if +other+ is not an \Integer. + * + * Related: Integer#| (bitwise OR), Integer#^ (bitwise EXCLUSIVE OR). + * + */ + VALUE rb_int_and(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_and(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_and(x, y); } return Qnil; } -/* - * Document-method: Integer#| - * call-seq: - * int | other_int -> integer - * - * Bitwise OR. - */ - static VALUE fix_or(VALUE x, VALUE y) { @@ -4491,33 +4991,40 @@ fix_or(VALUE x, VALUE y) return LONG2NUM(val); } - if (RB_TYPE_P(y, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(y)) { return rb_big_or(y, x); } return rb_num_coerce_bit(x, y, '|'); } +/* + * call-seq: + * self | other -> integer + * + * Bitwise OR; each bit in the result is 1 if either corresponding bit + * in +self+ or +other+ is 1, 0 otherwise: + * + * "%04b" % (0b0101 | 0b0110) # => "0111" + * + * Raises an exception if +other+ is not an \Integer. + * + * Related: Integer#& (bitwise AND), Integer#^ (bitwise EXCLUSIVE OR). + * + */ + static VALUE int_or(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_or(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_or(x, y); } return Qnil; } -/* - * Document-method: Integer#^ - * call-seq: - * int ^ other_int -> integer - * - * Bitwise EXCLUSIVE OR. - */ - static VALUE fix_xor(VALUE x, VALUE y) { @@ -4526,40 +5033,47 @@ fix_xor(VALUE x, VALUE y) return LONG2NUM(val); } - if (RB_TYPE_P(y, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(y)) { return rb_big_xor(y, x); } return rb_num_coerce_bit(x, y, '^'); } +/* + * call-seq: + * self ^ other -> integer + * + * Bitwise EXCLUSIVE OR; each bit in the result is 1 if the corresponding bits + * in +self+ and +other+ are different, 0 otherwise: + * + * "%04b" % (0b0101 ^ 0b0110) # => "0011" + * + * Raises an exception if +other+ is not an \Integer. + * + * Related: Integer#& (bitwise AND), Integer#| (bitwise OR). + * + */ + static VALUE int_xor(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return fix_xor(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_xor(x, y); } return Qnil; } -/* - * Document-method: Integer#<< - * call-seq: - * int << count -> integer - * - * Returns +int+ shifted left +count+ positions, or right if +count+ - * is negative. - */ - static VALUE rb_fix_lshift(VALUE x, VALUE y) { long val, width; val = NUM2LONG(x); + if (!val) return (rb_to_int(y), INT2FIX(0)); if (!FIXNUM_P(y)) return rb_big_lshift(rb_int2big(val), y); width = FIX2LONG(y); @@ -4579,33 +5093,42 @@ fix_lshift(long val, unsigned long width) return LONG2NUM(val); } +/* + * call-seq: + * self << count -> integer + * + * Returns +self+ with bits shifted +count+ positions to the left, + * or to the right if +count+ is negative: + * + * n = 0b11110000 + * "%08b" % (n << 1) # => "111100000" + * "%08b" % (n << 3) # => "11110000000" + * "%08b" % (n << -1) # => "01111000" + * "%08b" % (n << -3) # => "00011110" + * + * Related: Integer#>>. + * + */ + VALUE rb_int_lshift(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return rb_fix_lshift(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_lshift(x, y); } return Qnil; } -/* - * Document-method: Integer#>> - * call-seq: - * int >> count -> integer - * - * Returns +int+ shifted right +count+ positions, or left if +count+ - * is negative. - */ - static VALUE rb_fix_rshift(VALUE x, VALUE y) { long i, val; val = FIX2LONG(x); + if (!val) return (rb_to_int(y), INT2FIX(0)); if (!FIXNUM_P(y)) return rb_big_rshift(rb_int2big(val), y); i = FIX2LONG(y); @@ -4626,13 +5149,30 @@ fix_rshift(long val, unsigned long i) return LONG2FIX(val); } +/* + * call-seq: + * self >> count -> integer + * + * Returns +self+ with bits shifted +count+ positions to the right, + * or to the left if +count+ is negative: + * + * n = 0b11110000 + * "%08b" % (n >> 1) # => "01111000" + * "%08b" % (n >> 3) # => "00011110" + * "%08b" % (n >> -1) # => "111100000" + * "%08b" % (n >> -3) # => "11110000000" + * + * Related: Integer#<<. + * + */ + static VALUE rb_int_rshift(VALUE x, VALUE y) { if (FIXNUM_P(x)) { return rb_fix_rshift(x, y); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return rb_big_rshift(x, y); } return Qnil; @@ -4700,7 +5240,7 @@ int_aref1(VALUE num, VALUE arg) if (!RTEST(num_negative_p(end))) { if (!excl) end = rb_int_plus(end, INT2FIX(1)); VALUE mask = generate_mask(end); - if (RTEST(num_zero_p(rb_int_and(num, mask)))) { + if (RTEST(int_zero_p(rb_int_and(num, mask)))) { return INT2FIX(0); } else { @@ -4733,7 +5273,7 @@ int_aref1(VALUE num, VALUE arg) if (FIXNUM_P(num)) { return rb_fix_aref(num, arg); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return rb_big_aref(num, arg); } return Qnil; @@ -4749,41 +5289,42 @@ int_aref2(VALUE num, VALUE beg, VALUE len) } /* - * Document-method: Integer#[] * call-seq: - * int[n] -> 0, 1 - * int[n, m] -> num - * int[range] -> num + * self[offset] -> 0 or 1 + * self[offset, size] -> integer + * self[range] -> integer * - * Bit Reference---Returns the nth bit in the - * binary representation of +int+, where int[0] - * is the least significant bit. + * Returns a slice of bits from +self+. * - * a = 0b11001100101010 - * 30.downto(0) {|n| print a[n] } - * #=> 0000000000000000011001100101010 + * With argument +offset+, returns the bit at the given offset, + * where offset 0 refers to the least significant bit: * - * a = 9**15 - * 50.downto(0) {|n| print a[n] } - * #=> 000101110110100000111000011110010100111100010111001 + * n = 0b10 # => 2 + * n[0] # => 0 + * n[1] # => 1 + * n[2] # => 0 + * n[3] # => 0 * * In principle, n[i] is equivalent to (n >> i) & 1. - * Thus, any negative index always returns zero: + * Thus, negative index always returns zero: + * + * 255[-1] # => 0 * - * p 255[-1] #=> 0 + * With arguments +offset+ and +size+, returns +size+ bits from +self+, + * beginning at +offset+ and including bits of greater significance: * - * Range operations n[i, len] and n[i..j] - * are naturally extended. + * n = 0b111000 # => 56 + * "%010b" % n[0, 10] # => "0000111000" + * "%010b" % n[4, 10] # => "0000000011" * - * * n[i, len] equals to (n >> i) & ((1 << len) - 1). - * * n[i..j] equals to (n >> i) & ((1 << (j - i + 1)) - 1). - * * n[i...j] equals to (n >> i) & ((1 << (j - i)) - 1). - * * n[i..] equals to (n >> i). - * * n[..j] is zero if n & ((1 << (j + 1)) - 1) is zero. Otherwise, raises an ArgumentError. - * * n[...j] is zero if n & ((1 << j) - 1) is zero. Otherwise, raises an ArgumentError. + * With argument +range+, returns range.size bits from +self+, + * beginning at range.begin and including bits of greater significance: * - * Note that range operation may exhaust memory. - * For example, -1[0, 1000000000000] will raise NoMemoryError. + * n = 0b111000 # => 56 + * "%010b" % n[0..9] # => "0000111000" + * "%010b" % n[4..9] # => "0000000011" + * + * Raises an exception if the slice cannot be constructed. */ static VALUE @@ -4799,12 +5340,20 @@ int_aref(int const argc, VALUE * const argv, VALUE const num) } /* - * Document-method: Integer#to_f * call-seq: - * int.to_f -> float + * to_f -> float + * + * Converts +self+ to a Float: + * + * 1.to_f # => 1.0 + * -1.to_f # => -1.0 + * + * If the value of +self+ does not fit in a \Float, + * the result is infinity: + * + * (10**400).to_f # => Infinity + * (-10**400).to_f # => -Infinity * - * Converts +int+ to a Float. If +int+ doesn't fit in a Float, - * the result is infinity. */ static VALUE @@ -4815,7 +5364,7 @@ int_to_f(VALUE num) if (FIXNUM_P(num)) { val = (double)FIX2LONG(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { val = rb_big2dbl(num); } else { @@ -4825,22 +5374,6 @@ int_to_f(VALUE num) return DBL2NUM(val); } -/* - * Document-method: Integer#abs - * Document-method: Integer#magnitude - * call-seq: - * int.abs -> integer - * int.magnitude -> integer - * - * Returns the absolute value of +int+. - * - * (-12345).abs #=> 12345 - * -12345.abs #=> 12345 - * 12345.abs #=> 12345 - * - * Integer#magnitude is an alias for Integer#abs. - */ - static VALUE fix_abs(VALUE fix) { @@ -4857,91 +5390,30 @@ rb_int_abs(VALUE num) if (FIXNUM_P(num)) { return fix_abs(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return rb_big_abs(num); } return Qnil; } -/* - * Document-method: Integer#size - * call-seq: - * int.size -> int - * - * Returns the number of bytes in the machine representation of +int+ - * (machine dependent). - * - * 1.size #=> 8 - * -1.size #=> 8 - * 2147483647.size #=> 8 - * (256**10 - 1).size #=> 10 - * (256**20 - 1).size #=> 20 - * (256**40 - 1).size #=> 40 - */ - static VALUE fix_size(VALUE fix) { return INT2FIX(sizeof(long)); } -static VALUE -int_size(VALUE num) +MJIT_FUNC_EXPORTED VALUE +rb_int_size(VALUE num) { if (FIXNUM_P(num)) { return fix_size(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return rb_big_size_m(num); } return Qnil; } -/* - * Document-method: Integer#bit_length - * call-seq: - * int.bit_length -> integer - * - * Returns the number of bits of the value of +int+. - * - * "Number of bits" means the bit position of the highest bit - * which is different from the sign bit - * (where the least significant bit has bit position 1). - * If there is no such bit (zero or minus one), zero is returned. - * - * I.e. this method returns ceil(log2(int < 0 ? -int : int+1)). - * - * (-2**1000-1).bit_length #=> 1001 - * (-2**1000).bit_length #=> 1000 - * (-2**1000+1).bit_length #=> 1000 - * (-2**12-1).bit_length #=> 13 - * (-2**12).bit_length #=> 12 - * (-2**12+1).bit_length #=> 12 - * -0x101.bit_length #=> 9 - * -0x100.bit_length #=> 8 - * -0xff.bit_length #=> 8 - * -2.bit_length #=> 1 - * -1.bit_length #=> 0 - * 0.bit_length #=> 0 - * 1.bit_length #=> 1 - * 0xff.bit_length #=> 8 - * 0x100.bit_length #=> 9 - * (2**12-1).bit_length #=> 12 - * (2**12).bit_length #=> 13 - * (2**12+1).bit_length #=> 13 - * (2**1000-1).bit_length #=> 1000 - * (2**1000).bit_length #=> 1001 - * (2**1000+1).bit_length #=> 1001 - * - * This method can be used to detect overflow in Array#pack as follows: - * - * if n.bit_length < 32 - * [n].pack("l") # no overflow - * else - * raise "overflow" - * end - */ - static VALUE rb_fix_bit_length(VALUE fix) { @@ -4951,38 +5423,18 @@ rb_fix_bit_length(VALUE fix) return LONG2FIX(bit_length(v)); } -static VALUE +VALUE rb_int_bit_length(VALUE num) { if (FIXNUM_P(num)) { return rb_fix_bit_length(num); } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { return rb_big_bit_length(num); } return Qnil; } -/* - * Document-method: Integer#digits - * call-seq: - * int.digits -> array - * int.digits(base) -> array - * - * Returns the digits of +int+'s place-value representation - * with radix +base+ (default: 10). - * The digits are returned as an array with the least significant digit - * as the first array element. - * - * +base+ must be greater than or equal to 2. - * - * 12345.digits #=> [5, 4, 3, 2, 1] - * 12345.digits(7) #=> [4, 6, 6, 0, 5] - * 12345.digits(100) #=> [45, 23, 1] - * - * -12345.digits(7) #=> Math::DomainError - */ - static VALUE rb_fix_digits(VALUE fix, long base) { @@ -5010,16 +5462,16 @@ rb_fix_digits(VALUE fix, long base) static VALUE rb_int_digits_bigbase(VALUE num, VALUE base) { - VALUE digits; + VALUE digits, bases; assert(!rb_num_negative_p(num)); - if (RB_TYPE_P(base, T_BIGNUM)) + if (RB_BIGNUM_TYPE_P(base)) base = rb_big_norm(base); if (FIXNUM_P(base) && FIX2LONG(base) < 2) rb_raise(rb_eArgError, "invalid radix %ld", FIX2LONG(base)); - else if (RB_TYPE_P(base, T_BIGNUM) && BIGNUM_NEGATIVE_P(base)) + else if (RB_BIGNUM_TYPE_P(base) && BIGNUM_NEGATIVE_P(base)) rb_raise(rb_eArgError, "negative radix"); if (FIXNUM_P(base) && FIXNUM_P(num)) @@ -5028,16 +5480,53 @@ rb_int_digits_bigbase(VALUE num, VALUE base) if (FIXNUM_P(num)) return rb_ary_new_from_args(1, num); - digits = rb_ary_new(); - while (!FIXNUM_P(num) || FIX2LONG(num) > 0) { - VALUE qr = rb_int_divmod(num, base); - rb_ary_push(digits, RARRAY_AREF(qr, 1)); - num = RARRAY_AREF(qr, 0); + if (int_lt(rb_int_div(rb_int_bit_length(num), rb_int_bit_length(base)), INT2FIX(50))) { + digits = rb_ary_new(); + while (!FIXNUM_P(num) || FIX2LONG(num) > 0) { + VALUE qr = rb_int_divmod(num, base); + rb_ary_push(digits, RARRAY_AREF(qr, 1)); + num = RARRAY_AREF(qr, 0); + } + return digits; + } + + bases = rb_ary_new(); + for (VALUE b = base; int_lt(b, num) == Qtrue; b = rb_int_mul(b, b)) { + rb_ary_push(bases, b); + } + digits = rb_ary_new_from_args(1, num); + while (RARRAY_LEN(bases)) { + VALUE b = rb_ary_pop(bases); + long i, last_idx = RARRAY_LEN(digits) - 1; + for(i = last_idx; i >= 0; i--) { + VALUE n = RARRAY_AREF(digits, i); + VALUE divmod = rb_int_divmod(n, b); + VALUE div = RARRAY_AREF(divmod, 0); + VALUE mod = RARRAY_AREF(divmod, 1); + if (i != last_idx || div != INT2FIX(0)) rb_ary_store(digits, 2 * i + 1, div); + rb_ary_store(digits, 2 * i, mod); + } } return digits; } +/* + * call-seq: + * digits(base = 10) -> array_of_integers + * + * Returns an array of integers representing the +base+-radix + * digits of +self+; + * the first element of the array represents the least significant digit: + * + * 12345.digits # => [5, 4, 3, 2, 1] + * 12345.digits(7) # => [4, 6, 6, 0, 5] + * 12345.digits(100) # => [45, 23, 1] + * + * Raises an exception if +self+ is negative or +base+ is less than 2. + * + */ + static VALUE rb_int_digits(int argc, VALUE *argv, VALUE num) { @@ -5052,7 +5541,7 @@ rb_int_digits(int argc, VALUE *argv, VALUE num) if (!RB_INTEGER_TYPE_P(base_value)) rb_raise(rb_eTypeError, "wrong argument type %s (expected Integer)", rb_obj_classname(argv[0])); - if (RB_TYPE_P(base_value, T_BIGNUM)) + if (RB_BIGNUM_TYPE_P(base_value)) return rb_int_digits_bigbase(num, base_value); base = FIX2LONG(base_value); @@ -5066,32 +5555,38 @@ rb_int_digits(int argc, VALUE *argv, VALUE num) if (FIXNUM_P(num)) return rb_fix_digits(num, base); - else if (RB_TYPE_P(num, T_BIGNUM)) + else if (RB_BIGNUM_TYPE_P(num)) return rb_int_digits_bigbase(num, LONG2FIX(base)); return Qnil; } +static VALUE +int_upto_size(VALUE from, VALUE args, VALUE eobj) +{ + return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(1), FALSE); +} + /* - * Document-method: Integer#upto * call-seq: - * int.upto(limit) {|i| block } -> self - * int.upto(limit) -> an_enumerator + * upto(limit) {|i| ... } -> self + * upto(limit) -> enumerator + * + * Calls the given block with each integer value from +self+ up to +limit+; + * returns +self+: * - * Iterates the given block, passing in integer values from +int+ up to and - * including +limit+. + * a = [] + * 5.upto(10) {|i| a << i } # => 5 + * a # => [5, 6, 7, 8, 9, 10] + * a = [] + * -5.upto(0) {|i| a << i } # => -5 + * a # => [-5, -4, -3, -2, -1, 0] + * 5.upto(4) {|i| fail 'Cannot happen' } # => 5 * - * If no block is given, an Enumerator is returned instead. + * With no block given, returns an Enumerator. * - * 5.upto(10) {|i| print i, " " } #=> 5 6 7 8 9 10 */ -static VALUE -int_upto_size(VALUE from, VALUE args, VALUE eobj) -{ - return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(1), FALSE); -} - static VALUE int_upto(VALUE from, VALUE to) { @@ -5111,33 +5606,37 @@ int_upto(VALUE from, VALUE to) rb_yield(i); i = rb_funcall(i, '+', 1, INT2FIX(1)); } - if (NIL_P(c)) rb_cmperr(i, to); + ensure_cmp(c, i, to); } return from; } +static VALUE +int_downto_size(VALUE from, VALUE args, VALUE eobj) +{ + return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE); +} + /* - * Document-method: Integer#downto * call-seq: - * int.downto(limit) {|i| block } -> self - * int.downto(limit) -> an_enumerator + * downto(limit) {|i| ... } -> self + * downto(limit) -> enumerator + * + * Calls the given block with each integer value from +self+ down to +limit+; + * returns +self+: * - * Iterates the given block, passing in decreasing values from +int+ down to - * and including +limit+. + * a = [] + * 10.downto(5) {|i| a << i } # => 10 + * a # => [10, 9, 8, 7, 6, 5] + * a = [] + * 0.downto(-5) {|i| a << i } # => 0 + * a # => [0, -1, -2, -3, -4, -5] + * 4.downto(5) {|i| fail 'Cannot happen' } # => 4 * - * If no block is given, an Enumerator is returned instead. + * With no block given, returns an Enumerator. * - * 5.downto(1) { |n| print n, ".. " } - * puts "Liftoff!" - * #=> "5.. 4.. 3.. 2.. 1.. Liftoff!" */ -static VALUE -int_downto_size(VALUE from, VALUE args, VALUE eobj) -{ - return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE); -} - static VALUE int_downto(VALUE from, VALUE to) { @@ -5162,20 +5661,6 @@ int_downto(VALUE from, VALUE to) return from; } -/* - * Document-method: Integer#times - * call-seq: - * int.times {|i| block } -> self - * int.times -> an_enumerator - * - * Iterates the given block +int+ times, passing in values from zero to - * int - 1. - * - * If no block is given, an Enumerator is returned instead. - * - * 5.times {|i| print i, " " } #=> 0 1 2 3 4 - */ - static VALUE int_dotimes_size(VALUE num, VALUE args, VALUE eobj) { @@ -5188,6 +5673,21 @@ int_dotimes_size(VALUE num, VALUE args, VALUE eobj) return num; } +/* + * call-seq: + * times {|i| ... } -> self + * times -> enumerator + * + * Calls the given block +self+ times with each integer in (0..self-1): + * + * a = [] + * 5.times {|i| a.push(i) } # => 5 + * a # => [0, 1, 2, 3, 4] + * + * With no block given, returns an Enumerator. + * + */ + static VALUE int_dotimes(VALUE num) { @@ -5205,44 +5705,61 @@ int_dotimes(VALUE num) VALUE i = INT2FIX(0); for (;;) { - if (!RTEST(rb_funcall(i, '<', 1, num))) break; + if (!RTEST(int_le(i, num))) break; rb_yield(i); - i = rb_funcall(i, '+', 1, INT2FIX(1)); + i = rb_int_plus(i, INT2FIX(1)); } } return num; } /* - * Document-method: Integer#round * call-seq: - * int.round([ndigits] [, half: mode]) -> integer or float + * round(ndigits= 0, half: :up) -> integer * - * Returns +int+ rounded to the nearest value with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ rounded to the nearest value with + * a precision of +ndigits+ decimal digits. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. + * When +ndigits+ is negative, the returned value + * has at least ndigits.abs trailing zeros: + * + * 555.round(-1) # => 560 + * 555.round(-2) # => 600 + * 555.round(-3) # => 1000 + * -555.round(-2) # => -600 + * 555.round(-4) # => 0 * * Returns +self+ when +ndigits+ is zero or positive. * - * 1.round #=> 1 - * 1.round(2) #=> 1 - * 15.round(-1) #=> 20 - * (-15).round(-1) #=> -20 - * - * The optional +half+ keyword argument is available - * similar to Float#round. - * - * 25.round(-1, half: :up) #=> 30 - * 25.round(-1, half: :down) #=> 20 - * 25.round(-1, half: :even) #=> 20 - * 35.round(-1, half: :up) #=> 40 - * 35.round(-1, half: :down) #=> 30 - * 35.round(-1, half: :even) #=> 40 - * (-25).round(-1, half: :up) #=> -30 - * (-25).round(-1, half: :down) #=> -20 - * (-25).round(-1, half: :even) #=> -20 + * 555.round # => 555 + * 555.round(1) # => 555 + * 555.round(50) # => 555 + * + * If keyword argument +half+ is given, + * and +self+ is equidistant from the two candidate values, + * the rounding is according to the given +half+ value: + * + * - +:up+ or +nil+: round away from zero: + * + * 25.round(-1, half: :up) # => 30 + * (-25).round(-1, half: :up) # => -30 + * + * - +:down+: round toward zero: + * + * 25.round(-1, half: :down) # => 20 + * (-25).round(-1, half: :down) # => -20 + * + * + * - +:even+: round toward the candidate whose last nonzero digit is even: + * + * 25.round(-1, half: :even) # => 20 + * 15.round(-1, half: :even) # => 20 + * (-25).round(-1, half: :even) # => -20 + * + * Raises and exception if the value for +half+ is invalid. + * + * Related: Integer#truncate. + * */ static VALUE @@ -5262,22 +5779,27 @@ int_round(int argc, VALUE* argv, VALUE num) } /* - * Document-method: Integer#floor * call-seq: - * int.floor([ndigits]) -> integer or float + * floor(ndigits = 0) -> integer * - * Returns the largest number less than or equal to +int+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the largest number less than or equal to +self+ with + * a precision of +ndigits+ decimal digits. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. + * When +ndigits+ is negative, the returned value + * has at least ndigits.abs trailing zeros: + * + * 555.floor(-1) # => 550 + * 555.floor(-2) # => 500 + * -555.floor(-2) # => -600 + * 555.floor(-3) # => 0 * * Returns +self+ when +ndigits+ is zero or positive. * - * 1.floor #=> 1 - * 1.floor(2) #=> 1 - * 18.floor(-1) #=> 10 - * (-18).floor(-1) #=> -20 + * 555.floor # => 555 + * 555.floor(50) # => 555 + * + * Related: Integer#ceil. + * */ static VALUE @@ -5294,22 +5816,27 @@ int_floor(int argc, VALUE* argv, VALUE num) } /* - * Document-method: Integer#ceil * call-seq: - * int.ceil([ndigits]) -> integer or float + * ceil(ndigits = 0) -> integer * - * Returns the smallest number greater than or equal to +int+ with - * a precision of +ndigits+ decimal digits (default: 0). + * Returns the smallest number greater than or equal to +self+ with + * a precision of +ndigits+ decimal digits. * * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. + * with at least ndigits.abs trailing zeros: + * + * 555.ceil(-1) # => 560 + * 555.ceil(-2) # => 600 + * -555.ceil(-2) # => -500 + * 555.ceil(-3) # => 1000 * * Returns +self+ when +ndigits+ is zero or positive. * - * 1.ceil #=> 1 - * 1.ceil(2) #=> 1 - * 18.ceil(-1) #=> 20 - * (-18).ceil(-1) #=> -10 + * 555.ceil # => 555 + * 555.ceil(50) # => 555 + * + * Related: Integer#floor. + * */ static VALUE @@ -5326,22 +5853,26 @@ int_ceil(int argc, VALUE* argv, VALUE num) } /* - * Document-method: Integer#truncate * call-seq: - * int.truncate([ndigits]) -> integer or float + * truncate(ndigits = 0) -> integer * - * Returns +int+ truncated (toward zero) to - * a precision of +ndigits+ decimal digits (default: 0). + * Returns +self+ truncated (toward zero) to + * a precision of +ndigits+ decimal digits. * - * When the precision is negative, the returned value is an integer - * with at least ndigits.abs trailing zeros. + * When +ndigits+ is negative, the returned value + * has at least ndigits.abs trailing zeros: + * + * 555.truncate(-1) # => 550 + * 555.truncate(-2) # => 500 + * -555.truncate(-2) # => -500 * * Returns +self+ when +ndigits+ is zero or positive. * - * 1.truncate #=> 1 - * 1.truncate(2) #=> 1 - * 18.truncate(-1) #=> 10 - * (-18).truncate(-1) #=> -10 + * 555.truncate # => 555 + * 555.truncate(50) # => 555 + * + * Related: Integer#round. + * */ static VALUE @@ -5398,32 +5929,36 @@ DEFINE_INT_SQRT(BDIGIT, rb_bdigit_dbl, BDIGIT_DBL) #define domain_error(msg) \ rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg) -VALUE rb_big_isqrt(VALUE); - /* - * Document-method: Integer::sqrt * call-seq: - * Integer.sqrt(n) -> integer + * Integer.sqrt(numeric) -> integer * * Returns the integer square root of the non-negative integer +n+, - * i.e. the largest non-negative integer less than or equal to the - * square root of +n+. + * which is the largest non-negative integer less than or equal to the + * square root of +numeric+. + * + * Integer.sqrt(0) # => 0 + * Integer.sqrt(1) # => 1 + * Integer.sqrt(24) # => 4 + * Integer.sqrt(25) # => 5 + * Integer.sqrt(10**400) # => 10**200 * - * Integer.sqrt(0) #=> 0 - * Integer.sqrt(1) #=> 1 - * Integer.sqrt(24) #=> 4 - * Integer.sqrt(25) #=> 5 - * Integer.sqrt(10**400) #=> 10**200 + * If +numeric+ is not an \Integer, it is converted to an \Integer: * - * Equivalent to Math.sqrt(n).floor, except that - * the result of the latter code may differ from the true value + * Integer.sqrt(Complex(4, 0)) # => 2 + * Integer.sqrt(Rational(4, 1)) # => 2 + * Integer.sqrt(4.0) # => 2 + * Integer.sqrt(3.14159) # => 1 + * + * This method is equivalent to Math.sqrt(numeric).floor, + * except that the result of the latter code may differ from the true value * due to the limited precision of floating point arithmetic. * - * Integer.sqrt(10**46) #=> 100000000000000000000000 - * Math.sqrt(10**46).floor #=> 99999999999999991611392 (!) + * Integer.sqrt(10**46) # => 100000000000000000000000 + * Math.sqrt(10**46).floor # => 99999999999999991611392 + * + * Raises an exception if +numeric+ is negative. * - * If +n+ is not an Integer, it is converted to an Integer first. - * If +n+ is negative, a Math::DomainError is raised. */ static VALUE @@ -5458,6 +5993,13 @@ rb_int_s_isqrt(VALUE self, VALUE num) } } +/* :nodoc: */ +static VALUE +int_s_try_convert(VALUE self, VALUE num) +{ + return rb_check_integer_type(num); +} + /* * Document-class: ZeroDivisionError * @@ -5552,20 +6094,97 @@ rb_int_s_isqrt(VALUE self, VALUE num) * tally = Tally.new('||') * puts tally * 2 #=> "||||" * puts tally > 1 #=> true + * + * == What's Here + * + * First, what's elsewhere. \Class \Numeric: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here]. + * + * Here, class \Numeric provides methods for: + * + * - {Querying}[#class-Numeric-label-Querying] + * - {Comparing}[#class-Numeric-label-Comparing] + * - {Converting}[#class-Numeric-label-Converting] + * - {Other}[#class-Numeric-label-Other] + * + * === Querying + * + * - #finite?:: Returns true unless +self+ is infinite or not a number. + * - #infinite?:: Returns -1, +nil+ or +1, depending on whether +self+ + * is -Infinity, finite, or +Infinity. + * - #integer?:: Returns whether +self+ is an integer. + * - #negative?:: Returns whether +self+ is negative. + * - #nonzero?:: Returns whether +self+ is not zero. + * - #positive?:: Returns whether +self+ is positive. + * - #real?:: Returns whether +self+ is a real value. + * - #zero?:: Returns whether +self+ is zero. + * + * === Comparing + * + * - {<=>}[#method-i-3C-3D-3E]:: Returns: + * - -1 if +self+ is less than the given value. + * - 0 if +self+ is equal to the given value. + * - 1 if +self+ is greater than the given value. + * - +nil+ if +self+ and the given value are not comparable. + * - #eql?:: Returns whether +self+ and the given value have the same value and type. + * + * === Converting + * + * - #% (aliased as #modulo):: Returns the remainder of +self+ divided by the given value. + * - #-@:: Returns the value of +self+, negated. + * - #abs (aliased as #magnitude):: Returns the absolute value of +self+. + * - #abs2:: Returns the square of +self+. + * - #angle (aliased as #arg and #phase):: Returns 0 if +self+ is positive, + * Math::PI otherwise. + * - #ceil:: Returns the smallest number greater than or equal to +self+, + * to a given precision. + * - #coerce:: Returns array [coerced_self, coerced_other] + * for the given other value. + * - #conj (aliased as #conjugate):: Returns the complex conjugate of +self+. + * - #denominator:: Returns the denominator (always positive) + * of the Rational representation of +self+. + * - #div:: Returns the value of +self+ divided by the given value + * and converted to an integer. + * - #divmod:: Returns array [quotient, modulus] resulting + * from dividing +self+ the given divisor. + * - #fdiv:: Returns the Float result of dividing +self+ by the given divisor. + * - #floor:: Returns the largest number less than or equal to +self+, + * to a given precision. + * - #i:: Returns the Complex object Complex(0, self). + * the given value. + * - #imaginary (aliased as #imag):: Returns the imaginary part of the +self+. + * - #numerator:: Returns the numerator of the Rational representation of +self+; + * has the same sign as +self+. + * - #polar:: Returns the array [self.abs, self.arg]. + * - #quo:: Returns the value of +self+ divided by the given value. + * - #real:: Returns the real part of +self+. + * - #rect (aliased as #rectangular):: Returns the array [self, 0]. + * - #remainder:: Returns self-arg*(self/arg).truncate for the given +arg+. + * - #round:: Returns the value of +self+ rounded to the nearest value + * for the given a precision. + * - #to_c:: Returns the Complex representation of +self+. + * - #to_int:: Returns the Integer representation of +self+, truncating if necessary. + * - #truncate:: Returns +self+ truncated (toward zero) to a given precision. + * + * === Other + * + * - #clone:: Returns +self+; does not allow freezing. + * - #dup (aliased as #+@):: Returns +self+. + * - #step:: Invokes the given block with the sequence of specified numbers. + * */ void Init_Numeric(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - #ifdef _UNICOSMP /* Turn off floating point exceptions for divide by zero, etc. */ _set_Creg(0, 0); #endif - id_coerce = rb_intern("coerce"); - id_to = rb_intern("to"); - id_by = rb_intern("by"); + id_coerce = rb_intern_const("coerce"); + id_to = rb_intern_const("to"); + id_by = rb_intern_const("by"); rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError); rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError); @@ -5592,12 +6211,8 @@ Init_Numeric(void) rb_define_method(rb_cNumeric, "magnitude", num_abs, 0); rb_define_method(rb_cNumeric, "to_int", num_to_int, 0); - rb_define_method(rb_cNumeric, "real?", num_real_p, 0); - rb_define_method(rb_cNumeric, "integer?", num_int_p, 0); rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0); rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0); - rb_define_method(rb_cNumeric, "finite?", num_finite_p, 0); - rb_define_method(rb_cNumeric, "infinite?", num_infinite_p, 0); rb_define_method(rb_cNumeric, "floor", num_floor, -1); rb_define_method(rb_cNumeric, "ceil", num_ceil, -1); @@ -5611,12 +6226,10 @@ Init_Numeric(void) rb_undef_alloc_func(rb_cInteger); rb_undef_method(CLASS_OF(rb_cInteger), "new"); rb_define_singleton_method(rb_cInteger, "sqrt", rb_int_s_isqrt, 1); + rb_define_singleton_method(rb_cInteger, "try_convert", int_s_try_convert, 1); - rb_define_method(rb_cInteger, "to_s", int_to_s, -1); + rb_define_method(rb_cInteger, "to_s", rb_int_to_s, -1); rb_define_alias(rb_cInteger, "inspect", "to_s"); - rb_define_method(rb_cInteger, "integer?", int_int_p, 0); - rb_define_method(rb_cInteger, "odd?", rb_int_odd_p, 0); - rb_define_method(rb_cInteger, "even?", int_even_p, 0); rb_define_method(rb_cInteger, "allbits?", int_allbits_p, 1); rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1); rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1); @@ -5627,9 +6240,6 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "next", int_succ, 0); rb_define_method(rb_cInteger, "pred", int_pred, 0); rb_define_method(rb_cInteger, "chr", int_chr, -1); - rb_define_method(rb_cInteger, "ord", int_ord, 0); - rb_define_method(rb_cInteger, "to_i", int_to_i, 0); - rb_define_method(rb_cInteger, "to_int", int_to_i, 0); rb_define_method(rb_cInteger, "to_f", int_to_f, 0); rb_define_method(rb_cInteger, "floor", int_floor, -1); rb_define_method(rb_cInteger, "ceil", int_ceil, -1); @@ -5637,7 +6247,6 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "round", int_round, -1); rb_define_method(rb_cInteger, "<=>", rb_int_cmp, 1); - rb_define_method(rb_cInteger, "-@", rb_int_uminus, 0); rb_define_method(rb_cInteger, "+", rb_int_plus, 1); rb_define_method(rb_cInteger, "-", rb_int_minus, 1); rb_define_method(rb_cInteger, "*", rb_int_mul, 1); @@ -5652,9 +6261,6 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "pow", rb_int_powm, -1); /* in bignum.c */ - rb_define_method(rb_cInteger, "abs", rb_int_abs, 0); - rb_define_method(rb_cInteger, "magnitude", rb_int_abs, 0); - rb_define_method(rb_cInteger, "===", rb_int_equal, 1); rb_define_method(rb_cInteger, "==", rb_int_equal, 1); rb_define_method(rb_cInteger, ">", rb_int_gt, 1); @@ -5662,7 +6268,6 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "<", int_lt, 1); rb_define_method(rb_cInteger, "<=", int_le, 1); - rb_define_method(rb_cInteger, "~", int_comp, 0); rb_define_method(rb_cInteger, "&", rb_int_and, 1); rb_define_method(rb_cInteger, "|", int_or, 1); rb_define_method(rb_cInteger, "^", int_xor, 1); @@ -5671,13 +6276,22 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "<<", rb_int_lshift, 1); rb_define_method(rb_cInteger, ">>", rb_int_rshift, 1); - rb_define_method(rb_cInteger, "size", int_size, 0); - rb_define_method(rb_cInteger, "bit_length", rb_int_bit_length, 0); rb_define_method(rb_cInteger, "digits", rb_int_digits, -1); -#ifndef RUBY_INTEGER_UNIFICATION - rb_cFixnum = rb_cInteger; -#endif + rb_fix_to_s_static[0] = rb_fstring_literal("0"); + rb_fix_to_s_static[1] = rb_fstring_literal("1"); + rb_fix_to_s_static[2] = rb_fstring_literal("2"); + rb_fix_to_s_static[3] = rb_fstring_literal("3"); + rb_fix_to_s_static[4] = rb_fstring_literal("4"); + rb_fix_to_s_static[5] = rb_fstring_literal("5"); + rb_fix_to_s_static[6] = rb_fstring_literal("6"); + rb_fix_to_s_static[7] = rb_fstring_literal("7"); + rb_fix_to_s_static[8] = rb_fstring_literal("8"); + rb_fix_to_s_static[9] = rb_fstring_literal("9"); + for(int i = 0; i < 10; i++) { + rb_gc_register_mark_object(rb_fix_to_s_static[i]); + } + /* An obsolete class, use Integer */ rb_define_const(rb_cObject, "Fixnum", rb_cInteger); rb_deprecate_constant(rb_cObject, "Fixnum"); @@ -5687,23 +6301,6 @@ Init_Numeric(void) rb_undef_alloc_func(rb_cFloat); rb_undef_method(CLASS_OF(rb_cFloat), "new"); - /* - * Deprecated, do not use. - * - * Represents the rounding mode for floating point addition at the start time. - * - * Usually defaults to 1, rounding to the nearest number. - * - * Other modes include: - * - * -1:: Indeterminable - * 0:: Rounding towards zero - * 1:: Rounding to the nearest number - * 2:: Rounding towards positive infinity - * 3:: Rounding towards negative infinity - */ - rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS)); - rb_deprecate_constant(rb_cFloat, "ROUNDS"); /* * The base of the floating point, or number of unique digits used to * represent the number. @@ -5788,9 +6385,8 @@ Init_Numeric(void) rb_define_method(rb_cFloat, "to_s", flo_to_s, 0); rb_define_alias(rb_cFloat, "inspect", "to_s"); rb_define_method(rb_cFloat, "coerce", flo_coerce, 1); - rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0); rb_define_method(rb_cFloat, "+", rb_float_plus, 1); - rb_define_method(rb_cFloat, "-", flo_minus, 1); + rb_define_method(rb_cFloat, "-", rb_float_minus, 1); rb_define_method(rb_cFloat, "*", rb_float_mul, 1); rb_define_method(rb_cFloat, "/", rb_float_div, 1); rb_define_method(rb_cFloat, "quo", flo_quo, 1); @@ -5808,10 +6404,6 @@ Init_Numeric(void) rb_define_method(rb_cFloat, "<=", flo_le, 1); rb_define_method(rb_cFloat, "eql?", flo_eql, 1); rb_define_method(rb_cFloat, "hash", flo_hash, 0); - rb_define_method(rb_cFloat, "to_f", flo_to_f, 0); - rb_define_method(rb_cFloat, "abs", rb_float_abs, 0); - rb_define_method(rb_cFloat, "magnitude", rb_float_abs, 0); - rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0); rb_define_method(rb_cFloat, "to_i", flo_to_i, 0); rb_define_method(rb_cFloat, "to_int", flo_to_i, 0); @@ -5825,8 +6417,6 @@ Init_Numeric(void) rb_define_method(rb_cFloat, "finite?", rb_flo_is_finite_p, 0); rb_define_method(rb_cFloat, "next_float", flo_next_float, 0); rb_define_method(rb_cFloat, "prev_float", flo_prev_float, 0); - rb_define_method(rb_cFloat, "positive?", flo_positive_p, 0); - rb_define_method(rb_cFloat, "negative?", flo_negative_p, 0); } #undef rb_float_value @@ -5842,3 +6432,5 @@ rb_float_new(double d) { return rb_float_new_inline(d); } + +#include "numeric.rbinc" diff --git a/ruby/numeric.rb b/ruby/numeric.rb new file mode 100644 index 000000000..9f2200d2a --- /dev/null +++ b/ruby/numeric.rb @@ -0,0 +1,332 @@ +class Numeric + # + # call-seq: + # num.real? -> true or false + # + # Returns +true+ if +num+ is a real number (i.e. not Complex). + # + def real? + return true + end + + # + # call-seq: + # num.integer? -> true or false + # + # Returns +true+ if +num+ is an Integer. + # + # 1.0.integer? #=> false + # 1.integer? #=> true + # + def integer? + return false + end + + # + # call-seq: + # num.finite? -> true or false + # + # Returns +true+ if +num+ is a finite number, otherwise returns +false+. + # + def finite? + return true + end + + # + # call-seq: + # num.infinite? -> -1, 1, or nil + # + # Returns +nil+, -1, or 1 depending on whether the value is + # finite, -Infinity, or +Infinity. + # + def infinite? + return nil + end +end + +class Integer + # call-seq: + # -int -> integer + # + # Returns +int+, negated. + def -@ + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_uminus(self)' + end + + # call-seq: + # ~int -> integer + # + # One's complement: returns a number where each bit is flipped. + # + # Inverts the bits in an Integer. As integers are conceptually of + # infinite length, the result acts as if it had an infinite number of + # one bits to the left. In hex representations, this is displayed + # as two periods to the left of the digits. + # + # sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA" + def ~ + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_comp(self)' + end + + # call-seq: + # int.abs -> integer + # int.magnitude -> integer + # + # Returns the absolute value of +int+. + # + # (-12345).abs #=> 12345 + # -12345.abs #=> 12345 + # 12345.abs #=> 12345 + # + # Integer#magnitude is an alias for Integer#abs. + def abs + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_abs(self)' + end + + # call-seq: + # int.bit_length -> integer + # + # Returns the number of bits of the value of +int+. + # + # "Number of bits" means the bit position of the highest bit + # which is different from the sign bit + # (where the least significant bit has bit position 1). + # If there is no such bit (zero or minus one), zero is returned. + # + # I.e. this method returns ceil(log2(int < 0 ? -int : int+1)). + # + # (-2**1000-1).bit_length #=> 1001 + # (-2**1000).bit_length #=> 1000 + # (-2**1000+1).bit_length #=> 1000 + # (-2**12-1).bit_length #=> 13 + # (-2**12).bit_length #=> 12 + # (-2**12+1).bit_length #=> 12 + # -0x101.bit_length #=> 9 + # -0x100.bit_length #=> 8 + # -0xff.bit_length #=> 8 + # -2.bit_length #=> 1 + # -1.bit_length #=> 0 + # 0.bit_length #=> 0 + # 1.bit_length #=> 1 + # 0xff.bit_length #=> 8 + # 0x100.bit_length #=> 9 + # (2**12-1).bit_length #=> 12 + # (2**12).bit_length #=> 13 + # (2**12+1).bit_length #=> 13 + # (2**1000-1).bit_length #=> 1000 + # (2**1000).bit_length #=> 1001 + # (2**1000+1).bit_length #=> 1001 + # + # This method can be used to detect overflow in Array#pack as follows: + # + # if n.bit_length < 32 + # [n].pack("l") # no overflow + # else + # raise "overflow" + # end + def bit_length + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_bit_length(self)' + end + + # call-seq: + # int.even? -> true or false + # + # Returns +true+ if +int+ is an even number. + def even? + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_even_p(self)' + end + + # call-seq: + # int.integer? -> true + # + # Since +int+ is already an Integer, this always returns +true+. + def integer? + return true + end + + alias magnitude abs +=begin + def magnitude + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_abs(self)' + end +=end + + # call-seq: + # int.odd? -> true or false + # + # Returns +true+ if +int+ is an odd number. + def odd? + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_odd_p(self)' + end + + # call-seq: + # int.ord -> self + # + # Returns the +int+ itself. + # + # 97.ord #=> 97 + # + # This method is intended for compatibility to character literals + # in Ruby 1.9. + # + # For example, ?a.ord returns 97 both in 1.8 and 1.9. + def ord + return self + end + + # + # Document-method: Integer#size + # call-seq: + # int.size -> int + # + # Returns the number of bytes in the machine representation of +int+ + # (machine dependent). + # + # 1.size #=> 8 + # -1.size #=> 8 + # 2147483647.size #=> 8 + # (256**10 - 1).size #=> 10 + # (256**20 - 1).size #=> 20 + # (256**40 - 1).size #=> 40 + # + def size + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_size(self)' + end + + # call-seq: + # int.to_i -> integer + # + # Since +int+ is already an Integer, returns +self+. + # + # #to_int is an alias for #to_i. + def to_i + return self + end + + # call-seq: + # int.to_int -> integer + # + # Since +int+ is already an Integer, returns +self+. + def to_int + return self + end + + # call-seq: + # int.zero? -> true or false + # + # Returns +true+ if +int+ has a zero value. + def zero? + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_int_zero_p(self)' + end +end + +# call-seq: +# Integer.try_convert(object) -> object, integer, or nil +# +# If +object+ is an \Integer object, returns +object+. +# Integer.try_convert(1) # => 1 +# +# Otherwise if +object+ responds to :to_int, +# calls object.to_int and returns the result. +# Integer.try_convert(1.25) # => 1 +# +# Returns +nil+ if +object+ does not respond to :to_int +# Integer.try_convert([]) # => nil +# +# Raises an exception unless object.to_int returns an \Integer object. +# +def Integer.try_convert(num) +=begin + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_check_integer_type(num)' +=end +end if false + +class Float + # + # call-seq: + # float.to_f -> self + # + # Since +float+ is already a Float, returns +self+. + # + def to_f + return self + end + + # + # call-seq: + # float.abs -> float + # float.magnitude -> float + # + # Returns the absolute value of +float+. + # + # (-34.56).abs #=> 34.56 + # -34.56.abs #=> 34.56 + # 34.56.abs #=> 34.56 + # + # Float#magnitude is an alias for Float#abs. + # + def abs + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_float_abs(self)' + end + + def magnitude + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_float_abs(self)' + end + + # + # call-seq: + # -float -> float + # + # Returns +float+, negated. + # + def -@ + Primitive.attr! 'inline' + Primitive.cexpr! 'rb_float_uminus(self)' + end + + # + # call-seq: + # float.zero? -> true or false + # + # Returns +true+ if +float+ is 0.0. + # + def zero? + Primitive.attr! 'inline' + Primitive.cexpr! 'RBOOL(FLOAT_ZERO_P(self))' + end + + # + # call-seq: + # float.positive? -> true or false + # + # Returns +true+ if +float+ is greater than 0. + # + def positive? + Primitive.attr! 'inline' + Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) > 0.0)' + end + + # + # call-seq: + # float.negative? -> true or false + # + # Returns +true+ if +float+ is less than 0. + # + def negative? + Primitive.attr! 'inline' + Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) < 0.0)' + end + +end diff --git a/ruby/object.c b/ruby/object.c index 61be0d386..3b83c7d08 100644 --- a/ruby/object.c +++ b/ruby/object.c @@ -11,34 +11,50 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/st.h" -#include "ruby/util.h" -#include "internal.h" -#include -#include +#include "ruby/internal/config.h" + #include -#include +#include #include +#include +#include + #include "constant.h" #include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/class.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/inits.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/struct.h" +#include "internal/string.h" +#include "internal/symbol.h" +#include "internal/variable.h" #include "probes.h" +#include "ruby/encoding.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "ruby/assert.h" +#include "builtin.h" /*! - * \defgroup object Core objects and their operations + * \addtogroup object * \{ */ -VALUE rb_cBasicObject; /*!< BasicObject class */ -VALUE rb_mKernel; /*!< Kernel module */ -VALUE rb_cObject; /*!< Object class */ -VALUE rb_cModule; /*!< Module class */ -VALUE rb_cClass; /*!< Class class */ -VALUE rb_cData; /*!< Data class */ +VALUE rb_cBasicObject; +VALUE rb_mKernel; +VALUE rb_cObject; +VALUE rb_cModule; +VALUE rb_cClass; +VALUE rb_cRefinement; -VALUE rb_cNilClass; /*!< NilClass class */ -VALUE rb_cTrueClass; /*!< TrueClass class */ -VALUE rb_cFalseClass; /*!< FalseClass class */ +VALUE rb_cNilClass; +VALUE rb_cTrueClass; +VALUE rb_cFalseClass; static VALUE rb_cNilClass_to_s; static VALUE rb_cTrueClass_to_s; @@ -62,18 +78,6 @@ static VALUE rb_cFalseClass_to_s; /*! \endcond */ -/*! - * Make the object invisible from Ruby code. - * - * It is useful to let Ruby's GC manage your internal data structure -- - * The object keeps being managed by GC, but \c ObjectSpace.each_object - * never yields the object. - * - * Note that the object also lose a way to call a method on it. - * - * \param[in] obj a Ruby object - * \sa rb_obj_reveal - */ VALUE rb_obj_hide(VALUE obj) { @@ -83,14 +87,6 @@ rb_obj_hide(VALUE obj) return obj; } -/*! - * Make a hidden object visible again. - * - * It is the caller's responsibility to pass the right \a klass - * which \a obj originally used to belong to. - * - * \sa rb_obj_hide - */ VALUE rb_obj_reveal(VALUE obj, VALUE klass) { @@ -100,14 +96,6 @@ rb_obj_reveal(VALUE obj, VALUE klass) return obj; } -/*! - * Fills common (\c RBasic) fields in \a obj. - * - * \note Prefer rb_newobj_of() to this function. - * \param[in,out] obj a Ruby object to be set up. - * \param[in] klass \c obj will belong to this class. - * \param[in] type one of \c ruby_value_type - */ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type) { @@ -123,10 +111,10 @@ rb_obj_setup(VALUE obj, VALUE klass, VALUE type) * Case Equality -- For class Object, effectively the same as calling * #==, but typically overridden by descendants to provide * meaningful semantics in +case+ statements. - *-- - * Same as \c Object#===, case equality. - *++ */ +#define case_equal rb_equal + /* The default implementation of #=== is + * to call #== with the rb_equal() optimization. */ VALUE rb_equal(VALUE obj1, VALUE obj2) @@ -138,19 +126,9 @@ rb_equal(VALUE obj1, VALUE obj2) if (result == Qundef) { result = rb_funcall(obj1, id_eq, 1, obj2); } - if (RTEST(result)) return Qtrue; - return Qfalse; + return RBOOL(RTEST(result)); } -/** - * Determines if \a obj1 and \a obj2 are equal in terms of - * \c Object#eql?. - * - * \note It actually calls \c #eql? when necessary. - * So you cannot implement \c #eql? with this function. - * \retval non-zero if they are eql? - * \retval zero if they are not eql?. - */ int rb_eql(VALUE obj1, VALUE obj2) { @@ -161,8 +139,7 @@ rb_eql(VALUE obj1, VALUE obj2) if (result == Qundef) { result = rb_funcall(obj1, id_eql, 1, obj2); } - if (RTEST(result)) return Qtrue; - return Qfalse; + return RBOOL(RTEST(result)); } /** @@ -209,8 +186,7 @@ rb_eql(VALUE obj1, VALUE obj2) MJIT_FUNC_EXPORTED VALUE rb_obj_equal(VALUE obj1, VALUE obj2) { - if (obj1 == obj2) return Qtrue; - return Qfalse; + return RBOOL(obj1 == obj2); } VALUE rb_obj_hash(VALUE obj); @@ -248,14 +224,6 @@ rb_obj_not_equal(VALUE obj1, VALUE obj2) return RTEST(result) ? Qfalse : Qtrue; } -/*! - * Looks up the nearest ancestor of \a cl, skipping singleton classes or - * module inclusions. - * It returns the \a cl itself if it is neither a singleton class or a module. - * - * \param[in] cl a Class object. - * \return the ancestor class found, or a falsey value if nothing found. - */ VALUE rb_class_real(VALUE cl) { @@ -266,22 +234,6 @@ rb_class_real(VALUE cl) return cl; } -/** - * call-seq: - * obj.class -> class - * - * Returns the class of obj. This method must always be called - * with an explicit receiver, as #class is also a reserved word in - * Ruby. - * - * 1.class #=> Integer - * self.class #=> Object - *-- - * Equivalent to \c Object\#class in Ruby. - * - * Returns the class of \c obj, skipping singleton classes or module inclusions. - *++ - */ VALUE rb_obj_class(VALUE obj) { @@ -315,28 +267,33 @@ rb_obj_singleton_class(VALUE obj) MJIT_FUNC_EXPORTED void rb_obj_copy_ivar(VALUE dest, VALUE obj) { - if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) { - xfree(ROBJECT_IVPTR(dest)); - ROBJECT(dest)->as.heap.ivptr = 0; - ROBJECT(dest)->as.heap.numiv = 0; - ROBJECT(dest)->as.heap.iv_index_tbl = 0; - } + VALUE *dst_buf = 0; + VALUE *src_buf = 0; + uint32_t len = ROBJECT_EMBED_LEN_MAX; + if (RBASIC(obj)->flags & ROBJECT_EMBED) { - MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX); - RBASIC(dest)->flags |= ROBJECT_EMBED; + src_buf = ROBJECT(obj)->as.ary; + + // embedded -> embedded + if (RBASIC(dest)->flags & ROBJECT_EMBED) { + dst_buf = ROBJECT(dest)->as.ary; + } + // embedded -> extended + else { + dst_buf = ROBJECT(dest)->as.heap.ivptr; + } } + // extended -> extended else { - uint32_t len = ROBJECT(obj)->as.heap.numiv; - VALUE *ptr = 0; - if (len > 0) { - ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, ROBJECT(obj)->as.heap.ivptr, VALUE, len); - } - ROBJECT(dest)->as.heap.ivptr = ptr; - ROBJECT(dest)->as.heap.numiv = len; - ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl; - RBASIC(dest)->flags &= ~ROBJECT_EMBED; + uint32_t src_len = ROBJECT(obj)->as.heap.numiv; + uint32_t dst_len = ROBJECT(dest)->as.heap.numiv; + + len = src_len < dst_len ? src_len : dst_len; + dst_buf = ROBJECT(dest)->as.heap.ivptr; + src_buf = ROBJECT(obj)->as.heap.ivptr; } + + MEMCPY(dst_buf, src_buf, VALUE, len); } static void @@ -355,9 +312,8 @@ init_copy(VALUE dest, VALUE obj) } } -static int freeze_opt(int argc, VALUE *argv); -static VALUE immutable_obj_clone(VALUE obj, int kwfreeze); -static VALUE mutable_obj_clone(VALUE obj, int kwfreeze); +static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze); +static VALUE mutable_obj_clone(VALUE obj, VALUE kwfreeze); PUREFUNC(static inline int special_object_p(VALUE obj)); /*!< \private */ static inline int special_object_p(VALUE obj) @@ -376,35 +332,25 @@ special_object_p(VALUE obj) } } -/* - * call-seq: - * obj.clone(freeze: true) -> an_object - * - * Produces a shallow copy of obj---the instance variables of - * obj are copied, but not the objects they reference. - * #clone copies the frozen (unless +:freeze+ keyword argument is - * given with a false value) state of obj. See - * also the discussion under Object#dup. - * - * class Klass - * attr_accessor :str - * end - * s1 = Klass.new #=> # - * s1.str = "Hello" #=> "Hello" - * s2 = s1.clone #=> # - * s2.str[1,4] = "i" #=> "i" - * s1.inspect #=> "#" - * s2.inspect #=> "#" - * - * This method may have class-specific behavior. If so, that - * behavior will be documented under the #+initialize_copy+ method of - * the class. - */ +static VALUE +obj_freeze_opt(VALUE freeze) +{ + switch (freeze) { + case Qfalse: + case Qtrue: + case Qnil: + break; + default: + rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE, rb_obj_class(freeze)); + } + + return freeze; +} static VALUE -rb_obj_clone2(int argc, VALUE *argv, VALUE obj) +rb_obj_clone2(rb_execution_context_t *ec, VALUE obj, VALUE freeze) { - int kwfreeze = freeze_opt(argc, argv); + VALUE kwfreeze = obj_freeze_opt(freeze); if (!special_object_p(obj)) return mutable_obj_clone(obj, kwfreeze); return immutable_obj_clone(obj, kwfreeze); @@ -414,16 +360,16 @@ rb_obj_clone2(int argc, VALUE *argv, VALUE obj) VALUE rb_immutable_obj_clone(int argc, VALUE *argv, VALUE obj) { - int kwfreeze = freeze_opt(argc, argv); + VALUE kwfreeze = rb_get_freeze_opt(argc, argv); return immutable_obj_clone(obj, kwfreeze); } -static int -freeze_opt(int argc, VALUE *argv) +VALUE +rb_get_freeze_opt(int argc, VALUE *argv) { static ID keyword_ids[1]; VALUE opt; - VALUE kwfreeze; + VALUE kwfreeze = Qnil; if (!keyword_ids[0]) { CONST_ID(keyword_ids[0], "freeze"); @@ -431,28 +377,26 @@ freeze_opt(int argc, VALUE *argv) rb_scan_args(argc, argv, "0:", &opt); if (!NIL_P(opt)) { rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze); - if (kwfreeze == Qfalse) return FALSE; - if (kwfreeze != Qundef && kwfreeze != Qtrue) { - rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE, - rb_obj_class(kwfreeze)); - } + if (kwfreeze != Qundef) + kwfreeze = obj_freeze_opt(kwfreeze); } - return TRUE; + return kwfreeze; } static VALUE -immutable_obj_clone(VALUE obj, int kwfreeze) +immutable_obj_clone(VALUE obj, VALUE kwfreeze) { - if (!kwfreeze) + if (kwfreeze == Qfalse) rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE, rb_obj_class(obj)); return obj; } static VALUE -mutable_obj_clone(VALUE obj, int kwfreeze) +mutable_obj_clone(VALUE obj, VALUE kwfreeze) { VALUE clone, singleton; + VALUE argv[2]; clone = rb_obj_alloc(rb_obj_class(obj)); @@ -463,29 +407,58 @@ mutable_obj_clone(VALUE obj, int kwfreeze) } init_copy(clone, obj); - rb_funcall(clone, id_init_clone, 1, obj); - if (kwfreeze) { + switch (kwfreeze) { + case Qnil: + rb_funcall(clone, id_init_clone, 1, obj); RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE; + break; + case Qtrue: + { + static VALUE freeze_true_hash; + if (!freeze_true_hash) { + freeze_true_hash = rb_hash_new(); + rb_gc_register_mark_object(freeze_true_hash); + rb_hash_aset(freeze_true_hash, ID2SYM(idFreeze), Qtrue); + rb_obj_freeze(freeze_true_hash); + } + + argv[0] = obj; + argv[1] = freeze_true_hash; + rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS); + RBASIC(clone)->flags |= FL_FREEZE; + break; + } + case Qfalse: + { + static VALUE freeze_false_hash; + if (!freeze_false_hash) { + freeze_false_hash = rb_hash_new(); + rb_gc_register_mark_object(freeze_false_hash); + rb_hash_aset(freeze_false_hash, ID2SYM(idFreeze), Qfalse); + rb_obj_freeze(freeze_false_hash); + } + + argv[0] = obj; + argv[1] = freeze_false_hash; + rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS); + break; + } + default: + rb_bug("invalid kwfreeze passed to mutable_obj_clone"); } return clone; } -/** - * :nodoc - *-- - * Almost same as \c Object#clone - *++ - */ VALUE rb_obj_clone(VALUE obj) { if (special_object_p(obj)) return obj; - return mutable_obj_clone(obj, Qtrue); + return mutable_obj_clone(obj, Qnil); } -/** +/* * call-seq: * obj.dup -> an_object * @@ -518,14 +491,11 @@ rb_obj_clone(VALUE obj) * s1.extend(Foo) #=> # * s1.foo #=> "foo" * - * s2 = s1.clone #=> # + * s2 = s1.clone #=> # * s2.foo #=> "foo" * - * s3 = s1.dup #=> # - * s3.foo #=> NoMethodError: undefined method `foo' for # - *-- - * Equivalent to \c Object\#dup in Ruby - *++ + * s3 = s1.dup #=> # + * s3.foo #=> NoMethodError: undefined method `foo' for # */ VALUE rb_obj_dup(VALUE obj) @@ -559,47 +529,16 @@ rb_obj_itself(VALUE obj) return obj; } -static VALUE +VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj) { return LONG2FIX(1); } -/* - * call-seq: - * obj.then {|x| block } -> an_object - * obj.yield_self {|x| block } -> an_object - * - * Yields self to the block and returns the result of the block. - * - * 3.next.then {|x| x**x }.to_s #=> "256" - * "my string".yield_self {|s| s.upcase } #=> "MY STRING" - * - * Good usage for +then+ is value piping in method chains: - * - * require 'open-uri' - * require 'json' - * - * construct_url(arguments). - * then {|url| open(url).read }. - * then {|response| JSON.parse(response) } - * - * When called without block, the method returns +Enumerator+, - * which can be used, for example, for conditional - * circuit-breaking: - * - * # meets condition, no-op - * 1.then.detect(&:odd?) # => 1 - * # does not meet condition, drop value - * 2.then.detect(&:odd?) # => nil - * - */ - static VALUE -rb_obj_yield_self(VALUE obj) +block_given_p(rb_execution_context_t *ec, VALUE self) { - RETURN_SIZED_ENUMERATOR(obj, 0, 0, rb_obj_size); - return rb_yield_values2(1, &obj); + return RBOOL(rb_block_given_p()); } /** @@ -624,10 +563,10 @@ rb_obj_init_copy(VALUE obj, VALUE orig) /*! * :nodoc: *-- - * Default implementation of \c #initialize_dup and \c #initialize_clone + * Default implementation of \c #initialize_dup * * \param[in,out] obj the receiver being initialized - * \param[in] orig the object to be dup or cloned from. + * \param[in] orig the object to be dup from. *++ **/ VALUE @@ -637,7 +576,29 @@ rb_obj_init_dup_clone(VALUE obj, VALUE orig) return obj; } -/** +/*! + * :nodoc: + *-- + * Default implementation of \c #initialize_clone + * + * \param[in] The number of arguments + * \param[in] The array of arguments + * \param[in] obj the receiver being initialized + *++ + **/ +static VALUE +rb_obj_init_clone(int argc, VALUE *argv, VALUE obj) +{ + VALUE orig, opts; + if (rb_scan_args(argc, argv, "1:", &orig, &opts) < argc) { + /* Ignore a freeze keyword */ + rb_get_freeze_opt(1, &opts); + } + rb_funcall(obj, id_init_copy, 1, orig); + return obj; +} + +/* * call-seq: * obj.to_s -> string * @@ -646,9 +607,6 @@ rb_obj_init_dup_clone(VALUE obj, VALUE orig) * case, the top-level object that is the initial execution context * of Ruby programs returns ``main''. * - *-- - * Default implementation of \c #to_s. - *++ */ VALUE rb_any_to_s(VALUE obj) @@ -661,19 +619,6 @@ rb_any_to_s(VALUE obj) return str; } -VALUE rb_str_escape(VALUE str); -/*! - * Convenient wrapper of \c Object#inspect. - * Returns a human-readable string representation of \a obj, - * similarly to \c Object#inspect. - * - * Unlike Ruby-level \c #inspect, it escapes characters to keep the - * result compatible to the default internal or external encoding. - * If the default internal or external encoding is ASCII compatible, - * the encoding of the inspected result must be compatible with it. - * If the default internal or external encoding is ASCII incompatible, - * the result must be ASCII only. - */ VALUE rb_inspect(VALUE obj) { @@ -735,7 +680,7 @@ inspect_obj(VALUE obj, VALUE str, int recur) * * Returns a string containing a human-readable representation of obj. * The default #inspect shows the object's class name, an encoding of - * the object id, and a list of the instance variables and their + * its memory address, and a list of the instance variables and their * values (by calling #inspect on each of them). User defined classes * should override this method to provide a better representation of * obj. When overriding this method, it should return a string @@ -774,15 +719,13 @@ rb_obj_inspect(VALUE obj) static VALUE class_or_module_required(VALUE c) { - if (SPECIAL_CONST_P(c)) goto not_class; - switch (BUILTIN_TYPE(c)) { + switch (OBJ_BUILTIN_TYPE(c)) { case T_MODULE: case T_CLASS: case T_ICLASS: break; default: - not_class: rb_raise(rb_eTypeError, "class or module required"); } return c; @@ -790,7 +733,7 @@ class_or_module_required(VALUE c) static VALUE class_search_ancestor(VALUE cl, VALUE c); -/** +/* * call-seq: * obj.instance_of?(class) -> true or false * @@ -805,25 +748,17 @@ static VALUE class_search_ancestor(VALUE cl, VALUE c); * b.instance_of? A #=> false * b.instance_of? B #=> true * b.instance_of? C #=> false - *-- - * Determines if \a obj is an instance of \a c. - * - * Equivalent to \c Object\#is_instance_of in Ruby. - * \param[in] obj the object to be determined. - * \param[in] c a Class object - *++ */ VALUE rb_obj_is_instance_of(VALUE obj, VALUE c) { c = class_or_module_required(c); - if (rb_obj_class(obj) == c) return Qtrue; - return Qfalse; + return RBOOL(rb_obj_class(obj) == c); } -/** +/* * call-seq: * obj.is_a?(class) -> true or false * obj.kind_of?(class) -> true or false @@ -849,13 +784,6 @@ rb_obj_is_instance_of(VALUE obj, VALUE c) * b.kind_of? B #=> true * b.kind_of? C #=> false * b.kind_of? M #=> true - *-- - * Determines if \a obj is a kind of \a c. - * - * Equivalent to \c Object\#kind_of? in Ruby. - * \param[in] obj the object to be determined - * \param[in] c a Module object. - *++ */ VALUE @@ -863,8 +791,10 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) { VALUE cl = CLASS_OF(obj); + // Note: YJIT needs this function to never allocate and never raise when + // `c` is a class or a module. c = class_or_module_required(c); - return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse; + return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c))); } static VALUE @@ -887,31 +817,6 @@ rb_class_search_ancestor(VALUE cl, VALUE c) return class_search_ancestor(cl, RCLASS_ORIGIN(c)); } -/** - * call-seq: - * obj.tap {|x| block } -> obj - * - * Yields self to the block, and then returns self. - * The primary purpose of this method is to "tap into" a method chain, - * in order to perform operations on intermediate results within the chain. - * - * (1..10) .tap {|x| puts "original: #{x}" } - * .to_a .tap {|x| puts "array: #{x}" } - * .select {|x| x.even? } .tap {|x| puts "evens: #{x}" } - * .map {|x| x*x } .tap {|x| puts "squares: #{x}" } - * - *-- - * \private - *++ - */ - -VALUE -rb_obj_tap(VALUE obj) -{ - rb_yield(obj); - return obj; -} - /* * Document-method: inherited @@ -940,6 +845,7 @@ rb_obj_tap(VALUE obj) * New subclass: Bar * New subclass: Baz */ +#define rb_obj_class_inherited rb_obj_dummy1 /* Document-method: method_added * @@ -962,6 +868,7 @@ rb_obj_tap(VALUE obj) * Adding :some_instance_method * */ +#define rb_obj_mod_method_added rb_obj_dummy1 /* Document-method: method_removed * @@ -988,6 +895,34 @@ rb_obj_tap(VALUE obj) * Removing :some_instance_method * */ +#define rb_obj_mod_method_removed rb_obj_dummy1 + +/* Document-method: method_undefined + * + * call-seq: + * method_undefined(method_name) + * + * Invoked as a callback whenever an instance method is undefined from the + * receiver. + * + * module Chatty + * def self.method_undefined(method_name) + * puts "Undefining #{method_name.inspect}" + * end + * def self.some_class_method() end + * def some_instance_method() end + * class << self + * undef_method :some_class_method + * end + * undef_method :some_instance_method + * end + * + * produces: + * + * Undefining :some_instance_method + * + */ +#define rb_obj_mod_method_undefined rb_obj_dummy1 /* * Document-method: singleton_method_added @@ -1014,6 +949,7 @@ rb_obj_tap(VALUE obj) * Adding three * */ +#define rb_obj_singleton_method_added rb_obj_dummy1 /* * Document-method: singleton_method_removed @@ -1042,6 +978,7 @@ rb_obj_tap(VALUE obj) * Removing three * Removing one */ +#define rb_obj_singleton_method_removed rb_obj_dummy1 /* * Document-method: singleton_method_undefined @@ -1066,6 +1003,7 @@ rb_obj_tap(VALUE obj) * * Undefining one */ +#define rb_obj_singleton_method_undefined rb_obj_dummy1 /* * Document-method: extended @@ -1085,6 +1023,7 @@ rb_obj_tap(VALUE obj) * end * # => prints "A extended in Enumerable" */ +#define rb_obj_mod_extended rb_obj_dummy1 /* * Document-method: included @@ -1107,6 +1046,7 @@ rb_obj_tap(VALUE obj) * end * # => prints "A included in Enumerable" */ +#define rb_obj_mod_included rb_obj_dummy1 /* * Document-method: prepended @@ -1126,6 +1066,7 @@ rb_obj_tap(VALUE obj) * end * # => prints "A prepended to Enumerable" */ +#define rb_obj_mod_prepended rb_obj_dummy1 /* * Document-method: initialize @@ -1135,13 +1076,14 @@ rb_obj_tap(VALUE obj) * * Returns a new BasicObject. */ +#define rb_obj_initialize rb_obj_dummy0 /* * Not documented */ static VALUE -rb_obj_dummy() +rb_obj_dummy(void) { return Qnil; } @@ -1158,7 +1100,7 @@ rb_obj_dummy1(VALUE _x, VALUE _y) return rb_obj_dummy(); } -/** +/* * call-seq: * obj.tainted? -> false * @@ -1168,11 +1110,11 @@ rb_obj_dummy1(VALUE _x, VALUE _y) VALUE rb_obj_tainted(VALUE obj) { - rb_warning("Object#tainted? is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#tainted?", NULL); return Qfalse; } -/** +/* * call-seq: * obj.taint -> obj * @@ -1182,12 +1124,12 @@ rb_obj_tainted(VALUE obj) VALUE rb_obj_taint(VALUE obj) { - rb_warning("Object#taint is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#taint", NULL); return obj; } -/** +/* * call-seq: * obj.untaint -> obj * @@ -1197,11 +1139,11 @@ rb_obj_taint(VALUE obj) VALUE rb_obj_untaint(VALUE obj) { - rb_warning("Object#untaint is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#untaint", NULL); return obj; } -/** +/* * call-seq: * obj.untrusted? -> false * @@ -1211,11 +1153,11 @@ rb_obj_untaint(VALUE obj) VALUE rb_obj_untrusted(VALUE obj) { - rb_warning("Object#untrusted? is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#untrusted?", NULL); return Qfalse; } -/** +/* * call-seq: * obj.untrust -> obj * @@ -1225,12 +1167,12 @@ rb_obj_untrusted(VALUE obj) VALUE rb_obj_untrust(VALUE obj) { - rb_warning("Object#untrust is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#untrust", NULL); return obj; } -/** +/* * call-seq: * obj.trust -> obj * @@ -1240,26 +1182,22 @@ rb_obj_untrust(VALUE obj) VALUE rb_obj_trust(VALUE obj) { - rb_warning("Object#trust is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "Object#trust", NULL); return obj; } -/** - * Does nothing. This method is deprecated and will be removed in Ruby 3.2. - */ - void rb_obj_infect(VALUE victim, VALUE carrier) { - rb_warning("rb_obj_infect is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_obj_infect", NULL); } -/** +/* * call-seq: * obj.freeze -> obj * * Prevents further modifications to obj. A - * RuntimeError will be raised if modification is attempted. + * FrozenError will be raised if modification is attempted. * There is no way to unfreeze a frozen object. See also * Object#frozen?. * @@ -1276,11 +1214,6 @@ rb_obj_infect(VALUE victim, VALUE carrier) * * Objects of the following classes are always frozen: Integer, * Float, Symbol. - *-- - * Make the object unmodifiable. Equivalent to \c Object\#freeze in Ruby. - * \param[in,out] obj the object to be frozen - * \return the frozen object - *++ */ VALUE @@ -1295,27 +1228,10 @@ rb_obj_freeze(VALUE obj) return obj; } -/** - * call-seq: - * obj.frozen? -> true or false - * - * Returns the freeze status of obj. - * - * a = [ "a", "b", "c" ] - * a.freeze #=> ["a", "b", "c"] - * a.frozen? #=> true - *-- - * Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby. - * \param[in] obj the object to be determines - * \retval Qtrue if frozen - * \retval Qfalse if not frozen - *++ - */ - VALUE rb_obj_frozen_p(VALUE obj) { - return OBJ_FROZEN(obj) ? Qtrue : Qfalse; + return RBOOL(OBJ_FROZEN(obj)); } @@ -1325,37 +1241,6 @@ rb_obj_frozen_p(VALUE obj) * The class of the singleton object nil. */ -/* - * call-seq: - * nil.to_i -> 0 - * - * Always returns zero. - * - * nil.to_i #=> 0 - */ - - -static VALUE -nil_to_i(VALUE obj) -{ - return INT2FIX(0); -} - -/* - * call-seq: - * nil.to_f -> 0.0 - * - * Always returns zero. - * - * nil.to_f #=> 0.0 - */ - -static VALUE -nil_to_f(VALUE obj) -{ - return DBL2NUM(0.0); -} - /* * call-seq: * nil.to_s -> "" @@ -1363,8 +1248,8 @@ nil_to_f(VALUE obj) * Always returns the empty string. */ -static VALUE -nil_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_nil_to_s(VALUE obj) { return rb_cNilClass_to_s; } @@ -1446,8 +1331,8 @@ nil_match(VALUE obj1, VALUE obj2) * The string representation of true is "true". */ -static VALUE -true_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_true_to_s(VALUE obj) { return rb_cTrueClass_to_s; } @@ -1464,7 +1349,7 @@ true_to_s(VALUE obj) static VALUE true_and(VALUE obj, VALUE obj2) { - return RTEST(obj2)?Qtrue:Qfalse; + return RBOOL(RTEST(obj2)); } /* @@ -1523,8 +1408,8 @@ true_xor(VALUE obj, VALUE obj2) * The string representation of false is "false". */ -static VALUE -false_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_false_to_s(VALUE obj) { return rb_cFalseClass_to_s; } @@ -1555,13 +1440,7 @@ false_and(VALUE obj, VALUE obj2) * nil or false; true otherwise. */ -static VALUE -false_or(VALUE obj, VALUE obj2) -{ - return RTEST(obj2)?Qtrue:Qfalse; -} - - +#define false_or true_and /* * call-seq: @@ -1574,11 +1453,7 @@ false_or(VALUE obj, VALUE obj2) * */ -static VALUE -false_xor(VALUE obj, VALUE obj2) -{ - return RTEST(obj2)?Qtrue:Qfalse; -} +#define false_xor true_and /* * call-seq: @@ -1617,15 +1492,15 @@ rb_false(VALUE obj) * * This method is deprecated. * - * This is not only unuseful but also troublesome because it - * may hide a type error. + * This is not only useless but also troublesome because it may hide a + * type error. */ static VALUE rb_obj_match(VALUE obj1, VALUE obj2) { if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) { - rb_warn("deprecated Object#=~ is called on %"PRIsVALUE + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "deprecated Object#=~ is called on %"PRIsVALUE "; it always returns nil", rb_obj_class(obj1)); } return Qnil; @@ -1668,7 +1543,7 @@ rb_obj_not_match(VALUE obj1, VALUE obj2) static VALUE rb_obj_cmp(VALUE obj1, VALUE obj2) { - if (obj1 == obj2 || rb_equal(obj1, obj2)) + if (rb_equal(obj1, obj2)) return INT2FIX(0); return Qnil; } @@ -1710,7 +1585,7 @@ rb_obj_cmp(VALUE obj1, VALUE obj2) * show information on the thing we're attached to as well. */ -static VALUE +MJIT_FUNC_EXPORTED VALUE rb_mod_to_s(VALUE klass) { ID id_defined_at; @@ -1777,7 +1652,7 @@ rb_mod_eqq(VALUE mod, VALUE arg) return rb_obj_is_kind_of(arg, mod); } -/** +/* * call-seq: * mod <= other -> true, false, or nil * @@ -1786,15 +1661,6 @@ rb_mod_eqq(VALUE mod, VALUE arg) * nil if there's no relationship between the two. * (Think of the relationship in terms of the class definition: * "class A < B" implies "A < B".) - *-- - * Determines if \a mod inherits \a arg. Equivalent to \c Module\#<= in Ruby - * - * \param[in] mod a Module object - * \param[in] arg another Module object or an iclass of a module - * \retval Qtrue if \a mod inherits \a arg, or \a mod equals \a arg - * \retval Qfalse if \a arg inherits \a mod - * \retval Qnil if otherwise - *++ */ VALUE @@ -1903,20 +1769,7 @@ rb_mod_cmp(VALUE mod, VALUE arg) return INT2FIX(1); } -static VALUE -rb_module_s_alloc(VALUE klass) -{ - VALUE mod = rb_module_new(); - - RBASIC_SET_CLASS(mod, klass); - return mod; -} - -static VALUE -rb_class_s_alloc(VALUE klass) -{ - return rb_class_boot(0); -} +static VALUE rb_mod_initialize_exec(VALUE module); /* * call-seq: @@ -1946,6 +1799,12 @@ rb_class_s_alloc(VALUE klass) static VALUE rb_mod_initialize(VALUE module) +{ + return rb_mod_initialize_exec(module); +} + +static VALUE +rb_mod_initialize_exec(VALUE module) { if (rb_block_given_p()) { rb_mod_module_exec(1, &module, module); @@ -1955,10 +1814,11 @@ rb_mod_initialize(VALUE module) /* :nodoc: */ static VALUE -rb_mod_initialize_clone(VALUE clone, VALUE orig) +rb_mod_initialize_clone(int argc, VALUE* argv, VALUE clone) { - VALUE ret; - ret = rb_obj_init_dup_clone(clone, orig); + VALUE ret, orig, opts; + rb_scan_args(argc, argv, "1:", &orig, &opts); + ret = rb_obj_init_clone(argc, argv, clone); if (OBJ_FROZEN(orig)) rb_class_name(clone); return ret; @@ -2015,7 +1875,7 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass) RCLASS_SET_SUPER(klass, super); rb_make_metaclass(klass, RBASIC(super)->klass); rb_class_inherited(super, klass); - rb_mod_initialize(klass); + rb_mod_initialize_exec(klass); return klass; } @@ -2104,20 +1964,6 @@ class_call_alloc_func(rb_alloc_func_t allocator, VALUE klass) return obj; } -/** - * Allocates an instance of \a klass - * - * \note It calls the allocator defined by {rb_define_alloc_func}. - * So you cannot use this function to define an allocator. - * Use {rb_newobj_of}, {TypedData_Make_Struct} or others, instead. - * \note Usually prefer rb_class_new_instance to rb_obj_alloc and rb_obj_call_init - * \param[in] klass a Class object - * \sa rb_class_new_instance - * \sa rb_obj_call_init - * \sa rb_define_alloc_func - * \sa rb_newobj_of - * \sa TypedData_Make_Struct - */ VALUE rb_obj_alloc(VALUE klass) { @@ -2125,13 +1971,6 @@ rb_obj_alloc(VALUE klass) return rb_class_alloc(klass); } -static VALUE -rb_class_allocate_instance(VALUE klass) -{ - NEWOBJ_OF(obj, struct RObject, klass, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0)); - return (VALUE)obj; -} - /* * call-seq: * class.new(args, ...) -> obj @@ -2143,8 +1982,8 @@ rb_class_allocate_instance(VALUE klass) * */ -static VALUE -rb_class_s_new(int argc, const VALUE *argv, VALUE klass) +VALUE +rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass) { VALUE obj; @@ -2166,18 +2005,6 @@ rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat) return obj; } -/** - * Allocates and initializes an instance of \a klass. - * - * Equivalent to \c Class\#new in Ruby - * - * \param[in] argc the number of arguments to \c #initialize - * \param[in] argv a pointer to an array of arguments to \c #initialize - * \param[in] klass a Class object - * \return the new instance of \a klass - * \sa rb_obj_call_init - * \sa rb_obj_alloc - */ VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass) { @@ -2235,13 +2062,6 @@ rb_class_superclass(VALUE klass) return super; } -/** - * Returns the superclass of \a klass - * The return value might be an iclass of a module, unlike rb_class_superclass. - * - * Also it returns Qfalse when \a klass does not have a parent class. - * \sa rb_class_superclass - */ VALUE rb_class_get_superclass(VALUE klass) { @@ -2296,37 +2116,42 @@ id_for_attr(VALUE obj, VALUE name) /* * call-seq: - * attr_reader(symbol, ...) -> nil - * attr(symbol, ...) -> nil - * attr_reader(string, ...) -> nil - * attr(string, ...) -> nil + * attr_reader(symbol, ...) -> array + * attr(symbol, ...) -> array + * attr_reader(string, ...) -> array + * attr(string, ...) -> array * * Creates instance variables and corresponding methods that return the * value of each instance variable. Equivalent to calling * ``attr:name'' on each name in turn. * String arguments are converted to symbols. + * Returns an array of defined method names as symbols. */ static VALUE rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass) { int i; + VALUE names = rb_ary_new2(argc); for (i=0; i nil - * attr(name, true) -> nil - * attr(name, false) -> nil + * attr(name, ...) -> array + * attr(name, true) -> array + * attr(name, false) -> array * * The first form is equivalent to #attr_reader. * The second form is equivalent to attr_accessor(name) but deprecated. * The last form is equivalent to attr_reader(name) but deprecated. + * Returns an array of defined method names as symbols. *-- * \private * \todo can be static? @@ -2336,47 +2161,57 @@ VALUE rb_mod_attr(int argc, VALUE *argv, VALUE klass) { if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) { - rb_warning("optional boolean argument is obsoleted"); - rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE); - return Qnil; + ID id = id_for_attr(klass, argv[0]); + VALUE names = rb_ary_new(); + + rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "optional boolean argument is obsoleted"); + rb_attr(klass, id, 1, RTEST(argv[1]), TRUE); + rb_ary_push(names, ID2SYM(id)); + if (argv[1] == Qtrue) rb_ary_push(names, ID2SYM(rb_id_attrset(id))); + return names; } return rb_mod_attr_reader(argc, argv, klass); } /* * call-seq: - * attr_writer(symbol, ...) -> nil - * attr_writer(string, ...) -> nil + * attr_writer(symbol, ...) -> array + * attr_writer(string, ...) -> array * * Creates an accessor method to allow assignment to the attribute * symbol.id2name. * String arguments are converted to symbols. + * Returns an array of defined method names as symbols. */ static VALUE rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass) { int i; + VALUE names = rb_ary_new2(argc); for (i=0; i nil - * attr_accessor(string, ...) -> nil + * attr_accessor(symbol, ...) -> array + * attr_accessor(string, ...) -> array * * Defines a named attribute for this module, where the name is * symbol.id2name, creating an instance variable * (@name) and a corresponding access method to read it. * Also creates a method called name= to set the attribute. * String arguments are converted to symbols. + * Returns an array of defined method names as symbols. * * module Mod - * attr_accessor(:one, :two) + * attr_accessor(:one, :two) #=> [:one, :one=, :two, :two=] * end * Mod.instance_methods.sort #=> [:one, :one=, :two, :two=] */ @@ -2385,11 +2220,16 @@ static VALUE rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass) { int i; + VALUE names = rb_ary_new2(argc * 2); for (i=0; i= pend || !*p) { - wrong_name: - rb_name_err_raise(wrong_constant_name, mod, name); + goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { @@ -2530,6 +2369,10 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) } return mod; + + wrong_name: + rb_name_err_raise(wrong_constant_name, mod, name); + UNREACHABLE_RETURN(Qundef); } /* @@ -2632,8 +2475,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) pend = path + RSTRING_LEN(name); if (p >= pend || !*p) { - wrong_name: - rb_name_err_raise(wrong_constant_name, mod, name); + goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { @@ -2706,6 +2548,10 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) } return Qtrue; + + wrong_name: + rb_name_err_raise(wrong_constant_name, mod, name); + UNREACHABLE_RETURN(Qundef); } /* @@ -2713,8 +2559,8 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) * mod.const_source_location(sym, inherit=true) -> [String, Integer] * mod.const_source_location(str, inherit=true) -> [String, Integer] * - * Returns the Ruby source filename and line number containing first definition - * of constant specified. If the named constant is not found, +nil+ is returned. + * Returns the Ruby source filename and line number containing the definition + * of the constant specified. If the named constant is not found, +nil+ is returned. * If the constant is found, but its source location can not be extracted * (constant is defined in C code), empty array is returned. * @@ -2722,30 +2568,34 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) * by default). * * # test.rb: - * class A + * class A # line 1 * C1 = 1 + * C2 = 2 * end * - * module M - * C2 = 2 + * module M # line 6 + * C3 = 3 * end * - * class B < A + * class B < A # line 10 * include M - * C3 = 3 + * C4 = 4 * end * * class A # continuation of A definition + * C2 = 8 # constant redefinition; warned yet allowed * end * - * p B.const_source_location('C3') # => ["test.rb", 11] - * p B.const_source_location('C2') # => ["test.rb", 6] + * p B.const_source_location('C4') # => ["test.rb", 12] + * p B.const_source_location('C3') # => ["test.rb", 7] * p B.const_source_location('C1') # => ["test.rb", 2] * - * p B.const_source_location('C2', false) # => nil -- don't lookup in ancestors + * p B.const_source_location('C3', false) # => nil -- don't lookup in ancestors * - * p Object.const_source_location('B') # => ["test.rb", 9] - * p Object.const_source_location('A') # => ["test.rb", 1] -- note it is first entry, not "continuation" + * p A.const_source_location('C2') # => ["test.rb", 16] -- actual (last) definition place + * + * p Object.const_source_location('B') # => ["test.rb", 10] -- top-level constant could be looked through Object + * p Object.const_source_location('A') # => ["test.rb", 1] -- class reopening is NOT considered new definition * * p B.const_source_location('A') # => ["test.rb", 1] -- because Object is in ancestors * p M.const_source_location('A') # => ["test.rb", 1] -- Object is not ancestor, but additionally checked for modules @@ -2785,8 +2635,7 @@ rb_mod_const_source_location(int argc, VALUE *argv, VALUE mod) pend = path + RSTRING_LEN(name); if (p >= pend || !*p) { - wrong_name: - rb_name_err_raise(wrong_constant_name, mod, name); + goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { @@ -2852,6 +2701,10 @@ rb_mod_const_source_location(int argc, VALUE *argv, VALUE mod) } return loc; + + wrong_name: + rb_name_err_raise(wrong_constant_name, mod, name); + UNREACHABLE_RETURN(Qundef); } /* @@ -2893,9 +2746,9 @@ rb_obj_ivar_get(VALUE obj, VALUE iv) * obj.instance_variable_set(string, obj) -> obj * * Sets the instance variable named by symbol to the given - * object, thereby frustrating the efforts of the class's - * author to attempt to provide proper encapsulation. The variable - * does not have to exist prior to this call. + * object. This may circumvent the encapsulation intended by + * the author of the class, so it should be used with care. + * The variable does not have to exist prior to this call. * If the instance variable name is passed as a string, that string * is converted to a symbol. * @@ -3049,9 +2902,7 @@ rb_mod_cvar_defined(VALUE obj, VALUE iv) static VALUE rb_mod_singleton_p(VALUE klass) { - if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) - return Qtrue; - return Qfalse; + return RBOOL(RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)); } /*! \private */ @@ -3070,6 +2921,7 @@ static const struct conv_method_tbl { M(a), M(s), M(i), + M(f), M(r), #undef M }; @@ -3138,19 +2990,6 @@ conversion_mismatch(VALUE val, const char *tname, const char *method, VALUE resu cname, tname, cname, method, rb_obj_class(result)); } -/*! - * Converts an object into another type. - * Calls the specified conversion method if necessary. - * - * \param[in] val the object to be converted - * \param[in] type a value of \c ruby_value_type - * \param[in] tname name of the target type. - * only used for error messages. - * \param[in] method name of the method - * \return an object of the specified type - * \throw TypeError on failure - * \sa rb_check_convert_type - */ VALUE rb_convert_type(VALUE val, int type, const char *tname, const char *method) { @@ -3178,20 +3017,6 @@ rb_convert_type_with_id(VALUE val, int type, const char *tname, ID method) return v; } -/*! - * Tries to convert an object into another type. - * Calls the specified conversion method if necessary. - * - * \param[in] val the object to be converted - * \param[in] type a value of \c ruby_value_type - * \param[in] tname name of the target type. - * only used for error messages. - * \param[in] method name of the method - * \return an object of the specified type, or Qnil if no such conversion method defined. - * \throw TypeError if the conversion method returns an unexpected type of value. - * \sa rb_convert_type - * \sa rb_check_convert_type_with_id - */ VALUE rb_check_convert_type(VALUE val, int type, const char *tname, const char *method) { @@ -3226,37 +3051,30 @@ rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method) #define try_to_int(val, mid, raise) \ convert_type_with_id(val, "Integer", mid, raise, -1) -ALWAYS_INLINE(static VALUE rb_to_integer(VALUE val, const char *method, ID mid)); +ALWAYS_INLINE(static VALUE rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise)); +/* Integer specific rb_check_convert_type_with_id */ static inline VALUE -rb_to_integer(VALUE val, const char *method, ID mid) +rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise) { VALUE v; if (RB_INTEGER_TYPE_P(val)) return val; - v = try_to_int(val, mid, TRUE); + v = try_to_int(val, mid, raise); + if (!raise && NIL_P(v)) return Qnil; if (!RB_INTEGER_TYPE_P(v)) { conversion_mismatch(val, "Integer", method, v); } return v; } +#define rb_to_integer(val, method, mid) \ + rb_to_integer_with_id_exception(val, method, mid, TRUE) -/** - * Tries to convert \a val into \c Integer. - * It calls the specified conversion method if necessary. - * - * \param[in] val a Ruby object - * \param[in] method a name of a method - * \return an \c Integer object on success, - * or \c Qnil if no such conversion method defined. - * \exception TypeError if the conversion method returns a non-Integer object. - */ VALUE rb_check_to_integer(VALUE val, const char *method) { VALUE v; - if (FIXNUM_P(val)) return val; - if (RB_TYPE_P(val, T_BIGNUM)) return val; + if (RB_INTEGER_TYPE_P(val)) return val; v = convert_type(val, "Integer", method, FALSE); if (!RB_INTEGER_TYPE_P(v)) { return Qnil; @@ -3264,29 +3082,12 @@ rb_check_to_integer(VALUE val, const char *method) return v; } -/** - * Converts \a val into \c Integer. - * It calls \a #to_int method if necessary. - * - * \param[in] val a Ruby object - * \return an \c Integer object - * \exception TypeError on failure - */ VALUE rb_to_int(VALUE val) { return rb_to_integer(val, "to_int", idTo_int); } -/** - * Tries to convert \a val into Integer. - * It calls \c #to_int method if necessary. - * - * \param[in] val a Ruby object - * \return an Integer object on success, - * or \c Qnil if \c #to_int is not defined. - * \exception TypeError if \c #to_int returns a non-Integer object. - */ VALUE rb_check_to_int(VALUE val) { @@ -3310,33 +3111,35 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception) { VALUE tmp; + if (base) { + tmp = rb_check_string_type(val); + + if (! NIL_P(tmp)) { + val = tmp; + } + else if (! raise_exception) { + return Qnil; + } + else { + rb_raise(rb_eArgError, "base specified for non string value"); + } + } if (RB_FLOAT_TYPE_P(val)) { - double f; - if (base != 0) goto arg_error; - f = RFLOAT_VALUE(val); + double f = RFLOAT_VALUE(val); if (!raise_exception && !isfinite(f)) return Qnil; if (FIXABLE(f)) return LONG2FIX((long)f); return rb_dbl2big(f); } else if (RB_INTEGER_TYPE_P(val)) { - if (base != 0) goto arg_error; return val; } else if (RB_TYPE_P(val, T_STRING)) { return rb_str_convert_to_inum(val, base, TRUE, raise_exception); } else if (NIL_P(val)) { - if (base != 0) goto arg_error; if (!raise_exception) return Qnil; rb_raise(rb_eTypeError, "can't convert nil into Integer"); } - if (base != 0) { - tmp = rb_check_string_type(val); - if (!NIL_P(tmp)) return rb_str_convert_to_inum(tmp, base, TRUE, raise_exception); - arg_error: - if (!raise_exception) return Qnil; - rb_raise(rb_eArgError, "base specified for non string value"); - } tmp = rb_protect(rb_check_to_int, val, NULL); if (RB_INTEGER_TYPE_P(tmp)) return tmp; @@ -3351,18 +3154,18 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception) return rb_to_integer(val, "to_i", idTo_i); } -/** - * Equivalent to \c Kernel\#Integer in Ruby. - * - * Converts \a val into \c Integer in a slightly more strict manner - * than \c #to_i. - */ VALUE rb_Integer(VALUE val) { return rb_convert_to_integer(val, 0, TRUE); } +VALUE +rb_check_integer_type(VALUE val) +{ + return rb_to_integer_with_id_exception(val, "to_int", idTo_int, FALSE); +} + int rb_bool_expected(VALUE obj, const char *flagname) { @@ -3370,7 +3173,7 @@ rb_bool_expected(VALUE obj, const char *flagname) case Qtrue: case Qfalse: break; default: - rb_raise(rb_eArgError, "true or false is expected as %s: %+"PRIsVALUE, + rb_raise(rb_eArgError, "expected true or false as %s: %+"PRIsVALUE, flagname, obj); } return obj != Qfalse; @@ -3379,7 +3182,7 @@ rb_bool_expected(VALUE obj, const char *flagname) int rb_opts_exception_p(VALUE opts, int default_value) { - static ID kwds[1] = {idException}; + static const ID kwds[1] = {idException}; VALUE exception; if (rb_get_kwargs(opts, kwds, 0, 1, &exception)) return rb_bool_expected(exception, "exception"); @@ -3398,8 +3201,9 @@ rb_opts_exception_p(VALUE opts, int default_value) * integer string representation. If arg is a String, * when base is omitted or equals zero, radix indicators * (0, 0b, and 0x) are honored. - * In any case, strings should be strictly conformed to numeric - * representation. This behavior is different from that of + * In any case, strings should consist only of one or more digits, except + * for that a sign, one underscore between two digits, and leading/trailing + * spaces are optional. This behavior is different from that of * String#to_i. Non string values will be converted by first * trying to_int, then to_i. * @@ -3413,6 +3217,7 @@ rb_opts_exception_p(VALUE opts, int default_value) * Integer(Time.new) #=> 1204973019 * Integer("0930", 10) #=> 930 * Integer("111", 2) #=> 7 + * Integer(" +1_0 ") #=> 10 * Integer(nil) #=> TypeError: can't convert nil into Integer * Integer("x") #=> ArgumentError: invalid value for Integer(): "x" * @@ -3476,13 +3281,7 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error) } if (p == end) { if (badcheck) { - bad: - if (raise) - rb_invalid_str(q, "Float()"); - else { - if (error) *error = 1; - return 0.0; - } + goto bad; } return d; } @@ -3557,19 +3356,18 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error) rb_raise(rb_eArgError, "Float %.*s%s out of range", w, q, ellipsis); } return d; + + bad: + if (raise) { + rb_invalid_str(q, "Float()"); + UNREACHABLE_RETURN(nan("")); + } + else { + if (error) *error = 1; + return 0.0; + } } -/*! - * Parses a string representation of a floating point number. - * - * \param[in] p a string representation of a floating number - * \param[in] badcheck raises an exception on parse error if \a badcheck is non-zero. - * \return the floating point number in the string on success, - * 0.0 on parse error and \a badcheck is zero. - * \note it always fails to parse a hexadecimal representation like "0xAB.CDp+1" when - * \a badcheck is zero, even though it would success if \a badcheck was non-zero. - * This inconsistency is coming from a historical compatibility reason. [ruby-dev:40822] - */ double rb_cstr_to_dbl(const char *p, int badcheck) { @@ -3611,17 +3409,6 @@ rb_str_to_dbl_raise(VALUE str, int badcheck, int raise, int *error) FUNC_MINIMIZED(double rb_str_to_dbl(VALUE str, int badcheck)); -/*! - * Parses a string representation of a floating point number. - * - * \param[in] str a \c String object representation of a floating number - * \param[in] badcheck raises an exception on parse error if \a badcheck is non-zero. - * \return the floating point number in the string on success, - * 0.0 on parse error and \a badcheck is zero. - * \note it always fails to parse a hexadecimal representation like "0xAB.CDp+1" when - * \a badcheck is zero, even though it would success if \a badcheck was non-zero. - * This inconsistency is coming from a historical compatibility reason. [ruby-dev:40822] - */ double rb_str_to_dbl(VALUE str, int badcheck) { @@ -3635,7 +3422,7 @@ rb_str_to_dbl(VALUE str, int badcheck) (FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x)) #define num2dbl_without_to_f(x) \ (FIXNUM_P(x) ? fix2dbl_without_to_f(x) : \ - RB_TYPE_P(x, T_BIGNUM) ? big2dbl_without_to_f(x) : \ + RB_BIGNUM_TYPE_P(x) ? big2dbl_without_to_f(x) : \ (Check_Type(x, T_FLOAT), RFLOAT_VALUE(x))) static inline double rat2dbl_without_to_f(VALUE x) @@ -3738,44 +3525,23 @@ rb_convert_to_float(VALUE val, int raise_exception) FUNC_MINIMIZED(VALUE rb_Float(VALUE val)); -/*! - * Equivalent to \c Kernel\#Float in Ruby. - * - * Converts \a val into \c Float in a slightly more strict manner - * than \c #to_f. - */ VALUE rb_Float(VALUE val) { return rb_convert_to_float(val, TRUE); } -/* - * call-seq: - * Float(arg, exception: true) -> float or nil - * - * Returns arg converted to a float. Numeric types are - * converted directly, and with exception to String and - * nil the rest are converted using - * arg.to_f. Converting a String with invalid - * characters will result in a ArgumentError. Converting - * nil generates a TypeError. Exceptions can be - * suppressed by passing exception: false. - * - * Float(1) #=> 1.0 - * Float("123.456") #=> 123.456 - * Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring" - * Float(nil) #=> TypeError: can't convert nil into Float - * Float("123.0_badstring", exception: false) #=> nil - */ - static VALUE -rb_f_float(int argc, VALUE *argv, VALUE obj) +rb_f_float1(rb_execution_context_t *ec, VALUE obj, VALUE arg) { - VALUE arg = Qnil, opts = Qnil; + return rb_convert_to_float(arg, TRUE); +} - rb_scan_args(argc, argv, "1:", &arg, &opts); - return rb_convert_to_float(arg, opts_exception_p(opts)); +static VALUE +rb_f_float(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE opts) +{ + int exception = rb_bool_expected(opts, "exception"); + return rb_convert_to_float(arg, exception); } static VALUE @@ -3788,11 +3554,6 @@ numeric_to_float(VALUE val) return rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f); } -/*! - * Converts a \c Numeric object into \c Float. - * \param[in] val a \c Numeric object - * \exception TypeError if \a val is not a \c Numeric or other conversion failures. - */ VALUE rb_to_float(VALUE val) { @@ -3803,17 +3564,10 @@ rb_to_float(VALUE val) return numeric_to_float(val); } -/*! - * Tries to convert an object into \c Float. - * It calls \c #to_f if necessary. - * - * It returns \c Qnil if the object is not a \c Numeric - * or \c #to_f is not defined on the object. - */ VALUE rb_check_to_float(VALUE val) { - if (RB_TYPE_P(val, T_FLOAT)) return val; + if (RB_FLOAT_TYPE_P(val)) return val; if (!rb_obj_is_kind_of(val, rb_cNumeric)) { return Qnil; } @@ -3854,19 +3608,14 @@ rb_num_to_dbl(VALUE val) if (basic_to_f_p(rb_cRational)) return rat2dbl_without_to_f(val); break; + default: + break; } } val = numeric_to_float(val); return RFLOAT_VALUE(val); } -/*! - * Converts a \c Numeric object to \c double. - * \param[in] val a \c Numeric object - * \return the converted value - * \exception TypeError if \a val is not a \c Numeric or - * it does not support conversion to a floating point number. - */ double rb_num2dbl(VALUE val) { @@ -3891,18 +3640,14 @@ rb_num2dbl(VALUE val) return rat2dbl_without_to_f(val); case T_STRING: rb_raise(rb_eTypeError, "no implicit conversion to float from string"); + default: + break; } } val = rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f); return RFLOAT_VALUE(val); } -/*! - * Equivalent to \c Kernel\#String in Ruby. - * - * Converts \a val into \c String by trying \c #to_str at first and - * then trying \c #to_s. - */ VALUE rb_String(VALUE val) { @@ -3932,9 +3677,6 @@ rb_f_string(VALUE obj, VALUE arg) return rb_String(arg); } -/*! - * Equivalent to \c Kernel\#Array in Ruby. - */ VALUE rb_Array(VALUE val) { @@ -4069,13 +3811,13 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound) continue; } break; + default: + break; } } return rb_check_funcall_with_hook_kw(obj, id_dig, argc, argv, no_dig_method, obj, - rb_empty_keyword_given_p() ? - RB_PASS_EMPTY_KEYWORDS : - RB_NO_KEYWORDS); + RB_NO_KEYWORDS); } return obj; } @@ -4460,6 +4202,31 @@ f_sprintf(int c, const VALUE *v, VALUE _) * ::Object.const_get(name) * end * end + * + * === What's Here + * + * These are the methods defined for \BasicObject: + * + * - ::new:: Returns a new \BasicObject instance. + * - {!}[#method-i-21]:: Returns the boolean negation of +self+: +true+ or +false+. + * - {!=}[#method-i-21-3D]:: Returns whether +self+ and the given object + * are _not_ equal. + * - {==}[#method-i-3D-3D]:: Returns whether +self+ and the given object + * are equivalent. + * - {__id__}[#method-i-__id__]:: Returns the integer object identifier for +self+. + * - {__send__}[#method-i-__send__]:: Calls the method identified by the given symbol. + * - #equal?:: Returns whether +self+ and the given object are the same object. + * - #instance_eval:: Evaluates the given string or block in the context of +self+. + * - #instance_exec:: Executes the given block in the context of +self+, + * passing the given arguments. + * - #method_missing:: Method called when an undefined method is called on +self+. + * - #singleton_method_added:: Method called when a singleton method + * is added to +self+. + * - #singleton_method_removed:: Method called when a singleton method + * is added removed from +self+. + * - #singleton_method_undefined:: Method called when a singleton method + * is undefined in +self+. + * */ /* Document-class: Object @@ -4479,6 +4246,90 @@ f_sprintf(int c, const VALUE *v, VALUE _) * In the descriptions of Object's methods, the parameter symbol refers * to a symbol, which is either a quoted string or a Symbol (such as * :name). + * + * == What's Here + * + * First, what's elsewhere. \Class \Object: + * + * - Inherits from {class BasicObject}[BasicObject.html#class-BasicObject-label-What-27s+Here]. + * - Includes {module Kernel}[Kernel.html#module-Kernel-label-What-27s+Here]. + * + * Here, class \Object provides methods for: + * + * - {Querying}[#class-Object-label-Querying] + * - {Instance Variables}[#class-Object-label-Instance+Variables] + * - {Other}[#class-Object-label-Other] + * + * === Querying + * + * - {!~}[#method-i-21~]:: Returns +true+ if +self+ does not match the given object, + * otherwise +false+. + * - {<=>}[#method-i-3C-3D-3E]:: Returns 0 if +self+ and the given object +object+ + * are the same object, or if + * self == object; otherwise returns +nil+. + * - #===:: Implements case equality, effectively the same as calling #==. + * - #eql?:: Implements hash equality, effectively the same as calling #==. + * - #kind_of? (aliased as #is_a?):: Returns whether given argument is an ancestor + * of the singleton class of +self+. + * - #instance_of?:: Returns whether +self+ is an instance of the given class. + * - #instance_variable_defined?:: Returns whether the given instance variable + * is defined in +self+. + * - #method:: Returns the Method object for the given method in +self+. + * - #methods:: Returns an array of symbol names of public and protected methods + * in +self+. + * - #nil?:: Returns +false+. (Only +nil+ responds +true+ to method nil?.) + * - #object_id:: Returns an integer corresponding to +self+ that is unique + * for the current process + * - #private_methods:: Returns an array of the symbol names + * of the private methods in +self+. + * - #protected_methods:: Returns an array of the symbol names + * of the protected methods in +self+. + * - #public_method:: Returns the Method object for the given public method in +self+. + * - #public_methods:: Returns an array of the symbol names + * of the public methods in +self+. + * - #respond_to?:: Returns whether +self+ responds to the given method. + * - #singleton_class:: Returns the singleton class of +self+. + * - #singleton_method:: Returns the Method object for the given singleton method + * in +self+. + * - #singleton_methods:: Returns an array of the symbol names + * of the singleton methods in +self+. + * + * - #define_singleton_method:: Defines a singleton method in +self+ + * for the given symbol method-name and block or proc. + * - #extend:: Includes the given modules in the singleton class of +self+. + * - #public_send:: Calls the given public method in +self+ with the given argument. + * - #send:: Calls the given method in +self+ with the given argument. + * + * === Instance Variables + * + * - #instance_variable_get:: Returns the value of the given instance variable + * in +self+, or +nil+ if the instance variable is not set. + * - #instance_variable_set:: Sets the value of the given instance variable in +self+ + * to the given object. + * - #instance_variables:: Returns an array of the symbol names + * of the instance variables in +self+. + * - #remove_instance_variable:: Removes the named instance variable from +self+. + * + * === Other + * + * - #clone:: Returns a shallow copy of +self+, including singleton class + * and frozen state. + * - #define_singleton_method:: Defines a singleton method in +self+ + * for the given symbol method-name and block or proc. + * - #display:: Prints +self+ to the given \IO stream or $stdout. + * - #dup:: Returns a shallow unfrozen copy of +self+. + * - #enum_for (aliased as #to_enum):: Returns an Enumerator for +self+ + * using the using the given method, + * arguments, and block. + * - #extend:: Includes the given modules in the singleton class of +self+. + * - #freeze:: Prevents further modifications to +self+. + * - #hash:: Returns the integer hash value for +self+. + * - #inspect:: Returns a human-readable string representation of +self+. + * - #itself:: Returns +self+. + * - #public_send:: Calls the given public method in +self+ with the given argument. + * - #send:: Calls the given method in +self+ with the given argument. + * - #to_s:: Returns a string representation of +self+. + * */ /*! @@ -4513,21 +4364,19 @@ InitVM_Object(void) rb_cObject = rb_define_class("Object", rb_cBasicObject); rb_cModule = rb_define_class("Module", rb_cObject); rb_cClass = rb_define_class("Class", rb_cModule); + rb_cRefinement = rb_define_class("Refinement", rb_cModule); #endif -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy0, 0); + rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_initialize, 0); rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance); rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1); rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1); rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0); rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy1, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy1, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy1, 1); + rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_singleton_method_added, 1); + rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_singleton_method_removed, 1); + rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_singleton_method_undefined, 1); /* Document-module: Kernel * @@ -4540,35 +4389,164 @@ InitVM_Object(void) * * sprintf "%.1f", 1.234 #=> "1.2" * + * == What's Here + * + * \Module \Kernel provides methods that are useful for: + * + * - {Converting}[#module-Kernel-label-Converting] + * - {Querying}[#module-Kernel-label-Querying] + * - {Exiting}[#module-Kernel-label-Exiting] + * - {Exceptions}[#module-Kernel-label-Exceptions] + * - {IO}[#module-Kernel-label-IO] + * - {Procs}[#module-Kernel-label-Procs] + * - {Tracing}[#module-Kernel-label-Tracing] + * - {Subprocesses}[#module-Kernel-label-Subprocesses] + * - {Loading}[#module-Kernel-label-Loading] + * - {Yielding}[#module-Kernel-label-Yielding] + * - {Random Values}[#module-Kernel-label-Random+Values] + * - {Other}[#module-Kernel-label-Other] + * + * === Converting + * + * - {#Array}[#method-i-Array]:: Returns an Array based on the given argument. + * - {#Complex}[#method-i-Complex]:: Returns a Complex based on the given arguments. + * - {#Float}[#method-i-Float]:: Returns a Float based on the given arguments. + * - {#Hash}[#method-i-Hash]:: Returns a Hash based on the given argument. + * - {#Integer}[#method-i-Integer]:: Returns an Integer based on the given arguments. + * - {#Rational}[#method-i-Rational]:: Returns a Rational + * based on the given arguments. + * - {#String}[#method-i-String]:: Returns a String based on the given argument. + * + * === Querying + * + * - {#__callee__}[#method-i-__callee__]:: Returns the called name + * of the current method as a symbol. + * - {#__dir__}[#method-i-__dir__]:: Returns the path to the directory + * from which the current method is called. + * - {#__method__}[#method-i-__method__]:: Returns the name + * of the current method as a symbol. + * - #autoload?:: Returns the file to be loaded when the given module is referenced. + * - #binding:: Returns a Binding for the context at the point of call. + * - #block_given?:: Returns +true+ if a block was passed to the calling method. + * - #caller:: Returns the current execution stack as an array of strings. + * - #caller_locations:: Returns the current execution stack as an array + * of Thread::Backtrace::Location objects. + * - #class:: Returns the class of +self+. + * - #frozen?:: Returns whether +self+ is frozen. + * - #global_variables:: Returns an array of global variables as symbols. + * - #local_variables:: Returns an array of local variables as symbols. + * - #test:: Performs specified tests on the given single file or pair of files. + * + * === Exiting + * + * - #abort:: Exits the current process after printing the given arguments. + * - #at_exit:: Executes the given block when the process exits. + * - #exit:: Exits the current process after calling any registered + * +at_exit+ handlers. + * - #exit!:: Exits the current process without calling any registered + * +at_exit+ handlers. + * + * === Exceptions + * + * - #catch:: Executes the given block, possibly catching a thrown object. + * - #raise (aliased as #fail):: Raises an exception based on the given arguments. + * - #throw:: Returns from the active catch block waiting for the given tag. + * + * + * === \IO + * + * - #gets:: Returns and assigns to $_ the next line from the current input. + * - #open:: Creates an IO object connected to the given stream, file, or subprocess. + * - #p:: Prints the given objects' inspect output to the standard output. + * - #pp:: Prints the given objects in pretty form. + * - #print:: Prints the given objects to standard output without a newline. + * - #printf:: Prints the string resulting from applying the given format string + * to any additional arguments. + * - #putc:: Equivalent to for the given object. + * - #puts:: Equivalent to $stdout.puts(*objects) for the given objects. + * - #readline:: Similar to #gets, but raises an exception at the end of file. + * - #readlines:: Returns an array of the remaining lines from the current input. + * - #select:: Same as IO.select. + * + * === Procs + * + * - #lambda:: Returns a lambda proc for the given block. + * - #proc:: Returns a new Proc; equivalent to Proc.new. + * + * === Tracing + * + * - #set_trace_func:: Sets the given proc as the handler for tracing, + * or disables tracing if given +nil+. + * - #trace_var:: Starts tracing assignments to the given global variable. + * - #untrace_var:: Disables tracing of assignments to the given global variable. + * + * === Subprocesses + * + * - #`cmd`:: Returns the standard output of running +cmd+ in a subshell. + * - #exec:: Replaces current process with a new process. + * - #fork:: Forks the current process into two processes. + * - #spawn:: Executes the given command and returns its pid without waiting + * for completion. + * - #system:: Executes the given command in a subshell. + * + * === Loading + * + * - #autoload:: Registers the given file to be loaded when the given constant + * is first referenced. + * - #load:: Loads the given Ruby file. + * - #require:: Loads the given Ruby file unless it has already been loaded. + * - #require_relative:: Loads the Ruby file path relative to the calling file, + * unless it has already been loaded. + * + * === Yielding + * + * - #tap:: Yields +self+ to the given block; returns +self+. + * - #then (aliased as #yield_self):: Yields +self+ to the block + * and returns the result of the block. + * + * === \Random Values + * + * - #rand:: Returns a pseudo-random floating point number + * strictly between 0.0 and 1.0. + * - #srand:: Seeds the pseudo-random number generator with the given number. + * + * === Other + * + * - #eval:: Evaluates the given string as Ruby code. + * - #loop:: Repeatedly executes the given block. + * - #sleep:: Suspends the current thread for the given number of seconds. + * - #sprintf (aliased as #format):: Returns the string resulting from applying + * the given format string + * to any additional arguments. + * - #syscall:: Runs an operating system call. + * - #trap:: Specifies the handling of system signals. + * - #warn:: Issue a warning based on the given messages and options. + * */ rb_mKernel = rb_define_module("Kernel"); rb_include_module(rb_cObject, rb_mKernel); - rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "included", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "extended", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "prepended", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy1, 1); - rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy1, 1); + rb_define_private_method(rb_cClass, "inherited", rb_obj_class_inherited, 1); + rb_define_private_method(rb_cModule, "included", rb_obj_mod_included, 1); + rb_define_private_method(rb_cModule, "extended", rb_obj_mod_extended, 1); + rb_define_private_method(rb_cModule, "prepended", rb_obj_mod_prepended, 1); + rb_define_private_method(rb_cModule, "method_added", rb_obj_mod_method_added, 1); + rb_define_private_method(rb_cModule, "method_removed", rb_obj_mod_method_removed, 1); + rb_define_private_method(rb_cModule, "method_undefined", rb_obj_mod_method_undefined, 1); rb_define_method(rb_mKernel, "nil?", rb_false, 0); - rb_define_method(rb_mKernel, "===", rb_equal, 1); + rb_define_method(rb_mKernel, "===", case_equal, 1); rb_define_method(rb_mKernel, "=~", rb_obj_match, 1); rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1); rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1); rb_define_method(rb_mKernel, "hash", rb_obj_hash, 0); /* in hash.c */ rb_define_method(rb_mKernel, "<=>", rb_obj_cmp, 1); - rb_define_method(rb_mKernel, "class", rb_obj_class, 0); rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0); - rb_define_method(rb_mKernel, "clone", rb_obj_clone2, -1); rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0); rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0); - rb_define_method(rb_mKernel, "yield_self", rb_obj_yield_self, 0); - rb_define_method(rb_mKernel, "then", rb_obj_yield_self, 0); rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1); rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1); - rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_dup_clone, 1); + rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_clone, -1); rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0); rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0); @@ -4577,7 +4555,6 @@ InitVM_Object(void) rb_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted, 0); rb_define_method(rb_mKernel, "trust", rb_obj_trust, 0); rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0); - rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0); rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0); rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0); @@ -4596,13 +4573,11 @@ InitVM_Object(void) rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1); rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1); rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1); - rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0); rb_define_global_function("sprintf", f_sprintf, -1); rb_define_global_function("format", f_sprintf, -1); rb_define_global_function("Integer", rb_f_integer, -1); - rb_define_global_function("Float", rb_f_float, -1); rb_define_global_function("String", rb_f_string, 1); rb_define_global_function("Array", rb_f_array, 1); @@ -4611,9 +4586,7 @@ InitVM_Object(void) rb_cNilClass = rb_define_class("NilClass", rb_cObject); rb_cNilClass_to_s = rb_fstring_enc_lit("", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cNilClass_to_s); - rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0); - rb_define_method(rb_cNilClass, "to_f", nil_to_f, 0); - rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0); + rb_define_method(rb_cNilClass, "to_s", rb_nil_to_s, 0); rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0); rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0); rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0); @@ -4621,16 +4594,11 @@ InitVM_Object(void) rb_define_method(rb_cNilClass, "&", false_and, 1); rb_define_method(rb_cNilClass, "|", false_or, 1); rb_define_method(rb_cNilClass, "^", false_xor, 1); - rb_define_method(rb_cNilClass, "===", rb_equal, 1); + rb_define_method(rb_cNilClass, "===", case_equal, 1); rb_define_method(rb_cNilClass, "nil?", rb_true, 0); rb_undef_alloc_func(rb_cNilClass); rb_undef_method(CLASS_OF(rb_cNilClass), "new"); - /* - * An obsolete alias of +nil+ - */ - rb_define_global_const("NIL", Qnil); - rb_deprecate_constant(rb_cObject, "NIL"); rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0); rb_define_method(rb_cModule, "===", rb_mod_eqq, 1); @@ -4654,8 +4622,9 @@ InitVM_Object(void) rb_define_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1); rb_define_alloc_func(rb_cModule, rb_module_s_alloc); + rb_undef_method(rb_singleton_class(rb_cModule), "allocate"); rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0); - rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, 1); + rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, -1); rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1); /* in class.c */ rb_define_method(rb_cModule, "public_instance_methods", rb_class_public_instance_methods, -1); /* in class.c */ @@ -4685,60 +4654,45 @@ InitVM_Object(void) rb_define_method(rb_cModule, "deprecate_constant", rb_mod_deprecate_constant, -1); /* in variable.c */ rb_define_method(rb_cModule, "singleton_class?", rb_mod_singleton_p, 0); + rb_define_method(rb_singleton_class(rb_cClass), "allocate", rb_class_alloc_m, 0); rb_define_method(rb_cClass, "allocate", rb_class_alloc_m, 0); - rb_define_method(rb_cClass, "new", rb_class_s_new, -1); + rb_define_method(rb_cClass, "new", rb_class_new_instance_pass_kw, -1); rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1); rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0); + rb_define_method(rb_cClass, "subclasses", rb_class_subclasses, 0); /* in class.c */ rb_define_alloc_func(rb_cClass, rb_class_s_alloc); rb_undef_method(rb_cClass, "extend_object"); rb_undef_method(rb_cClass, "append_features"); rb_undef_method(rb_cClass, "prepend_features"); - /* - * Document-class: Data - * - * This is a deprecated class, base class for C extensions using - * Data_Make_Struct or Data_Wrap_Struct. - */ - rb_cData = rb_define_class("Data", rb_cObject); - rb_undef_alloc_func(rb_cData); - rb_deprecate_constant(rb_cObject, "Data"); - rb_cTrueClass = rb_define_class("TrueClass", rb_cObject); rb_cTrueClass_to_s = rb_fstring_enc_lit("true", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cTrueClass_to_s); - rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0); + rb_define_method(rb_cTrueClass, "to_s", rb_true_to_s, 0); rb_define_alias(rb_cTrueClass, "inspect", "to_s"); rb_define_method(rb_cTrueClass, "&", true_and, 1); rb_define_method(rb_cTrueClass, "|", true_or, 1); rb_define_method(rb_cTrueClass, "^", true_xor, 1); - rb_define_method(rb_cTrueClass, "===", rb_equal, 1); + rb_define_method(rb_cTrueClass, "===", case_equal, 1); rb_undef_alloc_func(rb_cTrueClass); rb_undef_method(CLASS_OF(rb_cTrueClass), "new"); - /* - * An obsolete alias of +true+ - */ - rb_define_global_const("TRUE", Qtrue); - rb_deprecate_constant(rb_cObject, "TRUE"); rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cFalseClass_to_s); - rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0); + rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, 0); rb_define_alias(rb_cFalseClass, "inspect", "to_s"); rb_define_method(rb_cFalseClass, "&", false_and, 1); rb_define_method(rb_cFalseClass, "|", false_or, 1); rb_define_method(rb_cFalseClass, "^", false_xor, 1); - rb_define_method(rb_cFalseClass, "===", rb_equal, 1); + rb_define_method(rb_cFalseClass, "===", case_equal, 1); rb_undef_alloc_func(rb_cFalseClass); rb_undef_method(CLASS_OF(rb_cFalseClass), "new"); - /* - * An obsolete alias of +false+ - */ - rb_define_global_const("FALSE", Qfalse); - rb_deprecate_constant(rb_cObject, "FALSE"); } +#include "kernel.rbinc" +#include "nilclass.rbinc" + void Init_Object(void) { diff --git a/ruby/pack.c b/ruby/pack.c index ae5a9a18e..1fbbd724d 100644 --- a/ruby/pack.c +++ b/ruby/pack.c @@ -9,12 +9,21 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "internal.h" -#include +#include "ruby/internal/config.h" + #include #include #include +#include + +#include "internal.h" +#include "internal/array.h" +#include "internal/bits.h" +#include "internal/string.h" +#include "internal/symbol.h" +#include "internal/variable.h" +#include "ruby/util.h" + #include "builtin.h" /* @@ -126,13 +135,28 @@ str_associate(VALUE str, VALUE add) static VALUE str_associated(VALUE str) { - return rb_ivar_lookup(str, id_associated, Qfalse); + VALUE associates = rb_ivar_lookup(str, id_associated, Qfalse); + if (!associates) + rb_raise(rb_eArgError, "no associated pointer"); + return associates; +} + +static VALUE +associated_pointer(VALUE associates, const char *t) +{ + const VALUE *p = RARRAY_CONST_PTR(associates); + const VALUE *pend = p + RARRAY_LEN(associates); + for (; p < pend; p++) { + VALUE tmp = *p; + if (RB_TYPE_P(tmp, T_STRING) && RSTRING_PTR(tmp) == t) return tmp; + } + rb_raise(rb_eArgError, "non associated pointer"); + UNREACHABLE_RETURN(Qnil); } static void unknown_directive(const char *mode, char type, VALUE fmt) { - VALUE f; char unknown[5]; if (ISPRINT(type)) { @@ -142,10 +166,7 @@ unknown_directive(const char *mode, char type, VALUE fmt) else { snprintf(unknown, sizeof(unknown), "\\x%.2x", type & 0xff); } - f = rb_str_quote_unprintable(fmt); - if (f != fmt) { - fmt = rb_str_subseq(f, 1, RSTRING_LEN(f) - 2); - } + fmt = rb_str_quote_unprintable(fmt); rb_warning("unknown %s directive '%s' in '%"PRIsVALUE"'", mode, unknown, fmt); } @@ -923,12 +944,12 @@ hex2num(char c) #define UNPACK_1 2 static VALUE -pack_unpack_internal(VALUE str, VALUE fmt, int mode) +pack_unpack_internal(VALUE str, VALUE fmt, int mode, long offset) { #define hexdigits ruby_hexdigits char *s, *send; char *p, *pend; - VALUE ary; + VALUE ary, associates = Qfalse; char type; long len; AVOID_CC_BUG long tmp_len; @@ -952,11 +973,20 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) StringValue(str); StringValue(fmt); + + if (offset < 0) rb_raise(rb_eArgError, "offset can't be negative"); + len = RSTRING_LEN(str); + if (offset > len) rb_raise(rb_eArgError, "offset outside of string"); + s = RSTRING_PTR(str); - send = s + RSTRING_LEN(str); + send = s + len; + s += offset; + p = RSTRING_PTR(fmt); pend = p + RSTRING_LEN(fmt); +#define UNPACK_FETCH(var, type) (memcpy((var), s, sizeof(type)), s += sizeof(type)) + ary = mode == UNPACK_ARRAY ? rb_ary_new() : Qnil; while (p < pend) { int explicit_endian = 0; @@ -1266,8 +1296,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(float)); while (len-- > 0) { float tmp; - memcpy(&tmp, s, sizeof(float)); - s += sizeof(float); + UNPACK_FETCH(&tmp, float); UNPACK_PUSH(DBL2NUM((double)tmp)); } PACK_ITEM_ADJUST(); @@ -1277,8 +1306,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(float)); while (len-- > 0) { FLOAT_CONVWITH(tmp); - memcpy(tmp.buf, s, sizeof(float)); - s += sizeof(float); + UNPACK_FETCH(tmp.buf, float); VTOHF(tmp); UNPACK_PUSH(DBL2NUM(tmp.f)); } @@ -1289,8 +1317,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(double)); while (len-- > 0) { DOUBLE_CONVWITH(tmp); - memcpy(tmp.buf, s, sizeof(double)); - s += sizeof(double); + UNPACK_FETCH(tmp.buf, double); VTOHD(tmp); UNPACK_PUSH(DBL2NUM(tmp.d)); } @@ -1302,8 +1329,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(double)); while (len-- > 0) { double tmp; - memcpy(&tmp, s, sizeof(double)); - s += sizeof(double); + UNPACK_FETCH(&tmp, double); UNPACK_PUSH(DBL2NUM(tmp)); } PACK_ITEM_ADJUST(); @@ -1313,8 +1339,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(float)); while (len-- > 0) { FLOAT_CONVWITH(tmp); - memcpy(tmp.buf, s, sizeof(float)); - s += sizeof(float); + UNPACK_FETCH(tmp.buf, float); NTOHF(tmp); UNPACK_PUSH(DBL2NUM(tmp.f)); } @@ -1325,8 +1350,7 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) PACK_LENGTH_ADJUST_SIZE(sizeof(double)); while (len-- > 0) { DOUBLE_CONVWITH(tmp); - memcpy(tmp.buf, s, sizeof(double)); - s += sizeof(double); + UNPACK_FETCH(tmp.buf, double); NTOHD(tmp); UNPACK_PUSH(DBL2NUM(tmp.d)); } @@ -1537,33 +1561,13 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) VALUE tmp = Qnil; char *t; - memcpy(&t, s, sizeof(char *)); - s += sizeof(char *); - + UNPACK_FETCH(&t, char *); if (t) { - VALUE a; - const VALUE *p, *pend; - - if (!(a = str_associated(str))) { - rb_raise(rb_eArgError, "no associated pointer"); - } - p = RARRAY_CONST_PTR(a); - pend = p + RARRAY_LEN(a); - while (p < pend) { - if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) { - if (len < RSTRING_LEN(*p)) { - tmp = rb_str_new(t, len); - str_associate(tmp, a); - } - else { - tmp = *p; - } - break; - } - p++; - } - if (p == pend) { - rb_raise(rb_eArgError, "non associated pointer"); + if (!associates) associates = str_associated(str); + tmp = associated_pointer(associates, t); + if (len < RSTRING_LEN(tmp)) { + tmp = rb_str_new(t, len); + str_associate(tmp, associates); } } UNPACK_PUSH(tmp); @@ -1580,28 +1584,10 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) VALUE tmp = Qnil; char *t; - memcpy(&t, s, sizeof(char *)); - s += sizeof(char *); - + UNPACK_FETCH(&t, char *); if (t) { - VALUE a; - const VALUE *p, *pend; - - if (!(a = str_associated(str))) { - rb_raise(rb_eArgError, "no associated pointer"); - } - p = RARRAY_CONST_PTR(a); - pend = p + RARRAY_LEN(a); - while (p < pend) { - if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) { - tmp = *p; - break; - } - p++; - } - if (p == pend) { - rb_raise(rb_eArgError, "non associated pointer"); - } + if (!associates) associates = str_associated(str); + tmp = associated_pointer(associates, t); } UNPACK_PUSH(tmp); } @@ -1635,16 +1621,16 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) } static VALUE -pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt) +pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt, VALUE offset) { int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY; - return pack_unpack_internal(str, fmt, mode); + return pack_unpack_internal(str, fmt, mode, RB_NUM2LONG(offset)); } static VALUE -pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt) +pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt, VALUE offset) { - return pack_unpack_internal(str, fmt, UNPACK_1); + return pack_unpack_internal(str, fmt, UNPACK_1, RB_NUM2LONG(offset)); } int @@ -1759,7 +1745,5 @@ utf8_to_uv(const char *p, long *lenp) void Init_pack(void) { - load_pack(); - id_associated = rb_make_internal_id(); } diff --git a/ruby/pack.rb b/ruby/pack.rb index 3f921a93d..6f542e2f9 100644 --- a/ruby/pack.rb +++ b/ruby/pack.rb @@ -33,6 +33,16 @@ class Array # the offset, the rest of offsetOfBuffer are overwritten by the result. # If it's shorter, the gap is filled with ``\0''. # + # # packed data is appended by default + # [255].pack("C", buffer:"foo".b) #=> "foo\xFF" + # + # # "@0" (offset 0) specifies that packed data is filled from beginning. + # # Also, original data after packed data is removed. ("oo" is removed.) + # [255].pack("@0C", buffer:"foo".b) #=> "\xFF" + # + # # If the offset is bigger than the original length, \x00 is filled. + # [255].pack("@5C", buffer:"foo".b) #=> "foo\x00\x00\xFF" + # # Note that ``buffer:'' option does not guarantee not to allocate memory # in +pack+. If the capacity of aBufferString is not enough, # +pack+ allocates memory. @@ -77,14 +87,14 @@ class Array # S> s> S!> s!> | Integer | same as the directives without ">" except # L> l> L!> l!> | | big endian # I!> i!> | | (available since Ruby 1.9.3) - # Q> q> Q!> q!> | | "S>" is same as "n" - # J> j> J!> j!> | | "L>" is same as "N" + # Q> q> Q!> q!> | | "S>" is the same as "n" + # J> j> J!> j!> | | "L>" is the same as "N" # | | # S< s< S!< s!< | Integer | same as the directives without "<" except # L< l< L!< l!< | | little endian # I!< i!< | | (available since Ruby 1.9.3) - # Q< q< Q!< q!< | | "S<" is same as "v" - # J< j< J!< j!< | | "L<" is same as "V" + # Q< q< Q!< q!< | | "S<" is the same as "v" + # J< j< J!< j!< | | "L<" is the same as "V" # | | # n | Integer | 16-bit unsigned, network (big-endian) byte order # N | Integer | 32-bit unsigned, network (big-endian) byte order @@ -131,17 +141,18 @@ class Array # X | --- | back up a byte # x | --- | null byte def pack(fmt, buffer: nil) - __builtin_pack_pack(fmt, buffer) + Primitive.pack_pack(fmt, buffer) end end class String # call-seq: # str.unpack(format) -> anArray + # str.unpack(format, offset: anInteger) -> anArray # # Decodes str (which may contain binary data) according to the - # format string, returning an array of each value extracted. The - # format string consists of a sequence of single-character directives, + # format string, returning an array of each value extracted. + # The format string consists of a sequence of single-character directives, # summarized in the table at the end of this entry. # Each directive may be followed # by a number, indicating the number of times to repeat with this @@ -151,7 +162,9 @@ class String # exclamation mark (``!'') to use the underlying # platform's native size for the specified type; otherwise, it uses a # platform-independent consistent size. Spaces are ignored in the - # format string. See also String#unpack1, Array#pack. + # format string. + # + # See also String#unpack1, Array#pack. # # "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "] # "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"] @@ -197,14 +210,14 @@ class String # S> s> S!> s!> | Integer | same as the directives without ">" except # L> l> L!> l!> | | big endian # I!> i!> | | - # Q> q> Q!> q!> | | "S>" is same as "n" - # J> j> J!> j!> | | "L>" is same as "N" + # Q> q> Q!> q!> | | "S>" is the same as "n" + # J> j> J!> j!> | | "L>" is the same as "N" # | | # S< s< S!< s!< | Integer | same as the directives without "<" except # L< l< L!< l!< | | little endian # I!< i!< | | - # Q< q< Q!< q!< | | "S<" is same as "v" - # J< j< J!< j!< | | "L<" is same as "V" + # Q< q< Q!< q!< | | "S<" is the same as "v" + # J< j< J!< j!< | | "L<" is the same as "V" # | | # n | Integer | 16-bit unsigned, network (big-endian) byte order # N | Integer | 32-bit unsigned, network (big-endian) byte order @@ -212,7 +225,7 @@ class String # V | Integer | 32-bit unsigned, VAX (little-endian) byte order # | | # U | Integer | UTF-8 character - # w | Integer | BER-compressed integer (see Array.pack) + # w | Integer | BER-compressed integer (see Array#pack) # # Float | | # Directive | Returns | Meaning @@ -248,20 +261,28 @@ class String # X | --- | skip backward one byte # x | --- | skip forward one byte # + # The keyword offset can be given to start the decoding after skipping + # the specified amount of bytes: + # "abc".unpack("C*") # => [97, 98, 99] + # "abc".unpack("C*", offset: 2) # => [99] + # "abc".unpack("C*", offset: 4) # => offset outside of string (ArgumentError) + # # HISTORY # # * J, J! j, and j! are available since Ruby 2.3. # * Q_, Q!, q_, and q! are available since Ruby 2.1. # * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3. - def unpack(fmt) - __builtin_pack_unpack(fmt) + def unpack(fmt, offset: 0) + Primitive.pack_unpack(fmt, offset) end # call-seq: # str.unpack1(format) -> obj + # str.unpack1(format, offset: anInteger) -> obj # # Decodes str (which may contain binary data) according to the # format string, returning the first value extracted. + # # See also String#unpack, Array#pack. # # Contrast with String#unpack: @@ -272,12 +293,19 @@ def unpack(fmt) # In that case data would be lost but often it's the case that the array # only holds one value, especially when unpacking binary data. For instance: # - # "\xff\x00\x00\x00".unpack("l") #=> [255] - # "\xff\x00\x00\x00".unpack1("l") #=> 255 + # "\xff\x00\x00\x00".unpack("l") #=> [255] + # "\xff\x00\x00\x00".unpack1("l") #=> 255 # # Thus unpack1 is convenient, makes clear the intention and signals # the expected return value to those reading the code. - def unpack1(fmt) - __builtin_pack_unpack1(fmt) + # + # The keyword offset can be given to start the decoding after skipping + # the specified amount of bytes: + # "abc".unpack1("C*") # => 97 + # "abc".unpack1("C*", offset: 2) # => 99 + # "abc".unpack1("C*", offset: 4) # => offset outside of string (ArgumentError) + # + def unpack1(fmt, offset: 0) + Primitive.pack_unpack1(fmt, offset) end end diff --git a/ruby/pack.rbinc b/ruby/pack.rbinc index 9a828a2e7..5fe20d585 100644 --- a/ruby/pack.rbinc +++ b/ruby/pack.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with pack.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_pack(void) +void Init_builtin_pack(void) { // table definition static const struct rb_builtin_function pack_table[] = { diff --git a/ruby/parse.c b/ruby/parse.c index 11823a7ea..ba5158c4e 100644 --- a/ruby/parse.c +++ b/ruby/parse.c @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -61,8 +65,8 @@ -/* Copy the first part of user declarations. */ -#line 12 "parse.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 12 "parse.y" #if !YYPURE @@ -74,18 +78,37 @@ #define YYLTYPE rb_code_location_t #define YYLTYPE_IS_DECLARED 1 -#include "ruby/ruby.h" -#include "ruby/st.h" -#include "ruby/encoding.h" +#include "ruby/config.h" + +#include +#include +#include + #include "internal.h" +#include "internal/compile.h" +#include "internal/complex.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/parse.h" +#include "internal/rational.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/util.h" +#include "internal/variable.h" #include "node.h" #include "parse.h" -#include "symbol.h" -#include "regenc.h" -#include -#include -#include #include "probes.h" +#include "regenc.h" +#include "ruby/encoding.h" +#include "ruby/regex.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "symbol.h" #ifndef WARN_PAST_SCOPE # define WARN_PAST_SCOPE 0 @@ -350,7 +373,6 @@ struct parser_params { unsigned int do_loop: 1; unsigned int do_chomp: 1; unsigned int do_split: 1; - unsigned int warn_location: 1; NODE *eval_tree_begin; NODE *eval_tree; @@ -1019,13 +1041,26 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in (void)0) static int looking_at_eol_p(struct parser_params *p); -#line 1023 "parse.c" /* yacc.c:339 */ +#line 1045 "parse.c" +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -1037,8 +1072,8 @@ static int looking_at_eol_p(struct parser_params *p); # define YYERROR_VERBOSE 0 #endif -/* In a future release of Bison, this section will be replaced - by #include "y.tab.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_YY_Y_TAB_H_INCLUDED # define YY_YY_Y_TAB_H_INCLUDED /* Debug traces. */ @@ -1181,10 +1216,9 @@ extern int yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 978 "parse.y" /* yacc.c:355 */ +#line 996 "parse.y" VALUE val; NODE *node; @@ -1194,9 +1228,9 @@ union YYSTYPE const struct vtable *vars; struct rb_strterm_struct *strterm; -#line 1196 "parse.c" /* yacc.c:355 */ -}; +#line 1230 "parse.c" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 @@ -1222,36 +1256,81 @@ int yyparse (struct parser_params *p); #endif /* !YY_YY_Y_TAB_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 1226 "parse.c" /* yacc.c:358 */ #ifdef short # undef short #endif -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif #endif -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; #else typedef signed char yytype_int8; #endif -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; #else -typedef unsigned short int yytype_uint16; +typedef short yytype_uint8; #endif -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; #else -typedef short int yytype_int16; +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif #endif #ifndef YYSIZE_T @@ -1259,15 +1338,27 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS @@ -1281,30 +1372,19 @@ typedef short int yytype_int16; # endif #endif -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) # else -# define YY_ATTRIBUTE(Spec) /* empty */ +# define YY_ATTRIBUTE_PURE # endif #endif -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - #ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) # else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# define YY_ATTRIBUTE_UNUSED # endif #endif @@ -1315,13 +1395,13 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value @@ -1334,6 +1414,20 @@ typedef short int yytype_int16; # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) #if ! defined yyoverflow || YYERROR_VERBOSE @@ -1411,18 +1505,19 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; + yy_state_t yyss_alloc; YYSTYPE yyvs_alloc; YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ + + YYSIZEOF (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 @@ -1435,11 +1530,11 @@ union yyalloc # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ - YYSIZE_T yynewbytes; \ + YYPTRDIFF_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ } \ while (0) @@ -1451,12 +1546,12 @@ union yyalloc # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ - YYSIZE_T yyi; \ + YYPTRDIFF_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ @@ -1468,27 +1563,28 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 13766 +#define YYLAST 13832 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 154 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 266 +#define YYNNTS 265 /* YYNRULES -- Number of rules. */ -#define YYNRULES 759 +#define YYNRULES 757 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 1243 +#define YYNSTATES 1241 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 353 + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 71, @@ -1531,84 +1627,84 @@ static const yytype_uint8 yytranslate[] = #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 1176, 1176, 1176, 1202, 1208, 1215, 1222, 1229, 1235, - 1236, 1242, 1255, 1253, 1264, 1275, 1281, 1288, 1295, 1302, - 1308, 1313, 1312, 1322, 1322, 1329, 1336, 1346, 1354, 1361, - 1369, 1377, 1389, 1401, 1411, 1425, 1426, 1434, 1442, 1451, - 1458, 1461, 1468, 1475, 1483, 1490, 1497, 1505, 1512, 1522, - 1527, 1536, 1539, 1540, 1544, 1548, 1552, 1557, 1564, 1566, - 1556, 1574, 1577, 1584, 1584, 1584, 1590, 1591, 1594, 1595, - 1604, 1614, 1624, 1633, 1644, 1651, 1658, 1665, 1672, 1680, - 1688, 1695, 1702, 1711, 1712, 1721, 1722, 1731, 1738, 1745, - 1752, 1759, 1766, 1773, 1780, 1787, 1794, 1803, 1804, 1813, - 1820, 1829, 1836, 1845, 1852, 1859, 1866, 1876, 1883, 1893, - 1900, 1907, 1917, 1924, 1931, 1938, 1945, 1952, 1959, 1966, - 1973, 1983, 1990, 1993, 2000, 2007, 2016, 2017, 2018, 2019, - 2024, 2031, 2038, 2041, 2048, 2048, 2058, 2059, 2060, 2061, - 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, - 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, - 2082, 2083, 2084, 2085, 2086, 2087, 2090, 2090, 2090, 2091, - 2091, 2092, 2092, 2092, 2093, 2093, 2093, 2093, 2094, 2094, - 2094, 2094, 2095, 2095, 2095, 2096, 2096, 2096, 2096, 2097, - 2097, 2097, 2097, 2098, 2098, 2098, 2098, 2099, 2099, 2099, - 2099, 2100, 2100, 2100, 2100, 2101, 2101, 2104, 2111, 2118, - 2126, 2134, 2142, 2150, 2158, 2165, 2173, 2182, 2191, 2203, - 2215, 2227, 2239, 2243, 2247, 2251, 2255, 2259, 2263, 2267, - 2271, 2275, 2279, 2283, 2287, 2291, 2292, 2296, 2300, 2304, - 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2336, 2341, - 2350, 2356, 2357, 2358, 2359, 2362, 2366, 2373, 2380, 2381, - 2385, 2392, 2401, 2406, 2417, 2424, 2453, 2454, 2457, 2458, - 2459, 2463, 2470, 2479, 2487, 2494, 2502, 2510, 2514, 2514, - 2551, 2560, 2564, 2570, 2577, 2584, 2591, 2600, 2601, 2604, - 2611, 2618, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, - 2635, 2636, 2637, 2645, 2644, 2659, 2659, 2666, 2666, 2674, - 2682, 2689, 2696, 2703, 2711, 2718, 2725, 2732, 2739, 2739, - 2744, 2748, 2752, 2759, 2760, 2769, 2768, 2779, 2790, 2801, - 2811, 2822, 2821, 2838, 2837, 2852, 2861, 2909, 2908, 2932, - 2931, 2954, 2953, 2977, 2983, 2976, 3003, 3004, 3003, 3029, - 3036, 3043, 3050, 3059, 3066, 3072, 3089, 3095, 3101, 3107, - 3113, 3119, 3125, 3131, 3137, 3143, 3149, 3155, 3161, 3167, - 3182, 3189, 3195, 3202, 3203, 3204, 3207, 3208, 3211, 3212, - 3224, 3225, 3234, 3235, 3238, 3246, 3255, 3262, 3271, 3278, - 3285, 3292, 3299, 3308, 3316, 3325, 3329, 3333, 3337, 3341, - 3347, 3352, 3357, 3361, 3365, 3369, 3373, 3377, 3385, 3389, - 3393, 3397, 3401, 3405, 3409, 3413, 3417, 3423, 3424, 3430, - 3439, 3451, 3455, 3464, 3466, 3470, 3475, 3481, 3484, 3488, - 3492, 3496, 3481, 3520, 3528, 3538, 3543, 3549, 3559, 3573, - 3580, 3587, 3596, 3605, 3613, 3621, 3628, 3636, 3644, 3651, - 3658, 3671, 3679, 3689, 3690, 3694, 3689, 3711, 3712, 3716, - 3711, 3735, 3743, 3750, 3758, 3767, 3779, 3780, 3784, 3790, - 3791, 3793, 3794, 3795, 3783, 3808, 3809, 3812, 3813, 3821, - 3831, 3832, 3837, 3845, 3849, 3855, 3858, 3867, 3870, 3877, - 3880, 3881, 3883, 3884, 3893, 3902, 3907, 3916, 3925, 3930, - 3930, 3935, 3941, 3940, 3952, 3957, 3957, 3964, 3973, 3977, - 3986, 3990, 3994, 3998, 4002, 4005, 4009, 4018, 4022, 4026, - 4030, 4036, 4037, 4046, 4055, 4059, 4063, 4067, 4071, 4075, - 4081, 4083, 4092, 4100, 4114, 4115, 4138, 4142, 4148, 4154, - 4155, 4164, 4173, 4185, 4197, 4198, 4199, 4200, 4212, 4226, - 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4242, 4241, - 4254, 4264, 4277, 4284, 4291, 4300, 4312, 4315, 4322, 4329, - 4332, 4336, 4339, 4346, 4349, 4350, 4353, 4370, 4371, 4372, - 4381, 4391, 4400, 4406, 4416, 4422, 4431, 4433, 4442, 4452, - 4458, 4467, 4476, 4486, 4492, 4502, 4508, 4518, 4528, 4547, - 4553, 4563, 4573, 4614, 4617, 4616, 4633, 4637, 4642, 4646, - 4650, 4632, 4671, 4678, 4685, 4692, 4695, 4696, 4699, 4709, - 4710, 4711, 4712, 4715, 4725, 4726, 4736, 4737, 4738, 4739, - 4742, 4743, 4744, 4745, 4746, 4749, 4750, 4751, 4752, 4753, - 4754, 4755, 4758, 4771, 4780, 4787, 4796, 4797, 4801, 4800, - 4810, 4818, 4827, 4842, 4842, 4856, 4860, 4864, 4868, 4872, - 4878, 4883, 4888, 4892, 4896, 4900, 4904, 4908, 4912, 4916, - 4920, 4924, 4928, 4932, 4936, 4940, 4945, 4951, 4960, 4968, - 4976, 4984, 4994, 4995, 5003, 5012, 5020, 5041, 5043, 5056, - 5066, 5074, 5084, 5091, 5100, 5107, 5117, 5124, 5133, 5134, - 5137, 5145, 5153, 5163, 5173, 5183, 5190, 5199, 5206, 5215, - 5216, 5219, 5227, 5237, 5238, 5241, 5251, 5255, 5261, 5266, - 5266, 5290, 5291, 5300, 5302, 5325, 5336, 5343, 5351, 5370, - 5371, 5372, 5375, 5376, 5377, 5378, 5381, 5382, 5383, 5386, - 5387, 5390, 5391, 5394, 5395, 5398, 5399, 5402, 5403, 5406, - 5409, 5412, 5415, 5416, 5417, 5420, 5421, 5424, 5425, 5429 +static const yytype_int16 yyrline[] = +{ + 0, 1194, 1194, 1194, 1220, 1226, 1233, 1240, 1247, 1253, + 1254, 1260, 1273, 1271, 1282, 1293, 1299, 1306, 1313, 1320, + 1326, 1331, 1330, 1340, 1340, 1347, 1354, 1364, 1372, 1379, + 1387, 1395, 1407, 1419, 1429, 1443, 1444, 1452, 1460, 1469, + 1476, 1479, 1487, 1495, 1504, 1512, 1520, 1528, 1536, 1546, + 1551, 1560, 1563, 1564, 1568, 1572, 1576, 1581, 1588, 1590, + 1580, 1598, 1601, 1608, 1608, 1608, 1614, 1615, 1618, 1619, + 1628, 1638, 1648, 1657, 1668, 1675, 1682, 1689, 1696, 1704, + 1712, 1719, 1726, 1735, 1736, 1745, 1746, 1755, 1762, 1769, + 1776, 1783, 1790, 1797, 1804, 1811, 1818, 1827, 1828, 1837, + 1844, 1853, 1860, 1869, 1876, 1883, 1890, 1900, 1907, 1917, + 1924, 1931, 1941, 1948, 1955, 1962, 1969, 1976, 1983, 1990, + 1997, 2007, 2014, 2017, 2024, 2031, 2040, 2041, 2042, 2043, + 2048, 2055, 2062, 2065, 2072, 2072, 2082, 2083, 2084, 2085, + 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, + 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, + 2106, 2107, 2108, 2109, 2110, 2111, 2114, 2114, 2114, 2115, + 2115, 2116, 2116, 2116, 2117, 2117, 2117, 2117, 2118, 2118, + 2118, 2118, 2119, 2119, 2119, 2120, 2120, 2120, 2120, 2121, + 2121, 2121, 2121, 2122, 2122, 2122, 2122, 2123, 2123, 2123, + 2123, 2124, 2124, 2124, 2124, 2125, 2125, 2128, 2135, 2142, + 2150, 2158, 2166, 2174, 2182, 2189, 2197, 2206, 2215, 2227, + 2239, 2251, 2263, 2267, 2271, 2275, 2279, 2283, 2287, 2291, + 2295, 2299, 2303, 2307, 2311, 2315, 2316, 2320, 2324, 2328, + 2332, 2336, 2340, 2344, 2348, 2352, 2356, 2360, 2360, 2365, + 2374, 2380, 2381, 2382, 2383, 2386, 2390, 2397, 2404, 2405, + 2409, 2416, 2425, 2430, 2441, 2448, 2477, 2478, 2481, 2482, + 2483, 2487, 2494, 2503, 2511, 2518, 2526, 2534, 2538, 2538, + 2575, 2584, 2588, 2594, 2601, 2608, 2615, 2624, 2625, 2628, + 2635, 2642, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, + 2659, 2660, 2661, 2669, 2668, 2683, 2683, 2690, 2690, 2698, + 2706, 2713, 2720, 2727, 2735, 2742, 2749, 2756, 2763, 2763, + 2768, 2772, 2776, 2783, 2784, 2793, 2792, 2803, 2814, 2825, + 2835, 2846, 2845, 2862, 2861, 2876, 2885, 2933, 2932, 2956, + 2955, 2978, 2977, 3001, 3007, 3000, 3027, 3028, 3027, 3053, + 3060, 3067, 3074, 3083, 3090, 3096, 3113, 3119, 3125, 3131, + 3137, 3143, 3149, 3155, 3161, 3167, 3173, 3179, 3185, 3191, + 3206, 3213, 3219, 3226, 3227, 3228, 3231, 3232, 3235, 3236, + 3248, 3249, 3258, 3259, 3262, 3270, 3279, 3286, 3295, 3302, + 3309, 3316, 3323, 3332, 3340, 3349, 3353, 3357, 3361, 3365, + 3371, 3376, 3381, 3385, 3389, 3393, 3397, 3401, 3409, 3413, + 3417, 3421, 3425, 3429, 3433, 3437, 3441, 3447, 3448, 3454, + 3463, 3475, 3479, 3488, 3490, 3494, 3499, 3505, 3508, 3512, + 3516, 3520, 3505, 3544, 3552, 3562, 3567, 3573, 3583, 3597, + 3604, 3611, 3620, 3629, 3637, 3645, 3652, 3660, 3668, 3675, + 3682, 3695, 3703, 3713, 3714, 3718, 3713, 3735, 3736, 3740, + 3735, 3759, 3767, 3774, 3782, 3791, 3803, 3804, 3808, 3814, + 3815, 3817, 3818, 3819, 3807, 3832, 3833, 3836, 3837, 3845, + 3855, 3856, 3861, 3869, 3873, 3879, 3882, 3891, 3894, 3901, + 3904, 3905, 3907, 3908, 3917, 3926, 3931, 3940, 3949, 3954, + 3954, 3959, 3964, 3964, 3969, 3974, 3974, 3981, 3990, 3994, + 4003, 4007, 4011, 4015, 4019, 4022, 4026, 4035, 4039, 4043, + 4047, 4053, 4054, 4063, 4072, 4076, 4080, 4084, 4088, 4094, + 4096, 4105, 4113, 4127, 4128, 4151, 4155, 4161, 4167, 4168, + 4177, 4186, 4198, 4210, 4211, 4212, 4213, 4225, 4239, 4240, + 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4255, 4254, 4267, + 4277, 4290, 4297, 4304, 4313, 4325, 4328, 4335, 4342, 4345, + 4349, 4352, 4359, 4362, 4363, 4366, 4383, 4384, 4385, 4394, + 4404, 4413, 4419, 4429, 4435, 4444, 4446, 4455, 4465, 4471, + 4480, 4489, 4499, 4505, 4515, 4521, 4531, 4541, 4560, 4566, + 4576, 4586, 4627, 4630, 4629, 4646, 4650, 4655, 4659, 4663, + 4645, 4684, 4691, 4698, 4705, 4708, 4709, 4712, 4722, 4723, + 4724, 4725, 4728, 4738, 4739, 4749, 4750, 4751, 4752, 4755, + 4756, 4757, 4758, 4759, 4762, 4763, 4764, 4765, 4766, 4767, + 4768, 4771, 4784, 4793, 4800, 4809, 4810, 4814, 4813, 4823, + 4831, 4840, 4855, 4855, 4869, 4873, 4877, 4881, 4885, 4891, + 4896, 4901, 4905, 4909, 4913, 4917, 4921, 4925, 4929, 4933, + 4937, 4941, 4945, 4949, 4953, 4958, 4964, 4973, 4981, 4989, + 4997, 5007, 5008, 5016, 5025, 5033, 5054, 5056, 5069, 5079, + 5087, 5097, 5104, 5113, 5120, 5130, 5137, 5146, 5147, 5150, + 5158, 5166, 5176, 5186, 5196, 5203, 5212, 5219, 5228, 5229, + 5232, 5240, 5250, 5251, 5254, 5264, 5268, 5274, 5279, 5279, + 5303, 5304, 5313, 5315, 5338, 5349, 5356, 5364, 5383, 5384, + 5385, 5388, 5389, 5390, 5391, 5394, 5395, 5396, 5399, 5400, + 5403, 5404, 5407, 5408, 5411, 5412, 5415, 5416, 5419, 5422, + 5425, 5426, 5427, 5430, 5431, 5434, 5435, 5439 }; #endif @@ -1695,14 +1791,14 @@ static const char *const yytname[] = "blkarg_mark", "f_block_arg", "opt_f_block_arg", "singleton", "$@56", "assoc_list", "assocs", "assoc", "operation", "operation2", "operation3", "dot_or_colon", "call_op", "call_op2", "opt_terms", "opt_nl", "rparen", - "rbracket", "rbrace", "trailer", "term", "terms", "none", YY_NULLPTR + "rbracket", "trailer", "term", "terms", "none", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = +static const yytype_int16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -1723,164 +1819,164 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -1028 +#define YYPACT_NINF (-1056) -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-1028))) +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) -#define YYTABLE_NINF -760 +#define YYTABLE_NINF (-758) -#define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-760))) +#define yytable_value_is_error(Yyn) \ + ((Yyn) == YYTABLE_NINF) /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { - -1028, 133, 3772, -1028, 9176, -1028, -1028, -1028, 8634, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, 9302, 9302, -1028, -1028, - -1028, 5241, 4800, -1028, -1028, -1028, -1028, 533, 8489, 1, - 100, 124, -1028, -1028, -1028, 4065, 4947, -1028, -1028, 4212, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 10940, 10940, - 10940, 10940, 200, 6689, 9428, 9806, 10184, 8918, -1028, 8344, - -1028, -1028, -1028, 155, 181, 247, 265, 1275, 11066, 10940, - -1028, 232, -1028, 1140, -1028, 319, -1028, -1028, 14, 411, - 330, -1028, 332, 11318, -1028, 380, 2654, 644, 46, 425, - -1028, 11192, 11192, -1028, -1028, 7671, 11440, 11562, 11684, 8198, - 9302, 819, 108, -1028, -1028, 456, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 717, 729, - -1028, 420, 783, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, 432, -1028, -1028, -1028, 479, 10940, 524, 6840, - 10940, 10940, 10940, -1028, 10940, -1028, 503, 4337, 542, -1028, - -1028, 513, 515, 267, 365, 614, 366, 545, -1028, -1028, - 7545, -1028, 9302, 9554, -1028, -1028, 7797, -1028, 11192, 858, - -1028, 574, 6991, -1028, 7142, -1028, -1028, 598, 605, 14, - -1028, 522, -1028, 718, 3380, 3380, 791, 9428, -1028, 6689, - 657, 232, -1028, 1140, 1, 682, -1028, 1140, 1, 665, - 371, 519, -1028, 542, 673, 519, -1028, 1, 763, 1275, - 11806, 677, -1028, 690, 708, 716, 724, -1028, -1028, -1028, - -1028, -1028, 481, -1028, 580, 678, 953, -1028, -1028, -1028, - -1028, 748, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 7923, - 11192, 11192, 11192, 11192, 9428, 11192, 11192, -1028, -1028, -1028, - 721, -1028, -1028, -1028, -1028, -1028, 10310, -1028, 6689, 9047, - 684, 10310, -1028, 10940, 10940, 10940, 10940, 10940, -1028, -1028, - 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, -1028, - -1028, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, 10940, - 10940, -1028, -1028, 12269, 9302, 12359, 5833, 319, 86, 86, - 7293, 11192, 7293, 232, -1028, 691, 777, -1028, -1028, 741, - 822, 53, 68, 69, 681, 956, 11192, 733, -1028, 714, - 891, -1028, -1028, -1028, -1028, 130, 291, 527, 572, 582, - 586, 608, 653, 663, -1028, -1028, -1028, 666, -1028, -1028, - -1028, 13619, -1028, -1028, 11066, 11066, -1028, -1028, 374, -1028, - -1028, -1028, 618, 10940, 10940, 9680, -1028, -1028, 12449, 9302, - 12539, 10940, 10940, 9932, -1028, 1, 710, -1028, -1028, 10940, - 1, -1028, 711, 1, 722, -1028, 107, -1028, -1028, -1028, - -1028, -1028, 8634, -1028, 10940, 726, 728, 12449, 12539, 10940, - 1140, 100, 1, -1028, -1028, 8049, 732, 1, -1028, -1028, - 10058, -1028, -1028, 10184, -1028, -1028, -1028, 574, 893, -1028, - -1028, 734, 11806, 12629, 9302, 12719, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 786, 101, - 988, 102, 10940, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, 757, -1028, -1028, -1028, 882, -1028, 882, 10940, - -1028, 760, 767, 874, -1028, 1, 11806, 774, -1028, -1028, - -1028, 880, 806, 4043, -1028, -1028, -1028, 963, 400, -1028, - 718, 3896, 3896, 3896, 3896, 4484, 3134, 3896, 3896, 3380, - 3380, 759, 759, 3267, 1222, 1222, 1464, 406, 406, 718, - 718, 718, 1115, 1115, 3482, 4359, 5535, 4506, -1028, 605, - -1028, 1, 850, -1028, 1016, -1028, -1028, 5094, 882, 925, - -1028, 5984, 922, 6437, 882, 60, 882, 914, 927, 76, - 12809, 9302, 12899, -1028, 319, -1028, 893, -1028, -1028, -1028, - 12989, 9302, 13079, 5833, 11192, -1028, -1028, -1028, -1028, -1028, - -1028, 2683, -1028, 4190, -1028, -1028, -1028, 8634, 10940, -1028, - 10940, 542, -1028, 545, 3918, 4653, 1, 453, 458, -1028, - -1028, -1028, -1028, 9680, -1028, 9932, -1028, -1028, 11192, 4337, - -1028, -1028, 605, 605, -1028, -1028, -9, -1028, -1028, 519, - 11806, 734, 381, 686, 1, 362, 407, -1028, -1028, 1249, - -1028, 566, -1028, 794, -1028, -1028, 568, 795, -1028, 718, - -1028, -1028, 804, -1028, -1028, -1028, -1028, 812, 10436, 9428, - -1028, 734, 11806, 9428, 11066, 10940, 13169, 9302, 13259, 12202, - 832, 11066, 11066, -1028, 721, 816, 1020, 11066, 11066, -1028, - -1028, 721, -1028, -1028, -1028, 10562, 755, -1028, 825, -1028, - 950, -1028, -1028, -1028, -1028, -1028, -1028, 927, 882, -1028, - 10688, 882, 33, 278, 1, 77, 83, 7293, 232, 11192, - 5833, 995, 686, -1028, 1, 882, 107, 820, 8779, 108, - 411, -1028, -1028, -1028, -1028, 10940, 10940, 462, 10940, 10940, - 824, 107, -1028, -1028, 626, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, 843, -1028, 843, - 10940, 833, -1028, 734, -1028, 4337, 5388, 5682, 1, 466, - 470, -1028, -1028, 3091, 3091, 751, -1028, 616, 345, -1028, - 940, 899, -1028, 871, -1028, -1028, 815, -1028, -1028, 336, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 10940, - -1028, -1028, -1028, -1028, -1028, -1028, 11066, -1028, -1028, -1028, - -1028, -1028, 760, -1028, 904, -1028, -1028, -1028, 7293, -1028, - -1028, -1028, -1028, 7293, 11192, 882, -1028, -1028, 882, -1028, - -1028, 882, -1028, 10940, -1028, 54, -1028, 113, 882, 5833, - 232, 882, -1028, -1028, -1028, 1877, 5833, 1686, -1028, -1028, - -1028, 10940, 9932, -1028, 1519, -1028, 1385, 7142, -1028, -1028, - 5833, 862, 538, -1028, -1028, -1028, -1028, 12202, 12083, -1028, - 257, 866, -1028, -1028, -1028, 964, -1028, 12202, 3091, 3091, - 751, 616, 547, 3621, 3621, 4337, -1028, -1028, 11928, 86, - -1028, -1028, 6563, -1028, 86, -1028, -1028, -1028, -1028, -1028, - 10814, 6135, -1028, 882, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, 1537, -1028, -1028, -1028, -1028, -1028, - -1028, 1, 1, -1028, -1028, 896, -1028, 877, 10940, -1028, - 883, 106, 887, 887, -1028, 894, 980, 895, 987, -1028, - 882, 232, 820, 1686, -1028, -1028, -1028, -1028, 1, 912, - 920, 901, 12050, -1028, 911, 887, 887, -1028, 916, 918, - -1028, 929, -1028, -1028, 276, 27, 3, 1, 12169, -1028, - 919, -1028, -1028, 1, 932, -1028, 12202, -1028, -1028, 348, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - 1, 1, 1, 1, 994, -1028, 1025, 118, 135, 179, - 5833, 1078, 5984, 3621, 10940, -1028, 92, -1028, 1537, 1208, - -1028, 949, 1, 954, -1028, -1028, -1028, 10940, 1686, -1028, - -1028, 1060, -1028, -1028, -1028, -1028, 216, -1028, -1028, 1686, - -1028, -1028, 1096, -1028, -1028, -1028, -1028, 5833, 1, 63, - 7419, 972, -1028, 12050, 1686, -1028, 1049, 1030, 1060, -1028, - -1028, -1028, 1686, -1028, 1096, -1028, 1424, -1028, 978, 12202, - -1028, 43, 899, 982, -1028, 288, -1028, 257, 899, -1028, - -1028, 1079, -1028, -1028, -1028, -1028, 222, 13349, 9302, 13439, - 925, -1028, 825, 86, 886, 255, -1028, -1028, -1028, -1028, - -1028, -1028, 1, -1028, 1537, -1028, 1560, -1028, -1028, -1028, - 983, 986, -1028, 1082, 887, -1028, 989, -1028, 990, -1028, - 989, 882, 992, 5833, 7142, -1028, 1019, -1028, 1030, -1028, - 998, 1001, -1028, 13529, -1028, 887, 1003, -1028, 1011, 1003, - -1028, 592, -1028, -1028, 12202, 1012, -1028, 1015, 12202, -1028, - -1028, -1028, -1028, -1028, 134, 158, 1, 315, 318, -1028, - -1028, -1028, 11192, 11192, 12083, -1028, -1028, 1017, 1021, 1686, - -1028, 1096, -1028, -1028, 1096, -1028, 1096, -1028, -1028, -1028, - -1028, 882, 1027, -1028, 1686, -1028, 1096, -1028, 1024, 1029, - -1028, 1096, -1028, 1096, -1028, -1028, 1424, -1028, 1012, 12202, - 12202, 1012, 457, -1028, -1028, -1028, -1028, 1560, 1560, 989, - 1041, 989, 989, -1028, -1028, 1003, 1043, 1003, 1003, -1028, - -1028, 1012, -1028, 1021, -1028, 1096, -1028, -1028, -1028, -1028, - 1096, -1028, -1028, -1028, 6286, 989, 1003, 150, -1028, -1028, - -1028, -1028, -1028 + -1056, 97, 3943, -1056, 9202, -1056, -1056, -1056, 8660, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, 9328, 9328, -1056, -1056, + -1056, 5267, 4826, -1056, -1056, -1056, -1056, -41, 8515, 18, + -33, 124, -1056, -1056, -1056, 3778, 4973, -1056, -1056, 4238, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 10966, 10966, + 10966, 10966, 90, 6715, 9454, 9832, 10210, 8944, -1056, 8370, + -1056, -1056, -1056, 72, 143, 146, 197, 1315, 11092, 10966, + -1056, 6, -1056, 1265, -1056, 411, -1056, -1056, 249, 152, + 253, -1056, 239, 11344, -1056, 279, 1752, 377, 542, 624, + -1056, 11218, 11218, -1056, -1056, 7697, 11466, 11588, 11710, 8224, + 9328, 48, 21, -1056, -1056, 281, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 394, 461, + -1056, 355, 498, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, 343, -1056, -1056, -1056, 346, 10966, 453, 6866, + 10966, 10966, 10966, -1056, 10966, -1056, 399, 4510, 448, -1056, + -1056, 357, 723, 9, 300, 438, 547, 423, -1056, -1056, + 7571, -1056, 9328, 9580, -1056, -1056, 7823, -1056, 11218, 336, + -1056, 430, 7017, -1056, 7168, -1056, -1056, 464, 483, 249, + -1056, 740, -1056, 565, 3504, 3504, 581, 9454, -1056, 6715, + 549, 6, -1056, 1265, 18, 586, -1056, 1265, 18, 568, + 588, 640, -1056, 448, 578, 640, -1056, 18, 690, 1315, + 11832, 617, -1056, 790, 858, 885, 923, -1056, -1056, -1056, + -1056, -1056, 362, -1056, 446, 562, 683, -1056, -1056, -1056, + -1056, 694, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 7949, + 11218, 11218, 11218, 11218, 9454, 11218, 11218, -1056, -1056, -1056, + 668, -1056, -1056, -1056, -1056, -1056, 10336, -1056, 6715, 9073, + 663, 10336, -1056, 10966, 10966, 10966, 10966, 10966, -1056, -1056, + 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, -1056, + -1056, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, 10966, + 10966, -1056, -1056, 12335, 9328, 12425, 5859, 411, 108, 108, + 7319, 11218, 7319, 6, -1056, 674, 758, -1056, -1056, 936, + 819, 53, 77, 126, 732, 827, 11218, 274, -1056, 727, + 940, -1056, -1056, -1056, -1056, 403, 437, 475, 517, 533, + 540, 543, 554, 558, -1056, -1056, -1056, 566, -1056, -1056, + -1056, 13685, -1056, -1056, 11092, 11092, -1056, -1056, 629, -1056, + -1056, -1056, 407, 10966, 10966, 9706, -1056, -1056, 12515, 9328, + 12605, 10966, 10966, 9958, -1056, 18, 718, -1056, -1056, 10966, + 18, -1056, 750, 18, 752, -1056, 96, -1056, -1056, -1056, + -1056, -1056, 8660, -1056, 10966, 729, 757, 12515, 12605, 10966, + 1265, -33, 18, -1056, -1056, 8075, 754, 18, -1056, -1056, + 10084, -1056, -1056, 10210, -1056, -1056, -1056, 430, 963, -1056, + -1056, 771, 11832, 12695, 9328, 12785, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 824, 101, + 992, 141, 10966, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, 759, -1056, -1056, -1056, 866, -1056, 866, 10966, + -1056, 773, 779, 860, -1056, 18, 11832, 781, -1056, -1056, + -1056, 884, 806, 4216, -1056, -1056, -1056, 1006, 644, -1056, + 565, 2696, 2696, 2696, 2696, 4071, 2908, 2696, 2696, 3504, + 3504, 814, 814, 3389, 1310, 1310, 1335, 24, 24, 565, + 565, 565, 1921, 1921, 3606, 4385, 5561, 4532, -1056, 483, + -1056, 18, 832, -1056, 870, -1056, -1056, 5120, 866, 922, + -1056, 6010, 921, 6463, 866, 37, 866, 935, 947, 153, + 12875, 9328, 12965, -1056, 411, -1056, 963, -1056, -1056, -1056, + 13055, 9328, 13145, 5859, 11218, -1056, -1056, -1056, -1056, -1056, + -1056, 3199, -1056, 4363, -1056, -1056, -1056, 8660, 10966, -1056, + 10966, 448, -1056, 423, 4091, 4679, 18, 655, 707, -1056, + -1056, -1056, -1056, 9706, -1056, 9958, -1056, -1056, 11218, 4510, + -1056, -1056, 483, 483, -1056, -1056, -6, -1056, -1056, 640, + 11832, 771, 57, 749, 18, 447, 519, -1056, -1056, 1173, + -1056, 538, -1056, 831, -1056, -1056, 553, 843, -1056, 565, + -1056, -1056, 822, -1056, -1056, -1056, -1056, 830, 10462, 9454, + -1056, 771, 11832, 9454, 11092, 10966, 13235, 9328, 13325, 12268, + 856, 11092, 11092, -1056, 668, 848, 875, 11092, 11092, -1056, + -1056, 668, -1056, -1056, -1056, 10588, 167, -1056, 817, -1056, + 991, -1056, -1056, -1056, -1056, -1056, -1056, 947, 866, -1056, + 10714, 866, 81, 177, 18, 288, 307, 7319, 6, 11218, + 5859, 1030, 749, -1056, 18, 866, 96, 862, 8805, 21, + 152, -1056, -1056, -1056, -1056, 10966, 10966, 714, 10966, 10966, + 868, 96, -1056, -1056, 607, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, 887, -1056, 887, + 10966, 876, -1056, 771, -1056, 4510, 5414, 5708, 18, 744, + 748, -1056, -1056, 2641, 2641, 534, -1056, 400, 881, -1056, + 975, 934, -1056, 904, -1056, -1056, 804, -1056, -1056, 267, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 10966, + -1056, -1056, -1056, -1056, -1056, -1056, 11092, -1056, -1056, -1056, + -1056, -1056, 773, -1056, 938, -1056, -1056, -1056, 7319, -1056, + -1056, -1056, -1056, 7319, 11218, 866, -1056, -1056, 866, -1056, + -1056, 866, -1056, 10966, -1056, 63, -1056, 330, 866, 5859, + 6, 866, -1056, -1056, -1056, 1233, 5859, 1709, -1056, -1056, + -1056, 10966, 9958, -1056, 1648, -1056, 1383, 7168, -1056, -1056, + 5859, 895, 756, -1056, -1056, -1056, -1056, 12268, 2069, -1056, + -1056, 687, -1056, -1056, 1000, -1056, 12268, 2641, 2641, 534, + 400, 501, 12149, 12149, 4510, -1056, -1056, 11954, 108, -1056, + -1056, 6589, -1056, 108, -1056, -1056, -1056, -1056, -1056, 10840, + 6161, -1056, 866, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, 1218, -1056, -1056, -1056, -1056, -1056, -1056, + 18, 18, -1056, -1056, 917, -1056, 907, 10966, -1056, 911, + 595, 916, 916, -1056, 919, 1015, 924, 1020, -1056, 866, + 6, 862, 1709, -1056, -1056, -1056, -1056, 18, 942, 949, + 932, 12076, -1056, 933, 916, 916, -1056, 943, 945, -1056, + 931, -1056, -1056, 206, 38, 117, 18, 12235, -1056, 948, + -1056, -1056, 952, 954, -1056, 12268, -1056, -1056, 679, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 18, 18, + 18, 18, 1060, -1056, 1049, 183, 292, 324, 5859, 1110, + 6010, 12149, 10966, -1056, 649, -1056, 1218, 1276, -1056, 974, + 18, 976, -1056, -1056, -1056, 10966, 1709, -1056, -1056, 1099, + -1056, -1056, -1056, -1056, 359, -1056, -1056, 1709, -1056, -1056, + 1860, -1056, -1056, -1056, -1056, 5859, 18, 123, 7445, 994, + -1056, 12076, 1709, -1056, 1074, 1070, 1099, -1056, -1056, -1056, + 1709, -1056, 1860, -1056, 1293, -1056, 988, 12268, -1056, 163, + 934, 990, -1056, 717, -1056, 687, 934, -1056, -1056, 730, + -1056, -1056, -1056, -1056, 360, 13415, 9328, 13505, 922, -1056, + 817, 108, 838, 295, -1056, -1056, -1056, -1056, -1056, -1056, + 18, -1056, 1218, -1056, 855, -1056, -1056, -1056, 993, 996, + -1056, 1091, 916, -1056, 998, -1056, 1001, -1056, 998, 866, + 999, 5859, 7168, -1056, 1032, -1056, 1070, -1056, 1009, 1014, + -1056, 13595, -1056, 916, 1017, -1056, 1019, 1017, -1056, 710, + -1056, -1056, 12268, 1023, -1056, 1026, 12268, -1056, -1056, -1056, + -1056, -1056, 105, 187, 18, 371, 396, -1056, -1056, -1056, + 11218, 11218, 2069, -1056, -1056, 1037, 1038, 1709, -1056, 1860, + -1056, -1056, 1860, -1056, 1860, -1056, -1056, -1056, -1056, 866, + 1042, -1056, 1709, -1056, 1860, -1056, 1013, 1040, -1056, 1860, + -1056, 1860, -1056, -1056, 1293, -1056, 1023, 12268, 12268, 1023, + 406, -1056, -1056, -1056, -1056, 855, 855, 998, 1052, 998, + 998, -1056, -1056, 1017, 1053, 1017, 1017, -1056, -1056, 1023, + -1056, 1038, -1056, 1860, -1056, -1056, -1056, -1056, 1860, -1056, + -1056, -1056, 6312, 998, 1017, 80, -1056, -1056, -1056, -1056, + -1056 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ -static const yytype_uint16 yydefact[] = +static const yytype_int16 yydefact[] = { 2, 0, 0, 1, 0, 361, 362, 363, 0, 354, 355, 356, 359, 357, 358, 360, 349, 350, 351, 352, - 372, 278, 278, 636, 635, 637, 638, 747, 0, 747, - 0, 0, 640, 639, 641, 729, 731, 632, 631, 730, - 634, 626, 627, 628, 629, 577, 646, 647, 0, 0, - 0, 0, 0, 0, 305, 759, 759, 95, 325, 597, - 597, 599, 601, 0, 0, 0, 0, 0, 0, 0, - 3, 745, 6, 9, 35, 40, 52, 67, 278, 66, + 372, 278, 278, 635, 634, 636, 637, 746, 0, 746, + 0, 0, 639, 638, 640, 728, 730, 631, 630, 729, + 633, 625, 626, 627, 628, 576, 645, 646, 0, 0, + 0, 0, 0, 0, 305, 757, 757, 95, 325, 596, + 596, 598, 600, 0, 0, 0, 0, 0, 0, 0, + 3, 744, 6, 9, 35, 40, 52, 67, 278, 66, 0, 83, 0, 87, 97, 0, 61, 235, 250, 0, - 303, 0, 0, 63, 63, 745, 0, 0, 0, 0, - 314, 68, 323, 292, 293, 576, 578, 294, 295, 296, - 298, 297, 299, 575, 616, 617, 574, 624, 642, 643, + 303, 0, 0, 63, 63, 744, 0, 0, 0, 0, + 314, 68, 323, 292, 293, 575, 577, 294, 295, 296, + 298, 297, 299, 574, 615, 616, 573, 623, 641, 642, 300, 0, 301, 71, 5, 8, 176, 187, 177, 200, 173, 193, 183, 182, 203, 204, 198, 181, 180, 175, 201, 205, 206, 185, 174, 188, 192, 194, 186, 179, @@ -1890,174 +1986,174 @@ static const yytype_uint16 yydefact[] = 143, 163, 164, 149, 150, 154, 158, 144, 146, 136, 137, 138, 151, 152, 153, 155, 156, 159, 160, 165, 131, 133, 28, 129, 130, 132, 0, 0, 0, 0, - 0, 0, 0, 597, 0, 273, 0, 257, 283, 81, - 277, 759, 0, 642, 643, 0, 301, 759, 723, 82, - 747, 79, 0, 759, 448, 78, 747, 748, 0, 0, + 0, 0, 0, 596, 0, 273, 0, 257, 283, 81, + 277, 757, 0, 641, 642, 0, 301, 757, 722, 82, + 746, 79, 0, 757, 448, 78, 746, 747, 0, 0, 23, 247, 0, 10, 0, 349, 350, 317, 449, 0, 229, 0, 314, 230, 220, 221, 311, 0, 21, 0, - 0, 745, 17, 20, 747, 85, 16, 307, 747, 0, - 752, 752, 258, 0, 0, 752, 721, 747, 0, 0, - 0, 93, 353, 0, 103, 104, 111, 427, 621, 620, - 622, 619, 0, 618, 0, 0, 0, 584, 593, 589, - 595, 625, 56, 241, 242, 755, 756, 4, 757, 746, + 0, 744, 17, 20, 746, 85, 16, 307, 746, 0, + 750, 750, 258, 0, 0, 750, 720, 746, 0, 0, + 0, 93, 353, 0, 103, 104, 111, 427, 620, 619, + 621, 618, 0, 617, 0, 0, 0, 583, 592, 588, + 594, 624, 56, 241, 242, 753, 754, 4, 755, 745, 0, 0, 0, 0, 0, 0, 0, 364, 453, 442, 72, 457, 322, 365, 457, 438, 0, 99, 0, 91, 88, 0, 57, 0, 0, 0, 0, 0, 253, 254, 0, 0, 0, 0, 218, 219, 0, 0, 0, 251, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 741, 742, 0, 759, 0, 0, 62, 0, 0, - 0, 0, 0, 745, 333, 746, 0, 383, 382, 0, - 0, 642, 643, 301, 121, 122, 0, 0, 124, 650, - 0, 642, 643, 301, 341, 196, 189, 199, 184, 166, - 167, 168, 126, 127, 719, 343, 718, 0, 80, 744, - 743, 0, 324, 579, 0, 0, 134, 726, 311, 284, - 728, 280, 0, 0, 0, 0, 274, 282, 0, 759, - 0, 0, 0, 0, 275, 747, 0, 316, 279, 677, - 747, 269, 759, 747, 759, 268, 747, 321, 55, 25, + 0, 740, 741, 0, 757, 0, 0, 62, 0, 0, + 0, 0, 0, 744, 333, 745, 0, 383, 382, 0, + 0, 641, 642, 301, 121, 122, 0, 0, 124, 649, + 0, 641, 642, 301, 341, 196, 189, 199, 184, 166, + 167, 168, 126, 127, 718, 343, 717, 0, 80, 743, + 742, 0, 324, 578, 0, 0, 134, 725, 311, 284, + 727, 280, 0, 0, 0, 0, 274, 282, 0, 757, + 0, 0, 0, 0, 275, 746, 0, 316, 279, 676, + 746, 269, 757, 746, 757, 268, 746, 321, 55, 25, 27, 26, 0, 318, 0, 0, 0, 0, 0, 0, - 19, 0, 747, 309, 15, 746, 84, 747, 306, 312, - 754, 753, 259, 754, 261, 313, 722, 0, 110, 625, - 101, 96, 0, 0, 759, 0, 326, 428, 603, 623, - 606, 604, 598, 580, 581, 600, 582, 602, 0, 0, - 0, 0, 0, 758, 7, 29, 30, 31, 32, 33, + 19, 0, 746, 309, 15, 745, 84, 746, 306, 312, + 752, 751, 259, 752, 261, 313, 721, 0, 110, 624, + 101, 96, 0, 0, 757, 0, 326, 428, 602, 622, + 605, 603, 597, 579, 580, 599, 581, 601, 0, 0, + 0, 0, 0, 756, 7, 29, 30, 31, 32, 33, 53, 54, 0, 454, 453, 73, 0, 458, 0, 0, - 36, 288, 0, 39, 287, 747, 0, 89, 100, 51, + 36, 288, 0, 39, 287, 746, 0, 89, 100, 51, 41, 49, 0, 262, 283, 207, 37, 0, 301, 58, 227, 234, 236, 237, 238, 245, 246, 239, 240, 216, - 217, 243, 244, 747, 231, 232, 233, 222, 223, 224, - 225, 226, 255, 256, 732, 734, 733, 735, 447, 278, - 445, 747, 732, 734, 733, 735, 446, 278, 0, 759, + 217, 243, 244, 746, 231, 232, 233, 222, 223, 224, + 225, 226, 255, 256, 731, 733, 732, 734, 447, 278, + 445, 746, 731, 733, 732, 734, 446, 278, 0, 757, 374, 0, 373, 0, 0, 0, 0, 331, 0, 311, - 0, 759, 0, 63, 339, 121, 122, 123, 648, 337, - 0, 759, 0, 0, 0, 344, 739, 740, 346, 732, - 733, 278, 42, 262, 208, 48, 215, 0, 0, 725, - 0, 285, 281, 759, 732, 733, 747, 732, 733, 724, - 315, 749, 264, 270, 265, 272, 320, 24, 0, 248, - 11, 34, 0, 759, 214, 22, 86, 18, 308, 752, - 0, 94, 736, 109, 747, 732, 733, 429, 607, 0, - 583, 0, 586, 0, 591, 588, 0, 0, 592, 228, + 0, 757, 0, 63, 339, 121, 122, 123, 647, 337, + 0, 757, 0, 0, 0, 344, 738, 739, 346, 731, + 732, 278, 42, 262, 208, 48, 215, 0, 0, 724, + 0, 285, 281, 757, 731, 732, 746, 731, 732, 723, + 315, 748, 264, 270, 265, 272, 320, 24, 0, 248, + 11, 34, 0, 757, 214, 22, 86, 18, 308, 750, + 0, 94, 735, 109, 746, 731, 732, 429, 606, 0, + 582, 0, 585, 0, 590, 587, 0, 0, 591, 228, 451, 455, 0, 371, 452, 459, 437, 291, 0, 0, - 98, 92, 0, 0, 0, 0, 0, 759, 0, 0, + 98, 92, 0, 0, 0, 0, 0, 757, 0, 0, 0, 0, 0, 444, 76, 0, 450, 0, 0, 267, - 443, 74, 266, 304, 366, 759, 759, 566, 759, 375, - 759, 329, 377, 64, 376, 330, 468, 0, 0, 368, - 0, 0, 736, 310, 747, 732, 733, 0, 0, 0, - 0, 121, 122, 125, 747, 0, 747, 653, 0, 439, - 69, 135, 727, 286, 276, 0, 0, 450, 0, 0, - 759, 747, 260, 102, 450, 430, 608, 612, 613, 614, - 605, 615, 585, 587, 594, 590, 596, 759, 70, 759, - 0, 289, 38, 90, 50, 263, 732, 733, 747, 732, - 733, 560, 564, 0, 0, 0, 505, 499, 502, 558, - 0, 59, 485, 487, 489, 492, 539, 544, 545, 546, - 549, 550, 551, 552, 553, 555, 554, 556, 557, 0, - 47, 212, 46, 213, 77, 750, 0, 44, 210, 45, - 211, 75, 567, 568, 759, 569, 367, 369, 0, 12, - 14, 573, 370, 0, 0, 0, 378, 380, 0, 65, + 443, 74, 266, 304, 366, 757, 757, 565, 757, 375, + 757, 329, 377, 64, 376, 330, 468, 0, 0, 368, + 0, 0, 735, 310, 746, 731, 732, 0, 0, 0, + 0, 121, 122, 125, 746, 0, 746, 652, 0, 439, + 69, 135, 726, 286, 276, 0, 0, 450, 0, 0, + 757, 746, 260, 102, 450, 430, 607, 611, 612, 613, + 604, 614, 584, 586, 593, 589, 595, 757, 70, 757, + 0, 289, 38, 90, 50, 263, 731, 732, 746, 731, + 732, 559, 563, 0, 0, 0, 505, 499, 502, 557, + 0, 59, 485, 487, 489, 492, 538, 543, 544, 545, + 548, 549, 550, 551, 552, 554, 553, 555, 556, 0, + 47, 212, 46, 213, 77, 749, 0, 44, 210, 45, + 211, 75, 566, 567, 757, 568, 367, 369, 0, 12, + 14, 572, 370, 0, 0, 0, 378, 380, 0, 65, 469, 0, 335, 0, 461, 0, 334, 450, 0, 0, - 0, 0, 450, 342, 720, 676, 0, 676, 347, 440, - 441, 0, 271, 319, 676, 609, 747, 0, 418, 417, - 0, 290, 450, 547, 548, 122, 562, 0, 0, 501, - 0, 0, 504, 427, 561, 0, 60, 0, 542, 543, - 0, 491, 490, 0, 0, 249, 43, 209, 0, 0, - 571, 572, 0, 381, 0, 327, 328, 470, 332, 462, - 0, 0, 336, 0, 649, 338, 683, 680, 679, 678, - 681, 689, 698, 677, 0, 710, 699, 714, 713, 709, - 675, 747, 747, 682, 684, 685, 687, 661, 691, 696, - 759, 702, 759, 759, 707, 661, 712, 661, 0, 659, - 0, 0, 653, 676, 431, 434, 610, 416, 747, 0, - 685, 401, 693, 694, 759, 759, 759, 705, 401, 401, - 399, 421, 456, 460, 747, 519, 507, 747, 508, 514, - 0, 534, 597, 747, 525, 530, 533, 527, 529, 537, - 751, 559, 486, 488, 540, 541, 563, 498, 495, 597, - 747, 747, 747, 747, 0, 570, 0, 642, 643, 301, - 0, 759, 0, 0, 0, 463, 759, 340, 0, 394, - 386, 388, 747, 391, 384, 651, 652, 0, 0, 668, - 690, 0, 656, 717, 700, 701, 0, 658, 657, 0, - 671, 711, 0, 673, 715, 345, 654, 0, 747, 0, - 0, 0, 419, 0, 407, 409, 0, 692, 0, 396, - 398, 397, 0, 412, 0, 414, 0, 506, 517, 0, - 500, 512, 523, 509, 515, 0, 503, 526, 532, 538, - 536, 0, 493, 494, 496, 497, 311, 0, 759, 0, - 759, 13, 759, 0, 477, 480, 483, 484, 464, 466, - 467, 465, 747, 393, 0, 686, 0, 703, 660, 688, - 661, 661, 697, 702, 759, 716, 661, 708, 661, 685, - 661, 0, 0, 0, 0, 432, 0, 420, 704, 400, - 401, 401, 311, 0, 695, 759, 401, 706, 401, 401, - 425, 747, 423, 426, 0, 520, 521, 510, 0, 516, - 535, 531, 524, 528, 736, 310, 747, 732, 733, 565, - 379, 471, 0, 0, 481, 385, 387, 389, 392, 0, - 664, 0, 666, 655, 0, 672, 0, 669, 674, 348, - 433, 0, 0, 611, 0, 404, 0, 406, 736, 310, - 395, 0, 413, 0, 410, 415, 0, 422, 518, 0, - 0, 513, 450, 472, 478, 479, 482, 0, 0, 661, - 661, 661, 661, 436, 435, 401, 401, 401, 401, 424, - 522, 511, 473, 390, 665, 0, 662, 667, 670, 405, - 0, 402, 408, 411, 0, 661, 401, 759, 663, 403, - 475, 476, 474 + 0, 0, 450, 342, 719, 675, 0, 675, 347, 440, + 441, 0, 271, 319, 675, 608, 746, 0, 418, 417, + 0, 290, 450, 546, 547, 122, 561, 0, 0, 501, + 504, 0, 427, 560, 0, 60, 0, 541, 542, 0, + 491, 490, 0, 0, 249, 43, 209, 0, 0, 570, + 571, 0, 381, 0, 327, 328, 470, 332, 462, 0, + 0, 336, 0, 648, 338, 682, 679, 678, 677, 680, + 688, 697, 676, 0, 709, 698, 713, 712, 708, 674, + 746, 746, 681, 683, 684, 686, 660, 690, 695, 757, + 701, 757, 757, 706, 660, 711, 660, 0, 658, 0, + 0, 652, 675, 431, 434, 609, 416, 746, 0, 684, + 401, 692, 693, 757, 757, 757, 704, 401, 401, 399, + 421, 456, 460, 746, 519, 507, 746, 508, 514, 0, + 533, 596, 0, 525, 529, 532, 526, 528, 536, 558, + 486, 488, 539, 540, 562, 498, 495, 596, 746, 746, + 746, 746, 0, 569, 0, 641, 642, 301, 0, 757, + 0, 0, 0, 463, 757, 340, 0, 394, 386, 388, + 746, 391, 384, 650, 651, 0, 0, 667, 689, 0, + 655, 716, 699, 700, 0, 657, 656, 0, 670, 710, + 0, 672, 714, 345, 653, 0, 746, 0, 0, 0, + 419, 0, 407, 409, 0, 691, 0, 396, 398, 397, + 0, 412, 0, 414, 0, 506, 517, 0, 500, 512, + 523, 509, 515, 0, 503, 0, 531, 537, 535, 0, + 493, 494, 496, 497, 311, 0, 757, 0, 757, 13, + 757, 0, 477, 480, 483, 484, 464, 466, 467, 465, + 746, 393, 0, 685, 0, 702, 659, 687, 660, 660, + 696, 701, 757, 715, 660, 707, 660, 684, 660, 0, + 0, 0, 0, 432, 0, 420, 703, 400, 401, 401, + 311, 0, 694, 757, 401, 705, 401, 401, 425, 746, + 423, 426, 0, 520, 521, 510, 0, 516, 534, 530, + 524, 527, 735, 310, 746, 731, 732, 564, 379, 471, + 0, 0, 481, 385, 387, 389, 392, 0, 663, 0, + 665, 654, 0, 671, 0, 668, 673, 348, 433, 0, + 0, 610, 0, 404, 0, 406, 735, 310, 395, 0, + 413, 0, 410, 415, 0, 422, 518, 0, 0, 513, + 450, 472, 478, 479, 482, 0, 0, 660, 660, 660, + 660, 436, 435, 401, 401, 401, 401, 424, 522, 511, + 473, 390, 664, 0, 661, 666, 669, 405, 0, 402, + 408, 411, 0, 660, 401, 757, 662, 403, 475, 476, + 474 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1028, -1028, -1028, 923, -1028, 62, 730, -552, -1028, -35, - -1028, 731, -1028, 72, -1028, -212, -254, -66, -1028, -1028, - -1028, -32, -88, -1028, -1028, -36, -1028, -260, 641, 25, - 1106, -141, -6, -68, -1028, -410, -19, 2212, -370, 1108, - -40, -24, -1028, -1028, 5, -1028, 2954, -1028, 1121, -1028, - 1541, -1028, 652, 426, 601, -307, 94, -10, -1028, -360, - -218, 66, -1028, -310, -52, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, 32, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, 509, -1028, 210, 981, -368, - -1028, 126, -700, -1028, -1024, -1001, 198, 116, 355, 317, - -1028, 461, -1028, -860, -1028, 30, 350, -1028, -1028, -1028, - -1028, -1028, -1028, -1028, 494, -1028, -1028, -95, 723, -1028, - -1028, -1028, 915, -1028, -1028, -1028, -1028, -680, -1028, -1, - -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -1028, -526, - -1028, -1028, -1028, -1028, 354, -1028, -1028, -1028, -824, -1028, - 230, -609, -594, -781, -1028, 177, -1028, 178, 190, -1028, - -376, -1028, 373, -1028, -1028, 166, -1028, -1028, 263, 485, - 499, -1028, 1171, 747, 1110, 1394, -1028, 780, 1448, -1028, - 1612, 1744, -1028, -1028, -57, -1028, -1028, -199, -1028, -1028, - -1028, -1028, -1028, -1028, -1028, 0, -1028, -1028, -1028, -1028, - -37, 2020, 1174, 1178, 2236, 1512, -1028, -1028, 329, -1028, - -705, 314, -773, 429, -1027, -785, -603, -908, 236, -200, - 258, 243, -1028, -1028, -503, -690, -213, -984, -987, 234, - 274, -1028, -846, -1028, -513, -379, -1028, -1028, -1028, 6, - -417, -1028, -275, -1028, -1028, -87, -1028, -71, 23, 185, - -583, 322, -194, -60, -44, -2 + -1056, -1056, -1056, 953, -1056, 22, 743, -541, -1056, -51, + -1056, 736, -1056, 115, -1056, -228, -321, -68, -1056, -1056, + -1056, -32, -72, -1056, -1056, 2, -1056, -5, 735, 4, + 1113, -175, 26, -76, -1056, -452, -19, 2254, -362, 1108, + -43, -14, -1056, -1056, 0, -1056, 3078, -1056, 1123, -1056, + 778, -1056, 709, 133, 601, -307, 121, -13, -1056, -283, + -209, -4, -1056, -314, -25, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, 32, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, 507, -1056, -296, 1267, -365, + -1056, 127, -700, -1056, -1027, -1024, 200, 119, 363, 165, + -1056, 454, -1056, -874, -1056, 40, 349, -1056, -1056, -1056, + -1056, -1056, -1056, -1056, 495, -1056, -1056, -96, 722, -1056, + -1056, -1056, 915, -1056, -1056, -1056, -1056, -698, -1056, 5, + -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -1056, -591, + -1056, -1056, -1056, -1056, 361, -1056, -1056, -1056, -851, -1056, + 230, -1055, -711, -779, -1056, 168, -1056, 170, 171, -1056, + -409, -1056, 366, -1056, -1056, 166, -1056, -1056, 246, 28, + 375, -1056, 1151, 666, 777, 842, -1056, 760, 1516, -1056, + 2119, 2191, -1056, -1056, -59, -1056, -1056, -229, -1056, -1056, + -1056, -1056, -1056, -1056, -1056, 3, -1056, -1056, -1056, -1056, + -27, 2015, 1563, 1159, 2490, 1953, -1056, -1056, 314, -1056, + -390, 71, -701, 421, -1019, -433, 145, -971, 75, -404, + 248, 226, -1056, -1056, -214, -674, -320, -969, -991, 234, + 266, -1056, -616, -1056, 162, -816, -1056, -1056, -1056, 157, + -396, -1056, -319, -1056, -1056, -86, -1056, -7, 23, 56, + -593, -236, -66, -28, -2 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 70, 71, 72, 243, 578, 902, 579, + -1, 1, 2, 70, 71, 72, 243, 578, 901, 579, 261, 262, 461, 263, 452, 74, 530, 75, 539, 689, - 886, 368, 370, 371, 839, 76, 77, 515, 249, 79, + 885, 368, 370, 371, 839, 76, 77, 515, 249, 79, 80, 264, 81, 82, 83, 481, 84, 216, 388, 389, 200, 201, 202, 617, 567, 204, 86, 454, 359, 87, 218, 269, 535, 568, 700, 440, 441, 231, 232, 220, 426, 442, 523, 524, 88, 366, 268, 467, 638, 287, - 717, 588, 730, 728, 603, 605, 737, 738, 952, 251, + 717, 588, 730, 728, 603, 605, 737, 738, 951, 251, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 321, 324, 705, 828, 720, 833, 834, 674, 252, 581, - 713, 835, 836, 380, 1020, 1021, 1022, 1023, 1129, 1055, - 958, 867, 868, 959, 1141, 1142, 486, 487, 657, 755, - 864, 1049, 954, 1125, 325, 101, 102, 322, 512, 513, - 671, 767, 516, 517, 675, 769, 845, 721, 1101, 718, - 840, 907, 1013, 1203, 1222, 1234, 1242, 1093, 1094, 1072, - 792, 793, 893, 894, 794, 878, 880, 877, 977, 978, - 979, 1145, 980, 983, 984, 985, 986, 987, 988, 795, - 796, 883, 797, 798, 799, 706, 824, 899, 830, 103, + 713, 835, 836, 380, 1018, 1019, 1020, 1021, 1127, 1053, + 957, 867, 868, 958, 1139, 1140, 486, 487, 657, 755, + 864, 1047, 953, 1123, 325, 101, 102, 322, 512, 513, + 671, 767, 516, 517, 675, 769, 845, 721, 1099, 718, + 840, 906, 1011, 1201, 1220, 1232, 1240, 1091, 1092, 1070, + 792, 793, 892, 893, 794, 878, 881, 877, 976, 977, + 978, 1143, 979, 982, 983, 984, 985, 986, 987, 795, + 796, 882, 797, 798, 799, 706, 824, 898, 830, 103, 104, 105, 106, 107, 108, 109, 498, 661, 110, 500, 111, 112, 499, 501, 292, 295, 296, 492, 659, 658, - 756, 865, 956, 1050, 760, 113, 114, 293, 115, 116, + 756, 865, 955, 1048, 760, 113, 114, 293, 115, 116, 117, 223, 224, 120, 225, 226, 599, 729, 856, 857, - 1108, 1029, 931, 443, 933, 934, 1119, 936, 937, 938, - 939, 963, 964, 940, 941, 942, 943, 944, 967, 968, - 945, 946, 947, 948, 949, 1032, 407, 604, 274, 444, + 1106, 1027, 930, 443, 932, 933, 1117, 935, 936, 937, + 938, 962, 963, 939, 940, 941, 942, 943, 966, 967, + 944, 945, 946, 947, 948, 1030, 407, 604, 274, 444, 228, 123, 642, 570, 608, 602, 411, 307, 436, 437, - 696, 882, 472, 582, 375, 266 + 696, 472, 582, 375, 266 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -2065,678 +2161,595 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 124, 583, 365, 294, 240, 282, 372, 412, 205, 434, - 838, 308, 235, 203, 410, 330, 629, 597, 260, 291, - 969, 536, 227, 227, 374, 367, 367, 309, 205, 367, - 301, 282, 302, 203, 89, 308, 89, 841, 281, 1143, - 317, 215, 215, 747, 282, 282, 282, 265, 222, 222, - 238, 735, 241, 272, 276, 1117, 629, 571, -116, 405, - 369, 271, 275, 373, 203, 622, 125, 580, 320, 1000, - 1002, 754, 651, 622, 73, 1137, 73, 474, -112, 1068, - 1166, 476, 221, 221, 951, 89, 89, 712, 569, 283, - 577, 955, 1123, -113, -120, 1147, 495, 497, 1051, 580, - 222, -119, -115, 885, 203, 1168, 227, 827, -117, 719, - 219, 229, 1001, 1003, -353, 283, 681, -84, 462, 529, - 1109, 270, 626, 222, 222, 215, 267, 222, 379, 390, - 390, -112, 222, 3, 317, 430, 611, -98, -114, 1024, - 1034, 847, -353, -353, 315, 316, 1109, -116, -113, -523, - 930, 852, 930, 569, 237, 577, 422, 318, 1035, 930, - 612, 615, 233, 791, 458, 827, 221, 663, 667, 1143, - 446, -118, 448, 1069, 260, 716, 965, 654, 851, -107, - 1048, -732, 1111, 643, 1166, 1117, 1124, 525, 1122, 1148, - 464, -353, -120, 1118, 408, 872, 485, 1137, -636, -103, - 910, 308, 529, 529, 879, 305, 1223, 306, 1131, 456, - 643, 305, 480, 306, -104, -111, 1138, 465, 629, 427, - 664, 668, -110, -106, 260, 427, 434, -636, 282, -108, - 733, 445, 1097, 1024, 1103, -119, 227, 305, 227, 306, - 124, 89, 479, 242, 367, 367, 367, 367, 930, 510, - 511, 318, 935, 265, 935, 215, 256, 215, 215, -105, - 237, 935, 222, 960, 222, 222, 1109, 244, 222, -112, - 222, -112, 773, 622, 89, 622, 89, 282, 505, 506, - 507, 508, -732, 1109, 724, -116, -113, -116, -113, 89, - 520, 89, 592, 260, 734, 531, 221, 913, 221, 662, - 477, 662, 587, -118, 950, 367, -733, 297, 997, -118, - 527, -118, 283, 308, 73, 981, 1099, 643, 973, 1024, - 594, 1024, 265, 1210, 435, 927, 438, 643, -115, 460, - -120, -117, -120, 298, 922, 584, 1100, 586, 1216, 585, - 1206, 89, 222, 222, 222, 222, 89, 222, 222, 928, - 935, 974, 976, 970, 488, 885, 315, 316, 222, -635, - 89, 283, 445, 537, 965, 926, -644, 976, 976, 982, - 575, 504, 965, -119, 965, -119, 885, 989, 531, 531, - 778, 73, 1079, 305, 1073, 306, 509, -106, -635, 215, - 989, 989, 522, -112, 1070, 823, 222, 522, 89, 299, - 1080, 1164, 89, 222, 89, 744, -107, 873, 874, 490, - 491, 569, 1150, 577, 480, 876, 575, 300, 222, 1084, - 1085, 447, 1024, 1024, -109, 935, -733, 445, 637, 237, - 282, 623, -108, 890, 814, 575, 935, 810, 812, 323, - 427, 821, 427, 817, 819, 629, 537, 537, 234, 466, - 688, 960, 205, 468, 215, 752, 326, 203, 480, 960, - 1078, 222, 763, 575, -645, 432, -115, 763, -115, -117, - -114, -117, 529, 459, 282, 1146, 649, 911, 327, 529, - 529, 891, 445, 333, 892, 529, 529, 1095, -106, -747, - 575, -113, -120, 361, 965, 1121, 965, 89, 237, 415, - -119, 965, 622, 965, 319, 727, 331, -107, -106, 215, - 989, -106, 994, 995, 283, -106, 222, 470, 1115, 414, - 996, 362, 363, 1115, 471, 714, -120, -107, 1113, -732, - -107, 1010, 744, -108, -107, 1198, 1012, 1240, 736, 1201, - 965, 970, 356, 357, 358, 1115, 708, 488, 710, 970, - 1146, 970, 748, -108, 1146, 1113, -108, 749, 283, 694, - -108, 861, 896, 1037, 1038, 697, 935, 701, 60, 698, - 364, 1181, 751, 1202, 989, 702, 690, 707, 416, -115, - 418, 960, 753, 361, -117, 1059, 1060, 1061, -114, 445, - 361, 1221, -115, 741, 695, -637, -117, 575, 282, 445, - 489, 740, 490, 491, 529, 1220, 1146, 575, -114, 702, - -114, 362, 428, 89, 480, 89, 215, 205, 362, 457, - 630, 427, 203, 222, -637, 632, 215, 236, 634, 423, - 282, 636, 488, 222, 488, 89, 222, 816, 976, 750, - -638, 702, 424, 78, 859, 78, 488, 646, 531, 695, - -640, -105, 648, 966, -639, 531, 531, 78, 78, 425, - 429, 531, 531, 367, -114, 473, 962, 429, 849, -638, - 222, 970, 471, 970, 234, 319, -641, 695, 970, -640, - 970, 236, 283, -639, 488, 445, 237, 490, 491, 490, - 491, 433, 848, 575, 78, 78, -747, 850, 858, 493, - 237, 490, 491, 825, 831, -641, 837, -729, 837, 78, - 680, 89, 215, 431, 283, 89, 537, 970, 762, 222, - 765, -630, 453, 537, 537, 1161, 338, 339, 676, 537, - 537, -633, 78, 78, 606, 1173, 78, 493, 1196, 490, - 491, 78, 618, 203, 488, 237, 230, 695, 427, -630, - -630, 772, -105, 233, -310, 774, 1190, 695, 361, 89, - -633, 222, 89, 607, 826, 869, -747, 869, 367, 237, - 827, 522, -105, 349, 350, -105, -642, -630, -630, -105, - 531, 1156, -310, -310, -643, 595, 362, 483, 703, 596, - 914, 576, -301, 901, 711, 333, 715, 494, 903, 490, - 491, 695, 904, 595, -642, -642, 463, 875, -83, 361, - 695, 881, -643, -643, 643, 469, -644, 475, 1114, 478, - -301, -301, 900, 482, -729, 502, -630, 514, -645, -729, - 528, -310, 972, 589, -733, 484, 333, 362, 590, 832, - 827, 966, 503, -112, 598, 1135, 282, 593, 537, 966, - 78, 966, 488, -642, 962, -113, 576, 633, 962, 631, - 89, -643, 962, -103, 962, 89, 222, 1011, 635, -301, - 640, 78, 641, 78, 78, -104, 1016, 78, -98, 78, - 650, 89, 415, 78, 576, 78, 591, 361, 89, 971, - 459, 1046, 673, 354, 355, 356, 357, 358, 78, 89, - 78, 670, 89, 888, 889, 660, -283, 490, 491, -120, - 282, 576, 449, 678, 695, 362, 409, -119, 679, 1089, - 682, 854, 450, 451, 683, 1075, 1162, 1163, 842, -111, - 1006, 846, 684, 704, 89, 709, 863, -110, 1033, 716, - 1033, 1033, 1081, 89, 719, 853, 764, 766, 768, 697, - 78, 78, 78, 78, 78, 78, 78, 78, -284, 361, - 809, -311, 1033, 1033, 1033, 827, 815, 78, 855, 78, - 862, 966, 78, 966, 866, 1090, -115, 1092, 966, -285, - 966, 971, -730, 100, 962, 100, 962, 362, 600, -311, - -311, 962, 884, 962, 1057, 693, -106, 100, 100, 885, - 695, 282, 887, 699, 898, 78, 881, 78, -286, 831, - 990, 78, 78, 78, 837, 1126, 781, 966, 576, 488, - 496, -736, 1027, 1028, -633, 695, 695, 78, 576, 1031, - 962, 361, 1041, 1036, 100, 100, 601, 699, -311, 1044, - 1039, 1042, 89, 1052, 89, 905, 1053, 1054, 906, 100, - 1086, 908, -633, -633, 488, 78, 78, 1058, 912, 362, - 686, 915, 1062, -736, 1064, 1074, 614, 616, 693, 699, - 78, 971, 100, 100, 490, 491, 100, 998, 1077, 89, - 1066, 100, 89, 614, 616, 1128, 445, 826, 707, 1182, - 837, -736, -736, 361, 575, 1104, 367, 367, 361, -730, - 1106, -633, 961, 1127, -730, 1132, 78, 665, 687, 490, - 491, 644, 1033, 215, 576, 698, 1025, 1026, 921, 816, - 222, 362, 1087, 1017, 1144, 78, 362, 1133, 1149, 1169, - 1204, 1205, 1171, 1033, 1035, 1174, 1176, 922, -736, 1183, - -736, 1180, -117, -732, 1184, 488, -114, 1186, 916, 1191, - 917, 918, 919, 920, 921, 89, 89, 1193, 1199, 1067, - 1045, 1200, -108, 1207, 1197, 455, -105, 1208, 926, 927, - 1088, 1214, -732, 922, 800, 601, 119, -733, 119, 695, - 310, 311, 312, 313, 314, 1082, 1083, 1225, 801, 1230, - 100, 645, 333, 928, 222, 222, 647, 924, 493, 1237, - 490, 491, 377, 1150, 926, 927, 394, 1105, 360, 346, - 347, 100, 739, 100, 100, 829, 1102, 100, 1160, 100, - 1167, 957, 78, 100, 78, 100, 1219, 119, 119, 928, - 870, 285, 78, 991, 860, 837, 1241, 672, 100, 518, - 100, 993, 78, 1096, 78, 78, 351, 352, 353, 354, - 355, 356, 357, 358, 1151, 1152, 1159, 285, 992, 1040, - 916, 1043, 917, 918, 919, 920, 89, 1153, 800, 800, - 382, 392, 392, 392, 1091, 1116, 413, 406, 1120, 78, - 666, 1047, 801, 801, 932, 1063, 1065, 1165, 1130, 1112, - 100, 100, 100, 100, 100, 100, 100, 100, 1136, 333, - 1139, 1134, 1110, 757, 758, 1076, 759, 100, 0, 100, - 0, 0, 100, 46, 47, 0, 346, 347, 0, 0, - 78, 0, 0, 0, 78, 78, 0, 0, 78, 0, - 0, 1179, 78, 78, 41, 42, 43, 44, 78, 78, - 0, 0, 0, 811, 813, 100, 0, 100, 0, 818, - 820, 100, 100, 100, 0, 353, 354, 355, 356, 357, - 358, 0, 800, 800, 0, 0, 0, 100, 78, 0, - 78, 78, 800, 800, 800, 0, 801, 801, 800, 800, - 0, 0, 0, 119, 0, 0, 801, 801, 801, 0, - 0, 1213, 801, 801, 0, 100, 100, 811, 813, 0, - 818, 820, 0, 0, 0, 1209, 0, 1211, 0, 0, - 100, 0, 1212, 0, 0, 0, 119, 0, 119, 0, - 1215, 0, 1217, 0, 1170, 1172, 0, 0, 0, 1218, - 1175, 119, 1177, 119, 1178, 0, 802, 916, 0, 917, - 918, 919, 920, 921, 0, 0, 100, 1185, 1187, 0, - 0, 0, 0, 1192, 285, 1194, 1195, 78, 0, 0, - 0, 1235, 922, 800, 0, 100, 1236, 0, 897, 78, - 0, 800, 0, 0, 78, 78, 1140, 801, 917, 918, - 919, 920, 0, 119, 0, 801, 924, 0, 119, 0, - 78, 0, 925, 926, 927, 0, 0, 78, 800, 0, - 0, 0, 119, 285, 0, 0, 0, 0, 78, 0, - 0, 78, 801, 897, 122, 576, 122, 0, 928, 0, - 0, 929, 0, 1224, 1226, 1227, 1228, 0, 0, 0, - 802, 802, 1229, 1231, 1232, 1233, 0, 0, 237, 0, - 119, 333, 0, 78, 119, 0, 119, 0, 0, 1238, - 0, 0, 78, 1239, 800, 0, 0, 0, 346, 347, - 0, 0, 100, 0, 100, 122, 122, 0, 801, 286, - 0, 916, 100, 917, 918, 919, 920, 921, 0, 0, - 0, 0, 100, 0, 100, 100, 0, 0, 0, 916, - 0, 917, 918, 919, 920, 286, 922, 273, 354, 355, - 356, 357, 358, 0, 0, 0, 0, 0, 383, 393, - 393, 0, 916, 0, 917, 918, 919, 920, 0, 100, - 924, 0, 0, 0, 802, 802, 925, 926, 927, 800, - 0, 0, 0, 800, 802, 802, 802, 0, 1018, 119, - 802, 802, 0, 801, 1019, 0, 0, 801, 0, 800, - 0, 78, 928, 78, 0, 929, 285, 0, 0, 0, - 100, 1018, 0, 801, 100, 100, 0, 953, 100, 0, - 0, 0, 100, 100, 0, 0, 0, 0, 100, 100, - 0, 0, 0, 0, 800, 800, 0, 0, 78, 0, - 0, 78, 0, 0, 0, 0, 0, 0, 801, 801, - 285, 0, 0, 0, 0, 0, 0, 0, 100, 0, - 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 122, 0, 0, 0, 802, 0, 0, 0, 78, - 0, 0, 0, 802, 0, 0, 0, 0, 916, 0, - 917, 918, 919, 920, 921, 0, 0, 0, 417, 0, - 0, 419, 420, 421, 122, 119, 122, 119, 0, 0, - 802, 0, 0, 922, 78, 78, 0, 0, 0, 122, - 0, 122, 0, 0, 0, 0, 0, 119, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 924, 0, 0, - 0, 0, 286, 925, 926, 927, 0, 100, 0, 803, - 0, 0, 0, 78, 78, 0, 0, 0, 0, 100, - 0, 0, 0, 0, 100, 100, 802, 0, 0, 928, - 0, 122, 929, 0, 285, 0, 122, 0, 0, 0, - 100, 0, 0, 0, 0, 0, 0, 100, 0, 0, - 122, 286, 0, 538, 0, 0, 0, 0, 100, 0, - 0, 100, 0, 119, 0, 0, 285, 119, 0, 0, - 0, 0, 0, 808, 0, 0, 0, 521, 0, 0, - 0, 0, 534, 0, 0, 78, 0, 0, 122, 0, - 0, 0, 122, 100, 122, 0, 0, 0, 0, 0, - 0, 802, 100, 803, 803, 802, 0, 0, 0, 0, - 0, 119, 0, 0, 119, 0, 0, 0, 0, 0, - 0, 802, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 538, 538, 0, 916, - 0, 917, 918, 919, 920, 921, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 802, 802, 0, 0, - 0, 0, 0, 0, 922, 0, 0, 808, 808, 0, - 0, 0, 0, 0, 0, 619, 621, 0, 923, 0, - 0, 0, 0, 0, 273, 0, 0, 122, 924, 0, - 0, 0, 0, 0, 925, 926, 927, 803, 803, 0, - 0, 100, 0, 100, 286, 0, 0, 803, 803, 803, - 0, 0, 119, 803, 803, 0, 0, 119, 0, 0, - 928, 621, 0, 929, 273, 0, 0, 0, 0, 0, - 0, 0, 118, 119, 118, 0, 0, 0, 100, 0, - 119, 100, 0, 0, 0, 0, 0, 0, 286, 0, - 0, 119, 0, 0, 119, 0, 0, 0, 0, 0, - 0, 808, 808, 0, 0, 0, 0, 0, 0, 0, - 677, 808, 808, 808, 0, 0, 0, 808, 808, 100, - 0, 0, 1008, 118, 118, 0, 119, 284, 0, 0, - 0, 0, 0, 804, 0, 119, 0, 0, 803, 0, - 0, 0, 0, 122, 0, 122, 803, 0, 0, 0, - 0, 0, 0, 284, 100, 100, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 122, 381, 391, 391, 391, - 0, 0, 0, 803, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 392, 805, 0, 0, - 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, - 0, 0, 808, 0, 0, 0, 0, 0, 0, 742, - 808, 743, 286, 0, 0, 0, 0, 0, 0, 0, - 0, 761, 0, 0, 621, 0, 273, 804, 804, 803, - 0, 0, 0, 0, 119, 0, 119, 808, 0, 0, - 0, 122, 0, 0, 286, 122, 538, 0, 0, 0, - 0, 0, 0, 538, 538, 0, 0, 0, 0, 538, - 538, 0, 0, 0, 85, 100, 85, 0, 0, 771, - 0, 119, 0, 0, 119, 0, 0, 392, 0, 118, - 0, 805, 805, 0, 0, 0, 0, 0, 121, 122, - 121, 0, 122, 808, 0, 0, 822, 0, 0, 0, - 0, 0, 0, 0, 803, 0, 0, 0, 803, 0, - 0, 844, 118, 0, 118, 85, 85, 0, 0, 0, - 0, 804, 804, 0, 803, 0, 0, 118, 0, 118, - 0, 804, 804, 804, 0, 0, 0, 804, 804, 121, - 121, 0, 0, 0, 0, 0, 0, 119, 119, 0, - 284, 806, 0, 0, 0, 0, 0, 0, 378, 803, - 803, 871, 0, 0, 0, 0, 0, 0, 808, 0, - 0, 0, 808, 0, 0, 805, 805, 0, 538, 118, - 0, 0, 0, 0, 118, 805, 805, 805, 808, 0, - 122, 805, 805, 0, 0, 122, 0, 0, 118, 284, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 122, 0, 0, 0, 0, 0, 0, 122, 0, - 0, 0, 804, 808, 808, 0, 0, 0, 0, 122, - 804, 0, 122, 0, 909, 0, 118, 0, 0, 0, - 118, 0, 118, 0, 0, 806, 806, 0, 0, 0, - 0, 0, 0, 273, 0, 0, 0, 804, 119, 0, - 1009, 0, 0, 0, 122, 0, 0, 0, 0, 0, - 0, 85, 0, 122, 0, 0, 805, 0, 0, 0, - 0, 0, 0, 807, 805, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 121, 0, 0, 0, 0, - 0, 1015, 0, 0, 85, 0, 85, 0, 0, 0, - 0, 805, 0, 804, 0, 0, 0, 0, 0, 85, - 0, 85, 0, 0, 393, 0, 0, 0, 121, 1030, - 121, 0, 0, 0, 0, 118, 0, 0, 0, 806, - 806, 0, 0, 121, 0, 121, 0, 0, 0, 806, - 806, 806, 284, 0, 0, 806, 806, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 805, 0, 0, - 0, 85, 122, 0, 122, 0, 85, 807, 807, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 804, 0, - 85, 0, 804, 532, 0, 121, 284, 0, 0, 0, - 121, 0, 0, 0, 0, 1098, 0, 0, 804, 122, - 0, 0, 122, 0, 121, 393, 0, 121, 1107, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, - 0, 0, 85, 0, 85, 0, 0, 0, 0, 0, - 806, 0, 805, 804, 804, 0, 805, 0, 806, 0, - 0, 118, 121, 118, 0, 0, 121, 0, 121, 0, - 0, 0, 805, 0, 0, 0, 0, 0, 0, 0, - 0, 807, 807, 118, 0, 806, 532, 532, 0, 0, - 0, 807, 807, 807, 0, 122, 122, 807, 807, 0, - 0, 0, 0, 0, 0, 0, 0, 805, 805, 0, - 121, 121, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 284, 0, 0, 0, 0, 0, 0, 85, 0, 332, - 0, 806, 0, -759, 0, 0, 0, 0, 0, 0, - 0, -759, -759, -759, 0, 0, -759, -759, -759, 118, - -759, 121, 284, 118, 0, 0, 0, 0, -759, -759, - -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -759, -759, 807, -759, -759, -759, -759, -759, 0, 0, - 807, 333, 334, 335, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 0, 0, 122, 118, 346, 347, - 118, -759, 0, 0, 0, 0, 806, 807, 0, 0, - 806, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 806, 0, 0, -759, - -759, 348, 0, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 85, 0, 85, 0, 0, 0, 0, - 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, - 0, 806, 806, 807, 0, 85, 0, 121, 0, 121, - 0, 0, 0, 0, 0, 0, -759, -759, 0, 0, - 0, 233, -759, 0, -759, 0, -759, 0, 0, 121, - 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, - 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, - 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 118, 807, 0, - 118, 85, 807, 0, 0, 85, 532, 0, 0, 0, - 0, 0, 0, 532, 532, 0, 0, 0, 807, 532, - 532, 0, 0, 0, 0, 121, 0, 0, 1007, 121, - 121, 0, 118, 0, 0, 0, 0, 121, 121, 0, - 0, 118, 0, 121, 121, 0, 0, 0, 0, 85, - 0, 0, 85, 807, 807, 0, 0, 0, 0, 0, + 124, 294, 260, 365, 583, 308, 412, 330, 203, 235, + 838, 205, 221, 221, 240, 410, 291, 536, 434, 841, + 215, 215, 372, 367, 367, 597, 125, 367, 203, 308, + 651, 205, 282, 747, 89, 474, 89, 629, 281, 476, + 301, 998, 1000, 309, 569, 1141, 577, 317, 222, 222, + 238, 270, 241, 272, 276, 1107, 405, 571, 282, 203, + 369, 754, 735, 373, 712, 320, 495, 497, 1115, 1135, + 302, 282, 282, 282, 681, 1164, 580, 629, -112, 265, + 1166, 1107, -107, 1049, 462, 89, 89, 1196, 374, 283, + 1066, 1199, 611, 612, 615, 827, 221, 3, 791, 203, + 222, 333, -113, 529, 215, 716, -116, 236, -643, 569, + 242, 577, 237, 999, 1001, 283, 361, 73, -116, 73, + -84, 580, 626, 222, 222, 1035, 1036, 222, 379, 390, + 390, 847, 222, 315, 316, -112, 430, 219, 229, 643, + -98, 852, 622, 1219, 362, 409, 256, 1057, 1058, 1059, + 622, -120, 1121, 525, 422, 234, 950, 305, 260, 306, + 356, 357, 358, 954, 318, 458, 643, 663, 446, 267, + 448, 237, 1120, 227, 227, 1141, 826, 654, -119, 1164, + 323, 1221, 827, -107, 1067, 872, 529, 529, 305, 851, + 306, 1135, 964, 456, 879, 308, -112, 485, 1115, -103, + -118, 1107, -118, -107, 480, -731, -107, 667, 260, 909, + -107, 319, 271, 275, 305, 1145, 306, 884, 1107, 427, + 664, 408, 676, -104, 297, 427, 221, -107, 221, -731, + 773, 445, 1095, 465, 215, 434, 215, 215, 733, 629, + 124, 89, 367, 367, 367, 367, 1122, 510, 511, 237, + 968, 1046, 479, -731, 464, 282, -116, 227, -116, 305, + 668, 306, 222, -523, 222, 222, 1071, 244, 222, 662, + 222, 662, -111, 643, 89, 317, 89, 260, 505, 506, + 507, 508, 703, 643, 724, 265, 973, 975, 711, 89, + 715, 89, 447, 592, 734, 298, 1171, 995, 299, -110, + 477, 975, 975, 367, 282, -113, 884, 308, 912, 1146, + 527, 1204, 283, -115, 1097, 949, 1098, 1188, 594, 584, + 466, 586, 522, -109, 468, -732, 595, 522, 520, 972, + 596, 504, -117, 531, -112, -732, -112, -120, -118, 585, + -118, 89, 222, 222, 222, 222, 89, 222, 222, 300, + 622, 435, 622, 438, 265, -114, 1144, 73, 222, 237, + 89, 283, 445, 537, 889, 575, 587, 569, 215, 577, + 810, 812, 460, -119, 873, 874, 817, 819, 964, 326, + 778, 234, 319, 1068, -115, 327, 964, 227, 964, 227, + 449, 823, 318, 60, 1076, 884, 222, 233, 89, -644, + 450, 451, 89, 222, 89, 331, 480, 1082, 1083, -117, + 1109, 575, 890, 752, 744, 891, 531, 531, 222, -114, + 1093, 1116, 842, 876, 73, 846, -113, 445, 488, 509, + 575, 1144, 763, 215, -106, 1144, 1129, 763, 637, 853, + 427, 1162, 427, -113, 1136, -113, 537, 537, 315, 316, + 480, 688, 203, -108, 414, 205, 529, 282, 575, 338, + 339, 222, 961, 529, 529, 929, 629, 929, 926, 529, + 529, -635, -106, 488, 929, -120, -105, -120, 992, 993, + 910, 489, 445, 490, 491, 575, 1218, 1144, 215, 416, + 1022, 630, 927, -643, 236, 895, 632, 89, 576, 634, + -635, 282, 636, 425, 1119, -634, 349, 350, 964, 418, + 964, -119, 488, -119, 283, 964, 222, 964, 646, 714, + -112, 727, -115, 648, -115, 423, 493, 994, 490, 491, + 708, 618, 710, 1008, -634, 1238, 736, 431, 1010, 904, + -103, 744, 905, -636, -108, 907, 965, -117, 424, -117, + -746, 1208, 911, 237, 964, 914, 694, -114, 283, -114, + -644, 1200, 929, 576, 701, 493, 1214, 490, 491, 433, + 751, 975, -636, -106, 753, 702, 690, 707, 453, 622, + 1179, 680, 623, 1022, 1101, -637, 595, -113, 529, 445, + 875, 576, 575, -106, 695, 215, -106, 415, 740, 445, + -106, -639, 575, 741, 488, 215, 480, -104, -638, 702, + -353, -640, 230, 89, -637, 89, 1015, 203, 576, 488, + 205, 427, -629, 222, -120, 282, -632, 649, 488, 1032, + -639, 233, -105, 222, 606, 89, 222, -638, -353, -353, + -640, 702, 333, 859, -111, -108, 432, 1033, 961, 695, + -746, -629, 961, 1043, 237, -632, 961, 282, 961, 490, + 491, 367, 849, 607, 827, -108, 719, 988, -108, 1022, + 222, 1022, -108, -120, 490, 491, 848, 695, 988, 988, + 459, 494, 283, 490, 491, 445, 531, -353, 575, 814, + 762, 215, 361, 531, 531, 858, 821, 850, 463, 531, + 531, 522, 693, 825, 831, 765, 837, -119, 837, 1112, + 699, 89, -83, 1077, 283, 89, 537, 800, 469, 222, + 362, 363, 475, 537, 537, 576, 1159, -110, 459, 537, + 537, 1078, 965, -105, 470, 576, 1133, 78, 203, 78, + 965, 471, 965, 415, 699, 980, 478, 695, 427, 488, + 496, 78, 78, -105, 748, -119, -105, 695, -728, 89, + -105, 222, 89, 482, 921, 869, 367, 869, 643, 364, + -120, 502, 1022, 1022, 514, 693, 699, 900, 961, 1154, + 961, -115, 902, 488, 913, 961, 473, 961, 78, 78, + 750, 361, 854, 471, 772, 925, 488, 988, 774, 981, + -629, 695, 903, 78, 490, 491, 749, 863, 361, 528, + 695, 800, 800, 861, 589, 1111, 971, -310, 531, 362, + 428, 576, 899, 1177, 961, 503, 78, 78, -629, -629, + 78, 832, 827, -117, 273, 78, 362, 457, 490, 491, + -114, 1148, 1111, 697, 593, -310, -310, 698, 537, 493, + 1009, 490, 491, -729, 1148, 816, 1194, 598, 361, 1014, + 89, 988, 965, 237, 965, 89, 222, 631, 429, 965, + -115, 965, 282, 640, -117, -728, 673, -629, 1160, 1161, + -728, 89, -114, 1211, 1044, 429, 362, 483, 89, 970, + 488, 333, 887, 888, -310, -632, 633, -732, 635, 89, + -98, 641, 89, 670, 679, 800, 800, 915, 965, 916, + 917, 918, 919, 695, 800, 800, 800, 650, 1087, -283, + 800, 800, 1073, -632, -632, 678, -641, 682, 683, 1004, + 704, 697, 684, 89, 709, 484, 282, 1031, 1079, 1031, + 1031, 960, 89, 660, 78, 490, 491, 996, 354, 355, + 356, 357, 358, -642, -641, -641, 1016, 1088, -115, 1090, + 716, 1031, 1031, 1031, 719, 78, 768, 78, 78, 698, + -729, 78, -632, 78, 816, -729, -284, 78, -106, 78, + 970, -642, -642, 764, 809, 417, 1023, 1024, 419, 420, + 421, -301, 78, 1055, 78, 766, -117, 1124, 815, 695, + 934, -114, 934, -641, 361, 800, 827, 831, 361, 934, + 855, 959, 837, 800, 862, 1038, -108, 1041, 866, -301, + -301, -105, -285, 695, 695, 880, 282, 883, 969, 1065, + -642, -311, 362, 590, 884, 886, 362, 600, 897, 800, + 89, -286, 89, 1025, 78, 78, 78, 78, 78, 78, + 78, 78, 781, 1026, 1080, 1081, -735, 1029, 488, -311, + -311, 78, 1034, 78, 801, 1037, 78, 1039, -301, 970, + 1040, 1180, 1042, 1050, 361, 1051, 1103, 89, 1052, 1056, + 89, 591, 1064, 1126, 445, 601, 707, 575, 837, 1060, + 215, 1062, 367, 367, 1072, 800, 1074, 934, -735, 78, + 1075, 78, 362, 686, 521, 78, 78, 78, -311, 534, + 1031, 665, 1114, 490, 491, 1118, 1084, 361, 222, 826, + 1102, 78, 1104, 614, 616, 1125, -735, -735, 1202, 1203, + 1130, 1031, 1061, 1063, 1142, 1134, 1147, 1137, 361, 1167, + 614, 616, 1169, 1033, 1172, 362, 1085, 1174, 1178, 78, + 78, 687, 1181, 89, 89, 1182, 1163, 920, 801, 801, + 1184, -731, 1195, 1189, 78, 1191, 362, 1131, 644, 1197, + 800, 934, 1198, -735, 800, -735, 921, 695, -731, 1168, + 1170, 1235, 934, 1205, 1206, 1173, 1212, 1175, -732, 1176, + 800, 1113, 222, 222, 1086, 455, 1113, 959, 1223, 1228, + 78, 647, 619, 621, 645, 959, 394, 925, 926, 377, + 360, 273, 739, 829, 969, 601, 1100, 1158, 1113, 78, + 576, 1165, 969, 870, 969, 800, 800, 757, 758, 956, + 759, 989, 927, 837, 1217, 860, 672, 46, 47, 518, + 1239, 1094, 1207, 1149, 1209, 1150, 1151, 991, 621, 1210, + 990, 273, 801, 801, 1157, 1089, 413, 1213, 406, 1215, + 666, 801, 801, 801, 89, 1045, 1216, 801, 801, 100, + 915, 100, 916, 917, 918, 919, 931, 1110, 1222, 1224, + 1225, 1226, 1132, 100, 100, 915, 1128, 916, 917, 918, + 919, 920, 1108, 1183, 1185, 0, 0, 677, 1233, 1190, + 0, 1192, 1193, 1234, 1236, 310, 311, 312, 313, 314, + 921, 0, 934, 0, 0, 0, 78, 0, 78, 1016, + 100, 100, 0, 0, 922, 1017, 78, 959, 915, 0, + 916, 917, 918, 919, 923, 100, 78, 0, 78, 78, + 924, 925, 926, 0, 969, 1138, 969, 916, 917, 918, + 919, 969, 801, 969, 0, 802, 0, 0, 100, 100, + 801, 0, 100, 0, 0, 0, 927, 100, 0, 928, + 0, 0, 0, 78, 41, 42, 43, 44, 1227, 1229, + 1230, 1231, 0, 0, 0, 0, 801, 333, 0, 0, + 969, 0, 0, 0, 0, 0, 742, 0, 743, 1237, + 811, 813, 0, 0, 346, 347, 818, 820, 0, 0, + 0, 621, 333, 273, 78, 0, 0, 0, 78, 78, + 0, 0, 78, 0, 0, 0, 78, 78, 0, 346, + 347, 0, 78, 78, 0, 915, 0, 916, 917, 918, + 919, 920, 801, 353, 354, 355, 356, 357, 358, 802, + 802, 0, 0, 0, 811, 813, 771, 818, 820, 0, + 921, 0, 78, 0, 78, 78, 803, 0, 0, 354, + 355, 356, 357, 358, 0, 0, 100, 0, 0, 0, + 0, 0, 0, 822, 923, 0, 0, 0, 0, 0, + 924, 925, 926, 0, 0, 0, 0, 100, 844, 100, + 100, 0, 0, 100, 0, 100, 0, 0, 0, 100, + 0, 100, 0, 0, 0, 0, 927, 801, 0, 928, + 0, 801, 0, 0, 100, 896, 100, 0, 0, 0, + 0, 804, 0, 0, 0, 0, 237, 801, 0, 0, + 0, 0, 0, 802, 802, 0, 0, 0, 871, 0, + 0, 78, 802, 802, 802, 0, 0, 0, 802, 802, + 803, 803, 0, 78, 0, 119, 0, 119, 78, 78, + 896, 0, 801, 801, 0, 0, 100, 100, 100, 100, + 100, 100, 100, 100, 78, 0, 0, 0, 0, 0, + 0, 78, 0, 100, 0, 100, 0, 0, 100, 0, + 0, 0, 78, 0, 0, 78, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 119, 0, 0, + 285, 908, 0, 0, 0, 804, 804, 0, 0, 0, + 0, 100, 0, 100, 0, 0, 78, 100, 100, 100, + 273, 0, 0, 802, 0, 78, 285, 0, 0, 0, + 0, 802, 0, 100, 803, 803, 0, 0, 0, 382, + 392, 392, 392, 803, 803, 803, 0, 0, 0, 803, + 803, 0, 0, 0, 0, 0, 0, 802, 0, 0, + 0, 100, 100, 0, 0, 0, 0, 1013, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, + 915, 0, 916, 917, 918, 919, 920, 0, 0, 0, + 0, 0, 0, 0, 0, 1028, 0, 0, 0, 804, + 804, 0, 0, 0, 0, 921, 0, 0, 804, 804, + 804, 0, 100, 802, 804, 804, 0, 0, 0, 0, + 0, 0, 0, 78, 0, 78, 0, 0, 0, 923, + 0, 100, 0, 0, 803, 924, 925, 926, 0, 0, + 0, 915, 803, 916, 917, 918, 919, 920, 0, 0, + 0, 0, 119, 0, 0, 0, 0, 332, 0, 0, + 78, 927, 0, 78, 928, 0, 921, 0, 803, 0, + 1096, 0, 0, 0, 0, 0, 952, 0, 0, 0, + 0, 0, 0, 1105, 0, 119, 0, 119, 802, 0, + 923, 0, 802, 0, 0, 0, 924, 925, 926, 804, + 119, 78, 119, 0, 0, 0, 0, 804, 802, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 927, 285, 803, 928, 346, 347, 100, 0, + 100, 0, 0, 804, 0, 0, 78, 78, 100, 0, + 0, 0, 0, 802, 802, 0, 0, 0, 100, 0, + 100, 100, 119, 0, 0, 0, 0, 119, 0, 348, + 0, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 119, 285, 0, 0, 78, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 0, 0, 804, + 0, 0, 915, 0, 916, 917, 918, 919, 920, 803, + 0, 0, 0, 803, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 119, 0, 119, 0, 921, 0, 803, + 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, + 100, 100, 0, 0, 100, 122, 0, 122, 100, 100, + 0, 923, 0, 0, 100, 100, 0, 78, 925, 926, + 0, 0, 0, 0, 803, 803, 0, 0, 0, 0, + 0, 0, 0, 0, 804, 0, 0, 0, 804, 0, + 0, 0, 0, 927, 100, 0, 100, 100, 333, 0, + 0, 0, 0, 0, 804, 0, 122, 122, 0, 0, + 286, 0, 0, 0, 0, 346, 347, 118, 0, 118, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, 286, 0, 0, 804, + 804, 0, 0, 0, 0, 285, 0, 0, 0, 383, + 393, 393, 351, 352, 353, 354, 355, 356, 357, 358, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, + 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 0, 0, 0, 0, 0, 285, + 0, 0, 0, 0, 0, 100, 0, 0, 284, 0, + 100, 100, 23, 24, 25, 26, 0, 0, 0, 0, + 0, 381, 391, 391, 391, 0, 100, 0, 32, 33, + 34, 781, 0, 100, 0, 782, 0, 0, 41, 42, + 43, 44, 45, 0, 100, 0, 0, 100, 0, 0, + 0, 0, 0, 0, 119, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 783, + 784, 0, 122, 0, 0, 0, 119, 785, 100, 0, + 786, 0, 0, 787, 788, 0, 974, 100, 0, 789, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 122, 0, 122, 0, 0, + 0, 790, 0, 0, 0, 805, 0, 0, 279, 0, + 122, 0, 122, 285, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, + 0, 0, 0, 286, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 285, 119, 0, 0, 0, + 0, 0, 808, 0, 0, 0, 85, 118, 85, 118, + 0, 0, 122, 0, 0, 0, 0, 122, 0, 0, + 0, 0, 118, 0, 118, 100, 0, 100, 0, 0, + 0, 122, 286, 0, 538, 0, 0, 0, 0, 0, + 119, 0, 0, 119, 0, 284, 0, 0, 0, 805, + 805, 0, 0, 0, 0, 0, 0, 85, 85, 0, + 0, 0, 100, 0, 0, 100, 0, 0, 0, 122, + 0, 0, 0, 122, 118, 122, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 121, 0, 0, 121, 0, 0, 0, - 217, 217, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 391, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 118, 284, 0, 808, 808, 0, 0, + 378, 0, 0, 100, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 538, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 250, 253, 254, 255, 0, 0, 0, 217, - 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 303, 304, 0, 0, 0, 0, 532, 0, - 118, 0, 118, 0, 0, 0, 0, 0, 0, 0, - 85, 0, 0, 0, 0, 85, 0, 0, 0, 0, - 0, 0, 121, 0, 217, 0, 0, 0, 0, 0, - 0, 85, 0, 0, 121, 0, 0, 118, 85, 121, - 118, 0, 0, 391, 0, 0, 0, 0, 0, 85, - 0, 0, 85, 0, 0, 121, 0, 0, 0, 0, - 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 121, 0, 0, 121, 0, 0, 0, - 1005, 0, 0, 0, 85, 0, 0, 0, 0, 0, - 0, 0, 0, 85, 23, 24, 25, 26, 0, 0, + 0, 118, 0, 0, 0, 118, 0, 118, 100, 100, + 0, 119, 0, 805, 805, 0, 119, 0, 0, 0, + 0, 0, 805, 805, 805, 0, 0, 0, 805, 805, + 0, 0, 119, 0, 0, 0, 0, 0, 122, 119, + 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, + 119, 0, 0, 119, 0, 286, 0, 0, 0, 0, + 808, 808, 0, 0, 0, 0, 0, 0, 0, 808, + 808, 808, 0, 0, 0, 808, 808, 0, 0, 0, + 1006, 0, 0, 85, 119, 0, 0, 0, 0, 0, + 0, 0, 0, 119, 0, 0, 0, 0, 0, 286, + 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 121, 805, 121, 0, 85, 284, 85, 100, + 0, 805, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 85, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 392, 0, 0, 805, 0, 0, + 0, 0, 0, 0, 122, 0, 122, 0, 0, 0, + 808, 284, 0, 121, 121, 0, 0, 0, 808, 0, + 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 85, 0, + 0, 119, 0, 119, 808, 0, 0, 0, 0, 0, + 0, 0, 85, 805, 0, 532, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 0, 118, 0, + 0, 0, 0, 286, 0, 0, 0, 0, 119, 0, + 0, 119, 761, 0, 392, 0, 0, 0, 118, 0, + 85, 0, 0, 0, 85, 0, 85, 0, 0, 0, + 808, 0, 122, 0, 0, 286, 122, 538, 0, 0, + 0, 0, 0, 0, 538, 538, 0, 0, 0, 0, + 538, 538, 0, 0, 0, 0, 0, 0, 805, 0, + 0, 0, 805, 0, 0, 284, 0, 0, 532, 532, + 0, 0, 0, 0, 23, 24, 25, 26, 805, 0, + 122, 0, 0, 122, 119, 119, 0, 0, 0, 0, + 32, 33, 34, 0, 118, 0, 0, 284, 118, 121, + 41, 42, 43, 44, 45, 808, 0, 0, 0, 808, + 0, 0, 0, 805, 805, 0, 0, 0, 0, 85, + 0, 0, 0, 0, 0, 808, 0, 0, 0, 0, + 0, 0, 121, 0, 121, 0, 0, 0, 0, 0, + 0, 0, 118, 0, 0, 118, 0, 121, 0, 121, + 0, 789, 59, 60, 61, 62, 63, 64, 65, 66, + 808, 808, 0, 0, 0, 0, 0, 0, 0, 538, + 0, 0, 0, 333, -758, -758, -758, -758, 338, 339, + 279, 122, -758, -758, 0, 0, 122, 0, 0, 0, + 346, 347, 0, 0, 0, 119, 0, 0, 0, 121, + 0, 0, 122, 0, 121, 0, 0, 0, 806, 122, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, - 32, 33, 34, 118, 118, 0, 0, 121, 0, 0, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 217, 0, 0, 217, 217, 217, 0, 303, 0, + 122, 121, 0, 122, 0, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 85, 0, 85, 0, 0, + 0, 0, 0, 118, 0, 0, 0, 0, 118, 0, + 1007, 0, 0, 0, 122, 0, 121, 85, 0, 0, + 121, 0, 121, 122, 118, 0, 0, 0, 0, 0, + 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, + 807, 0, 118, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 217, 0, 217, 217, 0, 0, + 0, 0, 806, 806, 121, 121, 0, 0, 0, 0, + 0, 0, 1005, 0, 393, 0, 118, 0, 0, 0, + 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 85, 532, 0, + 0, 0, 0, 0, 0, 532, 532, 0, 0, 0, + 0, 532, 532, 0, 0, 121, 0, 0, 0, 0, + 0, 122, 0, 122, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 807, 807, 391, 0, 0, 0, + 0, 85, 0, 0, 85, 333, 334, 335, 336, 337, + 338, 339, 340, 0, 342, 343, 806, 806, 122, 0, + 0, 122, 346, 347, 393, 806, 806, 806, 0, 0, + 0, 806, 806, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 118, 0, 118, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 789, 59, 60, 61, 62, 63, 64, 65, 66, - 0, 333, 334, 335, 336, 337, 338, 339, 340, 0, - 342, 343, 85, 0, 85, 0, 0, 0, 346, 347, - 279, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 121, 0, 121, 0, - 0, 0, 0, 0, 118, 0, 0, 0, 0, 85, - 0, 0, 85, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 0, 0, 0, 0, 0, 0, 0, - 217, 0, 0, 121, 0, 533, 121, 540, 541, 542, - 543, 544, 0, 0, 545, 546, 547, 548, 549, 550, - 551, 552, 553, 0, 0, 554, 555, 556, 557, 558, - 559, 560, 561, 562, 563, 0, 0, 0, 217, 0, + 118, 0, 0, 118, 0, 0, 391, 0, 807, 807, + 532, 121, 0, 121, 122, 122, 0, 807, 807, 807, + 0, 0, 85, 807, 807, 0, 0, 85, 0, 0, + 0, 0, 0, 121, 217, 217, 806, 0, 0, 0, + 0, 0, 0, 85, 806, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 0, 85, 0, 250, 253, 254, 255, + 806, 0, 0, 217, 217, 0, 118, 118, 0, 0, + 0, 0, 0, 0, 0, 0, 303, 304, 0, 0, + 0, 1003, 0, 0, 0, 85, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, 0, 0, 807, 121, + 0, 0, 0, 121, 121, 0, 807, 0, 217, 0, + 0, 121, 121, 0, 0, 122, 806, 121, 121, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, + 0, 0, 807, 0, 0, 0, 0, -757, -757, -757, + 0, 0, -757, -757, -757, 0, -757, 121, 0, 0, + 121, 0, 0, 0, -757, -757, -757, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -757, -757, 0, -757, + -757, -757, -757, -757, 0, 0, 0, 118, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 807, 0, + 0, 806, 85, 0, 85, 806, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 806, 0, 0, 0, 217, 0, 0, 217, 217, + 217, 0, 303, 0, 0, -757, -757, 0, 0, 85, + 0, 0, 85, 0, 0, 0, 121, 0, 217, 0, + 217, 217, 0, 0, 0, 0, 806, 806, 121, -757, + 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 807, 0, 0, 0, 807, 0, 121, + 0, 0, -757, -757, 0, 0, 121, 233, -757, 0, + -757, 0, -757, 807, 0, 0, 0, 121, 0, 0, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 0, 0, 0, - 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 0, 0, 121, - 121, 346, 347, 0, 0, 0, 0, 0, 613, 613, - 0, 0, 0, 0, 0, 0, 0, 613, 217, 217, - 0, 0, 0, 217, 0, 613, 613, 217, 0, 0, - 0, 0, 0, 255, 348, 0, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 0, 0, 639, 0, - 0, 0, 0, 613, 0, 0, 0, 0, 0, 0, - 237, 0, 0, 0, 217, 0, 0, 217, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, - 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 669, 333, 334, 335, - 336, 337, 338, 339, 340, 341, 342, 343, -760, -760, - 121, 0, 0, 217, 346, 347, 0, 0, 0, 0, - 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, - -736, -736, -736, 0, 0, 0, -736, -736, 0, -736, - 0, 0, 0, 0, 0, 0, 0, -736, -736, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, -736, - -736, 0, -736, -736, -736, -736, -736, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, - -736, 0, 0, 0, 0, 217, 0, 0, 0, -736, - -736, -736, -736, -736, -736, -736, -736, -736, -736, -736, - -736, -736, 217, 0, 217, 0, -736, -736, -736, -736, - 0, 691, 0, 0, 0, 0, 0, 217, 0, 217, + 0, 0, 0, 0, 0, 0, 0, 0, 807, 807, + 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 0, 0, 0, 217, 0, 0, 0, 0, 533, + 0, 540, 541, 542, 543, 544, 0, 0, 545, 546, + 547, 548, 549, 550, 551, 552, 553, 0, 0, 554, + 555, 556, 557, 558, 559, 560, 561, 562, 563, 0, + 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -736, 0, 0, 0, 0, 0, -116, -736, - 0, -736, -736, -736, -736, -736, -736, -736, -736, -736, - -736, 0, 0, 0, 0, -736, -736, -736, -107, 0, - 0, -736, 217, -736, 0, -736, 0, 0, 613, 775, - 0, 217, 0, 0, 0, 613, 613, 0, 0, 0, - 0, 613, 613, 0, 23, 24, 25, 26, 0, 217, + 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 0, + 0, 0, 0, 346, 347, 0, 85, 0, 0, 0, + 0, 0, 613, 613, 0, 0, 0, 0, 121, 0, + 121, 613, 217, 217, 0, 0, 0, 217, 0, 613, + 613, 217, 0, 0, 0, 0, 348, 255, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 0, 0, + 0, 0, 639, 0, 0, 121, 0, 613, 121, 0, + 0, 0, 237, 0, 0, 0, 0, 0, 217, 0, + 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 33, 34, 781, 217, 0, 0, 782, 0, 981, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 922, 613, - 613, 0, 613, 613, 0, 0, 0, 0, 0, 0, - 0, 783, 784, 0, 0, 0, 0, 0, 0, 785, - 0, 0, 786, 0, 217, 787, 788, 0, 975, 926, - 0, 789, 59, 999, 61, 62, 63, 64, 65, 66, + 669, 333, 334, 335, 336, 337, 338, 339, 340, 341, + 342, 343, -758, -758, 0, 0, 0, 217, 346, 347, + 0, 0, 0, 0, 0, 0, -735, 0, 0, 0, + 0, 121, 121, 0, -735, -735, -735, 0, 0, 0, + -735, -735, 0, -735, 0, 0, 0, 0, 0, 0, + 0, -735, -735, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, -735, -735, 0, -735, -735, -735, -735, + -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, + 0, 0, 0, 0, -735, 0, 0, 0, 0, 217, + 0, 0, 0, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, -735, -735, -735, 217, 0, 217, 0, + -735, -735, -735, -735, 0, 691, 0, 0, 0, 0, + 0, 217, 0, 217, 0, 0, 0, 0, 0, 0, + 0, 0, 121, 0, 0, 0, -735, 0, 0, 0, + 0, 0, -116, -735, 0, -735, -735, -735, -735, -735, + -735, -735, -735, -735, -735, 0, 0, 0, 0, -735, + -735, -735, -107, 0, 0, -735, 217, -735, 0, -735, + 0, 0, 613, 775, 0, 217, 0, 0, 0, 613, + 613, 0, 0, 0, 0, 613, 613, 0, -629, 0, + 0, 0, 0, 217, 0, 0, -629, -629, -629, 0, + 0, -629, -629, -629, 0, -629, 0, 0, 217, 0, + 0, 0, 0, -629, 0, -629, -629, -629, 0, 0, + 0, 0, 0, 0, 0, -629, -629, 0, -629, -629, + -629, -629, -629, 613, 613, 0, 613, 613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 790, 0, 0, 0, 0, 0, 0, - 279, 0, 0, 895, 0, 0, 0, 0, 0, 0, - 613, 0, -759, 4, 0, 5, 6, 7, 8, 9, - 0, 0, 0, 10, 11, 0, 0, 0, 12, 0, - 13, 14, 15, 16, 17, 18, 19, 217, 0, 0, - 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 27, 0, 0, 0, 613, 217, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, + 0, 0, 0, 0, 0, 0, -629, 0, 217, 0, + 0, 0, 0, 0, 0, -629, -629, -629, -629, -629, + -629, -629, -629, -629, -629, -629, -629, -629, 0, 0, + 0, 0, -629, -629, -629, -629, 0, -629, -629, 0, + 0, 0, 0, 0, -629, 0, 0, 894, 0, 0, + 0, 0, 0, 0, 613, 0, 0, 0, -629, 0, + 0, -629, 0, 0, -629, -629, -629, -629, -629, -629, + -629, -629, -629, -629, -629, -629, -629, 0, 0, 0, + 0, 217, -629, -629, -629, 0, 0, -629, -629, -629, + 0, -629, 0, 0, 0, 0, 0, 0, 0, 613, + 217, 0, 0, -757, 4, 0, 5, 6, 7, 8, + 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, + 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, + 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, + 0, 0, 27, 0, 0, 0, 0, 217, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 0, 217, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 51, 217, 0, 0, 0, 0, 0, - 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, - 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 0, 217, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, + 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, + 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 67, 68, 69, 0, 0, 0, 0, -736, 0, - 0, 0, 0, -759, 0, -759, -736, -736, -736, 0, - 0, -736, -736, -736, 0, -736, 0, 0, 0, 0, - 0, 0, 0, -736, -736, -736, -736, -736, 0, 0, - 0, 0, 0, 0, 0, -736, -736, 0, -736, -736, - -736, -736, -736, 0, 0, 0, 0, 0, 217, 0, - 0, 0, 0, 333, -760, -760, -760, -760, 338, 339, - 0, 217, -760, -760, 0, 0, -736, 0, 0, 0, - 346, 347, 0, 0, 0, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, -736, 0, 0, - 0, 0, -736, -736, -736, -736, 0, 745, -736, 0, - 0, 0, 0, 0, -736, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 0, 0, 0, -736, 0, - 0, -736, 217, 0, -116, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, 0, 0, 0, - 0, -736, -736, -736, -736, -630, 0, -736, -736, -736, - 0, -736, 0, -630, -630, -630, 0, 0, -630, -630, - -630, 0, -630, 0, 0, 0, 0, 685, 0, 0, - -630, 0, -630, -630, -630, 0, 0, 0, 0, 0, - 0, 0, -630, -630, 0, -630, -630, -630, -630, -630, + 0, 0, 67, 68, 69, 0, 0, 0, 0, 0, + 217, -735, 0, 0, -757, 0, -757, 0, 0, -735, + -735, -735, 0, 217, -735, -735, -735, 0, -735, 0, + 0, 0, 0, 0, 0, 0, -735, -735, -735, -735, + -735, 0, 0, 0, 0, 0, 0, 0, -735, -735, + 0, -735, -735, -735, -735, -735, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, + 335, 336, 337, 338, 339, 0, 0, 342, 343, -735, + 0, 0, 0, 0, 217, 346, 347, 0, -735, -735, + -735, -735, -735, -735, -735, -735, -735, -735, -735, -735, + -735, 0, 0, 0, 0, -735, -735, -735, -735, 0, + 745, -735, 0, 0, 0, 0, 0, -735, 0, 0, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 0, -735, 0, 0, -735, 0, 0, -116, -735, -735, + -735, -735, -735, -735, -735, -735, -735, -735, -735, -735, + 0, 0, 0, 0, -735, -735, -735, -735, -632, 0, + -735, -735, -735, 0, -735, 0, -632, -632, -632, 0, + 0, -632, -632, -632, 0, -632, 0, 0, 0, 0, + 685, 0, 0, -632, 0, -632, -632, -632, 0, 0, + 0, 0, 0, 0, 0, -632, -632, 0, -632, -632, + -632, -632, -632, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, -632, 0, 0, 0, + 346, 347, 0, 0, 0, -632, -632, -632, -632, -632, + -632, -632, -632, -632, -632, -632, -632, -632, 0, 0, + 0, 0, -632, -632, -632, -632, 0, -632, -632, 0, + 0, 0, 0, 348, -632, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 0, 0, 0, -632, 0, + 0, -632, -257, 0, -632, -632, -632, -632, -632, -632, + -632, -632, -632, -632, -632, -632, -632, 0, 0, 0, + 0, 0, -632, -632, -632, -736, 0, -632, -632, -632, + 0, -632, 0, -736, -736, -736, 0, 0, -736, -736, + -736, 0, -736, 0, 0, 0, 0, 685, 0, 0, + -736, -736, -736, -736, -736, 0, 0, 0, 0, 0, + 0, 0, -736, -736, 0, -736, -736, -736, -736, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, -630, 0, 0, 0, 346, 347, 0, - 0, 0, -630, -630, -630, -630, -630, -630, -630, -630, - -630, -630, -630, -630, -630, 0, 0, 0, 0, -630, - -630, -630, -630, 0, -630, -630, 0, 0, 0, 0, - 348, -630, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 0, 0, 0, -630, 0, 0, -630, -257, - 0, -630, -630, -630, -630, -630, -630, -630, -630, -630, - -630, -630, -630, -630, 0, 0, 0, 0, 0, -630, - -630, -630, -633, 0, -630, -630, -630, 0, -630, 0, - -633, -633, -633, 0, 0, -633, -633, -633, 0, -633, - 0, 0, 0, 0, 685, 0, 0, -633, 0, -633, - -633, -633, 0, 0, 0, 0, 0, 0, 0, -633, - -633, 0, -633, -633, -633, -633, -633, 0, 0, 0, + 343, 344, 345, -736, 0, 0, 0, 346, 347, 0, + 0, 0, -736, -736, -736, -736, -736, -736, -736, -736, + -736, -736, -736, -736, -736, 0, 0, 0, 0, -736, + -736, -736, -736, 0, 0, -736, 0, 0, 0, 0, + 348, -736, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 0, 0, 0, -736, 0, 0, -736, 0, + 0, 0, -736, -736, -736, -736, -736, -736, -736, -736, + -736, -736, -736, -736, 0, 0, 0, 0, -736, -736, + -736, -736, -737, 0, -736, -736, -736, 0, -736, 0, + -737, -737, -737, 0, 0, -737, -737, -737, 0, -737, + 0, 0, 0, 0, 0, 0, 0, -737, -737, -737, + -737, -737, 0, 0, 0, 0, 0, 0, 0, -737, + -737, 0, -737, -737, -737, -737, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - -633, 0, 0, 0, 346, 347, 0, 0, 0, -633, - -633, -633, -633, -633, -633, -633, -633, -633, -633, -633, - -633, -633, 0, 0, 0, 0, -633, -633, -633, -633, - 0, -633, -633, 0, 0, 0, 0, 348, -633, 349, + -737, 0, 0, 0, 346, 347, 0, 0, 0, -737, + -737, -737, -737, -737, -737, -737, -737, -737, -737, -737, + -737, -737, 0, 0, 0, 0, -737, -737, -737, -737, + 0, 0, -737, 0, 0, 0, 0, 348, -737, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 0, - 0, 0, -633, 0, 0, -633, 0, 0, -633, -633, - -633, -633, -633, -633, -633, -633, -633, -633, -633, -633, - -633, 0, 0, 0, 0, 0, -633, -633, -633, -737, - 0, -633, -633, -633, 0, -633, 0, -737, -737, -737, - 0, 0, -737, -737, -737, 0, -737, 0, 0, 0, - 0, 0, 0, 0, -737, -737, -737, -737, -737, 0, - 0, 0, 0, 0, 0, 0, -737, -737, 0, -737, - -737, -737, -737, -737, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, -737, 0, 0, - 0, 346, 347, 0, 0, 0, -737, -737, -737, -737, - -737, -737, -737, -737, -737, -737, -737, -737, -737, 0, - 0, 0, 0, -737, -737, -737, -737, 0, 0, -737, - 0, 0, 0, 0, 348, -737, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 0, 0, 0, -737, - 0, 0, -737, 0, 0, 0, -737, -737, -737, -737, - -737, -737, -737, -737, -737, -737, -737, -737, 0, 0, - 0, 0, -737, -737, -737, -737, -738, 0, -737, -737, - -737, 0, -737, 0, -738, -738, -738, 0, 0, -738, - -738, -738, 0, -738, 0, 0, 0, 0, 0, 0, - 0, -738, -738, -738, -738, -738, 0, 0, 0, 0, - 0, 0, 0, -738, -738, 0, -738, -738, -738, -738, - -738, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 337, 338, 339, 0, 0, - 342, 343, 0, 0, -738, 0, 0, 0, 346, 347, - 0, 0, 0, -738, -738, -738, -738, -738, -738, -738, - -738, -738, -738, -738, -738, -738, 0, 0, 0, 0, - -738, -738, -738, -738, 0, 0, -738, 0, 0, 0, - 0, 0, -738, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 0, 0, 0, -738, 0, 0, -738, - 0, 0, 0, -738, -738, -738, -738, -738, -738, -738, - -738, -738, -738, -738, -738, 0, 0, 0, 0, -738, - -738, -738, -738, -310, 0, -738, -738, -738, 0, -738, - 0, -310, -310, -310, 0, 0, -310, -310, -310, 0, - -310, 0, 0, 0, 0, 0, 0, 0, -310, 0, - -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, - -310, -310, 0, -310, -310, -310, -310, -310, 0, 0, + 0, 0, -737, 0, 0, -737, 0, 0, 0, -737, + -737, -737, -737, -737, -737, -737, -737, -737, -737, -737, + -737, 0, 0, 0, 0, -737, -737, -737, -737, -310, + 0, -737, -737, -737, 0, -737, 0, -310, -310, -310, + 0, 0, -310, -310, -310, 0, -310, 0, 0, 0, + 0, 0, 0, 0, -310, 0, -310, -310, -310, 0, + 0, 0, 0, 0, 0, 0, -310, -310, 0, -310, + -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, + 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, -310, 0, + 0, 0, 0, -310, -310, -310, -310, 0, 746, -310, + 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, + 0, 0, -310, 0, 0, -118, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, 0, 0, + 0, 0, 0, -310, -310, -310, -449, 0, -310, -310, + -310, 0, -310, 0, -449, -449, -449, 0, 0, -449, + -449, -449, 0, -449, 0, 0, 0, 0, 0, 0, + 0, -449, -449, -449, -449, 0, 0, 0, 0, 0, + 0, 0, 0, -449, -449, 0, -449, -449, -449, -449, + -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, - -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, -310, 0, 0, 0, 0, -310, -310, -310, - -310, 0, 746, -310, 0, 0, 0, 0, 0, -310, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -310, 0, 0, -310, 0, 0, -118, - -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, 0, 0, 0, 0, 0, -310, -310, -310, - -449, 0, -310, -310, -310, 0, -310, 0, -449, -449, - -449, 0, 0, -449, -449, -449, 0, -449, 0, 0, - 0, 0, 0, 0, 0, -449, -449, -449, -449, 0, - 0, 0, 0, 0, 0, 0, 0, -449, -449, 0, - -449, -449, -449, -449, -449, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -449, 0, - 0, 0, 0, 0, 0, 0, 0, -449, -449, -449, - -449, -449, -449, -449, -449, -449, -449, -449, -449, -449, - 0, 0, 0, 0, -449, -449, -449, -449, 0, 0, - -449, 0, 0, 0, 0, 0, -449, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -449, 0, 0, 0, 0, 0, 0, -449, 0, -449, - -449, -449, -449, -449, -449, -449, -449, -449, -449, 0, - 0, 0, 0, -449, -449, -449, -449, -302, 233, -449, - -449, -449, 0, -449, 0, -302, -302, -302, 0, 0, - -302, -302, -302, 0, -302, 0, 0, 0, 0, 0, - 0, 0, -302, 0, -302, -302, -302, 0, 0, 0, - 0, 0, 0, 0, -302, -302, 0, -302, -302, -302, - -302, -302, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -449, 0, 0, 0, 0, 0, + 0, 0, 0, -449, -449, -449, -449, -449, -449, -449, + -449, -449, -449, -449, -449, -449, 0, 0, 0, 0, + -449, -449, -449, -449, 0, 0, -449, 0, 0, 0, + 0, 0, -449, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -449, 0, 0, 0, + 0, 0, 0, -449, 0, -449, -449, -449, -449, -449, + -449, -449, -449, -449, -449, 0, 0, 0, 0, -449, + -449, -449, -449, -302, 233, -449, -449, -449, 0, -449, + 0, -302, -302, -302, 0, 0, -302, -302, -302, 0, + -302, 0, 0, 0, 0, 0, 0, 0, -302, 0, + -302, -302, -302, 0, 0, 0, 0, 0, 0, 0, + -302, -302, 0, -302, -302, -302, -302, -302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -302, 0, 0, 0, 0, - 0, 0, 0, 0, -302, -302, -302, -302, -302, -302, - -302, -302, -302, -302, -302, -302, -302, 0, 0, 0, - 0, -302, -302, -302, -302, 0, 0, -302, 0, 0, - 0, 0, 0, -302, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -302, 0, 0, - -302, 0, 0, 0, -302, -302, -302, -302, -302, -302, - -302, -302, -302, -302, -302, -302, 0, 0, 0, 0, - 0, -302, -302, -302, -759, 0, -302, -302, -302, 0, - -302, 0, -759, -759, -759, 0, 0, -759, -759, -759, - 0, -759, 0, 0, 0, 0, 0, 0, 0, -759, - -759, -759, -759, 0, 0, 0, 0, 0, 0, 0, - 0, -759, -759, 0, -759, -759, -759, -759, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -302, 0, 0, 0, 0, 0, 0, 0, 0, + -302, -302, -302, -302, -302, -302, -302, -302, -302, -302, + -302, -302, -302, 0, 0, 0, 0, -302, -302, -302, + -302, 0, 0, -302, 0, 0, 0, 0, 0, -302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, - 0, -759, -759, -759, -759, -759, -759, -759, -759, -759, - -759, -759, -759, -759, 0, 0, 0, 0, -759, -759, - -759, -759, 0, 0, -759, 0, 0, 0, 0, 0, - -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, - 0, -759, 0, -759, -759, -759, -759, -759, -759, -759, - -759, -759, -759, 0, 0, 0, 0, -759, -759, -759, - -759, -317, 233, -759, -759, -759, 0, -759, 0, -317, - -317, -317, 0, 0, -317, -317, -317, 0, -317, 0, - 0, 0, 0, 0, 0, 0, -317, 0, -317, -317, - 0, 0, 0, 0, 0, 0, 0, 0, -317, -317, - 0, -317, -317, -317, -317, -317, 0, 0, 0, 0, + 0, 0, 0, -302, 0, 0, -302, 0, 0, 0, + -302, -302, -302, -302, -302, -302, -302, -302, -302, -302, + -302, -302, 0, 0, 0, 0, 0, -302, -302, -302, + -757, 0, -302, -302, -302, 0, -302, 0, -757, -757, + -757, 0, 0, -757, -757, -757, 0, -757, 0, 0, + 0, 0, 0, 0, 0, -757, -757, -757, -757, 0, + 0, 0, 0, 0, 0, 0, 0, -757, -757, 0, + -757, -757, -757, -757, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, - 0, 0, 0, 0, 0, 0, 0, 0, -317, -317, - -317, -317, -317, -317, -317, -317, -317, -317, -317, -317, - -317, 0, 0, 0, 0, -317, -317, -317, -317, 0, - 0, -317, 0, 0, 0, 0, 0, -317, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, + 0, 0, 0, 0, 0, 0, 0, -757, -757, -757, + -757, -757, -757, -757, -757, -757, -757, -757, -757, -757, + 0, 0, 0, 0, -757, -757, -757, -757, 0, 0, + -757, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -317, 0, 0, 0, 0, 0, 0, -317, 0, - -317, -317, -317, -317, -317, -317, -317, -317, -317, -317, - 0, 0, 0, 0, 0, -317, -317, -317, -736, 230, - -317, -317, -317, 0, -317, 0, -736, -736, -736, 0, - 0, 0, -736, -736, 0, -736, 0, 0, 0, 0, - 0, 0, 0, -736, -736, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -736, -736, 0, -736, -736, - -736, -736, -736, 0, 0, 0, 0, 0, 0, 0, + -757, 0, 0, 0, 0, 0, 0, -757, 0, -757, + -757, -757, -757, -757, -757, -757, -757, -757, -757, 0, + 0, 0, 0, -757, -757, -757, -757, -317, 233, -757, + -757, -757, 0, -757, 0, -317, -317, -317, 0, 0, + -317, -317, -317, 0, -317, 0, 0, 0, 0, 0, + 0, 0, -317, 0, -317, -317, 0, 0, 0, 0, + 0, 0, 0, 0, -317, -317, 0, -317, -317, -317, + -317, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, - 0, 0, 0, 0, 0, -736, -736, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, -736, 0, 0, - 0, 0, -736, -736, -736, -736, 0, 691, 0, 0, + 0, 0, 0, 0, 0, -317, 0, 0, 0, 0, + 0, 0, 0, 0, -317, -317, -317, -317, -317, -317, + -317, -317, -317, -317, -317, -317, -317, 0, 0, 0, + 0, -317, -317, -317, -317, 0, 0, -317, 0, 0, + 0, 0, 0, -317, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -317, 0, 0, + 0, 0, 0, 0, -317, 0, -317, -317, -317, -317, + -317, -317, -317, -317, -317, -317, 0, 0, 0, 0, + 0, -317, -317, -317, -735, 230, -317, -317, -317, 0, + -317, 0, -735, -735, -735, 0, 0, 0, -735, -735, + 0, -735, 0, 0, 0, 0, 0, 0, 0, -735, + -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -735, -735, 0, -735, -735, -735, -735, -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, - 0, 0, 0, 0, -116, -736, 0, -736, -736, -736, - -736, -736, -736, -736, -736, -736, -736, 0, 0, 0, - 0, -736, -736, -736, -736, -310, 0, -736, 0, -736, - 0, -736, 0, -310, -310, -310, 0, 0, 0, -310, - -310, 0, -310, 0, 0, 0, 0, 0, 0, 0, - -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -310, -310, 0, -310, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -735, 0, 0, 0, 0, 0, 0, 0, + 0, -735, -735, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, -735, 0, 0, 0, 0, -735, -735, + -735, -735, 0, 691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, - 0, 0, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, -310, -310, -310, 0, 0, 0, 0, -310, - -310, -310, -310, 0, 692, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -735, 0, 0, 0, 0, 0, + -116, -735, 0, -735, -735, -735, -735, -735, -735, -735, + -735, -735, -735, 0, 0, 0, 0, -735, -735, -735, + -735, -310, 0, -735, 0, -735, 0, -735, 0, -310, + -310, -310, 0, 0, 0, -310, -310, 0, -310, 0, + 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, + 0, -310, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, - 0, -118, -310, 0, -310, -310, -310, -310, -310, -310, - -310, -310, -310, -310, 0, 0, 0, 0, 0, -310, - -310, -109, -310, 0, -310, 0, -310, 0, -310, 0, - -310, -310, -310, 0, 0, 0, -310, -310, 0, -310, - 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, - -310, 0, -310, -310, -310, -310, -310, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -310, 0, 0, 0, 0, 0, 0, 0, 0, -310, + 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, -310, 0, 0, 0, 0, -310, -310, -310, -310, - 0, 692, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -310, 0, 0, 0, 0, 0, -118, -310, - 0, -310, -310, -310, -310, -310, -310, -310, -310, -310, - -310, 0, 0, 0, 0, 0, -310, -310, -310, 0, - 0, -310, 0, -310, 257, -310, 5, 6, 7, 8, - 9, -759, -759, -759, 10, 11, 0, 0, -759, 12, - 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 68, 69, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -759, 257, -759, 5, 6, 7, - 8, 9, 0, 0, -759, 10, 11, 0, -759, -759, - 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, - 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, - 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, - 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, - 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, - 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 67, 68, 69, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -759, 257, -759, 5, 6, - 7, 8, 9, 0, 0, -759, 10, 11, 0, 0, - -759, 12, -759, 13, 14, 15, 16, 17, 18, 19, - 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, - 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, - 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, - 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, - 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, - 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, + -310, 0, 0, 0, 0, -310, -310, -310, -310, 0, + 692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -759, 257, -759, 5, - 6, 7, 8, 9, 0, 0, -759, 10, 11, 0, - 0, -759, 12, 0, 13, 14, 15, 16, 17, 18, - 19, -759, 0, 0, 0, 0, 20, 21, 22, 23, - 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, - 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, - 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, - 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, - 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, -310, 0, 0, 0, 0, 0, -118, -310, 0, + -310, -310, -310, -310, -310, -310, -310, -310, -310, -310, + 0, 0, 0, 0, 0, -310, -310, -109, -310, 0, + -310, 0, -310, 0, -310, 0, -310, -310, -310, 0, + 0, 0, -310, -310, 0, -310, 0, 0, 0, 0, + 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -310, -310, 0, -310, -310, + -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 67, 68, 69, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -759, 257, -759, - 5, 6, 7, 8, 9, 0, 0, -759, 10, 11, - 0, 0, -759, 12, 0, 13, 14, 15, 16, 17, - 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, - 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, - 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, - 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, - 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, - 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 257, 0, 5, 6, 7, 8, - 9, 0, -759, -759, 10, 11, 67, 68, 69, 12, - 0, 13, 14, 15, 16, 17, 18, 19, -759, 0, - -759, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, + 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, + 0, 0, 0, 0, 0, -310, -310, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, -310, 0, 0, + 0, 0, -310, -310, -310, -310, 0, 692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 257, 0, 5, 6, 7, 8, 9, 0, 0, 0, - 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, -759, 0, -759, 0, 0, 20, + 0, 0, 0, 0, 0, 0, 0, 0, -310, 0, + 0, 0, 0, 0, -118, -310, 0, -310, -310, -310, + -310, -310, -310, -310, -310, -310, -310, 0, 0, 0, + 0, 0, -310, -310, -310, 0, 0, -310, 0, -310, + 257, -310, 5, 6, 7, 8, 9, -757, -757, -757, + 10, 11, 0, 0, -757, 12, 0, 13, 14, 15, + 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, @@ -2744,13 +2757,13 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, - 259, 54, 0, 55, 56, 0, 57, 0, 0, 58, + 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, - 69, 0, 0, 0, 0, 0, 0, 0, -759, 0, - -759, 257, -759, 5, 6, 7, 8, 9, 0, 0, - 0, 10, 11, 0, 0, 0, 12, 0, 13, 14, + 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -757, 257, -757, 5, 6, 7, 8, 9, 0, 0, + -757, 10, 11, 0, -757, -757, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, @@ -2763,12 +2776,12 @@ static const yytype_int16 yytable[] = 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, - 68, 69, 0, 0, 0, 0, 0, 0, 0, -759, - 0, -759, 4, -759, 5, 6, 7, 8, 9, 0, - 0, 0, 10, 11, 0, 0, 0, 12, 0, 13, + 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -757, 257, -757, 5, 6, 7, 8, 9, 0, + 0, -757, 10, 11, 0, 0, -757, 12, -757, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 27, 0, 0, 0, 0, 0, 28, 29, 30, 31, + 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, @@ -2778,10 +2791,10 @@ static const yytype_int16 yytable[] = 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 67, 68, 69, 0, 0, -759, 0, 0, 0, 0, - 0, 0, -759, 257, -759, 5, 6, 7, 8, 9, - 0, 0, 0, 10, 11, 0, 0, 0, 12, 0, - 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, + 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -757, 257, -757, 5, 6, 7, 8, 9, + 0, 0, -757, 10, 11, 0, 0, -757, 12, 0, + 13, 14, 15, 16, 17, 18, 19, -757, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, @@ -2793,9 +2806,9 @@ static const yytype_int16 yytable[] = 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 67, 68, 69, 0, 0, -759, 0, 0, 0, - 0, 0, 0, -759, 257, -759, 5, 6, 7, 8, - 9, 0, 0, -759, 10, 11, 0, 0, 0, 12, + 0, 67, 68, 69, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -757, 257, -757, 5, 6, 7, 8, + 9, 0, 0, -757, 10, 11, 0, 0, -757, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, @@ -2807,9 +2820,9 @@ static const yytype_int16 yytable[] = 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 257, 0, 5, 6, 7, 8, 9, 0, 0, 0, + 257, 0, 5, 6, 7, 8, 9, 0, -757, -757, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, -759, 0, -759, 0, 0, 20, + 16, 17, 18, 19, -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, @@ -2818,36 +2831,109 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 0, -759, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, - 7, 0, 9, 0, 0, 0, 10, 11, 67, 68, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 257, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, - -759, 0, -759, 0, 0, 20, 21, 22, 23, 24, - 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, - 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, + -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, - 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, - 56, 0, 210, 211, 212, 58, 59, 213, 61, 62, + 0, 0, 0, 52, 0, 0, 259, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, + 0, 0, 0, 0, -757, 0, -757, 257, -757, 5, + 6, 7, 8, 9, 0, 0, 0, 10, 11, 0, + 0, 0, 12, 0, 13, 14, 15, 16, 17, 18, + 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, + 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, + 0, 28, 29, 258, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, + 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, + 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, + 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 67, 68, 69, 0, 0, + 0, 0, 0, 0, 0, -757, 0, -757, 4, -757, + 5, 6, 7, 8, 9, 0, 0, 0, 10, 11, + 0, 0, 0, 12, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, + 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, + 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, + 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, + 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, + 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 67, 68, 69, 0, + 0, -757, 0, 0, 0, 0, 0, 0, -757, 257, + -757, 5, 6, 7, 8, 9, 0, 0, 0, 10, + 11, 0, 0, 0, 12, 0, 13, 14, 15, 16, + 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, + 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, + 0, 0, 0, 28, 29, 258, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, + 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 67, 68, 69, + 0, 0, -757, 0, 0, 0, 0, 0, 0, -757, + 257, -757, 5, 6, 7, 8, 9, 0, 0, -757, + 10, 11, 0, 0, 0, 12, 0, 13, 14, 15, + 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, + 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, + 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, + 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, + 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 257, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, + 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, + -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, - 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, - 14, 15, 16, 17, 18, 19, 0, 0, 237, 0, + 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, + 14, 15, 16, 17, 18, 19, -757, 0, -757, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 27, 0, 0, 0, 0, 0, 0, 29, 0, 0, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, + 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, - 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, - 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 0, 0, 209, 54, 0, 55, 56, 0, 210, 211, + 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, - 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, - 18, 19, 305, 0, 306, 0, 0, 20, 21, 22, + 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 0, 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, @@ -2857,24 +2943,24 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, - 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, - 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 27, 0, 0, 0, 0, 0, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 0, 13, 14, 15, 16, 17, 18, 19, 305, 0, + 306, 0, 0, 20, 21, 22, 23, 24, 25, 26, + 0, 0, 27, 0, 0, 0, 0, 0, 0, 29, + 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, - 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, - 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 0, 208, 0, 0, 209, 54, 0, 55, 56, 0, + 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, 15, - 16, 17, 18, 19, 503, 0, 0, 0, 0, 20, + 16, 17, 18, 19, 0, 0, 237, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 27, 0, - 0, 0, 0, 0, 28, 29, 258, 31, 32, 33, + 0, 0, 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, @@ -2882,30 +2968,28 @@ static const yytype_int16 yytable[] = 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, + 7, 8, 9, 0, 0, 0, 10, 11, 67, 68, + 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, + 503, 0, 0, 0, 0, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 27, 0, 0, 0, 0, 0, + 28, 29, 258, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 53, 54, 0, 55, + 56, 0, 57, 0, 0, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, - 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 503, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 0, 0, 0, 150, 151, - 152, 395, 396, 397, 398, 157, 158, 159, 0, 0, - 0, 0, 0, 160, 161, 162, 163, 399, 400, 401, - 402, 168, 37, 38, 403, 40, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, - 181, 182, 183, 184, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 185, 186, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 0, 197, 198, - 0, 0, 0, 0, 0, 199, 404, 126, 127, 128, + 0, 0, 0, 0, 67, 68, 69, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 503, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 0, 0, 0, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 0, 0, 0, 0, 0, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 288, 289, - 169, 290, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 0, 0, 0, 150, 151, 152, 395, 396, 397, + 398, 157, 158, 159, 0, 0, 0, 0, 0, 160, + 161, 162, 163, 399, 400, 401, 402, 168, 37, 38, + 403, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, 184, @@ -2914,136 +2998,138 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, 0, - 0, 199, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 0, 0, 0, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, - 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 239, 0, 169, 0, 0, 0, 0, + 0, 199, 404, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 0, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 288, 289, 169, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, - 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 0, 0, 0, 0, 0, 199, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 0, 0, 0, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 0, 0, 0, 0, 0, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 0, 0, - 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 0, 0, 0, 0, 181, 182, 183, 184, + 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, + 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 185, 186, 0, 0, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, + 197, 198, 0, 0, 0, 0, 0, 199, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 0, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 0, 0, 0, 0, 0, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 239, + 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 0, 197, 198, 0, 0, 0, 0, - 0, 199, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 0, 0, 0, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, - 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 0, 0, 169, 0, 0, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, + 0, 0, 199, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 0, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 5, 6, 7, 0, 9, 199, 0, 0, 10, - 11, 0, 0, 0, 12, 0, 13, 14, 15, 245, - 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, - 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, - 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, + 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 185, 186, 0, + 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 0, + 197, 198, 0, 0, 0, 0, 0, 199, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 0, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 0, 0, 0, 0, 0, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 0, + 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 278, 0, 0, 209, - 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 5, 6, 7, + 0, 9, 199, 0, 0, 10, 11, 0, 0, 0, + 12, 0, 13, 14, 15, 245, 246, 18, 19, 0, + 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, + 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 7, 0, 9, 0, 0, 279, 10, 11, - 0, 0, 0, 12, 280, 13, 14, 15, 245, 246, - 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, - 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, - 0, 0, 0, 277, 0, 0, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, - 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 278, 0, 0, 209, 54, - 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, - 6, 7, 8, 9, 0, 0, 279, 10, 11, 0, - 0, 0, 12, 526, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, - 24, 25, 26, 0, 0, 27, 0, 0, 0, 0, - 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, - 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, - 0, 0, 0, 0, 52, 0, 0, 53, 54, 0, - 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, - 0, 0, 0, 10, 11, 67, 68, 69, 12, 0, + 0, 0, 278, 0, 0, 209, 54, 0, 55, 56, + 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, + 9, 0, 0, 279, 10, 11, 0, 0, 0, 12, + 280, 13, 14, 15, 245, 246, 18, 19, 0, 0, + 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, + 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, + 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 278, 0, 0, 209, 54, 0, 55, 56, 0, + 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, + 0, 0, 279, 10, 11, 0, 0, 0, 12, 526, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, - 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, + 0, 27, 0, 0, 0, 0, 0, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 210, - 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, + 52, 0, 0, 53, 54, 0, 55, 56, 0, 57, + 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 6, 7, 8, 9, 0, 0, 0, 10, - 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, + 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, + 11, 67, 68, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, - 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, - 0, 0, 0, 28, 29, 0, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, + 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, - 0, 0, 0, 0, 0, 0, 52, 0, 0, 53, - 54, 0, 55, 56, 0, 57, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, + 54, 0, 55, 56, 0, 210, 211, 212, 58, 59, + 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, - 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, + 8, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, - 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, - 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, + 26, 0, 0, 27, 0, 0, 0, 0, 0, 28, + 29, 0, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 439, 0, 0, 0, 0, - 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 210, 211, 212, 58, 59, 213, 61, 62, 63, + 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 53, 54, 0, 55, 56, + 0, 57, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, - 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, - 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, - 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, + 0, 10, 11, 67, 68, 69, 12, 0, 13, 14, + 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, + 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 620, 211, 212, + 50, 439, 0, 0, 0, 0, 0, 0, 208, 0, + 0, 209, 54, 0, 55, 56, 0, 210, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, @@ -3056,7 +3142,7 @@ static const yytype_int16 yytable[] = 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, - 55, 56, 0, 210, 211, 0, 58, 59, 213, 61, + 55, 56, 0, 620, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, @@ -3068,8 +3154,8 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 0, - 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, + 208, 0, 0, 209, 54, 0, 55, 56, 0, 210, + 211, 0, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 245, @@ -3081,7 +3167,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, - 54, 0, 55, 56, 0, 620, 211, 0, 58, 59, + 54, 0, 55, 56, 0, 0, 211, 212, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, @@ -3094,24 +3180,24 @@ static const yytype_int16 yytable[] = 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 0, 211, 0, 58, 59, 213, 61, 62, 63, + 0, 620, 211, 0, 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, - 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, - 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, + 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, + 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, + 33, 34, 35, 36, 37, 38, 39, 40, 207, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 519, 0, 0, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, + 0, 209, 54, 0, 55, 56, 0, 0, 211, 0, + 58, 59, 213, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, - 214, 69, 12, 0, 13, 14, 15, 245, 246, 18, - 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, + 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, + 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, @@ -3119,7 +3205,7 @@ static const yytype_int16 yytable[] = 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, - 55, 56, 0, 770, 0, 0, 58, 59, 60, 61, + 55, 56, 0, 519, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, @@ -3131,7 +3217,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 209, 54, 0, 55, 56, 0, 519, + 208, 0, 0, 209, 54, 0, 55, 56, 0, 770, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, @@ -3144,7 +3230,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, - 54, 0, 55, 56, 0, 843, 0, 0, 58, 59, + 54, 0, 55, 56, 0, 519, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, @@ -3157,7 +3243,7 @@ static const yytype_int16 yytable[] = 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, 54, 0, 55, 56, - 0, 1014, 0, 0, 58, 59, 60, 61, 62, 63, + 0, 843, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, @@ -3169,12 +3255,12 @@ static const yytype_int16 yytable[] = 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, + 0, 209, 54, 0, 55, 56, 0, 1012, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 67, - 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, - 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, + 214, 69, 12, 0, 13, 14, 15, 245, 246, 18, + 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, @@ -3188,7 +3274,7 @@ static const yytype_int16 yytable[] = 0, 0, 0, 10, 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 0, - 0, 27, 0, 0, 0, 0, 0, 0, 29, 0, + 0, 206, 0, 0, 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 0, @@ -3198,52 +3284,89 @@ static const yytype_int16 yytable[] = 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, - 11, 67, 68, 69, 12, 0, 13, 14, 15, 245, + 11, 67, 214, 69, 12, 0, 13, 14, 15, 16, + 17, 18, 19, 0, 0, 0, 0, 0, 20, 21, + 22, 23, 24, 25, 26, 0, 0, 27, 0, 0, + 0, 0, 0, 0, 29, 0, 0, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 209, + 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, + 0, 9, 0, 0, 0, 10, 11, 67, 68, 69, + 12, 0, 13, 14, 15, 245, 246, 18, 19, 0, + 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, + 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 278, 0, 0, 328, 54, 0, 55, 56, + 0, 329, 0, 0, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, + 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, + 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, + 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, + 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, + 0, 0, 277, 0, 0, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, + 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 376, 0, 0, 53, 54, 0, + 55, 56, 0, 57, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, + 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, + 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, + 384, 36, 37, 38, 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 278, 0, 0, 328, - 54, 0, 55, 56, 0, 329, 0, 0, 58, 59, + 0, 0, 386, 0, 0, 0, 387, 0, 0, 209, + 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, + 33, 34, 384, 36, 37, 38, 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 376, 0, - 0, 53, 54, 0, 55, 56, 0, 57, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 387, 0, + 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, 277, 0, - 0, 32, 33, 34, 384, 36, 37, 38, 385, 40, + 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 386, 0, 0, 0, - 387, 0, 0, 209, 54, 0, 55, 56, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 278, 0, 0, 328, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, 0, 0, 0, 0, - 277, 0, 0, 32, 33, 34, 384, 36, 37, 38, - 385, 40, 0, 41, 42, 43, 44, 45, 46, 47, + 277, 0, 0, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 0, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 387, 0, 0, 209, 54, 0, 55, 56, + 0, 0, 1002, 0, 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, 11, 0, @@ -3255,621 +3378,633 @@ static const yytype_int16 yytable[] = 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 278, 0, 0, 328, 54, 0, - 55, 56, 0, 0, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, - 0, 5, 6, 7, 0, 9, 0, 0, 0, 10, - 11, 0, 0, 0, 12, 279, 13, 14, 15, 245, - 246, 18, 19, 0, 0, 0, 0, 0, 20, 247, - 248, 23, 24, 25, 26, 0, 0, 206, 0, 0, - 0, 0, 0, 0, 277, 0, 0, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1004, 0, 0, 209, - 54, 0, 55, 56, 0, 0, 0, 0, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, - 0, 0, 0, 5, 6, 7, 0, 9, 0, 0, - 0, 10, 11, 0, 0, 0, 12, 279, 13, 14, - 15, 245, 246, 18, 19, 0, 0, 0, 0, 0, - 20, 247, 248, 23, 24, 25, 26, 0, 0, 206, - 0, 0, 0, 0, 0, 0, 277, 0, 0, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, - 42, 43, 44, 45, 46, 47, 23, 24, 25, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 33, 34, 781, 0, 0, 0, 782, - 0, 0, 41, 42, 43, 44, 45, 0, 1056, 0, - 0, 209, 54, 0, 55, 56, 0, 0, 0, 0, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, - 0, 0, 0, 783, 784, 0, 0, 0, 0, 0, - 0, 785, 0, 0, 786, 0, 0, 787, 788, 279, - 975, 0, 0, 789, 59, 60, 61, 62, 63, 64, - 65, 66, 23, 24, 25, 26, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 790, 0, 0, 32, 33, - 34, 781, 279, 0, 0, 782, 0, 0, 41, 42, - 43, 44, 45, 0, 0, 23, 24, 25, 26, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 33, 34, 781, 0, 0, 0, 782, 783, - 784, 41, 42, 43, 44, 45, 0, 785, 0, 0, - 786, 0, 0, 787, 788, 0, 1071, 0, 0, 789, - 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, - 0, 0, 783, 784, 0, 0, 0, 0, 0, 0, - 785, 790, 0, 786, 0, 0, 787, 788, 279, 0, - 0, 0, 789, 59, 60, 61, 62, 63, 64, 65, - 66, 564, 565, 0, 0, 566, 0, 0, 0, 0, - 0, 0, 0, 0, 790, 0, 0, 0, 0, 0, - 0, 279, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 0, 0, 0, 0, 1054, 0, 0, 209, 54, 0, + 55, 56, 23, 24, 25, 26, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 0, 0, 0, 32, 33, + 34, 781, 0, 0, 0, 782, 0, 980, 41, 42, + 43, 44, 45, 0, 0, 279, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 921, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 783, + 784, 0, 0, 0, 0, 0, 0, 785, 0, 0, + 786, 0, 0, 787, 788, 0, 974, 925, 0, 789, + 59, 997, 61, 62, 63, 64, 65, 66, 23, 24, + 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 790, 0, 0, 32, 33, 34, 781, 279, 0, + 0, 782, 0, 0, 41, 42, 43, 44, 45, 0, + 0, 23, 24, 25, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, + 781, 0, 0, 0, 782, 783, 784, 41, 42, 43, + 44, 45, 0, 785, 0, 0, 786, 0, 0, 787, + 788, 0, 1069, 0, 0, 789, 59, 60, 61, 62, + 63, 64, 65, 66, 0, 0, 0, 0, 783, 784, + 0, 0, 0, 0, 0, 0, 785, 790, 0, 786, + 0, 0, 787, 788, 279, 0, 0, 0, 789, 59, + 60, 61, 62, 63, 64, 65, 66, 564, 565, 0, + 0, 566, 0, 0, 0, 0, 0, 0, 0, 0, + 790, 0, 0, 0, 0, 0, 0, 279, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 572, 573, 0, 0, 574, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 572, 573, 0, + 0, 574, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 624, 565, 0, 0, 625, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 624, 565, 0, + 0, 625, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 627, 573, 0, 0, 628, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 627, 573, 0, + 0, 628, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 652, 565, 0, 0, 653, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 652, 565, 0, + 0, 653, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 655, 573, 0, 0, 656, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 655, 573, 0, + 0, 656, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 722, 565, 0, 0, 723, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 722, 565, 0, + 0, 723, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 725, 573, 0, 0, 726, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 725, 573, 0, + 0, 726, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 731, 565, 0, 0, 732, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 731, 565, 0, + 0, 732, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 609, 573, 0, 0, 610, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 609, 573, 0, + 0, 610, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 776, 565, 0, 0, 777, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 776, 565, 0, + 0, 777, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 779, 573, 0, 0, 780, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 779, 573, 0, + 0, 780, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1154, 565, 0, 0, 1155, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1152, 565, 0, + 0, 1153, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1157, 573, 0, 0, 1158, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1155, 573, 0, + 0, 1156, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 1188, 565, 0, 0, 1189, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 1186, 565, 0, + 0, 1187, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 609, 573, 0, 0, 610, 199, 233, 0, 0, + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 609, 573, 0, + 0, 610, 199, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, - 0, 181, 182, 183, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 185, 186, 0, 0, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 181, 182, 183, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 185, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 0, 197, - 198, 0, 0, 0, 0, 0, 199 + 0, 0, 0, 0, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 0, 197, 198, 0, 0, 0, + 0, 0, 199 }; static const yytype_int16 yycheck[] = { - 2, 369, 89, 60, 28, 57, 94, 102, 8, 227, - 710, 71, 22, 8, 101, 83, 433, 387, 53, 59, - 866, 331, 16, 17, 95, 91, 92, 71, 28, 95, - 67, 83, 68, 28, 2, 95, 4, 717, 57, 1066, - 26, 16, 17, 626, 96, 97, 98, 53, 16, 17, - 27, 603, 29, 55, 56, 1039, 473, 364, 25, 99, - 92, 55, 56, 95, 59, 425, 4, 13, 78, 893, - 894, 654, 482, 433, 2, 1062, 4, 271, 25, 52, - 1104, 275, 16, 17, 857, 53, 54, 27, 363, 57, - 365, 864, 29, 25, 25, 52, 295, 296, 958, 13, - 68, 25, 25, 100, 99, 1106, 100, 15, 25, 17, - 16, 17, 893, 894, 68, 83, 526, 126, 259, 331, - 1028, 55, 429, 91, 92, 100, 54, 95, 96, 97, - 98, 13, 100, 0, 26, 222, 411, 146, 25, 924, - 34, 724, 96, 97, 37, 38, 1054, 13, 13, 146, - 855, 734, 857, 428, 153, 430, 213, 143, 52, 864, - 414, 415, 148, 689, 251, 15, 100, 66, 66, 1196, - 236, 13, 238, 146, 209, 25, 866, 484, 730, 146, - 953, 148, 1028, 458, 1208, 1169, 123, 328, 1048, 146, - 261, 145, 13, 1039, 100, 778, 283, 1184, 68, 146, - 146, 261, 414, 415, 787, 151, 1207, 153, 1054, 244, - 485, 151, 280, 153, 146, 146, 1062, 261, 635, 221, - 119, 119, 146, 146, 259, 227, 444, 97, 280, 146, - 600, 233, 1013, 1018, 1019, 13, 230, 151, 232, 153, - 242, 209, 279, 143, 310, 311, 312, 313, 953, 315, - 316, 143, 855, 259, 857, 230, 56, 232, 233, 146, - 153, 864, 230, 866, 232, 233, 1174, 143, 236, 151, - 238, 153, 682, 633, 242, 635, 244, 329, 310, 311, - 312, 313, 148, 1191, 591, 151, 151, 153, 153, 257, - 326, 259, 379, 328, 601, 331, 230, 849, 232, 498, - 277, 500, 373, 25, 856, 371, 148, 152, 891, 151, - 329, 153, 280, 373, 242, 58, 1016, 592, 870, 1104, - 386, 1106, 328, 1169, 230, 109, 232, 602, 13, 257, - 151, 13, 153, 152, 77, 370, 1016, 372, 1184, 371, - 1164, 309, 310, 311, 312, 313, 314, 315, 316, 133, - 953, 877, 878, 866, 66, 100, 37, 38, 326, 68, - 328, 329, 364, 331, 1054, 108, 99, 893, 894, 112, - 365, 309, 1062, 151, 1064, 153, 100, 880, 414, 415, - 687, 309, 34, 151, 978, 153, 314, 25, 97, 364, - 893, 894, 326, 126, 977, 705, 364, 331, 366, 152, - 52, 146, 370, 371, 372, 623, 25, 783, 784, 121, - 122, 686, 124, 688, 482, 785, 411, 152, 386, 1002, - 1003, 236, 1207, 1208, 146, 1028, 148, 429, 452, 153, - 482, 425, 25, 97, 694, 430, 1039, 691, 692, 28, - 442, 701, 444, 697, 698, 862, 414, 415, 22, 264, - 537, 1054, 452, 268, 429, 649, 126, 452, 526, 1062, - 986, 429, 661, 458, 99, 99, 151, 666, 153, 151, - 13, 153, 684, 99, 526, 1069, 470, 845, 146, 691, - 692, 145, 484, 77, 148, 697, 698, 1013, 126, 144, - 485, 126, 126, 68, 1184, 1047, 1186, 465, 153, 99, - 126, 1191, 862, 1193, 78, 593, 126, 126, 146, 484, - 1013, 149, 888, 889, 482, 153, 484, 146, 1031, 99, - 890, 96, 97, 1036, 153, 585, 126, 146, 1031, 148, - 149, 899, 750, 126, 153, 1144, 904, 1237, 604, 1148, - 1230, 1054, 136, 137, 138, 1058, 581, 66, 583, 1062, - 1144, 1064, 99, 146, 1148, 1058, 149, 99, 526, 569, - 153, 99, 816, 942, 943, 99, 1169, 577, 112, 99, - 145, 1123, 638, 1156, 1077, 577, 553, 579, 146, 126, - 56, 1184, 650, 68, 126, 964, 965, 966, 126, 591, - 68, 1200, 126, 617, 571, 68, 126, 592, 650, 601, - 119, 611, 121, 122, 816, 1199, 1200, 602, 151, 611, - 153, 96, 97, 581, 682, 583, 591, 617, 96, 97, - 435, 623, 617, 591, 97, 440, 601, 148, 443, 126, - 682, 446, 66, 601, 66, 603, 604, 99, 1164, 633, - 68, 643, 100, 2, 739, 4, 66, 462, 684, 626, - 68, 25, 467, 866, 68, 691, 692, 16, 17, 146, - 145, 697, 698, 729, 126, 146, 866, 145, 728, 97, - 638, 1184, 153, 1186, 248, 249, 68, 654, 1191, 97, - 1193, 148, 650, 97, 66, 687, 153, 121, 122, 121, - 122, 146, 727, 688, 53, 54, 149, 729, 738, 119, - 153, 121, 122, 705, 706, 97, 708, 26, 710, 68, - 525, 679, 687, 99, 682, 683, 684, 1230, 152, 687, - 152, 68, 148, 691, 692, 1093, 82, 83, 518, 697, - 698, 68, 91, 92, 68, 1114, 95, 119, 146, 121, - 122, 100, 124, 738, 66, 153, 148, 724, 750, 68, - 97, 679, 126, 148, 68, 683, 1135, 734, 68, 727, - 97, 729, 730, 97, 9, 767, 150, 769, 834, 153, - 15, 705, 146, 129, 130, 149, 68, 96, 97, 153, - 816, 1088, 96, 97, 68, 52, 96, 97, 578, 56, - 850, 365, 68, 828, 584, 77, 586, 119, 833, 121, - 122, 778, 834, 52, 96, 97, 149, 56, 126, 68, - 787, 788, 96, 97, 1089, 150, 99, 144, 1031, 56, - 96, 97, 824, 146, 143, 77, 145, 106, 99, 148, - 146, 145, 867, 56, 148, 145, 77, 96, 97, 14, - 15, 1054, 151, 126, 130, 1058, 898, 25, 816, 1062, - 209, 1064, 66, 145, 1054, 126, 430, 146, 1058, 149, - 828, 145, 1062, 146, 1064, 833, 834, 902, 146, 145, - 144, 230, 144, 232, 233, 146, 911, 236, 146, 238, - 146, 849, 99, 242, 458, 244, 145, 68, 856, 866, - 99, 951, 10, 134, 135, 136, 137, 138, 257, 867, - 259, 144, 870, 88, 89, 119, 146, 121, 122, 126, - 962, 485, 54, 146, 891, 96, 97, 126, 44, 1006, - 146, 736, 64, 65, 44, 982, 40, 41, 718, 146, - 898, 721, 126, 8, 902, 13, 751, 146, 940, 25, - 942, 943, 999, 911, 17, 735, 152, 152, 144, 99, - 309, 310, 311, 312, 313, 314, 315, 316, 146, 68, - 128, 68, 964, 965, 966, 15, 150, 326, 148, 328, - 146, 1184, 331, 1186, 131, 1010, 126, 1012, 1191, 146, - 1193, 958, 26, 2, 1184, 4, 1186, 96, 97, 96, - 97, 1191, 52, 1193, 962, 569, 146, 16, 17, 100, - 977, 1053, 131, 577, 100, 364, 983, 366, 146, 1011, - 144, 370, 371, 372, 1016, 1050, 52, 1230, 592, 66, - 67, 26, 126, 146, 68, 1002, 1003, 386, 602, 146, - 1230, 68, 52, 146, 53, 54, 145, 611, 145, 52, - 146, 146, 1010, 131, 1012, 835, 126, 146, 838, 68, - 56, 841, 96, 97, 66, 414, 415, 146, 848, 96, - 97, 851, 146, 68, 146, 146, 414, 415, 642, 643, - 429, 1048, 91, 92, 121, 122, 95, 892, 146, 1047, - 151, 100, 1050, 431, 432, 1053, 1088, 9, 1090, 1124, - 1092, 96, 97, 68, 1089, 146, 1162, 1163, 68, 143, - 146, 145, 866, 131, 148, 56, 465, 119, 145, 121, - 122, 459, 1114, 1088, 688, 99, 931, 932, 58, 99, - 1088, 96, 97, 913, 146, 484, 96, 97, 146, 146, - 1162, 1163, 146, 1135, 52, 146, 146, 77, 143, 120, - 145, 149, 126, 148, 146, 66, 126, 146, 52, 146, - 54, 55, 56, 57, 58, 1123, 1124, 146, 146, 974, - 950, 146, 146, 146, 1141, 242, 146, 146, 108, 109, - 145, 144, 148, 77, 689, 145, 2, 148, 4, 1156, - 40, 41, 42, 43, 44, 1000, 1001, 146, 689, 146, - 209, 461, 77, 133, 1162, 1163, 465, 101, 119, 1234, - 121, 122, 96, 124, 108, 109, 98, 1022, 87, 94, - 95, 230, 611, 232, 233, 706, 1018, 236, 1092, 238, - 1104, 866, 581, 242, 583, 244, 1196, 53, 54, 133, - 769, 57, 591, 883, 740, 1237, 1237, 514, 257, 324, - 259, 887, 601, 1013, 603, 604, 131, 132, 133, 134, - 135, 136, 137, 138, 1077, 1077, 1090, 83, 885, 945, - 52, 947, 54, 55, 56, 57, 1234, 1077, 783, 784, - 96, 97, 98, 99, 1011, 1039, 105, 99, 1042, 638, - 500, 952, 783, 784, 855, 968, 969, 1102, 1054, 1031, - 309, 310, 311, 312, 313, 314, 315, 316, 1062, 77, - 1064, 1058, 1028, 54, 55, 983, 57, 326, -1, 328, - -1, -1, 331, 64, 65, -1, 94, 95, -1, -1, - 679, -1, -1, -1, 683, 684, -1, -1, 687, -1, - -1, 1121, 691, 692, 59, 60, 61, 62, 697, 698, - -1, -1, -1, 691, 692, 364, -1, 366, -1, 697, - 698, 370, 371, 372, -1, 133, 134, 135, 136, 137, - 138, -1, 877, 878, -1, -1, -1, 386, 727, -1, - 729, 730, 887, 888, 889, -1, 877, 878, 893, 894, - -1, -1, -1, 209, -1, -1, 887, 888, 889, -1, - -1, 1181, 893, 894, -1, 414, 415, 745, 746, -1, - 748, 749, -1, -1, -1, 1169, -1, 1171, -1, -1, - 429, -1, 1176, -1, -1, -1, 242, -1, 244, -1, - 1184, -1, 1186, -1, 1110, 1111, -1, -1, -1, 1193, - 1116, 257, 1118, 259, 1120, -1, 689, 52, -1, 54, - 55, 56, 57, 58, -1, -1, 465, 1130, 1131, -1, - -1, -1, -1, 1136, 280, 1138, 1139, 816, -1, -1, - -1, 1225, 77, 978, -1, 484, 1230, -1, 816, 828, - -1, 986, -1, -1, 833, 834, 52, 978, 54, 55, - 56, 57, -1, 309, -1, 986, 101, -1, 314, -1, - 849, -1, 107, 108, 109, -1, -1, 856, 1013, -1, - -1, -1, 328, 329, -1, -1, -1, -1, 867, -1, - -1, 870, 1013, 861, 2, 1089, 4, -1, 133, -1, - -1, 136, -1, 1209, 1210, 1211, 1212, -1, -1, -1, - 783, 784, 1215, 1216, 1217, 1218, -1, -1, 153, -1, - 366, 77, -1, 902, 370, -1, 372, -1, -1, 1235, - -1, -1, 911, 1236, 1069, -1, -1, -1, 94, 95, - -1, -1, 581, -1, 583, 53, 54, -1, 1069, 57, - -1, 52, 591, 54, 55, 56, 57, 58, -1, -1, - -1, -1, 601, -1, 603, 604, -1, -1, -1, 52, - -1, 54, 55, 56, 57, 83, 77, 56, 134, 135, - 136, 137, 138, -1, -1, -1, -1, -1, 96, 97, - 98, -1, 52, -1, 54, 55, 56, 57, -1, 638, - 101, -1, -1, -1, 877, 878, 107, 108, 109, 1144, - -1, -1, -1, 1148, 887, 888, 889, -1, 101, 465, - 893, 894, -1, 1144, 107, -1, -1, 1148, -1, 1164, - -1, 1010, 133, 1012, -1, 136, 482, -1, -1, -1, - 679, 101, -1, 1164, 683, 684, -1, 148, 687, -1, - -1, -1, 691, 692, -1, -1, -1, -1, 697, 698, - -1, -1, -1, -1, 1199, 1200, -1, -1, 1047, -1, - -1, 1050, -1, -1, -1, -1, -1, -1, 1199, 1200, - 526, -1, -1, -1, -1, -1, -1, -1, 727, -1, - 729, 730, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 209, -1, -1, -1, 978, -1, -1, -1, 1088, - -1, -1, -1, 986, -1, -1, -1, -1, 52, -1, - 54, 55, 56, 57, 58, -1, -1, -1, 207, -1, - -1, 210, 211, 212, 242, 581, 244, 583, -1, -1, - 1013, -1, -1, 77, 1123, 1124, -1, -1, -1, 257, - -1, 259, -1, -1, -1, -1, -1, 603, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, - -1, -1, 280, 107, 108, 109, -1, 816, -1, 689, - -1, -1, -1, 1162, 1163, -1, -1, -1, -1, 828, - -1, -1, -1, -1, 833, 834, 1069, -1, -1, 133, - -1, 309, 136, -1, 650, -1, 314, -1, -1, -1, - 849, -1, -1, -1, -1, -1, -1, 856, -1, -1, - 328, 329, -1, 331, -1, -1, -1, -1, 867, -1, - -1, 870, -1, 679, -1, -1, 682, 683, -1, -1, - -1, -1, -1, 689, -1, -1, -1, 326, -1, -1, - -1, -1, 331, -1, -1, 1234, -1, -1, 366, -1, - -1, -1, 370, 902, 372, -1, -1, -1, -1, -1, - -1, 1144, 911, 783, 784, 1148, -1, -1, -1, -1, - -1, 727, -1, -1, 730, -1, -1, -1, -1, -1, - -1, 1164, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 414, 415, -1, 52, - -1, 54, 55, 56, 57, 58, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1199, 1200, -1, -1, - -1, -1, -1, -1, 77, -1, -1, 783, 784, -1, - -1, -1, -1, -1, -1, 424, 425, -1, 91, -1, - -1, -1, -1, -1, 433, -1, -1, 465, 101, -1, - -1, -1, -1, -1, 107, 108, 109, 877, 878, -1, - -1, 1010, -1, 1012, 482, -1, -1, 887, 888, 889, - -1, -1, 828, 893, 894, -1, -1, 833, -1, -1, - 133, 470, -1, 136, 473, -1, -1, -1, -1, -1, - -1, -1, 2, 849, 4, -1, -1, -1, 1047, -1, - 856, 1050, -1, -1, -1, -1, -1, -1, 526, -1, - -1, 867, -1, -1, 870, -1, -1, -1, -1, -1, - -1, 877, 878, -1, -1, -1, -1, -1, -1, -1, - 519, 887, 888, 889, -1, -1, -1, 893, 894, 1088, - -1, -1, 898, 53, 54, -1, 902, 57, -1, -1, - -1, -1, -1, 689, -1, 911, -1, -1, 978, -1, - -1, -1, -1, 581, -1, 583, 986, -1, -1, -1, - -1, -1, -1, 83, 1123, 1124, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 603, 96, 97, 98, 99, - -1, -1, -1, 1013, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 962, 689, -1, -1, - -1, -1, -1, 1162, 1163, -1, -1, -1, -1, -1, - -1, -1, 978, -1, -1, -1, -1, -1, -1, 618, - 986, 620, 650, -1, -1, -1, -1, -1, -1, -1, - -1, 659, -1, -1, 633, -1, 635, 783, 784, 1069, - -1, -1, -1, -1, 1010, -1, 1012, 1013, -1, -1, - -1, 679, -1, -1, 682, 683, 684, -1, -1, -1, - -1, -1, -1, 691, 692, -1, -1, -1, -1, 697, - 698, -1, -1, -1, 2, 1234, 4, -1, -1, 678, - -1, 1047, -1, -1, 1050, -1, -1, 1053, -1, 209, - -1, 783, 784, -1, -1, -1, -1, -1, 2, 727, - 4, -1, 730, 1069, -1, -1, 705, -1, -1, -1, - -1, -1, -1, -1, 1144, -1, -1, -1, 1148, -1, - -1, 720, 242, -1, 244, 53, 54, -1, -1, -1, - -1, 877, 878, -1, 1164, -1, -1, 257, -1, 259, - -1, 887, 888, 889, -1, -1, -1, 893, 894, 53, - 54, -1, -1, -1, -1, -1, -1, 1123, 1124, -1, - 280, 689, -1, -1, -1, -1, -1, -1, 96, 1199, - 1200, 770, -1, -1, -1, -1, -1, -1, 1144, -1, - -1, -1, 1148, -1, -1, 877, 878, -1, 816, 309, - -1, -1, -1, -1, 314, 887, 888, 889, 1164, -1, - 828, 893, 894, -1, -1, 833, -1, -1, 328, 329, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 849, -1, -1, -1, -1, -1, -1, 856, -1, - -1, -1, 978, 1199, 1200, -1, -1, -1, -1, 867, - 986, -1, 870, -1, 843, -1, 366, -1, -1, -1, - 370, -1, 372, -1, -1, 783, 784, -1, -1, -1, - -1, -1, -1, 862, -1, -1, -1, 1013, 1234, -1, - 898, -1, -1, -1, 902, -1, -1, -1, -1, -1, - -1, 209, -1, 911, -1, -1, 978, -1, -1, -1, - -1, -1, -1, 689, 986, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 209, -1, -1, -1, -1, - -1, 910, -1, -1, 242, -1, 244, -1, -1, -1, - -1, 1013, -1, 1069, -1, -1, -1, -1, -1, 257, - -1, 259, -1, -1, 962, -1, -1, -1, 242, 938, - 244, -1, -1, -1, -1, 465, -1, -1, -1, 877, - 878, -1, -1, 257, -1, 259, -1, -1, -1, 887, - 888, 889, 482, -1, -1, 893, 894, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1069, -1, -1, - -1, 309, 1010, -1, 1012, -1, 314, 783, 784, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1144, -1, - 328, -1, 1148, 331, -1, 309, 526, -1, -1, -1, - 314, -1, -1, -1, -1, 1014, -1, -1, 1164, 1047, - -1, -1, 1050, -1, 328, 1053, -1, 331, 1027, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 366, -1, - -1, -1, 370, -1, 372, -1, -1, -1, -1, -1, - 978, -1, 1144, 1199, 1200, -1, 1148, -1, 986, -1, - -1, 581, 366, 583, -1, -1, 370, -1, 372, -1, - -1, -1, 1164, -1, -1, -1, -1, -1, -1, -1, - -1, 877, 878, 603, -1, 1013, 414, 415, -1, -1, - -1, 887, 888, 889, -1, 1123, 1124, 893, 894, -1, - -1, -1, -1, -1, -1, -1, -1, 1199, 1200, -1, - 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 650, -1, -1, -1, -1, -1, -1, 465, -1, 25, - -1, 1069, -1, 0, -1, -1, -1, -1, -1, -1, - -1, 8, 9, 10, -1, -1, 13, 14, 15, 679, - 17, 465, 682, 683, -1, -1, -1, -1, 25, 26, - 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 37, 38, 978, 40, 41, 42, 43, 44, -1, -1, - 986, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, -1, -1, 1234, 727, 94, 95, - 730, 68, -1, -1, -1, -1, 1144, 1013, -1, -1, - 1148, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1164, -1, -1, 96, - 97, 127, -1, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 581, -1, 583, -1, -1, -1, -1, - -1, -1, -1, 120, -1, -1, -1, -1, -1, -1, - -1, 1199, 1200, 1069, -1, 603, -1, 581, -1, 583, - -1, -1, -1, -1, -1, -1, 143, 144, -1, -1, - -1, 148, 149, -1, 151, -1, 153, -1, -1, 603, - -1, -1, -1, -1, -1, -1, -1, -1, 828, -1, - -1, -1, -1, 833, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 849, - -1, -1, -1, -1, -1, -1, 856, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 867, 1144, -1, - 870, 679, 1148, -1, -1, 683, 684, -1, -1, -1, - -1, -1, -1, 691, 692, -1, -1, -1, 1164, 697, - 698, -1, -1, -1, -1, 679, -1, -1, 898, 683, - 684, -1, 902, -1, -1, -1, -1, 691, 692, -1, - -1, 911, -1, 697, 698, -1, -1, -1, -1, 727, - -1, -1, 730, 1199, 1200, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 727, -1, -1, 730, -1, -1, -1, - 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 962, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 48, 49, 50, 51, -1, -1, -1, 55, - 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 68, 69, -1, -1, -1, -1, 816, -1, - 1010, -1, 1012, -1, -1, -1, -1, -1, -1, -1, - 828, -1, -1, -1, -1, 833, -1, -1, -1, -1, - -1, -1, 816, -1, 100, -1, -1, -1, -1, -1, - -1, 849, -1, -1, 828, -1, -1, 1047, 856, 833, - 1050, -1, -1, 1053, -1, -1, -1, -1, -1, 867, - -1, -1, 870, -1, -1, 849, -1, -1, -1, -1, - -1, -1, 856, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 867, -1, -1, 870, -1, -1, -1, - 898, -1, -1, -1, 902, -1, -1, -1, -1, -1, - -1, -1, -1, 911, 33, 34, 35, 36, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 902, -1, - 49, 50, 51, 1123, 1124, -1, -1, 911, -1, -1, - 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, - -1, 207, -1, -1, 210, 211, 212, -1, 214, -1, + 2, 60, 53, 89, 369, 71, 102, 83, 8, 22, + 710, 8, 16, 17, 28, 101, 59, 331, 227, 717, + 16, 17, 94, 91, 92, 387, 4, 95, 28, 95, + 482, 28, 57, 626, 2, 271, 4, 433, 57, 275, + 67, 892, 893, 71, 363, 1064, 365, 26, 16, 17, + 27, 55, 29, 55, 56, 1026, 99, 364, 83, 59, + 92, 654, 603, 95, 27, 78, 295, 296, 1037, 1060, + 68, 96, 97, 98, 526, 1102, 13, 473, 25, 53, + 1104, 1052, 25, 957, 259, 53, 54, 1142, 95, 57, + 52, 1146, 411, 414, 415, 15, 100, 0, 689, 99, + 68, 77, 25, 331, 100, 25, 25, 148, 99, 428, + 143, 430, 153, 892, 893, 83, 68, 2, 13, 4, + 126, 13, 429, 91, 92, 941, 942, 95, 96, 97, + 98, 724, 100, 37, 38, 126, 222, 16, 17, 458, + 146, 734, 425, 1198, 96, 97, 56, 963, 964, 965, + 433, 25, 29, 328, 213, 22, 857, 151, 209, 153, + 136, 137, 138, 864, 143, 251, 485, 66, 236, 54, + 238, 153, 1046, 16, 17, 1194, 9, 484, 25, 1206, + 28, 1205, 15, 126, 146, 778, 414, 415, 151, 730, + 153, 1182, 866, 244, 787, 261, 13, 283, 1167, 146, + 13, 1172, 25, 146, 280, 148, 149, 66, 259, 146, + 153, 78, 55, 56, 151, 52, 153, 100, 1189, 221, + 119, 100, 518, 146, 152, 227, 230, 146, 232, 148, + 682, 233, 1011, 261, 230, 444, 232, 233, 600, 635, + 242, 209, 310, 311, 312, 313, 123, 315, 316, 153, + 866, 952, 279, 148, 261, 280, 151, 100, 153, 151, + 119, 153, 230, 146, 232, 233, 977, 143, 236, 498, + 238, 500, 146, 592, 242, 26, 244, 328, 310, 311, + 312, 313, 578, 602, 591, 259, 877, 878, 584, 257, + 586, 259, 236, 379, 601, 152, 1112, 890, 152, 146, + 277, 892, 893, 371, 329, 13, 100, 373, 849, 146, + 329, 1162, 280, 25, 1014, 856, 1014, 1133, 386, 370, + 264, 372, 326, 146, 268, 148, 52, 331, 326, 870, + 56, 309, 25, 331, 151, 148, 153, 13, 151, 371, + 153, 309, 310, 311, 312, 313, 314, 315, 316, 152, + 633, 230, 635, 232, 328, 25, 1067, 242, 326, 153, + 328, 329, 364, 331, 97, 365, 373, 686, 364, 688, + 691, 692, 257, 13, 783, 784, 697, 698, 1052, 126, + 687, 248, 249, 976, 13, 146, 1060, 230, 1062, 232, + 54, 705, 143, 112, 985, 100, 364, 148, 366, 99, + 64, 65, 370, 371, 372, 126, 482, 1000, 1001, 13, + 1026, 411, 145, 649, 623, 148, 414, 415, 386, 13, + 1011, 1037, 718, 785, 309, 721, 126, 429, 66, 314, + 430, 1142, 661, 429, 146, 1146, 1052, 666, 452, 735, + 442, 146, 444, 151, 1060, 153, 414, 415, 37, 38, + 526, 537, 452, 146, 99, 452, 684, 482, 458, 82, + 83, 429, 866, 691, 692, 855, 862, 857, 109, 697, + 698, 68, 25, 66, 864, 151, 146, 153, 887, 888, + 845, 119, 484, 121, 122, 485, 1197, 1198, 484, 146, + 923, 435, 133, 99, 148, 816, 440, 465, 365, 443, + 97, 526, 446, 146, 1045, 68, 129, 130, 1182, 56, + 1184, 151, 66, 153, 482, 1189, 484, 1191, 462, 585, + 126, 593, 151, 467, 153, 126, 119, 889, 121, 122, + 581, 124, 583, 898, 97, 1235, 604, 99, 903, 835, + 146, 750, 838, 68, 25, 841, 866, 151, 100, 153, + 150, 1167, 848, 153, 1228, 851, 569, 151, 526, 153, + 99, 1154, 952, 430, 577, 119, 1182, 121, 122, 146, + 638, 1162, 97, 126, 650, 577, 553, 579, 148, 862, + 1121, 525, 425, 1016, 1017, 68, 52, 126, 816, 591, + 56, 458, 592, 146, 571, 591, 149, 99, 611, 601, + 153, 68, 602, 617, 66, 601, 682, 146, 68, 611, + 68, 68, 148, 581, 97, 583, 912, 617, 485, 66, + 617, 623, 68, 591, 126, 650, 68, 470, 66, 34, + 97, 148, 25, 601, 68, 603, 604, 97, 96, 97, + 97, 643, 77, 739, 146, 126, 99, 52, 1052, 626, + 149, 97, 1056, 949, 153, 97, 1060, 682, 1062, 121, + 122, 729, 728, 97, 15, 146, 17, 881, 149, 1102, + 638, 1104, 153, 126, 121, 122, 727, 654, 892, 893, + 99, 119, 650, 121, 122, 687, 684, 145, 688, 694, + 152, 687, 68, 691, 692, 738, 701, 729, 149, 697, + 698, 705, 569, 705, 706, 152, 708, 126, 710, 1029, + 577, 679, 126, 34, 682, 683, 684, 689, 150, 687, + 96, 97, 144, 691, 692, 592, 1091, 146, 99, 697, + 698, 52, 1052, 126, 146, 602, 1056, 2, 738, 4, + 1060, 153, 1062, 99, 611, 58, 56, 724, 750, 66, + 67, 16, 17, 146, 99, 126, 149, 734, 26, 727, + 153, 729, 730, 146, 77, 767, 834, 769, 1087, 145, + 126, 77, 1205, 1206, 106, 642, 643, 828, 1182, 1086, + 1184, 126, 833, 66, 850, 1189, 146, 1191, 53, 54, + 633, 68, 736, 153, 679, 108, 66, 1011, 683, 112, + 68, 778, 834, 68, 121, 122, 99, 751, 68, 146, + 787, 783, 784, 99, 56, 1029, 867, 68, 816, 96, + 97, 688, 824, 1119, 1228, 151, 91, 92, 96, 97, + 95, 14, 15, 126, 56, 100, 96, 97, 121, 122, + 126, 124, 1056, 99, 25, 96, 97, 99, 816, 119, + 901, 121, 122, 26, 124, 99, 146, 130, 68, 910, + 828, 1075, 1182, 153, 1184, 833, 834, 149, 145, 1189, + 126, 1191, 897, 144, 126, 143, 10, 145, 40, 41, + 148, 849, 126, 1179, 950, 145, 96, 97, 856, 866, + 66, 77, 88, 89, 145, 68, 146, 148, 146, 867, + 146, 144, 870, 144, 44, 877, 878, 52, 1228, 54, + 55, 56, 57, 890, 886, 887, 888, 146, 1004, 146, + 892, 893, 981, 96, 97, 146, 68, 146, 44, 897, + 8, 99, 126, 901, 13, 145, 961, 939, 997, 941, + 942, 866, 910, 119, 209, 121, 122, 891, 134, 135, + 136, 137, 138, 68, 96, 97, 101, 1008, 126, 1010, + 25, 963, 964, 965, 17, 230, 144, 232, 233, 99, + 143, 236, 145, 238, 99, 148, 146, 242, 146, 244, + 957, 96, 97, 152, 128, 207, 930, 931, 210, 211, + 212, 68, 257, 961, 259, 152, 126, 1048, 150, 976, + 855, 126, 857, 145, 68, 977, 15, 1009, 68, 864, + 148, 866, 1014, 985, 146, 944, 146, 946, 131, 96, + 97, 146, 146, 1000, 1001, 144, 1051, 52, 866, 973, + 145, 68, 96, 97, 100, 131, 96, 97, 100, 1011, + 1008, 146, 1010, 126, 309, 310, 311, 312, 313, 314, + 315, 316, 52, 146, 998, 999, 26, 146, 66, 96, + 97, 326, 146, 328, 689, 146, 331, 52, 145, 1046, + 146, 1122, 52, 131, 68, 126, 1020, 1045, 146, 146, + 1048, 145, 151, 1051, 1086, 145, 1088, 1087, 1090, 146, + 1086, 146, 1160, 1161, 146, 1067, 144, 952, 68, 364, + 146, 366, 96, 97, 326, 370, 371, 372, 145, 331, + 1112, 119, 1037, 121, 122, 1040, 56, 68, 1086, 9, + 146, 386, 146, 414, 415, 131, 96, 97, 1160, 1161, + 56, 1133, 967, 968, 146, 1060, 146, 1062, 68, 146, + 431, 432, 146, 52, 146, 96, 97, 146, 149, 414, + 415, 145, 120, 1121, 1122, 146, 1100, 58, 783, 784, + 146, 148, 1139, 146, 429, 146, 96, 97, 459, 146, + 1142, 1026, 146, 143, 1146, 145, 77, 1154, 148, 1108, + 1109, 1232, 1037, 146, 146, 1114, 144, 1116, 148, 1118, + 1162, 1029, 1160, 1161, 145, 242, 1034, 1052, 146, 146, + 465, 465, 424, 425, 461, 1060, 98, 108, 109, 96, + 87, 433, 611, 706, 1052, 145, 1016, 1090, 1056, 484, + 1087, 1102, 1060, 769, 1062, 1197, 1198, 54, 55, 866, + 57, 882, 133, 1235, 1194, 740, 514, 64, 65, 324, + 1235, 1011, 1167, 1075, 1169, 1075, 1075, 886, 470, 1174, + 884, 473, 877, 878, 1088, 1009, 105, 1182, 99, 1184, + 500, 886, 887, 888, 1232, 951, 1191, 892, 893, 2, + 52, 4, 54, 55, 56, 57, 855, 1029, 1207, 1208, + 1209, 1210, 1056, 16, 17, 52, 1052, 54, 55, 56, + 57, 58, 1026, 1128, 1129, -1, -1, 519, 1223, 1134, + -1, 1136, 1137, 1228, 1233, 40, 41, 42, 43, 44, + 77, -1, 1167, -1, -1, -1, 581, -1, 583, 101, + 53, 54, -1, -1, 91, 107, 591, 1182, 52, -1, + 54, 55, 56, 57, 101, 68, 601, -1, 603, 604, + 107, 108, 109, -1, 1182, 52, 1184, 54, 55, 56, + 57, 1189, 977, 1191, -1, 689, -1, -1, 91, 92, + 985, -1, 95, -1, -1, -1, 133, 100, -1, 136, + -1, -1, -1, 638, 59, 60, 61, 62, 1213, 1214, + 1215, 1216, -1, -1, -1, -1, 1011, 77, -1, -1, + 1228, -1, -1, -1, -1, -1, 618, -1, 620, 1234, + 691, 692, -1, -1, 94, 95, 697, 698, -1, -1, + -1, 633, 77, 635, 679, -1, -1, -1, 683, 684, + -1, -1, 687, -1, -1, -1, 691, 692, -1, 94, + 95, -1, 697, 698, -1, 52, -1, 54, 55, 56, + 57, 58, 1067, 133, 134, 135, 136, 137, 138, 783, + 784, -1, -1, -1, 745, 746, 678, 748, 749, -1, + 77, -1, 727, -1, 729, 730, 689, -1, -1, 134, + 135, 136, 137, 138, -1, -1, 209, -1, -1, -1, + -1, -1, -1, 705, 101, -1, -1, -1, -1, -1, + 107, 108, 109, -1, -1, -1, -1, 230, 720, 232, + 233, -1, -1, 236, -1, 238, -1, -1, -1, 242, + -1, 244, -1, -1, -1, -1, 133, 1142, -1, 136, + -1, 1146, -1, -1, 257, 816, 259, -1, -1, -1, + -1, 689, -1, -1, -1, -1, 153, 1162, -1, -1, + -1, -1, -1, 877, 878, -1, -1, -1, 770, -1, + -1, 816, 886, 887, 888, -1, -1, -1, 892, 893, + 783, 784, -1, 828, -1, 2, -1, 4, 833, 834, + 861, -1, 1197, 1198, -1, -1, 309, 310, 311, 312, + 313, 314, 315, 316, 849, -1, -1, -1, -1, -1, + -1, 856, -1, 326, -1, 328, -1, -1, 331, -1, + -1, -1, 867, -1, -1, 870, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 53, 54, -1, -1, + 57, 843, -1, -1, -1, 783, 784, -1, -1, -1, + -1, 364, -1, 366, -1, -1, 901, 370, 371, 372, + 862, -1, -1, 977, -1, 910, 83, -1, -1, -1, + -1, 985, -1, 386, 877, 878, -1, -1, -1, 96, + 97, 98, 99, 886, 887, 888, -1, -1, -1, 892, + 893, -1, -1, -1, -1, -1, -1, 1011, -1, -1, + -1, 414, 415, -1, -1, -1, -1, 909, -1, -1, + -1, -1, -1, -1, -1, -1, 429, -1, -1, -1, + 52, -1, 54, 55, 56, 57, 58, -1, -1, -1, + -1, -1, -1, -1, -1, 937, -1, -1, -1, 877, + 878, -1, -1, -1, -1, 77, -1, -1, 886, 887, + 888, -1, 465, 1067, 892, 893, -1, -1, -1, -1, + -1, -1, -1, 1008, -1, 1010, -1, -1, -1, 101, + -1, 484, -1, -1, 977, 107, 108, 109, -1, -1, + -1, 52, 985, 54, 55, 56, 57, 58, -1, -1, + -1, -1, 209, -1, -1, -1, -1, 25, -1, -1, + 1045, 133, -1, 1048, 136, -1, 77, -1, 1011, -1, + 1012, -1, -1, -1, -1, -1, 148, -1, -1, -1, + -1, -1, -1, 1025, -1, 242, -1, 244, 1142, -1, + 101, -1, 1146, -1, -1, -1, 107, 108, 109, 977, + 257, 1086, 259, -1, -1, -1, -1, 985, 1162, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 133, 280, 1067, 136, 94, 95, 581, -1, + 583, -1, -1, 1011, -1, -1, 1121, 1122, 591, -1, + -1, -1, -1, 1197, 1198, -1, -1, -1, 601, -1, + 603, 604, 309, -1, -1, -1, -1, 314, -1, 127, + -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 328, 329, -1, -1, 1160, 1161, -1, -1, -1, + -1, -1, -1, -1, -1, 638, -1, -1, -1, 1067, + -1, -1, 52, -1, 54, 55, 56, 57, 58, 1142, + -1, -1, -1, 1146, -1, -1, -1, -1, -1, 366, + -1, -1, -1, 370, -1, 372, -1, 77, -1, 1162, + -1, -1, -1, -1, -1, -1, 679, -1, -1, -1, + 683, 684, -1, -1, 687, 2, -1, 4, 691, 692, + -1, 101, -1, -1, 697, 698, -1, 1232, 108, 109, + -1, -1, -1, -1, 1197, 1198, -1, -1, -1, -1, + -1, -1, -1, -1, 1142, -1, -1, -1, 1146, -1, + -1, -1, -1, 133, 727, -1, 729, 730, 77, -1, + -1, -1, -1, -1, 1162, -1, 53, 54, -1, -1, + 57, -1, -1, -1, -1, 94, 95, 2, -1, 4, + -1, -1, -1, -1, -1, -1, -1, -1, 465, -1, + -1, -1, -1, -1, -1, -1, 83, -1, -1, 1197, + 1198, -1, -1, -1, -1, 482, -1, -1, -1, 96, + 97, 98, 131, 132, 133, 134, 135, 136, 137, 138, + -1, -1, -1, -1, -1, -1, -1, -1, 53, 54, + -1, -1, 57, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 816, -1, -1, -1, -1, -1, 526, + -1, -1, -1, -1, -1, 828, -1, -1, 83, -1, + 833, 834, 33, 34, 35, 36, -1, -1, -1, -1, + -1, 96, 97, 98, 99, -1, 849, -1, 49, 50, + 51, 52, -1, 856, -1, 56, -1, -1, 59, 60, + 61, 62, 63, -1, 867, -1, -1, 870, -1, -1, + -1, -1, -1, -1, 581, -1, 583, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, 209, -1, -1, -1, 603, 98, 901, -1, + 101, -1, -1, 104, 105, -1, 107, 910, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, 242, -1, 244, -1, -1, + -1, 132, -1, -1, -1, 689, -1, -1, 139, -1, + 257, -1, 259, 650, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 209, -1, -1, -1, -1, -1, + -1, -1, -1, 280, -1, -1, -1, -1, -1, -1, + -1, -1, 679, -1, -1, 682, 683, -1, -1, -1, + -1, -1, 689, -1, -1, -1, 2, 242, 4, 244, + -1, -1, 309, -1, -1, -1, -1, 314, -1, -1, + -1, -1, 257, -1, 259, 1008, -1, 1010, -1, -1, + -1, 328, 329, -1, 331, -1, -1, -1, -1, -1, + 727, -1, -1, 730, -1, 280, -1, -1, -1, 783, + 784, -1, -1, -1, -1, -1, -1, 53, 54, -1, + -1, -1, 1045, -1, -1, 1048, -1, -1, -1, 366, + -1, -1, -1, 370, 309, 372, -1, -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 230, -1, 232, 233, -1, -1, + -1, -1, -1, 328, 329, -1, 783, 784, -1, -1, + 96, -1, -1, 1086, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 366, -1, -1, -1, 370, -1, 372, 1121, 1122, + -1, 828, -1, 877, 878, -1, 833, -1, -1, -1, + -1, -1, 886, 887, 888, -1, -1, -1, 892, 893, + -1, -1, 849, -1, -1, -1, -1, -1, 465, 856, + -1, -1, -1, -1, -1, -1, -1, 1160, 1161, -1, + 867, -1, -1, 870, -1, 482, -1, -1, -1, -1, + 877, 878, -1, -1, -1, -1, -1, -1, -1, 886, + 887, 888, -1, -1, -1, 892, 893, -1, -1, -1, + 897, -1, -1, 209, 901, -1, -1, -1, -1, -1, + -1, -1, -1, 910, -1, -1, -1, -1, -1, 526, + 465, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2, 977, 4, -1, 242, 482, 244, 1232, + -1, 985, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, -1, 259, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 961, -1, -1, 1011, -1, -1, + -1, -1, -1, -1, 581, -1, 583, -1, -1, -1, + 977, 526, -1, 53, 54, -1, -1, -1, 985, -1, + -1, -1, -1, -1, -1, -1, 603, -1, -1, -1, + -1, -1, -1, 309, -1, -1, -1, -1, 314, -1, + -1, 1008, -1, 1010, 1011, -1, -1, -1, -1, -1, + -1, -1, 328, 1067, -1, 331, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 581, -1, 583, -1, + -1, -1, -1, 650, -1, -1, -1, -1, 1045, -1, + -1, 1048, 659, -1, 1051, -1, -1, -1, 603, -1, + 366, -1, -1, -1, 370, -1, 372, -1, -1, -1, + 1067, -1, 679, -1, -1, 682, 683, 684, -1, -1, + -1, -1, -1, -1, 691, 692, -1, -1, -1, -1, + 697, 698, -1, -1, -1, -1, -1, -1, 1142, -1, + -1, -1, 1146, -1, -1, 650, -1, -1, 414, 415, + -1, -1, -1, -1, 33, 34, 35, 36, 1162, -1, + 727, -1, -1, 730, 1121, 1122, -1, -1, -1, -1, + 49, 50, 51, -1, 679, -1, -1, 682, 683, 209, + 59, 60, 61, 62, 63, 1142, -1, -1, -1, 1146, + -1, -1, -1, 1197, 1198, -1, -1, -1, -1, 465, + -1, -1, -1, -1, -1, 1162, -1, -1, -1, -1, + -1, -1, 242, -1, 244, -1, -1, -1, -1, -1, + -1, -1, 727, -1, -1, 730, -1, 257, -1, 259, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, - -1, 77, 78, 79, 80, 81, 82, 83, 84, -1, - 86, 87, 1010, -1, 1012, -1, -1, -1, 94, 95, - 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1010, -1, 1012, -1, - -1, -1, -1, -1, 1234, -1, -1, -1, -1, 1047, - -1, -1, 1050, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, -1, -1, -1, -1, -1, -1, - 326, -1, -1, 1047, -1, 331, 1050, 333, 334, 335, - 336, 337, -1, -1, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, -1, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, -1, -1, -1, 364, -1, + 1197, 1198, -1, -1, -1, -1, -1, -1, -1, 816, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 139, 828, 86, 87, -1, -1, 833, -1, -1, -1, + 94, 95, -1, -1, -1, 1232, -1, -1, -1, 309, + -1, -1, 849, -1, 314, -1, -1, -1, 689, 856, + -1, -1, -1, -1, -1, -1, -1, -1, 328, -1, + 867, 331, -1, 870, -1, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 581, -1, 583, -1, -1, + -1, -1, -1, 828, -1, -1, -1, -1, 833, -1, + 897, -1, -1, -1, 901, -1, 366, 603, -1, -1, + 370, -1, 372, 910, 849, -1, -1, -1, -1, -1, + -1, 856, -1, -1, -1, -1, -1, -1, -1, -1, + 689, -1, 867, -1, -1, 870, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1123, 1124, -1, -1, -1, - -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, -1, -1, 1123, - 1124, 94, 95, -1, -1, -1, -1, -1, 414, 415, - -1, -1, -1, -1, -1, -1, -1, 423, 424, 425, - -1, -1, -1, 429, -1, 431, 432, 433, -1, -1, - -1, -1, -1, 439, 127, -1, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, -1, -1, 454, -1, - -1, -1, -1, 459, -1, -1, -1, -1, -1, -1, - 153, -1, -1, -1, 470, -1, -1, 473, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 484, -1, - -1, -1, -1, -1, -1, -1, 1234, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 502, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 1234, -1, -1, 519, 94, 95, -1, -1, -1, -1, - -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, - 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, - -1, -1, -1, -1, -1, -1, -1, 25, 26, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 37, - 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, + -1, -1, 783, 784, 414, 415, -1, -1, -1, -1, + -1, -1, 897, -1, 961, -1, 901, -1, -1, -1, + -1, -1, -1, -1, -1, 910, -1, -1, -1, -1, + -1, -1, -1, 679, -1, -1, -1, 683, 684, -1, + -1, -1, -1, -1, -1, 691, 692, -1, -1, -1, + -1, 697, 698, -1, -1, 465, -1, -1, -1, -1, + -1, 1008, -1, 1010, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 783, 784, 961, -1, -1, -1, + -1, 727, -1, -1, 730, 77, 78, 79, 80, 81, + 82, 83, 84, -1, 86, 87, 877, 878, 1045, -1, + -1, 1048, 94, 95, 1051, 886, 887, 888, -1, -1, + -1, 892, 893, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1008, -1, 1010, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 591, -1, -1, -1, -1, - 68, -1, -1, -1, -1, 601, -1, -1, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 618, -1, 620, -1, 94, 95, 96, 97, - -1, 99, -1, -1, -1, -1, -1, 633, -1, 635, + 1045, -1, -1, 1048, -1, -1, 1051, -1, 877, 878, + 816, 581, -1, 583, 1121, 1122, -1, 886, 887, 888, + -1, -1, 828, 892, 893, -1, -1, 833, -1, -1, + -1, -1, -1, 603, 16, 17, 977, -1, -1, -1, + -1, -1, -1, 849, 985, -1, -1, -1, -1, -1, + 856, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 867, -1, -1, 870, -1, 48, 49, 50, 51, + 1011, -1, -1, 55, 56, -1, 1121, 1122, -1, -1, + -1, -1, -1, -1, -1, -1, 68, 69, -1, -1, + -1, 897, -1, -1, -1, 901, -1, -1, -1, -1, + -1, -1, -1, -1, 910, -1, -1, -1, 977, 679, + -1, -1, -1, 683, 684, -1, 985, -1, 100, -1, + -1, 691, 692, -1, -1, 1232, 1067, 697, 698, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, 1011, -1, -1, -1, -1, 8, 9, 10, + -1, -1, 13, 14, 15, -1, 17, 727, -1, -1, + 730, -1, -1, -1, 25, 26, 27, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, + 41, 42, 43, 44, -1, -1, -1, 1232, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1067, -1, + -1, 1142, 1008, -1, 1010, 1146, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, - -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, 143, 144, 145, 146, -1, - -1, 149, 678, 151, -1, 153, -1, -1, 684, 685, - -1, 687, -1, -1, -1, 691, 692, -1, -1, -1, - -1, 697, 698, -1, 33, 34, 35, 36, -1, 705, + -1, 1162, -1, -1, -1, 207, -1, -1, 210, 211, + 212, -1, 214, -1, -1, 96, 97, -1, -1, 1045, + -1, -1, 1048, -1, -1, -1, 816, -1, 230, -1, + 232, 233, -1, -1, -1, -1, 1197, 1198, 828, 120, + -1, -1, -1, 833, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1142, -1, -1, -1, 1146, -1, 849, + -1, -1, 143, 144, -1, -1, 856, 148, 149, -1, + 151, -1, 153, 1162, -1, -1, -1, 867, -1, -1, + 870, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1121, 1122, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1197, 1198, + -1, 901, -1, -1, -1, -1, -1, -1, -1, -1, + 910, -1, -1, -1, 326, -1, -1, -1, -1, 331, + -1, 333, 334, 335, 336, 337, -1, -1, 340, 341, + 342, 343, 344, 345, 346, 347, 348, -1, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 49, 50, 51, 52, 720, -1, -1, 56, -1, 58, - 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 77, 745, - 746, -1, 748, 749, -1, -1, -1, -1, -1, -1, - -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, - -1, -1, 101, -1, 770, 104, 105, -1, 107, 108, - -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, + -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, + -1, -1, -1, 94, 95, -1, 1232, -1, -1, -1, + -1, -1, 414, 415, -1, -1, -1, -1, 1008, -1, + 1010, 423, 424, 425, -1, -1, -1, 429, -1, 431, + 432, 433, -1, -1, -1, -1, 127, 439, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, + -1, -1, 454, -1, -1, 1045, -1, 459, 1048, -1, + -1, -1, 153, -1, -1, -1, -1, -1, 470, -1, + -1, 473, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 484, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 132, -1, -1, -1, -1, -1, -1, - 139, -1, -1, 809, -1, -1, -1, -1, -1, -1, - 816, -1, 0, 1, -1, 3, 4, 5, 6, 7, - -1, -1, -1, 11, 12, -1, -1, -1, 16, -1, - 18, 19, 20, 21, 22, 23, 24, 843, -1, -1, - -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, - -1, 39, -1, -1, -1, 861, 862, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, + 502, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, -1, -1, -1, 519, 94, 95, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, 1121, 1122, -1, 8, 9, 10, -1, -1, -1, + 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, + -1, 25, 26, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 37, 38, -1, 40, 41, 42, 43, + 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 591, + -1, -1, -1, -1, 68, -1, -1, -1, -1, 601, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 618, -1, 620, -1, + 94, 95, 96, 97, -1, 99, -1, -1, -1, -1, + -1, 633, -1, 635, -1, -1, -1, -1, -1, -1, + -1, -1, 1232, -1, -1, -1, 120, -1, -1, -1, + -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, + 144, 145, 146, -1, -1, 149, 678, 151, -1, 153, + -1, -1, 684, 685, -1, 687, -1, -1, -1, 691, + 692, -1, -1, -1, -1, 697, 698, -1, 0, -1, + -1, -1, -1, 705, -1, -1, 8, 9, 10, -1, + -1, 13, 14, 15, -1, 17, -1, -1, 720, -1, + -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, + -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, + 42, 43, 44, 745, 746, -1, 748, 749, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 90, 91, 910, -1, -1, -1, -1, -1, - 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, - -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, - 118, -1, 938, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 68, -1, 770, -1, + -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, + -1, -1, 94, 95, 96, 97, -1, 99, 100, -1, + -1, -1, -1, -1, 106, -1, -1, 809, -1, -1, + -1, -1, -1, -1, 816, -1, -1, -1, 120, -1, + -1, 123, -1, -1, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, + -1, 843, 144, 145, 146, -1, -1, 149, 150, 151, + -1, 153, -1, -1, -1, -1, -1, -1, -1, 861, + 862, -1, -1, 0, 1, -1, 3, 4, 5, 6, + 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, + -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, + -1, -1, 39, -1, -1, -1, -1, 909, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, + -1, -1, -1, -1, -1, 937, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, -1, 0, -1, - -1, -1, -1, 151, -1, 153, 8, 9, 10, -1, + -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, + -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, + 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 139, 140, 141, -1, -1, -1, -1, -1, + 1012, 0, -1, -1, 151, -1, 153, -1, -1, 8, + 9, 10, -1, 1025, 13, 14, 15, -1, 17, -1, + -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, + 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, + -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, -1, -1, 86, 87, 68, + -1, -1, -1, -1, 1086, 94, 95, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, + 99, 100, -1, -1, -1, -1, -1, 106, -1, -1, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + -1, 120, -1, -1, 123, -1, -1, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, + 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, - -1, -1, -1, 25, 26, 27, 28, 29, -1, -1, + 44, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, - 42, 43, 44, -1, -1, -1, -1, -1, 1014, -1, + 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, - -1, 1027, 86, 87, -1, -1, 68, -1, -1, -1, + 84, 85, 86, 87, 88, 89, 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, 99, 100, -1, - -1, -1, -1, -1, 106, 129, 130, 131, 132, 133, + -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, 120, -1, - -1, 123, 1088, -1, 126, 127, 128, 129, 130, 131, + -1, 123, 146, -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, - -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, + -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, 44, -1, -1, - 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, + 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, - 95, 96, 97, -1, 99, 100, -1, -1, -1, -1, + 95, 96, 97, -1, -1, 100, -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, -1, -1, -1, 120, -1, -1, 123, 146, - -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, + 137, 138, -1, -1, -1, 120, -1, -1, 123, -1, + -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, - -1, -1, -1, -1, 44, -1, -1, 25, -1, 27, + -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, @@ -3877,41 +4012,41 @@ static const yytype_int16 yycheck[] = 68, -1, -1, -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, - -1, 99, 100, -1, -1, -1, -1, 127, 106, 129, + -1, -1, 100, -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, - -1, -1, 120, -1, -1, 123, -1, -1, 126, 127, + -1, -1, 120, -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, -1, 144, 145, 146, 0, + 138, -1, -1, -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, - -1, -1, -1, -1, 25, 26, 27, 28, 29, -1, + -1, -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 68, -1, -1, - -1, 94, 95, -1, -1, -1, 77, 78, 79, 80, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, + -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, - -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, - -1, -1, -1, -1, 127, 106, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, -1, -1, -1, 120, - -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, + -1, -1, -1, 94, 95, 96, 97, -1, 99, 100, + -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, + -1, -1, 123, -1, -1, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, - -1, -1, 143, 144, 145, 146, 0, -1, 149, 150, + -1, -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, - -1, 25, 26, 27, 28, 29, -1, -1, -1, -1, + -1, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 77, 78, 79, 80, 81, 82, 83, -1, -1, - 86, 87, -1, -1, 68, -1, -1, -1, 94, 95, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, -1, -1, -1, - -1, -1, 106, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, -1, -1, 120, -1, -1, 123, - -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, + -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, + -1, -1, -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, - 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, + 144, 145, 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, @@ -3921,9 +4056,9 @@ static const yytype_int16 yycheck[] = -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, - 97, -1, 99, 100, -1, -1, -1, -1, -1, 106, + 97, -1, -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 120, -1, -1, 123, -1, -1, 126, + -1, -1, -1, 120, -1, -1, 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, 153, -1, 8, 9, @@ -3943,7 +4078,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, 143, 144, 145, 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, -1, -1, -1, -1, - -1, -1, 25, -1, 27, 28, 29, -1, -1, -1, + -1, -1, 25, -1, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3953,26 +4088,26 @@ static const yytype_int16 yycheck[] = -1, 94, 95, 96, 97, -1, -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, - 123, -1, -1, -1, 127, 128, 129, 130, 131, 132, + -1, -1, -1, -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, - -1, 144, 145, 146, 0, -1, 149, 150, 151, -1, - 153, -1, 8, 9, 10, -1, -1, 13, 14, 15, + -1, 144, 145, 146, 0, 148, 149, 150, 151, -1, + 153, -1, 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, 25, - 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, + 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, - 96, 97, -1, -1, 100, -1, -1, -1, -1, -1, - 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, 97, -1, 99, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, - -1, 127, -1, 129, 130, 131, 132, 133, 134, 135, + 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, -1, 143, 144, 145, - 146, 0, 148, 149, 150, 151, -1, 153, -1, 8, - 9, 10, -1, -1, 13, 14, 15, -1, 17, -1, - -1, -1, -1, -1, -1, -1, 25, -1, 27, 28, + 146, 0, -1, 149, -1, 151, -1, 153, -1, 8, + 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, + -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3980,14 +4115,14 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, -1, - -1, 100, -1, -1, -1, -1, -1, 106, -1, -1, + 99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 120, -1, -1, -1, -1, -1, -1, 127, -1, + -1, 120, -1, -1, -1, -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - -1, -1, -1, -1, -1, 144, 145, 146, 0, 148, - 149, 150, 151, -1, 153, -1, 8, 9, 10, -1, + -1, -1, -1, -1, -1, 144, 145, 146, 0, -1, + 149, -1, 151, -1, 153, -1, 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, -1, -1, -1, -1, - -1, -1, -1, 25, 26, -1, -1, -1, -1, -1, + -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3999,125 +4134,10 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, - -1, 143, 144, 145, 146, 0, -1, 149, -1, 151, - -1, 153, -1, 8, 9, 10, -1, -1, -1, 14, - 15, -1, 17, -1, -1, -1, -1, -1, -1, -1, - 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 37, 38, -1, 40, 41, 42, 43, 44, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, - -1, -1, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, -1, -1, -1, -1, 94, - 95, 96, 97, -1, 99, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, - -1, 126, 127, -1, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, -1, -1, -1, -1, -1, 144, - 145, 146, 0, -1, 149, -1, 151, -1, 153, -1, - 8, 9, 10, -1, -1, -1, 14, 15, -1, 17, - -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, - 38, -1, 40, 41, 42, 43, 44, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 68, -1, -1, -1, -1, -1, -1, -1, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, -1, -1, -1, -1, 94, 95, 96, 97, - -1, 99, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 120, -1, -1, -1, -1, -1, 126, 127, - -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, -1, -1, -1, -1, -1, 144, 145, 146, -1, - -1, 149, -1, 151, 1, 153, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, -1, 15, 16, - -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 139, 140, 141, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, - 6, 7, -1, -1, 10, 11, 12, -1, 14, 15, - 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, - 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, - -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, - 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 139, 140, 141, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, - 5, 6, 7, -1, -1, 10, 11, 12, -1, -1, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, - 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, - -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, - 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, - 4, 5, 6, 7, -1, -1, 10, 11, 12, -1, - -1, 15, 16, -1, 18, 19, 20, 21, 22, 23, - 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, - 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, - -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, - -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 139, 140, 141, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, - 3, 4, 5, 6, 7, -1, -1, 10, 11, 12, - -1, -1, 15, 16, -1, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, - 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, - -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, - -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, - -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, 1, -1, 3, 4, 5, 6, - 7, -1, 9, 10, 11, 12, 139, 140, 141, 16, - -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, - 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - 1, -1, 3, 4, 5, 6, 7, -1, -1, -1, - 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, - 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, + -1, -1, 144, 145, 146, -1, -1, 149, -1, 151, + 1, 153, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, -1, -1, 15, 16, -1, 18, 19, 20, + 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, @@ -4129,9 +4149,9 @@ static const yytype_int16 yycheck[] = 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, -1, -1, -1, -1, 149, -1, + 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, -1, -1, - -1, 11, 12, -1, -1, -1, 16, -1, 18, 19, + 10, 11, 12, -1, 14, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, @@ -4144,9 +4164,9 @@ static const yytype_int16 yycheck[] = 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, -1, -1, -1, -1, 149, + 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, -1, - -1, -1, 11, 12, -1, -1, -1, 16, -1, 18, + -1, 10, 11, 12, -1, -1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, @@ -4159,10 +4179,10 @@ static const yytype_int16 yycheck[] = -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 139, 140, 141, -1, -1, 144, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, 7, - -1, -1, -1, 11, 12, -1, -1, -1, 16, -1, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, + -1, -1, 10, 11, 12, -1, -1, 15, 16, -1, + 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, @@ -4174,9 +4194,9 @@ static const yytype_int16 yycheck[] = -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 139, 140, 141, -1, -1, 144, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, 1, 153, 3, 4, 5, 6, - 7, -1, -1, 10, 11, 12, -1, -1, -1, 16, + 7, -1, -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, @@ -4184,13 +4204,86 @@ static const yytype_int16 yycheck[] = 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - 1, -1, 3, 4, 5, 6, 7, -1, -1, -1, - 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, - 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, + -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, + -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, + 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + 1, -1, 3, 4, 5, 6, 7, -1, 9, 10, + 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, + 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, + 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, + -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, + 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, + 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, + 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, + 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, + 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, + -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, + -1, -1, -1, -1, 149, -1, 151, 1, 153, 3, + 4, 5, 6, 7, -1, -1, -1, 11, 12, -1, + -1, -1, 16, -1, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, + 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, + -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, + -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, + 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 139, 140, 141, -1, -1, + -1, -1, -1, -1, -1, 149, -1, 151, 1, 153, + 3, 4, 5, 6, 7, -1, -1, -1, 11, 12, + -1, -1, -1, 16, -1, 18, 19, 20, 21, 22, + 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, + 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, + -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, + 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, + -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, + -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, + 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 139, 140, 141, -1, + -1, 144, -1, -1, -1, -1, -1, -1, 151, 1, + 153, 3, 4, 5, 6, 7, -1, -1, -1, 11, + 12, -1, -1, -1, 16, -1, 18, 19, 20, 21, + 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, + 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, + -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 139, 140, 141, + -1, -1, 144, -1, -1, -1, -1, -1, -1, 151, + 1, 153, 3, 4, 5, 6, 7, -1, -1, 10, + 11, 12, -1, -1, -1, 16, -1, 18, 19, 20, + 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, @@ -4199,36 +4292,36 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, + 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, - -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, - 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, 120, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, - 19, 20, 21, 22, 23, 24, -1, -1, 153, -1, + 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, - -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, - -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, + -1, -1, 101, 102, -1, 104, 105, -1, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, - 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, + 23, 24, -1, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, @@ -4238,22 +4331,22 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, - -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, 18, 19, 20, 21, 22, 23, 24, 151, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, - -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, + -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, + -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, - 21, 22, 23, 24, 151, -1, -1, -1, -1, 30, + 21, 22, 23, 24, -1, -1, 153, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, @@ -4263,24 +4356,22 @@ static const yytype_int16 yycheck[] = 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, + 5, 6, 7, -1, -1, -1, 11, 12, 139, 140, + 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, + 151, -1, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, + -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 151, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - -1, -1, -1, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 75, 76, 77, 78, 79, 80, 81, - 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, - 92, 93, 94, 95, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 107, 108, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, -1, 140, 141, - -1, -1, -1, -1, -1, 147, 148, 3, 4, 5, + -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 151, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, 35, @@ -4295,124 +4386,126 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, -1, - -1, 147, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, -1, 56, -1, -1, -1, -1, + -1, 147, 148, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, - 111, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, -1, -1, -1, -1, -1, 147, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, - 76, 77, 78, 79, 80, 81, 82, 83, -1, -1, - 86, 87, -1, -1, -1, -1, 92, 93, 94, 95, + -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, + -1, -1, 92, 93, 94, 95, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 107, 108, -1, -1, 111, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, + 140, 141, -1, -1, -1, -1, -1, 147, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, -1, 140, 141, -1, -1, -1, -1, - -1, 147, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, -1, -1, -1, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, - 51, 52, 53, -1, -1, 56, -1, -1, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, 111, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, + -1, -1, 147, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, + 50, 51, 52, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 3, 4, 5, -1, 7, 147, -1, -1, 11, - 12, -1, -1, -1, 16, -1, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, + -1, -1, 92, 93, 94, 95, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 107, 108, -1, + -1, 111, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, -1, + 140, 141, -1, -1, -1, -1, -1, 147, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, + 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 3, 4, 5, + -1, 7, 147, -1, -1, 11, 12, -1, -1, -1, + 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, + 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, + 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, 5, -1, 7, -1, -1, 139, 11, 12, - -1, -1, -1, 16, 146, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, - 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, - -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 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, - -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, - -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, - 4, 5, 6, 7, -1, -1, 139, 11, 12, -1, - -1, -1, 16, 146, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, - 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, - -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, - -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, - -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, + -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, + -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, + 7, -1, -1, 139, 11, 12, -1, -1, -1, 16, + 146, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, + -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, + -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, + 57, -1, 59, 60, 61, 62, 63, 64, 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, -1, -1, -1, -1, + -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, + -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, + -1, -1, 139, 11, 12, -1, -1, -1, 16, 146, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, - -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, - -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, + -1, 39, -1, -1, -1, -1, -1, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, 5, 6, 7, -1, -1, -1, 11, + -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, 45, 46, -1, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + 102, -1, 104, 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, + 6, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, - 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, - 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 36, -1, -1, 39, -1, -1, -1, -1, -1, 45, + 46, -1, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, @@ -4437,7 +4530,7 @@ static const yytype_int16 yycheck[] = -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, 107, 108, -1, 110, 111, 112, 113, + 104, 105, -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, @@ -4449,8 +4542,8 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, - 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 98, -1, -1, 101, 102, -1, 104, 105, -1, 107, + 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, @@ -4462,7 +4555,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, 108, -1, 110, 111, + 102, -1, 104, 105, -1, -1, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, @@ -4475,19 +4568,19 @@ static const yytype_int16 yycheck[] = 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, - -1, -1, 108, -1, 110, 111, 112, 113, 114, 115, + -1, 107, 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, + -1, 101, 102, -1, 104, 105, -1, -1, 108, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, @@ -4550,7 +4643,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, + -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, 139, @@ -4585,10 +4678,47 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, + -1, 7, -1, -1, -1, 11, 12, 139, 140, 141, + 16, -1, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, + 36, -1, -1, 39, -1, -1, -1, -1, -1, -1, + 46, -1, -1, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 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, 98, -1, -1, 101, - 102, -1, 104, 105, -1, 107, -1, -1, 110, 111, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, + -1, 107, -1, -1, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, + 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, + -1, -1, 16, 139, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, -1, -1, 30, 31, 32, 33, + 34, 35, 36, -1, -1, 39, -1, -1, -1, -1, + -1, -1, 46, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 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, -1, + -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, + 104, 105, -1, 107, -1, -1, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, + -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, + 12, -1, -1, -1, 16, 139, 18, 19, 20, 21, + 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, + 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, + -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 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, -1, 94, -1, -1, -1, 98, -1, -1, 101, + 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, 139, 18, 19, @@ -4600,7 +4730,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, 107, -1, -1, + -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, 12, -1, -1, -1, 16, 139, @@ -4611,7 +4741,7 @@ static const yytype_int16 yycheck[] = -1, 59, 60, 61, 62, 63, 64, 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, -1, 94, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, 3, 4, 5, @@ -4637,197 +4767,177 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, -1, 101, 102, -1, - 104, 105, -1, -1, -1, -1, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, 3, 4, 5, -1, 7, -1, -1, -1, 11, - 12, -1, -1, -1, 16, 139, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, 30, 31, - 32, 33, 34, 35, 36, -1, -1, 39, -1, -1, - -1, -1, -1, -1, 46, -1, -1, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 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, -1, -1, -1, -1, -1, 98, -1, -1, 101, - 102, -1, 104, 105, -1, -1, -1, -1, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, -1, -1, - -1, -1, -1, 3, 4, 5, -1, 7, -1, -1, - -1, 11, 12, -1, -1, -1, 16, 139, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, - 30, 31, 32, 33, 34, 35, 36, -1, -1, 39, - -1, -1, -1, -1, -1, -1, 46, -1, -1, 49, - 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, 65, 33, 34, 35, 36, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 49, 50, 51, 52, -1, -1, -1, 56, - -1, -1, 59, 60, 61, 62, 63, -1, 98, -1, - -1, 101, 102, -1, 104, 105, -1, -1, -1, -1, - 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, - -1, -1, -1, 90, 91, -1, -1, -1, -1, -1, - -1, 98, -1, -1, 101, -1, -1, 104, 105, 139, - 107, -1, -1, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 33, 34, 35, 36, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 132, -1, -1, 49, 50, - 51, 52, 139, -1, -1, 56, -1, -1, 59, 60, - 61, 62, 63, -1, -1, 33, 34, 35, 36, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 49, 50, 51, 52, -1, -1, -1, 56, 90, - 91, 59, 60, 61, 62, 63, -1, 98, -1, -1, - 101, -1, -1, 104, 105, -1, 107, -1, -1, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, -1, - -1, -1, 90, 91, -1, -1, -1, -1, -1, -1, - 98, 132, -1, 101, -1, -1, 104, 105, 139, -1, - -1, -1, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 52, 53, -1, -1, 56, -1, -1, -1, -1, - -1, -1, -1, -1, 132, -1, -1, -1, -1, -1, - -1, 139, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 104, 105, 33, 34, 35, 36, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, -1, -1, 49, 50, + 51, 52, -1, -1, -1, 56, -1, 58, 59, 60, + 61, 62, 63, -1, -1, 139, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 77, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, + 91, -1, -1, -1, -1, -1, -1, 98, -1, -1, + 101, -1, -1, 104, 105, -1, 107, 108, -1, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 33, 34, + 35, 36, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 132, -1, -1, 49, 50, 51, 52, 139, -1, + -1, 56, -1, -1, 59, 60, 61, 62, 63, -1, + -1, 33, 34, 35, 36, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 49, 50, 51, + 52, -1, -1, -1, 56, 90, 91, 59, 60, 61, + 62, 63, -1, 98, -1, -1, 101, -1, -1, 104, + 105, -1, 107, -1, -1, 110, 111, 112, 113, 114, + 115, 116, 117, 118, -1, -1, -1, -1, 90, 91, + -1, -1, -1, -1, -1, -1, 98, 132, -1, 101, + -1, -1, 104, 105, 139, -1, -1, -1, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 52, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + 132, -1, -1, -1, -1, -1, -1, 139, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, 52, 53, -1, -1, 56, 147, 148, -1, -1, + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, 52, 53, -1, + -1, 56, 147, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 107, 108, -1, -1, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, 92, 93, 94, + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, -1, 140, - 141, -1, -1, -1, -1, -1, 147 + -1, -1, -1, -1, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, -1, 140, 141, -1, -1, -1, + -1, -1, 147 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = +static const yytype_int16 yystos[] = { 0, 155, 156, 0, 1, 3, 4, 5, 6, 7, 11, 12, 16, 18, 19, 20, 21, 22, 23, 24, @@ -4841,7 +4951,7 @@ static const yytype_uint16 yystos[] = 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 252, 279, 280, 333, 334, 335, 336, 337, 338, 339, 342, 344, 345, 359, 360, 362, 363, 364, 365, 366, - 367, 368, 369, 405, 419, 159, 3, 4, 5, 6, + 367, 368, 369, 405, 418, 159, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, @@ -4855,28 +4965,28 @@ static const yytype_uint16 yystos[] = 148, 211, 212, 148, 207, 211, 148, 153, 412, 54, 195, 412, 143, 160, 143, 21, 22, 31, 32, 182, 200, 233, 252, 200, 200, 200, 56, 1, 47, 101, - 163, 164, 165, 167, 185, 186, 419, 167, 220, 205, - 215, 403, 419, 204, 402, 403, 419, 46, 98, 139, + 163, 164, 165, 167, 185, 186, 418, 167, 220, 205, + 215, 403, 418, 204, 402, 403, 418, 46, 98, 139, 146, 190, 218, 233, 365, 366, 369, 223, 54, 55, 57, 194, 348, 361, 348, 349, 350, 152, 152, 152, - 152, 364, 179, 200, 200, 151, 153, 411, 417, 418, + 152, 364, 179, 200, 200, 151, 153, 411, 416, 417, 40, 41, 42, 43, 44, 37, 38, 26, 143, 207, 211, 244, 281, 28, 245, 278, 126, 146, 101, 107, 187, 126, 25, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 94, 95, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 202, 202, 68, 96, 97, 145, 409, 219, 171, 175, 175, - 176, 177, 176, 175, 411, 418, 98, 184, 191, 233, + 176, 177, 176, 175, 411, 417, 98, 184, 191, 233, 257, 365, 366, 369, 52, 56, 94, 98, 192, 193, 233, 365, 366, 369, 193, 33, 34, 35, 36, 49, 50, 51, 52, 56, 148, 194, 367, 400, 210, 97, 409, 410, 281, 336, 99, 99, 146, 204, 56, 204, - 204, 204, 348, 126, 100, 146, 214, 419, 97, 145, + 204, 204, 348, 126, 100, 146, 214, 418, 97, 145, 409, 99, 99, 146, 214, 210, 412, 413, 210, 91, - 209, 210, 215, 377, 403, 419, 171, 413, 171, 54, + 209, 210, 215, 377, 403, 418, 171, 413, 171, 54, 64, 65, 168, 148, 201, 157, 163, 97, 409, 99, - 167, 166, 185, 149, 411, 418, 413, 221, 413, 150, - 146, 153, 416, 146, 416, 144, 416, 412, 56, 364, + 167, 166, 185, 149, 411, 417, 413, 221, 413, 150, + 146, 153, 415, 146, 415, 144, 415, 412, 56, 364, 187, 189, 146, 97, 145, 409, 270, 271, 66, 119, 121, 122, 351, 119, 119, 351, 67, 351, 340, 346, 343, 347, 77, 151, 159, 175, 175, 175, 175, 167, @@ -4887,7 +4997,7 @@ static const yytype_uint16 yystos[] = 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 52, 53, 56, 198, 207, 406, 407, 209, 52, 53, 56, 198, 207, 406, 161, 163, - 13, 253, 417, 253, 163, 175, 163, 411, 225, 56, + 13, 253, 416, 253, 163, 175, 163, 411, 225, 56, 97, 145, 409, 25, 171, 52, 56, 192, 130, 370, 97, 145, 409, 228, 401, 229, 68, 97, 408, 52, 56, 406, 170, 200, 206, 170, 206, 197, 124, 204, @@ -4899,65 +5009,65 @@ static const yytype_uint16 yystos[] = 144, 284, 282, 10, 251, 288, 251, 204, 146, 44, 413, 189, 146, 44, 126, 44, 97, 145, 409, 173, 412, 99, 99, 207, 211, 412, 414, 99, 99, 207, - 208, 211, 419, 251, 8, 246, 329, 419, 163, 13, - 163, 251, 27, 254, 417, 251, 25, 224, 293, 17, + 208, 211, 418, 251, 8, 246, 329, 418, 163, 13, + 163, 251, 27, 254, 416, 251, 25, 224, 293, 17, 248, 291, 52, 56, 209, 52, 56, 176, 227, 371, 226, 52, 56, 192, 209, 161, 171, 230, 231, 208, 211, 195, 204, 204, 214, 99, 99, 414, 99, 99, - 403, 171, 416, 187, 414, 273, 354, 54, 55, 57, + 403, 171, 415, 187, 414, 273, 354, 54, 55, 57, 358, 369, 152, 351, 152, 152, 152, 285, 144, 289, 107, 204, 167, 189, 167, 200, 52, 56, 209, 52, 56, 52, 56, 90, 91, 98, 101, 104, 105, 110, 132, 303, 304, 305, 308, 323, 324, 326, 327, 328, 333, 334, 337, 338, 339, 342, 344, 345, 366, 128, 170, 206, 170, 206, 181, 150, 99, 170, 206, 170, - 206, 181, 204, 217, 330, 419, 9, 15, 247, 249, - 332, 419, 14, 249, 250, 255, 256, 419, 256, 178, - 294, 291, 251, 107, 204, 290, 251, 414, 163, 417, + 206, 181, 204, 217, 330, 418, 9, 15, 247, 249, + 332, 418, 14, 249, 250, 255, 256, 418, 256, 178, + 294, 291, 251, 107, 204, 290, 251, 414, 163, 416, 175, 161, 414, 251, 413, 148, 372, 373, 194, 281, - 278, 99, 146, 413, 274, 355, 131, 265, 266, 419, + 278, 99, 146, 413, 274, 355, 131, 265, 266, 418, 265, 204, 414, 324, 324, 56, 192, 311, 309, 414, - 310, 412, 415, 325, 52, 100, 174, 131, 88, 89, - 97, 145, 148, 306, 307, 200, 170, 206, 100, 331, - 419, 163, 162, 163, 175, 251, 251, 295, 251, 204, - 146, 253, 251, 161, 417, 251, 52, 54, 55, 56, - 57, 58, 77, 91, 101, 107, 108, 109, 133, 136, - 374, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 387, 388, 389, 390, 391, 394, 395, 396, 397, 398, - 161, 376, 232, 148, 276, 376, 356, 262, 264, 267, - 380, 382, 383, 385, 386, 389, 390, 392, 393, 396, - 398, 412, 163, 161, 303, 107, 303, 312, 313, 314, - 316, 58, 112, 317, 318, 319, 320, 321, 322, 388, - 144, 270, 326, 308, 324, 324, 192, 414, 413, 112, - 312, 317, 312, 317, 98, 191, 233, 365, 366, 369, - 253, 163, 253, 296, 107, 204, 163, 251, 101, 107, - 258, 259, 260, 261, 379, 413, 413, 126, 146, 375, - 204, 146, 399, 419, 34, 52, 146, 399, 399, 146, - 375, 52, 146, 375, 52, 251, 417, 372, 376, 275, - 357, 267, 131, 126, 146, 263, 98, 233, 146, 399, - 399, 399, 146, 263, 146, 263, 151, 413, 52, 146, - 414, 107, 303, 316, 146, 348, 415, 146, 303, 34, - 52, 348, 413, 413, 414, 414, 56, 97, 145, 409, - 163, 332, 163, 301, 302, 303, 314, 317, 204, 256, - 291, 292, 260, 379, 146, 413, 146, 204, 374, 381, - 394, 396, 384, 388, 390, 398, 382, 391, 396, 380, - 382, 161, 267, 29, 123, 277, 163, 131, 233, 262, - 393, 396, 56, 97, 385, 390, 382, 392, 396, 382, - 52, 268, 269, 378, 146, 315, 316, 52, 146, 146, - 124, 319, 321, 322, 52, 56, 209, 52, 56, 329, - 255, 253, 40, 41, 146, 413, 258, 261, 259, 146, - 375, 146, 375, 399, 146, 375, 146, 375, 375, 251, - 149, 161, 163, 120, 146, 263, 146, 263, 52, 56, - 399, 146, 263, 146, 263, 263, 146, 412, 315, 146, - 146, 315, 414, 297, 175, 175, 312, 146, 146, 382, - 396, 382, 382, 251, 144, 382, 396, 382, 382, 269, - 316, 315, 298, 259, 375, 146, 375, 375, 375, 263, - 146, 263, 263, 263, 299, 382, 382, 163, 375, 263, - 256, 293, 300 + 144, 310, 325, 52, 100, 174, 131, 88, 89, 97, + 145, 148, 306, 307, 200, 170, 206, 100, 331, 418, + 163, 162, 163, 175, 251, 251, 295, 251, 204, 146, + 253, 251, 161, 416, 251, 52, 54, 55, 56, 57, + 58, 77, 91, 101, 107, 108, 109, 133, 136, 374, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 387, + 388, 389, 390, 391, 394, 395, 396, 397, 398, 161, + 376, 232, 148, 276, 376, 356, 262, 264, 267, 380, + 382, 383, 385, 386, 389, 390, 392, 393, 396, 398, + 412, 163, 161, 303, 107, 303, 312, 313, 314, 316, + 58, 112, 317, 318, 319, 320, 321, 322, 388, 270, + 326, 308, 324, 324, 192, 414, 413, 112, 312, 317, + 312, 317, 98, 191, 233, 365, 366, 369, 253, 163, + 253, 296, 107, 204, 163, 251, 101, 107, 258, 259, + 260, 261, 379, 413, 413, 126, 146, 375, 204, 146, + 399, 418, 34, 52, 146, 399, 399, 146, 375, 52, + 146, 375, 52, 251, 416, 372, 376, 275, 357, 267, + 131, 126, 146, 263, 98, 233, 146, 399, 399, 399, + 146, 263, 146, 263, 151, 413, 52, 146, 414, 107, + 303, 316, 146, 348, 144, 146, 303, 34, 52, 348, + 413, 413, 414, 414, 56, 97, 145, 409, 163, 332, + 163, 301, 302, 303, 314, 317, 204, 256, 291, 292, + 260, 379, 146, 413, 146, 204, 374, 381, 394, 396, + 384, 388, 390, 398, 382, 391, 396, 380, 382, 161, + 267, 29, 123, 277, 163, 131, 233, 262, 393, 396, + 56, 97, 385, 390, 382, 392, 396, 382, 52, 268, + 269, 378, 146, 315, 316, 52, 146, 146, 124, 319, + 321, 322, 52, 56, 209, 52, 56, 329, 255, 253, + 40, 41, 146, 413, 258, 261, 259, 146, 375, 146, + 375, 399, 146, 375, 146, 375, 375, 251, 149, 161, + 163, 120, 146, 263, 146, 263, 52, 56, 399, 146, + 263, 146, 263, 263, 146, 412, 315, 146, 146, 315, + 414, 297, 175, 175, 312, 146, 146, 382, 396, 382, + 382, 251, 144, 382, 396, 382, 382, 269, 316, 315, + 298, 259, 375, 146, 375, 375, 375, 263, 146, 263, + 263, 263, 299, 382, 382, 163, 375, 263, 256, 293, + 300 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = +static const yytype_int16 yyr1[] = { 0, 154, 156, 155, 157, 158, 158, 158, 158, 159, 159, 160, 162, 161, 161, 163, 164, 164, 164, 164, @@ -5011,34 +5121,34 @@ static const yytype_uint16 yyr1[] = 306, 307, 308, 308, 308, 308, 308, 308, 308, 309, 308, 308, 310, 308, 308, 311, 308, 312, 312, 312, 312, 312, 312, 312, 312, 313, 313, 314, 314, 314, - 314, 315, 315, 316, 317, 317, 317, 317, 317, 317, - 318, 318, 319, 319, 320, 320, 321, 321, 322, 323, - 323, 323, 323, 323, 323, 323, 323, 323, 323, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 325, 324, - 326, 327, 328, 328, 328, 329, 329, 330, 330, 330, - 331, 331, 332, 332, 333, 333, 334, 335, 335, 335, - 336, 337, 338, 339, 340, 340, 341, 341, 342, 343, - 343, 344, 345, 346, 346, 347, 347, 348, 348, 349, - 349, 350, 350, 351, 352, 351, 353, 354, 355, 356, - 357, 351, 358, 358, 358, 358, 359, 359, 360, 361, - 361, 361, 361, 362, 363, 363, 364, 364, 364, 364, - 365, 365, 365, 365, 365, 366, 366, 366, 366, 366, - 366, 366, 367, 367, 368, 368, 369, 369, 371, 370, - 370, 372, 372, 373, 372, 374, 374, 374, 374, 374, - 375, 375, 376, 376, 376, 376, 376, 376, 376, 376, - 376, 376, 376, 376, 376, 376, 376, 377, 378, 378, - 378, 378, 379, 379, 380, 381, 381, 382, 382, 383, - 384, 384, 385, 385, 386, 386, 387, 387, 388, 388, - 389, 390, 390, 391, 392, 393, 393, 394, 394, 395, - 395, 396, 396, 397, 397, 398, 399, 399, 400, 401, - 400, 402, 402, 403, 403, 404, 404, 404, 404, 405, - 405, 405, 406, 406, 406, 406, 407, 407, 407, 408, - 408, 409, 409, 410, 410, 411, 411, 412, 412, 413, - 414, 415, 416, 416, 416, 417, 417, 418, 418, 419 + 314, 315, 315, 316, 317, 317, 317, 317, 317, 318, + 318, 319, 319, 320, 320, 321, 321, 322, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 325, 324, 326, + 327, 328, 328, 328, 329, 329, 330, 330, 330, 331, + 331, 332, 332, 333, 333, 334, 335, 335, 335, 336, + 337, 338, 339, 340, 340, 341, 341, 342, 343, 343, + 344, 345, 346, 346, 347, 347, 348, 348, 349, 349, + 350, 350, 351, 352, 351, 353, 354, 355, 356, 357, + 351, 358, 358, 358, 358, 359, 359, 360, 361, 361, + 361, 361, 362, 363, 363, 364, 364, 364, 364, 365, + 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, + 366, 367, 367, 368, 368, 369, 369, 371, 370, 370, + 372, 372, 373, 372, 374, 374, 374, 374, 374, 375, + 375, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 376, 376, 376, 376, 376, 376, 377, 378, 378, 378, + 378, 379, 379, 380, 381, 381, 382, 382, 383, 384, + 384, 385, 385, 386, 386, 387, 387, 388, 388, 389, + 390, 390, 391, 392, 393, 393, 394, 394, 395, 395, + 396, 396, 397, 397, 398, 399, 399, 400, 401, 400, + 402, 402, 403, 403, 404, 404, 404, 404, 405, 405, + 405, 406, 406, 406, 406, 407, 407, 407, 408, 408, + 409, 409, 410, 410, 411, 411, 412, 412, 413, 414, + 415, 415, 415, 416, 416, 417, 417, 418 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +static const yytype_int8 yyr2[] = { 0, 2, 0, 2, 2, 1, 1, 3, 2, 1, 2, 3, 0, 6, 3, 2, 1, 1, 3, 2, @@ -5092,30 +5202,30 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 4, 4, 3, 4, 4, 3, 0, 4, 2, 0, 4, 2, 0, 4, 1, 1, 2, 3, 5, 2, 4, 1, 2, 3, 2, 4, 1, - 3, 1, 3, 1, 3, 1, 2, 1, 3, 1, - 1, 3, 2, 1, 1, 3, 2, 1, 2, 1, - 3, 3, 2, 2, 1, 1, 1, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, - 1, 2, 2, 3, 1, 6, 1, 1, 1, 1, - 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, - 3, 3, 3, 4, 0, 3, 1, 2, 4, 0, - 3, 4, 4, 0, 3, 0, 3, 0, 2, 0, - 2, 0, 2, 1, 0, 3, 0, 0, 0, 0, - 0, 8, 1, 1, 1, 1, 1, 1, 2, 1, - 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, + 3, 1, 3, 1, 3, 1, 1, 3, 1, 1, + 3, 2, 1, 1, 3, 2, 1, 2, 1, 3, + 3, 2, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, + 2, 2, 3, 1, 6, 1, 1, 1, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, + 3, 3, 4, 0, 3, 1, 2, 4, 0, 3, + 4, 4, 0, 3, 0, 3, 0, 2, 0, 2, + 0, 2, 1, 0, 3, 0, 0, 0, 0, 0, + 8, 1, 1, 1, 1, 1, 1, 2, 1, 1, + 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, - 0, 3, 3, 0, 3, 4, 2, 2, 2, 1, - 2, 0, 6, 8, 4, 6, 4, 6, 2, 4, - 6, 2, 4, 2, 4, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, - 2, 1, 2, 1, 1, 3, 1, 3, 1, 1, - 2, 2, 1, 3, 3, 1, 3, 1, 3, 1, - 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, - 4, 1, 2, 1, 3, 3, 2, 4, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, + 3, 3, 0, 3, 4, 2, 2, 2, 1, 2, + 0, 6, 8, 4, 6, 4, 6, 2, 4, 6, + 2, 4, 2, 4, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 3, 1, 2, + 1, 2, 1, 1, 3, 1, 3, 1, 1, 2, + 2, 1, 3, 3, 1, 3, 1, 3, 1, 1, + 2, 1, 1, 1, 2, 2, 1, 1, 0, 4, + 1, 2, 1, 3, 3, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 0, 1, 2, - 2, 2, 0, 1, 1, 1, 1, 1, 2, 0 + 1, 1, 1, 1, 0, 1, 0, 1, 2, 2, + 0, 1, 1, 1, 1, 1, 2, 0 }; @@ -5131,22 +5241,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, p, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, p, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -5205,10 +5315,10 @@ do { \ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED -static unsigned +static int yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { - unsigned res = 0; + int res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { @@ -5251,40 +5361,42 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yylocationp); YYUSE (p); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_params *p) { YYFPRINTF (p, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - YY_LOCATION_PRINT (yyoutput, *yylocationp); + YY_LOCATION_PRINT (yyo, *yylocationp); YYFPRINTF (p, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, p); + yy_symbol_value_print (yyo, yytype, yyvaluep, yylocationp, p); YYFPRINTF (p, ")"); } @@ -5294,7 +5406,7 @@ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYL `------------------------------------------------------------------*/ static void -ruby_parser_yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop, struct parser_params *p) +ruby_parser_yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop, struct parser_params *p) #define yy_stack_print(b, t) ruby_parser_yy_stack_print(b, t, p) { YYFPRINTF (p, "Stack now"); @@ -5318,12 +5430,12 @@ do { \ `------------------------------------------------*/ static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct parser_params *p) +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct parser_params *p) { - unsigned long int yylno = yyrline[yyrule]; + int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - YYFPRINTF (p, "Reducing stack by rule %d (line %lu):\n", + YYFPRINTF (p, "Reducing stack by rule %d (line %d):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) @@ -5331,7 +5443,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule YYFPRINTF (p, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , &(yylsp[(yyi + 1) - (yynrhs)]) , p); YYFPRINTF (p, "\n"); } @@ -5377,13 +5489,13 @@ int yydebug; # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen +# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) # else /* Return the length of YYSTR. */ -static YYSIZE_T +static YYPTRDIFF_T yystrlen (const char *yystr) { - YYSIZE_T yylen; + YYPTRDIFF_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; @@ -5419,12 +5531,12 @@ yystpcpy (char *yydest, const char *yysrc) backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ -static YYSIZE_T +static YYPTRDIFF_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { - YYSIZE_T yyn = 0; + YYPTRDIFF_T yyn = 0; char const *yyp = yystr; for (;;) @@ -5437,7 +5549,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -5452,10 +5567,10 @@ yytnamerr (char *yyres, const char *yystr) do_not_strip_quotes: ; } - if (! yyres) + if (yyres) + return yystpcpy (yyres, yystr) - yyres; + else return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; } # endif @@ -5468,19 +5583,19 @@ yytnamerr (char *yyres, const char *yystr) *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int -yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +yysyntax_error (struct parser_params *p, YYPTRDIFF_T *yymsg_alloc, char **yymsg, + yy_state_t *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ + /* Arguments of yyformat: reported tokens (one for the "unexpected", + one per "expected"). */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ + /* Actual size of YYARG. */ int yycount = 0; + /* Cumulated lengths of YYARG. */ + YYPTRDIFF_T yysize = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then @@ -5508,6 +5623,8 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; + YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + yysize = yysize0; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { @@ -5532,11 +5649,12 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } yyarg[yycount++] = yytname[yyx]; { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + YYPTRDIFF_T yysize1 + = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -5548,6 +5666,7 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -5558,10 +5677,13 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + /* Don't count the "%s"s in the final size, but reserve room for + the terminator. */ + YYPTRDIFF_T yysize1 = yysize + (yystrlen (yyformat) - 2 * yycount) + 1; + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -5587,8 +5709,8 @@ yysyntax_error (struct parser_params *p, YYSIZE_T *yymsg_alloc, char **yymsg, } else { - yyp++; - yyformat++; + ++yyp; + ++yyformat; } } return 0; @@ -5645,7 +5767,7 @@ YYLTYPE yylloc = yyloc_default; /* Number of syntax errors so far. */ int yynerrs; - int yystate; + yy_state_fast_t yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -5658,9 +5780,9 @@ YYLTYPE yylloc = yyloc_default; to reallocate them elsewhere. */ /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss; + yy_state_t *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -5675,7 +5797,7 @@ YYLTYPE yylloc = yyloc_default; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; - YYSIZE_T yystacksize; + YYPTRDIFF_T yystacksize; int yyn; int yyresult; @@ -5690,7 +5812,7 @@ YYLTYPE yylloc = yyloc_default; /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; + YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) @@ -5712,38 +5834,51 @@ YYLTYPE yylloc = yyloc_default; yychar = YYEMPTY; /* Cause a token to be read. */ /* User initialization code. */ -#line 974 "parse.y" /* yacc.c:1429 */ +#line 992 "parse.y" { RUBY_SET_YYLLOC_OF_NONE(yylloc); } -#line 5716 "parse.c" /* yacc.c:1429 */ +#line 5838 "parse.c" + yylsp[0] = yylloc; goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((p, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYPTRDIFF_T yysize = yyssp - yyss + 1; -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ + yy_state_t *yyss1 = yyss; YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the @@ -5751,19 +5886,15 @@ YYLTYPE yylloc = yyloc_default; conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yyls1, yysize * YYSIZEOF (*yylsp), &yystacksize); - - yyls = yyls1; yyss = yyss1; yyvs = yyvs1; + yyls = yyls1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -5772,44 +5903,45 @@ YYLTYPE yylloc = yyloc_default; yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; + yy_state_t *yyss1 = yyss; union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; - YYDPRINTF ((p, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((p, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) YYABORT; } - - YYDPRINTF ((p, "Entering state %d\n", yystate)); +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ if (yystate == YYFINAL) YYACCEPT; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -5859,15 +5991,14 @@ YYLTYPE yylloc = yyloc_default; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; + + /* Discard the shifted token. */ + yychar = YYEMPTY; goto yynewstate; @@ -5882,7 +6013,7 @@ YYLTYPE yylloc = yyloc_default; /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -5898,23 +6029,24 @@ YYLTYPE yylloc = yyloc_default; GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ + /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 1176 "parse.y" /* yacc.c:1646 */ - { + case 2: +#line 1194 "parse.y" + { SET_LEX_STATE(EXPR_BEG); local_push(p, ifndef_ripper(1)+0); } -#line 5908 "parse.c" /* yacc.c:1646 */ +#line 6040 "parse.c" break; case 3: -#line 1181 "parse.y" /* yacc.c:1646 */ - { +#line 1199 "parse.y" + { /*%%%*/ if ((yyvsp[0].node) && !compile_for_eval) { NODE *node = (yyvsp[0].node); @@ -5933,69 +6065,69 @@ YYLTYPE yylloc = yyloc_default; /*% ripper[final]: program!($2) %*/ local_pop(p); } -#line 5932 "parse.c" /* yacc.c:1646 */ +#line 6064 "parse.c" break; case 4: -#line 1203 "parse.y" /* yacc.c:1646 */ - { +#line 1221 "parse.y" + { (yyval.node) = void_stmts(p, (yyvsp[-1].node)); } -#line 5940 "parse.c" /* yacc.c:1646 */ +#line 6072 "parse.c" break; case 5: -#line 1209 "parse.y" /* yacc.c:1646 */ - { +#line 1227 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/ } -#line 5951 "parse.c" /* yacc.c:1646 */ +#line 6083 "parse.c" break; case 6: -#line 1216 "parse.y" /* yacc.c:1646 */ - { +#line 1234 "parse.y" + { /*%%%*/ (yyval.node) = newline_node((yyvsp[0].node)); /*% %*/ /*% ripper: stmts_add!(stmts_new!, $1) %*/ } -#line 5962 "parse.c" /* yacc.c:1646 */ +#line 6094 "parse.c" break; case 7: -#line 1223 "parse.y" /* yacc.c:1646 */ - { +#line 1241 "parse.y" + { /*%%%*/ (yyval.node) = block_append(p, (yyvsp[-2].node), newline_node((yyvsp[0].node))); /*% %*/ /*% ripper: stmts_add!($1, $3) %*/ } -#line 5973 "parse.c" /* yacc.c:1646 */ +#line 6105 "parse.c" break; case 8: -#line 1230 "parse.y" /* yacc.c:1646 */ - { +#line 1248 "parse.y" + { (yyval.node) = remove_begin((yyvsp[0].node)); } -#line 5981 "parse.c" /* yacc.c:1646 */ +#line 6113 "parse.c" break; case 10: -#line 1237 "parse.y" /* yacc.c:1646 */ - { +#line 1255 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 5989 "parse.c" /* yacc.c:1646 */ +#line 6121 "parse.c" break; case 11: -#line 1243 "parse.y" /* yacc.c:1646 */ - { +#line 1261 "parse.y" + { /*%%%*/ p->eval_tree_begin = block_append(p, p->eval_tree_begin, NEW_BEGIN((yyvsp[-1].node), &(yyloc))); @@ -6003,141 +6135,141 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: BEGIN!($2) %*/ } -#line 6002 "parse.c" /* yacc.c:1646 */ +#line 6134 "parse.c" break; case 12: -#line 1255 "parse.y" /* yacc.c:1646 */ - {if (!(yyvsp[-1].node)) {yyerror1(&(yylsp[0]), "else without rescue is useless");}} -#line 6008 "parse.c" /* yacc.c:1646 */ +#line 1273 "parse.y" + {if (!(yyvsp[-1].node)) {yyerror1(&(yylsp[0]), "else without rescue is useless");}} +#line 6140 "parse.c" break; case 13: -#line 1258 "parse.y" /* yacc.c:1646 */ - { +#line 1276 "parse.y" + { /*%%%*/ (yyval.node) = new_bodystmt(p, (yyvsp[-5].node), (yyvsp[-4].node), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: bodystmt!(escape_Qundef($1), escape_Qundef($2), escape_Qundef($5), escape_Qundef($6)) %*/ } -#line 6019 "parse.c" /* yacc.c:1646 */ +#line 6151 "parse.c" break; case 14: -#line 1267 "parse.y" /* yacc.c:1646 */ - { +#line 1285 "parse.y" + { /*%%%*/ (yyval.node) = new_bodystmt(p, (yyvsp[-2].node), (yyvsp[-1].node), 0, (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: bodystmt!(escape_Qundef($1), escape_Qundef($2), Qnil, escape_Qundef($3)) %*/ } -#line 6030 "parse.c" /* yacc.c:1646 */ +#line 6162 "parse.c" break; case 15: -#line 1276 "parse.y" /* yacc.c:1646 */ - { +#line 1294 "parse.y" + { (yyval.node) = void_stmts(p, (yyvsp[-1].node)); } -#line 6038 "parse.c" /* yacc.c:1646 */ +#line 6170 "parse.c" break; case 16: -#line 1282 "parse.y" /* yacc.c:1646 */ - { +#line 1300 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/ } -#line 6049 "parse.c" /* yacc.c:1646 */ +#line 6181 "parse.c" break; case 17: -#line 1289 "parse.y" /* yacc.c:1646 */ - { +#line 1307 "parse.y" + { /*%%%*/ (yyval.node) = newline_node((yyvsp[0].node)); /*% %*/ /*% ripper: stmts_add!(stmts_new!, $1) %*/ } -#line 6060 "parse.c" /* yacc.c:1646 */ +#line 6192 "parse.c" break; case 18: -#line 1296 "parse.y" /* yacc.c:1646 */ - { +#line 1314 "parse.y" + { /*%%%*/ (yyval.node) = block_append(p, (yyvsp[-2].node), newline_node((yyvsp[0].node))); /*% %*/ /*% ripper: stmts_add!($1, $3) %*/ } -#line 6071 "parse.c" /* yacc.c:1646 */ +#line 6203 "parse.c" break; case 19: -#line 1303 "parse.y" /* yacc.c:1646 */ - { +#line 1321 "parse.y" + { (yyval.node) = remove_begin((yyvsp[0].node)); } -#line 6079 "parse.c" /* yacc.c:1646 */ +#line 6211 "parse.c" break; case 20: -#line 1309 "parse.y" /* yacc.c:1646 */ - { +#line 1327 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 6087 "parse.c" /* yacc.c:1646 */ +#line 6219 "parse.c" break; case 21: -#line 1313 "parse.y" /* yacc.c:1646 */ - { +#line 1331 "parse.y" + { yyerror1(&(yylsp[0]), "BEGIN is permitted only at toplevel"); } -#line 6095 "parse.c" /* yacc.c:1646 */ +#line 6227 "parse.c" break; case 22: -#line 1317 "parse.y" /* yacc.c:1646 */ - { +#line 1335 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 6103 "parse.c" /* yacc.c:1646 */ +#line 6235 "parse.c" break; case 23: -#line 1322 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} -#line 6109 "parse.c" /* yacc.c:1646 */ +#line 1340 "parse.y" + {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} +#line 6241 "parse.c" break; case 24: -#line 1323 "parse.y" /* yacc.c:1646 */ - { +#line 1341 "parse.y" + { /*%%%*/ (yyval.node) = NEW_ALIAS((yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: alias!($2, $4) %*/ } -#line 6120 "parse.c" /* yacc.c:1646 */ +#line 6252 "parse.c" break; case 25: -#line 1330 "parse.y" /* yacc.c:1646 */ - { +#line 1348 "parse.y" + { /*%%%*/ (yyval.node) = NEW_VALIAS((yyvsp[-1].id), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: var_alias!($2, $3) %*/ } -#line 6131 "parse.c" /* yacc.c:1646 */ +#line 6263 "parse.c" break; case 26: -#line 1337 "parse.y" /* yacc.c:1646 */ - { +#line 1355 "parse.y" + { /*%%%*/ char buf[2]; buf[0] = '$'; @@ -6146,59 +6278,59 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: var_alias!($2, $3) %*/ } -#line 6145 "parse.c" /* yacc.c:1646 */ +#line 6277 "parse.c" break; case 27: -#line 1347 "parse.y" /* yacc.c:1646 */ - { +#line 1365 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "can't make alias for the number variables"); (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper[error]: alias_error!(var_alias!($2, $3)) %*/ } -#line 6157 "parse.c" /* yacc.c:1646 */ +#line 6289 "parse.c" break; case 28: -#line 1355 "parse.y" /* yacc.c:1646 */ - { +#line 1373 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: undef!($2) %*/ } -#line 6168 "parse.c" /* yacc.c:1646 */ +#line 6300 "parse.c" break; case 29: -#line 1362 "parse.y" /* yacc.c:1646 */ - { +#line 1380 "parse.y" + { /*%%%*/ (yyval.node) = new_if(p, (yyvsp[0].node), remove_begin((yyvsp[-2].node)), 0, &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: if_mod!($3, $1) %*/ } -#line 6180 "parse.c" /* yacc.c:1646 */ +#line 6312 "parse.c" break; case 30: -#line 1370 "parse.y" /* yacc.c:1646 */ - { +#line 1388 "parse.y" + { /*%%%*/ (yyval.node) = new_unless(p, (yyvsp[0].node), remove_begin((yyvsp[-2].node)), 0, &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: unless_mod!($3, $1) %*/ } -#line 6192 "parse.c" /* yacc.c:1646 */ +#line 6324 "parse.c" break; case 31: -#line 1378 "parse.y" /* yacc.c:1646 */ - { +#line 1396 "parse.y" + { /*%%%*/ if ((yyvsp[-2].node) && nd_type((yyvsp[-2].node)) == NODE_BEGIN) { (yyval.node) = NEW_WHILE(cond(p, (yyvsp[0].node), &(yylsp[0])), (yyvsp[-2].node)->nd_body, 0, &(yyloc)); @@ -6209,12 +6341,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: while_mod!($3, $1) %*/ } -#line 6208 "parse.c" /* yacc.c:1646 */ +#line 6340 "parse.c" break; case 32: -#line 1390 "parse.y" /* yacc.c:1646 */ - { +#line 1408 "parse.y" + { /*%%%*/ if ((yyvsp[-2].node) && nd_type((yyvsp[-2].node)) == NODE_BEGIN) { (yyval.node) = NEW_UNTIL(cond(p, (yyvsp[0].node), &(yylsp[0])), (yyvsp[-2].node)->nd_body, 0, &(yyloc)); @@ -6225,12 +6357,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: until_mod!($3, $1) %*/ } -#line 6224 "parse.c" /* yacc.c:1646 */ +#line 6356 "parse.c" break; case 33: -#line 1402 "parse.y" /* yacc.c:1646 */ - { +#line 1420 "parse.y" + { /*%%%*/ NODE *resq; YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); @@ -6239,12 +6371,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rescue_mod!($1, $3) %*/ } -#line 6238 "parse.c" /* yacc.c:1646 */ +#line 6370 "parse.c" break; case 34: -#line 1412 "parse.y" /* yacc.c:1646 */ - { +#line 1430 "parse.y" + { if (p->in_def) { rb_warn0("END in method; use at_exit"); } @@ -6257,36 +6389,36 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: END!($3) %*/ } -#line 6256 "parse.c" /* yacc.c:1646 */ +#line 6388 "parse.c" break; case 36: -#line 1427 "parse.y" /* yacc.c:1646 */ - { +#line 1445 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = node_assign(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: massign!($1, $3) %*/ } -#line 6268 "parse.c" /* yacc.c:1646 */ +#line 6400 "parse.c" break; case 37: -#line 1435 "parse.y" /* yacc.c:1646 */ - { +#line 1453 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = node_assign(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: assign!($1, $3) %*/ } -#line 6280 "parse.c" /* yacc.c:1646 */ +#line 6412 "parse.c" break; case 38: -#line 1443 "parse.y" /* yacc.c:1646 */ - { +#line 1461 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].node)); @@ -6294,123 +6426,129 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: massign!($1, rescue_mod!($3, $5)) %*/ } -#line 6293 "parse.c" /* yacc.c:1646 */ +#line 6425 "parse.c" break; case 39: -#line 1452 "parse.y" /* yacc.c:1646 */ - { +#line 1470 "parse.y" + { /*%%%*/ (yyval.node) = node_assign(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: massign!($1, $3) %*/ } -#line 6304 "parse.c" /* yacc.c:1646 */ +#line 6436 "parse.c" break; case 41: -#line 1462 "parse.y" /* yacc.c:1646 */ - { +#line 1480 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = node_assign(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: assign!($1, $3) %*/ } -#line 6315 "parse.c" /* yacc.c:1646 */ +#line 6448 "parse.c" break; case 42: -#line 1469 "parse.y" /* yacc.c:1646 */ - { +#line 1488 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = new_op_assign(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!($1, $2, $3) %*/ } -#line 6326 "parse.c" /* yacc.c:1646 */ +#line 6460 "parse.c" break; case 43: -#line 1476 "parse.y" /* yacc.c:1646 */ - { +#line 1496 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = new_ary_op_assign(p, (yyvsp[-5].node), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-3]), &(yyloc)); /*% %*/ /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/ } -#line 6338 "parse.c" /* yacc.c:1646 */ +#line 6473 "parse.c" break; case 44: -#line 1484 "parse.y" /* yacc.c:1646 */ - { +#line 1505 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), (yyvsp[-3].id), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ } -#line 6349 "parse.c" /* yacc.c:1646 */ +#line 6485 "parse.c" break; case 45: -#line 1491 "parse.y" /* yacc.c:1646 */ - { +#line 1513 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), (yyvsp[-3].id), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ } -#line 6360 "parse.c" /* yacc.c:1646 */ +#line 6497 "parse.c" break; case 46: -#line 1498 "parse.y" /* yacc.c:1646 */ - { +#line 1521 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-4]), &(yylsp[-2])); (yyval.node) = new_const_op_assign(p, NEW_COLON2((yyvsp[-4].node), (yyvsp[-2].id), &loc), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/ } -#line 6372 "parse.c" /* yacc.c:1646 */ +#line 6509 "parse.c" break; case 47: -#line 1506 "parse.y" /* yacc.c:1646 */ - { +#line 1529 "parse.y" + { /*%%%*/ + value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), ID2VAL(idCOLON2), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/ } -#line 6383 "parse.c" /* yacc.c:1646 */ +#line 6521 "parse.c" break; case 48: -#line 1513 "parse.y" /* yacc.c:1646 */ - { +#line 1537 "parse.y" + { /*%%%*/ rb_backref_error(p, (yyvsp[-2].node)); (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper[error]: assign_error!(assign!(var_field(p, $1), $3)) %*/ } -#line 6395 "parse.c" /* yacc.c:1646 */ +#line 6533 "parse.c" break; case 49: -#line 1523 "parse.y" /* yacc.c:1646 */ - { +#line 1547 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 6404 "parse.c" /* yacc.c:1646 */ +#line 6542 "parse.c" break; case 50: -#line 1528 "parse.y" /* yacc.c:1646 */ - { +#line 1552 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].node)); @@ -6418,144 +6556,144 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rescue_mod!($1, $3) %*/ } -#line 6417 "parse.c" /* yacc.c:1646 */ +#line 6555 "parse.c" break; case 53: -#line 1541 "parse.y" /* yacc.c:1646 */ - { +#line 1565 "parse.y" + { (yyval.node) = logop(p, idAND, (yyvsp[-2].node), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 6425 "parse.c" /* yacc.c:1646 */ +#line 6563 "parse.c" break; case 54: -#line 1545 "parse.y" /* yacc.c:1646 */ - { +#line 1569 "parse.y" + { (yyval.node) = logop(p, idOR, (yyvsp[-2].node), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 6433 "parse.c" /* yacc.c:1646 */ +#line 6571 "parse.c" break; case 55: -#line 1549 "parse.y" /* yacc.c:1646 */ - { +#line 1573 "parse.y" + { (yyval.node) = call_uni_op(p, method_cond(p, (yyvsp[0].node), &(yylsp[0])), METHOD_NOT, &(yylsp[-2]), &(yyloc)); } -#line 6441 "parse.c" /* yacc.c:1646 */ +#line 6579 "parse.c" break; case 56: -#line 1553 "parse.y" /* yacc.c:1646 */ - { +#line 1577 "parse.y" + { (yyval.node) = call_uni_op(p, method_cond(p, (yyvsp[0].node), &(yylsp[0])), '!', &(yylsp[-1]), &(yyloc)); } -#line 6449 "parse.c" /* yacc.c:1646 */ +#line 6587 "parse.c" break; case 57: -#line 1557 "parse.y" /* yacc.c:1646 */ - { +#line 1581 "parse.y" + { value_expr((yyvsp[-1].node)); SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; (yyval.num) = p->in_kwarg; p->in_kwarg = 1; } -#line 6461 "parse.c" /* yacc.c:1646 */ +#line 6599 "parse.c" break; case 58: -#line 1564 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pvtbl(p);} -#line 6467 "parse.c" /* yacc.c:1646 */ +#line 1588 "parse.y" + {(yyval.tbl) = push_pvtbl(p);} +#line 6605 "parse.c" break; case 59: -#line 1566 "parse.y" /* yacc.c:1646 */ - {pop_pvtbl(p, (yyvsp[-1].tbl));} -#line 6473 "parse.c" /* yacc.c:1646 */ +#line 1590 "parse.y" + {pop_pvtbl(p, (yyvsp[-1].tbl));} +#line 6611 "parse.c" break; case 60: -#line 1567 "parse.y" /* yacc.c:1646 */ - { +#line 1591 "parse.y" + { p->in_kwarg = !!(yyvsp[-3].num); /*%%%*/ (yyval.node) = new_case3(p, (yyvsp[-5].node), NEW_IN((yyvsp[-1].node), 0, 0, &(yylsp[-1])), &(yyloc)); /*% %*/ /*% ripper: case!($1, in!($5, Qnil, Qnil)) %*/ } -#line 6485 "parse.c" /* yacc.c:1646 */ +#line 6623 "parse.c" break; case 62: -#line 1578 "parse.y" /* yacc.c:1646 */ - { +#line 1602 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 6494 "parse.c" /* yacc.c:1646 */ +#line 6632 "parse.c" break; case 63: -#line 1584 "parse.y" /* yacc.c:1646 */ - {COND_PUSH(1);} -#line 6500 "parse.c" /* yacc.c:1646 */ +#line 1608 "parse.y" + {COND_PUSH(1);} +#line 6638 "parse.c" break; case 64: -#line 1584 "parse.y" /* yacc.c:1646 */ - {COND_POP();} -#line 6506 "parse.c" /* yacc.c:1646 */ +#line 1608 "parse.y" + {COND_POP();} +#line 6644 "parse.c" break; case 65: -#line 1585 "parse.y" /* yacc.c:1646 */ - { +#line 1609 "parse.y" + { (yyval.node) = (yyvsp[-2].node); } -#line 6514 "parse.c" /* yacc.c:1646 */ +#line 6652 "parse.c" break; case 69: -#line 1596 "parse.y" /* yacc.c:1646 */ - { +#line 1620 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, (yyvsp[-2].id), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); /*% %*/ /*% ripper: method_add_arg!(call!($1, $2, $3), $4) %*/ } -#line 6525 "parse.c" /* yacc.c:1646 */ +#line 6663 "parse.c" break; case 70: -#line 1605 "parse.y" /* yacc.c:1646 */ - { +#line 1629 "parse.y" + { (yyval.node) = (yyvsp[-1].node); /*%%%*/ (yyval.node)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.node), (yylsp[-2]).end_pos.lineno); /*% %*/ } -#line 6537 "parse.c" /* yacc.c:1646 */ +#line 6675 "parse.c" break; case 71: -#line 1615 "parse.y" /* yacc.c:1646 */ - { +#line 1639 "parse.y" + { /*%%%*/ (yyval.node) = NEW_FCALL((yyvsp[0].id), 0, &(yyloc)); nd_set_line((yyval.node), p->tokline); /*% %*/ /*% ripper: $1 %*/ } -#line 6549 "parse.c" /* yacc.c:1646 */ +#line 6687 "parse.c" break; case 72: -#line 1625 "parse.y" /* yacc.c:1646 */ - { +#line 1649 "parse.y" + { /*%%%*/ (yyvsp[-1].node)->nd_args = (yyvsp[0].node); nd_set_last_loc((yyvsp[-1].node), (yylsp[0]).end_pos); @@ -6563,12 +6701,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: command!($1, $2) %*/ } -#line 6562 "parse.c" /* yacc.c:1646 */ +#line 6700 "parse.c" break; case 73: -#line 1634 "parse.y" /* yacc.c:1646 */ - { +#line 1658 "parse.y" + { /*%%%*/ block_dup_check(p, (yyvsp[-1].node), (yyvsp[0].node)); (yyvsp[-2].node)->nd_args = (yyvsp[-1].node); @@ -6578,333 +6716,333 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: method_add_block!(command!($1, $2), $3) %*/ } -#line 6577 "parse.c" /* yacc.c:1646 */ +#line 6715 "parse.c" break; case 74: -#line 1645 "parse.y" /* yacc.c:1646 */ - { +#line 1669 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, (yyvsp[-2].id), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), Qnull, &(yylsp[-1]), &(yyloc)); /*% %*/ /*% ripper: command_call!($1, $2, $3, $4) %*/ } -#line 6588 "parse.c" /* yacc.c:1646 */ +#line 6726 "parse.c" break; case 75: -#line 1652 "parse.y" /* yacc.c:1646 */ - { +#line 1676 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, (yyvsp[-3].id), (yyvsp[-4].node), (yyvsp[-2].id), (yyvsp[-1].node), (yyvsp[0].node), &(yylsp[-2]), &(yyloc)); /*% %*/ /*% ripper: method_add_block!(command_call!($1, $2, $3, $4), $5) %*/ } -#line 6599 "parse.c" /* yacc.c:1646 */ +#line 6737 "parse.c" break; case 76: -#line 1659 "parse.y" /* yacc.c:1646 */ - { +#line 1683 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, ID2VAL(idCOLON2), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), Qnull, &(yylsp[-1]), &(yyloc)); /*% %*/ /*% ripper: command_call!($1, ID2VAL(idCOLON2), $3, $4) %*/ } -#line 6610 "parse.c" /* yacc.c:1646 */ +#line 6748 "parse.c" break; case 77: -#line 1666 "parse.y" /* yacc.c:1646 */ - { +#line 1690 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, ID2VAL(idCOLON2), (yyvsp[-4].node), (yyvsp[-2].id), (yyvsp[-1].node), (yyvsp[0].node), &(yylsp[-2]), &(yyloc)); /*% %*/ /*% ripper: method_add_block!(command_call!($1, ID2VAL(idCOLON2), $3, $4), $5) %*/ } -#line 6621 "parse.c" /* yacc.c:1646 */ +#line 6759 "parse.c" break; case 78: -#line 1673 "parse.y" /* yacc.c:1646 */ - { +#line 1697 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SUPER((yyvsp[0].node), &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: super!($2) %*/ } -#line 6633 "parse.c" /* yacc.c:1646 */ +#line 6771 "parse.c" break; case 79: -#line 1681 "parse.y" /* yacc.c:1646 */ - { +#line 1705 "parse.y" + { /*%%%*/ (yyval.node) = new_yield(p, (yyvsp[0].node), &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: yield!($2) %*/ } -#line 6645 "parse.c" /* yacc.c:1646 */ +#line 6783 "parse.c" break; case 80: -#line 1689 "parse.y" /* yacc.c:1646 */ - { +#line 1713 "parse.y" + { /*%%%*/ (yyval.node) = NEW_RETURN(ret_args(p, (yyvsp[0].node)), &(yyloc)); /*% %*/ /*% ripper: return!($2) %*/ } -#line 6656 "parse.c" /* yacc.c:1646 */ +#line 6794 "parse.c" break; case 81: -#line 1696 "parse.y" /* yacc.c:1646 */ - { +#line 1720 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BREAK(ret_args(p, (yyvsp[0].node)), &(yyloc)); /*% %*/ /*% ripper: break!($2) %*/ } -#line 6667 "parse.c" /* yacc.c:1646 */ +#line 6805 "parse.c" break; case 82: -#line 1703 "parse.y" /* yacc.c:1646 */ - { +#line 1727 "parse.y" + { /*%%%*/ (yyval.node) = NEW_NEXT(ret_args(p, (yyvsp[0].node)), &(yyloc)); /*% %*/ /*% ripper: next!($2) %*/ } -#line 6678 "parse.c" /* yacc.c:1646 */ +#line 6816 "parse.c" break; case 84: -#line 1713 "parse.y" /* yacc.c:1646 */ - { +#line 1737 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: mlhs_paren!($2) %*/ } -#line 6689 "parse.c" /* yacc.c:1646 */ +#line 6827 "parse.c" break; case 86: -#line 1723 "parse.y" /* yacc.c:1646 */ - { +#line 1747 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(NEW_LIST((yyvsp[-1].node), &(yyloc)), 0, &(yyloc)); /*% %*/ /*% ripper: mlhs_paren!($2) %*/ } -#line 6700 "parse.c" /* yacc.c:1646 */ +#line 6838 "parse.c" break; case 87: -#line 1732 "parse.y" /* yacc.c:1646 */ - { +#line 1756 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[0].node), 0, &(yyloc)); /*% %*/ /*% ripper: $1 %*/ } -#line 6711 "parse.c" /* yacc.c:1646 */ +#line 6849 "parse.c" break; case 88: -#line 1739 "parse.y" /* yacc.c:1646 */ - { +#line 1763 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(list_append(p, (yyvsp[-1].node),(yyvsp[0].node)), 0, &(yyloc)); /*% %*/ /*% ripper: mlhs_add!($1, $2) %*/ } -#line 6722 "parse.c" /* yacc.c:1646 */ +#line 6860 "parse.c" break; case 89: -#line 1746 "parse.y" /* yacc.c:1646 */ - { +#line 1770 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!($1, $3) %*/ } -#line 6733 "parse.c" /* yacc.c:1646 */ +#line 6871 "parse.c" break; case 90: -#line 1753 "parse.y" /* yacc.c:1646 */ - { +#line 1777 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-4].node), NEW_POSTARG((yyvsp[-2].node),(yyvsp[0].node),&(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!($1, $3), $5) %*/ } -#line 6744 "parse.c" /* yacc.c:1646 */ +#line 6882 "parse.c" break; case 91: -#line 1760 "parse.y" /* yacc.c:1646 */ - { +#line 1784 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-1].node), NODE_SPECIAL_NO_NAME_REST, &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!($1, Qnil) %*/ } -#line 6755 "parse.c" /* yacc.c:1646 */ +#line 6893 "parse.c" break; case 92: -#line 1767 "parse.y" /* yacc.c:1646 */ - { +#line 1791 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-3].node), NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!($1, Qnil), $4) %*/ } -#line 6766 "parse.c" /* yacc.c:1646 */ +#line 6904 "parse.c" break; case 93: -#line 1774 "parse.y" /* yacc.c:1646 */ - { +#line 1798 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!(mlhs_new!, $2) %*/ } -#line 6777 "parse.c" /* yacc.c:1646 */ +#line 6915 "parse.c" break; case 94: -#line 1781 "parse.y" /* yacc.c:1646 */ - { +#line 1805 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, NEW_POSTARG((yyvsp[-2].node),(yyvsp[0].node),&(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $2), $4) %*/ } -#line 6788 "parse.c" /* yacc.c:1646 */ +#line 6926 "parse.c" break; case 95: -#line 1788 "parse.y" /* yacc.c:1646 */ - { +#line 1812 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, NODE_SPECIAL_NO_NAME_REST, &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!(mlhs_new!, Qnil) %*/ } -#line 6799 "parse.c" /* yacc.c:1646 */ +#line 6937 "parse.c" break; case 96: -#line 1795 "parse.y" /* yacc.c:1646 */ - { +#line 1819 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, Qnil), $3) %*/ } -#line 6810 "parse.c" /* yacc.c:1646 */ +#line 6948 "parse.c" break; case 98: -#line 1805 "parse.y" /* yacc.c:1646 */ - { +#line 1829 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: mlhs_paren!($2) %*/ } -#line 6821 "parse.c" /* yacc.c:1646 */ +#line 6959 "parse.c" break; case 99: -#line 1814 "parse.y" /* yacc.c:1646 */ - { +#line 1838 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[-1].node), &(yylsp[-1])); /*% %*/ /*% ripper: mlhs_add!(mlhs_new!, $1) %*/ } -#line 6832 "parse.c" /* yacc.c:1646 */ +#line 6970 "parse.c" break; case 100: -#line 1821 "parse.y" /* yacc.c:1646 */ - { +#line 1845 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, (yyvsp[-2].node), (yyvsp[-1].node)); /*% %*/ /*% ripper: mlhs_add!($1, $2) %*/ } -#line 6843 "parse.c" /* yacc.c:1646 */ +#line 6981 "parse.c" break; case 101: -#line 1830 "parse.y" /* yacc.c:1646 */ - { +#line 1854 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add!(mlhs_new!, $1) %*/ } -#line 6854 "parse.c" /* yacc.c:1646 */ +#line 6992 "parse.c" break; case 102: -#line 1837 "parse.y" /* yacc.c:1646 */ - { +#line 1861 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, (yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: mlhs_add!($1, $3) %*/ } -#line 6865 "parse.c" /* yacc.c:1646 */ +#line 7003 "parse.c" break; case 103: -#line 1846 "parse.y" /* yacc.c:1646 */ - { +#line 1870 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 6876 "parse.c" /* yacc.c:1646 */ +#line 7014 "parse.c" break; case 104: -#line 1853 "parse.y" /* yacc.c:1646 */ - { +#line 1877 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 6887 "parse.c" /* yacc.c:1646 */ +#line 7025 "parse.c" break; case 105: -#line 1860 "parse.y" /* yacc.c:1646 */ - { +#line 1884 "parse.y" + { /*%%%*/ (yyval.node) = aryset(p, (yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: aref_field!($1, escape_Qundef($3)) %*/ } -#line 6898 "parse.c" /* yacc.c:1646 */ +#line 7036 "parse.c" break; case 106: -#line 1867 "parse.y" /* yacc.c:1646 */ - { +#line 1891 "parse.y" + { if ((yyvsp[-1].id) == tANDDOT) { yyerror1(&(yylsp[-1]), "&. inside multiple assignment destination"); } @@ -6913,23 +7051,23 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: field!($1, $2, $3) %*/ } -#line 6912 "parse.c" /* yacc.c:1646 */ +#line 7050 "parse.c" break; case 107: -#line 1877 "parse.y" /* yacc.c:1646 */ - { +#line 1901 "parse.y" + { /*%%%*/ (yyval.node) = attrset(p, (yyvsp[-2].node), idCOLON2, (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: const_path_field!($1, $3) %*/ } -#line 6923 "parse.c" /* yacc.c:1646 */ +#line 7061 "parse.c" break; case 108: -#line 1884 "parse.y" /* yacc.c:1646 */ - { +#line 1908 "parse.y" + { if ((yyvsp[-1].id) == tANDDOT) { yyerror1(&(yylsp[-1]), "&. inside multiple assignment destination"); } @@ -6938,533 +7076,533 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: field!($1, $2, $3) %*/ } -#line 6937 "parse.c" /* yacc.c:1646 */ +#line 7075 "parse.c" break; case 109: -#line 1894 "parse.y" /* yacc.c:1646 */ - { +#line 1918 "parse.y" + { /*%%%*/ (yyval.node) = const_decl(p, NEW_COLON2((yyvsp[-2].node), (yyvsp[0].id), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: const_decl(p, const_path_field!($1, $3)) %*/ } -#line 6948 "parse.c" /* yacc.c:1646 */ +#line 7086 "parse.c" break; case 110: -#line 1901 "parse.y" /* yacc.c:1646 */ - { +#line 1925 "parse.y" + { /*%%%*/ (yyval.node) = const_decl(p, NEW_COLON3((yyvsp[0].id), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: const_decl(p, top_const_field!($2)) %*/ } -#line 6959 "parse.c" /* yacc.c:1646 */ +#line 7097 "parse.c" break; case 111: -#line 1908 "parse.y" /* yacc.c:1646 */ - { +#line 1932 "parse.y" + { /*%%%*/ rb_backref_error(p, (yyvsp[0].node)); (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper[error]: assign_error!(var_field(p, $1)) %*/ } -#line 6971 "parse.c" /* yacc.c:1646 */ +#line 7109 "parse.c" break; case 112: -#line 1918 "parse.y" /* yacc.c:1646 */ - { +#line 1942 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 6982 "parse.c" /* yacc.c:1646 */ +#line 7120 "parse.c" break; case 113: -#line 1925 "parse.y" /* yacc.c:1646 */ - { +#line 1949 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 6993 "parse.c" /* yacc.c:1646 */ +#line 7131 "parse.c" break; case 114: -#line 1932 "parse.y" /* yacc.c:1646 */ - { +#line 1956 "parse.y" + { /*%%%*/ (yyval.node) = aryset(p, (yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: aref_field!($1, escape_Qundef($3)) %*/ } -#line 7004 "parse.c" /* yacc.c:1646 */ +#line 7142 "parse.c" break; case 115: -#line 1939 "parse.y" /* yacc.c:1646 */ - { +#line 1963 "parse.y" + { /*%%%*/ (yyval.node) = attrset(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: field!($1, $2, $3) %*/ } -#line 7015 "parse.c" /* yacc.c:1646 */ +#line 7153 "parse.c" break; case 116: -#line 1946 "parse.y" /* yacc.c:1646 */ - { +#line 1970 "parse.y" + { /*%%%*/ (yyval.node) = attrset(p, (yyvsp[-2].node), idCOLON2, (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: field!($1, ID2VAL(idCOLON2), $3) %*/ } -#line 7026 "parse.c" /* yacc.c:1646 */ +#line 7164 "parse.c" break; case 117: -#line 1953 "parse.y" /* yacc.c:1646 */ - { +#line 1977 "parse.y" + { /*%%%*/ (yyval.node) = attrset(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: field!($1, $2, $3) %*/ } -#line 7037 "parse.c" /* yacc.c:1646 */ +#line 7175 "parse.c" break; case 118: -#line 1960 "parse.y" /* yacc.c:1646 */ - { +#line 1984 "parse.y" + { /*%%%*/ (yyval.node) = const_decl(p, NEW_COLON2((yyvsp[-2].node), (yyvsp[0].id), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: const_decl(p, const_path_field!($1, $3)) %*/ } -#line 7048 "parse.c" /* yacc.c:1646 */ +#line 7186 "parse.c" break; case 119: -#line 1967 "parse.y" /* yacc.c:1646 */ - { +#line 1991 "parse.y" + { /*%%%*/ (yyval.node) = const_decl(p, NEW_COLON3((yyvsp[0].id), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: const_decl(p, top_const_field!($2)) %*/ } -#line 7059 "parse.c" /* yacc.c:1646 */ +#line 7197 "parse.c" break; case 120: -#line 1974 "parse.y" /* yacc.c:1646 */ - { +#line 1998 "parse.y" + { /*%%%*/ rb_backref_error(p, (yyvsp[0].node)); (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper[error]: assign_error!(var_field(p, $1)) %*/ } -#line 7071 "parse.c" /* yacc.c:1646 */ +#line 7209 "parse.c" break; case 121: -#line 1984 "parse.y" /* yacc.c:1646 */ - { +#line 2008 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "class/module name must be CONSTANT"); /*% %*/ /*% ripper[error]: class_name_error!($1) %*/ } -#line 7082 "parse.c" /* yacc.c:1646 */ +#line 7220 "parse.c" break; case 123: -#line 1994 "parse.y" /* yacc.c:1646 */ - { +#line 2018 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON3((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: top_const_ref!($2) %*/ } -#line 7093 "parse.c" /* yacc.c:1646 */ +#line 7231 "parse.c" break; case 124: -#line 2001 "parse.y" /* yacc.c:1646 */ - { +#line 2025 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON2(0, (yyval.node), &(yyloc)); /*% %*/ /*% ripper: const_ref!($1) %*/ } -#line 7104 "parse.c" /* yacc.c:1646 */ +#line 7242 "parse.c" break; case 125: -#line 2008 "parse.y" /* yacc.c:1646 */ - { +#line 2032 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON2((yyvsp[-2].node), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: const_path_ref!($1, $3) %*/ } -#line 7115 "parse.c" /* yacc.c:1646 */ +#line 7253 "parse.c" break; case 129: -#line 2020 "parse.y" /* yacc.c:1646 */ - { +#line 2044 "parse.y" + { SET_LEX_STATE(EXPR_ENDFN); (yyval.id) = (yyvsp[0].id); } -#line 7124 "parse.c" /* yacc.c:1646 */ +#line 7262 "parse.c" break; case 130: -#line 2025 "parse.y" /* yacc.c:1646 */ - { +#line 2049 "parse.y" + { SET_LEX_STATE(EXPR_ENDFN); (yyval.id) = (yyvsp[0].id); } -#line 7133 "parse.c" /* yacc.c:1646 */ +#line 7271 "parse.c" break; case 131: -#line 2032 "parse.y" /* yacc.c:1646 */ - { +#line 2056 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIT(ID2SYM((yyvsp[0].id)), &(yyloc)); /*% %*/ /*% ripper: symbol_literal!($1) %*/ } -#line 7144 "parse.c" /* yacc.c:1646 */ +#line 7282 "parse.c" break; case 133: -#line 2042 "parse.y" /* yacc.c:1646 */ - { +#line 2066 "parse.y" + { /*%%%*/ (yyval.node) = NEW_UNDEF((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 7155 "parse.c" /* yacc.c:1646 */ +#line 7293 "parse.c" break; case 134: -#line 2048 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} -#line 7161 "parse.c" /* yacc.c:1646 */ +#line 2072 "parse.y" + {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} +#line 7299 "parse.c" break; case 135: -#line 2049 "parse.y" /* yacc.c:1646 */ - { +#line 2073 "parse.y" + { /*%%%*/ NODE *undef = NEW_UNDEF((yyvsp[0].node), &(yylsp[0])); (yyval.node) = block_append(p, (yyvsp[-3].node), undef); /*% %*/ /*% ripper: rb_ary_push($1, get_value($4)) %*/ } -#line 7173 "parse.c" /* yacc.c:1646 */ +#line 7311 "parse.c" break; case 136: -#line 2058 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '|'); } -#line 7179 "parse.c" /* yacc.c:1646 */ +#line 2082 "parse.y" + { ifndef_ripper((yyval.id) = '|'); } +#line 7317 "parse.c" break; case 137: -#line 2059 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '^'); } -#line 7185 "parse.c" /* yacc.c:1646 */ +#line 2083 "parse.y" + { ifndef_ripper((yyval.id) = '^'); } +#line 7323 "parse.c" break; case 138: -#line 2060 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '&'); } -#line 7191 "parse.c" /* yacc.c:1646 */ +#line 2084 "parse.y" + { ifndef_ripper((yyval.id) = '&'); } +#line 7329 "parse.c" break; case 139: -#line 2061 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tCMP); } -#line 7197 "parse.c" /* yacc.c:1646 */ +#line 2085 "parse.y" + { ifndef_ripper((yyval.id) = tCMP); } +#line 7335 "parse.c" break; case 140: -#line 2062 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tEQ); } -#line 7203 "parse.c" /* yacc.c:1646 */ +#line 2086 "parse.y" + { ifndef_ripper((yyval.id) = tEQ); } +#line 7341 "parse.c" break; case 141: -#line 2063 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tEQQ); } -#line 7209 "parse.c" /* yacc.c:1646 */ +#line 2087 "parse.y" + { ifndef_ripper((yyval.id) = tEQQ); } +#line 7347 "parse.c" break; case 142: -#line 2064 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tMATCH); } -#line 7215 "parse.c" /* yacc.c:1646 */ +#line 2088 "parse.y" + { ifndef_ripper((yyval.id) = tMATCH); } +#line 7353 "parse.c" break; case 143: -#line 2065 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tNMATCH); } -#line 7221 "parse.c" /* yacc.c:1646 */ +#line 2089 "parse.y" + { ifndef_ripper((yyval.id) = tNMATCH); } +#line 7359 "parse.c" break; case 144: -#line 2066 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '>'); } -#line 7227 "parse.c" /* yacc.c:1646 */ +#line 2090 "parse.y" + { ifndef_ripper((yyval.id) = '>'); } +#line 7365 "parse.c" break; case 145: -#line 2067 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tGEQ); } -#line 7233 "parse.c" /* yacc.c:1646 */ +#line 2091 "parse.y" + { ifndef_ripper((yyval.id) = tGEQ); } +#line 7371 "parse.c" break; case 146: -#line 2068 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '<'); } -#line 7239 "parse.c" /* yacc.c:1646 */ +#line 2092 "parse.y" + { ifndef_ripper((yyval.id) = '<'); } +#line 7377 "parse.c" break; case 147: -#line 2069 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tLEQ); } -#line 7245 "parse.c" /* yacc.c:1646 */ +#line 2093 "parse.y" + { ifndef_ripper((yyval.id) = tLEQ); } +#line 7383 "parse.c" break; case 148: -#line 2070 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tNEQ); } -#line 7251 "parse.c" /* yacc.c:1646 */ +#line 2094 "parse.y" + { ifndef_ripper((yyval.id) = tNEQ); } +#line 7389 "parse.c" break; case 149: -#line 2071 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tLSHFT); } -#line 7257 "parse.c" /* yacc.c:1646 */ +#line 2095 "parse.y" + { ifndef_ripper((yyval.id) = tLSHFT); } +#line 7395 "parse.c" break; case 150: -#line 2072 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tRSHFT); } -#line 7263 "parse.c" /* yacc.c:1646 */ +#line 2096 "parse.y" + { ifndef_ripper((yyval.id) = tRSHFT); } +#line 7401 "parse.c" break; case 151: -#line 2073 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '+'); } -#line 7269 "parse.c" /* yacc.c:1646 */ +#line 2097 "parse.y" + { ifndef_ripper((yyval.id) = '+'); } +#line 7407 "parse.c" break; case 152: -#line 2074 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '-'); } -#line 7275 "parse.c" /* yacc.c:1646 */ +#line 2098 "parse.y" + { ifndef_ripper((yyval.id) = '-'); } +#line 7413 "parse.c" break; case 153: -#line 2075 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '*'); } -#line 7281 "parse.c" /* yacc.c:1646 */ +#line 2099 "parse.y" + { ifndef_ripper((yyval.id) = '*'); } +#line 7419 "parse.c" break; case 154: -#line 2076 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '*'); } -#line 7287 "parse.c" /* yacc.c:1646 */ +#line 2100 "parse.y" + { ifndef_ripper((yyval.id) = '*'); } +#line 7425 "parse.c" break; case 155: -#line 2077 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '/'); } -#line 7293 "parse.c" /* yacc.c:1646 */ +#line 2101 "parse.y" + { ifndef_ripper((yyval.id) = '/'); } +#line 7431 "parse.c" break; case 156: -#line 2078 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '%'); } -#line 7299 "parse.c" /* yacc.c:1646 */ +#line 2102 "parse.y" + { ifndef_ripper((yyval.id) = '%'); } +#line 7437 "parse.c" break; case 157: -#line 2079 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tPOW); } -#line 7305 "parse.c" /* yacc.c:1646 */ +#line 2103 "parse.y" + { ifndef_ripper((yyval.id) = tPOW); } +#line 7443 "parse.c" break; case 158: -#line 2080 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tDSTAR); } -#line 7311 "parse.c" /* yacc.c:1646 */ +#line 2104 "parse.y" + { ifndef_ripper((yyval.id) = tDSTAR); } +#line 7449 "parse.c" break; case 159: -#line 2081 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '!'); } -#line 7317 "parse.c" /* yacc.c:1646 */ +#line 2105 "parse.y" + { ifndef_ripper((yyval.id) = '!'); } +#line 7455 "parse.c" break; case 160: -#line 2082 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '~'); } -#line 7323 "parse.c" /* yacc.c:1646 */ +#line 2106 "parse.y" + { ifndef_ripper((yyval.id) = '~'); } +#line 7461 "parse.c" break; case 161: -#line 2083 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tUPLUS); } -#line 7329 "parse.c" /* yacc.c:1646 */ +#line 2107 "parse.y" + { ifndef_ripper((yyval.id) = tUPLUS); } +#line 7467 "parse.c" break; case 162: -#line 2084 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tUMINUS); } -#line 7335 "parse.c" /* yacc.c:1646 */ +#line 2108 "parse.y" + { ifndef_ripper((yyval.id) = tUMINUS); } +#line 7473 "parse.c" break; case 163: -#line 2085 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tAREF); } -#line 7341 "parse.c" /* yacc.c:1646 */ +#line 2109 "parse.y" + { ifndef_ripper((yyval.id) = tAREF); } +#line 7479 "parse.c" break; case 164: -#line 2086 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = tASET); } -#line 7347 "parse.c" /* yacc.c:1646 */ +#line 2110 "parse.y" + { ifndef_ripper((yyval.id) = tASET); } +#line 7485 "parse.c" break; case 165: -#line 2087 "parse.y" /* yacc.c:1646 */ - { ifndef_ripper((yyval.id) = '`'); } -#line 7353 "parse.c" /* yacc.c:1646 */ +#line 2111 "parse.y" + { ifndef_ripper((yyval.id) = '`'); } +#line 7491 "parse.c" break; case 207: -#line 2105 "parse.y" /* yacc.c:1646 */ - { +#line 2129 "parse.y" + { /*%%%*/ (yyval.node) = node_assign(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: assign!($1, $3) %*/ } -#line 7364 "parse.c" /* yacc.c:1646 */ +#line 7502 "parse.c" break; case 208: -#line 2112 "parse.y" /* yacc.c:1646 */ - { +#line 2136 "parse.y" + { /*%%%*/ (yyval.node) = new_op_assign(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!($1, $2, $3) %*/ } -#line 7375 "parse.c" /* yacc.c:1646 */ +#line 7513 "parse.c" break; case 209: -#line 2119 "parse.y" /* yacc.c:1646 */ - { +#line 2143 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = new_ary_op_assign(p, (yyvsp[-5].node), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-3]), &(yyloc)); /*% %*/ /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/ } -#line 7387 "parse.c" /* yacc.c:1646 */ +#line 7525 "parse.c" break; case 210: -#line 2127 "parse.y" /* yacc.c:1646 */ - { +#line 2151 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), (yyvsp[-3].id), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ } -#line 7399 "parse.c" /* yacc.c:1646 */ +#line 7537 "parse.c" break; case 211: -#line 2135 "parse.y" /* yacc.c:1646 */ - { +#line 2159 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), (yyvsp[-3].id), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ } -#line 7411 "parse.c" /* yacc.c:1646 */ +#line 7549 "parse.c" break; case 212: -#line 2143 "parse.y" /* yacc.c:1646 */ - { +#line 2167 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = new_attr_op_assign(p, (yyvsp[-4].node), ID2VAL(idCOLON2), (yyvsp[-2].id), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/ } -#line 7423 "parse.c" /* yacc.c:1646 */ +#line 7561 "parse.c" break; case 213: -#line 2151 "parse.y" /* yacc.c:1646 */ - { +#line 2175 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-4]), &(yylsp[-2])); (yyval.node) = new_const_op_assign(p, NEW_COLON2((yyvsp[-4].node), (yyvsp[-2].id), &loc), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/ } -#line 7435 "parse.c" /* yacc.c:1646 */ +#line 7573 "parse.c" break; case 214: -#line 2159 "parse.y" /* yacc.c:1646 */ - { +#line 2183 "parse.y" + { /*%%%*/ (yyval.node) = new_const_op_assign(p, NEW_COLON3((yyvsp[-2].id), &(yyloc)), (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: opassign!(top_const_field!($2), $3, $4) %*/ } -#line 7446 "parse.c" /* yacc.c:1646 */ +#line 7584 "parse.c" break; case 215: -#line 2166 "parse.y" /* yacc.c:1646 */ - { +#line 2190 "parse.y" + { /*%%%*/ rb_backref_error(p, (yyvsp[-2].node)); (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper[error]: assign_error!(opassign!(var_field(p, $1), $2, $3)) %*/ } -#line 7458 "parse.c" /* yacc.c:1646 */ +#line 7596 "parse.c" break; case 216: -#line 2174 "parse.y" /* yacc.c:1646 */ - { +#line 2198 "parse.y" + { /*%%%*/ value_expr((yyvsp[-2].node)); value_expr((yyvsp[0].node)); @@ -7472,12 +7610,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!($1, $3) %*/ } -#line 7471 "parse.c" /* yacc.c:1646 */ +#line 7609 "parse.c" break; case 217: -#line 2183 "parse.y" /* yacc.c:1646 */ - { +#line 2207 "parse.y" + { /*%%%*/ value_expr((yyvsp[-2].node)); value_expr((yyvsp[0].node)); @@ -7485,12 +7623,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!($1, $3) %*/ } -#line 7484 "parse.c" /* yacc.c:1646 */ +#line 7622 "parse.c" break; case 218: -#line 2192 "parse.y" /* yacc.c:1646 */ - { +#line 2216 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -7501,12 +7639,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!($1, Qnil) %*/ } -#line 7500 "parse.c" /* yacc.c:1646 */ +#line 7638 "parse.c" break; case 219: -#line 2204 "parse.y" /* yacc.c:1646 */ - { +#line 2228 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -7517,12 +7655,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!($1, Qnil) %*/ } -#line 7516 "parse.c" /* yacc.c:1646 */ +#line 7654 "parse.c" break; case 220: -#line 2216 "parse.y" /* yacc.c:1646 */ - { +#line 2240 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -7533,12 +7671,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!(Qnil, $2) %*/ } -#line 7532 "parse.c" /* yacc.c:1646 */ +#line 7670 "parse.c" break; case 221: -#line 2228 "parse.y" /* yacc.c:1646 */ - { +#line 2252 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -7549,219 +7687,219 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!(Qnil, $2) %*/ } -#line 7548 "parse.c" /* yacc.c:1646 */ +#line 7686 "parse.c" break; case 222: -#line 2240 "parse.y" /* yacc.c:1646 */ - { +#line 2264 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '+', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7556 "parse.c" /* yacc.c:1646 */ +#line 7694 "parse.c" break; case 223: -#line 2244 "parse.y" /* yacc.c:1646 */ - { +#line 2268 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '-', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7564 "parse.c" /* yacc.c:1646 */ +#line 7702 "parse.c" break; case 224: -#line 2248 "parse.y" /* yacc.c:1646 */ - { +#line 2272 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '*', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7572 "parse.c" /* yacc.c:1646 */ +#line 7710 "parse.c" break; case 225: -#line 2252 "parse.y" /* yacc.c:1646 */ - { +#line 2276 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '/', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7580 "parse.c" /* yacc.c:1646 */ +#line 7718 "parse.c" break; case 226: -#line 2256 "parse.y" /* yacc.c:1646 */ - { +#line 2280 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '%', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7588 "parse.c" /* yacc.c:1646 */ +#line 7726 "parse.c" break; case 227: -#line 2260 "parse.y" /* yacc.c:1646 */ - { +#line 2284 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idPow, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7596 "parse.c" /* yacc.c:1646 */ +#line 7734 "parse.c" break; case 228: -#line 2264 "parse.y" /* yacc.c:1646 */ - { +#line 2288 "parse.y" + { (yyval.node) = call_uni_op(p, call_bin_op(p, (yyvsp[-2].node), idPow, (yyvsp[0].node), &(yylsp[-2]), &(yyloc)), idUMinus, &(yylsp[-3]), &(yyloc)); } -#line 7604 "parse.c" /* yacc.c:1646 */ +#line 7742 "parse.c" break; case 229: -#line 2268 "parse.y" /* yacc.c:1646 */ - { +#line 2292 "parse.y" + { (yyval.node) = call_uni_op(p, (yyvsp[0].node), idUPlus, &(yylsp[-1]), &(yyloc)); } -#line 7612 "parse.c" /* yacc.c:1646 */ +#line 7750 "parse.c" break; case 230: -#line 2272 "parse.y" /* yacc.c:1646 */ - { +#line 2296 "parse.y" + { (yyval.node) = call_uni_op(p, (yyvsp[0].node), idUMinus, &(yylsp[-1]), &(yyloc)); } -#line 7620 "parse.c" /* yacc.c:1646 */ +#line 7758 "parse.c" break; case 231: -#line 2276 "parse.y" /* yacc.c:1646 */ - { +#line 2300 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '|', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7628 "parse.c" /* yacc.c:1646 */ +#line 7766 "parse.c" break; case 232: -#line 2280 "parse.y" /* yacc.c:1646 */ - { +#line 2304 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '^', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7636 "parse.c" /* yacc.c:1646 */ +#line 7774 "parse.c" break; case 233: -#line 2284 "parse.y" /* yacc.c:1646 */ - { +#line 2308 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), '&', (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7644 "parse.c" /* yacc.c:1646 */ +#line 7782 "parse.c" break; case 234: -#line 2288 "parse.y" /* yacc.c:1646 */ - { +#line 2312 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idCmp, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7652 "parse.c" /* yacc.c:1646 */ +#line 7790 "parse.c" break; case 236: -#line 2293 "parse.y" /* yacc.c:1646 */ - { +#line 2317 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idEq, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7660 "parse.c" /* yacc.c:1646 */ +#line 7798 "parse.c" break; case 237: -#line 2297 "parse.y" /* yacc.c:1646 */ - { +#line 2321 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idEqq, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7668 "parse.c" /* yacc.c:1646 */ +#line 7806 "parse.c" break; case 238: -#line 2301 "parse.y" /* yacc.c:1646 */ - { +#line 2325 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idNeq, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7676 "parse.c" /* yacc.c:1646 */ +#line 7814 "parse.c" break; case 239: -#line 2305 "parse.y" /* yacc.c:1646 */ - { +#line 2329 "parse.y" + { (yyval.node) = match_op(p, (yyvsp[-2].node), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7684 "parse.c" /* yacc.c:1646 */ +#line 7822 "parse.c" break; case 240: -#line 2309 "parse.y" /* yacc.c:1646 */ - { +#line 2333 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idNeqTilde, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7692 "parse.c" /* yacc.c:1646 */ +#line 7830 "parse.c" break; case 241: -#line 2313 "parse.y" /* yacc.c:1646 */ - { +#line 2337 "parse.y" + { (yyval.node) = call_uni_op(p, method_cond(p, (yyvsp[0].node), &(yylsp[0])), '!', &(yylsp[-1]), &(yyloc)); } -#line 7700 "parse.c" /* yacc.c:1646 */ +#line 7838 "parse.c" break; case 242: -#line 2317 "parse.y" /* yacc.c:1646 */ - { +#line 2341 "parse.y" + { (yyval.node) = call_uni_op(p, (yyvsp[0].node), '~', &(yylsp[-1]), &(yyloc)); } -#line 7708 "parse.c" /* yacc.c:1646 */ +#line 7846 "parse.c" break; case 243: -#line 2321 "parse.y" /* yacc.c:1646 */ - { +#line 2345 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idLTLT, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7716 "parse.c" /* yacc.c:1646 */ +#line 7854 "parse.c" break; case 244: -#line 2325 "parse.y" /* yacc.c:1646 */ - { +#line 2349 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), idGTGT, (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7724 "parse.c" /* yacc.c:1646 */ +#line 7862 "parse.c" break; case 245: -#line 2329 "parse.y" /* yacc.c:1646 */ - { +#line 2353 "parse.y" + { (yyval.node) = logop(p, idANDOP, (yyvsp[-2].node), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7732 "parse.c" /* yacc.c:1646 */ +#line 7870 "parse.c" break; case 246: -#line 2333 "parse.y" /* yacc.c:1646 */ - { +#line 2357 "parse.y" + { (yyval.node) = logop(p, idOROP, (yyvsp[-2].node), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7740 "parse.c" /* yacc.c:1646 */ +#line 7878 "parse.c" break; case 247: -#line 2336 "parse.y" /* yacc.c:1646 */ - {p->in_defined = 1;} -#line 7746 "parse.c" /* yacc.c:1646 */ +#line 2360 "parse.y" + {p->in_defined = 1;} +#line 7884 "parse.c" break; case 248: -#line 2337 "parse.y" /* yacc.c:1646 */ - { +#line 2361 "parse.y" + { p->in_defined = 0; (yyval.node) = new_defined(p, (yyvsp[0].node), &(yyloc)); } -#line 7755 "parse.c" /* yacc.c:1646 */ +#line 7893 "parse.c" break; case 249: -#line 2342 "parse.y" /* yacc.c:1646 */ - { +#line 2366 "parse.y" + { /*%%%*/ value_expr((yyvsp[-5].node)); (yyval.node) = new_if(p, (yyvsp[-5].node), (yyvsp[-3].node), (yyvsp[0].node), &(yyloc)); @@ -7769,109 +7907,109 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: ifop!($1, $3, $6) %*/ } -#line 7768 "parse.c" /* yacc.c:1646 */ +#line 7906 "parse.c" break; case 250: -#line 2351 "parse.y" /* yacc.c:1646 */ - { +#line 2375 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 7776 "parse.c" /* yacc.c:1646 */ +#line 7914 "parse.c" break; case 251: -#line 2356 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = '>';} -#line 7782 "parse.c" /* yacc.c:1646 */ +#line 2380 "parse.y" + {(yyval.id) = '>';} +#line 7920 "parse.c" break; case 252: -#line 2357 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = '<';} -#line 7788 "parse.c" /* yacc.c:1646 */ +#line 2381 "parse.y" + {(yyval.id) = '<';} +#line 7926 "parse.c" break; case 253: -#line 2358 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = idGE;} -#line 7794 "parse.c" /* yacc.c:1646 */ +#line 2382 "parse.y" + {(yyval.id) = idGE;} +#line 7932 "parse.c" break; case 254: -#line 2359 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = idLE;} -#line 7800 "parse.c" /* yacc.c:1646 */ +#line 2383 "parse.y" + {(yyval.id) = idLE;} +#line 7938 "parse.c" break; case 255: -#line 2363 "parse.y" /* yacc.c:1646 */ - { +#line 2387 "parse.y" + { (yyval.node) = call_bin_op(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7808 "parse.c" /* yacc.c:1646 */ +#line 7946 "parse.c" break; case 256: -#line 2367 "parse.y" /* yacc.c:1646 */ - { +#line 2391 "parse.y" + { rb_warning1("comparison '%s' after comparison", WARN_ID((yyvsp[-1].id))); (yyval.node) = call_bin_op(p, (yyvsp[-2].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); } -#line 7817 "parse.c" /* yacc.c:1646 */ +#line 7955 "parse.c" break; case 257: -#line 2374 "parse.y" /* yacc.c:1646 */ - { +#line 2398 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 7826 "parse.c" /* yacc.c:1646 */ +#line 7964 "parse.c" break; case 259: -#line 2382 "parse.y" /* yacc.c:1646 */ - { +#line 2406 "parse.y" + { (yyval.node) = (yyvsp[-1].node); } -#line 7834 "parse.c" /* yacc.c:1646 */ +#line 7972 "parse.c" break; case 260: -#line 2386 "parse.y" /* yacc.c:1646 */ - { +#line 2410 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? arg_append(p, (yyvsp[-3].node), new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].node); /*% %*/ /*% ripper: args_add!($1, bare_assoc_hash!($3)) %*/ } -#line 7845 "parse.c" /* yacc.c:1646 */ +#line 7983 "parse.c" break; case 261: -#line 2393 "parse.y" /* yacc.c:1646 */ - { +#line 2417 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? NEW_LIST(new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yyloc)) : 0; /*% %*/ /*% ripper: args_add!(args_new!, bare_assoc_hash!($1)) %*/ } -#line 7856 "parse.c" /* yacc.c:1646 */ +#line 7994 "parse.c" break; case 262: -#line 2402 "parse.y" /* yacc.c:1646 */ - { +#line 2426 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 7865 "parse.c" /* yacc.c:1646 */ +#line 8003 "parse.c" break; case 263: -#line 2407 "parse.y" /* yacc.c:1646 */ - { +#line 2431 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); value_expr((yyvsp[-2].node)); @@ -7879,23 +8017,23 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rescue_mod!($1, $3) %*/ } -#line 7878 "parse.c" /* yacc.c:1646 */ +#line 8016 "parse.c" break; case 264: -#line 2418 "parse.y" /* yacc.c:1646 */ - { +#line 2442 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: arg_paren!(escape_Qundef($2)) %*/ } -#line 7889 "parse.c" /* yacc.c:1646 */ +#line 8027 "parse.c" break; case 265: -#line 2425 "parse.y" /* yacc.c:1646 */ - { +#line 2449 "parse.y" + { if (!local_id(p, idFWD_REST) || #if idFWD_KWREST !local_id(p, idFWD_KWREST) || @@ -7921,89 +8059,89 @@ YYLTYPE yylloc = yyloc_default; /*% ripper: arg_paren!($2) %*/ } } -#line 7920 "parse.c" /* yacc.c:1646 */ +#line 8058 "parse.c" break; case 270: -#line 2460 "parse.y" /* yacc.c:1646 */ - { +#line 2484 "parse.y" + { (yyval.node) = (yyvsp[-1].node); } -#line 7928 "parse.c" /* yacc.c:1646 */ +#line 8066 "parse.c" break; case 271: -#line 2464 "parse.y" /* yacc.c:1646 */ - { +#line 2488 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? arg_append(p, (yyvsp[-3].node), new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].node); /*% %*/ /*% ripper: args_add!($1, bare_assoc_hash!($3)) %*/ } -#line 7939 "parse.c" /* yacc.c:1646 */ +#line 8077 "parse.c" break; case 272: -#line 2471 "parse.y" /* yacc.c:1646 */ - { +#line 2495 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? NEW_LIST(new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yylsp[-1])) : 0; /*% %*/ /*% ripper: args_add!(args_new!, bare_assoc_hash!($1)) %*/ } -#line 7950 "parse.c" /* yacc.c:1646 */ +#line 8088 "parse.c" break; case 273: -#line 2480 "parse.y" /* yacc.c:1646 */ - { +#line 2504 "parse.y" + { /*%%%*/ value_expr((yyvsp[0].node)); (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add!(args_new!, $1) %*/ } -#line 7962 "parse.c" /* yacc.c:1646 */ +#line 8100 "parse.c" break; case 274: -#line 2488 "parse.y" /* yacc.c:1646 */ - { +#line 2512 "parse.y" + { /*%%%*/ (yyval.node) = arg_blk_pass((yyvsp[-1].node), (yyvsp[0].node)); /*% %*/ /*% ripper: args_add_block!($1, $2) %*/ } -#line 7973 "parse.c" /* yacc.c:1646 */ +#line 8111 "parse.c" break; case 275: -#line 2495 "parse.y" /* yacc.c:1646 */ - { +#line 2519 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? NEW_LIST(new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yylsp[-1])) : 0; (yyval.node) = arg_blk_pass((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: args_add_block!(args_add!(args_new!, bare_assoc_hash!($1)), $2) %*/ } -#line 7985 "parse.c" /* yacc.c:1646 */ +#line 8123 "parse.c" break; case 276: -#line 2503 "parse.y" /* yacc.c:1646 */ - { +#line 2527 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node) ? arg_append(p, (yyvsp[-3].node), new_hash(p, (yyvsp[-1].node), &(yylsp[-1])), &(yyloc)) : (yyvsp[-3].node); (yyval.node) = arg_blk_pass((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: args_add_block!(args_add!($1, bare_assoc_hash!($3)), $4) %*/ } -#line 7997 "parse.c" /* yacc.c:1646 */ +#line 8135 "parse.c" break; case 278: -#line 2514 "parse.y" /* yacc.c:1646 */ - { +#line 2538 "parse.y" + { /* If call_args starts with a open paren '(' or '[', * look-ahead reading of the letters calls CMDARG_PUSH(0), * but the push must be done after CMDARG_PUSH(1). @@ -8020,12 +8158,12 @@ YYLTYPE yylloc = yyloc_default; CMDARG_PUSH(1); if (lookahead) CMDARG_PUSH(0); } -#line 8019 "parse.c" /* yacc.c:1646 */ +#line 8157 "parse.c" break; case 279: -#line 2532 "parse.y" /* yacc.c:1646 */ - { +#line 2556 "parse.y" + { /* call_args can be followed by tLBRACE_ARG (that does CMDARG_PUSH(0) in the lexer) * but the push must be done after CMDARG_POP() in the parser. * So this code does CMDARG_POP() to pop 0 pushed by tLBRACE_ARG, @@ -8042,135 +8180,135 @@ YYLTYPE yylloc = yyloc_default; if (lookahead) CMDARG_PUSH(0); (yyval.node) = (yyvsp[0].node); } -#line 8041 "parse.c" /* yacc.c:1646 */ +#line 8179 "parse.c" break; case 280: -#line 2552 "parse.y" /* yacc.c:1646 */ - { +#line 2576 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BLOCK_PASS((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: $2 %*/ } -#line 8052 "parse.c" /* yacc.c:1646 */ +#line 8190 "parse.c" break; case 281: -#line 2561 "parse.y" /* yacc.c:1646 */ - { +#line 2585 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 8060 "parse.c" /* yacc.c:1646 */ +#line 8198 "parse.c" break; case 282: -#line 2565 "parse.y" /* yacc.c:1646 */ - { +#line 2589 "parse.y" + { (yyval.node) = 0; } -#line 8068 "parse.c" /* yacc.c:1646 */ +#line 8206 "parse.c" break; case 283: -#line 2571 "parse.y" /* yacc.c:1646 */ - { +#line 2595 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add!(args_new!, $1) %*/ } -#line 8079 "parse.c" /* yacc.c:1646 */ +#line 8217 "parse.c" break; case 284: -#line 2578 "parse.y" /* yacc.c:1646 */ - { +#line 2602 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SPLAT((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add_star!(args_new!, $2) %*/ } -#line 8090 "parse.c" /* yacc.c:1646 */ +#line 8228 "parse.c" break; case 285: -#line 2585 "parse.y" /* yacc.c:1646 */ - { +#line 2609 "parse.y" + { /*%%%*/ (yyval.node) = last_arg_append(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add!($1, $3) %*/ } -#line 8101 "parse.c" /* yacc.c:1646 */ +#line 8239 "parse.c" break; case 286: -#line 2592 "parse.y" /* yacc.c:1646 */ - { +#line 2616 "parse.y" + { /*%%%*/ (yyval.node) = rest_arg_append(p, (yyvsp[-3].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add_star!($1, $4) %*/ } -#line 8112 "parse.c" /* yacc.c:1646 */ +#line 8250 "parse.c" break; case 289: -#line 2605 "parse.y" /* yacc.c:1646 */ - { +#line 2629 "parse.y" + { /*%%%*/ (yyval.node) = last_arg_append(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mrhs_add!(mrhs_new_from_args!($1), $3) %*/ } -#line 8123 "parse.c" /* yacc.c:1646 */ +#line 8261 "parse.c" break; case 290: -#line 2612 "parse.y" /* yacc.c:1646 */ - { +#line 2636 "parse.y" + { /*%%%*/ (yyval.node) = rest_arg_append(p, (yyvsp[-3].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mrhs_add_star!(mrhs_new_from_args!($1), $4) %*/ } -#line 8134 "parse.c" /* yacc.c:1646 */ +#line 8272 "parse.c" break; case 291: -#line 2619 "parse.y" /* yacc.c:1646 */ - { +#line 2643 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SPLAT((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mrhs_add_star!(mrhs_new!, $2) %*/ } -#line 8145 "parse.c" /* yacc.c:1646 */ +#line 8283 "parse.c" break; case 302: -#line 2638 "parse.y" /* yacc.c:1646 */ - { +#line 2662 "parse.y" + { /*%%%*/ (yyval.node) = NEW_FCALL((yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: method_add_arg!(fcall!($1), args_new!) %*/ } -#line 8156 "parse.c" /* yacc.c:1646 */ +#line 8294 "parse.c" break; case 303: -#line 2645 "parse.y" /* yacc.c:1646 */ - { +#line 2669 "parse.y" + { CMDARG_PUSH(0); } -#line 8164 "parse.c" /* yacc.c:1646 */ +#line 8302 "parse.c" break; case 304: -#line 2650 "parse.y" /* yacc.c:1646 */ - { +#line 2674 "parse.y" + { CMDARG_POP(); /*%%%*/ set_line_body((yyvsp[-1].node), (yylsp[-3]).end_pos.lineno); @@ -8179,278 +8317,278 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: begin!($3) %*/ } -#line 8178 "parse.c" /* yacc.c:1646 */ +#line 8316 "parse.c" break; case 305: -#line 2659 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_ENDARG);} -#line 8184 "parse.c" /* yacc.c:1646 */ +#line 2683 "parse.y" + {SET_LEX_STATE(EXPR_ENDARG);} +#line 8322 "parse.c" break; case 306: -#line 2660 "parse.y" /* yacc.c:1646 */ - { +#line 2684 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper: paren!(0) %*/ } -#line 8195 "parse.c" /* yacc.c:1646 */ +#line 8333 "parse.c" break; case 307: -#line 2666 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_ENDARG);} -#line 8201 "parse.c" /* yacc.c:1646 */ +#line 2690 "parse.y" + {SET_LEX_STATE(EXPR_ENDARG);} +#line 8339 "parse.c" break; case 308: -#line 2667 "parse.y" /* yacc.c:1646 */ - { +#line 2691 "parse.y" + { /*%%%*/ if (nd_type((yyvsp[-2].node)) == NODE_SELF) (yyvsp[-2].node)->nd_state = 0; (yyval.node) = (yyvsp[-2].node); /*% %*/ /*% ripper: paren!($2) %*/ } -#line 8213 "parse.c" /* yacc.c:1646 */ +#line 8351 "parse.c" break; case 309: -#line 2675 "parse.y" /* yacc.c:1646 */ - { +#line 2699 "parse.y" + { /*%%%*/ if (nd_type((yyvsp[-1].node)) == NODE_SELF) (yyvsp[-1].node)->nd_state = 0; (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: paren!($2) %*/ } -#line 8225 "parse.c" /* yacc.c:1646 */ +#line 8363 "parse.c" break; case 310: -#line 2683 "parse.y" /* yacc.c:1646 */ - { +#line 2707 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON2((yyvsp[-2].node), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: const_path_ref!($1, $3) %*/ } -#line 8236 "parse.c" /* yacc.c:1646 */ +#line 8374 "parse.c" break; case 311: -#line 2690 "parse.y" /* yacc.c:1646 */ - { +#line 2714 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON3((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: top_const_ref!($2) %*/ } -#line 8247 "parse.c" /* yacc.c:1646 */ +#line 8385 "parse.c" break; case 312: -#line 2697 "parse.y" /* yacc.c:1646 */ - { +#line 2721 "parse.y" + { /*%%%*/ (yyval.node) = make_list((yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: array!(escape_Qundef($2)) %*/ } -#line 8258 "parse.c" /* yacc.c:1646 */ +#line 8396 "parse.c" break; case 313: -#line 2704 "parse.y" /* yacc.c:1646 */ - { +#line 2728 "parse.y" + { /*%%%*/ (yyval.node) = new_hash(p, (yyvsp[-1].node), &(yyloc)); (yyval.node)->nd_brace = TRUE; /*% %*/ /*% ripper: hash!(escape_Qundef($2)) %*/ } -#line 8270 "parse.c" /* yacc.c:1646 */ +#line 8408 "parse.c" break; case 314: -#line 2712 "parse.y" /* yacc.c:1646 */ - { +#line 2736 "parse.y" + { /*%%%*/ (yyval.node) = NEW_RETURN(0, &(yyloc)); /*% %*/ /*% ripper: return0! %*/ } -#line 8281 "parse.c" /* yacc.c:1646 */ +#line 8419 "parse.c" break; case 315: -#line 2719 "parse.y" /* yacc.c:1646 */ - { +#line 2743 "parse.y" + { /*%%%*/ (yyval.node) = new_yield(p, (yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: yield!(paren!($3)) %*/ } -#line 8292 "parse.c" /* yacc.c:1646 */ +#line 8430 "parse.c" break; case 316: -#line 2726 "parse.y" /* yacc.c:1646 */ - { +#line 2750 "parse.y" + { /*%%%*/ (yyval.node) = NEW_YIELD(0, &(yyloc)); /*% %*/ /*% ripper: yield!(paren!(args_new!)) %*/ } -#line 8303 "parse.c" /* yacc.c:1646 */ +#line 8441 "parse.c" break; case 317: -#line 2733 "parse.y" /* yacc.c:1646 */ - { +#line 2757 "parse.y" + { /*%%%*/ (yyval.node) = NEW_YIELD(0, &(yyloc)); /*% %*/ /*% ripper: yield0! %*/ } -#line 8314 "parse.c" /* yacc.c:1646 */ +#line 8452 "parse.c" break; case 318: -#line 2739 "parse.y" /* yacc.c:1646 */ - {p->in_defined = 1;} -#line 8320 "parse.c" /* yacc.c:1646 */ +#line 2763 "parse.y" + {p->in_defined = 1;} +#line 8458 "parse.c" break; case 319: -#line 2740 "parse.y" /* yacc.c:1646 */ - { +#line 2764 "parse.y" + { p->in_defined = 0; (yyval.node) = new_defined(p, (yyvsp[-1].node), &(yyloc)); } -#line 8329 "parse.c" /* yacc.c:1646 */ +#line 8467 "parse.c" break; case 320: -#line 2745 "parse.y" /* yacc.c:1646 */ - { +#line 2769 "parse.y" + { (yyval.node) = call_uni_op(p, method_cond(p, (yyvsp[-1].node), &(yylsp[-1])), METHOD_NOT, &(yylsp[-3]), &(yyloc)); } -#line 8337 "parse.c" /* yacc.c:1646 */ +#line 8475 "parse.c" break; case 321: -#line 2749 "parse.y" /* yacc.c:1646 */ - { +#line 2773 "parse.y" + { (yyval.node) = call_uni_op(p, method_cond(p, new_nil(&(yylsp[-1])), &(yylsp[-1])), METHOD_NOT, &(yylsp[-2]), &(yyloc)); } -#line 8345 "parse.c" /* yacc.c:1646 */ +#line 8483 "parse.c" break; case 322: -#line 2753 "parse.y" /* yacc.c:1646 */ - { +#line 2777 "parse.y" + { /*%%%*/ (yyval.node) = method_add_block(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: method_add_block!(method_add_arg!(fcall!($1), args_new!), $2) %*/ } -#line 8356 "parse.c" /* yacc.c:1646 */ +#line 8494 "parse.c" break; case 324: -#line 2761 "parse.y" /* yacc.c:1646 */ - { +#line 2785 "parse.y" + { /*%%%*/ block_dup_check(p, (yyvsp[-1].node)->nd_args, (yyvsp[0].node)); (yyval.node) = method_add_block(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: method_add_block!($1, $2) %*/ } -#line 8368 "parse.c" /* yacc.c:1646 */ +#line 8506 "parse.c" break; case 325: -#line 2769 "parse.y" /* yacc.c:1646 */ - { +#line 2793 "parse.y" + { token_info_push(p, "->", &(yylsp[0])); } -#line 8376 "parse.c" /* yacc.c:1646 */ +#line 8514 "parse.c" break; case 326: -#line 2773 "parse.y" /* yacc.c:1646 */ - { +#line 2797 "parse.y" + { (yyval.node) = (yyvsp[0].node); /*%%%*/ nd_set_first_loc((yyval.node), (yylsp[-2]).beg_pos); /*% %*/ } -#line 8387 "parse.c" /* yacc.c:1646 */ +#line 8525 "parse.c" break; case 327: -#line 2783 "parse.y" /* yacc.c:1646 */ - { +#line 2807 "parse.y" + { /*%%%*/ (yyval.node) = new_if(p, (yyvsp[-4].node), (yyvsp[-2].node), (yyvsp[-1].node), &(yyloc)); fixpos((yyval.node), (yyvsp[-4].node)); /*% %*/ /*% ripper: if!($2, $4, escape_Qundef($5)) %*/ } -#line 8399 "parse.c" /* yacc.c:1646 */ +#line 8537 "parse.c" break; case 328: -#line 2794 "parse.y" /* yacc.c:1646 */ - { +#line 2818 "parse.y" + { /*%%%*/ (yyval.node) = new_unless(p, (yyvsp[-4].node), (yyvsp[-2].node), (yyvsp[-1].node), &(yyloc)); fixpos((yyval.node), (yyvsp[-4].node)); /*% %*/ /*% ripper: unless!($2, $4, escape_Qundef($5)) %*/ } -#line 8411 "parse.c" /* yacc.c:1646 */ +#line 8549 "parse.c" break; case 329: -#line 2804 "parse.y" /* yacc.c:1646 */ - { +#line 2828 "parse.y" + { /*%%%*/ (yyval.node) = NEW_WHILE(cond(p, (yyvsp[-2].node), &(yylsp[-2])), (yyvsp[-1].node), 1, &(yyloc)); fixpos((yyval.node), (yyvsp[-2].node)); /*% %*/ /*% ripper: while!($2, $3) %*/ } -#line 8423 "parse.c" /* yacc.c:1646 */ +#line 8561 "parse.c" break; case 330: -#line 2814 "parse.y" /* yacc.c:1646 */ - { +#line 2838 "parse.y" + { /*%%%*/ (yyval.node) = NEW_UNTIL(cond(p, (yyvsp[-2].node), &(yylsp[-2])), (yyvsp[-1].node), 1, &(yyloc)); fixpos((yyval.node), (yyvsp[-2].node)); /*% %*/ /*% ripper: until!($2, $3) %*/ } -#line 8435 "parse.c" /* yacc.c:1646 */ +#line 8573 "parse.c" break; case 331: -#line 2822 "parse.y" /* yacc.c:1646 */ - { +#line 2846 "parse.y" + { (yyval.val) = p->case_labels; p->case_labels = Qnil; } -#line 8444 "parse.c" /* yacc.c:1646 */ +#line 8582 "parse.c" break; case 332: -#line 2828 "parse.y" /* yacc.c:1646 */ - { +#line 2852 "parse.y" + { if (RTEST(p->case_labels)) rb_hash_clear(p->case_labels); p->case_labels = (yyvsp[-2].val); /*%%%*/ @@ -8459,21 +8597,21 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: case!($2, $5) %*/ } -#line 8458 "parse.c" /* yacc.c:1646 */ +#line 8596 "parse.c" break; case 333: -#line 2838 "parse.y" /* yacc.c:1646 */ - { +#line 2862 "parse.y" + { (yyval.val) = p->case_labels; p->case_labels = 0; } -#line 8467 "parse.c" /* yacc.c:1646 */ +#line 8605 "parse.c" break; case 334: -#line 2844 "parse.y" /* yacc.c:1646 */ - { +#line 2868 "parse.y" + { if (RTEST(p->case_labels)) rb_hash_clear(p->case_labels); p->case_labels = (yyvsp[-2].val); /*%%%*/ @@ -8481,23 +8619,23 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: case!(Qnil, $4) %*/ } -#line 8480 "parse.c" /* yacc.c:1646 */ +#line 8618 "parse.c" break; case 335: -#line 2855 "parse.y" /* yacc.c:1646 */ - { +#line 2879 "parse.y" + { /*%%%*/ (yyval.node) = new_case3(p, (yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: case!($2, $4) %*/ } -#line 8491 "parse.c" /* yacc.c:1646 */ +#line 8629 "parse.c" break; case 336: -#line 2864 "parse.y" /* yacc.c:1646 */ - { +#line 2888 "parse.y" + { /*%%%*/ /* * for a, b, c in e @@ -8541,12 +8679,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: for!($2, $4, $5) %*/ } -#line 8540 "parse.c" /* yacc.c:1646 */ +#line 8678 "parse.c" break; case 337: -#line 2909 "parse.y" /* yacc.c:1646 */ - { +#line 2933 "parse.y" + { if (p->in_def) { YYLTYPE loc = code_loc_gen(&(yylsp[-2]), &(yylsp[-1])); yyerror1(&loc, "class definition in method body"); @@ -8555,12 +8693,12 @@ YYLTYPE yylloc = yyloc_default; p->in_class = 1; local_push(p, 0); } -#line 8554 "parse.c" /* yacc.c:1646 */ +#line 8692 "parse.c" break; case 338: -#line 2920 "parse.y" /* yacc.c:1646 */ - { +#line 2944 "parse.y" + { /*%%%*/ (yyval.node) = NEW_CLASS((yyvsp[-4].node), (yyvsp[-1].node), (yyvsp[-3].node), &(yyloc)); nd_set_line((yyval.node)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8571,23 +8709,23 @@ YYLTYPE yylloc = yyloc_default; local_pop(p); p->in_class = (yyvsp[-5].num) & 1; } -#line 8570 "parse.c" /* yacc.c:1646 */ +#line 8708 "parse.c" break; case 339: -#line 2932 "parse.y" /* yacc.c:1646 */ - { +#line 2956 "parse.y" + { (yyval.num) = (p->in_class << 1) | p->in_def; p->in_def = 0; p->in_class = 0; local_push(p, 0); } -#line 8581 "parse.c" /* yacc.c:1646 */ +#line 8719 "parse.c" break; case 340: -#line 2941 "parse.y" /* yacc.c:1646 */ - { +#line 2965 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SCLASS((yyvsp[-4].node), (yyvsp[-1].node), &(yyloc)); nd_set_line((yyval.node)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8599,12 +8737,12 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-3].num) & 1; p->in_class = ((yyvsp[-3].num) >> 1) & 1; } -#line 8598 "parse.c" /* yacc.c:1646 */ +#line 8736 "parse.c" break; case 341: -#line 2954 "parse.y" /* yacc.c:1646 */ - { +#line 2978 "parse.y" + { if (p->in_def) { YYLTYPE loc = code_loc_gen(&(yylsp[-1]), &(yylsp[0])); yyerror1(&loc, "module definition in method body"); @@ -8613,12 +8751,12 @@ YYLTYPE yylloc = yyloc_default; p->in_class = 1; local_push(p, 0); } -#line 8612 "parse.c" /* yacc.c:1646 */ +#line 8750 "parse.c" break; case 342: -#line 2965 "parse.y" /* yacc.c:1646 */ - { +#line 2989 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MODULE((yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); nd_set_line((yyval.node)->nd_body, (yylsp[0]).end_pos.lineno); @@ -8629,32 +8767,32 @@ YYLTYPE yylloc = yyloc_default; local_pop(p); p->in_class = (yyvsp[-4].num) & 1; } -#line 8628 "parse.c" /* yacc.c:1646 */ +#line 8766 "parse.c" break; case 343: -#line 2977 "parse.y" /* yacc.c:1646 */ - { +#line 3001 "parse.y" + { numparam_name(p, get_id((yyvsp[0].id))); local_push(p, 0); (yyval.id) = p->cur_arg; p->cur_arg = 0; } -#line 8639 "parse.c" /* yacc.c:1646 */ +#line 8777 "parse.c" break; case 344: -#line 2983 "parse.y" /* yacc.c:1646 */ - { +#line 3007 "parse.y" + { (yyval.num) = p->in_def; p->in_def = 1; } -#line 8648 "parse.c" /* yacc.c:1646 */ +#line 8786 "parse.c" break; case 345: -#line 2990 "parse.y" /* yacc.c:1646 */ - { +#line 3014 "parse.y" + { /*%%%*/ NODE *body = remove_begin((yyvsp[-1].node)); reduce_nodes(p, &body); @@ -8667,18 +8805,18 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-3].num) & 1; p->cur_arg = (yyvsp[-4].id); } -#line 8666 "parse.c" /* yacc.c:1646 */ +#line 8804 "parse.c" break; case 346: -#line 3003 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_FNAME);} -#line 8672 "parse.c" /* yacc.c:1646 */ +#line 3027 "parse.y" + {SET_LEX_STATE(EXPR_FNAME);} +#line 8810 "parse.c" break; case 347: -#line 3004 "parse.y" /* yacc.c:1646 */ - { +#line 3028 "parse.y" + { numparam_name(p, get_id((yyvsp[0].id))); (yyvsp[-1].num) = p->in_def; p->in_def = 1; @@ -8687,12 +8825,12 @@ YYLTYPE yylloc = yyloc_default; (yyval.id) = p->cur_arg; p->cur_arg = 0; } -#line 8686 "parse.c" /* yacc.c:1646 */ +#line 8824 "parse.c" break; case 348: -#line 3016 "parse.y" /* yacc.c:1646 */ - { +#line 3040 "parse.y" + { /*%%%*/ NODE *body = remove_begin((yyvsp[-1].node)); reduce_nodes(p, &body); @@ -8705,73 +8843,73 @@ YYLTYPE yylloc = yyloc_default; p->in_def = (yyvsp[-5].num) & 1; p->cur_arg = (yyvsp[-3].id); } -#line 8704 "parse.c" /* yacc.c:1646 */ +#line 8842 "parse.c" break; case 349: -#line 3030 "parse.y" /* yacc.c:1646 */ - { +#line 3054 "parse.y" + { /*%%%*/ (yyval.node) = NEW_BREAK(0, &(yyloc)); /*% %*/ /*% ripper: break!(args_new!) %*/ } -#line 8715 "parse.c" /* yacc.c:1646 */ +#line 8853 "parse.c" break; case 350: -#line 3037 "parse.y" /* yacc.c:1646 */ - { +#line 3061 "parse.y" + { /*%%%*/ (yyval.node) = NEW_NEXT(0, &(yyloc)); /*% %*/ /*% ripper: next!(args_new!) %*/ } -#line 8726 "parse.c" /* yacc.c:1646 */ +#line 8864 "parse.c" break; case 351: -#line 3044 "parse.y" /* yacc.c:1646 */ - { +#line 3068 "parse.y" + { /*%%%*/ (yyval.node) = NEW_REDO(&(yyloc)); /*% %*/ /*% ripper: redo! %*/ } -#line 8737 "parse.c" /* yacc.c:1646 */ +#line 8875 "parse.c" break; case 352: -#line 3051 "parse.y" /* yacc.c:1646 */ - { +#line 3075 "parse.y" + { /*%%%*/ (yyval.node) = NEW_RETRY(&(yyloc)); /*% %*/ /*% ripper: retry! %*/ } -#line 8748 "parse.c" /* yacc.c:1646 */ +#line 8886 "parse.c" break; case 353: -#line 3060 "parse.y" /* yacc.c:1646 */ - { +#line 3084 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 8757 "parse.c" /* yacc.c:1646 */ +#line 8895 "parse.c" break; case 354: -#line 3067 "parse.y" /* yacc.c:1646 */ - { +#line 3091 "parse.y" + { token_info_push(p, "begin", &(yyloc)); } -#line 8765 "parse.c" /* yacc.c:1646 */ +#line 8903 "parse.c" break; case 355: -#line 3073 "parse.y" /* yacc.c:1646 */ - { +#line 3097 "parse.y" + { WARN_EOL("if"); token_info_push(p, "if", &(yyloc)); if (p->token_info && p->token_info->nonspc && @@ -8785,116 +8923,116 @@ YYLTYPE yylloc = yyloc_default; } } } -#line 8784 "parse.c" /* yacc.c:1646 */ +#line 8922 "parse.c" break; case 356: -#line 3090 "parse.y" /* yacc.c:1646 */ - { +#line 3114 "parse.y" + { token_info_push(p, "unless", &(yyloc)); } -#line 8792 "parse.c" /* yacc.c:1646 */ +#line 8930 "parse.c" break; case 357: -#line 3096 "parse.y" /* yacc.c:1646 */ - { +#line 3120 "parse.y" + { token_info_push(p, "while", &(yyloc)); } -#line 8800 "parse.c" /* yacc.c:1646 */ +#line 8938 "parse.c" break; case 358: -#line 3102 "parse.y" /* yacc.c:1646 */ - { +#line 3126 "parse.y" + { token_info_push(p, "until", &(yyloc)); } -#line 8808 "parse.c" /* yacc.c:1646 */ +#line 8946 "parse.c" break; case 359: -#line 3108 "parse.y" /* yacc.c:1646 */ - { +#line 3132 "parse.y" + { token_info_push(p, "case", &(yyloc)); } -#line 8816 "parse.c" /* yacc.c:1646 */ +#line 8954 "parse.c" break; case 360: -#line 3114 "parse.y" /* yacc.c:1646 */ - { +#line 3138 "parse.y" + { token_info_push(p, "for", &(yyloc)); } -#line 8824 "parse.c" /* yacc.c:1646 */ +#line 8962 "parse.c" break; case 361: -#line 3120 "parse.y" /* yacc.c:1646 */ - { +#line 3144 "parse.y" + { token_info_push(p, "class", &(yyloc)); } -#line 8832 "parse.c" /* yacc.c:1646 */ +#line 8970 "parse.c" break; case 362: -#line 3126 "parse.y" /* yacc.c:1646 */ - { +#line 3150 "parse.y" + { token_info_push(p, "module", &(yyloc)); } -#line 8840 "parse.c" /* yacc.c:1646 */ +#line 8978 "parse.c" break; case 363: -#line 3132 "parse.y" /* yacc.c:1646 */ - { +#line 3156 "parse.y" + { token_info_push(p, "def", &(yyloc)); } -#line 8848 "parse.c" /* yacc.c:1646 */ +#line 8986 "parse.c" break; case 364: -#line 3138 "parse.y" /* yacc.c:1646 */ - { +#line 3162 "parse.y" + { token_info_push(p, "do", &(yyloc)); } -#line 8856 "parse.c" /* yacc.c:1646 */ +#line 8994 "parse.c" break; case 365: -#line 3144 "parse.y" /* yacc.c:1646 */ - { +#line 3168 "parse.y" + { token_info_push(p, "do", &(yyloc)); } -#line 8864 "parse.c" /* yacc.c:1646 */ +#line 9002 "parse.c" break; case 366: -#line 3150 "parse.y" /* yacc.c:1646 */ - { +#line 3174 "parse.y" + { token_info_warn(p, "rescue", p->token_info, 1, &(yyloc)); } -#line 8872 "parse.c" /* yacc.c:1646 */ +#line 9010 "parse.c" break; case 367: -#line 3156 "parse.y" /* yacc.c:1646 */ - { +#line 3180 "parse.y" + { token_info_warn(p, "ensure", p->token_info, 1, &(yyloc)); } -#line 8880 "parse.c" /* yacc.c:1646 */ +#line 9018 "parse.c" break; case 368: -#line 3162 "parse.y" /* yacc.c:1646 */ - { +#line 3186 "parse.y" + { token_info_warn(p, "when", p->token_info, 0, &(yyloc)); } -#line 8888 "parse.c" /* yacc.c:1646 */ +#line 9026 "parse.c" break; case 369: -#line 3168 "parse.y" /* yacc.c:1646 */ - { +#line 3192 "parse.y" + { token_info *ptinfo_beg = p->token_info; int same = ptinfo_beg && strcmp(ptinfo_beg->token, "case") != 0; token_info_warn(p, "else", p->token_info, same, &(yyloc)); @@ -8906,372 +9044,372 @@ YYLTYPE yylloc = yyloc_default; if (!e.nonspc) *ptinfo_beg = e; } } -#line 8905 "parse.c" /* yacc.c:1646 */ +#line 9043 "parse.c" break; case 370: -#line 3183 "parse.y" /* yacc.c:1646 */ - { +#line 3207 "parse.y" + { WARN_EOL("elsif"); token_info_warn(p, "elsif", p->token_info, 1, &(yyloc)); } -#line 8914 "parse.c" /* yacc.c:1646 */ +#line 9052 "parse.c" break; case 371: -#line 3190 "parse.y" /* yacc.c:1646 */ - { +#line 3214 "parse.y" + { token_info_pop(p, "end", &(yyloc)); } -#line 8922 "parse.c" /* yacc.c:1646 */ +#line 9060 "parse.c" break; case 372: -#line 3196 "parse.y" /* yacc.c:1646 */ - { +#line 3220 "parse.y" + { if (p->in_class && !p->in_def && !dyna_in_block(p)) yyerror1(&(yylsp[0]), "Invalid return in class/module body"); } -#line 8931 "parse.c" /* yacc.c:1646 */ +#line 9069 "parse.c" break; case 379: -#line 3215 "parse.y" /* yacc.c:1646 */ - { +#line 3239 "parse.y" + { /*%%%*/ (yyval.node) = new_if(p, (yyvsp[-3].node), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); fixpos((yyval.node), (yyvsp[-3].node)); /*% %*/ /*% ripper: elsif!($2, $4, escape_Qundef($5)) %*/ } -#line 8943 "parse.c" /* yacc.c:1646 */ +#line 9081 "parse.c" break; case 381: -#line 3226 "parse.y" /* yacc.c:1646 */ - { +#line 3250 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: else!($2) %*/ } -#line 8954 "parse.c" /* yacc.c:1646 */ +#line 9092 "parse.c" break; case 384: -#line 3239 "parse.y" /* yacc.c:1646 */ - { +#line 3263 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); mark_lvar_used(p, (yyval.node)); /*% %*/ /*% ripper: assignable(p, $1) %*/ } -#line 8966 "parse.c" /* yacc.c:1646 */ +#line 9104 "parse.c" break; case 385: -#line 3247 "parse.y" /* yacc.c:1646 */ - { +#line 3271 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: mlhs_paren!($2) %*/ } -#line 8977 "parse.c" /* yacc.c:1646 */ +#line 9115 "parse.c" break; case 386: -#line 3256 "parse.y" /* yacc.c:1646 */ - { +#line 3280 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add!(mlhs_new!, $1) %*/ } -#line 8988 "parse.c" /* yacc.c:1646 */ +#line 9126 "parse.c" break; case 387: -#line 3263 "parse.y" /* yacc.c:1646 */ - { +#line 3287 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, (yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: mlhs_add!($1, $3) %*/ } -#line 8999 "parse.c" /* yacc.c:1646 */ +#line 9137 "parse.c" break; case 388: -#line 3272 "parse.y" /* yacc.c:1646 */ - { +#line 3296 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[0].node), 0, &(yyloc)); /*% %*/ /*% ripper: $1 %*/ } -#line 9010 "parse.c" /* yacc.c:1646 */ +#line 9148 "parse.c" break; case 389: -#line 3279 "parse.y" /* yacc.c:1646 */ - { +#line 3303 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!($1, $3) %*/ } -#line 9021 "parse.c" /* yacc.c:1646 */ +#line 9159 "parse.c" break; case 390: -#line 3286 "parse.y" /* yacc.c:1646 */ - { +#line 3310 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN((yyvsp[-4].node), NEW_POSTARG((yyvsp[-2].node), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!($1, $3), $5) %*/ } -#line 9032 "parse.c" /* yacc.c:1646 */ +#line 9170 "parse.c" break; case 391: -#line 3293 "parse.y" /* yacc.c:1646 */ - { +#line 3317 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_star!(mlhs_new!, $1) %*/ } -#line 9043 "parse.c" /* yacc.c:1646 */ +#line 9181 "parse.c" break; case 392: -#line 3300 "parse.y" /* yacc.c:1646 */ - { +#line 3324 "parse.y" + { /*%%%*/ (yyval.node) = NEW_MASGN(0, NEW_POSTARG((yyvsp[-2].node), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $1), $3) %*/ } -#line 9054 "parse.c" /* yacc.c:1646 */ +#line 9192 "parse.c" break; case 393: -#line 3309 "parse.y" /* yacc.c:1646 */ - { +#line 3333 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); mark_lvar_used(p, (yyval.node)); /*% %*/ /*% ripper: assignable(p, $2) %*/ } -#line 9066 "parse.c" /* yacc.c:1646 */ +#line 9204 "parse.c" break; case 394: -#line 3317 "parse.y" /* yacc.c:1646 */ - { +#line 3341 "parse.y" + { /*%%%*/ (yyval.node) = NODE_SPECIAL_NO_NAME_REST; /*% %*/ /*% ripper: Qnil %*/ } -#line 9077 "parse.c" /* yacc.c:1646 */ +#line 9215 "parse.c" break; case 395: -#line 3326 "parse.y" /* yacc.c:1646 */ - { +#line 3350 "parse.y" + { (yyval.node) = new_args_tail(p, (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].id), &(yylsp[-1])); } -#line 9085 "parse.c" /* yacc.c:1646 */ +#line 9223 "parse.c" break; case 396: -#line 3330 "parse.y" /* yacc.c:1646 */ - { +#line 3354 "parse.y" + { (yyval.node) = new_args_tail(p, (yyvsp[-1].node), Qnone, (yyvsp[0].id), &(yylsp[-1])); } -#line 9093 "parse.c" /* yacc.c:1646 */ +#line 9231 "parse.c" break; case 397: -#line 3334 "parse.y" /* yacc.c:1646 */ - { +#line 3358 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, (yyvsp[-1].id), (yyvsp[0].id), &(yylsp[-1])); } -#line 9101 "parse.c" /* yacc.c:1646 */ +#line 9239 "parse.c" break; case 398: -#line 3338 "parse.y" /* yacc.c:1646 */ - { +#line 3362 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, ID2VAL(idNil), (yyvsp[0].id), &(yylsp[-1])); } -#line 9109 "parse.c" /* yacc.c:1646 */ +#line 9247 "parse.c" break; case 399: -#line 3342 "parse.y" /* yacc.c:1646 */ - { +#line 3366 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, Qnone, (yyvsp[0].id), &(yylsp[0])); } -#line 9117 "parse.c" /* yacc.c:1646 */ +#line 9255 "parse.c" break; case 400: -#line 3348 "parse.y" /* yacc.c:1646 */ - { +#line 3372 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 9125 "parse.c" /* yacc.c:1646 */ +#line 9263 "parse.c" break; case 401: -#line 3352 "parse.y" /* yacc.c:1646 */ - { +#line 3376 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); } -#line 9133 "parse.c" /* yacc.c:1646 */ +#line 9271 "parse.c" break; case 402: -#line 3358 "parse.y" /* yacc.c:1646 */ - { +#line 3382 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), (yyvsp[-3].node), (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9141 "parse.c" /* yacc.c:1646 */ +#line 9279 "parse.c" break; case 403: -#line 3362 "parse.y" /* yacc.c:1646 */ - { +#line 3386 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-7].node), (yyvsp[-5].node), (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9149 "parse.c" /* yacc.c:1646 */ +#line 9287 "parse.c" break; case 404: -#line 3366 "parse.y" /* yacc.c:1646 */ - { +#line 3390 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-3].node), (yyvsp[-1].node), Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9157 "parse.c" /* yacc.c:1646 */ +#line 9295 "parse.c" break; case 405: -#line 3370 "parse.y" /* yacc.c:1646 */ - { +#line 3394 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), (yyvsp[-3].node), Qnone, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9165 "parse.c" /* yacc.c:1646 */ +#line 9303 "parse.c" break; case 406: -#line 3374 "parse.y" /* yacc.c:1646 */ - { +#line 3398 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-3].node), Qnone, (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9173 "parse.c" /* yacc.c:1646 */ +#line 9311 "parse.c" break; case 407: -#line 3378 "parse.y" /* yacc.c:1646 */ - { +#line 3402 "parse.y" + { /*%%%*/ /* magic number for rest_id in iseq_set_arguments() */ (yyval.node) = new_args(p, (yyvsp[-1].node), Qnone, NODE_SPECIAL_EXCESSIVE_COMMA, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[-1])), &(yyloc)); /*% %*/ /*% ripper: new_args(p, $1, Qnone, excessed_comma!, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, NULL), NULL) %*/ } -#line 9185 "parse.c" /* yacc.c:1646 */ +#line 9323 "parse.c" break; case 408: -#line 3386 "parse.y" /* yacc.c:1646 */ - { +#line 3410 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), Qnone, (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9193 "parse.c" /* yacc.c:1646 */ +#line 9331 "parse.c" break; case 409: -#line 3390 "parse.y" /* yacc.c:1646 */ - { +#line 3414 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-1].node), Qnone, Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9201 "parse.c" /* yacc.c:1646 */ +#line 9339 "parse.c" break; case 410: -#line 3394 "parse.y" /* yacc.c:1646 */ - { +#line 3418 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-3].node), (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9209 "parse.c" /* yacc.c:1646 */ +#line 9347 "parse.c" break; case 411: -#line 3398 "parse.y" /* yacc.c:1646 */ - { +#line 3422 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-5].node), (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9217 "parse.c" /* yacc.c:1646 */ +#line 9355 "parse.c" break; case 412: -#line 3402 "parse.y" /* yacc.c:1646 */ - { +#line 3426 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-1].node), Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9225 "parse.c" /* yacc.c:1646 */ +#line 9363 "parse.c" break; case 413: -#line 3406 "parse.y" /* yacc.c:1646 */ - { +#line 3430 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-3].node), Qnone, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9233 "parse.c" /* yacc.c:1646 */ +#line 9371 "parse.c" break; case 414: -#line 3410 "parse.y" /* yacc.c:1646 */ - { +#line 3434 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9241 "parse.c" /* yacc.c:1646 */ +#line 9379 "parse.c" break; case 415: -#line 3414 "parse.y" /* yacc.c:1646 */ - { +#line 3438 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 9249 "parse.c" /* yacc.c:1646 */ +#line 9387 "parse.c" break; case 416: -#line 3418 "parse.y" /* yacc.c:1646 */ - { +#line 3442 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9257 "parse.c" /* yacc.c:1646 */ +#line 9395 "parse.c" break; case 418: -#line 3425 "parse.y" /* yacc.c:1646 */ - { +#line 3449 "parse.y" + { p->command_start = TRUE; } -#line 9265 "parse.c" /* yacc.c:1646 */ +#line 9403 "parse.c" break; case 419: -#line 3431 "parse.y" /* yacc.c:1646 */ - { +#line 3455 "parse.y" + { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; /*%%%*/ @@ -9279,12 +9417,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: block_var!(params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), escape_Qundef($2)) %*/ } -#line 9278 "parse.c" /* yacc.c:1646 */ +#line 9416 "parse.c" break; case 420: -#line 3440 "parse.y" /* yacc.c:1646 */ - { +#line 3464 "parse.y" + { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; /*%%%*/ @@ -9292,90 +9430,90 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: block_var!(escape_Qundef($2), escape_Qundef($3)) %*/ } -#line 9291 "parse.c" /* yacc.c:1646 */ +#line 9429 "parse.c" break; case 421: -#line 3452 "parse.y" /* yacc.c:1646 */ - { +#line 3476 "parse.y" + { (yyval.node) = 0; } -#line 9299 "parse.c" /* yacc.c:1646 */ +#line 9437 "parse.c" break; case 422: -#line 3456 "parse.y" /* yacc.c:1646 */ - { +#line 3480 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: $3 %*/ } -#line 9310 "parse.c" /* yacc.c:1646 */ +#line 9448 "parse.c" break; case 425: -#line 3471 "parse.y" /* yacc.c:1646 */ - { +#line 3495 "parse.y" + { new_bv(p, get_id((yyvsp[0].id))); /*% ripper: get_value($1) %*/ } -#line 9319 "parse.c" /* yacc.c:1646 */ +#line 9457 "parse.c" break; case 426: -#line 3476 "parse.y" /* yacc.c:1646 */ - { +#line 3500 "parse.y" + { (yyval.node) = 0; } -#line 9327 "parse.c" /* yacc.c:1646 */ +#line 9465 "parse.c" break; case 427: -#line 3481 "parse.y" /* yacc.c:1646 */ - { +#line 3505 "parse.y" + { (yyval.vars) = dyna_push(p); } -#line 9335 "parse.c" /* yacc.c:1646 */ +#line 9473 "parse.c" break; case 428: -#line 3484 "parse.y" /* yacc.c:1646 */ - { +#line 3508 "parse.y" + { (yyval.num) = p->lex.lpar_beg; p->lex.lpar_beg = p->lex.paren_nest; } -#line 9344 "parse.c" /* yacc.c:1646 */ +#line 9482 "parse.c" break; case 429: -#line 3488 "parse.y" /* yacc.c:1646 */ - { +#line 3512 "parse.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9353 "parse.c" /* yacc.c:1646 */ +#line 9491 "parse.c" break; case 430: -#line 3492 "parse.y" /* yacc.c:1646 */ - { +#line 3516 "parse.y" + { (yyval.node) = numparam_push(p); } -#line 9361 "parse.c" /* yacc.c:1646 */ +#line 9499 "parse.c" break; case 431: -#line 3496 "parse.y" /* yacc.c:1646 */ - { +#line 3520 "parse.y" + { CMDARG_PUSH(0); } -#line 9369 "parse.c" /* yacc.c:1646 */ +#line 9507 "parse.c" break; case 432: -#line 3500 "parse.y" /* yacc.c:1646 */ - { +#line 3524 "parse.y" + { int max_numparam = p->max_numparam; p->lex.lpar_beg = (yyvsp[-5].num); p->max_numparam = (yyvsp[-4].num); @@ -9393,65 +9531,65 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-3].node)); dyna_pop(p, (yyvsp[-6].vars)); } -#line 9392 "parse.c" /* yacc.c:1646 */ +#line 9530 "parse.c" break; case 433: -#line 3521 "parse.y" /* yacc.c:1646 */ - { +#line 3545 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-2].node); p->max_numparam = ORDINAL_PARAM; /*% %*/ /*% ripper: paren!($2) %*/ } -#line 9404 "parse.c" /* yacc.c:1646 */ +#line 9542 "parse.c" break; case 434: -#line 3529 "parse.y" /* yacc.c:1646 */ - { +#line 3553 "parse.y" + { /*%%%*/ if (!args_info_empty_p((yyvsp[0].node)->nd_ainfo)) p->max_numparam = ORDINAL_PARAM; /*% %*/ (yyval.node) = (yyvsp[0].node); } -#line 9416 "parse.c" /* yacc.c:1646 */ +#line 9554 "parse.c" break; case 435: -#line 3539 "parse.y" /* yacc.c:1646 */ - { +#line 3563 "parse.y" + { token_info_pop(p, "}", &(yylsp[0])); (yyval.node) = (yyvsp[-1].node); } -#line 9425 "parse.c" /* yacc.c:1646 */ +#line 9563 "parse.c" break; case 436: -#line 3544 "parse.y" /* yacc.c:1646 */ - { +#line 3568 "parse.y" + { (yyval.node) = (yyvsp[-1].node); } -#line 9433 "parse.c" /* yacc.c:1646 */ +#line 9571 "parse.c" break; case 437: -#line 3550 "parse.y" /* yacc.c:1646 */ - { +#line 3574 "parse.y" + { (yyval.node) = (yyvsp[-1].node); /*%%%*/ (yyval.node)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.node), (yylsp[-2]).end_pos.lineno); /*% %*/ } -#line 9445 "parse.c" /* yacc.c:1646 */ +#line 9583 "parse.c" break; case 438: -#line 3560 "parse.y" /* yacc.c:1646 */ - { +#line 3584 "parse.y" + { /*%%%*/ if (nd_type((yyvsp[-1].node)) == NODE_YIELD) { compile_error(p, "block given to yield"); @@ -9464,45 +9602,45 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: method_add_block!($1, $2) %*/ } -#line 9463 "parse.c" /* yacc.c:1646 */ +#line 9601 "parse.c" break; case 439: -#line 3574 "parse.y" /* yacc.c:1646 */ - { +#line 3598 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, (yyvsp[-2].id), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); /*% %*/ /*% ripper: opt_event(:method_add_arg!, call!($1, $2, $3), $4) %*/ } -#line 9474 "parse.c" /* yacc.c:1646 */ +#line 9612 "parse.c" break; case 440: -#line 3581 "parse.y" /* yacc.c:1646 */ - { +#line 3605 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, (yyvsp[-3].id), (yyvsp[-4].node), (yyvsp[-2].id), (yyvsp[-1].node), (yyvsp[0].node), &(yylsp[-2]), &(yyloc)); /*% %*/ /*% ripper: opt_event(:method_add_block!, command_call!($1, $2, $3, $4), $5) %*/ } -#line 9485 "parse.c" /* yacc.c:1646 */ +#line 9623 "parse.c" break; case 441: -#line 3588 "parse.y" /* yacc.c:1646 */ - { +#line 3612 "parse.y" + { /*%%%*/ (yyval.node) = new_command_qcall(p, (yyvsp[-3].id), (yyvsp[-4].node), (yyvsp[-2].id), (yyvsp[-1].node), (yyvsp[0].node), &(yylsp[-2]), &(yyloc)); /*% %*/ /*% ripper: method_add_block!(command_call!($1, $2, $3, $4), $5) %*/ } -#line 9496 "parse.c" /* yacc.c:1646 */ +#line 9634 "parse.c" break; case 442: -#line 3597 "parse.y" /* yacc.c:1646 */ - { +#line 3621 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); (yyval.node)->nd_args = (yyvsp[0].node); @@ -9510,93 +9648,93 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: method_add_arg!(fcall!($1), $2) %*/ } -#line 9509 "parse.c" /* yacc.c:1646 */ +#line 9647 "parse.c" break; case 443: -#line 3606 "parse.y" /* yacc.c:1646 */ - { +#line 3630 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, (yyvsp[-2].id), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.node), (yylsp[-1]).end_pos.lineno); /*% %*/ /*% ripper: opt_event(:method_add_arg!, call!($1, $2, $3), $4) %*/ } -#line 9521 "parse.c" /* yacc.c:1646 */ +#line 9659 "parse.c" break; case 444: -#line 3614 "parse.y" /* yacc.c:1646 */ - { +#line 3638 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.node), (yylsp[-1]).end_pos.lineno); /*% %*/ /*% ripper: method_add_arg!(call!($1, ID2VAL(idCOLON2), $3), $4) %*/ } -#line 9533 "parse.c" /* yacc.c:1646 */ +#line 9671 "parse.c" break; case 445: -#line 3622 "parse.y" /* yacc.c:1646 */ - { +#line 3646 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-2].node), (yyvsp[0].id), Qnull, &(yylsp[0]), &(yyloc)); /*% %*/ /*% ripper: call!($1, ID2VAL(idCOLON2), $3) %*/ } -#line 9544 "parse.c" /* yacc.c:1646 */ +#line 9682 "parse.c" break; case 446: -#line 3629 "parse.y" /* yacc.c:1646 */ - { +#line 3653 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, (yyvsp[-1].id), (yyvsp[-2].node), ID2VAL(idCall), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.node), (yylsp[-1]).end_pos.lineno); /*% %*/ /*% ripper: method_add_arg!(call!($1, $2, ID2VAL(idCall)), $3) %*/ } -#line 9556 "parse.c" /* yacc.c:1646 */ +#line 9694 "parse.c" break; case 447: -#line 3637 "parse.y" /* yacc.c:1646 */ - { +#line 3661 "parse.y" + { /*%%%*/ (yyval.node) = new_qcall(p, ID2VAL(idCOLON2), (yyvsp[-2].node), ID2VAL(idCall), (yyvsp[0].node), &(yylsp[-1]), &(yyloc)); nd_set_line((yyval.node), (yylsp[-1]).end_pos.lineno); /*% %*/ /*% ripper: method_add_arg!(call!($1, ID2VAL(idCOLON2), ID2VAL(idCall)), $3) %*/ } -#line 9568 "parse.c" /* yacc.c:1646 */ +#line 9706 "parse.c" break; case 448: -#line 3645 "parse.y" /* yacc.c:1646 */ - { +#line 3669 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SUPER((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: super!($2) %*/ } -#line 9579 "parse.c" /* yacc.c:1646 */ +#line 9717 "parse.c" break; case 449: -#line 3652 "parse.y" /* yacc.c:1646 */ - { +#line 3676 "parse.y" + { /*%%%*/ (yyval.node) = NEW_ZSUPER(&(yyloc)); /*% %*/ /*% ripper: zsuper! %*/ } -#line 9590 "parse.c" /* yacc.c:1646 */ +#line 9728 "parse.c" break; case 450: -#line 3659 "parse.y" /* yacc.c:1646 */ - { +#line 3683 "parse.y" + { /*%%%*/ if ((yyvsp[-3].node) && nd_type((yyvsp[-3].node)) == NODE_SELF) (yyval.node) = NEW_FCALL(tAREF, (yyvsp[-1].node), &(yyloc)); @@ -9606,59 +9744,59 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: aref!($1, escape_Qundef($3)) %*/ } -#line 9605 "parse.c" /* yacc.c:1646 */ +#line 9743 "parse.c" break; case 451: -#line 3672 "parse.y" /* yacc.c:1646 */ - { +#line 3696 "parse.y" + { (yyval.node) = (yyvsp[-1].node); /*%%%*/ (yyval.node)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.node), (yylsp[-2]).end_pos.lineno); /*% %*/ } -#line 9617 "parse.c" /* yacc.c:1646 */ +#line 9755 "parse.c" break; case 452: -#line 3680 "parse.y" /* yacc.c:1646 */ - { +#line 3704 "parse.y" + { (yyval.node) = (yyvsp[-1].node); /*%%%*/ (yyval.node)->nd_body->nd_loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); nd_set_line((yyval.node), (yylsp[-2]).end_pos.lineno); /*% %*/ } -#line 9629 "parse.c" /* yacc.c:1646 */ +#line 9767 "parse.c" break; case 453: -#line 3689 "parse.y" /* yacc.c:1646 */ - {(yyval.vars) = dyna_push(p);} -#line 9635 "parse.c" /* yacc.c:1646 */ +#line 3713 "parse.y" + {(yyval.vars) = dyna_push(p);} +#line 9773 "parse.c" break; case 454: -#line 3690 "parse.y" /* yacc.c:1646 */ - { +#line 3714 "parse.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9644 "parse.c" /* yacc.c:1646 */ +#line 9782 "parse.c" break; case 455: -#line 3694 "parse.y" /* yacc.c:1646 */ - { +#line 3718 "parse.y" + { (yyval.node) = numparam_push(p); } -#line 9652 "parse.c" /* yacc.c:1646 */ +#line 9790 "parse.c" break; case 456: -#line 3698 "parse.y" /* yacc.c:1646 */ - { +#line 3722 "parse.y" + { int max_numparam = p->max_numparam; p->max_numparam = (yyvsp[-3].num); (yyvsp[-1].node) = args_with_numbered(p, (yyvsp[-1].node), max_numparam); @@ -9669,36 +9807,36 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-2].node)); dyna_pop(p, (yyvsp[-4].vars)); } -#line 9668 "parse.c" /* yacc.c:1646 */ +#line 9806 "parse.c" break; case 457: -#line 3711 "parse.y" /* yacc.c:1646 */ - {(yyval.vars) = dyna_push(p);} -#line 9674 "parse.c" /* yacc.c:1646 */ +#line 3735 "parse.y" + {(yyval.vars) = dyna_push(p);} +#line 9812 "parse.c" break; case 458: -#line 3712 "parse.y" /* yacc.c:1646 */ - { +#line 3736 "parse.y" + { (yyval.num) = p->max_numparam; p->max_numparam = 0; } -#line 9683 "parse.c" /* yacc.c:1646 */ +#line 9821 "parse.c" break; case 459: -#line 3716 "parse.y" /* yacc.c:1646 */ - { +#line 3740 "parse.y" + { (yyval.node) = numparam_push(p); CMDARG_PUSH(0); } -#line 9692 "parse.c" /* yacc.c:1646 */ +#line 9830 "parse.c" break; case 460: -#line 3721 "parse.y" /* yacc.c:1646 */ - { +#line 3745 "parse.y" + { int max_numparam = p->max_numparam; p->max_numparam = (yyvsp[-3].num); (yyvsp[-1].node) = args_with_numbered(p, (yyvsp[-1].node), max_numparam); @@ -9710,185 +9848,185 @@ YYLTYPE yylloc = yyloc_default; numparam_pop(p, (yyvsp[-2].node)); dyna_pop(p, (yyvsp[-4].vars)); } -#line 9709 "parse.c" /* yacc.c:1646 */ +#line 9847 "parse.c" break; case 461: -#line 3736 "parse.y" /* yacc.c:1646 */ - { +#line 3760 "parse.y" + { /*%%%*/ check_literal_when(p, (yyvsp[0].node), &(yylsp[0])); (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add!(args_new!, $1) %*/ } -#line 9721 "parse.c" /* yacc.c:1646 */ +#line 9859 "parse.c" break; case 462: -#line 3744 "parse.y" /* yacc.c:1646 */ - { +#line 3768 "parse.y" + { /*%%%*/ (yyval.node) = NEW_SPLAT((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add_star!(args_new!, $2) %*/ } -#line 9732 "parse.c" /* yacc.c:1646 */ +#line 9870 "parse.c" break; case 463: -#line 3751 "parse.y" /* yacc.c:1646 */ - { +#line 3775 "parse.y" + { /*%%%*/ check_literal_when(p, (yyvsp[0].node), &(yylsp[0])); (yyval.node) = last_arg_append(p, (yyvsp[-2].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add!($1, $3) %*/ } -#line 9744 "parse.c" /* yacc.c:1646 */ +#line 9882 "parse.c" break; case 464: -#line 3759 "parse.y" /* yacc.c:1646 */ - { +#line 3783 "parse.y" + { /*%%%*/ (yyval.node) = rest_arg_append(p, (yyvsp[-3].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: args_add_star!($1, $4) %*/ } -#line 9755 "parse.c" /* yacc.c:1646 */ +#line 9893 "parse.c" break; case 465: -#line 3770 "parse.y" /* yacc.c:1646 */ - { +#line 3794 "parse.y" + { /*%%%*/ (yyval.node) = NEW_WHEN((yyvsp[-3].node), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); fixpos((yyval.node), (yyvsp[-3].node)); /*% %*/ /*% ripper: when!($2, $4, escape_Qundef($5)) %*/ } -#line 9767 "parse.c" /* yacc.c:1646 */ +#line 9905 "parse.c" break; case 468: -#line 3784 "parse.y" /* yacc.c:1646 */ - { +#line 3808 "parse.y" + { SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; (yyval.num) = p->in_kwarg; p->in_kwarg = 1; } -#line 9778 "parse.c" /* yacc.c:1646 */ +#line 9916 "parse.c" break; case 469: -#line 3790 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pvtbl(p);} -#line 9784 "parse.c" /* yacc.c:1646 */ +#line 3814 "parse.y" + {(yyval.tbl) = push_pvtbl(p);} +#line 9922 "parse.c" break; case 470: -#line 3791 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9790 "parse.c" /* yacc.c:1646 */ +#line 3815 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 9928 "parse.c" break; case 471: -#line 3793 "parse.y" /* yacc.c:1646 */ - {pop_pktbl(p, (yyvsp[-2].tbl));} -#line 9796 "parse.c" /* yacc.c:1646 */ +#line 3817 "parse.y" + {pop_pktbl(p, (yyvsp[-2].tbl));} +#line 9934 "parse.c" break; case 472: -#line 3794 "parse.y" /* yacc.c:1646 */ - {pop_pvtbl(p, (yyvsp[-4].tbl));} -#line 9802 "parse.c" /* yacc.c:1646 */ +#line 3818 "parse.y" + {pop_pvtbl(p, (yyvsp[-4].tbl));} +#line 9940 "parse.c" break; case 473: -#line 3795 "parse.y" /* yacc.c:1646 */ - { +#line 3819 "parse.y" + { p->in_kwarg = !!(yyvsp[-6].num); } -#line 9810 "parse.c" /* yacc.c:1646 */ +#line 9948 "parse.c" break; case 474: -#line 3800 "parse.y" /* yacc.c:1646 */ - { +#line 3824 "parse.y" + { /*%%%*/ (yyval.node) = NEW_IN((yyvsp[-6].node), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: in!($5, $10, escape_Qundef($11)) %*/ } -#line 9821 "parse.c" /* yacc.c:1646 */ +#line 9959 "parse.c" break; case 478: -#line 3814 "parse.y" /* yacc.c:1646 */ - { +#line 3838 "parse.y" + { /*%%%*/ (yyval.node) = new_if(p, (yyvsp[0].node), remove_begin((yyvsp[-2].node)), 0, &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: if_mod!($3, $1) %*/ } -#line 9833 "parse.c" /* yacc.c:1646 */ +#line 9971 "parse.c" break; case 479: -#line 3822 "parse.y" /* yacc.c:1646 */ - { +#line 3846 "parse.y" + { /*%%%*/ (yyval.node) = new_unless(p, (yyvsp[0].node), remove_begin((yyvsp[-2].node)), 0, &(yyloc)); fixpos((yyval.node), (yyvsp[0].node)); /*% %*/ /*% ripper: unless_mod!($3, $1) %*/ } -#line 9845 "parse.c" /* yacc.c:1646 */ +#line 9983 "parse.c" break; case 481: -#line 3833 "parse.y" /* yacc.c:1646 */ - { +#line 3857 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &(yyloc)); (yyval.node) = new_array_pattern(p, Qnone, get_value((yyvsp[-1].node)), (yyval.node), &(yyloc)); } -#line 9854 "parse.c" /* yacc.c:1646 */ +#line 9992 "parse.c" break; case 482: -#line 3838 "parse.y" /* yacc.c:1646 */ - { +#line 3862 "parse.y" + { (yyval.node) = new_array_pattern(p, Qnone, get_value((yyvsp[-2].node)), (yyvsp[0].node), &(yyloc)); /*%%%*/ nd_set_first_loc((yyval.node), (yylsp[-2]).beg_pos); /*% %*/ } -#line 9866 "parse.c" /* yacc.c:1646 */ +#line 10004 "parse.c" break; case 483: -#line 3846 "parse.y" /* yacc.c:1646 */ - { +#line 3870 "parse.y" + { (yyval.node) = new_array_pattern(p, Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9874 "parse.c" /* yacc.c:1646 */ +#line 10012 "parse.c" break; case 484: -#line 3850 "parse.y" /* yacc.c:1646 */ - { +#line 3874 "parse.y" + { (yyval.node) = new_hash_pattern(p, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 9882 "parse.c" /* yacc.c:1646 */ +#line 10020 "parse.c" break; case 486: -#line 3859 "parse.y" /* yacc.c:1646 */ - { +#line 3883 "parse.y" + { /*%%%*/ NODE *n = NEW_LIST((yyvsp[-2].node), &(yyloc)); n = list_append(p, n, (yyvsp[0].node)); @@ -9896,35 +10034,35 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: binary!($1, STATIC_ID2SYM((id_assoc)), $3) %*/ } -#line 9895 "parse.c" /* yacc.c:1646 */ +#line 10033 "parse.c" break; case 488: -#line 3871 "parse.y" /* yacc.c:1646 */ - { +#line 3895 "parse.y" + { /*%%%*/ (yyval.node) = NEW_NODE(NODE_OR, (yyvsp[-2].node), (yyvsp[0].node), 0, &(yyloc)); /*% %*/ /*% ripper: binary!($1, STATIC_ID2SYM(idOr), $3) %*/ } -#line 9906 "parse.c" /* yacc.c:1646 */ +#line 10044 "parse.c" break; case 490: -#line 3880 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9912 "parse.c" /* yacc.c:1646 */ +#line 3904 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10050 "parse.c" break; case 491: -#line 3881 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9918 "parse.c" /* yacc.c:1646 */ +#line 3905 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10056 "parse.c" break; case 493: -#line 3885 "parse.y" /* yacc.c:1646 */ - { +#line 3909 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = new_array_pattern(p, (yyvsp[-3].node), Qnone, (yyvsp[-1].node), &(yyloc)); /*%%%*/ @@ -9932,12 +10070,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ } -#line 9931 "parse.c" /* yacc.c:1646 */ +#line 10069 "parse.c" break; case 494: -#line 3894 "parse.y" /* yacc.c:1646 */ - { +#line 3918 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = new_hash_pattern(p, (yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); /*%%%*/ @@ -9945,21 +10083,21 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ } -#line 9944 "parse.c" /* yacc.c:1646 */ +#line 10082 "parse.c" break; case 495: -#line 3903 "parse.y" /* yacc.c:1646 */ - { +#line 3927 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.node) = new_array_pattern(p, (yyvsp[-2].node), Qnone, (yyval.node), &(yyloc)); } -#line 9953 "parse.c" /* yacc.c:1646 */ +#line 10091 "parse.c" break; case 496: -#line 3908 "parse.y" /* yacc.c:1646 */ - { +#line 3932 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = new_array_pattern(p, (yyvsp[-3].node), Qnone, (yyvsp[-1].node), &(yyloc)); /*%%%*/ @@ -9967,12 +10105,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ } -#line 9966 "parse.c" /* yacc.c:1646 */ +#line 10104 "parse.c" break; case 497: -#line 3917 "parse.y" /* yacc.c:1646 */ - { +#line 3941 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = new_hash_pattern(p, (yyvsp[-3].node), (yyvsp[-1].node), &(yyloc)); /*%%%*/ @@ -9980,89 +10118,84 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ } -#line 9979 "parse.c" /* yacc.c:1646 */ +#line 10117 "parse.c" break; case 498: -#line 3926 "parse.y" /* yacc.c:1646 */ - { +#line 3950 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.node) = new_array_pattern(p, (yyvsp[-2].node), Qnone, (yyval.node), &(yyloc)); } -#line 9988 "parse.c" /* yacc.c:1646 */ +#line 10126 "parse.c" break; case 499: -#line 3930 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 9994 "parse.c" /* yacc.c:1646 */ +#line 3954 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10132 "parse.c" break; case 500: -#line 3931 "parse.y" /* yacc.c:1646 */ - { +#line 3955 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = new_array_pattern(p, Qnone, Qnone, (yyvsp[-1].node), &(yyloc)); } -#line 10003 "parse.c" /* yacc.c:1646 */ +#line 10141 "parse.c" break; case 501: -#line 3936 "parse.y" /* yacc.c:1646 */ - { +#line 3960 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &(yyloc)); (yyval.node) = new_array_pattern(p, Qnone, Qnone, (yyval.node), &(yyloc)); } -#line 10012 "parse.c" /* yacc.c:1646 */ +#line 10150 "parse.c" break; case 502: -#line 3941 "parse.y" /* yacc.c:1646 */ - { - (yyval.tbl) = push_pktbl(p); - (yyvsp[0].num) = p->in_kwarg; - p->in_kwarg = 0; - } -#line 10022 "parse.c" /* yacc.c:1646 */ +#line 3964 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10156 "parse.c" break; case 503: -#line 3947 "parse.y" /* yacc.c:1646 */ - { +#line 3965 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); - p->in_kwarg = (yyvsp[-3].num); (yyval.node) = new_hash_pattern(p, Qnone, (yyvsp[-1].node), &(yyloc)); } -#line 10032 "parse.c" /* yacc.c:1646 */ +#line 10165 "parse.c" break; case 504: -#line 3953 "parse.y" /* yacc.c:1646 */ - { +#line 3970 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, Qnone, 0, &(yyloc)); (yyval.node) = new_hash_pattern(p, Qnone, (yyval.node), &(yyloc)); } -#line 10041 "parse.c" /* yacc.c:1646 */ +#line 10174 "parse.c" break; case 505: -#line 3957 "parse.y" /* yacc.c:1646 */ - {(yyval.tbl) = push_pktbl(p);} -#line 10047 "parse.c" /* yacc.c:1646 */ +#line 3974 "parse.y" + {(yyval.tbl) = push_pktbl(p);} +#line 10180 "parse.c" break; case 506: -#line 3958 "parse.y" /* yacc.c:1646 */ - { +#line 3975 "parse.y" + { pop_pktbl(p, (yyvsp[-2].tbl)); (yyval.node) = (yyvsp[-1].node); } -#line 10056 "parse.c" /* yacc.c:1646 */ +#line 10189 "parse.c" break; case 507: -#line 3965 "parse.y" /* yacc.c:1646 */ - { +#line 3982 "parse.y" + { /*%%%*/ NODE *pre_args = NEW_LIST((yyvsp[0].node), &(yyloc)); (yyval.node) = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &(yyloc)); @@ -10070,20 +10203,20 @@ YYLTYPE yylloc = yyloc_default; $$ = new_array_pattern_tail(p, rb_ary_new_from_args(1, get_value($1)), 0, 0, Qnone, &@$); %*/ } -#line 10069 "parse.c" /* yacc.c:1646 */ +#line 10202 "parse.c" break; case 508: -#line 3974 "parse.y" /* yacc.c:1646 */ - { +#line 3991 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, (yyvsp[0].node), 1, 0, Qnone, &(yyloc)); } -#line 10077 "parse.c" /* yacc.c:1646 */ +#line 10210 "parse.c" break; case 509: -#line 3978 "parse.y" /* yacc.c:1646 */ - { +#line 3995 "parse.y" + { /*%%%*/ (yyval.node) = new_array_pattern_tail(p, list_concat((yyvsp[-1].node), (yyvsp[0].node)), 0, 0, Qnone, &(yyloc)); /*% @@ -10091,188 +10224,180 @@ YYLTYPE yylloc = yyloc_default; $$ = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &@$); %*/ } -#line 10090 "parse.c" /* yacc.c:1646 */ +#line 10223 "parse.c" break; case 510: -#line 3987 "parse.y" /* yacc.c:1646 */ - { +#line 4004 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, (yyvsp[-2].node), 1, (yyvsp[0].id), Qnone, &(yyloc)); } -#line 10098 "parse.c" /* yacc.c:1646 */ +#line 10231 "parse.c" break; case 511: -#line 3991 "parse.y" /* yacc.c:1646 */ - { +#line 4008 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, (yyvsp[-4].node), 1, (yyvsp[-2].id), (yyvsp[0].node), &(yyloc)); } -#line 10106 "parse.c" /* yacc.c:1646 */ +#line 10239 "parse.c" break; case 512: -#line 3995 "parse.y" /* yacc.c:1646 */ - { +#line 4012 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, (yyvsp[-1].node), 1, 0, Qnone, &(yyloc)); } -#line 10114 "parse.c" /* yacc.c:1646 */ +#line 10247 "parse.c" break; case 513: -#line 3999 "parse.y" /* yacc.c:1646 */ - { +#line 4016 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, (yyvsp[-3].node), 1, 0, (yyvsp[0].node), &(yyloc)); } -#line 10122 "parse.c" /* yacc.c:1646 */ +#line 10255 "parse.c" break; case 515: -#line 4006 "parse.y" /* yacc.c:1646 */ - { +#line 4023 "parse.y" + { (yyval.node) = (yyvsp[-1].node); } -#line 10130 "parse.c" /* yacc.c:1646 */ +#line 10263 "parse.c" break; case 516: -#line 4010 "parse.y" /* yacc.c:1646 */ - { +#line 4027 "parse.y" + { /*%%%*/ (yyval.node) = list_concat((yyvsp[-2].node), (yyvsp[-1].node)); /*% %*/ /*% ripper: rb_ary_concat($1, get_value($2)) %*/ } -#line 10141 "parse.c" /* yacc.c:1646 */ +#line 10274 "parse.c" break; case 517: -#line 4019 "parse.y" /* yacc.c:1646 */ - { +#line 4036 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 1, (yyvsp[0].id), Qnone, &(yyloc)); } -#line 10149 "parse.c" /* yacc.c:1646 */ +#line 10282 "parse.c" break; case 518: -#line 4023 "parse.y" /* yacc.c:1646 */ - { +#line 4040 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 1, (yyvsp[-2].id), (yyvsp[0].node), &(yyloc)); } -#line 10157 "parse.c" /* yacc.c:1646 */ +#line 10290 "parse.c" break; case 519: -#line 4027 "parse.y" /* yacc.c:1646 */ - { +#line 4044 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &(yyloc)); } -#line 10165 "parse.c" /* yacc.c:1646 */ +#line 10298 "parse.c" break; case 520: -#line 4031 "parse.y" /* yacc.c:1646 */ - { +#line 4048 "parse.y" + { (yyval.node) = new_array_pattern_tail(p, Qnone, 1, 0, (yyvsp[0].node), &(yyloc)); } -#line 10173 "parse.c" /* yacc.c:1646 */ +#line 10306 "parse.c" break; case 522: -#line 4038 "parse.y" /* yacc.c:1646 */ - { +#line 4055 "parse.y" + { /*%%%*/ (yyval.node) = list_concat((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_concat($1, get_value($3)) %*/ } -#line 10184 "parse.c" /* yacc.c:1646 */ +#line 10317 "parse.c" break; case 523: -#line 4047 "parse.y" /* yacc.c:1646 */ - { +#line 4064 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: rb_ary_new_from_args(1, get_value($1)) %*/ } -#line 10195 "parse.c" /* yacc.c:1646 */ +#line 10328 "parse.c" break; case 524: -#line 4056 "parse.y" /* yacc.c:1646 */ - { +#line 4073 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-2].node), &(yyloc)), (yyvsp[0].id), &(yyloc)); } -#line 10203 "parse.c" /* yacc.c:1646 */ +#line 10336 "parse.c" break; case 525: -#line 4060 "parse.y" /* yacc.c:1646 */ - { +#line 4077 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[0].node), &(yyloc)), 0, &(yyloc)); } -#line 10211 "parse.c" /* yacc.c:1646 */ +#line 10344 "parse.c" break; case 526: -#line 4064 "parse.y" /* yacc.c:1646 */ - { - (yyval.node) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-1].node), &(yyloc)), 0, &(yyloc)); - } -#line 10219 "parse.c" /* yacc.c:1646 */ - break; - - case 527: -#line 4068 "parse.y" /* yacc.c:1646 */ - { +#line 4081 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), (yyvsp[0].id), &(yyloc)); } -#line 10227 "parse.c" /* yacc.c:1646 */ +#line 10352 "parse.c" break; - case 528: -#line 4072 "parse.y" /* yacc.c:1646 */ - { + case 527: +#line 4085 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, new_unique_key_hash(p, (yyvsp[-2].node), &(yyloc)), ID2VAL(idNil), &(yyloc)); } -#line 10235 "parse.c" /* yacc.c:1646 */ +#line 10360 "parse.c" break; - case 529: -#line 4076 "parse.y" /* yacc.c:1646 */ - { + case 528: +#line 4089 "parse.y" + { (yyval.node) = new_hash_pattern_tail(p, new_hash(p, Qnone, &(yyloc)), ID2VAL(idNil), &(yyloc)); } -#line 10243 "parse.c" /* yacc.c:1646 */ +#line 10368 "parse.c" break; - case 531: -#line 4084 "parse.y" /* yacc.c:1646 */ - { + case 530: +#line 4097 "parse.y" + { /*%%%*/ (yyval.node) = list_concat((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_push($1, $3) %*/ } -#line 10254 "parse.c" /* yacc.c:1646 */ +#line 10379 "parse.c" break; - case 532: -#line 4093 "parse.y" /* yacc.c:1646 */ - { + case 531: +#line 4106 "parse.y" + { error_duplicate_pattern_key(p, get_id((yyvsp[-1].id)), &(yylsp[-1])); /*%%%*/ (yyval.node) = list_append(p, NEW_LIST(NEW_LIT(ID2SYM((yyvsp[-1].id)), &(yyloc)), &(yyloc)), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_new_from_args(2, get_value($1), get_value($2)) %*/ } -#line 10266 "parse.c" /* yacc.c:1646 */ +#line 10391 "parse.c" break; - case 533: -#line 4101 "parse.y" /* yacc.c:1646 */ - { + case 532: +#line 4114 "parse.y" + { error_duplicate_pattern_key(p, get_id((yyvsp[0].id)), &(yylsp[0])); if ((yyvsp[0].id) && !is_local_id(get_id((yyvsp[0].id)))) { yyerror1(&(yylsp[0]), "key must be valid as local variables"); @@ -10283,12 +10408,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rb_ary_new_from_args(2, get_value($1), Qnil) %*/ } -#line 10282 "parse.c" /* yacc.c:1646 */ +#line 10407 "parse.c" break; - case 535: -#line 4116 "parse.y" /* yacc.c:1646 */ - { + case 534: +#line 4129 "parse.y" + { YYLTYPE loc = code_loc_gen(&(yylsp[-2]), &(yylsp[0])); /*%%%*/ if (!(yyvsp[-1].node) || nd_type((yyvsp[-1].node)) == NODE_STR) { @@ -10308,36 +10433,36 @@ YYLTYPE yylloc = yyloc_default; (yyval.id) = 0; } } -#line 10307 "parse.c" /* yacc.c:1646 */ +#line 10432 "parse.c" break; - case 536: -#line 4139 "parse.y" /* yacc.c:1646 */ - { + case 535: +#line 4152 "parse.y" + { (yyval.id) = (yyvsp[0].id); } -#line 10315 "parse.c" /* yacc.c:1646 */ +#line 10440 "parse.c" break; - case 537: -#line 4143 "parse.y" /* yacc.c:1646 */ - { + case 536: +#line 4156 "parse.y" + { (yyval.id) = 0; } -#line 10323 "parse.c" /* yacc.c:1646 */ +#line 10448 "parse.c" break; - case 538: -#line 4149 "parse.y" /* yacc.c:1646 */ - { + case 537: +#line 4162 "parse.y" + { (yyval.id) = 0; } -#line 10331 "parse.c" /* yacc.c:1646 */ +#line 10456 "parse.c" break; - case 540: -#line 4156 "parse.y" /* yacc.c:1646 */ - { + case 539: +#line 4169 "parse.y" + { /*%%%*/ value_expr((yyvsp[-2].node)); value_expr((yyvsp[0].node)); @@ -10345,12 +10470,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!($1, $3) %*/ } -#line 10344 "parse.c" /* yacc.c:1646 */ +#line 10469 "parse.c" break; - case 541: -#line 4165 "parse.y" /* yacc.c:1646 */ - { + case 540: +#line 4178 "parse.y" + { /*%%%*/ value_expr((yyvsp[-2].node)); value_expr((yyvsp[0].node)); @@ -10358,12 +10483,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!($1, $3) %*/ } -#line 10357 "parse.c" /* yacc.c:1646 */ +#line 10482 "parse.c" break; - case 542: -#line 4174 "parse.y" /* yacc.c:1646 */ - { + case 541: +#line 4187 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -10374,12 +10499,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!($1, Qnil) %*/ } -#line 10373 "parse.c" /* yacc.c:1646 */ +#line 10498 "parse.c" break; - case 543: -#line 4186 "parse.y" /* yacc.c:1646 */ - { + case 542: +#line 4199 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[0]).end_pos; @@ -10390,12 +10515,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!($1, Qnil) %*/ } -#line 10389 "parse.c" /* yacc.c:1646 */ +#line 10514 "parse.c" break; - case 547: -#line 4201 "parse.y" /* yacc.c:1646 */ - { + case 546: +#line 4214 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -10406,12 +10531,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot2!(Qnil, $2) %*/ } -#line 10405 "parse.c" /* yacc.c:1646 */ +#line 10530 "parse.c" break; - case 548: -#line 4213 "parse.y" /* yacc.c:1646 */ - { + case 547: +#line 4226 "parse.y" + { /*%%%*/ YYLTYPE loc; loc.beg_pos = (yylsp[-1]).beg_pos; @@ -10422,54 +10547,54 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: dot3!(Qnil, $2) %*/ } -#line 10421 "parse.c" /* yacc.c:1646 */ +#line 10546 "parse.c" break; - case 557: -#line 4235 "parse.y" /* yacc.c:1646 */ - { + case 556: +#line 4248 "parse.y" + { /*%%%*/ if (!((yyval.node) = gettable(p, (yyvsp[0].id), &(yyloc)))) (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 10432 "parse.c" /* yacc.c:1646 */ +#line 10557 "parse.c" break; - case 558: -#line 4242 "parse.y" /* yacc.c:1646 */ - { + case 557: +#line 4255 "parse.y" + { token_info_push(p, "->", &(yylsp[0])); } -#line 10440 "parse.c" /* yacc.c:1646 */ +#line 10565 "parse.c" break; - case 559: -#line 4246 "parse.y" /* yacc.c:1646 */ - { + case 558: +#line 4259 "parse.y" + { (yyval.node) = (yyvsp[0].node); /*%%%*/ nd_set_first_loc((yyval.node), (yylsp[-2]).beg_pos); /*% %*/ } -#line 10451 "parse.c" /* yacc.c:1646 */ +#line 10576 "parse.c" break; - case 560: -#line 4255 "parse.y" /* yacc.c:1646 */ - { + case 559: +#line 4268 "parse.y" + { /*%%%*/ error_duplicate_pattern_variable(p, (yyvsp[0].id), &(yylsp[0])); (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 10463 "parse.c" /* yacc.c:1646 */ +#line 10588 "parse.c" break; - case 561: -#line 4265 "parse.y" /* yacc.c:1646 */ - { + case 560: +#line 4278 "parse.y" + { /*%%%*/ NODE *n = gettable(p, (yyvsp[0].id), &(yyloc)); if (!(nd_type(n) == NODE_LVAR || nd_type(n) == NODE_DVAR)) { @@ -10479,45 +10604,45 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: var_ref!($2) %*/ } -#line 10478 "parse.c" /* yacc.c:1646 */ +#line 10603 "parse.c" break; - case 562: -#line 4278 "parse.y" /* yacc.c:1646 */ - { + case 561: +#line 4291 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON3((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: top_const_ref!($2) %*/ } -#line 10489 "parse.c" /* yacc.c:1646 */ +#line 10614 "parse.c" break; - case 563: -#line 4285 "parse.y" /* yacc.c:1646 */ - { + case 562: +#line 4298 "parse.y" + { /*%%%*/ (yyval.node) = NEW_COLON2((yyvsp[-2].node), (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: const_path_ref!($1, $3) %*/ } -#line 10500 "parse.c" /* yacc.c:1646 */ +#line 10625 "parse.c" break; - case 564: -#line 4292 "parse.y" /* yacc.c:1646 */ - { + case 563: +#line 4305 "parse.y" + { /*%%%*/ (yyval.node) = gettable(p, (yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 10511 "parse.c" /* yacc.c:1646 */ +#line 10636 "parse.c" break; - case 565: -#line 4303 "parse.y" /* yacc.c:1646 */ - { + case 564: +#line 4316 "parse.y" + { /*%%%*/ (yyval.node) = NEW_RESBODY((yyvsp[-4].node), (yyvsp[-3].node) ? block_append(p, node_assign(p, (yyvsp[-3].node), NEW_ERRINFO(&(yylsp[-3])), &(yylsp[-3])), (yyvsp[-1].node)) : (yyvsp[-1].node), @@ -10526,53 +10651,53 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rescue!(escape_Qundef($2), escape_Qundef($3), escape_Qundef($5), escape_Qundef($6)) %*/ } -#line 10525 "parse.c" /* yacc.c:1646 */ +#line 10650 "parse.c" break; - case 567: -#line 4316 "parse.y" /* yacc.c:1646 */ - { + case 566: +#line 4329 "parse.y" + { /*%%%*/ (yyval.node) = NEW_LIST((yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 10536 "parse.c" /* yacc.c:1646 */ +#line 10661 "parse.c" break; - case 568: -#line 4323 "parse.y" /* yacc.c:1646 */ - { + case 567: +#line 4336 "parse.y" + { /*%%%*/ if (!((yyval.node) = splat_array((yyvsp[0].node)))) (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: $1 %*/ } -#line 10547 "parse.c" /* yacc.c:1646 */ +#line 10672 "parse.c" break; - case 570: -#line 4333 "parse.y" /* yacc.c:1646 */ - { + case 569: +#line 4346 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 10555 "parse.c" /* yacc.c:1646 */ +#line 10680 "parse.c" break; - case 572: -#line 4340 "parse.y" /* yacc.c:1646 */ - { + case 571: +#line 4353 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: ensure!($2) %*/ } -#line 10566 "parse.c" /* yacc.c:1646 */ +#line 10691 "parse.c" break; - case 576: -#line 4354 "parse.y" /* yacc.c:1646 */ - { + case 575: +#line 4367 "parse.y" + { /*%%%*/ NODE *node = (yyvsp[0].node); if (!node) { @@ -10586,197 +10711,197 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: $1 %*/ } -#line 10585 "parse.c" /* yacc.c:1646 */ +#line 10710 "parse.c" break; - case 579: -#line 4373 "parse.y" /* yacc.c:1646 */ - { + case 578: +#line 4386 "parse.y" + { /*%%%*/ (yyval.node) = literal_concat(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: string_concat!($1, $2) %*/ } -#line 10596 "parse.c" /* yacc.c:1646 */ +#line 10721 "parse.c" break; - case 580: -#line 4382 "parse.y" /* yacc.c:1646 */ - { + case 579: +#line 4395 "parse.y" + { /*%%%*/ (yyval.node) = heredoc_dedent(p, (yyvsp[-1].node)); if ((yyval.node)) nd_set_loc((yyval.node), &(yyloc)); /*% %*/ /*% ripper: string_literal!(heredoc_dedent(p, $2)) %*/ } -#line 10608 "parse.c" /* yacc.c:1646 */ +#line 10733 "parse.c" break; - case 581: -#line 4392 "parse.y" /* yacc.c:1646 */ - { + case 580: +#line 4405 "parse.y" + { /*%%%*/ (yyval.node) = new_xstring(p, heredoc_dedent(p, (yyvsp[-1].node)), &(yyloc)); /*% %*/ /*% ripper: xstring_literal!(heredoc_dedent(p, $2)) %*/ } -#line 10619 "parse.c" /* yacc.c:1646 */ +#line 10744 "parse.c" break; - case 582: -#line 4401 "parse.y" /* yacc.c:1646 */ - { + case 581: +#line 4414 "parse.y" + { (yyval.node) = new_regexp(p, (yyvsp[-1].node), (yyvsp[0].num), &(yyloc)); } -#line 10627 "parse.c" /* yacc.c:1646 */ +#line 10752 "parse.c" break; - case 583: -#line 4407 "parse.y" /* yacc.c:1646 */ - { + case 582: +#line 4420 "parse.y" + { /*%%%*/ (yyval.node) = make_list((yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: array!($3) %*/ } -#line 10638 "parse.c" /* yacc.c:1646 */ +#line 10763 "parse.c" break; - case 584: -#line 4416 "parse.y" /* yacc.c:1646 */ - { + case 583: +#line 4429 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: words_new! %*/ } -#line 10649 "parse.c" /* yacc.c:1646 */ +#line 10774 "parse.c" break; - case 585: -#line 4423 "parse.y" /* yacc.c:1646 */ - { + case 584: +#line 4436 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, (yyvsp[-2].node), evstr2dstr(p, (yyvsp[-1].node))); /*% %*/ /*% ripper: words_add!($1, $2) %*/ } -#line 10660 "parse.c" /* yacc.c:1646 */ +#line 10785 "parse.c" break; - case 587: -#line 4434 "parse.y" /* yacc.c:1646 */ - { + case 586: +#line 4447 "parse.y" + { /*%%%*/ (yyval.node) = literal_concat(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: word_add!($1, $2) %*/ } -#line 10671 "parse.c" /* yacc.c:1646 */ +#line 10796 "parse.c" break; - case 588: -#line 4443 "parse.y" /* yacc.c:1646 */ - { + case 587: +#line 4456 "parse.y" + { /*%%%*/ (yyval.node) = make_list((yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: array!($3) %*/ } -#line 10682 "parse.c" /* yacc.c:1646 */ +#line 10807 "parse.c" break; - case 589: -#line 4452 "parse.y" /* yacc.c:1646 */ - { + case 588: +#line 4465 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: symbols_new! %*/ } -#line 10693 "parse.c" /* yacc.c:1646 */ +#line 10818 "parse.c" break; - case 590: -#line 4459 "parse.y" /* yacc.c:1646 */ - { + case 589: +#line 4472 "parse.y" + { /*%%%*/ (yyval.node) = symbol_append(p, (yyvsp[-2].node), evstr2dstr(p, (yyvsp[-1].node))); /*% %*/ /*% ripper: symbols_add!($1, $2) %*/ } -#line 10704 "parse.c" /* yacc.c:1646 */ +#line 10829 "parse.c" break; - case 591: -#line 4468 "parse.y" /* yacc.c:1646 */ - { + case 590: +#line 4481 "parse.y" + { /*%%%*/ (yyval.node) = make_list((yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: array!($3) %*/ } -#line 10715 "parse.c" /* yacc.c:1646 */ +#line 10840 "parse.c" break; - case 592: -#line 4477 "parse.y" /* yacc.c:1646 */ - { + case 591: +#line 4490 "parse.y" + { /*%%%*/ (yyval.node) = make_list((yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: array!($3) %*/ } -#line 10726 "parse.c" /* yacc.c:1646 */ +#line 10851 "parse.c" break; - case 593: -#line 4486 "parse.y" /* yacc.c:1646 */ - { + case 592: +#line 4499 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: qwords_new! %*/ } -#line 10737 "parse.c" /* yacc.c:1646 */ +#line 10862 "parse.c" break; - case 594: -#line 4493 "parse.y" /* yacc.c:1646 */ - { + case 593: +#line 4506 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, (yyvsp[-2].node), (yyvsp[-1].node)); /*% %*/ /*% ripper: qwords_add!($1, $2) %*/ } -#line 10748 "parse.c" /* yacc.c:1646 */ +#line 10873 "parse.c" break; - case 595: -#line 4502 "parse.y" /* yacc.c:1646 */ - { + case 594: +#line 4515 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: qsymbols_new! %*/ } -#line 10759 "parse.c" /* yacc.c:1646 */ +#line 10884 "parse.c" break; - case 596: -#line 4509 "parse.y" /* yacc.c:1646 */ - { + case 595: +#line 4522 "parse.y" + { /*%%%*/ (yyval.node) = symbol_append(p, (yyvsp[-2].node), (yyvsp[-1].node)); /*% %*/ /*% ripper: qsymbols_add!($1, $2) %*/ } -#line 10770 "parse.c" /* yacc.c:1646 */ +#line 10895 "parse.c" break; - case 597: -#line 4518 "parse.y" /* yacc.c:1646 */ - { + case 596: +#line 4531 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ @@ -10786,12 +10911,12 @@ YYLTYPE yylloc = yyloc_default; $$ = ripper_new_yylval(p, 0, $$, 0); %*/ } -#line 10785 "parse.c" /* yacc.c:1646 */ +#line 10910 "parse.c" break; - case 598: -#line 4529 "parse.y" /* yacc.c:1646 */ - { + case 597: +#line 4542 "parse.y" + { /*%%%*/ (yyval.node) = literal_concat(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ @@ -10806,34 +10931,34 @@ YYLTYPE yylloc = yyloc_default; } %*/ } -#line 10805 "parse.c" /* yacc.c:1646 */ +#line 10930 "parse.c" break; - case 599: -#line 4547 "parse.y" /* yacc.c:1646 */ - { + case 598: +#line 4560 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: xstring_new! %*/ } -#line 10816 "parse.c" /* yacc.c:1646 */ +#line 10941 "parse.c" break; - case 600: -#line 4554 "parse.y" /* yacc.c:1646 */ - { + case 599: +#line 4567 "parse.y" + { /*%%%*/ (yyval.node) = literal_concat(p, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); /*% %*/ /*% ripper: xstring_add!($1, $2) %*/ } -#line 10827 "parse.c" /* yacc.c:1646 */ +#line 10952 "parse.c" break; - case 601: -#line 4563 "parse.y" /* yacc.c:1646 */ - { + case 600: +#line 4576 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ @@ -10843,12 +10968,12 @@ YYLTYPE yylloc = yyloc_default; $$ = ripper_new_yylval(p, 0, $$, 0); %*/ } -#line 10842 "parse.c" /* yacc.c:1646 */ +#line 10967 "parse.c" break; - case 602: -#line 4574 "parse.y" /* yacc.c:1646 */ - { + case 601: +#line 4587 "parse.y" + { /*%%%*/ NODE *head = (yyvsp[-1].node), *tail = (yyvsp[0].node); if (!head) { @@ -10886,23 +11011,23 @@ YYLTYPE yylloc = yyloc_default; } %*/ } -#line 10885 "parse.c" /* yacc.c:1646 */ +#line 11010 "parse.c" break; - case 604: -#line 4617 "parse.y" /* yacc.c:1646 */ - { + case 603: +#line 4630 "parse.y" + { /* need to backup p->lex.strterm so that a string literal `%&foo,#$&,bar&` can be parsed */ (yyval.strterm) = p->lex.strterm; p->lex.strterm = 0; SET_LEX_STATE(EXPR_BEG); } -#line 10896 "parse.c" /* yacc.c:1646 */ +#line 11021 "parse.c" break; - case 605: -#line 4624 "parse.y" /* yacc.c:1646 */ - { + case 604: +#line 4637 "parse.y" + { p->lex.strterm = (yyvsp[-1].strterm); /*%%%*/ (yyval.node) = NEW_EVSTR((yyvsp[0].node), &(yyloc)); @@ -10910,58 +11035,58 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: string_dvar!($3) %*/ } -#line 10909 "parse.c" /* yacc.c:1646 */ +#line 11034 "parse.c" break; - case 606: -#line 4633 "parse.y" /* yacc.c:1646 */ - { + case 605: +#line 4646 "parse.y" + { CMDARG_PUSH(0); COND_PUSH(0); } -#line 10918 "parse.c" /* yacc.c:1646 */ +#line 11043 "parse.c" break; - case 607: -#line 4637 "parse.y" /* yacc.c:1646 */ - { + case 606: +#line 4650 "parse.y" + { /* need to backup p->lex.strterm so that a string literal `%!foo,#{ !0 },bar!` can be parsed */ (yyval.strterm) = p->lex.strterm; p->lex.strterm = 0; } -#line 10928 "parse.c" /* yacc.c:1646 */ +#line 11053 "parse.c" break; - - case 608: -#line 4642 "parse.y" /* yacc.c:1646 */ - { + + case 607: +#line 4655 "parse.y" + { (yyval.num) = p->lex.state; SET_LEX_STATE(EXPR_BEG); } -#line 10937 "parse.c" /* yacc.c:1646 */ +#line 11062 "parse.c" break; - case 609: -#line 4646 "parse.y" /* yacc.c:1646 */ - { + case 608: +#line 4659 "parse.y" + { (yyval.num) = p->lex.brace_nest; p->lex.brace_nest = 0; } -#line 10946 "parse.c" /* yacc.c:1646 */ +#line 11071 "parse.c" break; - case 610: -#line 4650 "parse.y" /* yacc.c:1646 */ - { + case 609: +#line 4663 "parse.y" + { (yyval.num) = p->heredoc_indent; p->heredoc_indent = 0; } -#line 10955 "parse.c" /* yacc.c:1646 */ +#line 11080 "parse.c" break; - case 611: -#line 4655 "parse.y" /* yacc.c:1646 */ - { + case 610: +#line 4668 "parse.y" + { COND_POP(); CMDARG_POP(); p->lex.strterm = (yyvsp[-5].strterm); @@ -10975,123 +11100,123 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: string_embexpr!($7) %*/ } -#line 10974 "parse.c" /* yacc.c:1646 */ +#line 11099 "parse.c" break; - case 612: -#line 4672 "parse.y" /* yacc.c:1646 */ - { + case 611: +#line 4685 "parse.y" + { /*%%%*/ (yyval.node) = NEW_GVAR((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 10985 "parse.c" /* yacc.c:1646 */ +#line 11110 "parse.c" break; - case 613: -#line 4679 "parse.y" /* yacc.c:1646 */ - { + case 612: +#line 4692 "parse.y" + { /*%%%*/ (yyval.node) = NEW_IVAR((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 10996 "parse.c" /* yacc.c:1646 */ +#line 11121 "parse.c" break; - case 614: -#line 4686 "parse.y" /* yacc.c:1646 */ - { + case 613: +#line 4699 "parse.y" + { /*%%%*/ (yyval.node) = NEW_CVAR((yyvsp[0].id), &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 11007 "parse.c" /* yacc.c:1646 */ +#line 11132 "parse.c" break; - case 618: -#line 4700 "parse.y" /* yacc.c:1646 */ - { + case 617: +#line 4713 "parse.y" + { SET_LEX_STATE(EXPR_END); /*%%%*/ (yyval.node) = NEW_LIT(ID2SYM((yyvsp[0].id)), &(yyloc)); /*% %*/ /*% ripper: symbol_literal!(symbol!($2)) %*/ } -#line 11019 "parse.c" /* yacc.c:1646 */ +#line 11144 "parse.c" break; - case 623: -#line 4716 "parse.y" /* yacc.c:1646 */ - { + case 622: +#line 4729 "parse.y" + { SET_LEX_STATE(EXPR_END); /*%%%*/ (yyval.node) = dsym_node(p, (yyvsp[-1].node), &(yyloc)); /*% %*/ /*% ripper: dyna_symbol!($2) %*/ } -#line 11031 "parse.c" /* yacc.c:1646 */ +#line 11156 "parse.c" break; - case 625: -#line 4727 "parse.y" /* yacc.c:1646 */ - { + case 624: +#line 4740 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); RB_OBJ_WRITE(p->ast, &(yyval.node)->nd_lit, negate_lit(p, (yyval.node)->nd_lit)); /*% %*/ /*% ripper: unary!(ID2VAL(idUMinus), $2) %*/ } -#line 11043 "parse.c" /* yacc.c:1646 */ +#line 11168 "parse.c" + break; + + case 634: +#line 4762 "parse.y" + {(yyval.id) = KWD2EID(nil, (yyvsp[0].id));} +#line 11174 "parse.c" break; case 635: -#line 4749 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(nil, (yyvsp[0].id));} -#line 11049 "parse.c" /* yacc.c:1646 */ +#line 4763 "parse.y" + {(yyval.id) = KWD2EID(self, (yyvsp[0].id));} +#line 11180 "parse.c" break; case 636: -#line 4750 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(self, (yyvsp[0].id));} -#line 11055 "parse.c" /* yacc.c:1646 */ +#line 4764 "parse.y" + {(yyval.id) = KWD2EID(true, (yyvsp[0].id));} +#line 11186 "parse.c" break; case 637: -#line 4751 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(true, (yyvsp[0].id));} -#line 11061 "parse.c" /* yacc.c:1646 */ +#line 4765 "parse.y" + {(yyval.id) = KWD2EID(false, (yyvsp[0].id));} +#line 11192 "parse.c" break; case 638: -#line 4752 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(false, (yyvsp[0].id));} -#line 11067 "parse.c" /* yacc.c:1646 */ +#line 4766 "parse.y" + {(yyval.id) = KWD2EID(_FILE__, (yyvsp[0].id));} +#line 11198 "parse.c" break; case 639: -#line 4753 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(_FILE__, (yyvsp[0].id));} -#line 11073 "parse.c" /* yacc.c:1646 */ +#line 4767 "parse.y" + {(yyval.id) = KWD2EID(_LINE__, (yyvsp[0].id));} +#line 11204 "parse.c" break; case 640: -#line 4754 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(_LINE__, (yyvsp[0].id));} -#line 11079 "parse.c" /* yacc.c:1646 */ +#line 4768 "parse.y" + {(yyval.id) = KWD2EID(_ENCODING__, (yyvsp[0].id));} +#line 11210 "parse.c" break; case 641: -#line 4755 "parse.y" /* yacc.c:1646 */ - {(yyval.id) = KWD2EID(_ENCODING__, (yyvsp[0].id));} -#line 11085 "parse.c" /* yacc.c:1646 */ - break; - - case 642: -#line 4759 "parse.y" /* yacc.c:1646 */ - { +#line 4772 "parse.y" + { /*%%%*/ if (!((yyval.node) = gettable(p, (yyvsp[0].id), &(yyloc)))) (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% @@ -11103,73 +11228,73 @@ YYLTYPE yylloc = yyloc_default; } %*/ } -#line 11102 "parse.c" /* yacc.c:1646 */ +#line 11227 "parse.c" break; - case 643: -#line 4772 "parse.y" /* yacc.c:1646 */ - { + case 642: +#line 4785 "parse.y" + { /*%%%*/ if (!((yyval.node) = gettable(p, (yyvsp[0].id), &(yyloc)))) (yyval.node) = NEW_BEGIN(0, &(yyloc)); /*% %*/ /*% ripper: var_ref!($1) %*/ } -#line 11113 "parse.c" /* yacc.c:1646 */ +#line 11238 "parse.c" break; - case 644: -#line 4781 "parse.y" /* yacc.c:1646 */ - { + case 643: +#line 4794 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 11124 "parse.c" /* yacc.c:1646 */ +#line 11249 "parse.c" break; - case 645: -#line 4788 "parse.y" /* yacc.c:1646 */ - { + case 644: +#line 4801 "parse.y" + { /*%%%*/ (yyval.node) = assignable(p, (yyvsp[0].id), 0, &(yyloc)); /*% %*/ /*% ripper: assignable(p, var_field(p, $1)) %*/ } -#line 11135 "parse.c" /* yacc.c:1646 */ +#line 11260 "parse.c" break; - case 648: -#line 4801 "parse.y" /* yacc.c:1646 */ - { + case 647: +#line 4814 "parse.y" + { SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11144 "parse.c" /* yacc.c:1646 */ +#line 11269 "parse.c" break; - case 649: -#line 4806 "parse.y" /* yacc.c:1646 */ - { + case 648: +#line 4819 "parse.y" + { (yyval.node) = (yyvsp[-1].node); } -#line 11152 "parse.c" /* yacc.c:1646 */ +#line 11277 "parse.c" break; - case 650: -#line 4810 "parse.y" /* yacc.c:1646 */ - { + case 649: +#line 4823 "parse.y" + { /*%%%*/ (yyval.node) = 0; /*% %*/ /*% ripper: Qnil %*/ } -#line 11163 "parse.c" /* yacc.c:1646 */ +#line 11288 "parse.c" break; - case 651: -#line 4819 "parse.y" /* yacc.c:1646 */ - { + case 650: +#line 4832 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ @@ -11177,12 +11302,12 @@ YYLTYPE yylloc = yyloc_default; SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11176 "parse.c" /* yacc.c:1646 */ +#line 11301 "parse.c" break; - case 652: -#line 4828 "parse.y" /* yacc.c:1646 */ - { + case 651: +#line 4841 "parse.y" + { arg_var(p, idFWD_REST); #if idFWD_KWREST arg_var(p, idFWD_KWREST); @@ -11196,302 +11321,302 @@ YYLTYPE yylloc = yyloc_default; SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11195 "parse.c" /* yacc.c:1646 */ +#line 11320 "parse.c" break; - case 653: -#line 4842 "parse.y" /* yacc.c:1646 */ - { + case 652: +#line 4855 "parse.y" + { (yyval.num) = p->in_kwarg; p->in_kwarg = 1; SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */ } -#line 11205 "parse.c" /* yacc.c:1646 */ +#line 11330 "parse.c" break; - case 654: -#line 4848 "parse.y" /* yacc.c:1646 */ - { + case 653: +#line 4861 "parse.y" + { p->in_kwarg = !!(yyvsp[-2].num); (yyval.node) = (yyvsp[-1].node); SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } -#line 11216 "parse.c" /* yacc.c:1646 */ +#line 11341 "parse.c" break; - case 655: -#line 4857 "parse.y" /* yacc.c:1646 */ - { + case 654: +#line 4870 "parse.y" + { (yyval.node) = new_args_tail(p, (yyvsp[-3].node), (yyvsp[-1].id), (yyvsp[0].id), &(yylsp[-1])); } -#line 11224 "parse.c" /* yacc.c:1646 */ +#line 11349 "parse.c" break; - case 656: -#line 4861 "parse.y" /* yacc.c:1646 */ - { + case 655: +#line 4874 "parse.y" + { (yyval.node) = new_args_tail(p, (yyvsp[-1].node), Qnone, (yyvsp[0].id), &(yylsp[-1])); } -#line 11232 "parse.c" /* yacc.c:1646 */ +#line 11357 "parse.c" break; - case 657: -#line 4865 "parse.y" /* yacc.c:1646 */ - { + case 656: +#line 4878 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, (yyvsp[-1].id), (yyvsp[0].id), &(yylsp[-1])); } -#line 11240 "parse.c" /* yacc.c:1646 */ +#line 11365 "parse.c" break; - case 658: -#line 4869 "parse.y" /* yacc.c:1646 */ - { + case 657: +#line 4882 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, ID2VAL(idNil), (yyvsp[0].id), &(yylsp[-1])); } -#line 11248 "parse.c" /* yacc.c:1646 */ +#line 11373 "parse.c" break; - case 659: -#line 4873 "parse.y" /* yacc.c:1646 */ - { + case 658: +#line 4886 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, Qnone, (yyvsp[0].id), &(yylsp[0])); } -#line 11256 "parse.c" /* yacc.c:1646 */ +#line 11381 "parse.c" break; - case 660: -#line 4879 "parse.y" /* yacc.c:1646 */ - { + case 659: +#line 4892 "parse.y" + { (yyval.node) = (yyvsp[0].node); } -#line 11264 "parse.c" /* yacc.c:1646 */ +#line 11389 "parse.c" break; - case 661: -#line 4883 "parse.y" /* yacc.c:1646 */ - { + case 660: +#line 4896 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); } -#line 11272 "parse.c" /* yacc.c:1646 */ +#line 11397 "parse.c" break; - case 662: -#line 4889 "parse.y" /* yacc.c:1646 */ - { + case 661: +#line 4902 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), (yyvsp[-3].node), (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11280 "parse.c" /* yacc.c:1646 */ +#line 11405 "parse.c" break; - case 663: -#line 4893 "parse.y" /* yacc.c:1646 */ - { + case 662: +#line 4906 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-7].node), (yyvsp[-5].node), (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11288 "parse.c" /* yacc.c:1646 */ +#line 11413 "parse.c" break; - case 664: -#line 4897 "parse.y" /* yacc.c:1646 */ - { + case 663: +#line 4910 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-3].node), (yyvsp[-1].node), Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11296 "parse.c" /* yacc.c:1646 */ +#line 11421 "parse.c" break; - case 665: -#line 4901 "parse.y" /* yacc.c:1646 */ - { + case 664: +#line 4914 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), (yyvsp[-3].node), Qnone, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11304 "parse.c" /* yacc.c:1646 */ +#line 11429 "parse.c" break; - case 666: -#line 4905 "parse.y" /* yacc.c:1646 */ - { + case 665: +#line 4918 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-3].node), Qnone, (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11312 "parse.c" /* yacc.c:1646 */ +#line 11437 "parse.c" break; - case 667: -#line 4909 "parse.y" /* yacc.c:1646 */ - { + case 666: +#line 4922 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-5].node), Qnone, (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11320 "parse.c" /* yacc.c:1646 */ +#line 11445 "parse.c" break; - case 668: -#line 4913 "parse.y" /* yacc.c:1646 */ - { + case 667: +#line 4926 "parse.y" + { (yyval.node) = new_args(p, (yyvsp[-1].node), Qnone, Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11328 "parse.c" /* yacc.c:1646 */ +#line 11453 "parse.c" break; - case 669: -#line 4917 "parse.y" /* yacc.c:1646 */ - { + case 668: +#line 4930 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-3].node), (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11336 "parse.c" /* yacc.c:1646 */ +#line 11461 "parse.c" break; - case 670: -#line 4921 "parse.y" /* yacc.c:1646 */ - { + case 669: +#line 4934 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-5].node), (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11344 "parse.c" /* yacc.c:1646 */ +#line 11469 "parse.c" break; - case 671: -#line 4925 "parse.y" /* yacc.c:1646 */ - { + case 670: +#line 4938 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-1].node), Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11352 "parse.c" /* yacc.c:1646 */ +#line 11477 "parse.c" break; - case 672: -#line 4929 "parse.y" /* yacc.c:1646 */ - { + case 671: +#line 4942 "parse.y" + { (yyval.node) = new_args(p, Qnone, (yyvsp[-3].node), Qnone, (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11360 "parse.c" /* yacc.c:1646 */ +#line 11485 "parse.c" break; - case 673: -#line 4933 "parse.y" /* yacc.c:1646 */ - { + case 672: +#line 4946 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, (yyvsp[-1].id), Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11368 "parse.c" /* yacc.c:1646 */ +#line 11493 "parse.c" break; - case 674: -#line 4937 "parse.y" /* yacc.c:1646 */ - { + case 673: +#line 4950 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, (yyvsp[-3].id), (yyvsp[-1].node), (yyvsp[0].node), &(yyloc)); } -#line 11376 "parse.c" /* yacc.c:1646 */ +#line 11501 "parse.c" break; - case 675: -#line 4941 "parse.y" /* yacc.c:1646 */ - { + case 674: +#line 4954 "parse.y" + { (yyval.node) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyvsp[0].node), &(yyloc)); } -#line 11384 "parse.c" /* yacc.c:1646 */ +#line 11509 "parse.c" break; - case 676: -#line 4945 "parse.y" /* yacc.c:1646 */ - { + case 675: +#line 4958 "parse.y" + { (yyval.node) = new_args_tail(p, Qnone, Qnone, Qnone, &(yylsp[0])); (yyval.node) = new_args(p, Qnone, Qnone, Qnone, Qnone, (yyval.node), &(yylsp[0])); } -#line 11393 "parse.c" /* yacc.c:1646 */ +#line 11518 "parse.c" break; - case 677: -#line 4952 "parse.y" /* yacc.c:1646 */ - { + case 676: +#line 4965 "parse.y" + { /*%%%*/ (yyval.id) = idDot3; /*% %*/ /*% ripper: args_forward! %*/ } -#line 11404 "parse.c" /* yacc.c:1646 */ +#line 11529 "parse.c" break; - case 678: -#line 4961 "parse.y" /* yacc.c:1646 */ - { + case 677: +#line 4974 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "formal argument cannot be a constant"); (yyval.id) = 0; /*% %*/ /*% ripper[error]: param_error!($1) %*/ } -#line 11416 "parse.c" /* yacc.c:1646 */ +#line 11541 "parse.c" break; - case 679: -#line 4969 "parse.y" /* yacc.c:1646 */ - { + case 678: +#line 4982 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "formal argument cannot be an instance variable"); (yyval.id) = 0; /*% %*/ /*% ripper[error]: param_error!($1) %*/ } -#line 11428 "parse.c" /* yacc.c:1646 */ +#line 11553 "parse.c" break; - case 680: -#line 4977 "parse.y" /* yacc.c:1646 */ - { + case 679: +#line 4990 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "formal argument cannot be a global variable"); (yyval.id) = 0; /*% %*/ /*% ripper[error]: param_error!($1) %*/ } -#line 11440 "parse.c" /* yacc.c:1646 */ +#line 11565 "parse.c" break; - case 681: -#line 4985 "parse.y" /* yacc.c:1646 */ - { + case 680: +#line 4998 "parse.y" + { /*%%%*/ yyerror1(&(yylsp[0]), "formal argument cannot be a class variable"); (yyval.id) = 0; /*% %*/ /*% ripper[error]: param_error!($1) %*/ } -#line 11452 "parse.c" /* yacc.c:1646 */ +#line 11577 "parse.c" break; - case 683: -#line 4996 "parse.y" /* yacc.c:1646 */ - { + case 682: +#line 5009 "parse.y" + { formal_argument(p, get_id((yyvsp[0].id))); p->max_numparam = ORDINAL_PARAM; (yyval.id) = (yyvsp[0].id); } -#line 11462 "parse.c" /* yacc.c:1646 */ +#line 11587 "parse.c" break; - case 684: -#line 5004 "parse.y" /* yacc.c:1646 */ - { + case 683: +#line 5017 "parse.y" + { ID id = get_id((yyvsp[0].id)); arg_var(p, id); p->cur_arg = id; (yyval.id) = (yyvsp[0].id); } -#line 11473 "parse.c" /* yacc.c:1646 */ +#line 11598 "parse.c" break; - case 685: -#line 5013 "parse.y" /* yacc.c:1646 */ - { + case 684: +#line 5026 "parse.y" + { p->cur_arg = 0; /*%%%*/ (yyval.node) = NEW_ARGS_AUX((yyvsp[0].id), 1, &NULL_LOC); /*% %*/ /*% ripper: get_value($1) %*/ } -#line 11485 "parse.c" /* yacc.c:1646 */ +#line 11610 "parse.c" break; - case 686: -#line 5021 "parse.y" /* yacc.c:1646 */ - { + case 685: +#line 5034 "parse.y" + { /*%%%*/ ID tid = internal_id(p); YYLTYPE loc; @@ -11509,12 +11634,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: mlhs_paren!($2) %*/ } -#line 11508 "parse.c" /* yacc.c:1646 */ +#line 11633 "parse.c" break; - case 688: -#line 5044 "parse.y" /* yacc.c:1646 */ - { + case 687: +#line 5057 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-2].node); (yyval.node)->nd_plen++; @@ -11523,283 +11648,283 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11522 "parse.c" /* yacc.c:1646 */ +#line 11647 "parse.c" break; - case 689: -#line 5057 "parse.y" /* yacc.c:1646 */ - { + case 688: +#line 5070 "parse.y" + { ID id = get_id((yyvsp[0].id)); arg_var(p, formal_argument(p, id)); p->cur_arg = id; p->max_numparam = ORDINAL_PARAM; (yyval.id) = (yyvsp[0].id); } -#line 11534 "parse.c" /* yacc.c:1646 */ +#line 11659 "parse.c" break; - case 690: -#line 5067 "parse.y" /* yacc.c:1646 */ - { + case 689: +#line 5080 "parse.y" + { p->cur_arg = 0; /*%%%*/ (yyval.node) = new_kw_arg(p, assignable(p, (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), get_value($2)) %*/ } -#line 11546 "parse.c" /* yacc.c:1646 */ +#line 11671 "parse.c" break; - case 691: -#line 5075 "parse.y" /* yacc.c:1646 */ - { + case 690: +#line 5088 "parse.y" + { p->cur_arg = 0; /*%%%*/ (yyval.node) = new_kw_arg(p, assignable(p, (yyvsp[0].id), NODE_SPECIAL_REQUIRED_KEYWORD, &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), 0) %*/ } -#line 11558 "parse.c" /* yacc.c:1646 */ +#line 11683 "parse.c" break; - case 692: -#line 5085 "parse.y" /* yacc.c:1646 */ - { + case 691: +#line 5098 "parse.y" + { /*%%%*/ (yyval.node) = new_kw_arg(p, assignable(p, (yyvsp[-1].id), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), get_value($2)) %*/ } -#line 11569 "parse.c" /* yacc.c:1646 */ +#line 11694 "parse.c" break; - case 693: -#line 5092 "parse.y" /* yacc.c:1646 */ - { + case 692: +#line 5105 "parse.y" + { /*%%%*/ (yyval.node) = new_kw_arg(p, assignable(p, (yyvsp[0].id), NODE_SPECIAL_REQUIRED_KEYWORD, &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), 0) %*/ } -#line 11580 "parse.c" /* yacc.c:1646 */ +#line 11705 "parse.c" break; - case 694: -#line 5101 "parse.y" /* yacc.c:1646 */ - { + case 693: +#line 5114 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 11591 "parse.c" /* yacc.c:1646 */ +#line 11716 "parse.c" break; - case 695: -#line 5108 "parse.y" /* yacc.c:1646 */ - { + case 694: +#line 5121 "parse.y" + { /*%%%*/ (yyval.node) = kwd_append((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11602 "parse.c" /* yacc.c:1646 */ +#line 11727 "parse.c" break; - case 696: -#line 5118 "parse.y" /* yacc.c:1646 */ - { + case 695: +#line 5131 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 11613 "parse.c" /* yacc.c:1646 */ +#line 11738 "parse.c" break; - case 697: -#line 5125 "parse.y" /* yacc.c:1646 */ - { + case 696: +#line 5138 "parse.y" + { /*%%%*/ (yyval.node) = kwd_append((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11624 "parse.c" /* yacc.c:1646 */ +#line 11749 "parse.c" break; - case 700: -#line 5138 "parse.y" /* yacc.c:1646 */ - { + case 699: +#line 5151 "parse.y" + { /*%%%*/ /*% %*/ /*% ripper: nokw_param!(Qnil) %*/ } -#line 11634 "parse.c" /* yacc.c:1646 */ +#line 11759 "parse.c" break; - case 701: -#line 5146 "parse.y" /* yacc.c:1646 */ - { + case 700: +#line 5159 "parse.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].id)))); /*%%%*/ (yyval.id) = (yyvsp[0].id); /*% %*/ /*% ripper: kwrest_param!($2) %*/ } -#line 11646 "parse.c" /* yacc.c:1646 */ +#line 11771 "parse.c" break; - case 702: -#line 5154 "parse.y" /* yacc.c:1646 */ - { + case 701: +#line 5167 "parse.y" + { /*%%%*/ (yyval.id) = internal_id(p); arg_var(p, (yyval.id)); /*% %*/ /*% ripper: kwrest_param!(Qnil) %*/ } -#line 11658 "parse.c" /* yacc.c:1646 */ +#line 11783 "parse.c" break; - case 703: -#line 5164 "parse.y" /* yacc.c:1646 */ - { + case 702: +#line 5177 "parse.y" + { p->cur_arg = 0; /*%%%*/ (yyval.node) = NEW_OPT_ARG(0, assignable(p, (yyvsp[-2].id), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), get_value($3)) %*/ } -#line 11670 "parse.c" /* yacc.c:1646 */ +#line 11795 "parse.c" break; - case 704: -#line 5174 "parse.y" /* yacc.c:1646 */ - { + case 703: +#line 5187 "parse.y" + { p->cur_arg = 0; /*%%%*/ (yyval.node) = NEW_OPT_ARG(0, assignable(p, (yyvsp[-2].id), (yyvsp[0].node), &(yyloc)), &(yyloc)); /*% %*/ /*% ripper: rb_assoc_new(get_value(assignable(p, $1)), get_value($3)) %*/ } -#line 11682 "parse.c" /* yacc.c:1646 */ +#line 11807 "parse.c" break; - case 705: -#line 5184 "parse.y" /* yacc.c:1646 */ - { + case 704: +#line 5197 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 11693 "parse.c" /* yacc.c:1646 */ +#line 11818 "parse.c" break; - case 706: -#line 5191 "parse.y" /* yacc.c:1646 */ - { + case 705: +#line 5204 "parse.y" + { /*%%%*/ (yyval.node) = opt_arg_append((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11704 "parse.c" /* yacc.c:1646 */ +#line 11829 "parse.c" break; - case 707: -#line 5200 "parse.y" /* yacc.c:1646 */ - { + case 706: +#line 5213 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[0].node); /*% %*/ /*% ripper: rb_ary_new3(1, get_value($1)) %*/ } -#line 11715 "parse.c" /* yacc.c:1646 */ +#line 11840 "parse.c" break; - case 708: -#line 5207 "parse.y" /* yacc.c:1646 */ - { + case 707: +#line 5220 "parse.y" + { /*%%%*/ (yyval.node) = opt_arg_append((yyvsp[-2].node), (yyvsp[0].node)); /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11726 "parse.c" /* yacc.c:1646 */ +#line 11851 "parse.c" break; - case 711: -#line 5220 "parse.y" /* yacc.c:1646 */ - { + case 710: +#line 5233 "parse.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].id)))); /*%%%*/ (yyval.id) = (yyvsp[0].id); /*% %*/ /*% ripper: rest_param!($2) %*/ } -#line 11738 "parse.c" /* yacc.c:1646 */ +#line 11863 "parse.c" break; - case 712: -#line 5228 "parse.y" /* yacc.c:1646 */ - { + case 711: +#line 5241 "parse.y" + { /*%%%*/ (yyval.id) = internal_id(p); arg_var(p, (yyval.id)); /*% %*/ /*% ripper: rest_param!(Qnil) %*/ } -#line 11750 "parse.c" /* yacc.c:1646 */ +#line 11875 "parse.c" break; - case 715: -#line 5242 "parse.y" /* yacc.c:1646 */ - { + case 714: +#line 5255 "parse.y" + { arg_var(p, shadowing_lvar(p, get_id((yyvsp[0].id)))); /*%%%*/ (yyval.id) = (yyvsp[0].id); /*% %*/ /*% ripper: blockarg!($2) %*/ } -#line 11762 "parse.c" /* yacc.c:1646 */ +#line 11887 "parse.c" break; - case 716: -#line 5252 "parse.y" /* yacc.c:1646 */ - { + case 715: +#line 5265 "parse.y" + { (yyval.id) = (yyvsp[0].id); } -#line 11770 "parse.c" /* yacc.c:1646 */ +#line 11895 "parse.c" break; - case 717: -#line 5256 "parse.y" /* yacc.c:1646 */ - { + case 716: +#line 5269 "parse.y" + { (yyval.id) = Qnull; } -#line 11778 "parse.c" /* yacc.c:1646 */ +#line 11903 "parse.c" break; - case 718: -#line 5262 "parse.y" /* yacc.c:1646 */ - { + case 717: +#line 5275 "parse.y" + { value_expr((yyvsp[0].node)); (yyval.node) = (yyvsp[0].node); } -#line 11787 "parse.c" /* yacc.c:1646 */ +#line 11912 "parse.c" break; - case 719: -#line 5266 "parse.y" /* yacc.c:1646 */ - {SET_LEX_STATE(EXPR_BEG);} -#line 11793 "parse.c" /* yacc.c:1646 */ + case 718: +#line 5279 "parse.y" + {SET_LEX_STATE(EXPR_BEG);} +#line 11918 "parse.c" break; - case 720: -#line 5267 "parse.y" /* yacc.c:1646 */ - { + case 719: +#line 5280 "parse.y" + { /*%%%*/ switch (nd_type((yyvsp[-1].node))) { case NODE_STR: @@ -11820,23 +11945,23 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: paren!($3) %*/ } -#line 11819 "parse.c" /* yacc.c:1646 */ +#line 11944 "parse.c" break; - case 722: -#line 5292 "parse.y" /* yacc.c:1646 */ - { + case 721: +#line 5305 "parse.y" + { /*%%%*/ (yyval.node) = (yyvsp[-1].node); /*% %*/ /*% ripper: assoclist_from_args!($1) %*/ } -#line 11830 "parse.c" /* yacc.c:1646 */ +#line 11955 "parse.c" break; - case 724: -#line 5303 "parse.y" /* yacc.c:1646 */ - { + case 723: +#line 5316 "parse.y" + { /*%%%*/ NODE *assocs = (yyvsp[-2].node); NODE *tail = (yyvsp[0].node); @@ -11856,12 +11981,12 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: rb_ary_push($1, get_value($3)) %*/ } -#line 11855 "parse.c" /* yacc.c:1646 */ +#line 11980 "parse.c" break; - case 725: -#line 5326 "parse.y" /* yacc.c:1646 */ - { + case 724: +#line 5339 "parse.y" + { /*%%%*/ if (nd_type((yyvsp[-2].node)) == NODE_STR) { nd_set_type((yyvsp[-2].node), NODE_LIT); @@ -11871,35 +11996,35 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: assoc_new!($1, $3) %*/ } -#line 11870 "parse.c" /* yacc.c:1646 */ +#line 11995 "parse.c" break; - case 726: -#line 5337 "parse.y" /* yacc.c:1646 */ - { + case 725: +#line 5350 "parse.y" + { /*%%%*/ (yyval.node) = list_append(p, NEW_LIST(NEW_LIT(ID2SYM((yyvsp[-1].id)), &(yylsp[-1])), &(yyloc)), (yyvsp[0].node)); /*% %*/ /*% ripper: assoc_new!($1, $2) %*/ } -#line 11881 "parse.c" /* yacc.c:1646 */ +#line 12006 "parse.c" break; - case 727: -#line 5344 "parse.y" /* yacc.c:1646 */ - { + case 726: +#line 5357 "parse.y" + { /*%%%*/ YYLTYPE loc = code_loc_gen(&(yylsp[-3]), &(yylsp[-1])); (yyval.node) = list_append(p, NEW_LIST(dsym_node(p, (yyvsp[-2].node), &loc), &loc), (yyvsp[0].node)); /*% %*/ /*% ripper: assoc_new!(dyna_symbol!($2), $4) %*/ } -#line 11893 "parse.c" /* yacc.c:1646 */ +#line 12018 "parse.c" break; - case 728: -#line 5352 "parse.y" /* yacc.c:1646 */ - { + case 727: +#line 5365 "parse.y" + { /*%%%*/ if (nd_type((yyvsp[0].node)) == NODE_HASH && !((yyvsp[0].node)->nd_head && (yyvsp[0].node)->nd_head->nd_alen)) { @@ -11915,37 +12040,38 @@ YYLTYPE yylloc = yyloc_default; /*% %*/ /*% ripper: assoc_splat!($2) %*/ } -#line 11914 "parse.c" /* yacc.c:1646 */ +#line 12039 "parse.c" break; - case 755: -#line 5420 "parse.y" /* yacc.c:1646 */ - {yyerrok;token_flush(p);} -#line 11920 "parse.c" /* yacc.c:1646 */ + case 753: +#line 5430 "parse.y" + {yyerrok;token_flush(p);} +#line 12045 "parse.c" break; - case 756: -#line 5421 "parse.y" /* yacc.c:1646 */ - {token_flush(p);} -#line 11926 "parse.c" /* yacc.c:1646 */ + case 754: +#line 5431 "parse.y" + {token_flush(p);} +#line 12051 "parse.c" break; - case 758: -#line 5425 "parse.y" /* yacc.c:1646 */ - {yyerrok;} -#line 11932 "parse.c" /* yacc.c:1646 */ + case 756: +#line 5435 "parse.y" + {yyerrok;} +#line 12057 "parse.c" break; - case 759: -#line 5429 "parse.y" /* yacc.c:1646 */ - { + case 757: +#line 5439 "parse.y" + { (yyval.node) = Qnull; } -#line 11940 "parse.c" /* yacc.c:1646 */ +#line 12065 "parse.c" break; -#line 11944 "parse.c" /* yacc.c:1646 */ +#line 12069 "parse.c" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -11971,14 +12097,13 @@ YYLTYPE yylloc = yyloc_default; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -12010,7 +12135,7 @@ YYLTYPE yylloc = yyloc_default; { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + yymsg = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); if (!yymsg) { yymsg = yymsgbuf; @@ -12061,14 +12186,11 @@ YYLTYPE yylloc = yyloc_default; | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -12134,6 +12256,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -12141,6 +12264,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -12151,6 +12275,10 @@ YYLTYPE yylloc = yyloc_default; /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -12180,7 +12308,7 @@ YYLTYPE yylloc = yyloc_default; #endif return yyresult; } -#line 5433 "parse.y" /* yacc.c:1906 */ +#line 5443 "parse.y" # undef p # undef yylex @@ -12290,9 +12418,6 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t) #define has_delayed_token(p) (!NIL_P(p->delayed.token)) #endif /* RIPPER */ -#include "ruby/regex.h" -#include "ruby/util.h" - static inline int is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc) { @@ -12598,7 +12723,7 @@ vtable_free_gen(struct parser_params *p, int line, const char *name, if (tbl->tbl) { ruby_sized_xfree(tbl->tbl, tbl->capa * sizeof(ID)); } - ruby_sized_xfree(tbl, sizeof(tbl)); + ruby_sized_xfree(tbl, sizeof(*tbl)); } } #define vtable_free(tbl) vtable_free_gen(p, __LINE__, #tbl, tbl) @@ -16660,19 +16785,6 @@ past_dvar_p(struct parser_params *p, ID id) } # endif -/* As Ripper#warn does not have arguments for the location, so the - * following messages cannot be separated */ -#define WARN_LOCATION(type) do { \ - if (p->warn_location) { \ - int line; \ - VALUE file = rb_source_location(&line); \ - rb_warn3(type" in eval may not return location in binding;" \ - " use Binding#source_location instead\n" \ - "%"PRIsWARN":%d: warning: in `%"PRIsWARN"'", \ - file, WARN_I(line), rb_id2str(rb_frame_this_func())); \ - } \ -} while (0) - static int numparam_nested_p(struct parser_params *p) { @@ -16706,7 +16818,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case keyword_false: return NEW_FALSE(loc); case keyword__FILE__: - WARN_LOCATION("__FILE__"); { VALUE file = p->ruby_sourcefile_string; if (NIL_P(file)) @@ -16718,7 +16829,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) } return node; case keyword__LINE__: - WARN_LOCATION("__LINE__"); return NEW_LIT(INT2FIX(p->tokline), loc); case keyword__ENCODING__: node = NEW_LIT(rb_enc_from_encoding(p->enc), loc); @@ -17999,7 +18109,7 @@ negate_lit(struct parser_params *p, VALUE lit) lit = rb_big_norm(lit); break; case T_RATIONAL: - RRATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); + RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); break; case T_COMPLEX: RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real)); @@ -18800,7 +18910,7 @@ dvar_defined_ref(struct parser_params *p, ID id, ID **vidrefp) if (used) used = used->prev; } - if (vars == DVARS_INHERIT) { + if (vars == DVARS_INHERIT && !NUMPARAM_ID_P(id)) { return rb_dvar_defined(id, p->parent_iseq); } @@ -18995,14 +19105,6 @@ rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split) p->do_split = split; } -void -rb_parser_warn_location(VALUE vparser, int warn) -{ - struct parser_params *p; - TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - p->warn_location = warn; -} - static NODE * parser_append_options(struct parser_params *p, NODE *node) { diff --git a/ruby/parse.h b/ruby/parse.h index 3d74603f0..a2f9bf2fd 100644 --- a/ruby/parse.h +++ b/ruby/parse.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_YY_Y_TAB_H_INCLUDED # define YY_YY_Y_TAB_H_INCLUDED /* Debug traces. */ @@ -170,7 +174,6 @@ extern int yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { @@ -182,8 +185,8 @@ union YYSTYPE const struct vtable *vars; struct rb_strterm_struct *strterm; -}; +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 diff --git a/ruby/parse.y b/ruby/parse.y index d34d3f9ad..7555d0db1 100644 --- a/ruby/parse.y +++ b/ruby/parse.y @@ -20,18 +20,61 @@ #define YYLTYPE rb_code_location_t #define YYLTYPE_IS_DECLARED 1 -#include "ruby/ruby.h" -#include "ruby/st.h" -#include "ruby/encoding.h" +#include "ruby/internal/config.h" + +#include +#include +#include + +struct lex_context; + #include "internal.h" +#include "internal/compile.h" +#include "internal/compilers.h" +#include "internal/complex.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/io.h" +#include "internal/numeric.h" +#include "internal/parse.h" +#include "internal/rational.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/variable.h" #include "node.h" -#include "parse.h" -#include "symbol.h" -#include "regenc.h" -#include -#include -#include #include "probes.h" +#include "regenc.h" +#include "ruby/encoding.h" +#include "ruby/regex.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/util.h" +#include "ruby/ractor.h" +#include "symbol.h" + +enum shareability { + shareable_none, + shareable_literal, + shareable_copy, + shareable_everything, +}; + +struct lex_context { + unsigned int in_defined: 1; + unsigned int in_kwarg: 1; + unsigned int in_argdef: 1; + unsigned int in_def: 1; + unsigned int in_class: 1; + BITFIELD(enum shareability, shareable_constant_value, 2); +}; + +#include "parse.h" + +#define NO_LEX_CTXT (struct lex_context){0} + +#define AREF(ary, i) RARRAY_AREF(ary, i) #ifndef WARN_PAST_SCOPE # define WARN_PAST_SCOPE 0 @@ -46,7 +89,6 @@ #define YYCALLOC(nelem, size) rb_parser_calloc(p, (nelem), (size)) #define YYFREE(ptr) rb_parser_free(p, (ptr)) #define YYFPRINTF rb_parser_printf -#define YYPRINT(out, tok, val) parser_token_value_print(p, (tok), &(val)) #define YY_LOCATION_PRINT(File, loc) \ rb_parser_printf(p, "%d.%d-%d.%d", \ (loc).beg_pos.lineno, (loc).beg_pos.column,\ @@ -64,6 +106,9 @@ (Current).end_pos = YYRHSLOC(Rhs, 0).end_pos; \ } \ while (0) +#define YY_(Msgid) \ + (((Msgid)[0] == 'm') && (strcmp((Msgid), "memory exhausted") == 0) ? \ + "nesting too deep" : (Msgid)) #define RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(Current) \ rb_parser_set_location_from_strterm_heredoc(p, &p->lex.strterm->u.heredoc, &(Current)) @@ -121,10 +166,8 @@ enum lex_state_e { #define IS_lex_state_all(ls) IS_lex_state_all_for(p->lex.state, (ls)) # define SET_LEX_STATE(ls) \ - (p->lex.state = \ - (p->debug ? \ - rb_parser_trace_lex_state(p, p->lex.state, (ls), __LINE__) : \ - (enum lex_state_e)(ls))) + parser_set_lex_state(p, ls, __LINE__) +static inline enum lex_state_e parser_set_lex_state(struct parser_params *p, enum lex_state_e ls, int line); typedef VALUE stack_type; @@ -272,15 +315,13 @@ struct parser_params { int max_numparam; + struct lex_context ctxt; + unsigned int command_start:1; unsigned int eofp: 1; unsigned int ruby__end__seen: 1; unsigned int debug: 1; unsigned int has_shebang: 1; - unsigned int in_defined: 1; - unsigned int in_kwarg: 1; - unsigned int in_def: 1; - unsigned int in_class: 1; unsigned int token_seen: 1; unsigned int token_info_enabled: 1; # if WARN_PAST_SCOPE @@ -296,7 +337,7 @@ struct parser_params { unsigned int do_loop: 1; unsigned int do_chomp: 1; unsigned int do_split: 1; - unsigned int warn_location: 1; + unsigned int keep_script_lines: 1; NODE *eval_tree_begin; NODE *eval_tree; @@ -356,12 +397,21 @@ pop_pktbl(struct parser_params *p, st_table *tbl) p->pktbl = tbl; } +RBIMPL_ATTR_NONNULL((1, 2, 3)) static int parser_yyerror(struct parser_params*, const YYLTYPE *yylloc, const char*); -#define yyerror0(msg) parser_yyerror(p, NULL, (msg)) +RBIMPL_ATTR_NONNULL((1, 2)) +static int parser_yyerror0(struct parser_params*, const char*); +#define yyerror0(msg) parser_yyerror0(p, (msg)) #define yyerror1(loc, msg) parser_yyerror(p, (loc), (msg)) #define yyerror(yylloc, p, msg) parser_yyerror(p, yylloc, msg) #define token_flush(ptr) ((ptr)->lex.ptok = (ptr)->lex.pcur) +static void token_info_setup(token_info *ptinfo, const char *ptr, const rb_code_location_t *loc); +static void token_info_push(struct parser_params*, const char *token, const rb_code_location_t *loc); +static void token_info_pop(struct parser_params*, const char *token, const rb_code_location_t *loc); +static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc); +static void token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos); + #ifdef RIPPER #define compile_for_eval (0) #else @@ -376,6 +426,8 @@ static int parser_yyerror(struct parser_params*, const YYLTYPE *yylloc, const ch #define lambda_beginning_p() (p->lex.lpar_beg == p->lex.paren_nest) +#define ANON_BLOCK_ID '&' + static enum yytokentype yylex(YYSTYPE*, YYLTYPE*, struct parser_params*); #ifndef RIPPER @@ -431,6 +483,7 @@ set_line_body(NODE *body, int line) static NODE* cond(struct parser_params *p, NODE *node, const YYLTYPE *loc); static NODE* method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc); #define new_nil(loc) NEW_NIL(loc) +static NODE *new_nil_at(struct parser_params *p, const rb_code_position_t *pos); static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*); static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*); static NODE *logop(struct parser_params*,ID,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*); @@ -442,7 +495,7 @@ static int value_expr_gen(struct parser_params*,NODE*); static void void_expr(struct parser_params*,NODE*); static NODE *remove_begin(NODE*); static NODE *remove_begin_all(NODE*); -#define value_expr(node) value_expr_gen(p, (node) = remove_begin(node)) +#define value_expr(node) value_expr_gen(p, (node)) static NODE *void_stmts(struct parser_params*,NODE*); static void reduce_nodes(struct parser_params*,NODE**); static void block_dup_check(struct parser_params*,NODE*,NODE*); @@ -455,6 +508,7 @@ static NODE *last_arg_append(struct parser_params *p, NODE *args, NODE *last_arg static NODE *rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc); static NODE *literal_concat(struct parser_params*,NODE*,NODE*,const YYLTYPE*); static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*); +static NODE *new_dstr(struct parser_params*,NODE*,const YYLTYPE*); static NODE *evstr2dstr(struct parser_params*,NODE*); static NODE *splat_array(NODE*); static void mark_lvar_used(struct parser_params *p, NODE *rhs); @@ -470,9 +524,10 @@ static NODE *new_args(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*,const YYL static NODE *new_args_tail(struct parser_params*,NODE*,ID,ID,const YYLTYPE*); static NODE *new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *aryptn, const YYLTYPE *loc); static NODE *new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID rest_arg, NODE *post_args, const YYLTYPE *loc); +static NODE *new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc); +static NODE *new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc); static NODE *new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc); static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, const YYLTYPE *loc); -static NODE *new_case3(struct parser_params *p, NODE *val, NODE *pat, const YYLTYPE *loc); static NODE *new_kw_arg(struct parser_params *p, NODE *k, const YYLTYPE *loc); static NODE *args_with_numbered(struct parser_params*,NODE*,int); @@ -490,12 +545,12 @@ static NODE *aryset(struct parser_params*,NODE*,NODE*,const YYLTYPE*); static NODE *attrset(struct parser_params*,NODE*,ID,ID,const YYLTYPE*); static void rb_backref_error(struct parser_params*,NODE*); -static NODE *node_assign(struct parser_params*,NODE*,NODE*,const YYLTYPE*); +static NODE *node_assign(struct parser_params*,NODE*,NODE*,struct lex_context,const YYLTYPE*); -static NODE *new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc); +static NODE *new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc); static NODE *new_ary_op_assign(struct parser_params *p, NODE *ary, NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc); static NODE *new_attr_op_assign(struct parser_params *p, NODE *lhs, ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc); -static NODE *new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc); +static NODE *new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc); static NODE *new_bodystmt(struct parser_params *p, NODE *head, NODE *rescue, NODE *rescue_else, NODE *ensure, const YYLTYPE *loc); static NODE *const_decl(struct parser_params *p, NODE* path, const YYLTYPE *loc); @@ -518,7 +573,7 @@ static NODE *symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol) static NODE *match_op(struct parser_params*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*); -static ID *local_tbl(struct parser_params*); +static rb_ast_id_table_t *local_tbl(struct parser_params*); static VALUE reg_compile(struct parser_params*, VALUE, int); static void reg_fragment_setenc(struct parser_params*, VALUE, int); @@ -535,6 +590,7 @@ static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYP #define get_num(num) (num) #else /* RIPPER */ #define NODE_RIPPER NODE_CDECL +#define NEW_RIPPER(a,b,c,loc) (VALUE)NEW_CDECL(a,b,c,loc) static inline int ripper_is_node_yylval(VALUE n); @@ -544,13 +600,13 @@ ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c) if (ripper_is_node_yylval(c)) c = RNODE(c)->nd_cval; add_mark_object(p, b); add_mark_object(p, c); - return (VALUE)NEW_CDECL(a, b, c, &NULL_LOC); + return NEW_RIPPER(a, b, c, &NULL_LOC); } static inline int ripper_is_node_yylval(VALUE n) { - return RB_TYPE_P(n, T_NODE) && nd_type(RNODE(n)) == NODE_RIPPER; + return RB_TYPE_P(n, T_NODE) && nd_type_p(RNODE(n), NODE_RIPPER); } #define value_expr(node) ((void)(node)) @@ -579,10 +635,11 @@ static VALUE new_regexp(struct parser_params *, VALUE, VALUE, const YYLTYPE *); static VALUE const_decl(struct parser_params *p, VALUE path); static VALUE var_field(struct parser_params *p, VALUE a); -static VALUE assign_error(struct parser_params *p, VALUE a); +static VALUE assign_error(struct parser_params *p, const char *mesg, VALUE a); static VALUE parser_reg_compile(struct parser_params*, VALUE, int, VALUE *); +static VALUE backref_error(struct parser_params*, NODE *, VALUE); #endif /* !RIPPER */ /* forward declaration */ @@ -602,8 +659,11 @@ RUBY_SYMBOL_EXPORT_END static void error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *loc); static void error_duplicate_pattern_key(struct parser_params *p, ID id, const YYLTYPE *loc); -static void parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp); +#ifndef RIPPER static ID formal_argument(struct parser_params*, ID); +#else +static ID formal_argument(struct parser_params*, VALUE); +#endif static ID shadowing_lvar(struct parser_params*,ID); static void new_bv(struct parser_params*,ID); @@ -615,7 +675,10 @@ static int local_id(struct parser_params *p, ID id); static int local_id_ref(struct parser_params*, ID, ID **); #ifndef RIPPER static ID internal_id(struct parser_params*); +static NODE *new_args_forward_call(struct parser_params*, NODE*, const YYLTYPE*, const YYLTYPE*); #endif +static int check_forwarding_args(struct parser_params*); +static void add_forwarding_args(struct parser_params *p); static const struct vtable *dyna_push(struct parser_params *); static void dyna_pop(struct parser_params*, const struct vtable *); @@ -796,14 +859,7 @@ static VALUE new_array_pattern(struct parser_params *p, VALUE constant, VALUE pre_arg, VALUE aryptn, const YYLTYPE *loc) { NODE *t = (NODE *)aryptn; - struct rb_ary_pattern_info *apinfo = t->nd_apinfo; - VALUE pre_args = Qnil, rest_arg = Qnil, post_args = Qnil; - - if (apinfo) { - pre_args = rb_ary_entry(apinfo->imemo, 0); - rest_arg = rb_ary_entry(apinfo->imemo, 1); - post_args = rb_ary_entry(apinfo->imemo, 2); - } + VALUE pre_args = t->u1.value, rest_arg = t->u2.value, post_args = t->u3.value; if (!NIL_P(pre_arg)) { if (!NIL_P(pre_args)) { @@ -820,7 +876,6 @@ static VALUE new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest, VALUE rest_arg, VALUE post_args, const YYLTYPE *loc) { NODE *t; - struct rb_ary_pattern_info *apinfo; if (has_rest) { rest_arg = dispatch1(var_field, rest_arg ? rest_arg : Qnil); @@ -829,14 +884,34 @@ new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest, rest_arg = Qnil; } - VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer(); - apinfo = ZALLOC(struct rb_ary_pattern_info); - rb_imemo_tmpbuf_set_ptr(tmpbuf, apinfo); - apinfo->imemo = rb_ary_new_from_args(4, pre_args, rest_arg, post_args, tmpbuf); + t = rb_node_newnode(NODE_ARYPTN, pre_args, rest_arg, post_args, &NULL_LOC); + add_mark_object(p, pre_args); + add_mark_object(p, rest_arg); + add_mark_object(p, post_args); + return (VALUE)t; +} + +static VALUE +new_find_pattern(struct parser_params *p, VALUE constant, VALUE fndptn, const YYLTYPE *loc) +{ + NODE *t = (NODE *)fndptn; + VALUE pre_rest_arg = t->u1.value, args = t->u2.value, post_rest_arg = t->u3.value; + + return dispatch4(fndptn, constant, pre_rest_arg, args, post_rest_arg); +} + +static VALUE +new_find_pattern_tail(struct parser_params *p, VALUE pre_rest_arg, VALUE args, VALUE post_rest_arg, const YYLTYPE *loc) +{ + NODE *t; - t = rb_node_newnode(NODE_ARYPTN, Qnil, Qnil, (VALUE)apinfo, &NULL_LOC); - RB_OBJ_WRITTEN(p->ast, Qnil, apinfo->imemo); + pre_rest_arg = dispatch1(var_field, pre_rest_arg ? pre_rest_arg : Qnil); + post_rest_arg = dispatch1(var_field, post_rest_arg ? post_rest_arg : Qnil); + t = rb_node_newnode(NODE_FNDPTN, pre_rest_arg, args, post_rest_arg, &NULL_LOC); + add_mark_object(p, pre_rest_arg); + add_mark_object(p, args); + add_mark_object(p, post_rest_arg); return (VALUE)t; } @@ -881,8 +956,53 @@ static VALUE heredoc_dedent(struct parser_params*,VALUE); #define ID2VAL(id) (id) #define TOKEN2VAL(t) ID2VAL(t) #define KWD2EID(t, v) keyword_##t + +static NODE * +set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const YYLTYPE *loc) +{ + body = remove_begin(body); + reduce_nodes(p, &body); + n->nd_defn = NEW_SCOPE(args, body, loc); + n->nd_loc = *loc; + nd_set_line(n->nd_defn, loc->end_pos.lineno); + set_line_body(body, loc->beg_pos.lineno); + return n; +} + +static NODE * +rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue, + const YYLTYPE *arg_loc, const YYLTYPE *mod_loc, const YYLTYPE *res_loc) +{ + YYLTYPE loc = code_loc_gen(mod_loc, res_loc); + rescue = NEW_RESBODY(0, remove_begin(rescue), 0, &loc); + loc.beg_pos = arg_loc->beg_pos; + return NEW_RESCUE(arg, rescue, 0, &loc); +} + #endif /* RIPPER */ +static void +restore_defun(struct parser_params *p, NODE *name) +{ + YYSTYPE c = {.val = name->nd_cval}; + p->cur_arg = name->nd_vid; + p->ctxt.in_def = c.ctxt.in_def; + p->ctxt.shareable_constant_value = c.ctxt.shareable_constant_value; +} + +static void +endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc) +{ +#ifdef RIPPER + defn = defn->nd_defn; +#endif + ID mid = defn->nd_mid; + if (is_attrset_id(mid)) { + yyerror1(loc, "setter method cannot be defined in an endless method definition"); + } + token_info_drop(p, "def", loc->beg_pos); +} + #ifndef RIPPER # define Qnone 0 # define Qnull 0 @@ -915,12 +1035,14 @@ static VALUE heredoc_dedent(struct parser_params*,VALUE); # define rb_warning4L(l,fmt,a,b,c,d) WARNING_CALL(WARNING_ARGS_L(l, fmt, 5), (a), (b), (c), (d)) #ifdef RIPPER static ID id_warn, id_warning, id_gets, id_assoc; +# define ERR_MESG() STR_NEW2(mesg) /* to bypass Ripper DSL */ # define WARN_S_L(s,l) STR_NEW(s,l) # define WARN_S(s) STR_NEW2(s) # define WARN_I(i) INT2NUM(i) # define WARN_ID(i) rb_id2str(i) # define WARN_IVAL(i) i # define PRIsWARN "s" +# define rb_warn0L_experimental(l,fmt) WARN_CALL(WARN_ARGS_L(l, fmt, 1)) # define WARN_ARGS(fmt,n) p->value, id_warn, n, rb_usascii_str_new_lit(fmt) # define WARN_ARGS_L(l,fmt,n) WARN_ARGS(fmt,n) # ifdef HAVE_VA_ARGS_MACRO @@ -947,6 +1069,7 @@ PRINTF_ARGS(static void ripper_compile_error(struct parser_params*, const char * # define WARN_ARGS(fmt,n) WARN_ARGS_L(p->ruby_sourceline,fmt,n) # define WARN_ARGS_L(l,fmt,n) p->ruby_sourcefile, (l), (fmt) # define WARN_CALL rb_compile_warn +# define rb_warn0L_experimental(l,fmt) rb_category_compile_warn(RB_WARN_CATEGORY_EXPERIMENTAL, WARN_ARGS_L(l, fmt, 1)) # define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n) # define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n) # define WARNING_CALL rb_compile_warning @@ -954,11 +1077,6 @@ PRINTF_ARGS(static void parser_compile_error(struct parser_params*, const char * # define compile_error parser_compile_error #endif -static void token_info_setup(token_info *ptinfo, const char *ptr, const rb_code_location_t *loc); -static void token_info_push(struct parser_params*, const char *token, const rb_code_location_t *loc); -static void token_info_pop(struct parser_params*, const char *token, const rb_code_location_t *loc); -static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc); - #define WARN_EOL(tok) \ (looking_at_eol_p(p) ? \ (void)rb_warning0("`" tok "' at the end of line without an expression") : \ @@ -968,6 +1086,36 @@ static int looking_at_eol_p(struct parser_params *p); %expect 0 %define api.pure +%define parse.error verbose +%printer { +#ifndef RIPPER + rb_parser_printf(p, "%"PRIsVALUE, rb_id2str($$)); +#else + rb_parser_printf(p, "%"PRIsVALUE, RNODE($$)->nd_rval); +#endif +} tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tOP_ASGN +%printer { +#ifndef RIPPER + rb_parser_printf(p, "%+"PRIsVALUE, $$->nd_lit); +#else + rb_parser_printf(p, "%+"PRIsVALUE, get_value($$)); +#endif +} tINTEGER tFLOAT tRATIONAL tIMAGINARY tSTRING_CONTENT tCHAR +%printer { +#ifndef RIPPER + rb_parser_printf(p, "$%ld", $$->nd_nth); +#else + rb_parser_printf(p, "%"PRIsVALUE, $$); +#endif +} tNTH_REF +%printer { +#ifndef RIPPER + rb_parser_printf(p, "$%c", (int)$$->nd_nth); +#else + rb_parser_printf(p, "%"PRIsVALUE, $$); +#endif +} tBACK_REF + %lex-param {struct parser_params *p} %parse-param {struct parser_params *p} %initial-action @@ -983,6 +1131,7 @@ static int looking_at_eol_p(struct parser_params *p); st_table *tbl; const struct vtable *vars; struct rb_strterm_struct *strterm; + struct lex_context ctxt; } %token @@ -1042,7 +1191,7 @@ static int looking_at_eol_p(struct parser_params *p); %token tIVAR "instance variable" %token tCONSTANT "constant" %token tCVAR "class variable" -%token tLABEL +%token tLABEL "label" %token tINTEGER "integer literal" %token tFLOAT "float literal" %token tRATIONAL "rational literal" @@ -1056,7 +1205,7 @@ static int looking_at_eol_p(struct parser_params *p); %type singleton strings string string1 xstring regexp %type string_contents xstring_contents regexp_contents string_content %type words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word -%type literal numeric simple_numeric ssym dsym symbol cpath +%type literal numeric simple_numeric ssym dsym symbol cpath def_name defn_head defs_head %type top_compstmt top_stmts top_stmt begin_block %type bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call %type expr_value expr_value_do arg_value primary_value fcall rel_expr @@ -1067,7 +1216,8 @@ static int looking_at_eol_p(struct parser_params *p); %type command_rhs arg_rhs %type command_asgn mrhs mrhs_arg superclass block_call block_command %type f_block_optarg f_block_opt -%type f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs f_rest_marg +%type f_arglist f_opt_paren_args f_paren_args f_args f_arg f_arg_item +%type f_optarg f_marg f_marg_list f_margs f_rest_marg %type assoc_list assocs assoc undef_list backref string_dvar for_var %type block_param opt_block_param block_param_def f_opt %type f_kwarg f_kw f_block_kwarg f_block_kw @@ -1076,15 +1226,16 @@ static int looking_at_eol_p(struct parser_params *p); %type brace_block cmd_brace_block do_block lhs none fitem %type mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner %type p_case_body p_cases p_top_expr p_top_expr_body -%type p_expr p_as p_alt p_expr_basic +%type p_expr p_as p_alt p_expr_basic p_find %type p_args p_args_head p_args_tail p_args_post p_arg -%type p_value p_primitive p_variable p_var_ref p_const +%type p_value p_primitive p_variable p_var_ref p_expr_ref p_const %type p_kwargs p_kwarg p_kw %type keyword_variable user_variable sym operation operation2 operation3 %type cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg %type f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon -%type p_kwrest p_kwnorest p_kw_label -%type f_no_kwarg args_forward +%type p_rest p_kwrest p_kwnorest p_any_kwrest p_kw_label +%type f_no_kwarg f_any_kwrest args_forward excessed_comma nonlocal_var + %type lex_ctxt /* keep in ripper */ %token END_OF_INPUT 0 "end-of-input" %token '.' /* escaped chars, should be ignored otherwise */ @@ -1183,7 +1334,7 @@ program : { if ($2 && !compile_for_eval) { NODE *node = $2; /* last expression should not be void */ - if (nd_type(node) == NODE_BLOCK) { + if (nd_type_p(node, NODE_BLOCK)) { while (node->nd_next) { node = node->nd_next; } @@ -1345,11 +1496,12 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem } | keyword_alias tGVAR tNTH_REF { + static const char mesg[] = "can't make alias for the number variables"; /*%%%*/ - yyerror1(&@3, "can't make alias for the number variables"); + yyerror1(&@3, mesg); $$ = NEW_BEGIN(0, &@$); /*% %*/ - /*% ripper[error]: alias_error!(var_alias!($2, $3)) %*/ + /*% ripper[error]: alias_error!(ERR_MESG(), $3) %*/ } | keyword_undef undef_list { @@ -1377,7 +1529,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem | stmt modifier_while expr_value { /*%%%*/ - if ($1 && nd_type($1) == NODE_BEGIN) { + if ($1 && nd_type_p($1, NODE_BEGIN)) { $$ = NEW_WHILE(cond(p, $3, &@3), $1->nd_body, 0, &@$); } else { @@ -1389,7 +1541,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem | stmt modifier_until expr_value { /*%%%*/ - if ($1 && nd_type($1) == NODE_BEGIN) { + if ($1 && nd_type_p($1, NODE_BEGIN)) { $$ = NEW_UNTIL(cond(p, $3, &@3), $1->nd_body, 0, &@$); } else { @@ -1410,7 +1562,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem } | keyword_END '{' compstmt '}' { - if (p->in_def) { + if (p->ctxt.in_def) { rb_warn0("END in method; use at_exit"); } /*%%%*/ @@ -1423,99 +1575,147 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem /*% ripper: END!($3) %*/ } | command_asgn - | mlhs '=' command_call + | mlhs '=' lex_ctxt command_call { /*%%%*/ - value_expr($3); - $$ = node_assign(p, $1, $3, &@$); + value_expr($4); + $$ = node_assign(p, $1, $4, $3, &@$); /*% %*/ - /*% ripper: massign!($1, $3) %*/ + /*% ripper: massign!($1, $4) %*/ } - | lhs '=' mrhs + | lhs '=' lex_ctxt mrhs { /*%%%*/ - value_expr($3); - $$ = node_assign(p, $1, $3, &@$); + $$ = node_assign(p, $1, $4, $3, &@$); /*% %*/ - /*% ripper: assign!($1, $3) %*/ + /*% ripper: assign!($1, $4) %*/ } - | mlhs '=' mrhs_arg modifier_rescue stmt + | mlhs '=' lex_ctxt mrhs_arg modifier_rescue stmt { /*%%%*/ - YYLTYPE loc = code_loc_gen(&@4, &@5); - value_expr($3); - $$ = node_assign(p, $1, NEW_RESCUE($3, NEW_RESBODY(0, remove_begin($5), 0, &loc), 0, &@$), &@$); + YYLTYPE loc = code_loc_gen(&@5, &@6); + $$ = node_assign(p, $1, NEW_RESCUE($4, NEW_RESBODY(0, remove_begin($6), 0, &loc), 0, &@$), $3, &@$); /*% %*/ - /*% ripper: massign!($1, rescue_mod!($3, $5)) %*/ + /*% ripper: massign!($1, rescue_mod!($4, $6)) %*/ } - | mlhs '=' mrhs_arg + | mlhs '=' lex_ctxt mrhs_arg { /*%%%*/ - $$ = node_assign(p, $1, $3, &@$); + $$ = node_assign(p, $1, $4, $3, &@$); /*% %*/ - /*% ripper: massign!($1, $3) %*/ + /*% ripper: massign!($1, $4) %*/ } | expr ; -command_asgn : lhs '=' command_rhs +command_asgn : lhs '=' lex_ctxt command_rhs { /*%%%*/ - $$ = node_assign(p, $1, $3, &@$); + $$ = node_assign(p, $1, $4, $3, &@$); /*% %*/ - /*% ripper: assign!($1, $3) %*/ + /*% ripper: assign!($1, $4) %*/ } - | var_lhs tOP_ASGN command_rhs + | var_lhs tOP_ASGN lex_ctxt command_rhs { /*%%%*/ - $$ = new_op_assign(p, $1, $2, $3, &@$); + $$ = new_op_assign(p, $1, $2, $4, $3, &@$); /*% %*/ - /*% ripper: opassign!($1, $2, $3) %*/ + /*% ripper: opassign!($1, $2, $4) %*/ } - | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs + | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt command_rhs { /*%%%*/ - $$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$); + $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$); /*% %*/ - /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/ + /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $7) %*/ } - | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs + | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt command_rhs { /*%%%*/ - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); + $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ + /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/ } - | primary_value call_op tCONSTANT tOP_ASGN command_rhs + | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt command_rhs { /*%%%*/ - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); + $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ + /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/ } - | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs + | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt command_rhs { /*%%%*/ YYLTYPE loc = code_loc_gen(&@1, &@3); - $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $5, &@$); + $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$); + /*% %*/ + /*% ripper: opassign!(const_path_field!($1, $3), $4, $6) %*/ + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt command_rhs + { + /*%%%*/ + $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$); + /*% %*/ + /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/ + } + | defn_head f_opt_paren_args '=' command + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $$ = set_defun_body(p, $1, $2, $4, &@$); /*% %*/ - /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/ + /*% ripper[$4]: bodystmt!($4, Qnil, Qnil, Qnil) %*/ + /*% ripper: def!(get_value($1), $2, $4) %*/ + local_pop(p); } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs + | defn_head f_opt_paren_args '=' command modifier_rescue arg { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); /*%%%*/ - $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$); + $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6); + $$ = set_defun_body(p, $1, $2, $4, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/ + /*% ripper[$4]: bodystmt!(rescue_mod!($4, $6), Qnil, Qnil, Qnil) %*/ + /*% ripper: def!(get_value($1), $2, $4) %*/ + local_pop(p); + } + | defs_head f_opt_paren_args '=' command + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% + $1 = get_value($1); + %*/ + /*% ripper[$4]: bodystmt!($4, Qnil, Qnil, Qnil) %*/ + /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/ + local_pop(p); + } + | defs_head f_opt_paren_args '=' command modifier_rescue arg + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6); + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% + $1 = get_value($1); + %*/ + /*% ripper[$4]: bodystmt!(rescue_mod!($4, $6), Qnil, Qnil, Qnil) %*/ + /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/ + local_pop(p); } - | backref tOP_ASGN command_rhs + | backref tOP_ASGN lex_ctxt command_rhs { /*%%%*/ rb_backref_error(p, $1); $$ = NEW_BEGIN(0, &@$); /*% %*/ - /*% ripper[error]: assign_error!(assign!(var_field(p, $1), $3)) %*/ + /*% ripper[error]: backref_error(p, RNODE($1), assign!(var_field(p, $1), $4)) %*/ } ; @@ -1553,27 +1753,90 @@ expr : command_call { $$ = call_uni_op(p, method_cond(p, $2, &@2), '!', &@1, &@$); } + | arg tASSOC + { + value_expr($1); + SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); + p->command_start = FALSE; + $2 = p->ctxt; + p->ctxt.in_kwarg = 1; + $$ = push_pvtbl(p); + } + p_top_expr_body + { + pop_pvtbl(p, $3); + p->ctxt.in_kwarg = $2.in_kwarg; + /*%%%*/ + $$ = NEW_CASE3($1, NEW_IN($4, 0, 0, &@4), &@$); + /*% %*/ + /*% ripper: case!($1, in!($4, Qnil, Qnil)) %*/ + } | arg keyword_in { value_expr($1); SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; - $$ = p->in_kwarg; - p->in_kwarg = 1; + $2 = p->ctxt; + p->ctxt.in_kwarg = 1; + $$ = push_pvtbl(p); } - {$$ = push_pvtbl(p);} - p_expr - {pop_pvtbl(p, $4);} + p_top_expr_body { - p->in_kwarg = !!$3; + pop_pvtbl(p, $3); + p->ctxt.in_kwarg = $1.in_kwarg; /*%%%*/ - $$ = new_case3(p, $1, NEW_IN($5, 0, 0, &@5), &@$); + $$ = NEW_CASE3($1, NEW_IN($4, NEW_TRUE(&@4), NEW_FALSE(&@4), &@4), &@$); /*% %*/ - /*% ripper: case!($1, in!($5, Qnil, Qnil)) %*/ + /*% ripper: case!($1, in!($4, Qnil, Qnil)) %*/ } | arg %prec tLBRACE_ARG ; +def_name : fname + { + ID fname = get_id($1); + ID cur_arg = p->cur_arg; + YYSTYPE c = {.ctxt = p->ctxt}; + numparam_name(p, fname); + local_push(p, 0); + p->cur_arg = 0; + p->ctxt.in_def = 1; + $$ = NEW_NODE(NODE_SELF, /*vid*/cur_arg, /*mid*/fname, /*cval*/c.val, &@$); + /*%%%*/ + /*% + $$ = NEW_RIPPER(fname, get_value($1), $$, &NULL_LOC); + %*/ + } + ; + +defn_head : k_def def_name + { + $$ = $2; + /*%%%*/ + $$ = NEW_NODE(NODE_DEFN, 0, $$->nd_mid, $$, &@$); + /*% %*/ + } + ; + +defs_head : k_def singleton dot_or_colon + { + SET_LEX_STATE(EXPR_FNAME); + p->ctxt.in_argdef = 1; + } + def_name + { + SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */ + $$ = $5; + /*%%%*/ + $$ = NEW_NODE(NODE_DEFS, $2, $$->nd_mid, $$, &@$); + /*% + VALUE ary = rb_ary_new_from_args(3, $2, $3, get_value($$)); + add_mark_object(p, ary); + $$->nd_rval = ary; + %*/ + } + ; + expr_value : expr { value_expr($1); @@ -1585,7 +1848,7 @@ expr_value_do : {COND_PUSH(1);} expr_value do {COND_POP();} { $$ = $2; } - + ; command_call : command | block_command @@ -1910,7 +2173,7 @@ mlhs_node : user_variable rb_backref_error(p, $1); $$ = NEW_BEGIN(0, &@$); /*% %*/ - /*% ripper[error]: assign_error!(var_field(p, $1)) %*/ + /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/ } ; @@ -1976,16 +2239,17 @@ lhs : user_variable rb_backref_error(p, $1); $$ = NEW_BEGIN(0, &@$); /*% %*/ - /*% ripper[error]: assign_error!(var_field(p, $1)) %*/ + /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/ } ; cname : tIDENTIFIER { + static const char mesg[] = "class/module name must be CONSTANT"; /*%%%*/ - yyerror1(&@1, "class/module name must be CONSTANT"); + yyerror1(&@1, mesg); /*% %*/ - /*% ripper[error]: class_name_error!($1) %*/ + /*% ripper[error]: class_name_error!(ERR_MESG(), $1) %*/ } | tCONSTANT ; @@ -2022,10 +2286,6 @@ fname : tIDENTIFIER $$ = $1; } | reswords - { - SET_LEX_STATE(EXPR_ENDFN); - $$ = $1; - } ; fitem : fname @@ -2101,74 +2361,71 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg : lhs '=' arg_rhs +arg : lhs '=' lex_ctxt arg_rhs { /*%%%*/ - $$ = node_assign(p, $1, $3, &@$); + $$ = node_assign(p, $1, $4, $3, &@$); /*% %*/ - /*% ripper: assign!($1, $3) %*/ + /*% ripper: assign!($1, $4) %*/ } - | var_lhs tOP_ASGN arg_rhs + | var_lhs tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - $$ = new_op_assign(p, $1, $2, $3, &@$); + $$ = new_op_assign(p, $1, $2, $4, $3, &@$); /*% %*/ - /*% ripper: opassign!($1, $2, $3) %*/ + /*% ripper: opassign!($1, $2, $4) %*/ } - | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs + | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - value_expr($6); - $$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$); + $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$); /*% %*/ - /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/ + /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $7) %*/ } - | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs + | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - value_expr($5); - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); + $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ + /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/ } - | primary_value call_op tCONSTANT tOP_ASGN arg_rhs + | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - value_expr($5); - $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$); + $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/ + /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/ } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - value_expr($5); - $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$); + $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$); /*% %*/ - /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/ + /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/ } - | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs + | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ YYLTYPE loc = code_loc_gen(&@1, &@3); - $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $5, &@$); + $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$); /*% %*/ - /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/ + /*% ripper: opassign!(const_path_field!($1, $3), $4, $6) %*/ } - | tCOLON3 tCONSTANT tOP_ASGN arg_rhs + | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ - $$ = new_const_op_assign(p, NEW_COLON3($2, &@$), $3, $4, &@$); + YYLTYPE loc = code_loc_gen(&@1, &@2); + $$ = new_const_op_assign(p, NEW_COLON3($2, &loc), $3, $5, $4, &@$); /*% %*/ - /*% ripper: opassign!(top_const_field!($2), $3, $4) %*/ + /*% ripper: opassign!(top_const_field!($2), $3, $5) %*/ } - | backref tOP_ASGN arg_rhs + | backref tOP_ASGN lex_ctxt arg_rhs { /*%%%*/ rb_backref_error(p, $1); $$ = NEW_BEGIN(0, &@$); /*% %*/ - /*% ripper[error]: assign_error!(opassign!(var_field(p, $1), $2, $3)) %*/ + /*% ripper[error]: backref_error(p, RNODE($1), opassign!(var_field(p, $1), $2, $4)) %*/ } | arg tDOT2 arg { @@ -2191,48 +2448,32 @@ arg : lhs '=' arg_rhs | arg tDOT2 { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @2.end_pos; - loc.end_pos = @2.end_pos; - value_expr($1); - $$ = NEW_DOT2($1, new_nil(&loc), &@$); + $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$); /*% %*/ /*% ripper: dot2!($1, Qnil) %*/ } | arg tDOT3 { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @2.end_pos; - loc.end_pos = @2.end_pos; - value_expr($1); - $$ = NEW_DOT3($1, new_nil(&loc), &@$); + $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$); /*% %*/ /*% ripper: dot3!($1, Qnil) %*/ } | tBDOT2 arg { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @1.beg_pos; - loc.end_pos = @1.beg_pos; - value_expr($2); - $$ = NEW_DOT2(new_nil(&loc), $2, &@$); + $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$); /*% %*/ /*% ripper: dot2!(Qnil, $2) %*/ } | tBDOT3 arg { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @1.beg_pos; - loc.end_pos = @1.beg_pos; - value_expr($2); - $$ = NEW_DOT3(new_nil(&loc), $2, &@$); + $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$); /*% %*/ /*% ripper: dot3!(Qnil, $2) %*/ } @@ -2333,9 +2574,9 @@ arg : lhs '=' arg_rhs { $$ = logop(p, idOROP, $1, $3, &@2, &@$); } - | keyword_defined opt_nl {p->in_defined = 1;} arg + | keyword_defined opt_nl {p->ctxt.in_defined = 1;} arg { - p->in_defined = 0; + p->ctxt.in_defined = 0; $$ = new_defined(p, $4, &@$); } | arg '?' arg opt_nl ':' arg @@ -2347,6 +2588,56 @@ arg : lhs '=' arg_rhs /*% %*/ /*% ripper: ifop!($1, $3, $6) %*/ } + | defn_head f_opt_paren_args '=' arg + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% %*/ + /*% ripper[$4]: bodystmt!($4, Qnil, Qnil, Qnil) %*/ + /*% ripper: def!(get_value($1), $2, $4) %*/ + local_pop(p); + } + | defn_head f_opt_paren_args '=' arg modifier_rescue arg + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6); + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% %*/ + /*% ripper[$4]: bodystmt!(rescue_mod!($4, $6), Qnil, Qnil, Qnil) %*/ + /*% ripper: def!(get_value($1), $2, $4) %*/ + local_pop(p); + } + | defs_head f_opt_paren_args '=' arg + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% + $1 = get_value($1); + %*/ + /*% ripper[$4]: bodystmt!($4, Qnil, Qnil, Qnil) %*/ + /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/ + local_pop(p); + } + | defs_head f_opt_paren_args '=' arg modifier_rescue arg + { + endless_method_name(p, $1, &@1); + restore_defun(p, $1->nd_defn); + /*%%%*/ + $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6); + $$ = set_defun_body(p, $1, $2, $4, &@$); + /*% + $1 = get_value($1); + %*/ + /*% ripper[$4]: bodystmt!(rescue_mod!($4, $6), Qnil, Qnil, Qnil) %*/ + /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/ + local_pop(p); + } | primary { $$ = $1; @@ -2370,6 +2661,16 @@ rel_expr : arg relop arg %prec '>' } ; +lex_ctxt : tSP + { + $$ = p->ctxt; + } + | none + { + $$ = p->ctxt; + } + ; + arg_value : arg { value_expr($1); @@ -2406,9 +2707,8 @@ arg_rhs : arg %prec tOP_ASGN | arg modifier_rescue arg { /*%%%*/ - YYLTYPE loc = code_loc_gen(&@2, &@3); value_expr($1); - $$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($3), 0, &loc), 0, &@$); + $$ = rescued_expr(p, $1, $3, &@1, &@2, &@3); /*% %*/ /*% ripper: rescue_mod!($1, $3) %*/ } @@ -2421,29 +2721,26 @@ paren_args : '(' opt_call_args rparen /*% %*/ /*% ripper: arg_paren!(escape_Qundef($2)) %*/ } + | '(' args ',' args_forward rparen + { + if (!check_forwarding_args(p)) { + $$ = Qnone; + } + else { + /*%%%*/ + $$ = new_args_forward_call(p, $2, &@4, &@$); + /*% %*/ + /*% ripper: arg_paren!(args_add!($2, $4)) %*/ + } + } | '(' args_forward rparen { - if (!local_id(p, idFWD_REST) || -#if idFWD_KWREST - !local_id(p, idFWD_KWREST) || -#endif - !local_id(p, idFWD_BLOCK)) { - compile_error(p, "unexpected ..."); + if (!check_forwarding_args(p)) { $$ = Qnone; } else { /*%%%*/ - NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@2), &@2); -#if idFWD_KWREST - NODE *kwrest = list_append(p, NEW_LIST(0, &@2), NEW_LVAR(idFWD_KWREST, &@2)); -#endif - NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@2), &@2); -#if idFWD_KWREST - $$ = arg_append(p, splat, new_hash(p, kwrest, &@2), &@2); -#else - $$ = splat; -#endif - $$ = arg_blk_pass($$, block); + $$ = new_args_forward_call(p, 0, &@2, &@$); /*% %*/ /*% ripper: arg_paren!($2) %*/ } @@ -2555,6 +2852,17 @@ block_arg : tAMPER arg_value /*% %*/ /*% ripper: $2 %*/ } + | tAMPER + { + /*%%%*/ + if (!local_id(p, ANON_BLOCK_ID)) { + compile_error(p, "no anonymous block parameter"); + } + $$ = NEW_BLOCK_PASS(NEW_LVAR(ANON_BLOCK_ID, &@1), &@$); + /*% + $$ = Qnil; + %*/ + } ; opt_block_arg : ',' block_arg @@ -2567,6 +2875,7 @@ opt_block_arg : ',' block_arg } ; +/* value */ args : arg_value { /*%%%*/ @@ -2597,10 +2906,12 @@ args : arg_value } ; +/* value */ mrhs_arg : mrhs | arg_value ; +/* value */ mrhs : args ',' arg_value { /*%%%*/ @@ -2666,7 +2977,7 @@ primary : literal | tLPAREN_ARG stmt {SET_LEX_STATE(EXPR_ENDARG);} rparen { /*%%%*/ - if (nd_type($2) == NODE_SELF) $2->nd_state = 0; + if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0; $$ = $2; /*% %*/ /*% ripper: paren!($2) %*/ @@ -2674,7 +2985,7 @@ primary : literal | tLPAREN compstmt ')' { /*%%%*/ - if (nd_type($2) == NODE_SELF) $2->nd_state = 0; + if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0; $$ = $2; /*% %*/ /*% ripper: paren!($2) %*/ @@ -2736,9 +3047,9 @@ primary : literal /*% %*/ /*% ripper: yield0! %*/ } - | keyword_defined opt_nl '(' {p->in_defined = 1;} expr rparen + | keyword_defined opt_nl '(' {p->ctxt.in_defined = 1;} expr rparen { - p->in_defined = 0; + p->ctxt.in_defined = 0; $$ = new_defined(p, $5, &@$); } | keyword_not '(' expr rparen @@ -2765,17 +3076,7 @@ primary : literal /*% %*/ /*% ripper: method_add_block!($1, $2) %*/ } - | tLAMBDA - { - token_info_push(p, "->", &@1); - } - lambda - { - $$ = $3; - /*%%%*/ - nd_set_first_loc($$, @1.beg_pos); - /*% %*/ - } + | lambda | k_if expr_value then compstmt if_tail @@ -2854,7 +3155,7 @@ primary : literal k_end { /*%%%*/ - $$ = new_case3(p, $2, $4, &@$); + $$ = NEW_CASE3($2, $4, &@$); /*% %*/ /*% ripper: case!($2, $4) %*/ } @@ -2875,31 +3176,26 @@ primary : literal ID id = internal_id(p); NODE *m = NEW_ARGS_AUX(0, 0, &NULL_LOC); NODE *args, *scope, *internal_var = NEW_DVAR(id, &@2); - VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer(); - ID *tbl = ALLOC_N(ID, 3); - rb_imemo_tmpbuf_set_ptr(tmpbuf, tbl); - tbl[0] = 1 /* length of local var table */; tbl[1] = id /* internal id */; - tbl[2] = tmpbuf; + rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1); + tbl->ids[0] = id; /* internal id */ switch (nd_type($2)) { case NODE_LASGN: - case NODE_DASGN: - case NODE_DASGN_CURR: /* e.each {|internal_var| a = internal_var; ... } */ + case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */ $2->nd_value = internal_var; id = 0; m->nd_plen = 1; m->nd_next = $2; break; case NODE_MASGN: /* e.each {|*internal_var| a, b, c = (internal_var.length == 1 && Array === (tmp = internal_var[0]) ? tmp : internal_var); ... } */ - m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(internal_var, &@2), &@2); + m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(internal_var, &@2), NO_LEX_CTXT, &@2); break; default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */ - m->nd_next = node_assign(p, NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, &@2); + m->nd_next = node_assign(p, NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, NO_LEX_CTXT, &@2); } /* {|*internal_id| = internal_id; ... } */ args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2); scope = NEW_NODE(NODE_SCOPE, tbl, $5, args, &@$); - RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf); $$ = NEW_FOR($4, scope, &@$); fixpos($$, $2); /*% %*/ @@ -2907,12 +3203,11 @@ primary : literal } | k_class cpath superclass { - if (p->in_def) { + if (p->ctxt.in_def) { YYLTYPE loc = code_loc_gen(&@1, &@2); yyerror1(&loc, "class definition in method body"); } - $1 = p->in_class; - p->in_class = 1; + p->ctxt.in_class = 1; local_push(p, 0); } bodystmt @@ -2926,13 +3221,13 @@ primary : literal /*% %*/ /*% ripper: class!($2, $3, $5) %*/ local_pop(p); - p->in_class = $1 & 1; + p->ctxt.in_class = $1.in_class; + p->ctxt.shareable_constant_value = $1.shareable_constant_value; } | k_class tLSHFT expr { - $$ = (p->in_class << 1) | p->in_def; - p->in_def = 0; - p->in_class = 0; + p->ctxt.in_def = 0; + p->ctxt.in_class = 0; local_push(p, 0); } term @@ -2947,17 +3242,17 @@ primary : literal /*% %*/ /*% ripper: sclass!($3, $6) %*/ local_pop(p); - p->in_def = $4 & 1; - p->in_class = ($4 >> 1) & 1; + p->ctxt.in_def = $1.in_def; + p->ctxt.in_class = $1.in_class; + p->ctxt.shareable_constant_value = $1.shareable_constant_value; } | k_module cpath { - if (p->in_def) { + if (p->ctxt.in_def) { YYLTYPE loc = code_loc_gen(&@1, &@2); yyerror1(&loc, "module definition in method body"); } - $1 = p->in_class; - p->in_class = 1; + p->ctxt.in_class = 1; local_push(p, 0); } bodystmt @@ -2971,60 +3266,34 @@ primary : literal /*% %*/ /*% ripper: module!($2, $4) %*/ local_pop(p); - p->in_class = $1 & 1; - } - | k_def fname - { - numparam_name(p, get_id($2)); - local_push(p, 0); - $$ = p->cur_arg; - p->cur_arg = 0; - } - { - $$ = p->in_def; - p->in_def = 1; + p->ctxt.in_class = $1.in_class; + p->ctxt.shareable_constant_value = $1.shareable_constant_value; } + | defn_head f_arglist bodystmt k_end { + restore_defun(p, $1->nd_defn); /*%%%*/ - NODE *body = remove_begin($6); - reduce_nodes(p, &body); - $$ = NEW_DEFN($2, $5, body, &@$); - nd_set_line($$->nd_defn, @7.end_pos.lineno); - set_line_body(body, @1.beg_pos.lineno); + $$ = set_defun_body(p, $1, $2, $3, &@$); /*% %*/ - /*% ripper: def!($2, $5, $6) %*/ + /*% ripper: def!(get_value($1), $2, $3) %*/ local_pop(p); - p->in_def = $4 & 1; - p->cur_arg = $3; - } - | k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} fname - { - numparam_name(p, get_id($5)); - $4 = p->in_def; - p->in_def = 1; - SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */ - local_push(p, 0); - $$ = p->cur_arg; - p->cur_arg = 0; } + | defs_head f_arglist bodystmt k_end { + restore_defun(p, $1->nd_defn); /*%%%*/ - NODE *body = remove_begin($8); - reduce_nodes(p, &body); - $$ = NEW_DEFS($2, $5, $7, body, &@$); - nd_set_line($$->nd_defn, @9.end_pos.lineno); - set_line_body(body, @1.beg_pos.lineno); - /*% %*/ - /*% ripper: defs!($2, $3, $5, $7, $8) %*/ + $$ = set_defun_body(p, $1, $2, $3, &@$); + /*% + $1 = get_value($1); + %*/ + /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $3) %*/ local_pop(p); - p->in_def = $4 & 1; - p->cur_arg = $6; } | keyword_break { @@ -3119,18 +3388,21 @@ k_for : keyword_for k_class : keyword_class { token_info_push(p, "class", &@$); + $$ = p->ctxt; } ; k_module : keyword_module { token_info_push(p, "module", &@$); + $$ = p->ctxt; } ; k_def : keyword_def { token_info_push(p, "def", &@$); + p->ctxt.in_argdef = 1; } ; @@ -3194,7 +3466,7 @@ k_end : keyword_end k_return : keyword_return { - if (p->in_class && !p->in_def && !dyna_in_block(p)) + if (p->ctxt.in_class && !p->ctxt.in_def && !dyna_in_block(p)) yyerror1(&@1, "Invalid return in class/module body"); } ; @@ -3322,6 +3594,12 @@ f_rest_marg : tSTAR f_norm_arg } ; +f_any_kwrest : f_kwrest + | f_no_kwarg {$$ = ID2VAL(idNil);} + ; + +f_eq : {p->ctxt.in_argdef = 0;} '='; + block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail(p, $1, $3, $4, &@3); @@ -3330,14 +3608,10 @@ block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail(p, $1, Qnone, $2, &@1); } - | f_kwrest opt_f_block_arg + | f_any_kwrest opt_f_block_arg { $$ = new_args_tail(p, Qnone, $1, $2, &@1); } - | f_no_kwarg opt_f_block_arg - { - $$ = new_args_tail(p, Qnone, ID2VAL(idNil), $2, &@1); - } | f_block_arg { $$ = new_args_tail(p, Qnone, Qnone, $1, &@1); @@ -3354,6 +3628,16 @@ opt_block_args_tail : ',' block_args_tail } ; +excessed_comma : ',' + { + /* magic number for rest_id in iseq_set_arguments() */ + /*%%%*/ + $$ = NODE_SPECIAL_EXCESSIVE_COMMA; + /*% %*/ + /*% ripper: excessed_comma! %*/ + } + ; + block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args(p, $1, $3, $5, Qnone, $6, &@$); @@ -3374,13 +3658,10 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args(p, $1, Qnone, $3, Qnone, $4, &@$); } - | f_arg ',' + | f_arg excessed_comma { - /*%%%*/ - /* magic number for rest_id in iseq_set_arguments() */ - $$ = new_args(p, $1, Qnone, NODE_SPECIAL_EXCESSIVE_COMMA, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, &@1), &@$); - /*% %*/ - /*% ripper: new_args(p, $1, Qnone, excessed_comma!, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, NULL), NULL) %*/ + $$ = new_args_tail(p, Qnone, Qnone, Qnone, &@2); + $$ = new_args(p, $1, Qnone, $2, Qnone, $$, &@$); } | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail { @@ -3431,6 +3712,7 @@ block_param_def : '|' opt_bv_decl '|' { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; + p->ctxt.in_argdef = 0; /*%%%*/ $$ = 0; /*% %*/ @@ -3440,6 +3722,7 @@ block_param_def : '|' opt_bv_decl '|' { p->cur_arg = 0; p->max_numparam = ORDINAL_PARAM; + p->ctxt.in_argdef = 0; /*%%%*/ $$ = $2; /*% %*/ @@ -3450,7 +3733,7 @@ block_param_def : '|' opt_bv_decl '|' opt_bv_decl : opt_nl { - $$ = 0; + $$ = 0; } | opt_nl ';' bv_decls opt_nl { @@ -3478,10 +3761,10 @@ bvar : tIDENTIFIER } ; -lambda : { - $$ = dyna_push(p); - } +lambda : tLAMBDA { + token_info_push(p, "->", &@1); + $1 = dyna_push(p); $$ = p->lex.lpar_beg; p->lex.lpar_beg = p->lex.paren_nest; } @@ -3509,6 +3792,7 @@ lambda : { $$ = NEW_LAMBDA($5, $7, &loc); nd_set_line($$->nd_body, @7.end_pos.lineno); nd_set_line($$, @5.end_pos.lineno); + nd_set_first_loc($$, @1.beg_pos); } /*% %*/ /*% ripper: lambda!($5, $7) %*/ @@ -3519,6 +3803,7 @@ lambda : { f_larglist : '(' f_args opt_bv_decl ')' { + p->ctxt.in_argdef = 0; /*%%%*/ $$ = $2; p->max_numparam = ORDINAL_PARAM; @@ -3527,6 +3812,7 @@ f_larglist : '(' f_args opt_bv_decl ')' } | f_args { + p->ctxt.in_argdef = 0; /*%%%*/ if (!args_info_empty_p($1->nd_ainfo)) p->max_numparam = ORDINAL_PARAM; @@ -3559,7 +3845,7 @@ do_block : k_do_block do_body k_end block_call : command do_block { /*%%%*/ - if (nd_type($1) == NODE_YIELD) { + if (nd_type_p($1, NODE_YIELD)) { compile_error(p, "block given to yield"); } else { @@ -3658,7 +3944,7 @@ method_call : fcall paren_args | primary_value '[' opt_call_args rbracket { /*%%%*/ - if ($1 && nd_type($1) == NODE_SELF) + if ($1 && nd_type_p($1, NODE_SELF)) $$ = NEW_FCALL(tAREF, $3, &@$); else $$ = NEW_CALL($1, tAREF, $3, &@$); @@ -3784,24 +4070,26 @@ p_case_body : keyword_in { SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; - $$ = p->in_kwarg; - p->in_kwarg = 1; + $1 = p->ctxt; + p->ctxt.in_kwarg = 1; + $$ = push_pvtbl(p); + } + { + $$ = push_pktbl(p); } - {$$ = push_pvtbl(p);} - {$$ = push_pktbl(p);} p_top_expr then - {pop_pktbl(p, $4);} - {pop_pvtbl(p, $3);} { - p->in_kwarg = !!$2; + pop_pktbl(p, $3); + pop_pvtbl(p, $2); + p->ctxt.in_kwarg = $1.in_kwarg; } compstmt p_cases { /*%%%*/ - $$ = NEW_IN($5, $10, $11, &@$); + $$ = NEW_IN($4, $7, $8, &@$); /*% %*/ - /*% ripper: in!($5, $10, escape_Qundef($11)) %*/ + /*% ripper: in!($4, $7, escape_Qundef($8)) %*/ } ; @@ -3813,7 +4101,7 @@ p_top_expr : p_top_expr_body | p_top_expr_body modifier_if expr_value { /*%%%*/ - $$ = new_if(p, $3, remove_begin($1), 0, &@$); + $$ = new_if(p, $3, $1, 0, &@$); fixpos($$, $3); /*% %*/ /*% ripper: if_mod!($3, $1) %*/ @@ -3821,7 +4109,7 @@ p_top_expr : p_top_expr_body | p_top_expr_body modifier_unless expr_value { /*%%%*/ - $$ = new_unless(p, $3, remove_begin($1), 0, &@$); + $$ = new_unless(p, $3, $1, 0, &@$); fixpos($$, $3); /*% %*/ /*% ripper: unless_mod!($3, $1) %*/ @@ -3842,6 +4130,10 @@ p_top_expr_body : p_expr /*% %*/ } + | p_find + { + $$ = new_find_pattern(p, Qnone, $1, &@$); + } | p_args_tail { $$ = new_array_pattern(p, Qnone, Qnone, $1, &@$); @@ -3881,6 +4173,7 @@ p_lparen : '(' {$$ = push_pktbl(p);}; p_lbracket : '[' {$$ = push_pktbl(p);}; p_expr_basic : p_value + | p_variable | p_const p_lparen p_args rparen { pop_pktbl(p, $2); @@ -3890,6 +4183,15 @@ p_expr_basic : p_value /*% %*/ } + | p_const p_lparen p_find rparen + { + pop_pktbl(p, $2); + $$ = new_find_pattern(p, $1, $3, &@$); + /*%%%*/ + nd_set_first_loc($$, @1.beg_pos); + /*% + %*/ + } | p_const p_lparen p_kwargs rparen { pop_pktbl(p, $2); @@ -3913,6 +4215,15 @@ p_expr_basic : p_value /*% %*/ } + | p_const p_lbracket p_find rbracket + { + pop_pktbl(p, $2); + $$ = new_find_pattern(p, $1, $3, &@$); + /*%%%*/ + nd_set_first_loc($$, @1.beg_pos); + /*% + %*/ + } | p_const p_lbracket p_kwargs rbracket { pop_pktbl(p, $2); @@ -3927,10 +4238,13 @@ p_expr_basic : p_value $$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$); $$ = new_array_pattern(p, $1, Qnone, $$, &@$); } - | tLBRACK {$$ = push_pktbl(p);} p_args rbracket + | tLBRACK p_args rbracket { - pop_pktbl(p, $2); - $$ = new_array_pattern(p, Qnone, Qnone, $3, &@$); + $$ = new_array_pattern(p, Qnone, Qnone, $2, &@$); + } + | tLBRACK p_find rbracket + { + $$ = new_find_pattern(p, Qnone, $2, &@$); } | tLBRACK rbracket { @@ -3940,13 +4254,13 @@ p_expr_basic : p_value | tLBRACE { $$ = push_pktbl(p); - $1 = p->in_kwarg; - p->in_kwarg = 0; + $1 = p->ctxt; + p->ctxt.in_kwarg = 0; } p_kwargs rbrace { pop_pktbl(p, $2); - p->in_kwarg = $1; + p->ctxt.in_kwarg = $1.in_kwarg; $$ = new_hash_pattern(p, Qnone, $3, &@$); } | tLBRACE rbrace @@ -4015,21 +4329,33 @@ p_args_head : p_arg ',' } ; -p_args_tail : tSTAR tIDENTIFIER +p_args_tail : p_rest { - $$ = new_array_pattern_tail(p, Qnone, 1, $2, Qnone, &@$); + $$ = new_array_pattern_tail(p, Qnone, 1, $1, Qnone, &@$); } - | tSTAR tIDENTIFIER ',' p_args_post + | p_rest ',' p_args_post { - $$ = new_array_pattern_tail(p, Qnone, 1, $2, $4, &@$); + $$ = new_array_pattern_tail(p, Qnone, 1, $1, $3, &@$); } - | tSTAR + ; + +p_find : p_rest ',' p_args_post ',' p_rest { - $$ = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &@$); + $$ = new_find_pattern_tail(p, $1, $3, $5, &@$); + + if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) + rb_warn0L_experimental(nd_line($$), "Find pattern is experimental, and the behavior may change in future versions of Ruby!"); + } + ; + + +p_rest : tSTAR tIDENTIFIER + { + $$ = $2; } - | tSTAR ',' p_args_post + | tSTAR { - $$ = new_array_pattern_tail(p, Qnone, 1, 0, $3, &@$); + $$ = 0; } ; @@ -4052,7 +4378,7 @@ p_arg : p_expr } ; -p_kwargs : p_kwarg ',' p_kwrest +p_kwargs : p_kwarg ',' p_any_kwrest { $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), $3, &@$); } @@ -4064,18 +4390,10 @@ p_kwargs : p_kwarg ',' p_kwrest { $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), 0, &@$); } - | p_kwrest + | p_any_kwrest { $$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), $1, &@$); } - | p_kwarg ',' p_kwnorest - { - $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), ID2VAL(idNil), &@$); - } - | p_kwnorest - { - $$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), ID2VAL(idNil), &@$); - } ; p_kwarg : p_kw @@ -4116,7 +4434,7 @@ p_kw_label : tLABEL { YYLTYPE loc = code_loc_gen(&@1, &@3); /*%%%*/ - if (!$2 || nd_type($2) == NODE_STR) { + if (!$2 || nd_type_p($2, NODE_STR)) { NODE *node = dsym_node(p, $2, &loc); $$ = SYM2ID(node->nd_lit); } @@ -4151,6 +4469,10 @@ p_kwnorest : kwrest_mark keyword_nil } ; +p_any_kwrest : p_kwrest + | p_kwnorest {$$ = ID2VAL(idNil);} + ; + p_value : p_primitive | p_primitive tDOT2 p_primitive { @@ -4172,52 +4494,36 @@ p_value : p_primitive } | p_primitive tDOT2 { - /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @2.end_pos; - loc.end_pos = @2.end_pos; - + /*%%%*/ value_expr($1); - $$ = NEW_DOT2($1, new_nil(&loc), &@$); + $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$); /*% %*/ /*% ripper: dot2!($1, Qnil) %*/ } | p_primitive tDOT3 { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @2.end_pos; - loc.end_pos = @2.end_pos; - value_expr($1); - $$ = NEW_DOT3($1, new_nil(&loc), &@$); + $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$); /*% %*/ /*% ripper: dot3!($1, Qnil) %*/ } - | p_variable | p_var_ref + | p_expr_ref | p_const | tBDOT2 p_primitive { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @1.beg_pos; - loc.end_pos = @1.beg_pos; - value_expr($2); - $$ = NEW_DOT2(new_nil(&loc), $2, &@$); + $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$); /*% %*/ /*% ripper: dot2!(Qnil, $2) %*/ } | tBDOT3 p_primitive { /*%%%*/ - YYLTYPE loc; - loc.beg_pos = @1.beg_pos; - loc.end_pos = @1.beg_pos; - value_expr($2); - $$ = NEW_DOT3(new_nil(&loc), $2, &@$); + $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$); /*% %*/ /*% ripper: dot3!(Qnil, $2) %*/ } @@ -4238,17 +4544,7 @@ p_primitive : literal /*% %*/ /*% ripper: var_ref!($1) %*/ } - | tLAMBDA - { - token_info_push(p, "->", &@1); - } - lambda - { - $$ = $3; - /*%%%*/ - nd_set_first_loc($$, @1.beg_pos); - /*% %*/ - } + | lambda ; p_variable : tIDENTIFIER @@ -4265,13 +4561,29 @@ p_var_ref : '^' tIDENTIFIER { /*%%%*/ NODE *n = gettable(p, $2, &@$); - if (!(nd_type(n) == NODE_LVAR || nd_type(n) == NODE_DVAR)) { + if (!(nd_type_p(n, NODE_LVAR) || nd_type_p(n, NODE_DVAR))) { compile_error(p, "%"PRIsVALUE": no such local variable", rb_id2str($2)); } $$ = n; /*% %*/ /*% ripper: var_ref!($2) %*/ } + | '^' nonlocal_var + { + /*%%%*/ + if (!($$ = gettable(p, $2, &@$))) $$ = NEW_BEGIN(0, &@$); + /*% %*/ + /*% ripper: var_ref!($2) %*/ + } + ; + +p_expr_ref : '^' tLPAREN expr_value ')' + { + /*%%%*/ + $$ = NEW_BEGIN($3, &@$); + /*% %*/ + /*% ripper: begin!($3) %*/ + } ; p_const : tCOLON3 cname @@ -4303,7 +4615,7 @@ opt_rescue : k_rescue exc_list exc_var then { /*%%%*/ $$ = NEW_RESBODY($2, - $3 ? block_append(p, node_assign(p, $3, NEW_ERRINFO(&@3), &@3), $5) : $5, + $3 ? block_append(p, node_assign(p, $3, NEW_ERRINFO(&@3), NO_LEX_CTXT, &@3), $5) : $5, $6, &@$); fixpos($$, $2?$2:$5); /*% %*/ @@ -4739,6 +5051,11 @@ simple_numeric : tINTEGER | tIMAGINARY ; +nonlocal_var : tIVAR + | tGVAR + | tCVAR + ; + user_variable : tIDENTIFIER | tIVAR | tGVAR @@ -4815,38 +5132,38 @@ superclass : '<' } ; -f_arglist : '(' f_args rparen +f_opt_paren_args: f_paren_args + | none { - /*%%%*/ - $$ = $2; - /*% %*/ - /*% ripper: paren!($2) %*/ - SET_LEX_STATE(EXPR_BEG); - p->command_start = TRUE; + p->ctxt.in_argdef = 0; + $$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0); + $$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $$, &@0); } - | '(' args_forward rparen + ; + +f_paren_args : '(' f_args rparen { - arg_var(p, idFWD_REST); -#if idFWD_KWREST - arg_var(p, idFWD_KWREST); -#endif - arg_var(p, idFWD_BLOCK); /*%%%*/ - $$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@2); - $$ = new_args(p, Qnone, Qnone, idFWD_REST, Qnone, $$, &@2); + $$ = $2; /*% %*/ - /*% ripper: paren!(params_new(Qnone, Qnone, $2, Qnone, Qnone, Qnone, Qnone)) %*/ + /*% ripper: paren!($2) %*/ SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; + p->ctxt.in_argdef = 0; } + ; + +f_arglist : f_paren_args | { - $$ = p->in_kwarg; - p->in_kwarg = 1; + $$ = p->ctxt; + p->ctxt.in_kwarg = 1; + p->ctxt.in_argdef = 1; SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */ } - f_args term + f_args term { - p->in_kwarg = !!$1; + p->ctxt.in_kwarg = $1.in_kwarg; + p->ctxt.in_argdef = 0; $$ = $2; SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; @@ -4861,18 +5178,19 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail(p, $1, Qnone, $2, &@1); } - | f_kwrest opt_f_block_arg + | f_any_kwrest opt_f_block_arg { $$ = new_args_tail(p, Qnone, $1, $2, &@1); } - | f_no_kwarg opt_f_block_arg - { - $$ = new_args_tail(p, Qnone, ID2VAL(idNil), $2, &@1); - } | f_block_arg { $$ = new_args_tail(p, Qnone, Qnone, $1, &@1); } + | args_forward + { + add_forwarding_args(p); + $$ = new_args_tail(p, Qnone, $1, ID2VAL(idFWD_BLOCK), &@1); + } ; opt_args_tail : ',' args_tail @@ -4951,7 +5269,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail args_forward : tBDOT3 { /*%%%*/ - $$ = idDot3; + $$ = idFWD_KWREST; /*% %*/ /*% ripper: args_forward! %*/ } @@ -4959,42 +5277,46 @@ args_forward : tBDOT3 f_bad_arg : tCONSTANT { + static const char mesg[] = "formal argument cannot be a constant"; /*%%%*/ - yyerror1(&@1, "formal argument cannot be a constant"); + yyerror1(&@1, mesg); $$ = 0; /*% %*/ - /*% ripper[error]: param_error!($1) %*/ + /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/ } | tIVAR { + static const char mesg[] = "formal argument cannot be an instance variable"; /*%%%*/ - yyerror1(&@1, "formal argument cannot be an instance variable"); + yyerror1(&@1, mesg); $$ = 0; /*% %*/ - /*% ripper[error]: param_error!($1) %*/ + /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/ } | tGVAR { + static const char mesg[] = "formal argument cannot be a global variable"; /*%%%*/ - yyerror1(&@1, "formal argument cannot be a global variable"); + yyerror1(&@1, mesg); $$ = 0; /*% %*/ - /*% ripper[error]: param_error!($1) %*/ + /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/ } | tCVAR { + static const char mesg[] = "formal argument cannot be a class variable"; /*%%%*/ - yyerror1(&@1, "formal argument cannot be a class variable"); + yyerror1(&@1, mesg); $$ = 0; /*% %*/ - /*% ripper[error]: param_error!($1) %*/ + /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/ } ; f_norm_arg : f_bad_arg | tIDENTIFIER { - formal_argument(p, get_id($1)); + formal_argument(p, $1); p->max_numparam = ORDINAL_PARAM; $$ = $1; } @@ -5055,10 +5377,10 @@ f_arg : f_arg_item f_label : tLABEL { - ID id = get_id($1); - arg_var(p, formal_argument(p, id)); - p->cur_arg = id; + arg_var(p, formal_argument(p, $1)); + p->cur_arg = get_id($1); p->max_numparam = ORDINAL_PARAM; + p->ctxt.in_argdef = 0; $$ = $1; } ; @@ -5066,6 +5388,7 @@ f_label : tLABEL f_kw : f_label arg_value { p->cur_arg = 0; + p->ctxt.in_argdef = 1; /*%%%*/ $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$); /*% %*/ @@ -5074,6 +5397,7 @@ f_kw : f_label arg_value | f_label { p->cur_arg = 0; + p->ctxt.in_argdef = 1; /*%%%*/ $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$); /*% %*/ @@ -5083,6 +5407,7 @@ f_kw : f_label arg_value f_block_kw : f_label primary_value { + p->ctxt.in_argdef = 1; /*%%%*/ $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$); /*% %*/ @@ -5090,6 +5415,7 @@ f_block_kw : f_label primary_value } | f_label { + p->ctxt.in_argdef = 1; /*%%%*/ $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$); /*% %*/ @@ -5160,9 +5486,10 @@ f_kwrest : kwrest_mark tIDENTIFIER } ; -f_opt : f_arg_asgn '=' arg_value +f_opt : f_arg_asgn f_eq arg_value { p->cur_arg = 0; + p->ctxt.in_argdef = 1; /*%%%*/ $$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$); /*% %*/ @@ -5170,9 +5497,10 @@ f_opt : f_arg_asgn '=' arg_value } ; -f_block_opt : f_arg_asgn '=' primary_value +f_block_opt : f_arg_asgn f_eq primary_value { p->cur_arg = 0; + p->ctxt.in_argdef = 1; /*%%%*/ $$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$); /*% %*/ @@ -5246,6 +5574,14 @@ f_block_arg : blkarg_mark tIDENTIFIER /*% %*/ /*% ripper: blockarg!($2) %*/ } + | blkarg_mark + { + /*%%%*/ + arg_var(p, shadowing_lvar(p, get_id(ANON_BLOCK_ID))); + /*% + $$ = dispatch1(blockarg, Qnil); + %*/ + } ; opt_f_block_arg : ',' f_block_arg @@ -5309,8 +5645,8 @@ assocs : assoc } else if (tail) { if (assocs->nd_head && - !tail->nd_head && nd_type(tail->nd_next) == NODE_LIST && - nd_type(tail->nd_next->nd_head) == NODE_HASH) { + !tail->nd_head && nd_type_p(tail->nd_next, NODE_LIST) && + nd_type_p(tail->nd_next->nd_head, NODE_HASH)) { /* DSTAR */ tail = tail->nd_next->nd_head->nd_head; } @@ -5325,7 +5661,7 @@ assocs : assoc assoc : arg_value tASSOC arg_value { /*%%%*/ - if (nd_type($1) == NODE_STR) { + if (nd_type_p($1, NODE_STR)) { nd_set_type($1, NODE_LIT); RB_OBJ_WRITE(p->ast, &$1->nd_lit, rb_fstring($1->nd_lit)); } @@ -5340,6 +5676,15 @@ assoc : arg_value tASSOC arg_value /*% %*/ /*% ripper: assoc_new!($1, $2) %*/ } + | tLABEL + { + /*%%%*/ + NODE *val = gettable(p, $1, &@$); + if (!val) val = NEW_BEGIN(0, &@$); + $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@1), &@$), val); + /*% %*/ + /*% ripper: assoc_new!($1, Qnil) %*/ + } | tSTRING_BEG string_contents tLABEL_END arg_value { /*%%%*/ @@ -5351,7 +5696,7 @@ assoc : arg_value tASSOC arg_value | tDSTAR arg_value { /*%%%*/ - if (nd_type($2) == NODE_HASH && + if (nd_type_p($2, NODE_HASH) && !($2->nd_head && $2->nd_head->nd_alen)) { static VALUE empty_hash; if (!empty_hash) { @@ -5473,7 +5818,7 @@ ripper_yylval_id(struct parser_params *p, ID x) # define set_yylval_id(x) (void)(x) # define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(p, x)) # define set_yylval_literal(x) add_mark_object(p, (x)) -# define set_yylval_node(x) (void)(x) +# define set_yylval_node(x) (yylval.val = ripper_new_yylval(p, 0, 0, STR_NEW(p->lex.ptok, p->lex.pcur-p->lex.ptok))) # define yylval_id() yylval.id # define _cur_loc NULL_LOC /* dummy */ #endif @@ -5539,9 +5884,6 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t) #define has_delayed_token(p) (!NIL_P(p->delayed.token)) #endif /* RIPPER */ -#include "ruby/regex.h" -#include "ruby/util.h" - static inline int is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc) { @@ -5606,6 +5948,26 @@ token_info_pop(struct parser_params *p, const char *token, const rb_code_locatio ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg)); } +static void +token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos) +{ + token_info *ptinfo_beg = p->token_info; + + if (!ptinfo_beg) return; + p->token_info = ptinfo_beg->next; + + if (ptinfo_beg->beg.lineno != beg_pos.lineno || + ptinfo_beg->beg.column != beg_pos.column || + strcmp(ptinfo_beg->token, token)) { + compile_error(p, "token position mismatch: %d:%d:%s expected but %d:%d:%s", + beg_pos.lineno, beg_pos.column, token, + ptinfo_beg->beg.lineno, ptinfo_beg->beg.column, + ptinfo_beg->token); + } + + ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg)); +} + static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc) { @@ -5656,22 +6018,29 @@ parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc) static int parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg) { +#if 0 YYLTYPE current; if (!yylloc) { yylloc = RUBY_SET_YYLLOC(current); } else if ((p->ruby_sourceline != yylloc->beg_pos.lineno && - p->ruby_sourceline != yylloc->end_pos.lineno) || - (yylloc->beg_pos.lineno == yylloc->end_pos.lineno && - yylloc->beg_pos.column == yylloc->end_pos.column)) { + p->ruby_sourceline != yylloc->end_pos.lineno)) { yylloc = 0; } +#endif compile_error(p, "%s", msg); parser_show_error_line(p, yylloc); return 0; } +static int +parser_yyerror0(struct parser_params *p, const char *msg) +{ + YYLTYPE current; + return parser_yyerror(p, RUBY_SET_YYLLOC(current), msg); +} + static void ruby_show_error_line(VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str) { @@ -5781,16 +6150,14 @@ static int parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg) { const char *pcur = 0, *ptok = 0; - if (yylloc && - p->ruby_sourceline == yylloc->beg_pos.lineno && + if (p->ruby_sourceline == yylloc->beg_pos.lineno && p->ruby_sourceline == yylloc->end_pos.lineno) { pcur = p->lex.pcur; ptok = p->lex.ptok; p->lex.ptok = p->lex.pbeg + yylloc->beg_pos.column; p->lex.pcur = p->lex.pbeg + yylloc->end_pos.column; } - dispatch1(parse_error, STR_NEW2(msg)); - ripper_error(p); + parser_yyerror0(p, msg); if (pcur) { p->lex.ptok = ptok; p->lex.pcur = pcur; @@ -5798,6 +6165,14 @@ parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg) return 0; } +static int +parser_yyerror0(struct parser_params *p, const char *msg) +{ + dispatch1(parse_error, STR_NEW2(msg)); + ripper_error(p); + return 0; +} + static inline void parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc) { @@ -5847,7 +6222,7 @@ vtable_free_gen(struct parser_params *p, int line, const char *name, if (tbl->tbl) { ruby_sized_xfree(tbl->tbl, tbl->capa * sizeof(ID)); } - ruby_sized_xfree(tbl, sizeof(tbl)); + ruby_sized_xfree(tbl, sizeof(*tbl)); } } #define vtable_free(tbl) vtable_free_gen(p, __LINE__, #tbl, tbl) @@ -5945,7 +6320,7 @@ yycompile0(VALUE arg) if (!compile_for_eval && !NIL_P(p->ruby_sourcefile_string)) { p->debug_lines = debug_lines(p->ruby_sourcefile_string); if (p->debug_lines && p->ruby_sourceline > 0) { - VALUE str = STR_NEW0(); + VALUE str = rb_default_rs; n = p->ruby_sourceline; do { rb_ary_push(p->debug_lines, str); @@ -5957,6 +6332,14 @@ yycompile0(VALUE arg) } } + if (p->keep_script_lines || ruby_vm_keep_script_lines) { + if (!p->debug_lines) { + p->debug_lines = rb_ary_new(); + } + + RB_OBJ_WRITE(p->ast, &p->ast->body.script_lines, p->debug_lines); + } + parser_prepare(p); #define RUBY_DTRACE_PARSE_HOOK(name) \ if (RUBY_DTRACE_PARSE_##name##_ENABLED()) { \ @@ -5993,7 +6376,7 @@ yycompile0(VALUE arg) RB_OBJ_WRITE(p->ast, &p->ast->body.compile_option, opt); } p->ast->body.root = tree; - p->ast->body.line_count = p->line_count; + if (!p->ast->body.script_lines) p->ast->body.script_lines = INT2FIX(p->line_count); return TRUE; } @@ -6011,11 +6394,17 @@ yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line) } p->ruby_sourceline = line - 1; + p->lvtbl = NULL; + p->ast = ast = rb_ast_new(); rb_suppress_tracing(yycompile0, (VALUE)p); p->ast = 0; RB_GC_GUARD(vparser); /* prohibit tail call optimization */ + while (p->lvtbl) { + local_pop(p); + } + return ast; } #endif /* !RIPPER */ @@ -6056,6 +6445,7 @@ lex_getline(struct parser_params *p) VALUE line = (*p->lex.gets)(p, p->lex.input); if (NIL_P(line)) return line; must_be_ascii_compatible(line); + if (RB_OBJ_FROZEN(line)) line = rb_str_dup(line); // needed for RubyVM::AST.of because script_lines in iseq is deep-frozen #ifndef RIPPER if (p->debug_lines) { rb_enc_associate(line, p->enc); @@ -6253,11 +6643,6 @@ parser_cr(struct parser_params *p, int c) p->lex.pcur++; c = '\n'; } - else if (!p->cr_seen) { - p->cr_seen = TRUE; - /* carried over with p->lex.nextline for nextc() */ - rb_warn0("encountered \\r in middle of line, treated as a mere space"); - } return c; } @@ -6554,7 +6939,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp) goto eof; } if ((c = nextc(p)) == '\\') { - if (peek(p, 'u')) goto eof; + switch (peekc(p)) { + case 'u': case 'U': + nextc(p); + goto eof; + } return read_escape(p, flags|ESCAPE_META, encp) | 0x80; } else if (c == -1 || !ISASCII(c)) goto eof; @@ -6579,7 +6968,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp) case 'c': if (flags & ESCAPE_CONTROL) goto eof; if ((c = nextc(p))== '\\') { - if (peek(p, 'u')) goto eof; + switch (peekc(p)) { + case 'u': case 'U': + nextc(p); + goto eof; + } c = read_escape(p, flags|ESCAPE_CONTROL, encp); } else if (c == '?') @@ -6631,10 +7024,8 @@ static int tokadd_escape(struct parser_params *p, rb_encoding **encp) { int c; - int flags = 0; size_t numlen; - first: switch (c = nextc(p)) { case '\n': return 0; /* just ignore */ @@ -6657,37 +7048,6 @@ tokadd_escape(struct parser_params *p, rb_encoding **encp) } return 0; - case 'M': - if (flags & ESCAPE_META) goto eof; - if ((c = nextc(p)) != '-') { - pushback(p, c); - goto eof; - } - tokcopy(p, 3); - flags |= ESCAPE_META; - goto escaped; - - case 'C': - if (flags & ESCAPE_CONTROL) goto eof; - if ((c = nextc(p)) != '-') { - pushback(p, c); - goto eof; - } - tokcopy(p, 3); - goto escaped; - - case 'c': - if (flags & ESCAPE_CONTROL) goto eof; - tokcopy(p, 2); - flags |= ESCAPE_CONTROL; - escaped: - if ((c = nextc(p)) == '\\') { - goto first; - } - else if (c == -1) goto eof; - tokadd(p, c); - return 0; - eof: case -1: yyerror0("Invalid escape character syntax"); @@ -6880,6 +7240,23 @@ tokadd_string(struct parser_params *p, goto non_ascii; } if (func & STR_FUNC_REGEXP) { + switch (c) { + case 'c': + case 'C': + case 'M': { + pushback(p, c); + c = read_escape(p, 0, enc); + + int i; + char escbuf[5]; + snprintf(escbuf, sizeof(escbuf), "\\x%02X", c); + for (i = 0; i < 4; i++) { + tokadd(p, escbuf[i]); + } + continue; + } + } + if (c == term && !simple_re_meta(c)) { tokadd(p, c); continue; @@ -7180,7 +7557,7 @@ heredoc_identifier(struct parser_params *p) len = 0; while ((c = nextc(p)) != term) { if (c == -1 || c == '\r' || c == '\n') { - yyerror(NULL, p, "unterminated here document identifier"); + yyerror0("unterminated here document identifier"); return -1; } } @@ -7206,7 +7583,7 @@ heredoc_identifier(struct parser_params *p) len = p->lex.pcur - (p->lex.pbeg + offset) - quote; if ((unsigned long)len >= HERETERM_LENGTH_MAX) - yyerror(NULL, p, "too long here document identifier"); + yyerror0("too long here document identifier"); dispatch_scan_event(p, tHEREDOC_BEG); lex_goto_eol(p); @@ -7287,7 +7664,7 @@ heredoc_dedent(struct parser_params *p, NODE *root) if (!root) return root; prev_node = node = str_node = root; - if (nd_type(root) == NODE_LIST) str_node = root->nd_head; + if (nd_type_p(root, NODE_LIST)) str_node = root->nd_head; while (str_node) { VALUE lit = str_node->nd_lit; @@ -7304,7 +7681,7 @@ heredoc_dedent(struct parser_params *p, NODE *root) NODE *end = node->nd_end; node = prev_node->nd_next = node->nd_next; if (!node) { - if (nd_type(prev_node) == NODE_DSTR) + if (nd_type_p(prev_node, NODE_DSTR)) nd_set_type(prev_node, NODE_STR); break; } @@ -7315,7 +7692,7 @@ heredoc_dedent(struct parser_params *p, NODE *root) str_node = 0; while ((node = (prev_node = node)->nd_next) != 0) { next_str: - if (nd_type(node) != NODE_LIST) break; + if (!nd_type_p(node, NODE_LIST)) break; if ((str_node = node->nd_head) != 0) { enum node_type type = nd_type(str_node); if (type == NODE_STR || type == NODE_DSTR) break; @@ -7637,7 +8014,12 @@ static int arg_ambiguous(struct parser_params *p, char c) { #ifndef RIPPER - rb_warning1("ambiguous first argument; put parentheses or a space even after `%c' operator", WARN_I(c)); + if (c == '/') { + rb_warning1("ambiguity between regexp and two divisions: wrap regexp in parentheses or add a space after `%c' operator", WARN_I(c)); + } + else { + rb_warning1("ambiguous first argument; put parentheses or a space even after `%c' operator", WARN_I(c)); + } #else dispatch1(arg_ambiguous, rb_usascii_str_new(&c, 1)); #endif @@ -7645,35 +8027,40 @@ arg_ambiguous(struct parser_params *p, char c) } static ID +#ifndef RIPPER formal_argument(struct parser_params *p, ID lhs) +#else +formal_argument(struct parser_params *p, VALUE lhs) +#endif { - switch (id_type(lhs)) { + ID id = get_id(lhs); + + switch (id_type(id)) { case ID_LOCAL: break; #ifndef RIPPER +# define ERR(mesg) yyerror0(mesg) +#else +# define ERR(mesg) (dispatch2(param_error, WARN_S(mesg), lhs), ripper_error(p)) +#endif case ID_CONST: - yyerror0("formal argument cannot be a constant"); + ERR("formal argument cannot be a constant"); return 0; case ID_INSTANCE: - yyerror0("formal argument cannot be an instance variable"); + ERR("formal argument cannot be an instance variable"); return 0; case ID_GLOBAL: - yyerror0("formal argument cannot be a global variable"); + ERR("formal argument cannot be a global variable"); return 0; case ID_CLASS: - yyerror0("formal argument cannot be a class variable"); - return 0; - default: - yyerror0("formal argument must be local variable"); + ERR("formal argument cannot be a class variable"); return 0; -#else default: - lhs = dispatch1(param_error, lhs); - ripper_error(p); + ERR("formal argument must be local variable"); return 0; -#endif +#undef ERR } - shadowing_lvar(p, lhs); + shadowing_lvar(p, id); return lhs; } @@ -7751,6 +8138,8 @@ comment_at_top(struct parser_params *p) typedef long (*rb_magic_comment_length_t)(struct parser_params *p, const char *name, long len); typedef void (*rb_magic_comment_setter_t)(struct parser_params *p, const char *name, const char *val); +static int parser_invalid_pragma_value(struct parser_params *p, const char *name, const char *val); + static void magic_comment_encoding(struct parser_params *p, const char *name, const char *val) { @@ -7765,17 +8154,23 @@ parser_get_bool(struct parser_params *p, const char *name, const char *val) { switch (*val) { case 't': case 'T': - if (strcasecmp(val, "true") == 0) { + if (STRCASECMP(val, "true") == 0) { return TRUE; } break; case 'f': case 'F': - if (strcasecmp(val, "false") == 0) { + if (STRCASECMP(val, "false") == 0) { return FALSE; } break; } - rb_compile_warning(p->ruby_sourcefile, p->ruby_sourceline, "invalid value for %s: %s", name, val); + return parser_invalid_pragma_value(p, name, val); +} + +static int +parser_invalid_pragma_value(struct parser_params *p, const char *name, const char *val) +{ + rb_warning2("invalid value for %s: %s", WARN_S(name), WARN_S(val)); return -1; } @@ -7802,7 +8197,44 @@ parser_set_compile_option_flag(struct parser_params *p, const char *name, const if (!p->compile_option) p->compile_option = rb_obj_hide(rb_ident_hash_new()); rb_hash_aset(p->compile_option, ID2SYM(rb_intern(name)), - (b ? Qtrue : Qfalse)); + RBOOL(b)); +} + +static void +parser_set_shareable_constant_value(struct parser_params *p, const char *name, const char *val) +{ + for (const char *s = p->lex.pbeg, *e = p->lex.pcur; s < e; ++s) { + if (*s == ' ' || *s == '\t') continue; + if (*s == '#') break; + rb_warning1("`%s' is ignored unless in comment-only line", WARN_S(name)); + return; + } + + switch (*val) { + case 'n': case 'N': + if (STRCASECMP(val, "none") == 0) { + p->ctxt.shareable_constant_value = shareable_none; + return; + } + break; + case 'l': case 'L': + if (STRCASECMP(val, "literal") == 0) { + p->ctxt.shareable_constant_value = shareable_literal; + return; + } + break; + case 'e': case 'E': + if (STRCASECMP(val, "experimental_copy") == 0) { + p->ctxt.shareable_constant_value = shareable_copy; + return; + } + if (STRCASECMP(val, "experimental_everything") == 0) { + p->ctxt.shareable_constant_value = shareable_everything; + return; + } + break; + } + parser_invalid_pragma_value(p, name, val); } # if WARN_PAST_SCOPE @@ -7824,6 +8256,7 @@ static const struct magic_comment magic_comments[] = { {"coding", magic_comment_encoding, parser_encode_length}, {"encoding", magic_comment_encoding, parser_encode_length}, {"frozen_string_literal", parser_set_compile_option_flag}, + {"shareable_constant_value", parser_set_shareable_constant_value}, {"warn_indent", parser_set_token_info}, # if WARN_PAST_SCOPE {"warn_past_scope", parser_set_past_scope}, @@ -7993,6 +8426,7 @@ set_file_encoding(struct parser_params *p, const char *str, const char *send) continue; } if (STRNCASECMP(str-6, "coding", 6) == 0) break; + sep = 0; } for (;;) { do { @@ -8390,18 +8824,26 @@ parse_percent(struct parser_params *p, const int space_seen, const enum lex_stat c = nextc(p); quotation: - if (c == -1 || !ISALNUM(c)) { + if (c == -1) goto unterminated; + if (!ISALNUM(c)) { term = c; + if (!ISASCII(c)) goto unknown; c = 'Q'; } else { term = nextc(p); if (rb_enc_isalnum(term, p->enc) || !parser_isascii(p)) { + unknown: + pushback(p, term); + c = parser_precise_mbclen(p, p->lex.pcur); + if (c < 0) return 0; + p->lex.pcur += c; yyerror0("unknown type of %string"); return 0; } } - if (c == -1 || term == -1) { + if (term == -1) { + unterminated: compile_error(p, "unterminated quoted string meets end of file"); return 0; } @@ -8591,7 +9033,8 @@ parse_gvar(struct parser_params *p, const enum lex_state_e last_state) pushback(p, c); if (IS_lex_state_for(last_state, EXPR_FNAME)) goto gvar; tokfix(p); - set_yylval_node(NEW_NTH_REF(parse_numvar(p), &_cur_loc)); + c = parse_numvar(p); + set_yylval_node(NEW_NTH_REF(c, &_cur_loc)); return tNTH_REF; default: @@ -8737,11 +9180,12 @@ parse_ident(struct parser_params *p, int c, int cmd_state) kw = rb_reserved_word(tok(p), toklen(p)); if (kw) { enum lex_state_e state = p->lex.state; - SET_LEX_STATE(kw->state); if (IS_lex_state_for(state, EXPR_FNAME)) { + SET_LEX_STATE(EXPR_ENDFN); set_yylval_name(rb_intern2(tok(p), toklen(p))); return kw->id[0]; } + SET_LEX_STATE(kw->state); if (IS_lex_state(EXPR_BEG)) { p->command_start = TRUE; } @@ -8826,7 +9270,14 @@ parser_yylex(struct parser_params *p) return 0; /* white spaces */ - case ' ': case '\t': case '\f': case '\r': + case '\r': + if (!p->cr_seen) { + p->cr_seen = TRUE; + /* carried over with p->lex.nextline for nextc() */ + rb_warn0("encountered \\r in middle of line, treated as a mere space"); + } + /* fall through */ + case ' ': case '\t': case '\f': case '\13': /* '\v' */ space_seen = 1; #ifdef RIPPER @@ -8866,7 +9317,7 @@ parser_yylex(struct parser_params *p) dispatch_scan_event(p, tIGNORED_NL); } fallthru = FALSE; - if (!c && p->in_kwarg) { + if (!c && p->ctxt.in_kwarg) { goto normal_newline; } goto retry; @@ -9232,9 +9683,17 @@ parser_yylex(struct parser_params *p) SET_LEX_STATE(EXPR_BEG); if ((c = nextc(p)) == '.') { if ((c = nextc(p)) == '.') { + if (p->ctxt.in_argdef) { + SET_LEX_STATE(EXPR_ENDARG); + return tBDOT3; + } if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) { rb_warn0("... at EOL, should be parenthesized?"); } + else if (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest) { + if (IS_lex_state_for(last_state, EXPR_LABEL)) + return tDOT3; + } return is_beg ? tBDOT3 : tDOT3; } pushback(p, c); @@ -9391,6 +9850,7 @@ parser_yylex(struct parser_params *p) p->lex.paren_nest++; if (IS_AFTER_OPERATOR()) { if ((c = nextc(p)) == ']') { + p->lex.paren_nest--; SET_LEX_STATE(EXPR_ARG); if ((c = nextc(p)) == '=') { return tASET; @@ -9495,16 +9955,17 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p) p->lval = lval; lval->val = Qundef; t = parser_yylex(p); - if (has_delayed_token(p)) - dispatch_delayed_token(p, t); - else if (t != 0) - dispatch_scan_event(p, t); if (p->lex.strterm && (p->lex.strterm->flags & STRTERM_HEREDOC)) RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*yylloc); else RUBY_SET_YYLLOC(*yylloc); + if (has_delayed_token(p)) + dispatch_delayed_token(p, t); + else if (t != 0) + dispatch_scan_event(p, t); + return t; } @@ -9616,7 +10077,7 @@ block_append(struct parser_params *p, NODE *head, NODE *tail) break; } - if (nd_type(tail) != NODE_BLOCK) { + if (!nd_type_p(tail, NODE_BLOCK)) { tail = NEW_BLOCK(tail, &tail->nd_loc); tail->nd_end = tail; } @@ -9692,12 +10153,24 @@ literal_concat0(struct parser_params *p, VALUE head, VALUE tail) return 1; } +static VALUE +string_literal_head(enum node_type htype, NODE *head) +{ + if (htype != NODE_DSTR) return Qfalse; + if (head->nd_next) { + head = head->nd_next->nd_end->nd_head; + if (!head || !nd_type_p(head, NODE_STR)) return Qfalse; + } + const VALUE lit = head->nd_lit; + ASSUME(lit != Qfalse); + return lit; +} + /* concat two string literals */ static NODE * literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *loc) { enum node_type htype; - NODE *headlast; VALUE lit; if (!head) return tail; @@ -9705,9 +10178,7 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l htype = nd_type(head); if (htype == NODE_EVSTR) { - NODE *node = NEW_DSTR(STR_NEW0(), loc); - RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit); - head = list_append(p, node, head); + head = new_dstr(p, head, loc); htype = NODE_DSTR; } if (p->heredoc_indent > 0) { @@ -9722,10 +10193,8 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l } switch (nd_type(tail)) { case NODE_STR: - if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) && - nd_type(headlast) == NODE_STR) { + if ((lit = string_literal_head(htype, head)) != Qfalse) { htype = NODE_STR; - lit = headlast->nd_lit; } else { lit = head->nd_lit; @@ -9755,13 +10224,16 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l else if (NIL_P(tail->nd_lit)) { append: head->nd_alen += tail->nd_alen - 1; - head->nd_next->nd_end->nd_next = tail->nd_next; - head->nd_next->nd_end = tail->nd_next->nd_end; + if (!head->nd_next) { + head->nd_next = tail->nd_next; + } + else if (tail->nd_next) { + head->nd_next->nd_end->nd_next = tail->nd_next; + head->nd_next->nd_end = tail->nd_next->nd_end; + } rb_discard_node(p, tail); } - else if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) && - nd_type(headlast) == NODE_STR) { - lit = headlast->nd_lit; + else if ((lit = string_literal_head(htype, head)) != Qfalse) { if (!literal_concat0(p, lit, tail->nd_lit)) goto error; tail->nd_lit = Qnil; @@ -9786,10 +10258,8 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l static NODE * evstr2dstr(struct parser_params *p, NODE *node) { - if (nd_type(node) == NODE_EVSTR) { - NODE * dstr = NEW_DSTR(STR_NEW0(), &node->nd_loc); - RB_OBJ_WRITTEN(p->ast, Qnil, dstr->nd_lit); - node = list_append(p, dstr, node); + if (nd_type_p(node, NODE_EVSTR)) { + node = new_dstr(p, node, &node->nd_loc); } return node; } @@ -9801,13 +10271,27 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc) if (node) { switch (nd_type(node)) { - case NODE_STR: case NODE_DSTR: case NODE_EVSTR: + case NODE_STR: + nd_set_type(node, NODE_DSTR); + return node; + case NODE_DSTR: + break; + case NODE_EVSTR: return node; } } return NEW_EVSTR(head, loc); } +static NODE * +new_dstr(struct parser_params *p, NODE *node, const YYLTYPE *loc) +{ + VALUE lit = STR_NEW0(); + NODE *dstr = NEW_DSTR(lit, loc); + RB_OBJ_WRITTEN(p->ast, Qnil, lit); + return list_append(p, dstr, node); +} + static NODE * call_bin_op(struct parser_params *p, NODE *recv, ID id, NODE *arg1, const YYLTYPE *op_loc, const YYLTYPE *loc) @@ -9849,7 +10333,7 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a return ret; } -#define nd_once_body(node) (nd_type(node) == NODE_ONCE ? (node)->nd_body : node) +#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? (node)->nd_body : node) static NODE* match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_loc, const YYLTYPE *loc) { @@ -9909,19 +10393,6 @@ past_dvar_p(struct parser_params *p, ID id) } # endif -/* As Ripper#warn does not have arguments for the location, so the - * following messages cannot be separated */ -#define WARN_LOCATION(type) do { \ - if (p->warn_location) { \ - int line; \ - VALUE file = rb_source_location(&line); \ - rb_warn3(type" in eval may not return location in binding;" \ - " use Binding#source_location instead\n" \ - "%"PRIsWARN":%d: warning: in `%"PRIsWARN"'", \ - file, WARN_I(line), rb_id2str(rb_frame_this_func())); \ - } \ -} while (0) - static int numparam_nested_p(struct parser_params *p) { @@ -9955,7 +10426,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case keyword_false: return NEW_FALSE(loc); case keyword__FILE__: - WARN_LOCATION("__FILE__"); { VALUE file = p->ruby_sourcefile_string; if (NIL_P(file)) @@ -9967,7 +10437,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) } return node; case keyword__LINE__: - WARN_LOCATION("__LINE__"); return NEW_LIT(INT2FIX(p->tokline), loc); case keyword__ENCODING__: node = NEW_LIT(rb_enc_from_encoding(p->enc), loc); @@ -10005,7 +10474,7 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) return node; } # if WARN_PAST_SCOPE - if (!p->in_defined && RTEST(ruby_verbose) && past_dvar_p(p, id)) { + if (!p->ctxt.in_defined && RTEST(ruby_verbose) && past_dvar_p(p, id)) { rb_warning1("possible reference to past scope - %"PRIsWARN, rb_id2str(id)); } # endif @@ -10063,12 +10532,17 @@ new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) static NODE* symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol) { - if (nd_type(symbol) == NODE_DSTR) { + enum node_type type = nd_type(symbol); + switch (type) { + case NODE_DSTR: nd_set_type(symbol, NODE_DSYM); - } - else { + break; + case NODE_STR: nd_set_type(symbol, NODE_LIT); RB_OBJ_WRITTEN(p->ast, Qnil, symbol->nd_lit = rb_str_intern(symbol->nd_lit)); + break; + default: + compile_error(p, "unexpected node as symbol: %s", ruby_node_name(type)); } return list_append(p, symbols, symbol); } @@ -10104,8 +10578,10 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc) node->nd_cflag = options & RE_OPTION_MASK; if (!NIL_P(node->nd_lit)) reg_fragment_check(p, node->nd_lit, options); for (list = (prev = node)->nd_next; list; list = list->nd_next) { - if (nd_type(list->nd_head) == NODE_STR) { - VALUE tail = list->nd_head->nd_lit; + NODE *frag = list->nd_head; + enum node_type type = nd_type(frag); + if (type == NODE_STR || (type == NODE_DSTR && !frag->nd_next)) { + VALUE tail = frag->nd_lit; if (reg_fragment_check(p, tail, options) && prev && !NIL_P(prev->nd_lit)) { VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit; if (!literal_concat0(p, lit, tail)) { @@ -10179,7 +10655,7 @@ check_literal_when(struct parser_params *p, NODE *arg, const YYLTYPE *loc) lit = rb_node_case_when_optimizable_literal(arg); if (lit == Qundef) return; - if (nd_type(arg) == NODE_STR) { + if (nd_type_p(arg, NODE_STR)) { RB_OBJ_WRITTEN(p->ast, Qnil, arg->nd_lit = lit); } @@ -10238,6 +10714,14 @@ new_regexp(struct parser_params *p, VALUE re, VALUE opt, const YYLTYPE *loc) } #endif /* !RIPPER */ +static inline enum lex_state_e +parser_set_lex_state(struct parser_params *p, enum lex_state_e ls, int line) +{ + if (p->debug) { + ls = rb_parser_trace_lex_state(p, p->lex.state, ls, line); + } + return p->lex.state = ls; +} #ifndef RIPPER static const char rb_parser_lex_state_names[][8] = { @@ -10334,7 +10818,7 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...) va_start(ap, fmt); rb_str_vcatf(mesg, fmt, ap); va_end(ap); - parser_yyerror(p, NULL, RSTRING_PTR(mesg)); + yyerror0(RSTRING_PTR(mesg)); RB_GC_GUARD(mesg); mesg = rb_str_new(0, 0); @@ -10346,11 +10830,21 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...) rb_str_resize(mesg, 0); append_bitstack_value(p->cmdarg_stack, mesg); compile_error(p, "cmdarg_stack: %"PRIsVALUE, mesg); - if (p->debug_output == rb_stdout) - p->debug_output = rb_stderr; + if (p->debug_output == rb_ractor_stdout()) + p->debug_output = rb_ractor_stderr(); p->debug = TRUE; } +static YYLTYPE * +rb_parser_set_pos(YYLTYPE *yylloc, int sourceline, int beg_pos, int end_pos) +{ + yylloc->beg_pos.lineno = sourceline; + yylloc->beg_pos.column = beg_pos; + yylloc->end_pos.lineno = sourceline; + yylloc->end_pos.column = end_pos; + return yylloc; +} + YYLTYPE * rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_heredoc_t *here, YYLTYPE *yylloc) { @@ -10359,77 +10853,28 @@ rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_ - (rb_strlen_lit("<<-") - !(here->func & STR_FUNC_INDENT)); int end_pos = (int)here->offset + here->length + here->quote; - yylloc->beg_pos.lineno = sourceline; - yylloc->beg_pos.column = beg_pos; - yylloc->end_pos.lineno = sourceline; - yylloc->end_pos.column = end_pos; - return yylloc; + return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos); } YYLTYPE * rb_parser_set_location_of_none(struct parser_params *p, YYLTYPE *yylloc) { - yylloc->beg_pos.lineno = p->ruby_sourceline; - yylloc->beg_pos.column = (int)(p->lex.ptok - p->lex.pbeg); - yylloc->end_pos.lineno = p->ruby_sourceline; - yylloc->end_pos.column = (int)(p->lex.ptok - p->lex.pbeg); - return yylloc; + int sourceline = p->ruby_sourceline; + int beg_pos = (int)(p->lex.ptok - p->lex.pbeg); + int end_pos = (int)(p->lex.ptok - p->lex.pbeg); + return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos); } YYLTYPE * rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc) { - yylloc->beg_pos.lineno = p->ruby_sourceline; - yylloc->beg_pos.column = (int)(p->lex.ptok - p->lex.pbeg); - yylloc->end_pos.lineno = p->ruby_sourceline; - yylloc->end_pos.column = (int)(p->lex.pcur - p->lex.pbeg); - return yylloc; + int sourceline = p->ruby_sourceline; + int beg_pos = (int)(p->lex.ptok - p->lex.pbeg); + int end_pos = (int)(p->lex.pcur - p->lex.pbeg); + return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos); } #endif /* !RIPPER */ -static void -parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp) -{ - VALUE v; - - switch (type) { - case tIDENTIFIER: case tFID: case tGVAR: case tIVAR: - case tCONSTANT: case tCVAR: case tLABEL: case tOP_ASGN: -#ifndef RIPPER - v = rb_id2str(valp->id); -#else - v = valp->node->nd_rval; -#endif - rb_parser_printf(p, "%"PRIsVALUE, v); - break; - case tINTEGER: case tFLOAT: case tRATIONAL: case tIMAGINARY: - case tSTRING_CONTENT: case tCHAR: -#ifndef RIPPER - v = valp->node->nd_lit; -#else - v = valp->val; -#endif - rb_parser_printf(p, "%+"PRIsVALUE, v); - break; - case tNTH_REF: -#ifndef RIPPER - rb_parser_printf(p, "$%ld", valp->node->nd_nth); -#else - rb_parser_printf(p, "%"PRIsVALUE, valp->val); -#endif - break; - case tBACK_REF: -#ifndef RIPPER - rb_parser_printf(p, "$%c", (int)valp->node->nd_nth); -#else - rb_parser_printf(p, "%"PRIsVALUE, valp->val); -#endif - break; - default: - break; - } -} - static int assignable0(struct parser_params *p, ID id, const char **err) { @@ -10465,11 +10910,11 @@ assignable0(struct parser_params *p, ID id, const char **err) NUMPARAM_ID_TO_IDX(id)); return -1; } - if (dvar_curr(p, id)) return NODE_DASGN_CURR; + if (dvar_curr(p, id)) return NODE_DASGN; if (dvar_defined(p, id)) return NODE_DASGN; if (local_id(p, id)) return NODE_LASGN; dyna_var(p, id); - return NODE_DASGN_CURR; + return NODE_DASGN; } else { if (!local_id(p, id)) local_var(p, id); @@ -10479,7 +10924,7 @@ assignable0(struct parser_params *p, ID id, const char **err) case ID_GLOBAL: return NODE_GASGN; case ID_INSTANCE: return NODE_IASGN; case ID_CONST: - if (!p->in_def) return NODE_CDECL; + if (!p->ctxt.in_def) return NODE_CDECL; *err = "dynamic constant assignment"; return -1; case ID_CLASS: return NODE_CVASGN; @@ -10496,7 +10941,6 @@ assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc) const char *err = 0; int node_type = assignable0(p, id, &err); switch (node_type) { - case NODE_DASGN_CURR: return NEW_DASGN_CURR(id, val, loc); case NODE_DASGN: return NEW_DASGN(id, val, loc); case NODE_LASGN: return NEW_LASGN(id, val, loc); case NODE_GASGN: return NEW_GASGN(id, val, loc); @@ -10513,7 +10957,7 @@ assignable(struct parser_params *p, VALUE lhs) { const char *err = 0; assignable0(p, get_id(lhs), &err); - if (err) lhs = assign_error(p, lhs); + if (err) lhs = assign_error(p, err, lhs); return lhs; } #endif @@ -10583,7 +11027,7 @@ aryset(struct parser_params *p, NODE *recv, NODE *idx, const YYLTYPE *loc) static void block_dup_check(struct parser_params *p, NODE *node1, NODE *node2) { - if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) { + if (node2 && node1 && nd_type_p(node1, NODE_BLOCK_PASS)) { compile_error(p, "both block arg and actual block given"); } } @@ -10607,7 +11051,17 @@ rb_backref_error(struct parser_params *p, NODE *node) break; } } +#else +static VALUE +backref_error(struct parser_params *p, NODE *ref, VALUE expr) +{ + VALUE mesg = rb_str_new_cstr("Can't set variable "); + rb_str_append(mesg, ref->nd_cval); + return dispatch2(assign_error, mesg, expr); +} +#endif +#ifndef RIPPER static NODE * arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc) { @@ -10625,7 +11079,7 @@ arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc nd_set_type(node1, NODE_ARGSCAT); return node1; case NODE_ARGSCAT: - if (nd_type(node1->nd_body) != NODE_LIST) break; + if (!nd_type_p(node1->nd_body, NODE_LIST)) break; node1->nd_body = list_append(p, node1->nd_body, node2); node1->nd_loc.end_pos = node1->nd_body->nd_loc.end_pos; return node1; @@ -10645,13 +11099,13 @@ arg_concat(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc node1->nd_head = NEW_LIST(node2, loc); return node1; case NODE_ARGSPUSH: - if (nd_type(node2) != NODE_LIST) break; + if (!nd_type_p(node2, NODE_LIST)) break; node1->nd_body = list_concat(NEW_LIST(node1->nd_body, loc), node2); nd_set_type(node1, NODE_ARGSCAT); return node1; case NODE_ARGSCAT: - if (nd_type(node2) != NODE_LIST || - nd_type(node1->nd_body) != NODE_LIST) break; + if (!nd_type_p(node2, NODE_LIST) || + !nd_type_p(node1->nd_body, NODE_LIST)) break; node1->nd_body = list_concat(node1->nd_body, node2); return node1; } @@ -10672,7 +11126,7 @@ static NODE * rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc) { NODE *n1; - if ((nd_type(rest_arg) == NODE_LIST) && (n1 = splat_array(args)) != 0) { + if ((nd_type_p(rest_arg, NODE_LIST)) && (n1 = splat_array(args)) != 0) { return list_concat(n1, rest_arg); } return arg_concat(p, args, rest_arg, loc); @@ -10681,8 +11135,8 @@ rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTY static NODE * splat_array(NODE* node) { - if (nd_type(node) == NODE_SPLAT) node = node->nd_head; - if (nd_type(node) == NODE_LIST) return node; + if (nd_type_p(node, NODE_SPLAT)) node = node->nd_head; + if (nd_type_p(node, NODE_LIST)) return node; return 0; } @@ -10698,7 +11152,6 @@ mark_lvar_used(struct parser_params *p, NODE *rhs) } break; case NODE_DASGN: - case NODE_DASGN_CURR: if (dvar_defined_ref(p, rhs->nd_vid, &vidp)) { if (vidp) *vidp |= LVAR_USED; } @@ -10714,18 +11167,266 @@ mark_lvar_used(struct parser_params *p, NODE *rhs) } static NODE * -node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, const YYLTYPE *loc) +const_decl_path(struct parser_params *p, NODE **dest) +{ + NODE *n = *dest; + if (!nd_type_p(n, NODE_CALL)) { + const YYLTYPE *loc = &n->nd_loc; + VALUE path; + if (n->nd_vid) { + path = rb_id2str(n->nd_vid); + } + else { + n = n->nd_else; + path = rb_ary_new(); + for (; n && nd_type_p(n, NODE_COLON2); n = n->nd_head) { + rb_ary_push(path, rb_id2str(n->nd_mid)); + } + if (n && nd_type_p(n, NODE_CONST)) { + // Const::Name + rb_ary_push(path, rb_id2str(n->nd_vid)); + } + else if (n && nd_type_p(n, NODE_COLON3)) { + // ::Const::Name + 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("::")); + path = rb_fstring(path); + } + *dest = n = NEW_LIT(path, loc); + RB_OBJ_WRITTEN(p->ast, Qnil, n->nd_lit); + } + return n; +} + +extern VALUE rb_mRubyVMFrozenCore; + +static NODE * +make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTYPE *loc) +{ + NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc); + + if (copy) { + return NEW_CALL(fcore, rb_intern("make_shareable_copy"), + NEW_LIST(value, loc), loc); + } + else { + return NEW_CALL(fcore, rb_intern("make_shareable"), + NEW_LIST(value, loc), loc); + } +} + +static NODE * +ensure_shareable_node(struct parser_params *p, NODE **dest, NODE *value, const YYLTYPE *loc) +{ + NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc); + NODE *args = NEW_LIST(value, loc); + args = list_append(p, args, const_decl_path(p, dest)); + return NEW_CALL(fcore, rb_intern("ensure_shareable"), args, loc); +} + +static int is_static_content(NODE *node); + +static VALUE +shareable_literal_value(NODE *node) +{ + if (!node) return Qnil; + enum node_type type = nd_type(node); + switch (type) { + case NODE_TRUE: + return Qtrue; + case NODE_FALSE: + return Qfalse; + case NODE_NIL: + return Qnil; + case NODE_LIT: + return node->nd_lit; + default: + return Qundef; + } +} + +#ifndef SHAREABLE_BARE_EXPRESSION +#define SHAREABLE_BARE_EXPRESSION 1 +#endif + +static NODE * +shareable_literal_constant(struct parser_params *p, enum shareability shareable, + NODE **dest, NODE *value, const YYLTYPE *loc, size_t level) +{ +# define shareable_literal_constant_next(n) \ + shareable_literal_constant(p, shareable, dest, (n), &(n)->nd_loc, level+1) + VALUE lit = Qnil; + + if (!value) return 0; + enum node_type type = nd_type(value); + switch (type) { + case NODE_TRUE: + case NODE_FALSE: + case NODE_NIL: + case NODE_LIT: + return value; + + case NODE_DSTR: + if (shareable == shareable_literal) { + value = NEW_CALL(value, idUMinus, 0, loc); + } + return value; + + case NODE_STR: + lit = rb_fstring(value->nd_lit); + nd_set_type(value, NODE_LIT); + RB_OBJ_WRITE(p->ast, &value->nd_lit, lit); + return value; + + case NODE_ZLIST: + lit = rb_ary_new(); + OBJ_FREEZE_RAW(lit); + NODE *n = NEW_LIT(lit, loc); + RB_OBJ_WRITTEN(p->ast, Qnil, n->nd_lit); + return n; + + case NODE_LIST: + lit = rb_ary_new(); + for (NODE *n = value; n; n = n->nd_next) { + NODE *elt = n->nd_head; + if (elt) { + elt = shareable_literal_constant_next(elt); + if (elt) { + n->nd_head = elt; + } + else if (RTEST(lit)) { + rb_ary_clear(lit); + lit = Qfalse; + } + } + if (RTEST(lit)) { + VALUE e = shareable_literal_value(elt); + if (e != Qundef) { + rb_ary_push(lit, e); + } + else { + rb_ary_clear(lit); + lit = Qnil; /* make shareable at runtime */ + } + } + } + break; + + case NODE_HASH: + if (!value->nd_brace) return 0; + lit = rb_hash_new(); + for (NODE *n = value->nd_head; n; n = n->nd_next->nd_next) { + NODE *key = n->nd_head; + NODE *val = n->nd_next->nd_head; + if (key) { + key = shareable_literal_constant_next(key); + if (key) { + n->nd_head = key; + } + else if (RTEST(lit)) { + rb_hash_clear(lit); + lit = Qfalse; + } + } + if (val) { + val = shareable_literal_constant_next(val); + if (val) { + n->nd_next->nd_head = val; + } + else if (RTEST(lit)) { + rb_hash_clear(lit); + lit = Qfalse; + } + } + if (RTEST(lit)) { + VALUE k = shareable_literal_value(key); + VALUE v = shareable_literal_value(val); + if (k != Qundef && v != Qundef) { + rb_hash_aset(lit, k, v); + } + else { + rb_hash_clear(lit); + lit = Qnil; /* make shareable at runtime */ + } + } + } + break; + + default: + if (shareable == shareable_literal && + (SHAREABLE_BARE_EXPRESSION || level > 0)) { + return ensure_shareable_node(p, dest, value, loc); + } + return 0; + } + + /* Array or Hash */ + if (!lit) return 0; + if (NIL_P(lit)) { + // if shareable_literal, all elements should have been ensured + // as shareable + value = make_shareable_node(p, value, false, loc); + } + else { + value = NEW_LIT(rb_ractor_make_shareable(lit), loc); + RB_OBJ_WRITTEN(p->ast, Qnil, value->nd_lit); + } + + return value; +# undef shareable_literal_constant_next +} + +static NODE * +shareable_constant_value(struct parser_params *p, enum shareability shareable, + NODE *lhs, NODE *value, const YYLTYPE *loc) +{ + if (!value) return 0; + switch (shareable) { + case shareable_none: + return value; + + case shareable_literal: + { + NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0); + if (lit) return lit; + return value; + } + break; + + case shareable_copy: + case shareable_everything: + { + NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0); + if (lit) return lit; + return make_shareable_node(p, value, shareable == shareable_copy, loc); + } + break; + + default: + UNREACHABLE_RETURN(0); + } +} + +static NODE * +node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc) { if (!lhs) return 0; switch (nd_type(lhs)) { + case NODE_CDECL: + rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc); + /* fallthru */ + case NODE_GASGN: case NODE_IASGN: case NODE_LASGN: case NODE_DASGN: - case NODE_DASGN_CURR: case NODE_MASGN: - case NODE_CDECL: case NODE_CVASGN: lhs->nd_value = rhs; nd_set_loc(lhs, loc); @@ -10762,7 +11463,7 @@ value_expr_check(struct parser_params *p, NODE *node) return void_node ? void_node : node; case NODE_CASE3: - if (!node->nd_body || nd_type(node->nd_body) != NODE_IN) { + if (!node->nd_body || !nd_type_p(node->nd_body, NODE_IN)) { compile_error(p, "unexpected node"); return NULL; } @@ -10804,7 +11505,6 @@ value_expr_check(struct parser_params *p, NODE *node) case NODE_LASGN: case NODE_DASGN: - case NODE_DASGN_CURR: case NODE_MASGN: mark_lvar_used(p, node); return NULL; @@ -10918,7 +11618,7 @@ void_stmts(struct parser_params *p, NODE *node) NODE *const n = node; if (!RTEST(ruby_verbose)) return n; if (!node) return n; - if (nd_type(node) != NODE_BLOCK) return n; + if (!nd_type_p(node, NODE_BLOCK)) return n; while (node->nd_next) { void_expr(p, node->nd_head); @@ -10931,7 +11631,7 @@ static NODE * remove_begin(NODE *node) { NODE **n = &node, *n1 = node; - while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) { + while (n1 && nd_type_p(n1, NODE_BEGIN) && n1->nd_body) { *n = n1 = n1->nd_body; } return node; @@ -10941,7 +11641,7 @@ static NODE * remove_begin_all(NODE *node) { NODE **n = &node, *n1 = node; - while (n1 && nd_type(n1) == NODE_BEGIN) { + while (n1 && nd_type_p(n1, NODE_BEGIN)) { *n = n1 = n1->nd_body; } return node; @@ -11040,7 +11740,6 @@ assign_in_cond(struct parser_params *p, NODE *node) case NODE_MASGN: case NODE_LASGN: case NODE_DASGN: - case NODE_DASGN_CURR: case NODE_GASGN: case NODE_IASGN: break; @@ -11083,7 +11782,8 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc) value_expr(node); if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) { if (!e_option_supplied(p)) parser_warn(p, node, "integer literal in flip-flop"); - return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."), loc), loc), loc); + ID lineno = rb_intern("$."); + return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(lineno, loc), loc), loc); } return cond0(p, node, COND_IN_FF, loc); } @@ -11117,12 +11817,13 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l case NODE_DOT3: node->nd_beg = range_op(p, node->nd_beg, loc); node->nd_end = range_op(p, node->nd_end, loc); - if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2); - else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3); + if (nd_type_p(node, NODE_DOT2)) nd_set_type(node,NODE_FLIP2); + else if (nd_type_p(node, NODE_DOT3)) nd_set_type(node, NODE_FLIP3); break; case NODE_DSYM: - SWITCH_BY_COND_TYPE(type, warning, "string ") + warn_symbol: + SWITCH_BY_COND_TYPE(type, warning, "symbol ") break; case NODE_LIT: @@ -11134,6 +11835,9 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l node->nd_lit == Qfalse) { /* booleans are OK, e.g., while true */ } + else if (SYMBOL_P(node->nd_lit)) { + goto warn_symbol; + } else { SWITCH_BY_COND_TYPE(type, warning, "") } @@ -11157,6 +11861,13 @@ method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc) return cond0(p, node, COND_IN_OP, loc); } +static NODE* +new_nil_at(struct parser_params *p, const rb_code_position_t *pos) +{ + YYLTYPE loc = {*pos, *pos}; + return NEW_NIL(&loc); +} + static NODE* new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc) { @@ -11180,9 +11891,9 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right, enum node_type type = id == idAND || id == idANDOP ? NODE_AND : NODE_OR; NODE *op; value_expr(left); - if (left && (enum node_type)nd_type(left) == type) { + if (left && nd_type_p(left, type)) { NODE *node = left, *second; - while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) { + while ((second = node->nd_2nd) != 0 && nd_type_p(second, type)) { node = second; } node->nd_2nd = NEW_NODE(type, second, right, 0, loc); @@ -11198,7 +11909,7 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right, static void no_blockarg(struct parser_params *p, NODE *node) { - if (node && nd_type(node) == NODE_BLOCK_PASS) { + if (node && nd_type_p(node, NODE_BLOCK_PASS)) { compile_error(p, "block argument should not be given"); } } @@ -11208,7 +11919,7 @@ ret_args(struct parser_params *p, NODE *node) { if (node) { no_blockarg(p, node); - if (nd_type(node) == NODE_LIST) { + if (nd_type_p(node, NODE_LIST)) { if (node->nd_next == 0) { node = node->nd_head; } @@ -11248,14 +11959,14 @@ negate_lit(struct parser_params *p, VALUE lit) lit = rb_big_norm(lit); break; case T_RATIONAL: - RRATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); + RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num)); break; case T_COMPLEX: RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real)); RCOMPLEX_SET_IMAG(lit, negate_lit(p, RCOMPLEX(lit)->imag)); break; case T_FLOAT: - RFLOAT(lit)->float_value = -RFLOAT_VALUE(lit); + lit = DBL2NUM(-RFLOAT_VALUE(lit)); break; unknown: default: @@ -11298,6 +12009,14 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N int saved_line = p->ruby_sourceline; struct rb_args_info *args = tail->nd_ainfo; + if (args->block_arg == idFWD_BLOCK) { + if (rest_arg) { + yyerror1(&tail->nd_loc, "... after rest argument"); + return tail; + } + rest_arg = idFWD_REST; + } + args->pre_args_num = pre_args ? rb_long2int(pre_args->nd_plen) : 0; args->pre_init = pre_args ? pre_args->nd_next : 0; @@ -11318,7 +12037,7 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N } static NODE* -new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, const YYLTYPE *loc) +new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, const YYLTYPE *kw_rest_loc) { int saved_line = p->ruby_sourceline; NODE *node; @@ -11367,14 +12086,14 @@ new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, if (kw_rest_arg) arg_var(p, kw_rest_arg); if (block) arg_var(p, block); - args->kw_rest_arg = NEW_DVAR(kw_rest_arg, loc); + args->kw_rest_arg = NEW_DVAR(kw_rest_arg, kw_rest_loc); args->kw_rest_arg->nd_cflag = kw_bits; } else if (kw_rest_arg == idNil) { args->no_kwarg = 1; } else if (kw_rest_arg) { - args->kw_rest_arg = NEW_DVAR(kw_rest_arg, loc); + args->kw_rest_arg = NEW_DVAR(kw_rest_arg, kw_rest_loc); } p->ruby_sourceline = saved_line; @@ -11422,8 +12141,7 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer(); struct rb_ary_pattern_info *apinfo = ZALLOC(struct rb_ary_pattern_info); rb_imemo_tmpbuf_set_ptr(tmpbuf, apinfo); - node = NEW_NODE(NODE_ARYPTN, 0, 0, apinfo, loc); - apinfo->imemo = tmpbuf; + node = NEW_NODE(NODE_ARYPTN, 0, tmpbuf, apinfo, loc); RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf); apinfo->pre_args = pre_args; @@ -11446,6 +12164,33 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID return node; } +static NODE* +new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc) +{ + fndptn->nd_pconst = constant; + + return fndptn; +} + +static NODE* +new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc) +{ + int saved_line = p->ruby_sourceline; + NODE *node; + VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer(); + struct rb_fnd_pattern_info *fpinfo = ZALLOC(struct rb_fnd_pattern_info); + rb_imemo_tmpbuf_set_ptr(tmpbuf, fpinfo); + node = NEW_NODE(NODE_FNDPTN, 0, tmpbuf, fpinfo, loc); + RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf); + + fpinfo->pre_rest_arg = pre_rest_arg ? assignable(p, pre_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST; + fpinfo->args = args; + fpinfo->post_rest_arg = post_rest_arg ? assignable(p, post_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST; + + p->ruby_sourceline = saved_line; + return node; +} + static NODE* new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc) { @@ -11475,16 +12220,6 @@ new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, co return node; } -static NODE * -new_case3(struct parser_params *p, NODE *val, NODE *pat, const YYLTYPE *loc) -{ - NODE *node = NEW_CASE3(val, pat, loc); - - if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) - rb_warn0L(nd_line(node), "Pattern matching is experimental, and the behavior may change in future versions of Ruby!"); - return node; -} - static NODE* dsym_node(struct parser_params *p, NODE *node, const YYLTYPE *loc) { @@ -11527,29 +12262,66 @@ append_literal_keys(st_data_t k, st_data_t v, st_data_t h) return ST_CONTINUE; } +static bool +hash_literal_key_p(VALUE k) +{ + switch (OBJ_BUILTIN_TYPE(k)) { + case T_NODE: + return false; + default: + return true; + } +} + +static int +literal_cmp(VALUE val, VALUE lit) +{ + if (val == lit) return 0; + if (!hash_literal_key_p(val) || !hash_literal_key_p(lit)) return -1; + return rb_iseq_cdhash_cmp(val, lit); +} + +static st_index_t +literal_hash(VALUE a) +{ + if (!hash_literal_key_p(a)) return (st_index_t)a; + return rb_iseq_cdhash_hash(a); +} + +static const struct st_hash_type literal_type = { + literal_cmp, + literal_hash, +}; + static NODE * remove_duplicate_keys(struct parser_params *p, NODE *hash) { - st_table *literal_keys = st_init_numtable_with_size(hash->nd_alen / 2); + st_table *literal_keys = st_init_table_with_size(&literal_type, hash->nd_alen / 2); NODE *result = 0; + NODE *last_expr = 0; rb_code_location_t loc = hash->nd_loc; while (hash && hash->nd_head && hash->nd_next) { NODE *head = hash->nd_head; NODE *value = hash->nd_next; NODE *next = value->nd_next; - VALUE key = (VALUE)head; + st_data_t key = (st_data_t)head; st_data_t data; - if (nd_type(head) == NODE_LIT && - st_lookup(literal_keys, (key = head->nd_lit), &data)) { + value->nd_next = 0; + if (nd_type_p(head, NODE_LIT) && + st_delete(literal_keys, (key = (st_data_t)head->nd_lit, &key), &data)) { + NODE *dup_value = ((NODE *)data)->nd_next; rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), "key %+"PRIsVALUE" is duplicated and overwritten on line %d", head->nd_lit, nd_line(head)); - head = ((NODE *)data)->nd_next; - head->nd_head = block_append(p, head->nd_head, value->nd_head); - } - else { - st_insert(literal_keys, (st_data_t)key, (st_data_t)hash); + if (dup_value == last_expr) { + value->nd_head = block_append(p, dup_value->nd_head, value->nd_head); + } + else { + last_expr->nd_head = block_append(p, dup_value->nd_head, last_expr->nd_head); + } } + st_insert(literal_keys, (st_data_t)key, (st_data_t)hash); + last_expr = nd_type_p(head, NODE_LIT) ? value : head; hash = next; } st_foreach(literal_keys, append_literal_keys, (st_data_t)&result); @@ -11607,14 +12379,27 @@ new_unique_key_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc) #ifndef RIPPER static NODE * -new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc) +new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc) { NODE *asgn; if (lhs) { ID vid = lhs->nd_vid; YYLTYPE lhs_loc = lhs->nd_loc; + int shareable = ctxt.shareable_constant_value; + if (shareable) { + switch (nd_type(lhs)) { + case NODE_CDECL: + case NODE_COLON2: + case NODE_COLON3: + break; + default: + shareable = 0; + break; + } + } if (op == tOROP) { + rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc); lhs->nd_value = rhs; nd_set_loc(lhs, loc); asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc); @@ -11628,13 +12413,20 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYP } } else if (op == tANDOP) { + if (shareable) { + rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc); + } lhs->nd_value = rhs; nd_set_loc(lhs, loc); asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc); } else { asgn = lhs; - asgn->nd_value = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc); + rhs = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc); + if (shareable) { + rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc); + } + asgn->nd_value = rhs; nd_set_loc(asgn, loc); } } @@ -11651,7 +12443,7 @@ new_ary_op_assign(struct parser_params *p, NODE *ary, NODE *asgn; args = make_list(args, args_loc); - if (nd_type(args) == NODE_BLOCK_PASS) { + if (nd_type_p(args, NODE_BLOCK_PASS)) { args = NEW_ARGSCAT(args, rhs, loc); } else { @@ -11674,11 +12466,12 @@ new_attr_op_assign(struct parser_params *p, NODE *lhs, } static NODE * -new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc) +new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc) { NODE *asgn; if (lhs) { + rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc); asgn = NEW_OP_CDECL(lhs, op, rhs, loc); } else { @@ -11691,7 +12484,7 @@ new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const static NODE * const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc) { - if (p->in_def) { + if (p->ctxt.in_def) { yyerror1(loc, "dynamic constant assignment"); } return NEW_CDECL(0, 0, (path), loc); @@ -11700,17 +12493,16 @@ const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc) static VALUE const_decl(struct parser_params *p, VALUE path) { - if (p->in_def) { - path = dispatch1(assign_error, path); - ripper_error(p); + if (p->ctxt.in_def) { + path = assign_error(p, "dynamic constant assignment", path); } return path; } static VALUE -assign_error(struct parser_params *p, VALUE a) +assign_error(struct parser_params *p, const char *mesg, VALUE a) { - a = dispatch1(assign_error, a); + a = dispatch2(assign_error, ERR_MESG(), a); ripper_error(p); return a; } @@ -11818,43 +12610,36 @@ local_pop(struct parser_params *p) } #ifndef RIPPER -static ID* +static rb_ast_id_table_t * local_tbl(struct parser_params *p) { int cnt_args = vtable_size(p->lvtbl->args); int cnt_vars = vtable_size(p->lvtbl->vars); int cnt = cnt_args + cnt_vars; int i, j; - ID *buf; - VALUE tbl = 0; + rb_ast_id_table_t *tbl; if (cnt <= 0) return 0; - tbl = rb_imemo_tmpbuf_auto_free_pointer(); - buf = ALLOC_N(ID, cnt + 2); - rb_imemo_tmpbuf_set_ptr(tbl, buf); - MEMCPY(buf+1, p->lvtbl->args->tbl, ID, cnt_args); + tbl = rb_ast_new_local_table(p->ast, cnt); + MEMCPY(tbl->ids, p->lvtbl->args->tbl, ID, cnt_args); /* remove IDs duplicated to warn shadowing */ - for (i = 0, j = cnt_args+1; i < cnt_vars; ++i) { + for (i = 0, j = cnt_args; i < cnt_vars; ++i) { ID id = p->lvtbl->vars->tbl[i]; if (!vtable_included(p->lvtbl->args, id)) { - buf[j++] = id; + tbl->ids[j++] = id; } } - if (--j < cnt) { - REALLOC_N(buf, ID, (cnt = j) + 2); - rb_imemo_tmpbuf_set_ptr(tbl, buf); + if (j < cnt) { + tbl = rb_ast_resize_latest_local_table(p->ast, j); } - buf[0] = cnt; - buf[cnt + 1] = (ID)tbl; - RB_OBJ_WRITTEN(p->ast, Qnil, tbl); - return buf; + return tbl; } static NODE* node_newnode_with_locals(struct parser_params *p, enum node_type type, VALUE a1, VALUE a2, const rb_code_location_t *loc) { - ID *a0; + rb_ast_id_table_t *a0; NODE *n; a0 = local_tbl(p); @@ -11868,8 +12653,8 @@ static void numparam_name(struct parser_params *p, ID id) { if (!NUMPARAM_ID_P(id)) return; - rb_warn1("`_%d' is reserved for numbered parameter; consider another name", - WARN_I(NUMPARAM_ID_TO_IDX(id))); + compile_error(p, "_%d is reserved for numbered parameter", + NUMPARAM_ID_TO_IDX(id)); } static void @@ -11923,6 +12708,45 @@ local_id(struct parser_params *p, ID id) return local_id_ref(p, id, NULL); } +static int +check_forwarding_args(struct parser_params *p) +{ + if (local_id(p, idFWD_REST) && +#if idFWD_KWREST + local_id(p, idFWD_KWREST) && +#endif + local_id(p, idFWD_BLOCK)) return TRUE; + compile_error(p, "unexpected ..."); + return FALSE; +} + +static void +add_forwarding_args(struct parser_params *p) +{ + arg_var(p, idFWD_REST); +#if idFWD_KWREST + arg_var(p, idFWD_KWREST); +#endif + arg_var(p, idFWD_BLOCK); +} + +#ifndef RIPPER +static NODE * +new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc, const YYLTYPE *argsloc) +{ + NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, loc), loc); +#if idFWD_KWREST + NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc)); +#endif + NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), loc); + NODE *args = leading ? rest_arg_append(p, leading, splat, argsloc) : splat; +#if idFWD_KWREST + args = arg_append(p, splat, new_hash(p, kwrest, loc), loc); +#endif + return arg_blk_pass(args, block); +} +#endif + static NODE * numparam_push(struct parser_params *p) { @@ -12049,7 +12873,7 @@ dvar_defined_ref(struct parser_params *p, ID id, ID **vidrefp) if (used) used = used->prev; } - if (vars == DVARS_INHERIT) { + if (vars == DVARS_INHERIT && !NUMPARAM_ID_P(id)) { return rb_dvar_defined(id, p->parent_iseq); } @@ -12156,13 +12980,14 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end, NODE *node, *succ; if (!len) return ST_CONTINUE; - if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) - return ST_CONTINUE; if (rb_enc_symname_type(s, len, enc, (1U<loc), NEW_LIT(ID2SYM(var), arg->loc), arg->loc); + if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) { + if (!lvar_defined(p, var)) return ST_CONTINUE; + } + node = node_assign(p, assignable(p, var, 0, arg->loc), NEW_LIT(ID2SYM(var), arg->loc), NO_LEX_CTXT, arg->loc); succ = arg->succ_block; if (!succ) succ = NEW_BEGIN(0, arg->loc); succ = block_append(p, succ, node); @@ -12244,14 +13069,6 @@ rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split) p->do_split = split; } -void -rb_parser_warn_location(VALUE vparser, int warn) -{ - struct parser_params *p; - TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - p->warn_location = warn; -} - static NODE * parser_append_options(struct parser_params *p, NODE *node) { @@ -12267,8 +13084,10 @@ parser_append_options(struct parser_params *p, NODE *node) if (p->do_loop) { if (p->do_split) { - NODE *args = NEW_LIST(NEW_GVAR(rb_intern("$;"), LOC), LOC); - NODE *split = NEW_GASGN(rb_intern("$F"), + ID ifs = rb_intern("$;"); + ID fields = rb_intern("$F"); + NODE *args = NEW_LIST(NEW_GVAR(ifs, LOC), LOC); + NODE *split = NEW_GASGN(fields, NEW_CALL(NEW_GVAR(idLASTLINE, LOC), rb_intern("split"), args, LOC), LOC); @@ -12297,10 +13116,7 @@ rb_init_parse(void) static ID internal_id(struct parser_params *p) { - const ID max_id = RB_ID_SERIAL_MAX & ~0xffff; - ID id = (ID)vtable_size(p->lvtbl->args) + (ID)vtable_size(p->lvtbl->vars); - id = max_id - id; - return ID_STATIC_SYM | ID_INTERNAL | (id << ID_SCOPE_SHIFT); + return rb_make_temporary_id(vtable_size(p->lvtbl->args) + vtable_size(p->lvtbl->vars)); } #endif /* !RIPPER */ @@ -12320,7 +13136,7 @@ parser_initialize(struct parser_params *p) p->error_buffer = Qfalse; #endif p->debug_buffer = Qnil; - p->debug_output = rb_stdout; + p->debug_output = rb_ractor_stdout(); p->enc = rb_utf8_encoding(); } @@ -12441,6 +13257,15 @@ rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main p->parent_iseq = base; return vparser; } + +void +rb_parser_keep_script_lines(VALUE vparser) +{ + struct parser_params *p; + + TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); + p->keep_script_lines = 1; +} #endif #ifdef RIPPER @@ -12469,7 +13294,7 @@ ripper_error_p(VALUE vparser) struct parser_params *p; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - return p->error_p ? Qtrue : Qfalse; + return RBOOL(p->error_p); } #endif @@ -12485,7 +13310,7 @@ rb_parser_end_seen_p(VALUE vparser) struct parser_params *p; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - return p->ruby__end__seen ? Qtrue : Qfalse; + return RBOOL(p->ruby__end__seen); } /* @@ -12516,7 +13341,7 @@ rb_parser_get_yydebug(VALUE self) struct parser_params *p; TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p); - return p->debug ? Qtrue : Qfalse; + return RBOOL(p->debug); } #endif @@ -12623,12 +13448,10 @@ rb_parser_free(struct parser_params *p, void *ptr) while ((n = *prev) != NULL) { if (n->ptr == ptr) { *prev = n->next; - rb_gc_force_recycle((VALUE)n); break; } prev = &n->next; } - xfree(ptr); } #endif @@ -12682,7 +13505,6 @@ count_char(const char *str, int c) RUBY_FUNC_EXPORTED size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr) { - YYUSE(p); if (*yystr == '"') { size_t yyn = 0, bquote = 0; const char *yyp = yystr; @@ -12768,7 +13590,7 @@ ripper_validate_object(VALUE self, VALUE x) case T_RATIONAL: break; case T_NODE: - if (nd_type((NODE *)x) != NODE_RIPPER) { + if (!nd_type_p((NODE *)x, NODE_RIPPER)) { rb_raise(rb_eArgError, "NODE given: %p", (void *)x); } x = ((NODE *)x)->nd_rval; @@ -12857,7 +13679,7 @@ ripper_get_id(VALUE v) NODE *nd; if (!RB_TYPE_P(v, T_NODE)) return 0; nd = (NODE *)v; - if (nd_type(nd) != NODE_RIPPER) return 0; + if (!nd_type_p(nd, NODE_RIPPER)) return 0; return nd->nd_vid; } @@ -12868,7 +13690,7 @@ ripper_get_value(VALUE v) if (v == Qundef) return Qnil; if (!RB_TYPE_P(v, T_NODE)) return v; nd = (NODE *)v; - if (nd_type(nd) != NODE_RIPPER) return Qnil; + if (!nd_type_p(nd, NODE_RIPPER)) return Qnil; return nd->nd_rval; } diff --git a/ruby/prelude.rb b/ruby/prelude.rb index be249af75..b1e477a3e 100644 --- a/ruby/prelude.rb +++ b/ruby/prelude.rb @@ -1,18 +1,3 @@ -class << Thread - # call-seq: - # Thread.exclusive { block } -> obj - # - # Wraps the block in a single, VM-global Mutex.synchronize, returning the - # value of the block. A thread executing inside the exclusive section will - # only block other threads which also use the Thread.exclusive mechanism. - def exclusive(&block) end if false - mutex = Mutex.new # :nodoc: - define_method(:exclusive) do |&block| - warn "Thread.exclusive is deprecated, use Thread::Mutex", uplevel: 1 - mutex.synchronize(&block) - end -end - class Binding # :nodoc: def irb diff --git a/ruby/prelude.rbinc b/ruby/prelude.rbinc index 005f2a1bf..360136aff 100644 --- a/ruby/prelude.rbinc +++ b/ruby/prelude.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with prelude.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_prelude(void) +void Init_builtin_prelude(void) { // table definition static const struct rb_builtin_function prelude_table[] = { diff --git a/ruby/probes.d b/ruby/probes.d index 57a3d762b..0762a2d25 100644 --- a/ruby/probes.d +++ b/ruby/probes.d @@ -214,17 +214,6 @@ provider ruby { Fired at the end of a sweep phase. */ probe gc__sweep__end(); - - /* - ruby:::method-cache-clear(class, filename, lineno); - - This probe is fired when the method cache is cleared. - - * `class` the name of the class or "global" (a string) - * `filename` the file name where the cache is _being cleared_ (a string) - * `lineno` the line number where the cache is _being cleared_ (an int) - */ - probe method__cache__clear(const char *class, const char *filename, int lineno); }; #pragma D attributes Stable/Evolving/Common provider ruby provider diff --git a/ruby/probes_helper.h b/ruby/probes_helper.h index 115c78d46..d2d0ebb6e 100644 --- a/ruby/probes_helper.h +++ b/ruby/probes_helper.h @@ -12,7 +12,9 @@ struct ruby_dtrace_method_hook_args { volatile VALUE name; }; +MJIT_SYMBOL_EXPORT_BEGIN NOINLINE(int rb_dtrace_setup(rb_execution_context_t *, VALUE, ID, struct ruby_dtrace_method_hook_args *)); +MJIT_SYMBOL_EXPORT_END #define RUBY_DTRACE_METHOD_HOOK(name, ec, klazz, id) \ do { \ diff --git a/ruby/proc.c b/ruby/proc.c index deffe1fc0..d075b7382 100644 --- a/ruby/proc.c +++ b/ruby/proc.c @@ -10,14 +10,18 @@ **********************************************************************/ #include "eval_intern.h" -#include "internal.h" #include "gc.h" -#include "vm_core.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/symbol.h" +#include "method.h" #include "iseq.h" - -/* Proc.new with no block will raise an exception in the future - * versions */ -#define PROC_NEW_REQUIRES_BLOCK 0 +#include "vm_core.h" +#include "yjit.h" #if !defined(__GNUC__) || __GNUC__ < 5 || defined(__MINGW32__) # define NO_CLOBBERED(v) (*(volatile VALUE *)&(v)) @@ -46,6 +50,7 @@ VALUE rb_cProc; static rb_block_call_func bmcall; static int method_arity(VALUE); static int method_min_max_arity(VALUE, int *max); +static VALUE proc_binding(VALUE self); #define attached id__attached__ @@ -53,6 +58,23 @@ static int method_min_max_arity(VALUE, int *max); #define IS_METHOD_PROC_IFUNC(ifunc) ((ifunc)->func == bmcall) +/* :FIXME: The way procs are cloned has been historically different from the + * way everything else are. @shyouhei is not sure for the intention though. + */ +#undef CLONESETUP +static inline void +CLONESETUP(VALUE clone, VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); + RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(clone)); + + const VALUE flags = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1 | RUBY_FL_FINALIZE; + rb_obj_setup(clone, rb_singleton_class_clone(obj), + RB_FL_TEST_RAW(obj, ~flags)); + rb_singleton_class_attached(RBASIC_CLASS(clone), clone); + if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(clone, obj); +} + static void block_mark(const struct rb_block *block) { @@ -61,18 +83,18 @@ block_mark(const struct rb_block *block) case block_type_ifunc: { const struct rb_captured_block *captured = &block->as.captured; - RUBY_MARK_NO_PIN_UNLESS_NULL(captured->self); - RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)captured->code.val); + RUBY_MARK_MOVABLE_UNLESS_NULL(captured->self); + RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)captured->code.val); if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) { - RUBY_MARK_NO_PIN_UNLESS_NULL(VM_ENV_ENVVAL(captured->ep)); + rb_gc_mark(VM_ENV_ENVVAL(captured->ep)); } } break; case block_type_symbol: - RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.symbol); + RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.symbol); break; case block_type_proc: - RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.proc); + RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.proc); break; } } @@ -87,9 +109,6 @@ block_compact(struct rb_block *block) struct rb_captured_block *captured = &block->as.captured; captured->self = rb_gc_location(captured->self); captured->code.val = rb_gc_location(captured->code.val); - if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) { - UPDATE_REFERENCE(captured->ep[VM_ENV_DATA_INDEX_ENV]); - } } break; case block_type_symbol: @@ -151,12 +170,7 @@ rb_proc_alloc(VALUE klass) VALUE rb_obj_is_proc(VALUE proc) { - if (rb_typeddata_is_kind_of(proc, &proc_data_type)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_typeddata_is_kind_of(proc, &proc_data_type)); } /* :nodoc: */ @@ -277,7 +291,7 @@ rb_proc_lambda_p(VALUE procval) rb_proc_t *proc; GetProcPtr(procval, proc); - return proc->is_lambda ? Qtrue : Qfalse; + return RBOOL(proc->is_lambda); } /* Binding */ @@ -333,6 +347,9 @@ rb_binding_alloc(VALUE klass) VALUE obj; rb_binding_t *bind; obj = TypedData_Make_Struct(klass, rb_binding_t, &ruby_binding_data_type, bind); +#if YJIT_STATS + rb_yjit_collect_binding_alloc(); +#endif return obj; } @@ -421,7 +438,11 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid) const rb_env_t *env = *envp; do { if (!VM_ENV_FLAGS(env->ep, VM_FRAME_FLAG_CFRAME)) { - const rb_iseq_t *iseq = env->iseq; + if (VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ISOLATED)) { + return NULL; + } + + const rb_iseq_t *iseq = env->iseq; unsigned int i; VM_ASSERT(rb_obj_is_iseq((VALUE)iseq)); @@ -539,14 +560,15 @@ bind_local_variable_get(VALUE bindval, VALUE sym) GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); - if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) { - sym = ID2SYM(lid); - undefined: - rb_name_err_raise("local variable `%1$s' is not defined for %2$s", - bindval, sym); + if ((ptr = get_local_variable_ptr(&env, lid)) != NULL) { + return *ptr; } - return *ptr; + sym = ID2SYM(lid); + undefined: + rb_name_err_raise("local variable `%1$s' is not defined for %2$s", + bindval, sym); + UNREACHABLE_RETURN(Qundef); } /* @@ -592,6 +614,10 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val) env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); } +#if YJIT_STATS + rb_yjit_collect_binding_set(); +#endif + RB_OBJ_WRITE(env, ptr, val); return val; @@ -625,7 +651,7 @@ bind_local_variable_defined_p(VALUE bindval, VALUE sym) GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); - return get_local_variable_ptr(&env, lid) ? Qtrue : Qfalse; + return RBOOL(get_local_variable_ptr(&env, lid)); } /* @@ -661,7 +687,7 @@ bind_location(VALUE bindval) } static VALUE -cfunc_proc_new(VALUE klass, VALUE ifunc, int8_t is_lambda) +cfunc_proc_new(VALUE klass, VALUE ifunc) { rb_proc_t *proc; cfunc_proc_t *sproc; @@ -679,7 +705,7 @@ cfunc_proc_new(VALUE klass, VALUE ifunc, int8_t is_lambda) /* self? */ RB_OBJ_WRITE(procval, &proc->block.as.captured.code.ifunc, ifunc); - proc->is_lambda = is_lambda; + proc->is_lambda = TRUE; return procval; } @@ -691,6 +717,7 @@ sym_proc_new(VALUE klass, VALUE sym) GetProcPtr(procval, proc); vm_block_type_set(&proc->block, block_type_symbol); + proc->is_lambda = TRUE; RB_OBJ_WRITE(procval, &proc->block.as.symbol, sym); return procval; } @@ -721,21 +748,22 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m } arity.argc.min = min_argc; arity.argc.max = max_argc; - return IFUNC_NEW(func, data, arity.packed); + VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, 0); + return (struct vm_ifunc *)ret; } MJIT_FUNC_EXPORTED VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val) { struct vm_ifunc *ifunc = rb_vm_ifunc_proc_new(func, (void *)val); - return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 0); + return cfunc_proc_new(rb_cProc, (VALUE)ifunc); } -VALUE +MJIT_FUNC_EXPORTED VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc) { struct vm_ifunc *ifunc = rb_vm_ifunc_new(func, (void *)val, min_argc, max_argc); - return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 1); + return cfunc_proc_new(rb_cProc, (VALUE)ifunc); } static const char proc_without_block[] = "tried to create Proc object without a block"; @@ -749,25 +777,7 @@ proc_new(VALUE klass, int8_t is_lambda, int8_t kernel) VALUE block_handler; if ((block_handler = rb_vm_frame_block_handler(cfp)) == VM_BLOCK_HANDLER_NONE) { -#if !PROC_NEW_REQUIRES_BLOCK - cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - - if ((block_handler = rb_vm_frame_block_handler(cfp)) != VM_BLOCK_HANDLER_NONE) { - if (is_lambda) { - rb_raise(rb_eArgError, proc_without_block); - } - else { - const char *name = kernel ? "Kernel#proc" : "Proc.new"; - rb_warn_deprecated("Capturing the given block using %s", - "`&block`", name); - } - } -#else - if (0); -#endif - else { - rb_raise(rb_eArgError, proc_without_block); - } + rb_raise(rb_eArgError, proc_without_block); } /* block is in cf */ @@ -810,18 +820,15 @@ proc_new(VALUE klass, int8_t is_lambda, int8_t kernel) /* * call-seq: * Proc.new {|...| block } -> a_proc - * Proc.new -> a_proc * - * Creates a new Proc object, bound to the current context. Proc::new - * may be called without a block only within a method with an - * attached block, in which case that block is converted to the Proc - * object. + * Creates a new Proc object, bound to the current context. * - * def proc_from - * Proc.new - * end - * proc = proc_from { "hello" } + * proc = Proc.new { "hello" } * proc.call #=> "hello" + * + * Raises ArgumentError if called without a block. + * + * Proc.new #=> ArgumentError */ static VALUE @@ -858,6 +865,34 @@ rb_block_lambda(void) return proc_new(rb_cProc, TRUE, FALSE); } +static void +f_lambda_warn(void) +{ + rb_control_frame_t *cfp = GET_EC()->cfp; + VALUE block_handler = rb_vm_frame_block_handler(cfp); + + if (block_handler != VM_BLOCK_HANDLER_NONE) { + switch (vm_block_handler_type(block_handler)) { + case block_handler_type_iseq: + if (RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)->ep == VM_BH_TO_ISEQ_BLOCK(block_handler)->ep) { + return; + } + break; + case block_handler_type_symbol: + return; + case block_handler_type_proc: + if (rb_proc_lambda_p(VM_BH_TO_PROC(block_handler))) { + return; + } + break; + case block_handler_type_ifunc: + break; + } + } + + rb_warn_deprecated("lambda without a literal block", "the proc without lambda"); +} + /* * call-seq: * lambda { |...| block } -> a_proc @@ -869,6 +904,7 @@ rb_block_lambda(void) static VALUE f_lambda(VALUE _) { + f_lambda_warn(); return rb_block_lambda(); } @@ -949,14 +985,11 @@ rb_proc_call_kw(VALUE self, VALUE args, int kw_splat) { VALUE vret; rb_proc_t *proc; - VALUE v; int argc = check_argc(RARRAY_LEN(args)); const VALUE *argv = RARRAY_CONST_PTR(args); GetProcPtr(self, proc); - v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); vret = rb_vm_invoke_proc(GET_EC(), proc, argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE); - rb_free_tmp_buffer(&v); RB_GC_GUARD(self); RB_GC_GUARD(args); return vret; @@ -965,15 +998,7 @@ rb_proc_call_kw(VALUE self, VALUE args, int kw_splat) VALUE rb_proc_call(VALUE self, VALUE args) { - VALUE vret; - rb_proc_t *proc; - GetProcPtr(self, proc); - vret = rb_vm_invoke_proc(GET_EC(), proc, - check_argc(RARRAY_LEN(args)), RARRAY_CONST_PTR(args), - RB_NO_KEYWORDS, VM_BLOCK_HANDLER_NONE); - RB_GC_GUARD(self); - RB_GC_GUARD(args); - return vret; + return rb_proc_call_kw(self, args, RB_NO_KEYWORDS); } static VALUE @@ -988,10 +1013,8 @@ rb_proc_call_with_block_kw(VALUE self, int argc, const VALUE *argv, VALUE passed rb_execution_context_t *ec = GET_EC(); VALUE vret; rb_proc_t *proc; - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); GetProcPtr(self, proc); vret = rb_vm_invoke_proc(ec, proc, argc, argv, kw_splat, proc_to_block_handler(passed_procval)); - rb_free_tmp_buffer(&v); RB_GC_GUARD(self); return vret; } @@ -999,13 +1022,7 @@ rb_proc_call_with_block_kw(VALUE self, int argc, const VALUE *argv, VALUE passed VALUE rb_proc_call_with_block(VALUE self, int argc, const VALUE *argv, VALUE passed_procval) { - rb_execution_context_t *ec = GET_EC(); - VALUE vret; - rb_proc_t *proc; - GetProcPtr(self, proc); - vret = rb_vm_invoke_proc(ec, proc, argc, argv, RB_NO_KEYWORDS, proc_to_block_handler(passed_procval)); - RB_GC_GUARD(self); - return vret; + return rb_proc_call_with_block_kw(self, argc, argv, passed_procval, RB_NO_KEYWORDS); } @@ -1088,7 +1105,8 @@ rb_vm_block_min_max_arity(const struct rb_block *block, int *max) return ifunc->argc.min; } case block_type_symbol: - break; + *max = UNLIMITED_ARGUMENTS; + return 1; } *max = UNLIMITED_ARGUMENTS; return 0; @@ -1140,6 +1158,41 @@ block_setup(struct rb_block *block, VALUE block_handler) } } +int +rb_block_pair_yield_optimizable(void) +{ + int min, max; + const rb_execution_context_t *ec = GET_EC(); + rb_control_frame_t *cfp = ec->cfp; + VALUE block_handler = rb_vm_frame_block_handler(cfp); + struct rb_block block; + + if (block_handler == VM_BLOCK_HANDLER_NONE) { + rb_raise(rb_eArgError, "no block given"); + } + + block_setup(&block, block_handler); + min = rb_vm_block_min_max_arity(&block, &max); + + switch (vm_block_type(&block)) { + case block_handler_type_symbol: + return 0; + + case block_handler_type_proc: + { + VALUE procval = block_handler; + rb_proc_t *proc; + GetProcPtr(procval, proc); + if (proc->is_lambda) return 0; + if (min != max) return 0; + return min > 1; + } + + default: + return min > 1; + } +} + int rb_block_arity(void) { @@ -1166,7 +1219,6 @@ rb_block_arity(void) rb_proc_t *proc; GetProcPtr(procval, proc); return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1; - /* fall through */ } default: @@ -1207,7 +1259,7 @@ rb_proc_get_iseq(VALUE self, int *is_proc) return rb_proc_get_iseq(block->as.proc, is_proc); case block_type_ifunc: { - const struct vm_ifunc *ifunc = block->as.captured.code.ifunc; + const struct vm_ifunc *ifunc = block->as.captured.code.ifunc; if (IS_METHOD_PROC_IFUNC(ifunc)) { /* method(:foo).to_proc */ if (is_proc) *is_proc = 0; @@ -1225,6 +1277,89 @@ rb_proc_get_iseq(VALUE self, int *is_proc) return NULL; } +/* call-seq: + * prc == other -> true or false + * prc.eql?(other) -> true or false + * + * Two procs are the same if, and only if, they were created from the same code block. + * + * def return_block(&block) + * block + * end + * + * def pass_block_twice(&block) + * [return_block(&block), return_block(&block)] + * end + * + * block1, block2 = pass_block_twice { puts 'test' } + * # Blocks might be instantiated into Proc's lazily, so they may, or may not, + * # be the same object. + * # But they are produced from the same code block, so they are equal + * block1 == block2 + * #=> true + * + * # Another Proc will never be equal, even if the code is the "same" + * block1 == proc { puts 'test' } + * #=> false + * + */ +static VALUE +proc_eq(VALUE self, VALUE other) +{ + const rb_proc_t *self_proc, *other_proc; + const struct rb_block *self_block, *other_block; + + if (rb_obj_class(self) != rb_obj_class(other)) { + return Qfalse; + } + + GetProcPtr(self, self_proc); + GetProcPtr(other, other_proc); + + if (self_proc->is_from_method != other_proc->is_from_method || + self_proc->is_lambda != other_proc->is_lambda) { + return Qfalse; + } + + self_block = &self_proc->block; + other_block = &other_proc->block; + + if (vm_block_type(self_block) != vm_block_type(other_block)) { + return Qfalse; + } + + switch (vm_block_type(self_block)) { + case block_type_iseq: + if (self_block->as.captured.ep != \ + other_block->as.captured.ep || + self_block->as.captured.code.iseq != \ + other_block->as.captured.code.iseq) { + return Qfalse; + } + break; + case block_type_ifunc: + if (self_block->as.captured.ep != \ + other_block->as.captured.ep || + self_block->as.captured.code.ifunc != \ + other_block->as.captured.code.ifunc) { + return Qfalse; + } + break; + case block_type_proc: + if (self_block->as.proc != other_block->as.proc) { + return Qfalse; + } + break; + case block_type_symbol: + if (self_block->as.symbol != other_block->as.symbol) { + return Qfalse; + } + break; + } + + return Qtrue; +} + static VALUE iseq_location(const rb_iseq_t *iseq) { @@ -1305,7 +1440,7 @@ rb_hash_proc(st_index_t hash, VALUE prc) GetProcPtr(prc, proc); hash = rb_hash_uint(hash, (st_index_t)proc->block.as.captured.code.val); hash = rb_hash_uint(hash, (st_index_t)proc->block.as.captured.self); - return rb_hash_uint(hash, (st_index_t)proc->block.as.captured.ep >> 16); + return rb_hash_uint(hash, (st_index_t)proc->block.as.captured.ep); } MJIT_FUNC_EXPORTED VALUE @@ -1458,12 +1593,7 @@ static const rb_data_type_t method_data_type = { VALUE rb_obj_is_method(VALUE m) { - if (rb_typeddata_is_kind_of(m, &method_data_type)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_typeddata_is_kind_of(m, &method_data_type)); } static int @@ -1527,6 +1657,7 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass, } if (visi == METHOD_VISI_UNDEF) { visi = METHOD_ENTRY_VISI(me); + RUBY_ASSERT(visi != METHOD_VISI_UNDEF); /* !UNDEFINED_METHOD_ENTRY_P(me) */ if (scope && (visi != METHOD_VISI_PUBLIC)) { if (!error) return Qnil; rb_print_inaccessible(klass, id, visi); @@ -1534,12 +1665,12 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass, } if (me->def->type == VM_METHOD_TYPE_ZSUPER) { if (me->defined_class) { - VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class)); + VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class)); id = me->def->original_id; me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass); } else { - VALUE klass = RCLASS_SUPER(me->owner); + VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->owner)); id = me->def->original_id; me = rb_method_entry_without_refinements(klass, id, &iclass); } @@ -1564,20 +1695,26 @@ mnew_from_me(const rb_method_entry_t *me, VALUE klass, VALUE iclass, } static VALUE -mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) +mnew_callable(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) { const rb_method_entry_t *me; VALUE iclass = Qnil; - if (obj == Qundef) { /* UnboundMethod */ - me = rb_method_entry_with_refinements(klass, id, &iclass); - } - else { - me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass); - } + ASSUME(obj != Qundef); + me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass); return mnew_from_me(me, klass, iclass, obj, id, mclass, scope); } +static VALUE +mnew_unbound(VALUE klass, ID id, VALUE mclass, int scope) +{ + const rb_method_entry_t *me; + VALUE iclass = Qnil; + + me = rb_method_entry_with_refinements(klass, id, &iclass); + return mnew_from_me(me, klass, iclass, Qundef, id, mclass, scope); +} + static inline VALUE method_entry_defined_class(const rb_method_entry_t *me) { @@ -1619,8 +1756,8 @@ method_entry_defined_class(const rb_method_entry_t *me) * meth == other_meth -> true or false * * Two method objects are equal if they are bound to the same - * object and refer to the same method definition and their owners are the - * same class or module. + * object and refer to the same method definition and the classes + * defining the methods are the same class or module. */ static VALUE @@ -1779,7 +1916,7 @@ rb_method_name_error(VALUE klass, VALUE str) { #define MSG(s) rb_fstring_lit("undefined method `%1$s' for"s" `%2$s'") VALUE c = klass; - VALUE s; + VALUE s = Qundef; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_ivar_get(klass, attached); @@ -1788,15 +1925,15 @@ rb_method_name_error(VALUE klass, VALUE str) case T_MODULE: case T_CLASS: c = obj; - s = MSG(""); + break; + default: + break; } - goto normal_class; } else if (RB_TYPE_P(c, T_MODULE)) { s = MSG(" module"); } - else { - normal_class: + if (s == Qundef) { s = MSG(" class"); } rb_name_err_raise_str(s, c, str); @@ -1815,7 +1952,7 @@ obj_method(VALUE obj, VALUE vid, int scope) if (m) return m; rb_method_name_error(klass, vid); } - return mnew(klass, obj, id, mclass, scope); + return mnew_callable(klass, obj, id, mclass, scope); } /* @@ -1903,27 +2040,39 @@ rb_obj_public_method(VALUE obj, VALUE vid) VALUE rb_obj_singleton_method(VALUE obj, VALUE vid) { - const rb_method_entry_t *me; VALUE klass = rb_singleton_class_get(obj); ID id = rb_check_id(&vid); - if (NIL_P(klass) || NIL_P(klass = RCLASS_ORIGIN(klass))) { - undef: - rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'", - obj, vid); + if (NIL_P(klass)) { + /* goto undef; */ } - if (!id) { + else if (NIL_P(klass = RCLASS_ORIGIN(klass))) { + /* goto undef; */ + } + else if (! id) { VALUE m = mnew_missing_by_name(klass, obj, &vid, FALSE, rb_cMethod); if (m) return m; - goto undef; + /* else goto undef; */ } - me = rb_method_entry_at(klass, id); - if (UNDEFINED_METHOD_ENTRY_P(me) || - UNDEFINED_REFINED_METHOD_P(me->def)) { - vid = ID2SYM(id); - goto undef; + else { + const rb_method_entry_t *me = rb_method_entry_at(klass, id); + vid = ID2SYM(id); + + if (UNDEFINED_METHOD_ENTRY_P(me)) { + /* goto undef; */ + } + else if (UNDEFINED_REFINED_METHOD_P(me->def)) { + /* goto undef; */ + } + else { + return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE); + } } - return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE); + + /* undef: */ + rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'", + obj, vid); + UNREACHABLE_RETURN(Qundef); } /* @@ -1964,7 +2113,7 @@ rb_mod_instance_method(VALUE mod, VALUE vid) if (!id) { rb_method_name_error(mod, vid); } - return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE); + return mnew_unbound(mod, id, rb_cUnboundMethod, FALSE); } /* @@ -1981,7 +2130,7 @@ rb_mod_public_instance_method(VALUE mod, VALUE vid) if (!id) { rb_method_name_error(mod, vid); } - return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE); + return mnew_unbound(mod, id, rb_cUnboundMethod, TRUE); } /* @@ -2043,25 +2192,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod) name = argv[0]; id = rb_check_id(&name); if (argc == 1) { -#if PROC_NEW_REQUIRES_BLOCK body = rb_block_lambda(); -#else - const rb_execution_context_t *ec = GET_EC(); - VALUE block_handler = rb_vm_frame_block_handler(ec->cfp); - if (block_handler == VM_BLOCK_HANDLER_NONE) rb_raise(rb_eArgError, proc_without_block); - - switch (vm_block_handler_type(block_handler)) { - case block_handler_type_proc: - body = VM_BH_TO_PROC(block_handler); - break; - case block_handler_type_symbol: - body = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler)); - break; - case block_handler_type_iseq: - case block_handler_type_ifunc: - body = rb_vm_make_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc); - } -#endif } else { body = argv[1]; @@ -2230,10 +2361,22 @@ method_clone(VALUE self) */ +/* Document-method: Method#[] + * + * call-seq: + * meth[args, ...] -> obj + * + * Invokes the meth with the specified arguments, returning the + * method's return value, like #call. + * + * m = 12.method("+") + * m[3] #=> 15 + * m[20] #=> 32 + */ + /* * call-seq: * meth.call(args, ...) -> obj - * meth[args, ...] -> obj * * Invokes the meth with the specified arguments, returning the * method's return value. @@ -2355,16 +2498,16 @@ rb_method_call_with_block(int argc, const VALUE *argv, VALUE method, VALUE passe */ static void -convert_umethod_to_method_components(VALUE method, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out) +convert_umethod_to_method_components(const struct METHOD *data, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out) { - struct METHOD *data; - - TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - VALUE methclass = data->me->owner; VALUE iclass = data->me->defined_class; VALUE klass = CLASS_OF(recv); + if (RB_TYPE_P(methclass, T_MODULE)) { + VALUE refined_class = rb_refinement_module_get_refined_class(methclass); + if (!NIL_P(refined_class)) methclass = refined_class; + } if (!RB_TYPE_P(methclass, T_MODULE) && methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) { if (FL_TEST(methclass, FL_SINGLETON)) { @@ -2437,7 +2580,9 @@ umethod_bind(VALUE method, VALUE recv) { VALUE methclass, klass, iclass; const rb_method_entry_t *me; - convert_umethod_to_method_components(method, recv, &methclass, &klass, &iclass, &me); + const struct METHOD *data; + TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); + convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me); struct METHOD *bound; method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound); @@ -2465,15 +2610,25 @@ umethod_bind_call(int argc, VALUE *argv, VALUE method) argc--; argv++; - VALUE methclass, klass, iclass; - const rb_method_entry_t *me; - convert_umethod_to_method_components(method, recv, &methclass, &klass, &iclass, &me); - struct METHOD bound = { recv, klass, 0, me }; - VALUE passed_procval = rb_block_given_p() ? rb_block_proc() : Qnil; - rb_execution_context_t *ec = GET_EC(); - return call_method_data(ec, &bound, argc, argv, passed_procval, RB_PASS_CALLED_KEYWORDS); + + const struct METHOD *data; + TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); + + const rb_callable_method_entry_t *cme = rb_callable_method_entry(CLASS_OF(recv), data->me->called_id); + if (data->me == (const rb_method_entry_t *)cme) { + vm_passed_block_handler_set(ec, proc_to_block_handler(passed_procval)); + return rb_vm_call_kw(ec, recv, cme->called_id, argc, argv, cme, RB_PASS_CALLED_KEYWORDS); + } + else { + VALUE methclass, klass, iclass; + const rb_method_entry_t *me; + convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me); + struct METHOD bound = { recv, klass, 0, me }; + + return call_method_data(ec, &bound, argc, argv, passed_procval, RB_PASS_CALLED_KEYWORDS); + } } /* @@ -2482,10 +2637,8 @@ umethod_bind_call(int argc, VALUE *argv, VALUE method) * if there is no maximum. */ static int -rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max) +method_def_min_max_arity(const rb_method_definition_t *def, int *max) { - const rb_method_definition_t *def = me->def; - again: if (!def) return *max = 0; switch (def->type) { @@ -2516,7 +2669,7 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max) *max = UNLIMITED_ARGUMENTS; return 0; case VM_METHOD_TYPE_OPTIMIZED: { - switch (def->body.optimize_type) { + switch (def->body.optimized.type) { case OPTIMIZED_METHOD_TYPE_SEND: *max = UNLIMITED_ARGUMENTS; return 0; @@ -2526,6 +2679,12 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max) case OPTIMIZED_METHOD_TYPE_BLOCK_CALL: *max = UNLIMITED_ARGUMENTS; return 0; + case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: + *max = 0; + return 0; + case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: + *max = 1; + return 1; default: break; } @@ -2535,15 +2694,21 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max) *max = UNLIMITED_ARGUMENTS; return 0; } - rb_bug("rb_method_entry_min_max_arity: invalid method entry type (%d)", def->type); + rb_bug("method_def_min_max_arity: invalid method entry type (%d)", def->type); UNREACHABLE_RETURN(Qnil); } +static int +method_def_arity(const rb_method_definition_t *def) +{ + int max, min = method_def_min_max_arity(def, &max); + return min == max ? min : -min-1; +} + int rb_method_entry_arity(const rb_method_entry_t *me) { - int max, min = rb_method_entry_min_max_arity(me, &max); - return min == max ? min : -min-1; + return method_def_arity(me->def); } /* @@ -2625,7 +2790,7 @@ method_min_max_arity(VALUE method, int *max) const struct METHOD *data; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - return rb_method_entry_min_max_arity(data->me, max); + return method_def_min_max_arity(data->me->def, max); } int @@ -2642,6 +2807,21 @@ rb_obj_method_arity(VALUE obj, ID id) return rb_mod_method_arity(CLASS_OF(obj), id); } +VALUE +rb_callable_receiver(VALUE callable) +{ + if (rb_obj_is_proc(callable)) { + VALUE binding = proc_binding(callable); + return rb_funcall(binding, rb_intern("receiver"), 0); + } + else if (rb_obj_is_method(callable)) { + return method_receiver(callable); + } + else { + return Qundef; + } +} + const rb_method_definition_t * rb_method_def(VALUE method) { @@ -2730,6 +2910,69 @@ rb_method_location(VALUE method) return method_def_location(rb_method_def(method)); } +static const rb_method_definition_t * +vm_proc_method_def(VALUE procval) +{ + const rb_proc_t *proc; + const struct rb_block *block; + const struct vm_ifunc *ifunc; + + GetProcPtr(procval, proc); + block = &proc->block; + + if (vm_block_type(block) == block_type_ifunc && + IS_METHOD_PROC_IFUNC(ifunc = block->as.captured.code.ifunc)) { + return rb_method_def((VALUE)ifunc->data); + } + else { + return NULL; + } +} + +static VALUE +method_def_parameters(const rb_method_definition_t *def) +{ + const rb_iseq_t *iseq; + const rb_method_definition_t *bmethod_def; + + switch (def->type) { + case VM_METHOD_TYPE_ISEQ: + iseq = method_def_iseq(def); + return rb_iseq_parameters(iseq, 0); + case VM_METHOD_TYPE_BMETHOD: + if ((iseq = method_def_iseq(def)) != NULL) { + return rb_iseq_parameters(iseq, 0); + } + else if ((bmethod_def = vm_proc_method_def(def->body.bmethod.proc)) != NULL) { + return method_def_parameters(bmethod_def); + } + break; + + case VM_METHOD_TYPE_ALIAS: + return method_def_parameters(def->body.alias.original_me->def); + + case VM_METHOD_TYPE_OPTIMIZED: + if (def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET) { + VALUE param = rb_ary_new_from_args(2, ID2SYM(rb_intern("req")), ID2SYM(rb_intern("_"))); + return rb_ary_new_from_args(1, param); + } + break; + + case VM_METHOD_TYPE_CFUNC: + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + case VM_METHOD_TYPE_ZSUPER: + case VM_METHOD_TYPE_UNDEF: + case VM_METHOD_TYPE_NOTIMPLEMENTED: + case VM_METHOD_TYPE_MISSING: + case VM_METHOD_TYPE_REFINED: + break; + } + + return rb_unnamed_parameters(method_def_arity(def)); + +} + /* * call-seq: * meth.parameters -> array @@ -2752,11 +2995,7 @@ rb_method_location(VALUE method) static VALUE rb_method_parameters(VALUE method) { - const rb_iseq_t *iseq = rb_method_iseq(method); - if (!iseq) { - return rb_unnamed_parameters(method_arity(method)); - } - return rb_iseq_parameters(iseq, 0); + return method_def_parameters(rb_method_def(method)); } /* @@ -2847,9 +3086,12 @@ method_inspect(VALUE method) else { mklass = data->klass; if (FL_TEST(mklass, FL_SINGLETON)) { - do { - mklass = RCLASS_SUPER(mklass); - } while (RB_TYPE_P(mklass, T_ICLASS)); + VALUE v = rb_ivar_get(mklass, attached); + if (!(RB_TYPE_P(v, T_CLASS) || RB_TYPE_P(v, T_MODULE))) { + do { + mklass = RCLASS_SUPER(mklass); + } while (RB_TYPE_P(mklass, T_ICLASS)); + } } rb_str_buf_append(str, rb_inspect(mklass)); if (defined_class != mklass) { @@ -2925,7 +3167,12 @@ method_inspect(VALUE method) } } else if (kind == keyrest) { - rb_str_catf(str, "**%"PRIsVALUE, name); + if (name != ID2SYM(idPow)) { + rb_str_catf(str, "**%"PRIsVALUE, name); + } + else if (i > 0) { + rb_str_set_len(str, RSTRING_LEN(str) - 2); + } } else if (kind == block) { if (name == ID2SYM('&')) { @@ -2964,18 +3211,6 @@ method_inspect(VALUE method) return str; } -static VALUE -mproc(VALUE method) -{ - return rb_funcallv(rb_mRubyVMFrozenCore, idProc, 0, 0); -} - -static VALUE -mlambda(VALUE method) -{ - return rb_funcallv(rb_mRubyVMFrozenCore, idLambda, 0, 0); -} - static VALUE bmcall(RB_BLOCK_CALL_FUNC_ARGLIST(args, method)) { @@ -2987,7 +3222,7 @@ rb_proc_new( rb_block_call_func_t func, VALUE val) { - VALUE procval = rb_iterate(mproc, 0, func, val); + VALUE procval = rb_block_call(rb_mRubyVMFrozenCore, idProc, 0, 0, func, val); return procval; } @@ -3013,12 +3248,14 @@ method_to_proc(VALUE method) * end * end */ - procval = rb_iterate(mlambda, 0, bmcall, method); + procval = rb_block_call(rb_mRubyVMFrozenCore, idLambda, 0, 0, bmcall, method); GetProcPtr(procval, proc); proc->is_from_method = 1; return procval; } +extern VALUE rb_find_defined_class_by_owner(VALUE current_class, VALUE target_owner); + /* * call-seq: * meth.super_method -> method @@ -3038,14 +3275,66 @@ method_super_method(VALUE method) TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); iclass = data->iclass; if (!iclass) return Qnil; - super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass)); - mid = data->me->called_id; + if (data->me->def->type == VM_METHOD_TYPE_ALIAS && data->me->defined_class) { + super_class = RCLASS_SUPER(rb_find_defined_class_by_owner(data->me->defined_class, + data->me->def->body.alias.original_me->owner)); + mid = data->me->def->body.alias.original_me->def->original_id; + } + else { + super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass)); + mid = data->me->def->original_id; + } if (!super_class) return Qnil; me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(super_class, mid, &iclass); if (!me) return Qnil; return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE); } +/* + * call-seq: + * meth.public? -> true or false + * + * Returns whether the method is public. + */ + +static VALUE +method_public_p(VALUE method) +{ + const struct METHOD *data; + TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); + return RBOOL(METHOD_ENTRY_VISI(data->me) == METHOD_VISI_PUBLIC); +} + +/* + * call-seq: + * meth.protected? -> true or false + * + * Returns whether the method is protected. + */ + +static VALUE +method_protected_p(VALUE method) +{ + const struct METHOD *data; + TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); + return RBOOL(METHOD_ENTRY_VISI(data->me) == METHOD_VISI_PROTECTED); +} + +/* + * call-seq: + * meth.private? -> true or false + * + * Returns whether the method is private. + */ + +static VALUE +method_private_p(VALUE method) +{ + const struct METHOD *data; + TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); + return RBOOL(METHOD_ENTRY_VISI(data->me) == METHOD_VISI_PRIVATE); +} + /* * call-seq: * local_jump_error.exit_value -> obj @@ -3123,6 +3412,8 @@ proc_binding(VALUE self) GetProcPtr(self, proc); block = &proc->block; + if (proc->is_isolated) rb_raise(rb_eArgError, "Can't create Binding from isolated Proc"); + again: switch (vm_block_type(block)) { case block_type_iseq: @@ -3134,8 +3425,6 @@ proc_binding(VALUE self) GetProcPtr(block->as.proc, proc); block = &proc->block; goto again; - case block_type_symbol: - goto error; case block_type_ifunc: { const struct vm_ifunc *ifunc = block->as.captured.code.ifunc; @@ -3152,12 +3441,11 @@ proc_binding(VALUE self) RB_OBJ_WRITE(env, &env->iseq, empty); break; } - else { - error: - rb_raise(rb_eArgError, "Can't create Binding from C level Proc"); - return Qnil; - } } + /* FALLTHROUGH */ + case block_type_symbol: + rb_raise(rb_eArgError, "Can't create Binding from C level Proc"); + UNREACHABLE_RETURN(Qnil); } bindval = rb_binding_alloc(rb_cBinding); @@ -3387,8 +3675,14 @@ rb_proc_compose_to_left(VALUE self, VALUE g) procs[1] = g; args = rb_ary_tmp_new_from_values(0, 2, procs); - GetProcPtr(self, procp); - is_lambda = procp->is_lambda; + if (rb_obj_is_proc(g)) { + GetProcPtr(g, procp); + is_lambda = procp->is_lambda; + } + else { + VM_ASSERT(rb_obj_is_method(g) || rb_obj_respond_to(g, idCall, TRUE)); + is_lambda = 1; + } proc = rb_proc_new(compose, args); GetProcPtr(proc, procp); @@ -3479,8 +3773,8 @@ rb_method_compose_to_left(VALUE self, VALUE g) * meth >> g -> a_proc * * Returns a proc that is the composition of this method and the given g. - * The returned proc takes a variable number of arguments, calls g with them - * then calls this method with the result. + * The returned proc takes a variable number of arguments, calls this method + * with them then calls g with the result. * * def f(x) * x * x @@ -3659,7 +3953,8 @@ proc_ruby2_keywords(VALUE procval) * * lambda1 = lambda {|x| x**2 } * - * * Use the Lambda literal syntax (also constructs a proc with lambda semantics): + * * Use the {Lambda proc literal}[doc/syntax/literals_rdoc.html#label-Lambda+Proc+Literals] syntax + * (also constructs a proc with lambda semantics): * * lambda2 = ->(x) { x**2 } * @@ -3759,7 +4054,7 @@ proc_ruby2_keywords(VALUE procval) * * p = proc {|x, y| x } * l = lambda {|x, y| x } - * [[1, 2], [3, 4]].map(&p) #=> [1, 2] + * [[1, 2], [3, 4]].map(&p) #=> [1, 3] * [[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2) * * The only exception is dynamic method definition: even if defined by @@ -3791,7 +4086,7 @@ proc_ruby2_keywords(VALUE procval) * == Conversion of other objects to procs * * Any object that implements the +to_proc+ method can be converted into - * a proc by the & operator, and therefore con be + * a proc by the & operator, and therefore can be * consumed by iterators. * @@ -3907,14 +4202,10 @@ Init_Proc(void) rb_undef_alloc_func(rb_cProc); rb_define_singleton_method(rb_cProc, "new", rb_proc_s_new, -1); - rb_add_method(rb_cProc, idCall, VM_METHOD_TYPE_OPTIMIZED, - (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC); - rb_add_method(rb_cProc, rb_intern("[]"), VM_METHOD_TYPE_OPTIMIZED, - (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC); - rb_add_method(rb_cProc, rb_intern("==="), VM_METHOD_TYPE_OPTIMIZED, - (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC); - rb_add_method(rb_cProc, rb_intern("yield"), VM_METHOD_TYPE_OPTIMIZED, - (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC); + rb_add_method_optimized(rb_cProc, idCall, OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC); + rb_add_method_optimized(rb_cProc, rb_intern("[]"), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC); + rb_add_method_optimized(rb_cProc, rb_intern("==="), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC); + rb_add_method_optimized(rb_cProc, rb_intern("yield"), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC); #if 0 /* for RDoc */ rb_define_method(rb_cProc, "call", proc_call, -1); @@ -3935,9 +4226,12 @@ Init_Proc(void) rb_define_method(rb_cProc, "curry", proc_curry, -1); rb_define_method(rb_cProc, "<<", proc_compose_to_left, 1); rb_define_method(rb_cProc, ">>", proc_compose_to_right, 1); + rb_define_method(rb_cProc, "==", proc_eq, 1); + rb_define_method(rb_cProc, "eql?", proc_eq, 1); rb_define_method(rb_cProc, "source_location", rb_proc_location, 0); rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0); rb_define_method(rb_cProc, "ruby2_keywords", proc_ruby2_keywords, 0); + // rb_define_method(rb_cProc, "isolate", rb_proc_isolate, 0); is not accepted. /* Exceptions */ rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError); @@ -3977,6 +4271,9 @@ Init_Proc(void) rb_define_method(rb_cMethod, "source_location", rb_method_location, 0); rb_define_method(rb_cMethod, "parameters", rb_method_parameters, 0); rb_define_method(rb_cMethod, "super_method", method_super_method, 0); + rb_define_method(rb_cMethod, "public?", method_public_p, 0); + rb_define_method(rb_cMethod, "protected?", method_protected_p, 0); + rb_define_method(rb_cMethod, "private?", method_private_p, 0); rb_define_method(rb_mKernel, "method", rb_obj_method, 1); rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1); rb_define_method(rb_mKernel, "singleton_method", rb_obj_singleton_method, 1); @@ -4000,6 +4297,9 @@ Init_Proc(void) rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0); rb_define_method(rb_cUnboundMethod, "parameters", rb_method_parameters, 0); rb_define_method(rb_cUnboundMethod, "super_method", method_super_method, 0); + rb_define_method(rb_cUnboundMethod, "public?", method_public_p, 0); + rb_define_method(rb_cUnboundMethod, "protected?", method_protected_p, 0); + rb_define_method(rb_cUnboundMethod, "private?", method_private_p, 0); /* Module#*_method */ rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1); diff --git a/ruby/process.c b/ruby/process.c index 3a1b21295..399f0d753 100644 --- a/ruby/process.c +++ b/ruby/process.c @@ -11,93 +11,118 @@ **********************************************************************/ -#include "ruby/config.h" -#include "ruby/io.h" -#include "internal.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "vm_core.h" -#include "hrtime.h" +#include "ruby/internal/config.h" -#include +#include "ruby/fiber/scheduler.h" + +#include #include #include +#include +#include +#include + #ifdef HAVE_STDLIB_H -#include +# include #endif + #ifdef HAVE_UNISTD_H -#include +# include #endif + #ifdef HAVE_FCNTL_H -#include +# include #endif + #ifdef HAVE_PROCESS_H -#include +# include #endif -#include -#include - #ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 +# define EXIT_SUCCESS 0 #endif + #ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 +# define EXIT_FAILURE 1 #endif #ifdef HAVE_SYS_WAIT_H # include #endif + #ifdef HAVE_SYS_RESOURCE_H # include #endif + #ifdef HAVE_VFORK_H # include #endif + #ifdef HAVE_SYS_PARAM_H # include #endif + #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif -#include "ruby/st.h" #include #ifdef HAVE_SYS_TIME_H -#include +# include #endif + #ifdef HAVE_SYS_TIMES_H -#include +# include #endif #ifdef HAVE_PWD_H -#include +# include #endif + #ifdef HAVE_GRP_H -#include +# include # ifdef __CYGWIN__ int initgroups(const char *, rb_gid_t); # endif #endif + #ifdef HAVE_SYS_ID_H -#include +# include #endif #ifdef __APPLE__ # include #endif +#include "dln.h" +#include "hrtime.h" +#include "internal.h" +#include "internal/bits.h" +#include "internal/dir.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/process.h" +#include "internal/thread.h" +#include "internal/variable.h" +#include "internal/warnings.h" +#include "mjit.h" +#include "ruby/io.h" +#include "ruby/st.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "vm_core.h" +#include "ruby/ractor.h" + /* define system APIs */ #ifdef _WIN32 #undef open #define open rb_w32_uopen #endif -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - #if defined(HAVE_TIMES) || defined(_WIN32) static VALUE rb_cProcessTms; #endif @@ -153,17 +178,48 @@ static void check_uid_switch(void); static void check_gid_switch(void); static int exec_async_signal_safe(const struct rb_execarg *, char *, size_t); +VALUE rb_envtbl(void); +VALUE rb_env_to_hash(void); + #if 1 #define p_uid_from_name p_uid_from_name #define p_gid_from_name p_gid_from_name #endif +#if defined(HAVE_UNISTD_H) +# if defined(HAVE_GETLOGIN_R) +# define USE_GETLOGIN_R 1 +# define GETLOGIN_R_SIZE_DEFAULT 0x100 +# define GETLOGIN_R_SIZE_LIMIT 0x1000 +# if defined(_SC_LOGIN_NAME_MAX) +# define GETLOGIN_R_SIZE_INIT sysconf(_SC_LOGIN_NAME_MAX) +# else +# define GETLOGIN_R_SIZE_INIT GETLOGIN_R_SIZE_DEFAULT +# endif +# elif defined(HAVE_GETLOGIN) +# define USE_GETLOGIN 1 +# endif +#endif + #if defined(HAVE_PWD_H) -# if defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX) +# if defined(HAVE_GETPWUID_R) +# define USE_GETPWUID_R 1 +# elif defined(HAVE_GETPWUID) +# define USE_GETPWUID 1 +# endif +# if defined(HAVE_GETPWNAM_R) # define USE_GETPWNAM_R 1 -# define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX) +# elif defined(HAVE_GETPWNAM) +# define USE_GETPWNAM 1 +# endif +# if defined(HAVE_GETPWNAM_R) || defined(HAVE_GETPWUID_R) # define GETPW_R_SIZE_DEFAULT 0x1000 # define GETPW_R_SIZE_LIMIT 0x10000 +# if defined(_SC_GETPW_R_SIZE_MAX) +# define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX) +# else +# define GETPW_R_SIZE_INIT GETPW_R_SIZE_DEFAULT +# endif # endif # ifdef USE_GETPWNAM_R # define PREPARE_GETPWNAM \ @@ -263,7 +319,7 @@ static ID id_pgroup; #ifdef _WIN32 static ID id_new_pgroup; #endif -static ID id_unsetenv_others, id_chdir, id_umask, id_close_others, id_ENV; +static ID id_unsetenv_others, id_chdir, id_umask, id_close_others; static ID id_nanosecond, id_microsecond, id_millisecond, id_second; static ID id_float_microsecond, id_float_millisecond, id_float_second; static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME; @@ -321,8 +377,6 @@ close_unless_reserved(int fd) /*#define DEBUG_REDIRECT*/ #if defined(DEBUG_REDIRECT) -#include - static void ttyprintf(const char *fmt, ...) { @@ -518,6 +572,29 @@ proc_get_ppid(VALUE _) static VALUE rb_cProcessStatus; +struct rb_process_status { + rb_pid_t pid; + int status; + int error; +}; + +static const rb_data_type_t rb_process_status_type = { + .wrap_struct_name = "Process::Status", + .function = { + .dfree = RUBY_DEFAULT_FREE, + }, + .data = NULL, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static VALUE +rb_process_status_allocate(VALUE klass) +{ + struct rb_process_status *data = NULL; + + return TypedData_Make_Struct(klass, struct rb_process_status, &rb_process_status_type, data); +} + VALUE rb_last_status_get(void) { @@ -545,13 +622,47 @@ proc_s_last_status(VALUE mod) return rb_last_status_get(); } +VALUE +rb_process_status_new(rb_pid_t pid, int status, int error) +{ + VALUE last_status = rb_process_status_allocate(rb_cProcessStatus); + + struct rb_process_status *data = RTYPEDDATA_DATA(last_status); + data->pid = pid; + data->status = status; + data->error = error; + + rb_obj_freeze(last_status); + return last_status; +} + +static VALUE +process_status_dump(VALUE status) +{ + VALUE dump = rb_class_new_instance(0, 0, rb_cObject); + struct rb_process_status *data = RTYPEDDATA_DATA(status); + if (data->pid) { + rb_ivar_set(dump, id_status, INT2NUM(data->status)); + rb_ivar_set(dump, id_pid, PIDT2NUM(data->pid)); + } + return dump; +} + +static VALUE +process_status_load(VALUE real_obj, VALUE load_obj) +{ + struct rb_process_status *data = rb_check_typeddata(real_obj, &rb_process_status_type); + VALUE status = rb_attr_get(load_obj, id_status); + VALUE pid = rb_attr_get(load_obj, id_pid); + data->pid = NIL_P(pid) ? 0 : NUM2PIDT(pid); + data->status = NIL_P(status) ? 0 : NUM2INT(status); + return real_obj; +} + void rb_last_status_set(int status, rb_pid_t pid) { - rb_thread_t *th = GET_THREAD(); - th->last_status = rb_obj_alloc(rb_cProcessStatus); - rb_ivar_set(th->last_status, id_status, INT2FIX(status)); - rb_ivar_set(th->last_status, id_pid, PIDT2NUM(pid)); + GET_THREAD()->last_status = rb_process_status_new(pid, status, 0); } void @@ -560,11 +671,25 @@ rb_last_status_clear(void) GET_THREAD()->last_status = Qnil; } +static rb_pid_t +pst_pid(VALUE pst) +{ + struct rb_process_status *data = RTYPEDDATA_DATA(pst); + return data->pid; +} + +static int +pst_status(VALUE pst) +{ + struct rb_process_status *data = RTYPEDDATA_DATA(pst); + return data->status; +} + /* * call-seq: * stat.to_i -> integer * - * Returns the bits in _stat_ as a Integer. Poking + * Returns the bits in _stat_ as an Integer. Poking * around in these bits is platform dependent. * * fork { exit 0xab } #=> 26566 @@ -573,12 +698,13 @@ rb_last_status_clear(void) */ static VALUE -pst_to_i(VALUE st) +pst_to_i(VALUE self) { - return rb_ivar_get(st, id_status); + int status = pst_status(self); + return RB_INT2NUM(status); } -#define PST2INT(st) NUM2INT(pst_to_i(st)) +#define PST2INT(st) pst_status(st) /* * call-seq: @@ -592,9 +718,10 @@ pst_to_i(VALUE st) */ static VALUE -pst_pid(VALUE st) +pst_pid_m(VALUE self) { - return rb_attr_get(st, id_pid); + rb_pid_t pid = pst_pid(self); + return PIDT2NUM(pid); } static VALUE pst_message_status(VALUE str, int status); @@ -659,7 +786,7 @@ pst_to_s(VALUE st) int status; VALUE str; - pid = NUM2PIDT(pst_pid(st)); + pid = pst_pid(st); status = PST2INT(st); str = rb_str_buf_new(0); @@ -684,13 +811,12 @@ pst_inspect(VALUE st) { rb_pid_t pid; int status; - VALUE vpid, str; + VALUE str; - vpid = pst_pid(st); - if (NIL_P(vpid)) { + pid = pst_pid(st); + if (!pid) { return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st))); } - pid = NUM2PIDT(vpid); status = PST2INT(st); str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st))); @@ -772,10 +898,7 @@ pst_wifstopped(VALUE st) { int status = PST2INT(st); - if (WIFSTOPPED(status)) - return Qtrue; - else - return Qfalse; + return RBOOL(WIFSTOPPED(status)); } @@ -811,10 +934,7 @@ pst_wifsignaled(VALUE st) { int status = PST2INT(st); - if (WIFSIGNALED(status)) - return Qtrue; - else - return Qfalse; + return RBOOL(WIFSIGNALED(status)); } @@ -852,10 +972,7 @@ pst_wifexited(VALUE st) { int status = PST2INT(st); - if (WIFEXITED(status)) - return Qtrue; - else - return Qfalse; + return RBOOL(WIFEXITED(status)); } @@ -903,7 +1020,7 @@ pst_success_p(VALUE st) if (!WIFEXITED(status)) return Qnil; - return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse; + return RBOOL(WEXITSTATUS(status) == EXIT_SUCCESS); } @@ -921,10 +1038,7 @@ pst_wcoredump(VALUE st) #ifdef WCOREDUMP int status = PST2INT(st); - if (WCOREDUMP(status)) - return Qtrue; - else - return Qfalse; + return RBOOL(WCOREDUMP(status)); #else return Qfalse; #endif @@ -955,10 +1069,6 @@ struct waitpid_state { int errnum; }; -void rb_native_mutex_lock(rb_nativethread_lock_t *); -void rb_native_mutex_unlock(rb_nativethread_lock_t *); -void rb_native_cond_signal(rb_nativethread_cond_t *); -void rb_native_cond_wait(rb_nativethread_cond_t *, rb_nativethread_lock_t *); int rb_sigwait_fd_get(const rb_thread_t *); void rb_sigwait_sleep(const rb_thread_t *, int fd, const rb_hrtime_t *); void rb_sigwait_fd_put(const rb_thread_t *, int fd); @@ -1053,6 +1163,8 @@ waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options) w->ret = 0; w->pid = pid; w->options = options; + w->errnum = 0; + w->status = 0; } static const rb_hrtime_t * @@ -1163,8 +1275,10 @@ waitpid_wait(struct waitpid_state *w) */ rb_native_mutex_lock(&vm->waitpid_lock); - if (w->pid > 0 || list_empty(&vm->waiting_pids)) + if (w->pid > 0 || list_empty(&vm->waiting_pids)) { w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG); + } + if (w->ret) { if (w->ret == -1) w->errnum = errno; } @@ -1213,35 +1327,120 @@ waitpid_no_SIGCHLD(struct waitpid_state *w) w->errnum = errno; } -rb_pid_t -rb_waitpid(rb_pid_t pid, int *st, int flags) +VALUE +rb_process_status_wait(rb_pid_t pid, int flags) { - struct waitpid_state w; + // We only enter the scheduler if we are "blocking": + if (!(flags & WNOHANG)) { + VALUE scheduler = rb_fiber_scheduler_current(); + VALUE result = rb_fiber_scheduler_process_wait(scheduler, pid, flags); + if (result != Qundef) return result; + } + + struct waitpid_state waitpid_state; - waitpid_state_init(&w, pid, flags); - w.ec = GET_EC(); + waitpid_state_init(&waitpid_state, pid, flags); + waitpid_state.ec = GET_EC(); if (WAITPID_USE_SIGCHLD) { - waitpid_wait(&w); + waitpid_wait(&waitpid_state); } else { - waitpid_no_SIGCHLD(&w); + waitpid_no_SIGCHLD(&waitpid_state); } - if (st) *st = w.status; - if (w.ret == -1) { - errno = w.errnum; + if (waitpid_state.ret == 0) return Qnil; + + if (waitpid_state.ret > 0 && ruby_nocldwait) { + waitpid_state.ret = -1; + waitpid_state.errnum = ECHILD; } - else if (w.ret > 0) { - if (ruby_nocldwait) { - w.ret = -1; - errno = ECHILD; - } - else { - rb_last_status_set(w.status, w.ret); - } + + return rb_process_status_new(waitpid_state.ret, waitpid_state.status, waitpid_state.errnum); +} + +/* + * call-seq: + * Process::Status.wait(pid=-1, flags=0) -> Process::Status + * + * Waits for a child process to exit and returns a Process::Status object + * containing information on that process. Which child it waits on + * depends on the value of _pid_: + * + * > 0:: Waits for the child whose process ID equals _pid_. + * + * 0:: Waits for any child whose process group ID equals that of the + * calling process. + * + * -1:: Waits for any child process (the default if no _pid_ is + * given). + * + * < -1:: Waits for any child whose process group ID equals the absolute + * value of _pid_. + * + * The _flags_ argument may be a logical or of the flag values + * Process::WNOHANG (do not block if no child available) + * or Process::WUNTRACED (return stopped children that + * haven't been reported). Not all flags are available on all + * platforms, but a flag value of zero will work on all platforms. + * + * Returns +nil+ if there are no child processes. + * Not available on all platforms. + * + * May invoke the scheduler hook _process_wait_. + * + * fork { exit 99 } #=> 27429 + * Process::Status.wait #=> pid 27429 exit 99 + * $? #=> nil + * + * pid = fork { sleep 3 } #=> 27440 + * Time.now #=> 2008-03-08 19:56:16 +0900 + * Process::Status.wait(pid, Process::WNOHANG) #=> nil + * Time.now #=> 2008-03-08 19:56:16 +0900 + * Process::Status.wait(pid, 0) #=> pid 27440 exit 99 + * Time.now #=> 2008-03-08 19:56:19 +0900 + * + * This is an EXPERIMENTAL FEATURE. + */ + +VALUE +rb_process_status_waitv(int argc, VALUE *argv, VALUE _) +{ + rb_check_arity(argc, 0, 2); + + rb_pid_t pid = -1; + int flags = 0; + + if (argc >= 1) { + pid = NUM2PIDT(argv[0]); } - return w.ret; + + if (argc >= 2) { + flags = RB_NUM2INT(argv[1]); + } + + return rb_process_status_wait(pid, flags); +} + +rb_pid_t +rb_waitpid(rb_pid_t pid, int *st, int flags) +{ + VALUE status = rb_process_status_wait(pid, flags); + if (NIL_P(status)) return 0; + + struct rb_process_status *data = RTYPEDDATA_DATA(status); + pid = data->pid; + + if (st) *st = data->status; + + if (pid == -1) { + errno = data->error; + } + else { + GET_THREAD()->last_status = status; + } + + return pid; } static VALUE @@ -1261,12 +1460,15 @@ proc_wait(int argc, VALUE *argv) flags = NUM2UINT(vflags); } } + if ((pid = rb_waitpid(pid, &status, flags)) < 0) rb_sys_fail(0); + if (pid == 0) { rb_last_status_clear(); return Qnil; } + return PIDT2NUM(pid); } @@ -1567,7 +1769,12 @@ after_exec(void) } #if defined HAVE_WORKING_FORK || defined HAVE_DAEMON -#define before_fork_ruby() before_exec() +static void +before_fork_ruby(void) +{ + before_exec(); +} + static void after_fork_ruby(void) { @@ -1576,8 +1783,6 @@ after_fork_ruby(void) } #endif -#include "dln.h" - #if defined(HAVE_WORKING_FORK) /* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/ @@ -1841,8 +2046,7 @@ check_exec_redirect_fd(VALUE v, int iskey) fd = fptr->fd; } else { - wrong: - rb_raise(rb_eArgError, "wrong exec redirect"); + goto wrong; } if (fd < 0) { rb_raise(rb_eArgError, "negative file descriptor"); @@ -1853,6 +2057,10 @@ check_exec_redirect_fd(VALUE v, int iskey) } #endif return INT2FIX(fd); + + wrong: + rb_raise(rb_eArgError, "wrong exec redirect"); + UNREACHABLE_RETURN(Qundef); } static VALUE @@ -1866,12 +2074,11 @@ check_exec_redirect1(VALUE ary, VALUE key, VALUE param) rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param))); } else { - int i, n=0; + int i; for (i = 0 ; i < RARRAY_LEN(key); i++) { VALUE v = RARRAY_AREF(key, i); VALUE fd = check_exec_redirect_fd(v, !NIL_P(param)); rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param))); - n++; } } return ary; @@ -1887,7 +2094,7 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp) switch (TYPE(val)) { case T_SYMBOL: - if (!(id = rb_check_id(&val))) goto wrong_symbol; + id = rb_check_id(&val); if (id == id_close) { param = Qnil; eargp->fd_close = check_exec_redirect1(eargp->fd_close, key, param); @@ -1905,7 +2112,6 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp) eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param); } else { - wrong_symbol: rb_raise(rb_eArgError, "wrong exec redirect symbol: %"PRIsVALUE, val); } @@ -2308,7 +2514,7 @@ check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg) k = StringValueCStr(key); if (strchr(k, '=')) - rb_raise(rb_eArgError, "environment name contains a equal : %s", k); + rb_raise(rb_eArgError, "environment name contains a equal : %"PRIsVALUE, key); if (!NIL_P(val)) StringValueCStr(val); @@ -2373,6 +2579,8 @@ check_hash(VALUE obj) case T_STRING: case T_ARRAY: return Qnil; + default: + break; } return rb_check_hash_type(obj); } @@ -2720,8 +2928,6 @@ rb_execarg_parent_start1(VALUE execarg_obj) int fd2; if (NIL_P(fd2v)) { struct open_struct open_data; - FilePathValue(vpath); - vpath = rb_str_encode_ospath(vpath); again: open_data.fname = vpath; open_data.oflags = flags; @@ -2764,8 +2970,7 @@ rb_execarg_parent_start1(VALUE execarg_obj) envtbl = rb_hash_new(); } else { - envtbl = rb_const_get(rb_cObject, id_ENV); - envtbl = rb_to_hash_type(envtbl); + envtbl = rb_env_to_hash(); } hide_obj(envtbl); if (envopts != Qfalse) { @@ -2914,6 +3119,8 @@ rb_f_exec(int argc, const VALUE *argv) UNREACHABLE_RETURN(Qnil); } +NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _)); + /* * call-seq: * exec([env,] command... [,options]) @@ -2932,14 +3139,15 @@ rb_f_exec(int argc, const VALUE *argv) * shell expansion before being executed. * * The standard shell always means "/bin/sh" on Unix-like systems, - * same as ENV["RUBYSHELL"] - * (or ENV["COMSPEC"] on Windows NT series), and similar. + * otherwise, ENV["RUBYSHELL"] or ENV["COMSPEC"] on + * Windows and similar. The command is passed as an argument to the + * "-c" switch to the shell, except in the case of +COMSPEC+. * * If the string from the first form (exec("command")) follows * these simple rules: * * * no meta characters - * * no shell reserved word and no special built-in + * * not starting with shell reserved word or special built-in * * Ruby invokes the command directly without shell * * You can force shell invocation by adding ";" to the string (because ";" is @@ -2990,7 +3198,8 @@ rb_f_exec(int argc, const VALUE *argv) static VALUE f_exec(int c, const VALUE *a, VALUE _) { - return rb_f_exec(c, a); + rb_f_exec(c, a); + UNREACHABLE_RETURN(Qnil); } #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0) @@ -3373,7 +3582,7 @@ save_env(struct rb_execarg *sargp) if (!sargp) return; if (sargp->env_modification == Qfalse) { - VALUE env = rb_const_get(rb_cObject, id_ENV); + VALUE env = rb_envtbl(); if (RTEST(env)) { VALUE ary = hide_obj(rb_ary_new()); rb_block_call(env, idEach, 0, 0, save_env_i, @@ -3479,10 +3688,8 @@ rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, if (eargp->chdir_given) { if (sargp) { - char *cwd = ruby_getcwd(); sargp->chdir_given = 1; - sargp->chdir_dir = hide_obj(rb_str_new2(cwd)); - xfree(cwd); + sargp->chdir_dir = hide_obj(rb_dir_getwd_ospath()); } if (chdir(RSTRING_PTR(eargp->chdir_dir)) == -1) { /* async-signal-safe */ ERRMSG("chdir"); @@ -3633,7 +3840,7 @@ rb_thread_sleep_that_takes_VALUE_as_sole_argument(VALUE n) } static int -handle_fork_error(int err, int *status, int *ep, volatile int *try_gc_p) +handle_fork_error(int err, struct rb_process_status *status, int *ep, volatile int *try_gc_p) { int state = 0; @@ -3654,7 +3861,7 @@ handle_fork_error(int err, int *status, int *ep, volatile int *try_gc_p) } else { rb_protect(rb_thread_sleep_that_takes_VALUE_as_sole_argument, INT2FIX(1), &state); - if (status) *status = state; + if (status) status->status = state; if (!state) return 0; } break; @@ -3872,10 +4079,10 @@ struct child_handler_disabler_state static void disable_child_handler_before_fork(struct child_handler_disabler_state *old) { +#ifdef HAVE_PTHREAD_SIGMASK int ret; sigset_t all; -#ifdef HAVE_PTHREAD_SIGMASK ret = sigfillset(&all); if (ret == -1) rb_sys_fail("sigfillset"); @@ -3892,9 +4099,9 @@ disable_child_handler_before_fork(struct child_handler_disabler_state *old) static void disable_child_handler_fork_parent(struct child_handler_disabler_state *old) { +#ifdef HAVE_PTHREAD_SIGMASK int ret; -#ifdef HAVE_PTHREAD_SIGMASK ret = pthread_sigmask(SIG_SETMASK, &old->sigmask, NULL); /* not async-signal-safe */ if (ret != 0) { rb_syserr_fail(ret, "pthread_sigmask"); @@ -3942,12 +4149,8 @@ disable_child_handler_fork_child(struct child_handler_disabler_state *old, char return 0; } -COMPILER_WARNING_PUSH -#ifdef __GNUC__ -COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) -#endif static rb_pid_t -retry_fork_async_signal_safe(int *status, int *ep, +retry_fork_async_signal_safe(struct rb_process_status *status, int *ep, int (*chfunc)(void*, char *, size_t), void *charg, char *errmsg, size_t errmsg_buflen, struct waitpid_state *w) @@ -3970,9 +4173,9 @@ retry_fork_async_signal_safe(int *status, int *ep, if (!has_privilege()) pid = vfork(); else - pid = fork(); + pid = rb_fork(); #else - pid = fork(); + pid = rb_fork(); #endif if (pid == 0) {/* fork succeed, child process */ int ret; @@ -3989,7 +4192,7 @@ retry_fork_async_signal_safe(int *status, int *ep, _exit(127); #endif } - err = errno; + err = errno; waitpid_lock = waitpid_lock_init; if (waitpid_lock) { if (pid > 0 && w != WAITPID_LOCK_ONLY) { @@ -4006,10 +4209,9 @@ retry_fork_async_signal_safe(int *status, int *ep, return -1; } } -COMPILER_WARNING_POP static rb_pid_t -fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, +fork_check_err(struct rb_process_status *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen, struct rb_execarg *eargp) { @@ -4017,31 +4219,46 @@ fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, int err; int ep[2]; int error_occurred; - struct waitpid_state *w; - w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0; + struct waitpid_state *w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0; - if (status) *status = 0; + if (status) status->status = 0; if (pipe_nocrash(ep, fds)) return -1; - pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, - errmsg, errmsg_buflen, w); - if (pid < 0) + + pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen, w); + + if (status) status->pid = pid; + + if (pid < 0) { + if (status) status->error = errno; + return pid; + } + close(ep[1]); + error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen); + if (error_occurred) { if (status) { + int state = 0; + status->error = err; + VM_ASSERT((w == 0 || w == WAITPID_LOCK_ONLY) && "only used by extensions"); - rb_protect(proc_syswait, (VALUE)pid, status); + rb_protect(proc_syswait, (VALUE)pid, &state); + + status->status = state; } - else if (!w) { + else if (!w || w == WAITPID_LOCK_ONLY) { rb_syswait(pid); } + errno = err; return -1; } + return pid; } @@ -4057,44 +4274,100 @@ rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen) { - return fork_check_err(status, chfunc, charg, fds, errmsg, errmsg_buflen, 0); + struct rb_process_status process_status; + + rb_pid_t result = fork_check_err(&process_status, chfunc, charg, fds, errmsg, errmsg_buflen, 0); + + if (status) { + *status = process_status.status; + } + + return result; } -COMPILER_WARNING_PUSH -#ifdef __GNUC__ -COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) -#endif -rb_pid_t -rb_fork_ruby(int *status) +static rb_pid_t +rb_fork_ruby2(struct rb_process_status *status) { rb_pid_t pid; int try_gc = 1, err; struct child_handler_disabler_state old; - if (status) *status = 0; + if (status) status->status = 0; while (1) { - prefork(); + prefork(); if (mjit_enabled) mjit_pause(false); // Don't leave locked mutex to child. Note: child_handler must be enabled to pause MJIT. - disable_child_handler_before_fork(&old); - before_fork_ruby(); - pid = fork(); - err = errno; + disable_child_handler_before_fork(&old); + before_fork_ruby(); + pid = rb_fork(); + err = errno; + if (status) { + status->pid = pid; + status->error = err; + } after_fork_ruby(); - disable_child_handler_fork_parent(&old); /* yes, bad name */ + disable_child_handler_fork_parent(&old); /* yes, bad name */ + if (mjit_enabled && pid > 0) mjit_resume(); /* child (pid == 0) is cared by rb_thread_atfork */ - if (pid >= 0) /* fork succeed */ - return pid; - /* fork failed */ - if (handle_fork_error(err, status, NULL, &try_gc)) - return -1; + + if (pid >= 0) { /* fork succeed */ + if (pid == 0) rb_thread_atfork(); + return pid; + } + + /* fork failed */ + if (handle_fork_error(err, status, NULL, &try_gc)) { + return -1; + } } } -COMPILER_WARNING_POP +rb_pid_t +rb_fork_ruby(int *status) +{ + struct rb_process_status process_status = {0}; + + rb_pid_t pid = rb_fork_ruby2(&process_status); + + if (status) *status = process_status.status; + + return pid; +} + +rb_pid_t +rb_call_proc__fork(void) +{ + VALUE pid = rb_funcall(rb_mProcess, rb_intern("_fork"), 0); + + return NUM2PIDT(pid); +} #endif #if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD) +/* + * call-seq: + * Process._fork -> integer + * + * An internal API for fork. Do not call this method directly. + * Currently, this is called via Kernel#fork, Process.fork, and + * IO.popen with "-". + * + * This method is not for casual code but for application monitoring + * libraries. You can add custom code before and after fork events + * by overriding this method. + */ +VALUE +rb_proc__fork(VALUE _obj) +{ + rb_pid_t pid = rb_fork_ruby(NULL); + + if (pid == -1) { + rb_sys_fail("fork(2)"); + } + + return PIDT2NUM(pid); +} + /* * call-seq: * Kernel.fork [{ block }] -> integer or nil @@ -4125,25 +4398,21 @@ rb_f_fork(VALUE obj) { rb_pid_t pid; - switch (pid = rb_fork_ruby(NULL)) { - case 0: - rb_thread_atfork(); + pid = rb_call_proc__fork(); + + if (pid == 0) { if (rb_block_given_p()) { int status; rb_protect(rb_yield, Qundef, &status); ruby_stop(status); } return Qnil; - - case -1: - rb_sys_fail("fork(2)"); - return Qnil; - - default: - return PIDT2NUM(pid); } + + return PIDT2NUM(pid); } #else +#define rb_proc__fork rb_f_notimplement #define rb_f_fork rb_f_notimplement #endif @@ -4170,6 +4439,7 @@ exit_status_code(VALUE status) return istatus; } +NORETURN(static VALUE rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)); /* * call-seq: * Process.exit!(status=false) @@ -4226,6 +4496,7 @@ rb_f_exit(int argc, const VALUE *argv) UNREACHABLE_RETURN(Qnil); } +NORETURN(static VALUE f_exit(int c, const VALUE *a, VALUE _)); /* * call-seq: * exit(status=true) @@ -4270,20 +4541,10 @@ rb_f_exit(int argc, const VALUE *argv) static VALUE f_exit(int c, const VALUE *a, VALUE _) { - return rb_f_exit(c, a); + rb_f_exit(c, a); + UNREACHABLE_RETURN(Qnil); } -/* - * call-seq: - * abort - * Kernel::abort([msg]) - * Process.abort([msg]) - * - * Terminate execution immediately, effectively by calling - * Kernel.exit(false). If _msg_ is given, it is written - * to STDERR prior to terminating. - */ - VALUE rb_f_abort(int argc, const VALUE *argv) { @@ -4301,7 +4562,7 @@ rb_f_abort(int argc, const VALUE *argv) args[1] = args[0] = argv[0]; StringValue(args[0]); - rb_io_puts(1, args, rb_stderr); + rb_io_puts(1, args, rb_ractor_stderr()); args[0] = INT2NUM(EXIT_FAILURE); rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); } @@ -4309,10 +4570,24 @@ rb_f_abort(int argc, const VALUE *argv) UNREACHABLE_RETURN(Qnil); } +NORETURN(static VALUE f_abort(int c, const VALUE *a, VALUE _)); + +/* + * call-seq: + * abort + * Kernel::abort([msg]) + * Process.abort([msg]) + * + * Terminate execution immediately, effectively by calling + * Kernel.exit(false). If _msg_ is given, it is written + * to STDERR prior to terminating. + */ + static VALUE f_abort(int c, const VALUE *a, VALUE _) { - return rb_f_abort(c, a); + rb_f_abort(c, a); + UNREACHABLE_RETURN(Qnil); } void @@ -4323,7 +4598,7 @@ rb_syswait(rb_pid_t pid) rb_waitpid(pid, &status, 0); } -#if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV +#if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV && !defined __EMSCRIPTEN__ char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog) { @@ -4359,8 +4634,7 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen) #endif #if defined HAVE_WORKING_FORK && !USE_SPAWNV - pid = fork_check_err(0, rb_exec_atfork, eargp, eargp->redirect_fds, - errmsg, errmsg_buflen, eargp); + pid = fork_check_err(eargp->status, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen, eargp); #else prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name; @@ -4374,32 +4648,37 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen) } # if defined HAVE_SPAWNV if (eargp->use_shell) { - pid = proc_spawn_sh(RSTRING_PTR(prog)); + pid = proc_spawn_sh(RSTRING_PTR(prog)); } else { char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str); - pid = proc_spawn_cmd(argv, prog, eargp); + pid = proc_spawn_cmd(argv, prog, eargp); + } + + if (pid == -1) { + rb_last_status_set(0x7f << 8, pid); } - if (pid == -1) - rb_last_status_set(0x7f << 8, 0); # else status = system(rb_execarg_commandline(eargp, &prog)); - rb_last_status_set((status & 0xff) << 8, 0); pid = 1; /* dummy */ + rb_last_status_set((status & 0xff) << 8, pid); # endif + if (eargp->waitpid_state && eargp->waitpid_state != WAITPID_LOCK_ONLY) { eargp->waitpid_state->pid = pid; } + rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen); #endif + return pid; } struct spawn_args { VALUE execarg; struct { - char *ptr; - size_t buflen; + char *ptr; + size_t buflen; } errmsg; }; @@ -4508,58 +4787,62 @@ rb_spawn(int argc, const VALUE *argv) static VALUE rb_f_system(int argc, VALUE *argv, VALUE _) { - /* - * n.b. using alloca for now to simplify future Thread::Light code - * when we need to use malloc for non-native Fiber - */ - struct waitpid_state *w = alloca(sizeof(struct waitpid_state)); - rb_pid_t pid; /* may be different from waitpid_state.pid on exec failure */ - VALUE execarg_obj; - struct rb_execarg *eargp; - int exec_errnum; + VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE); + struct rb_execarg *eargp = rb_execarg_get(execarg_obj); - execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE); - eargp = rb_execarg_get(execarg_obj); - w->ec = GET_EC(); - waitpid_state_init(w, 0, 0); - eargp->waitpid_state = w; - pid = rb_execarg_spawn(execarg_obj, 0, 0); - exec_errnum = pid < 0 ? errno : 0; + struct rb_process_status status = {0}; + eargp->status = &status; -#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) - if (w->pid > 0) { - /* `pid' (not w->pid) may be < 0 here if execve failed in child */ - if (WAITPID_USE_SIGCHLD) { - rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w); + rb_last_status_clear(); + + // This function can set the thread's last status. + // May be different from waitpid_state.pid on exec failure. + rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0); + + if (pid > 0) { + VALUE status = rb_process_status_wait(pid, 0); + struct rb_process_status *data = RTYPEDDATA_DATA(status); + + // Set the last status: + rb_obj_freeze(status); + GET_THREAD()->last_status = status; + + if (data->status == EXIT_SUCCESS) { + return Qtrue; } - else { - waitpid_no_SIGCHLD(w); + + if (data->error != 0) { + if (eargp->exception) { + VALUE command = eargp->invoke.sh.shell_script; + RB_GC_GUARD(execarg_obj); + rb_syserr_fail_str(data->error, command); + } + else { + return Qnil; + } } - rb_last_status_set(w->status, w->ret); - } -#endif - if (w->pid < 0 /* fork failure */ || pid < 0 /* exec failure */) { - if (eargp->exception) { - int err = exec_errnum ? exec_errnum : w->errnum; + else if (eargp->exception) { VALUE command = eargp->invoke.sh.shell_script; + VALUE str = rb_str_new_cstr("Command failed with"); + rb_str_cat_cstr(pst_message_status(str, data->status), ": "); + rb_str_append(str, command); RB_GC_GUARD(execarg_obj); - rb_syserr_fail_str(err, command); + rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str)); } else { - return Qnil; + return Qfalse; } + + RB_GC_GUARD(status); } - if (w->status == EXIT_SUCCESS) return Qtrue; + if (eargp->exception) { VALUE command = eargp->invoke.sh.shell_script; - VALUE str = rb_str_new_cstr("Command failed with"); - rb_str_cat_cstr(pst_message_status(str, w->status), ": "); - rb_str_append(str, command); RB_GC_GUARD(execarg_obj); - rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str)); + rb_syserr_fail_str(errno, command); } else { - return Qfalse; + return Qnil; } } @@ -4879,20 +5162,25 @@ rb_f_spawn(int argc, VALUE *argv, VALUE _) static VALUE rb_f_sleep(int argc, VALUE *argv, VALUE _) { - time_t beg, end; + time_t beg = time(0); + VALUE scheduler = rb_fiber_scheduler_current(); - beg = time(0); - if (argc == 0) { - rb_thread_sleep_forever(); + if (scheduler != Qnil) { + rb_fiber_scheduler_kernel_sleepv(scheduler, argc, argv); } else { - rb_check_arity(argc, 0, 1); - rb_thread_wait_for(rb_time_interval(argv[0])); + if (argc == 0) { + rb_thread_sleep_forever(); + } + else { + rb_check_arity(argc, 0, 1); + rb_thread_wait_for(rb_time_interval(argv[0])); + } } - end = time(0) - beg; + time_t end = time(0) - beg; - return INT2FIX(end); + return TIMET2NUM(end); } @@ -5513,6 +5801,246 @@ check_gid_switch(void) } +#if defined(HAVE_PWD_H) +/** + * Best-effort attempt to obtain the name of the login user, if any, + * associated with the process. Processes not descended from login(1) (or + * similar) may not have a logged-in user; returns Qnil in that case. + */ +VALUE +rb_getlogin(void) +{ +#if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) ) + return Qnil; +#else + char MAYBE_UNUSED(*login) = NULL; + +# ifdef USE_GETLOGIN_R + +#if defined(__FreeBSD__) + typedef int getlogin_r_size_t; +#else + typedef size_t getlogin_r_size_t; +#endif + + long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */ + + if (loginsize < 0) + loginsize = GETLOGIN_R_SIZE_DEFAULT; + + VALUE maybe_result = rb_str_buf_new(loginsize); + + login = RSTRING_PTR(maybe_result); + loginsize = rb_str_capacity(maybe_result); + rb_str_set_len(maybe_result, loginsize); + + int gle; + errno = 0; + while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) { + + if (gle == ENOTTY || gle == ENXIO || gle == ENOENT) { + rb_str_resize(maybe_result, 0); + return Qnil; + } + + if (gle != ERANGE || loginsize >= GETLOGIN_R_SIZE_LIMIT) { + rb_str_resize(maybe_result, 0); + rb_syserr_fail(gle, "getlogin_r"); + } + + rb_str_modify_expand(maybe_result, loginsize); + login = RSTRING_PTR(maybe_result); + loginsize = rb_str_capacity(maybe_result); + } + + if (login == NULL) { + rb_str_resize(maybe_result, 0); + return Qnil; + } + + return maybe_result; + +# elif USE_GETLOGIN + + errno = 0; + login = getlogin(); + if (errno) { + if (errno == ENOTTY || errno == ENXIO || errno == ENOENT) { + return Qnil; + } + rb_syserr_fail(errno, "getlogin"); + } + + return login ? rb_str_new_cstr(login) : Qnil; +# endif + +#endif +} + +VALUE +rb_getpwdirnam_for_login(VALUE login_name) +{ +#if ( !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM) ) + return Qnil; +#else + + if (NIL_P(login_name)) { + /* nothing to do; no name with which to query the password database */ + return Qnil; + } + + char *login = RSTRING_PTR(login_name); + + struct passwd *pwptr; + +# ifdef USE_GETPWNAM_R + + struct passwd pwdnm; + char *bufnm; + long bufsizenm = GETPW_R_SIZE_INIT; /* maybe -1 */ + + if (bufsizenm < 0) + bufsizenm = GETPW_R_SIZE_DEFAULT; + + VALUE getpwnm_tmp = rb_str_tmp_new(bufsizenm); + + bufnm = RSTRING_PTR(getpwnm_tmp); + bufsizenm = rb_str_capacity(getpwnm_tmp); + rb_str_set_len(getpwnm_tmp, bufsizenm); + + int enm; + errno = 0; + while ((enm = getpwnam_r(login, &pwdnm, bufnm, bufsizenm, &pwptr)) != 0) { + + if (enm == ENOENT || enm== ESRCH || enm == EBADF || enm == EPERM) { + /* not found; non-errors */ + rb_str_resize(getpwnm_tmp, 0); + return Qnil; + } + + if (enm != ERANGE || bufsizenm >= GETPW_R_SIZE_LIMIT) { + rb_str_resize(getpwnm_tmp, 0); + rb_syserr_fail(enm, "getpwnam_r"); + } + + rb_str_modify_expand(getpwnm_tmp, bufsizenm); + bufnm = RSTRING_PTR(getpwnm_tmp); + bufsizenm = rb_str_capacity(getpwnm_tmp); + } + + if (pwptr == NULL) { + /* no record in the password database for the login name */ + rb_str_resize(getpwnm_tmp, 0); + return Qnil; + } + + /* found it */ + VALUE result = rb_str_new_cstr(pwptr->pw_dir); + rb_str_resize(getpwnm_tmp, 0); + return result; + +# elif USE_GETPWNAM + + errno = 0; + pwptr = getpwnam(login); + if (pwptr) { + /* found it */ + return rb_str_new_cstr(pwptr->pw_dir); + } + if (errno + /* avoid treating as errors errno values that indicate "not found" */ + && ( errno != ENOENT && errno != ESRCH && errno != EBADF && errno != EPERM)) { + rb_syserr_fail(errno, "getpwnam"); + } + + return Qnil; /* not found */ +# endif + +#endif +} + +/** + * Look up the user's dflt home dir in the password db, by uid. + */ +VALUE +rb_getpwdiruid(void) +{ +# if !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) + /* Should never happen... */ + return Qnil; +# else + uid_t ruid = getuid(); + + struct passwd *pwptr; + +# ifdef USE_GETPWUID_R + + struct passwd pwdid; + char *bufid; + long bufsizeid = GETPW_R_SIZE_INIT; /* maybe -1 */ + + if (bufsizeid < 0) + bufsizeid = GETPW_R_SIZE_DEFAULT; + + VALUE getpwid_tmp = rb_str_tmp_new(bufsizeid); + + bufid = RSTRING_PTR(getpwid_tmp); + bufsizeid = rb_str_capacity(getpwid_tmp); + rb_str_set_len(getpwid_tmp, bufsizeid); + + int eid; + errno = 0; + while ((eid = getpwuid_r(ruid, &pwdid, bufid, bufsizeid, &pwptr)) != 0) { + + if (eid == ENOENT || eid== ESRCH || eid == EBADF || eid == EPERM) { + /* not found; non-errors */ + rb_str_resize(getpwid_tmp, 0); + return Qnil; + } + + if (eid != ERANGE || bufsizeid >= GETPW_R_SIZE_LIMIT) { + rb_str_resize(getpwid_tmp, 0); + rb_syserr_fail(eid, "getpwuid_r"); + } + + rb_str_modify_expand(getpwid_tmp, bufsizeid); + bufid = RSTRING_PTR(getpwid_tmp); + bufsizeid = rb_str_capacity(getpwid_tmp); + } + + if (pwptr == NULL) { + /* no record in the password database for the uid */ + rb_str_resize(getpwid_tmp, 0); + return Qnil; + } + + /* found it */ + VALUE result = rb_str_new_cstr(pwptr->pw_dir); + rb_str_resize(getpwid_tmp, 0); + return result; + +# elif defined(USE_GETPWUID) + + errno = 0; + pwptr = getpwuid(ruid); + if (pwptr) { + /* found it */ + return rb_str_new_cstr(pwptr->pw_dir); + } + if (errno + /* avoid treating as errors errno values that indicate "not found" */ + && ( errno == ENOENT || errno == ESRCH || errno == EBADF || errno == EPERM)) { + rb_syserr_fail(errno, "getpwuid"); + } + + return Qnil; /* not found */ +# endif + +#endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */ +} +#endif /* HAVE_PWD_H */ + + /********************************************************************* * Document-class: Process::Sys * @@ -5570,7 +6098,7 @@ obj2uid(VALUE id #ifndef USE_GETPWNAM_R endpwent(); #endif - rb_raise(rb_eArgError, "can't find user for %s", usrname); + rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, id); } uid = pwptr->pw_uid; #ifndef USE_GETPWNAM_R @@ -5649,7 +6177,7 @@ obj2gid(VALUE id #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) endgrent(); #endif - rb_raise(rb_eArgError, "can't find group for %s", grpname); + rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, id); } gid = grptr->gr_gid; #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) @@ -6548,7 +7076,7 @@ rb_daemon(int nochdir, int noclose) #define fork_daemon() \ switch (rb_fork_ruby(NULL)) { \ case -1: return -1; \ - case 0: rb_thread_atfork(); break; \ + case 0: break; \ default: _exit(EXIT_SUCCESS); \ } @@ -7666,8 +8194,8 @@ ruby_real_ms_time(void) * The supported constants depends on OS and version. * Ruby provides following types of +clock_id+ if available. * - * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12 - * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12 + * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012 + * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12, Windows-2000 * [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12 * [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12 * [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1 @@ -7940,29 +8468,33 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _) * call-seq: * Process.clock_getres(clock_id [, unit]) -> number * - * Returns the time resolution returned by POSIX clock_getres() function. + * Returns an estimate of the resolution of a +clock_id+ using the POSIX + * clock_getres() function. + * + * Note the reported resolution is often inaccurate on most platforms due to + * underlying bugs for this function and therefore the reported resolution + * often differs from the actual resolution of the clock in practice. + * Inaccurate reported resolutions have been observed for various clocks including + * CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW when using Linux, macOS, BSD or AIX + * platforms, when using ARM processors, or when using virtualization. * * +clock_id+ specifies a kind of clock. * See the document of +Process.clock_gettime+ for details. - * - * +clock_id+ can be a symbol as +Process.clock_gettime+. - * However the result may not be accurate. - * For example, Process.clock_getres(:GETTIMEOFDAY_BASED_CLOCK_REALTIME) - * returns 1.0e-06 which means 1 microsecond, but actual resolution can be more coarse. + * +clock_id+ can be a symbol as for +Process.clock_gettime+. * * If the given +clock_id+ is not supported, Errno::EINVAL is raised. * - * +unit+ specifies a type of the return value. + * +unit+ specifies the type of the return value. * +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+. - * The default value, +:float_second+, is also same as + * The default value, +:float_second+, is also the same as * +Process.clock_gettime+. * * +Process.clock_getres+ also accepts +:hertz+ as +unit+. - * +:hertz+ means a the reciprocal of +:float_second+. + * +:hertz+ means the reciprocal of +:float_second+. * * +:hertz+ can be used to obtain the exact value of - * the clock ticks per second for times() function and - * CLOCKS_PER_SEC for clock() function. + * the clock ticks per second for the times() function and + * CLOCKS_PER_SEC for the clock() function. * * Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz) * returns the clock ticks per second. @@ -8146,10 +8678,12 @@ static VALUE rb_mProcID_Syscall; void InitVM_process(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) rb_define_virtual_variable("$?", get_CHILD_STATUS, 0); rb_define_virtual_variable("$$", get_PROCESS_ID, 0); + + rb_gvar_ractor_local("$$"); + rb_gvar_ractor_local("$?"); + rb_define_global_function("exec", f_exec, -1); rb_define_global_function("fork", rb_f_fork, 0); rb_define_global_function("exit!", rb_f_exit_bang, -1); @@ -8183,6 +8717,7 @@ InitVM_process(void) rb_define_singleton_method(rb_mProcess, "exit", f_exit, -1); rb_define_singleton_method(rb_mProcess, "abort", f_abort, -1); rb_define_singleton_method(rb_mProcess, "last_status", proc_s_last_status, 0); + rb_define_singleton_method(rb_mProcess, "_fork", rb_proc__fork, 0); rb_define_module_function(rb_mProcess, "kill", proc_rb_f_kill, -1); rb_define_module_function(rb_mProcess, "wait", proc_m_wait, -1); @@ -8199,7 +8734,12 @@ InitVM_process(void) rb_define_method(rb_cWaiter, "pid", detach_process_pid, 0); rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject); + rb_define_alloc_func(rb_cProcessStatus, rb_process_status_allocate); rb_undef_method(CLASS_OF(rb_cProcessStatus), "new"); + rb_marshal_define_compat(rb_cProcessStatus, rb_cObject, + process_status_dump, process_status_load); + + rb_define_singleton_method(rb_cProcessStatus, "wait", rb_process_status_waitv, -1); rb_define_method(rb_cProcessStatus, "==", pst_equal, 1); rb_define_method(rb_cProcessStatus, "&", pst_bitand, 1); @@ -8208,7 +8748,7 @@ InitVM_process(void) rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0); rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0); - rb_define_method(rb_cProcessStatus, "pid", pst_pid, 0); + rb_define_method(rb_cProcessStatus, "pid", pst_pid_m, 0); rb_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0); rb_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0); @@ -8510,9 +9050,6 @@ InitVM_process(void) #if defined(HAVE_TIMES) || defined(_WIN32) /* Placeholder for rusage */ rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL); - /* An obsolete name of Process::Tms for backward compatibility */ - rb_define_const(rb_cStruct, "Tms", rb_cProcessTms); - rb_deprecate_constant(rb_cStruct, "Tms"); #endif SAVED_USER_ID = geteuid(); @@ -8573,46 +9110,45 @@ InitVM_process(void) void Init_process(void) { - id_in = rb_intern("in"); - id_out = rb_intern("out"); - id_err = rb_intern("err"); - id_pid = rb_intern("pid"); - id_uid = rb_intern("uid"); - id_gid = rb_intern("gid"); - id_close = rb_intern("close"); - id_child = rb_intern("child"); + id_in = rb_intern_const("in"); + id_out = rb_intern_const("out"); + id_err = rb_intern_const("err"); + id_pid = rb_intern_const("pid"); + id_uid = rb_intern_const("uid"); + id_gid = rb_intern_const("gid"); + id_close = rb_intern_const("close"); + id_child = rb_intern_const("child"); #ifdef HAVE_SETPGID - id_pgroup = rb_intern("pgroup"); + id_pgroup = rb_intern_const("pgroup"); #endif #ifdef _WIN32 - id_new_pgroup = rb_intern("new_pgroup"); -#endif - id_unsetenv_others = rb_intern("unsetenv_others"); - id_chdir = rb_intern("chdir"); - id_umask = rb_intern("umask"); - id_close_others = rb_intern("close_others"); - id_ENV = rb_intern("ENV"); - id_nanosecond = rb_intern("nanosecond"); - id_microsecond = rb_intern("microsecond"); - id_millisecond = rb_intern("millisecond"); - id_second = rb_intern("second"); - id_float_microsecond = rb_intern("float_microsecond"); - id_float_millisecond = rb_intern("float_millisecond"); - id_float_second = rb_intern("float_second"); - id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern("GETTIMEOFDAY_BASED_CLOCK_REALTIME"); - id_TIME_BASED_CLOCK_REALTIME = rb_intern("TIME_BASED_CLOCK_REALTIME"); + id_new_pgroup = rb_intern_const("new_pgroup"); +#endif + id_unsetenv_others = rb_intern_const("unsetenv_others"); + id_chdir = rb_intern_const("chdir"); + id_umask = rb_intern_const("umask"); + id_close_others = rb_intern_const("close_others"); + id_nanosecond = rb_intern_const("nanosecond"); + id_microsecond = rb_intern_const("microsecond"); + id_millisecond = rb_intern_const("millisecond"); + id_second = rb_intern_const("second"); + id_float_microsecond = rb_intern_const("float_microsecond"); + id_float_millisecond = rb_intern_const("float_millisecond"); + id_float_second = rb_intern_const("float_second"); + id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern_const("GETTIMEOFDAY_BASED_CLOCK_REALTIME"); + id_TIME_BASED_CLOCK_REALTIME = rb_intern_const("TIME_BASED_CLOCK_REALTIME"); #ifdef HAVE_TIMES - id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern("TIMES_BASED_CLOCK_MONOTONIC"); - id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID"); + id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern_const("TIMES_BASED_CLOCK_MONOTONIC"); + id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID"); #endif #ifdef RUSAGE_SELF - id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID"); + id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID"); #endif - id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID"); + id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID"); #ifdef __APPLE__ - id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC"); + id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern_const("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC"); #endif - id_hertz = rb_intern("hertz"); + id_hertz = rb_intern_const("hertz"); InitVM(process); } diff --git a/ruby/ractor.c b/ruby/ractor.c new file mode 100644 index 000000000..3c05964e9 --- /dev/null +++ b/ruby/ractor.c @@ -0,0 +1,3261 @@ +// Ractor implementation + +#include "ruby/ruby.h" +#include "ruby/thread.h" +#include "ruby/ractor.h" +#include "ruby/thread_native.h" +#include "vm_core.h" +#include "vm_sync.h" +#include "ractor_core.h" +#include "internal/complex.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/rational.h" +#include "internal/struct.h" +#include "internal/thread.h" +#include "variable.h" +#include "gc.h" +#include "transient_heap.h" +#include "yjit.h" + +VALUE rb_cRactor; + +VALUE rb_eRactorUnsafeError; +VALUE rb_eRactorIsolationError; +static VALUE rb_eRactorError; +static VALUE rb_eRactorRemoteError; +static VALUE rb_eRactorMovedError; +static VALUE rb_eRactorClosedError; +static VALUE rb_cRactorMovedObject; + +static void vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *r, const char *file, int line); + +static void +ASSERT_ractor_unlocking(rb_ractor_t *r) +{ +#if RACTOR_CHECK_MODE > 0 + // GET_EC is NULL in an MJIT worker + if (rb_current_execution_context(false) != NULL && r->sync.locked_by == rb_ractor_self(GET_RACTOR())) { + rb_bug("recursive ractor locking"); + } +#endif +} + +static void +ASSERT_ractor_locking(rb_ractor_t *r) +{ +#if RACTOR_CHECK_MODE > 0 + // GET_EC is NULL in an MJIT worker + if (rb_current_execution_context(false) != NULL && r->sync.locked_by != rb_ractor_self(GET_RACTOR())) { + rp(r->sync.locked_by); + rb_bug("ractor lock is not acquired."); + } +#endif +} + +static void +ractor_lock(rb_ractor_t *r, const char *file, int line) +{ + RUBY_DEBUG_LOG2(file, line, "locking r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : ""); + + ASSERT_ractor_unlocking(r); + rb_native_mutex_lock(&r->sync.lock); + +#if RACTOR_CHECK_MODE > 0 + if (rb_current_execution_context(false) != NULL) { // GET_EC is NULL in an MJIT worker + r->sync.locked_by = rb_ractor_self(GET_RACTOR()); + } +#endif + + RUBY_DEBUG_LOG2(file, line, "locked r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : ""); +} + +static void +ractor_lock_self(rb_ractor_t *cr, const char *file, int line) +{ + VM_ASSERT(cr == GET_RACTOR()); + VM_ASSERT(cr->sync.locked_by != cr->pub.self); + ractor_lock(cr, file, line); +} + +static void +ractor_unlock(rb_ractor_t *r, const char *file, int line) +{ + ASSERT_ractor_locking(r); +#if RACTOR_CHECK_MODE > 0 + r->sync.locked_by = Qnil; +#endif + rb_native_mutex_unlock(&r->sync.lock); + + RUBY_DEBUG_LOG2(file, line, "r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : ""); +} + +static void +ractor_unlock_self(rb_ractor_t *cr, const char *file, int line) +{ + VM_ASSERT(cr == GET_RACTOR()); + VM_ASSERT(cr->sync.locked_by == cr->pub.self); + ractor_unlock(cr, file, line); +} + +#define RACTOR_LOCK(r) ractor_lock(r, __FILE__, __LINE__) +#define RACTOR_UNLOCK(r) ractor_unlock(r, __FILE__, __LINE__) +#define RACTOR_LOCK_SELF(r) ractor_lock_self(r, __FILE__, __LINE__) +#define RACTOR_UNLOCK_SELF(r) ractor_unlock_self(r, __FILE__, __LINE__) + +static void +ractor_cond_wait(rb_ractor_t *r) +{ +#if RACTOR_CHECK_MODE > 0 + VALUE locked_by = r->sync.locked_by; + r->sync.locked_by = Qnil; +#endif + rb_native_cond_wait(&r->sync.cond, &r->sync.lock); + +#if RACTOR_CHECK_MODE > 0 + r->sync.locked_by = locked_by; +#endif +} + +static const char * +ractor_status_str(enum ractor_status status) +{ + switch (status) { + case ractor_created: return "created"; + case ractor_running: return "running"; + case ractor_blocking: return "blocking"; + case ractor_terminated: return "terminated"; + } + rb_bug("unreachable"); +} + +static void +ractor_status_set(rb_ractor_t *r, enum ractor_status status) +{ + RUBY_DEBUG_LOG("r:%u [%s]->[%s]", r->pub.id, ractor_status_str(r->status_), ractor_status_str(status)); + + // check 1 + if (r->status_ != ractor_created) { + VM_ASSERT(r == GET_RACTOR()); // only self-modification is allowed. + ASSERT_vm_locking(); + } + + // check2: transition check. assume it will be vanished on non-debug build. + switch (r->status_) { + case ractor_created: + VM_ASSERT(status == ractor_blocking); + break; + case ractor_running: + VM_ASSERT(status == ractor_blocking|| + status == ractor_terminated); + break; + case ractor_blocking: + VM_ASSERT(status == ractor_running); + break; + case ractor_terminated: + VM_ASSERT(0); // unreachable + break; + } + + r->status_ = status; +} + +static bool +ractor_status_p(rb_ractor_t *r, enum ractor_status status) +{ + return rb_ractor_status_p(r, status); +} + +static struct rb_ractor_basket *ractor_queue_at(struct rb_ractor_queue *rq, int i); + +static void +ractor_queue_mark(struct rb_ractor_queue *rq) +{ + for (int i=0; icnt; i++) { + struct rb_ractor_basket *b = ractor_queue_at(rq, i); + rb_gc_mark(b->v); + rb_gc_mark(b->sender); + } +} + +static void ractor_local_storage_mark(rb_ractor_t *r); +static void ractor_local_storage_free(rb_ractor_t *r); + +static void +ractor_mark(void *ptr) +{ + rb_ractor_t *r = (rb_ractor_t *)ptr; + + ractor_queue_mark(&r->sync.incoming_queue); + rb_gc_mark(r->sync.wait.taken_basket.v); + rb_gc_mark(r->sync.wait.taken_basket.sender); + rb_gc_mark(r->sync.wait.yielded_basket.v); + rb_gc_mark(r->sync.wait.yielded_basket.sender); + rb_gc_mark(r->receiving_mutex); + + rb_gc_mark(r->loc); + rb_gc_mark(r->name); + rb_gc_mark(r->r_stdin); + rb_gc_mark(r->r_stdout); + rb_gc_mark(r->r_stderr); + rb_hook_list_mark(&r->pub.hooks); + + if (r->threads.cnt > 0) { + rb_thread_t *th = 0; + list_for_each(&r->threads.set, th, lt_node) { + VM_ASSERT(th != NULL); + rb_gc_mark(th->self); + } + } + + ractor_local_storage_mark(r); +} + +static void +ractor_queue_free(struct rb_ractor_queue *rq) +{ + free(rq->baskets); +} + +static void +ractor_waiting_list_free(struct rb_ractor_waiting_list *wl) +{ + free(wl->ractors); +} + +static void +ractor_free(void *ptr) +{ + rb_ractor_t *r = (rb_ractor_t *)ptr; + rb_native_mutex_destroy(&r->sync.lock); + rb_native_cond_destroy(&r->sync.cond); + ractor_queue_free(&r->sync.incoming_queue); + ractor_waiting_list_free(&r->sync.taking_ractors); + ractor_local_storage_free(r); + rb_hook_list_free(&r->pub.hooks); + ruby_xfree(r); +} + +static size_t +ractor_queue_memsize(const struct rb_ractor_queue *rq) +{ + return sizeof(struct rb_ractor_basket) * rq->size; +} + +static size_t +ractor_waiting_list_memsize(const struct rb_ractor_waiting_list *wl) +{ + return sizeof(rb_ractor_t *) * wl->size; +} + +static size_t +ractor_memsize(const void *ptr) +{ + rb_ractor_t *r = (rb_ractor_t *)ptr; + + // TODO + return sizeof(rb_ractor_t) + + ractor_queue_memsize(&r->sync.incoming_queue) + + ractor_waiting_list_memsize(&r->sync.taking_ractors); +} + +static const rb_data_type_t ractor_data_type = { + "ractor", + { + ractor_mark, + ractor_free, + ractor_memsize, + NULL, // update + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY /* | RUBY_TYPED_WB_PROTECTED */ +}; + +bool +rb_ractor_p(VALUE gv) +{ + if (rb_typeddata_is_kind_of(gv, &ractor_data_type)) { + return true; + } + else { + return false; + } +} + +static inline rb_ractor_t * +RACTOR_PTR(VALUE self) +{ + VM_ASSERT(rb_ractor_p(self)); + + rb_ractor_t *r = DATA_PTR(self); + // TODO: check + return r; +} + +static rb_atomic_t ractor_last_id; + +#if RACTOR_CHECK_MODE > 0 +MJIT_FUNC_EXPORTED uint32_t +rb_ractor_current_id(void) +{ + if (GET_THREAD()->ractor == NULL) { + return 1; // main ractor + } + else { + return rb_ractor_id(GET_RACTOR()); + } +} +#endif + +static void +ractor_queue_setup(struct rb_ractor_queue *rq) +{ + rq->size = 2; + rq->cnt = 0; + rq->start = 0; + rq->baskets = malloc(sizeof(struct rb_ractor_basket) * rq->size); +} + +static struct rb_ractor_basket * +ractor_queue_at(struct rb_ractor_queue *rq, int i) +{ + return &rq->baskets[(rq->start + i) % rq->size]; +} + +static void +ractor_queue_advance(struct rb_ractor_queue *rq) +{ + ASSERT_ractor_locking(GET_RACTOR()); + + if (rq->reserved_cnt == 0) { + rq->cnt--; + rq->start = (rq->start + 1) % rq->size; + rq->serial++; + } + else { + ractor_queue_at(rq, 0)->type = basket_type_deleted; + } +} + +static bool +ractor_queue_skip_p(struct rb_ractor_queue *rq, int i) +{ + struct rb_ractor_basket *b = ractor_queue_at(rq, i); + return b->type == basket_type_deleted || + b->type == basket_type_reserved; +} + +static void +ractor_queue_compact(rb_ractor_t *r, struct rb_ractor_queue *rq) +{ + ASSERT_ractor_locking(r); + + while (rq->cnt > 0 && ractor_queue_at(rq, 0)->type == basket_type_deleted) { + ractor_queue_advance(rq); + } +} + +static bool +ractor_queue_empty_p(rb_ractor_t *r, struct rb_ractor_queue *rq) +{ + ASSERT_ractor_locking(r); + + if (rq->cnt == 0) { + return true; + } + + ractor_queue_compact(r, rq); + + for (int i=0; icnt; i++) { + if (!ractor_queue_skip_p(rq, i)) { + return false; + } + } + + return true; +} + +static bool +ractor_queue_deq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_basket *basket) +{ + bool found = false; + + RACTOR_LOCK(r); + { + if (!ractor_queue_empty_p(r, rq)) { + for (int i=0; icnt; i++) { + if (!ractor_queue_skip_p(rq, i)) { + struct rb_ractor_basket *b = ractor_queue_at(rq, i); + *basket = *b; + + // remove from queue + b->type = basket_type_deleted; + ractor_queue_compact(r, rq); + found = true; + break; + } + } + } + } + RACTOR_UNLOCK(r); + + return found; +} + +static void +ractor_queue_enq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_basket *basket) +{ + ASSERT_ractor_locking(r); + + if (rq->size <= rq->cnt) { + rq->baskets = realloc(rq->baskets, sizeof(struct rb_ractor_basket) * rq->size * 2); + for (int i=rq->size - rq->start; icnt; i++) { + rq->baskets[i + rq->start] = rq->baskets[i + rq->start - rq->size]; + } + rq->size *= 2; + } + rq->baskets[(rq->start + rq->cnt++) % rq->size] = *basket; + // fprintf(stderr, "%s %p->cnt:%d\n", RUBY_FUNCTION_NAME_STRING, (void *)rq, rq->cnt); +} + +static void +ractor_basket_clear(struct rb_ractor_basket *b) +{ + b->type = basket_type_none; + b->v = Qfalse; + b->sender = Qfalse; +} + +static VALUE ractor_reset_belonging(VALUE obj); // in this file + +static VALUE +ractor_basket_value(struct rb_ractor_basket *b) +{ + switch (b->type) { + case basket_type_ref: + break; + case basket_type_copy: + case basket_type_move: + case basket_type_will: + b->type = basket_type_ref; + b->v = ractor_reset_belonging(b->v); + break; + default: + rb_bug("unreachable"); + } + + return b->v; +} + +static VALUE +ractor_basket_accept(struct rb_ractor_basket *b) +{ + VALUE v = ractor_basket_value(b); + + if (b->exception) { + VALUE cause = v; + VALUE err = rb_exc_new_cstr(rb_eRactorRemoteError, "thrown by remote Ractor."); + rb_ivar_set(err, rb_intern("@ractor"), b->sender); + ractor_basket_clear(b); + rb_ec_setup_exception(NULL, err, cause); + rb_exc_raise(err); + } + + ractor_basket_clear(b); + return v; +} + +static void +ractor_recursive_receive_if(rb_ractor_t *r) +{ + if (r->receiving_mutex && rb_mutex_owned_p(r->receiving_mutex)) { + rb_raise(rb_eRactorError, "can not call receive/receive_if recursively"); + } +} + +static VALUE +ractor_try_receive(rb_execution_context_t *ec, rb_ractor_t *r) +{ + struct rb_ractor_queue *rq = &r->sync.incoming_queue; + struct rb_ractor_basket basket; + + ractor_recursive_receive_if(r); + + if (ractor_queue_deq(r, rq, &basket) == false) { + if (r->sync.incoming_port_closed) { + rb_raise(rb_eRactorClosedError, "The incoming port is already closed"); + } + else { + return Qundef; + } + } + + return ractor_basket_accept(&basket); +} + +static bool +ractor_sleeping_by(const rb_ractor_t *r, enum ractor_wait_status wait_status) +{ + return (r->sync.wait.status & wait_status) && r->sync.wait.wakeup_status == wakeup_none; +} + +static bool +ractor_wakeup(rb_ractor_t *r, enum ractor_wait_status wait_status, enum ractor_wakeup_status wakeup_status) +{ + ASSERT_ractor_locking(r); + + // fprintf(stderr, "%s r:%p status:%s/%s wakeup_status:%s/%s\n", RUBY_FUNCTION_NAME_STRING, (void *)r, + // wait_status_str(r->sync.wait.status), wait_status_str(wait_status), + // wakeup_status_str(r->sync.wait.wakeup_status), wakeup_status_str(wakeup_status)); + + if (ractor_sleeping_by(r, wait_status)) { + r->sync.wait.wakeup_status = wakeup_status; + rb_native_cond_signal(&r->sync.cond); + return true; + } + else { + return false; + } +} + +static void * +ractor_sleep_wo_gvl(void *ptr) +{ + rb_ractor_t *cr = ptr; + RACTOR_LOCK_SELF(cr); + { + VM_ASSERT(cr->sync.wait.status != wait_none); + if (cr->sync.wait.wakeup_status == wakeup_none) { + ractor_cond_wait(cr); + } + cr->sync.wait.status = wait_none; + } + RACTOR_UNLOCK_SELF(cr); + return NULL; +} + +static void +ractor_sleep_interrupt(void *ptr) +{ + rb_ractor_t *r = ptr; + + RACTOR_LOCK(r); + { + ractor_wakeup(r, wait_receiving | wait_taking | wait_yielding, wakeup_by_interrupt); + } + RACTOR_UNLOCK(r); +} + +#if defined(USE_RUBY_DEBUG_LOG) && USE_RUBY_DEBUG_LOG +static const char * +wait_status_str(enum ractor_wait_status wait_status) +{ + switch ((int)wait_status) { + case wait_none: return "none"; + case wait_receiving: return "receiving"; + case wait_taking: return "taking"; + case wait_yielding: return "yielding"; + case wait_receiving|wait_taking: return "receiving|taking"; + case wait_receiving|wait_yielding: return "receiving|yielding"; + case wait_taking|wait_yielding: return "taking|yielding"; + case wait_receiving|wait_taking|wait_yielding: return "receiving|taking|yielding"; + } + rb_bug("unreachable"); +} + +static const char * +wakeup_status_str(enum ractor_wakeup_status wakeup_status) +{ + switch (wakeup_status) { + case wakeup_none: return "none"; + case wakeup_by_send: return "by_send"; + case wakeup_by_yield: return "by_yield"; + case wakeup_by_take: return "by_take"; + case wakeup_by_close: return "by_close"; + case wakeup_by_interrupt: return "by_interrupt"; + case wakeup_by_retry: return "by_retry"; + } + rb_bug("unreachable"); +} +#endif // USE_RUBY_DEBUG_LOG + +static void +ractor_sleep(rb_execution_context_t *ec, rb_ractor_t *cr) +{ + VM_ASSERT(GET_RACTOR() == cr); + VM_ASSERT(cr->sync.wait.status != wait_none); + // fprintf(stderr, "%s r:%p status:%s, wakeup_status:%s\n", RUBY_FUNCTION_NAME_STRING, (void *)cr, + // wait_status_str(cr->sync.wait.status), wakeup_status_str(cr->sync.wait.wakeup_status)); + + RACTOR_UNLOCK(cr); + { + rb_nogvl(ractor_sleep_wo_gvl, cr, + ractor_sleep_interrupt, cr, + RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_INTR_FAIL); + } + RACTOR_LOCK(cr); + + // rb_nogvl() can be canceled by interrupts + if (cr->sync.wait.status != wait_none) { + cr->sync.wait.status = wait_none; + cr->sync.wait.wakeup_status = wakeup_by_interrupt; + + RACTOR_UNLOCK(cr); + rb_thread_check_ints(); + RACTOR_LOCK(cr); // reachable? + } +} + +static void +ractor_register_taking(rb_ractor_t *r, rb_ractor_t *cr) +{ + VM_ASSERT(cr == GET_RACTOR()); + bool retry_try = false; + + RACTOR_LOCK(r); + { + if (ractor_sleeping_by(r, wait_yielding)) { + // already waiting for yielding. retry try_take. + retry_try = true; + } + else { + // insert cr into taking list + struct rb_ractor_waiting_list *wl = &r->sync.taking_ractors; + + for (int i=0; icnt; i++) { + if (wl->ractors[i] == cr) { + // TODO: make it clean code. + rb_native_mutex_unlock(&r->sync.lock); + rb_raise(rb_eRuntimeError, "Already another thread of same ractor is waiting."); + } + } + + if (wl->size == 0) { + wl->size = 1; + wl->ractors = malloc(sizeof(rb_ractor_t *) * wl->size); + if (wl->ractors == NULL) rb_bug("can't allocate buffer"); + } + else if (wl->size <= wl->cnt + 1) { + wl->size *= 2; + wl->ractors = realloc(wl->ractors, sizeof(rb_ractor_t *) * wl->size); + if (wl->ractors == NULL) rb_bug("can't re-allocate buffer"); + } + wl->ractors[wl->cnt++] = cr; + } + } + RACTOR_UNLOCK(r); + + if (retry_try) { + RACTOR_LOCK(cr); + { + if (cr->sync.wait.wakeup_status == wakeup_none) { + VM_ASSERT(cr->sync.wait.status != wait_none); + + cr->sync.wait.wakeup_status = wakeup_by_retry; + cr->sync.wait.status = wait_none; + } + } + RACTOR_UNLOCK(cr); + } +} + +static void +ractor_waiting_list_del(rb_ractor_t *r, struct rb_ractor_waiting_list *wl, rb_ractor_t *wr) +{ + RACTOR_LOCK(r); + { + int pos = -1; + for (int i=0; icnt; i++) { + if (wl->ractors[i] == wr) { + pos = i; + break; + } + } + if (pos >= 0) { // found + wl->cnt--; + for (int i=pos; icnt; i++) { + wl->ractors[i] = wl->ractors[i+1]; + } + } + } + RACTOR_UNLOCK(r); +} + +static rb_ractor_t * +ractor_waiting_list_shift(rb_ractor_t *r, struct rb_ractor_waiting_list *wl) +{ + ASSERT_ractor_locking(r); + VM_ASSERT(&r->sync.taking_ractors == wl); + + if (wl->cnt > 0) { + rb_ractor_t *tr = wl->ractors[0]; + for (int i=1; icnt; i++) { + wl->ractors[i-1] = wl->ractors[i]; + } + wl->cnt--; + return tr; + } + else { + return NULL; + } +} + +static void +ractor_receive_wait(rb_execution_context_t *ec, rb_ractor_t *cr) +{ + VM_ASSERT(cr == rb_ec_ractor_ptr(ec)); + ractor_recursive_receive_if(cr); + + RACTOR_LOCK(cr); + { + if (ractor_queue_empty_p(cr, &cr->sync.incoming_queue)) { + VM_ASSERT(cr->sync.wait.status == wait_none); + cr->sync.wait.status = wait_receiving; + cr->sync.wait.wakeup_status = wakeup_none; + ractor_sleep(ec, cr); + cr->sync.wait.wakeup_status = wakeup_none; + } + } + RACTOR_UNLOCK(cr); +} + +static VALUE +ractor_receive(rb_execution_context_t *ec, rb_ractor_t *cr) +{ + VM_ASSERT(cr == rb_ec_ractor_ptr(ec)); + VALUE v; + + while ((v = ractor_try_receive(ec, cr)) == Qundef) { + ractor_receive_wait(ec, cr); + } + + return v; +} + +#if 0 +// for debug +static const char * +basket_type_name(enum rb_ractor_basket_type type) +{ + switch (type) { +#define T(t) case basket_type_##t: return #t + T(none); + T(ref); + T(copy); + T(move); + T(will); + T(deleted); + T(reserved); + default: rb_bug("unreachable"); + } +} + +static void +rq_dump(struct rb_ractor_queue *rq) +{ + bool bug = false; + for (int i=0; icnt; i++) { + struct rb_ractor_basket *b = ractor_queue_at(rq, i); + fprintf(stderr, "%d (start:%d) type:%s %p %s\n", i, rq->start, basket_type_name(b->type), + (void *)b, RSTRING_PTR(RARRAY_AREF(b->v, 1))); + if (b->type == basket_type_reserved) bug = true; + } + if (bug) rb_bug("!!"); +} +#endif + +struct receive_block_data { + rb_ractor_t *cr; + struct rb_ractor_queue *rq; + VALUE v; + int index; + bool success; +}; + +static void +ractor_receive_if_lock(rb_ractor_t *cr) +{ + VALUE m = cr->receiving_mutex; + if (m == Qfalse) { + m = cr->receiving_mutex = rb_mutex_new(); + } + rb_mutex_lock(m); +} + +static VALUE +receive_if_body(VALUE ptr) +{ + struct receive_block_data *data = (struct receive_block_data *)ptr; + + ractor_receive_if_lock(data->cr); + VALUE block_result = rb_yield(data->v); + + RACTOR_LOCK_SELF(data->cr); + { + struct rb_ractor_basket *b = ractor_queue_at(data->rq, data->index); + VM_ASSERT(b->type == basket_type_reserved); + data->rq->reserved_cnt--; + + if (RTEST(block_result)) { + b->type = basket_type_deleted; + ractor_queue_compact(data->cr, data->rq); + } + else { + b->type = basket_type_ref; + } + } + RACTOR_UNLOCK_SELF(data->cr); + + data->success = true; + + if (RTEST(block_result)) { + return data->v; + } + else { + return Qundef; + } +} + +static VALUE +receive_if_ensure(VALUE v) +{ + struct receive_block_data *data = (struct receive_block_data *)v; + + if (!data->success) { + RACTOR_LOCK_SELF(data->cr); + { + struct rb_ractor_basket *b = ractor_queue_at(data->rq, data->index); + VM_ASSERT(b->type == basket_type_reserved); + b->type = basket_type_deleted; + data->rq->reserved_cnt--; + } + RACTOR_UNLOCK_SELF(data->cr); + } + + rb_mutex_unlock(data->cr->receiving_mutex); + return Qnil; +} + +static VALUE +ractor_receive_if(rb_execution_context_t *ec, VALUE crv, VALUE b) +{ + if (!RTEST(b)) rb_raise(rb_eArgError, "no block given"); + + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + unsigned int serial = (unsigned int)-1; + int index = 0; + struct rb_ractor_queue *rq = &cr->sync.incoming_queue; + + while (1) { + VALUE v = Qundef; + + ractor_receive_wait(ec, cr); + + RACTOR_LOCK_SELF(cr); + { + if (serial != rq->serial) { + serial = rq->serial; + index = 0; + } + + // check newer version + for (int i=index; icnt; i++) { + if (!ractor_queue_skip_p(rq, i)) { + struct rb_ractor_basket *b = ractor_queue_at(rq, i); + v = ractor_basket_value(b); + b->type = basket_type_reserved; + rq->reserved_cnt++; + index = i; + break; + } + } + } + RACTOR_UNLOCK_SELF(cr); + + if (v != Qundef) { + struct receive_block_data data = { + .cr = cr, + .rq = rq, + .v = v, + .index = index, + .success = false, + }; + + VALUE result = rb_ensure(receive_if_body, (VALUE)&data, + receive_if_ensure, (VALUE)&data); + + if (result != Qundef) return result; + index++; + } + } +} + +static void +ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_basket *b) +{ + bool closed = false; + struct rb_ractor_queue *rq = &r->sync.incoming_queue; + + RACTOR_LOCK(r); + { + if (r->sync.incoming_port_closed) { + closed = true; + } + else { + ractor_queue_enq(r, rq, b); + if (ractor_wakeup(r, wait_receiving, wakeup_by_send)) { + RUBY_DEBUG_LOG("wakeup"); + } + } + } + RACTOR_UNLOCK(r); + + if (closed) { + rb_raise(rb_eRactorClosedError, "The incoming-port is already closed"); + } +} + +static VALUE ractor_move(VALUE obj); // in this file +static VALUE ractor_copy(VALUE obj); // in this file + +static void +ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc, bool is_will, bool is_yield) +{ + basket->sender = rb_ec_ractor_ptr(ec)->pub.self; + basket->exception = exc; + + if (is_will) { + basket->type = basket_type_will; + basket->v = obj; + } + else if (rb_ractor_shareable_p(obj)) { + basket->type = basket_type_ref; + basket->v = obj; + } + else if (!RTEST(move)) { + basket->v = ractor_copy(obj); + basket->type = basket_type_copy; + } + else { + basket->type = basket_type_move; + + if (is_yield) { + basket->v = obj; // call ractor_move() when yielding timing. + } + else { + basket->v = ractor_move(obj); + } + } +} + +static VALUE +ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move) +{ + struct rb_ractor_basket basket; + ractor_basket_setup(ec, &basket, obj, move, false, false, false); + ractor_send_basket(ec, r, &basket); + return r->pub.self; +} + +static VALUE +ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r) +{ + struct rb_ractor_basket basket = { + .type = basket_type_none, + }; + bool closed = false; + + RACTOR_LOCK(r); + { + if (ractor_sleeping_by(r, wait_yielding)) { + MAYBE_UNUSED(bool) wakeup_result; + VM_ASSERT(r->sync.wait.yielded_basket.type != basket_type_none); + + if (r->sync.wait.yielded_basket.type == basket_type_move) { + wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_retry); + } + else { + wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_take); + basket = r->sync.wait.yielded_basket; + ractor_basket_clear(&r->sync.wait.yielded_basket); + } + VM_ASSERT(wakeup_result); + } + else if (r->sync.outgoing_port_closed) { + closed = true; + } + } + RACTOR_UNLOCK(r); + + if (basket.type == basket_type_none) { + if (closed) { + rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed"); + } + else { + return Qundef; + } + } + else { + return ractor_basket_accept(&basket); + } +} + +static VALUE +ractor_yield_move_body(VALUE v) +{ + return ractor_move(v); +} + +static bool +ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_basket *basket) +{ + ASSERT_ractor_unlocking(cr); + VM_ASSERT(basket->type != basket_type_none); + + if (cr->sync.outgoing_port_closed) { + rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed"); + } + + rb_ractor_t *r; + + retry_shift: + RACTOR_LOCK(cr); + { + r = ractor_waiting_list_shift(cr, &cr->sync.taking_ractors); + } + RACTOR_UNLOCK(cr); + + if (r) { + bool retry_shift = false; + + RACTOR_LOCK(r); + { + if (ractor_sleeping_by(r, wait_taking)) { + VM_ASSERT(r->sync.wait.taken_basket.type == basket_type_none); + + if (basket->type == basket_type_move) { + enum ractor_wait_status prev_wait_status = r->sync.wait.status; + r->sync.wait.status = wait_moving; + + RACTOR_UNLOCK(r); + { + int state; + VALUE moved_value = rb_protect(ractor_yield_move_body, basket->v, &state); + if (state) { + r->sync.wait.status = prev_wait_status; + rb_jump_tag(state); + } + else { + basket->v = moved_value; + } + } + RACTOR_LOCK(r); + + if (!ractor_wakeup(r, wait_moving, wakeup_by_yield)) { + // terminating? + } + } + else { + ractor_wakeup(r, wait_taking, wakeup_by_yield); + } + r->sync.wait.taken_basket = *basket; + } + else { + retry_shift = true; + } + } + RACTOR_UNLOCK(r); + + if (retry_shift) { + // get candidate take-waiting ractor, but already woke up by another reason. + // retry to check another ractor. + goto retry_shift; + } + else { + return true; + } + } + else { + return false; + } +} + +// select(r1, r2, r3, receive: true, yield: obj) +static VALUE +ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VALUE yielded_value, bool move, VALUE *ret_r) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + VALUE crv = cr->pub.self; + VALUE ret = Qundef; + int i; + bool interrupted = false; + enum ractor_wait_status wait_status = 0; + bool yield_p = (yielded_value != Qundef) ? true : false; + const int alen = rs_len + (yield_p ? 1 : 0); + + struct ractor_select_action { + enum ractor_select_action_type { + ractor_select_action_take, + ractor_select_action_receive, + ractor_select_action_yield, + } type; + VALUE v; + } *actions = ALLOCA_N(struct ractor_select_action, alen); + + VM_ASSERT(cr->sync.wait.status == wait_none); + VM_ASSERT(cr->sync.wait.wakeup_status == wakeup_none); + VM_ASSERT(cr->sync.wait.taken_basket.type == basket_type_none); + VM_ASSERT(cr->sync.wait.yielded_basket.type == basket_type_none); + + // setup actions + for (i=0; isync.wait.yielded_basket, yielded_value, move, false, false, true); + } + + // TODO: shuffle actions + + while (1) { + RUBY_DEBUG_LOG("try actions (%s)", wait_status_str(wait_status)); + + for (i=0; isync.wait.yielded_basket)) { + *ret_r = ID2SYM(rb_intern("yield")); + ret = Qnil; + goto cleanup; + } + } + break; + } + } + + RUBY_DEBUG_LOG("wait actions (%s)", wait_status_str(wait_status)); + + RACTOR_LOCK(cr); + { + VM_ASSERT(cr->sync.wait.status == wait_none); + cr->sync.wait.status = wait_status; + cr->sync.wait.wakeup_status = wakeup_none; + } + RACTOR_UNLOCK(cr); + + // prepare waiting + for (i=0; isync.wait.wakeup_status == wakeup_none) { + for (i=0; ipub.id); + cr->sync.wait.wakeup_status = wakeup_by_retry; + goto skip_sleep; + } + break; + case ractor_select_action_receive: + if (cr->sync.incoming_queue.cnt > 0) { + RUBY_DEBUG_LOG("wakeup_none, but incoming_queue has %u messages", cr->sync.incoming_queue.cnt); + cr->sync.wait.wakeup_status = wakeup_by_retry; + goto skip_sleep; + } + break; + case ractor_select_action_yield: + if (cr->sync.taking_ractors.cnt > 0) { + RUBY_DEBUG_LOG("wakeup_none, but %u taking_ractors are waiting", cr->sync.taking_ractors.cnt); + cr->sync.wait.wakeup_status = wakeup_by_retry; + goto skip_sleep; + } + else if (cr->sync.outgoing_port_closed) { + cr->sync.wait.wakeup_status = wakeup_by_close; + goto skip_sleep; + } + break; + } + } + + RUBY_DEBUG_LOG("sleep %s", wait_status_str(cr->sync.wait.status)); + ractor_sleep(ec, cr); + RUBY_DEBUG_LOG("awaken %s", wakeup_status_str(cr->sync.wait.wakeup_status)); + } + else { + skip_sleep: + RUBY_DEBUG_LOG("no need to sleep %s->%s", + wait_status_str(cr->sync.wait.status), + wakeup_status_str(cr->sync.wait.wakeup_status)); + cr->sync.wait.status = wait_none; + } + } + RACTOR_UNLOCK(cr); + + // cleanup waiting + for (i=0; isync.taking_ractors, cr); + break; + case ractor_select_action_receive: + case ractor_select_action_yield: + break; + } + } + + // check results + enum ractor_wakeup_status wakeup_status = cr->sync.wait.wakeup_status; + cr->sync.wait.wakeup_status = wakeup_none; + + switch (wakeup_status) { + case wakeup_none: + // OK. something happens. + // retry loop. + break; + case wakeup_by_retry: + // Retry request. + break; + case wakeup_by_send: + // OK. + // retry loop and try_receive will succss. + break; + case wakeup_by_yield: + // take was succeeded! + // cr.wait.taken_basket contains passed block + VM_ASSERT(cr->sync.wait.taken_basket.type != basket_type_none); + *ret_r = cr->sync.wait.taken_basket.sender; + VM_ASSERT(rb_ractor_p(*ret_r)); + ret = ractor_basket_accept(&cr->sync.wait.taken_basket); + goto cleanup; + case wakeup_by_take: + *ret_r = ID2SYM(rb_intern("yield")); + ret = Qnil; + goto cleanup; + case wakeup_by_close: + // OK. + // retry loop and will get CloseError. + break; + case wakeup_by_interrupt: + ret = Qundef; + interrupted = true; + goto cleanup; + } + } + + cleanup: + RUBY_DEBUG_LOG("cleanup actions (%s)", wait_status_str(wait_status)); + + if (cr->sync.wait.yielded_basket.type != basket_type_none) { + ractor_basket_clear(&cr->sync.wait.yielded_basket); + } + + VM_ASSERT(cr->sync.wait.status == wait_none); + VM_ASSERT(cr->sync.wait.wakeup_status == wakeup_none); + VM_ASSERT(cr->sync.wait.taken_basket.type == basket_type_none); + VM_ASSERT(cr->sync.wait.yielded_basket.type == basket_type_none); + + if (interrupted) { + rb_vm_check_ints_blocking(ec); + interrupted = false; + goto restart; + } + + VM_ASSERT(ret != Qundef); + return ret; +} + +static VALUE +ractor_yield(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move) +{ + VALUE ret_r; + ractor_select(ec, NULL, 0, obj, RTEST(move) ? true : false, &ret_r); + return Qnil; +} + +static VALUE +ractor_take(rb_execution_context_t *ec, rb_ractor_t *r) +{ + VALUE ret_r; + VALUE v = ractor_select(ec, &r->pub.self, 1, Qundef, false, &ret_r); + return v; +} + +static VALUE +ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r) +{ + VALUE prev; + + RACTOR_LOCK(r); + { + if (!r->sync.incoming_port_closed) { + prev = Qfalse; + r->sync.incoming_port_closed = true; + if (ractor_wakeup(r, wait_receiving, wakeup_by_close)) { + VM_ASSERT(r->sync.incoming_queue.cnt == 0); + RUBY_DEBUG_LOG("cancel receiving"); + } + } + else { + prev = Qtrue; + } + } + RACTOR_UNLOCK(r); + return prev; +} + +static VALUE +ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r) +{ + VALUE prev; + + RACTOR_LOCK(r); + { + if (!r->sync.outgoing_port_closed) { + prev = Qfalse; + r->sync.outgoing_port_closed = true; + } + else { + prev = Qtrue; + } + + // wakeup all taking ractors + rb_ractor_t *taking_ractor; + while ((taking_ractor = ractor_waiting_list_shift(r, &r->sync.taking_ractors)) != NULL) { + RACTOR_LOCK(taking_ractor); + ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close); + RACTOR_UNLOCK(taking_ractor); + } + + // raising yielding Ractor + if (!r->yield_atexit && + ractor_wakeup(r, wait_yielding, wakeup_by_close)) { + RUBY_DEBUG_LOG("cancel yielding"); + } + } + RACTOR_UNLOCK(r); + return prev; +} + +// creation/termination + +static uint32_t +ractor_next_id(void) +{ + uint32_t id; + + id = (uint32_t)(RUBY_ATOMIC_FETCH_ADD(ractor_last_id, 1) + 1); + + return id; +} + +static void +vm_insert_ractor0(rb_vm_t *vm, rb_ractor_t *r, bool single_ractor_mode) +{ + RUBY_DEBUG_LOG("r:%u ractor.cnt:%u++", r->pub.id, vm->ractor.cnt); + VM_ASSERT(single_ractor_mode || RB_VM_LOCKED_P()); + + list_add_tail(&vm->ractor.set, &r->vmlr_node); + vm->ractor.cnt++; +} + +static void +cancel_single_ractor_mode(void) +{ + // enable multi-ractor mode + RUBY_DEBUG_LOG("enable multi-ractor mode"); + + VALUE was_disabled = rb_gc_enable(); + + rb_gc_start(); + rb_transient_heap_evacuate(); + + if (was_disabled) { + rb_gc_disable(); + } + + ruby_single_main_ractor = NULL; + + if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) { + rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL, + "Ractor is experimental, and the behavior may change in future versions of Ruby! " + "Also there are many implementation issues."); + } +} + +static void +vm_insert_ractor(rb_vm_t *vm, rb_ractor_t *r) +{ + VM_ASSERT(ractor_status_p(r, ractor_created)); + + if (rb_multi_ractor_p()) { + RB_VM_LOCK(); + { + vm_insert_ractor0(vm, r, false); + vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__); + } + RB_VM_UNLOCK(); + } + else { + if (vm->ractor.cnt == 0) { + // main ractor + vm_insert_ractor0(vm, r, true); + ractor_status_set(r, ractor_blocking); + ractor_status_set(r, ractor_running); + } + else { + cancel_single_ractor_mode(); + vm_insert_ractor0(vm, r, true); + vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__); + } + } +} + +static void +vm_remove_ractor(rb_vm_t *vm, rb_ractor_t *cr) +{ + VM_ASSERT(ractor_status_p(cr, ractor_running)); + VM_ASSERT(vm->ractor.cnt > 1); + VM_ASSERT(cr->threads.cnt == 1); + + RB_VM_LOCK(); + { + RUBY_DEBUG_LOG("ractor.cnt:%u-- terminate_waiting:%d", + vm->ractor.cnt, vm->ractor.sync.terminate_waiting); + + VM_ASSERT(vm->ractor.cnt > 0); + list_del(&cr->vmlr_node); + + if (vm->ractor.cnt <= 2 && vm->ractor.sync.terminate_waiting) { + rb_native_cond_signal(&vm->ractor.sync.terminate_cond); + } + vm->ractor.cnt--; + + /* Clear the cached freelist to prevent a memory leak. */ + rb_gc_ractor_newobj_cache_clear(&cr->newobj_cache); + + ractor_status_set(cr, ractor_terminated); + } + RB_VM_UNLOCK(); +} + +static VALUE +ractor_alloc(VALUE klass) +{ + rb_ractor_t *r; + VALUE rv = TypedData_Make_Struct(klass, rb_ractor_t, &ractor_data_type, r); + FL_SET_RAW(rv, RUBY_FL_SHAREABLE); + r->pub.self = rv; + VM_ASSERT(ractor_status_p(r, ractor_created)); + return rv; +} + +rb_ractor_t * +rb_ractor_main_alloc(void) +{ + rb_ractor_t *r = ruby_mimmalloc(sizeof(rb_ractor_t)); + if (r == NULL) { + fprintf(stderr, "[FATAL] failed to allocate memory for main ractor\n"); + exit(EXIT_FAILURE); + } + MEMZERO(r, rb_ractor_t, 1); + r->pub.id = ++ractor_last_id; + r->loc = Qnil; + r->name = Qnil; + r->pub.self = Qnil; + ruby_single_main_ractor = r; + + return r; +} + +#if defined(HAVE_WORKING_FORK) +void +rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th) +{ + // initialize as a main ractor + vm->ractor.cnt = 0; + vm->ractor.blocking_cnt = 0; + ruby_single_main_ractor = th->ractor; + th->ractor->status_ = ractor_created; + + rb_ractor_living_threads_init(th->ractor); + rb_ractor_living_threads_insert(th->ractor, th); + + VM_ASSERT(vm->ractor.blocking_cnt == 0); + VM_ASSERT(vm->ractor.cnt == 1); +} +#endif + +void rb_gvl_init(rb_global_vm_lock_t *gvl); + +void +rb_ractor_living_threads_init(rb_ractor_t *r) +{ + list_head_init(&r->threads.set); + r->threads.cnt = 0; + r->threads.blocking_cnt = 0; +} + +static void +ractor_init(rb_ractor_t *r, VALUE name, VALUE loc) +{ + ractor_queue_setup(&r->sync.incoming_queue); + rb_native_mutex_initialize(&r->sync.lock); + rb_native_cond_initialize(&r->sync.cond); + rb_native_cond_initialize(&r->barrier_wait_cond); + + // thread management + rb_gvl_init(&r->threads.gvl); + rb_ractor_living_threads_init(r); + + // naming + if (!NIL_P(name)) { + rb_encoding *enc; + StringValueCStr(name); + enc = rb_enc_get(name); + if (!rb_enc_asciicompat(enc)) { + rb_raise(rb_eArgError, "ASCII incompatible encoding (%s)", + rb_enc_name(enc)); + } + name = rb_str_new_frozen(name); + } + r->name = name; + r->loc = loc; +} + +void +rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *r, rb_thread_t *th) +{ + r->pub.self = TypedData_Wrap_Struct(rb_cRactor, &ractor_data_type, r); + FL_SET_RAW(r->pub.self, RUBY_FL_SHAREABLE); + ractor_init(r, Qnil, Qnil); + r->threads.main = th; + rb_ractor_living_threads_insert(r, th); +} + +static VALUE +ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VALUE args, VALUE block) +{ + VALUE rv = ractor_alloc(self); + rb_ractor_t *r = RACTOR_PTR(rv); + ractor_init(r, name, loc); + + // can block here + r->pub.id = ractor_next_id(); + RUBY_DEBUG_LOG("r:%u", r->pub.id); + + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + r->verbose = cr->verbose; + r->debug = cr->debug; + + rb_yjit_before_ractor_spawn(); + rb_thread_create_ractor(r, args, block); + + RB_GC_GUARD(rv); + return rv; +} + +static void +ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc) +{ + if (cr->sync.outgoing_port_closed) { + return; + } + + ASSERT_ractor_unlocking(cr); + + struct rb_ractor_basket basket; + ractor_basket_setup(ec, &basket, v, Qfalse, exc, true, true /* this flag is ignored because move is Qfalse */); + + retry: + if (ractor_try_yield(ec, cr, &basket)) { + // OK. + } + else { + bool retry = false; + RACTOR_LOCK(cr); + { + if (cr->sync.taking_ractors.cnt == 0) { + cr->sync.wait.yielded_basket = basket; + + VM_ASSERT(cr->sync.wait.status == wait_none); + cr->sync.wait.status = wait_yielding; + cr->sync.wait.wakeup_status = wakeup_none; + + VM_ASSERT(cr->yield_atexit == false); + cr->yield_atexit = true; + } + else { + retry = true; // another ractor is waiting for the yield. + } + } + RACTOR_UNLOCK(cr); + + if (retry) goto retry; + } +} + +void +rb_ractor_teardown(rb_execution_context_t *ec) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + ractor_close_incoming(ec, cr); + ractor_close_outgoing(ec, cr); + + // sync with rb_ractor_terminate_interrupt_main_thread() + RB_VM_LOCK_ENTER(); + { + VM_ASSERT(cr->threads.main != NULL); + cr->threads.main = NULL; + } + RB_VM_LOCK_LEAVE(); +} + +void +rb_ractor_atexit(rb_execution_context_t *ec, VALUE result) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + ractor_yield_atexit(ec, cr, result, false); +} + +void +rb_ractor_atexit_exception(rb_execution_context_t *ec) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + ractor_yield_atexit(ec, cr, ec->errinfo, true); +} + +void +rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *r, int len, VALUE *ptr) +{ + for (int i=0; iractor.main_ractor; +} + +bool +rb_obj_is_main_ractor(VALUE gv) +{ + if (!rb_ractor_p(gv)) return false; + rb_ractor_t *r = DATA_PTR(gv); + return r == GET_VM()->ractor.main_ractor; +} + +rb_global_vm_lock_t * +rb_ractor_gvl(rb_ractor_t *r) +{ + return &r->threads.gvl; +} + +int +rb_ractor_living_thread_num(const rb_ractor_t *r) +{ + return r->threads.cnt; +} + +VALUE +rb_ractor_thread_list(rb_ractor_t *r) +{ + rb_thread_t *th = 0; + VALUE *ts; + int ts_cnt; + + RACTOR_LOCK(r); + { + ts = ALLOCA_N(VALUE, r->threads.cnt); + ts_cnt = 0; + + list_for_each(&r->threads.set, th, lt_node) { + switch (th->status) { + case THREAD_RUNNABLE: + case THREAD_STOPPED: + case THREAD_STOPPED_FOREVER: + ts[ts_cnt++] = th->self; + default: + break; + } + } + } + RACTOR_UNLOCK(r); + + VALUE ary = rb_ary_new(); + for (int i=0; ithreads.cnt:%d++", r->pub.id, r->threads.cnt); + list_add_tail(&r->threads.set, &th->lt_node); + r->threads.cnt++; + } + RACTOR_UNLOCK(r); + + // first thread for a ractor + if (r->threads.cnt == 1) { + VM_ASSERT(ractor_status_p(r, ractor_created)); + vm_insert_ractor(th->vm, r); + } +} + +static void +vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *r, const char *file, int line) +{ + ractor_status_set(r, ractor_blocking); + + RUBY_DEBUG_LOG2(file, line, "vm->ractor.blocking_cnt:%d++", vm->ractor.blocking_cnt); + vm->ractor.blocking_cnt++; + VM_ASSERT(vm->ractor.blocking_cnt <= vm->ractor.cnt); +} + +void +rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line) +{ + ASSERT_vm_locking(); + VM_ASSERT(GET_RACTOR() == cr); + vm_ractor_blocking_cnt_inc(vm, cr, file, line); +} + +void +rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line) +{ + ASSERT_vm_locking(); + VM_ASSERT(GET_RACTOR() == cr); + + RUBY_DEBUG_LOG2(file, line, "vm->ractor.blocking_cnt:%d--", vm->ractor.blocking_cnt); + VM_ASSERT(vm->ractor.blocking_cnt > 0); + vm->ractor.blocking_cnt--; + + ractor_status_set(cr, ractor_running); +} + +static void +ractor_check_blocking(rb_ractor_t *cr, unsigned int remained_thread_cnt, const char *file, int line) +{ + VM_ASSERT(cr == GET_RACTOR()); + + RUBY_DEBUG_LOG2(file, line, + "cr->threads.cnt:%u cr->threads.blocking_cnt:%u vm->ractor.cnt:%u vm->ractor.blocking_cnt:%u", + cr->threads.cnt, cr->threads.blocking_cnt, + GET_VM()->ractor.cnt, GET_VM()->ractor.blocking_cnt); + + VM_ASSERT(cr->threads.cnt >= cr->threads.blocking_cnt + 1); + + if (remained_thread_cnt > 0 && + // will be block + cr->threads.cnt == cr->threads.blocking_cnt + 1) { + // change ractor status: running -> blocking + rb_vm_t *vm = GET_VM(); + ASSERT_vm_unlocking(); + + RB_VM_LOCK(); + { + rb_vm_ractor_blocking_cnt_inc(vm, cr, file, line); + } + RB_VM_UNLOCK(); + } +} + +void +rb_ractor_living_threads_remove(rb_ractor_t *cr, rb_thread_t *th) +{ + VM_ASSERT(cr == GET_RACTOR()); + RUBY_DEBUG_LOG("r->threads.cnt:%d--", cr->threads.cnt); + ractor_check_blocking(cr, cr->threads.cnt - 1, __FILE__, __LINE__); + + if (cr->threads.cnt == 1) { + vm_remove_ractor(th->vm, cr); + } + else { + RACTOR_LOCK(cr); + { + list_del(&th->lt_node); + cr->threads.cnt--; + } + RACTOR_UNLOCK(cr); + } +} + +void +rb_ractor_blocking_threads_inc(rb_ractor_t *cr, const char *file, int line) +{ + RUBY_DEBUG_LOG2(file, line, "cr->threads.blocking_cnt:%d++", cr->threads.blocking_cnt); + + VM_ASSERT(cr->threads.cnt > 0); + VM_ASSERT(cr == GET_RACTOR()); + + ractor_check_blocking(cr, cr->threads.cnt, __FILE__, __LINE__); + cr->threads.blocking_cnt++; +} + +void +rb_ractor_blocking_threads_dec(rb_ractor_t *cr, const char *file, int line) +{ + RUBY_DEBUG_LOG2(file, line, + "r->threads.blocking_cnt:%d--, r->threads.cnt:%u", + cr->threads.blocking_cnt, cr->threads.cnt); + + VM_ASSERT(cr == GET_RACTOR()); + + if (cr->threads.cnt == cr->threads.blocking_cnt) { + rb_vm_t *vm = GET_VM(); + + RB_VM_LOCK_ENTER(); + { + rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__); + } + RB_VM_LOCK_LEAVE(); + } + + cr->threads.blocking_cnt--; +} + +void +rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r) +{ + VM_ASSERT(r != GET_RACTOR()); + ASSERT_ractor_unlocking(r); + ASSERT_vm_locking(); + + RACTOR_LOCK(r); + { + if (ractor_status_p(r, ractor_running)) { + rb_execution_context_t *ec = r->threads.running_ec; + if (ec) { + RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec); + } + } + } + RACTOR_UNLOCK(r); +} + +void +rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r) +{ + VM_ASSERT(r != GET_RACTOR()); + ASSERT_ractor_unlocking(r); + ASSERT_vm_locking(); + + rb_thread_t *main_th = r->threads.main; + if (main_th) { + if (main_th->status != THREAD_KILLED) { + RUBY_VM_SET_TERMINATE_INTERRUPT(main_th->ec); + rb_threadptr_interrupt(main_th); + } + else { + RUBY_DEBUG_LOG("killed (%p)", (void *)main_th); + } + } +} + +void rb_thread_terminate_all(rb_thread_t *th); // thread.c + +static void +ractor_terminal_interrupt_all(rb_vm_t *vm) +{ + if (vm->ractor.cnt > 1) { + // send terminate notification to all ractors + rb_ractor_t *r = 0; + list_for_each(&vm->ractor.set, r, vmlr_node) { + if (r != vm->ractor.main_ractor) { + rb_ractor_terminate_interrupt_main_thread(r); + } + } + } +} + +void +rb_ractor_terminate_all(void) +{ + rb_vm_t *vm = GET_VM(); + rb_ractor_t *cr = vm->ractor.main_ractor; + + VM_ASSERT(cr == GET_RACTOR()); // only main-ractor's main-thread should kick it. + + if (vm->ractor.cnt > 1) { + RB_VM_LOCK(); + ractor_terminal_interrupt_all(vm); // kill all ractors + RB_VM_UNLOCK(); + } + rb_thread_terminate_all(GET_THREAD()); // kill other threads in main-ractor and wait + + RB_VM_LOCK(); + { + while (vm->ractor.cnt > 1) { + RUBY_DEBUG_LOG("terminate_waiting:%d", vm->ractor.sync.terminate_waiting); + vm->ractor.sync.terminate_waiting = true; + + // wait for 1sec + rb_vm_ractor_blocking_cnt_inc(vm, cr, __FILE__, __LINE__); + rb_vm_cond_timedwait(vm, &vm->ractor.sync.terminate_cond, 1000 /* ms */); + rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__); + + ractor_terminal_interrupt_all(vm); + } + } + RB_VM_UNLOCK(); +} + +rb_execution_context_t * +rb_vm_main_ractor_ec(rb_vm_t *vm) +{ + return vm->ractor.main_ractor->threads.running_ec; +} + +static VALUE +ractor_moved_missing(int argc, VALUE *argv, VALUE self) +{ + rb_raise(rb_eRactorMovedError, "can not send any methods to a moved object"); +} + +/* + * Document-class: Ractor::ClosedError + * + * Raised when an attempt is made to send a message to a closed port, + * or to retrieve a message from a closed and empty port. + * Ports may be closed explicitly with Ractor#close_outgoing/close_incoming + * and are closed implicitly when a Ractor terminates. + * + * r = Ractor.new { sleep(500) } + * r.close_outgoing + * r.take # Ractor::ClosedError + * + * ClosedError is a descendant of StopIteration, so the closing of the ractor will break + * the loops without propagating the error: + * + * r = Ractor.new do + * loop do + * msg = receive # raises ClosedError and loop traps it + * puts "Received: #{msg}" + * end + * puts "loop exited" + * end + * + * 3.times{|i| r << i} + * r.close_incoming + * r.take + * puts "Continue successfully" + * + * This will print: + * + * Received: 0 + * Received: 1 + * Received: 2 + * loop exited + * Continue successfully + */ + +/* + * Document-class: Ractor::RemoteError + * + * Raised on attempt to Ractor#take if there was an uncaught exception in the Ractor. + * Its +cause+ will contain the original exception, and +ractor+ is the original ractor + * it was raised in. + * + * r = Ractor.new { raise "Something weird happened" } + * + * begin + * r.take + * rescue => e + * p e # => # + * p e.ractor == r # => true + * p e.cause # => # + * end + * + */ + +/* + * Document-class: Ractor::MovedError + * + * Raised on an attempt to access an object which was moved in Ractor#send or Ractor.yield. + * + * r = Ractor.new { sleep } + * + * ary = [1, 2, 3] + * r.send(ary, move: true) + * ary.inspect + * # Ractor::MovedError (can not send any methods to a moved object) + * + */ + +/* + * Document-class: Ractor::MovedObject + * + * A special object which replaces any value that was moved to another ractor in Ractor#send + * or Ractor.yield. Any attempt to access the object results in Ractor::MovedError. + * + * r = Ractor.new { receive } + * + * ary = [1, 2, 3] + * r.send(ary, move: true) + * p Ractor::MovedObject === ary + * # => true + * ary.inspect + * # Ractor::MovedError (can not send any methods to a moved object) + */ + +// Main docs are in ractor.rb, but without this clause there are weird artifacts +// in their rendering. +/* + * Document-class: Ractor + * + */ + +void +Init_Ractor(void) +{ + rb_cRactor = rb_define_class("Ractor", rb_cObject); + rb_undef_alloc_func(rb_cRactor); + + rb_eRactorError = rb_define_class_under(rb_cRactor, "Error", rb_eRuntimeError); + rb_eRactorIsolationError = rb_define_class_under(rb_cRactor, "IsolationError", rb_eRactorError); + rb_eRactorRemoteError = rb_define_class_under(rb_cRactor, "RemoteError", rb_eRactorError); + rb_eRactorMovedError = rb_define_class_under(rb_cRactor, "MovedError", rb_eRactorError); + rb_eRactorClosedError = rb_define_class_under(rb_cRactor, "ClosedError", rb_eStopIteration); + rb_eRactorUnsafeError = rb_define_class_under(rb_cRactor, "UnsafeError", rb_eRactorError); + + rb_cRactorMovedObject = rb_define_class_under(rb_cRactor, "MovedObject", rb_cBasicObject); + rb_undef_alloc_func(rb_cRactorMovedObject); + rb_define_method(rb_cRactorMovedObject, "method_missing", ractor_moved_missing, -1); + + // override methods defined in BasicObject + rb_define_method(rb_cRactorMovedObject, "__send__", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "!", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "==", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "!=", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "__id__", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "equal?", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "instance_eval", ractor_moved_missing, -1); + rb_define_method(rb_cRactorMovedObject, "instance_exec", ractor_moved_missing, -1); +} + +void +rb_ractor_dump(void) +{ + rb_vm_t *vm = GET_VM(); + rb_ractor_t *r = 0; + + list_for_each(&vm->ractor.set, r, vmlr_node) { + if (r != vm->ractor.main_ractor) { + fprintf(stderr, "r:%u (%s)\n", r->pub.id, ractor_status_str(r->status_)); + } + } +} + +VALUE +rb_ractor_stdin(void) +{ + if (rb_ractor_main_p()) { + return rb_stdin; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + return cr->r_stdin; + } +} + +VALUE +rb_ractor_stdout(void) +{ + if (rb_ractor_main_p()) { + return rb_stdout; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + return cr->r_stdout; + } +} + +VALUE +rb_ractor_stderr(void) +{ + if (rb_ractor_main_p()) { + return rb_stderr; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + return cr->r_stderr; + } +} + +void +rb_ractor_stdin_set(VALUE in) +{ + if (rb_ractor_main_p()) { + rb_stdin = in; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + RB_OBJ_WRITE(cr->pub.self, &cr->r_stdin, in); + } +} + +void +rb_ractor_stdout_set(VALUE out) +{ + if (rb_ractor_main_p()) { + rb_stdout = out; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + RB_OBJ_WRITE(cr->pub.self, &cr->r_stdout, out); + } +} + +void +rb_ractor_stderr_set(VALUE err) +{ + if (rb_ractor_main_p()) { + rb_stderr = err; + } + else { + rb_ractor_t *cr = GET_RACTOR(); + RB_OBJ_WRITE(cr->pub.self, &cr->r_stderr, err); + } +} + +rb_hook_list_t * +rb_ractor_hooks(rb_ractor_t *cr) +{ + return &cr->pub.hooks; +} + +/// traverse function + +// 2: stop search +// 1: skip child +// 0: continue + +enum obj_traverse_iterator_result { + traverse_cont, + traverse_skip, + traverse_stop, +}; + +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_enter_func)(VALUE obj); +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_leave_func)(VALUE obj); +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_final_func)(VALUE obj); + +static enum obj_traverse_iterator_result null_leave(VALUE obj); + +struct obj_traverse_data { + rb_obj_traverse_enter_func enter_func; + rb_obj_traverse_leave_func leave_func; + + st_table *rec; + VALUE rec_hash; +}; + + +struct obj_traverse_callback_data { + bool stop; + struct obj_traverse_data *data; +}; + +static int obj_traverse_i(VALUE obj, struct obj_traverse_data *data); + +static int +obj_hash_traverse_i(VALUE key, VALUE val, VALUE ptr) +{ + struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr; + + if (obj_traverse_i(key, d->data)) { + d->stop = true; + return ST_STOP; + } + + if (obj_traverse_i(val, d->data)) { + d->stop = true; + return ST_STOP; + } + + return ST_CONTINUE; +} + +static void +obj_traverse_reachable_i(VALUE obj, void *ptr) +{ + struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr; + + if (obj_traverse_i(obj, d->data)) { + d->stop = true; + } +} + +static struct st_table * +obj_traverse_rec(struct obj_traverse_data *data) +{ + if (UNLIKELY(!data->rec)) { + data->rec_hash = rb_ident_hash_new(); + data->rec = rb_hash_st_table(data->rec_hash); + } + return data->rec; +} + +static int +obj_traverse_i(VALUE obj, struct obj_traverse_data *data) +{ + if (RB_SPECIAL_CONST_P(obj)) return 0; + + switch (data->enter_func(obj)) { + case traverse_cont: break; + case traverse_skip: return 0; // skip children + case traverse_stop: return 1; // stop search + } + + if (UNLIKELY(st_insert(obj_traverse_rec(data), obj, 1))) { + // already traversed + return 0; + } + + if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) { + struct gen_ivtbl *ivtbl; + rb_ivar_generic_ivtbl_lookup(obj, &ivtbl); + for (uint32_t i = 0; i < ivtbl->numiv; i++) { + VALUE val = ivtbl->ivptr[i]; + if (val != Qundef && obj_traverse_i(val, data)) return 1; + } + } + + switch (BUILTIN_TYPE(obj)) { + // no child node + case T_STRING: + case T_FLOAT: + case T_BIGNUM: + case T_REGEXP: + case T_FILE: + case T_SYMBOL: + case T_MATCH: + break; + + case T_OBJECT: + { + uint32_t len = ROBJECT_NUMIV(obj); + VALUE *ptr = ROBJECT_IVPTR(obj); + + for (uint32_t i=0; inum, data)) return 1; + if (obj_traverse_i(RRATIONAL(obj)->den, data)) return 1; + break; + case T_COMPLEX: + if (obj_traverse_i(RCOMPLEX(obj)->real, data)) return 1; + if (obj_traverse_i(RCOMPLEX(obj)->imag, data)) return 1; + break; + + case T_DATA: + case T_IMEMO: + { + struct obj_traverse_callback_data d = { + .stop = false, + .data = data, + }; + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d); + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); + if (d.stop) return 1; + } + break; + + // unreachable + case T_CLASS: + case T_MODULE: + case T_ICLASS: + default: + rp(obj); + rb_bug("unreachable"); + } + + if (data->leave_func(obj) == traverse_stop) { + return 1; + } + else { + return 0; + } +} + +struct rb_obj_traverse_final_data { + rb_obj_traverse_final_func final_func; + int stopped; +}; + +static int +obj_traverse_final_i(st_data_t key, st_data_t val, st_data_t arg) +{ + struct rb_obj_traverse_final_data *data = (void *)arg; + if (data->final_func(key)) { + data->stopped = 1; + return ST_STOP; + } + return ST_CONTINUE; +} + +// 0: traverse all +// 1: stopped +static int +rb_obj_traverse(VALUE obj, + rb_obj_traverse_enter_func enter_func, + rb_obj_traverse_leave_func leave_func, + rb_obj_traverse_final_func final_func) +{ + struct obj_traverse_data data = { + .enter_func = enter_func, + .leave_func = leave_func, + .rec = NULL, + }; + + if (obj_traverse_i(obj, &data)) return 1; + if (final_func && data.rec) { + struct rb_obj_traverse_final_data f = {final_func, 0}; + st_foreach(data.rec, obj_traverse_final_i, (st_data_t)&f); + return f.stopped; + } + return 0; +} + +static int +frozen_shareable_p(VALUE obj, bool *made_shareable) +{ + if (!RB_TYPE_P(obj, T_DATA)) { + return true; + } + else if (RTYPEDDATA_P(obj)) { + const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); + if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) { + return true; + } + else if (made_shareable && rb_obj_is_proc(obj)) { + // special path to make shareable Proc. + rb_proc_ractor_make_shareable(obj); + *made_shareable = true; + VM_ASSERT(RB_OBJ_SHAREABLE_P(obj)); + return false; + } + } + + return false; +} + +static enum obj_traverse_iterator_result +make_shareable_check_shareable(VALUE obj) +{ + VM_ASSERT(!SPECIAL_CONST_P(obj)); + bool made_shareable = false; + + if (rb_ractor_shareable_p(obj)) { + return traverse_skip; + } + else if (!frozen_shareable_p(obj, &made_shareable)) { + if (made_shareable) { + return traverse_skip; + } + else { + rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj); + } + } + + if (!RB_OBJ_FROZEN_RAW(obj)) { + rb_funcall(obj, idFreeze, 0); + + if (UNLIKELY(!RB_OBJ_FROZEN_RAW(obj))) { + rb_raise(rb_eRactorError, "#freeze does not freeze object correctly"); + } + + if (RB_OBJ_SHAREABLE_P(obj)) { + return traverse_skip; + } + } + + return traverse_cont; +} + +static enum obj_traverse_iterator_result +mark_shareable(VALUE obj) +{ + FL_SET_RAW(obj, RUBY_FL_SHAREABLE); + return traverse_cont; +} + +VALUE +rb_ractor_make_shareable(VALUE obj) +{ + rb_obj_traverse(obj, + make_shareable_check_shareable, + null_leave, mark_shareable); + return obj; +} + +VALUE +rb_ractor_make_shareable_copy(VALUE obj) +{ + VALUE copy = ractor_copy(obj); + rb_obj_traverse(copy, + make_shareable_check_shareable, + null_leave, mark_shareable); + return copy; +} + +VALUE +rb_ractor_ensure_shareable(VALUE obj, VALUE name) +{ + if (!rb_ractor_shareable_p(obj)) { + VALUE message = rb_sprintf("cannot assign unshareable object to %"PRIsVALUE, + name); + rb_exc_raise(rb_exc_new_str(rb_eRactorIsolationError, message)); + } + return obj; +} + +static enum obj_traverse_iterator_result +shareable_p_enter(VALUE obj) +{ + if (RB_OBJ_SHAREABLE_P(obj)) { + return traverse_skip; + } + else if (RB_TYPE_P(obj, T_CLASS) || + RB_TYPE_P(obj, T_MODULE) || + RB_TYPE_P(obj, T_ICLASS)) { + // TODO: remove it + mark_shareable(obj); + return traverse_skip; + } + else if (RB_OBJ_FROZEN_RAW(obj) && + frozen_shareable_p(obj, NULL)) { + return traverse_cont; + } + + return traverse_stop; // fail +} + +MJIT_FUNC_EXPORTED bool +rb_ractor_shareable_p_continue(VALUE obj) +{ + if (rb_obj_traverse(obj, + shareable_p_enter, null_leave, + mark_shareable)) { + return false; + } + else { + return true; + } +} + +#if RACTOR_CHECK_MODE > 0 +static enum obj_traverse_iterator_result +reset_belonging_enter(VALUE obj) +{ + if (rb_ractor_shareable_p(obj)) { + return traverse_skip; + } + else { + rb_ractor_setup_belonging(obj); + return traverse_cont; + } +} +#endif + +static enum obj_traverse_iterator_result +null_leave(VALUE obj) +{ + return traverse_cont; +} + +static VALUE +ractor_reset_belonging(VALUE obj) +{ +#if RACTOR_CHECK_MODE > 0 + rb_obj_traverse(obj, reset_belonging_enter, null_leave, NULL); +#endif + return obj; +} + + +/// traverse and replace function + +// 2: stop search +// 1: skip child +// 0: continue + +struct obj_traverse_replace_data; +static int obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data); +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_enter_func)(VALUE obj, struct obj_traverse_replace_data *data); +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_leave_func)(VALUE obj, struct obj_traverse_replace_data *data); + +struct obj_traverse_replace_data { + rb_obj_traverse_replace_enter_func enter_func; + rb_obj_traverse_replace_leave_func leave_func; + + st_table *rec; + VALUE rec_hash; + + VALUE replacement; + bool move; +}; + +struct obj_traverse_replace_callback_data { + bool stop; + VALUE src; + struct obj_traverse_replace_data *data; +}; + +static int +obj_hash_traverse_replace_foreach_i(st_data_t key, st_data_t value, st_data_t argp, int error) +{ + return ST_REPLACE; +} + +static int +obj_hash_traverse_replace_i(st_data_t *key, st_data_t *val, st_data_t ptr, int exists) +{ + struct obj_traverse_replace_callback_data *d = (struct obj_traverse_replace_callback_data *)ptr; + struct obj_traverse_replace_data *data = d->data; + + if (obj_traverse_replace_i(*key, data)) { + d->stop = true; + return ST_STOP; + } + else if (*key != data->replacement) { + VALUE v = *key = data->replacement; + RB_OBJ_WRITTEN(d->src, Qundef, v); + } + + if (obj_traverse_replace_i(*val, data)) { + d->stop = true; + return ST_STOP; + } + else if (*val != data->replacement) { + VALUE v = *val = data->replacement; + RB_OBJ_WRITTEN(d->src, Qundef, v); + } + + return ST_CONTINUE; +} + +static struct st_table * +obj_traverse_replace_rec(struct obj_traverse_replace_data *data) +{ + if (UNLIKELY(!data->rec)) { + data->rec_hash = rb_ident_hash_new(); + data->rec = rb_hash_st_table(data->rec_hash); + } + return data->rec; +} + +#if USE_TRANSIENT_HEAP +void rb_ary_transient_heap_evacuate(VALUE ary, int promote); +void rb_obj_transient_heap_evacuate(VALUE obj, int promote); +void rb_hash_transient_heap_evacuate(VALUE hash, int promote); +void rb_struct_transient_heap_evacuate(VALUE st, int promote); +#endif + +static void +obj_refer_only_shareables_p_i(VALUE obj, void *ptr) +{ + int *pcnt = (int *)ptr; + + if (!rb_ractor_shareable_p(obj)) { + pcnt++; + } +} + +static int +obj_refer_only_shareables_p(VALUE obj) +{ + int cnt = 0; + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt); + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); + return cnt == 0; +} + +static int +obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data) +{ + VALUE replacement; + + if (RB_SPECIAL_CONST_P(obj)) { + data->replacement = obj; + return 0; + } + + switch (data->enter_func(obj, data)) { + case traverse_cont: break; + case traverse_skip: return 0; // skip children + case traverse_stop: return 1; // stop search + } + + replacement = data->replacement; + + if (UNLIKELY(st_lookup(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t *)&replacement))) { + data->replacement = replacement; + return 0; + } + else { + st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t)replacement); + } + + if (!data->move) { + obj = replacement; + } + +#define CHECK_AND_REPLACE(v) do { \ + VALUE _val = (v); \ + if (obj_traverse_replace_i(_val, data)) { return 1; } \ + else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \ +} while (0) + + if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) { + struct gen_ivtbl *ivtbl; + rb_ivar_generic_ivtbl_lookup(obj, &ivtbl); + for (uint32_t i = 0; i < ivtbl->numiv; i++) { + if (ivtbl->ivptr[i] != Qundef) { + CHECK_AND_REPLACE(ivtbl->ivptr[i]); + } + } + } + + switch (BUILTIN_TYPE(obj)) { + // no child node + case T_FLOAT: + case T_BIGNUM: + case T_REGEXP: + case T_FILE: + case T_SYMBOL: + case T_MATCH: + break; + case T_STRING: + rb_str_make_independent(obj); + break; + + case T_OBJECT: + { +#if USE_TRANSIENT_HEAP + if (data->move) rb_obj_transient_heap_evacuate(obj, TRUE); +#endif + + uint32_t len = ROBJECT_NUMIV(obj); + VALUE *ptr = ROBJECT_IVPTR(obj); + + for (uint32_t i=0; imove) rb_ary_transient_heap_evacuate(obj, TRUE); +#endif + + for (int i = 0; i < RARRAY_LENINT(obj); i++) { + VALUE e = rb_ary_entry(obj, i); + + if (obj_traverse_replace_i(e, data)) { + return 1; + } + else if (e != data->replacement) { + RARRAY_ASET(obj, i, data->replacement); + } + } + RB_GC_GUARD(obj); + } + break; + + case T_HASH: + { +#if USE_TRANSIENT_HEAP + if (data->move) rb_hash_transient_heap_evacuate(obj, TRUE); +#endif + struct obj_traverse_replace_callback_data d = { + .stop = false, + .data = data, + .src = obj, + }; + rb_hash_stlike_foreach_with_replace(obj, + obj_hash_traverse_replace_foreach_i, + obj_hash_traverse_replace_i, + (VALUE)&d); + if (d.stop) return 1; + // TODO: rehash here? + + VALUE ifnone = RHASH_IFNONE(obj); + if (obj_traverse_replace_i(ifnone, data)) { + return 1; + } + else if (ifnone != data->replacement) { + RHASH_SET_IFNONE(obj, data->replacement); + } + } + break; + + case T_STRUCT: + { +#if USE_TRANSIENT_HEAP + if (data->move) rb_struct_transient_heap_evacuate(obj, TRUE); +#endif + long len = RSTRUCT_LEN(obj); + const VALUE *ptr = RSTRUCT_CONST_PTR(obj); + + for (long i=0; inum); + CHECK_AND_REPLACE(RRATIONAL(obj)->den); + break; + case T_COMPLEX: + CHECK_AND_REPLACE(RCOMPLEX(obj)->real); + CHECK_AND_REPLACE(RCOMPLEX(obj)->imag); + break; + + case T_DATA: + if (!data->move && obj_refer_only_shareables_p(obj)) { + break; + } + else { + rb_raise(rb_eRactorError, "can not %s %"PRIsVALUE" object.", + data->move ? "move" : "copy", rb_class_of(obj)); + } + + case T_IMEMO: + // not supported yet + return 1; + + // unreachable + case T_CLASS: + case T_MODULE: + case T_ICLASS: + default: + rp(obj); + rb_bug("unreachable"); + } + + data->replacement = replacement; + + if (data->leave_func(obj, data) == traverse_stop) { + return 1; + } + else { + return 0; + } +} + +// 0: traverse all +// 1: stopped +static VALUE +rb_obj_traverse_replace(VALUE obj, + rb_obj_traverse_replace_enter_func enter_func, + rb_obj_traverse_replace_leave_func leave_func, + bool move) +{ + struct obj_traverse_replace_data data = { + .enter_func = enter_func, + .leave_func = leave_func, + .rec = NULL, + .replacement = Qundef, + .move = move, + }; + + if (obj_traverse_replace_i(obj, &data)) { + return Qundef; + } + else { + return data.replacement; + } +} + +struct RVALUE { + VALUE flags; + VALUE klass; + VALUE v1; + VALUE v2; + VALUE v3; +}; + +static const VALUE fl_users = FL_USER1 | FL_USER2 | FL_USER3 | + FL_USER4 | FL_USER5 | FL_USER6 | FL_USER7 | + FL_USER8 | FL_USER9 | FL_USER10 | FL_USER11 | + FL_USER12 | FL_USER13 | FL_USER14 | FL_USER15 | + FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19; + +static void +ractor_moved_bang(VALUE obj) +{ + // invalidate src object + struct RVALUE *rv = (void *)obj; + + rv->klass = rb_cRactorMovedObject; + rv->v1 = 0; + rv->v2 = 0; + rv->v3 = 0; + rv->flags = rv->flags & ~fl_users; + + // TODO: record moved location +} + +static enum obj_traverse_iterator_result +move_enter(VALUE obj, struct obj_traverse_replace_data *data) +{ + if (rb_ractor_shareable_p(obj)) { + data->replacement = obj; + return traverse_skip; + } + else { + data->replacement = rb_obj_alloc(RBASIC_CLASS(obj)); + return traverse_cont; + } +} + +void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c + +static enum obj_traverse_iterator_result +move_leave(VALUE obj, struct obj_traverse_replace_data *data) +{ + VALUE v = data->replacement; + struct RVALUE *dst = (struct RVALUE *)v; + struct RVALUE *src = (struct RVALUE *)obj; + + dst->flags = (dst->flags & ~fl_users) | (src->flags & fl_users); + + dst->v1 = src->v1; + dst->v2 = src->v2; + dst->v3 = src->v3; + + if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) { + rb_replace_generic_ivar(v, obj); + } + + // TODO: generic_ivar + + ractor_moved_bang(obj); + return traverse_cont; +} + +static VALUE +ractor_move(VALUE obj) +{ + VALUE val = rb_obj_traverse_replace(obj, move_enter, move_leave, true); + if (val != Qundef) { + return val; + } + else { + rb_raise(rb_eRactorError, "can not move the object"); + } +} + +static enum obj_traverse_iterator_result +copy_enter(VALUE obj, struct obj_traverse_replace_data *data) +{ + if (rb_ractor_shareable_p(obj)) { + data->replacement = obj; + return traverse_skip; + } + else { + data->replacement = rb_obj_clone(obj); + return traverse_cont; + } +} + +static enum obj_traverse_iterator_result +copy_leave(VALUE obj, struct obj_traverse_replace_data *data) +{ + return traverse_cont; +} + +static VALUE +ractor_copy(VALUE obj) +{ + VALUE val = rb_obj_traverse_replace(obj, copy_enter, copy_leave, false); + if (val != Qundef) { + return val; + } + else { + rb_raise(rb_eRactorError, "can not copy the object"); + } +} + +// Ractor local storage + +struct rb_ractor_local_key_struct { + const struct rb_ractor_local_storage_type *type; + void *main_cache; +}; + +static struct freed_ractor_local_keys_struct { + int cnt; + int capa; + rb_ractor_local_key_t *keys; +} freed_ractor_local_keys; + +static int +ractor_local_storage_mark_i(st_data_t key, st_data_t val, st_data_t dmy) +{ + struct rb_ractor_local_key_struct *k = (struct rb_ractor_local_key_struct *)key; + if (k->type->mark) (*k->type->mark)((void *)val); + return ST_CONTINUE; +} + +static enum rb_id_table_iterator_result +idkey_local_storage_mark_i(ID id, VALUE val, void *dmy) +{ + rb_gc_mark(val); + return ID_TABLE_CONTINUE; +} + +static void +ractor_local_storage_mark(rb_ractor_t *r) +{ + if (r->local_storage) { + st_foreach(r->local_storage, ractor_local_storage_mark_i, 0); + + for (int i=0; ilocal_storage, (st_data_t *)&key, &val) && + key->type->free) { + (*key->type->free)((void *)val); + } + } + } + + if (r->idkey_local_storage) { + rb_id_table_foreach(r->idkey_local_storage, idkey_local_storage_mark_i, NULL); + } +} + +static int +ractor_local_storage_free_i(st_data_t key, st_data_t val, st_data_t dmy) +{ + struct rb_ractor_local_key_struct *k = (struct rb_ractor_local_key_struct *)key; + if (k->type->free) (*k->type->free)((void *)val); + return ST_CONTINUE; +} + +static void +ractor_local_storage_free(rb_ractor_t *r) +{ + if (r->local_storage) { + st_foreach(r->local_storage, ractor_local_storage_free_i, 0); + st_free_table(r->local_storage); + } + + if (r->idkey_local_storage) { + rb_id_table_free(r->idkey_local_storage); + } +} + +static void +rb_ractor_local_storage_value_mark(void *ptr) +{ + rb_gc_mark((VALUE)ptr); +} + +static const struct rb_ractor_local_storage_type ractor_local_storage_type_null = { + NULL, + NULL, +}; + +const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free = { + NULL, + ruby_xfree, +}; + +static const struct rb_ractor_local_storage_type ractor_local_storage_type_value = { + rb_ractor_local_storage_value_mark, + NULL, +}; + +rb_ractor_local_key_t +rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type) +{ + rb_ractor_local_key_t key = ALLOC(struct rb_ractor_local_key_struct); + key->type = type ? type : &ractor_local_storage_type_null; + key->main_cache = (void *)Qundef; + return key; +} + +rb_ractor_local_key_t +rb_ractor_local_storage_value_newkey(void) +{ + return rb_ractor_local_storage_ptr_newkey(&ractor_local_storage_type_value); +} + +void +rb_ractor_local_storage_delkey(rb_ractor_local_key_t key) +{ + RB_VM_LOCK_ENTER(); + { + if (freed_ractor_local_keys.cnt == freed_ractor_local_keys.capa) { + freed_ractor_local_keys.capa = freed_ractor_local_keys.capa ? freed_ractor_local_keys.capa * 2 : 4; + REALLOC_N(freed_ractor_local_keys.keys, rb_ractor_local_key_t, freed_ractor_local_keys.capa); + } + freed_ractor_local_keys.keys[freed_ractor_local_keys.cnt++] = key; + } + RB_VM_LOCK_LEAVE(); +} + +static bool +ractor_local_ref(rb_ractor_local_key_t key, void **pret) +{ + if (rb_ractor_main_p()) { + if ((VALUE)key->main_cache != Qundef) { + *pret = key->main_cache; + return true; + } + else { + return false; + } + } + else { + rb_ractor_t *cr = GET_RACTOR(); + + if (cr->local_storage && st_lookup(cr->local_storage, (st_data_t)key, (st_data_t *)pret)) { + return true; + } + else { + return false; + } + } +} + +static void +ractor_local_set(rb_ractor_local_key_t key, void *ptr) +{ + rb_ractor_t *cr = GET_RACTOR(); + + if (cr->local_storage == NULL) { + cr->local_storage = st_init_numtable(); + } + + st_insert(cr->local_storage, (st_data_t)key, (st_data_t)ptr); + + if (rb_ractor_main_p()) { + key->main_cache = ptr; + } +} + +VALUE +rb_ractor_local_storage_value(rb_ractor_local_key_t key) +{ + VALUE val; + if (ractor_local_ref(key, (void **)&val)) { + return val; + } + else { + return Qnil; + } +} + +bool +rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val) +{ + if (ractor_local_ref(key, (void **)val)) { + return true; + } + else { + return false; + } +} + +void +rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val) +{ + ractor_local_set(key, (void *)val); +} + +void * +rb_ractor_local_storage_ptr(rb_ractor_local_key_t key) +{ + void *ret; + if (ractor_local_ref(key, &ret)) { + return ret; + } + else { + return NULL; + } +} + +void +rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr) +{ + ractor_local_set(key, ptr); +} + +#define DEFAULT_KEYS_CAPA 0x10 + +void +rb_ractor_finish_marking(void) +{ + for (int i=0; i DEFAULT_KEYS_CAPA) { + freed_ractor_local_keys.capa = DEFAULT_KEYS_CAPA; + REALLOC_N(freed_ractor_local_keys.keys, rb_ractor_local_key_t, DEFAULT_KEYS_CAPA); + } +} + +static VALUE +ractor_local_value(rb_execution_context_t *ec, VALUE self, VALUE sym) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + ID id = rb_check_id(&sym); + struct rb_id_table *tbl = cr->idkey_local_storage; + VALUE val; + + if (id && tbl && rb_id_table_lookup(tbl, id, &val)) { + return val; + } + else { + return Qnil; + } +} + +static VALUE +ractor_local_value_set(rb_execution_context_t *ec, VALUE self, VALUE sym, VALUE val) +{ + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + ID id = SYM2ID(rb_to_symbol(sym)); + struct rb_id_table *tbl = cr->idkey_local_storage; + + if (tbl == NULL) { + tbl = cr->idkey_local_storage = rb_id_table_create(2); + } + rb_id_table_insert(tbl, id, val); + return val; +} + +#include "ractor.rbinc" diff --git a/ruby/ractor.rb b/ruby/ractor.rb new file mode 100644 index 000000000..ef36b2937 --- /dev/null +++ b/ruby/ractor.rb @@ -0,0 +1,838 @@ +# Ractor is a Actor-model abstraction for Ruby that provides thread-safe parallel execution. +# +# Ractor.new can make a new Ractor, and it will run in parallel. +# +# # The simplest ractor +# r = Ractor.new {puts "I am in Ractor!"} +# r.take # wait for it to finish +# # here "I am in Ractor!" would be printed +# +# Ractors do not share usual objects, so the same kinds of thread-safety concerns such as data-race, +# race-conditions are not available on multi-ractor programming. +# +# To achieve this, ractors severely limit object sharing between different ractors. +# For example, unlike threads, ractors can't access each other's objects, nor any objects through +# variables of the outer scope. +# +# a = 1 +# r = Ractor.new {puts "I am in Ractor! a=#{a}"} +# # fails immediately with +# # ArgumentError (can not isolate a Proc because it accesses outer variables (a).) +# +# On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is held per ractor, so +# ractors are performed in parallel without locking each other. +# +# Instead of accessing the shared state, the objects should be passed to and from ractors via +# sending and receiving objects as messages. +# +# a = 1 +# r = Ractor.new do +# a_in_ractor = receive # receive blocks till somebody will pass message +# puts "I am in Ractor! a=#{a_in_ractor}" +# end +# r.send(a) # pass it +# r.take +# # here "I am in Ractor! a=1" would be printed +# +# There are two pairs of methods for sending/receiving messages: +# +# * Ractor#send and Ractor.receive for when the _sender_ knows the receiver (push); +# * Ractor.yield and Ractor#take for when the _receiver_ knows the sender (pull); +# +# In addition to that, an argument to Ractor.new would be passed to block and available there +# as if received by Ractor.receive, and the last block value would be sent outside of the +# ractor as if sent by Ractor.yield. +# +# A little demonstration on a classic ping-pong: +# +# server = Ractor.new do +# puts "Server starts: #{self.inspect}" +# puts "Server sends: ping" +# Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested +# received = Ractor.receive # The server doesn't know the sender and receives from whoever sent +# puts "Server received: #{received}" +# end +# +# client = Ractor.new(server) do |srv| # The server is sent inside client, and available as srv +# puts "Client starts: #{self.inspect}" +# received = srv.take # The Client takes a message specifically from the server +# puts "Client received from " \ +# "#{srv.inspect}: #{received}" +# puts "Client sends to " \ +# "#{srv.inspect}: pong" +# srv.send 'pong' # The client sends a message specifically to the server +# end +# +# [client, server].each(&:take) # Wait till they both finish +# +# This will output: +# +# Server starts: # +# Server sends: ping +# Client starts: # +# Client received from #: ping +# Client sends to #: pong +# Server received: pong +# +# It is said that Ractor receives messages via the incoming port, and sends them +# to the outgoing port. Either one can be disabled with Ractor#close_incoming and +# Ractor#close_outgoing respectively. If a ractor terminated, its ports will be closed +# automatically. +# +# == Shareable and unshareable objects +# +# When the object is sent to and from the ractor, it is important to understand whether the +# object is shareable or unshareable. Most of objects are unshareable objects. +# +# Shareable objects are basically those which can be used by several threads without compromising +# thread-safety; e.g. immutable ones. Ractor.shareable? allows to check this, and Ractor.make_shareable +# tries to make object shareable if it is not. +# +# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are +# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true +# Ractor.shareable?('foo'.freeze) #=> true +# +# ary = ['hello', 'world'] +# ary.frozen? #=> false +# ary[0].frozen? #=> false +# Ractor.make_shareable(ary) +# ary.frozen? #=> true +# ary[0].frozen? #=> true +# ary[1].frozen? #=> true +# +# When a shareable object is sent (via #send or Ractor.yield), no additional processing happens, +# and it just becomes usable by both ractors. When an unshareable object is sent, it can be +# either _copied_ or _moved_. The first is the default, and it makes the object's full copy by +# deep cloning of non-shareable parts of its structure. +# +# data = ['foo', 'bar'.freeze] +# r = Ractor.new do +# data2 = Ractor.receive +# puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}" +# end +# r.send(data) +# r.take +# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}" +# +# This will output: +# +# In ractor: 340, 360, 320 +# Outside : 380, 400, 320 +# +# (Note that object id of both array and non-frozen string inside array have changed inside +# the ractor, showing it is different objects. But the second array's element, which is a +# shareable frozen string, has the same object_id.) +# +# Deep cloning of the objects may be slow, and sometimes impossible. Alternatively, +# move: true may be used on sending. This will move the object to the +# receiving ractor, making it inaccessible for a sending ractor. +# +# data = ['foo', 'bar'] +# r = Ractor.new do +# data_in_ractor = Ractor.receive +# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}" +# end +# r.send(data, move: true) +# r.take +# puts "Outside: moved? #{Ractor::MovedObject === data}" +# puts "Outside: #{data.inspect}" +# +# This will output: +# +# In ractor: 100, 120 +# Outside: moved? true +# test.rb:9:in `method_missing': can not send any methods to a moved object (Ractor::MovedError) +# +# Notice that even +inspect+ (and more basic methods like __id__) is inaccessible +# on a moved object. +# +# Besides frozen objects, there are shareable objects. Class and Module objects are shareable so +# the Class/Module definitions are shared between ractors. Ractor objects are also shareable objects. +# All operations for the shareable mutable objects are thread-safe, so the thread-safety property +# will be kept. We can not define mutable shareable objects in Ruby, but C extensions can introduce them. +# +# It is prohibited to access instance variables of mutable shareable objects (especially Modules and classes) +# from ractors other than main: +# +# class C +# class << self +# attr_accessor :tricky +# end +# end +# +# C.tricky = 'test' +# +# r = Ractor.new(C) do |cls| +# puts "I see #{cls}" +# puts "I can't see #{cls.tricky}" +# end +# r.take +# # I see C +# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError) +# +# Ractors can access constants if they are shareable. The main Ractor is the only one that can +# access non-shareable constants. +# +# GOOD = 'good'.freeze +# BAD = 'bad' +# +# r = Ractor.new do +# puts "GOOD=#{GOOD}" +# puts "BAD=#{BAD}" +# end +# r.take +# # GOOD=good +# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError) +# +# # Consider the same C class from above +# +# r = Ractor.new do +# puts "I see #{C}" +# puts "I can't see #{C.tricky}" +# end +# r.take +# # I see C +# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError) +# +# See also the description of # shareable_constant_value pragma in +# {Comments syntax}[rdoc-ref:syntax/comments.rdoc] explanation. +# +# == Ractors vs threads +# +# Each ractor creates its own thread. New threads can be created from inside ractor +# (and, on CRuby, sharing GVL with other threads of this ractor). +# +# r = Ractor.new do +# a = 1 +# Thread.new {puts "Thread in ractor: a=#{a}"}.join +# end +# r.take +# # Here "Thread in ractor: a=1" will be printed +# +# == Note on code examples +# +# In examples below, sometimes we use the following method to wait till ractors that +# are not currently blocked will finish (or process till next blocking) method. +# +# def wait +# sleep(0.1) +# end +# +# It is **only for demonstration purposes** and shouldn't be used in a real code. +# Most of the times, just #take is used to wait till ractor will finish. +# +# == Reference +# +# See {Ractor design doc}[rdoc-ref:ractor.md] for more details. +# +class Ractor + # + # call-seq: + # Ractor.new(*args, name: nil) {|*args| block } -> ractor + # + # Create a new Ractor with args and a block. + # + # A block (Proc) will be isolated (can't access to outer variables). +self+ + # inside the block will refer to the current Ractor. + # + # r = Ractor.new { puts "Hi, I am #{self.inspect}" } + # r.take + # # Prints "Hi, I am #" + # + # +args+ passed to the method would be propagated to block args by the same rules as + # objects passed through #send/Ractor.receive: if +args+ are not shareable, they + # will be copied (via deep cloning, which might be inefficient). + # + # arg = [1, 2, 3] + # puts "Passing: #{arg} (##{arg.object_id})" + # r = Ractor.new(arg) {|received_arg| + # puts "Received: #{received_arg} (##{received_arg.object_id})" + # } + # r.take + # # Prints: + # # Passing: [1, 2, 3] (#280) + # # Received: [1, 2, 3] (#300) + # + # Ractor's +name+ can be set for debugging purposes: + # + # r = Ractor.new(name: 'my ractor') {} + # p r + # #=> # + # + def self.new(*args, name: nil, &block) + b = block # TODO: builtin bug + raise ArgumentError, "must be called with a block" unless block + loc = caller_locations(1, 1).first + loc = "#{loc.path}:#{loc.lineno}" + __builtin_ractor_create(loc, name, args, b) + end + + # Returns the currently executing Ractor. + # + # Ractor.current #=> # + def self.current + __builtin_cexpr! %q{ + rb_ractor_self(rb_ec_ractor_ptr(ec)); + } + end + + # Returns total count of Ractors currently running. + # + # Ractor.count #=> 1 + # r = Ractor.new(name: 'example') { Ractor.yield(1) } + # Ractor.count #=> 2 (main + example ractor) + # r.take # wait for Ractor.yield(1) + # r.take # wait till r will finish + # Ractor.count #=> 1 + def self.count + __builtin_cexpr! %q{ + ULONG2NUM(GET_VM()->ractor.cnt); + } + end + + # + # call-seq: + # Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj] + # + # Waits for the first ractor to have something in its outgoing port, reads from this ractor, and + # returns that ractor and the object received. + # + # r1 = Ractor.new {Ractor.yield 'from 1'} + # r2 = Ractor.new {Ractor.yield 'from 2'} + # + # r, obj = Ractor.select(r1, r2) + # + # puts "received #{obj.inspect} from #{r.inspect}" + # # Prints: received "from 1" from # + # + # If one of the given ractors is the current ractor, and it would be selected, +r+ will contain + # +:receive+ symbol instead of the ractor object. + # + # r1 = Ractor.new(Ractor.current) do |main| + # main.send 'to main' + # Ractor.yield 'from 1' + # end + # r2 = Ractor.new do + # Ractor.yield 'from 2' + # end + # + # r, obj = Ractor.select(r1, r2, Ractor.current) + # puts "received #{obj.inspect} from #{r.inspect}" + # # Prints: received "to main" from :receive + # + # If +yield_value+ is provided, that value may be yielded if another Ractor is calling #take. + # In this case, the pair [:yield, nil] would be returned: + # + # r1 = Ractor.new(Ractor.current) do |main| + # puts "Received from main: #{main.take}" + # end + # + # puts "Trying to select" + # r, obj = Ractor.select(r1, Ractor.current, yield_value: 123) + # wait + # puts "Received #{obj.inspect} from #{r.inspect}" + # + # This will print: + # + # Trying to select + # Received from main: 123 + # Received nil from :yield + # + # +move+ boolean flag defines whether yielded value should be copied (default) or moved. + def self.select(*ractors, yield_value: yield_unspecified = true, move: false) + raise ArgumentError, 'specify at least one ractor or `yield_value`' if yield_unspecified && ractors.empty? + + __builtin_cstmt! %q{ + const VALUE *rs = RARRAY_CONST_PTR_TRANSIENT(ractors); + VALUE rv; + VALUE v = ractor_select(ec, rs, RARRAY_LENINT(ractors), + yield_unspecified == Qtrue ? Qundef : yield_value, + (bool)RTEST(move) ? true : false, &rv); + return rb_ary_new_from_args(2, rv, v); + } + end + + # + # call-seq: + # Ractor.receive -> msg + # + # Receive an incoming message from the current Ractor's incoming port's queue, which was + # sent there by #send. + # + # r = Ractor.new do + # v1 = Ractor.receive + # puts "Received: #{v1}" + # end + # r.send('message1') + # r.take + # # Here will be printed: "Received: message1" + # + # Alternatively, private instance method +receive+ may be used: + # + # r = Ractor.new do + # v1 = receive + # puts "Received: #{v1}" + # end + # r.send('message1') + # r.take + # # Here will be printed: "Received: message1" + # + # The method blocks if the queue is empty. + # + # r = Ractor.new do + # puts "Before first receive" + # v1 = Ractor.receive + # puts "Received: #{v1}" + # v2 = Ractor.receive + # puts "Received: #{v2}" + # end + # wait + # puts "Still not received" + # r.send('message1') + # wait + # puts "Still received only one" + # r.send('message2') + # r.take + # + # Output: + # + # Before first receive + # Still not received + # Received: message1 + # Still received only one + # Received: message2 + # + # If close_incoming was called on the ractor, the method raises Ractor::ClosedError + # if there are no more messages in incoming queue: + # + # Ractor.new do + # close_incoming + # receive + # end + # wait + # # in `receive': The incoming port is already closed => # (Ractor::ClosedError) + # + def self.receive + __builtin_cexpr! %q{ + ractor_receive(ec, rb_ec_ractor_ptr(ec)) + } + end + + class << self + alias recv receive + end + + # same as Ractor.receive + private def receive + __builtin_cexpr! %q{ + ractor_receive(ec, rb_ec_ractor_ptr(ec)) + } + end + alias recv receive + + # + # call-seq: + # Ractor.receive_if {|msg| block } -> msg + # + # Receive only a specific message. + # + # Instead of Ractor.receive, Ractor.receive_if can provide a pattern + # by a block and you can choose the receiving message. + # + # r = Ractor.new do + # p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3" + # p Ractor.receive_if{|msg| msg.match?(/bar/)} #=> "bar1" + # p Ractor.receive_if{|msg| msg.match?(/baz/)} #=> "baz2" + # end + # r << "bar1" + # r << "baz2" + # r << "foo3" + # r.take + # + # This will output: + # + # foo3 + # bar1 + # baz2 + # + # If the block returns a truthy value, the message will be removed from the incoming queue + # and returned. + # Otherwise, the message remains in the incoming queue and the following received + # messages are checked by the given block. + # + # If there are no messages left in the incoming queue, the method will + # block until new messages arrive. + # + # If the block is escaped by break/return/exception/throw, the message is removed from + # the incoming queue as if a truthy value had been returned. + # + # r = Ractor.new do + # val = Ractor.receive_if{|msg| msg.is_a?(Array)} + # puts "Received successfully: #{val}" + # end + # + # r.send(1) + # r.send('test') + # wait + # puts "2 non-matching sent, nothing received" + # r.send([1, 2, 3]) + # wait + # + # Prints: + # + # 2 non-matching sent, nothing received + # Received successfully: [1, 2, 3] + # + # Note that you can not call receive/receive_if in the given block recursively. + # It means that you should not do any tasks in the block. + # + # Ractor.current << true + # Ractor.receive_if{|msg| Ractor.receive} + # #=> `receive': can not call receive/receive_if recursively (Ractor::Error) + # + def self.receive_if &b + Primitive.ractor_receive_if b + end + + private def receive_if &b + Primitive.ractor_receive_if b + end + + # + # call-seq: + # ractor.send(msg, move: false) -> self + # + # Send a message to a Ractor's incoming queue to be consumed by Ractor.receive. + # + # r = Ractor.new do + # value = Ractor.receive + # puts "Received #{value}" + # end + # r.send 'message' + # # Prints: "Received: message" + # + # The method is non-blocking (will return immediately even if the ractor is not ready + # to receive anything): + # + # r = Ractor.new {sleep(5)} + # r.send('test') + # puts "Sent successfully" + # # Prints: "Sent successfully" immediately + # + # Attempt to send to ractor which already finished its execution will raise Ractor::ClosedError. + # + # r = Ractor.new {} + # r.take + # p r + # # "#" + # r.send('test') + # # Ractor::ClosedError (The incoming-port is already closed) + # + # If close_incoming was called on the ractor, the method also raises Ractor::ClosedError. + # + # r = Ractor.new do + # sleep(500) + # receive + # end + # r.close_incoming + # r.send('test') + # # Ractor::ClosedError (The incoming-port is already closed) + # # The error would be raised immediately, not when ractor will try to receive + # + # If the +obj+ is unshareable, by default it would be copied into ractor by deep cloning. + # If the move: true is passed, object is _moved_ into ractor and becomes + # inaccessible to sender. + # + # r = Ractor.new {puts "Received: #{receive}"} + # msg = 'message' + # r.send(msg, move: true) + # r.take + # p msg + # + # This prints: + # + # Received: message + # in `p': undefined method `inspect' for # + # + # All references to the object and its parts will become invalid in sender. + # + # r = Ractor.new {puts "Received: #{receive}"} + # s = 'message' + # ary = [s] + # copy = ary.dup + # r.send(ary, move: true) + # + # s.inspect + # # Ractor::MovedError (can not send any methods to a moved object) + # ary.class + # # Ractor::MovedError (can not send any methods to a moved object) + # copy.class + # # => Array, it is different object + # copy[0].inspect + # # Ractor::MovedError (can not send any methods to a moved object) + # # ...but its item was still a reference to `s`, which was moved + # + # If the object was shareable, move: true has no effect on it: + # + # r = Ractor.new {puts "Received: #{receive}"} + # s = 'message'.freeze + # r.send(s, move: true) + # s.inspect #=> "message", still available + # + def send(obj, move: false) + __builtin_cexpr! %q{ + ractor_send(ec, RACTOR_PTR(self), obj, move) + } + end + alias << send + + # + # call-seq: + # Ractor.yield(msg, move: false) -> nil + # + # Send a message to the current ractor's outgoing port to be consumed by #take. + # + # r = Ractor.new {Ractor.yield 'Hello from ractor'} + # puts r.take + # # Prints: "Hello from ractor" + # + # The method is blocking, and will return only when somebody consumes the + # sent message. + # + # r = Ractor.new do + # Ractor.yield 'Hello from ractor' + # puts "Ractor: after yield" + # end + # wait + # puts "Still not taken" + # puts r.take + # + # This will print: + # + # Still not taken + # Hello from ractor + # Ractor: after yield + # + # If the outgoing port was closed with #close_outgoing, the method will raise: + # + # r = Ractor.new do + # close_outgoing + # Ractor.yield 'Hello from ractor' + # end + # wait + # # `yield': The outgoing-port is already closed (Ractor::ClosedError) + # + # The meaning of +move+ argument is the same as for #send. + def self.yield(obj, move: false) + __builtin_cexpr! %q{ + ractor_yield(ec, rb_ec_ractor_ptr(ec), obj, move) + } + end + + # + # call-seq: + # ractor.take -> msg + # + # Take a message from ractor's outgoing port, which was put there by Ractor.yield or at ractor's + # finalization. + # + # r = Ractor.new do + # Ractor.yield 'explicit yield' + # 'last value' + # end + # puts r.take #=> 'explicit yield' + # puts r.take #=> 'last value' + # puts r.take # Ractor::ClosedError (The outgoing-port is already closed) + # + # The fact that the last value is also put to outgoing port means that +take+ can be used + # as some analog of Thread#join ("just wait till ractor finishes"), but don't forget it + # will raise if somebody had already consumed everything ractor have produced. + # + # If the outgoing port was closed with #close_outgoing, the method will raise Ractor::ClosedError. + # + # r = Ractor.new do + # sleep(500) + # Ractor.yield 'Hello from ractor' + # end + # r.close_outgoing + # r.take + # # Ractor::ClosedError (The outgoing-port is already closed) + # # The error would be raised immediately, not when ractor will try to receive + # + # If an uncaught exception is raised in the Ractor, it is propagated on take as a + # Ractor::RemoteError. + # + # r = Ractor.new {raise "Something weird happened"} + # + # begin + # r.take + # rescue => e + # p e # => # + # p e.ractor == r # => true + # p e.cause # => # + # end + # + # Ractor::ClosedError is a descendant of StopIteration, so the closing of the ractor will break + # the loops without propagating the error: + # + # r = Ractor.new do + # 3.times {|i| Ractor.yield "message #{i}"} + # "finishing" + # end + # + # loop {puts "Received: " + r.take} + # puts "Continue successfully" + # + # This will print: + # + # Received: message 0 + # Received: message 1 + # Received: message 2 + # Received: finishing + # Continue successfully + def take + __builtin_cexpr! %q{ + ractor_take(ec, RACTOR_PTR(self)) + } + end + + def inspect + loc = __builtin_cexpr! %q{ RACTOR_PTR(self)->loc } + name = __builtin_cexpr! %q{ RACTOR_PTR(self)->name } + id = __builtin_cexpr! %q{ INT2FIX(rb_ractor_id(RACTOR_PTR(self))) } + status = __builtin_cexpr! %q{ + rb_str_new2(ractor_status_str(RACTOR_PTR(self)->status_)) + } + "#" + end + + alias to_s inspect + + # The name set in Ractor.new, or +nil+. + def name + __builtin_cexpr! %q{RACTOR_PTR(self)->name} + end + + class RemoteError + attr_reader :ractor + end + + # + # call-seq: + # ractor.close_incoming -> true | false + # + # Closes the incoming port and returns its previous state. + # All further attempts to Ractor.receive in the ractor, and #send to the ractor + # will fail with Ractor::ClosedError. + # + # r = Ractor.new {sleep(500)} + # r.close_incoming #=> false + # r.close_incoming #=> true + # r.send('test') + # # Ractor::ClosedError (The incoming-port is already closed) + def close_incoming + __builtin_cexpr! %q{ + ractor_close_incoming(ec, RACTOR_PTR(self)); + } + end + + # + # call-seq: + # ractor.close_outgoing -> true | false + # + # Closes the outgoing port and returns its previous state. + # All further attempts to Ractor.yield in the ractor, and #take from the ractor + # will fail with Ractor::ClosedError. + # + # r = Ractor.new {sleep(500)} + # r.close_outgoing #=> false + # r.close_outgoing #=> true + # r.take + # # Ractor::ClosedError (The outgoing-port is already closed) + def close_outgoing + __builtin_cexpr! %q{ + ractor_close_outgoing(ec, RACTOR_PTR(self)); + } + end + + # + # call-seq: + # Ractor.shareable?(obj) -> true | false + # + # Checks if the object is shareable by ractors. + # + # Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen + # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true + # Ractor.shareable?('foo'.freeze) #=> true + # + # See also the "Shareable and unshareable objects" section in the Ractor class docs. + def self.shareable? obj + __builtin_cexpr! %q{ + RBOOL(rb_ractor_shareable_p(obj)); + } + end + + # + # call-seq: + # Ractor.make_shareable(obj, copy: false) -> shareable_obj + # + # Make +obj+ shareable between ractors. + # + # +obj+ and all the objects it refers to will be frozen, unless they are + # already shareable. + # + # If +copy+ keyword is +true+, the method will copy objects before freezing them + # This is safer option but it can take be slower. + # + # Note that the specification and implementation of this method are not + # mature and may be changed in the future. + # + # obj = ['test'] + # Ractor.shareable?(obj) #=> false + # Ractor.make_shareable(obj) #=> ["test"] + # Ractor.shareable?(obj) #=> true + # obj.frozen? #=> true + # obj[0].frozen? #=> true + # + # # Copy vs non-copy versions: + # obj1 = ['test'] + # obj1s = Ractor.make_shareable(obj1) + # obj1.frozen? #=> true + # obj1s.object_id == obj1.object_id #=> true + # obj2 = ['test'] + # obj2s = Ractor.make_shareable(obj2, copy: true) + # obj2.frozen? #=> false + # obj2s.frozen? #=> true + # obj2s.object_id == obj2.object_id #=> false + # obj2s[0].object_id == obj2[0].object_id #=> false + # + # See also the "Shareable and unshareable objects" section in the Ractor class docs. + def self.make_shareable obj, copy: false + if copy + __builtin_cexpr! %q{ + rb_ractor_make_shareable_copy(obj); + } + else + __builtin_cexpr! %q{ + rb_ractor_make_shareable(obj); + } + end + end + + # get a value from ractor-local storage + def [](sym) + Primitive.ractor_local_value(sym) + end + + # set a value in ractor-local storage + def []=(sym, val) + Primitive.ractor_local_value_set(sym, val) + end + + # returns main ractor + def self.main + __builtin_cexpr! %q{ + rb_ractor_self(GET_VM()->ractor.main_ractor); + } + end +end diff --git a/ruby/ractor_core.h b/ruby/ractor_core.h new file mode 100644 index 000000000..7673607a0 --- /dev/null +++ b/ruby/ractor_core.h @@ -0,0 +1,346 @@ +#include "ruby/ruby.h" +#include "ruby/ractor.h" +#include "vm_core.h" +#include "id_table.h" +#include "vm_debug.h" + +#ifndef RACTOR_CHECK_MODE +#define RACTOR_CHECK_MODE (0 || VM_CHECK_MODE || RUBY_DEBUG) +#endif + +enum rb_ractor_basket_type { + basket_type_none, + basket_type_ref, + basket_type_copy, + basket_type_move, + basket_type_will, + basket_type_deleted, + basket_type_reserved, +}; + +struct rb_ractor_basket { + bool exception; + enum rb_ractor_basket_type type; + VALUE v; + VALUE sender; +}; + +struct rb_ractor_queue { + struct rb_ractor_basket *baskets; + int start; + int cnt; + int size; + unsigned int serial; + unsigned int reserved_cnt; +}; + +struct rb_ractor_waiting_list { + int cnt; + int size; + rb_ractor_t **ractors; +}; + +struct rb_ractor_sync { + // ractor lock + rb_nativethread_lock_t lock; +#if RACTOR_CHECK_MODE > 0 + VALUE locked_by; +#endif + rb_nativethread_cond_t cond; + + // communication + struct rb_ractor_queue incoming_queue; + struct rb_ractor_waiting_list taking_ractors; + + bool incoming_port_closed; + bool outgoing_port_closed; + + struct ractor_wait { + enum ractor_wait_status { + wait_none = 0x00, + wait_receiving = 0x01, + wait_taking = 0x02, + wait_yielding = 0x04, + wait_moving = 0x08, + } status; + + enum ractor_wakeup_status { + wakeup_none, + wakeup_by_send, + wakeup_by_yield, + wakeup_by_take, + wakeup_by_close, + wakeup_by_interrupt, + wakeup_by_retry, + } wakeup_status; + + struct rb_ractor_basket yielded_basket; + struct rb_ractor_basket taken_basket; + } wait; +}; + +struct rb_ractor_struct { + struct rb_ractor_pub pub; + + struct rb_ractor_sync sync; + VALUE receiving_mutex; + bool yield_atexit; + + // vm wide barrier synchronization + rb_nativethread_cond_t barrier_wait_cond; + + // thread management + struct { + struct list_head set; + unsigned int cnt; + unsigned int blocking_cnt; + unsigned int sleeper; + rb_global_vm_lock_t gvl; + rb_execution_context_t *running_ec; + rb_thread_t *main; + } threads; + VALUE thgroup_default; + + VALUE name; + VALUE loc; + + // created + // | ready to run + // ====================== inserted to vm->ractor + // v + // blocking <---+ all threads are blocking + // | | + // v | + // running -----+ + // | all threads are terminated. + // ====================== removed from vm->ractor + // v + // terminated + // + // status is protected by VM lock (global state) + + enum ractor_status { + ractor_created, + ractor_running, + ractor_blocking, + ractor_terminated, + } status_; + + struct list_node vmlr_node; + + // ractor local data + + st_table *local_storage; + struct rb_id_table *idkey_local_storage; + + VALUE r_stdin; + VALUE r_stdout; + VALUE r_stderr; + VALUE verbose; + VALUE debug; + + rb_ractor_newobj_cache_t newobj_cache; + + // gc.c rb_objspace_reachable_objects_from + struct gc_mark_func_data_struct { + void *data; + void (*mark_func)(VALUE v, void *data); + } *mfd; +}; // rb_ractor_t is defined in vm_core.h + + +static inline VALUE +rb_ractor_self(const rb_ractor_t *r) +{ + return r->pub.self; +} + +rb_ractor_t *rb_ractor_main_alloc(void); +void rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *main_ractor, rb_thread_t *main_thread); +void rb_ractor_atexit(rb_execution_context_t *ec, VALUE result); +void rb_ractor_atexit_exception(rb_execution_context_t *ec); +void rb_ractor_teardown(rb_execution_context_t *ec); +void rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *g, int len, VALUE *ptr); +void rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *g, VALUE args); + +VALUE rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc); // defined in thread.c + +rb_global_vm_lock_t *rb_ractor_gvl(rb_ractor_t *); +int rb_ractor_living_thread_num(const rb_ractor_t *); +VALUE rb_ractor_thread_list(rb_ractor_t *r); +bool rb_ractor_p(VALUE rv); + +void rb_ractor_living_threads_init(rb_ractor_t *r); +void rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th); +void rb_ractor_living_threads_remove(rb_ractor_t *r, rb_thread_t *th); +void rb_ractor_blocking_threads_inc(rb_ractor_t *r, const char *file, int line); // TODO: file, line only for RUBY_DEBUG_LOG +void rb_ractor_blocking_threads_dec(rb_ractor_t *r, const char *file, int line); // TODO: file, line only for RUBY_DEBUG_LOG + +void rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r); +void rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r); +void rb_ractor_terminate_all(void); +bool rb_ractor_main_p_(void); +void rb_ractor_finish_marking(void); +void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th); + +VALUE rb_ractor_ensure_shareable(VALUE obj, VALUE name); + +RUBY_SYMBOL_EXPORT_BEGIN +bool rb_ractor_shareable_p_continue(VALUE obj); + +// THIS FUNCTION SHOULD NOT CALL WHILE INCREMENTAL MARKING!! +// This function is for T_DATA::free_func +void rb_ractor_local_storage_delkey(rb_ractor_local_key_t key); + +RUBY_SYMBOL_EXPORT_END + +static inline bool +rb_ractor_main_p(void) +{ + if (ruby_single_main_ractor) { + return true; + } + else { + return rb_ractor_main_p_(); + } +} + +static inline bool +rb_ractor_status_p(rb_ractor_t *r, enum ractor_status status) +{ + return r->status_ == status; +} + +static inline void +rb_ractor_sleeper_threads_inc(rb_ractor_t *r) +{ + r->threads.sleeper++; +} + +static inline void +rb_ractor_sleeper_threads_dec(rb_ractor_t *r) +{ + r->threads.sleeper--; +} + +static inline void +rb_ractor_sleeper_threads_clear(rb_ractor_t *r) +{ + r->threads.sleeper = 0; +} + +static inline int +rb_ractor_sleeper_thread_num(rb_ractor_t *r) +{ + return r->threads.sleeper; +} + +static inline void +rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th) +{ + if (cr->threads.running_ec != th->ec) { + if (0) { + ruby_debug_printf("rb_ractor_thread_switch ec:%p->%p\n", + (void *)cr->threads.running_ec, (void *)th->ec); + } + } + else { + return; + } + + if (cr->threads.running_ec != th->ec) { + th->running_time_us = 0; + } + + cr->threads.running_ec = th->ec; + + VM_ASSERT(cr == GET_RACTOR()); +} + +static inline void +rb_ractor_set_current_ec(rb_ractor_t *cr, rb_execution_context_t *ec) +{ +#ifdef RB_THREAD_LOCAL_SPECIFIER + #ifdef __APPLE__ + rb_current_ec_set(ec); + #else + ruby_current_ec = ec; + #endif +#else + native_tls_set(ruby_current_ec_key, ec); +#endif + + if (cr->threads.running_ec != ec) { + if (0) { + ruby_debug_printf("rb_ractor_set_current_ec ec:%p->%p\n", + (void *)cr->threads.running_ec, (void *)ec); + } + } + else { + VM_ASSERT(0); // should be different + } + + cr->threads.running_ec = ec; +} + +void rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line); +void rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line); + +static inline uint32_t +rb_ractor_id(const rb_ractor_t *r) +{ + return r->pub.id; +} + +#if RACTOR_CHECK_MODE > 0 +uint32_t rb_ractor_current_id(void); + +static inline void +rb_ractor_setup_belonging_to(VALUE obj, uint32_t rid) +{ + VALUE flags = RBASIC(obj)->flags & 0xffffffff; // 4B + RBASIC(obj)->flags = flags | ((VALUE)rid << 32); +} + +static inline void +rb_ractor_setup_belonging(VALUE obj) +{ + rb_ractor_setup_belonging_to(obj, rb_ractor_current_id()); +} + +static inline uint32_t +rb_ractor_belonging(VALUE obj) +{ + if (SPECIAL_CONST_P(obj) || RB_OBJ_SHAREABLE_P(obj)) { + return 0; + } + else { + return RBASIC(obj)->flags >> 32; + } +} + +static inline VALUE +rb_ractor_confirm_belonging(VALUE obj) +{ + uint32_t id = rb_ractor_belonging(obj); + + if (id == 0) { + if (UNLIKELY(!rb_ractor_shareable_p(obj))) { + rp(obj); + rb_bug("id == 0 but not shareable"); + } + } + else if (UNLIKELY(id != rb_ractor_current_id())) { + if (rb_ractor_shareable_p(obj)) { + // ok + } + else { + rp(obj); + rb_bug("rb_ractor_confirm_belonging object-ractor id:%u, current-ractor id:%u", id, rb_ractor_current_id()); + } + } + return obj; +} +#else +#define rb_ractor_confirm_belonging(obj) obj +#endif diff --git a/ruby/random.c b/ruby/random.c index 68b47bcf1..f3dec5cca 100644 --- a/ruby/random.c +++ b/ruby/random.c @@ -9,41 +9,70 @@ **********************************************************************/ -#include "internal.h" +#include "ruby/internal/config.h" +#include #include +#include +#include +#include + #ifdef HAVE_UNISTD_H -#include +# include #endif -#include + #include #include + #ifdef HAVE_FCNTL_H -#include +# include #endif -#include -#include + #if defined(HAVE_SYS_TIME_H) -#include +# include #endif #ifdef HAVE_SYSCALL_H -#include +# include #elif defined HAVE_SYS_SYSCALL_H -#include +# include #endif #ifdef _WIN32 -#include -#include +# include +# include +# include +# include #endif -#include "ruby_atomic.h" -#ifdef __OpenBSD__ -/* to define OpenBSD for version check */ -#include +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +/* to define OpenBSD and FreeBSD for version check */ +# include #endif +#if defined HAVE_GETRANDOM || defined HAVE_GETENTROPY +# if defined(HAVE_SYS_RANDOM_H) +# include +# endif +#elif defined __linux__ && defined __NR_getrandom +# include +#endif + +#if defined __APPLE__ +# include +#endif + +#include "internal.h" +#include "internal/array.h" +#include "internal/compilers.h" +#include "internal/numeric.h" +#include "internal/random.h" +#include "internal/sanitizers.h" +#include "internal/variable.h" +#include "ruby_atomic.h" +#include "ruby/random.h" +#include "ruby/ractor.h" + typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; #include "missing/mt19937.c" @@ -58,12 +87,22 @@ genrand_real(struct MT *mt) return int_pair_to_real_exclusive(a, b); } +static const double dbl_reduce_scale = /* 2**(-DBL_MANT_DIG) */ + (1.0 + / (double)(DBL_MANT_DIG > 2*31 ? (1ul<<31) : 1.0) + / (double)(DBL_MANT_DIG > 1*31 ? (1ul<<31) : 1.0) + / (double)(1ul<<(DBL_MANT_DIG%31))); + static double int_pair_to_real_exclusive(uint32_t a, uint32_t b) { - a >>= 5; - b >>= 6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); + static const int a_shift = DBL_MANT_DIG < 64 ? + (64-DBL_MANT_DIG)/2 : 0; + static const int b_shift = DBL_MANT_DIG < 64 ? + (65-DBL_MANT_DIG)/2 : 0; + a >>= a_shift; + b >>= b_shift; + return (a*(double)(1ul<<(32-b_shift))+b)*dbl_reduce_scale; } /* generates a random number on [0,1] with 53-bit resolution*/ @@ -84,44 +123,82 @@ genrand_real2(struct MT *mt) #undef M typedef struct { - VALUE seed; + rb_random_t base; struct MT mt; -} rb_random_t; +} rb_random_mt_t; #define DEFAULT_SEED_CNT 4 -static rb_random_t default_rand; - -static VALUE rand_init(struct MT *mt, VALUE vseed); +static VALUE rand_init(const rb_random_interface_t *, rb_random_t *, VALUE); static VALUE random_seed(VALUE); +static void fill_random_seed(uint32_t *seed, size_t cnt); +static VALUE make_seed_value(uint32_t *ptr, size_t len); -static rb_random_t * -rand_start(rb_random_t *r) +RB_RANDOM_INTERFACE_DECLARE(rand_mt); +static const rb_random_interface_t random_mt_if = { + DEFAULT_SEED_CNT * 32, + RB_RANDOM_INTERFACE_DEFINE(rand_mt) +}; + +static rb_random_mt_t * +rand_mt_start(rb_random_mt_t *r) { - struct MT *mt = &r->mt; - if (!genrand_initialized(mt)) { - r->seed = rand_init(mt, random_seed(Qundef)); + if (!genrand_initialized(&r->mt)) { + r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef)); } return r; } -static struct MT * +static rb_random_t * +rand_start(rb_random_mt_t *r) +{ + return &rand_mt_start(r)->base; +} + +static rb_ractor_local_key_t default_rand_key; + +static void +default_rand_mark(void *ptr) +{ + rb_random_mt_t *rnd = (rb_random_mt_t *)ptr; + rb_gc_mark(rnd->base.seed); +} + +static const struct rb_ractor_local_storage_type default_rand_key_storage_type = { + default_rand_mark, + ruby_xfree, +}; + +static rb_random_mt_t * +default_rand(void) +{ + rb_random_mt_t *rnd; + + if ((rnd = rb_ractor_local_storage_ptr(default_rand_key)) == NULL) { + rnd = ZALLOC(rb_random_mt_t); + rb_ractor_local_storage_ptr_set(default_rand_key, rnd); + } + + return rnd; +} + +static rb_random_mt_t * default_mt(void) { - return &rand_start(&default_rand)->mt; + return rand_mt_start(default_rand()); } unsigned int rb_genrand_int32(void) { - struct MT *mt = default_mt(); + struct MT *mt = &default_mt()->mt; return genrand_int32(mt); } double rb_genrand_real(void) { - struct MT *mt = default_mt(); + struct MT *mt = &default_mt()->mt; return genrand_real(mt); } @@ -131,13 +208,13 @@ static double int_pair_to_real_inclusive(uint32_t a, uint32_t b) { double r; - enum {dig = 53}; + enum {dig = DBL_MANT_DIG}; enum {dig_u = dig-32, dig_r64 = 64-dig, bmask = ~(~0u<<(dig_r64))}; #if defined HAVE_UINT128_T const uint128_t m = ((uint128_t)1 << dig) | 1; uint128_t x = ((uint128_t)a << 32) | b; r = (double)(uint64_t)((x * m) >> 64); -#elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200) +#elif defined HAVE_UINT64_T && !MSC_VERSION_BEFORE(1300) uint64_t x = ((uint64_t)a << dig_u) + (((uint64_t)b + (a >> dig_u)) >> dig_r64); r = (double)x; @@ -146,7 +223,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b) b = (b >> dig_r64) + (((a >> dig_u) + (b & bmask)) >> dig_r64); r = (double)a * (1 << dig_u) + b; #endif - return ldexp(r, -dig); + return r * dbl_reduce_scale; } VALUE rb_cRandom; @@ -156,18 +233,15 @@ static ID id_rand, id_bytes; NORETURN(static void domain_error(void)); /* :nodoc: */ -static void +#define random_mark rb_random_mark + +void random_mark(void *ptr) { rb_gc_mark(((rb_random_t *)ptr)->seed); } -static void -random_free(void *ptr) -{ - if (ptr != &default_rand) - xfree(ptr); -} +#define random_free RUBY_TYPED_DEFAULT_FREE static size_t random_memsize(const void *ptr) @@ -175,8 +249,8 @@ random_memsize(const void *ptr) return sizeof(rb_random_t); } -static const rb_data_type_t random_mt_type = { - "random/MT", +const rb_data_type_t rb_random_data_type = { + "random", { random_mark, random_free, @@ -185,62 +259,125 @@ static const rb_data_type_t random_mt_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; +#define random_mt_mark rb_random_mark +#define random_mt_free RUBY_TYPED_DEFAULT_FREE + +static size_t +random_mt_memsize(const void *ptr) +{ + return sizeof(rb_random_mt_t); +} + +static const rb_data_type_t random_mt_type = { + "random/MT", + { + random_mt_mark, + random_mt_free, + random_mt_memsize, + }, + &rb_random_data_type, + (void *)&random_mt_if, + RUBY_TYPED_FREE_IMMEDIATELY +}; + static rb_random_t * get_rnd(VALUE obj) { rb_random_t *ptr; - TypedData_Get_Struct(obj, rb_random_t, &random_mt_type, ptr); - return rand_start(ptr); + TypedData_Get_Struct(obj, rb_random_t, &rb_random_data_type, ptr); + if (RTYPEDDATA_TYPE(obj) == &random_mt_type) + return rand_start((rb_random_mt_t *)ptr); + return ptr; +} + +static rb_random_mt_t * +get_rnd_mt(VALUE obj) +{ + rb_random_mt_t *ptr; + TypedData_Get_Struct(obj, rb_random_mt_t, &random_mt_type, ptr); + return ptr; } static rb_random_t * try_get_rnd(VALUE obj) { if (obj == rb_cRandom) { - return rand_start(&default_rand); + return rand_start(default_rand()); + } + if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL; + if (RTYPEDDATA_TYPE(obj) == &random_mt_type) + return rand_start(DATA_PTR(obj)); + rb_random_t *rnd = DATA_PTR(obj); + if (!rnd) { + rb_raise(rb_eArgError, "uninitialized random: %s", + RTYPEDDATA_TYPE(obj)->wrap_struct_name); + } + return rnd; +} + +static const rb_random_interface_t * +try_rand_if(VALUE obj, rb_random_t *rnd) +{ + if (rnd == &default_rand()->base) { + return &random_mt_if; } - if (!rb_typeddata_is_kind_of(obj, &random_mt_type)) return NULL; - return rand_start(DATA_PTR(obj)); + return rb_rand_if(obj); +} + +/* :nodoc: */ +void +rb_random_base_init(rb_random_t *rnd) +{ + rnd->seed = INT2FIX(0); } /* :nodoc: */ static VALUE random_alloc(VALUE klass) { - rb_random_t *rnd; - VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_mt_type, rnd); - rnd->seed = INT2FIX(0); + rb_random_mt_t *rnd; + VALUE obj = TypedData_Make_Struct(klass, rb_random_mt_t, &random_mt_type, rnd); + rb_random_base_init(&rnd->base); return obj; } static VALUE -rand_init(struct MT *mt, VALUE seed) +rand_init_default(const rb_random_interface_t *rng, rb_random_t *rnd) { - uint32_t buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0; + VALUE seed, buf0 = 0; + size_t len = roomof(rng->default_seed_bits, 32); + uint32_t *buf = ALLOCV_N(uint32_t, buf0, len+1); + + fill_random_seed(buf, len); + rng->init(rnd, buf, len); + seed = make_seed_value(buf, len); + explicit_bzero(buf, len * sizeof(*buf)); + ALLOCV_END(buf0); + return seed; +} + +static VALUE +rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed) +{ + uint32_t *buf; + VALUE buf0 = 0; size_t len; int sign; len = rb_absint_numwords(seed, 32, NULL); - if (len > numberof(buf0)) - buf = ALLOC_N(uint32_t, len); + if (len == 0) len = 1; + buf = ALLOCV_N(uint32_t, buf0, len); sign = rb_integer_pack(seed, buf, len, sizeof(uint32_t), 0, INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); if (sign < 0) sign = -sign; - if (len == 0) { - buf[0] = 0; - len = 1; - } - if (len <= 1) { - init_genrand(mt, buf[0]); - } - else { + if (len > 1) { if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */ len--; - init_by_array(mt, buf, (int)len); } + rng->init(rnd, buf, len); explicit_bzero(buf, len * sizeof(*buf)); - if (buf != buf0) xfree(buf); + ALLOCV_END(buf0); return seed; } @@ -256,19 +393,21 @@ rand_init(struct MT *mt, VALUE seed) static VALUE random_init(int argc, VALUE *argv, VALUE obj) { - VALUE vseed; - rb_random_t *rnd = get_rnd(obj); + rb_random_t *rnd = try_get_rnd(obj); + const rb_random_interface_t *rng = rb_rand_if(obj); - if (rb_check_arity(argc, 0, 1) == 0) { - rb_check_frozen(obj); - vseed = random_seed(obj); + if (!rng) { + rb_raise(rb_eTypeError, "undefined random interface: %s", + RTYPEDDATA_TYPE(obj)->wrap_struct_name); + } + argc = rb_check_arity(argc, 0, 1); + rb_check_frozen(obj); + if (argc == 0) { + rnd->seed = rand_init_default(rng, rnd); } else { - vseed = argv[0]; - rb_check_copyable(obj, vseed); - vseed = rb_to_int(vseed); + rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0])); } - rnd->seed = rand_init(&rnd->mt, vseed); return obj; } @@ -280,7 +419,23 @@ random_init(int argc, VALUE *argv, VALUE obj) # define USE_DEV_URANDOM 0 #endif -#if USE_DEV_URANDOM +#ifdef HAVE_GETENTROPY +# define MAX_SEED_LEN_PER_READ 256 +static int +fill_random_bytes_urandom(void *seed, size_t size) +{ + unsigned char *p = (unsigned char *)seed; + while (size) { + size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ; + if (getentropy(p, len) != 0) { + return -1; + } + p += len; + size -= len; + } + return 0; +} +#elif USE_DEV_URANDOM static int fill_random_bytes_urandom(void *seed, size_t size) { @@ -320,11 +475,7 @@ fill_random_bytes_urandom(void *seed, size_t size) # define fill_random_bytes_urandom(seed, size) -1 #endif -#if defined HAVE_GETRANDOM -# include -#elif defined __linux__ && defined __NR_getrandom -# include - +#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom # ifndef GRND_NONBLOCK # define GRND_NONBLOCK 0x0001 /* not defined in musl libc */ # endif @@ -335,20 +486,36 @@ fill_random_bytes_urandom(void *seed, size_t size) #if 0 #elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 -#include + +# if defined MAC_OS_X_VERSION_10_10 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10 +# include /* for old Xcode */ +# include +# define USE_COMMON_RANDOM 1 +# else +# include +# define USE_COMMON_RANDOM 0 +# endif static int fill_random_bytes_syscall(void *seed, size_t size, int unused) { - int status = SecRandomCopyBytes(kSecRandomDefault, size, seed); +#if USE_COMMON_RANDOM + int failed = CCRandomGenerateBytes(seed, size) != kCCSuccess; +#else + int failed = SecRandomCopyBytes(kSecRandomDefault, size, seed) != errSecSuccess; +#endif - if (status != errSecSuccess) { + if (failed) { # if 0 +# if USE_COMMON_RANDOM + /* How to get the error message? */ +# else CFStringRef s = SecCopyErrorMessageString(status, NULL); const char *m = s ? CFStringGetCStringPtr(s, kCFStringEncodingUTF8) : NULL; fprintf(stderr, "SecRandomCopyBytes failed: %d: %s\n", status, m ? m : "unknown"); if (s) CFRelease(s); +# endif # endif return -1; } @@ -368,41 +535,84 @@ fill_random_bytes_syscall(void *buf, size_t size, int unused) #endif } #elif defined(_WIN32) + +#ifndef DWORD_MAX +# define DWORD_MAX (~(DWORD)0UL) +#endif + +# if defined(CRYPT_VERIFYCONTEXT) +STATIC_ASSERT(sizeof_HCRYPTPROV, sizeof(HCRYPTPROV) == sizeof(size_t)); + +/* Although HCRYPTPROV is not a HANDLE, it looks like + * INVALID_HANDLE_VALUE is not a valid value */ +static const HCRYPTPROV INVALID_HCRYPTPROV = (HCRYPTPROV)INVALID_HANDLE_VALUE; + static void release_crypt(void *p) { - HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_PTR_EXCHANGE(*(HCRYPTPROV *)p, INVALID_HANDLE_VALUE); - if (prov && prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) { + HCRYPTPROV *ptr = p; + HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_SIZE_EXCHANGE(*ptr, INVALID_HCRYPTPROV); + if (prov && prov != INVALID_HCRYPTPROV) { CryptReleaseContext(prov, 0); } } static int -fill_random_bytes_syscall(void *seed, size_t size, int unused) +fill_random_bytes_crypt(void *seed, size_t size) { static HCRYPTPROV perm_prov; HCRYPTPROV prov = perm_prov, old_prov; if (!prov) { if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - prov = (HCRYPTPROV)INVALID_HANDLE_VALUE; + prov = INVALID_HCRYPTPROV; } - old_prov = (HCRYPTPROV)ATOMIC_PTR_CAS(perm_prov, 0, prov); + old_prov = (HCRYPTPROV)ATOMIC_SIZE_CAS(perm_prov, 0, prov); if (LIKELY(!old_prov)) { /* no other threads acquired */ - if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) { + if (prov != INVALID_HCRYPTPROV) { +#undef RUBY_UNTYPED_DATA_WARNING +#define RUBY_UNTYPED_DATA_WARNING 0 rb_gc_register_mark_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov)); } } else { /* another thread acquired */ - if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) { + if (prov != INVALID_HCRYPTPROV) { CryptReleaseContext(prov, 0); } prov = old_prov; } } - if (prov == (HCRYPTPROV)INVALID_HANDLE_VALUE) return -1; - CryptGenRandom(prov, size, seed); + if (prov == INVALID_HCRYPTPROV) return -1; + while (size > 0) { + DWORD n = (size > (size_t)DWORD_MAX) ? DWORD_MAX : (DWORD)size; + if (!CryptGenRandom(prov, n, seed)) return -1; + seed = (char *)seed + n; + size -= n; + } + return 0; +} +# else +# define fill_random_bytes_crypt(seed, size) -1 +# endif + +static int +fill_random_bytes_bcrypt(void *seed, size_t size) +{ + while (size > 0) { + ULONG n = (size > (size_t)ULONG_MAX) ? LONG_MAX : (ULONG)size; + if (BCryptGenRandom(NULL, seed, n, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) + return -1; + seed = (char *)seed + n; + size -= n; + } return 0; } + +static int +fill_random_bytes_syscall(void *seed, size_t size, int unused) +{ + if (fill_random_bytes_bcrypt(seed, size) == 0) return 0; + return fill_random_bytes_crypt(seed, size); +} #elif defined HAVE_GETRANDOM static int fill_random_bytes_syscall(void *seed, size_t size, int need_secure) @@ -440,10 +650,11 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure) #define fill_random_bytes ruby_fill_random_bytes +/* cnt must be 4 or more */ static void fill_random_seed(uint32_t *seed, size_t cnt) { - static int n = 0; + static rb_atomic_t n = 0; #if defined HAVE_CLOCK_GETTIME struct timespec tv; #elif defined HAVE_GETTIMEOFDAY @@ -466,7 +677,7 @@ fill_random_seed(uint32_t *seed, size_t cnt) #if SIZEOF_TIME_T > SIZEOF_INT seed[0] ^= (uint32_t)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT); #endif - seed[2] ^= getpid() ^ (n++ << 16); + seed[2] ^= getpid() ^ (ATOMIC_FETCH_ADD(n, 1) << 16); seed[3] ^= (uint32_t)(VALUE)&seed; #if SIZEOF_VOIDP > SIZEOF_INT seed[2] ^= (uint32_t)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT); @@ -489,6 +700,10 @@ make_seed_value(uint32_t *ptr, size_t len) return seed; } +#define with_random_seed(size, add) \ + for (uint32_t seedbuf[(size)+(add)], loop = (fill_random_seed(seedbuf, (size)), 1); \ + loop; explicit_bzero(seedbuf, (size)*sizeof(seedbuf[0])), loop = 0) + /* * call-seq: Random.new_seed -> integer * @@ -501,10 +716,9 @@ static VALUE random_seed(VALUE _) { VALUE v; - uint32_t buf[DEFAULT_SEED_CNT+1]; - fill_random_seed(buf, DEFAULT_SEED_CNT); - v = make_seed_value(buf, DEFAULT_SEED_CNT); - explicit_bzero(buf, DEFAULT_SEED_LEN); + with_random_seed(DEFAULT_SEED_CNT, 1) { + v = make_seed_value(seedbuf, DEFAULT_SEED_CNT); + } return v; } @@ -557,15 +771,15 @@ random_get_seed(VALUE obj) /* :nodoc: */ static VALUE -random_copy(VALUE obj, VALUE orig) +rand_mt_copy(VALUE obj, VALUE orig) { - rb_random_t *rnd1, *rnd2; + rb_random_mt_t *rnd1, *rnd2; struct MT *mt; if (!OBJ_INIT_COPY(obj, orig)) return obj; - rnd1 = get_rnd(obj); - rnd2 = get_rnd(orig); + rnd1 = get_rnd_mt(obj); + rnd2 = get_rnd_mt(orig); mt = &rnd1->mt; *rnd1 = *rnd2; @@ -583,9 +797,9 @@ mt_state(const struct MT *mt) /* :nodoc: */ static VALUE -random_state(VALUE obj) +rand_mt_state(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = get_rnd_mt(obj); return mt_state(&rnd->mt); } @@ -593,14 +807,14 @@ random_state(VALUE obj) static VALUE random_s_state(VALUE klass) { - return mt_state(&default_rand.mt); + return mt_state(&default_rand()->mt); } /* :nodoc: */ static VALUE -random_left(VALUE obj) +rand_mt_left(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = get_rnd_mt(obj); return INT2FIX(rnd->mt.left); } @@ -608,28 +822,28 @@ random_left(VALUE obj) static VALUE random_s_left(VALUE klass) { - return INT2FIX(default_rand.mt.left); + return INT2FIX(default_rand()->mt.left); } /* :nodoc: */ static VALUE -random_dump(VALUE obj) +rand_mt_dump(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type); VALUE dump = rb_ary_new2(3); rb_ary_push(dump, mt_state(&rnd->mt)); rb_ary_push(dump, INT2FIX(rnd->mt.left)); - rb_ary_push(dump, rnd->seed); + rb_ary_push(dump, rnd->base.seed); return dump; } /* :nodoc: */ static VALUE -random_load(VALUE obj, VALUE dump) +rand_mt_load(VALUE obj, VALUE dump) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type); struct MT *mt = &rnd->mt; VALUE state, left = INT2FIX(1), seed = INT2FIX(0); unsigned long x; @@ -656,17 +870,42 @@ random_load(VALUE obj, VALUE dump) } mt->left = (unsigned int)x; mt->next = mt->state + numberof(mt->state) - x + 1; - rnd->seed = rb_to_int(seed); + rnd->base.seed = rb_to_int(seed); return obj; } +static void +rand_mt_init(rb_random_t *rnd, const uint32_t *buf, size_t len) +{ + struct MT *mt = &((rb_random_mt_t *)rnd)->mt; + if (len <= 1) { + init_genrand(mt, len ? buf[0] : 0); + } + else { + init_by_array(mt, buf, (int)len); + } +} + +static unsigned int +rand_mt_get_int32(rb_random_t *rnd) +{ + struct MT *mt = &((rb_random_mt_t *)rnd)->mt; + return genrand_int32(mt); +} + +static void +rand_mt_get_bytes(rb_random_t *rnd, void *ptr, size_t n) +{ + rb_rand_bytes_int32(rand_mt_get_int32, rnd, ptr, n); +} + /* * call-seq: * srand(number = Random.new_seed) -> old_seed * - * Seeds the system pseudo-random number generator, Random::DEFAULT, with - * +number+. The previous seed value is returned. + * Seeds the system pseudo-random number generator, with +number+. + * The previous seed value is returned. * * If +number+ is omitted, seeds the generator using a source of entropy * provided by the operating system, if available (/dev/urandom on Unix systems @@ -688,7 +927,7 @@ static VALUE rb_f_srand(int argc, VALUE *argv, VALUE obj) { VALUE seed, old; - rb_random_t *r = &default_rand; + rb_random_mt_t *r = rand_mt_start(default_rand()); if (rb_check_arity(argc, 0, 1) == 0) { seed = random_seed(obj); @@ -696,8 +935,9 @@ rb_f_srand(int argc, VALUE *argv, VALUE obj) else { seed = rb_to_int(argv[0]); } - old = r->seed; - r->seed = rand_init(&r->mt, seed); + old = r->base.seed; + rand_init(&random_mt_if, &r->base, seed); + r->base.seed = seed; return old; } @@ -717,7 +957,7 @@ make_mask(unsigned long x) } static unsigned long -limited_rand(struct MT *mt, unsigned long limit) +limited_rand(const rb_random_interface_t *rng, rb_random_t *rnd, unsigned long limit) { /* mt must be initialized */ unsigned long val, mask; @@ -732,7 +972,7 @@ limited_rand(struct MT *mt, unsigned long limit) val = 0; for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) { if ((mask >> (i * 32)) & 0xffffffff) { - val |= (unsigned long)genrand_int32(mt) << (i * 32); + val |= (unsigned long)rng->get_int32(rnd) << (i * 32); val &= mask; if (limit < val) goto retry; @@ -743,13 +983,13 @@ limited_rand(struct MT *mt, unsigned long limit) #endif do { - val = genrand_int32(mt) & mask; + val = rng->get_int32(rnd) & mask; } while (limit < val); return val; } static VALUE -limited_big_rand(struct MT *mt, VALUE limit) +limited_big_rand(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE limit) { /* mt must be initialized */ @@ -773,22 +1013,19 @@ limited_big_rand(struct MT *mt, VALUE limit) mask = 0; boundary = 1; for (i = len-1; 0 <= i; i--) { - uint32_t rnd; + uint32_t r = 0; uint32_t lim = lim_array[i]; mask = mask ? 0xffffffff : (uint32_t)make_mask(lim); if (mask) { - rnd = genrand_int32(mt) & mask; + r = rng->get_int32(rnd) & mask; if (boundary) { - if (lim < rnd) + if (lim < r) goto retry; - if (rnd < lim) + if (r < lim) boundary = 0; } } - else { - rnd = 0; - } - rnd_array[i] = rnd; + rnd_array[i] = r; } val = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0, INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); @@ -806,7 +1043,8 @@ limited_big_rand(struct MT *mt, VALUE limit) unsigned long rb_genrand_ulong_limited(unsigned long limit) { - return limited_rand(default_mt(), limit); + rb_random_mt_t *mt = default_mt(); + return limited_rand(&random_mt_if, &mt->base, limit); } static VALUE @@ -826,9 +1064,9 @@ obj_random_bytes(VALUE obj, void *p, long n) } static unsigned int -random_int32(rb_random_t *rnd) +random_int32(const rb_random_interface_t *rng, rb_random_t *rnd) { - return genrand_int32(&rnd->mt); + return rng->get_int32(rnd); } unsigned int @@ -840,7 +1078,7 @@ rb_random_int32(VALUE obj) obj_random_bytes(obj, &x, sizeof(x)); return (unsigned int)x; } - return random_int32(rnd); + return random_int32(try_rand_if(obj, rnd), rnd); } static double @@ -855,9 +1093,17 @@ random_real(VALUE obj, rb_random_t *rnd, int excl) b = x[1]; } else { - a = random_int32(rnd); - b = random_int32(rnd); + const rb_random_interface_t *rng = try_rand_if(obj, rnd); + if (rng->get_real) return rng->get_real(rnd, excl); + a = random_int32(rng, rnd); + b = random_int32(rng, rnd); } + return rb_int_pair_to_real(a, b, excl); +} + +double +rb_int_pair_to_real(uint32_t a, uint32_t b, int excl) +{ if (excl) { return int_pair_to_real_exclusive(a, b); } @@ -881,7 +1127,7 @@ rb_random_real(VALUE obj) } return d; } - return genrand_real(&rnd->mt); + return random_real(obj, rnd, TRUE); } static inline VALUE @@ -923,7 +1169,7 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit) } while (limit < val); return val; } - return limited_rand(&rnd->mt, limit); + return limited_rand(try_rand_if(obj, rnd), rnd, limit); } unsigned long @@ -942,7 +1188,7 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit) } return r; } - return limited_rand(&rnd->mt, limit); + return limited_rand(try_rand_if(obj, rnd), rnd, limit); } static VALUE @@ -971,10 +1217,20 @@ random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax) ALLOCV_END(vtmp); return v; } - return limited_big_rand(&rnd->mt, vmax); + return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax); } -static VALUE genrand_bytes(rb_random_t *rnd, long n); +static VALUE +rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n) +{ + VALUE bytes; + char *ptr; + + bytes = rb_str_new(0, n); + ptr = RSTRING_PTR(bytes); + rng->get_bytes(rnd, ptr, n); + return bytes; +} /* * call-seq: prng.bytes(size) -> string @@ -987,20 +1243,18 @@ static VALUE genrand_bytes(rb_random_t *rnd, long n); static VALUE random_bytes(VALUE obj, VALUE len) { - return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len))); + rb_random_t *rnd = try_get_rnd(obj); + return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len))); } -static VALUE -genrand_bytes(rb_random_t *rnd, long n) +void +rb_rand_bytes_int32(rb_random_get_int32_func *get_int32, + rb_random_t *rnd, void *p, size_t n) { - VALUE bytes; - char *ptr; + char *ptr = p; unsigned int r, i; - - bytes = rb_str_new(0, n); - ptr = RSTRING_PTR(bytes); for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) { - r = genrand_int32(&rnd->mt); + r = get_int32(rnd); i = SIZEOF_INT32; do { *ptr++ = (char)r; @@ -1008,13 +1262,12 @@ genrand_bytes(rb_random_t *rnd, long n) } while (--i); } if (n > 0) { - r = genrand_int32(&rnd->mt); + r = get_int32(rnd); do { *ptr++ = (char)r; r >>= CHAR_BIT; } while (--n); } - return bytes; } VALUE @@ -1024,7 +1277,7 @@ rb_random_bytes(VALUE obj, long n) if (!rnd) { return obj_random_bytes(obj, NULL, n); } - return genrand_bytes(rnd, n); + return rand_bytes(try_rand_if(obj, rnd), rnd, n); } /* @@ -1036,8 +1289,30 @@ rb_random_bytes(VALUE obj, long n) static VALUE random_s_bytes(VALUE obj, VALUE len) { - rb_random_t *rnd = rand_start(&default_rand); - return genrand_bytes(rnd, NUM2LONG(rb_to_int(len))); + rb_random_t *rnd = rand_start(default_rand()); + return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len))); +} + +/* + * call-seq: Random.seed -> integer + * + * Returns the seed value used to initialize the Ruby system PRNG. + * This may be used to initialize another generator with the same + * state at a later time, causing it to produce the same sequence of + * numbers. + * + * Random.seed #=> 1234 + * prng1 = Random.new(Random.seed) + * prng1.seed #=> 1234 + * prng1.rand(100) #=> 47 + * Random.seed #=> 1234 + * Random.rand(100) #=> 47 + */ +static VALUE +random_s_seed(VALUE obj) +{ + rb_random_mt_t *rnd = rand_mt_start(default_rand()); + return rnd->base.seed; } static VALUE @@ -1120,7 +1395,7 @@ static inline double float_value(VALUE v) { double x = RFLOAT_VALUE(v); - if (isinf(x) || isnan(x)) { + if (!isfinite(x)) { domain_error(); } return x; @@ -1135,12 +1410,12 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range) if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse) return Qfalse; if (NIL_P(v)) domain_error(); - if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_int(vmax), !NIL_P(v))) { + if (!RB_FLOAT_TYPE_P(vmax) && (v = rb_check_to_int(vmax), !NIL_P(v))) { long max; vmax = v; v = Qnil; + fixnum: if (FIXNUM_P(vmax)) { - fixnum: if ((max = FIX2LONG(vmax) - excl) >= 0) { unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max); v = ULONG2NUM(r); @@ -1209,6 +1484,7 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd); * call-seq: * prng.rand -> float * prng.rand(max) -> number + * prng.rand(range) -> number * * When +max+ is an Integer, +rand+ returns a random integer greater than * or equal to zero and less than +max+. Unlike Kernel.rand, when +max+ @@ -1222,8 +1498,8 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd); * * prng.rand(1.5) # => 1.4600282860034115 * - * When +max+ is a Range, +rand+ returns a random number where - * range.member?(number) == true. + * When +range+ is a Range, +rand+ returns a random number where + * range.member?(number) == true. * * prng.rand(5..9) # => one of [5, 6, 7, 8, 9] * prng.rand(5...9) # => one of [5, 6, 7, 8] @@ -1237,7 +1513,7 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd); static VALUE random_rand(int argc, VALUE *argv, VALUE obj) { - VALUE v = rand_random(argc, argv, obj, get_rnd(obj)); + VALUE v = rand_random(argc, argv, obj, try_get_rnd(obj)); check_random_number(v, argv); return v; } @@ -1252,7 +1528,7 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd) } vmax = argv[0]; if (NIL_P(vmax)) return Qnil; - if (!RB_TYPE_P(vmax, T_FLOAT)) { + if (!RB_FLOAT_TYPE_P(vmax)) { v = rb_check_to_int(vmax); if (!NIL_P(v)) return rand_int(obj, rnd, v, 1); } @@ -1273,10 +1549,12 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd) /* * call-seq: - * prng.random_number -> float - * prng.random_number(max) -> number - * prng.rand -> float - * prng.rand(max) -> number + * prng.random_number -> float + * prng.random_number(max) -> number + * prng.random_number(range) -> number + * prng.rand -> float + * prng.rand(max) -> number + * prng.rand(range) -> number * * Generates formatted random number from raw random bytes. * See Random#rand. @@ -1316,16 +1594,16 @@ rand_random_number(int argc, VALUE *argv, VALUE obj) * prng1 == prng2 # => true */ static VALUE -random_equal(VALUE self, VALUE other) +rand_mt_equal(VALUE self, VALUE other) { - rb_random_t *r1, *r2; + rb_random_mt_t *r1, *r2; if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse; - r1 = get_rnd(self); - r2 = get_rnd(other); + r1 = get_rnd_mt(self); + r2 = get_rnd_mt(other); if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse; if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse; if (r1->mt.left != r2->mt.left) return Qfalse; - return rb_equal(r1->seed, r2->seed); + return rb_equal(r1->base.seed, r2->base.seed); } /* @@ -1363,32 +1641,34 @@ static VALUE rb_f_rand(int argc, VALUE *argv, VALUE obj) { VALUE vmax; - rb_random_t *rnd = rand_start(&default_rand); + rb_random_t *rnd = rand_start(default_rand()); if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) { - VALUE v = rand_range(Qnil, rnd, vmax); + VALUE v = rand_range(obj, rnd, vmax); if (v != Qfalse) return v; vmax = rb_to_int(vmax); if (vmax != INT2FIX(0)) { - v = rand_int(Qnil, rnd, vmax, 0); + v = rand_int(obj, rnd, vmax, 0); if (!NIL_P(v)) return v; } } - return DBL2NUM(genrand_real(&rnd->mt)); + return DBL2NUM(random_real(obj, rnd, TRUE)); } /* * call-seq: * Random.rand -> float * Random.rand(max) -> number + * Random.rand(range) -> number + * + * Returns a random number using the Ruby system PRNG. * - * Alias of Random::DEFAULT.rand. + * See also Random#rand. */ - static VALUE random_s_rand(int argc, VALUE *argv, VALUE obj) { - VALUE v = rand_random(argc, argv, Qnil, rand_start(&default_rand)); + VALUE v = rand_random(argc, argv, Qnil, rand_start(default_rand())); check_random_number(v, argv); return v; } @@ -1413,33 +1693,33 @@ random_s_rand(int argc, VALUE *argv, VALUE obj) typedef struct { st_index_t hash; uint8_t sip[16]; -} seed_keys_t; +} hash_salt_t; static union { - seed_keys_t key; - uint32_t u32[type_roomof(seed_keys_t, uint32_t)]; -} seed; + hash_salt_t key; + uint32_t u32[type_roomof(hash_salt_t, uint32_t)]; +} hash_salt; static void -init_seed(struct MT *mt) +init_hash_salt(struct MT *mt) { int i; - for (i = 0; i < numberof(seed.u32); ++i) - seed.u32[i] = genrand_int32(mt); + for (i = 0; i < numberof(hash_salt.u32); ++i) + hash_salt.u32[i] = genrand_int32(mt); } NO_SANITIZE("unsigned-integer-overflow", extern st_index_t rb_hash_start(st_index_t h)); st_index_t rb_hash_start(st_index_t h) { - return st_hash_start(seed.key.hash + h); + return st_hash_start(hash_salt.key.hash + h); } st_index_t rb_memhash(const void *ptr, long len) { - sip_uint64_t h = sip_hash13(seed.key.sip, ptr, len); + sip_uint64_t h = sip_hash13(hash_salt.key.sip, ptr, len); #ifdef HAVE_UINT64_T return (st_index_t)h; #else @@ -1452,54 +1732,31 @@ rb_memhash(const void *ptr, long len) void Init_RandomSeedCore(void) { + if (!fill_random_bytes(&hash_salt, sizeof(hash_salt), FALSE)) return; + /* - Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't + If failed to fill siphash's salt with random data, expand less random + data with MT. + + Don't reuse this MT for default_rand(). default_rand()::seed shouldn't provide a hint that an attacker guess siphash's seed. */ struct MT mt; - uint32_t initial_seed[DEFAULT_SEED_CNT]; - - fill_random_seed(initial_seed, DEFAULT_SEED_CNT); - init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT); - - init_seed(&mt); - - explicit_bzero(initial_seed, DEFAULT_SEED_LEN); -} - -static VALUE -init_randomseed(struct MT *mt) -{ - uint32_t initial[DEFAULT_SEED_CNT+1]; - VALUE seed; - fill_random_seed(initial, DEFAULT_SEED_CNT); - init_by_array(mt, initial, DEFAULT_SEED_CNT); - seed = make_seed_value(initial, DEFAULT_SEED_CNT); - explicit_bzero(initial, DEFAULT_SEED_LEN); - return seed; -} - -/* construct Random::DEFAULT bits */ -static VALUE -Init_Random_default(VALUE klass) -{ - rb_random_t *r = &default_rand; - struct MT *mt = &r->mt; - VALUE v = TypedData_Wrap_Struct(klass, &random_mt_type, r); - - rb_gc_register_mark_object(v); - r->seed = init_randomseed(mt); + with_random_seed(DEFAULT_SEED_CNT, 0) { + init_by_array(&mt, seedbuf, DEFAULT_SEED_CNT); + } - return v; + init_hash_salt(&mt); + explicit_bzero(&mt, sizeof(mt)); } void rb_reset_random_seed(void) { - rb_random_t *r = &default_rand; + rb_random_mt_t *r = default_rand(); uninit_genrand(&r->mt); - r->seed = INT2FIX(0); + r->base.seed = INT2FIX(0); } /* @@ -1515,60 +1772,81 @@ rb_reset_random_seed(void) * * The class method Random.rand provides the base functionality of Kernel.rand * along with better handling of floating point values. These are both - * interfaces to Random::DEFAULT, the Ruby system PRNG. + * interfaces to the Ruby system PRNG. * - * Random.new will create a new PRNG with a state independent of - * Random::DEFAULT, allowing multiple generators with different seed values or + * Random.new will create a new PRNG with a state independent of the Ruby + * system PRNG, allowing multiple generators with different seed values or * sequence positions to exist simultaneously. Random objects can be * marshaled, allowing sequences to be saved and resumed. * * PRNGs are currently implemented as a modified Mersenne Twister with a period - * of 2**19937-1. + * of 2**19937-1. As this algorithm is _not_ for cryptographical use, you must + * use SecureRandom for security purpose, instead of this PRNG. */ void InitVM_Random(void) { + VALUE base; + ID id_base = rb_intern_const("Base"); + rb_define_global_function("srand", rb_f_srand, -1); rb_define_global_function("rand", rb_f_rand, -1); - rb_cRandom = rb_define_class("Random", rb_cObject); + base = rb_define_class_id(id_base, rb_cObject); + rb_undef_alloc_func(base); + rb_cRandom = rb_define_class("Random", base); + rb_const_set(rb_cRandom, id_base, base); rb_define_alloc_func(rb_cRandom, random_alloc); + rb_define_method(base, "initialize", random_init, -1); + rb_define_method(base, "rand", random_rand, -1); + rb_define_method(base, "bytes", random_bytes, 1); + rb_define_method(base, "seed", random_get_seed, 0); + rb_define_method(rb_cRandom, "initialize_copy", rand_mt_copy, 1); + rb_define_private_method(rb_cRandom, "marshal_dump", rand_mt_dump, 0); + rb_define_private_method(rb_cRandom, "marshal_load", rand_mt_load, 1); + rb_define_private_method(rb_cRandom, "state", rand_mt_state, 0); + rb_define_private_method(rb_cRandom, "left", rand_mt_left, 0); + rb_define_method(rb_cRandom, "==", rand_mt_equal, 1); + +#if 0 /* for RDoc: it can't handle unnamed base class */ rb_define_method(rb_cRandom, "initialize", random_init, -1); rb_define_method(rb_cRandom, "rand", random_rand, -1); rb_define_method(rb_cRandom, "bytes", random_bytes, 1); rb_define_method(rb_cRandom, "seed", random_get_seed, 0); - rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1); - rb_define_private_method(rb_cRandom, "marshal_dump", random_dump, 0); - rb_define_private_method(rb_cRandom, "marshal_load", random_load, 1); - rb_define_private_method(rb_cRandom, "state", random_state, 0); - rb_define_private_method(rb_cRandom, "left", random_left, 0); - rb_define_method(rb_cRandom, "==", random_equal, 1); +#endif - { - /* Direct access to Ruby's Pseudorandom number generator (PRNG). */ - VALUE rand_default = Init_Random_default(rb_cRandom); - /* The default Pseudorandom number generator. Used by class - * methods of Random. */ - rb_define_const(rb_cRandom, "DEFAULT", rand_default); - } + rb_define_const(rb_cRandom, "DEFAULT", rb_cRandom); + rb_deprecate_constant(rb_cRandom, "DEFAULT"); rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1); rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1); rb_define_singleton_method(rb_cRandom, "bytes", random_s_bytes, 1); + rb_define_singleton_method(rb_cRandom, "seed", random_s_seed, 0); rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0); rb_define_singleton_method(rb_cRandom, "urandom", random_raw_seed, 1); rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0); rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0); { - /* Format raw random number as Random does */ + /* + * Generate a random number in the given range as Random does + * + * prng.random_number #=> 0.5816771641321361 + * prng.random_number(1000) #=> 485 + * prng.random_number(1..6) #=> 3 + * prng.rand #=> 0.5816771641321361 + * prng.rand(1000) #=> 485 + * prng.rand(1..6) #=> 3 + */ VALUE m = rb_define_module_under(rb_cRandom, "Formatter"); - rb_include_module(rb_cRandom, m); - rb_extend_object(rb_cRandom, m); + rb_include_module(base, m); + rb_extend_object(base, m); rb_define_method(m, "random_number", rand_random_number, -1); rb_define_method(m, "rand", rand_random_number, -1); } + + default_rand_key = rb_ractor_local_storage_ptr_newkey(&default_rand_key_storage_type); } #undef rb_intern diff --git a/ruby/range.c b/ruby/range.c index bf14c0c7a..6eb784231 100644 --- a/ruby/range.c +++ b/ruby/range.c @@ -9,26 +9,37 @@ **********************************************************************/ -#include "internal.h" -#include "id.h" +#include "ruby/internal/config.h" + #include +#include #ifdef HAVE_FLOAT_H #include #endif -#include + +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compar.h" +#include "internal/enum.h" +#include "internal/enumerator.h" +#include "internal/error.h" +#include "internal/numeric.h" +#include "internal/range.h" VALUE rb_cRange; static ID id_beg, id_end, id_excl; #define id_cmp idCmp #define id_succ idSucc +#define id_min idMin +#define id_max idMax static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE); #define RANGE_SET_BEG(r, v) (RSTRUCT_SET(r, 0, v)) #define RANGE_SET_END(r, v) (RSTRUCT_SET(r, 1, v)) #define RANGE_SET_EXCL(r, v) (RSTRUCT_SET(r, 2, v)) -#define RBOOL(v) ((v) ? Qtrue : Qfalse) #define EXCL(r) RTEST(RANGE_EXCL(r)) @@ -46,6 +57,10 @@ range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end) RANGE_SET_EXCL(range, exclude_end); RANGE_SET_BEG(range, beg); RANGE_SET_END(range, end); + + if (CLASS_OF(range) == rb_cRange) { + rb_obj_freeze(range); + } } VALUE @@ -69,11 +84,17 @@ range_modify(VALUE range) /* * call-seq: - * Range.new(begin, end, exclude_end=false) -> rng + * Range.new(begin, end, exclude_end = false) -> new_range + * + * Returns a new range based on the given objects +begin+ and +end+. + * Optional argument +exclude_end+ determines whether object +end+ + * is included as the last object in the range: + * + * Range.new(2, 5).to_a # => [2, 3, 4, 5] + * Range.new(2, 5, true).to_a # => [2, 3, 4] + * Range.new('a', 'd').to_a # => ["a", "b", "c", "d"] + * Range.new('a', 'd', true).to_a # => ["a", "b", "c"] * - * Constructs a range using the given +begin+ and +end+. If the +exclude_end+ - * parameter is omitted or is false, the range will include - * the end object; otherwise, it will be excluded. */ static VALUE @@ -98,18 +119,20 @@ range_initialize_copy(VALUE range, VALUE orig) /* * call-seq: - * rng.exclude_end? -> true or false + * exclude_end? -> true or false * - * Returns true if the range excludes its end value. + * Returns +true+ if +self+ excludes its end value; +false+ otherwise: * - * (1..5).exclude_end? #=> false - * (1...5).exclude_end? #=> true + * Range.new(2, 5).exclude_end? # => false + * Range.new(2, 5, true).exclude_end? # => true + * (2..5).exclude_end? # => false + * (2...5).exclude_end? # => true */ static VALUE range_exclude_end_p(VALUE range) { - return EXCL(range) ? Qtrue : Qfalse; + return RBOOL(EXCL(range)); } static VALUE @@ -121,23 +144,38 @@ recursive_equal(VALUE range, VALUE obj, int recur) if (!rb_equal(RANGE_END(range), RANGE_END(obj))) return Qfalse; - if (EXCL(range) != EXCL(obj)) - return Qfalse; - return Qtrue; + return RBOOL(EXCL(range) == EXCL(obj)); } /* * call-seq: - * rng == obj -> true or false + * self == other -> true or false + * + * Returns +true+ if and only if: + * + * - +other+ is a range. + * - other.begin == self.begin. + * - other.end == self.end. + * - other.exclude_end? == self.exclude_end?. + * + * Otherwise returns +false+. + * + * r = (1..5) + * r == (1..5) # => true + * r = Range.new(1, 5) + * r == 'foo' # => false + * r == (2..5) # => false + * r == (1..4) # => false + * r == (1...5) # => false + * r == Range.new(1, 5, true) # => false + * + * Note that even with the same argument, the return values of #== and #eql? can differ: * - * Returns true only if +obj+ is a Range, has equivalent - * begin and end items (by comparing them with ==), and has - * the same #exclude_end? setting as the range. + * (1..2) == (1..2.0) # => true + * (1..2).eql? (1..2.0) # => false * - * (0..2) == (0..2) #=> true - * (0..2) == Range.new(0,2) #=> true - * (0..2) == (0...2) #=> false + * Related: Range#eql?. * */ @@ -176,23 +214,37 @@ recursive_eql(VALUE range, VALUE obj, int recur) if (!rb_eql(RANGE_END(range), RANGE_END(obj))) return Qfalse; - if (EXCL(range) != EXCL(obj)) - return Qfalse; - return Qtrue; + return RBOOL(EXCL(range) == EXCL(obj)); } /* * call-seq: - * rng.eql?(obj) -> true or false + * eql?(other) -> true or false + * + * Returns +true+ if and only if: + * + * - +other+ is a range. + * - other.begin eql? self.begin. + * - other.end eql? self.end. + * - other.exclude_end? == self.exclude_end?. + * + * Otherwise returns +false+. * - * Returns true only if +obj+ is a Range, has equivalent - * begin and end items (by comparing them with eql?), - * and has the same #exclude_end? setting as the range. + * r = (1..5) + * r.eql?(1..5) # => true + * r = Range.new(1, 5) + * r.eql?('foo') # => false + * r.eql?(2..5) # => false + * r.eql?(1..4) # => false + * r.eql?(1...5) # => false + * r.eql?(Range.new(1, 5, true)) # => false * - * (0..2).eql?(0..2) #=> true - * (0..2).eql?(Range.new(0,2)) #=> true - * (0..2).eql?(0...2) #=> false + * Note that even with the same argument, the return values of #== and #eql? can differ: * + * (1..2) == (1..2.0) # => true + * (1..2).eql? (1..2.0) # => false + * + * Related: Range#==. */ static VALUE @@ -207,13 +259,13 @@ range_eql(VALUE range, VALUE obj) /* * call-seq: - * rng.hash -> integer + * hash -> integer * - * Compute a hash-code for this range. Two ranges with equal - * begin and end points (using eql?), and the same - * #exclude_end? value will generate the same hash-code. + * Returns the integer hash value for +self+. + * Two range objects +r0+ and +r1+ have the same hash value + * if and only if r0.eql?(r1). * - * See also Object#hash. + * Related: Range#eql?, Object#hash. */ static VALUE @@ -256,8 +308,8 @@ range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg) } } -static int -sym_step_i(VALUE i, VALUE arg) +static bool +step_i_iter(VALUE arg) { VALUE *iter = (VALUE *)arg; @@ -267,9 +319,16 @@ sym_step_i(VALUE i, VALUE arg) else { iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1)); } - if (iter[0] == INT2FIX(0)) { + if (iter[0] != INT2FIX(0)) return false; + iter[0] = iter[1]; + return true; +} + +static int +sym_step_i(VALUE i, VALUE arg) +{ + if (step_i_iter(arg)) { rb_yield(rb_str_intern(i)); - iter[0] = iter[1]; } return 0; } @@ -277,17 +336,8 @@ sym_step_i(VALUE i, VALUE arg) static int step_i(VALUE i, VALUE arg) { - VALUE *iter = (VALUE *)arg; - - if (FIXNUM_P(iter[0])) { - iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG; - } - else { - iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1)); - } - if (iter[0] == INT2FIX(0)) { + if (step_i_iter(arg)) { rb_yield(i); - iter[0] = iter[1]; } return 0; } @@ -295,7 +345,6 @@ step_i(VALUE i, VALUE arg) static int discrete_object_p(VALUE obj) { - if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */ return rb_respond_to(obj, id_succ); } @@ -308,6 +357,8 @@ linear_object_p(VALUE obj) case T_FLOAT: case T_BIGNUM: return TRUE; + default: + break; } if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE; if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE; @@ -348,45 +399,42 @@ range_step_size(VALUE range, VALUE args, VALUE eobj) } /* - * Document-method: Range#step - * Document-method: Range#% * call-seq: - * rng.step(n=1) {| obj | block } -> rng - * rng.step(n=1) -> an_enumerator - * rng.step(n=1) -> an_arithmetic_sequence - * rng % n -> an_enumerator - * rng % n -> an_arithmetic_sequence - * - * Iterates over the range, passing each nth element to the block. - * If begin and end are numeric, +n+ is added for each iteration. - * Otherwise #step invokes #succ to iterate through range elements. - * - * If no block is given, an enumerator is returned instead. - * Especially, the enumerator is an Enumerator::ArithmeticSequence - * if begin and end of the range are numeric. - * - * range = Xs.new(1)..Xs.new(10) - * range.step(2) {|x| puts x} - * puts - * range.step(3) {|x| puts x} - * - * produces: - * - * 1 x - * 3 xxx - * 5 xxxxx - * 7 xxxxxxx - * 9 xxxxxxxxx - * - * 1 x - * 4 xxxx - * 7 xxxxxxx - * 10 xxxxxxxxxx - * - * See Range for the definition of class Xs. + * step(n = 1) {|element| ... } -> self + * step(n = 1) -> enumerator + * + * Iterates over the elements of +self+. + * + * With a block given and no argument, + * calls the block each element of the range; returns +self+: + * + * a = [] + * (1..5).step {|element| a.push(element) } # => 1..5 + * a # => [1, 2, 3, 4, 5] + * a = [] + * ('a'..'e').step {|element| a.push(element) } # => "a".."e" + * a # => ["a", "b", "c", "d", "e"] + * + * With a block given and a positive integer argument +n+ given, + * calls the block with element +0+, element +n+, element 2n, and so on: + * + * a = [] + * (1..5).step(2) {|element| a.push(element) } # => 1..5 + * a # => [1, 3, 5] + * a = [] + * ('a'..'e').step(2) {|element| a.push(element) } # => "a".."e" + * a # => ["a", "c", "e"] + * + * With no block given, returns an enumerator, + * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric; + * otherwise of class Enumerator: + * + * e = (1..5).step(2) # => ((1..5).step(2)) + * e.class # => Enumerator::ArithmeticSequence + * ('a'..'e').step # => # + * + * Related: Range#%. */ - - static VALUE range_step(int argc, VALUE *argv, VALUE range) { @@ -397,6 +445,13 @@ range_step(int argc, VALUE *argv, VALUE range) step = (!rb_check_arity(argc, 0, 1) ? INT2FIX(1) : argv[0]); if (!rb_block_given_p()) { + if (!rb_obj_is_kind_of(step, rb_cNumeric)) { + step = rb_to_int(step); + } + if (rb_equal(step, INT2FIX(0))) { + rb_raise(rb_eArgError, "step can't be 0"); + } + const VALUE b_num_p = rb_obj_is_kind_of(b, rb_cNumeric); const VALUE e_num_p = rb_obj_is_kind_of(e, rb_cNumeric); if ((b_num_p && (NIL_P(e) || e_num_p)) || (NIL_P(b) && e_num_p)) { @@ -408,6 +463,7 @@ range_step(int argc, VALUE *argv, VALUE range) } step = check_step_domain(step); + VALUE iter[2] = {INT2FIX(1), step}; if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) { long i = FIX2LONG(b), unit = FIX2LONG(step); @@ -435,10 +491,6 @@ range_step(int argc, VALUE *argv, VALUE range) } else if (SYMBOL_P(b) && (NIL_P(e) || SYMBOL_P(e))) { /* symbols are special */ - VALUE iter[2]; - iter[0] = INT2FIX(1); - iter[1] = step; - b = rb_sym2str(b); if (NIL_P(e)) { rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter); @@ -467,12 +519,7 @@ range_step(int argc, VALUE *argv, VALUE range) tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { - VALUE iter[2]; - b = tmp; - iter[0] = INT2FIX(1); - iter[1] = step; - if (NIL_P(e)) { rb_str_upto_endless_each(b, step_i, (VALUE)iter); } @@ -481,20 +528,43 @@ range_step(int argc, VALUE *argv, VALUE range) } } else { - VALUE args[2]; - if (!discrete_object_p(b)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(b)); } - args[0] = INT2FIX(1); - args[1] = step; - range_each_func(range, step_i, (VALUE)args); + range_each_func(range, step_i, (VALUE)iter); } } return range; } +/* + * call-seq: + * %(n) {|element| ... } -> self + * %(n) -> enumerator + * + * Iterates over the elements of +self+. + * + * With a block given, calls the block with selected elements of the range; + * returns +self+: + * + * a = [] + * (1..5).%(2) {|element| a.push(element) } # => 1..5 + * a # => [1, 3, 5] + * a = [] + * ('a'..'e').%(2) {|element| a.push(element) } # => "a".."e" + * a # => ["a", "c", "e"] + * + * With no block given, returns an enumerator, + * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric; + * otherwise of class Enumerator: + * + * e = (1..5) % 2 # => ((1..5).%(2)) + * e.class # => Enumerator::ArithmeticSequence + * ('a'..'e') % 2 # => # + * + * Related: Range#step. + */ static VALUE range_percent_step(VALUE range, VALUE step) { @@ -558,7 +628,7 @@ bsearch_integer_range(VALUE beg, VALUE end, int excl) satisfied = val; \ smaller = 1; \ } \ - else if (v == Qfalse || v == Qnil) { \ + else if (!RTEST(v)) { \ smaller = 0; \ } \ else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \ @@ -601,54 +671,12 @@ bsearch_integer_range(VALUE beg, VALUE end, int excl) /* * call-seq: - * rng.bsearch {|obj| block } -> value - * - * By using binary search, finds a value in range which meets the given - * condition in O(log n) where n is the size of the range. + * bsearch {|obj| block } -> value * - * You can use this method in two use cases: a find-minimum mode and - * a find-any mode. In either case, the elements of the range must be - * monotone (or sorted) with respect to the block. + * Returns an element from +self+ selected by a binary search. * - * In find-minimum mode (this is a good choice for typical use case), - * the block must return true or false, and there must be a value x - * so that: + * See {Binary Searching}[rdoc-ref:bsearch.rdoc]. * - * - the block returns false for any value which is less than x, and - * - the block returns true for any value which is greater than or - * equal to x. - * - * If x is within the range, this method returns the value x. - * Otherwise, it returns nil. - * - * ary = [0, 4, 7, 10, 12] - * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1 - * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2 - * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3 - * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil - * - * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0 - * - * In find-any mode (this behaves like libc's bsearch(3)), the block - * must return a number, and there must be two values x and y (x <= y) - * so that: - * - * - the block returns a positive number for v if v < x, - * - the block returns zero for v if x <= v < y, and - * - the block returns a negative number for v if y <= v. - * - * This method returns any value which is within the intersection of - * the given range and x...y (if any). If there is no value that - * satisfies the condition, it returns nil. - * - * ary = [0, 100, 100, 100, 200] - * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3 - * (0..4).bsearch {|i| 300 - ary[i] } #=> nil - * (0..4).bsearch {|i| 50 - ary[i] } #=> nil - * - * You must not mix the two modes at a time; the block must always - * return either true/false, or always return a number. It is - * undefined which value is actually picked up at each iteration. */ static VALUE @@ -705,7 +733,7 @@ range_bsearch(VALUE range) BSEARCH(INT2FIX); } #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T) - else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) { + else if (RB_FLOAT_TYPE_P(beg) || RB_FLOAT_TYPE_P(end)) { int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg))); int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end))); int64_t mid, org_high; @@ -756,20 +784,23 @@ each_i(VALUE v, VALUE arg) static int sym_each_i(VALUE v, VALUE arg) { - rb_yield(rb_str_intern(v)); - return 0; + return each_i(rb_str_intern(v), arg); } /* * call-seq: - * rng.size -> num + * size -> non_negative_integer or Infinity or nil * - * Returns the number of elements in the range. Both the begin and the end of - * the Range must be Numeric, otherwise nil is returned. + * Returns the count of elements in +self+ + * if both begin and end values are numeric; + * otherwise, returns +nil+: * - * (10..20).size #=> 11 + * (1..4).size # => 4 + * (1...4).size # => 3 + * (1..).size # => Infinity * ('a'..'z').size #=> nil - * (-Float::INFINITY..Float::INFINITY).size #=> Infinity + * + * Related: Range#count. */ static VALUE @@ -793,13 +824,16 @@ range_size(VALUE range) /* * call-seq: - * rng.to_a -> array - * rng.entries -> array + * to_a -> array + * + * Returns an array containing the elements in +self+, if a finite collection; + * raises an exception otherwise. * - * Returns an array containing the items in the range. + * (1..4).to_a # => [1, 2, 3, 4] + * (1...4).to_a # => [1, 2, 3] + * ('a'..'d').to_a # => ["a", "b", "c", "d"] * - * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7] - * (1..).to_a #=> RangeError: cannot convert endless range to an array + * Range#entries is an alias for Range#to_a. */ static VALUE @@ -817,32 +851,60 @@ range_enum_size(VALUE range, VALUE args, VALUE eobj) return range_size(range); } +RBIMPL_ATTR_NORETURN() +static void +range_each_bignum_endless(VALUE beg) +{ + for (;; beg = rb_big_plus(beg, INT2FIX(1))) { + rb_yield(beg); + } + UNREACHABLE; +} + +RBIMPL_ATTR_NORETURN() +static void +range_each_fixnum_endless(VALUE beg) +{ + for (long i = FIX2LONG(beg); FIXABLE(i); i++) { + rb_yield(LONG2FIX(i)); + } + + range_each_bignum_endless(LONG2NUM(RUBY_FIXNUM_MAX + 1)); + UNREACHABLE; +} + +static VALUE +range_each_fixnum_loop(VALUE beg, VALUE end, VALUE range) +{ + long lim = FIX2LONG(end) + !EXCL(range); + for (long i = FIX2LONG(beg); i < lim; i++) { + rb_yield(LONG2FIX(i)); + } + return range; +} + /* * call-seq: - * rng.each {| i | block } -> rng - * rng.each -> an_enumerator + * each {|element| ... } -> self + * each -> an_enumerator * - * Iterates over the elements of range, passing each in turn to the - * block. + * With a block given, passes each element of +self+ to the block: * - * The +each+ method can only be used if the begin object of the range - * supports the +succ+ method. A TypeError is raised if the object - * does not have +succ+ method defined (like Float). + * a = [] + * (1..4).each {|element| a.push(element) } # => 1..4 + * a # => [1, 2, 3, 4] * - * If no block is given, an enumerator is returned instead. + * Raises an exception unless self.first.respond_to?(:succ). * - * (10..15).each {|n| print n, ' ' } - * # prints: 10 11 12 13 14 15 + * With no block given, returns an enumerator. * - * (2.5..5).each {|n| print n, ' ' } - * # raises: TypeError: can't iterate from Float */ static VALUE range_each(VALUE range) { VALUE beg, end; - long i, lim; + long i; RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size); @@ -850,24 +912,10 @@ range_each(VALUE range) end = RANGE_END(range); if (FIXNUM_P(beg) && NIL_P(end)) { - fixnum_endless: - i = FIX2LONG(beg); - while (FIXABLE(i)) { - rb_yield(LONG2FIX(i++)); - } - beg = LONG2NUM(i); - bignum_endless: - for (;; beg = rb_big_plus(beg, INT2FIX(1))) - rb_yield(beg); + range_each_fixnum_endless(beg); } else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */ - fixnum_loop: - lim = FIX2LONG(end); - if (!EXCL(range)) - lim += 1; - for (i = FIX2LONG(beg); i < lim; i++) { - rb_yield(LONG2FIX(i)); - } + return range_each_fixnum_loop(beg, end, range); } else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) { if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */ @@ -876,11 +924,11 @@ range_each(VALUE range) do { rb_yield(beg); } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1)))); - if (NIL_P(end)) goto fixnum_endless; - if (FIXNUM_P(end)) goto fixnum_loop; + if (NIL_P(end)) range_each_fixnum_endless(beg); + if (FIXNUM_P(end)) return range_each_fixnum_loop(beg, end, range); } else { - if (NIL_P(end)) goto bignum_endless; + if (NIL_P(end)) range_each_bignum_endless(beg); if (FIXNUM_P(end)) return range; } } @@ -948,11 +996,14 @@ range_each(VALUE range) /* * call-seq: - * rng.begin -> obj + * self.begin -> object + * + * Returns the object that defines the beginning of +self+. * - * Returns the object that defines the beginning of the range. + * (1..4).begin # => 1 + * (..2).begin # => nil * - * (1..10).begin #=> 1 + * Related: Range#first, Range#end. */ static VALUE @@ -964,12 +1015,15 @@ range_begin(VALUE range) /* * call-seq: - * rng.end -> obj + * self.end -> object * - * Returns the object that defines the end of the range. + * Returns the object that defines the end of +self+. * - * (1..10).end #=> 10 - * (1...10).end #=> 10 + * (1..4).end # => 4 + * (1...4).end # => 4 + * (1..).end # => nil + * + * Related: Range#begin, Range#last. */ @@ -991,20 +1045,30 @@ first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg)) } rb_ary_push(ary[1], i); n--; - ary[0] = INT2NUM(n); + ary[0] = LONG2NUM(n); return Qnil; } /* * call-seq: - * rng.first -> obj - * rng.first(n) -> an_array + * first -> object + * first(n) -> array + * + * With no argument, returns the first element of +self+, if it exists: + * + * (1..4).first # => 1 + * ('a'..'d').first # => "a" + * + * With non-negative integer argument +n+ given, + * returns the first +n+ elements in an array: + * + * (1..10).first(3) # => [1, 2, 3] + * (1..10).first(0) # => [] + * (1..4).first(50) # => [1, 2, 3, 4] * - * Returns the first object in the range, or an array of the first +n+ - * elements. + * Raises an exception if there is no first element: * - * (10..20).first #=> 10 - * (10..20).first(3) #=> [10, 11, 12] + * (..4).first # Raises RangeError */ static VALUE @@ -1080,19 +1144,37 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range) /* * call-seq: - * rng.last -> obj - * rng.last(n) -> an_array + * last -> object + * last(n) -> array * - * Returns the last object in the range, - * or an array of the last +n+ elements. + * With no argument, returns the last element of +self+, if it exists: * - * Note that with no arguments +last+ will return the object that defines - * the end of the range even if #exclude_end? is +true+. + * (1..4).last # => 4 + * ('a'..'d').last # => "d" + * + * Note that +last+ with no argument returns the end element of +self+ + * even if #exclude_end? is +true+: + * + * (1...4).last # => 4 + * ('a'...'d').last # => "d" + * + * With non-negative integer argument +n+ given, + * returns the last +n+ elements in an array: + * + * (1..10).last(3) # => [8, 9, 10] + * (1..10).last(0) # => [] + * (1..4).last(50) # => [1, 2, 3, 4] + * + * Note that +last+ with argument does not return the end element of +self+ + * if #exclude_end? it +true+: + * + * (1...4).last(3) # => [1, 2, 3] + * ('a'...'d').last(3) # => ["a", "b", "c"] + * + * Raises an exception if there is no last element: + * + * (1..).last # Raises RangeError * - * (10..20).last #=> 20 - * (10...20).last #=> 20 - * (10..20).last(3) #=> [18, 19, 20] - * (10...20).last(3) #=> [17, 18, 19] */ static VALUE @@ -1117,19 +1199,82 @@ range_last(int argc, VALUE *argv, VALUE range) /* * call-seq: - * rng.min -> obj - * rng.min {| a,b | block } -> obj - * rng.min(n) -> array - * rng.min(n) {| a,b | block } -> array + * min -> object + * min(n) -> array + * min {|a, b| ... } -> object + * min(n) {|a, b| ... } -> array + * + * Returns the minimum value in +self+, + * using method <=> or a given block for comparison. * - * Returns the minimum value in the range. Returns +nil+ if the begin - * value of the range is larger than the end value. Returns +nil+ if - * the begin value of an exclusive range is equal to the end value. + * With no argument and no block given, + * returns the minimum-valued element of +self+. * - * Can be given an optional block to override the default comparison - * method a <=> b. + * (1..4).min # => 1 + * ('a'..'d').min # => "a" + * (-4..-1).min # => -4 * - * (10..20).min #=> 10 + * With non-negative integer argument +n+ given, and no block given, + * returns the +n+ minimum-valued elements of +self+ in an array: + * + * (1..4).min(2) # => [1, 2] + * ('a'..'d').min(2) # => ["a", "b"] + * (-4..-1).min(2) # => [-4, -3] + * (1..4).min(50) # => [1, 2, 3, 4] + * + * If a block is given, it is called: + * + * - First, with the first two element of +self+. + * - Then, sequentially, with the so-far minimum value and the next element of +self+. + * + * To illustrate: + * + * (1..4).min {|a, b| p [a, b]; a <=> b } # => 1 + * + * Output: + * + * [2, 1] + * [3, 1] + * [4, 1] + * + * With no argument and a block given, + * returns the return value of the last call to the block: + * + * (1..4).min {|a, b| -(a <=> b) } # => 4 + * + * With non-negative integer argument +n+ given, and a block given, + * returns the return values of the last +n+ calls to the block in an array: + * + * (1..4).min(2) {|a, b| -(a <=> b) } # => [4, 3] + * (1..4).min(50) {|a, b| -(a <=> b) } # => [4, 3, 2, 1] + * + * Returns an empty array if +n+ is zero: + * + * (1..4).min(0) # => [] + * (1..4).min(0) {|a, b| -(a <=> b) } # => [] + * + * Returns +nil+ or an empty array if: + * + * - The begin value of the range is larger than the end value: + * + * (4..1).min # => nil + * (4..1).min(2) # => [] + * (4..1).min {|a, b| -(a <=> b) } # => nil + * (4..1).min(2) {|a, b| -(a <=> b) } # => [] + * + * - The begin value of an exclusive range is equal to the end value: + * + * (1...1).min # => nil + * (1...1).min(2) # => [] + * (1...1).min {|a, b| -(a <=> b) } # => nil + * (1...1).min(2) {|a, b| -(a <=> b) } # => [] + * + * Raises an exception if either: + * + * - +self+ is a beginless range: (..4). + * - A block is given and +self+ is an endless range. + * + * Related: Range#max, Range#minmax. */ @@ -1163,19 +1308,83 @@ range_min(int argc, VALUE *argv, VALUE range) /* * call-seq: - * rng.max -> obj - * rng.max {| a,b | block } -> obj - * rng.max(n) -> obj - * rng.max(n) {| a,b | block } -> obj + * max -> object + * max(n) -> array + * max {|a, b| ... } -> object + * max(n) {|a, b| ... } -> array + * + * Returns the maximum value in +self+, + * using method <=> or a given block for comparison. + * + * With no argument and no block given, + * returns the maximum-valued element of +self+. + * + * (1..4).max # => 4 + * ('a'..'d').max # => "d" + * (-4..-1).max # => -1 + * + * With non-negative integer argument +n+ given, and no block given, + * returns the +n+ maximum-valued elements of +self+ in an array: + * + * (1..4).max(2) # => [4, 3] + * ('a'..'d').max(2) # => ["d", "c"] + * (-4..-1).max(2) # => [-1, -2] + * (1..4).max(50) # => [4, 3, 2, 1] + * + * If a block is given, it is called: + * + * - First, with the first two element of +self+. + * - Then, sequentially, with the so-far maximum value and the next element of +self+. + * + * To illustrate: + * + * (1..4).max {|a, b| p [a, b]; a <=> b } # => 4 + * + * Output: + * + * [2, 1] + * [3, 2] + * [4, 3] + * + * With no argument and a block given, + * returns the return value of the last call to the block: + * + * (1..4).max {|a, b| -(a <=> b) } # => 1 + * + * With non-negative integer argument +n+ given, and a block given, + * returns the return values of the last +n+ calls to the block in an array: + * + * (1..4).max(2) {|a, b| -(a <=> b) } # => [1, 2] + * (1..4).max(50) {|a, b| -(a <=> b) } # => [1, 2, 3, 4] + * + * Returns an empty array if +n+ is zero: + * + * (1..4).max(0) # => [] + * (1..4).max(0) {|a, b| -(a <=> b) } # => [] * - * Returns the maximum value in the range. Returns +nil+ if the begin - * value of the range larger than the end value. Returns +nil+ if - * the begin value of an exclusive range is equal to the end value. + * Returns +nil+ or an empty array if: * - * Can be given an optional block to override the default comparison - * method a <=> b. + * - The begin value of the range is larger than the end value: + * + * (4..1).max # => nil + * (4..1).max(2) # => [] + * (4..1).max {|a, b| -(a <=> b) } # => nil + * (4..1).max(2) {|a, b| -(a <=> b) } # => [] + * + * - The begin value of an exclusive range is equal to the end value: + * + * (1...1).max # => nil + * (1...1).max(2) # => [] + * (1...1).max {|a, b| -(a <=> b) } # => nil + * (1...1).max(2) {|a, b| -(a <=> b) } # => [] + * + * Raises an exception if either: + * + * - +self+ is a endless range: (1..). + * - A block is given and +self+ is a beginless range. + * + * Related: Range#min, Range#minmax. * - * (10..20).max #=> 20 */ static VALUE @@ -1188,16 +1397,17 @@ range_max(int argc, VALUE *argv, VALUE range) rb_raise(rb_eRangeError, "cannot get the maximum of endless range"); } + VALUE b = RANGE_BEG(range); + if (rb_block_given_p() || (EXCL(range) && !nm) || argc) { - if (NIL_P(RANGE_BEG(range))) { + if (NIL_P(b)) { rb_raise(rb_eRangeError, "cannot get the maximum of beginless range with custom comparison method"); } return rb_call_super(argc, argv); } else { struct cmp_opt_data cmp_opt = { 0, 0 }; - VALUE b = RANGE_BEG(range); - int c = OPTIMIZED_CMP(b, e, cmp_opt); + int c = NIL_P(b) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt); if (c > 0) return Qnil; @@ -1220,14 +1430,48 @@ range_max(int argc, VALUE *argv, VALUE range) /* * call-seq: - * rng.minmax -> [obj, obj] - * rng.minmax {| a,b | block } -> [obj, obj] + * minmax -> [object, object] + * minmax {|a, b| ... } -> [object, object] + * + * Returns a 2-element array containing the minimum and maximum value in +self+, + * either according to comparison method <=> or a given block. + * + * With no block given, returns the minimum and maximum values, + * using <=> for comparison: + * + * (1..4).minmax # => [1, 4] + * (1...4).minmax # => [1, 3] + * ('a'..'d').minmax # => ["a", "d"] + * (-4..-1).minmax # => [-4, -1] + * + * With a block given, the block must return an integer: + * + * - Negative if +a+ is smaller than +b+. + * - Zero if +a+ and +b+ are equal. + * - Positive if +a+ is larger than +b+. + * + * The block is called self.size times to compare elements; + * returns a 2-element Array containing the minimum and maximum values from +self+, + * per the block: + * + * (1..4).minmax {|a, b| -(a <=> b) } # => [4, 1] + * + * Returns [nil, nil] if: + * + * - The begin value of the range is larger than the end value: + * + * (4..1).minmax # => [nil, nil] + * (4..1).minmax {|a, b| -(a <=> b) } # => [nil, nil] + * + * - The begin value of an exclusive range is equal to the end value: * - * Returns a two element array which contains the minimum and the - * maximum value in the range. + * (1...1).minmax # => [nil, nil] + * (1...1).minmax {|a, b| -(a <=> b) } # => [nil, nil] + * + * Raises an exception if +self+ is a beginless or an endless range. + * + * Related: Range#min, Range#max. * - * Can be given an optional block to override the default comparison - * method a <=> b. */ static VALUE @@ -1236,7 +1480,10 @@ range_minmax(VALUE range) if (rb_block_given_p()) { return rb_call_super(0, NULL); } - return rb_assoc_new(range_min(0, NULL, range), range_max(0, NULL, range)); + return rb_assoc_new( + rb_funcall(range, id_min, 0), + rb_funcall(range, id_max, 0) + ); } int @@ -1269,57 +1516,100 @@ rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp) return (int)Qtrue; } +/* Extract the components of a Range. + * + * You can use +err+ to control the behavior of out-of-range and exception. + * + * When +err+ is 0 or 2, if the begin offset is greater than +len+, + * it is out-of-range. The +RangeError+ is raised only if +err+ is 2, + * in this case. If +err+ is 0, +Qnil+ will be returned. + * + * When +err+ is 1, the begin and end offsets won't be adjusted even if they + * are greater than +len+. It allows +rb_ary_aset+ extends arrays. + * + * If the begin component of the given range is negative and is too-large + * abstract value, the +RangeError+ is raised only +err+ is 1 or 2. + * + * The case of err = 0 is used in item accessing methods such as + * +rb_ary_aref+, +rb_ary_slice_bang+, and +rb_str_aref+. + * + * The case of err = 1 is used in Array's methods such as + * +rb_ary_aset+ and +rb_ary_fill+. + * + * The case of err = 2 is used in +rb_str_aset+. + */ VALUE -rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err) +rb_range_component_beg_len(VALUE b, VALUE e, int excl, + long *begp, long *lenp, long len, int err) { - long beg, end, origbeg, origend; - VALUE b, e; - int excl; + long beg, end; - if (!rb_range_values(range, &b, &e, &excl)) - return Qfalse; beg = NIL_P(b) ? 0 : NUM2LONG(b); end = NIL_P(e) ? -1 : NUM2LONG(e); if (NIL_P(e)) excl = 0; - origbeg = beg; - origend = end; if (beg < 0) { - beg += len; - if (beg < 0) - goto out_of_range; + beg += len; + if (beg < 0) + goto out_of_range; } if (end < 0) - end += len; + end += len; if (!excl) - end++; /* include end point */ + end++; /* include end point */ if (err == 0 || err == 2) { - if (beg > len) - goto out_of_range; - if (end > len) - end = len; + if (beg > len) + goto out_of_range; + if (end > len) + end = len; } len = end - beg; if (len < 0) - len = 0; + len = 0; *begp = beg; *lenp = len; return Qtrue; out_of_range: - if (err) { - rb_raise(rb_eRangeError, "%ld..%s%ld out of range", - origbeg, excl ? "." : "", origend); - } return Qnil; } +VALUE +rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err) +{ + VALUE b, e; + int excl; + + if (!rb_range_values(range, &b, &e, &excl)) + return Qfalse; + + VALUE res = rb_range_component_beg_len(b, e, excl, begp, lenp, len, err); + if (NIL_P(res) && err) { + rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", range); + } + + return res; +} + /* * call-seq: - * rng.to_s -> string + * to_s -> string + * + * Returns a string representation of +self+, + * including begin.to_s and end.to_s: + * + * (1..4).to_s # => "1..4" + * (1...4).to_s # => "1...4" + * (1..).to_s # => "1.." + * (..4).to_s # => "..4" + * + * Note that returns from #to_s and #inspect may differ: + * + * ('a'..'d').to_s # => "a..d" + * ('a'..'d').inspect # => "\"a\"..\"d\"" + * + * Related: Range#inspect. * - * Convert this range object to a printable form (using #to_s to convert the - * begin and end objects). */ static VALUE @@ -1361,10 +1651,23 @@ inspect_range(VALUE range, VALUE dummy, int recur) /* * call-seq: - * rng.inspect -> string + * inspect -> string + * + * Returns a string representation of +self+, + * including begin.inspect and end.inspect: + * + * (1..4).inspect # => "1..4" + * (1...4).inspect # => "1...4" + * (1..).inspect # => "1.." + * (..4).inspect # => "..4" + * + * Note that returns from #to_s and #inspect may differ: + * + * ('a'..'d').to_s # => "a..d" + * ('a'..'d').inspect # => "\"a\"..\"d\"" + * + * Related: Range#to_s. * - * Convert this range object to a printable form (using #inspect to - * convert the begin and end objects). */ @@ -1378,27 +1681,40 @@ static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover /* * call-seq: - * rng === obj -> true or false + * self === object -> true or false * - * Returns true if +obj+ is between begin and end of range, - * false otherwise (same as #cover?). Conveniently, - * === is the comparison operator used by case - * statements. + * Returns +true+ if +object+ is between self.begin and self.end. + * +false+ otherwise: + * + * (1..4) === 2 # => true + * (1..4) === 5 # => false + * (1..4) === 'a' # => false + * (1..4) === 4 # => true + * (1...4) === 4 # => false + * ('a'..'d') === 'c' # => true + * ('a'..'d') === 'e' # => false + * + * A case statement uses method ===, and so: * * case 79 - * when 1..50 then puts "low" - * when 51..75 then puts "medium" - * when 76..100 then puts "high" - * end - * # Prints "high" + * when (1..50) + * "low" + * when (51..75) + * "medium" + * when (76..100) + * "high" + * end # => "high" * * case "2.6.5" - * when ..."2.4" then puts "EOL" - * when "2.4"..."2.5" then puts "maintenance" - * when "2.5"..."2.7" then puts "stable" - * when "2.7".. then puts "upcoming" - * end - * # Prints "stable" + * when ..."2.4" + * "EOL" + * when "2.4"..."2.5" + * "maintenance" + * when "2.5"..."3.0" + * "stable" + * when "3.1".. + * "upcoming" + * end # => "stable" * */ @@ -1413,23 +1729,33 @@ range_eqq(VALUE range, VALUE val) /* * call-seq: - * rng.member?(obj) -> true or false - * rng.include?(obj) -> true or false + * include?(object) -> true or false + * + * Returns +true+ if +object+ is an element of +self+, +false+ otherwise: * - * Returns true if +obj+ is an element of - * the range, false otherwise. + * (1..4).include?(2) # => true + * (1..4).include?(5) # => false + * (1..4).include?(4) # => true + * (1...4).include?(4) # => false + * ('a'..'d').include?('b') # => true + * ('a'..'d').include?('e') # => false + * ('a'..'d').include?('B') # => false + * ('a'..'d').include?('d') # => true + * ('a'...'d').include?('d') # => false * - * ("a".."z").include?("g") #=> true - * ("a".."z").include?("A") #=> false - * ("a".."z").include?("cc") #=> false + * If begin and end are numeric, #include? behaves like #cover? * - * If you need to ensure +obj+ is between +begin+ and +end+, use #cover? + * (1..3).include?(1.5) # => true + * (1..3).cover?(1.5) # => true * - * ("a".."z").cover?("cc") #=> true + * But when not numeric, the two methods may differ: * - * If begin and end are numeric, #include? behaves like #cover? + * ('a'..'d').include?('cc') # => false + * ('a'..'d').cover?('cc') # => true + * + * Related: Range#cover?. * - * (1..3).include?(1.5) # => true + * Range#member? is an alias for Range#include?. */ static VALUE @@ -1466,14 +1792,12 @@ range_include_internal(VALUE range, VALUE val, int string_use_cover) else if (NIL_P(beg)) { VALUE r = rb_funcall(val, id_cmp, 1, end); if (NIL_P(r)) return Qfalse; - if (rb_cmpint(r, val, end) <= 0) return Qtrue; - return Qfalse; + return RBOOL(rb_cmpint(r, val, end) <= 0); } else if (NIL_P(end)) { VALUE r = rb_funcall(beg, id_cmp, 1, val); if (NIL_P(r)) return Qfalse; - if (rb_cmpint(r, beg, val) <= 0) return Qtrue; - return Qfalse; + return RBOOL(rb_cmpint(r, beg, val) <= 0); } } return Qundef; @@ -1483,34 +1807,86 @@ static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val); /* * call-seq: - * rng.cover?(obj) -> true or false - * rng.cover?(range) -> true or false - * - * Returns true if +obj+ is between the begin and end of - * the range. - * - * This tests begin <= obj <= end when #exclude_end? is +false+ - * and begin <= obj < end when #exclude_end? is +true+. - * - * If called with a Range argument, returns true when the - * given range is covered by the receiver, - * by comparing the begin and end values. If the argument can be treated as - * a sequence, this method treats it that way. In the specific case of - * (a..b).cover?(c...d) with a <= c && b < d, - * the end of the sequence must be calculated, which may exhibit poor - * performance if c is non-numeric. - * Returns false if the begin value of the - * range is larger than the end value. Also returns +false+ if one of the - * internal calls to <=> returns +nil+ (indicating the objects - * are not comparable). - * - * ("a".."z").cover?("c") #=> true - * ("a".."z").cover?("5") #=> false - * ("a".."z").cover?("cc") #=> true - * ("a".."z").cover?(1) #=> false - * (1..5).cover?(2..3) #=> true - * (1..5).cover?(0..6) #=> false - * (1..5).cover?(1...6) #=> true + * cover?(object) -> true or false + * cover?(range) -> true or false + * + * Returns +true+ if the given argument is within +self+, +false+ otherwise. + * + * With non-range argument +object+, evaluates with <= and <. + * + * For range +self+ with included end value (#exclude_end? == false), + * evaluates thus: + * + * self.begin <= object <= self.end + * + * Examples: + * + * r = (1..4) + * r.cover?(1) # => true + * r.cover?(4) # => true + * r.cover?(0) # => false + * r.cover?(5) # => false + * r.cover?('foo') # => false + + * r = ('a'..'d') + * r.cover?('a') # => true + * r.cover?('d') # => true + * r.cover?(' ') # => false + * r.cover?('e') # => false + * r.cover?(0) # => false + * + * For range +r+ with excluded end value (#exclude_end? == true), + * evaluates thus: + * + * r.begin <= object < r.end + * + * Examples: + * + * r = (1...4) + * r.cover?(1) # => true + * r.cover?(3) # => true + * r.cover?(0) # => false + * r.cover?(4) # => false + * r.cover?('foo') # => false + + * r = ('a'...'d') + * r.cover?('a') # => true + * r.cover?('c') # => true + * r.cover?(' ') # => false + * r.cover?('d') # => false + * r.cover?(0) # => false + * + * With range argument +range+, compares the first and last + * elements of +self+ and +range+: + * + * r = (1..4) + * r.cover?(1..4) # => true + * r.cover?(0..4) # => false + * r.cover?(1..5) # => false + * r.cover?('a'..'d') # => false + + * r = (1...4) + * r.cover?(1..3) # => true + * r.cover?(1..4) # => false + * + * If begin and end are numeric, #cover? behaves like #include? + * + * (1..3).cover?(1.5) # => true + * (1..3).include?(1.5) # => true + * + * But when not numeric, the two methods may differ: + * + * ('a'..'d').cover?('cc') # => true + * ('a'..'d').include?('cc') # => false + * + * Returns +false+ if either: + * + * - The begin value of +self+ is larger than its end value. + * - An internal call to <=> returns +nil+; + * that is, the operands are not comparable. + * + * Related: Range#include?. + * */ static VALUE @@ -1544,7 +1920,7 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val) if (!NIL_P(end) && NIL_P(val_end)) return FALSE; if (!NIL_P(beg) && NIL_P(val_beg)) return FALSE; - if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > -EXCL(val)) return FALSE; + if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > (EXCL(val) ? -1 : 0)) return FALSE; if (!NIL_P(val_beg) && !r_cover_p(range, beg, end, val_beg)) return FALSE; cmp_end = r_less(end, val_end); @@ -1559,8 +1935,8 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val) return TRUE; } - val_max = rb_rescue2(r_call_max, val, NULL, Qnil, rb_eTypeError, (VALUE)0); - if (val_max == Qnil) return FALSE; + val_max = rb_rescue2(r_call_max, val, 0, Qnil, rb_eTypeError, (VALUE)0); + if (NIL_P(val_max)) return FALSE; return r_less(end, val_max) >= 0; } @@ -1579,10 +1955,7 @@ r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val) static VALUE range_dumper(VALUE range) { - VALUE v; - NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 1)); - - v = (VALUE)m; + VALUE v = rb_obj_alloc(rb_cObject); rb_ivar_set(v, id_excl, RANGE_EXCL(range)); rb_ivar_set(v, id_beg, RANGE_BEG(range)); @@ -1619,13 +1992,34 @@ range_alloc(VALUE klass) /* * call-seq: - * range.count -> int - * range.count(item) -> int - * range.count { |obj| block } -> int + * count -> integer + * count(object) -> integer + * count {|element| ... } -> integer + * + * Returns the count of elements, based on an argument or block criterion, if given. + * + * With no argument and no block given, returns the number of elements: + * + * (1..4).count # => 4 + * (1...4).count # => 3 + * ('a'..'d').count # => 4 + * ('a'...'d').count # => 3 + * (1..).count # => Infinity + * (..4).count # => Infinity + * + * With argument +object+, returns the number of +object+ found in +self+, + * which will usually be zero or one: + * + * (1..4).count(2) # => 1 + * (1..4).count(5) # => 0 + * (1..4).count('a') # => 0 * - * Identical to Enumerable#count, except it returns Infinity for endless - * ranges. + * With a block given, calls the block with each element; + * returns the number of elements for which the block returns a truthy value: * + * (1..4).count {|element| element < 3 } # => 2 + * + * Related: Range#size. */ static VALUE range_count(int argc, VALUE *argv, VALUE range) @@ -1653,108 +2047,228 @@ range_count(int argc, VALUE *argv, VALUE range) } } -/* A Range represents an interval---a set of values with a - * beginning and an end. Ranges may be constructed using the - * s..e and - * s...e literals, or with - * Range::new. Ranges constructed using .. - * run from the beginning to the end inclusively. Those created using - * ... exclude the end value. When used as an iterator, - * ranges return each value in the sequence. - * - * (-1..-5).to_a #=> [] - * (-5..-1).to_a #=> [-5, -4, -3, -2, -1] - * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"] - * ('a'...'e').to_a #=> ["a", "b", "c", "d"] - * - * == Beginless/Endless Ranges - * - * A "beginless range" and "endless range" represents a semi-infinite - * range. Literal notation for a beginless range is: - * - * (..1) - * # or - * (...1) - * - * Literal notation for an endless range is: - * - * (1..) - * # or similarly - * (1...) - * - * Which is equivalent to - * - * (1..nil) # or similarly (1...nil) - * Range.new(1, nil) # or Range.new(1, nil, true) - * - * Beginless/endless ranges are useful, for example, for idiomatic - * slicing of arrays: - * - * [1, 2, 3, 4, 5][...2] # => [1, 2] - * [1, 2, 3, 4, 5][2...] # => [3, 4, 5] - * - * Some implementation details: - * - * * +begin+ of beginless range and +end+ of endless range are +nil+; - * * +each+ of beginless range raises an exception; - * * +each+ of endless range enumerates infinite sequence (may be - * useful in combination with Enumerable#take_while or similar - * methods); - * * (1..) and (1...) are not equal, - * although technically representing the same sequence. - * - * == Custom Objects in Ranges - * - * Ranges can be constructed using any objects that can be compared - * using the <=> operator. - * Methods that treat the range as a sequence (#each and methods inherited - * from Enumerable) expect the begin object to implement a - * succ method to return the next object in sequence. - * The #step and #include? methods require the begin - * object to implement succ or to be numeric. - * - * In the Xs class below both <=> and - * succ are implemented so Xs can be used - * to construct ranges. Note that the Comparable module is included - * so the == method is defined in terms of <=>. - * - * class Xs # represent a string of 'x's - * include Comparable - * attr :length - * def initialize(n) - * @length = n - * end - * def succ - * Xs.new(@length + 1) - * end - * def <=>(other) - * @length <=> other.length - * end - * def to_s - * sprintf "%2d #{inspect}", @length - * end - * def inspect - * 'x' * @length - * end +/* A \Range object represents a collection of values + * that are between given begin and end values. + * + * You can create an \Range object explicitly with: + * + * - A {range literal}[doc/syntax/literals_rdoc.html#label-Range+Literals]: + * + * # Ranges that use '..' to include the given end value. + * (1..4).to_a # => [1, 2, 3, 4] + * ('a'..'d').to_a # => ["a", "b", "c", "d"] + * # Ranges that use '...' to exclude the given end value. + * (1...4).to_a # => [1, 2, 3] + * ('a'...'d').to_a # => ["a", "b", "c"] + * + * A range may be created using method Range.new: + * + * # Ranges that by default include the given end value. + * Range.new(1, 4).to_a # => [1, 2, 3, 4] + * Range.new('a', 'd').to_a # => ["a", "b", "c", "d"] + * # Ranges that use third argument +exclude_end+ to exclude the given end value. + * Range.new(1, 4, true).to_a # => [1, 2, 3] + * Range.new('a', 'd', true).to_a # => ["a", "b", "c"] + * + * == Beginless Ranges + * + * A _beginless_ _range_ has a definite end value, but a +nil+ begin value. + * Such a range includes all values up to the end value. + * + * r = (..4) # => nil..4 + * r.begin # => nil + * r.include?(-50) # => true + * r.include?(4) # => true + * + * r = (...4) # => nil...4 + * r.include?(4) # => false + * + * Range.new(nil, 4) # => nil..4 + * Range.new(nil, 4, true) # => nil...4 + * + * A beginless range may be used to slice an array: + * + * a = [1, 2, 3, 4] + * r = (..2) # => nil...2 + * a[r] # => [1, 2] + * + * \Method +each+ for a beginless range raises an exception. + * + * == Endless Ranges + * + * An _endless_ _range_ has a definite begin value, but a +nil+ end value. + * Such a range includes all values from the begin value. + * + * r = (1..) # => 1.. + * r.end # => nil + * r.include?(50) # => true + * + * Range.new(1, nil) # => 1.. + * + * The literal for an endless range may be written with either two dots + * or three. + * The range has the same elements, either way. + * But note that the two are not equal: + * + * r0 = (1..) # => 1.. + * r1 = (1...) # => 1... + * r0.begin == r1.begin # => true + * r0.end == r1.end # => true + * r0 == r1 # => false + * + * An endless range may be used to slice an array: + * + * a = [1, 2, 3, 4] + * r = (2..) # => 2.. + * a[r] # => [3, 4] + * + * \Method +each+ for an endless range calls the given block indefinitely: + * + * a = [] + * r = (1..) + * r.each do |i| + * a.push(i) if i.even? + * break if i > 10 + * end + * a # => [2, 4, 6, 8, 10] + * + * == Ranges and Other Classes + * + * An object may be put into a range if its class implements + * instance method <=>. + * Ruby core classes that do so include Array, Complex, File::Stat, + * Float, Integer, Kernel, Module, Numeric, Rational, String, Symbol, and Time. + * + * Example: + * + * t0 = Time.now # => 2021-09-19 09:22:48.4854986 -0500 + * t1 = Time.now # => 2021-09-19 09:22:56.0365079 -0500 + * t2 = Time.now # => 2021-09-19 09:23:08.5263283 -0500 + * (t0..t2).include?(t1) # => true + * (t0..t1).include?(t2) # => false + * + * A range can be iterated over only if its elements + * implement instance method +succ+. + * Ruby core classes that do so include Integer, String, and Symbol + * (but not the other classes mentioned above). + * + * Iterator methods include: + * + * - In \Range itself: #each, #step, and #% + * - Included from module Enumerable: #each_entry, #each_with_index, + * #each_with_object, #each_slice, #each_cons, and #reverse_each. + * + * Example: + * + * a = [] + * (1..4).each {|i| a.push(i) } + * a # => [1, 2, 3, 4] + * + * == Ranges and User-Defined Classes + * + * A user-defined class that is to be used in a range + * must implement instance <=>; + * see {Integer#<=>}[Integer.html#label-method-i-3C-3D-3E]. + * To make iteration available, it must also implement + * instance method +succ+; see Integer#succ. + * + * The class below implements both <=> and +succ+, + * and so can be used both to construct ranges and to iterate over them. + * Note that the Comparable module is included + * so the == method is defined in terms of <=>. + * + * # Represent a string of 'X' characters. + * class Xs + * include Comparable + * attr_accessor :length + * def initialize(n) + * @length = n + * end + * def succ + * Xs.new(@length + 1) * end + * def <=>(other) + * @length <=> other.length + * end + * def to_s + * sprintf "%2d #{inspect}", @length + * end + * def inspect + * 'X' * @length + * end + * end + * + * r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX + * r.to_a #=> [XXX, XXXX, XXXXX, XXXXXX] + * r.include?(Xs.new(5)) #=> true + * r.include?(Xs.new(7)) #=> false + * + * == What's Here + * + * First, what's elsewhere. \Class \Range: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * which provides dozens of additional methods. + * + * Here, class \Range provides methods that are useful for: + * + * - {Creating a Range}[#class-Range-label-Methods+for+Creating+a+Range] + * - {Querying}[#class-Range-label-Methods+for+Querying] + * - {Comparing}[#class-Range-label-Methods+for+Comparing] + * - {Iterating}[#class-Range-label-Methods+for+Iterating] + * - {Converting}[#class-Range-label-Methods+for+Converting] * - * An example of using Xs to construct a range: + * === Methods for Creating a \Range * - * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx - * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx] - * r.member?(Xs.new(5)) #=> true + * - ::new:: Returns a new range. + * + * === Methods for Querying + * + * - #begin:: Returns the begin value given for +self+. + * - #bsearch:: Returns an element from +self+ selected by a binary search. + * - #count:: Returns a count of elements in +self+. + * - #end:: Returns the end value given for +self+. + * - #exclude_end?:: Returns whether the end object is excluded. + * - #first:: Returns the first elements of +self+. + * - #hash:: Returns the integer hash code. + * - #last:: Returns the last elements of +self+. + * - #max:: Returns the maximum values in +self+. + * - #min:: Returns the minimum values in +self+. + * - #minmax:: Returns the minimum and maximum values in +self+. + * - #size:: Returns the count of elements in +self+. + * + * === Methods for Comparing + * + * - {#==}[#method-i-3D-3D]:: Returns whether a given object is equal to +self+ + * (uses #==). + * - #===:: Returns whether the given object is between the begin and end values. + * - #cover?:: Returns whether a given object is within +self+. + * - #eql?:: Returns whether a given object is equal to +self+ (uses #eql?). + * - #include? (aliased as #member?):: Returns whether a given object + * is an element of +self+. + * + * === Methods for Iterating + * + * - #%:: Requires argument +n+; calls the block with each +n+-th element of +self+. + * - #each:: Calls the block with each element of +self+. + * - #step:: Takes optional argument +n+ (defaults to 1); + calls the block with each +n+-th element of +self+. + * + * === Methods for Converting + * + * - #inspect:: Returns a string representation of +self+ (uses #inspect). + * - #to_a (aliased as #entries):: Returns elements of +self+ in an array. + * - #to_s:: Returns a string representation of +self+ (uses #to_s). * */ void Init_Range(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - id_beg = rb_intern("begin"); - id_end = rb_intern("end"); - id_excl = rb_intern("excl"); + id_beg = rb_intern_const("begin"); + id_end = rb_intern_const("end"); + id_excl = rb_intern_const("excl"); rb_cRange = rb_struct_define_without_accessor( "Range", rb_cObject, range_alloc, diff --git a/ruby/rational.c b/ruby/rational.c index c606f3c62..7817bdbce 100644 --- a/ruby/rational.c +++ b/ruby/rational.c @@ -5,30 +5,37 @@ which is written in ruby. */ -#include "internal.h" -#include "id.h" -#include +#include "ruby/internal/config.h" + +#include #include +#include #ifdef HAVE_IEEEFP_H #include #endif -#define NDEBUG -#include "ruby_assert.h" - #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) #define USE_GMP #include #endif +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/complex.h" +#include "internal/gc.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/rational.h" +#include "ruby_assert.h" + #define ZERO INT2FIX(0) #define ONE INT2FIX(1) #define TWO INT2FIX(2) #define GMP_GCD_DIGITS 1 -#define INT_POSITIVE_P(x) (FIXNUM_P(x) ? FIXNUM_POSITIVE_P(x) : BIGNUM_POSITIVE_P(x)) #define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x)) VALUE rb_cRational; @@ -39,11 +46,11 @@ static ID id_abs, id_integer_p, #define id_idiv idDiv #define id_to_i idTo_i -#define f_boolcast(x) ((x) ? Qtrue : Qfalse) #define f_inspect rb_inspect #define f_to_s rb_obj_as_string static VALUE nurat_to_f(VALUE self); +static VALUE float_to_r(VALUE self); inline static VALUE f_add(VALUE x, VALUE y) @@ -52,6 +59,8 @@ f_add(VALUE x, VALUE y) return x; if (FIXNUM_ZERO_P(x)) return y; + if (RB_INTEGER_TYPE_P(x)) + return rb_int_plus(x, y); return rb_funcall(x, '+', 1, y); } @@ -70,6 +79,10 @@ f_lt_p(VALUE x, VALUE y) { if (FIXNUM_P(x) && FIXNUM_P(y)) return (SIGNED_VALUE)x < (SIGNED_VALUE)y; + if (RB_INTEGER_TYPE_P(x)) { + VALUE r = rb_int_cmp(x, y); + if (!NIL_P(r)) return rb_int_negative_p(r); + } return RTEST(rb_funcall(x, '<', 1, y)); } @@ -115,7 +128,7 @@ f_abs(VALUE x) } -inline static VALUE +inline static int f_integer_p(VALUE x) { return RB_INTEGER_TYPE_P(x); @@ -129,11 +142,13 @@ f_to_i(VALUE x) return rb_funcall(x, id_to_i, 0); } -inline static VALUE +inline static int f_eqeq_p(VALUE x, VALUE y) { if (FIXNUM_P(x) && FIXNUM_P(y)) return x == y; + if (RB_INTEGER_TYPE_P(x)) + return RTEST(rb_int_equal(x, y)); return (int)rb_equal(x, y); } @@ -184,7 +199,7 @@ f_minus_one_p(VALUE x) if (RB_INTEGER_TYPE_P(x)) { return x == LONG2FIX(-1); } - else if (RB_TYPE_P(x, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(x)) { return Qfalse; } else if (RB_TYPE_P(x, T_RATIONAL)) { @@ -350,7 +365,7 @@ inline static VALUE f_gcd(VALUE x, VALUE y) { #ifdef USE_GMP - if (RB_TYPE_P(x, T_BIGNUM) && RB_TYPE_P(y, T_BIGNUM)) { + if (RB_BIGNUM_TYPE_P(x) && RB_BIGNUM_TYPE_P(y)) { size_t xn = BIGNUM_LEN(x); size_t yn = BIGNUM_LEN(y); if (GMP_GCD_DIGITS <= xn || GMP_GCD_DIGITS <= yn) @@ -394,9 +409,9 @@ nurat_s_new_internal(VALUE klass, VALUE num, VALUE den) { NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0)); - RRATIONAL_SET_NUM(obj, num); - RRATIONAL_SET_DEN(obj, den); - OBJ_FREEZE_RAW(obj); + RATIONAL_SET_NUM((VALUE)obj, num); + RATIONAL_SET_DEN((VALUE)obj, den); + OBJ_FREEZE_RAW((VALUE)obj); return (VALUE)obj; } @@ -413,18 +428,6 @@ f_rational_new_bang1(VALUE klass, VALUE x) return nurat_s_new_internal(klass, x, ONE); } -#ifdef CANONICALIZATION_FOR_MATHN -static int canonicalization = 0; - -RUBY_FUNC_EXPORTED void -nurat_canonicalization(int f) -{ - canonicalization = f; -} -#else -# define canonicalization 0 -#endif - inline static void nurat_int_check(VALUE num) { @@ -473,8 +476,6 @@ nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den) nurat_canonicalize(&num, &den); nurat_reduce(&num, &den); - if (canonicalization && f_one_p(den)) - return num; return nurat_s_new_internal(klass, num, den); } @@ -483,30 +484,9 @@ nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den) { nurat_canonicalize(&num, &den); - if (canonicalization && f_one_p(den)) - return num; return nurat_s_new_internal(klass, num, den); } -static VALUE -nurat_s_new(int argc, VALUE *argv, VALUE klass) -{ - VALUE num, den; - - switch (rb_scan_args(argc, argv, "11", &num, &den)) { - case 1: - num = nurat_int_value(num); - den = ONE; - break; - default: - num = nurat_int_value(num); - den = nurat_int_value(den); - break; - } - - return nurat_s_canonicalize_internal(klass, num, den); -} - inline static VALUE f_rational_new2(VALUE klass, VALUE x, VALUE y) { @@ -774,8 +754,8 @@ rb_rational_plus(VALUE self, VALUE other) * Rational(9, 8) - 4 #=> (-23/8) * Rational(20, 9) - 9.8 #=> -7.577777777777778 */ -static VALUE -nurat_sub(VALUE self, VALUE other) +VALUE +rb_rational_minus(VALUE self, VALUE other) { if (RB_INTEGER_TYPE_P(other)) { { @@ -912,8 +892,8 @@ rb_rational_mul(VALUE self, VALUE other) * Rational(9, 8) / 4 #=> (9/32) * Rational(20, 9) / 9.8 #=> 0.22675736961451246 */ -static VALUE -nurat_div(VALUE self, VALUE other) +VALUE +rb_rational_div(VALUE self, VALUE other) { if (RB_INTEGER_TYPE_P(other)) { if (f_zero_p(other)) @@ -965,10 +945,10 @@ nurat_fdiv(VALUE self, VALUE other) { VALUE div; if (f_zero_p(other)) - return nurat_div(self, rb_float_new(0.0)); + return rb_rational_div(self, rb_float_new(0.0)); if (FIXNUM_P(other) && other == LONG2FIX(1)) return nurat_to_f(self); - div = nurat_div(self, other); + div = rb_rational_div(self, other); if (RB_TYPE_P(div, T_RATIONAL)) return nurat_to_f(div); if (RB_FLOAT_TYPE_P(div)) @@ -976,15 +956,6 @@ nurat_fdiv(VALUE self, VALUE other) return rb_funcall(div, idTo_f, 0); } -inline static VALUE -f_odd_p(VALUE integer) -{ - if (rb_funcall(integer, '%', 1, INT2FIX(2)) != INT2FIX(0)) { - return Qtrue; - } - return Qfalse; -} - /* * call-seq: * rat ** numeric -> numeric @@ -1019,7 +990,7 @@ rb_rational_pow(VALUE self, VALUE other) return f_rational_new_bang1(CLASS_OF(self), ONE); } else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) { - return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1)); + return f_rational_new_bang1(CLASS_OF(self), INT2FIX(rb_int_odd_p(other) ? -1 : 1)); } else if (INT_ZERO_P(dat->num)) { if (rb_num_negative_p(other)) { @@ -1063,7 +1034,7 @@ rb_rational_pow(VALUE self, VALUE other) return f_rational_new2(CLASS_OF(self), num, den); } } - else if (RB_TYPE_P(other, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(other)) { rb_warn("in a**b, b may be too big"); return rb_float_pow(nurat_to_f(self), other); } @@ -1071,7 +1042,7 @@ rb_rational_pow(VALUE self, VALUE other) return rb_float_pow(nurat_to_f(self), other); } else { - return rb_num_coerce_bin(self, other, rb_intern("**")); + return rb_num_coerce_bin(self, other, idPow); } } #define nurat_expt rb_rational_pow @@ -1096,21 +1067,19 @@ rb_rational_pow(VALUE self, VALUE other) VALUE rb_rational_cmp(VALUE self, VALUE other) { - if (RB_INTEGER_TYPE_P(other)) { + switch (TYPE(other)) { + case T_FIXNUM: + case T_BIGNUM: { get_dat1(self); if (dat->den == LONG2FIX(1)) return rb_int_cmp(dat->num, other); /* c14n */ other = f_rational_new_bang1(CLASS_OF(self), other); - goto other_is_rational; + /* FALLTHROUGH */ } - } - else if (RB_FLOAT_TYPE_P(other)) { - return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other)); - } - else if (RB_TYPE_P(other, T_RATIONAL)) { - other_is_rational: + + case T_RATIONAL: { VALUE num1, num2; @@ -1127,9 +1096,12 @@ rb_rational_cmp(VALUE self, VALUE other) } return rb_int_cmp(rb_int_minus(num1, num2), ZERO); } - } - else { - return rb_num_coerce_cmp(self, other, rb_intern("<=>")); + + case T_FLOAT: + return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other)); + + default: + return rb_num_coerce_cmp(self, other, idCmp); } } @@ -1163,12 +1135,12 @@ nurat_eqeq_p(VALUE self, VALUE other) } else { const double d = nurat_to_double(self); - return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other)))); + return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other)))); } } else if (RB_FLOAT_TYPE_P(other)) { const double d = nurat_to_double(self); - return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other)))); + return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other)))); } else if (RB_TYPE_P(other, T_RATIONAL)) { { @@ -1177,7 +1149,7 @@ nurat_eqeq_p(VALUE self, VALUE other) if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num)) return Qtrue; - return f_boolcast(rb_int_equal(adat->num, bdat->num) && + return RBOOL(rb_int_equal(adat->num, bdat->num) && rb_int_equal(adat->den, bdat->den)); } } @@ -1200,11 +1172,17 @@ nurat_coerce(VALUE self, VALUE other) return rb_assoc_new(other, self); } else if (RB_TYPE_P(other, T_COMPLEX)) { - if (k_exact_zero_p(RCOMPLEX(other)->imag)) - return rb_assoc_new(f_rational_new_bang1 - (CLASS_OF(self), RCOMPLEX(other)->real), self); - else + if (!k_exact_zero_p(RCOMPLEX(other)->imag)) return rb_assoc_new(other, rb_Complex(self, INT2FIX(0))); + other = RCOMPLEX(other)->real; + if (RB_FLOAT_TYPE_P(other)) { + other = float_to_r(other); + RBASIC_SET_CLASS(other, CLASS_OF(self)); + } + else { + other = f_rational_new_bang1(CLASS_OF(self), other); + } + return rb_assoc_new(other, self); } rb_raise(rb_eTypeError, "%s can't be coerced into %s", @@ -1222,7 +1200,7 @@ static VALUE nurat_positive_p(VALUE self) { get_dat1(self); - return f_boolcast(INT_POSITIVE_P(dat->num)); + return RBOOL(INT_POSITIVE_P(dat->num)); } /* @@ -1235,7 +1213,7 @@ static VALUE nurat_negative_p(VALUE self) { get_dat1(self); - return f_boolcast(INT_NEGATIVE_P(dat->num)); + return RBOOL(INT_NEGATIVE_P(dat->num)); } /* @@ -1403,7 +1381,7 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE)) s = (*func)(s); - s = nurat_div(f_rational_new_bang1(CLASS_OF(self), s), b); + s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b); if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0) s = nurat_truncate(s); @@ -1411,6 +1389,18 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE)) return s; } +VALUE +rb_rational_floor(VALUE self, int ndigits) +{ + if (ndigits == 0) { + return nurat_floor(self); + } + else { + VALUE n = INT2NUM(ndigits); + return f_round_common(1, &n, self, nurat_floor); + } +} + /* * call-seq: * rat.floor([ndigits]) -> integer or rational @@ -1549,6 +1539,12 @@ nurat_round_n(int argc, VALUE *argv, VALUE self) return f_round_common(argc, argv, self, round_func); } +VALUE +rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num) +{ + return nurat_to_f(nurat_round_n(argc, argv, float_to_r(num))); +} + static double nurat_to_double(VALUE self) { @@ -1723,27 +1719,36 @@ static VALUE nurat_rationalize(int argc, VALUE *argv, VALUE self) { VALUE e, a, b, p, q; + VALUE rat = self; + get_dat1(self); if (rb_check_arity(argc, 0, 1) == 0) return self; - if (nurat_negative_p(self)) - return rb_rational_uminus(nurat_rationalize(argc, argv, rb_rational_uminus(self))); - e = f_abs(argv[0]); - a = f_sub(self, e); - b = f_add(self, e); + + if (INT_NEGATIVE_P(dat->num)) { + rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den); + } + + a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e); + b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e); if (f_eqeq_p(a, b)) return self; nurat_rationalize_internal(a, b, &p, &q); + if (rat != self) { + RATIONAL_SET_NUM(rat, rb_int_uminus(p)); + RATIONAL_SET_DEN(rat, q); + return rat; + } return f_rational_new2(CLASS_OF(self), p, q); } /* :nodoc: */ -static VALUE -nurat_hash(VALUE self) +st_index_t +rb_rational_hash(VALUE self) { st_index_t v, h[2]; VALUE n; @@ -1754,9 +1759,16 @@ nurat_hash(VALUE self) n = rb_hash(dat->den); h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); - return ST2FIX(v); + return v; } +static VALUE +nurat_hash(VALUE self) +{ + return ST2FIX(rb_rational_hash(self)); +} + + static VALUE f_format(VALUE self, VALUE (*func)(VALUE)) { @@ -1827,8 +1839,8 @@ nurat_loader(VALUE self, VALUE a) nurat_int_check(num); nurat_int_check(den); nurat_canonicalize(&num, &den); - RRATIONAL_SET_NUM(dat, num); - RRATIONAL_SET_DEN(dat, den); + RATIONAL_SET_NUM((VALUE)dat, num); + RATIONAL_SET_DEN((VALUE)dat, den); OBJ_FREEZE_RAW(self); return self; @@ -1869,13 +1881,11 @@ nurat_marshal_load(VALUE self, VALUE a) return self; } -/* --- */ - VALUE rb_rational_reciprocal(VALUE x) { get_dat1(x); - return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num); + return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE); } /* @@ -1938,6 +1948,14 @@ rb_gcdlcm(VALUE self, VALUE other) VALUE rb_rational_raw(VALUE x, VALUE y) { + if (! RB_INTEGER_TYPE_P(x)) + x = rb_to_int(x); + if (! RB_INTEGER_TYPE_P(y)) + y = rb_to_int(y); + if (INT_NEGATIVE_P(y)) { + x = rb_int_uminus(x); + y = rb_int_uminus(y); + } return nurat_s_new_internal(rb_cRational, x, y); } @@ -2021,13 +2039,8 @@ rb_numeric_quo(VALUE x, VALUE y) return rb_funcallv(x, idFdiv, 1, &y); } - if (canonicalization) { - x = rb_rational_raw1(x); - } - else { - x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r"); - } - return nurat_div(x, y); + x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r"); + return rb_rational_div(x, y); } VALUE @@ -2064,7 +2077,6 @@ integer_denominator(VALUE self) return INT2FIX(1); } -static VALUE float_to_r(VALUE self); /* * call-seq: * flo.numerator -> integer @@ -2082,12 +2094,9 @@ rb_float_numerator(VALUE self) { double d = RFLOAT_VALUE(self); VALUE r; - if (isinf(d) || isnan(d)) + if (!isfinite(d)) return self; r = float_to_r(self); - if (canonicalization && k_integer_p(r)) { - return r; - } return nurat_numerator(r); } @@ -2105,12 +2114,9 @@ rb_float_denominator(VALUE self) { double d = RFLOAT_VALUE(self); VALUE r; - if (isinf(d) || isnan(d)) + if (!isfinite(d)) return INT2FIX(1); r = float_to_r(self); - if (canonicalization && k_integer_p(r)) { - return ONE; - } return nurat_denominator(r); } @@ -2241,7 +2247,7 @@ rb_flt_rationalize_with_prec(VALUE flt, VALUE prec) VALUE rb_flt_rationalize(VALUE flt) { - VALUE a, b, f, p, q; + VALUE a, b, f, p, q, den; int n; float_decode_internal(flt, &f, &n); @@ -2249,7 +2255,7 @@ rb_flt_rationalize(VALUE flt) return rb_rational_new1(rb_int_lshift(f, INT2FIX(n))); { - VALUE radix_times_f, den; + VALUE radix_times_f; radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f); #if FLT_RADIX == 2 && 0 @@ -2258,13 +2264,15 @@ rb_flt_rationalize(VALUE flt) den = rb_int_positive_pow(FLT_RADIX, 1-n); #endif - a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); - b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); + a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)); + b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)); } - if (nurat_eqeq_p(a, b)) + if (f_eqeq_p(a, b)) return float_to_r(flt); + a = rb_rational_new2(a, den); + b = rb_rational_new2(b, den); nurat_rationalize_internal(a, b, &p, &q); return rb_rational_new2(p, q); } @@ -2287,20 +2295,20 @@ static VALUE float_rationalize(int argc, VALUE *argv, VALUE self) { double d = RFLOAT_VALUE(self); - - if (d < 0.0) - return rb_rational_uminus(float_rationalize(argc, argv, DBL2NUM(-d))); + VALUE rat; + int neg = d < 0.0; + if (neg) self = DBL2NUM(-d); if (rb_check_arity(argc, 0, 1)) { - return rb_flt_rationalize_with_prec(self, argv[0]); + rat = rb_flt_rationalize_with_prec(self, argv[0]); } else { - return rb_flt_rationalize(self); + rat = rb_flt_rationalize(self); } + if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num)); + return rat; } -#include - inline static int issign(int c) { @@ -2416,7 +2424,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise) if (!read_num(&s, e, &num, &nexp)) { if (strict) return Qnil; - return canonicalization ? ZERO : nurat_s_alloc(rb_cRational); + return nurat_s_alloc(rb_cRational); } den = ONE; if (s < e && *s == '/') { @@ -2444,24 +2452,27 @@ parse_rat(const char *s, const char *const e, int strict, int raise) if (nexp != ZERO) { if (INT_NEGATIVE_P(nexp)) { VALUE mul; - if (!FIXNUM_P(nexp)) { - overflow: - return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); + if (FIXNUM_P(nexp)) { + mul = f_expt10(LONG2NUM(-FIX2LONG(nexp))); + if (! RB_FLOAT_TYPE_P(mul)) { + num = rb_int_mul(num, mul); + goto reduce; + } } - mul = f_expt10(LONG2NUM(-FIX2LONG(nexp))); - if (RB_FLOAT_TYPE_P(mul)) goto overflow; - num = rb_int_mul(num, mul); + return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); } else { VALUE div; - if (!FIXNUM_P(nexp)) { - underflow: - return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0); + if (FIXNUM_P(nexp)) { + div = f_expt10(nexp); + if (! RB_FLOAT_TYPE_P(div)) { + den = rb_int_mul(den, div); + goto reduce; + } } - div = f_expt10(nexp); - if (RB_FLOAT_TYPE_P(div)) goto underflow; - den = rb_int_mul(den, div); + return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0); } + reduce: nurat_reduce(&num, &den); } @@ -2469,9 +2480,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise) num = negate_num(num); } - if (!canonicalization || den != ONE) - num = rb_rational_raw(num, den); - return num; + return rb_rational_raw(num, den); } static VALUE @@ -2561,6 +2570,8 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) VALUE a1 = numv, a2 = denv; int state; + assert(a1 != Qundef); + if (NIL_P(a1) || NIL_P(a2)) { if (!raise) return Qnil; rb_raise(rb_eTypeError, "can't convert nil into Rational"); @@ -2576,21 +2587,47 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) a2 = RCOMPLEX(a2)->real; } - if (RB_FLOAT_TYPE_P(a1)) { + if (RB_INTEGER_TYPE_P(a1)) { + // nothing to do + } + else if (RB_FLOAT_TYPE_P(a1)) { a1 = float_to_r(a1); } + else if (RB_TYPE_P(a1, T_RATIONAL)) { + // nothing to do + } else if (RB_TYPE_P(a1, T_STRING)) { a1 = string_to_r_strict(a1, raise); if (!raise && NIL_P(a1)) return Qnil; } + else if (!rb_respond_to(a1, idTo_r)) { + VALUE tmp = rb_protect(rb_check_to_int, a1, NULL); + rb_set_errinfo(Qnil); + if (!NIL_P(tmp)) { + a1 = tmp; + } + } - if (RB_FLOAT_TYPE_P(a2)) { + if (RB_INTEGER_TYPE_P(a2)) { + // nothing to do + } + else if (RB_FLOAT_TYPE_P(a2)) { a2 = float_to_r(a2); } + else if (RB_TYPE_P(a2, T_RATIONAL)) { + // nothing to do + } else if (RB_TYPE_P(a2, T_STRING)) { a2 = string_to_r_strict(a2, raise); if (!raise && NIL_P(a2)) return Qnil; } + else if (a2 != Qundef && !rb_respond_to(a2, idTo_r)) { + VALUE tmp = rb_protect(rb_check_to_int, a2, NULL); + rb_set_errinfo(Qnil); + if (!NIL_P(tmp)) { + a2 = tmp; + } + } if (RB_TYPE_P(a1, T_RATIONAL)) { if (a2 == Qundef || (k_exact_one_p(a2))) @@ -2598,7 +2635,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) } if (a2 == Qundef) { - if (!k_integer_p(a1)) { + if (!RB_INTEGER_TYPE_P(a1)) { if (!raise) { VALUE result = rb_protect(to_rational, a1, NULL); rb_set_errinfo(Qnil); @@ -2633,25 +2670,32 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) } } if ((k_numeric_p(a1) && k_numeric_p(a2)) && - (!f_integer_p(a1) || !f_integer_p(a2))) + (!f_integer_p(a1) || !f_integer_p(a2))) { + VALUE tmp = rb_protect(to_rational, a1, &state); + if (!state) { + a1 = tmp; + } + else { + rb_set_errinfo(Qnil); + } return f_div(a1, a2); + } } - { - int argc; - VALUE argv2[2]; - argv2[0] = a1; - if (a2 == Qundef) { - argv2[1] = Qnil; - argc = 1; - } - else { - if (!k_integer_p(a2) && !raise) return Qnil; - argv2[1] = a2; - argc = 2; - } - return nurat_s_new(argc, argv2, klass); + a1 = nurat_int_value(a1); + + if (a2 == Qundef) { + a2 = ONE; + } + else if (!k_integer_p(a2) && !raise) { + return Qnil; + } + else { + a2 = nurat_int_value(a2); } + + + return nurat_s_canonicalize_internal(klass, a1, a2); } static VALUE @@ -2671,13 +2715,19 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass) * a/b (b>0), where a is the numerator and b is the denominator. * Integer a equals rational a/1 mathematically. * - * In Ruby, you can create rational objects with the Kernel#Rational, - * to_r, or rationalize methods or by suffixing +r+ to a literal. - * The return values will be irreducible fractions. + * You can create a \Rational object explicitly with: + * + * - A {rational literal}[doc/syntax/literals_rdoc.html#label-Rational+Literals]. + * + * You can convert certain objects to Rationals with: + * + * - \Method {Rational}[Kernel.html#method-i-Rational]. + * + * Examples * * Rational(1) #=> (1/1) * Rational(2, 3) #=> (2/3) - * Rational(4, -6) #=> (-2/3) + * Rational(4, -6) #=> (-2/3) # Reduced. * 3.to_r #=> (3/1) * 2/3r #=> (2/3) * @@ -2712,13 +2762,10 @@ void Init_Rational(void) { VALUE compat; -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - id_abs = rb_intern("abs"); - id_integer_p = rb_intern("integer?"); - id_i_num = rb_intern("@numerator"); - id_i_den = rb_intern("@denominator"); + id_abs = rb_intern_const("abs"); + id_integer_p = rb_intern_const("integer?"); + id_i_num = rb_intern_const("@numerator"); + id_i_den = rb_intern_const("@denominator"); rb_cRational = rb_define_class("Rational", rb_cNumeric); @@ -2734,10 +2781,10 @@ Init_Rational(void) rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0); rb_define_method(rb_cRational, "+", rb_rational_plus, 1); - rb_define_method(rb_cRational, "-", nurat_sub, 1); + rb_define_method(rb_cRational, "-", rb_rational_minus, 1); rb_define_method(rb_cRational, "*", rb_rational_mul, 1); - rb_define_method(rb_cRational, "/", nurat_div, 1); - rb_define_method(rb_cRational, "quo", nurat_div, 1); + rb_define_method(rb_cRational, "/", rb_rational_div, 1); + rb_define_method(rb_cRational, "quo", rb_rational_div, 1); rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1); rb_define_method(rb_cRational, "**", nurat_expt, 1); @@ -2771,8 +2818,6 @@ Init_Rational(void) rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1); rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader); - /* --- */ - rb_define_method(rb_cInteger, "gcd", rb_gcd, 1); rb_define_method(rb_cInteger, "lcm", rb_lcm, 1); rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1); diff --git a/ruby/re.c b/ruby/re.c index 9e9df700c..d91909a74 100644 --- a/ruby/re.c +++ b/ruby/re.c @@ -9,13 +9,21 @@ **********************************************************************/ +#include "ruby/internal/config.h" + +#include + +#include "encindex.h" +#include "internal.h" +#include "internal/hash.h" +#include "internal/imemo.h" +#include "internal/re.h" +#include "internal/string.h" +#include "internal/variable.h" +#include "regint.h" #include "ruby/encoding.h" #include "ruby/re.h" #include "ruby/util.h" -#include "internal.h" -#include "regint.h" -#include "encindex.h" -#include VALUE rb_eRegexpError; @@ -304,8 +312,10 @@ char_to_option(int c) return val; } +enum { OPTBUF_SIZE = 4 }; + static char * -option_to_str(char str[4], int options) +option_to_str(char str[OPTBUF_SIZE], int options) { char *p = str; if (options & ONIG_OPTION_MULTILINE) *p++ = 'm'; @@ -455,7 +465,7 @@ rb_reg_desc(const char *s, long len, VALUE re) rb_reg_expr_str(str, s, len, enc, resenc, '/'); rb_str_buf_cat2(str, "/"); if (re) { - char opts[4]; + char opts[OPTBUF_SIZE]; rb_reg_check(re); if (*option_to_str(opts, RREGEXP_PTR(re)->options)) rb_str_buf_cat2(str, opts); @@ -547,7 +557,7 @@ rb_reg_str_with_term(VALUE re, int term) long len; const UChar* ptr; VALUE str = rb_str_buf_new2("(?"); - char optbuf[5]; + char optbuf[OPTBUF_SIZE + 1]; /* for '-' */ rb_encoding *enc = rb_enc_get(re); rb_reg_check(re); @@ -661,7 +671,7 @@ rb_reg_raise(const char *s, long len, const char *err, VALUE re) static VALUE rb_enc_reg_error_desc(const char *s, long len, rb_encoding *enc, int options, const char *err) { - char opts[6]; + char opts[OPTBUF_SIZE + 1]; /* for '/' */ VALUE desc = rb_str_buf_new2(err); rb_encoding *resenc = rb_default_internal_encoding(); if (resenc == NULL) resenc = rb_default_external_encoding(); @@ -714,8 +724,7 @@ static VALUE rb_reg_casefold_p(VALUE re) { rb_reg_check(re); - if (RREGEXP_PTR(re)->options & ONIG_OPTION_IGNORECASE) return Qtrue; - return Qfalse; + return RBOOL(RREGEXP_PTR(re)->options & ONIG_OPTION_IGNORECASE); } @@ -917,12 +926,12 @@ make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_bu * aliased as global variables: * * * $~ is Regexp.last_match; - * * $& is Regexp.last_match[0]; + * * $& is Regexp.last_match[ 0 ]; * * $1, $2, and so on are - * Regexp.last_match[i] (captures by number); + * Regexp.last_match[ i ] (captures by number); * * $` is Regexp.last_match.pre_match; * * $' is Regexp.last_match.post_match; - * * $+ is Regexp.last_match[-1] (the last capture). + * * $+ is Regexp.last_match[ -1 ] (the last capture). * * See also "Special global variables" section in Regexp documentation. */ @@ -1103,7 +1112,7 @@ match_regexp(VALUE match) * mtch.names -> [name1, name2, ...] * * Returns a list of names of captures as an array of strings. - * It is same as mtch.regexp.names. + * This is the same as mtch.regexp.names. * * /(?.)(?.)(?.)/.match("hoge").names * #=> ["foo", "bar", "baz"] @@ -1141,6 +1150,21 @@ match_size(VALUE match) } static int name_to_backref_number(struct re_registers *, VALUE, const char*, const char*); +NORETURN(static void name_to_backref_error(VALUE name)); + +static void +name_to_backref_error(VALUE name) +{ + rb_raise(rb_eIndexError, "undefined group name reference: % "PRIsVALUE, + name); +} + +static void +backref_number_check(struct re_registers *regs, int i) +{ + if (i < 0 || regs->num_regs <= i) + rb_raise(rb_eIndexError, "index %d out of matches", i); +} static int match_backref_number(VALUE match, VALUE backref) @@ -1160,10 +1184,10 @@ match_backref_number(VALUE match, VALUE backref) } name = StringValueCStr(backref); - num = name_to_backref_number(regs, regexp, name, name + strlen(name)); + num = name_to_backref_number(regs, regexp, name, name + RSTRING_LEN(backref)); if (num < 1) { - rb_raise(rb_eIndexError, "undefined group name reference: %s", name); + name_to_backref_error(backref); } return num; @@ -1200,8 +1224,7 @@ match_offset(VALUE match, VALUE n) struct re_registers *regs = RMATCH_REGS(match); match_check(match); - if (i < 0 || regs->num_regs <= i) - rb_raise(rb_eIndexError, "index %d out of matches", i); + backref_number_check(regs, i); if (BEG(i) < 0) return rb_assoc_new(Qnil, Qnil); @@ -1236,8 +1259,7 @@ match_begin(VALUE match, VALUE n) struct re_registers *regs = RMATCH_REGS(match); match_check(match); - if (i < 0 || regs->num_regs <= i) - rb_raise(rb_eIndexError, "index %d out of matches", i); + backref_number_check(regs, i); if (BEG(i) < 0) return Qnil; @@ -1271,8 +1293,7 @@ match_end(VALUE match, VALUE n) struct re_registers *regs = RMATCH_REGS(match); match_check(match); - if (i < 0 || regs->num_regs <= i) - rb_raise(rb_eIndexError, "index %d out of matches", i); + backref_number_check(regs, i); if (BEG(i) < 0) return Qnil; @@ -1281,6 +1302,75 @@ match_end(VALUE match, VALUE n) return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end); } +/* + * call-seq: + * mtch.match(n) -> string or nil + * + * Returns the captured substring corresponding to the argument. + * n can be a string or symbol to reference a named capture. + * + * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + * m.match(0) #=> "HX1138" + * m.match(4) #=> "8" + * m.match(5) #=> nil + * + * m = /(?.)(.)(?.+)/.match("hoge") + * m.match(:foo) #=> "h" + * m.match(:bar) #=> "ge" + * + */ + +static VALUE +match_nth(VALUE match, VALUE n) +{ + int i = match_backref_number(match, n); + struct re_registers *regs = RMATCH_REGS(match); + + backref_number_check(regs, i); + + long start = BEG(i), end = END(i); + if (start < 0) + return Qnil; + + return rb_str_subseq(RMATCH(match)->str, start, end - start); +} + +/* + * call-seq: + * mtch.match_length(n) -> array + * + * Returns the length of the captured substring corresponding to the argument. + * n can be a string or symbol to reference a named capture. + * + * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + * m.match_length(0) #=> 6 + * m.match_length(4) #=> 1 + * m.match_length(5) #=> nil + * + * m = /(?.)(.)(?.+)/.match("hoge") + * m.match_length(:foo) #=> 1 + * m.match_length(:bar) #=> 2 + * + */ + +static VALUE +match_nth_length(VALUE match, VALUE n) +{ + int i = match_backref_number(match, n); + struct re_registers *regs = RMATCH_REGS(match); + + match_check(match); + backref_number_check(regs, i); + + if (BEG(i) < 0) + return Qnil; + + update_char_offset(match); + const struct rmatch_offset *const ofs = + &RMATCH(match)->rmatch->char_offset[i]; + return LONG2NUM(ofs->end - ofs->beg); +} + #define MATCH_BUSY FL_USER2 void @@ -1379,10 +1469,7 @@ rb_backref_set_string(VALUE string, long pos, long len) static VALUE rb_reg_fixed_encoding_p(VALUE re) { - if (FL_TEST(re, KCODE_FIXED)) - return Qtrue; - else - return Qfalse; + return RBOOL(FL_TEST(re, KCODE_FIXED)); } static VALUE @@ -1470,12 +1557,14 @@ rb_reg_prepare_re0(VALUE re, VALUE str, onig_errmsg_buffer err) pattern, pattern + RREGEXP_SRC_LEN(re), enc, &fixed_enc, err); - if (unescaped == Qnil) { + if (NIL_P(unescaped)) { rb_raise(rb_eArgError, "regexp preprocess failed: %s", err); } - r = onig_new(®, (UChar* )RSTRING_PTR(unescaped), - (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)), + const char *ptr; + long len; + RSTRING_GETMEM(unescaped, ptr, len); + r = onig_new(®, (UChar *)ptr, (UChar *)(ptr + len), reg->options, enc, OnigDefaultSyntax, &einfo); if (r) { @@ -1526,18 +1615,21 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int reverse) } /* returns byte offset */ -long -rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str) +static long +rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_backref_str, VALUE *set_match) { long result; VALUE match; struct re_registers regi, *regs = ®i; - char *range = RSTRING_PTR(str); + char *start, *range; + long len; regex_t *reg; int tmpreg; onig_errmsg_buffer err = ""; - if (pos > RSTRING_LEN(str) || pos < 0) { + RSTRING_GETMEM(str, start, len); + range = start; + if (pos > len || pos < 0) { rb_backref_set(Qnil); return -1; } @@ -1546,25 +1638,14 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str) tmpreg = reg != RREGEXP_PTR(re); if (!tmpreg) RREGEXP(re)->usecnt++; - match = rb_backref_get(); - if (!NIL_P(match)) { - if (FL_TEST(match, MATCH_BUSY)) { - match = Qnil; - } - else { - regs = RMATCH_REGS(match); - } - } - if (NIL_P(match)) { - MEMZERO(regs, struct re_registers, 1); - } + MEMZERO(regs, struct re_registers, 1); if (!reverse) { - range += RSTRING_LEN(str); + range += len; } result = onig_search(reg, - (UChar*)(RSTRING_PTR(str)), - ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)), - ((UChar*)(RSTRING_PTR(str)) + pos), + (UChar*)start, + ((UChar*)(start + len)), + ((UChar*)(start + pos)), ((UChar*)range), regs, ONIG_OPTION_NONE); if (!tmpreg) RREGEXP(re)->usecnt--; @@ -1590,13 +1671,10 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str) } } - if (NIL_P(match)) { - int err; - match = match_alloc(rb_cMatch); - err = rb_reg_region_copy(RMATCH_REGS(match), regs); - onig_region_free(regs, 0); - if (err) rb_memerror(); - } + match = match_alloc(rb_cMatch); + int copy_err = rb_reg_region_copy(RMATCH_REGS(match), regs); + onig_region_free(regs, 0); + if (copy_err) rb_memerror(); if (set_backref_str) { RMATCH(match)->str = rb_str_new4(str); @@ -1604,10 +1682,17 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str) RMATCH(match)->regexp = re; rb_backref_set(match); + if (set_match) *set_match = match; return result; } +long +rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str) +{ + return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, NULL); +} + long rb_reg_search(VALUE re, VALUE str, long pos, int reverse) { @@ -1640,10 +1725,13 @@ rb_reg_start_with_p(VALUE re, VALUE str) if (NIL_P(match)) { MEMZERO(regs, struct re_registers, 1); } + const char *ptr; + long len; + RSTRING_GETMEM(str, ptr, len); result = onig_match(reg, - (UChar*)(RSTRING_PTR(str)), - ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)), - (UChar*)(RSTRING_PTR(str)), + (UChar*)(ptr), + ((UChar*)(ptr + len)), + (UChar*)(ptr), regs, ONIG_OPTION_NONE); if (!tmpreg) RREGEXP(re)->usecnt--; if (tmpreg) { @@ -1698,8 +1786,7 @@ rb_reg_nth_defined(int nth, VALUE match) nth += regs->num_regs; if (nth <= 0) return Qnil; } - if (BEG(nth) == -1) return Qfalse; - return Qtrue; + return RBOOL(BEG(nth) != -1); } VALUE @@ -1910,14 +1997,6 @@ name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name (const unsigned char *)name, (const unsigned char *)name_end, regs); } -NORETURN(static void name_to_backref_error(VALUE name)); -static void -name_to_backref_error(VALUE name) -{ - rb_raise(rb_eIndexError, "undefined group name reference: % "PRIsVALUE, - name); -} - #define NAME_TO_NUMBER(regs, re, name, name_ptr, name_end) \ (NIL_P(re) ? 0 : \ !rb_enc_compatible(RREGEXP_SRC(re), (name)) ? 0 : \ @@ -2059,6 +2138,7 @@ match_aref(int argc, VALUE *argv, VALUE match) * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie") * m.to_a #=> ["HX1138", "H", "X", "113", "8"] * m.values_at(0, 2, -2) #=> ["HX1138", "X", "113"] + * m.values_at(1..2, -1) #=> ["H", "X", "8"] * * m = /(?\d+) *(?[+\-*\/]) *(?\d+)/.match("1 + 2") * m.to_a #=> ["1 + 2", "1", "+", "2"] @@ -2277,7 +2357,7 @@ match_inspect(VALUE match) rb_str_buf_cat2(str, ":"); } v = rb_reg_nth_match(i, match); - if (v == Qnil) + if (NIL_P(v)) rb_str_buf_cat2(str, "nil"); else rb_str_buf_append(str, rb_str_inspect(v)); @@ -2720,7 +2800,7 @@ rb_reg_check_preprocess(VALUE str) buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err); RB_GC_GUARD(str); - if (buf == Qnil) { + if (NIL_P(buf)) { return rb_reg_error_desc(str, 0, err); } return Qnil; @@ -2761,7 +2841,7 @@ rb_reg_preprocess_dregexp(VALUE ary, int options) buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err); - if (buf == Qnil) + if (NIL_P(buf)) rb_raise(rb_eArgError, "%s", err); if (fixed_enc != 0) { @@ -2807,7 +2887,7 @@ rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc, } unescaped = rb_reg_preprocess(s, s+len, enc, &fixed_enc, err); - if (unescaped == Qnil) + if (NIL_P(unescaped)) return -1; if (fixed_enc) { @@ -2926,7 +3006,9 @@ rb_reg_init_str_enc(VALUE re, VALUE s, rb_encoding *enc, int options) MJIT_FUNC_EXPORTED VALUE rb_reg_new_ary(VALUE ary, int opt) { - return rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt); + VALUE re = rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt); + rb_obj_freeze(re); + return re; } VALUE @@ -2961,6 +3043,7 @@ rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline) return Qnil; } FL_SET(re, REG_LITERAL); + rb_obj_freeze(re); return re; } @@ -2987,7 +3070,7 @@ static st_index_t reg_hash(VALUE re); * See also Object#hash. */ -static VALUE +VALUE rb_reg_hash(VALUE re) { st_index_t hashval = reg_hash(re); @@ -3021,7 +3104,7 @@ reg_hash(VALUE re) * /abc/u == /abc/n #=> false */ -static VALUE +VALUE rb_reg_equal(VALUE re1, VALUE re2) { if (re1 == re2) return Qtrue; @@ -3031,10 +3114,7 @@ rb_reg_equal(VALUE re1, VALUE re2) if (RREGEXP_PTR(re1)->options != RREGEXP_PTR(re2)->options) return Qfalse; if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse; if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse; - if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) { - return Qtrue; - } - return Qfalse; + return RBOOL(memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0); } /* @@ -3106,7 +3186,7 @@ reg_operand(VALUE s, int check) } static long -reg_match_pos(VALUE re, VALUE *strp, long pos) +reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match) { VALUE str = *strp; @@ -3125,7 +3205,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos) } pos = rb_str_offset(str, pos); } - return rb_reg_search(re, str, pos, 0); + return rb_reg_search_set_match(re, str, pos, 0, 1, set_match); } /* @@ -3179,7 +3259,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos) VALUE rb_reg_match(VALUE re, VALUE str) { - long pos = reg_match_pos(re, &str, 0); + long pos = reg_match_pos(re, &str, 0, NULL); if (pos < 0) return Qnil; pos = rb_str_sublen(str, pos); return LONG2FIX(pos); @@ -3206,7 +3286,7 @@ rb_reg_match(VALUE re, VALUE str) * /^[A-Z]*$/ === "HELLO" #=> true */ -VALUE +static VALUE rb_reg_eqq(VALUE re, VALUE str) { long start; @@ -3257,8 +3337,8 @@ rb_reg_match2(VALUE re) /* * call-seq: - * rxp.match(str) -> matchdata or nil - * rxp.match(str,pos) -> matchdata or nil + * rxp.match(str, pos=0) -> matchdata or nil + * rxp.match(str, pos=0) {|match| block } -> obj * * Returns a MatchData object describing the match, or * nil if there was no match. This is equivalent to @@ -3290,7 +3370,7 @@ rb_reg_match2(VALUE re) static VALUE rb_reg_match_m(int argc, VALUE *argv, VALUE re) { - VALUE result, str, initpos; + VALUE result = Qnil, str, initpos; long pos; if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) { @@ -3300,12 +3380,11 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re) pos = 0; } - pos = reg_match_pos(re, &str, pos); + pos = reg_match_pos(re, &str, pos, &result); if (pos < 0) { rb_backref_set(Qnil); return Qnil; } - result = rb_backref_get(); rb_match_busy(result); if (!NIL_P(result) && rb_block_given_p()) { return rb_yield(result); @@ -3315,10 +3394,10 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re) /* * call-seq: - * rxp.match?(str) -> true or false - * rxp.match?(str,pos) -> true or false + * rxp.match?(str) -> true or false + * rxp.match?(str, pos=0) -> true or false * - * Returns a true or false indicates whether the + * Returns true or false to indicate whether the * regexp is matched or not without updating $~ and other related variables. * If the second parameter is present, it specifies the position in the string * to begin the search. @@ -3446,7 +3525,7 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self) flags |= ARG_ENCODING_NONE; } else { - rb_warn("encoding option is ignored - %s", kcode); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "encoding option is ignored - %s", kcode); } } str = StringValue(argv[0]); @@ -3502,8 +3581,9 @@ rb_reg_quote(VALUE str) } t = RSTRING_PTR(tmp); /* copy upto metacharacter */ - memcpy(t, RSTRING_PTR(str), s - RSTRING_PTR(str)); - t += s - RSTRING_PTR(str); + const char *p = RSTRING_PTR(str); + memcpy(t, p, s - p); + t += s - p; while (s < send) { c = rb_enc_ascget(s, send, &clen, enc); @@ -3587,7 +3667,7 @@ rb_reg_options(VALUE re) return options; } -VALUE +static VALUE rb_check_regexp_type(VALUE re) { return rb_check_convert_type(re, T_REGEXP, "Regexp", "to_regexp"); @@ -3781,10 +3861,12 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp) rb_encoding *str_enc = rb_enc_get(str); rb_encoding *src_enc = rb_enc_get(src); int acompat = rb_enc_asciicompat(str_enc); + long n; #define ASCGET(s,e,cl) (acompat ? (*(cl)=1,ISASCII((s)[0])?(s)[0]:-1) : rb_enc_ascget((s), (e), (cl), str_enc)) - p = s = RSTRING_PTR(str); - e = s + RSTRING_LEN(str); + RSTRING_GETMEM(str, s, n); + p = s; + e = s + n; while (s < e) { int c = ASCGET(s, e, &clen); @@ -3895,30 +3977,17 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp) return val; } -static VALUE -kcode_getter(ID _x, VALUE *_y) -{ - rb_warn("variable $KCODE is no longer effective"); - return Qnil; -} - -static void -kcode_setter(VALUE val, ID id, VALUE *_) -{ - rb_warn("variable $KCODE is no longer effective; ignored"); -} - static VALUE ignorecase_getter(ID _x, VALUE *_y) { - rb_warn("variable $= is no longer effective"); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective"); return Qfalse; } static void ignorecase_setter(VALUE val, ID id, VALUE *_) { - rb_warn("variable $= is no longer effective; ignored"); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective; ignored"); } static VALUE @@ -4013,6 +4082,10 @@ re_warn(const char *s) * and %r{...} literals, and by the Regexp::new * constructor. * + * You can create a \Regexp object explicitly with: + * + * - A {regexp literal}[doc/syntax/literals_rdoc.html#label-Regexp+Literals]. + * * :include: doc/regexp.rdoc */ @@ -4031,9 +4104,13 @@ Init_Regexp(void) rb_define_virtual_variable("$'", postmatch_getter, 0); rb_define_virtual_variable("$+", last_paren_match_getter, 0); + rb_gvar_ractor_local("$~"); + rb_gvar_ractor_local("$&"); + rb_gvar_ractor_local("$`"); + rb_gvar_ractor_local("$'"); + rb_gvar_ractor_local("$+"); + rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter); - rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter); - rb_define_virtual_variable("$-K", kcode_getter, kcode_setter); rb_cRegexp = rb_define_class("Regexp", rb_cObject); rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc); @@ -4090,6 +4167,8 @@ Init_Regexp(void) rb_define_method(rb_cMatch, "offset", match_offset, 1); rb_define_method(rb_cMatch, "begin", match_begin, 1); rb_define_method(rb_cMatch, "end", match_end, 1); + rb_define_method(rb_cMatch, "match", match_nth, 1); + rb_define_method(rb_cMatch, "match_length", match_nth_length, 1); rb_define_method(rb_cMatch, "to_a", match_to_a, 0); rb_define_method(rb_cMatch, "[]", match_aref, -1); rb_define_method(rb_cMatch, "captures", match_captures, 0); diff --git a/ruby/regcomp.c b/ruby/regcomp.c index df7f73bac..fbef92e18 100644 --- a/ruby/regcomp.c +++ b/ruby/regcomp.c @@ -138,6 +138,27 @@ bitset_on_num(BitSetRef bs) } #endif +// Attempt to right size allocated buffers for a regex post compile +static void +onig_reg_resize(regex_t *reg) +{ + do { + if (!reg->used) { + xfree(reg->p); + reg->alloc = 0; + reg->p = 0; + } + else if (reg->alloc > reg->used) { + unsigned char *new_ptr = xrealloc(reg->p, reg->used); + // Skip the right size optimization if memory allocation fails + if (new_ptr) { + reg->alloc = reg->used; + reg->p = new_ptr; + } + } + } while ((reg = reg->chain) != 0); +} + extern int onig_bbuf_init(BBuf* buf, OnigDistance size) { @@ -1914,7 +1935,7 @@ noname_disable_map(Node** plink, GroupNumRemap* map, int* counter) } static int -renumber_node_backref(Node* node, GroupNumRemap* map) +renumber_node_backref(Node* node, GroupNumRemap* map, const int num_mem) { int i, pos, n, old_num; int *backs; @@ -1930,6 +1951,7 @@ renumber_node_backref(Node* node, GroupNumRemap* map) backs = bn->back_dynamic; for (i = 0, pos = 0; i < old_num; i++) { + if (backs[i] > num_mem) return ONIGERR_INVALID_BACKREF; n = map[backs[i]].new_val; if (n > 0) { backs[pos] = n; @@ -1942,7 +1964,7 @@ renumber_node_backref(Node* node, GroupNumRemap* map) } static int -renumber_by_map(Node* node, GroupNumRemap* map) +renumber_by_map(Node* node, GroupNumRemap* map, const int num_mem) { int r = 0; @@ -1950,28 +1972,30 @@ renumber_by_map(Node* node, GroupNumRemap* map) case NT_LIST: case NT_ALT: do { - r = renumber_by_map(NCAR(node), map); + r = renumber_by_map(NCAR(node), map, num_mem); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: - r = renumber_by_map(NQTFR(node)->target, map); + r = renumber_by_map(NQTFR(node)->target, map, num_mem); break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); - if (en->type == ENCLOSE_CONDITION) + if (en->type == ENCLOSE_CONDITION) { + if (en->regnum > num_mem) return ONIGERR_INVALID_BACKREF; en->regnum = map[en->regnum].new_val; - r = renumber_by_map(en->target, map); + } + r = renumber_by_map(en->target, map, num_mem); } break; case NT_BREF: - r = renumber_node_backref(node, map); + r = renumber_node_backref(node, map, num_mem); break; case NT_ANCHOR: if (NANCHOR(node)->target) - r = renumber_by_map(NANCHOR(node)->target, map); + r = renumber_by_map(NANCHOR(node)->target, map, num_mem); break; default: @@ -2033,7 +2057,7 @@ disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env) r = noname_disable_map(root, map, &counter); if (r != 0) return r; - r = renumber_by_map(*root, map); + r = renumber_by_map(*root, map, env->num_mem); if (r != 0) return r; for (i = 1, pos = 1; i <= env->num_mem; i++) { @@ -3733,10 +3757,8 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env) switch (type) { case NT_LIST: { - Node* prev = NULL_NODE; do { r = setup_comb_exp_check(NCAR(node), r, env); - prev = NCAR(node); } while (r >= 0 && IS_NOT_NULL(node = NCDR(node))); } break; @@ -5014,7 +5036,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) if (NSTRING_IS_DONT_GET_OPT_INFO(node)) { int n = onigenc_strlen(env->enc, sn->s, sn->end); - max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n; + max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * (OnigDistance)n; } else { concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, @@ -5886,6 +5908,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, #endif end: + onig_reg_resize(reg); return r; err_unset: diff --git a/ruby/regerror.c b/ruby/regerror.c index efcfefffd..b18fc2e88 100644 --- a/ruby/regerror.c +++ b/ruby/regerror.c @@ -312,7 +312,7 @@ onig_error_code_to_str(UChar* s, OnigPosition code, ...) void onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, - UChar* pat, UChar* pat_end, const UChar *fmt, va_list args) + UChar* pat, UChar* pat_end, const char *fmt, va_list args) { size_t need; int n, len; @@ -376,7 +376,7 @@ onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, #if 0 /* unused */ void onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, - UChar* pat, UChar* pat_end, const UChar *fmt, ...) + UChar* pat, UChar* pat_end, const char *fmt, ...) { va_list args; va_start(args, fmt); diff --git a/ruby/regexec.c b/ruby/regexec.c index 10ada4d81..8334b16e9 100644 --- a/ruby/regexec.c +++ b/ruby/regexec.c @@ -601,7 +601,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end, (((s) - str) * num_comb_exp_check + ((snum) - 1)) # define STATE_CHECK_VAL(v,snum) do {\ if (state_check_buff != NULL) {\ - int x = STATE_CHECK_POS(s,snum);\ + ptrdiff_t x = STATE_CHECK_POS(s,snum);\ (v) = state_check_buff[x/8] & (1<<(x%8));\ }\ else (v) = 0;\ @@ -610,7 +610,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end, # define ELSE_IF_STATE_CHECK_MARK(stk) \ else if ((stk)->type == STK_STATE_CHECK_MARK) { \ - int x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\ + ptrdiff_t x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\ state_check_buff[x/8] |= (1<<(x%8)); \ } @@ -3873,7 +3873,7 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On MATCH_ARG_INIT(msa, option, region, at, at); #ifdef USE_COMBINATION_EXPLOSION_CHECK { - int offset = at - str; + ptrdiff_t offset = at - str; STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check); } #endif @@ -4352,7 +4352,7 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end, MATCH_ARG_INIT(msa, option, region, start, global_pos); #ifdef USE_COMBINATION_EXPLOSION_CHECK { - int offset = (MIN(start, range) - str); + ptrdiff_t offset = (MIN(start, range) - str); STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check); } #endif diff --git a/ruby/regint.h b/ruby/regint.h index a2f5bbba1..b136d804d 100644 --- a/ruby/regint.h +++ b/ruby/regint.h @@ -52,7 +52,7 @@ #ifndef UNALIGNED_WORD_ACCESS # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(__powerpc64__) || \ + defined(__powerpc64__) || defined(__aarch64__) || \ defined(__mc68020__) # define UNALIGNED_WORD_ACCESS 1 # else @@ -903,9 +903,13 @@ extern void onig_print_statistics(FILE* f); # endif #endif +#ifndef PRINTF_ARGS +#define PRINTF_ARGS(func, fmt, vargs) func +#endif + extern UChar* onig_error_code_to_format(OnigPosition code); -extern void onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, va_list args); -extern void onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, ...); +PRINTF_ARGS(extern void onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const char *fmt, va_list args), 6, 0); +PRINTF_ARGS(extern void onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const char *fmt, ...), 6, 7); extern int onig_bbuf_init(BBuf* buf, OnigDistance size); extern int onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo); #ifdef RUBY diff --git a/ruby/regparse.c b/ruby/regparse.c index a96c8c2fa..3348381e2 100644 --- a/ruby/regparse.c +++ b/ruby/regparse.c @@ -2187,7 +2187,6 @@ enum ReduceType { RQ_AQ, /* to '*?' */ RQ_QQ, /* to '??' */ RQ_P_QQ, /* to '+)??' */ - RQ_PQ_Q /* to '+?)?' */ }; static enum ReduceType const ReduceTypeTable[6][6] = { @@ -2197,7 +2196,7 @@ static enum ReduceType const ReduceTypeTable[6][6] = { {RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */ {RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */ {RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */ - {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */ + {RQ_ASIS, RQ_ASIS, RQ_ASIS, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */ }; extern void @@ -2234,12 +2233,6 @@ onig_reduce_nested_quantifier(Node* pnode, Node* cnode) c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1; return ; break; - case RQ_PQ_Q: - p->target = cnode; - p->lower = 0; p->upper = 1; p->greedy = 1; - c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0; - return ; - break; case RQ_ASIS: p->target = cnode; return ; @@ -2840,6 +2833,10 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end, #endif /* USE_NAMED_GROUP */ +#ifdef PRINTF_ARGS +PRINTF_ARGS(static void onig_syntax_warn(ScanEnv *env, const char *fmt, ...), 2, 3); +#endif + static void onig_syntax_warn(ScanEnv *env, const char *fmt, ...) { @@ -2848,7 +2845,7 @@ onig_syntax_warn(ScanEnv *env, const char *fmt, ...) va_start(args, fmt); onig_vsnprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, env->pattern, env->pattern_end, - (const UChar *)fmt, args); + fmt, args); va_end(args); #ifdef RUBY if (env->sourcefile == NULL) @@ -4348,7 +4345,7 @@ fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env) OnigEncoding enc = env->enc; UChar *prev, *start, *p = *src; - r = 0; + r = ONIGERR_INVALID_CHAR_PROPERTY_NAME; start = prev = p; while (!PEND) { @@ -4362,7 +4359,6 @@ fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env) return r; } else if (c == '(' || c == ')' || c == '{' || c == '|') { - r = ONIGERR_INVALID_CHAR_PROPERTY_NAME; break; } } diff --git a/ruby/revision.h b/ruby/revision.h index 51e025f8f..ef60a0c4b 100644 --- a/ruby/revision.h +++ b/ruby/revision.h @@ -1,2 +1,4 @@ -#define RUBY_REVISION "a0c7c23c9c" -#define RUBY_FULL_REVISION "a0c7c23c9cec0d0ffcba012279cd652d28ad5bf3" +#define RUBY_REVISION "f451bb5406" +#define RUBY_FULL_REVISION "f451bb5406878e1ac9ce9d37952f171837d0cb09" +#define RUBY_BRANCH_NAME "master" +#define RUBY_RELEASE_DATETIME "2020-01-20T10:13:19Z" diff --git a/ruby/ruby-runner.c b/ruby/ruby-runner.c index d41ba274c..b756c219f 100644 --- a/ruby/ruby-runner.c +++ b/ruby/ruby-runner.c @@ -1,5 +1,5 @@ #define _POSIX_C_SOURCE 200809L -#include "ruby/config.h" +#include "ruby/internal/config.h" #include #include #include diff --git a/ruby/ruby.c b/ruby/ruby.c index ffad7928f..d7ba181a2 100644 --- a/ruby/ruby.c +++ b/ruby/ruby.c @@ -11,38 +11,61 @@ **********************************************************************/ -#ifdef __CYGWIN__ -#include -#include -#endif -#include "ruby/encoding.h" -#include "ruby/thread.h" -#include "ruby/version.h" -#include "internal.h" -#include "eval_intern.h" -#include "dln.h" +#include "ruby/internal/config.h" + +#include #include #include -#include + +#ifdef __CYGWIN__ +# include +# include +#endif #ifdef __hpux -#include +# include #endif + #if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR) -#include +# include #endif #ifdef HAVE_UNISTD_H -#include +# include #endif + #if defined(HAVE_FCNTL_H) -#include +# include #elif defined(HAVE_SYS_FCNTL_H) -#include +# include #endif + #ifdef HAVE_SYS_PARAM_H # include #endif + +#include "dln.h" +#include "eval_intern.h" +#include "internal.h" +#include "internal/error.h" +#include "internal/file.h" +#include "internal/inits.h" +#include "internal/io.h" +#include "internal/load.h" +#include "internal/loadpath.h" +#include "internal/missing.h" +#include "internal/object.h" +#include "internal/parse.h" +#include "internal/process.h" +#include "internal/variable.h" +#include "mjit.h" +#include "yjit.h" +#include "ruby/encoding.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "ruby/version.h" +#include "ruby/internal/error.h" + #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif @@ -50,14 +73,6 @@ # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) #endif -#include "ruby/util.h" - -#include "mjit.h" - -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - void Init_ruby_description(void); #ifndef HAVE_STDLIB_H @@ -80,13 +95,17 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits); #define EACH_FEATURES(X, SEP) \ X(gems) \ SEP \ + X(error_highlight) \ + SEP \ X(did_you_mean) \ SEP \ X(rubyopt) \ SEP \ X(frozen_string_literal) \ SEP \ - X(jit) \ + X(mjit) \ + SEP \ + X(yjit) /* END OF FEATURES */ #define EACH_DEBUG_FEATURES(X, SEP) \ X(frozen_string_literal) \ @@ -124,13 +143,15 @@ enum feature_flag_bits { X(parsetree_with_comment) \ SEP \ X(insns) \ + SEP \ + X(insns_without_opt) \ /* END OF DUMPS */ enum dump_flag_bits { dump_version_v, EACH_DUMPS(DEFINE_DUMP, COMMA), dump_exit_bits = (DUMP_BIT(yydebug) | DUMP_BIT(syntax) | DUMP_BIT(parsetree) | DUMP_BIT(parsetree_with_comment) | - DUMP_BIT(insns)) + DUMP_BIT(insns) | DUMP_BIT(insns_without_opt)) }; typedef struct ruby_cmdline_options ruby_cmdline_options_t; @@ -170,6 +191,8 @@ struct ruby_cmdline_options { #if USE_MJIT struct mjit_options mjit; #endif + struct rb_yjit_options yjit; + int sflag, xflag; unsigned int warning: 1; unsigned int verbose: 1; @@ -197,7 +220,8 @@ enum { & ~FEATURE_BIT(gems) #endif & ~FEATURE_BIT(frozen_string_literal) - & ~FEATURE_BIT(jit) + & ~FEATURE_BIT(mjit) + & ~FEATURE_BIT(yjit) ) }; @@ -211,8 +235,15 @@ cmdline_options_init(ruby_cmdline_options_t *opt) opt->intern.enc.index = -1; opt->features.set = DEFAULT_FEATURES; #ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */ - opt->features.set |= FEATURE_BIT(jit); + opt->features.set |= FEATURE_BIT(mjit); +#elif defined(YJIT_FORCE_ENABLE) + opt->features.set |= FEATURE_BIT(yjit); #endif + + if (getenv("RUBY_YJIT_ENABLE")) { + opt->features.set |= FEATURE_BIT(yjit); + } + return opt; } @@ -227,20 +258,26 @@ static struct { char **argv; } origarg; +static const char esc_standout[] = "\n\033[1;7m"; +static const char esc_bold[] = "\033[1m"; +static const char esc_reset[] = "\033[0m"; +static const char esc_none[] = ""; + static void -show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, int help) +show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, int help, int highlight, unsigned int w) { - const unsigned int w = 16; + const char *sb = highlight ? esc_bold : esc_none; + const char *se = highlight ? esc_reset : esc_none; const int wrap = help && namelen + secondlen - 1 > w; - printf(" %.*s%-*.*s%-*s%s\n", namelen-1, str, + printf(" %s%.*s%-*.*s%s%-*s%s\n", sb, namelen-1, str, (wrap ? 0 : w - namelen + 1), - (help ? secondlen-1 : 0), str + namelen, + (help ? secondlen-1 : 0), str + namelen, se, (wrap ? w + 3 : 0), (wrap ? "\n" : ""), str + namelen + secondlen); } static void -usage(const char *name, int help) +usage(const char *name, int help, int highlight, int columns) { /* This message really ought to be max 23 lines. * Removed -h because the user already knows that option. Others? */ @@ -254,6 +291,11 @@ usage(const char *name, int help) (unsigned short)sizeof(shortopt), \ (unsigned short)sizeof(longopt), \ } +#if YJIT_SUPPORTED_P +# define PLATFORM_JIT_OPTION "--yjit" +#else +# define PLATFORM_JIT_OPTION "--mjit" +#endif static const struct message usage_msg[] = { M("-0[octal]", "", "specify record separator (\\0, if no argument)"), M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"), @@ -275,72 +317,94 @@ usage(const char *name, int help) M("-w", "", "turn warnings on for your script"), M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"), M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"), - M("--jit", "", "enable JIT with default options (experimental)"), - M("--jit-[option]","", "enable JIT with an option (experimental)"), + M("--jit", "", "enable JIT for the platform, same as " PLATFORM_JIT_OPTION " (experimental)"), + M("--mjit", "", "enable C compiler-based JIT compiler (experimental)"), + M("--yjit", "", "enable in-process JIT compiler (experimental)"), M("-h", "", "show this message, --help for more info"), }; static const struct message help_msg[] = { M("--copyright", "", "print the copyright"), M("--dump={insns|parsetree|...}[,...]", "", "dump debug information. see below for available dump list"), - M("--enable={gems|rubyopt|...}[,...]", ", --disable={gems|rubyopt|...}[,...]", + M("--enable={mjit|rubyopt|...}[,...]", ", --disable={mjit|rubyopt|...}[,...]", "enable or disable features. see below for available features"), M("--external-encoding=encoding", ", --internal-encoding=encoding", "specify the default external or internal character encoding"), + M("--backtrace-limit=num", "", "limit the maximum length of backtrace"), M("--verbose", "", "turn on verbose mode and disable script from stdin"), M("--version", "", "print the version number, then exit"), M("--help", "", "show this message, -h for short message"), }; static const struct message dumps[] = { M("insns", "", "instruction sequences"), + M("insns_without_opt", "", "instruction sequences compiled with no optimization"), M("yydebug", "", "yydebug of yacc parser generator"), M("parsetree", "", "AST"), M("parsetree_with_comment", "", "AST with comments"), }; static const struct message features[] = { - M("gems", "", "rubygems (default: "DEFAULT_RUBYGEMS_ENABLED")"), + M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")"), + M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED")"), M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"), M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"), M("frozen-string-literal", "", "freeze all string literals (default: disabled)"), - M("jit", "", "JIT compiler (default: disabled)"), + M("mjit", "", "C compiler-based JIT compiler (default: disabled)"), + M("yjit", "", "in-process JIT compiler (default: disabled)"), }; static const struct message warn_categories[] = { M("deprecated", "", "deprecated features"), M("experimental", "", "experimental features"), }; static const struct message mjit_options[] = { - M("--jit-warnings", "", "Enable printing JIT warnings"), - M("--jit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"), - M("--jit-wait", "", "Wait until JIT compilation finishes every time (for testing)"), - M("--jit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"), - M("--jit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"), - M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"), - M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"), + M("--mjit-warnings", "", "Enable printing JIT warnings"), + M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"), + M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"), + M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"), + M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"), + M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 10000)"), + M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"), + }; + static const struct message yjit_options[] = { +#if YJIT_STATS + M("--yjit-stats", "", "Enable collecting YJIT statistics"), +#endif + M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 256)"), + M("--yjit-call-threshold", "", "Number of calls to trigger JIT (default: 10)"), + M("--yjit-max-versions", "", "Maximum number of versions per basic block (default: 4)"), + M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"), }; int i; + const char *sb = highlight ? esc_standout+1 : esc_none; + const char *se = highlight ? esc_reset : esc_none; const int num = numberof(usage_msg) - (help ? 1 : 0); -#define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help) + unsigned int w = (columns > 80 ? (columns - 79) / 2 : 0) + 16; +#define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help, highlight, w) - printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name); + printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb, se, name); for (i = 0; i < num; ++i) SHOW(usage_msg[i]); if (!help) return; + if (highlight) sb = esc_standout; + for (i = 0; i < numberof(help_msg); ++i) SHOW(help_msg[i]); - puts("Dump List:"); + printf("%s""Dump List:%s\n", sb, se); for (i = 0; i < numberof(dumps); ++i) SHOW(dumps[i]); - puts("Features:"); + printf("%s""Features:%s\n", sb, se); for (i = 0; i < numberof(features); ++i) SHOW(features[i]); - puts("Warning categories:"); + printf("%s""Warning categories:%s\n", sb, se); for (i = 0; i < numberof(warn_categories); ++i) SHOW(warn_categories[i]); - puts("JIT options (experimental):"); + printf("%s""MJIT options (experimental):%s\n", sb, se); for (i = 0; i < numberof(mjit_options); ++i) SHOW(mjit_options[i]); + printf("%s""YJIT options (experimental):%s\n", sb, se); + for (i = 0; i < numberof(yjit_options); ++i) + SHOW(yjit_options[i]); } #define rubylib_path_new rb_str_new @@ -510,7 +574,12 @@ static VALUE runtime_libruby_path(void) { #if defined _WIN32 || defined __CYGWIN__ - DWORD len = RSTRING_EMBED_LEN_MAX, ret; + DWORD len, ret; +#if USE_RVARGC + len = 32; +#else + len = RSTRING_EMBED_LEN_MAX; +#endif VALUE path; VALUE wsopath = rb_str_new(0, len*sizeof(WCHAR)); WCHAR *wlibpath; @@ -588,9 +657,6 @@ ruby_init_loadpath(void) VALUE load_path, archlibdir = 0; ID id_initial_load_path_mark; const char *paths = ruby_initial_load_paths; -// --------- [Enclose.IO Hack start] --------- -#ifndef ENCLOSE_IO_RUBYC_BUILD_PASS2 -// --------- [Enclose.IO Hack end] --------- #if defined LOAD_RELATIVE #if !defined ENABLE_MULTIARCH # define RUBY_ARCH_PATH "" @@ -648,8 +714,11 @@ ruby_init_loadpath(void) p = p2; } #endif + baselen = p - libpath; + } + else { + baselen = 0; } - baselen = p - libpath; rb_str_resize(sopath, baselen); libpath = RSTRING_PTR(sopath); #define PREFIX_PATH() sopath @@ -660,16 +729,6 @@ ruby_init_loadpath(void) #define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len)) #define PREFIX_PATH() RUBY_RELATIVE(ruby_exec_prefix, exec_prefix_len) #endif -// --------- [Enclose.IO Hack start] --------- -#else // ifndef ENCLOSE_IO_RUBYC_BUILD_PASS2 -#define PREFIX_PATH() rb_str_new("/__enclose_io_memfs__", 21) -#ifdef _WIN32 -#define RUBY_RELATIVE(path, len) rb_str_buf_cat(rb_str_buf_cat(rb_str_buf_new(21+(len)), "/__enclose_io_memfs__", 21), (path), (len)) -#else // ifdef _WIN32 -#define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len)) -#endif // ifdef _WIN32 -#endif // ifndef ENCLOSE_IO_RUBYC_BUILD_PASS2 -// --------- [Enclose.IO Hack end] --------- rb_gc_register_address(&ruby_prefix_path); ruby_prefix_path = PREFIX_PATH(); OBJ_FREEZE_RAW(ruby_prefix_path); @@ -898,10 +957,22 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable) #define SET_FEATURE(bit) \ if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;} EACH_FEATURES(SET_FEATURE, ;); + if (NAME_MATCH_P("jit", str, len)) { // This allows you to cancel --jit +#if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P + set |= mask = FEATURE_BIT(mjit); +#else + set |= mask = FEATURE_BIT(yjit); +#endif + goto found; + } if (NAME_MATCH_P("all", str, len)) { - found: - FEATURE_SET_TO(*argp, mask, (mask & enable)); - return; + // YJIT and MJIT cannot be enabled at the same time. We enable only YJIT for --enable=all. +#if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P + mask &= ~(FEATURE_BIT(yjit)); +#else + mask &= ~(FEATURE_BIT(mjit)); +#endif + goto found; } #if AMBIGUOUS_FEATURE_NAMES if (matched == 1) goto found; @@ -917,10 +988,17 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable) rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, mesg)); #undef ADD_FEATURE_NAME } +#else + (void)set; #endif rb_warn("unknown argument for --%s: `%.*s'", enable ? "enable" : "disable", len, str); rb_warn("features are [%.*s].", (int)strlen(list), list); + return; + + found: + FEATURE_SET_TO(*argp, mask, (mask & enable)); + return; } static void @@ -989,38 +1067,93 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen #define set_source_encoding_once(opt, e, elen) \ set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen)) +#define opt_match(s, l, name) \ + ((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \ + (l) == rb_strlen_lit(name)) && \ + memcmp((s), name, rb_strlen_lit(name)) == 0 && \ + (((s) += rb_strlen_lit(name)), 1)) +#define opt_match_noarg(s, l, name) \ + opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1) +#define opt_match_arg(s, l, name) \ + opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0)) + +#define yjit_opt_match_noarg(s, l, name) \ + opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1) +#define yjit_opt_match_arg(s, l, name) \ + opt_match(s, l, name) && (*(s) && *(s+1) ? 1 : (rb_raise(rb_eRuntimeError, "--yjit-" name " needs an argument"), 0)) + +static bool +setup_yjit_options(const char *s, struct rb_yjit_options *yjit_opt) +{ + const char prefix[] = "yjit-"; + if (strncmp(prefix, s, sizeof(prefix)-1) != 0) { + return false; + } + s += sizeof(prefix)-1; + const size_t l = strlen(s); + if (l == 0) { + return false; + } + + if (yjit_opt_match_arg(s, l, "exec-mem-size")) { + yjit_opt->exec_mem_size = atoi(s + 1); + } + else if (yjit_opt_match_arg(s, l, "call-threshold")) { + yjit_opt->call_threshold = atoi(s + 1); + } + else if (yjit_opt_match_arg(s, l, "max-versions")) { + yjit_opt->max_versions = atoi(s + 1); + } + else if (yjit_opt_match_noarg(s, l, "greedy-versioning")) { + yjit_opt->greedy_versioning = true; + } + else if (yjit_opt_match_noarg(s, l, "no-type-prop")) { + yjit_opt->no_type_prop = true; + } + else if (yjit_opt_match_noarg(s, l, "stats")) { + yjit_opt->gen_stats = true; + } + else { + rb_raise(rb_eRuntimeError, + "invalid yjit option `%s' (--help will show valid yjit options)", s); + } + return true; +} + #if USE_MJIT static void setup_mjit_options(const char *s, struct mjit_options *mjit_opt) { + if (*s != '-') return; + const size_t l = strlen(++s); if (*s == 0) return; - else if (strcmp(s, "-warnings") == 0) { + else if (opt_match_noarg(s, l, "warnings")) { mjit_opt->warnings = 1; } - else if (strncmp(s, "-debug=", 7) == 0) { - mjit_opt->debug_flags = strdup(s + 7); - } - else if (strcmp(s, "-debug") == 0) { - mjit_opt->debug = 1; + else if (opt_match(s, l, "debug")) { + if (*s) + mjit_opt->debug_flags = strdup(s + 1); + else + mjit_opt->debug = 1; } - else if (strcmp(s, "-wait") == 0) { + else if (opt_match_noarg(s, l, "wait")) { mjit_opt->wait = 1; } - else if (strcmp(s, "-save-temps") == 0) { + else if (opt_match_noarg(s, l, "save-temps")) { mjit_opt->save_temps = 1; } - else if (strncmp(s, "-verbose=", 9) == 0) { - mjit_opt->verbose = atoi(s + 9); + else if (opt_match(s, l, "verbose")) { + mjit_opt->verbose = *s ? atoi(s + 1) : 1; } - else if (strncmp(s, "-max-cache=", 11) == 0) { - mjit_opt->max_cache_size = atoi(s + 11); + else if (opt_match_arg(s, l, "max-cache")) { + mjit_opt->max_cache_size = atoi(s + 1); } - else if (strncmp(s, "-min-calls=", 11) == 0) { - mjit_opt->min_calls = atoi(s + 11); + else if (opt_match_arg(s, l, "min-calls")) { + mjit_opt->min_calls = atoi(s + 1); } else { rb_raise(rb_eRuntimeError, - "invalid MJIT option `%s' (--help will show valid MJIT options)", s + 1); + "invalid MJIT option `%s' (--help will show valid MJIT options)", s); } } #endif @@ -1083,6 +1216,7 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) warning = 1; ruby_verbose = Qtrue; } + FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS); s++; goto reswitch; @@ -1112,7 +1246,7 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) if (*++s) { v = scan_oct(s, 1, &numlen); if (numlen == 0) - v = 1; + v = 2; s += numlen; } if (!opt->warning) { @@ -1129,6 +1263,17 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) } } warning = 1; + switch (v) { + case 0: + FEATURE_SET_TO(opt->warn, RB_WARN_CATEGORY_ALL_BITS, 0); + break; + case 1: + FEATURE_SET_TO(opt->warn, 1U << RB_WARN_CATEGORY_DEPRECATED, 0); + break; + default: + FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS); + break; + } } goto reswitch; @@ -1263,18 +1408,6 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) } goto reswitch; - case 'T': - { - size_t numlen; - - if (*++s) { - scan_oct(s, 2, &numlen); - s += numlen; - } - } - rb_warn("ruby -T will be removed in Ruby 3.0"); - goto reswitch; - case 'I': forbid_setid("-I"); if (*++s) @@ -1392,12 +1525,28 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) opt->verbose = 1; ruby_verbose = Qtrue; } - else if (strncmp("jit", s, 3) == 0) { + else if (strcmp("jit", s) == 0) { +#if !USE_MJIT + rb_warn("Ruby was built without JIT support"); +#elif defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P + FEATURE_SET(opt->features, FEATURE_BIT(mjit)); +#else + FEATURE_SET(opt->features, FEATURE_BIT(yjit)); +#endif + } + else if (strncmp("mjit", s, 4) == 0) { #if USE_MJIT - FEATURE_SET(opt->features, FEATURE_BIT(jit)); - setup_mjit_options(s + 3, &opt->mjit); + FEATURE_SET(opt->features, FEATURE_BIT(mjit)); + setup_mjit_options(s + 4, &opt->mjit); #else rb_warn("MJIT support is disabled."); +#endif + } + else if (strcmp("yjit", s) == 0 || setup_yjit_options(s, &opt->yjit)) { +#if USE_MJIT + FEATURE_SET(opt->features, FEATURE_BIT(yjit)); +#else + rb_warn("Ruby was built without JIT support"); #endif } else if (strcmp("yydebug", s) == 0) { @@ -1412,6 +1561,12 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt) opt->dump |= DUMP_BIT(help); goto switch_end; } + else if (is_option_with_arg("backtrace-limit", Qfalse, Qfalse)) { + char *e; + long n = strtol(s, &e, 10); + if (errno == ERANGE || n < 0 || *e) rb_raise(rb_eRuntimeError, "wrong limit for backtrace length"); + rb_backtrace_length_limit = n; + } else { rb_raise(rb_eRuntimeError, "invalid option --%s (-h will show valid options)", s); @@ -1463,6 +1618,33 @@ ruby_init_prelude(void) rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX")); } +void rb_call_builtin_inits(void); + +static void +ruby_opt_init(ruby_cmdline_options_t *opt) +{ + if (opt->dump & dump_exit_bits) return; + + if (opt->features.set & FEATURE_BIT(gems)) { + rb_define_module("Gem"); + if (opt->features.set & FEATURE_BIT(error_highlight)) { + rb_define_module("ErrorHighlight"); + } + if (opt->features.set & FEATURE_BIT(did_you_mean)) { + rb_define_module("DidYouMean"); + } + } + + rb_warning_category_update(opt->warn.mask, opt->warn.set); + + Init_ext(); /* load statically linked extensions before rubygems */ + rb_call_builtin_inits(); + ruby_init_prelude(); + + ruby_set_script_name(opt->script_name); + require_libraries(&opt->req_list); +} + static int opt_enc_index(VALUE enc_name) { @@ -1586,6 +1768,40 @@ rb_f_chomp(int argc, VALUE *argv, VALUE _) return str; } +static void +setup_pager_env(void) +{ + if (!getenv("LESS")) ruby_setenv("LESS", "-R"); // Output "raw" control characters. +} + +#ifdef _WIN32 +static int +tty_enabled(void) +{ + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD m; + if (!GetConsoleMode(h, &m)) return 0; +# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4 +# endif + if (!(m & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 0; + return 1; +} +#elif !defined(HAVE_WORKING_FORK) +# define tty_enabled() 0 +#endif + +static VALUE +copy_str(VALUE str, rb_encoding *enc, bool intern) +{ + if (!intern) { + if (rb_enc_str_coderange_scan(str, enc) == ENC_CODERANGE_BROKEN) + return 0; + return rb_enc_associate(rb_str_dup(str), enc); + } + return rb_enc_interned_str(RSTRING_PTR(str), RSTRING_LEN(str), enc); +} + static VALUE process_options(int argc, char **argv, ruby_cmdline_options_t *opt) { @@ -1595,19 +1811,73 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) const rb_iseq_t *iseq; rb_encoding *enc, *lenc; #if UTF8_PATH - rb_encoding *uenc, *ienc = 0; + rb_encoding *ienc = 0; + rb_encoding *const uenc = rb_utf8_encoding(); #endif const char *s; char fbuf[MAXPATHLEN]; int i = (int)proc_options(argc, argv, opt, 0); unsigned int dump = opt->dump & dump_exit_bits; + rb_vm_t *vm = GET_VM(); + const long loaded_before_enc = RARRAY_LEN(vm->loaded_features); if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) { + int tty = isatty(1); const char *const progname = (argc > 0 && argv && argv[0] ? argv[0] : origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] : ruby_engine); - usage(progname, (opt->dump & DUMP_BIT(help))); + int columns = 0; + if ((opt->dump & DUMP_BIT(help)) && tty) { + const char *pager_env = getenv("RUBY_PAGER"); + if (!pager_env) pager_env = getenv("PAGER"); + if (pager_env && *pager_env && isatty(0)) { + const char *columns_env = getenv("COLUMNS"); + if (columns_env) columns = atoi(columns_env); + VALUE pager = rb_str_new_cstr(pager_env); +#ifdef HAVE_WORKING_FORK + int fds[2]; + if (rb_pipe(fds) == 0) { + rb_pid_t pid = rb_fork(); + if (pid > 0) { + /* exec PAGER with reading from child */ + dup2(fds[0], 0); + } + else if (pid == 0) { + /* send the help message to the parent PAGER */ + dup2(fds[1], 1); + dup2(fds[1], 2); + } + close(fds[0]); + close(fds[1]); + if (pid > 0) { + setup_pager_env(); + rb_f_exec(1, &pager); + kill(SIGTERM, pid); + rb_waitpid(pid, 0, 0); + } + } +#else + setup_pager_env(); + VALUE port = rb_io_popen(pager, rb_str_new_lit("w"), Qnil, Qnil); + if (!NIL_P(port)) { + int oldout = dup(1); + int olderr = dup(2); + int fd = RFILE(port)->fptr->fd; + tty = tty_enabled(); + dup2(fd, 1); + dup2(fd, 2); + usage(progname, 1, tty, columns); + fflush(stdout); + dup2(oldout, 1); + dup2(olderr, 2); + rb_io_close(port); + return Qtrue; + } +#endif + } + } + usage(progname, (opt->dump & DUMP_BIT(help)), tty, columns); return Qtrue; } @@ -1634,13 +1904,25 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } if (opt->src.enc.name) - rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior"); + /* cannot set deprecated category, as enabling deprecation warnings based on flags + * has not happened yet. + */ + rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior"); #if USE_MJIT - if (opt->features.set & FEATURE_BIT(jit)) { + if (opt->features.set & FEATURE_BIT(mjit)) { opt->mjit.on = TRUE; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */ } #endif + if (opt->features.set & FEATURE_BIT(yjit)) { +#if USE_MJIT + if (opt->mjit.on) { + rb_warn("MJIT and YJIT cannot both be enabled at the same time. Exiting"); + exit(1); + } +#endif + rb_yjit_init(&opt->yjit); + } if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) { #if USE_MJIT mjit_opts.on = opt->mjit.on; /* used by ruby_show_version(). mjit_init() still can't be called here. */ @@ -1665,7 +1947,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) opt->script = "-"; } else if (opt->do_search) { - char *path = getenv("RUBYPATH"); + const char *path = getenv("RUBYPATH"); opt->script = 0; if (path) { @@ -1688,7 +1970,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) opt->script_name = rb_str_new_cstr(opt->script); opt->script = RSTRING_PTR(opt->script_name); -#if _WIN32 +#ifdef _WIN32 translit_char_bin(RSTRING_PTR(opt->script_name), '\\', '/'); #elif defined DOSISH translit_char(RSTRING_PTR(opt->script_name), '\\', '/'); @@ -1726,7 +2008,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) enc = rb_enc_from_index(opt->ext.enc.index); } else { - enc = lenc; + enc = IF_UTF8_PATH(uenc, lenc); } rb_enc_set_default_external(rb_enc_from_encoding(enc)); if (opt->intern.enc.index >= 0) { @@ -1738,8 +2020,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) #endif } script_name = opt->script_name; - rb_enc_associate(opt->script_name, - IF_UTF8_PATH(uenc = rb_utf8_encoding(), lenc)); + rb_enc_associate(opt->script_name, IF_UTF8_PATH(uenc, lenc)); #if UTF8_PATH if (uenc != lenc) { opt->script_name = str_conv_enc(opt->script_name, uenc, lenc); @@ -1749,7 +2030,6 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_obj_freeze(opt->script_name); if (IF_UTF8_PATH(uenc != lenc, 1)) { long i; - rb_vm_t *vm = GET_VM(); VALUE load_path = vm->load_path; const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK; int modifiable = FALSE; @@ -1763,7 +2043,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) if (newpath == path) continue; path = newpath; #else - path = rb_enc_associate(rb_str_dup(path), lenc); + if (!(path = copy_str(path, lenc, !mark))) continue; #endif if (mark) rb_ivar_set(path, id_initial_load_path_mark, path); if (!modifiable) { @@ -1776,19 +2056,25 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_ary_replace(vm->load_path_snapshot, load_path); } } - Init_ext(); /* load statically linked extensions before rubygems */ - if (opt->features.set & FEATURE_BIT(gems)) { - rb_define_module("Gem"); - if (opt->features.set & FEATURE_BIT(did_you_mean)) { - rb_define_module("DidYouMean"); - } + { + VALUE loaded_features = vm->loaded_features; + bool modified = false; + for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) { + VALUE path = RARRAY_AREF(loaded_features, i); + if (!(path = copy_str(path, IF_UTF8_PATH(uenc, lenc), true))) continue; + modified = true; + RARRAY_ASET(loaded_features, i, path); + } + if (modified) { + rb_ary_replace(vm->loaded_features_snapshot, loaded_features); + } } - ruby_init_prelude(); + if (opt->features.mask & COMPILATION_FEATURES) { VALUE option = rb_hash_new(); #define SET_COMPILE_OPTION(h, o, name) \ rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \ - (FEATURE_SET_P(o->features, FEATURE_BIT(name)) ? Qtrue : Qfalse)); + RBOOL(FEATURE_SET_P(o->features, FEATURE_BIT(name)))); SET_COMPILE_OPTION(option, opt, frozen_string_literal); SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal); rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option); @@ -1817,14 +2103,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } #endif rb_enc_associate(opt->e_script, eenc); - if (!(opt->dump & ~DUMP_BIT(version_v))) { - ruby_set_script_name(opt->script_name); - require_libraries(&opt->req_list); - } + ruby_opt_init(opt); ruby_set_script_name(progname); rb_parser_set_options(parser, opt->do_print, opt->do_loop, opt->do_line, opt->do_split); - rb_warning_category_update(opt->warn.mask, opt->warn.set); ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1); } else { @@ -1842,7 +2124,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) enc = rb_enc_from_index(opt->ext.enc.index); } else { - enc = lenc; + enc = IF_UTF8_PATH(uenc, lenc); } rb_enc_set_default_external(rb_enc_from_encoding(enc)); if (opt->intern.enc.index >= 0) { @@ -1904,11 +2186,11 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")), toplevel_binding); const struct rb_block *base_block = toplevel_context(toplevel_binding); - iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block)); + iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block), !(dump & DUMP_BIT(insns_without_opt))); rb_ast_dispose(ast); } - if (dump & DUMP_BIT(insns)) { + if (dump & (DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))) { rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq)); rb_io_flush(rb_stdout); dump &= ~DUMP_BIT(insns); @@ -1920,7 +2202,12 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_define_readonly_boolean("$-l", opt->do_line); rb_define_readonly_boolean("$-a", opt->do_split); + rb_gvar_ractor_local("$-p"); + rb_gvar_ractor_local("$-l"); + rb_gvar_ractor_local("$-a"); + if ((rb_e_script = opt->e_script) != 0) { + rb_str_freeze(rb_e_script); rb_gc_register_mark_object(opt->e_script); } @@ -2047,10 +2334,7 @@ load_file_internal(VALUE argp_v) if (NIL_P(c)) { argp->f = f = Qnil; } - if (!(opt->dump & ~DUMP_BIT(version_v))) { - ruby_set_script_name(opt->script_name); - require_libraries(&opt->req_list); /* Why here? unnatural */ - } + ruby_opt_init(opt); } if (opt->src.enc.index >= 0) { enc = rb_enc_from_index(opt->src.enc.index); @@ -2063,7 +2347,6 @@ load_file_internal(VALUE argp_v) } rb_parser_set_options(parser, opt->do_print, opt->do_loop, opt->do_line, opt->do_split); - rb_warning_category_update(opt->warn.mask, opt->warn.set); if (NIL_P(f)) { f = rb_str_new(0, 0); rb_enc_associate(f, enc); @@ -2091,6 +2374,26 @@ load_file_internal(VALUE argp_v) return (VALUE)ast; } +/* disabling O_NONBLOCK, and returns 0 on success, otherwise errno */ +static inline int +disable_nonblock(int fd) +{ +#if defined(HAVE_FCNTL) && defined(F_SETFL) + if (fcntl(fd, F_SETFL, 0) < 0) { + const int e = errno; + ASSUME(e != 0); +# if defined ENOTSUP + if (e == ENOTSUP) return 0; +# endif +# if defined B_UNSUPPORTED + if (e == B_UNSUPPORTED) return 0; +# endif + return e; + } +#endif + return 0; +} + static VALUE open_load_file(VALUE fname_v, int *xflag) { @@ -2140,14 +2443,10 @@ open_load_file(VALUE fname_v, int *xflag) } rb_update_max_fd(fd); -#if defined HAVE_FCNTL && MODE_TO_LOAD != O_RDONLY - /* disabling O_NONBLOCK */ - if (fcntl(fd, F_SETFL, 0) < 0) { - e = errno; + if (MODE_TO_LOAD != O_RDONLY && (e = disable_nonblock(fd)) != 0) { (void)close(fd); rb_load_fail(fname_v, strerror(e)); } -#endif e = ruby_is_fd_loadable(fd); if (!e) { @@ -2162,7 +2461,7 @@ open_load_file(VALUE fname_v, int *xflag) We need to wait if FIFO is empty. It's FIFO's semantics. rb_thread_wait_fd() release GVL. So, it's safe. */ - rb_thread_wait_fd(fd); + rb_io_wait(f, RB_INT2NUM(RUBY_IO_READABLE), Qnil); } } return f; @@ -2285,11 +2584,6 @@ external_str_new_cstr(const char *p) #endif } -/*! Sets the current script name to this value. - * - * This is similar to $0 = name in Ruby level but also affects - * Method#location and others. - */ void ruby_script(const char *name) { @@ -2332,16 +2626,24 @@ forbid_setid(const char *s, const ruby_cmdline_options_t *opt) rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s); } +static VALUE +verbose_getter(ID id, VALUE *ptr) +{ + return *rb_ruby_verbose_ptr(); +} + static void verbose_setter(VALUE val, ID id, VALUE *variable) { - *variable = RTEST(val) ? Qtrue : val; + *rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val; } static VALUE -opt_W_getter(ID id, VALUE *variable) +opt_W_getter(ID id, VALUE *dmy) { - switch (*variable) { + VALUE v = *rb_ruby_verbose_ptr(); + + switch (v) { case Qnil: return INT2FIX(0); case Qfalse: @@ -2353,16 +2655,34 @@ opt_W_getter(ID id, VALUE *variable) } } -/*! Defines built-in variables */ +static VALUE +debug_getter(ID id, VALUE *dmy) +{ + return *rb_ruby_debug_ptr(); +} + +static void +debug_setter(VALUE val, ID id, VALUE *dmy) +{ + *rb_ruby_debug_ptr() = val; +} + void ruby_prog_init(void) { - rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter); - rb_define_variable("$DEBUG", &ruby_debug); - rb_define_variable("$-d", &ruby_debug); + rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-v", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-w", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter); + rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter); + rb_define_virtual_variable("$-d", debug_getter, debug_setter); + + rb_gvar_ractor_local("$VERBOSE"); + rb_gvar_ractor_local("$-v"); + rb_gvar_ractor_local("$-w"); + rb_gvar_ractor_local("$-W"); + rb_gvar_ractor_local("$DEBUG"); + rb_gvar_ractor_local("$-d"); rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0); rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0); @@ -2385,12 +2705,6 @@ ruby_set_argv(int argc, char **argv) int i; VALUE av = rb_argv; -#if defined(USE_DLN_A_OUT) - if (origarg.argc > 0 && origarg.argv) - dln_argv0 = origarg.argv[0]; - else if (argc > 0 && argv) - dln_argv0 = argv[0]; -#endif rb_ary_clear(av); for (i = 0; i < argc; i++) { VALUE arg = external_str_new_cstr(argv[i]); @@ -2453,13 +2767,6 @@ fill_standard_fds(void) } } -/*! Initializes the process for libruby. - * - * This function assumes this process is ruby(1) and it has just started. - * Usually programs that embed CRuby interpreter may not call this function, - * and may do their own initialization. - * argc and argv cannot be NULL. - */ void ruby_sysinit(int *argc, char ***argv) { @@ -2469,9 +2776,6 @@ ruby_sysinit(int *argc, char ***argv) if (*argc >= 0 && *argv) { origarg.argc = *argc; origarg.argv = *argv; -#if defined(USE_DLN_A_OUT) - dln_argv0 = origarg.argv[0]; -#endif } fill_standard_fds(); } diff --git a/ruby/ruby_assert.h b/ruby/ruby_assert.h index fa15da1e2..d8f7ddd35 100644 --- a/ruby/ruby_assert.h +++ b/ruby/ruby_assert.h @@ -1,15 +1,14 @@ +#ifndef RUBY_TOPLEVEL_ASSERT_H /*-*-C-*-vi:se ft=c:*/ +#define RUBY_TOPLEVEL_ASSERT_H +/** + * @author Ruby developers + * @copyright 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. + */ #include "ruby/assert.h" - -#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) -/* C89 compilers are required to support strings of only 509 chars. */ -/* can't use RUBY_ASSERT for such compilers. */ -#include -#else #undef assert -#define assert RUBY_ASSERT -#endif +#define assert RUBY_ASSERT_NDEBUG -#ifdef NDEBUG - #undef RUBY_NDEBUG - #define RUBY_NDEBUG 1 -#endif +#endif /* RUBY_TOPLEVEL_ASSERT_H */ diff --git a/ruby/ruby_atomic.h b/ruby/ruby_atomic.h index 1b395cd23..57d341082 100644 --- a/ruby/ruby_atomic.h +++ b/ruby/ruby_atomic.h @@ -1,244 +1,23 @@ -#ifndef RUBY_ATOMIC_H -#define RUBY_ATOMIC_H - -#if 0 -#elif defined HAVE_GCC_ATOMIC_BUILTINS -typedef unsigned int rb_atomic_t; -# define ATOMIC_SET(var, val) (void)__atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST) -# define ATOMIC_INC(var) __atomic_fetch_add(&(var), 1, __ATOMIC_SEQ_CST) -# define ATOMIC_DEC(var) __atomic_fetch_sub(&(var), 1, __ATOMIC_SEQ_CST) -# define ATOMIC_OR(var, val) __atomic_fetch_or(&(var), (val), __ATOMIC_SEQ_CST) -# define ATOMIC_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST) -# define ATOMIC_CAS(var, oldval, newval) RB_GNUC_EXTENSION_BLOCK( \ - __typeof__(var) oldvaldup = (oldval); /* oldval should not be modified */ \ - __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ - oldvaldup ) - -# define ATOMIC_SIZE_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST) -# define ATOMIC_SIZE_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST) - -# define RUBY_ATOMIC_GENERIC_MACRO 1 - -#elif defined HAVE_GCC_SYNC_BUILTINS -/* @shyouhei hack to support atomic operations in case of gcc. Gcc - * has its own pseudo-insns to support them. See info, or - * http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */ - -typedef unsigned int rb_atomic_t; /* Anything OK */ -# define ATOMIC_SET(var, val) (void)__sync_lock_test_and_set(&(var), (val)) -# define ATOMIC_INC(var) __sync_fetch_and_add(&(var), 1) -# define ATOMIC_DEC(var) __sync_fetch_and_sub(&(var), 1) -# define ATOMIC_OR(var, val) __sync_fetch_and_or(&(var), (val)) -# define ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val)) -# define ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval)) - -# define ATOMIC_SIZE_ADD(var, val) __sync_fetch_and_add(&(var), (val)) -# define ATOMIC_SIZE_SUB(var, val) __sync_fetch_and_sub(&(var), (val)) - -# define RUBY_ATOMIC_GENERIC_MACRO 1 - -#elif defined _WIN32 -#if defined _MSC_VER && _MSC_VER > 1200 -#pragma intrinsic(_InterlockedOr) -#endif -typedef LONG rb_atomic_t; - -# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val)) -# define ATOMIC_INC(var) InterlockedIncrement(&(var)) -# define ATOMIC_DEC(var) InterlockedDecrement(&(var)) -#if defined __GNUC__ -# define ATOMIC_OR(var, val) __asm__("lock\n\t" "orl\t%1, %0" : "=m"(var) : "Ir"(val)) -#elif defined _MSC_VER && _MSC_VER <= 1200 -# define ATOMIC_OR(var, val) rb_w32_atomic_or(&(var), (val)) -static inline void -rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val) -{ -#ifdef _M_IX86 - __asm mov eax, var; - __asm mov ecx, val; - __asm lock or [eax], ecx; -#else -#error unsupported architecture -#endif -} -#else -# define ATOMIC_OR(var, val) _InterlockedOr(&(var), (val)) -#endif -# define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val)) -# define ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval)) -# if defined _MSC_VER && _MSC_VER <= 1200 -static inline rb_atomic_t -rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval) -{ - return (rb_atomic_t)InterlockedCompareExchange((PVOID *)var, (PVOID)newval, (PVOID)oldval); -} -# undef ATOMIC_CAS -# define ATOMIC_CAS(var, oldval, newval) rb_w32_atomic_cas(&(var), (oldval), (newval)) -# endif -# ifdef _M_AMD64 -# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), (val)) -# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), -(LONG)(val)) -# define ATOMIC_SIZE_INC(var) InterlockedIncrement64(&(var)) -# define ATOMIC_SIZE_DEC(var) InterlockedDecrement64(&(var)) -# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange64(&(var), (val)) -# define ATOMIC_SIZE_CAS(var, oldval, newval) InterlockedCompareExchange64(&(var), (newval), (oldval)) -# else -# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd((LONG *)&(var), (val)) -# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd((LONG *)&(var), -(LONG)(val)) -# define ATOMIC_SIZE_INC(var) InterlockedIncrement((LONG *)&(var)) -# define ATOMIC_SIZE_DEC(var) InterlockedDecrement((LONG *)&(var)) -# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange((LONG *)&(var), (val)) -# endif - -# ifdef InterlockedExchangePointer -# define ATOMIC_PTR_EXCHANGE(var, val) InterlockedExchangePointer((PVOID volatile *)&(var), (PVOID)(val)) -# endif /* See below for definitions of other situations */ - -#elif defined(__sun) && defined(HAVE_ATOMIC_H) -#include -typedef unsigned int rb_atomic_t; - -# define ATOMIC_SET(var, val) (void)atomic_swap_uint(&(var), (val)) -# define ATOMIC_INC(var) atomic_inc_uint(&(var)) -# define ATOMIC_DEC(var) atomic_dec_uint(&(var)) -# define ATOMIC_OR(var, val) atomic_or_uint(&(var), (val)) -# define ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val)) -# define ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval)) - -# if SIZEOF_SIZE_T == SIZEOF_LONG -# define ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val)) -# define ATOMIC_SIZE_SUB(var, val) atomic_add_long(&(var), -(val)) -# define ATOMIC_SIZE_INC(var) atomic_inc_ulong(&(var)) -# define ATOMIC_SIZE_DEC(var) atomic_dec_ulong(&(var)) -# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_ulong(&(var), (val)) -# define ATOMIC_SIZE_CAS(var, oldval, val) atomic_cas_ulong(&(var), (oldval), (val)) -# else -# define ATOMIC_SIZE_ADD(var, val) atomic_add_int(&(var), (val)) -# define ATOMIC_SIZE_SUB(var, val) atomic_add_int(&(var), -(val)) -# define ATOMIC_SIZE_INC(var) atomic_inc_uint(&(var)) -# define ATOMIC_SIZE_DEC(var) atomic_dec_uint(&(var)) -# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_uint(&(var), (val)) -# endif - -#else -typedef int rb_atomic_t; -#define NEED_RUBY_ATOMIC_OPS -extern rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val); -extern rb_atomic_t ruby_atomic_compare_and_swap(rb_atomic_t *ptr, - rb_atomic_t cmp, - rb_atomic_t newval); - -# define ATOMIC_SET(var, val) (void)((var) = (val)) -# define ATOMIC_INC(var) ((var)++) -# define ATOMIC_DEC(var) ((var)--) -# define ATOMIC_OR(var, val) ((var) |= (val)) -# define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val)) -# define ATOMIC_CAS(var, oldval, newval) ruby_atomic_compare_and_swap(&(var), (oldval), (newval)) - -# define ATOMIC_SIZE_ADD(var, val) (void)((var) += (val)) -# define ATOMIC_SIZE_SUB(var, val) (void)((var) -= (val)) -# define ATOMIC_SIZE_EXCHANGE(var, val) ruby_atomic_size_exchange(&(var), (val)) -static inline size_t -ruby_atomic_size_exchange(size_t *ptr, size_t val) -{ - size_t old = *ptr; - *ptr = val; - return old; -} -#endif - -#ifndef ATOMIC_SIZE_INC -# define ATOMIC_SIZE_INC(var) ATOMIC_INC(var) -#endif - -#ifndef ATOMIC_SIZE_DEC -# define ATOMIC_SIZE_DEC(var) ATOMIC_DEC(var) -#endif - -#ifndef ATOMIC_SIZE_EXCHANGE -# define ATOMIC_SIZE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val) -#endif - -#ifndef ATOMIC_SIZE_CAS -# define ATOMIC_SIZE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val) -#endif - -#if RUBY_ATOMIC_GENERIC_MACRO -# ifndef ATOMIC_PTR_EXCHANGE -# define ATOMIC_PTR_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val) -# endif - -# ifndef ATOMIC_PTR_CAS -# define ATOMIC_PTR_CAS(var, oldval, newval) ATOMIC_CAS(var, oldval, newval) -# endif - -# ifndef ATOMIC_VALUE_EXCHANGE -# define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val) -# endif - -# ifndef ATOMIC_VALUE_CAS -# define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val) -# endif -#endif - -#ifndef ATOMIC_PTR_EXCHANGE -# if SIZEOF_VOIDP == SIZEOF_SIZE_T -# define ATOMIC_PTR_EXCHANGE(var, val) (void *)ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val)) -# else -# define ATOMIC_PTR_EXCHANGE(var, val) ruby_atomic_ptr_exchange((const void **)&(var), (val)) -static inline void * -ruby_atomic_ptr_exchange(const void **ptr, const void *val) -{ - const void *const old = *ptr; - *ptr = val; - return (void *)old; -} -# endif -#endif - -#ifndef ATOMIC_PTR_CAS -# if SIZEOF_VOIDP == SIZEOF_SIZE_T -# define ATOMIC_PTR_CAS(var, oldval, val) (void *)ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val)) -# else -# define ATOMIC_PTR_CAS(var, oldval, val) ruby_atomic_ptr_cas(&(var), (oldval), (val)) -static inline void * -ruby_atomic_ptr_cas(const void **ptr, const void *oldval, const void *val) -{ - const void *const old = *ptr; - if (old == oldval) *ptr = val; - return (void *)old; -} -# endif -#endif - -#ifndef ATOMIC_VALUE_EXCHANGE -# if SIZEOF_VALUE == SIZEOF_SIZE_T -# define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val)) -# else -# define ATOMIC_VALUE_EXCHANGE(var, val) ruby_atomic_value_exchange(&(var), (val)) -static inline VALUE -ruby_atomic_value_exchange(VALUE *ptr, VALUE val) -{ - const VALUE old = *ptr; - *ptr = val; - return old; -} -# endif -#endif - -#ifndef ATOMIC_VALUE_CAS -# if SIZEOF_VALUE == SIZEOF_SIZE_T -# define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val)) -# else -# define ATOMIC_VALUE_CAS(var, oldval, val) ruby_atomic_value_cas(&(var), (oldval), (val)) -static inline VALUE -ruby_atomic_value_cas(VALUE *ptr, VALUE oldval, VALUE val) -{ - const VALUE old = *ptr; - if (old == oldval) *ptr = val; - return old; -} -# endif -#endif - -#endif /* RUBY_ATOMIC_H */ +#include "ruby/atomic.h" + +/* shim macros only */ +#define ATOMIC_ADD(var, val) RUBY_ATOMIC_ADD(var, val) +#define ATOMIC_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval) +#define ATOMIC_DEC(var) RUBY_ATOMIC_DEC(var) +#define ATOMIC_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val) +#define ATOMIC_FETCH_ADD(var, val) RUBY_ATOMIC_FETCH_ADD(var, val) +#define ATOMIC_FETCH_SUB(var, val) RUBY_ATOMIC_FETCH_SUB(var, val) +#define ATOMIC_INC(var) RUBY_ATOMIC_INC(var) +#define ATOMIC_OR(var, val) RUBY_ATOMIC_OR(var, val) +#define ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_PTR_CAS(var, oldval, newval) +#define ATOMIC_PTR_EXCHANGE(var, val) RUBY_ATOMIC_PTR_EXCHANGE(var, val) +#define ATOMIC_SET(var, val) RUBY_ATOMIC_SET(var, val) +#define ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_SIZE_ADD(var, val) +#define ATOMIC_SIZE_CAS(var, oldval, newval) RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) +#define ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_SIZE_DEC(var) +#define ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_SIZE_EXCHANGE(var, val) +#define ATOMIC_SIZE_INC(var) RUBY_ATOMIC_SIZE_INC(var) +#define ATOMIC_SIZE_SUB(var, val) RUBY_ATOMIC_SIZE_SUB(var, val) +#define ATOMIC_SUB(var, val) RUBY_ATOMIC_SUB(var, val) +#define ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_VALUE_CAS(var, oldval, val) +#define ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_VALUE_EXCHANGE(var, val) diff --git a/ruby/safe.c b/ruby/safe.c deleted file mode 100644 index a6b490533..000000000 --- a/ruby/safe.c +++ /dev/null @@ -1,145 +0,0 @@ -/********************************************************************** - - safe.c - - - $Author$ - created at: Tue Sep 23 09:44:32 JST 2008 - - Copyright (C) 2008 Yukihiro Matsumoto - -**********************************************************************/ - -#define SAFE_LEVEL_MAX RUBY_SAFE_LEVEL_MAX - -#include "ruby/ruby.h" -#include "vm_core.h" - -/* $SAFE accessor */ - -#undef rb_secure -#undef rb_set_safe_level -#undef ruby_safe_level_2_warning - -int -ruby_safe_level_2_warning(void) -{ - rb_warn("rb_safe_level_2_warning will be removed in Ruby 3.0"); - return 2; -} - -int -rb_safe_level(void) -{ - rb_warn("rb_safe_level will be removed in Ruby 3.0"); - return GET_VM()->safe_level_; -} - -void -rb_set_safe_level_force(int safe) -{ - rb_warn("rb_set_safe_level_force will be removed in Ruby 3.0"); - GET_VM()->safe_level_ = safe; -} - -void -rb_set_safe_level(int level) -{ - rb_vm_t *vm = GET_VM(); - - rb_warn("rb_set_safe_level will be removed in Ruby 3.0"); - if (level > SAFE_LEVEL_MAX) { - rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete"); - } - else if (level < 0) { - rb_raise(rb_eArgError, "$SAFE should be >= 0"); - } - else { - int line; - const char *path = rb_source_location_cstr(&line); - - if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n", - path ? path : "-", line, vm->safe_level_, level); - - vm->safe_level_ = level; - } -} - -static VALUE -safe_getter(ID _x, VALUE *_y) -{ - rb_warn("$SAFE will become a normal global variable in Ruby 3.0"); - return INT2NUM(GET_VM()->safe_level_); -} - -static void -safe_setter(VALUE val, ID _x, VALUE *_y) -{ - int level = NUM2INT(val); - rb_vm_t *vm = GET_VM(); - - rb_warn("$SAFE will become a normal global variable in Ruby 3.0"); - if (level > SAFE_LEVEL_MAX) { - rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete"); - } - else if (level < 0) { - rb_raise(rb_eArgError, "$SAFE should be >= 0"); - } - else { - int line; - const char *path = rb_source_location_cstr(&line); - - if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n", - path ? path : "-", line, vm->safe_level_, level); - - vm->safe_level_ = level; - } -} - -void -rb_secure(int level) -{ - rb_warn("rb_secure will be removed in Ruby 3.0"); - if (level <= GET_VM()->safe_level_) { - ID caller_name = rb_frame_callee(); - if (caller_name) { - rb_raise(rb_eSecurityError, "Insecure operation `%"PRIsVALUE"' at level %d", - rb_id2str(caller_name), GET_VM()->safe_level_); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation at level %d", - GET_VM()->safe_level_); - } - } -} - -void -rb_secure_update(VALUE obj) -{ - rb_warn("rb_secure_update will be removed in Ruby 3.0"); -} - -void -rb_insecure_operation(void) -{ - rb_warn("rb_insecure_operation will be removed in Ruby 3.0"); - ID caller_name = rb_frame_callee(); - if (caller_name) { - rb_raise(rb_eSecurityError, "Insecure operation - %"PRIsVALUE, - rb_id2str(caller_name)); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation: -r"); - } -} - -void -rb_check_safe_obj(VALUE x) -{ - rb_warn("rb_check_safe_obj will be removed in Ruby 3.0"); -} - -void -Init_safe(void) -{ - rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); -} diff --git a/ruby/sample/drb/README.ja.rdoc b/ruby/sample/drb/README.ja.rdoc index 3ab70f336..1697b1b70 100644 --- a/ruby/sample/drb/README.ja.rdoc +++ b/ruby/sample/drb/README.ja.rdoc @@ -50,7 +50,7 @@ * drbssl_s.rb * drbssl_c.rb -* DRbProtoclã®è¿½åР例 +* DRbProtocolã®è¿½åР例 * http0.rb * http0serv.rb diff --git a/ruby/sample/drb/README.rdoc b/ruby/sample/drb/README.rdoc index 80ae910a8..fcb418241 100644 --- a/ruby/sample/drb/README.rdoc +++ b/ruby/sample/drb/README.rdoc @@ -47,7 +47,7 @@ * drbssl_s.rb * drbssl_c.rb -* add DRbProtocl +* add DRbProtocol * http0.rb * http0serv.rb diff --git a/ruby/sample/drb/dchats.rb b/ruby/sample/drb/dchats.rb index 58af3cf00..c96486a45 100644 --- a/ruby/sample/drb/dchats.rb +++ b/ruby/sample/drb/dchats.rb @@ -28,7 +28,7 @@ def listen(str) class ChatServer def initialize - @mutex = Mutex.new + @mutex = Thread::Mutex.new @members = {} end diff --git a/ruby/sample/drb/name.rb b/ruby/sample/drb/name.rb index a8ad28749..6d88186da 100644 --- a/ruby/sample/drb/name.rb +++ b/ruby/sample/drb/name.rb @@ -39,11 +39,12 @@ module DRbNamedObject DRbNAMEDICT = {} + DRBNAMEMUTEX = Thread::Mutex.new attr_reader(:drb_name) def drb_name=(name) @drb_name = name - Thread.exclusive do + DRBNAMEMUTEX.synchronize do raise(IndexError, name) if DRbNAMEDICT[name] DRbNAMEDICT[name] = self end diff --git a/ruby/sample/exyacc.rb b/ruby/sample/exyacc.rb index 9a9435a0d..cbcc18d58 100644 --- a/ruby/sample/exyacc.rb +++ b/ruby/sample/exyacc.rb @@ -8,7 +8,7 @@ grammar = source[sbeg, send-sbeg] grammar.sub!(/.*\n/, "") grammar.gsub!(/'\{'/, "'\001'") - grammar.gsub!(/'\}'/, "'\002'") + grammar.gsub!(/["']\}["']/, "'\002'") grammar.gsub!(%r{\*/}, "\003\003") grammar.gsub!(%r{/\*[^\003]*\003\003}, '') while grammar.gsub!(/\{[^{}]*\}/, ''); end diff --git a/ruby/sample/list.rb b/ruby/sample/list.rb index b4d1d653e..7458ba024 100644 --- a/ruby/sample/list.rb +++ b/ruby/sample/list.rb @@ -5,7 +5,6 @@ def initialize(item) # @variables are instance variable, no declaration needed @data = item @succ = nil - @head = nil end def data @@ -23,6 +22,10 @@ def succ=(new) end class MyList + def initialize + @head = nil + end + def add_to_list(obj) elt = MyElem.new(obj) if @head diff --git a/ruby/sample/openssl/c_rehash.rb b/ruby/sample/openssl/c_rehash.rb index cd6c9d5fd..de4b66e90 100644 --- a/ruby/sample/openssl/c_rehash.rb +++ b/ruby/sample/openssl/c_rehash.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require 'openssl' -require 'digest/md5' class CHashDir include Enumerable @@ -161,7 +160,7 @@ def hash_name(name) end def fingerprint(der) - Digest::MD5.hexdigest(der).upcase + OpenSSL::Digest.hexdigest('MD5', der).upcase end end diff --git a/ruby/sample/openssl/cert2text.rb b/ruby/sample/openssl/cert2text.rb index 50da224e7..fe14e51d3 100644 --- a/ruby/sample/openssl/cert2text.rb +++ b/ruby/sample/openssl/cert2text.rb @@ -1,10 +1,13 @@ #!/usr/bin/env ruby require 'openssl' -include OpenSSL::X509 def cert2text(cert_str) - [Certificate, CRL, Request].each do |klass| + [ + OpenSSL::X509::Certificate, + OpenSSL::X509::CRL, + OpenSSL::X509::Request, + ].each do |klass| begin puts klass.new(cert_str).to_text return diff --git a/ruby/sample/openssl/certstore.rb b/ruby/sample/openssl/certstore.rb index c6e8f816b..72e59f6da 100644 --- a/ruby/sample/openssl/certstore.rb +++ b/ruby/sample/openssl/certstore.rb @@ -3,9 +3,6 @@ class CertStore - include OpenSSL - include X509 - attr_reader :self_signed_ca attr_reader :other_ca attr_reader :ee @@ -17,11 +14,11 @@ def initialize(certs_dir) @c_store = CHashDir.new(@certs_dir) @c_store.hash_dir(true) @crl_store = CrlStore.new(@c_store) - @x509store = Store.new + @x509store = OpenSSL::X509::Store.new @self_signed_ca = @other_ca = @ee = @crl = nil # Uncomment this line to let OpenSSL to check CRL for each certs. - # @x509store.flags = V_FLAG_CRL_CHECK | V_FLAG_CRL_CHECK_ALL + # @x509store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK | OpenSSL::X509::V_FLAG_CRL_CHECK_ALL add_path scan_certs diff --git a/ruby/sample/openssl/echo_cli.rb b/ruby/sample/openssl/echo_cli.rb index 069a21ec9..3fbadf336 100644 --- a/ruby/sample/openssl/echo_cli.rb +++ b/ruby/sample/openssl/echo_cli.rb @@ -15,7 +15,7 @@ ctx = OpenSSL::SSL::SSLContext.new() if cert_file && key_file ctx.cert = OpenSSL::X509::Certificate.new(File::read(cert_file)) - ctx.key = OpenSSL::PKey::RSA.new(File::read(key_file)) + ctx.key = OpenSSL::PKey.read(File::read(key_file)) end if ca_path ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER diff --git a/ruby/sample/openssl/echo_svr.rb b/ruby/sample/openssl/echo_svr.rb index 719de6be8..f20fb52bf 100644 --- a/ruby/sample/openssl/echo_svr.rb +++ b/ruby/sample/openssl/echo_svr.rb @@ -13,9 +13,9 @@ if cert_file && key_file cert = OpenSSL::X509::Certificate.new(File::read(cert_file)) - key = OpenSSL::PKey::RSA.new(File::read(key_file)) + key = OpenSSL::PKey.read(File::read(key_file)) else - key = OpenSSL::PKey::RSA.new(512){ print "." } + key = OpenSSL::PKey::RSA.new(2048){ print "." } puts cert = OpenSSL::X509::Certificate.new cert.version = 2 @@ -25,7 +25,7 @@ cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + 3600 - cert.public_key = key.public_key + cert.public_key = key ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) cert.extensions = [ ef.create_extension("basicConstraints","CA:FALSE"), @@ -37,7 +37,7 @@ ef.issuer_certificate = cert cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") - cert.sign(key, OpenSSL::Digest::SHA1.new) + cert.sign(key, "SHA1") end ctx = OpenSSL::SSL::SSLContext.new() diff --git a/ruby/sample/openssl/gen_csr.rb b/ruby/sample/openssl/gen_csr.rb index 4228707fd..34b23fec1 100644 --- a/ruby/sample/openssl/gen_csr.rb +++ b/ruby/sample/openssl/gen_csr.rb @@ -3,8 +3,6 @@ require 'optparse' require 'openssl' -include OpenSSL - def usage myname = File::basename($0) $stderr.puts < y[0] -end[0..20].each do |title, items| - puts "Channel: #{title}" unless items.empty? - items.sort do |x, y| - x.title <=> y.title - end[0..10].each do |item| - puts " Item: #{item.title.shorten(50)}" - puts " Description: #{item.description.shorten(50)}" - end -end - -puts "Used XML parser: #{RSS::Parser.default_parser}" -puts "Processing time: #{processing_time}s" diff --git a/ruby/sample/rss/re_read.rb b/ruby/sample/rss/re_read.rb deleted file mode 100755 index c386ab20f..000000000 --- a/ruby/sample/rss/re_read.rb +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env ruby - -require "rss" - -def error(exception) - mark = "=" * 20 - mark = "#{mark} error #{mark}" - puts mark - puts exception.class - puts exception.message - puts exception.backtrace - puts mark -end - -verbose = false -before_time = Time.now - -ARGV.each do |fname| - if fname == '-v' - verbose = true - next - end - source = nil - File.open(fname) do |f| - source = f.read - end - - rss = nil - read = false - begin - rss = RSS::Parser.parse(source) - puts "Re-read valid feed: #{fname}" - RSS::Parser.parse(rss.to_s) - read = true - rescue RSS::InvalidRSSError - error($!) if verbose - ## do non validate parse for invalid feed - begin - rss = RSS::Parser.parse(source, false) - rescue RSS::Error - ## invalid feed - error($!) if verbose - end - rescue RSS::Error - error($!) if verbose - end - - if rss.nil? - puts "Invalid feed: #{fname}" - elsif !read - puts "Re-read invalid feed: #{fname}" - begin - RSS::Parser.parse(rss.to_s) - rescue RSS::Error - puts " Error occurred: #{fname}" - error($!) if verbose - end - end -end - -processing_time = Time.now - before_time - -puts "Used XML parser: #{RSS::Parser.default_parser}" -puts "Processing time: #{processing_time}s" diff --git a/ruby/sample/rss/rss_recent.rb b/ruby/sample/rss/rss_recent.rb deleted file mode 100755 index 14c861284..000000000 --- a/ruby/sample/rss/rss_recent.rb +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env ruby - -require "nkf" -class String - # From tdiary.rb - def shorten( len = 120 ) - lines = NKF::nkf( "-t -m0 -f#{len}", self.gsub( /\n/, ' ' ) ).split( /\n/ ) - lines[0].concat( '...' ) if lines[0] and lines[1] - lines[0] - end -end - -require "rss" - -items = [] -verbose = false - -def error(exception) - mark = "=" * 20 - mark = "#{mark} error #{mark}" - puts mark - puts exception.class - puts exception.message - puts exception.backtrace - puts mark -end -before_time = Time.now -ARGV.each do |fname| - if fname == '-v' - verbose = true - next - end - rss = nil - f = File.new(fname).read - begin - ## do validate parse - rss = RSS::Parser.parse(f) - rescue RSS::InvalidRSSError - error($!) if verbose - ## do non validate parse for invalid RSS 1.0 - begin - rss = RSS::Parser.parse(f, false) - rescue RSS::Error - ## invalid RSS. - error($!) if verbose - end - rescue RSS::Error - error($!) if verbose - end - if rss.nil? - puts "#{fname} does not include RSS 1.0 or 0.9x/2.0" - else - begin - rss.output_encoding = "utf-8" - rescue RSS::UnknownConversionMethodError - error($!) if verbose - end - - rss = rss.to_rss("1.0") do |maker| - maker.channel.about ||= maker.channel.link - maker.channel.description ||= "No description" - maker.items.each do |item| - item.title ||= "UNKNOWN" - item.link ||= "UNKNOWN" - end - end - next if rss.nil? - - rss.items.each do |item| - items << [rss.channel, item] if item.dc_date - end - end -end -processing_time = Time.now - before_time - -items.sort do |x, y| - y[1].dc_date <=> x[1].dc_date -end[0..20].each do |channel, item| - puts "#{item.dc_date.localtime.iso8601}: " << - "#{channel.title}: #{item.title}" - puts " Description: #{item.description.shorten(50)}" if item.description -end - -puts "Used XML parser: #{RSS::Parser.default_parser}" -puts "Processing time: #{processing_time}s" diff --git a/ruby/sample/testunit/adder.rb b/ruby/sample/testunit/adder.rb deleted file mode 100644 index aa5c88cc7..000000000 --- a/ruby/sample/testunit/adder.rb +++ /dev/null @@ -1,13 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -class Adder - def initialize(number) - @number = number - end - def add(number) - return @number + number - end -end - diff --git a/ruby/sample/testunit/subtracter.rb b/ruby/sample/testunit/subtracter.rb deleted file mode 100644 index 2c0824780..000000000 --- a/ruby/sample/testunit/subtracter.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -class Subtracter - def initialize(number) - @number = number - end - def subtract(number) - return @number - number - end -end diff --git a/ruby/sample/testunit/tc_adder.rb b/ruby/sample/testunit/tc_adder.rb deleted file mode 100644 index 8453beb20..000000000 --- a/ruby/sample/testunit/tc_adder.rb +++ /dev/null @@ -1,18 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require 'adder' - -class TC_Adder < Test::Unit::TestCase - def setup - @adder = Adder.new(5) - end - def test_add - assert_equal(7, @adder.add(2), "Should have added correctly") - end - def teardown - @adder = nil - end -end diff --git a/ruby/sample/testunit/tc_subtracter.rb b/ruby/sample/testunit/tc_subtracter.rb deleted file mode 100644 index d2c831335..000000000 --- a/ruby/sample/testunit/tc_subtracter.rb +++ /dev/null @@ -1,18 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require 'subtracter' - -class TC_Subtracter < Test::Unit::TestCase - def setup - @subtracter = Subtracter.new(5) - end - def test_subtract - assert_equal(3, @subtracter.subtract(2), "Should have subtracted correctly") - end - def teardown - @subtracter = nil - end -end diff --git a/ruby/sample/testunit/ts_examples.rb b/ruby/sample/testunit/ts_examples.rb deleted file mode 100644 index 3d24dd652..000000000 --- a/ruby/sample/testunit/ts_examples.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Author:: Nathaniel Talbott. -# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. -# License:: Ruby license. - -require 'test/unit' -require 'tc_adder' -require 'tc_subtracter' diff --git a/ruby/sample/trick2013/mame/remarks.markdown b/ruby/sample/trick2013/mame/remarks.markdown index 8c1988c80..488681d88 100644 --- a/ruby/sample/trick2013/mame/remarks.markdown +++ b/ruby/sample/trick2013/mame/remarks.markdown @@ -27,7 +27,7 @@ In the piano roll, `#` represents a pin that hits a note, and `|` represents a s The leftmost column corresponds 110Hz (low A). Every column corresponds a semitone higher than the left one. -This program uses [the frequency modulation synthesis](http://en.wikipedia.org/wiki/Frequency_modulation_synthesis) to play the sound like a music-box. +This program uses [the frequency modulation synthesis](https://en.wikipedia.org/wiki/Frequency_modulation_synthesis) to play the sound like a music-box. You can create a different-sounding tone by changing the parameter. For example, the following will play the sound like a harpsichord. @@ -44,4 +44,4 @@ You have to use sox by replacing the following part: with: - IO.popen("./pl","wb") \ No newline at end of file + IO.popen("./pl","wb") diff --git a/ruby/sample/trick2015/kinaba/entry.rb b/ruby/sample/trick2015/kinaba/entry.rb index 18923a6a9..aa077dc24 100644 --- a/ruby/sample/trick2015/kinaba/entry.rb +++ b/ruby/sample/trick2015/kinaba/entry.rb @@ -62,7 +62,7 @@ def increment TrueClass Dir Encoding - Data + Proc Hash Method Enumerator diff --git a/ruby/sample/trick2018/01-kinaba/remarks.markdown b/ruby/sample/trick2018/01-kinaba/remarks.markdown index a1a05bfd7..d0b9fdffd 100644 --- a/ruby/sample/trick2018/01-kinaba/remarks.markdown +++ b/ruby/sample/trick2018/01-kinaba/remarks.markdown @@ -34,7 +34,7 @@ Difficult (and interesting) points of the theme are: Or, jump-out statements cannot occur at a position that requires a value; `if return then true end` is a "void value expression" syntax error. * Inserting newlines for each 6 word (to match with the spec html) is also - an interseting challenge, since Ruby is sensitive to newlines. + an interesting challenge, since Ruby is sensitive to newlines. Tricks used in the code are: diff --git a/ruby/sample/webrick/demo-app.rb b/ruby/sample/webrick/demo-app.rb deleted file mode 100644 index c7a2a0a6a..000000000 --- a/ruby/sample/webrick/demo-app.rb +++ /dev/null @@ -1,66 +0,0 @@ -require "pp" - -module DemoApplication - def initialize(config, enctype) - super - @enctype = enctype - end - - def do_GET(req, res) - if req.path_info != "/" - res.set_redirect(WEBrick::HTTPStatus::Found, req.script_name + "/") - end - res.body =<<-_end_of_html_ - -
- text:
- file:
- check: - a, - b, - c, -
- -
- - _end_of_html_ - res['content-type'] = 'text/html; charset=iso-8859-1' - end - - def do_POST(req, res) - if req["content-length"].to_i > 1024*10 - raise WEBrick::HTTPStatus::Forbidden, "file size too large" - end - res.body =<<-_end_of_html_ - -

Query Parameters

- #{display_query(req.query)} -
return -

Request

-
#{WEBrick::HTMLUtils::escape(PP::pp(req, "", 80))}
-

Response

-
#{WEBrick::HTMLUtils::escape(PP::pp(res, "", 80))}
- - _end_of_html_ - res['content-type'] = 'text/html; charset=iso-8859-1' - end - - private - - def display_query(q) - ret = "" - q.each{|key, val| - ret << "

#{WEBrick::HTMLUtils::escape(key)}

" - ret << "" - ret << make_tr("val", val.inspect) - ret << make_tr("val.to_a", val.to_a.inspect) - ret << make_tr("val.to_ary", val.to_ary.inspect) - ret << "
" - } - ret - end - - def make_tr(arg0, arg1) - "#{arg0}#{WEBrick::HTMLUtils::escape(arg1)}" - end -end diff --git a/ruby/sample/webrick/demo-multipart.cgi b/ruby/sample/webrick/demo-multipart.cgi deleted file mode 100644 index 0893fadad..000000000 --- a/ruby/sample/webrick/demo-multipart.cgi +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby -require "webrick/cgi" -require "webrick/https" # should load if it runs on HTTPS server -require "./demo-app" - -class DemoCGI < WEBrick::CGI - include DemoApplication -end - -config = { :NPH => false } -cgi = DemoCGI.new(config, "multipart/form-data") -cgi.start diff --git a/ruby/sample/webrick/demo-servlet.rb b/ruby/sample/webrick/demo-servlet.rb deleted file mode 100644 index 9c18cc65d..000000000 --- a/ruby/sample/webrick/demo-servlet.rb +++ /dev/null @@ -1,6 +0,0 @@ -require "webrick" -require "./demo-app" - -class DemoServlet < WEBrick::HTTPServlet::AbstractServlet - include DemoApplication -end diff --git a/ruby/sample/webrick/demo-urlencoded.cgi b/ruby/sample/webrick/demo-urlencoded.cgi deleted file mode 100644 index e4706f8b5..000000000 --- a/ruby/sample/webrick/demo-urlencoded.cgi +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby -require "webrick/cgi" -require "webrick/https" # should load if it runs on HTTPS server -require "./demo-app" - -class DemoCGI < WEBrick::CGI - include DemoApplication -end - -config = { :NPH => false } -cgi = DemoCGI.new(config, "application/x-www-form-urlencoded") -cgi.start diff --git a/ruby/sample/webrick/hello.cgi b/ruby/sample/webrick/hello.cgi deleted file mode 100644 index 35d2240df..000000000 --- a/ruby/sample/webrick/hello.cgi +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env ruby -require "webrick/cgi" - -class HelloCGI < WEBrick::CGI - def do_GET(req, res) - res["content-type"] = "text/plain" - res.body = "Hello, world.\n" - end -end - -HelloCGI.new.start diff --git a/ruby/sample/webrick/hello.rb b/ruby/sample/webrick/hello.rb deleted file mode 100644 index 4d0267681..000000000 --- a/ruby/sample/webrick/hello.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "webrick" - -class HelloServlet < WEBrick::HTTPServlet::AbstractServlet - def do_GET(req, res) - res["content-type"] = "text/plain" - res.body = "Hello, world.\n" - end -end diff --git a/ruby/sample/webrick/httpd.rb b/ruby/sample/webrick/httpd.rb deleted file mode 100644 index b0edf4758..000000000 --- a/ruby/sample/webrick/httpd.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "webrick" - -httpd = WEBrick::HTTPServer.new( - :DocumentRoot => File::dirname(__FILE__), - :Port => 10080, - :Logger => WEBrick::Log.new($stderr, WEBrick::Log::DEBUG), - :AccessLog => [ - [ $stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT ], - [ $stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT ], - [ $stderr, WEBrick::AccessLog::AGENT_LOG_FORMAT ], - ], - :CGIPathEnv => ENV["PATH"] # PATH environment variable for CGI. -) - -require "./hello" -httpd.mount("/hello", HelloServlet) - -require "./demo-servlet" -httpd.mount("/urlencoded", DemoServlet, "application/x-www-form-urlencoded") -httpd.mount("/multipart", DemoServlet, "multipart/form-data") - -trap(:INT){ httpd.shutdown } -httpd.start diff --git a/ruby/sample/webrick/httpproxy.rb b/ruby/sample/webrick/httpproxy.rb deleted file mode 100644 index c84457ece..000000000 --- a/ruby/sample/webrick/httpproxy.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "webrick" -require "webrick/httpproxy" - -# The :ProxyContentHandler proc will be invoked before sending a response to -# the User-Agent. You can inspect the pair of request and response messages -# (or edit the response message if necessary). - -pch = Proc.new{|req, res| - p [ req.request_line, res.status_line ] -} - -def upstream_proxy - if prx = ENV["http_proxy"] - return URI.parse(prx) - end - return nil -end - -httpd = WEBrick::HTTPProxyServer.new( - :Port => 10080, - :ProxyContentHandler => pch, - :ProxyURI => upstream_proxy -) -Signal.trap(:INT){ httpd.shutdown } -httpd.start diff --git a/ruby/sample/webrick/httpsd.rb b/ruby/sample/webrick/httpsd.rb deleted file mode 100644 index a120782c3..000000000 --- a/ruby/sample/webrick/httpsd.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "webrick" -require "webrick/https" - -hostname = WEBrick::Utils::getservername -subject = [["O", "ruby-lang.org"], ["OU", "sample"], ["CN", hostname]] -comment = "Comment for self-signed certificate" - -httpd = WEBrick::HTTPServer.new( - :DocumentRoot => File::dirname(__FILE__), - :Port => 10443, - :SSLEnable => true, - - # Specify key pair and server certificate. - # :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read("server.key")), - # :SSLCertificate => OpenSSL::X509::Certificate.new(File.read("server.crt")), - - # specify the following SSL options if you want to use auto - # generated self-signed certificate. - :SSLCertName => subject, - :SSLComment => comment, - - :CGIPathEnv => ENV["PATH"] # PATH environment variable for CGI. -) - -require "./hello" -httpd.mount("/hello", HelloServlet) - -require "./demo-servlet" -httpd.mount("/urlencoded", DemoServlet, "application/x-www-form-urlencoded") -httpd.mount("/multipart", DemoServlet, "multipart/form-data") - -trap(:INT){ httpd.shutdown } -httpd.start diff --git a/ruby/scheduler.c b/ruby/scheduler.c new file mode 100644 index 000000000..06658356b --- /dev/null +++ b/ruby/scheduler.c @@ -0,0 +1,316 @@ +/********************************************************************** + + scheduler.c + + $Author$ + + Copyright (C) 2020 Samuel Grant Dawson Williams + +**********************************************************************/ + +#include "vm_core.h" +#include "ruby/fiber/scheduler.h" +#include "ruby/io.h" +#include "ruby/io/buffer.h" + +#include "internal/thread.h" + +static ID id_close; +static ID id_scheduler_close; + +static ID id_block; +static ID id_unblock; + +static ID id_timeout_after; +static ID id_kernel_sleep; +static ID id_process_wait; + +static ID id_io_read, id_io_pread; +static ID id_io_write, id_io_pwrite; +static ID id_io_wait; +static ID id_io_close; + +static ID id_address_resolve; + +void +Init_Fiber_Scheduler(void) +{ + id_close = rb_intern_const("close"); + id_scheduler_close = rb_intern_const("scheduler_close"); + + id_block = rb_intern_const("block"); + id_unblock = rb_intern_const("unblock"); + + id_timeout_after = rb_intern_const("timeout_after"); + id_kernel_sleep = rb_intern_const("kernel_sleep"); + id_process_wait = rb_intern_const("process_wait"); + + id_io_read = rb_intern_const("io_read"); + id_io_pread = rb_intern_const("io_pread"); + id_io_write = rb_intern_const("io_write"); + id_io_pwrite = rb_intern_const("io_pwrite"); + + id_io_wait = rb_intern_const("io_wait"); + id_io_close = rb_intern_const("io_close"); + + id_address_resolve = rb_intern_const("address_resolve"); +} + +VALUE +rb_fiber_scheduler_get(void) +{ + VM_ASSERT(ruby_thread_has_gvl_p()); + + rb_thread_t *thread = GET_THREAD(); + VM_ASSERT(thread); + + return thread->scheduler; +} + +static void +verify_interface(VALUE scheduler) +{ + if (!rb_respond_to(scheduler, id_block)) { + rb_raise(rb_eArgError, "Scheduler must implement #block"); + } + + if (!rb_respond_to(scheduler, id_unblock)) { + rb_raise(rb_eArgError, "Scheduler must implement #unblock"); + } + + if (!rb_respond_to(scheduler, id_kernel_sleep)) { + rb_raise(rb_eArgError, "Scheduler must implement #kernel_sleep"); + } + + if (!rb_respond_to(scheduler, id_io_wait)) { + rb_raise(rb_eArgError, "Scheduler must implement #io_wait"); + } +} + +VALUE +rb_fiber_scheduler_set(VALUE scheduler) +{ + VM_ASSERT(ruby_thread_has_gvl_p()); + + rb_thread_t *thread = GET_THREAD(); + VM_ASSERT(thread); + + if (scheduler != Qnil) { + verify_interface(scheduler); + } + + // We invoke Scheduler#close when setting it to something else, to ensure the previous scheduler runs to completion before changing the scheduler. That way, we do not need to consider interactions, e.g., of a Fiber from the previous scheduler with the new scheduler. + if (thread->scheduler != Qnil) { + rb_fiber_scheduler_close(thread->scheduler); + } + + thread->scheduler = scheduler; + + return thread->scheduler; +} + +static VALUE +rb_fiber_scheduler_current_for_threadptr(rb_thread_t *thread) +{ + VM_ASSERT(thread); + + if (thread->blocking == 0) { + return thread->scheduler; + } + else { + return Qnil; + } +} + +VALUE +rb_fiber_scheduler_current(void) +{ + return rb_fiber_scheduler_current_for_threadptr(GET_THREAD()); +} + +VALUE rb_fiber_scheduler_current_for_thread(VALUE thread) +{ + return rb_fiber_scheduler_current_for_threadptr(rb_thread_ptr(thread)); +} + +VALUE +rb_fiber_scheduler_close(VALUE scheduler) +{ + VM_ASSERT(ruby_thread_has_gvl_p()); + + VALUE result; + + result = rb_check_funcall(scheduler, id_scheduler_close, 0, NULL); + if (result != Qundef) return result; + + result = rb_check_funcall(scheduler, id_close, 0, NULL); + if (result != Qundef) return result; + + return Qnil; +} + +VALUE +rb_fiber_scheduler_make_timeout(struct timeval *timeout) +{ + if (timeout) { + return rb_float_new((double)timeout->tv_sec + (0.000001f * timeout->tv_usec)); + } + + return Qnil; +} + +VALUE +rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE timeout) +{ + return rb_funcall(scheduler, id_kernel_sleep, 1, timeout); +} + +VALUE +rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv) +{ + return rb_funcallv(scheduler, id_kernel_sleep, argc, argv); +} + +#if 0 +VALUE +rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message) +{ + VALUE arguments[] = { + timeout, exception, message + }; + + return rb_check_funcall(scheduler, id_timeout_after, 3, arguments); +} + +VALUE +rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv) +{ + return rb_check_funcall(scheduler, id_timeout_after, argc, argv); +} +#endif + +VALUE +rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags) +{ + VALUE arguments[] = { + PIDT2NUM(pid), RB_INT2NUM(flags) + }; + + return rb_check_funcall(scheduler, id_process_wait, 2, arguments); +} + +VALUE +rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout) +{ + return rb_funcall(scheduler, id_block, 2, blocker, timeout); +} + +VALUE +rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber) +{ + VM_ASSERT(rb_obj_is_fiber(fiber)); + + return rb_funcall(scheduler, id_unblock, 2, blocker, fiber); +} + +VALUE +rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout) +{ + return rb_funcall(scheduler, id_io_wait, 3, io, events, timeout); +} + +VALUE +rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io) +{ + return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_READABLE), Qnil); +} + +VALUE +rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io) +{ + return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), Qnil); +} + +VALUE +rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length) +{ + VALUE arguments[] = { + io, buffer, SIZET2NUM(length) + }; + + return rb_check_funcall(scheduler, id_io_read, 3, arguments); +} + +VALUE +rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset) +{ + VALUE arguments[] = { + io, buffer, SIZET2NUM(length), OFFT2NUM(offset) + }; + + return rb_check_funcall(scheduler, id_io_pread, 4, arguments); +} + +VALUE +rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length) +{ + VALUE arguments[] = { + io, buffer, SIZET2NUM(length) + }; + + return rb_check_funcall(scheduler, id_io_write, 3, arguments); +} + +VALUE +rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset) +{ + VALUE arguments[] = { + io, buffer, SIZET2NUM(length), OFFT2NUM(offset) + }; + + return rb_check_funcall(scheduler, id_io_pwrite, 4, arguments); +} + +VALUE +rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length) +{ + VALUE buffer = rb_io_buffer_new(base, size, RB_IO_BUFFER_LOCKED); + + VALUE result = rb_fiber_scheduler_io_read(scheduler, io, buffer, length); + + rb_io_buffer_unlock(buffer); + rb_io_buffer_free(buffer); + + return result; +} + +VALUE +rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length) +{ + VALUE buffer = rb_io_buffer_new((void*)base, size, RB_IO_BUFFER_LOCKED|RB_IO_BUFFER_READONLY); + + VALUE result = rb_fiber_scheduler_io_write(scheduler, io, buffer, length); + + rb_io_buffer_unlock(buffer); + rb_io_buffer_free(buffer); + + return result; +} + +VALUE +rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io) +{ + VALUE arguments[] = {io}; + + return rb_check_funcall(scheduler, id_io_close, 1, arguments); +} + +VALUE +rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname) +{ + VALUE arguments[] = { + hostname + }; + + return rb_check_funcall(scheduler, id_address_resolve, 1, arguments); +} diff --git a/ruby/signal.c b/ruby/signal.c index 68d68c54b..4ca52b2ee 100644 --- a/ruby/signal.c +++ b/ruby/signal.c @@ -11,36 +11,40 @@ **********************************************************************/ -#include "internal.h" -#include "vm_core.h" +#include "ruby/internal/config.h" + +#include #include #include -#include -#include "ruby_atomic.h" -#include "eval_intern.h" + #ifdef HAVE_UNISTD_H # include #endif + #ifdef HAVE_SYS_UIO_H -#include +# include #endif + #ifdef HAVE_UCONTEXT_H -#include +# include #endif -#ifdef HAVE_VALGRIND_MEMCHECK_H -# include -# ifndef VALGRIND_MAKE_MEM_DEFINED -# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n)) -# endif -# ifndef VALGRIND_MAKE_MEM_UNDEFINED -# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n)) -# endif -#else -# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0 -# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 +#ifdef HAVE_PTHREAD_H +# include #endif +#include "debug_counter.h" +#include "eval_intern.h" +#include "internal.h" +#include "internal/eval.h" +#include "internal/sanitizers.h" +#include "internal/signal.h" +#include "internal/string.h" +#include "internal/thread.h" +#include "ruby_atomic.h" +#include "vm_core.h" +#include "ractor_core.h" + #ifdef NEED_RUBY_ATOMIC_OPS rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val) @@ -240,23 +244,7 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr) prefix += signame_prefix_len; } if (len <= (long)prefix) { - unsupported: - if (prefix == signame_prefix_len) { - prefix = 0; - } - else if (prefix > signame_prefix_len) { - prefix -= signame_prefix_len; - len -= prefix; - vsig = rb_str_subseq(vsig, prefix, len); - prefix = 0; - } - else { - len -= prefix; - vsig = rb_str_subseq(vsig, prefix, len); - prefix = signame_prefix_len; - } - rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'", - prefix, signame_prefix, vsig); + goto unsupported; } if (prefix_ptr) *prefix_ptr = prefix; @@ -269,7 +257,25 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr) return negative ? -sigs->signo : sigs->signo; } } - goto unsupported; + + unsupported: + if (prefix == signame_prefix_len) { + prefix = 0; + } + else if (prefix > signame_prefix_len) { + prefix -= signame_prefix_len; + len -= prefix; + vsig = rb_str_subseq(vsig, prefix, len); + prefix = 0; + } + else { + len -= prefix; + vsig = rb_str_subseq(vsig, prefix, len); + prefix = signame_prefix_len; + } + rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'", + prefix, signame_prefix, vsig); + UNREACHABLE_RETURN(0); } static const char* @@ -395,7 +401,6 @@ interrupt_init(int argc, VALUE *argv, VALUE self) return rb_call_super(2, args); } -#include "debug_counter.h" void rb_malloc_info_show_results(void); /* gc.c */ void @@ -410,7 +415,7 @@ ruby_default_signal(int sig) raise(sig); } -static RETSIGTYPE sighandler(int sig); +static void sighandler(int sig); static int signal_ignored(int sig); static void signal_enque(int sig); @@ -444,7 +449,7 @@ rb_f_kill(int argc, const VALUE *argv) } } else { - const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1; + const rb_pid_t self = (GET_THREAD() == GET_VM()->ractor.main_thread) ? getpid() : -1; int wakeup = 0; for (i=1; imain_thread); + rb_threadptr_check_signal(GET_VM()->ractor.main_thread); } } rb_thread_execute_interrupts(rb_thread_current()); @@ -514,17 +519,19 @@ typedef void ruby_sigaction_t(int, siginfo_t*, void*); #define SIGINFO_ARG , siginfo_t *info, void *ctx #define SIGINFO_CTX ctx #else -typedef RETSIGTYPE ruby_sigaction_t(int); +typedef void ruby_sigaction_t(int); #define SIGINFO_ARG #define SIGINFO_CTX 0 #endif #ifdef USE_SIGALTSTACK +/* XXX: BSD_vfprintf() uses >1500B stack and x86-64 need >5KiB stack. */ +#define RUBY_SIGALTSTACK_SIZE (16*1024) + static int rb_sigaltstack_size(void) { - /* XXX: BSD_vfprintf() uses >1500KiB stack and x86-64 need >5KiB stack. */ - int size = 16*1024; + int size = RUBY_SIGALTSTACK_SIZE; #ifdef MINSIGSTKSZ { @@ -545,14 +552,28 @@ rb_sigaltstack_size(void) return size; } +static int rb_sigaltstack_size_value = 0; + +void * +rb_allocate_sigaltstack(void) +{ + void *altstack; + if (!rb_sigaltstack_size_value) { + rb_sigaltstack_size_value = rb_sigaltstack_size(); + } + altstack = malloc(rb_sigaltstack_size_value); + if (!altstack) rb_memerror(); + return altstack; +} + /* alternate stack for SIGSEGV */ void * -rb_register_sigaltstack(void) +rb_register_sigaltstack(void *altstack) { stack_t newSS, oldSS; - newSS.ss_size = rb_sigaltstack_size(); - newSS.ss_sp = xmalloc(newSS.ss_size); + newSS.ss_size = rb_sigaltstack_size_value; + newSS.ss_sp = altstack; newSS.ss_flags = 0; sigaltstack(&newSS, &oldSS); /* ignore error. */ @@ -694,7 +715,7 @@ static rb_atomic_t sigchld_hit; # define GET_SIGCHLD_HIT() 0 #endif -static RETSIGTYPE +static void sighandler(int sig) { int old_errnum = errno; @@ -705,7 +726,7 @@ sighandler(int sig) rb_vm_t *vm = GET_VM(); ATOMIC_EXCHANGE(sigchld_hit, 1); - /* avoid spurious wakeup in main thread iff nobody uses trap(:CHLD) */ + /* avoid spurious wakeup in main thread if and only if nobody uses trap(:CHLD) */ if (vm && ACCESS_ONCE(VALUE, vm->trap_list.cmd[sig])) { signal_enque(sig); } @@ -728,10 +749,6 @@ rb_signal_buff_size(void) return signal_buff.size; } -#if HAVE_PTHREAD_H -#include -#endif - static void rb_disable_interrupt(void) { @@ -864,12 +881,13 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx) (sp_page <= fault_page && fault_page <= bp_page)) { rb_execution_context_t *ec = GET_EC(); int crit = FALSE; - if ((uintptr_t)ec->tag->buf / pagesize <= fault_page + 1) { + int uplevel = roomof(pagesize, sizeof(*ec->tag)) / 2; /* XXX: heuristic */ + while ((uintptr_t)ec->tag->buf / pagesize <= fault_page + 1) { /* drop the last tag if it is close to the fault, * otherwise it can cause stack overflow again at the same * place. */ + if ((crit = (!ec->tag->prev || !--uplevel)) != FALSE) break; ec->tag = ec->tag->prev; - crit = TRUE; } reset_sigmask(sig); rb_ec_stack_overflow(ec, crit); @@ -916,7 +934,7 @@ NOINLINE(static void check_reserved_signal_(const char *name, size_t name_len)); static sighandler_t default_sigbus_handler; NORETURN(static ruby_sigaction_t sigbus); -static RETSIGTYPE +static void sigbus(int sig SIGINFO_ARG) { check_reserved_signal("BUS"); @@ -938,7 +956,7 @@ sigbus(int sig SIGINFO_ARG) static sighandler_t default_sigsegv_handler; NORETURN(static ruby_sigaction_t sigsegv); -static RETSIGTYPE +static void sigsegv(int sig SIGINFO_ARG) { check_reserved_signal("SEGV"); @@ -952,11 +970,11 @@ sigsegv(int sig SIGINFO_ARG) static sighandler_t default_sigill_handler; NORETURN(static ruby_sigaction_t sigill); -static RETSIGTYPE +static void sigill(int sig SIGINFO_ARG) { check_reserved_signal("ILL"); -#if defined __APPLE__ +#if defined __APPLE__ || defined __linux__ CHECK_STACK_OVERFLOW(); #endif rb_bug_for_fatal_signal(default_sigill_handler, sig, SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS); @@ -1017,7 +1035,7 @@ check_reserved_signal_(const char *name, size_t name_len) #endif #if defined SIGPIPE || defined SIGSYS -static RETSIGTYPE +static void sig_do_nothing(int sig) { } @@ -1199,6 +1217,14 @@ trap_handler(VALUE *cmd, int sig) *cmd = command; RSTRING_GETMEM(command, cptr, len); switch (len) { + sig_ign: + func = SIG_IGN; + *cmd = Qtrue; + break; + sig_dfl: + func = default_handler(sig); + *cmd = 0; + break; case 0: goto sig_ign; break; @@ -1213,14 +1239,10 @@ trap_handler(VALUE *cmd, int sig) break; case 7: if (memcmp(cptr, "SIG_IGN", 7) == 0) { -sig_ign: - func = SIG_IGN; - *cmd = Qtrue; + goto sig_ign; } else if (memcmp(cptr, "SIG_DFL", 7) == 0) { -sig_dfl: - func = default_handler(sig); - *cmd = 0; + goto sig_dfl; } else if (memcmp(cptr, "DEFAULT", 7) == 0) { goto sig_dfl; @@ -1393,6 +1415,11 @@ sig_trap(int argc, VALUE *argv, VALUE _) func = trap_handler(&cmd, sig); } + if (rb_obj_is_proc(cmd) && + !rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) { + cmd = rb_proc_isolate(cmd); + } + return trap(sig, func, cmd); } @@ -1563,7 +1590,7 @@ Init_signal(void) force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler); #endif #ifdef SIGSEGV - RB_ALTSTACK_INIT(GET_VM()->main_altstack); + RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack()); force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler); #endif } diff --git a/ruby/siphash.c b/ruby/siphash.c index 153d2c690..091376747 100644 --- a/ruby/siphash.c +++ b/ruby/siphash.c @@ -5,11 +5,18 @@ #define SIP_HASH_STREAMING 1 #endif -#ifdef _WIN32 +#if defined(__MINGW32__) + #include + + /* MinGW only defines LITTLE_ENDIAN and BIG_ENDIAN macros */ + #define __LITTLE_ENDIAN LITTLE_ENDIAN + #define __BIG_ENDIAN BIG_ENDIAN +#elif defined(_WIN32) #define BYTE_ORDER __LITTLE_ENDIAN -#elif !defined BYTE_ORDER +#elif !defined(BYTE_ORDER) #include #endif + #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN __LITTLE_ENDIAN #endif @@ -30,7 +37,7 @@ #ifndef UNALIGNED_WORD_ACCESS # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(__powerpc64__) || \ + defined(__powerpc64__) || defined(__aarch64__) || \ defined(__mc68020__) # define UNALIGNED_WORD_ACCESS 1 # endif @@ -180,7 +187,7 @@ int_sip_dump(sip_state *state) int v; for (v = 0; v < 4; v++) { -#if HAVE_UINT64_T +#ifdef HAVE_UINT64_T printf("v%d: %" PRIx64 "\n", v, state->v[v]); #else printf("v%d: %" PRIx32 "%.8" PRIx32 "\n", v, state->v[v].hi, state->v[v].lo); @@ -447,7 +454,7 @@ sip_hash13(const uint8_t key[16], const uint8_t *data, size_t len) OR_BYTE(4); case 4: #if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS - #if HAVE_UINT64_T + #ifdef HAVE_UINT64_T last |= (uint64_t) ((uint32_t *) end)[0]; #else last.lo |= ((uint32_t *) end)[0]; diff --git a/ruby/spec/README.md b/ruby/spec/README.md index 1b2e4d5f5..c67aedbb8 100644 --- a/ruby/spec/README.md +++ b/ruby/spec/README.md @@ -66,7 +66,7 @@ See `spec/ruby/CONTRIBUTING.md` for more documentation about guards. To verify specs are compatible with older Ruby versions: ``` cd spec/ruby -$RUBY_MANAGER use 2.4.6 +$RUBY_MANAGER use 2.4.9 ../mspec/bin/mspec -j ``` diff --git a/ruby/spec/bundler/bundler/bundler_spec.rb b/ruby/spec/bundler/bundler/bundler_spec.rb index 247838600..aeadcf972 100644 --- a/ruby/spec/bundler/bundler/bundler_spec.rb +++ b/ruby/spec/bundler/bundler/bundler_spec.rb @@ -21,30 +21,6 @@ it "catches YAML syntax errors" do expect { subject }.to raise_error(Bundler::GemspecError, /error while loading `test.gemspec`/) end - - context "on Rubies with a settable YAML engine", :if => defined?(YAML::ENGINE) do - context "with Syck as YAML::Engine" do - it "raises a GemspecError after YAML load throws ArgumentError" do - orig_yamler = YAML::ENGINE.yamler - YAML::ENGINE.yamler = "syck" - - expect { subject }.to raise_error(Bundler::GemspecError) - - YAML::ENGINE.yamler = orig_yamler - end - end - - context "with Psych as YAML::Engine" do - it "raises a GemspecError after YAML load throws Psych::SyntaxError" do - orig_yamler = YAML::ENGINE.yamler - YAML::ENGINE.yamler = "psych" - - expect { subject }.to raise_error(Bundler::GemspecError) - - YAML::ENGINE.yamler = orig_yamler - end - end - end end context "with correct YAML file", :if => defined?(Encoding) do @@ -124,7 +100,15 @@ describe "#which" do let(:executable) { "executable" } - let(:path) { %w[/a /b c ../d /e] } + + let(:path) do + if Gem.win_platform? + %w[C:/a C:/b C:/c C:/../d C:/e] + else + %w[/a /b c ../d /e] + end + end + let(:expected) { "executable" } before do @@ -149,7 +133,13 @@ it_behaves_like "it returns the correct executable" context "when the executable in inside a quoted path" do - let(:expected) { "/e/executable" } + let(:expected) do + if Gem.win_platform? + "C:/e/executable" + else + "/e/executable" + end + end it_behaves_like "it returns the correct executable" end @@ -162,11 +152,9 @@ describe "configuration" do context "disable_shared_gems" do it "should unset GEM_PATH with empty string" do - env = {} expect(Bundler).to receive(:use_system_gems?).and_return(false) - Bundler.send(:configure_gem_path, env) - expect(env.keys).to include("GEM_PATH") - expect(env["GEM_PATH"]).to eq "" + Bundler.send(:configure_gem_path) + expect(ENV["GEM_PATH"]).to eq "" end end end @@ -196,6 +184,8 @@ gem "rack" G + allow(Bundler).to receive(:root).and_return(bundled_app) + Bundler.mkdir_p(bundled_app.join("foo", "bar")) expect(bundled_app.join("foo", "bar")).to exist end @@ -233,11 +223,8 @@ allow(Bundler.rubygems).to receive(:user_home).and_return(path) allow(File).to receive(:directory?).with(path).and_return false allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom")) - message = < false + expect(exitstatus).to_not be_zero end it "returns non-zero exit status when passed unrecognized task" do - bundle "unrecognized-task" - expect(exitstatus).to_not be_zero if exitstatus + bundle "unrecognized-task", :raise_on_error => false + expect(exitstatus).to_not be_zero end it "looks for a binary and executes it if it's named bundler-" do + skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform? + File.open(tmp("bundler-testtasks"), "w", 0o755) do |f| ruby = ENV["RUBY"] || "/usr/bin/env ruby" f.puts "#!#{ruby}\nputs 'Hello, world'\n" @@ -23,7 +25,6 @@ bundle "testtasks" end - expect(exitstatus).to be_zero if exitstatus expect(out).to eq("Hello, world") end @@ -31,55 +32,63 @@ it "aliases e to exec" do bundle "e --help" - expect(out).to include("BUNDLE-EXEC") + expect(out_with_macos_man_workaround).to include("bundle-exec") end it "aliases ex to exec" do bundle "ex --help" - expect(out).to include("BUNDLE-EXEC") + expect(out_with_macos_man_workaround).to include("bundle-exec") end it "aliases exe to exec" do bundle "exe --help" - expect(out).to include("BUNDLE-EXEC") + expect(out_with_macos_man_workaround).to include("bundle-exec") end it "aliases c to check" do bundle "c --help" - expect(out).to include("BUNDLE-CHECK") + expect(out_with_macos_man_workaround).to include("bundle-check") end it "aliases i to install" do bundle "i --help" - expect(out).to include("BUNDLE-INSTALL") + expect(out_with_macos_man_workaround).to include("bundle-install") end it "aliases ls to list" do bundle "ls --help" - expect(out).to include("BUNDLE-LIST") + expect(out_with_macos_man_workaround).to include("bundle-list") end it "aliases package to cache" do bundle "package --help" - expect(out).to include("BUNDLE-CACHE") + expect(out_with_macos_man_workaround).to include("bundle-cache") end it "aliases pack to cache" do bundle "pack --help" - expect(out).to include("BUNDLE-CACHE") + expect(out_with_macos_man_workaround).to include("bundle-cache") + end + + private + + # Some `man` (e.g., on macOS) always highlights the output even to + # non-tty. + def out_with_macos_man_workaround + out.gsub(/.[\b]/, "") end end context "with no arguments" do it "prints a concise help message", :bundler => "3" do - bundle! "" + bundle "" expect(err).to be_empty expect(out).to include("Bundler version #{Bundler::VERSION}"). and include("\n\nBundler commands:\n\n"). @@ -91,7 +100,7 @@ context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do it "ignores it" do - gemfile bundled_app("Gemfile"), <<-G + gemfile bundled_app_gemfile, <<-G source "#{file_uri_for(gem_repo1)}" gem 'rack' G @@ -102,54 +111,38 @@ end end - context "when ENV['RUBYGEMS_GEMDEPS'] is set" do - it "displays a warning" do - gemfile bundled_app("Gemfile"), <<-G - source "#{file_uri_for(gem_repo1)}" - gem 'rack' - G - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" } - expect(err).to include("RUBYGEMS_GEMDEPS") - expect(err).to include("conflict with Bundler") - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" } - expect(err).not_to include("RUBYGEMS_GEMDEPS") - end - end - context "with --verbose" do it "prints the running command" do - gemfile "" - bundle! "info bundler", :verbose => true + gemfile "source \"#{file_uri_for(gem_repo1)}\"" + bundle "info bundler", :verbose => true expect(out).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION}") end it "doesn't print defaults" do - install_gemfile! "", :verbose => true - expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}") + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", :verbose => true + expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}") end it "doesn't print defaults" do - install_gemfile! "", :verbose => true - expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}") + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", :verbose => true + expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}") end end describe "printing the outdated warning" do shared_examples_for "no warning" do it "prints no warning" do - bundle "fail" + bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false expect(last_command.stdboth).to eq("Could not find command \"fail\".") end end - let(:bundler_version) { "1.1" } + let(:bundler_version) { "2.0" } let(:latest_version) { nil } before do - bundle! "config set --global disable_version_check false" + bundle "config set --global disable_version_check false" - simulate_bundler_version(bundler_version) + pristine_system_gems "bundler-#{bundler_version}" if latest_version info_path = home(".bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/bundler") info_path.parent.mkpath @@ -174,24 +167,24 @@ context "when the latest version is greater than the current version" do let(:latest_version) { "222.0" } it "prints the version warning" do - bundle "fail" + bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false expect(err).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To install the latest version, run `gem install bundler` +To update to the most recent version, run `bundle update --bundler` EOS end context "and disable_version_check is set" do - before { bundle! "config set disable_version_check true" } + before { bundle "config set disable_version_check true", :env => { "BUNDLER_VERSION" => bundler_version } } include_examples "no warning" end context "running a parseable command" do it "prints no warning" do - bundle! "config get --parseable foo" + bundle "config get --parseable foo", :env => { "BUNDLER_VERSION" => bundler_version } expect(last_command.stdboth).to eq "" - bundle "platform --ruby" + bundle "platform --ruby", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false expect(last_command.stdboth).to eq "Could not locate Gemfile" end end @@ -199,10 +192,10 @@ context "and is a pre-release" do let(:latest_version) { "222.0.0.pre.4" } it "prints the version warning" do - bundle "fail" + bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false expect(err).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To install the latest version, run `gem install bundler --pre` +To update to the most recent version, run `bundle update --bundler` EOS end end diff --git a/ruby/spec/bundler/bundler/compact_index_client/updater_spec.rb b/ruby/spec/bundler/bundler/compact_index_client/updater_spec.rb index fd554a7b0..fe417e392 100644 --- a/ruby/spec/bundler/bundler/compact_index_client/updater_spec.rb +++ b/ruby/spec/bundler/bundler/compact_index_client/updater_spec.rb @@ -3,28 +3,24 @@ require "net/http" require "bundler/compact_index_client" require "bundler/compact_index_client/updater" +require "tmpdir" RSpec.describe Bundler::CompactIndexClient::Updater do let(:fetcher) { double(:fetcher) } - let(:local_path) { Pathname("/tmp/localpath") } + let(:local_path) { Pathname.new Dir.mktmpdir("localpath") } let(:remote_path) { double(:remote_path) } - subject(:updater) { described_class.new(fetcher) } + let!(:updater) { described_class.new(fetcher) } context "when the ETag header is missing" do - # Regression test for https://github.com/bundler/bundler/issues/5463 + # Regression test for https://github.com/rubygems/bundler/issues/5463 + let(:response) { double(:response, :body => "abc123") } - let(:response) { double(:response, :body => "") } - - it "MisMatchedChecksumError is raised" do - # Twice: #update retries on failure - expect(response).to receive(:[]).with("Content-Encoding").twice { "" } - expect(response).to receive(:[]).with("ETag").twice { nil } - expect(fetcher).to receive(:call).twice { response } + it "treats the response as an update" do + expect(response).to receive(:[]).with("ETag") { nil } + expect(fetcher).to receive(:call) { response } - expect do - updater.update(local_path, remote_path) - end.to raise_error(Bundler::CompactIndexClient::Updater::MisMatchedChecksumError) + updater.update(local_path, remote_path) end end @@ -32,8 +28,7 @@ let(:response) { double(:response, :body => "") } it "raises HTTPError" do - expect(response).to receive(:[]).with("Content-Encoding") { "gzip" } - expect(fetcher).to receive(:call) { response } + expect(fetcher).to receive(:call).and_raise(Zlib::GzipFile::Error) expect do updater.update(local_path, remote_path) @@ -41,15 +36,24 @@ end end - context "when bundler doesn't have permissions on Dir.tmpdir" do - let(:response) { double(:response, :body => "") } + context "when receiving non UTF-8 data and default internal encoding set to ASCII" do + let(:response) { double(:response, :body => "\x8B".b) } - it "Errno::EACCES is raised" do - allow(Dir).to receive(:mktmpdir) { raise Errno::EACCES } + it "works just fine" do + old_verbose = $VERBOSE + previous_internal_encoding = Encoding.default_internal + + begin + $VERBOSE = false + Encoding.default_internal = "ASCII" + expect(response).to receive(:[]).with("ETag") { nil } + expect(fetcher).to receive(:call) { response } - expect do updater.update(local_path, remote_path) - end.to raise_error(Bundler::PermissionError) + ensure + Encoding.default_internal = previous_internal_encoding + $VERBOSE = old_verbose + end end end end diff --git a/ruby/spec/bundler/bundler/definition_spec.rb b/ruby/spec/bundler/bundler/definition_spec.rb index 1f4c1a080..2618786e7 100644 --- a/ruby/spec/bundler/bundler/definition_spec.rb +++ b/ruby/spec/bundler/bundler/definition_spec.rb @@ -31,48 +31,20 @@ to raise_error(Bundler::TemporaryResourceError, /temporarily unavailable/) end end - end - - describe "detects changes" do - it "for a path gem with changes", :bundler => "< 3" do - build_lib "foo", "1.0", :path => lib_path("foo") - - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "foo", :path => "#{lib_path("foo")}" - G + context "when Bundler::Definition.no_lock is set to true" do + subject { Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) } + before { Bundler::Definition.no_lock = true } + after { Bundler::Definition.no_lock = false } - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" + it "does not create a lock file" do + subject.lock("Gemfile.lock") + expect(File.file?("Gemfile.lock")).to eq false end - - bundle :install, :env => { "DEBUG" => "1" } - - expect(out).to match(/re-resolving dependencies/) - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G end + end - it "for a path gem with changes", :bundler => "3" do + describe "detects changes" do + it "for a path gem with changes" do build_lib "foo", "1.0", :path => lib_path("foo") install_gemfile <<-G @@ -87,7 +59,7 @@ bundle :install, :env => { "DEBUG" => "1" } expect(out).to match(/re-resolving dependencies/) - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo")} specs: @@ -124,7 +96,7 @@ bundle :check, :env => { "DEBUG" => "1" } expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo")} specs: @@ -157,15 +129,14 @@ bundle :check, :env => { "DEBUG" => "1" } expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo1)}/ specs: only_java (1.1-java) PLATFORMS - java - #{lockfile_platforms} + #{lockfile_platforms_for(["java"] + local_platforms)} DEPENDENCIES only_java @@ -184,7 +155,7 @@ bundle :check, :env => { "DEBUG" => "1" } expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo1)}/ specs: @@ -210,10 +181,12 @@ source "#{file_uri_for(gem_repo1)}" gem "foo" G + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end it "should get a locked specs list when updating all" do - definition = Bundler::Definition.new(bundled_app("Gemfile.lock"), [], Bundler::SourceList.new, true) + definition = Bundler::Definition.new(bundled_app_lock, [], Bundler::SourceList.new, true) locked_specs = definition.gem_version_promoter.locked_specs expect(locked_specs.to_a.map(&:name)).to eq ["foo"] expect(definition.instance_variable_get("@locked_specs").empty?).to eq true @@ -230,7 +203,7 @@ context "eager unlock" do let(:source_list) do Bundler::SourceList.new.tap do |source_list| - source_list.global_rubygems_source = file_uri_for(gem_repo4) + source_list.add_global_rubygems_remote(file_uri_for(gem_repo4)) end end @@ -267,6 +240,8 @@ BUNDLED WITH 1.13.0 L + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end it "should not eagerly unlock shared dependency with bundle install conservative updating behavior" do @@ -275,7 +250,7 @@ Bundler::Dependency.new("shared_owner_b", ">= 0")] unlock_hash_for_bundle_install = {} definition = Bundler::Definition.new( - bundled_app("Gemfile.lock"), + bundled_app_lock, updated_deps_in_gemfile, source_list, unlock_hash_for_bundle_install @@ -289,10 +264,10 @@ Bundler::Dependency.new("shared_owner_a", ">= 0"), Bundler::Dependency.new("shared_owner_b", ">= 0")] definition = Bundler::Definition.new( - bundled_app("Gemfile.lock"), + bundled_app_lock, updated_deps_in_gemfile, source_list, - :gems => ["shared_owner_a"], :lock_shared_dependencies => true + :gems => ["shared_owner_a"], :conservative => true ) locked = definition.send(:converge_locked_specs).map(&:name) expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b] @@ -302,33 +277,6 @@ end end - describe "find_resolved_spec" do - it "with no platform set in SpecSet" do - ss = Bundler::SpecSet.new([build_stub_spec("a", "1.0"), build_stub_spec("b", "1.0")]) - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@specs", ss) - found = dfn.find_resolved_spec(build_spec("a", "0.9", "ruby").first) - expect(found.name).to eq "a" - expect(found.version.to_s).to eq "1.0" - end - end - - describe "find_indexed_specs" do - it "with no platform set in indexed specs" do - index = Bundler::Index.new - %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) } - - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@index", index) - found = dfn.find_indexed_specs(build_spec("foo", "0.9", "ruby").first) - expect(found.length).to eq 3 - end - end - - def build_stub_spec(name, version) - Bundler::StubSpecification.new(name, version, nil, nil) - end - def mock_source_list Class.new do def all_sources diff --git a/ruby/spec/bundler/bundler/dep_proxy_spec.rb b/ruby/spec/bundler/bundler/dep_proxy_spec.rb index 0f8d6b107..8d02a3372 100644 --- a/ruby/spec/bundler/bundler/dep_proxy_spec.rb +++ b/ruby/spec/bundler/bundler/dep_proxy_spec.rb @@ -2,10 +2,10 @@ RSpec.describe Bundler::DepProxy do let(:dep) { Bundler::Dependency.new("rake", ">= 0") } - subject { described_class.new(dep, Gem::Platform::RUBY) } + subject { described_class.get_proxy(dep, Gem::Platform::RUBY) } let(:same) { subject } - let(:other) { subject.dup } - let(:different) { described_class.new(dep, Gem::Platform::JAVA) } + let(:other) { described_class.get_proxy(dep, Gem::Platform::RUBY) } + let(:different) { described_class.get_proxy(dep, Gem::Platform::JAVA) } describe "#eql?" do it { expect(subject.eql?(same)).to be true } @@ -15,8 +15,18 @@ it { expect(subject.eql?("foobar")).to be false } end - describe "#hash" do - it { expect(subject.hash).to eq(same.hash) } - it { expect(subject.hash).to eq(other.hash) } + describe "must use factory methods" do + it { expect { described_class.new(dep, Gem::Platform::RUBY) }.to raise_error NoMethodError } + it { expect { subject.dup }.to raise_error NoMethodError } + it { expect { subject.clone }.to raise_error NoMethodError } + end + + describe "frozen" do + if Gem.ruby_version >= Gem::Version.new("2.5.0") + error = Object.const_get("FrozenError") + else + error = RuntimeError + end + it { expect { subject.instance_variable_set(:@__platform, {}) }.to raise_error error } end end diff --git a/ruby/spec/bundler/bundler/digest_spec.rb b/ruby/spec/bundler/bundler/digest_spec.rb new file mode 100644 index 000000000..d6bb043fd --- /dev/null +++ b/ruby/spec/bundler/bundler/digest_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "digest" +require "bundler/digest" + +RSpec.describe Bundler::Digest do + context "SHA1" do + subject { Bundler::Digest } + let(:stdlib) { ::Digest::SHA1 } + + it "is compatible with stdlib" do + ["foo", "skfjsdlkfjsdf", "3924m", "ldskfj"].each do |payload| + expect(subject.sha1(payload)).to be == stdlib.hexdigest(payload) + end + end + end +end diff --git a/ruby/spec/bundler/bundler/dsl_spec.rb b/ruby/spec/bundler/bundler/dsl_spec.rb index 40739a431..a44a12924 100644 --- a/ruby/spec/bundler/bundler/dsl_spec.rb +++ b/ruby/spec/bundler/bundler/dsl_spec.rb @@ -25,7 +25,46 @@ expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) end - context "default hosts", :bundler => "2" do + it "converts :github PR to URI using https" do + subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5") + github_uri = "https://github.com/indirect/sparks.git" + expect(subject.dependencies.first.source.uri).to eq(github_uri) + expect(subject.dependencies.first.source.branch).to eq("refs/pull/5/head") + end + + it "rejects :github PR URI with a branch, ref or tag" do + expect do + subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :branch => "foo") + end.to raise_error( + Bundler::GemfileError, + %(The :branch option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`), + ) + + expect do + subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :ref => "foo") + end.to raise_error( + Bundler::GemfileError, + %(The :ref option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`), + ) + + expect do + subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :tag => "foo") + end.to raise_error( + Bundler::GemfileError, + %(The :tag option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`), + ) + end + + it "rejects :github with :git" do + expect do + subject.gem("sparks", :github => "indirect/sparks", :git => "https://github.com/indirect/sparks.git") + end.to raise_error( + Bundler::GemfileError, + %(The :git option can't be used with `github: "indirect/sparks"`), + ) + end + + context "default hosts", :bundler => "< 3" do it "converts :github to URI using https" do subject.gem("sparks", :github => "indirect/sparks") github_uri = "https://github.com/indirect/sparks.git" @@ -63,16 +102,16 @@ end end - context "default git sources", :bundler => "3" do - it "has none" do - expect(subject.instance_variable_get(:@git_sources)).to eq({}) + context "default git sources" do + it "has bitbucket, gist, and github" do + expect(subject.instance_variable_get(:@git_sources).keys.sort).to eq(%w[bitbucket gist github]) end end end describe "#method_missing" do it "raises an error for unknown DSL methods" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s). + expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s). and_return("unknown") error_msg = "There was an error parsing `Gemfile`: Undefined local variable or method `unknown' for Gemfile. Bundler cannot continue." @@ -83,13 +122,13 @@ describe "#eval_gemfile" do it "handles syntax errors with a useful message" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return("}") + expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s).and_return("}") expect { subject.eval_gemfile("Gemfile") }. to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'). Bundler cannot continue./) end it "distinguishes syntax errors from evaluation errors" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return( + expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s).and_return( "ruby '2.1.5', :engine => 'ruby', :engine_version => '1.2.4'" ) expect { subject.eval_gemfile("Gemfile") }. @@ -174,40 +213,6 @@ end end - describe "#gemspec" do - let(:spec) do - Gem::Specification.new do |gem| - gem.name = "example" - gem.platform = platform - end - end - - before do - allow(Dir).to receive(:[]).and_return(["spec_path"]) - allow(Bundler).to receive(:load_gemspec).with("spec_path").and_return(spec) - allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile")) - end - - context "with a ruby platform" do - let(:platform) { "ruby" } - - it "keeps track of the ruby platforms in the dependency" do - subject.gemspec - expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::RUBY]) - end - end - - context "with a jruby platform" do - let(:platform) { "java" } - - it "keeps track of the jruby platforms in the dependency" do - allow(Gem::Platform).to receive(:local).and_return(java) - subject.gemspec - expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::JAVA]) - end - end - end - context "can bundle groups of gems with" do # git "https://github.com/rails/rails.git" do # gem "railties" @@ -229,20 +234,7 @@ # gem 'spree_api' # gem 'spree_backend' # end - describe "#github", :bundler => "< 3" do - it "from github" do - spree_gems = %w[spree_core spree_api spree_backend] - subject.github "spree" do - spree_gems.each {|spree_gem| subject.send :gem, spree_gem } - end - - subject.dependencies.each do |d| - expect(d.source.uri).to eq("https://github.com/spree/spree.git") - end - end - end - - describe "#github", :bundler => "2" do + describe "#github" do it "from github" do spree_gems = %w[spree_core spree_api spree_backend] subject.github "spree" do @@ -254,23 +246,12 @@ end end end - - describe "#github", :bundler => "3" do - it "from github" do - expect do - spree_gems = %w[spree_core spree_api spree_backend] - subject.github "spree" do - spree_gems.each {|spree_gem| subject.send :gem, spree_gem } - end - end.to raise_error(Bundler::DeprecatedError, /github method has been removed/) - end - end end describe "syntax errors" do it "will raise a Bundler::GemfileError" do gemfile "gem 'foo', :path => /unquoted/string/syntax/error" - expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }. + expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }. to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)? unknown regexp options - trg.+ Bundler cannot continue./) end end @@ -278,7 +259,7 @@ describe "Runtime errors" do it "will raise a Bundler::GemfileError" do gemfile "raise RuntimeError, 'foo'" - expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }. + expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }. to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: foo. Bundler cannot continue./i) end end @@ -299,4 +280,21 @@ end end end + + describe "#check_primary_source_safety" do + context "when a global source is not defined implicitly" do + it "will raise a major deprecation warning" do + not_a_global_source = double("not-a-global-source", :no_remotes? => true) + allow(Bundler::Source::Rubygems).to receive(:new).and_return(not_a_global_source) + + warning = "This Gemfile does not include an explicit global source. " \ + "Not using an explicit global source may result in a different lockfile being generated depending on " \ + "the gems you have installed locally before bundler is run. " \ + "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"." + expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(2, warning) + + subject.check_primary_source_safety + end + end + end end diff --git a/ruby/spec/bundler/bundler/endpoint_specification_spec.rb b/ruby/spec/bundler/bundler/endpoint_specification_spec.rb index a9371f661..02a90d507 100644 --- a/ruby/spec/bundler/bundler/endpoint_specification_spec.rb +++ b/ruby/spec/bundler/bundler/endpoint_specification_spec.rb @@ -5,9 +5,10 @@ let(:version) { "1.0.0" } let(:platform) { Gem::Platform::RUBY } let(:dependencies) { [] } + let(:spec_fetcher) { double(:spec_fetcher) } let(:metadata) { nil } - subject(:spec) { described_class.new(name, version, platform, dependencies, metadata) } + subject(:spec) { described_class.new(name, version, platform, spec_fetcher, dependencies, metadata) } describe "#build_dependency" do let(:name) { "foo" } @@ -32,22 +33,6 @@ ) end end - - context "when there is an ill formed requirement" do - before do - allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) { - raise ArgumentError.new("Ill-formed requirement [\"# nil, :required_rubygems_version => nil) + allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec) + other_spec = described_class.new("bar", version, platform, spec_fetcher, dependencies, metadata) expect(spec).to eql(spec) expect(spec).to_not eql(other_spec) end diff --git a/ruby/spec/bundler/bundler/env_spec.rb b/ruby/spec/bundler/bundler/env_spec.rb index 7686fe386..a6f4b2ba8 100644 --- a/ruby/spec/bundler/bundler/env_spec.rb +++ b/ruby/spec/bundler/bundler/env_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require "openssl" require "bundler/settings" +require "openssl" RSpec.describe Bundler::Env do let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil, nil) } @@ -34,6 +34,8 @@ end it "prints user home" do + skip "needs to use a valid HOME" if Gem.win_platform? && RUBY_VERSION < "2.6.0" + with_clear_paths("HOME", "/a/b/c") do out = described_class.report expect(out).to include("User Home /a/b/c") @@ -41,7 +43,11 @@ end it "prints user path" do + skip "needs to use a valid HOME" if Gem.win_platform? && RUBY_VERSION < "2.6.0" + with_clear_paths("HOME", "/a/b/c") do + allow(File).to receive(:exist?) + allow(File).to receive(:exist?).with("/a/b/c/.gem").and_return(true) out = described_class.report expect(out).to include("User Path /a/b/c/.gem") end @@ -54,7 +60,7 @@ end end - private + private def with_clear_paths(env_var, env_value) old_env_var = ENV[env_var] @@ -68,7 +74,7 @@ def with_clear_paths(env_var, env_value) context "when there is a Gemfile and a lockfile and print_gemfile is true" do before do - gemfile "gem 'rack', '1.0.0'" + gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem 'rack', '1.0.0'" lockfile <<-L GEM @@ -82,6 +88,8 @@ def with_clear_paths(env_var, env_value) BUNDLED WITH 1.10.0 L + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end let(:output) { described_class.report(:print_gemfile => true) } @@ -105,6 +113,34 @@ def with_clear_paths(env_var, env_value) end end + context "when there's bundler config with credentials" do + before do + bundle "config set https://localgemserver.test/ user:pass" + end + + let(:output) { described_class.report(:print_gemfile => true) } + + it "prints the config with redacted values" do + expect(output).to include("https://localgemserver.test") + expect(output).to include("user:[REDACTED]") + expect(output).to_not include("user:pass") + end + end + + context "when there's bundler config with OAuth token credentials" do + before do + bundle "config set https://localgemserver.test/ api_token:x-oauth-basic" + end + + let(:output) { described_class.report(:print_gemfile => true) } + + it "prints the config with redacted values" do + expect(output).to include("https://localgemserver.test") + expect(output).to include("[REDACTED]:x-oauth-basic") + expect(output).to_not include("api_token:x-oauth-basic") + end + end + context "when Gemfile contains a gemspec and print_gemspecs is true" do let(:gemspec) do strip_whitespace(<<-GEMSPEC) @@ -116,11 +152,13 @@ def with_clear_paths(env_var, env_value) end before do - gemfile("gemspec") + gemfile("source \"#{file_uri_for(gem_repo1)}\"; gemspec") File.open(bundled_app.join("foo.gemspec"), "wb") do |f| f.write(gemspec) end + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end it "prints the gemspec" do @@ -133,13 +171,15 @@ def with_clear_paths(env_var, env_value) context "when eval_gemfile is used" do it "prints all gemfiles" do - create_file "other/Gemfile-other", "gem 'rack'" - create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'" - create_file "Gemfile-alt", <<-G + create_file bundled_app("other/Gemfile-other"), "gem 'rack'" + create_file bundled_app("other/Gemfile"), "eval_gemfile 'Gemfile-other'" + create_file bundled_app("Gemfile-alt"), <<-G source "#{file_uri_for(gem_repo1)}" eval_gemfile "other/Gemfile" G - gemfile "eval_gemfile #{File.expand_path("Gemfile-alt").dump}" + gemfile "eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}" + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app) output = described_class.report(:print_gemspecs => true) expect(output).to include(strip_whitespace(<<-ENV)) @@ -148,7 +188,7 @@ def with_clear_paths(env_var, env_value) ### Gemfile ```ruby - eval_gemfile #{File.expand_path("Gemfile-alt").dump} + eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump} ``` ### Gemfile-alt @@ -173,7 +213,7 @@ def with_clear_paths(env_var, env_value) ### Gemfile.lock ``` - + ``` ENV end diff --git a/ruby/spec/bundler/bundler/fetcher/compact_index_spec.rb b/ruby/spec/bundler/bundler/fetcher/compact_index_spec.rb index c9419d3eb..00eb27ede 100644 --- a/ruby/spec/bundler/bundler/fetcher/compact_index_spec.rb +++ b/ruby/spec/bundler/bundler/fetcher/compact_index_spec.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# load CompactIndexClient upfront to prevent thread safety issues during parallel specs +require "bundler/compact_index_client" + RSpec.describe Bundler::Fetcher::CompactIndex do let(:downloader) { double(:downloader) } let(:display_uri) { Bundler::URI("http://sampleuri.com") } @@ -62,7 +65,7 @@ def remove_cached_md5_availability context "when FIPS-mode is active" do before do - allow(OpenSSL::Digest::MD5).to receive(:digest). + allow(OpenSSL::Digest).to receive(:digest).with("MD5", ""). and_raise(OpenSSL::Digest::DigestError) end diff --git a/ruby/spec/bundler/bundler/fetcher/downloader_spec.rb b/ruby/spec/bundler/bundler/fetcher/downloader_spec.rb index ba8451d9f..94a0993a5 100644 --- a/ruby/spec/bundler/bundler/fetcher/downloader_spec.rb +++ b/ruby/spec/bundler/bundler/fetcher/downloader_spec.rb @@ -83,6 +83,11 @@ /Authentication is required for www.uri-to-fetch.com/) end + it "should raise a Bundler::Fetcher::AuthenticationRequiredError with advices" do + expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, + /`bundle config set --global www\.uri-to-fetch\.com username:password`.*`BUNDLE_WWW__URI___TO___FETCH__COM`/m) + end + context "when the there are credentials provided in the request" do let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") } @@ -188,7 +193,7 @@ let(:message) { "undefined method 'undefined_method_call'" } it "should raise the original NoMethodError" do - expect { subject.request(uri, options) }.to raise_error(NoMethodError, "undefined method 'undefined_method_call'") + expect { subject.request(uri, options) }.to raise_error(NoMethodError, /undefined method 'undefined_method_call'/) end end end @@ -226,16 +231,7 @@ end end - context "when error message is about getaddrinfo issues" do - let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" } - - it "should raise a Bundler::Fetcher::NetworkDownError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError, - /Could not reach host www.uri-to-fetch.com/) - end - end - - context "when error message is about neither host down or getaddrinfo" do + context "when error message is not about host down" do let(:message) { "other error about network" } it "should raise a Bundler::HTTPError" do diff --git a/ruby/spec/bundler/bundler/fetcher/index_spec.rb b/ruby/spec/bundler/bundler/fetcher/index_spec.rb index 5ecd7d9e0..f0db07583 100644 --- a/ruby/spec/bundler/bundler/fetcher/index_spec.rb +++ b/ruby/spec/bundler/bundler/fetcher/index_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rubygems/remote_fetcher" + RSpec.describe Bundler::Fetcher::Index do let(:downloader) { nil } let(:remote) { nil } @@ -17,100 +19,81 @@ end context "error handling" do - shared_examples_for "the error is properly handled" do - let(:remote_uri) { Bundler::URI("http://remote-uri.org") } - before do - allow(subject).to receive(:remote_uri).and_return(remote_uri) - end + let(:remote_uri) { Bundler::URI("http://remote-uri.org") } + before do + allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, display_uri) } + allow(subject).to receive(:remote_uri).and_return(remote_uri) + end - context "when certificate verify failed" do - let(:error_message) { "certificate verify failed" } + context "when certificate verify failed" do + let(:error_message) { "certificate verify failed" } - it "should raise a Bundler::Fetcher::CertificateFailureError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError, - %r{Could not verify the SSL certificate for http://sample_uri.com}) - end + it "should raise a Bundler::Fetcher::CertificateFailureError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError, + %r{Could not verify the SSL certificate for http://sample_uri.com}) end + end - context "when a 401 response occurs" do - let(:error_message) { "401" } - - before do - allow(remote_uri).to receive(:userinfo).and_return(userinfo) - end - - context "and there was userinfo" do - let(:userinfo) { double(:userinfo) } + context "when a 401 response occurs" do + let(:error_message) { "401" } - it "should raise a Bundler::Fetcher::BadAuthenticationError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, - %r{Bad username or password for http://remote-uri.org}) - end - end + before do + allow(remote_uri).to receive(:userinfo).and_return(userinfo) + end - context "and there was no userinfo" do - let(:userinfo) { nil } + context "and there was userinfo" do + let(:userinfo) { double(:userinfo) } - it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote-uri.org}) - end + it "should raise a Bundler::Fetcher::BadAuthenticationError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, + %r{Bad username or password for http://remote-uri.org}) end end - context "when a 403 response occurs" do - let(:error_message) { "403" } + context "and there was no userinfo" do + let(:userinfo) { nil } - before do - allow(remote_uri).to receive(:userinfo).and_return(userinfo) + it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, + %r{Authentication is required for http://remote-uri.org}) end + end + end - context "and there was userinfo" do - let(:userinfo) { double(:userinfo) } + context "when a 403 response occurs" do + let(:error_message) { "403" } - it "should raise a Bundler::Fetcher::BadAuthenticationError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, - %r{Bad username or password for http://remote-uri.org}) - end - end + before do + allow(remote_uri).to receive(:userinfo).and_return(userinfo) + end - context "and there was no userinfo" do - let(:userinfo) { nil } + context "and there was userinfo" do + let(:userinfo) { double(:userinfo) } - it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote-uri.org}) - end + it "should raise a Bundler::Fetcher::BadAuthenticationError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, + %r{Bad username or password for http://remote-uri.org}) end end - context "any other message is returned" do - let(:error_message) { "You get an error, you get an error!" } - - before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) } + context "and there was no userinfo" do + let(:userinfo) { nil } - it "should raise a Bundler::HTTPError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com") + it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, + %r{Authentication is required for http://remote-uri.org}) end end end - context "when a Gem::RemoteFetcher::FetchError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, nil) } } + context "any other message is returned" do + let(:error_message) { "You get an error, you get an error!" } - it_behaves_like "the error is properly handled" - end - - context "when a OpenSSL::SSL::SSLError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise OpenSSL::SSL::SSLError.new(error_message) } } - - it_behaves_like "the error is properly handled" - end - - context "when a Net::HTTPFatalError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Net::HTTPFatalError.new(error_message, 404) } } + before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) } - it_behaves_like "the error is properly handled" + it "should raise a Bundler::HTTPError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com due to underlying error ") + end end end end diff --git a/ruby/spec/bundler/bundler/fetcher_spec.rb b/ruby/spec/bundler/bundler/fetcher_spec.rb index 539179db4..a10476007 100644 --- a/ruby/spec/bundler/bundler/fetcher_spec.rb +++ b/ruby/spec/bundler/bundler/fetcher_spec.rb @@ -26,7 +26,7 @@ context "when Gem.configuration specifies http_proxy " do let(:proxy) { "http://proxy-example2.com" } before do - allow(Bundler.rubygems.configuration).to receive(:[]).with(:http_proxy).and_return(proxy) + allow(Gem.configuration).to receive(:[]).with(:http_proxy).and_return(proxy) end it "consider Gem.configuration when determine proxy" do expect(fetcher.http_proxy).to match("http://proxy-example2.com") @@ -113,7 +113,7 @@ context "when gem ssl configuration is set" do before do - allow(Bundler.rubygems.configuration).to receive_messages( + allow(Gem.configuration).to receive_messages( :http_proxy => nil, :ssl_client_cert => "cert", :ssl_ca_cert => "ca" @@ -150,9 +150,10 @@ end it "from many CI" do - with_env_vars("TRAVIS" => "foo", "CI_NAME" => "my_ci") do + with_env_vars("TRAVIS" => "foo", "GITLAB_CI" => "gitlab", "CI_NAME" => "my_ci") do ci_part = fetcher.user_agent.split(" ").find {|x| x.start_with?("ci/") } expect(ci_part).to match("travis") + expect(ci_part).to match("gitlab") expect(ci_part).to match("my_ci") end end diff --git a/ruby/spec/bundler/bundler/friendly_errors_spec.rb b/ruby/spec/bundler/bundler/friendly_errors_spec.rb index e9189b051..496191f89 100644 --- a/ruby/spec/bundler/bundler/friendly_errors_spec.rb +++ b/ruby/spec/bundler/bundler/friendly_errors_spec.rb @@ -7,13 +7,13 @@ RSpec.describe Bundler, "friendly errors" do context "with invalid YAML in .gemrc" do before do - File.open(Gem.configuration.config_file_name, "w") do |f| + File.open(home(".gemrc"), "w") do |f| f.write "invalid: yaml: hah" end end after do - FileUtils.rm(Gem.configuration.config_file_name) + FileUtils.rm(home(".gemrc")) end it "reports a relevant friendly error message" do @@ -25,7 +25,6 @@ bundle :install, :env => { "DEBUG" => "true" } expect(err).to include("Failed to load #{home(".gemrc")}") - expect(exitstatus).to eq(0) if exitstatus end end @@ -115,18 +114,12 @@ context "LoadError" do let(:error) { LoadError.new("cannot load such file -- openssl") } - it "Bundler.ui receive error" do - expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL.") - Bundler::FriendlyErrors.log_error(error) - end - - it "Bundler.ui receive warn" do - expect(Bundler.ui).to receive(:warn).with(any_args, :wrap => true) - Bundler::FriendlyErrors.log_error(error) + before do + allow(error).to receive(:backtrace).and_return(["backtrace"]) end - it "Bundler.ui receive trace" do - expect(Bundler.ui).to receive(:trace).with(error) + it "Bundler.ui receive error" do + expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL. LoadError: cannot load such file -- openssl\nbacktrace") Bundler::FriendlyErrors.log_error(error) end end @@ -200,9 +193,9 @@ class OutOfMemoryError < StandardError; end describe "#request_issue_report_for" do it "calls relevant methods for Bundler.ui" do - expect(Bundler.ui).to receive(:info) - expect(Bundler.ui).to receive(:error) - expect(Bundler.ui).to receive(:warn) + expect(Bundler.ui).not_to receive(:info) + expect(Bundler.ui).to receive(:error).exactly(3).times + expect(Bundler.ui).not_to receive(:warn) Bundler::FriendlyErrors.request_issue_report_for(StandardError.new) end @@ -221,7 +214,7 @@ class OutOfMemoryError < StandardError; end it "generates a search URL for the exception message" do exception = Exception.new("Exception message") - expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=Exception+message&type=Issues") + expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/rubygems/rubygems/search?q=Exception+message&type=Issues") end it "generates a search URL for only the first line of a multi-line exception message" do @@ -230,7 +223,7 @@ class OutOfMemoryError < StandardError; end Second line of the exception message END - expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=First+line+of+the+exception+message&type=Issues") + expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/rubygems/rubygems/search?q=First+line+of+the+exception+message&type=Issues") end it "generates the url without colons" do @@ -239,7 +232,7 @@ class OutOfMemoryError < StandardError; end END issues_url = Bundler::FriendlyErrors.issues_url(exception) expect(issues_url).not_to include("%3A") - expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Exception with colons ")}&type=Issues") + expect(issues_url).to eq("https://github.com/rubygems/rubygems/search?q=#{CGI.escape("Exception with colons ")}&type=Issues") end it "removes information after - for Errono::EACCES" do @@ -249,7 +242,7 @@ class OutOfMemoryError < StandardError; end allow(exception).to receive(:is_a?).with(Errno).and_return(true) issues_url = Bundler::FriendlyErrors.issues_url(exception) expect(issues_url).not_to include("/Users/foo/bar") - expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues") + expect(issues_url).to eq("https://github.com/rubygems/rubygems/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues") end end end diff --git a/ruby/spec/bundler/bundler/gem_helper_spec.rb b/ruby/spec/bundler/bundler/gem_helper_spec.rb index 29e10d64f..5cd79de62 100644 --- a/ruby/spec/bundler/bundler/gem_helper_spec.rb +++ b/ruby/spec/bundler/bundler/gem_helper_spec.rb @@ -9,7 +9,8 @@ let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") } before(:each) do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false" + global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false", + "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false" bundle "gem #{app_name}" prepare_gemspec(app_gemspec_path) end @@ -60,10 +61,20 @@ def mock_build_message(name, version) mock_confirm_message message end + def mock_checksum_message(name, version) + message = "#{name} #{version} checksum written to checksums/#{name}-#{version}.gem.sha512." + mock_confirm_message message + end + + def sha512_hexdigest(path) + Digest::SHA512.file(path).hexdigest + end + subject! { Bundler::GemHelper.new(app_path) } let(:app_version) { "0.1.0" } let(:app_gem_dir) { app_path.join("pkg") } let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") } + let(:app_sha_path) { app_path.join("checksums", "#{app_name}-#{app_version}.gem.sha512") } let(:app_gemspec_content) { File.read(app_gemspec_path) } before(:each) do @@ -97,6 +108,7 @@ def mock_build_message(name, version) context "before installation" do it "raises an error with appropriate message" do task_names.each do |name| + skip "Rake::FileTask '#{name}' exists" if File.exist?(name) expect { Rake.application[name] }. to raise_error(/^Don't know how to build task '#{name}'/) end @@ -138,6 +150,68 @@ def mock_build_message(name, version) expect(app_gem_path).to exist end end + + context "when building in the current working directory" do + it "creates .gem file" do + mock_build_message app_name, app_version + Dir.chdir app_path do + Bundler::GemHelper.new.build_gem + end + expect(app_gem_path).to exist + end + end + + context "when building in a location relative to the current working directory" do + it "creates .gem file" do + mock_build_message app_name, app_version + Dir.chdir File.dirname(app_path) do + Bundler::GemHelper.new(File.basename(app_path)).build_gem + end + expect(app_gem_path).to exist + end + end + end + + describe "#build_checksum" do + it "calculates SHA512 of the content" do + FileUtils.mkdir_p(app_gem_dir) + File.write(app_gem_path, "") + mock_checksum_message app_name, app_version + subject.build_checksum(app_gem_path) + expect(File.read(app_sha_path).chomp).to eql(Digest::SHA512.hexdigest("")) + end + + context "when build was successful" do + it "creates .sha512 file" do + mock_build_message app_name, app_version + mock_checksum_message app_name, app_version + subject.build_checksum + expect(app_sha_path).to exist + expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path)) + end + end + context "when building in the current working directory" do + it "creates a .sha512 file" do + mock_build_message app_name, app_version + mock_checksum_message app_name, app_version + Dir.chdir app_path do + Bundler::GemHelper.new.build_checksum + end + expect(app_sha_path).to exist + expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path)) + end + end + context "when building in a location relative to the current working directory" do + it "creates a .sha512 file" do + mock_build_message app_name, app_version + mock_checksum_message app_name, app_version + Dir.chdir File.dirname(app_path) do + Bundler::GemHelper.new(File.basename(app_path)).build_checksum + end + expect(app_sha_path).to exist + expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path)) + end + end end describe "#install_gem" do @@ -147,7 +221,7 @@ def mock_build_message(name, version) mock_confirm_message "#{app_name} (#{app_version}) installed." subject.install_gem(nil, :local) expect(app_gem_path).to exist - gem_command! :list + gem_command :list expect(out).to include("#{app_name} (#{app_version})") end end @@ -160,7 +234,7 @@ def mock_build_message(name, version) FileUtils.touch app_gem_path app_gem_path end - expect { subject.install_gem }.to raise_error(/Couldn't install gem/) + expect { subject.install_gem }.to raise_error(/Running `#{gem_bin} install #{app_gem_path}` failed/) end end end @@ -178,13 +252,11 @@ def mock_build_message(name, version) end before do - Dir.chdir(app_path) do - `git init` - `git config user.email "you@example.com"` - `git config user.name "name"` - `git config commit.gpgsign false` - `git config push.default simple` - end + sys_exec("git init", :dir => app_path) + sys_exec("git config user.email \"you@example.com\"", :dir => app_path) + sys_exec("git config user.name \"name\"", :dir => app_path) + sys_exec("git config commit.gpgsign false", :dir => app_path) + sys_exec("git config push.default simple", :dir => app_path) # silence messages allow(Bundler.ui).to receive(:confirm) @@ -198,13 +270,13 @@ def mock_build_message(name, version) end it "when there are uncommitted files" do - Dir.chdir(app_path) { `git add .` } + sys_exec("git add .", :dir => app_path) expect { Rake.application["release"].invoke }. to raise_error("There are files that need to be committed first.") end it "when there is no git remote" do - Dir.chdir(app_path) { `git commit -a -m "initial commit"` } + sys_exec("git commit -a -m \"initial commit\"", :dir => app_path) expect { Rake.application["release"].invoke }.to raise_error(RuntimeError) end end @@ -213,19 +285,17 @@ def mock_build_message(name, version) let(:repo) { build_git("foo", :bare => true) } before do - Dir.chdir(app_path) do - sys_exec("git remote add origin #{file_uri_for(repo.path)}") - sys_exec('git commit -a -m "initial commit"') - end + sys_exec("git remote add origin #{file_uri_for(repo.path)}", :dir => app_path) + sys_exec('git commit -a -m "initial commit"', :dir => app_path) end context "on releasing" do before do mock_build_message app_name, app_version mock_confirm_message "Tagged v#{app_version}." - mock_confirm_message "Pushed git commits and tags." + mock_confirm_message "Pushed git commits and release tag." - Dir.chdir(app_path) { sys_exec("git push -u origin master") } + sys_exec("git push -u origin master", :dir => app_path) end it "calls rubygem_push with proper arguments" do @@ -235,7 +305,43 @@ def mock_build_message(name, version) end it "uses Kernel.system" do - expect(Kernel).to receive(:system).with(gem_bin, "push", app_gem_path.to_s, "--host", "http://example.org").and_return(true) + cmd = gem_bin.shellsplit + expect(Kernel).to receive(:system).with(*cmd, "push", app_gem_path.to_s, "--host", "http://example.org").and_return(true) + + Rake.application["release"].invoke + end + + it "also works when releasing from an ambiguous reference" do + # Create a branch with the same name as the tag + sys_exec("git checkout -b v#{app_version}", :dir => app_path) + sys_exec("git push -u origin v#{app_version}", :dir => app_path) + + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + + Rake.application["release"].invoke + end + + it "also works with releasing from a branch not yet pushed" do + sys_exec("git checkout -b module_function", :dir => app_path) + + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + + Rake.application["release"].invoke + end + end + + context "on releasing with a custom tag prefix" do + before do + Bundler::GemHelper.tag_prefix = "foo-" + mock_build_message app_name, app_version + mock_confirm_message "Pushed git commits and release tag." + + sys_exec("git push -u origin master", :dir => app_path) + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + end + + it "prepends the custom prefix to the tag" do + mock_confirm_message "Tagged foo-v#{app_version}." Rake.application["release"].invoke end @@ -246,9 +352,7 @@ def mock_build_message(name, version) mock_confirm_message "Tag v#{app_version} has already been created." expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) - Dir.chdir(app_path) do - `git tag -a -m \"Version #{app_version}\" v#{app_version}` - end + sys_exec("git tag -a -m \"Version #{app_version}\" v#{app_version}", :dir => app_path) Rake.application["release"].invoke end @@ -269,12 +373,10 @@ def mock_build_message(name, version) end before do - Dir.chdir(app_path) do - `git init` - `git config user.email "you@example.com"` - `git config user.name "name"` - `git config push.default simple` - end + sys_exec("git init", :dir => app_path) + sys_exec("git config user.email \"you@example.com\"", :dir => app_path) + sys_exec("git config user.name \"name\"", :dir => app_path) + sys_exec("git config push.gpgsign simple", :dir => app_path) # silence messages allow(Bundler.ui).to receive(:confirm) diff --git a/ruby/spec/bundler/bundler/gem_version_promoter_spec.rb b/ruby/spec/bundler/bundler/gem_version_promoter_spec.rb index 01e0232fb..43a3630bb 100644 --- a/ruby/spec/bundler/bundler/gem_version_promoter_spec.rb +++ b/ruby/spec/bundler/bundler/gem_version_promoter_spec.rb @@ -28,7 +28,7 @@ def keep_locked(options) def build_spec_groups(name, versions) versions.map do |v| - Bundler::Resolver::SpecGroup.new(build_spec(name, v)) + Bundler::Resolver::SpecGroup.create_for({ Gem::Platform::RUBY => build_spec(name, v) }, [Gem::Platform::RUBY], Gem::Platform::RUBY) end end @@ -170,7 +170,7 @@ def build_spec_groups(name, versions) context "debug output" do it "should not kerblooie on its own debug output" do gvp = unlocking(:level => :patch) - dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby") + dep = Bundler::DepProxy.get_proxy(dep("foo", "1.2.0").first, "ruby") result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0])) expect(result.class).to eq Array end diff --git a/ruby/spec/bundler/bundler/installer/parallel_installer_spec.rb b/ruby/spec/bundler/bundler/installer/parallel_installer_spec.rb index ace5c1a23..e68063386 100644 --- a/ruby/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/ruby/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -44,4 +44,37 @@ end end end + + context "when the spec set is not a valid resolution" do + let(:all_specs) do + [ + build_spec("cucumber", "4.1.0") {|s| s.runtime "diff-lcs", "< 1.4" }, + build_spec("diff-lcs", "1.4.4"), + ].flatten + end + + it "prints a warning" do + expect(Bundler.ui).to receive(:warn).with(<<-W.strip) +Your lockfile doesn't include a valid resolution. +You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies. +The unmet dependencies are: +* diff-lcs (< 1.4), depended upon cucumber-4.1.0, unsatisfied by diff-lcs-1.4.4 + W + subject.check_for_unmet_dependencies + end + end + + context "when the spec set is a valid resolution" do + let(:all_specs) do + [ + build_spec("cucumber", "4.1.0") {|s| s.runtime "diff-lcs", "< 1.4" }, + build_spec("diff-lcs", "1.3"), + ].flatten + end + + it "doesn't print a warning" do + expect(Bundler.ui).not_to receive(:warn) + subject.check_for_unmet_dependencies + end + end end diff --git a/ruby/spec/bundler/bundler/installer/spec_installation_spec.rb b/ruby/spec/bundler/bundler/installer/spec_installation_spec.rb index a9cf09a37..e63ef26cb 100644 --- a/ruby/spec/bundler/bundler/installer/spec_installation_spec.rb +++ b/ruby/spec/bundler/bundler/installer/spec_installation_spec.rb @@ -8,6 +8,10 @@ def a_spec.name "I like tests" end + + def a_spec.full_name + "I really like tests" + end a_spec end diff --git a/ruby/spec/bundler/bundler/mirror_spec.rb b/ruby/spec/bundler/bundler/mirror_spec.rb index 4a8a0c7c4..1eaf1e9a8 100644 --- a/ruby/spec/bundler/bundler/mirror_spec.rb +++ b/ruby/spec/bundler/bundler/mirror_spec.rb @@ -305,6 +305,8 @@ def with_server_and_mirror end it "probes the server correctly" do + skip "obscure error" if Gem.win_platform? + with_server_and_mirror do |server, mirror| expect(server.closed?).to be_falsey expect(probe.replies?(mirror)).to be_truthy diff --git a/ruby/spec/bundler/bundler/plugin/api/source_spec.rb b/ruby/spec/bundler/bundler/plugin/api/source_spec.rb index 2c50ff56a..428ceb220 100644 --- a/ruby/spec/bundler/bundler/plugin/api/source_spec.rb +++ b/ruby/spec/bundler/bundler/plugin/api/source_spec.rb @@ -79,4 +79,10 @@ end end end + + describe "to_s" do + it "returns the string with type and uri" do + expect(source.to_s).to eq("plugin source for spec_type with uri uri://to/test") + end + end end diff --git a/ruby/spec/bundler/bundler/plugin/dsl_spec.rb b/ruby/spec/bundler/bundler/plugin/dsl_spec.rb index be23db3bb..00e39dca6 100644 --- a/ruby/spec/bundler/bundler/plugin/dsl_spec.rb +++ b/ruby/spec/bundler/bundler/plugin/dsl_spec.rb @@ -28,7 +28,7 @@ expect(dsl.inferred_plugins).to eq(["bundler-source-news"]) end - it "registers a source type plugin only once for multiple declataions" do + it "registers a source type plugin only once for multiple declarations" do expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once dsl.source("some_random_url", :type => "news") {} diff --git a/ruby/spec/bundler/bundler/plugin/index_spec.rb b/ruby/spec/bundler/bundler/plugin/index_spec.rb index e18e960fb..d34b0de34 100644 --- a/ruby/spec/bundler/bundler/plugin/index_spec.rb +++ b/ruby/spec/bundler/bundler/plugin/index_spec.rb @@ -4,7 +4,8 @@ Index = Bundler::Plugin::Index before do - gemfile "" + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + gemfile "source \"#{file_uri_for(gem_repo1)}\"" path = lib_path(plugin_name) index.register_plugin("new-plugin", path.to_s, [path.join("lib").to_s], commands, sources, hooks) end @@ -21,7 +22,7 @@ expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name)) end - it "load_paths is available for retrival" do + it "load_paths is available for retrieval" do expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s]) end @@ -97,7 +98,13 @@ expect(index.hook_plugins("after-bar")).to eq([plugin_name]) end - context "that are not registered", :focused do + it "is gone after unregistration" do + expect(index.index_file.read).to include("after-bar:\n - \"new-plugin\"\n") + index.unregister_plugin(plugin_name) + expect(index.index_file.read).to_not include("after-bar:\n - \n") + end + + context "that are not registered" do let(:file) { double("index-file") } before do @@ -117,11 +124,11 @@ describe "global index" do before do - Dir.chdir(tmp) do - Bundler::Plugin.reset! - path = lib_path("gplugin") - index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], []) - end + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil) + + Bundler::Plugin.reset! + path = lib_path("gplugin") + index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], []) end it "skips sources" do diff --git a/ruby/spec/bundler/bundler/plugin/installer_spec.rb b/ruby/spec/bundler/bundler/plugin/installer_spec.rb index e89720f6f..2c50ee5af 100644 --- a/ruby/spec/bundler/bundler/plugin/installer_spec.rb +++ b/ruby/spec/bundler/bundler/plugin/installer_spec.rb @@ -7,7 +7,7 @@ it "uses Gem.sources when non of the source is provided" do sources = double(:sources) Bundler.settings # initialize it before we have to touch rubygems.ext_lock - allow(Bundler).to receive_message_chain("rubygems.sources") { sources } + allow(Gem).to receive(:sources) { sources } allow(installer).to receive(:install_rubygems). with("new-plugin", [">= 0"], sources).once diff --git a/ruby/spec/bundler/bundler/plugin_spec.rb b/ruby/spec/bundler/bundler/plugin_spec.rb index e0e2e9afd..8a1a6cd97 100644 --- a/ruby/spec/bundler/bundler/plugin_spec.rb +++ b/ruby/spec/bundler/bundler/plugin_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_relative "../support/streams" - RSpec.describe Bundler::Plugin do Plugin = Bundler::Plugin @@ -67,6 +65,8 @@ end it "passes the name and options to installer" do + allow(index).to receive(:installed?). + with("new-plugin") allow(installer).to receive(:install).with(["new-plugin"], opts) do { "new-plugin" => spec } end.once @@ -75,6 +75,8 @@ end it "validates the installed plugin" do + allow(index).to receive(:installed?). + with("new-plugin") allow(subject). to receive(:validate_plugin!).with(lib_path("new-plugin")).once @@ -82,6 +84,8 @@ end it "registers the plugin with index" do + allow(index).to receive(:installed?). + with("new-plugin") allow(index).to receive(:register_plugin). with("new-plugin", lib_path("new-plugin").to_s, [lib_path("new-plugin").join("lib").to_s], []).once subject.install ["new-plugin"], opts @@ -98,6 +102,7 @@ end.once allow(subject).to receive(:validate_plugin!).twice + allow(index).to receive(:installed?).twice allow(index).to receive(:register_plugin).twice subject.install ["new-plugin", "another-plugin"], opts end @@ -107,11 +112,12 @@ describe "evaluate gemfile for plugins" do let(:definition) { double("definition") } let(:builder) { double("builder") } - let(:gemfile) { bundled_app("Gemfile") } + let(:gemfile) { bundled_app_gemfile } before do allow(Plugin::DSL).to receive(:new) { builder } allow(builder).to receive(:eval_gemfile).with(gemfile) + allow(builder).to receive(:check_primary_source_safety) allow(builder).to receive(:to_definition) { definition } allow(builder).to receive(:inferred_plugins) { [] } end @@ -237,7 +243,7 @@ describe "#root" do context "in app dir" do before do - gemfile "" + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end it "returns plugin dir in app .bundle path" do @@ -246,8 +252,11 @@ end context "outside app dir" do + before do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil) + end + it "returns plugin dir in global bundle path" do - Dir.chdir tmp expect(subject.root).to eq(home.join(".bundle/plugin")) end end @@ -275,7 +284,7 @@ Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2") allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1). - and_return(["foo-plugin"]) + and_return(["foo-plugin", "", nil]) allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2). and_return(["foo-plugin"]) allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path) @@ -293,11 +302,9 @@ end it "executes the hook" do - out = capture(:stdout) do + expect do Plugin.hook(Bundler::Plugin::Events::EVENT_1) - end.strip - - expect(out).to eq("hook for event 1") + end.to output("hook for event 1\n").to_stdout end context "single plugin declaring more than one hook" do @@ -308,12 +315,10 @@ RUBY it "evals plugins.rb once" do - out = capture(:stdout) do + expect do Plugin.hook(Bundler::Plugin::Events::EVENT_1) Plugin.hook(Bundler::Plugin::Events::EVENT_2) - end.strip - - expect(out).to eq("loaded") + end.to output("loaded\n").to_stdout end end @@ -323,11 +328,9 @@ RUBY it "is passed to the hook" do - out = capture(:stdout) do + expect do Plugin.hook(Bundler::Plugin::Events::EVENT_1) { puts "win" } - end.strip - - expect(out).to eq("win") + end.to output("win\n").to_stdout end end end diff --git a/ruby/spec/bundler/bundler/psyched_yaml_spec.rb b/ruby/spec/bundler/bundler/psyched_yaml_spec.rb deleted file mode 100644 index d5d68c5cc..000000000 --- a/ruby/spec/bundler/bundler/psyched_yaml_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -require "bundler/psyched_yaml" - -RSpec.describe "Bundler::YamlLibrarySyntaxError" do - it "is raised on YAML parse errors" do - expect { YAML.parse "{foo" }.to raise_error(Bundler::YamlLibrarySyntaxError) - end -end diff --git a/ruby/spec/bundler/bundler/rubygems_integration_spec.rb b/ruby/spec/bundler/bundler/rubygems_integration_spec.rb index 11fa2f4e0..369f28fce 100644 --- a/ruby/spec/bundler/bundler/rubygems_integration_spec.rb +++ b/ruby/spec/bundler/bundler/rubygems_integration_spec.rb @@ -34,21 +34,12 @@ end end - describe "#configuration" do - it "handles Gem::SystemExitException errors" do - allow(Gem).to receive(:configuration) { raise Gem::SystemExitException.new(1) } - expect { Bundler.rubygems.configuration }.to raise_error(Gem::SystemExitException) - end - end - describe "#download_gem" do let(:bundler_retry) { double(Bundler::Retry) } - let(:retry) { double("Bundler::Retry") } - let(:uri) { Bundler::URI.parse("https://foo.bar") } - let(:path) { Gem.path.first } + let(:uri) { Bundler::URI.parse("https://foo.bar") } + let(:cache_dir) { "#{Gem.path.first}/cache" } let(:spec) do - spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"), - Gem::Platform::RUBY, nil) + spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2")) spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s) spec end @@ -56,13 +47,13 @@ it "successfully downloads gem with retries" do expect(Bundler.rubygems).to receive(:gem_remote_fetcher).and_return(fetcher) - expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "https://foo.bar") + expect(fetcher).to receive(:headers=).with({ "X-Gemfile-Source" => "https://foo.bar" }) expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/"). and_return(bundler_retry) expect(bundler_retry).to receive(:attempts).and_yield - expect(fetcher).to receive(:download).with(spec, uri, path) + expect(fetcher).to receive(:cache_update_path) - Bundler.rubygems.download_gem(spec, uri, path) + Bundler.rubygems.download_gem(spec, uri, cache_dir) end end @@ -78,7 +69,7 @@ it "sets the 'X-Gemfile-Source' header containing the original source" do expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher) - expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "http://zombo.com").twice + expect(fetcher).to receive(:headers=).with({ "X-Gemfile-Source" => "http://zombo.com" }).twice expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response) expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response) result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror) diff --git a/ruby/spec/bundler/bundler/settings_spec.rb b/ruby/spec/bundler/bundler/settings_spec.rb index b83d76847..24e3de7ba 100644 --- a/ruby/spec/bundler/bundler/settings_spec.rb +++ b/ruby/spec/bundler/bundler/settings_spec.rb @@ -64,13 +64,10 @@ describe "#global_config_file" do context "when $HOME is not accessible" do - context "when $TMPDIR is not writable" do - it "does not raise" do - expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil) - expect(Bundler).to receive(:tmp).twice.and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler") + it "does not raise" do + expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil) - expect(subject.send(:global_config_file)).to be_nil - end + expect(subject.send(:global_config_file)).to be_nil end end end @@ -130,6 +127,8 @@ describe "#temporary" do it "reset after used" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + Bundler.settings.set_command_option :no_install, true Bundler.settings.temporary(:no_install => false) do @@ -310,16 +309,26 @@ describe "BUNDLE_ keys format" do let(:settings) { described_class.new(bundled_app(".bundle")) } - it "converts older keys without double dashes" do + it "converts older keys without double underscore" do config("BUNDLE_MY__PERSONAL.RACK" => "~/Work/git/rack") expect(settings["my.personal.rack"]).to eq("~/Work/git/rack") end - it "converts older keys without trailing slashes and double dashes" do + it "converts older keys without trailing slashes and double underscore" do config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://rubygems-mirror.org") expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") end + it "converts older keys with dashes" do + config("BUNDLE_MY-PERSONAL-SERVER__ORG" => "my-personal-server.org") + expect(Bundler.ui).to receive(:warn).with( + "Your #{bundled_app(".bundle/config")} config includes `BUNDLE_MY-PERSONAL-SERVER__ORG`, which contains the dash character (`-`).\n" \ + "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ + "Please edit #{bundled_app(".bundle/config")} and replace any dashes in configuration keys with a triple underscore (`___`)." + ) + expect(settings["my-personal-server.org"]).to eq("my-personal-server.org") + end + it "reads newer keys format properly" do config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org") expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") diff --git a/ruby/spec/bundler/bundler/shared_helpers_spec.rb b/ruby/spec/bundler/bundler/shared_helpers_spec.rb index 4530a9a5c..68a24be31 100644 --- a/ruby/spec/bundler/bundler/shared_helpers_spec.rb +++ b/ruby/spec/bundler/bundler/shared_helpers_spec.rb @@ -4,10 +4,13 @@ let(:ext_lock_double) { double(:ext_lock) } before do + pwd_stub allow(Bundler.rubygems).to receive(:ext_lock).and_return(ext_lock_double) allow(ext_lock_double).to receive(:synchronize) {|&block| block.call } end + let(:pwd_stub) { allow(subject).to receive(:pwd).and_return(bundled_app) } + subject { Bundler::SharedHelpers } describe "#default_gemfile" do @@ -77,7 +80,7 @@ let(:global_rubygems_dir) { Pathname.new(bundled_app) } before do - Dir.mkdir ".bundle" + Dir.mkdir bundled_app(".bundle") allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir) end @@ -91,7 +94,7 @@ let(:expected_bundle_dir_path) { Pathname.new("#{bundled_app}/.bundle") } before do - Dir.mkdir ".bundle" + Dir.mkdir bundled_app(".bundle") allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir) end @@ -109,7 +112,8 @@ shared_examples_for "correctly determines whether to return a Gemfile path" do context "currently in directory with a Gemfile" do - before { File.new("Gemfile", "w") } + before { FileUtils.touch(bundled_app_gemfile) } + after { FileUtils.rm(bundled_app_gemfile) } it "returns path of the bundle Gemfile" do expect(subject.in_bundle?).to eq("#{bundled_app}/Gemfile") @@ -147,22 +151,24 @@ describe "#chdir" do let(:op_block) { proc { Dir.mkdir "nested_dir" } } - before { Dir.mkdir "chdir_test_dir" } + before { Dir.mkdir bundled_app("chdir_test_dir") } it "executes the passed block while in the specified directory" do - subject.chdir("chdir_test_dir", &op_block) - expect(Pathname.new("chdir_test_dir/nested_dir")).to exist + subject.chdir(bundled_app("chdir_test_dir"), &op_block) + expect(bundled_app("chdir_test_dir/nested_dir")).to exist end end describe "#pwd" do + let(:pwd_stub) { nil } + it "returns the current absolute path" do - expect(subject.pwd).to eq(bundled_app) + expect(subject.pwd).to eq(source_root) end end describe "#with_clean_git_env" do - let(:with_clean_git_env_block) { proc { Dir.mkdir "with_clean_git_env_test_dir" } } + let(:with_clean_git_env_block) { proc { Dir.mkdir bundled_app("with_clean_git_env_test_dir") } } before do ENV["GIT_DIR"] = "ORIGINAL_ENV_GIT_DIR" @@ -171,20 +177,20 @@ it "executes the passed block" do subject.with_clean_git_env(&with_clean_git_env_block) - expect(Pathname.new("with_clean_git_env_test_dir")).to exist + expect(bundled_app("with_clean_git_env_test_dir")).to exist end context "when a block is passed" do let(:with_clean_git_env_block) do proc do - Dir.mkdir "git_dir_test_dir" unless ENV["GIT_DIR"].nil? - Dir.mkdir "git_work_tree_test_dir" unless ENV["GIT_WORK_TREE"].nil? + Dir.mkdir bundled_app("git_dir_test_dir") unless ENV["GIT_DIR"].nil? + Dir.mkdir bundled_app("git_work_tree_test_dir") unless ENV["GIT_WORK_TREE"].nil? end end it "uses a fresh git env for execution" do subject.with_clean_git_env(&with_clean_git_env_block) - expect(Pathname.new("git_dir_test_dir")).to_not exist - expect(Pathname.new("git_work_tree_test_dir")).to_not exist + expect(bundled_app("git_dir_test_dir")).to_not exist + expect(bundled_app("git_work_tree_test_dir")).to_not exist end end @@ -224,7 +230,7 @@ end shared_examples_for "ENV['PATH'] gets set correctly" do - before { Dir.mkdir ".bundle" } + before { Dir.mkdir bundled_app(".bundle") } it "ensures bundle bin path is in ENV['PATH']" do subject.set_bundle_environment @@ -236,7 +242,7 @@ shared_examples_for "ENV['RUBYOPT'] gets set correctly" do it "ensures -rbundler/setup is at the beginning of ENV['RUBYOPT']" do subject.set_bundle_environment - expect(ENV["RUBYOPT"].split(" ")).to start_with("-r#{lib_dir}/bundler/setup") + expect(ENV["RUBYOPT"].split(" ")).to start_with("-r#{source_lib_dir}/bundler/setup") end end @@ -244,7 +250,7 @@ let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } before do - allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(ruby_lib_path) + allow(subject).to receive(:bundler_ruby_lib).and_return(ruby_lib_path) end it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do @@ -263,7 +269,7 @@ end it "ignores if bundler_ruby_lib is same as rubylibdir" do - allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(RbConfig::CONFIG["rubylibdir"]) + allow(subject).to receive(:bundler_ruby_lib).and_return(RbConfig::CONFIG["rubylibdir"]) subject.set_bundle_environment @@ -422,8 +428,8 @@ let(:file_op_block) { proc {|path| FileUtils.mkdir_p(path) } } it "performs the operation in the passed block" do - subject.filesystem_access("./test_dir", &file_op_block) - expect(Pathname.new("test_dir")).to exist + subject.filesystem_access(bundled_app("test_dir"), &file_op_block) + expect(bundled_app("test_dir")).to exist end end @@ -488,28 +494,4 @@ end end end - - describe "#const_get_safely" do - module TargetNamespace - VALID_CONSTANT = 1 - end - - context "when the namespace does have the requested constant" do - it "returns the value of the requested constant" do - expect(subject.const_get_safely(:VALID_CONSTANT, TargetNamespace)).to eq(1) - end - end - - context "when the requested constant is passed as a string" do - it "returns the value of the requested constant" do - expect(subject.const_get_safely("VALID_CONSTANT", TargetNamespace)).to eq(1) - end - end - - context "when the namespace does not have the requested constant" do - it "returns nil" do - expect(subject.const_get_safely("INVALID_CONSTANT", TargetNamespace)).to be_nil - end - end - end end diff --git a/ruby/spec/bundler/bundler/source/git/git_proxy_spec.rb b/ruby/spec/bundler/bundler/source/git/git_proxy_spec.rb index c18490233..cffd72cc3 100644 --- a/ruby/spec/bundler/bundler/source/git/git_proxy_spec.rb +++ b/ruby/spec/bundler/bundler/source/git/git_proxy_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do let(:path) { Pathname("path") } - let(:uri) { "https://github.com/bundler/bundler.git" } + let(:uri) { "https://github.com/rubygems/rubygems.git" } let(:ref) { "HEAD" } let(:revision) { nil } let(:git_source) { nil } @@ -11,30 +11,30 @@ context "with configured credentials" do it "adds username and password to URI" do Bundler.settings.temporary(uri => "u:p") do - expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) + expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s) subject.checkout end end it "adds username and password to URI for host" do Bundler.settings.temporary("github.com" => "u:p") do - expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) + expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s) subject.checkout end end it "does not add username and password to mismatched URI" do - Bundler.settings.temporary("https://u:p@github.com/bundler/bundler-mismatch.git" => "u:p") do - expect(subject).to receive(:git_retry).with(match(uri)) + Bundler.settings.temporary("https://u:p@github.com/rubygems/rubygems-mismatch.git" => "u:p") do + expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", uri, path.to_s) subject.checkout end end it "keeps original userinfo" do Bundler.settings.temporary("github.com" => "u:p") do - original = "https://orig:info@github.com/bundler/bundler.git" + original = "https://orig:info@github.com/rubygems/rubygems.git" subject = described_class.new(Pathname("path"), original, "HEAD") - expect(subject).to receive(:git_retry).with(match(original)) + expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", original, path.to_s) subject.checkout end end @@ -123,26 +123,49 @@ end describe "#copy_to" do + let(:cache) { tmpdir("cache_path") } let(:destination) { tmpdir("copy_to_path") } let(:submodules) { false } context "when given a SHA as a revision" do let(:revision) { "abcd" * 10 } - let(:command) { "reset --hard #{revision}" } + let(:command) { ["reset", "--hard", revision] } + let(:command_for_display) { "git #{command.shelljoin}" } it "fails gracefully when resetting to the revision fails" do - expect(subject).to receive(:git_retry).with(start_with("clone ")) { destination.mkpath } - expect(subject).to receive(:git_retry).with(start_with("fetch ")) - expect(subject).to receive(:git).with(command).and_raise(Bundler::Source::Git::GitCommandError, command) + expect(subject).to receive(:git_retry).with("clone", any_args) { destination.mkpath } + expect(subject).to receive(:git_retry).with("fetch", any_args, :dir => destination) + expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command_for_display, destination)) expect(subject).not_to receive(:git) expect { subject.copy_to(destination, submodules) }. to raise_error( Bundler::Source::Git::MissingGitRevisionError, - "Git error: command `git #{command}` in directory #{destination} has failed.\n" \ - "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?" \ + "Git error: command `#{command_for_display}` in directory #{destination} has failed.\n" \ + "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?\n" \ + "If this error persists you could try removing the cache directory '#{destination}'" ) end end end + + it "doesn't allow arbitrary code execution through Gemfile uris with a leading dash" do + gemfile <<~G + gem "poc", git: "-u./pay:load.sh" + G + + file = bundled_app("pay:load.sh") + + create_file file, <<~RUBY + #!/bin/sh + + touch #{bundled_app("canary")} + RUBY + + FileUtils.chmod("+x", file) + + bundle :lock, :raise_on_error => false + + expect(Pathname.new(bundled_app("canary"))).not_to exist + end end diff --git a/ruby/spec/bundler/bundler/source/git_spec.rb b/ruby/spec/bundler/bundler/source/git_spec.rb index f7475a35a..ed6dc3cd2 100644 --- a/ruby/spec/bundler/bundler/source/git_spec.rb +++ b/ruby/spec/bundler/bundler/source/git_spec.rb @@ -14,14 +14,59 @@ describe "#to_s" do it "returns a description" do - expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)" + expect(subject.to_s).to eq "https://github.com/foo/bar.git" end context "when the URI contains credentials" do let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" } it "filters credentials" do - expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)" + expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git" + end + end + + context "when the source has a glob specifier" do + let(:glob) { "bar/baz/*.gemspec" } + let(:options) do + { "uri" => uri, "glob" => glob } + end + + it "includes it" do + expect(subject.to_s).to eq "https://github.com/foo/bar.git (glob: bar/baz/*.gemspec)" + end + end + + context "when the source has a reference" do + let(:git_proxy_stub) do + instance_double(Bundler::Source::Git::GitProxy, :revision => "123abc", :branch => "v1.0.0") + end + let(:options) do + { "uri" => uri, "ref" => "v1.0.0" } + end + + before do + allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub) + end + + it "includes it" do + expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc)" + end + end + + context "when the source has both reference and glob specifiers" do + let(:git_proxy_stub) do + instance_double(Bundler::Source::Git::GitProxy, :revision => "123abc", :branch => "v1.0.0") + end + let(:options) do + { "uri" => uri, "ref" => "v1.0.0", "glob" => "gems/foo/*.gemspec" } + end + + before do + allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub) + end + + it "includes both" do + expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc, glob: gems/foo/*.gemspec)" end end end diff --git a/ruby/spec/bundler/bundler/source/rubygems_spec.rb b/ruby/spec/bundler/bundler/source/rubygems_spec.rb index 7c457a726..884fa8104 100644 --- a/ruby/spec/bundler/bundler/source/rubygems_spec.rb +++ b/ruby/spec/bundler/bundler/source/rubygems_spec.rb @@ -30,4 +30,18 @@ end end end + + describe "#no_remotes?" do + context "when no remote provided" do + it "returns a truthy value" do + expect(described_class.new("remotes" => []).no_remotes?).to be_truthy + end + end + + context "when a remote provided" do + it "returns a falsey value" do + expect(described_class.new("remotes" => ["https://rubygems.org"]).no_remotes?).to be_falsey + end + end + end end diff --git a/ruby/spec/bundler/bundler/source_list_spec.rb b/ruby/spec/bundler/bundler/source_list_spec.rb index 93159998c..f860e9ff5 100644 --- a/ruby/spec/bundler/bundler/source_list_spec.rb +++ b/ruby/spec/bundler/bundler/source_list_spec.rb @@ -75,7 +75,7 @@ let(:msg) do "The git source `git://existing-git.org/path.git` " \ "uses the `git` protocol, which transmits data without encryption. " \ - "Disable this warning with `bundle config set git.allow_insecure true`, " \ + "Disable this warning with `bundle config set --local git.allow_insecure true`, " \ "or switch to the `https` protocol to keep your data secure." end @@ -115,15 +115,15 @@ end end - describe "#add_rubygems_remote", :bundler => "< 3" do - let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") } + describe "#add_global_rubygems_remote" do + let!(:returned_source) { source_list.add_global_rubygems_remote("https://rubygems.org/") } it "returns the aggregate rubygems source" do expect(returned_source).to be_instance_of(Bundler::Source::Rubygems) end it "adds the provided remote to the beginning of the aggregate source" do - source_list.add_rubygems_remote("https://othersource.org") + source_list.add_global_rubygems_remote("https://othersource.org") expect(returned_source.remotes).to eq [ Bundler::URI("https://othersource.org/"), Bundler::URI("https://rubygems.org/"), @@ -212,22 +212,22 @@ describe "#path_sources" do it "returns an empty array when no path sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") + source_list.add_global_rubygems_remote("https://rubygems.org") source_list.add_git_source("uri" => "git://host/path.git") expect(source_list.path_sources).to be_empty end it "returns path sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") + source_list.add_global_rubygems_remote("https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") + source_list.add_global_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") + source_list.add_global_rubygems_remote("https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") + source_list.add_global_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") + source_list.add_global_rubygems_remote("https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.path_sources).to eq [ @@ -240,7 +240,7 @@ describe "#git_sources" do it "returns an empty array when no git sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") + source_list.add_global_rubygems_remote("https://rubygems.org") source_list.add_path_source("path" => "/path/to/gem") expect(source_list.git_sources).to be_empty @@ -248,15 +248,15 @@ it "returns git sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") + source_list.add_global_rubygems_remote("https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") + source_list.add_global_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") + source_list.add_global_rubygems_remote("https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") + source_list.add_global_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") + source_list.add_global_rubygems_remote("https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.git_sources).to eq [ @@ -269,7 +269,7 @@ describe "#plugin_sources" do it "returns an empty array when no plugin sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") + source_list.add_global_rubygems_remote("https://rubygems.org") source_list.add_path_source("path" => "/path/to/gem") expect(source_list.plugin_sources).to be_empty @@ -279,13 +279,13 @@ source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git") source_list.add_git_source("https://new-git.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") + source_list.add_global_rubygems_remote("https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") + source_list.add_global_rubygems_remote("https://third-rubygems.org") source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") + source_list.add_global_rubygems_remote("https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") + source_list.add_global_rubygems_remote("https://first-rubygems.org") source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git") expect(source_list.plugin_sources).to eq [ @@ -339,7 +339,7 @@ describe "#get" do context "when it includes an equal source" do let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) } - before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") } + before { @equal_source = source_list.add_global_rubygems_remote("https://rubygems.org") } it "returns the equal source" do expect(source_list.get(rubygems_source)).to be @equal_source @@ -372,26 +372,7 @@ source_list.add_git_source("uri" => "git://first-git.org/path.git") end - it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do - expect(source_list.lock_sources).to eq [ - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - ASourcePlugin.new("uri" => "https://second-plugin.org/random"), - ASourcePlugin.new("uri" => "https://third-bar.org/foo"), - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - Bundler::Source::Rubygems.new("remotes" => [ - "https://duplicate-rubygems.org", - "https://first-rubygems.org", - "https://second-rubygems.org", - "https://third-rubygems.org", - ]), - ] - end - - it "returns all sources, without combining rubygems sources", :bundler => "3" do + it "returns all sources, without combining rubygems sources" do expect(source_list.lock_sources).to eq [ Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), @@ -460,4 +441,19 @@ source_list.remote! end end + + describe "implicit_global_source?" do + context "when a global rubygem source provided" do + it "returns a falsy value" do + source_list.add_global_rubygems_remote("https://rubygems.org") + + expect(source_list.implicit_global_source?).to be_falsey + end + end + context "when no global rubygem source provided" do + it "returns a truthy value" do + expect(source_list.implicit_global_source?).to be_truthy + end + end + end end diff --git a/ruby/spec/bundler/bundler/source_spec.rb b/ruby/spec/bundler/bundler/source_spec.rb index 0c35c27fd..af370bb45 100644 --- a/ruby/spec/bundler/bundler/source_spec.rb +++ b/ruby/spec/bundler/bundler/source_spec.rb @@ -188,7 +188,7 @@ class ExampleSource < Bundler::Source end end -private + private def with_ui(ui) old_ui = Bundler.ui diff --git a/ruby/spec/bundler/bundler/stub_specification_spec.rb b/ruby/spec/bundler/bundler/stub_specification_spec.rb index 7495b5d66..fb612813c 100644 --- a/ruby/spec/bundler/bundler/stub_specification_spec.rb +++ b/ruby/spec/bundler/bundler/stub_specification_spec.rb @@ -1,15 +1,14 @@ # frozen_string_literal: true RSpec.describe Bundler::StubSpecification do - let(:gemspec) do - Gem::Specification.new do |s| + let(:with_bundler_stub_spec) do + gemspec = Gem::Specification.new do |s| s.name = "gemname" s.version = "1.0.0" s.loaded_from = __FILE__ + s.extensions = "ext/gemname" end - end - let(:with_bundler_stub_spec) do described_class.from_stub(gemspec) end @@ -19,4 +18,30 @@ expect(stub).to be(with_bundler_stub_spec) end end + + describe "#manually_installed?" do + it "returns true if installed_by_version is nil or 0" do + stub = described_class.from_stub(with_bundler_stub_spec) + expect(stub.manually_installed?).to be true + end + + it "returns false if installed_by_version is greater than 0" do + stub = described_class.from_stub(with_bundler_stub_spec) + stub.installed_by_version = Gem::Version.new(1) + expect(stub.manually_installed?).to be false + end + end + + describe "#missing_extensions?" do + it "returns false if manually_installed?" do + stub = described_class.from_stub(with_bundler_stub_spec) + expect(stub.missing_extensions?).to be false + end + + it "returns true if not manually_installed?" do + stub = described_class.from_stub(with_bundler_stub_spec) + stub.installed_by_version = Gem::Version.new(1) + expect(stub.missing_extensions?).to be true + end + end end diff --git a/ruby/spec/bundler/bundler/ui/shell_spec.rb b/ruby/spec/bundler/bundler/ui/shell_spec.rb index 536014c6a..15120a8a4 100644 --- a/ruby/spec/bundler/bundler/ui/shell_spec.rb +++ b/ruby/spec/bundler/bundler/ui/shell_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_relative "../../support/streams" - RSpec.describe Bundler::UI::Shell do subject { described_class.new } @@ -43,10 +41,19 @@ context "when stderr is closed" do it "doesn't report anything" do - output = capture(:stderr, :closed => true) do - subject.error("Something went wrong") - end - expect(output).to_not eq("Something went wrong\n") + output = begin + result = StringIO.new + result.close + + $stderr = result + + subject.error("Something went wrong") + + result.string + ensure + $stderr = STDERR + end + expect(output).to_not eq("Something went wrong") end end end diff --git a/ruby/spec/bundler/bundler/worker_spec.rb b/ruby/spec/bundler/bundler/worker_spec.rb index 2e5642709..e4ebbd293 100644 --- a/ruby/spec/bundler/bundler/worker_spec.rb +++ b/ruby/spec/bundler/bundler/worker_spec.rb @@ -19,4 +19,51 @@ end end end + + describe "handling interrupts" do + let(:status) do + pid = Process.fork do + $stderr.reopen File.new("/dev/null", "w") + Signal.trap "INT", previous_interrupt_handler + subject.enq "a" + subject.stop unless interrupt_before_stopping + Process.kill "INT", Process.pid + end + + Process.wait2(pid).last + end + + before do + skip "requires Process.fork" unless Process.respond_to?(:fork) + end + + context "when interrupted before stopping" do + let(:interrupt_before_stopping) { true } + let(:previous_interrupt_handler) { ->(*) { exit 0 } } + + it "aborts" do + expect(status.exitstatus).to eq(1) + end + end + + context "when interrupted after stopping" do + let(:interrupt_before_stopping) { false } + + context "when the previous interrupt handler was the default" do + let(:previous_interrupt_handler) { "DEFAULT" } + + it "uses the default interrupt handler" do + expect(status).to be_signaled + end + end + + context "when the previous interrupt handler was customized" do + let(:previous_interrupt_handler) { ->(*) { exit 42 } } + + it "restores the custom interrupt handler after stopping" do + expect(status.exitstatus).to eq(42) + end + end + end + end end diff --git a/ruby/spec/bundler/cache/gems_spec.rb b/ruby/spec/bundler/cache/gems_spec.rb index 89d6d4157..a8382a5d8 100644 --- a/ruby/spec/bundler/cache/gems_spec.rb +++ b/ruby/spec/bundler/cache/gems_spec.rb @@ -4,11 +4,12 @@ shared_examples_for "when there are only gemsources" do before :each do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' G - system_gems "rack-1.0.0", :path => :bundle_path - bundle! :cache + system_gems "rack-1.0.0", :path => path + bundle :cache end it "copies the .gem file to vendor/cache" do @@ -27,7 +28,7 @@ end it "uses the cache as a source when installing gems with --local" do - system_gems [], :path => :bundle_path + system_gems [], :path => default_bundle_path bundle "install --local" expect(the_bundle).to include_gems("rack 1.0.0") @@ -39,6 +40,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -46,9 +48,10 @@ end it "does not reinstall gems from the cache if they exist in the bundle" do - system_gems "rack-1.0.0", :path => :bundle_path + system_gems "rack-1.0.0", :path => default_bundle_path gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -56,7 +59,7 @@ s.write "lib/rack.rb", "RACK = 'FAIL'" end - bundle! :install, :local => true + bundle :install, :local => true expect(the_bundle).to include_gems("rack 1.0.0") end @@ -64,54 +67,55 @@ cache_gems "rack-1.0.0" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G bundle "cache" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end end context "using system gems" do - before { bundle! "config set path.system true" } + before { bundle "config set path.system true" } + let(:path) { system_gem_path } it_behaves_like "when there are only gemsources" end context "installing into a local path" do - before { bundle! "config set path ./.bundle" } + before { bundle "config set path ./.bundle" } + let(:path) { local_gem_path } it_behaves_like "when there are only gemsources" end - describe "when there is a built-in gem" do + describe "when there is a built-in gem", :ruby_repo do + let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" } + before :each do build_repo2 do - build_gem "builtin_gem", "1.0.2" + build_gem "json", default_json_version end - build_gem "builtin_gem", "1.0.2", :to_system => true do |s| - s.summary = "This builtin_gem is bundled with Ruby" - end - - FileUtils.rm("#{system_gem_path}/cache/builtin_gem-1.0.2.gem") + build_gem "json", default_json_version, :to_system => true, :default => true end it "uses builtin gems when installing to system gems" do - bundle! "config set path.system true" - install_gemfile %(gem 'builtin_gem', '1.0.2') - expect(the_bundle).to include_gems("builtin_gem 1.0.2") + bundle "config set path.system true" + install_gemfile %(source "#{file_uri_for(gem_repo1)}"; gem 'json', '#{default_json_version}'), :verbose => true + expect(out).to include("Using json #{default_json_version}") end it "caches remote and builtin gems" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" - gem 'builtin_gem', '1.0.2' + gem 'json', '#{default_json_version}' gem 'rack', '1.0.0' G bundle :cache expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist - expect(bundled_app("vendor/cache/builtin_gem-1.0.2.gem")).to exist + expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist end it "doesn't make remote request after caching the gem" do @@ -129,15 +133,16 @@ end it "errors if the builtin gem isn't available to cache" do - bundle! "config set path.system true" + bundle "config set path.system true" install_gemfile <<-G - gem 'builtin_gem', '1.0.2' + source "#{file_uri_for(gem_repo1)}" + gem 'json', '#{default_json_version}' G - bundle :cache - expect(exitstatus).to_not eq(0) if exitstatus - expect(err).to include("builtin_gem-1.0.2 is built in to Ruby, and can't be cached") + bundle :cache, :raise_on_error => false + expect(exitstatus).to_not eq(0) + expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached") end end @@ -165,11 +170,11 @@ end it "should not explode if the lockfile is not present" do - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) bundle :cache - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end end @@ -195,7 +200,12 @@ end it "adds and removes when gems are updated" do - update_repo2 + update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + end + bundle "update", :all => true expect(cached_gem("rack-1.2")).to exist expect(cached_gem("rack-1.0.0")).not_to exist @@ -295,6 +305,7 @@ :path => bundled_app("vendor/cache") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo-bundler" G diff --git a/ruby/spec/bundler/cache/git_spec.rb b/ruby/spec/bundler/cache/git_spec.rb index 75525d405..b88993e9b 100644 --- a/ruby/spec/bundler/cache/git_spec.rb +++ b/ruby/spec/bundler/cache/git_spec.rb @@ -18,6 +18,7 @@ ref = git.ref_for("master", 11) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G @@ -31,15 +32,17 @@ expect(the_bundle).to include_gems "foo 1.0" end - it "copies repository to vendor cache and uses it even when installed with bundle --path" do + it "copies repository to vendor cache and uses it even when configured with `path`" do git = build_git "foo" ref = git.ref_for("master", 11) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G - bundle "install --path vendor/bundle" + bundle "config set --local path vendor/bundle" + bundle "install" bundle "config set cache_all true" bundle :cache @@ -53,13 +56,14 @@ it "runs twice without exploding" do build_git "foo" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G bundle "config set cache_all true" - bundle! :cache - bundle! :cache + bundle :cache + bundle :cache expect(out).to include "Updating files in vendor/cache" FileUtils.rm_rf lib_path("foo-1.0") @@ -71,6 +75,7 @@ old_ref = git.ref_for("master", 11) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G @@ -84,15 +89,15 @@ ref = git.ref_for("master", 11) expect(ref).not_to eq(old_ref) - bundle! "update", :all => true + bundle "update", :all => true bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist FileUtils.rm_rf lib_path("foo-1.0") - run! "require 'foo'" + run "require 'foo'" expect(out).to eq("CACHE") end @@ -101,11 +106,12 @@ old_ref = git.ref_for("master", 11) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G bundle "config set cache_all true" - bundle! :cache + bundle :cache update_git "foo" do |s| s.write "lib/foo.rb", "puts :CACHE" @@ -129,6 +135,7 @@ ref = git.ref_for("master", 11) gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master G @@ -155,12 +162,11 @@ s.add_dependency "submodule" end - Dir.chdir(lib_path("has_submodule-1.0")) do - sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0" - `git commit -m "submodulator"` - end + sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0") + sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("has_submodule-1.0")}", :submodules => true do gem "has_submodule" end @@ -175,32 +181,6 @@ expect(the_bundle).to include_gems "has_submodule 1.0" end - it "displays warning message when detecting git repo in Gemfile", :bundler => "< 3" do - build_git "foo" - - install_gemfile <<-G - gem "foo", :git => '#{lib_path("foo-1.0")}' - G - - bundle :cache - - expect(err).to include("Your Gemfile contains path and git dependencies.") - end - - it "does not display warning message if cache_all is set in bundle config" do - build_git "foo" - - install_gemfile <<-G - gem "foo", :git => '#{lib_path("foo-1.0")}' - G - - bundle "config set cache_all true" - bundle :cache - bundle :cache - - expect(err).not_to include("Your Gemfile contains path and git dependencies.") - end - it "caches pre-evaluated gemspecs" do git = build_git "foo" @@ -210,6 +190,7 @@ update_git("foo") {|s| s.write "foo.gemspec", spec_lines.join("\n") } install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G bundle "config set cache_all true" @@ -224,15 +205,16 @@ build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G - bundle! "config set cache_all true" - bundle! :cache, "all-platforms" => true, :install => false, :path => "./vendor/cache" + bundle "config set cache_all true" + bundle :cache, "all-platforms" => true, :install => false simulate_new_machine with_path_as "" do - bundle! "config set deployment true" - bundle! :install, :local => true + bundle "config set deployment true" + bundle :install, :local => true expect(the_bundle).to include_gem "foo 1.0" end end diff --git a/ruby/spec/bundler/cache/path_spec.rb b/ruby/spec/bundler/cache/path_spec.rb index 79e8b4a82..2ad136a00 100644 --- a/ruby/spec/bundler/cache/path_spec.rb +++ b/ruby/spec/bundler/cache/path_spec.rb @@ -5,6 +5,7 @@ build_lib "foo", :path => bundled_app("lib/foo") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{bundled_app("lib/foo")}' G @@ -18,6 +19,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G @@ -26,17 +28,17 @@ expect(bundled_app("vendor/cache/foo-1.0")).to exist expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file - FileUtils.rm_rf lib_path("foo-1.0") expect(the_bundle).to include_gems "foo 1.0" end it "copies when the path is outside the bundle and the paths intersect" do - libname = File.basename(Dir.pwd) + "_gem" - libpath = File.join(File.dirname(Dir.pwd), libname) + libname = File.basename(bundled_app) + "_gem" + libpath = File.join(File.dirname(bundled_app), libname) build_lib libname, :path => libpath install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "#{libname}", :path => '#{libpath}' G @@ -45,7 +47,6 @@ expect(bundled_app("vendor/cache/#{libname}")).to exist expect(bundled_app("vendor/cache/#{libname}/.bundlecache")).to be_file - FileUtils.rm_rf libpath expect(the_bundle).to include_gems "#{libname} 1.0" end @@ -53,6 +54,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G @@ -66,7 +68,6 @@ bundle :cache expect(bundled_app("vendor/cache/foo-1.0")).to exist - FileUtils.rm_rf lib_path("foo-1.0") run "require 'foo'" expect(out).to eq("CACHE") @@ -76,36 +77,57 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G bundle "config set cache_all true" bundle :cache + expect(bundled_app("vendor/cache/foo-1.0")).to exist + + build_lib "bar" + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "bar", :path => '#{lib_path("bar-1.0")}' G bundle :cache - expect(bundled_app("vendor/cache/bar-1.0")).not_to exist + expect(bundled_app("vendor/cache/foo-1.0")).not_to exist end - it "raises a warning without --all", :bundler => "< 3" do + it "does not cache path gems by default", :bundler => "< 3" do build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G bundle :cache - expect(err).to match(/please pass the \-\-all flag/) + expect(err).to be_empty expect(bundled_app("vendor/cache/foo-1.0")).not_to exist end + it "caches path gems by default", :bundler => "3" do + build_lib "foo" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "foo", :path => '#{lib_path("foo-1.0")}' + G + + bundle :cache + expect(err).to be_empty + expect(bundled_app("vendor/cache/foo-1.0")).to exist + end + it "stores the given flag" do build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G @@ -114,6 +136,7 @@ build_lib "bar" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' gem "bar", :path => '#{lib_path("bar-1.0")}' G @@ -126,6 +149,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' G @@ -134,11 +158,12 @@ build_lib "baz" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => '#{lib_path("foo-1.0")}' gem "baz", :path => '#{lib_path("baz-1.0")}' G - bundle "cache --no-all" + bundle "cache --no-all", :raise_on_error => false expect(bundled_app("vendor/cache/baz-1.0")).not_to exist end end diff --git a/ruby/spec/bundler/cache/platform_spec.rb b/ruby/spec/bundler/cache/platform_spec.rb index b65bb06ae..128278956 100644 --- a/ruby/spec/bundler/cache/platform_spec.rb +++ b/ruby/spec/bundler/cache/platform_spec.rb @@ -34,14 +34,14 @@ end it "ensures that a successful bundle install does not delete gems for other platforms" do - bundle! "install" + bundle "install" expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist end it "ensures that a successful bundle update does not delete gems for other platforms" do - bundle! "update", :all => true + bundle "update", :all => true expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist diff --git a/ruby/spec/bundler/commands/add_spec.rb b/ruby/spec/bundler/commands/add_spec.rb index 35fd43d3d..96ea23806 100644 --- a/ruby/spec/bundler/commands/add_spec.rb +++ b/ruby/spec/bundler/commands/add_spec.rb @@ -13,7 +13,7 @@ build_git "foo", "2.0" - install_gemfile <<-G + gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "weakling", "~> 0.0.1" G @@ -21,7 +21,7 @@ context "when no gems are specified" do it "shows error" do - bundle "add" + bundle "add", :raise_on_error => false expect(err).to include("Please specify gems to add") end @@ -30,25 +30,25 @@ describe "without version specified" do it "version requirement becomes ~> major.minor.patch when resolved version is < 1.0" do bundle "add 'bar'" - expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/) + expect(bundled_app_gemfile.read).to match(/gem "bar", "~> 0.12.3"/) expect(the_bundle).to include_gems "bar 0.12.3" end it "version requirement becomes ~> major.minor when resolved version is > 1.0" do bundle "add 'baz'" - expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/) + expect(bundled_app_gemfile.read).to match(/gem "baz", "~> 1.2"/) expect(the_bundle).to include_gems "baz 1.2.3" end it "version requirement becomes ~> major.minor.patch.pre when resolved version is < 1.0" do bundle "add 'cat'" - expect(bundled_app("Gemfile").read).to match(/gem "cat", "~> 0.12.3.pre"/) + expect(bundled_app_gemfile.read).to match(/gem "cat", "~> 0.12.3.pre"/) expect(the_bundle).to include_gems "cat 0.12.3.pre" end it "version requirement becomes ~> major.minor.pre when resolved version is > 1.0.pre" do bundle "add 'dog'" - expect(bundled_app("Gemfile").read).to match(/gem "dog", "~> 1.1.pre"/) + expect(bundled_app_gemfile.read).to match(/gem "dog", "~> 1.1.pre"/) expect(the_bundle).to include_gems "dog 1.1.3.pre" end end @@ -56,28 +56,40 @@ describe "with --version" do it "adds dependency of specified version and runs install" do bundle "add 'foo' --version='~> 1.0'" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 1.0"/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 1.0"/) expect(the_bundle).to include_gems "foo 1.1" end it "adds multiple version constraints when specified" do requirements = ["< 3.0", "> 1.0"] bundle "add 'foo' --version='#{requirements.join(", ")}'" - expect(bundled_app("Gemfile").read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/) + expect(bundled_app_gemfile.read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/) expect(the_bundle).to include_gems "foo 2.0" end end + describe "with --require" do + it "adds the require param for the gem" do + bundle "add 'foo' --require=foo/engine" + expect(bundled_app_gemfile.read).to match(%r{gem "foo",(?: .*,) :require => "foo\/engine"}) + end + + it "converts false to a boolean" do + bundle "add 'foo' --require=false" + expect(bundled_app_gemfile.read).to match(/gem "foo",(?: .*,) :require => false/) + end + end + describe "with --group" do it "adds dependency for the specified group" do bundle "add 'foo' --group='development'" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :group => :development/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :group => :development/) expect(the_bundle).to include_gems "foo 2.0" end it "adds dependency to more than one group" do bundle "add 'foo' --group='development, test'" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :groups => \[:development, :test\]/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :groups => \[:development, :test\]/) expect(the_bundle).to include_gems "foo 2.0" end end @@ -86,16 +98,16 @@ it "adds dependency with specified source" do bundle "add 'foo' --source='#{file_uri_for(gem_repo2)}'" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :source => "#{file_uri_for(gem_repo2)}"/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :source => "#{file_uri_for(gem_repo2)}"/) expect(the_bundle).to include_gems "foo 2.0" end end describe "with --git" do - it "adds dependency with specified github source" do + it "adds dependency with specified git source" do bundle "add foo --git=#{lib_path("foo-2.0")}" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}"/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}"/) expect(the_bundle).to include_gems "foo 2.0" end end @@ -105,78 +117,111 @@ update_git "foo", "2.0", :branch => "test" end - it "adds dependency with specified github source and branch" do + it "adds dependency with specified git source and branch" do bundle "add foo --git=#{lib_path("foo-2.0")} --branch=test" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}", :branch => "test"/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}", :branch => "test"/) expect(the_bundle).to include_gems "foo 2.0" end end + describe "with --git and --ref" do + it "adds dependency with specified git source and branch" do + bundle "add foo --git=#{lib_path("foo-2.0")} --ref=#{revision_for(lib_path("foo-2.0"))}" + + expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2\.0", :git => "#{lib_path("foo-2.0")}", :ref => "#{revision_for(lib_path("foo-2.0"))}"/) + expect(the_bundle).to include_gems "foo 2.0" + end + end + + describe "with --github" do + it "adds dependency with specified github source" do + bundle "add rake --github=ruby/rake" + + expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake"}) + end + end + + describe "with --github and --branch" do + it "adds dependency with specified github source and branch" do + bundle "add rake --github=ruby/rake --branch=master" + + expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake", :branch => "master"}) + end + end + + describe "with --github and --ref" do + it "adds dependency with specified github source and ref" do + bundle "add rake --github=ruby/rake --ref=5c60da8" + + expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake", :ref => "5c60da8"}) + end + end + describe "with --skip-install" do it "adds gem to Gemfile but is not installed" do bundle "add foo --skip-install --version=2.0" - expect(bundled_app("Gemfile").read).to match(/gem "foo", "= 2.0"/) + expect(bundled_app_gemfile.read).to match(/gem "foo", "= 2.0"/) expect(the_bundle).to_not include_gems "foo 2.0" end end it "using combination of short form options works like long form" do bundle "add 'foo' -s='#{file_uri_for(gem_repo2)}' -g='development' -v='~>1.0'" - expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 1.0", :group => :development, :source => "#{file_uri_for(gem_repo2)}") + expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 1.0", :group => :development, :source => "#{file_uri_for(gem_repo2)}") expect(the_bundle).to include_gems "foo 1.1" end it "shows error message when version is not formatted correctly" do - bundle "add 'foo' -v='~>1 . 0'" + bundle "add 'foo' -v='~>1 . 0'", :raise_on_error => false expect(err).to match("Invalid gem requirement pattern '~>1 . 0'") end it "shows error message when gem cannot be found" do bundle "config set force_ruby_platform true" - bundle "add 'werk_it'" + bundle "add 'werk_it'", :raise_on_error => false expect(err).to match("Could not find gem 'werk_it' in") - bundle "add 'werk_it' -s='#{file_uri_for(gem_repo2)}'" + bundle "add 'werk_it' -s='#{file_uri_for(gem_repo2)}'", :raise_on_error => false expect(err).to match("Could not find gem 'werk_it' in rubygems repository") end it "shows error message when source cannot be reached" do - bundle "add 'baz' --source='http://badhostasdf'" + bundle "add 'baz' --source='http://badhostasdf'", :raise_on_error => false expect(err).to include("Could not reach host badhostasdf. Check your network connection and try again.") - bundle "add 'baz' --source='file://does/not/exist'" + bundle "add 'baz' --source='file://does/not/exist'", :raise_on_error => false expect(err).to include("Could not fetch specs from file://does/not/exist/") end describe "with --optimistic" do it "adds optimistic version" do - bundle! "add 'foo' --optimistic" - expect(bundled_app("Gemfile").read).to include %(gem "foo", ">= 2.0") + bundle "add 'foo' --optimistic" + expect(bundled_app_gemfile.read).to include %(gem "foo", ">= 2.0") expect(the_bundle).to include_gems "foo 2.0" end end describe "with --strict option" do it "adds strict version" do - bundle! "add 'foo' --strict" - expect(bundled_app("Gemfile").read).to include %(gem "foo", "= 2.0") + bundle "add 'foo' --strict" + expect(bundled_app_gemfile.read).to include %(gem "foo", "= 2.0") expect(the_bundle).to include_gems "foo 2.0" end end describe "with no option" do it "adds pessimistic version" do - bundle! "add 'foo'" - expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 2.0") + bundle "add 'foo'" + expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 2.0") expect(the_bundle).to include_gems "foo 2.0" end end describe "with --optimistic and --strict" do it "throws error" do - bundle "add 'foo' --strict --optimistic" + bundle "add 'foo' --strict --optimistic", :raise_on_error => false expect(err).to include("You can not specify `--strict` and `--optimistic` at the same time") end @@ -184,14 +229,14 @@ context "multiple gems" do it "adds multiple gems to gemfile" do - bundle! "add bar baz" + bundle "add bar baz" - expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/) - expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/) + expect(bundled_app_gemfile.read).to match(/gem "bar", "~> 0.12.3"/) + expect(bundled_app_gemfile.read).to match(/gem "baz", "~> 1.2"/) end it "throws error if any of the specified gems are present in the gemfile with different version" do - bundle "add weakling bar" + bundle "add weakling bar", :raise_on_error => false expect(err).to include("You cannot specify the same gem twice with different version requirements") expect(err).to include("You specified: weakling (~> 0.0.1) and weakling (>= 0).") @@ -205,7 +250,7 @@ gem "rack", "1.0" G - bundle "add 'rack' --version=1.1" + bundle "add 'rack' --version=1.1", :raise_on_error => false expect(err).to include("You cannot specify the same gem twice with different version requirements") expect(err).to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive") @@ -217,7 +262,7 @@ gem "rack", "1.0" G - bundle "add 'rack'" + bundle "add 'rack'", :raise_on_error => false expect(err).to include("Gem already added.") expect(err).to include("You cannot specify the same gem twice with different version requirements") @@ -232,7 +277,7 @@ gem "rack" G - bundle "add 'rack' --version=1.1" + bundle "add 'rack' --version=1.1", :raise_on_error => false expect(err).to include("You cannot specify the same gem twice with different version requirements") expect(err).to include("If you want to update the gem version, run `bundle update rack`.") @@ -242,7 +287,7 @@ describe "when a gem is added and cache exists" do it "caches all new dependencies added for the specified gem" do - bundle! :cache + bundle :cache bundle "add 'rack' --version=1.0.0" expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist diff --git a/ruby/spec/bundler/commands/binstubs_spec.rb b/ruby/spec/bundler/commands/binstubs_spec.rb index 7c04e8ddb..198226207 100644 --- a/ruby/spec/bundler/commands/binstubs_spec.rb +++ b/ruby/spec/bundler/commands/binstubs_spec.rb @@ -40,25 +40,37 @@ end it "allows installing all binstubs" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rails" G - bundle! :binstubs, :all => true + bundle :binstubs, :all => true expect(bundled_app("bin/rails")).to exist expect(bundled_app("bin/rake")).to exist end + it "allows installing binstubs for all platforms" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle "binstubs rack --all-platforms" + + expect(bundled_app("bin/rackup")).to exist + expect(bundled_app("bin/rackup.cmd")).to exist + end + it "displays an error when used without any gem" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "binstubs" - expect(exitstatus).to eq(1) if exitstatus + bundle "binstubs", :raise_on_error => false + expect(exitstatus).to eq(1) expect(err).to include("`bundle binstubs` needs at least one gem to run.") end @@ -68,7 +80,7 @@ gem "rack" G - bundle "binstubs rack", :all => true + bundle "binstubs rack", :all => true, :raise_on_error => false expect(last_command).to be_failure expect(err).to include("Cannot specify --all with specific gems") end @@ -82,11 +94,11 @@ bundle "binstubs rack" - File.open("bin/bundle", "wb") do |file| + File.open(bundled_app("bin/bundle"), "wb") do |file| file.print "OMG" end - sys_exec "bin/rackup" + sys_exec "bin/rackup", :raise_on_error => false expect(err).to include("was not generated by Bundler") end @@ -94,49 +106,49 @@ context "the bundle binstub" do before do - if system_bundler_version == :bundler - system_gems :bundler - elsif system_bundler_version - build_repo4 do - build_gem "bundler", system_bundler_version do |s| - s.executables = "bundle" - s.bindir = "exe" - s.write "exe/bundle", "puts %(system bundler #{system_bundler_version}\\n\#{ARGV.inspect})" - end - end - system_gems "bundler-#{system_bundler_version}", :gem_repo => gem_repo4 - end + pristine_system_gems "bundler-#{system_bundler_version}" build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "prints_loaded_gems", "1.0" do |s| s.executables = "print_loaded_gems" s.bindir = "exe" s.write "exe/print_loaded_gems", <<-R - specs = Gem.loaded_specs.values.reject {|s| Bundler.rubygems.spec_default_gem?(s) } + specs = Gem.loaded_specs.values.reject {|s| s.default_gem? } puts specs.map(&:full_name).sort.inspect R end end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rack" gem "prints_loaded_gems" G - bundle! "binstubs bundler rack prints_loaded_gems" + bundle "binstubs bundler rack prints_loaded_gems" end let(:system_bundler_version) { Bundler::VERSION } it "runs bundler" do - sys_exec! "#{bundled_app("bin/bundle")} install" - expect(out).to eq %(system bundler #{system_bundler_version}\n["install"]) + sys_exec "bin/bundle install", :env => { "DEBUG" => "1" } + expect(out).to include %(Using bundler #{system_bundler_version}\n) end context "when BUNDLER_VERSION is set" do it "runs the correct version of bundler" do - sys_exec "#{bundled_app("bin/bundle")} install", "BUNDLER_VERSION" => "999.999.999" - expect(exitstatus).to eq(42) if exitstatus - expect(err).to include("Activating bundler (~> 999.999) failed:"). - and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`") + sys_exec "bin/bundle install", :env => { "BUNDLER_VERSION" => "999.999.999" }, :raise_on_error => false + expect(exitstatus).to eq(42) + expect(err).to include("Activating bundler (999.999.999) failed:"). + and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`") + end + + it "runs the correct version of bundler even if a higher version is installed" do + system_gems "bundler-999.999.998", "bundler-999.999.999" + + sys_exec "bin/bundle install", :env => { "BUNDLER_VERSION" => "999.999.998", "DEBUG" => "1" }, :raise_on_error => false + expect(out).to include %(Using bundler 999.999.998\n) end end @@ -147,8 +159,8 @@ end it "runs the correct version of bundler" do - sys_exec "#{bundled_app("bin/bundle")} install" - expect(exitstatus).to eq(42) if exitstatus + sys_exec "bin/bundle install", :raise_on_error => false + expect(exitstatus).to eq(42) expect(err).to include("Activating bundler (~> 999.999) failed:"). and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`") end @@ -162,24 +174,34 @@ end it "runs the correct version of bundler" do - sys_exec "#{bundled_app("bin/bundle")} install" - expect(exitstatus).to eq(42) if exitstatus + sys_exec "bin/bundle install", :raise_on_error => false + expect(exitstatus).to eq(42) expect(err).to include("Activating bundler (~> 44.0) failed:"). and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 44.0'`") end end context "and the version is older and the same major" do - let(:system_bundler_version) { "55.1" } + let(:system_bundler_version) { "2.999.999" } before do - lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 55.0") + lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 2.3.0") + end + + it "installs and runs the exact version of bundler", :rubygems => ">= 3.3.0.dev" do + sys_exec "bin/bundle install --verbose", :artifice => "vcr" + expect(exitstatus).not_to eq(42) + expect(out).to include("Bundler 2.999.999 is running, but your lockfile was generated with 2.3.0. Installing Bundler 2.3.0 and restarting using that version.") + expect(out).to include("Using bundler 2.3.0") + expect(err).not_to include("Activating bundler (~> 2.3.0) failed:") end - it "runs the available version of bundler when the version is older and the same major" do - sys_exec "#{bundled_app("bin/bundle")} install" - expect(exitstatus).not_to eq(42) if exitstatus - expect(err).not_to include("Activating bundler (~> 55.0) failed:") + it "runs the available version of bundler", :rubygems => "< 3.3.0.dev" do + sys_exec "bin/bundle install --verbose" + expect(exitstatus).not_to eq(42) + expect(out).not_to include("Bundler 2.999.999 is running, but your lockfile was generated with 2.3.0. Installing Bundler 2.3.0 and restarting using that version.") + expect(out).to include("Using bundler 2.999.999") + expect(err).not_to include("Activating bundler (~> 2.3.0) failed:") end end @@ -191,8 +213,8 @@ end it "runs the correct version of bundler when the version is a pre-release" do - sys_exec "#{bundled_app("bin/bundle")} install" - expect(exitstatus).to eq(42) if exitstatus + sys_exec "bin/bundle install", :raise_on_error => false + expect(exitstatus).to eq(42) expect(err).to include("Activating bundler (~> 2.12.a) failed:"). and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 2.12.a'`") end @@ -203,30 +225,29 @@ before { lockfile.gsub(system_bundler_version, "1.1.1") } it "calls through to the latest bundler version" do - sys_exec! "#{bundled_app("bin/bundle")} update --bundler" - expect(out).to eq %(system bundler #{system_bundler_version}\n["update", "--bundler"]) + sys_exec "bin/bundle update --bundler", :env => { "DEBUG" => "1" } + expect(out).to include %(Using bundler #{system_bundler_version}\n) end it "calls through to the explicit bundler version" do - sys_exec "#{bundled_app("bin/bundle")} update --bundler=999.999.999" - expect(exitstatus).to eq(42) if exitstatus - expect(err).to include("Activating bundler (~> 999.999) failed:"). - and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`") + sys_exec "bin/bundle update --bundler=999.999.999", :raise_on_error => false + expect(exitstatus).to eq(42) + expect(err).to include("Activating bundler (999.999.999) failed:"). + and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`") end end context "without a lockfile" do it "falls back to the latest installed bundler" do - FileUtils.rm bundled_app("Gemfile.lock") - sys_exec! bundled_app("bin/bundle").to_s - expect(out).to eq "system bundler #{system_bundler_version}\n[]" + FileUtils.rm bundled_app_lock + sys_exec "bin/bundle install", :env => { "DEBUG" => "1" } + expect(out).to include "Using bundler #{system_bundler_version}\n" end end context "using another binstub" do - let(:system_bundler_version) { :bundler } it "loads all gems" do - sys_exec! bundled_app("bin/print_loaded_gems").to_s + sys_exec bundled_app("bin/print_loaded_gems").to_s expect(out).to eq %(["bundler-#{Bundler::VERSION}", "prints_loaded_gems-1.0", "rack-1.2"]) end @@ -234,8 +255,8 @@ before { lockfile lockfile.gsub(Bundler::VERSION, "999.999.999") } it "attempts to load that version" do - sys_exec bundled_app("bin/rackup").to_s - expect(exitstatus).to eq(42) if exitstatus + sys_exec bundled_app("bin/rackup").to_s, :raise_on_error => false + expect(exitstatus).to eq(42) expect(err).to include("Activating bundler (~> 999.999) failed:"). and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`") end @@ -250,6 +271,7 @@ s.executables = %w[foo] end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo")}" G @@ -265,6 +287,7 @@ s.executables = %w[foo] end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo")}" G @@ -282,7 +305,7 @@ bundle "binstubs rack" binary = bundled_app("bin/rackup") - expect(File.stat(binary).mode.to_s(8)).to eq("100775") + expect(File.stat(binary).mode.to_s(8)).to eq(Gem.win_platform? ? "100644" : "100775") end end @@ -294,8 +317,7 @@ G bundle "binstubs rack --shebang jruby" - - expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env jruby\n") + expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env jruby\n") end end end @@ -306,9 +328,9 @@ source "#{file_uri_for(gem_repo1)}" G - bundle "binstubs doesnt_exist" + bundle "binstubs doesnt_exist", :raise_on_error => false - expect(exitstatus).to eq(7) if exitstatus + expect(exitstatus).to eq(7) expect(err).to include("Could not find gem 'doesnt_exist'.") end end @@ -332,8 +354,8 @@ gem "rails" G - bundle! "binstubs rack", :path => "exec" - bundle! :install + bundle "binstubs rack", :path => "exec" + bundle :install expect(bundled_app("exec/rails")).to exist end @@ -348,21 +370,29 @@ end it "generates a standalone binstub" do - bundle! "binstubs rack --standalone" + bundle "binstubs rack --standalone" expect(bundled_app("bin/rackup")).to exist end it "generates a binstub that does not depend on rubygems or bundler" do - bundle! "binstubs rack --standalone" + bundle "binstubs rack --standalone" expect(File.read(bundled_app("bin/rackup"))).to_not include("Gem.bin_path") end context "when specified --path option" do it "generates a standalone binstub at the given path" do - bundle! "binstubs rack --standalone --path foo" + bundle "binstubs rack --standalone --path foo" expect(bundled_app("foo/rackup")).to exist end end + + context "when specified --all-platforms option" do + it "generates standalone binstubs for all platforms" do + bundle "binstubs rack --standalone --all-platforms" + expect(bundled_app("bin/rackup")).to exist + expect(bundled_app("bin/rackup.cmd")).to exist + end + end end context "when the bin already exists" do @@ -428,8 +458,14 @@ end it "works if the gem has development dependencies" do + build_repo2 do + build_gem "with_development_dependency" do |s| + s.add_development_dependency "activesupport", "= 2.3.5" + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "with_development_dependency" G diff --git a/ruby/spec/bundler/commands/cache_spec.rb b/ruby/spec/bundler/commands/cache_spec.rb index 07ec186c2..356a658e7 100644 --- a/ruby/spec/bundler/commands/cache_spec.rb +++ b/ruby/spec/bundler/commands/cache_spec.rb @@ -1,6 +1,19 @@ # frozen_string_literal: true RSpec.describe "bundle cache" do + it "doesn't update the cache multiple times, even if it already exists" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle :cache + expect(out).to include("Updating files in vendor/cache").once + + bundle :cache + expect(out).to include("Updating files in vendor/cache").once + end + context "with --gemfile" do it "finds the gemfile" do gemfile bundled_app("NotGemfile"), <<-G @@ -56,7 +69,7 @@ D bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist @@ -88,7 +101,7 @@ D bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist @@ -133,7 +146,7 @@ D bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist @@ -152,7 +165,7 @@ gem 'rack' D - bundle! :cache, forgotten_command_line_options(:path => bundled_app("test")) + bundle "cache --path #{bundled_app("test")}" expect(the_bundle).to include_gems "rack 1.0.0" expect(bundled_app("test/vendor/cache/")).to exist @@ -166,7 +179,7 @@ gem 'rack' D - bundle! "cache --no-install" + bundle "cache --no-install" expect(the_bundle).not_to include_gems "rack 1.0.0" expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist @@ -178,8 +191,8 @@ gem 'rack' D - bundle! "cache --no-install" - bundle! "install" + bundle "cache --no-install" + bundle "install" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -190,8 +203,8 @@ gem "rack", "1.0.0" D - bundle! "cache --no-install" - bundle! "update --all" + bundle "cache --no-install" + bundle "update --all" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -201,7 +214,7 @@ it "puts the gems in vendor/cache even for other rubies" do gemfile <<-D source "#{file_uri_for(gem_repo1)}" - gem 'rack', :platforms => :ruby_19 + gem 'rack', :platforms => [:ruby_20, :x64_mingw_20] D bundle "cache --all-platforms" @@ -217,28 +230,45 @@ end end - install_gemfile! <<-G, forgotten_command_line_options(:without => "wo") - source "file:#{gem_repo1}" + bundle "config set --local without wo" + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" group :wo do gem "weakling" - gem "uninstallable", :source => "file:#{gem_repo4}" + gem "uninstallable", :source => "#{file_uri_for(gem_repo4)}" end G - bundle! :cache, "all-platforms" => true + bundle :cache, "all-platforms" => true expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist expect(bundled_app("vendor/cache/uninstallable-2.0.gem")).to exist expect(the_bundle).to include_gem "rack 1.0" expect(the_bundle).not_to include_gems "weakling", "uninstallable" - bundle! :install, forgotten_command_line_options(:without => "wo") + bundle "config set --local without wo" + bundle :install expect(the_bundle).to include_gem "rack 1.0" expect(the_bundle).not_to include_gems "weakling", "uninstallable" end + + it "does not fail to cache gems in excluded groups when there's a lockfile but gems not previously installed" do + bundle "config set --local without wo" + gemfile <<-G + source "https://my.gem.repo.1" + gem "rack" + group :wo do + gem "weakling" + end + G + + bundle :lock, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s } + bundle :cache, "all-platforms" => true, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s } + expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist + end end - context "with --frozen" do + context "with frozen configured" do before do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -247,17 +277,20 @@ bundle "install" end - subject { bundle :cache, forgotten_command_line_options(:frozen => true) } + subject do + bundle "config set --local frozen true" + bundle :cache, :raise_on_error => false + end it "tries to install with frozen" do - bundle! "config set deployment true" + bundle "config set deployment true" gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" gem "rack-obama" G subject - expect(exitstatus).to eq(16) if exitstatus + expect(exitstatus).to eq(16) expect(err).to include("deployment mode") expect(err).to include("You have added to the Gemfile") expect(err).to include("* rack-obama") @@ -265,6 +298,30 @@ expect(out).to include("frozen").or include("deployment") end end + + context "with gems with extensions" do + before do + build_repo2 do + build_gem "racc", "2.0" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", "task(:default) { puts 'INSTALLING rack' }" + end + end + + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + + gem "racc" + G + end + + it "installs them properly from cache to a different path" do + bundle "cache" + bundle "config set --local path vendor/bundle" + bundle "install --local" + end + end end RSpec.describe "bundle install with gem sources" do @@ -284,18 +341,38 @@ expect(the_bundle).to include_gems "rack 1.0.0" end - it "does not hit the remote at all" do + it "does not hit the remote at all in frozen mode" do + build_repo2 + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "rack" + G + + bundle :cache + simulate_new_machine + FileUtils.rm_rf gem_repo2 + + bundle "config set --local deployment true" + bundle "config set --local path vendor/bundle" + bundle :install + expect(the_bundle).to include_gems "rack 1.0.0" + end + + it "does not hit the remote at all when cache_all_platforms configured" do build_repo2 - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rack" G - bundle! :cache + bundle :cache simulate_new_machine FileUtils.rm_rf gem_repo2 - bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle") + bundle "config set --local cache_all_platforms true" + bundle "config set --local path vendor/bundle" + bundle "install --local" + expect(out).not_to include("Fetching gem metadata") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -326,14 +403,14 @@ simulate_new_machine - simulate_platform "ruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "platform_specific" - G - run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" - expect(out).to eq("1.0.0 RUBY") - end + bundle "config set --local force_ruby_platform true" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" + G + run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" + expect(out).to eq("1.0.0 RUBY") end it "does not update the cache if --no-cache is passed" do diff --git a/ruby/spec/bundler/commands/check_spec.rb b/ruby/spec/bundler/commands/check_spec.rb index c755ef280..e0c9a04c2 100644 --- a/ruby/spec/bundler/commands/check_spec.rb +++ b/ruby/spec/bundler/commands/check_spec.rb @@ -8,7 +8,6 @@ G bundle :check - expect(exitstatus).to eq(0) if exitstatus expect(out).to include("The Gemfile's dependencies are satisfied") end @@ -18,8 +17,7 @@ gem "rails" G - Dir.chdir tmp - bundle "check --gemfile bundled_app/Gemfile" + bundle "check --gemfile bundled_app/Gemfile", :dir => tmp expect(out).to include("The Gemfile's dependencies are satisfied") end @@ -29,11 +27,11 @@ gem "rails" G - FileUtils.rm("Gemfile.lock") + FileUtils.rm(bundled_app_lock) bundle "check" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "does not create a Gemfile.lock if --dry-run was passed" do @@ -42,11 +40,11 @@ gem "rails" G - FileUtils.rm("Gemfile.lock") + FileUtils.rm(bundled_app_lock) bundle "check --dry-run" - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist end it "prints a generic error if the missing gems are unresolvable" do @@ -57,7 +55,7 @@ gem "rails" G - bundle :check + bundle :check, :raise_on_error => false expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.") end @@ -67,28 +65,30 @@ gem "rails" G - bundle :check - expect(exitstatus).to be > 0 if exitstatus + bundle :check, :raise_on_error => false + expect(exitstatus).to be > 0 expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.") end it "prints a generic message if you changed your lockfile" do + build_repo2 do + build_gem "rails_pinned_to_old_activesupport" do |s| + s.add_dependency "activesupport", "= 1.2.3" + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem 'rails' G - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem 'rails_fail' - G gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rails" - gem "rails_fail" + gem "rails_pinned_to_old_activesupport" G - bundle :check + bundle :check, :raise_on_error => false expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.") end @@ -100,21 +100,21 @@ end G - bundle! "install --without foo" - bundle! "check" + bundle "install --without foo" + bundle "check" expect(out).to include("The Gemfile's dependencies are satisfied") end it "uses the without setting" do - bundle! "config set without foo" - install_gemfile! <<-G + bundle "config set without foo" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" group :foo do gem "rack" end G - bundle! "check" + bundle "check" expect(out).to include("The Gemfile's dependencies are satisfied") end @@ -124,16 +124,33 @@ gem "rack", :group => :foo G - bundle :install, forgotten_command_line_options(:without => "foo") + bundle "config set --local without foo" + bundle :install gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "check" + bundle "check", :raise_on_error => false + expect(err).to include("* rack (1.0.0)") + expect(exitstatus).to eq(1) + end + + it "ensures that gems are actually installed and not just cached in applications' cache" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle "config set --local path vendor/bundle" + bundle :cache + + gem_command "uninstall rack", :env => { "GEM_HOME" => vendored_gems.to_s } + + bundle "check", :raise_on_error => false expect(err).to include("* rack (1.0.0)") - expect(exitstatus).to eq(1) if exitstatus + expect(exitstatus).to eq(1) end it "ignores missing gems restricted to other platforms" do @@ -145,7 +162,7 @@ end G - system_gems "rack-1.0.0", :path => :bundle_path + system_gems "rack-1.0.0", :path => default_bundle_path lockfile <<-G GEM @@ -176,7 +193,7 @@ end G - system_gems "rack-1.0.0", :path => :bundle_path + system_gems "rack-1.0.0", :path => default_bundle_path lockfile <<-G GEM @@ -199,42 +216,28 @@ end it "outputs an error when the default Gemfile is not found" do - bundle :check - expect(exitstatus).to eq(10) if exitstatus + bundle :check, :raise_on_error => false + expect(exitstatus).to eq(10) expect(err).to include("Could not locate Gemfile") end it "does not output fatal error message" do - bundle :check - expect(exitstatus).to eq(10) if exitstatus + bundle :check, :raise_on_error => false + expect(exitstatus).to eq(10) expect(err).not_to include("Unfortunately, a fatal error has occurred. ") end - it "should not crash when called multiple times on a new machine" do - gemfile <<-G - gem 'rails', '3.0.0.beta3' - gem 'paperclip', :git => 'git://github.com/thoughtbot/paperclip.git' - G - - simulate_new_machine - bundle "check" - last_out = out - 3.times do - bundle :check - expect(out).to eq(last_out) - end - end - it "fails when there's no lock file and frozen is set" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "foo" G - bundle! "install", forgotten_command_line_options(:deployment => true) - FileUtils.rm(bundled_app("Gemfile.lock")) + bundle "config set --local deployment true" + bundle "install" + FileUtils.rm(bundled_app_lock) - bundle :check + bundle :check, :raise_on_error => false expect(last_command).to be_failure end @@ -251,13 +254,13 @@ end it "returns success" do - bundle! "check --path vendor/bundle" + bundle "check --path vendor/bundle" expect(out).to include("The Gemfile's dependencies are satisfied") end it "should write to .bundle/config" do bundle "check --path vendor/bundle" - bundle! "check" + bundle "check" end end @@ -268,11 +271,11 @@ gem "rails" G - bundle "check --path vendor/bundle" + bundle "check --path vendor/bundle", :raise_on_error => false end it "returns false" do - expect(exitstatus).to eq(1) if exitstatus + expect(exitstatus).to eq(1) expect(err).to match(/The following gems are missing/) end end @@ -290,21 +293,147 @@ it "returns success when the Gemfile is satisfied" do bundle :install bundle :check - expect(exitstatus).to eq(0) if exitstatus expect(out).to include("The Gemfile's dependencies are satisfied") end it "shows what is missing with the current Gemfile if it is not satisfied" do simulate_new_machine - bundle :check + bundle :check, :raise_on_error => false expect(err).to match(/The following gems are missing/) expect(err).to include("* rack (1.0") end end + describe "when locked with multiple dependents with different requirements" do + before :each do + build_repo4 do + build_gem "depends_on_rack" do |s| + s.add_dependency "rack", ">= 1.0" + end + build_gem "also_depends_on_rack" do |s| + s.add_dependency "rack", "~> 1.0" + end + build_gem "rack" + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "depends_on_rack" + gem "also_depends_on_rack" + G + + bundle "lock" + end + + it "shows what is missing with the current Gemfile without duplications" do + bundle :check, :raise_on_error => false + expect(err).to match(/The following gems are missing/) + expect(err).to include("* rack (1.0").once + end + end + + describe "when locked under multiple platforms" do + before :each do + build_repo4 do + build_gem "rack" + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + ruby + #{specific_local_platform} + + DEPENDENCIES + rack + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "shows what is missing with the current Gemfile without duplications" do + bundle :check, :raise_on_error => false + expect(err).to match(/The following gems are missing/) + expect(err).to include("* rack (1.0").once + end + end + + describe "when using only scoped rubygems sources" do + before do + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + source "#{file_uri_for(gem_repo1)}" do + gem "rack" + end + G + end + + it "returns success when the Gemfile is satisfied" do + system_gems "rack-1.0.0", :path => default_bundle_path + bundle :check + expect(out).to include("The Gemfile's dependencies are satisfied") + end + end + + describe "when using only scoped rubygems sources with indirect dependencies" do + before do + build_repo4 do + build_gem "depends_on_rack" do |s| + s.add_dependency "rack" + end + + build_gem "rack" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo4)}" do + gem "depends_on_rack" + end + G + end + + it "returns success when the Gemfile is satisfied and generates a correct lockfile" do + system_gems "depends_on_rack-1.0", "rack-1.0", :gem_repo => gem_repo4, :path => default_bundle_path + bundle :check + expect(out).to include("The Gemfile's dependencies are satisfied") + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + depends_on_rack (1.0) + rack + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + depends_on_rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + describe "BUNDLED WITH" do def lock_with(bundler_version = nil) - lock = <<-L + lock = <<~L GEM remote: #{file_uri_for(gem_repo1)}/ specs: @@ -318,13 +447,15 @@ def lock_with(bundler_version = nil) L if bundler_version - lock += "\n BUNDLED WITH\n #{bundler_version}\n" + lock += "\nBUNDLED WITH\n #{bundler_version}\n" end lock end before do + bundle "config set --local path vendor/bundle" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -335,24 +466,25 @@ def lock_with(bundler_version = nil) it "does not change the lock" do lockfile lock_with(nil) bundle :check - lockfile_should_be lock_with(nil) + expect(lockfile).to eq lock_with(nil) end end context "is newer" do - it "does not change the lock but warns" do + it "does not change the lock and does not warn" do lockfile lock_with(Bundler::VERSION.succ) - bundle! :check - expect(err).to include("the running version of Bundler (#{Bundler::VERSION}) is older than the version that created the lockfile (#{Bundler::VERSION.succ})") - lockfile_should_be lock_with(Bundler::VERSION.succ) + bundle :check + expect(err).to be_empty + expect(lockfile).to eq lock_with(Bundler::VERSION.succ) end end context "is older" do it "does not change the lock" do - lockfile lock_with("1.10.1") + system_gems "bundler-1.18.0" + lockfile lock_with("1.18.0") bundle :check - lockfile_should_be lock_with("1.10.1") + expect(lockfile).to eq lock_with("1.18.0") end end end diff --git a/ruby/spec/bundler/commands/clean_spec.rb b/ruby/spec/bundler/commands/clean_spec.rb index 5cc97de91..576872b0f 100644 --- a/ruby/spec/bundler/commands/clean_spec.rb +++ b/ruby/spec/bundler/commands/clean_spec.rb @@ -27,16 +27,16 @@ def should_not_have_gems(*gems) bundle "config set path vendor/bundle" bundle "config set clean false" - bundle! "install" + bundle "install" gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "thin" G - bundle! "install" + bundle "install" - bundle! :clean + bundle :clean expect(out).to include("Removing foo (1.0)") @@ -86,7 +86,7 @@ def should_not_have_gems(*gems) bundle "config set path vendor/bundle" bundle "config set clean false" - bundle! "install" + bundle "install" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -94,9 +94,9 @@ def should_not_have_gems(*gems) gem "rack", "0.9.1" gem "foo" G - bundle! "update rack" + bundle "update rack" - bundle! :clean + bundle :clean expect(out).to include("Removing rack (1.0.0)") @@ -199,7 +199,7 @@ def should_not_have_gems(*gems) revision = revision_for(git_path) gemfile <<-G - source "file://#{gem_repo1}" + source "#{file_uri_for(gem_repo1)}" gem "rack", "1.0.0" git "#{git_path}", :ref => "#{revision}" do @@ -234,13 +234,13 @@ def should_not_have_gems(*gems) G bundle "config set path vendor/bundle" - bundle! "install" + bundle "install" - update_git "foo", :path => lib_path("foo-bar") + update_git "foo-bar", :path => lib_path("foo-bar") revision2 = revision_for(lib_path("foo-bar")) - bundle! "update", :all => true - bundle! :clean + bundle "update", :all => true + bundle :clean expect(out).to include("Removing foo-bar (#{revision[0..11]})") @@ -261,6 +261,7 @@ def should_not_have_gems(*gems) revision = revision_for(lib_path("rails")) gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "activesupport", :git => "#{lib_path("rails")}", :ref => '#{revision}' G @@ -315,20 +316,19 @@ def should_not_have_gems(*gems) bundle "install" bundle :clean - expect(exitstatus).to eq(0) if exitstatus end it "displays an error when used without --path" do - bundle! "config set path.system true" + bundle "config set path.system true" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", "1.0.0" G - bundle :clean + bundle :clean, :raise_on_error => false - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) expect(err).to include("--force") end @@ -364,22 +364,22 @@ def should_not_have_gems(*gems) end it "does not call clean automatically when using system gems" do - bundle! "config set path.system true" + bundle "config set path.system true" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "thin" gem "rack" G - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - gem_command! :list + gem_command :list expect(out).to include("rack (1.0.0)").and include("thin (1.0)") end @@ -421,7 +421,7 @@ def should_not_have_gems(*gems) build_gem "foo", "1.0.1" end - bundle! "update", :all => true + bundle "update", :all => true should_have_gems "foo-1.0.1" should_not_have_gems "foo-1.0" @@ -430,7 +430,7 @@ def should_not_have_gems(*gems) it "automatically cleans when path has not been set", :bundler => "3" do build_repo2 - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "foo" @@ -440,7 +440,7 @@ def should_not_have_gems(*gems) build_gem "foo", "1.0.1" end - bundle! "update", :all => true + bundle "update", :all => true files = Pathname.glob(bundled_app(".bundle", Bundler.ruby_scope, "*", "*")) files.map! {|f| f.to_s.sub(bundled_app(".bundle", Bundler.ruby_scope).to_s, "") } @@ -480,18 +480,18 @@ def should_not_have_gems(*gems) gem "foo" G bundle "config set path vendor/bundle" - bundle! "install" + bundle "install" update_repo2 do build_gem "foo", "1.0.1" end - bundle! :update, :all => true + bundle :update, :all => true should_have_gems "foo-1.0", "foo-1.0.1" end it "does not clean on bundle update when using --system" do - bundle! "config set path.system true" + bundle "config set path.system true" build_repo2 @@ -500,19 +500,19 @@ def should_not_have_gems(*gems) gem "foo" G - bundle! "install" + bundle "install" update_repo2 do build_gem "foo", "1.0.1" end - bundle! :update, :all => true + bundle :update, :all => true - gem_command! :list + gem_command :list expect(out).to include("foo (1.0.1, 1.0)") end it "cleans system gems when --force is used" do - bundle! "config set path.system true" + bundle "config set path.system true" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -531,12 +531,12 @@ def should_not_have_gems(*gems) bundle "clean --force" expect(out).to include("Removing foo (1.0)") - gem_command! :list + gem_command :list expect(out).not_to include("foo (1.0)") expect(out).to include("rack (1.0.0)") end - describe "when missing permissions" do + describe "when missing permissions", :permissions do before { ENV["BUNDLE_PATH__SYSTEM"] = "true" } let(:system_cache_path) { system_gem_path("cache") } after do @@ -560,12 +560,12 @@ def should_not_have_gems(*gems) FileUtils.chmod(0o500, system_cache_path) - bundle :clean, :force => true + bundle :clean, :force => true, :raise_on_error => false expect(err).to include(system_gem_path.to_s) expect(err).to include("grant write permissions") - gem_command! :list + gem_command :list expect(out).to include("foo (1.0)") expect(out).to include("rack (1.0.0)") end @@ -585,11 +585,11 @@ def should_not_have_gems(*gems) bundle "install" # mimic 7 length git revisions in Gemfile.lock - gemfile_lock = File.read(bundled_app("Gemfile.lock")).split("\n") + gemfile_lock = File.read(bundled_app_lock).split("\n") gemfile_lock.each_with_index do |line, index| gemfile_lock[index] = line[0..(11 + 7)] if line.include?(" revision:") end - lockfile(bundled_app("Gemfile.lock"), gemfile_lock.join("\n")) + lockfile(bundled_app_lock, gemfile_lock.join("\n")) bundle "config set path vendor/bundle" bundle "install" @@ -602,10 +602,9 @@ def should_not_have_gems(*gems) end it "when using --force on system gems, it doesn't remove binaries" do - bundle! "config set path.system true" + bundle "config set path.system true" - build_repo2 - update_repo2 do + build_repo2 do build_gem "bindir" do |s| s.bindir = "exe" s.executables = "foo" @@ -623,10 +622,38 @@ def should_not_have_gems(*gems) sys_exec "foo" - expect(exitstatus).to eq(0) if exitstatus expect(out).to eq("1.0") end + it "when using --force, it doesn't remove default gem binaries" do + skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0" + + skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2 + + default_irb_version = ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false + skip "irb isn't a default gem" if default_irb_version.empty? + + # simulate executable for default gem + build_gem "irb", default_irb_version, :to_system => true, :default => true do |s| + s.executables = "irb" + end + + if Gem.win_platform? && RUBY_VERSION < "3.1.0" + default_fiddle_version = ruby "require 'fiddle'; puts Gem.loaded_specs['fiddle'].version" + realworld_system_gems "fiddle --version #{default_fiddle_version}" + end + + realworld_system_gems "tsort --version 0.1.0", "pathname --version 0.1.0", "set --version 1.0.1" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + G + + bundle "clean --force", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s } + + expect(out).not_to include("Removing irb") + end + it "doesn't blow up on path gems without a .gemspec" do relative_path = "vendor/private_gems/bar-1.0" absolute_path = bundled_app(relative_path) @@ -644,7 +671,7 @@ def should_not_have_gems(*gems) bundle "config set path vendor/bundle" bundle "install" - bundle! :clean + bundle :clean end it "doesn't remove gems in dry-run mode with path set" do @@ -749,7 +776,7 @@ def should_not_have_gems(*gems) bundle "config set path vendor/bundle" bundle "config set clean false" - bundle! "install" + bundle "install" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -758,8 +785,8 @@ def should_not_have_gems(*gems) gem "weakling" G - bundle! "config set auto_install 1" - bundle! :clean + bundle "config set auto_install 1" + bundle :clean expect(out).to include("Installing weakling 0.0.3") should_have_gems "thin-1.0", "rack-1.0.0", "weakling-0.0.3" should_not_have_gems "foo-1.0" @@ -777,11 +804,11 @@ def should_not_have_gems(*gems) G bundle "config set path vendor/bundle" - bundle! "install" + bundle "install" expect(vendored_gems("bundler/gems/extensions")).to exist expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist - bundle! :clean + bundle :clean expect(out).to be_empty expect(vendored_gems("bundler/gems/extensions")).to exist @@ -798,7 +825,7 @@ def should_not_have_gems(*gems) G bundle "config set path vendor/bundle" - bundle! "install" + bundle "install" very_simple_binary_extensions_dir = Pathname.glob("#{vendored_gems}/extensions/*/*/very_simple_binary-1.0").first @@ -816,8 +843,8 @@ def should_not_have_gems(*gems) gem "simple_binary" G - bundle! "install" - bundle! :clean + bundle "install" + bundle :clean expect(out).to eq("Removing very_simple_binary (1.0)") expect(very_simple_binary_extensions_dir).not_to exist @@ -838,7 +865,7 @@ def should_not_have_gems(*gems) G bundle "config set path vendor/bundle" - bundle! "install" + bundle "install" very_simple_binary_extensions_dir = Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first @@ -846,25 +873,27 @@ def should_not_have_gems(*gems) expect(very_simple_binary_extensions_dir).to exist gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}" G - bundle! "install" - bundle! :clean + bundle "install" + bundle :clean expect(out).to include("Removing thin (1.0)") expect(very_simple_binary_extensions_dir).to exist gemfile <<-G + source "#{file_uri_for(gem_repo1)}" G - bundle! "install" - bundle! :clean + bundle "install" + bundle :clean expect(out).to eq("Removing very_simple_git_binary-1.0 (#{short_revision})") expect(very_simple_binary_extensions_dir).not_to exist end - it "keeps git extension directories when excluded by group", :ruby_repo do + it "keeps git extension directories when excluded by group" do build_git "very_simple_git_binary", &:add_c_extension revision = revision_for(lib_path("very_simple_git_binary-1.0")) @@ -881,8 +910,8 @@ def should_not_have_gems(*gems) bundle :lock bundle "config set without development" bundle "config set path vendor/bundle" - bundle! "install" - bundle! :clean + bundle "install" + bundle :clean very_simple_binary_extensions_dir = Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first diff --git a/ruby/spec/bundler/commands/config_spec.rb b/ruby/spec/bundler/commands/config_spec.rb index ef580463e..fb7aa3cc6 100644 --- a/ruby/spec/bundler/commands/config_spec.rb +++ b/ruby/spec/bundler/commands/config_spec.rb @@ -35,7 +35,7 @@ end end - describe "location" do + describe "location with a gemfile" do before :each do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -43,9 +43,16 @@ G end + it "is local by default" do + bundle "config set foo bar" + expect(bundled_app(".bundle/config")).to exist + expect(home(".bundle/config")).not_to exist + end + it "can be moved with an environment variable" do ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s - bundle "install", forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle "install" expect(bundled_app(".bundle")).not_to exist expect(tmp("foo/bar/config")).to exist @@ -54,14 +61,54 @@ it "can provide a relative path with the environment variable" do FileUtils.mkdir_p bundled_app("omg") - Dir.chdir bundled_app("omg") ENV["BUNDLE_APP_CONFIG"] = "../foo" - bundle "install", forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle "install", :dir => bundled_app("omg") expect(bundled_app(".bundle")).not_to exist expect(bundled_app("../foo/config")).to exist - expect(the_bundle).to include_gems "rack 1.0.0" + expect(the_bundle).to include_gems "rack 1.0.0", :dir => bundled_app("omg") + end + end + + describe "location without a gemfile" do + it "is global by default" do + bundle "config set foo bar" + expect(bundled_app(".bundle/config")).not_to exist + expect(home(".bundle/config")).to exist + end + + it "works with an absolute path" do + ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s + bundle "config set --local path vendor/bundle" + + expect(bundled_app(".bundle")).not_to exist + expect(tmp("foo/bar/config")).to exist + end + end + + describe "config location" do + let(:bundle_user_config) { File.join(Dir.home, ".config/bundler") } + + before do + Dir.mkdir File.dirname(bundle_user_config) + end + + it "can be configured through BUNDLE_USER_CONFIG" do + bundle "config set path vendor", :env => { "BUNDLE_USER_CONFIG" => bundle_user_config } + bundle "config get path", :env => { "BUNDLE_USER_CONFIG" => bundle_user_config } + expect(out).to include("Set for the current user (#{bundle_user_config}): \"vendor\"") + end + + context "when not explicitly configured, but BUNDLE_USER_HOME set" do + let(:bundle_user_home) { bundled_app(".bundle").to_s } + + it "uses the right location" do + bundle "config set path vendor", :env => { "BUNDLE_USER_HOME" => bundle_user_home } + bundle "config get path", :env => { "BUNDLE_USER_HOME" => bundle_user_home } + expect(out).to include("Set for the current user (#{bundle_user_home}/config): \"vendor\"") + end end end @@ -80,8 +127,8 @@ end it "can also be set explicitly" do - bundle! "config set --global foo global" - run! "puts Bundler.settings[:foo]" + bundle "config set --global foo global" + run "puts Bundler.settings[:foo]" expect(out).to eq("global") end @@ -138,7 +185,7 @@ it "expands the path at time of setting" do bundle "config set --global local.foo .." run "puts Bundler.settings['local.foo']" - expect(out).to eq(File.expand_path(Dir.pwd + "/..")) + expect(out).to eq(File.expand_path(bundled_app.to_s + "/..")) end it "saves with parseable option" do @@ -205,7 +252,7 @@ it "expands the path at time of setting" do bundle "config set --local local.foo .." run "puts Bundler.settings['local.foo']" - expect(out).to eq(File.expand_path(Dir.pwd + "/..")) + expect(out).to eq(File.expand_path(bundled_app.to_s + "/..")) end it "can be deleted with parseable option" do @@ -310,7 +357,7 @@ end describe "quoting" do - before(:each) { gemfile "# no gems" } + before(:each) { gemfile "source \"#{file_uri_for(gem_repo1)}\"" } let(:long_string) do "--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \ "--with-xslt-dir=/usr/pkg" @@ -324,7 +371,7 @@ it "doesn't return quotes around values" do bundle "config set foo '1'" - run "puts Bundler.settings.send(:global_config_file).read" + run "puts Bundler.settings.send(:local_config_file).read" expect(out).to include('"1"') run "puts Bundler.settings[:foo]" expect(out).to eq("1") @@ -390,85 +437,101 @@ describe "subcommands" do it "list" do - bundle! "config list" - expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\"" + bundle "config list", :env => { "BUNDLE_FOO" => "bar" } + expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nfoo\nSet via BUNDLE_FOO: \"bar\"" - bundle! "config list", :parseable => true - expect(out).to eq "spec_run=true" + bundle "config list", :env => { "BUNDLE_FOO" => "bar" }, :parseable => true + expect(out).to eq "foo=bar" + end + + it "list with credentials" do + bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" } + expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\"" + + bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" } + expect(out).to eq "gems.myserver.com=user:password" + end + + it "list with API token credentials" do + bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" } + expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\"" + + bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" } + expect(out).to eq "gems.myserver.com=api_token:x-oauth-basic" end it "get" do ENV["BUNDLE_BAR"] = "bar_val" - bundle! "config get foo" + bundle "config get foo" expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" ENV["BUNDLE_FOO"] = "foo_val" - bundle! "config get foo --parseable" + bundle "config get foo --parseable" expect(out).to eq "foo=foo_val" - bundle! "config get foo" + bundle "config get foo" expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nSet via BUNDLE_FOO: \"foo_val\"" end it "set" do - bundle! "config set foo 1" + bundle "config set foo 1" expect(out).to eq "" - bundle! "config set --local foo 2" + bundle "config set --local foo 2" expect(out).to eq "" - bundle! "config set --global foo 3" + bundle "config set --global foo 3" expect(out).to eq "Your application has set foo to \"2\". This will override the global value you are currently setting" - bundle! "config set --parseable --local foo 4" + bundle "config set --parseable --local foo 4" expect(out).to eq "foo=4" - bundle! "config set --local foo 4.1" + bundle "config set --local foo 4.1" expect(out).to eq "You are replacing the current local value of foo, which is currently \"4\"" - bundle "config set --global --local foo 5" + bundle "config set --global --local foo 5", :raise_on_error => false expect(last_command).to be_failure expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time." end it "unset" do - bundle! "config unset foo" + bundle "config unset foo" expect(out).to eq "" - bundle! "config set foo 1" - bundle! "config unset foo --parseable" + bundle "config set foo 1" + bundle "config unset foo --parseable" expect(out).to eq "" - bundle! "config set --local foo 1" - bundle! "config set --global foo 2" + bundle "config set --local foo 1" + bundle "config set --global foo 2" - bundle! "config unset foo" + bundle "config unset foo" expect(out).to eq "" - expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" + expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" - bundle! "config set --local foo 1" - bundle! "config set --global foo 2" + bundle "config set --local foo 1" + bundle "config set --global foo 2" - bundle! "config unset foo --local" + bundle "config unset foo --local" expect(out).to eq "" - expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for the current user (#{home(".bundle/config")}): \"2\"" - bundle! "config unset foo --global" + expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for the current user (#{home(".bundle/config")}): \"2\"" + bundle "config unset foo --global" expect(out).to eq "" - expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" + expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" - bundle! "config set --local foo 1" - bundle! "config set --global foo 2" + bundle "config set --local foo 1" + bundle "config set --global foo 2" - bundle! "config unset foo --global" + bundle "config unset foo --global" expect(out).to eq "" - expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for your local app (#{bundled_app(".bundle/config")}): \"1\"" - bundle! "config unset foo --local" + expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for your local app (#{bundled_app(".bundle/config")}): \"1\"" + bundle "config unset foo --local" expect(out).to eq "" - expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" + expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`" - bundle "config unset foo --local --global" + bundle "config unset foo --local --global", :raise_on_error => false expect(last_command).to be_failure expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time." end @@ -484,7 +547,7 @@ G bundle "config set --local gemfile #{bundled_app("NotGemfile")}" - expect(File.exist?(".bundle/config")).to eq(true) + expect(File.exist?(bundled_app(".bundle/config"))).to eq(true) bundle "config list" expect(out).to include("NotGemfile") diff --git a/ruby/spec/bundler/commands/console_spec.rb b/ruby/spec/bundler/commands/console_spec.rb index a0b71ff01..aa76096e3 100644 --- a/ruby/spec/bundler/commands/console_spec.rb +++ b/ruby/spec/bundler/commands/console_spec.rb @@ -1,9 +1,44 @@ # frozen_string_literal: true -RSpec.describe "bundle console", :bundler => "< 3" do +RSpec.describe "bundle console", :bundler => "< 3", :readline => true do before :each do + build_repo2 do + # A minimal fake pry console + build_gem "pry" do |s| + s.write "lib/pry.rb", <<-RUBY + class Pry + class << self + def toplevel_binding + unless defined?(@toplevel_binding) && @toplevel_binding + TOPLEVEL_BINDING.eval %{ + def self.__pry__; binding; end + Pry.instance_variable_set(:@toplevel_binding, __pry__) + class << self; undef __pry__; end + } + end + @toplevel_binding.eval('private') + @toplevel_binding + end + + def __pry__ + while line = gets + begin + puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1') + rescue Exception => e + puts "\#{e.class}: \#{e.message}" + puts e.backtrace.first + end + end + end + alias start __pry__ + end + end + RUBY + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rack" gem "activesupport", :group => :test gem "rack_middleware", :group => :development @@ -20,15 +55,15 @@ it "uses IRB as default console" do bundle "console" do |input, _, _| - input.puts("__method__") + input.puts("__FILE__") input.puts("exit") end - expect(out).to include(":irb_binding") + expect(out).to include("(irb)") end it "starts another REPL if configured as such" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "pry" G bundle "config set console pry" @@ -45,10 +80,10 @@ # make sure pry isn't there bundle "console" do |input, _, _| - input.puts("__method__") + input.puts("__FILE__") input.puts("exit") end - expect(out).to include(":irb_binding") + expect(out).to include("(irb)") end it "doesn't load any other groups" do @@ -87,7 +122,7 @@ it "performs an automatic bundle install" do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rack" gem "activesupport", :group => :test gem "rack_middleware", :group => :development diff --git a/ruby/spec/bundler/commands/doctor_spec.rb b/ruby/spec/bundler/commands/doctor_spec.rb index d829f0009..1eeb27610 100644 --- a/ruby/spec/bundler/commands/doctor_spec.rb +++ b/ruby/spec/bundler/commands/doctor_spec.rb @@ -7,7 +7,7 @@ RSpec.describe "bundle doctor" do before(:each) do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -24,15 +24,16 @@ it "succeeds on a sane installation" do bundle :doctor - - expect(exitstatus).to eq(0) end context "when all files in home are readable/writable" do before(:each) do stat = double("stat") unwritable_file = double("file") + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] } + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(unwritable_file).and_return(true) allow(File).to receive(:stat).with(unwritable_file) { stat } allow(stat).to receive(:uid) { Process.uid } allow(File).to receive(:writable?).with(unwritable_file) { true } @@ -48,9 +49,8 @@ doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"] - allow(File).to receive(:exist?).and_call_original - allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true) - expect { doctor.run }.not_to(raise_error, @stdout.string) + allow(Fiddle).to receive(:dlopen).with("/usr/lib/libSystem.dylib").and_return(true) + expect { doctor.run }.not_to raise_error expect(@stdout.string).to be_empty end @@ -58,8 +58,7 @@ doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"] - allow(File).to receive(:exist?).and_call_original - allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false) + allow(Fiddle).to receive(:dlopen).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_raise(Fiddle::DLError) expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string The following gems are missing OS dependencies: * bundler: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib @@ -68,11 +67,32 @@ end end + context "when home contains broken symlinks" do + before(:each) do + @broken_symlink = double("file") + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@broken_symlink] } + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(@broken_symlink) { false } + end + + it "exits with an error if home contains files that are not readable/writable" do + expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error + expect(@stdout.string).to include( + "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{@broken_symlink}" + ) + expect(@stdout.string).not_to include("No issues") + end + end + context "when home contains files that are not readable/writable" do before(:each) do @stat = double("stat") @unwritable_file = double("file") + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] } + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(@unwritable_file) { true } allow(File).to receive(:stat).with(@unwritable_file) { @stat } end @@ -87,7 +107,7 @@ expect(@stdout.string).not_to include("No issues") end - context "when home contains files that are not owned by the current process" do + context "when home contains files that are not owned by the current process", :permissions do before(:each) do allow(@stat).to receive(:uid) { 0o0000 } end @@ -113,4 +133,14 @@ end end end + + context "when home contains filesname with special characters" do + it "escape filename before command execute" do + doctor = Bundler::CLI::Doctor.new({}) + expect(doctor).to receive(:`).with("/usr/bin/otool -L \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string") + doctor.dylibs_darwin('$(date) "\'\.bundle') + expect(doctor).to receive(:`).with("/usr/bin/ldd \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string") + doctor.dylibs_ldd('$(date) "\'\.bundle') + end + end end diff --git a/ruby/spec/bundler/commands/exec_spec.rb b/ruby/spec/bundler/commands/exec_spec.rb index 42f760ab1..c6947afea 100644 --- a/ruby/spec/bundler/commands/exec_spec.rb +++ b/ruby/spec/bundler/commands/exec_spec.rb @@ -3,11 +3,12 @@ RSpec.describe "bundle exec" do let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] } before :each do - system_gems(system_gems_to_install, :path => :bundle_path) + system_gems(system_gems_to_install, :path => default_bundle_path) end it "works with --gemfile flag" do create_file "CustomGemfile", <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "1.0.0" G @@ -17,6 +18,7 @@ it "activates the correct gem" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G @@ -24,8 +26,20 @@ expect(out).to eq("0.9.1") end + it "works and prints no warnings when HOME is not writable" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", "0.9.1" + G + + bundle "exec rackup", :env => { "HOME" => "/" } + expect(out).to eq("0.9.1") + expect(err).to be_empty + end + it "works when the bins are in ~/.bundle" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -35,6 +49,7 @@ it "works when running from a random directory" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -44,53 +59,85 @@ end it "works when exec'ing something else" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec echo exec" expect(out).to eq("exec") end it "works when exec'ing to ruby" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec ruby -e 'puts %{hi}'" expect(out).to eq("hi") end it "works when exec'ing to rubygems" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) end it "works when exec'ing to rubygems through sh -c" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec sh -c '#{gem_cmd} --version'" expect(out).to eq(Gem::VERSION) end + it "works when exec'ing back to bundler with a lockfile that doesn't include the current platform" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", "0.9.1" + G + + # simulate lockfile generated with old version not including specific platform + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + + PLATFORMS + RUBY + + DEPENDENCIES + rack (= 0.9.1) + + BUNDLED WITH + 2.1.4 + L + + bundle "exec bundle cache", :env => { "BUNDLER_VERSION" => Bundler::VERSION } + + expect(out).to include("Updating files in vendor/cache") + end + it "respects custom process title when loading through ruby" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility = <<~'RUBY' - Process.setproctitle("1-2-3-4-5-6-7-8-9-10-11-12-13-14-15") + Process.setproctitle("1-2-3-4-5-6-7") puts `ps -ocommand= -p#{$$}` RUBY - create_file "Gemfile" + create_file "Gemfile", "source \"#{file_uri_for(gem_repo1)}\"" create_file "a.rb", script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility bundle "exec ruby a.rb" - expect(out).to eq("1-2-3-4-5-6-7-8-9-10-11-12-13-14-15") + expect(out).to eq("1-2-3-4-5-6-7") end it "accepts --verbose" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec --verbose echo foobar" expect(out).to eq("foobar") end it "passes --verbose to command if it is given after the command" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec echo --verbose" expect(out).to eq("--verbose") end it "handles --keep-file-descriptors" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + require "tempfile" command = Tempfile.new("io-test") @@ -107,7 +154,7 @@ end G - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" sys_exec "#{Gem.ruby} #{command.path}" expect(out).to be_empty @@ -115,19 +162,21 @@ end it "accepts --keep-file-descriptors" do - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" bundle "exec --keep-file-descriptors echo foobar" expect(err).to be_empty end it "can run a command named --verbose" do - install_gemfile 'gem "rack"' - File.open("--verbose", "w") do |f| + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" + File.open(bundled_app("--verbose"), "w") do |f| f.puts "#!/bin/sh" f.puts "echo foobar" end - File.chmod(0o744, "--verbose") + File.chmod(0o744, bundled_app("--verbose")) with_path_as(".") do bundle "exec -- --verbose" end @@ -146,40 +195,35 @@ gem "rack", "0.9.1" G - Dir.chdir bundled_app2 do - install_gemfile bundled_app2("Gemfile"), <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack_two", "1.0.0" - G - end + install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2 + source "#{file_uri_for(gem_repo2)}" + gem "rack_two", "1.0.0" + G - bundle! "exec rackup" + bundle "exec rackup" expect(out).to eq("0.9.1") - Dir.chdir bundled_app2 do - bundle! "exec rackup" - expect(out).to eq("1.0.0") - end + bundle "exec rackup", :dir => bundled_app2 + expect(out).to eq("1.0.0") end context "with default gems" do let(:system_gems_to_install) { [] } - let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION" } + let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false } context "when not specified in Gemfile" do before do skip "irb isn't a default gem" if default_irb_version.empty? - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" end it "uses version provided by ruby" do - bundle! "exec irb --version" + bundle "exec irb --version" expect(out).to include(default_irb_version) - expect(err).to be_empty end end @@ -202,7 +246,7 @@ end it "uses version specified" do - bundle! "exec irb --version" + bundle "exec irb --version" expect(out).to eq(specified_irb_version) expect(err).to be_empty @@ -230,7 +274,7 @@ gem "gem_depending_on_old_irb" G - bundle! "exec irb --version" + bundle "exec irb --version" end it "uses resolved version" do @@ -247,21 +291,19 @@ end end - bundle "config set path.system true" + bundle "config set --global path.system true" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G - Dir.chdir bundled_app2 do - install_gemfile bundled_app2("Gemfile"), <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack_two", "1.0.0" - G - end + install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2 + source "#{file_uri_for(gem_repo2)}" + gem "rack_two", "1.0.0" + G - bundle! "exec rackup" + bundle "exec rackup" expect(last_command.stderr).to eq( "Bundler is using a binstub that was created for a different gem (rack).\n" \ @@ -270,7 +312,8 @@ end it "handles gems installed with --without" do - install_gemfile <<-G, forgotten_command_line_options(:without => "middleware") + bundle "config set --local without middleware" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" # rack 0.9.1 and 1.0 exist @@ -286,22 +329,29 @@ end it "does not duplicate already exec'ed RUBYOPT" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G - rubyopt = ENV["RUBYOPT"] - rubyopt = "-r#{lib_dir}/bundler/setup #{rubyopt}" + bundler_setup_opt = "-r#{lib_dir}/bundler/setup" + + rubyopt = opt_add(bundler_setup_opt, ENV["RUBYOPT"]) bundle "exec 'echo $RUBYOPT'" - expect(out).to have_rubyopts(rubyopt) + expect(out.split(" ").count(bundler_setup_opt)).to eq(1) bundle "exec 'echo $RUBYOPT'", :env => { "RUBYOPT" => rubyopt } - expect(out).to have_rubyopts(rubyopt) + expect(out.split(" ").count(bundler_setup_opt)).to eq(1) end it "does not duplicate already exec'ed RUBYLIB" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -318,45 +368,48 @@ it "errors nicely when the argument doesn't exist" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "exec foobarbaz" - expect(exitstatus).to eq(127) if exitstatus + bundle "exec foobarbaz", :raise_on_error => false + expect(exitstatus).to eq(127) expect(err).to include("bundler: command not found: foobarbaz") expect(err).to include("Install missing gem executables with `bundle install`") end it "errors nicely when the argument is not executable" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G bundle "exec touch foo" - bundle "exec ./foo" - expect(exitstatus).to eq(126) if exitstatus + bundle "exec ./foo", :raise_on_error => false + expect(exitstatus).to eq(126) expect(err).to include("bundler: not executable: ./foo") end it "errors nicely when no arguments are passed" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "exec" - expect(exitstatus).to eq(128) if exitstatus + bundle "exec", :raise_on_error => false + expect(exitstatus).to eq(128) expect(err).to include("bundler: exec needs a command to run") end it "raises a helpful error when exec'ing to something outside of the bundle" do - bundle! "config set clean false" # want to keep the rackup binstub - install_gemfile! <<-G + bundle "config set clean false" # want to keep the rackup binstub + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - gem "with_license" + gem "foo" G [true, false].each do |l| - bundle! "config set disable_exec_load #{l}" - bundle "exec rackup" + bundle "config set disable_exec_load #{l}" + bundle "exec rackup", :raise_on_error => false expect(err).to include "can't find executable rackup for gem rack. rack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?" end end @@ -368,7 +421,10 @@ each_prefix.call("exec") do |exec| describe "when #{exec} is used" do before(:each) do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -415,44 +471,45 @@ with_fake_man do bundle "#{exec} --help cat" end - expect(out).to include(%(["#{root}/man/bundle-exec.1"])) + expect(out).to include(%(["#{man_dir}/bundle-exec.1"])) end it "shows bundle-exec's man page when --help is before exec" do with_fake_man do bundle "--help #{exec}" end - expect(out).to include(%(["#{root}/man/bundle-exec.1"])) + expect(out).to include(%(["#{man_dir}/bundle-exec.1"])) end it "shows bundle-exec's man page when -h is before exec" do with_fake_man do bundle "-h #{exec}" end - expect(out).to include(%(["#{root}/man/bundle-exec.1"])) + expect(out).to include(%(["#{man_dir}/bundle-exec.1"])) end it "shows bundle-exec's man page when --help is after exec" do with_fake_man do bundle "#{exec} --help" end - expect(out).to include(%(["#{root}/man/bundle-exec.1"])) + expect(out).to include(%(["#{man_dir}/bundle-exec.1"])) end it "shows bundle-exec's man page when -h is after exec" do with_fake_man do bundle "#{exec} -h" end - expect(out).to include(%(["#{root}/man/bundle-exec.1"])) + expect(out).to include(%(["#{man_dir}/bundle-exec.1"])) end end end end describe "with gem executables" do - describe "run from a random directory", :ruby_repo do + describe "run from a random directory" do before(:each) do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G end @@ -476,6 +533,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz", :path => "#{File.expand_path(home("fizz"))}" G end @@ -500,6 +558,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz_git", :git => "#{lib_path("fizz_git-1.0")}" G end @@ -523,6 +582,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz_no_gemspec", "1.0", :git => "#{lib_path("fizz_no_gemspec-1.0")}" G end @@ -552,6 +612,36 @@ expect(out).to include("Installing foo 1.0") end + it "loads the correct optparse when `auto_install` is set, and optparse is a dependency" do + if Gem.ruby_version >= Gem::Version.new("3.0.0") && Gem.rubygems_version < Gem::Version.new("3.3.0.a") + skip "optparse is a default gem, and rubygems loads it during install" + end + + build_repo4 do + build_gem "fastlane", "2.192.0" do |s| + s.executables = "fastlane" + s.add_dependency "optparse", "~> 999.999.999" + end + + build_gem "optparse", "999.999.998" + build_gem "optparse", "999.999.999" + end + + system_gems "optparse-999.999.998", :gem_repo => gem_repo4 + + bundle "config set auto_install 1" + bundle "config set --local path vendor/bundle" + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "fastlane" + G + + bundle "exec fastlane" + expect(out).to include("Installing optparse 999.999.999") + expect(out).to include("2.192.0") + end + describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do build_lib "foo" @@ -568,11 +658,12 @@ G end - install_gemfile <<-G + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G - bundle "exec irb" + bundle "exec irb", :raise_on_error => false expect(err).to match("The gemspec at #{lib_path("foo-1.0").join("foo.gemspec")} is not valid") expect(err).to match('"TODO" is not a summary') @@ -581,7 +672,11 @@ describe "with gems bundled for deployment" do it "works when calling bundler from another script" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + module Monkey def bin_path(a,b,c) raise Gem::GemNotFoundException.new('Fail') @@ -589,8 +684,9 @@ def bin_path(a,b,c) end Bundler.rubygems.extend(Monkey) G - bundle "install --deployment" - bundle "exec ruby -e '`#{bindir.join("bundler")} -v`; puts $?.success?'" + bundle "config set path.system true" + bundle "install" + bundle "exec ruby -e '`bundle -v`; puts $?.success?'", :env => { "BUNDLER_VERSION" => Bundler::VERSION } expect(out).to match("true") end end @@ -610,10 +706,11 @@ def bin_path(a,b,c) RUBY before do - path.open("w") {|f| f << executable } - path.chmod(0o755) + bundled_app(path).open("w") {|f| f << executable } + bundled_app(path).chmod(0o755) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G end @@ -630,29 +727,42 @@ def bin_path(a,b,c) let(:expected) { [exec, args, rack, process].join("\n") } let(:expected_err) { "" } - subject { bundle "exec #{path} arg1 arg2" } + subject { bundle "exec #{path} arg1 arg2", :raise_on_error => false } - shared_examples_for "it runs" do - it "like a normally executed executable" do - subject - expect(exitstatus).to eq(exit_code) if exitstatus - expect(err).to eq(expected_err) - expect(out).to eq(expected) - end - end + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - it_behaves_like "it runs" + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end context "the executable exits explicitly" do let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" } context "with exit 0" do - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "with exit 99" do let(:exit_code) { 99 } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end end @@ -665,11 +775,17 @@ def bin_path(a,b,c) end let(:expected_err) { "" } let(:exit_code) do - # signal mask 128 + plus signal 15 -> TERM - # this is specified by C99 - 128 + 15 + exit_status_for_signal(Signal.list["TERM"]) + end + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) end - it_behaves_like "it runs" end context "the executable is empty" do @@ -678,7 +794,15 @@ def bin_path(a,b,c) let(:exit_code) { 0 } let(:expected_err) { "#{path} is empty" } let(:expected) { "" } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "the executable raises" do @@ -686,28 +810,52 @@ def bin_path(a,b,c) let(:exit_code) { 1 } let(:expected_err) do "bundler: failed to load command: #{path} (#{path})" \ - "\nRuntimeError: ERROR\n #{path}:10:in `'" + "\n#{path}:10:in `': ERROR (RuntimeError)" + end + + it "runs like a normally executed executable" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to start_with(expected_err) + expect(out).to eq(expected) end - it_behaves_like "it runs" end context "the executable raises an error without a backtrace" do let(:executable) { super() << "\nclass Err < Exception\ndef backtrace; end;\nend\nraise Err" } let(:exit_code) { 1 } - let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\nErr: Err" } + let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\n#{system_gem_path("bin/bundle")}: Err (Err)" } let(:expected) { super() } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when the file uses the current ruby shebang" do let(:shebang) { "#!#{Gem.ruby}" } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when Bundler.setup fails", :bundler => "< 3" do before do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack', '2' G ENV["BUNDLER_FORCE_TTY"] = "true" @@ -716,16 +864,28 @@ def bin_path(a,b,c) let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:expected) { "" } let(:expected_err) { <<-EOS.strip } -\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile.\e[0m -\e[33mRun `bundle install` to install missing gems.\e[0m +Could not find gem 'rack (= 2)' in locally installed gems. + +The source contains the following gems matching 'rack': + * rack-0.9.1 + * rack-1.0.0 +Run `bundle install` to install missing gems. EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when Bundler.setup fails", :bundler => "3" do before do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack', '2' G ENV["BUNDLER_FORCE_TTY"] = "true" @@ -734,19 +894,35 @@ def bin_path(a,b,c) let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:expected) { "" } let(:expected_err) { <<-EOS.strip } -\e[31mCould not find gem 'rack (= 2)' in locally installed gems. -The source contains 'rack' at: 1.0.0\e[0m -\e[33mRun `bundle install` to install missing gems.\e[0m +Could not find gem 'rack (= 2)' in locally installed gems. + +The source contains the following gems matching 'rack': + * rack-1.0.0 +Run `bundle install` to install missing gems. EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when the executable exits non-zero via at_exit" do let(:executable) { super() + "\n\nat_exit { $! ? raise($!) : exit(1) }" } let(:exit_code) { 1 } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when disable_exec_load is set" do @@ -757,7 +933,14 @@ def bin_path(a,b,c) bundle "config set disable_exec_load true" end - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "regarding $0 and __FILE__" do @@ -773,16 +956,30 @@ def bin_path(a,b,c) __FILE__: #{path.to_s.inspect} EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end context "when the path is relative" do let(:path) { super().relative_path_from(bundled_app) } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when the path is relative with a leading ./" do - let(:path) { Pathname.new("./#{super().relative_path_from(Pathname.pwd)}") } + let(:path) { Pathname.new("./#{super().relative_path_from(bundled_app)}") } pending "relative paths with ./ have absolute __FILE__" end @@ -813,7 +1010,9 @@ def bin_path(a,b,c) RUBY it "receives the signal" do - bundle!("exec #{path}") do |_, o, thr| + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + bundle("exec #{path}") do |_, o, thr| o.gets # Consumes 'Started' and ensures that thread has started Process.kill("INT", thr.pid) end @@ -834,11 +1033,13 @@ def bin_path(a,b,c) RUBY it "makes sure no unexpected signals are restored to DEFAULT" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + test_signals.each do |n| Signal.trap(n, "IGNORE") end - bundle!("exec #{path}") + bundle("exec #{path}") expect(out).to eq(test_signals.count.to_s) end @@ -849,65 +1050,176 @@ def bin_path(a,b,c) context "nested bundle exec" do context "when bundle in a local path" do before do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G bundle "config set path vendor/bundler" - bundle! :install + bundle :install end - it "correctly shells out", :ruby_repo do + it "correctly shells out" do file = bundled_app("file_that_bundle_execs.rb") - create_file(file, <<-RB) + create_file(file, <<-RUBY) #!#{Gem.ruby} puts `bundle exec echo foo` - RB + RUBY file.chmod(0o777) - bundle! "exec #{file}" + bundle "exec #{file}", :env => { "PATH" => path } expect(out).to eq("foo") end end + context "when Kernel.require uses extra monkeypatches" do + before do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + end + + it "does not undo the monkeypatches" do + karafka = bundled_app("bin/karafka") + create_file(karafka, <<~RUBY) + #!#{Gem.ruby} + + module Kernel + module_function + + alias_method :require_before_extra_monkeypatches, :require + + def require(path) + puts "requiring \#{path} used the monkeypatch" + + require_before_extra_monkeypatches(path) + end + end + + Bundler.setup(:default) + + require "foo" + RUBY + karafka.chmod(0o777) + + foreman = bundled_app("bin/foreman") + create_file(foreman, <<~RUBY) + #!#{Gem.ruby} + + puts `bundle exec bin/karafka` + RUBY + foreman.chmod(0o777) + + bundle "exec #{foreman}" + expect(out).to eq("requiring foo used the monkeypatch") + end + end + + context "when gemfile and path are configured", :ruby_repo do + before do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + build_repo2 do + build_gem "rails", "6.1.0" do |s| + s.executables = "rails" + end + end + + bundle "config set path vendor/bundle" + bundle "config set gemfile gemfiles/rack_6_1.gemfile" + + create_file(bundled_app("gemfiles/rack_6_1.gemfile"), <<~RUBY) + source "#{file_uri_for(gem_repo2)}" + + gem "rails", "6.1.0" + RUBY + + # A Gemfile needs to be in the root to trick bundler's root resolution + create_file(bundled_app("Gemfile"), "source \"#{file_uri_for(gem_repo1)}\"") + + bundle "install" + end + + it "can still find gems after a nested subprocess" do + script = bundled_app("bin/myscript") + + create_file(script, <<~RUBY) + #!#{Gem.ruby} + + puts `bundle exec rails` + RUBY + + script.chmod(0o777) + + bundle "exec #{script}" + + expect(err).to be_empty + expect(out).to eq("6.1.0") + end + end + context "with a system gem that shadows a default gem" do let(:openssl_version) { "99.9.9" } - let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil } + let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil, :raise_on_error => false } it "only leaves the default gem in the stdlib available" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? skip "openssl isn't a default gem" if expected.empty? - install_gemfile! "" # must happen before installing the broken system gem + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" # must happen before installing the broken system gem build_repo4 do build_gem "openssl", openssl_version do |s| - s.write("lib/openssl.rb", <<-RB) + s.write("lib/openssl.rb", <<-RUBY) raise "custom openssl should not be loaded, it's not in the gemfile!" - RB + RUBY end end - system_gems(:bundler, "openssl-#{openssl_version}", :gem_repo => gem_repo4) + system_gems("openssl-#{openssl_version}", :gem_repo => gem_repo4) file = bundled_app("require_openssl.rb") - create_file(file, <<-RB) + create_file(file, <<-RUBY) #!/usr/bin/env ruby require "openssl" puts OpenSSL::VERSION warn Gem.loaded_specs.values.map(&:full_name) - RB + RUBY file.chmod(0o777) + env = { "PATH" => path } aggregate_failures do - expect(bundle!("exec #{file}", :artifice => nil)).to eq(expected) - expect(bundle!("exec bundle exec #{file}", :artifice => nil)).to eq(expected) - expect(bundle!("exec ruby #{file}", :artifice => nil)).to eq(expected) - expect(run!(file.read, :artifice => nil)).to eq(expected) + expect(bundle("exec #{file}", :artifice => nil, :env => env)).to eq(expected) + expect(bundle("exec bundle exec #{file}", :artifice => nil, :env => env)).to eq(expected) + expect(bundle("exec ruby #{file}", :artifice => nil, :env => env)).to eq(expected) + expect(run(file.read, :artifice => nil, :env => env)).to eq(expected) end + skip "ruby_core has openssl and rubygems in the same folder, and this test needs rubygems require but default openssl not in a directly added entry in $LOAD_PATH" if ruby_core? # sanity check that we get the newer, custom version without bundler - sys_exec("#{Gem.ruby} #{file}") + sys_exec "#{Gem.ruby} #{file}", :env => env, :raise_on_error => false expect(err).to include("custom openssl should not be loaded") end end + + context "with a git gem that includes extensions", :ruby_repo do + before do + build_git "simple_git_binary", &:add_c_extension + bundle "config set --local path .bundle" + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "simple_git_binary", :git => '#{lib_path("simple_git_binary-1.0")}' + G + end + + it "allows calling bundle install" do + bundle "exec bundle install" + end + + it "allows calling bundle install after removing gem.build_complete" do + FileUtils.rm_rf Dir[bundled_app(".bundle/**/gem.build_complete")] + bundle "exec #{Gem.ruby} -S bundle install" + end + end end end diff --git a/ruby/spec/bundler/commands/fund_spec.rb b/ruby/spec/bundler/commands/fund_spec.rb new file mode 100644 index 000000000..5a0c5411d --- /dev/null +++ b/ruby/spec/bundler/commands/fund_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +RSpec.describe "bundle fund" do + before do + build_repo2 do + build_gem "has_funding_and_other_metadata" do |s| + s.metadata = { + "bug_tracker_uri" => "https://example.com/user/bestgemever/issues", + "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md", + "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1", + "homepage_uri" => "https://bestgemever.example.io", + "mailing_list_uri" => "https://groups.example.com/bestgemever", + "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding", + "source_code_uri" => "https://example.com/user/bestgemever", + "wiki_uri" => "https://example.com/user/bestgemever/wiki", + } + end + + build_gem "has_funding", "1.2.3" do |s| + s.metadata = { + "funding_uri" => "https://example.com/has_funding/funding", + } + end + + build_gem "gem_with_dependent_funding", "1.0" do |s| + s.add_dependency "has_funding" + end + end + end + + it "prints fund information for all gems in the bundle" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding_and_other_metadata' + gem 'has_funding' + gem 'rack-obama' + G + + bundle "fund" + + expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding") + expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding") + expect(out).to_not include("rack-obama") + end + + it "does not consider fund information for gem dependencies" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'gem_with_dependent_funding' + G + + bundle "fund" + + expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding") + expect(out).to_not include("gem_with_dependent_funding") + end + + it "prints message if none of the gems have fund information" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'rack-obama' + G + + bundle "fund" + + expect(out).to include("None of the installed gems you directly depend on are looking for funding.") + end + + describe "with --group option" do + it "prints fund message for only specified group gems" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding_and_other_metadata', :group => :development + gem 'has_funding' + G + + bundle "fund --group development" + expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding") + expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding") + end + end +end diff --git a/ruby/spec/bundler/commands/help_spec.rb b/ruby/spec/bundler/commands/help_spec.rb index f4f90b934..f72763900 100644 --- a/ruby/spec/bundler/commands/help_spec.rb +++ b/ruby/spec/bundler/commands/help_spec.rb @@ -1,25 +1,25 @@ # frozen_string_literal: true RSpec.describe "bundle help" do - it "uses mann when available" do + it "uses man when available" do with_fake_man do bundle "help gemfile" end - expect(out).to eq(%(["#{root}/man/gemfile.5"])) + expect(out).to eq(%(["#{man_dir}/gemfile.5"])) end - it "prefixes bundle commands with bundle- when finding the groff files" do + it "prefixes bundle commands with bundle- when finding the man files" do with_fake_man do bundle "help install" end - expect(out).to eq(%(["#{root}/man/bundle-install.1"])) + expect(out).to eq(%(["#{man_dir}/bundle-install.1"])) end - it "simply outputs the txt file when there is no man on the path" do + it "simply outputs the human readable file when there is no man on the path" do with_path_as("") do bundle "help install" end - expect(out).to match(/BUNDLE-INSTALL/) + expect(out).to match(/bundle-install/) end it "still outputs the old help for commands that do not have man pages yet" do @@ -28,6 +28,8 @@ end it "looks for a binary and executes it with --help option if it's named bundler-" do + skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform? + File.open(tmp("bundler-testtasks"), "w", 0o755) do |f| f.puts "#!/usr/bin/env ruby\nputs ARGV.join(' ')\n" end @@ -36,7 +38,6 @@ bundle "help testtasks" end - expect(exitstatus).to be_zero if exitstatus expect(out).to eq("--help") end @@ -44,33 +45,33 @@ with_fake_man do bundle "install --help" end - expect(out).to eq(%(["#{root}/man/bundle-install.1"])) + expect(out).to eq(%(["#{man_dir}/bundle-install.1"])) end it "is called when the --help flag is used before the command" do with_fake_man do bundle "--help install" end - expect(out).to eq(%(["#{root}/man/bundle-install.1"])) + expect(out).to eq(%(["#{man_dir}/bundle-install.1"])) end it "is called when the -h flag is used before the command" do with_fake_man do bundle "-h install" end - expect(out).to eq(%(["#{root}/man/bundle-install.1"])) + expect(out).to eq(%(["#{man_dir}/bundle-install.1"])) end it "is called when the -h flag is used after the command" do with_fake_man do bundle "install -h" end - expect(out).to eq(%(["#{root}/man/bundle-install.1"])) + expect(out).to eq(%(["#{man_dir}/bundle-install.1"])) end it "has helpful output when using --help flag for a non-existent command" do with_fake_man do - bundle "instill -h" + bundle "instill -h", :raise_on_error => false end expect(err).to include('Could not find command "instill".') end @@ -79,11 +80,11 @@ with_fake_man do bundle "--help" end - expect(out).to eq(%(["#{root}/man/bundle.1"])) + expect(out).to eq(%(["#{man_dir}/bundle.1"])) with_fake_man do bundle "-h" end - expect(out).to eq(%(["#{root}/man/bundle.1"])) + expect(out).to eq(%(["#{man_dir}/bundle.1"])) end end diff --git a/ruby/spec/bundler/commands/info_spec.rb b/ruby/spec/bundler/commands/info_spec.rb index 457282349..74943703a 100644 --- a/ruby/spec/bundler/commands/info_spec.rb +++ b/ruby/spec/bundler/commands/info_spec.rb @@ -3,18 +3,34 @@ RSpec.describe "bundle info" do context "with a standard Gemfile" do before do + build_repo2 do + build_gem "has_metadata" do |s| + s.metadata = { + "bug_tracker_uri" => "https://example.com/user/bestgemever/issues", + "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md", + "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1", + "homepage_uri" => "https://bestgemever.example.io", + "mailing_list_uri" => "https://groups.example.com/bestgemever", + "source_code_uri" => "https://example.com/user/bestgemever", + "wiki_uri" => "https://example.com/user/bestgemever/wiki", + } + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rails" + gem "has_metadata" + gem "thin" G end it "creates a Gemfile.lock when invoked with a gem name" do - FileUtils.rm("Gemfile.lock") + FileUtils.rm(bundled_app_lock) bundle "info rails" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "prints information if gem exists in bundle" do @@ -35,11 +51,41 @@ expect(out).to eq(root.to_s) end + it "prints gem version if exists in bundle" do + bundle "info rails --version" + expect(out).to eq("2.3.2") + end + + it "doesn't claim that bundler has been deleted, even if using a custom path without bundler there" do + bundle "config set --local path vendor/bundle" + bundle "install" + bundle "info bundler" + expect(out).to include("\tPath: #{root}") + expect(err).not_to match(/The gem bundler has been deleted/i) + end + it "complains if gem not in bundle" do - bundle "info missing" + bundle "info missing", :raise_on_error => false expect(err).to eq("Could not find gem 'missing'.") end + it "warns if path no longer exists on disk" do + FileUtils.rm_rf(default_bundle_path("gems", "rails-2.3.2")) + + bundle "info rails --path" + + expect(err).to match(/The gem rails has been deleted/i) + expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s) + + bundle "info rail --path" + expect(err).to match(/The gem rails has been deleted/i) + expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s) + + bundle "info rails" + expect(err).to match(/The gem rails has been deleted/i) + expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s) + end + context "given a default gem shippped in ruby", :ruby_repo do it "prints information about the default gem" do bundle "info rdoc" @@ -48,6 +94,22 @@ end end + context "given a gem with metadata" do + it "prints the gem metadata" do + bundle "info has_metadata" + expect(out).to include "* has_metadata (1.0) +\tSummary: This is just a fake gem for testing +\tHomepage: http://example.com +\tDocumentation: https://www.example.info/gems/bestgemever/0.0.1 +\tSource Code: https://example.com/user/bestgemever +\tWiki: https://example.com/user/bestgemever/wiki +\tChangelog: https://example.com/user/bestgemever/CHANGELOG.md +\tBug Tracker: https://example.com/user/bestgemever/issues +\tMailing List: https://groups.example.com/bestgemever +\tPath: #{default_bundle_path("gems", "has_metadata-1.0")}" + end + end + context "when gem does not have homepage" do before do build_repo2 do @@ -62,6 +124,30 @@ expect(out).to_not include("Homepage:") end end + + context "when gem has a reverse dependency on any version" do + it "prints the details" do + bundle "info rack" + + expect(out).to include("Reverse Dependencies: \n\t\tthin (1.0) depends on rack (>= 0)") + end + end + + context "when gem has a reverse dependency on a specific version" do + it "prints the details" do + bundle "info actionpack" + + expect(out).to include("Reverse Dependencies: \n\t\trails (2.3.2) depends on actionpack (= 2.3.2)") + end + end + + context "when gem has no reverse dependencies" do + it "excludes the reverse dependencies field from the output" do + bundle "info rails" + + expect(out).not_to include("Reverse Dependencies:") + end + end end context "with a git repo in the Gemfile" do @@ -71,6 +157,7 @@ it "prints out git info" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G expect(the_bundle).to include_gems "foo 1.0" @@ -86,6 +173,7 @@ @revision = revision_for(lib_path("foo-1.0"))[0...6] install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" G expect(the_bundle).to include_gems "foo 1.0.omg" @@ -97,6 +185,7 @@ it "doesn't print the branch when tied to a ref" do sha = revision_for(lib_path("foo-1.0")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{sha}" G @@ -107,17 +196,18 @@ it "handles when a version is a '-' prerelease" do @git = build_git("foo", "1.0.0-beta.1", :path => lib_path("foo")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.0.0-beta.1", :git => "#{lib_path("foo")}" G expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1" - bundle! "info foo" + bundle "info foo" expect(out).to include("foo (1.0.0.pre.beta.1") end end context "with a valid regexp for gem name" do - it "presents alternatives" do + it "presents alternatives", :readline do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -125,7 +215,7 @@ G bundle "info rac" - expect(out).to eq "1 : rack\n2 : rack-obama\n0 : - exit -\n>" + expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/) end end @@ -138,8 +228,22 @@ invalid_regexp = "[]" - bundle "info #{invalid_regexp}" + bundle "info #{invalid_regexp}", :raise_on_error => false expect(err).to include("Could not find gem '#{invalid_regexp}'.") end end + + context "with without configured" do + it "does not find the gem, but gives a helpful error" do + bundle "config without test" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rails", group: :test + G + + bundle "info rails", :raise_on_error => false + expect(err).to include("Could not find gem 'rails', because it's in the group 'test', configured to be ignored.") + end + end end diff --git a/ruby/spec/bundler/commands/init_spec.rb b/ruby/spec/bundler/commands/init_spec.rb index 7960ce85b..683a453c7 100644 --- a/ruby/spec/bundler/commands/init_spec.rb +++ b/ruby/spec/bundler/commands/init_spec.rb @@ -2,9 +2,9 @@ RSpec.describe "bundle init" do it "generates a Gemfile" do - bundle! :init + bundle :init expect(out).to include("Writing new Gemfile") - expect(bundled_app("Gemfile")).to be_file + expect(bundled_app_gemfile).to be_file end context "when a Gemfile already exists" do @@ -15,11 +15,11 @@ end it "does not change existing Gemfiles" do - expect { bundle :init }.not_to change { File.read(bundled_app("Gemfile")) } + expect { bundle :init, :raise_on_error => false }.not_to change { File.read(bundled_app_gemfile) } end it "notifies the user that an existing Gemfile already exists" do - bundle :init + bundle :init, :raise_on_error => false expect(err).to include("Gemfile already exists") end end @@ -28,13 +28,11 @@ let(:subdir) { "child_dir" } it "lets users generate a Gemfile in a child directory" do - bundle! :init + bundle :init FileUtils.mkdir bundled_app(subdir) - Dir.chdir bundled_app(subdir) do - bundle! :init - end + bundle :init, :dir => bundled_app(subdir) expect(out).to include("Writing new Gemfile") expect(bundled_app("#{subdir}/Gemfile")).to be_file @@ -50,9 +48,7 @@ mode = File.stat(bundled_app(subdir)).mode ^ 0o222 FileUtils.chmod mode, bundled_app(subdir) - Dir.chdir bundled_app(subdir) do - bundle :init - end + bundle :init, :dir => bundled_app(subdir), :raise_on_error => false expect(err).to include("directory is not writable") expect(Dir[bundled_app("#{subdir}/*")]).to be_empty @@ -75,7 +71,7 @@ bundle :init, :gemspec => spec_file - gemfile = bundled_app("Gemfile").read + gemfile = bundled_app_gemfile.read expect(gemfile).to match(%r{source 'https://rubygems.org'}) expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1) expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1) @@ -93,7 +89,7 @@ S end - bundle :init, :gemspec => spec_file + bundle :init, :gemspec => spec_file, :raise_on_error => false expect(err).to include("There was an error while loading `test.gemspec`") end end @@ -103,7 +99,7 @@ before { bundle "config set init_gems_rb true" } it "generates a gems.rb" do - bundle! :init + bundle :init expect(out).to include("Writing new gems.rb") expect(bundled_app("gems.rb")).to be_file end @@ -116,11 +112,11 @@ end it "does not change existing Gemfiles" do - expect { bundle :init }.not_to change { File.read(bundled_app("gems.rb")) } + expect { bundle :init, :raise_on_error => false }.not_to change { File.read(bundled_app("gems.rb")) } end it "notifies the user that an existing gems.rb already exists" do - bundle :init + bundle :init, :raise_on_error => false expect(err).to include("gems.rb already exists") end end @@ -129,13 +125,11 @@ let(:subdir) { "child_dir" } it "lets users generate a Gemfile in a child directory" do - bundle! :init + bundle :init FileUtils.mkdir bundled_app(subdir) - Dir.chdir bundled_app(subdir) do - bundle! :init - end + bundle :init, :dir => bundled_app(subdir) expect(out).to include("Writing new gems.rb") expect(bundled_app("#{subdir}/gems.rb")).to be_file diff --git a/ruby/spec/bundler/commands/inject_spec.rb b/ruby/spec/bundler/commands/inject_spec.rb index 01c1f9187..92e86bd6c 100644 --- a/ruby/spec/bundler/commands/inject_spec.rb +++ b/ruby/spec/bundler/commands/inject_spec.rb @@ -10,9 +10,9 @@ context "without a lockfile" do it "locks with the injected gems" do - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist bundle "inject 'rack-obama' '> 0'" - expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + expect(bundled_app_lock.read).to match(/rack-obama/) end end @@ -22,28 +22,28 @@ end it "adds the injected gems to the Gemfile" do - expect(bundled_app("Gemfile").read).not_to match(/rack-obama/) + expect(bundled_app_gemfile.read).not_to match(/rack-obama/) bundle "inject 'rack-obama' '> 0'" - expect(bundled_app("Gemfile").read).to match(/rack-obama/) + expect(bundled_app_gemfile.read).to match(/rack-obama/) end it "locks with the injected gems" do - expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + expect(bundled_app_lock.read).not_to match(/rack-obama/) bundle "inject 'rack-obama' '> 0'" - expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + expect(bundled_app_lock.read).to match(/rack-obama/) end end context "with injected gems already in the Gemfile" do it "doesn't add existing gems" do - bundle "inject 'rack' '> 0'" + bundle "inject 'rack' '> 0'", :raise_on_error => false expect(err).to match(/cannot specify the same gem twice/i) end end context "incorrect arguments" do it "fails when more than 2 arguments are passed" do - bundle "inject gem_name 1 v" + bundle "inject gem_name 1 v", :raise_on_error => false expect(err).to eq(<<-E.strip) ERROR: "bundle inject" was called with arguments ["gem_name", "1", "v"] Usage: "bundle inject GEM VERSION" @@ -54,7 +54,7 @@ context "with source option" do it "add gem with source option in gemfile" do bundle "inject 'foo' '>0' --source #{file_uri_for(gem_repo1)}" - gemfile = bundled_app("Gemfile").read + gemfile = bundled_app_gemfile.read str = "gem \"foo\", \"> 0\", :source => \"#{file_uri_for(gem_repo1)}\"" expect(gemfile).to include str end @@ -63,14 +63,14 @@ context "with group option" do it "add gem with group option in gemfile" do bundle "inject 'rack-obama' '>0' --group=development" - gemfile = bundled_app("Gemfile").read + gemfile = bundled_app_gemfile.read str = "gem \"rack-obama\", \"> 0\", :group => :development" expect(gemfile).to include str end it "add gem with multiple groups in gemfile" do bundle "inject 'rack-obama' '>0' --group=development,test" - gemfile = bundled_app("Gemfile").read + gemfile = bundled_app_gemfile.read str = "gem \"rack-obama\", \"> 0\", :groups => [:development, :test]" expect(gemfile).to include str end @@ -80,26 +80,26 @@ before do bundle "install" if Bundler.feature_flag.bundler_3_mode? - bundle! "config set --local deployment true" + bundle "config set --local deployment true" else - bundle! "config set --local frozen true" + bundle "config set --local frozen true" end end it "injects anyway" do bundle "inject 'rack-obama' '> 0'" - expect(bundled_app("Gemfile").read).to match(/rack-obama/) + expect(bundled_app_gemfile.read).to match(/rack-obama/) end it "locks with the injected gems" do - expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + expect(bundled_app_lock.read).not_to match(/rack-obama/) bundle "inject 'rack-obama' '> 0'" - expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/) + expect(bundled_app_lock.read).to match(/rack-obama/) end it "restores frozen afterwards" do bundle "inject 'rack-obama' '> 0'" - config = YAML.load(bundled_app(".bundle/config").read) + config = Psych.load(bundled_app(".bundle/config").read) expect(config["BUNDLE_DEPLOYMENT"] || config["BUNDLE_FROZEN"]).to eq("true") end @@ -108,10 +108,10 @@ source "#{file_uri_for(gem_repo1)}" gem "rack-obama" G - bundle "inject 'rack' '> 0'" + bundle "inject 'rack' '> 0'", :raise_on_error => false expect(err).to match(/trying to install in deployment mode after changing/) - expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/) + expect(bundled_app_lock.read).not_to match(/rack-obama/) end end end diff --git a/ruby/spec/bundler/commands/install_spec.rb b/ruby/spec/bundler/commands/install_spec.rb index b57d81b10..ec1d9bcd0 100644 --- a/ruby/spec/bundler/commands/install_spec.rb +++ b/ruby/spec/bundler/commands/install_spec.rb @@ -12,12 +12,12 @@ end it "does not make a lockfile if the install fails" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false raise StandardError, "FAIL" G expect(err).to include('StandardError, "FAIL"') - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist end it "creates a Gemfile.lock" do @@ -26,7 +26,7 @@ gem "rack" G - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "does not create ./.bundle by default", :bundler => "< 3" do @@ -35,7 +35,7 @@ gem "rack" G - bundle! :install # can't use install_gemfile since it sets retry + bundle :install # can't use install_gemfile since it sets retry expect(bundled_app(".bundle")).not_to exist end @@ -45,7 +45,7 @@ gem "rack" G - bundle! :install, :env => { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry + bundle :install, :env => { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry expect(bundled_app(".bundle")).not_to exist end @@ -66,13 +66,13 @@ gem 'rack' G - lockfile = File.read(bundled_app("Gemfile.lock")) + lockfile = File.read(bundled_app_lock) - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false raise StandardError, "FAIL" G - expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile) + expect(File.read(bundled_app_lock)).to eq(lockfile) end it "does not touch the lockfile if nothing changed" do @@ -81,7 +81,7 @@ gem "rack" G - expect { run "1" }.not_to change { File.mtime(bundled_app("Gemfile.lock")) } + expect { run "1" }.not_to change { File.mtime(bundled_app_lock) } end it "fetches gems" do @@ -94,6 +94,21 @@ expect(the_bundle).to include_gems("rack 1.0.0") end + it "auto-heals missing gems" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' + G + + FileUtils.rm_rf(default_bundle_path("gems/rack-1.0.0")) + + bundle "install --verbose" + + expect(out).to include("Installing rack 1.0.0") + expect(default_bundle_path("gems/rack-1.0.0")).to exist + expect(the_bundle).to include_gems("rack 1.0.0") + end + it "fetches gems when multiple versions are specified" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -115,11 +130,11 @@ end it "raises an appropriate error when gems are specified using symbols" do - install_gemfile(<<-G) + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem :rack G - expect(exitstatus).to eq(4) if exitstatus + expect(exitstatus).to eq(4) end it "pulls in dependencies" do @@ -141,8 +156,14 @@ end it "does not install the development dependency" do + build_repo2 do + build_gem "with_development_dependency" do |s| + s.add_development_dependency "activesupport", "= 2.3.5" + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "with_development_dependency" G @@ -176,7 +197,7 @@ end it "does not reinstall any gem that is already available locally" do - system_gems "activesupport-2.3.2", :path => :bundle_path + system_gems "activesupport-2.3.2", :path => default_bundle_path build_repo2 do build_gem "activesupport", "2.3.2" do |s| @@ -216,8 +237,22 @@ expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5" end + it "loads env plugins" do + plugin_msg = "hello from an env plugin!" + create_file "plugins/rubygems_plugin.rb", "puts '#{plugin_msg}'" + rubylib = ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR).unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) + install_gemfile <<-G, :env => { "RUBYLIB" => rubylib } + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + expect(last_command.stdboth).to include(plugin_msg) + end + describe "with a gem that installs multiple platforms" do it "installs gems for the local platform as first choice" do + skip "version is 1.0, not 1.0.0" if Gem.win_platform? + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "platform_specific" @@ -271,28 +306,32 @@ end it "works" do - bundle "install", forgotten_command_line_options(:path => "vendor") + bundle "config set --local path vendor" + bundle "install" expect(the_bundle).to include_gems "rack 1.0" end it "allows running bundle install --system without deleting foo", :bundler => "< 3" do - bundle "install", forgotten_command_line_options(:path => "vendor") - bundle "install", forgotten_command_line_options(:system => true) + bundle "install --path vendor" + bundle "install --system" FileUtils.rm_rf(bundled_app("vendor")) expect(the_bundle).to include_gems "rack 1.0" end it "allows running bundle install --system after deleting foo", :bundler => "< 3" do - bundle "install", forgotten_command_line_options(:path => "vendor") + bundle "install --path vendor" FileUtils.rm_rf(bundled_app("vendor")) - bundle "install", forgotten_command_line_options(:system => true) + bundle "install --system" expect(the_bundle).to include_gems "rack 1.0" end end it "finds gems in multiple sources", :bundler => "< 3" do - build_repo2 - update_repo2 + build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -306,80 +345,103 @@ end it "gives a useful error if no sources are set" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false gem "rack" G - bundle :install - expect(err).to include("Your Gemfile has no gem server sources") + expect(err).to include("This Gemfile does not include an explicit global source. " \ + "Not using an explicit global source may result in a different lockfile being generated depending on " \ + "the gems you have installed locally before bundler is run. " \ + "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\".") end it "creates a Gemfile.lock on a blank Gemfile" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" G - expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true) + expect(File.exist?(bundled_app_lock)).to eq(true) end - context "throws a warning if a gem is added twice in Gemfile" do - it "without version requirements" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack" - gem "rack" - G + it "throws a warning if a gem is added twice in Gemfile without version requirements" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rack" + gem "rack" + G - expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.") - expect(err).to include("Remove any duplicate entries and specify the gem only once.") - expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.") - end + expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.") + expect(err).to include("Remove any duplicate entries and specify the gem only once.") + expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.") + end - it "with same versions" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack", "1.0" - gem "rack", "1.0" - G + it "throws a warning if a gem is added twice in Gemfile with same versions" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rack", "1.0" + gem "rack", "1.0" + G - expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.") - expect(err).to include("Remove any duplicate entries and specify the gem only once.") - expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.") - end + expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.") + expect(err).to include("Remove any duplicate entries and specify the gem only once.") + expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.") end - context "throws an error if a gem is added twice in Gemfile" do - it "when version of one dependency is not specified" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack" - gem "rack", "1.0" - G + it "does not throw a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency" do + build_lib "my-gem", :path => bundled_app do |s| + s.add_development_dependency "my-private-gem" + end - expect(err).to include("You cannot specify the same gem twice with different version requirements") - expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).") + build_repo2 do + build_gem "my-private-gem" end - it "when different versions of both dependencies are specified" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "rack", "1.0" - gem "rack", "1.1" - G + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" - expect(err).to include("You cannot specify the same gem twice with different version requirements") - expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).") - end + gemspec + + gem "my-private-gem", :group => :development + G + + bundle :install + + expect(err).to be_empty + expect(the_bundle).to include_gems("my-private-gem 1.0") + end + + it "throws an error if a gem is added twice in Gemfile when version of one dependency is not specified" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rack" + gem "rack", "1.0" + G + + expect(err).to include("You cannot specify the same gem twice with different version requirements") + expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).") + end + + it "throws an error if a gem is added twice in Gemfile when different versions of both dependencies are specified" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rack", "1.0" + gem "rack", "1.1" + G + + expect(err).to include("You cannot specify the same gem twice with different version requirements") + expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).") end it "gracefully handles error when rubygems server is unavailable" do - install_gemfile <<-G, :artifice => nil + skip "networking issue" if Gem.win_platform? + + install_gemfile <<-G, :artifice => nil, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" source "http://0.0.0.0:9384" do gem 'foo' end G - bundle :install, :artifice => nil expect(err).to include("Could not fetch specs from http://0.0.0.0:9384/") expect(err).not_to include("file://") end @@ -397,7 +459,7 @@ build_gem "ruby-ajp", "1.0.0" end - install_gemfile <<-G, :full_index => true + install_gemfile <<-G, :full_index => true, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "ajp-rails", "0.0.0" @@ -405,7 +467,7 @@ expect(last_command.stdboth).not_to match(/Error Report/i) expect(err).to include("An error occurred while installing ajp-rails (0.0.0), and Bundler cannot continue."). - and include("Make sure that `gem install ajp-rails -v '0.0.0' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling.") + and include("Bundler::APIResponseInvalidDependenciesError") end it "doesn't blow up when the local .bundle/config is empty" do @@ -417,7 +479,6 @@ gem 'foo' G - expect(exitstatus).to eq(0) if exitstatus end it "doesn't blow up when the global .bundle/config is empty" do @@ -429,7 +490,6 @@ gem 'foo' G - expect(exitstatus).to eq(0) if exitstatus end end @@ -438,26 +498,26 @@ context "and using an unsupported Ruby version" do it "prints an error" do - install_gemfile <<-G - ::RUBY_VERSION = '2.0.1' - ruby '~> 2.2' + install_gemfile <<-G, :raise_on_error => false + ruby '~> 1.2' + source "#{file_uri_for(gem_repo1)}" G - expect(err).to include("Your Ruby version is 2.0.1, but your Gemfile specified ~> 2.2") + expect(err).to include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified ~> 1.2") end end context "and using a supported Ruby version" do before do install_gemfile <<-G - ::RUBY_VERSION = '2.1.3' - ::RUBY_PATCHLEVEL = 100 - ruby '~> 2.1.0' + ruby '~> #{RUBY_VERSION}' + source "#{file_uri_for(gem_repo1)}" G end it "writes current Ruby version to Gemfile.lock" do - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -466,22 +526,22 @@ DEPENDENCIES RUBY VERSION - ruby 2.1.3p100 + #{Bundler::RubyVersion.system} BUNDLED WITH #{Bundler::VERSION} L end - it "updates Gemfile.lock with updated incompatible ruby version" do + it "updates Gemfile.lock with updated yet still compatible ruby version" do install_gemfile <<-G - ::RUBY_VERSION = '2.2.3' - ::RUBY_PATCHLEVEL = 100 - ruby '~> 2.2.0' + ruby '~> #{RUBY_VERSION[0..2]}' + source "#{file_uri_for(gem_repo1)}" G - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -490,55 +550,205 @@ DEPENDENCIES RUBY VERSION - ruby 2.2.3p100 + #{Bundler::RubyVersion.system} BUNDLED WITH #{Bundler::VERSION} L end + + it "does not crash when unlocking" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + ruby '>= 2.1.0' + G + + bundle "update" + + expect(err).not_to include("Could not find gem 'Ruby") + end end end describe "when Bundler root contains regex chars" do - before do + it "doesn't blow up when using the `gem` DSL" do root_dir = tmp("foo[]bar") FileUtils.mkdir_p(root_dir) - in_app_root_custom(root_dir) - end - it "doesn't blow up" do build_lib "foo" gemfile = <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "#{lib_path("foo-1.0")}" G - File.open("Gemfile", "w") do |file| + File.open("#{root_dir}/Gemfile", "w") do |file| file.puts gemfile end - bundle :install + bundle :install, :dir => root_dir + end + + it "doesn't blow up when using the `gemspec` DSL" do + root_dir = tmp("foo[]bar") + + FileUtils.mkdir_p(root_dir) + + build_lib "foo", :path => root_dir + gemfile = <<-G + source "#{file_uri_for(gem_repo1)}" + gemspec + G + File.open("#{root_dir}/Gemfile", "w") do |file| + file.puts gemfile + end - expect(exitstatus).to eq(0) if exitstatus + bundle :install, :dir => root_dir end end describe "when requesting a quiet install via --quiet" do - it "should be quiet" do + it "should be quiet if there are no warnings" do bundle "config set force_ruby_platform true" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' G bundle :install, :quiet => true - expect(err).to include("Could not find gem 'rack'") - expect(err).to_not include("Your Gemfile has no gem server sources") + expect(out).to be_empty + expect(err).to be_empty + end + + it "should still display warnings and errors" do + bundle "config set force_ruby_platform true" + + create_file("install_with_warning.rb", <<~RUBY) + require "#{lib_dir}/bundler" + require "#{lib_dir}/bundler/cli" + require "#{lib_dir}/bundler/cli/install" + + module RunWithWarning + def run + super + rescue + Bundler.ui.warn "BOOOOO" + raise + end + end + + Bundler::CLI::Install.prepend(RunWithWarning) + RUBY + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'non-existing-gem' + G + + bundle :install, :quiet => true, :raise_on_error => false, :env => { "RUBYOPT" => "-r#{bundled_app("install_with_warning.rb")}" } + expect(out).to be_empty + expect(err).to include("Could not find gem 'non-existing-gem'") + expect(err).to include("BOOOOO") + end + end + + describe "when bundle path does not have write access", :permissions do + let(:bundle_path) { bundled_app("vendor") } + + before do + FileUtils.mkdir_p(bundle_path) + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' + G + end + + it "should display a proper message to explain the problem" do + FileUtils.chmod(0o500, bundle_path) + + bundle "config set --local path vendor" + bundle :install, :raise_on_error => false + expect(err).to include(bundle_path.to_s) + expect(err).to include("grant write permissions") + end + end + + describe "when bundle gems path does not have write access", :permissions do + let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") } + + before do + FileUtils.mkdir_p(gems_path) + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' + G + end + + it "should display a proper message to explain the problem" do + FileUtils.chmod("-x", gems_path) + bundle "config set --local path vendor" + + begin + bundle :install, :raise_on_error => false + ensure + FileUtils.chmod("+x", gems_path) + end + + expect(err).not_to include("ERROR REPORT TEMPLATE") + + expect(err).to include( + "There was an error while trying to create `#{gems_path.join("rack-1.0.0")}`. " \ + "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{gems_path}`." + ) + end + end + + describe "when the path of a specific gem is not writable", :permissions do + let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") } + let(:foo_path) { gems_path.join("foo-1.0.0") } + + before do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.write "CHANGELOG.md", "foo" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem 'foo' + G + end + + it "should display a proper message to explain the problem" do + bundle "config set --local path vendor" + bundle :install + expect(out).to include("Bundle complete!") + expect(err).to be_empty + + FileUtils.chmod("-x", foo_path) + + begin + bundle "install --redownload", :raise_on_error => false + ensure + FileUtils.chmod("+x", foo_path) + end + + expect(err).not_to include("ERROR REPORT TEMPLATE") + + expect(err).to include( + "There was an error while trying to delete `#{foo_path}`. " \ + "It is likely that you need to grant executable permissions for all parent directories " \ + "and write permissions for `#{gems_path}`, and the same thing for all subdirectories inside #{foo_path}." + ) end end - describe "when bundle path does not have write access" do + describe "when bundle cache path does not have write access", :permissions do + let(:cache_path) { bundled_app("vendor/#{Bundler.ruby_scope}/cache") } + before do - FileUtils.mkdir_p(bundled_app("vendor")) + FileUtils.mkdir_p(cache_path) gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem 'rack' @@ -546,26 +756,27 @@ end it "should display a proper message to explain the problem" do - FileUtils.chmod(0o500, bundled_app("vendor")) + FileUtils.chmod(0o500, cache_path) - bundle :install, forgotten_command_line_options(:path => "vendor") - expect(err).to include(bundled_app("vendor").to_s) + bundle "config set --local path vendor" + bundle :install, :raise_on_error => false + expect(err).to include(cache_path.to_s) expect(err).to include("grant write permissions") end end context "after installing with --standalone" do before do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - forgotten_command_line_options(:path => "bundle") - bundle! "install", :standalone => true + bundle "config set --local path bundle" + bundle "install", :standalone => true end it "includes the standalone path" do - bundle! "binstubs rack", :standalone => true + bundle "binstubs rack", :standalone => true standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip expect(standalone_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath) end @@ -580,10 +791,166 @@ end it "should display a helpful message explaining how to fix it" do - bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" } - expect(exitstatus).to eq(17) if exitstatus + bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }, :raise_on_error => false + expect(exitstatus).to eq(17) expect(err).to eq("Please CGI escape your usernames and passwords before " \ "setting them for authentication.") end end + + context "in a frozen bundle" do + before do + build_repo4 do + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-19" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + + gem "libv8" + G + + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + libv8 (8.4.255.0-x86_64-darwin-19) + + PLATFORMS + x86_64-darwin-19 + + DEPENDENCIES + libv8 + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "config set --local deployment true" + end + + it "should fail loudly if the lockfile platforms don't include the current platform" do + simulate_platform(Gem::Platform.new("x86_64-linux")) { bundle "install", :raise_on_error => false } + + expect(err).to eq( + "Your bundle only supports platforms [\"x86_64-darwin-19\"] but your local platform is x86_64-linux. " \ + "Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again." + ) + end + end + + context "with missing platform specific gems in lockfile" do + before do + build_repo4 do + build_gem "racc", "1.5.2" + + build_gem "nokogiri", "1.12.4" do |s| + s.platform = "x86_64-darwin" + s.add_runtime_dependency "racc", "~> 1.4" + end + + build_gem "nokogiri", "1.12.4" do |s| + s.platform = "x86_64-linux" + s.add_runtime_dependency "racc", "~> 1.4" + end + + build_gem "crass", "1.0.6" + + build_gem "loofah", "2.12.0" do |s| + s.add_runtime_dependency "crass", "~> 1.0.2" + s.add_runtime_dependency "nokogiri", ">= 1.5.9" + end + end + + gemfile <<-G + source "https://gem.repo4" + + ruby "#{RUBY_VERSION}" + + gem "loofah", "~> 2.12.0" + G + + lockfile <<-L + GEM + remote: https://gem.repo4/ + specs: + crass (1.0.6) + loofah (2.12.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + nokogiri (1.12.4-x86_64-darwin) + racc (~> 1.4) + racc (1.5.2) + + PLATFORMS + x86_64-darwin-20 + x86_64-linux + + DEPENDENCIES + loofah (~> 2.12.0) + + RUBY VERSION + #{Bundler::RubyVersion.system} + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "automatically fixes the lockfile" do + bundle "config set --local path vendor/bundle" + + simulate_platform "x86_64-linux" do + bundle "install", :artifice => "compact_index" + end + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + crass (1.0.6) + loofah (2.12.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + nokogiri (1.12.4-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.12.4-x86_64-linux) + racc (~> 1.4) + racc (1.5.2) + + PLATFORMS + x86_64-darwin-20 + x86_64-linux + + DEPENDENCIES + loofah (~> 2.12.0) + + RUBY VERSION + #{Bundler::RubyVersion.system} + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "with --local flag" do + before do + system_gems "rack-1.0.0", :path => default_bundle_path + end + + it "respects installed gems without fetching any remote sources" do + install_gemfile <<-G, :local => true + source "#{file_uri_for(gem_repo1)}" + + source "https://not-existing-source" do + gem "rack" + end + G + + expect(last_command).to be_success + end + end end diff --git a/ruby/spec/bundler/commands/licenses_spec.rb b/ruby/spec/bundler/commands/licenses_spec.rb index d4fa02d0a..a20398489 100644 --- a/ruby/spec/bundler/commands/licenses_spec.rb +++ b/ruby/spec/bundler/commands/licenses_spec.rb @@ -2,8 +2,14 @@ RSpec.describe "bundle licenses" do before :each do + build_repo2 do + build_gem "with_license" do |s| + s.license = "MIT" + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rails" gem "with_license" G @@ -18,7 +24,7 @@ it "performs an automatic bundle install" do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rails" gem "with_license" gem "foo" diff --git a/ruby/spec/bundler/commands/list_spec.rb b/ruby/spec/bundler/commands/list_spec.rb index 71d2136d3..66930ded7 100644 --- a/ruby/spec/bundler/commands/list_spec.rb +++ b/ruby/spec/bundler/commands/list_spec.rb @@ -3,7 +3,7 @@ RSpec.describe "bundle list" do context "with name-only and paths option" do it "raises an error" do - bundle "list --name-only --paths" + bundle "list --name-only --paths", :raise_on_error => false expect(err).to eq "The `--name-only` and `--paths` options cannot be used together" end @@ -11,7 +11,7 @@ context "with without-group and only-group option" do it "raises an error" do - bundle "list --without-group dev --only-group test" + bundle "list --without-group dev --only-group test", :raise_on_error => false expect(err).to eq "The `--only-group` and `--without-group` options cannot be used together" end @@ -24,25 +24,37 @@ gem "rack" gem "rspec", :group => [:test] + gem "rails", :group => [:production] G end context "when group is present" do it "prints the gems not in the specified group" do - bundle! "list --without-group test" + bundle "list --without-group test" expect(out).to include(" * rack (1.0.0)") + expect(out).to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end end context "when group is not found" do it "raises an error" do - bundle "list --without-group random" + bundle "list --without-group random", :raise_on_error => false expect(err).to eq "`random` group could not be found." end end + + context "when multiple groups" do + it "prints the gems not in the specified groups" do + bundle "list --without-group test production" + + expect(out).to include(" * rack (1.0.0)") + expect(out).not_to include(" * rails (2.3.2)") + expect(out).not_to include(" * rspec (1.2.7)") + end + end end describe "with only-group option" do @@ -52,12 +64,13 @@ gem "rack" gem "rspec", :group => [:test] + gem "rails", :group => [:production] G end context "when group is present" do it "prints the gems in the specified group" do - bundle! "list --only-group default" + bundle "list --only-group default" expect(out).to include(" * rack (1.0.0)") expect(out).not_to include(" * rspec (1.2.7)") @@ -66,11 +79,21 @@ context "when group is not found" do it "raises an error" do - bundle "list --only-group random" + bundle "list --only-group random", :raise_on_error => false expect(err).to eq "`random` group could not be found." end end + + context "when multiple groups" do + it "prints the gems in the specified groups" do + bundle "list --only-group default production" + + expect(out).to include(" * rack (1.0.0)") + expect(out).to include(" * rails (2.3.2)") + expect(out).not_to include(" * rspec (1.2.7)") + end + end end context "with name-only option" do @@ -94,6 +117,10 @@ context "with paths option" do before do build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "bar" end diff --git a/ruby/spec/bundler/commands/lock_spec.rb b/ruby/spec/bundler/commands/lock_spec.rb index 1d9813a83..ee1c3ffd4 100644 --- a/ruby/spec/bundler/commands/lock_spec.rb +++ b/ruby/spec/bundler/commands/lock_spec.rb @@ -15,7 +15,7 @@ def read_lockfile(file = "Gemfile.lock") gemfile <<-G source "#{file_uri_for(repo)}" gem "rails" - gem "with_license" + gem "weakling" gem "foo" G @@ -38,9 +38,9 @@ def read_lockfile(file = "Gemfile.lock") actionpack (= 2.3.2) activerecord (= 2.3.2) activeresource (= 2.3.2) - rake (= 12.3.2) - rake (12.3.2) - with_license (1.0) + rake (= 13.0.1) + rake (13.0.1) + weakling (0.0.3) PLATFORMS #{lockfile_platforms} @@ -48,7 +48,7 @@ def read_lockfile(file = "Gemfile.lock") DEPENDENCIES foo rails - with_license + weakling BUNDLED WITH #{Bundler::VERSION} @@ -78,15 +78,15 @@ def read_lockfile(file = "Gemfile.lock") it "writes a lockfile when there is an outdated lockfile using --update" do lockfile @lockfile.gsub("2.3.2", "2.3.1") - bundle! "lock --update" + bundle "lock --update" expect(read_lockfile).to eq(@lockfile) end it "does not fetch remote specs when using the --local option" do - bundle "lock --update --local" + bundle "lock --update --local", :raise_on_error => false - expect(err).to match(/sources listed in your Gemfile|installed locally/) + expect(err).to match(/locally installed gems/) end it "works with --gemfile flag" do @@ -133,7 +133,7 @@ def read_lockfile(file = "Gemfile.lock") end it "update specific gems using --update" do - lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("12.3.2", "10.0.1") + lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("13.0.1", "10.0.1") bundle "lock --update rails rake" @@ -143,7 +143,7 @@ def read_lockfile(file = "Gemfile.lock") it "errors when updating a missing specific gems using --update" do lockfile @lockfile - bundle "lock --update blahblah" + bundle "lock --update blahblah", :raise_on_error => false expect(err).to eq("Could not find gem 'blahblah'.") expect(read_lockfile).to eq(@lockfile) @@ -156,10 +156,10 @@ def read_lockfile(file = "Gemfile.lock") gem "thin" gem "rack_middleware", :group => "test" G - bundle! "config set without test" - bundle! "config set path .bundle" - bundle! "lock" - expect(bundled_app(".bundle")).not_to exist + bundle "config set without test" + bundle "config set path vendor/bundle" + bundle "lock" + expect(bundled_app("vendor/bundle")).not_to exist end # see update_spec for more coverage on same options. logic is shared so it's not necessary @@ -195,6 +195,8 @@ def read_lockfile(file = "Gemfile.lock") gem 'foo' gem 'qux' G + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end it "single gem updates dependent gem to minor" do @@ -211,14 +213,41 @@ def read_lockfile(file = "Gemfile.lock") end it "supports adding new platforms" do - bundle! "lock --add-platform java x86-mingw32" + bundle "lock --add-platform java x86-mingw32" + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) lockfile = Bundler::LockfileParser.new(read_lockfile) expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq) end + it "supports adding new platforms with force_ruby_platform = true" do + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0) + platform_specific (1.0-x86-linux) + + PLATFORMS + ruby + x86-linux + + DEPENDENCIES + platform_specific + L + + bundle "config set force_ruby_platform true" + bundle "lock --add-platform java x86-mingw32" + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + lockfile = Bundler::LockfileParser.new(read_lockfile) + expect(lockfile.platforms).to contain_exactly(rb, linux, java, mingw) + end + it "supports adding the `ruby` platform" do - bundle! "lock --add-platform ruby" + bundle "lock --add-platform ruby" + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) lockfile = Bundler::LockfileParser.new(read_lockfile) expect(lockfile.platforms).to match_array(local_platforms.unshift("ruby").uniq) end @@ -229,23 +258,24 @@ def read_lockfile(file = "Gemfile.lock") end it "allows removing platforms" do - bundle! "lock --add-platform java x86-mingw32" + bundle "lock --add-platform java x86-mingw32" + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) lockfile = Bundler::LockfileParser.new(read_lockfile) expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq) - bundle! "lock --remove-platform java" + bundle "lock --remove-platform java" lockfile = Bundler::LockfileParser.new(read_lockfile) expect(lockfile.platforms).to match_array(local_platforms.unshift(mingw).uniq) end it "errors when removing all platforms" do - bundle "lock --remove-platform #{local_platforms.join(" ")}" + bundle "lock --remove-platform #{local_platforms.join(" ")}", :raise_on_error => false expect(err).to include("Removing all platforms from the bundle is not allowed") end - # from https://github.com/bundler/bundler/issues/4896 + # from https://github.com/rubygems/bundler/issues/4896 it "properly adds platforms when platform requirements come from different dependencies" do build_repo4 do build_gem "ffi", "1.9.14" @@ -282,9 +312,9 @@ def read_lockfile(file = "Gemfile.lock") gem "gssapi" G - simulate_platform(mingw) { bundle! :lock } + simulate_platform(mingw) { bundle :lock } - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo4)}/ specs: @@ -307,9 +337,10 @@ def read_lockfile(file = "Gemfile.lock") #{Bundler::VERSION} G - simulate_platform(rb) { bundle! :lock } + bundle "config set --local force_ruby_platform true" + bundle :lock - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo4)}/ specs: @@ -336,6 +367,181 @@ def read_lockfile(file = "Gemfile.lock") G end + it "doesn't crash when an update candidate doesn't have any matching platform" do + build_repo4 do + build_gem "libv8", "8.4.255.0" + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-19" + end + + build_gem "libv8", "15.0.71.48.1beta2" do |s| + s.platform = "x86_64-linux" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + + gem "libv8" + G + + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + libv8 (8.4.255.0) + libv8 (8.4.255.0-x86_64-darwin-19) + + PLATFORMS + ruby + x86_64-darwin-19 + + DEPENDENCIES + libv8 + + BUNDLED WITH + #{Bundler::VERSION} + G + + simulate_platform(Gem::Platform.new("x86_64-darwin-19")) { bundle "lock --update" } + + expect(out).to match(/Writing lockfile to.+Gemfile\.lock/) + end + + it "adds all more specific candidates when they all have the same dependencies" do + build_repo4 do + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-19" + end + + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-20" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + + gem "libv8" + G + + simulate_platform(Gem::Platform.new("x86_64-darwin")) { bundle "lock" } + + expect(lockfile).to eq <<~G + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + libv8 (8.4.255.0-x86_64-darwin-19) + libv8 (8.4.255.0-x86_64-darwin-20) + + PLATFORMS + x86_64-darwin + + DEPENDENCIES + libv8 + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + it "respects the previous lockfile if it had a matching less specific platform already locked, and installs the best variant for each platform" do + build_repo4 do + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-19" + end + + build_gem "libv8", "8.4.255.0" do |s| + s.platform = "x86_64-darwin-20" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + + gem "libv8" + G + + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + libv8 (8.4.255.0-x86_64-darwin-19) + libv8 (8.4.255.0-x86_64-darwin-20) + + PLATFORMS + x86_64-darwin + + DEPENDENCIES + libv8 + + BUNDLED WITH + #{Bundler::VERSION} + G + + previous_lockfile = lockfile + + %w[x86_64-darwin-19 x86_64-darwin-20].each do |platform| + simulate_platform(Gem::Platform.new(platform)) do + bundle "lock" + expect(lockfile).to eq(previous_lockfile) + + bundle "install" + expect(the_bundle).to include_gem("libv8 8.4.255.0 #{platform}") + end + end + end + + it "does not conflict on ruby requirements when adding new platforms" do + next_minor = Gem.ruby_version.segments[0..1].map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".") + + build_repo4 do + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x86_64-linux" + s.required_ruby_version = "< #{next_minor}.dev" + end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "universal-darwin" + s.required_ruby_version = "< #{next_minor}.dev" + end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x64-mingw32" + s.required_ruby_version = "< #{next_minor}.dev" + end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x64-mingw-ucrt" + s.required_ruby_version = "< #{next_minor}.dev" + end + end + + gemfile <<-G + source "https://localgemserver.test" + + gem "raygun-apm" + G + + lockfile <<-L + GEM + remote: https://localgemserver.test/ + specs: + raygun-apm (1.0.78-universal-darwin) + + PLATFORMS + x86_64-darwin-19 + + DEPENDENCIES + raygun-apm + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock --add-platform x86_64-linux", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + end + context "when an update is available" do let(:repo) { gem_repo2 } @@ -347,14 +553,14 @@ def read_lockfile(file = "Gemfile.lock") end it "does not implicitly update" do - bundle! "lock" + bundle "lock" expect(read_lockfile).to eq(@lockfile) end it "accounts for changes in the gemfile" do gemfile gemfile.gsub('"foo"', '"foo", "2.0"') - bundle! "lock" + bundle "lock" expect(read_lockfile).to eq(@lockfile.sub("foo (1.0)", "foo (2.0)").sub(/foo$/, "foo (= 2.0)")) end diff --git a/ruby/spec/bundler/commands/newgem_spec.rb b/ruby/spec/bundler/commands/newgem_spec.rb index 708b41f62..55a04b69c 100644 --- a/ruby/spec/bundler/commands/newgem_spec.rb +++ b/ruby/spec/bundler/commands/newgem_spec.rb @@ -10,92 +10,68 @@ def gem_skeleton_assertions expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist end + def bundle_exec_rubocop + prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec")) + bundle "config set path #{rubocop_gems}", :dir => bundled_app(gem_name) + bundle "exec rubocop --debug --config .rubocop.yml", :dir => bundled_app(gem_name) + end + + def bundle_exec_standardrb + prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec")) + bundle "config set path #{standard_gems}", :dir => bundled_app(gem_name) + bundle "exec standardrb --debug", :dir => bundled_app(gem_name) + end + let(:generated_gemspec) { Bundler.load_gemspec_uncached(bundled_app(gem_name).join("#{gem_name}.gemspec")) } let(:gem_name) { "mygem" } let(:require_path) { "mygem" } - before do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false" - git_config_content = <<-EOF - [user] - name = "Bundler User" - email = user@example.com - [github] - user = bundleuser - EOF - @git_config_location = ENV["GIT_CONFIG"] - path = "#{tmp}/test_git_config.txt" - File.open(path, "w") {|f| f.write(git_config_content) } - ENV["GIT_CONFIG"] = path - end - - after do - FileUtils.rm(ENV["GIT_CONFIG"]) if File.exist?(ENV["GIT_CONFIG"]) - ENV["GIT_CONFIG"] = @git_config_location - end - - shared_examples_for "git config is present" do - context "git config user.{name,email} present" do - it "sets gemspec author to git user.name if available" do - expect(generated_gemspec.authors.first).to eq("Bundler User") - end + let(:minitest_test_file_path) { "test/test_mygem.rb" } - it "sets gemspec email to git user.email if available" do - expect(generated_gemspec.email.first).to eq("user@example.com") - end - end - end - - shared_examples_for "git config is absent" do - it "sets gemspec author to default message if git user.name is not set or empty" do - expect(generated_gemspec.authors.first).to eq("TODO: Write your name") - end + let(:minitest_test_class_name) { "class TestMygem < Minitest::Test" } - it "sets gemspec email to default message if git user.email is not set or empty" do - expect(generated_gemspec.email.first).to eq("TODO: Write your email address") - end + before do + sys_exec("git config --global user.name 'Bundler User'") + sys_exec("git config --global user.email user@example.com") + sys_exec("git config --global github.user bundleuser") end describe "git repo initialization" do - shared_examples_for "a gem with an initial git repo" do - before do - bundle! "gem #{gem_name} #{flags}" - end - - it "generates a gem skeleton with a .git folder" do - gem_skeleton_assertions - expect(bundled_app("#{gem_name}/.git")).to exist - end + it "generates a gem skeleton with a .git folder", :readline do + bundle "gem #{gem_name}" + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/.git")).to exist end - context "when using the default" do - it_behaves_like "a gem with an initial git repo" do - let(:flags) { "" } - end + it "generates a gem skeleton with a .git folder when passing --git", :readline do + bundle "gem #{gem_name} --git" + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/.git")).to exist end - context "when explicitly passing --git" do - it_behaves_like "a gem with an initial git repo" do - let(:flags) { "--git" } - end + it "generates a gem skeleton without a .git folder when passing --no-git", :readline do + bundle "gem #{gem_name} --no-git" + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/.git")).not_to exist end - context "when passing --no-git" do + context "on a path with spaces" do before do - bundle! "gem #{gem_name} --no-git" + Dir.mkdir(bundled_app("path with spaces")) end - it "generates a gem skeleton without a .git folder" do - gem_skeleton_assertions - expect(bundled_app("#{gem_name}/.git")).not_to exist + + it "properly initializes git repo", :readline do + bundle "gem #{gem_name}", :dir => bundled_app("path with spaces") + expect(bundled_app("path with spaces/#{gem_name}/.git")).to exist end end end shared_examples_for "--mit flag" do before do - bundle! "gem #{gem_name} --mit" + bundle "gem #{gem_name} --mit" end it "generates a gem skeleton with MIT license" do gem_skeleton_assertions @@ -106,7 +82,7 @@ def gem_skeleton_assertions shared_examples_for "--no-mit flag" do before do - bundle! "gem #{gem_name} --no-mit" + bundle "gem #{gem_name} --no-mit" end it "generates a gem skeleton without MIT license" do gem_skeleton_assertions @@ -115,43 +91,283 @@ def gem_skeleton_assertions end shared_examples_for "--coc flag" do - before do - bundle! "gem #{gem_name} --coc" - end it "generates a gem skeleton with MIT license" do + bundle "gem #{gem_name} --coc" gem_skeleton_assertions expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to exist end - describe "README additions" do - it "generates the README with a section for the Code of Conduct" do - expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") - expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md") - end + it "generates the README with a section for the Code of Conduct" do + bundle "gem #{gem_name} --coc" + expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md}) + end + + it "generates the README with a section for the Code of Conduct, respecting the configured git default branch", :git => ">= 2.28.0" do + sys_exec("git config --global init.defaultBranch main") + bundle "gem #{gem_name} --coc" + + expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/main/CODE_OF_CONDUCT.md") end end shared_examples_for "--no-coc flag" do before do - bundle! "gem #{gem_name} --no-coc" + bundle "gem #{gem_name} --no-coc" end it "generates a gem skeleton without Code of Conduct" do gem_skeleton_assertions expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to_not exist end - describe "README additions" do - it "generates the README without a section for the Code of Conduct" do - expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct") - expect(bundled_app("#{gem_name}/README.md").read).not_to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md") + it "generates the README without a section for the Code of Conduct" do + expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).not_to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md}) + end + end + + shared_examples_for "--changelog flag" do + before do + bundle "gem #{gem_name} --changelog" + end + it "generates a gem skeleton with a CHANGELOG", :readline do + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/CHANGELOG.md")).to exist + end + end + + shared_examples_for "--no-changelog flag" do + before do + bundle "gem #{gem_name} --no-changelog" + end + it "generates a gem skeleton without a CHANGELOG", :readline do + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/CHANGELOG.md")).to_not exist + end + end + + shared_examples_for "--rubocop flag" do + context "is deprecated", :bundler => "< 3" do + before do + bundle "gem #{gem_name} --rubocop" + end + + it "generates a gem skeleton with rubocop" do + gem_skeleton_assertions + expect(bundled_app("test-gem/Rakefile")).to read_as( + include("# frozen_string_literal: true"). + and(include('require "rubocop/rake_task"'). + and(include("RuboCop::RakeTask.new"). + and(match(/default:.+:rubocop/)))) + ) + end + + it "includes rubocop in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" } + expect(rubocop_dep).not_to be_nil + end + + it "generates a default .rubocop.yml" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + end + end + end + + shared_examples_for "--no-rubocop flag" do + context "is deprecated", :bundler => "< 3" do + define_negated_matcher :exclude, :include + + before do + bundle "gem #{gem_name} --no-rubocop" + end + + it "generates a gem skeleton without rubocop" do + gem_skeleton_assertions + expect(bundled_app("test-gem/Rakefile")).to read_as(exclude("rubocop")) + expect(bundled_app("test-gem/#{gem_name}.gemspec")).to read_as(exclude("rubocop")) end + + it "does not include rubocop in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" } + expect(rubocop_dep).to be_nil + end + + it "doesn't generate a default .rubocop.yml" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist + end + end + end + + shared_examples_for "--linter=rubocop flag" do + before do + bundle "gem #{gem_name} --linter=rubocop" + end + + it "generates a gem skeleton with rubocop" do + gem_skeleton_assertions + expect(bundled_app("test-gem/Rakefile")).to read_as( + include("# frozen_string_literal: true"). + and(include('require "rubocop/rake_task"'). + and(include("RuboCop::RakeTask.new"). + and(match(/default:.+:rubocop/)))) + ) + end + + it "includes rubocop in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" } + expect(rubocop_dep).not_to be_nil + end + + it "generates a default .rubocop.yml" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + end + end + + shared_examples_for "--linter=standard flag" do + before do + bundle "gem #{gem_name} --linter=standard" + end + + it "generates a gem skeleton with standard" do + gem_skeleton_assertions + expect(bundled_app("test-gem/Rakefile")).to read_as( + include('require "standard/rake"'). + and(match(/default:.+:standard/)) + ) + end + + it "includes standard in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + standard_dep = builder.dependencies.find {|d| d.name == "standard" } + expect(standard_dep).not_to be_nil + end + + it "generates a default .standard.yml" do + expect(bundled_app("#{gem_name}/.standard.yml")).to exist + end + end + + shared_examples_for "--linter=none flag" do + define_negated_matcher :exclude, :include + + before do + bundle "gem #{gem_name} --linter=none" + end + + it "generates a gem skeleton without rubocop" do + gem_skeleton_assertions + expect(bundled_app("test-gem/Rakefile")).to read_as(exclude("rubocop")) + expect(bundled_app("test-gem/#{gem_name}.gemspec")).to read_as(exclude("rubocop")) + end + + it "does not include rubocop in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" } + expect(rubocop_dep).to be_nil + end + + it "does not include standard in generated Gemfile" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + standard_dep = builder.dependencies.find {|d| d.name == "standard" } + expect(standard_dep).to be_nil + end + + it "doesn't generate a default .rubocop.yml" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist + end + + it "doesn't generate a default .standard.yml" do + expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist + end + end + + it "has no rubocop offenses when using --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --ext --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext, --test=minitest, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --ext --test=minitest --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext, --test=rspec, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --ext --test=rspec --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext, --ext=test-unit, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --ext --test=test-unit --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no standard offenses when using --linter=standard flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + bundle "gem #{gem_name} --linter=standard" + bundle_exec_standardrb + expect(last_command).to be_success + end + + shared_examples_for "CI config is absent" do + it "does not create any CI files" do + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist + expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist + expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist + expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist end end - context "README.md" do + shared_examples_for "test framework is absent" do + it "does not create any test framework files" do + expect(bundled_app("#{gem_name}/.rspec")).to_not exist + expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to_not exist + expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to_not exist + expect(bundled_app("#{gem_name}/test/#{require_path}.rb")).to_not exist + expect(bundled_app("#{gem_name}/test/test_helper.rb")).to_not exist + end + end + + context "README.md", :readline do context "git config github.user present" do before do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" end it "contribute URL set to git username" do @@ -162,7 +378,7 @@ def gem_skeleton_assertions context "git config github.user is absent" do before do - sys_exec("git config --unset github.user") + sys_exec("git config --global --unset github.user") bundle "gem #{gem_name}" end @@ -173,18 +389,18 @@ def gem_skeleton_assertions end end - it "creates a new git repository" do + it "creates a new git repository", :readline do bundle "gem #{gem_name}" expect(bundled_app("#{gem_name}/.git")).to exist end - context "when git is not available" do + context "when git is not available", :readline do # This spec cannot have `git` available in the test env before do load_paths = [lib_dir, spec_dir] load_path_str = "-I#{load_paths.join(File::PATH_SEPARATOR)}" - sys_exec "#{Gem.ruby} #{load_path_str} #{bindir.join("bundle")} gem #{gem_name}", "PATH" => "" + sys_exec "#{Gem.ruby} #{load_path_str} #{bindir.join("bundle")} gem #{gem_name}", :env => { "PATH" => "" } end it "creates the gem without the need for git" do @@ -200,25 +416,24 @@ def gem_skeleton_assertions end end - it "generates a valid gemspec" do - bundle! "gem newgem --bin" + it "generates a valid gemspec", :readline, :ruby_repo do + bundle "gem newgem --bin" prepare_gemspec(bundled_app("newgem", "newgem.gemspec")) - Dir.chdir(bundled_app("newgem")) do - gems = ["rake-12.3.2"] - system_gems gems, :path => :bundle_path - bundle! "exec rake build" - end + gems = ["rake-13.0.1"] + path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(:base => bundled_app("newgem")) : system_gem_path + system_gems gems, :path => path + bundle "exec rake build", :dir => bundled_app("newgem") expect(last_command.stdboth).not_to include("ERROR") end - context "gem naming with relative paths" do + context "gem naming with relative paths", :readline do it "resolves ." do create_temporary_dir("tmp") - bundle "gem ." + bundle "gem .", :dir => bundled_app("tmp") expect(bundled_app("tmp/lib/tmp.rb")).to exist end @@ -226,7 +441,7 @@ def gem_skeleton_assertions it "resolves .." do create_temporary_dir("temp/empty_dir") - bundle "gem .." + bundle "gem ..", :dir => bundled_app("temp/empty_dir") expect(bundled_app("temp/lib/temp.rb")).to exist end @@ -234,89 +449,164 @@ def gem_skeleton_assertions it "resolves relative directory" do create_temporary_dir("tmp/empty/tmp") - bundle "gem ../../empty" + bundle "gem ../../empty", :dir => bundled_app("tmp/empty/tmp") expect(bundled_app("tmp/empty/lib/empty.rb")).to exist end def create_temporary_dir(dir) - FileUtils.mkdir_p(dir) - Dir.chdir(dir) + FileUtils.mkdir_p(bundled_app(dir)) + end + end + + shared_examples_for "--github-username option" do |github_username| + before do + bundle "gem #{gem_name} --github-username=#{github_username}" + end + + it "generates a gem skeleton" do + gem_skeleton_assertions + end + + it "contribute URL set to given github username" do + expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]") + expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/#{github_username}") + end + end + + shared_examples_for "github_username configuration" do + context "with github_username setting set to some value" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username" + bundle "gem #{gem_name}" + end + + it "generates a gem skeleton" do + gem_skeleton_assertions + end + + it "contribute URL set to bundle config setting" do + expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]") + expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/different_username") + end + end + + context "with github_username setting set to false" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false" + bundle "gem #{gem_name}" + end + + it "generates a gem skeleton" do + gem_skeleton_assertions + end + + it "contribute URL set to [USERNAME]" do + expect(bundled_app("#{gem_name}/README.md").read).to include("[USERNAME]") + expect(bundled_app("#{gem_name}/README.md").read).not_to include("github.com/bundleuser") + end end end shared_examples_for "generating a gem" do it "generates a gem skeleton" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to exist expect(bundled_app("#{gem_name}/Gemfile")).to exist expect(bundled_app("#{gem_name}/Rakefile")).to exist expect(bundled_app("#{gem_name}/lib/#{require_path}.rb")).to exist expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist + expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs")).to exist expect(bundled_app("#{gem_name}/.gitignore")).to exist expect(bundled_app("#{gem_name}/bin/setup")).to exist expect(bundled_app("#{gem_name}/bin/console")).to exist expect(bundled_app("#{gem_name}/bin/setup")).to be_executable expect(bundled_app("#{gem_name}/bin/console")).to be_executable + expect(bundled_app("#{gem_name}/bin/setup").read).to start_with("#!") + expect(bundled_app("#{gem_name}/bin/console").read).to start_with("#!") end it "starts with version 0.1.0" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/VERSION = "0.1.0"/) end + it "declare String type for VERSION constant" do + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs").read).to match(/VERSION: String/) + end + context "git config user.{name,email} is set" do before do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" + end + + it "sets gemspec author to git user.name if available" do + expect(generated_gemspec.authors.first).to eq("Bundler User") end - it_should_behave_like "git config is present" + it "sets gemspec email to git user.email if available" do + expect(generated_gemspec.email.first).to eq("user@example.com") + end end context "git config user.{name,email} is not set" do before do - `git config --unset user.name` - `git config --unset user.email` + sys_exec("git config --global --unset user.name") + sys_exec("git config --global --unset user.email") bundle "gem #{gem_name}" end - it_should_behave_like "git config is absent" + it "sets gemspec author to default message if git user.name is not set or empty" do + expect(generated_gemspec.authors.first).to eq("TODO: Write your name") + end + + it "sets gemspec email to default message if git user.email is not set or empty" do + expect(generated_gemspec.email.first).to eq("TODO: Write your email address") + end end it "sets gemspec metadata['allowed_push_host']" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" expect(generated_gemspec.metadata["allowed_push_host"]). - to match(/mygemserver\.com/) + to match(/example\.com/) end it "sets a minimum ruby version" do - bundle! "gem #{gem_name}" - - bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec + bundle "gem #{gem_name}" - expect(bundler_gemspec.required_ruby_version).to eq(generated_gemspec.required_ruby_version) + expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=") end it "requires the version file" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" - expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require "#{require_path}/version"}) + expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require_relative "#{require_relative_path}/version"}) end it "creates a base error class" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/class Error < StandardError; end$/) end + it "does not include the gemspec file in files" do + bundle "gem #{gem_name}" + + bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec + + expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec") + end + it "runs rake without problems" do - bundle! "gem #{gem_name}" + bundle "gem #{gem_name}" - system_gems ["rake-12.3.2"] + system_gems ["rake-13.0.1"] rakefile = strip_whitespace <<-RAKEFILE task :default do @@ -327,10 +617,8 @@ def create_temporary_dir(dir) file.puts rakefile end - Dir.chdir(bundled_app(gem_name)) do - sys_exec(rake) - expect(out).to include("SUCCESS") - end + sys_exec(rake, :dir => bundled_app(gem_name)) + expect(out).to include("SUCCESS") end context "--exe parameter set" do @@ -366,13 +654,7 @@ def create_temporary_dir(dir) bundle "gem #{gem_name}" end - it "doesn't create any spec/test file" do - expect(bundled_app("#{gem_name}/.rspec")).to_not exist - expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to_not exist - expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to_not exist - expect(bundled_app("#{gem_name}/test/#{require_path}.rb")).to_not exist - expect(bundled_app("#{gem_name}/test/minitest_helper.rb")).to_not exist - end + it_behaves_like "test framework is absent" end context "--test parameter set to rspec" do @@ -387,13 +669,12 @@ def create_temporary_dir(dir) end it "depends on a specific version of rspec in generated Gemfile" do - Dir.chdir(bundled_app(gem_name)) do - builder = Bundler::Dsl.new - builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) - builder.dependencies - rspec_dep = builder.dependencies.find {|d| d.name == "rspec" } - expect(rspec_dep).to be_specific - end + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + rspec_dep = builder.dependencies.find {|d| d.name == "rspec" } + expect(rspec_dep).to be_specific end it "requires the main file" do @@ -425,7 +706,7 @@ def create_temporary_dir(dir) end it "builds spec skeleton" do - expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist + expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist end end @@ -436,17 +717,16 @@ def create_temporary_dir(dir) end it "depends on a specific version of minitest" do - Dir.chdir(bundled_app(gem_name)) do - builder = Bundler::Dsl.new - builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) - builder.dependencies - minitest_dep = builder.dependencies.find {|d| d.name == "minitest" } - expect(minitest_dep).to be_specific - end + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + minitest_dep = builder.dependencies.find {|d| d.name == "minitest" } + expect(minitest_dep).to be_specific end it "builds spec skeleton" do - expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist + expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist end @@ -454,12 +734,16 @@ def create_temporary_dir(dir) expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}")) end - it "requires 'minitest_helper'" do - expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper")) + it "requires 'test_helper'" do + expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(%(require "test_helper")) + end + + it "defines valid test class name" do + expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(minitest_test_class_name) end it "creates a default test which fails" do - expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include("assert false") + expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include("assert false") end end @@ -471,6 +755,66 @@ def create_temporary_dir(dir) it "creates a default rake task to run the test suite" do rakefile = strip_whitespace <<-RAKEFILE + # frozen_string_literal: true + + require "bundler/gem_tasks" + require "rake/testtask" + + Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.test_files = FileList["test/**/test_*.rb"] + end + + task default: :test + RAKEFILE + + expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile) + end + end + + context "--test parameter set to test-unit" do + before do + bundle "gem #{gem_name} --test=test-unit" + end + + it "depends on a specific version of test-unit" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + builder = Bundler::Dsl.new + builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile")) + builder.dependencies + test_unit_dep = builder.dependencies.find {|d| d.name == "test-unit" } + expect(test_unit_dep).to be_specific + end + + it "builds spec skeleton" do + expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist + expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist + end + + it "requires the main file" do + expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}")) + end + + it "requires 'test_helper'" do + expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper")) + end + + it "creates a default test which fails" do + expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include("assert_equal(\"expected\", \"actual\")") + end + end + + context "gem.test setting set to test-unit" do + before do + bundle "config set gem.test test-unit" + bundle "gem #{gem_name}" + end + + it "creates a default rake task to run the test suite" do + rakefile = strip_whitespace <<-RAKEFILE + # frozen_string_literal: true + require "bundler/gem_tasks" require "rake/testtask" @@ -480,81 +824,498 @@ def create_temporary_dir(dir) t.test_files = FileList["test/**/*_test.rb"] end - task :default => :test + task default: :test RAKEFILE expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile) end end - context "--test with no arguments" do + context "gem.test set to rspec and --test with no arguments", :hint_text do before do + bundle "config set gem.test rspec" bundle "gem #{gem_name} --test" end - it "defaults to rspec" do + it "builds spec skeleton" do + expect(bundled_app("#{gem_name}/.rspec")).to exist + expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to exist expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist - expect(bundled_app("#{gem_name}/test/minitest_helper.rb")).to_not exist end - it "creates a .travis.yml file to test the library against the current Ruby version on Travis CI" do - expect(bundled_app("#{gem_name}/.travis.yml").read).to match(/- #{RUBY_VERSION}/) + it "hints that --test is already configured" do + expect(out).to match("rspec is already configured, ignoring --test flag.") + end + end + + context "gem.test setting set to false and --test with no arguments", :hint_text do + before do + bundle "config set gem.test false" + bundle "gem #{gem_name} --test" + end + + it "asks to generate test files" do + expect(out).to match("Do you want to generate tests with your gem?") + end + + it "hints that the choice will only be applied to the current gem" do + expect(out).to match("Your choice will only be applied to this gem.") + end + + it_behaves_like "test framework is absent" + end + + context "gem.test setting not set and --test with no arguments", :hint_text do + before do + bundle "gem #{gem_name} --test" + end + + it "asks to generate test files" do + expect(out).to match("Do you want to generate tests with your gem?") + end + + it "hints that the choice will be applied to future bundle gem calls" do + hint = "Future `bundle gem` calls will use your choice. " \ + "This setting can be changed anytime with `bundle config gem.test`." + expect(out).to match(hint) + end + + it_behaves_like "test framework is absent" + end + + context "--ci with no argument" do + it "does not generate any CI config" do + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist + expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist + expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist + expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist + end + end + + context "--ci set to github" do + it "generates a GitHub Actions config file" do + bundle "gem #{gem_name} --ci=github" + + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist + end + end + + context "--ci set to gitlab" do + it "generates a GitLab CI config file" do + bundle "gem #{gem_name} --ci=gitlab" + + expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist + end + end + + context "--ci set to circle" do + it "generates a CircleCI config file" do + bundle "gem #{gem_name} --ci=circle" + + expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist + end + end + + context "--ci set to travis" do + it "generates a Travis CI config file" do + bundle "gem #{gem_name} --ci=travis" + + expect(bundled_app("#{gem_name}/.travis.yml")).to exist + end + end + + context "gem.ci setting set to none" do + it "doesn't generate any CI config" do + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist + expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist + expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist + expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist + end + end + + context "gem.ci setting set to github" do + it "generates a GitHub Actions config file" do + bundle "config set gem.ci github" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist + end + end + + context "gem.ci setting set to travis" do + it "generates a Travis CI config file" do + bundle "config set gem.ci travis" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.travis.yml")).to exist + end + end + + context "gem.ci setting set to gitlab" do + it "generates a GitLab CI config file" do + bundle "config set gem.ci gitlab" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist + end + end + + context "gem.ci setting set to circle" do + it "generates a CircleCI config file" do + bundle "config set gem.ci circle" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist + end + end + + context "gem.ci set to github and --ci with no arguments", :hint_text do + before do + bundle "config set gem.ci github" + bundle "gem #{gem_name} --ci" + end + + it "generates a GitHub Actions config file" do + expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist + end + + it "hints that --ci is already configured" do + expect(out).to match("github is already configured, ignoring --ci flag.") + end + end + + context "gem.ci setting set to false and --ci with no arguments", :hint_text do + before do + bundle "config set gem.ci false" + bundle "gem #{gem_name} --ci" + end + + it "asks to setup CI" do + expect(out).to match("Do you want to set up continuous integration for your gem?") + end + + it "hints that the choice will only be applied to the current gem" do + expect(out).to match("Your choice will only be applied to this gem.") + end + end + + context "gem.ci setting not set and --ci with no arguments", :hint_text do + before do + bundle "gem #{gem_name} --ci" + end + + it "asks to setup CI" do + expect(out).to match("Do you want to set up continuous integration for your gem?") + end + + it "hints that the choice will be applied to future bundle gem calls" do + hint = "Future `bundle gem` calls will use your choice. " \ + "This setting can be changed anytime with `bundle config gem.ci`." + expect(out).to match(hint) + end + end + + context "--linter with no argument" do + it "does not generate any linter config" do + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist + expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist + end + end + + context "--linter set to rubocop" do + it "generates a RuboCop config" do + bundle "gem #{gem_name} --linter=rubocop" + + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist + end + end + + context "--linter set to standard" do + it "generates a Standard config" do + bundle "gem #{gem_name} --linter=standard" + + expect(bundled_app("#{gem_name}/.standard.yml")).to exist + expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist + end + end + + context "gem.linter setting set to none" do + it "doesn't generate any linter config" do + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist + expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist + end + end + + context "gem.linter setting set to rubocop" do + it "generates a RuboCop config file" do + bundle "config set gem.linter rubocop" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + end + end + + context "gem.linter setting set to standard" do + it "generates a Standard config file" do + bundle "config set gem.linter standard" + bundle "gem #{gem_name}" + + expect(bundled_app("#{gem_name}/.standard.yml")).to exist + end + end + + context "gem.rubocop setting set to true", :bundler => "< 3" do + before do + bundle "config set gem.rubocop true" + bundle "gem #{gem_name}" + end + + it "generates rubocop config" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + end + + it "unsets gem.rubocop" do + bundle "config gem.rubocop" + expect(out).to include("You have not configured a value for `gem.rubocop`") + end + + it "sets gem.linter=rubocop instead" do + bundle "config gem.linter" + expect(out).to match(/Set for the current user .*: "rubocop"/) + end + end + + context "gem.linter set to rubocop and --linter with no arguments", :hint_text do + before do + bundle "config set gem.linter rubocop" + bundle "gem #{gem_name} --linter" + end + + it "generates a RuboCop config file" do + expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist + end + + it "hints that --linter is already configured" do + expect(out).to match("rubocop is already configured, ignoring --linter flag.") + end + end + + context "gem.linter setting set to false and --linter with no arguments", :hint_text do + before do + bundle "config set gem.linter false" + bundle "gem #{gem_name} --linter" + end + + it "asks to setup a linter" do + expect(out).to match("Do you want to add a code linter and formatter to your gem?") + end + + it "hints that the choice will only be applied to the current gem" do + expect(out).to match("Your choice will only be applied to this gem.") + end + end + + context "gem.linter setting not set and --linter with no arguments", :hint_text do + before do + bundle "gem #{gem_name} --linter" + end + + it "asks to setup a linter" do + expect(out).to match("Do you want to add a code linter and formatter to your gem?") + end + + it "hints that the choice will be applied to future bundle gem calls" do + hint = "Future `bundle gem` calls will use your choice. " \ + "This setting can be changed anytime with `bundle config gem.linter`." + expect(out).to match(hint) end end context "--edit option" do it "opens the generated gemspec in the user's text editor" do output = bundle "gem #{gem_name} --edit=echo" - gemspec_path = File.join(Dir.pwd, gem_name, "#{gem_name}.gemspec") + gemspec_path = File.join(bundled_app, gem_name, "#{gem_name}.gemspec") expect(output).to include("echo \"#{gemspec_path}\"") end end end - context "testing --mit and --coc options against bundle config settings" do + context "testing --mit and --coc options against bundle config settings", :readline do let(:gem_name) { "test-gem" } let(:require_path) { "test/gem" } context "with mit option in bundle config settings set to true" do before do - global_config "BUNDLE_GEM__MIT" => "true", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false" + global_config "BUNDLE_GEM__MIT" => "true" end it_behaves_like "--mit flag" it_behaves_like "--no-mit flag" end context "with mit option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__MIT" => "false" + end it_behaves_like "--mit flag" it_behaves_like "--no-mit flag" end context "with coc option in bundle config settings set to true" do before do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "true" + global_config "BUNDLE_GEM__COC" => "true" end it_behaves_like "--coc flag" it_behaves_like "--no-coc flag" end context "with coc option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__COC" => "false" + end it_behaves_like "--coc flag" it_behaves_like "--no-coc flag" end + + context "with rubocop option in bundle config settings set to true" do + before do + global_config "BUNDLE_GEM__RUBOCOP" => "true" + end + it_behaves_like "--linter=rubocop flag" + it_behaves_like "--linter=standard flag" + it_behaves_like "--linter=none flag" + it_behaves_like "--rubocop flag" + it_behaves_like "--no-rubocop flag" + end + + context "with rubocop option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__RUBOCOP" => "false" + end + it_behaves_like "--linter=rubocop flag" + it_behaves_like "--linter=standard flag" + it_behaves_like "--linter=none flag" + it_behaves_like "--rubocop flag" + it_behaves_like "--no-rubocop flag" + end + + context "with linter option in bundle config settings set to rubocop" do + before do + global_config "BUNDLE_GEM__LINTER" => "rubocop" + end + it_behaves_like "--linter=rubocop flag" + it_behaves_like "--linter=standard flag" + it_behaves_like "--linter=none flag" + end + + context "with linter option in bundle config settings set to standard" do + before do + global_config "BUNDLE_GEM__LINTER" => "standard" + end + it_behaves_like "--linter=rubocop flag" + it_behaves_like "--linter=standard flag" + it_behaves_like "--linter=none flag" + end + + context "with linter option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__LINTER" => "false" + end + it_behaves_like "--linter=rubocop flag" + it_behaves_like "--linter=standard flag" + it_behaves_like "--linter=none flag" + end + + context "with changelog option in bundle config settings set to true" do + before do + global_config "BUNDLE_GEM__CHANGELOG" => "true" + end + it_behaves_like "--changelog flag" + it_behaves_like "--no-changelog flag" + end + + context "with changelog option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__CHANGELOG" => "false" + end + it_behaves_like "--changelog flag" + it_behaves_like "--no-changelog flag" + end + end + + context "testing --github-username option against git and bundle config settings", :readline do + context "without git config set" do + before do + sys_exec("git config --global --unset github.user") + end + context "with github-username option in bundle config settings set to some value" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username" + end + it_behaves_like "--github-username option", "gh_user" + end + + context "with github-username option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false" + end + it_behaves_like "--github-username option", "gh_user" + end + end + + context "with git config set" do + context "with github-username option in bundle config settings set to some value" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username" + end + it_behaves_like "--github-username option", "gh_user" + end + + context "with github-username option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false" + end + it_behaves_like "--github-username option", "gh_user" + end + end end - context "gem naming with underscore" do + context "testing github_username bundle config against git config settings", :readline do + context "without git config set" do + before do + sys_exec("git config --global --unset github.user") + end + + it_behaves_like "github_username configuration" + end + + context "with git config set" do + it_behaves_like "github_username configuration" + end + end + + context "gem naming with underscore", :readline do let(:gem_name) { "test_gem" } let(:require_path) { "test_gem" } - let(:flags) { nil } + let(:require_relative_path) { "test_gem" } - before do - bundle! ["gem", gem_name, flags].compact.join(" ") - end + let(:minitest_test_file_path) { "test/test_test_gem.rb" } + + let(:minitest_test_class_name) { "class TestTestGem < Minitest::Test" } + + let(:flags) { nil } it "does not nest constants" do + bundle ["gem", gem_name, flags].compact.join(" ") expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module TestGem/) expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module TestGem/) end @@ -564,6 +1325,10 @@ def create_temporary_dir(dir) context "--ext parameter set" do let(:flags) { "--ext" } + before do + bundle ["gem", gem_name, flags].compact.join(" ") + end + it "builds ext skeleton" do expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist @@ -576,16 +1341,18 @@ def create_temporary_dir(dir) it "depends on compile task for build" do rakefile = strip_whitespace <<-RAKEFILE + # frozen_string_literal: true + require "bundler/gem_tasks" require "rake/extensiontask" - task :build => :compile + task build: :compile Rake::ExtensionTask.new("#{gem_name}") do |ext| ext.lib_dir = "lib/#{gem_name}" end - task :default => [:clobber, :compile, :spec] + task default: %i[clobber compile] RAKEFILE expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile) @@ -593,16 +1360,19 @@ def create_temporary_dir(dir) end end - context "gem naming with dashed" do + context "gem naming with dashed", :readline do let(:gem_name) { "test-gem" } let(:require_path) { "test/gem" } - before do - bundle! "gem #{gem_name}" - end + let(:require_relative_path) { "gem" } + + let(:minitest_test_file_path) { "test/test/test_gem.rb" } + + let(:minitest_test_class_name) { "class Test::TestGem < Minitest::Test" } it "nests constants so they work" do + bundle "gem #{gem_name}" expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module Test\n module Gem/) expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module Test\n module Gem/) end @@ -611,29 +1381,29 @@ def create_temporary_dir(dir) end describe "uncommon gem names" do - it "can deal with two dashes" do - bundle! "gem a--a" + it "can deal with two dashes", :readline do + bundle "gem a--a" expect(bundled_app("a--a/a--a.gemspec")).to exist end it "fails gracefully with a ." do - bundle "gem foo.gemspec" + bundle "gem foo.gemspec", :raise_on_error => false expect(err).to end_with("Invalid gem name foo.gemspec -- `Foo.gemspec` is an invalid constant name") end it "fails gracefully with a ^" do - bundle "gem ^" + bundle "gem ^", :raise_on_error => false expect(err).to end_with("Invalid gem name ^ -- `^` is an invalid constant name") end it "fails gracefully with a space" do - bundle "gem 'foo bar'" + bundle "gem 'foo bar'", :raise_on_error => false expect(err).to end_with("Invalid gem name foo bar -- `Foo bar` is an invalid constant name") end it "fails gracefully when multiple names are passed" do - bundle "gem foo bar baz" + bundle "gem foo bar baz", :raise_on_error => false expect(err).to eq(<<-E.strip) ERROR: "bundle gem" was called with arguments ["foo", "bar", "baz"] Usage: "bundle gem NAME [OPTIONS]" @@ -641,9 +1411,9 @@ def create_temporary_dir(dir) end end - describe "#ensure_safe_gem_name" do + describe "#ensure_safe_gem_name", :readline do before do - bundle "gem #{subject}" + bundle "gem #{subject}", :raise_on_error => false end context "with an existing const name" do @@ -667,7 +1437,7 @@ def create_temporary_dir(dir) end end - context "on first run" do + context "on first run", :readline do it "asks about test framework" do global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false" @@ -677,20 +1447,32 @@ def create_temporary_dir(dir) expect(bundled_app("foobar/spec/spec_helper.rb")).to exist rakefile = strip_whitespace <<-RAKEFILE + # frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) - task :default => :spec + task default: :spec RAKEFILE expect(bundled_app("foobar/Rakefile").read).to eq(rakefile) expect(bundled_app("foobar/Gemfile").read).to include('gem "rspec"') end + it "asks about CI service" do + global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false" + + bundle "gem foobar" do |input, _, _| + input.puts "github" + end + + expect(bundled_app("foobar/.github/workflows/main.yml")).to exist + end + it "asks about MIT license" do - global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false" + global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false" bundle "config list" @@ -702,7 +1484,7 @@ def create_temporary_dir(dir) end it "asks about CoC" do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false" + global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false" bundle "gem foobar" do |input, _, _| input.puts "yes" @@ -710,21 +1492,32 @@ def create_temporary_dir(dir) expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist end + + it "asks about CHANGELOG" do + global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false", + "BUNDLE_GEM__COC" => "false" + + bundle "gem foobar" do |input, _, _| + input.puts "yes" + end + + expect(bundled_app("foobar/CHANGELOG.md")).to exist + end end - context "on conflicts with a previously created file" do + context "on conflicts with a previously created file", :readline do it "should fail gracefully" do - FileUtils.touch("conflict-foobar") - bundle "gem conflict-foobar" - expect(err).to include("Errno::ENOTDIR") - expect(exitstatus).to eql(32) if exitstatus + FileUtils.touch(bundled_app("conflict-foobar")) + bundle "gem conflict-foobar", :raise_on_error => false + expect(err).to eq("Couldn't create a new gem named `conflict-foobar` because there's an existing file named `conflict-foobar`.") + expect(exitstatus).to eql(32) end end - context "on conflicts with a previously created directory" do + context "on conflicts with a previously created directory", :readline do it "should succeed" do - FileUtils.mkdir_p("conflict-foobar/Gemfile") - bundle! "gem conflict-foobar" + FileUtils.mkdir_p(bundled_app("conflict-foobar/Gemfile")) + bundle "gem conflict-foobar" expect(out).to include("file_clash conflict-foobar/Gemfile"). and include "Initializing git repo in #{bundled_app("conflict-foobar")}" end diff --git a/ruby/spec/bundler/commands/open_spec.rb b/ruby/spec/bundler/commands/open_spec.rb index 8fae4af5b..53dc35c2c 100644 --- a/ruby/spec/bundler/commands/open_spec.rb +++ b/ruby/spec/bundler/commands/open_spec.rb @@ -30,7 +30,7 @@ end it "complains if gem not in bundle" do - bundle "open missing", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" } + bundle "open missing", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false expect(err).to match(/could not find gem 'missing'/i) end @@ -48,7 +48,7 @@ end it "suggests alternatives for similar-sounding gems" do - bundle "open Rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" } + bundle "open Rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false expect(err).to match(/did you mean rails\?/i) end @@ -58,7 +58,7 @@ expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}") end - it "select the gem from many match gems" do + it "select the gem from many match gems", :readline do env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" } bundle "open active", :env => env do |input, _, _| input.puts "2" @@ -67,9 +67,9 @@ expect(out).to match(/bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}\z/) end - it "allows selecting exit from many match gems" do + it "allows selecting exit from many match gems", :readline do env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" } - bundle! "open active", :env => env do |input, _, _| + bundle "open active", :env => env do |input, _, _| input.puts "0" end end @@ -87,14 +87,14 @@ end it "opens the editor with a clean env" do - bundle "open", :env => { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" } + bundle "open", :env => { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false expect(out).not_to include("BUNDLE_GEMFILE=") end end context "when opening a default gem" do let(:default_gems) do - ruby!(<<-RUBY).split("\n") + ruby(<<-RUBY).split("\n") if Gem::Specification.is_a?(Enumerable) puts Gem::Specification.select(&:default_gem?).map(&:name) end @@ -105,6 +105,7 @@ skip "No default gems available on this test run" if default_gems.empty? install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "json" G end diff --git a/ruby/spec/bundler/commands/outdated_spec.rb b/ruby/spec/bundler/commands/outdated_spec.rb index df911eaff..731d67af1 100644 --- a/ruby/spec/bundler/commands/outdated_spec.rb +++ b/ruby/spec/bundler/commands/outdated_spec.rb @@ -1,24 +1,24 @@ # frozen_string_literal: true RSpec.describe "bundle outdated" do - before :each do - build_repo2 do - build_git "foo", :path => lib_path("foo") - build_git "zebra", :path => lib_path("zebra") - end - - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "zebra", :git => "#{lib_path("zebra")}" - gem "foo", :git => "#{lib_path("foo")}" - gem "activesupport", "2.3.5" - gem "weakling", "~> 0.0.1" - gem "duradura", '7.0' - gem "terranova", '8' - G - end - describe "with no arguments" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + end + it "returns a sorted list of outdated gems" do update_repo2 do build_gem "activesupport", "3.0" @@ -27,15 +27,37 @@ update_git "zebra", :path => lib_path("zebra") end - bundle "outdated" + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 default + foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default + weakling 0.0.3 0.2 ~> 0.0.1 default + zebra 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default + TABLE + + expect(out).to match(Regexp.new(expected_output)) + end + + it "excludes header row from the sorting" do + update_repo2 do + build_gem "AAA", %w[1.0.0 2.0.0] + end - expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)") - expect(out).to include("weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)") - expect(out).to include("foo (newest 1.0") + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "AAA", "1.0.0" + G + + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE + Gem Current Latest Requested Groups + AAA 1.0.0 2.0.0 = 1.0.0 default + TABLE - # Gem names are one per-line, between "*" and their parenthesized version. - gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact - expect(gem_list).to eq(gem_list.sort) + expect(out).to include(expected_output.strip) end it "returns non zero exit status if outdated gems present" do @@ -44,15 +66,13 @@ update_git "foo", :path => lib_path("foo") end - bundle "outdated" + bundle "outdated", :raise_on_error => false - expect(exitstatus).to_not be_zero if exitstatus + expect(exitstatus).to_not be_zero end it "returns success exit status if no outdated gems present" do bundle "outdated" - - expect(exitstatus).to be_zero if exitstatus end it "adds gem group to dependency output when repo is updated" do @@ -69,14 +89,141 @@ update_repo2 { build_gem "activesupport", "3.0" } update_repo2 { build_gem "terranova", "9" } - bundle "outdated --verbose" - expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5) in groups \"development, test\"") - expect(out).to include("terranova (newest 9, installed 8, requested = 8) in group \"default\"") + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 development, test + terranova 8 9 = 8 default + TABLE + + expect(out).to end_with(expected_output) + end + end + + describe "with --verbose option" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + end + + it "shows the location of the latest version's gemspec if installed" do + bundle "config set clean false" + + update_repo2 { build_gem "activesupport", "3.0" } + update_repo2 { build_gem "terranova", "9" } + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "terranova", '9' + gem 'activesupport', '2.3.5' + G + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "terranova", '8' + gem 'activesupport', '2.3.5' + G + + bundle "outdated --verbose", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups Path + activesupport 2.3.5 3.0 = 2.3.5 default + terranova 8 9 = 8 default #{default_bundle_path("specifications/terranova-9.gemspec")} + TABLE + + expect(out).to end_with(expected_output) + end + end + + describe "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do + before do + build_repo2 do + build_gem "dotenv", "2.7.6" + + build_gem "oj", "3.11.3" + build_gem "oj", "3.11.5" + + build_gem "vcr", "6.0.0" + end + + build_repo gem_repo3 do + build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s| + s.add_dependency "oj" + end + end + + gemfile <<~G + source "https://gem.repo2" + + gem "dotenv" + + source "https://gem.repo3" do + gem 'pkg-gem-flowbyte-with-dep' + end + + gem "vcr",source: "https://gem.repo2" + G + + lockfile <<~L + GEM + remote: https://gem.repo2/ + remote: https://gem.repo3/ + specs: + dotenv (2.7.6) + oj (3.11.3) + pkg-gem-flowbyte-with-dep (1.0.0) + oj + vcr (6.0.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + dotenv + pkg-gem-flowbyte-with-dep! + vcr! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "works" do + bundle :install, :artifice => "compact_index" + bundle :outdated, :artifice => "compact_index", :raise_on_error => false + + expected_output = <<~TABLE + Gem Current Latest Requested Groups + oj 3.11.3 3.11.5 + TABLE + + expect(out).to include(expected_output.strip) end end describe "with --group option" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -89,62 +236,100 @@ G end - def test_group_option(group = nil, gems_list_size = 1) + def test_group_option(group) update_repo2 do build_gem "activesupport", "3.0" build_gem "terranova", "9" build_gem "duradura", "8.0" end - bundle "outdated --group #{group}" - - # Gem names are one per-line, between "*" and their parenthesized version. - gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact - expect(gem_list).to eq(gem_list.sort) - expect(gem_list.size).to eq gems_list_size + bundle "outdated --group #{group}", :raise_on_error => false end - it "not outdated gems" do + it "works when the bundle is up to date" do bundle "outdated --group" - expect(out).to include("Bundle up to date!") + expect(out).to end_with("Bundle up to date!") end it "returns a sorted list of outdated gems from one group => 'default'" do test_group_option("default") - expect(out).to include("===== Group \"default\" =====") - expect(out).to include("terranova (") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + terranova 8 9 = 8 default + TABLE - expect(out).not_to include("===== Groups \"development, test\" =====") - expect(out).not_to include("activesupport") - expect(out).not_to include("duradura") + expect(out).to end_with(expected_output) end it "returns a sorted list of outdated gems from one group => 'development'" do - test_group_option("development", 2) + test_group_option("development") - expect(out).not_to include("===== Group \"default\" =====") - expect(out).not_to include("terranova (") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 development, test + duradura 7.0 8.0 = 7.0 development, test + TABLE - expect(out).to include("===== Groups \"development, test\" =====") - expect(out).to include("activesupport") - expect(out).to include("duradura") + expect(out).to end_with(expected_output) end it "returns a sorted list of outdated gems from one group => 'test'" do - test_group_option("test", 2) + test_group_option("test") + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 development, test + duradura 7.0 8.0 = 7.0 development, test + TABLE + + expect(out).to end_with(expected_output) + end + end + + describe "with --groups option and outdated transitive dependencies" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + + build_gem "bar", %w[2.0.0] + + build_gem "bar_dependant", "7.0" do |s| + s.add_dependency "bar", "~> 2.0" + end + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "bar_dependant", '7.0' + G + + update_repo2 do + build_gem "bar", %w[3.0.0] + end + end + + it "returns a sorted list of outdated gems" do + bundle "outdated --groups", :raise_on_error => false - expect(out).not_to include("===== Group \"default\" =====") - expect(out).not_to include("terranova (") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + bar 2.0.0 3.0.0 + TABLE - expect(out).to include("===== Groups \"development, test\" =====") - expect(out).to include("activesupport") - expect(out).to include("duradura") + expect(out).to end_with(expected_output) end end describe "with --groups option" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -159,7 +344,7 @@ def test_group_option(group = nil, gems_list_size = 1) it "not outdated gems" do bundle "outdated --groups" - expect(out).to include("Bundle up to date!") + expect(out).to end_with("Bundle up to date!") end it "returns a sorted list of outdated gems by groups" do @@ -169,35 +354,58 @@ def test_group_option(group = nil, gems_list_size = 1) build_gem "duradura", "8.0" end - bundle "outdated --groups" - expect(out).to include("===== Group \"default\" =====") - expect(out).to include("terranova (newest 9, installed 8, requested = 8)") - expect(out).to include("===== Groups \"development, test\" =====") - expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)") - expect(out).to include("duradura (newest 8.0, installed 7.0, requested = 7.0)") + bundle "outdated --groups", :raise_on_error => false - expect(out).not_to include("weakling (") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 development, test + duradura 7.0 8.0 = 7.0 development, test + terranova 8 9 = 8 default + TABLE - # TODO: check gems order inside the group + expect(out).to end_with(expected_output) end end describe "with --local option" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "weakling", "~> 0.0.1" + gem "terranova", '8' + group :development, :test do + gem 'activesupport', '2.3.5' + gem "duradura", '7.0' + end + G + end + it "uses local cache to return a list of outdated gems" do update_repo2 do build_gem "activesupport", "2.3.4" end - bundle! "config set clean false" + bundle "config set clean false" install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport", "2.3.4" G - bundle "outdated --local" + bundle "outdated --local", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.4 2.3.5 = 2.3.4 default + TABLE - expect(out).to include("activesupport (newest 2.3.5, installed 2.3.4, requested = 2.3.4)") + expect(out).to end_with(expected_output) end it "doesn't hit repo2" do @@ -211,10 +419,23 @@ def test_group_option(group = nil, gems_list_size = 1) shared_examples_for "a minimal output is desired" do context "and gems are outdated" do before do - update_repo2 do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + build_gem "activesupport", "3.0" build_gem "weakling", "0.2" end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G end it "outputs a sorted list of outdated gems with a more minimal format" do @@ -234,31 +455,68 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --parseable option" do - subject { bundle "outdated --parseable" } + subject { bundle "outdated --parseable", :raise_on_error => false } it_behaves_like "a minimal output is desired" end describe "with aliased --porcelain option" do - subject { bundle "outdated --porcelain" } + subject { bundle "outdated --porcelain", :raise_on_error => false } it_behaves_like "a minimal output is desired" end describe "with specified gems" do it "returns list of outdated gems" do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "3.0" update_git "foo", :path => lib_path("foo") end - bundle "outdated foo" - expect(out).not_to include("activesupport (newest") - expect(out).to include("foo (newest 1.0") + bundle "outdated foo", :raise_on_error => false + + expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip + Gem Current Latest Requested Groups + foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default + TABLE + + expect(out).to match(Regexp.new(expected_output)) end end describe "pre-release gems" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + end + context "without the --pre option" do it "ignores pre-release versions" do update_repo2 do @@ -266,7 +524,8 @@ def test_group_option(group = nil, gems_list_size = 1) end bundle "outdated" - expect(out).not_to include("activesupport (3.0.0.beta > 2.3.5)") + + expect(out).to end_with("Bundle up to date!") end end @@ -276,8 +535,14 @@ def test_group_option(group = nil, gems_list_size = 1) build_gem "activesupport", "3.0.0.beta" end - bundle "outdated --pre" - expect(out).to include("activesupport (newest 3.0.0.beta, installed 2.3.5, requested = 2.3.5)") + bundle "outdated --pre", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0.0.beta = 2.3.5 default + TABLE + + expect(out).to end_with(expected_output) end end @@ -293,24 +558,62 @@ def test_group_option(group = nil, gems_list_size = 1) gem "activesupport", "3.0.0.beta.1" G - bundle "outdated" - expect(out).to include("(newest 3.0.0.beta.2, installed 3.0.0.beta.1, requested = 3.0.0.beta.1)") + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + activesupport 3.0.0.beta.1 3.0.0.beta.2 = 3.0.0.beta.1 default + TABLE + + expect(out).to end_with(expected_output) end end end filter_strict_option = Bundler.feature_flag.bundler_2_mode? ? :"filter-strict" : :strict describe "with --#{filter_strict_option} option" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + end + it "only reports gems that have a newer version that matches the specified dependency version requirements" do update_repo2 do build_gem "activesupport", "3.0" build_gem "weakling", "0.0.5" end + bundle :outdated, filter_strict_option => true, :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + weakling 0.0.3 0.0.5 ~> 0.0.1 default + TABLE + + expect(out).to end_with(expected_output) + end + + it "doesn't crash when some deps unused on the current platform" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", platforms: [:ruby_22] + G + bundle :outdated, filter_strict_option => true - expect(out).to_not include("activesupport (newest") - expect(out).to include("(newest 0.0.5, installed 0.0.3, requested ~> 0.0.1)") + expect(out).to end_with("Bundle up to date!") end it "only reports gem dependencies when they can actually be updated" do @@ -321,7 +624,7 @@ def test_group_option(group = nil, gems_list_size = 1) bundle :outdated, filter_strict_option => true - expect(out).to_not include("rack (1.2") + expect(out).to end_with("Bundle up to date!") end describe "and filter options" do @@ -337,10 +640,14 @@ def test_group_option(group = nil, gems_list_size = 1) build_gem "weakling", "0.0.5" end - bundle :outdated, filter_strict_option => true, "filter-patch" => true + bundle :outdated, filter_strict_option => true, "filter-patch" => true, :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + weakling 0.0.3 0.0.5 >= 0.0.1 default + TABLE - expect(out).to_not include("activesupport (newest") - expect(out).to include("(newest 0.0.5, installed 0.0.3") + expect(out).to end_with(expected_output) end it "only reports gems that match requirement and minor filter level" do @@ -355,10 +662,14 @@ def test_group_option(group = nil, gems_list_size = 1) build_gem "weakling", "0.1.5" end - bundle :outdated, filter_strict_option => true, "filter-minor" => true + bundle :outdated, filter_strict_option => true, "filter-minor" => true, :raise_on_error => false - expect(out).to_not include("activesupport (newest") - expect(out).to include("(newest 0.1.5, installed 0.0.3") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + weakling 0.0.3 0.1.5 >= 0.0.1 default + TABLE + + expect(out).to end_with(expected_output) end it "only reports gems that match requirement and major filter level" do @@ -373,23 +684,44 @@ def test_group_option(group = nil, gems_list_size = 1) build_gem "weakling", "1.1.5" end - bundle :outdated, filter_strict_option => true, "filter-major" => true + bundle :outdated, filter_strict_option => true, "filter-major" => true, :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + weakling 0.0.3 1.1.5 >= 0.0.1 default + TABLE - expect(out).to_not include("activesupport (newest") - expect(out).to include("(newest 1.1.5, installed 0.0.3") + expect(out).to end_with(expected_output) end end end describe "with invalid gem name" do + before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + end + it "returns could not find gem name" do - bundle "outdated invalid_gem_name" + bundle "outdated invalid_gem_name", :raise_on_error => false expect(err).to include("Could not find gem 'invalid_gem_name'.") end it "returns non-zero exit code" do - bundle "outdated invalid_gem_name" - expect(exitstatus).to_not be_zero if exitstatus + bundle "outdated invalid_gem_name", :raise_on_error => false + expect(exitstatus).to_not be_zero end end @@ -401,24 +733,28 @@ def test_group_option(group = nil, gems_list_size = 1) G bundle "config set auto_install 1" - bundle :outdated + bundle :outdated, :raise_on_error => false expect(out).to include("Installing foo 1.0") end context "after bundle install --deployment", :bundler => "< 3" do before do - install_gemfile <<-G, forgotten_command_line_options(:deployment => true) + build_repo2 + + gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rack" gem "foo" G + bundle :lock + bundle :install, :deployment => true end it "outputs a helpful message about being in deployment mode" do update_repo2 { build_gem "activesupport", "3.0" } - bundle "outdated" + bundle "outdated", :raise_on_error => false expect(last_command).to be_failure expect(err).to include("You are trying to check outdated gems in deployment mode.") expect(err).to include("Run `bundle outdated` elsewhere.") @@ -427,21 +763,26 @@ def test_group_option(group = nil, gems_list_size = 1) end end - context "after bundle config set deployment true" do + context "after bundle config set --local deployment true" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rack" gem "foo" G - bundle! "config set deployment true" + bundle "config set --local deployment true" end it "outputs a helpful message about being in deployment mode" do update_repo2 { build_gem "activesupport", "3.0" } - bundle "outdated" + bundle "outdated", :raise_on_error => false expect(last_command).to be_failure expect(err).to include("You are trying to check outdated gems in deployment mode.") expect(err).to include("Run `bundle outdated` elsewhere.") @@ -452,6 +793,8 @@ def test_group_option(group = nil, gems_list_size = 1) context "update available for a gem on a different platform" do before do + build_repo2 + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "laduradura", '= 5.15.2' @@ -460,11 +803,15 @@ def test_group_option(group = nil, gems_list_size = 1) it "reports that no updates are available" do bundle "outdated" - expect(out).to include("Bundle up to date!") + expect(out).to end_with("Bundle up to date!") end end context "update available for a gem on the same platform while multiple platforms used for gem" do + before do + build_repo2 + end + it "reports that updates are available if the Ruby platform is used" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -472,36 +819,53 @@ def test_group_option(group = nil, gems_list_size = 1) G bundle "outdated" - expect(out).to include("Bundle up to date!") + expect(out).to end_with("Bundle up to date!") end - it "reports that updates are available if the JRuby platform is used" do - simulate_ruby_engine "jruby", "1.6.7" do - simulate_platform "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby] - G + it "reports that updates are available if the JRuby platform is used", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby] + G - bundle "outdated" - expect(out).to include("Outdated gems included in the bundle:") - expect(out).to include("laduradura (newest 5.15.3, installed 5.15.2, requested = 5.15.2)") - end - end + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + laduradura 5.15.2 5.15.3 = 5.15.2 default + TABLE + + expect(out).to end_with(expected_output) end end shared_examples_for "version update is detected" do it "reports that a gem has a newer version" do subject - expect(out).to include("Outdated gems included in the bundle:") - expect(out).to include("activesupport (newest") - expect(out).to_not include("ERROR REPORT TEMPLATE") + + outdated_gems = out.split("\n").drop_while {|l| !l.start_with?("Gem") }[1..-1] + + expect(outdated_gems.size).to be > 0 end end shared_examples_for "major version updates are detected" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "3.3.5" build_gem "weakling", "0.8.0" @@ -513,6 +877,21 @@ def test_group_option(group = nil, gems_list_size = 1) context "when on a new machine" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + simulate_new_machine update_git "foo", :path => lib_path("foo") @@ -522,12 +901,27 @@ def test_group_option(group = nil, gems_list_size = 1) end end - subject { bundle "outdated" } + subject { bundle "outdated", :raise_on_error => false } it_behaves_like "version update is detected" end shared_examples_for "minor version updates are detected" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "2.7.5" build_gem "weakling", "2.0.1" @@ -539,6 +933,21 @@ def test_group_option(group = nil, gems_list_size = 1) shared_examples_for "patch version updates are detected" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "2.3.7" build_gem "weakling", "0.3.1" @@ -551,15 +960,27 @@ def test_group_option(group = nil, gems_list_size = 1) shared_examples_for "no version updates are detected" do it "does not detect any version updates" do subject - expect(out).to include("updates to display.") - expect(out).to_not include("ERROR REPORT TEMPLATE") - expect(out).to_not include("activesupport (newest") - expect(out).to_not include("weakling (newest") + expect(out).to end_with("updates to display.") end end shared_examples_for "major version is ignored" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "3.3.5" build_gem "weakling", "1.0.1" @@ -571,6 +992,21 @@ def test_group_option(group = nil, gems_list_size = 1) shared_examples_for "minor version is ignored" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "2.4.5" build_gem "weakling", "0.3.1" @@ -582,6 +1018,21 @@ def test_group_option(group = nil, gems_list_size = 1) shared_examples_for "patch version is ignored" do before do + build_repo2 do + build_git "foo", :path => lib_path("foo") + build_git "zebra", :path => lib_path("zebra") + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "zebra", :git => "#{lib_path("zebra")}" + gem "foo", :git => "#{lib_path("foo")}" + gem "activesupport", "2.3.5" + gem "weakling", "~> 0.0.1" + gem "duradura", '7.0' + gem "terranova", '8' + G + update_repo2 do build_gem "activesupport", "2.3.6" build_gem "weakling", "0.0.4" @@ -592,7 +1043,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-major option" do - subject { bundle "outdated --filter-major" } + subject { bundle "outdated --filter-major", :raise_on_error => false } it_behaves_like "major version updates are detected" it_behaves_like "minor version is ignored" @@ -600,7 +1051,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-minor option" do - subject { bundle "outdated --filter-minor" } + subject { bundle "outdated --filter-minor", :raise_on_error => false } it_behaves_like "minor version updates are detected" it_behaves_like "major version is ignored" @@ -608,7 +1059,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-patch option" do - subject { bundle "outdated --filter-patch" } + subject { bundle "outdated --filter-patch", :raise_on_error => false } it_behaves_like "patch version updates are detected" it_behaves_like "major version is ignored" @@ -616,7 +1067,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-minor --filter-patch options" do - subject { bundle "outdated --filter-minor --filter-patch" } + subject { bundle "outdated --filter-minor --filter-patch", :raise_on_error => false } it_behaves_like "minor version updates are detected" it_behaves_like "patch version updates are detected" @@ -624,7 +1075,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-major --filter-minor options" do - subject { bundle "outdated --filter-major --filter-minor" } + subject { bundle "outdated --filter-major --filter-minor", :raise_on_error => false } it_behaves_like "major version updates are detected" it_behaves_like "minor version updates are detected" @@ -632,7 +1083,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-major --filter-patch options" do - subject { bundle "outdated --filter-major --filter-patch" } + subject { bundle "outdated --filter-major --filter-patch", :raise_on_error => false } it_behaves_like "major version updates are detected" it_behaves_like "patch version updates are detected" @@ -640,7 +1091,7 @@ def test_group_option(group = nil, gems_list_size = 1) end describe "with --filter-major --filter-minor --filter-patch options" do - subject { bundle "outdated --filter-major --filter-minor --filter-patch" } + subject { bundle "outdated --filter-major --filter-minor --filter-patch", :raise_on_error => false } it_behaves_like "major version updates are detected" it_behaves_like "minor version updates are detected" @@ -658,49 +1109,55 @@ def test_group_option(group = nil, gems_list_size = 1) # establish a lockfile set to 1.0.0 install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem 'patch', '1.0.0' - gem 'minor', '1.0.0' - gem 'major', '1.0.0' + source "#{file_uri_for(gem_repo4)}" + gem 'patch', '1.0.0' + gem 'minor', '1.0.0' + gem 'major', '1.0.0' G # remove 1.4.3 requirement and bar altogether # to setup update specs below gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem 'patch' - gem 'minor' - gem 'major' + source "#{file_uri_for(gem_repo4)}" + gem 'patch' + gem 'minor' + gem 'major' G end it "shows nothing when patching and filtering to minor" do bundle "outdated --patch --filter-minor" - expect(out).to include("No minor updates to display.") - expect(out).not_to include("patch (newest") - expect(out).not_to include("minor (newest") - expect(out).not_to include("major (newest") + expect(out).to end_with("No minor updates to display.") end it "shows all gems when patching and filtering to patch" do - bundle "outdated --patch --filter-patch" + bundle "outdated --patch --filter-patch", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + major 1.0.0 1.0.1 >= 0 default + minor 1.0.0 1.0.1 >= 0 default + patch 1.0.0 1.0.1 >= 0 default + TABLE - expect(out).to include("patch (newest 1.0.1") - expect(out).to include("minor (newest 1.0.1") - expect(out).to include("major (newest 1.0.1") + expect(out).to end_with(expected_output) end it "shows minor and major when updating to minor and filtering to patch and minor" do - bundle "outdated --minor --filter-minor" + bundle "outdated --minor --filter-minor", :raise_on_error => false - expect(out).not_to include("patch (newest") - expect(out).to include("minor (newest 1.1.0") - expect(out).to include("major (newest 1.1.0") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + major 1.0.0 1.1.0 >= 0 default + minor 1.0.0 1.1.0 >= 0 default + TABLE + + expect(out).to end_with(expected_output) end it "shows minor when updating to major and filtering to minor with parseable" do - bundle "outdated --major --filter-minor --parseable" + bundle "outdated --major --filter-minor --parseable", :raise_on_error => false expect(out).not_to include("patch (newest") expect(out).to include("minor (newest") @@ -742,11 +1199,15 @@ def test_group_option(group = nil, gems_list_size = 1) end it "shows gems with update-strict updating to patch and filtering to patch" do - bundle "outdated --patch --update-strict --filter-patch" + bundle "outdated --patch --update-strict --filter-patch", :raise_on_error => false - expect(out).to include("foo (newest 1.4.4") - expect(out).to include("bar (newest 2.0.5") - expect(out).not_to include("qux (newest") + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + bar 2.0.3 2.0.5 + foo 1.4.3 1.4.4 >= 0 default + TABLE + + expect(out).to end_with(expected_output) end end end @@ -771,10 +1232,113 @@ def test_group_option(group = nil, gems_list_size = 1) gem 'weakling' G - bundle "outdated --only-explicit" + bundle "outdated --only-explicit", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + weakling 0.2 0.3 >= 0 default + TABLE + + expect(out).to end_with(expected_output) + end + end + + describe "with a multiplatform lockfile" do + before do + build_repo4 do + build_gem "nokogiri", "1.11.1" + build_gem "nokogiri", "1.11.1" do |s| + s.platform = Bundler.local_platform + end + + build_gem "nokogiri", "1.11.2" + build_gem "nokogiri", "1.11.2" do |s| + s.platform = Bundler.local_platform + end + end + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + nokogiri (1.11.1) + nokogiri (1.11.1-#{Bundler.local_platform}) + + PLATFORMS + ruby + #{Bundler.local_platform} + + DEPENDENCIES + nokogiri + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "nokogiri" + G + end + + it "reports a single entry per gem" do + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + nokogiri 1.11.1 1.11.2 >= 0 default + TABLE + + expect(out).to end_with(expected_output) + end + end + + context "when a gem is no longer a dependency after a full update" do + before do + build_repo4 do + build_gem "mini_portile2", "2.5.2" do |s| + s.add_dependency "net-ftp", "~> 0.1" + end + + build_gem "mini_portile2", "2.5.3" + + build_gem "net-ftp", "0.1.2" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "mini_portile2" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + mini_portile2 (2.5.2) + net-ftp (~> 0.1) + net-ftp (0.1.2) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + mini_portile2 + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "works" do + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.strip + Gem Current Latest Requested Groups + mini_portile2 2.5.2 2.5.3 >= 0 default + TABLE - expect(out).to include("weakling (newest 0.3") - expect(out).not_to include("bar (newest 2.2") + expect(out).to end_with(expected_output) end end end diff --git a/ruby/spec/bundler/commands/post_bundle_message_spec.rb b/ruby/spec/bundler/commands/post_bundle_message_spec.rb index 6fd4fb708..3050b8775 100644 --- a/ruby/spec/bundler/commands/post_bundle_message_spec.rb +++ b/ruby/spec/bundler/commands/post_bundle_message_spec.rb @@ -22,78 +22,86 @@ let(:bundle_show_message) { Bundler::VERSION.split(".").first.to_i < 3 ? bundle_show_system_message : bundle_show_path_message } describe "for fresh bundle install" do - it "without any options" do + it "shows proper messages according to the configured groups" do bundle :install expect(out).to include(bundle_show_message) expect(out).not_to include("Gems in the group") expect(out).to include(bundle_complete_message) expect(out).to include(installed_gems_stats) - end - it "with --without one group" do - bundle! :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the group emo were not installed") + expect(out).to include("Gems in the group 'emo' were not installed") expect(out).to include(bundle_complete_message) expect(out).to include(installed_gems_stats) - end - it "with --without two groups" do - bundle! :install, forgotten_command_line_options(:without => "emo test") + bundle "config set --local without emo test" + bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo and test were not installed") + expect(out).to include("Gems in the groups 'emo' and 'test' were not installed") expect(out).to include(bundle_complete_message) expect(out).to include("4 Gemfile dependencies, 3 gems now installed.") - end - it "with --without more groups" do - bundle! :install, forgotten_command_line_options(:without => "emo obama test") + bundle "config set --local without emo obama test" + bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") + expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed") expect(out).to include(bundle_complete_message) expect(out).to include("4 Gemfile dependencies, 2 gems now installed.") end - describe "with --path and" do + describe "with `path` configured" do let(:bundle_path) { "./vendor" } - it "without any options" do - bundle! :install, forgotten_command_line_options(:path => "vendor") + it "shows proper messages according to the configured groups" do + bundle "config set --local path vendor" + bundle :install expect(out).to include(bundle_show_path_message) expect(out).to_not include("Gems in the group") expect(out).to include(bundle_complete_message) - end - it "with --without one group" do - bundle! :install, forgotten_command_line_options(:without => "emo", :path => "vendor") + bundle "config set --local path vendor" + bundle "config set --local without emo" + bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the group emo were not installed") + expect(out).to include("Gems in the group 'emo' were not installed") expect(out).to include(bundle_complete_message) - end - it "with --without two groups" do - bundle! :install, forgotten_command_line_options(:without => "emo test", :path => "vendor") + bundle "config set --local path vendor" + bundle "config set --local without emo test" + bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the groups emo and test were not installed") + expect(out).to include("Gems in the groups 'emo' and 'test' were not installed") expect(out).to include(bundle_complete_message) - end - it "with --without more groups" do - bundle! :install, forgotten_command_line_options(:without => "emo obama test", :path => "vendor") + bundle "config set --local path vendor" + bundle "config set --local without emo obama test" + bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") + expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed") expect(out).to include(bundle_complete_message) end + end + + describe "with an absolute `path` inside the cwd configured" do + let(:bundle_path) { bundled_app("cache") } - it "with an absolute --path inside the cwd" do - bundle! :install, forgotten_command_line_options(:path => bundled_app("cache")) + it "shows proper messages according to the configured groups" do + bundle "config set --local path #{bundle_path}" + bundle :install expect(out).to include("Bundled gems are installed into `./cache`") expect(out).to_not include("Gems in the group") expect(out).to include(bundle_complete_message) end + end + + describe "with `path` configured to an absolute path outside the cwd" do + let(:bundle_path) { tmp("not_bundled_app") } - it "with an absolute --path outside the cwd" do - bundle! :install, forgotten_command_line_options(:path => tmp("not_bundled_app")) + it "shows proper messages according to the configured groups" do + bundle "config set --local path #{bundle_path}" + bundle :install expect(out).to include("Bundled gems are installed into `#{tmp("not_bundled_app")}`") expect(out).to_not include("Gems in the group") expect(out).to include(bundle_complete_message) @@ -105,24 +113,14 @@ bundle "config set force_ruby_platform true" end - it "should report a helpful error message", :bundler => "< 3" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - gem "not-a-gem", :group => :development - G - expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.") - end - - it "should report a helpful error message", :bundler => "3" do - install_gemfile <<-G + it "should report a helpful error message" do + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" gem "not-a-gem", :group => :development G expect(err).to include <<-EOS.strip Could not find gem 'not-a-gem' in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally. -The source does not contain any versions of 'not-a-gem' EOS end @@ -133,7 +131,7 @@ G bundle :cache expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" gem "not-a-gem", :group => :development @@ -144,7 +142,7 @@ end end - describe "for second bundle install run" do + describe "for second bundle install run", :bundler => "< 3" do it "without any options" do 2.times { bundle :install } expect(out).to include(bundle_show_message) @@ -154,56 +152,53 @@ end it "with --without one group" do - bundle! :install, forgotten_command_line_options(:without => "emo") - bundle! :install + bundle "install --without emo" + bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the group emo were not installed") + expect(out).to include("Gems in the group 'emo' were not installed") expect(out).to include(bundle_complete_message) expect(out).to include(installed_gems_stats) end it "with --without two groups" do - bundle! :install, forgotten_command_line_options(:without => "emo test") - bundle! :install + bundle "install --without emo test" + bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo and test were not installed") + expect(out).to include("Gems in the groups 'emo' and 'test' were not installed") expect(out).to include(bundle_complete_message) end it "with --without more groups" do - bundle! :install, forgotten_command_line_options(:without => "emo obama test") + bundle "install --without emo obama test" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") + expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed") expect(out).to include(bundle_complete_message) end end describe "for bundle update" do - it "without any options" do - bundle! :update, :all => true + it "shows proper messages according to the configured groups" do + bundle :update, :all => true expect(out).not_to include("Gems in the groups") expect(out).to include(bundle_updated_message) - end - it "with --without one group" do - bundle! :install, forgotten_command_line_options(:without => "emo") - bundle! :update, :all => true - expect(out).to include("Gems in the group emo were not updated") + bundle "config set --local without emo" + bundle :install + bundle :update, :all => true + expect(out).to include("Gems in the group 'emo' were not updated") expect(out).to include(bundle_updated_message) - end - it "with --without two groups" do - bundle! :install, forgotten_command_line_options(:without => "emo test") - bundle! :update, :all => true - expect(out).to include("Gems in the groups emo and test were not updated") + bundle "config set --local without emo test" + bundle :install + bundle :update, :all => true + expect(out).to include("Gems in the groups 'emo' and 'test' were not updated") expect(out).to include(bundle_updated_message) - end - it "with --without more groups" do - bundle! :install, forgotten_command_line_options(:without => "emo obama test") - bundle! :update, :all => true - expect(out).to include("Gems in the groups emo, obama and test were not updated") + bundle "config set --local without emo obama test" + bundle :install + bundle :update, :all => true + expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not updated") expect(out).to include(bundle_updated_message) end end diff --git a/ruby/spec/bundler/commands/pristine_spec.rb b/ruby/spec/bundler/commands/pristine_spec.rb index cc7f760d7..2f730bd4e 100644 --- a/ruby/spec/bundler/commands/pristine_spec.rb +++ b/ruby/spec/bundler/commands/pristine_spec.rb @@ -18,21 +18,23 @@ build_lib "bar", :path => lib_path("bar") end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "weakling" gem "very_simple_binary" - gem "foo", :git => "#{lib_path("foo")}" + gem "foo", :git => "#{lib_path("foo")}", :branch => "master" gem "git_with_ext", :git => "#{lib_path("git_with_ext")}" gem "bar", :path => "#{lib_path("bar")}" gemspec G + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) end context "when sourced from RubyGems" do it "reverts using cached .gem file" do - spec = Bundler.definition.specs["weakling"].first + spec = find_spec("weakling") changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt") FileUtils.touch(changes_txt) @@ -43,10 +45,9 @@ end it "does not delete the bundler gem" do - system_gems :bundler - bundle! "install" - bundle! "pristine", :system_bundler => true - bundle! "-v", :system_bundler => true + bundle "install" + bundle "pristine" + bundle "-v" expected = if Bundler::VERSION < "3.0" "Bundler version" @@ -60,32 +61,45 @@ context "when sourced from git repo" do it "reverts by resetting to current revision`" do - spec = Bundler.definition.specs["foo"].first + spec = find_spec("foo") changed_file = Pathname.new(spec.full_gem_path).join("lib/foo.rb") diff = "#Pristine spec changes" File.open(changed_file, "a") {|f| f.puts diff } expect(File.read(changed_file)).to include(diff) - bundle! "pristine" + bundle "pristine" expect(File.read(changed_file)).to_not include(diff) end it "removes added files" do - spec = Bundler.definition.specs["foo"].first + spec = find_spec("foo") changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt") FileUtils.touch(changes_txt) expect(changes_txt).to be_file - bundle! "pristine" + bundle "pristine" expect(changes_txt).not_to be_file end + + it "displays warning and ignores changes when a local config exists" do + spec = find_spec("foo") + bundle "config set local.#{spec.name} #{lib_path(spec.name)}" + + changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt") + FileUtils.touch(changes_txt) + expect(changes_txt).to be_file + + bundle "pristine" + expect(changes_txt).to be_file + expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is locally overridden.") + end end context "when sourced from gemspec" do it "displays warning and ignores changes when sourced from gemspec" do - spec = Bundler.definition.specs["baz"].first + spec = find_spec("baz") changed_file = Pathname.new(spec.full_gem_path).join("lib/baz.rb") diff = "#Pristine spec changes" @@ -98,7 +112,7 @@ end it "reinstall gemspec dependency" do - spec = Bundler.definition.specs["baz-dev"].first + spec = find_spec("baz-dev") changed_file = Pathname.new(spec.full_gem_path).join("lib/baz/dev.rb") diff = "#Pristine spec changes" @@ -112,7 +126,7 @@ context "when sourced from path" do it "displays warning and ignores changes when sourced from local path" do - spec = Bundler.definition.specs["bar"].first + spec = find_spec("bar") changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt") FileUtils.touch(changes_txt) expect(changes_txt).to be_file @@ -124,22 +138,22 @@ context "when passing a list of gems to pristine" do it "resets them" do - foo = Bundler.definition.specs["foo"].first + foo = find_spec("foo") foo_changes_txt = Pathname.new(foo.full_gem_path).join("lib/changes.txt") FileUtils.touch(foo_changes_txt) expect(foo_changes_txt).to be_file - bar = Bundler.definition.specs["bar"].first + bar = find_spec("bar") bar_changes_txt = Pathname.new(bar.full_gem_path).join("lib/changes.txt") FileUtils.touch(bar_changes_txt) expect(bar_changes_txt).to be_file - weakling = Bundler.definition.specs["weakling"].first + weakling = find_spec("weakling") weakling_changes_txt = Pathname.new(weakling.full_gem_path).join("lib/changes.txt") FileUtils.touch(weakling_changes_txt) expect(weakling_changes_txt).to be_file - bundle! "pristine foo bar weakling" + bundle "pristine foo bar weakling" expect(err).to include("Cannot pristine bar (1.0). Gem is sourced from local path.") expect(out).to include("Installing weakling 1.0") @@ -150,13 +164,13 @@ end it "raises when one of them is not in the lockfile" do - bundle "pristine abcabcabc" + bundle "pristine abcabcabc", :raise_on_error => false expect(err).to include("Could not find gem 'abcabcabc'.") end end context "when a build config exists for one of the gems" do - let(:very_simple_binary) { Bundler.definition.specs["very_simple_binary"].first } + let(:very_simple_binary) { find_spec("very_simple_binary") } let(:c_ext_dir) { Pathname.new(very_simple_binary.full_gem_path).join("ext") } let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" } before { bundle "config set build.very_simple_binary -- #{build_opt}" } @@ -164,7 +178,7 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - bundle! "pristine" + bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/) @@ -173,7 +187,7 @@ end context "when a build config exists for a git sourced gem" do - let(:git_with_ext) { Bundler.definition.specs["git_with_ext"].first } + let(:git_with_ext) { find_spec("git_with_ext") } let(:c_ext_dir) { Pathname.new(git_with_ext.full_gem_path).join("ext") } let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" } before { bundle "config set build.git_with_ext -- #{build_opt}" } @@ -181,11 +195,27 @@ # This just verifies that the generated Makefile from the c_ext gem makes # use of the build_args from the bundle config it "applies the config when installing the gem" do - bundle! "pristine" + bundle "pristine" makefile_contents = File.read(c_ext_dir.join("Makefile").to_s) expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/) expect(makefile_contents).to match(/LIBPATH =.*-L#{c_ext_dir}/) end end + + context "when BUNDLE_GEMFILE doesn't exist" do + before do + bundle "pristine", :env => { "BUNDLE_GEMFILE" => "does/not/exist" }, :raise_on_error => false + end + + it "shows a meaningful error" do + expect(err).to eq("#{bundled_app("does/not/exist")} not found") + end + end + + def find_spec(name) + without_env_side_effects do + Bundler.definition.specs[name].first + end + end end diff --git a/ruby/spec/bundler/commands/remove_spec.rb b/ruby/spec/bundler/commands/remove_spec.rb index 402faaf1f..95d6e75e9 100644 --- a/ruby/spec/bundler/commands/remove_spec.rb +++ b/ruby/spec/bundler/commands/remove_spec.rb @@ -7,13 +7,13 @@ source "#{file_uri_for(gem_repo1)}" G - bundle "remove" + bundle "remove", :raise_on_error => false expect(err).to include("Please specify gems to remove.") end end - context "when --install flag is specified" do + context "when --install flag is specified", :bundler => "< 3" do it "removes gems from .bundle" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -21,7 +21,7 @@ gem "rack" G - bundle! "remove rack --install" + bundle "remove rack --install" expect(out).to include("rack was removed.") expect(the_bundle).to_not include_gems "rack" @@ -37,13 +37,40 @@ gem "rack" G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") - gemfile_should_be <<-G + expect(the_bundle).to_not include_gems "rack" + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end + + context "when gem is specified in multiple lines" do + it "shows success for removed gem" do + build_git "rack" + + gemfile <<-G + source '#{file_uri_for(gem_repo1)}' + + gem 'git' + gem 'rack', + git: "#{lib_path("rack-1.0")}", + branch: 'master' + gem 'nokogiri' + G + + bundle "remove rack" + + expect(out).to include("rack was removed.") + expect(gemfile).to eq <<~G + source '#{file_uri_for(gem_repo1)}' + + gem 'git' + gem 'nokogiri' + G + end + end end context "when gem is not present in gemfile" do @@ -52,14 +79,14 @@ source "#{file_uri_for(gem_repo1)}" G - bundle "remove rack" + bundle "remove rack", :raise_on_error => false - expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.") + expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.") end end end - describe "remove mutiple gems from gemfile" do + describe "remove multiple gems from gemfile" do context "when all gems are present in gemfile" do it "shows success fir all removed gems" do gemfile <<-G @@ -69,11 +96,11 @@ gem "rails" G - bundle! "remove rack rails" + bundle "remove rack rails" expect(out).to include("rack was removed.") expect(out).to include("rails was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -89,10 +116,10 @@ gem "rspec" G - bundle "remove rails rack minitest" + bundle "remove rails rack minitest", :raise_on_error => false - expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.") - gemfile_should_be <<-G + expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.") + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" gem "rails" @@ -111,10 +138,10 @@ gem "rack", :group => [:dev] G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -131,10 +158,10 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -151,10 +178,10 @@ end G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" group :test do @@ -177,16 +204,16 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end end - context "when the gem belongs to mutiple groups" do + context "when the gem belongs to multiple groups" do it "removes the groups" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -196,16 +223,16 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end end - context "when the gem is present in mutiple groups" do + context "when the gem is present in multiple groups" do it "removes all empty blocks" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -219,10 +246,10 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -242,10 +269,10 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -265,10 +292,10 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" group :test do @@ -292,10 +319,10 @@ end G - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" group :test do @@ -309,17 +336,17 @@ end describe "arbitrary gemfile" do - context "when mutiple gems are present in same line" do + context "when multiple gems are present in same line" do it "shows warning for gems not removed" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack"; gem "rails" G - bundle "remove rails" + bundle "remove rails", :raise_on_error => false expect(err).to include("Gems could not be removed. rack (>= 0) would also have been removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" gem "rack"; gem "rails" G @@ -328,7 +355,7 @@ context "when some gems could not be removed" do it "shows warning for gems not removed and success for those removed" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem"rack" gem"rspec" @@ -336,12 +363,12 @@ gem "minitest" G - bundle! "remove rails rack rspec minitest" + bundle "remove rails rack rspec minitest" expect(out).to include("rails was removed.") expect(out).to include("minitest was removed.") expect(out).to include("rack, rspec could not be removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" gem"rack" gem"rspec" @@ -368,12 +395,12 @@ end G - bundle! "install" + bundle "install" - bundle! "remove rspec" + bundle "remove rspec" expect(out).to include("rspec was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -396,7 +423,7 @@ gem "rack" G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") end @@ -414,7 +441,7 @@ eval_gemfile "Gemfile-other" G - bundle! "remove rack" + bundle "remove rack" expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"") expect(out).to include("rack was removed.") @@ -434,9 +461,9 @@ eval_gemfile "Gemfile-other" G - bundle "remove rack" + bundle "remove rack", :raise_on_error => false - expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.") + expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.") end end @@ -453,11 +480,11 @@ gem "rack" G - bundle "remove rack" + bundle "remove rack", :raise_on_error => false expect(out).to include("rack was removed.") expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" eval_gemfile "Gemfile-other" @@ -478,11 +505,11 @@ gem "rack" G - bundle "remove rack" + bundle "remove rack", :raise_on_error => false expect(out).to include("rack was removed.") expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" eval_gemfile "Gemfile-other" @@ -503,11 +530,11 @@ gem "rails"; gem "rack" G - bundle "remove rack" + bundle "remove rack", :raise_on_error => false expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.") expect(bundled_app("Gemfile-other").read).to include("gem \"rack\"") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" eval_gemfile "Gemfile-other" @@ -529,7 +556,7 @@ gem"rack" G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"") @@ -547,10 +574,10 @@ end G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -566,10 +593,10 @@ end G - bundle! "remove rack" + bundle "remove rack" expect(out).to include("rack was removed.") - gemfile_should_be <<-G + expect(gemfile).to eq <<~G source "#{file_uri_for(gem_repo1)}" G end @@ -587,9 +614,89 @@ gemspec :path => '#{tmp.join("foo")}', :name => 'foo' G - bundle! "remove foo" + bundle "remove foo" expect(out).to include("foo could not be removed.") end end + + describe "with comments that mention gems" do + context "when comment is a separate line comment" do + it "does not remove the line comment" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + + # gem "rack" might be used in the future + gem "rack" + G + + bundle "remove rack" + + expect(out).to include("rack was removed.") + expect(gemfile).to eq <<~G + source "#{file_uri_for(gem_repo1)}" + + # gem "rack" might be used in the future + G + end + end + + context "when gem specified for removal has an inline comment" do + it "removes the inline comment" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + + gem "rack" # this can be removed + G + + bundle "remove rack" + + expect(out).to include("rack was removed.") + expect(gemfile).to eq <<~G + source "#{file_uri_for(gem_repo1)}" + G + end + end + + context "when gem specified for removal is mentioned in other gem's comment" do + it "does not remove other gem" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "puma" # implements interface provided by gem "rack" + + gem "rack" + G + + bundle "remove rack" + + expect(out).to_not include("puma was removed.") + expect(out).to include("rack was removed.") + expect(gemfile).to eq <<~G + source "#{file_uri_for(gem_repo1)}" + gem "puma" # implements interface provided by gem "rack" + G + end + end + + context "when gem specified for removal has a comment that mentions other gem" do + it "does not remove other gem" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "puma" # implements interface provided by gem "rack" + + gem "rack" + G + + bundle "remove puma" + + expect(out).to include("puma was removed.") + expect(out).to_not include("rack was removed.") + expect(gemfile).to eq <<~G + source "#{file_uri_for(gem_repo1)}" + + gem "rack" + G + end + end + end end diff --git a/ruby/spec/bundler/commands/show_spec.rb b/ruby/spec/bundler/commands/show_spec.rb index 61b8f73e7..2adb12161 100644 --- a/ruby/spec/bundler/commands/show_spec.rb +++ b/ruby/spec/bundler/commands/show_spec.rb @@ -10,19 +10,19 @@ end it "creates a Gemfile.lock if one did not exist" do - FileUtils.rm("Gemfile.lock") + FileUtils.rm(bundled_app_lock) bundle "show" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "creates a Gemfile.lock when invoked with a gem name" do - FileUtils.rm("Gemfile.lock") + FileUtils.rm(bundled_app_lock) bundle "show rails" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "prints path if gem exists in bundle" do @@ -50,14 +50,14 @@ end it "complains if gem not in bundle" do - bundle "show missing" + bundle "show missing", :raise_on_error => false expect(err).to match(/could not find gem 'missing'/i) end it "prints path of all gems in bundle sorted by name" do bundle "show --paths" - expect(out).to include(default_bundle_path("gems", "rake-12.3.2").to_s) + expect(out).to include(default_bundle_path("gems", "rake-13.0.1").to_s) expect(out).to include(default_bundle_path("gems", "rails-2.3.2").to_s) # Gem names are the last component of their path. @@ -135,7 +135,7 @@ G expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1" - bundle! :show + bundle :show expect(out).to include("foo (1.0.0.pre.beta.1") end end @@ -143,13 +143,12 @@ context "in a fresh gem in a blank git repo" do before :each do build_git "foo", :path => lib_path("foo") - in_app_root_custom lib_path("foo") - File.open("Gemfile", "w") {|f| f.puts "gemspec" } - sys_exec "rm -rf .git && git init" + File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts "gemspec" } + sys_exec "rm -rf .git && git init", :dir => lib_path("foo") end it "does not output git errors" do - bundle :show + bundle :show, :dir => lib_path("foo") expect(err_without_deprecations).to be_empty end end @@ -166,7 +165,7 @@ end context "with a valid regexp for gem name" do - it "presents alternatives" do + it "presents alternatives", :readline do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -174,7 +173,7 @@ G bundle "show rac" - expect(out).to eq "1 : rack\n2 : rack-obama\n0 : - exit -\n>" + expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/) end end @@ -187,19 +186,19 @@ invalid_regexp = "[]" - bundle "show #{invalid_regexp}" + bundle "show #{invalid_regexp}", :raise_on_error => false expect(err).to include("Could not find gem '#{invalid_regexp}'.") end end context "--outdated option" do - # Regression test for https://github.com/bundler/bundler/issues/5375 + # Regression test for https://github.com/rubygems/bundler/issues/5375 before do build_repo2 end it "doesn't update gems to newer versions" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rails" G @@ -212,9 +211,9 @@ end end - bundle! "show --outdated" + bundle "show --outdated" - bundle! "install" + bundle "install" expect(the_bundle).to include_gem("rails 2.3.2") end end diff --git a/ruby/spec/bundler/commands/update_spec.rb b/ruby/spec/bundler/commands/update_spec.rb index e4449312e..ee5d53c52 100644 --- a/ruby/spec/bundler/commands/update_spec.rb +++ b/ruby/spec/bundler/commands/update_spec.rb @@ -1,20 +1,24 @@ # frozen_string_literal: true RSpec.describe "bundle update" do - before :each do - build_repo2 + describe "with no arguments" do + before do + build_repo2 - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - gem "rack-obama" - gem "platform_specific" - G - end + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end - describe "with no arguments", :bundler => "< 3" do it "updates the entire bundle" do update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end @@ -30,31 +34,48 @@ gem "rack-obama" exit! G - bundle "update" - expect(bundled_app("Gemfile.lock")).to exist + bundle "update", :raise_on_error => false + expect(bundled_app_lock).to exist end end - describe "with --all", :bundler => "3" do + describe "with --all" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "updates the entire bundle" do update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end - bundle! "update", :all => true + bundle "update", :all => true expect(out).to include("Bundle updated!") expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0" end it "doesn't delete the Gemfile.lock file if something goes wrong" do + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" gem "rack-obama" exit! G - bundle "update", :all => true - expect(bundled_app("Gemfile.lock")).to exist + bundle "update", :all => true, :raise_on_error => false + expect(bundled_app_lock).to exist end end @@ -65,35 +86,46 @@ gem "rack", "1.0" G - bundle! "update --gemfile OmgFile", :all => true + bundle "update --gemfile OmgFile", :all => true expect(bundled_app("OmgFile.lock")).to exist end end context "when update_requires_all_flag is set" do - before { bundle! "config set update_requires_all_flag true" } + before { bundle "config set update_requires_all_flag true" } it "errors when passed nothing" do - install_gemfile! "" - bundle :update + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + bundle :update, :raise_on_error => false expect(err).to eq("To update everything, pass the `--all` flag.") end it "errors when passed --all and another option" do - install_gemfile! "" - bundle "update --all foo" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + bundle "update --all foo", :raise_on_error => false expect(err).to eq("Cannot specify --all along with specific options.") end it "updates everything when passed --all" do - install_gemfile! "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" bundle "update --all" expect(out).to include("Bundle updated!") end end describe "--quiet argument" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "hides UI messages" do bundle "update --quiet" expect(out).not_to include("Bundle updated!") @@ -101,8 +133,23 @@ end describe "with a top level dependency" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "unlocks all child dependencies that are unrelated to other locked dependencies" do update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end @@ -112,95 +159,276 @@ end describe "with an unknown dependency" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "should inform the user" do - bundle "update halting-problem-solver" + bundle "update halting-problem-solver", :raise_on_error => false expect(err).to include "Could not find gem 'halting-problem-solver'" end it "should suggest alternatives" do - bundle "update platformspecific" + bundle "update platformspecific", :raise_on_error => false expect(err).to include "Did you mean platform_specific?" end end describe "with a child dependency" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "should update the child dependency" do - update_repo2 + update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + end + bundle "update rack" expect(the_bundle).to include_gems "rack 1.2" end end describe "when a possible resolve requires an older version of a locked gem" do - context "and only_update_to_newer_versions is set" do - before do - bundle! "config set only_update_to_newer_versions true" + it "does not go to an older version" do + build_repo4 do + build_gem "tilt", "2.0.8" + build_gem "slim", "3.0.9" do |s| + s.add_dependency "tilt", [">= 1.3.3", "< 2.1"] + end + build_gem "slim_lint", "0.16.1" do |s| + s.add_dependency "slim", [">= 3.0", "< 5.0"] + end + build_gem "slim-rails", "0.2.1" do |s| + s.add_dependency "slim", ">= 0.9.2" + end + build_gem "slim-rails", "3.1.3" do |s| + s.add_dependency "slim", "~> 3.0" + end end - it "does not go to an older version" do - build_repo4 do - build_gem "tilt", "2.0.8" - build_gem "slim", "3.0.9" do |s| - s.add_dependency "tilt", [">= 1.3.3", "< 2.1"] - end - build_gem "slim_lint", "0.16.1" do |s| - s.add_dependency "slim", [">= 3.0", "< 5.0"] - end - build_gem "slim-rails", "0.2.1" do |s| - s.add_dependency "slim", ">= 0.9.2" - end - build_gem "slim-rails", "3.1.3" do |s| - s.add_dependency "slim", "~> 3.0" - end + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "slim-rails" + gem "slim_lint" + G + + expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") + + update_repo4 do + build_gem "slim", "4.0.0" do |s| + s.add_dependency "tilt", [">= 2.0.6", "< 2.1"] end + end - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "slim-rails" - gem "slim_lint" - G + bundle "update", :all => true - expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") + expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") + end - update_repo4 do - build_gem "slim", "4.0.0" do |s| - s.add_dependency "tilt", [">= 2.0.6", "< 2.1"] - end + it "does not go to an older version, even if the version upgrade that could cause another gem to downgrade is activated first" do + build_repo4 do + # countries is processed before country_select by the resolver due to having less spec groups (groups of versions with the same dependencies) (2 vs 3) + + build_gem "countries", "2.1.4" + build_gem "countries", "3.1.0" + + build_gem "countries", "4.0.0" do |s| + s.add_dependency "sixarm_ruby_unaccent", "~> 1.1" + end + + build_gem "country_select", "1.2.0" + + build_gem "country_select", "2.1.4" do |s| + s.add_dependency "countries", "~> 2.0" + end + build_gem "country_select", "3.1.1" do |s| + s.add_dependency "countries", "~> 2.0" end - bundle! "update", :all => true + build_gem "country_select", "5.1.0" do |s| + s.add_dependency "countries", "~> 3.0" + end - expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") + build_gem "sixarm_ruby_unaccent", "1.1.0" end - it "should still downgrade if forced by the Gemfile" do - build_repo4 do - build_gem "a" - build_gem "b", "1.0" - build_gem "b", "2.0" + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "country_select" + gem "countries" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + countries (3.1.0) + country_select (5.1.0) + countries (~> 3.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + countries + country_select + + BUNDLED WITH + #{Bundler::VERSION} + L + + previous_lockfile = lockfile + + bundle "lock --update" + + expect(lockfile).to eq(previous_lockfile) + end + + it "does not downgrade indirect dependencies unnecessarily" do + build_repo4 do + build_gem "a" do |s| + s.add_dependency "b" + s.add_dependency "c" end + build_gem "b" + build_gem "c" + build_gem "c", "2.0" + end - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "a" - gem "b" - G + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo4)}" + gem "a" + G - expect(the_bundle).to include_gems("a 1.0", "b 2.0") + expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0") - gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "a" - gem "b", "1.0" - G + update_repo4 do + build_gem "b", "2.0" do |s| + s.add_dependency "c", "< 2" + end + end - bundle! "update b" + bundle "update", :all => true, :verbose => true + expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0") + end - expect(the_bundle).to include_gems("a 1.0", "b 1.0") + it "should still downgrade if forced by the Gemfile" do + build_repo4 do + build_gem "a" + build_gem "b", "1.0" + build_gem "b", "2.0" end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "a" + gem "b" + G + + expect(the_bundle).to include_gems("a 1.0", "b 2.0") + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "a" + gem "b", "1.0" + G + + bundle "update b" + + expect(the_bundle).to include_gems("a 1.0", "b 1.0") + end + + it "should still downgrade if forced by the Gemfile, when transitive dependencies also need downgrade" do + build_repo4 do + build_gem "activesupport", "6.1.4.1" do |s| + s.add_dependency "tzinfo", "~> 2.0" + end + + build_gem "activesupport", "6.0.4.1" do |s| + s.add_dependency "tzinfo", "~> 1.1" + end + + build_gem "tzinfo", "2.0.4" + build_gem "tzinfo", "1.2.9" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "activesupport", "~> 6.1.0" + G + + expect(the_bundle).to include_gems("activesupport 6.1.4.1", "tzinfo 2.0.4") + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "activesupport", "~> 6.0.0" + G + + original_lockfile = lockfile + + expected_lockfile = <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + activesupport (6.0.4.1) + tzinfo (~> 1.1) + tzinfo (1.2.9) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + activesupport (~> 6.0.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "update activesupport" + expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9") + expect(lockfile).to eq(expected_lockfile) + + lockfile original_lockfile + bundle "update" + expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9") + expect(lockfile).to eq(expected_lockfile) + + lockfile original_lockfile + bundle "lock --update" + expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9") + expect(lockfile).to eq(expected_lockfile) end end describe "with --local option" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "doesn't hit repo2" do FileUtils.rm_rf(gem_repo2) @@ -210,6 +438,10 @@ end describe "with --group option" do + before do + build_repo2 + end + it "should update only specified group gems" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -217,6 +449,10 @@ gem "rack" G update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end bundle "update --group development" @@ -242,7 +478,7 @@ end context "when there is a source with the same name as a gem in a group" do - before :each do + before do build_git "foo", :path => lib_path("activesupport") install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -269,6 +505,10 @@ gem "rack" G update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end bundle "update --group development" @@ -280,9 +520,20 @@ end describe "in a frozen bundle" do + before do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" + gem "platform_specific" + G + end + it "should fail loudly", :bundler => "< 3" do - bundle! "install --deployment" - bundle "update", :all => true + bundle "install --deployment" + bundle "update", :all => true, :raise_on_error => false expect(last_command).to be_failure expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m) @@ -290,56 +541,45 @@ end it "should suggest different command when frozen is set globally", :bundler => "< 3" do - bundle! "config set --global frozen 1" - bundle "update", :all => true + bundle "config set --global frozen 1" + bundle "update", :all => true, :raise_on_error => false expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m). and match(/freeze \nby running `bundle config unset frozen`./m) end it "should suggest different command when frozen is set globally", :bundler => "3" do - bundle! "config set --global deployment true" - bundle "update", :all => true + bundle "config set --global deployment true" + bundle "update", :all => true, :raise_on_error => false expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m). and match(/freeze \nby running `bundle config unset deployment`./m) end end describe "with --source option" do - it "should not update gems not included in the source that happen to have the same name", :bundler => "< 3" do - install_gemfile! <<-G + before do + build_repo2 + end + + it "should not update gems not included in the source that happen to have the same name" do + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" G update_repo2 { build_gem "activesupport", "3.0" } - bundle! "update --source activesupport" - expect(the_bundle).to include_gem "activesupport 3.0" + bundle "update --source activesupport" + expect(the_bundle).not_to include_gem "activesupport 3.0" end - it "should not update gems not included in the source that happen to have the same name", :bundler => "3" do - install_gemfile! <<-G + it "should not update gems not included in the source that happen to have the same name" do + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" G update_repo2 { build_gem "activesupport", "3.0" } - bundle! "update --source activesupport" - expect(the_bundle).not_to include_gem "activesupport 3.0" - end - - context "with unlock_source_unlocks_spec set to false" do - before { bundle! "config set unlock_source_unlocks_spec false" } - - it "should not update gems not included in the source that happen to have the same name" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - G - update_repo2 { build_gem "activesupport", "3.0" } - - bundle "update --source activesupport" - expect(the_bundle).not_to include_gems "activesupport 3.0" - end + bundle "update --source activesupport" + expect(the_bundle).not_to include_gems "activesupport 3.0" end end @@ -359,20 +599,7 @@ G end - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do - update_repo2 do - build_gem "fred", "2.0" - build_gem "harry", "2.0" do |s| - s.add_dependency "fred" - end - end - - bundle "update --source harry" - expect(the_bundle).to include_gems "harry 2.0" - expect(the_bundle).to include_gems "fred 1.0" - end - - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do + it "should not update the child dependencies of a gem that has the same name as the source" do update_repo2 do build_gem "fred", "2.0" build_gem "harry", "2.0" do |s| @@ -404,7 +631,7 @@ G end - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do + it "should not update the child dependencies of a gem that has the same name as the source" do update_repo2 do build_gem "george", "2.0" build_gem "harry", "2.0" do |s| @@ -413,27 +640,133 @@ end bundle "update --source harry" - expect(the_bundle).to include_gems "harry 2.0" - expect(the_bundle).to include_gems "fred 1.0" - expect(the_bundle).to include_gems "george 1.0" + expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0" end + end - it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do - update_repo2 do - build_gem "george", "2.0" - build_gem "harry", "2.0" do |s| - s.add_dependency "george" + it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do + build_repo2 + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + G + + bundle "update", :all => true + expect(out).to include("Using activesupport 2.3.5") + + update_repo2 do + build_gem "activesupport", "3.0" + end + + bundle "update", :all => true + expect(out).to include("Installing activesupport 3.0 (was 2.3.5)") + end + + context "with suppress_install_using_messages set" do + before { bundle "config set suppress_install_using_messages true" } + + it "only prints `Using` for versions that have changed" do + build_repo4 do + build_gem "bar" + build_gem "foo" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "bar" + gem "foo" + G + + bundle "update", :all => true + expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/) + + update_repo4 do + build_gem "foo", "2.0" + end + + bundle "update", :all => true + out.sub!("Removing foo (1.0)\n", "") + expect(out).to match(/Resolving dependencies\.\.\.\.*\nFetching foo 2\.0 \(was 1\.0\)\nInstalling foo 2\.0 \(was 1\.0\)\nBundle updated/) + end + end + + it "shows error message when Gemfile.lock is not preset and gem is specified" do + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + G + + bundle "update nonexisting", :raise_on_error => false + expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.") + expect(exitstatus).to eq(22) + end + + context "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do + before do + build_repo2 do + build_gem "dotenv", "2.7.6" + + build_gem "oj", "3.11.3" + build_gem "oj", "3.11.5" + + build_gem "vcr", "6.0.0" + end + + build_repo gem_repo3 do + build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s| + s.add_dependency "oj" end end - bundle "update --source harry" - expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0" + gemfile <<~G + source "https://gem.repo2" + + gem "dotenv" + + source "https://gem.repo3" do + gem 'pkg-gem-flowbyte-with-dep' + end + + gem "vcr",source: "https://gem.repo2" + G + + lockfile <<~L + GEM + remote: https://gem.repo2/ + remote: https://gem.repo3/ + specs: + dotenv (2.7.6) + oj (3.11.3) + pkg-gem-flowbyte-with-dep (1.0.0) + oj + vcr (6.0.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + dotenv + pkg-gem-flowbyte-with-dep! + vcr! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "works" do + bundle :install, :artifice => "compact_index" + bundle "update oj", :artifice => "compact_index" + + expect(out).to include("Bundle updated!") + expect(the_bundle).to include_gems "oj 3.11.5" end end end RSpec.describe "bundle update in more complicated situations" do - before :each do + before do build_repo2 end @@ -446,6 +779,10 @@ G update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "thin", "2.0" do |s| s.add_dependency "rack" end @@ -456,7 +793,7 @@ end it "will warn when some explicitly updated gems are not updated" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "thin" @@ -468,7 +805,7 @@ build_gem "rack", "10.0" end - bundle! "update thin rack-obama" + bundle "update thin rack-obama" expect(last_command.stdboth).to include "Bundler attempted to update rack-obama but its version stayed the same" expect(the_bundle).to include_gems "thin 2.0", "rack 10.0", "rack-obama 1.0" end @@ -476,7 +813,8 @@ it "will not warn when an explicitly updated git gem changes sha but not version" do build_git "foo" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => '#{lib_path("foo-1.0")}' G @@ -484,7 +822,7 @@ s.write "lib/foo2.rb", "puts :foo2" end - bundle! "update foo" + bundle "update foo" expect(last_command.stdboth).not_to include "attempted to update" end @@ -492,7 +830,8 @@ it "will not warn when changing gem sources but not versions" do build_git "rack" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" gem "rack", :git => '#{lib_path("rack-1.0")}' G @@ -501,7 +840,7 @@ gem "rack" G - bundle! "update rack" + bundle "update rack" expect(last_command.stdboth).not_to include "attempted to update" end @@ -554,12 +893,12 @@ end it "allows updating" do - bundle! :update, :all => true + bundle :update, :all => true expect(the_bundle).to include_gem "a 1.1" end it "allows updating a specific gem" do - bundle! "update a" + bundle "update a" expect(the_bundle).to include_gem "a 1.1" end end @@ -593,7 +932,7 @@ end it "is not updated because it is not actually included in the bundle" do - bundle! "update a" + bundle "update a" expect(last_command.stdboth).to include "Bundler attempted to update a but it was not considered because it is for a different platform from the current one" expect(the_bundle).to_not include_gem "a" end @@ -617,11 +956,13 @@ end RSpec.describe "bundle update when a gem depends on a newer version of bundler" do - before(:each) do + before do build_repo2 do build_gem "rails", "3.0.1" do |s| s.add_dependency "bundler", Bundler::VERSION.succ end + + build_gem "bundler", Bundler::VERSION.succ end gemfile <<-G @@ -630,110 +971,32 @@ G end - it "should explain that bundler conflicted", :bundler => "< 3" do - bundle "update", :all => true + it "should explain that bundler conflicted and how to resolve the conflict" do + bundle "update", :all => true, :raise_on_error => false expect(last_command.stdboth).not_to match(/in snapshot/i) expect(err).to match(/current Bundler version/i). - and match(/perhaps you need to update bundler/i) - end - - it "should warn that the newer version of Bundler would conflict", :bundler => "3" do - bundle! "update", :all => true - expect(err).to include("rails (3.0.1) has dependency bundler"). - and include("so the dependency is being ignored") - expect(the_bundle).to include_gem "rails 3.0.1" - end -end - -RSpec.describe "bundle update" do - it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do - build_repo2 - - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - G - - bundle "update", :all => true - expect(out).to include("Using activesupport 2.3.5") - - update_repo2 do - build_gem "activesupport", "3.0" - end - - bundle "update", :all => true - expect(out).to include("Installing activesupport 3.0 (was 2.3.5)") - end - - context "with suppress_install_using_messages set" do - before { bundle! "config set suppress_install_using_messages true" } - - it "only prints `Using` for versions that have changed" do - build_repo4 do - build_gem "bar" - build_gem "foo" - end - - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "bar" - gem "foo" - G - - bundle! "update", :all => true - out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "") - expect(out).to include "Resolving dependencies...\nBundle updated!" - - update_repo4 do - build_gem "foo", "2.0" - end - - bundle! "update", :all => true - out.sub!("Removing foo (1.0)\n", "") - out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "") - expect(out).to include strip_whitespace(<<-EOS).strip - Resolving dependencies... - Fetching foo 2.0 (was 1.0) - Installing foo 2.0 (was 1.0) - Bundle updated - EOS - end - end - - it "shows error message when Gemfile.lock is not preset and gem is specified" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - G - - bundle "update nonexisting" - expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.") - expect(exitstatus).to eq(22) if exitstatus + and match(/Install the necessary version with `gem install bundler:#{Bundler::VERSION.succ}`/i) end end RSpec.describe "bundle update --ruby" do - before do - install_gemfile <<-G - ::RUBY_VERSION = '2.1.3' - ::RUBY_PATCHLEVEL = 100 - ruby '~> 2.1.0' - G - bundle "update --ruby" - end - context "when the Gemfile removes the ruby" do before do install_gemfile <<-G - ::RUBY_VERSION = '2.1.4' - ::RUBY_PATCHLEVEL = 222 + ruby '~> #{RUBY_VERSION}' + source "#{file_uri_for(gem_repo1)}" + G + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" G end it "removes the Ruby from the Gemfile.lock" do bundle "update --ruby" - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -750,16 +1013,21 @@ context "when the Gemfile specified an updated Ruby version" do before do install_gemfile <<-G - ::RUBY_VERSION = '2.1.4' - ::RUBY_PATCHLEVEL = 222 - ruby '~> 2.1.0' + ruby '~> #{RUBY_VERSION}' + source "#{file_uri_for(gem_repo1)}" + G + + gemfile <<-G + ruby '~> #{RUBY_VERSION[0..2]}' + source "#{file_uri_for(gem_repo1)}" G end it "updates the Gemfile.lock with the latest version" do bundle "update --ruby" - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -768,7 +1036,7 @@ DEPENDENCIES RUBY VERSION - ruby 2.1.4p222 + #{Bundler::RubyVersion.system} BUNDLED WITH #{Bundler::VERSION} @@ -779,31 +1047,52 @@ context "when a different Ruby is being used than has been versioned" do before do install_gemfile <<-G - ::RUBY_VERSION = '2.2.2' - ::RUBY_PATCHLEVEL = 505 + ruby '~> #{RUBY_VERSION}' + source "#{file_uri_for(gem_repo1)}" + G + + gemfile <<-G ruby '~> 2.1.0' + source "#{file_uri_for(gem_repo1)}" G end it "shows a helpful error message" do - bundle "update --ruby" + bundle "update --ruby", :raise_on_error => false - expect(err).to include("Your Ruby version is 2.2.2, but your Gemfile specified ~> 2.1.0") + expect(err).to include("Your Ruby version is #{Bundler::RubyVersion.system.gem_version}, but your Gemfile specified ~> 2.1.0") end end context "when updating Ruby version and Gemfile `ruby`" do before do - install_gemfile <<-G - ::RUBY_VERSION = '1.8.3' - ::RUBY_PATCHLEVEL = 55 - ruby '~> 1.8.0' + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + + RUBY VERSION + ruby 2.1.4p222 + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<-G + ruby '~> #{RUBY_VERSION}' + source "#{file_uri_for(gem_repo1)}" G end it "updates the Gemfile.lock with the latest version" do bundle "update --ruby" - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -812,7 +1101,7 @@ DEPENDENCIES RUBY VERSION - ruby 1.8.3p55 + #{Bundler::RubyVersion.system} BUNDLED WITH #{Bundler::VERSION} @@ -827,7 +1116,7 @@ build_gem "rack", "1.0" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" gem "rack" G @@ -835,10 +1124,204 @@ FileUtils.rm_r gem_repo4 - bundle! :update, :bundler => true, :verbose => true + bundle :update, :bundler => true, :artifice => "compact_index", :verbose => true + expect(out).to include("Using bundler #{Bundler::VERSION}") + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack + + BUNDLED WITH + #{Bundler::VERSION} + L + + expect(the_bundle).to include_gem "rack 1.0" + end + + it "updates the bundler version in the lockfile without re-resolving if the highest version is already installed" do + system_gems "bundler-2.3.3" + + build_repo4 do + build_gem "rack", "1.0" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.3") + + bundle :update, :bundler => true, :artifice => "compact_index", :verbose => true + expect(out).to include("Using bundler #{Bundler::VERSION}") + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack + + BUNDLED WITH + #{Bundler::VERSION} + L + expect(the_bundle).to include_gem "rack 1.0" + end + + it "updates the bundler version in the lockfile even if the latest version is not installed", :ruby_repo, :realworld do + pristine_system_gems "bundler-2.3.3" + + build_repo4 do + build_gem "rack", "1.0" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.3") + + bundle :update, :bundler => true, :artifice => "vcr", :verbose => true + + # Only updates properly on modern RubyGems. + + if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev") + expect(out).to include("Updating bundler to 2.3.4") + expect(out).to include("Using bundler 2.3.4") + expect(out).not_to include("Installing Bundler 2.3.3 and restarting using that version.") + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack + + BUNDLED WITH + 2.3.4 + L + + expect(the_bundle).to include_gems "bundler 2.3.4" + end + + expect(the_bundle).to include_gems "rack 1.0" + end + + it "errors if the explicit target version does not exist", :realworld do + pristine_system_gems "bundler-2.3.3" + + build_repo4 do + build_gem "rack", "1.0" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.3") + + bundle :update, :bundler => "999.999.999", :artifice => "vcr", :raise_on_error => false + + # Only gives a meaningful error message on modern RubyGems. + + if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev") + expect(last_command).to be_failure + expect(err).to include("The `bundle update --bundler` target version (999.999.999) does not exist") + end + end + + it "allows updating to development versions if already installed locally" do + system_gems "bundler-2.3.0.dev" + + build_repo4 do + build_gem "rack", "1.0" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + + bundle :update, :bundler => "2.3.0.dev" + + # Only updates properly on modern RubyGems. + + if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev") + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack + + BUNDLED WITH + 2.3.0.dev + L + + expect(out).to include("Using bundler 2.3.0.dev") + end + end + + it "does not touch the network if not necessary" do + system_gems "bundler-2.3.3" + + build_repo4 do + build_gem "rack", "1.0" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "rack" + G + + bundle :update, :bundler => "2.3.3", :raise_on_error => false + + expect(out).not_to include("Fetching gem metadata from https://rubygems.org/") + + # Only updates properly on modern RubyGems. + + if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev") + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + rack (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack - expect(the_bundle.locked_gems.bundler_version).to eq v(Bundler::VERSION) + BUNDLED WITH + 2.3.3 + L + + expect(out).to include("Using bundler 2.3.3") + end end end @@ -879,8 +1362,8 @@ context "with patch set as default update level in config" do it "should do a patch level update" do - bundle! "config set --local prefer_patch true" - bundle! "update foo" + bundle "config set --local prefer_patch true" + bundle "update foo" expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0" end @@ -888,13 +1371,13 @@ context "patch preferred" do it "single gem updates dependent gem to minor" do - bundle! "update --patch foo" + bundle "update --patch foo" expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0" end it "update all" do - bundle! "update --patch", :all => true + bundle "update --patch", :all => true expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.1" end @@ -902,7 +1385,7 @@ context "minor preferred" do it "single gem updates dependent gem to major" do - bundle! "update --minor foo" + bundle "update --minor foo" expect(the_bundle).to include_gems "foo 1.5.1", "bar 3.0.0", "qux 1.0.0" end @@ -910,13 +1393,13 @@ context "strict" do it "patch preferred" do - bundle! "update --patch foo bar --strict" + bundle "update --patch foo bar --strict" expect(the_bundle).to include_gems "foo 1.4.4", "bar 2.0.5", "qux 1.0.0" end it "minor preferred" do - bundle! "update --minor --strict", :all => true + bundle "update --minor --strict", :all => true expect(the_bundle).to include_gems "foo 1.5.0", "bar 2.1.1", "qux 1.1.0" end @@ -948,9 +1431,9 @@ gem 'shared_owner_b' G - lockfile <<-L + lockfile <<~L GEM - remote: #{file_uri_for(gem_repo4)} + remote: #{file_uri_for(gem_repo4)}/ specs: isolated_dep (2.0.1) isolated_owner (1.0.1) @@ -962,15 +1445,15 @@ shared_dep (~> 5.0) PLATFORMS - ruby + #{specific_local_platform} DEPENDENCIES + isolated_owner shared_owner_a shared_owner_b - isolated_owner BUNDLED WITH - 1.13.0 + #{Bundler::VERSION} L end @@ -989,7 +1472,42 @@ it "should not eagerly unlock with --conservative" do bundle "update --conservative shared_owner_a isolated_owner" - expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1" + expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1" + end + + it "should only update direct dependencies when fully updating with --conservative" do + bundle "update --conservative" + + expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.2" + end + + it "should only change direct dependencies when updating the lockfile with --conservative" do + bundle "lock --update --conservative" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + isolated_dep (2.0.1) + isolated_owner (1.0.2) + isolated_dep (~> 2.0) + shared_dep (5.0.1) + shared_owner_a (3.0.2) + shared_dep (~> 5.0) + shared_owner_b (4.0.2) + shared_dep (~> 5.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + isolated_owner + shared_owner_a + shared_owner_b + + BUNDLED WITH + #{Bundler::VERSION} + L end it "should match bundle install conservative update behavior when not eagerly unlocking" do @@ -1009,11 +1527,11 @@ context "error handling" do before do - gemfile "" + gemfile "source \"#{file_uri_for(gem_repo1)}\"" end it "raises if too many flags are provided" do - bundle "update --patch --minor", :all => true + bundle "update --patch --minor", :all => true, :raise_on_error => false expect(err).to eq "Provide only one of the following options: minor, patch" end diff --git a/ruby/spec/bundler/commands/version_spec.rb b/ruby/spec/bundler/commands/version_spec.rb index 8eecd9c53..53d545f5f 100644 --- a/ruby/spec/bundler/commands/version_spec.rb +++ b/ruby/spec/bundler/commands/version_spec.rb @@ -11,36 +11,36 @@ context "with -v" do it "outputs the version", :bundler => "< 3" do - bundle! "-v" + bundle "-v" expect(out).to eq("Bundler version #{Bundler::VERSION}") end it "outputs the version", :bundler => "3" do - bundle! "-v" + bundle "-v" expect(out).to eq(Bundler::VERSION) end end context "with --version" do it "outputs the version", :bundler => "< 3" do - bundle! "--version" + bundle "--version" expect(out).to eq("Bundler version #{Bundler::VERSION}") end it "outputs the version", :bundler => "3" do - bundle! "--version" + bundle "--version" expect(out).to eq(Bundler::VERSION) end end context "with version" do it "outputs the version with build metadata", :bundler => "< 3" do - bundle! "version" + bundle "version" expect(out).to match(/\ABundler version #{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/) end it "outputs the version with build metadata", :bundler => "3" do - bundle! "version" + bundle "version" expect(out).to match(/\A#{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/) end end diff --git a/ruby/spec/bundler/commands/viz_spec.rb b/ruby/spec/bundler/commands/viz_spec.rb index 029c3aca2..0efb24b50 100644 --- a/ruby/spec/bundler/commands/viz_spec.rb +++ b/ruby/spec/bundler/commands/viz_spec.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do - let(:ruby_graphviz) do - graphviz_glob = base_system_gems.join("cache/ruby-graphviz*") - Pathname.glob(graphviz_glob).first - end - before do - system_gems ruby_graphviz + graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4" + + realworld_system_gems "ruby-graphviz --version #{graphviz_version}" end it "graphs gems from the Gemfile" do @@ -17,10 +14,10 @@ gem "rack-obama" G - bundle! "viz" + bundle "viz" expect(out).to include("gem_graph.png") - bundle! "viz", :format => "debug" + bundle "viz", :format => "debug" expect(out).to eq(strip_whitespace(<<-DOT).strip) digraph Gemfile { concentrate = "true"; @@ -51,10 +48,10 @@ gem "rack-obama" G - bundle! "viz" + bundle "viz" expect(out).to include("gem_graph.png") - bundle! "viz", :format => :debug, :version => true + bundle "viz", :format => :debug, :version => true expect(out).to eq(strip_whitespace(<<-EOS).strip) digraph Gemfile { concentrate = "true"; @@ -82,7 +79,7 @@ end end - system_gems ruby_graphviz, "graphviz-999", :gem_repo => gem_repo4 + system_gems "graphviz-999", :gem_repo => gem_repo4 end it "loads the correct ruby-graphviz gem" do @@ -92,7 +89,7 @@ gem "rack-obama" G - bundle! "viz", :format => "debug" + bundle "viz", :format => "debug" expect(out).to eq(strip_whitespace(<<-DOT).strip) digraph Gemfile { concentrate = "true"; @@ -124,7 +121,7 @@ end G - bundle! "viz --without=rails" + bundle "viz --without=rails" expect(out).to include("gem_graph.png") end @@ -142,7 +139,7 @@ end G - bundle! "viz --without=rails:rack" + bundle "viz --without=rails:rack" expect(out).to include("gem_graph.png") end end diff --git a/ruby/spec/bundler/install/allow_offline_install_spec.rb b/ruby/spec/bundler/install/allow_offline_install_spec.rb index 8af88b7ef..524363fde 100644 --- a/ruby/spec/bundler/install/allow_offline_install_spec.rb +++ b/ruby/spec/bundler/install/allow_offline_install_spec.rb @@ -7,7 +7,7 @@ context "with no cached data locally" do it "still installs" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" source "http://testgemserver.local" gem "rack-obama" G @@ -15,7 +15,7 @@ end it "still fails when the network is down" do - install_gemfile <<-G, :artifice => "fail" + install_gemfile <<-G, :artifice => "fail", :raise_on_error => false source "http://testgemserver.local" gem "rack-obama" G @@ -26,10 +26,10 @@ context "with cached data locally" do it "will install from the compact index" do - system_gems ["rack-1.0.0"], :path => :bundle_path + system_gems ["rack-1.0.0"], :path => default_bundle_path - bundle! "config set clean false" - install_gemfile! <<-G, :artifice => "compact_index" + bundle "config set clean false" + install_gemfile <<-G, :artifice => "compact_index" source "http://testgemserver.local" gem "rack-obama" gem "rack", "< 1.0" @@ -42,7 +42,7 @@ gem "rack-obama" G - bundle! :update, :artifice => "fail", :all => true + bundle :update, :artifice => "fail", :all => true expect(last_command.stdboth).to include "Using the cached data for the new index because of a network error" expect(the_bundle).to include_gems("rack-obama 1.0", "rack 1.0.0") @@ -70,18 +70,22 @@ def break_git_remote_ops! end it "will install from a cached git repo" do + skip "doesn't print errors" if Gem.win_platform? + git = build_git "a", "1.0.0", :path => lib_path("a") update_git("a", :path => git.path, :branch => "new_branch") - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "a", :git => #{git.path.to_s.dump} G - break_git_remote_ops! { bundle! :update, :all => true } + break_git_remote_ops! { bundle :update, :all => true } expect(err).to include("Using cached git data because of network errors") expect(the_bundle).to be_locked break_git_remote_ops! do - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "a", :git => #{git.path.to_s.dump}, :branch => "new_branch" G end diff --git a/ruby/spec/bundler/install/binstubs_spec.rb b/ruby/spec/bundler/install/binstubs_spec.rb index 78ee893b8..6961171f4 100644 --- a/ruby/spec/bundler/install/binstubs_spec.rb +++ b/ruby/spec/bundler/install/binstubs_spec.rb @@ -35,7 +35,7 @@ def Gem.bindir; "/usr/bin"; end end it "warns about the situation" do - bundle! "exec rackup" + bundle "exec rackup" expect(last_command.stderr).to include( "The `rackup` executable in the `fake` gem is being loaded, but it's also present in other gems (rack).\n" \ diff --git a/ruby/spec/bundler/install/bundler_spec.rb b/ruby/spec/bundler/install/bundler_spec.rb index 6ea15d13b..963ce82db 100644 --- a/ruby/spec/bundler/install/bundler_spec.rb +++ b/ruby/spec/bundler/install/bundler_spec.rb @@ -21,18 +21,58 @@ expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}" end - it "are not added if not already present" do + it "are forced to the current bundler version even if not already present" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - expect(the_bundle).not_to include_gems "bundler #{Bundler::VERSION}" + expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}" end - it "causes a conflict if explicitly requesting a different version" do - bundle "config set force_ruby_platform true" + it "causes a conflict if explicitly requesting a different version of bundler" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rails", "3.0" + gem "bundler", "0.9.1" + G - install_gemfile <<-G + nice_error = <<-E.strip.gsub(/^ {8}/, "") + Bundler could not find compatible versions for gem "bundler": + In Gemfile: + bundler (= 0.9.1) + + Current Bundler version: + bundler (#{Bundler::VERSION}) + + Your bundle requires a different version of Bundler than the one you're running. + Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` + E + expect(err).to include(nice_error) + end + + it "causes a conflict if explicitly requesting a non matching requirement on bundler" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rails", "3.0" + gem "bundler", "~> 0.8" + G + + nice_error = <<-E.strip.gsub(/^ {8}/, "") + Bundler could not find compatible versions for gem "bundler": + In Gemfile: + bundler (~> 0.8) + + Current Bundler version: + bundler (#{Bundler::VERSION}) + + Your bundle requires a different version of Bundler than the one you're running. + Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` + E + expect(err).to include(nice_error) + end + + it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "rails", "3.0" gem "bundler", "0.9.2" @@ -45,15 +85,19 @@ Current Bundler version: bundler (#{Bundler::VERSION}) - This Gemfile requires a different version of Bundler. - Perhaps you need to update Bundler by running `gem install bundler`? - Could not find gem 'bundler (= 0.9.2)' in any + Your bundle requires a different version of Bundler than the one you're running, and that version could not be found. E expect(err).to include(nice_error) end it "works for gems with multiple versions in its dependencies" do + build_repo2 do + build_gem "multiple_versioned_deps" do |s| + s.add_dependency "weakling", ">= 0.0.1", "< 0.1" + end + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -93,10 +137,16 @@ it "causes a conflict if child dependencies conflict" do bundle "config set force_ruby_platform true" - install_gemfile <<-G + update_repo2 do + build_gem "rails_pinned_to_old_activesupport" do |s| + s.add_dependency "activesupport", "= 1.2.3" + end + end + + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "activemerchant" - gem "rails_fail" + gem "rails_pinned_to_old_activesupport" G nice_error = <<-E.strip.gsub(/^ {8}/, "") @@ -105,7 +155,7 @@ activemerchant was resolved to 1.0, which depends on activesupport (>= 2.0.0) - rails_fail was resolved to 1.0, which depends on + rails_pinned_to_old_activesupport was resolved to 1.0, which depends on activesupport (= 1.2.3) E expect(err).to include(nice_error) @@ -114,9 +164,15 @@ it "causes a conflict if a child dependency conflicts with the Gemfile" do bundle "config set force_ruby_platform true" - install_gemfile <<-G + update_repo2 do + build_gem "rails_pinned_to_old_activesupport" do |s| + s.add_dependency "activesupport", "= 1.2.3" + end + end + + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" - gem "rails_fail" + gem "rails_pinned_to_old_activesupport" gem "activesupport", "2.3.5" G @@ -125,58 +181,59 @@ In Gemfile: activesupport (= 2.3.5) - rails_fail was resolved to 1.0, which depends on + rails_pinned_to_old_activesupport was resolved to 1.0, which depends on activesupport (= 1.2.3) E expect(err).to include(nice_error) end - it "can install dependencies with newer bundler version with system gems" do - bundle! "config set path.system true" - install_gemfile! <<-G + it "does not cause a conflict if new dependencies in the Gemfile require older dependencies than the lockfile" do + update_repo2 do + build_gem "rails_pinned_to_old_activesupport" do |s| + s.add_dependency "activesupport", "= 1.2.3" + end + end + + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" - gem "rails", "3.0" + gem 'rails', "2.3.2" G - simulate_bundler_version "99999999.99.1" + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "rails_pinned_to_old_activesupport" + G - bundle! "check" - expect(out).to include("The Gemfile's dependencies are satisfied") + expect(out).to include("Installing activesupport 1.2.3 (was 2.3.2)") + expect(err).to be_empty end - it "can install dependencies with newer bundler version with a local path" do - bundle! "config set path .bundle" - install_gemfile! <<-G + it "can install dependencies with newer bundler version with system gems" do + bundle "config set path.system true" + + system_gems "bundler-99999999.99.1" + + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rails", "3.0" G - simulate_bundler_version "99999999.99.1" - - bundle! "check" + bundle "check" expect(out).to include("The Gemfile's dependencies are satisfied") end - context "with allow_bundler_dependency_conflicts set" do - before { bundle! "config set allow_bundler_dependency_conflicts true" } - - it "are forced to the current bundler version with warnings when no compatible version is found" do - build_repo4 do - build_gem "requires_nonexistant_bundler" do |s| - s.add_runtime_dependency "bundler", "99.99.99.99" - end - end + it "can install dependencies with newer bundler version with a local path" do + bundle "config set path .bundle" - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "requires_nonexistant_bundler" - G + system_gems "bundler-99999999.99.1" - expect(err).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \ - "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored" + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "rails", "3.0" + G - expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0" - end + bundle "check" + expect(out).to include("The Gemfile's dependencies are satisfied") end end end diff --git a/ruby/spec/bundler/install/deploy_spec.rb b/ruby/spec/bundler/install/deploy_spec.rb index f92a531bf..3bcb6a703 100644 --- a/ruby/spec/bundler/install/deploy_spec.rb +++ b/ruby/spec/bundler/install/deploy_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "install with --deployment or --frozen" do +RSpec.describe "install in deployment or frozen mode" do before do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -10,76 +10,94 @@ context "with CLI flags", :bundler => "< 3" do it "fails without a lockfile and says that --deployment requires a lock" do - bundle "install --deployment" + bundle "install --deployment", :raise_on_error => false expect(err).to include("The --deployment flag requires a Gemfile.lock") end it "fails without a lockfile and says that --frozen requires a lock" do - bundle "install --frozen" + bundle "install --frozen", :raise_on_error => false expect(err).to include("The --frozen flag requires a Gemfile.lock") end it "disallows --deployment --system" do - bundle "install --deployment --system" + bundle "install --deployment --system", :raise_on_error => false expect(err).to include("You have specified both --deployment") expect(err).to include("Please choose only one option") - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) end it "disallows --deployment --path --system" do - bundle "install --deployment --path . --system" + bundle "install --deployment --path . --system", :raise_on_error => false expect(err).to include("You have specified both --path") expect(err).to include("as well as --system") expect(err).to include("Please choose only one option") - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) end it "doesn't mess up a subsequent `bundle install` after you try to deploy without a lock" do - bundle "install --deployment" - bundle! :install + bundle "install --deployment", :raise_on_error => false + bundle :install expect(the_bundle).to include_gems "rack 1.0" end end it "still works if you are not in the app directory and specify --gemfile" do - bundle! "install" - Dir.chdir tmp do - simulate_new_machine - bundle! :install, - forgotten_command_line_options(:gemfile => "#{tmp}/bundled_app/Gemfile", - :deployment => true, - :path => "vendor/bundle") - end + bundle "install" + simulate_new_machine + bundle "config set --local deployment true" + bundle "config set --local path vendor/bundle" + bundle "install --gemfile #{tmp}/bundled_app/Gemfile", :dir => tmp expect(the_bundle).to include_gems "rack 1.0" end it "works if you exclude a group with a git gem" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" group :test do gem "foo", :git => "#{lib_path("foo-1.0")}" end G - bundle! :install - bundle! :install, forgotten_command_line_options(:deployment => true, :without => "test") + bundle :install + bundle "config set --local deployment true" + bundle "config set --local without test" + bundle :install end it "works when you bundle exec bundle" do - bundle! :install - bundle "install --deployment" - bundle! "exec bundle check" + skip "doesn't find bundle" if Gem.win_platform? + + bundle :install + bundle "config set --local deployment true" + bundle :install + bundle "exec bundle check", :env => { "PATH" => path } end it "works when using path gems from the same path and the version is specified" do build_lib "foo", :path => lib_path("nested/foo") build_lib "bar", :path => lib_path("nested/bar") gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.0", :path => "#{lib_path("nested")}" gem "bar", :path => "#{lib_path("nested")}" G - bundle! :install - bundle! :install, forgotten_command_line_options(:deployment => true) + bundle :install + bundle "config set --local deployment true" + bundle :install + end + + it "works when path gems are specified twice" do + build_lib "foo", :path => lib_path("nested/foo") + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "foo", :path => "#{lib_path("nested/foo")}" + gem "foo", :path => "#{lib_path("nested/foo")}" + G + + bundle :install + bundle "config set --local deployment true" + bundle :install end it "works when there are credentials in the source URL" do @@ -89,66 +107,70 @@ gem "rack-obama", ">= 1.0" G - bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint_strict_basic_authentication") + bundle "config set --local deployment true" + bundle :install, :artifice => "endpoint_strict_basic_authentication" end it "works with sources given by a block" do - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}" do gem "rack" end G - bundle! :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install expect(the_bundle).to include_gems "rack 1.0" end context "when replacing a host with the same host with credentials" do before do - bundle! "install", forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle "install" gemfile <<-G - source "http://user_name:password@localgemserver.test/" - gem "rack" + source "http://user_name:password@localgemserver.test/" + gem "rack" G lockfile <<-G - GEM - remote: http://localgemserver.test/ - specs: - rack (1.0.0) + GEM + remote: http://localgemserver.test/ + specs: + rack (1.0.0) - PLATFORMS - #{local} + PLATFORMS + #{local} - DEPENDENCIES - rack + DEPENDENCIES + rack G - bundle! "config set --local deployment true" + bundle "config set --local deployment true" end it "prevents the replace by default" do - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/The list of sources changed/) end context "when allow_deployment_source_credential_changes is true" do - before { bundle! "config set allow_deployment_source_credential_changes true" } + before { bundle "config set allow_deployment_source_credential_changes true" } it "allows the replace" do - bundle! :install + bundle :install expect(out).to match(/Bundle complete!/) end end context "when allow_deployment_source_credential_changes is false" do - before { bundle! "config set allow_deployment_source_credential_changes false" } + before { bundle "config set allow_deployment_source_credential_changes false" } it "prevents the replace" do - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/The list of sources changed/) end @@ -168,7 +190,7 @@ before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "false" } it "prevents the replace" do - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/The list of sources changed/) end @@ -177,29 +199,29 @@ describe "with an existing lockfile" do before do - bundle! "install" + bundle "install" end it "installs gems by default to vendor/bundle", :bundler => "< 3" do - bundle! "install --deployment" + bundle "install --deployment" expect(out).to include("vendor/bundle") end it "installs gems to custom path if specified", :bundler => "< 3" do - bundle! "install --path vendor/bundle2 --deployment" + bundle "install --path vendor/bundle2 --deployment" expect(out).to include("vendor/bundle2") end it "works with the --deployment flag if you didn't change anything", :bundler => "< 3" do - bundle! "install --deployment" + bundle "install --deployment" end it "works with the --frozen flag if you didn't change anything", :bundler => "< 3" do - bundle! "install --frozen" + bundle "install --frozen" end it "works with BUNDLE_FROZEN if you didn't change anything" do - bundle! :install, :env => { "BUNDLE_FROZEN" => "true" } + bundle :install, :env => { "BUNDLE_FROZEN" => "true" } end it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do @@ -209,7 +231,8 @@ gem "rack-obama" G - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("deployment mode") expect(err).to include("You have added to the Gemfile") expect(err).to include("* rack-obama") @@ -219,7 +242,7 @@ it "works if a path gem is missing but is in a without group" do build_lib "path_gem" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rake" gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development @@ -227,14 +250,28 @@ expect(the_bundle).to include_gems "path_gem 1.0" FileUtils.rm_r lib_path("path_gem-1.0") - bundle! :install, forgotten_command_line_options(:path => ".bundle", :without => "development", :deployment => true).merge(:env => { "DEBUG" => "1" }) - run! "puts :WIN" + bundle "config set --local path .bundle" + bundle "config set --local without development" + bundle "config set --local deployment true" + bundle :install, :env => { "DEBUG" => "1" } + run "puts :WIN" expect(out).to eq("WIN") end + it "works if a gem is missing, but it's on a different platform, and the Gemfile has no global source", :bundler => "< 3" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" do + gem "rake", platform: :#{not_local_tag} + end + G + + bundle :install, :env => { "BUNDLE_FROZEN" => "true" } + expect(last_command).to be_success + end + it "explodes if a path gem is missing" do build_lib "path_gem" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rake" gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development @@ -242,7 +279,9 @@ expect(the_bundle).to include_gems "path_gem 1.0" FileUtils.rm_r lib_path("path_gem-1.0") - bundle :install, forgotten_command_line_options(:path => ".bundle", :deployment => true) + bundle "config set --local path .bundle" + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.") end @@ -254,7 +293,7 @@ G ENV["BUNDLE_FROZEN"] = "1" - bundle "install" + bundle "install", :raise_on_error => false expect(err).to include("deployment mode") expect(err).to include("You have added to the Gemfile") expect(err).to include("* rack-obama") @@ -270,7 +309,7 @@ G ENV["BUNDLE_DEPLOYMENT"] = "true" - bundle "install" + bundle "install", :raise_on_error => false expect(err).to include("deployment mode") expect(err).to include("You have added to the Gemfile") expect(err).to include("* rack-obama") @@ -278,7 +317,7 @@ expect(err).not_to include("You have changed in the Gemfile") end - it "installs gems by default to vendor/bundle when `--deployment` is set via an environment variable", :bundler => "< 3" do + it "installs gems by default to vendor/bundle when deployment mode is set via an environment variable", :bundler => "< 3" do ENV["BUNDLE_DEPLOYMENT"] = "true" bundle "install" expect(out).to include("vendor/bundle") @@ -312,7 +351,8 @@ gem "activesupport" G - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("deployment mode") expect(err).to include("You have added to the Gemfile:\n* activesupport\n\n") expect(err).to include("You have deleted from the Gemfile:\n* rack") @@ -325,13 +365,14 @@ gem "rack", :git => "git://hubz.com" G - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)") - expect(err).not_to include("You have changed in the Gemfile") + expect(err).not_to include("You have added to the Gemfile") + expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `git://hubz.com`") end - it "explodes if you unpin a source" do + it "explodes if you change a source" do build_git "rack" install_gemfile <<-G @@ -344,14 +385,15 @@ gem "rack" G - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master@#{revision_for(lib_path("rack-1.0"))[0..6]}") + expect(err).not_to include("You have deleted from the Gemfile") expect(err).not_to include("You have added to the Gemfile") - expect(err).not_to include("You have changed in the Gemfile") + expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack-1.0")}` to `no specified source`") end - it "explodes if you unpin a source, leaving it pinned somewhere else" do + it "explodes if you change a source" do build_lib "foo", :path => lib_path("rack/foo") build_git "rack", :path => lib_path("rack") @@ -367,17 +409,18 @@ gem "foo", :git => "#{lib_path("rack")}" G - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master@#{revision_for(lib_path("rack"))[0..6]})`") + expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack")}` to `no specified source`") expect(err).not_to include("You have added to the Gemfile") expect(err).not_to include("You have deleted from the Gemfile") end it "remembers that the bundle is frozen at runtime" do - bundle! :lock + bundle :lock - bundle! "config set --local deployment true" + bundle "config set --local deployment true" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -385,7 +428,7 @@ gem "rack-obama" G - expect(the_bundle).not_to include_gems "rack 1.0.0" + run "require 'rack'", :raise_on_error => false expect(err).to include strip_whitespace(<<-E).strip The dependencies in your gemfile changed @@ -402,23 +445,24 @@ context "with path in Gemfile and packed" do it "works fine after bundle package and bundle install --local" do build_lib "foo", :path => lib_path("foo") - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo")}" G - bundle! :install + bundle :install expect(the_bundle).to include_gems "foo 1.0" bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/foo")).to be_directory - bundle! "install --local" + bundle "install --local" expect(out).to include("Updating files in vendor/cache") simulate_new_machine - bundle! "config set --local deployment true" - bundle! "install --verbose" + bundle "config set --local deployment true" + bundle "install --verbose" expect(out).not_to include("You are trying to install in deployment mode after changing your Gemfile") expect(out).not_to include("You have added to the Gemfile") expect(out).not_to include("You have deleted from the Gemfile") diff --git a/ruby/spec/bundler/install/failure_spec.rb b/ruby/spec/bundler/install/failure_spec.rb index 57ffafd58..4a9c33754 100644 --- a/ruby/spec/bundler/install/failure_spec.rb +++ b/ruby/spec/bundler/install/failure_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "bundle install" do context "installing a gem fails" do - it "prints out why that gem was being installed" do + it "prints out why that gem was being installed and the underlying error" do build_repo2 do build_gem "activesupport", "2.3.2" do |s| s.extensions << "Rakefile" @@ -14,106 +14,13 @@ end end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "rails" G + expect(err).to start_with("Gem::Ext::BuildError: ERROR: Failed to build gem native extension.") expect(err).to end_with(<<-M.strip) An error occurred while installing activesupport (2.3.2), and Bundler cannot continue. -Make sure that `gem install activesupport -v '2.3.2' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling. - -In Gemfile: - rails was resolved to 2.3.2, which depends on - actionmailer was resolved to 2.3.2, which depends on - activesupport - M - end - - context "when installing a git gem" do - it "does not tell the user to run 'gem install'" do - build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - abort "make installing activesupport-2.3.2 fail" - end - RUBY - end - - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rails" - gem "activesupport", :git => "#{lib_path("activesupport")}" - G - - expect(err).to end_with(<<-M.strip) -An error occurred while installing activesupport (2.3.2), and Bundler cannot continue. - -In Gemfile: - rails was resolved to 2.3.2, which depends on - actionmailer was resolved to 2.3.2, which depends on - activesupport - M - end - end - - context "when installing a gem using a git block" do - it "does not tell the user to run 'gem install'" do - build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - abort "make installing activesupport-2.3.2 fail" - end - RUBY - end - - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rails" - - git "#{lib_path("activesupport")}" do - gem "activesupport" - end - G - - expect(err).to end_with(<<-M.strip) -An error occurred while installing activesupport (2.3.2), and Bundler cannot continue. - - -In Gemfile: - rails was resolved to 2.3.2, which depends on - actionmailer was resolved to 2.3.2, which depends on - activesupport - M - end - end - - it "prints out the hint for the remote source when available" do - build_repo2 do - build_gem "activesupport", "2.3.2" do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - abort "make installing activesupport-2.3.2 fail" - end - RUBY - end - end - - build_repo4 do - build_gem "a" - end - - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - source "#{file_uri_for(gem_repo2)}" do - gem "rails" - end - G - expect(err).to end_with(<<-M.strip) -An error occurred while installing activesupport (2.3.2), and Bundler cannot continue. -Make sure that `gem install activesupport -v '2.3.2' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling. In Gemfile: rails was resolved to 2.3.2, which depends on @@ -132,7 +39,7 @@ end it "removes the downloaded .gem" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo4)}" gem "a" G diff --git a/ruby/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/ruby/spec/bundler/install/gemfile/eval_gemfile_spec.rb index 7df94aaff..02283291b 100644 --- a/ruby/spec/bundler/install/gemfile/eval_gemfile_spec.rb +++ b/ruby/spec/bundler/install/gemfile/eval_gemfile_spec.rb @@ -11,12 +11,14 @@ context "eval-ed Gemfile points to an internal gemspec" do before do create_file "Gemfile-other", <<-G + source "#{file_uri_for(gem_repo1)}" gemspec :path => 'gems/gunks' G end it "installs the gemspec specified gem" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" eval_gemfile 'Gemfile-other' G expect(out).to include("Resolving dependencies") @@ -26,28 +28,65 @@ end end + context "eval-ed Gemfile points to an internal gemspec and uses a scoped source that duplicates the main Gemfile global source" do + before do + build_repo2 do + build_gem "rails", "6.1.3.2" + + build_gem "zip-zip", "0.3" + end + + create_file bundled_app("gems/Gemfile"), <<-G + source "#{file_uri_for(gem_repo2)}" + + gemspec :path => "\#{__dir__}/gunks" + + source "#{file_uri_for(gem_repo2)}" do + gem "zip-zip" + end + G + end + + it "installs and finds gems correctly" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "rails" + + eval_gemfile File.join(__dir__, "gems/Gemfile") + G + expect(out).to include("Resolving dependencies") + expect(out).to include("Bundle complete") + + expect(the_bundle).to include_gem "rails 6.1.3.2" + end + end + context "eval-ed Gemfile has relative-path gems" do before do - build_lib("a", :path => "gems/a") - create_file "nested/Gemfile-nested", <<-G + build_lib("a", :path => bundled_app("gems/a")) + create_file bundled_app("nested/Gemfile-nested"), <<-G + source "#{file_uri_for(gem_repo1)}" gem "a", :path => "../gems/a" G gemfile <<-G + source "#{file_uri_for(gem_repo1)}" eval_gemfile "nested/Gemfile-nested" G end it "installs the path gem" do - bundle! :install + bundle :install expect(the_bundle).to include_gem("a 1.0") end # Make sure that we are properly comparing path based gems between the # parsed lockfile and the evaluated gemfile. - it "bundles with --deployment" do - bundle! :install - bundle! :install, forgotten_command_line_options(:deployment => true) + it "bundles with deployment mode configured" do + bundle :install + bundle "config set --local deployment true" + bundle :install end end @@ -56,6 +95,7 @@ it "installs the gemspec specified gem" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" eval_gemfile 'other/Gemfile-other' gemspec :path => 'gems/gunks' G @@ -74,7 +114,7 @@ source "#{file_uri_for(gem_repo1)}" eval_gemfile "other/Gemfile" G - install_gemfile! "eval_gemfile File.expand_path('Gemfile-alt')" + install_gemfile "eval_gemfile File.expand_path('Gemfile-alt')" expect(the_bundle).to include_gem "rack 1.0.0" end diff --git a/ruby/spec/bundler/install/gemfile/gemspec_spec.rb b/ruby/spec/bundler/install/gemfile/gemspec_spec.rb index 26a623516..6bcfadab7 100644 --- a/ruby/spec/bundler/install/gemfile/gemspec_spec.rb +++ b/ruby/spec/bundler/install/gemfile/gemspec_spec.rb @@ -61,7 +61,7 @@ it "should raise if there are no gemspecs available" do build_lib("foo", :path => tmp.join("foo"), :gemspec => false) - install_gemfile(<<-G) + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gemspec :path => '#{tmp.join("foo")}' G @@ -73,7 +73,7 @@ s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby) end - install_gemfile(<<-G) + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gemspec :path => '#{tmp.join("foo")}' G @@ -117,21 +117,20 @@ build_lib("foo", :path => tmp.join("foo")) do |s| s.write("Gemfile", "source '#{file_uri_for(gem_repo1)}'\ngemspec") s.add_dependency "actionpack", "=2.3.2" - s.add_development_dependency "rake", "=12.3.2" + s.add_development_dependency "rake", "=13.0.1" end - Dir.chdir(tmp.join("foo")) do - bundle "install" - # This should really be able to rely on $stderr, but, it's not written - # right, so we can't. In fact, this is a bug negation test, and so it'll - # ghost pass in future, and will only catch a regression if the message - # doesn't change. Exit codes should be used correctly (they can be more - # than just 0 and 1). - output = bundle("install --deployment") - expect(output).not_to match(/You have added to the Gemfile/) - expect(output).not_to match(/You have deleted from the Gemfile/) - expect(output).not_to match(/install in deployment mode after changing/) - end + bundle "install", :dir => tmp.join("foo") + # This should really be able to rely on $stderr, but, it's not written + # right, so we can't. In fact, this is a bug negation test, and so it'll + # ghost pass in future, and will only catch a regression if the message + # doesn't change. Exit codes should be used correctly (they can be more + # than just 0 and 1). + bundle "config set --local deployment true" + output = bundle("install", :dir => tmp.join("foo")) + expect(output).not_to match(/You have added to the Gemfile/) + expect(output).not_to match(/You have deleted from the Gemfile/) + expect(output).not_to match(/install in deployment mode after changing/) end it "should match a lockfile without needing to re-resolve" do @@ -139,12 +138,12 @@ s.add_dependency "rack" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => '#{tmp.join("foo")}' G - bundle! "install", :verbose => true + bundle "install", :verbose => true message = "Found no changes, using resolution from the lockfile" expect(out.scan(message).size).to eq(1) @@ -158,32 +157,29 @@ s.add_development_dependency "thin" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => '#{tmp.join("foo")}' G - bundle! "install", :verbose => true + bundle "install", :verbose => true message = "Found no changes, using resolution from the lockfile" expect(out.scan(message).size).to eq(1) end - it "should match a lockfile on non-ruby platforms with a transitive platform dependency" do - simulate_platform java - simulate_ruby_engine "jruby" - + it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby do build_lib("foo", :path => tmp.join("foo")) do |s| s.add_dependency "platform_specific" end - system_gems "platform_specific-1.0-java", :path => :bundle_path, :keep_path => true + system_gems "platform_specific-1.0-java", :path => default_bundle_path - install_gemfile! <<-G + install_gemfile <<-G gemspec :path => '#{tmp.join("foo")}' G - bundle! "update --bundler", :verbose => true + bundle "update --bundler", :artifice => "compact_index", :verbose => true expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA" end @@ -193,7 +189,7 @@ s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'" end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false gemspec :path => '#{tmp.join("foo")}' G expect(last_command.stdboth).not_to include("ahh") @@ -201,7 +197,7 @@ it "allows the gemspec to activate other gems" do ENV["BUNDLE_PATH__SYSTEM"] = "true" - # see https://github.com/bundler/bundler/issues/5409 + # see https://github.com/rubygems/bundler/issues/5409 # # issue was caused by rubygems having an unresolved gem during a require, # so emulate that @@ -213,7 +209,8 @@ f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack/obama' }" end - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gemspec G @@ -251,7 +248,7 @@ build_gem "foo", "0.0.1" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "deps" gemspec :path => '#{tmp.join("foo")}', :name => 'foo' @@ -259,20 +256,21 @@ expect(the_bundle).to include_gems "foo 1.0.0" - run! "Gem.finish_resolve; puts 'WIN'" + run "Gem.finish_resolve; puts 'WIN'" expect(out).to eq("WIN") end - it "works with only_update_to_newer_versions" do + it "handles downgrades" do build_lib "omg", "2.0", :path => lib_path("omg") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gemspec :path => "#{lib_path("omg")}" G build_lib "omg", "1.0", :path => lib_path("omg") - bundle! :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" } + bundle :install expect(the_bundle).to include_gems "omg 1.0" end @@ -284,7 +282,7 @@ s.add_dependency "activesupport", ">= 1" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec G @@ -295,7 +293,8 @@ s.add_dependency "activesupport", ">= 1.0.1" end - bundle :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :raise_on_error => false expect(err).to include("changed") end @@ -333,6 +332,8 @@ let(:platform) { "ruby" } before do + skip "not installing for some reason" if Gem.win_platform? + build_lib("foo", :path => tmp.join("foo")) do |s| s.add_dependency "rack", "=1.0.0" end @@ -365,13 +366,11 @@ L end - context "using JRuby with explicit platform" do - let(:platform) { "java" } - + context "using JRuby with explicit platform", :jruby do before do create_file( - tmp.join("foo", "foo-#{platform}.gemspec"), - build_spec("foo", "1.0", platform) do + tmp.join("foo", "foo-java.gemspec"), + build_spec("foo", "1.0", "java") do dep "rack", "=1.0.0" @spec.authors = "authors" @spec.summary = "summary" @@ -380,27 +379,17 @@ end it "should install" do - simulate_ruby_engine "jruby" do - simulate_platform "java" do - results = bundle "install", :artifice => "endpoint" - expect(results).to include("Installing rack 1.0.0") - expect(the_bundle).to include_gems "rack 1.0.0" - end - end + results = bundle "install", :artifice => "endpoint" + expect(results).to include("Installing rack 1.0.0") + expect(the_bundle).to include_gems "rack 1.0.0" end end - context "using JRuby" do - let(:platform) { "java" } - + context "using JRuby", :jruby do it "should install" do - simulate_ruby_engine "jruby" do - simulate_platform "java" do - results = bundle "install", :artifice => "endpoint" - expect(results).to include("Installing rack 1.0.0") - expect(the_bundle).to include_gems "rack 1.0.0" - end - end + results = bundle "install", :artifice => "endpoint" + expect(results).to include("Installing rack 1.0.0") + expect(the_bundle).to include_gems "rack 1.0.0" end end @@ -425,7 +414,7 @@ end end - build_lib "foo", :path => "." do |s| + build_lib "foo", :path => bundled_app do |s| if platform_specific_type == :runtime s.add_runtime_dependency dependency elsif platform_specific_type == :development @@ -435,19 +424,21 @@ end end - %w[ruby jruby].each do |platform| - simulate_platform(platform) do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gemspec - G - end - end + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gemspec + G + + bundle "config set --local force_ruby_platform true" + bundle "install" + + simulate_new_machine + simulate_platform("jruby") { bundle "install" } end context "on ruby" do before do - simulate_platform("ruby") + bundle "config set --local force_ruby_platform true" bundle :install end @@ -558,9 +549,9 @@ end it "installs the ruby platform gemspec" do - simulate_platform "ruby" + bundle "config set --local force_ruby_platform true" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => '#{tmp.join("foo")}', :name => 'foo' G @@ -568,10 +559,11 @@ expect(the_bundle).to include_gems "foo 1.0.0", "rack 1.0.0" end - it "installs the ruby platform gemspec and skips dev deps with --without development" do - simulate_platform "ruby" + it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do + bundle "config set --local force_ruby_platform true" - install_gemfile! <<-G, forgotten_command_line_options(:without => "development") + bundle "config set --local without development" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => '#{tmp.join("foo")}', :name => 'foo' G @@ -580,4 +572,117 @@ expect(the_bundle).not_to include_gem "rack" end end + + context "with multiple platforms and resolving for more specific platforms" do + before do + build_lib("chef", :path => tmp.join("chef")) do |s| + s.version = "17.1.17" + s.write "chef-universal-mingw32.gemspec", build_spec("chef", "17.1.17", "universal-mingw32") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby + end + end + + it "does not remove the platform specific specs from the lockfile when updating" do + build_repo4 do + build_gem "win32-api", "1.5.3" do |s| + s.platform = "universal-mingw32" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gemspec :path => "../chef" + G + + initial_lockfile = <<~L + PATH + remote: ../chef + specs: + chef (17.1.17) + chef (17.1.17-universal-mingw32) + win32-api (~> 1.5.3) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + win32-api (1.5.3-universal-mingw32) + + PLATFORMS + ruby + x64-mingw32 + x86-mingw32 + + DEPENDENCIES + chef! + + BUNDLED WITH + #{Bundler::VERSION} + L + + lockfile initial_lockfile + + bundle "update" + + expect(lockfile).to eq initial_lockfile + end + end + + context "with multiple locked platforms" do + before do + build_lib("activeadmin", :path => tmp.join("activeadmin")) do |s| + s.version = "2.9.0" + s.add_dependency "railties", ">= 5.2", "< 6.2" + end + + build_repo4 do + build_gem "railties", "6.1.4" + + build_gem "jruby-openssl", "0.10.7" do |s| + s.platform = "java" + end + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gemspec :path => "../activeadmin" + gem "jruby-openssl", :platform => :jruby + G + + bundle "lock --add-platform java" + end + + it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do + expect(lockfile).to eq <<~L + PATH + remote: ../activeadmin + specs: + activeadmin (2.9.0) + railties (>= 5.2, < 6.2) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + jruby-openssl (0.10.7-java) + railties (6.1.4) + + PLATFORMS + #{lockfile_platforms_for(["java"] + local_platforms)} + + DEPENDENCIES + activeadmin! + jruby-openssl + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemspec = tmp.join("activeadmin/activeadmin.gemspec") + File.write(gemspec, File.read(gemspec).sub(">= 5.2", ">= 6.0")) + + previous_lockfile = lockfile + + bundle "install --local" + + expect(lockfile).to eq(previous_lockfile.sub(">= 5.2", ">= 6.0")) + end + end end diff --git a/ruby/spec/bundler/install/gemfile/git_spec.rb b/ruby/spec/bundler/install/gemfile/git_spec.rb index 00f8e9662..365a84f39 100644 --- a/ruby/spec/bundler/install/gemfile/git_spec.rb +++ b/ruby/spec/bundler/install/gemfile/git_spec.rb @@ -30,11 +30,15 @@ expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes :size => 1 end - it "caches the git repo globally" do + it "caches the git repo globally and properly uses the cached repo on the next invocation" do simulate_new_machine - bundle! "config set global_gem_cache true" - bundle! :install + bundle "config set global_gem_cache true" + bundle :install expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes :size => 1 + + bundle "install --verbose" + expect(err).to be_empty + expect(out).to include("Using foo 1.0 from #{lib_path("foo")}") end it "caches the evaluated gemspec" do @@ -57,22 +61,19 @@ it "does not update the git source implicitly" do update_git "foo" - in_app_root2 do - install_gemfile bundled_app2("Gemfile"), <<-G - git "#{lib_path("foo-1.0")}" do - gem 'foo' - end - G - end + install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2 + source "#{file_uri_for(gem_repo1)}" + git "#{lib_path("foo-1.0")}" do + gem 'foo' + end + G - in_app_root do - run <<-RUBY - require 'foo' - puts "fail" if defined?(FOO_PREV_REF) - RUBY + run <<-RUBY + require 'foo' + puts "fail" if defined?(FOO_PREV_REF) + RUBY - expect(out).to be_empty - end + expect(out).to be_empty end it "sets up git gem executables on the path" do @@ -83,32 +84,30 @@ it "complains if pinned specs don't exist in the git repo" do build_git "foo" - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}" G - expect(err).to include("The source contains 'foo' at: 1.0") + expect(err).to include("The source contains the following gems matching 'foo':\n * foo-1.0") end - it "complains with version and platform if pinned specs don't exist in the git repo" do - simulate_platform "java" - + it "complains with version and platform if pinned specs don't exist in the git repo", :jruby do build_git "only_java" do |s| s.platform = "java" end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" platforms :jruby do gem "only_java", "1.2", :git => "#{lib_path("only_java-1.0-java")}" end G - expect(err).to include("The source contains 'only_java' at: 1.0 java") + expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java") end - it "complains with multiple versions and platforms if pinned specs don't exist in the git repo" do - simulate_platform "java" - + it "complains with multiple versions and platforms if pinned specs don't exist in the git repo", :jruby do build_git "only_java", "1.0" do |s| s.platform = "java" end @@ -118,30 +117,33 @@ s.write "only_java1-0.gemspec", File.read("#{lib_path("only_java-1.0-java")}/only_java.gemspec") end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" platforms :jruby do gem "only_java", "1.2", :git => "#{lib_path("only_java-1.1-java")}" end G - expect(err).to include("The source contains 'only_java' at: 1.0 java, 1.1 java") + expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java\n * only_java-1.1-java") end it "still works after moving the application directory" do - bundle "install --path vendor/bundle" + bundle "config set --local path vendor/bundle" + bundle "install" + FileUtils.mv bundled_app, tmp("bundled_app.bck") - Dir.chdir tmp("bundled_app.bck") - expect(the_bundle).to include_gems "foo 1.0" + expect(the_bundle).to include_gems "foo 1.0", :dir => tmp("bundled_app.bck") end it "can still install after moving the application directory" do - bundle "install --path vendor/bundle" + bundle "config set --local path vendor/bundle" + bundle "install" + FileUtils.mv bundled_app, tmp("bundled_app.bck") update_git "foo", "1.1", :path => lib_path("foo-1.0") - Dir.chdir tmp("bundled_app.bck") gemfile tmp("bundled_app.bck/Gemfile"), <<-G source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do @@ -151,9 +153,9 @@ gem "rack", "1.0" G - bundle "update foo" + bundle "update foo", :dir => tmp("bundled_app.bck") - expect(the_bundle).to include_gems "foo 1.1", "rack 1.0" + expect(the_bundle).to include_gems "foo 1.1", "rack 1.0", :dir => tmp("bundled_app.bck") end end @@ -185,6 +187,7 @@ it "works" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :ref => "#{@revision}" do gem "foo" end @@ -200,6 +203,7 @@ it "works when the revision is a symbol" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :ref => #{@revision.to_sym.inspect} do gem "foo" end @@ -220,23 +224,22 @@ s.write("lib/foo.rb", "raise 'FAIL'") end - Dir.chdir(lib_path("foo-1.0")) do - `git update-ref -m "Bundler Spec!" refs/bundler/1 master~1` - end + sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0")) # want to ensure we don't fallback to HEAD update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s| - s.write("lib/foo.rb", "raise 'FAIL'") + s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'") end - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do gem "foo" end G expect(err).to be_empty - run! <<-RUBY + run <<-RUBY require 'foo' puts "WIN" if defined?(FOO) RUBY @@ -245,7 +248,8 @@ end it "works when the revision is a non-head ref and it was previously downloaded" do - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem "foo" end @@ -256,23 +260,22 @@ s.write("lib/foo.rb", "raise 'FAIL'") end - Dir.chdir(lib_path("foo-1.0")) do - `git update-ref -m "Bundler Spec!" refs/bundler/1 master~1` - end + sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0")) # want to ensure we don't fallback to HEAD update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s| - s.write("lib/foo.rb", "raise 'FAIL'") + s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'") end - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do gem "foo" end G expect(err).to be_empty - run! <<-RUBY + run <<-RUBY require 'foo' puts "WIN" if defined?(FOO) RUBY @@ -281,24 +284,21 @@ end it "does not download random non-head refs" do - Dir.chdir(lib_path("foo-1.0")) do - sys_exec!('git update-ref -m "Bundler Spec!" refs/bundler/1 master~1') - end + sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0")) - bundle! "config set global_gem_cache true" + bundle "config set global_gem_cache true" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem "foo" end G # ensure we also git fetch after cloning - bundle! :update, :all => true + bundle :update, :all => true - Dir.chdir(Dir[home(".bundle/cache/git/foo-*")].first) do - sys_exec("git ls-remote .") - end + sys_exec("git ls-remote .", :dir => Dir[home(".bundle/cache/git/foo-*")].first) expect(out).not_to include("refs/bundler/1") end @@ -307,12 +307,12 @@ describe "when specifying a branch" do let(:branch) { "branch" } let(:repo) { build_git("foo").path } - before(:each) do - update_git("foo", :path => repo, :branch => branch) - end it "works" do + update_git("foo", :path => repo, :branch => branch) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :branch => #{branch.dump} do gem "foo" end @@ -324,7 +324,12 @@ context "when the branch starts with a `#`" do let(:branch) { "#149/redirect-url-fragment" } it "works" do + skip "git does not accept this" if Gem.win_platform? + + update_git("foo", :path => repo, :branch => branch) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :branch => #{branch.dump} do gem "foo" end @@ -337,7 +342,12 @@ context "when the branch includes quotes" do let(:branch) { %('") } it "works" do + skip "git does not accept this" if Gem.win_platform? + + update_git("foo", :path => repo, :branch => branch) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :branch => #{branch.dump} do gem "foo" end @@ -351,12 +361,12 @@ describe "when specifying a tag" do let(:tag) { "tag" } let(:repo) { build_git("foo").path } - before(:each) do - update_git("foo", :path => repo, :tag => tag) - end it "works" do + update_git("foo", :path => repo, :tag => tag) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :tag => #{tag.dump} do gem "foo" end @@ -368,7 +378,12 @@ context "when the tag starts with a `#`" do let(:tag) { "#149/redirect-url-fragment" } it "works" do + skip "git does not accept this" if Gem.win_platform? + + update_git("foo", :path => repo, :tag => tag) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :tag => #{tag.dump} do gem "foo" end @@ -381,7 +396,12 @@ context "when the tag includes quotes" do let(:tag) { %('") } it "works" do + skip "git does not accept this" if Gem.win_platform? + + update_git("foo", :path => repo, :tag => tag) + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{repo}", :tag => #{tag.dump} do gem "foo" end @@ -394,9 +414,6 @@ describe "when specifying local override" do it "uses the local repository instead of checking a new one out" do - # We don't generate it because we actually don't need it - # build_git "rack", "0.8" - build_git "rack", "0.8", :path => lib_path("local-rack") do |s| s.write "lib/rack.rb", "puts :LOCAL" end @@ -406,8 +423,8 @@ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" G - bundle! %(config set local.rack #{lib_path("local-rack")}) - bundle! :install + bundle %(config set local.rack #{lib_path("local-rack")}) + bundle :install run "require 'rack'" expect(out).to eq("LOCAL") @@ -442,14 +459,14 @@ s.write "lib/rack.rb", "puts :LOCAL" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" G - bundle! %(config set local.rack #{lib_path("local-rack")}) - bundle! :install - run! "require 'rack'" + bundle %(config set local.rack #{lib_path("local-rack")}) + bundle :install + run "require 'rack'" expect(out).to eq("LOCAL") end @@ -463,7 +480,7 @@ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" G - lockfile0 = File.read(bundled_app("Gemfile.lock")) + lockfile0 = File.read(bundled_app_lock) FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack")) update_git "rack", "0.8", :path => lib_path("local-rack") do |s| @@ -473,7 +490,7 @@ bundle %(config set local.rack #{lib_path("local-rack")}) run "require 'rack'" - lockfile1 = File.read(bundled_app("Gemfile.lock")) + lockfile1 = File.read(bundled_app_lock) expect(lockfile1).not_to eq(lockfile0) end @@ -485,7 +502,7 @@ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" G - lockfile0 = File.read(bundled_app("Gemfile.lock")) + lockfile0 = File.read(bundled_app_lock) FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack")) update_git "rack", "0.8", :path => lib_path("local-rack") @@ -493,7 +510,7 @@ bundle %(config set local.rack #{lib_path("local-rack")}) bundle :install - lockfile1 = File.read(bundled_app("Gemfile.lock")) + lockfile1 = File.read(bundled_app_lock) expect(lockfile1).not_to eq(lockfile0) end @@ -506,7 +523,7 @@ G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/) solution = "config unset local.rack" @@ -528,7 +545,7 @@ G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/Cannot use local override for rack-0.8 at #{Regexp.escape(lib_path('local-rack').to_s)} because :branch is not specified in Gemfile/) solution = "config unset local.rack" @@ -570,7 +587,7 @@ G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/is using branch another but Gemfile specifies master/) end @@ -587,9 +604,27 @@ G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/The Gemfile lock is pointing to revision \w+/) end + + it "does not explode on invalid revision on install" do + build_git "rack", "0.8" + + build_git "rack", "0.8", :path => lib_path("local-rack") do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" + G + + bundle %(config set local.rack #{lib_path("local-rack")}) + bundle %(config set disable_local_revision_check true) + bundle :install + expect(out).to match(/Bundle complete!/) + end end describe "specified inline" do @@ -679,6 +714,7 @@ build_lib "hi2u", :path => lib_path("hi2u") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path("hi2u")}" do gem "omg" gem "hi2u" @@ -695,6 +731,7 @@ update_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{@revision}" G @@ -759,6 +796,7 @@ build_git "foo", "1.0" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}" G @@ -780,10 +818,11 @@ it "catches git errors and spits out useful output" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.0", :git => "omgomg" G - bundle :install + bundle :install, :raise_on_error => false expect(err).to include("Git error:") expect(err).to include("fatal") @@ -794,6 +833,7 @@ build_git "foo", :path => lib_path("foo space-1.0") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo space-1.0")}" G @@ -804,6 +844,7 @@ build_git "forced", "1.0" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("forced-1.0")}" do gem 'forced' end @@ -817,9 +858,7 @@ bundle "update", :all => true expect(the_bundle).to include_gems "forced 1.1" - Dir.chdir(lib_path("forced-1.0")) do - `git reset --hard HEAD^` - end + sys_exec("git reset --hard HEAD^", :dir => lib_path("forced-1.0")) bundle "update", :all => true expect(the_bundle).to include_gems "forced 1.0" @@ -830,12 +869,11 @@ build_git "has_submodule", "1.0" do |s| s.add_dependency "submodule" end - Dir.chdir(lib_path("has_submodule-1.0")) do - sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0" - `git commit -m "submodulator"` - end + sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0") + sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0") - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("has_submodule-1.0")}" do gem "has_submodule" end @@ -850,12 +888,11 @@ build_git "has_submodule", "1.0" do |s| s.add_dependency "submodule" end - Dir.chdir(lib_path("has_submodule-1.0")) do - sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0" - `git commit -m "submodulator"` - end + sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0") + sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("has_submodule-1.0")}", :submodules => true do gem "has_submodule" end @@ -864,10 +901,30 @@ expect(the_bundle).to include_gems "has_submodule 1.0" end + it "does not warn when deiniting submodules" do + build_git "submodule", "1.0" + build_git "has_submodule", "1.0" + + sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0") + sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0") + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + git "#{lib_path("has_submodule-1.0")}" do + gem "has_submodule" + end + G + expect(err).to be_empty + + expect(the_bundle).to include_gems "has_submodule 1.0" + expect(the_bundle).to_not include_gems "submodule 1.0" + end + it "handles implicit updates when modifying the source info" do git = build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem "foo" end @@ -877,6 +934,7 @@ update_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :ref => "#{git.ref_for("HEAD^")}" do gem "foo" end @@ -894,6 +952,7 @@ build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -907,12 +966,12 @@ build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G bundle "install" bundle "install" - expect(exitstatus).to eq(0) if exitstatus end it "prints a friendly error if a file blocks the git repo" do @@ -921,11 +980,12 @@ FileUtils.mkdir_p(default_bundle_path) FileUtils.touch(default_bundle_path("bundler")) - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G - expect(exitstatus).to_not eq(0) if exitstatus + expect(exitstatus).to_not eq(0) expect(err).to include("Bundler could not install a gem because it " \ "needs to create a directory, but a file exists " \ "- #{default_bundle_path("bundler")}") @@ -939,11 +999,12 @@ build_git "bar", :path => lib_path("nested") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("nested")}" gem "bar", :git => "#{lib_path("nested")}" G - expect(File.read(bundled_app("Gemfile.lock")).scan("GIT").size).to eq(1) + expect(File.read(bundled_app_lock).scan("GIT").size).to eq(1) end describe "switching sources" do @@ -996,6 +1057,7 @@ build_git "valim" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "valim", :git => "#{file_uri_for(lib_path("valim-1.0"))}" G @@ -1003,8 +1065,8 @@ update_git "valim" new_revision = revision_for(lib_path("valim-1.0")) - old_lockfile = File.read(bundled_app("Gemfile.lock")) - lockfile(bundled_app("Gemfile.lock"), old_lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}")) + old_lockfile = File.read(bundled_app_lock) + lockfile(bundled_app_lock, old_lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}")) bundle "install" @@ -1021,18 +1083,20 @@ revision = revision_for(lib_path("foo-1.0")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :ref => "#{revision}" G expect(out).to_not match(/Revision.*does not exist/) - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :ref => "deadbeef" G expect(err).to include("Revision deadbeef does not exist in the repository") end end - describe "bundle install --deployment with git sources" do + describe "bundle install with deployment mode configured and git sources" do it "works" do build_git "valim", :path => lib_path("valim") @@ -1043,7 +1107,8 @@ simulate_new_machine - bundle! :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install end end @@ -1051,6 +1116,7 @@ it "runs pre-install hooks" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -1070,6 +1136,7 @@ it "runs post-install hooks" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -1089,6 +1156,7 @@ it "complains if the install hook fails" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -1100,8 +1168,7 @@ H end - bundle :install, - :requires => [lib_path("install_hooks.rb")] + bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false expect(err).to include("failed for foo-1.0") end end @@ -1133,7 +1200,7 @@ R expect(out).to eq("YES") - run! <<-R + run <<-R puts $:.grep(/ext/) R expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s) @@ -1150,16 +1217,15 @@ end 2.times do |i| - Dir.chdir(git_reader.path) do - File.open("ext/foo.c", "w") do |file| - file.write <<-C - #include "ruby.h" - VALUE foo() { return INT2FIX(#{i}); } - void Init_foo() { rb_define_global_function("foo", &foo, 0); } - C - end - `git commit -m "commit for iteration #{i}" ext/foo.c` + File.open(git_reader.path.join("ext/foo.c"), "w") do |file| + file.write <<-C + #include "ruby.h" + VALUE foo() { return INT2FIX(#{i}); } + void Init_foo() { rb_define_global_function("foo", &foo, 0); } + C end + sys_exec("git commit -m \"commit for iteration #{i}\" ext/foo.c", :dir => git_reader.path) + git_commit_sha = git_reader.ref_for("HEAD") install_gemfile <<-G @@ -1187,7 +1253,7 @@ RUBY end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -1222,7 +1288,7 @@ gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1235,7 +1301,7 @@ gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1264,7 +1330,7 @@ gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1278,7 +1344,7 @@ gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1306,14 +1372,15 @@ gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R require 'foo' puts FOO R + installed_time = out + update_git("foo", :branch => "branch2") - installed_time = out expect(installed_time).to match(/\A\d+\.\d+\z/) install_gemfile <<-G @@ -1321,7 +1388,7 @@ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "branch2" G - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1330,9 +1397,9 @@ installed_time = out update_git("foo") - bundle! "update foo" + bundle "update foo" - run! <<-R + run <<-R require 'foo' puts FOO R @@ -1356,24 +1423,61 @@ end G - expect(exitstatus).to eq(0) if exitstatus expect(ENV["GIT_DIR"]).to eq("bar") expect(ENV["GIT_WORK_TREE"]).to eq("bar") end end describe "without git installed" do - it "prints a better error message" do + it "prints a better error message when installing" do + build_git "foo" + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + + gem "rake", git: "https://github.com/ruby/rake" + G + + lockfile <<-L + GIT + remote: https://github.com/ruby/rake + revision: 5c60da8644a9e4f655e819252e3b6ca77f42b7af + specs: + rake (13.0.6) + + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rake! + + BUNDLED WITH + #{Bundler::VERSION} + L + + with_path_as("") do + bundle "install", :raise_on_error => false + end + expect(err). + to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git") + end + + it "prints a better error message when updating" do build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem 'foo' end G with_path_as("") do - bundle "update", :all => true + bundle "update", :all => true, :raise_on_error => false end expect(err). to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git") @@ -1383,6 +1487,7 @@ build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem 'foo' end @@ -1391,14 +1496,14 @@ bundle :cache simulate_new_machine - bundle! "install", :env => { "PATH" => "" } + bundle "install", :env => { "PATH" => "" } expect(out).to_not include("You need to install git to be able to use gems from git repositories.") end end describe "when the git source is overridden with a local git repo" do before do - bundle! "config set --global local.foo #{lib_path("foo")}" + bundle "config set --global local.foo #{lib_path("foo")}" end describe "and git output is colorized" do @@ -1412,6 +1517,7 @@ build_git "foo", "1.0", :path => lib_path("foo") gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo")}", :branch => "master" G @@ -1426,7 +1532,8 @@ let(:credentials) { "user1:password1" } it "does not display the password" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" git "https://#{credentials}@github.com/company/private-repo" do gem "foo" end @@ -1441,7 +1548,8 @@ let(:credentials) { "oauth_token" } it "displays the oauth scheme but not the oauth token" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" git "https://#{credentials}:x-oauth-basic@github.com/company/private-repo" do gem "foo" end diff --git a/ruby/spec/bundler/install/gemfile/groups_spec.rb b/ruby/spec/bundler/install/gemfile/groups_spec.rb index 63be1a4e4..734e012e8 100644 --- a/ruby/spec/bundler/install/gemfile/groups_spec.rb +++ b/ruby/spec/bundler/install/gemfile/groups_spec.rb @@ -70,7 +70,7 @@ end end - describe "installing --without" do + describe "without option" do describe "with gems assigned to a single group" do before :each do gemfile <<-G @@ -86,30 +86,50 @@ end it "installs gems in the default group" do - bundle! :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install + expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default] + end + + it "respects global `without` configuration, but does not save it locally" do + bundle "config set --global without emo" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default] + bundle "config list" + expect(out).not_to include("Set for your local app (#{bundled_app(".bundle/config")}): [:emo]") + expect(out).to include("Set for the current user (#{home(".bundle/config")}): [:emo]") + end + + it "allows running application where groups where configured by a different user", :bundler => "< 3" do + bundle "config set without emo" + bundle :install + bundle "exec ruby -e 'puts 42'", :env => { "BUNDLE_USER_HOME" => tmp("new_home").to_s } + expect(out).to include("42") end it "does not install gems from the excluded group" do - bundle :install, :without => "emo" + bundle "config set --local without emo" + bundle :install expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default] end - it "does not install gems from the previously excluded group" do - bundle :install, forgotten_command_line_options(:without => "emo") + it "remembers previous exclusion with `--without`", :bundler => "< 3" do + bundle "install --without emo" expect(the_bundle).not_to include_gems "activesupport 2.3.5" bundle :install expect(the_bundle).not_to include_gems "activesupport 2.3.5" end it "does not say it installed gems from the excluded group" do - bundle! :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install expect(out).not_to include("activesupport") end it "allows Bundler.setup for specific groups" do - bundle :install, forgotten_command_line_options(:without => "emo") - run!("require 'rack'; puts RACK", :default) + bundle "config set --local without emo" + bundle :install + run("require 'rack'; puts RACK", :default) expect(out).to eq("1.0.0") end @@ -122,20 +142,11 @@ end G - bundle :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => [:default] end - it "still works on a different machine and excludes gems" do - bundle :install, forgotten_command_line_options(:without => "emo") - - simulate_new_machine - bundle :install, forgotten_command_line_options(:without => "emo") - - expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default] - expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default] - end - it "still works when BUNDLE_WITHOUT is set" do ENV["BUNDLE_WITHOUT"] = "emo" @@ -148,15 +159,15 @@ ENV["BUNDLE_WITHOUT"] = nil end - it "clears without when passed an empty list" do - bundle :install, forgotten_command_line_options(:without => "emo") + it "clears --without when passed an empty list", :bundler => "< 3" do + bundle "install --without emo" - bundle :install, forgotten_command_line_options(:without => "") + bundle "install --without ''" expect(the_bundle).to include_gems "activesupport 2.3.5" end - it "doesn't clear without when nothing is passed" do - bundle :install, forgotten_command_line_options(:without => "emo") + it "doesn't clear without when nothing is passed", :bundler => "< 3" do + bundle "install --without emo" bundle :install expect(the_bundle).not_to include_gems "activesupport 2.3.5" @@ -167,45 +178,46 @@ expect(the_bundle).not_to include_gems "thin 1.0" end - it "does install gems from the optional group when requested" do - bundle :install, forgotten_command_line_options(:with => "debugging") + it "installs gems from the optional group when requested" do + bundle "config set --local with debugging" + bundle :install expect(the_bundle).to include_gems "thin 1.0" end - it "does install gems from the previously requested group" do - bundle :install, forgotten_command_line_options(:with => "debugging") + it "installs gems from the previously requested group", :bundler => "< 3" do + bundle "install --with debugging" expect(the_bundle).to include_gems "thin 1.0" bundle :install expect(the_bundle).to include_gems "thin 1.0" end - it "does install gems from the optional groups requested with BUNDLE_WITH" do + it "installs gems from the optional groups requested with BUNDLE_WITH" do ENV["BUNDLE_WITH"] = "debugging" bundle :install expect(the_bundle).to include_gems "thin 1.0" ENV["BUNDLE_WITH"] = nil end - it "clears with when passed an empty list" do - bundle :install, forgotten_command_line_options(:with => "debugging") - bundle :install, forgotten_command_line_options(:with => "") + it "clears --with when passed an empty list", :bundler => "< 3" do + bundle "install --with debugging" + bundle "install --with ''" expect(the_bundle).not_to include_gems "thin 1.0" end - it "does remove groups from without when passed at --with", :bundler => "< 3" do - bundle :install, forgotten_command_line_options(:without => "emo") - bundle :install, forgotten_command_line_options(:with => "emo") + it "removes groups from without when passed at --with", :bundler => "< 3" do + bundle "config set --local without emo" + bundle "install --with emo" expect(the_bundle).to include_gems "activesupport 2.3.5" end - it "does remove groups from with when passed at --without", :bundler => "< 3" do - bundle :install, forgotten_command_line_options(:with => "debugging") - bundle :install, forgotten_command_line_options(:without => "debugging") + it "removes groups from with when passed at --without", :bundler => "< 3" do + bundle "config set --local with debugging" + bundle "install --without debugging", :raise_on_error => false expect(the_bundle).not_to include_gem "thin 1.0" end it "errors out when passing a group to with and without via CLI flags", :bundler => "< 3" do - bundle :install, forgotten_command_line_options(:with => "emo debugging", :without => "emo") + bundle "install --with emo debugging --without emo", :raise_on_error => false expect(last_command).to be_failure expect(err).to include("The offending groups are: emo") end @@ -213,29 +225,31 @@ it "allows the BUNDLE_WITH setting to override BUNDLE_WITHOUT" do ENV["BUNDLE_WITH"] = "debugging" - bundle! :install + bundle :install expect(the_bundle).to include_gem "thin 1.0" ENV["BUNDLE_WITHOUT"] = "debugging" expect(the_bundle).to include_gem "thin 1.0" - bundle! :install + bundle :install expect(the_bundle).to include_gem "thin 1.0" end - it "can add and remove a group at the same time" do - bundle :install, forgotten_command_line_options(:with => "debugging", :without => "emo") + it "can add and remove a group at the same time", :bundler => "< 3" do + bundle "install --with debugging --without emo" expect(the_bundle).to include_gems "thin 1.0" expect(the_bundle).not_to include_gems "activesupport 2.3.5" end - it "does have no effect when listing a not optional group in with" do - bundle :install, forgotten_command_line_options(:with => "emo") + it "has no effect when listing a not optional group in with" do + bundle "config set --local with emo" + bundle :install expect(the_bundle).to include_gems "activesupport 2.3.5" end - it "does have no effect when listing an optional group in without" do - bundle :install, forgotten_command_line_options(:without => "debugging") + it "has no effect when listing an optional group in without" do + bundle "config set --local without debugging" + bundle :install expect(the_bundle).not_to include_gems "thin 1.0" end end @@ -252,12 +266,14 @@ end it "installs gems in the default group" do - bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster") + bundle "config set --local without emo lolercoaster" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0" end it "installs the gem if any of its groups are installed" do - bundle! :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5" end @@ -277,23 +293,21 @@ G end - it "installs the gem w/ option --without emo" do - bundle :install, forgotten_command_line_options(:without => "emo") + it "installs the gem unless all groups are excluded" do + bundle "config set --local without emo" + bundle :install expect(the_bundle).to include_gems "activesupport 2.3.5" - end - it "installs the gem w/ option --without lolercoaster" do - bundle :install, forgotten_command_line_options(:without => "lolercoaster") + bundle "config set --local without lolercoaster" + bundle :install expect(the_bundle).to include_gems "activesupport 2.3.5" - end - it "does not install the gem w/ option --without emo lolercoaster" do - bundle :install, forgotten_command_line_options(:without => "emo lolercoaster") + bundle "config set --local without emo lolercoaster" + bundle :install expect(the_bundle).not_to include_gems "activesupport 2.3.5" - end - it "does not install the gem w/ option --without 'emo lolercoaster'" do - bundle :install, forgotten_command_line_options(:without => "'emo lolercoaster'") + bundle "config set --local without 'emo lolercoaster'" + bundle :install expect(the_bundle).not_to include_gems "activesupport 2.3.5" end end @@ -313,12 +327,14 @@ end it "installs gems in the default group" do - bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster") + bundle "config set --local without emo lolercoaster" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0" end it "installs the gem if any of its groups are installed" do - bundle! :install, forgotten_command_line_options(:without => "emo") + bundle "config set --local without emo" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5" end end @@ -333,7 +349,7 @@ G ruby <<-R - require "#{lib_dir}/bundler" + require "#{entrypoint}" Bundler.setup :default Bundler.require :default puts RACK @@ -349,19 +365,21 @@ end end - describe "when locked and installed with --without" do + describe "when locked and installed with `without` option" do before(:each) do build_repo2 - system_gems "rack-0.9.1" do - install_gemfile <<-G, forgotten_command_line_options(:without => "rack") - source "#{file_uri_for(gem_repo2)}" - gem "rack" - group :rack do - gem "rack_middleware" - end - G - end + system_gems "rack-0.9.1" + + bundle "config set --local without rack" + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "rack" + + group :rack do + gem "rack_middleware" + end + G end it "uses the correct versions even if --without was used on the original" do @@ -377,7 +395,8 @@ it "does not hit the remote a second time" do FileUtils.rm_rf gem_repo2 - bundle! :install, forgotten_command_line_options(:without => "rack").merge(:verbose => true) + bundle "config set --local without rack" + bundle :install, :verbose => true expect(last_command.stdboth).not_to match(/fetching/i) end end diff --git a/ruby/spec/bundler/install/gemfile/install_if.rb b/ruby/spec/bundler/install/gemfile/install_if.rb deleted file mode 100644 index bfdd8fbae..000000000 --- a/ruby/spec/bundler/install/gemfile/install_if.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -describe "bundle install with install_if conditionals" do - it "follows the install_if DSL" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - install_if(lambda { true }) do - gem "activesupport", "2.3.5" - end - gem "thin", :install_if => false - install_if(lambda { false }) do - gem "foo" - end - gem "rack" - G - - expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5") - expect(the_bundle).not_to include_gems("thin") - expect(the_bundle).not_to include_gems("foo") - - lockfile_should_be <<-L - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - activesupport (2.3.5) - foo (1.0) - rack (1.0.0) - thin (1.0) - rack - - PLATFORMS - ruby - - DEPENDENCIES - activesupport (= 2.3.5) - foo - rack - thin - - BUNDLED WITH - #{Bundler::VERSION} - L - end -end diff --git a/ruby/spec/bundler/install/gemfile/install_if_spec.rb b/ruby/spec/bundler/install/gemfile/install_if_spec.rb new file mode 100644 index 000000000..3d2d15a69 --- /dev/null +++ b/ruby/spec/bundler/install/gemfile/install_if_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +RSpec.describe "bundle install with install_if conditionals" do + it "follows the install_if DSL" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + install_if(lambda { true }) do + gem "activesupport", "2.3.5" + end + gem "thin", :install_if => false + install_if(lambda { false }) do + gem "foo" + end + gem "rack" + G + + expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5") + expect(the_bundle).not_to include_gems("thin") + expect(the_bundle).not_to include_gems("foo") + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + activesupport (2.3.5) + foo (1.0) + rack (1.0.0) + thin (1.0) + rack + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + activesupport (= 2.3.5) + foo + rack + thin + + BUNDLED WITH + #{Bundler::VERSION} + L + end +end diff --git a/ruby/spec/bundler/install/gemfile/lockfile_spec.rb b/ruby/spec/bundler/install/gemfile/lockfile_spec.rb index b9545b91c..313e99d0b 100644 --- a/ruby/spec/bundler/install/gemfile/lockfile_spec.rb +++ b/ruby/spec/bundler/install/gemfile/lockfile_spec.rb @@ -16,12 +16,12 @@ context "with plugins disabled" do before do - bundle! "config set plugins false" + bundle "config set plugins false" subject end it "does not evaluate the gemfile twice" do - bundle! :install + bundle :install with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" } @@ -31,10 +31,10 @@ end context "when the gem is not installed" do - before { FileUtils.rm_rf ".bundle" } + before { FileUtils.rm_rf bundled_app(".bundle") } it "does not evaluate the gemfile twice" do - bundle! :install + bundle :install with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" } diff --git a/ruby/spec/bundler/install/gemfile/path_spec.rb b/ruby/spec/bundler/install/gemfile/path_spec.rb index e53636da0..bea7c11de 100644 --- a/ruby/spec/bundler/install/gemfile/path_spec.rb +++ b/ruby/spec/bundler/install/gemfile/path_spec.rb @@ -16,6 +16,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path("foo-1.0")}" do gem 'foo' end @@ -28,6 +29,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "#{lib_path("foo-1.0")}" G @@ -37,9 +39,10 @@ it "supports relative paths" do build_lib "foo" - relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new(Dir.pwd)) + relative_path = lib_path("foo-1.0").relative_path_from(bundled_app) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "#{relative_path}" G @@ -52,6 +55,7 @@ relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("~").expand_path) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "~/#{relative_path}" G @@ -59,11 +63,14 @@ end it "expands paths raise error with not existing user's home dir" do + skip "problems with ~ expansion" if Gem.win_platform? + build_lib "foo" username = "some_unexisting_user" relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("/home/#{username}").expand_path) - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "~#{username}/#{relative_path}" G expect(err).to match("There was an error while trying to use the path `~#{username}/#{relative_path}`.") @@ -74,13 +81,11 @@ build_lib "foo", :path => bundled_app("foo-1.0") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "./foo-1.0" G - bundled_app("subdir").mkpath - Dir.chdir(bundled_app("subdir")) do - expect(the_bundle).to include_gems("foo 1.0") - end + expect(the_bundle).to include_gems("foo 1.0", :dir => bundled_app("subdir").mkpath) end it "sorts paths consistently on install and update when they start with ./" do @@ -88,6 +93,7 @@ build_lib "aaa", :path => lib_path("demo/aaa") gemfile = <<-G + source "#{file_uri_for(gem_repo1)}" gemspec gem "aaa", :path => "./aaa" G @@ -106,6 +112,7 @@ aaa (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -119,23 +126,22 @@ #{Bundler::VERSION} L - Dir.chdir(lib_path("demo")) do - bundle :install - expect(lib_path("demo/Gemfile.lock")).to have_lockfile(lockfile) - bundle :update, :all => true - expect(lib_path("demo/Gemfile.lock")).to have_lockfile(lockfile) - end + bundle :install, :dir => lib_path("demo") + expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile) + bundle :update, :all => true, :dir => lib_path("demo") + expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile) end it "expands paths when comparing locked paths to Gemfile paths" do build_lib "foo", :path => bundled_app("foo-1.0") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__) G - bundle! :install, forgotten_command_line_options(:frozen => true) - expect(exitstatus).to eq(0) if exitstatus + bundle "config set --local frozen true" + bundle :install end it "installs dependencies from the path even if a newer gem is available elsewhere" do @@ -170,22 +176,90 @@ build_lib "foo", "1.0.0", :path => lib_path("omg/foo") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "omg", :path => "#{lib_path("omg")}" G expect(the_bundle).to include_gems "foo 1.0" end - it "works with only_update_to_newer_versions" do + it "works when using prereleases of 0.0.0" do + build_lib "foo", "0.0.0.dev", :path => lib_path("foo") + + gemfile <<~G + source "#{file_uri_for(gem_repo1)}" + gem "foo", :path => "#{lib_path("foo")}" + G + + lockfile <<~L + PATH + remote: #{lib_path("foo")} + specs: + foo (0.0.0.dev) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle :install + + expect(the_bundle).to include_gems "foo 0.0.0.dev" + end + + it "works when using uppercase prereleases of 0.0.0" do + build_lib "foo", "0.0.0.SNAPSHOT", :path => lib_path("foo") + + gemfile <<~G + source "#{file_uri_for(gem_repo1)}" + gem "foo", :path => "#{lib_path("foo")}" + G + + lockfile <<~L + PATH + remote: #{lib_path("foo")} + specs: + foo (0.0.0.SNAPSHOT) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle :install + + expect(the_bundle).to include_gems "foo 0.0.0.SNAPSHOT" + end + + it "handles downgrades" do build_lib "omg", "2.0", :path => lib_path("omg") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "omg", :path => "#{lib_path("omg")}" G build_lib "omg", "1.0", :path => lib_path("omg") - bundle! :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" } + bundle :install expect(the_bundle).to include_gems "omg 1.0" end @@ -203,6 +277,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "premailer", :path => "#{lib_path("premailer")}" G @@ -223,11 +298,11 @@ G end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G - expect(err).to_not include("ERROR REPORT") expect(err).to_not include("Your Gemfile has no gem server sources.") expect(err).to match(/is not valid. Please fix this gemspec./) expect(err).to match(/The validation error was 'missing value for attribute version'/) @@ -246,11 +321,9 @@ File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile } - Dir.chdir(lib_path("foo")) do - bundle "install" - expect(the_bundle).to include_gems "foo 1.0" - expect(the_bundle).to include_gems "rack 1.0" - end + bundle "install", :dir => lib_path("foo") + expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo") + expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo") end it "supports gemspec syntax with an alternative path" do @@ -272,19 +345,17 @@ s.add_dependency "rack", ">= 1.0" end - Dir.chdir lib_path("foo") - - install_gemfile lib_path("foo/Gemfile"), <<-G + install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo") source "#{file_uri_for(gem_repo1)}" gemspec G build_gem "rack", "1.0.1", :to_system => true - bundle "install" + bundle "install", :dir => lib_path("foo") - expect(the_bundle).to include_gems "foo 1.0" - expect(the_bundle).to include_gems "rack 1.0" + expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo") + expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo") end it "doesn't automatically unlock dependencies when using the gemspec syntax and the gem has development dependencies" do @@ -293,19 +364,17 @@ s.add_development_dependency "activesupport" end - Dir.chdir lib_path("foo") - - install_gemfile lib_path("foo/Gemfile"), <<-G + install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo") source "#{file_uri_for(gem_repo1)}" gemspec G build_gem "rack", "1.0.1", :to_system => true - bundle "install" + bundle "install", :dir => lib_path("foo") - expect(the_bundle).to include_gems "foo 1.0" - expect(the_bundle).to include_gems "rack 1.0" + expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo") + expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo") end it "raises if there are multiple gemspecs" do @@ -313,11 +382,12 @@ s.write "bar.gemspec", build_spec("bar", "1.0").first.to_ruby end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gemspec :path => "#{lib_path("foo")}" G - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) expect(err).to match(/There are multiple gemspecs/) end @@ -327,6 +397,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gemspec :path => "#{lib_path("foo")}", :name => "foo" G @@ -338,11 +409,13 @@ s.executables = "foobar" end - install_gemfile <<-G + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo1)}" path "#{lib_path("foo-1.0")}" do gem 'foo' end G + expect(out).to include("Using foo 1.0 from source at `#{lib_path("foo-1.0")}` and installing its executables") expect(the_bundle).to include_gems "foo 1.0" bundle "exec foobar" @@ -355,6 +428,7 @@ lib_path("foo-1.0").join("bin/performance").mkpath install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', '1.0', :path => "#{lib_path("foo-1.0")}" G expect(err).to be_empty @@ -364,6 +438,7 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :path => "#{lib_path("foo-1.0")}" G @@ -376,6 +451,7 @@ build_lib "hi2u" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "omg" gem "hi2u" @@ -394,6 +470,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo")}" gem "omg", :path => "#{lib_path("omg")}" G @@ -405,6 +482,7 @@ build_lib "foo", :gemspec => false gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", "1.0", :path => "#{lib_path("foo-1.0")}" G @@ -420,15 +498,15 @@ specs: GEM - remote: http://rubygems.org + remote: http://rubygems.org/ L - in_app_root { FileUtils.mkdir_p("vendor/bar") } + FileUtils.mkdir_p(bundled_app("vendor/bar")) install_gemfile <<-G + source "http://rubygems.org" gem "bar", "1.0.0", path: "vendor/bar", require: "bar/nyard" G - expect(exitstatus).to eq(0) if exitstatus end context "existing lockfile" do @@ -471,6 +549,7 @@ end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G @@ -486,6 +565,7 @@ build_lib "bar", "1.0", :path => lib_path("foo/bar") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo")}" G end @@ -538,7 +618,7 @@ expect(the_bundle).to include_gems "rack 0.9.1" - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo")} specs: @@ -566,7 +646,7 @@ bundle "install" - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo")} specs: @@ -590,6 +670,71 @@ expect(the_bundle).to include_gems "rack 0.9.1" end + + it "keeps using the same version even when another dependency is added" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "0.9.1" + end + + bundle "install" + + expect(the_bundle).to include_gems "rack 0.9.1" + + expect(lockfile).to eq <<~G + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack (= 0.9.1) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack" + s.add_dependency "rake", "13.0.1" + end + + bundle "install" + + expect(lockfile).to eq <<~G + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack + rake (= 13.0.1) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + rake (13.0.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + + expect(the_bundle).to include_gems "rack 0.9.1" + end end describe "switching sources" do @@ -617,7 +762,7 @@ it "switches the source when the gem existed in rubygems and the path was already being used for another gem" do build_lib "foo", "1.0", :path => lib_path("foo") - build_gem "bar", "1.0", :to_system => true do |s| + build_gem "bar", "1.0", :to_bundle => true do |s| s.write "lib/bar.rb", "raise 'fail'" end @@ -653,13 +798,11 @@ G File.open(lib_path("private_lib/Gemfile"), "w") {|f| f.puts gemfile } - Dir.chdir(lib_path("private_lib")) do - bundle :install, :env => { "DEBUG" => "1" }, :artifice => "endpoint" - expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$}) - expect(out).not_to match(/^HTTP GET.*private_lib/) - expect(the_bundle).to include_gems "private_lib 2.2" - expect(the_bundle).to include_gems "rack 1.0" - end + bundle :install, :env => { "DEBUG" => "1" }, :artifice => "endpoint", :dir => lib_path("private_lib") + expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$}) + expect(out).not_to match(/^HTTP GET.*private_lib/) + expect(the_bundle).to include_gems "private_lib 2.2", :dir => lib_path("private_lib") + expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("private_lib") end end @@ -667,6 +810,7 @@ it "runs pre-install hooks" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -686,6 +830,7 @@ it "runs post-install hooks" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -705,6 +850,7 @@ it "complains if the install hook fails" do build_git "foo" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G @@ -716,8 +862,7 @@ H end - bundle :install, - :requires => [lib_path("install_hooks.rb")] + bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false expect(err).to include("failed for foo-1.0") end @@ -728,14 +873,15 @@ expect(bar_file).not_to be_file build_lib "foo" do |s| - s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{foo_file}')") + s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{foo_file}')") end build_git "bar" do |s| - s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{bar_file}')") + s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{bar_file}')") end - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" gem "bar", :path => "#{lib_path("bar-1.0")}" G diff --git a/ruby/spec/bundler/install/gemfile/platform_spec.rb b/ruby/spec/bundler/install/gemfile/platform_spec.rb index c09653139..839db0089 100644 --- a/ruby/spec/bundler/install/gemfile/platform_spec.rb +++ b/ruby/spec/bundler/install/gemfile/platform_spec.rb @@ -50,27 +50,53 @@ expect(the_bundle).to include_gems "platform_specific 1.0 JAVA" end - it "works with gems that have different dependencies" do - simulate_platform "java" + it "pulls the pure ruby version on jruby if the java platform is not present in the lockfile and bundler is run in frozen mode", :jruby do + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo1)} + specs: + platform_specific (1.0) + + PLATFORMS + ruby + + DEPENDENCIES + platform_specific + G + + bundle "config set --local frozen true" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - gem "nokogiri" + gem "platform_specific" G - expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" - - simulate_new_machine + expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" + end - simulate_platform "ruby" + it "works with gems that have different dependencies" do + simulate_platform "java" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri" G + expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" + + simulate_new_machine + bundle "config set --local force_ruby_platform true" + bundle "install" + expect(the_bundle).to include_gems "nokogiri 1.4.2" expect(the_bundle).not_to include_gems "weakling" + + simulate_new_machine + simulate_platform "java" + bundle "install" + + expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" end it "does not keep unneeded platforms for gems that are used" do @@ -95,14 +121,14 @@ simulate_platform java - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" gem "empyrean", "0.1.0" gem "pry" G - lockfile_should_be <<-L + expect(lockfile).to eq <<~L GEM remote: #{file_uri_for(gem_repo4)}/ specs: @@ -128,9 +154,9 @@ #{Bundler::VERSION} L - bundle! "lock --add-platform ruby" + bundle "lock --add-platform ruby" - good_lockfile = strip_whitespace(<<-L) + good_lockfile = <<~L GEM remote: #{file_uri_for(gem_repo4)}/ specs: @@ -160,9 +186,9 @@ #{Bundler::VERSION} L - lockfile_should_be good_lockfile + expect(lockfile).to eq good_lockfile - bad_lockfile = strip_whitespace <<-L + bad_lockfile = <<~L GEM remote: #{file_uri_for(gem_repo4)}/ specs: @@ -195,65 +221,54 @@ aggregate_failures do lockfile bad_lockfile - bundle! :install - lockfile_should_be good_lockfile + bundle :install + expect(lockfile).to eq good_lockfile lockfile bad_lockfile - bundle! :update, :all => true - lockfile_should_be good_lockfile + bundle :update, :all => true + expect(lockfile).to eq good_lockfile lockfile bad_lockfile - bundle! "update ffi" - lockfile_should_be good_lockfile + bundle "update ffi" + expect(lockfile).to eq good_lockfile lockfile bad_lockfile - bundle! "update empyrean" - lockfile_should_be good_lockfile + bundle "update empyrean" + expect(lockfile).to eq good_lockfile lockfile bad_lockfile - bundle! :lock - lockfile_should_be good_lockfile + bundle :lock + expect(lockfile).to eq good_lockfile end end - it "works the other way with gems that have different dependencies" do - simulate_platform "ruby" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - - gem "nokogiri" - G - - simulate_platform "java" - bundle "install" - - expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" - end - - it "works with gems that have extra platform-specific runtime dependencies", :bundler => "< 3" do + it "works with gems with platform-specific dependency having different requirements order" do simulate_platform x64_mac update_repo2 do - build_gem "facter", "2.4.6" - build_gem "facter", "2.4.6" do |s| + build_gem "fspath", "3" + build_gem "image_optim_pack", "1.2.3" do |s| + s.add_runtime_dependency "fspath", ">= 2.1", "< 4" + end + build_gem "image_optim_pack", "1.2.3" do |s| s.platform = "universal-darwin" - s.add_runtime_dependency "CFPropertyList" + s.add_runtime_dependency "fspath", "< 4", ">= 2.1" end - build_gem "CFPropertyList" end - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + G + + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" - gem "facter" + gem "image_optim_pack" G - expect(err).to include "Unable to use the platform-specific (universal-darwin) version of facter (2.4.6) " \ - "because it has different dependencies from the ruby version. " \ - "To use the platform-specific version of the gem, run `bundle config set specific_platform true` and install again." + expect(err).not_to include "Unable to use the platform-specific" - expect(the_bundle).to include_gem "facter 2.4.6" - expect(the_bundle).not_to include_gem "CFPropertyList" + expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin" end it "fetches gems again after changing the version of Ruby" do @@ -263,17 +278,62 @@ gem "rack", "1.0.0" G - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle :install FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, "1.8")) - bundle! :install + bundle :install expect(vendored_gems("gems/rack-1.0.0")).to exist end + + it "keeps existing platforms when installing with force_ruby_platform" do + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0-java) + + PLATFORMS + java + + DEPENDENCIES + platform_specific + G + + bundle "config set --local force_ruby_platform true" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" + G + + expect(the_bundle).to include_gem "platform_specific 1.0 RUBY" + + expect(lockfile).to eq <<~G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0) + platform_specific (1.0-java) + + PLATFORMS + java + ruby + + DEPENDENCIES + platform_specific + + BUNDLED WITH + #{Bundler::VERSION} + G + end end RSpec.describe "bundle install with platform conditionals" do it "installs gems tagged w/ the current platforms" do + skip "platform issues" if Gem.win_platform? + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -298,7 +358,52 @@ expect(the_bundle).not_to include_gems "nokogiri 1.4.2" end + it "installs gems tagged w/ another platform but also dependent on the current one transitively" do + build_repo4 do + build_gem "activesupport", "6.1.4.1" do |s| + s.add_dependency "tzinfo", "~> 2.0" + end + + build_gem "tzinfo", "2.0.4" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "activesupport" + + platforms :#{not_local_tag} do + gem "tzinfo", "~> 1.2" + end + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + activesupport (6.1.4.1) + tzinfo (~> 2.0) + tzinfo (2.0.4) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + tzinfo (~> 1.2) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install --verbose" + + expect(the_bundle).to include_gems "tzinfo 2.0.4" + end + it "installs gems tagged w/ the current platforms inline" do + skip "platform issues" if Gem.win_platform? + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri", :platforms => :#{local_tag} @@ -317,6 +422,8 @@ end it "installs gems tagged w/ the current platform inline" do + skip "platform issues" if Gem.win_platform? + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri", :platform => :#{local_tag} @@ -336,18 +443,17 @@ build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" platform :#{not_local_tag} do gem "foo", :git => "#{lib_path("foo-1.0")}" end G bundle :list - expect(exitstatus).to eq(0) if exitstatus end it "does not attempt to install gems from :rbx when using --local" do - simulate_platform "ruby" - simulate_ruby_engine "ruby" + bundle "config set --local force_ruby_platform true" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -359,8 +465,7 @@ end it "does not attempt to install gems from other rubies when using --local" do - simulate_platform "ruby" - simulate_ruby_engine "ruby" + bundle "config set --local force_ruby_platform true" other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18 gemfile <<-G @@ -372,9 +477,8 @@ expect(out).not_to match(/Could not find gem 'some_gem/) end - it "prints a helpful warning when a dependency is unused on any platform" do - simulate_platform "ruby" - simulate_ruby_engine "ruby" + it "does not print a warning when a dependency is unused on a platform different from the current one" do + bundle "config set --local force_ruby_platform true" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -382,30 +486,24 @@ gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby] G - bundle! "install" - - expect(err).to include <<-O.strip -The dependency #{Gem::Dependency.new("rack", ">= 0")} will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`. - O - end - - context "when disable_platform_warnings is true" do - before { bundle! "config set disable_platform_warnings true" } + bundle "install" - it "does not print the warning when a dependency is unused on any platform" do - simulate_platform "ruby" - simulate_ruby_engine "ruby" + expect(err).to be_empty - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: - gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby] - G + PLATFORMS + ruby - bundle! "install" + DEPENDENCIES + rack - expect(out).not_to match(/The dependency (.*) will be unused/) - end + BUNDLED WITH + #{Bundler::VERSION} + L end end @@ -413,13 +511,21 @@ it "still installs correctly" do simulate_platform mswin + build_repo2 do + # The rcov gem is platform mswin32, but has no arch + build_gem "rcov" do |s| + s.platform = Gem::Platform.new([nil, "mswin32", nil]) + s.write "lib/rcov.rb", "RCOV = '1.0.0'" + end + end + gemfile <<-G # Try to install gem with nil arch source "http://localgemserver.test/" gem "rcov" G - bundle :install, :artifice => "windows" + bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(the_bundle).to include_gems "rcov 1.0.0" end end diff --git a/ruby/spec/bundler/install/gemfile/ruby_spec.rb b/ruby/spec/bundler/install/gemfile/ruby_spec.rb index d1e9fc7e0..ba250acfd 100644 --- a/ruby/spec/bundler/install/gemfile/ruby_spec.rb +++ b/ruby/spec/bundler/install/gemfile/ruby_spec.rb @@ -2,10 +2,10 @@ RSpec.describe "ruby requirement" do def locked_ruby_version - Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(lockfile).ruby_version) + Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(File.read(bundled_app_lock)).ruby_version) end - # As discovered by https://github.com/bundler/bundler/issues/4147, there is + # As discovered by https://github.com/rubygems/bundler/issues/4147, there is # no test coverage to ensure that adding a gem is possible with a ruby # requirement. This test verifies the fix, committed in bfbad5c5. it "allows adding gems" do @@ -22,7 +22,6 @@ def locked_ruby_version gem "rack-obama" G - expect(exitstatus).to eq(0) if exitstatus expect(the_bundle).to include_gems "rack-obama 1.0" end @@ -47,17 +46,16 @@ def locked_ruby_version it "allows changing the ruby version requirement to something compatible" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - ruby ">= 1.0.0" + ruby ">= #{RUBY_VERSION[0..2]}.0" gem "rack" G + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) expect(locked_ruby_version).to eq(Bundler::RubyVersion.system) - simulate_ruby_version "5100" - install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - ruby ">= 1.0.1" + ruby ">= #{RUBY_VERSION}" gem "rack" G @@ -72,22 +70,39 @@ def locked_ruby_version gem "rack" G - expect(locked_ruby_version).to eq(Bundler::RubyVersion.system) + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (1.0.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack - simulate_ruby_version "5100" + RUBY VERSION + ruby 2.1.4p422 + + BUNDLED WITH + #{Bundler::VERSION} + L + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - ruby ">= 5000.0" + ruby ">= #{RUBY_VERSION[0..2]}.0" gem "rack" G expect(the_bundle).to include_gems "rack 1.0.0" - expect(locked_ruby_version.versions).to eq(["5100"]) + expect(locked_ruby_version).to eq(Bundler::RubyVersion.system) end it "allows requirements with trailing whitespace" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" ruby "#{RUBY_VERSION}\\n \t\\n" gem "rack" @@ -97,7 +112,7 @@ def locked_ruby_version end it "fails gracefully with malformed requirements" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" ruby ">= 0", "-.\\0" gem "rack" diff --git a/ruby/spec/bundler/install/gemfile/sources_spec.rb b/ruby/spec/bundler/install/gemfile/sources_spec.rb index 61943ef2e..26ecb840c 100644 --- a/ruby/spec/bundler/install/gemfile/sources_spec.rb +++ b/ruby/spec/bundler/install/gemfile/sources_spec.rb @@ -15,56 +15,56 @@ end end - context "with multiple toplevel sources", :bundler => "< 3" do + context "with multiple toplevel sources" do let(:repo3_rack_version) { "1.0.0" } before do gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" + source "https://gem.repo3" + source "https://gem.repo1" gem "rack-obama" gem "rack" G end - it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "2" do - bundle :install + it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do + bundle :install, :artifice => "compact_index" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}") + expect(err).to include("Installed from: https://gem.repo1") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1") end it "fails", :bundler => "3" do - bundle :install + bundle :instal, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) if exitstatus + expect(exitstatus).to eq(4) end end - context "when different versions of the same gem are in multiple sources", :bundler => "< 3" do + context "when different versions of the same gem are in multiple sources" do let(:repo3_rack_version) { "1.2" } before do gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" + source "https://gem.repo3" + source "https://gem.repo1" gem "rack-obama" gem "rack", "1.0.0" # force it to install the working version in repo1 G - - bundle :install end - it "warns about ambiguous gems, but installs anyway", :bundler => "2" do + it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do + bundle :install, :artifice => "compact_index" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}") + expect(err).to include("Installed from: https://gem.repo1") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1") end it "fails", :bundler => "3" do + bundle :install, :artifice => "compact_index", :raise_on_error => false expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) if exitstatus + expect(exitstatus).to eq(4) end end end @@ -85,29 +85,30 @@ end gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - source "#{file_uri_for(gem_repo1)}" do + source "https://gem.repo3" + source "https://gem.repo1" do gem "thin" # comes first to test name sorting gem "rack" end - gem "rack-obama" # shoud come from repo3! + gem "rack-obama" # should come from repo3! G end it "installs the gems without any warning" do - bundle! :install - expect(out).not_to include("Warning") + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack-obama 1.0.0") expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1") end it "can cache and deploy" do - bundle! :cache + bundle :cache, :artifice => "compact_index" expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist - bundle! :install, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0") end @@ -127,258 +128,813 @@ end end - gemfile <<-G - source "#{file_uri_for(gem_repo3)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo3" gem "rack-obama" # should come from repo3! - gem "rack", :source => "#{file_uri_for(gem_repo1)}" + gem "rack", :source => "https://gem.repo1" G end it "installs the gems without any warning" do - bundle :install - expect(out).not_to include("Warning") + expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0") end end - context "when a pinned gem has an indirect dependency" do + context "when a pinned gem has an indirect dependency in the pinned source" do before do build_repo gem_repo3 do build_gem "depends_on_rack", "1.0.1" do |s| s.add_dependency "rack" end end + + # we need a working rack gem in repo3 + update_repo gem_repo3 do + build_gem "rack", "1.0.0" + end + + gemfile <<-G + source "https://gem.repo2" + source "https://gem.repo3" do + gem "depends_on_rack" + end + G end - context "when the indirect dependency is in the pinned source" do + context "and not in any other sources" do before do - # we need a working rack gem in repo3 - update_repo gem_repo3 do - build_gem "rack", "1.0.0" + build_repo(gem_repo2) {} + end + + it "installs from the same source without any warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end + end + + context "and in another source" do + before do + # need this to be broken to check for correct source ordering + build_repo gem_repo2 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end + + it "installs from the same source without any warning" do + bundle :install, :artifice => "compact_index" + + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + + # In https://github.com/bundler/bundler/issues/3585 this failed + # when there is already a lock file, and the gems are missing, so try again + system_gems [] + bundle :install, :artifice => "compact_index" + + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end + end + end + + context "when a pinned gem has an indirect dependency in a different source" do + before do + # In these tests, we need a working rack gem in repo2 and not repo3 + + build_repo gem_repo3 do + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" end + end + + build_repo gem_repo2 do + build_gem "rack", "1.0.0" + end + end + + context "and not in any other sources" do + before do + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo2" + source "https://gem.repo3" do + gem "depends_on_rack" + end + G + end + + it "installs from the other source without any warning" do + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + end + end + context "and in yet another source" do + before do gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo1" + source "https://gem.repo2" + source "https://gem.repo3" do gem "depends_on_rack" end G end - context "and not in any other sources" do - before do - build_repo(gem_repo2) {} - end + it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do + bundle :install, :artifice => "compact_index" + expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") + expect(err).to include("Installed from: https://gem.repo2") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo1/ + remote: https://gem.repo2/ + specs: + rack (1.0.0) + + GEM + remote: https://gem.repo3/ + specs: + depends_on_rack (1.0.1) + rack + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + depends_on_rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + + previous_lockfile = lockfile + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + expect(lockfile).to eq(previous_lockfile) + end - it "installs from the same source without any warning" do - bundle :install - expect(out).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end + it "fails", :bundler => "3" do + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include("Each source after the first must include a block") + expect(exitstatus).to eq(4) end + end - context "and in another source" do - before do - # need this to be broken to check for correct source ordering - build_repo gem_repo2 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end + context "and only the dependency is pinned" do + before do + # need this to be broken to check for correct source ordering + build_repo gem_repo2 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" end end - context "when disable_multisource is set" do - before do - bundle! "config set disable_multisource true" - end + gemfile <<-G + source "https://gem.repo3" # contains depends_on_rack + source "https://gem.repo2" # contains broken rack - it "installs from the same source without any warning" do - bundle! :install + gem "depends_on_rack" # installed from gem_repo3 + gem "rack", :source => "https://gem.repo1" + G + end - expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + it "installs the dependency from the pinned source without warning", :bundler => "< 3" do + bundle :install, :artifice => "compact_index" - # when there is already a lock file, and the gems are missing, so try again - system_gems [] - bundle! :install + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end - end + # In https://github.com/rubygems/bundler/issues/3585 this failed + # when there is already a lock file, and the gems are missing, so try again + system_gems [] + bundle :install, :artifice => "compact_index" + + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + end + + it "fails", :bundler => "3" do + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include("Each source after the first must include a block") + expect(exitstatus).to eq(4) end end + end - context "when the indirect dependency is in a different source" do - before do - # In these tests, we need a working rack gem in repo2 and not repo3 - build_repo gem_repo2 do - build_gem "rack", "1.0.0" - end + context "when a top-level gem can only be found in an scoped source" do + before do + build_repo2 + + build_repo gem_repo3 do + build_gem "private_gem_1", "1.0.0" + build_gem "private_gem_2", "1.0.0" end - context "and not in any other sources" do - before do - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do - gem "depends_on_rack" - end - G + gemfile <<-G + source "https://gem.repo2" + + gem "private_gem_1" + + source "https://gem.repo3" do + gem "private_gem_2" end + G + end + + it "fails" do + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/ or installed locally.") + end + end + + context "when an indirect dependency can't be found in the aggregate rubygems source", :bundler => "< 3" do + before do + build_repo2 - it "installs from the other source without any warning" do - bundle :install - expect(out).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + build_repo gem_repo3 do + build_gem "depends_on_missing", "1.0.1" do |s| + s.add_dependency "missing" end end - context "and in yet another source", :bundler => "< 3" do - before do - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do - gem "depends_on_rack" - end - G + gemfile <<-G + source "https://gem.repo2" + + source "https://gem.repo3" + + gem "depends_on_missing" + G + end + + it "fails" do + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include("Could not find gem 'missing', which is required by gem 'depends_on_missing', in any of the sources.") + end + end - bundle :install + context "when a top-level gem has an indirect dependency" do + before do + build_repo gem_repo2 do + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" end + end - it "installs from the other source and warns about ambiguous gems", :bundler => "2" do - expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + build_repo gem_repo3 do + build_gem "unrelated_gem", "1.0.0" + end + + gemfile <<-G + source "https://gem.repo2" + + gem "depends_on_rack" + + source "https://gem.repo3" do + gem "unrelated_gem" end + G + end - it "fails", :bundler => "3" do - expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) if exitstatus + context "and the dependency is only in the top-level source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" end end - context "and only the dependency is pinned", :bundler => "< 3" do - before do - # need this to be broken to check for correct source ordering - build_repo gem_repo2 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end + it "installs the dependency from the top-level source without warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3") + end + end + + context "and the dependency is only in a pinned source" do + before do + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" end + end + end - gemfile <<-G - source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack - source "#{file_uri_for(gem_repo2)}" # contains broken rack + it "does not find the dependency" do + bundle :install, :artifice => "compact_index", :raise_on_error => false + expect(err).to include( + "Could not find gem 'rack', which is required by gem 'depends_on_rack', in rubygems repository https://gem.repo2/ or installed locally." + ) + end + end - gem "depends_on_rack" # installed from gem_repo3 - gem "rack", :source => "#{file_uri_for(gem_repo1)}" - G + context "and the dependency is in both the top-level and a pinned source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" end - it "installs the dependency from the pinned source without warning", :bundler => "2" do - bundle :install + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + it "installs the dependency from the top-level source without warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(run("require 'rack'; puts RACK")).to eq("1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3") + end + end + end - # In https://github.com/bundler/bundler/issues/3585 this failed - # when there is already a lock file, and the gems are missing, so try again - system_gems [] - bundle :install + context "when a scoped gem has a deeply nested indirect dependency" do + before do + build_repo gem_repo3 do + build_gem "depends_on_depends_on_rack", "1.0.1" do |s| + s.add_dependency "depends_on_rack" + end - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" end + end - it "fails", :bundler => "3" do - bundle :install - expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) if exitstatus + gemfile <<-G + source "https://gem.repo2" + + source "https://gem.repo3" do + gem "depends_on_depends_on_rack" end + G + end + + context "and the dependency is only in the top-level source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" + end + end + + it "installs the dependency from the top-level source" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0") + expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote2") + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", :source => "remote3") end end - end - context "when a top-level gem has an indirect dependency" do - context "when disable_multisource is set" do + context "and the dependency is only in a pinned source" do before do - bundle! "config set disable_multisource true" + build_repo2 + + update_repo gem_repo3 do + build_gem "rack", "1.0.0" + end end + it "installs the dependency from the pinned source" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end + end + + context "and the dependency is in both the top-level and a pinned source" do before do - build_repo gem_repo2 do - build_gem "depends_on_rack", "1.0.1" do |s| - s.add_dependency "rack" + update_repo gem_repo2 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" end end - build_repo gem_repo3 do - build_gem "unrelated_gem", "1.0.0" + update_repo gem_repo3 do + build_gem "rack", "1.0.0" end + end - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + it "installs the dependency from the pinned source without warning" do + bundle :install, :artifice => "compact_index" + expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") + end + end + end - gem "depends_on_rack" + context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do + before do + build_repo gem_repo2 do + build_gem "activesupport", "6.0.3.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 0.7", "< 2" + s.add_dependency "minitest", "~> 5.1" + s.add_dependency "tzinfo", "~> 1.1" + s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2" + end - source "#{file_uri_for(gem_repo3)}" do - gem "unrelated_gem" - end - G - end + build_gem "activesupport", "6.1.2.1" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 1.6", "< 2" + s.add_dependency "minitest", ">= 5.1" + s.add_dependency "tzinfo", "~> 2.0" + s.add_dependency "zeitwerk", "~> 2.3" + end - context "and the dependency is only in the top-level source" do - before do - update_repo gem_repo2 do - build_gem "rack", "1.0.0" - end + build_gem "concurrent-ruby", "1.1.8" + build_gem "concurrent-ruby", "1.1.9" + build_gem "connection_pool", "2.2.3" + + build_gem "i18n", "1.8.9" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" + end + + build_gem "minitest", "5.14.3" + build_gem "rack", "2.2.3" + build_gem "redis", "4.2.5" + + build_gem "sidekiq", "6.1.3" do |s| + s.add_dependency "connection_pool", ">= 2.2.2" + s.add_dependency "rack", "~> 2.0" + s.add_dependency "redis", ">= 4.2.0" + end + + build_gem "thread_safe", "0.3.6" + + build_gem "tzinfo", "1.2.9" do |s| + s.add_dependency "thread_safe", "~> 0.1" end - it "installs all gems without warning" do - bundle :install - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + build_gem "tzinfo", "2.0.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" end + + build_gem "zeitwerk", "2.4.2" end - context "and the dependency is only in a pinned source" do - before do - update_repo gem_repo3 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end - end + build_repo gem_repo3 do + build_gem "sidekiq-pro", "5.2.1" do |s| + s.add_dependency "connection_pool", ">= 2.2.3" + s.add_dependency "sidekiq", ">= 6.1.0" end + end + + gemfile <<-G + # frozen_string_literal: true - it "does not find the dependency" do - bundle :install - expect(err).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources") + source "https://gem.repo2" + + gem "activesupport" + + source "https://gem.repo3" do + gem "sidekiq-pro" end + G + + lockfile <<~L + GEM + remote: https://gem.repo2/ + remote: https://gem.repo3/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.8) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "does not install newer versions but updates the lockfile format when running bundle install in non frozen mode, and doesn't warn" do + bundle :install, :artifice => "compact_index" + expect(err).to be_empty + + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.8) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) + + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns", :bundler => "< 3" do + initial_lockfile = lockfile + + bundle "config set --local frozen true" + bundle :install, :artifice => "compact_index" + + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9") + + expect(lockfile).to eq(initial_lockfile) + end + + it "fails when running bundle install in frozen mode", :bundler => "3" do + initial_lockfile = lockfile + + bundle "config set --local frozen true" + bundle :install, :artifice => "compact_index", :raise_on_error => false + + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + + expect(lockfile).to eq(initial_lockfile) + end + + it "splits sections and upgrades gems when running bundle update, and doesn't warn" do + bundle "update --all", :artifice => "compact_index" + expect(err).to be_empty + + expect(the_bundle).not_to include_gems("activesupport 6.0.3.4") + expect(the_bundle).to include_gems("activesupport 6.1.2.1") + expect(the_bundle).not_to include_gems("tzinfo 1.2.9") + expect(the_bundle).to include_gems("tzinfo 2.0.4") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.1.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + concurrent-ruby (1.1.9) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + zeitwerk (2.4.2) + + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "upgrades the lockfile format and upgrades the requested gem when running bundle update with an argument" do + bundle "update concurrent-ruby", :artifice => "compact_index" + expect(err).to be_empty + + expect(the_bundle).to include_gems("activesupport 6.0.3.4") + expect(the_bundle).not_to include_gems("activesupport 6.1.2.1") + expect(the_bundle).to include_gems("tzinfo 1.2.9") + expect(the_bundle).not_to include_gems("tzinfo 2.0.4") + expect(the_bundle).to include_gems("concurrent-ruby 1.1.9") + expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.9) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) + + GEM + remote: https://gem.repo3/ + specs: + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved" do + before do + build_lib "activesupport", "7.0.0.alpha", :path => lib_path("rails/activesupport") + build_lib "rails", "7.0.0.alpha", :path => lib_path("rails") do |s| + s.add_dependency "activesupport", "= 7.0.0.alpha" end - context "and the dependency is in both the top-level and a pinned source" do - before do - update_repo gem_repo2 do - build_gem "rack", "1.0.0" - end + build_repo gem_repo2 do + build_gem "activesupport", "6.1.2" - update_repo gem_repo3 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end - end + build_gem "webpacker", "5.2.1" do |s| + s.add_dependency "activesupport", ">= 5.2" end + end + + gemfile <<-G + source "https://gem.repo2" + + gemspec :path => "#{lib_path("rails")}" - it "installs the dependency from the top-level source without warning" do - bundle :install - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + gem "webpacker", "~> 5.0" + G + end + + it "installs all gems without warning" do + bundle :install, :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha") + expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", :source => "path@#{lib_path("rails/activesupport")}") + expect(the_bundle).to include_gems("rails 7.0.0.alpha", :source => "path@#{lib_path("rails")}") + end + end + + context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source " do + before do + build_repo gem_repo3 do + build_gem "handsoap", "0.2.5.5" do |s| + s.add_dependency "nokogiri", ">= 1.2.3" end end + + update_repo gem_repo2 do + build_gem "nokogiri", "1.11.1" do |s| + s.add_dependency "racca", "~> 1.4" + end + + build_gem "racca", "1.5.2" + end + + gemfile <<-G + source "https://gem.repo2" + + source "https://gem.repo3" do + gem "handsoap" + end + + gem "nokogiri" + G + end + + it "installs from the default source without any warnings or errors and generates a proper lockfile" do + expected_lockfile = <<~L + GEM + remote: https://gem.repo2/ + specs: + nokogiri (1.11.1) + racca (~> 1.4) + racca (1.5.2) + + GEM + remote: https://gem.repo3/ + specs: + handsoap (0.2.5.5) + nokogiri (>= 1.2.3) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + handsoap! + nokogiri + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install --verbose", :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") + expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") + expect(lockfile).to eq(expected_lockfile) + + # Even if the gems are already installed + FileUtils.rm bundled_app_lock + bundle "install --verbose", :artifice => "compact_index" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") + expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") + expect(lockfile).to eq(expected_lockfile) end end @@ -388,64 +944,145 @@ build_gem "not_in_repo1", "1.0.0" end - gemfile <<-G - source "#{file_uri_for(gem_repo3)}" - gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "https://gem.repo3" + gem "not_in_repo1", :source => "https://gem.repo1" G end it "does not install the gem" do - bundle :install expect(err).to include("Could not find gem 'not_in_repo1'") end end context "with an existing lockfile" do before do - system_gems "rack-0.9.1", "rack-1.0.0", :path => :bundle_path + system_gems "rack-0.9.1", "rack-1.0.0", :path => default_bundle_path lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)} - remote: #{file_uri_for(gem_repo3)} + remote: https://gem.repo1 + specs: + + GEM + remote: https://gem.repo3 specs: rack (0.9.1) PLATFORMS - ruby + #{specific_local_platform} DEPENDENCIES rack! L gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo1" + source "https://gem.repo3" do gem 'rack' end G end - # Reproduction of https://github.com/bundler/bundler/issues/3298 + # Reproduction of https://github.com/rubygems/bundler/issues/3298 it "does not unlock the installed gem on exec" do expect(the_bundle).to include_gems("rack 0.9.1") end end + context "with a lockfile with aggregated rubygems sources" do + let(:aggregate_gem_section_lockfile) do + <<~L + GEM + remote: https://gem.repo1/ + remote: https://gem.repo3/ + specs: + rack (0.9.1) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + let(:split_gem_section_lockfile) do + <<~L + GEM + remote: https://gem.repo1/ + specs: + + GEM + remote: https://gem.repo3/ + specs: + rack (0.9.1) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + before do + build_repo gem_repo3 do + build_gem "rack", "0.9.1" + end + + gemfile <<-G + source "https://gem.repo1" + source "https://gem.repo3" do + gem 'rack' + end + G + + lockfile aggregate_gem_section_lockfile + end + + it "installs the existing lockfile but prints a warning", :bundler => "< 3" do + bundle "config set --local deployment true" + + bundle "install", :artifice => "compact_index" + + expect(lockfile).to eq(aggregate_gem_section_lockfile) + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3") + end + + it "refuses to install the existing lockfile and prints an error", :bundler => "3" do + bundle "config set --local deployment true" + + bundle "install", :artifice => "compact_index", :raise_on_error =>false + + expect(lockfile).to eq(aggregate_gem_section_lockfile) + expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") + expect(out).to be_empty + end + end + context "with a path gem in the same Gemfile" do before do build_lib "foo" gemfile <<-G - gem "rack", :source => "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo1)}" + gem "rack", :source => "https://gem.repo1" gem "foo", :path => "#{lib_path("foo-1.0")}" G end it "does not unlock the non-path gem after install" do - bundle! :install + bundle :install, :artifice => "compact_index" - bundle! %(exec ruby -e 'puts "OK"') + bundle %(exec ruby -e 'puts "OK"') expect(out).to include("OK") end @@ -456,14 +1093,13 @@ before do system_gems "rack-0.9.1" - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" # shoud come from repo1! + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" + gem "rack" # should come from repo1! G end it "installs the gems without any warning" do - bundle :install expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack 1.0.0") end @@ -479,13 +1115,14 @@ # Installing this gemfile... gemfile <<-G - source '#{file_uri_for(gem_repo1)}' + source 'https://gem.repo1' gem 'rack' - gem 'foo', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' - gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' + gem 'foo', '~> 0.1', :source => 'https://gem.repo4' + gem 'bar', '~> 0.1', :source => 'https://gem.repo4' G - bundle! :install, forgotten_command_line_options(:path => "../gems/system") + bundle "config set --local path ../gems/system" + bundle :install, :artifice => "compact_index" # And then we add some new versions... update_repo4 do @@ -496,11 +1133,11 @@ it "allows them to be unlocked separately" do # And install this gemfile, updating only foo. - install_gemfile <<-G - source '#{file_uri_for(gem_repo1)}' + install_gemfile <<-G, :artifice => "compact_index" + source 'https://gem.repo1' gem 'rack' - gem 'foo', '~> 0.2', :source => '#{file_uri_for(gem_repo4)}' - gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}' + gem 'foo', '~> 0.2', :source => 'https://gem.repo4' + gem 'bar', '~> 0.1', :source => 'https://gem.repo4' G # It should update foo to 0.2, but not the (locked) bar 0.1 @@ -511,17 +1148,20 @@ context "re-resolving" do context "when there is a mix of sources in the gemfile" do before do - build_repo3 + build_repo gem_repo3 do + build_gem "rack" + end + build_lib "path1" build_lib "path2" build_git "git1" build_git "git2" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rails" - source "#{file_uri_for(gem_repo3)}" do + source "https://gem.repo3" do gem "rack" end @@ -533,7 +1173,7 @@ end it "does not re-resolve" do - bundle! :install, :verbose => true + bundle :install, :artifice => "compact_index", :verbose => true expect(out).to include("using resolution from the lockfile") expect(out).not_to include("re-resolving dependencies") end @@ -542,27 +1182,24 @@ context "when a gem is installed to system gems" do before do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rack" G end context "and the gemfile changes" do it "is still able to find that gem from remote sources" do - source_uri = file_uri_for(gem_repo1) - second_uri = file_uri_for(gem_repo4) - build_repo4 do build_gem "rack", "2.0.1.1.forked" build_gem "thor", "0.19.1.1.forked" end # When this gemfile is installed... - install_gemfile <<-G - source "#{source_uri}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" - source "#{second_uri}" do + source "https://gem.repo4" do gem "rack", "2.0.1.1.forked" gem "thor" end @@ -571,9 +1208,9 @@ # Then we change the Gemfile by adding a version to thor gemfile <<-G - source "#{source_uri}" + source "https://gem.repo1" - source "#{second_uri}" do + source "https://gem.repo4" do gem "rack", "2.0.1.1.forked" gem "thor", "0.19.1.1.forked" end @@ -581,20 +1218,24 @@ G # But we should still be able to find rack 2.0.1.1.forked and install it - bundle! :install + bundle :install, :artifice => "compact_index" end end end describe "source changed to one containing a higher version of a dependency" do before do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo1" gem "rack" G build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "bar" end @@ -602,23 +1243,109 @@ s.add_dependency "bar", "=1.0.0" end - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo2" gem "rack" gemspec :path => "#{tmp.join("gemspec_test")}" G end - it "keeps the old version", :bundler => "2" do + it "conservatively installs the existing locked version" do expect(the_bundle).to include_gems("rack 1.0.0") end + end + + it "doesn't update version when a gem uses a source block but a higher version from another source is already installed locally" do + build_repo2 do + build_gem "example", "0.1.0" + end + + build_repo4 do + build_gem "example", "1.0.2" + end + + install_gemfile <<-G, :artifice => "compact_index" + source "https://gem.repo4" + + gem "example", :source => "https://gem.repo2" + G + + bundle "info example" + expect(out).to include("example (0.1.0)") + + system_gems "example-1.0.2", :path => default_bundle_path, :gem_repo => gem_repo4 + + bundle "update example --verbose", :artifice => "compact_index" + expect(out).not_to include("Using example 1.0.2") + expect(out).to include("Using example 0.1.0") + end + + it "fails inmmediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do + gemfile <<-G + source "https://gem.repo1" + + source "https://gem.repo4" do + gem "example" + end + G + + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + ruby <<~R, :raise_on_error => false + require 'bundler/setup' + R + end + + expect(last_command).to be_failure + expect(err).to include("Could not find gem 'example' in locally installed gems.") + end + + it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do + gemfile <<-G + source "https://gem.repo1" + + source "https://gem.repo4" do + gem "example" + end + G + + bundle "install", :artifice => nil, :raise_on_error => false + + expect(last_command).to be_failure + expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.") + end + + context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do + it "succeeds but warns, suggesting a source block" do + build_repo4 do + build_gem "depends_on_rack" do |s| + s.add_dependency "rack" + end + build_gem "rack" + end + + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" + + source "https://gem.repo4" do + gem "depends_on_rack" + end - it "installs the higher version in the new repo", :bundler => "3" do - expect(the_bundle).to include_gems("rack 1.2") + source "https://gem.repo1" do + gem "thin" + end + G + expect(err).to eq strip_whitespace(<<-EOS).strip + Warning: The gem 'rack' was found in multiple relevant sources. + * rubygems repository https://gem.repo1/ + * rubygems repository https://gem.repo4/ + You should add this gem to the source block for the source you wish it to be installed from. + EOS + expect(last_command).to be_success + expect(the_bundle).to be_locked end end - context "when a gem is available from multiple ambiguous sources", :bundler => "3" do + context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "3" do it "raises, suggesting a source block" do build_repo4 do build_gem "depends_on_rack" do |s| @@ -627,21 +1354,146 @@ build_gem "rack" end - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - source "#{file_uri_for(gem_repo1)}" do + install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" + source "https://gem.repo4" do + gem "depends_on_rack" + end + source "https://gem.repo1" do gem "thin" end - gem "depends_on_rack" G expect(last_command).to be_failure expect(err).to eq strip_whitespace(<<-EOS).strip The gem 'rack' was found in multiple relevant sources. - * rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally - * rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally + * rubygems repository https://gem.repo1/ + * rubygems repository https://gem.repo4/ You must add this gem to the source block for the source you wish it to be installed from. EOS expect(the_bundle).not_to be_locked end end + + context "when upgrading a lockfile suffering from dependency confusion" do + before do + build_repo4 do + build_gem "mime-types", "3.0.0" + end + + build_repo2 do + build_gem "capybara", "2.5.0" do |s| + s.add_dependency "mime-types", ">= 1.16" + end + + build_gem "mime-types", "3.3.1" + end + + gemfile <<~G + source "https://gem.repo2" + + gem "capybara", "~> 2.5.0" + + source "https://gem.repo4" do + gem "mime-types", "~> 3.0" + end + G + + lockfile <<-L + GEM + remote: https://gem.repo2/ + remote: https://gem.repo4/ + specs: + capybara (2.5.0) + mime-types (>= 1.16) + mime-types (3.3.1) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + capybara (~> 2.5.0) + mime-types (~> 3.0)! + L + end + + it "upgrades the lockfile correctly" do + bundle "lock --update", :artifice => "compact_index" + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + capybara (2.5.0) + mime-types (>= 1.16) + + GEM + remote: https://gem.repo4/ + specs: + mime-types (3.0.0) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + capybara (~> 2.5.0) + mime-types (~> 3.0)! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "when default source includes old gems with nil required_rubygems_version" do + before do + build_repo2 do + build_gem "ruport", "1.7.0.3" do |s| + s.add_dependency "pdf-writer", "1.1.8" + end + end + + build_repo gem_repo4 do + build_gem "pdf-writer", "1.1.8" + end + + path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz" + spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path))) + spec.instance_variable_set(:@required_rubygems_version, nil) + File.open(path, "wb") do |f| + f.write Gem.deflate(Marshal.dump(spec)) + end + + gemfile <<~G + source "https://localgemserver.test" + + gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra" + G + end + + it "handles that fine" do + bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + + expect(lockfile).to eq <<~L + GEM + remote: https://localgemserver.test/ + specs: + pdf-writer (1.1.8) + + GEM + remote: https://localgemserver.test/extra/ + specs: + ruport (1.7.0.3) + pdf-writer (= 1.1.8) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + ruport (= 1.7.0.3)! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end end diff --git a/ruby/spec/bundler/install/gemfile/specific_platform_spec.rb b/ruby/spec/bundler/install/gemfile/specific_platform_spec.rb index 24b602589..113a0a135 100644 --- a/ruby/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/ruby/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -1,53 +1,6 @@ # frozen_string_literal: true -RSpec.describe "bundle install with specific_platform enabled" do - before do - bundle "config set specific_platform true" - - build_repo2 do - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" } - - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") - - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") - - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" } - - build_gem("google-protobuf", "3.0.0.alpha.4.0") - build_gem("google-protobuf", "3.0.0.alpha.3.1.pre") - build_gem("google-protobuf", "3.0.0.alpha.3") - build_gem("google-protobuf", "3.0.0.alpha.2.0") - build_gem("google-protobuf", "3.0.0.alpha.1.1") - build_gem("google-protobuf", "3.0.0.alpha.1.0") - - build_gem("facter", "2.4.6") - build_gem("facter", "2.4.6") do |s| - s.platform = "universal-darwin" - s.add_runtime_dependency "CFPropertyList" - end - build_gem("CFPropertyList") - end - end - +RSpec.describe "bundle install with specific platforms" do let(:google_protobuf) { <<-G } source "#{file_uri_for(gem_repo2)}" gem "google-protobuf" @@ -56,54 +9,239 @@ context "when on a darwin machine" do before { simulate_platform "x86_64-darwin-15" } - it "locks to both the specific darwin platform and ruby" do - install_gemfile!(google_protobuf) - expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")]) + it "locks to the specific darwin platform" do + setup_multiplatform_gem + install_gemfile(google_protobuf) + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin ]) end - it "caches both the universal-darwin and ruby gems when --all-platforms is passed" do + it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do + setup_multiplatform_gem + + system_gems "bundler-2.1.4" + + # Consistent location to install and look for gems + bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" } + + install_gemfile(google_protobuf, :env => { "BUNDLER_VERSION" => "2.1.4" }) + + # simulate lockfile created with old bundler, which only locks for ruby platform + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + google-protobuf (3.0.0.alpha.5.0.5.1) + + PLATFORMS + ruby + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + 2.1.4 + L + + # force strict usage of the lock file by setting frozen mode + bundle "config set --local frozen true", :env => { "BUNDLER_VERSION" => "2.1.4" } + + # make sure the platform that got actually installed with the old bundler is used + expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") + end + + it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do + setup_multiplatform_gem + + system_gems "bundler-2.1.4" + + # Consistent location to install and look for gems + bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" } + + gemfile google_protobuf + + # simulate lockfile created with old bundler, which only locks for ruby platform + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + google-protobuf (3.0.0.alpha.4.0) + + PLATFORMS + ruby + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + 2.1.4 + L + + bundle "update", :env => { "BUNDLER_VERSION" => Bundler::VERSION } + + # make sure the platform that the platform specific dependency is used, since we're only locked to ruby + expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") + + # make sure we're still only locked to ruby + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + google-protobuf (3.0.0.alpha.5.0.5.1) + + PLATFORMS + ruby + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do + build_repo2 do + build_gem("libv8", "8.4.255.0") + build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" } + + build_gem("mini_racer", "1.0.0") do |s| + s.add_runtime_dependency "libv8" + end + end + + system_gems "bundler-2.1.4" + + # Consistent location to install and look for gems + bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" } + + gemfile <<-G + source "https://localgemserver.test" + gem "libv8" + G + + # simulate lockfile created with old bundler, which only locks for ruby platform + lockfile <<-L + GEM + remote: https://localgemserver.test/ + specs: + libv8 (8.4.255.0) + + PLATFORMS + ruby + + DEPENDENCIES + libv8 + + BUNDLED WITH + 2.1.4 + L + + bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + expect(out).to include("Installing libv8 8.4.255.0 (universal-darwin)") + + bundle "add mini_racer --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)") + end + + it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do + setup_multiplatform_gem gemfile(google_protobuf) - bundle! "package --all-platforms" - expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]). - to all(exist) + bundle "cache --all-platforms" + expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist + + bundle "install --verbose" + expect(err).to be_empty + end + + it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do + setup_multiplatform_gem + gemfile(google_protobuf) + bundle "config set --local cache_all_platforms true" + bundle "cache" + expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist + + bundle "install --verbose" + expect(err).to be_empty + end + + it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do + git = build_git "pg_array_parser", "1.0" + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}" + G + + lockfile <<-L + GIT + remote: #{lib_path("pg_array_parser-1.0")} + revision: #{git.ref_for("master")} + specs: + pg_array_parser (1.0-java) + pg_array_parser (1.0) + + GEM + specs: + + PLATFORMS + java + #{lockfile_platforms} + + DEPENDENCIES + pg_array_parser! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "config set --local cache_all true" + bundle "cache --all-platforms" + + expect(err).to be_empty end it "uses the platform-specific gem with extra dependencies" do - install_gemfile! <<-G + setup_multiplatform_gem_with_different_dependencies_per_platform + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "facter" G + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0") expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0", - "facter-2.4.6", "facter-2.4.6-universal-darwin"]) end context "when adding a platform via lock --add_platform" do + before do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + end + it "adds the foreign platform" do - install_gemfile!(google_protobuf) - bundle! "lock --add-platform=#{x64_mingw}" + setup_multiplatform_gem + install_gemfile(google_protobuf) + bundle "lock --add-platform=#{x64_mingw}" - expect(the_bundle.locked_gems.platforms).to eq([rb, x64_mingw, pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([x64_mingw, pl("x86_64-darwin-15")]) expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32 ]) end it "falls back on plain ruby when that version doesnt have a platform-specific gem" do - install_gemfile!(google_protobuf) - bundle! "lock --add-platform=#{java}" + setup_multiplatform_gem + install_gemfile(google_protobuf) + bundle "lock --add-platform=#{java}" - expect(the_bundle.locked_gems.platforms).to eq([java, rb, pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([java, pl("x86_64-darwin-15")]) expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin @@ -111,4 +249,118 @@ end end end + + it "installs sorbet-static, which does not provide a pure ruby variant, just fine on truffleruby", :truffleruby do + build_repo2 do + build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "x86_64-linux" } + build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "universal-darwin-20" } + end + + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + + gem "sorbet-static", "0.5.6403" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + sorbet-static (0.5.6403-universal-darwin-20) + sorbet-static (0.5.6403-x86_64-linux) + + PLATFORMS + ruby + + DEPENDENCIES + sorbet-static (= 0.5.6403) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install --verbose" + end + + it "does not resolve if the current platform does not match any of available platform specific variants for a top level dependency" do + build_repo2 do + build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" } + build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" } + end + + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + + gem "sorbet-static", "0.5.6433" + G + + simulate_platform "arm64-darwin-21" do + bundle "install", :raise_on_error => false + end + + expect(err).to include <<~ERROR.rstrip + Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally. + + The source contains the following gems matching 'sorbet-static (= 0.5.6433)': + * sorbet-static-0.5.6433-universal-darwin-20 + * sorbet-static-0.5.6433-x86_64-linux + ERROR + end + + it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do + build_repo2 do + build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" } + build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" } + build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" } + end + + gemfile <<~G + source "#{file_uri_for(gem_repo2)}" + + gem "sorbet", "0.5.6433" + G + + simulate_platform "arm64-darwin-21" do + bundle "install", :raise_on_error => false + end + + expect(err).to include <<~ERROR.rstrip + Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21', which is required by gem 'sorbet (= 0.5.6433)', in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally. + + The source contains the following gems matching 'sorbet-static (= 0.5.6433)': + * sorbet-static-0.5.6433-universal-darwin-20 + * sorbet-static-0.5.6433-x86_64-linux + ERROR + end + + private + + def setup_multiplatform_gem + build_repo2 do + build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") + build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" } + build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" } + build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" } + + build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" } + build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" } + build_gem("google-protobuf", "3.0.0.alpha.5.0.5") + + build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" } + + build_gem("google-protobuf", "3.0.0.alpha.4.0") + build_gem("google-protobuf", "3.0.0.alpha.3.1.pre") + end + end + + def setup_multiplatform_gem_with_different_dependencies_per_platform + build_repo2 do + build_gem("facter", "2.4.6") + build_gem("facter", "2.4.6") do |s| + s.platform = "universal-darwin" + s.add_runtime_dependency "CFPropertyList" + end + build_gem("CFPropertyList") + end + end end diff --git a/ruby/spec/bundler/install/gemfile_spec.rb b/ruby/spec/bundler/install/gemfile_spec.rb index dd08939cb..0f8f1ecfa 100644 --- a/ruby/spec/bundler/install/gemfile_spec.rb +++ b/ruby/spec/bundler/install/gemfile_spec.rb @@ -3,7 +3,9 @@ RSpec.describe "bundle install" do context "with duplicated gems" do it "will display a warning" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" + gem 'rails', '~> 4.0.0' gem 'rails', '~> 4.0.0' G @@ -44,62 +46,52 @@ end it "uses the gemfile while in a subdirectory" do bundled_app("subdir").mkpath - Dir.chdir(bundled_app("subdir")) do - bundle "install" - bundle "list" + bundle "install", :dir => bundled_app("subdir") + bundle "list", :dir => bundled_app("subdir") - expect(out).to include("rack (1.0.0)") - end + expect(out).to include("rack (1.0.0)") end end context "with deprecated features" do - before :each do - in_app_root - end - it "reports that lib is an invalid option" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", :lib => "rack" G - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/You passed :lib as an option for gem 'rack', but it is invalid/) end end - context "with engine specified in symbol" do + context "with engine specified in symbol", :jruby do it "does not raise any error parsing Gemfile" do - simulate_ruby_version "2.3.0" do - simulate_ruby_engine "jruby", "9.1.2.0" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0" - G - - expect(out).to match(/Bundle complete!/) - end - end + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}" + G + + expect(out).to match(/Bundle complete!/) end it "installation succeeds" do - simulate_ruby_version "2.3.0" do - simulate_ruby_engine "jruby", "9.1.2.0" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0" - gem "rack" - G - - expect(the_bundle).to include_gems "rack 1.0.0" - end - end + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}" + gem "rack" + G + + expect(the_bundle).to include_gems "rack 1.0.0" end end context "with a Gemfile containing non-US-ASCII characters" do it "reads the Gemfile with the UTF-8 encoding by default" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + str = "Il était une fois ..." puts "The source encoding is: " + str.encoding.name G @@ -113,6 +105,8 @@ # NOTE: This works thanks to #eval interpreting the magic encoding comment install_gemfile <<-G # encoding: iso-8859-1 + source "#{file_uri_for(gem_repo1)}" + str = "Il #{"\xE9".dup.force_encoding("binary")}tait une fois ..." puts "The source encoding is: " + str.encoding.name G diff --git a/ruby/spec/bundler/install/gems/compact_index_spec.rb b/ruby/spec/bundler/install/gems/compact_index_spec.rb index a294b83d1..66f755c18 100644 --- a/ruby/spec/bundler/install/gems/compact_index_spec.rb +++ b/ruby/spec/bundler/install/gems/compact_index_spec.rb @@ -10,7 +10,7 @@ gem "rack" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -21,7 +21,7 @@ gem " sinatra" G - bundle :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index", :raise_on_error => false expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.") end @@ -31,7 +31,7 @@ gem "rails" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems( "rails 2.3.2", @@ -51,7 +51,7 @@ build_gem "Rack", "0.1" end - install_gemfile! <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } source "#{source_uri}" gem "rack", "1.0" gem "Rack", "0.1" @@ -59,7 +59,7 @@ # can't use `include_gems` here since the `require` will conflict on a # case-insensitive FS - run! "Bundler.require; puts Gem.loaded_specs.values_at('rack', 'Rack').map(&:full_name)" + run "Bundler.require; puts Gem.loaded_specs.values_at('rack', 'Rack').map(&:full_name)" expect(out).to eq("rack-1.0\nRack-0.1") end @@ -69,18 +69,20 @@ gem "net-sftp" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems "net-sftp 1.1.1" end - it "should use the endpoint when using --deployment" do + it "should use the endpoint when using deployment mode" do gemfile <<-G source "#{source_uri}" gem "rack" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" - bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "compact_index") + bundle "config set --local deployment true" + bundle "config set --local path vendor/bundle" + bundle :install, :artifice => "compact_index" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -98,12 +100,12 @@ end G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems("rails 2.3.2") end - it "handles git dependencies that are in rubygems using --deployment" do + it "handles git dependencies that are in rubygems using deployment mode" do build_git "foo" do |s| s.executables = "foobar" s.add_dependency "rails", "2.3.2" @@ -114,14 +116,15 @@ gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" - bundle "install --deployment", :artifice => "compact_index" + bundle "config set --local deployment true" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems("rails 2.3.2") end - it "doesn't fail if you only have a git gem with no deps when using --deployment" do + it "doesn't fail if you only have a git gem with no deps when using deployment mode" do build_git "foo" gemfile <<-G source "#{source_uri}" @@ -129,31 +132,19 @@ G bundle "install", :artifice => "compact_index" - bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "compact_index") + bundle "config set --local deployment true" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems("foo 1.0") end - it "falls back when the API errors out" do - simulate_platform mswin - - gemfile <<-G - source "#{source_uri}" - gem "rcov" - G - - bundle! :install, :artifice => "windows" - expect(out).to include("Fetching source index from #{source_uri}") - expect(the_bundle).to include_gems "rcov 1.0.0" - end - it "falls back when the API URL returns 403 Forbidden" do gemfile <<-G source "#{source_uri}" gem "rack" G - bundle! :install, :verbose => true, :artifice => "compact_index_forbidden" + bundle :install, :verbose => true, :artifice => "compact_index_forbidden" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -164,7 +155,7 @@ gem "rack" G - bundle! :install, :verbose => true, :artifice => "compact_index_checksum_mismatch" + bundle :install, :verbose => true, :artifice => "compact_index_checksum_mismatch" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(out).to include <<-'WARN' The checksum of /versions does not match the checksum provided by the server! Something is wrong (local checksum is "\"d41d8cd98f00b204e9800998ecf8427e\"", was expecting "\"123\""). @@ -180,7 +171,7 @@ gem "rack" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -191,7 +182,7 @@ gem "rack" G - bundle! :install, :artifice => "compact_index_host_redirect" + bundle :install, :artifice => "compact_index_host_redirect" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -214,7 +205,7 @@ def require(*args) H end - bundle! :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")] + bundle :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")] expect(out).to_not match(/Too many redirects/) expect(the_bundle).to include_gems "rack 1.0.0" end @@ -225,7 +216,7 @@ def require(*args) gem "rack" G - bundle :install, :artifice => "compact_index_redirects" + bundle :install, :artifice => "compact_index_redirects", :raise_on_error => false expect(err).to match(/Too many redirects/) end @@ -247,21 +238,44 @@ def require(*args) gem "rack" G - bundle! "update --full-index", :artifice => "compact_index", :all => true + bundle "update --full-index", :artifice => "compact_index", :all => true expect(out).to include("Fetching source index from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end end it "does not double check for gems that are only installed locally" do - system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0] - bundle! "config set --local path.system true" + build_repo2 do + build_gem "net_a" do |s| + s.add_dependency "net_b" + s.add_dependency "net_build_extensions" + end + + build_gem "net_b" + + build_gem "net_build_extensions" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/net_build_extensions.rb", "w") do |f| + f.puts "NET_BUILD_EXTENSIONS = 'YES'" + end + end + RUBY + end + end + + system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0], :gem_repo => gem_repo2 + bundle "config set --local path.system true" ENV["BUNDLER_SPEC_ALL_REQUESTS"] = strip_whitespace(<<-EOS).strip #{source_uri}/versions #{source_uri}/info/rack EOS - install_gemfile! <<-G, :artifice => "compact_index", :verbose => true + install_gemfile <<-G, :artifice => "compact_index", :verbose => true, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } source "#{source_uri}" gem "rack" G @@ -283,7 +297,7 @@ def require(*args) gem "back_deps" G - bundle! :install, :artifice => "compact_index_extra" + bundle :install, :artifice => "compact_index_extra" expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0" end @@ -295,7 +309,7 @@ def require(*args) FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] end - install_gemfile! <<-G, :artifice => "compact_index_extra", :verbose => true + install_gemfile <<-G, :artifice => "compact_index_extra", :verbose => true source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" @@ -310,7 +324,7 @@ def require(*args) source "#{source_uri}" gem "rack", "1.0.0" G - bundle! :install, :artifice => "compact_index_extra_api" + bundle :install, :artifice => "compact_index_extra_api" expect(the_bundle).to include_gems "rack 1.0.0" build_repo4 do @@ -324,7 +338,7 @@ def require(*args) source "#{source_uri}/extra" gem "rack", "1.2" G - bundle! :install, :artifice => "compact_index_extra_api" + bundle :install, :artifice => "compact_index_extra_api" expect(the_bundle).to include_gems "rack 1.2" end @@ -346,32 +360,7 @@ def require(*args) gem 'somegem', '1.0.0' G - bundle! :install, :artifice => "compact_index_extra_api" - - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" - end - - it "considers all possible versions of dependencies from all api gem sources when using blocks", :bundler => "< 3" do - # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that - # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0 - # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other - # repo and installs it. - build_repo4 do - build_gem "activesupport", "1.2.0" - build_gem "somegem", "1.0.0" do |s| - s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1 - end - end - - gemfile <<-G - source "#{source_uri}" - source "#{source_uri}/extra" do - gem 'somegem', '1.0.0' - end - G - - bundle! :install, :artifice => "compact_index_extra_api" + bundle :install, :artifice => "compact_index_extra_api" expect(the_bundle).to include_gems "somegem 1.0.0" expect(the_bundle).to include_gems "activesupport 1.2.3" @@ -392,7 +381,7 @@ def require(*args) end G - bundle! :install, :artifice => "compact_index_extra" + bundle :install, :artifice => "compact_index_extra" expect(out).to include("Fetching gem metadata from http://localgemserver.test/") expect(out).to include("Fetching source index from http://localgemserver.test/extra") @@ -404,22 +393,19 @@ def require(*args) s.add_dependency "foo" end build_gem "missing" - # need to hit the limit - 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i| - build_gem "gem#{i}" - end FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] end - gemfile <<-G + api_request_limit = low_api_request_limit_for(gem_repo2) + + install_gemfile <<-G, :artifice => "compact_index_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end G - bundle! :install, :artifice => "compact_index_extra_missing" expect(the_bundle).to include_gems "back_deps 1.0" end @@ -429,15 +415,13 @@ def require(*args) s.add_dependency "foo" end build_gem "missing" - # need to hit the limit - 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i| - build_gem "gem#{i}" - end FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")] end - install_gemfile! <<-G, :artifice => "compact_index_extra_api_missing" + api_request_limit = low_api_request_limit_for(gem_repo4) + + install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" @@ -454,11 +438,11 @@ def require(*args) gem 'foo' G - bundle! :install, :artifice => "compact_index_api_missing" + bundle :install, :artifice => "compact_index_api_missing" expect(the_bundle).to include_gems "foo 1.0" end - it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -472,13 +456,13 @@ def require(*args) gem "back_deps" G - bundle! :install, :artifice => "compact_index_extra" - - bundle "install --deployment", :artifice => "compact_index_extra" + bundle :install, :artifice => "compact_index_extra" + bundle "config --set local deployment true" + bundle :install, :artifice => "compact_index_extra" expect(the_bundle).to include_gems "back_deps 1.0" end - it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -493,20 +477,26 @@ def require(*args) end G - bundle! :install, :artifice => "compact_index_extra" - - bundle "install --deployment", :artifice => "compact_index_extra" + bundle :install, :artifice => "compact_index_extra" + bundle "config set --local deployment true" + bundle :install, :artifice => "compact_index_extra" expect(the_bundle).to include_gems "back_deps 1.0" end it "does not refetch if the only unmet dependency is bundler" do + build_repo2 do + build_gem "bundler_dep" do |s| + s.add_dependency "bundler" + end + end + gemfile <<-G source "#{source_uri}" gem "bundler_dep" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(out).to include("Fetching gem metadata from #{source_uri}") end @@ -518,7 +508,7 @@ def require(*args) source "#{source_uri}" gem "rails" G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(the_bundle).to include_gems "rails 2.3.2" end @@ -562,7 +552,7 @@ def require(*args) gem 'rack-obama' G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(out).to include("Post-install message from rack:") end @@ -572,7 +562,7 @@ def require(*args) gem 'rack_middleware' G - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expect(out).to include("Post-install message from rack:") expect(out).to include("Rack's post install message") end @@ -581,7 +571,7 @@ def require(*args) let(:user) { "user" } let(:password) { "pass" } let(:basic_auth_source_uri) do - uri = URI.parse(source_uri) + uri = Bundler::URI.parse(source_uri) uri.user = user uri.password = password @@ -594,32 +584,22 @@ def require(*args) gem "rack" G - bundle! :install, :artifice => "compact_index_basic_authentication" + bundle :install, :artifice => "compact_index_basic_authentication" expect(out).not_to include("#{user}:#{password}") expect(the_bundle).to include_gems "rack 1.0.0" end - it "strips http basic authentication creds for modern index" do + it "passes basic authentication details and strips out creds also in verbose mode" do gemfile <<-G source "#{basic_auth_source_uri}" gem "rack" G - bundle! :install, :artifice => "endopint_marshal_fail_basic_authentication" + bundle :install, :verbose => true, :artifice => "compact_index_basic_authentication" expect(out).not_to include("#{user}:#{password}") expect(the_bundle).to include_gems "rack 1.0.0" end - it "strips http basic auth creds when it can't reach the server" do - gemfile <<-G - source "#{basic_auth_source_uri}" - gem "rack" - G - - bundle :install, :artifice => "endpoint_500" - expect(out).not_to include("#{user}:#{password}") - end - it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do gemfile <<-G source "#{basic_auth_source_uri}" @@ -627,7 +607,7 @@ def require(*args) gem "rack" G - bundle! :install, :artifice => "compact_index_basic_authentication" + bundle :install, :artifice => "compact_index_basic_authentication" expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).not_to include("#{user}:#{password}") expect(the_bundle).to include_gems "rack 1.0.0" @@ -639,7 +619,7 @@ def require(*args) gem "rack" G - bundle! :install, :artifice => "compact_index_creds_diff_host" + bundle :install, :artifice => "compact_index_creds_diff_host" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -654,7 +634,7 @@ def require(*args) it "reads authentication details by host name from bundle config" do bundle "config set #{source_hostname} #{user}:#{password}" - bundle! :install, :artifice => "compact_index_strict_basic_authentication" + bundle :install, :artifice => "compact_index_strict_basic_authentication" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" @@ -664,7 +644,7 @@ def require(*args) # The trailing slash is necessary here; Fetcher canonicalizes the URI. bundle "config set #{source_uri}/ #{user}:#{password}" - bundle! :install, :artifice => "compact_index_strict_basic_authentication" + bundle :install, :artifice => "compact_index_strict_basic_authentication" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" @@ -672,7 +652,7 @@ def require(*args) it "should use the API" do bundle "config set #{source_hostname} #{user}:#{password}" - bundle! :install, :artifice => "compact_index_strict_basic_authentication" + bundle :install, :artifice => "compact_index_strict_basic_authentication" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -685,19 +665,19 @@ def require(*args) bundle "config set #{source_hostname} otheruser:wrong" - bundle! :install, :artifice => "compact_index_strict_basic_authentication" + bundle :install, :artifice => "compact_index_strict_basic_authentication" expect(the_bundle).to include_gems "rack 1.0.0" end it "shows instructions if auth is not provided for the source" do - bundle :install, :artifice => "compact_index_strict_basic_authentication" - expect(err).to include("bundle config set #{source_hostname} username:password") + bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false + expect(err).to include("bundle config set --global #{source_hostname} username:password") end it "fails if authentication has already been provided, but failed" do bundle "config set #{source_hostname} #{user}:wrong" - bundle :install, :artifice => "compact_index_strict_basic_authentication" + bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false expect(err).to include("Bad username or password") end end @@ -711,7 +691,7 @@ def require(*args) gem "rack" G - bundle! :install, :artifice => "compact_index_basic_authentication" + bundle :install, :artifice => "compact_index_basic_authentication" expect(the_bundle).to include_gems "rack 1.0.0" end end @@ -736,7 +716,7 @@ def require(*args) gem "rack" G - bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" } + bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false expect(err).to include("OpenSSL") end end @@ -756,40 +736,40 @@ def start gem "rack" G - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/could not verify the SSL certificate/i) end end context ".gemrc with sources is present" do - before do + it "uses other sources declared in the Gemfile" do File.open(home(".gemrc"), "w") do |file| file.puts({ :sources => ["https://rubygems.org"] }.to_yaml) end - end - after do - home(".gemrc").rmtree - end - - it "uses other sources declared in the Gemfile" do - gemfile <<-G - source "#{source_uri}" - gem 'rack' - G + begin + gemfile <<-G + source "#{source_uri}" + gem 'rack' + G - bundle! :install, :artifice => "compact_index_forbidden" + bundle :install, :artifice => "compact_index_forbidden" + ensure + home(".gemrc").rmtree + end end end it "performs partial update with a non-empty range" do + skip "HTTP_RANGE not set" if Gem.win_platform? + gemfile <<-G source "#{source_uri}" gem 'rack', '0.9.1' G # Initial install creates the cached versions file - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" # Update the Gemfile so we can check subsequent install was successful gemfile <<-G @@ -798,7 +778,7 @@ def start G # Second install should make only a partial request to /versions - bundle! :install, :artifice => "compact_index_partial_update" + bundle :install, :artifice => "compact_index_partial_update" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -815,12 +795,34 @@ def start FileUtils.mkdir_p(File.dirname(versions)) FileUtils.touch(versions) - bundle! :install, :artifice => "compact_index_concurrent_download" + bundle :install, :artifice => "compact_index_concurrent_download" expect(File.read(versions)).to start_with("created_at") expect(the_bundle).to include_gems "rack 1.0.0" end + it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no Etag" do + build_repo4 do + build_gem "rack", "0.9.1" + end + + install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + source "#{source_uri}" + gem 'rack', '0.9.1' + G + + update_repo4 do + build_gem "rack", "1.0.0" + end + + install_gemfile <<-G, :artifice => "compact_index_partial_update_no_etag_not_incremental", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + source "#{source_uri}" + gem 'rack', '1.0.0' + G + + expect(the_bundle).to include_gems "rack 1.0.0" + end + it "performs full update of compact index info cache if range is not satisfiable" do gemfile <<-G source "#{source_uri}" @@ -830,7 +832,7 @@ def start rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack") - bundle! :install, :artifice => "compact_index" + bundle :install, :artifice => "compact_index" expected_rack_info_content = File.read(rake_info_path) @@ -845,7 +847,7 @@ def start # The cache files now being longer means the requested range is going to be not satisfiable # Bundler must end up requesting the whole file to fix things up. - bundle! :install, :artifice => "compact_index_range_not_satisfiable" + bundle :install, :artifice => "compact_index_range_not_satisfiable" resulting_rack_info_content = File.read(rake_info_path) @@ -853,11 +855,11 @@ def start end it "fails gracefully when the source URI has an invalid scheme" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "htps://rubygems.org" gem "rack" G - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) expect(err).to end_with(<<-E.strip) The request uri `htps://index.rubygems.org/versions` has an invalid scheme (`htps`). Did you mean `http` or `https`? E @@ -865,12 +867,12 @@ def start describe "checksum validation" do it "raises when the checksum does not match" do - install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum" + install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :raise_on_error => false source "#{source_uri}" gem "rack" G - expect(exitstatus).to eq(19) if exitstatus + expect(exitstatus).to eq(19) expect(err). to include("Bundler cannot continue installing rack (1.0.0)."). and include("The checksum for the downloaded `rack-1.0.0.gem` does not match the checksum given by the server."). @@ -879,23 +881,23 @@ def start and include("1. delete the downloaded gem located at: `#{default_bundle_path}/gems/rack-1.0.0/rack-1.0.0.gem`"). and include("2. run `bundle install`"). and include("If you wish to continue installing the downloaded gem, and are certain it does not pose a security issue despite the mismatching checksum, do the following:"). - and include("1. run `bundle config set disable_checksum_validation true` to turn off checksum verification"). + and include("1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification"). and include("2. run `bundle install`"). and match(/\(More info: The expected SHA256 checksum was "#{"ab" * 22}", but the checksum for the downloaded gem was ".+?"\.\)/) end it "raises when the checksum is the wrong length" do - install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!" } + install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, :verbose => true, :raise_on_error => false source "#{source_uri}" gem "rack" G - expect(exitstatus).to eq(5) if exitstatus + expect(exitstatus).to eq(5) expect(err).to include("The given checksum for rack-1.0.0 (\"checksum!\") is not a valid SHA256 hexdigest nor base64digest") end it "does not raise when disable_checksum_validation is set" do - bundle! "config set disable_checksum_validation true" - install_gemfile! <<-G, :artifice => "compact_index_wrong_gem_checksum" + bundle "config set disable_checksum_validation true" + install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum" source "#{source_uri}" gem "rack" G @@ -903,7 +905,7 @@ def start end it "works when cache dir is world-writable" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" File.umask(0000) source "#{source_uri}" gem "rack" @@ -911,30 +913,32 @@ def start end it "doesn't explode when the API dependencies are wrong" do - install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" } + install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" }, :raise_on_error => false source "#{source_uri}" gem "rails" G - deps = [Gem::Dependency.new("rake", "= 12.3.2"), + deps = [Gem::Dependency.new("rake", "= 13.0.1"), Gem::Dependency.new("actionpack", "= 2.3.2"), Gem::Dependency.new("activerecord", "= 2.3.2"), Gem::Dependency.new("actionmailer", "= 2.3.2"), Gem::Dependency.new("activeresource", "= 2.3.2")] - expect(out).to include(<<-E.strip).and include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies") + expect(out).to include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies") + expect(err).to include(<<-E.strip) Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API or the lockfile (#{deps.map(&:to_s).join(", ")}). Either installing with `--full-index` or running `bundle update rails` should fix the problem. E end it "does not duplicate specs in the lockfile when updating and a dependency is not installed" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" + source "#{file_uri_for(gem_repo1)}" source "#{source_uri}" do gem "rails" gem "activemerchant" end G - gem_command! :uninstall, "activemerchant" - bundle! "update rails", :artifice => "compact_index" + gem_command "uninstall activemerchant" + bundle "update rails", :artifice => "compact_index" expect(lockfile.scan(/activemerchant \(/).size).to eq(1) end end diff --git a/ruby/spec/bundler/install/gems/dependency_api_spec.rb b/ruby/spec/bundler/install/gems/dependency_api_spec.rb index a8713eb44..79317a7fa 100644 --- a/ruby/spec/bundler/install/gems/dependency_api_spec.rb +++ b/ruby/spec/bundler/install/gems/dependency_api_spec.rb @@ -21,7 +21,7 @@ gem " sinatra" G - bundle :install, :artifice => "endpoint" + bundle :install, :artifice => "endpoint", :raise_on_error => false expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.") end @@ -53,14 +53,16 @@ expect(the_bundle).to include_gems "net-sftp 1.1.1" end - it "should use the endpoint when using --deployment" do + it "should use the endpoint when using deployment mode" do gemfile <<-G source "#{source_uri}" gem "rack" G bundle :install, :artifice => "endpoint" - bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "endpoint") + bundle "config set --local deployment true" + bundle "config set --local path vendor/bundle" + bundle :install, :artifice => "endpoint" expect(out).to include("Fetching gem metadata from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -83,7 +85,7 @@ expect(the_bundle).to include_gems("rails 2.3.2") end - it "handles git dependencies that are in rubygems using --deployment" do + it "handles git dependencies that are in rubygems using deployment mode" do build_git "foo" do |s| s.executables = "foobar" s.add_dependency "rails", "2.3.2" @@ -96,12 +98,13 @@ bundle :install, :artifice => "endpoint" - bundle "install --deployment", :artifice => "endpoint" + bundle "config set --local deployment true" + bundle :install, :artifice => "endpoint" expect(the_bundle).to include_gems("rails 2.3.2") end - it "doesn't fail if you only have a git gem with no deps when using --deployment" do + it "doesn't fail if you only have a git gem with no deps when using deployment mode" do build_git "foo" gemfile <<-G source "#{source_uri}" @@ -109,7 +112,8 @@ G bundle "install", :artifice => "endpoint" - bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint") + bundle "config set --local deployment true" + bundle :install, :artifice => "endpoint" expect(the_bundle).to include_gems("foo 1.0") end @@ -117,12 +121,20 @@ it "falls back when the API errors out" do simulate_platform mswin + build_repo2 do + # The rcov gem is platform mswin32, but has no arch + build_gem "rcov" do |s| + s.platform = Gem::Platform.new([nil, "mswin32", nil]) + s.write "lib/rcov.rb", "RCOV = '1.0.0'" + end + end + gemfile <<-G source "#{source_uri}" gem "rcov" G - bundle :install, :artifice => "windows" + bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(out).to include("Fetching source index from #{source_uri}") expect(the_bundle).to include_gems "rcov 1.0.0" end @@ -215,7 +227,7 @@ def require(*args) gem "rack" G - bundle :install, :artifice => "endpoint_redirect" + bundle :install, :artifice => "endpoint_redirect", :raise_on_error => false expect(err).to match(/Too many redirects/) end @@ -237,7 +249,7 @@ def require(*args) gem "rack" G - bundle! "update --full-index", :artifice => "endpoint", :all => true + bundle "update --full-index", :artifice => "endpoint", :all => true expect(out).to include("Fetching source index from #{source_uri}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -320,31 +332,6 @@ def require(*args) gem 'somegem', '1.0.0' G - bundle! :install, :artifice => "endpoint_extra_api" - - expect(the_bundle).to include_gems "somegem 1.0.0" - expect(the_bundle).to include_gems "activesupport 1.2.3" - end - - it "considers all possible versions of dependencies from all api gem sources using blocks" do - # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that - # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0 - # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other - # repo and installs it. - build_repo4 do - build_gem "activesupport", "1.2.0" - build_gem "somegem", "1.0.0" do |s| - s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1 - end - end - - gemfile <<-G - source "#{source_uri}" - source "#{source_uri}/extra" do - gem 'somegem', '1.0.0' - end - G - bundle :install, :artifice => "endpoint_extra_api" expect(the_bundle).to include_gems "somegem 1.0.0" @@ -378,21 +365,18 @@ def require(*args) s.add_dependency "foo" end build_gem "missing" - # need to hit the limit - 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i| - build_gem "gem#{i}" - end FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] end - gemfile <<-G + api_request_limit = low_api_request_limit_for(gem_repo2) + + install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" gem "back_deps" G - bundle :install, :artifice => "endpoint_extra_missing" expect(the_bundle).to include_gems "back_deps 1.0" end @@ -402,37 +386,23 @@ def require(*args) s.add_dependency "foo" end build_gem "missing" - # need to hit the limit - 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i| - build_gem "gem#{i}" - end FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")] end - gemfile <<-G + api_request_limit = low_api_request_limit_for(gem_repo2) + + install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) source "#{source_uri}" source "#{source_uri}/extra" do gem "back_deps" end G - bundle :install, :artifice => "endpoint_extra_missing" expect(the_bundle).to include_gems "back_deps 1.0" end - it "uses the endpoint if all sources support it" do - gemfile <<-G - source "#{source_uri}" - - gem 'foo' - G - - bundle :install, :artifice => "endpoint_api_missing" - expect(the_bundle).to include_gems "foo 1.0" - end - - it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -447,12 +417,12 @@ def require(*args) G bundle :install, :artifice => "endpoint_extra" - - bundle "install --deployment", :artifice => "endpoint_extra" + bundle "config set --local deployment true" + bundle :install, :artifice => "endpoint_extra" expect(the_bundle).to include_gems "back_deps 1.0" end - it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do + it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -468,19 +438,25 @@ def require(*args) G bundle :install, :artifice => "endpoint_extra" - - bundle "install --deployment", :artifice => "endpoint_extra" + bundle "config set --local deployment true" + bundle "install", :artifice => "endpoint_extra" expect(the_bundle).to include_gems "back_deps 1.0" end it "does not refetch if the only unmet dependency is bundler" do + build_repo2 do + build_gem "bundler_dep" do |s| + s.add_dependency "bundler" + end + end + gemfile <<-G source "#{source_uri}" gem "bundler_dep" G - bundle :install, :artifice => "endpoint" + bundle :install, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } expect(out).to include("Fetching gem metadata from #{source_uri}") end @@ -555,7 +531,7 @@ def require(*args) let(:user) { "user" } let(:password) { "pass" } let(:basic_auth_source_uri) do - uri = URI.parse(source_uri) + uri = Bundler::URI.parse(source_uri) uri.user = user uri.password = password @@ -573,13 +549,24 @@ def require(*args) expect(the_bundle).to include_gems "rack 1.0.0" end + it "passes basic authentication details and strips out creds also in verbose mode" do + gemfile <<-G + source "#{basic_auth_source_uri}" + gem "rack" + G + + bundle :install, :verbose => true, :artifice => "endpoint_basic_authentication" + expect(out).not_to include("#{user}:#{password}") + expect(the_bundle).to include_gems "rack 1.0.0" + end + it "strips http basic authentication creds for modern index" do gemfile <<-G source "#{basic_auth_source_uri}" gem "rack" G - bundle :install, :artifice => "endopint_marshal_fail_basic_authentication" + bundle :install, :artifice => "endpoint_marshal_fail_basic_authentication" expect(out).not_to include("#{user}:#{password}") expect(the_bundle).to include_gems "rack 1.0.0" end @@ -590,7 +577,7 @@ def require(*args) gem "rack" G - bundle :install, :artifice => "endpoint_500" + bundle :install, :artifice => "endpoint_500", :raise_on_error => false expect(out).not_to include("#{user}:#{password}") end @@ -617,6 +604,22 @@ def require(*args) expect(the_bundle).to include_gems "rack 1.0.0" end + describe "with host including dashes" do + before do + gemfile <<-G + source "http://local-gemserver.test" + gem "rack" + G + end + + it "reads authentication details from a valid ENV variable" do + bundle :install, :artifice => "endpoint_strict_basic_authentication", :env => { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" } + + expect(out).to include("Fetching gem metadata from http://local-gemserver.test") + expect(the_bundle).to include_gems "rack 1.0.0" + end + end + describe "with authentication details in bundle config" do before do gemfile <<-G @@ -664,14 +667,14 @@ def require(*args) end it "shows instructions if auth is not provided for the source" do - bundle :install, :artifice => "endpoint_strict_basic_authentication" - expect(err).to include("bundle config set #{source_hostname} username:password") + bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false + expect(err).to include("bundle config set --global #{source_hostname} username:password") end it "fails if authentication has already been provided, but failed" do bundle "config set #{source_hostname} #{user}:wrong" - bundle :install, :artifice => "endpoint_strict_basic_authentication" + bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false expect(err).to include("Bad username or password") end end @@ -710,7 +713,7 @@ def require(*args) gem "rack" G - bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" } + bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false expect(err).to include("OpenSSL") end end @@ -730,31 +733,27 @@ def start gem "rack" G - bundle :install + bundle :install, :raise_on_error => false expect(err).to match(/could not verify the SSL certificate/i) end end context ".gemrc with sources is present" do - before do + it "uses other sources declared in the Gemfile" do File.open(home(".gemrc"), "w") do |file| file.puts({ :sources => ["https://rubygems.org"] }.to_yaml) end - end - after do - home(".gemrc").rmtree - end - - it "uses other sources declared in the Gemfile" do - gemfile <<-G - source "#{source_uri}" - gem 'rack' - G - - bundle "install", :artifice => "endpoint_marshal_fail" + begin + gemfile <<-G + source "#{source_uri}" + gem 'rack' + G - expect(exitstatus).to eq(0) if exitstatus + bundle "install", :artifice => "endpoint_marshal_fail" + ensure + home(".gemrc").rmtree + end end end end diff --git a/ruby/spec/bundler/install/gems/flex_spec.rb b/ruby/spec/bundler/install/gems/flex_spec.rb index 865bc7b72..f9b374cf0 100644 --- a/ruby/spec/bundler/install/gems/flex_spec.rb +++ b/ruby/spec/bundler/install/gems/flex_spec.rb @@ -166,8 +166,7 @@ expect(the_bundle).to include_gems "rack_middleware 1.0", "rack 0.9.1" - build_repo2 - update_repo2 do + build_repo2 do build_gem "rack-obama", "2.0" do |s| s.add_dependency "rack", "=1.2" end @@ -184,8 +183,8 @@ end it "does not install gems whose dependencies are not met" do - bundle :install - ruby <<-RUBY + bundle :install, :raise_on_error => false + ruby <<-RUBY, :raise_on_error => false require 'bundler/setup' RUBY expect(err).to match(/could not find gem 'rack-obama/i) @@ -210,7 +209,7 @@ the gems in your Gemfile, which may resolve the conflict. E - bundle :install, :retry => 0 + bundle :install, :retry => 0, :raise_on_error => false expect(err).to end_with(nice_error) end end @@ -230,14 +229,27 @@ G end - it "does something" do - expect do - bundle "install" - end.not_to change { File.read(bundled_app("Gemfile.lock")) } + it "should work when you install" do + bundle "install" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + rack-obama (1.0) + rack - expect(err).to include("rack = 0.9.1") - expect(err).to include("locked at 1.0.0") - expect(err).to include("bundle update rack") + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack (= 0.9.1) + rack-obama + + BUNDLED WITH + #{Bundler::VERSION} + L end it "should work when you update" do @@ -246,68 +258,38 @@ end describe "when adding a new source" do - it "updates the lockfile", :bundler => "< 3" do - build_repo2 - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - G - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo2)}" - gem "rack" - G - - lockfile_should_be <<-L - GEM - remote: #{file_uri_for(gem_repo1)}/ - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "updates the lockfile", :bundler => "3" do + it "updates the lockfile" do build_repo2 - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo2)}" do end gem "rack" G - lockfile_should_be <<-L - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - rack (1.0.0) + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (1.0.0) - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: - PLATFORMS - #{lockfile_platforms} + PLATFORMS + #{lockfile_platforms} - DEPENDENCIES - rack + DEPENDENCIES + rack - BUNDLED WITH - #{Bundler::VERSION} + BUNDLED WITH + #{Bundler::VERSION} L end end @@ -341,7 +323,7 @@ G # upgrade Rails to 3.0.0 and then install again - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "rails", "3.0.0" gem "capybara", "0.3.9" diff --git a/ruby/spec/bundler/install/gems/fund_spec.rb b/ruby/spec/bundler/install/gems/fund_spec.rb new file mode 100644 index 000000000..f521b0296 --- /dev/null +++ b/ruby/spec/bundler/install/gems/fund_spec.rb @@ -0,0 +1,137 @@ +# frozen_string_literal: true + +RSpec.describe "bundle install" do + context "with gem sources" do + before do + build_repo2 do + build_gem "has_funding_and_other_metadata" do |s| + s.metadata = { + "bug_tracker_uri" => "https://example.com/user/bestgemever/issues", + "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md", + "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1", + "homepage_uri" => "https://bestgemever.example.io", + "mailing_list_uri" => "https://groups.example.com/bestgemever", + "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding", + "source_code_uri" => "https://example.com/user/bestgemever", + "wiki_uri" => "https://example.com/user/bestgemever/wiki", + } + end + + build_gem "has_funding", "1.2.3" do |s| + s.metadata = { + "funding_uri" => "https://example.com/has_funding/funding", + } + end + + build_gem "gem_with_dependent_funding", "1.0" do |s| + s.add_dependency "has_funding" + end + end + end + + context "when gems include a fund URI" do + it "displays the plural fund message after installing" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding_and_other_metadata' + gem 'has_funding' + gem 'rack-obama' + G + + expect(out).to include("2 installed gems you directly depend on are looking for funding.") + end + + it "displays the singular fund message after installing" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding' + gem 'rack-obama' + G + + expect(out).to include("1 installed gem you directly depend on is looking for funding.") + end + end + + context "when gems do not include fund messages" do + it "does not display any fund messages" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + G + + expect(out).not_to include("gem you depend on") + end + end + + context "when a dependency includes a fund message" do + it "does not display the fund message" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'gem_with_dependent_funding' + G + + expect(out).not_to include("gem you depend on") + end + end + end + + context "with git sources" do + context "when gems include fund URI" do + it "displays the fund message after installing" do + build_git "also_has_funding" do |s| + s.metadata = { + "funding_uri" => "https://example.com/also_has_funding/funding", + } + end + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}' + G + + expect(out).to include("1 installed gem you directly depend on is looking for funding.") + end + + it "displays the fund message if repo is updated" do + build_git "also_has_funding" do |s| + s.metadata = { + "funding_uri" => "https://example.com/also_has_funding/funding", + } + end + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}' + G + + build_git "also_has_funding", "1.1" do |s| + s.metadata = { + "funding_uri" => "https://example.com/also_has_funding/funding", + } + end + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.1")}' + G + + expect(out).to include("1 installed gem you directly depend on is looking for funding.") + end + + it "displays the fund message if repo is not updated" do + build_git "also_has_funding" do |s| + s.metadata = { + "funding_uri" => "https://example.com/also_has_funding/funding", + } + end + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}' + G + + bundle :install + expect(out).to include("1 installed gem you directly depend on is looking for funding.") + + bundle :install + expect(out).to include("1 installed gem you directly depend on is looking for funding.") + end + end + end +end diff --git a/ruby/spec/bundler/install/gems/native_extensions_spec.rb b/ruby/spec/bundler/install/gems/native_extensions_spec.rb index 3e59a3ceb..d5cafcfc2 100644 --- a/ruby/spec/bundler/install/gems/native_extensions_spec.rb +++ b/ruby/spec/bundler/install/gems/native_extensions_spec.rb @@ -40,7 +40,6 @@ bundle "config set build.c_extension --with-c_extension=hello" bundle "install" - expect(out).not_to include("extconf.rb failed") expect(out).to include("Installing c_extension 1.0 with native extensions") run "Bundler.require; puts CExtension.new.its_true" @@ -76,18 +75,73 @@ C end - bundle! "config set build.c_extension --with-c_extension=hello" + bundle "config set build.c_extension --with-c_extension=hello" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump} G - expect(out).not_to include("extconf.rb failed") + expect(err).to_not include("warning: conflicting chdir during another chdir block") - run! "Bundler.require; puts CExtension.new.its_true" + run "Bundler.require; puts CExtension.new.its_true" expect(out).to eq("true") end + it "installs correctly from git when multiple gems with extensions share one repository" do + build_repo2 do + ["one", "two"].each do |n| + build_lib "c_extension_#{n}", "1.0", :path => lib_path("gems/c_extension_#{n}") do |s| + s.extensions = ["ext/extconf.rb"] + s.write "ext/extconf.rb", <<-E + require "mkmf" + name = "c_extension_bundle_#{n}" + dir_config(name) + raise "OMG" unless with_config("c_extension_#{n}") == "#{n}" + create_makefile(name) + E + + s.write "ext/c_extension_#{n}.c", <<-C + #include "ruby.h" + + VALUE c_extension_#{n}_value(VALUE self) { + return rb_str_new_cstr("#{n}"); + } + + void Init_c_extension_bundle_#{n}() { + VALUE c_Extension = rb_define_class("CExtension_#{n}", rb_cObject); + rb_define_method(c_Extension, "value", c_extension_#{n}_value, 0); + } + C + + s.write "lib/c_extension_#{n}.rb", <<-C + require "c_extension_bundle_#{n}" + C + end + end + build_git "gems", :path => lib_path("gems"), :gemspec => false + end + + bundle "config set build.c_extension_one --with-c_extension_one=one" + bundle "config set build.c_extension_two --with-c_extension_two=two" + + # 1st time, require only one gem -- only one of the extensions gets built. + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "c_extension_one", :git => #{lib_path("gems").to_s.dump} + G + + # 2nd time, require both gems -- we need both extensions to be built now. + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "c_extension_one", :git => #{lib_path("gems").to_s.dump} + gem "c_extension_two", :git => #{lib_path("gems").to_s.dump} + G + + run "Bundler.require; puts CExtension_one.new.value; puts CExtension_two.new.value" + expect(out).to eq("one\ntwo") + end + it "install with multiple build flags" do build_git "c_extension" do |s| s.extensions = ["ext/extconf.rb"] @@ -117,15 +171,14 @@ C end - bundle! "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola" + bundle "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump} G - expect(out).not_to include("extconf.rb failed") - - run! "Bundler.require; puts CExtension.new.its_true" + run "Bundler.require; puts CExtension.new.its_true" expect(out).to eq("true") end end diff --git a/ruby/spec/bundler/install/gems/post_install_spec.rb b/ruby/spec/bundler/install/gems/post_install_spec.rb index 3f6d7ce42..7426f5487 100644 --- a/ruby/spec/bundler/install/gems/post_install_spec.rb +++ b/ruby/spec/bundler/install/gems/post_install_spec.rb @@ -33,7 +33,7 @@ end end - context "when a dependecy includes a post install message" do + context "when a dependency includes a post install message" do it "should display the post install message" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" diff --git a/ruby/spec/bundler/install/gems/resolving_spec.rb b/ruby/spec/bundler/install/gems/resolving_spec.rb index 52511ff67..b0209489b 100644 --- a/ruby/spec/bundler/install/gems/resolving_spec.rb +++ b/ruby/spec/bundler/install/gems/resolving_spec.rb @@ -1,9 +1,72 @@ # frozen_string_literal: true RSpec.describe "bundle install with install-time dependencies" do + before do + build_repo2 do + build_gem "with_implicit_rake_dep" do |s| + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/implicit_rake_dep.rb", "w") do |f| + f.puts "IMPLICIT_RAKE_DEP = 'YES'" + end + end + RUBY + end + + build_gem "another_implicit_rake_dep" do |s| + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f| + f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'" + end + end + RUBY + end + + # Test complicated gem dependencies for install + build_gem "net_a" do |s| + s.add_dependency "net_b" + s.add_dependency "net_build_extensions" + end + + build_gem "net_b" + + build_gem "net_build_extensions" do |s| + s.add_dependency "rake" + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/net_build_extensions.rb", "w") do |f| + f.puts "NET_BUILD_EXTENSIONS = 'YES'" + end + end + RUBY + end + + build_gem "net_c" do |s| + s.add_dependency "net_a" + s.add_dependency "net_d" + end + + build_gem "net_d" + + build_gem "net_e" do |s| + s.add_dependency "net_d" + end + end + end + it "installs gems with implicit rake dependencies" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "with_implicit_rake_dep" gem "another_implicit_rake_dep" gem "rake" @@ -18,6 +81,25 @@ expect(out).to eq("YES\nYES") end + it "installs gems with implicit rake dependencies without rake previously installed" do + with_path_as("") do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "with_implicit_rake_dep" + gem "another_implicit_rake_dep" + gem "rake" + G + end + + run <<-R + require 'implicit_rake_dep' + require 'another_implicit_rake_dep' + puts IMPLICIT_RAKE_DEP + puts ANOTHER_IMPLICIT_RAKE_DEP + R + expect(out).to eq("YES\nYES") + end + it "installs gems with a dependency with no type" do build_repo2 @@ -26,7 +108,7 @@ spec.dependencies.each do |d| d.instance_variable_set(:@type, :fail) end - File.open(path, "w") do |f| + File.open(path, "wb") do |f| f.write Gem.deflate(Marshal.dump(spec)) end @@ -41,7 +123,7 @@ describe "with crazy rubygem plugin stuff" do it "installs plugins" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "net_b" G @@ -49,8 +131,8 @@ end it "installs plugins depended on by other plugins" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :env => { "DEBUG" => "1" } + source "#{file_uri_for(gem_repo2)}" gem "net_a" G @@ -58,8 +140,8 @@ end it "installs multiple levels of dependencies" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :env => { "DEBUG" => "1" } + source "#{file_uri_for(gem_repo2)}" gem "net_c" gem "net_e" G @@ -67,34 +149,54 @@ expect(the_bundle).to include_gems "net_a 1.0", "net_b 1.0", "net_c 1.0", "net_d 1.0", "net_e 1.0" end + context "with ENV['BUNDLER_DEBUG_RESOLVER'] set" do + it "produces debug output" do + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "net_c" + gem "net_e" + G + + bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" } + + expect(out).to include("BUNDLER: Starting resolution") + end + end + context "with ENV['DEBUG_RESOLVER'] set" do it "produces debug output" do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "net_c" gem "net_e" G - bundle :install, :env => { "DEBUG_RESOLVER" => "1" } + bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" } - expect(err).to include("Creating possibility state for net_c") + expect(out).to include("BUNDLER: Starting resolution") end end context "with ENV['DEBUG_RESOLVER_TREE'] set" do it "produces debug output" do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "net_c" gem "net_e" G - bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1" } + bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" } + + activated_groups = if local_platforms.any? + "net_b (1.0) (ruby), net_b (1.0) (#{local_platforms.join(", ")})" + else + "net_b (1.0) (ruby)" + end - expect(err).to include(" net_b"). - and include("Starting resolution"). - and include("Finished resolution"). - and include("Attempting to activate") + expect(out).to include(" net_b"). + and include("BUNDLER: Starting resolution"). + and include("BUNDLER: Finished resolution"). + and include("Attempting to activate [#{activated_groups}]") end end end @@ -103,6 +205,10 @@ context "allows only an older version" do it "installs the older version" do build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "rack", "9001.0.0" do |s| s.required_ruby_version = "> 9000" end @@ -118,6 +224,27 @@ expect(the_bundle).to include_gems("rack 1.2") end + it "installs the older version when using servers not implementing the compact index API" do + build_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + + build_gem "rack", "9001.0.0" do |s| + s.required_ruby_version = "> 9000" + end + end + + install_gemfile <<-G, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + ruby "#{RUBY_VERSION}" + source "http://localgemserver.test/" + gem 'rack' + G + + expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000") + expect(the_bundle).to include_gems("rack 1.2") + end + it "installs the older version under rate limiting conditions" do build_repo4 do build_gem "rack", "9001.0.0" do |s| @@ -137,6 +264,31 @@ expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000") expect(the_bundle).to include_gems("rack 1.2") end + + it "installs the older not platform specific version" do + build_repo4 do + build_gem "rack", "9001.0.0" do |s| + s.required_ruby_version = "> 9000" + end + build_gem "rack", "1.2" do |s| + s.platform = mingw + s.required_ruby_version = "> 9000" + end + build_gem "rack", "1.2" + end + + simulate_platform mingw do + install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + ruby "#{RUBY_VERSION}" + source "http://localgemserver.test/" + gem 'rack' + G + end + + expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000") + expect(out).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000") + expect(the_bundle).to include_gems("rack 1.2") + end end context "allows no gems" do @@ -153,7 +305,7 @@ shared_examples_for "ruby version conflicts" do it "raises an error during resolution" do - install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } + install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false source "http://localgemserver.test/" ruby #{ruby_requirement} gem 'require_ruby' @@ -168,8 +320,6 @@ require_ruby was resolved to 1.0, which depends on Ruby\0 (> 9000) - - Ruby\0 (> 9000), which is required by gem 'require_ruby', is not available in the local ruby installation E expect(err).to end_with(nice_error) end @@ -202,13 +352,21 @@ end end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem 'require_rubygems' G expect(err).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000") - expect(err).to include("require_rubygems-1.0 requires rubygems version > 9000, which is incompatible with the current version, #{Gem::VERSION}") + nice_error = strip_whitespace(<<-E).strip + Bundler found conflicting requirements for the RubyGems\0 version: + In Gemfile: + RubyGems\0 (= #{Gem::VERSION}) + + require_rubygems was resolved to 1.0, which depends on + RubyGems\0 (> 9000) + E + expect(err).to end_with(nice_error) end end end diff --git a/ruby/spec/bundler/install/gems/standalone_spec.rb b/ruby/spec/bundler/install/gems/standalone_spec.rb index f1d5c8b50..c7efc836a 100644 --- a/ruby/spec/bundler/install/gems/standalone_spec.rb +++ b/ruby/spec/bundler/install/gems/standalone_spec.rb @@ -7,6 +7,12 @@ expect(the_bundle).to include_gems(*args) end + it "still makes system gems unavailable to normal bundler" do + system_gems "rack-1.0.0" + + expect(the_bundle).to_not include_gems("rack") + end + it "generates a bundle/bundler/setup.rb" do expect(bundled_app("bundle/bundler/setup.rb")).to exist end @@ -21,15 +27,51 @@ testrb << "\nrequire \"#{k}\"" testrb << "\nputs #{k.upcase}" end - Dir.chdir(bundled_app) do - ruby testrb, :no_lib => true + ruby testrb + + expect(out).to eq(expected_gems.values.join("\n")) + end + + it "makes the gems available without bundler via Kernel.require" do + testrb = String.new <<-RUBY + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + RUBY + expected_gems.each do |k, _| + testrb << "\nKernel.require \"#{k}\"" + testrb << "\nputs #{k.upcase}" end + ruby testrb expect(out).to eq(expected_gems.values.join("\n")) end + it "makes system gems unavailable without bundler" do + system_gems "rack-1.0.0" + + testrb = String.new <<-RUBY + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + begin + require "rack" + rescue LoadError + puts "LoadError" + end + RUBY + ruby testrb + + expect(out).to eq("LoadError") + end + it "works on a different system" do - FileUtils.mv(bundled_app, "#{bundled_app}2") + begin + FileUtils.mv(bundled_app, "#{bundled_app}2") + rescue Errno::ENOTEMPTY + puts "Couldn't rename test app since the target folder has these files: #{Dir.glob("#{bundled_app}2/*")}" + raise + end testrb = String.new <<-RUBY $:.unshift File.expand_path("bundle") @@ -40,9 +82,7 @@ testrb << "\nrequire \"#{k}\"" testrb << "\nputs #{k.upcase}" end - Dir.chdir("#{bundled_app}2") do - ruby testrb, :no_lib => true - end + ruby testrb, :dir => "#{bundled_app}2" expect(out).to eq(expected_gems.values.join("\n")) end @@ -54,7 +94,8 @@ source "#{file_uri_for(gem_repo1)}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :dir => cwd end let(:expected_gems) do @@ -67,9 +108,85 @@ include_examples "common functionality" end + describe "with default gems and a lockfile", :ruby_repo do + before do + skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2 + skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0" + + if Gem.win_platform? && RUBY_VERSION < "3.1.0" + default_fiddle_version = ruby "require 'fiddle'; puts Gem.loaded_specs['fiddle'].version" + realworld_system_gems "fiddle --version #{default_fiddle_version}" + end + + realworld_system_gems "tsort --version 0.1.0" + + necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.0.0"] + necessary_system_gems += ["shellwords --version 0.1.0", "base64 --version 0.1.0", "resolv --version 0.2.1"] if Gem.rubygems_version < Gem::Version.new("3.3.a") + necessary_system_gems += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a") + realworld_system_gems(*necessary_system_gems, :path => scoped_gem_path(bundled_app("bundle"))) + + build_gem "foo", "1.0.0", :to_system => true, :default => true do |s| + s.add_dependency "bar" + end + + build_gem "bar", "1.0.0", :to_system => true, :default => true + + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.add_dependency "bar" + end + + build_gem "bar", "1.0.0" + end + + gemfile <<-G + source "https://gem.repo4" + gem "foo" + G + + bundle "lock", :dir => cwd, :artifice => "compact_index" + end + + it "works" do + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :dir => cwd, :artifice => "compact_index", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s } + end + end + + describe "with Gemfiles using path sources and resulting bundle moved to a folder hierarchy with different nesting" do + before do + build_lib "minitest", "1.0.0", :path => lib_path("minitest") + + Dir.mkdir bundled_app("app") + + gemfile bundled_app("app/Gemfile"), <<-G + source "#{file_uri_for(gem_repo1)}" + gem "minitest", :path => "#{lib_path("minitest")}" + G + + bundle "install", :standalone => true, :dir => bundled_app("app") + + Dir.mkdir tmp("one_more_level") + FileUtils.mv bundled_app, tmp("one_more_level") + end + + it "also works" do + ruby <<-RUBY, :dir => tmp("one_more_level/bundled_app/app") + require "./bundle/bundler/setup" + + require "minitest" + puts MINITEST + RUBY + + expect(out).to eq("1.0.0") + expect(err).to be_empty + end + end + describe "with gems with native extension", :ruby_repo do before do - install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + bundle "config set --local path #{bundled_app("bundle")}" + install_gemfile <<-G, :standalone => true, :dir => cwd source "#{file_uri_for(gem_repo1)}" gem "very_simple_binary" G @@ -78,8 +195,8 @@ it "generates a bundle/bundler/setup.rb with the proper paths" do expected_path = bundled_app("bundle/bundler/setup.rb") extension_line = File.read(expected_path).each_line.find {|line| line.include? "/extensions/" }.strip - expect(extension_line).to start_with '$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/' - expect(extension_line).to end_with '/very_simple_binary-1.0"' + expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}/extensions/' + expect(extension_line).to end_with '/very_simple_binary-1.0")' end end @@ -102,7 +219,9 @@ end G end - install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + bundle "config set --local path #{bundled_app("bundle")}" + install_gemfile <<-G, :standalone => true, :dir => cwd, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" gem "bar", :git => "#{lib_path("bar-1.0")}" G end @@ -122,7 +241,8 @@ gem "rails" gem "devise", :git => "#{lib_path("devise-1.0")}" G - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :dir => cwd end let(:expected_gems) do @@ -149,7 +269,8 @@ gem "rack-test" end G - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :dir => cwd end let(:expected_gems) do @@ -162,88 +283,69 @@ include_examples "common functionality" it "allows creating a standalone file with limited groups" do - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => "default") + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => "default", :dir => cwd - Dir.chdir(bundled_app) do - load_error_ruby <<-RUBY, "spec", :no_lib => true - $:.unshift File.expand_path("bundle") - require "bundler/setup" + load_error_ruby <<-RUBY, "spec" + $:.unshift File.expand_path("bundle") + require "bundler/setup" - require "actionpack" - puts ACTIONPACK - require "spec" - RUBY - end + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY expect(out).to eq("2.3.2") expect(err).to eq("ZOMG LOAD ERROR") end - it "allows --without to limit the groups used in a standalone" do - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle"), :without => "test").merge(:standalone => true) + it "allows `without` configuration to limit the groups used in a standalone" do + bundle "config set --local path #{bundled_app("bundle")}" + bundle "config set --local without test" + bundle :install, :standalone => true, :dir => cwd - Dir.chdir(bundled_app) do - load_error_ruby <<-RUBY, "spec", :no_lib => true - $:.unshift File.expand_path("bundle") - require "bundler/setup" + load_error_ruby <<-RUBY, "spec" + $:.unshift File.expand_path("bundle") + require "bundler/setup" - require "actionpack" - puts ACTIONPACK - require "spec" - RUBY - end + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY expect(out).to eq("2.3.2") expect(err).to eq("ZOMG LOAD ERROR") end - it "allows --path to change the location of the standalone bundle", :bundler => "< 3" do - bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true) - - Dir.chdir(bundled_app) do - ruby <<-RUBY, :no_lib => true - $:.unshift File.expand_path("path/to/bundle") - require "bundler/setup" - - require "actionpack" - puts ACTIONPACK - RUBY - end + it "allows `path` configuration to change the location of the standalone bundle" do + bundle "config set --local path path/to/bundle" + bundle "install", :standalone => true, :dir => cwd - expect(out).to eq("2.3.2") - end - - it "allows --path to change the location of the standalone bundle", :bundler => "3" do - bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true) - path = File.expand_path("path/to/bundle") - - Dir.chdir(bundled_app) do - ruby <<-RUBY, :no_lib => true - $:.unshift File.expand_path(#{path.dump}) - require "bundler/setup" + ruby <<-RUBY + $:.unshift File.expand_path("path/to/bundle") + require "bundler/setup" - require "actionpack" - puts ACTIONPACK - RUBY - end + require "actionpack" + puts ACTIONPACK + RUBY expect(out).to eq("2.3.2") end - it "allows remembered --without to limit the groups used in a standalone" do - bundle! :install, forgotten_command_line_options(:without => "test") - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) + it "allows `without` to limit the groups used in a standalone" do + bundle "config set --local without test" + bundle :install, :dir => cwd + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :dir => cwd - Dir.chdir(bundled_app) do - load_error_ruby <<-RUBY, "spec", :no_lib => true - $:.unshift File.expand_path("bundle") - require "bundler/setup" + load_error_ruby <<-RUBY, "spec" + $:.unshift File.expand_path("bundle") + require "bundler/setup" - require "actionpack" - puts ACTIONPACK - require "spec" - RUBY - end + require "actionpack" + puts ACTIONPACK + require "spec" + RUBY expect(out).to eq("2.3.2") expect(err).to eq("ZOMG LOAD ERROR") @@ -259,7 +361,8 @@ source "#{source_uri}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :artifice => "endpoint") + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :artifice => "endpoint", :dir => cwd end let(:expected_gems) do @@ -279,7 +382,8 @@ source "#{file_uri_for(gem_repo1)}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :binstubs => true) + bundle "config set --local path #{bundled_app("bundle")}" + bundle :install, :standalone => true, :binstubs => true, :dir => cwd end let(:expected_gems) do @@ -292,28 +396,24 @@ include_examples "common functionality" it "creates stubs that use the standalone load path" do - Dir.chdir(bundled_app) do - expect(`bin/rails -v`.chomp).to eql "2.3.2" - end + expect(sys_exec("bin/rails -v").chomp).to eql "2.3.2" end it "creates stubs that can be executed from anywhere" do require "tmpdir" - Dir.chdir(Dir.tmpdir) do - sys_exec!(%(#{bundled_app("bin/rails")} -v)) - expect(out).to eq("2.3.2") - end + sys_exec(%(#{bundled_app("bin/rails")} -v), :dir => Dir.tmpdir) + expect(out).to eq("2.3.2") end it "creates stubs that can be symlinked" do - pending "File.symlink is unsupported on Windows" if Bundler::WINDOWS + skip "symlinks unsupported" if Gem.win_platform? symlink_dir = tmp("symlink") FileUtils.mkdir_p(symlink_dir) symlink = File.join(symlink_dir, "rails") File.symlink(bundled_app("bin/rails"), symlink) - sys_exec!("#{symlink} -v") + sys_exec("#{symlink} -v") expect(out).to eq("2.3.2") end @@ -325,13 +425,13 @@ end RSpec.describe "bundle install --standalone" do + let(:cwd) { bundled_app } + include_examples("bundle install --standalone") end RSpec.describe "bundle install --standalone run in a subdirectory" do - before do - Dir.chdir(bundled_app("bob").tap(&:mkpath)) - end + let(:cwd) { bundled_app("bob").tap(&:mkpath) } include_examples("bundle install --standalone") end diff --git a/ruby/spec/bundler/install/gems/sudo_spec.rb b/ruby/spec/bundler/install/gems/sudo_spec.rb index 170ffaca0..3e5d38ea4 100644 --- a/ruby/spec/bundler/install/gems/sudo_spec.rb +++ b/ruby/spec/bundler/install/gems/sudo_spec.rb @@ -8,7 +8,7 @@ end before do - bundle! "config set path.system true" + bundle "config set path.system true" subdir.mkpath sudo "chmod u-w #{subdir}" end @@ -32,7 +32,7 @@ describe "and GEM_HOME is owned by root" do before :each do - bundle! "config set path.system true" + bundle "config set path.system true" chown_system_gems_to_root end @@ -49,8 +49,23 @@ end it "installs rake and a gem dependent on rake in the same session" do + build_repo2 do + build_gem "another_implicit_rake_dep" do |s| + s.extensions << "Rakefile" + s.write "Rakefile", <<-RUBY + task :default do + path = File.expand_path("../lib", __FILE__) + FileUtils.mkdir_p(path) + File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f| + f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'" + end + end + RUBY + end + end + gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rake" gem "another_implicit_rake_dep" G @@ -105,11 +120,12 @@ describe "and BUNDLE_PATH is not writable" do before do - sudo "chmod ugo-w #{default_bundle_path}" + bundle "config set --local path .bundle" + sudo "chmod ugo-w .bundle" end after do - sudo "chmod ugo+w #{default_bundle_path}" + sudo "chmod ugo+w .bundle" end it "installs" do @@ -118,7 +134,7 @@ gem "rack", '1.0' G - expect(default_bundle_path("gems/rack-1.0.0")).to exist + expect(local_gem_path("gems/rack-1.0.0")).to exist expect(the_bundle).to include_gems "rack 1.0" end @@ -140,11 +156,13 @@ describe "and GEM_HOME is not writable" do it "installs" do - bundle! "config set path.system true" + bundle "config set path.system true" gem_home = tmp("sudo_gem_home") sudo "mkdir -p #{gem_home}" sudo "chmod ugo-w #{gem_home}" + system_gems :bundler, :path => gem_home + gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", '1.0' @@ -166,7 +184,7 @@ end it "warns against that" do - bundle :install, :sudo => true + bundle :install, :sudo => :preserve_env expect(err).to include(warning) end @@ -179,7 +197,7 @@ context "when silence_root_warning = false" do it "warns against that" do - bundle :install, :sudo => true, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" } + bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" } expect(err).to include(warning) end end diff --git a/ruby/spec/bundler/install/gems/win32_spec.rb b/ruby/spec/bundler/install/gems/win32_spec.rb index 01edcca80..419b14ff0 100644 --- a/ruby/spec/bundler/install/gems/win32_spec.rb +++ b/ruby/spec/bundler/install/gems/win32_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "bundle install with win32-generated lockfile" do it "should read lockfile" do - File.open(bundled_app("Gemfile.lock"), "wb") do |f| + File.open(bundled_app_lock, "wb") do |f| f << "GEM\r\n" f << " remote: #{file_uri_for(gem_repo1)}/\r\n" f << " specs:\r\n" @@ -21,6 +21,5 @@ gem "rack" G - expect(exitstatus).to eq(0) if exitstatus end end diff --git a/ruby/spec/bundler/install/gemspecs_spec.rb b/ruby/spec/bundler/install/gemspecs_spec.rb index 4c00caa60..3684d8749 100644 --- a/ruby/spec/bundler/install/gemspecs_spec.rb +++ b/ruby/spec/bundler/install/gemspecs_spec.rb @@ -21,6 +21,7 @@ build_lib "yaml_spec", :gemspec => :yaml install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'yaml_spec', :path => "#{lib_path("yaml_spec-1.0")}" G expect(err).to be_empty @@ -33,6 +34,8 @@ gem 'rack' G + system_gems "rack-1.0.0", :path => default_bundle_path + FileUtils.mkdir_p "#{default_bundle_path}/specifications" File.open("#{default_bundle_path}/specifications/rack-1.0.0.gemspec", "w+") do |f| spec = Gem::Specification.new do |s| @@ -43,7 +46,7 @@ f.write spec.to_ruby end bundle :install, :artifice => "endpoint_marshal_fail" # force gemspec load - expect(the_bundle).to include_gems "activesupport 2.3.2" + expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2" end it "does not hang when gemspec has incompatible encoding" do @@ -57,6 +60,7 @@ G install_gemfile <<-G, :env => { "LANG" => "C" } + source "#{file_uri_for(gem_repo1)}" gemspec G @@ -82,6 +86,7 @@ module Persistent💎 G install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gemspec G @@ -96,6 +101,7 @@ module Persistent💎 install_gemfile <<-G ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby' + source "#{file_uri_for(gem_repo1)}" gemspec G expect(the_bundle).to include_gems "foo 1.0" @@ -107,8 +113,9 @@ module Persistent💎 s.required_ruby_version = "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{RUBY_PATCHLEVEL}' + source "#{file_uri_for(gem_repo1)}" gemspec G expect(the_bundle).to include_gems "foo 1.0" @@ -121,14 +128,15 @@ module Persistent💎 s.required_ruby_version = "#{RUBY_VERSION}.#{patchlevel}" end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{patchlevel}' + source "#{file_uri_for(gem_repo1)}" gemspec G expect(err).to include("Ruby patchlevel") expect(err).to include("but your Gemfile specified") - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) end it "fails and complains about version on version mismatch" do @@ -138,14 +146,15 @@ module Persistent💎 s.required_ruby_version = version end - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false ruby '#{version}', :engine_version => '#{version}', :engine => 'ruby' + source "#{file_uri_for(gem_repo1)}" gemspec G expect(err).to include("Ruby version") expect(err).to include("but your Gemfile specified") - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) end end end diff --git a/ruby/spec/bundler/install/git_spec.rb b/ruby/spec/bundler/install/git_spec.rb index cc8bf70b0..d43aacee7 100644 --- a/ruby/spec/bundler/install/git_spec.rb +++ b/ruby/spec/bundler/install/git_spec.rb @@ -2,37 +2,51 @@ RSpec.describe "bundle install" do context "git sources" do - it "displays the revision hash of the gem repository", :bundler => "< 3" do + it "displays the revision hash of the gem repository" do build_git "foo", "1.0", :path => lib_path("foo") - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo")}" + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo1)}" + gem "foo", :git => "#{file_uri_for(lib_path("foo"))}" + G + + expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master@#{revision_for(lib_path("foo"))[0..6]})") + expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" + end + + it "displays the correct default branch", :git => ">= 2.28.0" do + build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main" + + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo1)}" + gem "foo", :git => "#{file_uri_for(lib_path("foo"))}" G - bundle! :install - expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master@#{revision_for(lib_path("foo"))[0..6]})") + expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{revision_for(lib_path("foo"))[0..6]})") expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" end - it "displays the ref of the gem repository when using branch~num as a ref", :bundler => "< 3" do + it "displays the ref of the gem repository when using branch~num as a ref" do + skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform? + build_git "foo", "1.0", :path => lib_path("foo") rev = revision_for(lib_path("foo"))[0..6] update_git "foo", "2.0", :path => lib_path("foo"), :gemspec => true rev2 = revision_for(lib_path("foo"))[0..6] update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true - install_gemfile! <<-G - gem "foo", :git => "#{lib_path("foo")}", :ref => "master~2" + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo1)}" + gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2" G - bundle! :install - expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master~2@#{rev})") + expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev})") expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true - bundle! :update, :all => true - expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at master~2@#{rev2})") + bundle :update, :all => true, :verbose => true + expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev2})") expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}" end @@ -40,6 +54,7 @@ revision = build_git("foo").ref_for("HEAD") gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :group => :development G @@ -57,7 +72,9 @@ foo! L - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle", :without => "development") + bundle "config set --local path vendor/bundle" + bundle "config set --local without development" + bundle :install expect(out).to include("Bundle complete!") end @@ -71,8 +88,8 @@ install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" - gem "foo", :git => "#{lib_path("gems")}", :glob => "foo/*.gemspec" - gem "zebra", :git => "#{lib_path("gems")}", :glob => "zebra/*.gemspec" + gem "foo", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "foo/*.gemspec" + gem "zebra", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "zebra/*.gemspec" G bundle "info foo" diff --git a/ruby/spec/bundler/install/global_cache_spec.rb b/ruby/spec/bundler/install/global_cache_spec.rb index 023e52b06..afa0ff76c 100644 --- a/ruby/spec/bundler/install/global_cache_spec.rb +++ b/ruby/spec/bundler/install/global_cache_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe "global gem caching" do - before { bundle! "config set global_gem_cache true" } + before { bundle "config set global_gem_cache true" } describe "using the cross-application user cache" do let(:source) { "http://localgemserver.test" } @@ -16,7 +16,7 @@ def source2_global_cache(*segments) end it "caches gems into the global cache on download" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" source "#{source}" gem "rack" G @@ -29,7 +29,7 @@ def source2_global_cache(*segments) source_global_cache.mkpath FileUtils.cp(gem_repo1("gems/rack-1.0.0.gem"), source_global_cache("rack-1.0.0.gem")) - install_gemfile! <<-G, :artifice => "compact_index_no_gem" + install_gemfile <<-G, :artifice => "compact_index_no_gem" source "#{source}" gem "rack" G @@ -37,24 +37,36 @@ def source2_global_cache(*segments) expect(the_bundle).to include_gems "rack 1.0.0" end + it "shows a proper error message if a cached gem is corrupted" do + source_global_cache.mkpath + FileUtils.touch(source_global_cache("rack-1.0.0.gem")) + + install_gemfile <<-G, :artifice => "compact_index_no_gem", :raise_on_error => false + source "#{source}" + gem "rack" + G + + expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("rack-1.0.0.gem")}") + end + describe "when the same gem from different sources is installed" do it "should use the appropriate one from the global cache" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" source "#{source}" gem "rack" G - FileUtils.rm_r(default_bundle_path) + simulate_new_machine expect(the_bundle).not_to include_gems "rack 1.0.0" expect(source_global_cache("rack-1.0.0.gem")).to exist # rack 1.0.0 is not installed and it is in the global cache - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" source "#{source2}" gem "rack", "0.9.1" G - FileUtils.rm_r(default_bundle_path) + simulate_new_machine expect(the_bundle).not_to include_gems "rack 0.9.1" expect(source2_global_cache("rack-0.9.1.gem")).to exist # rack 0.9.1 is not installed and it is in the global cache @@ -64,18 +76,18 @@ def source2_global_cache(*segments) gem "rack", "1.0.0" G - bundle! :install, :artifice => "compact_index_no_gem" + bundle :install, :artifice => "compact_index_no_gem" # rack 1.0.0 is installed and rack 0.9.1 is not expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).not_to include_gems "rack 0.9.1" - FileUtils.rm_r(default_bundle_path) + simulate_new_machine gemfile <<-G source "#{source2}" gem "rack", "0.9.1" G - bundle! :install, :artifice => "compact_index_no_gem" + bundle :install, :artifice => "compact_index_no_gem" # rack 0.9.1 is installed and rack 1.0.0 is not expect(the_bundle).to include_gems "rack 0.9.1" expect(the_bundle).not_to include_gems "rack 1.0.0" @@ -87,8 +99,8 @@ def source2_global_cache(*segments) gem "rack" G - bundle! :install, :artifice => "compact_index" - FileUtils.rm_r(default_bundle_path) + bundle :install, :artifice => "compact_index" + simulate_new_machine expect(the_bundle).not_to include_gems "rack 1.0.0" expect(source_global_cache("rack-1.0.0.gem")).to exist # rack 1.0.0 is not installed and it is in the global cache @@ -98,8 +110,8 @@ def source2_global_cache(*segments) gem "rack", "0.9.1" G - bundle! :install, :artifice => "compact_index" - FileUtils.rm_r(default_bundle_path) + bundle :install, :artifice => "compact_index" + simulate_new_machine expect(the_bundle).not_to include_gems "rack 0.9.1" expect(source2_global_cache("rack-0.9.1.gem")).to exist # rack 0.9.1 is not installed and it is in the global cache @@ -111,8 +123,10 @@ def source2_global_cache(*segments) expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source2_global_cache("rack-0.9.1.gem")).to exist - bundle :install, :artifice => "compact_index_no_gem" + bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false expect(err).to include("Internal Server Error 500") + expect(err).not_to include("ERROR REPORT TEMPLATE") + # rack 1.0.0 is not installed and rack 0.9.1 is not expect(the_bundle).not_to include_gems "rack 1.0.0" expect(the_bundle).not_to include_gems "rack 0.9.1" @@ -124,8 +138,10 @@ def source2_global_cache(*segments) expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source2_global_cache("rack-0.9.1.gem")).to exist - bundle :install, :artifice => "compact_index_no_gem" + bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false expect(err).to include("Internal Server Error 500") + expect(err).not_to include("ERROR REPORT TEMPLATE") + # rack 0.9.1 is not installed and rack 1.0.0 is not expect(the_bundle).not_to include_gems "rack 0.9.1" expect(the_bundle).not_to include_gems "rack 1.0.0" @@ -134,7 +150,7 @@ def source2_global_cache(*segments) describe "when installing gems from a different directory" do it "uses the global cache as a source" do - install_gemfile! <<-G, :artifice => "compact_index" + install_gemfile <<-G, :artifice => "compact_index" source "#{source}" gem "rack" gem "activesupport" @@ -145,12 +161,12 @@ def source2_global_cache(*segments) expect(the_bundle).to include_gems "activesupport 2.3.5" expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source_global_cache("activesupport-2.3.5.gem")).to exist - FileUtils.rm_r(default_bundle_path) + simulate_new_machine # Both gems are now only in the global cache expect(the_bundle).not_to include_gems "rack 1.0.0" expect(the_bundle).not_to include_gems "activesupport 2.3.5" - install_gemfile! <<-G, :artifice => "compact_index_no_gem" + install_gemfile <<-G, :artifice => "compact_index_no_gem" source "#{source}" gem "rack" G @@ -161,39 +177,42 @@ def source2_global_cache(*segments) expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source_global_cache("activesupport-2.3.5.gem")).to exist - Dir.chdir bundled_app2 do - create_file bundled_app2("gems.rb"), <<-G - source "#{source}" - gem "activesupport" - G - - # Neither gem is installed and both are in the global cache - expect(the_bundle).not_to include_gems "rack 1.0.0" - expect(the_bundle).not_to include_gems "activesupport 2.3.5" - expect(source_global_cache("rack-1.0.0.gem")).to exist - expect(source_global_cache("activesupport-2.3.5.gem")).to exist - - # Install using the global cache instead of by downloading the .gem - # from the server - bundle! :install, :artifice => "compact_index_no_gem" - - # activesupport is installed and both are in the global cache - expect(the_bundle).not_to include_gems "rack 1.0.0" - expect(the_bundle).to include_gems "activesupport 2.3.5" - expect(source_global_cache("rack-1.0.0.gem")).to exist - expect(source_global_cache("activesupport-2.3.5.gem")).to exist + create_file bundled_app2("gems.rb"), <<-G + source "#{source}" + gem "activesupport" + G + + # Neither gem is installed and both are in the global cache + expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2 + expect(the_bundle).not_to include_gems "activesupport 2.3.5", :dir => bundled_app2 + expect(source_global_cache("rack-1.0.0.gem")).to exist + expect(source_global_cache("activesupport-2.3.5.gem")).to exist + + # Install using the global cache instead of by downloading the .gem + # from the server + bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2 + + # activesupport is installed and both are in the global cache + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2 + expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2 end + + expect(source_global_cache("rack-1.0.0.gem")).to exist + expect(source_global_cache("activesupport-2.3.5.gem")).to exist end end end - describe "extension caching", :ruby_repo do - it "works" do + describe "extension caching" do + it "works", :ruby_repo do + skip "gets incorrect ref in path" if Gem.win_platform? + build_git "very_simple_git_binary", &:add_c_extension build_lib "very_simple_path_binary", &:add_c_extension revision = revision_for(lib_path("very_simple_git_binary-1.0"))[0, 12] - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "very_simple_binary" @@ -209,7 +228,7 @@ def source2_global_cache(*segments) cached_extensions = Pathname.glob(home(".bundle", "cache", "extensions", "*", "*", "*", "*", "*")).sort expect(cached_extensions).to eq [gem_binary_cache, git_binary_cache].sort - run! <<-R + run <<-R require 'very_simple_binary_c'; puts ::VERY_SIMPLE_BINARY_IN_C require 'very_simple_git_binary_c'; puts ::VERY_SIMPLE_GIT_BINARY_IN_C R @@ -220,12 +239,12 @@ def source2_global_cache(*segments) gem_binary_cache.join("very_simple_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" } git_binary_cache.join("very_simple_git_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" } - bundle! "config set --local path different_path" - bundle! :install + bundle "config set --local path different_path" + bundle :install expect(Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]).to all(end_with(".rb")) - run! <<-R + run <<-R require 'very_simple_binary_c' require 'very_simple_git_binary_c' R diff --git a/ruby/spec/bundler/install/path_spec.rb b/ruby/spec/bundler/install/path_spec.rb index 5240c5820..b0392c4ed 100644 --- a/ruby/spec/bundler/install/path_spec.rb +++ b/ruby/spec/bundler/install/path_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe "bundle install" do - describe "with --path" do + describe "with path configured" do before :each do build_gem "rack", "1.0.0", :to_system => true do |s| s.write "lib/rack.rb", "puts 'FAIL'" @@ -13,32 +13,41 @@ G end - it "does not use available system gems with bundle --path vendor/bundle", :bundler => "< 3" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + it "does not use available system gems with `vendor/bundle" do + bundle "config set --local path vendor/bundle" + bundle :install expect(the_bundle).to include_gems "rack 1.0.0" end + it "uses system gems with `path.system` configured with more priority than `path`" do + bundle "config set --local path.system true" + bundle "config set --global path vendor/bundle" + bundle :install + run "require 'rack'", :raise_on_error => false + expect(out).to include("FAIL") + end + it "handles paths with regex characters in them" do dir = bundled_app("bun++dle") dir.mkpath - Dir.chdir(dir) do - bundle! :install, forgotten_command_line_options(:path => dir.join("vendor/bundle")) - expect(out).to include("installed into `./vendor/bundle`") - end + bundle "config set --local path #{dir.join("vendor/bundle")}" + bundle :install, :dir => dir + expect(out).to include("installed into `./vendor/bundle`") dir.rmtree end - it "prints a warning to let the user know what has happened with bundle --path vendor/bundle" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + it "prints a message to let the user know where gems where installed" do + bundle "config set --local path vendor/bundle" + bundle :install expect(out).to include("gems are installed into `./vendor/bundle`") end it "disallows --path vendor/bundle --system", :bundler => "< 3" do - bundle "install --path vendor/bundle --system" + bundle "install --path vendor/bundle --system", :raise_on_error => false expect(err).to include("Please choose only one option.") - expect(exitstatus).to eq(15) if exitstatus + expect(exitstatus).to eq(15) end it "remembers to disable system gems after the first time with bundle --path vendor/bundle", :bundler => "< 3" do @@ -51,33 +60,27 @@ end context "with path_relative_to_cwd set to true" do - before { bundle! "config set path_relative_to_cwd true" } + before { bundle "config set path_relative_to_cwd true" } it "installs the bundle relatively to current working directory", :bundler => "< 3" do - Dir.chdir(bundled_app.parent) do - bundle! "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle" - expect(out).to include("installed into `./vendor/bundle`") - expect(bundled_app("../vendor/bundle")).to be_directory - end + bundle "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle", :dir => bundled_app.parent + expect(out).to include("installed into `./vendor/bundle`") + expect(bundled_app("../vendor/bundle")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" end it "installs the standalone bundle relative to the cwd" do - Dir.chdir(bundled_app.parent) do - bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true - expect(out).to include("installed into `./bundled_app/bundle`") - expect(bundled_app("bundle")).to be_directory - expect(bundled_app("bundle/ruby")).to be_directory - end + bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app.parent + expect(out).to include("installed into `./bundled_app/bundle`") + expect(bundled_app("bundle")).to be_directory + expect(bundled_app("bundle/ruby")).to be_directory - bundle! "config unset path" + bundle "config unset path" - Dir.chdir(bundled_app("subdir").tap(&:mkpath)) do - bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true - expect(out).to include("installed into `../bundle`") - expect(bundled_app("bundle")).to be_directory - expect(bundled_app("bundle/ruby")).to be_directory - end + bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app("subdir").tap(&:mkpath) + expect(out).to include("installed into `../bundle`") + expect(bundled_app("bundle")).to be_directory + expect(bundled_app("bundle/ruby")).to be_directory end end end @@ -98,7 +101,7 @@ def set_bundle_path(type, location) if type == :env ENV["BUNDLE_PATH"] = location elsif type == :global - bundle! "config set path #{location}", "no-color" => nil + bundle "config set path #{location}", "no-color" => nil end end @@ -106,7 +109,8 @@ def set_bundle_path(type, location) context "when set via #{type}" do it "installs gems to a path if one is specified" do set_bundle_path(type, bundled_app("vendor2").to_s) - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle :install expect(vendored_gems("gems/rack-1.0.0")).to be_directory expect(bundled_app("vendor2")).not_to be_directory @@ -115,9 +119,9 @@ def set_bundle_path(type, location) it "installs gems to ." do set_bundle_path(type, ".") - bundle! "config set --global disable_shared_gems true" + bundle "config set --global disable_shared_gems true" - bundle! :install + bundle :install paths_to_exist = %w[cache/rack-1.0.0.gem gems/rack-1.0.0 specifications/rack-1.0.0.gemspec].map {|path| bundled_app(Bundler.ruby_scope, path) } expect(paths_to_exist).to all exist @@ -127,7 +131,7 @@ def set_bundle_path(type, location) it "installs gems to the path" do set_bundle_path(type, bundled_app("vendor").to_s) - bundle! :install + bundle :install expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" @@ -137,9 +141,7 @@ def set_bundle_path(type, location) set_bundle_path(type, "vendor") FileUtils.mkdir_p bundled_app("lol") - Dir.chdir(bundled_app("lol")) do - bundle! :install - end + bundle :install, :dir => bundled_app("lol") expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" @@ -157,7 +159,8 @@ def set_bundle_path(type, location) end it "sets BUNDLE_PATH as the first argument to bundle install" do - bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle") + bundle "config set --local path ./vendor/bundle" + bundle :install expect(vendored_gems("gems/rack-1.0.0")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" @@ -166,7 +169,8 @@ def set_bundle_path(type, location) it "disables system gems when passing a path to install" do # This is so that vendored gems can be distributed to others build_gem "rack", "1.1.0", :to_system => true - bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle") + bundle "config set --local path ./vendor/bundle" + bundle :install expect(vendored_gems("gems/rack-1.0.0")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" @@ -182,7 +186,8 @@ def set_bundle_path(type, location) gem "very_simple_binary" G - bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle") + bundle "config set --local path ./vendor/bundle" + bundle :install expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory expect(vendored_gems("extensions")).to be_directory @@ -190,10 +195,11 @@ def set_bundle_path(type, location) vendored_gems("extensions").rmtree - run "require 'very_simple_binary_c'" + run "require 'very_simple_binary_c'", :raise_on_error => false expect(err).to include("Bundler::GemNotFound") - bundle :install, forgotten_command_line_options(:path => "./vendor/bundle") + bundle "config set --local path ./vendor/bundle" + bundle :install expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory expect(vendored_gems("extensions")).to be_directory @@ -203,9 +209,7 @@ def set_bundle_path(type, location) describe "to a file" do before do - in_app_root do - FileUtils.touch "bundle" - end + FileUtils.touch bundled_app("bundle") end it "reports the file exists" do @@ -214,7 +218,8 @@ def set_bundle_path(type, location) gem "rack" G - bundle :install, forgotten_command_line_options(:path => "bundle") + bundle "config set --local path bundle" + bundle :install, :raise_on_error => false expect(err).to include("file already exists") end end diff --git a/ruby/spec/bundler/install/prereleases_spec.rb b/ruby/spec/bundler/install/prereleases_spec.rb index fb01220ed..629eb89da 100644 --- a/ruby/spec/bundler/install/prereleases_spec.rb +++ b/ruby/spec/bundler/install/prereleases_spec.rb @@ -1,10 +1,19 @@ # frozen_string_literal: true RSpec.describe "bundle install" do + before do + build_repo2 do + build_gem "not_released", "1.0.pre" + + build_gem "has_prerelease", "1.0" + build_gem "has_prerelease", "1.1.pre" + end + end + describe "when prerelease gems are available" do it "finds prereleases" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "not_released" G expect(the_bundle).to include_gems "not_released 1.0.pre" @@ -12,7 +21,7 @@ it "uses regular releases if available" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "has_prerelease" G expect(the_bundle).to include_gems "has_prerelease 1.0" @@ -20,7 +29,7 @@ it "uses prereleases if requested" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "has_prerelease", "1.1.pre" G expect(the_bundle).to include_gems "has_prerelease 1.1.pre" @@ -29,7 +38,11 @@ describe "when prerelease gems are not available" do it "still works" do - build_repo3 + build_repo gem_repo3 do + build_gem "rack" + end + FileUtils.rm_rf Dir[gem_repo3("prerelease*")] + install_gemfile <<-G source "#{file_uri_for(gem_repo3)}" gem "rack" diff --git a/ruby/spec/bundler/install/process_lock_spec.rb b/ruby/spec/bundler/install/process_lock_spec.rb index cab4ba081..dac0d34bc 100644 --- a/ruby/spec/bundler/install/process_lock_spec.rb +++ b/ruby/spec/bundler/install/process_lock_spec.rb @@ -12,7 +12,7 @@ end end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G diff --git a/ruby/spec/bundler/install/redownload_spec.rb b/ruby/spec/bundler/install/redownload_spec.rb index 818c33bd6..a936b2b53 100644 --- a/ruby/spec/bundler/install/redownload_spec.rb +++ b/ruby/spec/bundler/install/redownload_spec.rb @@ -12,9 +12,9 @@ it "re-installs installed gems" do rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb") - bundle! :install + bundle :install rack_lib.open("w") {|f| f.write("blah blah blah") } - bundle! :install, flag => true + bundle :install, flag => true expect(out).to include "Installing rack 1.0.0" expect(rack_lib.open(&:read)).to eq("RACK = '1.0.0'\n") @@ -22,7 +22,7 @@ end it "works on first bundle install" do - bundle! :install, flag => true + bundle :install, flag => true expect(out).to include "Installing rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0" @@ -33,6 +33,7 @@ before do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G end @@ -40,16 +41,16 @@ it "re-installs installed gems" do foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb") - bundle! :install + bundle :install foo_lib.open("w") {|f| f.write("blah blah blah") } - bundle! :install, flag => true + bundle :install, flag => true expect(foo_lib.open(&:read)).to eq("FOO = '1.0'\n") expect(the_bundle).to include_gems "foo 1.0" end it "works on first bundle install" do - bundle! :install, flag => true + bundle :install, flag => true expect(the_bundle).to include_gems "foo 1.0" end @@ -62,12 +63,12 @@ end it "shows a deprecation when single flag passed" do - bundle! "install --force" + bundle "install --force" expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end it "shows a deprecation when multiple flags passed" do - bundle! "install --no-color --force" + bundle "install --no-color --force" expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end end @@ -78,12 +79,12 @@ end it "does not show a deprecation when single flag passed" do - bundle! "install --redownload" + bundle "install --redownload" expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end it "does not show a deprecation when single multiple flags passed" do - bundle! "install --no-color --redownload" + bundle "install --no-color --redownload" expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end end diff --git a/ruby/spec/bundler/install/security_policy_spec.rb b/ruby/spec/bundler/install/security_policy_spec.rb index 28c34d9ce..43c3069c4 100644 --- a/ruby/spec/bundler/install/security_policy_spec.rb +++ b/ruby/spec/bundler/install/security_policy_spec.rb @@ -16,30 +16,28 @@ end it "will work after you try to deploy without a lock" do - bundle "install --deployment" + bundle "install --deployment", :raise_on_error => false bundle :install - expect(exitstatus).to eq(0) if exitstatus expect(the_bundle).to include_gems "rack 1.0", "signed_gem 1.0" end it "will fail when given invalid security policy" do - bundle "install --trust-policy=InvalidPolicyName" + bundle "install --trust-policy=InvalidPolicyName", :raise_on_error => false expect(err).to include("RubyGems doesn't know about trust policy") end it "will fail with High Security setting due to presence of unsigned gem" do - bundle "install --trust-policy=HighSecurity" + bundle "install --trust-policy=HighSecurity", :raise_on_error => false expect(err).to include("security policy didn't allow") end it "will fail with Medium Security setting due to presence of unsigned gem" do - bundle "install --trust-policy=MediumSecurity" + bundle "install --trust-policy=MediumSecurity", :raise_on_error => false expect(err).to include("security policy didn't allow") end it "will succeed with no policy" do bundle "install" - expect(exitstatus).to eq(0) if exitstatus end end @@ -53,24 +51,22 @@ end it "will fail with High Security setting, gem is self-signed" do - bundle "install --trust-policy=HighSecurity" + bundle "install --trust-policy=HighSecurity", :raise_on_error => false expect(err).to include("security policy didn't allow") end it "will fail with Medium Security setting, gem is self-signed" do - bundle "install --trust-policy=MediumSecurity" + bundle "install --trust-policy=MediumSecurity", :raise_on_error => false expect(err).to include("security policy didn't allow") end it "will succeed with Low Security setting, low security accepts self signed gem" do bundle "install --trust-policy=LowSecurity" - expect(exitstatus).to eq(0) if exitstatus expect(the_bundle).to include_gems "signed_gem 1.0" end it "will succeed with no policy" do bundle "install" - expect(exitstatus).to eq(0) if exitstatus expect(the_bundle).to include_gems "signed_gem 1.0" end end diff --git a/ruby/spec/bundler/install/yanked_spec.rb b/ruby/spec/bundler/install/yanked_spec.rb index 80729b3f5..c5f3d788b 100644 --- a/ruby/spec/bundler/install/yanked_spec.rb +++ b/ruby/spec/bundler/install/yanked_spec.rb @@ -22,7 +22,7 @@ L - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo4)}" gem "foo", "10.0.0" G @@ -33,7 +33,7 @@ it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do bundle "config set force_ruby_platform true" - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo4)}" gem "foo", "10.0.0" G @@ -63,11 +63,42 @@ rack (= 0.9.1) L - bundle :list + bundle :list, :raise_on_error => false expect(err).to include("Could not find rack-0.9.1 in any of the sources") expect(err).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.") expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.") expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.") end + + it "does not suggest the author has yanked the gem when using more than one gem, but shows all gems that couldn't be found in the source" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", "0.9.1" + gem "rack_middleware", "1.0" + G + + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo1)} + specs: + rack (0.9.1) + rack_middleware (1.0) + + PLATFORMS + ruby + + DEPENDENCIES + rack (= 0.9.1) + rack_middleware (1.0) + L + + bundle :list, :raise_on_error => false + + expect(err).to include("Could not find rack-0.9.1, rack_middleware-1.0 in any of the sources") + expect(err).to include("Install missing gems with `bundle install`.") + expect(err).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.") + expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.") + expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.") + end end diff --git a/ruby/spec/bundler/lock/git_spec.rb b/ruby/spec/bundler/lock/git_spec.rb index 14b80483e..56db5d830 100644 --- a/ruby/spec/bundler/lock/git_spec.rb +++ b/ruby/spec/bundler/lock/git_spec.rb @@ -5,6 +5,7 @@ build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :git => "#{lib_path("foo-1.0")}" G end diff --git a/ruby/spec/bundler/lock/lockfile_spec.rb b/ruby/spec/bundler/lock/lockfile_spec.rb index ddab4831a..561de9f3b 100644 --- a/ruby/spec/bundler/lock/lockfile_spec.rb +++ b/ruby/spec/bundler/lock/lockfile_spec.rb @@ -1,18 +1,20 @@ # frozen_string_literal: true RSpec.describe "the lockfile format" do - include Bundler::GemHelpers + before do + build_repo2 + end it "generates a simple lockfile for a single source, gem" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -27,7 +29,9 @@ G end - it "updates the lockfile's bundler version if current ver. is newer" do + it "updates the lockfile's bundler version if current ver. is newer, and version was forced through BUNDLER_VERSION" do + system_gems "bundler-1.8.2" + lockfile <<-L GIT remote: git://github.com/nex3/haml.git @@ -35,7 +39,7 @@ specs: GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -50,15 +54,18 @@ 1.8.2 L - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :verbose => true, :env => { "BUNDLER_VERSION" => Bundler::VERSION } + source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.") + expect(out).to include("Using bundler #{Bundler::VERSION}") + + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -73,12 +80,12 @@ G end - it "does not update the lockfile's bundler version if nothing changed during bundle install" do - version = "#{Bundler::VERSION.split(".").first}.0.0.a" + it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version", :rubygems => ">= 3.3.0.a", :realworld => true do + version = "2.3.0" lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -92,15 +99,18 @@ #{version} L - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :verbose => true, :artifice => "vcr" + source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.") + expect(out).to include("Using bundler #{version}") + + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -115,10 +125,12 @@ G end - it "updates the lockfile's bundler version if not present" do + it "does not update the lockfile's bundler version if nothing changed during bundle install, and uses the latest version", :rubygems => "< 3.3.0.a" do + version = "#{Bundler::VERSION.split(".").first}.0.0.a" + lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -127,17 +139,23 @@ DEPENDENCIES rack + + BUNDLED WITH + #{version} L - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :verbose => true + source "#{file_uri_for(gem_repo2)}" - gem "rack", "> 0" + gem "rack" G - lockfile_should_be <<-G + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.") + expect(out).to include("Using bundler #{Bundler::VERSION}") + + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -145,20 +163,17 @@ #{lockfile_platforms} DEPENDENCIES - rack (> 0) + rack BUNDLED WITH - #{Bundler::VERSION} + #{version} G end - it "warns if the current is older than lockfile's bundler version" do - current_version = Bundler::VERSION - newer_minor = bump_minor(current_version) - + it "adds the BUNDLED WITH section if not present" do lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -167,27 +182,17 @@ DEPENDENCIES rack - - BUNDLED WITH - #{newer_minor} L install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo2)}" - gem "rack" + gem "rack", "> 0" G - pre_flag = prerelease?(newer_minor) ? " --pre" : "" - warning_message = "the running version of Bundler (#{current_version}) is older " \ - "than the version that created the lockfile (#{newer_minor}). " \ - "We suggest you to upgrade to the version that created the " \ - "lockfile by running `gem install bundler:#{newer_minor}#{pre_flag}`." - expect(err).to include warning_message - - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -195,20 +200,22 @@ #{lockfile_platforms} DEPENDENCIES - rack + rack (> 0) BUNDLED WITH - #{newer_minor} + #{Bundler::VERSION} G end - it "warns when updating bundler major version" do + it "update the bundler major version just fine" do current_version = Bundler::VERSION older_major = previous_major(current_version) + system_gems "bundler-#{older_major}" + lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -222,20 +229,17 @@ #{older_major} L - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION } + source "#{file_uri_for(gem_repo2)}/" gem "rack" G - expect(err).to include( - "Warning: the lockfile is being updated to Bundler " \ - "#{current_version.split(".").first}, after which you will be unable to return to Bundler #{older_major.split(".").first}." - ) + expect(err).to be_empty - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -252,14 +256,14 @@ it "generates a simple lockfile for a single source, gem with dependencies" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack-obama" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) rack-obama (1.0) @@ -278,14 +282,14 @@ it "generates a simple lockfile for a single source, gem with a version requirement" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack-obama", ">= 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) rack-obama (1.0) @@ -302,43 +306,12 @@ G end - it "generates a lockfile without credentials for a configured source", :bundler => "< 3" do + it "generates a lockfile without credentials for a configured source" do bundle "config set http://localgemserver.test/ user:pass" install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) - source "http://localgemserver.test/" do - - end - - source "http://user:pass@othergemserver.test/" do - gem "rack-obama", ">= 1.0" - end - G - - lockfile_should_be <<-G - GEM - remote: http://localgemserver.test/ - remote: http://user:pass@othergemserver.test/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack-obama (>= 1.0)! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates a lockfile without credentials for a configured source", :bundler => "3" do - bundle "config set http://localgemserver.test/ user:pass" + source "#{file_uri_for(gem_repo1)}" - install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) source "http://localgemserver.test/" do end @@ -348,8 +321,9 @@ end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM + remote: #{file_uri_for(gem_repo1)}/ specs: GEM @@ -376,13 +350,13 @@ it "generates lockfiles with multiple requirements" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "net-sftp" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: net-sftp (1.1.1) net-ssh (>= 1.0.0, < 1.99.0) @@ -401,42 +375,15 @@ expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0" end - it "generates a simple lockfile for a single pinned source, gem with a version requirement", :bundler => "< 3" do - git = build_git "foo" - - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}" - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - it "generates a simple lockfile for a single pinned source, gem with a version requirement" do git = build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("master")} @@ -444,6 +391,7 @@ foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -461,7 +409,7 @@ build_lib "omg", :path => lib_path("omg") gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" platforms :#{not_local_tag} do gem "omg", :path => "#{lib_path("omg")}" @@ -477,7 +425,7 @@ specs: GEM - remote: #{file_uri_for(gem_repo1)}// + remote: #{file_uri_for(gem_repo2)}// specs: rack (1.0.0) @@ -492,7 +440,7 @@ #{Bundler::VERSION} L - bundle! "install" + bundle "install" expect(the_bundle).to include_gems "rack 1.0.0" end @@ -500,12 +448,13 @@ git = build_git "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do gem "foo" end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("master")} @@ -513,6 +462,7 @@ foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -531,10 +481,11 @@ update_git "foo", :branch => "omg" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -543,6 +494,7 @@ foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -561,10 +513,11 @@ update_git "foo", :tag => "omg" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -573,6 +526,7 @@ foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -590,16 +544,18 @@ build_lib "foo" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -616,21 +572,23 @@ it "serializes pinned path sources to the lockfile even when packaging" do build_lib "foo" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G bundle "config set cache_all true" - bundle! :cache - bundle! :install, :local => true + bundle :cache + bundle :install, :local => true - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -649,14 +607,14 @@ bar = build_git "bar" install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "foo", :path => "#{lib_path("foo-1.0")}" gem "bar", :git => "#{lib_path("bar-1.0")}" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("bar-1.0")} revision: #{bar.ref_for("master")} @@ -669,7 +627,7 @@ foo (1.0) GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -686,18 +644,42 @@ G end + it "removes redundant sources" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}/" + + gem "rack", :source => "#{file_uri_for(gem_repo2)}/" + G + + expect(lockfile).to eq <<~G + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + rack (1.0.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack! + + BUNDLED WITH + #{Bundler::VERSION} + G + end + it "lists gems alphabetically" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "thin" gem "actionpack" gem "rack-obama" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: actionpack (2.3.2) activesupport (= 2.3.2) @@ -723,14 +705,14 @@ it "orders dependencies' dependencies in alphabetical order" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rails" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: actionmailer (2.3.2) activesupport (= 2.3.2) @@ -746,8 +728,8 @@ actionpack (= 2.3.2) activerecord (= 2.3.2) activeresource (= 2.3.2) - rake (= 12.3.2) - rake (12.3.2) + rake (= 13.0.1) + rake (13.0.1) PLATFORMS #{lockfile_platforms} @@ -761,14 +743,24 @@ end it "orders dependencies by version" do + update_repo2 do + # Capistrano did this (at least until version 2.5.10) + # RubyGems 2.2 doesn't allow the specifying of a dependency twice + # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f + build_gem "double_deps", "1.0", :skip_validation => true do |s| + s.add_dependency "net-ssh", ">= 1.0.0" + s.add_dependency "net-ssh" + end + end + install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem 'double_deps' G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: double_deps (1.0) net-ssh @@ -788,14 +780,14 @@ it "does not add the :require option to the lockfile" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack-obama", ">= 1.0", :require => "rack/obama" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) rack-obama (1.0) @@ -814,14 +806,14 @@ it "does not add the :group option to the lockfile" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack-obama", ">= 1.0", :group => :test G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) rack-obama (1.0) @@ -842,18 +834,20 @@ build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "foo" do gem "foo" end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: foo specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -871,18 +865,20 @@ build_lib "foo", :path => bundled_app(File.join("..", "foo")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "../foo" do gem "foo" end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: ../foo specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -900,18 +896,20 @@ build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path File.expand_path("../foo", __FILE__) do gem "foo" end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: foo specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -929,16 +927,18 @@ build_lib("foo", :path => tmp.join("foo")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gemspec :path => "../foo" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: ../foo specs: foo (1.0) GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -952,51 +952,10 @@ G end - it "keeps existing platforms in the lockfile", :bundler => "< 3" do - lockfile <<-G - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - rack (1.0.0) - - PLATFORMS - java - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" - - gem "rack" - G - - lockfile_should_be <<-G - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - rack (1.0.0) - - PLATFORMS - java - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "keeps existing platforms in the lockfile", :bundler => "3" do + it "keeps existing platforms in the lockfile" do lockfile <<-G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -1011,21 +970,19 @@ G install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) PLATFORMS - java - #{generic_local_platform} - #{specific_local_platform} + #{lockfile_platforms_for(["java"] + local_platforms)} DEPENDENCIES rack @@ -1035,7 +992,7 @@ G end - it "persists the spec's platform to the lockfile", :bundler => "< 3" do + it "persists the spec's specific platform to the lockfile" do build_repo2 do build_gem "platform_specific", "1.0" do |s| s.platform = Gem::Platform.new("universal-java-16") @@ -1044,51 +1001,18 @@ simulate_platform "universal-java-16" - install_gemfile! <<-G - source "#{file_uri_for(gem_repo2)}" - gem "platform_specific" - G - - lockfile_should_be <<-G - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - platform_specific (1.0-java) - - PLATFORMS - java - - DEPENDENCIES - platform_specific - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "persists the spec's platform and specific platform to the lockfile", :bundler => "3" do - build_repo2 do - build_gem "platform_specific", "1.0" do |s| - s.platform = Gem::Platform.new("universal-java-16") - end - end - - simulate_platform "universal-java-16" - - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "platform_specific" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: - platform_specific (1.0-java) platform_specific (1.0-universal-java-16) PLATFORMS - java universal-java-16 DEPENDENCIES @@ -1101,19 +1025,19 @@ it "does not add duplicate gems" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack" G install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "activesupport" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: activesupport (2.3.5) rack (1.0.0) @@ -1132,14 +1056,14 @@ it "does not add duplicate dependencies" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "rack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -1156,14 +1080,14 @@ it "does not add duplicate dependencies with versions" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0" gem "rack", "1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -1180,14 +1104,14 @@ it "does not add duplicate dependencies in different groups" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0", :group => :one gem "rack", "1.0", :group => :two G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) @@ -1203,36 +1127,36 @@ end it "raises if two different versions are used" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0" gem "rack", "1.1" G - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist expect(err).to include "rack (= 1.0) and rack (= 1.1)" end it "raises if two different sources are used" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "rack", :git => "git://hubz.com" G - expect(bundled_app("Gemfile.lock")).not_to exist - expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)" + expect(bundled_app_lock).not_to exist + expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com" end it "works correctly with multiple version dependencies" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" gem "rack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (0.9.1) @@ -1249,14 +1173,14 @@ it "captures the Ruby version in the lockfile" do install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" + source "#{file_uri_for(gem_repo2)}/" ruby '#{RUBY_VERSION}' gem "rack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack (0.9.1) @@ -1274,86 +1198,10 @@ G end - # Some versions of the Bundler 1.1 RC series introduced corrupted - # lockfiles. There were two major problems: - # - # * multiple copies of the same GIT section appeared in the lockfile - # * when this happened, those sections got multiple copies of gems - # in those sections. - it "fixes corrupted lockfiles" do - build_git "omg", :path => lib_path("omg") - revision = revision_for(lib_path("omg")) - - gemfile <<-G - source "#{file_uri_for(gem_repo1)}/" - gem "omg", :git => "#{lib_path("omg")}", :branch => 'master' - G - - bundle! :install, forgotten_command_line_options(:path => "vendor") - expect(the_bundle).to include_gems "omg 1.0" - - # Create a Gemfile.lock that has duplicate GIT sections - lockfile <<-L - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - - FileUtils.rm_rf(bundled_app("vendor")) - bundle "install" - expect(the_bundle).to include_gems "omg 1.0" - - # Confirm that duplicate specs do not appear - lockfile_should_be(<<-L) - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - it "raises a helpful error message when the lockfile is missing deps" do lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo2)}/ specs: rack_middleware (1.0) @@ -1364,8 +1212,8 @@ rack_middleware L - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" gem "rack_middleware" G @@ -1376,7 +1224,7 @@ describe "a line ending" do def set_lockfile_mtime_to_known_value time = Time.local(2000, 1, 1, 0, 0, 0) - File.utime(time, time, bundled_app("Gemfile.lock")) + File.utime(time, time, bundled_app_lock) end before(:each) do build_repo2 @@ -1389,28 +1237,42 @@ def set_lockfile_mtime_to_known_value end it "generates Gemfile.lock with \\n line endings" do - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") + expect(File.read(bundled_app_lock)).not_to match("\r\n") expect(the_bundle).to include_gems "rack 1.0" end context "during updates" do it "preserves Gemfile.lock \\n line endings" do - update_repo2 - - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") + update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + end + + expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } + expect(File.read(bundled_app_lock)).not_to match("\r\n") expect(the_bundle).to include_gems "rack 1.2" end it "preserves Gemfile.lock \\n\\r line endings" do - update_repo2 - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } + skip "needs to be adapted" if Gem.win_platform? + + update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + end + + win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n") + File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) } set_lockfile_mtime_to_known_value - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" + expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } + expect(File.read(bundled_app_lock)).to match("\r\n") + + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + expect(the_bundle).to include_gems "rack 1.2" + end end end @@ -1421,20 +1283,20 @@ def set_lockfile_mtime_to_known_value require 'bundler' Bundler.setup RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } + end.not_to change { File.mtime(bundled_app_lock) } end it "preserves Gemfile.lock \\n\\r line endings" do - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } + win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n") + File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) } set_lockfile_mtime_to_known_value expect do ruby <<-RUBY - require 'bundler' + require '#{entrypoint}' Bundler.setup RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } + end.not_to change { File.mtime(bundled_app_lock) } end end end @@ -1442,7 +1304,7 @@ def set_lockfile_mtime_to_known_value it "refuses to install if Gemfile.lock contains conflict markers" do lockfile <<-L GEM - remote: #{file_uri_for(gem_repo1)}// + remote: #{file_uri_for(gem_repo2)}// specs: <<<<<<< rack (1.0.0) @@ -1460,8 +1322,8 @@ def set_lockfile_mtime_to_known_value #{Bundler::VERSION} L - install_gemfile(<<-G) - source "#{file_uri_for(gem_repo1)}/" + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}/" gem "rack" G @@ -1469,7 +1331,7 @@ def set_lockfile_mtime_to_known_value expect(err).to match(/git checkout HEAD -- Gemfile.lock/i) end -private + private def prerelease?(version) Gem::Version.new(version).prerelease? diff --git a/ruby/spec/bundler/other/cli_dispatch_spec.rb b/ruby/spec/bundler/other/cli_dispatch_spec.rb index 0082606d7..2d6080296 100644 --- a/ruby/spec/bundler/other/cli_dispatch_spec.rb +++ b/ruby/spec/bundler/other/cli_dispatch_spec.rb @@ -2,19 +2,19 @@ RSpec.describe "bundle command names" do it "work when given fully" do - bundle "install" + bundle "install", :raise_on_error => false expect(err).to eq("Could not locate Gemfile") expect(last_command.stdboth).not_to include("Ambiguous command") end it "work when not ambiguous" do - bundle "ins" + bundle "ins", :raise_on_error => false expect(err).to eq("Could not locate Gemfile") expect(last_command.stdboth).not_to include("Ambiguous command") end it "print a friendly error when ambiguous" do - bundle "in" + bundle "in", :raise_on_error => false expect(err).to eq("Ambiguous command in matches [info, init, inject, install]") end end diff --git a/ruby/spec/bundler/other/ext_spec.rb b/ruby/spec/bundler/other/ext_spec.rb index f2a512e62..e13f62a85 100644 --- a/ruby/spec/bundler/other/ext_spec.rb +++ b/ruby/spec/bundler/other/ext_spec.rb @@ -55,7 +55,7 @@ end it "does not explode when called" do - run "Gem.source_index.refresh!" - run "Gem::SourceIndex.new([]).refresh!" + run "Gem.source_index.refresh!", :raise_on_error => false + run "Gem::SourceIndex.new([]).refresh!", :raise_on_error => false end end diff --git a/ruby/spec/bundler/other/major_deprecation_spec.rb b/ruby/spec/bundler/other/major_deprecation_spec.rb index df2fdd263..c6490ad25 100644 --- a/ruby/spec/bundler/other/major_deprecation_spec.rb +++ b/ruby/spec/bundler/other/major_deprecation_spec.rb @@ -5,7 +5,7 @@ describe "Bundler" do before do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -17,7 +17,7 @@ bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_env", :bundler => "2" do + it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do expect(deprecations).to include \ "`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \ @@ -33,7 +33,7 @@ bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_env", :bundler => "2" do + it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \ @@ -50,7 +50,7 @@ bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_system", :bundler => "2" do + it "is deprecated in favor of .unbundled_system", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \ @@ -67,7 +67,7 @@ bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_exec", :bundler => "2" do + it "is deprecated in favor of .unbundled_exec", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \ @@ -84,7 +84,7 @@ bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .load", :bundler => "2" do + it "is deprecated in favor of .load", :bundler => "< 3" do expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)" end @@ -92,9 +92,21 @@ end end + describe "bundle exec --no-keep-file-descriptors" do + before do + bundle "exec --no-keep-file-descriptors -e 1", :raise_on_error => false + end + + it "is deprecated", :bundler => "< 3" do + expect(deprecations).to include "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to" + end + + pending "is removed and shows a helpful error message about it", :bundler => "3" + end + describe "bundle update --quiet" do it "does not print any deprecations" do - bundle :update, :quiet => true + bundle :update, :quiet => true, :raise_on_error => false expect(deprecations).to be_empty end end @@ -106,25 +118,91 @@ gem "rack" G - bundle "check --path vendor/bundle" + bundle "check --path vendor/bundle", :raise_on_error => false end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `--path` flag is deprecated because it relies on being " \ "remembered across bundler invocations, which bundler will no " \ - "longer do in future versions. Instead please use `bundle config set " \ + "longer do in future versions. Instead please use `bundle config set --local " \ + "path 'vendor/bundle'`, and stop using this flag" + ) + end + + pending "fails with a helpful error", :bundler => "3" + end + + context "bundle check --path=" do + before do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle "check --path=vendor/bundle", :raise_on_error => false + end + + it "should print a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include( + "The `--path` flag is deprecated because it relies on being " \ + "remembered across bundler invocations, which bundler will no " \ + "longer do in future versions. Instead please use `bundle config set --local " \ "path 'vendor/bundle'`, and stop using this flag" ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" + end + + context "bundle cache --all" do + before do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle "cache --all", :raise_on_error => false + end + + it "should print a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include( + "The `--all` flag is deprecated because it relies on being " \ + "remembered across bundler invocations, which bundler will no " \ + "longer do in future versions. Instead please use `bundle config set " \ + "cache_all true`, and stop using this flag" + ) + end + + pending "fails with a helpful error", :bundler => "3" + end + + context "bundle cache --path" do + before do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle "cache --path foo", :raise_on_error => false + end + + it "should print a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include( + "The `--path` flag is deprecated because its semantics are unclear. " \ + "Use `bundle config cache_path` to configure the path of your cache of gems, " \ + "and `bundle config path` to configure the path where your gems are installed, " \ + "and stop using this flag" + ) + end + + pending "fails with a helpful error", :bundler => "3" end describe "bundle config" do describe "old list interface" do before do - bundle! "config" + bundle "config" end it "warns", :bundler => "3" do @@ -136,7 +214,7 @@ describe "old get interface" do before do - bundle! "config waka" + bundle "config waka" end it "warns", :bundler => "3" do @@ -148,7 +226,7 @@ describe "old set interface" do before do - bundle! "config waka wakapun" + bundle "config waka wakapun" end it "warns", :bundler => "3" do @@ -160,7 +238,7 @@ describe "old set interface with --local" do before do - bundle! "config --local waka wakapun" + bundle "config --local waka wakapun" end it "warns", :bundler => "3" do @@ -172,7 +250,7 @@ describe "old set interface with --global" do before do - bundle! "config --global waka wakapun" + bundle "config --global waka wakapun" end it "warns", :bundler => "3" do @@ -184,7 +262,7 @@ describe "old unset interface" do before do - bundle! "config --delete waka" + bundle "config --delete waka" end it "warns", :bundler => "3" do @@ -196,7 +274,7 @@ describe "old unset interface with --local" do before do - bundle! "config --delete --local waka" + bundle "config --delete --local waka" end it "warns", :bundler => "3" do @@ -208,7 +286,7 @@ describe "old unset interface with --global" do before do - bundle! "config --delete --global waka" + bundle "config --delete --global waka" end it "warns", :bundler => "3" do @@ -228,14 +306,14 @@ end it "warns when no options are given", :bundler => "3" do - bundle! "update" + bundle "update" expect(deprecations).to include("Pass --all to `bundle update` to update everything") end pending "fails with a helpful error when no options are given", :bundler => "3" it "does not warn when --all is passed" do - bundle! "update --all" + bundle "update --all" expect(deprecations).to be_empty end end @@ -248,8 +326,8 @@ G end - it "should output a deprecation warning", :bundler => "2" do - expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs`") + it "should output a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`") end pending "fails with a helpful error", :bundler => "3" @@ -267,8 +345,8 @@ end it "should print a proper warning, and use gems.rb" do - create_file "gems.rb" - install_gemfile! <<-G + create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\"" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -292,17 +370,18 @@ end { - :clean => true, - :deployment => true, - :frozen => true, - :"no-cache" => true, - :"no-prune" => true, - :path => "vendor/bundle", - :shebang => "ruby27", - :system => true, - :without => "development", - :with => "development", - }.each do |name, value| + "clean" => ["clean", true], + "deployment" => ["deployment", true], + "frozen" => ["frozen", true], + "no-deployment" => ["deployment", false], + "no-prune" => ["no_prune", true], + "path" => ["path", "vendor/bundle"], + "shebang" => ["shebang", "ruby27"], + "system" => ["system", true], + "without" => ["without", "development"], + "with" => ["with", "development"], + }.each do |name, expectations| + option_name, value = *expectations flag_name = "--#{name}" context "with the #{flag_name} flag" do @@ -311,16 +390,16 @@ bundle "install #{flag_name} #{value}" end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `#{flag_name}` flag is deprecated because it relies on " \ "being remembered across bundler invocations, which bundler " \ "will no longer do in future versions. Instead please use " \ - "`bundle config set #{name} '#{value}'`, and stop using this flag" + "`bundle config set --local #{option_name} '#{value}'`, and stop using this flag" ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end end end @@ -333,30 +412,98 @@ G end - it "shows a deprecation", :bundler => "2" do + it "shows a deprecation", :bundler => "< 3" do + expect(deprecations).to include( + "Your Gemfile contains multiple primary sources. " \ + "Using `source` more than once without a block is a security risk, and " \ + "may result in installing unexpected gems. To resolve this warning, use " \ + "a block to indicate which gems should come from the secondary source." + ) + end + + it "doesn't show lockfile deprecations if there's a lockfile", :bundler => "< 3" do + bundle "install" + expect(deprecations).to include( "Your Gemfile contains multiple primary sources. " \ "Using `source` more than once without a block is a security risk, and " \ "may result in installing unexpected gems. To resolve this warning, use " \ - "a block to indicate which gems should come from the secondary source. " \ - "To upgrade this warning to an error, run `bundle config set " \ - "disable_multisource true`." + "a block to indicate which gems should come from the secondary source." + ) + expect(deprecations).not_to include( + "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \ + "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure." + ) + bundle "config set --local frozen true" + bundle "install" + + expect(deprecations).to include( + "Your Gemfile contains multiple primary sources. " \ + "Using `source` more than once without a block is a security risk, and " \ + "may result in installing unexpected gems. To resolve this warning, use " \ + "a block to indicate which gems should come from the secondary source." + ) + expect(deprecations).not_to include( + "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \ + "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure." ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" + end + + context "bundle install in frozen mode with a lockfile with a single rubygems section with multiple remotes" do + before do + build_repo gem_repo3 do + build_gem "rack", "0.9.1" + end + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + source "#{file_uri_for(gem_repo3)}" do + gem 'rack' + end + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + remote: #{file_uri_for(gem_repo3)}/ + specs: + rack (0.9.1) + + PLATFORMS + ruby + + DEPENDENCIES + rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "config set --local frozen true" + end + + it "shows a deprecation", :bundler => "< 3" do + bundle "install" + + expect(deprecations).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.") + end + + pending "fails with a helpful error", :bundler => "3" end context "when Bundler.setup is run in a ruby script" do before do - create_file "gems.rb" - install_gemfile! <<-G + create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\"" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", :group => :test G ruby <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.setup Bundler.setup @@ -372,191 +519,132 @@ context "when `bundler/deployment` is required in a ruby script" do before do - ruby(<<-RUBY) + ruby(<<-RUBY, :env => env_for_missing_prerelease_default_gem_activation) require 'bundler/deployment' RUBY end - it "should print a capistrano deprecation warning", :bundler => "2" do + it "should print a capistrano deprecation warning", :bundler => "< 3" do expect(deprecations).to include("Bundler no longer integrates " \ "with Capistrano, but Capistrano provides " \ "its own integration with Bundler via the " \ "capistrano-bundler gem. Use it instead.") end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end - describe Bundler::Dsl do + context "bundle show" do before do - @rubygems = double("rubygems") - allow(Bundler::Source::Rubygems).to receive(:new) { @rubygems } - end - - context "with github gems" do - it "warns about removal", :bundler => "2" do - msg = <<-EOS -The :github git source is deprecated, and will be removed in the future. Change any "reponame" :github sources to "username/reponame". Add this code to the top of your Gemfile to ensure it continues to work: - - git_source(:github) {|repo_name| "https://github.com/\#{repo_name}.git" } - - EOS - expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg) - subject.gem("sparks", :github => "indirect/sparks") - github_uri = "https://github.com/indirect/sparks.git" - expect(subject.dependencies.first.source.uri).to eq(github_uri) - end - - pending "should fail with a helpful error", :bundler => "3" - end - - context "with bitbucket gems" do - it "warns about removal", :bundler => "2" do - allow(Bundler.ui).to receive(:deprecate) - msg = <<-EOS -The :bitbucket git source is deprecated, and will be removed in the future. Add this code to the top of your Gemfile to ensure it continues to work: - - git_source(:bitbucket) do |repo_name| - user_name, repo_name = repo_name.split("/") - repo_name ||= user_name - "https://\#{user_name}@bitbucket.org/\#{user_name}/\#{repo_name}.git" + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G end - EOS - expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg) - subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails") + context "with --outdated flag" do + before do + bundle "show --outdated" end - pending "should fail with a helpful error", :bundler => "3" - end - - context "with gist gems" do - it "warns about removal", :bundler => "2" do - allow(Bundler.ui).to receive(:deprecate) - msg = <<-EOS -The :gist git source is deprecated, and will be removed in the future. Add this code to the top of your Gemfile to ensure it continues to work: - - git_source(:gist) {|repo_name| "https://gist.github.com/\#{repo_name}.git" } - - EOS - expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg) - subject.gem("not-really-a-gem", :gist => "1234") + it "prints a deprecation warning informing about its removal", :bundler => "< 3" do + expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful message", :bundler => "3" end end - context "bundle show" do + context "bundle remove" do before do - install_gemfile! <<-G + gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G end - context "without flags" do - before do - bundle! :show - end + context "with --install" do + it "shows a deprecation warning", :bundler => "< 3" do + bundle "remove rack --install" - it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do - expect(deprecations).to include("use `bundle list` instead of `bundle show`") + expect(err).to include "[DEPRECATED] The `--install` flag has been deprecated. `bundle install` is triggered by default." end pending "fails with a helpful message", :bundler => "3" end + end - context "with --outdated flag" do - before do - bundle! "show --outdated" - end - - it "prints a deprecation warning informing about its removal", :bundler => "2" do - expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") - end + context "bundle console" do + before do + bundle "console", :raise_on_error => false + end - pending "fails with a helpful message", :bundler => "3" + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include \ + "bundle console will be replaced by `bin/console` generated by `bundle gem `" end - context "with --verbose flag" do - before do - bundle! "show --verbose" - end + pending "fails with a helpful message", :bundler => "3" + end - it "prints a deprecation warning informing about its removal", :bundler => "2" do - expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement") - end + context "bundle viz" do + before do + graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4" + realworld_system_gems "ruby-graphviz --version #{graphviz_version}" + create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\"" + bundle "viz" + end - pending "fails with a helpful message", :bundler => "3" + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph" end - context "with a gem argument" do + pending "fails with a helpful message", :bundler => "3" + end + + describe "deprecating rubocop", :readline do + context "bundle gem --rubocop" do before do - bundle! "show rack" + bundle "gem my_new_gem --rubocop", :raise_on_error => false end - it "prints a deprecation warning recommending `bundle info`", :bundler => "2" do - expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`") + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include \ + "--rubocop is deprecated, use --linter=rubocop" end - - pending "fails with a helpful message", :bundler => "3" end - context "with the --paths option" do + context "bundle gem --no-rubocop" do before do - bundle "show --paths" + bundle "gem my_new_gem --no-rubocop", :raise_on_error => false end - it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do - expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`") + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include \ + "--no-rubocop is deprecated, use --linter" end - - pending "fails with a helpful message", :bundler => "3" end - context "with a gem argument and the --paths option" do + context "bundle gem with gem.rubocop set to true" do before do - bundle "show rack --paths" + bundle "gem my_new_gem", :env => { "BUNDLE_GEM__RUBOCOP" => "true" }, :raise_on_error => false end - it "prints deprecation warning recommending `bundle info`", :bundler => "2" do - expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`") + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include \ + "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead" end - - pending "fails with a helpful message", :bundler => "3" end - end - context "bundle console" do - before do - bundle "console" - end - - it "prints a deprecation warning", :bundler => "2" do - expect(deprecations).to include \ - "bundle console will be replaced by `bin/console` generated by `bundle gem `" - end - - pending "fails with a helpful message", :bundler => "3" - end - - context "bundle viz" do - let(:ruby_graphviz) do - graphviz_glob = base_system_gems.join("cache/ruby-graphviz*") - Pathname.glob(graphviz_glob).first - end - - before do - system_gems ruby_graphviz - create_file "gems.rb" - bundle "viz" - end + context "bundle gem with gem.rubocop set to false" do + before do + bundle "gem my_new_gem", :env => { "BUNDLE_GEM__RUBOCOP" => "false" }, :raise_on_error => false + end - it "prints a deprecation warning", :bundler => "2" do - expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz" + it "prints a deprecation warning", :bundler => "< 3" do + expect(deprecations).to include \ + "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead" + end end - - pending "fails with a helpful message", :bundler => "3" end end diff --git a/ruby/spec/bundler/other/platform_spec.rb b/ruby/spec/bundler/other/platform_spec.rb index 8b02505ad..bf38a0564 100644 --- a/ruby/spec/bundler/other/platform_spec.rb +++ b/ruby/spec/bundler/other/platform_spec.rb @@ -17,7 +17,7 @@ bundle "platform" expect(out).to eq(<<-G.chomp) -Your platform is: #{RUBY_PLATFORM} +Your platform is: #{Gem::Platform.local} Your app has gems that work on these platforms: #{bundle_platform_platforms_string} @@ -40,7 +40,7 @@ bundle "platform" expect(out).to eq(<<-G.chomp) -Your platform is: #{RUBY_PLATFORM} +Your platform is: #{Gem::Platform.local} Your app has gems that work on these platforms: #{bundle_platform_platforms_string} @@ -61,7 +61,7 @@ bundle "platform" expect(out).to eq(<<-G.chomp) -Your platform is: #{RUBY_PLATFORM} +Your platform is: #{Gem::Platform.local} Your app has gems that work on these platforms: #{bundle_platform_platforms_string} @@ -81,7 +81,7 @@ bundle "platform" expect(out).to eq(<<-G.chomp) -Your platform is: #{RUBY_PLATFORM} +Your platform is: #{Gem::Platform.local} Your app has gems that work on these platforms: #{bundle_platform_platforms_string} @@ -168,9 +168,9 @@ gem "foo" G - bundle "platform" + bundle "platform", :raise_on_error => false - expect(exitstatus).not_to eq(0) if exitstatus + expect(exitstatus).not_to eq(0) end it "raises an error if engine_version is used but engine is not" do @@ -181,9 +181,9 @@ gem "foo" G - bundle "platform" + bundle "platform", :raise_on_error => false - expect(exitstatus).not_to eq(0) if exitstatus + expect(exitstatus).not_to eq(0) end it "raises an error if engine version doesn't match ruby version for MRI" do @@ -194,9 +194,9 @@ gem "foo" G - bundle "platform" + bundle "platform", :raise_on_error => false - expect(exitstatus).not_to eq(0) if exitstatus + expect(exitstatus).not_to eq(0) end it "should print if no ruby version is specified" do @@ -213,11 +213,13 @@ it "handles when there is a locked requirement" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" ruby "< 1.8.7" G lockfile <<-L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: PLATFORMS @@ -232,25 +234,27 @@ #{Bundler::VERSION} L - bundle! "platform --ruby" + bundle "platform --ruby" expect(out).to eq("ruby 1.0.0p127") end it "handles when there is a requirement in the gemfile" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" ruby ">= 1.8.7" G - bundle! "platform --ruby" + bundle "platform --ruby" expect(out).to eq("ruby 1.8.7") end it "handles when there are multiple requirements in the gemfile" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" ruby ">= 1.8.7", "< 2.0.0" G - bundle! "platform --ruby" + bundle "platform --ruby" expect(out).to eq("ruby 1.8.7") end end @@ -265,27 +269,27 @@ let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" } def should_be_ruby_version_incorrect - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) expect(err).to be_include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}") end def should_be_engine_incorrect - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) expect(err).to be_include("Your Ruby engine is #{local_ruby_engine}, but your Gemfile specified #{not_local_tag}") end def should_be_engine_version_incorrect - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) expect(err).to be_include("Your #{local_ruby_engine} version is #{local_engine_version}, but your Gemfile specified #{local_ruby_engine} #{not_local_engine_version}") end def should_be_patchlevel_incorrect - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) expect(err).to be_include("Your Ruby patchlevel is #{RUBY_PATCHLEVEL}, but your Gemfile specified #{not_local_patchlevel}") end def should_be_patchlevel_fixnum - expect(exitstatus).to eq(18) if exitstatus + expect(exitstatus).to eq(18) expect(err).to be_include("The Ruby patchlevel in your Gemfile must be a string") end @@ -298,20 +302,18 @@ def should_be_patchlevel_fixnum #{ruby_version_correct} G - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end - it "installs fine with any engine" do - simulate_ruby_engine "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" + it "installs fine with any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - expect(bundled_app("Gemfile.lock")).to exist - end + expect(bundled_app_lock).to exist end it "installs fine when the patchlevel matches" do @@ -322,56 +324,54 @@ def should_be_patchlevel_fixnum #{ruby_version_correct_patchlevel} G - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end it "doesn't install when the ruby version doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" #{ruby_version_incorrect} G - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_ruby_version_incorrect end it "doesn't install when engine doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" #{engine_incorrect} G - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_engine_incorrect end - it "doesn't install when engine version doesn't match" do - simulate_ruby_engine "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" + it "doesn't install when engine version doesn't match", :jruby do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" + gem "rack" - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - expect(bundled_app("Gemfile.lock")).not_to exist - should_be_engine_version_incorrect - end + expect(bundled_app_lock).not_to exist + should_be_engine_version_incorrect end it "doesn't install when patchlevel doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" #{patchlevel_incorrect} G - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_patchlevel_incorrect end end @@ -391,28 +391,24 @@ def should_be_patchlevel_fixnum G bundle :check - expect(exitstatus).to eq(0) if exitstatus - expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied") + expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/) end - it "checks fine with any engine" do - simulate_ruby_engine "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - G + it "checks fine with any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle :check - expect(exitstatus).to eq(0) if exitstatus - expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied") - end + bundle :check + expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/) end it "fails when ruby version doesn't match" do @@ -428,7 +424,7 @@ def should_be_patchlevel_fixnum #{ruby_version_incorrect} G - bundle :check + bundle :check, :raise_on_error => false should_be_ruby_version_incorrect end @@ -445,27 +441,25 @@ def should_be_patchlevel_fixnum #{engine_incorrect} G - bundle :check + bundle :check, :raise_on_error => false should_be_engine_incorrect end - it "fails when engine version doesn't match" do - simulate_ruby_engine "ruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - G + it "fails when engine version doesn't match", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle :check - should_be_engine_version_incorrect - end + bundle :check, :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do @@ -481,7 +475,7 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - bundle :check + bundle :check, :raise_on_error => false should_be_patchlevel_incorrect end end @@ -506,6 +500,10 @@ def should_be_patchlevel_fixnum #{ruby_version_correct} G update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" + end + build_gem "activesupport", "3.0" end @@ -513,22 +511,24 @@ def should_be_patchlevel_fixnum expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0" end - it "updates fine with any engine" do - simulate_ruby_engine "jruby" do - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - gem "rack-obama" + it "updates fine with any engine", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" - #{ruby_version_correct_engineless} - G - update_repo2 do - build_gem "activesupport", "3.0" + #{ruby_version_correct_engineless} + G + update_repo2 do + build_gem "rack", "1.2" do |s| + s.executables = "rackup" end - bundle "update", :all => true - expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0" + build_gem "activesupport", "3.0" end + + bundle "update", :all => true + expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0" end it "fails when ruby version doesn't match" do @@ -543,11 +543,11 @@ def should_be_patchlevel_fixnum build_gem "activesupport", "3.0" end - bundle :update, :all => true + bundle :update, :all => true, :raise_on_error => false should_be_ruby_version_incorrect end - it "fails when ruby engine doesn't match" do + it "fails when ruby engine doesn't match", :jruby do gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "activesupport" @@ -559,26 +559,24 @@ def should_be_patchlevel_fixnum build_gem "activesupport", "3.0" end - bundle :update, :all => true + bundle :update, :all => true, :raise_on_error => false should_be_engine_incorrect end - it "fails when ruby engine version doesn't match" do - simulate_ruby_engine "jruby" do - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport" - gem "rack-obama" - - #{engine_version_incorrect} - G - update_repo2 do - build_gem "activesupport", "3.0" - end + it "fails when ruby engine version doesn't match", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport" + gem "rack-obama" - bundle :update, :all => true - should_be_engine_version_incorrect + #{engine_version_incorrect} + G + update_repo2 do + build_gem "activesupport", "3.0" end + + bundle :update, :all => true, :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do @@ -592,7 +590,7 @@ def should_be_patchlevel_fixnum build_gem "activesupport", "3.0" end - bundle :update, :all => true + bundle :update, :all => true, :raise_on_error => false should_be_patchlevel_incorrect end end @@ -606,7 +604,7 @@ def should_be_patchlevel_fixnum end it "prints path if ruby version is correct" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rails" @@ -617,18 +615,16 @@ def should_be_patchlevel_fixnum expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s) end - it "prints path if ruby version is correct for any engine" do - simulate_ruby_engine "jruby" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rails" + it "prints path if ruby version is correct for any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rails" - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle "info rails --path" - expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s) - end + bundle "info rails --path" + expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s) end it "fails if ruby version doesn't match", :bundler => "< 3" do @@ -639,7 +635,7 @@ def should_be_patchlevel_fixnum #{ruby_version_incorrect} G - bundle "show rails" + bundle "show rails", :raise_on_error => false should_be_ruby_version_incorrect end @@ -651,22 +647,20 @@ def should_be_patchlevel_fixnum #{engine_incorrect} G - bundle "show rails" + bundle "show rails", :raise_on_error => false should_be_engine_incorrect end - it "fails if engine version doesn't match", :bundler => "< 3" do - simulate_ruby_engine "jruby" do - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rails" + it "fails if engine version doesn't match", :bundler => "< 3", :jruby => true do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rails" - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle "show rails" - should_be_engine_version_incorrect - end + bundle "show rails", :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match", :bundler => "< 3" do @@ -680,7 +674,7 @@ def should_be_patchlevel_fixnum build_gem "activesupport", "3.0" end - bundle "show rails" + bundle "show rails", :raise_on_error => false should_be_patchlevel_incorrect end end @@ -695,6 +689,7 @@ def should_be_patchlevel_fixnum it "copies the .gem file to vendor/cache when ruby version matches" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{ruby_version_correct} @@ -704,53 +699,52 @@ def should_be_patchlevel_fixnum expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist end - it "copies the .gem file to vendor/cache when ruby version matches for any engine" do - simulate_ruby_engine "jruby" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - gem 'rack' + it "copies the .gem file to vendor/cache when ruby version matches for any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle! :cache - expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist - end + bundle :cache + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist end it "fails if the ruby version doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{ruby_version_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_ruby_version_incorrect end it "fails if the engine doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{engine_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_engine_incorrect end - it "fails if the engine version doesn't match" do - simulate_ruby_engine "jruby" do - gemfile <<-G - gem 'rack' + it "fails if the engine version doesn't match", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle :cache - should_be_engine_version_incorrect - end + bundle :cache, :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do @@ -761,14 +755,14 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_patchlevel_incorrect end end context "bundle pack" do before do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem 'rack' G @@ -776,6 +770,7 @@ def should_be_patchlevel_fixnum it "copies the .gem file to vendor/cache when ruby version matches" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{ruby_version_correct} @@ -785,53 +780,52 @@ def should_be_patchlevel_fixnum expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist end - it "copies the .gem file to vendor/cache when ruby version matches any engine" do - simulate_ruby_engine "jruby" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo1)}" - gem 'rack' + it "copies the .gem file to vendor/cache when ruby version matches any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle :cache - expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist - end + bundle :cache + expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist end it "fails if the ruby version doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{ruby_version_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_ruby_version_incorrect end it "fails if the engine doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack' #{engine_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_engine_incorrect end - it "fails if the engine version doesn't match" do - simulate_ruby_engine "jruby" do - gemfile <<-G - gem 'rack' + it "fails if the engine version doesn't match", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack' - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle :cache - should_be_engine_version_incorrect - end + bundle :cache, :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do @@ -842,7 +836,7 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - bundle :cache + bundle :cache, :raise_on_error => false should_be_patchlevel_incorrect end end @@ -850,11 +844,12 @@ def should_be_patchlevel_fixnum context "bundle exec" do before do ENV["BUNDLER_FORCE_TTY"] = "true" - system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path + system_gems "rack-1.0.0", "rack-0.9.1", :path => default_bundle_path end it "activates the correct gem when ruby version matches" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" #{ruby_version_correct} @@ -864,53 +859,52 @@ def should_be_patchlevel_fixnum expect(out).to include("0.9.1") end - it "activates the correct gem when ruby version matches any engine" do - simulate_ruby_engine "jruby" do - system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path - gemfile <<-G - gem "rack", "0.9.1" + it "activates the correct gem when ruby version matches any engine", :jruby do + system_gems "rack-1.0.0", "rack-0.9.1", :path => default_bundle_path + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", "0.9.1" - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle "exec rackup" - expect(out).to include("0.9.1") - end + bundle "exec rackup" + expect(out).to include("0.9.1") end it "fails when the ruby version doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" #{ruby_version_incorrect} G - bundle "exec rackup" + bundle "exec rackup", :raise_on_error => false should_be_ruby_version_incorrect end it "fails when the engine doesn't match" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" #{engine_incorrect} G - bundle "exec rackup" + bundle "exec rackup", :raise_on_error => false should_be_engine_incorrect end - # it "fails when the engine version doesn't match" do - # simulate_ruby_engine "jruby" do - # gemfile <<-G - # gem "rack", "0.9.1" + # it "fails when the engine version doesn't match", :jruby do + # gemfile <<-G + # gem "rack", "0.9.1" # - # #{engine_version_incorrect} - # G + # #{engine_version_incorrect} + # G # - # bundle "exec rackup" - # should_be_engine_version_incorrect - # end + # bundle "exec rackup" + # should_be_engine_version_incorrect # end it "fails when patchlevel doesn't match" do @@ -921,7 +915,7 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - bundle "exec rackup" + bundle "exec rackup", :raise_on_error => false should_be_patchlevel_incorrect end end @@ -936,7 +930,7 @@ def should_be_patchlevel_fixnum G end - it "starts IRB with the default group loaded when ruby version matches" do + it "starts IRB with the default group loaded when ruby version matches", :readline do gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -953,23 +947,21 @@ def should_be_patchlevel_fixnum expect(out).to include("0.9.1") end - it "starts IRB with the default group loaded when ruby version matches any engine" do - simulate_ruby_engine "jruby" do - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - gem "activesupport", :group => :test - gem "rack_middleware", :group => :development + it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - bundle "console" do |input, _, _| - input.puts("puts RACK") - input.puts("exit") - end - expect(out).to include("0.9.1") + bundle "console" do |input, _, _| + input.puts("puts RACK") + input.puts("exit") end + expect(out).to include("0.9.1") end it "fails when ruby version doesn't match" do @@ -982,7 +974,7 @@ def should_be_patchlevel_fixnum #{ruby_version_incorrect} G - bundle "console" + bundle "console", :raise_on_error => false should_be_ruby_version_incorrect end @@ -996,24 +988,22 @@ def should_be_patchlevel_fixnum #{engine_incorrect} G - bundle "console" + bundle "console", :raise_on_error => false should_be_engine_incorrect end - it "fails when engine version doesn't match" do - simulate_ruby_engine "jruby" do - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - gem "activesupport", :group => :test - gem "rack_middleware", :group => :development + it "fails when engine version doesn't match", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + gem "activesupport", :group => :test + gem "rack_middleware", :group => :development - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle "console" - should_be_engine_version_incorrect - end + bundle "console", :raise_on_error => false + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do @@ -1026,7 +1016,7 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - bundle "console" + bundle "console", :raise_on_error => false should_be_patchlevel_incorrect end end @@ -1051,31 +1041,29 @@ def should_be_patchlevel_fixnum #{ruby_version_correct} G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) run "1" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end - it "makes a Gemfile.lock if setup succeeds for any engine" do - simulate_ruby_engine "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "yard" - gem "rack" + it "makes a Gemfile.lock if setup succeeds for any engine", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "yard" + gem "rack" - #{ruby_version_correct_engineless} - G + #{ruby_version_correct_engineless} + G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) - run "1" - expect(bundled_app("Gemfile.lock")).to exist - end + run "1" + expect(bundled_app_lock).to exist end it "fails when ruby version doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "yard" gem "rack" @@ -1083,18 +1071,16 @@ def should_be_patchlevel_fixnum #{ruby_version_incorrect} G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) - ruby <<-R - require 'bundler/setup' - R + ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_ruby_version_incorrect end it "fails when engine doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "yard" gem "rack" @@ -1102,39 +1088,33 @@ def should_be_patchlevel_fixnum #{engine_incorrect} G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) - ruby <<-R - require 'bundler/setup' - R + ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_engine_incorrect end - it "fails when engine version doesn't match" do - simulate_ruby_engine "jruby" do - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "yard" - gem "rack" + it "fails when engine version doesn't match", :jruby do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo1)}" + gem "yard" + gem "rack" - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) - ruby <<-R - require 'bundler/setup' - R + ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false - expect(bundled_app("Gemfile.lock")).not_to exist - should_be_engine_version_incorrect - end + expect(bundled_app_lock).not_to exist + should_be_engine_version_incorrect end it "fails when patchlevel doesn't match" do - install_gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "yard" gem "rack" @@ -1142,13 +1122,11 @@ def should_be_patchlevel_fixnum #{patchlevel_incorrect} G - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) - ruby <<-R - require 'bundler/setup' - R + ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist should_be_patchlevel_incorrect end end @@ -1180,31 +1158,41 @@ def should_be_patchlevel_fixnum #{ruby_version_correct} G - bundle "outdated" - expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5") - expect(out).to include("foo (newest 1.0") + bundle "outdated", :raise_on_error => false + + expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 default + foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default + TABLE + + expect(out).to match(Regexp.new(expected_output)) end - it "returns list of outdated gems when the ruby version matches for any engine" do - simulate_ruby_engine "jruby" do - bundle! :install - update_repo2 do - build_gem "activesupport", "3.0" - update_git "foo", :path => lib_path("foo") - end + it "returns list of outdated gems when the ruby version matches for any engine", :jruby do + bundle :install + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path("foo")}" + + #{ruby_version_correct_engineless} + G - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport", "2.3.5" - gem "foo", :git => "#{lib_path("foo")}" + bundle "outdated", :raise_on_error => false - #{ruby_version_correct_engineless} - G + expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip + Gem Current Latest Requested Groups + activesupport 2.3.5 3.0 = 2.3.5 default + foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default + TABLE - bundle "outdated" - expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)") - expect(out).to include("foo (newest 1.0") - end + expect(out).to match(Regexp.new(expected_output)) end it "fails when the ruby version doesn't match" do @@ -1221,7 +1209,7 @@ def should_be_patchlevel_fixnum #{ruby_version_incorrect} G - bundle "outdated" + bundle "outdated", :raise_on_error => false should_be_ruby_version_incorrect end @@ -1239,68 +1227,62 @@ def should_be_patchlevel_fixnum #{engine_incorrect} G - bundle "outdated" + bundle "outdated", :raise_on_error => false should_be_engine_incorrect end - it "fails when the engine version doesn't match" do - simulate_ruby_engine "jruby" do - update_repo2 do - build_gem "activesupport", "3.0" - update_git "foo", :path => lib_path("foo") - end + it "fails when the engine version doesn't match", :jruby do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport", "2.3.5" - gem "foo", :git => "#{lib_path("foo")}" + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path("foo")}" - #{engine_version_incorrect} - G + #{engine_version_incorrect} + G - bundle "outdated" - should_be_engine_version_incorrect - end + bundle "outdated", :raise_on_error => false + should_be_engine_version_incorrect end - it "fails when the patchlevel doesn't match" do - simulate_ruby_engine "jruby" do - update_repo2 do - build_gem "activesupport", "3.0" - update_git "foo", :path => lib_path("foo") - end + it "fails when the patchlevel doesn't match", :jruby do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport", "2.3.5" - gem "foo", :git => "#{lib_path("foo")}" + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path("foo")}" - #{patchlevel_incorrect} - G + #{patchlevel_incorrect} + G - bundle "outdated" - should_be_patchlevel_incorrect - end + bundle "outdated", :raise_on_error => false + should_be_patchlevel_incorrect end - it "fails when the patchlevel is a fixnum" do - simulate_ruby_engine "jruby" do - update_repo2 do - build_gem "activesupport", "3.0" - update_git "foo", :path => lib_path("foo") - end + it "fails when the patchlevel is a fixnum", :jruby do + update_repo2 do + build_gem "activesupport", "3.0" + update_git "foo", :path => lib_path("foo") + end - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gem "activesupport", "2.3.5" - gem "foo", :git => "#{lib_path("foo")}" + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", "2.3.5" + gem "foo", :git => "#{lib_path("foo")}" - #{patchlevel_fixnum} - G + #{patchlevel_fixnum} + G - bundle "outdated" - should_be_patchlevel_fixnum - end + bundle "outdated", :raise_on_error => false + should_be_patchlevel_fixnum end end end diff --git a/ruby/spec/bundler/plugins/command_spec.rb b/ruby/spec/bundler/plugins/command_spec.rb index 4728f66f5..3a7adf4b4 100644 --- a/ruby/spec/bundler/plugins/command_spec.rb +++ b/ruby/spec/bundler/plugins/command_spec.rb @@ -69,12 +69,10 @@ def exec(command, args) end end - bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}" + bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}", :raise_on_error => false expect(out).not_to include("Installed plugin copycat") - expect(err).to include("Failed to install plugin") - - expect(err).to include("Command(s) `mahcommand` declared by copycat are already registered.") + expect(err).to include("Failed to install plugin `copycat`, due to Bundler::Plugin::Index::CommandConflict (Command(s) `mahcommand` declared by copycat are already registered.)") end end diff --git a/ruby/spec/bundler/plugins/install_spec.rb b/ruby/spec/bundler/plugins/install_spec.rb index 669ed09fb..009516260 100644 --- a/ruby/spec/bundler/plugins/install_spec.rb +++ b/ruby/spec/bundler/plugins/install_spec.rb @@ -9,7 +9,7 @@ end it "shows proper message when gem in not found in the source" do - bundle "plugin install no-foo --source #{file_uri_for(gem_repo1)}" + bundle "plugin install no-foo --source #{file_uri_for(gem_repo1)}", :raise_on_error => false expect(err).to include("Could not find") plugin_should_not_be_installed("no-foo") @@ -22,6 +22,19 @@ plugin_should_be_installed("foo") end + it "installs from sources configured as Gem.sources without any flags" do + bundle "plugin install foo", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s } + + expect(out).to include("Installed plugin foo") + plugin_should_be_installed("foo") + end + + it "shows help when --help flag is given" do + bundle "plugin install --help" + + expect(out).to include("bundle plugin install PLUGINS # Install the plugin from the source") + end + context "plugin is already installed" do before do bundle "plugin install foo --source #{file_uri_for(gem_repo2)}" @@ -56,6 +69,21 @@ plugin_should_be_installed("foo", "kung-foo") end + it "installs the latest version if not installed" do + update_repo2 do + build_plugin "foo", "1.1" + end + + bundle "plugin install foo --version 1.0 --source #{file_uri_for(gem_repo2)} --verbose" + expect(out).to include("Installing foo 1.0") + + bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose" + expect(out).to include("Installing foo 1.1") + + bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose" + expect(out).to include("Using foo 1.1") + end + it "works with different load paths" do build_repo2 do build_plugin "testing" do |s| @@ -96,9 +124,9 @@ def exec(command, args) build_gem "charlie" end - bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}" + bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}", :raise_on_error => false - expect(err).to include("plugins.rb was not found") + expect(err).to include("Failed to install plugin `charlie`, due to Bundler::Plugin::MalformattedPlugin (plugins.rb was not found in the plugin.)") expect(global_plugin_gem("charlie-1.0")).not_to be_directory @@ -115,7 +143,7 @@ def exec(command, args) end end - bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}" + bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}", :raise_on_error => false expect(global_plugin_gem("chaplin-1.0")).not_to be_directory @@ -147,14 +175,18 @@ def exec(command, args) end it "raises an error when both git and local git sources are specified" do - bundle "plugin install foo --local_git /phony/path/project --git git@gitphony.com:/repo/project" + bundle "plugin install foo --local_git /phony/path/project --git git@gitphony.com:/repo/project", :raise_on_error => false - expect(exitstatus).not_to eq(0) if exitstatus + expect(exitstatus).not_to eq(0) expect(err).to eq("Remote and local plugin git sources can't be both specified") end end context "Gemfile eval" do + before do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + end + it "installs plugins listed in gemfile" do gemfile <<-G source '#{file_uri_for(gem_repo2)}' @@ -197,6 +229,7 @@ def exec(command, args) end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" plugin 'ga-plugin', :git => "#{lib_path("ga-plugin-1.0")}" G @@ -204,14 +237,29 @@ def exec(command, args) plugin_should_be_installed("ga-plugin") end + it "accepts path sources" do + build_lib "ga-plugin" do |s| + s.write "plugins.rb" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + plugin 'ga-plugin', :path => "#{lib_path("ga-plugin-1.0")}" + G + + expect(out).to include("Installed plugin ga-plugin") + plugin_should_be_installed("ga-plugin") + end + context "in deployment mode" do it "installs plugins" do - install_gemfile! <<-G + install_gemfile <<-G source '#{file_uri_for(gem_repo2)}' gem 'rack', "1.0.0" G - install_gemfile! <<-G, forgotten_command_line_options(:deployment => true) + bundle "config set --local deployment true" + install_gemfile <<-G source '#{file_uri_for(gem_repo2)}' plugin 'foo' gem 'rack', "1.0.0" @@ -238,13 +286,14 @@ def exec(command, args) end RUBY - ruby code + ruby code, :env => { "BUNDLER_VERSION" => Bundler::VERSION } expect(local_plugin_gem("foo-1.0", "plugins.rb")).to exist end end describe "local plugin" do it "is installed when inside an app" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) gemfile "" bundle "plugin install foo --source #{file_uri_for(gem_repo2)}" @@ -287,21 +336,16 @@ def exec(command, args) end # outside the app - Dir.chdir tmp - bundle "plugin install fubar --source #{file_uri_for(gem_repo2)}" + bundle "plugin install fubar --source #{file_uri_for(gem_repo2)}", :dir => tmp end it "inside the app takes precedence over global plugin" do - Dir.chdir bundled_app - bundle "shout" expect(out).to eq("local_one") end it "outside the app global plugin is used" do - Dir.chdir tmp - - bundle "shout" + bundle "shout", :dir => tmp expect(out).to eq("global_one") end end diff --git a/ruby/spec/bundler/plugins/source/example_spec.rb b/ruby/spec/bundler/plugins/source/example_spec.rb index f2151a5a7..7d098997e 100644 --- a/ruby/spec/bundler/plugins/source/example_spec.rb +++ b/ruby/spec/bundler/plugins/source/example_spec.rb @@ -33,6 +33,7 @@ def fetch_gemspec_files def install(spec, opts) mkdir_p(install_path.parent) + require 'fileutils' FileUtils.cp_r(path, install_path) spec_path = install_path.join("\#{spec.full_name}.gemspec") @@ -66,35 +67,10 @@ def install(spec, opts) expect(the_bundle).to include_gems("a-path-gem 1.0") end - it "writes to lock file", :bundler => "< 3" do + it "writes to lock file" do bundle "install" - lockfile_should_be <<-G - PLUGIN SOURCE - remote: #{lib_path("a-path-gem-1.0")} - type: mpath - specs: - a-path-gem (1.0) - - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - a-path-gem! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "writes to lock file", :bundler => "3" do - bundle "install" - - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PLUGIN SOURCE remote: #{lib_path("a-path-gem-1.0")} type: mpath @@ -155,10 +131,11 @@ def install(spec, opts) expect(the_bundle).to include_gems("a-path-gem 1.0") end - it "copies repository to vendor cache and uses it even when installed with bundle --path" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + it "copies repository to vendor cache and uses it even when installed with `path` configured" do + bundle "config set --local path vendor/bundle" + bundle :install bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist @@ -167,9 +144,10 @@ def install(spec, opts) end it "bundler package copies repository to vendor cache" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle :install bundle "config set cache_all true" - bundle! :cache + bundle :cache expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist @@ -203,7 +181,7 @@ def install(spec, opts) end it "installs" do - bundle! "install" + bundle "install" expect(the_bundle).to include_gems("a-path-gem 1.0") end @@ -215,6 +193,8 @@ def install(spec, opts) build_repo2 do build_plugin "bundler-source-gitp" do |s| s.write "plugins.rb", <<-RUBY + require "open3" + class SPlugin < Bundler::Plugin::API source "gitp" @@ -254,9 +234,7 @@ def install(spec, opts) mkdir_p(install_path.dirname) rm_rf(install_path) `git clone --no-checkout --quiet "\#{cache_path}" "\#{install_path}"` - Dir.chdir install_path do - `git reset --hard \#{revision}` - end + Open3.capture2e("git reset --hard \#{revision}", :chdir => install_path) spec_path = install_path.join("\#{spec.full_name}.gemspec") spec_path.open("wb") {|f| f.write spec.to_ruby } @@ -310,9 +288,8 @@ def latest_revision cache_repo end - Dir.chdir cache_path do - `git rev-parse --verify \#{@ref}`.strip - end + output, _status = Open3.capture2e("git rev-parse --verify \#{@ref}", :chdir => cache_path) + output.strip end def base_name @@ -361,38 +338,11 @@ def installed? expect(the_bundle).to include_gems("ma-gitp-gem 1.0") end - it "writes to lock file", :bundler => "< 3" do - revision = revision_for(lib_path("ma-gitp-gem-1.0")) - bundle "install" - - lockfile_should_be <<-G - PLUGIN SOURCE - remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))} - type: gitp - revision: #{revision} - specs: - ma-gitp-gem (1.0) - - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - ma-gitp-gem! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "writes to lock file", :bundler => "3" do + it "writes to lock file" do revision = revision_for(lib_path("ma-gitp-gem-1.0")) bundle "install" - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PLUGIN SOURCE remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))} type: gitp diff --git a/ruby/spec/bundler/plugins/source_spec.rb b/ruby/spec/bundler/plugins/source_spec.rb index c8deee96b..14643e5c8 100644 --- a/ruby/spec/bundler/plugins/source_spec.rb +++ b/ruby/spec/bundler/plugins/source_spec.rb @@ -21,6 +21,7 @@ class OPSource < Bundler::Plugin::API end G + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) plugin_should_be_installed("bundler-source-psource") end @@ -75,6 +76,7 @@ class Cheater < Bundler::Plugin::API end it "installs the explicit one" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) plugin_should_be_installed("another-psource") end @@ -100,6 +102,7 @@ class Cheater < Bundler::Plugin::API end it "installs the default one" do + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) plugin_should_be_installed("bundler-source-psource") end end diff --git a/ruby/spec/bundler/plugins/uninstall_spec.rb b/ruby/spec/bundler/plugins/uninstall_spec.rb new file mode 100644 index 000000000..818024191 --- /dev/null +++ b/ruby/spec/bundler/plugins/uninstall_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +RSpec.describe "bundler plugin uninstall" do + before do + build_repo2 do + build_plugin "foo" + build_plugin "kung-foo" + end + end + + it "shows proper error message when plugins are not specified" do + bundle "plugin uninstall" + expect(err).to include("No plugins to uninstall") + end + + it "uninstalls specified plugins" do + bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}" + plugin_should_be_installed("foo") + plugin_should_be_installed("kung-foo") + + bundle "plugin uninstall foo" + expect(out).to include("Uninstalled plugin foo") + plugin_should_not_be_installed("foo") + plugin_should_be_installed("kung-foo") + end + + it "shows proper message when plugin is not installed" do + bundle "plugin uninstall foo" + expect(err).to include("Plugin foo is not installed") + plugin_should_not_be_installed("foo") + end + + describe "with --all" do + it "uninstalls all installed plugins" do + bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}" + plugin_should_be_installed("foo") + plugin_should_be_installed("kung-foo") + + bundle "plugin uninstall --all" + plugin_should_not_be_installed("foo") + plugin_should_not_be_installed("kung-foo") + end + + it "shows proper no plugins installed message when no plugins installed" do + bundle "plugin uninstall --all" + expect(out).to include("No plugins installed") + end + end +end diff --git a/ruby/spec/bundler/quality_es_spec.rb b/ruby/spec/bundler/quality_es_spec.rb index 4238ac745..90968e627 100644 --- a/ruby/spec/bundler/quality_es_spec.rb +++ b/ruby/spec/bundler/quality_es_spec.rb @@ -40,12 +40,10 @@ def check_for_specific_pronouns(filename) it "mantiene la calidad de lenguaje de la documentación" do included = /ronn/ error_messages = [] - Dir.chdir(root) do - `git ls-files -z -- man`.split("\x0").each do |filename| - next unless filename =~ included - error_messages << check_for_expendable_words(filename) - error_messages << check_for_specific_pronouns(filename) - end + man_tracked_files.each do |filename| + next unless filename =~ included + error_messages << check_for_expendable_words(filename) + error_messages << check_for_specific_pronouns(filename) end expect(error_messages.compact).to be_well_formed end @@ -53,12 +51,10 @@ def check_for_specific_pronouns(filename) it "mantiene la calidad de lenguaje de oraciones usadas en el código fuente" do error_messages = [] exempt = /vendor/ - Dir.chdir(root) do - lib_tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_expendable_words(filename) - error_messages << check_for_specific_pronouns(filename) - end + lib_tracked_files.each do |filename| + next if filename =~ exempt + error_messages << check_for_expendable_words(filename) + error_messages << check_for_specific_pronouns(filename) end expect(error_messages.compact).to be_well_formed end diff --git a/ruby/spec/bundler/quality_spec.rb b/ruby/spec/bundler/quality_spec.rb index 09e59d88a..62f3722a3 100644 --- a/ruby/spec/bundler/quality_spec.rb +++ b/ruby/spec/bundler/quality_spec.rb @@ -3,25 +3,6 @@ require "set" RSpec.describe "The library itself" do - def check_for_debugging_mechanisms(filename) - debugging_mechanisms_regex = / - (binding\.pry)| - (debugger)| - (sleep\s*\(?\d+)| - (fit\s*\(?("|\w)) - /x - - failing_lines = [] - each_line(filename) do |line, number| - if line =~ debugging_mechanisms_regex && !line.end_with?("# ignore quality_spec\n") - failing_lines << number + 1 - end - end - - return if failing_lines.empty? - "#{filename} has debugging mechanisms (like binding.pry, sleep, debugger, rspec focusing, etc.) on lines #{failing_lines.join(", ")}" - end - def check_for_git_merge_conflicts(filename) merge_conflicts_regex = / <<<<<<<| @@ -105,14 +86,12 @@ def check_for_specific_pronouns(filename) end it "has no malformed whitespace" do - exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|\.txt$/ + exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|index\.txt$/ error_messages = [] - Dir.chdir(root) do - tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_tab_characters(filename) - error_messages << check_for_extra_spaces(filename) - end + tracked_files.each do |filename| + next if filename =~ exempt + error_messages << check_for_tab_characters(filename) + error_messages << check_for_extra_spaces(filename) end expect(error_messages.compact).to be_well_formed end @@ -120,23 +99,9 @@ def check_for_specific_pronouns(filename) it "has no estraneous quotes" do exempt = /vendor|vcr_cassettes|LICENSE|rbreadline\.diff/ error_messages = [] - Dir.chdir(root) do - tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_straneous_quotes(filename) - end - end - expect(error_messages.compact).to be_well_formed - end - - it "does not include any leftover debugging or development mechanisms" do - exempt = %r{quality_spec.rb|support/helpers|vcr_cassettes|\.md|\.ronn|\.txt|\.5|\.1} - error_messages = [] - Dir.chdir(root) do - tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_debugging_mechanisms(filename) - end + tracked_files.each do |filename| + next if filename =~ exempt + error_messages << check_for_straneous_quotes(filename) end expect(error_messages.compact).to be_well_formed end @@ -144,11 +109,9 @@ def check_for_specific_pronouns(filename) it "does not include any unresolved merge conflicts" do error_messages = [] exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser\.rb} - Dir.chdir(root) do - tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_git_merge_conflicts(filename) - end + tracked_files.each do |filename| + next if filename =~ exempt + error_messages << check_for_git_merge_conflicts(filename) end expect(error_messages.compact).to be_well_formed end @@ -156,37 +119,38 @@ def check_for_specific_pronouns(filename) it "maintains language quality of the documentation" do included = /ronn/ error_messages = [] - Dir.chdir(root) do - `git ls-files -z -- man`.split("\x0").each do |filename| - next unless filename =~ included - error_messages << check_for_expendable_words(filename) - error_messages << check_for_specific_pronouns(filename) - end + man_tracked_files.each do |filename| + next unless filename =~ included + error_messages << check_for_expendable_words(filename) + error_messages << check_for_specific_pronouns(filename) end expect(error_messages.compact).to be_well_formed end it "maintains language quality of sentences used in source code" do error_messages = [] - exempt = /vendor|vcr_cassettes/ - Dir.chdir(root) do - lib_tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - error_messages << check_for_expendable_words(filename) - error_messages << check_for_specific_pronouns(filename) - end + exempt = /vendor|vcr_cassettes|CODE_OF_CONDUCT/ + lib_tracked_files.each do |filename| + next if filename =~ exempt + error_messages << check_for_expendable_words(filename) + error_messages << check_for_specific_pronouns(filename) end expect(error_messages.compact).to be_well_formed end it "documents all used settings" do exemptions = %w[ - auto_config_jobs - deployment_means_frozen forget_cli_options + gem.changelog + gem.ci gem.coc + gem.linter gem.mit + gem.rubocop + gem.test + git.allow_insecure inline + trust-policy use_gem_version_promoter_for_major_updates ] @@ -196,16 +160,15 @@ def check_for_specific_pronouns(filename) Bundler::Settings::BOOL_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::BOOL_KEYS" } Bundler::Settings::NUMBER_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::NUMBER_KEYS" } Bundler::Settings::ARRAY_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::ARRAY_KEYS" } + Bundler::Settings::STRING_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::STRING_KEYS" } - Dir.chdir(root) do - key_pattern = /([a-z\._-]+)/i - lib_tracked_files.split("\x0").each do |filename| - each_line(filename) do |line, number| - line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" } - end + key_pattern = /([a-z\._-]+)/i + lib_tracked_files.each do |filename| + each_line(filename) do |line, number| + line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" } end - documented_settings = File.read("man/bundle-config.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten end + documented_settings = File.read("lib/bundler/man/bundle-config.1.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten documented_settings.each do |s| all_settings.delete(s) @@ -231,57 +194,52 @@ def check_for_specific_pronouns(filename) end it "ships the correct set of files" do - Dir.chdir(root) do - git_list = shipped_files.split("\x0") + git_list = git_ls_files(ruby_core? ? "lib/bundler lib/bundler.rb libexec/bundle*" : "lib exe CHANGELOG.md LICENSE.md README.md bundler.gemspec") - gem_list = Gem::Specification.load(gemspec.to_s).files + gem_list = loaded_gemspec.files - expect(git_list.to_set).to eq(gem_list.to_set) - end + expect(git_list.sort).to eq(gem_list.sort) end it "does not contain any warnings" do - Dir.chdir(root) do - exclusions = %w[ - lib/bundler/capistrano.rb - lib/bundler/deployment.rb - lib/bundler/gem_tasks.rb - lib/bundler/vlad.rb - lib/bundler/templates/gems.rb - ] - files_to_require = lib_tracked_files.split("\x0").grep(/\.rb$/) - exclusions - files_to_require.reject! {|f| f.start_with?("lib/bundler/vendor") } - files_to_require.map! {|f| f.chomp(".rb") } - sys_exec!("ruby -w -Ilib") do |input, _, _| - files_to_require.each do |f| - input.puts "require '#{f.sub(%r{\Alib/}, "")}'" - end + exclusions = %w[ + lib/bundler/capistrano.rb + lib/bundler/deployment.rb + lib/bundler/gem_tasks.rb + lib/bundler/vlad.rb + lib/bundler/templates/gems.rb + ] + files_to_require = lib_tracked_files.grep(/\.rb$/) - exclusions + files_to_require.reject! {|f| f.start_with?("lib/bundler/vendor") } + files_to_require.map! {|f| File.expand_path(f, source_root) } + files_to_require.sort! + sys_exec("ruby -w") do |input, _, _| + files_to_require.each do |f| + input.puts "require '#{f}'" end + end - warnings = last_command.stdboth.split("\n") - # ignore warnings around deprecated Object#=~ method in RubyGems - warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} } + warnings = last_command.stdboth.split("\n") + # ignore warnings around deprecated Object#=~ method in RubyGems + warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} } - expect(warnings).to be_well_formed - end + expect(warnings).to be_well_formed end it "does not use require internally, but require_relative" do - Dir.chdir(root) do - exempt = %r{templates/|vendor/} - all_bad_requires = [] - lib_tracked_files.split("\x0").each do |filename| - next if filename =~ exempt - each_line(filename) do |line, number| - line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" } - end + exempt = %r{templates/|\.5|\.1|vendor/} + all_bad_requires = [] + lib_tracked_files.each do |filename| + next if filename =~ exempt + each_line(filename) do |line, number| + line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" } end - - expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}" end + + expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}" end -private + private def each_line(filename, &block) File.readlines(filename, :encoding => "UTF-8").each_with_index(&block) diff --git a/ruby/spec/bundler/realworld/dependency_api_spec.rb b/ruby/spec/bundler/realworld/dependency_api_spec.rb index dea8329a4..08c6acf19 100644 --- a/ruby/spec/bundler/realworld/dependency_api_spec.rb +++ b/ruby/spec/bundler/realworld/dependency_api_spec.rb @@ -24,7 +24,7 @@ @t.run wait_for_server("127.0.0.1", port) - bundle! "config set timeout 1" + bundle "config set timeout 1" end after do @@ -34,7 +34,7 @@ end it "times out and falls back on the modern index" do - install_gemfile! <<-G, :artifice => nil + install_gemfile <<-G, :artifice => nil source "#{@server_uri}" gem "rack" G diff --git a/ruby/spec/bundler/realworld/double_check_spec.rb b/ruby/spec/bundler/realworld/double_check_spec.rb index 90cf298b3..d7f28d10b 100644 --- a/ruby/spec/bundler/realworld/double_check_spec.rb +++ b/ruby/spec/bundler/realworld/double_check_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "double checking sources", :realworld => true, :sometimes => true do +RSpec.describe "double checking sources", :realworld => true do it "finds already-installed gems" do create_file("rails.gemspec", <<-RUBY) Gem::Specification.new do |s| @@ -25,16 +25,16 @@ RUBY cmd = <<-RUBY - require "#{lib_dir}/bundler" + require "#{entrypoint}" require "#{spec_dir}/support/artifice/vcr" - require "#{lib_dir}/bundler/inline" + require "#{entrypoint}/inline" gemfile(true) do source "https://rubygems.org" gem "rails", path: "." end RUBY - ruby! cmd - ruby! cmd + ruby cmd + ruby cmd end end diff --git a/ruby/spec/bundler/realworld/edgecases_spec.rb b/ruby/spec/bundler/realworld/edgecases_spec.rb index a91e6a359..df5eeda9f 100644 --- a/ruby/spec/bundler/realworld/edgecases_spec.rb +++ b/ruby/spec/bundler/realworld/edgecases_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do +RSpec.describe "real world edgecases", :realworld => true do def rubygems_version(name, requirement) - ruby! <<-RUBY + ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" - require "#{lib_dir}/bundler" - require "#{lib_dir}/bundler/source/rubygems/remote" - require "#{lib_dir}/bundler/fetcher" + require "#{entrypoint}" + require "#{entrypoint}/source/rubygems/remote" + require "#{entrypoint}/fetcher" rubygem = Bundler.ui.silence do source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) @@ -29,7 +29,7 @@ def rubygems_version(name, requirement) gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle! :lock + bundle :lock expect(lockfile).to include(rubygems_version("rails", "~> 5.0")) expect(lockfile).to include("capybara (2.2.1)") end @@ -43,7 +43,7 @@ def rubygems_version(name, requirement) gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle! :lock + bundle :lock expect(lockfile).to include("gxapi_rails (0.0.6)") end @@ -56,13 +56,15 @@ def rubygems_version(name, requirement) gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" G - bundle! :lock + bundle :lock expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0")) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do - # from https://github.com/bundler/bundler/issues/5031 + # from https://github.com/rubygems/bundler/issues/5031 + + system_gems "bundler-2.99.0" gemfile <<-G source "https://rubygems.org" @@ -189,159 +191,337 @@ def rubygems_version(name, requirement) rails (~> 4.2.7.1) L - bundle! "lock --update paperclip" + bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" } expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end - # https://github.com/bundler/bundler/issues/1500 - it "does not fail install because of gem plugins" do - realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") - gemfile <<-G + it "outputs a helpful error message when gems have invalid gemspecs" do + install_gemfile <<-G, :standalone => true, :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" } + source 'https://rubygems.org' + gem "resque-scheduler", "2.2.0" + gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0 + gem "ruby2_keywords", "0.0.5" + G + expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") + expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") + end + + it "doesn't hang on big gemfile" do + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ + + gemfile <<~G + # frozen_string_literal: true + source "https://rubygems.org" - gem 'rack', '1.0.1' + ruby "2.7.3" + + gem "rails" + gem "pg", ">= 0.18", "< 2.0" + gem "goldiloader" + gem "awesome_nested_set" + gem "circuitbox" + gem "passenger" + gem "globalid" + gem "rack-cors" + gem "rails-pg-extras" + gem "linear_regression_trend" + gem "rack-protection" + gem "pundit" + gem "remote_ip_proxy_scrubber" + gem "bcrypt" + gem "searchkick" + gem "excon" + gem "faraday_middleware-aws-sigv4" + gem "typhoeus" + gem "sidekiq" + gem "sidekiq-undertaker" + gem "sidekiq-cron" + gem "storext" + gem "appsignal" + gem "fcm" + gem "business_time" + gem "tzinfo" + gem "holidays" + gem "bigdecimal" + gem "progress_bar" + gem "redis" + gem "hiredis" + gem "state_machines" + gem "state_machines-audit_trail" + gem "state_machines-activerecord" + gem "interactor" + gem "ar_transaction_changes" + gem "redis-rails" + gem "seed_migration" + gem "lograge" + gem "graphiql-rails", group: :development + gem "graphql" + gem "pusher" + gem "rbnacl" + gem "jwt" + gem "json-schema" + gem "discard" + gem "money" + gem "strip_attributes" + gem "validates_email_format_of" + gem "audited" + gem "concurrent-ruby" + gem "with_advisory_lock" + + group :test do + gem "rspec-sidekiq" + gem "simplecov", require: false + end + + group :development, :test do + gem "byebug", platform: :mri + gem "guard" + gem "guard-bundler" + gem "guard-rspec" + gem "rb-fsevent" + gem "rspec_junit_formatter" + gem "rspec-collection_matchers" + gem "rspec-rails" + gem "rspec-retry" + gem "state_machines-rspec" + gem "dotenv-rails" + gem "database_cleaner-active_record" + gem "database_cleaner-redis" + gem "timecop" + end + + gem "factory_bot_rails" + gem "faker" + + group :development do + gem "listen" + gem "sql_queries_count" + gem "rubocop" + gem "rubocop-performance" + gem "rubocop-rspec" + gem "rubocop-rails" + gem "brakeman" + gem "bundler-audit" + gem "solargraph" + gem "annotate" + end G - bundle "config set --local path vendor/bundle" - bundle! :install - expect(err).not_to include("Could not find rake") - expect(err).to be_empty + if Bundler.feature_flag.bundler_3_mode? + # Conflicts on bundler version, so fails earlier + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false + expect(out).to display_total_steps_of(435) + else + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + expect(out).to display_total_steps_of(1025) + end end - it "checks out git repos when the lockfile is corrupted" do - gemfile <<-G - source "https://rubygems.org" - git_source(:github) {|repo| "https://github.com/\#{repo}.git" } + it "doesn't hang on tricky gemfile" do + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ + + gemfile <<~G + source 'https://rubygems.org' - gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + group :development do + gem "puppet-module-posix-default-r2.7", '~> 0.3' + gem "puppet-module-posix-dev-r2.7", '~> 0.3' + gem "beaker-rspec" + gem "beaker-puppet" + gem "beaker-docker" + gem "beaker-puppet_install_helper" + gem "beaker-module_install_helper" + end G - lockfile <<-L - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - GEM - remote: https://rubygems.org/ - specs: - arel (3.0.2) - builder (3.0.0) - erubis (2.7.0) - hike (1.2.1) - i18n (0.6.0) - journey (1.0.3) - multi_json (1.1.0) - rack (1.4.1) - rack-cache (1.2) - rack (>= 0.4) - rack-test (0.6.1) - rack (>= 1.0) - sprockets (2.1.2) - hike (~> 1.2) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - tilt (1.3.3) - tzinfo (0.3.32) + if Bundler.feature_flag.bundler_3_mode? + expect(out).to display_total_steps_of(890) + else + expect(out).to display_total_steps_of(891) + end + end - PLATFORMS - ruby + it "doesn't hang on nix gemfile" do + skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/ - DEPENDENCIES - actionpack! - activerecord! - activesupport! - L + gemfile <<~G + source "https://rubygems.org" do + gem "addressable" + gem "atk" + gem "awesome_print" + gem "bacon" + gem "byebug" + gem "cairo" + gem "cairo-gobject" + gem "camping" + gem "charlock_holmes" + gem "cld3" + gem "cocoapods" + gem "cocoapods-acknowledgements" + gem "cocoapods-art" + gem "cocoapods-bin" + gem "cocoapods-browser" + gem "cocoapods-bugsnag" + gem "cocoapods-check" + gem "cocoapods-clean" + gem "cocoapods-clean_build_phases_scripts" + gem "cocoapods-core" + gem "cocoapods-coverage" + gem "cocoapods-deintegrate" + gem "cocoapods-dependencies" + gem "cocoapods-deploy" + gem "cocoapods-downloader" + gem "cocoapods-expert-difficulty" + gem "cocoapods-fix-react-native" + gem "cocoapods-generate" + gem "cocoapods-git_url_rewriter" + gem "cocoapods-keys" + gem "cocoapods-no-dev-schemes" + gem "cocoapods-open" + gem "cocoapods-packager" + gem "cocoapods-playgrounds" + gem "cocoapods-plugins" + gem "cocoapods-prune-localizations" + gem "cocoapods-rome" + gem "cocoapods-search" + gem "cocoapods-sorted-search" + gem "cocoapods-static-swift-framework" + gem "cocoapods-stats" + gem "cocoapods-tdfire-binary" + gem "cocoapods-testing" + gem "cocoapods-trunk" + gem "cocoapods-try" + gem "cocoapods-try-release-fix" + gem "cocoapods-update-if-you-dare" + gem "cocoapods-whitelist" + gem "cocoapods-wholemodule" + gem "coderay" + gem "concurrent-ruby" + gem "curb" + gem "curses" + gem "daemons" + gem "dep-selector-libgecode" + gem "digest-sha3" + gem "domain_name" + gem "do_sqlite3" + gem "ethon" + gem "eventmachine" + gem "excon" + gem "faraday" + gem "ffi" + gem "ffi-rzmq-core" + gem "fog-dnsimple" + gem "gdk_pixbuf2" + gem "gio2" + gem "gitlab-markup" + gem "glib2" + gem "gpgme" + gem "gtk2" + gem "hashie" + gem "highline" + gem "hike" + gem "hitimes" + gem "hpricot" + gem "httpclient" + gem "http-cookie" + gem "iconv" + gem "idn-ruby" + gem "jbuilder" + gem "jekyll" + gem "jmespath" + gem "jwt" + gem "libv8" + gem "libxml-ruby" + gem "magic" + gem "markaby" + gem "method_source" + gem "mini_magick" + gem "msgpack" + gem "mysql2" + gem "ncursesw" + gem "netrc" + gem "net-scp" + gem "net-ssh" + gem "nokogiri" + gem "opus-ruby" + gem "ovirt-engine-sdk" + gem "pango" + gem "patron" + gem "pcaprub" + gem "pg" + gem "pry" + gem "pry-byebug" + gem "pry-doc" + gem "public_suffix" + gem "puma" + gem "rails" + gem "rainbow" + gem "rbnacl" + gem "rb-readline" + gem "re2" + gem "redis" + gem "redis-rack" + gem "rest-client" + gem "rmagick" + gem "rpam2" + gem "rspec" + gem "rubocop" + gem "rubocop-performance" + gem "ruby-libvirt" + gem "ruby-lxc" + gem "ruby-progressbar" + gem "ruby-terminfo" + gem "ruby-vips" + gem "rubyzip" + gem "rugged" + gem "sassc" + gem "scrypt" + gem "semian" + gem "sequel" + gem "sequel_pg" + gem "simplecov" + gem "sinatra" + gem "slop" + gem "snappy" + gem "sqlite3" + gem "taglib-ruby" + gem "thrift" + gem "tilt" + gem "tiny_tds" + gem "treetop" + gem "typhoeus" + gem "tzinfo" + gem "unf_ext" + gem "uuid4r" + gem "whois" + gem "zookeeper" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - bundle! :lock - expect(err).to be_empty + if Bundler.feature_flag.bundler_3_mode? + expect(out).to display_total_steps_of(1874) + else + expect(out).to display_total_steps_of(1922) + end end - it "outputs a helpful error message when gems have invalid gemspecs" do - install_gemfile <<-G, :standalone => true - source 'https://rubygems.org' - gem "resque-scheduler", "2.2.0" - G - expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") - expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") + private + + RSpec::Matchers.define :display_total_steps_of do |expected_steps| + match do |out| + out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)") + end + + failure_message do |out| + actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first + + "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}" + end end end diff --git a/ruby/spec/bundler/realworld/ffi_spec.rb b/ruby/spec/bundler/realworld/ffi_spec.rb new file mode 100644 index 000000000..083ea3890 --- /dev/null +++ b/ruby/spec/bundler/realworld/ffi_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +RSpec.describe "loading dinamically linked library on a bundle exec context", :realworld => true do + it "passes ENV right after argv in memory" do + create_file "foo.rb", <<~RUBY + require 'ffi' + + module FOO + extend FFI::Library + ffi_lib './libfoo.so' + + attach_function :Hello, [], :void + end + + FOO.Hello() + RUBY + + create_file "libfoo.c", <<~'C' + #include + + static int foo_init(int argc, char** argv, char** envp) { + if (argv[argc+1] == NULL) { + printf("FAIL\n"); + } else { + printf("OK\n"); + } + + return 0; + } + + #if defined(__APPLE__) && defined(__MACH__) + __attribute__((section("__DATA,__mod_init_func"), used, aligned(sizeof(void*)))) + #else + __attribute__((section(".init_array"))) + #endif + static void *ctr = &foo_init; + + extern char** environ; + + void Hello() { + return; + } + C + + sys_exec "gcc -g -o libfoo.so -shared -fpic libfoo.c" + + install_gemfile <<-G + source "https://rubygems.org" + + gem 'ffi' + G + + bundle "exec ruby foo.rb" + + expect(out).to eq("OK") + end +end diff --git a/ruby/spec/bundler/realworld/fixtures/warbler/.gitignore b/ruby/spec/bundler/realworld/fixtures/warbler/.gitignore new file mode 100644 index 000000000..d392f0e82 --- /dev/null +++ b/ruby/spec/bundler/realworld/fixtures/warbler/.gitignore @@ -0,0 +1 @@ +*.jar diff --git a/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile b/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile new file mode 100644 index 000000000..4fbf2d05a --- /dev/null +++ b/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "demo", :path => "./demo" +gem "jruby-jars", "~> 9.2" +gem "warbler", "~> 2.0" diff --git a/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile.lock new file mode 100644 index 000000000..05bcb877d --- /dev/null +++ b/ruby/spec/bundler/realworld/fixtures/warbler/Gemfile.lock @@ -0,0 +1,30 @@ +PATH + remote: demo + specs: + demo (1.0) + +GEM + remote: https://rubygems.org/ + specs: + jruby-jars (9.2.16.0) + jruby-rack (1.1.21) + rake (13.0.1) + rubyzip (1.3.0) + warbler (2.0.5) + jruby-jars (>= 9.0.0.0) + jruby-rack (>= 1.1.1, < 1.3) + rake (>= 10.1.0) + rubyzip (~> 1.0, < 1.4) + +PLATFORMS + java + ruby + universal-java-11 + +DEPENDENCIES + demo! + jruby-jars (~> 9.2) + warbler (~> 2.0) + +BUNDLED WITH + 2.3.0.dev diff --git a/ruby/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb b/ruby/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb new file mode 100644 index 000000000..25f614ecc --- /dev/null +++ b/ruby/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +puts require "bundler/setup" diff --git a/ruby/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec b/ruby/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec new file mode 100644 index 000000000..ed5a0dc08 --- /dev/null +++ b/ruby/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = "demo" + spec.version = "1.0" + spec.author = "Somebody" + spec.summary = "A demo gem" + spec.license = "MIT" + spec.homepage = "https://example.org" +end diff --git a/ruby/spec/bundler/realworld/gemfile_source_header_spec.rb b/ruby/spec/bundler/realworld/gemfile_source_header_spec.rb index 3f507b056..ada2fc92e 100644 --- a/ruby/spec/bundler/realworld/gemfile_source_header_spec.rb +++ b/ruby/spec/bundler/realworld/gemfile_source_header_spec.rb @@ -30,7 +30,7 @@ expect(the_bundle).to include_gems "weakling 0.0.3" end -private + private def setup_server require_rack diff --git a/ruby/spec/bundler/realworld/mirror_probe_spec.rb b/ruby/spec/bundler/realworld/mirror_probe_spec.rb index 735fb2b3d..241424d4d 100644 --- a/ruby/spec/bundler/realworld/mirror_probe_spec.rb +++ b/ruby/spec/bundler/realworld/mirror_probe_spec.rb @@ -71,30 +71,15 @@ gem 'weakling' G - bundle :install, :artifice => nil + bundle :install, :artifice => nil, :raise_on_error => false expect(out).to include("Fetching source index from #{mirror}") - expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Could not fetch specs from #{mirror}") - end - it "prints each error and warning on a new line" do - gemfile <<-G - source "#{original}" - gem 'weakling' - G - - bundle :install, :artifice => nil - - expect(out).to include "Fetching source index from #{mirror}/" - expect(err).to include <<-EOS.strip -Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ -Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ -Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ -Could not fetch specs from #{mirror}/ - EOS + err_lines = err.split("\n") + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(2/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(3/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(4/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ACould not fetch specs from #{mirror}/ due to underlying error <}) end end @@ -109,13 +94,15 @@ gem 'weakling' G - bundle :install, :artifice => nil + bundle :install, :artifice => nil, :raise_on_error => false expect(out).to include("Fetching source index from #{mirror}") - expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}") - expect(err).to include("Could not fetch specs from #{mirror}") + + err_lines = err.split("\n") + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(2/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(3/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ARetrying fetcher due to error \(4/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <}) + expect(err_lines).to include(%r{\ACould not fetch specs from #{mirror}/ due to underlying error <}) end end @@ -138,7 +125,7 @@ def setup_server end def setup_mirror - mirror_port = find_unused_port - @mirror_uri = "http://#{host}:#{mirror_port}" + @mirror_port = find_unused_port + @mirror_uri = "http://#{host}:#{@mirror_port}" end end diff --git a/ruby/spec/bundler/realworld/parallel_spec.rb b/ruby/spec/bundler/realworld/parallel_spec.rb index 7738b46aa..a1e4f8390 100644 --- a/ruby/spec/bundler/realworld/parallel_spec.rb +++ b/ruby/spec/bundler/realworld/parallel_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "parallel", :realworld => true, :sometimes => true do +RSpec.describe "parallel", :realworld => true do it "installs" do gemfile <<-G source "https://rubygems.org" @@ -46,14 +46,14 @@ end it "works with --standalone" do - gemfile <<-G, :standalone => true + gemfile <<-G source "https://rubygems.org" gem "diff-lcs" G bundle :install, :standalone => true, :jobs => 4 - ruby <<-RUBY, :no_lib => true + ruby <<-RUBY $:.unshift File.expand_path("bundle") require "bundler/setup" diff --git a/ruby/spec/bundler/realworld/slow_perf_spec.rb b/ruby/spec/bundler/realworld/slow_perf_spec.rb new file mode 100644 index 000000000..aced5a164 --- /dev/null +++ b/ruby/spec/bundler/realworld/slow_perf_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "bundle install with complex dependencies", :realworld => true do + it "resolves quickly" do + gemfile <<-G + source 'https://rubygems.org' + + gem "actionmailer" + gem "mongoid", ">= 0.10.2" + G + + start_time = Time.now + + bundle "lock" + + duration = Time.now - start_time + + expect(duration.to_f).to be < 12 # seconds + end +end diff --git a/ruby/spec/bundler/resolver/basic_spec.rb b/ruby/spec/bundler/resolver/basic_spec.rb index 57897f89b..ee62dc357 100644 --- a/ruby/spec/bundler/resolver/basic_spec.rb +++ b/ruby/spec/bundler/resolver/basic_spec.rb @@ -176,7 +176,7 @@ deps = [] @deps.each do |d| - deps << Bundler::DepProxy.new(d, "ruby") + deps << Bundler::DepProxy.get_proxy(d, "ruby") end should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]] diff --git a/ruby/spec/bundler/resolver/platform_spec.rb b/ruby/spec/bundler/resolver/platform_spec.rb index fee0cf1f1..bc4081f8b 100644 --- a/ruby/spec/bundler/resolver/platform_spec.rb +++ b/ruby/spec/bundler/resolver/platform_spec.rb @@ -28,6 +28,266 @@ end end + it "resolves multiplatform gems with redundant platforms correctly" do + @index = build_index do + gem "zookeeper", "1.4.11" + gem "zookeeper", "1.4.11", "java" do + dep "slyphon-log4j", "= 1.2.15" + dep "slyphon-zookeeper_jar", "= 3.3.5" + end + gem "slyphon-log4j", "1.2.15" + gem "slyphon-zookeeper_jar", "3.3.5", "java" + end + + dep "zookeeper" + platforms "java", "ruby", "universal-java-11" + + should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java] + end + + it "takes the latest ruby gem, even if an older platform specific version is available" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" + gem "foo", "1.1.0" + end + dep "foo" + platforms "x64-mingw32" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the ruby version if the platform version is incompatible" do + @index = build_index do + gem "bar", "1.0.0" + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" do + dep "bar", "< 1" + end + end + dep "foo" + platforms "x64-mingw32" + + should_resolve_as %w[foo-1.0.0] + end + + it "prefers the platform specific gem to the ruby version" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" + end + dep "foo" + platforms "x64-mingw32" + + should_resolve_as %w[foo-1.0.0-x64-mingw32] + end + + it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" + gem "foo", "1.1.0" + gem "foo", "1.1.0", "x64-mingw32" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "foo" + dep "Ruby\0", "2.5.1" + platforms "x64-mingw32" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the latest ruby gem with required_ruby_version if the platform specific gem doesn't match the required_ruby_version" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" + gem "foo", "1.1.0" do |s| + s.required_ruby_version = [">= 2.0"] + end + gem "foo", "1.1.0", "x64-mingw32" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "foo" + dep "Ruby\0", "2.5.1" + platforms "x64-mingw32" + + should_resolve_as %w[foo-1.1.0] + end + + it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version with multiple platforms" do + @index = build_index do + gem "foo", "1.0.0" + gem "foo", "1.0.0", "x64-mingw32" + gem "foo", "1.1.0" do |s| + s.required_ruby_version = [">= 2.0"] + end + gem "foo", "1.1.0", "x64-mingw32" do |s| + s.required_ruby_version = [">= 2.0", "< 2.4"] + end + gem "Ruby\0", "2.5.1" + end + dep "foo" + dep "Ruby\0", "2.5.1" + platforms "x86_64-linux", "x64-mingw32" + + should_resolve_as %w[foo-1.1.0] + end + + it "doesn't include gems not needed for none of the platforms" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + end + + dep "empyrean", "0.1.0" + dep "pry" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "includes gems needed for at least one platform" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "extra2", ">= 0" + end + + gem "extra2", "1.0.0" do + dep "extra3", ">= 0" + end + + gem "extra3", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "properly adds platforms when platform requirements come from different dependencies" do + @index = build_index do + gem "ffi", "1.9.14" + gem "ffi", "1.9.14", "universal-mingw32" + + gem "gssapi", "0.1" + gem "gssapi", "0.2" + gem "gssapi", "0.3" + gem "gssapi", "1.2.0" do + dep "ffi", ">= 1.0.1" + end + + gem "mixlib-shellout", "2.2.6" + gem "mixlib-shellout", "2.2.6", "universal-mingw32" do + dep "win32-process", "~> 0.8.2" + end + + # we need all these versions to get the sorting the same as it would be + # pulling from rubygems.org + %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v| + gem "win32-process", v do + dep "ffi", ">= 1.0.0" + end + end + end + + dep "mixlib-shellout" + dep "gssapi" + + platforms "universal-mingw32", "ruby" + + should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3] + end + describe "with mingw32" do before :each do @index = build_index do @@ -90,11 +350,11 @@ end end - it "reports on the conflict" do + it "takes the ruby version as fallback" do platforms "ruby", "java" dep "foo" - should_conflict_on "baz" + should_resolve_as %w[bar-1.0.0 baz-1.0.0 foo-1.0.0] end end end diff --git a/ruby/spec/bundler/runtime/executable_spec.rb b/ruby/spec/bundler/runtime/executable_spec.rb index 003be97cd..a11f54764 100644 --- a/ruby/spec/bundler/runtime/executable_spec.rb +++ b/ruby/spec/bundler/runtime/executable_spec.rb @@ -2,14 +2,14 @@ RSpec.describe "Running bin/* commands" do before :each do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G end it "runs the bundled command when in the bundle" do - bundle! "binstubs rack" + bundle "binstubs rack" build_gem "rack", "2.0", :to_system => true do |s| s.executables = "rackup" @@ -20,7 +20,7 @@ end it "allows the location of the gem stubs to be specified" do - bundle! "binstubs rack", :path => "gbin" + bundle "binstubs rack", :path => "gbin" expect(bundled_app("bin")).not_to exist expect(bundled_app("gbin/rackup")).to exist @@ -30,33 +30,31 @@ end it "allows absolute paths as a specification of where to install bin stubs" do - bundle! "binstubs rack", :path => tmp("bin") + bundle "binstubs rack", :path => tmp("bin") gembin tmp("bin/rackup") expect(out).to eq("1.0.0") end it "uses the default ruby install name when shebang is not specified" do - bundle! "binstubs rack" - expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n") + bundle "binstubs rack" + expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n") end it "allows the name of the shebang executable to be specified" do - bundle! "binstubs rack", :shebang => "ruby-foo" - expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env ruby-foo\n") + bundle "binstubs rack", :shebang => "ruby-foo" + expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env ruby-foo\n") end it "runs the bundled command when out of the bundle" do - bundle! "binstubs rack" + bundle "binstubs rack" build_gem "rack", "2.0", :to_system => true do |s| s.executables = "rackup" end - Dir.chdir(tmp) do - gembin "rackup" - expect(out).to eq("1.0.0") - end + gembin "rackup", :dir => tmp + expect(out).to eq("1.0.0") end it "works with gems in path" do @@ -65,10 +63,11 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", :path => "#{lib_path("rack")}" G - bundle! "binstubs rack" + bundle "binstubs rack" build_gem "rack", "2.0", :to_system => true do |s| s.executables = "rackup" @@ -79,34 +78,32 @@ end it "creates a bundle binstub" do - build_gem "bundler", Bundler::VERSION, :to_system => true do |s| - s.executables = "bundle" - end - gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "bundler" G - bundle! "binstubs bundler" + bundle "binstubs bundler" expect(bundled_app("bin/bundle")).to exist end it "does not generate bin stubs if the option was not specified" do - bundle! "install" + bundle "install" expect(bundled_app("bin/rackup")).not_to exist end it "allows you to stop installing binstubs", :bundler => "< 3" do - bundle! "install --binstubs bin/" + skip "delete permission error" if Gem.win_platform? + + bundle "install --binstubs bin/" bundled_app("bin/rackup").rmtree - bundle! "install --binstubs \"\"" + bundle "install --binstubs \"\"" expect(bundled_app("bin/rackup")).not_to exist - bundle! "config bin" + bundle "config bin" expect(out).to include("You have not configured a value for `bin`") end @@ -116,7 +113,7 @@ gem "activesupport" G - bundle! :install, :binstubs => "bin" + bundle :install, :binstubs => "bin" gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -130,21 +127,21 @@ end it "rewrites bins on binstubs (to maintain backwards compatibility)" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G create_file("bin/rackup", "OMG") - bundle! "binstubs rack" + bundle "binstubs rack" expect(bundled_app("bin/rackup").read).to_not eq("OMG") end it "use BUNDLE_GEMFILE gemfile for binstub" do # context with bin/bundler w/ default Gemfile - bundle! "binstubs bundler" + bundle "binstubs bundler" # generate other Gemfile with executable gem build_repo2 do @@ -159,7 +156,7 @@ # generate binstub for executable from non default Gemfile (other then bin/bundler version) ENV["BUNDLE_GEMFILE"] = "OtherGemfile" bundle "install" - bundle! "binstubs bindir" + bundle "binstubs bindir" # remove user settings ENV["BUNDLE_GEMFILE"] = nil @@ -167,7 +164,6 @@ # run binstub for non default Gemfile gembin "foo" - expect(exitstatus).to eq(0) if exitstatus expect(out).to eq("1.0") end end diff --git a/ruby/spec/bundler/runtime/gem_tasks_spec.rb b/ruby/spec/bundler/runtime/gem_tasks_spec.rb index 74270a231..b89fdf2cb 100644 --- a/ruby/spec/bundler/runtime/gem_tasks_spec.rb +++ b/ruby/spec/bundler/runtime/gem_tasks_spec.rb @@ -15,12 +15,11 @@ bundled_app("Rakefile").open("w") do |f| f.write <<-RAKEFILE - $:.unshift("#{lib_dir}") require "bundler/gem_tasks" RAKEFILE end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rake" @@ -28,8 +27,8 @@ end it "includes the relevant tasks" do - with_gem_path_as(Spec::Path.base_system_gems.to_s) do - sys_exec "#{rake} -T", "RUBYOPT" => "-I#{lib_dir}" + with_gem_path_as(base_system_gem_path.to_s) do + sys_exec "#{rake} -T", :env => { "GEM_HOME" => system_gem_path.to_s } end expect(err).to be_empty @@ -42,38 +41,65 @@ ] tasks = out.lines.to_a.map {|s| s.split("#").first.strip } expect(tasks & expected_tasks).to eq(expected_tasks) - expect(exitstatus).to eq(0) if exitstatus end - it "defines a working `rake install` task" do - with_gem_path_as(Spec::Path.base_system_gems.to_s) do - sys_exec "#{rake} install", "RUBYOPT" => "-I#{lib_dir}" + it "defines a working `rake install` task", :ruby_repo do + with_gem_path_as(base_system_gem_path.to_s) do + sys_exec "#{rake} install", :env => { "GEM_HOME" => system_gem_path.to_s } end expect(err).to be_empty - bundle! "exec rake install" + bundle "exec rake install" expect(err).to be_empty end - context "rake build when path has spaces" do + context "rake build when path has spaces", :ruby_repo do before do spaced_bundled_app = tmp.join("bundled app") - FileUtils.mv bundled_app, spaced_bundled_app - Dir.chdir(spaced_bundled_app) + FileUtils.cp_r bundled_app, spaced_bundled_app + bundle "exec rake build", :dir => spaced_bundled_app end it "still runs successfully" do - bundle! "exec rake build" + expect(err).to be_empty + end + end + + context "rake build when path has brackets", :ruby_repo do + before do + bracketed_bundled_app = tmp.join("bundled[app") + FileUtils.cp_r bundled_app, bracketed_bundled_app + bundle "exec rake build", :dir => bracketed_bundled_app + end + + it "still runs successfully" do + expect(err).to be_empty + end + end + + context "bundle path configured locally" do + before do + bundle "config set path vendor/bundle" + end + + it "works", :ruby_repo do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + + gem "rake" + G + + bundle "exec rake -T" expect(err).to be_empty end end it "adds 'pkg' to rake/clean's CLOBBER" do - with_gem_path_as(Spec::Path.base_system_gems.to_s) do - sys_exec! %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect') + with_gem_path_as(base_system_gem_path.to_s) do + sys_exec %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect'), :env => { "GEM_HOME" => system_gem_path.to_s } end expect(out).to eq '["pkg"]' end diff --git a/ruby/spec/bundler/runtime/inline_spec.rb b/ruby/spec/bundler/runtime/inline_spec.rb index cd762fe63..24df75861 100644 --- a/ruby/spec/bundler/runtime/inline_spec.rb +++ b/ruby/spec/bundler/runtime/inline_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "bundler/inline#gemfile" do def script(code, options = {}) - requires = ["#{lib_dir}/bundler/inline"] + requires = ["#{entrypoint}/inline"] requires.unshift "#{spec_dir}/support/artifice/" + options.delete(:artifice) if options.key?(:artifice) requires = requires.map {|r| "require '#{r}'" }.join("\n") ruby("#{requires}\n\n" + code, options) @@ -48,6 +48,7 @@ def script(code, options = {}) it "requires the gems" do script <<-RUBY gemfile do + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "two" end @@ -55,10 +56,10 @@ def script(code, options = {}) RUBY expect(out).to eq("two") - expect(exitstatus).to be_zero if exitstatus - script <<-RUBY + script <<-RUBY, :raise_on_error => false gemfile do + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "eleven" end @@ -78,7 +79,6 @@ def script(code, options = {}) RUBY expect(out).to include("Rack's post install message") - expect(exitstatus).to be_zero if exitstatus script <<-RUBY, :artifice => "endpoint" gemfile(true) do @@ -91,12 +91,11 @@ def script(code, options = {}) err_lines = err.split("\n") err_lines.reject!{|line| line =~ /\.rb:\d+: warning: / } unless RUBY_VERSION < "2.7" expect(err_lines).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "lets me use my own ui object" do script <<-RUBY, :artifice => "endpoint" - require '#{lib_dir}/bundler' + require '#{entrypoint}' class MyBundlerUI < Bundler::UI::Silent def confirm(msg, newline = nil) puts "CONFIRMED!" @@ -109,12 +108,11 @@ def confirm(msg, newline = nil) RUBY expect(out).to eq("CONFIRMED!\nCONFIRMED!") - expect(exitstatus).to be_zero if exitstatus end it "has an option for quiet installation" do script <<-RUBY, :artifice => "endpoint" - require '#{lib_dir}/bundler/inline' + require '#{entrypoint}/inline' gemfile(true, :quiet => true) do source "https://notaserver.com" @@ -126,7 +124,7 @@ def confirm(msg, newline = nil) end it "raises an exception if passed unknown arguments" do - script <<-RUBY + script <<-RUBY, :raise_on_error => false gemfile(true, :arglebargle => true) do path "#{lib_path}" gem "two" @@ -140,9 +138,10 @@ def confirm(msg, newline = nil) it "does not mutate the option argument" do script <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' options = { :ui => Bundler::UI::Shell.new } gemfile(false, options) do + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "two" end @@ -151,7 +150,6 @@ def confirm(msg, newline = nil) RUBY expect(out).to match("OKAY") - expect(exitstatus).to be_zero if exitstatus end it "installs quietly if necessary when the install option is not set" do @@ -166,7 +164,6 @@ def confirm(msg, newline = nil) expect(out).to eq("1.0.0") expect(err).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "installs quietly from git if necessary when the install option is not set" do @@ -174,6 +171,7 @@ def confirm(msg, newline = nil) baz_ref = build_git("baz", "2.0.0").ref_for("HEAD") script <<-RUBY gemfile do + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => #{lib_path("foo-1.0.0").to_s.dump} gem "baz", :git => #{lib_path("baz-2.0.0").to_s.dump}, :ref => #{baz_ref.dump} end @@ -184,19 +182,20 @@ def confirm(msg, newline = nil) expect(out).to eq("1.0.0\n2.0.0") expect(err).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "allows calling gemfile twice" do script <<-RUBY gemfile do path "#{lib_path}" do + source "#{file_uri_for(gem_repo1)}" gem "two" end end gemfile do path "#{lib_path}" do + source "#{file_uri_for(gem_repo1)}" gem "four" end end @@ -204,7 +203,6 @@ def confirm(msg, newline = nil) expect(out).to eq("two\nfour") expect(err).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "installs inline gems when a Gemfile.lock is present" do @@ -226,22 +224,19 @@ def confirm(msg, newline = nil) rake BUNDLED WITH - 1.13.6 + #{Bundler::VERSION} G - in_app_root do - script <<-RUBY - gemfile do - source "#{file_uri_for(gem_repo1)}" - gem "rack" - end + script <<-RUBY + gemfile do + source "#{file_uri_for(gem_repo1)}" + gem "rack" + end - puts RACK - RUBY - end + puts RACK + RUBY expect(err).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "installs inline gems when frozen is set" do @@ -255,25 +250,34 @@ def confirm(msg, newline = nil) RUBY expect(last_command.stderr).to be_empty - expect(exitstatus).to be_zero if exitstatus + end + + it "installs inline gems when deployment is set" do + script <<-RUBY, :env => { "BUNDLE_DEPLOYMENT" => "true" } + gemfile do + source "#{file_uri_for(gem_repo1)}" + gem "rack" + end + + puts RACK + RUBY + + expect(last_command.stderr).to be_empty end it "installs inline gems when BUNDLE_GEMFILE is set to an empty string" do ENV["BUNDLE_GEMFILE"] = "" - in_app_root do - script <<-RUBY - gemfile do - source "#{file_uri_for(gem_repo1)}" - gem "rack" - end + script <<-RUBY + gemfile do + source "#{file_uri_for(gem_repo1)}" + gem "rack" + end - puts RACK - RUBY - end + puts RACK + RUBY expect(err).to be_empty - expect(exitstatus).to be_zero if exitstatus end it "installs inline gems when BUNDLE_BIN is set" do @@ -295,7 +299,7 @@ def confirm(msg, newline = nil) it "installs inline gems to the system path regardless" do script <<-RUBY, :env => { "BUNDLE_PATH" => "./vendor/inline" } gemfile(true) do - source "file://#{gem_repo1}" + source "#{file_uri_for(gem_repo1)}" gem "rack" end RUBY @@ -305,7 +309,7 @@ def confirm(msg, newline = nil) end it "skips platform warnings" do - simulate_platform "ruby" + bundle "config set --local force_ruby_platform true" script <<-RUBY gemfile(true) do @@ -350,4 +354,67 @@ def confirm(msg, newline = nil) expect(last_command).to be_success expect(out).to include("BUNDLE_GEMFILE is empty") end + + it "does not error out if library requires optional dependencies" do + Dir.mkdir tmp("path_without_gemfile") + + foo_code = <<~RUBY + begin + gem "bar" + rescue LoadError + end + + puts "WIN" + RUBY + + build_lib "foo", "1.0.0" do |s| + s.write "lib/foo.rb", foo_code + end + + script <<-RUBY, :dir => tmp("path_without_gemfile") + gemfile do + source "#{file_uri_for(gem_repo2)}" + path "#{lib_path}" do + gem "foo", require: false + end + end + + require "foo" + RUBY + + expect(out).to eq("WIN") + expect(err).to be_empty + end + + it "when requiring fileutils after does not show redefinition warnings" do + dependency_installer_loads_fileutils = ruby "require 'rubygems/dependency_installer'; puts $LOADED_FEATURES.grep(/fileutils/)", :raise_on_error => false + skip "does not work if rubygems/dependency_installer loads fileutils, which happens until rubygems 3.2.0" unless dependency_installer_loads_fileutils.empty? + + skip "pathname does not install cleanly on this ruby" if RUBY_VERSION < "2.7.0" + + Dir.mkdir tmp("path_without_gemfile") + + default_fileutils_version = ruby "gem 'fileutils', '< 999999'; require 'fileutils'; puts FileUtils::VERSION", :raise_on_error => false + skip "fileutils isn't a default gem" if default_fileutils_version.empty? + + realworld_system_gems "fileutils --version 1.4.1" + + realworld_system_gems "pathname --version 0.2.0" + + realworld_system_gems "fiddle" # not sure why, but this is needed on Windows to boot rubygems successfully + + realworld_system_gems "timeout uri" # this spec uses net/http which requires these default gems + + script <<-RUBY, :dir => tmp("path_without_gemfile"), :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s } + require "bundler/inline" + + gemfile(true) do + source "#{file_uri_for(gem_repo2)}" + end + + require "fileutils" + RUBY + + expect(err).to eq("The Gemfile specifies no dependencies") + end end diff --git a/ruby/spec/bundler/runtime/load_spec.rb b/ruby/spec/bundler/runtime/load_spec.rb index 7de67e247..96a22a46c 100644 --- a/ruby/spec/bundler/runtime/load_spec.rb +++ b/ruby/spec/bundler/runtime/load_spec.rb @@ -3,10 +3,11 @@ RSpec.describe "Bundler.load" do describe "with a gemfile" do before(:each) do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G + allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app) end it "provides a list of the env dependencies" do @@ -31,7 +32,8 @@ source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle! :install + bundle :install + allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app) end it "provides a list of the env dependencies" do @@ -73,14 +75,14 @@ describe "when called twice" do it "doesn't try to load the runtime twice" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" gem "activesupport", :group => :test G - ruby! <<-RUBY - require "#{lib_dir}/bundler" + ruby <<-RUBY + require "#{entrypoint}" Bundler.setup :default Bundler.require :default puts RACK @@ -97,11 +99,11 @@ describe "not hurting brittle rubygems" do it "does not inject #source into the generated YAML of the gem specs" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "activerecord" G - + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) Bundler.load.specs.each do |spec| expect(spec.to_yaml).not_to match(/^\s+source:/) expect(spec.to_yaml).not_to match(/^\s+groups:/) diff --git a/ruby/spec/bundler/runtime/platform_spec.rb b/ruby/spec/bundler/runtime/platform_spec.rb index f7e93eacf..f7159635e 100644 --- a/ruby/spec/bundler/runtime/platform_spec.rb +++ b/ruby/spec/bundler/runtime/platform_spec.rb @@ -22,7 +22,7 @@ ruby <<-R begin - require 'bundler' + require '#{entrypoint}' Bundler.ui.silence { Bundler.setup } rescue Bundler::GemNotFound => e puts "WIN" @@ -49,7 +49,7 @@ G simulate_platform "x86-darwin-10" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri" G @@ -57,6 +57,126 @@ expect(the_bundle).to include_gems "nokogiri 1.4.2" end + it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do + build_repo4 do + build_gem "nokogiri", "1.11.1" do |s| + s.add_dependency "mini_portile2", "~> 2.5.0" + s.add_dependency "racc", "~> 1.5.2" + end + + build_gem "nokogiri", "1.11.1" do |s| + s.platform = Bundler.local_platform + s.add_dependency "racc", "~> 1.4" + end + + build_gem "mini_portile2", "2.5.0" + build_gem "racc", "1.5.2" + end + + good_lockfile = <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + mini_portile2 (2.5.0) + nokogiri (1.11.1) + mini_portile2 (~> 2.5.0) + racc (~> 1.5.2) + nokogiri (1.11.1-#{Bundler.local_platform}) + racc (~> 1.4) + racc (1.5.2) + + PLATFORMS + #{lockfile_platforms_for(["ruby"] + local_platforms)} + + DEPENDENCIES + nokogiri (~> 1.11) + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "nokogiri", "~> 1.11" + G + + lockfile good_lockfile + + bundle "update nokogiri" + + expect(lockfile).to eq(good_lockfile) + end + + it "will not try to install platform specific gems when they don't match the current ruby if locked only to ruby" do + build_repo4 do + build_gem "nokogiri", "1.11.1" + + build_gem "nokogiri", "1.11.1" do |s| + s.platform = Bundler.local_platform + s.required_ruby_version = "< #{Gem.ruby_version}" + end + end + + gemfile <<-G + source "https://gems.repo4" + gem "nokogiri" + G + + lockfile <<~L + GEM + remote: https://gems.repo4/ + specs: + nokogiri (1.11.1) + + PLATFORMS + ruby + + DEPENDENCIES + nokogiri + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + + expect(out).to include("Fetching nokogiri 1.11.1") + expect(the_bundle).to include_gems "nokogiri 1.11.1" + expect(the_bundle).not_to include_gems "nokogiri 1.11.1 #{Bundler.local_platform}" + end + + it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "nokogiri" + G + + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + nokogiri (1.4.2) + nokogiri (1.4.2-java) + weakling (>= 0.0.3) + weakling (0.0.3) + + PLATFORMS + java + ruby + + DEPENDENCIES + nokogiri + + BUNDLED WITH + #{Bundler::VERSION} + G + + bundle "install" + + expect(out).to include("Fetching nokogiri 1.4.2 (java)") + expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA" + end + it "will add the resolve for the current platform" do lockfile <<-G GEM @@ -75,7 +195,7 @@ simulate_platform "x86-darwin-100" - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri" gem "platform_specific" @@ -84,40 +204,76 @@ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100" end + it "allows specifying only-ruby-platform on jruby", :jruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "nokogiri" + gem "platform_specific" + G + + bundle "config set force_ruby_platform true" + + bundle "install" + + expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY" + end + it "allows specifying only-ruby-platform" do - simulate_platform "java" + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "nokogiri" + gem "platform_specific" + G + + bundle "config set force_ruby_platform true" - install_gemfile! <<-G + bundle "install" + + expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY" + end + + it "allows specifying only-ruby-platform even if the lockfile is locked to a specific compatible platform" do + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri" gem "platform_specific" G - bundle! "config set force_ruby_platform true" + bundle "config set force_ruby_platform true" - bundle! "install" + bundle "install" expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY" end + it "doesn't pull platform specific gems on truffleruby", :truffleruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" + G + + expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" + end + it "allows specifying only-ruby-platform on windows with dependency platforms" do simulate_windows do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri", :platforms => [:mingw, :mswin, :x64_mingw, :jruby] gem "platform_specific" G - bundle! "config set force_ruby_platform true" + bundle "config set force_ruby_platform true" - bundle! "install" + bundle "install" expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" + expect(the_bundle).to not_include_gems "nokogiri" end end it "allows specifying only-ruby-platform on windows with gemspec dependency" do - build_lib("foo", "1.0", :path => ".") do |s| + build_lib("foo", "1.0", :path => bundled_app) do |s| s.add_dependency "rack" end @@ -125,11 +281,11 @@ source "#{file_uri_for(gem_repo1)}" gemspec G - bundle! :lock + bundle :lock simulate_windows do - bundle! "config set force_ruby_platform true" - bundle! "install" + bundle "config set force_ruby_platform true" + bundle "install" expect(the_bundle).to include_gems "rack 1.0" end @@ -158,7 +314,7 @@ requires_platform_specific L - install_gemfile! <<-G, :verbose => true + install_gemfile <<-G, :verbose => true source "#{file_uri_for(gem_repo2)}" gem "requires_platform_specific" G diff --git a/ruby/spec/bundler/runtime/require_spec.rb b/ruby/spec/bundler/runtime/require_spec.rb index a8d782612..d91b5f866 100644 --- a/ruby/spec/bundler/runtime/require_spec.rb +++ b/ruby/spec/bundler/runtime/require_spec.rb @@ -46,6 +46,7 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "one", :group => :bar, :require => %w[baz qux] gem "two" @@ -112,6 +113,7 @@ it "raises an exception if a require is specified but the file does not exist" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "two", :require => 'fail' end @@ -130,12 +132,13 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "faulty" end G - run "Bundler.require" + run "Bundler.require", :raise_on_error => false expect(err).to match("error while trying to load the gem 'faulty'") expect(err).to match("Gem Internal Error Message") end @@ -146,6 +149,7 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "loadfuuu" end @@ -155,7 +159,7 @@ begin Bundler.require rescue LoadError => e - $stderr.puts "ZOMG LOAD ERROR: \#{e.message}" + warn "ZOMG LOAD ERROR: \#{e.message}" end RUBY run(cmd) @@ -172,6 +176,7 @@ it "requires gem names that are namespaced" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path '#{lib_path}' do gem 'jquery-rails' end @@ -186,13 +191,15 @@ s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'" end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + path "#{lib_path}" do gem "bcrypt-ruby" end G cmd = <<-RUBY - require '#{lib_dir}/bundler' + require '#{entrypoint}' Bundler.require RUBY ruby(cmd) @@ -202,6 +209,7 @@ it "does not mangle explicitly given requires" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem 'jquery-rails', :require => 'jquery-rails' end @@ -219,6 +227,7 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "load-fuuu" end @@ -228,7 +237,7 @@ begin Bundler.require rescue LoadError => e - $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'") + warn "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'") end RUBY run(cmd) @@ -242,6 +251,7 @@ end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "load-fuuu" end @@ -251,7 +261,7 @@ begin Bundler.require rescue LoadError => e - $stderr.puts "ZOMG LOAD ERROR: \#{e.message}" + warn "ZOMG LOAD ERROR: \#{e.message}" end RUBY run(cmd) @@ -300,6 +310,7 @@ def self.two it "works when the gems are in the Gemfile in the correct order" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "two" gem "one" @@ -318,6 +329,7 @@ def self.two end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "multi_gem", :require => "one", :group => :one gem "multi_gem", :require => "two", :group => :two G @@ -341,6 +353,7 @@ def self.two it "fails when the gems are in the Gemfile in the wrong order" do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" path "#{lib_path}" do gem "one" gem "two" @@ -358,6 +371,7 @@ def self.two end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "busted_require" G @@ -370,12 +384,12 @@ def self.two end it "does not load rubygems gemspecs that are used" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - run! <<-R + run <<-R path = File.join(Gem.dir, "specifications", "rack-1.0.0.gemspec") contents = File.read(path) contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join @@ -384,7 +398,7 @@ def self.two end R - run! <<-R + run <<-R Bundler.require puts "WIN" R @@ -395,11 +409,12 @@ def self.two it "does not load git gemspecs that are used" do build_git "foo" - install_gemfile! <<-G + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}" G - run! <<-R + run <<-R path = Gem.loaded_specs["foo"].loaded_from contents = File.read(path) contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join @@ -408,7 +423,7 @@ def self.two end R - run! <<-R + run <<-R Bundler.require puts "WIN" R @@ -423,7 +438,7 @@ def self.two source "#{file_uri_for(gem_repo1)}" platforms :#{not_local_tag} do - gem "fail", :require => "omgomg" + gem "platform_specific", :require => "omgomg" end gem "rack", "1.0.0" @@ -434,6 +449,8 @@ def self.two end it "requires gems pinned to multiple platforms, including the current one" do + skip "platform issues" if Gem.win_platform? + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" diff --git a/ruby/spec/bundler/runtime/self_management_spec.rb b/ruby/spec/bundler/runtime/self_management_spec.rb new file mode 100644 index 000000000..0032c6aef --- /dev/null +++ b/ruby/spec/bundler/runtime/self_management_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +RSpec.describe "Self management", :rubygems => ">= 3.3.0.dev", :realworld => true do + describe "auto switching" do + let(:previous_minor) do + "2.3.0" + end + + before do + build_repo2 + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "rack" + G + end + + it "installs locked version when using system path and uses it" do + lockfile_bundled_with(previous_minor) + + bundle "config set --local path.system true" + bundle "install", :artifice => "vcr" + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + + # It uninstalls the older system bundler + bundle "clean --force" + expect(out).to eq("Removing bundler (#{Bundler::VERSION})") + + # App now uses locked version + bundle "-v" + expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + + # Subsequent installs use the locked version without reinstalling + bundle "install --verbose" + expect(out).to include("Using bundler #{previous_minor}") + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + end + + it "installs locked version when using local path and uses it" do + lockfile_bundled_with(previous_minor) + + bundle "config set --local path vendor/bundle" + bundle "install", :artifice => "vcr" + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist + + # It does not uninstall the locked bundler + bundle "clean" + expect(out).to be_empty + + # App now uses locked version + bundle "-v" + expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + + # Subsequent installs use the locked version without reinstalling + bundle "install --verbose" + expect(out).to include("Using bundler #{previous_minor}") + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + end + + it "installs locked version when using deployment option and uses it" do + lockfile_bundled_with(previous_minor) + + bundle "config set --local deployment true" + bundle "install", :artifice => "vcr" + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist + + # It does not uninstall the locked bundler + bundle "clean" + expect(out).to be_empty + + # App now uses locked version + bundle "-v" + expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + + # Subsequent installs use the locked version without reinstalling + bundle "install --verbose" + expect(out).to include("Using bundler #{previous_minor}") + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + end + + it "does not try to install a development version" do + lockfile_bundled_with("#{previous_minor}.dev") + + bundle "install --verbose" + expect(out).not_to match(/restarting using that version/) + + bundle "-v" + expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION) + end + + it "shows a discreet message if locked bundler does not exist" do + missing_minor ="#{Bundler::VERSION[0]}.999.999" + + lockfile_bundled_with(missing_minor) + + bundle "install", :artifice => "vcr" + expect(err).to eq("Your lockfile is locked to a version of bundler (#{missing_minor}) that doesn't exist at https://rubygems.org/. Going on using #{Bundler::VERSION}") + + bundle "-v" + expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION) + end + + private + + def lockfile_bundled_with(version) + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + rack (1.0.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + rack + + BUNDLED WITH + #{version} + L + end + end +end diff --git a/ruby/spec/bundler/runtime/setup_spec.rb b/ruby/spec/bundler/runtime/setup_spec.rb index 7f00a6307..35873dcaa 100644 --- a/ruby/spec/bundler/runtime/setup_spec.rb +++ b/ruby/spec/bundler/runtime/setup_spec.rb @@ -12,7 +12,7 @@ G ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup require 'rack' @@ -34,7 +34,7 @@ it "doesn't make all groups available" do ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup(:default) begin @@ -49,7 +49,7 @@ it "accepts string for group name" do ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup(:default, 'test') require 'rack' @@ -61,7 +61,7 @@ it "leaves all groups available if they were already" do ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup Bundler.setup(:default) @@ -74,7 +74,7 @@ it "leaves :default available if setup is called twice" do ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup(:default) Bundler.setup(:default, :test) @@ -90,8 +90,8 @@ end it "handles multiple non-additive invocations" do - ruby <<-RUBY - require '#{lib_dir}/bundler' + ruby <<-RUBY, :raise_on_error => false + require 'bundler' Bundler.setup(:default, :test) Bundler.setup(:default) require 'rack' @@ -107,9 +107,9 @@ context "load order" do def clean_load_path(lp) - without_bundler_load_path = ruby!("puts $LOAD_PATH").split("\n") - lp -= without_bundler_load_path - lp.map! {|p| p.sub(/^#{Regexp.union system_gem_path.to_s, default_bundle_path.to_s, lib_dir.to_s}/i, "") } + without_bundler_load_path = ruby("puts $LOAD_PATH").split("\n") + lp -= [*without_bundler_load_path, lib_dir.to_s] + lp.map! {|p| p.sub(system_gem_path.to_s, "") } end it "puts loaded gems after -I and RUBYLIB", :ruby_repo do @@ -122,7 +122,7 @@ def clean_load_path(lp) ENV["RUBYLIB"] = "rubylib_dir" ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' Bundler.setup puts $LOAD_PATH RUBY @@ -136,15 +136,15 @@ def clean_load_path(lp) end it "orders the load path correctly when there are dependencies" do - system_gems :bundler + bundle "config set path.system true" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rails" G - ruby! <<-RUBY - require '#{lib_dir}/bundler' + ruby <<-RUBY + require 'bundler' Bundler.setup puts $LOAD_PATH RUBY @@ -153,26 +153,27 @@ def clean_load_path(lp) expect(load_path).to start_with( "/gems/rails-2.3.2/lib", - "/gems/bundler-#{Bundler::VERSION}/lib", "/gems/activeresource-2.3.2/lib", "/gems/activerecord-2.3.2/lib", "/gems/actionpack-2.3.2/lib", "/gems/actionmailer-2.3.2/lib", "/gems/activesupport-2.3.2/lib", - "/gems/rake-12.3.2/lib" + "/gems/rake-13.0.1/lib" ) end it "falls back to order the load path alphabetically for backwards compatibility" do - install_gemfile! <<-G + bundle "config set path.system true" + + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "weakling" gem "duradura" gem "terranova" G - ruby! <<-RUBY - require '#{lib_dir}/bundler/setup' + ruby <<-RUBY + require 'bundler/setup' puts $LOAD_PATH RUBY @@ -193,7 +194,7 @@ def clean_load_path(lp) G ruby <<-R - require '#{lib_dir}/bundler' + require '#{entrypoint}' begin Bundler.setup @@ -212,13 +213,13 @@ def clean_load_path(lp) gem "rack" G - ruby <<-R - require '#{lib_dir}/bundler' + ruby <<-R, :raise_on_error => false + require 'bundler' Bundler.setup R - expect(bundled_app("Gemfile.lock")).not_to exist + expect(bundled_app_lock).not_to exist end it "doesn't change the Gemfile.lock if the setup fails" do @@ -227,7 +228,7 @@ def clean_load_path(lp) gem "rack" G - lockfile = File.read(bundled_app("Gemfile.lock")) + lockfile = File.read(bundled_app_lock) gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -235,13 +236,13 @@ def clean_load_path(lp) gem "nosuchgem", "10.0" G - ruby <<-R - require '#{lib_dir}/bundler' + ruby <<-R, :raise_on_error => false + require 'bundler' Bundler.setup R - expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile) + expect(File.read(bundled_app_lock)).to eq(lockfile) end it "makes a Gemfile.lock if setup succeeds" do @@ -250,12 +251,12 @@ def clean_load_path(lp) gem "rack" G - File.read(bundled_app("Gemfile.lock")) + File.read(bundled_app_lock) - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) run "1" - expect(bundled_app("Gemfile.lock")).to exist + expect(bundled_app_lock).to exist end describe "$BUNDLE_GEMFILE" do @@ -279,17 +280,17 @@ def clean_load_path(lp) end context "an absolute path is not provided" do - it "uses BUNDLE_GEMFILE to locate the gemfile if present" do + it "uses BUNDLE_GEMFILE to locate the gemfile if present and doesn't fail in deployment mode" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" G bundle "install" - bundle "install --deployment" + bundle "config set --local deployment true" ENV["BUNDLE_GEMFILE"] = "Gemfile" ruby <<-R - require '#{lib_dir}/bundler' + require 'bundler' begin Bundler.setup @@ -429,12 +430,13 @@ def clean_load_path(lp) build_git "rack", "1.0.0" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", :git => "#{lib_path("rack-1.0.0")}" G end it "provides a useful exception when the git repo is not checked out yet" do - run "1" + run "1", :raise_on_error => false expect(err).to match(/the git source #{lib_path('rack-1.0.0')} is not yet checked out. Please run `bundle install`/i) end @@ -444,7 +446,7 @@ def clean_load_path(lp) break_git! ruby <<-R - require '#{lib_dir}/bundler' + require 'bundler' begin Bundler.setup @@ -460,12 +462,12 @@ def clean_load_path(lp) it "provides a good exception if the lockfile is unavailable" do bundle "install" - FileUtils.rm(bundled_app("Gemfile.lock")) + FileUtils.rm(bundled_app_lock) break_git! ruby <<-R - require "#{lib_dir}/bundler" + require "#{entrypoint}" begin Bundler.setup @@ -475,29 +477,32 @@ def clean_load_path(lp) end R - run "puts 'FAIL'" + run "puts 'FAIL'", :raise_on_error => false expect(err).not_to include "This is not the git you are looking for" end it "works even when the cache directory has been deleted" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle :install FileUtils.rm_rf vendored_gems("cache") expect(the_bundle).to include_gems "rack 1.0.0" end it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle :install - with_read_only("**/*") do + with_read_only("#{bundled_app}/**/*") do expect(the_bundle).to include_gems "rack 1.0.0" end end it "finds git gem when default bundle path becomes read only" do + bundle "config set --local path .bundle" bundle "install" - with_read_only("#{Bundler.bundle_path}/**/*") do + with_read_only("#{bundled_app(".bundle")}/**/*") do expect(the_bundle).to include_gems "rack 1.0.0" end end @@ -515,10 +520,10 @@ def clean_load_path(lp) G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle! :install + bundle :install FileUtils.rm_rf(lib_path("local-rack")) - run "require 'rack'" + run "require 'rack'", :raise_on_error => false expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/) end @@ -533,14 +538,14 @@ def clean_load_path(lp) G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle! :install + bundle :install gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", :git => "#{lib_path("rack-0.8")}" G - run "require 'rack'" + run "require 'rack'", :raise_on_error => false expect(err).to match(/because :branch is not specified in Gemfile/) end @@ -555,14 +560,14 @@ def clean_load_path(lp) G bundle %(config set local.rack #{lib_path("local-rack")}) - bundle! :install + bundle :install gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "changed" G - run "require 'rack'" + run "require 'rack'", :raise_on_error => false expect(err).to match(/is using branch master but Gemfile specifies changed/) end @@ -582,14 +587,15 @@ def clean_load_path(lp) G bundle %(config set local.rack #{lib_path("local-rack")}) - run "require 'rack'" + run "require 'rack'", :raise_on_error => false expect(err).to match(/is using branch master but Gemfile specifies nonexistant/) end end describe "when excluding groups" do it "doesn't change the resolve if --without is used" do - install_gemfile <<-G, forgotten_command_line_options(:without => :rails) + bundle "config set --local without rails" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "activesupport" @@ -598,13 +604,14 @@ def clean_load_path(lp) end G - install_gems "activesupport-2.3.5" + system_gems "activesupport-2.3.5" expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => :default end it "remembers --without and does not bail on bare Bundler.setup" do - install_gemfile <<-G, forgotten_command_line_options(:without => :rails) + bundle "config set --local without rails" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "activesupport" @@ -613,13 +620,53 @@ def clean_load_path(lp) end G - install_gems "activesupport-2.3.5" + system_gems "activesupport-2.3.5" expect(the_bundle).to include_gems "activesupport 2.3.2" end + it "remembers --without and does not bail on bare Bundler.setup, even in the case of path gems no longer available" do + bundle "config set --local without development" + + path = bundled_app(File.join("vendor", "foo")) + build_lib "foo", :path => path + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "activesupport", "2.3.2" + gem 'foo', :path => 'vendor/foo', :group => :development + G + + FileUtils.rm_rf(path) + + ruby "require 'bundler'; Bundler.setup", :env => { "DEBUG" => "1" } + expect(out).to include("Assuming that source at `vendor/foo` has not changed since fetching its specs errored") + expect(out).to include("Found no changes, using resolution from the lockfile") + expect(err).to be_empty + end + + it "doesn't re-resolve when a pre-release bundler is used and a dependency includes a dependency on bundler" do + system_gems "bundler-9.99.9.beta1" + + build_repo4 do + build_gem "depends_on_bundler", "1.0" do |s| + s.add_dependency "bundler", ">= 1.5.0" + end + end + + install_gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "depends_on_bundler" + G + + ruby "require '#{system_gem_path("gems/bundler-9.99.9.beta1/lib/bundler.rb")}'; Bundler.setup", :env => { "DEBUG" => "1" } + expect(out).to include("Found no changes, using resolution from the lockfile") + expect(err).to be_empty + end + it "remembers --without and does not include groups passed to Bundler.setup" do - install_gemfile <<-G, forgotten_command_line_options(:without => :rails) + bundle "config set --local without rails" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "activesupport" @@ -659,12 +706,12 @@ def clean_load_path(lp) end it "does not load all gemspecs" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - run! <<-R + run <<-R File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f| f.write <<-RUBY # -*- encoding: utf-8 -*- @@ -679,7 +726,7 @@ def clean_load_path(lp) end R - run! <<-R + run <<-R puts "WIN" R @@ -698,41 +745,68 @@ def clean_load_path(lp) expect(err).to be_empty end - describe "$MANPATH" do - before do + context "when the user has `MANPATH` set", :man do + before { ENV["MANPATH"] = "/foo#{File::PATH_SEPARATOR}" } + + it "adds the gem's man dir to the MANPATH" do build_repo4 do build_gem "with_man" do |s| s.write("man/man1/page.1", "MANPAGE") end end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "with_man" + G + + run "puts ENV['MANPATH']" + expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}/foo") end + end - context "when the user has one set" do - before { ENV["MANPATH"] = "/foo:" } + context "when the user does not have `MANPATH` set", :man do + before { ENV.delete("MANPATH") } - it "adds the gem's man dir to the MANPATH" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "with_man" - G + it "adds the gem's man dir to the MANPATH, leaving : in the end so that system man pages still work" do + build_repo4 do + build_gem "with_man" do |s| + s.write("man/man1/page.1", "MANPAGE") + end - run! "puts ENV['MANPATH']" - expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}:/foo") + build_gem "with_man_overriding_system_man" do |s| + s.write("man/man1/ls.1", "LS MANPAGE") + end end - end - context "when the user does not have one set" do - before { ENV.delete("MANPATH") } + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "with_man" + G - it "adds the gem's man dir to the MANPATH" do - install_gemfile! <<-G - source "#{file_uri_for(gem_repo4)}" - gem "with_man" - G + run <<~RUBY + puts ENV['MANPATH'] + require "open3" + puts Open3.capture2e("man", "ls")[1].success? + RUBY - run! "puts ENV['MANPATH']" - expect(out).to eq(default_bundle_path("gems/with_man-1.0/man").to_s) - end + expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}\ntrue") + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "with_man_overriding_system_man" + G + + run <<~RUBY + puts ENV['MANPATH'] + require "open3" + puts Open3.capture2e("man", "ls")[0] + RUBY + + lines = out.split("\n") + + expect(lines).to include("#{default_bundle_path("gems/with_man_overriding_system_man-1.0/man")}#{File::PATH_SEPARATOR}") + expect(lines).to include("LS MANPAGE") end end @@ -759,22 +833,20 @@ def clean_load_path(lp) full_gem_name = gem_name + "-1.0" ext_dir = File.join(tmp("extensions", full_gem_name)) - install_gems full_gem_name + system_gems full_gem_name install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" G ruby <<-R - if Gem::Specification.method_defined? :extension_dir - s = Gem::Specification.find_by_name '#{gem_name}' - s.extension_dir = '#{ext_dir}' + s = Gem::Specification.find_by_name '#{gem_name}' + s.extension_dir = '#{ext_dir}' - # Don't build extensions. - s.class.send(:define_method, :build_extensions) { nil } - end + # Don't build extensions. + s.class.send(:define_method, :build_extensions) { nil } - require '#{lib_dir}/bundler' + require 'bundler' gem '#{gem_name}' puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} >= 2 @@ -793,13 +865,15 @@ def clean_load_path(lp) let(:full_name) { "bundler-#{Bundler::VERSION}" } before do + skip "symlink destination exists" if Gem.win_platform? + FileUtils.ln_sf(gem_home, symlinked_gem_home) gems_dir = File.join(gem_home, "gems") specifications_dir = File.join(gem_home, "specifications") Dir.mkdir(gems_dir) Dir.mkdir(specifications_dir) - FileUtils.ln_s(root, File.join(gems_dir, full_name)) + FileUtils.ln_s(source_root, File.join(gems_dir, full_name)) gemspec_content = File.binread(gemspec). sub("Bundler::VERSION", %("#{Bundler::VERSION}")). @@ -811,11 +885,11 @@ def clean_load_path(lp) end it "should not remove itself from the LOAD_PATH and require a different copy of 'bundler/setup'" do - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" - ruby <<-R, :env => { "GEM_PATH" => symlinked_gem_home }, :no_lib => true + ruby <<-R, :env => { "GEM_PATH" => symlinked_gem_home } TracePoint.trace(:class) do |tp| - if tp.path.include?("bundler") && !tp.path.start_with?("#{root}") + if tp.path.include?("bundler") && !tp.path.start_with?("#{source_root}") puts "OMG. Defining a class from another bundler at \#{tp.path}:\#{tp.lineno}" end end @@ -860,14 +934,13 @@ def clean_load_path(lp) FileUtils.rm(File.join(path, "foo.gemspec")) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', '1.2.3', :path => 'vendor/foo' G - Dir.chdir(bundled_app.parent) do - run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile").to_s } - require 'foo' - R - end + run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, :dir => bundled_app.parent + require 'foo' + R expect(err).to be_empty end @@ -882,16 +955,15 @@ def clean_load_path(lp) FileUtils.rm(File.join(absolute_path, "foo.gemspec")) gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', '1.2.3', :path => '#{relative_path}' G bundle :install - Dir.chdir(bundled_app.parent) do - run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile").to_s } - require 'foo' - R - end + run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, :dir => bundled_app.parent + require 'foo' + R expect(err).to be_empty end @@ -902,6 +974,7 @@ def clean_load_path(lp) build_git "no_gemspec", :gemspec => false install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "no_gemspec", "1.0", :git => "#{lib_path("no_gemspec-1.0")}" G end @@ -969,7 +1042,7 @@ def clean_load_path(lp) describe "with system gems in the bundle" do before :each do - bundle! "config set path.system true" + bundle "config set path.system true" system_gems "rack-1.0.0" install_gemfile <<-G @@ -1004,6 +1077,7 @@ def clean_load_path(lp) end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "bar", :git => "#{lib_path("bar-1.0")}" G end @@ -1015,14 +1089,15 @@ def clean_load_path(lp) end it "error intelligently if the gemspec has a LoadError" do + skip "whitespace issue?" if Gem.win_platform? + ref = update_git "bar", :gemspec => false do |s| s.write "bar.gemspec", "require 'foobarbaz'" end.ref_for("HEAD") - bundle :install + bundle :install, :raise_on_error => false expect(err.lines.map(&:chomp)).to include( a_string_starting_with("[!] There was an error while loading `bar.gemspec`:"), - a_string_starting_with("Does it try to require a relative path? That's been removed in Ruby 1.9."), " # from #{default_bundle_path "bundler", "gems", "bar-1.0-#{ref[0, 12]}", "bar.gemspec"}:1", " > require 'foobarbaz'" ) @@ -1032,7 +1107,7 @@ def clean_load_path(lp) bundle "install" ruby <<-RUBY - require '#{lib_dir}/bundler' + require 'bundler' bundler_module = class << Bundler; self; end bundler_module.send(:remove_method, :require) def Bundler.require(path) @@ -1049,6 +1124,7 @@ def Bundler.require(path) describe "when Bundler is bundled" do it "doesn't blow up" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "bundler", :path => "#{root}" G @@ -1059,7 +1135,7 @@ def Bundler.require(path) describe "when BUNDLED WITH" do def lock_with(bundler_version = nil) - lock = <<-L + lock = <<~L GEM remote: #{file_uri_for(gem_repo1)}/ specs: @@ -1073,13 +1149,15 @@ def lock_with(bundler_version = nil) L if bundler_version - lock += "\n BUNDLED WITH\n #{bundler_version}\n" + lock += "\nBUNDLED WITH\n #{bundler_version}\n" end lock end before do + bundle "config set --local path.system true" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -1089,26 +1167,27 @@ def lock_with(bundler_version = nil) context "is not present" do it "does not change the lock" do lockfile lock_with(nil) - ruby "require '#{lib_dir}/bundler/setup'" - lockfile_should_be lock_with(nil) + ruby "require '#{entrypoint}/setup'" + expect(lockfile).to eq lock_with(nil) end end context "is newer" do it "does not change the lock or warn" do lockfile lock_with(Bundler::VERSION.succ) - ruby "require '#{lib_dir}/bundler/setup'" + ruby "require 'bundler/setup'" expect(out).to be_empty expect(err).to be_empty - lockfile_should_be lock_with(Bundler::VERSION.succ) + expect(lockfile).to eq lock_with(Bundler::VERSION.succ) end end context "is older" do it "does not change the lock" do + system_gems "bundler-1.10.1" lockfile lock_with("1.10.1") - ruby "require '#{lib_dir}/bundler/setup'" - lockfile_should_be lock_with("1.10.1") + ruby "require '#{entrypoint}/setup'" + expect(lockfile).to eq lock_with("1.10.1") end end end @@ -1117,7 +1196,7 @@ def lock_with(bundler_version = nil) let(:ruby_version) { nil } def lock_with(ruby_version = nil) - lock = <<-L + lock = <<~L GEM remote: #{file_uri_for(gem_repo1)}/ specs: @@ -1131,10 +1210,10 @@ def lock_with(ruby_version = nil) L if ruby_version - lock += "\n RUBY VERSION\n ruby #{ruby_version}\n" + lock += "\nRUBY VERSION\n ruby #{ruby_version}\n" end - lock += <<-L + lock += <<~L BUNDLED WITH #{Bundler::VERSION} @@ -1154,14 +1233,14 @@ def lock_with(ruby_version = nil) context "is not present" do it "does not change the lock" do - expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile } + expect { ruby "require 'bundler/setup'" }.not_to change { lockfile } end end context "is newer" do let(:ruby_version) { "5.5.5" } it "does not change the lock or warn" do - expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile } + expect { ruby "require 'bundler/setup'" }.not_to change { lockfile } expect(out).to be_empty expect(err).to be_empty end @@ -1170,16 +1249,51 @@ def lock_with(ruby_version = nil) context "is older" do let(:ruby_version) { "1.0.0" } it "does not change the lock" do - expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile } + expect { ruby "require 'bundler/setup'" }.not_to change { lockfile } end end end describe "with gemified standard libraries" do + it "does not load Digest", :ruby_repo do + skip "Only for Ruby 3.0+" unless RUBY_VERSION >= "3.0" + + build_git "bar", :gemspec => false do |s| + s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0') + s.write "bar.gemspec", <<-G + require_relative 'lib/bar/version' + + Gem::Specification.new do |s| + s.name = 'bar' + s.version = BAR_VERSION + s.summary = 'Bar' + s.files = Dir["lib/**/*.rb"] + s.author = 'no one' + + s.add_runtime_dependency 'digest' + end + G + end + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "bar", :git => "#{lib_path("bar-1.0")}" + G + + bundle :install + + ruby <<-RUBY + require '#{entrypoint}/setup' + puts defined?(::Digest) ? "Digest defined" : "Digest undefined" + require 'digest' + RUBY + expect(out).to eq("Digest undefined") + end + it "does not load Psych" do - gemfile "" + gemfile "source \"#{file_uri_for(gem_repo1)}\"" ruby <<-RUBY - require '#{lib_dir}/bundler/setup' + require '#{entrypoint}/setup' puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined" require 'psych' puts Psych::VERSION @@ -1190,9 +1304,9 @@ def lock_with(ruby_version = nil) end it "does not load openssl" do - install_gemfile! "" - ruby! <<-RUBY - require "#{lib_dir}/bundler/setup" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + ruby <<-RUBY + require "bundler/setup" puts defined?(OpenSSL) || "undefined" require "openssl" puts defined?(OpenSSL) || "undefined" @@ -1202,11 +1316,19 @@ def lock_with(ruby_version = nil) describe "default gem activation" do let(:exemptions) do - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7") + exempts = if Gem.rubygems_version >= Gem::Version.new("2.7") %w[did_you_mean] else %w[io-console openssl] end << "bundler" + exempts << "fiddle" if Gem.win_platform? && Gem.rubygems_version >= Gem::Version.new("2.7") + exempts << "uri" if Gem.ruby_version >= Gem::Version.new("2.7") + exempts << "pathname" if Gem.ruby_version >= Gem::Version.new("3.0") + exempts << "set" unless Gem.rubygems_version >= Gem::Version.new("3.2.6") + exempts << "tsort" unless Gem.rubygems_version >= Gem::Version.new("3.2.31") + exempts << "error_highlight" # added in Ruby 3.1 as a default gem + exempts << "ruby2_keywords" # added in Ruby 3.1 as a default gem + exempts end let(:activation_warning_hack) { strip_whitespace(<<-RUBY) } @@ -1243,23 +1365,25 @@ def lock_with(ruby_version = nil) RUBY it "activates no gems with -rbundler/setup" do - install_gemfile! "" - ruby! code, :env => { "RUBYOPT" => activation_warning_hack_rubyopt + " -r#{lib_dir}/bundler/setup" } + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + ruby code, :env => { "RUBYOPT" => activation_warning_hack_rubyopt + " -rbundler/setup" } expect(out).to eq("{}") end it "activates no gems with bundle exec" do - install_gemfile! "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" create_file("script.rb", code) - bundle! "exec ruby ./script.rb", :env => { "RUBYOPT" => activation_warning_hack_rubyopt } + bundle "exec ruby ./script.rb", :env => { "RUBYOPT" => activation_warning_hack_rubyopt } expect(out).to eq("{}") end it "activates no gems with bundle exec that is loaded" do - install_gemfile! "" + skip "not executable" if Gem.win_platform? + + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" create_file("script.rb", "#!/usr/bin/env ruby\n\n#{code}") FileUtils.chmod(0o777, bundled_app("script.rb")) - bundle! "exec ./script.rb", :artifice => nil, :env => { "RUBYOPT" => activation_warning_hack_rubyopt } + bundle "exec ./script.rb", :artifice => nil, :env => { "RUBYOPT" => activation_warning_hack_rubyopt } expect(out).to eq("{}") end @@ -1268,31 +1392,31 @@ def lock_with(ruby_version = nil) build_gem "net-http-pipeline", "1.0.1" end - system_gems "net-http-pipeline-1.0.1", :gem_repo => gem_repo4 do - gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "net-http-pipeline", "1.0.1" - G + system_gems "net-http-pipeline-1.0.1", :gem_repo => gem_repo4 - bundle "config set --local path vendor/bundle" + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "net-http-pipeline", "1.0.1" + G - bundle! :install + bundle "config set --local path vendor/bundle" - bundle! :check + bundle :install - expect(out).to eq("The Gemfile's dependencies are satisfied") - end + bundle :check + + expect(out).to eq("The Gemfile's dependencies are satisfied") end Gem::Specification.select(&:default_gem?).map(&:name).each do |g| - it "activates newer versions of #{g}" do + it "activates newer versions of #{g}", :ruby_repo do skip if exemptions.include?(g) build_repo4 do build_gem g, "999999" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" gem "#{g}", "999999" G @@ -1300,14 +1424,14 @@ def lock_with(ruby_version = nil) expect(the_bundle).to include_gem("#{g} 999999", :env => { "RUBYOPT" => activation_warning_hack_rubyopt }) end - it "activates older versions of #{g}" do + it "activates older versions of #{g}", :ruby_repo do skip if exemptions.include?(g) build_repo4 do build_gem g, "0.0.0.a" end - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" gem "#{g}", "0.0.0.a" G @@ -1325,8 +1449,8 @@ def lock_with(ruby_version = nil) gem "rack" G - ruby! <<-RUBY - require "#{lib_dir}/bundler/setup" + ruby <<-RUBY + require "bundler/setup" Object.new.gem "rack" puts Gem.loaded_specs["rack"].full_name RUBY @@ -1335,13 +1459,13 @@ def lock_with(ruby_version = nil) end it "keeps Kernel#gem private", :bundler => "3" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - ruby <<-RUBY - require "#{lib_dir}/bundler/setup" + ruby <<-RUBY, :raise_on_error => false + require "bundler/setup" Object.new.gem "rack" puts "FAIL" RUBY @@ -1351,13 +1475,13 @@ def lock_with(ruby_version = nil) end it "keeps Kernel#require private" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - ruby <<-RUBY - require "#{lib_dir}/bundler/setup" + ruby <<-RUBY, :raise_on_error => false + require "bundler/setup" Object.new.require "rack" puts "FAIL" RUBY @@ -1367,9 +1491,48 @@ def lock_with(ruby_version = nil) end it "takes care of requiring rubygems" do - sys_exec("#{Gem.ruby} -I#{lib_dir} -e \"puts require('bundler/setup')\"", "RUBYOPT" => "--disable=gems") + sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", :env => { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) }) expect(last_command.stdboth).to eq("true") end + + it "memoizes initial set of specs when requiring bundler/setup, so that even if further code mutates dependencies, Bundler.definition.specs is not affected" do + install_gemfile <<~G + source "#{file_uri_for(gem_repo1)}" + gem "yard" + gem "rack", :group => :test + G + + ruby <<-RUBY, :raise_on_error => false + require "bundler/setup" + Bundler.require(:test).select! {|d| (d.groups & [:test]).any? } + puts Bundler.definition.specs.map(&:name).join(", ") + RUBY + + expect(out).to include("rack, yard") + end + + it "does not cause double loads when higher versions of default gems are activated before bundler" do + build_repo2 do + build_gem "json", "999.999.999" do |s| + s.write "lib/json.rb", <<~RUBY + module JSON + VERSION = "999.999.999" + end + RUBY + end + end + + system_gems "json-999.999.999", :gem_repo => gem_repo2 + + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" + ruby <<-RUBY + require "json" + require "bundler/setup" + require "json" + RUBY + + expect(err).to be_empty + end end end diff --git a/ruby/spec/bundler/runtime/with_unbundled_env_spec.rb b/ruby/spec/bundler/runtime/with_unbundled_env_spec.rb index 4aaf9d499..731a9921a 100644 --- a/ruby/spec/bundler/runtime/with_unbundled_env_spec.rb +++ b/ruby/spec/bundler/runtime/with_unbundled_env_spec.rb @@ -1,50 +1,58 @@ # frozen_string_literal: true RSpec.describe "Bundler.with_env helpers" do - def bundle_exec_ruby!(code, options = {}) + def bundle_exec_ruby(args, options = {}) build_bundler_context options - bundle! "exec '#{Gem.ruby}' -e #{code}", options + bundle "exec '#{Gem.ruby}' #{args}", options end def build_bundler_context(options = {}) bundle "config set path vendor/bundle" - gemfile "" + gemfile "source \"#{file_uri_for(gem_repo1)}\"" bundle "install", options end + def run_bundler_script(env, script) + system(env, "ruby", "-I#{lib_dir}", "-rbundler", script.to_s) + end + describe "Bundler.original_env" do it "should return the PATH present before bundle was activated" do - code = "print Bundler.original_env['PATH']" + create_file("source.rb", <<-RUBY) + print Bundler.original_env["PATH"] + RUBY path = `getconf PATH`.strip + "#{File::PATH_SEPARATOR}/foo" with_path_as(path) do - bundle_exec_ruby!(code.dump) + bundle_exec_ruby(bundled_app("source.rb").to_s) expect(last_command.stdboth).to eq(path) end end it "should return the GEM_PATH present before bundle was activated" do - code = "print Bundler.original_env['GEM_PATH']" - gem_path = ENV["GEM_PATH"] + ":/foo" + create_file("source.rb", <<-RUBY) + print Bundler.original_env['GEM_PATH'] + RUBY + gem_path = ENV["GEM_PATH"] + "#{File::PATH_SEPARATOR}/foo" with_gem_path_as(gem_path) do - bundle_exec_ruby!(code.dump) + bundle_exec_ruby(bundled_app("source.rb").to_s) expect(last_command.stdboth).to eq(gem_path) end end - it "works with nested bundle exec invocations" do - create_file("exe.rb", <<-'RB') + it "works with nested bundle exec invocations", :ruby_repo do + create_file("exe.rb", <<-'RUBY') count = ARGV.first.to_i exit if count < 0 - STDERR.puts "#{count} #{ENV["PATH"].end_with?(":/foo")}" + STDERR.puts "#{count} #{ENV["PATH"].end_with?("#{File::PATH_SEPARATOR}/foo")}" if count == 2 - ENV["PATH"] = "#{ENV["PATH"]}:/foo" + ENV["PATH"] = "#{ENV["PATH"]}#{File::PATH_SEPARATOR}/foo" end exec(Gem.ruby, __FILE__, (count - 1).to_s) - RB + RUBY path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby) with_path_as(path) do build_bundler_context - bundle! "exec '#{Gem.ruby}' #{bundled_app("exe.rb")} 2" + bundle_exec_ruby("#{bundled_app("exe.rb")} 2") end expect(err).to eq <<-EOS.strip 2 false @@ -57,41 +65,65 @@ def build_bundler_context(options = {}) # Simulate bundler has not yet been loaded ENV.replace(ENV.to_hash.delete_if {|k, _v| k.start_with?(Bundler::EnvironmentPreserver::BUNDLER_PREFIX) }) - original = ruby!('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")') - code = 'puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n")' - bundle_exec_ruby! code.dump + original = ruby('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")') + create_file("source.rb", <<-RUBY) + puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n") + RUBY + bundle_exec_ruby bundled_app("source.rb") expect(out).to eq original end end shared_examples_for "an unbundling helper" do it "should delete BUNDLE_PATH" do - code = "print #{modified_env}.has_key?('BUNDLE_PATH')" + create_file("source.rb", <<-RUBY) + print #{modified_env}.has_key?('BUNDLE_PATH') + RUBY ENV["BUNDLE_PATH"] = "./foo" - bundle_exec_ruby! code.dump + bundle_exec_ruby bundled_app("source.rb") expect(last_command.stdboth).to include "false" end - it "should remove '-rbundler/setup' from RUBYOPT" do - code = "print #{modified_env}['RUBYOPT']" - ENV["RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}" - bundle_exec_ruby! code.dump, :env => { "BUNDLER_SPEC_DISABLE_DEFAULT_BUNDLER_GEM" => "true" } + it "should remove absolute path to 'bundler/setup' from RUBYOPT even if it was present in original env" do + create_file("source.rb", <<-RUBY) + print #{modified_env}['RUBYOPT'] + RUBY + setup_require = "-r#{lib_dir}/bundler/setup" + ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 #{setup_require} #{ENV["RUBYOPT"]}" + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + bundle_exec_ruby bundled_app("source.rb") + end + expect(last_command.stdboth).not_to include(setup_require) + end + + it "should remove relative path to 'bundler/setup' from RUBYOPT even if it was present in original env" do + create_file("source.rb", <<-RUBY) + print #{modified_env}['RUBYOPT'] + RUBY + ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}" + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + bundle_exec_ruby bundled_app("source.rb") + end expect(last_command.stdboth).not_to include("-rbundler/setup") end it "should restore RUBYLIB", :ruby_repo do - code = "print #{modified_env}['RUBYLIB']" + create_file("source.rb", <<-RUBY) + print #{modified_env}['RUBYLIB'] + RUBY ENV["RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo" ENV["BUNDLER_ORIG_RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo-original" - bundle_exec_ruby! code.dump + bundle_exec_ruby bundled_app("source.rb") expect(last_command.stdboth).to include("/foo-original") end it "should restore the original MANPATH" do - code = "print #{modified_env}['MANPATH']" + create_file("source.rb", <<-RUBY) + print #{modified_env}['MANPATH'] + RUBY ENV["MANPATH"] = "/foo" ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original" - bundle_exec_ruby! code.dump + bundle_exec_ruby bundled_app("source.rb") expect(last_command.stdboth).to include("/foo-original") end end @@ -111,7 +143,7 @@ def build_bundler_context(options = {}) describe "Bundler.with_original_env" do it "should set ENV to original_env in the block" do expected = Bundler.original_env - actual = Bundler.with_original_env { ENV.to_hash } + actual = Bundler.with_original_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) } expect(actual).to eq(expected) end @@ -129,7 +161,7 @@ def build_bundler_context(options = {}) expected = Bundler.unbundled_env actual = Bundler.ui.silence do - Bundler.with_clean_env { ENV.to_hash } + Bundler.with_clean_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) } end expect(actual).to eq(expected) @@ -147,7 +179,7 @@ def build_bundler_context(options = {}) describe "Bundler.with_unbundled_env" do it "should set ENV to unbundled_env in the block" do expected = Bundler.unbundled_env - actual = Bundler.with_unbundled_env { ENV.to_hash } + actual = Bundler.with_unbundled_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) } expect(actual).to eq(expected) end @@ -161,53 +193,53 @@ def build_bundler_context(options = {}) end describe "Bundler.original_system" do - let(:code) do - <<~RUBY - Bundler.original_system(%([ "\$BUNDLE_FOO" = "bar" ] && exit 42)) + before do + create_file("source.rb", <<-'RUBY') + Bundler.original_system("ruby", "-e", "exit(42) if ENV['BUNDLE_FOO'] == 'bar'") exit $?.exitstatus RUBY end it "runs system inside with_original_env" do - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(42) end end describe "Bundler.clean_system", :bundler => 2 do - let(:code) do - <<~RUBY - Bundler.ui.silence { Bundler.clean_system(%([ "\$BUNDLE_FOO" = "bar" ] || exit 42)) } + before do + create_file("source.rb", <<-'RUBY') + Bundler.ui.silence { Bundler.clean_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'") } exit $?.exitstatus RUBY end it "runs system inside with_clean_env" do - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(42) end end describe "Bundler.unbundled_system" do - let(:code) do - <<~RUBY - Bundler.unbundled_system(%([ "\$BUNDLE_FOO" = "bar" ] || exit 42)) + before do + create_file("source.rb", <<-'RUBY') + Bundler.unbundled_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'") exit $?.exitstatus RUBY end it "runs system inside with_unbundled_env" do - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(42) end end describe "Bundler.original_exec" do - let(:code) do - <<~RUBY + before do + create_file("source.rb", <<-'RUBY') Process.fork do exit Bundler.original_exec(%(test "\$BUNDLE_FOO" = "bar")) end @@ -221,14 +253,14 @@ def build_bundler_context(options = {}) it "runs exec inside with_original_env" do skip "Fork not implemented" if Gem.win_platform? - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(0) end end describe "Bundler.clean_exec", :bundler => 2 do - let(:code) do - <<~RUBY + before do + create_file("source.rb", <<-'RUBY') Process.fork do exit Bundler.ui.silence { Bundler.clean_exec(%(test "\$BUNDLE_FOO" = "bar")) } end @@ -242,14 +274,14 @@ def build_bundler_context(options = {}) it "runs exec inside with_clean_env" do skip "Fork not implemented" if Gem.win_platform? - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(1) end end describe "Bundler.unbundled_exec" do - let(:code) do - <<~RUBY + before do + create_file("source.rb", <<-'RUBY') Process.fork do exit Bundler.unbundled_exec(%(test "\$BUNDLE_FOO" = "bar")) end @@ -263,7 +295,7 @@ def build_bundler_context(options = {}) it "runs exec inside with_clean_env" do skip "Fork not implemented" if Gem.win_platform? - system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'") + run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) expect($?.exitstatus).to eq(1) end end diff --git a/ruby/spec/bundler/spec_helper.rb b/ruby/spec/bundler/spec_helper.rb index 0a49b46aa..dce2939e8 100644 --- a/ruby/spec/bundler/spec_helper.rb +++ b/ruby/spec/bundler/spec_helper.rb @@ -1,11 +1,6 @@ # frozen_string_literal: true -require_relative "support/path" - -$:.unshift Spec::Path.spec_dir.to_s -$:.unshift Spec::Path.lib_dir.to_s - -require "bundler/psyched_yaml" +require "psych" require "bundler/vendored_fileutils" require "bundler/vendored_uri" require "digest" @@ -15,17 +10,19 @@ end require "bundler" -require "rspec" +require "rspec/core" +require "rspec/expectations" +require "rspec/mocks" +require "rspec/support/differ" require_relative "support/builders" +require_relative "support/build_metadata" require_relative "support/filters" require_relative "support/helpers" require_relative "support/indexes" require_relative "support/matchers" -require_relative "support/parallel" require_relative "support/permissions" require_relative "support/platforms" -require_relative "support/sometimes" require_relative "support/sudo" $debug = false @@ -49,6 +46,8 @@ def self.ruby=(ruby) # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" + config.silence_filter_announcements = !ENV["TEST_ENV_NUMBER"].nil? + config.disable_monkey_patching! # Since failures cause us to keep a bunch of long strings in memory, stop @@ -59,9 +58,6 @@ def self.ruby=(ruby) config.bisect_runner = :shell - original_wd = Dir.pwd - original_env = ENV.to_hash - config.expect_with :rspec do |c| c.syntax = :expect end @@ -70,61 +66,54 @@ def self.ruby=(ruby) mocks.allow_message_expectations_on_nil = false end - config.around :each do |example| - if ENV["RUBY"] - orig_ruby = Gem.ruby - Gem.ruby = ENV["RUBY"] - end - example.run - Gem.ruby = orig_ruby if ENV["RUBY"] - end - config.before :suite do + Gem.ruby = ENV["RUBY"] if ENV["RUBY"] + require_relative "support/rubygems_ext" - Spec::Rubygems.setup - ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -r#{Spec::Path.spec_dir}/support/hax.rb" - ENV["BUNDLE_SPEC_RUN"] = "true" + Spec::Rubygems.test_setup + ENV["BUNDLER_SPEC_RUN"] = "true" + ENV["BUNDLER_NO_OLD_RUBYGEMS_WARNING"] = "true" ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil + ENV["RUBYGEMS_GEMDEPS"] = nil + ENV["XDG_CONFIG_HOME"] = nil ENV["GEMRC"] = nil # Don't wrap output in tests ENV["THOR_COLUMNS"] = "10000" - original_env = ENV.to_hash - - if ENV["RUBY"] - FileUtils.cp_r Spec::Path.bindir, File.join(Spec::Path.root, "lib", "exe") - end + extend(Spec::Helpers) + system_gems :bundler, :path => pristine_system_gem_path end config.before :all do + check_test_gems! + build_repo1 + + reset_paths! end config.around :each do |example| - ENV.replace(original_env) - reset! - system_gems [] - in_app_root - @command_executions = [] - - Bundler.ui.silence { example.run } - - all_output = @command_executions.map(&:to_s_verbose).join("\n\n") - if example.exception && !all_output.empty? - warn all_output unless config.formatters.grep(RSpec::Core::Formatters::DocumentationFormatter).empty? - message = example.exception.message + "\n\nCommands:\n#{all_output}" - (class << example.exception; self; end).send(:define_method, :message) do - message + begin + FileUtils.cp_r pristine_system_gem_path, system_gem_path + + with_gem_path_as(system_gem_path) do + Bundler.ui.silence { example.run } + + all_output = all_commands_output + if example.exception && !all_output.empty? + message = all_output + "\n" + example.exception.message + (class << example.exception; self; end).send(:define_method, :message) do + message + end + end end + ensure + reset! end - - Dir.chdir(original_wd) end config.after :suite do - if ENV["RUBY"] - FileUtils.rm_rf File.join(Spec::Path.root, "lib", "exe") - end + FileUtils.rm_r Spec::Path.pristine_system_gem_path end end diff --git a/ruby/spec/bundler/support/api_request_limit_hax.rb b/ruby/spec/bundler/support/api_request_limit_hax.rb new file mode 100644 index 000000000..37ff0203b --- /dev/null +++ b/ruby/spec/bundler/support/api_request_limit_hax.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"] + require_relative "path" + require "bundler/source" + require "bundler/source/rubygems" + + module Bundler + class Source + class Rubygems < Source + remove_const :API_REQUEST_LIMIT + API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i + end + end + end +end diff --git a/ruby/spec/bundler/support/artifice/compact_index.rb b/ruby/spec/bundler/support/artifice/compact_index.rb index 72abf2622..fb068fa9b 100644 --- a/ruby/spec/bundler/support/artifice/compact_index.rb +++ b/ruby/spec/bundler/support/artifice/compact_index.rb @@ -2,11 +2,13 @@ require_relative "endpoint" -$LOAD_PATH.unshift Dir[base_system_gems.join("gems/compact_index*/lib")].first.to_s +$LOAD_PATH.unshift Dir[Spec::Path.base_system_gem_path.join("gems/compact_index*/lib")].first.to_s require "compact_index" class CompactIndexAPI < Endpoint helpers do + include Spec::Path + def load_spec(name, version, platform, gem_repo) full_name = "#{name}-#{version}" full_name += "-#{platform}" if platform != "ruby" @@ -60,7 +62,7 @@ def slice_body(body, range) body.byteslice(range) end - def gems(gem_repo = GEM_REPO) + def gems(gem_repo = default_gem_repo) @gems ||= {} @gems[gem_repo] ||= begin specs = Bundler::Deprecate.skip_during do @@ -78,12 +80,12 @@ def gems(gem_repo = GEM_REPO) CompactIndex::Dependency.new(d.name, reqs) end checksum = begin - Digest(:SHA256).file("#{GEM_REPO}/gems/#{spec.original_name}.gem").base64digest + Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").base64digest rescue StandardError nil end CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil, - deps, spec.required_ruby_version, spec.required_rubygems_version) + deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s) end CompactIndex::Gem.new(name, gem_versions) end @@ -100,7 +102,7 @@ def gems(gem_repo = GEM_REPO) get "/versions" do etag_response do file = tmp("versions.list") - file.delete if file.file? + FileUtils.rm_f(file) file = CompactIndex::VersionsFile.new(file.to_s) file.create(gems) file.contents diff --git a/ruby/spec/bundler/support/artifice/compact_index_concurrent_download.rb b/ruby/spec/bundler/support/artifice/compact_index_concurrent_download.rb index 7f989a3f3..14c31f35a 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_concurrent_download.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_concurrent_download.rb @@ -10,7 +10,7 @@ class CompactIndexConcurrentDownload < CompactIndexAPI "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions") # Verify the original (empty) content hasn't been deleted, e.g. on a retry - File.read(versions) == "" || raise("Original file should be present and empty") + File.binread(versions) == "" || raise("Original file should be present and empty") # Verify this is only requested once for a partial download env["HTTP_RANGE"] || raise("Missing Range header for expected partial download") @@ -21,7 +21,7 @@ class CompactIndexConcurrentDownload < CompactIndexAPI etag_response do file = tmp("versions.list") - file.delete if file.file? + FileUtils.rm_f(file) file = CompactIndex::VersionsFile.new(file.to_s) file.create(gems) file.contents diff --git a/ruby/spec/bundler/support/artifice/compact_index_creds_diff_host.rb b/ruby/spec/bundler/support/artifice/compact_index_creds_diff_host.rb index 6c3442e14..cfe22c7f5 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_creds_diff_host.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_creds_diff_host.rb @@ -31,7 +31,7 @@ def protected! get "/no/creds/:id" do if request.host.include?("diffhost") && !auth.provided? - File.read("#{gem_repo1}/gems/#{params[:id]}") + File.binread("#{gem_repo1}/gems/#{params[:id]}") end end end diff --git a/ruby/spec/bundler/support/artifice/compact_index_extra.rb b/ruby/spec/bundler/support/artifice/compact_index_extra.rb index 3a09afd06..cec368276 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_extra.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_extra.rb @@ -14,11 +14,11 @@ class CompactIndexExtra < CompactIndexAPI end get "/extra/specs.4.8.gz" do - File.read("#{gem_repo2}/specs.4.8.gz") + File.binread("#{gem_repo2}/specs.4.8.gz") end get "/extra/prerelease_specs.4.8.gz" do - File.read("#{gem_repo2}/prerelease_specs.4.8.gz") + File.binread("#{gem_repo2}/prerelease_specs.4.8.gz") end get "/extra/quick/Marshal.4.8/:id" do @@ -26,11 +26,11 @@ class CompactIndexExtra < CompactIndexAPI end get "/extra/fetch/actual/gem/:id" do - File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") + File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") end get "/extra/gems/:id" do - File.read("#{gem_repo2}/gems/#{params[:id]}") + File.binread("#{gem_repo2}/gems/#{params[:id]}") end end diff --git a/ruby/spec/bundler/support/artifice/compact_index_extra_api.rb b/ruby/spec/bundler/support/artifice/compact_index_extra_api.rb index 3c716763c..5cc13421a 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_extra_api.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_extra_api.rb @@ -14,7 +14,7 @@ class CompactIndexExtraApi < CompactIndexAPI get "/extra/versions" do etag_response do file = tmp("versions.list") - file.delete if file.file? + FileUtils.rm_f(file) file = CompactIndex::VersionsFile.new(file.to_s) file.create(gems(gem_repo4)) file.contents @@ -29,11 +29,11 @@ class CompactIndexExtraApi < CompactIndexAPI end get "/extra/specs.4.8.gz" do - File.read("#{gem_repo4}/specs.4.8.gz") + File.binread("#{gem_repo4}/specs.4.8.gz") end get "/extra/prerelease_specs.4.8.gz" do - File.read("#{gem_repo4}/prerelease_specs.4.8.gz") + File.binread("#{gem_repo4}/prerelease_specs.4.8.gz") end get "/extra/quick/Marshal.4.8/:id" do @@ -41,11 +41,11 @@ class CompactIndexExtraApi < CompactIndexAPI end get "/extra/fetch/actual/gem/:id" do - File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") + File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") end get "/extra/gems/:id" do - File.read("#{gem_repo4}/gems/#{params[:id]}") + File.binread("#{gem_repo4}/gems/#{params[:id]}") end end diff --git a/ruby/spec/bundler/support/artifice/compact_index_partial_update.rb b/ruby/spec/bundler/support/artifice/compact_index_partial_update.rb index 6e7c05d42..cb1c7b948 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_partial_update.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_partial_update.rb @@ -18,19 +18,19 @@ def not_modified?(_checksum) ) # Verify a cached copy of the versions file exists - unless File.read(cached_versions_path).start_with?("created_at: ") + unless File.binread(cached_versions_path).start_with?("created_at: ") raise("Cached versions file should be present and have content") end # Verify that a partial request is made, starting from the index of the # final byte of the cached file. - unless env["HTTP_RANGE"] == "bytes=#{File.read(cached_versions_path).bytesize - 1}-" + unless env["HTTP_RANGE"] == "bytes=#{File.binread(cached_versions_path).bytesize - 1}-" raise("Range header should be present, and start from the index of the final byte of the cache.") end etag_response do # Return the exact contents of the cache. - File.read(cached_versions_path) + File.binread(cached_versions_path) end end end diff --git a/ruby/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb b/ruby/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb new file mode 100644 index 000000000..acf76dfbf --- /dev/null +++ b/ruby/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require_relative "compact_index" + +Artifice.deactivate + +class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI + def partial_update_no_etag + response_body = yield + headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60" + content_type "text/plain" + requested_range_for(response_body) + end + + get "/versions" do + partial_update_no_etag do + file = tmp("versions.list") + FileUtils.rm_f(file) + file = CompactIndex::VersionsFile.new(file.to_s) + file.create(gems) + lines = file.contents([], :calculate_info_checksums => true).split("\n") + name, versions, checksum = lines.last.split(" ") + + # shuffle versions so new versions are not appended to the end + [*lines[0..-2], [name, versions.split(",").reverse.join(","), checksum].join(" ")].join("\n") + end + end + + get "/info/:name" do + partial_update_no_etag do + gem = gems.find {|g| g.name == params[:name] } + lines = CompactIndex.info(gem ? gem.versions : []).split("\n") + + # shuffle versions so new versions are not appended to the end + [lines.first, lines.last, *lines[1..-2]].join("\n") + end + end +end + +Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental) diff --git a/ruby/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb b/ruby/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb index 788f9d6f9..bb616125b 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb @@ -11,7 +11,7 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI else etag_response do file = tmp("versions.list") - file.delete if file.file? + FileUtils.rm_f(file) file = CompactIndex::VersionsFile.new(file.to_s) file.create(gems) file.contents diff --git a/ruby/spec/bundler/support/artifice/compact_index_rate_limited.rb b/ruby/spec/bundler/support/artifice/compact_index_rate_limited.rb index ba1747604..570105e2a 100644 --- a/ruby/spec/bundler/support/artifice/compact_index_rate_limited.rb +++ b/ruby/spec/bundler/support/artifice/compact_index_rate_limited.rb @@ -7,7 +7,7 @@ class CompactIndexRateLimited < CompactIndexAPI class RequestCounter def self.queue - @queue ||= Queue.new + @queue ||= Thread::Queue.new end def self.size diff --git a/ruby/spec/bundler/support/artifice/endpoint.rb b/ruby/spec/bundler/support/artifice/endpoint.rb index 7bca681e7..c00113b28 100644 --- a/ruby/spec/bundler/support/artifice/endpoint.rb +++ b/ruby/spec/bundler/support/artifice/endpoint.rb @@ -1,16 +1,14 @@ # frozen_string_literal: true require_relative "../path" -require Spec::Path.lib_dir.join("bundler/deprecate") -include Spec::Path -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) require "artifice" require "sinatra/base" ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant -ALL_REQUESTS_MUTEX = Mutex.new +ALL_REQUESTS_MUTEX = Thread::Mutex.new at_exit do if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"] @@ -28,7 +26,6 @@ def self.all_requests @all_requests ||= [] end - GEM_REPO = Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1) set :raise_errors, true set :show_exceptions, false @@ -41,28 +38,46 @@ def call!(*) end helpers do - def dependencies_for(gem_names, gem_repo = GEM_REPO) + include Spec::Path + + def default_gem_repo + if ENV["BUNDLER_SPEC_GEM_REPO"] + Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"]) + else + case request.host + when "gem.repo1" + Spec::Path.gem_repo1 + when "gem.repo2" + Spec::Path.gem_repo2 + when "gem.repo3" + Spec::Path.gem_repo3 + when "gem.repo4" + Spec::Path.gem_repo4 + else + Spec::Path.gem_repo1 + end + end + end + + def dependencies_for(gem_names, gem_repo = default_gem_repo) return [] if gem_names.nil? || gem_names.empty? - require "#{Spec::Path.lib_dir}/bundler" - Bundler::Deprecate.skip_during do - all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename| - Marshal.load(File.open(gem_repo.join(filename)).read) - end.inject(:+) - - all_specs.map do |name, version, platform| - spec = load_spec(name, version, platform, gem_repo) - next unless gem_names.include?(spec.name) - { - :name => spec.name, - :number => spec.version.version, - :platform => spec.platform.to_s, - :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep| - [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")] - end, - } - end.compact - end + all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename| + Marshal.load(File.open(gem_repo.join(filename)).read) + end.inject(:+) + + all_specs.map do |name, version, platform| + spec = load_spec(name, version, platform, gem_repo) + next unless gem_names.include?(spec.name) + { + :name => spec.name, + :number => spec.version.version, + :platform => spec.platform.to_s, + :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep| + [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")] + end, + } + end.compact end def load_spec(name, version, platform, gem_repo) @@ -77,11 +92,11 @@ def load_spec(name, version, platform, gem_repo) end get "/fetch/actual/gem/:id" do - File.read("#{GEM_REPO}/quick/Marshal.4.8/#{params[:id]}") + File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}") end get "/gems/:id" do - File.read("#{GEM_REPO}/gems/#{params[:id]}") + File.binread("#{default_gem_repo}/gems/#{params[:id]}") end get "/api/v1/dependencies" do @@ -89,11 +104,11 @@ def load_spec(name, version, platform, gem_repo) end get "/specs.4.8.gz" do - File.read("#{GEM_REPO}/specs.4.8.gz") + File.binread("#{default_gem_repo}/specs.4.8.gz") end get "/prerelease_specs.4.8.gz" do - File.read("#{GEM_REPO}/prerelease_specs.4.8.gz") + File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz") end end diff --git a/ruby/spec/bundler/support/artifice/endpoint_500.rb b/ruby/spec/bundler/support/artifice/endpoint_500.rb index f98e7e3bc..a0d850a44 100644 --- a/ruby/spec/bundler/support/artifice/endpoint_500.rb +++ b/ruby/spec/bundler/support/artifice/endpoint_500.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true require_relative "../path" -include Spec::Path -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) require "artifice" require "sinatra/base" diff --git a/ruby/spec/bundler/support/artifice/endpoint_api_missing.rb b/ruby/spec/bundler/support/artifice/endpoint_api_missing.rb deleted file mode 100644 index 755c42e83..000000000 --- a/ruby/spec/bundler/support/artifice/endpoint_api_missing.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -require_relative "endpoint" - -Artifice.deactivate - -class EndpointApiMissing < Endpoint - get "/fetch/actual/gem/:id" do - warn params[:id] - if params[:id] == "rack-1.0.gemspec.rz" - halt 404 - else - File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") - end - end -end - -Artifice.activate_with(EndpointApiMissing) diff --git a/ruby/spec/bundler/support/artifice/endpoint_creds_diff_host.rb b/ruby/spec/bundler/support/artifice/endpoint_creds_diff_host.rb index f20ef74ac..8b8972ced 100644 --- a/ruby/spec/bundler/support/artifice/endpoint_creds_diff_host.rb +++ b/ruby/spec/bundler/support/artifice/endpoint_creds_diff_host.rb @@ -31,7 +31,7 @@ def protected! get "/no/creds/:id" do if request.host.include?("diffhost") && !auth.provided? - File.read("#{gem_repo1}/gems/#{params[:id]}") + File.binread("#{gem_repo1}/gems/#{params[:id]}") end end end diff --git a/ruby/spec/bundler/support/artifice/endpoint_extra.rb b/ruby/spec/bundler/support/artifice/endpoint_extra.rb index 31f682216..942c4352b 100644 --- a/ruby/spec/bundler/support/artifice/endpoint_extra.rb +++ b/ruby/spec/bundler/support/artifice/endpoint_extra.rb @@ -10,11 +10,11 @@ class EndpointExtra < Endpoint end get "/extra/specs.4.8.gz" do - File.read("#{gem_repo2}/specs.4.8.gz") + File.binread("#{gem_repo2}/specs.4.8.gz") end get "/extra/prerelease_specs.4.8.gz" do - File.read("#{gem_repo2}/prerelease_specs.4.8.gz") + File.binread("#{gem_repo2}/prerelease_specs.4.8.gz") end get "/extra/quick/Marshal.4.8/:id" do @@ -22,11 +22,11 @@ class EndpointExtra < Endpoint end get "/extra/fetch/actual/gem/:id" do - File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") + File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}") end get "/extra/gems/:id" do - File.read("#{gem_repo2}/gems/#{params[:id]}") + File.binread("#{gem_repo2}/gems/#{params[:id]}") end end diff --git a/ruby/spec/bundler/support/artifice/endpoint_extra_api.rb b/ruby/spec/bundler/support/artifice/endpoint_extra_api.rb index 213b8e589..1cfef7a7f 100644 --- a/ruby/spec/bundler/support/artifice/endpoint_extra_api.rb +++ b/ruby/spec/bundler/support/artifice/endpoint_extra_api.rb @@ -11,11 +11,11 @@ class EndpointExtraApi < Endpoint end get "/extra/specs.4.8.gz" do - File.read("#{gem_repo4}/specs.4.8.gz") + File.binread("#{gem_repo4}/specs.4.8.gz") end get "/extra/prerelease_specs.4.8.gz" do - File.read("#{gem_repo4}/prerelease_specs.4.8.gz") + File.binread("#{gem_repo4}/prerelease_specs.4.8.gz") end get "/extra/quick/Marshal.4.8/:id" do @@ -23,11 +23,11 @@ class EndpointExtraApi < Endpoint end get "/extra/fetch/actual/gem/:id" do - File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") + File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}") end get "/extra/gems/:id" do - File.read("#{gem_repo4}/gems/#{params[:id]}") + File.binread("#{gem_repo4}/gems/#{params[:id]}") end end diff --git a/ruby/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb b/ruby/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb similarity index 100% rename from ruby/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb rename to ruby/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb diff --git a/ruby/spec/bundler/support/artifice/endpoint_mirror_source.rb b/ruby/spec/bundler/support/artifice/endpoint_mirror_source.rb index 318866e42..788a9027f 100644 --- a/ruby/spec/bundler/support/artifice/endpoint_mirror_source.rb +++ b/ruby/spec/bundler/support/artifice/endpoint_mirror_source.rb @@ -5,7 +5,7 @@ class EndpointMirrorSource < Endpoint get "/gems/:id" do if request.env["HTTP_X_GEMFILE_SOURCE"] == "https://server.example.org/" - File.read("#{gem_repo1}/gems/#{params[:id]}") + File.binread("#{gem_repo1}/gems/#{params[:id]}") else halt 500 end diff --git a/ruby/spec/bundler/support/artifice/fail.rb b/ruby/spec/bundler/support/artifice/fail.rb index 1059c6df4..f69f2eccc 100644 --- a/ruby/spec/bundler/support/artifice/fail.rb +++ b/ruby/spec/bundler/support/artifice/fail.rb @@ -1,11 +1,6 @@ # frozen_string_literal: true require "net/http" -begin - require "net/https" -rescue LoadError - nil # net/https or openssl -end # We can't use artifice here because it uses rack diff --git a/ruby/spec/bundler/support/artifice/vcr.rb b/ruby/spec/bundler/support/artifice/vcr.rb index a46f8e939..ceb133346 100644 --- a/ruby/spec/bundler/support/artifice/vcr.rb +++ b/ruby/spec/bundler/support/artifice/vcr.rb @@ -31,7 +31,6 @@ def handle_request def recorded_response? return true if ENV["BUNDLER_SPEC_PRE_RECORDED"] - return false if ENV["BUNDLER_SPEC_FORCE_RECORD"] request_pair_paths.all? {|f| File.exist?(f) } end @@ -40,7 +39,7 @@ def recorded_response response_io = ::Net::BufferedIO.new(response_file) ::Net::HTTPResponse.read_new(response_io).tap do |response| response.decode_content = request.decode_content if request.respond_to?(:decode_content) - response.uri = request.uri if request.respond_to?(:uri) + response.uri = request.uri response.reading_body(response_io, request.response_body_permitted?) do response_block.call(response) if response_block @@ -57,6 +56,7 @@ def record_response response = http.request_without_vcr(request, body, &response_block) @recording = false unless @recording + require "fileutils" FileUtils.mkdir_p(File.dirname(request_path)) binwrite(request_path, request_to_string(request)) binwrite(response_path, response_to_string(response)) @@ -69,7 +69,7 @@ def key end def file_name_for_key(key) - key.join("/").gsub(/[\:*?"<>|]/, "-") + File.join(*key).gsub(/[\:*?"<>|]/, "-") end def request_pair_paths @@ -79,7 +79,7 @@ def request_pair_paths end def read_stored_request(path) - contents = File.read(path) + contents = File.binread(path) headers = {} method = nil path = nil @@ -133,6 +133,19 @@ def binwrite(path, contents) end end + def start_with_vcr + if ENV["BUNDLER_SPEC_PRE_RECORDED"] + raise IOError, "HTTP session already opened" if @started + @socket = nil + @started = true + else + start_without_vcr + end + end + + alias_method :start_without_vcr, :start + alias_method :start, :start_with_vcr + def request_with_vcr(request, *args, &block) handler = request.instance_eval do remove_instance_variable(:@__vcr_request_handler) if defined?(@__vcr_request_handler) diff --git a/ruby/spec/bundler/support/artifice/windows.rb b/ruby/spec/bundler/support/artifice/windows.rb index 21170c81d..674470688 100644 --- a/ruby/spec/bundler/support/artifice/windows.rb +++ b/ruby/spec/bundler/support/artifice/windows.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true require_relative "../path" -include Spec::Path -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) require "artifice" require "sinatra/base" @@ -15,7 +14,7 @@ class Windows < Sinatra::Base set :show_exceptions, false helpers do - def gem_repo + def default_gem_repo Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1) end end @@ -27,7 +26,7 @@ def gem_repo files.each do |file| get "/#{file}" do - File.binread gem_repo.join(file) + File.binread default_gem_repo.join(file) end end diff --git a/ruby/spec/bundler/support/build_metadata.rb b/ruby/spec/bundler/support/build_metadata.rb new file mode 100644 index 000000000..98d8ac23c --- /dev/null +++ b/ruby/spec/bundler/support/build_metadata.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require_relative "path" +require_relative "helpers" + +module Spec + module BuildMetadata + include Spec::Path + include Spec::Helpers + + def write_build_metadata(dir: source_root) + build_metadata = { + :git_commit_sha => git_commit_sha, + :built_at => loaded_gemspec.date.utc.strftime("%Y-%m-%d"), + :release => true, + } + + replace_build_metadata(build_metadata, dir: dir) # rubocop:disable Style/HashSyntax + end + + def reset_build_metadata(dir: source_root) + build_metadata = { + :release => false, + } + + replace_build_metadata(build_metadata, dir: dir) # rubocop:disable Style/HashSyntax + end + + private + + def replace_build_metadata(build_metadata, dir:) + build_metadata_file = File.expand_path("lib/bundler/build_metadata.rb", dir) + + ivars = build_metadata.sort.map do |k, v| + " @#{k} = #{loaded_gemspec.send(:ruby_code, v)}" + end.join("\n") + + contents = File.read(build_metadata_file) + contents.sub!(/^(\s+# begin ivars).+(^\s+# end ivars)/m, "\\1\n#{ivars}\n\\2") + File.open(build_metadata_file, "w") {|f| f << contents } + end + + def git_commit_sha + ruby_core_tarball? ? "unknown" : sys_exec("git rev-parse --short HEAD", :dir => source_root).strip + end + + extend self + end +end diff --git a/ruby/spec/bundler/support/builders.rb b/ruby/spec/bundler/support/builders.rb index b3f5f9b87..aca31638a 100644 --- a/ruby/spec/bundler/support/builders.rb +++ b/ruby/spec/bundler/support/builders.rb @@ -17,8 +17,29 @@ def pl(platform) Gem::Platform.new(platform) end + # Returns a number smaller than the size of the index. Useful for specs that + # need the API request limit to be reached for some reason. + def low_api_request_limit_for(gem_repo) + all_gems = Dir[gem_repo.join("gems/*.gem")] + + all_gem_names = all_gems.map do |file| + File.basename(file, ".gem").match(/\A(?[^-]+)-.*\z/)[:gem_name] + end.uniq + + (all_gem_names - ["bundler"]).size + end + def build_repo1 + rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first + build_repo gem_repo1 do + FileUtils.cp rake_path, "#{gem_repo1}/gems/" + + build_gem "coffee-script-source" + build_gem "git" + build_gem "puma" + build_gem "minitest" + build_gem "rack", %w[0.9.1 1.0.0] do |s| s.executables = "rackup" s.post_install_message = "Rack's post install message" @@ -40,7 +61,7 @@ def build_repo1 build_gem "rails", "2.3.2" do |s| s.executables = "rails" - s.add_dependency "rake", "12.3.2" + s.add_dependency "rake", "13.0.1" s.add_dependency "actionpack", "2.3.2" s.add_dependency "activerecord", "2.3.2" s.add_dependency "actionmailer", "2.3.2" @@ -64,14 +85,6 @@ def build_repo1 s.add_dependency "activesupport", ">= 2.0.0" end - build_gem "rails_fail" do |s| - s.add_dependency "activesupport", "= 1.2.3" - end - - build_gem "missing_dep" do |s| - s.add_dependency "not_here" - end - build_gem "rspec", "1.2.7", :no_default => true do |s| s.write "lib/spec.rb", "SPEC = '1.2.7'" end @@ -146,49 +159,6 @@ def build_repo1 build_gem "duradura", "7.0" - build_gem "multiple_versioned_deps" do |s| - s.add_dependency "weakling", ">= 0.0.1", "< 0.1" - end - - build_gem "not_released", "1.0.pre" - - build_gem "has_prerelease", "1.0" - build_gem "has_prerelease", "1.1.pre" - - build_gem "with_development_dependency" do |s| - s.add_development_dependency "activesupport", "= 2.3.5" - end - - build_gem "with_license" do |s| - s.license = "MIT" - end - - build_gem "with_implicit_rake_dep" do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - path = File.expand_path("../lib", __FILE__) - FileUtils.mkdir_p(path) - File.open("\#{path}/implicit_rake_dep.rb", "w") do |f| - f.puts "IMPLICIT_RAKE_DEP = 'YES'" - end - end - RUBY - end - - build_gem "another_implicit_rake_dep" do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - path = File.expand_path("../lib", __FILE__) - FileUtils.mkdir_p(path) - File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f| - f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'" - end - end - RUBY - end - build_gem "very_simple_binary", &:add_c_extension build_gem "simple_binary", &:add_c_extension @@ -203,10 +173,6 @@ def build_repo1 s.write "lib/rubygems_plugin.rb", "require 'bundler/omg' ; puts 'FAIL'" end - build_gem "bundler_dep" do |s| - s.add_dependency "bundler" - end - # The yard gem iterates over Gem.source_index looking for plugins build_gem "yard" do |s| s.write "lib/yard.rb", <<-Y @@ -216,92 +182,12 @@ def build_repo1 Y end - # The rcov gem is platform mswin32, but has no arch - build_gem "rcov" do |s| - s.platform = Gem::Platform.new([nil, "mswin32", nil]) - s.write "lib/rcov.rb", "RCOV = '1.0.0'" - end - build_gem "net-ssh" build_gem "net-sftp", "1.1.1" do |s| s.add_dependency "net-ssh", ">= 1.0.0", "< 1.99.0" end - # Test complicated gem dependencies for install - build_gem "net_a" do |s| - s.add_dependency "net_b" - s.add_dependency "net_build_extensions" - end - - build_gem "net_b" - - build_gem "net_build_extensions" do |s| - s.add_dependency "rake" - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - path = File.expand_path("../lib", __FILE__) - FileUtils.mkdir_p(path) - File.open("\#{path}/net_build_extensions.rb", "w") do |f| - f.puts "NET_BUILD_EXTENSIONS = 'YES'" - end - end - RUBY - end - - build_gem "net_c" do |s| - s.add_dependency "net_a" - s.add_dependency "net_d" - end - - build_gem "net_d" - - build_gem "net_e" do |s| - s.add_dependency "net_d" - end - - # Capistrano did this (at least until version 2.5.10) - # RubyGems 2.2 doesn't allow the specifying of a dependency twice - # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f - build_gem "double_deps", "1.0", :skip_validation => true do |s| - s.add_dependency "net-ssh", ">= 1.0.0" - s.add_dependency "net-ssh" - end - build_gem "foo" - - # A minimal fake pry console - build_gem "pry" do |s| - s.write "lib/pry.rb", <<-RUBY - class Pry - class << self - def toplevel_binding - unless defined?(@toplevel_binding) && @toplevel_binding - TOPLEVEL_BINDING.eval %{ - def self.__pry__; binding; end - Pry.instance_variable_set(:@toplevel_binding, __pry__) - class << self; undef __pry__; end - } - end - @toplevel_binding.eval('private') - @toplevel_binding - end - - def __pry__ - while line = gets - begin - puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1') - rescue Exception => e - puts "\#{e.class}: \#{e.message}" - puts e.backtrace.first - end - end - end - alias start __pry__ - end - end - RUBY - end end end @@ -311,13 +197,6 @@ def build_repo2(&blk) update_repo2(&blk) if block_given? end - def build_repo3 - build_repo gem_repo3 do - build_gem "rack" - end - FileUtils.rm_rf Dir[gem_repo3("prerelease*")] - end - # A repo that has no pre-installed gems included. (The caller completely # determines the contents with the block.) def build_repo4(&blk) @@ -331,9 +210,6 @@ def update_repo4(&blk) def update_repo2 update_repo gem_repo2 do - build_gem "rack", "1.2" do |s| - s.executables = "rackup" - end yield if block_given? end end @@ -355,22 +231,24 @@ def build_security_repo def build_repo(path, &blk) return if File.directory?(path) + + FileUtils.mkdir_p("#{path}/gems") + + update_repo(path, &blk) + end + + def check_test_gems! rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first if rake_path.nil? - Spec::Path.base_system_gems.rmtree - Spec::Rubygems.setup + FileUtils.rm_rf(Path.base_system_gems) + Spec::Rubygems.install_test_deps rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first end - if rake_path - FileUtils.mkdir_p("#{path}/gems") - FileUtils.cp rake_path, "#{path}/gems/" - else + if rake_path.nil? abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again." end - - update_repo(path, &blk) end def update_repo(path) @@ -381,8 +259,8 @@ def update_repo(path) @_build_path = "#{path}/gems" @_build_repo = File.basename(path) yield - with_gem_path_as Path.base_system_gems do - Dir.chdir(path) { gem_command! :generate_index } + with_gem_path_as Path.base_system_gem_path do + gem_command :generate_index, :dir => path end ensure @_build_path = nil @@ -424,20 +302,20 @@ def build_git(name, *args, &block) opts = args.last.is_a?(Hash) ? args.last : {} builder = opts[:bare] ? GitBareBuilder : GitBuilder spec = build_with(builder, name, args, &block) - GitReader.new(opts[:path] || lib_path(spec.full_name)) + GitReader.new(self, opts[:path] || lib_path(spec.full_name)) end def update_git(name, *args, &block) opts = args.last.is_a?(Hash) ? args.last : {} spec = build_with(GitUpdater, name, args, &block) - GitReader.new(opts[:path] || lib_path(spec.full_name)) + GitReader.new(self, opts[:path] || lib_path(spec.full_name)) end def build_plugin(name, *args, &blk) build_with(PluginBuilder, name, args, &blk) end - private + private def build_with(builder, name, args, &blk) @_build_path ||= nil @@ -451,7 +329,6 @@ def build_with(builder, name, args, &blk) Array(versions).each do |version| spec = builder.new(self, name, version) - spec.authors = ["no one"] if !spec.authors || spec.authors.empty? yield spec if block_given? spec._build(options) end @@ -599,15 +476,6 @@ def @spec.mark_version; end def @spec.validate(*); end end - case options[:gemspec] - when false - # do nothing - when :yaml - @files["#{name}.gemspec"] = @spec.to_yaml - else - @files["#{name}.gemspec"] = @spec.to_ruby - end - unless options[:no_default] gem_source = options[:source] || "path@#{path}" @files = _default_files. @@ -616,13 +484,25 @@ def @spec.validate(*); end end @spec.authors = ["no one"] + @spec.files = @files.keys + + case options[:gemspec] + when false + # do nothing + when :yaml + @spec.files << "#{name}.gemspec" + @files["#{name}.gemspec"] = @spec.to_yaml + else + @spec.files << "#{name}.gemspec" + @files["#{name}.gemspec"] = @spec.to_ruby + end @files.each do |file, source| file = Pathname.new(path).join(file) FileUtils.mkdir_p(file.dirname) File.open(file, "w") {|f| f.puts source } + File.chmod("+x", file) if @spec.executables.map {|exe| "#{@spec.bindir}/#{exe}" }.include?(file) end - @spec.files = @files.keys path end @@ -645,17 +525,17 @@ def platform_string class GitBuilder < LibBuilder def _build(options) + default_branch = options[:default_branch] || "master" path = options[:path] || _default_path source = options[:source] || "git@#{path}" super(options.merge(:path => path, :source => source)) - Dir.chdir(path) do - `git init` - `git add *` - `git config user.email "lol@wut.com"` - `git config user.name "lolwut"` - `git config commit.gpgsign false` - `git commit -m "OMG INITIAL COMMIT"` - end + @context.git("config --global init.defaultBranch #{default_branch}", path) + @context.git("init", path) + @context.git("add *", path) + @context.git("config user.email lol@wut.com", path) + @context.git("config user.name lolwut", path) + @context.git("config commit.gpgsign false", path) + @context.git("commit -m OMG_INITIAL_COMMIT", path) end end @@ -663,91 +543,71 @@ class GitBareBuilder < LibBuilder def _build(options) path = options[:path] || _default_path super(options.merge(:path => path)) - Dir.chdir(path) do - `git init --bare` - end + @context.git("init --bare", path) end end class GitUpdater < LibBuilder - def silently(str) - `#{str} 2>#{Bundler::NULL}` - end - def _build(options) libpath = options[:path] || _default_path update_gemspec = options[:gemspec] || false source = options[:source] || "git@#{libpath}" - Dir.chdir(libpath) do - silently "git checkout master" - - if branch = options[:branch] - raise "You can't specify `master` as the branch" if branch == "master" - escaped_branch = Shellwords.shellescape(branch) - - if `git branch | grep #{escaped_branch}`.empty? - silently("git branch #{escaped_branch}") - end - - silently("git checkout #{escaped_branch}") - elsif tag = options[:tag] - `git tag #{Shellwords.shellescape(tag)}` - elsif options[:remote] - silently("git remote add origin #{options[:remote]}") - elsif options[:push] - silently("git push origin #{options[:push]}") - end + if branch = options[:branch] + @context.git("checkout -b #{Shellwords.shellescape(branch)}", libpath) + elsif tag = options[:tag] + @context.git("tag #{Shellwords.shellescape(tag)}", libpath) + elsif options[:remote] + @context.git("remote add origin #{options[:remote]}", libpath) + elsif options[:push] + @context.git("push origin #{options[:push]}", libpath) + end - current_ref = `git rev-parse HEAD`.strip - _default_files.keys.each do |path| - _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'" - end - super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source)) - `git add *` - `git commit -m "BUMP"` + current_ref = @context.git("rev-parse HEAD", libpath).strip + _default_files.keys.each do |path| + _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'" end + super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source)) + @context.git("commit -am BUMP", libpath) end end class GitReader - attr_reader :path + attr_reader :context, :path - def initialize(path) + def initialize(context, path) + @context = context @path = path end def ref_for(ref, len = nil) - ref = git "rev-parse #{ref}" + ref = context.git "rev-parse #{ref}", path ref = ref[0..len] if len ref end - - private - - def git(cmd) - Bundler::SharedHelpers.with_clean_git_env do - Dir.chdir(@path) { `git #{cmd}`.strip } - end - end end class GemBuilder < LibBuilder def _build(opts) lib_path = super(opts.merge(:path => @context.tmp(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default])) destination = opts[:path] || _default_path - Dir.chdir(lib_path) do - FileUtils.mkdir_p(destination) - - @spec.authors = ["that guy"] if !@spec.authors || @spec.authors.empty? + FileUtils.mkdir_p(lib_path.join(destination)) - Bundler.rubygems.build(@spec, opts[:skip_validation]) + if opts[:gemspec] == :yaml || opts[:gemspec] == false + Dir.chdir(lib_path) do + Bundler.rubygems.build(@spec, opts[:skip_validation]) + end + elsif opts[:skip_validation] + @context.gem_command "build --force #{@spec.name}", :dir => lib_path + else + @context.gem_command "build #{@spec.name}", :dir => lib_path end + gem_path = File.expand_path("#{@spec.full_name}.gem", lib_path) if opts[:to_system] - @context.system_gems gem_path, :keep_path => true + @context.system_gems gem_path, :default => opts[:default] elsif opts[:to_bundle] - @context.system_gems gem_path, :path => :bundle_path, :keep_path => true + @context.system_gems gem_path, :path => @context.default_bundle_path else FileUtils.mv(gem_path, destination) end diff --git a/ruby/spec/bundler/support/bundle.rb b/ruby/spec/bundler/support/bundle.rb new file mode 100644 index 000000000..bb21526d3 --- /dev/null +++ b/ruby/spec/bundler/support/bundle.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "rubygems" +require_relative "path" +bundler_gemspec = Spec::Path.loaded_gemspec +bundler_gemspec.instance_variable_set(:@full_gem_path, Spec::Path.source_root) +bundler_gemspec.activate if bundler_gemspec.respond_to?(:activate) +load File.expand_path("bundle", Spec::Path.bindir) diff --git a/ruby/spec/bundler/support/command_execution.rb b/ruby/spec/bundler/support/command_execution.rb index b3c289979..68e5c56c7 100644 --- a/ruby/spec/bundler/support/command_execution.rb +++ b/ruby/spec/bundler/support/command_execution.rb @@ -3,18 +3,7 @@ module Spec CommandExecution = Struct.new(:command, :working_directory, :exitstatus, :stdout, :stderr) do def to_s - c = Shellwords.shellsplit(command.strip).map {|s| s.include?("\n") ? " \\\n <= 100 - acc + " \\\n " + elem - else - concat - end - end - "$ #{c.strip}" + "$ #{command}" end alias_method :inspect, :to_s diff --git a/ruby/spec/bundler/support/filters.rb b/ruby/spec/bundler/support/filters.rb index 4ce6648cd..96f2e2a27 100644 --- a/ruby/spec/bundler/support/filters.rb +++ b/ruby/spec/bundler/support/filters.rb @@ -21,25 +21,21 @@ def inspect end RSpec.configure do |config| - if ENV["BUNDLER_SUDO_TESTS"] && Spec::Sudo.present? - config.filter_run :sudo => true - else - config.filter_run_excluding :sudo => true - end - - if ENV["BUNDLER_REALWORLD_TESTS"] - config.filter_run :realworld => true - else - config.filter_run_excluding :realworld => true - end + config.filter_run_excluding :sudo => true + config.filter_run_excluding :realworld => true git_version = Bundler::Source::Git::GitProxy.new(nil, nil, nil).version - config.filter_run_excluding :rubygems => RequirementChecker.against(Gem::VERSION) config.filter_run_excluding :git => RequirementChecker.against(git_version) config.filter_run_excluding :bundler => RequirementChecker.against(Bundler::VERSION.split(".")[0]) + config.filter_run_excluding :rubygems => RequirementChecker.against(Gem::VERSION) config.filter_run_excluding :ruby_repo => !ENV["GEM_COMMAND"].nil? config.filter_run_excluding :no_color_tty => Gem.win_platform? || !ENV["GITHUB_ACTION"].nil? + config.filter_run_excluding :permissions => Gem.win_platform? + config.filter_run_excluding :readline => Gem.win_platform? + config.filter_run_excluding :jruby => RUBY_ENGINE != "jruby" + config.filter_run_excluding :truffleruby => RUBY_ENGINE != "truffleruby" + config.filter_run_excluding :man => Gem.win_platform? config.filter_run_when_matching :focus unless ENV["CI"] end diff --git a/ruby/spec/bundler/support/hax.rb b/ruby/spec/bundler/support/hax.rb index c18470acd..3d97b93c5 100644 --- a/ruby/spec/bundler/support/hax.rb +++ b/ruby/spec/bundler/support/hax.rb @@ -9,60 +9,26 @@ def self.ruby=(ruby) Gem.ruby = ENV["RUBY"] end - if version = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] - remove_const(:VERSION) if const_defined?(:VERSION) - VERSION = version + if ENV["BUNDLER_GEM_DEFAULT_DIR"] + @default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"] + @default_specifications_dir = nil end - class Platform - @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) if ENV["BUNDLER_SPEC_PLATFORM"] - end - @platforms = [Gem::Platform::RUBY, Gem::Platform.local] - - # We only need this hack for rubygems versions without the BundlerVersionFinder - if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") || ENV["BUNDLER_SPEC_DISABLE_DEFAULT_BUNDLER_GEM"] - @path_to_default_spec_map.delete_if do |_path, spec| - spec.name == "bundler" + if ENV["BUNDLER_SPEC_PLATFORM"] + class Platform + @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) end + @platforms = [Gem::Platform::RUBY, Gem::Platform.local] end -end - -if ENV["BUNDLER_SPEC_VERSION"] - require_relative "path" - require "#{Spec::Path.lib_dir}/bundler/version" - module Bundler - remove_const(:VERSION) if const_defined?(:VERSION) - VERSION = ENV["BUNDLER_SPEC_VERSION"].dup + if ENV["BUNDLER_SPEC_GEM_SOURCES"] + self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]] end -end - -if ENV["BUNDLER_SPEC_WINDOWS"] == "true" - require_relative "path" - require "#{Spec::Path.lib_dir}/bundler/constants" - module Bundler - remove_const :WINDOWS if defined?(WINDOWS) - WINDOWS = true - end -end - -class Object - if ENV["BUNDLER_SPEC_RUBY_ENGINE"] - if RUBY_ENGINE != "jruby" && ENV["BUNDLER_SPEC_RUBY_ENGINE"] == "jruby" - begin - # this has to be done up front because psych will try to load a .jar - # if it thinks its on jruby - require "psych" - rescue LoadError - nil - end + # We only need this hack for rubygems versions without the BundlerVersionFinder + if Gem.rubygems_version < Gem::Version.new("2.7.0") + @path_to_default_spec_map.delete_if do |_path, spec| + spec.name == "bundler" end - - remove_const :RUBY_ENGINE - RUBY_ENGINE = ENV["BUNDLER_SPEC_RUBY_ENGINE"] - - remove_const :RUBY_ENGINE_VERSION - RUBY_ENGINE_VERSION = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] end end diff --git a/ruby/spec/bundler/support/helpers.rb b/ruby/spec/bundler/support/helpers.rb index e9c9e766c..d7556102b 100644 --- a/ruby/spec/bundler/support/helpers.rb +++ b/ruby/spec/bundler/support/helpers.rb @@ -2,39 +2,37 @@ require_relative "command_execution" require_relative "the_bundle" +require_relative "path" module Spec module Helpers + include Spec::Path + def reset! Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir| - next if %w[base remote1 gems rubygems . ..].include?(File.basename(dir)) - if ENV["BUNDLER_SUDO_TESTS"] - `sudo rm -rf "#{dir}"` - else - FileUtils.rm_rf(dir) - end + next if %w[base base_system remote1 rubocop standard gems rubygems . ..].include?(File.basename(dir)) + FileUtils.rm_rf(dir) end FileUtils.mkdir_p(home) FileUtils.mkdir_p(tmpdir) - Bundler.reset! + reset_paths! end - def self.bang(method) - define_method("#{method}!") do |*args, &blk| - send(method, *args, &blk).tap do - unless last_command.success? - raise "Invoking #{method}!(#{args.map(&:inspect).join(", ")}) failed:\n#{last_command.stdboth}" - end - end - end + def reset_paths! + Bundler.reset! + Gem.clear_paths end def the_bundle(*args) TheBundle.new(*args) end + def command_executions + @command_executions ||= [] + end + def last_command - @command_executions.last || raise("There is no last command") + command_executions.last || raise("There is no last command") end def out @@ -59,32 +57,19 @@ def exitstatus last_command.exitstatus end - def in_app_root(&blk) - Dir.chdir(bundled_app, &blk) - end - - def in_app_root2(&blk) - Dir.chdir(bundled_app2, &blk) - end - - def in_app_root_custom(root, &blk) - Dir.chdir(root, &blk) - end - def run(cmd, *args) opts = args.last.is_a?(Hash) ? args.pop : {} groups = args.map(&:inspect).join(", ") - setup = "require '#{lib_dir}/bundler' ; Bundler.ui.silence { Bundler.setup(#{groups}) }\n" - ruby(setup + cmd, opts) + setup = "require '#{entrypoint}' ; Bundler.ui.silence { Bundler.setup(#{groups}) }" + ruby([setup, cmd].join(" ; "), opts) end - bang :run def load_error_run(ruby, name, *args) cmd = <<-RUBY begin #{ruby} rescue LoadError => e - $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("-- #{name}") + warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}") end RUBY opts = args.last.is_a?(Hash) ? args.pop : {} @@ -92,39 +77,34 @@ def load_error_run(ruby, name, *args) run(cmd, *args) end - def bundle(cmd, options = {}) + def bundle(cmd, options = {}, &block) with_sudo = options.delete(:sudo) - sudo = with_sudo == :preserve_env ? "sudo -E" : "sudo" if with_sudo - - bundle_bin = options.delete("bundle_bin") || bindir.join("bundle") + sudo = with_sudo == :preserve_env ? "sudo -E --preserve-env=RUBYOPT" : "sudo" if with_sudo - if system_bundler = options.delete(:system_bundler) - bundle_bin = system_gem_path.join("bin/bundler") - end + bundle_bin = options.delete(:bundle_bin) + bundle_bin ||= installed_bindir.join("bundle") env = options.delete(:env) || {} - env["PATH"].gsub!("#{Path.root}/exe", "") if env["PATH"] && system_bundler requires = options.delete(:requires) || [] - requires << "support/hax" + realworld = RSpec.current_example.metadata[:realworld] artifice = options.delete(:artifice) do - if RSpec.current_example.metadata[:realworld] + if realworld "vcr" else "fail" end end if artifice - requires << "support/artifice/#{artifice}" + requires << "#{Path.spec_dir}/support/artifice/#{artifice}.rb" end - requires_str = requires.map {|r| "-r#{r}" }.join(" ") - load_path = [] - load_path << lib_dir unless system_bundler load_path << spec_dir - load_path_str = "-I#{load_path.join(File::PATH_SEPARATOR)}" + + dir = options.delete(:dir) || bundled_app + raise_on_error = options.delete(:raise_on_error) args = options.map do |k, v| case v @@ -139,74 +119,74 @@ def bundle(cmd, options = {}) end end.join - cmd = "#{sudo} #{Gem.ruby} #{load_path_str} #{requires_str} #{bundle_bin} #{cmd}#{args}" - sys_exec(cmd, env) {|i, o, thr| yield i, o, thr if block_given? } - end - bang :bundle - - def forgotten_command_line_options(options) - remembered = Bundler::VERSION.split(".", 2).first == "2" - options = options.map do |k, v| - v = '""' if v && v.to_s.empty? - [k, v] - end - return Hash[options] if remembered - options.each do |k, v| - if v.nil? - bundle! "config unset #{k}" - else - bundle! "config set --local #{k} #{v}" - end - end - {} + ruby_cmd = build_ruby_cmd({ :sudo => sudo, :load_path => load_path, :requires => requires }) + cmd = "#{ruby_cmd} #{bundle_bin} #{cmd}#{args}" + sys_exec(cmd, { :env => env, :dir => dir, :raise_on_error => raise_on_error }, &block) end def bundler(cmd, options = {}) - options["bundle_bin"] = bindir.join("bundler") + options[:bundle_bin] = system_gem_path.join("bin/bundler") bundle(cmd, options) end def ruby(ruby, options = {}) - env = options.delete(:env) || {} - ruby = ruby.gsub(/["`\$]/) {|m| "\\#{m}" } - lib_option = options[:no_lib] ? "" : " -I#{lib_dir}" - sys_exec(%(#{Gem.ruby}#{lib_option} -w -e "#{ruby}"), env) + ruby_cmd = build_ruby_cmd + escaped_ruby = ruby.shellescape + sys_exec(%(#{ruby_cmd} -w -e #{escaped_ruby}), options) end - bang :ruby def load_error_ruby(ruby, name, opts = {}) ruby(<<-R) begin #{ruby} rescue LoadError => e - $stderr.puts "ZOMG LOAD ERROR"# if e.message.include?("-- #{name}") + warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}") end R end - def gembin(cmd) - old = ENV["RUBYOPT"] - ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -I#{lib_dir}" + def build_ruby_cmd(options = {}) + sudo = options.delete(:sudo) + + libs = options.delete(:load_path) + lib_option = libs ? "-I#{libs.join(File::PATH_SEPARATOR)}" : [] + + requires = options.delete(:requires) || [] + requires << "#{Path.spec_dir}/support/hax.rb" + require_option = requires.map {|r| "-r#{r}" } + + [sudo, Gem.ruby, *lib_option, *require_option].compact.join(" ") + end + + def gembin(cmd, options = {}) cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/") - sys_exec(cmd.to_s) - ensure - ENV["RUBYOPT"] = old + sys_exec(cmd.to_s, options) end - def gem_command(command, args = "") - sys_exec("#{Path.gem_bin} #{command} #{args}") + def gem_command(command, options = {}) + env = options[:env] || {} + env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"]), ENV["RUBYOPT"]) + options[:env] = env + sys_exec("#{Path.gem_bin} #{command}", options) end - bang :gem_command def rake "#{Gem.ruby} -S #{ENV["GEM_PATH"]}/bin/rake" end - def sys_exec(cmd, env = {}) - command_execution = CommandExecution.new(cmd.to_s, Dir.pwd) + def git(cmd, path, options = {}) + sys_exec("git #{cmd}", options.merge(:dir => path)) + end + + def sys_exec(cmd, options = {}) + env = options[:env] || {} + env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"]), ENV["RUBYOPT"]) + dir = options[:dir] || bundled_app + command_execution = CommandExecution.new(cmd.to_s, dir) require "open3" - Open3.popen3(env, cmd.to_s) do |stdin, stdout, stderr, wait_thr| + require "shellwords" + Open3.popen3(env, *cmd.shellsplit, :chdir => dir) do |stdin, stdout, stderr, wait_thr| yield stdin, stdout, wait_thr if block_given? stdin.close @@ -214,17 +194,38 @@ def sys_exec(cmd, env = {}) stderr_read_thread = Thread.new { stderr.read } command_execution.stdout = stdout_read_thread.value.strip command_execution.stderr = stderr_read_thread.value.strip - command_execution.exitstatus = wait_thr && wait_thr.value.exitstatus + + status = wait_thr.value + command_execution.exitstatus = if status.exited? + status.exitstatus + elsif status.signaled? + exit_status_for_signal(status.termsig) + end + end + + unless options[:raise_on_error] == false || command_execution.success? + raise <<~ERROR + + Invoking `#{cmd}` failed with output: + ---------------------------------------------------------------------- + #{command_execution.stdboth} + ---------------------------------------------------------------------- + ERROR end - (@command_executions ||= []) << command_execution + command_executions << command_execution command_execution.stdout end - bang :sys_exec + + def all_commands_output + return "" if command_executions.empty? + + "\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}" + end def config(config = nil, path = bundled_app(".bundle/config")) - return YAML.load_file(path) unless config + return Psych.load_file(path) unless config FileUtils.mkdir_p(File.dirname(path)) File.open(path, "w") do |f| f.puts config.to_yaml @@ -236,33 +237,31 @@ def global_config(config = nil) config(config, home(".bundle/config")) end - def create_file(*args) - path = bundled_app(args.shift) - path = args.shift if args.first.is_a?(Pathname) - str = args.shift || "" + def create_file(path, contents = "") + path = Pathname.new(path).expand_path(bundled_app) unless path.is_a?(Pathname) path.dirname.mkpath File.open(path.to_s, "w") do |f| - f.puts strip_whitespace(str) + f.puts strip_whitespace(contents) end end def gemfile(*args) - contents = args.shift + contents = args.pop if contents.nil? - File.open("Gemfile", "r", &:read) + File.open(bundled_app_gemfile, "r", &:read) else - create_file("Gemfile", contents, *args) + create_file(args.pop || "Gemfile", contents) end end def lockfile(*args) - contents = args.shift + contents = args.pop if contents.nil? - File.open("Gemfile.lock", "r", &:read) + File.open(bundled_app_lock, "r", &:read) else - create_file("Gemfile.lock", contents, *args) + create_file(args.pop || "Gemfile.lock", contents) end end @@ -273,79 +272,116 @@ def strip_whitespace(str) end def install_gemfile(*args) + opts = args.last.is_a?(Hash) ? args.pop : {} gemfile(*args) - opts = args.last.is_a?(Hash) ? args.last : {} - opts[:retry] ||= 0 bundle :install, opts end - bang :install_gemfile def lock_gemfile(*args) gemfile(*args) opts = args.last.is_a?(Hash) ? args.last : {} - opts[:retry] ||= 0 bundle :lock, opts end - def install_gems(*gems) + def system_gems(*gems) + gems = gems.flatten options = gems.last.is_a?(Hash) ? gems.pop : {} - gem_repo = options.fetch(:gem_repo) { gem_repo1 } - gems.each do |g| - if g == :bundler - with_built_bundler {|gem_path| install_gem(gem_path) } - elsif g.to_s =~ %r{\A(?:[A-Z]:)?/.*\.gem\z} - install_gem(g) - else - install_gem("#{gem_repo}/gems/#{g}.gem") + path = options.fetch(:path, system_gem_path) + default = options.fetch(:default, false) + with_gem_path_as(path) do + gem_repo = options.fetch(:gem_repo, gem_repo1) + gems.each do |g| + gem_name = g.to_s + if gem_name.start_with?("bundler") + version = gem_name.match(/\Abundler-(?.*)\z/)[:version] if gem_name != "bundler" + with_built_bundler(version) {|gem_path| install_gem(gem_path, default) } + elsif gem_name =~ %r{\A(?:[a-zA-Z]:)?/.*\.gem\z} + install_gem(gem_name, default) + else + install_gem("#{gem_repo}/gems/#{gem_name}.gem", default) + end end end end - def install_gem(path) + def install_gem(path, default = false) raise "OMG `#{path}` does not exist!" unless File.exist?(path) - gem_command! :install, "--no-document --ignore-dependencies '#{path}'" + args = "--no-document --ignore-dependencies" + args += " --default --install-dir #{system_gem_path}" if default + + gem_command "install #{args} '#{path}'" end - def with_built_bundler - with_root_gemspec do |gemspec| - Dir.chdir(root) { gem_command! :build, gemspec.to_s } - end + def with_built_bundler(version = nil) + version ||= Bundler::VERSION + full_name = "bundler-#{version}" + build_path = tmp + full_name + bundler_path = build_path + "#{full_name}.gem" - bundler_path = root + "bundler-#{Bundler::VERSION}.gem" + Dir.mkdir build_path begin + shipped_files.each do |shipped_file| + target_shipped_file = build_path + shipped_file + target_shipped_dir = File.dirname(target_shipped_file) + FileUtils.mkdir_p target_shipped_dir unless File.directory?(target_shipped_dir) + FileUtils.cp shipped_file, target_shipped_file, :preserve => true + end + + replace_version_file(version, dir: build_path) # rubocop:disable Style/HashSyntax + + Spec::BuildMetadata.write_build_metadata(dir: build_path) # rubocop:disable Style/HashSyntax + + gem_command "build #{relative_gemspec}", :dir => build_path + yield(bundler_path) ensure - bundler_path.rmtree + build_path.rmtree end end def with_gem_path_as(path) - backup = ENV.to_hash - ENV["GEM_HOME"] = path.to_s - ENV["GEM_PATH"] = path.to_s - ENV["BUNDLER_ORIG_GEM_PATH"] = nil - yield - ensure - ENV.replace(backup) + without_env_side_effects do + ENV["GEM_HOME"] = path.to_s + ENV["GEM_PATH"] = path.to_s + ENV["BUNDLER_ORIG_GEM_HOME"] = nil + ENV["BUNDLER_ORIG_GEM_PATH"] = nil + yield + end end def with_path_as(path) + without_env_side_effects do + ENV["PATH"] = path.to_s + ENV["BUNDLER_ORIG_PATH"] = nil + yield + end + end + + def without_env_side_effects backup = ENV.to_hash - ENV["PATH"] = path.to_s - ENV["BUNDLER_ORIG_PATH"] = nil yield ensure ENV.replace(backup) end def with_path_added(path) - with_path_as(path.to_s + ":" + ENV["PATH"]) do + with_path_as([path.to_s, ENV["PATH"]].join(File::PATH_SEPARATOR)) do yield end end + def opt_add(option, options) + [option.strip, options].compact.reject(&:empty?).join(" ") + end + + def opt_remove(option, options) + return unless options + + options.split(" ").reject {|opt| opt.strip == option.strip }.join(" ") + end + def break_git! FileUtils.mkdir_p(tmp("broken_path")) File.open(tmp("broken_path/git"), "w", 0o755) do |f| @@ -356,6 +392,8 @@ def break_git! end def with_fake_man + skip "fake_man is not a Windows friendly binstub" if Gem.win_platform? + FileUtils.mkdir_p(tmp("fake_man")) File.open(tmp("fake_man/man"), "w", 0o755) do |f| f.puts "#!/usr/bin/env ruby\nputs ARGV.inspect\n" @@ -363,68 +401,21 @@ def with_fake_man with_path_added(tmp("fake_man")) { yield } end - def system_gems(*gems) - opts = gems.last.is_a?(Hash) ? gems.last : {} - path = opts.fetch(:path, system_gem_path) - if path == :bundle_path - path = ruby!(<<-RUBY) - require "bundler" - begin - puts Bundler.bundle_path - rescue Bundler::GemfileNotFound - ENV["BUNDLE_GEMFILE"] = "Gemfile" - retry - end - - RUBY - end - gems = gems.flatten - - unless opts[:keep_path] - FileUtils.rm_rf(path) - FileUtils.mkdir_p(path) - end - - Gem.clear_paths - - env_backup = ENV.to_hash - ENV["GEM_HOME"] = path.to_s - ENV["GEM_PATH"] = path.to_s - ENV["BUNDLER_ORIG_GEM_PATH"] = nil + def pristine_system_gems(*gems) + FileUtils.rm_rf(system_gem_path) - install_gems(*gems) - return unless block_given? - begin - yield - ensure - ENV.replace(env_backup) - end + system_gems(*gems) end def realworld_system_gems(*gems) gems = gems.flatten + opts = gems.last.is_a?(Hash) ? gems.pop : {} + path = opts.fetch(:path, system_gem_path) - FileUtils.rm_rf(system_gem_path) - FileUtils.mkdir_p(system_gem_path) - - Gem.clear_paths - - gem_home = ENV["GEM_HOME"] - gem_path = ENV["GEM_PATH"] - path = ENV["PATH"] - ENV["GEM_HOME"] = system_gem_path.to_s - ENV["GEM_PATH"] = system_gem_path.to_s - - gems.each do |gem| - gem_command! :install, "--no-document #{gem}" - end - return unless block_given? - begin - yield - ensure - ENV["GEM_HOME"] = gem_home - ENV["GEM_PATH"] = gem_path - ENV["PATH"] = path + with_gem_path_as(path) do + gems.each do |gem| + gem_command "install --no-document #{gem}" + end end end @@ -442,9 +433,8 @@ def cache_gems(*gems) end def simulate_new_machine - system_gems [] - FileUtils.rm_rf system_gem_path FileUtils.rm_rf bundled_app(".bundle") + pristine_system_gems :bundler end def simulate_platform(platform) @@ -455,56 +445,40 @@ def simulate_platform(platform) ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given? end - def simulate_ruby_version(version) - return if version == RUBY_VERSION - old = ENV["BUNDLER_SPEC_RUBY_VERSION"] - ENV["BUNDLER_SPEC_RUBY_VERSION"] = version - yield if block_given? - ensure - ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given? + def simulate_windows(platform = mswin) + simulate_platform platform do + simulate_bundler_version_when_missing_prerelease_default_gem_activation do + yield + end + end end - def simulate_ruby_engine(engine, version = "1.6.0") - return if engine == local_ruby_engine - - old = ENV["BUNDLER_SPEC_RUBY_ENGINE"] - ENV["BUNDLER_SPEC_RUBY_ENGINE"] = engine - old_version = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] - ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = version - yield if block_given? - ensure - ENV["BUNDLER_SPEC_RUBY_ENGINE"] = old if block_given? - ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = old_version if block_given? - end + def simulate_bundler_version_when_missing_prerelease_default_gem_activation + return yield unless rubygems_version_failing_to_activate_bundler_prereleases - def simulate_bundler_version(version) - old = ENV["BUNDLER_SPEC_VERSION"] - ENV["BUNDLER_SPEC_VERSION"] = version.to_s - yield if block_given? + old = ENV["BUNDLER_VERSION"] + ENV["BUNDLER_VERSION"] = Bundler::VERSION + yield ensure - ENV["BUNDLER_SPEC_VERSION"] = old if block_given? + ENV["BUNDLER_VERSION"] = old end - def simulate_rubygems_version(version) - old = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] - ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = version.to_s - yield if block_given? - ensure - ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = old if block_given? + def env_for_missing_prerelease_default_gem_activation + if rubygems_version_failing_to_activate_bundler_prereleases + { "BUNDLER_VERSION" => Bundler::VERSION } + else + {} + end end - def simulate_windows(platform = mswin) - old = ENV["BUNDLER_SPEC_WINDOWS"] - ENV["BUNDLER_SPEC_WINDOWS"] = "true" - simulate_platform platform do - yield - end - ensure - ENV["BUNDLER_SPEC_WINDOWS"] = old + # versions providing a bundler version finder but not including + # https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1 + def rubygems_version_failing_to_activate_bundler_prereleases + Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") && Gem.rubygems_version >= Gem::Version.new("2.7.0") end def revision_for(path) - Dir.chdir(path) { `git rev-parse HEAD`.strip } + sys_exec("git rev-parse HEAD", :dir => path).strip end def with_read_only(pattern) @@ -526,11 +500,11 @@ def prepare_gemspec(pathname) process_file(pathname) do |line| case line when /spec\.metadata\["(?:allowed_push_host|homepage_uri|source_code_uri|changelog_uri)"\]/, /spec\.homepage/ - line.gsub(/\=.*$/, "= 'http://example.org'") + line.gsub(/\=.*$/, '= "http://example.org"') when /spec\.summary/ - line.gsub(/\=.*$/, "= %q{A short summary of my new gem.}") + line.gsub(/\=.*$/, '= "A short summary of my new gem."') when /spec\.description/ - line.gsub(/\=.*$/, "= %q{A longer description of my new gem.}") + line.gsub(/\=.*$/, '= "A longer description of my new gem."') else line end @@ -559,7 +533,7 @@ def with_env_vars(env_hash, &block) def require_rack # need to hack, so we can require rack old_gem_home = ENV["GEM_HOME"] - ENV["GEM_HOME"] = Spec::Path.base_system_gems.to_s + ENV["GEM_HOME"] = Spec::Path.base_system_gem_path.to_s require "rack" ENV["GEM_HOME"] = old_gem_home end @@ -583,5 +557,16 @@ def find_unused_port end port end + + def exit_status_for_signal(signal_number) + # For details see: https://en.wikipedia.org/wiki/Exit_status#Shell_and_scripts + 128 + signal_number + end + + private + + def git_root_dir? + root.to_s == `git rev-parse --show-toplevel`.chomp + end end end diff --git a/ruby/spec/bundler/support/indexes.rb b/ruby/spec/bundler/support/indexes.rb index dc6e0bd1e..638f394e7 100644 --- a/ruby/spec/bundler/support/indexes.rb +++ b/ruby/spec/bundler/support/indexes.rb @@ -17,16 +17,19 @@ def platform(*args) def resolve(args = []) @platforms ||= ["ruby"] deps = [] - default_source = instance_double("Bundler::Source::Rubygems", :specs => @index) + default_source = instance_double("Bundler::Source::Rubygems", :specs => @index, :to_s => "locally install gems") source_requirements = { :default => default_source } @deps.each do |d| + source_requirements[d.name] = d.source = default_source @platforms.each do |p| - source_requirements[d.name] = d.source = default_source - deps << Bundler::DepProxy.new(d, p) + deps << Bundler::DepProxy.get_proxy(d, p) end end - source_requirements ||= {} - Bundler::Resolver.resolve(deps, @index, source_requirements, *args) + args[0] ||= [] # base + args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter + args[2] ||= [] # additional_base_requirements + args[3] ||= @platforms # platforms + Bundler::Resolver.resolve(deps, source_requirements, *args) end def should_resolve_as(specs) diff --git a/ruby/spec/bundler/support/matchers.rb b/ruby/spec/bundler/support/matchers.rb index df35854c2..3c2a7f9f5 100644 --- a/ruby/spec/bundler/support/matchers.rb +++ b/ruby/spec/bundler/support/matchers.rb @@ -75,16 +75,6 @@ def self.define_compound_matcher(matcher, preconditions, &declarations) end end - RSpec::Matchers.define :have_rubyopts do |*args| - args = args.flatten - args = args.first.split(/\s+/) if args.size == 1 - - match do |actual| - actual = actual.split(/\s+/) if actual.is_a?(String) - args.all? {|arg| actual.include?(arg) } && actual.uniq.size == actual.size - end - end - RSpec::Matchers.define :be_sorted do diffable attr_reader :expected @@ -124,34 +114,49 @@ def indent(string, padding = 4, indent_character = " ") match do opts = names.last.is_a?(Hash) ? names.pop : {} source = opts.delete(:source) - groups = Array(opts[:groups]) - groups << opts - @errors = names.map do |name| - name, version, platform = name.split(/\s+/) - require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/") + groups = Array(opts.delete(:groups)).map(&:inspect).join(", ") + opts[:raise_on_error] = false + @errors = names.map do |full_name| + name, version, platform = full_name.split(/\s+/) + require_path = name.tr("-", "/") version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name) - begin - run! "require '#{require_path}.rb'; puts #{version_const}", *groups - rescue StandardError => e - next "#{name} is not installed:\n#{indent(e)}" - end - actual_version, actual_platform = out.strip.split(/\s+/, 2) - unless Gem::Version.new(actual_version) == Gem::Version.new(version) + source_const = "#{Spec::Builders.constantize(name)}_SOURCE" + ruby <<~R, opts + require 'bundler' + Bundler.setup(#{groups}) + + require '#{require_path}' + actual_version, actual_platform = #{version_const}.split(/\s+/, 2) + unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}') + puts actual_version + exit 64 + end + unless actual_platform.to_s == '#{platform}' + puts actual_platform + exit 65 + end + require '#{require_path}/source' + exit 0 if #{source.nil?} + actual_source = #{source_const} + unless actual_source == '#{source}' + puts actual_source + exit 66 + end + R + next if exitstatus == 0 + if exitstatus == 64 + actual_version = out.split("\n").last next "#{name} was expected to be at version #{version} but was #{actual_version}" end - unless actual_platform == platform + if exitstatus == 65 + actual_platform = out.split("\n").last next "#{name} was expected to be of platform #{platform} but was #{actual_platform}" end - next unless source - begin - source_const = "#{Spec::Builders.constantize(name)}_SOURCE" - run! "require '#{require_path}/source'; puts #{source_const}", *groups - rescue StandardError - next "#{name} does not have a source defined:\n#{indent(e)}" - end - unless out.strip == source - next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{out}`" + if exitstatus == 66 + actual_source = out.split("\n").last + next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{actual_source}`" end + next "Command to check for inclusion of gem #{full_name} failed" end.compact @errors.empty? @@ -159,26 +164,34 @@ def indent(string, padding = 4, indent_character = " ") match_when_negated do opts = names.last.is_a?(Hash) ? names.pop : {} - groups = Array(opts[:groups]) || [] + groups = Array(opts.delete(:groups)).map(&:inspect).join(", ") + opts[:raise_on_error] = false @errors = names.map do |name| name, version = name.split(/\s+/, 2) - begin - run <<-R, *(groups + [opts]) - begin - require '#{name}' - puts #{Spec::Builders.constantize(name)} - rescue LoadError, NameError - puts "WIN" + ruby <<-R, opts + begin + require 'bundler' + Bundler.setup(#{groups}) + rescue Bundler::GemNotFound, Bundler::GitError + exit 0 + end + + begin + require '#{name}' + name_constant = '#{Spec::Builders.constantize(name)}' + if #{version.nil?} || name_constant == '#{version}' + exit 64 + else + exit 0 end - R - rescue StandardError => e - next "checking for #{name} failed:\n#{e}\n#{e.backtrace.join("\n")}" - end - next if out == "WIN" + rescue LoadError, NameError + exit 0 + end + R + next if exitstatus == 0 + next "command to check version of #{name} installed failed" unless exitstatus == 64 next "expected #{name} to not be installed, but it was" if version.nil? - if Gem::Version.new(out) == Gem::Version.new(version) - next "expected #{name} (#{version}) not to be installed, but it was" - end + next "expected #{name} (#{version}) not to be installed, but it was" end.compact @errors.empty? @@ -195,10 +208,6 @@ def indent(string, padding = 4, indent_character = " ") RSpec::Matchers.define_negated_matcher :not_include_gems, :include_gems RSpec::Matchers.alias_matcher :include_gem, :include_gems - def have_lockfile(expected) - read_as(strip_whitespace(expected)) - end - def plugin_should_be_installed(*names) names.each do |name| expect(Bundler::Plugin).to be_installed(name) @@ -212,13 +221,5 @@ def plugin_should_not_be_installed(*names) expect(Bundler::Plugin).not_to be_installed(name) end end - - def lockfile_should_be(expected) - expect(bundled_app("Gemfile.lock")).to have_lockfile(expected) - end - - def gemfile_should_be(expected) - expect(bundled_app("Gemfile")).to read_as(strip_whitespace(expected)) - end end end diff --git a/ruby/spec/bundler/support/parallel.rb b/ruby/spec/bundler/support/parallel.rb deleted file mode 100644 index 8763cb9ec..000000000 --- a/ruby/spec/bundler/support/parallel.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -RSpec.configure do |config| - config.silence_filter_announcements = true -end diff --git a/ruby/spec/bundler/support/path.rb b/ruby/spec/bundler/support/path.rb index 645da52c9..41b36997b 100644 --- a/ruby/spec/bundler/support/path.rb +++ b/ruby/spec/bundler/support/path.rb @@ -5,54 +5,98 @@ module Spec module Path + def source_root + @source_root ||= Pathname.new(ruby_core? ? "../../.." : "../..").expand_path(__dir__) + end + def root - @root ||= Pathname.new(ruby_core? ? "../../../.." : "../../..").expand_path(__FILE__) + @root ||= system_gem_path("gems/bundler-#{Bundler::VERSION}") end def gemspec - @gemspec ||= root.join(ruby_core? ? "lib/bundler/bundler.gemspec" : "bundler.gemspec") + @gemspec ||= source_root.join(relative_gemspec) + end + + def relative_gemspec + @relative_gemspec ||= ruby_core? ? "lib/bundler/bundler.gemspec" : "bundler.gemspec" end def gemspec_dir @gemspec_dir ||= gemspec.parent end + def loaded_gemspec + @loaded_gemspec ||= Gem::Specification.load(gemspec.to_s) + end + + def test_gemfile + @test_gemfile ||= tool_dir.join("test_gems.rb") + end + + def rubocop_gemfile + @rubocop_gemfile ||= source_root.join(rubocop_gemfile_basename) + end + + def standard_gemfile + @standard_gemfile ||= source_root.join(standard_gemfile_basename) + end + + def dev_gemfile + @dev_gemfile ||= tool_dir.join("dev_gems.rb") + end + def bindir - @bindir ||= root.join(ruby_core? ? "libexec" : "exe") + @bindir ||= source_root.join(ruby_core? ? "libexec" : "exe") + end + + def installed_bindir + @installed_bindir ||= system_gem_path("bin") end def gem_cmd - @gem_cmd ||= ruby_core? ? root.join("bin/gem") : "gem" + @gem_cmd ||= ruby_core? ? source_root.join("bin/gem") : "gem" end def gem_bin @gem_bin ||= ruby_core? ? ENV["GEM_COMMAND"] : "gem" end + def path + env_path = ENV["PATH"] + env_path = env_path.split(File::PATH_SEPARATOR).reject {|path| path == bindir.to_s }.join(File::PATH_SEPARATOR) if ruby_core? + env_path + end + def spec_dir - @spec_dir ||= root.join(ruby_core? ? "spec/bundler" : "spec") + @spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec") end - def tracked_files - skip "not in git working directory" unless git_root_dir? + def api_request_limit_hack_file + spec_dir.join("support/api_request_limit_hax.rb") + end - @tracked_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler man/bundler*` : `git ls-files -z` + def man_dir + @man_dir ||= lib_dir.join("bundler/man") end - def shipped_files - skip "not in git working directory" unless git_root_dir? + def tracked_files + @tracked_files ||= git_ls_files(tracked_files_glob) + end - @shipped_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb man/bundler* libexec/bundle*` : `git ls-files -z -- lib man exe CHANGELOG.md LICENSE.md README.md bundler.gemspec` + def shipped_files + @shipped_files ||= loaded_gemspec.files end def lib_tracked_files - skip "not in git working directory" unless git_root_dir? + @lib_tracked_files ||= git_ls_files(lib_tracked_files_glob) + end - @lib_tracked_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb` : `git ls-files -z -- lib` + def man_tracked_files + @man_tracked_files ||= git_ls_files(man_tracked_files_glob) end def tmp(*path) - root.join("tmp", scope, *path) + source_root.join("tmp", scope, *path) end def scope @@ -67,10 +111,10 @@ def home(*path) end def default_bundle_path(*path) - if Bundler::VERSION.split(".").first.to_i < 3 - system_gem_path(*path) + if Bundler.feature_flag.default_install_uses_path? + local_gem_path(*path) else - bundled_app(*[".bundle", ENV.fetch("BUNDLER_SPEC_RUBY_ENGINE", Gem.ruby_engine), RbConfig::CONFIG["ruby_version"], *path].compact) + system_gem_path(*path) end end @@ -80,8 +124,6 @@ def bundled_app(*path) root.join(*path) end - alias_method :bundled_app1, :bundled_app - def bundled_app2(*path) root = tmp.join("bundled_app2") FileUtils.mkdir_p(root) @@ -89,17 +131,37 @@ def bundled_app2(*path) end def vendored_gems(path = nil) - bundled_app(*["vendor/bundle", Gem.ruby_engine, RbConfig::CONFIG["ruby_version"], path].compact) + scoped_gem_path(bundled_app("vendor/bundle")).join(*[path].compact) end def cached_gem(path) bundled_app("vendor/cache/#{path}.gem") end + def bundled_app_gemfile + bundled_app("Gemfile") + end + + def bundled_app_lock + bundled_app("Gemfile.lock") + end + + def base_system_gem_path + scoped_gem_path(base_system_gems) + end + def base_system_gems tmp.join("gems/base") end + def rubocop_gems + tmp.join("gems/rubocop") + end + + def standard_gems + tmp.join("gems/standard") + end + def file_uri_for(path) protocol = "file://" root = Gem.win_platform? ? "/" : "" @@ -135,14 +197,37 @@ def system_gem_path(*path) tmp("gems/system", *path) end + def pristine_system_gem_path + tmp("gems/base_system") + end + + def local_gem_path(*path, base: bundled_app) + scoped_gem_path(base.join(".bundle")).join(*path) + end + + def scoped_gem_path(base) + base.join(Gem.ruby_engine, RbConfig::CONFIG["ruby_version"]) + end + def lib_path(*args) tmp("libs", *args) end + def source_lib_dir + source_root.join("lib") + end + def lib_dir root.join("lib") end + # Sometimes rubygems version under test does not include + # https://github.com/rubygems/rubygems/pull/2728 and will not always end up + # activating the current bundler. In that case, require bundler absolutely. + def entrypoint + Gem.rubygems_version < Gem::Version.new("3.1.a") ? "#{lib_dir}/bundler" : "bundler" + end + def global_plugin_gem(*args) home ".bundle", "plugin", "gems", *args end @@ -155,18 +240,11 @@ def tmpdir(*args) tmp "tmpdir", *args end - def with_root_gemspec - if ruby_core? - root_gemspec = root.join("bundler.gemspec") - # Dir.chdir(root) for Dir.glob in gemspec - spec = Dir.chdir(root) { Gem::Specification.load(gemspec.to_s) } - spec.bindir = "libexec" - File.open(root_gemspec.to_s, "w") {|f| f.write spec.to_ruby } - yield(root_gemspec) - FileUtils.rm(root_gemspec) - else - yield(gemspec) - end + def replace_version_file(version, dir: source_root) + version_file = File.expand_path("lib/bundler/version.rb", dir) + contents = File.read(version_file) + contents.sub!(/(^\s+VERSION\s*=\s*)"#{Gem::Version::VERSION_PATTERN}"/, %(\\1"#{version}")) + File.open(version_file, "w") {|f| f << contents } end def ruby_core? @@ -180,12 +258,60 @@ def ruby_core? end end - extend self + private + + def git_ls_files(glob) + skip "Not running on a git context, since running tests from a tarball" if ruby_core_tarball? + + sys_exec("git ls-files -z -- #{glob}", :dir => source_root).split("\x0") + end + + def tracked_files_glob + ruby_core? ? "lib/bundler lib/bundler.rb spec/bundler man/bundle*" : "" + end + + def lib_tracked_files_glob + ruby_core? ? "lib/bundler lib/bundler.rb" : "lib" + end + + def man_tracked_files_glob + ruby_core? ? "man/bundle* man/gemfile*" : "lib/bundler/man/bundle*.1 lib/bundler/man/gemfile*.5" + end + + def git_root + ruby_core? ? source_root : source_root.parent + end + + def ruby_core_tarball? + !git_root.join(".git").directory? + end - private + def rubocop_gemfile_basename + filename = if RUBY_VERSION.start_with?("2.3") + "rubocop23_gems" + elsif RUBY_VERSION.start_with?("2.4") + "rubocop24_gems" + else + "rubocop_gems" + end + tool_dir.join("#{filename}.rb") + end - def git_root_dir? - root.to_s == `git rev-parse --show-toplevel`.chomp + def standard_gemfile_basename + filename = if RUBY_VERSION.start_with?("2.3") + "standard23_gems" + elsif RUBY_VERSION.start_with?("2.4") + "standard24_gems" + else + "standard_gems" + end + tool_dir.join("#{filename}.rb") end + + def tool_dir + source_root.join("tool/bundler") + end + + extend self end end diff --git a/ruby/spec/bundler/support/platforms.rb b/ruby/spec/bundler/support/platforms.rb index f4d63c8de..07973fd72 100644 --- a/ruby/spec/bundler/support/platforms.rb +++ b/ruby/spec/bundler/support/platforms.rb @@ -65,12 +65,10 @@ def not_local_tag end def local_ruby_engine - ENV["BUNDLER_SPEC_RUBY_ENGINE"] || RUBY_ENGINE + RUBY_ENGINE end def local_engine_version - return ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] if ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] - RUBY_ENGINE_VERSION end @@ -92,15 +90,15 @@ def not_local_patchlevel end def lockfile_platforms - local_platforms.map(&:to_s).sort.join("\n ") + lockfile_platforms_for(local_platforms) + end + + def lockfile_platforms_for(platforms) + platforms.map(&:to_s).sort.join("\n ") end def local_platforms - if Bundler.feature_flag.specific_platform? - [local, specific_local_platform] - else - [local] - end + [specific_local_platform] end end end diff --git a/ruby/spec/bundler/support/rubygems_ext.rb b/ruby/spec/bundler/support/rubygems_ext.rb index ee9c750a5..fd5f06b14 100644 --- a/ruby/spec/bundler/support/rubygems_ext.rb +++ b/ruby/spec/bundler/support/rubygems_ext.rb @@ -2,45 +2,18 @@ require_relative "path" +$LOAD_PATH.unshift(Spec::Path.source_lib_dir.to_s) + module Spec module Rubygems - DEV_DEPS = { - "automatiek" => "~> 0.3.0", - "parallel_tests" => "~> 2.29", - "rake" => "~> 12.0", - "ronn" => "~> 0.7.3", - "rspec" => "~> 3.8", - "rubocop" => "= 0.77.0", - "rubocop-performance" => "= 1.5.1", - }.freeze - - DEPS = { - "rack" => "~> 2.0", - "rack-test" => "~> 1.1", - "artifice" => "~> 0.6.0", - "compact_index" => "~> 0.11.0", - "sinatra" => "~> 2.0", - # Rake version has to be consistent for tests to pass - "rake" => "12.3.2", - "builder" => "~> 3.2", - # ruby-graphviz is used by the viz tests - "ruby-graphviz" => ">= 0.a", - }.freeze - extend self def dev_setup - deps = DEV_DEPS - - # JRuby can't build ronn, so we skip that - deps.delete("ronn") if RUBY_ENGINE == "jruby" - - install_gems(deps) + install_gems(dev_gemfile) end def gem_load(gem_name, bin_container) - require_relative "rubygems_version_manager" - RubygemsVersionManager.new(ENV["RGV"]).switch + require_relative "switch_rubygems" gem_load_and_activate(gem_name, bin_container) end @@ -50,25 +23,10 @@ def gem_require(gem_name) require gem_name end - def setup - require "fileutils" - - Gem.clear_paths + def test_setup + setup_test_paths - ENV["BUNDLE_PATH"] = nil - ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gems.to_s - ENV["PATH"] = [Path.bindir, Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - - manifest = DEPS.to_a.sort_by(&:first).map {|k, v| "#{k} => #{v}\n" } - manifest_path = Path.base_system_gems.join("manifest.txt") - # it's OK if there are extra gems - if !manifest_path.file? || !(manifest - manifest_path.readlines).empty? - FileUtils.rm_rf(Path.base_system_gems) - FileUtils.mkdir_p(Path.base_system_gems) - puts "installing gems for the tests to use..." - install_gems(DEPS) - manifest_path.open("wb") {|f| f << manifest.join } - end + require "fileutils" FileUtils.mkdir_p(Path.home) FileUtils.mkdir_p(Path.tmpdir) @@ -80,28 +38,122 @@ def setup Gem::DefaultUserInteraction.ui = Gem::SilentUI.new end - private + def install_parallel_test_deps + Gem.clear_paths + + require "parallel" + require "fileutils" + + install_test_deps + + (2..Parallel.processor_count).each do |n| + source = Path.source_root.join("tmp", "1") + destination = Path.source_root.join("tmp", n.to_s) + + FileUtils.rm_rf destination + FileUtils.cp_r source, destination + end + end + + def setup_test_paths + Gem.clear_paths + + ENV["BUNDLE_PATH"] = nil + ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gem_path.to_s + ENV["PATH"] = [Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + ENV["PATH"] = [Path.bindir, ENV["PATH"]].join(File::PATH_SEPARATOR) if Path.ruby_core? + end + + def install_test_deps + install_gems(test_gemfile, Path.base_system_gems.to_s) + install_gems(rubocop_gemfile, Path.rubocop_gems.to_s) + install_gems(standard_gemfile, Path.standard_gems.to_s) + end + + def check_source_control_changes(success_message:, error_message:) + require "open3" + + output, status = Open3.capture2e("git status --porcelain") + + if status.success? && output.empty? + puts + puts success_message + puts + else + system("git status --porcelain") + + puts + puts error_message + puts + + exit(1) + end + end + + private def gem_load_and_activate(gem_name, bin_container) gem_activate(gem_name) load Gem.bin_path(gem_name, bin_container) rescue Gem::LoadError => e - abort "We couln't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`" + abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`" end def gem_activate(gem_name) - gem_requirement = DEV_DEPS[gem_name] + require "bundler" + gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).dependencies[gem_name]&.requirement gem gem_name, gem_requirement end - def install_gems(gems) - reqs, no_reqs = gems.partition {|_, req| !req.nil? && !req.split(" ").empty? } - no_reqs.map!(&:first) - reqs.map! {|name, req| "'#{name}:#{req}'" } - deps = reqs.concat(no_reqs).join(" ") - gem = ENV["GEM_COMMAND"] || "#{Gem.ruby} -S gem --backtrace" - cmd = "#{gem} install #{deps} --no-document --conservative" - system(cmd) || raise("Installing gems #{deps} for the tests to use failed!") + def install_gems(gemfile, path = nil) + old_gemfile = ENV["BUNDLE_GEMFILE"] + old_orig_gemfile = ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] + ENV["BUNDLE_GEMFILE"] = gemfile.to_s + ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil + + if path + old_path = ENV["BUNDLE_PATH"] + ENV["BUNDLE_PATH"] = path + else + old_path__system = ENV["BUNDLE_PATH__SYSTEM"] + ENV["BUNDLE_PATH__SYSTEM"] = "true" + end + + output = `#{Gem.ruby} #{File.expand_path("support/bundle.rb", Path.spec_dir)} install --verbose` + raise "Error when installing gems in #{gemfile}: #{output}" unless $?.success? + ensure + if path + ENV["BUNDLE_PATH"] = old_path + else + ENV["BUNDLE_PATH__SYSTEM"] = old_path__system + end + + ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = old_orig_gemfile + ENV["BUNDLE_GEMFILE"] = old_gemfile + end + + def test_gemfile + Path.test_gemfile + end + + def rubocop_gemfile + Path.rubocop_gemfile + end + + def standard_gemfile + Path.standard_gemfile + end + + def dev_gemfile + Path.dev_gemfile + end + + def dev_lockfile + lockfile_for(dev_gemfile) + end + + def lockfile_for(gemfile) + Pathname.new("#{gemfile.expand_path}.lock") end end end diff --git a/ruby/spec/bundler/support/rubygems_version_manager.rb b/ruby/spec/bundler/support/rubygems_version_manager.rb index 854bce890..d1b1f8dd0 100644 --- a/ruby/spec/bundler/support/rubygems_version_manager.rb +++ b/ruby/spec/bundler/support/rubygems_version_manager.rb @@ -15,12 +15,37 @@ def initialize(source) def switch return if use_system? + assert_system_features_not_loaded! + switch_local_copy_if_needed reexec_if_needed end -private + def assert_system_features_not_loaded! + at_exit do + rubylibdir = RbConfig::CONFIG["rubylibdir"] + + rubygems_path = rubylibdir + "/rubygems" + rubygems_default_path = rubygems_path + "/defaults" + + bundler_path = rubylibdir + "/bundler" + bundler_exemptions = Gem.rubygems_version < Gem::Version.new("3.2.0") ? [bundler_path + "/errors.rb"] : [] + + bad_loaded_features = $LOADED_FEATURES.select do |loaded_feature| + (loaded_feature.start_with?(rubygems_path) && !loaded_feature.start_with?(rubygems_default_path)) || + (loaded_feature.start_with?(bundler_path) && !bundler_exemptions.any? {|bundler_exemption| loaded_feature.start_with?(bundler_exemption) }) + end + + errors = if bad_loaded_features.any? + all_commands_output + "the following features were incorrectly loaded:\n#{bad_loaded_features.join("\n")}" + end + + raise errors if errors + end + end + + private def use_system? @source.nil? @@ -31,12 +56,9 @@ def reexec_if_needed require "rbconfig" - ruby = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"]) - ruby << RbConfig::CONFIG["EXEEXT"] + cmd = [RbConfig.ruby, $0, *ARGV].compact - cmd = [ruby, $0, *ARGV].compact - - ENV["RUBYOPT"] = "-I#{local_copy_path.join("lib")} #{ENV["RUBYOPT"]}" + ENV["RUBYOPT"] = opt_add("-I#{local_copy_path.join("lib")}", opt_remove("--disable-gems", ENV["RUBYOPT"])) exec(ENV, *cmd) end @@ -44,15 +66,13 @@ def reexec_if_needed def switch_local_copy_if_needed return unless local_copy_switch_needed? - Dir.chdir(local_copy_path) do - sys_exec!("git remote update") - sys_exec!("git checkout #{target_tag} --quiet") - end + sys_exec("git checkout #{target_tag}", :dir => local_copy_path) ENV["RGV"] = local_copy_path.to_s end def rubygems_unrequire_needed? + require "rubygems" !$LOADED_FEATURES.include?(local_copy_path.join("lib/rubygems.rb").to_s) end @@ -65,9 +85,7 @@ def target_tag end def local_copy_tag - Dir.chdir(local_copy_path) do - sys_exec!("git rev-parse --abbrev-ref HEAD") - end + sys_exec("git rev-parse --abbrev-ref HEAD", :dir => local_copy_path) end def local_copy_path @@ -77,11 +95,10 @@ def local_copy_path def resolve_local_copy_path return expanded_source if source_is_path? - rubygems_path = root.join("tmp/rubygems") + rubygems_path = source_root.join("tmp/rubygems") unless rubygems_path.directory? - rubygems_path.parent.mkpath - sys_exec!("git clone https://github.com/rubygems/rubygems.git #{rubygems_path}") + sys_exec("git clone .. #{rubygems_path}", :dir => source_root) end rubygems_path @@ -92,7 +109,7 @@ def source_is_path? end def expanded_source - @expanded_source ||= Pathname.new(@source).expand_path(root) + @expanded_source ||= Pathname.new(@source).expand_path(source_root) end def resolve_target_tag diff --git a/ruby/spec/bundler/support/sometimes.rb b/ruby/spec/bundler/support/sometimes.rb deleted file mode 100644 index 65a95ed59..000000000 --- a/ruby/spec/bundler/support/sometimes.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Sometimes - def run_with_retries(example_to_run, retries) - example = RSpec.current_example - example.metadata[:retries] ||= retries - - retries.times do |t| - example.metadata[:retried] = t + 1 - example.instance_variable_set(:@exception, nil) - example_to_run.run - break unless example.exception - end - - if e = example.exception - new_exception = e.exception(e.message + "[Retried #{retries} times]") - new_exception.set_backtrace e.backtrace - example.instance_variable_set(:@exception, new_exception) - end - end -end - -RSpec.configure do |config| - config.include Sometimes - config.alias_example_to :sometimes, :sometimes => true - config.add_setting :sometimes_retry_count, :default => 5 - - config.around(:each, :sometimes => true) do |example| - retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count - run_with_retries(example, retries) - end - - config.after(:suite) do - message = proc do |color, text| - colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color) - notification = RSpec::Core::Notifications::MessageNotification.new(colored) - formatter = RSpec.configuration.formatters.first - formatter.message(notification) if formatter.respond_to?(:message) - end - - retried_examples = RSpec.world.example_groups.map do |g| - g.descendants.map do |d| - d.filtered_examples.select do |e| - e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1 - end - end - end.flatten - - message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}") - - retried_examples.each do |e| - message.call(:cyan, " #{e.full_description}") - path = RSpec::Core::Metadata.relative_path(e.location) - message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path) - end - end -end diff --git a/ruby/spec/bundler/support/streams.rb b/ruby/spec/bundler/support/streams.rb deleted file mode 100644 index a947eebf6..000000000 --- a/ruby/spec/bundler/support/streams.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -require "stringio" - -def capture(*args) - opts = args.pop if args.last.is_a?(Hash) - opts ||= {} - - args.map!(&:to_s) - begin - result = StringIO.new - result.close if opts[:closed] - args.each {|stream| eval "$#{stream} = result" } - yield - ensure - args.each {|stream| eval("$#{stream} = #{stream.upcase}") } - end - result.string -end diff --git a/ruby/spec/bundler/support/switch_rubygems.rb b/ruby/spec/bundler/support/switch_rubygems.rb new file mode 100644 index 000000000..a138d2233 --- /dev/null +++ b/ruby/spec/bundler/support/switch_rubygems.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +require_relative "rubygems_version_manager" +RubygemsVersionManager.new(ENV["RGV"]).switch diff --git a/ruby/spec/bundler/update/gemfile_spec.rb b/ruby/spec/bundler/update/gemfile_spec.rb index 8c2bd9ccb..1c5294101 100644 --- a/ruby/spec/bundler/update/gemfile_spec.rb +++ b/ruby/spec/bundler/update/gemfile_spec.rb @@ -8,8 +8,8 @@ gem 'rack' G - bundle! :install, :gemfile => bundled_app("NotGemfile") - bundle! :update, :gemfile => bundled_app("NotGemfile"), :all => true + bundle :install, :gemfile => bundled_app("NotGemfile") + bundle :update, :gemfile => bundled_app("NotGemfile"), :all => true # Specify BUNDLE_GEMFILE for `the_bundle` # to retrieve the proper Gemfile @@ -26,11 +26,11 @@ G bundle "config set --local gemfile #{bundled_app("NotGemfile")}" - bundle! :install + bundle :install end it "uses the gemfile to update" do - bundle! "update", :all => true + bundle "update", :all => true bundle "list" expect(out).to include("rack (1.0.0)") @@ -38,12 +38,10 @@ it "uses the gemfile while in a subdirectory" do bundled_app("subdir").mkpath - Dir.chdir(bundled_app("subdir")) do - bundle! "update", :all => true - bundle "list" + bundle "update", :all => true, :dir => bundled_app("subdir") + bundle "list", :dir => bundled_app("subdir") - expect(out).to include("rack (1.0.0)") - end + expect(out).to include("rack (1.0.0)") end end end diff --git a/ruby/spec/bundler/update/gems/fund_spec.rb b/ruby/spec/bundler/update/gems/fund_spec.rb new file mode 100644 index 000000000..0dfe63d36 --- /dev/null +++ b/ruby/spec/bundler/update/gems/fund_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +RSpec.describe "bundle update" do + before do + build_repo2 do + build_gem "has_funding_and_other_metadata" do |s| + s.metadata = { + "bug_tracker_uri" => "https://example.com/user/bestgemever/issues", + "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md", + "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1", + "homepage_uri" => "https://bestgemever.example.io", + "mailing_list_uri" => "https://groups.example.com/bestgemever", + "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding", + "source_code_uri" => "https://example.com/user/bestgemever", + "wiki_uri" => "https://example.com/user/bestgemever/wiki", + } + end + + build_gem "has_funding", "1.2.3" do |s| + s.metadata = { + "funding_uri" => "https://example.com/has_funding/funding", + } + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding_and_other_metadata' + gem 'has_funding', '< 2.0' + G + + bundle :install + end + + context "when listed gems are updated" do + before do + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem 'has_funding_and_other_metadata' + gem 'has_funding' + G + + bundle :update, :all => true + end + + it "displays fund message" do + expect(out).to include("2 installed gems you directly depend on are looking for funding.") + end + end +end diff --git a/ruby/spec/bundler/update/gems/post_install_spec.rb b/ruby/spec/bundler/update/gems/post_install_spec.rb index 5b061eb61..3aaa659d5 100644 --- a/ruby/spec/bundler/update/gems/post_install_spec.rb +++ b/ruby/spec/bundler/update/gems/post_install_spec.rb @@ -10,9 +10,9 @@ gem 'thin' G - bundle! "config set #{config}" if config + bundle "config set #{config}" if config - bundle! :install + bundle :install end shared_examples "a config observer" do @@ -52,7 +52,7 @@ gem 'thin' G - bundle! :update, :all => true + bundle :update, :all => true end it_behaves_like "a post-install message outputter" @@ -67,7 +67,7 @@ gem 'thin' G - bundle! :update, :all => true + bundle :update, :all => true end it_behaves_like "a post-install message outputter" diff --git a/ruby/spec/bundler/update/git_spec.rb b/ruby/spec/bundler/update/git_spec.rb index 752033c84..0787ee41a 100644 --- a/ruby/spec/bundler/update/git_spec.rb +++ b/ruby/spec/bundler/update/git_spec.rb @@ -7,12 +7,13 @@ update_git "foo", :branch => "omg" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}", :branch => "omg" do gem 'foo' end G - update_git "foo", :branch => "omg" do |s| + update_git "foo" do |s| s.write "lib/foo.rb", "FOO = '1.1'" end @@ -27,11 +28,12 @@ s.add_dependency "activesupport", "= 3.0" end - install_gemfile! <<-G - gem "rails", :git => "#{lib_path("rails")}" + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rails", :git => "#{file_uri_for(lib_path("rails"))}" G - bundle! "update rails" + bundle "update rails" expect(the_bundle).to include_gems "rails 3.0", "activesupport 3.0" end @@ -40,12 +42,13 @@ update_git "foo", :branch => "omg", :path => lib_path("foo") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo")}", :branch => "omg" do gem 'foo' end G - update_git "foo", :branch => "omg", :path => lib_path("foo") do |s| + update_git "foo", :path => lib_path("foo") do |s| s.write "lib/foo.rb", "FOO = '1.1'" end @@ -61,7 +64,8 @@ end install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo")}" + source "#{file_uri_for(gem_repo1)}" + gem "foo", :git => "#{file_uri_for(lib_path("foo"))}" gem "bar" G @@ -79,17 +83,19 @@ build_git "foo", :path => lib_path("foo_two") install_gemfile <<-G - gem "foo", "1.0", :git => "#{lib_path("foo_one")}" + source "#{file_uri_for(gem_repo1)}" + gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_one"))}" G FileUtils.rm_rf lib_path("foo_one") install_gemfile <<-G - gem "foo", "1.0", :git => "#{lib_path("foo_two")}" + source "#{file_uri_for(gem_repo1)}" + gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_two"))}" G expect(err).to be_empty - expect(out).to include("Fetching #{lib_path}/foo_two") + expect(out).to include("Fetching #{file_uri_for(lib_path)}/foo_two") expect(out).to include("Bundle complete!") end @@ -100,6 +106,7 @@ update_git "foo", :push => "master" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :git => "#{@remote.path}" G @@ -108,11 +115,11 @@ update_git "foo", :push => "fubar" gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'foo', :git => "#{@remote.path}", :tag => "fubar" G bundle "update", :all => true - expect(exitstatus).to eq(0) if exitstatus end describe "with submodules" do @@ -131,10 +138,8 @@ s.add_dependency "submodule" end - Dir.chdir(lib_path("has_submodule-1.0")) do - sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0" - `git commit -m "submodulator"` - end + sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0") + sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0") end it "it unlocks the source when submodules are added to a git source" do @@ -160,24 +165,24 @@ end it "unlocks the source when submodules are removed from git source", :git => ">= 2.9.0" do - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" git "#{lib_path("has_submodule-1.0")}", :submodules => true do gem "has_submodule" end G - run! "require 'submodule'" + run "require 'submodule'" expect(out).to eq("GIT") - install_gemfile! <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo4)}" git "#{lib_path("has_submodule-1.0")}" do gem "has_submodule" end G - run! "require 'submodule'" + run "require 'submodule'" expect(out).to eq("GEM") end end @@ -186,12 +191,13 @@ build_git "foo", "1.0" install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}" + source "#{file_uri_for(gem_repo1)}" + gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}" G lib_path("foo-1.0").join(".git").rmtree - bundle :update, :all => true + bundle :update, :all => true, :raise_on_error => false expect(err).to include(lib_path("foo-1.0").to_s). and match(/Git error: command `git fetch.+has failed/) end @@ -205,7 +211,7 @@ install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" + gem "rack", :git => "#{file_uri_for(lib_path("rack-0.8"))}", :branch => "master" G bundle %(config set local.rack #{lib_path("local-rack")}) @@ -214,27 +220,17 @@ end it "shows the previous version of the gem" do - build_git "rails", "3.0", :path => lib_path("rails") + build_git "rails", "2.3.2", :path => lib_path("rails") install_gemfile <<-G - gem "rails", :git => "#{lib_path("rails")}" + source "#{file_uri_for(gem_repo1)}" + gem "rails", :git => "#{file_uri_for(lib_path("rails"))}" G - lockfile <<-G - GIT - remote: #{lib_path("rails")} - specs: - rails (2.3.2) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rails! - G + update_git "rails", "3.0", :path => lib_path("rails"), :gemspec => true bundle "update", :all => true - expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path("rails")} (at master@#{revision_for(lib_path("rails"))[0..6]})") + expect(out).to include("Using rails 3.0 (was 2.3.2) from #{file_uri_for(lib_path("rails"))} (at master@#{revision_for(lib_path("rails"))[0..6]})") end end @@ -259,14 +255,12 @@ bundle "update --source foo" - in_app_root do - run <<-RUBY - require 'foo' - puts "WIN" if defined?(FOO_PREV_REF) - RUBY + run <<-RUBY + require 'foo' + puts "WIN" if defined?(FOO_PREV_REF) + RUBY - expect(out).to eq("WIN") - end + expect(out).to eq("WIN") end it "unlocks gems that were originally pulled in by the source" do @@ -299,43 +293,7 @@ G end - it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "< 3" do - spec_lines = lib_path("bar/foo.gemspec").read.split("\n") - spec_lines[5] = "s.version = '2.0'" - - update_git "foo", "2.0", :path => @git.path do |s| - s.write "foo.gemspec", spec_lines.join("\n") - end - - ref = @git.ref_for "master" - - bundle "update --source bar" - - lockfile_should_be <<-G - GIT - remote: #{@git.path} - revision: #{ref} - specs: - foo (2.0) - - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "3" do + it "the --source flag updates version of gems that were originally pulled in by the source" do spec_lines = lib_path("bar/foo.gemspec").read.split("\n") spec_lines[5] = "s.version = '2.0'" @@ -347,7 +305,7 @@ bundle "update --source bar" - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{@git.path} revision: #{ref} diff --git a/ruby/spec/bundler/update/path_spec.rb b/ruby/spec/bundler/update/path_spec.rb index 38c125e04..756770313 100644 --- a/ruby/spec/bundler/update/path_spec.rb +++ b/ruby/spec/bundler/update/path_spec.rb @@ -6,6 +6,7 @@ build_lib "activesupport", "2.3.5", :path => lib_path("rails/activesupport") install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "activesupport", :path => "#{lib_path("rails/activesupport")}" G diff --git a/ruby/spec/bundler/update/redownload_spec.rb b/ruby/spec/bundler/update/redownload_spec.rb index b34a02c78..147be823f 100644 --- a/ruby/spec/bundler/update/redownload_spec.rb +++ b/ruby/spec/bundler/update/redownload_spec.rb @@ -10,24 +10,24 @@ describe "with --force" do it "shows a deprecation when single flag passed", :bundler => 2 do - bundle! "update rack --force" + bundle "update rack --force" expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end it "shows a deprecation when multiple flags passed", :bundler => 2 do - bundle! "update rack --no-color --force" + bundle "update rack --no-color --force" expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end end describe "with --redownload" do it "does not show a deprecation when single flag passed" do - bundle! "update rack --redownload" + bundle "update rack --redownload" expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end it "does not show a deprecation when single multiple flags passed" do - bundle! "update rack --no-color --redownload" + bundle "update rack --no-color --redownload" expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`" end end diff --git a/ruby/spec/default.mspec b/ruby/spec/default.mspec index 8791058f9..2dbaeb83d 100644 --- a/ruby/spec/default.mspec +++ b/ruby/spec/default.mspec @@ -9,22 +9,20 @@ OBJDIR = File.expand_path("spec/ruby/optional/capi/ext") class MSpecScript builddir = Dir.pwd srcdir = ENV['SRCDIR'] - if !srcdir and File.exist?("#{builddir}/Makefile") then - File.open("#{builddir}/Makefile", "r:US-ASCII") {|f| - f.read[/^\s*srcdir\s*=\s*(.+)/i] and srcdir = $1 - } - end - srcdir = File.expand_path(srcdir) + srcdir ||= File.read("Makefile", encoding: "US-ASCII")[/^\s*srcdir\s*=\s*(.+)/i, 1] rescue nil config = RbConfig::CONFIG # The default implementation to run the specs. set :target, File.join(builddir, "miniruby#{config['exeext']}") set :prefix, File.expand_path('ruby', File.dirname(__FILE__)) - set :flags, %W[ - -I#{srcdir}/lib - #{srcdir}/tool/runruby.rb --archdir=#{Dir.pwd} --extout=#{config['EXTOUT']} - -- - ] + if srcdir + srcdir = File.expand_path(srcdir) + set :flags, %W[ + -I#{srcdir}/lib + #{srcdir}/tool/runruby.rb --archdir=#{builddir} --extout=#{config['EXTOUT']} + -- + ] + end end module MSpecScript::JobServer diff --git a/ruby/spec/mspec/.rspec b/ruby/spec/mspec/.rspec new file mode 100644 index 000000000..4e1e0d2f7 --- /dev/null +++ b/ruby/spec/mspec/.rspec @@ -0,0 +1 @@ +--color diff --git a/ruby/spec/mspec/Gemfile b/ruby/spec/mspec/Gemfile index 3dc3c4145..617a995ca 100644 --- a/ruby/spec/mspec/Gemfile +++ b/ruby/spec/mspec/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' -gem "rake", "~> 10.0" -gem "rspec", "~> 2.14.1" +gem "rake", "~> 12.3" +gem "rspec", "~> 3.0" diff --git a/ruby/spec/mspec/Gemfile.lock b/ruby/spec/mspec/Gemfile.lock index ce0aa9841..cd3990604 100644 --- a/ruby/spec/mspec/Gemfile.lock +++ b/ruby/spec/mspec/Gemfile.lock @@ -1,21 +1,26 @@ GEM remote: https://rubygems.org/ specs: - diff-lcs (1.3) - rake (10.5.0) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.8) - rspec-expectations (2.14.5) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) + diff-lcs (1.4.4) + rake (12.3.3) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.2) PLATFORMS java ruby DEPENDENCIES - rake (~> 10.0) - rspec (~> 2.14.1) + rake (~> 12.3) + rspec (~> 3.0) diff --git a/ruby/spec/mspec/README.md b/ruby/spec/mspec/README.md index e6fe44c6a..94ab60803 100644 --- a/ruby/spec/mspec/README.md +++ b/ruby/spec/mspec/README.md @@ -1,5 +1,3 @@ -[![Build Status](https://travis-ci.org/ruby/mspec.svg?branch=master)](https://travis-ci.org/ruby/mspec) - ## Overview MSpec is a specialized framework that is syntax-compatible with RSpec 2 for @@ -38,7 +36,7 @@ specs in a manner compatible with multiple Ruby implementations. ## Requirements -MSpec requires Ruby 2.4 or more recent. +MSpec requires Ruby 2.6 or more recent. ## Bundler @@ -55,7 +53,7 @@ To install the gem dependencies with Bundler, run the following: ruby -S bundle install ``` -## Running Specs +## Development Use RSpec to run the MSpec specs. There are no plans currently to make the MSpec specs runnable by MSpec: https://github.com/ruby/mspec/issues/19. diff --git a/ruby/spec/mspec/lib/mspec/expectations/should.rb b/ruby/spec/mspec/lib/mspec/expectations/should.rb index 231ad15c2..c1790e0ac 100644 --- a/ruby/spec/mspec/lib/mspec/expectations/should.rb +++ b/ruby/spec/mspec/lib/mspec/expectations/should.rb @@ -1,12 +1,18 @@ class Object NO_MATCHER_GIVEN = Object.new - def should(matcher = NO_MATCHER_GIVEN) + def should(matcher = NO_MATCHER_GIVEN, &block) MSpec.expectation - MSpec.actions :expectation, MSpec.current.state + state = MSpec.current.state + raise "should outside example" unless state + MSpec.actions :expectation, state + if NO_MATCHER_GIVEN.equal?(matcher) SpecPositiveOperatorMatcher.new(self) else + # The block was given to #should syntactically, but it was intended for a matcher like #raise_error + matcher.block = block if block + unless matcher.matches? self expected, actual = matcher.failure_message SpecExpectation.fail_with(expected, actual) @@ -14,12 +20,18 @@ def should(matcher = NO_MATCHER_GIVEN) end end - def should_not(matcher = NO_MATCHER_GIVEN) + def should_not(matcher = NO_MATCHER_GIVEN, &block) MSpec.expectation - MSpec.actions :expectation, MSpec.current.state + state = MSpec.current.state + raise "should_not outside example" unless state + MSpec.actions :expectation, state + if NO_MATCHER_GIVEN.equal?(matcher) SpecNegativeOperatorMatcher.new(self) else + # The block was given to #should_not syntactically, but it was intended for the matcher + matcher.block = block if block + if matcher.matches? self expected, actual = matcher.negative_failure_message SpecExpectation.fail_with(expected, actual) diff --git a/ruby/spec/mspec/lib/mspec/guards/bug.rb b/ruby/spec/mspec/lib/mspec/guards/bug.rb index b1bfc6413..a6af0ef96 100644 --- a/ruby/spec/mspec/lib/mspec/guards/bug.rb +++ b/ruby/spec/mspec/lib/mspec/guards/bug.rb @@ -1,28 +1,29 @@ require 'mspec/guards/version' class BugGuard < VersionGuard - def initialize(bug, version) + def initialize(bug, requirement) @bug = bug - if String === version + if String === requirement MSpec.deprecate "ruby_bug with a single version", 'an exclusive range ("2.1"..."2.3")' - @version = SpecVersion.new version, true + super(FULL_RUBY_VERSION, requirement) + @requirement = SpecVersion.new requirement, true else - super(version) + super(FULL_RUBY_VERSION, requirement) end - @parameters = [@bug, @version] end def match? return false if MSpec.mode? :no_ruby_bug return false unless PlatformGuard.standard? - if Range === @version + + if Range === @requirement super else - FULL_RUBY_VERSION <= @version + FULL_RUBY_VERSION <= @requirement end end end -def ruby_bug(bug, version, &block) - BugGuard.new(bug, version).run_unless(:ruby_bug, &block) +def ruby_bug(bug, requirement, &block) + BugGuard.new(bug, requirement).run_unless(:ruby_bug, &block) end diff --git a/ruby/spec/mspec/lib/mspec/guards/guard.rb b/ruby/spec/mspec/lib/mspec/guards/guard.rb index 322a08145..3a6372a66 100644 --- a/ruby/spec/mspec/lib/mspec/guards/guard.rb +++ b/ruby/spec/mspec/lib/mspec/guards/guard.rb @@ -111,7 +111,7 @@ def record(description) def add(example) record example.description - MSpec.retrieve(:formatter).tally.counter.guards! + MSpec.formatter.tally.counter.guards! end def unregister diff --git a/ruby/spec/mspec/lib/mspec/guards/platform.rb b/ruby/spec/mspec/lib/mspec/guards/platform.rb index 2d22d4fb5..2d5c2de6b 100644 --- a/ruby/spec/mspec/lib/mspec/guards/platform.rb +++ b/ruby/spec/mspec/lib/mspec/guards/platform.rb @@ -26,8 +26,11 @@ def self.standard? def self.os?(*oses) oses.any? do |os| raise ":java is not a valid OS" if os == :java - if os == :windows + case os + when :windows PLATFORM =~ /(mswin|mingw)/ + when :wsl + wsl? else PLATFORM.include?(os.to_s) end @@ -38,6 +41,14 @@ def self.windows? os?(:windows) end + def self.wsl? + if defined?(@wsl_p) + @wsl_p + else + @wsl_p = `uname -r`.match?(/microsoft/i) + end + end + WORD_SIZE = 1.size * 8 POINTER_SIZE = begin diff --git a/ruby/spec/mspec/lib/mspec/guards/version.rb b/ruby/spec/mspec/lib/mspec/guards/version.rb index cb08fdac7..20f8c06d3 100644 --- a/ruby/spec/mspec/lib/mspec/guards/version.rb +++ b/ruby/spec/mspec/lib/mspec/guards/version.rb @@ -5,33 +5,40 @@ class VersionGuard < SpecGuard FULL_RUBY_VERSION = SpecVersion.new SpecGuard.ruby_version(:full) - def initialize(version) - case version + def initialize(version, requirement) + version = SpecVersion.new(version) unless SpecVersion === version + @version = version + + case requirement when String - @version = SpecVersion.new version + @requirement = SpecVersion.new requirement when Range - MSpec.deprecate "an empty version range end", 'a specific version' if version.end.empty? - a = SpecVersion.new version.begin - b = SpecVersion.new version.end - unless version.exclude_end? + MSpec.deprecate "an empty version range end", 'a specific version' if requirement.end.empty? + a = SpecVersion.new requirement.begin + b = SpecVersion.new requirement.end + unless requirement.exclude_end? MSpec.deprecate "ruby_version_is with an inclusive range", 'an exclusive range ("2.1"..."2.3")' end - @version = version.exclude_end? ? a...b : a..b + @requirement = requirement.exclude_end? ? a...b : a..b else - raise "version must be a String or Range but was a #{version.class}" + raise "version must be a String or Range but was a #{requirement.class}" end - @parameters = [version] + super(@version, @requirement) end def match? - if Range === @version - @version.include? FULL_RUBY_VERSION + if Range === @requirement + @requirement.include? @version else - FULL_RUBY_VERSION >= @version + @version >= @requirement end end end -def ruby_version_is(*args, &block) - VersionGuard.new(*args).run_if(:ruby_version_is, &block) +def version_is(base_version, requirement, &block) + VersionGuard.new(base_version, requirement).run_if(:version_is, &block) +end + +def ruby_version_is(requirement, &block) + VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, requirement).run_if(:ruby_version_is, &block) end diff --git a/ruby/spec/mspec/lib/mspec/helpers.rb b/ruby/spec/mspec/lib/mspec/helpers.rb index b7ac9f4e8..90f9fd3fd 100644 --- a/ruby/spec/mspec/lib/mspec/helpers.rb +++ b/ruby/spec/mspec/lib/mspec/helpers.rb @@ -3,7 +3,6 @@ require 'mspec/helpers/datetime' require 'mspec/helpers/fixture' require 'mspec/helpers/flunk' -require 'mspec/helpers/frozen_error_class' require 'mspec/helpers/fs' require 'mspec/helpers/io' require 'mspec/helpers/mock_to_path' diff --git a/ruby/spec/mspec/lib/mspec/helpers/frozen_error_class.rb b/ruby/spec/mspec/lib/mspec/helpers/frozen_error_class.rb deleted file mode 100644 index 07cc2b4ba..000000000 --- a/ruby/spec/mspec/lib/mspec/helpers/frozen_error_class.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'mspec/guards/version' - -# This helper makes it easy to write version independent -# specs for frozen objects. -unless respond_to? :frozen_error_class, true - ruby_version_is "2.5" do - def frozen_error_class - FrozenError - end - end - - ruby_version_is ""..."2.5" do - def frozen_error_class - RuntimeError - end - end -end diff --git a/ruby/spec/mspec/lib/mspec/helpers/io.rb b/ruby/spec/mspec/lib/mspec/helpers/io.rb index 1938255d1..29c6c37a1 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/io.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/io.rb @@ -85,7 +85,3 @@ def new_io(name, mode = "w:utf-8") File.new(name, mode) end end - -def find_unused_fd - Dir.entries("/dev/fd").map(&:to_i).max + 1 -end diff --git a/ruby/spec/mspec/lib/mspec/helpers/numeric.rb b/ruby/spec/mspec/lib/mspec/helpers/numeric.rb index c6c2e8272..db1fde64d 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/numeric.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/numeric.rb @@ -12,6 +12,14 @@ def bignum_value(plus = 0) 0x8000_0000_0000_0000 + plus end +def max_long + 2**(0.size * 8 - 1) - 1 +end + +def min_long + -(2**(0.size * 8 - 1)) +end + # This is a bit hairy, but we need to be able to write specs that cover the # boundary between Fixnum and Bignum for operations like Fixnum#<<. Since # this boundary is implementation-dependent, we use these helpers to write diff --git a/ruby/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/ruby/spec/mspec/lib/mspec/helpers/ruby_exe.rb index 6d5470bbb..4948ec09f 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/ruby_exe.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/ruby_exe.rb @@ -15,8 +15,10 @@ # # `#{RUBY_EXE} 'path/to/some/file.rb'` # -# The ruby_exe helper also accepts an options hash with three -# keys: :options, :args and :env. For example: +# The ruby_exe helper also accepts an options hash with four +# keys: :options, :args :env and :exception. +# +# For example: # # ruby_exe('file.rb', :options => "-w", # :args => "arg1 arg2", @@ -28,6 +30,9 @@ # # with access to ENV["FOO"] with value "bar". # +# When `exception: false` and Ruby command fails then exception will not be +# raised. +# # If +nil+ is passed for the first argument, the command line # will be built only from the options hash. # @@ -52,6 +57,8 @@ # (with -T on the command line or in the config with set :flags) # will be appended to RUBY_EXE so that the interpreter # is always called with those flags. +# +# Failure of a Ruby command leads to raising exception by default. def ruby_exe_options(option) case option @@ -128,9 +135,21 @@ def ruby_exe(code = :not_given, opts = {}) code = tmpfile end + expected_status = opts.fetch(:exit_status, 0) + begin platform_is_not :opal do - `#{ruby_cmd(code, opts)}` + command = ruby_cmd(code, opts) + output = `#{command}` + + exit_status = Process.last_status.exitstatus + if exit_status != expected_status + formatted_output = output.lines.map { |line| " #{line}" }.join + raise SpecExpectationNotMetError, + "Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}" + end + + output end ensure saved_env.each { |key, value| ENV[key] = value } @@ -153,5 +172,7 @@ def ruby_cmd(code, opts = {}) body = "-e #{code.inspect}" end - [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ') + command = [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ') + STDERR.puts "\nruby_cmd: #{command}" if ENV["DEBUG_MSPEC_RUBY_CMD"] == "true" + command end diff --git a/ruby/spec/mspec/lib/mspec/helpers/scratch.rb b/ruby/spec/mspec/lib/mspec/helpers/scratch.rb index a6b0c0274..0da3315cd 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/scratch.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/scratch.rb @@ -14,4 +14,8 @@ def self.<<(arg) def self.recorded @record end + + def self.inspect + "" + end end diff --git a/ruby/spec/mspec/lib/mspec/helpers/tmp.rb b/ruby/spec/mspec/lib/mspec/helpers/tmp.rb index 1677fb4f1..b2a38ee98 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/tmp.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/tmp.rb @@ -3,11 +3,16 @@ # should clean up any temporary files created so that the temp # directory is empty when the process exits. -SPEC_TEMP_DIR = File.expand_path(ENV["SPEC_TEMP_DIR"] || "rubyspec_temp") +SPEC_TEMP_DIR_PID = Process.pid -SPEC_TEMP_UNIQUIFIER = "0" +if spec_temp_dir = ENV["SPEC_TEMP_DIR"] + spec_temp_dir = File.realdirpath(spec_temp_dir) +else + spec_temp_dir = "#{File.realpath(Dir.pwd)}/rubyspec_temp/#{SPEC_TEMP_DIR_PID}" +end +SPEC_TEMP_DIR = spec_temp_dir -SPEC_TEMP_DIR_PID = Process.pid +SPEC_TEMP_UNIQUIFIER = "0" at_exit do begin @@ -31,7 +36,7 @@ end def tmp(name, uniquify = true) - Dir.mkdir SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR + mkdir_p SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR if uniquify and !name.empty? slash = name.rindex "/" diff --git a/ruby/spec/mspec/lib/mspec/helpers/warning.rb b/ruby/spec/mspec/lib/mspec/helpers/warning.rb index f94551c18..e3d72b78b 100644 --- a/ruby/spec/mspec/lib/mspec/helpers/warning.rb +++ b/ruby/spec/mspec/lib/mspec/helpers/warning.rb @@ -1,5 +1,7 @@ require 'mspec/guards/version' +# You might be looking for #silence_warnings, use #suppress_warning instead. +# MSpec calls it #suppress_warning for consistency with EnvUtil.suppress_warning in CRuby test/. def suppress_warning verbose = $VERBOSE $VERBOSE = nil diff --git a/ruby/spec/mspec/lib/mspec/matchers/include.rb b/ruby/spec/mspec/lib/mspec/matchers/include.rb index 0b7eaf3ce..3f07f3554 100644 --- a/ruby/spec/mspec/lib/mspec/matchers/include.rb +++ b/ruby/spec/mspec/lib/mspec/matchers/include.rb @@ -15,11 +15,11 @@ def matches?(actual) end def failure_message - ["Expected #{@actual.inspect}", "to include #{@element.inspect}"] + ["Expected #{MSpec.format(@actual)}", "to include #{MSpec.format(@element)}"] end def negative_failure_message - ["Expected #{@actual.inspect}", "not to include #{@element.inspect}"] + ["Expected #{MSpec.format(@actual)}", "not to include #{MSpec.format(@element)}"] end end diff --git a/ruby/spec/mspec/lib/mspec/matchers/match_yaml.rb b/ruby/spec/mspec/lib/mspec/matchers/match_yaml.rb index 920d85a14..30561627c 100644 --- a/ruby/spec/mspec/lib/mspec/matchers/match_yaml.rb +++ b/ruby/spec/mspec/lib/mspec/matchers/match_yaml.rb @@ -30,7 +30,11 @@ def clean_yaml(yaml) def valid_yaml?(obj) require 'yaml' begin - YAML.load(obj) + if YAML.respond_to?(:unsafe_load) + YAML.unsafe_load(obj) + else + YAML.load(obj) + end rescue false else diff --git a/ruby/spec/mspec/lib/mspec/matchers/raise_error.rb b/ruby/spec/mspec/lib/mspec/matchers/raise_error.rb index 0e57c1b86..0ee895351 100644 --- a/ruby/spec/mspec/lib/mspec/matchers/raise_error.rb +++ b/ruby/spec/mspec/lib/mspec/matchers/raise_error.rb @@ -1,4 +1,6 @@ class RaiseErrorMatcher + attr_writer :block + def initialize(exception, message, &block) @exception = exception @message = message @@ -6,34 +8,43 @@ def initialize(exception, message, &block) @actual = nil end + # This #matches? method is unusual because it doesn't always return a boolean but instead + # re-raises the original exception if proc.call raises an exception and #matching_exception? is false. + # The reasoning is the original exception class matters and we don't want to change it by raising another exception, + # so instead we attach the #failure_message and extract it in ExceptionState#message. def matches?(proc) @result = proc.call return false rescue Exception => actual @actual = actual + if matching_exception?(actual) # The block has its own expectations and will throw an exception if it fails @block[actual] if @block - return true else + actual.instance_variable_set(:@mspec_raise_error_message, failure_message) raise actual end end - def matching_exception?(exc) - return false unless @exception === exc + def matching_class?(exc) + @exception === exc + end - if @message then - case @message - when String - return false if @message != exc.message - when Regexp - return false if @message !~ exc.message - end + def matching_message?(exc) + case @message + when String + @message == exc.message + when Regexp + @message =~ exc.message + else + true end + end - return true + def matching_exception?(exc) + matching_class?(exc) and matching_message?(exc) end def exception_class_and_message(exception_class, message) @@ -56,7 +67,7 @@ def failure_message message = ["Expected #{format_expected_exception}"] if @actual - message << "but got #{format_exception(@actual)}" + message << "but got: #{format_exception(@actual)}" else message << "but no exception was raised (#{MSpec.format(@result)} was returned)" end @@ -67,7 +78,7 @@ def failure_message def negative_failure_message message = ["Expected to not get #{format_expected_exception}", ""] unless @actual.class == @exception - message[1] = "but got #{format_exception(@actual)}" + message[1] = "but got: #{format_exception(@actual)}" end message end diff --git a/ruby/spec/mspec/lib/mspec/mocks/mock.rb b/ruby/spec/mspec/lib/mspec/mocks/mock.rb index bce41b630..28a083cc1 100644 --- a/ruby/spec/mspec/lib/mspec/mocks/mock.rb +++ b/ruby/spec/mspec/lib/mspec/mocks/mock.rb @@ -180,7 +180,7 @@ def self.verify_call(obj, sym, *args, &block) mock_respond_to? obj, *args else SpecExpectation.fail_with("Mock '#{name_or_inspect obj}': method #{sym}\n", - "called with unexpected arguments #{inspect_args compare}") + "called with unexpected arguments #{inspect_args args}") end end diff --git a/ruby/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb b/ruby/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb index fd0a3efe1..abfb6dd0e 100644 --- a/ruby/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb +++ b/ruby/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb @@ -1,9 +1,14 @@ class ConstantsLockFile LOCK_FILE_NAME = '.mspec.constants' + def self.lock_file + @prefix ||= File.expand_path(MSpecScript.get(:prefix) || '.') + "#{@prefix}/#{LOCK_FILE_NAME}" + end + def self.load - if File.exist?(LOCK_FILE_NAME) - File.readlines(LOCK_FILE_NAME).map(&:chomp) + if File.exist?(lock_file) + File.readlines(lock_file).map(&:chomp) else [] end @@ -11,7 +16,7 @@ def self.load def self.dump(ary) contents = ary.map(&:to_s).uniq.sort.join("\n") + "\n" - File.write(LOCK_FILE_NAME, contents) + File.write(lock_file, contents) end end diff --git a/ruby/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/ruby/spec/mspec/lib/mspec/runner/actions/leakchecker.rb index f70799d90..596b120d9 100644 --- a/ruby/spec/mspec/lib/mspec/runner/actions/leakchecker.rb +++ b/ruby/spec/mspec/lib/mspec/runner/actions/leakchecker.rb @@ -36,6 +36,7 @@ def initialize @thread_info = find_threads @env_info = find_env @argv_info = find_argv + @globals_info = find_globals @encoding_info = find_encodings end @@ -48,8 +49,10 @@ def check(state) check_process_leak check_env check_argv + check_globals check_encodings - GC.start if !@leaks.empty? + check_tracepoints + GC.start unless @leaks.empty? @leaks.empty? end @@ -243,6 +246,19 @@ def check_argv end end + def find_globals + { verbose: $VERBOSE, debug: $DEBUG } + end + + def check_globals + old_globals = @globals_info + new_globals = find_globals + if new_globals != old_globals + leak "Globals changed: #{old_globals.inspect} to #{new_globals.inspect}" + @globals_info = new_globals + end + end + def find_encodings [Encoding.default_internal, Encoding.default_external] end @@ -259,6 +275,14 @@ def check_encodings @encoding_info = [new_internal, new_external] end + def check_tracepoints + ObjectSpace.each_object(TracePoint) do |tp| + if tp.enabled? + leak "TracePoint is still enabled: #{tp.inspect}" + end + end + end + def leak(message) if @leaks.empty? $stderr.puts "\n" diff --git a/ruby/spec/mspec/lib/mspec/runner/actions/timeout.rb b/ruby/spec/mspec/lib/mspec/runner/actions/timeout.rb index 03fe14811..c85bf49ad 100644 --- a/ruby/spec/mspec/lib/mspec/runner/actions/timeout.rb +++ b/ruby/spec/mspec/lib/mspec/runner/actions/timeout.rb @@ -37,7 +37,7 @@ def start if elapsed > @timeout STDERR.puts "\n#{@current_state.description}" STDERR.flush - abort "Example took #{now - @started}s, which is longer than the timeout of #{@timeout}s" + abort "Example took longer than the configured timeout of #{@timeout}s" end end end diff --git a/ruby/spec/mspec/lib/mspec/runner/context.rb b/ruby/spec/mspec/lib/mspec/runner/context.rb index 5f6c9c8ae..62483590b 100644 --- a/ruby/spec/mspec/lib/mspec/runner/context.rb +++ b/ruby/spec/mspec/lib/mspec/runner/context.rb @@ -12,15 +12,14 @@ class ContextState attr_reader :state, :parent, :parents, :children, :examples, :to_s - def initialize(mod, options = nil) - @to_s = mod.to_s - if options.is_a? Hash - @options = options - else - @to_s += "#{".:#".include?(options[0,1]) ? "" : " "}#{options}" if options - @options = { } - end - @options[:shared] ||= false + MOCK_VERIFY = -> { Mock.verify_count } + MOCK_CLEANUP = -> { Mock.cleanup } + EXPECTATION_MISSING = -> { raise SpecExpectationNotFoundError } + + def initialize(description, options = nil) + raise "#describe options should be a Hash or nil" unless Hash === options or options.nil? + @to_s = description.to_s + @shared = options && options[:shared] @parsed = false @before = { :all => [], :each => [] } @@ -28,13 +27,10 @@ def initialize(mod, options = nil) @pre = {} @post = {} @examples = [] + @state = nil @parent = nil @parents = [self] @children = [] - - @mock_verify = Proc.new { Mock.verify_count } - @mock_cleanup = Proc.new { Mock.cleanup } - @expectation_missing = Proc.new { raise SpecExpectationNotFoundError } end # Remove caching when a ContextState is dup'd for shared specs. @@ -46,7 +42,7 @@ def initialize_copy(other) # Returns true if this is a shared +ContextState+. Essentially, when # created with: describe "Something", :shared => true { ... } def shared? - return @options[:shared] + @shared end # Set the parent (enclosing) +ContextState+ for this state. Creates @@ -127,6 +123,7 @@ def after(what, &block) # Creates an ExampleState instance for the block and stores it # in a list of examples to evaluate unless the example is filtered. def it(desc, &block) + raise "nested #it" if @state example = ExampleState.new(self, desc, block) MSpec.actions :add, example return if MSpec.guarded? @@ -205,7 +202,7 @@ def process if protect "before :all", pre(:all) @examples.each do |state| MSpec.repeat do - @state = state + @state = state example = state.example MSpec.actions :before, state @@ -214,20 +211,20 @@ def process if example passed = protect nil, example MSpec.actions :example, state, example - protect nil, @expectation_missing if !MSpec.expectation? and passed + protect nil, EXPECTATION_MISSING if !MSpec.expectation? and passed end end protect "after :each", post(:each) - protect "Mock.verify_count", @mock_verify + protect "Mock.verify_count", MOCK_VERIFY - protect "Mock.cleanup", @mock_cleanup + protect "Mock.cleanup", MOCK_CLEANUP MSpec.actions :after, state @state = nil end end protect "after :all", post(:all) else - protect "Mock.cleanup", @mock_cleanup + protect "Mock.cleanup", MOCK_CLEANUP end MSpec.actions :leave diff --git a/ruby/spec/mspec/lib/mspec/runner/example.rb b/ruby/spec/mspec/lib/mspec/runner/example.rb index 82feba0b0..0d9f0d618 100644 --- a/ruby/spec/mspec/lib/mspec/runner/example.rb +++ b/ruby/spec/mspec/lib/mspec/runner/example.rb @@ -3,12 +3,12 @@ # Holds some of the state of the example (i.e. +it+ block) that is # being evaluated. See also +ContextState+. class ExampleState - attr_reader :context, :it, :example + attr_reader :context, :it, :example def initialize(context, it, example = nil) - @context = context - @it = it - @example = example + @context = context + @it = it + @example = example end def context=(context) @@ -25,8 +25,8 @@ def description end def filtered? - incl = MSpec.retrieve(:include) || [] - excl = MSpec.retrieve(:exclude) || [] + incl = MSpec.include + excl = MSpec.exclude included = incl.empty? || incl.any? { |f| f === description } included &&= excl.empty? || !excl.any? { |f| f === description } !included diff --git a/ruby/spec/mspec/lib/mspec/runner/exception.rb b/ruby/spec/mspec/lib/mspec/runner/exception.rb index 0d9bb4310..e07f02f68 100644 --- a/ruby/spec/mspec/lib/mspec/runner/exception.rb +++ b/ruby/spec/mspec/lib/mspec/runner/exception.rb @@ -6,6 +6,7 @@ class ExceptionState def initialize(state, location, exception) @exception = exception + @failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError @description = location ? "An exception occurred during: #{location}" : "" if state @@ -19,25 +20,35 @@ def initialize(state, location, exception) end def failure? - [SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e } + @failure end def message - if @exception.message.empty? - "" - elsif @exception.class == SpecExpectationNotMetError || - @exception.class == SpecExpectationNotFoundError - @exception.message + message = @exception.message + message = "" if message.empty? + + if @failure + message + elsif raise_error_message = @exception.instance_variable_get(:@mspec_raise_error_message) + raise_error_message.join("\n") else - "#{@exception.class}: #{@exception.message}" + "#{@exception.class}: #{message}" end end def backtrace - @backtrace_filter ||= MSpecScript.config[:backtrace_filter] + @backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)} bt = @exception.backtrace || [] - - bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n") + unless $MSPEC_DEBUG + # Exclude + print <<-XML + XML if h[:exception] outcome = h[:test].failure? ? "failure" : "error" diff --git a/ruby/spec/mspec/lib/mspec/runner/formatters/method.rb b/ruby/spec/mspec/lib/mspec/runner/formatters/method.rb index 8fe02575c..925858c84 100644 --- a/ruby/spec/mspec/lib/mspec/runner/formatters/method.rb +++ b/ruby/spec/mspec/lib/mspec/runner/formatters/method.rb @@ -6,13 +6,13 @@ class MethodFormatter < BaseFormatter def initialize(out = nil) super(out) @methods = Hash.new do |h, k| - hash = {} - hash[:examples] = 0 - hash[:expectations] = 0 - hash[:failures] = 0 - hash[:errors] = 0 - hash[:exceptions] = [] - h[k] = hash + h[k] = { + examples: 0, + expectations: 0, + failures: 0, + errors: 0, + exceptions: [] + } end end diff --git a/ruby/spec/mspec/lib/mspec/runner/formatters/spinner.rb b/ruby/spec/mspec/lib/mspec/runner/formatters/spinner.rb index 8815e1a48..817d8c02b 100644 --- a/ruby/spec/mspec/lib/mspec/runner/formatters/spinner.rb +++ b/ruby/spec/mspec/lib/mspec/runner/formatters/spinner.rb @@ -78,7 +78,7 @@ def clear_progress_line # Callback for the MSpec :start event. Stores the total # number of files that will be processed. def start - @total = MSpec.retrieve(:files).size + @total = MSpec.files_array.size compute_progress print progress_line end diff --git a/ruby/spec/mspec/lib/mspec/runner/formatters/stats.rb b/ruby/spec/mspec/lib/mspec/runner/formatters/stats.rb new file mode 100644 index 000000000..8cff96d14 --- /dev/null +++ b/ruby/spec/mspec/lib/mspec/runner/formatters/stats.rb @@ -0,0 +1,57 @@ +require 'mspec/runner/formatters/base' + +class StatsPerFileFormatter < BaseFormatter + def initialize(out = nil) + super(out) + @data = {} + @root = File.expand_path(MSpecScript.get(:prefix) || '.') + end + + def register + super + MSpec.register :load, self + MSpec.register :unload, self + end + + # Resets the tallies so the counts are only for this file. + def load + tally.counter.examples = 0 + tally.counter.errors = 0 + tally.counter.failures = 0 + tally.counter.tagged = 0 + end + + def unload + file = format_file MSpec.file + + raise if @data.key?(file) + @data[file] = { + examples: tally.counter.examples, + errors: tally.counter.errors, + failures: tally.counter.failures, + tagged: tally.counter.tagged, + } + end + + def finish + width = @data.keys.max_by(&:size).size + f = "%3d" + @data.each_pair do |file, data| + total = data[:examples] + passing = total - data[:errors] - data[:failures] - data[:tagged] + puts "#{file.ljust(width)} #{f % passing}/#{f % total}" + end + + require 'yaml' + yaml = YAML.dump(@data) + File.write "results-#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}.yml", yaml + end + + private def format_file(file) + if file.start_with?(@root) + file[@root.size+1..-1] + else + raise file + end + end +end diff --git a/ruby/spec/mspec/lib/mspec/runner/mspec.rb b/ruby/spec/mspec/lib/mspec/runner/mspec.rb index 5528f27cf..833108619 100644 --- a/ruby/spec/mspec/lib/mspec/runner/mspec.rb +++ b/ruby/spec/mspec/lib/mspec/runner/mspec.rb @@ -10,7 +10,6 @@ class MSpecEnv end module MSpec - @exit = nil @abort = nil @start = nil @@ -20,8 +19,8 @@ module MSpec @after = nil @leave = nil @finish = nil - @exclude = nil - @include = nil + @exclude = [] + @include = [] @leave = nil @load = nil @unload = nil @@ -33,13 +32,19 @@ module MSpec @guarded = [] @features = {} @exception = nil - @randomize = nil - @repeat = nil + @randomize = false + @repeat = 1 @expectation = nil @expectations = false - def self.describe(mod, options = nil, &block) - state = ContextState.new mod, options + class << self + attr_reader :file, :include, :exclude + attr_writer :repeat, :randomize + attr_accessor :formatter + end + + def self.describe(description, options = nil, &block) + state = ContextState.new description, options state.parent = current MSpec.register_current state @@ -57,6 +62,10 @@ def self.process actions :finish end + def self.files_array + @files + end + def self.each_file(&block) if ENV["MSPEC_MULTI"] while file = STDIN.gets @@ -74,7 +83,7 @@ def self.each_file(&block) # The parent closed the connection without QUIT abort "the parent did not send QUIT" else - return unless files = retrieve(:files) + return unless files = @files shuffle files if randomize? files.each(&block) end @@ -83,10 +92,11 @@ def self.each_file(&block) def self.files each_file do |file| setup_env - store :file, file + @file = file actions :load protect("loading #{file}") { Kernel.load file } actions :unload + raise "#{file} was executed but did not reset the current example: #{@current}" if @current end end @@ -101,7 +111,7 @@ def self.actions(action, *args) def self.protect(location, &block) begin - @env.instance_eval(&block) + @env.instance_exec(&block) return true rescue SystemExit => e raise e @@ -130,22 +140,24 @@ def self.guarded? # Sets the toplevel ContextState to +state+. def self.register_current(state) - store :current, state + @current = state end # Sets the toplevel ContextState to +nil+. def self.clear_current - store :current, nil + @current = nil end # Returns the toplevel ContextState. def self.current - retrieve :current + @current end # Stores the shared ContextState keyed by description. def self.register_shared(state) - @shared[state.to_s] = state + name = state.to_s + raise "duplicated shared #describe: #{name}" if @shared.key?(name) + @shared[name] = state end # Returns the shared ContextState matching description. @@ -155,17 +167,17 @@ def self.retrieve_shared(desc) # Stores the exit code used by the runner scripts. def self.register_exit(code) - store :exit, code + @exit = code end # Retrieves the stored exit code. def self.exit_code - retrieve(:exit).to_i + @exit.to_i end # Stores the list of files to be evaluated. def self.register_files(files) - store :files, files + @files = files end # Stores one or more substitution patterns for transforming @@ -176,7 +188,7 @@ def self.register_files(files) # # See also +tags_file+. def self.register_tags_patterns(patterns) - store :tags_patterns, patterns + @tags_patterns = patterns end # Registers an operating mode. Modes recognized by MSpec: @@ -187,30 +199,30 @@ def self.register_tags_patterns(patterns) # :report - specs that are guarded are reported # :unguarded - all guards are forced off def self.register_mode(mode) - modes = retrieve :modes + modes = @modes modes << mode unless modes.include? mode end # Clears all registered modes. def self.clear_modes - store :modes, [] + @modes = [] end # Returns +true+ if +mode+ is registered. def self.mode?(mode) - retrieve(:modes).include? mode + @modes.include? mode end def self.enable_feature(feature) - retrieve(:features)[feature] = true + @features[feature] = true end def self.disable_feature(feature) - retrieve(:features)[feature] = false + @features[feature] = false end def self.feature_enabled?(feature) - retrieve(:features)[feature] || false + @features[feature] || false end def self.retrieve(symbol) @@ -259,21 +271,17 @@ def self.unregister(symbol, action) end end - def self.randomize(flag = true) - @randomize = flag - end - def self.randomize? - @randomize == true - end - - def self.repeat=(times) - @repeat = times + @randomize end def self.repeat - (@repeat || 1).times do + if @repeat == 1 yield + else + @repeat.times do + yield + end end end @@ -289,17 +297,17 @@ def self.shuffle(ary) # Records that an expectation has been encountered in an example. def self.expectation - store :expectations, true + @expectations = true end # Returns true if an expectation has been encountered def self.expectation? - retrieve :expectations + @expectations end # Resets the flag that an expectation has been encountered in an example. def self.clear_expectations - store :expectations, false + @expectations = false end # Transforms a spec filename into a tags filename by applying each @@ -313,9 +321,9 @@ def self.clear_expectations # # See also +register_tags_patterns+. def self.tags_file - patterns = retrieve(:tags_patterns) || + patterns = @tags_patterns || [[%r(spec/), 'spec/tags/'], [/_spec.rb$/, '_tags.txt']] - patterns.inject(retrieve(:file).dup) do |file, pattern| + patterns.inject(@file.dup) do |file, pattern| file.gsub(*pattern) end end diff --git a/ruby/spec/mspec/lib/mspec/runner/object.rb b/ruby/spec/mspec/lib/mspec/runner/object.rb index d5d965079..58d98cc4d 100644 --- a/ruby/spec/mspec/lib/mspec/runner/object.rb +++ b/ruby/spec/mspec/lib/mspec/runner/object.rb @@ -7,8 +7,8 @@ class Object MSpec.current.after at, &block end - private def describe(mod, msg = nil, options = nil, &block) - MSpec.describe mod, msg, &block + private def describe(description, options = nil, &block) + MSpec.describe description, options, &block end private def it(desc, &block) diff --git a/ruby/spec/mspec/lib/mspec/runner/parallel.rb b/ruby/spec/mspec/lib/mspec/runner/parallel.rb index 7428b3368..6a9ecd155 100644 --- a/ruby/spec/mspec/lib/mspec/runner/parallel.rb +++ b/ruby/spec/mspec/lib/mspec/runner/parallel.rb @@ -15,7 +15,7 @@ def launch_children @output_files << name env = { - "SPEC_TEMP_DIR" => "rubyspec_temp_#{i}", + "SPEC_TEMP_DIR" => "#{SPEC_TEMP_DIR}_#{i}", "MSPEC_MULTI" => i.to_s } command = @argv + ["-fy", "-o", name] diff --git a/ruby/spec/mspec/lib/mspec/utils/format.rb b/ruby/spec/mspec/lib/mspec/utils/format.rb index bb75e131d..425dd4d11 100644 --- a/ruby/spec/mspec/lib/mspec/utils/format.rb +++ b/ruby/spec/mspec/lib/mspec/utils/format.rb @@ -13,7 +13,11 @@ def pretty_inspect module MSpec def self.format(obj) - obj.pretty_inspect.chomp + if String === obj and obj.include?("\n") + "\n#{obj.inspect.gsub('\n', "\n")}" + else + obj.pretty_inspect.chomp + end rescue => e "#<#{obj.class}>(#pretty_inspect raised #{e.inspect})" end diff --git a/ruby/spec/mspec/lib/mspec/utils/options.rb b/ruby/spec/mspec/lib/mspec/utils/options.rb index 3e3f708a2..bef1dbdd2 100644 --- a/ruby/spec/mspec/lib/mspec/utils/options.rb +++ b/ruby/spec/mspec/lib/mspec/utils/options.rb @@ -274,6 +274,8 @@ def formatters config[:formatter] = SpinnerFormatter when 't', 'method' config[:formatter] = MethodFormatter + when 'e', 'stats' + config[:formatter] = StatsPerFileFormatter when 'y', 'yaml' config[:formatter] = YamlFormatter when 'p', 'profile' @@ -281,7 +283,7 @@ def formatters when 'j', 'junit' config[:formatter] = JUnitFormatter else - abort "Unknown format: #{o}\n#{@parser}" unless File.exist?(o) + abort "Unknown format: #{o}" unless File.exist?(o) require File.expand_path(o) if Object.const_defined?(:CUSTOM_MSPEC_FORMATTER) config[:formatter] = CUSTOM_MSPEC_FORMATTER @@ -300,6 +302,7 @@ def formatters doc " m, summary SummaryFormatter" doc " a, *, spin SpinnerFormatter" doc " t, method MethodFormatter" + doc " e, stats StatsPerFileFormatter" doc " y, yaml YamlFormatter" doc " p, profile ProfileFormatter" doc " j, junit JUnitFormatter\n" @@ -377,7 +380,7 @@ def unguarded def randomize on("-H", "--random", "Randomize the list of spec files") do - MSpec.randomize + MSpec.randomize = true end end @@ -392,11 +395,11 @@ def verbose on("-V", "--verbose", "Output the name of each file processed") do obj = Object.new def obj.start - @width = MSpec.retrieve(:files).inject(0) { |max, f| f.size > max ? f.size : max } + @width = MSpec.files_array.inject(0) { |max, f| f.size > max ? f.size : max } end def obj.load - file = MSpec.retrieve :file - STDERR.print "\n#{file.ljust(@width)}" + file = MSpec.file + STDERR.print "\n#{file.ljust(@width)}\n" end MSpec.register :start, obj MSpec.register :load, obj @@ -467,8 +470,6 @@ def debug end def all - # Generated with: - # puts File.read(__FILE__).scan(/def (\w+).*\n\s*on\(/) configure {} targets formatters @@ -481,6 +482,7 @@ def all repeat verbose interrupt + timeout verify action_filters actions diff --git a/ruby/spec/mspec/lib/mspec/utils/script.rb b/ruby/spec/mspec/lib/mspec/utils/script.rb index 2545a16ba..a77476ee2 100644 --- a/ruby/spec/mspec/lib/mspec/utils/script.rb +++ b/ruby/spec/mspec/lib/mspec/utils/script.rb @@ -3,7 +3,6 @@ require 'mspec/utils/warnings' # MSpecScript provides a skeleton for all the MSpec runner scripts. - class MSpecScript # Returns the config object. Maintained at the class # level to easily enable simple config files. See the @@ -39,9 +38,7 @@ def self.get(key) end def initialize - ruby_version_is ""..."2.4" do - abort "MSpec needs Ruby 2.4 or more recent" - end + check_version! config[:formatter] = nil config[:includes] = [] @@ -127,7 +124,7 @@ def register if formatter = config_formatter formatter.register - MSpec.store :formatter, formatter + MSpec.formatter = formatter end MatchFilter.new(:include, *config[:includes]).register unless config[:includes].empty? @@ -281,4 +278,10 @@ def self.main require 'mspec' script.run end + + private def check_version! + ruby_version_is ""..."2.6" do + warn "MSpec is supported for Ruby 2.6 and above only" + end + end end diff --git a/ruby/spec/mspec/lib/mspec/utils/version.rb b/ruby/spec/mspec/lib/mspec/utils/version.rb index 787a76b05..9c1c58b8d 100644 --- a/ruby/spec/mspec/lib/mspec/utils/version.rb +++ b/ruby/spec/mspec/lib/mspec/utils/version.rb @@ -42,7 +42,7 @@ def to_int def <=>(other) if other.respond_to? :to_int - other = Integer other + other = Integer(other.to_int) else other = SpecVersion.new(String(other)).to_i end diff --git a/ruby/spec/mspec/lib/mspec/utils/warnings.rb b/ruby/spec/mspec/lib/mspec/utils/warnings.rb index 7c2bc6fe8..0d3d36fad 100644 --- a/ruby/spec/mspec/lib/mspec/utils/warnings.rb +++ b/ruby/spec/mspec/lib/mspec/utils/warnings.rb @@ -1,21 +1,20 @@ require 'mspec/guards/version' -if RUBY_ENGINE == "ruby" and ruby_version_is("2.4") - ruby_version_is "2.4"..."2.5" do - # Kernel#warn does not delegate to Warning.warn in 2.4 - module Kernel - remove_method :warn - def warn(*messages) - return if $VERBOSE == nil or messages.empty? - msg = messages.join("\n") - msg += "\n" unless msg.end_with?("\n") - Warning.warn(msg) - end - private :warn - end - end +# Always enable deprecation warnings when running MSpec, as ruby/spec tests for them, +# and like in most test frameworks, deprecation warnings should be enabled by default, +# so that deprecations are noticed before the breaking change. +# Disable experimental warnings, we want to test new experimental features in ruby/spec. +if Object.const_defined?(:Warning) and Warning.respond_to?(:[]=) + Warning[:deprecated] = true + Warning[:experimental] = false +end + +if Object.const_defined?(:Warning) and Warning.respond_to?(:warn) + def Warning.warn(message, category: nil) + # Suppress any warning inside the method to prevent recursion + verbose = $VERBOSE + $VERBOSE = nil - def Warning.warn(message) if Thread.current[:in_mspec_complain_matcher] return $stderr.write(message) end @@ -43,18 +42,11 @@ def Warning.warn(message) when /passing a block to String#(bytes|chars|codepoints|lines) is deprecated/ when /core\/string\/modulo_spec\.rb:\d+: warning: too many arguments for format string/ when /regexp\/shared\/new_ascii(_8bit)?\.rb:\d+: warning: Unknown escape .+ is ignored/ - - # $VERBOSE = false warnings - when /constant ::(Fixnum|Bignum) is deprecated/ - when /\/(argf|io|stringio)\/.+(ARGF|IO)#(lines|chars|bytes|codepoints) is deprecated/ - when /Thread\.exclusive is deprecated.+\n.+thread\/exclusive_spec\.rb/ - when /hash\/shared\/index\.rb:\d+: warning: Hash#index is deprecated; use Hash#key/ - when /env\/shared\/key\.rb:\d+: warning: ENV\.index is deprecated; use ENV\.key/ - when /exponent(_spec)?\.rb:\d+: warning: in a\*\*b, b may be too big/ - when /enumerator\/(new_spec|initialize_spec)\.rb:\d+: warning: Enumerator\.new without a block is deprecated/ else $stderr.write message end + ensure + $VERBOSE = verbose end else $VERBOSE = nil unless ENV['OUTPUT_WARNINGS'] diff --git a/ruby/spec/mspec/spec/commands/mkspec_spec.rb b/ruby/spec/mspec/spec/commands/mkspec_spec.rb index 1b959dcb7..825add721 100644 --- a/ruby/spec/mspec/spec/commands/mkspec_spec.rb +++ b/ruby/spec/mspec/spec/commands/mkspec_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' require 'mspec/commands/mkspec' +require 'fileutils' - -describe "The -c, --constant CONSTANT option" do +RSpec.describe "The -c, --constant CONSTANT option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-c", "--constant", "CONSTANT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-c", "--constant", "CONSTANT", an_instance_of(String)) @script.options [] end @@ -21,22 +21,22 @@ ["-c", "--constant"].each do |opt| @config[:constants] = [] @script.options [opt, "Object"] - @config[:constants].should include("Object") + expect(@config[:constants]).to include("Object") end end end -describe "The -b, --base DIR option" do +RSpec.describe "The -b, --base DIR option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-b", "--base", "DIR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-b", "--base", "DIR", an_instance_of(String)) @script.options [] end @@ -45,22 +45,22 @@ ["-b", "--base"].each do |opt| @config[:base] = nil @script.options [opt, "superspec"] - @config[:base].should == File.expand_path("superspec") + expect(@config[:base]).to eq(File.expand_path("superspec")) end end end -describe "The -r, --require LIBRARY option" do +RSpec.describe "The -r, --require LIBRARY option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-r", "--require", "LIBRARY", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-r", "--require", "LIBRARY", an_instance_of(String)) @script.options [] end @@ -69,22 +69,22 @@ ["-r", "--require"].each do |opt| @config[:requires] = [] @script.options [opt, "libspec"] - @config[:requires].should include("libspec") + expect(@config[:requires]).to include("libspec") end end end -describe "The -V, --version-guard VERSION option" do +RSpec.describe "The -V, --version-guard VERSION option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-V", "--version-guard", "VERSION", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-V", "--version-guard", "VERSION", an_instance_of(String)) @script.options [] end @@ -93,150 +93,150 @@ ["-r", "--require"].each do |opt| @config[:requires] = [] @script.options [opt, "libspec"] - @config[:requires].should include("libspec") + expect(@config[:requires]).to include("libspec") end end end -describe MkSpec, "#options" do +RSpec.describe MkSpec, "#options" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new end it "parses the command line options" do - @options.should_receive(:parse).with(["--this", "and", "--that"]) + expect(@options).to receive(:parse).with(["--this", "and", "--that"]) @script.options ["--this", "and", "--that"] end it "parses ARGV unless passed other options" do - @options.should_receive(:parse).with(ARGV) + expect(@options).to receive(:parse).with(ARGV) @script.options end it "prints help and exits if passed an unrecognized option" do - @options.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) - @options.stub(:puts) - @options.stub(:exit) + expect(@options).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) + allow(@options).to receive(:puts) + allow(@options).to receive(:exit) @script.options ["--iunknown"] end end -describe MkSpec, "#create_directory" do +RSpec.describe MkSpec, "#create_directory" do before :each do @script = MkSpec.new @script.config[:base] = "spec" end it "prints a warning if a file with the directory name exists" do - File.should_receive(:exist?).and_return(true) - File.should_receive(:directory?).and_return(false) - FileUtils.should_not_receive(:mkdir_p) - @script.should_receive(:puts).with("spec/class already exists and is not a directory.") - @script.create_directory("Class").should == nil + expect(File).to receive(:exist?).and_return(true) + expect(File).to receive(:directory?).and_return(false) + expect(FileUtils).not_to receive(:mkdir_p) + expect(@script).to receive(:puts).with("spec/class already exists and is not a directory.") + expect(@script.create_directory("Class")).to eq(nil) end it "does nothing if the directory already exists" do - File.should_receive(:exist?).and_return(true) - File.should_receive(:directory?).and_return(true) - FileUtils.should_not_receive(:mkdir_p) - @script.create_directory("Class").should == "spec/class" + expect(File).to receive(:exist?).and_return(true) + expect(File).to receive(:directory?).and_return(true) + expect(FileUtils).not_to receive(:mkdir_p) + expect(@script.create_directory("Class")).to eq("spec/class") end it "creates the directory if it does not exist" do - File.should_receive(:exist?).and_return(false) - @script.should_receive(:mkdir_p).with("spec/class") - @script.create_directory("Class").should == "spec/class" + expect(File).to receive(:exist?).and_return(false) + expect(@script).to receive(:mkdir_p).with("spec/class") + expect(@script.create_directory("Class")).to eq("spec/class") end it "creates the directory for a namespaced module if it does not exist" do - File.should_receive(:exist?).and_return(false) - @script.should_receive(:mkdir_p).with("spec/struct/tms") - @script.create_directory("Struct::Tms").should == "spec/struct/tms" + expect(File).to receive(:exist?).and_return(false) + expect(@script).to receive(:mkdir_p).with("spec/struct/tms") + expect(@script.create_directory("Struct::Tms")).to eq("spec/struct/tms") end end -describe MkSpec, "#write_requires" do +RSpec.describe MkSpec, "#write_requires" do before :each do @script = MkSpec.new @script.config[:base] = "spec" @file = double("file") - File.stub(:open).and_yield(@file) + allow(File).to receive(:open).and_yield(@file) end it "writes the spec_helper require line" do - @file.should_receive(:puts).with("require_relative '../../../spec_helper'") + expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'") @script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb") end it "writes require lines for each library specified on the command line" do - @file.stub(:puts) - @file.should_receive(:puts).with("require_relative '../../../spec_helper'") - @file.should_receive(:puts).with("require 'complex'") + allow(@file).to receive(:puts) + expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'") + expect(@file).to receive(:puts).with("require 'complex'") @script.config[:requires] << 'complex' @script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb") end end -describe MkSpec, "#write_spec" do +RSpec.describe MkSpec, "#write_spec" do before :each do @file = IOStub.new - File.stub(:open).and_yield(@file) + allow(File).to receive(:open).and_yield(@file) @script = MkSpec.new - @script.stub(:puts) + allow(@script).to receive(:puts) @response = double("system command response") - @response.stub(:include?).and_return(false) - @script.stub(:`).and_return(@response) + allow(@response).to receive(:include?).and_return(false) + allow(@script).to receive(:`).and_return(@response) end it "checks if specs exist for the method if the spec file exists" do name = Regexp.escape(@script.ruby) - @script.should_receive(:`).with( + expect(@script).to receive(:`).with( %r"#{name} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e 'Object#inspect' spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "checks for the method name in the spec file output" do - @response.should_receive(:include?).with("Array#[]=") + expect(@response).to receive(:include?).with("Array#[]=") @script.write_spec("spec/core/yarra/element_set_spec.rb", "Array#[]=", true) end it "returns nil if the spec file exists and contains a spec for the method" do - @response.stub(:include?).and_return(true) - @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true).should == nil + allow(@response).to receive(:include?).and_return(true) + expect(@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)).to eq(nil) end it "does not print the spec file name if it exists and contains a spec for the method" do - @response.stub(:include?).and_return(true) - @script.should_not_receive(:puts) + allow(@response).to receive(:include?).and_return(true) + expect(@script).not_to receive(:puts) @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "prints the spec file name if a template spec is written" do - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "writes a template spec to the file if the spec file does not exist" do - @file.should_receive(:puts).twice - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@file).to receive(:puts).twice + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", false) end it "writes a template spec to the file if it exists but contains no spec for the method" do - @response.should_receive(:include?).and_return(false) - @file.should_receive(:puts).twice - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@response).to receive(:include?).and_return(false) + expect(@file).to receive(:puts).twice + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "writes a template spec" do @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) - @file.should == < ["run"]}) - @script.should_receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run") + expect(@script).to receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run") @script.run end end -describe MkSpec, ".main" do +RSpec.describe MkSpec, ".main" do before :each do @script = double("MkSpec").as_null_object - MkSpec.stub(:new).and_return(@script) + allow(MkSpec).to receive(:new).and_return(@script) end it "sets MSPEC_RUNNER = '1' in the environment" do ENV["MSPEC_RUNNER"] = "0" MkSpec.main - ENV["MSPEC_RUNNER"].should == "1" + expect(ENV["MSPEC_RUNNER"]).to eq("1") end it "creates an instance of MSpecScript" do - MkSpec.should_receive(:new).and_return(@script) + expect(MkSpec).to receive(:new).and_return(@script) MkSpec.main end it "calls the #options method on the script" do - @script.should_receive(:options) + expect(@script).to receive(:options) MkSpec.main end it "calls the #run method on the script" do - @script.should_receive(:run) + expect(@script).to receive(:run) MkSpec.main end end diff --git a/ruby/spec/mspec/spec/commands/mspec_ci_spec.rb b/ruby/spec/mspec/spec/commands/mspec_ci_spec.rb index a90cbd8d0..bcbc5b422 100644 --- a/ruby/spec/mspec/spec/commands/mspec_ci_spec.rb +++ b/ruby/spec/mspec/spec/commands/mspec_ci_spec.rb @@ -3,148 +3,148 @@ require 'mspec/runner/filters/tag' require 'mspec/commands/mspec-ci' -describe MSpecCI, "#options" do +RSpec.describe MSpecCI, "#options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecCI.new - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return([]) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return([]) end it "enables the chdir option" do - @options.should_receive(:chdir) + expect(@options).to receive(:chdir) @script.options [] end it "enables the prefix option" do - @options.should_receive(:prefix) + expect(@options).to receive(:prefix) @script.options [] end it "enables the config option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options [] end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec"] end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options [] end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options [] end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options [] end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options [] end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options [] end it "enables the action options" do - @options.should_receive(:actions) + expect(@options).to receive(:actions) @script.options [] end it "enables the action filter options" do - @options.should_receive(:action_filters) + expect(@options).to receive(:action_filters) @script.options [] end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options [] end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) @script.options [] end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options [] end end -describe MSpecCI, "#run" do +RSpec.describe MSpecCI, "#run" do before :each do - MSpec.stub(:process) + allow(MSpec).to receive(:process) @filter = double("TagFilter") - TagFilter.stub(:new).and_return(@filter) - @filter.stub(:register) + allow(TagFilter).to receive(:new).and_return(@filter) + allow(@filter).to receive(:register) @tags = ["fails", "critical", "unstable", "incomplete", "unsupported"] @config = { :ci_files => ["one", "two"] } @script = MSpecCI.new - @script.stub(:exit) - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return(["one", "two"]) + allow(@script).to receive(:exit) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return(["one", "two"]) @script.options [] end it "registers the tags patterns" do @config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(["one", "two"]) + expect(MSpec).to receive(:register_files).with(["one", "two"]) @script.run end it "registers a tag filter for 'fails', 'unstable', 'incomplete', 'critical', 'unsupported'" do filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, *@tags).and_return(filter) - filter.should_receive(:register) + expect(TagFilter).to receive(:new).with(:exclude, *@tags).and_return(filter) + expect(filter).to receive(:register) @script.run end it "registers an additional exclude tag specified by :ci_xtags" do @config[:ci_xtags] = "windows" filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter) - filter.should_receive(:register) + expect(TagFilter).to receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter) + expect(filter).to receive(:register) @script.run end it "registers additional exclude tags specified by a :ci_xtags array" do @config[:ci_xtags] = ["windows", "windoze"] filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, + expect(TagFilter).to receive(:new).with(:exclude, *(@tags + ["windows", "windoze"])).and_return(filter) - filter.should_receive(:register) + expect(filter).to receive(:register) @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end diff --git a/ruby/spec/mspec/spec/commands/mspec_run_spec.rb b/ruby/spec/mspec/spec/commands/mspec_run_spec.rb index fcb44ad5a..62acd49d7 100644 --- a/ruby/spec/mspec/spec/commands/mspec_run_spec.rb +++ b/ruby/spec/mspec/spec/commands/mspec_run_spec.rb @@ -5,130 +5,130 @@ one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb' two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb' -describe MSpecRun, ".new" do +RSpec.describe MSpecRun, ".new" do before :each do @script = MSpecRun.new end it "sets config[:files] to an empty list" do - @script.config[:files].should == [] + expect(@script.config[:files]).to eq([]) end end -describe MSpecRun, "#options" do +RSpec.describe MSpecRun, "#options" do before :each do @argv = [one_spec, two_spec] @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecRun.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "enables the filter options" do - @options.should_receive(:filters) + expect(@options).to receive(:filters) @script.options @argv end it "enables the chdir option" do - @options.should_receive(:chdir) + expect(@options).to receive(:chdir) @script.options @argv end it "enables the prefix option" do - @options.should_receive(:prefix) + expect(@options).to receive(:prefix) @script.options @argv end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options @argv end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec", one_spec] end it "enables the randomize option to runs specs in random order" do - @options.should_receive(:randomize) + expect(@options).to receive(:randomize) @script.options @argv end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options @argv end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options @argv end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options @argv end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options @argv end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options @argv end it "enables the verify options" do - @options.should_receive(:verify) + expect(@options).to receive(:verify) @script.options @argv end it "enables the action options" do - @options.should_receive(:actions) + expect(@options).to receive(:actions) @script.options @argv end it "enables the action filter options" do - @options.should_receive(:action_filters) + expect(@options).to receive(:action_filters) @script.options @argv end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options @argv end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) @script.options @argv end it "exits if there are no files to process and './spec' is not a directory" do - File.should_receive(:directory?).with("./spec").and_return(false) - @options.should_receive(:parse).and_return([]) - @script.should_receive(:abort).with("No files specified.") + expect(File).to receive(:directory?).with("./spec").and_return(false) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:abort).with("No files specified.") @script.options end it "process 'spec/' if it is a directory and no files were specified" do - File.should_receive(:directory?).with("./spec").and_return(true) - @options.should_receive(:parse).and_return([]) - @script.should_receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"]) + expect(File).to receive(:directory?).with("./spec").and_return(true) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"]) @script.options end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options @argv end end -describe MSpecRun, "#run" do +RSpec.describe MSpecRun, "#run" do before :each do @script = MSpecRun.new - @script.stub(:exit) + allow(@script).to receive(:exit) @spec_dir = File.expand_path(File.dirname(__FILE__)+"/fixtures") @file_patterns = [ @spec_dir+"/level2", @@ -139,35 +139,35 @@ @spec_dir+"/one_spec.rb", @spec_dir+"/two_spec.rb"] @script.options @file_patterns - MSpec.stub :process + allow(MSpec).to receive :process end it "registers the tags patterns" do @script.config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(@files) + expect(MSpec).to receive(:register_files).with(@files) @script.run end it "uses config[:files] if no files are given on the command line" do @script.config[:files] = @file_patterns - MSpec.should_receive(:register_files).with(@files) + expect(MSpec).to receive(:register_files).with(@files) @script.options [] @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end diff --git a/ruby/spec/mspec/spec/commands/mspec_spec.rb b/ruby/spec/mspec/spec/commands/mspec_spec.rb index b01af6b41..82201c207 100644 --- a/ruby/spec/mspec/spec/commands/mspec_spec.rb +++ b/ruby/spec/mspec/spec/commands/mspec_spec.rb @@ -2,55 +2,55 @@ require 'yaml' require 'mspec/commands/mspec' -describe MSpecMain, "#options" do +RSpec.describe MSpecMain, "#options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) - @script.stub(:load) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:load) end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options end it "provides a custom action (block) to the config option" do @script.options ["-B", "config"] - @config[:options].should include("-B", "config") + expect(@config[:options]).to include("-B", "config") end it "loads the file specified by the config option" do - @script.should_receive(:load).with("config") + expect(@script).to receive(:load).with("config") @script.options ["-B", "config"] end it "enables the target options" do - @options.should_receive(:targets) + expect(@options).to receive(:targets) @script.options end it "sets config[:options] to all argv entries that are not registered options" do @options.on "-X", "--exclude", "ARG", "description" @script.options [".", "-G", "fail", "-X", "ARG", "--list", "unstable", "some/file.rb"] - @config[:options].should == [".", "-G", "fail", "--list", "unstable", "some/file.rb"] + expect(@config[:options]).to eq([".", "-G", "fail", "--list", "unstable", "some/file.rb"]) end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options end end -describe MSpecMain, "#run" do +RSpec.describe MSpecMain, "#run" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) - @script.stub(:exec) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:exec) @err = $stderr $stderr = IOStub.new end @@ -60,76 +60,76 @@ end it "uses exec to invoke the runner script" do - @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) + expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @script.options [] @script.run end it "shows the command line on stderr" do - @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) + expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @script.options [] @script.run - $stderr.to_s.should == "$ ruby #{Dir.pwd}/bin/mspec-run\n" + expect($stderr.to_s).to eq("$ ruby #{Dir.pwd}/bin/mspec-run\n") end it "adds config[:launch] to the exec options" do - @script.should_receive(:exec).with("ruby", + expect(@script).to receive(:exec).with("ruby", "-Xlaunch.option", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @config[:launch] << "-Xlaunch.option" @script.options [] @script.run - $stderr.to_s.should == "$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n" + expect($stderr.to_s).to eq("$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n") end it "calls #multi_exec if the command is 'ci' and the multi option is passed" do - @script.should_receive(:multi_exec).and_return do |argv| - argv.should == ["ruby", "#{MSPEC_HOME}/bin/mspec-ci"] + expect(@script).to receive(:multi_exec) do |argv| + expect(argv).to eq(["ruby", "#{MSPEC_HOME}/bin/mspec-ci"]) end @script.options ["ci", "-j"] - lambda do + expect do @script.run - end.should raise_error(SystemExit) + end.to raise_error(SystemExit) end end -describe "The --warnings option" do +RSpec.describe "The --warnings option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("--warnings", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--warnings", an_instance_of(String)) @script.options end it "sets flags to -w" do @config[:flags] = [] @script.options ["--warnings"] - @config[:flags].should include("-w") + expect(@config[:flags]).to include("-w") end it "set OUTPUT_WARNINGS = '1' in the environment" do ENV['OUTPUT_WARNINGS'] = '0' @script.options ["--warnings"] - ENV['OUTPUT_WARNINGS'].should == '1' + expect(ENV['OUTPUT_WARNINGS']).to eq('1') end end -describe "The -j, --multi option" do +RSpec.describe "The -j, --multi option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-j", "--multi", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-j", "--multi", an_instance_of(String)) @script.options end @@ -137,22 +137,22 @@ ["-j", "--multi"].each do |opt| @config[:multi] = nil @script.options [opt] - @config[:multi].should == true + expect(@config[:multi]).to eq(true) end end end -describe "The -h, --help option" do +RSpec.describe "The -h, --help option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-h", "--help", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-h", "--help", an_instance_of(String)) @script.options end @@ -160,30 +160,30 @@ ["-h", "--help"].each do |opt| @config[:options] = [] @script.options ["ci", opt] - @config[:options].sort.should == ["-h"] + expect(@config[:options].sort).to eq(["-h"]) end end it "prints help and exits" do - @script.should_receive(:puts).twice - @script.should_receive(:exit).twice + expect(@script).to receive(:puts).twice + expect(@script).to receive(:exit).twice ["-h", "--help"].each do |opt| @script.options [opt] end end end -describe "The -v, --version option" do +RSpec.describe "The -v, --version option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-v", "--version", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-v", "--version", an_instance_of(String)) @script.options end @@ -191,15 +191,15 @@ ["-v", "--version"].each do |opt| @config[:options] = [] @script.options ["ci", opt] - @config[:options].sort.should == ["-v"] + expect(@config[:options].sort).to eq(["-v"]) end end it "prints the version and exits if no subscript is invoked" do @config[:command] = nil - File.stub(:basename).and_return("mspec") - @script.should_receive(:puts).twice.with("mspec #{MSpec::VERSION}") - @script.should_receive(:exit).twice + allow(File).to receive(:basename).and_return("mspec") + expect(@script).to receive(:puts).twice.with("mspec #{MSpec::VERSION}") + expect(@script).to receive(:exit).twice ["-v", "--version"].each do |opt| @script.options [opt] end diff --git a/ruby/spec/mspec/spec/commands/mspec_tag_spec.rb b/ruby/spec/mspec/spec/commands/mspec_tag_spec.rb index cdb3ac1a6..1ab5f6ea5 100644 --- a/ruby/spec/mspec/spec/commands/mspec_tag_spec.rb +++ b/ruby/spec/mspec/spec/commands/mspec_tag_spec.rb @@ -8,13 +8,13 @@ one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb' two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb' -describe MSpecTag, ".new" do +RSpec.describe MSpecTag, ".new" do before :each do @script = MSpecTag.new end it "sets config[:ltags] to an empty list" do - @script.config[:ltags].should == [] + expect(@script.config[:ltags]).to eq([]) end it "sets config[:tagger] to :add" do @@ -30,16 +30,16 @@ end end -describe MSpecTag, "#options" do +RSpec.describe MSpecTag, "#options" do before :each do @stdout, $stdout = $stdout, IOStub.new @argv = [one_spec, two_spec] @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecTag.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end after :each do @@ -47,80 +47,80 @@ end it "enables the filter options" do - @options.should_receive(:filters) + expect(@options).to receive(:filters) @script.options @argv end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options @argv end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec", one_spec] end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options @argv end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options @argv end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options @argv end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options @argv end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options @argv end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options @argv end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) @script.options @argv end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options @argv end it "exits if there are no files to process" do - @options.should_receive(:parse).and_return([]) - @script.should_receive(:exit) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:exit) @script.options - $stdout.should include "No files specified" + expect($stdout.to_s).to include "No files specified" end end -describe MSpecTag, "options" do +RSpec.describe MSpecTag, "options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecTag.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end describe "-N, --add TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-N", "--add", "TAG", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-N", "--add", "TAG", an_instance_of(String)) @script.options [one_spec] end @@ -129,16 +129,16 @@ @config[:tagger] = nil @config[:tag] = nil @script.options [opt, "taggit", one_spec] - @config[:tagger].should == :add - @config[:tag].should == "taggit:" + expect(@config[:tagger]).to eq(:add) + expect(@config[:tag]).to eq("taggit:") end end end describe "-R, --del TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-R", "--del", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-R", "--del", "TAG", an_instance_of(String)) @script.options [one_spec] end @@ -149,17 +149,17 @@ @config[:tag] = nil @config[:outcome] = nil @script.options [opt, "taggit", one_spec] - @config[:tagger].should == :del - @config[:tag].should == "taggit:" - @config[:outcome].should == :pass + expect(@config[:tagger]).to eq(:del) + expect(@config[:tag]).to eq("taggit:") + expect(@config[:outcome]).to eq(:pass) end end end describe "-Q, --pass" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-Q", "--pass", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-Q", "--pass", an_instance_of(String)) @script.options [one_spec] end @@ -167,15 +167,15 @@ ["-Q", "--pass"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :pass + expect(@config[:outcome]).to eq(:pass) end end end describe "-F, --fail" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-F", "--fail", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-F", "--fail", an_instance_of(String)) @script.options [one_spec] end @@ -183,15 +183,15 @@ ["-F", "--fail"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :fail + expect(@config[:outcome]).to eq(:fail) end end end describe "-L, --all" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-L", "--all", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-L", "--all", an_instance_of(String)) @script.options [one_spec] end @@ -199,100 +199,100 @@ ["-L", "--all"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :all + expect(@config[:outcome]).to eq(:all) end end end describe "--list TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--list", "TAG", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--list", "TAG", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :list" do @config[:tagger] = nil @script.options ["--list", "TAG", one_spec] - @config[:tagger].should == :list + expect(@config[:tagger]).to eq(:list) end it "sets ltags to include TAG" do @config[:tag] = nil @script.options ["--list", "TAG", one_spec] - @config[:ltags].should == ["TAG"] + expect(@config[:ltags]).to eq(["TAG"]) end end describe "--list-all" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--list-all", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--list-all", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :list_all" do @config[:tagger] = nil @script.options ["--list-all", one_spec] - @config[:tagger].should == :list_all + expect(@config[:tagger]).to eq(:list_all) end end describe "--purge" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--purge", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--purge", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :purge" do @config[:tagger] = nil @script.options ["--purge", one_spec] - @config[:tagger].should == :purge + expect(@config[:tagger]).to eq(:purge) end end end -describe MSpecTag, "#run" do +RSpec.describe MSpecTag, "#run" do before :each do - MSpec.stub(:process) + allow(MSpec).to receive(:process) options = double("MSpecOptions").as_null_object - options.stub(:parse).and_return(["one", "two"]) - MSpecOptions.stub(:new).and_return(options) + allow(options).to receive(:parse).and_return(["one", "two"]) + allow(MSpecOptions).to receive(:new).and_return(options) @config = { } @script = MSpecTag.new - @script.stub(:exit) - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return(["one", "two"]) + allow(@script).to receive(:exit) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return(["one", "two"]) @script.options end it "registers the tags patterns" do @config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(["one", "two"]) + expect(MSpec).to receive(:register_files).with(["one", "two"]) @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end -describe MSpecTag, "#register" do +RSpec.describe MSpecTag, "#register" do before :each do @script = MSpecTag.new @config = @script.config @@ -301,19 +301,19 @@ @config[:astrings] = [] @config[:ltags] = ["fails", "unstable"] - @script.stub(:files).and_return([]) + allow(@script).to receive(:files).and_return([]) @script.options "fake" @t = double("TagAction") - @t.stub(:register) + allow(@t).to receive(:register) @tl = double("TagListAction") - @tl.stub(:register) + allow(@tl).to receive(:register) end it "raises an ArgumentError if no recognized action is given" do @config[:tagger] = :totally_whack - lambda { @script.register }.should raise_error(ArgumentError) + expect { @script.register }.to raise_error(ArgumentError) end describe "when config[:tagger] is the default (:add)" do @@ -322,93 +322,93 @@ end it "creates a TagAction" do - TagAction.should_receive(:new).and_return(@t) + expect(TagAction).to receive(:new).and_return(@t) @script.register end it "creates a TagAction if config[:tagger] is :del" do @config[:tagger] = :del @config[:outcome] = :pass - TagAction.should_receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t) + expect(TagAction).to receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t) @script.register end it "calls #register on the TagAction instance" do - TagAction.should_receive(:new).and_return(@t) - @t.should_receive(:register) + expect(TagAction).to receive(:new).and_return(@t) + expect(@t).to receive(:register) @script.register end end describe "when config[:tagger] is :list" do before :each do - TagListAction.should_receive(:new).with(@config[:ltags]).and_return(@tl) + expect(TagListAction).to receive(:new).with(@config[:ltags]).and_return(@tl) @config[:tagger] = :list end it "creates a TagListAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end describe "when config[:tagger] is :list_all" do before :each do - TagListAction.should_receive(:new).with(nil).and_return(@tl) + expect(TagListAction).to receive(:new).with(nil).and_return(@tl) @config[:tagger] = :list_all end it "creates a TagListAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end describe "when config[:tagger] is :purge" do before :each do - TagPurgeAction.should_receive(:new).and_return(@tl) - MSpec.stub(:register_mode) + expect(TagPurgeAction).to receive(:new).and_return(@tl) + allow(MSpec).to receive(:register_mode) @config[:tagger] = :purge end it "creates a TagPurgeAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec in pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "registers MSpec in unguarded mode" do - MSpec.should_receive(:register_mode).with(:unguarded) + expect(MSpec).to receive(:register_mode).with(:unguarded) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end end diff --git a/ruby/spec/mspec/spec/expectations/expectations_spec.rb b/ruby/spec/mspec/spec/expectations/expectations_spec.rb index fea692f3e..371829d4f 100644 --- a/ruby/spec/mspec/spec/expectations/expectations_spec.rb +++ b/ruby/spec/mspec/spec/expectations/expectations_spec.rb @@ -1,29 +1,29 @@ require 'spec_helper' require 'mspec/expectations/expectations' -describe SpecExpectationNotMetError do +RSpec.describe SpecExpectationNotMetError do it "is a subclass of StandardError" do - SpecExpectationNotMetError.ancestors.should include(StandardError) + expect(SpecExpectationNotMetError.ancestors).to include(StandardError) end end -describe SpecExpectationNotFoundError do +RSpec.describe SpecExpectationNotFoundError do it "is a subclass of StandardError" do - SpecExpectationNotFoundError.ancestors.should include(StandardError) + expect(SpecExpectationNotFoundError.ancestors).to include(StandardError) end end -describe SpecExpectationNotFoundError, "#message" do +RSpec.describe SpecExpectationNotFoundError, "#message" do it "returns 'No behavior expectation was found in the example'" do m = SpecExpectationNotFoundError.new.message - m.should == "No behavior expectation was found in the example" + expect(m).to eq("No behavior expectation was found in the example") end end -describe SpecExpectation, "#fail_with" do +RSpec.describe SpecExpectation, "#fail_with" do it "raises an SpecExpectationNotMetError" do - lambda { + expect { SpecExpectation.fail_with "expected this", "to equal that" - }.should raise_error(SpecExpectationNotMetError, "expected this to equal that") + }.to raise_error(SpecExpectationNotMetError, "expected this to equal that") end end diff --git a/ruby/spec/mspec/spec/expectations/should_spec.rb b/ruby/spec/mspec/spec/expectations/should_spec.rb index b8bda8f86..472890979 100644 --- a/ruby/spec/mspec/spec/expectations/should_spec.rb +++ b/ruby/spec/mspec/spec/expectations/should_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' require 'rbconfig' -describe "MSpec" do +RSpec.describe "MSpec" do before :all do path = RbConfig::CONFIG['bindir'] exe = RbConfig::CONFIG['ruby_install_name'] - file = File.dirname(__FILE__) + '/should.rb' + file = File.expand_path('../../fixtures/should.rb', __FILE__) @out = `#{path}/#{exe} #{file}` end describe "#should" do it "records failures" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 1) MSpec expectation method #should causes a failure to be recorded FAILED Expected 1 == 2 @@ -20,7 +20,7 @@ end it "raises exceptions for examples with no expectations" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 2) MSpec expectation method #should registers that an expectation has been encountered FAILED No behavior expectation was found in the example @@ -30,7 +30,7 @@ describe "#should_not" do it "records failures" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 3) MSpec expectation method #should_not causes a failure to be recorded FAILED Expected 1 == 1 @@ -39,7 +39,7 @@ end it "raises exceptions for examples with no expectations" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 4) MSpec expectation method #should_not registers that an expectation has been encountered FAILED No behavior expectation was found in the example @@ -48,14 +48,14 @@ end it "prints status information" do - @out.should include ".FF..FF." + expect(@out).to include ".FF..FF." end it "prints out a summary" do - @out.should include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors" + expect(@out).to include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors" end it "records expectations" do - @out.should include "I was called 6 times" + expect(@out).to include "I was called 6 times" end end diff --git a/ruby/spec/mspec/spec/fixtures/config.mspec b/ruby/spec/mspec/spec/fixtures/config.mspec index 4a069e2eb..01654c509 100644 --- a/ruby/spec/mspec/spec/fixtures/config.mspec +++ b/ruby/spec/mspec/spec/fixtures/config.mspec @@ -1,8 +1,6 @@ class MSpecScript set :target, 'ruby' - set :backtrace_filter, /lib\/mspec\// - set :tags_patterns, [ [%r(spec/fixtures/), 'spec/fixtures/tags/'], [/_spec.rb$/, '_tags.txt'] diff --git a/ruby/spec/mspec/spec/fixtures/my_ruby b/ruby/spec/mspec/spec/fixtures/my_ruby index 4d552f27f..eeda3eeee 100755 --- a/ruby/spec/mspec/spec/fixtures/my_ruby +++ b/ruby/spec/mspec/spec/fixtures/my_ruby @@ -1,4 +1,4 @@ #!/usr/bin/env bash echo $RUBY_EXE -ruby "$@" +exec ruby "$@" diff --git a/ruby/spec/mspec/spec/expectations/should.rb b/ruby/spec/mspec/spec/fixtures/should.rb similarity index 96% rename from ruby/spec/mspec/spec/expectations/should.rb rename to ruby/spec/mspec/spec/fixtures/should.rb index 48503b163..f494775c5 100644 --- a/ruby/spec/mspec/spec/expectations/should.rb +++ b/ruby/spec/mspec/spec/fixtures/should.rb @@ -8,6 +8,8 @@ # specs but is run by MSpec. This avoids conflicting with # RSpec's #should and #should_not methods. +raise "RSpec should not be loaded" if defined?(RSpec) + class ShouldSpecsMonitor def initialize @called = 0 diff --git a/ruby/spec/mspec/spec/guards/block_device_spec.rb b/ruby/spec/mspec/spec/guards/block_device_spec.rb index 3b437b6d7..dd420d4a8 100644 --- a/ruby/spec/mspec/spec/guards/block_device_spec.rb +++ b/ruby/spec/mspec/spec/guards/block_device_spec.rb @@ -1,46 +1,46 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#with_block_device" do +RSpec.describe Object, "#with_block_device" do before :each do ScratchPad.clear @guard = BlockDeviceGuard.new - BlockDeviceGuard.stub(:new).and_return(@guard) + allow(BlockDeviceGuard).to receive(:new).and_return(@guard) end platform_is_not :freebsd, :windows do it "yields if block device is available" do - @guard.should_receive(:`).and_return("block devices") + expect(@guard).to receive(:`).and_return("block devices") with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if block device is not available" do - @guard.should_receive(:`).and_return(nil) + expect(@guard).to receive(:`).and_return(nil) with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end platform_is :freebsd, :windows do it "does not yield, since platform does not support block devices" do - @guard.should_not_receive(:`) + expect(@guard).not_to receive(:`) with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end it "sets the name of the guard to :with_block_device" do with_block_device { } - @guard.name.should == :with_block_device + expect(@guard.name).to eq(:with_block_device) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do with_block_device { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/bug_spec.rb b/ruby/spec/mspec/spec/guards/bug_spec.rb index c8529a49f..72a3405db 100644 --- a/ruby/spec/mspec/spec/guards/bug_spec.rb +++ b/ruby/spec/mspec/spec/guards/bug_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require 'mspec/guards' -describe BugGuard, "#match? when #implementation? is 'ruby'" do +RSpec.describe BugGuard, "#match? when #implementation? is 'ruby'" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -23,47 +23,47 @@ end it "returns false when version argument is less than RUBY_VERSION" do - BugGuard.new("#1", "1.8.5").match?.should == false + expect(BugGuard.new("#1", "1.8.5").match?).to eq(false) end it "returns true when version argument is equal to RUBY_VERSION" do - BugGuard.new("#1", "1.8.6").match?.should == true + expect(BugGuard.new("#1", "1.8.6").match?).to eq(true) end it "returns true when version argument is greater than RUBY_VERSION" do - BugGuard.new("#1", "1.8.7").match?.should == true + expect(BugGuard.new("#1", "1.8.7").match?).to eq(true) end it "returns true when version argument implicitly includes RUBY_VERSION" do - BugGuard.new("#1", "1.8").match?.should == true - BugGuard.new("#1", "1.8.6").match?.should == true + expect(BugGuard.new("#1", "1.8").match?).to eq(true) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(true) end it "returns true when the argument range includes RUBY_VERSION" do - BugGuard.new("#1", '1.8.5'..'1.8.7').match?.should == true - BugGuard.new("#1", '1.8'..'1.9').match?.should == true - BugGuard.new("#1", '1.8'...'1.9').match?.should == true - BugGuard.new("#1", '1.8'..'1.8.6').match?.should == true - BugGuard.new("#1", '1.8.5'..'1.8.6').match?.should == true - BugGuard.new("#1", ''...'1.8.7').match?.should == true + expect(BugGuard.new("#1", '1.8.5'..'1.8.7').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'..'1.9').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'..'1.8.6').match?).to eq(true) + expect(BugGuard.new("#1", '1.8.5'..'1.8.6').match?).to eq(true) + expect(BugGuard.new("#1", ''...'1.8.7').match?).to eq(true) end it "returns false when the argument range does not include RUBY_VERSION" do - BugGuard.new("#1", '1.8.7'..'1.8.9').match?.should == false - BugGuard.new("#1", '1.8.4'..'1.8.5').match?.should == false - BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false - BugGuard.new("#1", '1.8.5'...'1.8.6').match?.should == false - BugGuard.new("#1", ''...'1.8.6').match?.should == false + expect(BugGuard.new("#1", '1.8.7'..'1.8.9').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'..'1.8.5').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.5'...'1.8.6').match?).to eq(false) + expect(BugGuard.new("#1", ''...'1.8.6').match?).to eq(false) end it "returns false when MSpec.mode?(:no_ruby_bug) is true" do - MSpec.should_receive(:mode?).with(:no_ruby_bug).twice.and_return(:true) - BugGuard.new("#1", "1.8.5").match?.should == false - BugGuard.new("#1", "1.8").match?.should == false + expect(MSpec).to receive(:mode?).with(:no_ruby_bug).twice.and_return(:true) + expect(BugGuard.new("#1", "1.8.5").match?).to eq(false) + expect(BugGuard.new("#1", "1.8").match?).to eq(false) end end -describe BugGuard, "#match? when #implementation? is not 'ruby'" do +RSpec.describe BugGuard, "#match? when #implementation? is not 'ruby'" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -88,64 +88,64 @@ end it "returns false when version argument is less than RUBY_VERSION" do - BugGuard.new("#1", "1.8").match?.should == false - BugGuard.new("#1", "1.8.6").match?.should == false + expect(BugGuard.new("#1", "1.8").match?).to eq(false) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end it "returns false when version argument is equal to RUBY_VERSION" do - BugGuard.new("#1", "1.8.6").match?.should == false + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end it "returns false when version argument is greater than RUBY_VERSION" do - BugGuard.new("#1", "1.8.7").match?.should == false + expect(BugGuard.new("#1", "1.8.7").match?).to eq(false) end it "returns false no matter if the argument range includes RUBY_VERSION" do - BugGuard.new("#1", '1.8'...'1.9').match?.should == false - BugGuard.new("#1", '1.8.5'...'1.8.7').match?.should == false - BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false + expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.5'...'1.8.7').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false) end it "returns false when MSpec.mode?(:no_ruby_bug) is true" do - MSpec.stub(:mode?).and_return(:true) - BugGuard.new("#1", "1.8.6").match?.should == false + allow(MSpec).to receive(:mode?).and_return(:true) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end end -describe Object, "#ruby_bug" do +RSpec.describe Object, "#ruby_bug" do before :each do hide_deprecation_warnings @guard = BugGuard.new "#1234", "x.x.x" - BugGuard.stub(:new).and_return(@guard) + allow(BugGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when #match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "requires a bug tracker number and a version number" do - lambda { ruby_bug { } }.should raise_error(ArgumentError) - lambda { ruby_bug("#1234") { } }.should raise_error(ArgumentError) + expect { ruby_bug { } }.to raise_error(ArgumentError) + expect { ruby_bug("#1234") { } }.to raise_error(ArgumentError) end it "sets the name of the guard to :ruby_bug" do ruby_bug("#1234", "1.8.6") { } - @guard.name.should == :ruby_bug + expect(@guard.name).to eq(:ruby_bug) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:unregister) + expect do ruby_bug("", "") { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/conflict_spec.rb b/ruby/spec/mspec/spec/guards/conflict_spec.rb index deada9682..7dbe83153 100644 --- a/ruby/spec/mspec/spec/guards/conflict_spec.rb +++ b/ruby/spec/mspec/spec/guards/conflict_spec.rb @@ -1,53 +1,53 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#conflicts_with" do +RSpec.describe Object, "#conflicts_with" do before :each do hide_deprecation_warnings ScratchPad.clear end it "does not yield if Object.constants includes any of the arguments" do - Object.stub(:constants).and_return(["SomeClass", "OtherClass"]) + allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"]) conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "does not yield if Object.constants (as Symbols) includes any of the arguments" do - Object.stub(:constants).and_return([:SomeClass, :OtherClass]) + allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass]) conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields if Object.constants does not include any of the arguments" do - Object.stub(:constants).and_return(["SomeClass", "OtherClass"]) + allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"]) conflicts_with(:AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields if Object.constants (as Symbols) does not include any of the arguments" do - Object.stub(:constants).and_return([:SomeClass, :OtherClass]) + allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass]) conflicts_with(:AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end end -describe Object, "#conflicts_with" do +RSpec.describe Object, "#conflicts_with" do before :each do hide_deprecation_warnings @guard = ConflictsGuard.new - ConflictsGuard.stub(:new).and_return(@guard) + allow(ConflictsGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :conflicts_with" do conflicts_with(:AClass, :BClass) { } - @guard.name.should == :conflicts_with + expect(@guard.name).to eq(:conflicts_with) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:unregister) + expect do conflicts_with(:AClass, :BClass) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/endian_spec.rb b/ruby/spec/mspec/spec/guards/endian_spec.rb index 5b40c203a..943b558ed 100644 --- a/ruby/spec/mspec/spec/guards/endian_spec.rb +++ b/ruby/spec/mspec/spec/guards/endian_spec.rb @@ -1,55 +1,55 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#big_endian" do +RSpec.describe Object, "#big_endian" do before :each do @guard = BigEndianGuard.new - BigEndianGuard.stub(:new).and_return(@guard) + allow(BigEndianGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields on big-endian platforms" do - @guard.stub(:pattern).and_return([?\001]) + allow(@guard).to receive(:pattern).and_return([?\001]) big_endian { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield on little-endian platforms" do - @guard.stub(:pattern).and_return([?\000]) + allow(@guard).to receive(:pattern).and_return([?\000]) big_endian { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "sets the name of the guard to :big_endian" do big_endian { } - @guard.name.should == :big_endian + expect(@guard.name).to eq(:big_endian) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.stub(:pattern).and_return([?\001]) - @guard.should_receive(:unregister) - lambda do + allow(@guard).to receive(:pattern).and_return([?\001]) + expect(@guard).to receive(:unregister) + expect do big_endian { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#little_endian" do +RSpec.describe Object, "#little_endian" do before :each do @guard = BigEndianGuard.new - BigEndianGuard.stub(:new).and_return(@guard) + allow(BigEndianGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields on little-endian platforms" do - @guard.stub(:pattern).and_return([?\000]) + allow(@guard).to receive(:pattern).and_return([?\000]) little_endian { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield on big-endian platforms" do - @guard.stub(:pattern).and_return([?\001]) + allow(@guard).to receive(:pattern).and_return([?\001]) little_endian { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end diff --git a/ruby/spec/mspec/spec/guards/feature_spec.rb b/ruby/spec/mspec/spec/guards/feature_spec.rb index 8761cb2fb..fcb899759 100644 --- a/ruby/spec/mspec/spec/guards/feature_spec.rb +++ b/ruby/spec/mspec/spec/guards/feature_spec.rb @@ -1,120 +1,120 @@ require 'spec_helper' require 'mspec/guards' -describe FeatureGuard, ".enabled?" do +RSpec.describe FeatureGuard, ".enabled?" do it "returns true if the feature is enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true) - FeatureGuard.enabled?(:encoding).should be_true + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) + expect(FeatureGuard.enabled?(:encoding)).to be_truthy end it "returns false if the feature is not enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false) - FeatureGuard.enabled?(:encoding).should be_false + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) + expect(FeatureGuard.enabled?(:encoding)).to be_falsey end it "returns true if all the features are enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(true) - FeatureGuard.enabled?(:one, :two).should be_true + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true) + expect(FeatureGuard.enabled?(:one, :two)).to be_truthy end it "returns false if any of the features are not enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(false) - FeatureGuard.enabled?(:one, :two).should be_false + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false) + expect(FeatureGuard.enabled?(:one, :two)).to be_falsey end end -describe Object, "#with_feature" do +RSpec.describe Object, "#with_feature" do before :each do ScratchPad.clear @guard = FeatureGuard.new :encoding - FeatureGuard.stub(:new).and_return(@guard) + allow(FeatureGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :with_feature" do with_feature(:encoding) { } - @guard.name.should == :with_feature + expect(@guard.name).to eq(:with_feature) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do with_feature { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#with_feature" do +RSpec.describe Object, "#with_feature" do before :each do ScratchPad.clear end it "yields if the feature is enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) with_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields if all the features are enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true) with_feature(:one, :two) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if the feature is not enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) with_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end it "does not yield if any of the features are not enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(false) + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false) with_feature(:one, :two) { ScratchPad.record :yield } - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end end -describe Object, "#without_feature" do +RSpec.describe Object, "#without_feature" do before :each do ScratchPad.clear @guard = FeatureGuard.new :encoding - FeatureGuard.stub(:new).and_return(@guard) + allow(FeatureGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :without_feature" do without_feature(:encoding) { } - @guard.name.should == :without_feature + expect(@guard.name).to eq(:without_feature) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do without_feature { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#without_feature" do +RSpec.describe Object, "#without_feature" do before :each do ScratchPad.clear end it "does not yield if the feature is enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) without_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end it "yields if the feature is disabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) without_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end end diff --git a/ruby/spec/mspec/spec/guards/guard_spec.rb b/ruby/spec/mspec/spec/guards/guard_spec.rb index 5c3dae4b3..e29d23574 100644 --- a/ruby/spec/mspec/spec/guards/guard_spec.rb +++ b/ruby/spec/mspec/spec/guards/guard_spec.rb @@ -2,41 +2,41 @@ require 'mspec/guards' require 'rbconfig' -describe SpecGuard, ".ruby_version" do +RSpec.describe SpecGuard, ".ruby_version" do before :each do stub_const "RUBY_VERSION", "8.2.3" end it "returns the full version for :full" do - SpecGuard.ruby_version(:full).should == "8.2.3" + expect(SpecGuard.ruby_version(:full)).to eq("8.2.3") end it "returns major.minor.tiny for :tiny" do - SpecGuard.ruby_version(:tiny).should == "8.2.3" + expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3") end it "returns major.minor.tiny for :teeny" do - SpecGuard.ruby_version(:tiny).should == "8.2.3" + expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3") end it "returns major.minor for :minor" do - SpecGuard.ruby_version(:minor).should == "8.2" + expect(SpecGuard.ruby_version(:minor)).to eq("8.2") end it "defaults to :minor" do - SpecGuard.ruby_version.should == "8.2" + expect(SpecGuard.ruby_version).to eq("8.2") end it "returns major for :major" do - SpecGuard.ruby_version(:major).should == "8" + expect(SpecGuard.ruby_version(:major)).to eq("8") end end -describe SpecGuard, "#yield?" do +RSpec.describe SpecGuard, "#yield?" do before :each do MSpec.clear_modes @guard = SpecGuard.new - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) end after :each do @@ -47,77 +47,77 @@ it "returns true if MSpec.mode?(:unguarded) is true" do MSpec.register_mode :unguarded - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:verify) is true" do MSpec.register_mode :verify - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:verify) is true regardless of invert being true" do MSpec.register_mode :verify - @guard.yield?(true).should == true + expect(@guard.yield?(true)).to eq(true) end it "returns true if MSpec.mode?(:report) is true" do MSpec.register_mode :report - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:report) is true regardless of invert being true" do MSpec.register_mode :report - @guard.yield?(true).should == true + expect(@guard.yield?(true)).to eq(true) end it "returns true if MSpec.mode?(:report_on) is true and SpecGuards.guards contains the named guard" do MSpec.register_mode :report_on SpecGuard.guards << :guard_name - @guard.yield?.should == false + expect(@guard.yield?).to eq(false) @guard.name = :guard_name - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns #match? if neither report nor verify mode are true" do - @guard.stub(:match?).and_return(false) - @guard.yield?.should == false - @guard.stub(:match?).and_return(true) - @guard.yield?.should == true + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.yield?).to eq(false) + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.yield?).to eq(true) end it "returns #match? if invert is true and neither report nor verify mode are true" do - @guard.stub(:match?).and_return(false) - @guard.yield?(true).should == true - @guard.stub(:match?).and_return(true) - @guard.yield?(true).should == false + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.yield?(true)).to eq(true) + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.yield?(true)).to eq(false) end end -describe SpecGuard, "#match?" do +RSpec.describe SpecGuard, "#match?" do before :each do @guard = SpecGuard.new end it "must be implemented in subclasses" do - lambda { + expect { @guard.match? - }.should raise_error("must be implemented by the subclass") + }.to raise_error("must be implemented by the subclass") end end -describe SpecGuard, "#unregister" do +RSpec.describe SpecGuard, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @guard = SpecGuard.new end it "unregisters from MSpec :add actions" do - MSpec.should_receive(:unregister).with(:add, @guard) + expect(MSpec).to receive(:unregister).with(:add, @guard) @guard.unregister end end -describe SpecGuard, "#record" do +RSpec.describe SpecGuard, "#record" do after :each do SpecGuard.clear end @@ -126,28 +126,28 @@ guard = SpecGuard.new "a", "1.8"..."1.9" guard.name = :named_guard guard.record "SomeClass#action returns true" - SpecGuard.report.should == { + expect(SpecGuard.report).to eq({ 'named_guard a, 1.8...1.9' => ["SomeClass#action returns true"] - } + }) end end -describe SpecGuard, ".guards" do +RSpec.describe SpecGuard, ".guards" do it "returns an Array" do - SpecGuard.guards.should be_kind_of(Array) + expect(SpecGuard.guards).to be_kind_of(Array) end end -describe SpecGuard, ".clear_guards" do +RSpec.describe SpecGuard, ".clear_guards" do it "resets the array to empty" do SpecGuard.guards << :guard - SpecGuard.guards.should == [:guard] + expect(SpecGuard.guards).to eq([:guard]) SpecGuard.clear_guards - SpecGuard.guards.should == [] + expect(SpecGuard.guards).to eq([]) end end -describe SpecGuard, ".finish" do +RSpec.describe SpecGuard, ".finish" do before :each do $stdout = @out = IOStub.new end @@ -163,88 +163,88 @@ guard.record "SomeClass#action returns true" guard.record "SomeClass#reverse returns false" SpecGuard.finish - $stdout.should == %[ + expect($stdout).to eq(%[ 2 specs omitted by guard: named_guard a, 1.8...1.9: SomeClass#action returns true SomeClass#reverse returns false -] +]) end end -describe SpecGuard, ".run_if" do +RSpec.describe SpecGuard, ".run_if" do before :each do @guard = SpecGuard.new ScratchPad.clear end it "yields if match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) @guard.run_if(:name) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) @guard.run_if(:name) { fail } end it "returns the result of the block if match? is true" do - @guard.stub(:match?).and_return(true) - @guard.run_if(:name) { 42 }.should == 42 + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_if(:name) { 42 }).to eq(42) end it "returns nil if given a block and match? is false" do - @guard.stub(:match?).and_return(false) - @guard.run_if(:name) { 42 }.should == nil + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_if(:name) { 42 }).to eq(nil) end it "returns what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - @guard.run_if(:name).should == true - @guard.stub(:match?).and_return(false) - @guard.run_if(:name).should == false + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_if(:name)).to eq(true) + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_if(:name)).to eq(false) end end -describe SpecGuard, ".run_unless" do +RSpec.describe SpecGuard, ".run_unless" do before :each do @guard = SpecGuard.new ScratchPad.clear end it "yields if match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) @guard.run_unless(:name) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) @guard.run_unless(:name) { fail } end it "returns the result of the block if match? is false" do - @guard.stub(:match?).and_return(false) - @guard.run_unless(:name) { 42 }.should == 42 + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_unless(:name) { 42 }).to eq(42) end it "returns nil if given a block and match? is true" do - @guard.stub(:match?).and_return(true) - @guard.run_unless(:name) { 42 }.should == nil + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_unless(:name) { 42 }).to eq(nil) end it "returns the opposite of what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - @guard.run_unless(:name).should == false - @guard.stub(:match?).and_return(false) - @guard.run_unless(:name).should == true + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_unless(:name)).to eq(false) + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_unless(:name)).to eq(true) end end -describe Object, "#guard" do +RSpec.describe Object, "#guard" do before :each do ScratchPad.clear end @@ -254,32 +254,32 @@ end it "allows to combine guards" do - guard1 = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(guard1) + guard1 = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(guard1) guard2 = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(guard2) + allow(PlatformGuard).to receive(:new).and_return(guard2) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(true) guard -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(true) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(false) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(false) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end @@ -289,7 +289,7 @@ guard -> { true } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Proc returns false" do @@ -304,12 +304,12 @@ guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "yields if MSpec.mode?(:verify) is true" do @@ -318,12 +318,12 @@ guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "yields if MSpec.mode?(:report) is true" do @@ -332,72 +332,72 @@ guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "raises an error if no Proc is given" do - -> { guard :foo }.should raise_error(RuntimeError) + expect { guard :foo }.to raise_error(RuntimeError) end it "requires a block" do - -> { + expect { guard(-> { true }) - }.should raise_error(LocalJumpError) - -> { + }.to raise_error(LocalJumpError) + expect { guard(-> { false }) - }.should raise_error(LocalJumpError) + }.to raise_error(LocalJumpError) end end -describe Object, "#guard_not" do +RSpec.describe Object, "#guard_not" do before :each do ScratchPad.clear end it "allows to combine guards" do - guard1 = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(guard1) + guard1 = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(guard1) guard2 = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(guard2) + allow(PlatformGuard).to receive(:new).and_return(guard2) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(true) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(true) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(false) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(false) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield3 end - ScratchPad.recorded.should == :yield3 + expect(ScratchPad.recorded).to eq(:yield3) end it "yields when the Proc returns false" do guard_not -> { false } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Proc returns true" do @@ -407,15 +407,15 @@ end it "raises an error if no Proc is given" do - -> { guard_not :foo }.should raise_error(RuntimeError) + expect { guard_not :foo }.to raise_error(RuntimeError) end it "requires a block" do - -> { + expect { guard_not(-> { true }) - }.should raise_error(LocalJumpError) - -> { + }.to raise_error(LocalJumpError) + expect { guard_not(-> { false }) - }.should raise_error(LocalJumpError) + }.to raise_error(LocalJumpError) end end diff --git a/ruby/spec/mspec/spec/guards/platform_spec.rb b/ruby/spec/mspec/spec/guards/platform_spec.rb index 6088fb2ba..88a7ad86f 100644 --- a/ruby/spec/mspec/spec/guards/platform_spec.rb +++ b/ruby/spec/mspec/spec/guards/platform_spec.rb @@ -1,252 +1,252 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#platform_is" do +RSpec.describe Object, "#platform_is" do before :each do @guard = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when #os? returns false" do - PlatformGuard.stub(:os?).and_return(false) + allow(PlatformGuard).to receive(:os?).and_return(false) platform_is(:ruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #os? returns true" do - PlatformGuard.stub(:os?).and_return(true) + allow(PlatformGuard).to receive(:os?).and_return(true) platform_is(:solarce) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "returns what #os? returns when no block is given" do - PlatformGuard.stub(:os?).and_return(true) - platform_is(:solarce).should == true - PlatformGuard.stub(:os?).and_return(false) - platform_is(:solarce).should == false + allow(PlatformGuard).to receive(:os?).and_return(true) + expect(platform_is(:solarce)).to eq(true) + allow(PlatformGuard).to receive(:os?).and_return(false) + expect(platform_is(:solarce)).to eq(false) end it "sets the name of the guard to :platform_is" do platform_is(:solarce) { } - @guard.name.should == :platform_is + expect(@guard.name).to eq(:platform_is) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do platform_is(:solarce) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#platform_is_not" do +RSpec.describe Object, "#platform_is_not" do before :each do @guard = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when #os? returns true" do - PlatformGuard.stub(:os?).and_return(true) + allow(PlatformGuard).to receive(:os?).and_return(true) platform_is_not(:ruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #os? returns false" do - PlatformGuard.stub(:os?).and_return(false) + allow(PlatformGuard).to receive(:os?).and_return(false) platform_is_not(:solarce) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "returns the opposite of what #os? returns when no block is given" do - PlatformGuard.stub(:os?).and_return(true) - platform_is_not(:solarce).should == false - PlatformGuard.stub(:os?).and_return(false) - platform_is_not(:solarce).should == true + allow(PlatformGuard).to receive(:os?).and_return(true) + expect(platform_is_not(:solarce)).to eq(false) + allow(PlatformGuard).to receive(:os?).and_return(false) + expect(platform_is_not(:solarce)).to eq(true) end it "sets the name of the guard to :platform_is_not" do platform_is_not(:solarce) { } - @guard.name.should == :platform_is_not + expect(@guard.name).to eq(:platform_is_not) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do platform_is_not(:solarce) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#platform_is :wordsize => SIZE_SPEC" do +RSpec.describe Object, "#platform_is :wordsize => SIZE_SPEC" do before :each do @guard = PlatformGuard.new :darwin, :wordsize => 32 - PlatformGuard.stub(:os?).and_return(true) - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:os?).and_return(true) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #wordsize? returns true" do - PlatformGuard.stub(:wordsize?).and_return(true) + allow(PlatformGuard).to receive(:wordsize?).and_return(true) platform_is(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "doesn not yield when #wordsize? returns false" do - PlatformGuard.stub(:wordsize?).and_return(false) + allow(PlatformGuard).to receive(:wordsize?).and_return(false) platform_is(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end -describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do +RSpec.describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do before :each do @guard = PlatformGuard.new :darwin, :wordsize => 32 - PlatformGuard.stub(:os?).and_return(true) - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:os?).and_return(true) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #wordsize? returns false" do - PlatformGuard.stub(:wordsize?).and_return(false) + allow(PlatformGuard).to receive(:wordsize?).and_return(false) platform_is_not(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "doesn not yield when #wordsize? returns true" do - PlatformGuard.stub(:wordsize?).and_return(true) + allow(PlatformGuard).to receive(:wordsize?).and_return(true) platform_is_not(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end -describe PlatformGuard, ".implementation?" do +RSpec.describe PlatformGuard, ".implementation?" do it "returns true if passed :ruby and RUBY_ENGINE == 'ruby'" do stub_const 'RUBY_ENGINE', 'ruby' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) end it "returns true if passed :rubinius and RUBY_ENGINE == 'rbx'" do stub_const 'RUBY_ENGINE', 'rbx' - PlatformGuard.implementation?(:rubinius).should == true + expect(PlatformGuard.implementation?(:rubinius)).to eq(true) end it "returns true if passed :jruby and RUBY_ENGINE == 'jruby'" do stub_const 'RUBY_ENGINE', 'jruby' - PlatformGuard.implementation?(:jruby).should == true + expect(PlatformGuard.implementation?(:jruby)).to eq(true) end it "returns true if passed :ironruby and RUBY_ENGINE == 'ironruby'" do stub_const 'RUBY_ENGINE', 'ironruby' - PlatformGuard.implementation?(:ironruby).should == true + expect(PlatformGuard.implementation?(:ironruby)).to eq(true) end it "returns true if passed :maglev and RUBY_ENGINE == 'maglev'" do stub_const 'RUBY_ENGINE', 'maglev' - PlatformGuard.implementation?(:maglev).should == true + expect(PlatformGuard.implementation?(:maglev)).to eq(true) end it "returns true if passed :topaz and RUBY_ENGINE == 'topaz'" do stub_const 'RUBY_ENGINE', 'topaz' - PlatformGuard.implementation?(:topaz).should == true + expect(PlatformGuard.implementation?(:topaz)).to eq(true) end it "returns true if passed :ruby and RUBY_ENGINE matches /^ruby/" do stub_const 'RUBY_ENGINE', 'ruby' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) stub_const 'RUBY_ENGINE', 'ruby1.8' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) stub_const 'RUBY_ENGINE', 'ruby1.9' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) end it "works for an unrecognized name" do stub_const 'RUBY_ENGINE', 'myrubyimplementation' - PlatformGuard.implementation?(:myrubyimplementation).should == true - PlatformGuard.implementation?(:other).should == false + expect(PlatformGuard.implementation?(:myrubyimplementation)).to eq(true) + expect(PlatformGuard.implementation?(:other)).to eq(false) end end -describe PlatformGuard, ".standard?" do +RSpec.describe PlatformGuard, ".standard?" do it "returns true if implementation? returns true" do - PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(true) - PlatformGuard.standard?.should be_true + expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(true) + expect(PlatformGuard.standard?).to be_truthy end it "returns false if implementation? returns false" do - PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(false) - PlatformGuard.standard?.should be_false + expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(false) + expect(PlatformGuard.standard?).to be_falsey end end -describe PlatformGuard, ".wordsize?" do +RSpec.describe PlatformGuard, ".wordsize?" do it "returns true when arg is 32 and 1.size is 4" do - PlatformGuard.wordsize?(32).should == (1.size == 4) + expect(PlatformGuard.wordsize?(32)).to eq(1.size == 4) end it "returns true when arg is 64 and 1.size is 8" do - PlatformGuard.wordsize?(64).should == (1.size == 8) + expect(PlatformGuard.wordsize?(64)).to eq(1.size == 8) end end -describe PlatformGuard, ".os?" do +RSpec.describe PlatformGuard, ".os?" do before :each do stub_const 'PlatformGuard::PLATFORM', 'solarce' end it "returns false when arg does not match the platform" do - PlatformGuard.os?(:ruby).should == false + expect(PlatformGuard.os?(:ruby)).to eq(false) end it "returns false when no arg matches the platform" do - PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev).should == false + expect(PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev)).to eq(false) end it "returns true when arg matches the platform" do - PlatformGuard.os?(:solarce).should == true + expect(PlatformGuard.os?(:solarce)).to eq(true) end it "returns true when any arg matches the platform" do - PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev).should == true + expect(PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev)).to eq(true) end it "returns true when arg is :windows and the platform contains 'mswin'" do stub_const 'PlatformGuard::PLATFORM', 'mswin32' - PlatformGuard.os?(:windows).should == true + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when arg is :windows and the platform contains 'mingw'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.os?(:windows).should == true + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32' - PlatformGuard.os?(:linux).should == false + expect(PlatformGuard.os?(:linux)).to eq(false) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + expect(PlatformGuard.os?(:linux)).to eq(false) end end -describe PlatformGuard, ".os?" do +RSpec.describe PlatformGuard, ".os?" do it "returns true if called with the current OS or architecture" do os = RbConfig::CONFIG["host_os"].sub("-gnu", "") arch = RbConfig::CONFIG["host_arch"] - PlatformGuard.os?(os).should == true - PlatformGuard.os?(arch).should == true - PlatformGuard.os?("#{arch}-#{os}").should == true + expect(PlatformGuard.os?(os)).to eq(true) + expect(PlatformGuard.os?(arch)).to eq(true) + expect(PlatformGuard.os?("#{arch}-#{os}")).to eq(true) end end -describe PlatformGuard, ".os? on JRuby" do +RSpec.describe PlatformGuard, ".os? on JRuby" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -266,72 +266,72 @@ end it "raises an error when testing for a :java platform" do - lambda { + expect { PlatformGuard.os?(:java) - }.should raise_error(":java is not a valid OS") + }.to raise_error(":java is not a valid OS") end it "returns true when arg is :windows and RUBY_PLATFORM contains 'java' and os?(:windows) is true" do stub_const 'PlatformGuard::PLATFORM', 'mswin32' - PlatformGuard.os?(:windows).should == true + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when RUBY_PLATFORM contains 'java' and os?(argument) is true" do stub_const 'PlatformGuard::PLATFORM', 'amiga' - PlatformGuard.os?(:amiga).should == true + expect(PlatformGuard.os?(:amiga)).to eq(true) end end -describe PlatformGuard, ".os?" do +RSpec.describe PlatformGuard, ".os?" do before :each do stub_const 'PlatformGuard::PLATFORM', 'unreal' end it "returns true if argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:unreal).should == true + expect(PlatformGuard.os?(:unreal)).to eq(true) end it "returns true if any argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:bsd, :unreal, :amiga).should == true + expect(PlatformGuard.os?(:bsd, :unreal, :amiga)).to eq(true) end it "returns false if no argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos).should == false + expect(PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos)).to eq(false) end it "returns false if argument does not match RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:amiga).should == false + expect(PlatformGuard.os?(:amiga)).to eq(false) end it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32' - PlatformGuard.os?(:windows).should == true + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.os?(:windows).should == true + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + expect(PlatformGuard.os?(:linux)).to eq(false) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + expect(PlatformGuard.os?(:linux)).to eq(false) end end -describe PlatformGuard, ".windows?" do +RSpec.describe PlatformGuard, ".windows?" do it "returns true on windows" do stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' - PlatformGuard.windows?.should == true + expect(PlatformGuard.windows?).to eq(true) end it "returns false on non-windows" do stub_const 'PlatformGuard::PLATFORM', 'i586-linux' - PlatformGuard.windows?.should == false + expect(PlatformGuard.windows?).to eq(false) end end diff --git a/ruby/spec/mspec/spec/guards/quarantine_spec.rb b/ruby/spec/mspec/spec/guards/quarantine_spec.rb index e5c7da793..eb5ff1da2 100644 --- a/ruby/spec/mspec/spec/guards/quarantine_spec.rb +++ b/ruby/spec/mspec/spec/guards/quarantine_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/guards' -describe QuarantineGuard, "#match?" do +RSpec.describe QuarantineGuard, "#match?" do it "returns true" do - QuarantineGuard.new.match?.should == true + expect(QuarantineGuard.new.match?).to eq(true) end end -describe Object, "#quarantine!" do +RSpec.describe Object, "#quarantine!" do before :each do ScratchPad.clear @guard = QuarantineGuard.new - QuarantineGuard.stub(:new).and_return(@guard) + allow(QuarantineGuard).to receive(:new).and_return(@guard) end it "does not yield" do quarantine! { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "sets the name of the guard to :quarantine!" do quarantine! { } - @guard.name.should == :quarantine! + expect(@guard.name).to eq(:quarantine!) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do quarantine! { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/superuser_spec.rb b/ruby/spec/mspec/spec/guards/superuser_spec.rb index f8815057e..aba2cc2bb 100644 --- a/ruby/spec/mspec/spec/guards/superuser_spec.rb +++ b/ruby/spec/mspec/spec/guards/superuser_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#as_superuser" do +RSpec.describe Object, "#as_superuser" do before :each do @guard = SuperUserGuard.new - SuperUserGuard.stub(:new).and_return(@guard) + allow(SuperUserGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when Process.euid is not 0" do - Process.stub(:euid).and_return(501) + allow(Process).to receive(:euid).and_return(501) as_superuser { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when Process.euid is 0" do - Process.stub(:euid).and_return(0) + allow(Process).to receive(:euid).and_return(0) as_superuser { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "sets the name of the guard to :as_superuser" do as_superuser { } - @guard.name.should == :as_superuser + expect(@guard.name).to eq(:as_superuser) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do as_superuser { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/support_spec.rb b/ruby/spec/mspec/spec/guards/support_spec.rb index 38414abeb..a61d003d6 100644 --- a/ruby/spec/mspec/spec/guards/support_spec.rb +++ b/ruby/spec/mspec/spec/guards/support_spec.rb @@ -1,54 +1,54 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#not_supported_on" do +RSpec.describe Object, "#not_supported_on" do before :each do ScratchPad.clear end it "raises an Exception when passed :ruby" do stub_const "RUBY_ENGINE", "jruby" - lambda { + expect { not_supported_on(:ruby) { ScratchPad.record :yield } - }.should raise_error(Exception) - ScratchPad.recorded.should_not == :yield + }.to raise_error(Exception) + expect(ScratchPad.recorded).not_to eq(:yield) end it "does not yield when #implementation? returns true" do stub_const "RUBY_ENGINE", "jruby" not_supported_on(:jruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #standard? returns true" do stub_const "RUBY_ENGINE", "ruby" not_supported_on(:rubinius) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields when #implementation? returns false" do stub_const "RUBY_ENGINE", "jruby" not_supported_on(:rubinius) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end end -describe Object, "#not_supported_on" do +RSpec.describe Object, "#not_supported_on" do before :each do @guard = SupportedGuard.new - SupportedGuard.stub(:new).and_return(@guard) + allow(SupportedGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :not_supported_on" do not_supported_on(:rubinius) { } - @guard.name.should == :not_supported_on + expect(@guard.name).to eq(:not_supported_on) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do not_supported_on(:rubinius) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/ruby/spec/mspec/spec/guards/user_spec.rb b/ruby/spec/mspec/spec/guards/user_spec.rb index 2de4db739..252650465 100644 --- a/ruby/spec/mspec/spec/guards/user_spec.rb +++ b/ruby/spec/mspec/spec/guards/user_spec.rb @@ -1,20 +1,20 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#as_user" do +RSpec.describe Object, "#as_user" do before :each do ScratchPad.clear end it "yields when the Process.euid is not 0" do - Process.stub(:euid).and_return(501) + allow(Process).to receive(:euid).and_return(501) as_user { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Process.euid is 0" do - Process.stub(:euid).and_return(0) + allow(Process).to receive(:euid).and_return(0) as_user { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end diff --git a/ruby/spec/mspec/spec/guards/version_spec.rb b/ruby/spec/mspec/spec/guards/version_spec.rb index 07eb451ec..5a5f4ddc3 100644 --- a/ruby/spec/mspec/spec/guards/version_spec.rb +++ b/ruby/spec/mspec/spec/guards/version_spec.rb @@ -11,80 +11,102 @@ # is as typically understood: a..b means v >= a and v <= b; # a...b means v >= a and v < b. -describe VersionGuard, "#match?" do +RSpec.describe VersionGuard, "#match?" do before :each do hide_deprecation_warnings - stub_const "VersionGuard::FULL_RUBY_VERSION", SpecVersion.new('1.8.6') + @current = '1.8.6' end it "returns true when the argument is equal to RUBY_VERSION" do - VersionGuard.new('1.8.6').match?.should == true + expect(VersionGuard.new(@current, '1.8.6').match?).to eq(true) end it "returns true when the argument is less than RUBY_VERSION" do - VersionGuard.new('1.8').match?.should == true - VersionGuard.new('1.8.5').match?.should == true + expect(VersionGuard.new(@current, '1.8').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8.5').match?).to eq(true) end it "returns false when the argument is greater than RUBY_VERSION" do - VersionGuard.new('1.8.7').match?.should == false - VersionGuard.new('1.9.2').match?.should == false + expect(VersionGuard.new(@current, '1.8.7').match?).to eq(false) + expect(VersionGuard.new(@current, '1.9.2').match?).to eq(false) end it "returns true when the argument range includes RUBY_VERSION" do - VersionGuard.new('1.8.5'..'1.8.7').match?.should == true - VersionGuard.new('1.8'..'1.9').match?.should == true - VersionGuard.new('1.8'...'1.9').match?.should == true - VersionGuard.new('1.8'..'1.8.6').match?.should == true - VersionGuard.new('1.8.5'..'1.8.6').match?.should == true - VersionGuard.new(''...'1.8.7').match?.should == true + expect(VersionGuard.new(@current, '1.8.5'..'1.8.7').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'..'1.9').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'...'1.9').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'..'1.8.6').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8.5'..'1.8.6').match?).to eq(true) + expect(VersionGuard.new(@current, ''...'1.8.7').match?).to eq(true) end it "returns false when the argument range does not include RUBY_VERSION" do - VersionGuard.new('1.8.7'..'1.8.9').match?.should == false - VersionGuard.new('1.8.4'..'1.8.5').match?.should == false - VersionGuard.new('1.8.4'...'1.8.6').match?.should == false - VersionGuard.new('1.8.5'...'1.8.6').match?.should == false - VersionGuard.new(''...'1.8.6').match?.should == false + expect(VersionGuard.new(@current, '1.8.7'..'1.8.9').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.4'..'1.8.5').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.4'...'1.8.6').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.5'...'1.8.6').match?).to eq(false) + expect(VersionGuard.new(@current, ''...'1.8.6').match?).to eq(false) end end -describe Object, "#ruby_version_is" do +RSpec.describe Object, "#ruby_version_is" do before :each do - @guard = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(@guard) + @guard = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) ruby_version_is('x.x.x') { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when #match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) ruby_version_is('x.x.x') { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "returns what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - ruby_version_is('x.x.x').should == true - @guard.stub(:match?).and_return(false) - ruby_version_is('x.x.x').should == false + allow(@guard).to receive(:match?).and_return(true) + expect(ruby_version_is('x.x.x')).to eq(true) + allow(@guard).to receive(:match?).and_return(false) + expect(ruby_version_is('x.x.x')).to eq(false) end it "sets the name of the guard to :ruby_version_is" do ruby_version_is("") { } - @guard.name.should == :ruby_version_is + expect(@guard.name).to eq(:ruby_version_is) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do ruby_version_is("") { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) + end +end + +RSpec.describe Object, "#version_is" do + before :each do + hide_deprecation_warnings + end + + it "returns the expected values" do + expect(version_is('1.2.3', '1.2.2')).to eq(true) + expect(version_is('1.2.3', '1.2.3')).to eq(true) + expect(version_is('1.2.3', '1.2.4')).to eq(false) + + expect(version_is('1.2.3', '1')).to eq(true) + expect(version_is('1.2.3', '1.0')).to eq(true) + expect(version_is('1.2.3', '2')).to eq(false) + expect(version_is('1.2.3', '2.0')).to eq(false) + + expect(version_is('1.2.3', '1.2.2'..'1.2.4')).to eq(true) + expect(version_is('1.2.3', '1.2.2'..'1.2.3')).to eq(true) + expect(version_is('1.2.3', '1.2.2'...'1.2.3')).to eq(false) + expect(version_is('1.2.3', '1.2.3'..'1.2.4')).to eq(true) end end diff --git a/ruby/spec/mspec/spec/helpers/argf_spec.rb b/ruby/spec/mspec/spec/helpers/argf_spec.rb index cf5eb0fe8..1412d71f8 100644 --- a/ruby/spec/mspec/spec/helpers/argf_spec.rb +++ b/ruby/spec/mspec/spec/helpers/argf_spec.rb @@ -2,7 +2,7 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#argf" do +RSpec.describe Object, "#argf" do before :each do @saved_argv = ARGV.dup @argv = [__FILE__] @@ -10,28 +10,28 @@ it "sets @argf to an instance of ARGF.class with the given argv" do argf @argv do - @argf.should be_an_instance_of ARGF.class - @argf.filename.should == @argv.first + expect(@argf).to be_an_instance_of ARGF.class + expect(@argf.filename).to eq(@argv.first) end - @argf.should be_nil + expect(@argf).to be_nil end it "does not alter ARGV nor ARGF" do argf @argv do end - ARGV.should == @saved_argv - ARGF.argv.should == @saved_argv + expect(ARGV).to eq(@saved_argv) + expect(ARGF.argv).to eq(@saved_argv) end it "does not close STDIN" do argf ['-'] do end - STDIN.should_not be_closed + expect(STDIN).not_to be_closed end it "disallows nested calls" do argf @argv do - lambda { argf @argv }.should raise_error + expect { argf @argv }.to raise_error end end end diff --git a/ruby/spec/mspec/spec/helpers/argv_spec.rb b/ruby/spec/mspec/spec/helpers/argv_spec.rb index c3b21c763..1db7e3865 100644 --- a/ruby/spec/mspec/spec/helpers/argv_spec.rb +++ b/ruby/spec/mspec/spec/helpers/argv_spec.rb @@ -2,7 +2,7 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#argv" do +RSpec.describe Object, "#argv" do before :each do ScratchPad.clear @@ -12,16 +12,16 @@ it "replaces and restores the value of ARGV" do argv @argv - ARGV.should == @argv + expect(ARGV).to eq(@argv) argv :restore - ARGV.should == @saved_argv + expect(ARGV).to eq(@saved_argv) end it "yields to the block after setting ARGV" do argv @argv do ScratchPad.record ARGV.dup end - ScratchPad.recorded.should == @argv - ARGV.should == @saved_argv + expect(ScratchPad.recorded).to eq(@argv) + expect(ARGV).to eq(@saved_argv) end end diff --git a/ruby/spec/mspec/spec/helpers/datetime_spec.rb b/ruby/spec/mspec/spec/helpers/datetime_spec.rb index 8696c0c9c..af4f55737 100644 --- a/ruby/spec/mspec/spec/helpers/datetime_spec.rb +++ b/ruby/spec/mspec/spec/helpers/datetime_spec.rb @@ -2,43 +2,43 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#new_datetime" do +RSpec.describe Object, "#new_datetime" do it "returns a default DateTime instance" do - new_datetime.should == DateTime.new + expect(new_datetime).to eq(DateTime.new) end it "returns a DateTime instance with the specified year value" do d = new_datetime :year => 1970 - d.year.should == 1970 + expect(d.year).to eq(1970) end it "returns a DateTime instance with the specified month value" do d = new_datetime :month => 11 - d.mon.should == 11 + expect(d.mon).to eq(11) end it "returns a DateTime instance with the specified day value" do d = new_datetime :day => 23 - d.day.should == 23 + expect(d.day).to eq(23) end it "returns a DateTime instance with the specified hour value" do d = new_datetime :hour => 10 - d.hour.should == 10 + expect(d.hour).to eq(10) end it "returns a DateTime instance with the specified minute value" do d = new_datetime :minute => 10 - d.min.should == 10 + expect(d.min).to eq(10) end it "returns a DateTime instance with the specified second value" do d = new_datetime :second => 2 - d.sec.should == 2 + expect(d.sec).to eq(2) end it "returns a DateTime instance with the specified offset value" do d = new_datetime :offset => Rational(3,24) - d.offset.should == Rational(3,24) + expect(d.offset).to eq(Rational(3,24)) end end diff --git a/ruby/spec/mspec/spec/helpers/fixture_spec.rb b/ruby/spec/mspec/spec/helpers/fixture_spec.rb index 4dbdd092f..d8e2ae7be 100644 --- a/ruby/spec/mspec/spec/helpers/fixture_spec.rb +++ b/ruby/spec/mspec/spec/helpers/fixture_spec.rb @@ -2,24 +2,24 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#fixture" do +RSpec.describe Object, "#fixture" do before :each do @dir = File.realpath("..", __FILE__) end it "returns the expanded path to a fixture file" do name = fixture(__FILE__, "subdir", "file.txt") - name.should == "#{@dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{@dir}/fixtures/subdir/file.txt") end it "omits '/shared' if it is the suffix of the directory string" do name = fixture("#{@dir}/shared/file.rb", "subdir", "file.txt") - name.should == "#{@dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{@dir}/fixtures/subdir/file.txt") end it "does not append '/fixtures' if it is the suffix of the directory string" do commands_dir = "#{File.dirname(@dir)}/commands" name = fixture("#{commands_dir}/fixtures/file.rb", "subdir", "file.txt") - name.should == "#{commands_dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{commands_dir}/fixtures/subdir/file.txt") end end diff --git a/ruby/spec/mspec/spec/helpers/flunk_spec.rb b/ruby/spec/mspec/spec/helpers/flunk_spec.rb index 7b1216d3f..b6a1f21c1 100644 --- a/ruby/spec/mspec/spec/helpers/flunk_spec.rb +++ b/ruby/spec/mspec/spec/helpers/flunk_spec.rb @@ -4,17 +4,17 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#flunk" do +RSpec.describe Object, "#flunk" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end it "raises an SpecExpectationNotMetError unconditionally" do - lambda { flunk }.should raise_error(SpecExpectationNotMetError) + expect { flunk }.to raise_error(SpecExpectationNotMetError) end it "accepts on argument for an optional message" do - lambda {flunk "test"}.should raise_error(SpecExpectationNotMetError) + expect {flunk "test"}.to raise_error(SpecExpectationNotMetError) end end diff --git a/ruby/spec/mspec/spec/helpers/fs_spec.rb b/ruby/spec/mspec/spec/helpers/fs_spec.rb index e40c6c560..15bb43903 100644 --- a/ruby/spec/mspec/spec/helpers/fs_spec.rb +++ b/ruby/spec/mspec/spec/helpers/fs_spec.rb @@ -2,7 +2,7 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#cp" do +RSpec.describe Object, "#cp" do before :each do @source = tmp("source.txt") @copy = tmp("copied.txt") @@ -19,12 +19,12 @@ it "copies a file" do cp @source, @copy data = IO.read(@copy) - data.should == @contents - data.should == IO.read(@source) + expect(data).to eq(@contents) + expect(data).to eq(IO.read(@source)) end end -describe Object, "#touch" do +RSpec.describe Object, "#touch" do before :all do @name = tmp("touched.txt") end @@ -35,29 +35,29 @@ it "creates a file" do touch @name - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end it "accepts an optional mode argument" do touch @name, "wb" - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end it "overwrites an existing file" do File.open(@name, "w") { |f| f.puts "used" } - File.size(@name).should > 0 + expect(File.size(@name)).to be > 0 touch @name - File.size(@name).should == 0 + expect(File.size(@name)).to eq(0) end it "yields the open file if passed a block" do touch(@name) { |f| f.write "touching" } - IO.read(@name).should == "touching" + expect(IO.read(@name)).to eq("touching") end end -describe Object, "#touch" do +RSpec.describe Object, "#touch" do before :all do @name = tmp("subdir/touched.txt") end @@ -68,11 +68,11 @@ it "creates all the directories in the path to the file" do touch @name - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end end -describe Object, "#mkdir_p" do +RSpec.describe Object, "#mkdir_p" do before :all do @dir1 = tmp("/nested") @dir2 = @dir1 + "/directory" @@ -86,17 +86,17 @@ it "creates all the directories in a path" do mkdir_p @dir2 - File.directory?(@dir2).should be_true + expect(File.directory?(@dir2)).to be_truthy end it "raises an ArgumentError if a path component is a file" do File.open(@dir1, "w") { |f| } - lambda { mkdir_p @dir2 }.should raise_error(ArgumentError) + expect { mkdir_p @dir2 }.to raise_error(ArgumentError) end it "works if multiple processes try to create the same directory concurrently" do original = File.method(:directory?) - File.should_receive(:directory?).at_least(:once) { |dir| + expect(File).to receive(:directory?).at_least(:once) { |dir| ret = original.call(dir) if !ret and dir == @dir1 Dir.mkdir(dir) # Simulate race @@ -104,11 +104,11 @@ ret } mkdir_p @dir1 - original.call(@dir1).should be_true + expect(original.call(@dir1)).to be_truthy end end -describe Object, "#rm_r" do +RSpec.describe Object, "#rm_r" do before :all do @topdir = tmp("rm_r_tree") @topfile = @topdir + "/file.txt" @@ -137,59 +137,59 @@ end it "raises an ArgumentError if the path is not prefixed by MSPEC_RM_PREFIX" do - lambda { rm_r "some_file.txt" }.should raise_error(ArgumentError) + expect { rm_r "some_file.txt" }.to raise_error(ArgumentError) end it "removes a single file" do rm_r @subfile - File.exist?(@subfile).should be_false + expect(File.exist?(@subfile)).to be_falsey end it "removes multiple files" do rm_r @topfile, @subfile - File.exist?(@topfile).should be_false - File.exist?(@subfile).should be_false + expect(File.exist?(@topfile)).to be_falsey + expect(File.exist?(@subfile)).to be_falsey end platform_is_not :windows do it "removes a symlink to a file" do File.symlink @topfile, @link rm_r @link - File.exist?(@link).should be_false + expect(File.exist?(@link)).to be_falsey end it "removes a symlink to a directory" do File.symlink @subdir1, @link rm_r @link - lambda do + expect do File.lstat(@link) - end.should raise_error(Errno::ENOENT) - File.exist?(@subdir1).should be_true + end.to raise_error(Errno::ENOENT) + expect(File.exist?(@subdir1)).to be_truthy end it "removes a dangling symlink" do File.symlink "non_existent_file", @link rm_r @link - lambda do + expect do File.lstat(@link) - end.should raise_error(Errno::ENOENT) + end.to raise_error(Errno::ENOENT) end it "removes a socket" do require 'socket' UNIXServer.new(@socket).close rm_r @socket - File.exist?(@socket).should be_false + expect(File.exist?(@socket)).to be_falsey end end it "removes a single directory" do rm_r @subdir2 - File.directory?(@subdir2).should be_false + expect(File.directory?(@subdir2)).to be_falsey end it "recursively removes a directory tree" do rm_r @topdir - File.directory?(@topdir).should be_false + expect(File.directory?(@topdir)).to be_falsey end end diff --git a/ruby/spec/mspec/spec/helpers/io_spec.rb b/ruby/spec/mspec/spec/helpers/io_spec.rb index 19f838491..14c1a2d6b 100644 --- a/ruby/spec/mspec/spec/helpers/io_spec.rb +++ b/ruby/spec/mspec/spec/helpers/io_spec.rb @@ -2,7 +2,7 @@ require 'mspec/guards' require 'mspec/helpers' -describe IOStub do +RSpec.describe IOStub do before :each do @out = IOStub.new @sep = $\ @@ -14,42 +14,42 @@ it "provides a write method" do @out.write "this" - @out.should == "this" + expect(@out).to eq("this") end it "concatenates the arguments sent to write" do @out.write "flim ", "flam" - @out.should == "flim flam" + expect(@out).to eq("flim flam") end it "provides a print method that appends the default separator" do $\ = " [newline] " @out.print "hello" @out.print "world" - @out.should == "hello [newline] world [newline] " + expect(@out).to eq("hello [newline] world [newline] ") end it "provides a puts method that appends the default separator" do @out.puts "hello", 1, 2, 3 - @out.should == "hello\n1\n2\n3\n" + expect(@out).to eq("hello\n1\n2\n3\n") end it "provides a puts method that appends separator if argument not given" do @out.puts - @out.should == "\n" + expect(@out).to eq("\n") end it "provides a printf method" do @out.printf "%-10s, %03d, %2.1f", "test", 42, 4.2 - @out.should == "test , 042, 4.2" + expect(@out).to eq("test , 042, 4.2") end it "provides a flush method that does nothing and returns self" do - @out.flush.should == @out + expect(@out.flush).to eq(@out) end end -describe Object, "#new_fd" do +RSpec.describe Object, "#new_fd" do before :each do @name = tmp("io_specs") @io = nil @@ -60,36 +60,36 @@ rm_r @name end - it "returns a Integer that can be used to create an IO instance" do + it "returns an Integer that can be used to create an IO instance" do fd = new_fd @name - fd.should be_kind_of(Integer) + expect(fd).to be_kind_of(Integer) @io = IO.new fd, 'w:utf-8' @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "accepts an options Hash" do - FeatureGuard.stub(:enabled?).and_return(true) + allow(FeatureGuard).to receive(:enabled?).and_return(true) fd = new_fd @name, { :mode => 'w:utf-8' } - fd.should be_kind_of(Integer) + expect(fd).to be_kind_of(Integer) @io = IO.new fd, 'w:utf-8' @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "raises an ArgumentError if the options Hash does not include :mode" do - FeatureGuard.stub(:enabled?).and_return(true) - lambda { new_fd @name, { :encoding => "utf-8" } }.should raise_error(ArgumentError) + allow(FeatureGuard).to receive(:enabled?).and_return(true) + expect { new_fd @name, { :encoding => "utf-8" } }.to raise_error(ArgumentError) end end -describe Object, "#new_io" do +RSpec.describe Object, "#new_io" do before :each do @name = tmp("io_specs.txt") end @@ -101,14 +101,14 @@ it "returns a File instance" do @io = new_io @name - @io.should be_an_instance_of(File) + expect(@io).to be_an_instance_of(File) end it "opens the IO for reading if passed 'r'" do touch(@name) { |f| f.print "io data" } @io = new_io @name, "r" - @io.read.should == "io data" - lambda { @io.puts "more data" }.should raise_error(IOError) + expect(@io.read).to eq("io data") + expect { @io.puts "more data" }.to raise_error(IOError) end it "opens the IO for writing if passed 'w'" do @@ -116,14 +116,14 @@ @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "opens the IO for reading if passed { :mode => 'r' }" do touch(@name) { |f| f.print "io data" } @io = new_io @name, { :mode => "r" } - @io.read.should == "io data" - lambda { @io.puts "more data" }.should raise_error(IOError) + expect(@io.read).to eq("io data") + expect { @io.puts "more data" }.to raise_error(IOError) end it "opens the IO for writing if passed { :mode => 'w' }" do @@ -131,6 +131,6 @@ @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end end diff --git a/ruby/spec/mspec/spec/helpers/mock_to_path_spec.rb b/ruby/spec/mspec/spec/helpers/mock_to_path_spec.rb index 464e7e544..c2ce98519 100644 --- a/ruby/spec/mspec/spec/helpers/mock_to_path_spec.rb +++ b/ruby/spec/mspec/spec/helpers/mock_to_path_spec.rb @@ -1,17 +1,23 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' +require 'mspec/mocks' + +RSpec.describe Object, "#mock_to_path" do + before :each do + state = double("run state").as_null_object + expect(MSpec).to receive(:current).and_return(state) + end -describe Object, "#mock_to_path" do it "returns an object that responds to #to_path" do obj = mock_to_path("foo") - obj.should be_a(MockObject) - obj.should respond_to(:to_path) + expect(obj).to be_a(MockObject) + expect(obj).to respond_to(:to_path) obj.to_path end it "returns the provided path when #to_path is called" do obj = mock_to_path("/tmp/foo") - obj.to_path.should == "/tmp/foo" + expect(obj.to_path).to eq("/tmp/foo") end end diff --git a/ruby/spec/mspec/spec/helpers/numeric_spec.rb b/ruby/spec/mspec/spec/helpers/numeric_spec.rb index 2ea56e596..e65f3e861 100644 --- a/ruby/spec/mspec/spec/helpers/numeric_spec.rb +++ b/ruby/spec/mspec/spec/helpers/numeric_spec.rb @@ -2,24 +2,24 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#bignum_value" do +RSpec.describe Object, "#bignum_value" do it "returns a value that is an instance of Bignum on any platform" do - bignum_value.should == 0x8000_0000_0000_0000 + expect(bignum_value).to eq(0x8000_0000_0000_0000) end it "returns the default value incremented by the argument" do - bignum_value(42).should == 0x8000_0000_0000_002a + expect(bignum_value(42)).to eq(0x8000_0000_0000_002a) end end -describe Object, "#nan_value" do +RSpec.describe Object, "#nan_value" do it "returns NaN" do - nan_value.nan?.should be_true + expect(nan_value.nan?).to be_truthy end end -describe Object, "#infinity_value" do +RSpec.describe Object, "#infinity_value" do it "returns Infinity" do - infinity_value.infinite?.should == 1 + expect(infinity_value.infinite?).to eq(1) end end diff --git a/ruby/spec/mspec/spec/helpers/ruby_exe_spec.rb b/ruby/spec/mspec/spec/helpers/ruby_exe_spec.rb index 803604357..79ce55ca7 100644 --- a/ruby/spec/mspec/spec/helpers/ruby_exe_spec.rb +++ b/ruby/spec/mspec/spec/helpers/ruby_exe_spec.rb @@ -10,7 +10,7 @@ class RubyExeSpecs public :ruby_exe end -describe "#ruby_exe_options" do +RSpec.describe "#ruby_exe_options" do before :each do @ruby_exe_env = ENV['RUBY_EXE'] @script = RubyExeSpecs.new @@ -22,89 +22,89 @@ class RubyExeSpecs it "returns ENV['RUBY_EXE'] when passed :env" do ENV['RUBY_EXE'] = "kowabunga" - @script.ruby_exe_options(:env).should == "kowabunga" + expect(@script.ruby_exe_options(:env)).to eq("kowabunga") end it "returns 'bin/jruby' when passed :engine and RUBY_ENGINE is 'jruby'" do stub_const "RUBY_ENGINE", 'jruby' - @script.ruby_exe_options(:engine).should == 'bin/jruby' + expect(@script.ruby_exe_options(:engine)).to eq('bin/jruby') end it "returns 'bin/rbx' when passed :engine, RUBY_ENGINE is 'rbx'" do stub_const "RUBY_ENGINE", 'rbx' - @script.ruby_exe_options(:engine).should == 'bin/rbx' + expect(@script.ruby_exe_options(:engine)).to eq('bin/rbx') end it "returns 'ir' when passed :engine and RUBY_ENGINE is 'ironruby'" do stub_const "RUBY_ENGINE", 'ironruby' - @script.ruby_exe_options(:engine).should == 'ir' + expect(@script.ruby_exe_options(:engine)).to eq('ir') end it "returns 'maglev-ruby' when passed :engine and RUBY_ENGINE is 'maglev'" do stub_const "RUBY_ENGINE", 'maglev' - @script.ruby_exe_options(:engine).should == 'maglev-ruby' + expect(@script.ruby_exe_options(:engine)).to eq('maglev-ruby') end it "returns 'topaz' when passed :engine and RUBY_ENGINE is 'topaz'" do stub_const "RUBY_ENGINE", 'topaz' - @script.ruby_exe_options(:engine).should == 'topaz' + expect(@script.ruby_exe_options(:engine)).to eq('topaz') end it "returns RUBY_ENGINE + $(EXEEXT) when passed :name" do bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') name = File.join ".", bin - @script.ruby_exe_options(:name).should == name + expect(@script.ruby_exe_options(:name)).to eq(name) end it "returns $(bindir)/$(RUBY_INSTALL_NAME) + $(EXEEXT) when passed :install_name" do bin = RbConfig::CONFIG['RUBY_INSTALL_NAME'] + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') name = File.join RbConfig::CONFIG['bindir'], bin - @script.ruby_exe_options(:install_name).should == name + expect(@script.ruby_exe_options(:install_name)).to eq(name) end end -describe "#resolve_ruby_exe" do +RSpec.describe "#resolve_ruby_exe" do before :each do @name = "ruby_spec_exe" @script = RubyExeSpecs.new end it "returns the value returned by #ruby_exe_options if it exists and is executable" do - @script.should_receive(:ruby_exe_options).and_return(@name) - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return(@name) - @script.resolve_ruby_exe.should == @name + expect(@script).to receive(:ruby_exe_options).and_return(@name) + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return(@name) + expect(@script.resolve_ruby_exe).to eq(@name) end it "expands the path portion of the result of #ruby_exe_options" do - @script.should_receive(:ruby_exe_options).and_return("#{@name}") - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}") - @script.resolve_ruby_exe.should == "/usr/bin/#{@name}" + expect(@script).to receive(:ruby_exe_options).and_return("#{@name}") + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}") + expect(@script.resolve_ruby_exe).to eq("/usr/bin/#{@name}") end it "adds the flags after the executable" do @name = 'bin/rbx' - @script.should_receive(:ruby_exe_options).and_return(@name) - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return(@name) + expect(@script).to receive(:ruby_exe_options).and_return(@name) + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return(@name) - ENV.should_receive(:[]).with("RUBY_FLAGS").and_return('-X19') - @script.resolve_ruby_exe.should == 'bin/rbx -X19' + expect(ENV).to receive(:[]).with("RUBY_FLAGS").and_return('-X19') + expect(@script.resolve_ruby_exe).to eq('bin/rbx -X19') end it "raises an exception if no exe is found" do - File.should_receive(:file?).at_least(:once).and_return(false) - lambda { + expect(File).to receive(:file?).at_least(:once).and_return(false) + expect { @script.resolve_ruby_exe - }.should raise_error(Exception) + }.to raise_error(Exception) end end -describe Object, "#ruby_cmd" do +RSpec.describe Object, "#ruby_cmd" do before :each do stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q' @@ -115,83 +115,142 @@ class RubyExeSpecs end it "returns a command that runs the given file if it is a file that exists" do - File.should_receive(:exist?).with(@file).and_return(true) - @script.ruby_cmd(@file).should == "ruby_spec_exe -w -Q some/ruby/file.rb" + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@script.ruby_cmd(@file)).to eq("ruby_spec_exe -w -Q some/ruby/file.rb") end it "includes the given options and arguments with a file" do - File.should_receive(:exist?).with(@file).and_return(true) - @script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt").should == + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt")).to eq( "ruby_spec_exe -w -Q -w -Cdir some/ruby/file.rb < file.txt" + ) end it "includes the given options and arguments with -e" do - File.should_receive(:exist?).with(@code).and_return(false) - @script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt").should == + expect(File).to receive(:exist?).with(@code).and_return(false) + expect(@script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt")).to eq( %(ruby_spec_exe -w -Q -W0 -Cdir -e "some \\"real\\" 'ruby' code" < file.txt) + ) end it "returns a command with options and arguments but without code or file" do - @script.ruby_cmd(nil, :options => "-c", :args => "> file.txt").should == + expect(@script.ruby_cmd(nil, :options => "-c", :args => "> file.txt")).to eq( "ruby_spec_exe -w -Q -c > file.txt" + ) end end -describe Object, "#ruby_exe" do +RSpec.describe Object, "#ruby_exe" do before :each do stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q' @script = RubyExeSpecs.new - @script.stub(:`) + allow(@script).to receive(:`).and_return('OUTPUT') + + status_successful = double(Process::Status, exitstatus: 0) + allow(Process).to receive(:last_status).and_return(status_successful) + end + + it "returns command STDOUT when given command" do + code = "code" + options = {} + output = "output" + allow(@script).to receive(:`).and_return(output) + + expect(@script.ruby_exe(code, options)).to eq output end it "returns an Array containing the interpreter executable and flags when given no arguments" do - @script.ruby_exe.should == ['ruby_spec_exe', '-w', '-Q'] + expect(@script.ruby_exe).to eq(['ruby_spec_exe', '-w', '-Q']) end it "executes (using `) the result of calling #ruby_cmd with the given arguments" do code = "code" options = {} - @script.should_receive(:ruby_cmd).and_return("ruby_cmd") - @script.should_receive(:`).with("ruby_cmd") + expect(@script).to receive(:ruby_cmd).and_return("ruby_cmd") + expect(@script).to receive(:`).with("ruby_cmd") @script.ruby_exe(code, options) end + it "raises exception when command exit status is not successful" do + code = "code" + options = {} + + status_failed = double(Process::Status, exitstatus: 4) + allow(Process).to receive(:last_status).and_return(status_failed) + + expect { + @script.ruby_exe(code, options) + }.to raise_error(%r{Expected exit status is 0 but actual is 4 for command ruby_exe\(.+\)}) + end + + it "shows in the exception message if exitstatus is nil (e.g., signal)" do + code = "code" + options = {} + + status_failed = double(Process::Status, exitstatus: nil) + allow(Process).to receive(:last_status).and_return(status_failed) + + expect { + @script.ruby_exe(code, options) + }.to raise_error(%r{Expected exit status is 0 but actual is nil for command ruby_exe\(.+\)}) + end + describe "with :dir option" do it "is deprecated" do - lambda { + expect { @script.ruby_exe nil, :dir => "tmp" - }.should raise_error(/no longer supported, use Dir\.chdir/) + }.to raise_error(/no longer supported, use Dir\.chdir/) end end describe "with :env option" do it "preserves the values of existing ENV keys" do ENV["ABC"] = "123" - ENV.stub(:[]) - ENV.should_receive(:[]).with("ABC") + allow(ENV).to receive(:[]) + expect(ENV).to receive(:[]).with("ABC") @script.ruby_exe nil, :env => { :ABC => "xyz" } end it "adds the :env entries to ENV" do - ENV.should_receive(:[]=).with("ABC", "xyz") + expect(ENV).to receive(:[]=).with("ABC", "xyz") @script.ruby_exe nil, :env => { :ABC => "xyz" } end it "deletes the :env entries in ENV when an exception is raised" do - ENV.should_receive(:delete).with("XYZ") + expect(ENV).to receive(:delete).with("XYZ") @script.ruby_exe nil, :env => { :XYZ => "xyz" } end it "resets the values of existing ENV keys when an exception is raised" do ENV["ABC"] = "123" - ENV.should_receive(:[]=).with("ABC", "xyz") - ENV.should_receive(:[]=).with("ABC", "123") + expect(ENV).to receive(:[]=).with("ABC", "xyz") + expect(ENV).to receive(:[]=).with("ABC", "123") - @script.should_receive(:`).and_raise(Exception) - lambda do + expect(@script).to receive(:`).and_raise(Exception) + expect do @script.ruby_exe nil, :env => { :ABC => "xyz" } - end.should raise_error(Exception) + end.to raise_error(Exception) + end + end + + describe "with :exit_status option" do + before do + status_failed = double(Process::Status, exitstatus: 4) + allow(Process).to receive(:last_status).and_return(status_failed) + end + + it "raises exception when command ends with not expected status" do + expect { + @script.ruby_exe("path", exit_status: 1) + }.to raise_error(%r{Expected exit status is 1 but actual is 4 for command ruby_exe\(.+\)}) + end + + it "does not raise exception when command ends with expected status" do + output = "output" + allow(@script).to receive(:`).and_return(output) + + expect(@script.ruby_exe("path", exit_status: 4)).to eq output end end end diff --git a/ruby/spec/mspec/spec/helpers/scratch_spec.rb b/ruby/spec/mspec/spec/helpers/scratch_spec.rb index 6a9eb2cf7..9dbef94aa 100644 --- a/ruby/spec/mspec/spec/helpers/scratch_spec.rb +++ b/ruby/spec/mspec/spec/helpers/scratch_spec.rb @@ -2,23 +2,23 @@ require 'mspec/guards' require 'mspec/helpers' -describe ScratchPad do +RSpec.describe ScratchPad do it "records an object and returns a previously recorded object" do ScratchPad.record :this - ScratchPad.recorded.should == :this + expect(ScratchPad.recorded).to eq(:this) end it "clears the recorded object" do ScratchPad.record :that - ScratchPad.recorded.should == :that + expect(ScratchPad.recorded).to eq(:that) ScratchPad.clear - ScratchPad.recorded.should == nil + expect(ScratchPad.recorded).to eq(nil) end it "provides a convenience shortcut to append to a previously recorded object" do ScratchPad.record [] ScratchPad << :new ScratchPad << :another - ScratchPad.recorded.should == [:new, :another] + expect(ScratchPad.recorded).to eq([:new, :another]) end end diff --git a/ruby/spec/mspec/spec/helpers/suppress_warning_spec.rb b/ruby/spec/mspec/spec/helpers/suppress_warning_spec.rb index d16361fa5..4cae189bd 100644 --- a/ruby/spec/mspec/spec/helpers/suppress_warning_spec.rb +++ b/ruby/spec/mspec/spec/helpers/suppress_warning_spec.rb @@ -2,7 +2,7 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#suppress_warning" do +RSpec.describe Object, "#suppress_warning" do it "hides warnings" do suppress_warning do warn "should not be shown" @@ -14,6 +14,6 @@ suppress_warning do a = 1 end - a.should == 1 + expect(a).to eq(1) end end diff --git a/ruby/spec/mspec/spec/helpers/tmp_spec.rb b/ruby/spec/mspec/spec/helpers/tmp_spec.rb index afadc7f51..c41dcd57b 100644 --- a/ruby/spec/mspec/spec/helpers/tmp_spec.rb +++ b/ruby/spec/mspec/spec/helpers/tmp_spec.rb @@ -2,26 +2,26 @@ require 'mspec/guards' require 'mspec/helpers' -describe Object, "#tmp" do +RSpec.describe Object, "#tmp" do before :all do - @dir = "#{File.expand_path(Dir.pwd)}/rubyspec_temp" + @dir = SPEC_TEMP_DIR end it "returns a name relative to the current working directory" do - tmp("test.txt").should == "#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt" + expect(tmp("test.txt")).to eq("#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt") end it "returns a 'unique' name on repeated calls" do a = tmp("text.txt") b = tmp("text.txt") - a.should_not == b + expect(a).not_to eq(b) end it "does not 'uniquify' the name if requested not to" do - tmp("test.txt", false).should == "#{@dir}/test.txt" + expect(tmp("test.txt", false)).to eq("#{@dir}/test.txt") end it "returns the name of the temporary directory when passed an empty string" do - tmp("").should == "#{@dir}/" + expect(tmp("")).to eq("#{@dir}/") end end diff --git a/ruby/spec/mspec/spec/integration/interpreter_spec.rb b/ruby/spec/mspec/spec/integration/interpreter_spec.rb index b6fa6859d..dbf3987a0 100644 --- a/ruby/spec/mspec/spec/integration/interpreter_spec.rb +++ b/ruby/spec/mspec/spec/integration/interpreter_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "The interpreter passed with -t" do +RSpec.describe "The interpreter passed with -t" do it "is used in subprocess" do fixtures = "spec/fixtures" interpreter = "#{fixtures}/my_ruby" @@ -8,11 +8,11 @@ out = out.lines.map(&:chomp).reject { |line| line == 'RUBY_DESCRIPTION' }.take(3) - out.should == [ + expect(out).to eq([ interpreter, interpreter, "CWD/#{interpreter}" - ] - ret.success?.should == true + ]) + expect(ret.success?).to eq(true) end end diff --git a/ruby/spec/mspec/spec/integration/object_methods_spec.rb b/ruby/spec/mspec/spec/integration/object_methods_spec.rb index 3be704beb..697fbd10f 100644 --- a/ruby/spec/mspec/spec/integration/object_methods_spec.rb +++ b/ruby/spec/mspec/spec/integration/object_methods_spec.rb @@ -9,10 +9,10 @@ 1 file, 1 example, 1 expectation, 0 failures, 0 errors, 0 tagged EOS -describe "MSpec" do +RSpec.describe "MSpec" do it "does not define public methods on Object" do out, ret = run_mspec("run", "spec/fixtures/object_methods_spec.rb") - out.should == expected_output - ret.success?.should == true + expect(out).to eq(expected_output) + expect(ret.success?).to eq(true) end end diff --git a/ruby/spec/mspec/spec/integration/run_spec.rb b/ruby/spec/mspec/spec/integration/run_spec.rb index df10f7709..90dc05154 100644 --- a/ruby/spec/mspec/spec/integration/run_spec.rb +++ b/ruby/spec/mspec/spec/integration/run_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Running mspec" do +RSpec.describe "Running mspec" do a_spec_output = <' CWD/spec/fixtures/a_spec.rb:2:in `' -CWD/bin/mspec-run:7:in `
' 2) Foo#bar fails ERROR RuntimeError: failure CWD/spec/fixtures/a_spec.rb:12:in `block (2 levels) in ' CWD/spec/fixtures/a_spec.rb:2:in `' -CWD/bin/mspec-run:7:in `
' Finished in D.DDDDDD seconds EOS @@ -27,20 +25,20 @@ it "runs the specs" do out, ret = run_mspec("run", "#{fixtures}/a_spec.rb") - out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}") + expect(ret.success?).to eq(false) end it "directly with mspec-run runs the specs" do out, ret = run_mspec("-run", "#{fixtures}/a_spec.rb") - out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}") + expect(ret.success?).to eq(false) end it "runs the specs in parallel with -j using the dotted formatter" do out, ret = run_mspec("run", "-j #{fixtures}/a_spec.rb #{fixtures}/b_spec.rb") - out.should == "RUBY_DESCRIPTION\n...\n#{a_spec_output}\n#{ab_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n...\n#{a_spec_output}\n#{ab_stats}") + expect(ret.success?).to eq(false) end it "runs the specs in parallel with -j -fa" do @@ -49,25 +47,25 @@ "\r[/ | 0% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " + "\r[- | ==================50% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " + "\r[\\ | ==================100%================== | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " - out.should == "RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}") + expect(ret.success?).to eq(false) end it "gives a useful error message when a subprocess dies in parallel mode" do out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/die_spec.rb") lines = out.lines - lines.should include "A child mspec-run process died unexpectedly while running CWD/spec/fixtures/die_spec.rb\n" - lines.should include "Finished in D.DDDDDD seconds\n" - lines.last.should =~ /^\d files?, \d examples?, \d expectations?, 0 failures, 0 errors, 0 tagged$/ - ret.success?.should == false + expect(lines).to include "A child mspec-run process died unexpectedly while running CWD/spec/fixtures/die_spec.rb\n" + expect(lines).to include "Finished in D.DDDDDD seconds\n" + expect(lines.last).to match(/^\d files?, \d examples?, \d expectations?, 0 failures, 0 errors, 0 tagged$/) + expect(ret.success?).to eq(false) end it "gives a useful error message when a subprocess prints unexpected output on STDOUT in parallel mode" do out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/chatty_spec.rb") lines = out.lines - lines.should include "A child mspec-run process printed unexpected output on STDOUT: #{'"Hello\nIt\'s me!\n"'} while running CWD/spec/fixtures/chatty_spec.rb\n" - lines.should include "Finished in D.DDDDDD seconds\n" - lines.last.should == "2 files, 2 examples, 2 expectations, 0 failures, 0 errors, 0 tagged\n" - ret.success?.should == false + expect(lines).to include "A child mspec-run process printed unexpected output on STDOUT: #{'"Hello\nIt\'s me!\n"'} while running CWD/spec/fixtures/chatty_spec.rb\n" + expect(lines).to include "Finished in D.DDDDDD seconds\n" + expect(lines.last).to eq("2 files, 2 examples, 2 expectations, 0 failures, 0 errors, 0 tagged\n") + expect(ret.success?).to eq(false) end end diff --git a/ruby/spec/mspec/spec/integration/tag_spec.rb b/ruby/spec/mspec/spec/integration/tag_spec.rb index 1882d71e3..33df1cfd4 100644 --- a/ruby/spec/mspec/spec/integration/tag_spec.rb +++ b/ruby/spec/mspec/spec/integration/tag_spec.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require 'spec_helper' -describe "Running mspec tag" do +RSpec.describe "Running mspec tag" do before :all do FileUtils.rm_rf 'spec/fixtures/tags' end @@ -13,7 +13,7 @@ it "tags the failing specs" do fixtures = "spec/fixtures" out, ret = run_mspec("tag", "--add fails --fail #{fixtures}/tagging_spec.rb") - out.should == <' CWD/spec/fixtures/tagging_spec.rb:3:in `' -CWD/bin/mspec-tag:7:in `
' 2) Tag#me érròrs in unicode FAILED @@ -36,19 +35,18 @@ to be truthy but was false CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in ' CWD/spec/fixtures/tagging_spec.rb:3:in `' -CWD/bin/mspec-tag:7:in `
' Finished in D.DDDDDD seconds 1 file, 3 examples, 3 expectations, 2 failures, 0 errors, 0 tagged EOS - ret.success?.should == false + expect(ret.success?).to eq(false) end it "does not run already tagged specs" do fixtures = "spec/fixtures" out, ret = run_mspec("run", "--excl-tag fails #{fixtures}/tagging_spec.rb") - out.should == < operator" do +RSpec.describe SpecPositiveOperatorMatcher, "> operator" do it "provides a failure message that 'Expected x to be greater than y'" do - lambda { + expect { SpecPositiveOperatorMatcher.new(4) > 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false") + }.to raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false") end it "does not raise an exception when > returns true" do @@ -39,11 +39,11 @@ end end -describe SpecPositiveOperatorMatcher, ">= operator" do +RSpec.describe SpecPositiveOperatorMatcher, ">= operator" do it "provides a failure message that 'Expected x to be greater than or equal to y'" do - lambda { + expect { SpecPositiveOperatorMatcher.new(4) >= 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false") + }.to raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false") end it "does not raise an exception when > returns true" do @@ -52,11 +52,11 @@ end end -describe SpecPositiveOperatorMatcher, "< operator" do +RSpec.describe SpecPositiveOperatorMatcher, "< operator" do it "provides a failure message that 'Expected x to be less than y'" do - lambda { + expect { SpecPositiveOperatorMatcher.new(5) < 4 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false") + }.to raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false") end it "does not raise an exception when < returns true" do @@ -64,11 +64,11 @@ end end -describe SpecPositiveOperatorMatcher, "<= operator" do +RSpec.describe SpecPositiveOperatorMatcher, "<= operator" do it "provides a failure message that 'Expected x to be less than or equal to y'" do - lambda { + expect { SpecPositiveOperatorMatcher.new(5) <= 4 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false") + }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false") end it "does not raise an exception when < returns true" do @@ -77,7 +77,7 @@ end end -describe SpecPositiveOperatorMatcher, "arbitrary predicates" do +RSpec.describe SpecPositiveOperatorMatcher, "arbitrary predicates" do it "do not raise an exception when the predicate is truthy" do SpecPositiveOperatorMatcher.new(2).eql?(2) SpecPositiveOperatorMatcher.new(2).equal?(2) @@ -89,31 +89,31 @@ end it "provide a failure message when the predicate returns a falsy value" do - lambda { + expect { SpecPositiveOperatorMatcher.new(2).eql?(3) - }.should raise_error(SpecExpectationNotMetError, "Expected 2.eql? 3\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 3\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new(2).equal?(3) - }.should raise_error(SpecExpectationNotMetError, "Expected 2.equal? 3\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 3\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(4) - }.should raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 4\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 4\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new("abc").start_with?("de") - }.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"de\"\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"de\"\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new("abc").start_with?("d", "e") - }.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"e\"\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"e\"\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new(2).odd? - }.should raise_error(SpecExpectationNotMetError, "Expected 2.odd?\nto be truthy but was false") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 2.odd?\nto be truthy but was false") + expect { SpecPositiveOperatorMatcher.new([1, 3]).any? { |e| e.even? } - }.should raise_error(SpecExpectationNotMetError, "Expected [1, 3].any? { ... }\nto be truthy but was false") + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 3].any? { ... }\nto be truthy but was false") end end -describe SpecNegativeOperatorMatcher, "arbitrary predicates" do +RSpec.describe SpecNegativeOperatorMatcher, "arbitrary predicates" do it "do not raise an exception when the predicate returns a falsy value" do SpecNegativeOperatorMatcher.new(2).eql?(3) SpecNegativeOperatorMatcher.new(2).equal?(3) @@ -125,35 +125,35 @@ end it "provide a failure message when the predicate returns a truthy value" do - lambda { + expect { SpecNegativeOperatorMatcher.new(2).eql?(2) - }.should raise_error(SpecExpectationNotMetError, "Expected 2.eql? 2\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 2\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(2).equal?(2) - }.should raise_error(SpecExpectationNotMetError, "Expected 2.equal? 2\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 2\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(2) - }.should raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 2\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 2\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new("abc").start_with?("ab") - }.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"ab\"\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"ab\"\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new("abc").start_with?("d", "a") - }.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"a\"\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"a\"\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(3).odd? - }.should raise_error(SpecExpectationNotMetError, "Expected 3.odd?\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 3.odd?\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new([1, 2]).any? { |e| e.even? } - }.should raise_error(SpecExpectationNotMetError, "Expected [1, 2].any? { ... }\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2].any? { ... }\nto be falsy but was true") end end -describe SpecNegativeOperatorMatcher, "== operator" do +RSpec.describe SpecNegativeOperatorMatcher, "== operator" do it "provides a failure message that 'Expected x not to equal y'" do - lambda { + expect { SpecNegativeOperatorMatcher.new(1) == 1 - }.should raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true") end it "does not raise an exception when == returns false" do @@ -161,11 +161,11 @@ end end -describe SpecNegativeOperatorMatcher, "=~ operator" do +RSpec.describe SpecNegativeOperatorMatcher, "=~ operator" do it "provides a failure message that 'Expected \"x\" not to match /y/'" do - lambda { + expect { SpecNegativeOperatorMatcher.new('real') =~ /real/ - }.should raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0") + }.to raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0") end it "does not raise an exception when =~ returns false" do @@ -173,11 +173,11 @@ end end -describe SpecNegativeOperatorMatcher, "< operator" do +RSpec.describe SpecNegativeOperatorMatcher, "< operator" do it "provides a failure message that 'Expected x not to be less than y'" do - lambda { + expect { SpecNegativeOperatorMatcher.new(4) < 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true") end it "does not raise an exception when < returns false" do @@ -185,14 +185,14 @@ end end -describe SpecNegativeOperatorMatcher, "<= operator" do +RSpec.describe SpecNegativeOperatorMatcher, "<= operator" do it "provides a failure message that 'Expected x not to be less than or equal to y'" do - lambda { + expect { SpecNegativeOperatorMatcher.new(4) <= 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(5) <= 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true") end it "does not raise an exception when <= returns false" do @@ -200,11 +200,11 @@ end end -describe SpecNegativeOperatorMatcher, "> operator" do +RSpec.describe SpecNegativeOperatorMatcher, "> operator" do it "provides a failure message that 'Expected x not to be greater than y'" do - lambda { + expect { SpecNegativeOperatorMatcher.new(5) > 4 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true") end it "does not raise an exception when > returns false" do @@ -212,14 +212,14 @@ end end -describe SpecNegativeOperatorMatcher, ">= operator" do +RSpec.describe SpecNegativeOperatorMatcher, ">= operator" do it "provides a failure message that 'Expected x not to be greater than or equal to y'" do - lambda { + expect { SpecNegativeOperatorMatcher.new(5) >= 4 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true") - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(5) >= 5 - }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true") + }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true") end it "does not raise an exception when >= returns false" do diff --git a/ruby/spec/mspec/spec/matchers/be_an_instance_of_spec.rb b/ruby/spec/mspec/spec/matchers/be_an_instance_of_spec.rb index 7f2126df7..7c74249d2 100644 --- a/ruby/spec/mspec/spec/matchers/be_an_instance_of_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_an_instance_of_spec.rb @@ -13,38 +13,38 @@ class C < B end end -describe BeAnInstanceOfMatcher do +RSpec.describe BeAnInstanceOfMatcher do it "matches when actual is an instance_of? expected" do a = BeAnInOfSpecs::A.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a).should be_true + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a)).to be_truthy b = BeAnInOfSpecs::B.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b).should be_true + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b)).to be_truthy end it "does not match when actual is not an instance_of? expected" do a = BeAnInOfSpecs::A.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a)).to be_falsey b = BeAnInOfSpecs::B.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b)).to be_falsey c = BeAnInOfSpecs::C.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c).should be_false - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c)).to be_falsey + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c)).to be_falsey end it "provides a useful failure message" do matcher = BeAnInstanceOfMatcher.new(Numeric) matcher.matches?("string") - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to be an instance of Numeric"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to be an instance of Numeric"]) end it "provides a useful negative failure message" do matcher = BeAnInstanceOfMatcher.new(Numeric) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to be an instance of Numeric"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to be an instance of Numeric"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_ancestor_of_spec.rb b/ruby/spec/mspec/spec/matchers/be_ancestor_of_spec.rb index c6bd1a26c..abc05e0f7 100644 --- a/ruby/spec/mspec/spec/matchers/be_ancestor_of_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_ancestor_of_spec.rb @@ -5,24 +5,24 @@ class Parent; end class Child < Parent; end -describe BeAncestorOfMatcher do +RSpec.describe BeAncestorOfMatcher do it "matches when actual is an ancestor of expected" do - BeAncestorOfMatcher.new(Child).matches?(Parent).should == true + expect(BeAncestorOfMatcher.new(Child).matches?(Parent)).to eq(true) end it "does not match when actual is not an ancestor of expected" do - BeAncestorOfMatcher.new(Parent).matches?(Child).should == false + expect(BeAncestorOfMatcher.new(Parent).matches?(Child)).to eq(false) end it "provides a useful failure message" do matcher = BeAncestorOfMatcher.new(Parent) matcher.matches?(Child) - matcher.failure_message.should == ["Expected Child", "to be an ancestor of Parent"] + expect(matcher.failure_message).to eq(["Expected Child", "to be an ancestor of Parent"]) end it "provides a useful negative failure message" do matcher = BeAncestorOfMatcher.new(Child) matcher.matches?(Parent) - matcher.negative_failure_message.should == ["Expected Parent", "not to be an ancestor of Child"] + expect(matcher.negative_failure_message).to eq(["Expected Parent", "not to be an ancestor of Child"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_close_spec.rb b/ruby/spec/mspec/spec/matchers/be_close_spec.rb index 6edff98e4..dfd4f4ddb 100644 --- a/ruby/spec/mspec/spec/matchers/be_close_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_close_spec.rb @@ -3,46 +3,46 @@ require 'mspec/matchers' # Adapted from RSpec 1.0.8 -describe BeCloseMatcher do +RSpec.describe BeCloseMatcher do it "matches when actual == expected" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.0).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.0)).to eq(true) end it "matches when actual < (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.49).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.49)).to eq(true) end it "matches when actual > (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.51).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.51)).to eq(true) end it "matches when actual == (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.5).should == true - BeCloseMatcher.new(3, 2).matches?(5).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.5)).to eq(true) + expect(BeCloseMatcher.new(3, 2).matches?(5)).to eq(true) end it "matches when actual == (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.5).should == true - BeCloseMatcher.new(3, 2).matches?(1).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.5)).to eq(true) + expect(BeCloseMatcher.new(3, 2).matches?(1)).to eq(true) end it "does not match when actual < (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.49).should == false + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.49)).to eq(false) end it "does not match when actual > (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.51).should == false + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.51)).to eq(false) end it "provides a useful failure message" do matcher = BeCloseMatcher.new(5.0, 0.5) matcher.matches?(6.5) - matcher.failure_message.should == ["Expected 6.5", "to be within 5.0 +/- 0.5"] + expect(matcher.failure_message).to eq(["Expected 6.5", "to be within 5.0 +/- 0.5"]) end it "provides a useful negative failure message" do matcher = BeCloseMatcher.new(5.0, 0.5) matcher.matches?(4.9) - matcher.negative_failure_message.should == ["Expected 4.9", "not to be within 5.0 +/- 0.5"] + expect(matcher.negative_failure_message).to eq(["Expected 4.9", "not to be within 5.0 +/- 0.5"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_computed_by_spec.rb b/ruby/spec/mspec/spec/matchers/be_computed_by_spec.rb index 9833e211a..f73861a57 100644 --- a/ruby/spec/mspec/spec/matchers/be_computed_by_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_computed_by_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/matchers' -describe BeComputedByMatcher do +RSpec.describe BeComputedByMatcher do it "matches when all entries in the Array compute" do array = [ [65, "A"], [90, "Z"] ] - BeComputedByMatcher.new(:chr).matches?(array).should be_true + expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_truthy end it "matches when all entries in the Array with arguments compute" do array = [ [1, 2, 3], [2, 4, 6] ] - BeComputedByMatcher.new(:+).matches?(array).should be_true + expect(BeComputedByMatcher.new(:+).matches?(array)).to be_truthy end it "does not match when any entry in the Array does not compute" do array = [ [65, "A" ], [91, "Z" ] ] - BeComputedByMatcher.new(:chr).matches?(array).should be_false + expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_falsey end it "accepts an argument list to apply to each method call" do array = [ [65, "1000001" ], [90, "1011010" ] ] - BeComputedByMatcher.new(:to_s, 2).matches?(array).should be_true + expect(BeComputedByMatcher.new(:to_s, 2).matches?(array)).to be_truthy end it "does not match when any entry in the Array with arguments does not compute" do array = [ [1, 2, 3], [2, 4, 7] ] - BeComputedByMatcher.new(:+).matches?(array).should be_false + expect(BeComputedByMatcher.new(:+).matches?(array)).to be_falsey end it "provides a useful failure message" do @@ -37,6 +37,6 @@ [91, "Z" ] ] matcher = BeComputedByMatcher.new(:chr) matcher.matches?(array) - matcher.failure_message.should == ["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"] + expect(matcher.failure_message).to eq(["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_empty_spec.rb b/ruby/spec/mspec/spec/matchers/be_empty_spec.rb index cb8663f5e..30678fe85 100644 --- a/ruby/spec/mspec/spec/matchers/be_empty_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_empty_spec.rb @@ -2,25 +2,25 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeEmptyMatcher do +RSpec.describe BeEmptyMatcher do it "matches when actual is empty" do - BeEmptyMatcher.new.matches?("").should == true + expect(BeEmptyMatcher.new.matches?("")).to eq(true) end it "does not match when actual is not empty" do - BeEmptyMatcher.new.matches?([10]).should == false + expect(BeEmptyMatcher.new.matches?([10])).to eq(false) end it "provides a useful failure message" do matcher = BeEmptyMatcher.new matcher.matches?("not empty string") - matcher.failure_message.should == ["Expected \"not empty string\"", "to be empty"] + expect(matcher.failure_message).to eq(["Expected \"not empty string\"", "to be empty"]) end it "provides a useful negative failure message" do matcher = BeEmptyMatcher.new matcher.matches?("") - matcher.negative_failure_message.should == ["Expected \"\"", "not to be empty"] + expect(matcher.negative_failure_message).to eq(["Expected \"\"", "not to be empty"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_false_spec.rb b/ruby/spec/mspec/spec/matchers/be_false_spec.rb index 31afd24eb..46d725322 100644 --- a/ruby/spec/mspec/spec/matchers/be_false_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_false_spec.rb @@ -2,27 +2,27 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeFalseMatcher do +RSpec.describe BeFalseMatcher do it "matches when actual is false" do - BeFalseMatcher.new.matches?(false).should == true + expect(BeFalseMatcher.new.matches?(false)).to eq(true) end it "does not match when actual is not false" do - BeFalseMatcher.new.matches?("").should == false - BeFalseMatcher.new.matches?(true).should == false - BeFalseMatcher.new.matches?(nil).should == false - BeFalseMatcher.new.matches?(0).should == false + expect(BeFalseMatcher.new.matches?("")).to eq(false) + expect(BeFalseMatcher.new.matches?(true)).to eq(false) + expect(BeFalseMatcher.new.matches?(nil)).to eq(false) + expect(BeFalseMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeFalseMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be false"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be false"]) end it "provides a useful negative failure message" do matcher = BeFalseMatcher.new matcher.matches?(false) - matcher.negative_failure_message.should == ["Expected false", "not to be false"] + expect(matcher.negative_failure_message).to eq(["Expected false", "not to be false"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_kind_of_spec.rb b/ruby/spec/mspec/spec/matchers/be_kind_of_spec.rb index 7c4a59f7b..1e1905841 100644 --- a/ruby/spec/mspec/spec/matchers/be_kind_of_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_kind_of_spec.rb @@ -2,30 +2,30 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeKindOfMatcher do +RSpec.describe BeKindOfMatcher do it "matches when actual is a kind_of? expected" do - BeKindOfMatcher.new(Numeric).matches?(1).should == true - BeKindOfMatcher.new(Integer).matches?(2).should == true - BeKindOfMatcher.new(Regexp).matches?(/m/).should == true + expect(BeKindOfMatcher.new(Numeric).matches?(1)).to eq(true) + expect(BeKindOfMatcher.new(Integer).matches?(2)).to eq(true) + expect(BeKindOfMatcher.new(Regexp).matches?(/m/)).to eq(true) end it "does not match when actual is not a kind_of? expected" do - BeKindOfMatcher.new(Integer).matches?(1.5).should == false - BeKindOfMatcher.new(String).matches?(:a).should == false - BeKindOfMatcher.new(Hash).matches?([]).should == false + expect(BeKindOfMatcher.new(Integer).matches?(1.5)).to eq(false) + expect(BeKindOfMatcher.new(String).matches?(:a)).to eq(false) + expect(BeKindOfMatcher.new(Hash).matches?([])).to eq(false) end it "provides a useful failure message" do matcher = BeKindOfMatcher.new(Numeric) matcher.matches?('string') - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to be kind of Numeric"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to be kind of Numeric"]) end it "provides a useful negative failure message" do matcher = BeKindOfMatcher.new(Numeric) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to be kind of Numeric"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to be kind of Numeric"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_nan_spec.rb b/ruby/spec/mspec/spec/matchers/be_nan_spec.rb index 2062763a9..baa744794 100644 --- a/ruby/spec/mspec/spec/matchers/be_nan_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_nan_spec.rb @@ -4,25 +4,25 @@ require 'mspec/helpers' require 'mspec/matchers' -describe BeNaNMatcher do +RSpec.describe BeNaNMatcher do it "matches when actual is NaN" do - BeNaNMatcher.new.matches?(nan_value).should == true + expect(BeNaNMatcher.new.matches?(nan_value)).to eq(true) end it "does not match when actual is not NaN" do - BeNaNMatcher.new.matches?(1.0).should == false - BeNaNMatcher.new.matches?(0).should == false + expect(BeNaNMatcher.new.matches?(1.0)).to eq(false) + expect(BeNaNMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeNaNMatcher.new matcher.matches?(0) - matcher.failure_message.should == ["Expected 0", "to be NaN"] + expect(matcher.failure_message).to eq(["Expected 0", "to be NaN"]) end it "provides a useful negative failure message" do matcher = BeNaNMatcher.new matcher.matches?(nan_value) - matcher.negative_failure_message.should == ["Expected NaN", "not to be NaN"] + expect(matcher.negative_failure_message).to eq(["Expected NaN", "not to be NaN"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_nil_spec.rb b/ruby/spec/mspec/spec/matchers/be_nil_spec.rb index 6551feb5d..e2768acf8 100644 --- a/ruby/spec/mspec/spec/matchers/be_nil_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_nil_spec.rb @@ -2,26 +2,26 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeNilMatcher do +RSpec.describe BeNilMatcher do it "matches when actual is nil" do - BeNilMatcher.new.matches?(nil).should == true + expect(BeNilMatcher.new.matches?(nil)).to eq(true) end it "does not match when actual is not nil" do - BeNilMatcher.new.matches?("").should == false - BeNilMatcher.new.matches?(false).should == false - BeNilMatcher.new.matches?(0).should == false + expect(BeNilMatcher.new.matches?("")).to eq(false) + expect(BeNilMatcher.new.matches?(false)).to eq(false) + expect(BeNilMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeNilMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be nil"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be nil"]) end it "provides a useful negative failure message" do matcher = BeNilMatcher.new matcher.matches?(nil) - matcher.negative_failure_message.should == ["Expected nil", "not to be nil"] + expect(matcher.negative_failure_message).to eq(["Expected nil", "not to be nil"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_true_or_false_spec.rb b/ruby/spec/mspec/spec/matchers/be_true_or_false_spec.rb index 3edffcb1b..e4b456eaf 100644 --- a/ruby/spec/mspec/spec/matchers/be_true_or_false_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_true_or_false_spec.rb @@ -2,18 +2,18 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeTrueOrFalseMatcher do +RSpec.describe BeTrueOrFalseMatcher do it "matches when actual is true" do - BeTrueOrFalseMatcher.new.matches?(true).should == true + expect(BeTrueOrFalseMatcher.new.matches?(true)).to eq(true) end it "matches when actual is false" do - BeTrueOrFalseMatcher.new.matches?(false).should == true + expect(BeTrueOrFalseMatcher.new.matches?(false)).to eq(true) end it "provides a useful failure message" do matcher = BeTrueOrFalseMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be true or false"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true or false"]) end end diff --git a/ruby/spec/mspec/spec/matchers/be_true_spec.rb b/ruby/spec/mspec/spec/matchers/be_true_spec.rb index 90c89b391..39ef05a0f 100644 --- a/ruby/spec/mspec/spec/matchers/be_true_spec.rb +++ b/ruby/spec/mspec/spec/matchers/be_true_spec.rb @@ -2,27 +2,27 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeTrueMatcher do +RSpec.describe BeTrueMatcher do it "matches when actual is true" do - BeTrueMatcher.new.matches?(true).should == true + expect(BeTrueMatcher.new.matches?(true)).to eq(true) end it "does not match when actual is not true" do - BeTrueMatcher.new.matches?("").should == false - BeTrueMatcher.new.matches?(false).should == false - BeTrueMatcher.new.matches?(nil).should == false - BeTrueMatcher.new.matches?(0).should == false + expect(BeTrueMatcher.new.matches?("")).to eq(false) + expect(BeTrueMatcher.new.matches?(false)).to eq(false) + expect(BeTrueMatcher.new.matches?(nil)).to eq(false) + expect(BeTrueMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeTrueMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be true"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true"]) end it "provides a useful negative failure message" do matcher = BeTrueMatcher.new matcher.matches?(true) - matcher.negative_failure_message.should == ["Expected true", "not to be true"] + expect(matcher.negative_failure_message).to eq(["Expected true", "not to be true"]) end end diff --git a/ruby/spec/mspec/spec/matchers/block_caller_spec.rb b/ruby/spec/mspec/spec/matchers/block_caller_spec.rb index d6793b977..5d7085fa6 100644 --- a/ruby/spec/mspec/spec/matchers/block_caller_spec.rb +++ b/ruby/spec/mspec/spec/matchers/block_caller_spec.rb @@ -2,12 +2,12 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BlockingMatcher do +RSpec.describe BlockingMatcher do it 'matches when a Proc blocks the caller' do - BlockingMatcher.new.matches?(proc { sleep }).should == true + expect(BlockingMatcher.new.matches?(proc { sleep })).to eq(true) end it 'does not match when a Proc does not block the caller' do - BlockingMatcher.new.matches?(proc { 1 }).should == false + expect(BlockingMatcher.new.matches?(proc { 1 })).to eq(false) end end diff --git a/ruby/spec/mspec/spec/matchers/complain_spec.rb b/ruby/spec/mspec/spec/matchers/complain_spec.rb index 90f94c368..399ef3105 100644 --- a/ruby/spec/mspec/spec/matchers/complain_spec.rb +++ b/ruby/spec/mspec/spec/matchers/complain_spec.rb @@ -2,52 +2,57 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe ComplainMatcher do +RSpec.describe ComplainMatcher do it "matches when executing the proc results in output to $stderr" do proc = lambda { warn "I'm gonna tell yo mama" } - ComplainMatcher.new(nil).matches?(proc).should == true + expect(ComplainMatcher.new(nil).matches?(proc)).to eq(true) end it "matches when executing the proc results in the expected output to $stderr" do proc = lambda { warn "Que haces?" } - ComplainMatcher.new("Que haces?\n").matches?(proc).should == true - ComplainMatcher.new("Que pasa?\n").matches?(proc).should == false - ComplainMatcher.new(/Que/).matches?(proc).should == true - ComplainMatcher.new(/Quoi/).matches?(proc).should == false + expect(ComplainMatcher.new("Que haces?\n").matches?(proc)).to eq(true) + expect(ComplainMatcher.new("Que pasa?\n").matches?(proc)).to eq(false) + expect(ComplainMatcher.new(/Que/).matches?(proc)).to eq(true) + expect(ComplainMatcher.new(/Quoi/).matches?(proc)).to eq(false) end it "does not match when there is no output to $stderr" do - ComplainMatcher.new(nil).matches?(lambda {}).should == false + expect(ComplainMatcher.new(nil).matches?(lambda {})).to eq(false) end it "provides a useful failure message" do matcher = ComplainMatcher.new(nil) matcher.matches?(lambda { }) - matcher.failure_message.should == ["Expected a warning", "but received none"] + expect(matcher.failure_message).to eq(["Expected a warning", "but received none"]) matcher = ComplainMatcher.new("listen here") matcher.matches?(lambda { warn "look out" }) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected warning: \"listen here\"", "but got: \"look out\""] + ) matcher = ComplainMatcher.new(/talk/) matcher.matches?(lambda { warn "listen up" }) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected warning to match: /talk/", "but got: \"listen up\""] + ) end it "provides a useful negative failure message" do proc = lambda { warn "ouch" } matcher = ComplainMatcher.new(nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Unexpected warning: ", "\"ouch\""] + ) matcher = ComplainMatcher.new("ouchy") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected warning: \"ouchy\"", "but got: \"ouch\""] + ) matcher = ComplainMatcher.new(/ou/) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected warning not to match: /ou/", "but got: \"ouch\""] + ) end context "`verbose` option specified" do @@ -64,10 +69,10 @@ proc = lambda { verbose = $VERBOSE } ComplainMatcher.new(nil, verbose: true).matches?(proc) - verbose.should == true + expect(verbose).to eq(true) ComplainMatcher.new(nil, verbose: false).matches?(proc) - verbose.should == false + expect(verbose).to eq(false) end it "sets $VERBOSE with false by default" do @@ -75,15 +80,15 @@ proc = lambda { verbose = $VERBOSE } ComplainMatcher.new(nil).matches?(proc) - verbose.should == false + expect(verbose).to eq(false) end it "does not have side effect" do proc = lambda { safe_value = $VERBOSE } - lambda do + expect do ComplainMatcher.new(nil, verbose: true).matches?(proc) - end.should_not change { $VERBOSE } + end.not_to change { $VERBOSE } end it "accepts a verbose level as single argument" do @@ -91,7 +96,7 @@ proc = lambda { verbose = $VERBOSE } ComplainMatcher.new(verbose: true).matches?(proc) - verbose.should == true + expect(verbose).to eq(true) end end end diff --git a/ruby/spec/mspec/spec/matchers/eql_spec.rb b/ruby/spec/mspec/spec/matchers/eql_spec.rb index f29e6976d..66307d2a9 100644 --- a/ruby/spec/mspec/spec/matchers/eql_spec.rb +++ b/ruby/spec/mspec/spec/matchers/eql_spec.rb @@ -2,32 +2,32 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqlMatcher do +RSpec.describe EqlMatcher do it "matches when actual is eql? to expected" do - EqlMatcher.new(1).matches?(1).should == true - EqlMatcher.new(1.5).matches?(1.5).should == true - EqlMatcher.new("red").matches?("red").should == true - EqlMatcher.new(:blue).matches?(:blue).should == true - EqlMatcher.new(Object).matches?(Object).should == true + expect(EqlMatcher.new(1).matches?(1)).to eq(true) + expect(EqlMatcher.new(1.5).matches?(1.5)).to eq(true) + expect(EqlMatcher.new("red").matches?("red")).to eq(true) + expect(EqlMatcher.new(:blue).matches?(:blue)).to eq(true) + expect(EqlMatcher.new(Object).matches?(Object)).to eq(true) o = Object.new - EqlMatcher.new(o).matches?(o).should == true + expect(EqlMatcher.new(o).matches?(o)).to eq(true) end it "does not match when actual is not eql? to expected" do - EqlMatcher.new(1).matches?(1.0).should == false - EqlMatcher.new(Hash).matches?(Object).should == false + expect(EqlMatcher.new(1).matches?(1.0)).to eq(false) + expect(EqlMatcher.new(Hash).matches?(Object)).to eq(false) end it "provides a useful failure message" do matcher = EqlMatcher.new("red") matcher.matches?("red") - matcher.failure_message.should == ["Expected \"red\"", "to have same value and type as \"red\""] + expect(matcher.failure_message).to eq(["Expected \"red\"", "to have same value and type as \"red\""]) end it "provides a useful negative failure message" do matcher = EqlMatcher.new(1) matcher.matches?(1.0) - matcher.negative_failure_message.should == ["Expected 1.0", "not to have same value or type as 1"] + expect(matcher.negative_failure_message).to eq(["Expected 1.0", "not to have same value or type as 1"]) end end diff --git a/ruby/spec/mspec/spec/matchers/equal_element_spec.rb b/ruby/spec/mspec/spec/matchers/equal_element_spec.rb index 06fae762c..3a5ae4ede 100644 --- a/ruby/spec/mspec/spec/matchers/equal_element_spec.rb +++ b/ruby/spec/mspec/spec/matchers/equal_element_spec.rb @@ -2,74 +2,74 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqualElementMatcher do +RSpec.describe EqualElementMatcher do it "matches if it finds an element with the passed name, no matter what attributes/content" do - EqualElementMatcher.new("A").matches?('').should be_true - EqualElementMatcher.new("A").matches?('').should be_true - EqualElementMatcher.new("A").matches?('').should be_true + expect(EqualElementMatcher.new("A").matches?('')).to be_truthy + expect(EqualElementMatcher.new("A").matches?('')).to be_truthy + expect(EqualElementMatcher.new("A").matches?('')).to be_truthy - EqualElementMatcher.new("BASE").matches?('').should be_false - EqualElementMatcher.new("BASE").matches?('').should be_false - EqualElementMatcher.new("BASE").matches?('').should be_false - EqualElementMatcher.new("BASE").matches?('').should be_false - EqualElementMatcher.new("BASE").matches?('').should be_false + expect(EqualElementMatcher.new("BASE").matches?('')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('')).to be_falsey end it "matches if it finds an element with the passed name and the passed attributes" do - EqualElementMatcher.new("A", {}).matches?('').should be_true - EqualElementMatcher.new("A", nil).matches?('').should be_true - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('').should be_true + expect(EqualElementMatcher.new("A", {}).matches?('')).to be_truthy + expect(EqualElementMatcher.new("A", nil).matches?('')).to be_truthy + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('')).to be_truthy - EqualElementMatcher.new("A", {}).matches?('').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('').should be_false + expect(EqualElementMatcher.new("A", {}).matches?('')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('')).to be_falsey end it "matches if it finds an element with the passed name, the passed attributes and the passed content" do - EqualElementMatcher.new("A", {}, "").matches?('').should be_true - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('Example').should be_true + expect(EqualElementMatcher.new("A", {}, "").matches?('')).to be_truthy + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('Example')).to be_truthy - EqualElementMatcher.new("A", {}, "Test").matches?('').should be_false - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('').should be_false - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('Test').should be_false + expect(EqualElementMatcher.new("A", {}, "Test").matches?('')).to be_falsey + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('')).to be_falsey + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('Test')).to be_falsey end it "can match unclosed elements" do - EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('').should be_true - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('').should be_true - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('Example').should be_true + expect(EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('')).to be_truthy + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('')).to be_truthy + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('Example')).to be_truthy - EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('').should be_false - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('Example').should be_false - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('Example').should be_false + expect(EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('')).to be_falsey + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('Example')).to be_falsey + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('Example')).to be_falsey end it "provides a useful failure message" do equal_element = EqualElementMatcher.new("A", {}, "Test") - equal_element.matches?('').should be_false - equal_element.failure_message.should == [%{Expected ""}, %{to be a 'A' element with no attributes and "Test" as content}] + expect(equal_element.matches?('')).to be_falsey + expect(equal_element.failure_message).to eq([%{Expected ""}, %{to be a 'A' element with no attributes and "Test" as content}]) equal_element = EqualElementMatcher.new("A", {}, "") - equal_element.matches?('Test').should be_false - equal_element.failure_message.should == [%{Expected "Test"}, %{to be a 'A' element with no attributes and no content}] + expect(equal_element.matches?('Test')).to be_falsey + expect(equal_element.failure_message).to eq([%{Expected "Test"}, %{to be a 'A' element with no attributes and no content}]) equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") - equal_element.matches?('Test').should be_false - equal_element.failure_message.should == [%{Expected "Test"}, %{to be a 'A' element with HREF="http://www.example.com" and any content}] + expect(equal_element.matches?('Test')).to be_falsey + expect(equal_element.failure_message).to eq([%{Expected "Test"}, %{to be a 'A' element with HREF="http://www.example.com" and any content}]) end it "provides a useful negative failure message" do equal_element = EqualElementMatcher.new("A", {}, "Test") - equal_element.matches?('').should be_false - equal_element.negative_failure_message.should == [%{Expected ""}, %{not to be a 'A' element with no attributes and "Test" as content}] + expect(equal_element.matches?('')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{Expected ""}, %{not to be a 'A' element with no attributes and "Test" as content}]) equal_element = EqualElementMatcher.new("A", {}, "") - equal_element.matches?('Test').should be_false - equal_element.negative_failure_message.should == [%{Expected "Test"}, %{not to be a 'A' element with no attributes and no content}] + expect(equal_element.matches?('Test')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{Expected "Test"}, %{not to be a 'A' element with no attributes and no content}]) equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") - equal_element.matches?('Test').should be_false - equal_element.negative_failure_message.should == [%{Expected "Test"}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}] + expect(equal_element.matches?('Test')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{Expected "Test"}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}]) end end diff --git a/ruby/spec/mspec/spec/matchers/equal_spec.rb b/ruby/spec/mspec/spec/matchers/equal_spec.rb index a61432b75..2df1de54b 100644 --- a/ruby/spec/mspec/spec/matchers/equal_spec.rb +++ b/ruby/spec/mspec/spec/matchers/equal_spec.rb @@ -2,31 +2,31 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqualMatcher do +RSpec.describe EqualMatcher do it "matches when actual is equal? to expected" do - EqualMatcher.new(1).matches?(1).should == true - EqualMatcher.new(:blue).matches?(:blue).should == true - EqualMatcher.new(Object).matches?(Object).should == true + expect(EqualMatcher.new(1).matches?(1)).to eq(true) + expect(EqualMatcher.new(:blue).matches?(:blue)).to eq(true) + expect(EqualMatcher.new(Object).matches?(Object)).to eq(true) o = Object.new - EqualMatcher.new(o).matches?(o).should == true + expect(EqualMatcher.new(o).matches?(o)).to eq(true) end it "does not match when actual is not a equal? to expected" do - EqualMatcher.new(1).matches?(1.0).should == false - EqualMatcher.new("blue").matches?("blue").should == false - EqualMatcher.new(Hash).matches?(Object).should == false + expect(EqualMatcher.new(1).matches?(1.0)).to eq(false) + expect(EqualMatcher.new("blue").matches?("blue")).to eq(false) + expect(EqualMatcher.new(Hash).matches?(Object)).to eq(false) end it "provides a useful failure message" do matcher = EqualMatcher.new("red") matcher.matches?("red") - matcher.failure_message.should == ["Expected \"red\"", "to be identical to \"red\""] + expect(matcher.failure_message).to eq(["Expected \"red\"", "to be identical to \"red\""]) end it "provides a useful negative failure message" do matcher = EqualMatcher.new(1) matcher.matches?(1) - matcher.negative_failure_message.should == ["Expected 1", "not to be identical to 1"] + expect(matcher.negative_failure_message).to eq(["Expected 1", "not to be identical to 1"]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_class_variable_spec.rb b/ruby/spec/mspec/spec/matchers/have_class_variable_spec.rb index 01ba9d0f5..d6fcf9d4e 100644 --- a/ruby/spec/mspec/spec/matchers/have_class_variable_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_class_variable_spec.rb @@ -8,42 +8,42 @@ def self.class_variables end end -describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do +RSpec.describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do it "matches when mod has the class variable, given as string" do matcher = HaveClassVariableMatcher.new('@foo') - matcher.matches?(IVarModMock).should be_true + expect(matcher.matches?(IVarModMock)).to be_truthy end it "matches when mod has the class variable, given as symbol" do matcher = HaveClassVariableMatcher.new(:@foo) - matcher.matches?(IVarModMock).should be_true + expect(matcher.matches?(IVarModMock)).to be_truthy end it "does not match when mod hasn't got the class variable, given as string" do matcher = HaveClassVariableMatcher.new('@bar') - matcher.matches?(IVarModMock).should be_false + expect(matcher.matches?(IVarModMock)).to be_falsey end it "does not match when mod hasn't got the class variable, given as symbol" do matcher = HaveClassVariableMatcher.new(:@bar) - matcher.matches?(IVarModMock).should be_false + expect(matcher.matches?(IVarModMock)).to be_falsey end it "provides a failure message for #should" do matcher = HaveClassVariableMatcher.new(:@bar) matcher.matches?(IVarModMock) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected IVarModMock to have class variable '@bar'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveClassVariableMatcher.new(:@bar) matcher.matches?(IVarModMock) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected IVarModMock NOT to have class variable '@bar'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_constant_spec.rb b/ruby/spec/mspec/spec/matchers/have_constant_spec.rb index 20c5f161d..0bf44dbe2 100644 --- a/ruby/spec/mspec/spec/matchers/have_constant_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_constant_spec.rb @@ -6,32 +6,32 @@ class HCMSpecs X = :x end -describe HaveConstantMatcher do +RSpec.describe HaveConstantMatcher do it "matches when mod has the constant" do matcher = HaveConstantMatcher.new :X - matcher.matches?(HCMSpecs).should be_true + expect(matcher.matches?(HCMSpecs)).to be_truthy end it "does not match when mod does not have the constant" do matcher = HaveConstantMatcher.new :A - matcher.matches?(HCMSpecs).should be_false + expect(matcher.matches?(HCMSpecs)).to be_falsey end it "provides a failure message for #should" do matcher = HaveConstantMatcher.new :A matcher.matches?(HCMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HCMSpecs to have constant 'A'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveConstantMatcher.new :X matcher.matches?(HCMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HCMSpecs NOT to have constant 'X'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_instance_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_instance_method_spec.rb index 738f5f875..7c2e50dba 100644 --- a/ruby/spec/mspec/spec/matchers/have_instance_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_instance_method_spec.rb @@ -12,42 +12,42 @@ def instance_sub_method end end -describe HaveInstanceMethodMatcher do +RSpec.describe HaveInstanceMethodMatcher do it "inherits from MethodMatcher" do - HaveInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the instance method" do matcher = HaveInstanceMethodMatcher.new :instance_method - matcher.matches?(HIMMSpecs).should be_true - matcher.matches?(HIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HIMMSpecs)).to be_truthy + expect(matcher.matches?(HIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the instance method" do matcher = HaveInstanceMethodMatcher.new :another_method - matcher.matches?(HIMMSpecs).should be_false + expect(matcher.matches?(HIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveInstanceMethodMatcher.new :instance_method, false - matcher.matches?(HIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveInstanceMethodMatcher.new :some_method matcher.matches?(HIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HIMMSpecs to have instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveInstanceMethodMatcher.new :some_method matcher.matches?(HIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HIMMSpecs NOT to have instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_instance_variable_spec.rb b/ruby/spec/mspec/spec/matchers/have_instance_variable_spec.rb index 4122c6551..12e2470f1 100644 --- a/ruby/spec/mspec/spec/matchers/have_instance_variable_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_instance_variable_spec.rb @@ -2,7 +2,7 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe HaveInstanceVariableMatcher do +RSpec.describe HaveInstanceVariableMatcher do before :each do @object = Object.new def @object.instance_variables @@ -12,39 +12,39 @@ def @object.instance_variables it "matches when object has the instance variable, given as string" do matcher = HaveInstanceVariableMatcher.new('@foo') - matcher.matches?(@object).should be_true + expect(matcher.matches?(@object)).to be_truthy end it "matches when object has the instance variable, given as symbol" do matcher = HaveInstanceVariableMatcher.new(:@foo) - matcher.matches?(@object).should be_true + expect(matcher.matches?(@object)).to be_truthy end it "does not match when object hasn't got the instance variable, given as string" do matcher = HaveInstanceVariableMatcher.new('@bar') - matcher.matches?(@object).should be_false + expect(matcher.matches?(@object)).to be_falsey end it "does not match when object hasn't got the instance variable, given as symbol" do matcher = HaveInstanceVariableMatcher.new(:@bar) - matcher.matches?(@object).should be_false + expect(matcher.matches?(@object)).to be_falsey end it "provides a failure message for #should" do matcher = HaveInstanceVariableMatcher.new(:@bar) matcher.matches?(@object) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected #{@object.inspect} to have instance variable '@bar'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveInstanceVariableMatcher.new(:@bar) matcher.matches?(@object) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected #{@object.inspect} NOT to have instance variable '@bar'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_method_spec.rb index 41bd48511..4fc0bf5e4 100644 --- a/ruby/spec/mspec/spec/matchers/have_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_method_spec.rb @@ -12,44 +12,44 @@ def instance_sub_method end end -describe HaveMethodMatcher do +RSpec.describe HaveMethodMatcher do it "inherits from MethodMatcher" do - HaveMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the method" do matcher = HaveMethodMatcher.new :instance_method - matcher.matches?(HMMSpecs).should be_true - matcher.matches?(HMMSpecs.new).should be_true - matcher.matches?(HMMSpecs::Subclass).should be_true - matcher.matches?(HMMSpecs::Subclass.new).should be_true + expect(matcher.matches?(HMMSpecs)).to be_truthy + expect(matcher.matches?(HMMSpecs.new)).to be_truthy + expect(matcher.matches?(HMMSpecs::Subclass)).to be_truthy + expect(matcher.matches?(HMMSpecs::Subclass.new)).to be_truthy end it "does not match when mod does not have the method" do matcher = HaveMethodMatcher.new :another_method - matcher.matches?(HMMSpecs).should be_false + expect(matcher.matches?(HMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveMethodMatcher.new :instance_method, false - matcher.matches?(HMMSpecs::Subclass).should be_false + expect(matcher.matches?(HMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveMethodMatcher.new :some_method matcher.matches?(HMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HMMSpecs to have method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveMethodMatcher.new :some_method matcher.matches?(HMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HMMSpecs NOT to have method 'some_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_private_instance_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_private_instance_method_spec.rb index 827c6b603..0e65c264d 100644 --- a/ruby/spec/mspec/spec/matchers/have_private_instance_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_private_instance_method_spec.rb @@ -16,42 +16,42 @@ def private_sub_method end end -describe HavePrivateInstanceMethodMatcher do +RSpec.describe HavePrivateInstanceMethodMatcher do it "inherits from MethodMatcher" do - HavePrivateInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePrivateInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the private instance method" do matcher = HavePrivateInstanceMethodMatcher.new :private_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the private instance method" do matcher = HavePrivateInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HavePrivateInstanceMethodMatcher.new :private_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HavePrivateInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have private instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HavePrivateInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have private instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_private_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_private_method_spec.rb index e63a9a3c2..f43328805 100644 --- a/ruby/spec/mspec/spec/matchers/have_private_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_private_method_spec.rb @@ -9,36 +9,36 @@ def self.private_method private_class_method :private_method end -describe HavePrivateMethodMatcher do +RSpec.describe HavePrivateMethodMatcher do it "inherits from MethodMatcher" do - HavePrivateMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePrivateMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the private method" do matcher = HavePrivateMethodMatcher.new :private_method - matcher.matches?(HPMMSpecs).should be_true + expect(matcher.matches?(HPMMSpecs)).to be_truthy end it "does not match when mod does not have the private method" do matcher = HavePrivateMethodMatcher.new :another_method - matcher.matches?(HPMMSpecs).should be_false + expect(matcher.matches?(HPMMSpecs)).to be_falsey end it "provides a failure message for #should" do matcher = HavePrivateMethodMatcher.new :some_method matcher.matches?(HPMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPMMSpecs to have private method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HavePrivateMethodMatcher.new :private_method matcher.matches?(HPMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPMMSpecs NOT to have private method 'private_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb index 460d0368f..45b39004a 100644 --- a/ruby/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb @@ -16,42 +16,42 @@ def protected_sub_method end end -describe HaveProtectedInstanceMethodMatcher do +RSpec.describe HaveProtectedInstanceMethodMatcher do it "inherits from MethodMatcher" do - HaveProtectedInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveProtectedInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the protected instance method" do matcher = HaveProtectedInstanceMethodMatcher.new :protected_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the protected instance method" do matcher = HaveProtectedInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveProtectedInstanceMethodMatcher.new :protected_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveProtectedInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have protected instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveProtectedInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have protected instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_public_instance_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_public_instance_method_spec.rb index bff1046f0..771d5b791 100644 --- a/ruby/spec/mspec/spec/matchers/have_public_instance_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_public_instance_method_spec.rb @@ -12,42 +12,42 @@ def public_sub_method end end -describe HavePublicInstanceMethodMatcher do +RSpec.describe HavePublicInstanceMethodMatcher do it "inherits from MethodMatcher" do - HavePublicInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePublicInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the public instance method" do matcher = HavePublicInstanceMethodMatcher.new :public_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the public instance method" do matcher = HavePublicInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HavePublicInstanceMethodMatcher.new :public_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HavePublicInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have public instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HavePublicInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have public instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/have_singleton_method_spec.rb b/ruby/spec/mspec/spec/matchers/have_singleton_method_spec.rb index 57c37e01d..61ef00d49 100644 --- a/ruby/spec/mspec/spec/matchers/have_singleton_method_spec.rb +++ b/ruby/spec/mspec/spec/matchers/have_singleton_method_spec.rb @@ -7,14 +7,14 @@ def self.singleton_method end end -describe HaveSingletonMethodMatcher do +RSpec.describe HaveSingletonMethodMatcher do it "inherits from MethodMatcher" do - HaveSingletonMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveSingletonMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when the class has a singleton method" do matcher = HaveSingletonMethodMatcher.new :singleton_method - matcher.matches?(HSMMSpecs).should be_true + expect(matcher.matches?(HSMMSpecs)).to be_truthy end it "matches when the object has a singleton method" do @@ -22,24 +22,24 @@ def self.singleton_method def obj.singleton_method; end matcher = HaveSingletonMethodMatcher.new :singleton_method - matcher.matches?(obj).should be_true + expect(matcher.matches?(obj)).to be_truthy end it "provides a failure message for #should" do matcher = HaveSingletonMethodMatcher.new :some_method matcher.matches?(HSMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HSMMSpecs to have singleton method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HaveSingletonMethodMatcher.new :singleton_method matcher.matches?(HSMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HSMMSpecs NOT to have singleton method 'singleton_method'", "but it does" - ] + ]) end end diff --git a/ruby/spec/mspec/spec/matchers/include_any_of_spec.rb b/ruby/spec/mspec/spec/matchers/include_any_of_spec.rb index 697c8d888..1473bb6d0 100644 --- a/ruby/spec/mspec/spec/matchers/include_any_of_spec.rb +++ b/ruby/spec/mspec/spec/matchers/include_any_of_spec.rb @@ -2,41 +2,41 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe IncludeAnyOfMatcher do +RSpec.describe IncludeAnyOfMatcher do it "matches when actual includes expected" do - IncludeAnyOfMatcher.new(2).matches?([1,2,3]).should == true - IncludeAnyOfMatcher.new("b").matches?("abc").should == true + expect(IncludeAnyOfMatcher.new(2).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("b").matches?("abc")).to eq(true) end it "does not match when actual does not include expected" do - IncludeAnyOfMatcher.new(4).matches?([1,2,3]).should == false - IncludeAnyOfMatcher.new("d").matches?("abc").should == false + expect(IncludeAnyOfMatcher.new(4).matches?([1,2,3])).to eq(false) + expect(IncludeAnyOfMatcher.new("d").matches?("abc")).to eq(false) end it "matches when actual includes all expected" do - IncludeAnyOfMatcher.new(3, 2, 1).matches?([1,2,3]).should == true - IncludeAnyOfMatcher.new("a", "b", "c").matches?("abc").should == true + expect(IncludeAnyOfMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("a", "b", "c").matches?("abc")).to eq(true) end it "matches when actual includes any expected" do - IncludeAnyOfMatcher.new(3, 4, 5).matches?([1,2,3]).should == true - IncludeAnyOfMatcher.new("c", "d", "e").matches?("abc").should == true + expect(IncludeAnyOfMatcher.new(3, 4, 5).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("c", "d", "e").matches?("abc")).to eq(true) end it "does not match when actual does not include any expected" do - IncludeAnyOfMatcher.new(4, 5).matches?([1,2,3]).should == false - IncludeAnyOfMatcher.new("de").matches?("abc").should == false + expect(IncludeAnyOfMatcher.new(4, 5).matches?([1,2,3])).to eq(false) + expect(IncludeAnyOfMatcher.new("de").matches?("abc")).to eq(false) end it "provides a useful failure message" do matcher = IncludeAnyOfMatcher.new(5, 6) matcher.matches?([1,2,3]) - matcher.failure_message.should == ["Expected [1, 2, 3]", "to include any of [5, 6]"] + expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include any of [5, 6]"]) end it "provides a useful negative failure message" do matcher = IncludeAnyOfMatcher.new(1, 2, 3) matcher.matches?([1,2]) - matcher.negative_failure_message.should == ["Expected [1, 2]", "not to include any of [1, 2, 3]"] + expect(matcher.negative_failure_message).to eq(["Expected [1, 2]", "not to include any of [1, 2, 3]"]) end end diff --git a/ruby/spec/mspec/spec/matchers/include_spec.rb b/ruby/spec/mspec/spec/matchers/include_spec.rb index f045c5e0c..6bf1bef08 100644 --- a/ruby/spec/mspec/spec/matchers/include_spec.rb +++ b/ruby/spec/mspec/spec/matchers/include_spec.rb @@ -2,36 +2,36 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe IncludeMatcher do +RSpec.describe IncludeMatcher do it "matches when actual includes expected" do - IncludeMatcher.new(2).matches?([1,2,3]).should == true - IncludeMatcher.new("b").matches?("abc").should == true + expect(IncludeMatcher.new(2).matches?([1,2,3])).to eq(true) + expect(IncludeMatcher.new("b").matches?("abc")).to eq(true) end it "does not match when actual does not include expected" do - IncludeMatcher.new(4).matches?([1,2,3]).should == false - IncludeMatcher.new("d").matches?("abc").should == false + expect(IncludeMatcher.new(4).matches?([1,2,3])).to eq(false) + expect(IncludeMatcher.new("d").matches?("abc")).to eq(false) end it "matches when actual includes all expected" do - IncludeMatcher.new(3, 2, 1).matches?([1,2,3]).should == true - IncludeMatcher.new("a", "b", "c").matches?("abc").should == true + expect(IncludeMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true) + expect(IncludeMatcher.new("a", "b", "c").matches?("abc")).to eq(true) end it "does not match when actual does not include all expected" do - IncludeMatcher.new(3, 2, 4).matches?([1,2,3]).should == false - IncludeMatcher.new("a", "b", "c", "d").matches?("abc").should == false + expect(IncludeMatcher.new(3, 2, 4).matches?([1,2,3])).to eq(false) + expect(IncludeMatcher.new("a", "b", "c", "d").matches?("abc")).to eq(false) end it "provides a useful failure message" do matcher = IncludeMatcher.new(5, 2) matcher.matches?([1,2,3]) - matcher.failure_message.should == ["Expected [1, 2, 3]", "to include 5"] + expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include 5"]) end it "provides a useful negative failure message" do matcher = IncludeMatcher.new(1, 2, 3) matcher.matches?([1,2,3]) - matcher.negative_failure_message.should == ["Expected [1, 2, 3]", "not to include 3"] + expect(matcher.negative_failure_message).to eq(["Expected [1, 2, 3]", "not to include 3"]) end end diff --git a/ruby/spec/mspec/spec/matchers/infinity_spec.rb b/ruby/spec/mspec/spec/matchers/infinity_spec.rb index 6eb8ac294..78c419452 100644 --- a/ruby/spec/mspec/spec/matchers/infinity_spec.rb +++ b/ruby/spec/mspec/spec/matchers/infinity_spec.rb @@ -4,31 +4,31 @@ require 'mspec/helpers' require 'mspec/matchers' -describe InfinityMatcher do +RSpec.describe InfinityMatcher do it "matches when actual is infinite and has the correct sign" do - InfinityMatcher.new(1).matches?(infinity_value).should == true - InfinityMatcher.new(-1).matches?(-infinity_value).should == true + expect(InfinityMatcher.new(1).matches?(infinity_value)).to eq(true) + expect(InfinityMatcher.new(-1).matches?(-infinity_value)).to eq(true) end it "does not match when actual is not infinite" do - InfinityMatcher.new(1).matches?(1.0).should == false - InfinityMatcher.new(-1).matches?(-1.0).should == false + expect(InfinityMatcher.new(1).matches?(1.0)).to eq(false) + expect(InfinityMatcher.new(-1).matches?(-1.0)).to eq(false) end it "does not match when actual is infinite but has the incorrect sign" do - InfinityMatcher.new(1).matches?(-infinity_value).should == false - InfinityMatcher.new(-1).matches?(infinity_value).should == false + expect(InfinityMatcher.new(1).matches?(-infinity_value)).to eq(false) + expect(InfinityMatcher.new(-1).matches?(infinity_value)).to eq(false) end it "provides a useful failure message" do matcher = InfinityMatcher.new(-1) matcher.matches?(0) - matcher.failure_message.should == ["Expected 0", "to be -Infinity"] + expect(matcher.failure_message).to eq(["Expected 0", "to be -Infinity"]) end it "provides a useful negative failure message" do matcher = InfinityMatcher.new(1) matcher.matches?(infinity_value) - matcher.negative_failure_message.should == ["Expected Infinity", "not to be Infinity"] + expect(matcher.negative_failure_message).to eq(["Expected Infinity", "not to be Infinity"]) end end diff --git a/ruby/spec/mspec/spec/matchers/match_yaml_spec.rb b/ruby/spec/mspec/spec/matchers/match_yaml_spec.rb index 4f16aee0e..85123bb87 100644 --- a/ruby/spec/mspec/spec/matchers/match_yaml_spec.rb +++ b/ruby/spec/mspec/spec/matchers/match_yaml_spec.rb @@ -2,38 +2,38 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe MatchYAMLMatcher do +RSpec.describe MatchYAMLMatcher do before :each do @matcher = MatchYAMLMatcher.new("--- \nfoo: bar\n") end it "compares YAML documents and matches if they're equivalent" do - @matcher.matches?("--- \nfoo: bar\n").should == true + expect(@matcher.matches?("--- \nfoo: bar\n")).to eq(true) end it "compares YAML documents and does not match if they're not equivalent" do - @matcher.matches?("--- \nbar: foo\n").should == false - @matcher.matches?("--- \nfoo: \nbar\n").should == false + expect(@matcher.matches?("--- \nbar: foo\n")).to eq(false) + expect(@matcher.matches?("--- \nfoo: \nbar\n")).to eq(false) end it "also receives objects that respond_to to_yaml" do matcher = MatchYAMLMatcher.new("some string") - matcher.matches?("some string").should == true + expect(matcher.matches?("some string")).to eq(true) matcher = MatchYAMLMatcher.new(['a', 'b']) - matcher.matches?("--- \n- a\n- b\n").should == true + expect(matcher.matches?("--- \n- a\n- b\n")).to eq(true) matcher = MatchYAMLMatcher.new("foo" => "bar") - matcher.matches?("--- \nfoo: bar\n").should == true + expect(matcher.matches?("--- \nfoo: bar\n")).to eq(true) end it "matches documents with trailing whitespace" do - @matcher.matches?("--- \nfoo: bar \n").should == true - @matcher.matches?("--- \nfoo: bar \n").should == true + expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true) + expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true) end it "fails with a descriptive error message" do - @matcher.matches?("foo").should == false - @matcher.failure_message.should == ["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""] + expect(@matcher.matches?("foo")).to eq(false) + expect(@matcher.failure_message).to eq(["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""]) end end diff --git a/ruby/spec/mspec/spec/matchers/output_spec.rb b/ruby/spec/mspec/spec/matchers/output_spec.rb index 264da3b56..3baad9a4b 100644 --- a/ruby/spec/mspec/spec/matchers/output_spec.rb +++ b/ruby/spec/mspec/spec/matchers/output_spec.rb @@ -2,73 +2,83 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe OutputMatcher do +RSpec.describe OutputMatcher do it "matches when executing the proc results in the expected output to $stdout" do proc = Proc.new { puts "bang!" } - OutputMatcher.new("bang!\n", nil).matches?(proc).should == true - OutputMatcher.new("pop", nil).matches?(proc).should == false - OutputMatcher.new(/bang/, nil).matches?(proc).should == true - OutputMatcher.new(/po/, nil).matches?(proc).should == false + expect(OutputMatcher.new("bang!\n", nil).matches?(proc)).to eq(true) + expect(OutputMatcher.new("pop", nil).matches?(proc)).to eq(false) + expect(OutputMatcher.new(/bang/, nil).matches?(proc)).to eq(true) + expect(OutputMatcher.new(/po/, nil).matches?(proc)).to eq(false) end it "matches when executing the proc results in the expected output to $stderr" do proc = Proc.new { $stderr.write "boom!" } - OutputMatcher.new(nil, "boom!").matches?(proc).should == true - OutputMatcher.new(nil, "fizzle").matches?(proc).should == false - OutputMatcher.new(nil, /boom/).matches?(proc).should == true - OutputMatcher.new(nil, /fizzl/).matches?(proc).should == false + expect(OutputMatcher.new(nil, "boom!").matches?(proc)).to eq(true) + expect(OutputMatcher.new(nil, "fizzle").matches?(proc)).to eq(false) + expect(OutputMatcher.new(nil, /boom/).matches?(proc)).to eq(true) + expect(OutputMatcher.new(nil, /fizzl/).matches?(proc)).to eq(false) end it "provides a useful failure message" do proc = Proc.new { print "unexpected"; $stderr.print "unerror" } matcher = OutputMatcher.new("expected", "error") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: \"expected\"\n $stderr: \"error\"\n", " got:\n $stdout: \"unexpected\"\n $stderr: \"unerror\"\n"] + ) matcher = OutputMatcher.new("expected", nil) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: \"expected\"\n", " got:\n $stdout: \"unexpected\"\n"] + ) matcher = OutputMatcher.new(nil, "error") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stderr: \"error\"\n", " got:\n $stderr: \"unerror\"\n"] + ) matcher = OutputMatcher.new(/base/, nil) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: /base/\n", " got:\n $stdout: \"unexpected\"\n"] + ) matcher = OutputMatcher.new(nil, /octave/) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stderr: /octave/\n", " got:\n $stderr: \"unerror\"\n"] + ) end it "provides a useful negative failure message" do proc = Proc.new { puts "expected"; $stderr.puts "error" } matcher = OutputMatcher.new("expected", "error") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n $stderr: \"error\"\n"] + ) matcher = OutputMatcher.new("expected", nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n"] + ) matcher = OutputMatcher.new(nil, "error") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stderr: \"error\"\n"] + ) matcher = OutputMatcher.new(/expect/, nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n"] + ) matcher = OutputMatcher.new(nil, /err/) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stderr: \"error\"\n"] + ) end end diff --git a/ruby/spec/mspec/spec/matchers/output_to_fd_spec.rb b/ruby/spec/mspec/spec/matchers/output_to_fd_spec.rb index e584c4e00..a39cab320 100644 --- a/ruby/spec/mspec/spec/matchers/output_to_fd_spec.rb +++ b/ruby/spec/mspec/spec/matchers/output_to_fd_spec.rb @@ -2,43 +2,43 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe OutputToFDMatcher do +RSpec.describe OutputToFDMatcher do # Figure out how in the hell to achieve this it "matches when running the block produces the expected output to the given FD" do - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" }).should == true + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" })).to eq(true) end it "does not match if running the block does not produce the expected output to the FD" do - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") }).should == false + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") })).to eq(false) end it "propagate the exception if one is thrown while matching" do exc = RuntimeError.new("propagates") - lambda { - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { + expect { + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { raise exc - }).should == false - }.should raise_error(exc) + })).to eq(false) + }.to raise_error(exc) end it "defaults to matching against STDOUT" do object = Object.new object.extend MSpecMatchers - object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" }).should == true + expect(object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" })).to eq(true) end it "accepts any IO instance" do io = IO.new STDOUT.fileno - OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" }).should == true + expect(OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" })).to eq(true) end it "allows matching with a Regexp" do s = "Hi there\n" - OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s }).should == false + expect(OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s })).to eq(false) end end diff --git a/ruby/spec/mspec/spec/matchers/raise_error_spec.rb b/ruby/spec/mspec/spec/matchers/raise_error_spec.rb index 1ed794e0a..8613eee11 100644 --- a/ruby/spec/mspec/spec/matchers/raise_error_spec.rb +++ b/ruby/spec/mspec/spec/matchers/raise_error_spec.rb @@ -1,105 +1,153 @@ require 'spec_helper' -require 'mspec/expectations/expectations' -require 'mspec/matchers' class ExpectedException < Exception; end class UnexpectedException < Exception; end -describe RaiseErrorMatcher do +RSpec.describe RaiseErrorMatcher do + before :each do + state = double("run state").as_null_object + allow(MSpec).to receive(:current).and_return(state) + end + it "matches when the proc raises the expected exception" do proc = Proc.new { raise ExpectedException } matcher = RaiseErrorMatcher.new(ExpectedException, nil) - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end - it "executes it's optional block if matched" do + it "executes its optional {/} block if matched" do + ensure_mspec_method(-> {}.method(:should)) + run = false - proc = Proc.new { raise ExpectedException } - matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error| + -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error { |error| + expect(error.class).to eq(ExpectedException) run = true - error.class.should == ExpectedException } + expect(run).to eq(true) + end + + it "executes its optional do/end block if matched" do + ensure_mspec_method(-> {}.method(:should)) - matcher.matches?(proc).should == true - run.should == true + run = false + -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error do |error| + expect(error.class).to eq(ExpectedException) + run = true + end + expect(run).to eq(true) end it "matches when the proc raises the expected exception with the expected message" do proc = Proc.new { raise ExpectedException, "message" } matcher = RaiseErrorMatcher.new(ExpectedException, "message") - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end it "matches when the proc raises the expected exception with a matching message" do proc = Proc.new { raise ExpectedException, "some message" } matcher = RaiseErrorMatcher.new(ExpectedException, /some/) - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end it "does not match when the proc does not raise the expected exception" do exc = UnexpectedException.new matcher = RaiseErrorMatcher.new(ExpectedException, nil) - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + expect { matcher.matches?(Proc.new { raise exc }) - }.should raise_error(UnexpectedException) + }.to raise_error(UnexpectedException) end it "does not match when the proc raises the expected exception with an unexpected message" do exc = ExpectedException.new("unexpected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + expect { matcher.matches?(Proc.new { raise exc }) - }.should raise_error(ExpectedException) + }.to raise_error(ExpectedException) end it "does not match when the proc does not raise an exception" do proc = Proc.new {} matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matches?(proc).should == false + expect(matcher.matches?(proc)).to eq(false) end - it "provides a useful failure message" do - exc = UnexpectedException.new("unexpected") - matcher = RaiseErrorMatcher.new(ExpectedException, "expected") + it "provides a useful failure message when the exception class differs" do + exc = UnexpectedException.new("message") + matcher = RaiseErrorMatcher.new(ExpectedException, "message") - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + begin matcher.matches?(Proc.new { raise exc }) - }.should raise_error(UnexpectedException) - matcher.failure_message.should == - ["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"] + rescue UnexpectedException => e + expect(matcher.failure_message).to eq( + ["Expected ExpectedException (message)", "but got: UnexpectedException (message)"] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException (message)\nbut got: UnexpectedException (message)" + ) + else + raise "no exception" + end end it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do exc = ExpectedException.new("unexpected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + begin + matcher.matches?(Proc.new { raise exc }) + rescue ExpectedException => e + expect(matcher.failure_message).to eq( + ["Expected ExpectedException (expected)", "but got: ExpectedException (unexpected)"] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException (expected)\nbut got: ExpectedException (unexpected)" + ) + else + raise "no exception" + end + end + + it "provides a useful failure message when both the exception class and message differ" do + exc = UnexpectedException.new("unexpected") + matcher = RaiseErrorMatcher.new(ExpectedException, "expected") + + expect(matcher.matching_exception?(exc)).to eq(false) + begin matcher.matches?(Proc.new { raise exc }) - }.should raise_error(ExpectedException) - matcher.failure_message.should == - ["Expected ExpectedException (expected)", "but got ExpectedException (unexpected)"] + rescue UnexpectedException => e + expect(matcher.failure_message).to eq( + ["Expected ExpectedException (expected)", "but got: UnexpectedException (unexpected)"] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException (expected)\nbut got: UnexpectedException (unexpected)" + ) + else + raise "no exception" + end end it "provides a useful failure message when no exception is raised" do proc = Proc.new { 120 } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected ExpectedException (expected)", "but no exception was raised (120 was returned)"] + ) end it "provides a useful failure message when no exception is raised and nil is returned" do proc = Proc.new { nil } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected ExpectedException (expected)", "but no exception was raised (nil was returned)"] + ) end it "provides a useful failure message when no exception is raised and the result raises in #pretty_inspect" do @@ -110,23 +158,26 @@ def result.pretty_inspect proc = Proc.new { result } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected ExpectedException (expected)", "but no exception was raised (#(#pretty_inspect raised #) was returned)"] + ) end it "provides a useful negative failure message" do proc = Proc.new { raise ExpectedException, "expected" } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected to not get ExpectedException (expected)", ""] + ) end it "provides a useful negative failure message for strict subclasses of the matched exception class" do proc = Proc.new { raise UnexpectedException, "unexpected" } matcher = RaiseErrorMatcher.new(Exception, nil) matcher.matches?(proc) - matcher.negative_failure_message.should == - ["Expected to not get Exception", "but got UnexpectedException (unexpected)"] + expect(matcher.negative_failure_message).to eq( + ["Expected to not get Exception", "but got: UnexpectedException (unexpected)"] + ) end end diff --git a/ruby/spec/mspec/spec/matchers/respond_to_spec.rb b/ruby/spec/mspec/spec/matchers/respond_to_spec.rb index 988caf4df..6f1cd8d14 100644 --- a/ruby/spec/mspec/spec/matchers/respond_to_spec.rb +++ b/ruby/spec/mspec/spec/matchers/respond_to_spec.rb @@ -2,32 +2,32 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe RespondToMatcher do +RSpec.describe RespondToMatcher do it "matches when actual does respond_to? expected" do - RespondToMatcher.new(:to_s).matches?(Object.new).should == true - RespondToMatcher.new(:inject).matches?([]).should == true - RespondToMatcher.new(:[]).matches?(1).should == true - RespondToMatcher.new(:[]=).matches?("string").should == true + expect(RespondToMatcher.new(:to_s).matches?(Object.new)).to eq(true) + expect(RespondToMatcher.new(:inject).matches?([])).to eq(true) + expect(RespondToMatcher.new(:[]).matches?(1)).to eq(true) + expect(RespondToMatcher.new(:[]=).matches?("string")).to eq(true) end it "does not match when actual does not respond_to? expected" do - RespondToMatcher.new(:to_i).matches?(Object.new).should == false - RespondToMatcher.new(:inject).matches?(1).should == false - RespondToMatcher.new(:non_existent_method).matches?([]).should == false - RespondToMatcher.new(:[]=).matches?(1).should == false + expect(RespondToMatcher.new(:to_i).matches?(Object.new)).to eq(false) + expect(RespondToMatcher.new(:inject).matches?(1)).to eq(false) + expect(RespondToMatcher.new(:non_existent_method).matches?([])).to eq(false) + expect(RespondToMatcher.new(:[]=).matches?(1)).to eq(false) end it "provides a useful failure message" do matcher = RespondToMatcher.new(:non_existent_method) matcher.matches?('string') - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to respond to non_existent_method"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to respond to non_existent_method"]) end it "provides a useful negative failure message" do matcher = RespondToMatcher.new(:to_i) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to respond to to_i"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to respond to to_i"]) end end diff --git a/ruby/spec/mspec/spec/matchers/signed_zero_spec.rb b/ruby/spec/mspec/spec/matchers/signed_zero_spec.rb index 9c5c50c60..6d1c1007b 100644 --- a/ruby/spec/mspec/spec/matchers/signed_zero_spec.rb +++ b/ruby/spec/mspec/spec/matchers/signed_zero_spec.rb @@ -2,31 +2,31 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' -describe SignedZeroMatcher do +RSpec.describe SignedZeroMatcher do it "matches when actual is zero and has the correct sign" do - SignedZeroMatcher.new(1).matches?(0.0).should == true - SignedZeroMatcher.new(-1).matches?(-0.0).should == true + expect(SignedZeroMatcher.new(1).matches?(0.0)).to eq(true) + expect(SignedZeroMatcher.new(-1).matches?(-0.0)).to eq(true) end it "does not match when actual is non-zero" do - SignedZeroMatcher.new(1).matches?(1.0).should == false - SignedZeroMatcher.new(-1).matches?(-1.0).should == false + expect(SignedZeroMatcher.new(1).matches?(1.0)).to eq(false) + expect(SignedZeroMatcher.new(-1).matches?(-1.0)).to eq(false) end it "does not match when actual is zero but has the incorrect sign" do - SignedZeroMatcher.new(1).matches?(-0.0).should == false - SignedZeroMatcher.new(-1).matches?(0.0).should == false + expect(SignedZeroMatcher.new(1).matches?(-0.0)).to eq(false) + expect(SignedZeroMatcher.new(-1).matches?(0.0)).to eq(false) end it "provides a useful failure message" do matcher = SignedZeroMatcher.new(-1) matcher.matches?(0.0) - matcher.failure_message.should == ["Expected 0.0", "to be -0.0"] + expect(matcher.failure_message).to eq(["Expected 0.0", "to be -0.0"]) end it "provides a useful negative failure message" do matcher = SignedZeroMatcher.new(-1) matcher.matches?(-0.0) - matcher.negative_failure_message.should == ["Expected -0.0", "not to be -0.0"] + expect(matcher.negative_failure_message).to eq(["Expected -0.0", "not to be -0.0"]) end end diff --git a/ruby/spec/mspec/spec/mocks/mock_spec.rb b/ruby/spec/mspec/spec/mocks/mock_spec.rb index 8cf04cf46..73f9bdfa1 100644 --- a/ruby/spec/mspec/spec/mocks/mock_spec.rb +++ b/ruby/spec/mspec/spec/mocks/mock_spec.rb @@ -7,78 +7,78 @@ require 'mspec/mocks/mock' require 'mspec/mocks/proxy' -describe Mock, ".mocks" do +RSpec.describe Mock, ".mocks" do it "returns a Hash" do - Mock.mocks.should be_kind_of(Hash) + expect(Mock.mocks).to be_kind_of(Hash) end end -describe Mock, ".stubs" do +RSpec.describe Mock, ".stubs" do it "returns a Hash" do - Mock.stubs.should be_kind_of(Hash) + expect(Mock.stubs).to be_kind_of(Hash) end end -describe Mock, ".replaced_name" do +RSpec.describe Mock, ".replaced_name" do it "returns the name for a method that is being replaced by a mock method" do m = double('a fake id') - Mock.replaced_name(m, :method_call).should == :"__mspec_#{m.object_id}_method_call__" + expect(Mock.replaced_name(m, :method_call)).to eq(:"__mspec_#{m.object_id}_method_call__") end end -describe Mock, ".replaced_key" do +RSpec.describe Mock, ".replaced_key" do it "returns a key used internally by Mock" do m = double('a fake id') - Mock.replaced_key(m, :method_call).should == [:"__mspec_#{m.object_id}_method_call__", :method_call] + expect(Mock.replaced_key(m, :method_call)).to eq([:"__mspec_#{m.object_id}_method_call__", :method_call]) end end -describe Mock, ".replaced?" do +RSpec.describe Mock, ".replaced?" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end it "returns true if a method has been stubbed on an object" do Mock.install_method @mock, :method_call - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true + expect(Mock.replaced?(Mock.replaced_name(@mock, :method_call))).to be_truthy end it "returns true if a method has been mocked on an object" do Mock.install_method @mock, :method_call, :stub - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true + expect(Mock.replaced?(Mock.replaced_name(@mock, :method_call))).to be_truthy end it "returns false if a method has not been stubbed or mocked" do - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_false + expect(Mock.replaced?(Mock.replaced_name(@mock, :method_call))).to be_falsey end end -describe Mock, ".name_or_inspect" do +RSpec.describe Mock, ".name_or_inspect" do before :each do @mock = double("I have a #name") end it "returns the value of @name if set" do @mock.instance_variable_set(:@name, "Myself") - Mock.name_or_inspect(@mock).should == "Myself" + expect(Mock.name_or_inspect(@mock)).to eq("Myself") end end -describe Mock, ".install_method for mocks" do +RSpec.describe Mock, ".install_method for mocks" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do - Mock.cleanup + Mock.reset end it "returns a MockProxy instance" do - Mock.install_method(@mock, :method_call).should be_an_instance_of(MockProxy) + expect(Mock.install_method(@mock, :method_call)).to be_an_instance_of(MockProxy) end it "does not override a previously mocked method with the same name" do @@ -86,7 +86,7 @@ Mock.install_method(@mock, :method_call).with(:c).and_return(2) @mock.method_call(:a, :b) @mock.method_call(:c) - lambda { @mock.method_call(:d) }.should raise_error(SpecExpectationNotMetError) + expect { @mock.method_call(:d) }.to raise_error(SpecExpectationNotMetError) end # This illustrates RSpec's behavior. This spec fails in mock call count verification @@ -105,44 +105,44 @@ # it "does not override a previously mocked method having the same arguments" do Mock.install_method(@mock, :method_call).with(:a).and_return(true) - @mock.method_call(:a).should == true + expect(@mock.method_call(:a)).to eq(true) Mock.install_method(@mock, :method_call).with(:a).and_return(false) - @mock.method_call(:a).should == true - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect(@mock.method_call(:a)).to eq(true) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "properly sends #respond_to? calls to the aliased respond_to? method when not matching mock expectations" do Mock.install_method(@mock, :respond_to?).with(:to_str).and_return('mock to_str') Mock.install_method(@mock, :respond_to?).with(:to_int).and_return('mock to_int') - @mock.respond_to?(:to_str).should == 'mock to_str' - @mock.respond_to?(:to_int).should == 'mock to_int' - @mock.respond_to?(:to_s).should == true - @mock.respond_to?(:not_really_a_real_method_seriously).should == false + expect(@mock.respond_to?(:to_str)).to eq('mock to_str') + expect(@mock.respond_to?(:to_int)).to eq('mock to_int') + expect(@mock.respond_to?(:to_s)).to eq(true) + expect(@mock.respond_to?(:not_really_a_real_method_seriously)).to eq(false) end it "adds to the expectation tally" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_receive(:current).and_return(state) - MSpec.should_receive(:actions).with(:expectation, state.state) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).to receive(:current).and_return(state) + expect(MSpec).to receive(:actions).with(:expectation, state.state) Mock.install_method(@mock, :method_call).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end it "registers that an expectation has been encountered" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_receive(:expectation) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).to receive(:expectation) Mock.install_method(@mock, :method_call).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end end -describe Mock, ".install_method for stubs" do +RSpec.describe Mock, ".install_method for stubs" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do @@ -150,7 +150,7 @@ end it "returns a MockProxy instance" do - Mock.install_method(@mock, :method_call, :stub).should be_an_instance_of(MockProxy) + expect(Mock.install_method(@mock, :method_call, :stub)).to be_an_instance_of(MockProxy) end # This illustrates RSpec's behavior. This spec passes on RSpec and we mimic it @@ -166,26 +166,26 @@ # end it "inserts new stubs before old stubs" do Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(true) - @mock.method_call(:a).should == true + expect(@mock.method_call(:a)).to eq(true) Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(false) - @mock.method_call(:a).should == false + expect(@mock.method_call(:a)).to eq(false) Mock.verify_count end it "does not add to the expectation tally" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_not_receive(:actions) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).not_to receive(:actions) Mock.install_method(@mock, :method_call, :stub).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end end -describe Mock, ".install_method" do +RSpec.describe Mock, ".install_method" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do @@ -193,24 +193,24 @@ end it "does not alias a mocked or stubbed method when installing a new mock or stub" do - @mock.should_not respond_to(:method_call) + expect(@mock).not_to respond_to(:method_call) Mock.install_method @mock, :method_call - @mock.should respond_to(:method_call) - @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call)) + expect(@mock).to respond_to(:method_call) + expect(@mock).not_to respond_to(Mock.replaced_name(@mock, :method_call)) Mock.install_method @mock, :method_call, :stub - @mock.should respond_to(:method_call) - @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call)) + expect(@mock).to respond_to(:method_call) + expect(@mock).not_to respond_to(Mock.replaced_name(@mock, :method_call)) end end class MockAndRaiseError < Exception; end -describe Mock, ".verify_call" do +RSpec.describe Mock, ".verify_call" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_call') @proxy = Mock.install_method @mock, :method_call @@ -228,23 +228,23 @@ class MockAndRaiseError < Exception; end it "raises an SpecExpectationNotMetError when the mock method does not receive the expected arguments" do @proxy.with(4, 2) - lambda { + expect { Mock.verify_call @mock, :method_call, 42 - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock method is called with arguments but expects none" do - lambda { + expect { @proxy.with(:no_args) Mock.verify_call @mock, :method_call, "hello" - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock method is called with no arguments but expects some" do @proxy.with("hello", "beautiful", "world") - lambda { + expect { Mock.verify_call @mock, :method_call - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock method is called with arguments and is expecting :any_args" do @@ -257,14 +257,14 @@ class MockAndRaiseError < Exception; end Mock.verify_call @mock, :method_call do ScratchPad.record true end - ScratchPad.recorded.should == true + expect(ScratchPad.recorded).to eq(true) end it "does not yield a passed block when it is not expected to" do Mock.verify_call @mock, :method_call do ScratchPad.record true end - ScratchPad.recorded.should == nil + expect(ScratchPad.recorded).to eq(nil) end it "can yield subsequently" do @@ -274,28 +274,28 @@ class MockAndRaiseError < Exception; end Mock.verify_call @mock, :method_call do |arg| ScratchPad << arg end - ScratchPad.recorded.should == [1, 2, 3] + expect(ScratchPad.recorded).to eq([1, 2, 3]) end it "can yield and return an expected value" do @proxy.and_yield(1).and_return(3) - Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }.should == 3 - ScratchPad.recorded.should == 1 + expect(Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }).to eq(3) + expect(ScratchPad.recorded).to eq(1) end it "raises an exception when it is expected to yield but no block is given" do @proxy.and_yield(1, 2, 3) - lambda { + expect { Mock.verify_call(@mock, :method_call) - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an exception when it is expected to yield more arguments than the block can take" do @proxy.and_yield(1, 2, 3) - lambda { + expect { Mock.verify_call(@mock, :method_call) {|a, b|} - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when it is expected to yield to a block that can take any number of arguments" do @@ -307,16 +307,16 @@ class MockAndRaiseError < Exception; end it "raises an exception when expected to" do @proxy.and_raise(MockAndRaiseError) - lambda { + expect { Mock.verify_call @mock, :method_call - }.should raise_error(MockAndRaiseError) + }.to raise_error(MockAndRaiseError) end end -describe Mock, ".verify_call mixing mocks and stubs" do +RSpec.describe Mock, ".verify_call mixing mocks and stubs" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_call') end @@ -330,17 +330,17 @@ class MockAndRaiseError < Exception; end Mock.install_method @mock, :method_call, :stub Mock.install_method(@mock, :method_call, :mock).with("arg") - -> { + expect { @mock.method_call - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) - -> { + expect { @mock.method_call("a", "b") - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) - -> { + expect { @mock.method_call("foo") - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) @mock.method_call("arg") end @@ -349,26 +349,26 @@ class MockAndRaiseError < Exception; end Mock.install_method(@mock, :method_call, :mock).with("arg") Mock.install_method @mock, :method_call, :stub - -> { + expect { @mock.method_call - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) - -> { + expect { @mock.method_call("a", "b") - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) - -> { + expect { @mock.method_call("foo") - }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) @mock.method_call("arg") end end -describe Mock, ".verify_count" do +RSpec.describe Mock, ".verify_count" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_count') @proxy = Mock.install_method @mock, :method_call @@ -388,7 +388,7 @@ class MockAndRaiseError < Exception; end it "raises an SpecExpectationNotMetError when the mock receives less than at least the expected number of calls" do @proxy.at_least(2) @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock receives at most the expected number of calls" do @@ -403,7 +403,7 @@ class MockAndRaiseError < Exception; end @mock.method_call @mock.method_call @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock receives exactly the expected number of calls" do @@ -416,7 +416,7 @@ class MockAndRaiseError < Exception; end it "raises an SpecExpectationNotMetError when the mock receives less than exactly the expected number of calls" do @proxy.exactly(2) @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock receives more than exactly the expected number of calls" do @@ -424,14 +424,14 @@ class MockAndRaiseError < Exception; end @mock.method_call @mock.method_call @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end end -describe Mock, ".verify_count mixing mocks and stubs" do +RSpec.describe Mock, ".verify_count mixing mocks and stubs" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_count') end @@ -449,9 +449,9 @@ class MockAndRaiseError < Exception; end Mock.install_method @mock, :method_call, :stub Mock.install_method @mock, :method_call, :mock - -> { + expect { Mock.verify_count - }.should raise_error(SpecExpectationNotMetError, /received it 0 times/) + }.to raise_error(SpecExpectationNotMetError, /received it 0 times/) @mock.method_call Mock.verify_count @@ -461,19 +461,19 @@ class MockAndRaiseError < Exception; end Mock.install_method @mock, :method_call, :mock Mock.install_method @mock, :method_call, :stub - -> { + expect { Mock.verify_count - }.should raise_error(SpecExpectationNotMetError, /received it 0 times/) + }.to raise_error(SpecExpectationNotMetError, /received it 0 times/) @mock.method_call Mock.verify_count end end -describe Mock, ".cleanup" do +RSpec.describe Mock, ".cleanup" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('cleanup') @proxy = Mock.install_method @mock, :method_call @@ -484,47 +484,47 @@ class MockAndRaiseError < Exception; end end it "removes the mock method call if it did not override an existing method" do - @mock.should respond_to(:method_call) + expect(@mock).to respond_to(:method_call) Mock.cleanup - @mock.should_not respond_to(:method_call) + expect(@mock).not_to respond_to(:method_call) end it "removes the replaced method if the mock method overrides an existing method" do def @mock.already_here() :hey end - @mock.should respond_to(:already_here) + expect(@mock).to respond_to(:already_here) replaced_name = Mock.replaced_name(@mock, :already_here) Mock.install_method @mock, :already_here - @mock.should respond_to(replaced_name) + expect(@mock).to respond_to(replaced_name) Mock.cleanup - @mock.should_not respond_to(replaced_name) - @mock.should respond_to(:already_here) - @mock.already_here.should == :hey + expect(@mock).not_to respond_to(replaced_name) + expect(@mock).to respond_to(:already_here) + expect(@mock.already_here).to eq(:hey) end it "removes all mock expectations" do - Mock.mocks.should == { Mock.replaced_key(@mock, :method_call) => [@proxy] } + expect(Mock.mocks).to eq({ Mock.replaced_key(@mock, :method_call) => [@proxy] }) Mock.cleanup - Mock.mocks.should == {} + expect(Mock.mocks).to eq({}) end it "removes all stubs" do Mock.cleanup # remove @proxy @stub = Mock.install_method @mock, :method_call, :stub - Mock.stubs.should == { Mock.replaced_key(@mock, :method_call) => [@stub] } + expect(Mock.stubs).to eq({ Mock.replaced_key(@mock, :method_call) => [@stub] }) Mock.cleanup - Mock.stubs.should == {} + expect(Mock.stubs).to eq({}) end it "removes the replaced name for mocks" do replaced_key = Mock.replaced_key(@mock, :method_call) - Mock.should_receive(:clear_replaced).with(replaced_key) + expect(Mock).to receive(:clear_replaced).with(replaced_key) replaced_name = Mock.replaced_name(@mock, :method_call) - Mock.replaced?(replaced_name).should be_true + expect(Mock.replaced?(replaced_name)).to be_truthy Mock.cleanup - Mock.replaced?(replaced_name).should be_false + expect(Mock.replaced?(replaced_name)).to be_falsey end end diff --git a/ruby/spec/mspec/spec/mocks/proxy_spec.rb b/ruby/spec/mspec/spec/mocks/proxy_spec.rb index d9e754b97..b99463469 100644 --- a/ruby/spec/mspec/spec/mocks/proxy_spec.rb +++ b/ruby/spec/mspec/spec/mocks/proxy_spec.rb @@ -1,276 +1,276 @@ require 'spec_helper' require 'mspec/mocks/proxy' -describe MockObject, ".new" do +RSpec.describe MockObject, ".new" do it "creates a new mock object" do m = MockObject.new('not a null object') - lambda { m.not_a_method }.should raise_error(NoMethodError) + expect { m.not_a_method }.to raise_error(NoMethodError) end it "creates a new mock object that follows the NullObject pattern" do m = MockObject.new('null object', :null_object => true) - m.not_really_a_method.should equal(m) + expect(m.not_really_a_method).to equal(m) end end -describe MockProxy, ".new" do +RSpec.describe MockProxy, ".new" do it "creates a mock proxy by default" do - MockProxy.new.mock?.should be_true + expect(MockProxy.new.mock?).to be_truthy end it "creates a stub proxy by request" do - MockProxy.new(:stub).stub?.should be_true + expect(MockProxy.new(:stub).stub?).to be_truthy end it "sets the call expectation to 1 call for a mock" do - MockProxy.new.count.should == [:exactly, 1] + expect(MockProxy.new.count).to eq([:exactly, 1]) end it "sets the call expectation to any number of times for a stub" do - MockProxy.new(:stub).count.should == [:any_number_of_times, 0] + expect(MockProxy.new(:stub).count).to eq([:any_number_of_times, 0]) end end -describe MockProxy, "#count" do +RSpec.describe MockProxy, "#count" do before :each do @proxy = MockProxy.new end it "returns the expected number of calls the mock should receive" do - @proxy.count.should == [:exactly, 1] - @proxy.at_least(3).count.should == [:at_least, 3] + expect(@proxy.count).to eq([:exactly, 1]) + expect(@proxy.at_least(3).count).to eq([:at_least, 3]) end end -describe MockProxy, "#arguments" do +RSpec.describe MockProxy, "#arguments" do before :each do @proxy = MockProxy.new end it "returns the expected arguments" do - @proxy.arguments.should == :any_args + expect(@proxy.arguments).to eq(:any_args) end end -describe MockProxy, "#with" do +RSpec.describe MockProxy, "#with" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.with(:a).should be_equal(@proxy) + expect(@proxy.with(:a)).to be_equal(@proxy) end it "raises an ArgumentError if no arguments are given" do - lambda { @proxy.with }.should raise_error(ArgumentError) + expect { @proxy.with }.to raise_error(ArgumentError) end it "accepts any number of arguments" do - @proxy.with(1, 2, 3).should be_an_instance_of(MockProxy) - @proxy.arguments.should == [1,2,3] + expect(@proxy.with(1, 2, 3)).to be_an_instance_of(MockProxy) + expect(@proxy.arguments).to eq([1,2,3]) end end -describe MockProxy, "#once" do +RSpec.describe MockProxy, "#once" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.once.should be_equal(@proxy) + expect(@proxy.once).to be_equal(@proxy) end it "sets the expected calls to 1" do @proxy.once - @proxy.count.should == [:exactly, 1] + expect(@proxy.count).to eq([:exactly, 1]) end it "accepts no arguments" do - lambda { @proxy.once(:a) }.should raise_error + expect { @proxy.once(:a) }.to raise_error end end -describe MockProxy, "#twice" do +RSpec.describe MockProxy, "#twice" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.twice.should be_equal(@proxy) + expect(@proxy.twice).to be_equal(@proxy) end it "sets the expected calls to 2" do @proxy.twice - @proxy.count.should == [:exactly, 2] + expect(@proxy.count).to eq([:exactly, 2]) end it "accepts no arguments" do - lambda { @proxy.twice(:b) }.should raise_error + expect { @proxy.twice(:b) }.to raise_error end end -describe MockProxy, "#exactly" do +RSpec.describe MockProxy, "#exactly" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.exactly(2).should be_equal(@proxy) + expect(@proxy.exactly(2)).to be_equal(@proxy) end it "sets the expected calls to exactly n" do @proxy.exactly(5) - @proxy.count.should == [:exactly, 5] + expect(@proxy.count).to eq([:exactly, 5]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.exactly('x') }.should raise_error + expect { @proxy.exactly('x') }.to raise_error end end -describe MockProxy, "#at_least" do +RSpec.describe MockProxy, "#at_least" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.at_least(3).should be_equal(@proxy) + expect(@proxy.at_least(3)).to be_equal(@proxy) end it "sets the expected calls to at least n" do @proxy.at_least(3) - @proxy.count.should == [:at_least, 3] + expect(@proxy.count).to eq([:at_least, 3]) end it "accepts :once :twice" do @proxy.at_least(:once) - @proxy.count.should == [:at_least, 1] + expect(@proxy.count).to eq([:at_least, 1]) @proxy.at_least(:twice) - @proxy.count.should == [:at_least, 2] + expect(@proxy.count).to eq([:at_least, 2]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.at_least('x') }.should raise_error + expect { @proxy.at_least('x') }.to raise_error end end -describe MockProxy, "#at_most" do +RSpec.describe MockProxy, "#at_most" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.at_most(2).should be_equal(@proxy) + expect(@proxy.at_most(2)).to be_equal(@proxy) end it "sets the expected calls to at most n" do @proxy.at_most(2) - @proxy.count.should == [:at_most, 2] + expect(@proxy.count).to eq([:at_most, 2]) end it "accepts :once, :twice" do @proxy.at_most(:once) - @proxy.count.should == [:at_most, 1] + expect(@proxy.count).to eq([:at_most, 1]) @proxy.at_most(:twice) - @proxy.count.should == [:at_most, 2] + expect(@proxy.count).to eq([:at_most, 2]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.at_most('x') }.should raise_error + expect { @proxy.at_most('x') }.to raise_error end end -describe MockProxy, "#any_number_of_times" do +RSpec.describe MockProxy, "#any_number_of_times" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.any_number_of_times.should be_equal(@proxy) + expect(@proxy.any_number_of_times).to be_equal(@proxy) end it "sets the expected calls to any number of times" do @proxy.any_number_of_times - @proxy.count.should == [:any_number_of_times, 0] + expect(@proxy.count).to eq([:any_number_of_times, 0]) end it "does not accept an argument" do - lambda { @proxy.any_number_of_times(2) }.should raise_error + expect { @proxy.any_number_of_times(2) }.to raise_error end end -describe MockProxy, "#and_return" do +RSpec.describe MockProxy, "#and_return" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.and_return(false).should equal(@proxy) + expect(@proxy.and_return(false)).to equal(@proxy) end it "sets the expected return value" do @proxy.and_return(false) - @proxy.returning.should == false + expect(@proxy.returning).to eq(false) end it "accepts any number of return values" do @proxy.and_return(1, 2, 3) - @proxy.returning.should == 1 - @proxy.returning.should == 2 - @proxy.returning.should == 3 + expect(@proxy.returning).to eq(1) + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(3) end it "implicitly sets the expected number of calls" do @proxy.and_return(1, 2, 3) - @proxy.count.should == [:exactly, 3] + expect(@proxy.count).to eq([:exactly, 3]) end it "only sets the expected number of calls if it is higher than what is already set" do @proxy.at_least(5).times.and_return(1, 2, 3) - @proxy.count.should == [:at_least, 5] + expect(@proxy.count).to eq([:at_least, 5]) @proxy.at_least(2).times.and_return(1, 2, 3) - @proxy.count.should == [:at_least, 3] + expect(@proxy.count).to eq([:at_least, 3]) end end -describe MockProxy, "#returning" do +RSpec.describe MockProxy, "#returning" do before :each do @proxy = MockProxy.new end it "returns nil by default" do - @proxy.returning.should be_nil + expect(@proxy.returning).to be_nil end it "returns the value set by #and_return" do @proxy.and_return(2) - @proxy.returning.should == 2 - @proxy.returning.should == 2 + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(2) end it "returns a sequence of values set by #and_return" do @proxy.and_return(1,2,3,4) - @proxy.returning.should == 1 - @proxy.returning.should == 2 - @proxy.returning.should == 3 - @proxy.returning.should == 4 - @proxy.returning.should == 4 - @proxy.returning.should == 4 + expect(@proxy.returning).to eq(1) + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(3) + expect(@proxy.returning).to eq(4) + expect(@proxy.returning).to eq(4) + expect(@proxy.returning).to eq(4) end end -describe MockProxy, "#calls" do +RSpec.describe MockProxy, "#calls" do before :each do @proxy = MockProxy.new end it "returns the number of times the proxy is called" do - @proxy.calls.should == 0 + expect(@proxy.calls).to eq(0) end end -describe MockProxy, "#called" do +RSpec.describe MockProxy, "#called" do before :each do @proxy = MockProxy.new end @@ -278,128 +278,128 @@ it "increments the number of times the proxy is called" do @proxy.called @proxy.called - @proxy.calls.should == 2 + expect(@proxy.calls).to eq(2) end end -describe MockProxy, "#times" do +RSpec.describe MockProxy, "#times" do before :each do @proxy = MockProxy.new end it "is a no-op" do - @proxy.times.should == @proxy + expect(@proxy.times).to eq(@proxy) end end -describe MockProxy, "#stub?" do +RSpec.describe MockProxy, "#stub?" do it "returns true if the proxy is created as a stub" do - MockProxy.new(:stub).stub?.should be_true + expect(MockProxy.new(:stub).stub?).to be_truthy end it "returns false if the proxy is created as a mock" do - MockProxy.new(:mock).stub?.should be_false + expect(MockProxy.new(:mock).stub?).to be_falsey end end -describe MockProxy, "#mock?" do +RSpec.describe MockProxy, "#mock?" do it "returns true if the proxy is created as a mock" do - MockProxy.new(:mock).mock?.should be_true + expect(MockProxy.new(:mock).mock?).to be_truthy end it "returns false if the proxy is created as a stub" do - MockProxy.new(:stub).mock?.should be_false + expect(MockProxy.new(:stub).mock?).to be_falsey end end -describe MockProxy, "#and_yield" do +RSpec.describe MockProxy, "#and_yield" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.and_yield(false).should equal(@proxy) + expect(@proxy.and_yield(false)).to equal(@proxy) end it "sets the expected values to yield" do - @proxy.and_yield(1).yielding.should == [[1]] + expect(@proxy.and_yield(1).yielding).to eq([[1]]) end it "accepts multiple values to yield" do - @proxy.and_yield(1, 2, 3).yielding.should == [[1, 2, 3]] + expect(@proxy.and_yield(1, 2, 3).yielding).to eq([[1, 2, 3]]) end end -describe MockProxy, "#raising" do +RSpec.describe MockProxy, "#raising" do before :each do @proxy = MockProxy.new end it "returns nil by default" do - @proxy.raising.should be_nil + expect(@proxy.raising).to be_nil end it "returns the exception object passed to #and_raise" do exc = double("exception") @proxy.and_raise(exc) - @proxy.raising.should equal(exc) + expect(@proxy.raising).to equal(exc) end it "returns an instance of RuntimeError when a String is passed to #and_raise" do @proxy.and_raise("an error") exc = @proxy.raising - exc.should be_an_instance_of(RuntimeError) - exc.message.should == "an error" + expect(exc).to be_an_instance_of(RuntimeError) + expect(exc.message).to eq("an error") end end -describe MockProxy, "#yielding" do +RSpec.describe MockProxy, "#yielding" do before :each do @proxy = MockProxy.new end it "returns an empty array by default" do - @proxy.yielding.should == [] + expect(@proxy.yielding).to eq([]) end it "returns an array of arrays of values the proxy should yield" do @proxy.and_yield(3) - @proxy.yielding.should == [[3]] + expect(@proxy.yielding).to eq([[3]]) end it "returns an accumulation of arrays of values the proxy should yield" do @proxy.and_yield(1).and_yield(2, 3) - @proxy.yielding.should == [[1], [2, 3]] + expect(@proxy.yielding).to eq([[1], [2, 3]]) end end -describe MockProxy, "#yielding?" do +RSpec.describe MockProxy, "#yielding?" do before :each do @proxy = MockProxy.new end it "returns false if the proxy is not yielding" do - @proxy.yielding?.should be_false + expect(@proxy.yielding?).to be_falsey end it "returns true if the proxy is yielding" do @proxy.and_yield(1) - @proxy.yielding?.should be_true + expect(@proxy.yielding?).to be_truthy end end -describe MockIntObject, "#to_int" do +RSpec.describe MockIntObject, "#to_int" do before :each do @int = MockIntObject.new(10) end it "returns the number if to_int is called" do - @int.to_int.should == 10 - @int.count.should == [:at_least, 1] + expect(@int.to_int).to eq(10) + expect(@int.count).to eq([:at_least, 1]) end it "tries to convert the target to int if to_int is called" do - MockIntObject.new(@int).to_int.should == 10 - @int.count.should == [:at_least, 1] + expect(MockIntObject.new(@int).to_int).to eq(10) + expect(@int.count).to eq([:at_least, 1]) end end diff --git a/ruby/spec/mspec/spec/runner/actions/filter_spec.rb b/ruby/spec/mspec/spec/runner/actions/filter_spec.rb index d18578175..7582b31c1 100644 --- a/ruby/spec/mspec/spec/runner/actions/filter_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/filter_spec.rb @@ -3,82 +3,82 @@ require 'mspec/runner/mspec' require 'mspec/runner/tag' -describe ActionFilter do +RSpec.describe ActionFilter do it "creates a filter when not passed a description" do - MatchFilter.should_not_receive(:new) + expect(MatchFilter).not_to receive(:new) ActionFilter.new(nil, nil) end it "creates a filter from a single description" do - MatchFilter.should_receive(:new).with(nil, "match me") + expect(MatchFilter).to receive(:new).with(nil, "match me") ActionFilter.new(nil, "match me") end it "creates a filter from an array of descriptions" do - MatchFilter.should_receive(:new).with(nil, "match me", "again") + expect(MatchFilter).to receive(:new).with(nil, "match me", "again") ActionFilter.new(nil, ["match me", "again"]) end end -describe ActionFilter, "#===" do +RSpec.describe ActionFilter, "#===" do before :each do - MSpec.stub(:read_tags).and_return(["match"]) + allow(MSpec).to receive(:read_tags).and_return(["match"]) @action = ActionFilter.new(nil, ["catch", "if you"]) end it "returns false if there are no filters" do action = ActionFilter.new - action.===("anything").should == false + expect(action.===("anything")).to eq(false) end it "returns true if the argument matches any of the descriptions" do - @action.===("catch").should == true - @action.===("if you can").should == true + expect(@action.===("catch")).to eq(true) + expect(@action.===("if you can")).to eq(true) end it "returns false if the argument does not match any of the descriptions" do - @action.===("patch me").should == false - @action.===("if I can").should == false + expect(@action.===("patch me")).to eq(false) + expect(@action.===("if I can")).to eq(false) end end -describe ActionFilter, "#load" do +RSpec.describe ActionFilter, "#load" do before :each do @tag = SpecTag.new "tag(comment):description" end it "creates a filter from a single tag" do - MSpec.should_receive(:read_tags).with(["tag"]).and_return([@tag]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MSpec).to receive(:read_tags).with(["tag"]).and_return([@tag]) + expect(MatchFilter).to receive(:new).with(nil, "description") ActionFilter.new("tag", nil).load end it "creates a filter from an array of tags" do - MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([@tag]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([@tag]) + expect(MatchFilter).to receive(:new).with(nil, "description") ActionFilter.new(["tag", "key"], nil).load end it "creates a filter from both tags and descriptions" do - MSpec.should_receive(:read_tags).and_return([@tag]) + expect(MSpec).to receive(:read_tags).and_return([@tag]) filter = ActionFilter.new("tag", ["match me", "again"]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MatchFilter).to receive(:new).with(nil, "description") filter.load end end -describe ActionFilter, "#register" do +RSpec.describe ActionFilter, "#register" do it "registers itself with MSpec for the :load actions" do filter = ActionFilter.new - MSpec.should_receive(:register).with(:load, filter) + expect(MSpec).to receive(:register).with(:load, filter) filter.register end end -describe ActionFilter, "#unregister" do +RSpec.describe ActionFilter, "#unregister" do it "unregisters itself with MSpec for the :load actions" do filter = ActionFilter.new - MSpec.should_receive(:unregister).with(:load, filter) + expect(MSpec).to receive(:unregister).with(:load, filter) filter.unregister end end diff --git a/ruby/spec/mspec/spec/runner/actions/tag_spec.rb b/ruby/spec/mspec/spec/runner/actions/tag_spec.rb index 92df362d0..738e9a18c 100644 --- a/ruby/spec/mspec/spec/runner/actions/tag_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/tag_spec.rb @@ -4,211 +4,211 @@ require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagAction, ".new" do +RSpec.describe TagAction, ".new" do it "creates an MatchFilter with its tag and desc arguments" do filter = double('action filter').as_null_object - MatchFilter.should_receive(:new).with(nil, "some", "thing").and_return(filter) + expect(MatchFilter).to receive(:new).with(nil, "some", "thing").and_return(filter) TagAction.new :add, :all, nil, nil, ["tag", "key"], ["some", "thing"] end end -describe TagAction, "#===" do +RSpec.describe TagAction, "#===" do before :each do - MSpec.stub(:read_tags).and_return(["match"]) + allow(MSpec).to receive(:read_tags).and_return(["match"]) @action = TagAction.new :add, :fail, nil, nil, nil, ["catch", "if you"] end it "returns true if there are no filters" do action = TagAction.new :add, :all, nil, nil - action.===("anything").should == true + expect(action.===("anything")).to eq(true) end it "returns true if the argument matches any of the descriptions" do - @action.===("catch").should == true - @action.===("if you can").should == true + expect(@action.===("catch")).to eq(true) + expect(@action.===("if you can")).to eq(true) end it "returns false if the argument does not match any of the descriptions" do - @action.===("patch me").should == false - @action.===("if I can").should == false + expect(@action.===("patch me")).to eq(false) + expect(@action.===("if I can")).to eq(false) end end -describe TagAction, "#exception?" do +RSpec.describe TagAction, "#exception?" do before :each do @action = TagAction.new :add, :fail, nil, nil, nil, nil end it "returns false if no exception has been raised while evaluating an example" do - @action.exception?.should be_false + expect(@action.exception?).to be_falsey end it "returns true if an exception was raised while evaluating an example" do @action.exception ExceptionState.new nil, nil, Exception.new("failed") - @action.exception?.should be_true + expect(@action.exception?).to be_truthy end end -describe TagAction, "#outcome?" do +RSpec.describe TagAction, "#outcome?" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "returns true if outcome is :fail and the spec fails" do action = TagAction.new :add, :fail, nil, nil, nil, nil action.exception @exception - action.outcome?.should == true + expect(action.outcome?).to eq(true) end it "returns false if the outcome is :fail and the spec passes" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.outcome?.should == false + expect(action.outcome?).to eq(false) end it "returns true if the outcome is :pass and the spec passes" do action = TagAction.new :del, :pass, nil, nil, nil, nil - action.outcome?.should == true + expect(action.outcome?).to eq(true) end it "returns false if the outcome is :pass and the spec fails" do action = TagAction.new :del, :pass, nil, nil, nil, nil action.exception @exception - action.outcome?.should == false + expect(action.outcome?).to eq(false) end it "returns true if the outcome is :all" do action = TagAction.new :add, :all, nil, nil, nil, nil action.exception @exception - action.outcome?.should == true + expect(action.outcome?).to eq(true) end end -describe TagAction, "#before" do +RSpec.describe TagAction, "#before" do it "resets the #exception? flag to false" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.exception?.should be_false + expect(action.exception?).to be_falsey action.exception ExceptionState.new(nil, nil, Exception.new("Fail!")) - action.exception?.should be_true + expect(action.exception?).to be_truthy action.before(ExampleState.new(ContextState.new("describe"), "it")) - action.exception?.should be_false + expect(action.exception?).to be_falsey end end -describe TagAction, "#exception" do +RSpec.describe TagAction, "#exception" do it "sets the #exception? flag" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.exception?.should be_false + expect(action.exception?).to be_falsey action.exception ExceptionState.new(nil, nil, Exception.new("Fail!")) - action.exception?.should be_true + expect(action.exception?).to be_truthy end end -describe TagAction, "#after when action is :add" do +RSpec.describe TagAction, "#after when action is :add" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" @tag = SpecTag.new "tag(comment):Catch#me if you can" - SpecTag.stub(:new).and_return(@tag) + allow(SpecTag).to receive(:new).and_return(@tag) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "does not write a tag if the description does not match" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :all, "tag", "comment", nil, "match" action.after @state end it "does not write a tag if outcome is :fail and the spec passed" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :fail, "tag", "comment", nil, "can" action.after @state end it "writes a tag if the outcome is :fail and the spec failed" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :fail, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "does not write a tag if outcome is :pass and the spec failed" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :pass, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "writes a tag if the outcome is :pass and the spec passed" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :pass, "tag", "comment", nil, "can" action.after @state end it "writes a tag if the outcome is :all" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :all, "tag", "comment", nil, "can" action.after @state end end -describe TagAction, "#after when action is :del" do +RSpec.describe TagAction, "#after when action is :del" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" @tag = SpecTag.new "tag(comment):Catch#me if you can" - SpecTag.stub(:new).and_return(@tag) + allow(SpecTag).to receive(:new).and_return(@tag) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "does not delete a tag if the description does not match" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :all, "tag", "comment", nil, "match" action.after @state end it "does not delete a tag if outcome is :fail and the spec passed" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :fail, "tag", "comment", nil, "can" action.after @state end it "deletes a tag if the outcome is :fail and the spec failed" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :fail, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "does not delete a tag if outcome is :pass and the spec failed" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :pass, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "deletes a tag if the outcome is :pass and the spec passed" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :pass, "tag", "comment", nil, "can" action.after @state end it "deletes a tag if the outcome is :all" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :all, "tag", "comment", nil, "can" action.after @state end end -describe TagAction, "#finish" do +RSpec.describe TagAction, "#finish" do before :each do $stdout = @out = IOStub.new context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" - MSpec.stub(:write_tag).and_return(true) - MSpec.stub(:delete_tag).and_return(true) + allow(MSpec).to receive(:write_tag).and_return(true) + allow(MSpec).to receive(:delete_tag).and_return(true) end after :each do @@ -217,99 +217,97 @@ it "reports no specs tagged if none where tagged" do action = TagAction.new :add, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(false) + allow(action).to receive(:outcome?).and_return(false) action.after @state action.finish - @out.should == "\nTagAction: no specs were tagged with 'tag'\n" + expect(@out).to eq("\nTagAction: no specs were tagged with 'tag'\n") end it "reports no specs tagged if none where tagged" do action = TagAction.new :del, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(false) + allow(action).to receive(:outcome?).and_return(false) action.after @state action.finish - @out.should == "\nTagAction: no tags 'tag' were deleted\n" + expect(@out).to eq("\nTagAction: no tags 'tag' were deleted\n") end it "reports the spec descriptions that were tagged" do action = TagAction.new :add, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(true) + allow(action).to receive(:outcome?).and_return(true) action.after @state action.finish - @out.should == -%[ + expect(@out).to eq(%[ TagAction: specs tagged with 'tag': Catch#me if you can -] +]) end it "reports the spec descriptions for the tags that were deleted" do action = TagAction.new :del, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(true) + allow(action).to receive(:outcome?).and_return(true) action.after @state action.finish - @out.should == -%[ + expect(@out).to eq(%[ TagAction: tag 'tag' deleted for specs: Catch#me if you can -] +]) end end -describe TagAction, "#register" do +RSpec.describe TagAction, "#register" do before :each do - MSpec.stub(:register) - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:read_tags).and_return([]) @action = TagAction.new :add, :all, nil, nil, nil, nil end it "registers itself with MSpec for the :before event" do - MSpec.should_receive(:register).with(:before, @action) + expect(MSpec).to receive(:register).with(:before, @action) @action.register end it "registers itself with MSpec for the :after event" do - MSpec.should_receive(:register).with(:after, @action) + expect(MSpec).to receive(:register).with(:after, @action) @action.register end it "registers itself with MSpec for the :exception event" do - MSpec.should_receive(:register).with(:exception, @action) + expect(MSpec).to receive(:register).with(:exception, @action) @action.register end it "registers itself with MSpec for the :finish event" do - MSpec.should_receive(:register).with(:finish, @action) + expect(MSpec).to receive(:register).with(:finish, @action) @action.register end end -describe TagAction, "#unregister" do +RSpec.describe TagAction, "#unregister" do before :each do - MSpec.stub(:unregister) - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:unregister) + allow(MSpec).to receive(:read_tags).and_return([]) @action = TagAction.new :add, :all, nil, nil, nil, nil end it "unregisters itself with MSpec for the :before event" do - MSpec.should_receive(:unregister).with(:before, @action) + expect(MSpec).to receive(:unregister).with(:before, @action) @action.unregister end it "unregisters itself with MSpec for the :after event" do - MSpec.should_receive(:unregister).with(:after, @action) + expect(MSpec).to receive(:unregister).with(:after, @action) @action.unregister end it "unregisters itself with MSpec for the :exception event" do - MSpec.should_receive(:unregister).with(:exception, @action) + expect(MSpec).to receive(:unregister).with(:exception, @action) @action.unregister end it "unregisters itself with MSpec for the :finish event" do - MSpec.should_receive(:unregister).with(:finish, @action) + expect(MSpec).to receive(:unregister).with(:finish, @action) @action.unregister end end diff --git a/ruby/spec/mspec/spec/runner/actions/taglist_spec.rb b/ruby/spec/mspec/spec/runner/actions/taglist_spec.rb index 418c761c2..b6a5400f7 100644 --- a/ruby/spec/mspec/spec/runner/actions/taglist_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/taglist_spec.rb @@ -4,34 +4,34 @@ require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagListAction, "#include?" do +RSpec.describe TagListAction, "#include?" do it "returns true" do - TagListAction.new.include?(:anything).should be_true + expect(TagListAction.new.include?(:anything)).to be_truthy end end -describe TagListAction, "#===" do +RSpec.describe TagListAction, "#===" do before :each do tag = SpecTag.new "fails:description" - MSpec.stub(:read_tags).and_return([tag]) + allow(MSpec).to receive(:read_tags).and_return([tag]) @filter = double("MatchFilter").as_null_object - MatchFilter.stub(:new).and_return(@filter) + allow(MatchFilter).to receive(:new).and_return(@filter) @action = TagListAction.new @action.load end it "returns true if filter === string returns true" do - @filter.should_receive(:===).with("str").and_return(true) - @action.===("str").should be_true + expect(@filter).to receive(:===).with("str").and_return(true) + expect(@action.===("str")).to be_truthy end it "returns false if filter === string returns false" do - @filter.should_receive(:===).with("str").and_return(false) - @action.===("str").should be_false + expect(@filter).to receive(:===).with("str").and_return(false) + expect(@action.===("str")).to be_falsey end end -describe TagListAction, "#start" do +RSpec.describe TagListAction, "#start" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -44,48 +44,48 @@ it "prints a banner for specific tags" do action = TagListAction.new ["fails", "unstable"] action.start - $stdout.should == "\nListing specs tagged with 'fails', 'unstable'\n\n" + expect($stdout).to eq("\nListing specs tagged with 'fails', 'unstable'\n\n") end it "prints a banner for all tags" do action = TagListAction.new action.start - $stdout.should == "\nListing all tagged specs\n\n" + expect($stdout).to eq("\nListing all tagged specs\n\n") end end -describe TagListAction, "#load" do +RSpec.describe TagListAction, "#load" do before :each do @t1 = SpecTag.new "fails:I fail" @t2 = SpecTag.new "unstable:I'm unstable" end it "creates a MatchFilter for matching tags" do - MSpec.should_receive(:read_tags).with(["fails"]).and_return([@t1]) - MatchFilter.should_receive(:new).with(nil, "I fail") + expect(MSpec).to receive(:read_tags).with(["fails"]).and_return([@t1]) + expect(MatchFilter).to receive(:new).with(nil, "I fail") TagListAction.new(["fails"]).load end it "creates a MatchFilter for all tags" do - MSpec.should_receive(:read_tags).and_return([@t1, @t2]) - MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable") + expect(MSpec).to receive(:read_tags).and_return([@t1, @t2]) + expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable") TagListAction.new.load end it "does not create a MatchFilter if there are no matching tags" do - MSpec.stub(:read_tags).and_return([]) - MatchFilter.should_not_receive(:new) + allow(MSpec).to receive(:read_tags).and_return([]) + expect(MatchFilter).not_to receive(:new) TagListAction.new(["fails"]).load end end -describe TagListAction, "#after" do +RSpec.describe TagListAction, "#after" do before :each do @stdout = $stdout $stdout = IOStub.new @state = double("ExampleState") - @state.stub(:description).and_return("str") + allow(@state).to receive(:description).and_return("str") @action = TagListAction.new end @@ -95,58 +95,58 @@ end it "prints nothing if the filter does not match" do - @action.should_receive(:===).with("str").and_return(false) + expect(@action).to receive(:===).with("str").and_return(false) @action.after(@state) - $stdout.should == "" + expect($stdout).to eq("") end it "prints the example description if the filter matches" do - @action.should_receive(:===).with("str").and_return(true) + expect(@action).to receive(:===).with("str").and_return(true) @action.after(@state) - $stdout.should == "str\n" + expect($stdout).to eq("str\n") end end -describe TagListAction, "#register" do +RSpec.describe TagListAction, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) @action = TagListAction.new end it "registers itself with MSpec for the :start event" do - MSpec.should_receive(:register).with(:start, @action) + expect(MSpec).to receive(:register).with(:start, @action) @action.register end it "registers itself with MSpec for the :load event" do - MSpec.should_receive(:register).with(:load, @action) + expect(MSpec).to receive(:register).with(:load, @action) @action.register end it "registers itself with MSpec for the :after event" do - MSpec.should_receive(:register).with(:after, @action) + expect(MSpec).to receive(:register).with(:after, @action) @action.register end end -describe TagListAction, "#unregister" do +RSpec.describe TagListAction, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @action = TagListAction.new end it "unregisters itself with MSpec for the :start event" do - MSpec.should_receive(:unregister).with(:start, @action) + expect(MSpec).to receive(:unregister).with(:start, @action) @action.unregister end it "unregisters itself with MSpec for the :load event" do - MSpec.should_receive(:unregister).with(:load, @action) + expect(MSpec).to receive(:unregister).with(:load, @action) @action.unregister end it "unregisters itself with MSpec for the :after event" do - MSpec.should_receive(:unregister).with(:after, @action) + expect(MSpec).to receive(:unregister).with(:after, @action) @action.unregister end end diff --git a/ruby/spec/mspec/spec/runner/actions/tagpurge_spec.rb b/ruby/spec/mspec/spec/runner/actions/tagpurge_spec.rb index 27ad2a147..37df0afd5 100644 --- a/ruby/spec/mspec/spec/runner/actions/tagpurge_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/tagpurge_spec.rb @@ -4,7 +4,7 @@ require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagPurgeAction, "#start" do +RSpec.describe TagPurgeAction, "#start" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -17,45 +17,45 @@ it "prints a banner" do action = TagPurgeAction.new action.start - $stdout.should == "\nRemoving tags not matching any specs\n\n" + expect($stdout).to eq("\nRemoving tags not matching any specs\n\n") end end -describe TagPurgeAction, "#load" do +RSpec.describe TagPurgeAction, "#load" do before :each do @t1 = SpecTag.new "fails:I fail" @t2 = SpecTag.new "unstable:I'm unstable" end it "creates a MatchFilter for all tags" do - MSpec.should_receive(:read_tags).and_return([@t1, @t2]) - MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable") + expect(MSpec).to receive(:read_tags).and_return([@t1, @t2]) + expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable") TagPurgeAction.new.load end end -describe TagPurgeAction, "#after" do +RSpec.describe TagPurgeAction, "#after" do before :each do @state = double("ExampleState") - @state.stub(:description).and_return("str") + allow(@state).to receive(:description).and_return("str") @action = TagPurgeAction.new end it "does not save the description if the filter does not match" do - @action.should_receive(:===).with("str").and_return(false) + expect(@action).to receive(:===).with("str").and_return(false) @action.after @state - @action.matching.should == [] + expect(@action.matching).to eq([]) end it "saves the description if the filter matches" do - @action.should_receive(:===).with("str").and_return(true) + expect(@action).to receive(:===).with("str").and_return(true) @action.after @state - @action.matching.should == ["str"] + expect(@action.matching).to eq(["str"]) end end -describe TagPurgeAction, "#unload" do +RSpec.describe TagPurgeAction, "#unload" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -64,11 +64,11 @@ @t2 = SpecTag.new "unstable:I'm unstable" @t3 = SpecTag.new "fails:I'm unstable" - MSpec.stub(:read_tags).and_return([@t1, @t2, @t3]) - MSpec.stub(:write_tags) + allow(MSpec).to receive(:read_tags).and_return([@t1, @t2, @t3]) + allow(MSpec).to receive(:write_tags) @state = double("ExampleState") - @state.stub(:description).and_return("I'm unstable") + allow(@state).to receive(:description).and_return("I'm unstable") @action = TagPurgeAction.new @action.load @@ -80,37 +80,37 @@ end it "does not rewrite any tags if there were no tags for the specs" do - MSpec.should_receive(:read_tags).and_return([]) - MSpec.should_receive(:delete_tags) - MSpec.should_not_receive(:write_tags) + expect(MSpec).to receive(:read_tags).and_return([]) + expect(MSpec).to receive(:delete_tags) + expect(MSpec).not_to receive(:write_tags) @action.load @action.after @state @action.unload - $stdout.should == "" + expect($stdout).to eq("") end it "rewrites tags that were matched" do - MSpec.should_receive(:write_tags).with([@t2, @t3]) + expect(MSpec).to receive(:write_tags).with([@t2, @t3]) @action.unload end it "prints tags that were not matched" do @action.unload - $stdout.should == "I fail\n" + expect($stdout).to eq("I fail\n") end end -describe TagPurgeAction, "#unload" do +RSpec.describe TagPurgeAction, "#unload" do before :each do @stdout = $stdout $stdout = IOStub.new - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) @state = double("ExampleState") - @state.stub(:description).and_return("I'm unstable") + allow(@state).to receive(:description).and_return("I'm unstable") @action = TagPurgeAction.new @action.load @@ -122,33 +122,33 @@ end it "deletes the tag file if no tags were found" do - MSpec.should_not_receive(:write_tags) - MSpec.should_receive(:delete_tags) + expect(MSpec).not_to receive(:write_tags) + expect(MSpec).to receive(:delete_tags) @action.unload - $stdout.should == "" + expect($stdout).to eq("") end end -describe TagPurgeAction, "#register" do +RSpec.describe TagPurgeAction, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) @action = TagPurgeAction.new end it "registers itself with MSpec for the :unload event" do - MSpec.should_receive(:register).with(:unload, @action) + expect(MSpec).to receive(:register).with(:unload, @action) @action.register end end -describe TagPurgeAction, "#unregister" do +RSpec.describe TagPurgeAction, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @action = TagPurgeAction.new end it "unregisters itself with MSpec for the :unload event" do - MSpec.should_receive(:unregister).with(:unload, @action) + expect(MSpec).to receive(:unregister).with(:unload, @action) @action.unregister end end diff --git a/ruby/spec/mspec/spec/runner/actions/tally_spec.rb b/ruby/spec/mspec/spec/runner/actions/tally_spec.rb index be4635ffe..d80ab1164 100644 --- a/ruby/spec/mspec/spec/runner/actions/tally_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/tally_spec.rb @@ -4,169 +4,169 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' -describe Tally, "#files!" do +RSpec.describe Tally, "#files!" do before :each do @tally = Tally.new end it "increments the count returned by #files" do @tally.files! 3 - @tally.files.should == 3 + expect(@tally.files).to eq(3) @tally.files! - @tally.files.should == 4 + expect(@tally.files).to eq(4) end end -describe Tally, "#examples!" do +RSpec.describe Tally, "#examples!" do before :each do @tally = Tally.new end it "increments the count returned by #examples" do @tally.examples! 2 - @tally.examples.should == 2 + expect(@tally.examples).to eq(2) @tally.examples! 2 - @tally.examples.should == 4 + expect(@tally.examples).to eq(4) end end -describe Tally, "#expectations!" do +RSpec.describe Tally, "#expectations!" do before :each do @tally = Tally.new end it "increments the count returned by #expectations" do @tally.expectations! - @tally.expectations.should == 1 + expect(@tally.expectations).to eq(1) @tally.expectations! 3 - @tally.expectations.should == 4 + expect(@tally.expectations).to eq(4) end end -describe Tally, "#failures!" do +RSpec.describe Tally, "#failures!" do before :each do @tally = Tally.new end it "increments the count returned by #failures" do @tally.failures! 1 - @tally.failures.should == 1 + expect(@tally.failures).to eq(1) @tally.failures! - @tally.failures.should == 2 + expect(@tally.failures).to eq(2) end end -describe Tally, "#errors!" do +RSpec.describe Tally, "#errors!" do before :each do @tally = Tally.new end it "increments the count returned by #errors" do @tally.errors! - @tally.errors.should == 1 + expect(@tally.errors).to eq(1) @tally.errors! 2 - @tally.errors.should == 3 + expect(@tally.errors).to eq(3) end end -describe Tally, "#guards!" do +RSpec.describe Tally, "#guards!" do before :each do @tally = Tally.new end it "increments the count returned by #guards" do @tally.guards! - @tally.guards.should == 1 + expect(@tally.guards).to eq(1) @tally.guards! 2 - @tally.guards.should == 3 + expect(@tally.guards).to eq(3) end end -describe Tally, "#file" do +RSpec.describe Tally, "#file" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #files" do - @tally.file.should == "0 files" + expect(@tally.file).to eq("0 files") @tally.files! - @tally.file.should == "1 file" + expect(@tally.file).to eq("1 file") @tally.files! - @tally.file.should == "2 files" + expect(@tally.file).to eq("2 files") end end -describe Tally, "#example" do +RSpec.describe Tally, "#example" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #examples" do - @tally.example.should == "0 examples" + expect(@tally.example).to eq("0 examples") @tally.examples! - @tally.example.should == "1 example" + expect(@tally.example).to eq("1 example") @tally.examples! - @tally.example.should == "2 examples" + expect(@tally.example).to eq("2 examples") end end -describe Tally, "#expectation" do +RSpec.describe Tally, "#expectation" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #expectations" do - @tally.expectation.should == "0 expectations" + expect(@tally.expectation).to eq("0 expectations") @tally.expectations! - @tally.expectation.should == "1 expectation" + expect(@tally.expectation).to eq("1 expectation") @tally.expectations! - @tally.expectation.should == "2 expectations" + expect(@tally.expectation).to eq("2 expectations") end end -describe Tally, "#failure" do +RSpec.describe Tally, "#failure" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #failures" do - @tally.failure.should == "0 failures" + expect(@tally.failure).to eq("0 failures") @tally.failures! - @tally.failure.should == "1 failure" + expect(@tally.failure).to eq("1 failure") @tally.failures! - @tally.failure.should == "2 failures" + expect(@tally.failure).to eq("2 failures") end end -describe Tally, "#error" do +RSpec.describe Tally, "#error" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #errors" do - @tally.error.should == "0 errors" + expect(@tally.error).to eq("0 errors") @tally.errors! - @tally.error.should == "1 error" + expect(@tally.error).to eq("1 error") @tally.errors! - @tally.error.should == "2 errors" + expect(@tally.error).to eq("2 errors") end end -describe Tally, "#guard" do +RSpec.describe Tally, "#guard" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #guards" do - @tally.guard.should == "0 guards" + expect(@tally.guard).to eq("0 guards") @tally.guards! - @tally.guard.should == "1 guard" + expect(@tally.guard).to eq("1 guard") @tally.guards! - @tally.guard.should == "2 guards" + expect(@tally.guard).to eq("2 guards") end end -describe Tally, "#format" do +RSpec.describe Tally, "#format" do before :each do @tally = Tally.new end @@ -181,7 +181,7 @@ @tally.expectations! 4 @tally.errors! @tally.tagged! - @tally.format.should == "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged" + expect(@tally.format).to eq("1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged") end it "includes guards if MSpec is in verify mode" do @@ -192,8 +192,9 @@ @tally.errors! @tally.tagged! @tally.guards! - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 1 guard" + ) end it "includes guards if MSpec is in report mode" do @@ -204,8 +205,9 @@ @tally.errors! @tally.tagged! @tally.guards! 2 - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 2 guards" + ) end it "includes guards if MSpec is in report_on mode" do @@ -215,23 +217,24 @@ @tally.expectations! 4 @tally.errors! @tally.guards! 2 - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 0 tagged, 2 guards" + ) end end -describe TallyAction, "#counter" do +RSpec.describe TallyAction, "#counter" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "returns the Tally object" do - @tally.counter.should be_kind_of(Tally) + expect(@tally.counter).to be_kind_of(Tally) end end -describe TallyAction, "#load" do +RSpec.describe TallyAction, "#load" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -239,11 +242,11 @@ it "increments the count returned by Tally#files" do @tally.load - @tally.counter.files.should == 1 + expect(@tally.counter.files).to eq(1) end end -describe TallyAction, "#expectation" do +RSpec.describe TallyAction, "#expectation" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -251,11 +254,11 @@ it "increments the count returned by Tally#expectations" do @tally.expectation @state - @tally.counter.expectations.should == 1 + expect(@tally.counter.expectations).to eq(1) end end -describe TallyAction, "#example" do +RSpec.describe TallyAction, "#example" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -263,14 +266,14 @@ it "increments counts returned by Tally#examples" do @tally.example @state, nil - @tally.counter.examples.should == 1 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 0 - @tally.counter.errors.should == 0 + expect(@tally.counter.examples).to eq(1) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(0) + expect(@tally.counter.errors).to eq(0) end end -describe TallyAction, "#exception" do +RSpec.describe TallyAction, "#exception" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -279,14 +282,14 @@ it "increments counts returned by Tally#failures" do exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!") @tally.exception exc - @tally.counter.examples.should == 0 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 1 - @tally.counter.errors.should == 0 + expect(@tally.counter.examples).to eq(0) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(1) + expect(@tally.counter.errors).to eq(0) end end -describe TallyAction, "#exception" do +RSpec.describe TallyAction, "#exception" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -295,14 +298,14 @@ it "increments counts returned by Tally#errors" do exc = ExceptionState.new nil, nil, Exception.new("Error!") @tally.exception exc - @tally.counter.examples.should == 0 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 0 - @tally.counter.errors.should == 1 + expect(@tally.counter.examples).to eq(0) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(0) + expect(@tally.counter.errors).to eq(1) end end -describe TallyAction, "#format" do +RSpec.describe TallyAction, "#format" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -315,38 +318,38 @@ @tally.expectation @state exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!") @tally.exception exc - @tally.format.should == "1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged" + expect(@tally.format).to eq("1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged") end end -describe TallyAction, "#register" do +RSpec.describe TallyAction, "#register" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "registers itself with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:load, @tally) - MSpec.should_receive(:register).with(:exception, @tally) - MSpec.should_receive(:register).with(:example, @tally) - MSpec.should_receive(:register).with(:tagged, @tally) - MSpec.should_receive(:register).with(:expectation, @tally) + expect(MSpec).to receive(:register).with(:load, @tally) + expect(MSpec).to receive(:register).with(:exception, @tally) + expect(MSpec).to receive(:register).with(:example, @tally) + expect(MSpec).to receive(:register).with(:tagged, @tally) + expect(MSpec).to receive(:register).with(:expectation, @tally) @tally.register end end -describe TallyAction, "#unregister" do +RSpec.describe TallyAction, "#unregister" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "unregisters itself with MSpec for appropriate actions" do - MSpec.should_receive(:unregister).with(:load, @tally) - MSpec.should_receive(:unregister).with(:exception, @tally) - MSpec.should_receive(:unregister).with(:example, @tally) - MSpec.should_receive(:unregister).with(:tagged, @tally) - MSpec.should_receive(:unregister).with(:expectation, @tally) + expect(MSpec).to receive(:unregister).with(:load, @tally) + expect(MSpec).to receive(:unregister).with(:exception, @tally) + expect(MSpec).to receive(:unregister).with(:example, @tally) + expect(MSpec).to receive(:unregister).with(:tagged, @tally) + expect(MSpec).to receive(:unregister).with(:expectation, @tally) @tally.unregister end end diff --git a/ruby/spec/mspec/spec/runner/actions/timer_spec.rb b/ruby/spec/mspec/spec/runner/actions/timer_spec.rb index 417367d5a..28a317177 100644 --- a/ruby/spec/mspec/spec/runner/actions/timer_spec.rb +++ b/ruby/spec/mspec/spec/runner/actions/timer_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/mspec' require 'time' -describe TimerAction do +RSpec.describe TimerAction do before :each do @timer = TimerAction.new @start_time = Time.utc(2009, 3, 30, 14, 5, 19) @@ -11,34 +11,34 @@ end it "responds to #start by recording the current time" do - Time.should_receive(:now) + expect(Time).to receive(:now) @timer.start end it "responds to #finish by recording the current time" do - Time.should_receive(:now) + expect(Time).to receive(:now) @timer.finish end it "responds to #elapsed by returning the difference between stop and start" do - Time.stub(:now).and_return(@start_time) + allow(Time).to receive(:now).and_return(@start_time) @timer.start - Time.stub(:now).and_return(@stop_time) + allow(Time).to receive(:now).and_return(@stop_time) @timer.finish - @timer.elapsed.should == 33 + expect(@timer.elapsed).to eq(33) end it "responds to #format by returning a readable string of elapsed time" do - Time.stub(:now).and_return(@start_time) + allow(Time).to receive(:now).and_return(@start_time) @timer.start - Time.stub(:now).and_return(@stop_time) + allow(Time).to receive(:now).and_return(@stop_time) @timer.finish - @timer.format.should == "Finished in 33.000000 seconds" + expect(@timer.format).to eq("Finished in 33.000000 seconds") end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:start, @timer) - MSpec.should_receive(:register).with(:finish, @timer) + expect(MSpec).to receive(:register).with(:start, @timer) + expect(MSpec).to receive(:register).with(:finish, @timer) @timer.register end end diff --git a/ruby/spec/mspec/spec/runner/context_spec.rb b/ruby/spec/mspec/spec/runner/context_spec.rb index d9c20aa0c..a864428ae 100644 --- a/ruby/spec/mspec/spec/runner/context_spec.rb +++ b/ruby/spec/mspec/spec/runner/context_spec.rb @@ -6,7 +6,7 @@ require 'mspec/runner/context' require 'mspec/runner/example' -describe ContextState, "#describe" do +RSpec.describe ContextState, "#describe" do before :each do @state = ContextState.new "C#m" @proc = proc { ScratchPad.record :a } @@ -15,79 +15,63 @@ it "evaluates the passed block" do @state.describe(&@proc) - ScratchPad.recorded.should == :a + expect(ScratchPad.recorded).to eq(:a) end it "evaluates the passed block via #protect" do - @state.should_receive(:protect).with("C#m", @proc, false) + expect(@state).to receive(:protect).with("C#m", @proc, false) @state.describe(&@proc) end it "registers #parent as the current MSpec ContextState" do parent = ContextState.new "" @state.parent = parent - MSpec.should_receive(:register_current).with(parent) + expect(MSpec).to receive(:register_current).with(parent) @state.describe { } end it "registers self with MSpec when #shared? is true" do state = ContextState.new "something shared", :shared => true - MSpec.should_receive(:register_shared).with(state) + expect(MSpec).to receive(:register_shared).with(state) state.describe { } end end -describe ContextState, "#shared?" do +RSpec.describe ContextState, "#shared?" do it "returns false when the ContextState is not shared" do - ContextState.new("").shared?.should be_false + expect(ContextState.new("").shared?).to be_falsey end it "returns true when the ContextState is shared" do - ContextState.new("", {:shared => true}).shared?.should be_true + expect(ContextState.new("", {:shared => true}).shared?).to be_truthy end end -describe ContextState, "#to_s" do +RSpec.describe ContextState, "#to_s" do it "returns a description string for self when passed a Module" do - ContextState.new(Object).to_s.should == "Object" + expect(ContextState.new(Object).to_s).to eq("Object") end it "returns a description string for self when passed a String" do - ContextState.new("SomeClass").to_s.should == "SomeClass" - end - - it "returns a description string for self when passed a Module, String" do - ContextState.new(Object, "when empty").to_s.should == "Object when empty" - end - - it "returns a description string for self when passed a Module and String beginning with '#'" do - ContextState.new(Object, "#to_s").to_s.should == "Object#to_s" - end - - it "returns a description string for self when passed a Module and String beginning with '.'" do - ContextState.new(Object, ".to_s").to_s.should == "Object.to_s" - end - - it "returns a description string for self when passed a Module and String beginning with '::'" do - ContextState.new(Object, "::to_s").to_s.should == "Object::to_s" + expect(ContextState.new("SomeClass").to_s).to eq("SomeClass") end end -describe ContextState, "#description" do +RSpec.describe ContextState, "#description" do before :each do @state = ContextState.new "when empty" @parent = ContextState.new "Toplevel" end it "returns a composite description string from self and all parents" do - @parent.description.should == "Toplevel" - @state.description.should == "when empty" + expect(@parent.description).to eq("Toplevel") + expect(@state.description).to eq("when empty") @state.parent = @parent - @state.description.should == "Toplevel when empty" + expect(@state.description).to eq("Toplevel when empty") end end -describe ContextState, "#it" do +RSpec.describe ContextState, "#it" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -96,25 +80,25 @@ end it "creates an ExampleState instance for the block" do - ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex) + expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex) @state.describe(&@proc) @state.it("it", &@proc) end it "calls registered :add actions" do - ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex) + expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex) add_action = double("add") - add_action.should_receive(:add).with(@ex).and_return { ScratchPad.record :add } + expect(add_action).to receive(:add).with(@ex) { ScratchPad.record :add } MSpec.register :add, add_action @state.it("it", &@proc) - ScratchPad.recorded.should == :add + expect(ScratchPad.recorded).to eq(:add) MSpec.unregister :add, add_action end end -describe ContextState, "#examples" do +RSpec.describe ContextState, "#examples" do before :each do @state = ContextState.new "" end @@ -122,11 +106,11 @@ it "returns a list of all examples in this ContextState" do @state.it("first") { } @state.it("second") { } - @state.examples.size.should == 2 + expect(@state.examples.size).to eq(2) end end -describe ContextState, "#before" do +RSpec.describe ContextState, "#before" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -134,16 +118,16 @@ it "records the block for :each" do @state.before(:each, &@proc) - @state.before(:each).should == [@proc] + expect(@state.before(:each)).to eq([@proc]) end it "records the block for :all" do @state.before(:all, &@proc) - @state.before(:all).should == [@proc] + expect(@state.before(:all)).to eq([@proc]) end end -describe ContextState, "#after" do +RSpec.describe ContextState, "#after" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -151,16 +135,16 @@ it "records the block for :each" do @state.after(:each, &@proc) - @state.after(:each).should == [@proc] + expect(@state.after(:each)).to eq([@proc]) end it "records the block for :all" do @state.after(:all, &@proc) - @state.after(:all).should == [@proc] + expect(@state.after(:all)).to eq([@proc]) end end -describe ContextState, "#pre" do +RSpec.describe ContextState, "#pre" do before :each do @a = lambda {|*| } @b = lambda {|*| } @@ -177,17 +161,17 @@ it "returns before(:each) actions in the order they were defined" do @state.before(:each, &@a) @state.before(:each, &@b) - @state.pre(:each).should == [@c, @a, @b] + expect(@state.pre(:each)).to eq([@c, @a, @b]) end it "returns before(:all) actions in the order they were defined" do @state.before(:all, &@a) @state.before(:all, &@b) - @state.pre(:all).should == [@c, @a, @b] + expect(@state.pre(:all)).to eq([@c, @a, @b]) end end -describe ContextState, "#post" do +RSpec.describe ContextState, "#post" do before :each do @a = lambda {|*| } @b = lambda {|*| } @@ -204,17 +188,17 @@ it "returns after(:each) actions in the reverse order they were defined" do @state.after(:each, &@a) @state.after(:each, &@b) - @state.post(:each).should == [@b, @a, @c] + expect(@state.post(:each)).to eq([@b, @a, @c]) end it "returns after(:all) actions in the reverse order they were defined" do @state.after(:all, &@a) @state.after(:all, &@b) - @state.post(:all).should == [@b, @a, @c] + expect(@state.post(:all)).to eq([@b, @a, @c]) end end -describe ContextState, "#protect" do +RSpec.describe ContextState, "#protect" do before :each do ScratchPad.record [] @a = lambda {|*| ScratchPad << :a } @@ -223,41 +207,41 @@ end it "returns true and does execute any blocks if check and MSpec.mode?(:pretend) are true" do - MSpec.should_receive(:mode?).with(:pretend).and_return(true) - ContextState.new("").protect("message", [@a, @b]).should be_true - ScratchPad.recorded.should == [] + expect(MSpec).to receive(:mode?).with(:pretend).and_return(true) + expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy + expect(ScratchPad.recorded).to eq([]) end it "executes the blocks if MSpec.mode?(:pretend) is false" do - MSpec.should_receive(:mode?).with(:pretend).and_return(false) + expect(MSpec).to receive(:mode?).with(:pretend).and_return(false) ContextState.new("").protect("message", [@a, @b]) - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "executes the blocks if check is false" do ContextState.new("").protect("message", [@a, @b], false) - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "returns true if none of the blocks raise an exception" do - ContextState.new("").protect("message", [@a, @b]).should be_true + expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy end it "returns false if any of the blocks raise an exception" do - ContextState.new("").protect("message", [@a, @c, @b]).should be_false + expect(ContextState.new("").protect("message", [@a, @c, @b])).to be_falsey end end -describe ContextState, "#parent=" do +RSpec.describe ContextState, "#parent=" do before :each do @state = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "does not set self as a child of parent if shared" do - @parent.should_not_receive(:child) + expect(@parent).not_to receive(:child) state = ContextState.new "", :shared => true state.parent = @parent end @@ -265,70 +249,70 @@ it "does not set parents if shared" do state = ContextState.new "", :shared => true state.parent = @parent - state.parents.should == [state] + expect(state.parents).to eq([state]) end it "sets self as a child of parent" do - @parent.should_receive(:child).with(@state) + expect(@parent).to receive(:child).with(@state) @state.parent = @parent end it "creates the list of parents" do @state.parent = @parent - @state.parents.should == [@parent, @state] + expect(@state.parents).to eq([@parent, @state]) end end -describe ContextState, "#parent" do +RSpec.describe ContextState, "#parent" do before :each do @state = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "returns nil if parent has not been set" do - @state.parent.should be_nil + expect(@state.parent).to be_nil end it "returns the parent" do @state.parent = @parent - @state.parent.should == @parent + expect(@state.parent).to eq(@parent) end end -describe ContextState, "#parents" do +RSpec.describe ContextState, "#parents" do before :each do @first = ContextState.new "" @second = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "returns a list of all enclosing ContextState instances" do @first.parent = @parent @second.parent = @first - @second.parents.should == [@parent, @first, @second] + expect(@second.parents).to eq([@parent, @first, @second]) end end -describe ContextState, "#child" do +RSpec.describe ContextState, "#child" do before :each do @first = ContextState.new "" @second = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "adds the ContextState to the list of contained ContextStates" do @first.child @second - @first.children.should == [@second] + expect(@first.children).to eq([@second]) end end -describe ContextState, "#children" do +RSpec.describe ContextState, "#children" do before :each do @parent = ContextState.new "" @first = ContextState.new "" @@ -338,12 +322,12 @@ it "returns the list of directly contained ContextStates" do @first.parent = @parent @second.parent = @first - @parent.children.should == [@first] - @first.children.should == [@second] + expect(@parent.children).to eq([@first]) + expect(@first.children).to eq([@second]) end end -describe ContextState, "#state" do +RSpec.describe ContextState, "#state" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -352,7 +336,7 @@ end it "returns nil if no spec is being executed" do - @state.state.should == nil + expect(@state.state).to eq(nil) end it "returns a ExampleState instance if an example is being executed" do @@ -360,16 +344,16 @@ @state.describe { } @state.it("") { ScratchPad.record ScratchPad.recorded.state } @state.process - @state.state.should == nil - ScratchPad.recorded.should be_kind_of(ExampleState) + expect(@state.state).to eq(nil) + expect(ScratchPad.recorded).to be_kind_of(ExampleState) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :before, [] MSpec.store :after, [] - MSpec.stub(:register_current) + allow(MSpec).to receive(:register_current) @state = ContextState.new "" @state.describe { } @@ -384,7 +368,7 @@ @state.before(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "calls each after(:all) block" do @@ -392,22 +376,22 @@ @state.after(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:b, :a] + expect(ScratchPad.recorded).to eq([:b, :a]) end it "calls each it block" do @state.it("one", &@a) @state.it("two", &@b) @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "does not call the #it block if #filtered? returns true" do @state.it("one", &@a) @state.it("two", &@b) - @state.examples.first.stub(:filtered?).and_return(true) + allow(@state.examples.first).to receive(:filtered?).and_return(true) @state.process - ScratchPad.recorded.should == [:b] + expect(ScratchPad.recorded).to eq([:b]) end it "calls each before(:each) block" do @@ -415,7 +399,7 @@ @state.before(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "calls each after(:each) block" do @@ -423,20 +407,20 @@ @state.after(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:b, :a] + expect(ScratchPad.recorded).to eq([:b, :a]) end it "calls Mock.cleanup for each it block" do @state.it("") { } @state.it("") { } - Mock.should_receive(:cleanup).twice + expect(Mock).to receive(:cleanup).twice @state.process end it "calls Mock.verify_count for each it block" do @state.it("") { } @state.it("") { } - Mock.should_receive(:verify_count).twice + expect(Mock).to receive(:verify_count).twice @state.process end @@ -444,7 +428,7 @@ ScratchPad.record [] @state.describe { ScratchPad << :a } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end it "creates a new ExampleState instance for each example" do @@ -452,44 +436,47 @@ @state.describe { } @state.it("it") { ScratchPad.record ScratchPad.recorded.state } @state.process - ScratchPad.recorded.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to be_kind_of(ExampleState) end it "clears the expectations flag before evaluating the #it block" do MSpec.clear_expectations - MSpec.should_receive(:clear_expectations) + expect(MSpec).to receive(:clear_expectations) @state.it("it") { ScratchPad.record MSpec.expectation? } @state.process - ScratchPad.recorded.should be_false + expect(ScratchPad.recorded).to be_falsey end it "shuffles the spec list if MSpec.randomize? is true" do - MSpec.randomize - MSpec.should_receive(:shuffle) - @state.it("") { } - @state.process - MSpec.randomize false + MSpec.randomize = true + begin + expect(MSpec).to receive(:shuffle) + @state.it("") { } + @state.process + ensure + MSpec.randomize = false + end end it "sets the current MSpec ContextState" do - MSpec.should_receive(:register_current).with(@state) + expect(MSpec).to receive(:register_current).with(@state) @state.process end it "resets the current MSpec ContextState to nil when there are examples" do - MSpec.should_receive(:register_current).with(nil) + expect(MSpec).to receive(:register_current).with(nil) @state.it("") { } @state.process end it "resets the current MSpec ContextState to nil when there are no examples" do - MSpec.should_receive(:register_current).with(nil) + expect(MSpec).to receive(:register_current).with(nil) @state.process end it "call #process on children when there are examples" do child = ContextState.new "" - child.should_receive(:process) + expect(child).to receive(:process) @state.child child @state.it("") { } @state.process @@ -497,13 +484,13 @@ it "call #process on children when there are no examples" do child = ContextState.new "" - child.should_receive(:process) + expect(child).to receive(:process) @state.child child @state.process end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :exception, [] @@ -527,23 +514,23 @@ def action.exception(exc) it "raises an SpecExpectationNotFoundError if an #it block does not contain an expectation" do @state.it("it") { } @state.process - ScratchPad.recorded.should == :exception + expect(ScratchPad.recorded).to eq(:exception) end it "does not raise an SpecExpectationNotFoundError if an #it block does contain an expectation" do @state.it("it") { MSpec.expectation } @state.process - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end it "does not raise an SpecExpectationNotFoundError if the #it block causes a failure" do @state.it("it") { raise Exception, "Failed!" } @state.process - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :example, [] @@ -567,18 +554,18 @@ def example.example(state, spec) @state.it("") { MSpec.expectation } @state.process - ScratchPad.recorded.first.should be_kind_of(ExampleState) - ScratchPad.recorded.last.should be_kind_of(Proc) + expect(ScratchPad.recorded.first).to be_kind_of(ExampleState) + expect(ScratchPad.recorded.last).to be_kind_of(Proc) end it "does not call registered example actions if the example has no block" do @state.it("empty example") @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -595,30 +582,30 @@ def example.example(state, spec) it "calls registered :before actions with the current ExampleState instance" do before = double("before") - before.should_receive(:before).and_return { + expect(before).to receive(:before) { ScratchPad.record :before @spec_state = @state.state } MSpec.register :before, before @state.process - ScratchPad.recorded.should == :before - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:before) + expect(@spec_state).to be_kind_of(ExampleState) end it "calls registered :after actions with the current ExampleState instance" do after = double("after") - after.should_receive(:after).and_return { + expect(after).to receive(:after) { ScratchPad.record :after @spec_state = @state.state } MSpec.register :after, after @state.process - ScratchPad.recorded.should == :after - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:after) + expect(@spec_state).to be_kind_of(ExampleState) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :enter, [] MSpec.store :leave, [] @@ -635,22 +622,22 @@ def example.example(state, spec) it "calls registered :enter actions with the current #describe string" do enter = double("enter") - enter.should_receive(:enter).with("C#m").and_return { ScratchPad.record :enter } + expect(enter).to receive(:enter).with("C#m") { ScratchPad.record :enter } MSpec.register :enter, enter @state.process - ScratchPad.recorded.should == :enter + expect(ScratchPad.recorded).to eq(:enter) end it "calls registered :leave actions" do leave = double("leave") - leave.should_receive(:leave).and_return { ScratchPad.record :leave } + expect(leave).to receive(:leave) { ScratchPad.record :leave } MSpec.register :leave, leave @state.process - ScratchPad.recorded.should == :leave + expect(ScratchPad.recorded).to eq(:leave) end end -describe ContextState, "#process when an exception is raised in before(:all)" do +RSpec.describe ContextState, "#process when an exception is raised in before(:all)" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -674,43 +661,43 @@ def example.example(state, spec) @state.before(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call the it block" do @state.it("one", &@a) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call after(:each)" do @state.after(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call after(:each)" do @state.after(:all, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call Mock.verify_count" do @state.it("") { } - Mock.should_not_receive(:verify_count) + expect(Mock).not_to receive(:verify_count) @state.process end it "calls Mock.cleanup" do @state.it("") { } - Mock.should_receive(:cleanup) + expect(Mock).to receive(:cleanup) @state.process end end -describe ContextState, "#process when an exception is raised in before(:each)" do +RSpec.describe ContextState, "#process when an exception is raised in before(:each)" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -733,24 +720,24 @@ def example.example(state, spec) it "does not call the it block" do @state.it("one", &@a) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end - it "does call after(:each)" do + it "calls after(:each)" do @state.after(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end - it "does not call Mock.verify_count" do + it "calls Mock.verify_count" do @state.it("") { } - Mock.should_not_receive(:verify_count) + expect(Mock).to receive(:verify_count) @state.process end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -776,30 +763,30 @@ def example.example(state, spec) it "calls registered :before actions with the current ExampleState instance" do before = double("before") - before.should_receive(:before).and_return { + expect(before).to receive(:before) { ScratchPad.record :before @spec_state = @state.state } MSpec.register :before, before @state.process - ScratchPad.recorded.should == :before - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:before) + expect(@spec_state).to be_kind_of(ExampleState) end it "calls registered :after actions with the current ExampleState instance" do after = double("after") - after.should_receive(:after).and_return { + expect(after).to receive(:after) { ScratchPad.record :after @spec_state = @state.state } MSpec.register :after, after @state.process - ScratchPad.recorded.should == :after - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:after) + expect(@spec_state).to be_kind_of(ExampleState) end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -824,7 +811,7 @@ def example.example(state, spec) ScratchPad.record [] @state.describe { ScratchPad << :a } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end it "does not call any before(:all) block" do @@ -832,7 +819,7 @@ def example.example(state, spec) @state.before(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any after(:all) block" do @@ -840,14 +827,14 @@ def example.example(state, spec) @state.after(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any it block" do @state.it("one", &@a) @state.it("two", &@b) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any before(:each) block" do @@ -855,7 +842,7 @@ def example.example(state, spec) @state.before(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any after(:each) block" do @@ -863,18 +850,18 @@ def example.example(state, spec) @state.after(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call Mock.cleanup" do @state.it("") { } @state.it("") { } - Mock.should_not_receive(:cleanup) + expect(Mock).not_to receive(:cleanup) @state.process end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -899,26 +886,26 @@ def example.example(state, spec) it "calls registered :enter actions with the current #describe string" do enter = double("enter") - enter.should_receive(:enter).and_return { ScratchPad.record :enter } + expect(enter).to receive(:enter) { ScratchPad.record :enter } MSpec.register :enter, enter @state.process - ScratchPad.recorded.should == :enter + expect(ScratchPad.recorded).to eq(:enter) end it "calls registered :leave actions" do leave = double("leave") - leave.should_receive(:leave).and_return { ScratchPad.record :leave } + expect(leave).to receive(:leave) { ScratchPad.record :leave } MSpec.register :leave, leave @state.process - ScratchPad.recorded.should == :leave + expect(ScratchPad.recorded).to eq(:leave) end end -describe ContextState, "#it_should_behave_like" do +RSpec.describe ContextState, "#it_should_behave_like" do before :each do @shared_desc = :shared_context @shared = ContextState.new(@shared_desc, :shared => true) - MSpec.stub(:retrieve_shared).and_return(@shared) + allow(MSpec).to receive(:retrieve_shared).and_return(@shared) @state = ContextState.new "Top level" @a = lambda {|*| } @@ -926,8 +913,8 @@ def example.example(state, spec) end it "raises an Exception if unable to find the shared ContextState" do - MSpec.should_receive(:retrieve_shared).and_return(nil) - lambda { @state.it_should_behave_like "this" }.should raise_error(Exception) + expect(MSpec).to receive(:retrieve_shared).and_return(nil) + expect { @state.it_should_behave_like "this" }.to raise_error(Exception) end describe "for nested ContextState instances" do @@ -938,24 +925,24 @@ def example.example(state, spec) @shared.children << @nested @nested_dup = @nested.dup - @nested.stub(:dup).and_return(@nested_dup) + allow(@nested).to receive(:dup).and_return(@nested_dup) end it "duplicates the nested ContextState" do @state.it_should_behave_like @shared_desc - @state.children.first.should equal(@nested_dup) + expect(@state.children.first).to equal(@nested_dup) end it "sets the parent of the nested ContextState to the containing ContextState" do @state.it_should_behave_like @shared_desc - @nested_dup.parent.should equal(@state) + expect(@nested_dup.parent).to equal(@state) end it "sets the context for nested examples to the nested ContextState's dup" do @shared.it "an example", &@a @shared.it "another example", &@b @state.it_should_behave_like @shared_desc - @nested_dup.examples.each { |x| x.context.should equal(@nested_dup) } + @nested_dup.examples.each { |x| expect(x.context).to equal(@nested_dup) } end it "omits the shored ContextState's description" do @@ -963,58 +950,58 @@ def example.example(state, spec) @nested.it "another example", &@b @state.it_should_behave_like @shared_desc - @nested_dup.description.should == "Top level nested context" - @nested_dup.examples.first.description.should == "Top level nested context an example" - @nested_dup.examples.last.description.should == "Top level nested context another example" + expect(@nested_dup.description).to eq("Top level nested context") + expect(@nested_dup.examples.first.description).to eq("Top level nested context an example") + expect(@nested_dup.examples.last.description).to eq("Top level nested context another example") end end it "adds duped examples from the shared ContextState" do @shared.it "some method", &@a ex_dup = @shared.examples.first.dup - @shared.examples.first.stub(:dup).and_return(ex_dup) + allow(@shared.examples.first).to receive(:dup).and_return(ex_dup) @state.it_should_behave_like @shared_desc - @state.examples.should == [ex_dup] + expect(@state.examples).to eq([ex_dup]) end it "sets the context for examples to the containing ContextState" do @shared.it "an example", &@a @shared.it "another example", &@b @state.it_should_behave_like @shared_desc - @state.examples.each { |x| x.context.should equal(@state) } + @state.examples.each { |x| expect(x.context).to equal(@state) } end it "adds before(:all) blocks from the shared ContextState" do @shared.before :all, &@a @shared.before :all, &@b @state.it_should_behave_like @shared_desc - @state.before(:all).should include(*@shared.before(:all)) + expect(@state.before(:all)).to include(*@shared.before(:all)) end it "adds before(:each) blocks from the shared ContextState" do @shared.before :each, &@a @shared.before :each, &@b @state.it_should_behave_like @shared_desc - @state.before(:each).should include(*@shared.before(:each)) + expect(@state.before(:each)).to include(*@shared.before(:each)) end it "adds after(:each) blocks from the shared ContextState" do @shared.after :each, &@a @shared.after :each, &@b @state.it_should_behave_like @shared_desc - @state.after(:each).should include(*@shared.after(:each)) + expect(@state.after(:each)).to include(*@shared.after(:each)) end it "adds after(:all) blocks from the shared ContextState" do @shared.after :all, &@a @shared.after :all, &@b @state.it_should_behave_like @shared_desc - @state.after(:all).should include(*@shared.after(:all)) + expect(@state.after(:all)).to include(*@shared.after(:all)) end end -describe ContextState, "#filter_examples" do +RSpec.describe ContextState, "#filter_examples" do before :each do @state = ContextState.new "" @state.it("one") { } @@ -1022,20 +1009,20 @@ def example.example(state, spec) end it "removes examples that are filtered" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.examples.size.should == 2 + allow(@state.examples.first).to receive(:filtered?).and_return(true) + expect(@state.examples.size).to eq(2) @state.filter_examples - @state.examples.size.should == 1 + expect(@state.examples.size).to eq(1) end it "returns true if there are remaining examples to evaluate" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.filter_examples.should be_true + allow(@state.examples.first).to receive(:filtered?).and_return(true) + expect(@state.filter_examples).to be_truthy end it "returns false if there are no remaining examples to evaluate" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.examples.last.stub(:filtered?).and_return(true) - @state.filter_examples.should be_false + allow(@state.examples.first).to receive(:filtered?).and_return(true) + allow(@state.examples.last).to receive(:filtered?).and_return(true) + expect(@state.filter_examples).to be_falsey end end diff --git a/ruby/spec/mspec/spec/runner/example_spec.rb b/ruby/spec/mspec/spec/runner/example_spec.rb index b4391f802..8bac166da 100644 --- a/ruby/spec/mspec/spec/runner/example_spec.rb +++ b/ruby/spec/mspec/spec/runner/example_spec.rb @@ -4,36 +4,36 @@ require 'mspec/mocks/mock' require 'mspec/runner/example' -describe ExampleState do +RSpec.describe ExampleState do it "is initialized with the ContextState, #it string, and #it block" do prc = lambda { } context = ContextState.new "" - ExampleState.new(context, "does", prc).should be_kind_of(ExampleState) + expect(ExampleState.new(context, "does", prc)).to be_kind_of(ExampleState) end end -describe ExampleState, "#describe" do +RSpec.describe ExampleState, "#describe" do before :each do - @context = ContextState.new Object, "#to_s" + @context = ContextState.new "Object#to_s" @state = ExampleState.new @context, "it" end it "returns the ContextState#description" do - @state.describe.should == @context.description + expect(@state.describe).to eq(@context.description) end end -describe ExampleState, "#it" do +RSpec.describe ExampleState, "#it" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" end it "returns the argument to the #it block" do - @state.it.should == "it" + expect(@state.it).to eq("it") end end -describe ExampleState, "#context=" do +RSpec.describe ExampleState, "#context=" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @context = ContextState.new "New#context" @@ -41,77 +41,77 @@ it "sets the containing ContextState" do @state.context = @context - @state.context.should == @context + expect(@state.context).to eq(@context) end it "resets the description" do - @state.description.should == "describe it" + expect(@state.description).to eq("describe it") @state.context = @context - @state.description.should == "New#context it" + expect(@state.description).to eq("New#context it") end end -describe ExampleState, "#example" do +RSpec.describe ExampleState, "#example" do before :each do @proc = lambda { } @state = ExampleState.new ContextState.new("describe"), "it", @proc end it "returns the #it block" do - @state.example.should == @proc + expect(@state.example).to eq(@proc) end end -describe ExampleState, "#filtered?" do +RSpec.describe ExampleState, "#filtered?" do before :each do - MSpec.store :include, nil - MSpec.store :exclude, nil + MSpec.store :include, [] + MSpec.store :exclude, [] @state = ExampleState.new ContextState.new("describe"), "it" @filter = double("filter") end after :each do - MSpec.store :include, nil - MSpec.store :exclude, nil + MSpec.store :include, [] + MSpec.store :exclude, [] end it "returns false if MSpec include filters list is empty" do - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns false if MSpec include filters match this spec" do - @filter.should_receive(:===).and_return(true) + expect(@filter).to receive(:===).and_return(true) MSpec.register :include, @filter - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns true if MSpec include filters do not match this spec" do - @filter.should_receive(:===).and_return(false) + expect(@filter).to receive(:===).and_return(false) MSpec.register :include, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end it "returns false if MSpec exclude filters list is empty" do - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns false if MSpec exclude filters do not match this spec" do - @filter.should_receive(:===).and_return(false) + expect(@filter).to receive(:===).and_return(false) MSpec.register :exclude, @filter - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns true if MSpec exclude filters match this spec" do - @filter.should_receive(:===).and_return(true) + expect(@filter).to receive(:===).and_return(true) MSpec.register :exclude, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end it "returns true if MSpec include and exclude filters match this spec" do - @filter.should_receive(:===).twice.and_return(true) + expect(@filter).to receive(:===).twice.and_return(true) MSpec.register :include, @filter MSpec.register :exclude, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end end diff --git a/ruby/spec/mspec/spec/runner/exception_spec.rb b/ruby/spec/mspec/spec/runner/exception_spec.rb index 309442435..a77a2c9cf 100644 --- a/ruby/spec/mspec/spec/runner/exception_spec.rb +++ b/ruby/spec/mspec/spec/runner/exception_spec.rb @@ -4,16 +4,16 @@ require 'mspec/runner/exception' require 'mspec/utils/script' -describe ExceptionState, "#initialize" do +RSpec.describe ExceptionState, "#initialize" do it "takes a state, location (e.g. before :each), and exception" do context = ContextState.new "Class#method" state = ExampleState.new context, "does something" exc = Exception.new "Fail!" - ExceptionState.new(state, "location", exc).should be_kind_of(ExceptionState) + expect(ExceptionState.new(state, "location", exc)).to be_kind_of(ExceptionState) end end -describe ExceptionState, "#description" do +RSpec.describe ExceptionState, "#description" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" @@ -21,99 +21,99 @@ it "returns the state description if state was not nil" do exc = ExceptionState.new(@state, nil, nil) - exc.description.should == "Class#method does something" + expect(exc.description).to eq("Class#method does something") end it "returns the location if it is not nil and description is nil" do exc = ExceptionState.new(nil, "location", nil) - exc.description.should == "An exception occurred during: location" + expect(exc.description).to eq("An exception occurred during: location") end it "returns both description and location if neither are nil" do exc = ExceptionState.new(@state, "location", nil) - exc.description.should == "An exception occurred during: location\nClass#method does something" + expect(exc.description).to eq("An exception occurred during: location\nClass#method does something") end end -describe ExceptionState, "#describe" do +RSpec.describe ExceptionState, "#describe" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" end it "returns the ExampleState#describe string if created with a non-nil state" do - ExceptionState.new(@state, nil, nil).describe.should == @state.describe + expect(ExceptionState.new(@state, nil, nil).describe).to eq(@state.describe) end it "returns an empty string if created with a nil state" do - ExceptionState.new(nil, nil, nil).describe.should == "" + expect(ExceptionState.new(nil, nil, nil).describe).to eq("") end end -describe ExceptionState, "#it" do +RSpec.describe ExceptionState, "#it" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" end it "returns the ExampleState#it string if created with a non-nil state" do - ExceptionState.new(@state, nil, nil).it.should == @state.it + expect(ExceptionState.new(@state, nil, nil).it).to eq(@state.it) end it "returns an empty string if created with a nil state" do - ExceptionState.new(nil, nil, nil).it.should == "" + expect(ExceptionState.new(nil, nil, nil).it).to eq("") end end -describe ExceptionState, "#failure?" do +RSpec.describe ExceptionState, "#failure?" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" end it "returns true if the exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!") - exc.failure?.should be_true + expect(exc.failure?).to be_truthy end it "returns true if the exception is an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", SpecExpectationNotFoundError.new("Fail!") - exc.failure?.should be_true + expect(exc.failure?).to be_truthy end it "returns false if the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", Exception.new("Fail!") - exc.failure?.should be_false + expect(exc.failure?).to be_falsey end end -describe ExceptionState, "#message" do +RSpec.describe ExceptionState, "#message" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" end it "returns if the exception message is empty" do exc = ExceptionState.new @state, "", Exception.new("") - exc.message.should == "" + expect(exc.message).to eq("Exception: ") end it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!") - exc.message.should == "Fail!" + expect(exc.message).to eq("Fail!") end it "returns SpecExpectationNotFoundError#message when the exception is an SpecExpectationNotFoundError" do e = SpecExpectationNotFoundError.new exc = ExceptionState.new @state, "", e - exc.message.should == e.message + expect(exc.message).to eq(e.message) end it "returns the message with exception class when the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", Exception.new("Fail!") - exc.message.should == "Exception: Fail!" + expect(exc.message).to eq("Exception: Fail!") end end -describe ExceptionState, "#backtrace" do +RSpec.describe ExceptionState, "#backtrace" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" begin @@ -128,19 +128,19 @@ end it "returns a string representation of the exception backtrace" do - @exc.backtrace.should be_kind_of(String) + expect(@exc.backtrace).to be_kind_of(String) end it "does not filter files from the backtrace if $MSPEC_DEBUG is true" do $MSPEC_DEBUG = true - @exc.backtrace.should == @exception.backtrace.join("\n") + expect(@exc.backtrace).to eq(@exception.backtrace.join("\n")) end it "filters files matching config[:backtrace_filter]" do MSpecScript.set :backtrace_filter, %r[mspec/lib] $MSPEC_DEBUG = nil @exc.backtrace.split("\n").each do |line| - line.should_not =~ %r[mspec/lib] + expect(line).not_to match(%r[mspec/lib]) end end end diff --git a/ruby/spec/mspec/spec/runner/filters/match_spec.rb b/ruby/spec/mspec/spec/runner/filters/match_spec.rb index f2c665c49..970da0044 100644 --- a/ruby/spec/mspec/spec/runner/filters/match_spec.rb +++ b/ruby/spec/mspec/spec/runner/filters/match_spec.rb @@ -2,33 +2,33 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters/match' -describe MatchFilter, "#===" do +RSpec.describe MatchFilter, "#===" do before :each do @filter = MatchFilter.new nil, 'a', 'b', 'c' end it "returns true if the argument matches any of the #initialize strings" do - @filter.===('aaa').should == true - @filter.===('bccb').should == true + expect(@filter.===('aaa')).to eq(true) + expect(@filter.===('bccb')).to eq(true) end it "returns false if the argument matches none of the #initialize strings" do - @filter.===('d').should == false + expect(@filter.===('d')).to eq(false) end end -describe MatchFilter, "#register" do +RSpec.describe MatchFilter, "#register" do it "registers itself with MSpec for the designated action list" do filter = MatchFilter.new :include - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.register end end -describe MatchFilter, "#unregister" do +RSpec.describe MatchFilter, "#unregister" do it "unregisters itself with MSpec for the designated action list" do filter = MatchFilter.new :exclude - MSpec.should_receive(:unregister).with(:exclude, filter) + expect(MSpec).to receive(:unregister).with(:exclude, filter) filter.unregister end end diff --git a/ruby/spec/mspec/spec/runner/filters/profile_spec.rb b/ruby/spec/mspec/spec/runner/filters/profile_spec.rb index 89d0ad191..25f5e07ae 100644 --- a/ruby/spec/mspec/spec/runner/filters/profile_spec.rb +++ b/ruby/spec/mspec/spec/runner/filters/profile_spec.rb @@ -2,45 +2,45 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters/profile' -describe ProfileFilter, "#find" do +RSpec.describe ProfileFilter, "#find" do before :each do @filter = ProfileFilter.new nil - File.stub(:exist?).and_return(false) + allow(File).to receive(:exist?).and_return(false) @file = "rails.yaml" end it "attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@file).and_return(@file) - File.should_receive(:exist?).with(@file).and_return(true) - @filter.find(@file).should == @file + expect(File).to receive(:expand_path).with(@file).and_return(@file) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@filter.find(@file)).to eq(@file) end it "attempts to locate the file in 'spec/profiles'" do path = File.join "spec/profiles", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in 'spec'" do path = File.join "spec", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in 'profiles'" do path = File.join "profiles", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in '.'" do path = File.join ".", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end end -describe ProfileFilter, "#parse" do +RSpec.describe ProfileFilter, "#parse" do before :each do @filter = ProfileFilter.new nil @file = File.open(File.dirname(__FILE__) + "/b.yaml", "r") @@ -51,14 +51,14 @@ end it "creates a Hash of the contents of the YAML file" do - @filter.parse(@file).should == { + expect(@filter.parse(@file)).to eq({ "B." => ["b", "bb"], "B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="] - } + }) end end -describe ProfileFilter, "#load" do +RSpec.describe ProfileFilter, "#load" do before :each do @filter = ProfileFilter.new nil @files = [ @@ -68,50 +68,50 @@ end it "generates a composite hash from multiple YAML files" do - @filter.load(*@files).should == { + expect(@filter.load(*@files)).to eq({ "A#" => ["a", "aa"], "B." => ["b", "bb"], "B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="] - } + }) end end -describe ProfileFilter, "#===" do +RSpec.describe ProfileFilter, "#===" do before :each do @filter = ProfileFilter.new nil - @filter.stub(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]}) + allow(@filter).to receive(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]}) @filter.send :initialize, nil end it "returns true if the spec description is for a method in the profile" do - @filter.===("The A#[]= method").should == true - @filter.===("A#a returns").should == true - @filter.===("A#a! replaces").should == true - @filter.===("A#a? returns").should == true - @filter.===("A#aa= raises").should == true + expect(@filter.===("The A#[]= method")).to eq(true) + expect(@filter.===("A#a returns")).to eq(true) + expect(@filter.===("A#a! replaces")).to eq(true) + expect(@filter.===("A#a? returns")).to eq(true) + expect(@filter.===("A#aa= raises")).to eq(true) end it "returns false if the spec description is for a method not in the profile" do - @filter.===("The A#[] method").should == false - @filter.===("B#a returns").should == false - @filter.===("A.a! replaces").should == false - @filter.===("AA#a? returns").should == false - @filter.===("A#aa raises").should == false + expect(@filter.===("The A#[] method")).to eq(false) + expect(@filter.===("B#a returns")).to eq(false) + expect(@filter.===("A.a! replaces")).to eq(false) + expect(@filter.===("AA#a? returns")).to eq(false) + expect(@filter.===("A#aa raises")).to eq(false) end end -describe ProfileFilter, "#register" do +RSpec.describe ProfileFilter, "#register" do it "registers itself with MSpec for the designated action list" do filter = ProfileFilter.new :include - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.register end end -describe ProfileFilter, "#unregister" do +RSpec.describe ProfileFilter, "#unregister" do it "unregisters itself with MSpec for the designated action list" do filter = ProfileFilter.new :exclude - MSpec.should_receive(:unregister).with(:exclude, filter) + expect(MSpec).to receive(:unregister).with(:exclude, filter) filter.unregister end end diff --git a/ruby/spec/mspec/spec/runner/filters/regexp_spec.rb b/ruby/spec/mspec/spec/runner/filters/regexp_spec.rb index 8e9b0ec7e..1d1d3554f 100644 --- a/ruby/spec/mspec/spec/runner/filters/regexp_spec.rb +++ b/ruby/spec/mspec/spec/runner/filters/regexp_spec.rb @@ -2,30 +2,30 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters/regexp' -describe MatchFilter, "#===" do +RSpec.describe MatchFilter, "#===" do before :each do @filter = RegexpFilter.new nil, 'a(b|c)', 'b[^ab]', 'cc?' end it "returns true if the argument matches any of the #initialize strings" do - @filter.===('ab').should == true - @filter.===('bc suffix').should == true - @filter.===('prefix cc').should == true + expect(@filter.===('ab')).to eq(true) + expect(@filter.===('bc suffix')).to eq(true) + expect(@filter.===('prefix cc')).to eq(true) end it "returns false if the argument matches none of the #initialize strings" do - @filter.===('aa').should == false - @filter.===('ba').should == false - @filter.===('prefix d suffix').should == false + expect(@filter.===('aa')).to eq(false) + expect(@filter.===('ba')).to eq(false) + expect(@filter.===('prefix d suffix')).to eq(false) end end -describe RegexpFilter, "#to_regexp" do +RSpec.describe RegexpFilter, "#to_regexp" do before :each do @filter = RegexpFilter.new nil end it "converts its arguments to Regexp instances" do - @filter.send(:to_regexp, 'a(b|c)', 'b[^ab]', 'cc?').should == [/a(b|c)/, /b[^ab]/, /cc?/] + expect(@filter.send(:to_regexp, 'a(b|c)', 'b[^ab]', 'cc?')).to eq([/a(b|c)/, /b[^ab]/, /cc?/]) end end diff --git a/ruby/spec/mspec/spec/runner/filters/tag_spec.rb b/ruby/spec/mspec/spec/runner/filters/tag_spec.rb index fe1f3df03..356175a75 100644 --- a/ruby/spec/mspec/spec/runner/filters/tag_spec.rb +++ b/ruby/spec/mspec/spec/runner/filters/tag_spec.rb @@ -3,90 +3,90 @@ require 'mspec/runner/filters/match' require 'mspec/runner/filters/tag' -describe TagFilter, "#load" do +RSpec.describe TagFilter, "#load" do before :each do @match = double("match filter").as_null_object @filter = TagFilter.new :include, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) end it "loads tags from the tag file" do - MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([]) + expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([]) @filter.load end it "registers itself with MSpec for the :include action" do filter = TagFilter.new(:include) - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.load end it "registers itself with MSpec for the :exclude action" do filter = TagFilter.new(:exclude) - MSpec.should_receive(:register).with(:exclude, filter) + expect(MSpec).to receive(:register).with(:exclude, filter) filter.load end end -describe TagFilter, "#unload" do +RSpec.describe TagFilter, "#unload" do before :each do @filter = TagFilter.new :include, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) end it "unregisters itself" do @filter.load - MSpec.should_receive(:unregister).with(:include, @filter) + expect(MSpec).to receive(:unregister).with(:include, @filter) @filter.unload end end -describe TagFilter, "#register" do +RSpec.describe TagFilter, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers itself with MSpec for the :load, :unload actions" do filter = TagFilter.new(nil) - MSpec.should_receive(:register).with(:load, filter) - MSpec.should_receive(:register).with(:unload, filter) + expect(MSpec).to receive(:register).with(:load, filter) + expect(MSpec).to receive(:register).with(:unload, filter) filter.register end end -describe TagFilter, "#unregister" do +RSpec.describe TagFilter, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) end it "unregisters itself with MSpec for the :load, :unload actions" do filter = TagFilter.new(nil) - MSpec.should_receive(:unregister).with(:load, filter) - MSpec.should_receive(:unregister).with(:unload, filter) + expect(MSpec).to receive(:unregister).with(:load, filter) + expect(MSpec).to receive(:unregister).with(:unload, filter) filter.unregister end end -describe TagFilter, "#===" do +RSpec.describe TagFilter, "#===" do before :each do @filter = TagFilter.new nil, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) @filter.load end it "returns true if the argument matches any of the descriptions" do - @filter.===('description').should == true + expect(@filter.===('description')).to eq(true) end it "returns false if the argument matches none of the descriptions" do - @filter.===('descriptionA').should == false - @filter.===('adescription').should == false + expect(@filter.===('descriptionA')).to eq(false) + expect(@filter.===('adescription')).to eq(false) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/describe_spec.rb b/ruby/spec/mspec/spec/runner/formatters/describe_spec.rb index 415ced71f..55f497aca 100644 --- a/ruby/spec/mspec/spec/runner/formatters/describe_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/describe_spec.rb @@ -2,14 +2,14 @@ require 'mspec/runner/formatters/describe' require 'mspec/runner/example' -describe DescribeFormatter, "#finish" do +RSpec.describe DescribeFormatter, "#finish" do before :each do - MSpec.stub(:register) - MSpec.stub(:unregister) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:unregister) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) - @timer.stub(:format).and_return("Finished in 2.0 seconds") + allow(TimerAction).to receive(:new).and_return(@timer) + allow(@timer).to receive(:format).and_return("Finished in 2.0 seconds") $stdout = @out = IOStub.new context = ContextState.new "Class#method" @@ -32,36 +32,36 @@ it "prints a summary of elapsed time" do @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do @formatter.finish - @out.should =~ /^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/ + expect(@out).to match(/^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/) end it "does not print exceptions" do @formatter.finish - @out.should == %[ + expect(@out).to eq(%[ Finished in 2.0 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end it "prints a summary of failures and errors for each describe block" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should == %[ + expect(@out).to eq(%[ Class#method 0 failures, 1 error Finished in 2.0 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/dotted_spec.rb b/ruby/spec/mspec/spec/runner/formatters/dotted_spec.rb index 5af2ff55f..336b1227e 100644 --- a/ruby/spec/mspec/spec/runner/formatters/dotted_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/dotted_spec.rb @@ -4,7 +4,7 @@ require 'mspec/runner/example' require 'mspec/utils/script' -describe DottedFormatter, "#initialize" do +RSpec.describe DottedFormatter, "#initialize" do it "permits zero arguments" do DottedFormatter.new end @@ -14,33 +14,33 @@ end end -describe DottedFormatter, "#register" do +RSpec.describe DottedFormatter, "#register" do before :each do @formatter = DottedFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers self with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:exception, @formatter) - MSpec.should_receive(:register).with(:before, @formatter) - MSpec.should_receive(:register).with(:after, @formatter) - MSpec.should_receive(:register).with(:finish, @formatter) + expect(MSpec).to receive(:register).with(:exception, @formatter) + expect(MSpec).to receive(:register).with(:before, @formatter) + expect(MSpec).to receive(:register).with(:after, @formatter) + expect(MSpec).to receive(:register).with(:finish, @formatter) @formatter.register end it "creates TimerAction and TallyAction" do timer = double("timer") tally = double("tally") - timer.should_receive(:register) - tally.should_receive(:register) - tally.should_receive(:counter) - TimerAction.should_receive(:new).and_return(timer) - TallyAction.should_receive(:new).and_return(tally) + expect(timer).to receive(:register) + expect(tally).to receive(:register) + expect(tally).to receive(:counter) + expect(TimerAction).to receive(:new).and_return(timer) + expect(TallyAction).to receive(:new).and_return(tally) @formatter.register end end -describe DottedFormatter, "#print" do +RSpec.describe DottedFormatter, "#print" do before :each do $stdout = IOStub.new end @@ -52,25 +52,25 @@ it "writes to $stdout by default" do formatter = DottedFormatter.new formatter.print "begonias" - $stdout.should == "begonias" + expect($stdout).to eq("begonias") end it "writes to the file specified when the formatter was created" do out = IOStub.new - File.should_receive(:open).with("some/file", "w").and_return(out) + expect(File).to receive(:open).with("some/file", "w").and_return(out) formatter = DottedFormatter.new "some/file" formatter.print "begonias" - out.should == "begonias" + expect(out).to eq("begonias") end it "flushes the IO output" do - $stdout.should_receive(:flush) + expect($stdout).to receive(:flush) formatter = DottedFormatter.new formatter.print "begonias" end end -describe DottedFormatter, "#exception" do +RSpec.describe DottedFormatter, "#exception" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -79,27 +79,27 @@ it "sets the #failure? flag" do @formatter.exception @failure - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.exception @error - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "sets the #exception? flag" do @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.exception @failure - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end it "adds the exception to the list of exceptions" do - @formatter.exceptions.should == [] + expect(@formatter.exceptions).to eq([]) @formatter.exception @error @formatter.exception @failure - @formatter.exceptions.should == [@error, @failure] + expect(@formatter.exceptions).to eq([@error, @failure]) end end -describe DottedFormatter, "#exception?" do +RSpec.describe DottedFormatter, "#exception?" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -107,29 +107,29 @@ end it "returns false if there have been no exceptions" do - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end it "returns true if any exceptions are errors" do @formatter.exception @failure @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end it "returns true if all exceptions are failures" do @formatter.exception @failure @formatter.exception @failure - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end it "returns true if all exceptions are errors" do @formatter.exception @error @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end end -describe DottedFormatter, "#failure?" do +RSpec.describe DottedFormatter, "#failure?" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -137,23 +137,23 @@ end it "returns false if there have been no exceptions" do - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "returns false if any exceptions are errors" do @formatter.exception @failure @formatter.exception @error - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "returns true if all exceptions are failures" do @formatter.exception @failure @formatter.exception @failure - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy end end -describe DottedFormatter, "#before" do +RSpec.describe DottedFormatter, "#before" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @formatter = DottedFormatter.new @@ -161,19 +161,19 @@ end it "resets the #failure? flag to false" do - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.before @state - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "resets the #exception? flag to false" do - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.before @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe DottedFormatter, "#after" do +RSpec.describe DottedFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = DottedFormatter.new @@ -186,21 +186,21 @@ it "prints a '.' if there was no exception raised" do @formatter.after(@state) - @out.should == "." + expect(@out).to eq(".") end it "prints an 'F' if there was an expectation failure" do exc = SpecExpectationNotMetError.new "failed" @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "F" + expect(@out).to eq("F") end it "prints an 'E' if there was an exception other than expectation failure" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "E" + expect(@out).to eq("E") end it "prints an 'E' if there are mixed exceptions and exepctation failures" do @@ -209,21 +209,21 @@ exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "E" + expect(@out).to eq("E") end end -describe DottedFormatter, "#finish" do +RSpec.describe DottedFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) $stdout = @out = IOStub.new context = ContextState.new "Class#method" @state = ExampleState.new(context, "runs") - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter = DottedFormatter.new @formatter.register end @@ -237,40 +237,39 @@ @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ /^1\)\nClass#method runs ERROR$/ + expect(@out).to match(/^1\)\nClass#method runs ERROR$/) end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ %r[path/to/some/file.rb:35:in method$] + expect(@out).to match(%r[path/to/some/file.rb:35:in method$]) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should =~ /^1 example, 0 failures$/ + expect(@out).to match(/^1 example, 0 failures$/) end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 1 failure") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 1 failure") @formatter.after @state @formatter.finish - @out.should == -%[E + expect(@out).to eq(%[E 1) Class#method runs ERROR @@ -280,6 +279,6 @@ Finished in 2.0 seconds 1 example, 1 failure -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/file_spec.rb b/ruby/spec/mspec/spec/runner/formatters/file_spec.rb index 946683ad5..ae11d6084 100644 --- a/ruby/spec/mspec/spec/runner/formatters/file_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/file_spec.rb @@ -3,27 +3,27 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' -describe FileFormatter, "#register" do +RSpec.describe FileFormatter, "#register" do before :each do @formatter = FileFormatter.new - MSpec.stub(:register) - MSpec.stub(:unregister) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:unregister) end it "registers self with MSpec for :load, :unload actions" do - MSpec.should_receive(:register).with(:load, @formatter) - MSpec.should_receive(:register).with(:unload, @formatter) + expect(MSpec).to receive(:register).with(:load, @formatter) + expect(MSpec).to receive(:register).with(:unload, @formatter) @formatter.register end it "unregisters self with MSpec for :before, :after actions" do - MSpec.should_receive(:unregister).with(:before, @formatter) - MSpec.should_receive(:unregister).with(:after, @formatter) + expect(MSpec).to receive(:unregister).with(:before, @formatter) + expect(MSpec).to receive(:unregister).with(:after, @formatter) @formatter.register end end -describe FileFormatter, "#load" do +RSpec.describe FileFormatter, "#load" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @formatter = FileFormatter.new @@ -31,19 +31,19 @@ end it "resets the #failure? flag to false" do - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.load @state - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "resets the #exception? flag to false" do - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.load @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe FileFormatter, "#unload" do +RSpec.describe FileFormatter, "#unload" do before :each do $stdout = @out = IOStub.new @formatter = FileFormatter.new @@ -56,21 +56,21 @@ it "prints a '.' if there was no exception raised" do @formatter.unload(@state) - @out.should == "." + expect(@out).to eq(".") end it "prints an 'F' if there was an expectation failure" do exc = SpecExpectationNotMetError.new "failed" @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "F" + expect(@out).to eq("F") end it "prints an 'E' if there was an exception other than expectation failure" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "E" + expect(@out).to eq("E") end it "prints an 'E' if there are mixed exceptions and exepctation failures" do @@ -79,6 +79,6 @@ exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "E" + expect(@out).to eq("E") end end diff --git a/ruby/spec/mspec/spec/runner/formatters/html_spec.rb b/ruby/spec/mspec/spec/runner/formatters/html_spec.rb index 3783ab6a8..ed973ad93 100644 --- a/ruby/spec/mspec/spec/runner/formatters/html_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/html_spec.rb @@ -4,22 +4,23 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/utils/script' +require 'mspec/helpers' -describe HtmlFormatter do +RSpec.describe HtmlFormatter do before :each do @formatter = HtmlFormatter.new end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.stub(:register) - MSpec.should_receive(:register).with(:start, @formatter) - MSpec.should_receive(:register).with(:enter, @formatter) - MSpec.should_receive(:register).with(:leave, @formatter) + allow(MSpec).to receive(:register) + expect(MSpec).to receive(:register).with(:start, @formatter) + expect(MSpec).to receive(:register).with(:enter, @formatter) + expect(MSpec).to receive(:register).with(:leave, @formatter) @formatter.register end end -describe HtmlFormatter, "#start" do +RSpec.describe HtmlFormatter, "#start" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -32,9 +33,8 @@ it "prints the HTML head" do @formatter.start ruby_engine = RUBY_ENGINE - ruby_engine.should =~ /^#{ruby_engine}/ - @out.should == -%[ @@ -55,11 +55,11 @@ -] +]) end end -describe HtmlFormatter, "#enter" do +RSpec.describe HtmlFormatter, "#enter" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -71,11 +71,11 @@ it "prints the #describe string" do @formatter.enter "describe" - @out.should == "

describe

\n
    \n" + expect(@out).to eq("

    describe

    \n
      \n") end end -describe HtmlFormatter, "#leave" do +RSpec.describe HtmlFormatter, "#leave" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -87,11 +87,11 @@ it "prints the closing tags for the #describe string" do @formatter.leave - @out.should == "
    \n
    \n" + expect(@out).to eq("
\n
\n") end end -describe HtmlFormatter, "#exception" do +RSpec.describe HtmlFormatter, "#exception" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -108,14 +108,13 @@ @formatter.exception exc exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == -%[
  • - it (FAILED - 1)
  • + expect(@out).to eq(%[
  • - it (FAILED - 1)
  • - it (ERROR - 2)
  • -] +]) end end -describe HtmlFormatter, "#after" do +RSpec.describe HtmlFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -129,7 +128,7 @@ it "prints the #it once when there are no exceptions raised" do @formatter.after @state - @out.should == %[
  • - it
  • \n] + expect(@out).to eq(%[
  • - it
  • \n]) end it "does not print any output if an exception is raised" do @@ -137,68 +136,73 @@ @formatter.exception exc out = @out.dup @formatter.after @state - @out.should == out + expect(@out).to eq(out) end end -describe HtmlFormatter, "#finish" do +RSpec.describe HtmlFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("HtmlFormatter") - $stdout = @out = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - MSpec.stub(:register) - @formatter = HtmlFormatter.new + allow(MSpec).to receive(:register) + @formatter = HtmlFormatter.new(@out) @formatter.register @exception = MSpecExampleError.new("broken") - @exception.stub(:backtrace).and_return(["file.rb:1", "file.rb:2"]) + allow(@exception).to receive(:backtrace).and_return(["file.rb:1", "file.rb:2"]) end after :each do - $stdout = STDOUT + rm_r @out end it "prints a failure message for an exception" do exc = ExceptionState.new @state, nil, @exception @formatter.exception exc @formatter.finish - @out.should include "

    describe it ERROR

    " + output = File.read(@out) + expect(output).to include "

    describe it ERROR

    " end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, @exception - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should =~ %r[
    .*path/to/some/file.rb:35:in method.*
    ]m + output = File.read(@out) + expect(output).to match(%r[
    .*path/to/some/file.rb:35:in method.*
    ]m) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should include "

    Finished in 2.0 seconds

    \n" + output = File.read(@out) + expect(output).to include "

    Finished in 2.0 seconds

    \n" end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should include '

    1 example, 0 failures

    ' + output = File.read(@out) + expect(output).to include '

    1 example, 0 failures

    ' end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, @exception - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 1 failures") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 1 failures") @formatter.finish - @out.should == -%[
  • - it (ERROR - 1)
  • + output = File.read(@out) + expect(output).to eq(%[
  • - it (ERROR - 1)

    1. describe it ERROR

      @@ -211,6 +215,6 @@

      1 example, 1 failures

      -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/junit_spec.rb b/ruby/spec/mspec/spec/runner/formatters/junit_spec.rb index 66e7d70e9..3b3da7384 100644 --- a/ruby/spec/mspec/spec/runner/formatters/junit_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/junit_spec.rb @@ -2,22 +2,23 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/junit' require 'mspec/runner/example' +require 'mspec/helpers' -describe JUnitFormatter, "#initialize" do +RSpec.describe JUnitFormatter, "#initialize" do it "permits zero arguments" do - lambda { JUnitFormatter.new }.should_not raise_error + expect { JUnitFormatter.new }.not_to raise_error end it "accepts one argument" do - lambda { JUnitFormatter.new nil }.should_not raise_error + expect { JUnitFormatter.new nil }.not_to raise_error end end -describe JUnitFormatter, "#print" do +RSpec.describe JUnitFormatter, "#print" do before :each do $stdout = IOStub.new @out = IOStub.new - File.stub(:open).and_return(@out) + allow(File).to receive(:open).and_return(@out) @formatter = JUnitFormatter.new "some/file" end @@ -27,121 +28,132 @@ it "writes to $stdout if #switch has not been called" do @formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end it "writes to the file passed to #initialize once #switch has been called" do @formatter.switch @formatter.print "begonias" - $stdout.should == "" - @out.should == "begonias" + expect($stdout).to eq("") + expect(@out).to eq("begonias") end it "writes to $stdout once #switch is called if no file was passed to #initialize" do formatter = JUnitFormatter.new formatter.switch formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end end -describe JUnitFormatter, "#finish" do +RSpec.describe JUnitFormatter, "#finish" do before :each do @tally = double("tally").as_null_object @counter = double("counter").as_null_object - @tally.stub(:counter).and_return(@counter) - TallyAction.stub(:new).and_return(@tally) + allow(@tally).to receive(:counter).and_return(@counter) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("JUnitFormatter") - $stdout = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - @formatter = JUnitFormatter.new - @formatter.stub(:backtrace).and_return("") - MSpec.stub(:register) + @formatter = JUnitFormatter.new(@out) + allow(@formatter).to receive(:backtrace).and_return("") + allow(MSpec).to receive(:register) @formatter.register exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state end after :each do - $stdout = STDOUT + rm_r @out end it "calls #switch" do - @formatter.should_receive(:switch) + expect(@formatter).to receive(:switch).and_call_original @formatter.finish end it "outputs a failure message and backtrace" do @formatter.finish - $stdout.should include 'message="error in describe it" type="error"' - $stdout.should include "MSpecExampleError: broken\n" - $stdout.should include "path/to/some/file.rb:35:in method" + output = File.read(@out) + expect(output).to include 'message="error in describe it" type="error"' + expect(output).to include "MSpecExampleError: broken\n" + expect(output).to include "path/to/some/file.rb:35:in method" end it "encodes message and backtrace in latin1 for jenkins" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken…") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in methød") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in methød") @formatter.exception exc @formatter.finish - $stdout.should =~ /MSpecExampleError: broken((\.\.\.)|\?)\n/ - $stdout.should =~ /path\/to\/some\/file\.rb:35:in meth(\?|o)d/ + output = File.binread(@out) + expect(output).to match(/MSpecExampleError: broken((\.\.\.)|\?)\n/) + expect(output).to match(/path\/to\/some\/file\.rb:35:in meth(\?|o)d/) end it "outputs an elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include 'time="4.2"' + output = File.read(@out) + expect(output).to include 'time="4.2"' end it "outputs overall elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include 'timeCount="4.2"' + output = File.read(@out) + expect(output).to include 'timeCount="4.2"' end it "outputs the number of examples as test count" do - @counter.should_receive(:examples).and_return(9) + expect(@counter).to receive(:examples).and_return(9) @formatter.finish - $stdout.should include 'tests="9"' + output = File.read(@out) + expect(output).to include 'tests="9"' end it "outputs overall number of examples as test count" do - @counter.should_receive(:examples).and_return(9) + expect(@counter).to receive(:examples).and_return(9) @formatter.finish - $stdout.should include 'testCount="9"' + output = File.read(@out) + expect(output).to include 'testCount="9"' end it "outputs a failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include 'failureCount="2"' + output = File.read(@out) + expect(output).to include 'failureCount="2"' end it "outputs overall failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include 'failures="2"' + output = File.read(@out) + expect(output).to include 'failures="2"' end it "outputs an error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include 'errors="1"' + output = File.read(@out) + expect(output).to include 'errors="1"' end it "outputs overall error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include 'errorCount="1"' + output = File.read(@out) + expect(output).to include 'errorCount="1"' end end diff --git a/ruby/spec/mspec/spec/runner/formatters/method_spec.rb b/ruby/spec/mspec/spec/runner/formatters/method_spec.rb index 77204f74c..02bf47d53 100644 --- a/ruby/spec/mspec/spec/runner/formatters/method_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/method_spec.rb @@ -4,29 +4,29 @@ require 'mspec/runner/example' require 'mspec/utils/script' -describe MethodFormatter, "#method_type" do +RSpec.describe MethodFormatter, "#method_type" do before :each do @formatter = MethodFormatter.new end it "returns 'class' if the separator is '.' or '::'" do - @formatter.method_type('.').should == "class" - @formatter.method_type('::').should == "class" + expect(@formatter.method_type('.')).to eq("class") + expect(@formatter.method_type('::')).to eq("class") end it "returns 'instance' if the separator is '#'" do - @formatter.method_type('#').should == "instance" + expect(@formatter.method_type('#')).to eq("instance") end it "returns 'unknown' for all other cases" do - @formatter.method_type(nil).should == "unknown" + expect(@formatter.method_type(nil)).to eq("unknown") end end -describe MethodFormatter, "#before" do +RSpec.describe MethodFormatter, "#before" do before :each do @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -38,32 +38,32 @@ state = ExampleState.new ContextState.new("describe"), "it" @formatter.before state - @formatter.tally.counter.examples.should == 0 - @formatter.tally.counter.expectations.should == 0 - @formatter.tally.counter.failures.should == 0 - @formatter.tally.counter.errors.should == 0 + expect(@formatter.tally.counter.examples).to eq(0) + expect(@formatter.tally.counter.expectations).to eq(0) + expect(@formatter.tally.counter.failures).to eq(0) + expect(@formatter.tally.counter.errors).to eq(0) end it "records the class, method if available" do state = ExampleState.new ContextState.new("Some#method"), "it" @formatter.before state key = "Some#method" - @formatter.methods.keys.should include(key) + expect(@formatter.methods.keys).to include(key) h = @formatter.methods[key] - h[:class].should == "Some" - h[:method].should == "method" - h[:description].should == "Some#method it" + expect(h[:class]).to eq("Some") + expect(h[:method]).to eq("method") + expect(h[:description]).to eq("Some#method it") end it "does not record class, method unless both are available" do state = ExampleState.new ContextState.new("Some method"), "it" @formatter.before state key = "Some method" - @formatter.methods.keys.should include(key) + expect(@formatter.methods.keys).to include(key) h = @formatter.methods[key] - h[:class].should == "" - h[:method].should == "" - h[:description].should == "Some method it" + expect(h[:class]).to eq("") + expect(h[:method]).to eq("") + expect(h[:description]).to eq("Some method it") end it "sets the method type to unknown if class and method are not available" do @@ -71,7 +71,7 @@ @formatter.before state key = "Some method" h = @formatter.methods[key] - h[:type].should == "unknown" + expect(h[:type]).to eq("unknown") end it "sets the method type based on the class, method separator" do @@ -79,7 +79,7 @@ state = ExampleState.new ContextState.new(k), "it" @formatter.before state h = @formatter.methods[k] - h[:type].should == t + expect(h[:type]).to eq(t) end end @@ -87,14 +87,14 @@ state = ExampleState.new ContextState.new("describe"), "it" @formatter.exceptions << "stuff" @formatter.before state - @formatter.exceptions.should be_empty + expect(@formatter.exceptions).to be_empty end end -describe MethodFormatter, "#after" do +RSpec.describe MethodFormatter, "#after" do before :each do @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -109,10 +109,10 @@ @formatter.after state h = @formatter.methods["Some#method"] - h[:examples].should == 3 - h[:expectations].should == 4 - h[:failures].should == 2 - h[:errors].should == 1 + expect(h[:examples]).to eq(3) + expect(h[:expectations]).to eq(4) + expect(h[:failures]).to eq(2) + expect(h[:errors]).to eq(1) end it "renders the list of exceptions" do @@ -125,20 +125,20 @@ @formatter.after state h = @formatter.methods["Some#method"] - h[:exceptions].should == [ + expect(h[:exceptions]).to eq([ %[failed\n\n], %[failed\n\n] - ] + ]) end end -describe MethodFormatter, "#after" do +RSpec.describe MethodFormatter, "#after" do before :each do $stdout = IOStub.new context = ContextState.new "Class#method" @state = ExampleState.new(context, "runs") @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -159,8 +159,7 @@ @formatter.after @state @formatter.finish - $stdout.should == -%[--- + expect($stdout).to eq(%[--- "Class#method": class: "Class" method: "method" @@ -173,6 +172,6 @@ exceptions: - "failed\\n\\n" - "failed\\n\\n" -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/multi_spec.rb b/ruby/spec/mspec/spec/runner/formatters/multi_spec.rb index d0ed8edc9..2d13c0583 100644 --- a/ruby/spec/mspec/spec/runner/formatters/multi_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/multi_spec.rb @@ -4,20 +4,20 @@ require 'mspec/runner/example' require 'yaml' -describe MultiFormatter, "#aggregate_results" do +RSpec.describe MultiFormatter, "#aggregate_results" do before :each do @stdout, $stdout = $stdout, IOStub.new @file = double("file").as_null_object - File.stub(:delete) - File.stub(:read) + allow(File).to receive(:delete) + allow(File).to receive(:read) @hash = { "files"=>1, "examples"=>1, "expectations"=>2, "failures"=>0, "errors"=>0 } - YAML.stub(:load).and_return(@hash) + allow(YAML).to receive(:load).and_return(@hash) @formatter = DottedFormatter.new.extend(MultiFormatter) - @formatter.timer.stub(:format).and_return("Finished in 42 seconds") + allow(@formatter.timer).to receive(:format).and_return("Finished in 42 seconds") end after :each do @@ -27,13 +27,12 @@ it "outputs a summary without errors" do @formatter.aggregate_results(["a", "b"]) @formatter.finish - $stdout.should == -%[ + expect($stdout).to eq(%[ Finished in 42 seconds 2 files, 2 examples, 4 expectations, 0 failures, 0 errors, 0 tagged -] +]) end it "outputs a summary with errors" do @@ -43,8 +42,7 @@ ] @formatter.aggregate_results(["a"]) @formatter.finish - $stdout.should == -%[ + expect($stdout).to eq(%[ 1) Some#method works real good FAILED @@ -65,6 +63,6 @@ Finished in 42 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/specdoc_spec.rb b/ruby/spec/mspec/spec/runner/formatters/specdoc_spec.rb index edb439fc1..54b5e2cf0 100644 --- a/ruby/spec/mspec/spec/runner/formatters/specdoc_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/specdoc_spec.rb @@ -2,19 +2,19 @@ require 'mspec/runner/formatters/specdoc' require 'mspec/runner/example' -describe SpecdocFormatter do +RSpec.describe SpecdocFormatter do before :each do @formatter = SpecdocFormatter.new end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.stub(:register) - MSpec.should_receive(:register).with(:enter, @formatter) + allow(MSpec).to receive(:register) + expect(MSpec).to receive(:register).with(:enter, @formatter) @formatter.register end end -describe SpecdocFormatter, "#enter" do +RSpec.describe SpecdocFormatter, "#enter" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -26,11 +26,11 @@ it "prints the #describe string" do @formatter.enter("describe") - @out.should == "\ndescribe\n" + expect(@out).to eq("\ndescribe\n") end end -describe SpecdocFormatter, "#before" do +RSpec.describe SpecdocFormatter, "#before" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -43,19 +43,19 @@ it "prints the #it string" do @formatter.before @state - @out.should == "- it" + expect(@out).to eq("- it") end it "resets the #exception? flag" do exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing") @formatter.exception exc - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.before @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe SpecdocFormatter, "#exception" do +RSpec.describe SpecdocFormatter, "#exception" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -70,13 +70,13 @@ it "prints 'ERROR' if an exception is not an SpecExpectationNotMetError" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == " (ERROR - 1)" + expect(@out).to eq(" (ERROR - 1)") end it "prints 'FAILED' if an exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing") @formatter.exception exc - @out.should == " (FAILED - 1)" + expect(@out).to eq(" (FAILED - 1)") end it "prints the #it string if an exception has already been raised" do @@ -84,11 +84,11 @@ @formatter.exception exc exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == " (FAILED - 1)\n- it (ERROR - 2)" + expect(@out).to eq(" (FAILED - 1)\n- it (ERROR - 2)") end end -describe SpecdocFormatter, "#after" do +RSpec.describe SpecdocFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -101,6 +101,6 @@ it "prints a newline character" do @formatter.after @state - @out.should == "\n" + expect(@out).to eq("\n") end end diff --git a/ruby/spec/mspec/spec/runner/formatters/spinner_spec.rb b/ruby/spec/mspec/spec/runner/formatters/spinner_spec.rb index a122620e3..5c93d3882 100644 --- a/ruby/spec/mspec/spec/runner/formatters/spinner_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/spinner_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' -describe SpinnerFormatter, "#initialize" do +RSpec.describe SpinnerFormatter, "#initialize" do it "permits zero arguments" do SpinnerFormatter.new end @@ -13,33 +13,33 @@ end end -describe SpinnerFormatter, "#register" do +RSpec.describe SpinnerFormatter, "#register" do before :each do @formatter = SpinnerFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers self with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:start, @formatter) - MSpec.should_receive(:register).with(:unload, @formatter) - MSpec.should_receive(:register).with(:after, @formatter) - MSpec.should_receive(:register).with(:finish, @formatter) + expect(MSpec).to receive(:register).with(:start, @formatter) + expect(MSpec).to receive(:register).with(:unload, @formatter) + expect(MSpec).to receive(:register).with(:after, @formatter) + expect(MSpec).to receive(:register).with(:finish, @formatter) @formatter.register end it "creates TimerAction and TallyAction" do timer = double("timer") tally = double("tally") - timer.should_receive(:register) - tally.should_receive(:register) - tally.should_receive(:counter) - TimerAction.should_receive(:new).and_return(timer) - TallyAction.should_receive(:new).and_return(tally) + expect(timer).to receive(:register) + expect(tally).to receive(:register) + expect(tally).to receive(:counter) + expect(TimerAction).to receive(:new).and_return(timer) + expect(TallyAction).to receive(:new).and_return(tally) @formatter.register end end -describe SpinnerFormatter, "#print" do +RSpec.describe SpinnerFormatter, "#print" do after :each do $stdout = STDOUT end @@ -48,11 +48,11 @@ $stdout = IOStub.new formatter = SpinnerFormatter.new "some/file" formatter.print "begonias" - $stdout.should == "begonias" + expect($stdout).to eq("begonias") end end -describe SpinnerFormatter, "#after" do +RSpec.describe SpinnerFormatter, "#after" do before :each do $stdout = IOStub.new MSpec.store(:files, ["a", "b", "c", "d"]) @@ -78,6 +78,6 @@ output = "\r[/ | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \ "\r[- | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \ "\r[\\ | ========== 25% | 00:00:00] #{green} 0F #{green} 0E#{reset} " - $stdout.should == output + expect($stdout).to eq(output) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/summary_spec.rb b/ruby/spec/mspec/spec/runner/formatters/summary_spec.rb index 16a156b69..c87d94004 100644 --- a/ruby/spec/mspec/spec/runner/formatters/summary_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/summary_spec.rb @@ -2,7 +2,7 @@ require 'mspec/runner/formatters/summary' require 'mspec/runner/example' -describe SummaryFormatter, "#after" do +RSpec.describe SummaryFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = SummaryFormatter.new @@ -21,6 +21,6 @@ exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc @formatter.after(@state) - @out.should == "" + expect(@out).to eq("") end end diff --git a/ruby/spec/mspec/spec/runner/formatters/unit_spec.rb b/ruby/spec/mspec/spec/runner/formatters/unit_spec.rb index 18167a32b..d349e6871 100644 --- a/ruby/spec/mspec/spec/runner/formatters/unit_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/unit_spec.rb @@ -3,17 +3,17 @@ require 'mspec/runner/example' require 'mspec/utils/script' -describe UnitdiffFormatter, "#finish" do +RSpec.describe UnitdiffFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) $stdout = @out = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter = UnitdiffFormatter.new @formatter.register end @@ -27,39 +27,38 @@ @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ /^1\)\ndescribe it ERROR$/ + expect(@out).to match(/^1\)\ndescribe it ERROR$/) end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, Exception.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should =~ %r[path/to/some/file.rb:35:in method$] + expect(@out).to match(%r[path/to/some/file.rb:35:in method$]) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should =~ /^1 example, 0 failures$/ + expect(@out).to match(/^1 example, 0 failures$/) end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, Exception.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should == -%[E + expect(@out).to eq(%[E Finished in 2.0 seconds @@ -69,6 +68,6 @@ path/to/some/file.rb:35:in method 1 example, 0 failures -] +]) end end diff --git a/ruby/spec/mspec/spec/runner/formatters/yaml_spec.rb b/ruby/spec/mspec/spec/runner/formatters/yaml_spec.rb index eb4d99f74..2e334fdbb 100644 --- a/ruby/spec/mspec/spec/runner/formatters/yaml_spec.rb +++ b/ruby/spec/mspec/spec/runner/formatters/yaml_spec.rb @@ -1,8 +1,9 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/yaml' require 'mspec/runner/example' +require 'mspec/helpers' -describe YamlFormatter, "#initialize" do +RSpec.describe YamlFormatter, "#initialize" do it "permits zero arguments" do YamlFormatter.new end @@ -12,11 +13,11 @@ end end -describe YamlFormatter, "#print" do +RSpec.describe YamlFormatter, "#print" do before :each do $stdout = IOStub.new @out = IOStub.new - File.stub(:open).and_return(@out) + allow(File).to receive(:open).and_return(@out) @formatter = YamlFormatter.new "some/file" end @@ -26,100 +27,108 @@ it "writes to $stdout if #switch has not been called" do @formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end it "writes to the file passed to #initialize once #switch has been called" do @formatter.switch @formatter.print "begonias" - $stdout.should == "" - @out.should == "begonias" + expect($stdout).to eq("") + expect(@out).to eq("begonias") end it "writes to $stdout once #switch is called if no file was passed to #initialize" do formatter = YamlFormatter.new formatter.switch formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end end -describe YamlFormatter, "#finish" do +RSpec.describe YamlFormatter, "#finish" do before :each do @tally = double("tally").as_null_object @counter = double("counter").as_null_object - @tally.stub(:counter).and_return(@counter) - TallyAction.stub(:new).and_return(@tally) + allow(@tally).to receive(:counter).and_return(@counter) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("YamlFormatter") - $stdout = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - @formatter = YamlFormatter.new - @formatter.stub(:backtrace).and_return("") - MSpec.stub(:register) + @formatter = YamlFormatter.new(@out) + allow(@formatter).to receive(:backtrace).and_return("") + allow(MSpec).to receive(:register) @formatter.register exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state end after :each do - $stdout = STDOUT + rm_r @out end it "calls #switch" do - @formatter.should_receive(:switch) + expect(@formatter).to receive(:switch).and_call_original @formatter.finish end it "outputs a failure message and backtrace" do @formatter.finish - $stdout.should include "describe it ERROR" - $stdout.should include "MSpecExampleError: broken\\n" - $stdout.should include "path/to/some/file.rb:35:in method" + output = File.read(@out) + expect(output).to include "describe it ERROR" + expect(output).to include "MSpecExampleError: broken\\n" + expect(output).to include "path/to/some/file.rb:35:in method" end it "outputs an elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include "time: 4.2" + output = File.read(@out) + expect(output).to include "time: 4.2" end it "outputs a file count" do - @counter.should_receive(:files).and_return(3) + expect(@counter).to receive(:files).and_return(3) @formatter.finish - $stdout.should include "files: 3" + output = File.read(@out) + expect(output).to include "files: 3" end it "outputs an example count" do - @counter.should_receive(:examples).and_return(3) + expect(@counter).to receive(:examples).and_return(3) @formatter.finish - $stdout.should include "examples: 3" + output = File.read(@out) + expect(output).to include "examples: 3" end it "outputs an expectation count" do - @counter.should_receive(:expectations).and_return(9) + expect(@counter).to receive(:expectations).and_return(9) @formatter.finish - $stdout.should include "expectations: 9" + output = File.read(@out) + expect(output).to include "expectations: 9" end it "outputs a failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include "failures: 2" + output = File.read(@out) + expect(output).to include "failures: 2" end it "outputs an error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include "errors: 1" + output = File.read(@out) + expect(output).to include "errors: 1" end end diff --git a/ruby/spec/mspec/spec/runner/mspec_spec.rb b/ruby/spec/mspec/spec/runner/mspec_spec.rb index 91338c6dd..4af01806c 100644 --- a/ruby/spec/mspec/spec/runner/mspec_spec.rb +++ b/ruby/spec/mspec/spec/runner/mspec_spec.rb @@ -1,97 +1,98 @@ require 'spec_helper' +require 'mspec/expectations/expectations' require 'mspec/helpers/tmp' require 'mspec/helpers/fs' require 'mspec/matchers/base' require 'mspec/runner/mspec' require 'mspec/runner/example' -describe MSpec, ".register_files" do +RSpec.describe MSpec, ".register_files" do it "records which spec files to run" do MSpec.register_files [:one, :two, :three] - MSpec.retrieve(:files).should == [:one, :two, :three] + expect(MSpec.files_array).to eq([:one, :two, :three]) end end -describe MSpec, ".register_mode" do +RSpec.describe MSpec, ".register_mode" do before :each do MSpec.clear_modes end it "sets execution mode flags" do MSpec.register_mode :verify - MSpec.retrieve(:modes).should == [:verify] + expect(MSpec.retrieve(:modes)).to eq([:verify]) end end -describe MSpec, ".register_tags_patterns" do +RSpec.describe MSpec, ".register_tags_patterns" do it "records the patterns for generating a tag file from a spec file" do MSpec.register_tags_patterns [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]] - MSpec.retrieve(:tags_patterns).should == [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]] + expect(MSpec.retrieve(:tags_patterns)).to eq([[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]]) end end -describe MSpec, ".register_exit" do +RSpec.describe MSpec, ".register_exit" do before :each do MSpec.store :exit, 0 end it "records the exit code" do - MSpec.exit_code.should == 0 + expect(MSpec.exit_code).to eq(0) MSpec.register_exit 1 - MSpec.exit_code.should == 1 + expect(MSpec.exit_code).to eq(1) end end -describe MSpec, ".exit_code" do +RSpec.describe MSpec, ".exit_code" do it "retrieves the code set with .register_exit" do MSpec.register_exit 99 - MSpec.exit_code.should == 99 + expect(MSpec.exit_code).to eq(99) end end -describe MSpec, ".store" do +RSpec.describe MSpec, ".store" do it "records data for MSpec settings" do MSpec.store :anything, :value - MSpec.retrieve(:anything).should == :value + expect(MSpec.retrieve(:anything)).to eq(:value) end end -describe MSpec, ".retrieve" do +RSpec.describe MSpec, ".retrieve" do it "accesses .store'd data" do MSpec.register :retrieve, :first - MSpec.retrieve(:retrieve).should == [:first] + expect(MSpec.retrieve(:retrieve)).to eq([:first]) end end -describe MSpec, ".randomize" do +RSpec.describe MSpec, ".randomize" do it "sets the flag to randomize spec execution order" do - MSpec.randomize?.should == false - MSpec.randomize - MSpec.randomize?.should == true - MSpec.randomize false - MSpec.randomize?.should == false + expect(MSpec.randomize?).to eq(false) + MSpec.randomize = true + expect(MSpec.randomize?).to eq(true) + MSpec.randomize = false + expect(MSpec.randomize?).to eq(false) end end -describe MSpec, ".register" do +RSpec.describe MSpec, ".register" do it "is the gateway behind the register(symbol, action) facility" do MSpec.register :bonus, :first MSpec.register :bonus, :second MSpec.register :bonus, :second - MSpec.retrieve(:bonus).should == [:first, :second] + expect(MSpec.retrieve(:bonus)).to eq([:first, :second]) end end -describe MSpec, ".unregister" do +RSpec.describe MSpec, ".unregister" do it "is the gateway behind the unregister(symbol, actions) facility" do MSpec.register :unregister, :first MSpec.register :unregister, :second MSpec.unregister :unregister, :second - MSpec.retrieve(:unregister).should == [:first] + expect(MSpec.retrieve(:unregister)).to eq([:first]) end end -describe MSpec, ".protect" do +RSpec.describe MSpec, ".protect" do before :each do MSpec.clear_current @cs = ContextState.new "C#m" @@ -102,11 +103,11 @@ end it "returns true if no exception is raised" do - MSpec.protect("passed") { 1 }.should be_true + expect(MSpec.protect("passed") { 1 }).to be_truthy end it "returns false if an exception is raised" do - MSpec.protect("testing") { raise ScratchPad.recorded }.should be_false + expect(MSpec.protect("testing") { raise ScratchPad.recorded }).to be_falsey end it "rescues any exceptions raised when evaluating the block argument" do @@ -119,244 +120,245 @@ rescue SystemExit ScratchPad.record :system_exit end - ScratchPad.recorded.should == :system_exit + expect(ScratchPad.recorded).to eq(:system_exit) end it "calls all the exception actions" do exc = ExceptionState.new @es, "testing", ScratchPad.recorded - ExceptionState.stub(:new).and_return(exc) + allow(ExceptionState).to receive(:new).and_return(exc) action = double("exception") - action.should_receive(:exception).with(exc) + expect(action).to receive(:exception).with(exc) MSpec.register :exception, action MSpec.protect("testing") { raise ScratchPad.recorded } MSpec.unregister :exception, action end it "registers a non-zero exit code when an exception is raised" do - MSpec.should_receive(:register_exit).with(1) + expect(MSpec).to receive(:register_exit).with(1) MSpec.protect("testing") { raise ScratchPad.recorded } end end -describe MSpec, ".register_current" do +RSpec.describe MSpec, ".register_current" do before :each do MSpec.clear_current end it "sets the value returned by MSpec.current" do - MSpec.current.should be_nil + expect(MSpec.current).to be_nil MSpec.register_current :a - MSpec.current.should == :a + expect(MSpec.current).to eq(:a) end end -describe MSpec, ".clear_current" do +RSpec.describe MSpec, ".clear_current" do it "sets the value returned by MSpec.current to nil" do MSpec.register_current :a - MSpec.current.should_not be_nil + expect(MSpec.current).not_to be_nil MSpec.clear_current - MSpec.current.should be_nil + expect(MSpec.current).to be_nil end end -describe MSpec, ".current" do +RSpec.describe MSpec, ".current" do before :each do MSpec.clear_current end it "returns nil if no ContextState has been registered" do - MSpec.current.should be_nil + expect(MSpec.current).to be_nil end it "returns the most recently registered ContextState" do first = ContextState.new "" second = ContextState.new "" MSpec.register_current first - MSpec.current.should == first + expect(MSpec.current).to eq(first) MSpec.register_current second - MSpec.current.should == second + expect(MSpec.current).to eq(second) end end -describe MSpec, ".actions" do +RSpec.describe MSpec, ".actions" do before :each do MSpec.store :start, [] ScratchPad.record [] start_one = double("one") - start_one.stub(:start).and_return { ScratchPad << :one } + allow(start_one).to receive(:start) { ScratchPad << :one } start_two = double("two") - start_two.stub(:start).and_return { ScratchPad << :two } + allow(start_two).to receive(:start) { ScratchPad << :two } MSpec.register :start, start_one MSpec.register :start, start_two end it "does not attempt to run any actions if none have been registered" do MSpec.store :finish, nil - lambda { MSpec.actions :finish }.should_not raise_error + expect { MSpec.actions :finish }.not_to raise_error end it "runs each action registered as a start action" do MSpec.actions :start - ScratchPad.recorded.should == [:one, :two] + expect(ScratchPad.recorded).to eq([:one, :two]) end end -describe MSpec, ".mode?" do +RSpec.describe MSpec, ".mode?" do before :each do MSpec.clear_modes end it "returns true if the mode has been set" do - MSpec.mode?(:verify).should == false + expect(MSpec.mode?(:verify)).to eq(false) MSpec.register_mode :verify - MSpec.mode?(:verify).should == true + expect(MSpec.mode?(:verify)).to eq(true) end end -describe MSpec, ".clear_modes" do +RSpec.describe MSpec, ".clear_modes" do it "clears all registered modes" do MSpec.register_mode(:pretend) MSpec.register_mode(:verify) - MSpec.mode?(:pretend).should == true - MSpec.mode?(:verify).should == true + expect(MSpec.mode?(:pretend)).to eq(true) + expect(MSpec.mode?(:verify)).to eq(true) MSpec.clear_modes - MSpec.mode?(:pretend).should == false - MSpec.mode?(:verify).should == false + expect(MSpec.mode?(:pretend)).to eq(false) + expect(MSpec.mode?(:verify)).to eq(false) end end -describe MSpec, ".guarded?" do +RSpec.describe MSpec, ".guarded?" do before :each do MSpec.instance_variable_set :@guarded, [] end it "returns false if no guard has run" do - MSpec.guarded?.should == false + expect(MSpec.guarded?).to eq(false) end it "returns true if a single guard has run" do MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) end it "returns true if more than one guard has run" do MSpec.guard MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) end it "returns true until all guards have finished" do MSpec.guard MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) MSpec.unguard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) MSpec.unguard - MSpec.guarded?.should == false + expect(MSpec.guarded?).to eq(false) end end -describe MSpec, ".describe" do +RSpec.describe MSpec, ".describe" do before :each do MSpec.clear_current @cs = ContextState.new "" - ContextState.stub(:new).and_return(@cs) - MSpec.stub(:current).and_return(nil) - MSpec.stub(:register_current) + allow(ContextState).to receive(:new).and_return(@cs) + allow(MSpec).to receive(:current).and_return(nil) + allow(MSpec).to receive(:register_current) end it "creates a new ContextState for the block" do - ContextState.should_receive(:new).and_return(@cs) + expect(ContextState).to receive(:new).and_return(@cs) MSpec.describe(Object) { } end it "accepts an optional second argument" do - ContextState.should_receive(:new).and_return(@cs) + expect(ContextState).to receive(:new).and_return(@cs) MSpec.describe(Object, "msg") { } end it "registers the newly created ContextState" do - MSpec.should_receive(:register_current).with(@cs).twice + expect(MSpec).to receive(:register_current).with(@cs).twice MSpec.describe(Object) { } end it "invokes the ContextState#describe method" do - prc = lambda { } - @cs.should_receive(:describe).with(&prc) - MSpec.describe(Object, "msg", &prc) + expect(@cs).to receive(:describe) + MSpec.describe(Object, "msg") {} end end -describe MSpec, ".process" do +RSpec.describe MSpec, ".process" do before :each do - MSpec.stub(:files) + allow(MSpec).to receive(:files) MSpec.store :start, [] MSpec.store :finish, [] - STDOUT.stub(:puts) + allow(STDOUT).to receive(:puts) end it "prints the RUBY_DESCRIPTION" do - STDOUT.should_receive(:puts).with(RUBY_DESCRIPTION) + expect(STDOUT).to receive(:puts).with(RUBY_DESCRIPTION) MSpec.process end it "calls all start actions" do start = double("start") - start.stub(:start).and_return { ScratchPad.record :start } + allow(start).to receive(:start) { ScratchPad.record :start } MSpec.register :start, start MSpec.process - ScratchPad.recorded.should == :start + expect(ScratchPad.recorded).to eq(:start) end it "calls all finish actions" do finish = double("finish") - finish.stub(:finish).and_return { ScratchPad.record :finish } + allow(finish).to receive(:finish) { ScratchPad.record :finish } MSpec.register :finish, finish MSpec.process - ScratchPad.recorded.should == :finish + expect(ScratchPad.recorded).to eq(:finish) end it "calls the files method" do - MSpec.should_receive(:files) + expect(MSpec).to receive(:files) MSpec.process end end -describe MSpec, ".files" do +RSpec.describe MSpec, ".files" do before :each do MSpec.store :load, [] MSpec.store :unload, [] MSpec.register_files [:one, :two, :three] - Kernel.stub(:load) + allow(Kernel).to receive(:load) end it "calls load actions before each file" do load = double("load") - load.stub(:load).and_return { ScratchPad.record :load } + allow(load).to receive(:load) { ScratchPad.record :load } MSpec.register :load, load MSpec.files - ScratchPad.recorded.should == :load + expect(ScratchPad.recorded).to eq(:load) end it "shuffles the file list if .randomize? is true" do - MSpec.randomize - MSpec.should_receive(:shuffle) + MSpec.randomize = true + expect(MSpec).to receive(:shuffle) MSpec.files - MSpec.randomize false + MSpec.randomize = false end it "registers the current file" do - MSpec.should_receive(:store).with(:file, :one) - MSpec.should_receive(:store).with(:file, :two) - MSpec.should_receive(:store).with(:file, :three) + load = double("load") + files = [] + allow(load).to receive(:load) { files << MSpec.file } + MSpec.register :load, load MSpec.files + expect(files).to eq([:one, :two, :three]) end end -describe MSpec, ".shuffle" do +RSpec.describe MSpec, ".shuffle" do before :each do @base = (0..100).to_a @list = @base.clone @@ -365,30 +367,30 @@ it "does not alter the elements in the list" do @base.each do |elt| - @list.should include(elt) + expect(@list).to include(elt) end end it "changes the order of the list" do # obviously, this spec has a certain probability # of failing. If it fails, run it again. - @list.should_not == @base + expect(@list).not_to eq(@base) end end -describe MSpec, ".tags_file" do +RSpec.describe MSpec, ".tags_file" do before :each do MSpec.store :file, "path/to/spec/something/some_spec.rb" MSpec.store :tags_patterns, nil end it "returns the default tags file for the current spec file" do - MSpec.tags_file.should == "path/to/spec/tags/something/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/spec/tags/something/some_tags.txt") end it "returns the tags file for the current spec file with custom tags_patterns" do MSpec.register_tags_patterns [[/^(.*)\/spec/, '\1/tags'], [/_spec.rb/, "_tags.txt"]] - MSpec.tags_file.should == "path/to/tags/something/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/tags/something/some_tags.txt") end it "performs multiple substitutions" do @@ -397,31 +399,31 @@ [%r(/spec/), "/spec/tags/"], [/_spec.rb/, "_tags.txt"] ] - MSpec.tags_file.should == "path/to/spec/tags/other/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/spec/tags/other/some_tags.txt") end it "handles cases where no substitution is performed" do MSpec.register_tags_patterns [[/nothing/, "something"]] - MSpec.tags_file.should == "path/to/spec/something/some_spec.rb" + expect(MSpec.tags_file).to eq("path/to/spec/something/some_spec.rb") end end -describe MSpec, ".read_tags" do +RSpec.describe MSpec, ".read_tags" do before :each do - MSpec.stub(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt') + allow(MSpec).to receive(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt') end it "returns a list of tag instances for matching tag names found" do one = SpecTag.new "fail(broken):Some#method? works" - MSpec.read_tags(["fail", "pass"]).should == [one] + expect(MSpec.read_tags(["fail", "pass"])).to eq([one]) end it "returns [] if no tags names match" do - MSpec.read_tags("super").should == [] + expect(MSpec.read_tags("super")).to eq([]) end end -describe MSpec, ".read_tags" do +RSpec.describe MSpec, ".read_tags" do before :each do @tag = SpecTag.new "fails:Some#method" File.open(tmp("tags.txt", false), "w") do |f| @@ -429,18 +431,18 @@ f.puts @tag f.puts "" end - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) end it "does not return a tag object for empty lines" do - MSpec.read_tags(["fails"]).should == [@tag] + expect(MSpec.read_tags(["fails"])).to eq([@tag]) end end -describe MSpec, ".write_tags" do +RSpec.describe MSpec, ".write_tags" do before :each do FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag1 = SpecTag.new "check(broken):Tag#rewrite works" @tag2 = SpecTag.new "broken:Tag#write_tags fails" end @@ -450,22 +452,22 @@ end it "overwrites the tags in the tag file" do - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) MSpec.write_tags [@tag1, @tag2] - IO.read(tmp("tags.txt", false)).should == %[check(broken):Tag#rewrite works + expect(IO.read(tmp("tags.txt", false))).to eq(%[check(broken):Tag#rewrite works broken:Tag#write_tags fails -] +]) end end -describe MSpec, ".write_tag" do +RSpec.describe MSpec, ".write_tag" do before :each do - FileUtils.stub(:mkdir_p) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(FileUtils).to receive(:mkdir_p) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag = SpecTag.new "fail(broken):Some#method works" end @@ -475,20 +477,20 @@ it "writes a tag to the tags file for the current spec file" do MSpec.write_tag @tag - IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n" + expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n") end it "does not write a duplicate tag" do File.open(tmp("tags.txt", false), "w") { |f| f.puts @tag } MSpec.write_tag @tag - IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n" + expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n") end end -describe MSpec, ".delete_tag" do +RSpec.describe MSpec, ".delete_tag" do before :each do FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag = SpecTag.new "fail(Comments don't matter):Some#method? works" end @@ -497,84 +499,84 @@ end it "deletes the tag if it exists" do - MSpec.delete_tag(@tag).should == true - IO.read(tmp("tags.txt", false)).should == %[incomplete(20%):The#best method ever + expect(MSpec.delete_tag(@tag)).to eq(true) + expect(IO.read(tmp("tags.txt", false))).to eq(%[incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) end it "deletes a tag with escaped newlines" do - MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true) + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today -] +]) end it "does not change the tags file contents if the tag doesn't exist" do @tag.tag = "failed" - MSpec.delete_tag(@tag).should == false - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(MSpec.delete_tag(@tag)).to eq(false) + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) end it "deletes the tag file if it is empty" do - MSpec.delete_tag(@tag).should == true - MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever")).should == true - MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today")).should == true - MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true - File.exist?(tmp("tags.txt", false)).should == false + expect(MSpec.delete_tag(@tag)).to eq(true) + expect(MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever"))).to eq(true) + expect(MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today"))).to eq(true) + expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true) + expect(File.exist?(tmp("tags.txt", false))).to eq(false) end end -describe MSpec, ".delete_tags" do +RSpec.describe MSpec, ".delete_tags" do before :each do @tags = tmp("tags.txt", false) FileUtils.cp File.dirname(__FILE__) + "/tags.txt", @tags - MSpec.stub(:tags_file).and_return(@tags) + allow(MSpec).to receive(:tags_file).and_return(@tags) end it "deletes the tag file" do MSpec.delete_tags - File.exist?(@tags).should be_false + expect(File.exist?(@tags)).to be_falsey end end -describe MSpec, ".expectation" do +RSpec.describe MSpec, ".expectation" do it "sets the flag that an expectation has been reported" do MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy end end -describe MSpec, ".expectation?" do +RSpec.describe MSpec, ".expectation?" do it "returns true if an expectation has been reported" do MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy end it "returns false if an expectation has not been reported" do MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey end end -describe MSpec, ".clear_expectations" do +RSpec.describe MSpec, ".clear_expectations" do it "clears the flag that an expectation has been reported" do MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey end end -describe MSpec, ".register_shared" do +RSpec.describe MSpec, ".register_shared" do it "stores a shared ContextState by description" do parent = ContextState.new "container" state = ContextState.new "shared" @@ -582,14 +584,14 @@ prc = lambda { } state.describe(&prc) MSpec.register_shared(state) - MSpec.retrieve(:shared)["shared"].should == state + expect(MSpec.retrieve(:shared)["shared"]).to eq(state) end end -describe MSpec, ".retrieve_shared" do +RSpec.describe MSpec, ".retrieve_shared" do it "retrieves the shared ContextState matching description" do state = ContextState.new "" MSpec.retrieve(:shared)["shared"] = state - MSpec.retrieve_shared(:shared).should == state + expect(MSpec.retrieve_shared(:shared)).to eq(state) end end diff --git a/ruby/spec/mspec/spec/runner/shared_spec.rb b/ruby/spec/mspec/spec/runner/shared_spec.rb index b91800b7d..153b8f069 100644 --- a/ruby/spec/mspec/spec/runner/shared_spec.rb +++ b/ruby/spec/mspec/spec/runner/shared_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/context' require 'mspec/runner/example' -describe Object, "#it_behaves_like" do +RSpec.describe Object, "#it_behaves_like" do before :each do ScratchPad.clear @@ -14,14 +14,14 @@ @state.singleton_class.send(:public, :it_behaves_like) @shared = ContextState.new :shared_spec, :shared => true - MSpec.stub(:retrieve_shared).and_return(@shared) + allow(MSpec).to receive(:retrieve_shared).and_return(@shared) end it "creates @method set to the name of the aliased method" do @shared.it("an example") { ScratchPad.record @method } @state.it_behaves_like :shared_spec, :some_method @state.process - ScratchPad.recorded.should == :some_method + expect(ScratchPad.recorded).to eq(:some_method) end it "creates @object if the passed object" do @@ -29,7 +29,7 @@ @shared.it("an example") { ScratchPad.record @object } @state.it_behaves_like :shared_spec, :some_method, object @state.process - ScratchPad.recorded.should == object + expect(ScratchPad.recorded).to eq(object) end it "creates @object if the passed false" do @@ -37,11 +37,11 @@ @shared.it("an example") { ScratchPad.record @object } @state.it_behaves_like :shared_spec, :some_method, object @state.process - ScratchPad.recorded.should == object + expect(ScratchPad.recorded).to eq(object) end it "sends :it_should_behave_like" do - @state.should_receive(:it_should_behave_like) + expect(@state).to receive(:it_should_behave_like) @state.it_behaves_like :shared_spec, :some_method end @@ -61,12 +61,12 @@ @state.it_behaves_like :shared_spec, :some_method, @obj @state.process - ScratchPad.recorded.should == [:some_method, @obj] + expect(ScratchPad.recorded).to eq([:some_method, @obj]) @state2.it_behaves_like :shared_spec, :another_method, @obj2 @state2.process - ScratchPad.recorded.should == [:another_method, @obj2] + expect(ScratchPad.recorded).to eq([:another_method, @obj2]) end it "ensures the shared spec state is distinct for nested shared specs" do @@ -79,12 +79,12 @@ @state.it_behaves_like :shared_spec, :some_method, @obj @state.process - ScratchPad.recorded.should == [:shared, :some_method, @obj] + expect(ScratchPad.recorded).to eq([:shared, :some_method, @obj]) @state2.it_behaves_like :shared_spec, :another_method, @obj2 @state2.process - ScratchPad.recorded.should == [:shared, :another_method, @obj2] + expect(ScratchPad.recorded).to eq([:shared, :another_method, @obj2]) end end end diff --git a/ruby/spec/mspec/spec/runner/tag_spec.rb b/ruby/spec/mspec/spec/runner/tag_spec.rb index db55a1b18..bda9ac428 100644 --- a/ruby/spec/mspec/spec/runner/tag_spec.rb +++ b/ruby/spec/mspec/spec/runner/tag_spec.rb @@ -1,123 +1,123 @@ require 'spec_helper' require 'mspec/runner/tag' -describe SpecTag do +RSpec.describe SpecTag do it "accepts an optional string to parse into fields" do tag = SpecTag.new "tag(comment):description" - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "description" + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("description") end end -describe SpecTag, "#parse" do +RSpec.describe SpecTag, "#parse" do before :each do @tag = SpecTag.new end it "accepts 'tag(comment):description'" do @tag.parse "tag(I'm real):Some#method returns a value" - @tag.tag.should == "tag" - @tag.comment.should == "I'm real" - @tag.description.should == "Some#method returns a value" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("I'm real") + expect(@tag.description).to eq("Some#method returns a value") end it "accepts 'tag:description'" do @tag.parse "tag:Another#method" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("Another#method") end it "accepts 'tag():description'" do @tag.parse "tag():Another#method" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("Another#method") end it "accepts 'tag:'" do @tag.parse "tag:" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("") end it "accepts 'tag(bug:555):Another#method'" do @tag.parse "tag(bug:555):Another#method" - @tag.tag.should == "tag" - @tag.comment.should == "bug:555" - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("bug:555") + expect(@tag.description).to eq("Another#method") end it "accepts 'tag(http://someplace.com/neato):Another#method'" do @tag.parse "tag(http://someplace.com/neato):Another#method" - @tag.tag.should == "tag" - @tag.comment.should == "http://someplace.com/neato" - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("http://someplace.com/neato") + expect(@tag.description).to eq("Another#method") end it "accepts 'tag(comment):\"Multi-line\\ntext\"'" do @tag.parse 'tag(comment):"Multi-line\ntext"' - @tag.tag.should == "tag" - @tag.comment.should == "comment" - @tag.description.should == "Multi-line\ntext" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("comment") + expect(@tag.description).to eq("Multi-line\ntext") end it "ignores '#anything'" do @tag.parse "# this could be a comment" - @tag.tag.should == nil - @tag.comment.should == nil - @tag.description.should == nil + expect(@tag.tag).to eq(nil) + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq(nil) end end -describe SpecTag, "#to_s" do +RSpec.describe SpecTag, "#to_s" do it "formats itself as 'tag(comment):description'" do txt = "tag(comment):description" tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "description" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("description") + expect(tag.to_s).to eq(txt) end it "formats itself as 'tag:description" do txt = "tag:description" tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == nil - tag.description.should == "description" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq(nil) + expect(tag.description).to eq("description") + expect(tag.to_s).to eq(txt) end it "formats itself as 'tag(comment):\"multi-line\\ntext\\ntag\"'" do txt = 'tag(comment):"multi-line\ntext\ntag"' tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "multi-line\ntext\ntag" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("multi-line\ntext\ntag") + expect(tag.to_s).to eq(txt) end end -describe SpecTag, "#==" do +RSpec.describe SpecTag, "#==" do it "returns true if the tags have the same fields" do one = SpecTag.new "tag(this):unicorn" two = SpecTag.new "tag(this):unicorn" - one.==(two).should == true - [one].==([two]).should == true + expect(one.==(two)).to eq(true) + expect([one].==([two])).to eq(true) end end -describe SpecTag, "#unescape" do +RSpec.describe SpecTag, "#unescape" do it "replaces \\n by LF when the description is quoted" do tag = SpecTag.new 'tag:"desc with\nnew line"' - tag.description.should == "desc with\nnew line" + expect(tag.description).to eq("desc with\nnew line") end it "does not replaces \\n by LF when the description is not quoted " do tag = SpecTag.new 'tag:desc with\nnew line' - tag.description.should == "desc with\\nnew line" + expect(tag.description).to eq("desc with\\nnew line") end end diff --git a/ruby/spec/mspec/spec/spec_helper.rb b/ruby/spec/mspec/spec/spec_helper.rb index a307eaf46..3a749581e 100644 --- a/ruby/spec/mspec/spec/spec_helper.rb +++ b/ruby/spec/mspec/spec/spec_helper.rb @@ -1,6 +1,9 @@ -require 'mspec/utils/format' -require 'mspec/helpers/io' -require 'mspec/helpers/scratch' +RSpec.configure do |config| + config.disable_monkey_patching! + config.raise_errors_for_deprecations! +end + +require 'mspec' # Remove this when MRI has intelligent warnings $VERBOSE = nil unless $VERBOSE @@ -37,7 +40,7 @@ class MSpecExampleError < Exception end def hide_deprecation_warnings - MSpec.stub(:deprecate) + allow(MSpec).to receive(:deprecate) end def run_mspec(command, args) @@ -53,3 +56,13 @@ def run_mspec(command, args) out = out.gsub(cwd, "CWD") return out, ret end + +def ensure_mspec_method(method) + file, _line = method.source_location + expect(file).to start_with(File.expand_path('../../lib/mspec', __FILE__ )) +end + +PublicMSpecMatchers = Class.new { + include MSpecMatchers + public :raise_error +}.new diff --git a/ruby/spec/mspec/spec/utils/deprecate_spec.rb b/ruby/spec/mspec/spec/utils/deprecate_spec.rb index 7fa60df26..73eaf7d04 100644 --- a/ruby/spec/mspec/spec/utils/deprecate_spec.rb +++ b/ruby/spec/mspec/spec/utils/deprecate_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' require 'mspec/utils/deprecate' -describe MSpec, "#deprecate" do +RSpec.describe MSpec, "#deprecate" do it "warns when using a deprecated method" do warning = nil - $stderr.stub(:puts) { |str| warning = str } + allow($stderr).to receive(:puts) { |str| warning = str } MSpec.deprecate(:some_method, :other_method) - warning.should start_with(<<-EOS.chomp) + expect(warning).to start_with(<<-EOS.chomp) some_method is deprecated, use other_method instead. from EOS - warning.should include(__FILE__) - warning.should include('8') + expect(warning).to include(__FILE__) + expect(warning).to include('8') end end diff --git a/ruby/spec/mspec/spec/utils/name_map_spec.rb b/ruby/spec/mspec/spec/utils/name_map_spec.rb index d5d2cca84..a18a48150 100644 --- a/ruby/spec/mspec/spec/utils/name_map_spec.rb +++ b/ruby/spec/mspec/spec/utils/name_map_spec.rb @@ -25,46 +25,46 @@ def self.n; end def n; end end -describe NameMap, "#exception?" do +RSpec.describe NameMap, "#exception?" do before :each do @map = NameMap.new end it "returns true if the constant is Errno" do - @map.exception?("Errno").should == true + expect(@map.exception?("Errno")).to eq(true) end it "returns true if the constant is a kind of Exception" do - @map.exception?("Errno::EBADF").should == true - @map.exception?("LoadError").should == true - @map.exception?("SystemExit").should == true + expect(@map.exception?("Errno::EBADF")).to eq(true) + expect(@map.exception?("LoadError")).to eq(true) + expect(@map.exception?("SystemExit")).to eq(true) end it "returns false if the constant is not a kind of Exception" do - @map.exception?("NameMapSpecs::Error").should == false - @map.exception?("NameMapSpecs").should == false + expect(@map.exception?("NameMapSpecs::Error")).to eq(false) + expect(@map.exception?("NameMapSpecs")).to eq(false) end it "returns false if the constant does not exist" do - @map.exception?("Nonexistent").should == false + expect(@map.exception?("Nonexistent")).to eq(false) end end -describe NameMap, "#class_or_module" do +RSpec.describe NameMap, "#class_or_module" do before :each do @map = NameMap.new true end it "returns the constant specified by the string" do - @map.class_or_module("NameMapSpecs").should == NameMapSpecs + expect(@map.class_or_module("NameMapSpecs")).to eq(NameMapSpecs) end it "returns the constant specified by the 'A::B' string" do - @map.class_or_module("NameMapSpecs::A").should == NameMapSpecs::A + expect(@map.class_or_module("NameMapSpecs::A")).to eq(NameMapSpecs::A) end it "returns nil if the constant is not a class or module" do - @map.class_or_module("Float::MAX").should == nil + expect(@map.class_or_module("Float::MAX")).to eq(nil) end it "returns nil if the constant is in the set of excluded constants" do @@ -75,101 +75,101 @@ def n; end ] excluded.each do |const| - @map.class_or_module(const).should == nil + expect(@map.class_or_module(const)).to eq(nil) end end it "returns nil if the constant does not exist" do - @map.class_or_module("Heaven").should == nil - @map.class_or_module("Hell").should == nil - @map.class_or_module("Bush::Brain").should == nil + expect(@map.class_or_module("Heaven")).to eq(nil) + expect(@map.class_or_module("Hell")).to eq(nil) + expect(@map.class_or_module("Bush::Brain")).to eq(nil) end end -describe NameMap, "#dir_name" do +RSpec.describe NameMap, "#dir_name" do before :each do @map = NameMap.new end it "returns a directory name from the base name and constant" do - @map.dir_name("NameMapSpecs", 'spec/core').should == 'spec/core/namemapspecs' + expect(@map.dir_name("NameMapSpecs", 'spec/core')).to eq('spec/core/namemapspecs') end it "returns a directory name from the components in the constants name" do - @map.dir_name("NameMapSpecs::A", 'spec').should == 'spec/namemapspecs/a' - @map.dir_name("NameMapSpecs::A::B", 'spec').should == 'spec/namemapspecs/a/b' + expect(@map.dir_name("NameMapSpecs::A", 'spec')).to eq('spec/namemapspecs/a') + expect(@map.dir_name("NameMapSpecs::A::B", 'spec')).to eq('spec/namemapspecs/a/b') end it "returns a directory name without 'class' for constants like TrueClass" do - @map.dir_name("TrueClass", 'spec').should == 'spec/true' - @map.dir_name("FalseClass", 'spec').should == 'spec/false' + expect(@map.dir_name("TrueClass", 'spec')).to eq('spec/true') + expect(@map.dir_name("FalseClass", 'spec')).to eq('spec/false') end it "returns 'exception' for the directory name of any Exception subclass" do - @map.dir_name("SystemExit", 'spec').should == 'spec/exception' - @map.dir_name("Errno::EBADF", 'spec').should == 'spec/exception' + expect(@map.dir_name("SystemExit", 'spec')).to eq('spec/exception') + expect(@map.dir_name("Errno::EBADF", 'spec')).to eq('spec/exception') end it "returns 'class' for Class" do - @map.dir_name("Class", 'spec').should == 'spec/class' + expect(@map.dir_name("Class", 'spec')).to eq('spec/class') end end # These specs do not cover all the mappings, but only describe how the # name is derived when the hash item maps to a single value, a hash with # a specific item, or a hash with a :default item. -describe NameMap, "#file_name" do +RSpec.describe NameMap, "#file_name" do before :each do @map = NameMap.new end it "returns the name of the spec file based on the constant and method" do - @map.file_name("[]=", "Array").should == "element_set_spec.rb" + expect(@map.file_name("[]=", "Array")).to eq("element_set_spec.rb") end it "returns the name of the spec file based on the special entry for the method" do - @map.file_name("~", "Regexp").should == "match_spec.rb" - @map.file_name("~", "Integer").should == "complement_spec.rb" + expect(@map.file_name("~", "Regexp")).to eq("match_spec.rb") + expect(@map.file_name("~", "Integer")).to eq("complement_spec.rb") end it "returns the name of the spec file based on the default entry for the method" do - @map.file_name("<<", "NameMapSpecs").should == "append_spec.rb" + expect(@map.file_name("<<", "NameMapSpecs")).to eq("append_spec.rb") end it "uses the last component of the constant to look up the method name" do - @map.file_name("^", "NameMapSpecs::Integer").should == "bit_xor_spec.rb" + expect(@map.file_name("^", "NameMapSpecs::Integer")).to eq("bit_xor_spec.rb") end end -describe NameMap, "#namespace" do +RSpec.describe NameMap, "#namespace" do before :each do @map = NameMap.new end it "prepends the module to the constant name" do - @map.namespace("SubModule", Integer).should == "SubModule::Integer" + expect(@map.namespace("SubModule", Integer)).to eq("SubModule::Integer") end it "does not prepend Object, Class, or Module to the constant name" do - @map.namespace("Object", String).should == "String" - @map.namespace("Module", Integer).should == "Integer" - @map.namespace("Class", Float).should == "Float" + expect(@map.namespace("Object", String)).to eq("String") + expect(@map.namespace("Module", Integer)).to eq("Integer") + expect(@map.namespace("Class", Float)).to eq("Float") end end -describe NameMap, "#map" do +RSpec.describe NameMap, "#map" do before :each do @map = NameMap.new end it "flattens an object hierarchy into a single Hash" do - @map.map({}, [NameMapSpecs]).should == { + expect(@map.map({}, [NameMapSpecs])).to eq({ "NameMapSpecs." => ["n"], "NameMapSpecs#" => ["n"], "NameMapSpecs::A." => ["a"], "NameMapSpecs::A#" => ["a", "c"], "NameMapSpecs::A::B#" => ["b"], "NameMapSpecs::Fixnum#" => ["f"] - } + }) end end diff --git a/ruby/spec/mspec/spec/utils/options_spec.rb b/ruby/spec/mspec/spec/utils/options_spec.rb index face90928..2e3925f57 100644 --- a/ruby/spec/mspec/spec/utils/options_spec.rb +++ b/ruby/spec/mspec/spec/utils/options_spec.rb @@ -5,155 +5,155 @@ require 'mspec/runner/mspec' require 'mspec/runner/formatters' -describe MSpecOption, ".new" do +RSpec.describe MSpecOption, ".new" do before :each do @opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block) end it "sets the short attribute" do - @opt.short.should == "-a" + expect(@opt.short).to eq("-a") end it "sets the long attribute" do - @opt.long.should == "--bdc" + expect(@opt.long).to eq("--bdc") end it "sets the arg attribute" do - @opt.arg.should == "ARG" + expect(@opt.arg).to eq("ARG") end it "sets the description attribute" do - @opt.description.should == "desc" + expect(@opt.description).to eq("desc") end it "sets the block attribute" do - @opt.block.should == :block + expect(@opt.block).to eq(:block) end end -describe MSpecOption, "#arg?" do +RSpec.describe MSpecOption, "#arg?" do it "returns true if arg attribute is not nil" do - MSpecOption.new(nil, nil, "ARG", nil, nil).arg?.should be_true + expect(MSpecOption.new(nil, nil, "ARG", nil, nil).arg?).to be_truthy end it "returns false if arg attribute is nil" do - MSpecOption.new(nil, nil, nil, nil, nil).arg?.should be_false + expect(MSpecOption.new(nil, nil, nil, nil, nil).arg?).to be_falsey end end -describe MSpecOption, "#match?" do +RSpec.describe MSpecOption, "#match?" do before :each do @opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block) end it "returns true if the argument matches the short option" do - @opt.match?("-a").should be_true + expect(@opt.match?("-a")).to be_truthy end it "returns true if the argument matches the long option" do - @opt.match?("--bdc").should be_true + expect(@opt.match?("--bdc")).to be_truthy end it "returns false if the argument matches neither the short nor long option" do - @opt.match?("-b").should be_false - @opt.match?("-abdc").should be_false + expect(@opt.match?("-b")).to be_falsey + expect(@opt.match?("-abdc")).to be_falsey end end -describe MSpecOptions, ".new" do +RSpec.describe MSpecOptions, ".new" do before :each do @opt = MSpecOptions.new("cmd", 20, :config) end it "sets the banner attribute" do - @opt.banner.should == "cmd" + expect(@opt.banner).to eq("cmd") end it "sets the config attribute" do - @opt.config.should == :config + expect(@opt.config).to eq(:config) end it "sets the width attribute" do - @opt.width.should == 20 + expect(@opt.width).to eq(20) end it "sets the default width attribute" do - MSpecOptions.new.width.should == 30 + expect(MSpecOptions.new.width).to eq(30) end end -describe MSpecOptions, "#on" do +RSpec.describe MSpecOptions, "#on" do before :each do @opt = MSpecOptions.new end it "adds a short option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short option taking an argument" do - @opt.should_receive(:add).with("-a", nil, "ARG", "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, "ARG", "desc", nil) @opt.on("-a", "ARG", "desc") end it "adds a long option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a long option taking an argument" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short and long option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short and long option taking an argument" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "raises MSpecOptions::OptionError if pass less than 2 arguments" do - lambda { @opt.on }.should raise_error(MSpecOptions::OptionError) - lambda { @opt.on "" }.should raise_error(MSpecOptions::OptionError) + expect { @opt.on }.to raise_error(MSpecOptions::OptionError) + expect { @opt.on "" }.to raise_error(MSpecOptions::OptionError) end end -describe MSpecOptions, "#add" do +RSpec.describe MSpecOptions, "#add" do before :each do @opt = MSpecOptions.new "cmd", 20 @prc = lambda { } end it "adds documentation for an option" do - @opt.should_receive(:doc).with(" -t, --typo ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" -t, --typo ARG Correct typo ARG") @opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc) end it "leaves spaces in the documentation for a missing short option" do - @opt.should_receive(:doc).with(" --typo ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" --typo ARG Correct typo ARG") @opt.add(nil, "--typo", "ARG", "Correct typo ARG", @prc) end it "handles a short option with argument but no long argument" do - @opt.should_receive(:doc).with(" -t ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" -t ARG Correct typo ARG") @opt.add("-t", nil, "ARG", "Correct typo ARG", @prc) end it "registers an option" do option = MSpecOption.new "-t", "--typo", "ARG", "Correct typo ARG", @prc - MSpecOption.should_receive(:new).with( + expect(MSpecOption).to receive(:new).with( "-t", "--typo", "ARG", "Correct typo ARG", @prc).and_return(option) @opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc) - @opt.options.should == [option] + expect(@opt.options).to eq([option]) end end -describe MSpecOptions, "#match?" do +RSpec.describe MSpecOptions, "#match?" do before :each do @opt = MSpecOptions.new end @@ -161,15 +161,15 @@ it "returns the MSpecOption instance matching the argument" do @opt.on "-a", "--abdc", "desc" option = @opt.match? "-a" - @opt.match?("--abdc").should be(option) - option.should be_kind_of(MSpecOption) - option.short.should == "-a" - option.long.should == "--abdc" - option.description.should == "desc" + expect(@opt.match?("--abdc")).to be(option) + expect(option).to be_kind_of(MSpecOption) + expect(option.short).to eq("-a") + expect(option.long).to eq("--abdc") + expect(option.description).to eq("desc") end end -describe MSpecOptions, "#process" do +RSpec.describe MSpecOptions, "#process" do before :each do @opt = MSpecOptions.new ScratchPad.clear @@ -178,62 +178,62 @@ it "calls the on_extra block if the argument does not match any option" do @opt.on_extra { ScratchPad.record :extra } @opt.process ["-a"], "-a", "-a", nil - ScratchPad.recorded.should == :extra + expect(ScratchPad.recorded).to eq(:extra) end it "returns the matching option" do @opt.on "-a", "ARG", "desc" option = @opt.process [], "-a", "-a", "ARG" - option.should be_kind_of(MSpecOption) - option.short.should == "-a" - option.arg.should == "ARG" - option.description.should == "desc" + expect(option).to be_kind_of(MSpecOption) + expect(option.short).to eq("-a") + expect(option.arg).to eq("ARG") + expect(option.description).to eq("desc") end it "raises an MSpecOptions::ParseError if arg is nil and there are no more entries in argv" do @opt.on "-a", "ARG", "desc" - lambda { @opt.process [], "-a", "-a", nil }.should raise_error(MSpecOptions::ParseError) + expect { @opt.process [], "-a", "-a", nil }.to raise_error(MSpecOptions::ParseError) end it "fetches the argument for the option from argv if arg is nil" do @opt.on("-a", "ARG", "desc") { |o| ScratchPad.record o } @opt.process ["ARG"], "-a", "-a", nil - ScratchPad.recorded.should == "ARG" + expect(ScratchPad.recorded).to eq("ARG") end it "calls the option's block" do @opt.on("-a", "ARG", "desc") { ScratchPad.record :option } @opt.process [], "-a", "-a", "ARG" - ScratchPad.recorded.should == :option + expect(ScratchPad.recorded).to eq(:option) end it "does not call the option's block if it is nil" do @opt.on "-a", "ARG", "desc" - lambda { @opt.process [], "-a", "-a", "ARG" }.should_not raise_error + expect { @opt.process [], "-a", "-a", "ARG" }.not_to raise_error end end -describe MSpecOptions, "#split" do +RSpec.describe MSpecOptions, "#split" do before :each do @opt = MSpecOptions.new end it "breaks a string at the nth character" do opt, arg, rest = @opt.split "-bdc", 2 - opt.should == "-b" - arg.should == "dc" - rest.should == "dc" + expect(opt).to eq("-b") + expect(arg).to eq("dc") + expect(rest).to eq("dc") end it "returns nil for arg if there are no characters left" do opt, arg, rest = @opt.split "-b", 2 - opt.should == "-b" - arg.should == nil - rest.should == "" + expect(opt).to eq("-b") + expect(arg).to eq(nil) + expect(rest).to eq("") end end -describe MSpecOptions, "#parse" do +RSpec.describe MSpecOptions, "#parse" do before :each do @opt = MSpecOptions.new @prc = lambda { ScratchPad.record :parsed } @@ -244,43 +244,43 @@ it "parses a short option" do @opt.on "-a", "desc", &@prc @opt.parse ["-a"] - ScratchPad.recorded.should == :parsed + expect(ScratchPad.recorded).to eq(:parsed) end it "parse a long option" do @opt.on "--abdc", "desc", &@prc @opt.parse ["--abdc"] - ScratchPad.recorded.should == :parsed + expect(ScratchPad.recorded).to eq(:parsed) end it "parses a short option group" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-a", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option with an argument" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-a", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option with connected argument" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-aARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a long option with an argument" do @opt.on "--abdc", "ARG", "desc", &@arg_prc @opt.parse ["--abdc", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a long option with an '=' argument" do @opt.on "--abdc", "ARG", "desc", &@arg_prc @opt.parse ["--abdc=ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option group with the final option taking an argument" do @@ -288,7 +288,7 @@ @opt.on("-a", "desc") { |o| ScratchPad << :a } @opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] } @opt.parse ["-ab", "ARG"] - ScratchPad.recorded.should == [:a, [:b, "ARG"]] + expect(ScratchPad.recorded).to eq([:a, [:b, "ARG"]]) end it "parses a short option group with a connected argument" do @@ -297,12 +297,12 @@ @opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] } @opt.on("-c", "desc") { |o| ScratchPad << :c } @opt.parse ["-acbARG"] - ScratchPad.recorded.should == [:a, :c, [:b, "ARG"]] + expect(ScratchPad.recorded).to eq([:a, :c, [:b, "ARG"]]) end it "returns the unprocessed entries" do @opt.on "-a", "ARG", "desc", &@arg_prc - @opt.parse(["abdc", "-a", "ilny"]).should == ["abdc"] + expect(@opt.parse(["abdc", "-a", "ilny"])).to eq(["abdc"]) end it "calls the on_extra handler with unrecognized options" do @@ -310,59 +310,59 @@ @opt.on_extra { |o| ScratchPad << o } @opt.on "-a", "desc" @opt.parse ["-a", "-b"] - ScratchPad.recorded.should == ["-b"] + expect(ScratchPad.recorded).to eq(["-b"]) end it "does not attempt to call the block if it is nil" do @opt.on "-a", "ARG", "desc" - @opt.parse(["-a", "ARG"]).should == [] + expect(@opt.parse(["-a", "ARG"])).to eq([]) end it "raises MSpecOptions::ParseError if passed an unrecognized option" do - @opt.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) - @opt.stub(:puts) - @opt.stub(:exit) + expect(@opt).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) + allow(@opt).to receive(:puts) + allow(@opt).to receive(:exit) @opt.parse "-u" end end -describe MSpecOptions, "#banner=" do +RSpec.describe MSpecOptions, "#banner=" do before :each do @opt = MSpecOptions.new end it "sets the banner attribute" do - @opt.banner.should == "" + expect(@opt.banner).to eq("") @opt.banner = "banner" - @opt.banner.should == "banner" + expect(@opt.banner).to eq("banner") end end -describe MSpecOptions, "#width=" do +RSpec.describe MSpecOptions, "#width=" do before :each do @opt = MSpecOptions.new end it "sets the width attribute" do - @opt.width.should == 30 + expect(@opt.width).to eq(30) @opt.width = 20 - @opt.width.should == 20 + expect(@opt.width).to eq(20) end end -describe MSpecOptions, "#config=" do +RSpec.describe MSpecOptions, "#config=" do before :each do @opt = MSpecOptions.new end it "sets the config attribute" do - @opt.config.should be_nil + expect(@opt.config).to be_nil @opt.config = :config - @opt.config.should == :config + expect(@opt.config).to eq(:config) end end -describe MSpecOptions, "#doc" do +RSpec.describe MSpecOptions, "#doc" do before :each do @opt = MSpecOptions.new "command" end @@ -370,7 +370,7 @@ it "adds text to be displayed with #to_s" do @opt.doc "Some message" @opt.doc "Another message" - @opt.to_s.should == <<-EOD + expect(@opt.to_s).to eq <<-EOD command Some message @@ -379,15 +379,15 @@ end end -describe MSpecOptions, "#version" do +RSpec.describe MSpecOptions, "#version" do before :each do @opt = MSpecOptions.new ScratchPad.clear end it "installs a basic -v, --version option" do - @opt.should_receive(:puts) - @opt.should_receive(:exit) + expect(@opt).to receive(:puts) + expect(@opt).to receive(:exit) @opt.version "1.0.0" @opt.parse "-v" end @@ -395,19 +395,19 @@ it "accepts a block instead of using the default block" do @opt.version("1.0.0") { |o| ScratchPad.record :version } @opt.parse "-v" - ScratchPad.recorded.should == :version + expect(ScratchPad.recorded).to eq(:version) end end -describe MSpecOptions, "#help" do +RSpec.describe MSpecOptions, "#help" do before :each do @opt = MSpecOptions.new ScratchPad.clear end it "installs a basic -h, --help option" do - @opt.should_receive(:puts) - @opt.should_receive(:exit).with(1) + expect(@opt).to receive(:puts) + expect(@opt).to receive(:exit).with(1) @opt.help @opt.parse "-h" end @@ -415,11 +415,11 @@ it "accepts a block instead of using the default block" do @opt.help { |o| ScratchPad.record :help } @opt.parse "-h" - ScratchPad.recorded.should == :help + expect(ScratchPad.recorded).to eq(:help) end end -describe MSpecOptions, "#on_extra" do +RSpec.describe MSpecOptions, "#on_extra" do before :each do @opt = MSpecOptions.new ScratchPad.clear @@ -428,18 +428,18 @@ it "registers a block to be called when an option is not recognized" do @opt.on_extra { ScratchPad.record :extra } @opt.parse "-g" - ScratchPad.recorded.should == :extra + expect(ScratchPad.recorded).to eq(:extra) end end -describe MSpecOptions, "#to_s" do +RSpec.describe MSpecOptions, "#to_s" do before :each do @opt = MSpecOptions.new "command" end it "returns the banner and descriptive strings for all registered options" do @opt.on "-t", "--this ARG", "Adds this ARG to the list" - @opt.to_s.should == <<-EOD + expect(@opt.to_s).to eq <<-EOD command -t, --this ARG Adds this ARG to the list @@ -447,13 +447,13 @@ end end -describe "The -B, --config FILE option" do +RSpec.describe "The -B, --config FILE option" do before :each do @options, @config = new_option end it "is enabled with #configure { }" do - @options.should_receive(:on).with("-B", "--config", "FILE", + expect(@options).to receive(:on).with("-B", "--config", "FILE", an_instance_of(String)) @options.configure {} end @@ -464,38 +464,38 @@ @options.configure { |x| ScratchPad.record x } @options.parse [opt, "file"] - ScratchPad.recorded.should == "file" + expect(ScratchPad.recorded).to eq("file") end end end -describe "The -C, --chdir DIR option" do +RSpec.describe "The -C, --chdir DIR option" do before :each do @options, @config = new_option @options.chdir end it "is enabled with #chdir" do - @options.should_receive(:on).with("-C", "--chdir", "DIR", + expect(@options).to receive(:on).with("-C", "--chdir", "DIR", an_instance_of(String)) @options.chdir end it "changes the working directory to DIR" do - Dir.should_receive(:chdir).with("dir").twice + expect(Dir).to receive(:chdir).with("dir").twice ["-C", "--chdir"].each do |opt| @options.parse [opt, "dir"] end end end -describe "The --prefix STR option" do +RSpec.describe "The --prefix STR option" do before :each do @options, @config = new_option end it "is enabled with #prefix" do - @options.should_receive(:on).with("--prefix", "STR", + expect(@options).to receive(:on).with("--prefix", "STR", an_instance_of(String)) @options.prefix end @@ -503,19 +503,19 @@ it "sets the prefix config value" do @options.prefix @options.parse ["--prefix", "some/dir"] - @config[:prefix].should == "some/dir" + expect(@config[:prefix]).to eq("some/dir") end end -describe "The -t, --target TARGET option" do +RSpec.describe "The -t, --target TARGET option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-t", "--target", "TARGET", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-t", "--target", "TARGET", an_instance_of(String)) @options.targets end @@ -525,7 +525,7 @@ ["r", "ruby"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "ruby" + expect(@config[:target]).to eq("ruby") end end end @@ -535,7 +535,7 @@ ["j", "jruby"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "jruby" + expect(@config[:target]).to eq("jruby") end end end @@ -545,7 +545,7 @@ ["x", "rubinius"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "./bin/rbx" + expect(@config[:target]).to eq("./bin/rbx") end end end @@ -555,7 +555,7 @@ ["X", "rbx"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "rbx" + expect(@config[:target]).to eq("rbx") end end end @@ -565,7 +565,7 @@ ["m", "maglev"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "maglev-ruby" + expect(@config[:target]).to eq("maglev-ruby") end end end @@ -575,7 +575,7 @@ ["t", "topaz"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "topaz" + expect(@config[:target]).to eq("topaz") end end end @@ -584,20 +584,20 @@ ["-t", "--target"].each do |opt| @config[:target] = nil @options.parse [opt, "whateva"] - @config[:target].should == "whateva" + expect(@config[:target]).to eq("whateva") end end end -describe "The -T, --target-opt OPT option" do +RSpec.describe "The -T, --target-opt OPT option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-T", "--target-opt", "OPT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-T", "--target-opt", "OPT", an_instance_of(String)) @options.targets end @@ -606,20 +606,20 @@ ["-T", "--target-opt"].each do |opt| @config[:flags].delete "--whateva" @options.parse [opt, "--whateva"] - @config[:flags].should include("--whateva") + expect(@config[:flags]).to include("--whateva") end end end -describe "The -I, --include DIR option" do +RSpec.describe "The -I, --include DIR option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-I", "--include", "DIR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-I", "--include", "DIR", an_instance_of(String)) @options.targets end @@ -628,20 +628,20 @@ ["-I", "--include"].each do |opt| @config[:loadpath].delete "-Ipackage" @options.parse [opt, "package"] - @config[:loadpath].should include("-Ipackage") + expect(@config[:loadpath]).to include("-Ipackage") end end end -describe "The -r, --require LIBRARY option" do +RSpec.describe "The -r, --require LIBRARY option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-r", "--require", "LIBRARY", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-r", "--require", "LIBRARY", an_instance_of(String)) @options.targets end @@ -650,20 +650,20 @@ ["-r", "--require"].each do |opt| @config[:requires].delete "-rlibrick" @options.parse [opt, "librick"] - @config[:requires].should include("-rlibrick") + expect(@config[:requires]).to include("-rlibrick") end end end -describe "The -f, --format FORMAT option" do +RSpec.describe "The -f, --format FORMAT option" do before :each do @options, @config = new_option @options.formatters end it "is enabled with #formatters" do - @options.stub(:on) - @options.should_receive(:on).with("-f", "--format", "FORMAT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-f", "--format", "FORMAT", an_instance_of(String)) @options.formatters end @@ -673,7 +673,7 @@ ["s", "specdoc"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SpecdocFormatter + expect(@config[:formatter]).to eq(SpecdocFormatter) end end end @@ -683,7 +683,7 @@ ["h", "html"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == HtmlFormatter + expect(@config[:formatter]).to eq(HtmlFormatter) end end end @@ -693,7 +693,7 @@ ["d", "dot", "dotted"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == DottedFormatter + expect(@config[:formatter]).to eq(DottedFormatter) end end end @@ -703,7 +703,7 @@ ["b", "describe"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == DescribeFormatter + expect(@config[:formatter]).to eq(DescribeFormatter) end end end @@ -713,7 +713,7 @@ ["f", "file"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == FileFormatter + expect(@config[:formatter]).to eq(FileFormatter) end end end @@ -723,7 +723,7 @@ ["u", "unit", "unitdiff"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == UnitdiffFormatter + expect(@config[:formatter]).to eq(UnitdiffFormatter) end end end @@ -733,7 +733,7 @@ ["m", "summary"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SummaryFormatter + expect(@config[:formatter]).to eq(SummaryFormatter) end end end @@ -743,7 +743,7 @@ ["a", "*", "spin"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SpinnerFormatter + expect(@config[:formatter]).to eq(SpinnerFormatter) end end end @@ -753,7 +753,7 @@ ["t", "method"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == MethodFormatter + expect(@config[:formatter]).to eq(MethodFormatter) end end end @@ -763,7 +763,7 @@ ["y", "yaml"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == YamlFormatter + expect(@config[:formatter]).to eq(YamlFormatter) end end end @@ -773,21 +773,21 @@ ["j", "junit"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == JUnitFormatter + expect(@config[:formatter]).to eq(JUnitFormatter) end end end end -describe "The -o, --output FILE option" do +RSpec.describe "The -o, --output FILE option" do before :each do @options, @config = new_option @options.formatters end it "is enabled with #formatters" do - @options.stub(:on) - @options.should_receive(:on).with("-o", "--output", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-o", "--output", "FILE", an_instance_of(String)) @options.formatters end @@ -796,20 +796,20 @@ ["-o", "--output"].each do |opt| @config[:output] = nil @options.parse [opt, "some/file"] - @config[:output].should == "some/file" + expect(@config[:output]).to eq("some/file") end end end -describe "The -e, --example STR" do +RSpec.describe "The -e, --example STR" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-e", "--example", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-e", "--example", "STR", an_instance_of(String)) @options.filters end @@ -818,20 +818,20 @@ ["-e", "--example"].each do |opt| @config[:includes] = [] @options.parse [opt, "this spec"] - @config[:includes].should include("this spec") + expect(@config[:includes]).to include("this spec") end end end -describe "The -E, --exclude STR" do +RSpec.describe "The -E, --exclude STR" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-E", "--exclude", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-E", "--exclude", "STR", an_instance_of(String)) @options.filters end @@ -840,20 +840,20 @@ ["-E", "--exclude"].each do |opt| @config[:excludes] = [] @options.parse [opt, "this spec"] - @config[:excludes].should include("this spec") + expect(@config[:excludes]).to include("this spec") end end end -describe "The -p, --pattern PATTERN" do +RSpec.describe "The -p, --pattern PATTERN" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-p", "--pattern", "PATTERN", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-p", "--pattern", "PATTERN", an_instance_of(String)) @options.filters end @@ -862,20 +862,20 @@ ["-p", "--pattern"].each do |opt| @config[:patterns] = [] @options.parse [opt, "this spec"] - @config[:patterns].should include(/this spec/) + expect(@config[:patterns]).to include(/this spec/) end end end -describe "The -P, --excl-pattern PATTERN" do +RSpec.describe "The -P, --excl-pattern PATTERN" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-P", "--excl-pattern", "PATTERN", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-P", "--excl-pattern", "PATTERN", an_instance_of(String)) @options.filters end @@ -884,20 +884,20 @@ ["-P", "--excl-pattern"].each do |opt| @config[:xpatterns] = [] @options.parse [opt, "this spec"] - @config[:xpatterns].should include(/this spec/) + expect(@config[:xpatterns]).to include(/this spec/) end end end -describe "The -g, --tag TAG" do +RSpec.describe "The -g, --tag TAG" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-g", "--tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-g", "--tag", "TAG", an_instance_of(String)) @options.filters end @@ -906,20 +906,20 @@ ["-g", "--tag"].each do |opt| @config[:tags] = [] @options.parse [opt, "this spec"] - @config[:tags].should include("this spec") + expect(@config[:tags]).to include("this spec") end end end -describe "The -G, --excl-tag TAG" do +RSpec.describe "The -G, --excl-tag TAG" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-G", "--excl-tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-G", "--excl-tag", "TAG", an_instance_of(String)) @options.filters end @@ -928,20 +928,20 @@ ["-G", "--excl-tag"].each do |opt| @config[:xtags] = [] @options.parse [opt, "this spec"] - @config[:xtags].should include("this spec") + expect(@config[:xtags]).to include("this spec") end end end -describe "The -w, --profile FILE option" do +RSpec.describe "The -w, --profile FILE option" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-w", "--profile", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-w", "--profile", "FILE", an_instance_of(String)) @options.filters end @@ -950,20 +950,20 @@ ["-w", "--profile"].each do |opt| @config[:profiles] = [] @options.parse [opt, "spec/profiles/rails.yaml"] - @config[:profiles].should include("spec/profiles/rails.yaml") + expect(@config[:profiles]).to include("spec/profiles/rails.yaml") end end end -describe "The -W, --excl-profile FILE option" do +RSpec.describe "The -W, --excl-profile FILE option" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-W", "--excl-profile", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-W", "--excl-profile", "FILE", an_instance_of(String)) @options.filters end @@ -972,93 +972,93 @@ ["-W", "--excl-profile"].each do |opt| @config[:xprofiles] = [] @options.parse [opt, "spec/profiles/rails.yaml"] - @config[:xprofiles].should include("spec/profiles/rails.yaml") + expect(@config[:xprofiles]).to include("spec/profiles/rails.yaml") end end end -describe "The -Z, --dry-run option" do +RSpec.describe "The -Z, --dry-run option" do before :each do @options, @config = new_option @options.pretend end it "is enabled with #pretend" do - @options.should_receive(:on).with("-Z", "--dry-run", an_instance_of(String)) + expect(@options).to receive(:on).with("-Z", "--dry-run", an_instance_of(String)) @options.pretend end it "registers the MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend).twice + expect(MSpec).to receive(:register_mode).with(:pretend).twice ["-Z", "--dry-run"].each do |opt| @options.parse opt end end end -describe "The --unguarded option" do +RSpec.describe "The --unguarded option" do before :each do @options, @config = new_option @options.unguarded end it "is enabled with #unguarded" do - @options.stub(:on) - @options.should_receive(:on).with("--unguarded", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--unguarded", an_instance_of(String)) @options.unguarded end it "registers the MSpec unguarded mode" do - MSpec.should_receive(:register_mode).with(:unguarded) + expect(MSpec).to receive(:register_mode).with(:unguarded) @options.parse "--unguarded" end end -describe "The --no-ruby_guard option" do +RSpec.describe "The --no-ruby_guard option" do before :each do @options, @config = new_option @options.unguarded end it "is enabled with #unguarded" do - @options.stub(:on) - @options.should_receive(:on).with("--no-ruby_bug", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--no-ruby_bug", an_instance_of(String)) @options.unguarded end it "registers the MSpec no_ruby_bug mode" do - MSpec.should_receive(:register_mode).with(:no_ruby_bug) + expect(MSpec).to receive(:register_mode).with(:no_ruby_bug) @options.parse "--no-ruby_bug" end end -describe "The -H, --random option" do +RSpec.describe "The -H, --random option" do before :each do @options, @config = new_option @options.randomize end it "is enabled with #randomize" do - @options.should_receive(:on).with("-H", "--random", an_instance_of(String)) + expect(@options).to receive(:on).with("-H", "--random", an_instance_of(String)) @options.randomize end it "registers the MSpec randomize mode" do - MSpec.should_receive(:randomize).twice + expect(MSpec).to receive(:randomize=).twice ["-H", "--random"].each do |opt| @options.parse opt end end end -describe "The -R, --repeat option" do +RSpec.describe "The -R, --repeat option" do before :each do @options, @config = new_option @options.repeat end it "is enabled with #repeat" do - @options.should_receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String)) + expect(@options).to receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String)) @options.repeat end @@ -1070,117 +1070,115 @@ MSpec.repeat do repeat_count += 1 end - repeat_count.should == 10 + expect(repeat_count).to eq(10) end end end -describe "The -V, --verbose option" do +RSpec.describe "The -V, --verbose option" do before :each do @options, @config = new_option @options.verbose end it "is enabled with #verbose" do - @options.stub(:on) - @options.should_receive(:on).with("-V", "--verbose", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-V", "--verbose", an_instance_of(String)) @options.verbose end it "registers a verbose output object with MSpec" do - MSpec.should_receive(:register).with(:start, anything()).twice - MSpec.should_receive(:register).with(:load, anything()).twice + expect(MSpec).to receive(:register).with(:start, anything()).twice + expect(MSpec).to receive(:register).with(:load, anything()).twice ["-V", "--verbose"].each do |opt| @options.parse opt end end end -describe "The -m, --marker MARKER option" do +RSpec.describe "The -m, --marker MARKER option" do before :each do @options, @config = new_option @options.verbose end it "is enabled with #verbose" do - @options.stub(:on) - @options.should_receive(:on).with("-m", "--marker", "MARKER", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-m", "--marker", "MARKER", an_instance_of(String)) @options.verbose end it "registers a marker output object with MSpec" do - MSpec.should_receive(:register).with(:load, anything()).twice + expect(MSpec).to receive(:register).with(:load, anything()).twice ["-m", "--marker"].each do |opt| @options.parse [opt, ","] end end end -describe "The --int-spec option" do +RSpec.describe "The --int-spec option" do before :each do @options, @config = new_option @options.interrupt end it "is enabled with #interrupt" do - @options.should_receive(:on).with("--int-spec", an_instance_of(String)) + expect(@options).to receive(:on).with("--int-spec", an_instance_of(String)) @options.interrupt end it "sets the abort config option to false to only abort the running spec with ^C" do @config[:abort] = true @options.parse "--int-spec" - @config[:abort].should == false + expect(@config[:abort]).to eq(false) end end -describe "The -Y, --verify option" do +RSpec.describe "The -Y, --verify option" do before :each do @options, @config = new_option @options.verify end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("-Y", "--verify", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-Y", "--verify", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :verify" do - MSpec.should_receive(:register_mode).with(:verify).twice + expect(MSpec).to receive(:register_mode).with(:verify).twice ["-Y", "--verify"].each do |m| @options.parse m end end end -describe "The -O, --report option" do +RSpec.describe "The -O, --report option" do before :each do @options, @config = new_option @options.verify end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("-O", "--report", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-O", "--report", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :report" do - MSpec.should_receive(:register_mode).with(:report).twice + expect(MSpec).to receive(:register_mode).with(:report).twice ["-O", "--report"].each do |m| @options.parse m end end end -describe "The --report-on GUARD option" do - before :all do - MSpec.stub(:register_mode) - end - +RSpec.describe "The --report-on GUARD option" do before :each do + allow(MSpec).to receive(:register_mode) + @options, @config = new_option @options.verify @@ -1192,37 +1190,37 @@ end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("--report-on", "GUARD", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--report-on", "GUARD", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :report_on" do - MSpec.should_receive(:register_mode).with(:report_on) + expect(MSpec).to receive(:register_mode).with(:report_on) @options.parse ["--report-on", "ruby_bug"] end it "converts the guard name to a symbol" do name = double("ruby_bug") - name.should_receive(:to_sym) + expect(name).to receive(:to_sym) @options.parse ["--report-on", name] end it "saves the name of the guard" do @options.parse ["--report-on", "ruby_bug"] - SpecGuard.guards.should == [:ruby_bug] + expect(SpecGuard.guards).to eq([:ruby_bug]) end end -describe "The -K, --action-tag TAG option" do +RSpec.describe "The -K, --action-tag TAG option" do before :each do @options, @config = new_option @options.action_filters end it "is enabled with #action_filters" do - @options.stub(:on) - @options.should_receive(:on).with("-K", "--action-tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-K", "--action-tag", "TAG", an_instance_of(String)) @options.action_filters end @@ -1231,20 +1229,20 @@ ["-K", "--action-tag"].each do |opt| @config[:atags] = [] @options.parse [opt, "action-tag"] - @config[:atags].should include("action-tag") + expect(@config[:atags]).to include("action-tag") end end end -describe "The -S, --action-string STR option" do +RSpec.describe "The -S, --action-string STR option" do before :each do @options, @config = new_option @options.action_filters end it "is enabled with #action_filters" do - @options.stub(:on) - @options.should_receive(:on).with("-S", "--action-string", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-S", "--action-string", "STR", an_instance_of(String)) @options.action_filters end @@ -1253,12 +1251,12 @@ ["-S", "--action-string"].each do |opt| @config[:astrings] = [] @options.parse [opt, "action-str"] - @config[:astrings].should include("action-str") + expect(@config[:astrings]).to include("action-str") end end end -describe "The -d, --debug option" do +RSpec.describe "The -d, --debug option" do before :each do @options, @config = new_option @options.debug @@ -1269,17 +1267,36 @@ end it "is enabled with #debug" do - @options.stub(:on) - @options.should_receive(:on).with("-d", "--debug", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-d", "--debug", an_instance_of(String)) @options.debug end it "sets $MSPEC_DEBUG to true" do ["-d", "--debug"].each do |opt| - $MSPEC_DEBUG.should_not be_true + expect($MSPEC_DEBUG).not_to be_truthy @options.parse opt - $MSPEC_DEBUG.should be_true + expect($MSPEC_DEBUG).to be_truthy $MSPEC_DEBUG = nil end end end + +RSpec.describe "MSpecOptions#all" do + it "includes all options" do + meth = MSpecOptions.instance_method(:all) + file, line = meth.source_location + contents = File.read(file) + lines = contents.lines + + from = line + to = from + to += 1 until /^\s*end\s*$/ =~ lines[to] + calls = lines[from...to].map(&:strip) + + option_methods = contents.scan(/def (\w+).*\n\s*on\(/).map(&:first) + option_methods[0].sub!("configure", "configure {}") + + expect(calls).to eq(option_methods) + end +end diff --git a/ruby/spec/mspec/spec/utils/script_spec.rb b/ruby/spec/mspec/spec/utils/script_spec.rb index 3cc85fa1e..d9f6eac9a 100644 --- a/ruby/spec/mspec/spec/utils/script_spec.rb +++ b/ruby/spec/mspec/spec/utils/script_spec.rb @@ -4,40 +4,40 @@ require 'mspec/runner/filters' require 'mspec/runner/actions/filter' -describe MSpecScript, ".config" do +RSpec.describe MSpecScript, ".config" do it "returns a Hash" do - MSpecScript.config.should be_kind_of(Hash) + expect(MSpecScript.config).to be_kind_of(Hash) end end -describe MSpecScript, ".set" do +RSpec.describe MSpecScript, ".set" do it "sets the config hash key, value" do MSpecScript.set :a, 10 - MSpecScript.config[:a].should == 10 + expect(MSpecScript.config[:a]).to eq(10) end end -describe MSpecScript, ".get" do +RSpec.describe MSpecScript, ".get" do it "gets the config hash value for a key" do MSpecScript.set :a, 10 - MSpecScript.get(:a).should == 10 + expect(MSpecScript.get(:a)).to eq(10) end end -describe MSpecScript, "#config" do +RSpec.describe MSpecScript, "#config" do it "returns the MSpecScript config hash" do MSpecScript.set :b, 5 - MSpecScript.new.config[:b].should == 5 + expect(MSpecScript.new.config[:b]).to eq(5) end it "returns the MSpecScript config hash from subclasses" do class MSSClass < MSpecScript; end MSpecScript.set :b, 5 - MSSClass.new.config[:b].should == 5 + expect(MSSClass.new.config[:b]).to eq(5) end end -describe MSpecScript, "#load_default" do +RSpec.describe MSpecScript, "#load_default" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -53,7 +53,7 @@ class MSSClass < MSpecScript; end @engine = Object.const_get :RUBY_ENGINE end @script = MSpecScript.new - MSpecScript.stub(:new).and_return(@script) + allow(MSpecScript).to receive(:new).and_return(@script) end after :each do @@ -62,8 +62,8 @@ class MSSClass < MSpecScript; end end it "attempts to load 'default.mspec'" do - @script.stub(:try_load) - @script.should_receive(:try_load).with('default.mspec').and_return(true) + allow(@script).to receive(:try_load) + expect(@script).to receive(:try_load).with('default.mspec').and_return(true) @script.load_default end @@ -71,145 +71,145 @@ class MSSClass < MSpecScript; end Object.const_set :RUBY_ENGINE, "ybur" Object.const_set :RUBY_VERSION, "1.8.9" default = "ybur.1.8.mspec" - @script.should_receive(:try_load).with('default.mspec').and_return(false) - @script.should_receive(:try_load).with(default) - @script.should_receive(:try_load).with('ybur.mspec') + expect(@script).to receive(:try_load).with('default.mspec').and_return(false) + expect(@script).to receive(:try_load).with(default) + expect(@script).to receive(:try_load).with('ybur.mspec') @script.load_default end end -describe MSpecScript, ".main" do +RSpec.describe MSpecScript, ".main" do before :each do @script = double("MSpecScript").as_null_object - MSpecScript.stub(:new).and_return(@script) + allow(MSpecScript).to receive(:new).and_return(@script) # Do not require full mspec as it would conflict with RSpec - MSpecScript.should_receive(:require).with('mspec') + expect(MSpecScript).to receive(:require).with('mspec') end it "creates an instance of MSpecScript" do - MSpecScript.should_receive(:new).and_return(@script) + expect(MSpecScript).to receive(:new).and_return(@script) MSpecScript.main end it "attempts to load the default config" do - @script.should_receive(:load_default) + expect(@script).to receive(:load_default) MSpecScript.main end it "attempts to load the '~/.mspecrc' script" do - @script.should_receive(:try_load).with('~/.mspecrc') + expect(@script).to receive(:try_load).with('~/.mspecrc') MSpecScript.main end it "calls the #options method on the script" do - @script.should_receive(:options) + expect(@script).to receive(:options) MSpecScript.main end it "calls the #signals method on the script" do - @script.should_receive(:signals) + expect(@script).to receive(:signals) MSpecScript.main end it "calls the #register method on the script" do - @script.should_receive(:register) + expect(@script).to receive(:register) MSpecScript.main end it "calls the #setup_env method on the script" do - @script.should_receive(:setup_env) + expect(@script).to receive(:setup_env) MSpecScript.main end it "calls the #run method on the script" do - @script.should_receive(:run) + expect(@script).to receive(:run) MSpecScript.main end end -describe MSpecScript, "#initialize" do +RSpec.describe MSpecScript, "#initialize" do before :each do @config = MSpecScript.new.config end it "sets the default config values" do - @config[:formatter].should == nil - @config[:includes].should == [] - @config[:excludes].should == [] - @config[:patterns].should == [] - @config[:xpatterns].should == [] - @config[:tags].should == [] - @config[:xtags].should == [] - @config[:atags].should == [] - @config[:astrings].should == [] - @config[:abort].should == true - @config[:config_ext].should == '.mspec' + expect(@config[:formatter]).to eq(nil) + expect(@config[:includes]).to eq([]) + expect(@config[:excludes]).to eq([]) + expect(@config[:patterns]).to eq([]) + expect(@config[:xpatterns]).to eq([]) + expect(@config[:tags]).to eq([]) + expect(@config[:xtags]).to eq([]) + expect(@config[:atags]).to eq([]) + expect(@config[:astrings]).to eq([]) + expect(@config[:abort]).to eq(true) + expect(@config[:config_ext]).to eq('.mspec') end end -describe MSpecScript, "#load" do +RSpec.describe MSpecScript, "#load" do before :each do - File.stub(:exist?).and_return(false) + allow(File).to receive(:exist?).and_return(false) @script = MSpecScript.new @file = "default.mspec" @base = "default" end it "attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@file, ".").and_return(@file) - File.should_receive(:exist?).with(@file).and_return(true) - Kernel.should_receive(:load).with(@file).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:expand_path).with(@file, ".").and_return(@file) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(Kernel).to receive(:load).with(@file).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@base, ".").and_return(@base) - File.should_receive(:expand_path).with(@base, "spec").and_return(@base) - File.should_receive(:expand_path).with(@file, ".").and_return(@file) - File.should_receive(:exist?).with(@base).and_return(false) - File.should_receive(:exist?).with(@file).and_return(true) - Kernel.should_receive(:load).with(@file).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:expand_path).with(@base, ".").and_return(@base) + expect(File).to receive(:expand_path).with(@base, "spec").and_return(@base) + expect(File).to receive(:expand_path).with(@file, ".").and_return(@file) + expect(File).to receive(:exist?).with(@base).and_return(false) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(Kernel).to receive(:load).with(@file).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "attempts to locate the file in '.'" do path = File.expand_path @file, "." - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file in '.'" do path = File.expand_path @file, "." - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "attempts to locate the file in 'spec'" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file in 'spec'" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "loads a given file only once" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).once.with(path).and_return(:loaded) - @script.load(@base).should == :loaded - @script.load(@base).should == true + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).once.with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) + expect(@script.load(@base)).to eq(true) end end -describe MSpecScript, "#custom_options" do +RSpec.describe MSpecScript, "#custom_options" do before :each do @script = MSpecScript.new end @@ -219,12 +219,12 @@ class MSSClass < MSpecScript; end it "prints 'None'" do options = double("options") - options.should_receive(:doc).with(" No custom options registered") + expect(options).to receive(:doc).with(" No custom options registered") @script.custom_options options end end -describe MSpecScript, "#register" do +RSpec.describe MSpecScript, "#register" do before :each do @script = MSpecScript.new @@ -233,8 +233,8 @@ class MSSClass < MSpecScript; end end it "creates and registers the formatter" do - @formatter.should_receive(:new).and_return(@formatter) - @formatter.should_receive(:register) + expect(@formatter).to receive(:new).and_return(@formatter) + expect(@formatter).to receive(:register) @script.register end @@ -244,24 +244,24 @@ class MSSClass < MSpecScript; end end it "calls #custom_register" do - @script.should_receive(:custom_register) + expect(@script).to receive(:custom_register) @script.register end it "registers :formatter with the formatter instance" do - @formatter.stub(:new).and_return(@formatter) - MSpec.should_receive(:store).with(:formatter, @formatter) + allow(@formatter).to receive(:new).and_return(@formatter) @script.register + expect(MSpec.formatter).to be(@formatter) end it "does not register :formatter if config[:formatter] is false" do @script.config[:formatter] = false - MSpec.should_not_receive(:store) + expect(MSpec).not_to receive(:store) @script.register end end -describe MSpecScript, "#register" do +RSpec.describe MSpecScript, "#register" do before :each do @script = MSpecScript.new @@ -269,61 +269,61 @@ class MSSClass < MSpecScript; end @script.config[:formatter] = @formatter @filter = double("filter") - @filter.should_receive(:register) + expect(@filter).to receive(:register) @ary = ["some", "spec"] end it "creates and registers a MatchFilter for include specs" do - MatchFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(MatchFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:includes] = @ary @script.register end it "creates and registers a MatchFilter for excluded specs" do - MatchFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(MatchFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:excludes] = @ary @script.register end it "creates and registers a RegexpFilter for include specs" do - RegexpFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(RegexpFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:patterns] = @ary @script.register end it "creates and registers a RegexpFilter for excluded specs" do - RegexpFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(RegexpFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xpatterns] = @ary @script.register end it "creates and registers a TagFilter for include specs" do - TagFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(TagFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:tags] = @ary @script.register end it "creates and registers a TagFilter for excluded specs" do - TagFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(TagFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xtags] = @ary @script.register end it "creates and registers a ProfileFilter for include specs" do - ProfileFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(ProfileFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:profiles] = @ary @script.register end it "creates and registers a ProfileFilter for excluded specs" do - ProfileFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(ProfileFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xprofiles] = @ary @script.register end end -describe MSpecScript, "#signals" do +RSpec.describe MSpecScript, "#signals" do before :each do @script = MSpecScript.new @abort = @script.config[:abort] @@ -334,42 +334,42 @@ class MSSClass < MSpecScript; end end it "traps the INT signal if config[:abort] is true" do - Signal.should_receive(:trap).with("INT") + expect(Signal).to receive(:trap).with("INT") @script.config[:abort] = true @script.signals end it "does not trap the INT signal if config[:abort] is not true" do - Signal.should_not_receive(:trap).with("INT") + expect(Signal).not_to receive(:trap).with("INT") @script.config[:abort] = false @script.signals end end -describe MSpecScript, "#entries" do +RSpec.describe MSpecScript, "#entries" do before :each do @script = MSpecScript.new - File.stub(:realpath).and_return("name") - File.stub(:file?).and_return(false) - File.stub(:directory?).and_return(false) + allow(File).to receive(:realpath).and_return("name") + allow(File).to receive(:file?).and_return(false) + allow(File).to receive(:directory?).and_return(false) end it "returns the pattern in an array if it is a file" do - File.should_receive(:realpath).with("file").and_return("file/expanded.rb") - File.should_receive(:file?).with("file/expanded.rb").and_return(true) - @script.entries("file").should == ["file/expanded.rb"] + expect(File).to receive(:realpath).with("file").and_return("file/expanded.rb") + expect(File).to receive(:file?).with("file/expanded.rb").and_return(true) + expect(@script.entries("file")).to eq(["file/expanded.rb"]) end it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do - File.should_receive(:directory?).with("name").and_return(true) - File.stub(:realpath).and_return("name", "name/**/*_spec.rb") - Dir.should_receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"]) - @script.entries("name").should == ["dir1", "dir2"] + expect(File).to receive(:directory?).with("name").and_return(true) + allow(File).to receive(:realpath).and_return("name", "name/**/*_spec.rb") + expect(Dir).to receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"]) + expect(@script.entries("name")).to eq(["dir1", "dir2"]) end it "aborts if pattern cannot be resolved to a file nor a directory" do - @script.should_receive(:abort) + expect(@script).to receive(:abort) @script.entries("pattern") end @@ -382,47 +382,47 @@ class MSSClass < MSpecScript; end it "returns the pattern in an array if it is a file" do name = "#{@name}.rb" - File.should_receive(:realpath).with(name).and_return(name) - File.should_receive(:file?).with(name).and_return(true) - @script.entries("name.rb").should == [name] + expect(File).to receive(:realpath).with(name).and_return(name) + expect(File).to receive(:file?).with(name).and_return(true) + expect(@script.entries("name.rb")).to eq([name]) end it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do - File.stub(:realpath).and_return(@name, @name+"/**/*_spec.rb") - File.should_receive(:directory?).with(@name).and_return(true) - Dir.should_receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"]) - @script.entries("name").should == ["dir1", "dir2"] + allow(File).to receive(:realpath).and_return(@name, @name+"/**/*_spec.rb") + expect(File).to receive(:directory?).with(@name).and_return(true) + expect(Dir).to receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"]) + expect(@script.entries("name")).to eq(["dir1", "dir2"]) end it "aborts if pattern cannot be resolved to a file nor a directory" do - @script.should_receive(:abort) + expect(@script).to receive(:abort) @script.entries("pattern") end end end -describe MSpecScript, "#files" do +RSpec.describe MSpecScript, "#files" do before :each do @script = MSpecScript.new end it "accumulates the values returned by #entries" do - @script.should_receive(:entries).and_return(["file1"], ["file2"]) - @script.files(["a", "b"]).should == ["file1", "file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file2"]) + expect(@script.files(["a", "b"])).to eq(["file1", "file2"]) end it "strips a leading '^' and removes the values returned by #entries" do - @script.should_receive(:entries).and_return(["file1"], ["file2"], ["file1"]) - @script.files(["a", "b", "^a"]).should == ["file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file2"], ["file1"]) + expect(@script.files(["a", "b", "^a"])).to eq(["file2"]) end it "processes the array elements in order" do - @script.should_receive(:entries).and_return(["file1"], ["file1"], ["file2"]) - @script.files(["^a", "a", "b"]).should == ["file1", "file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file1"], ["file2"]) + expect(@script.files(["^a", "a", "b"])).to eq(["file1", "file2"]) end end -describe MSpecScript, "#files" do +RSpec.describe MSpecScript, "#files" do before :each do MSpecScript.set :files, ["file1", "file2"] @@ -434,21 +434,21 @@ class MSSClass < MSpecScript; end end it "looks up items with leading ':' in the config object" do - @script.should_receive(:entries).and_return(["file1"], ["file2"]) - @script.files([":files"]).should == ["file1", "file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file2"]) + expect(@script.files([":files"])).to eq(["file1", "file2"]) end it "aborts if the config key is not set" do - @script.should_receive(:abort).with("Key :all_files not found in mspec config.") + expect(@script).to receive(:abort).with("Key :all_files not found in mspec config.") @script.files([":all_files"]) end end -describe MSpecScript, "#setup_env" do +RSpec.describe MSpecScript, "#setup_env" do before :each do @script = MSpecScript.new @options, @config = new_option - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end after :each do @@ -457,19 +457,19 @@ class MSSClass < MSpecScript; end it "sets MSPEC_RUNNER = '1' in the environment" do ENV["MSPEC_RUNNER"] = "0" @script.setup_env - ENV["MSPEC_RUNNER"].should == "1" + expect(ENV["MSPEC_RUNNER"]).to eq("1") end it "sets RUBY_EXE = config[:target] in the environment" do ENV["RUBY_EXE"] = nil @script.setup_env - ENV["RUBY_EXE"].should == @config[:target] + expect(ENV["RUBY_EXE"]).to eq(@config[:target]) end it "sets RUBY_FLAGS = config[:flags] in the environment" do ENV["RUBY_FLAGS"] = nil @config[:flags] = ["-w", "-Q"] @script.setup_env - ENV["RUBY_FLAGS"].should == "-w -Q" + expect(ENV["RUBY_FLAGS"]).to eq("-w -Q") end end diff --git a/ruby/spec/mspec/spec/utils/version_spec.rb b/ruby/spec/mspec/spec/utils/version_spec.rb index 0b2d383c6..ec367d2a1 100644 --- a/ruby/spec/mspec/spec/utils/version_spec.rb +++ b/ruby/spec/mspec/spec/utils/version_spec.rb @@ -1,45 +1,45 @@ require 'spec_helper' require 'mspec/utils/version' -describe SpecVersion, "#to_s" do +RSpec.describe SpecVersion, "#to_s" do it "returns the string with which it was initialized" do - SpecVersion.new("1.8").to_s.should == "1.8" - SpecVersion.new("2.118.9").to_s.should == "2.118.9" + expect(SpecVersion.new("1.8").to_s).to eq("1.8") + expect(SpecVersion.new("2.118.9").to_s).to eq("2.118.9") end end -describe SpecVersion, "#to_str" do +RSpec.describe SpecVersion, "#to_str" do it "returns the same string as #to_s" do version = SpecVersion.new("2.118.9") - version.to_str.should == version.to_s + expect(version.to_str).to eq(version.to_s) end end -describe SpecVersion, "#to_i with ceil = false" do +RSpec.describe SpecVersion, "#to_i with ceil = false" do it "returns an integer representation of the version string" do - SpecVersion.new("2.23.10").to_i.should == 1022310 + expect(SpecVersion.new("2.23.10").to_i).to eq(1022310) end it "replaces missing version parts with zeros" do - SpecVersion.new("1.8").to_i.should == 1010800 - SpecVersion.new("1.8.6").to_i.should == 1010806 + expect(SpecVersion.new("1.8").to_i).to eq(1010800) + expect(SpecVersion.new("1.8.6").to_i).to eq(1010806) end end -describe SpecVersion, "#to_i with ceil = true" do +RSpec.describe SpecVersion, "#to_i with ceil = true" do it "returns an integer representation of the version string" do - SpecVersion.new("1.8.6", true).to_i.should == 1010806 + expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806) end it "fills in 9s for missing tiny values" do - SpecVersion.new("1.8", true).to_i.should == 1010899 - SpecVersion.new("1.8.6", true).to_i.should == 1010806 + expect(SpecVersion.new("1.8", true).to_i).to eq(1010899) + expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806) end end -describe SpecVersion, "#to_int" do +RSpec.describe SpecVersion, "#to_int" do it "returns the same value as #to_i" do version = SpecVersion.new("4.16.87") - version.to_int.should == version.to_i + expect(version.to_int).to eq(version.to_i) end end diff --git a/ruby/spec/mspec/tool/remove_old_guards.rb b/ruby/spec/mspec/tool/remove_old_guards.rb index d6ed619d9..718e351e1 100644 --- a/ruby/spec/mspec/tool/remove_old_guards.rb +++ b/ruby/spec/mspec/tool/remove_old_guards.rb @@ -57,9 +57,10 @@ def search(regexp) end version = Regexp.escape(ARGV.fetch(0)) -remove_guards(/ruby_version_is ["']#{version}["'] do/, true) -remove_guards(/ruby_version_is ["'][0-9.]*["']...["']#{version}["'] do/, false) -remove_guards(/ruby_bug "#\d+", ["'][0-9.]*["']...["']#{version}["'] do/, true) +version += "(?:\\.0)?" if version.count(".") < 2 +remove_guards(/ruby_version_is (["'])#{version}\1 do/, true) +remove_guards(/ruby_version_is (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, false) +remove_guards(/ruby_bug "#\d+", (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, true) -search(/["']#{version}["']/) +search(/(["'])#{version}\1/) search(/^\s*#.+#{version}/) diff --git a/ruby/spec/mspec/tool/sync/sync-rubyspec.rb b/ruby/spec/mspec/tool/sync/sync-rubyspec.rb index 48047e013..b4c79d2af 100644 --- a/ruby/spec/mspec/tool/sync/sync-rubyspec.rb +++ b/ruby/spec/mspec/tool/sync/sync-rubyspec.rb @@ -1,3 +1,6 @@ +# This script is based on commands from the wiki: +# https://github.com/ruby/spec/wiki/Merging-specs-from-JRuby-and-other-sources + IMPLS = { truffleruby: { git: "https://github.com/oracle/truffleruby.git", @@ -12,14 +15,13 @@ }, mri: { git: "https://github.com/ruby/ruby.git", - master: "trunk", }, } MSPEC = ARGV.delete('--mspec') CHECK_LAST_MERGE = ENV['CHECK_LAST_MERGE'] != 'false' -TEST_TRUNK = ENV['TEST_TRUNK'] != 'false' +TEST_MASTER = ENV['TEST_MASTER'] != 'false' MSPEC_REPO = File.expand_path("../../..", __FILE__) raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git") @@ -36,6 +38,9 @@ BRIGHT_YELLOW = "\e[33;1m" RESET = "\e[0m" +# git filter-branch --subdirectory-filter works fine for our use case +ENV['FILTER_BRANCH_SQUELCH_WARNING'] = '1' + class RubyImplementation attr_reader :name @@ -48,14 +53,14 @@ def git_url @data[:git] end - def default_branch - @data[:master] || "master" - end - def repo_name File.basename(git_url, ".git") end + def repo_path + "#{__dir__}/#{repo_name}" + end + def repo_org File.basename(File.dirname(git_url)) end @@ -99,7 +104,7 @@ def update_repo(impl) Dir.chdir(impl.repo_name) do puts Dir.pwd - sh "git", "checkout", impl.default_branch + sh "git", "checkout", "master" sh "git", "pull" end end @@ -140,7 +145,7 @@ def rebase_commits(impl) else last_merge = `git log --grep='^#{impl.last_merge_message}' -n 1 --format='%H %ct'` end - last_merge, commit_timestamp = last_merge.chomp.split(' ') + last_merge, commit_timestamp = last_merge.split(' ') raise "Could not find last merge" unless last_merge puts "Last merge is #{last_merge}" @@ -151,6 +156,11 @@ def rebase_commits(impl) raise "#{days_since_last_merge.floor} days since last merge, probably wrong commit" end + puts "Checking if the last merge is consistent with upstream files" + rubyspec_commit = `git log -n 1 --format='%s' #{last_merge}`.chomp.split('@', 2)[-1] + sh "git", "checkout", last_merge + sh "git", "diff", "--exit-code", rubyspec_commit, "--", ":!.github" + puts "Rebasing..." sh "git", "branch", "-D", rebased if branch?(rebased) sh "git", "checkout", "-b", rebased, impl.name @@ -159,14 +169,23 @@ def rebase_commits(impl) end end +def new_commits?(impl) + Dir.chdir(SOURCE_REPO) do + diff = `git diff master #{impl.rebased_branch}` + !diff.empty? + end +end + def test_new_specs require "yaml" Dir.chdir(SOURCE_REPO) do - versions = YAML.load_file("#{MSPEC_REPO}/.travis.yml").fetch("rvm") + workflow = YAML.load_file(".github/workflows/ci.yml") + job_name = MSPEC ? "test" : "specs" + versions = workflow.dig("jobs", job_name, "strategy", "matrix", "ruby") versions = versions.grep(/^\d+\./) # Test on MRI min_version, max_version = versions.minmax - test_command = MSPEC ? "bundle exec rspec" : "../mspec/bin/mspec -j" + test_command = MSPEC ? "bundle install && bundle exec rspec" : "../mspec/bin/mspec -j" run_test = -> version { command = "chruby #{version} && #{test_command}" @@ -175,7 +194,7 @@ def test_new_specs run_test[min_version] run_test[max_version] - run_test["trunk"] if TEST_TRUNK + run_test["ruby-master"] if TEST_MASTER end end @@ -192,8 +211,8 @@ def verify_commits(impl) def fast_forward_master(impl) Dir.chdir(SOURCE_REPO) do sh "git", "checkout", "master" - sh "git", "merge", "--ff-only", "#{impl.name}-rebased" - sh "git", "branch", "--delete", "#{impl.name}-rebased" + sh "git", "merge", "--ff-only", impl.rebased_branch + sh "git", "branch", "--delete", impl.rebased_branch end end @@ -212,10 +231,15 @@ def main(impls) update_repo(impl) filter_commits(impl) rebase_commits(impl) - test_new_specs - verify_commits(impl) - fast_forward_master(impl) - check_ci + if new_commits?(impl) + test_new_specs + verify_commits(impl) + fast_forward_master(impl) + check_ci + else + STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}" + fast_forward_master(impl) + end end end diff --git a/ruby/spec/mspec/tool/tag_from_output.rb b/ruby/spec/mspec/tool/tag_from_output.rb index 43fc4808b..ebe13434c 100755 --- a/ruby/spec/mspec/tool/tag_from_output.rb +++ b/ruby/spec/mspec/tool/tag_from_output.rb @@ -15,9 +15,10 @@ ERROR_OR_FAILED = / (ERROR|FAILED)$/ SPEC_FILE = /^(\/.+_spec\.rb)\:\d+/ -output.slice_before(NUMBER).select { |number, error_line, *rest| - number =~ NUMBER and error_line =~ ERROR_OR_FAILED -}.each { |number, error_line, *rest| +output.slice_before(NUMBER).select { |number, *rest| + number =~ NUMBER and rest.any? { |line| line =~ ERROR_OR_FAILED } +}.each { |number, *rest| + error_line = rest.find { |line| line =~ ERROR_OR_FAILED } description = error_line.match(ERROR_OR_FAILED).pre_match spec_file = rest.find { |line| line =~ SPEC_FILE } @@ -26,10 +27,11 @@ next end spec_file = spec_file[SPEC_FILE, 1] - prefix = spec_file.index('spec/ruby') + prefix = spec_file.index('spec/ruby/') || spec_file.index('spec/truffle/') spec_file = spec_file[prefix..-1] - tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub(/_spec\.rb$/, '_tags.txt') + tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub('spec/truffle/', "#{tags_dir}/truffle/") + tags_file = tags_file.sub(/_spec\.rb$/, '_tags.txt') dir = File.dirname(tags_file) Dir.mkdir(dir) unless Dir.exist?(dir) @@ -37,6 +39,7 @@ tag_line = "fails:#{description}" lines = File.exist?(tags_file) ? File.readlines(tags_file, chomp: true) : [] unless lines.include?(tag_line) + puts tags_file File.write(tags_file, (lines + [tag_line]).join("\n") + "\n") end } diff --git a/ruby/spec/mspec/tool/wrap_with_guard.rb b/ruby/spec/mspec/tool/wrap_with_guard.rb new file mode 100755 index 000000000..5b1bf4d7f --- /dev/null +++ b/ruby/spec/mspec/tool/wrap_with_guard.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +# Wrap the passed the files with a guard (e.g., `ruby_version_is ""..."3.0"`). +# Notably if some methods are removed, this is a convenient way to skip such file from a given version. +# Example usage: +# $ spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.0"' spec/ruby/library/set/sortedset/**/*_spec.rb + +guard, *files = ARGV +abort "Usage: #{$0} GUARD FILES..." if files.empty? + +files.each do |file| + contents = File.binread(file) + lines = contents.lines.to_a + + lines = lines.map { |line| line.chomp.empty? ? line : " #{line}" } + + version_line = "#{guard} do\n" + if lines[0] =~ /^\s*require.+spec_helper/ + lines[0] = lines[0].sub(/^ /, '') + lines.insert 1, "\n", version_line + else + warn "Could not find 'require spec_helper' line in #{file}" + lines.insert 0, version_line + end + + lines << "end\n" + + File.binwrite file, lines.join +end diff --git a/ruby/spec/ruby/.mspec.constants b/ruby/spec/ruby/.mspec.constants index e88e58989..6b70274c5 100644 --- a/ruby/spec/ruby/.mspec.constants +++ b/ruby/spec/ruby/.mspec.constants @@ -41,6 +41,7 @@ ComparisonTest ConstantSpecsIncludedModule ConstantVisibility Coverage +CoverageSpecs CustomArgumentError DRb DRbIdConv @@ -55,6 +56,7 @@ DefSpecsLambdaVisibility DefineMethodByProcClass DefineMethodSpecClass DefineSingletonMethodSpecClass +Delegator DescArray DescObjectTest Digest @@ -148,8 +150,10 @@ Readline ReceiverClass RegexpSpecsSubclass RegexpSpecsSubclassTwo +Reline RescueInClassExample Resolv +Ripper SHA1Constants SHA256Constants SHA384Constants @@ -161,6 +165,7 @@ SecondClass SecureRandom Set Shellwords +SimpleDelegator SingleForwardable Singleton Socket @@ -188,6 +193,7 @@ TimeoutError UDPSocket UNIXServer UNIXSocket +URI UnaryMinusTest UnicodeNormalize UnloadableDumpableDir diff --git a/ruby/spec/ruby/.rubocop.yml b/ruby/spec/ruby/.rubocop.yml index 77e4e78e7..eab4c3c4a 100644 --- a/ruby/spec/ruby/.rubocop.yml +++ b/ruby/spec/ruby/.rubocop.yml @@ -1,7 +1,7 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 2.4 + TargetRubyVersion: 2.6 DisplayCopNames: true Exclude: - command_line/fixtures/bad_syntax.rb @@ -10,11 +10,15 @@ AllCops: Layout/TrailingWhitespace: Enabled: true -Layout/TrailingBlankLines: +Layout/TrailingEmptyLines: Enabled: true Exclude: - library/coverage/fixtures/some_class.rb +Layout/SpaceInLambdaLiteral: + Enabled: true + EnforcedStyle: require_space + Lint: Enabled: true @@ -34,10 +38,10 @@ Lint/InterpolationCheck: Lint/LiteralAsCondition: Enabled: false -Lint/UnneededRequireStatement: +Lint/RedundantRequireStatement: Enabled: false -Lint/UnneededSplatExpansion: +Lint/RedundantSplatExpansion: Enabled: false Lint/UnifiedInteger: @@ -88,8 +92,10 @@ Lint/UnreachableCode: Exclude: - 'core/enumerator/lazy/fixtures/classes.rb' - 'core/kernel/catch_spec.rb' + - 'core/kernel/raise_spec.rb' - 'core/kernel/throw_spec.rb' - 'language/break_spec.rb' + - 'language/optional_assignments_spec.rb' - 'language/fixtures/break.rb' - 'language/fixtures/break_lambda_toplevel.rb' - 'language/fixtures/break_lambda_toplevel_block.rb' @@ -108,12 +114,16 @@ Lint/Debugger: Exclude: - 'core/binding/fixtures/irb.rb' +Lint/Loop: + Enabled: false + Style/Lambda: Enabled: true EnforcedStyle: literal Exclude: - 'language/lambda_spec.rb' - 'language/proc_spec.rb' + - 'language/numbered_parameters_spec.rb' - 'core/kernel/lambda_spec.rb' Style/EmptyLambdaParameter: diff --git a/ruby/spec/ruby/.rubocop_todo.yml b/ruby/spec/ruby/.rubocop_todo.yml index aac54f62a..a46921384 100644 --- a/ruby/spec/ruby/.rubocop_todo.yml +++ b/ruby/spec/ruby/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2018-04-03 22:23:59 +0900 using RuboCop version 0.54.0. +# on 2019-12-12 22:16:26 +0900 using RuboCop version 0.77.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -20,22 +20,24 @@ Lint/DuplicateMethods: - 'core/unboundmethod/fixtures/classes.rb' - 'fixtures/class.rb' -# Offense count: 5 +# Offense count: 8 Lint/EnsureReturn: Exclude: - 'language/fixtures/ensure.rb' - 'language/fixtures/return.rb' - 'language/return_spec.rb' +# Offense count: 10 +Lint/FlipFlop: + Exclude: + - 'language/if_spec.rb' + - 'language/precedence_spec.rb' + # Offense count: 10 Lint/FloatOutOfRange: Exclude: - 'core/string/modulo_spec.rb' -# Offense count: 29 -Lint/HandleExceptions: - Enabled: false - # Offense count: 2 Lint/ImplicitStringConcatenation: Exclude: @@ -57,28 +59,30 @@ Lint/InheritException: - 'core/enumerator/lazy/fixtures/classes.rb' - 'core/exception/fixtures/common.rb' - 'core/module/fixtures/autoload_ex1.rb' + - 'shared/kernel/raise.rb' -# Offense count: 5 +# Offense count: 72 # Cop supports --auto-correct. Lint/LiteralInInterpolation: Exclude: - 'core/module/refine_spec.rb' + - 'core/regexp/shared/new.rb' + - 'core/string/shared/to_sym.rb' + - 'language/alias_spec.rb' - 'language/defined_spec.rb' - 'language/fixtures/squiggly_heredoc.rb' - -# Offense count: 16 -Lint/Loop: - Exclude: - - 'language/until_spec.rb' - - 'language/while_spec.rb' + - 'language/string_spec.rb' + - 'language/symbol_spec.rb' + - 'language/undef_spec.rb' + - 'library/net/ftp/connect_spec.rb' # Offense count: 8 # Cop supports --auto-correct. -Lint/MultipleCompare: +Lint/MultipleComparison: Exclude: - 'language/precedence_spec.rb' -# Offense count: 12 +# Offense count: 9 Lint/ParenthesesAsGroupedExpression: Exclude: - 'core/string/fixtures/freeze_magic_comment.rb' @@ -86,13 +90,19 @@ Lint/ParenthesesAsGroupedExpression: - 'language/fixtures/send.rb' - 'language/method_spec.rb' +# Offense count: 2 +# Cop supports --auto-correct. +Lint/RedundantStringCoercion: + Exclude: + - 'core/io/print_spec.rb' + # Offense count: 1 # Cop supports --auto-correct. Lint/RedundantWithIndex: Exclude: - 'core/enumerator/with_index_spec.rb' -# Offense count: 26 +# Offense count: 22 Lint/RescueException: Exclude: - 'command_line/fixtures/debug_info.rb' @@ -100,29 +110,27 @@ Lint/RescueException: - 'core/exception/cause_spec.rb' - 'core/exception/no_method_error_spec.rb' - 'core/kernel/fixtures/autoload_frozen.rb' + - 'core/kernel/raise_spec.rb' - 'core/module/autoload_spec.rb' - 'core/mutex/sleep_spec.rb' - - 'core/process/euid_spec.rb' - - 'core/process/setsid_spec.rb' - - 'core/process/uid_spec.rb' - 'core/thread/abort_on_exception_spec.rb' - 'core/thread/shared/exit.rb' - 'language/rescue_spec.rb' - 'library/erb/filename_spec.rb' -# Offense count: 2 +# Offense count: 4 # Configuration parameters: IgnoreImplicitReferences. Lint/ShadowedArgument: Exclude: - 'language/fixtures/super.rb' -# Offense count: 2 -# Cop supports --auto-correct. -Lint/StringConversionInInterpolation: - Exclude: - - 'core/io/print_spec.rb' +# Offense count: 39 +# Configuration parameters: AllowComments. +Lint/SuppressedException: + Enabled: false # Offense count: 9 +# Configuration parameters: AllowKeywordBlockArguments. Lint/UnderscorePrefixedVariableName: Exclude: - 'core/io/pipe_spec.rb' @@ -137,13 +145,4 @@ Lint/UselessAccessModifier: - 'core/module/fixtures/classes.rb' - 'core/module/module_function_spec.rb' - 'core/module/private_class_method_spec.rb' - - 'core/module/private_spec.rb' - - 'core/module/protected_spec.rb' - - 'core/module/public_spec.rb' - 'language/fixtures/send.rb' - -# Offense count: 6186 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. -# URISchemes: http, https -Metrics/LineLength: - Max: 588 diff --git a/ruby/spec/ruby/CONTRIBUTING.md b/ruby/spec/ruby/CONTRIBUTING.md index 1ec6f0ff4..30941677e 100644 --- a/ruby/spec/ruby/CONTRIBUTING.md +++ b/ruby/spec/ruby/CONTRIBUTING.md @@ -8,7 +8,7 @@ Spec are grouped in 5 separate top-level groups: * `command_line`: for the ruby executable command-line flags (`-v`, `-e`, etc) * `language`: for the language keywords and syntax constructs (`if`, `def`, `A::B`, etc) -* `core`: for the core methods (`Fixnum#+`, `String#upcase`, no need to require anything) +* `core`: for the core methods (`Integer#+`, `String#upcase`, no need to require anything) * `library`: for the standard libraries methods (`CSV.new`, `YAML.parse`, need to require the stdlib) * `optional/capi`: for functions available to the Ruby C-extension API @@ -53,12 +53,14 @@ which indicates the file was generated but the method unspecified. Here is a list of frequently-used matchers, which should be enough for most specs. There are a few extra specific matchers used in the couple specs that need it. +#### Comparison matchers + ```ruby (1 + 2).should == 3 # Calls #== (1 + 2).should_not == 5 -File.should equal(File) # Calls #equal? (tests identity) -(1 + 2).should eql(3) # Calls #eql? (Hash equality) +File.should.equal?(File) # Calls #equal? (tests identity) +(1 + 2).should.eql?(3) # Calls #eql? (Hash equality) 1.should < 2 2.should <= 2 @@ -66,12 +68,19 @@ File.should equal(File) # Calls #equal? (tests identity) 4.should > 3 "Hello".should =~ /l{2}/ # Calls #=~ (Regexp match) +``` + +#### Predicate matchers + +```ruby +[].should.empty? +[1,2,3].should.include?(2) -[].should be_empty # Calls #empty? -[1,2,3].should include(2) # Calls #include? +"hello".should.start_with?("h") +"hello".should.end_with?("o") (0.1 + 0.2).should be_close(0.3, TOLERANCE) # (0.2-0.1).abs < TOLERANCE -(0.0/0.0).should be_nan # Calls Float#nan? +(0.0/0.0).should.nan? (1.0/0.0).should be_positive_infinity (-1.0/0.0).should be_negative_infinity @@ -79,11 +88,16 @@ File.should equal(File) # Calls #equal? (tests identity) 3.14.should be_kind_of(Numeric) # Calls #is_a? Numeric.should be_ancestor_of(Float) # Float.ancestors.include?(Numeric) -3.14.should respond_to(:to_i) # Calls #respond_to? -Fixnum.should have_instance_method(:+) +3.14.should.respond_to?(:to_i) +Integer.should have_instance_method(:+) Array.should have_method(:new) -# Also have_constant, have_private_instance_method, have_singleton_method, etc +``` + +Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, etc. + +#### Exception matchers +```ruby -> { raise "oops" }.should raise_error(RuntimeError, /oops/) @@ -92,14 +106,23 @@ Array.should have_method(:new) raise "oops" }.should raise_error(RuntimeError) { |e| # Custom checks on the Exception object - e.message.should include("oops") + e.message.should.include?("oops") e.cause.should == nil } +``` + +##### should_not raise_error + +**To avoid!** Instead, use an expectation testing what the code in the lambda does. +If an exception is raised, it will fail the example anyway. -# To avoid! Instead, use an expectation testing what the code in the lambda does. -# If an exception is raised, it will fail the example anyway. +```ruby -> { ... }.should_not raise_error +``` + +#### Warning matcher +```ruby -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/) # Expect a warning @@ -110,15 +133,21 @@ Array.should have_method(:new) Different guards are available as defined by mspec. Here is a list of the most commonly-used guards: +#### Version guards + ```ruby -ruby_version_is ""..."2.4" do - # Specs for RUBY_VERSION < 2.4 +ruby_version_is ""..."2.6" do + # Specs for RUBY_VERSION < 2.6 end -ruby_version_is "2.4" do - # Specs for RUBY_VERSION >= 2.4 +ruby_version_is "2.6" do + # Specs for RUBY_VERSION >= 2.6 end +``` + +#### Platform guards +```ruby platform_is :windows do # Specs only valid on Windows end @@ -140,27 +169,37 @@ end big_endian do # Big-endian platform end +``` + +#### Guard for bug + +In case there is a bug in MRI but the expected behavior is obvious. +First, file a bug at https://bugs.ruby-lang.org/. +It is better to use a `ruby_version_is` guard if there was a release with the fix. -# In case there is a bug in MRI but the expected behavior is obvious -# First file a bug at https://bugs.ruby-lang.org/ -# It is better to use a ruby_version_is guard if there was a release with the fix -ruby_bug '#13669', ''...'2.5' do +```ruby +ruby_bug '#13669', ''...'2.7' do it "works like this" do # Specify the expected behavior here, not the bug end end +``` +#### Combining guards -# Combining guards -guard -> { platform_is :windows and ruby_version_is ""..."2.5" } do - # Windows and RUBY_VERSION < 2.5 +```ruby +guard -> { platform_is :windows and ruby_version_is ""..."2.6" } do + # Windows and RUBY_VERSION < 2.6 end -guard_not -> { platform_is :windows and ruby_version_is ""..."2.5" } do +guard_not -> { platform_is :windows and ruby_version_is ""..."2.6" } do # The opposite end +``` -# Custom guard +#### Custom guard + +```ruby max_uint = (1 << 32) - 1 guard -> { max_uint <= fixnum_max } do end @@ -168,6 +207,8 @@ end Custom guards are better than a simple `if` as they allow [mspec commands](https://github.com/ruby/mspec/issues/30#issuecomment-312487779) to work properly. +#### Implementation-specific behaviors + In general, the usage of guards should be minimized as possible. There are no guards to define implementation-specific behavior because diff --git a/ruby/spec/ruby/README.md b/ruby/spec/ruby/README.md index 3163a7890..e62ddc7dc 100644 --- a/ruby/spec/ruby/README.md +++ b/ruby/spec/ruby/README.md @@ -1,11 +1,12 @@ # The Ruby Spec Suite -[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg?branch=master)](https://github.com/ruby/spec/actions) -[![Windows Actions Build Status](https://github.com/ruby/spec/workflows/Windows/badge.svg?branch=master)](https://github.com/ruby/spec/actions) +[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg)](https://github.com/ruby/spec/actions) [![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec) The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language. +### Description and Motivation + It is not a standardized specification like the ISO one, and does not aim to become one. Instead, it is a practical tool to describe and test the behavior of Ruby with code. @@ -27,17 +28,21 @@ ruby/spec is known to be tested in these implementations for every commit: * [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x * [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby) * [Opal](https://github.com/opal/opal/tree/master/spec) +* [Artichoke](https://github.com/artichoke/spec/tree/artichoke-vendor) + +ruby/spec describes the behavior of Ruby 2.6 and more recent Ruby versions. +More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.6.x, 2.7.x, 3.0.x, etc), and those are tested in CI. -ruby/spec describes the behavior of Ruby 2.4 and more recent Ruby versions. -More precisely, every latest stable MRI release should [pass](https://travis-ci.org/ruby/spec) all specs of ruby/spec (2.4.x, 2.5.x, 2.6.x, etc), and those are tested in TravisCI. +### Synchronization with Ruby Implementations -The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby. +The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby, +using [this script](https://github.com/ruby/mspec/blob/master/tool/sync/sync-rubyspec.rb). Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs. Any of these repositories can be used to add or edit specs, use what is most convenient for you. -For *testing* a Ruby implementation, one should always test against the implementation's copy of the specs under `spec/ruby`, as that's what the Ruby implementation tests against in their CI. +For *testing* the development version of a Ruby implementation, one should always test against that implementation's copy of the specs under `spec/ruby`, as that's what the Ruby implementation tests against in their CI. Also, this repository doesn't always contain the latest spec changes from MRI (it's synchronized monthly), and does not contain tags (specs marked as failing on that Ruby implementation). -Running specs in a Ruby implementation can be done with: +Running specs on a Ruby implementation can be done with: ``` $ cd ruby_implementation/spec/ruby @@ -45,11 +50,15 @@ $ cd ruby_implementation/spec/ruby $ ../mspec/bin/mspec ``` +### Specs for old Ruby versions + For older specs try these commits: * Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures) * Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed) * Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3) * Ruby 2.3.8 - [Suite](https://github.com/ruby/spec/commit/dc733114d8ae66a3368ba3a98422c50147a76ba5) using [MSpec](https://github.com/ruby/mspec/commit/4599bc195fb109f2a482a01c32a7d659518369ea) +* Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2) +* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041) ### Running the specs @@ -120,6 +129,16 @@ MSpec can automatically add new top-level constants in this file with: See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) for documentation about contributing and writing specs (guards, matchers, etc). +### Dependencies + +These command-line executables are needed to run the specs. + +* `echo` +* `stat` for `core/file/*time_spec.rb` +* `find` for `core/file/fixtures/file_types.rb` (package `findutils`, not needed on Windows) + +The file `/etc/services` is required for socket specs (package `netbase` on Debian, not needed on Windows). + ### Socket specs from rubysl-socket Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket). diff --git a/ruby/spec/ruby/command_line/backtrace_limit_spec.rb b/ruby/spec/ruby/command_line/backtrace_limit_spec.rb new file mode 100644 index 000000000..56afa8efe --- /dev/null +++ b/ruby/spec/ruby/command_line/backtrace_limit_spec.rb @@ -0,0 +1,48 @@ +require_relative '../spec_helper' + +ruby_version_is "3.0" do + describe "The --backtrace-limit command line option" do + it "limits top-level backtraces to a given number of entries" do + file = fixture(__FILE__ , "backtrace.rb") + out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1) + out = out.gsub(__dir__, '') + + out.should == <<-MSG +top +/fixtures/backtrace.rb:2:in `a': oops (RuntimeError) +\tfrom /fixtures/backtrace.rb:6:in `b' +\tfrom /fixtures/backtrace.rb:10:in `c' +\t ... 2 levels... + MSG + end + + it "affects Exception#full_message" do + file = fixture(__FILE__ , "backtrace.rb") + out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1") + out = out.gsub(__dir__, '') + + out.should == <<-MSG +full_message +/fixtures/backtrace.rb:2:in `a': oops (RuntimeError) +\tfrom /fixtures/backtrace.rb:6:in `b' +\tfrom /fixtures/backtrace.rb:10:in `c' +\t ... 2 levels... + MSG + end + + it "does not affect Exception#backtrace" do + file = fixture(__FILE__ , "backtrace.rb") + out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1") + out = out.gsub(__dir__, '') + + out.should == <<-MSG +backtrace +/fixtures/backtrace.rb:2:in `a' +/fixtures/backtrace.rb:6:in `b' +/fixtures/backtrace.rb:10:in `c' +/fixtures/backtrace.rb:14:in `d' +/fixtures/backtrace.rb:29:in `
      ' + MSG + end + end +end diff --git a/ruby/spec/ruby/command_line/dash_e_spec.rb b/ruby/spec/ruby/command_line/dash_e_spec.rb index 9f600eb41..24ed34376 100644 --- a/ruby/spec/ruby/command_line/dash_e_spec.rb +++ b/ruby/spec/ruby/command_line/dash_e_spec.rb @@ -23,7 +23,7 @@ #needs to test return => LocalJumpError - describe "with -n and a Fixnum range" do + describe "with -n and an Integer range" do before :each do @script = "-ne 'print if %s' #{fixture(__FILE__, "conditional_range.txt")}" end diff --git a/ruby/spec/ruby/command_line/dash_encoding_spec.rb b/ruby/spec/ruby/command_line/dash_encoding_spec.rb index 36ce55af5..5803d328c 100644 --- a/ruby/spec/ruby/command_line/dash_encoding_spec.rb +++ b/ruby/spec/ruby/command_line/dash_encoding_spec.rb @@ -25,6 +25,12 @@ end it "does not accept a third encoding" do - ruby_exe(@test_string, options: "--disable-gems --encoding big5:#{@enc2}:utf-32le", args: "2>&1").should =~ /extra argument for --encoding: utf-32le/ + options = { + options: "--disable-gems --encoding big5:#{@enc2}:utf-32le", + args: "2>&1", + exit_status: 1 + } + + ruby_exe(@test_string, options).should =~ /extra argument for --encoding: utf-32le/ end end diff --git a/ruby/spec/ruby/command_line/dash_l_spec.rb b/ruby/spec/ruby/command_line/dash_l_spec.rb new file mode 100644 index 000000000..5c1d3cf4c --- /dev/null +++ b/ruby/spec/ruby/command_line/dash_l_spec.rb @@ -0,0 +1,31 @@ +require_relative '../spec_helper' + +describe "The -l command line option" do + before :each do + @names = fixture __FILE__, "full_names.txt" + end + + it "chomps lines with default separator" do + ruby_exe('puts $_.end_with?("\n")', options: "-n -l", escape: true, + args: " < #{@names}").should == + "false\nfalse\nfalse\n" + end + + it "chomps last line based on $/" do + ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l", escape: true, + args: " < #{@names}").should == + "alice j\nbob field\njames grey\n" + end + + it "sets $\\ to the value of $/" do + ruby_exe("puts $\\ == $/", options: "-W0 -n -l", escape: true, + args: " < #{@names}").should == + "true\ntrue\ntrue\n" + end + + it "sets $-l" do + ruby_exe("puts $-l", options: "-n -l", escape: true, + args: " < #{@names}").should == + "true\ntrue\ntrue\n" + end +end diff --git a/ruby/spec/ruby/command_line/dash_r_spec.rb b/ruby/spec/ruby/command_line/dash_r_spec.rb index b29895bd2..ea5bde5ad 100644 --- a/ruby/spec/ruby/command_line/dash_r_spec.rb +++ b/ruby/spec/ruby/command_line/dash_r_spec.rb @@ -7,7 +7,22 @@ end it "requires the specified file" do - result = ruby_exe(@script, options: "-r #{@test_file}") - result.should include(@test_file + ".rb") + out = ruby_exe(@script, options: "-r #{@test_file}") + out.should include("REQUIRED") + out.should include(@test_file + ".rb") + end + + it "requires the file before parsing the main script" do + out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), options: "-r #{@test_file}", args: "2>&1", exit_status: 1) + $?.should_not.success? + out.should include("REQUIRED") + out.should include("syntax error") + end + + it "does not require the file if the main script file does not exist" do + out = `#{ruby_exe.to_a.join(' ')} -r #{@test_file} #{fixture(__FILE__, "does_not_exist.rb")} 2>&1` + $?.should_not.success? + out.should_not.include?("REQUIRED") + out.should.include?("No such file or directory") end end diff --git a/ruby/spec/ruby/command_line/dash_upper_e_spec.rb b/ruby/spec/ruby/command_line/dash_upper_e_spec.rb index b3c6ce262..5a8396258 100644 --- a/ruby/spec/ruby/command_line/dash_upper_e_spec.rb +++ b/ruby/spec/ruby/command_line/dash_upper_e_spec.rb @@ -31,6 +31,7 @@ it "raises a RuntimeError if used with -U" do ruby_exe("p 1", options: '-Eascii:ascii -U', - args: '2>&1').should =~ /RuntimeError/ + args: '2>&1', + exit_status: 1).should =~ /RuntimeError/ end end diff --git a/ruby/spec/ruby/command_line/dash_upper_k_spec.rb b/ruby/spec/ruby/command_line/dash_upper_k_spec.rb index a060eab79..7e7153229 100644 --- a/ruby/spec/ruby/command_line/dash_upper_k_spec.rb +++ b/ruby/spec/ruby/command_line/dash_upper_k_spec.rb @@ -58,8 +58,8 @@ end it "ignores unknown codes" do - locale = Encoding.find('locale') + external = Encoding.find('external') ruby_exe(@test_string, options: '-KZ').should == - [Encoding::UTF_8.name, locale.name, nil].inspect + [Encoding::UTF_8.name, external.name, nil].inspect end end diff --git a/ruby/spec/ruby/command_line/dash_upper_s_spec.rb b/ruby/spec/ruby/command_line/dash_upper_s_spec.rb index 3a28fa2ad..17991503f 100644 --- a/ruby/spec/ruby/command_line/dash_upper_s_spec.rb +++ b/ruby/spec/ruby/command_line/dash_upper_s_spec.rb @@ -21,7 +21,7 @@ end it "runs launcher found in PATH and sets the exit status to 1 if it fails" do - result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'PATH' => @path }, args: '2>&1') + result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'PATH' => @path }, args: '2>&1', exit_status: 1) result.should =~ /\bdie\b/ $?.exitstatus.should == 1 end diff --git a/ruby/spec/ruby/command_line/dash_upper_u_spec.rb b/ruby/spec/ruby/command_line/dash_upper_u_spec.rb index 2546b5b9f..d62718b09 100644 --- a/ruby/spec/ruby/command_line/dash_upper_u_spec.rb +++ b/ruby/spec/ruby/command_line/dash_upper_u_spec.rb @@ -32,12 +32,14 @@ it "raises a RuntimeError if used with -Eext:int" do ruby_exe("p 1", options: '-U -Eascii:ascii', - args: '2>&1').should =~ /RuntimeError/ + args: '2>&1', + exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError if used with -E:int" do ruby_exe("p 1", options: '-U -E:ascii', - args: '2>&1').should =~ /RuntimeError/ + args: '2>&1', + exit_status: 1).should =~ /RuntimeError/ end end diff --git a/ruby/spec/ruby/command_line/dash_upper_w_spec.rb b/ruby/spec/ruby/command_line/dash_upper_w_spec.rb index 31bb976ad..cbb040a8d 100644 --- a/ruby/spec/ruby/command_line/dash_upper_w_spec.rb +++ b/ruby/spec/ruby/command_line/dash_upper_w_spec.rb @@ -18,3 +18,30 @@ describe "The -W command line option with 2" do it_behaves_like :command_line_verbose, "-W2" end + +# Regarding the defaults, see core/warning/element_reference_spec.rb +ruby_version_is "2.7" do + describe "The -W command line option with :deprecated" do + it "enables deprecation warnings" do + ruby_exe('p Warning[:deprecated]', options: '-W:deprecated').should == "true\n" + end + end + + describe "The -W command line option with :no-deprecated" do + it "suppresses deprecation warnings" do + ruby_exe('p Warning[:deprecated]', options: '-w -W:no-deprecated').should == "false\n" + end + end + + describe "The -W command line option with :experimental" do + it "enables experimental warnings" do + ruby_exe('p Warning[:experimental]', options: '-W:experimental').should == "true\n" + end + end + + describe "The -W command line option with :no-experimental" do + it "suppresses experimental warnings" do + ruby_exe('p Warning[:experimental]', options: '-w -W:no-experimental').should == "false\n" + end + end +end diff --git a/ruby/spec/ruby/command_line/dash_v_spec.rb b/ruby/spec/ruby/command_line/dash_v_spec.rb index 04d684fda..a4f4dcd05 100644 --- a/ruby/spec/ruby/command_line/dash_v_spec.rb +++ b/ruby/spec/ruby/command_line/dash_v_spec.rb @@ -7,6 +7,7 @@ describe "when used alone" do it "prints version and ends" do ruby_exe(nil, args: '-v').should include(RUBY_DESCRIPTION) - end + end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) || + (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?) end end diff --git a/ruby/spec/ruby/command_line/dash_w_spec.rb b/ruby/spec/ruby/command_line/dash_w_spec.rb index 1d93e0347..c262df12c 100644 --- a/ruby/spec/ruby/command_line/dash_w_spec.rb +++ b/ruby/spec/ruby/command_line/dash_w_spec.rb @@ -3,4 +3,10 @@ describe "The -w command line option" do it_behaves_like :command_line_verbose, "-w" + + ruby_version_is "2.7" do + it "enables both deprecated and experimental warnings" do + ruby_exe('p Warning[:deprecated]; p Warning[:experimental]', options: '-w').should == "true\ntrue\n" + end + end end diff --git a/ruby/spec/ruby/command_line/dash_x_spec.rb b/ruby/spec/ruby/command_line/dash_x_spec.rb index eb89db014..ae14b6107 100644 --- a/ruby/spec/ruby/command_line/dash_x_spec.rb +++ b/ruby/spec/ruby/command_line/dash_x_spec.rb @@ -9,7 +9,7 @@ it "fails when /\#!.*ruby.*/-ish line in target file is not found" do bad_embedded_ruby = fixture __FILE__, "bin/bad_embedded_ruby.txt" - result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1') + result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1', exit_status: 1) result.should include "no Ruby script found in input" end diff --git a/ruby/spec/ruby/command_line/error_message_spec.rb b/ruby/spec/ruby/command_line/error_message_spec.rb index 5fee3ead4..02150f30c 100644 --- a/ruby/spec/ruby/command_line/error_message_spec.rb +++ b/ruby/spec/ruby/command_line/error_message_spec.rb @@ -2,10 +2,10 @@ describe "The error message caused by an exception" do it "is not printed to stdout" do - out = ruby_exe("this_does_not_exist", args: "2> #{File::NULL}") - out.chomp.empty?.should == true + out = ruby_exe("this_does_not_exist", args: "2> #{File::NULL}", exit_status: 1) + out.chomp.should.empty? - out = ruby_exe("end #syntax error", args: "2> #{File::NULL}") - out.chomp.empty?.should == true + out = ruby_exe("end #syntax error", args: "2> #{File::NULL}", exit_status: 1) + out.chomp.should.empty? end end diff --git a/ruby/spec/ruby/command_line/feature_spec.rb b/ruby/spec/ruby/command_line/feature_spec.rb index 02571ee8c..1a9ea925c 100644 --- a/ruby/spec/ruby/command_line/feature_spec.rb +++ b/ruby/spec/ruby/command_line/feature_spec.rb @@ -1,6 +1,12 @@ require_relative '../spec_helper' describe "The --enable and --disable flags" do + before :all do + # Since some specs disable reading RUBYOPT, we instead pass its contents as :options for those specs + rubyopt = [ENV["RUBYOPT"]] + rubyopt << ENV["#{RUBY_ENGINE.upcase}OPT"] unless RUBY_ENGINE == 'ruby' + @rubyopt = RUBY_ENGINE == "ruby" ? "" : rubyopt.compact.join(" ") + end it "can be used with gems" do ruby_exe("p defined?(Gem)", options: "--enable=gems").chomp.should == "\"constant\"" @@ -25,9 +31,9 @@ it "can be used with rubyopt" do ruby_exe("p $VERBOSE", options: "--enable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true" - ruby_exe("p $VERBOSE", options: "--disable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" + ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" ruby_exe("p $VERBOSE", options: "--enable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true" - ruby_exe("p $VERBOSE", options: "--disable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" + ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" end it "can be used with frozen-string-literal" do @@ -37,13 +43,20 @@ ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false" end - it "can be used with all" do + platform_is_not :darwin do # frequently hangs for >60s on GitHub Actions macos-latest + it "can be used with all for enable" do + e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]" + env = {'RUBYOPT' => '-w'} + # Use a single variant here because it can be quite slow as it might enable jit, etc + ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]" + end + end + + it "can be used with all for disable" do e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]" env = {'RUBYOPT' => '-w'} - ruby_exe(e, options: "--enable=all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]" - ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]" - ruby_exe(e, options: "--disable=all", env: env).chomp.should == "[nil, nil, false, false]" - ruby_exe(e, options: "--disable-all", env: env).chomp.should == "[nil, nil, false, false]" + ruby_exe(e, options: "#{@rubyopt} --disable=all", env: env).chomp.should == "[nil, nil, false, false]" + ruby_exe(e, options: "#{@rubyopt} --disable-all", env: env).chomp.should == "[nil, nil, false, false]" end it "prints a warning for unknown features" do diff --git a/ruby/spec/ruby/command_line/fixtures/backtrace.rb b/ruby/spec/ruby/command_line/fixtures/backtrace.rb new file mode 100644 index 000000000..99acae95c --- /dev/null +++ b/ruby/spec/ruby/command_line/fixtures/backtrace.rb @@ -0,0 +1,35 @@ +def a + raise 'oops' +end + +def b + a +end + +def c + b +end + +def d + c +end + +arg = ARGV.first +$stderr.puts arg + +case arg +when 'full_message' + begin + d + rescue => exc + puts exc.full_message + end +when 'backtrace' + begin + d + rescue => exc + puts exc.backtrace + end +else + d +end diff --git a/ruby/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh b/ruby/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh index 0eede2a99..fd3249f0e 100644 --- a/ruby/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh +++ b/ruby/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash -exec somehow this file +echo 'error' && exit 1 #!ruby puts 'success' diff --git a/ruby/spec/ruby/command_line/fixtures/test_file.rb b/ruby/spec/ruby/command_line/fixtures/test_file.rb index 961e3c0b0..30a832299 100644 --- a/ruby/spec/ruby/command_line/fixtures/test_file.rb +++ b/ruby/spec/ruby/command_line/fixtures/test_file.rb @@ -1 +1 @@ -"test file" +puts "REQUIRED" diff --git a/ruby/spec/ruby/command_line/rubyopt_spec.rb b/ruby/spec/ruby/command_line/rubyopt_spec.rb index 2db42f77e..a2b817bad 100644 --- a/ruby/spec/ruby/command_line/rubyopt_spec.rb +++ b/ruby/spec/ruby/command_line/rubyopt_spec.rb @@ -59,6 +59,26 @@ ruby_exe("p $VERBOSE", escape: true).chomp.should == "true" end + ruby_version_is "2.7" do + it "suppresses deprecation warnings for '-W:no-deprecated'" do + ENV["RUBYOPT"] = '-W:no-deprecated' + result = ruby_exe('$; = ""', args: '2>&1') + result.should == "" + end + + it "suppresses experimental warnings for '-W:no-experimental'" do + ENV["RUBYOPT"] = '-W:no-experimental' + result = ruby_exe('case 0; in a; end', args: '2>&1') + result.should == "" + end + + it "suppresses deprecation and experimental warnings for '-W:no-deprecated -W:no-experimental'" do + ENV["RUBYOPT"] = '-W:no-deprecated -W:no-experimental' + result = ruby_exe('case ($; = ""); in a; end', args: '2>&1') + result.should == "" + end + end + it "requires the file for '-r'" do f = fixture __FILE__, "rubyopt" ENV["RUBYOPT"] = "-r#{f}" @@ -67,101 +87,101 @@ it "raises a RuntimeError for '-a'" do ENV["RUBYOPT"] = '-a' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-p'" do ENV["RUBYOPT"] = '-p' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-n'" do ENV["RUBYOPT"] = '-n' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-y'" do ENV["RUBYOPT"] = '-y' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-c'" do ENV["RUBYOPT"] = '-c' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-s'" do ENV["RUBYOPT"] = '-s' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-h'" do ENV["RUBYOPT"] = '-h' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '--help'" do ENV["RUBYOPT"] = '--help' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-l'" do ENV["RUBYOPT"] = '-l' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-S'" do ENV["RUBYOPT"] = '-S irb' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-e'" do ENV["RUBYOPT"] = '-e0' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-i'" do ENV["RUBYOPT"] = '-i.bak' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-x'" do ENV["RUBYOPT"] = '-x' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-C'" do ENV["RUBYOPT"] = '-C' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-X'" do ENV["RUBYOPT"] = '-X.' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-F'" do ENV["RUBYOPT"] = '-F' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '-0'" do ENV["RUBYOPT"] = '-0' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '--copyright'" do ENV["RUBYOPT"] = '--copyright' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '--version'" do ENV["RUBYOPT"] = '--version' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end it "raises a RuntimeError for '--yydebug'" do ENV["RUBYOPT"] = '--yydebug' - ruby_exe("", args: '2>&1').should =~ /RuntimeError/ + ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/ end end diff --git a/ruby/spec/ruby/command_line/syntax_error_spec.rb b/ruby/spec/ruby/command_line/syntax_error_spec.rb index f61cfe928..444ea9635 100644 --- a/ruby/spec/ruby/command_line/syntax_error_spec.rb +++ b/ruby/spec/ruby/command_line/syntax_error_spec.rb @@ -2,12 +2,12 @@ describe "The interpreter" do it "prints an error when given a file with invalid syntax" do - out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), args: "2>&1") + out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), args: "2>&1", exit_status: 1) out.should include "syntax error" end it "prints an error when given code via -e with invalid syntax" do - out = ruby_exe(nil, args: "-e 'a{' 2>&1") + out = ruby_exe(nil, args: "-e 'a{' 2>&1", exit_status: 1) out.should include "syntax error" end end diff --git a/ruby/spec/ruby/core/argf/binmode_spec.rb b/ruby/spec/ruby/core/argf/binmode_spec.rb index bdcc6aa30..e083a30a2 100644 --- a/ruby/spec/ruby/core/argf/binmode_spec.rb +++ b/ruby/spec/ruby/core/argf/binmode_spec.rb @@ -34,7 +34,7 @@ it "sets the file's encoding to BINARY" do argf [@bin_file, @file1] do @argf.binmode - @argf.binmode?.should == true + @argf.should.binmode? @argf.gets.encoding.should == Encoding::BINARY @argf.skip @argf.read.encoding.should == Encoding::BINARY diff --git a/ruby/spec/ruby/core/argf/bytes_spec.rb b/ruby/spec/ruby/core/argf/bytes_spec.rb index 71d07fabc..bf35ded1d 100644 --- a/ruby/spec/ruby/core/argf/bytes_spec.rb +++ b/ruby/spec/ruby/core/argf/bytes_spec.rb @@ -1,6 +1,16 @@ require_relative '../../spec_helper' require_relative 'shared/each_byte' -describe "ARGF.bytes" do - it_behaves_like :argf_each_byte, :bytes +ruby_version_is ''...'3.0' do + describe "ARGF.bytes" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :argf_each_byte, :bytes + end end diff --git a/ruby/spec/ruby/core/argf/chars_spec.rb b/ruby/spec/ruby/core/argf/chars_spec.rb index ee79ea763..6af73cdab 100644 --- a/ruby/spec/ruby/core/argf/chars_spec.rb +++ b/ruby/spec/ruby/core/argf/chars_spec.rb @@ -1,6 +1,16 @@ require_relative '../../spec_helper' require_relative 'shared/each_char' -describe "ARGF.chars" do - it_behaves_like :argf_each_char, :chars +ruby_version_is ''...'3.0' do + describe "ARGF.chars" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :argf_each_char, :chars + end end diff --git a/ruby/spec/ruby/core/argf/codepoints_spec.rb b/ruby/spec/ruby/core/argf/codepoints_spec.rb index 7aa8a761f..bb28c17fb 100644 --- a/ruby/spec/ruby/core/argf/codepoints_spec.rb +++ b/ruby/spec/ruby/core/argf/codepoints_spec.rb @@ -1,6 +1,16 @@ require_relative '../../spec_helper' require_relative 'shared/each_codepoint' -describe "ARGF.codepoints" do - it_behaves_like :argf_each_codepoint, :codepoints +ruby_version_is ''...'3.0' do + describe "ARGF.codepoints" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :argf_each_codepoint, :codepoints + end end diff --git a/ruby/spec/ruby/core/argf/lines_spec.rb b/ruby/spec/ruby/core/argf/lines_spec.rb index 6ca6ff125..e964dbd0d 100644 --- a/ruby/spec/ruby/core/argf/lines_spec.rb +++ b/ruby/spec/ruby/core/argf/lines_spec.rb @@ -1,6 +1,16 @@ require_relative '../../spec_helper' require_relative 'shared/each_line' -describe "ARGF.lines" do - it_behaves_like :argf_each_line, :lines +ruby_version_is ''...'3.0' do + describe "ARGF.lines" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :argf_each_line, :lines + end end diff --git a/ruby/spec/ruby/core/argf/shared/fileno.rb b/ruby/spec/ruby/core/argf/shared/fileno.rb index 5d674048e..4350d4374 100644 --- a/ruby/spec/ruby/core/argf/shared/fileno.rb +++ b/ruby/spec/ruby/core/argf/shared/fileno.rb @@ -11,7 +11,7 @@ # returns first current file even when not yet open result << @argf.send(@method) while @argf.gets # returns last current file even when closed - result.map { |d| d.class }.should == [Fixnum, Fixnum, Fixnum, Fixnum] + result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer] end end diff --git a/ruby/spec/ruby/core/array/any_spec.rb b/ruby/spec/ruby/core/array/any_spec.rb index 2fa5353e9..09d949fe6 100644 --- a/ruby/spec/ruby/core/array/any_spec.rb +++ b/ruby/spec/ruby/core/array/any_spec.rb @@ -4,17 +4,17 @@ describe 'with no block given (a default block of { |x| x } is implicit)' do it "is false if the array is empty" do empty_array = [] - empty_array.any?.should == false + empty_array.should_not.any? end it "is false if the array is not empty, but all the members of the array are falsy" do falsy_array = [false, nil, false] - falsy_array.any?.should == false + falsy_array.should_not.any? end it "is true if the array has any truthy members" do not_empty_array = ['anything', nil] - not_empty_array.any?.should == true + not_empty_array.should.any? end end diff --git a/ruby/spec/ruby/core/array/append_spec.rb b/ruby/spec/ruby/core/array/append_spec.rb index 302dc4a90..c12473dc0 100644 --- a/ruby/spec/ruby/core/array/append_spec.rb +++ b/ruby/spec/ruby/core/array/append_spec.rb @@ -30,13 +30,11 @@ a.should == [:foo] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array << 5 }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array << 5 }.should raise_error(FrozenError) end end -ruby_version_is "2.5" do - describe "Array#append" do - it_behaves_like :array_push, :append - end +describe "Array#append" do + it_behaves_like :array_push, :append end diff --git a/ruby/spec/ruby/core/array/bsearch_index_spec.rb b/ruby/spec/ruby/core/array/bsearch_index_spec.rb index aafded178..df2c7c098 100644 --- a/ruby/spec/ruby/core/array/bsearch_index_spec.rb +++ b/ruby/spec/ruby/core/array/bsearch_index_spec.rb @@ -77,7 +77,7 @@ @array.bsearch_index { |x| (-1) * (2**100) }.should be_nil end - it "handles values from Bignum#coerce" do + it "handles values from Integer#coerce" do [1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first }) end end diff --git a/ruby/spec/ruby/core/array/clear_spec.rb b/ruby/spec/ruby/core/array/clear_spec.rb index d399d5a37..bddc672d3 100644 --- a/ruby/spec/ruby/core/array/clear_spec.rb +++ b/ruby/spec/ruby/core/array/clear_spec.rb @@ -16,7 +16,7 @@ it "leaves the Array empty" do a = [1] a.clear - a.empty?.should == true + a.should.empty? a.size.should == 0 end @@ -44,9 +44,9 @@ end end - it "raises a #{frozen_error_class} on a frozen array" do + it "raises a FrozenError on a frozen array" do a = [1] a.freeze - -> { a.clear }.should raise_error(frozen_error_class) + -> { a.clear }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/clone_spec.rb b/ruby/spec/ruby/core/array/clone_spec.rb index 803e746e0..e22a6c6d5 100644 --- a/ruby/spec/ruby/core/array/clone_spec.rb +++ b/ruby/spec/ruby/core/array/clone_spec.rb @@ -12,8 +12,8 @@ aa = a.clone bb = b.clone - aa.frozen?.should == true - bb.frozen?.should == false + aa.should.frozen? + bb.should_not.frozen? end it "copies singleton methods" do diff --git a/ruby/spec/ruby/core/array/compact_spec.rb b/ruby/spec/ruby/core/array/compact_spec.rb index ee3dfc0ca..aa3c1c044 100644 --- a/ruby/spec/ruby/core/array/compact_spec.rb +++ b/ruby/spec/ruby/core/array/compact_spec.rb @@ -75,7 +75,7 @@ end end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.compact! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.compact! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/concat_spec.rb b/ruby/spec/ruby/core/array/concat_spec.rb index b297c091a..da6763bfd 100644 --- a/ruby/spec/ruby/core/array/concat_spec.rb +++ b/ruby/spec/ruby/core/array/concat_spec.rb @@ -32,13 +32,13 @@ [].concat(obj).should == [5, 6, 7] end - it "raises a #{frozen_error_class} when Array is frozen and modification occurs" do - -> { ArraySpecs.frozen_array.concat [1] }.should raise_error(frozen_error_class) + it "raises a FrozenError when Array is frozen and modification occurs" do + -> { ArraySpecs.frozen_array.concat [1] }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} when Array is frozen and no modification occurs" do - -> { ArraySpecs.frozen_array.concat([]) }.should raise_error(frozen_error_class) + it "raises a FrozenError when Array is frozen and no modification occurs" do + -> { ArraySpecs.frozen_array.concat([]) }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/array/deconstruct_spec.rb b/ruby/spec/ruby/core/array/deconstruct_spec.rb new file mode 100644 index 000000000..2b07152df --- /dev/null +++ b/ruby/spec/ruby/core/array/deconstruct_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Array#deconstruct" do + it "returns self" do + array = [1] + + array.deconstruct.should equal array + end + end +end diff --git a/ruby/spec/ruby/core/array/delete_at_spec.rb b/ruby/spec/ruby/core/array/delete_at_spec.rb index 0ed56c18b..fc225a03f 100644 --- a/ruby/spec/ruby/core/array/delete_at_spec.rb +++ b/ruby/spec/ruby/core/array/delete_at_spec.rb @@ -35,8 +35,8 @@ a.delete_at(-2).should == 1 end - it "raises a #{frozen_error_class} on a frozen array" do - -> { [1,2,3].freeze.delete_at(0) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { [1,2,3].freeze.delete_at(0) }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/array/delete_if_spec.rb b/ruby/spec/ruby/core/array/delete_if_spec.rb index 2312917c4..e1931220f 100644 --- a/ruby/spec/ruby/core/array/delete_if_spec.rb +++ b/ruby/spec/ruby/core/array/delete_if_spec.rb @@ -39,12 +39,12 @@ @a.freeze.delete_if.should be_an_instance_of(Enumerator) end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.delete_if {} }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.delete_if {} }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/array/delete_spec.rb b/ruby/spec/ruby/core/array/delete_spec.rb index 41e211e66..5d53c74e4 100644 --- a/ruby/spec/ruby/core/array/delete_spec.rb +++ b/ruby/spec/ruby/core/array/delete_spec.rb @@ -40,8 +40,8 @@ def x.==(other) 3 == other end [1, 2, 3].freeze.delete(0).should == nil end - it "raises a #{frozen_error_class} on a frozen array" do - -> { [1, 2, 3].freeze.delete(1) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { [1, 2, 3].freeze.delete(1) }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/array/difference_spec.rb b/ruby/spec/ruby/core/array/difference_spec.rb index a35765796..9f7d4c4a1 100644 --- a/ruby/spec/ruby/core/array/difference_spec.rb +++ b/ruby/spec/ruby/core/array/difference_spec.rb @@ -2,23 +2,21 @@ require_relative 'fixtures/classes' require_relative 'shared/difference' -ruby_version_is "2.6" do - describe "Array#difference" do - it_behaves_like :array_binary_difference, :difference +describe "Array#difference" do + it_behaves_like :array_binary_difference, :difference - it "returns a copy when called without any parameter" do - x = [1, 2, 3, 2] - x.difference.should == x - x.difference.should_not equal x - end + it "returns a copy when called without any parameter" do + x = [1, 2, 3, 2] + x.difference.should == x + x.difference.should_not equal x + end - it "does not return subclass instances for Array subclasses" do - ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array) - end + it "does not return subclass instances for Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array) + end - it "accepts multiple arguments" do - x = [1, 2, 3, 1] - x.difference([], [0, 1], [3, 4], [3]).should == [2] - end + it "accepts multiple arguments" do + x = [1, 2, 3, 1] + x.difference([], [0, 1], [3, 4], [3]).should == [2] end end diff --git a/ruby/spec/ruby/core/array/drop_spec.rb b/ruby/spec/ruby/core/array/drop_spec.rb index 84ea86b04..f911fd901 100644 --- a/ruby/spec/ruby/core/array/drop_spec.rb +++ b/ruby/spec/ruby/core/array/drop_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Array#drop" do it "removes the specified number of elements from the start of the array" do @@ -48,4 +49,16 @@ -> { [1, 2].drop(obj) }.should raise_error(TypeError) end + + ruby_version_is ''...'3.0' do + it 'returns a subclass instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it 'returns a Array instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should be_an_instance_of(Array) + end + end end diff --git a/ruby/spec/ruby/core/array/drop_while_spec.rb b/ruby/spec/ruby/core/array/drop_while_spec.rb index cfb6b1e26..bb783d22a 100644 --- a/ruby/spec/ruby/core/array/drop_while_spec.rb +++ b/ruby/spec/ruby/core/array/drop_while_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Array#drop_while" do it "removes elements from the start of the array while the block evaluates to true" do @@ -12,4 +13,16 @@ it "removes elements from the start of the array until the block returns false" do [1, 2, 3, false, 5].drop_while { |n| n }.should == [false, 5] end + + ruby_version_is ''...'3.0' do + it 'returns a subclass instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it 'returns a Array instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should be_an_instance_of(Array) + end + end end diff --git a/ruby/spec/ruby/core/array/element_set_spec.rb b/ruby/spec/ruby/core/array/element_set_spec.rb index 9375ff9b8..1e192c100 100644 --- a/ruby/spec/ruby/core/array/element_set_spec.rb +++ b/ruby/spec/ruby/core/array/element_set_spec.rb @@ -36,6 +36,7 @@ a[3, 2] = ['a', 'b', 'c', 'd'] a.should == [2, 2, 3, "a", "b", "c", "d", 6] end + it "replaces the section defined by [start,length] with the given values" do a = [1, 2, 3, 4, 5, 6] a[3, 2] = 'a', 'b', 'c', 'd' @@ -94,8 +95,8 @@ it "checks frozen before attempting to coerce arguments" do a = [1,2,3,4].freeze - -> {a[:foo] = 1}.should raise_error(frozen_error_class) - -> {a[:foo, :bar] = 1}.should raise_error(frozen_error_class) + -> {a[:foo] = 1}.should raise_error(FrozenError) + -> {a[:foo, :bar] = 1}.should raise_error(FrozenError) end it "sets elements in the range arguments when passed ranges" do @@ -169,6 +170,7 @@ ary[1...1] = [] ary.should == [1, 2, 3] end + it "does nothing if the section defined by range has negative width and the rhs is an empty array" do ary = [1, 2, 3, 4, 5] ary[1...0] = [] @@ -236,8 +238,8 @@ def obj.to_ary() [1, 2, 3] end ary.should == [5, 6, 7] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(FrozenError) end end @@ -284,6 +286,12 @@ def obj.to_ary() [1, 2, 3] end (a[2, 3] = [4, 5]).should == [4, 5] end + it "accepts a frozen String literal as RHS" do + a = ['a', 'b', 'c'] + a[0, 2] = 'd'.freeze + a.should == ['d', 'c'] + end + it "just sets the section defined by [start,length] to nil even if the rhs is nil" do a = ['a', 'b', 'c', 'd', 'e'] a[1, 3] = nil @@ -323,6 +331,10 @@ def obj.to_ary() [1, 2, 3] end b = [1, 2, 3, 4, 5] b[10, 0] = [1] a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1] + + c = [1, 2, 3, 4, 5] + c[10, 0] = [] + c.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil] end it "inserts other section in place defined by idx" do @@ -396,6 +408,14 @@ def obj.to_ary() [1, 2, 3] end a.should == [1, 2, 3, 8, 4, 5] end + it "inserts at the end if m > the array size" do + a = [1, 2, 3] + a[3..3] = [4] + a.should == [1, 2, 3, 4] + a[5..7] = [6] + a.should == [1, 2, 3, 4, nil, 6] + end + describe "Range subclasses" do before :each do @range_incl = ArraySpecs::MyRange.new(1, 2) @@ -425,6 +445,89 @@ def obj.to_ary() [1, 2, 3] end end end +describe "Array#[]= with [m..]" do + it "just sets the section defined by range to nil even if the rhs is nil" do + a = [1, 2, 3, 4, 5] + a[eval("(2..)")] = nil + a.should == [1, 2, nil] + end + + it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do + a = [1, 2, 3, 4, 5] + a[eval("(-3..)")] = nil + a.should == [1, 2, nil] + end + + it "replaces the section defined by range" do + a = [6, 5, 4, 3, 2, 1] + a[eval("(3...)")] = 9 + a.should == [6, 5, 4, 9] + a[eval("(2..)")] = [7, 7, 7] + a.should == [6, 5, 7, 7, 7] + end + + it "replaces the section if m and n < 0" do + a = [1, 2, 3, 4, 5] + a[eval("(-3..)")] = [7, 8, 9] + a.should == [1, 2, 7, 8, 9] + end + + it "inserts at the end if m > the array size" do + a = [1, 2, 3] + a[eval("(3..)")] = [4] + a.should == [1, 2, 3, 4] + a[eval("(5..)")] = [6] + a.should == [1, 2, 3, 4, nil, 6] + end +end + +ruby_version_is "2.7" do + describe "Array#[]= with [..n] and [...n]" do + it "just sets the section defined by range to nil even if the rhs is nil" do + a = [1, 2, 3, 4, 5] + a[eval("(..2)")] = nil + a.should == [nil, 4, 5] + a[eval("(...2)")] = nil + a.should == [nil, 5] + end + + it "just sets the section defined by range to nil if n < 0 and the rhs is nil" do + a = [1, 2, 3, 4, 5] + a[eval("(..-3)")] = nil + a.should == [nil, 4, 5] + a[eval("(...-1)")] = [nil, 5] + end + + it "replaces the section defined by range" do + a = [6, 5, 4, 3, 2, 1] + a[eval("(...3)")] = 9 + a.should == [9, 3, 2, 1] + a[eval("(..2)")] = [7, 7, 7, 7, 7] + a.should == [7, 7, 7, 7, 7, 1] + end + + it "replaces the section if n < 0" do + a = [1, 2, 3, 4, 5] + a[eval("(..-2)")] = [7, 8, 9] + a.should == [7, 8, 9, 5] + end + + it "replaces everything if n > the array size" do + a = [1, 2, 3] + a[eval("(...7)")] = [4] + a.should == [4] + end + + it "inserts at the beginning if n < negative the array size" do + a = [1, 2, 3] + a[eval("(..-7)")] = [4] + a.should == [4, 1, 2, 3] + a[eval("(...-10)")] = [6] + a.should == [6, 4, 1, 2, 3] + end + end +end + describe "Array#[] after a shift" do it "works for insertion" do a = [1,2] diff --git a/ruby/spec/ruby/core/array/empty_spec.rb b/ruby/spec/ruby/core/array/empty_spec.rb index b5f3e8ed4..f70b1b6eb 100644 --- a/ruby/spec/ruby/core/array/empty_spec.rb +++ b/ruby/spec/ruby/core/array/empty_spec.rb @@ -3,8 +3,8 @@ describe "Array#empty?" do it "returns true if the array has no elements" do - [].empty?.should == true - [1].empty?.should == false - [1, 2].empty?.should == false + [].should.empty? + [1].should_not.empty? + [1, 2].should_not.empty? end end diff --git a/ruby/spec/ruby/core/array/fill_spec.rb b/ruby/spec/ruby/core/array/fill_spec.rb index 1c1beef25..bfa8db551 100644 --- a/ruby/spec/ruby/core/array/fill_spec.rb +++ b/ruby/spec/ruby/core/array/fill_spec.rb @@ -43,12 +43,12 @@ [nil, nil, nil, nil].fill { |i| i * 2 }.should == [0, 2, 4, 6] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.fill('x') }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.fill('x') }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(FrozenError) end it "raises an ArgumentError if 4 or more arguments are passed when no block given" do @@ -207,8 +207,9 @@ not_supported_on :opal do it "raises an ArgumentError or RangeError for too-large sizes" do + error_types = [RangeError, ArgumentError] arr = [1, 2, 3] - -> { arr.fill(10, 1, fixnum_max) }.should raise_error(ArgumentError) + -> { arr.fill(10, 1, fixnum_max) }.should raise_error { |err| error_types.should include(err.class) } -> { arr.fill(10, 1, bignum_value) }.should raise_error(RangeError) end end @@ -314,4 +315,18 @@ def obj.<=>(rhs); rhs == self ? 0 : nil end def obj.<=>(rhs); rhs == self ? 0 : nil end -> { [].fill('a', obj..obj) }.should raise_error(TypeError) end + + it "works with endless ranges" do + [1, 2, 3, 4].fill('x', eval("(1..)")).should == [1, 'x', 'x', 'x'] + [1, 2, 3, 4].fill('x', eval("(3...)")).should == [1, 2, 3, 'x'] + [1, 2, 3, 4].fill(eval("(1..)")) { |x| x + 2 }.should == [1, 3, 4, 5] + [1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5] + end + + ruby_version_is "2.7" do + it "works with beginless ranges" do + [1, 2, 3, 4].fill('x', eval("(..2)")).should == ["x", "x", "x", 4] + [1, 2, 3, 4].fill(eval("(...2)")) { |x| x + 2 }.should == [2, 3, 3, 4] + end + end end diff --git a/ruby/spec/ruby/core/array/filter_spec.rb b/ruby/spec/ruby/core/array/filter_spec.rb index ee4f71ca2..156ad14f9 100644 --- a/ruby/spec/ruby/core/array/filter_spec.rb +++ b/ruby/spec/ruby/core/array/filter_spec.rb @@ -1,16 +1,14 @@ require_relative '../../spec_helper' require_relative 'shared/select' -ruby_version_is "2.6" do - describe "Array#filter" do - it_behaves_like :array_select, :filter - end - - describe "Array#filter!" do - it "returns nil if no changes were made in the array" do - [1, 2, 3].filter! { true }.should be_nil - end +describe "Array#filter" do + it_behaves_like :array_select, :filter +end - it_behaves_like :keep_if, :filter! +describe "Array#filter!" do + it "returns nil if no changes were made in the array" do + [1, 2, 3].filter! { true }.should be_nil end + + it_behaves_like :keep_if, :filter! end diff --git a/ruby/spec/ruby/core/array/fixtures/classes.rb b/ruby/spec/ruby/core/array/fixtures/classes.rb index 42071ed0c..affb3b49e 100644 --- a/ruby/spec/ruby/core/array/fixtures/classes.rb +++ b/ruby/spec/ruby/core/array/fixtures/classes.rb @@ -126,7 +126,7 @@ def self.compared? attr_accessor :order end - class ComparableWithFixnum + class ComparableWithInteger include Comparable def initialize(num) @num = num @@ -144,7 +144,7 @@ def <=>(obj) end def self.universal_pack_object - obj = mock("string float int") + obj = mock("string float int".freeze) obj.stub!(:to_int).and_return(1) obj.stub!(:to_str).and_return("1") obj.stub!(:to_f).and_return(1.0) diff --git a/ruby/spec/ruby/core/array/flatten_spec.rb b/ruby/spec/ruby/core/array/flatten_spec.rb index 66af20ad7..2f9fb8a3e 100644 --- a/ruby/spec/ruby/core/array/flatten_spec.rb +++ b/ruby/spec/ruby/core/array/flatten_spec.rb @@ -75,12 +75,24 @@ [[obj]].flatten(1) end - it "returns subclass instance for Array subclasses" do - ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4] - [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + ruby_version_is ''...'3.0' do + it "returns subclass instance for Array subclasses" do + ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4] + [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + end + end + + ruby_version_is '3.0' do + it "returns Array instance for Array subclasses" do + ArraySpecs::MyArray[].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4] + [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + end end it "is not destructive" do @@ -109,20 +121,10 @@ -> { [@obj].flatten }.should raise_error(TypeError) end - ruby_version_is ""..."2.5" do - it "calls respond_to_missing?(:to_ary, false) to try coercing" do - def @obj.respond_to_missing?(*args) ScratchPad << args; false end - [@obj].flatten.should == [@obj] - ScratchPad.recorded.should == [[:to_ary, false]] - end - end - - ruby_version_is "2.5" do - it "calls respond_to_missing?(:to_ary, true) to try coercing" do - def @obj.respond_to_missing?(*args) ScratchPad << args; false end - [@obj].flatten.should == [@obj] - ScratchPad.recorded.should == [[:to_ary, true]] - end + it "calls respond_to_missing?(:to_ary, true) to try coercing" do + def @obj.respond_to_missing?(*args) ScratchPad << args; false end + [@obj].flatten.should == [@obj] + ScratchPad.recorded.should == [[:to_ary, true]] end it "does not call #to_ary if not defined when #respond_to_missing? returns false" do @@ -272,15 +274,15 @@ def bo.respond_to?(name, *) ary.should == [1, 2, 3] end - it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do + it "raises a FrozenError on frozen arrays when the array is modified" do nested_ary = [1, 2, []] nested_ary.freeze - -> { nested_ary.flatten! }.should raise_error(frozen_error_class) + -> { nested_ary.flatten! }.should raise_error(FrozenError) end # see [ruby-core:23663] - it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do - -> { ArraySpecs.frozen_array.flatten! }.should raise_error(frozen_error_class) - -> { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(frozen_error_class) + it "raises a FrozenError on frozen arrays when the array would not be modified" do + -> { ArraySpecs.frozen_array.flatten! }.should raise_error(FrozenError) + -> { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/frozen_spec.rb b/ruby/spec/ruby/core/array/frozen_spec.rb index bb4b2b406..3ba54be46 100644 --- a/ruby/spec/ruby/core/array/frozen_spec.rb +++ b/ruby/spec/ruby/core/array/frozen_spec.rb @@ -4,13 +4,13 @@ describe "Array#frozen?" do it "returns true if array is frozen" do a = [1, 2, 3] - a.frozen?.should == false + a.should_not.frozen? a.freeze - a.frozen?.should == true + a.should.frozen? end it "returns false for an array being sorted by #sort" do a = [1, 2, 3] - a.sort { |x,y| a.frozen?.should == false; x <=> y } + a.sort { |x,y| a.should_not.frozen?; x <=> y } end end diff --git a/ruby/spec/ruby/core/array/hash_spec.rb b/ruby/spec/ruby/core/array/hash_spec.rb index 8392253ae..f3bcc83fc 100644 --- a/ruby/spec/ruby/core/array/hash_spec.rb +++ b/ruby/spec/ruby/core/array/hash_spec.rb @@ -7,7 +7,7 @@ [[], [1, 2, 3]].each do |ary| ary.hash.should == ary.dup.hash - ary.hash.should be_an_instance_of(Fixnum) + ary.hash.should be_an_instance_of(Integer) end end diff --git a/ruby/spec/ruby/core/array/initialize_spec.rb b/ruby/spec/ruby/core/array/initialize_spec.rb index dfc2ae351..a8deed2b8 100644 --- a/ruby/spec/ruby/core/array/initialize_spec.rb +++ b/ruby/spec/ruby/core/array/initialize_spec.rb @@ -32,13 +32,13 @@ end.should raise_error(ArgumentError) end - it "raises a #{frozen_error_class} on frozen arrays" do + it "raises a FrozenError on frozen arrays" do -> do ArraySpecs.frozen_array.send :initialize - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) -> do ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) end it "calls #to_ary to convert the value to an array, even if it's private" do diff --git a/ruby/spec/ruby/core/array/insert_spec.rb b/ruby/spec/ruby/core/array/insert_spec.rb index 7577a8f74..9e1757f68 100644 --- a/ruby/spec/ruby/core/array/insert_spec.rb +++ b/ruby/spec/ruby/core/array/insert_spec.rb @@ -67,12 +67,12 @@ -> { [].insert() }.should raise_error(ArgumentError) end - it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do - -> { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(frozen_error_class) + it "raises a FrozenError on frozen arrays when the array is modified" do + -> { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do - -> { ArraySpecs.frozen_array.insert(0) }.should raise_error(frozen_error_class) + it "raises a FrozenError on frozen arrays when the array would not be modified" do + -> { ArraySpecs.frozen_array.insert(0) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/intersect_spec.rb b/ruby/spec/ruby/core/array/intersect_spec.rb new file mode 100644 index 000000000..b8c5b1e69 --- /dev/null +++ b/ruby/spec/ruby/core/array/intersect_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' + +describe 'Array#intersect?' do + ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/15198 + describe 'when at least one element in two Arrays is the same' do + it 'returns true' do + [1, 2].intersect?([2, 3]).should == true + end + end + + describe 'when there are no elements in common between two Arrays' do + it 'returns false' do + [1, 2].intersect?([3, 4]).should == false + end + end + end +end diff --git a/ruby/spec/ruby/core/array/intersection_spec.rb b/ruby/spec/ruby/core/array/intersection_spec.rb index 7bf2ec4db..27d90f1e4 100644 --- a/ruby/spec/ruby/core/array/intersection_spec.rb +++ b/ruby/spec/ruby/core/array/intersection_spec.rb @@ -1,87 +1,21 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/intersection' describe "Array#&" do - it "creates an array with elements common to both arrays (intersection)" do - ([] & []).should == [] - ([1, 2] & []).should == [] - ([] & [1, 2]).should == [] - ([ 1, 3, 5 ] & [ 1, 2, 3 ]).should == [1, 3] - end - - it "creates an array with no duplicates" do - ([ 1, 1, 3, 5 ] & [ 1, 2, 3 ]).uniq!.should == nil - end - - it "creates an array with elements in order they are first encountered" do - ([ 1, 2, 3, 2, 5 ] & [ 5, 2, 3, 4 ]).should == [2, 3, 5] - end - - it "does not modify the original Array" do - a = [1, 1, 3, 5] - (a & [1, 2, 3]).should == [1, 3] - a.should == [1, 1, 3, 5] - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - (empty & empty).should == empty - - (ArraySpecs.recursive_array & []).should == [] - ([] & ArraySpecs.recursive_array).should == [] - - (ArraySpecs.recursive_array & ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array] - end + it_behaves_like :array_intersection, :& +end - it "tries to convert the passed argument to an Array using #to_ary" do - obj = mock('[1,2,3]') - obj.should_receive(:to_ary).and_return([1, 2, 3]) - ([1, 2] & obj).should == ([1, 2]) - end +ruby_version_is "2.7" do + describe "Array#intersection" do + it_behaves_like :array_intersection, :intersection - it "determines equivalence between elements in the sense of eql?" do - not_supported_on :opal do - ([5.0, 4.0] & [5, 4]).should == [] + it "accepts multiple arguments" do + [1, 2, 3, 4].intersection([1, 2, 3], [2, 3, 4]).should == [2, 3] end - str = "x" - ([str] & [str.dup]).should == [str] - - obj1 = mock('1') - obj2 = mock('2') - obj1.stub!(:hash).and_return(0) - obj2.stub!(:hash).and_return(0) - obj1.should_receive(:eql?).at_least(1).and_return(true) - obj2.stub!(:eql?).and_return(true) - - ([obj1] & [obj2]).should == [obj1] - ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj1] - - obj1 = mock('3') - obj2 = mock('4') - obj1.stub!(:hash).and_return(0) - obj2.stub!(:hash).and_return(0) - obj1.should_receive(:eql?).at_least(1).and_return(false) - - ([obj1] & [obj2]).should == [] - ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj2] - end - - it "does return subclass instances for Array subclasses" do - (ArraySpecs::MyArray[1, 2, 3] & []).should be_an_instance_of(Array) - (ArraySpecs::MyArray[1, 2, 3] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array) - ([] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array) - end - - it "does not call to_ary on array subclasses" do - ([5, 6] & ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6] - end - - it "properly handles an identical item even when its #eql? isn't reflexive" do - x = mock('x') - x.stub!(:hash).and_return(42) - x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI. - - ([x] & [x]).should == [x] + it "preserves elements order from original array" do + [1, 2, 3, 4].intersection([3, 2, 1]).should == [1, 2, 3] + end end end diff --git a/ruby/spec/ruby/core/array/minmax_spec.rb b/ruby/spec/ruby/core/array/minmax_spec.rb new file mode 100644 index 000000000..e11fe6334 --- /dev/null +++ b/ruby/spec/ruby/core/array/minmax_spec.rb @@ -0,0 +1,14 @@ +require_relative '../../spec_helper' +require_relative '../../shared/enumerable/minmax' + +describe "Array#minmax" do + before :each do + @enum = [6, 4, 5, 10, 8] + @empty_enum = [] + @incomparable_enum = [BasicObject.new, BasicObject.new] + @incompatible_enum = [11, "22"] + @strs = ["333", "2", "60", "55555", "1010", "111"] + end + + it_behaves_like :enumerable_minmax, :minmax +end diff --git a/ruby/spec/ruby/core/array/multiply_spec.rb b/ruby/spec/ruby/core/array/multiply_spec.rb index 4060666d4..16e407348 100644 --- a/ruby/spec/ruby/core/array/multiply_spec.rb +++ b/ruby/spec/ruby/core/array/multiply_spec.rb @@ -76,10 +76,20 @@ def obj.to_str() "2" end @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] end - it "returns a subclass instance" do - (@array * 0).should be_an_instance_of(ArraySpecs::MyArray) - (@array * 1).should be_an_instance_of(ArraySpecs::MyArray) - (@array * 2).should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns a subclass instance" do + (@array * 0).should be_an_instance_of(ArraySpecs::MyArray) + (@array * 1).should be_an_instance_of(ArraySpecs::MyArray) + (@array * 2).should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it "returns an Array instance" do + (@array * 0).should be_an_instance_of(Array) + (@array * 1).should be_an_instance_of(Array) + (@array * 2).should be_an_instance_of(Array) + end end it "does not call #initialize on the subclass instance" do @@ -92,39 +102,39 @@ def obj.to_str() "2" end it "copies the taint status of the original array even if the passed count is 0" do ary = [1, 2, 3] ary.taint - (ary * 0).tainted?.should == true + (ary * 0).should.tainted? end it "copies the taint status of the original array even if the array is empty" do ary = [] ary.taint - (ary * 3).tainted?.should == true + (ary * 3).should.tainted? end it "copies the taint status of the original array if the passed count is not 0" do ary = [1, 2, 3] ary.taint - (ary * 1).tainted?.should == true - (ary * 2).tainted?.should == true + (ary * 1).should.tainted? + (ary * 2).should.tainted? end it "copies the untrusted status of the original array even if the passed count is 0" do ary = [1, 2, 3] ary.untrust - (ary * 0).untrusted?.should == true + (ary * 0).should.untrusted? end it "copies the untrusted status of the original array even if the array is empty" do ary = [] ary.untrust - (ary * 3).untrusted?.should == true + (ary * 3).should.untrusted? end it "copies the untrusted status of the original array if the passed count is not 0" do ary = [1, 2, 3] ary.untrust - (ary * 1).untrusted?.should == true - (ary * 2).untrusted?.should == true + (ary * 1).should.untrusted? + (ary * 2).should.untrusted? end end end diff --git a/ruby/spec/ruby/core/array/pop_spec.rb b/ruby/spec/ruby/core/array/pop_spec.rb index 2cfecbb2b..96ef78da3 100644 --- a/ruby/spec/ruby/core/array/pop_spec.rb +++ b/ruby/spec/ruby/core/array/pop_spec.rb @@ -40,12 +40,12 @@ end end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.pop }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.pop }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.pop }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.pop }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do @@ -158,9 +158,9 @@ end end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.pop(2) }.should raise_error(frozen_error_class) - -> { ArraySpecs.frozen_array.pop(0) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.pop(2) }.should raise_error(FrozenError) + -> { ArraySpecs.frozen_array.pop(0) }.should raise_error(FrozenError) end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/array/prepend_spec.rb b/ruby/spec/ruby/core/array/prepend_spec.rb index 22230ec30..368b8dcfc 100644 --- a/ruby/spec/ruby/core/array/prepend_spec.rb +++ b/ruby/spec/ruby/core/array/prepend_spec.rb @@ -2,8 +2,6 @@ require_relative 'fixtures/classes' require_relative 'shared/unshift' -ruby_version_is "2.5" do - describe "Array#prepend" do - it_behaves_like :array_unshift, :prepend - end +describe "Array#prepend" do + it_behaves_like :array_unshift, :prepend end diff --git a/ruby/spec/ruby/core/array/reject_spec.rb b/ruby/spec/ruby/core/array/reject_spec.rb index 1e9c296c8..fcf43fabd 100644 --- a/ruby/spec/ruby/core/array/reject_spec.rb +++ b/ruby/spec/ruby/core/array/reject_spec.rb @@ -103,12 +103,12 @@ ArraySpecs.frozen_array.reject!.should be_an_instance_of(Enumerator) end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.reject! {} }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.reject! {} }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(FrozenError) end it "does not truncate the array is the block raises an exception" do diff --git a/ruby/spec/ruby/core/array/reverse_spec.rb b/ruby/spec/ruby/core/array/reverse_spec.rb index e738be6fe..05dbd2efc 100644 --- a/ruby/spec/ruby/core/array/reverse_spec.rb +++ b/ruby/spec/ruby/core/array/reverse_spec.rb @@ -36,7 +36,7 @@ array.reverse!.should == [array, array, array, array, array, 3.0, 'two', 1] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.reverse! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.reverse! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/rotate_spec.rb b/ruby/spec/ruby/core/array/rotate_spec.rb index cc1aabf98..60dcc8b11 100644 --- a/ruby/spec/ruby/core/array/rotate_spec.rb +++ b/ruby/spec/ruby/core/array/rotate_spec.rb @@ -121,9 +121,9 @@ a.should == [] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(frozen_error_class) - -> { [1].freeze.rotate!(42) }.should raise_error(frozen_error_class) - -> { [].freeze.rotate! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(FrozenError) + -> { [1].freeze.rotate!(42) }.should raise_error(FrozenError) + -> { [].freeze.rotate! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/sample_spec.rb b/ruby/spec/ruby/core/array/sample_spec.rb index 44be91ba1..565d7ff7f 100644 --- a/ruby/spec/ruby/core/array/sample_spec.rb +++ b/ruby/spec/ruby/core/array/sample_spec.rb @@ -65,28 +65,11 @@ end describe "with options" do - it "calls #to_hash to convert the passed Object" do - obj = mock("array_sample") - obj.should_receive(:to_hash).and_return({}) - obj.should_not_receive(:to_int) - - [1, 2].sample(obj).should be_an_instance_of(Fixnum) - end - - it "calls #to_int on the first argument and #to_hash on the second when passed Objects" do - count = mock("array_sample_count") - count.should_receive(:to_int).and_return(2) - options = mock("array_sample_options") - options.should_receive(:to_hash).and_return({}) - - [1, 2].sample(count, options).size.should == 2 - end - it "calls #rand on the Object passed by the :random key in the arguments Hash" do obj = mock("array_sample_random") obj.should_receive(:rand).and_return(0.5) - [1, 2].sample(random: obj).should be_an_instance_of(Fixnum) + [1, 2].sample(random: obj).should be_an_instance_of(Integer) end it "raises a NoMethodError if an object passed for the RNG does not define #rand" do @@ -95,8 +78,8 @@ -> { [1, 2].sample(random: obj) }.should raise_error(NoMethodError) end - describe "when the object returned by #rand is a Fixnum" do - it "uses the fixnum as index" do + describe "when the object returned by #rand is an Integer" do + it "uses the integer as index" do random = mock("array_sample_random_ret") random.should_receive(:rand).and_return(0) @@ -124,7 +107,7 @@ end end - describe "when the object returned by #rand is not a Fixnum but responds to #to_int" do + describe "when the object returned by #rand is not an Integer but responds to #to_int" do it "calls #to_int on the Object" do value = mock("array_sample_random_value") value.should_receive(:to_int).and_return(1) diff --git a/ruby/spec/ruby/core/array/shared/clone.rb b/ruby/spec/ruby/core/array/shared/clone.rb index f6f581b17..3c17b1f10 100644 --- a/ruby/spec/ruby/core/array/shared/clone.rb +++ b/ruby/spec/ruby/core/array/shared/clone.rb @@ -26,8 +26,8 @@ aa = a.send @method bb = b.send @method - aa.tainted?.should == true - bb.tainted?.should == false + aa.should.tainted? + bb.should_not.tainted? end it "copies untrusted status from the original" do @@ -37,8 +37,8 @@ aa = a.send @method bb = b.send @method - aa.untrusted?.should == true - bb.untrusted?.should == false + aa.should.untrusted? + bb.should_not.untrusted? end end end diff --git a/ruby/spec/ruby/core/array/shared/collect.rb b/ruby/spec/ruby/core/array/shared/collect.rb index cbe32d2ab..d84432734 100644 --- a/ruby/spec/ruby/core/array/shared/collect.rb +++ b/ruby/spec/ruby/core/array/shared/collect.rb @@ -114,22 +114,22 @@ end describe "when frozen" do - it "raises a #{frozen_error_class}" do - -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(frozen_error_class) + it "raises a FrozenError" do + -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when empty" do - -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(frozen_error_class) + it "raises a FrozenError when empty" do + -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when calling #each on the returned Enumerator" do + it "raises a FrozenError when calling #each on the returned Enumerator" do enumerator = ArraySpecs.frozen_array.send(@method) - -> { enumerator.each {|x| x } }.should raise_error(frozen_error_class) + -> { enumerator.each {|x| x } }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when calling #each on the returned Enumerator when empty" do + it "raises a FrozenError when calling #each on the returned Enumerator when empty" do enumerator = ArraySpecs.empty_frozen_array.send(@method) - -> { enumerator.each {|x| x } }.should raise_error(frozen_error_class) + -> { enumerator.each {|x| x } }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/shared/intersection.rb b/ruby/spec/ruby/core/array/shared/intersection.rb new file mode 100644 index 000000000..49849b08c --- /dev/null +++ b/ruby/spec/ruby/core/array/shared/intersection.rb @@ -0,0 +1,84 @@ +describe :array_intersection, shared: true do + it "creates an array with elements common to both arrays (intersection)" do + [].send(@method, []).should == [] + [1, 2].send(@method, []).should == [] + [].send(@method, [1, 2]).should == [] + [ 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).should == [1, 3] + end + + it "creates an array with no duplicates" do + [ 1, 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).uniq!.should == nil + end + + it "creates an array with elements in order they are first encountered" do + [ 1, 2, 3, 2, 5 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5] + end + + it "does not modify the original Array" do + a = [1, 1, 3, 5] + a.send(@method, [1, 2, 3]).should == [1, 3] + a.should == [1, 1, 3, 5] + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.send(@method, empty).should == empty + + ArraySpecs.recursive_array.send(@method, []).should == [] + [].send(@method, ArraySpecs.recursive_array).should == [] + + ArraySpecs.recursive_array.send(@method, ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array] + end + + it "tries to convert the passed argument to an Array using #to_ary" do + obj = mock('[1,2,3]') + obj.should_receive(:to_ary).and_return([1, 2, 3]) + [1, 2].send(@method, obj).should == ([1, 2]) + end + + it "determines equivalence between elements in the sense of eql?" do + not_supported_on :opal do + [5.0, 4.0].send(@method, [5, 4]).should == [] + end + + str = "x" + [str].send(@method, [str.dup]).should == [str] + + obj1 = mock('1') + obj2 = mock('2') + obj1.stub!(:hash).and_return(0) + obj2.stub!(:hash).and_return(0) + obj1.should_receive(:eql?).at_least(1).and_return(true) + obj2.stub!(:eql?).and_return(true) + + [obj1].send(@method, [obj2]).should == [obj1] + [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1] + + obj1 = mock('3') + obj2 = mock('4') + obj1.stub!(:hash).and_return(0) + obj2.stub!(:hash).and_return(0) + obj1.should_receive(:eql?).at_least(1).and_return(false) + + [obj1].send(@method, [obj2]).should == [] + [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj2] + end + + it "does return subclass instances for Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array) + ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array) + [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array) + end + + it "does not call to_ary on array subclasses" do + [5, 6].send(@method, ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6] + end + + it "properly handles an identical item even when its #eql? isn't reflexive" do + x = mock('x') + x.stub!(:hash).and_return(42) + x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI. + + [x].send(@method, [x]).should == [x] + end +end diff --git a/ruby/spec/ruby/core/array/shared/join.rb b/ruby/spec/ruby/core/array/shared/join.rb index 5e7193de8..dfdb4ae1e 100644 --- a/ruby/spec/ruby/core/array/shared/join.rb +++ b/ruby/spec/ruby/core/array/shared/join.rb @@ -113,6 +113,21 @@ class << obj; undef :to_s; end -> { ary_utf8_bad_binary.send(@method) }.should raise_error(EncodingError) end + + ruby_version_is "2.7" do + context "when $, is not nil" do + before do + suppress_warning do + $, = '*' + end + end + + it "warns" do + -> { [].join }.should complain(/warning: \$, is set to non-nil value/) + -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/) + end + end + end end describe :array_join_with_string_separator, shared: true do diff --git a/ruby/spec/ruby/core/array/shared/keep_if.rb b/ruby/spec/ruby/core/array/shared/keep_if.rb index 2f1299c2b..f26aff028 100644 --- a/ruby/spec/ruby/core/array/shared/keep_if.rb +++ b/ruby/spec/ruby/core/array/shared/keep_if.rb @@ -41,8 +41,8 @@ @frozen.should == @origin end - it "raises a #{frozen_error_class}" do - -> { @frozen.send(@method) { true } }.should raise_error(frozen_error_class) + it "raises a FrozenError" do + -> { @frozen.send(@method) { true } }.should raise_error(FrozenError) end end @@ -52,8 +52,8 @@ @frozen.should == @origin end - it "raises a #{frozen_error_class}" do - -> { @frozen.send(@method) { false } }.should raise_error(frozen_error_class) + it "raises a FrozenError" do + -> { @frozen.send(@method) { false } }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/array/shared/push.rb b/ruby/spec/ruby/core/array/shared/push.rb index df307073c..ac790fb6a 100644 --- a/ruby/spec/ruby/core/array/shared/push.rb +++ b/ruby/spec/ruby/core/array/shared/push.rb @@ -26,8 +26,8 @@ array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class) - -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError) + -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/shared/replace.rb b/ruby/spec/ruby/core/array/shared/replace.rb index b3474fad0..9a6e60c1b 100644 --- a/ruby/spec/ruby/core/array/shared/replace.rb +++ b/ruby/spec/ruby/core/array/shared/replace.rb @@ -52,9 +52,9 @@ [].send(@method, ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7] end - it "raises a #{frozen_error_class} on a frozen array" do + it "raises a FrozenError on a frozen array" do -> { ArraySpecs.frozen_array.send(@method, ArraySpecs.frozen_array) - }.should raise_error(frozen_error_class) + }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/shared/slice.rb b/ruby/spec/ruby/core/array/shared/slice.rb index 1e7fdf934..540a05013 100644 --- a/ruby/spec/ruby/core/array/shared/slice.rb +++ b/ruby/spec/ruby/core/array/shared/slice.rb @@ -397,28 +397,56 @@ def to.to_int() -2 end @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] end - it "returns a subclass instance with [n, m]" do - @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns a subclass instance with [n, m]" do + @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n, m]" do + @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n..m]" do + @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n...m]" do + @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n..-m]" do + @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n...-m]" do + @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray) + end end - it "returns a subclass instance with [-n, m]" do - @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray) - end + ruby_version_is '3.0' do + it "returns a Array instance with [n, m]" do + @array.send(@method, 0, 2).should be_an_instance_of(Array) + end - it "returns a subclass instance with [n..m]" do - @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [-n, m]" do + @array.send(@method, -3, 2).should be_an_instance_of(Array) + end - it "returns a subclass instance with [n...m]" do - @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [n..m]" do + @array.send(@method, 1..3).should be_an_instance_of(Array) + end - it "returns a subclass instance with [-n..-m]" do - @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [n...m]" do + @array.send(@method, 1...3).should be_an_instance_of(Array) + end + + it "returns a Array instance with [-n..-m]" do + @array.send(@method, -3..-1).should be_an_instance_of(Array) + end - it "returns a subclass instance with [-n...-m]" do - @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray) + it "returns a Array instance with [-n...-m]" do + @array.send(@method, -3...-1).should be_an_instance_of(Array) + end end it "returns an empty array when m == n with [m...n]" do @@ -461,20 +489,307 @@ def to.to_int() -2 end it "raises a RangeError when the start index is out of range of Fixnum" do array = [1, 2, 3, 4, 5, 6] obj = mock('large value') - obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000) + obj.should_receive(:to_int).and_return(bignum_value) -> { array.send(@method, obj) }.should raise_error(RangeError) obj = 8e19 -> { array.send(@method, obj) }.should raise_error(RangeError) + + # boundary value when longs are 64 bits + -> { array.send(@method, 2.0**63) }.should raise_error(RangeError) + + # just under the boundary value when longs are 64 bits + array.send(@method, max_long.to_f.prev_float).should == nil end it "raises a RangeError when the length is out of range of Fixnum" do array = [1, 2, 3, 4, 5, 6] obj = mock('large value') - obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000) + obj.should_receive(:to_int).and_return(bignum_value) -> { array.send(@method, 1, obj) }.should raise_error(RangeError) obj = 8e19 -> { array.send(@method, 1, obj) }.should raise_error(RangeError) end + + it "raises a type error if a range is passed with a length" do + ->{ [1, 2, 3].send(@method, 1..2, 1) }.should raise_error(TypeError) + end + + it "raises a RangeError if passed a range with a bound that is too large" do + array = [1, 2, 3, 4, 5, 6] + -> { array.send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError) + -> { array.send(@method, 0..bignum_value) }.should raise_error(RangeError) + end + + it "can accept endless ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(2..)")).should == [2, 3, 4, 5] + a.send(@method, eval("(2...)")).should == [2, 3, 4, 5] + a.send(@method, eval("(-2..)")).should == [4, 5] + a.send(@method, eval("(-2...)")).should == [4, 5] + a.send(@method, eval("(9..)")).should == nil + a.send(@method, eval("(9...)")).should == nil + a.send(@method, eval("(-9..)")).should == nil + a.send(@method, eval("(-9...)")).should == nil + end + + ruby_version_is "3.0" do + describe "can be sliced with Enumerator::ArithmeticSequence" do + before :each do + @array = [0, 1, 2, 3, 4, 5] + end + + it "has endless range and positive steps" do + @array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5] + @array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4] + @array.send(@method, eval("(0..).step(10)")).should == [0] + + @array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5] + @array.send(@method, eval("(2..).step(2)")).should == [2, 4] + @array.send(@method, eval("(2..).step(10)")).should == [2] + + @array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5] + @array.send(@method, eval("(-3..).step(2)")).should == [3, 5] + @array.send(@method, eval("(-3..).step(10)")).should == [3] + end + + it "has beginless range and positive steps" do + # end with zero index + @array.send(@method, eval("(..0).step(1)")).should == [0] + @array.send(@method, eval("(...0).step(1)")).should == [] + + @array.send(@method, eval("(..0).step(2)")).should == [0] + @array.send(@method, eval("(...0).step(2)")).should == [] + + @array.send(@method, eval("(..0).step(10)")).should == [0] + @array.send(@method, eval("(...0).step(10)")).should == [] + + # end with positive index + @array.send(@method, eval("(..3).step(1)")).should == [0, 1, 2, 3] + @array.send(@method, eval("(...3).step(1)")).should == [0, 1, 2] + + @array.send(@method, eval("(..3).step(2)")).should == [0, 2] + @array.send(@method, eval("(...3).step(2)")).should == [0, 2] + + @array.send(@method, eval("(..3).step(10)")).should == [0] + @array.send(@method, eval("(...3).step(10)")).should == [0] + + # end with negative index + @array.send(@method, eval("(..-2).step(1)")).should == [0, 1, 2, 3, 4,] + @array.send(@method, eval("(...-2).step(1)")).should == [0, 1, 2, 3] + + @array.send(@method, eval("(..-2).step(2)")).should == [0, 2, 4] + @array.send(@method, eval("(...-2).step(2)")).should == [0, 2] + + @array.send(@method, eval("(..-2).step(10)")).should == [0] + @array.send(@method, eval("(...-2).step(10)")).should == [0] + end + + it "has endless range and negative steps" do + @array.send(@method, eval("(0..).step(-1)")).should == [0] + @array.send(@method, eval("(0..).step(-2)")).should == [0] + @array.send(@method, eval("(0..).step(-10)")).should == [0] + + @array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0] + @array.send(@method, eval("(2..).step(-2)")).should == [2, 0] + + @array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0] + @array.send(@method, eval("(-3..).step(-2)")).should == [3, 1] + end + + it "has closed range and positive steps" do + # start and end with 0 + @array.send(@method, eval("(0..0).step(1)")).should == [0] + @array.send(@method, eval("(0...0).step(1)")).should == [] + + @array.send(@method, eval("(0..0).step(2)")).should == [0] + @array.send(@method, eval("(0...0).step(2)")).should == [] + + @array.send(@method, eval("(0..0).step(10)")).should == [0] + @array.send(@method, eval("(0...0).step(10)")).should == [] + + # start and end with positive index + @array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3] + @array.send(@method, eval("(1...3).step(1)")).should == [1, 2] + + @array.send(@method, eval("(1..3).step(2)")).should == [1, 3] + @array.send(@method, eval("(1...3).step(2)")).should == [1] + + @array.send(@method, eval("(1..3).step(10)")).should == [1] + @array.send(@method, eval("(1...3).step(10)")).should == [1] + + # start with positive index, end with negative index + @array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4] + @array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3] + + @array.send(@method, eval("(1..-2).step(2)")).should == [1, 3] + @array.send(@method, eval("(1...-2).step(2)")).should == [1, 3] + + @array.send(@method, eval("(1..-2).step(10)")).should == [1] + @array.send(@method, eval("(1...-2).step(10)")).should == [1] + + # start with negative index, end with positive index + @array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4] + @array.send(@method, eval("(-4...4).step(1)")).should == [2, 3] + + @array.send(@method, eval("(-4..4).step(2)")).should == [2, 4] + @array.send(@method, eval("(-4...4).step(2)")).should == [2] + + @array.send(@method, eval("(-4..4).step(10)")).should == [2] + @array.send(@method, eval("(-4...4).step(10)")).should == [2] + + # start with negative index, end with negative index + @array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4] + @array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3] + + @array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4] + @array.send(@method, eval("(-4...-2).step(2)")).should == [2] + + @array.send(@method, eval("(-4..-2).step(10)")).should == [2] + @array.send(@method, eval("(-4...-2).step(10)")).should == [2] + end + + it "has closed range and negative steps" do + # start and end with 0 + @array.send(@method, eval("(0..0).step(-1)")).should == [0] + @array.send(@method, eval("(0...0).step(-1)")).should == [] + + @array.send(@method, eval("(0..0).step(-2)")).should == [0] + @array.send(@method, eval("(0...0).step(-2)")).should == [] + + @array.send(@method, eval("(0..0).step(-10)")).should == [0] + @array.send(@method, eval("(0...0).step(-10)")).should == [] + + # start and end with positive index + @array.send(@method, eval("(1..3).step(-1)")).should == [] + @array.send(@method, eval("(1...3).step(-1)")).should == [] + + @array.send(@method, eval("(1..3).step(-2)")).should == [] + @array.send(@method, eval("(1...3).step(-2)")).should == [] + + @array.send(@method, eval("(1..3).step(-10)")).should == [] + @array.send(@method, eval("(1...3).step(-10)")).should == [] + + # start with positive index, end with negative index + @array.send(@method, eval("(1..-2).step(-1)")).should == [] + @array.send(@method, eval("(1...-2).step(-1)")).should == [] + + @array.send(@method, eval("(1..-2).step(-2)")).should == [] + @array.send(@method, eval("(1...-2).step(-2)")).should == [] + + @array.send(@method, eval("(1..-2).step(-10)")).should == [] + @array.send(@method, eval("(1...-2).step(-10)")).should == [] + + # start with negative index, end with positive index + @array.send(@method, eval("(-4..4).step(-1)")).should == [] + @array.send(@method, eval("(-4...4).step(-1)")).should == [] + + @array.send(@method, eval("(-4..4).step(-2)")).should == [] + @array.send(@method, eval("(-4...4).step(-2)")).should == [] + + @array.send(@method, eval("(-4..4).step(-10)")).should == [] + @array.send(@method, eval("(-4...4).step(-10)")).should == [] + + # start with negative index, end with negative index + @array.send(@method, eval("(-4..-2).step(-1)")).should == [] + @array.send(@method, eval("(-4...-2).step(-1)")).should == [] + + @array.send(@method, eval("(-4..-2).step(-2)")).should == [] + @array.send(@method, eval("(-4...-2).step(-2)")).should == [] + + @array.send(@method, eval("(-4..-2).step(-10)")).should == [] + @array.send(@method, eval("(-4...-2).step(-10)")).should == [] + end + + it "has inverted closed range and positive steps" do + # start and end with positive index + @array.send(@method, eval("(3..1).step(1)")).should == [] + @array.send(@method, eval("(3...1).step(1)")).should == [] + + @array.send(@method, eval("(3..1).step(2)")).should == [] + @array.send(@method, eval("(3...1).step(2)")).should == [] + + @array.send(@method, eval("(3..1).step(10)")).should == [] + @array.send(@method, eval("(3...1).step(10)")).should == [] + + # start with negative index, end with positive index + @array.send(@method, eval("(-2..1).step(1)")).should == [] + @array.send(@method, eval("(-2...1).step(1)")).should == [] + + @array.send(@method, eval("(-2..1).step(2)")).should == [] + @array.send(@method, eval("(-2...1).step(2)")).should == [] + + @array.send(@method, eval("(-2..1).step(10)")).should == [] + @array.send(@method, eval("(-2...1).step(10)")).should == [] + + # start with positive index, end with negative index + @array.send(@method, eval("(4..-4).step(1)")).should == [] + @array.send(@method, eval("(4...-4).step(1)")).should == [] + + @array.send(@method, eval("(4..-4).step(2)")).should == [] + @array.send(@method, eval("(4...-4).step(2)")).should == [] + + @array.send(@method, eval("(4..-4).step(10)")).should == [] + @array.send(@method, eval("(4...-4).step(10)")).should == [] + + # start with negative index, end with negative index + @array.send(@method, eval("(-2..-4).step(1)")).should == [] + @array.send(@method, eval("(-2...-4).step(1)")).should == [] + + @array.send(@method, eval("(-2..-4).step(2)")).should == [] + @array.send(@method, eval("(-2...-4).step(2)")).should == [] + + @array.send(@method, eval("(-2..-4).step(10)")).should == [] + @array.send(@method, eval("(-2...-4).step(10)")).should == [] + end + + it "has range with bounds outside of array" do + # end is equal to array's length + @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5] + -> { @array.send(@method, (0..6).step(2)) }.should raise_error(RangeError) + + # end is greater than length with positive steps + @array.send(@method, (1..6).step(2)).should == [1, 3, 5] + @array.send(@method, (2..7).step(2)).should == [2, 4] + -> { @array.send(@method, (2..8).step(2)) }.should raise_error(RangeError) + + # begin is greater than length with negative steps + @array.send(@method, (6..1).step(-2)).should == [5, 3, 1] + @array.send(@method, (7..2).step(-2)).should == [5, 3] + -> { @array.send(@method, (8..2).step(-2)) }.should raise_error(RangeError) + end + + it "has endless range with start outside of array's bounds" do + @array.send(@method, eval("(6..).step(1)")).should == [] + @array.send(@method, eval("(7..).step(1)")).should == nil + + @array.send(@method, eval("(6..).step(2)")).should == [] + -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError) + end + end + end + + ruby_version_is "2.7" do + it "can accept beginless ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(..3)")).should == [0, 1, 2, 3] + a.send(@method, eval("(...3)")).should == [0, 1, 2] + a.send(@method, eval("(..-3)")).should == [0, 1, 2, 3] + a.send(@method, eval("(...-3)")).should == [0, 1, 2] + a.send(@method, eval("(..0)")).should == [0] + a.send(@method, eval("(...0)")).should == [] + a.send(@method, eval("(..9)")).should == [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(...9)")).should == [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(..-9)")).should == [] + a.send(@method, eval("(...-9)")).should == [] + end + + it "can accept nil...nil ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(nil...nil)")).should == a + a.send(@method, eval("(...nil)")).should == a + a.send(@method, eval("(nil..)")).should == a + end + end end diff --git a/ruby/spec/ruby/core/array/shared/union.rb b/ruby/spec/ruby/core/array/shared/union.rb index 12a98cc9f..0b60df9ca 100644 --- a/ruby/spec/ruby/core/array/shared/union.rb +++ b/ruby/spec/ruby/core/array/shared/union.rb @@ -31,7 +31,7 @@ [0].send(@method, obj).should == ([0] | [1, 2, 3]) end - # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Fixnum/Symbol + # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Integer/Symbol it "acts as if using an intermediate hash to collect values" do not_supported_on :opal do [5.0, 4.0].send(@method, [5, 4]).should == [5.0, 4.0, 5, 4] diff --git a/ruby/spec/ruby/core/array/shared/unshift.rb b/ruby/spec/ruby/core/array/shared/unshift.rb index be62084e9..fc82e19e2 100644 --- a/ruby/spec/ruby/core/array/shared/unshift.rb +++ b/ruby/spec/ruby/core/array/shared/unshift.rb @@ -35,12 +35,12 @@ array[0..5].should == [:new, 1, 'two', 3.0, array, array] end - it "raises a #{frozen_error_class} on a frozen array when the array is modified" do - -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array when the array is modified" do + -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do - -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array when the array would not be modified" do + -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/shift_spec.rb b/ruby/spec/ruby/core/array/shift_spec.rb index 13f1abbbf..b998e45d2 100644 --- a/ruby/spec/ruby/core/array/shift_spec.rb +++ b/ruby/spec/ruby/core/array/shift_spec.rb @@ -30,11 +30,11 @@ array[0..2].should == ['two', 3.0, array] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.shift }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.shift }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.shift }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.shift }.should raise_error(FrozenError) end describe "passed a number n as an argument" do diff --git a/ruby/spec/ruby/core/array/shuffle_spec.rb b/ruby/spec/ruby/core/array/shuffle_spec.rb index 7a2fed7d5..b255147c7 100644 --- a/ruby/spec/ruby/core/array/shuffle_spec.rb +++ b/ruby/spec/ruby/core/array/shuffle_spec.rb @@ -25,12 +25,6 @@ ArraySpecs::MyArray[1, 2, 3].shuffle.should be_an_instance_of(Array) end - it "attempts coercion via #to_hash" do - obj = mock('hash') - obj.should_receive(:to_hash).once.and_return({}) - [2, 3].shuffle(obj) - end - it "calls #rand on the Object passed by the :random key in the arguments Hash" do obj = mock("array_shuffle_random") obj.should_receive(:rand).at_least(1).times.and_return(0.5) @@ -95,8 +89,8 @@ a.should equal(original) end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.shuffle! }.should raise_error(frozen_error_class) - -> { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.shuffle! }.should raise_error(FrozenError) + -> { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/array/slice_spec.rb b/ruby/spec/ruby/core/array/slice_spec.rb index 16220bdf0..8c276f908 100644 --- a/ruby/spec/ruby/core/array/slice_spec.rb +++ b/ruby/spec/ruby/core/array/slice_spec.rb @@ -150,8 +150,96 @@ def to.to_int() -2 end a.should == [1, 2] end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(FrozenError) + end + + it "works with endless ranges" do + a = [1, 2, 3] + a.slice!(eval("(1..)")).should == [2, 3] + a.should == [1] + + a = [1, 2, 3] + a.slice!(eval("(2...)")).should == [3] + a.should == [1, 2] + + a = [1, 2, 3] + a.slice!(eval("(-2..)")).should == [2, 3] + a.should == [1] + + a = [1, 2, 3] + a.slice!(eval("(-1...)")).should == [3] + a.should == [1, 2] + end + + ruby_version_is "2.7" do + it "works with beginless ranges" do + a = [0,1,2,3,4] + a.slice!(eval("(..3)")).should == [0, 1, 2, 3] + a.should == [4] + + a = [0,1,2,3,4] + a.slice!(eval("(...-2)")).should == [0, 1, 2] + a.should == [3, 4] + end + end + + describe "with a subclass of Array" do + before :each do + @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] + end + + ruby_version_is ''...'3.0' do + it "returns a subclass instance with [n, m]" do + @array.slice!(0, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n, m]" do + @array.slice!(-3, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n..m]" do + @array.slice!(1..3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n...m]" do + @array.slice!(1...3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n..-m]" do + @array.slice!(-3..-1).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n...-m]" do + @array.slice!(-3...-1).should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it "returns a Array instance with [n, m]" do + @array.slice!(0, 2).should be_an_instance_of(Array) + end + + it "returns a Array instance with [-n, m]" do + @array.slice!(-3, 2).should be_an_instance_of(Array) + end + + it "returns a Array instance with [n..m]" do + @array.slice!(1..3).should be_an_instance_of(Array) + end + + it "returns a Array instance with [n...m]" do + @array.slice!(1...3).should be_an_instance_of(Array) + end + + it "returns a Array instance with [-n..-m]" do + @array.slice!(-3..-1).should be_an_instance_of(Array) + end + + it "returns a Array instance with [-n...-m]" do + @array.slice!(-3...-1).should be_an_instance_of(Array) + end + end end end diff --git a/ruby/spec/ruby/core/array/sort_by_spec.rb b/ruby/spec/ruby/core/array/sort_by_spec.rb index 045051d30..7cea6ec6d 100644 --- a/ruby/spec/ruby/core/array/sort_by_spec.rb +++ b/ruby/spec/ruby/core/array/sort_by_spec.rb @@ -23,12 +23,12 @@ a.should be_an_instance_of(Array) end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on an empty frozen array" do - -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty frozen array" do + -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(FrozenError) end it "returns the specified value when it would break in the given block" do diff --git a/ruby/spec/ruby/core/array/sort_spec.rb b/ruby/spec/ruby/core/array/sort_spec.rb index 6b84a82a4..e20b65051 100644 --- a/ruby/spec/ruby/core/array/sort_spec.rb +++ b/ruby/spec/ruby/core/array/sort_spec.rb @@ -58,9 +58,9 @@ b = ArraySpecs::MockForCompared.new c = ArraySpecs::MockForCompared.new - ArraySpecs::MockForCompared.compared?.should == false + ArraySpecs::MockForCompared.should_not.compared? [a, b, c].sort.should == [c, b, a] - ArraySpecs::MockForCompared.compared?.should == true + ArraySpecs::MockForCompared.should.compared? end it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do @@ -104,17 +104,17 @@ it "does not freezes self during being sorted" do a = [1, 2, 3] - a.sort { |x,y| a.frozen?.should == false; x <=> y } + a.sort { |x,y| a.should_not.frozen?; x <=> y } end it "returns the specified value when it would break in the given block" do [1, 2, 3].sort{ break :a }.should == :a end - it "uses the sign of Bignum block results as the sort result" do + it "uses the sign of Integer block results as the sort result" do a = [1, 2, 5, 10, 7, -4, 12] begin - class Bignum; + class Integer alias old_spaceship <=> def <=>(other) raise @@ -122,7 +122,7 @@ def <=>(other) end a.sort {|n, m| (n - m) * (2 ** 200)}.should == [-4, 1, 2, 5, 7, 10, 12] ensure - class Bignum + class Integer alias <=> old_spaceship end end @@ -132,7 +132,7 @@ class Bignum a = [1, 2, 5, 10, 7, -4, 12] a.sort { |n, m| n - m }.should == [-4, 1, 2, 5, 7, 10, 12] a.sort { |n, m| - ArraySpecs::ComparableWithFixnum.new(n-m) + ArraySpecs::ComparableWithInteger.new(n-m) }.should == [-4, 1, 2, 5, 7, 10, 12] -> { a.sort { |n, m| (n - m).to_s } @@ -207,9 +207,9 @@ class Bignum b = ArraySpecs::MockForCompared.new c = ArraySpecs::MockForCompared.new - ArraySpecs::MockForCompared.compared?.should == false + ArraySpecs::MockForCompared.should_not.compared? [a, b, c].sort!.should == [c, b, a] - ArraySpecs::MockForCompared.compared?.should == true + ArraySpecs::MockForCompared.should.compared? end it "does not call #<=> on contained objects when invoked with a block" do @@ -233,8 +233,8 @@ class Bignum a.sort!{ -1 }.should be_an_instance_of(Array) end - it "raises a #{frozen_error_class} on a frozen array" do - -> { ArraySpecs.frozen_array.sort! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.sort! }.should raise_error(FrozenError) end it "returns the specified value when it would break in the given block" do diff --git a/ruby/spec/ruby/core/array/sum_spec.rb b/ruby/spec/ruby/core/array/sum_spec.rb index 39c769d32..8ca8353a6 100644 --- a/ruby/spec/ruby/core/array/sum_spec.rb +++ b/ruby/spec/ruby/core/array/sum_spec.rb @@ -9,6 +9,35 @@ [1, 2, 3].sum { |i| i * 10 }.should == 60 end + # https://bugs.ruby-lang.org/issues/12217 + # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214 + it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do + floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5] + naive_sum = floats.reduce { |sum, e| sum + e } + naive_sum.should == 50.00000000000001 + floats.sum.should == 50.0 + end + + it "handles infinite values and NaN" do + [1.0, Float::INFINITY].sum.should == Float::INFINITY + [1.0, -Float::INFINITY].sum.should == -Float::INFINITY + [1.0, Float::NAN].sum.should.nan? + + [Float::INFINITY, 1.0].sum.should == Float::INFINITY + [-Float::INFINITY, 1.0].sum.should == -Float::INFINITY + [Float::NAN, 1.0].sum.should.nan? + + [Float::NAN, Float::INFINITY].sum.should.nan? + [Float::INFINITY, Float::NAN].sum.should.nan? + + [Float::INFINITY, -Float::INFINITY].sum.should.nan? + [-Float::INFINITY, Float::INFINITY].sum.should.nan? + + [Float::INFINITY, Float::INFINITY].sum.should == Float::INFINITY + [-Float::INFINITY, -Float::INFINITY].sum.should == -Float::INFINITY + [Float::NAN, Float::NAN].sum.should.nan? + end + it "returns init value if array is empty" do [].sum(-1).should == -1 end diff --git a/ruby/spec/ruby/core/array/take_spec.rb b/ruby/spec/ruby/core/array/take_spec.rb index 0de99b0a7..4fb6f0ce7 100644 --- a/ruby/spec/ruby/core/array/take_spec.rb +++ b/ruby/spec/ruby/core/array/take_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Array#take" do it "returns the first specified number of elements" do @@ -24,4 +25,16 @@ it "raises an ArgumentError when the argument is negative" do ->{ [1].take(-3) }.should raise_error(ArgumentError) end + + ruby_version_is ''...'3.0' do + it 'returns a subclass instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it 'returns a Array instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should be_an_instance_of(Array) + end + end end diff --git a/ruby/spec/ruby/core/array/take_while_spec.rb b/ruby/spec/ruby/core/array/take_while_spec.rb index f159e6f25..363419b26 100644 --- a/ruby/spec/ruby/core/array/take_while_spec.rb +++ b/ruby/spec/ruby/core/array/take_while_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Array#take_while" do it "returns all elements until the block returns false" do @@ -12,4 +13,16 @@ it "returns all elements until the block returns false" do [1, 2, false, 4].take_while{ |element| element }.should == [1, 2] end + + ruby_version_is ''...'3.0' do + it 'returns a subclass instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it 'returns a Array instance for Array subclasses' do + ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should be_an_instance_of(Array) + end + end end diff --git a/ruby/spec/ruby/core/array/to_h_spec.rb b/ruby/spec/ruby/core/array/to_h_spec.rb index 46a79ba58..f5a7e546e 100644 --- a/ruby/spec/ruby/core/array/to_h_spec.rb +++ b/ruby/spec/ruby/core/array/to_h_spec.rb @@ -39,43 +39,41 @@ [[:a, 1], [:b, 2]].to_h[:c].should be_nil end - ruby_version_is "2.6" do - context "with block" do - it "converts [key, value] pairs returned by the block to a Hash" do - [:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } - end - - it "raises ArgumentError if block returns longer or shorter array" do - -> do - [:a, :b].to_h { |k| [k, k.to_s, 1] } - end.should raise_error(ArgumentError, /wrong array length at 0/) - - -> do - [:a, :b].to_h { |k| [k] } - end.should raise_error(ArgumentError, /wrong array length at 0/) - end - - it "raises TypeError if block returns something other than Array" do - -> do - [:a, :b].to_h { |k| "not-array" } - end.should raise_error(TypeError, /wrong element type String at 0/) - end - - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) - - [:a].to_h { |k| x }.should == { :b => 'b' } - end - - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) - - -> do - [:a].to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject at 0/) - end + context "with block" do + it "converts [key, value] pairs returned by the block to a Hash" do + [:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } + end + + it "raises ArgumentError if block returns longer or shorter array" do + -> do + [:a, :b].to_h { |k| [k, k.to_s, 1] } + end.should raise_error(ArgumentError, /wrong array length at 0/) + + -> do + [:a, :b].to_h { |k| [k] } + end.should raise_error(ArgumentError, /wrong array length at 0/) + end + + it "raises TypeError if block returns something other than Array" do + -> do + [:a, :b].to_h { |k| "not-array" } + end.should raise_error(TypeError, /wrong element type String at 0/) + end + + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) + + [:a].to_h { |k| x }.should == { :b => 'b' } + end + + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) + + -> do + [:a].to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject at 0/) end end end diff --git a/ruby/spec/ruby/core/array/union_spec.rb b/ruby/spec/ruby/core/array/union_spec.rb index 1dca47696..ba2cc0d6b 100644 --- a/ruby/spec/ruby/core/array/union_spec.rb +++ b/ruby/spec/ruby/core/array/union_spec.rb @@ -6,22 +6,20 @@ it_behaves_like :array_binary_union, :| end -ruby_version_is "2.6" do - describe "Array#union" do - it_behaves_like :array_binary_union, :union +describe "Array#union" do + it_behaves_like :array_binary_union, :union - it "returns unique elements when given no argument" do - x = [1, 2, 3, 2] - x.union.should == [1, 2, 3] - end + it "returns unique elements when given no argument" do + x = [1, 2, 3, 2] + x.union.should == [1, 2, 3] + end - it "does not return subclass instances for Array subclasses" do - ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array) - end + it "does not return subclass instances for Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array) + end - it "accepts multiple arguments" do - x = [1, 2, 3] - x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4] - end + it "accepts multiple arguments" do + x = [1, 2, 3] + x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4] end end diff --git a/ruby/spec/ruby/core/array/uniq_spec.rb b/ruby/spec/ruby/core/array/uniq_spec.rb index 4b56f3c84..5911c23e6 100644 --- a/ruby/spec/ruby/core/array/uniq_spec.rb +++ b/ruby/spec/ruby/core/array/uniq_spec.rb @@ -87,8 +87,8 @@ def obj.eql?(o) end a.uniq.should == a - a[0].tainted?.should == true - a[1].tainted?.should == true + a[0].should.tainted? + a[1].should.tainted? a = Array.new(2) do obj = mock('0') @@ -106,8 +106,8 @@ def obj.eql?(o) end a.uniq.size.should == 1 - a[0].tainted?.should == true - a[1].tainted?.should == true + a[0].should.tainted? + a[1].should.tainted? end end @@ -128,8 +128,16 @@ def obj.eql?(o) [false, nil, 42].uniq { :bar }.should == [false] end - it "returns subclass instance on Array subclasses" do - ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns subclass instance on Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it "returns Array instance on Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(Array) + end end it "properly handles an identical item even when its #eql? isn't reflexive" do @@ -220,20 +228,20 @@ def hash [ "a", "b", "c" ].uniq!.should == nil end - it "raises a #{frozen_error_class} on a frozen array when the array is modified" do + it "raises a FrozenError on a frozen array when the array is modified" do dup_ary = [1, 1, 2] dup_ary.freeze - -> { dup_ary.uniq! }.should raise_error(frozen_error_class) + -> { dup_ary.uniq! }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do - -> { ArraySpecs.frozen_array.uniq!}.should raise_error(frozen_error_class) - -> { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen array when the array would not be modified" do + -> { ArraySpecs.frozen_array.uniq!}.should raise_error(FrozenError) + -> { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(FrozenError) end it "doesn't yield to the block on a frozen array" do - -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(frozen_error_class) + -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(FrozenError) end it "compares elements based on the value returned from the block" do diff --git a/ruby/spec/ruby/core/array/values_at_spec.rb b/ruby/spec/ruby/core/array/values_at_spec.rb index 13860150b..f1522e0bf 100644 --- a/ruby/spec/ruby/core/array/values_at_spec.rb +++ b/ruby/spec/ruby/core/array/values_at_spec.rb @@ -60,4 +60,16 @@ def to.to_int() -2 end it "does not return subclass instance on Array subclasses" do ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array) end + + it "works when given endless ranges" do + [1, 2, 3, 4].values_at(eval("(1..)")).should == [2, 3, 4] + [1, 2, 3, 4].values_at(eval("(3...)")).should == [4] + end + + ruby_version_is "2.7" do + it "works when given beginless ranges" do + [1, 2, 3, 4].values_at(eval("(..2)")).should == [1, 2, 3] + [1, 2, 3, 4].values_at(eval("(...2)")).should == [1, 2] + end + end end diff --git a/ruby/spec/ruby/core/basicobject/instance_eval_spec.rb b/ruby/spec/ruby/core/basicobject/instance_eval_spec.rb index d3dd05b74..b6a146095 100644 --- a/ruby/spec/ruby/core/basicobject/instance_eval_spec.rb +++ b/ruby/spec/ruby/core/basicobject/instance_eval_spec.rb @@ -131,14 +131,14 @@ class B; end end quarantine! do # Not clean, leaves cvars lying around to break other specs - it "scopes class var accesses in the caller when called on a Fixnum" do - # Fixnum can take instance vars - Fixnum.class_eval "@@__tmp_instance_eval_spec = 1" + it "scopes class var accesses in the caller when called on an Integer" do + # Integer can take instance vars + Integer.class_eval "@@__tmp_instance_eval_spec = 1" (defined? @@__tmp_instance_eval_spec).should be_nil @@__tmp_instance_eval_spec = 2 1.instance_eval { @@__tmp_instance_eval_spec }.should == 2 - Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec) + Integer.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec) end end diff --git a/ruby/spec/ruby/core/basicobject/instance_exec_spec.rb b/ruby/spec/ruby/core/basicobject/instance_exec_spec.rb index e25482d58..289fdd889 100644 --- a/ruby/spec/ruby/core/basicobject/instance_exec_spec.rb +++ b/ruby/spec/ruby/core/basicobject/instance_exec_spec.rb @@ -85,14 +85,14 @@ def foo end quarantine! do # Not clean, leaves cvars lying around to break other specs - it "scopes class var accesses in the caller when called on a Fixnum" do - # Fixnum can take instance vars - Fixnum.class_eval "@@__tmp_instance_exec_spec = 1" + it "scopes class var accesses in the caller when called on an Integer" do + # Integer can take instance vars + Integer.class_eval "@@__tmp_instance_exec_spec = 1" (defined? @@__tmp_instance_exec_spec).should == nil @@__tmp_instance_exec_spec = 2 1.instance_exec { @@__tmp_instance_exec_spec }.should == 2 - Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec) + Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec) end end diff --git a/ruby/spec/ruby/core/basicobject/singleton_method_added_spec.rb b/ruby/spec/ruby/core/basicobject/singleton_method_added_spec.rb index 8d256e22d..ab6b2a2d1 100644 --- a/ruby/spec/ruby/core/basicobject/singleton_method_added_spec.rb +++ b/ruby/spec/ruby/core/basicobject/singleton_method_added_spec.rb @@ -83,4 +83,63 @@ class << self end ScratchPad.recorded.should == [:singleton_method_added, :new_method_with_define_method] end + + describe "when singleton_method_added is undefined" do + it "raises NoMethodError for a metaclass" do + class BasicObjectSpecs::NoSingletonMethodAdded + class << self + undef_method :singleton_method_added + end + + -> { + def self.foo + end + }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for/) + end + end + + it "raises NoMethodError for a singleton instance" do + object = Object.new + class << object + undef_method :singleton_method_added + + -> { + def foo + end + }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for # { + define_method(:bar) {} + }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for # { + object.define_singleton_method(:baz) {} + }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe| - pipe.puts "a ** 2" - pipe.puts "exit" - pipe.readlines.map(&:chomp) - end - - out[-3..-1].should == ["a ** 2", "100", "exit"] + out = IO.popen([{"IRBRC"=>irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe| + pipe.puts "a ** 2" + pipe.puts "exit" + pipe.readlines.map(&:chomp) end + + out[-3..-1].should == ["a ** 2", "100", "exit"] end end diff --git a/ruby/spec/ruby/core/binding/source_location_spec.rb b/ruby/spec/ruby/core/binding/source_location_spec.rb index e562bc65c..d439c3e39 100644 --- a/ruby/spec/ruby/core/binding/source_location_spec.rb +++ b/ruby/spec/ruby/core/binding/source_location_spec.rb @@ -1,11 +1,9 @@ require_relative '../../spec_helper' require_relative 'fixtures/location' -ruby_version_is "2.6" do - describe "Binding#source_location" do - it "returns an [file, line] pair" do - b = BindingSpecs::LocationMethod::TEST_BINDING - b.source_location.should == [BindingSpecs::LocationMethod::FILE_PATH, 4] - end +describe "Binding#source_location" do + it "returns an [file, line] pair" do + b = BindingSpecs::LocationMethod::TEST_BINDING + b.source_location.should == [BindingSpecs::LocationMethod::FILE_PATH, 4] end end diff --git a/ruby/spec/ruby/core/builtin_constants/builtin_constants_spec.rb b/ruby/spec/ruby/core/builtin_constants/builtin_constants_spec.rb index a5141c300..7c87a970d 100644 --- a/ruby/spec/ruby/core/builtin_constants/builtin_constants_spec.rb +++ b/ruby/spec/ruby/core/builtin_constants/builtin_constants_spec.rb @@ -7,8 +7,8 @@ end describe "RUBY_PATCHLEVEL" do - it "is a Fixnum" do - RUBY_PATCHLEVEL.should be_kind_of(Fixnum) + it "is an Integer" do + RUBY_PATCHLEVEL.should be_kind_of(Integer) end end @@ -34,6 +34,12 @@ it "is a String" do RUBY_PLATFORM.should be_kind_of(String) end + + platform_is :darwin do + it 'ends with the build time kernel major version on darwin' do + RUBY_PLATFORM.should =~ /-darwin\d+$/ + end + end end describe "RUBY_RELEASE_DATE" do @@ -45,7 +51,7 @@ describe "RUBY_REVISION" do ruby_version_is ""..."2.7" do it "is an Integer" do - RUBY_REVISION.should be_kind_of(Fixnum) + RUBY_REVISION.should be_kind_of(Integer) end end diff --git a/ruby/spec/ruby/core/class/allocate_spec.rb b/ruby/spec/ruby/core/class/allocate_spec.rb index c426c38ff..b39622e06 100644 --- a/ruby/spec/ruby/core/class/allocate_spec.rb +++ b/ruby/spec/ruby/core/class/allocate_spec.rb @@ -30,7 +30,7 @@ def initialized? end end - klass.allocate.initialized?.should == false + klass.allocate.should_not.initialized? end it "raises TypeError for #superclass" do diff --git a/ruby/spec/ruby/core/class/initialize_spec.rb b/ruby/spec/ruby/core/class/initialize_spec.rb index 9678d7b37..634875848 100644 --- a/ruby/spec/ruby/core/class/initialize_spec.rb +++ b/ruby/spec/ruby/core/class/initialize_spec.rb @@ -7,7 +7,7 @@ it "raises a TypeError when called on already initialized classes" do ->{ - Fixnum.send :initialize + Integer.send :initialize }.should raise_error(TypeError) ->{ diff --git a/ruby/spec/ruby/core/class/new_spec.rb b/ruby/spec/ruby/core/class/new_spec.rb index 8191ce6a3..93152a83e 100644 --- a/ruby/spec/ruby/core/class/new_spec.rb +++ b/ruby/spec/ruby/core/class/new_spec.rb @@ -95,12 +95,13 @@ def message2; "hello"; end end it "raises a TypeError when given a non-Class" do - error_msg = /superclass must be a Class/ - -> { Class.new("") }.should raise_error(TypeError, error_msg) - -> { Class.new(1) }.should raise_error(TypeError, error_msg) - -> { Class.new(:symbol) }.should raise_error(TypeError, error_msg) - -> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg) - -> { Class.new(Module.new) }.should raise_error(TypeError, error_msg) + error_msg = /superclass must be a.*Class/ + -> { Class.new("") }.should raise_error(TypeError, error_msg) + -> { Class.new(1) }.should raise_error(TypeError, error_msg) + -> { Class.new(:symbol) }.should raise_error(TypeError, error_msg) + -> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg) + -> { Class.new(Module.new) }.should raise_error(TypeError, error_msg) + -> { Class.new(BasicObject.new) }.should raise_error(TypeError, error_msg) end end @@ -126,7 +127,7 @@ def initialized? end end - klass.new.initialized?.should == true + klass.new.should.initialized? klass.new(1, 2, 3).args.should == [1, 2, 3] end diff --git a/ruby/spec/ruby/core/class/subclasses_spec.rb b/ruby/spec/ruby/core/class/subclasses_spec.rb new file mode 100644 index 000000000..ddbcfb02c --- /dev/null +++ b/ruby/spec/ruby/core/class/subclasses_spec.rb @@ -0,0 +1,38 @@ +require_relative '../../spec_helper' +require_relative '../module/fixtures/classes' + +ruby_version_is '3.1' do + describe "Class#subclasses" do + it "returns a list of classes directly inheriting from self" do + assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2]) + end + + it "does not return included modules" do + parent = Class.new + child = Class.new(parent) + mod = Module.new + parent.include(mod) + + assert_subclasses(parent, [child]) + end + + it "does not return singleton classes" do + a = Class.new + + a_obj = a.new + def a_obj.force_singleton_class + 42 + end + + a.subclasses.should_not include(a_obj.singleton_class) + end + + it "has 1 entry per module or class" do + ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq + end + + def assert_subclasses(mod,subclasses) + mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect) + end + end +end diff --git a/ruby/spec/ruby/core/class/superclass_spec.rb b/ruby/spec/ruby/core/class/superclass_spec.rb index deb5a4533..00579238a 100644 --- a/ruby/spec/ruby/core/class/superclass_spec.rb +++ b/ruby/spec/ruby/core/class/superclass_spec.rb @@ -8,7 +8,7 @@ Class.superclass.should == Module Class.new.superclass.should == Object Class.new(String).superclass.should == String - Class.new(Fixnum).superclass.should == Fixnum + Class.new(Integer).superclass.should == Integer end # redmine:567 diff --git a/ruby/spec/ruby/core/comparable/lt_spec.rb b/ruby/spec/ruby/core/comparable/lt_spec.rb index 4db92719e..bca95f8d2 100644 --- a/ruby/spec/ruby/core/comparable/lt_spec.rb +++ b/ruby/spec/ruby/core/comparable/lt_spec.rb @@ -40,4 +40,10 @@ a.should_receive(:<=>).any_number_of_times.and_return(nil) -> { (a < b) }.should raise_error(ArgumentError) end + + it "raises an argument error with a message containing the value" do + -> { ("foo" < 7) }.should raise_error(ArgumentError) { |e| + e.message.should == "comparison of String with 7 failed" + } + end end diff --git a/ruby/spec/ruby/core/complex/comparison_spec.rb b/ruby/spec/ruby/core/complex/comparison_spec.rb new file mode 100644 index 000000000..2a437afb7 --- /dev/null +++ b/ruby/spec/ruby/core/complex/comparison_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../spec_helper' + +describe "Complex#<=>" do + ruby_version_is "2.7" do + it "returns nil if either self or argument has imaginary part" do + (Complex(5, 1) <=> Complex(2)).should be_nil + (Complex(1) <=> Complex(2, 1)).should be_nil + (5 <=> Complex(2, 1)).should be_nil + end + + it "returns nil if argument is not numeric" do + (Complex(5, 1) <=> "cmp").should be_nil + (Complex(1) <=> "cmp").should be_nil + (Complex(1) <=> Object.new).should be_nil + end + + it "returns 0, 1, or -1 if self and argument do not have imaginary part" do + (Complex(5) <=> Complex(2)).should == 1 + (Complex(2) <=> Complex(3)).should == -1 + (Complex(2) <=> Complex(2)).should == 0 + + (Complex(5) <=> 2).should == 1 + (Complex(2) <=> 3).should == -1 + (Complex(2) <=> 2).should == 0 + end + end +end diff --git a/ruby/spec/ruby/core/complex/equal_value_spec.rb b/ruby/spec/ruby/core/complex/equal_value_spec.rb index b1e4f9cfc..ad7236b1b 100644 --- a/ruby/spec/ruby/core/complex/equal_value_spec.rb +++ b/ruby/spec/ruby/core/complex/equal_value_spec.rb @@ -53,7 +53,7 @@ end describe "with Object" do - # Fixnum#==, Float#== and Bignum#== only return booleans - Bug? + # Integer#== and Float#== only return booleans - Bug? it "calls other#== with self" do value = Complex(3, 0) diff --git a/ruby/spec/ruby/core/complex/exponent_spec.rb b/ruby/spec/ruby/core/complex/exponent_spec.rb index bf07c9003..86f827aec 100644 --- a/ruby/spec/ruby/core/complex/exponent_spec.rb +++ b/ruby/spec/ruby/core/complex/exponent_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Complex#**" do - describe "with Fixnum 0" do + describe "with Integer 0" do it "returns Complex(1)" do (Complex(3, 4) ** 0).should eql(Complex(1)) end diff --git a/ruby/spec/ruby/core/complex/finite_spec.rb b/ruby/spec/ruby/core/complex/finite_spec.rb index 718848390..7d9f82404 100644 --- a/ruby/spec/ruby/core/complex/finite_spec.rb +++ b/ruby/spec/ruby/core/complex/finite_spec.rb @@ -2,31 +2,31 @@ describe "Complex#finite?" do it "returns true if magnitude is finite" do - (1+1i).finite?.should == true + (1+1i).should.finite? end it "returns false for positive infinity" do value = Complex(Float::INFINITY, 42) - value.finite?.should == false + value.should_not.finite? end it "returns false for positive complex with infinite imaginary" do value = Complex(1, Float::INFINITY) - value.finite?.should == false + value.should_not.finite? end it "returns false for negative infinity" do value = -Complex(Float::INFINITY, 42) - value.finite?.should == false + value.should_not.finite? end it "returns false for negative complex with infinite imaginary" do value = -Complex(1, Float::INFINITY) - value.finite?.should == false + value.should_not.finite? end it "returns false for NaN" do value = Complex(Float::NAN, Float::NAN) - value.finite?.should == false + value.should_not.finite? end end diff --git a/ruby/spec/ruby/core/complex/spaceship_spec.rb b/ruby/spec/ruby/core/complex/spaceship_spec.rb deleted file mode 100644 index 7b2849a86..000000000 --- a/ruby/spec/ruby/core/complex/spaceship_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require_relative '../../spec_helper' - -describe "Complex#<=>" do - ruby_version_is '2.7' do - it "returns nil if either self or argument has imaginary part" do - (Complex(5, 1) <=> Complex(2)).should be_nil - (Complex(1) <=> Complex(2, 1)).should be_nil - (5 <=> Complex(2, 1)).should be_nil - end - - it "returns nil if argument is not numeric" do - (Complex(5, 1) <=> "cmp").should be_nil - (Complex(1) <=> "cmp").should be_nil - (Complex(1) <=> Object.new).should be_nil - end - - it "returns 0, 1, or -1 if self and argument do not have imaginary part" do - (Complex(5) <=> Complex(2)).should == 1 - (Complex(2) <=> Complex(3)).should == -1 - (Complex(2) <=> Complex(2)).should == 0 - - (Complex(5) <=> 2).should == 1 - (Complex(2) <=> 3).should == -1 - (Complex(2) <=> 2).should == 0 - end - end -end diff --git a/ruby/spec/ruby/core/complex/to_c_spec.rb b/ruby/spec/ruby/core/complex/to_c_spec.rb new file mode 100644 index 000000000..5ce01d9d4 --- /dev/null +++ b/ruby/spec/ruby/core/complex/to_c_spec.rb @@ -0,0 +1,12 @@ +require_relative '../../spec_helper' + +describe "Complex#to_c" do + it "returns self" do + value = Complex(1, 5) + value.to_c.should equal(value) + end + + it 'returns the same value' do + Complex(1, 5).to_c.should == Complex(1, 5) + end +end diff --git a/ruby/spec/ruby/core/complex/to_f_spec.rb b/ruby/spec/ruby/core/complex/to_f_spec.rb index 78e652649..b53471c1f 100644 --- a/ruby/spec/ruby/core/complex/to_f_spec.rb +++ b/ruby/spec/ruby/core/complex/to_f_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Complex#to_f" do - describe "when the imaginary part is Fixnum 0" do + describe "when the imaginary part is Integer 0" do it "returns the result of sending #to_f to the real part" do real = mock_numeric('real') real.should_receive(:to_f).and_return(:f) diff --git a/ruby/spec/ruby/core/complex/to_i_spec.rb b/ruby/spec/ruby/core/complex/to_i_spec.rb index 23134705b..1e78f5ec0 100644 --- a/ruby/spec/ruby/core/complex/to_i_spec.rb +++ b/ruby/spec/ruby/core/complex/to_i_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Complex#to_i" do - describe "when the imaginary part is Fixnum 0" do + describe "when the imaginary part is Integer 0" do it "returns the result of sending #to_i to the real part" do real = mock_numeric('real') real.should_receive(:to_i).and_return(:i) diff --git a/ruby/spec/ruby/core/complex/to_r_spec.rb b/ruby/spec/ruby/core/complex/to_r_spec.rb index 76a69a0b9..455992149 100644 --- a/ruby/spec/ruby/core/complex/to_r_spec.rb +++ b/ruby/spec/ruby/core/complex/to_r_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Complex#to_r" do - describe "when the imaginary part is Fixnum 0" do + describe "when the imaginary part is Integer 0" do it "returns the result of sending #to_r to the real part" do real = mock_numeric('real') real.should_receive(:to_r).and_return(:r) diff --git a/ruby/spec/ruby/core/conditionvariable/broadcast_spec.rb b/ruby/spec/ruby/core/conditionvariable/broadcast_spec.rb new file mode 100644 index 000000000..d88159df2 --- /dev/null +++ b/ruby/spec/ruby/core/conditionvariable/broadcast_spec.rb @@ -0,0 +1,40 @@ +require_relative '../../spec_helper' +require 'thread' + +describe "ConditionVariable#broadcast" do + it "releases all threads waiting in line for this resource" do + m = Mutex.new + cv = ConditionVariable.new + threads = [] + r1 = [] + r2 = [] + + # large number to attempt to cause race conditions + 100.times do |i| + threads << Thread.new(i) do |tid| + m.synchronize do + r1 << tid + cv.wait(m) + r2 << tid + end + end + end + + # wait for all threads to acquire the mutex the first time + Thread.pass until m.synchronize { r1.size == threads.size } + # wait until all threads are sleeping (ie waiting) + Thread.pass until threads.all?(&:stop?) + + r2.should be_empty + m.synchronize do + cv.broadcast + end + + threads.each {|t| t.join } + + # ensure that all threads that enter cv.wait are released + r2.sort.should == r1.sort + # note that order is not specified as broadcast results in a race + # condition on regaining the lock m + end +end diff --git a/ruby/spec/ruby/library/conditionvariable/marshal_dump_spec.rb b/ruby/spec/ruby/core/conditionvariable/marshal_dump_spec.rb similarity index 100% rename from ruby/spec/ruby/library/conditionvariable/marshal_dump_spec.rb rename to ruby/spec/ruby/core/conditionvariable/marshal_dump_spec.rb diff --git a/ruby/spec/ruby/core/conditionvariable/signal_spec.rb b/ruby/spec/ruby/core/conditionvariable/signal_spec.rb new file mode 100644 index 000000000..86383073f --- /dev/null +++ b/ruby/spec/ruby/core/conditionvariable/signal_spec.rb @@ -0,0 +1,77 @@ +require_relative '../../spec_helper' +require 'thread' + +describe "ConditionVariable#signal" do + it "releases the first thread waiting in line for this resource" do + m = Mutex.new + cv = ConditionVariable.new + threads = [] + r1 = [] + r2 = [] + + # large number to attempt to cause race conditions + 100.times do |i| + threads << Thread.new(i) do |tid| + m.synchronize do + r1 << tid + cv.wait(m) + r2 << tid + end + end + end + + # wait for all threads to acquire the mutex the first time + Thread.pass until m.synchronize { r1.size == threads.size } + # wait until all threads are sleeping (ie waiting) + Thread.pass until threads.all?(&:stop?) + + r2.should be_empty + 100.times do |i| + m.synchronize do + cv.signal + end + Thread.pass until r2.size == i+1 + end + + threads.each {|t| t.join } + + # ensure that all the threads that went into the cv.wait are + # released in the same order + r2.should == r1 + end + + it "allows control to be passed between a pair of threads" do + m = Mutex.new + cv = ConditionVariable.new + repeats = 100 + in_synchronize = false + + t1 = Thread.new do + m.synchronize do + in_synchronize = true + repeats.times do + cv.wait(m) + cv.signal + end + end + end + + # Make sure t1 is waiting for a signal before launching t2. + Thread.pass until in_synchronize + Thread.pass until t1.stop? + + t2 = Thread.new do + m.synchronize do + repeats.times do + cv.signal + cv.wait(m) + end + end + end + + # Check that both threads terminated without exception + t1.join + t2.join + m.should_not.locked? + end +end diff --git a/ruby/spec/ruby/core/conditionvariable/wait_spec.rb b/ruby/spec/ruby/core/conditionvariable/wait_spec.rb new file mode 100644 index 000000000..9a68c2b5a --- /dev/null +++ b/ruby/spec/ruby/core/conditionvariable/wait_spec.rb @@ -0,0 +1,175 @@ +require_relative '../../spec_helper' +require 'thread' + +describe "ConditionVariable#wait" do + it "calls #sleep on the given object" do + o = Object.new + o.should_receive(:sleep).with(1234) + + cv = ConditionVariable.new + + cv.wait(o, 1234) + end + + it "can be woken up by ConditionVariable#signal" do + m = Mutex.new + cv = ConditionVariable.new + in_synchronize = false + + th = Thread.new do + m.synchronize do + in_synchronize = true + cv.wait(m) + end + :success + end + + # wait for m to acquire the mutex + Thread.pass until in_synchronize + # wait until th is sleeping (ie waiting) + Thread.pass until th.stop? + + m.synchronize { cv.signal } + th.value.should == :success + end + + it "can be interrupted by Thread#run" do + m = Mutex.new + cv = ConditionVariable.new + in_synchronize = false + + th = Thread.new do + m.synchronize do + in_synchronize = true + cv.wait(m) + end + :success + end + + # wait for m to acquire the mutex + Thread.pass until in_synchronize + # wait until th is sleeping (ie waiting) + Thread.pass until th.stop? + + th.run + th.value.should == :success + end + + it "can be interrupted by Thread#wakeup" do + m = Mutex.new + cv = ConditionVariable.new + in_synchronize = false + + th = Thread.new do + m.synchronize do + in_synchronize = true + cv.wait(m) + end + :success + end + + # wait for m to acquire the mutex + Thread.pass until in_synchronize + # wait until th is sleeping (ie waiting) + Thread.pass until th.stop? + + th.wakeup + th.value.should == :success + end + + it "reacquires the lock even if the thread is killed" do + m = Mutex.new + cv = ConditionVariable.new + in_synchronize = false + owned = nil + + th = Thread.new do + m.synchronize do + in_synchronize = true + begin + cv.wait(m) + ensure + owned = m.owned? + $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned + end + end + end + + # wait for m to acquire the mutex + Thread.pass until in_synchronize + # wait until th is sleeping (ie waiting) + Thread.pass until th.stop? + + th.kill + th.join + + owned.should == true + end + + it "reacquires the lock even if the thread is killed after being signaled" do + m = Mutex.new + cv = ConditionVariable.new + in_synchronize = false + owned = nil + + th = Thread.new do + m.synchronize do + in_synchronize = true + begin + cv.wait(m) + ensure + owned = m.owned? + $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned + end + end + end + + # wait for m to acquire the mutex + Thread.pass until in_synchronize + # wait until th is sleeping (ie waiting) + Thread.pass until th.stop? + + m.synchronize { + cv.signal + # Wait that the thread is blocked on acquiring the Mutex + sleep 0.001 + # Kill the thread, yet the thread should first acquire the Mutex before going on + th.kill + } + + th.join + owned.should == true + end + + it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do + m = Mutex.new + cv = ConditionVariable.new + n_threads = 4 + events = [] + + threads = n_threads.times.map { + Thread.new { + m.synchronize { + events << :t_in_synchronize + cv.wait(m) + } + } + } + + Thread.pass until m.synchronize { events.size } == n_threads + Thread.pass until threads.any?(&:stop?) + m.synchronize do + threads.each { |t| + # Cause interactions with the waiting threads. + # On TruffleRuby, this causes a safepoint which has interesting + # interactions with the ConditionVariable. + bt = t.backtrace + bt.should be_kind_of(Array) + bt.size.should >= 2 + } + end + + cv.broadcast + threads.each(&:join) + end +end diff --git a/ruby/spec/ruby/core/data/constants_spec.rb b/ruby/spec/ruby/core/data/constants_spec.rb index 1b4c0d2df..1d469f923 100644 --- a/ruby/spec/ruby/core/data/constants_spec.rb +++ b/ruby/spec/ruby/core/data/constants_spec.rb @@ -1,15 +1,23 @@ require_relative '../../spec_helper' -describe "Data" do - it "is a subclass of Object" do - suppress_warning do - Data.superclass.should == Object +ruby_version_is ''...'3.0' do + describe "Data" do + it "is a subclass of Object" do + suppress_warning do + Data.superclass.should == Object + end end - end - ruby_version_is "2.5" do it "is deprecated" do -> { Data }.should complain(/constant ::Data is deprecated/) end end end + +ruby_version_is '3.0' do + describe "Data" do + it "does not exist anymore" do + Object.should_not have_constant(:Data) + end + end +end diff --git a/ruby/spec/ruby/core/dir/children_spec.rb b/ruby/spec/ruby/core/dir/children_spec.rb index 8f6e62b46..986c8f38c 100644 --- a/ruby/spec/ruby/core/dir/children_spec.rb +++ b/ruby/spec/ruby/core/dir/children_spec.rb @@ -3,136 +3,140 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -ruby_version_is "2.5" do - describe "Dir.children" do - before :all do - DirSpecs.create_mock_dirs - end +describe "Dir.children" do + before :all do + DirSpecs.create_mock_dirs + end - before :each do - @internal = Encoding.default_internal - end + before :each do + @internal = Encoding.default_internal + end - after :all do - DirSpecs.delete_mock_dirs - end + after :all do + DirSpecs.delete_mock_dirs + end - after :each do - Encoding.default_internal = @internal - end + after :each do + Encoding.default_internal = @internal + end - it "returns an Array of filenames in an existing directory including dotfiles" do - a = Dir.children(DirSpecs.mock_dir).sort + it "returns an Array of filenames in an existing directory including dotfiles" do + a = Dir.children(DirSpecs.mock_dir).sort - a.should == DirSpecs.expected_paths - %w[. ..] + a.should == DirSpecs.expected_paths - %w[. ..] - a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested").sort - a.should == %w|.dotfile.ext directory| - end + a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested").sort + a.should == %w|.dotfile.ext directory| + end - it "calls #to_path on non-String arguments" do - p = mock('path') - p.should_receive(:to_path).and_return(DirSpecs.mock_dir) - Dir.children(p) - end + it "calls #to_path on non-String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir) + Dir.children(p) + end - it "accepts an options Hash" do - a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort - a.should == %w|.dotfile.ext directory| - end + it "accepts an options Hash" do + a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort + a.should == %w|.dotfile.ext directory| + end - it "returns children encoded with the filesystem encoding by default" do - # This spec depends on the locale not being US-ASCII because if it is, the - # children that are not ascii_only? will be BINARY encoded. - children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort - encoding = Encoding.find("filesystem") - encoding = Encoding::BINARY if encoding == Encoding::US_ASCII - platform_is_not :windows do - children.should include("ã“ã‚“ã«ã¡ã¯.txt".force_encoding(encoding)) - end - children.first.encoding.should equal(Encoding.find("filesystem")) + it "returns children encoded with the filesystem encoding by default" do + # This spec depends on the locale not being US-ASCII because if it is, the + # children that are not ascii_only? will be BINARY encoded. + children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort + encoding = Encoding.find("filesystem") + encoding = Encoding::BINARY if encoding == Encoding::US_ASCII + platform_is_not :windows do + children.should include("ã“ã‚“ã«ã¡ã¯.txt".force_encoding(encoding)) end + children.first.encoding.should equal(Encoding.find("filesystem")) + end - it "returns children encoded with the specified encoding" do - dir = File.join(DirSpecs.mock_dir, 'special') - children = Dir.children(dir, encoding: "euc-jp").sort - children.first.encoding.should equal(Encoding::EUC_JP) - end + it "returns children encoded with the specified encoding" do + dir = File.join(DirSpecs.mock_dir, 'special') + children = Dir.children(dir, encoding: "euc-jp").sort + children.first.encoding.should equal(Encoding::EUC_JP) + end - it "returns children transcoded to the default internal encoding" do - Encoding.default_internal = Encoding::EUC_KR - children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort - children.first.encoding.should equal(Encoding::EUC_KR) - end + it "returns children transcoded to the default internal encoding" do + Encoding.default_internal = Encoding::EUC_KR + children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort + children.first.encoding.should equal(Encoding::EUC_KR) + end - it "raises a SystemCallError if called with a nonexistent directory" do - -> { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError) - end + it "raises a SystemCallError if called with a nonexistent directory" do + -> { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError) end end -ruby_version_is "2.6" do - describe "Dir#children" do - before :all do - DirSpecs.create_mock_dirs - end +describe "Dir#children" do + before :all do + DirSpecs.create_mock_dirs + end - before :each do - @internal = Encoding.default_internal - end + before :each do + @internal = Encoding.default_internal + end - after :all do - DirSpecs.delete_mock_dirs - end + after :all do + DirSpecs.delete_mock_dirs + end - after :each do - Encoding.default_internal = @internal - @dir.close if @dir - end + after :each do + Encoding.default_internal = @internal + @dir.close if @dir + end - it "returns an Array of filenames in an existing directory including dotfiles" do - @dir = Dir.new(DirSpecs.mock_dir) - a = @dir.children.sort - @dir.close + it "returns an Array of filenames in an existing directory including dotfiles" do + @dir = Dir.new(DirSpecs.mock_dir) + a = @dir.children.sort + @dir.close - a.should == DirSpecs.expected_paths - %w[. ..] + a.should == DirSpecs.expected_paths - %w[. ..] - @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested") - a = @dir.children.sort - a.should == %w|.dotfile.ext directory| - end + @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested") + a = @dir.children.sort + a.should == %w|.dotfile.ext directory| + end - it "accepts an options Hash" do - @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8") - a = @dir.children.sort - a.should == %w|.dotfile.ext directory| - end + it "accepts an encoding keyword for the encoding of the entries" do + @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8") + dirs = @dir.to_a.sort + dirs.each { |d| d.encoding.should == Encoding::UTF_8 } + end - it "returns children encoded with the filesystem encoding by default" do - # This spec depends on the locale not being US-ASCII because if it is, the - # children that are not ascii_only? will be BINARY encoded. - @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special')) - children = @dir.children.sort - encoding = Encoding.find("filesystem") - encoding = Encoding::BINARY if encoding == Encoding::US_ASCII - platform_is_not :windows do - children.should include("ã“ã‚“ã«ã¡ã¯.txt".force_encoding(encoding)) - end - children.first.encoding.should equal(Encoding.find("filesystem")) + ruby_version_is ""..."2.7" do + it "accepts nil options" do + @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", nil) + dirs = @dir.to_a.sort + dirs.each { |d| d.encoding.should == Encoding.find("filesystem") } end + end - it "returns children encoded with the specified encoding" do - path = File.join(DirSpecs.mock_dir, 'special') - @dir = Dir.new(path, encoding: "euc-jp") - children = @dir.children.sort - children.first.encoding.should equal(Encoding::EUC_JP) - end + it "returns children encoded with the filesystem encoding by default" do + # This spec depends on the locale not being US-ASCII because if it is, the + # children that are not ascii_only? will be BINARY encoded. + @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special')) + children = @dir.children.sort + encoding = Encoding.find("filesystem") + encoding = Encoding::BINARY if encoding == Encoding::US_ASCII + platform_is_not :windows do + children.should include("ã“ã‚“ã«ã¡ã¯.txt".force_encoding(encoding)) + end + children.first.encoding.should equal(Encoding.find("filesystem")) + end - it "returns children transcoded to the default internal encoding" do - Encoding.default_internal = Encoding::EUC_KR - @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special')) - children = @dir.children.sort - children.first.encoding.should equal(Encoding::EUC_KR) - end + it "returns children encoded with the specified encoding" do + path = File.join(DirSpecs.mock_dir, 'special') + @dir = Dir.new(path, encoding: "euc-jp") + children = @dir.children.sort + children.first.encoding.should equal(Encoding::EUC_JP) + end + + it "returns children transcoded to the default internal encoding" do + Encoding.default_internal = Encoding::EUC_KR + @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special')) + children = @dir.children.sort + children.first.encoding.should equal(Encoding::EUC_KR) end end diff --git a/ruby/spec/ruby/core/dir/each_child_spec.rb b/ruby/spec/ruby/core/dir/each_child_spec.rb index dcc9a456c..f7980991e 100644 --- a/ruby/spec/ruby/core/dir/each_child_spec.rb +++ b/ruby/spec/ruby/core/dir/each_child_spec.rb @@ -1,103 +1,111 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -ruby_version_is "2.5" do - describe "Dir.each_child" do - before :all do - DirSpecs.create_mock_dirs - end +describe "Dir.each_child" do + before :all do + DirSpecs.create_mock_dirs + end + + after :all do + DirSpecs.delete_mock_dirs + end - after :all do - DirSpecs.delete_mock_dirs + it "accepts an encoding keyword for the encoding of the entries" do + dirs = Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding::UTF_8} + end + + ruby_version_is ""..."2.7" do + it "accepts nil options" do + dirs = Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")} end + end - it "yields all names in an existing directory to the provided block" do - a, b = [], [] + it "yields all names in an existing directory to the provided block" do + a, b = [], [] - Dir.each_child(DirSpecs.mock_dir) {|f| a << f} - Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested") {|f| b << f} + Dir.each_child(DirSpecs.mock_dir) {|f| a << f} + Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested") {|f| b << f} - a.sort.should == DirSpecs.expected_paths - %w[. ..] - b.sort.should == %w|.dotfile.ext directory| - end + a.sort.should == DirSpecs.expected_paths - %w[. ..] + b.sort.should == %w|.dotfile.ext directory| + end - it "returns nil when successful" do - Dir.each_child(DirSpecs.mock_dir) {|f| f}.should == nil - end + it "returns nil when successful" do + Dir.each_child(DirSpecs.mock_dir) {|f| f}.should == nil + end - it "calls #to_path on non-String arguments" do - p = mock('path') - p.should_receive(:to_path).and_return(DirSpecs.mock_dir) - Dir.each_child(p).to_a - end + it "calls #to_path on non-String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir) + Dir.each_child(p).to_a + end - it "raises a SystemCallError if passed a nonexistent directory" do - -> { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError) - end + it "raises a SystemCallError if passed a nonexistent directory" do + -> { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError) + end - describe "when no block is given" do - it "returns an Enumerator" do - Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator) - Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..] - end + describe "when no block is given" do + it "returns an Enumerator" do + Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator) + Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..] + end - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - Dir.each_child(DirSpecs.mock_dir).size.should == nil - end + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + Dir.each_child(DirSpecs.mock_dir).size.should == nil end end end end end -ruby_version_is "2.6" do - describe "Dir#each_child" do - before :all do - DirSpecs.create_mock_dirs - end +describe "Dir#each_child" do + before :all do + DirSpecs.create_mock_dirs + end - after :all do - DirSpecs.delete_mock_dirs - end + after :all do + DirSpecs.delete_mock_dirs + end - after :each do - @dir.close if @dir - end + after :each do + @dir.close if @dir + end - it "yields all names in an existing directory to the provided block" do - a, b = [], [] - @dir = Dir.new(DirSpecs.mock_dir) - @dir2 = Dir.new("#{DirSpecs.mock_dir}/deeply/nested") + it "yields all names in an existing directory to the provided block" do + a, b = [], [] + @dir = Dir.new(DirSpecs.mock_dir) + @dir2 = Dir.new("#{DirSpecs.mock_dir}/deeply/nested") - @dir.each_child { |f| a << f } - @dir2.each_child { |f| b << f } - @dir2.close + @dir.each_child { |f| a << f } + @dir2.each_child { |f| b << f } + @dir2.close - a.sort.should == DirSpecs.expected_paths - %w|. ..| - b.sort.should == %w|.dotfile.ext directory| - end + a.sort.should == DirSpecs.expected_paths - %w|. ..| + b.sort.should == %w|.dotfile.ext directory| + end - it "returns self when successful" do - @dir = Dir.new(DirSpecs.mock_dir) - @dir.each_child { |f| f }.should == @dir - end + it "returns self when successful" do + @dir = Dir.new(DirSpecs.mock_dir) + @dir.each_child { |f| f }.should == @dir + end - describe "when no block is given" do - it "returns an Enumerator" do - @dir = Dir.new(DirSpecs.mock_dir) + describe "when no block is given" do + it "returns an Enumerator" do + @dir = Dir.new(DirSpecs.mock_dir) - @dir.each_child.should be_an_instance_of(Enumerator) - @dir.each_child.to_a.sort.should == DirSpecs.expected_paths - %w|. ..| - end + @dir.each_child.should be_an_instance_of(Enumerator) + @dir.each_child.to_a.sort.should == DirSpecs.expected_paths - %w|. ..| + end - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - @dir = Dir.new(DirSpecs.mock_dir) - @dir.each_child.size.should == nil - end + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + @dir = Dir.new(DirSpecs.mock_dir) + @dir.each_child.size.should == nil end end end diff --git a/ruby/spec/ruby/core/dir/entries_spec.rb b/ruby/spec/ruby/core/dir/entries_spec.rb index 33568b6fc..9aa58657d 100644 --- a/ruby/spec/ruby/core/dir/entries_spec.rb +++ b/ruby/spec/ruby/core/dir/entries_spec.rb @@ -35,9 +35,16 @@ Dir.entries(p) end - it "accepts an options Hash" do - a = Dir.entries("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort - a.should == %w|. .. .dotfile.ext directory| + it "accepts an encoding keyword for the encoding of the entries" do + dirs = Dir.entries("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding::UTF_8} + end + + ruby_version_is ""..."2.7" do + it "accepts nil options" do + dirs = Dir.entries("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")} + end end it "returns entries encoded with the filesystem encoding by default" do diff --git a/ruby/spec/ruby/core/dir/exists_spec.rb b/ruby/spec/ruby/core/dir/exists_spec.rb deleted file mode 100644 index 2c6f145db..000000000 --- a/ruby/spec/ruby/core/dir/exists_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' -require_relative 'shared/exist' - -describe "Dir.exists?" do - before :all do - DirSpecs.create_mock_dirs - end - - after :all do - DirSpecs.delete_mock_dirs - end - - it_behaves_like :dir_exist, :exists? -end diff --git a/ruby/spec/ruby/core/dir/fileno_spec.rb b/ruby/spec/ruby/core/dir/fileno_spec.rb index 504e36d44..bb84ef537 100644 --- a/ruby/spec/ruby/core/dir/fileno_spec.rb +++ b/ruby/spec/ruby/core/dir/fileno_spec.rb @@ -27,7 +27,7 @@ if has_dir_fileno it "returns the file descriptor of the dir" do - @dir.fileno.should be_kind_of(Fixnum) + @dir.fileno.should be_kind_of(Integer) end else it "raises an error when not implemented on the platform" do diff --git a/ruby/spec/ruby/core/dir/fixtures/common.rb b/ruby/spec/ruby/core/dir/fixtures/common.rb index f6708b04f..c32b05681 100644 --- a/ruby/spec/ruby/core/dir/fixtures/common.rb +++ b/ruby/spec/ruby/core/dir/fixtures/common.rb @@ -22,7 +22,7 @@ def self.clear_dirs [0xe9].pack('U') ].each do |dir| begin - Dir.rmdir dir + Dir.rmdir mock_dir(dir) rescue end end @@ -36,6 +36,8 @@ def self.mock_dir_files .dotfile .dotsubdir/.dotfile .dotsubdir/nondotfile + nested/.dotsubir/.dotfile + nested/.dotsubir/nondotfile deeply/.dotfile deeply/nested/.dotfile.ext @@ -79,6 +81,7 @@ def self.mock_dir_files special/} special/test{1}/file[1] + special/{}/special ] platform_is_not :windows do @@ -89,6 +92,7 @@ def self.mock_dir_files special/| special/ã“ã‚“ã«ã¡ã¯.txt + special/\a ] end end @@ -160,10 +164,21 @@ def self.expected_paths dir_filename_ordering file_one.ext file_two.ext + nested nondotfile special subdir_one subdir_two ] end + + if RUBY_VERSION > '3.1' + def self.expected_glob_paths + expected_paths - ['..'] + end + else + def self.expected_glob_paths + expected_paths + end + end end diff --git a/ruby/spec/ruby/core/dir/foreach_spec.rb b/ruby/spec/ruby/core/dir/foreach_spec.rb index 1560b85f8..c3ddb27a8 100644 --- a/ruby/spec/ruby/core/dir/foreach_spec.rb +++ b/ruby/spec/ruby/core/dir/foreach_spec.rb @@ -39,6 +39,18 @@ Dir.foreach(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths end + it "accepts an encoding keyword for the encoding of the entries" do + dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding::UTF_8} + end + + ruby_version_is ""..."2.7" do + it "accepts nil options" do + dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort + dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")} + end + end + describe "when no block is given" do it "returns an Enumerator" do Dir.foreach(DirSpecs.mock_dir).should be_an_instance_of(Enumerator) diff --git a/ruby/spec/ruby/core/dir/glob_spec.rb b/ruby/spec/ruby/core/dir/glob_spec.rb index 4b437b0e2..295a7ab92 100644 --- a/ruby/spec/ruby/core/dir/glob_spec.rb +++ b/ruby/spec/ruby/core/dir/glob_spec.rb @@ -29,6 +29,23 @@ %w!file_one.ext file_two.ext! end + it 'returns matching file paths when supplied :base keyword argument' do + dir = tmp('dir_glob_base') + file_1 = "#{dir}/lib/bloop.rb" + file_2 = "#{dir}/lib/soup.rb" + file_3 = "#{dir}/lib/mismatched_file_type.txt" + file_4 = "#{dir}/mismatched_directory.rb" + + touch file_1 + touch file_2 + touch file_3 + touch file_4 + + Dir.glob('**/*.rb', base: "#{dir}/lib").sort.should == ["bloop.rb", "soup.rb"].sort + ensure + rm_r dir + end + it "calls #to_path to convert multiple patterns" do pat1 = mock('file_one.ext') pat1.should_receive(:to_path).and_return('file_one.ext') @@ -39,7 +56,7 @@ end it "matches both dot and non-dotfiles with '*' and option File::FNM_DOTMATCH" do - Dir.glob('*', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_paths + Dir.glob('*', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_glob_paths end it "matches files with any beginning with '*' and option File::FNM_DOTMATCH" do @@ -47,7 +64,7 @@ end it "matches any files in the current directory with '**' and option File::FNM_DOTMATCH" do - Dir.glob('**', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_paths + Dir.glob('**', File::FNM_DOTMATCH).sort.should == DirSpecs.expected_glob_paths end it "recursively matches any subdirectories except './' or '../' with '**/' from the current directory and option File::FNM_DOTMATCH" do @@ -59,8 +76,11 @@ deeply/nested/directory/ deeply/nested/directory/structure/ dir/ + nested/ + nested/.dotsubir/ special/ special/test{1}/ + special/{}/ subdir_one/ subdir_two/ ] @@ -68,6 +88,33 @@ Dir.glob('**/', File::FNM_DOTMATCH).sort.should == expected end + ruby_version_is ''...'3.1' do + it "recursively matches files and directories in nested dot subdirectory with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do + expected = %w[ + nested/. + nested/.dotsubir + nested/.dotsubir/. + nested/.dotsubir/.dotfile + nested/.dotsubir/nondotfile + ] + + Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort + end + end + + ruby_version_is '3.1' do + it "recursively matches files and directories in nested dot subdirectory except . with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do + expected = %w[ + nested/. + nested/.dotsubir + nested/.dotsubir/.dotfile + nested/.dotsubir/nondotfile + ] + + Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort + end + end + # This is a separate case to check **/ coming after a constant # directory as well. it "recursively matches any subdirectories except './' or '../' with '**/' and option File::FNM_DOTMATCH" do @@ -80,8 +127,11 @@ ./deeply/nested/directory/ ./deeply/nested/directory/structure/ ./dir/ + ./nested/ + ./nested/.dotsubir/ ./special/ ./special/test{1}/ + ./special/{}/ ./subdir_one/ ./subdir_two/ ] @@ -102,6 +152,14 @@ Dir.glob('{deeply/**/,subdir_two/*}').sort.should == expected end + it "preserves multiple /s before a **" do + expected = %w[ + deeply//nested/directory/structure + ] + + Dir.glob('{deeply//**/structure}').sort.should == expected + end + it "accepts a block and yields it with each elements" do ary = [] ret = Dir.glob(["file_o*", "file_t*"]) { |t| ary << t } @@ -119,7 +177,7 @@ end it "handles infinite directory wildcards" do - Dir.glob('**/**/**').empty?.should == false + Dir.glob('**/**/**').should_not.empty? end it "handles simple filename patterns" do diff --git a/ruby/spec/ruby/core/dir/home_spec.rb b/ruby/spec/ruby/core/dir/home_spec.rb index cdfc9346d..713ba9db9 100644 --- a/ruby/spec/ruby/core/dir/home_spec.rb +++ b/ruby/spec/ruby/core/dir/home_spec.rb @@ -17,7 +17,7 @@ end it "returns a non-frozen string" do - Dir.home.frozen?.should == false + Dir.home.should_not.frozen? end end @@ -28,14 +28,14 @@ end end - platform_is_not :windows, :solaris do + platform_is_not :windows, :solaris, :android do it "returns the named user's home directory, from the user database" do Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp end end it "returns a non-frozen string" do - Dir.home(ENV['USER']).frozen?.should == false + Dir.home(ENV['USER']).should_not.frozen? end end diff --git a/ruby/spec/ruby/core/dir/mkdir_spec.rb b/ruby/spec/ruby/core/dir/mkdir_spec.rb index c6e2f164e..0ed28f5a9 100644 --- a/ruby/spec/ruby/core/dir/mkdir_spec.rb +++ b/ruby/spec/ruby/core/dir/mkdir_spec.rb @@ -13,29 +13,33 @@ it "creates the named directory with the given permissions" do DirSpecs.clear_dirs + nonexisting = DirSpecs.mock_dir('nonexisting') + default_perms = DirSpecs.mock_dir('default_perms') + reduced = DirSpecs.mock_dir('reduced') begin - File.should_not.exist?('nonexisting') - Dir.mkdir 'nonexisting' - File.should.exist?('nonexisting') + File.should_not.exist?(nonexisting) + Dir.mkdir nonexisting + File.should.exist?(nonexisting) platform_is_not :windows do - Dir.mkdir 'default_perms' - a = File.stat('default_perms').mode - Dir.mkdir 'reduced', (a - 1) - File.stat('reduced').mode.should_not == a + Dir.mkdir default_perms + a = File.stat(default_perms).mode + Dir.mkdir reduced, (a - 1) + File.stat(reduced).mode.should_not == a end platform_is :windows do - Dir.mkdir 'default_perms', 0666 - a = File.stat('default_perms').mode - Dir.mkdir 'reduced', 0444 - File.stat('reduced').mode.should_not == a + Dir.mkdir default_perms, 0666 + a = File.stat(default_perms).mode + Dir.mkdir reduced, 0444 + File.stat(reduced).mode.should_not == a end - Dir.mkdir('always_returns_0').should == 0 + always_returns_0 = DirSpecs.mock_dir('always_returns_0') + Dir.mkdir(always_returns_0).should == 0 platform_is_not(:windows) do - File.chmod(0777, "nonexisting","default_perms","reduced","always_returns_0") + File.chmod(0777, nonexisting, default_perms, reduced, always_returns_0) end platform_is_not(:windows) do - File.chmod(0644, "nonexisting","default_perms","reduced","always_returns_0") + File.chmod(0644, nonexisting, default_perms, reduced, always_returns_0) end ensure DirSpecs.clear_dirs @@ -45,7 +49,7 @@ it "calls #to_path on non-String arguments" do DirSpecs.clear_dirs p = mock('path') - p.should_receive(:to_path).and_return('nonexisting') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting')) Dir.mkdir(p) DirSpecs.clear_dirs end diff --git a/ruby/spec/ruby/core/dir/shared/glob.rb b/ruby/spec/ruby/core/dir/shared/glob.rb index b47e23b41..a38ff8aa6 100644 --- a/ruby/spec/ruby/core/dir/shared/glob.rb +++ b/ruby/spec/ruby/core/dir/shared/glob.rb @@ -23,14 +23,7 @@ Dir.send(@method, obj).should == %w[file_one.ext] end - ruby_version_is ""..."2.6" do - it "splits the string on \\0 if there is only one string given" do - Dir.send(@method, "file_o*\0file_t*").should == - %w!file_one.ext file_two.ext! - end - end - - ruby_version_is "2.6"..."2.7" do + ruby_version_is ""..."2.7" do it "splits the string on \\0 if there is only one string given and warns" do -> { Dir.send(@method, "file_o*\0file_t*").should == @@ -45,6 +38,44 @@ end end + ruby_version_is "3.0" do + it "result is sorted by default" do + result = Dir.send(@method, '*') + result.should == result.sort + end + + it "result is sorted with sort: true" do + result = Dir.send(@method, '*', sort: true) + result.should == result.sort + end + + it "sort: false returns same files" do + result = Dir.send(@method,'*', sort: false) + result.sort.should == Dir.send(@method, '*').sort + end + end + + ruby_version_is "3.0"..."3.1" do + it "result is sorted with any non false value of sort:" do + result = Dir.send(@method, '*', sort: 0) + result.should == result.sort + + result = Dir.send(@method, '*', sort: nil) + result.should == result.sort + + result = Dir.send(@method, '*', sort: 'false') + result.should == result.sort + end + end + + ruby_version_is "3.1" do + it "raises an ArgumentError if sort: is not true or false" do + -> { Dir.send(@method, '*', sort: 0) }.should raise_error ArgumentError, /expected true or false/ + -> { Dir.send(@method, '*', sort: nil) }.should raise_error ArgumentError, /expected true or false/ + -> { Dir.send(@method, '*', sort: 'false') }.should raise_error ArgumentError, /expected true or false/ + end + end + it "matches non-dotfiles with '*'" do expected = %w[ brace @@ -53,6 +84,7 @@ dir_filename_ordering file_one.ext file_two.ext + nested nondotfile special subdir_one @@ -70,6 +102,10 @@ Dir.send(@method, 'special/+').should == ['special/+'] end + it "matches directories with special characters when escaped" do + Dir.send(@method, 'special/\{}/special').should == ["special/{}/special"] + end + platform_is_not :windows do it "matches regexp special *" do Dir.send(@method, 'special/\*').should == ['special/*'] @@ -82,6 +118,10 @@ it "matches regexp special |" do Dir.send(@method, 'special/|').should == ['special/|'] end + + it "matches files with backslashes in their name" do + Dir.glob('special/\\\\{a,b}').should == ['special/\a'] + end end it "matches regexp special ^" do @@ -120,8 +160,16 @@ Dir.send(@method, 'special/test\{1\}/*').should == ['special/test{1}/file[1]'] end - it "matches dotfiles with '.*'" do - Dir.send(@method, '.*').sort.should == %w|. .. .dotfile .dotsubdir|.sort + ruby_version_is ''...'3.1' do + it "matches dotfiles with '.*'" do + Dir.send(@method, '.*').sort.should == %w|. .. .dotfile .dotsubdir|.sort + end + end + + ruby_version_is '3.1' do + it "matches dotfiles except .. with '.*'" do + Dir.send(@method, '.*').sort.should == %w|. .dotfile .dotsubdir|.sort + end end it "matches non-dotfiles with '*'" do @@ -156,6 +204,7 @@ dir_filename_ordering file_one.ext file_two.ext + nested nondotfile special subdir_one @@ -165,8 +214,16 @@ Dir.send(@method, '**').sort.should == expected end - it "matches dotfiles in the current directory with '.**'" do - Dir.send(@method, '.**').sort.should == %w|. .. .dotsubdir .dotfile|.sort + ruby_version_is ''...'3.1' do + it "matches dotfiles in the current directory with '.**'" do + Dir.send(@method, '.**').sort.should == %w|. .. .dotsubdir .dotfile|.sort + end + end + + ruby_version_is '3.1' do + it "matches dotfiles in the current directory except .. with '.**'" do + Dir.send(@method, '.**').sort.should == %w|. .dotsubdir .dotfile|.sort + end end it "recursively matches any nondot subdirectories with '**/'" do @@ -177,8 +234,10 @@ deeply/nested/directory/ deeply/nested/directory/structure/ dir/ + nested/ special/ special/test{1}/ + special/{}/ subdir_one/ subdir_two/ ] @@ -186,9 +245,27 @@ Dir.send(@method, '**/').sort.should == expected end - it "recursively matches any subdirectories including ./ and ../ with '.**/'" do - Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do - Dir.send(@method, '.**/').sort.should == %w|./ ../|.sort + it "recursively matches any subdirectories except './' or '../' with '**/' from the base directory if that is specified" do + expected = %w[ + nested/directory + ] + + Dir.send(@method, '**/*ory', base: 'deeply').sort.should == expected + end + + ruby_version_is ''...'3.1' do + it "recursively matches any subdirectories including ./ and ../ with '.**/'" do + Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do + Dir.send(@method, '.**/').sort.should == %w|./ ../|.sort + end + end + end + + ruby_version_is '3.1' do + it "recursively matches any subdirectories including ./ with '.**/'" do + Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do + Dir.send(@method, '.**/').should == ['./'] + end end end @@ -231,7 +308,7 @@ end it "matches dot or non-dotfiles with '{,.}*'" do - Dir.send(@method, '{,.}*').sort.should == DirSpecs.expected_paths + Dir.send(@method, '{,.}*').sort.should == DirSpecs.expected_glob_paths end it "respects the order of {} expressions, expanding left most first" do @@ -291,74 +368,72 @@ end end - ruby_version_is "2.5" do - context ":base option passed" do - before :each do - @mock_dir = File.expand_path tmp('dir_glob_mock') - - %w[ - a/b/x - a/b/c/y - a/b/c/d/z - ].each do |path| - file = File.join @mock_dir, path - mkdir_p File.dirname(file) - touch file - end - end + context ":base option passed" do + before :each do + @mock_dir = File.expand_path tmp('dir_glob_mock') - after :each do - rm_r @mock_dir + %w[ + a/b/x + a/b/c/y + a/b/c/d/z + ].each do |path| + file = File.join @mock_dir, path + mkdir_p File.dirname(file) + touch file end + end - it "matches entries only from within the specified directory" do - path = File.join(@mock_dir, "a/b/c") - Dir.send(@method, "*", base: path).sort.should == %w( d y ) - end + after :each do + rm_r @mock_dir + end - it "accepts both relative and absolute paths" do - require 'pathname' + it "matches entries only from within the specified directory" do + path = File.join(@mock_dir, "a/b/c") + Dir.send(@method, "*", base: path).sort.should == %w( d y ) + end - path_abs = File.join(@mock_dir, "a/b/c") - path_rel = Pathname.new(path_abs).relative_path_from(Pathname.new(Dir.pwd)) + it "accepts both relative and absolute paths" do + require 'pathname' - result_abs = Dir.send(@method, "*", base: path_abs).sort - result_rel = Dir.send(@method, "*", base: path_rel).sort + path_abs = File.join(@mock_dir, "a/b/c") + path_rel = Pathname.new(path_abs).relative_path_from(Pathname.new(Dir.pwd)) - result_abs.should == %w( d y ) - result_rel.should == %w( d y ) - end + result_abs = Dir.send(@method, "*", base: path_abs).sort + result_rel = Dir.send(@method, "*", base: path_rel).sort - it "returns [] if specified path does not exist" do - path = File.join(@mock_dir, "fake-name") - File.should_not.exist?(path) + result_abs.should == %w( d y ) + result_rel.should == %w( d y ) + end - Dir.send(@method, "*", base: path).should == [] - end + it "returns [] if specified path does not exist" do + path = File.join(@mock_dir, "fake-name") + File.should_not.exist?(path) + + Dir.send(@method, "*", base: path).should == [] + end - it "returns [] if specified path is a file" do - path = File.join(@mock_dir, "a/b/x") - File.should.exist?(path) + it "returns [] if specified path is a file" do + path = File.join(@mock_dir, "a/b/x") + File.should.exist?(path) - Dir.send(@method, "*", base: path).should == [] - end + Dir.send(@method, "*", base: path).should == [] + end - it "raises TypeError when cannot convert value to string" do - -> { - Dir.send(@method, "*", base: []) - }.should raise_error(TypeError) - end + it "raises TypeError when cannot convert value to string" do + -> { + Dir.send(@method, "*", base: []) + }.should raise_error(TypeError) + end - it "handles '' as current directory path" do - Dir.chdir @mock_dir do - Dir.send(@method, "*", base: "").should == %w( a ) - end + it "handles '' as current directory path" do + Dir.chdir @mock_dir do + Dir.send(@method, "*", base: "").should == %w( a ) end + end - it "handles nil as current directory path" do - Dir.chdir @mock_dir do - Dir.send(@method, "*", base: nil).should == %w( a ) - end + it "handles nil as current directory path" do + Dir.chdir @mock_dir do + Dir.send(@method, "*", base: nil).should == %w( a ) end end end diff --git a/ruby/spec/ruby/core/dir/shared/open.rb b/ruby/spec/ruby/core/dir/shared/open.rb index 76b08dc28..920845cba 100644 --- a/ruby/spec/ruby/core/dir/shared/open.rb +++ b/ruby/spec/ruby/core/dir/shared/open.rb @@ -66,7 +66,7 @@ Dir.send(@method, DirSpecs.mock_dir) do |dir| io = IO.for_fd(dir.fileno) io.autoclose = false - io.close_on_exec?.should == true + io.should.close_on_exec? end end end diff --git a/ruby/spec/ruby/core/encoding/compatible_spec.rb b/ruby/spec/ruby/core/encoding/compatible_spec.rb index dc47a6553..80ecab615 100644 --- a/ruby/spec/ruby/core/encoding/compatible_spec.rb +++ b/ruby/spec/ruby/core/encoding/compatible_spec.rb @@ -54,7 +54,7 @@ it "returns nil if the second's Encoding is not ASCII compatible" do a = "abc".force_encoding("UTF-8") - b = "123".force_encoding("UTF-16LE") + b = "1234".force_encoding("UTF-16LE") Encoding.compatible?(a, b).should be_nil end end diff --git a/ruby/spec/ruby/core/encoding/converter/constants_spec.rb b/ruby/spec/ruby/core/encoding/converter/constants_spec.rb index 57b6a4d4e..7d29bdb27 100644 --- a/ruby/spec/ruby/core/encoding/converter/constants_spec.rb +++ b/ruby/spec/ruby/core/encoding/converter/constants_spec.rb @@ -5,8 +5,8 @@ Encoding::Converter.should have_constant(:INVALID_MASK) end - it "has a Fixnum value" do - Encoding::Converter::INVALID_MASK.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::INVALID_MASK.should be_an_instance_of(Integer) end end @@ -15,8 +15,8 @@ Encoding::Converter.should have_constant(:INVALID_REPLACE) end - it "has a Fixnum value" do - Encoding::Converter::INVALID_REPLACE.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::INVALID_REPLACE.should be_an_instance_of(Integer) end end @@ -25,8 +25,8 @@ Encoding::Converter.should have_constant(:UNDEF_MASK) end - it "has a Fixnum value" do - Encoding::Converter::UNDEF_MASK.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::UNDEF_MASK.should be_an_instance_of(Integer) end end @@ -35,8 +35,8 @@ Encoding::Converter.should have_constant(:UNDEF_REPLACE) end - it "has a Fixnum value" do - Encoding::Converter::UNDEF_REPLACE.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::UNDEF_REPLACE.should be_an_instance_of(Integer) end end @@ -45,8 +45,8 @@ Encoding::Converter.should have_constant(:UNDEF_HEX_CHARREF) end - it "has a Fixnum value" do - Encoding::Converter::UNDEF_HEX_CHARREF.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::UNDEF_HEX_CHARREF.should be_an_instance_of(Integer) end end @@ -55,8 +55,8 @@ Encoding::Converter.should have_constant(:PARTIAL_INPUT) end - it "has a Fixnum value" do - Encoding::Converter::PARTIAL_INPUT.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::PARTIAL_INPUT.should be_an_instance_of(Integer) end end @@ -65,8 +65,8 @@ Encoding::Converter.should have_constant(:AFTER_OUTPUT) end - it "has a Fixnum value" do - Encoding::Converter::AFTER_OUTPUT.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::AFTER_OUTPUT.should be_an_instance_of(Integer) end end @@ -75,8 +75,8 @@ Encoding::Converter.should have_constant(:UNIVERSAL_NEWLINE_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should be_an_instance_of(Integer) end end @@ -85,8 +85,8 @@ Encoding::Converter.should have_constant(:CRLF_NEWLINE_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::CRLF_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::CRLF_NEWLINE_DECORATOR.should be_an_instance_of(Integer) end end @@ -95,8 +95,8 @@ Encoding::Converter.should have_constant(:CR_NEWLINE_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::CR_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::CR_NEWLINE_DECORATOR.should be_an_instance_of(Integer) end end @@ -105,8 +105,8 @@ Encoding::Converter.should have_constant(:XML_TEXT_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::XML_TEXT_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::XML_TEXT_DECORATOR.should be_an_instance_of(Integer) end end @@ -115,8 +115,8 @@ Encoding::Converter.should have_constant(:XML_ATTR_CONTENT_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should be_an_instance_of(Integer) end end @@ -125,7 +125,7 @@ Encoding::Converter.should have_constant(:XML_ATTR_QUOTE_DECORATOR) end - it "has a Fixnum value" do - Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should be_an_instance_of(Fixnum) + it "has an Integer value" do + Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should be_an_instance_of(Integer) end end diff --git a/ruby/spec/ruby/core/encoding/converter/new_spec.rb b/ruby/spec/ruby/core/encoding/converter/new_spec.rb index 9fc97263f..1f7affc72 100644 --- a/ruby/spec/ruby/core/encoding/converter/new_spec.rb +++ b/ruby/spec/ruby/core/encoding/converter/new_spec.rb @@ -47,7 +47,7 @@ conv.replacement.should == "fubar" end - it "calls #to_hash to convert the options argument to a Hash if not a Fixnum" do + it "calls #to_hash to convert the options argument to a Hash if not an Integer" do opts = mock("encoding converter options") opts.should_receive(:to_hash).and_return({ replace: "fubar" }) conv = Encoding::Converter.new("us-ascii", "utf-8", **opts) @@ -82,7 +82,7 @@ end.should raise_error(TypeError) end - it "raises a TypeError if passed a Fixnum for the replacement object" do + it "raises a TypeError if passed an Integer for the replacement object" do -> do Encoding::Converter.new("us-ascii", "utf-8", replace: 1) end.should raise_error(TypeError) diff --git a/ruby/spec/ruby/core/encoding/converter/putback_spec.rb b/ruby/spec/ruby/core/encoding/converter/putback_spec.rb index 87495eaf3..c4e0a5da2 100644 --- a/ruby/spec/ruby/core/encoding/converter/putback_spec.rb +++ b/ruby/spec/ruby/core/encoding/converter/putback_spec.rb @@ -34,14 +34,23 @@ @ec.putback.should == "" end + it "returns the problematic bytes for UTF-16LE" do + ec = Encoding::Converter.new("utf-16le", "iso-8859-1") + src = "\x00\xd8\x61\x00" + dst = "" + ec.primitive_convert(src, dst).should == :invalid_byte_sequence + ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"] + ec.putback.should == "a\x00".force_encoding("utf-16le") + ec.putback.should == "" + end + it "accepts an integer argument corresponding to the number of bytes to be put back" do ec = Encoding::Converter.new("utf-16le", "iso-8859-1") src = "\x00\xd8\x61\x00" dst = "" ec.primitive_convert(src, dst).should == :invalid_byte_sequence ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"] - ec.putback(1).should == "\x00".force_encoding("utf-16le") - ec.putback.should == "a".force_encoding("utf-16le") + ec.putback(2).should == "a\x00".force_encoding("utf-16le") ec.putback.should == "" end end diff --git a/ruby/spec/ruby/core/encoding/default_external_spec.rb b/ruby/spec/ruby/core/encoding/default_external_spec.rb index e2cb9b02f..682d49d37 100644 --- a/ruby/spec/ruby/core/encoding/default_external_spec.rb +++ b/ruby/spec/ruby/core/encoding/default_external_spec.rb @@ -17,6 +17,14 @@ Encoding.default_external = Encoding::SHIFT_JIS Encoding.default_external.should == Encoding::SHIFT_JIS end + + ruby_version_is "3.0" do + platform_is :windows do + it 'is UTF-8 by default on Windows' do + Encoding.default_external.should == Encoding::UTF_8 + end + end + end end describe "Encoding.default_external=" do diff --git a/ruby/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb b/ruby/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb index e3ef3e455..94201a9b1 100644 --- a/ruby/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb +++ b/ruby/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb @@ -2,7 +2,6 @@ require_relative '../../../spec_helper' describe "Encoding::InvalidByteSequenceError#incomplete_input?" do - it "returns nil by default" do Encoding::InvalidByteSequenceError.new.incomplete_input?.should be_nil end diff --git a/ruby/spec/ruby/core/encoding/list_spec.rb b/ruby/spec/ruby/core/encoding/list_spec.rb index 2a2078974..8efd94ab9 100644 --- a/ruby/spec/ruby/core/encoding/list_spec.rb +++ b/ruby/spec/ruby/core/encoding/list_spec.rb @@ -12,7 +12,7 @@ end it "returns each encoding only once" do - orig = Encoding.list.map {|e| e.name} + orig = Encoding.list.map { |e| e.name } orig.should == orig.uniq end @@ -33,7 +33,17 @@ end it "includes dummy encodings" do - Encoding.list.select {|e| e.dummy?}.should_not == [] + Encoding.list.select { |e| e.dummy? }.should_not == [] + end + + it 'includes UTF-8 encoding' do + Encoding.list.should.include?(Encoding::UTF_8) + end + + ruby_version_is "2.7" do + it 'includes CESU-8 encoding' do + Encoding.list.should.include?(Encoding::CESU_8) + end end # TODO: Find example that illustrates this diff --git a/ruby/spec/ruby/core/encoding/locale_charmap_spec.rb b/ruby/spec/ruby/core/encoding/locale_charmap_spec.rb index 5963a8beb..8143b9083 100644 --- a/ruby/spec/ruby/core/encoding/locale_charmap_spec.rb +++ b/ruby/spec/ruby/core/encoding/locale_charmap_spec.rb @@ -7,11 +7,13 @@ # FIXME: Get this working on Windows platform_is :linux do - it "returns a value based on the LC_ALL environment variable" do - old_lc_all = ENV['LC_ALL'] - ENV['LC_ALL'] = 'C' - ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968' - ENV['LC_ALL'] = old_lc_all + platform_is_not :android do + it "returns a value based on the LC_ALL environment variable" do + old_lc_all = ENV['LC_ALL'] + ENV['LC_ALL'] = 'C' + ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968' + ENV['LC_ALL'] = old_lc_all + end end end @@ -33,6 +35,15 @@ end end + platform_is :android do + it "always returns UTF-8" do + old_lc_all = ENV['LC_ALL'] + ENV['LC_ALL'] = 'C' + ruby_exe("print Encoding.locale_charmap").should == 'UTF-8' + ENV['LC_ALL'] = old_lc_all + end + end + platform_is :bsd, :darwin, :linux do it "is unaffected by assigning to ENV['LC_ALL'] in the same process" do old_charmap = Encoding.locale_charmap diff --git a/ruby/spec/ruby/core/encoding/replicate_spec.rb b/ruby/spec/ruby/core/encoding/replicate_spec.rb index 717e9cea7..45727a5c0 100644 --- a/ruby/spec/ruby/core/encoding/replicate_spec.rb +++ b/ruby/spec/ruby/core/encoding/replicate_spec.rb @@ -15,6 +15,8 @@ name = @prefix + '-ASCII' e = Encoding::ASCII.replicate(name) e.name.should == name + Encoding.find(name).should == e + "a".force_encoding(e).valid_encoding?.should be_true "\x80".force_encoding(e).valid_encoding?.should be_false end @@ -23,6 +25,8 @@ name = @prefix + 'UTF-8' e = Encoding::UTF_8.replicate(name) e.name.should == name + Encoding.find(name).should == e + "a".force_encoding(e).valid_encoding?.should be_true "\u3042".force_encoding(e).valid_encoding?.should be_true "\x80".force_encoding(e).valid_encoding?.should be_false @@ -32,6 +36,8 @@ name = @prefix + 'UTF-16-BE' e = Encoding::UTF_16BE.replicate(name) e.name.should == name + Encoding.find(name).should == e + "a".force_encoding(e).valid_encoding?.should be_false "\x30\x42".force_encoding(e).valid_encoding?.should be_true "\x80".force_encoding(e).valid_encoding?.should be_false @@ -40,7 +46,22 @@ it "returns a replica of ISO-2022-JP" do name = @prefix + 'ISO-2022-JP' e = Encoding::ISO_2022_JP.replicate(name) + Encoding.find(name).should == e + e.name.should == name e.dummy?.should be_true end + + # NOTE: it's unclear of the value of this (for the complexity cost of it), + # but it is the current CRuby behavior. + it "can be associated with a String" do + name = @prefix + '-US-ASCII' + e = Encoding::US_ASCII.replicate(name) + e.name.should == name + Encoding.find(name).should == e + + s = "abc".force_encoding(e) + s.encoding.should == e + s.encoding.name.should == name + end end diff --git a/ruby/spec/ruby/core/enumerable/all_spec.rb b/ruby/spec/ruby/core/enumerable/all_spec.rb index 8af80896a..b782f94a3 100644 --- a/ruby/spec/ruby/core/enumerable/all_spec.rb +++ b/ruby/spec/ruby/core/enumerable/all_spec.rb @@ -10,13 +10,13 @@ end it "always returns true on empty enumeration" do - @empty.all?.should == true + @empty.should.all? @empty.all? { nil }.should == true - [].all?.should == true + [].should.all? [].all? { false }.should == true - {}.all?.should == true + {}.should.all? {}.all? { nil }.should == true end @@ -26,15 +26,6 @@ -> { {}.all?(1, 2, 3) }.should raise_error(ArgumentError) end - ruby_version_is ""..."2.5" do - it "raises an ArgumentError when any arguments provided" do - -> { @enum.all?(Proc.new {}) }.should raise_error(ArgumentError) - -> { @enum.all?(nil) }.should raise_error(ArgumentError) - -> { @empty.all?(1) }.should raise_error(ArgumentError) - -> { @enum1.all?(1) {} }.should raise_error(ArgumentError) - end - end - it "does not hide exceptions out of #each" do -> { EnumerableSpecs::ThrowingEach.new.all? @@ -47,24 +38,24 @@ describe "with no block" do it "returns true if no elements are false or nil" do - @enum.all?.should == true - @enum1.all?.should == true - @enum2.all?.should == false + @enum.should.all? + @enum1.should.all? + @enum2.should_not.all? - EnumerableSpecs::Numerous.new('a','b','c').all?.should == true - EnumerableSpecs::Numerous.new(0, "x", true).all?.should == true + EnumerableSpecs::Numerous.new('a','b','c').should.all? + EnumerableSpecs::Numerous.new(0, "x", true).should.all? end it "returns false if there are false or nil elements" do - EnumerableSpecs::Numerous.new(false).all?.should == false - EnumerableSpecs::Numerous.new(false, false).all?.should == false + EnumerableSpecs::Numerous.new(false).should_not.all? + EnumerableSpecs::Numerous.new(false, false).should_not.all? - EnumerableSpecs::Numerous.new(nil).all?.should == false - EnumerableSpecs::Numerous.new(nil, nil).all?.should == false + EnumerableSpecs::Numerous.new(nil).should_not.all? + EnumerableSpecs::Numerous.new(nil, nil).should_not.all? - EnumerableSpecs::Numerous.new(1, nil, 2).all?.should == false - EnumerableSpecs::Numerous.new(0, "x", false, true).all?.should == false - @enum2.all?.should == false + EnumerableSpecs::Numerous.new(1, nil, 2).should_not.all? + EnumerableSpecs::Numerous.new(0, "x", false, true).should_not.all? + @enum2.should_not.all? end it "gathers whole arrays as elements when each yields multiple" do @@ -133,69 +124,59 @@ end end - ruby_version_is "2.5" do - describe 'when given a pattern argument' do - it "calls `===` on the pattern the return value " do - pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } - @enum1.all?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - end - - # may raise an exception in future versions - ruby_version_is ""..."2.6" do - it "ignores block" do - @enum2.all?(NilClass) { raise }.should == false - [1, 2, nil].all?(NilClass) { raise }.should == false - {a: 1}.all?(Array) { raise }.should == true - end - end - - it "always returns true on empty enumeration" do - @empty.all?(Integer).should == true - [].all?(Integer).should == true - {}.all?(NilClass).should == true - end - - it "does not hide exceptions out of #each" do - -> { - EnumerableSpecs::ThrowingEach.new.all?(Integer) - }.should raise_error(RuntimeError) - end - - it "returns true if the pattern never returns false or nil" do - pattern = EnumerableSpecs::Pattern.new { |x| 42 } - @enum.all?(pattern).should == true - - [1, 42, 3].all?(pattern).should == true - - pattern = EnumerableSpecs::Pattern.new { |x| Array === x } - {a: 1, b: 2}.all?(pattern).should == true - end - - it "returns false if the pattern ever returns false or nil" do - pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } - @enum1.all?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - - [1, 2, 3, -1].all?(pattern).should == false - - pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 } - {a: 1, b: -1}.all?(pattern).should == false - end - - it "does not hide exceptions out of pattern#===" do - pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } - -> { - @enum.all?(pattern) - }.should raise_error(RuntimeError) - end - - it "calls the pattern with gathered array when yielded with multiple arguments" do - multi = EnumerableSpecs::YieldsMulti.new - pattern = EnumerableSpecs::Pattern.new { true } - multi.all?(pattern).should == true - pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } + @enum1.all?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + end + + # may raise an exception in future versions + it "always returns true on empty enumeration" do + @empty.all?(Integer).should == true + [].all?(Integer).should == true + {}.all?(NilClass).should == true + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.all?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern never returns false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| 42 } + @enum.all?(pattern).should == true + + [1, 42, 3].all?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| Array === x } + {a: 1, b: 2}.all?(pattern).should == true + end + + it "returns false if the pattern ever returns false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } + @enum1.all?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3, -1].all?(pattern).should == false + + pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 } + {a: 1, b: -1}.all?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.all?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { true } + multi.all?(pattern).should == true + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] end end end diff --git a/ruby/spec/ruby/core/enumerable/any_spec.rb b/ruby/spec/ruby/core/enumerable/any_spec.rb index c800fe2d4..636b1fa45 100644 --- a/ruby/spec/ruby/core/enumerable/any_spec.rb +++ b/ruby/spec/ruby/core/enumerable/any_spec.rb @@ -10,13 +10,13 @@ end it "always returns false on empty enumeration" do - @empty.any?.should == false + @empty.should_not.any? @empty.any? { nil }.should == false - [].any?.should == false + [].should_not.any? [].any? { false }.should == false - {}.any?.should == false + {}.should_not.any? {}.any? { nil }.should == false end @@ -26,15 +26,6 @@ -> { {}.any?(1, 2, 3) }.should raise_error(ArgumentError) end - ruby_version_is ""..."2.5" do - it "raises an ArgumentError when any arguments provided" do - -> { @enum.any?(Proc.new {}) }.should raise_error(ArgumentError) - -> { @enum.any?(nil) }.should raise_error(ArgumentError) - -> { @empty.any?(1) }.should raise_error(ArgumentError) - -> { @enum1.any?(1) {} }.should raise_error(ArgumentError) - end - end - it "does not hide exceptions out of #each" do -> { EnumerableSpecs::ThrowingEach.new.any? @@ -47,24 +38,24 @@ describe "with no block" do it "returns true if any element is not false or nil" do - @enum.any?.should == true - @enum1.any?.should == true - @enum2.any?.should == true - EnumerableSpecs::Numerous.new(true).any?.should == true - EnumerableSpecs::Numerous.new('a','b','c').any?.should == true - EnumerableSpecs::Numerous.new('a','b','c', nil).any?.should == true - EnumerableSpecs::Numerous.new(1, nil, 2).any?.should == true - EnumerableSpecs::Numerous.new(1, false).any?.should == true - EnumerableSpecs::Numerous.new(false, nil, 1, false).any?.should == true - EnumerableSpecs::Numerous.new(false, 0, nil).any?.should == true + @enum.should.any? + @enum1.should.any? + @enum2.should.any? + EnumerableSpecs::Numerous.new(true).should.any? + EnumerableSpecs::Numerous.new('a','b','c').should.any? + EnumerableSpecs::Numerous.new('a','b','c', nil).should.any? + EnumerableSpecs::Numerous.new(1, nil, 2).should.any? + EnumerableSpecs::Numerous.new(1, false).should.any? + EnumerableSpecs::Numerous.new(false, nil, 1, false).should.any? + EnumerableSpecs::Numerous.new(false, 0, nil).should.any? end it "returns false if all elements are false or nil" do - EnumerableSpecs::Numerous.new(false).any?.should == false - EnumerableSpecs::Numerous.new(false, false).any?.should == false - EnumerableSpecs::Numerous.new(nil).any?.should == false - EnumerableSpecs::Numerous.new(nil, nil).any?.should == false - EnumerableSpecs::Numerous.new(nil, false, nil).any?.should == false + EnumerableSpecs::Numerous.new(false).should_not.any? + EnumerableSpecs::Numerous.new(false, false).should_not.any? + EnumerableSpecs::Numerous.new(nil).should_not.any? + EnumerableSpecs::Numerous.new(nil, nil).should_not.any? + EnumerableSpecs::Numerous.new(nil, false, nil).should_not.any? end it "gathers whole arrays as elements when each yields multiple" do @@ -147,68 +138,58 @@ end end - ruby_version_is "2.5" do - describe 'when given a pattern argument' do - it "calls `===` on the pattern the return value " do - pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } - @enum1.any?(pattern).should == true - pattern.yielded.should == [[0], [1], [2]] - end - - # may raise an exception in future versions - ruby_version_is ""..."2.6" do - it "ignores block" do - @enum2.any?(NilClass) { raise }.should == true - [1, 2, nil].any?(NilClass) { raise }.should == true - {a: 1}.any?(Array) { raise }.should == true - end - end - - it "always returns false on empty enumeration" do - @empty.any?(Integer).should == false - [].any?(Integer).should == false - {}.any?(NilClass).should == false - end - - it "does not hide exceptions out of #each" do - -> { - EnumerableSpecs::ThrowingEach.new.any?(Integer) - }.should raise_error(RuntimeError) - end - - it "returns true if the pattern ever returns a truthy value" do - @enum2.any?(NilClass).should == true - pattern = EnumerableSpecs::Pattern.new { |x| 42 } - @enum.any?(pattern).should == true - - [1, 42, 3].any?(pattern).should == true - - pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } - {a: 1, b: 2}.any?(pattern).should == true - end - - it "returns false if the block never returns other than false or nil" do - pattern = EnumerableSpecs::Pattern.new { |x| nil } - @enum1.any?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - - [1, 2, 3].any?(pattern).should == false - {a: 1}.any?(pattern).should == false - end - - it "does not hide exceptions out of pattern#===" do - pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } - -> { - @enum.any?(pattern) - }.should raise_error(RuntimeError) - end - - it "calls the pattern with gathered array when yielded with multiple arguments" do - multi = EnumerableSpecs::YieldsMulti.new - pattern = EnumerableSpecs::Pattern.new { false } - multi.any?(pattern).should == false - pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } + @enum1.any?(pattern).should == true + pattern.yielded.should == [[0], [1], [2]] + end + + # may raise an exception in future versions + it "always returns false on empty enumeration" do + @empty.any?(Integer).should == false + [].any?(Integer).should == false + {}.any?(NilClass).should == false + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.any?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern ever returns a truthy value" do + @enum2.any?(NilClass).should == true + pattern = EnumerableSpecs::Pattern.new { |x| 42 } + @enum.any?(pattern).should == true + + [1, 42, 3].any?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } + {a: 1, b: 2}.any?(pattern).should == true + end + + it "returns false if the block never returns other than false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum1.any?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3].any?(pattern).should == false + {a: 1}.any?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.any?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.any?(pattern).should == false + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] end end end diff --git a/ruby/spec/ruby/core/enumerable/chain_spec.rb b/ruby/spec/ruby/core/enumerable/chain_spec.rb index 85c0c0360..5e2105d29 100644 --- a/ruby/spec/ruby/core/enumerable/chain_spec.rb +++ b/ruby/spec/ruby/core/enumerable/chain_spec.rb @@ -1,25 +1,23 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "2.6" do - describe "Enumerable#chain" do - before :each do - ScratchPad.record [] - end +describe "Enumerable#chain" do + before :each do + ScratchPad.record [] + end - it "returns a chain of self and provided enumerables" do - one = EnumerableSpecs::Numerous.new(1) - two = EnumerableSpecs::Numerous.new(2, 3) - three = EnumerableSpecs::Numerous.new(4, 5, 6) + it "returns a chain of self and provided enumerables" do + one = EnumerableSpecs::Numerous.new(1) + two = EnumerableSpecs::Numerous.new(2, 3) + three = EnumerableSpecs::Numerous.new(4, 5, 6) - chain = one.chain(two, three) + chain = one.chain(two, three) - chain.each { |item| ScratchPad << item } - ScratchPad.recorded.should == [1, 2, 3, 4, 5, 6] - end + chain.each { |item| ScratchPad << item } + ScratchPad.recorded.should == [1, 2, 3, 4, 5, 6] + end - it "returns an Enumerator::Chain if given a block" do - EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain) - end + it "returns an Enumerator::Chain if given a block" do + EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain) end end diff --git a/ruby/spec/ruby/core/enumerable/chunk_spec.rb b/ruby/spec/ruby/core/enumerable/chunk_spec.rb index 548544f4e..c5579d67f 100644 --- a/ruby/spec/ruby/core/enumerable/chunk_spec.rb +++ b/ruby/spec/ruby/core/enumerable/chunk_spec.rb @@ -35,6 +35,11 @@ result.should == [[:_alone, [1]], [false, [2, 3, 2]], [:_alone, [1]]] end + it "yields Arrays as a single argument to a rest argument" do + e = EnumerableSpecs::Numerous.new([1, 2]) + result = e.chunk { |*x| x.should == [[1,2]] }.to_a + end + it "does not return elements for which the block returns :_separator" do e = EnumerableSpecs::Numerous.new(1, 2, 3, 3, 2, 1) result = e.chunk { |x| x == 2 ? :_separator : 1 }.to_a diff --git a/ruby/spec/ruby/core/enumerable/each_cons_spec.rb b/ruby/spec/ruby/core/enumerable/each_cons_spec.rb index 7d44f54f7..ba658203a 100644 --- a/ruby/spec/ruby/core/enumerable/each_cons_spec.rb +++ b/ruby/spec/ruby/core/enumerable/each_cons_spec.rb @@ -10,7 +10,7 @@ it "passes element groups to the block" do acc = [] - @enum.each_cons(3){|g| acc << g}.should be_nil + @enum.each_cons(3){|g| acc << g} acc.should == @in_threes end @@ -27,7 +27,7 @@ it "tries to convert n to an Integer using #to_int" do acc = [] - @enum.each_cons(3.3){|g| acc << g}.should == nil + @enum.each_cons(3.3){|g| acc << g} acc.should == @in_threes obj = mock('to_int') diff --git a/ruby/spec/ruby/core/enumerable/each_slice_spec.rb b/ruby/spec/ruby/core/enumerable/each_slice_spec.rb index ab3b79c34..2ea89f5e7 100644 --- a/ruby/spec/ruby/core/enumerable/each_slice_spec.rb +++ b/ruby/spec/ruby/core/enumerable/each_slice_spec.rb @@ -10,7 +10,7 @@ it "passes element groups to the block" do acc = [] - @enum.each_slice(3){|g| acc << g}.should be_nil + @enum.each_slice(3){|g| acc << g} acc.should == @sliced end @@ -27,7 +27,7 @@ it "tries to convert n to an Integer using #to_int" do acc = [] - @enum.each_slice(3.3){|g| acc << g}.should == nil + @enum.each_slice(3.3){|g| acc << g} acc.should == @sliced obj = mock('to_int') diff --git a/ruby/spec/ruby/core/enumerable/filter_spec.rb b/ruby/spec/ruby/core/enumerable/filter_spec.rb index f2dc7a7b7..7e4f8c0b5 100644 --- a/ruby/spec/ruby/core/enumerable/filter_spec.rb +++ b/ruby/spec/ruby/core/enumerable/filter_spec.rb @@ -2,8 +2,6 @@ require_relative 'fixtures/classes' require_relative 'shared/find_all' -ruby_version_is "2.6" do - describe "Enumerable#filter" do - it_behaves_like(:enumerable_find_all , :filter) - end +describe "Enumerable#filter" do + it_behaves_like(:enumerable_find_all , :filter) end diff --git a/ruby/spec/ruby/core/enumerable/fixtures/classes.rb b/ruby/spec/ruby/core/enumerable/fixtures/classes.rb index 505119674..fb4951c6e 100644 --- a/ruby/spec/ruby/core/enumerable/fixtures/classes.rb +++ b/ruby/spec/ruby/core/enumerable/fixtures/classes.rb @@ -251,7 +251,7 @@ def <=>(other) end end - class ComparableWithFixnum + class ComparableWithInteger include Comparable def initialize(num) @num = num diff --git a/ruby/spec/ruby/core/enumerable/grep_spec.rb b/ruby/spec/ruby/core/enumerable/grep_spec.rb index c9c0f34e2..b81075291 100644 --- a/ruby/spec/ruby/core/enumerable/grep_spec.rb +++ b/ruby/spec/ruby/core/enumerable/grep_spec.rb @@ -40,15 +40,43 @@ class EnumerableSpecGrep2; def ===(obj); /^ca/ =~ obj; end; end $~.should == nil end - it "sets $~ to the last match when given no block" do - "z" =~ /z/ # Reset $~ - ["abc", "def"].grep(/b/).should == ["abc"] + ruby_version_is ""..."3.0.0" do + it "sets $~ to the last match when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep(/b/).should == ["abc"] - # Set by the failed match of "def" - $~.should == nil + # Set by the failed match of "def" + $~.should == nil - ["abc", "def"].grep(/e/) - $&.should == "e" + ["abc", "def"].grep(/e/) + $&.should == "e" + end + end + + ruby_version_is "3.0.0" do + it "does not set $~ when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep(/b/).should == ["abc"] + $&.should == "z" + end + + it "does not modify Regexp.last_match without block" do + "z" =~ /z/ # Reset last match + ["abc", "def"].grep(/b/).should == ["abc"] + Regexp.last_match[0].should == "z" + end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep(/ll/).first.should.equal?(o) + end end describe "with a block" do diff --git a/ruby/spec/ruby/core/enumerable/grep_v_spec.rb b/ruby/spec/ruby/core/enumerable/grep_v_spec.rb index 6dec48706..35fde27eb 100644 --- a/ruby/spec/ruby/core/enumerable/grep_v_spec.rb +++ b/ruby/spec/ruby/core/enumerable/grep_v_spec.rb @@ -20,15 +20,43 @@ def (@odd_matcher = BasicObject.new).===(obj) $&.should == "e" end - it "sets $~ to the last match when given no block" do - "z" =~ /z/ # Reset $~ - ["abc", "def"].grep_v(/e/).should == ["abc"] + ruby_version_is ""..."3.0.0" do + it "sets $~ to the last match when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep_v(/e/).should == ["abc"] - # Set by the match of "def" - $&.should == "e" + # Set by the match of "def" + $&.should == "e" + + ["abc", "def"].grep_v(/b/) + $&.should == nil + end + end - ["abc", "def"].grep_v(/b/) - $&.should == nil + ruby_version_is "3.0.0" do + it "does not set $~ when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep_v(/e/).should == ["abc"] + $&.should == "z" + end + + it "does not modify Regexp.last_match without block" do + "z" =~ /z/ # Reset last match + ["abc", "def"].grep_v(/e/).should == ["abc"] + Regexp.last_match[0].should == "z" + end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep_v(/mm/).first.should.equal?(o) + end end describe "without block" do diff --git a/ruby/spec/ruby/core/enumerable/minmax_spec.rb b/ruby/spec/ruby/core/enumerable/minmax_spec.rb index 29f1ecf82..f5f17ef07 100644 --- a/ruby/spec/ruby/core/enumerable/minmax_spec.rb +++ b/ruby/spec/ruby/core/enumerable/minmax_spec.rb @@ -1,41 +1,17 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative '../../shared/enumerable/minmax' describe "Enumerable#minmax" do before :each do @enum = EnumerableSpecs::Numerous.new(6, 4, 5, 10, 8) - + @empty_enum = EnumerableSpecs::Empty.new + @incomparable_enum = EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new) + @incompatible_enum = EnumerableSpecs::Numerous.new(11,"22") @strs = EnumerableSpecs::Numerous.new("333", "2", "60", "55555", "1010", "111") end - it "min should return the minimum element" do - @enum.minmax.should == [4, 10] - @strs.minmax.should == ["1010", "60" ] - end - - it "returns [nil, nil] for an empty Enumerable" do - EnumerableSpecs::Empty.new.minmax.should == [nil, nil] - end - - it "raises an ArgumentError when elements are incomparable" do - -> do - EnumerableSpecs::Numerous.new(11,"22").minmax - end.should raise_error(ArgumentError) - -> do - EnumerableSpecs::Numerous.new(11,12,22,33).minmax{|a, b| nil} - end.should raise_error(ArgumentError) - end - - it "raises a NoMethodError for elements without #<=>" do - -> do - EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new).minmax - end.should raise_error(NoMethodError) - end - - it "returns the minimum when using a block rule" do - @enum.minmax {|a,b| b <=> a }.should == [10, 4] - @strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"] - end + it_behaves_like :enumerable_minmax, :minmax it "gathers whole arrays as elements when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new diff --git a/ruby/spec/ruby/core/enumerable/none_spec.rb b/ruby/spec/ruby/core/enumerable/none_spec.rb index 7c17e58a1..b898d0006 100644 --- a/ruby/spec/ruby/core/enumerable/none_spec.rb +++ b/ruby/spec/ruby/core/enumerable/none_spec.rb @@ -10,7 +10,7 @@ end it "always returns true on empty enumeration" do - @empty.none?.should == true + @empty.should.none? @empty.none? { true }.should == true end @@ -20,15 +20,6 @@ -> { {}.none?(1, 2, 3) }.should raise_error(ArgumentError) end - ruby_version_is ""..."2.5" do - it "raises an ArgumentError when any arguments provided" do - -> { @enum.none?(Proc.new {}) }.should raise_error(ArgumentError) - -> { @enum.none?(nil) }.should raise_error(ArgumentError) - -> { @empty.none?(1) }.should raise_error(ArgumentError) - -> { @enum.none?(1) {} }.should raise_error(ArgumentError) - end - end - it "does not hide exceptions out of #each" do -> { EnumerableSpecs::ThrowingEach.new.none? @@ -102,66 +93,56 @@ end end - ruby_version_is "2.5" do - describe 'when given a pattern argument' do - it "calls `===` on the pattern the return value " do - pattern = EnumerableSpecs::Pattern.new { |x| x == 3 } - @enum1.none?(pattern).should == true - pattern.yielded.should == [[0], [1], [2], [-1]] - end - - # may raise an exception in future versions - ruby_version_is ""..."2.6" do - it "ignores block" do - @enum2.none?(Integer) { raise }.should == true - [1, 2, nil].none?(TrueClass) { raise }.should == true - {a: 1}.none?(Hash) { raise }.should == true - end - end - - it "always returns true on empty enumeration" do - @empty.none?(Integer).should == true - [].none?(Integer).should == true - {}.none?(NilClass).should == true - end - - it "does not hide exceptions out of #each" do - -> { - EnumerableSpecs::ThrowingEach.new.none?(Integer) - }.should raise_error(RuntimeError) - end - - it "returns true if the pattern never returns a truthy value" do - @enum2.none?(Integer).should == true - pattern = EnumerableSpecs::Pattern.new { |x| nil } - @enum.none?(pattern).should == true - - [1, 42, 3].none?(pattern).should == true - {a: 1, b: 2}.none?(pattern).should == true - end - - it "returns false if the pattern ever returns other than false or nil" do - pattern = EnumerableSpecs::Pattern.new { |x| x < 0 } - @enum1.none?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - - [1, 2, 3, -1].none?(pattern).should == false - {a: 1}.none?(Array).should == false - end - - it "does not hide exceptions out of pattern#===" do - pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } - -> { - @enum.none?(pattern) - }.should raise_error(RuntimeError) - end - - it "calls the pattern with gathered array when yielded with multiple arguments" do - multi = EnumerableSpecs::YieldsMulti.new - pattern = EnumerableSpecs::Pattern.new { false } - multi.none?(pattern).should == true - pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 3 } + @enum1.none?(pattern).should == true + pattern.yielded.should == [[0], [1], [2], [-1]] + end + + # may raise an exception in future versions + it "always returns true on empty enumeration" do + @empty.none?(Integer).should == true + [].none?(Integer).should == true + {}.none?(NilClass).should == true + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.none?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern never returns a truthy value" do + @enum2.none?(Integer).should == true + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum.none?(pattern).should == true + + [1, 42, 3].none?(pattern).should == true + {a: 1, b: 2}.none?(pattern).should == true + end + + it "returns false if the pattern ever returns other than false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| x < 0 } + @enum1.none?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3, -1].none?(pattern).should == false + {a: 1}.none?(Array).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.none?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.none?(pattern).should == true + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] end end end diff --git a/ruby/spec/ruby/core/enumerable/one_spec.rb b/ruby/spec/ruby/core/enumerable/one_spec.rb index 2ae8b3efa..d54dd4a52 100644 --- a/ruby/spec/ruby/core/enumerable/one_spec.rb +++ b/ruby/spec/ruby/core/enumerable/one_spec.rb @@ -10,7 +10,7 @@ end it "always returns false on empty enumeration" do - @empty.one?.should == false + @empty.should_not.one? @empty.one? { true }.should == false end @@ -20,15 +20,6 @@ -> { {}.one?(1, 2, 3) }.should raise_error(ArgumentError) end - ruby_version_is ""..."2.5" do - it "raises an ArgumentError when any arguments provided" do - -> { @enum.one?(Proc.new {}) }.should raise_error(ArgumentError) - -> { @enum.one?(nil) }.should raise_error(ArgumentError) - -> { @empty.one?(1) }.should raise_error(ArgumentError) - -> { @enum.one?(1) {} }.should raise_error(ArgumentError) - end - end - it "does not hide exceptions out of #each" do -> { EnumerableSpecs::ThrowingEach.new.one? @@ -93,77 +84,67 @@ end - ruby_version_is "2.5" do - describe 'when given a pattern argument' do - it "calls `===` on the pattern the return value " do - pattern = EnumerableSpecs::Pattern.new { |x| x == 1 } - @enum1.one?(pattern).should == true - pattern.yielded.should == [[0], [1], [2], [-1]] - end - - # may raise an exception in future versions - ruby_version_is ""..."2.6" do - it "ignores block" do - @enum2.one?(NilClass) { raise }.should == true - [1, 2, nil].one?(NilClass) { raise }.should == true - {a: 1}.one?(Array) { raise }.should == true - end - end - - it "always returns false on empty enumeration" do - @empty.one?(Integer).should == false - [].one?(Integer).should == false - {}.one?(NilClass).should == false - end - - it "does not hide exceptions out of #each" do - -> { - EnumerableSpecs::ThrowingEach.new.one?(Integer) - }.should raise_error(RuntimeError) - end - - it "returns true if the pattern returns a truthy value only once" do - @enum2.one?(NilClass).should == true - pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } - @enum1.one?(pattern).should == true - - [1, 2, 42, 3].one?(pattern).should == true - - pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } - {a: 1, b: 2}.one?(pattern).should == true - end - - it "returns false if the pattern returns a truthy value more than once" do - pattern = EnumerableSpecs::Pattern.new { |x| !x } - @enum2.one?(pattern).should == false - pattern.yielded.should == [[nil], [false]] - - [1, 2, 3].one?(Integer).should == false - {a: 1, b: 2}.one?(Array).should == false - end - - it "returns false if the pattern never returns a truthy value" do - pattern = EnumerableSpecs::Pattern.new { |x| nil } - @enum1.one?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - - [1, 2, 3].one?(pattern).should == false - {a: 1}.one?(pattern).should == false - end - - it "does not hide exceptions out of pattern#===" do - pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } - -> { - @enum.one?(pattern) - }.should raise_error(RuntimeError) - end - - it "calls the pattern with gathered array when yielded with multiple arguments" do - multi = EnumerableSpecs::YieldsMulti.new - pattern = EnumerableSpecs::Pattern.new { false } - multi.one?(pattern).should == false - pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 1 } + @enum1.one?(pattern).should == true + pattern.yielded.should == [[0], [1], [2], [-1]] + end + + # may raise an exception in future versions + it "always returns false on empty enumeration" do + @empty.one?(Integer).should == false + [].one?(Integer).should == false + {}.one?(NilClass).should == false + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.one?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern returns a truthy value only once" do + @enum2.one?(NilClass).should == true + pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } + @enum1.one?(pattern).should == true + + [1, 2, 42, 3].one?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } + {a: 1, b: 2}.one?(pattern).should == true + end + + it "returns false if the pattern returns a truthy value more than once" do + pattern = EnumerableSpecs::Pattern.new { |x| !x } + @enum2.one?(pattern).should == false + pattern.yielded.should == [[nil], [false]] + + [1, 2, 3].one?(Integer).should == false + {a: 1, b: 2}.one?(Array).should == false + end + + it "returns false if the pattern never returns a truthy value" do + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum1.one?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3].one?(pattern).should == false + {a: 1}.one?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.one?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.one?(pattern).should == false + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] end end end diff --git a/ruby/spec/ruby/core/enumerable/shared/collect.rb b/ruby/spec/ruby/core/enumerable/shared/collect.rb index 05e94777c..6df1a616e 100644 --- a/ruby/spec/ruby/core/enumerable/shared/collect.rb +++ b/ruby/spec/ruby/core/enumerable/shared/collect.rb @@ -34,5 +34,74 @@ enum.each { |i| -i }.should == [-2, -5, -3, -6, -1, -4] end + it "reports the same arity as the given block" do + entries = [0, 1, 3, 4, 5, 6] + numerous = EnumerableSpecs::Numerous.new(*entries) + + def numerous.each(&block) + ScratchPad << block.arity + super + end + + numerous.send(@method) { |a, b| a % 2 }.should == [0, 1, 1, 0, 1, 0] + ScratchPad.recorded.should == [2] + ScratchPad.clear + ScratchPad.record [] + numerous.send(@method) { |i| i }.should == entries + ScratchPad.recorded.should == [1] + end + + it "yields an Array of 2 elements for a Hash when block arity is 1" do + c = Class.new do + def register(a) + ScratchPad << a + end + end + m = c.new.method(:register) + + ScratchPad.record [] + { 1 => 'a', 2 => 'b' }.map(&m) + ScratchPad.recorded.should == [[1, 'a'], [2, 'b']] + end + + it "yields 2 arguments for a Hash when block arity is 2" do + c = Class.new do + def register(a, b) + ScratchPad << [a, b] + end + end + m = c.new.method(:register) + + ScratchPad.record [] + { 1 => 'a', 2 => 'b' }.map(&m) + ScratchPad.recorded.should == [[1, 'a'], [2, 'b']] + end + + it "raises an error for a Hash when an arity enforcing block of arity >2 is passed in" do + c = Class.new do + def register(a, b, c) + end + end + m = c.new.method(:register) + + -> do + { 1 => 'a', 2 => 'b' }.map(&m) + end.should raise_error(ArgumentError) + end + + it "calls the each method on sub-classes" do + c = Class.new(Hash) do + def each + ScratchPad << 'in each' + super + end + end + h = c.new + h[1] = 'a' + ScratchPad.record [] + h.send(@method) { |k,v| v } + ScratchPad.recorded.should == ['in each'] + end + it_should_behave_like :enumerable_enumeratorized_with_origin_size end diff --git a/ruby/spec/ruby/core/enumerable/sort_spec.rb b/ruby/spec/ruby/core/enumerable/sort_spec.rb index cff1a5998..6fc64f325 100644 --- a/ruby/spec/ruby/core/enumerable/sort_spec.rb +++ b/ruby/spec/ruby/core/enumerable/sort_spec.rb @@ -31,7 +31,7 @@ it "compare values returned by block with 0" do EnumerableSpecs::Numerous.new.sort { |n, m| -(n+m) * (n <=> m) }.should == [6, 5, 4, 3, 2, 1] EnumerableSpecs::Numerous.new.sort { |n, m| - EnumerableSpecs::ComparableWithFixnum.new(-(n+m) * (n <=> m)) + EnumerableSpecs::ComparableWithInteger.new(-(n+m) * (n <=> m)) }.should == [6, 5, 4, 3, 2, 1] -> { EnumerableSpecs::Numerous.new.sort { |n, m| (n <=> m).to_s } diff --git a/ruby/spec/ruby/core/enumerable/sum_spec.rb b/ruby/spec/ruby/core/enumerable/sum_spec.rb index c9d7017b4..4a978794e 100644 --- a/ruby/spec/ruby/core/enumerable/sum_spec.rb +++ b/ruby/spec/ruby/core/enumerable/sum_spec.rb @@ -25,4 +25,13 @@ def each it 'takes a block to transform the elements' do @enum.sum { |element| element * 2 }.should == 10/3r end + + # https://bugs.ruby-lang.org/issues/12217 + # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214 + it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do + floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5].to_enum + naive_sum = floats.reduce { |sum, e| sum + e } + naive_sum.should == 50.00000000000001 + floats.sum.should == 50.0 + end end diff --git a/ruby/spec/ruby/core/enumerable/tally_spec.rb b/ruby/spec/ruby/core/enumerable/tally_spec.rb index 363b3def2..92aac507f 100644 --- a/ruby/spec/ruby/core/enumerable/tally_spec.rb +++ b/ruby/spec/ruby/core/enumerable/tally_spec.rb @@ -33,3 +33,50 @@ end end end + +ruby_version_is "3.1" do + describe "Enumerable#tally with a hash" do + before :each do + ScratchPad.record [] + end + + it "returns a hash with counts according to the value" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally({ 'foo' => 1 }).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1} + end + + it "returns the given hash" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + hash = { 'foo' => 1 } + enum.tally(hash).should equal(hash) + end + + it "raises a FrozenError and does not update the given hash when the hash is frozen" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + hash = { 'foo' => 1 }.freeze + -> { enum.tally(hash) }.should raise_error(FrozenError) + hash.should == { 'foo' => 1 } + end + + it "does not call given block" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally({ 'foo' => 1 }) { |v| ScratchPad << v } + ScratchPad.recorded.should == [] + end + + it "ignores the default value" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally(Hash.new(100)).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1} + end + + it "ignores the default proc" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally(Hash.new {100}).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1} + end + + it "needs the values counting each elements to be an integer" do + enum = EnumerableSpecs::Numerous.new('foo') + -> { enum.tally({ 'foo' => 'bar' }) }.should raise_error(TypeError) + end + end +end diff --git a/ruby/spec/ruby/core/enumerable/to_h_spec.rb b/ruby/spec/ruby/core/enumerable/to_h_spec.rb index 63bfdf19a..048913455 100644 --- a/ruby/spec/ruby/core/enumerable/to_h_spec.rb +++ b/ruby/spec/ruby/core/enumerable/to_h_spec.rb @@ -44,47 +44,45 @@ def enum.each(*args) -> { enum.to_h }.should raise_error(ArgumentError) end - ruby_version_is "2.6" do - context "with block" do - before do - @enum = EnumerableSpecs::EachDefiner.new(:a, :b) - end - - it "converts [key, value] pairs returned by the block to a hash" do - @enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } - end - - it "raises ArgumentError if block returns longer or shorter array" do - -> do - @enum.to_h { |k| [k, k.to_s, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) - - -> do - @enum.to_h { |k| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end - - it "raises TypeError if block returns something other than Array" do - -> do - @enum.to_h { |k| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end - - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) - - @enum.to_h { |k| x }.should == { :b => 'b' } - end - - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) - - -> do - @enum.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end + context "with block" do + before do + @enum = EnumerableSpecs::EachDefiner.new(:a, :b) + end + + it "converts [key, value] pairs returned by the block to a hash" do + @enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } + end + + it "raises ArgumentError if block returns longer or shorter array" do + -> do + @enum.to_h { |k| [k, k.to_s, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) + + -> do + @enum.to_h { |k| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end + + it "raises TypeError if block returns something other than Array" do + -> do + @enum.to_h { |k| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end + + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) + + @enum.to_h { |k| x }.should == { :b => 'b' } + end + + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) + + -> do + @enum.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) end end end diff --git a/ruby/spec/ruby/core/enumerable/uniq_spec.rb b/ruby/spec/ruby/core/enumerable/uniq_spec.rb index 82c041d4e..e58dd3636 100644 --- a/ruby/spec/ruby/core/enumerable/uniq_spec.rb +++ b/ruby/spec/ruby/core/enumerable/uniq_spec.rb @@ -79,8 +79,8 @@ def obj.eql?(o) end a.uniq.should == a - a[0].tainted?.should == true - a[1].tainted?.should == true + a[0].should.tainted? + a[1].should.tainted? a = Array.new(2) do obj = mock('0') @@ -98,8 +98,8 @@ def obj.eql?(o) end a.to_enum.uniq.size.should == 1 - a[0].tainted?.should == true - a[1].tainted?.should == true + a[0].should.tainted? + a[1].should.tainted? end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb index c8d91ebae..1837a4f24 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb @@ -1,11 +1,18 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#begin" do - it "returns the begin of the sequence" do - 1.step(10).begin.should == 1 - (1..10).step.begin.should == 1 - (1...10).step.begin.should == 1 +describe "Enumerator::ArithmeticSequence#begin" do + it "returns the begin of the sequence" do + 1.step(10).begin.should == 1 + (1..10).step.begin.should == 1 + (1...10).step.begin.should == 1 + end + + ruby_version_is "2.7" do + context "with beginless" do + it "returns nil as begin of the sequence" do + eval("(..10).step(1)").begin.should == nil + eval("(...10).step(1)").begin.should == nil + end end end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb index d7edf3a21..d4fff3e01 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb @@ -1,19 +1,17 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#each" do - before :each do - ScratchPad.record [] - @seq = 1.step(10, 4) - end +describe "Enumerator::ArithmeticSequence#each" do + before :each do + ScratchPad.record [] + @seq = 1.step(10, 4) + end - it "calls given block on each item of the sequence" do - @seq.each { |item| ScratchPad << item } - ScratchPad.recorded.should == [1, 5, 9] - end + it "calls given block on each item of the sequence" do + @seq.each { |item| ScratchPad << item } + ScratchPad.recorded.should == [1, 5, 9] + end - it "returns self" do - @seq.each { |item| }.should equal(@seq) - end + it "returns self" do + @seq.each { |item| }.should equal(@seq) end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb index 5a436e816..05429cac3 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb @@ -1,11 +1,16 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#end" do - it "returns the end of the sequence" do - 1.step(10).end.should == 10 - (1..10).step.end.should == 10 - (1...10).step(17).end.should == 10 +describe "Enumerator::ArithmeticSequence#end" do + it "returns the end of the sequence" do + 1.step(10).end.should == 10 + (1..10).step.end.should == 10 + (1...10).step(17).end.should == 10 + end + + context "with endless" do + it "returns nil as end of the sequence" do + (1..).step(1).end.should == nil + (1...).step(1).end.should == nil end end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb index 7895f9804..77eed02d8 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb @@ -1,20 +1,18 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#==" do - it "returns true if begin, end, step and exclude_end? are equal" do - 1.step(10).should == 1.step(10) - 1.step(10, 5).should == 1.step(10, 5) +describe "Enumerator::ArithmeticSequence#==" do + it "returns true if begin, end, step and exclude_end? are equal" do + 1.step(10).should == 1.step(10) + 1.step(10, 5).should == 1.step(10, 5) - (1..10).step.should == (1..10).step - (1...10).step(8).should == (1...10).step(8) + (1..10).step.should == (1..10).step + (1...10).step(8).should == (1...10).step(8) - # both have exclude_end? == false - (1..10).step(100).should == 1.step(10, 100) + # both have exclude_end? == false + (1..10).step(100).should == 1.step(10, 100) - ((1..10).step == (1..11).step).should == false - ((1..10).step == (1...10).step).should == false - ((1..10).step == (1..10).step(2)).should == false - end + ((1..10).step == (1..11).step).should == false + ((1..10).step == (1...10).step).should == false + ((1..10).step == (1..10).step(2)).should == false end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb index 8ce0ce0cd..021fe7d90 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb @@ -1,19 +1,17 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#exclude_end?" do - context "when created using Numeric#step" do - it "always returns false" do - 1.step(10).exclude_end?.should == false - 10.step(1).exclude_end?.should == false - end +describe "Enumerator::ArithmeticSequence#exclude_end?" do + context "when created using Numeric#step" do + it "always returns false" do + 1.step(10).should_not.exclude_end? + 10.step(1).should_not.exclude_end? end + end - context "when created using Range#step" do - it "mirrors range.exclude_end?" do - (1...10).step.exclude_end?.should == true - (1..10).step.exclude_end?.should == false - end + context "when created using Range#step" do + it "mirrors range.exclude_end?" do + (1...10).step.should.exclude_end? + (1..10).step.should_not.exclude_end? end end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb index 43c520d1f..ccd02be02 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb @@ -1,11 +1,9 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#first" do - it "returns the first element of the sequence" do - 1.step(10).first.should == 1 - (1..10).step.first.should == 1 - (1...10).step.first.should == 1 - end +describe "Enumerator::ArithmeticSequence#first" do + it "returns the first element of the sequence" do + 1.step(10).first.should == 1 + (1..10).step.first.should == 1 + (1...10).step.first.should == 1 end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb index 236f845f4..bdb308074 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb @@ -1,22 +1,20 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#hash" do - it "is based on begin, end, step and exclude_end?" do - 1.step(10).hash.should be_an_instance_of(Integer) +describe "Enumerator::ArithmeticSequence#hash" do + it "is based on begin, end, step and exclude_end?" do + 1.step(10).hash.should be_an_instance_of(Integer) - 1.step(10).hash.should == 1.step(10).hash - 1.step(10, 5).hash.should == 1.step(10, 5).hash + 1.step(10).hash.should == 1.step(10).hash + 1.step(10, 5).hash.should == 1.step(10, 5).hash - (1..10).step.hash.should == (1..10).step.hash - (1...10).step(8).hash.should == (1...10).step(8).hash + (1..10).step.hash.should == (1..10).step.hash + (1...10).step(8).hash.should == (1...10).step(8).hash - # both have exclude_end? == false - (1..10).step(100).hash.should == 1.step(10, 100).hash + # both have exclude_end? == false + (1..10).step(100).hash.should == 1.step(10, 100).hash - ((1..10).step.hash == (1..11).step.hash).should == false - ((1..10).step.hash == (1...10).step.hash).should == false - ((1..10).step.hash == (1..10).step(2).hash).should == false - end + ((1..10).step.hash == (1..11).step.hash).should == false + ((1..10).step.hash == (1...10).step.hash).should == false + ((1..10).step.hash == (1..10).step(2).hash).should == false end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb index 21e64a6b5..b73b49d27 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb @@ -1,22 +1,20 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#inspect" do - context 'when Numeric#step is used' do - it "returns '(begin.step(end{, step}))'" do - 1.step(10).inspect.should == "(1.step(10))" - 1.step(10, 3).inspect.should == "(1.step(10, 3))" - end +describe "Enumerator::ArithmeticSequence#inspect" do + context 'when Numeric#step is used' do + it "returns '(begin.step(end{, step}))'" do + 1.step(10).inspect.should == "(1.step(10))" + 1.step(10, 3).inspect.should == "(1.step(10, 3))" end + end - context 'when Range#step is used' do - it "returns '((range).step{(step)})'" do - (1..10).step.inspect.should == "((1..10).step)" - (1..10).step(3).inspect.should == "((1..10).step(3))" + context 'when Range#step is used' do + it "returns '((range).step{(step)})'" do + (1..10).step.inspect.should == "((1..10).step)" + (1..10).step(3).inspect.should == "((1..10).step(3))" - (1...10).step.inspect.should == "((1...10).step)" - (1...10).step(3).inspect.should == "((1...10).step(3))" - end + (1...10).step.inspect.should == "((1...10).step)" + (1...10).step(3).inspect.should == "((1...10).step(3))" end end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb index ebb20090f..31f982b7c 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb @@ -1,11 +1,9 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#last" do - it "returns the last element of the sequence" do - 1.step(10).last.should == 10 - (1..10).step.last.should == 10 - (1...10).step(4).last.should == 9 - end +describe "Enumerator::ArithmeticSequence#last" do + it "returns the last element of the sequence" do + 1.step(10).last.should == 10 + (1..10).step.last.should == 10 + (1...10).step(4).last.should == 9 end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb index 7227581fb..201598382 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb @@ -1,19 +1,17 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence.new" do - it "is not defined" do - -> { - Enumerator::ArithmeticSequence.new - }.should raise_error(NoMethodError) - end +describe "Enumerator::ArithmeticSequence.new" do + it "is not defined" do + -> { + Enumerator::ArithmeticSequence.new + }.should raise_error(NoMethodError) end +end - describe "Enumerator::ArithmeticSequence.allocate" do - it "is not defined" do - -> { - Enumerator::ArithmeticSequence.allocate - }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence') - end +describe "Enumerator::ArithmeticSequence.allocate" do + it "is not defined" do + -> { + Enumerator::ArithmeticSequence.allocate + }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence') end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb index 00403b023..7e03edd96 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb @@ -1,19 +1,17 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#size" do - context "for finite sequence" do - it "returns the number of elements in this arithmetic sequence" do - 1.step(10).size.should == 10 - (1...10).step.size.should == 9 - end +describe "Enumerator::ArithmeticSequence#size" do + context "for finite sequence" do + it "returns the number of elements in this arithmetic sequence" do + 1.step(10).size.should == 10 + (1...10).step.size.should == 9 end + end - context "for infinite sequence" do - it "returns Infinity" do - 1.step(Float::INFINITY).size.should == Float::INFINITY - (1..Float::INFINITY).step.size.should == Float::INFINITY - end + context "for infinite sequence" do + it "returns Infinity" do + 1.step(Float::INFINITY).size.should == Float::INFINITY + (1..Float::INFINITY).step.size.should == Float::INFINITY end end end diff --git a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb index 20a5cb6e7..c1f2d9173 100644 --- a/ruby/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb +++ b/ruby/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb @@ -1,15 +1,11 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence#step" do - it "returns the original value given to step method" do - (1..10).step.step.should == 1 - (1..10).step(3).step.should == 3 - (1..10).step(0).step.should == 0 +describe "Enumerator::ArithmeticSequence#step" do + it "returns the original value given to step method" do + (1..10).step.step.should == 1 + (1..10).step(3).step.should == 3 - 1.step(10).step.should == 1 - 1.step(10, 3).step.should == 3 - 1.step(10, 0).step.should == 0 - end + 1.step(10).step.should == 1 + 1.step(10, 3).step.should == 3 end end diff --git a/ruby/spec/ruby/core/enumerator/chain/each_spec.rb b/ruby/spec/ruby/core/enumerator/chain/each_spec.rb index ab4d355f2..cc93cbac6 100644 --- a/ruby/spec/ruby/core/enumerator/chain/each_spec.rb +++ b/ruby/spec/ruby/core/enumerator/chain/each_spec.rb @@ -1,17 +1,15 @@ require_relative '../../../spec_helper' require_relative '../../enumerable/fixtures/classes' -ruby_version_is "2.6" do - describe "Enumerator::Chain#each" do - it "calls each on its constituents as needed" do - a = EnumerableSpecs::EachCounter.new(:a, :b) - b = EnumerableSpecs::EachCounter.new(:c, :d) +describe "Enumerator::Chain#each" do + it "calls each on its constituents as needed" do + a = EnumerableSpecs::EachCounter.new(:a, :b) + b = EnumerableSpecs::EachCounter.new(:c, :d) - ScratchPad.record [] - Enumerator::Chain.new(a, b).each do |elem| - ScratchPad << elem << b.times_yielded - end - ScratchPad.recorded.should == [:a, 0, :b, 0, :c, 1, :d, 2] + ScratchPad.record [] + Enumerator::Chain.new(a, b).each do |elem| + ScratchPad << elem << b.times_yielded end + ScratchPad.recorded.should == [:a, 0, :b, 0, :c, 1, :d, 2] end end diff --git a/ruby/spec/ruby/core/enumerator/chain/initialize_spec.rb b/ruby/spec/ruby/core/enumerator/chain/initialize_spec.rb index e5aa32fd0..69484dfcb 100644 --- a/ruby/spec/ruby/core/enumerator/chain/initialize_spec.rb +++ b/ruby/spec/ruby/core/enumerator/chain/initialize_spec.rb @@ -1,33 +1,31 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::Chain#initialize" do - before :each do - @uninitialized = Enumerator::Chain.allocate - end +describe "Enumerator::Chain#initialize" do + before :each do + @uninitialized = Enumerator::Chain.allocate + end - it "is a private method" do - Enumerator::Chain.should have_private_instance_method(:initialize, false) - end + it "is a private method" do + Enumerator::Chain.should have_private_instance_method(:initialize, false) + end - it "returns self" do - @uninitialized.send(:initialize).should equal(@uninitialized) - end + it "returns self" do + @uninitialized.send(:initialize).should equal(@uninitialized) + end - it "accepts many arguments" do - @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized) - end + it "accepts many arguments" do + @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized) + end - it "accepts arguments that are not Enumerable nor responding to :each" do - @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) - end + it "accepts arguments that are not Enumerable nor responding to :each" do + @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + end - describe "on frozen instance" do - it "raises a RuntimeError" do - -> { - @uninitialized.freeze.send(:initialize) - }.should raise_error(RuntimeError) - end + describe "on frozen instance" do + it "raises a RuntimeError" do + -> { + @uninitialized.freeze.send(:initialize) + }.should raise_error(RuntimeError) end end end diff --git a/ruby/spec/ruby/core/enumerator/chain/inspect_spec.rb b/ruby/spec/ruby/core/enumerator/chain/inspect_spec.rb index a644d88c6..a0450c808 100644 --- a/ruby/spec/ruby/core/enumerator/chain/inspect_spec.rb +++ b/ruby/spec/ruby/core/enumerator/chain/inspect_spec.rb @@ -1,16 +1,14 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::Chain#inspect" do - it "shows a representation of the Enumerator" do - Enumerator::Chain.new.inspect.should == "#" - Enumerator::Chain.new(1..2, 3..4).inspect.should == "#" - end +describe "Enumerator::Chain#inspect" do + it "shows a representation of the Enumerator" do + Enumerator::Chain.new.inspect.should == "#" + Enumerator::Chain.new(1..2, 3..4).inspect.should == "#" + end - it "calls inspect on its chain elements" do - obj = mock('inspect') - obj.should_receive(:inspect).and_return('some desc') - Enumerator::Chain.new(obj).inspect.should == "#" - end + it "calls inspect on its chain elements" do + obj = mock('inspect') + obj.should_receive(:inspect).and_return('some desc') + Enumerator::Chain.new(obj).inspect.should == "#" end end diff --git a/ruby/spec/ruby/core/enumerator/chain/rewind_spec.rb b/ruby/spec/ruby/core/enumerator/chain/rewind_spec.rb index 951b364f0..5f51ce2cf 100644 --- a/ruby/spec/ruby/core/enumerator/chain/rewind_spec.rb +++ b/ruby/spec/ruby/core/enumerator/chain/rewind_spec.rb @@ -1,53 +1,51 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::Chain#rewind" do - before(:each) do - @obj = mock('obj') - @obj.should_receive(:each).any_number_of_times.and_yield - @second = mock('obj') - @second.should_receive(:each).any_number_of_times.and_yield - @enum = Enumerator::Chain.new(@obj, @second) - end - - it "returns self" do - @enum.rewind.should equal @enum - end - - it "does nothing if receiver has not been iterated" do - @obj.should_not_receive(:rewind) - @obj.respond_to?(:rewind).should == true # sanity check - @enum.rewind - end - - it "does nothing on objects that don't respond_to rewind" do - @obj.respond_to?(:rewind).should == false # sanity check - @enum.each {} - @enum.rewind - end - - it "calls_rewind its objects" do - @obj.should_receive(:rewind) - @enum.each {} - @enum.rewind - end - - it "calls_rewind in reverse order" do - @obj.should_not_receive(:rewind) - @second.should_receive(:rewind).and_raise(RuntimeError) - @enum.each {} - -> { @enum.rewind }.should raise_error(RuntimeError) - end - - it "calls rewind only for objects that have actually been iterated on" do - @obj = mock('obj') - @obj.should_receive(:each).any_number_of_times.and_raise(RuntimeError) - @enum = Enumerator::Chain.new(@obj, @second) - - @obj.should_receive(:rewind) - @second.should_not_receive(:rewind) - -> { @enum.each {} }.should raise_error(RuntimeError) - @enum.rewind - end +describe "Enumerator::Chain#rewind" do + before(:each) do + @obj = mock('obj') + @obj.should_receive(:each).any_number_of_times.and_yield + @second = mock('obj') + @second.should_receive(:each).any_number_of_times.and_yield + @enum = Enumerator::Chain.new(@obj, @second) + end + + it "returns self" do + @enum.rewind.should equal @enum + end + + it "does nothing if receiver has not been iterated" do + @obj.should_not_receive(:rewind) + @obj.respond_to?(:rewind).should == true # sanity check + @enum.rewind + end + + it "does nothing on objects that don't respond_to rewind" do + @obj.respond_to?(:rewind).should == false # sanity check + @enum.each {} + @enum.rewind + end + + it "calls_rewind its objects" do + @obj.should_receive(:rewind) + @enum.each {} + @enum.rewind + end + + it "calls_rewind in reverse order" do + @obj.should_not_receive(:rewind) + @second.should_receive(:rewind).and_raise(RuntimeError) + @enum.each {} + -> { @enum.rewind }.should raise_error(RuntimeError) + end + + it "calls rewind only for objects that have actually been iterated on" do + @obj = mock('obj') + @obj.should_receive(:each).any_number_of_times.and_raise(RuntimeError) + @enum = Enumerator::Chain.new(@obj, @second) + + @obj.should_receive(:rewind) + @second.should_not_receive(:rewind) + -> { @enum.each {} }.should raise_error(RuntimeError) + @enum.rewind end end diff --git a/ruby/spec/ruby/core/enumerator/chain/size_spec.rb b/ruby/spec/ruby/core/enumerator/chain/size_spec.rb index 42c31ac10..d85b88ee8 100644 --- a/ruby/spec/ruby/core/enumerator/chain/size_spec.rb +++ b/ruby/spec/ruby/core/enumerator/chain/size_spec.rb @@ -1,24 +1,22 @@ require_relative '../../../spec_helper' require_relative '../../enumerable/fixtures/classes' -ruby_version_is "2.6" do - describe "Enumerator::Chain#size" do - it "returns the sum of the sizes of the elements" do +describe "Enumerator::Chain#size" do + it "returns the sum of the sizes of the elements" do + a = mock('size') + a.should_receive(:size).and_return(40) + Enumerator::Chain.new(a, [:a, :b]).size.should == 42 + end + + it "returns nil or Infinity for the first element of such a size" do + [nil, Float::INFINITY].each do |special| a = mock('size') a.should_receive(:size).and_return(40) - Enumerator::Chain.new(a, [:a, :b]).size.should == 42 - end - - it "returns nil or Infinity for the first element of such a size" do - [nil, Float::INFINITY].each do |special| - a = mock('size') - a.should_receive(:size).and_return(40) - b = mock('special') - b.should_receive(:size).and_return(special) - c = mock('not called') - c.should_not_receive(:size) - Enumerator::Chain.new(a, b, c).size.should == special - end + b = mock('special') + b.should_receive(:size).and_return(special) + c = mock('not called') + c.should_not_receive(:size) + Enumerator::Chain.new(a, b, c).size.should == special end end end diff --git a/ruby/spec/ruby/core/enumerator/each_spec.rb b/ruby/spec/ruby/core/enumerator/each_spec.rb index d88c09cdb..99ac3120a 100644 --- a/ruby/spec/ruby/core/enumerator/each_spec.rb +++ b/ruby/spec/ruby/core/enumerator/each_spec.rb @@ -40,10 +40,10 @@ def object_each_with_arguments.each_with_arguments(arg, *args) end it "calls the method given in the constructor until it's exhausted" do - each = mock('each') - each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3) + each = mock('peach') + each.should_receive(:peach).and_yield(1).and_yield(2).and_yield(3) acc = [] - each.to_enum.each {|e| acc << e } + each.to_enum(:peach).each {|e| acc << e } acc.should == [1,2,3] end diff --git a/ruby/spec/ruby/core/enumerator/initialize_spec.rb b/ruby/spec/ruby/core/enumerator/initialize_spec.rb index 53bf5d4ef..217af1d3b 100644 --- a/ruby/spec/ruby/core/enumerator/initialize_spec.rb +++ b/ruby/spec/ruby/core/enumerator/initialize_spec.rb @@ -11,8 +11,12 @@ Enumerator.should have_private_instance_method(:initialize, false) end - it "returns self when given an object" do - @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + ruby_version_is ''...'3.0' do + it "returns self when given an object" do + suppress_warning do + @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + end + end end it "returns self when given a block" do @@ -43,7 +47,7 @@ @uninitialized.send(:initialize, Float::INFINITY) {}.size.should equal(Float::INFINITY) end - it "sets size to the given size if the given size is a Fixnum" do + it "sets size to the given size if the given size is an Integer" do @uninitialized.send(:initialize, 100) {}.size.should == 100 end diff --git a/ruby/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb index d55508987..772bd42de 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb @@ -6,4 +6,9 @@ s.lazy.chunk_while { |a, b| false }.first(100).should == s.first(100).chunk_while { |a, b| false }.to_a end + + it "should return a lazy enumerator" do + s = 0..Float::INFINITY + s.lazy.chunk_while { |a, b| false }.should be_kind_of(Enumerator::Lazy) + end end diff --git a/ruby/spec/ruby/core/enumerator/lazy/eager_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/eager_spec.rb new file mode 100644 index 000000000..30ba2dfe0 --- /dev/null +++ b/ruby/spec/ruby/core/enumerator/lazy/eager_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../../spec_helper' + +ruby_version_is "2.7" do + describe "Enumerator::Lazy#eager" do + it "returns a non-lazy Enumerator converted from the lazy enumerator" do + enum = [1, 2, 3].lazy + + enum.class.should == Enumerator::Lazy + enum.eager.class.should == Enumerator + end + + it "does not enumerate an enumerator" do + ScratchPad.record [] + + sequence = [1, 2, 3] + enum_lazy = Enumerator::Lazy.new(sequence) do |yielder, value| + yielder << value + ScratchPad << value + end + + ScratchPad.recorded.should == [] + enum = enum_lazy.eager + ScratchPad.recorded.should == [] + + enum.map { |i| i }.should == [1, 2, 3] + ScratchPad.recorded.should == [1, 2, 3] + end + end +end diff --git a/ruby/spec/ruby/core/enumerator/lazy/filter_map_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/filter_map_spec.rb new file mode 100644 index 000000000..3480af086 --- /dev/null +++ b/ruby/spec/ruby/core/enumerator/lazy/filter_map_spec.rb @@ -0,0 +1,16 @@ +# -*- encoding: us-ascii -*- + +require_relative '../../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "2.7" do + describe "Enumerator::Lazy#filter_map" do + it "maps only truthy results" do + (1..Float::INFINITY).lazy.filter_map { |i| i if i.odd? }.first(4).should == [1, 3, 5, 7] + end + + it "does not map false results" do + (1..Float::INFINITY).lazy.filter_map { |i| i.odd? ? i : false }.first(4).should == [1, 3, 5, 7] + end + end +end diff --git a/ruby/spec/ruby/core/enumerator/lazy/filter_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/filter_spec.rb index 2ababa69c..43128241e 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/filter_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/filter_spec.rb @@ -1,8 +1,6 @@ require_relative '../../../spec_helper' require_relative 'shared/select' -ruby_version_is "2.6" do - describe "Enumerator::Lazy#filter" do - it_behaves_like :enumerator_lazy_select, :filter - end +describe "Enumerator::Lazy#filter" do + it_behaves_like :enumerator_lazy_select, :filter end diff --git a/ruby/spec/ruby/core/enumerator/lazy/initialize_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/initialize_spec.rb index 88c66530b..f23018d01 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/initialize_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/initialize_spec.rb @@ -43,7 +43,7 @@ def receiver.each @uninitialized.send(:initialize, @receiver, Float::INFINITY) {}.size.should equal(Float::INFINITY) end - it "sets given size to own size if the given size is a Fixnum" do + it "sets given size to own size if the given size is an Integer" do @uninitialized.send(:initialize, @receiver, 100) {}.size.should == 100 end diff --git a/ruby/spec/ruby/core/enumerator/lazy/slice_after_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/slice_after_spec.rb index 438df8d55..8b08a1ecf 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/slice_after_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/slice_after_spec.rb @@ -6,4 +6,9 @@ s.lazy.slice_after { |n| true }.first(100).should == s.first(100).slice_after { |n| true }.to_a end + + it "should return a lazy enumerator" do + s = 0..Float::INFINITY + s.lazy.slice_after { |n| true }.should be_kind_of(Enumerator::Lazy) + end end diff --git a/ruby/spec/ruby/core/enumerator/lazy/slice_before_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/slice_before_spec.rb index 6c8660c1a..9c1ec9ba4 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/slice_before_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/slice_before_spec.rb @@ -6,4 +6,9 @@ s.lazy.slice_before { |n| true }.first(100).should == s.first(100).slice_before { |n| true }.to_a end + + it "should return a lazy enumerator" do + s = 0..Float::INFINITY + s.lazy.slice_before { |n| true }.should be_kind_of(Enumerator::Lazy) + end end diff --git a/ruby/spec/ruby/core/enumerator/lazy/slice_when_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/slice_when_spec.rb index e7673def4..f83403425 100644 --- a/ruby/spec/ruby/core/enumerator/lazy/slice_when_spec.rb +++ b/ruby/spec/ruby/core/enumerator/lazy/slice_when_spec.rb @@ -6,4 +6,9 @@ s.lazy.slice_when { |a, b| true }.first(100).should == s.first(100).slice_when { |a, b| true }.to_a end + + it "should return a lazy enumerator" do + s = 0..Float::INFINITY + s.lazy.slice_when { |a, b| true }.should be_kind_of(Enumerator::Lazy) + end end diff --git a/ruby/spec/ruby/core/enumerator/lazy/with_index_spec.rb b/ruby/spec/ruby/core/enumerator/lazy/with_index_spec.rb new file mode 100644 index 000000000..3a59ba411 --- /dev/null +++ b/ruby/spec/ruby/core/enumerator/lazy/with_index_spec.rb @@ -0,0 +1,30 @@ +# -*- encoding: us-ascii -*- + +require_relative '../../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "2.7" do + describe "Enumerator::Lazy#with_index" do + it "enumerates with an index" do + (0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]] + end + + it "enumerates with an index starting at a given offset" do + (0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]] + end + + it "enumerates with an index starting at 0 when offset is nil" do + (0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]] + end + + it "raises TypeError when offset does not convert to Integer" do + -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError) + end + + it "enumerates with a given block" do + result = [] + (0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3) + result.should == [[0,0],[2,1],[4,2]] + end + end +end diff --git a/ruby/spec/ruby/core/enumerator/new_spec.rb b/ruby/spec/ruby/core/enumerator/new_spec.rb index 170809dbc..5cc0b3ff2 100644 --- a/ruby/spec/ruby/core/enumerator/new_spec.rb +++ b/ruby/spec/ruby/core/enumerator/new_spec.rb @@ -1,41 +1,121 @@ require_relative '../../spec_helper' describe "Enumerator.new" do - it "creates a new custom enumerator with the given object, iterator and arguments" do - enum = Enumerator.new(1, :upto, 3) - enum.should be_an_instance_of(Enumerator) - end + context "no block given" do + ruby_version_is '3.0' do + it "raises" do + -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError) + end + end - it "creates a new custom enumerator that responds to #each" do - enum = Enumerator.new(1, :upto, 3) - enum.respond_to?(:each).should == true - end + ruby_version_is ''...'3.0' do + it "creates a new custom enumerator with the given object, iterator and arguments" do + enum = suppress_warning { Enumerator.new(1, :upto, 3) } + enum.should be_an_instance_of(Enumerator) + end - it "creates a new custom enumerator that runs correctly" do - Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3] - end + it "creates a new custom enumerator that responds to #each" do + enum = suppress_warning { Enumerator.new(1, :upto, 3) } + enum.respond_to?(:each).should == true + end - it "aliases the second argument to :each" do - Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a - end + it "creates a new custom enumerator that runs correctly" do + suppress_warning { Enumerator.new(1, :upto, 3) }.map{ |x| x }.should == [1,2,3] + end - it "doesn't check for the presence of the iterator method" do - Enumerator.new(nil).should be_an_instance_of(Enumerator) + it "aliases the second argument to :each" do + suppress_warning { Enumerator.new(1..2) }.to_a.should == + suppress_warning { Enumerator.new(1..2, :each) }.to_a + end + + it "doesn't check for the presence of the iterator method" do + suppress_warning { Enumerator.new(nil) }.should be_an_instance_of(Enumerator) + end + + it "uses the latest define iterator method" do + class StrangeEach + def each + yield :foo + end + end + enum = suppress_warning { Enumerator.new(StrangeEach.new) } + enum.to_a.should == [:foo] + class StrangeEach + def each + yield :bar + end + end + enum.to_a.should == [:bar] + end + end end - it "uses the latest define iterator method" do - class StrangeEach - def each - yield :foo + context "when passed a block" do + it "defines iteration with block, yielder argument and calling << method" do + enum = Enumerator.new do |yielder| + a = 1 + + loop do + yielder << a + a = a + 1 + end end + + enum.take(3).should == [1, 2, 3] end - enum = Enumerator.new(StrangeEach.new) - enum.to_a.should == [:foo] - class StrangeEach - def each - yield :bar + + it "defines iteration with block, yielder argument and calling yield method" do + enum = Enumerator.new do |yielder| + a = 1 + + loop do + yielder.yield(a) + a = a + 1 + end + end + + enum.take(3).should == [1, 2, 3] + end + + ruby_version_is "2.7" do + it "defines iteration with block, yielder argument and treating it as a proc" do + enum = Enumerator.new do |yielder| + "a\nb\nc".each_line(&yielder) + end + + enum.to_a.should == ["a\n", "b\n", "c"] + end + end + + describe 'yielded values' do + it 'handles yield arguments properly' do + Enumerator.new { |y| y.yield(1) }.to_a.should == [1] + Enumerator.new { |y| y.yield(1) }.first.should == 1 + + Enumerator.new { |y| y.yield([1]) }.to_a.should == [[1]] + Enumerator.new { |y| y.yield([1]) }.first.should == [1] + + Enumerator.new { |y| y.yield(1, 2) }.to_a.should == [[1, 2]] + Enumerator.new { |y| y.yield(1, 2) }.first.should == [1, 2] + + Enumerator.new { |y| y.yield([1, 2]) }.to_a.should == [[1, 2]] + Enumerator.new { |y| y.yield([1, 2]) }.first.should == [1, 2] + end + + it 'handles << arguments properly' do + Enumerator.new { |y| y.<<(1) }.to_a.should == [1] + Enumerator.new { |y| y.<<(1) }.first.should == 1 + + Enumerator.new { |y| y.<<([1]) }.to_a.should == [[1]] + Enumerator.new { |y| y.<<([1]) }.first.should == [1] + + # << doesn't accept multiple arguments + # Enumerator.new { |y| y.<<(1, 2) }.to_a.should == [[1, 2]] + # Enumerator.new { |y| y.<<(1, 2) }.first.should == [1, 2] + + Enumerator.new { |y| y.<<([1, 2]) }.to_a.should == [[1, 2]] + Enumerator.new { |y| y.<<([1, 2]) }.first.should == [1, 2] end end - enum.to_a.should == [:bar] end end diff --git a/ruby/spec/ruby/core/enumerator/next_spec.rb b/ruby/spec/ruby/core/enumerator/next_spec.rb index 3e9ed8b01..a5e01a399 100644 --- a/ruby/spec/ruby/core/enumerator/next_spec.rb +++ b/ruby/spec/ruby/core/enumerator/next_spec.rb @@ -24,4 +24,15 @@ @enum.rewind @enum.next.should == 1 end + + it "restarts the enumerator if an exception terminated a previous iteration" do + exception = StandardError.new + enum = Enumerator.new do + raise exception + end + + result = 2.times.map { enum.next rescue $! } + + result.should == [exception, exception] + end end diff --git a/ruby/spec/ruby/core/enumerator/plus_spec.rb b/ruby/spec/ruby/core/enumerator/plus_spec.rb index c9bae08b0..755be5b4e 100644 --- a/ruby/spec/ruby/core/enumerator/plus_spec.rb +++ b/ruby/spec/ruby/core/enumerator/plus_spec.rb @@ -1,35 +1,33 @@ require_relative '../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator#+" do - before :each do - ScratchPad.record [] - end +describe "Enumerator#+" do + before :each do + ScratchPad.record [] + end - it "returns a chain of self and provided enumerators" do - one = Enumerator.new { |y| y << 1 } - two = Enumerator.new { |y| y << 2 } - three = Enumerator.new { |y| y << 3 } + it "returns a chain of self and provided enumerators" do + one = Enumerator.new { |y| y << 1 } + two = Enumerator.new { |y| y << 2 } + three = Enumerator.new { |y| y << 3 } - chain = one + two + three + chain = one + two + three - chain.should be_an_instance_of(Enumerator::Chain) - chain.each { |item| ScratchPad << item } - ScratchPad.recorded.should == [1, 2, 3] - end + chain.should be_an_instance_of(Enumerator::Chain) + chain.each { |item| ScratchPad << item } + ScratchPad.recorded.should == [1, 2, 3] + end - it "calls #each on each argument" do - enum = Enumerator.new { |y| y << "one" } + it "calls #each on each argument" do + enum = Enumerator.new { |y| y << "one" } - obj1 = mock("obj1") - obj1.should_receive(:each).once.and_yield("two") + obj1 = mock("obj1") + obj1.should_receive(:each).once.and_yield("two") - obj2 = mock("obj2") - obj2.should_receive(:each).once.and_yield("three") + obj2 = mock("obj2") + obj2.should_receive(:each).once.and_yield("three") - chain = enum + obj1 + obj2 - chain.each { |item| ScratchPad << item } - ScratchPad.recorded.should == ["one", "two", "three"] - end + chain = enum + obj1 + obj2 + chain.each { |item| ScratchPad << item } + ScratchPad.recorded.should == ["one", "two", "three"] end end diff --git a/ruby/spec/ruby/core/enumerator/produce_spec.rb b/ruby/spec/ruby/core/enumerator/produce_spec.rb new file mode 100644 index 000000000..f6f1dcd42 --- /dev/null +++ b/ruby/spec/ruby/core/enumerator/produce_spec.rb @@ -0,0 +1,36 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Enumerator.produce" do + it "creates an infinite enumerator" do + enum = Enumerator.produce(0) { |prev| prev + 1 } + enum.take(5).should == [0, 1, 2, 3, 4] + end + + it "terminates iteration when block raises StopIteration exception" do + enum = Enumerator.produce(0) do | prev| + raise StopIteration if prev >= 2 + prev + 1 + end + + enum.to_a.should == [0, 1, 2] + end + + context "when initial value skipped" do + it "uses nil instead" do + ScratchPad.record [] + enum = Enumerator.produce { |prev| ScratchPad << prev; (prev || 0) + 1 } + + enum.take(3).should == [1, 2, 3] + ScratchPad.recorded.should == [nil, 1, 2] + end + + it "starts enumerable from result of first block call" do + array = "a\nb\nc\nd".lines + lines = Enumerator.produce { array.shift }.take_while { |s| s } + + lines.should == ["a\n", "b\n", "c\n", "d"] + end + end + end +end diff --git a/ruby/spec/ruby/core/enumerator/yielder/append_spec.rb b/ruby/spec/ruby/core/enumerator/yielder/append_spec.rb index dac66585a..a36e5d64b 100644 --- a/ruby/spec/ruby/core/enumerator/yielder/append_spec.rb +++ b/ruby/spec/ruby/core/enumerator/yielder/append_spec.rb @@ -21,4 +21,15 @@ y = Enumerator::Yielder.new {|x| x + 1} (y << 1).should equal(y) end + + context "when multiple arguments passed" do + it "raises an ArgumentError" do + ary = [] + y = Enumerator::Yielder.new { |*x| ary << x } + + -> { + y.<<(1, 2) + }.should raise_error(ArgumentError, /wrong number of arguments/) + end + end end diff --git a/ruby/spec/ruby/core/enumerator/yielder/to_proc_spec.rb b/ruby/spec/ruby/core/enumerator/yielder/to_proc_spec.rb new file mode 100644 index 000000000..0ed164585 --- /dev/null +++ b/ruby/spec/ruby/core/enumerator/yielder/to_proc_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../../spec_helper' + +ruby_version_is "2.7" do + describe "Enumerator::Yielder#to_proc" do + it "returns a Proc object that takes an argument and yields it to the block" do + ScratchPad.record [] + y = Enumerator::Yielder.new { |*args| ScratchPad << args; "foobar" } + + callable = y.to_proc + callable.class.should == Proc + + result = callable.call(1, 2) + ScratchPad.recorded.should == [[1, 2]] + + result.should == "foobar" + end + end +end diff --git a/ruby/spec/ruby/core/enumerator/yielder/yield_spec.rb b/ruby/spec/ruby/core/enumerator/yielder/yield_spec.rb index 58fc8e007..acfdf114b 100644 --- a/ruby/spec/ruby/core/enumerator/yielder/yield_spec.rb +++ b/ruby/spec/ruby/core/enumerator/yielder/yield_spec.rb @@ -20,4 +20,14 @@ y = Enumerator::Yielder.new {|x| x + 1} y.yield(1).should == 2 end + + context "when multiple arguments passed" do + it "yields the arguments list to the block" do + ary = [] + y = Enumerator::Yielder.new { |*x| ary << x } + y.yield(1, 2) + + ary.should == [[1, 2]] + end + end end diff --git a/ruby/spec/ruby/core/env/delete_spec.rb b/ruby/spec/ruby/core/env/delete_spec.rb index f11860b21..5e7891f74 100644 --- a/ruby/spec/ruby/core/env/delete_spec.rb +++ b/ruby/spec/ruby/core/env/delete_spec.rb @@ -30,6 +30,13 @@ ScratchPad.recorded.should == "foo" end + ruby_version_is "3.0" do + it "returns the result of given block if the named environment variable does not exist" do + ENV.delete("foo") + ENV.delete("foo") { |name| "bar" }.should == "bar" + end + end + it "does not evaluate the block if the environment variable exists" do ENV["foo"] = "bar" ENV.delete("foo") { |name| fail "Should not happen" } diff --git a/ruby/spec/ruby/core/env/element_reference_spec.rb b/ruby/spec/ruby/core/env/element_reference_spec.rb index 7d2a2d78e..560c127a9 100644 --- a/ruby/spec/ruby/core/env/element_reference_spec.rb +++ b/ruby/spec/ruby/core/env/element_reference_spec.rb @@ -1,5 +1,6 @@ # -*- encoding: binary -*- require_relative '../../spec_helper' +require_relative 'fixtures/common' describe "ENV.[]" do before :each do @@ -16,7 +17,7 @@ it "returns only frozen values" do ENV[@variable] = "a non-frozen string" - ENV[@variable].frozen?.should == true + ENV[@variable].should.frozen? end it "coerces a non-string name with #to_str" do @@ -58,7 +59,7 @@ it "uses the locale encoding if Encoding.default_internal is nil" do Encoding.default_internal = nil - locale = Encoding.find('locale') + locale = ENVSpecs.encoding locale = Encoding::BINARY if locale == Encoding::US_ASCII ENV[@variable] = "\xC3\xB8" ENV[@variable].encoding.should == locale diff --git a/ruby/spec/ruby/core/env/empty_spec.rb b/ruby/spec/ruby/core/env/empty_spec.rb index 7ef17d244..afeb406a9 100644 --- a/ruby/spec/ruby/core/env/empty_spec.rb +++ b/ruby/spec/ruby/core/env/empty_spec.rb @@ -4,12 +4,12 @@ it "returns true if the Environment is empty" do if ENV.keys.size > 0 - ENV.empty?.should == false + ENV.should_not.empty? end orig = ENV.to_hash begin ENV.clear - ENV.empty?.should == true + ENV.should.empty? ensure ENV.replace orig end @@ -17,7 +17,7 @@ it "returns false if not empty" do if ENV.keys.size > 0 - ENV.empty?.should == false + ENV.should_not.empty? end end end diff --git a/ruby/spec/ruby/core/env/except_spec.rb b/ruby/spec/ruby/core/env/except_spec.rb new file mode 100644 index 000000000..cfe5865ab --- /dev/null +++ b/ruby/spec/ruby/core/env/except_spec.rb @@ -0,0 +1,36 @@ +require_relative 'spec_helper' +require_relative 'shared/to_hash' + +ruby_version_is "3.0" do + describe "ENV.except" do + before do + @orig_hash = ENV.to_hash + end + + after do + ENV.replace @orig_hash + end + + # Testing the method without arguments is covered via + it_behaves_like :env_to_hash, :except + + it "returns a hash without the requested subset" do + ENV.clear + + ENV['one'] = '1' + ENV['two'] = '2' + ENV['three'] = '3' + + ENV.except('one', 'three').should == { 'two' => '2' } + end + + it "ignores keys not present in the original hash" do + ENV.clear + + ENV['one'] = '1' + ENV['two'] = '2' + + ENV.except('one', 'three').should == { 'two' => '2' } + end + end +end diff --git a/ruby/spec/ruby/core/env/fetch_spec.rb b/ruby/spec/ruby/core/env/fetch_spec.rb index ef8f0a4ed..b2e7a88ca 100644 --- a/ruby/spec/ruby/core/env/fetch_spec.rb +++ b/ruby/spec/ruby/core/env/fetch_spec.rb @@ -1,5 +1,6 @@ require_relative '../../spec_helper' require_relative '../../shared/hash/key_error' +require_relative 'fixtures/common' describe "ENV.fetch" do before :each do @@ -57,6 +58,6 @@ it "uses the locale encoding" do ENV["foo"] = "bar" - ENV.fetch("foo").encoding.should == Encoding.find('locale') + ENV.fetch("foo").encoding.should == ENVSpecs.encoding end end diff --git a/ruby/spec/ruby/core/env/filter_spec.rb b/ruby/spec/ruby/core/env/filter_spec.rb index ba18a3b33..52f8b79a0 100644 --- a/ruby/spec/ruby/core/env/filter_spec.rb +++ b/ruby/spec/ruby/core/env/filter_spec.rb @@ -2,14 +2,12 @@ require_relative '../enumerable/shared/enumeratorized' require_relative 'shared/select' -ruby_version_is "2.6" do - describe "ENV.filter!" do - it_behaves_like :env_select!, :filter! - it_behaves_like :enumeratorized_with_origin_size, :filter!, ENV - end +describe "ENV.filter!" do + it_behaves_like :env_select!, :filter! + it_behaves_like :enumeratorized_with_origin_size, :filter!, ENV +end - describe "ENV.filter" do - it_behaves_like :env_select, :filter - it_behaves_like :enumeratorized_with_origin_size, :filter, ENV - end +describe "ENV.filter" do + it_behaves_like :env_select, :filter + it_behaves_like :enumeratorized_with_origin_size, :filter, ENV end diff --git a/ruby/spec/ruby/core/env/fixtures/common.rb b/ruby/spec/ruby/core/env/fixtures/common.rb new file mode 100644 index 000000000..8d5057614 --- /dev/null +++ b/ruby/spec/ruby/core/env/fixtures/common.rb @@ -0,0 +1,9 @@ +module ENVSpecs + def self.encoding + locale = Encoding.find('locale') + if ruby_version_is '3' and platform_is :windows + locale = Encoding::UTF_8 + end + locale + end +end diff --git a/ruby/spec/ruby/core/env/index_spec.rb b/ruby/spec/ruby/core/env/index_spec.rb index 43875f5a5..301a66ab4 100644 --- a/ruby/spec/ruby/core/env/index_spec.rb +++ b/ruby/spec/ruby/core/env/index_spec.rb @@ -1,12 +1,14 @@ require_relative '../../spec_helper' require_relative 'shared/key' -describe "ENV.index" do - it_behaves_like :env_key, :index +ruby_version_is ''...'3.0' do + describe "ENV.index" do + it_behaves_like :env_key, :index - it "warns about deprecation" do - -> do - ENV.index("foo") - end.should complain(/warning: ENV.index is deprecated; use ENV.key/) + it "warns about deprecation" do + -> do + ENV.index("foo") + end.should complain(/warning: ENV.index is deprecated; use ENV.key/) + end end end diff --git a/ruby/spec/ruby/core/env/shared/key.rb b/ruby/spec/ruby/core/env/shared/key.rb index fcb3a9b8c..93396d2ac 100644 --- a/ruby/spec/ruby/core/env/shared/key.rb +++ b/ruby/spec/ruby/core/env/shared/key.rb @@ -9,15 +9,23 @@ it "returns the index associated with the passed value" do ENV["foo"] = "bar" - ENV.send(@method, "bar").should == "foo" + suppress_warning { + ENV.send(@method, "bar").should == "foo" + } end it "returns nil if the passed value is not found" do ENV.delete("foo") - ENV.send(@method, "foo").should be_nil + suppress_warning { + ENV.send(@method, "foo").should be_nil + } end it "raises TypeError if the argument is not a String and does not respond to #to_str" do - -> { ENV.send(@method, Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String") + -> { + suppress_warning { + ENV.send(@method, Object.new) + } + }.should raise_error(TypeError, "no implicit conversion of Object into String") end end diff --git a/ruby/spec/ruby/core/env/shift_spec.rb b/ruby/spec/ruby/core/env/shift_spec.rb index c03b5d50c..1b92e5d1e 100644 --- a/ruby/spec/ruby/core/env/shift_spec.rb +++ b/ruby/spec/ruby/core/env/shift_spec.rb @@ -1,28 +1,5 @@ require_relative '../../spec_helper' - -describe "ENV.shift" do - it "returns a pair and deletes it" do - ENV.empty?.should == false - orig = ENV.to_hash - begin - pair = ENV.shift - ENV.has_key?(pair.first).should == false - ensure - ENV.replace orig - end - ENV.has_key?(pair.first).should == true - end - - it "returns nil if ENV.empty?" do - orig = ENV.to_hash - begin - ENV.clear - ENV.shift.should == nil - ensure - ENV.replace orig - end - end -end +require_relative 'fixtures/common' describe "ENV.shift" do before :each do @@ -31,6 +8,7 @@ @internal = Encoding.default_internal Encoding.default_external = Encoding::BINARY + ENV.replace({"FOO"=>"BAR"}) end after :each do @@ -39,12 +17,24 @@ ENV.replace @orig end + it "returns a pair and deletes it" do + ENV.should.has_key?("FOO") + pair = ENV.shift + pair.should == ["FOO", "BAR"] + ENV.should_not.has_key?("FOO") + end + + it "returns nil if ENV.empty?" do + ENV.clear + ENV.shift.should == nil + end + it "uses the locale encoding if Encoding.default_internal is nil" do Encoding.default_internal = nil pair = ENV.shift - pair.first.encoding.should equal(Encoding.find("locale")) - pair.last.encoding.should equal(Encoding.find("locale")) + pair.first.encoding.should equal(ENVSpecs.encoding) + pair.last.encoding.should equal(ENVSpecs.encoding) end it "transcodes from the locale encoding to Encoding.default_internal if set" do diff --git a/ruby/spec/ruby/core/env/slice_spec.rb b/ruby/spec/ruby/core/env/slice_spec.rb index 1ac8a303f..e3b602039 100644 --- a/ruby/spec/ruby/core/env/slice_spec.rb +++ b/ruby/spec/ruby/core/env/slice_spec.rb @@ -1,29 +1,27 @@ require_relative '../../spec_helper' -ruby_version_is "2.6" do - describe "ENV.slice" do - before :each do - @saved_foo = ENV["foo"] - @saved_bar = ENV["bar"] - ENV["foo"] = "0" - ENV["bar"] = "1" - end +describe "ENV.slice" do + before :each do + @saved_foo = ENV["foo"] + @saved_bar = ENV["bar"] + ENV["foo"] = "0" + ENV["bar"] = "1" + end - after :each do - ENV["foo"] = @saved_foo - ENV["bar"] = @saved_bar - end + after :each do + ENV["foo"] = @saved_foo + ENV["bar"] = @saved_bar + end - it "returns a hash of the given environment variable names and their values" do - ENV.slice("foo", "bar").should == {"foo" => "0", "bar" => "1"} - end + it "returns a hash of the given environment variable names and their values" do + ENV.slice("foo", "bar").should == {"foo" => "0", "bar" => "1"} + end - it "ignores each String that is not an environment variable name" do - ENV.slice("foo", "boo", "bar").should == {"foo" => "0", "bar" => "1"} - end + it "ignores each String that is not an environment variable name" do + ENV.slice("foo", "boo", "bar").should == {"foo" => "0", "bar" => "1"} + end - it "raises TypeError if any argument is not a String and does not respond to #to_str" do - -> { ENV.slice(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String") - end + it "raises TypeError if any argument is not a String and does not respond to #to_str" do + -> { ENV.slice(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String") end end diff --git a/ruby/spec/ruby/core/env/to_h_spec.rb b/ruby/spec/ruby/core/env/to_h_spec.rb index 65cdb5995..3c4a92aa5 100644 --- a/ruby/spec/ruby/core/env/to_h_spec.rb +++ b/ruby/spec/ruby/core/env/to_h_spec.rb @@ -4,57 +4,55 @@ describe "ENV.to_h" do it_behaves_like :env_to_hash, :to_h - ruby_version_is "2.6" do - context "with block" do - before do - @orig_hash = ENV.to_hash - end - - after do - ENV.replace @orig_hash - end - - it "converts [key, value] pairs returned by the block to a hash" do - ENV.replace("a" => "b", "c" => "d") - ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" } - end - - it "does not require the array elements to be strings" do - ENV.replace("a" => "b", "c" => "d") - ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d } - end - - it "raises ArgumentError if block returns longer or shorter array" do - -> do - ENV.to_h { |k, v| [k, v.upcase, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) - - -> do - ENV.to_h { |k, v| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end - - it "raises TypeError if block returns something other than Array" do - -> do - ENV.to_h { |k, v| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end - - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) - - ENV.to_h { |k| x }.should == { :b => 'b' } - end - - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) - - -> do - ENV.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end + context "with block" do + before do + @orig_hash = ENV.to_hash + end + + after do + ENV.replace @orig_hash + end + + it "converts [key, value] pairs returned by the block to a hash" do + ENV.replace("a" => "b", "c" => "d") + ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" } + end + + it "does not require the array elements to be strings" do + ENV.replace("a" => "b", "c" => "d") + ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d } + end + + it "raises ArgumentError if block returns longer or shorter array" do + -> do + ENV.to_h { |k, v| [k, v.upcase, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) + + -> do + ENV.to_h { |k, v| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end + + it "raises TypeError if block returns something other than Array" do + -> do + ENV.to_h { |k, v| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end + + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) + + ENV.to_h { |k| x }.should == { :b => 'b' } + end + + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) + + -> do + ENV.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) end end end diff --git a/ruby/spec/ruby/core/env/values_at_spec.rb b/ruby/spec/ruby/core/env/values_at_spec.rb index ee970e5f6..338680e82 100644 --- a/ruby/spec/ruby/core/env/values_at_spec.rb +++ b/ruby/spec/ruby/core/env/values_at_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/common' describe "ENV.values_at" do before :each do @@ -28,7 +29,7 @@ end it "uses the locale encoding" do - ENV.values_at(ENV.keys.first).first.encoding.should == Encoding.find('locale') + ENV.values_at(ENV.keys.first).first.encoding.should == ENVSpecs.encoding end it "raises TypeError when a key is not coercible to String" do diff --git a/ruby/spec/ruby/core/exception/backtrace_spec.rb b/ruby/spec/ruby/core/exception/backtrace_spec.rb index 2d6825180..3f74c4cef 100644 --- a/ruby/spec/ruby/core/exception/backtrace_spec.rb +++ b/ruby/spec/ruby/core/exception/backtrace_spec.rb @@ -43,7 +43,7 @@ # This regexp is deliberately imprecise to account for the need to abstract out # the paths of the included mspec files and the desire to avoid specifying in any # detail what the in `...' portion looks like. - line.should =~ /^[^ ]+\:\d+(:in `[^`]+')?$/ + line.should =~ /^.+:\d+:in `[^`]+'$/ end end diff --git a/ruby/spec/ruby/core/exception/destination_encoding_name_spec.rb b/ruby/spec/ruby/core/exception/destination_encoding_name_spec.rb deleted file mode 100644 index a9e647497..000000000 --- a/ruby/spec/ruby/core/exception/destination_encoding_name_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::UndefinedConversionError#destination_encoding_name" do - it "returns the destination encoding name" do - ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") - begin - ec.convert("\xa0") - rescue Encoding::UndefinedConversionError => e - e.destination_encoding_name.should == "EUC-JP" - end - end -end - -describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do - it "returns the destination encoding name" do - ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") - begin - ec.convert("\xa0") - rescue Encoding::InvalidByteSequenceError => e - e.destination_encoding_name.should == "UTF-8" - end - end -end diff --git a/ruby/spec/ruby/core/exception/destination_encoding_spec.rb b/ruby/spec/ruby/core/exception/destination_encoding_spec.rb deleted file mode 100644 index 5709c31e5..000000000 --- a/ruby/spec/ruby/core/exception/destination_encoding_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::UndefinedConversionError#destination_encoding" do - it "returns the destination encoding" do - ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") - begin - ec.convert("\xa0") - rescue Encoding::UndefinedConversionError => e - e.destination_encoding.should == Encoding::EUC_JP - end - end -end - -describe "Encoding::InvalidByteSequenceError#destination_encoding" do - it "returns the destination encoding" do - ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") - begin - ec.convert("\xa0") - rescue Encoding::InvalidByteSequenceError => e - e.destination_encoding.should == Encoding::UTF_8 - end - end -end diff --git a/ruby/spec/ruby/core/exception/errno_spec.rb b/ruby/spec/ruby/core/exception/errno_spec.rb index 9e0bf0086..a063e522e 100644 --- a/ruby/spec/ruby/core/exception/errno_spec.rb +++ b/ruby/spec/ruby/core/exception/errno_spec.rb @@ -1,10 +1,6 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -describe "SystemCallError#errno" do - it "needs to be reviewed for spec completeness" -end - describe "Errno::EINVAL.new" do it "can be called with no arguments" do exc = Errno::EINVAL.new @@ -46,3 +42,26 @@ end end end + +describe "Errno::ENOTSUP" do + it "is defined" do + Errno.should have_constant(:ENOTSUP) + end + + it "is the same class as Errno::EOPNOTSUPP if they represent the same errno value" do + if Errno::ENOTSUP::Errno == Errno::EOPNOTSUPP::Errno + Errno::ENOTSUP.should == Errno::EOPNOTSUPP + else + Errno::ENOTSUP.should_not == Errno::EOPNOTSUPP + end + end +end + +describe "Errno::ENOENT" do + it "lets subclasses inherit the default error message" do + c = Class.new(Errno::ENOENT) + raise c, "custom message" + rescue => e + e.message.should == "No such file or directory - custom message" + end +end diff --git a/ruby/spec/ruby/core/exception/error_bytes_spec.rb b/ruby/spec/ruby/core/exception/error_bytes_spec.rb deleted file mode 100644 index 66dd4b62c..000000000 --- a/ruby/spec/ruby/core/exception/error_bytes_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::InvalidByteSequenceError#error_bytes" do - it "returns the error bytes" do - ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") - begin - ec.convert("\xa0") - rescue Encoding::InvalidByteSequenceError => e - e.error_bytes.should == "\xA0".force_encoding("ASCII-8BIT") - end - end -end diff --git a/ruby/spec/ruby/core/exception/error_char_spec.rb b/ruby/spec/ruby/core/exception/error_char_spec.rb deleted file mode 100644 index f95ae2a6c..000000000 --- a/ruby/spec/ruby/core/exception/error_char_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::UndefinedConversionError#error_char" do - it "returns the error char" do - ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") - begin - ec.convert("\xa0") - rescue Encoding::UndefinedConversionError => e - e.error_char.should == "\u00A0" - end - end -end diff --git a/ruby/spec/ruby/core/exception/exit_value_spec.rb b/ruby/spec/ruby/core/exception/exit_value_spec.rb index 43de56af8..99987dd1b 100644 --- a/ruby/spec/ruby/core/exception/exit_value_spec.rb +++ b/ruby/spec/ruby/core/exception/exit_value_spec.rb @@ -1,5 +1,13 @@ require_relative '../../spec_helper' describe "LocalJumpError#exit_value" do - it "needs to be reviewed for spec completeness" + def get_me_a_return + Proc.new { return 42 } + end + + it "returns the value given to return" do + -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e| + e.exit_value.should == 42 + } + end end diff --git a/ruby/spec/ruby/core/exception/frozen_error_spec.rb b/ruby/spec/ruby/core/exception/frozen_error_spec.rb index 1b5ea7114..f27b33295 100644 --- a/ruby/spec/ruby/core/exception/frozen_error_spec.rb +++ b/ruby/spec/ruby/core/exception/frozen_error_spec.rb @@ -1,13 +1,5 @@ require_relative '../../spec_helper' -describe "FrozenError" do - ruby_version_is "2.5" do - it "is a subclass of RuntimeError" do - RuntimeError.should be_ancestor_of(FrozenError) - end - end -end - describe "FrozenError.new" do ruby_version_is "2.7" do it "should take optional receiver argument" do diff --git a/ruby/spec/ruby/core/exception/full_message_spec.rb b/ruby/spec/ruby/core/exception/full_message_spec.rb index 3df2d47f6..4cece9ebf 100644 --- a/ruby/spec/ruby/core/exception/full_message_spec.rb +++ b/ruby/spec/ruby/core/exception/full_message_spec.rb @@ -1,94 +1,88 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "Exception#full_message" do - it "returns formatted string of exception using the same format that is used to print an uncaught exceptions to stderr" do - e = RuntimeError.new("Some runtime error") - e.set_backtrace(["a.rb:1", "b.rb:2"]) +describe "Exception#full_message" do + it "returns formatted string of exception using the same format that is used to print an uncaught exceptions to stderr" do + e = RuntimeError.new("Some runtime error") + e.set_backtrace(["a.rb:1", "b.rb:2"]) - full_message = e.full_message - full_message.should include "RuntimeError" - full_message.should include "Some runtime error" - full_message.should include "a.rb:1" - full_message.should include "b.rb:2" - end + full_message = e.full_message + full_message.should include "RuntimeError" + full_message.should include "Some runtime error" + full_message.should include "a.rb:1" + full_message.should include "b.rb:2" + end - ruby_version_is "2.5.1" do - it "supports :highlight option and adds escape sequences to highlight some strings" do - e = RuntimeError.new("Some runtime error") + it "supports :highlight option and adds escape sequences to highlight some strings" do + e = RuntimeError.new("Some runtime error") - full_message = e.full_message(highlight: true, order: :bottom) - full_message.should include "\e[1mTraceback\e[m (most recent call last)" - full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)" + full_message = e.full_message(highlight: true, order: :bottom) + full_message.should include "\e[1mTraceback\e[m (most recent call last)" + full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)" - full_message = e.full_message(highlight: false, order: :bottom) - full_message.should include "Traceback (most recent call last)" - full_message.should include "Some runtime error (RuntimeError)" - end + full_message = e.full_message(highlight: false, order: :bottom) + full_message.should include "Traceback (most recent call last)" + full_message.should include "Some runtime error (RuntimeError)" + end - it "supports :order option and places the error message and the backtrace at the top or the bottom" do - e = RuntimeError.new("Some runtime error") - e.set_backtrace(["a.rb:1", "b.rb:2"]) + it "supports :order option and places the error message and the backtrace at the top or the bottom" do + e = RuntimeError.new("Some runtime error") + e.set_backtrace(["a.rb:1", "b.rb:2"]) - e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m - e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m - end + e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m + e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m + end - it "shows the caller if the exception has no backtrace" do - e = RuntimeError.new("Some runtime error") - e.backtrace.should == nil - full_message = e.full_message(highlight: false, order: :top) - full_message.should include("#{__FILE__}:#{__LINE__-1}:in `") - full_message.should include("': Some runtime error (RuntimeError)\n") - end + it "shows the caller if the exception has no backtrace" do + e = RuntimeError.new("Some runtime error") + e.backtrace.should == nil + full_message = e.full_message(highlight: false, order: :top) + full_message.should include("#{__FILE__}:#{__LINE__-1}:in `") + full_message.should include("': Some runtime error (RuntimeError)\n") + end - it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do - begin - line = __LINE__; raise "first line\nsecond line" - rescue => e - full_message = e.full_message(highlight: false, order: :top).lines - full_message[0].should include("#{__FILE__}:#{line}:in `") - full_message[0].should include(": first line (RuntimeError)\n") - full_message[1].should == "second line\n" - end - end + it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do + begin + line = __LINE__; raise "first line\nsecond line" + rescue => e + full_message = e.full_message(highlight: false, order: :top).lines + full_message[0].should include("#{__FILE__}:#{line}:in `") + full_message[0].should include(": first line (RuntimeError)\n") + full_message[1].should == "second line\n" end + end - ruby_version_is "2.6" do - it "contains cause of exception" do - begin - begin - raise 'the cause' - rescue - raise 'main exception' - end - rescue => e - exception = e - end - - exception.full_message.should include "main exception" - exception.full_message.should include "the cause" + it "contains cause of exception" do + begin + begin + raise 'the cause' + rescue + raise 'main exception' end + rescue => e + exception = e + end + + exception.full_message.should include "main exception" + exception.full_message.should include "the cause" + end - it 'contains all the chain of exceptions' do + it 'contains all the chain of exceptions' do + begin + begin begin - begin - begin - raise 'origin exception' - rescue - raise 'intermediate exception' - end - rescue - raise 'last exception' - end - rescue => e - exception = e + raise 'origin exception' + rescue + raise 'intermediate exception' end - - exception.full_message.should include "last exception" - exception.full_message.should include "intermediate exception" - exception.full_message.should include "origin exception" + rescue + raise 'last exception' end + rescue => e + exception = e end + + exception.full_message.should include "last exception" + exception.full_message.should include "intermediate exception" + exception.full_message.should include "origin exception" end end diff --git a/ruby/spec/ruby/core/exception/hierarchy_spec.rb b/ruby/spec/ruby/core/exception/hierarchy_spec.rb index e52811c76..6514eb199 100644 --- a/ruby/spec/ruby/core/exception/hierarchy_spec.rb +++ b/ruby/spec/ruby/core/exception/hierarchy_spec.rb @@ -37,7 +37,9 @@ FloatDomainError => nil, }, RegexpError => nil, - RuntimeError => nil, + RuntimeError => { + FrozenError => nil, + }, SystemCallError => nil, ThreadError => nil, TypeError => nil, @@ -47,9 +49,7 @@ SystemStackError => nil, }, } - ruby_version_is "2.5" do - hierarchy[Exception][StandardError][RuntimeError] = {FrozenError => nil} - end + traverse = -> parent_class, parent_subclass_hash { parent_subclass_hash.each do |child_class, child_subclass_hash| child_class.class.should == Class diff --git a/ruby/spec/ruby/core/exception/incomplete_input_spec.rb b/ruby/spec/ruby/core/exception/incomplete_input_spec.rb deleted file mode 100644 index b033b33f5..000000000 --- a/ruby/spec/ruby/core/exception/incomplete_input_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::InvalidByteSequenceError#incomplete_input?" do - it "needs to be reviewed for spec completeness" -end diff --git a/ruby/spec/ruby/core/exception/initialize_spec.rb b/ruby/spec/ruby/core/exception/initialize_spec.rb deleted file mode 100644 index e724feaa3..000000000 --- a/ruby/spec/ruby/core/exception/initialize_spec.rb +++ /dev/null @@ -1 +0,0 @@ -require_relative '../../spec_helper' diff --git a/ruby/spec/ruby/core/exception/interrupt_spec.rb b/ruby/spec/ruby/core/exception/interrupt_spec.rb index 14f294bec..a7501efad 100644 --- a/ruby/spec/ruby/core/exception/interrupt_spec.rb +++ b/ruby/spec/ruby/core/exception/interrupt_spec.rb @@ -29,7 +29,23 @@ sleep rescue Interrupt => e e.signo.should == Signal.list["INT"] - e.signm.should == "" + ["", "Interrupt"].should.include?(e.message) end end end + +describe "Interrupt" do + # This spec is basically the same as above, + # but it does not rely on Signal.trap(:INT, :SIG_DFL) which can be tricky + it "is raised on the main Thread by the default SIGINT handler" do + out = ruby_exe(<<-'RUBY', args: "2>&1") + begin + Process.kill :INT, Process.pid + sleep + rescue Interrupt => e + puts "Interrupt: #{e.signo}" + end + RUBY + out.should == "Interrupt: #{Signal.list["INT"]}\n" + end +end diff --git a/ruby/spec/ruby/core/exception/io_error_spec.rb b/ruby/spec/ruby/core/exception/io_error_spec.rb index 8dc10cc6c..ab8a72518 100644 --- a/ruby/spec/ruby/core/exception/io_error_spec.rb +++ b/ruby/spec/ruby/core/exception/io_error_spec.rb @@ -1,11 +1,5 @@ require_relative '../../spec_helper' -describe "IOError" do - it "is a superclass of EOFError" do - IOError.should be_ancestor_of(EOFError) - end -end - describe "IO::EAGAINWaitReadable" do it "combines Errno::EAGAIN and IO::WaitReadable" do IO::EAGAINWaitReadable.superclass.should == Errno::EAGAIN diff --git a/ruby/spec/ruby/core/exception/key_error_spec.rb b/ruby/spec/ruby/core/exception/key_error_spec.rb index ad280279d..c5e2b1efb 100644 --- a/ruby/spec/ruby/core/exception/key_error_spec.rb +++ b/ruby/spec/ruby/core/exception/key_error_spec.rb @@ -1,15 +1,19 @@ require_relative '../../spec_helper' describe "KeyError" do - ruby_version_is "2.6" do - it "accepts :receiver and :key options" do - receiver = mock("receiver") - key = mock("key") + it "accepts :receiver and :key options" do + receiver = mock("receiver") + key = mock("key") - error = KeyError.new(receiver: receiver, key: key) + error = KeyError.new(receiver: receiver, key: key) - error.receiver.should == receiver - error.key.should == key - end + error.receiver.should == receiver + error.key.should == key + + error = KeyError.new("message", receiver: receiver, key: key) + + error.message.should == "message" + error.receiver.should == receiver + error.key.should == key end end diff --git a/ruby/spec/ruby/core/exception/name_error_spec.rb b/ruby/spec/ruby/core/exception/name_error_spec.rb index d0a810029..ddd51a92e 100644 --- a/ruby/spec/ruby/core/exception/name_error_spec.rb +++ b/ruby/spec/ruby/core/exception/name_error_spec.rb @@ -1,24 +1,28 @@ require_relative '../../spec_helper' -describe "NameError" do - it "is a superclass of NoMethodError" do - NameError.should be_ancestor_of(NoMethodError) - end -end - describe "NameError.new" do it "should take optional name argument" do NameError.new("msg","name").name.should == "name" end - ruby_version_is "2.6" do - it "accepts a :receiver keyword argument" do - receiver = mock("receiver") + it "accepts a :receiver keyword argument" do + receiver = mock("receiver") - error = NameError.new("msg", :name, receiver: receiver) + error = NameError.new("msg", :name, receiver: receiver) + + error.receiver.should == receiver + error.name.should == :name + end +end - error.receiver.should == receiver - error.name.should == :name +describe "NameError#dup" do + it "copies the name and receiver" do + begin + foo + rescue NameError => ne + name_error_dup = ne.dup + name_error_dup.name.should == :foo + name_error_dup.receiver.should == self end end end diff --git a/ruby/spec/ruby/core/exception/name_spec.rb b/ruby/spec/ruby/core/exception/name_spec.rb index d1def51f2..c8a49b40e 100644 --- a/ruby/spec/ruby/core/exception/name_spec.rb +++ b/ruby/spec/ruby/core/exception/name_spec.rb @@ -21,9 +21,7 @@ it "returns a class variable name as a symbol" do -> { - -> { - @@doesnt_exist - }.should complain(/class variable access from toplevel/) + eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__) }.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist } end diff --git a/ruby/spec/ruby/core/exception/no_method_error_spec.rb b/ruby/spec/ruby/core/exception/no_method_error_spec.rb index 28c354956..8428ba038 100644 --- a/ruby/spec/ruby/core/exception/no_method_error_spec.rb +++ b/ruby/spec/ruby/core/exception/no_method_error_spec.rb @@ -10,15 +10,13 @@ NoMethodError.new("msg").message.should == "msg" end - ruby_version_is "2.6" do - it "accepts a :receiver keyword argument" do - receiver = mock("receiver") + it "accepts a :receiver keyword argument" do + receiver = mock("receiver") - error = NoMethodError.new("msg", :name, receiver: receiver) + error = NoMethodError.new("msg", :name, receiver: receiver) - error.receiver.should == receiver - error.name.should == :name - end + error.receiver.should == receiver + error.name.should == :name end end @@ -64,7 +62,7 @@ NoMethodErrorSpecs::NoMethodErrorC.new.a_private_method rescue Exception => e e.should be_kind_of(NoMethodError) - e.message.match(/private method/).should_not == nil + e.message.lines[0].should =~ /private method `a_private_method' called for #/ end end @@ -103,4 +101,36 @@ def inspect message.should include test_class.inspect end end + + ruby_version_is "3.0" do + it "uses #name to display the receiver if it is a class or a module" do + klass = Class.new { def self.name; "MyClass"; end } + begin + klass.foo + rescue NoMethodError => error + error.message.lines.first.chomp.should == "undefined method `foo' for MyClass:Class" + end + + mod = Module.new { def self.name; "MyModule"; end } + begin + mod.foo + rescue NoMethodError => error + error.message.lines.first.chomp.should == "undefined method `foo' for MyModule:Module" + end + end + end +end + +describe "NoMethodError#dup" do + it "copies the name, arguments and receiver" do + begin + receiver = Object.new + receiver.foo(:one, :two) + rescue NoMethodError => nme + no_method_error_dup = nme.dup + no_method_error_dup.name.should == :foo + no_method_error_dup.receiver.should == receiver + no_method_error_dup.args.should == [:one, :two] + end + end end diff --git a/ruby/spec/ruby/core/exception/range_error_spec.rb b/ruby/spec/ruby/core/exception/range_error_spec.rb deleted file mode 100644 index 7cfbd0f1e..000000000 --- a/ruby/spec/ruby/core/exception/range_error_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../spec_helper' - -describe "RangeError" do - it "is a superclass of FloatDomainError" do - RangeError.should be_ancestor_of(FloatDomainError) - end -end diff --git a/ruby/spec/ruby/core/exception/readagain_bytes_spec.rb b/ruby/spec/ruby/core/exception/readagain_bytes_spec.rb deleted file mode 100644 index 0f1e24f1c..000000000 --- a/ruby/spec/ruby/core/exception/readagain_bytes_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::InvalidByteSequenceError#readagain_bytes" do - it "returns the next byte" do - begin - "abc\xa4def".encode("ISO-8859-1", "EUC-JP") - rescue Encoding::InvalidByteSequenceError => e - e.error_bytes.should == "\xA4".force_encoding("ASCII-8BIT") - e.readagain_bytes.should == 'd' - end - end -end diff --git a/ruby/spec/ruby/core/exception/reason_spec.rb b/ruby/spec/ruby/core/exception/reason_spec.rb index 6f18aaae1..210bbc972 100644 --- a/ruby/spec/ruby/core/exception/reason_spec.rb +++ b/ruby/spec/ruby/core/exception/reason_spec.rb @@ -1,5 +1,13 @@ require_relative '../../spec_helper' describe "LocalJumpError#reason" do - it "needs to be reviewed for spec completeness" + def get_me_a_return + Proc.new { return 42 } + end + + it "returns 'return' for a return" do + -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e| + e.reason.should == :return + } + end end diff --git a/ruby/spec/ruby/core/exception/receiver_spec.rb b/ruby/spec/ruby/core/exception/receiver_spec.rb index 7c57d63c3..d1c23b67b 100644 --- a/ruby/spec/ruby/core/exception/receiver_spec.rb +++ b/ruby/spec/ruby/core/exception/receiver_spec.rb @@ -28,10 +28,8 @@ def call_undefined_class_variable; @@doesnt_exist end it "returns the Object class when an undefined class variable is called" do -> { - -> { - @@doesnt_exist - }.should complain(/class variable access from toplevel/) - }.should raise_error(NameError) {|e| e.receiver.should equal(Object) } + eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__) + }.should raise_error(NameError) {|e| e.receiver.should equal(singleton_class::A) } end it "returns a class when an undefined class variable is called in a subclass' namespace" do diff --git a/ruby/spec/ruby/core/exception/result_spec.rb b/ruby/spec/ruby/core/exception/result_spec.rb index 5ba26ebab..d42fcdffc 100644 --- a/ruby/spec/ruby/core/exception/result_spec.rb +++ b/ruby/spec/ruby/core/exception/result_spec.rb @@ -1,11 +1,5 @@ require_relative '../../spec_helper' -describe "StopIteration" do - it "is a subclass of IndexError" do - StopIteration.superclass.should equal(IndexError) - end -end - describe "StopIteration#result" do before :each do obj = Object.new @@ -20,10 +14,8 @@ def obj.each it "returns the method-returned-object from an Enumerator" do @enum.next @enum.next - -> { @enum.next }.should( - raise_error(StopIteration) do |error| - error.result.should equal(:method_returned) - end - ) + -> { @enum.next }.should raise_error(StopIteration) { |error| + error.result.should equal(:method_returned) + } end end diff --git a/ruby/spec/ruby/core/exception/signal_exception_spec.rb b/ruby/spec/ruby/core/exception/signal_exception_spec.rb index e494e18cd..566bcb467 100644 --- a/ruby/spec/ruby/core/exception/signal_exception_spec.rb +++ b/ruby/spec/ruby/core/exception/signal_exception_spec.rb @@ -30,10 +30,8 @@ -> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError) end - ruby_version_is "2.6" do - it "raises an exception with an invalid first argument type" do - -> { SignalException.new(Object.new) }.should raise_error(ArgumentError) - end + it "raises an exception with an invalid first argument type" do + -> { SignalException.new(Object.new) }.should raise_error(ArgumentError) end it "takes a signal symbol without SIG prefix as the first argument" do @@ -95,7 +93,7 @@ platform_is_not :windows do it "runs after at_exit" do - output = ruby_exe(<<-RUBY) + output = ruby_exe(<<-RUBY, exit_status: nil) at_exit do puts "hello" $stdout.flush @@ -109,7 +107,7 @@ end it "cannot be trapped with Signal.trap" do - ruby_exe(<<-RUBY) + ruby_exe(<<-RUBY, exit_status: nil) Signal.trap("PROF") {} raise(SignalException, "PROF") RUBY @@ -118,7 +116,7 @@ end it "self-signals for USR1" do - ruby_exe("raise(SignalException, 'USR1')") + ruby_exe("raise(SignalException, 'USR1')", exit_status: nil) $?.termsig.should == Signal.list.fetch('USR1') end end diff --git a/ruby/spec/ruby/core/exception/signm_spec.rb b/ruby/spec/ruby/core/exception/signm_spec.rb index 8e3adcdda..4adff3b5e 100644 --- a/ruby/spec/ruby/core/exception/signm_spec.rb +++ b/ruby/spec/ruby/core/exception/signm_spec.rb @@ -1,5 +1,9 @@ require_relative '../../spec_helper' describe "SignalException#signm" do - it "needs to be reviewed for spec completeness" + it "returns the signal name" do + -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e| + e.signm.should == 'SIGTERM' + } + end end diff --git a/ruby/spec/ruby/core/exception/signo_spec.rb b/ruby/spec/ruby/core/exception/signo_spec.rb index 2d04cd780..62fc32151 100644 --- a/ruby/spec/ruby/core/exception/signo_spec.rb +++ b/ruby/spec/ruby/core/exception/signo_spec.rb @@ -1,5 +1,9 @@ require_relative '../../spec_helper' describe "SignalException#signo" do - it "needs to be reviewed for spec completeness" + it "returns the signal number" do + -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e| + e.signo.should == Signal.list['TERM'] + } + end end diff --git a/ruby/spec/ruby/core/exception/source_encoding_name_spec.rb b/ruby/spec/ruby/core/exception/source_encoding_name_spec.rb deleted file mode 100644 index 6f5dbd01a..000000000 --- a/ruby/spec/ruby/core/exception/source_encoding_name_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::UndefinedConversionError#source_encoding_name" do - it "returns the source encoding name" do - ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") - begin - ec.convert("\xa0") - rescue Encoding::UndefinedConversionError => e - e.source_encoding_name.should == "UTF-8" - end - end -end - -describe "Encoding::InvalidByteSequenceError#source_encoding_name" do - it "returns the source encoding name" do - ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") - begin - ec.convert("\xa0") - rescue Encoding::InvalidByteSequenceError => e - e.source_encoding_name.should == "EUC-JP" - end - end -end diff --git a/ruby/spec/ruby/core/exception/source_encoding_spec.rb b/ruby/spec/ruby/core/exception/source_encoding_spec.rb deleted file mode 100644 index fac38e75f..000000000 --- a/ruby/spec/ruby/core/exception/source_encoding_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_relative '../../spec_helper' - -describe "Encoding::UndefinedConversionError#source_encoding" do - it "returns the source encoding" do - ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") - begin - ec.convert("\xa0") - rescue Encoding::UndefinedConversionError => e - e.source_encoding.should == Encoding::UTF_8 - end - end -end - -describe "Encoding::InvalidByteSequenceError#source_encoding" do - it "returns the source encoding" do - ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") - begin - ec.convert("\xa0") - rescue Encoding::InvalidByteSequenceError => e - e.source_encoding.should == Encoding::EUC_JP - end - end -end diff --git a/ruby/spec/ruby/core/exception/status_spec.rb b/ruby/spec/ruby/core/exception/status_spec.rb index 1609bff3a..8ace00fe1 100644 --- a/ruby/spec/ruby/core/exception/status_spec.rb +++ b/ruby/spec/ruby/core/exception/status_spec.rb @@ -1,5 +1,9 @@ require_relative '../../spec_helper' describe "SystemExit#status" do - it "needs to be reviewed for spec completeness" + it "returns the exit status" do + -> { exit 42 }.should raise_error(SystemExit) { |e| + e.status.should == 42 + } + end end diff --git a/ruby/spec/ruby/core/exception/success_spec.rb b/ruby/spec/ruby/core/exception/success_spec.rb index 82e3df92c..6f2174334 100644 --- a/ruby/spec/ruby/core/exception/success_spec.rb +++ b/ruby/spec/ruby/core/exception/success_spec.rb @@ -1,5 +1,15 @@ require_relative '../../spec_helper' describe "SystemExit#success?" do - it "needs to be reviewed for spec completeness" + it "returns true if the process exited successfully" do + -> { exit 0 }.should raise_error(SystemExit) { |e| + e.should.success? + } + end + + it "returns false if the process exited unsuccessfully" do + -> { exit(-1) }.should raise_error(SystemExit) { |e| + e.should_not.success? + } + end end diff --git a/ruby/spec/ruby/core/exception/system_call_error_spec.rb b/ruby/spec/ruby/core/exception/system_call_error_spec.rb index c510ae440..73167bc28 100644 --- a/ruby/spec/ruby/core/exception/system_call_error_spec.rb +++ b/ruby/spec/ruby/core/exception/system_call_error_spec.rb @@ -31,7 +31,7 @@ def initialize -> { SystemCallError.new }.should raise_error(ArgumentError) end - it "accepts single Fixnum argument as errno" do + it "accepts single Integer argument as errno" do SystemCallError.new(-2**24).errno.should == -2**24 SystemCallError.new(-1).errno.should == -1 SystemCallError.new(0).errno.should == 0 @@ -128,3 +128,16 @@ def initialize SystemCallError.new("XXX").message.should =~ /XXX/ end end + +describe "SystemCallError#dup" do + it "copies the errno" do + dup_sce = SystemCallError.new("message", 42).dup + dup_sce.errno.should == 42 + end +end + +describe "SystemCallError#backtrace" do + it "is nil if not raised" do + SystemCallError.new("message", 42).backtrace.should == nil + end +end diff --git a/ruby/spec/ruby/core/exception/system_exit_spec.rb b/ruby/spec/ruby/core/exception/system_exit_spec.rb new file mode 100644 index 000000000..eef9faf27 --- /dev/null +++ b/ruby/spec/ruby/core/exception/system_exit_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' + +describe "SystemExit" do + it "sets the exit status and exits silently when raised" do + code = 'raise SystemExit.new(7)' + result = ruby_exe(code, args: "2>&1", exit_status: 7) + result.should == "" + $?.exitstatus.should == 7 + end + + it "sets the exit status and exits silently when raised when subclassed" do + code = 'class CustomExit < SystemExit; end; raise CustomExit.new(8)' + result = ruby_exe(code, args: "2>&1", exit_status: 8) + result.should == "" + $?.exitstatus.should == 8 + end +end diff --git a/ruby/spec/ruby/core/exception/system_stack_error_spec.rb b/ruby/spec/ruby/core/exception/system_stack_error_spec.rb deleted file mode 100644 index 0343d2da5..000000000 --- a/ruby/spec/ruby/core/exception/system_stack_error_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../spec_helper' - -describe "SystemStackError" do - it "is a subclass of Exception" do - SystemStackError.superclass.should == Exception - end -end diff --git a/ruby/spec/ruby/core/exception/top_level_spec.rb b/ruby/spec/ruby/core/exception/top_level_spec.rb new file mode 100644 index 000000000..b47648425 --- /dev/null +++ b/ruby/spec/ruby/core/exception/top_level_spec.rb @@ -0,0 +1,45 @@ +require_relative '../../spec_helper' + +describe "An Exception reaching the top level" do + it "is printed on STDERR" do + ruby_exe('raise "foo"', args: "2>&1", exit_status: 1).should.include?("in `
      ': foo (RuntimeError)") + end + + it "the Exception#cause is printed to STDERR with backtraces" do + code = <<-RUBY + def raise_cause + raise "the cause" + end + def raise_wrapped + raise "wrapped" + end + begin + raise_cause + rescue + raise_wrapped + end + RUBY + lines = ruby_exe(code, args: "2>&1", exit_status: 1).lines + lines.reject! { |l| l.include?('rescue in') } + lines.map! { |l| l.chomp[/:(in.+)/, 1] } + lines.should == ["in `raise_wrapped': wrapped (RuntimeError)", + "in `
      '", + "in `raise_cause': the cause (RuntimeError)", + "in `
      '"] + end + + describe "with a custom backtrace" do + it "is printed on STDERR" do + code = <<-RUBY + raise RuntimeError, "foo", [ + "/dir/foo.rb:10:in `raising'", + "/dir/bar.rb:20:in `caller'", + ] + RUBY + ruby_exe(code, args: "2>&1", exit_status: 1).should == <<-EOS +/dir/foo.rb:10:in `raising': foo (RuntimeError) +\tfrom /dir/bar.rb:20:in `caller' + EOS + end + end +end diff --git a/ruby/spec/ruby/core/exception/uncaught_throw_error_spec.rb b/ruby/spec/ruby/core/exception/uncaught_throw_error_spec.rb index 57f391d75..9267df667 100644 --- a/ruby/spec/ruby/core/exception/uncaught_throw_error_spec.rb +++ b/ruby/spec/ruby/core/exception/uncaught_throw_error_spec.rb @@ -1,11 +1,5 @@ require_relative '../../spec_helper' -describe "UncaughtThrowError" do - it "is a subclass of ArgumentError" do - ArgumentError.should be_ancestor_of(UncaughtThrowError) - end -end - describe "UncaughtThrowError#tag" do it "returns the object thrown" do begin diff --git a/ruby/spec/ruby/core/false/to_s_spec.rb b/ruby/spec/ruby/core/false/to_s_spec.rb index c996d8700..4cae27889 100644 --- a/ruby/spec/ruby/core/false/to_s_spec.rb +++ b/ruby/spec/ruby/core/false/to_s_spec.rb @@ -7,7 +7,7 @@ ruby_version_is "2.7" do it "returns a frozen string" do - false.to_s.frozen?.should == true + false.to_s.should.frozen? end it "always returns the same string" do diff --git a/ruby/spec/ruby/core/fiber/blocking_spec.rb b/ruby/spec/ruby/core/fiber/blocking_spec.rb new file mode 100644 index 000000000..5ae5fbd57 --- /dev/null +++ b/ruby/spec/ruby/core/fiber/blocking_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../spec_helper' +require_relative 'shared/blocking' + +ruby_version_is "3.0" do + require "fiber" + + describe "Fiber.blocking?" do + it_behaves_like :non_blocking_fiber, -> { Fiber.blocking? } + + context "when fiber is blocking" do + context "root Fiber of the main thread" do + it "returns 1 for blocking: true" do + fiber = Fiber.new(blocking: true) { Fiber.blocking? } + blocking = fiber.resume + + blocking.should == 1 + end + end + + context "root Fiber of a new thread" do + it "returns 1 for blocking: true" do + thread = Thread.new do + fiber = Fiber.new(blocking: true) { Fiber.blocking? } + blocking = fiber.resume + + blocking.should == 1 + end + + thread.join + end + end + end + end + + describe "Fiber#blocking?" do + it_behaves_like :non_blocking_fiber, -> { Fiber.current.blocking? } + + context "when fiber is blocking" do + context "root Fiber of the main thread" do + it "returns true for blocking: true" do + fiber = Fiber.new(blocking: true) { Fiber.current.blocking? } + blocking = fiber.resume + + blocking.should == true + end + end + + context "root Fiber of a new thread" do + it "returns true for blocking: true" do + thread = Thread.new do + fiber = Fiber.new(blocking: true) { Fiber.current.blocking? } + blocking = fiber.resume + + blocking.should == true + end + + thread.join + end + end + end + end +end diff --git a/ruby/spec/ruby/core/fiber/fixtures/classes.rb b/ruby/spec/ruby/core/fiber/fixtures/classes.rb new file mode 100644 index 000000000..c00facd6e --- /dev/null +++ b/ruby/spec/ruby/core/fiber/fixtures/classes.rb @@ -0,0 +1,12 @@ +module FiberSpecs + + class NewFiberToRaise + def self.raise(*args) + fiber = Fiber.new { Fiber.yield } + fiber.resume + fiber.raise(*args) + end + end + + class CustomError < StandardError; end +end diff --git a/ruby/spec/ruby/core/fiber/raise_spec.rb b/ruby/spec/ruby/core/fiber/raise_spec.rb new file mode 100644 index 000000000..2a465c8bf --- /dev/null +++ b/ruby/spec/ruby/core/fiber/raise_spec.rb @@ -0,0 +1,121 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative '../../shared/kernel/raise' + +ruby_version_is "2.7" do + describe "Fiber#raise" do + it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise + end + + describe "Fiber#raise" do + it 'raises RuntimeError by default' do + -> { FiberSpecs::NewFiberToRaise.raise }.should raise_error(RuntimeError) + end + + it "raises FiberError if Fiber is not born" do + fiber = Fiber.new { true } + -> { fiber.raise }.should raise_error(FiberError, "cannot raise exception on unborn fiber") + end + + it "raises FiberError if Fiber is dead" do + fiber = Fiber.new { true } + fiber.resume + -> { fiber.raise }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/) + end + + it 'accepts error class' do + -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should raise_error(FiberSpecs::CustomError) + end + + it 'accepts error message' do + -> { FiberSpecs::NewFiberToRaise.raise "error message" }.should raise_error(RuntimeError, "error message") + end + + it 'does not accept array of backtrace information only' do + -> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should raise_error(TypeError) + end + + it 'does not accept integer' do + -> { FiberSpecs::NewFiberToRaise.raise 100 }.should raise_error(TypeError) + end + + it 'accepts error class with error message' do + -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error') + end + + it 'accepts error class with with error message and backtrace information' do + -> { + FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo'] + }.should raise_error(FiberSpecs::CustomError) { |e| + e.message.should == 'test error' + e.backtrace.should == ['foo', 'boo'] + } + end + + it 'does not accept only error message and backtrace information' do + -> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should raise_error(TypeError) + end + + it "raises a FiberError if invoked from a different Thread" do + fiber = Fiber.new { Fiber.yield } + fiber.resume + Thread.new do + -> { + fiber.raise + }.should raise_error(FiberError, "fiber called across threads") + end.join + end + + it "kills Fiber" do + fiber = Fiber.new { Fiber.yield :first; :second } + fiber.resume + -> { fiber.raise }.should raise_error + -> { fiber.resume }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/) + end + + it "returns to calling fiber after raise" do + fiber_one = Fiber.new do + Fiber.yield :yield_one + :unreachable + end + + fiber_two = Fiber.new do + results = [] + results << fiber_one.resume + begin + fiber_one.raise + rescue + results << :rescued + end + results + end + + fiber_two.resume.should == [:yield_one, :rescued] + end + end + +end + +ruby_version_is "2.7"..."3.0" do + describe "Fiber#raise" do + it "raises a FiberError if invoked on a transferring Fiber" do + require "fiber" + root = Fiber.current + fiber = Fiber.new { root.transfer } + fiber.transfer + -> { fiber.raise }.should raise_error(FiberError, "cannot resume transferred Fiber") + end + end +end + +ruby_version_is "3.0" do + describe "Fiber#raise" do + it "transfers and raises on a transferring fiber" do + require "fiber" + root = Fiber.current + fiber = Fiber.new { root.transfer } + fiber.transfer + -> { fiber.raise "msg" }.should raise_error(RuntimeError, "msg") + end + end +end diff --git a/ruby/spec/ruby/core/fiber/resume_spec.rb b/ruby/spec/ruby/core/fiber/resume_spec.rb index 97495c505..273bc866a 100644 --- a/ruby/spec/ruby/core/fiber/resume_spec.rb +++ b/ruby/spec/ruby/core/fiber/resume_spec.rb @@ -6,9 +6,40 @@ end describe "Fiber#resume" do - it "raises a FiberError if the Fiber tries to resume itself" do - fiber = Fiber.new { fiber.resume } - -> { fiber.resume }.should raise_error(FiberError, /double resume/) + it "runs until Fiber.yield" do + obj = mock('obj') + obj.should_not_receive(:do) + fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do } + fiber.resume + end + + it "resumes from the last call to Fiber.yield on subsequent invocations" do + fiber = Fiber.new { Fiber.yield :first; :second } + fiber.resume.should == :first + fiber.resume.should == :second + end + + it "sets the block parameters to its arguments on the first invocation" do + first = mock('first') + first.should_receive(:arg).with(:first).twice + + fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; } + fiber.resume :first + fiber.resume :second + end + + ruby_version_is '3.0' do + it "raises a FiberError if the Fiber tries to resume itself" do + fiber = Fiber.new { fiber.resume } + -> { fiber.resume }.should raise_error(FiberError, /current fiber/) + end + end + + ruby_version_is '' ... '3.0' do + it "raises a FiberError if the Fiber tries to resume itself" do + fiber = Fiber.new { fiber.resume } + -> { fiber.resume }.should raise_error(FiberError, /double resume/) + end end it "returns control to the calling Fiber if called from one" do diff --git a/ruby/spec/ruby/core/fiber/shared/blocking.rb b/ruby/spec/ruby/core/fiber/shared/blocking.rb new file mode 100644 index 000000000..21707e1ea --- /dev/null +++ b/ruby/spec/ruby/core/fiber/shared/blocking.rb @@ -0,0 +1,41 @@ +describe :non_blocking_fiber, shared: true do + context "root Fiber of the main thread" do + it "returns false" do + fiber = Fiber.new { @method.call } + blocking = fiber.resume + + blocking.should == false + end + + it "returns false for blocking: false" do + fiber = Fiber.new(blocking: false) { @method.call } + blocking = fiber.resume + + blocking.should == false + end + end + + context "root Fiber of a new thread" do + it "returns false" do + thread = Thread.new do + fiber = Fiber.new { @method.call } + blocking = fiber.resume + + blocking.should == false + end + + thread.join + end + + it "returns false for blocking: false" do + thread = Thread.new do + fiber = Fiber.new(blocking: false) { @method.call } + blocking = fiber.resume + + blocking.should == false + end + + thread.join + end + end +end diff --git a/ruby/spec/ruby/core/file/absolute_path_spec.rb b/ruby/spec/ruby/core/file/absolute_path_spec.rb index 52839cf1c..9f3992347 100644 --- a/ruby/spec/ruby/core/file/absolute_path_spec.rb +++ b/ruby/spec/ruby/core/file/absolute_path_spec.rb @@ -73,6 +73,12 @@ File.absolute_path('~').should_not == File.expand_path('~') end + platform_is_not :windows do + it "does not expand '~' when given dir argument" do + File.absolute_path('~', '/').should == '/~' + end + end + it "does not expand '~user' to a home directory." do path = File.dirname(@abs) Dir.chdir(path) do diff --git a/ruby/spec/ruby/core/file/atime_spec.rb b/ruby/spec/ruby/core/file/atime_spec.rb index 02e841272..cef07ba01 100644 --- a/ruby/spec/ruby/core/file/atime_spec.rb +++ b/ruby/spec/ruby/core/file/atime_spec.rb @@ -15,16 +15,18 @@ File.atime(@file).should be_kind_of(Time) end - guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do - ## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed. - it "returns the last access time for the named file with microseconds" do - supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10) - if supports_subseconds != 0 - expected_time = Time.at(Time.now.to_i + 0.123456) - File.utime expected_time, 0, @file - File.atime(@file).usec.should == expected_time.usec - else - File.atime(__FILE__).usec.should == 0 + platform_is :linux, :windows do + platform_is_not :"powerpc64le-linux" do # https://bugs.ruby-lang.org/issues/17926 + ## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed. + it "returns the last access time for the named file with microseconds" do + supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10) + if supports_subseconds != 0 + expected_time = Time.at(Time.now.to_i + 0.123456) + File.utime expected_time, 0, @file + File.atime(@file).usec.should == expected_time.usec + else + File.atime(__FILE__).usec.should == 0 + end end end end diff --git a/ruby/spec/ruby/core/file/basename_spec.rb b/ruby/spec/ruby/core/file/basename_spec.rb index 6d7e43208..989409d76 100644 --- a/ruby/spec/ruby/core/file/basename_spec.rb +++ b/ruby/spec/ruby/core/file/basename_spec.rb @@ -164,5 +164,20 @@ basename.encoding.should == Encoding::Windows_1250 end + it "returns a new unfrozen String" do + exts = [nil, '.rb', '.*', '.txt'] + ['foo.rb','//', '/test/', 'test'].each do |example| + exts.each do |ext| + original = example.freeze + result = if ext + File.basename(original, ext) + else + File.basename(original) + end + result.should_not equal(original) + result.frozen?.should == false + end + end + end end diff --git a/ruby/spec/ruby/core/file/ctime_spec.rb b/ruby/spec/ruby/core/file/ctime_spec.rb index 68a9fa43c..b16eb13c1 100644 --- a/ruby/spec/ruby/core/file/ctime_spec.rb +++ b/ruby/spec/ruby/core/file/ctime_spec.rb @@ -14,7 +14,7 @@ File.ctime(@file).should be_kind_of(Time) end - guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do + platform_is :linux, :windows do it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d+)/, 1], 10) if supports_subseconds != 0 diff --git a/ruby/spec/ruby/core/file/dirname_spec.rb b/ruby/spec/ruby/core/file/dirname_spec.rb index 2ef04a7b6..cf0f909f5 100644 --- a/ruby/spec/ruby/core/file/dirname_spec.rb +++ b/ruby/spec/ruby/core/file/dirname_spec.rb @@ -11,6 +11,22 @@ File.dirname('/foo/foo').should == '/foo' end + ruby_version_is '3.1' do + it "returns all the components of filename except the last parts by the level" do + File.dirname('/home/jason', 2).should == '/' + File.dirname('/home/jason/poot.txt', 2).should == '/home' + end + + it "returns the same string if the level is 0" do + File.dirname('poot.txt', 0).should == 'poot.txt' + File.dirname('/', 0).should == '/' + end + + it "raises ArgumentError if the level is negative" do + -> {File.dirname('/home/jason', -1)}.should raise_error(ArgumentError) + end + end + it "returns a String" do File.dirname("foo").should be_kind_of(String) end diff --git a/ruby/spec/ruby/core/file/exists_spec.rb b/ruby/spec/ruby/core/file/exists_spec.rb deleted file mode 100644 index 31d0e4dd1..000000000 --- a/ruby/spec/ruby/core/file/exists_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require_relative '../../spec_helper' -require_relative '../../shared/file/exist' - -describe "File.exists?" do - it_behaves_like :file_exist, :exists?, File -end diff --git a/ruby/spec/ruby/core/file/expand_path_spec.rb b/ruby/spec/ruby/core/file/expand_path_spec.rb index 88078645a..c31f885b9 100644 --- a/ruby/spec/ruby/core/file/expand_path_spec.rb +++ b/ruby/spec/ruby/core/file/expand_path_spec.rb @@ -203,9 +203,9 @@ it "does not return a frozen string" do home = "/rubyspec_home" - File.expand_path('~').frozen?.should == false - File.expand_path('~', '/tmp/gumby/ddd').frozen?.should == false - File.expand_path('~/a', '/tmp/gumby/ddd').frozen?.should == false + File.expand_path('~').should_not.frozen? + File.expand_path('~', '/tmp/gumby/ddd').should_not.frozen? + File.expand_path('~/a', '/tmp/gumby/ddd').should_not.frozen? end end diff --git a/ruby/spec/ruby/core/file/extname_spec.rb b/ruby/spec/ruby/core/file/extname_spec.rb index e9b53bc24..e182ed44f 100644 --- a/ruby/spec/ruby/core/file/extname_spec.rb +++ b/ruby/spec/ruby/core/file/extname_spec.rb @@ -12,6 +12,16 @@ File.extname(".app.conf").should == ".conf" end + it "returns unfrozen strings" do + File.extname("foo.rb").frozen?.should == false + File.extname("/foo/bar.rb").frozen?.should == false + File.extname("/foo.rb/bar.c").frozen?.should == false + File.extname("bar").frozen?.should == false + File.extname(".bashrc").frozen?.should == false + File.extname("/foo.bar/baz").frozen?.should == false + File.extname(".app.conf").frozen?.should == false + end + it "returns the extension for edge cases" do File.extname("").should == "" File.extname(".").should == "" diff --git a/ruby/spec/ruby/core/file/ftype_spec.rb b/ruby/spec/ruby/core/file/ftype_spec.rb index 8ff70baa8..cdddc404d 100644 --- a/ruby/spec/ruby/core/file/ftype_spec.rb +++ b/ruby/spec/ruby/core/file/ftype_spec.rb @@ -35,6 +35,14 @@ end end + it "uses to_path to convert arguments" do + FileSpecs.normal_file do |file| + obj = mock('path') + obj.should_receive(:to_path).and_return(file) + File.ftype(obj).should == 'file' + end + end + # Both FreeBSD and Windows does not have block devices platform_is_not :freebsd, :windows do with_block_device do diff --git a/ruby/spec/ruby/core/file/join_spec.rb b/ruby/spec/ruby/core/file/join_spec.rb index f1eab02de..0feedbae9 100644 --- a/ruby/spec/ruby/core/file/join_spec.rb +++ b/ruby/spec/ruby/core/file/join_spec.rb @@ -136,4 +136,13 @@ File.join(bin).should == "bin" File.join("usr", bin).should == "usr/bin" end + + it "raises errors for null bytes" do + -> { File.join("\x00x", "metadata.gz") }.should raise_error(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + -> { File.join("metadata.gz", "\x00x") }.should raise_error(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + end end diff --git a/ruby/spec/ruby/core/file/lchmod_spec.rb b/ruby/spec/ruby/core/file/lchmod_spec.rb index 9490459a0..7420b95e4 100644 --- a/ruby/spec/ruby/core/file/lchmod_spec.rb +++ b/ruby/spec/ruby/core/file/lchmod_spec.rb @@ -20,23 +20,13 @@ File.chmod(0222, @lname).should == 1 File.lchmod(0755, @lname).should == 1 - File.lstat(@lname).executable?.should == true - File.lstat(@lname).readable?.should == true - File.lstat(@lname).writable?.should == true + File.lstat(@lname).should.executable? + File.lstat(@lname).should.readable? + File.lstat(@lname).should.writable? - File.stat(@lname).executable?.should == false - File.stat(@lname).readable?.should == false - File.stat(@lname).writable?.should == true - end - end - - platform_is :linux, :openbsd, :aix do - it "returns false from #respond_to?" do - File.respond_to?(:lchmod).should be_false - end - - it "raises a NotImplementedError when called" do - -> { File.lchmod 0 }.should raise_error(NotImplementedError) + File.stat(@lname).should_not.executable? + File.stat(@lname).should_not.readable? + File.stat(@lname).should.writable? end end end diff --git a/ruby/spec/ruby/core/file/link_spec.rb b/ruby/spec/ruby/core/file/link_spec.rb index cc63c76aa..a5d5b4815 100644 --- a/ruby/spec/ruby/core/file/link_spec.rb +++ b/ruby/spec/ruby/core/file/link_spec.rb @@ -13,7 +13,7 @@ rm_r @link, @file end - platform_is_not :windows do + platform_is_not :windows, :android do it "link a file with another" do File.link(@file, @link).should == 0 File.should.exist?(@link) diff --git a/ruby/spec/ruby/core/file/lstat_spec.rb b/ruby/spec/ruby/core/file/lstat_spec.rb index 918ed0216..a5ea9d15a 100644 --- a/ruby/spec/ruby/core/file/lstat_spec.rb +++ b/ruby/spec/ruby/core/file/lstat_spec.rb @@ -22,8 +22,8 @@ it "returns a File::Stat object with symlink properties for a symlink" do st = File.lstat(@link) - st.symlink?.should == true - st.file?.should == false + st.should.symlink? + st.should_not.file? end end end diff --git a/ruby/spec/ruby/core/file/lutime_spec.rb b/ruby/spec/ruby/core/file/lutime_spec.rb index 7449bc438..1f0625f61 100644 --- a/ruby/spec/ruby/core/file/lutime_spec.rb +++ b/ruby/spec/ruby/core/file/lutime_spec.rb @@ -1,40 +1,38 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "File.lutime" do - platform_is_not :windows do - before :each do - @atime = Time.utc(2000) - @mtime = Time.utc(2001) - @file = tmp("specs_lutime_file") - @symlink = tmp("specs_lutime_symlink") - touch @file - File.symlink(@file, @symlink) - end +describe "File.lutime" do + platform_is_not :windows do + before :each do + @atime = Time.utc(2000) + @mtime = Time.utc(2001) + @file = tmp("specs_lutime_file") + @symlink = tmp("specs_lutime_symlink") + touch @file + File.symlink(@file, @symlink) + end - after :each do - rm_r @file, @symlink - end + after :each do + rm_r @file, @symlink + end - it "sets the access and modification time for a regular file" do - File.lutime(@atime, @mtime, @file) - stat = File.stat(@file) - stat.atime.should == @atime - stat.mtime.should === @mtime - end + it "sets the access and modification time for a regular file" do + File.lutime(@atime, @mtime, @file) + stat = File.stat(@file) + stat.atime.should == @atime + stat.mtime.should === @mtime + end - it "sets the access and modification time for a symlink" do - original = File.stat(@file) + it "sets the access and modification time for a symlink" do + original = File.stat(@file) - File.lutime(@atime, @mtime, @symlink) - stat = File.lstat(@symlink) - stat.atime.should == @atime - stat.mtime.should === @mtime + File.lutime(@atime, @mtime, @symlink) + stat = File.lstat(@symlink) + stat.atime.should == @atime + stat.mtime.should === @mtime - file = File.stat(@file) - file.atime.should == original.atime - file.mtime.should == original.mtime - end + file = File.stat(@file) + file.atime.should == original.atime + file.mtime.should == original.mtime end end end diff --git a/ruby/spec/ruby/core/file/mtime_spec.rb b/ruby/spec/ruby/core/file/mtime_spec.rb index 1941e2ff8..8d47d3021 100644 --- a/ruby/spec/ruby/core/file/mtime_spec.rb +++ b/ruby/spec/ruby/core/file/mtime_spec.rb @@ -15,7 +15,7 @@ File.mtime(@filename).should be_close(@mtime, TIME_TOLERANCE) end - guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do + platform_is :linux, :windows do it "returns the modification Time of the file with microseconds" do supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d+)/, 1], 10) if supports_subseconds != 0 diff --git a/ruby/spec/ruby/core/file/open_spec.rb b/ruby/spec/ruby/core/file/open_spec.rb index e3c561879..c7dd34d5c 100644 --- a/ruby/spec/ruby/core/file/open_spec.rb +++ b/ruby/spec/ruby/core/file/open_spec.rb @@ -28,7 +28,7 @@ describe "with a block" do it "does not raise error when file is closed inside the block" do @fh = File.open(@file) { |fh| fh.close; fh } - @fh.closed?.should == true + @fh.should.closed? end it "invokes close on an opened file when exiting the block" do @@ -485,7 +485,7 @@ File.size(@file).should > 0 File.open(@file, "w+") do |f| f.pos.should == 0 - f.eof?.should == true + f.should.eof? end File.size(@file).should == 0 end @@ -495,7 +495,7 @@ File.size(@file).should > 0 File.open(@file, "rb+") do |f| f.pos.should == 0 - f.eof?.should == false + f.should_not.eof? end end @@ -504,7 +504,7 @@ File.size(@file).should > 0 File.open(@file, "wb+") do |f| f.pos.should == 0 - f.eof?.should == true + f.should.eof? end File.size(@file).should == 0 end @@ -623,39 +623,35 @@ end end - ruby_version_is "2.5" do - it "raises ArgumentError if mixing :newline and binary mode" do - -> { - File.open(@file, "rb", newline: :universal) {} - }.should raise_error(ArgumentError, "newline decorator with binary mode") - end + it "raises ArgumentError if mixing :newline and binary mode" do + -> { + File.open(@file, "rb", newline: :universal) {} + }.should raise_error(ArgumentError, "newline decorator with binary mode") end - ruby_version_is "2.6" do - context "'x' flag" do - before :each do - @xfile = tmp("x-flag") - rm_r @xfile - end + context "'x' flag" do + before :each do + @xfile = tmp("x-flag") + rm_r @xfile + end - after :each do - rm_r @xfile - end + after :each do + rm_r @xfile + end - it "does nothing if the file doesn't exist" do - File.open(@xfile, "wx") { |f| f.write("content") } - File.read(@xfile).should == "content" - end + it "does nothing if the file doesn't exist" do + File.open(@xfile, "wx") { |f| f.write("content") } + File.read(@xfile).should == "content" + end - it "throws a Errno::EEXIST error if the file exists" do - touch @xfile - -> { File.open(@xfile, "wx") }.should raise_error(Errno::EEXIST) - end + it "throws a Errno::EEXIST error if the file exists" do + touch @xfile + -> { File.open(@xfile, "wx") }.should raise_error(Errno::EEXIST) + end - it "can't be used with 'r' and 'a' flags" do - -> { File.open(@xfile, "rx") }.should raise_error(ArgumentError, 'invalid access mode rx') - -> { File.open(@xfile, "ax") }.should raise_error(ArgumentError, 'invalid access mode ax') - end + it "can't be used with 'r' and 'a' flags" do + -> { File.open(@xfile, "rx") }.should raise_error(ArgumentError, 'invalid access mode rx') + -> { File.open(@xfile, "ax") }.should raise_error(ArgumentError, 'invalid access mode ax') end end end diff --git a/ruby/spec/ruby/core/file/realpath_spec.rb b/ruby/spec/ruby/core/file/realpath_spec.rb index 0c5d19287..bd27e09da 100644 --- a/ruby/spec/ruby/core/file/realpath_spec.rb +++ b/ruby/spec/ruby/core/file/realpath_spec.rb @@ -67,6 +67,12 @@ it "raises Errno::ENOENT if the symlink points to an absent file" do -> { File.realpath(@fake_link) }.should raise_error(Errno::ENOENT) end + + it "converts the argument with #to_path" do + path = mock("path") + path.should_receive(:to_path).and_return(__FILE__) + File.realpath(path).should == File.realpath(__FILE__ ) + end end end diff --git a/ruby/spec/ruby/core/file/shared/path.rb b/ruby/spec/ruby/core/file/shared/path.rb index cfd119f79..0a5abe33f 100644 --- a/ruby/spec/ruby/core/file/shared/path.rb +++ b/ruby/spec/ruby/core/file/shared/path.rb @@ -15,6 +15,23 @@ @file.send(@method).should be_an_instance_of(String) end + it "returns a different String on every call" do + @file = File.new @path + path1 = @file.send(@method) + path2 = @file.send(@method) + path1.should == path2 + path1.should_not.equal?(path2) + end + + it "returns a mutable String" do + @file = File.new @path.dup.freeze + path = @file.send(@method) + path.should == @path + path.should_not.frozen? + path << "test" + @file.send(@method).should == @path + end + it "calls to_str on argument and returns exact value" do path = mock('path') path.should_receive(:to_str).and_return(@path) @@ -50,26 +67,24 @@ @file.send(@method).encoding.should == Encoding.find("euc-jp") end - ruby_version_is "2.5" do - platform_is :linux do - guard -> { defined?(File::TMPFILE) } do - before :each do - @dir = tmp("tmpfilespec") - mkdir_p @dir - end + platform_is :linux do + guard -> { defined?(File::TMPFILE) } do + before :each do + @dir = tmp("tmpfilespec") + mkdir_p @dir + end - after :each do - rm_r @dir - end + after :each do + rm_r @dir + end - it "raises IOError if file was opened with File::TMPFILE" do - begin - File.open(@dir, File::RDWR | File::TMPFILE) do |f| - -> { f.send(@method) }.should raise_error(IOError) - end - rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR - skip "no support from the filesystem" + it "raises IOError if file was opened with File::TMPFILE" do + begin + File.open(@dir, File::RDWR | File::TMPFILE) do |f| + -> { f.send(@method) }.should raise_error(IOError) end + rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR + skip "no support from the filesystem" end end end diff --git a/ruby/spec/ruby/core/file/shared/read.rb b/ruby/spec/ruby/core/file/shared/read.rb index a2d479966..f23223529 100644 --- a/ruby/spec/ruby/core/file/shared/read.rb +++ b/ruby/spec/ruby/core/file/shared/read.rb @@ -1,13 +1,13 @@ require_relative '../../dir/fixtures/common' describe :file_read_directory, shared: true do - platform_is :darwin, :linux, :openbsd, :windows do + platform_is :darwin, :linux, :freebsd, :openbsd, :windows do it "raises an Errno::EISDIR when passed a path that is a directory" do -> { @object.send(@method, ".") }.should raise_error(Errno::EISDIR) end end - platform_is :freebsd, :netbsd do + platform_is :netbsd do it "does not raises any exception when passed a path that is a directory" do -> { @object.send(@method, ".") }.should_not raise_error end diff --git a/ruby/spec/ruby/core/file/size_spec.rb b/ruby/spec/ruby/core/file/size_spec.rb index a2bf408da..11d20cbac 100644 --- a/ruby/spec/ruby/core/file/size_spec.rb +++ b/ruby/spec/ruby/core/file/size_spec.rb @@ -59,8 +59,8 @@ @file.respond_to?(:size).should be_true end - it "returns the file's size as a Fixnum" do - @file.size.should be_an_instance_of(Fixnum) + it "returns the file's size as an Integer" do + @file.size.should be_an_instance_of(Integer) end it "returns the file's size in bytes" do diff --git a/ruby/spec/ruby/core/file/stat/nlink_spec.rb b/ruby/spec/ruby/core/file/stat/nlink_spec.rb index 2dd0bff12..7143923cf 100644 --- a/ruby/spec/ruby/core/file/stat/nlink_spec.rb +++ b/ruby/spec/ruby/core/file/stat/nlink_spec.rb @@ -11,7 +11,7 @@ rm_r @link, @file end - platform_is_not :windows do + platform_is_not :windows, :android do it "returns the number of links to a file" do File::Stat.new(@file).nlink.should == 1 File.link(@file, @link) diff --git a/ruby/spec/ruby/core/file/stat/owned_spec.rb b/ruby/spec/ruby/core/file/stat/owned_spec.rb index 6f0c250f8..a23ad850c 100644 --- a/ruby/spec/ruby/core/file/stat/owned_spec.rb +++ b/ruby/spec/ruby/core/file/stat/owned_spec.rb @@ -18,15 +18,15 @@ it "returns true if the file is owned by the user" do st = File.stat(@file) - st.owned?.should == true + st.should.owned? end - platform_is_not :windows do + platform_is_not :windows, :android do as_user do it "returns false if the file is not owned by the user" do system_file = '/etc/passwd' st = File.stat(system_file) - st.owned?.should == false + st.should_not.owned? end end end diff --git a/ruby/spec/ruby/core/file/stat/pipe_spec.rb b/ruby/spec/ruby/core/file/stat/pipe_spec.rb index 7abb6c742..692dfbf42 100644 --- a/ruby/spec/ruby/core/file/stat/pipe_spec.rb +++ b/ruby/spec/ruby/core/file/stat/pipe_spec.rb @@ -12,7 +12,7 @@ touch(filename) st = File.stat(filename) - st.pipe?.should == false + st.should_not.pipe? rm_r filename end @@ -23,7 +23,7 @@ File.mkfifo(filename) st = File.stat(filename) - st.pipe?.should == true + st.should.pipe? rm_r filename end diff --git a/ruby/spec/ruby/core/file/stat_spec.rb b/ruby/spec/ruby/core/file/stat_spec.rb index 31f9dc58a..636550005 100644 --- a/ruby/spec/ruby/core/file/stat_spec.rb +++ b/ruby/spec/ruby/core/file/stat_spec.rb @@ -23,8 +23,8 @@ st = f.stat - st.file?.should == true - st.zero?.should == false + st.should.file? + st.should_not.zero? st.size.should == 8 st.size?.should == 8 st.blksize.should >= 0 @@ -38,8 +38,18 @@ File.symlink(@file, @link) st = File.stat(@link) - st.file?.should == true - st.symlink?.should == false + st.should.file? + st.should_not.symlink? + end + + it "returns an error when given missing non-ASCII path" do + missing_path = "/missingfilepath\xE3E4".b + -> { + File.stat(missing_path) + }.should raise_error(SystemCallError) { |e| + [Errno::ENOENT, Errno::EILSEQ].should include(e.class) + e.message.should include(missing_path) + } end end end diff --git a/ruby/spec/ruby/core/file/truncate_spec.rb b/ruby/spec/ruby/core/file/truncate_spec.rb index 43b86b738..b4a2e3e57 100644 --- a/ruby/spec/ruby/core/file/truncate_spec.rb +++ b/ruby/spec/ruby/core/file/truncate_spec.rb @@ -18,7 +18,7 @@ File.open(@name, "r") do |f| f.read(99).should == "12345" - f.eof?.should == true + f.should.eof? end end @@ -120,7 +120,7 @@ File.size(@name).should == 5 File.open(@name, "r") do |f| f.read(99).should == "12345" - f.eof?.should == true + f.should.eof? end end @@ -161,7 +161,7 @@ it "raises an IOError if file is closed" do @file.close - @file.closed?.should == true + @file.should.closed? -> { @file.truncate(42) }.should raise_error(IOError) end diff --git a/ruby/spec/ruby/core/file/umask_spec.rb b/ruby/spec/ruby/core/file/umask_spec.rb index 2640e3c31..7f7e40abb 100644 --- a/ruby/spec/ruby/core/file/umask_spec.rb +++ b/ruby/spec/ruby/core/file/umask_spec.rb @@ -12,8 +12,8 @@ File.umask(@orig_umask) end - it "returns a Fixnum" do - File.umask.should be_kind_of(Fixnum) + it "returns an Integer" do + File.umask.should be_kind_of(Integer) end platform_is_not :windows do diff --git a/ruby/spec/ruby/core/file/utime_spec.rb b/ruby/spec/ruby/core/file/utime_spec.rb index 03adc76ef..59eef20c6 100644 --- a/ruby/spec/ruby/core/file/utime_spec.rb +++ b/ruby/spec/ruby/core/file/utime_spec.rb @@ -3,7 +3,7 @@ describe "File.utime" do before :all do - @time_is_float = /mswin|mingw/ =~ RUBY_PLATFORM && RUBY_VERSION >= '2.5' + @time_is_float = platform_is :windows end before :each do @@ -70,13 +70,26 @@ end end + it "may set nanosecond precision" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) + File.utime(t, t, @file1) + File.atime(@file1).nsec.should.between?(0, 123500000) + File.mtime(@file1).nsec.should.between?(0, 123500000) + end + platform_is :linux do platform_is wordsize: 64 do - it "allows Time instances in the far future to set mtime and atime" do + it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19)" do + # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps + # "Therefore, timestamps should not overflow until May 2446." + # https://lwn.net/Articles/804382/ + # "On-disk timestamps hitting the y2038 limit..." + # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8 + # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz time = Time.at(1<<44) File.utime(time, time, @file1) - File.atime(@file1).year.should == 559444 - File.mtime(@file1).year.should == 559444 + [559444, 2446, 2038].should.include? File.atime(@file1).year + [559444, 2446, 2038].should.include? File.mtime(@file1).year end end end diff --git a/ruby/spec/ruby/core/filetest/exists_spec.rb b/ruby/spec/ruby/core/filetest/exists_spec.rb deleted file mode 100644 index d090d7d74..000000000 --- a/ruby/spec/ruby/core/filetest/exists_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require_relative '../../spec_helper' -require_relative '../../shared/file/exist' - -describe "FileTest.exists?" do - it_behaves_like :file_exist, :exists?, FileTest -end diff --git a/ruby/spec/ruby/core/float/comparison_spec.rb b/ruby/spec/ruby/core/float/comparison_spec.rb index 2dc993a17..53e7ec332 100644 --- a/ruby/spec/ruby/core/float/comparison_spec.rb +++ b/ruby/spec/ruby/core/float/comparison_spec.rb @@ -14,6 +14,9 @@ it "returns nil when the given argument is not a Float" do (1.0 <=> "1").should be_nil + (1.0 <=> "1".freeze).should be_nil + (1.0 <=> :one).should be_nil + (1.0 <=> true).should be_nil end it "compares using #coerce when argument is not a Float" do @@ -33,24 +36,22 @@ def coerce(other) coercible.call_count.should == 3 end - ruby_version_is "2.5" do - it "raises TypeError when #coerce misbehaves" do - klass = Class.new do - def coerce(other) - :incorrect - end + it "raises TypeError when #coerce misbehaves" do + klass = Class.new do + def coerce(other) + :incorrect end - - bad_coercible = klass.new - -> { - 4.2 <=> bad_coercible - }.should raise_error(TypeError, "coerce must return [x, y]") end + + bad_coercible = klass.new + -> { + 4.2 <=> bad_coercible + }.should raise_error(TypeError, "coerce must return [x, y]") end # The 4 tests below are taken from matz's revision 23730 for Ruby trunk # - it "returns 1 when self is Infinity and other is a Bignum" do + it "returns 1 when self is Infinity and other is an Integer" do (infinity_value <=> Float::MAX.to_i*2).should == 1 end @@ -65,4 +66,43 @@ def coerce(other) it "returns 1 when self is negative and other is -Infinity" do (-Float::MAX.to_i*2 <=> -infinity_value).should == 1 end + + it "returns 0 when self is Infinity and other other is infinite?=1" do + obj = Object.new + def obj.infinite? + 1 + end + (infinity_value <=> obj).should == 0 + end + + it "returns 1 when self is Infinity and other is infinite?=-1" do + obj = Object.new + def obj.infinite? + -1 + end + (infinity_value <=> obj).should == 1 + end + + it "returns 1 when self is Infinity and other is infinite?=nil (which means finite)" do + obj = Object.new + def obj.infinite? + nil + end + (infinity_value <=> obj).should == 1 + end + + it "returns 0 for -0.0 and 0.0" do + (-0.0 <=> 0.0).should == 0 + (0.0 <=> -0.0).should == 0 + end + + it "returns 0 for -0.0 and 0" do + (-0.0 <=> 0).should == 0 + (0 <=> -0.0).should == 0 + end + + it "returns 0 for 0.0 and 0" do + (0.0 <=> 0).should == 0 + (0 <=> 0.0).should == 0 + end end diff --git a/ruby/spec/ruby/core/float/finite_spec.rb b/ruby/spec/ruby/core/float/finite_spec.rb index c5fb3df84..d839b30e3 100644 --- a/ruby/spec/ruby/core/float/finite_spec.rb +++ b/ruby/spec/ruby/core/float/finite_spec.rb @@ -2,18 +2,18 @@ describe "Float#finite?" do it "returns true for finite values" do - 3.14159.finite?.should == true + 3.14159.should.finite? end it "returns false for positive infinity" do - infinity_value.finite?.should == false + infinity_value.should_not.finite? end it "returns false for negative infinity" do - (-infinity_value).finite?.should == false + (-infinity_value).should_not.finite? end it "returns false for NaN" do - nan_value.finite?.should == false + nan_value.should_not.finite? end end diff --git a/ruby/spec/ruby/core/float/inspect_spec.rb b/ruby/spec/ruby/core/float/inspect_spec.rb new file mode 100644 index 000000000..4be1927d8 --- /dev/null +++ b/ruby/spec/ruby/core/float/inspect_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative 'shared/to_s' + +describe "Float#inspect" do + it_behaves_like :float_to_s, :inspect +end diff --git a/ruby/spec/ruby/core/float/nan_spec.rb b/ruby/spec/ruby/core/float/nan_spec.rb index d09d25153..c1043ef21 100644 --- a/ruby/spec/ruby/core/float/nan_spec.rb +++ b/ruby/spec/ruby/core/float/nan_spec.rb @@ -2,8 +2,8 @@ describe "Float#nan?" do it "returns true if self is not a valid IEEE floating-point number" do - 0.0.nan?.should == false - -1.5.nan?.should == false - nan_value.nan?.should == true + 0.0.should_not.nan? + -1.5.should_not.nan? + nan_value.should.nan? end end diff --git a/ruby/spec/ruby/core/float/negative_spec.rb b/ruby/spec/ruby/core/float/negative_spec.rb new file mode 100644 index 000000000..511d92ade --- /dev/null +++ b/ruby/spec/ruby/core/float/negative_spec.rb @@ -0,0 +1,33 @@ +require_relative '../../spec_helper' + +describe "Float#negative?" do + describe "on positive numbers" do + it "returns false" do + 0.1.negative?.should be_false + end + end + + describe "on zero" do + it "returns false" do + 0.0.negative?.should be_false + end + end + + describe "on negative zero" do + it "returns false" do + -0.0.negative?.should be_false + end + end + + describe "on negative numbers" do + it "returns true" do + -0.1.negative?.should be_true + end + end + + describe "on NaN" do + it "returns false" do + nan_value.negative?.should be_false + end + end +end diff --git a/ruby/spec/ruby/core/float/next_float_spec.rb b/ruby/spec/ruby/core/float/next_float_spec.rb index 2f0eff605..29e2d3114 100644 --- a/ruby/spec/ruby/core/float/next_float_spec.rb +++ b/ruby/spec/ruby/core/float/next_float_spec.rb @@ -44,6 +44,6 @@ end it "returns NAN if NAN was the receiver" do - Float::NAN.next_float.nan?.should == true + Float::NAN.next_float.should.nan? end end diff --git a/ruby/spec/ruby/core/float/positive_spec.rb b/ruby/spec/ruby/core/float/positive_spec.rb new file mode 100644 index 000000000..575f92a72 --- /dev/null +++ b/ruby/spec/ruby/core/float/positive_spec.rb @@ -0,0 +1,33 @@ +require_relative '../../spec_helper' + +describe "Float#positive?" do + describe "on positive numbers" do + it "returns true" do + 0.1.positive?.should be_true + end + end + + describe "on zero" do + it "returns false" do + 0.0.positive?.should be_false + end + end + + describe "on negative zero" do + it "returns false" do + -0.0.positive?.should be_false + end + end + + describe "on negative numbers" do + it "returns false" do + -0.1.positive?.should be_false + end + end + + describe "on NaN" do + it "returns false" do + nan_value.positive?.should be_false + end + end +end diff --git a/ruby/spec/ruby/core/float/prev_float_spec.rb b/ruby/spec/ruby/core/float/prev_float_spec.rb index 40fcc25a6..5e50269da 100644 --- a/ruby/spec/ruby/core/float/prev_float_spec.rb +++ b/ruby/spec/ruby/core/float/prev_float_spec.rb @@ -44,6 +44,6 @@ end it "returns NAN if NAN was the receiver" do - Float::NAN.prev_float.nan?.should == true + Float::NAN.prev_float.should.nan? end end diff --git a/ruby/spec/ruby/core/float/round_spec.rb b/ruby/spec/ruby/core/float/round_spec.rb index e14368236..4bd2dc460 100644 --- a/ruby/spec/ruby/core/float/round_spec.rb +++ b/ruby/spec/ruby/core/float/round_spec.rb @@ -114,4 +114,17 @@ it "raise for a non-existent round mode" do -> { 14.2.round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense") end + + describe "when 0.0 is given" do + it "returns self for positive ndigits" do + (0.0).round(5).inspect.should == "0.0" + (-0.0).round(1).inspect.should == "-0.0" + end + + it "returns 0 for 0 or undefined ndigits" do + (0.0).round.should == 0 + (-0.0).round(0).should == 0 + (0.0).round(half: :up) == 0 + end + end end diff --git a/ruby/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb b/ruby/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb index 19a02572d..eec92d858 100644 --- a/ruby/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb +++ b/ruby/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb @@ -1,33 +1,11 @@ require_relative '../fixtures/classes' describe :float_arithmetic_exception_in_coerce, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) + it "does not rescue exception raised in other#coerce" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) - # e.g. 1.0 > b - -> { 1.0.send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Float/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. 1.0 > b - -> { 1.0.send(@method, b) }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) - - # e.g. 1.0 > b - -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError) - end + # e.g. 1.0 > b + -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError) end end diff --git a/ruby/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb b/ruby/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb index f8ded5364..3e2c1e28d 100644 --- a/ruby/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb +++ b/ruby/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb @@ -1,35 +1,11 @@ require_relative '../fixtures/classes' describe :float_comparison_exception_in_coerce, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) + it "does not rescue exception raised in other#coerce" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) - # e.g. 1.0 > b - -> { - -> { 1.0.send(@method, b) }.should raise_error(ArgumentError, /comparison of Float with MockObject failed/) - }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. 1.0 > b - -> { 1.0.send(@method, b) }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError) - - # e.g. 1.0 > b - -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError) - end + # e.g. 1.0 > b + -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError) end end diff --git a/ruby/spec/ruby/core/float/shared/quo.rb b/ruby/spec/ruby/core/float/shared/quo.rb index 3487824f7..0c90171b8 100644 --- a/ruby/spec/ruby/core/float/shared/quo.rb +++ b/ruby/spec/ruby/core/float/shared/quo.rb @@ -1,9 +1,9 @@ describe :float_quo, shared: true do - it "performs floating-point division between self and a Fixnum" do + it "performs floating-point division between self and an Integer" do 8.9.send(@method, 7).should == 1.2714285714285716 end - it "performs floating-point division between self and a Bignum" do + it "performs floating-point division between self and an Integer" do 8.9.send(@method, 9999999999999**9).should == 8.900000000008011e-117 end diff --git a/ruby/spec/ruby/core/float/shared/to_s.rb b/ruby/spec/ruby/core/float/shared/to_s.rb new file mode 100644 index 000000000..0925efc0f --- /dev/null +++ b/ruby/spec/ruby/core/float/shared/to_s.rb @@ -0,0 +1,308 @@ +describe :float_to_s, shared: true do + it "returns 'NaN' for NaN" do + nan_value().send(@method).should == 'NaN' + end + + it "returns 'Infinity' for positive infinity" do + infinity_value().send(@method).should == 'Infinity' + end + + it "returns '-Infinity' for negative infinity" do + (-infinity_value()).send(@method).should == '-Infinity' + end + + it "returns '0.0' for 0.0" do + 0.0.send(@method).should == "0.0" + end + + platform_is_not :openbsd do + it "emits '-' for -0.0" do + -0.0.send(@method).should == "-0.0" + end + end + + it "emits a '-' for negative values" do + -3.14.send(@method).should == "-3.14" + end + + it "emits a trailing '.0' for a whole number" do + 50.0.send(@method).should == "50.0" + end + + it "emits a trailing '.0' for the mantissa in e format" do + 1.0e20.send(@method).should == "1.0e+20" + end + + it "uses non-e format for a positive value with fractional part having 5 significant figures" do + 0.0001.send(@method).should == "0.0001" + end + + it "uses non-e format for a negative value with fractional part having 5 significant figures" do + -0.0001.send(@method).should == "-0.0001" + end + + it "uses e format for a positive value with fractional part having 6 significant figures" do + 0.00001.send(@method).should == "1.0e-05" + end + + it "uses e format for a negative value with fractional part having 6 significant figures" do + -0.00001.send(@method).should == "-1.0e-05" + end + + it "uses non-e format for a positive value with whole part having 15 significant figures" do + 10000000000000.0.send(@method).should == "10000000000000.0" + end + + it "uses non-e format for a negative value with whole part having 15 significant figures" do + -10000000000000.0.send(@method).should == "-10000000000000.0" + end + + it "uses non-e format for a positive value with whole part having 16 significant figures" do + 100000000000000.0.send(@method).should == "100000000000000.0" + end + + it "uses non-e format for a negative value with whole part having 16 significant figures" do + -100000000000000.0.send(@method).should == "-100000000000000.0" + end + + it "uses e format for a positive value with whole part having 18 significant figures" do + 10000000000000000.0.send(@method).should == "1.0e+16" + end + + it "uses e format for a negative value with whole part having 18 significant figures" do + -10000000000000000.0.send(@method).should == "-1.0e+16" + end + + it "uses e format for a positive value with whole part having 17 significant figures" do + 1000000000000000.0.send(@method).should == "1.0e+15" + end + + it "uses e format for a negative value with whole part having 17 significant figures" do + -1000000000000000.0.send(@method).should == "-1.0e+15" + end + + # #3273 + it "outputs the minimal, unique form necessary to recreate the value" do + value = 0.21611564636388508 + string = "0.21611564636388508" + + value.send(@method).should == string + string.to_f.should == value + end + + it "outputs the minimal, unique form to represent the value" do + 0.56.send(@method).should == "0.56" + end + + describe "matches" do + it "random examples in all ranges" do + # 50.times do + # bytes = (0...8).map { rand(256) } + # string = bytes.pack('C8') + # float = string.unpack('D').first + # puts "#{'%.20g' % float}.send(@method).should == #{float.send(@method).inspect}" + # end + + 2.5540217314354050325e+163.send(@method).should == "2.554021731435405e+163" + 2.5492588360356597544e-172.send(@method).should == "2.5492588360356598e-172" + 1.742770260934704852e-82.send(@method).should == "1.7427702609347049e-82" + 6.2108093676180883209e-104.send(@method).should == "6.210809367618088e-104" + -3.3448803488331067402e-143.send(@method).should == "-3.3448803488331067e-143" + -2.2740074343500832557e-168.send(@method).should == "-2.2740074343500833e-168" + 7.0587971678048535732e+191.send(@method).should == "7.058797167804854e+191" + -284438.88327586348169.send(@method).should == "-284438.8832758635" + 3.953272468476091301e+105.send(@method).should == "3.9532724684760913e+105" + -3.6361359552959847853e+100.send(@method).should == "-3.636135955295985e+100" + -1.3222325865575206185e-31.send(@method).should == "-1.3222325865575206e-31" + 1.1440138916932761366e+130.send(@method).should == "1.1440138916932761e+130" + 4.8750891560387561157e-286.send(@method).should == "4.875089156038756e-286" + 5.6101113356591453525e-257.send(@method).should == "5.610111335659145e-257" + -3.829644279545809575e-100.send(@method).should == "-3.8296442795458096e-100" + 1.5342839401396406117e-194.send(@method).should == "1.5342839401396406e-194" + 2.2284972755169921402e-144.send(@method).should == "2.228497275516992e-144" + 2.1825655917065601737e-61.send(@method).should == "2.1825655917065602e-61" + -2.6672271363524338322e-62.send(@method).should == "-2.667227136352434e-62" + -1.9257995160119059415e+21.send(@method).should == "-1.925799516011906e+21" + -8.9096732962887121718e-198.send(@method).should == "-8.909673296288712e-198" + 2.0202075376548644959e-90.send(@method).should == "2.0202075376548645e-90" + -7.7341602581786258961e-266.send(@method).should == "-7.734160258178626e-266" + 3.5134482598733635046e+98.send(@method).should == "3.5134482598733635e+98" + -2.124411722371029134e+154.send(@method).should == "-2.124411722371029e+154" + -4.573908787355718687e+110.send(@method).should == "-4.573908787355719e+110" + -1.9344425934170969879e-232.send(@method).should == "-1.934442593417097e-232" + -1.3274227399979271095e+171.send(@method).should == "-1.3274227399979271e+171" + 9.3495270482104442383e-283.send(@method).should == "9.349527048210444e-283" + -4.2046059371986483233e+307.send(@method).should == "-4.2046059371986483e+307" + 3.6133547278583543004e-117.send(@method).should == "3.613354727858354e-117" + 4.9247416523566613499e-08.send(@method).should == "4.9247416523566613e-08" + 1.6936145488250064007e-71.send(@method).should == "1.6936145488250064e-71" + 2.4455483206829433098e+96.send(@method).should == "2.4455483206829433e+96" + 7.9797449851436455384e+124.send(@method).should == "7.979744985143646e+124" + -1.3873689634457876774e-129.send(@method).should == "-1.3873689634457877e-129" + 3.9761102037533483075e+284.send(@method).should == "3.976110203753348e+284" + -4.2819791952139402486e-303.send(@method).should == "-4.28197919521394e-303" + -5.7981017546689831298e-116.send(@method).should == "-5.798101754668983e-116" + -3.953266497860534199e-28.send(@method).should == "-3.953266497860534e-28" + -2.0659852720290440959e-243.send(@method).should == "-2.065985272029044e-243" + 8.9670488995878688018e-05.send(@method).should == "8.967048899587869e-05" + -1.2317943708113061768e-98.send(@method).should == "-1.2317943708113062e-98" + -3.8930768307633080463e+248.send(@method).should == "-3.893076830763308e+248" + 6.5854032671803925627e-239.send(@method).should == "6.5854032671803926e-239" + 4.6257022188980878952e+177.send(@method).should == "4.625702218898088e+177" + -1.9397155125507235603e-187.send(@method).should == "-1.9397155125507236e-187" + 8.5752156951245705056e+117.send(@method).should == "8.57521569512457e+117" + -2.4784875958162501671e-132.send(@method).should == "-2.4784875958162502e-132" + -4.4125691841230058457e-203.send(@method).should == "-4.412569184123006e-203" + end + + it "random examples in human ranges" do + # 50.times do + # formatted = '' + # rand(1..3).times do + # formatted << rand(10).to_s + # end + # formatted << '.' + # rand(1..9).times do + # formatted << rand(10).to_s + # end + # float = formatted.to_f + # puts "#{'%.20f' % float}.send(@method).should == #{float.send(@method).inspect}" + # end + + 5.17869899999999994122.send(@method).should == "5.178699" + 905.62695729999995819526.send(@method).should == "905.6269573" + 62.75999999999999801048.send(@method).should == "62.76" + 6.93856795800000014651.send(@method).should == "6.938567958" + 4.95999999999999996447.send(@method).should == "4.96" + 32.77993899999999882766.send(@method).should == "32.779939" + 544.12756779999995160324.send(@method).should == "544.1275678" + 66.25801119999999855281.send(@method).should == "66.2580112" + 7.90000000000000035527.send(@method).should == "7.9" + 5.93100000000000004974.send(@method).should == "5.931" + 5.21229313600000043749.send(@method).should == "5.212293136" + 503.44173809000000119340.send(@method).should == "503.44173809" + 79.26000000000000511591.send(@method).should == "79.26" + 8.51524999999999998579.send(@method).should == "8.51525" + 174.00000000000000000000.send(@method).should == "174.0" + 50.39580000000000126192.send(@method).should == "50.3958" + 35.28999999999999914735.send(@method).should == "35.29" + 5.43136675399999990788.send(@method).should == "5.431366754" + 654.07680000000004838512.send(@method).should == "654.0768" + 6.07423700000000010846.send(@method).should == "6.074237" + 102.25779799999999397642.send(@method).should == "102.257798" + 5.08129999999999970584.send(@method).should == "5.0813" + 6.00000000000000000000.send(@method).should == "6.0" + 8.30000000000000071054.send(@method).should == "8.3" + 32.68345999999999662577.send(@method).should == "32.68346" + 581.11170000000004165486.send(@method).should == "581.1117" + 76.31342999999999676675.send(@method).should == "76.31343" + 438.30826000000001840817.send(@method).should == "438.30826" + 482.06631994000002805478.send(@method).should == "482.06631994" + 55.92721026899999969828.send(@method).should == "55.927210269" + 4.00000000000000000000.send(@method).should == "4.0" + 55.86693999999999959982.send(@method).should == "55.86694" + 787.98299999999994724931.send(@method).should == "787.983" + 5.73810511000000023074.send(@method).should == "5.73810511" + 74.51926810000000500622.send(@method).should == "74.5192681" + 892.89999999999997726263.send(@method).should == "892.9" + 68.27299999999999613465.send(@method).should == "68.273" + 904.10000000000002273737.send(@method).should == "904.1" + 5.23200000000000020606.send(@method).should == "5.232" + 4.09628000000000014325.send(@method).should == "4.09628" + 46.05152633699999853434.send(@method).should == "46.051526337" + 142.12884990599999923688.send(@method).should == "142.128849906" + 3.83057023500000015659.send(@method).should == "3.830570235" + 11.81684594699999912848.send(@method).should == "11.816845947" + 80.50000000000000000000.send(@method).should == "80.5" + 382.18215010000000120272.send(@method).should == "382.1821501" + 55.38444606899999911320.send(@method).should == "55.384446069" + 5.78000000000000024869.send(@method).should == "5.78" + 2.88244999999999995666.send(@method).should == "2.88245" + 43.27709999999999723741.send(@method).should == "43.2771" + end + + it "random values from divisions" do + (1.0 / 7).send(@method).should == "0.14285714285714285" + + # 50.times do + # a = rand(10) + # b = rand(10) + # c = rand(10) + # d = rand(10) + # expression = "#{a}.#{b} / #{c}.#{d}" + # puts " (#{expression}).send(@method).should == #{eval(expression).send(@method).inspect}" + # end + + (1.1 / 7.1).send(@method).should == "0.15492957746478875" + (6.5 / 8.8).send(@method).should == "0.7386363636363635" + (4.8 / 4.3).send(@method).should == "1.1162790697674418" + (4.0 / 1.9).send(@method).should == "2.1052631578947367" + (9.1 / 0.8).send(@method).should == "11.374999999999998" + (5.3 / 7.5).send(@method).should == "0.7066666666666667" + (2.8 / 1.8).send(@method).should == "1.5555555555555554" + (2.1 / 2.5).send(@method).should == "0.8400000000000001" + (3.5 / 6.0).send(@method).should == "0.5833333333333334" + (4.6 / 0.3).send(@method).should == "15.333333333333332" + (0.6 / 2.4).send(@method).should == "0.25" + (1.3 / 9.1).send(@method).should == "0.14285714285714288" + (0.3 / 5.0).send(@method).should == "0.06" + (5.0 / 4.2).send(@method).should == "1.1904761904761905" + (3.0 / 2.0).send(@method).should == "1.5" + (6.3 / 2.0).send(@method).should == "3.15" + (5.4 / 6.0).send(@method).should == "0.9" + (9.6 / 8.1).send(@method).should == "1.1851851851851851" + (8.7 / 1.6).send(@method).should == "5.437499999999999" + (1.9 / 7.8).send(@method).should == "0.24358974358974358" + (0.5 / 2.1).send(@method).should == "0.23809523809523808" + (9.3 / 5.8).send(@method).should == "1.6034482758620692" + (2.7 / 8.0).send(@method).should == "0.3375" + (9.7 / 7.8).send(@method).should == "1.2435897435897436" + (8.1 / 2.4).send(@method).should == "3.375" + (7.7 / 2.7).send(@method).should == "2.8518518518518516" + (7.9 / 1.7).send(@method).should == "4.647058823529412" + (6.5 / 8.2).send(@method).should == "0.7926829268292683" + (7.8 / 9.6).send(@method).should == "0.8125" + (2.2 / 4.6).send(@method).should == "0.47826086956521746" + (0.0 / 1.0).send(@method).should == "0.0" + (8.3 / 2.9).send(@method).should == "2.8620689655172415" + (3.1 / 6.1).send(@method).should == "0.5081967213114754" + (2.8 / 7.8).send(@method).should == "0.358974358974359" + (8.0 / 0.1).send(@method).should == "80.0" + (1.7 / 6.4).send(@method).should == "0.265625" + (1.8 / 5.4).send(@method).should == "0.3333333333333333" + (8.0 / 5.8).send(@method).should == "1.3793103448275863" + (5.2 / 4.1).send(@method).should == "1.2682926829268295" + (9.8 / 5.8).send(@method).should == "1.6896551724137934" + (5.4 / 9.5).send(@method).should == "0.5684210526315789" + (8.4 / 4.9).send(@method).should == "1.7142857142857142" + (1.7 / 3.5).send(@method).should == "0.4857142857142857" + (1.2 / 5.1).send(@method).should == "0.23529411764705882" + (1.4 / 2.0).send(@method).should == "0.7" + (4.8 / 8.0).send(@method).should == "0.6" + (9.0 / 2.5).send(@method).should == "3.6" + (0.2 / 0.6).send(@method).should == "0.33333333333333337" + (7.8 / 5.2).send(@method).should == "1.5" + (9.5 / 5.5).send(@method).should == "1.7272727272727273" + end + end + + describe 'encoding' do + before :each do + @internal = Encoding.default_internal + end + + after :each do + Encoding.default_internal = @internal + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do + Encoding.default_internal = nil + 1.23.send(@method).encoding.should equal(Encoding::US_ASCII) + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do + Encoding.default_internal = Encoding::IBM437 + 5.47.send(@method).encoding.should equal(Encoding::US_ASCII) + end + end +end diff --git a/ruby/spec/ruby/core/float/to_s_spec.rb b/ruby/spec/ruby/core/float/to_s_spec.rb index ad04bc4fb..6727a883f 100644 --- a/ruby/spec/ruby/core/float/to_s_spec.rb +++ b/ruby/spec/ruby/core/float/to_s_spec.rb @@ -1,310 +1,6 @@ require_relative '../../spec_helper' +require_relative 'shared/to_s' describe "Float#to_s" do - it "returns 'NaN' for NaN" do - nan_value().to_s.should == 'NaN' - end - - it "returns 'Infinity' for positive infinity" do - infinity_value().to_s.should == 'Infinity' - end - - it "returns '-Infinity' for negative infinity" do - (-infinity_value()).to_s.should == '-Infinity' - end - - it "returns '0.0' for 0.0" do - 0.0.to_s.should == "0.0" - end - - platform_is_not :openbsd do - it "emits '-' for -0.0" do - -0.0.to_s.should == "-0.0" - end - end - - it "emits a '-' for negative values" do - -3.14.to_s.should == "-3.14" - end - - it "emits a trailing '.0' for a whole number" do - 50.0.to_s.should == "50.0" - end - - it "emits a trailing '.0' for the mantissa in e format" do - 1.0e20.to_s.should == "1.0e+20" - end - - it "uses non-e format for a positive value with fractional part having 5 significant figures" do - 0.0001.to_s.should == "0.0001" - end - - it "uses non-e format for a negative value with fractional part having 5 significant figures" do - -0.0001.to_s.should == "-0.0001" - end - - it "uses e format for a positive value with fractional part having 6 significant figures" do - 0.00001.to_s.should == "1.0e-05" - end - - it "uses e format for a negative value with fractional part having 6 significant figures" do - -0.00001.to_s.should == "-1.0e-05" - end - - it "uses non-e format for a positive value with whole part having 15 significant figures" do - 10000000000000.0.to_s.should == "10000000000000.0" - end - - it "uses non-e format for a negative value with whole part having 15 significant figures" do - -10000000000000.0.to_s.should == "-10000000000000.0" - end - - it "uses non-e format for a positive value with whole part having 16 significant figures" do - 100000000000000.0.to_s.should == "100000000000000.0" - end - - it "uses non-e format for a negative value with whole part having 16 significant figures" do - -100000000000000.0.to_s.should == "-100000000000000.0" - end - - it "uses e format for a positive value with whole part having 18 significant figures" do - 10000000000000000.0.to_s.should == "1.0e+16" - end - - it "uses e format for a negative value with whole part having 18 significant figures" do - -10000000000000000.0.to_s.should == "-1.0e+16" - end - - it "uses e format for a positive value with whole part having 17 significant figures" do - 1000000000000000.0.to_s.should == "1.0e+15" - end - - it "uses e format for a negative value with whole part having 17 significant figures" do - -1000000000000000.0.to_s.should == "-1.0e+15" - end - - # #3273 - it "outputs the minimal, unique form necessary to recreate the value" do - value = 0.21611564636388508 - string = "0.21611564636388508" - - value.to_s.should == string - string.to_f.should == value - end - - it "outputs the minimal, unique form to represent the value" do - 0.56.to_s.should == "0.56" - end - - describe "matches" do - it "random examples in all ranges" do - # 50.times do - # bytes = (0...8).map { rand(256) } - # string = bytes.pack('C8') - # float = string.unpack('D').first - # puts "#{'%.20g' % float}.to_s.should == #{float.to_s.inspect}" - # end - - 2.5540217314354050325e+163.to_s.should == "2.554021731435405e+163" - 2.5492588360356597544e-172.to_s.should == "2.5492588360356598e-172" - 1.742770260934704852e-82.to_s.should == "1.7427702609347049e-82" - 6.2108093676180883209e-104.to_s.should == "6.210809367618088e-104" - -3.3448803488331067402e-143.to_s.should == "-3.3448803488331067e-143" - -2.2740074343500832557e-168.to_s.should == "-2.2740074343500833e-168" - 7.0587971678048535732e+191.to_s.should == "7.058797167804854e+191" - -284438.88327586348169.to_s.should == "-284438.8832758635" - 3.953272468476091301e+105.to_s.should == "3.9532724684760913e+105" - -3.6361359552959847853e+100.to_s.should == "-3.636135955295985e+100" - -1.3222325865575206185e-31.to_s.should == "-1.3222325865575206e-31" - 1.1440138916932761366e+130.to_s.should == "1.1440138916932761e+130" - 4.8750891560387561157e-286.to_s.should == "4.875089156038756e-286" - 5.6101113356591453525e-257.to_s.should == "5.610111335659145e-257" - -3.829644279545809575e-100.to_s.should == "-3.8296442795458096e-100" - 1.5342839401396406117e-194.to_s.should == "1.5342839401396406e-194" - 2.2284972755169921402e-144.to_s.should == "2.228497275516992e-144" - 2.1825655917065601737e-61.to_s.should == "2.1825655917065602e-61" - -2.6672271363524338322e-62.to_s.should == "-2.667227136352434e-62" - -1.9257995160119059415e+21.to_s.should == "-1.925799516011906e+21" - -8.9096732962887121718e-198.to_s.should == "-8.909673296288712e-198" - 2.0202075376548644959e-90.to_s.should == "2.0202075376548645e-90" - -7.7341602581786258961e-266.to_s.should == "-7.734160258178626e-266" - 3.5134482598733635046e+98.to_s.should == "3.5134482598733635e+98" - -2.124411722371029134e+154.to_s.should == "-2.124411722371029e+154" - -4.573908787355718687e+110.to_s.should == "-4.573908787355719e+110" - -1.9344425934170969879e-232.to_s.should == "-1.934442593417097e-232" - -1.3274227399979271095e+171.to_s.should == "-1.3274227399979271e+171" - 9.3495270482104442383e-283.to_s.should == "9.349527048210444e-283" - -4.2046059371986483233e+307.to_s.should == "-4.2046059371986483e+307" - 3.6133547278583543004e-117.to_s.should == "3.613354727858354e-117" - 4.9247416523566613499e-08.to_s.should == "4.9247416523566613e-08" - 1.6936145488250064007e-71.to_s.should == "1.6936145488250064e-71" - 2.4455483206829433098e+96.to_s.should == "2.4455483206829433e+96" - 7.9797449851436455384e+124.to_s.should == "7.979744985143646e+124" - -1.3873689634457876774e-129.to_s.should == "-1.3873689634457877e-129" - 3.9761102037533483075e+284.to_s.should == "3.976110203753348e+284" - -4.2819791952139402486e-303.to_s.should == "-4.28197919521394e-303" - -5.7981017546689831298e-116.to_s.should == "-5.798101754668983e-116" - -3.953266497860534199e-28.to_s.should == "-3.953266497860534e-28" - -2.0659852720290440959e-243.to_s.should == "-2.065985272029044e-243" - 8.9670488995878688018e-05.to_s.should == "8.967048899587869e-05" - -1.2317943708113061768e-98.to_s.should == "-1.2317943708113062e-98" - -3.8930768307633080463e+248.to_s.should == "-3.893076830763308e+248" - 6.5854032671803925627e-239.to_s.should == "6.5854032671803926e-239" - 4.6257022188980878952e+177.to_s.should == "4.625702218898088e+177" - -1.9397155125507235603e-187.to_s.should == "-1.9397155125507236e-187" - 8.5752156951245705056e+117.to_s.should == "8.57521569512457e+117" - -2.4784875958162501671e-132.to_s.should == "-2.4784875958162502e-132" - -4.4125691841230058457e-203.to_s.should == "-4.412569184123006e-203" - end - - it "random examples in human ranges" do - # 50.times do - # formatted = '' - # rand(1..3).times do - # formatted << rand(10).to_s - # end - # formatted << '.' - # rand(1..9).times do - # formatted << rand(10).to_s - # end - # float = formatted.to_f - # puts "#{'%.20f' % float}.to_s.should == #{float.to_s.inspect}" - # end - - 5.17869899999999994122.to_s.should == "5.178699" - 905.62695729999995819526.to_s.should == "905.6269573" - 62.75999999999999801048.to_s.should == "62.76" - 6.93856795800000014651.to_s.should == "6.938567958" - 4.95999999999999996447.to_s.should == "4.96" - 32.77993899999999882766.to_s.should == "32.779939" - 544.12756779999995160324.to_s.should == "544.1275678" - 66.25801119999999855281.to_s.should == "66.2580112" - 7.90000000000000035527.to_s.should == "7.9" - 5.93100000000000004974.to_s.should == "5.931" - 5.21229313600000043749.to_s.should == "5.212293136" - 503.44173809000000119340.to_s.should == "503.44173809" - 79.26000000000000511591.to_s.should == "79.26" - 8.51524999999999998579.to_s.should == "8.51525" - 174.00000000000000000000.to_s.should == "174.0" - 50.39580000000000126192.to_s.should == "50.3958" - 35.28999999999999914735.to_s.should == "35.29" - 5.43136675399999990788.to_s.should == "5.431366754" - 654.07680000000004838512.to_s.should == "654.0768" - 6.07423700000000010846.to_s.should == "6.074237" - 102.25779799999999397642.to_s.should == "102.257798" - 5.08129999999999970584.to_s.should == "5.0813" - 6.00000000000000000000.to_s.should == "6.0" - 8.30000000000000071054.to_s.should == "8.3" - 32.68345999999999662577.to_s.should == "32.68346" - 581.11170000000004165486.to_s.should == "581.1117" - 76.31342999999999676675.to_s.should == "76.31343" - 438.30826000000001840817.to_s.should == "438.30826" - 482.06631994000002805478.to_s.should == "482.06631994" - 55.92721026899999969828.to_s.should == "55.927210269" - 4.00000000000000000000.to_s.should == "4.0" - 55.86693999999999959982.to_s.should == "55.86694" - 787.98299999999994724931.to_s.should == "787.983" - 5.73810511000000023074.to_s.should == "5.73810511" - 74.51926810000000500622.to_s.should == "74.5192681" - 892.89999999999997726263.to_s.should == "892.9" - 68.27299999999999613465.to_s.should == "68.273" - 904.10000000000002273737.to_s.should == "904.1" - 5.23200000000000020606.to_s.should == "5.232" - 4.09628000000000014325.to_s.should == "4.09628" - 46.05152633699999853434.to_s.should == "46.051526337" - 142.12884990599999923688.to_s.should == "142.128849906" - 3.83057023500000015659.to_s.should == "3.830570235" - 11.81684594699999912848.to_s.should == "11.816845947" - 80.50000000000000000000.to_s.should == "80.5" - 382.18215010000000120272.to_s.should == "382.1821501" - 55.38444606899999911320.to_s.should == "55.384446069" - 5.78000000000000024869.to_s.should == "5.78" - 2.88244999999999995666.to_s.should == "2.88245" - 43.27709999999999723741.to_s.should == "43.2771" - end - - it "random values from divisions" do - (1.0 / 7).to_s.should == "0.14285714285714285" - - # 50.times do - # a = rand(10) - # b = rand(10) - # c = rand(10) - # d = rand(10) - # expression = "#{a}.#{b} / #{c}.#{d}" - # puts " (#{expression}).to_s.should == #{eval(expression).to_s.inspect}" - # end - - (1.1 / 7.1).to_s.should == "0.15492957746478875" - (6.5 / 8.8).to_s.should == "0.7386363636363635" - (4.8 / 4.3).to_s.should == "1.1162790697674418" - (4.0 / 1.9).to_s.should == "2.1052631578947367" - (9.1 / 0.8).to_s.should == "11.374999999999998" - (5.3 / 7.5).to_s.should == "0.7066666666666667" - (2.8 / 1.8).to_s.should == "1.5555555555555554" - (2.1 / 2.5).to_s.should == "0.8400000000000001" - (3.5 / 6.0).to_s.should == "0.5833333333333334" - (4.6 / 0.3).to_s.should == "15.333333333333332" - (0.6 / 2.4).to_s.should == "0.25" - (1.3 / 9.1).to_s.should == "0.14285714285714288" - (0.3 / 5.0).to_s.should == "0.06" - (5.0 / 4.2).to_s.should == "1.1904761904761905" - (3.0 / 2.0).to_s.should == "1.5" - (6.3 / 2.0).to_s.should == "3.15" - (5.4 / 6.0).to_s.should == "0.9" - (9.6 / 8.1).to_s.should == "1.1851851851851851" - (8.7 / 1.6).to_s.should == "5.437499999999999" - (1.9 / 7.8).to_s.should == "0.24358974358974358" - (0.5 / 2.1).to_s.should == "0.23809523809523808" - (9.3 / 5.8).to_s.should == "1.6034482758620692" - (2.7 / 8.0).to_s.should == "0.3375" - (9.7 / 7.8).to_s.should == "1.2435897435897436" - (8.1 / 2.4).to_s.should == "3.375" - (7.7 / 2.7).to_s.should == "2.8518518518518516" - (7.9 / 1.7).to_s.should == "4.647058823529412" - (6.5 / 8.2).to_s.should == "0.7926829268292683" - (7.8 / 9.6).to_s.should == "0.8125" - (2.2 / 4.6).to_s.should == "0.47826086956521746" - (0.0 / 1.0).to_s.should == "0.0" - (8.3 / 2.9).to_s.should == "2.8620689655172415" - (3.1 / 6.1).to_s.should == "0.5081967213114754" - (2.8 / 7.8).to_s.should == "0.358974358974359" - (8.0 / 0.1).to_s.should == "80.0" - (1.7 / 6.4).to_s.should == "0.265625" - (1.8 / 5.4).to_s.should == "0.3333333333333333" - (8.0 / 5.8).to_s.should == "1.3793103448275863" - (5.2 / 4.1).to_s.should == "1.2682926829268295" - (9.8 / 5.8).to_s.should == "1.6896551724137934" - (5.4 / 9.5).to_s.should == "0.5684210526315789" - (8.4 / 4.9).to_s.should == "1.7142857142857142" - (1.7 / 3.5).to_s.should == "0.4857142857142857" - (1.2 / 5.1).to_s.should == "0.23529411764705882" - (1.4 / 2.0).to_s.should == "0.7" - (4.8 / 8.0).to_s.should == "0.6" - (9.0 / 2.5).to_s.should == "3.6" - (0.2 / 0.6).to_s.should == "0.33333333333333337" - (7.8 / 5.2).to_s.should == "1.5" - (9.5 / 5.5).to_s.should == "1.7272727272727273" - end - end -end - -describe "Float#to_s" do - before :each do - @internal = Encoding.default_internal - end - - after :each do - Encoding.default_internal = @internal - end - - it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do - Encoding.default_internal = nil - 1.23.to_s.encoding.should equal(Encoding::US_ASCII) - end - - it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do - Encoding.default_internal = Encoding::IBM437 - 5.47.to_s.encoding.should equal(Encoding::US_ASCII) - end + it_behaves_like :float_to_s, :to_s end diff --git a/ruby/spec/ruby/core/float/uminus_spec.rb b/ruby/spec/ruby/core/float/uminus_spec.rb index e676a26ad..57bae0fb4 100644 --- a/ruby/spec/ruby/core/float/uminus_spec.rb +++ b/ruby/spec/ruby/core/float/uminus_spec.rb @@ -23,6 +23,6 @@ end it "returns NaN for NaN" do - nan_value.send(:-@).nan?.should == true + nan_value.send(:-@).should.nan? end end diff --git a/ruby/spec/ruby/core/float/zero_spec.rb b/ruby/spec/ruby/core/float/zero_spec.rb index e70edc422..1f3de2779 100644 --- a/ruby/spec/ruby/core/float/zero_spec.rb +++ b/ruby/spec/ruby/core/float/zero_spec.rb @@ -2,8 +2,8 @@ describe "Float#zero?" do it "returns true if self is 0.0" do - 0.0.zero?.should == true - 1.0.zero?.should == false - -1.0.zero?.should == false + 0.0.should.zero? + 1.0.should_not.zero? + -1.0.should_not.zero? end end diff --git a/ruby/spec/ruby/core/gc/auto_compact_spec.rb b/ruby/spec/ruby/core/gc/auto_compact_spec.rb new file mode 100644 index 000000000..4f9d04317 --- /dev/null +++ b/ruby/spec/ruby/core/gc/auto_compact_spec.rb @@ -0,0 +1,26 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.0" do + describe "GC.auto_compact" do + it "can set and get a boolean value" do + begin + GC.auto_compact = GC.auto_compact + rescue NotImplementedError # platform does not support autocompact + skip + end + + original = GC.auto_compact + begin + GC.auto_compact = !original + rescue NotImplementedError # platform does not support autocompact + skip + end + + begin + GC.auto_compact.should == !original + ensure + GC.auto_compact = original + end + end + end +end diff --git a/ruby/spec/ruby/core/gc/disable_spec.rb b/ruby/spec/ruby/core/gc/disable_spec.rb index b0221d852..f89a9d276 100644 --- a/ruby/spec/ruby/core/gc/disable_spec.rb +++ b/ruby/spec/ruby/core/gc/disable_spec.rb @@ -5,7 +5,7 @@ GC.enable end - it "returns true iff the garbage collection was previously disabled" do + it "returns true if and only if the garbage collection was previously disabled" do GC.enable GC.disable.should == false GC.disable.should == true diff --git a/ruby/spec/ruby/core/gc/enable_spec.rb b/ruby/spec/ruby/core/gc/enable_spec.rb index eb8d572f4..ca4488547 100644 --- a/ruby/spec/ruby/core/gc/enable_spec.rb +++ b/ruby/spec/ruby/core/gc/enable_spec.rb @@ -2,7 +2,7 @@ describe "GC.enable" do - it "returns true iff the garbage collection was already disabled" do + it "returns true if and only if the garbage collection was already disabled" do GC.enable GC.enable.should == false GC.disable diff --git a/ruby/spec/ruby/core/gc/measure_total_time_spec.rb b/ruby/spec/ruby/core/gc/measure_total_time_spec.rb new file mode 100644 index 000000000..05d4598eb --- /dev/null +++ b/ruby/spec/ruby/core/gc/measure_total_time_spec.rb @@ -0,0 +1,19 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "GC.measure_total_time" do + before :each do + @default = GC.measure_total_time + end + + after :each do + GC.measure_total_time = @default + end + + it "can set and get a boolean value" do + original = GC.measure_total_time + GC.measure_total_time = !original + GC.measure_total_time.should == !original + end + end +end diff --git a/ruby/spec/ruby/core/gc/profiler/disable_spec.rb b/ruby/spec/ruby/core/gc/profiler/disable_spec.rb index 321a207de..74089693e 100644 --- a/ruby/spec/ruby/core/gc/profiler/disable_spec.rb +++ b/ruby/spec/ruby/core/gc/profiler/disable_spec.rb @@ -11,6 +11,6 @@ it "disables the profiler" do GC::Profiler.disable - GC::Profiler.enabled?.should == false + GC::Profiler.should_not.enabled? end end diff --git a/ruby/spec/ruby/core/gc/profiler/enable_spec.rb b/ruby/spec/ruby/core/gc/profiler/enable_spec.rb index 159451167..313ca3d94 100644 --- a/ruby/spec/ruby/core/gc/profiler/enable_spec.rb +++ b/ruby/spec/ruby/core/gc/profiler/enable_spec.rb @@ -12,6 +12,6 @@ it "enables the profiler" do GC::Profiler.enable - GC::Profiler.enabled?.should == true + GC::Profiler.should.enabled? end end diff --git a/ruby/spec/ruby/core/gc/start_spec.rb b/ruby/spec/ruby/core/gc/start_spec.rb index fb6820db1..c94105896 100644 --- a/ruby/spec/ruby/core/gc/start_spec.rb +++ b/ruby/spec/ruby/core/gc/start_spec.rb @@ -5,4 +5,8 @@ GC.start.should == nil GC.start.should == nil end + + it "accepts keyword arguments" do + GC.start(full_mark: true, immediate_sweep: true).should == nil + end end diff --git a/ruby/spec/ruby/core/gc/stat_spec.rb b/ruby/spec/ruby/core/gc/stat_spec.rb index 51bd00c7c..3b43b28a9 100644 --- a/ruby/spec/ruby/core/gc/stat_spec.rb +++ b/ruby/spec/ruby/core/gc/stat_spec.rb @@ -1,16 +1,62 @@ require_relative '../../spec_helper' describe "GC.stat" do - it "supports access by key" do - keys = [:heap_free_slots, :total_allocated_objects, :count] - keys.each do |key| - GC.stat(key).should be_kind_of(Integer) - end - end - it "returns hash of values" do stat = GC.stat stat.should be_kind_of(Hash) - stat.keys.should include(:count) + stat.keys.should.include?(:count) + end + + it "updates the given hash values" do + hash = { count: "hello", __other__: "world" } + stat = GC.stat(hash) + + stat.should be_kind_of(Hash) + stat.should equal hash + stat[:count].should be_kind_of(Integer) + stat[:__other__].should == "world" + end + + it "the values are all Integer since rb_gc_stat() returns size_t" do + GC.stat.values.each { |value| value.should be_kind_of(Integer) } + end + + it "can return a single value" do + GC.stat(:count).should be_kind_of(Integer) + end + + it "increases count after GC is run" do + count = GC.stat(:count) + GC.start + GC.stat(:count).should > count + end + + it "increases major_gc_count after GC is run" do + count = GC.stat(:major_gc_count) + GC.start + GC.stat(:major_gc_count).should > count + end + + it "provides some number for count" do + GC.stat(:count).should be_kind_of(Integer) + GC.stat[:count].should be_kind_of(Integer) + end + + it "provides some number for heap_free_slots" do + GC.stat(:heap_free_slots).should be_kind_of(Integer) + GC.stat[:heap_free_slots].should be_kind_of(Integer) + end + + it "provides some number for total_allocated_objects" do + GC.stat(:total_allocated_objects).should be_kind_of(Integer) + GC.stat[:total_allocated_objects].should be_kind_of(Integer) + end + + it "raises an error if argument is not nil, a symbol, or a hash" do + -> { GC.stat(7) }.should raise_error(TypeError, "non-hash or symbol given") + end + + it "raises an error if an unknown key is given" do + -> { GC.stat(:foo) }.should raise_error(ArgumentError, "unknown key: foo") end end diff --git a/ruby/spec/ruby/core/gc/total_time_spec.rb b/ruby/spec/ruby/core/gc/total_time_spec.rb new file mode 100644 index 000000000..fcc8f45a8 --- /dev/null +++ b/ruby/spec/ruby/core/gc/total_time_spec.rb @@ -0,0 +1,15 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "GC.total_time" do + it "returns an Integer" do + GC.total_time.should be_kind_of(Integer) + end + + it "increases as collections are run" do + time_before = GC.total_time + GC.start + GC.total_time.should >= time_before + end + end +end diff --git a/ruby/spec/ruby/core/hash/any_spec.rb b/ruby/spec/ruby/core/hash/any_spec.rb index bd33e8cd8..c26dfabde 100644 --- a/ruby/spec/ruby/core/hash/any_spec.rb +++ b/ruby/spec/ruby/core/hash/any_spec.rb @@ -4,10 +4,10 @@ describe 'with no block given' do it "checks if there are any members of a Hash" do empty_hash = {} - empty_hash.any?.should == false + empty_hash.should_not.any? hash_with_members = { 'key' => 'value' } - hash_with_members.any?.should == true + hash_with_members.should.any? end end diff --git a/ruby/spec/ruby/core/hash/clear_spec.rb b/ruby/spec/ruby/core/hash/clear_spec.rb index e7816acbb..cf05e36ac 100644 --- a/ruby/spec/ruby/core/hash/clear_spec.rb +++ b/ruby/spec/ruby/core/hash/clear_spec.rb @@ -25,8 +25,8 @@ h.default_proc.should_not == nil end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.clear }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.clear }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.clear }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.clear }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/compact_spec.rb b/ruby/spec/ruby/core/hash/compact_spec.rb index ec9d4b5d7..2989afc8b 100644 --- a/ruby/spec/ruby/core/hash/compact_spec.rb +++ b/ruby/spec/ruby/core/hash/compact_spec.rb @@ -51,8 +51,8 @@ @hash.freeze end - it "keeps pairs and raises a #{frozen_error_class}" do - ->{ @hash.compact! }.should raise_error(frozen_error_class) + it "keeps pairs and raises a FrozenError" do + ->{ @hash.compact! }.should raise_error(FrozenError) @hash.should == @initial_pairs end end diff --git a/ruby/spec/ruby/core/hash/compare_by_identity_spec.rb b/ruby/spec/ruby/core/hash/compare_by_identity_spec.rb index 0658b4954..874cd46eb 100644 --- a/ruby/spec/ruby/core/hash/compare_by_identity_spec.rb +++ b/ruby/spec/ruby/core/hash/compare_by_identity_spec.rb @@ -33,7 +33,7 @@ def o.hash; 123; end it "has no effect on an already compare_by_identity hash" do @idh[:foo] = :bar @idh.compare_by_identity.should equal @idh - @idh.compare_by_identity?.should == true + @idh.should.compare_by_identity? @idh[:foo].should == :bar end @@ -80,9 +80,9 @@ def o.hash; 123; end @h[o].should == :o end - it "raises a #{frozen_error_class} on frozen hashes" do + it "raises a FrozenError on frozen hashes" do @h = @h.freeze - -> { @h.compare_by_identity }.should raise_error(frozen_error_class) + -> { @h.compare_by_identity }.should raise_error(FrozenError) end # Behaviour confirmed in bug #1871 diff --git a/ruby/spec/ruby/core/hash/deconstruct_keys_spec.rb b/ruby/spec/ruby/core/hash/deconstruct_keys_spec.rb new file mode 100644 index 000000000..b26573261 --- /dev/null +++ b/ruby/spec/ruby/core/hash/deconstruct_keys_spec.rb @@ -0,0 +1,25 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Hash#deconstruct_keys" do + it "returns self" do + hash = {a: 1, b: 2} + + hash.deconstruct_keys([:a, :b]).should equal hash + end + + it "requires one argument" do + -> { + {a: 1}.deconstruct_keys + }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/) + end + + it "ignores argument" do + hash = {a: 1, b: 2} + + hash.deconstruct_keys([:a]).should == {a: 1, b: 2} + hash.deconstruct_keys(0 ).should == {a: 1, b: 2} + hash.deconstruct_keys('' ).should == {a: 1, b: 2} + end + end +end diff --git a/ruby/spec/ruby/core/hash/default_proc_spec.rb b/ruby/spec/ruby/core/hash/default_proc_spec.rb index 83ad98e5b..f4e480363 100644 --- a/ruby/spec/ruby/core/hash/default_proc_spec.rb +++ b/ruby/spec/ruby/core/hash/default_proc_spec.rb @@ -73,8 +73,8 @@ end.should raise_error(TypeError) end - it "raises a #{frozen_error_class} if self is frozen" do - -> { {}.freeze.default_proc = Proc.new {} }.should raise_error(frozen_error_class) - -> { {}.freeze.default_proc = nil }.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { {}.freeze.default_proc = Proc.new {} }.should raise_error(FrozenError) + -> { {}.freeze.default_proc = nil }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/default_spec.rb b/ruby/spec/ruby/core/hash/default_spec.rb index 6cad65bb6..d8b62ea19 100644 --- a/ruby/spec/ruby/core/hash/default_spec.rb +++ b/ruby/spec/ruby/core/hash/default_spec.rb @@ -39,8 +39,8 @@ end end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.default = nil }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.default = nil }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.default = nil }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.default = nil }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/delete_if_spec.rb b/ruby/spec/ruby/core/hash/delete_if_spec.rb index 345a24a72..c9e670ffc 100644 --- a/ruby/spec/ruby/core/hash/delete_if_spec.rb +++ b/ruby/spec/ruby/core/hash/delete_if_spec.rb @@ -34,9 +34,9 @@ each_pairs.should == delete_pairs end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.delete_if { false } }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.delete_if { false } }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should raise_error(FrozenError) end it_behaves_like :hash_iteration_no_block, :delete_if diff --git a/ruby/spec/ruby/core/hash/delete_spec.rb b/ruby/spec/ruby/core/hash/delete_spec.rb index a69815c1d..b262e8846 100644 --- a/ruby/spec/ruby/core/hash/delete_spec.rb +++ b/ruby/spec/ruby/core/hash/delete_spec.rb @@ -37,8 +37,8 @@ { key => 5 }.delete(key).should == 5 end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.delete("foo") }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.delete("foo") }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/element_reference_spec.rb b/ruby/spec/ruby/core/hash/element_reference_spec.rb index 2eb65d378..e271f37ea 100644 --- a/ruby/spec/ruby/core/hash/element_reference_spec.rb +++ b/ruby/spec/ruby/core/hash/element_reference_spec.rb @@ -117,4 +117,18 @@ key = HashSpecs::KeyWithPrivateHash.new { key => 42 }[key].should == 42 end + + it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do + code = <<-EOC + load '#{fixture __FILE__, "name.rb"}' + hash = { true => 42, false => 42, 1 => 42, 2.0 => 42, "hello" => 42, :ok => 42 } + [true, false, 1, 2.0, "hello", :ok].each do |value| + raise "incorrect value" unless hash[value] == 42 + end + puts "Ok." + EOC + result = ruby_exe(code, args: "2>&1") + result.should == "Ok.\n" + end + end diff --git a/ruby/spec/ruby/core/hash/empty_spec.rb b/ruby/spec/ruby/core/hash/empty_spec.rb index e9be44bab..881e1cc34 100644 --- a/ruby/spec/ruby/core/hash/empty_spec.rb +++ b/ruby/spec/ruby/core/hash/empty_spec.rb @@ -3,13 +3,13 @@ describe "Hash#empty?" do it "returns true if the hash has no entries" do - {}.empty?.should == true - { 1 => 1 }.empty?.should == false + {}.should.empty? + { 1 => 1 }.should_not.empty? end it "returns true if the hash has no entries and has a default value" do - Hash.new(5).empty?.should == true - Hash.new { 5 }.empty?.should == true - Hash.new { |hsh, k| hsh[k] = k }.empty?.should == true + Hash.new(5).should.empty? + Hash.new { 5 }.should.empty? + Hash.new { |hsh, k| hsh[k] = k }.should.empty? end end diff --git a/ruby/spec/ruby/core/hash/except_spec.rb b/ruby/spec/ruby/core/hash/except_spec.rb new file mode 100644 index 000000000..82cfced72 --- /dev/null +++ b/ruby/spec/ruby/core/hash/except_spec.rb @@ -0,0 +1,34 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.0" do + describe "Hash#except" do + before :each do + @hash = { a: 1, b: 2, c: 3 } + end + + it "returns a new duplicate hash without arguments" do + ret = @hash.except + ret.should_not equal(@hash) + ret.should == @hash + end + + it "returns a hash without the requested subset" do + @hash.except(:c, :a).should == { b: 2 } + end + + it "ignores keys not present in the original hash" do + @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 } + end + + it "always returns a Hash without a default" do + klass = Class.new(Hash) + h = klass.new(:default) + h[:bar] = 12 + h[:foo] = 42 + r = h.except(:foo) + r.should == {bar: 12} + r.class.should == Hash + r.default.should == nil + end + end +end diff --git a/ruby/spec/ruby/core/hash/filter_spec.rb b/ruby/spec/ruby/core/hash/filter_spec.rb index 4382c94e6..7dabe4498 100644 --- a/ruby/spec/ruby/core/hash/filter_spec.rb +++ b/ruby/spec/ruby/core/hash/filter_spec.rb @@ -1,12 +1,10 @@ require_relative '../../spec_helper' require_relative 'shared/select' -ruby_version_is "2.6" do - describe "Hash#filter" do - it_behaves_like :hash_select, :filter - end +describe "Hash#filter" do + it_behaves_like :hash_select, :filter +end - describe "Hash#filter!" do - it_behaves_like :hash_select!, :filter! - end +describe "Hash#filter!" do + it_behaves_like :hash_select!, :filter! end diff --git a/ruby/spec/ruby/core/hash/fixtures/name.rb b/ruby/spec/ruby/core/hash/fixtures/name.rb new file mode 100644 index 000000000..b203bf6ae --- /dev/null +++ b/ruby/spec/ruby/core/hash/fixtures/name.rb @@ -0,0 +1,30 @@ +class TrueClass + def hash + raise "TrueClass#hash should not be called" + end +end +class FalseClass + def hash + raise "FalseClass#hash should not be called" + end +end +class Integer + def hash + raise "Integer#hash should not be called" + end +end +class Float + def hash + raise "Float#hash should not be called" + end +end +class String + def hash + raise "String#hash should not be called" + end +end +class Symbol + def hash + raise "Symbol#hash should not be called" + end +end diff --git a/ruby/spec/ruby/core/hash/index_spec.rb b/ruby/spec/ruby/core/hash/index_spec.rb index 2b52c6994..be4e2cc6a 100644 --- a/ruby/spec/ruby/core/hash/index_spec.rb +++ b/ruby/spec/ruby/core/hash/index_spec.rb @@ -2,6 +2,8 @@ require_relative 'fixtures/classes' require_relative 'shared/index' -describe "Hash#index" do - it_behaves_like :hash_index, :index +ruby_version_is ''...'3.0' do + describe "Hash#index" do + it_behaves_like :hash_index, :index + end end diff --git a/ruby/spec/ruby/core/hash/initialize_spec.rb b/ruby/spec/ruby/core/hash/initialize_spec.rb index 00e1174ec..d13496ba3 100644 --- a/ruby/spec/ruby/core/hash/initialize_spec.rb +++ b/ruby/spec/ruby/core/hash/initialize_spec.rb @@ -45,17 +45,17 @@ h.send(:initialize).should equal(h) end - it "raises a #{frozen_error_class} if called on a frozen instance" do + it "raises a FrozenError if called on a frozen instance" do block = -> { HashSpecs.frozen_hash.instance_eval { initialize() }} - block.should raise_error(frozen_error_class) + block.should raise_error(FrozenError) block = -> { HashSpecs.frozen_hash.instance_eval { initialize(nil) } } - block.should raise_error(frozen_error_class) + block.should raise_error(FrozenError) block = -> { HashSpecs.frozen_hash.instance_eval { initialize(5) } } - block.should raise_error(frozen_error_class) + block.should raise_error(FrozenError) block = -> { HashSpecs.frozen_hash.instance_eval { initialize { 5 } } } - block.should raise_error(frozen_error_class) + block.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/keep_if_spec.rb b/ruby/spec/ruby/core/hash/keep_if_spec.rb index 278eafc96..d50d96946 100644 --- a/ruby/spec/ruby/core/hash/keep_if_spec.rb +++ b/ruby/spec/ruby/core/hash/keep_if_spec.rb @@ -27,9 +27,9 @@ h.keep_if { true }.should equal(h) end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.keep_if { true } }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.keep_if { true } }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should raise_error(FrozenError) end it_behaves_like :hash_iteration_no_block, :keep_if diff --git a/ruby/spec/ruby/core/hash/merge_spec.rb b/ruby/spec/ruby/core/hash/merge_spec.rb index 91ded30eb..552186429 100644 --- a/ruby/spec/ruby/core/hash/merge_spec.rb +++ b/ruby/spec/ruby/core/hash/merge_spec.rb @@ -81,19 +81,17 @@ merge_pairs.should == expected_pairs end - ruby_version_is "2.6" do - it "accepts multiple hashes" do - result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 }) - result.should == { a: 1, b: 2, c: 3, d: 4 } - end - - it "accepts zero arguments and returns a copy of self" do - hash = { a: 1 } - merged = hash.merge - - merged.should eql(hash) - merged.should_not equal(hash) - end + it "accepts multiple hashes" do + result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 }) + result.should == { a: 1, b: 2, c: 3, d: 4 } + end + + it "accepts zero arguments and returns a copy of self" do + hash = { a: 1 } + merged = hash.merge + + merged.should eql(hash) + merged.should_not equal(hash) end end diff --git a/ruby/spec/ruby/core/hash/rehash_spec.rb b/ruby/spec/ruby/core/hash/rehash_spec.rb index 587935fc4..004908045 100644 --- a/ruby/spec/ruby/core/hash/rehash_spec.rb +++ b/ruby/spec/ruby/core/hash/rehash_spec.rb @@ -59,8 +59,26 @@ def k1.hash; 1; end h.keys.should == [a] end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.rehash }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.rehash }.should raise_error(frozen_error_class) + it "removes duplicate keys for large hashes" do + a = [1,2] + b = [1] + + h = {} + h[a] = true + h[b] = true + 100.times { |n| h[n] = true } + b << 2 + h.size.should == 102 + h.keys.should.include? a + h.keys.should.include? b + h.rehash + h.size.should == 101 + h.keys.should.include? a + h.keys.should_not.include? [1] + end + + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.rehash }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.rehash }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/reject_spec.rb b/ruby/spec/ruby/core/hash/reject_spec.rb index 1051ebd76..397000ab6 100644 --- a/ruby/spec/ruby/core/hash/reject_spec.rb +++ b/ruby/spec/ruby/core/hash/reject_spec.rb @@ -35,7 +35,7 @@ def h.to_a() end ruby_version_is ''...'2.7' do it "does not taint the resulting hash" do h = { a: 1 }.taint - h.reject {false}.tainted?.should == false + h.reject {false}.should_not.tainted? end end end @@ -89,12 +89,12 @@ def h.to_a() end reject_bang_pairs.should == delete_if_pairs end - it "raises a #{frozen_error_class} if called on a frozen instance that is modified" do - -> { HashSpecs.empty_frozen_hash.reject! { true } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance that is modified" do + -> { HashSpecs.empty_frozen_hash.reject! { true } }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do - -> { HashSpecs.frozen_hash.reject! { false } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance that would not be modified" do + -> { HashSpecs.frozen_hash.reject! { false } }.should raise_error(FrozenError) end it_behaves_like :hash_iteration_no_block, :reject! diff --git a/ruby/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb b/ruby/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb new file mode 100644 index 000000000..005886a48 --- /dev/null +++ b/ruby/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb @@ -0,0 +1,47 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "2.7" do + describe "Hash.ruby2_keywords_hash?" do + it "returns false if the Hash is not a keywords Hash" do + Hash.ruby2_keywords_hash?({}).should == false + end + + it "returns true if the Hash is a keywords Hash marked by Module#ruby2_keywords" do + obj = Class.new { + ruby2_keywords def m(*args) + args.last + end + }.new + Hash.ruby2_keywords_hash?(obj.m(a: 1)).should == true + end + + it "raises TypeError for non-Hash" do + -> { Hash.ruby2_keywords_hash?(nil) }.should raise_error(TypeError) + end + end + + describe "Hash.ruby2_keywords_hash" do + it "returns a copy of a Hash and marks the copy as a keywords Hash" do + h = {a: 1}.freeze + kw = Hash.ruby2_keywords_hash(h) + Hash.ruby2_keywords_hash?(h).should == false + Hash.ruby2_keywords_hash?(kw).should == true + kw.should == h + end + + it "returns an instance of the subclass if called on an instance of a subclass of Hash" do + h = HashSpecs::MyHash.new + h[:a] = 1 + kw = Hash.ruby2_keywords_hash(h) + kw.class.should == HashSpecs::MyHash + Hash.ruby2_keywords_hash?(h).should == false + Hash.ruby2_keywords_hash?(kw).should == true + kw.should == h + end + + it "raises TypeError for non-Hash" do + -> { Hash.ruby2_keywords_hash(nil) }.should raise_error(TypeError) + end + end +end diff --git a/ruby/spec/ruby/core/hash/shared/each.rb b/ruby/spec/ruby/core/hash/shared/each.rb index d1f2e5f67..b2483c811 100644 --- a/ruby/spec/ruby/core/hash/shared/each.rb +++ b/ruby/spec/ruby/core/hash/shared/each.rb @@ -21,19 +21,58 @@ ary.sort.should == ["a", "b", "c"] end - it "yields 2 values and not an Array of 2 elements when given a callable of arity 2" do + ruby_version_is ""..."3.0" do + it "yields 2 values and not an Array of 2 elements when given a callable of arity 2" do + obj = Object.new + def obj.foo(key, value) + ScratchPad << key << value + end + + ScratchPad.record([]) + { "a" => 1 }.send(@method, &obj.method(:foo)) + ScratchPad.recorded.should == ["a", 1] + + ScratchPad.record([]) + { "a" => 1 }.send(@method, &-> key, value { ScratchPad << key << value }) + ScratchPad.recorded.should == ["a", 1] + end + end + + ruby_version_is "3.0" do + it "always yields an Array of 2 elements, even when given a callable of arity 2" do + obj = Object.new + def obj.foo(key, value) + end + + -> { + { "a" => 1 }.send(@method, &obj.method(:foo)) + }.should raise_error(ArgumentError) + + -> { + { "a" => 1 }.send(@method, &-> key, value { }) + }.should raise_error(ArgumentError) + end + end + + it "yields an Array of 2 elements when given a callable of arity 1" do obj = Object.new - def obj.foo(key, value) - ScratchPad << key << value + def obj.foo(key_value) + ScratchPad << key_value end ScratchPad.record([]) { "a" => 1 }.send(@method, &obj.method(:foo)) - ScratchPad.recorded.should == ["a", 1] + ScratchPad.recorded.should == [["a", 1]] + end - ScratchPad.record([]) - { "a" => 1 }.send(@method, &-> key, value { ScratchPad << key << value }) - ScratchPad.recorded.should == ["a", 1] + it "raises an error for a Hash when an arity enforcing callable of arity >2 is passed in" do + obj = Object.new + def obj.foo(key, value, extra) + end + + -> { + { "a" => 1 }.send(@method, &obj.method(:foo)) + }.should raise_error(ArgumentError) end it "uses the same order as keys() and values()" do diff --git a/ruby/spec/ruby/core/hash/shared/eql.rb b/ruby/spec/ruby/core/hash/shared/eql.rb index d8c33179f..e294edd76 100644 --- a/ruby/spec/ruby/core/hash/shared/eql.rb +++ b/ruby/spec/ruby/core/hash/shared/eql.rb @@ -118,7 +118,7 @@ def y.eql?(o) true end { 1.0 => "x" }.send(@method, { 1 => "x" }).should be_false end - it "returns true iff other Hash has the same number of keys and each key-value pair matches" do + it "returns true if and only if other Hash has the same number of keys and each key-value pair matches" do a = { a: 5 } b = {} a.send(@method, b).should be_false diff --git a/ruby/spec/ruby/core/hash/shared/index.rb b/ruby/spec/ruby/core/hash/shared/index.rb index 4858ba85f..7f6a18646 100644 --- a/ruby/spec/ruby/core/hash/shared/index.rb +++ b/ruby/spec/ruby/core/hash/shared/index.rb @@ -3,25 +3,35 @@ describe :hash_index, shared: true do it "returns the corresponding key for value" do - { 2 => 'a', 1 => 'b' }.send(@method, 'b').should == 1 + suppress_warning do # for Hash#index + { 2 => 'a', 1 => 'b' }.send(@method, 'b').should == 1 + end end it "returns nil if the value is not found" do - { a: -1, b: 3.14, c: 2.718 }.send(@method, 1).should be_nil + suppress_warning do # for Hash#index + { a: -1, b: 3.14, c: 2.718 }.send(@method, 1).should be_nil + end end it "doesn't return default value if the value is not found" do - Hash.new(5).send(@method, 5).should be_nil + suppress_warning do # for Hash#index + Hash.new(5).send(@method, 5).should be_nil + end end it "compares values using ==" do - { 1 => 0 }.send(@method, 0.0).should == 1 - { 1 => 0.0 }.send(@method, 0).should == 1 + suppress_warning do # for Hash#index + { 1 => 0 }.send(@method, 0.0).should == 1 + { 1 => 0.0 }.send(@method, 0).should == 1 + end needle = mock('needle') inhash = mock('inhash') inhash.should_receive(:==).with(needle).and_return(true) - { 1 => inhash }.send(@method, needle).should == 1 + suppress_warning do # for Hash#index + { 1 => inhash }.send(@method, needle).should == 1 + end end end diff --git a/ruby/spec/ruby/core/hash/shared/replace.rb b/ruby/spec/ruby/core/hash/shared/replace.rb index b3d098763..bea64384b 100644 --- a/ruby/spec/ruby/core/hash/shared/replace.rb +++ b/ruby/spec/ruby/core/hash/shared/replace.rb @@ -37,15 +37,15 @@ hash_a.default.should == hash_b.default end - it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do + it "raises a FrozenError if called on a frozen instance that would not be modified" do -> do HashSpecs.frozen_hash.send(@method, HashSpecs.frozen_hash) - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} if called on a frozen instance that is modified" do + it "raises a FrozenError if called on a frozen instance that is modified" do -> do HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash) - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/hash/shared/select.rb b/ruby/spec/ruby/core/hash/shared/select.rb index bb781817c..5170af50d 100644 --- a/ruby/spec/ruby/core/hash/shared/select.rb +++ b/ruby/spec/ruby/core/hash/shared/select.rb @@ -74,12 +74,12 @@ { a: 1 }.send(@method) { |k,v| v <= 1 }.should == nil end - it "raises a #{frozen_error_class} if called on an empty frozen instance" do - -> { HashSpecs.empty_frozen_hash.send(@method) { false } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on an empty frozen instance" do + -> { HashSpecs.empty_frozen_hash.send(@method) { false } }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do - -> { HashSpecs.frozen_hash.send(@method) { true } }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance that would not be modified" do + -> { HashSpecs.frozen_hash.send(@method) { true } }.should raise_error(FrozenError) end it_should_behave_like :hash_iteration_no_block diff --git a/ruby/spec/ruby/core/hash/shared/store.rb b/ruby/spec/ruby/core/hash/shared/store.rb index ff40bef3e..b823ea45c 100644 --- a/ruby/spec/ruby/core/hash/shared/store.rb +++ b/ruby/spec/ruby/core/hash/shared/store.rb @@ -36,7 +36,7 @@ def key.reverse() "bar" end h[key].should == "foo" end - it " accepts keys with a Bignum hash" do + it " accepts keys with an Integer hash" do o = mock(hash: 1 << 100) h = {} h[o] = 1 @@ -50,7 +50,7 @@ def key.reverse() "bar" end key << "bar" h.should == { "foo" => 0 } - h.keys[0].frozen?.should == true + h.keys[0].should.frozen? end it "doesn't duplicate and freeze already frozen string keys" do @@ -86,8 +86,8 @@ def key.reverse() "bar" end h.keys.last.should_not equal(key2) end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.send(@method, 1, 2) }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.send(@method, 1, 2) }.should raise_error(FrozenError) end it "does not raise an exception if changing the value of an existing key during iteration" do @@ -95,4 +95,21 @@ def key.reverse() "bar" end hash.each { hash.send(@method, 1, :foo) } hash.should == {1 => :foo, 3 => 4, 5 => 6} end + + it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do + code = <<-EOC + load '#{fixture __FILE__, "name.rb"}' + hash = {} + [true, false, 1, 2.0, "hello", :ok].each do |value| + hash[value] = 42 + raise "incorrect value" unless hash[value] == 42 + hash[value] = 43 + raise "incorrect value" unless hash[value] == 43 + end + puts "OK" + puts hash.size + EOC + result = ruby_exe(code, args: "2>&1") + result.should == "OK\n6\n" + end end diff --git a/ruby/spec/ruby/core/hash/shared/update.rb b/ruby/spec/ruby/core/hash/shared/update.rb index 3af41c450..1b0eb809b 100644 --- a/ruby/spec/ruby/core/hash/shared/update.rb +++ b/ruby/spec/ruby/core/hash/shared/update.rb @@ -34,10 +34,10 @@ merge_bang_pairs.should == merge_pairs end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do + it "raises a FrozenError on a frozen instance that is modified" do -> do HashSpecs.frozen_hash.send(@method, 1 => 2) - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) end it "checks frozen status before coercing an object with #to_hash" do @@ -47,14 +47,14 @@ def obj.to_hash() raise Exception, "should not receive #to_hash" end obj.freeze - -> { HashSpecs.frozen_hash.send(@method, obj) }.should raise_error(frozen_error_class) + -> { HashSpecs.frozen_hash.send(@method, obj) }.should raise_error(FrozenError) end # see redmine #1571 - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do + it "raises a FrozenError on a frozen instance that would not be modified" do -> do HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash) - end.should raise_error(frozen_error_class) + end.should raise_error(FrozenError) end it "does not raise an exception if changing the value of an existing key during iteration" do @@ -64,15 +64,13 @@ def obj.to_hash() raise Exception, "should not receive #to_hash" end hash.should == {1 => :foo, 3 => :bar, 5 => 6} end - ruby_version_is "2.6" do - it "accepts multiple hashes" do - result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 }) - result.should == { a: 1, b: 2, c: 3, d: 4 } - end + it "accepts multiple hashes" do + result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 }) + result.should == { a: 1, b: 2, c: 3, d: 4 } + end - it "accepts zero arguments" do - hash = { a: 1 } - hash.send(@method).should eql(hash) - end + it "accepts zero arguments" do + hash = { a: 1 } + hash.send(@method).should eql(hash) end end diff --git a/ruby/spec/ruby/core/hash/shift_spec.rb b/ruby/spec/ruby/core/hash/shift_spec.rb index d9f121e38..9d43e640f 100644 --- a/ruby/spec/ruby/core/hash/shift_spec.rb +++ b/ruby/spec/ruby/core/hash/shift_spec.rb @@ -57,9 +57,9 @@ def h.default(key) h.should == {:c => 3} end - it "raises a #{frozen_error_class} if called on a frozen instance" do - -> { HashSpecs.frozen_hash.shift }.should raise_error(frozen_error_class) - -> { HashSpecs.empty_frozen_hash.shift }.should raise_error(frozen_error_class) + it "raises a FrozenError if called on a frozen instance" do + -> { HashSpecs.frozen_hash.shift }.should raise_error(FrozenError) + -> { HashSpecs.empty_frozen_hash.shift }.should raise_error(FrozenError) end it "works when the hash is at capacity" do diff --git a/ruby/spec/ruby/core/hash/slice_spec.rb b/ruby/spec/ruby/core/hash/slice_spec.rb index f7717c940..e3046d83d 100644 --- a/ruby/spec/ruby/core/hash/slice_spec.rb +++ b/ruby/spec/ruby/core/hash/slice_spec.rb @@ -1,55 +1,53 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "Hash#slice" do - before :each do - @hash = { a: 1, b: 2, c: 3 } - end +describe "Hash#slice" do + before :each do + @hash = { a: 1, b: 2, c: 3 } + end - it "returns a new empty hash without arguments" do - ret = @hash.slice - ret.should_not equal(@hash) - ret.should be_an_instance_of(Hash) - ret.should == {} - end + it "returns a new empty hash without arguments" do + ret = @hash.slice + ret.should_not equal(@hash) + ret.should be_an_instance_of(Hash) + ret.should == {} + end - it "returns the requested subset" do - @hash.slice(:c, :a).should == { c: 3, a: 1 } - end + it "returns the requested subset" do + @hash.slice(:c, :a).should == { c: 3, a: 1 } + end - it "returns a hash ordered in the order of the requested keys" do - @hash.slice(:c, :a).keys.should == [:c, :a] - end + it "returns a hash ordered in the order of the requested keys" do + @hash.slice(:c, :a).keys.should == [:c, :a] + end - it "returns only the keys of the original hash" do - @hash.slice(:a, :chunky_bacon).should == { a: 1 } - end + it "returns only the keys of the original hash" do + @hash.slice(:a, :chunky_bacon).should == { a: 1 } + end - it "returns a Hash instance, even on subclasses" do - klass = Class.new(Hash) - h = klass.new - h[:bar] = 12 - h[:foo] = 42 - r = h.slice(:foo) - r.should == {foo: 42} - r.class.should == Hash - end + it "returns a Hash instance, even on subclasses" do + klass = Class.new(Hash) + h = klass.new + h[:bar] = 12 + h[:foo] = 42 + r = h.slice(:foo) + r.should == {foo: 42} + r.class.should == Hash + end - it "uses the regular Hash#[] method, even on subclasses that override it" do - ScratchPad.record [] - klass = Class.new(Hash) do - def [](value) - ScratchPad << :used_subclassed_operator - super - end + it "uses the regular Hash#[] method, even on subclasses that override it" do + ScratchPad.record [] + klass = Class.new(Hash) do + def [](value) + ScratchPad << :used_subclassed_operator + super end + end - h = klass.new - h[:bar] = 12 - h[:foo] = 42 - h.slice(:foo) + h = klass.new + h[:bar] = 12 + h[:foo] = 42 + h.slice(:foo) - ScratchPad.recorded.should == [] - end + ScratchPad.recorded.should == [] end end diff --git a/ruby/spec/ruby/core/hash/to_h_spec.rb b/ruby/spec/ruby/core/hash/to_h_spec.rb index d6eaac9f3..75ebce68b 100644 --- a/ruby/spec/ruby/core/hash/to_h_spec.rb +++ b/ruby/spec/ruby/core/hash/to_h_spec.rb @@ -32,43 +32,41 @@ end end - ruby_version_is "2.6" do - context "with block" do - it "converts [key, value] pairs returned by the block to a hash" do - { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 } - end + context "with block" do + it "converts [key, value] pairs returned by the block to a hash" do + { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 } + end - it "raises ArgumentError if block returns longer or shorter array" do - -> do - { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) + it "raises ArgumentError if block returns longer or shorter array" do + -> do + { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) - -> do - { a: 1, b: 2 }.to_h { |k, v| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end + -> do + { a: 1, b: 2 }.to_h { |k, v| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end - it "raises TypeError if block returns something other than Array" do - -> do - { a: 1, b: 2 }.to_h { |k, v| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end + it "raises TypeError if block returns something other than Array" do + -> do + { a: 1, b: 2 }.to_h { |k, v| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) - { a: 1 }.to_h { |k| x }.should == { :b => 'b' } - end + { a: 1 }.to_h { |k| x }.should == { :b => 'b' } + end - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) - -> do - { a: 1 }.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end + -> do + { a: 1 }.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) end end end diff --git a/ruby/spec/ruby/core/hash/to_proc_spec.rb b/ruby/spec/ruby/core/hash/to_proc_spec.rb index 3e7e57d11..8f5d21beb 100644 --- a/ruby/spec/ruby/core/hash/to_proc_spec.rb +++ b/ruby/spec/ruby/core/hash/to_proc_spec.rb @@ -19,8 +19,20 @@ @proc = @hash.to_proc end - it "is not a lambda" do - @proc.lambda?.should == false + ruby_version_is ""..."3.0" do + it "is not a lambda" do + @proc.should_not.lambda? + end + end + + ruby_version_is "3.0" do + it "is a lambda" do + @proc.should.lambda? + end + + it "has an arity of 1" do + @proc.arity.should == 1 + end end it "raises ArgumentError if not passed exactly one argument" do diff --git a/ruby/spec/ruby/core/hash/transform_keys_spec.rb b/ruby/spec/ruby/core/hash/transform_keys_spec.rb index 32ac89b76..8ee1a2cd6 100644 --- a/ruby/spec/ruby/core/hash/transform_keys_spec.rb +++ b/ruby/spec/ruby/core/hash/transform_keys_spec.rb @@ -1,131 +1,147 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "Hash#transform_keys" do - before :each do - @hash = { a: 1, b: 2, c: 3 } - end +describe "Hash#transform_keys" do + before :each do + @hash = { a: 1, b: 2, c: 3 } + end - it "returns new hash" do - ret = @hash.transform_keys(&:succ) - ret.should_not equal(@hash) - ret.should be_an_instance_of(Hash) - end + it "returns new hash" do + ret = @hash.transform_keys(&:succ) + ret.should_not equal(@hash) + ret.should be_an_instance_of(Hash) + end - it "sets the result as transformed keys with the given block" do - @hash.transform_keys(&:succ).should == { b: 1, c: 2, d: 3 } - end + it "sets the result as transformed keys with the given block" do + @hash.transform_keys(&:succ).should == { b: 1, c: 2, d: 3 } + end - it "keeps last pair if new keys conflict" do - @hash.transform_keys { |_| :a }.should == { a: 3 } - end + it "keeps last pair if new keys conflict" do + @hash.transform_keys { |_| :a }.should == { a: 3 } + end - it "makes both hashes to share values" do - value = [1, 2, 3] - new_hash = { a: value }.transform_keys(&:upcase) - new_hash[:A].should equal(value) - end + it "makes both hashes to share values" do + value = [1, 2, 3] + new_hash = { a: value }.transform_keys(&:upcase) + new_hash[:A].should equal(value) + end - context "when no block is given" do - it "returns a sized Enumerator" do - enumerator = @hash.transform_keys - enumerator.should be_an_instance_of(Enumerator) - enumerator.size.should == @hash.size - enumerator.each(&:succ).should == { b: 1, c: 2, d: 3 } - end + context "when no block is given" do + it "returns a sized Enumerator" do + enumerator = @hash.transform_keys + enumerator.should be_an_instance_of(Enumerator) + enumerator.size.should == @hash.size + enumerator.each(&:succ).should == { b: 1, c: 2, d: 3 } end + end - it "returns a Hash instance, even on subclasses" do - klass = Class.new(Hash) - h = klass.new - h[:foo] = 42 - r = h.transform_keys{|v| :"x#{v}"} - r.keys.should == [:xfoo] - r.class.should == Hash - end + it "returns a Hash instance, even on subclasses" do + klass = Class.new(Hash) + h = klass.new + h[:foo] = 42 + r = h.transform_keys{|v| :"x#{v}"} + r.keys.should == [:xfoo] + r.class.should == Hash end - describe "Hash#transform_keys!" do - before :each do - @hash = { a: 1, b: 2, c: 3, d: 4 } - @initial_pairs = @hash.dup + ruby_version_is "3.0" do + it "allows a hash argument" do + @hash.transform_keys({ a: :A, b: :B, c: :C }).should == { A: 1, B: 2, C: 3 } end - it "returns self" do - @hash.transform_keys!(&:succ).should equal(@hash) + it "allows a partial transformation of keys when using a hash argument" do + @hash.transform_keys({ a: :A, c: :C }).should == { A: 1, b: 2, C: 3 } end - it "updates self as transformed values with the given block" do - @hash.transform_keys!(&:to_s) - @hash.should == { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 } + it "allows a combination of hash and block argument" do + @hash.transform_keys({ a: :A }, &:to_s).should == { A: 1, 'b' => 2, 'c' => 3 } end + end +end - # https://bugs.ruby-lang.org/issues/14380 - ruby_version_is ""..."2.5.1" do - it "does not prevent conflicts between new keys and old ones" do - @hash.transform_keys!(&:succ) - @hash.should == { e: 1 } - end - end +describe "Hash#transform_keys!" do + before :each do + @hash = { a: 1, b: 2, c: 3, d: 4 } + @initial_pairs = @hash.dup + end - ruby_version_is "2.5.1" do - it "prevents conflicts between new keys and old ones" do - @hash.transform_keys!(&:succ) - @hash.should == { b: 1, c: 2, d: 3, e: 4 } + it "returns self" do + @hash.transform_keys!(&:succ).should equal(@hash) + end + + it "updates self as transformed values with the given block" do + @hash.transform_keys!(&:to_s) + @hash.should == { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 } + end + + # https://bugs.ruby-lang.org/issues/14380 + it "prevents conflicts between new keys and old ones" do + @hash.transform_keys!(&:succ) + @hash.should == { b: 1, c: 2, d: 3, e: 4 } + end + + ruby_version_is ""..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735 + it "returns the processed keys if we broke from the block" do + @hash.transform_keys! do |v| + break if v == :c + v.succ end + @hash.should == { b: 1, c: 2 } end + end - ruby_version_is ""..."2.5.1" do - it "partially modifies the contents if we broke from the block" do - @hash.transform_keys! do |v| - break if v == :c - v.succ - end - @hash.should == { c: 1, d: 4 } + ruby_version_is "3.0.2" do + it "returns the processed keys and non evaluated keys if we broke from the block" do + @hash.transform_keys! do |v| + break if v == :c + v.succ end + @hash.should == { b: 1, c: 2, d: 4 } end + end - ruby_version_is "2.5.1" do - it "returns the processed keys if we broke from the block" do - @hash.transform_keys! do |v| - break if v == :c - v.succ - end - @hash.should == { b: 1, c: 2 } - end + it "keeps later pair if new keys conflict" do + @hash.transform_keys! { |_| :a }.should == { a: 4 } + end + + context "when no block is given" do + it "returns a sized Enumerator" do + enumerator = @hash.transform_keys! + enumerator.should be_an_instance_of(Enumerator) + enumerator.size.should == @hash.size + enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 } end + end - it "keeps later pair if new keys conflict" do - @hash.transform_keys! { |_| :a }.should == { a: 4 } + ruby_version_is "3.0" do + it "allows a hash argument" do + @hash.transform_keys!({ a: :A, b: :B, c: :C, d: :D }) + @hash.should == { A: 1, B: 2, C: 3, D: 4 } end + end - context "when no block is given" do - it "returns a sized Enumerator" do - enumerator = @hash.transform_keys! - enumerator.should be_an_instance_of(Enumerator) - enumerator.size.should == @hash.size - enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 } - end + describe "on frozen instance" do + before :each do + @hash.freeze end - describe "on frozen instance" do - before :each do - @hash.freeze - end + it "raises a FrozenError on an empty hash" do + ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(FrozenError) + end - it "raises a #{frozen_error_class} on an empty hash" do - ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(frozen_error_class) - end + it "keeps pairs and raises a FrozenError" do + ->{ @hash.transform_keys!(&:upcase) }.should raise_error(FrozenError) + @hash.should == @initial_pairs + end - it "keeps pairs and raises a #{frozen_error_class}" do - ->{ @hash.transform_keys!(&:upcase) }.should raise_error(frozen_error_class) - @hash.should == @initial_pairs + ruby_version_is "3.0" do + it "raises a FrozenError on hash argument" do + ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError) end + end - context "when no block is given" do - it "does not raise an exception" do - @hash.transform_keys!.should be_an_instance_of(Enumerator) - end + context "when no block is given" do + it "does not raise an exception" do + @hash.transform_keys!.should be_an_instance_of(Enumerator) end end end diff --git a/ruby/spec/ruby/core/hash/transform_values_spec.rb b/ruby/spec/ruby/core/hash/transform_values_spec.rb index 8b53b7a52..acb469416 100644 --- a/ruby/spec/ruby/core/hash/transform_values_spec.rb +++ b/ruby/spec/ruby/core/hash/transform_values_spec.rb @@ -79,12 +79,12 @@ @hash.freeze end - it "raises a #{frozen_error_class} on an empty hash" do - ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(frozen_error_class) + it "raises a FrozenError on an empty hash" do + ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(FrozenError) end - it "keeps pairs and raises a #{frozen_error_class}" do - ->{ @hash.transform_values!(&:succ) }.should raise_error(frozen_error_class) + it "keeps pairs and raises a FrozenError" do + ->{ @hash.transform_values!(&:succ) }.should raise_error(FrozenError) @hash.should == @initial_pairs end diff --git a/ruby/spec/ruby/core/integer/allbits_spec.rb b/ruby/spec/ruby/core/integer/allbits_spec.rb index f4a6fe990..edce4b15e 100644 --- a/ruby/spec/ruby/core/integer/allbits_spec.rb +++ b/ruby/spec/ruby/core/integer/allbits_spec.rb @@ -1,39 +1,37 @@ require_relative '../../spec_helper' -ruby_version_is '2.5' do - describe "Integer#allbits?" do - it "returns true iff all the bits of the argument are set in the receiver" do - 42.allbits?(42).should == true - 0b1010_1010.allbits?(0b1000_0010).should == true - 0b1010_1010.allbits?(0b1000_0001).should == false - 0b1000_0010.allbits?(0b1010_1010).should == false - (0b1010_1010 | bignum_value).allbits?(0b1000_0010 | bignum_value).should == true - (0b1010_1010 | bignum_value).allbits?(0b1000_0001 | bignum_value).should == false - (0b1000_0010 | bignum_value).allbits?(0b1010_1010 | bignum_value).should == false - end +describe "Integer#allbits?" do + it "returns true if and only if all the bits of the argument are set in the receiver" do + 42.allbits?(42).should == true + 0b1010_1010.allbits?(0b1000_0010).should == true + 0b1010_1010.allbits?(0b1000_0001).should == false + 0b1000_0010.allbits?(0b1010_1010).should == false + (0b1010_1010 | bignum_value).allbits?(0b1000_0010 | bignum_value).should == true + (0b1010_1010 | bignum_value).allbits?(0b1000_0001 | bignum_value).should == false + (0b1000_0010 | bignum_value).allbits?(0b1010_1010 | bignum_value).should == false + end - it "handles negative values using two's complement notation" do - (~0b1).allbits?(42).should == true - (-42).allbits?(-42).should == true - (~0b1010_1010).allbits?(~0b1110_1011).should == true - (~0b1010_1010).allbits?(~0b1000_0010).should == false - (~(0b1010_1010 | bignum_value)).allbits?(~(0b1110_1011 | bignum_value)).should == true - (~(0b1010_1010 | bignum_value)).allbits?(~(0b1000_0010 | bignum_value)).should == false - end + it "handles negative values using two's complement notation" do + (~0b1).allbits?(42).should == true + (-42).allbits?(-42).should == true + (~0b1010_1010).allbits?(~0b1110_1011).should == true + (~0b1010_1010).allbits?(~0b1000_0010).should == false + (~(0b1010_1010 | bignum_value)).allbits?(~(0b1110_1011 | bignum_value)).should == true + (~(0b1010_1010 | bignum_value)).allbits?(~(0b1000_0010 | bignum_value)).should == false + end - it "coerces the rhs using to_int" do - obj = mock("the int 0b10") - obj.should_receive(:to_int).and_return(0b10) - 0b110.allbits?(obj).should == true - end + it "coerces the rhs using to_int" do + obj = mock("the int 0b10") + obj.should_receive(:to_int).and_return(0b10) + 0b110.allbits?(obj).should == true + end - it "raises a TypeError when given a non-Integer" do - -> { - (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) - 13.allbits?(obj) - }.should raise_error(TypeError) - -> { 13.allbits?("10") }.should raise_error(TypeError) - -> { 13.allbits?(:symbol) }.should raise_error(TypeError) - end + it "raises a TypeError when given a non-Integer" do + -> { + (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) + 13.allbits?(obj) + }.should raise_error(TypeError) + -> { 13.allbits?("10") }.should raise_error(TypeError) + -> { 13.allbits?(:symbol) }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/core/integer/anybits_spec.rb b/ruby/spec/ruby/core/integer/anybits_spec.rb index 91f349258..e0449074a 100644 --- a/ruby/spec/ruby/core/integer/anybits_spec.rb +++ b/ruby/spec/ruby/core/integer/anybits_spec.rb @@ -1,38 +1,36 @@ require_relative '../../spec_helper' -ruby_version_is '2.5' do - describe "Integer#anybits?" do - it "returns true iff all the bits of the argument are set in the receiver" do - 42.anybits?(42).should == true - 0b1010_1010.anybits?(0b1000_0010).should == true - 0b1010_1010.anybits?(0b1000_0001).should == true - 0b1000_0010.anybits?(0b0010_1100).should == false - different_bignum = (2 * bignum_value) & (~bignum_value) - (0b1010_1010 | different_bignum).anybits?(0b1000_0010 | bignum_value).should == true - (0b1010_1010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == true - (0b1000_0010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == false - end +describe "Integer#anybits?" do + it "returns true if and only if all the bits of the argument are set in the receiver" do + 42.anybits?(42).should == true + 0b1010_1010.anybits?(0b1000_0010).should == true + 0b1010_1010.anybits?(0b1000_0001).should == true + 0b1000_0010.anybits?(0b0010_1100).should == false + different_bignum = (2 * bignum_value) & (~bignum_value) + (0b1010_1010 | different_bignum).anybits?(0b1000_0010 | bignum_value).should == true + (0b1010_1010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == true + (0b1000_0010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == false + end - it "handles negative values using two's complement notation" do - (~42).anybits?(42).should == false - (-42).anybits?(-42).should == true - (~0b100).anybits?(~0b1).should == true - (~(0b100 | bignum_value)).anybits?(~(0b1 | bignum_value)).should == true - end + it "handles negative values using two's complement notation" do + (~42).anybits?(42).should == false + (-42).anybits?(-42).should == true + (~0b100).anybits?(~0b1).should == true + (~(0b100 | bignum_value)).anybits?(~(0b1 | bignum_value)).should == true + end - it "coerces the rhs using to_int" do - obj = mock("the int 0b10") - obj.should_receive(:to_int).and_return(0b10) - 0b110.anybits?(obj).should == true - end + it "coerces the rhs using to_int" do + obj = mock("the int 0b10") + obj.should_receive(:to_int).and_return(0b10) + 0b110.anybits?(obj).should == true + end - it "raises a TypeError when given a non-Integer" do - -> { - (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) - 13.anybits?(obj) - }.should raise_error(TypeError) - -> { 13.anybits?("10") }.should raise_error(TypeError) - -> { 13.anybits?(:symbol) }.should raise_error(TypeError) - end + it "raises a TypeError when given a non-Integer" do + -> { + (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) + 13.anybits?(obj) + }.should raise_error(TypeError) + -> { 13.anybits?("10") }.should raise_error(TypeError) + -> { 13.anybits?(:symbol) }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/core/integer/chr_spec.rb b/ruby/spec/ruby/core/integer/chr_spec.rb index a8755eeb8..9f105e424 100644 --- a/ruby/spec/ruby/core/integer/chr_spec.rb +++ b/ruby/spec/ruby/core/integer/chr_spec.rb @@ -240,4 +240,17 @@ -> { integer.chr(encoding_name) }.should raise_error(RangeError) end end + + ruby_version_is "2.7" do + it 'returns a String encoding self interpreted as a codepoint in the CESU-8 encoding' do + # see more details here https://en.wikipedia.org/wiki/CESU-8 + # code points from U+0000 to U+FFFF is encoded in the same way as in UTF-8 + 0x0045.chr(Encoding::CESU_8).bytes.should == 0x0045.chr(Encoding::UTF_8).bytes + + # code points in range from U+10000 to U+10FFFF is CESU-8 data containing a 6-byte surrogate pair, + # which decodes to a 4-byte UTF-8 string + 0x10400.chr(Encoding::CESU_8).bytes.should != 0x10400.chr(Encoding::UTF_8).bytes + 0x10400.chr(Encoding::CESU_8).bytes.to_a.should == [0xED, 0xA0, 0x81, 0xED, 0xB0, 0x80] + end + end end diff --git a/ruby/spec/ruby/core/integer/coerce_spec.rb b/ruby/spec/ruby/core/integer/coerce_spec.rb index 9a19baf2e..f1f325603 100644 --- a/ruby/spec/ruby/core/integer/coerce_spec.rb +++ b/ruby/spec/ruby/core/integer/coerce_spec.rb @@ -7,7 +7,7 @@ describe "when given a Fixnum" do it "returns an array containing two Fixnums" do 1.coerce(2).should == [2, 1] - 1.coerce(2).map { |i| i.class }.should == [Fixnum, Fixnum] + 1.coerce(2).map { |i| i.class }.should == [Integer, Integer] end end @@ -46,8 +46,8 @@ a = bignum_value ary = a.coerce(2) - ary[0].should be_kind_of(Bignum) - ary[1].should be_kind_of(Bignum) + ary[0].should be_kind_of(Integer) + ary[1].should be_kind_of(Integer) ary.should == [2, a] end @@ -56,8 +56,8 @@ b = bignum_value ary = a.coerce(b) - ary[0].should be_kind_of(Bignum) - ary[1].should be_kind_of(Bignum) + ary[0].should be_kind_of(Integer) + ary[1].should be_kind_of(Integer) ary.should == [b, a] end diff --git a/ruby/spec/ruby/core/integer/comparison_spec.rb b/ruby/spec/ruby/core/integer/comparison_spec.rb index 2ff557c7c..408c8e52c 100644 --- a/ruby/spec/ruby/core/integer/comparison_spec.rb +++ b/ruby/spec/ruby/core/integer/comparison_spec.rb @@ -116,7 +116,7 @@ describe "with an Object" do before :each do @big = bignum_value - @num = mock("value for Bignum#<=>") + @num = mock("value for Integer#<=>") end it "calls #coerce on other" do @@ -124,23 +124,11 @@ @big <=> @num end - ruby_version_is ""..."2.5" do - it "returns nil if #coerce raises an exception" do - @num.should_receive(:coerce).with(@big).and_raise(RuntimeError) - -> { - @result = (@big <=> @num) - }.should complain(/Numerical comparison operators will no more rescue exceptions/) - @result.should be_nil - end - end - - ruby_version_is "2.5" do - it "lets the exception go through if #coerce raises an exception" do - @num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error")) - -> { - @big <=> @num - }.should raise_error(RuntimeError, "my error") - end + it "lets the exception go through if #coerce raises an exception" do + @num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error")) + -> { + @big <=> @num + }.should raise_error(RuntimeError, "my error") end it "raises an exception if #coerce raises a non-StandardError exception" do diff --git a/ruby/spec/ruby/core/integer/digits_spec.rb b/ruby/spec/ruby/core/integer/digits_spec.rb index 4a8e33980..3d0a64c25 100644 --- a/ruby/spec/ruby/core/integer/digits_spec.rb +++ b/ruby/spec/ruby/core/integer/digits_spec.rb @@ -29,4 +29,13 @@ it "raises Math::DomainError when calling digits on a negative number" do -> { -12345.digits(7) }.should raise_error(Math::DomainError) end + + it "returns integer values > 9 when base is above 10" do + 1234.digits(16).should == [2, 13, 4] + end + + it "can be used with base > 37" do + 1234.digits(100).should == [34, 12] + 980099.digits(100).should == [99, 0, 98] + end end diff --git a/ruby/spec/ruby/core/integer/div_spec.rb b/ruby/spec/ruby/core/integer/div_spec.rb index 087d012fe..bc1c4363d 100644 --- a/ruby/spec/ruby/core/integer/div_spec.rb +++ b/ruby/spec/ruby/core/integer/div_spec.rb @@ -36,7 +36,7 @@ 10.div(y).should == result end - it "coerces self and the given argument to Floats and returns self divided by other as Fixnum" do + it "coerces self and the given argument to Floats and returns self divided by other as Integer" do 1.div(0.2).should == 5 1.div(0.16).should == 6 1.div(0.169).should == 5 diff --git a/ruby/spec/ruby/core/integer/divide_spec.rb b/ruby/spec/ruby/core/integer/divide_spec.rb index a32d68c22..5ac2dc538 100644 --- a/ruby/spec/ruby/core/integer/divide_spec.rb +++ b/ruby/spec/ruby/core/integer/divide_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/arithmetic_coerce' describe "Integer#/" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_arithmetic_coerce_rescue, :/ - end - - ruby_version_is "2.5" do - it_behaves_like :integer_arithmetic_coerce_not_rescue, :/ - end + it_behaves_like :integer_arithmetic_coerce_not_rescue, :/ context "fixnum" do it "returns self divided by the given argument" do diff --git a/ruby/spec/ruby/core/integer/downto_spec.rb b/ruby/spec/ruby/core/integer/downto_spec.rb index af7a7e36b..987704b02 100644 --- a/ruby/spec/ruby/core/integer/downto_spec.rb +++ b/ruby/spec/ruby/core/integer/downto_spec.rb @@ -1,6 +1,6 @@ require_relative '../../spec_helper' -describe "Integer#downto [stop] when self and stop are Fixnums" do +describe "Integer#downto [stop] when self and stop are Integers" do it "does not yield when stop is greater than self" do result = [] 5.downto(6) { |x| result << x } diff --git a/ruby/spec/ruby/core/integer/element_reference_spec.rb b/ruby/spec/ruby/core/integer/element_reference_spec.rb index 99283fac3..7197ecdc0 100644 --- a/ruby/spec/ruby/core/integer/element_reference_spec.rb +++ b/ruby/spec/ruby/core/integer/element_reference_spec.rb @@ -78,6 +78,85 @@ it "returns 0 when passed a Float in the range of a Bignum" do 3[bignum_value.to_f].should == 0 end + + ruby_version_is "2.7" do + context "when index and length passed" do + it "returns specified number of bits from specified position" do + 0b101001101[2, 4].should == 0b0011 + 0b101001101[2, 5].should == 0b10011 + 0b101001101[2, 7].should == 0b1010011 + end + + it "ensures n[i, len] equals to (n >> i) & ((1 << len) - 1)" do + n = 0b101001101; i = 2; len = 4 + n[i, len].should == (n >> i) & ((1 << len) - 1) + end + + it "moves start position to the most significant bits when negative index passed" do + 0b000001[-1, 4].should == 0b10 + 0b000001[-2, 4].should == 0b100 + 0b000001[-3, 4].should == 0b1000 + end + + it "ignores negative length" do + 0b101001101[1, -1].should == 0b10100110 + 0b101001101[2, -1].should == 0b1010011 + 0b101001101[3, -1].should == 0b101001 + + 0b101001101[3, -5].should == 0b101001 + 0b101001101[3, -15].should == 0b101001 + 0b101001101[3, -125].should == 0b101001 + end + end + + context "when range passed" do + it "returns bits specified by range" do + 0b101001101[2..5].should == 0b0011 + 0b101001101[2..6].should == 0b10011 + 0b101001101[2..8].should == 0b1010011 + end + + it "ensures n[i..j] equals to (n >> i) & ((1 << (j - i + 1)) - 1)" do + n = 0b101001101; i = 2; j = 5 + n[i..j].should == (n >> i) & ((1 << (j - i + 1)) - 1) + end + + it "ensures n[i..] equals to (n >> i)" do + eval("0b101001101[3..]").should == 0b101001101 >> 3 + end + + it "moves lower boundary to the most significant bits when negative value passed" do + 0b000001[-1, 4].should == 0b10 + 0b000001[-2, 4].should == 0b100 + 0b000001[-3, 4].should == 0b1000 + end + + it "ignores upper boundary smaller than lower boundary" do + 0b101001101[4..1].should == 0b10100 + 0b101001101[4..2].should == 0b10100 + 0b101001101[-4..-5].should == 0b1010011010000 + end + + it "raises FloatDomainError if any boundary is infinity" do + -> { 0x0001[3..Float::INFINITY] }.should raise_error(FloatDomainError, /Infinity/) + -> { 0x0001[-Float::INFINITY..3] }.should raise_error(FloatDomainError, /-Infinity/) + end + + context "when passed (..i)" do + it "returns 0 if all i bits equal 0" do + eval("0b10000[..1]").should == 0 + eval("0b10000[..2]").should == 0 + eval("0b10000[..3]").should == 0 + end + + it "raises ArgumentError if any of i bit equals 1" do + -> { + eval("0b111110[..3]") + }.should raise_error(ArgumentError, /The beginless range for Integer#\[\] results in infinity/) + end + end + end + end end context "bignum" do diff --git a/ruby/spec/ruby/core/integer/gcd_spec.rb b/ruby/spec/ruby/core/integer/gcd_spec.rb index 8aa654a16..961f1c5c2 100644 --- a/ruby/spec/ruby/core/integer/gcd_spec.rb +++ b/ruby/spec/ruby/core/integer/gcd_spec.rb @@ -33,13 +33,13 @@ it "accepts a Bignum argument" do bignum = 9999**99 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) 99.gcd(bignum).should == 99 end it "works if self is a Bignum" do bignum = 9999**99 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) bignum.gcd(99).should == 99 end diff --git a/ruby/spec/ruby/core/integer/gcdlcm_spec.rb b/ruby/spec/ruby/core/integer/gcdlcm_spec.rb index 5b3669e62..ebf45e55a 100644 --- a/ruby/spec/ruby/core/integer/gcdlcm_spec.rb +++ b/ruby/spec/ruby/core/integer/gcdlcm_spec.rb @@ -28,13 +28,13 @@ it "accepts a Bignum argument" do bignum = 91999**99 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) 99.gcdlcm(bignum).should == [99.gcd(bignum), 99.lcm(bignum)] end it "works if self is a Bignum" do bignum = 9999**89 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) bignum.gcdlcm(99).should == [bignum.gcd(99), bignum.lcm(99)] end diff --git a/ruby/spec/ruby/core/integer/gt_spec.rb b/ruby/spec/ruby/core/integer/gt_spec.rb index 428a6f688..f0179e566 100644 --- a/ruby/spec/ruby/core/integer/gt_spec.rb +++ b/ruby/spec/ruby/core/integer/gt_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/comparison_coerce' describe "Integer#>" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_comparison_coerce_rescue, :> - end - - ruby_version_is "2.5" do - it_behaves_like :integer_comparison_coerce_not_rescue, :> - end + it_behaves_like :integer_comparison_coerce_not_rescue, :> context "fixnum" do it "returns true if self is greater than the given argument" do diff --git a/ruby/spec/ruby/core/integer/gte_spec.rb b/ruby/spec/ruby/core/integer/gte_spec.rb index ce1385c36..6237fc2c5 100644 --- a/ruby/spec/ruby/core/integer/gte_spec.rb +++ b/ruby/spec/ruby/core/integer/gte_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/comparison_coerce' describe "Integer#>=" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_comparison_coerce_rescue, :>= - end - - ruby_version_is "2.5" do - it_behaves_like :integer_comparison_coerce_not_rescue, :>= - end + it_behaves_like :integer_comparison_coerce_not_rescue, :>= context "fixnum" do it "returns true if self is greater than or equal to the given argument" do diff --git a/ruby/spec/ruby/core/integer/integer_spec.rb b/ruby/spec/ruby/core/integer/integer_spec.rb index f8067cda0..2d5d2e3e9 100644 --- a/ruby/spec/ruby/core/integer/integer_spec.rb +++ b/ruby/spec/ruby/core/integer/integer_spec.rb @@ -13,8 +13,8 @@ describe "Integer#integer?" do it "returns true for Integers" do - 0.integer?.should == true - -1.integer?.should == true - bignum_value.integer?.should == true + 0.should.integer? + -1.should.integer? + bignum_value.should.integer? end end diff --git a/ruby/spec/ruby/core/integer/lcm_spec.rb b/ruby/spec/ruby/core/integer/lcm_spec.rb index 77d3ad348..296a001c8 100644 --- a/ruby/spec/ruby/core/integer/lcm_spec.rb +++ b/ruby/spec/ruby/core/integer/lcm_spec.rb @@ -33,13 +33,13 @@ it "accepts a Bignum argument" do bignum = 9999**99 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) 99.lcm(bignum).should == bignum end it "works if self is a Bignum" do bignum = 9999**99 - bignum.should be_kind_of(Bignum) + bignum.should be_kind_of(Integer) bignum.lcm(99).should == bignum end diff --git a/ruby/spec/ruby/core/integer/left_shift_spec.rb b/ruby/spec/ruby/core/integer/left_shift_spec.rb index 4b5ef9386..4efcbef33 100644 --- a/ruby/spec/ruby/core/integer/left_shift_spec.rb +++ b/ruby/spec/ruby/core/integer/left_shift_spec.rb @@ -58,21 +58,24 @@ it "returns an Bignum == fixnum_max * 2 when fixnum_max << 1 and n > 0" do result = fixnum_max << 1 - result.should be_an_instance_of(Bignum) + result.should be_an_instance_of(Integer) result.should == fixnum_max * 2 end it "returns an Bignum == fixnum_min * 2 when fixnum_min << 1 and n < 0" do result = fixnum_min << 1 - result.should be_an_instance_of(Bignum) + result.should be_an_instance_of(Integer) result.should == fixnum_min * 2 end it "calls #to_int to convert the argument to an Integer" do obj = mock("4") obj.should_receive(:to_int).and_return(4) - (3 << obj).should == 48 + + obj = mock("to_int_neg_bignum") + obj.should_receive(:to_int).and_return(-bignum_value) + (3 << obj).should == 0 end it "raises a TypeError when #to_int does not return an Integer" do @@ -130,13 +133,13 @@ it "returns a Fixnum == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do result = (fixnum_max * 2) << -1 - result.should be_an_instance_of(Fixnum) + result.should be_an_instance_of(Integer) result.should == fixnum_max end it "returns a Fixnum == fixnum_min when (fixnum_min * 2) << -1 and n < 0" do result = (fixnum_min * 2) << -1 - result.should be_an_instance_of(Fixnum) + result.should be_an_instance_of(Integer) result.should == fixnum_min end diff --git a/ruby/spec/ruby/core/integer/lt_spec.rb b/ruby/spec/ruby/core/integer/lt_spec.rb index dfe2d9e36..c182f8255 100644 --- a/ruby/spec/ruby/core/integer/lt_spec.rb +++ b/ruby/spec/ruby/core/integer/lt_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/comparison_coerce' describe "Integer#<" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_comparison_coerce_rescue, :< - end - - ruby_version_is "2.5" do - it_behaves_like :integer_comparison_coerce_not_rescue, :< - end + it_behaves_like :integer_comparison_coerce_not_rescue, :< context "fixnum" do it "returns true if self is less than the given argument" do diff --git a/ruby/spec/ruby/core/integer/lte_spec.rb b/ruby/spec/ruby/core/integer/lte_spec.rb index 3d843a5dd..65b71d77f 100644 --- a/ruby/spec/ruby/core/integer/lte_spec.rb +++ b/ruby/spec/ruby/core/integer/lte_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/comparison_coerce' describe "Integer#<=" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_comparison_coerce_rescue, :<= - end - - ruby_version_is "2.5" do - it_behaves_like :integer_comparison_coerce_not_rescue, :<= - end + it_behaves_like :integer_comparison_coerce_not_rescue, :<= context "fixnum" do it "returns true if self is less than or equal to other" do @@ -46,6 +40,11 @@ (@bignum <= (@bignum + 0.5)).should == false end + it "returns true for bignums compare to a bigger float" do + (18446744073709551616 <= 1.8446744073709552e+19).should == true + (@bignum <= (@bignum + 9999.0)).should == true + end + it "raises an ArgumentError when given a non-Integer" do -> { @bignum <= "4" }.should raise_error(ArgumentError) -> { @bignum <= mock('str') }.should raise_error(ArgumentError) diff --git a/ruby/spec/ruby/core/integer/minus_spec.rb b/ruby/spec/ruby/core/integer/minus_spec.rb index 34dd36c1a..ce50c8752 100644 --- a/ruby/spec/ruby/core/integer/minus_spec.rb +++ b/ruby/spec/ruby/core/integer/minus_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/arithmetic_coerce' describe "Integer#-" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_arithmetic_coerce_rescue, :- - end - - ruby_version_is "2.5" do - it_behaves_like :integer_arithmetic_coerce_not_rescue, :- - end + it_behaves_like :integer_arithmetic_coerce_not_rescue, :- context "fixnum" do it "returns self minus the given Integer" do diff --git a/ruby/spec/ruby/core/integer/multiply_spec.rb b/ruby/spec/ruby/core/integer/multiply_spec.rb index 919786cbc..d1e9c2640 100644 --- a/ruby/spec/ruby/core/integer/multiply_spec.rb +++ b/ruby/spec/ruby/core/integer/multiply_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/arithmetic_coerce' describe "Integer#*" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_arithmetic_coerce_rescue, :* - end - - ruby_version_is "2.5" do - it_behaves_like :integer_arithmetic_coerce_not_rescue, :* - end + it_behaves_like :integer_arithmetic_coerce_not_rescue, :* context "fixnum" do it "returns self multiplied by the given Integer" do diff --git a/ruby/spec/ruby/core/integer/nobits_spec.rb b/ruby/spec/ruby/core/integer/nobits_spec.rb index af3b9e7db..685759ffa 100644 --- a/ruby/spec/ruby/core/integer/nobits_spec.rb +++ b/ruby/spec/ruby/core/integer/nobits_spec.rb @@ -1,38 +1,36 @@ require_relative '../../spec_helper' -ruby_version_is '2.5' do - describe "Integer#nobits?" do - it "returns true iff all no bits of the argument are set in the receiver" do - 42.nobits?(42).should == false - 0b1010_1010.nobits?(0b1000_0010).should == false - 0b1010_1010.nobits?(0b1000_0001).should == false - 0b0100_0101.nobits?(0b1010_1010).should == true - different_bignum = (2 * bignum_value) & (~bignum_value) - (0b1010_1010 | different_bignum).nobits?(0b1000_0010 | bignum_value).should == false - (0b1010_1010 | different_bignum).nobits?(0b1000_0001 | bignum_value).should == false - (0b0100_0101 | different_bignum).nobits?(0b1010_1010 | bignum_value).should == true - end +describe "Integer#nobits?" do + it "returns true if and only if all no bits of the argument are set in the receiver" do + 42.nobits?(42).should == false + 0b1010_1010.nobits?(0b1000_0010).should == false + 0b1010_1010.nobits?(0b1000_0001).should == false + 0b0100_0101.nobits?(0b1010_1010).should == true + different_bignum = (2 * bignum_value) & (~bignum_value) + (0b1010_1010 | different_bignum).nobits?(0b1000_0010 | bignum_value).should == false + (0b1010_1010 | different_bignum).nobits?(0b1000_0001 | bignum_value).should == false + (0b0100_0101 | different_bignum).nobits?(0b1010_1010 | bignum_value).should == true + end - it "handles negative values using two's complement notation" do - (~0b1101).nobits?(0b1101).should == true - (-42).nobits?(-42).should == false - (~0b1101).nobits?(~0b10).should == false - (~(0b1101 | bignum_value)).nobits?(~(0b10 | bignum_value)).should == false - end + it "handles negative values using two's complement notation" do + (~0b1101).nobits?(0b1101).should == true + (-42).nobits?(-42).should == false + (~0b1101).nobits?(~0b10).should == false + (~(0b1101 | bignum_value)).nobits?(~(0b10 | bignum_value)).should == false + end - it "coerces the rhs using to_int" do - obj = mock("the int 0b10") - obj.should_receive(:to_int).and_return(0b10) - 0b110.nobits?(obj).should == false - end + it "coerces the rhs using to_int" do + obj = mock("the int 0b10") + obj.should_receive(:to_int).and_return(0b10) + 0b110.nobits?(obj).should == false + end - it "raises a TypeError when given a non-Integer" do - -> { - (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) - 13.nobits?(obj) - }.should raise_error(TypeError) - -> { 13.nobits?("10") }.should raise_error(TypeError) - -> { 13.nobits?(:symbol) }.should raise_error(TypeError) - end + it "raises a TypeError when given a non-Integer" do + -> { + (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10]) + 13.nobits?(obj) + }.should raise_error(TypeError) + -> { 13.nobits?("10") }.should raise_error(TypeError) + -> { 13.nobits?(:symbol) }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/core/integer/plus_spec.rb b/ruby/spec/ruby/core/integer/plus_spec.rb index 7e919a16d..511a43687 100644 --- a/ruby/spec/ruby/core/integer/plus_spec.rb +++ b/ruby/spec/ruby/core/integer/plus_spec.rb @@ -2,13 +2,7 @@ require_relative 'shared/arithmetic_coerce' describe "Integer#+" do - ruby_version_is "2.4"..."2.5" do - it_behaves_like :integer_arithmetic_coerce_rescue, :+ - end - - ruby_version_is "2.5" do - it_behaves_like :integer_arithmetic_coerce_not_rescue, :+ - end + it_behaves_like :integer_arithmetic_coerce_not_rescue, :+ context "fixnum" do it "returns self plus the given Integer" do @@ -46,4 +40,19 @@ -> { @bignum + :symbol}.should raise_error(TypeError) end end + + it "can be redefined" do + code = <<~RUBY + class Integer + alias_method :old_plus, :+ + def +(other) + self - other + end + end + result = 1 + 2 + Integer.alias_method :+, :old_plus + print result + RUBY + ruby_exe(code).should == "-1" + end end diff --git a/ruby/spec/ruby/core/integer/pow_spec.rb b/ruby/spec/ruby/core/integer/pow_spec.rb index ed14c40a2..471291109 100644 --- a/ruby/spec/ruby/core/integer/pow_spec.rb +++ b/ruby/spec/ruby/core/integer/pow_spec.rb @@ -2,48 +2,50 @@ require_relative 'fixtures/classes' require_relative 'shared/exponent' -ruby_version_is "2.5" do - describe "Integer#pow" do - context "one argument is passed" do - it_behaves_like :integer_exponent, :pow +describe "Integer#pow" do + context "one argument is passed" do + it_behaves_like :integer_exponent, :pow + end + + context "two arguments are passed" do + it "returns modulo of self raised to the given power" do + 2.pow(5, 12).should == 8 + 2.pow(6, 13).should == 12 + 2.pow(7, 14).should == 2 + 2.pow(8, 15).should == 1 + end + + it "works well with bignums" do + 2.pow(61, 5843009213693951).should eql 3697379018277258 + 2.pow(62, 5843009213693952).should eql 1551748822859776 + 2.pow(63, 5843009213693953).should eql 3103497645717974 + 2.pow(64, 5843009213693954).should eql 363986077738838 + end + + it "handles sign like #divmod does" do + 2.pow(5, 12).should == 8 + 2.pow(5, -12).should == -4 + -2.pow(5, 12).should == 4 + -2.pow(5, -12).should == -8 + end + + it "ensures all arguments are integers" do + -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) + -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) + end + + it "raises TypeError for non-numeric value" do + -> { 2.pow(5, "12") }.should raise_error(TypeError) + -> { 2.pow(5, []) }.should raise_error(TypeError) + -> { 2.pow(5, nil) }.should raise_error(TypeError) + end + + it "raises a ZeroDivisionError when the given argument is 0" do + -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError) end - context "two arguments are passed" do - it "returns modulo of self raised to the given power" do - 2.pow(5, 12).should == 8 - 2.pow(6, 13).should == 12 - 2.pow(7, 14).should == 2 - 2.pow(8, 15).should == 1 - end - - it "works well with bignums" do - 2.pow(61, 5843009213693951).should eql 3697379018277258 - 2.pow(62, 5843009213693952).should eql 1551748822859776 - 2.pow(63, 5843009213693953).should eql 3103497645717974 - 2.pow(64, 5843009213693954).should eql 363986077738838 - end - - it "handles sign like #divmod does" do - 2.pow(5, 12).should == 8 - 2.pow(5, -12).should == -4 - -2.pow(5, 12).should == 4 - -2.pow(5, -12).should == -8 - end - - it "ensures all arguments are integers" do - -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) - -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) - end - - it "raises TypeError for non-numeric value" do - -> { 2.pow(5, "12") }.should raise_error(TypeError) - -> { 2.pow(5, []) }.should raise_error(TypeError) - -> { 2.pow(5, nil) }.should raise_error(TypeError) - end - - it "raises a ZeroDivisionError when the given argument is 0" do - -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError) - end + it "raises a RangeError when the first argument is negative and the second argument is present" do + -> { 2.pow(-5, 1) }.should raise_error(RangeError) end end end diff --git a/ruby/spec/ruby/core/integer/right_shift_spec.rb b/ruby/spec/ruby/core/integer/right_shift_spec.rb index 3eeaf3eb2..6abcd8d71 100644 --- a/ruby/spec/ruby/core/integer/right_shift_spec.rb +++ b/ruby/spec/ruby/core/integer/right_shift_spec.rb @@ -58,21 +58,24 @@ it "returns an Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do result = fixnum_max >> -1 - result.should be_an_instance_of(Bignum) + result.should be_an_instance_of(Integer) result.should == fixnum_max * 2 end it "returns an Bignum == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do result = fixnum_min >> -1 - result.should be_an_instance_of(Bignum) + result.should be_an_instance_of(Integer) result.should == fixnum_min * 2 end it "calls #to_int to convert the argument to an Integer" do obj = mock("2") obj.should_receive(:to_int).and_return(2) - (8 >> obj).should == 2 + + obj = mock("to_int_bignum") + obj.should_receive(:to_int).and_return(bignum_value) + (8 >> obj).should == 0 end it "raises a TypeError when #to_int does not return an Integer" do @@ -156,13 +159,13 @@ it "returns a Fixnum == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do result = (fixnum_max * 2) >> 1 - result.should be_an_instance_of(Fixnum) + result.should be_an_instance_of(Integer) result.should == fixnum_max end it "returns a Fixnum == fixnum_min when (fixnum_min * 2) >> 1 and n < 0" do result = (fixnum_min * 2) >> 1 - result.should be_an_instance_of(Fixnum) + result.should be_an_instance_of(Integer) result.should == fixnum_min end diff --git a/ruby/spec/ruby/core/integer/round_spec.rb b/ruby/spec/ruby/core/integer/round_spec.rb index feb6d475d..45ac126fd 100644 --- a/ruby/spec/ruby/core/integer/round_spec.rb +++ b/ruby/spec/ruby/core/integer/round_spec.rb @@ -6,14 +6,6 @@ it_behaves_like :integer_to_i, :round it_behaves_like :integer_rounding_positive_precision, :round - ruby_version_is ""..."2.5" do # Not just since 2.4 - it "rounds itself as a float if passed a positive precision" do - [2, -4, 10**70, -10**100].each do |v| - v.round(42).should eql(v.to_f) - end - end - end - # redmine:5228 it "returns itself rounded if passed a negative value" do +249.round(-2).should eql(+200) @@ -78,20 +70,10 @@ (-25).round(-1, half: nil).should eql(-30) end - ruby_version_is "2.4"..."2.5" do - it "returns itself as a float if passed a positive precision and the half option" do - 35.round(1, half: :up).should eql(35.0) - 35.round(1, half: :down).should eql(35.0) - 35.round(1, half: :even).should eql(35.0) - end - end - - ruby_version_is "2.5" do - it "returns itself if passed a positive precision and the half option" do - 35.round(1, half: :up).should eql(35) - 35.round(1, half: :down).should eql(35) - 35.round(1, half: :even).should eql(35) - end + it "returns itself if passed a positive precision and the half option" do + 35.round(1, half: :up).should eql(35) + 35.round(1, half: :down).should eql(35) + 35.round(1, half: :even).should eql(35) end it "raises ArgumentError for an unknown rounding mode" do diff --git a/ruby/spec/ruby/core/integer/shared/comparison_coerce.rb b/ruby/spec/ruby/core/integer/shared/comparison_coerce.rb index 50437f77f..af52f5e99 100644 --- a/ruby/spec/ruby/core/integer/shared/comparison_coerce.rb +++ b/ruby/spec/ruby/core/integer/shared/comparison_coerce.rb @@ -1,27 +1,5 @@ require_relative '../fixtures/classes' -describe :integer_comparison_coerce_rescue, shared: true do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) - - # e.g. 1 > b - -> { - -> { 1.send(@method, b) }.should raise_error(ArgumentError, /comparison of Integer with MockObject failed/) - }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. 1 > b - -> { 1.send(@method, b) }.should raise_error(exception) - end - end -end - describe :integer_comparison_coerce_not_rescue, shared: true do it "does not rescue exception raised in other#coerce" do b = mock("numeric with failed #coerce") diff --git a/ruby/spec/ruby/core/integer/shared/equal.rb b/ruby/spec/ruby/core/integer/shared/equal.rb index 03416b60f..ecee17831 100644 --- a/ruby/spec/ruby/core/integer/shared/equal.rb +++ b/ruby/spec/ruby/core/integer/shared/equal.rb @@ -4,14 +4,14 @@ 1.send(@method, 1).should == true 9.send(@method, 5).should == false - # Actually, these call Float#==, Bignum#== etc. + # Actually, these call Float#==, Integer#== etc. 9.send(@method, 9.0).should == true 9.send(@method, 9.01).should == false 10.send(@method, bignum_value).should == false end - it "calls 'other == self' if the given argument is not a Integer" do + it "calls 'other == self' if the given argument is not an Integer" do 1.send(@method, '*').should == false obj = mock('one other') diff --git a/ruby/spec/ruby/core/integer/shared/exponent.rb b/ruby/spec/ruby/core/integer/shared/exponent.rb index f292cc244..f949c514c 100644 --- a/ruby/spec/ruby/core/integer/shared/exponent.rb +++ b/ruby/spec/ruby/core/integer/shared/exponent.rb @@ -47,7 +47,9 @@ end it "returns Float::INFINITY when the number is too big" do - 2.send(@method, 427387904).should == Float::INFINITY + -> { + 2.send(@method, 427387904).should == Float::INFINITY + }.should complain(/warning: in a\*\*b, b may be too big/) end it "raises a ZeroDivisionError for 0 ** -1" do @@ -105,7 +107,10 @@ end it "switch to a Float when the values is too big" do - flt = @bignum.send(@method, @bignum) + flt = nil + -> { + flt = @bignum.send(@method, @bignum) + }.should complain(/warning: in a\*\*b, b may be too big/) flt.should be_kind_of(Float) flt.infinite?.should == 1 end diff --git a/ruby/spec/ruby/core/integer/shared/integer_rounding.rb b/ruby/spec/ruby/core/integer/shared/integer_rounding.rb index 3fb6e830e..56d1819f8 100644 --- a/ruby/spec/ruby/core/integer/shared/integer_rounding.rb +++ b/ruby/spec/ruby/core/integer/shared/integer_rounding.rb @@ -11,19 +11,9 @@ end end - ruby_version_is "2.4"..."2.5" do - it "returns itself as a float if passed a positive precision" do - [2, -4, 10**70, -10**100].each do |v| - v.send(@method, 42).should eql(v.to_f) - end - end - end - - ruby_version_is "2.5" do - it "returns itself if passed a positive precision" do - [2, -4, 10**70, -10**100].each do |v| - v.send(@method, 42).should eql(v) - end + it "returns itself if passed a positive precision" do + [2, -4, 10**70, -10**100].each do |v| + v.send(@method, 42).should eql(v) end end end diff --git a/ruby/spec/ruby/core/integer/sqrt_spec.rb b/ruby/spec/ruby/core/integer/sqrt_spec.rb index e56da058a..4149ca2cc 100644 --- a/ruby/spec/ruby/core/integer/sqrt_spec.rb +++ b/ruby/spec/ruby/core/integer/sqrt_spec.rb @@ -1,33 +1,31 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "Integer.sqrt" do - it "returns an integer" do - Integer.sqrt(10).should be_kind_of(Integer) - end +describe "Integer.sqrt" do + it "returns an integer" do + Integer.sqrt(10).should be_kind_of(Integer) + end - it "returns the integer square root of the argument" do - Integer.sqrt(0).should == 0 - Integer.sqrt(1).should == 1 - Integer.sqrt(24).should == 4 - Integer.sqrt(25).should == 5 - Integer.sqrt(10**400).should == 10**200 - end + it "returns the integer square root of the argument" do + Integer.sqrt(0).should == 0 + Integer.sqrt(1).should == 1 + Integer.sqrt(24).should == 4 + Integer.sqrt(25).should == 5 + Integer.sqrt(10**400).should == 10**200 + end - it "raises a Math::DomainError if the argument is negative" do - -> { Integer.sqrt(-4) }.should raise_error(Math::DomainError) - end + it "raises a Math::DomainError if the argument is negative" do + -> { Integer.sqrt(-4) }.should raise_error(Math::DomainError) + end - it "accepts any argument that can be coerced to Integer" do - Integer.sqrt(10.0).should == 3 - end + it "accepts any argument that can be coerced to Integer" do + Integer.sqrt(10.0).should == 3 + end - it "converts the argument with #to_int" do - Integer.sqrt(mock_int(10)).should == 3 - end + it "converts the argument with #to_int" do + Integer.sqrt(mock_int(10)).should == 3 + end - it "raises a TypeError if the argument cannot be coerced to Integer" do - -> { Integer.sqrt("test") }.should raise_error(TypeError) - end + it "raises a TypeError if the argument cannot be coerced to Integer" do + -> { Integer.sqrt("test") }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/core/integer/to_r_spec.rb b/ruby/spec/ruby/core/integer/to_r_spec.rb index 4a40575b7..7732bedca 100644 --- a/ruby/spec/ruby/core/integer/to_r_spec.rb +++ b/ruby/spec/ruby/core/integer/to_r_spec.rb @@ -15,7 +15,7 @@ it "works even if self is a Bignum" do bignum = 99999**999 - bignum.should be_an_instance_of(Bignum) + bignum.should be_an_instance_of(Integer) bignum.to_r.should == Rational(bignum, 1) end diff --git a/ruby/spec/ruby/core/integer/try_convert_spec.rb b/ruby/spec/ruby/core/integer/try_convert_spec.rb new file mode 100644 index 000000000..45c66eec7 --- /dev/null +++ b/ruby/spec/ruby/core/integer/try_convert_spec.rb @@ -0,0 +1,40 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "3.1" do + describe "Integer.try_convert" do + it "returns the argument if it's an Integer" do + x = 42 + Integer.try_convert(x).should equal(x) + end + + it "returns nil when the argument does not respond to #to_int" do + Integer.try_convert(Object.new).should be_nil + end + + it "sends #to_int to the argument and returns the result if it's nil" do + obj = mock("to_int") + obj.should_receive(:to_int).and_return(nil) + Integer.try_convert(obj).should be_nil + end + + it "sends #to_int to the argument and returns the result if it's an Integer" do + x = 234 + obj = mock("to_int") + obj.should_receive(:to_int).and_return(x) + Integer.try_convert(obj).should equal(x) + end + + it "sends #to_int to the argument and raises TypeError if it's not a kind of Integer" do + obj = mock("to_int") + obj.should_receive(:to_int).and_return(Object.new) + -> { Integer.try_convert obj }.should raise_error(TypeError) + end + + it "does not rescue exceptions raised by #to_int" do + obj = mock("to_int") + obj.should_receive(:to_int).and_raise(RuntimeError) + -> { Integer.try_convert obj }.should raise_error(RuntimeError) + end + end +end diff --git a/ruby/spec/ruby/core/integer/upto_spec.rb b/ruby/spec/ruby/core/integer/upto_spec.rb index 6049eb173..dd6995e94 100644 --- a/ruby/spec/ruby/core/integer/upto_spec.rb +++ b/ruby/spec/ruby/core/integer/upto_spec.rb @@ -1,6 +1,6 @@ require_relative '../../spec_helper' -describe "Integer#upto [stop] when self and stop are Fixnums" do +describe "Integer#upto [stop] when self and stop are Integers" do it "does not yield when stop is less than self" do result = [] 5.upto(4) { |x| result << x } diff --git a/ruby/spec/ruby/core/integer/zero_spec.rb b/ruby/spec/ruby/core/integer/zero_spec.rb new file mode 100644 index 000000000..2dac50c40 --- /dev/null +++ b/ruby/spec/ruby/core/integer/zero_spec.rb @@ -0,0 +1,21 @@ +require_relative '../../spec_helper' + +describe "Integer#zero?" do + it "returns true if self is 0" do + 0.should.zero? + 1.should_not.zero? + -1.should_not.zero? + end + + ruby_version_is "3.0" do + it "Integer#zero? overrides Numeric#zero?" do + 42.method(:zero?).owner.should == Integer + end + end + + ruby_version_is ""..."3.0" do + it "Integer#zero? uses Numeric#zero?" do + 42.method(:zero?).owner.should == Numeric + end + end +end diff --git a/ruby/spec/ruby/core/io/binmode_spec.rb b/ruby/spec/ruby/core/io/binmode_spec.rb index b698777ca..342cac2a9 100644 --- a/ruby/spec/ruby/core/io/binmode_spec.rb +++ b/ruby/spec/ruby/core/io/binmode_spec.rb @@ -57,4 +57,8 @@ @duped = @file.dup @duped.binmode?.should == @file.binmode? end + + it "raises an IOError on closed stream" do + -> { IOSpecs.closed_io.binmode? }.should raise_error(IOError) + end end diff --git a/ruby/spec/ruby/core/io/bytes_spec.rb b/ruby/spec/ruby/core/io/bytes_spec.rb index feeb49356..6e328983f 100644 --- a/ruby/spec/ruby/core/io/bytes_spec.rb +++ b/ruby/spec/ruby/core/io/bytes_spec.rb @@ -2,42 +2,46 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "IO#bytes" do - before :each do - @io = IOSpecs.io_fixture "lines.txt" - end - - after :each do - @io.close unless @io.closed? - end +ruby_version_is ''...'3.0' do + describe "IO#bytes" do + before :each do + @io = IOSpecs.io_fixture "lines.txt" + @verbose, $VERBOSE = $VERBOSE, nil + end - it "returns an enumerator of the next bytes from the stream" do - enum = @io.bytes - enum.should be_an_instance_of(Enumerator) - @io.readline.should == "Voici la ligne une.\n" - enum.first(5).should == [81, 117, 105, 32, 195] - end + after :each do + $VERBOSE = @verbose + @io.close unless @io.closed? + end - it "yields each byte" do - count = 0 - ScratchPad.record [] - @io.each_byte do |byte| - ScratchPad << byte - break if 4 < count += 1 + it "returns an enumerator of the next bytes from the stream" do + enum = @io.bytes + enum.should be_an_instance_of(Enumerator) + @io.readline.should == "Voici la ligne une.\n" + enum.first(5).should == [81, 117, 105, 32, 195] end - ScratchPad.recorded.should == [86, 111, 105, 99, 105] - end + it "yields each byte" do + count = 0 + ScratchPad.record [] + @io.each_byte do |byte| + ScratchPad << byte + break if 4 < count += 1 + end - it "raises an IOError on closed stream" do - enum = IOSpecs.closed_io.bytes - -> { enum.first }.should raise_error(IOError) - end + ScratchPad.recorded.should == [86, 111, 105, 99, 105] + end - it "raises an IOError on an enumerator for a stream that has been closed" do - enum = @io.bytes - enum.first.should == 86 - @io.close - -> { enum.first }.should raise_error(IOError) + it "raises an IOError on closed stream" do + enum = IOSpecs.closed_io.bytes + -> { enum.first }.should raise_error(IOError) + end + + it "raises an IOError on an enumerator for a stream that has been closed" do + enum = @io.bytes + enum.first.should == 86 + @io.close + -> { enum.first }.should raise_error(IOError) + end end end diff --git a/ruby/spec/ruby/core/io/chars_spec.rb b/ruby/spec/ruby/core/io/chars_spec.rb index cd5dbbce4..15db595ae 100644 --- a/ruby/spec/ruby/core/io/chars_spec.rb +++ b/ruby/spec/ruby/core/io/chars_spec.rb @@ -3,10 +3,28 @@ require_relative 'fixtures/classes' require_relative 'shared/chars' -describe "IO#chars" do - it_behaves_like :io_chars, :chars -end +ruby_version_is ''...'3.0' do + describe "IO#chars" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :io_chars, :chars + end + + describe "IO#chars" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end -describe "IO#chars" do - it_behaves_like :io_chars_empty, :chars + it_behaves_like :io_chars_empty, :chars + end end diff --git a/ruby/spec/ruby/core/io/close_on_exec_spec.rb b/ruby/spec/ruby/core/io/close_on_exec_spec.rb index f837bb56a..4e89e08d6 100644 --- a/ruby/spec/ruby/core/io/close_on_exec_spec.rb +++ b/ruby/spec/ruby/core/io/close_on_exec_spec.rb @@ -14,24 +14,24 @@ guard -> { platform_is_not :windows } do it "sets the close-on-exec flag if true" do @io.close_on_exec = true - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "sets the close-on-exec flag if non-false" do @io.close_on_exec = :true - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "unsets the close-on-exec flag if false" do @io.close_on_exec = true @io.close_on_exec = false - @io.close_on_exec?.should == false + @io.should_not.close_on_exec? end it "unsets the close-on-exec flag if nil" do @io.close_on_exec = true @io.close_on_exec = nil - @io.close_on_exec?.should == false + @io.should_not.close_on_exec? end it "ensures the IO's file descriptor is closed in exec'ed processes" do @@ -44,10 +44,6 @@ @io.close -> { @io.close_on_exec = true }.should raise_error(IOError) end - - it "returns nil" do - @io.send(:close_on_exec=, true).should be_nil - end end end @@ -64,12 +60,12 @@ guard -> { platform_is_not :windows } do it "returns true by default" do - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "returns true if set" do @io.close_on_exec = true - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "raises IOError if called on a closed IO" do diff --git a/ruby/spec/ruby/core/io/close_read_spec.rb b/ruby/spec/ruby/core/io/close_read_spec.rb index 6fa4fc8ff..26454bfdd 100644 --- a/ruby/spec/ruby/core/io/close_read_spec.rb +++ b/ruby/spec/ruby/core/io/close_read_spec.rb @@ -49,7 +49,7 @@ io.close_read - io.closed?.should == true + io.should.closed? end it "does nothing on closed stream" do diff --git a/ruby/spec/ruby/core/io/close_spec.rb b/ruby/spec/ruby/core/io/close_spec.rb index 21bba32cd..eb560eaf6 100644 --- a/ruby/spec/ruby/core/io/close_spec.rb +++ b/ruby/spec/ruby/core/io/close_spec.rb @@ -14,7 +14,7 @@ it "closes the stream" do @io.close - @io.closed?.should == true + @io.should.closed? end it "returns nil" do @@ -44,22 +44,37 @@ @io.close.should be_nil end - ruby_version_is '2.5' do - it 'raises an IOError with a clear message' do - read_io, write_io = IO.pipe - going_to_read = false - thread = Thread.new do - -> do - going_to_read = true - read_io.read - end.should raise_error(IOError, 'stream closed in another thread') + it 'raises an IOError with a clear message' do + matching_exception = nil + + -> do + IOSpecs::THREAD_CLOSE_RETRIES.times do + read_io, write_io = IO.pipe + going_to_read = false + + thread = Thread.new do + begin + going_to_read = true + read_io.read + rescue IOError => ioe + if ioe.message == IOSpecs::THREAD_CLOSE_ERROR_MESSAGE + matching_exception = ioe + end + # try again + end + end + + # best attempt to ensure the thread is actually blocked on read + Thread.pass until going_to_read && thread.stop? + sleep(0.001) + + read_io.close + thread.join + write_io.close + + matching_exception&.tap {|ex| raise ex} end - - Thread.pass until going_to_read && thread.stop? - read_io.close - thread.join - write_io.close - end + end.should raise_error(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE) end end diff --git a/ruby/spec/ruby/core/io/close_write_spec.rb b/ruby/spec/ruby/core/io/close_write_spec.rb index 75e157765..14835e4e2 100644 --- a/ruby/spec/ruby/core/io/close_write_spec.rb +++ b/ruby/spec/ruby/core/io/close_write_spec.rb @@ -45,7 +45,7 @@ io.close_write - io.closed?.should == true + io.should.closed? end it "flushes and closes the write stream" do diff --git a/ruby/spec/ruby/core/io/codepoints_spec.rb b/ruby/spec/ruby/core/io/codepoints_spec.rb index 915d99c02..04c115dd3 100644 --- a/ruby/spec/ruby/core/io/codepoints_spec.rb +++ b/ruby/spec/ruby/core/io/codepoints_spec.rb @@ -2,24 +2,37 @@ require_relative 'fixtures/classes' require_relative 'shared/codepoints' -# See redmine #1667 -describe "IO#codepoints" do - it_behaves_like :io_codepoints, :codepoints -end +ruby_version_is ''...'3.0' do -describe "IO#codepoints" do - before :each do - @io = IOSpecs.io_fixture "lines.txt" - end + # See redmine #1667 + describe "IO#codepoints" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end - after :each do - @io.close unless @io.closed? + it_behaves_like :io_codepoints, :codepoints end - it "calls the given block" do - r = [] - @io.codepoints { |c| r << c } - r[24].should == 232 - r.last.should == 10 + describe "IO#codepoints" do + before :each do + @io = IOSpecs.io_fixture "lines.txt" + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + @io.close unless @io.closed? + end + + it "calls the given block" do + r = [] + @io.codepoints { |c| r << c } + r[24].should == 232 + r.last.should == 10 + end end end diff --git a/ruby/spec/ruby/core/io/copy_stream_spec.rb b/ruby/spec/ruby/core/io/copy_stream_spec.rb index c541e96e1..df9c5c739 100644 --- a/ruby/spec/ruby/core/io/copy_stream_spec.rb +++ b/ruby/spec/ruby/core/io/copy_stream_spec.rb @@ -279,4 +279,44 @@ end end + + + describe "with a destination that does partial reads" do + before do + @from_out, @from_in = IO.pipe + @to_out, @to_in = IO.pipe + end + + after do + [@from_out, @from_in, @to_out, @to_in].each {|io| io.close rescue nil} + end + + it "calls #write repeatedly on the destination Object" do + @from_in.write "1234" + @from_in.close + + th = Thread.new do + IO.copy_stream(@from_out, @to_in) + end + + copied = "" + 4.times do + copied += @to_out.read(1) + end + + th.join + + copied.should == "1234" + end + + end +end + +describe "IO.copy_stream" do + it "does not use buffering when writing to STDOUT" do + IO.popen([*ruby_exe, fixture(__FILE__ , "copy_in_out.rb")], "r+") do |io| + io.write("bar") + io.read(3).should == "bar" + end + end end diff --git a/ruby/spec/ruby/core/io/dup_spec.rb b/ruby/spec/ruby/core/io/dup_spec.rb index de32c5e34..68d538377 100644 --- a/ruby/spec/ruby/core/io/dup_spec.rb +++ b/ruby/spec/ruby/core/io/dup_spec.rb @@ -51,16 +51,16 @@ @i.close -> { @f.gets }.should_not raise_error(Exception) - @i.closed?.should == true - @f.closed?.should == false + @i.should.closed? + @f.should_not.closed? end it "allows closing the original IO without affecting the new one" do @f.close -> { @i.gets }.should_not raise_error(Exception) - @i.closed?.should == false - @f.closed?.should == true + @i.should_not.closed? + @f.should.closed? end it "raises IOError on closed stream" do @@ -71,7 +71,7 @@ @f.close_on_exec = true dup = @f.dup begin - dup.close_on_exec?.should == true + dup.should.close_on_exec? ensure dup.close end @@ -79,9 +79,28 @@ @f.close_on_exec = false dup = @f.dup begin - dup.close_on_exec?.should == true + dup.should.close_on_exec? ensure dup.close end end + + it "always sets the autoclose flag for the new IO object" do + @f.autoclose = true + dup = @f.dup + begin + dup.should.autoclose? + ensure + dup.close + end + + @f.autoclose = false + dup = @f.dup + begin + dup.should.autoclose? + ensure + dup.close + @f.autoclose = true + end + end end diff --git a/ruby/spec/ruby/core/io/each_codepoint_spec.rb b/ruby/spec/ruby/core/io/each_codepoint_spec.rb index cddc6b466..07a4037c8 100644 --- a/ruby/spec/ruby/core/io/each_codepoint_spec.rb +++ b/ruby/spec/ruby/core/io/each_codepoint_spec.rb @@ -4,7 +4,7 @@ # See redmine #1667 describe "IO#each_codepoint" do - it_behaves_like :io_codepoints, :codepoints + it_behaves_like :io_codepoints, :each_codepoint end describe "IO#each_codepoint" do diff --git a/ruby/spec/ruby/core/io/eof_spec.rb b/ruby/spec/ruby/core/io/eof_spec.rb index 8fd3c3713..315345d94 100644 --- a/ruby/spec/ruby/core/io/eof_spec.rb +++ b/ruby/spec/ruby/core/io/eof_spec.rb @@ -12,7 +12,7 @@ end it "returns true on an empty stream that has just been opened" do - File.open(@name) { |empty| empty.eof?.should == true } + File.open(@name) { |empty| empty.should.eof? } end it "raises IOError on stream not opened for reading" do @@ -34,35 +34,35 @@ it "returns false when not at end of file" do @io.read 1 - @io.eof?.should == false + @io.should_not.eof? end it "returns true after reading with read with no parameters" do @io.read() - @io.eof?.should == true + @io.should.eof? end it "returns true after reading with read" do @io.read(File.size(@name)) - @io.eof?.should == true + @io.should.eof? end it "returns true after reading with sysread" do @io.sysread(File.size(@name)) - @io.eof?.should == true + @io.should.eof? end it "returns true after reading with readlines" do @io.readlines - @io.eof?.should == true + @io.should.eof? end it "returns false on just opened non-empty stream" do - @io.eof?.should == false + @io.should_not.eof? end it "does not consume the data from the stream" do - @io.eof?.should == false + @io.should_not.eof? @io.getc.should == 'V' end @@ -78,7 +78,7 @@ it "returns true on one-byte stream after single-byte read" do File.open(File.dirname(__FILE__) + '/fixtures/one_byte.txt') { |one_byte| one_byte.read(1) - one_byte.eof?.should == true + one_byte.should.eof? } end end @@ -92,16 +92,16 @@ it "returns true on receiving side of Pipe when writing side is closed" do @r, @w = IO.pipe @w.close - @r.eof?.should == true + @r.should.eof? end it "returns false on receiving side of Pipe when writing side wrote some data" do @r, @w = IO.pipe @w.puts "hello" - @r.eof?.should == false + @r.should_not.eof? @w.close - @r.eof?.should == false + @r.should_not.eof? @r.read - @r.eof?.should == true + @r.should.eof? end end diff --git a/ruby/spec/ruby/core/io/external_encoding_spec.rb b/ruby/spec/ruby/core/io/external_encoding_spec.rb index 966697464..2fcf1c721 100644 --- a/ruby/spec/ruby/core/io/external_encoding_spec.rb +++ b/ruby/spec/ruby/core/io/external_encoding_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe :io_external_encoding_write, shared: true do describe "when Encoding.default_internal is nil" do @@ -93,6 +94,14 @@ rm_r @name end + ruby_version_is '3.1' do + it "can be retrieved from a closed stream" do + io = IOSpecs.io_fixture("lines.txt", "r") + io.close + io.external_encoding.should equal(Encoding.default_external) + end + end + describe "with 'r' mode" do describe "when Encoding.default_internal is nil" do before :each do diff --git a/ruby/spec/ruby/core/io/fixtures/classes.rb b/ruby/spec/ruby/core/io/fixtures/classes.rb index 460dd6238..5d81d5fcd 100644 --- a/ruby/spec/ruby/core/io/fixtures/classes.rb +++ b/ruby/spec/ruby/core/io/fixtures/classes.rb @@ -1,6 +1,9 @@ # -*- encoding: utf-8 -*- module IOSpecs + THREAD_CLOSE_RETRIES = 10 + THREAD_CLOSE_ERROR_MESSAGE = 'stream closed in another thread' + class SubIO < IO end @@ -164,7 +167,7 @@ def initialize(io) @io = io end - def read(size, buf=nil) + def read(size, buf) @io.read size, buf end @@ -178,7 +181,7 @@ def initialize(io) @io = io end - def readpartial(size, buf=nil) + def readpartial(size, buf) @io.readpartial size, buf end diff --git a/ruby/spec/ruby/core/io/fixtures/copy_in_out.rb b/ruby/spec/ruby/core/io/fixtures/copy_in_out.rb new file mode 100644 index 000000000..b9d4085a4 --- /dev/null +++ b/ruby/spec/ruby/core/io/fixtures/copy_in_out.rb @@ -0,0 +1,2 @@ +STDOUT.sync = false +IO.copy_stream(STDIN, STDOUT) diff --git a/ruby/spec/ruby/core/io/gets_spec.rb b/ruby/spec/ruby/core/io/gets_spec.rb index 39b210847..a3cd180b6 100644 --- a/ruby/spec/ruby/core/io/gets_spec.rb +++ b/ruby/spec/ruby/core/io/gets_spec.rb @@ -41,7 +41,7 @@ ruby_version_is ''...'2.7' do it "returns tainted strings" do while line = @io.gets - line.tainted?.should == true + line.should.tainted? end end end @@ -67,7 +67,7 @@ ruby_version_is ''...'2.7' do it "returns tainted strings" do while line = @io.gets(nil) - line.tainted?.should == true + line.should.tainted? end end end @@ -103,7 +103,7 @@ ruby_version_is ''...'2.7' do it "returns tainted strings" do while line = @io.gets("") - line.tainted?.should == true + line.should.tainted? end end end @@ -129,7 +129,7 @@ ruby_version_is ''...'2.7' do it "returns tainted strings" do while line = @io.gets("la") - line.tainted?.should == true + line.should.tainted? end end end diff --git a/ruby/spec/ruby/core/io/initialize_spec.rb b/ruby/spec/ruby/core/io/initialize_spec.rb index c0d84765a..ba5bc117b 100644 --- a/ruby/spec/ruby/core/io/initialize_spec.rb +++ b/ruby/spec/ruby/core/io/initialize_spec.rb @@ -13,7 +13,7 @@ rm_r @name end - it "reassociates the IO instance with the new descriptor when passed a Fixnum" do + it "reassociates the IO instance with the new descriptor when passed an Integer" do fd = new_fd @name, "r:utf-8" @io.send :initialize, fd, 'r' @io.fileno.should == fd diff --git a/ruby/spec/ruby/core/io/internal_encoding_spec.rb b/ruby/spec/ruby/core/io/internal_encoding_spec.rb index 10ebf2870..60afaf2eb 100644 --- a/ruby/spec/ruby/core/io/internal_encoding_spec.rb +++ b/ruby/spec/ruby/core/io/internal_encoding_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe :io_internal_encoding, shared: true do describe "when Encoding.default_internal is not set" do @@ -112,6 +113,14 @@ Encoding.default_internal = @internal end + ruby_version_is '3.1' do + it "can be retrieved from a closed stream" do + io = IOSpecs.io_fixture("lines.txt", "r") + io.close + io.internal_encoding.should equal(Encoding.default_internal) + end + end + describe "with 'r' mode" do it_behaves_like :io_internal_encoding, nil, "r" end diff --git a/ruby/spec/ruby/core/io/ioctl_spec.rb b/ruby/spec/ruby/core/io/ioctl_spec.rb index e819a217a..8dcd9eb2c 100644 --- a/ruby/spec/ruby/core/io/ioctl_spec.rb +++ b/ruby/spec/ruby/core/io/ioctl_spec.rb @@ -20,12 +20,12 @@ end end - it "raises an Errno error when ioctl fails" do + it "raises a system call error when ioctl fails" do File.open(__FILE__, 'r') do |f| -> { # TIOCGWINSZ in /usr/include/asm-generic/ioctls.h f.ioctl 0x5413, nil - }.should raise_error(Errno::ENOTTY) + }.should raise_error(SystemCallError) end end end diff --git a/ruby/spec/ruby/core/io/lineno_spec.rb b/ruby/spec/ruby/core/io/lineno_spec.rb index 3d1b2275c..99266ecca 100644 --- a/ruby/spec/ruby/core/io/lineno_spec.rb +++ b/ruby/spec/ruby/core/io/lineno_spec.rb @@ -14,6 +14,24 @@ -> { IOSpecs.closed_io.lineno }.should raise_error(IOError) end + it "raises an IOError on a write-only stream" do + name = tmp("io_lineno.txt") + begin + File.open(name, 'w') do |f| + -> { f.lineno }.should raise_error(IOError) + end + ensure + rm_r name + end + end + + it "raises an IOError on a duplexed stream with the read side closed" do + IO.popen('cat', 'r+') do |p| + p.close_read + -> { p.lineno }.should raise_error(IOError) + end + end + it "returns the current line number" do @io.lineno.should == 0 @@ -40,6 +58,24 @@ -> { IOSpecs.closed_io.lineno = 5 }.should raise_error(IOError) end + it "raises an IOError on a write-only stream" do + name = tmp("io_lineno.txt") + begin + File.open(name, 'w') do |f| + -> { f.lineno = 0 }.should raise_error(IOError) + end + ensure + rm_r name + end + end + + it "raises an IOError on a duplexed stream with the read side closed" do + IO.popen('cat', 'r+') do |p| + p.close_read + -> { p.lineno = 0 }.should raise_error(IOError) + end + end + it "calls #to_int on a non-numeric argument" do obj = mock('123') obj.should_receive(:to_int).and_return(123) diff --git a/ruby/spec/ruby/core/io/lines_spec.rb b/ruby/spec/ruby/core/io/lines_spec.rb index a8b8023a2..5b29a1d07 100644 --- a/ruby/spec/ruby/core/io/lines_spec.rb +++ b/ruby/spec/ruby/core/io/lines_spec.rb @@ -2,41 +2,45 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "IO#lines" do - before :each do - @io = IOSpecs.io_fixture "lines.txt" - end - - after :each do - @io.close if @io - end +ruby_version_is ''...'3.0' do + describe "IO#lines" do + before :each do + @io = IOSpecs.io_fixture "lines.txt" + @verbose, $VERBOSE = $VERBOSE, nil + end - it "returns an Enumerator" do - @io.lines.should be_an_instance_of(Enumerator) - end + after :each do + $VERBOSE = @verbose + @io.close if @io + end - describe "when no block is given" do it "returns an Enumerator" do @io.lines.should be_an_instance_of(Enumerator) end - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - @io.lines.size.should == nil + describe "when no block is given" do + it "returns an Enumerator" do + @io.lines.should be_an_instance_of(Enumerator) + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + @io.lines.size.should == nil + end end end end - end - it "returns a line when accessed" do - enum = @io.lines - enum.first.should == IOSpecs.lines[0] - end + it "returns a line when accessed" do + enum = @io.lines + enum.first.should == IOSpecs.lines[0] + end - it "yields each line to the passed block" do - ScratchPad.record [] - @io.lines { |s| ScratchPad << s } - ScratchPad.recorded.should == IOSpecs.lines + it "yields each line to the passed block" do + ScratchPad.record [] + @io.lines { |s| ScratchPad << s } + ScratchPad.recorded.should == IOSpecs.lines + end end end diff --git a/ruby/spec/ruby/core/io/nonblock_spec.rb b/ruby/spec/ruby/core/io/nonblock_spec.rb new file mode 100644 index 000000000..e81ac10c5 --- /dev/null +++ b/ruby/spec/ruby/core/io/nonblock_spec.rb @@ -0,0 +1,70 @@ +require_relative '../../spec_helper' + +platform_is_not :windows do + describe "IO#nonblock?" do + before :all do + require 'io/nonblock' + end + + it "returns false for a file by default" do + File.open(__FILE__) do |f| + f.nonblock?.should == false + end + end + + ruby_version_is ""..."3.0" do + it "returns false for pipe by default" do + r, w = IO.pipe + begin + r.nonblock?.should == false + w.nonblock?.should == false + ensure + r.close + w.close + end + end + + it "returns false for socket by default" do + require 'socket' + TCPServer.open(0) do |socket| + socket.nonblock?.should == false + end + end + end + + ruby_version_is "3.0" do + it "returns true for pipe by default" do + r, w = IO.pipe + begin + r.nonblock?.should == true + w.nonblock?.should == true + ensure + r.close + w.close + end + end + + it "returns true for socket by default" do + require 'socket' + TCPServer.open(0) do |socket| + socket.nonblock?.should == true + end + end + end + end + + describe "IO#nonblock=" do + before :all do + require 'io/nonblock' + end + + it "changes the IO to non-blocking mode" do + File.open(__FILE__) do |f| + f.nonblock = true + f.nonblock?.should == true + f.nonblock = false + f.nonblock?.should == false + end + end + end +end diff --git a/ruby/spec/ruby/core/io/open_spec.rb b/ruby/spec/ruby/core/io/open_spec.rb index 94df5a5ef..d3a3961df 100644 --- a/ruby/spec/ruby/core/io/open_spec.rb +++ b/ruby/spec/ruby/core/io/open_spec.rb @@ -63,7 +63,7 @@ ScratchPad.recorded.should == :called end - it "does not propagate a IOError with 'closed stream' message raised by #close" do + it "does not propagate an IOError with 'closed stream' message raised by #close" do IO.open(@fd, "w") do |io| IOSpecs.io_mock(io, :close) do super() @@ -74,7 +74,7 @@ ScratchPad.recorded.should == :called end - it "does not set last error when a IOError with 'closed stream' raised by #close" do + it "does not set last error when an IOError with 'closed stream' raised by #close" do IO.open(@fd, "w") do |io| IOSpecs.io_mock(io, :close) do super() diff --git a/ruby/spec/ruby/core/io/pipe_spec.rb b/ruby/spec/ruby/core/io/pipe_spec.rb index a7dcb7fab..2f2cf06f4 100644 --- a/ruby/spec/ruby/core/io/pipe_spec.rb +++ b/ruby/spec/ruby/core/io/pipe_spec.rb @@ -44,8 +44,8 @@ r, w = IO.pipe do |_r, _w| [_r, _w] end - r.closed?.should == true - w.closed?.should == true + r.should.closed? + w.should.closed? end it "closes both IO objects when the block raises" do @@ -57,8 +57,8 @@ raise RuntimeError end end.should raise_error(RuntimeError) - r.closed?.should == true - w.closed?.should == true + r.should.closed? + w.should.closed? end it "allows IO objects to be closed within the block" do @@ -67,8 +67,8 @@ _w.close [_r, _w] end - r.closed?.should == true - w.closed?.should == true + r.should.closed? + w.should.closed? end end end diff --git a/ruby/spec/ruby/core/io/popen_spec.rb b/ruby/spec/ruby/core/io/popen_spec.rb index 4f873e61c..e9d32c5c7 100644 --- a/ruby/spec/ruby/core/io/popen_spec.rb +++ b/ruby/spec/ruby/core/io/popen_spec.rb @@ -77,10 +77,10 @@ Process.kill "KILL", pid @io.close platform_is_not :windows do - $?.signaled?.should == true + $?.should.signaled? end platform_is :windows do - $?.exited?.should == true + $?.should.exited? end end diff --git a/ruby/spec/ruby/core/io/pread_spec.rb b/ruby/spec/ruby/core/io/pread_spec.rb index bfe6472fe..43071d6a3 100644 --- a/ruby/spec/ruby/core/io/pread_spec.rb +++ b/ruby/spec/ruby/core/io/pread_spec.rb @@ -1,52 +1,50 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' -ruby_version_is "2.5" do - platform_is_not :windows do - describe "IO#pread" do - before :each do - @fname = tmp("io_pread.txt") - @contents = "1234567890" - touch(@fname) { |f| f.write @contents } - @file = File.open(@fname, "r+") - end - - after :each do - @file.close - rm_r @fname - end +platform_is_not :windows do + describe "IO#pread" do + before :each do + @fname = tmp("io_pread.txt") + @contents = "1234567890" + touch(@fname) { |f| f.write @contents } + @file = File.open(@fname, "r+") + end - it "accepts a length, and an offset" do - @file.pread(4, 0).should == "1234" - @file.pread(3, 4).should == "567" - end + after :each do + @file.close + rm_r @fname + end - it "accepts a length, an offset, and an output buffer" do - buffer = "foo" - @file.pread(3, 4, buffer) - buffer.should == "567" - end + it "accepts a length, and an offset" do + @file.pread(4, 0).should == "1234" + @file.pread(3, 4).should == "567" + end - it "does not advance the file pointer" do - @file.pread(4, 0).should == "1234" - @file.read.should == "1234567890" - end + it "accepts a length, an offset, and an output buffer" do + buffer = "foo" + @file.pread(3, 4, buffer) + buffer.should == "567" + end - it "raises EOFError if end-of-file is reached" do - -> { @file.pread(1, 10) }.should raise_error(EOFError) - end + it "does not advance the file pointer" do + @file.pread(4, 0).should == "1234" + @file.read.should == "1234567890" + end - it "raises IOError when file is not open in read mode" do - File.open(@fname, "w") do |file| - -> { file.pread(1, 1) }.should raise_error(IOError) - end - end + it "raises EOFError if end-of-file is reached" do + -> { @file.pread(1, 10) }.should raise_error(EOFError) + end - it "raises IOError when file is closed" do - file = File.open(@fname, "r+") - file.close + it "raises IOError when file is not open in read mode" do + File.open(@fname, "w") do |file| -> { file.pread(1, 1) }.should raise_error(IOError) end end + + it "raises IOError when file is closed" do + file = File.open(@fname, "r+") + file.close + -> { file.pread(1, 1) }.should raise_error(IOError) + end end end diff --git a/ruby/spec/ruby/core/io/print_spec.rb b/ruby/spec/ruby/core/io/print_spec.rb index 2021cd542..04e971ef6 100644 --- a/ruby/spec/ruby/core/io/print_spec.rb +++ b/ruby/spec/ruby/core/io/print_spec.rb @@ -1,15 +1,15 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe IO, "#print" do +describe "IO#print" do before :each do @old_separator = $\ - $\ = '->' + suppress_warning {$\ = '->'} @name = tmp("io_print") end after :each do - $\ = @old_separator + suppress_warning {$\ = @old_separator} rm_r @name end diff --git a/ruby/spec/ruby/core/io/puts_spec.rb b/ruby/spec/ruby/core/io/puts_spec.rb index 3e4b877b7..9a708fffe 100644 --- a/ruby/spec/ruby/core/io/puts_spec.rb +++ b/ruby/spec/ruby/core/io/puts_spec.rb @@ -16,7 +16,7 @@ def @io.write(str) ScratchPad.clear @io.close if @io rm_r @name - $/ = @before_separator + suppress_warning {$/ = @before_separator} end it "writes just a newline when given no args" do @@ -25,7 +25,7 @@ def @io.write(str) end it "writes just a newline when given just a newline" do - -> { $stdout.puts "\n" }.should output_to_fd("\n", STDOUT) + -> { $stdout.puts "\n" }.should output_to_fd("\n", $stdout) end it "writes empty string with a newline when given nil as an arg" do @@ -105,7 +105,7 @@ def @io.write(str) end it "ignores the $/ separator global" do - $/ = ":" + suppress_warning {$/ = ":"} @io.puts(5).should == nil ScratchPad.recorded.should == "5\n" end diff --git a/ruby/spec/ruby/core/io/pwrite_spec.rb b/ruby/spec/ruby/core/io/pwrite_spec.rb index 929ed0869..fe29d1e1f 100644 --- a/ruby/spec/ruby/core/io/pwrite_spec.rb +++ b/ruby/spec/ruby/core/io/pwrite_spec.rb @@ -1,45 +1,43 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' -ruby_version_is "2.5" do - platform_is_not :windows do - describe "IO#pwrite" do - before :each do - @fname = tmp("io_pwrite.txt") - @file = File.open(@fname, "w+") - end - - after :each do - @file.close - rm_r @fname - end +platform_is_not :windows do + describe "IO#pwrite" do + before :each do + @fname = tmp("io_pwrite.txt") + @file = File.open(@fname, "w+") + end - it "returns the number of bytes written" do - @file.pwrite("foo", 0).should == 3 - end + after :each do + @file.close + rm_r @fname + end - it "accepts a string and an offset" do - @file.pwrite("foo", 2) - @file.pread(3, 2).should == "foo" - end + it "returns the number of bytes written" do + @file.pwrite("foo", 0).should == 3 + end - it "does not advance the pointer in the file" do - @file.pwrite("bar", 3) - @file.write("foo") - @file.pread(6, 0).should == "foobar" - end + it "accepts a string and an offset" do + @file.pwrite("foo", 2) + @file.pread(3, 2).should == "foo" + end - it "raises IOError when file is not open in write mode" do - File.open(@fname, "r") do |file| - -> { file.pwrite("foo", 1) }.should raise_error(IOError) - end - end + it "does not advance the pointer in the file" do + @file.pwrite("bar", 3) + @file.write("foo") + @file.pread(6, 0).should == "foobar" + end - it "raises IOError when file is closed" do - file = File.open(@fname, "w+") - file.close + it "raises IOError when file is not open in write mode" do + File.open(@fname, "r") do |file| -> { file.pwrite("foo", 1) }.should raise_error(IOError) end end + + it "raises IOError when file is closed" do + file = File.open(@fname, "w+") + file.close + -> { file.pwrite("foo", 1) }.should raise_error(IOError) + end end end diff --git a/ruby/spec/ruby/core/io/read_nonblock_spec.rb b/ruby/spec/ruby/core/io/read_nonblock_spec.rb index 63ccab5a4..e50531d33 100644 --- a/ruby/spec/ruby/core/io/read_nonblock_spec.rb +++ b/ruby/spec/ruby/core/io/read_nonblock_spec.rb @@ -46,7 +46,7 @@ require 'io/nonblock' @write.write "abc" @read.read_nonblock(1).should == "a" - @read.nonblock?.should == true + @read.should.nonblock? end end diff --git a/ruby/spec/ruby/core/io/read_spec.rb b/ruby/spec/ruby/core/io/read_spec.rb index 1e9a8d2a4..841e693f3 100644 --- a/ruby/spec/ruby/core/io/read_spec.rb +++ b/ruby/spec/ruby/core/io/read_spec.rb @@ -216,7 +216,7 @@ it "is at end-of-file when everything has been read" do @io.read - @io.eof?.should == true + @io.should.eof? end it "reads the contents of a file" do diff --git a/ruby/spec/ruby/core/io/readlines_spec.rb b/ruby/spec/ruby/core/io/readlines_spec.rb index 0d4f00297..254f2927b 100644 --- a/ruby/spec/ruby/core/io/readlines_spec.rb +++ b/ruby/spec/ruby/core/io/readlines_spec.rb @@ -22,11 +22,11 @@ describe "when passed no arguments" do before :each do - @sep, $/ = $/, " " + suppress_warning {@sep, $/ = $/, " "} end after :each do - $/ = @sep + suppress_warning {$/ = @sep} end it "returns an Array containing lines based on $/" do @@ -101,31 +101,6 @@ @io.readlines(obj).should == IOSpecs.lines_r_separator end end - - describe "when passed a string that starts with a |" do - it "gets data from the standard out of the subprocess" do - cmd = "|sh -c 'echo hello;echo line2'" - platform_is :windows do - cmd = "|cmd.exe /C echo hello&echo line2" - end - lines = IO.readlines(cmd) - lines.should == ["hello\n", "line2\n"] - end - - platform_is_not :windows do - it "gets data from a fork when passed -" do - lines = IO.readlines("|-") - - if lines # parent - lines.should == ["hello\n", "from a fork\n"] - else - puts "hello" - puts "from a fork" - exit! - end - end - end - end end describe "IO#readlines" do @@ -169,6 +144,31 @@ $_.should == "test" end + describe "when passed a string that starts with a |" do + it "gets data from the standard out of the subprocess" do + cmd = "|sh -c 'echo hello;echo line2'" + platform_is :windows do + cmd = "|cmd.exe /C echo hello&echo line2" + end + lines = IO.readlines(cmd) + lines.should == ["hello\n", "line2\n"] + end + + platform_is_not :windows do + it "gets data from a fork when passed -" do + lines = IO.readlines("|-") + + if lines # parent + lines.should == ["hello\n", "from a fork\n"] + else + puts "hello" + puts "from a fork" + exit! + end + end + end + end + it_behaves_like :io_readlines, :readlines it_behaves_like :io_readlines_options_19, :readlines end @@ -184,7 +184,7 @@ after :each do Encoding.default_external = @external Encoding.default_internal = @internal - $/ = @dollar_slash + suppress_warning {$/ = @dollar_slash} end it "encodes lines using the default external encoding" do @@ -196,7 +196,7 @@ it "encodes lines using the default internal encoding, when set" do Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_16 - $/ = $/.encode Encoding::UTF_16 + suppress_warning {$/ = $/.encode Encoding::UTF_16} lines = IO.readlines(@name) lines.all? { |s| s.encoding == Encoding::UTF_16 }.should be_true end diff --git a/ruby/spec/ruby/core/io/reopen_spec.rb b/ruby/spec/ruby/core/io/reopen_spec.rb index faef80f51..8ff0f217f 100644 --- a/ruby/spec/ruby/core/io/reopen_spec.rb +++ b/ruby/spec/ruby/core/io/reopen_spec.rb @@ -150,11 +150,11 @@ @io.close_on_exec = true @io.reopen @other_name - @io.close_on_exec?.should == true + @io.should.close_on_exec? @io.close_on_exec = false @io.reopen @other_name - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "creates the file if it doesn't exist if the IO is opened in write mode" do @@ -293,12 +293,12 @@ def @io.to_io; flunk; end @other_io.close_on_exec = true @io.close_on_exec = true @io.reopen @other_io - @io.close_on_exec?.should == true + @io.should.close_on_exec? @other_io.close_on_exec = false @io.close_on_exec = false @io.reopen @other_io - @io.close_on_exec?.should == true + @io.should.close_on_exec? end it "may change the class of the instance" do diff --git a/ruby/spec/ruby/core/io/rewind_spec.rb b/ruby/spec/ruby/core/io/rewind_spec.rb index 954d56d30..649041afa 100644 --- a/ruby/spec/ruby/core/io/rewind_spec.rb +++ b/ruby/spec/ruby/core/io/rewind_spec.rb @@ -21,7 +21,7 @@ it "positions the instance to the beginning of input and clears EOF" do value = @io.read @io.rewind - @io.eof?.should == false + @io.should_not.eof? value.should == @io.read end diff --git a/ruby/spec/ruby/core/io/seek_spec.rb b/ruby/spec/ruby/core/io/seek_spec.rb index 7e9c30827..2fa4a73ac 100644 --- a/ruby/spec/ruby/core/io/seek_spec.rb +++ b/ruby/spec/ruby/core/io/seek_spec.rb @@ -44,21 +44,21 @@ it "moves the read position and clears EOF with SEEK_SET" do value = @io.read @io.seek(0, IO::SEEK_SET) - @io.eof?.should == false + @io.should_not.eof? value.should == @io.read end it "moves the read position and clears EOF with SEEK_CUR" do value = @io.read @io.seek(-1, IO::SEEK_CUR) - @io.eof?.should == false + @io.should_not.eof? value[-1].should == @io.read[0] end it "moves the read position and clears EOF with SEEK_END" do value = @io.read @io.seek(-1, IO::SEEK_END) - @io.eof?.should == false + @io.should_not.eof? value[-1].should == @io.read[0] end diff --git a/ruby/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/ruby/spec/ruby/core/io/set_encoding_by_bom_spec.rb new file mode 100644 index 000000000..7368ec767 --- /dev/null +++ b/ruby/spec/ruby/core/io/set_encoding_by_bom_spec.rb @@ -0,0 +1,77 @@ +require_relative '../../spec_helper' + +describe "IO#set_encoding_by_bom" do + before :each do + @name = tmp('io_set_encoding_by_bom.txt') + touch(@name) + @io = new_io(@name, 'rb') + end + + after :each do + @io.close unless @io.closed? + rm_r @name + end + + ruby_version_is "2.7" do + it "returns the result encoding if found BOM UTF-8 sequence" do + File.binwrite(@name, "\u{FEFF}abc") + + @io.set_encoding_by_bom.should == Encoding::UTF_8 + @io.external_encoding.should == Encoding::UTF_8 + end + + it "returns the result encoding if found BOM UTF_16LE sequence" do + File.binwrite(@name, "\xFF\xFEabc") + + @io.set_encoding_by_bom.should == Encoding::UTF_16LE + @io.external_encoding.should == Encoding::UTF_16LE + end + + it "returns the result encoding if found BOM UTF_16BE sequence" do + File.binwrite(@name, "\xFE\xFFabc") + + @io.set_encoding_by_bom.should == Encoding::UTF_16BE + @io.external_encoding.should == Encoding::UTF_16BE + end + + it "returns the result encoding if found BOM UTF_32LE sequence" do + File.binwrite(@name, "\xFF\xFE\x00\x00abc") + + @io.set_encoding_by_bom.should == Encoding::UTF_32LE + @io.external_encoding.should == Encoding::UTF_32LE + end + + it "returns the result encoding if found BOM UTF_32BE sequence" do + File.binwrite(@name, "\x00\x00\xFE\xFFabc") + + @io.set_encoding_by_bom.should == Encoding::UTF_32BE + @io.external_encoding.should == Encoding::UTF_32BE + end + + it "returns nil if found BOM sequence not provided" do + File.write(@name, "abc") + + @io.set_encoding_by_bom.should == nil + end + + it 'returns exception if io not in binary mode' do + not_binary_io = new_io(@name, 'r') + + -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode') + ensure + not_binary_io.close + end + + it 'returns exception if encoding already set' do + @io.set_encoding("utf-8") + + -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already') + end + + it 'returns exception if encoding conversion is already set' do + @io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE) + + -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set') + end + end +end diff --git a/ruby/spec/ruby/core/io/shared/each.rb b/ruby/spec/ruby/core/io/shared/each.rb index 0b2dfa354..91766fbe0 100644 --- a/ruby/spec/ruby/core/io/shared/each.rb +++ b/ruby/spec/ruby/core/io/shared/each.rb @@ -168,12 +168,12 @@ before :each do @io = IOSpecs.io_fixture "lines.txt" ScratchPad.record [] - @sep, $/ = $/, " " + suppress_warning {@sep, $/ = $/, " "} end after :each do @io.close if @io - $/ = @sep + suppress_warning {$/ = @sep} end it "uses $/ as the default line separator" do diff --git a/ruby/spec/ruby/core/io/shared/new.rb b/ruby/spec/ruby/core/io/shared/new.rb index a7b4fc1cb..f2a0970a4 100644 --- a/ruby/spec/ruby/core/io/shared/new.rb +++ b/ruby/spec/ruby/core/io/shared/new.rb @@ -18,7 +18,7 @@ rm_r @name end - it "creates an IO instance from a Fixnum argument" do + it "creates an IO instance from an Integer argument" do @io = IO.send(@method, @fd, "w") @io.should be_an_instance_of(IO) end @@ -55,7 +55,7 @@ end end - it "calls #to_int on an object to convert to a Fixnum" do + it "calls #to_int on an object to convert to an Integer" do obj = mock("file descriptor") obj.should_receive(:to_int).and_return(@fd) @io = IO.send(@method, obj, "w") @@ -148,22 +148,22 @@ it "sets binmode from mode string" do @io = IO.send(@method, @fd, 'wb') - @io.binmode?.should == true + @io.should.binmode? end it "does not set binmode without being asked" do @io = IO.send(@method, @fd, 'w') - @io.binmode?.should == false + @io.should_not.binmode? end it "sets binmode from :binmode option" do @io = IO.send(@method, @fd, 'w', binmode: true) - @io.binmode?.should == true + @io.should.binmode? end it "does not set binmode from false :binmode" do @io = IO.send(@method, @fd, 'w', binmode: false) - @io.binmode?.should == false + @io.should_not.binmode? end it "sets external encoding to binary with binmode in mode string" do @@ -197,11 +197,21 @@ @io.internal_encoding.to_s.should == 'IBM866' end - it "accepts nil options" do - @io = suppress_keyword_warning do - IO.send(@method, @fd, 'w', nil) + ruby_version_is ''...'3.0' do + it "accepts nil options" do + @io = suppress_keyword_warning do + IO.send(@method, @fd, 'w', nil) + end + @io.write("foo").should == 3 + end + end + + ruby_version_is '3.0' do + it "raises ArgumentError for nil options" do + -> { + IO.send(@method, @fd, 'w', nil) + }.should raise_error(ArgumentError) end - @io.write("foo").should == 3 end it "coerces mode with #to_str" do @@ -260,13 +270,13 @@ it "accepts an :autoclose option" do @io = IO.send(@method, @fd, 'w', autoclose: false) - @io.autoclose?.should == false + @io.should_not.autoclose? @io.autoclose = true end it "accepts any truthy option :autoclose" do @io = IO.send(@method, @fd, 'w', autoclose: 42) - @io.autoclose?.should == true + @io.should.autoclose? end end @@ -372,11 +382,21 @@ }.should raise_error(ArgumentError) end - it "raises TypeError if passed a hash for mode and nil for options" do - -> { - suppress_keyword_warning do + ruby_version_is ''...'3.0' do + it "raises TypeError if passed a hash for mode and nil for options" do + -> { + suppress_keyword_warning do + @io = IO.send(@method, @fd, {mode: 'w'}, nil) + end + }.should raise_error(TypeError) + end + end + + ruby_version_is '3.0' do + it "raises ArgumentError if passed a hash for mode and nil for options" do + -> { @io = IO.send(@method, @fd, {mode: 'w'}, nil) - end - }.should raise_error(TypeError) + }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/core/io/shared/pos.rb b/ruby/spec/ruby/core/io/shared/pos.rb index fb6d8087b..d83a6c669 100644 --- a/ruby/spec/ruby/core/io/shared/pos.rb +++ b/ruby/spec/ruby/core/io/shared/pos.rb @@ -27,7 +27,7 @@ io.read 1 io.read 1 io.send(@method) - io.eof?.should == false + io.should_not.eof? end end end @@ -60,7 +60,7 @@ end end - it "does not accept Bignums that don't fit in a C long" do + it "does not accept Integers that don't fit in a C long" do File.open @fname do |io| -> { io.send @method, 2**128 }.should raise_error(RangeError) end diff --git a/ruby/spec/ruby/core/io/shared/readlines.rb b/ruby/spec/ruby/core/io/shared/readlines.rb index de803f42e..8e4a73bb9 100644 --- a/ruby/spec/ruby/core/io/shared/readlines.rb +++ b/ruby/spec/ruby/core/io/shared/readlines.rb @@ -54,22 +54,22 @@ (result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator end - describe "when the object is a Fixnum" do + describe "when the object is an Integer" do before :each do @sep = $/ end after :each do - $/ = @sep + suppress_warning {$/ = @sep} end it "defaults to $/ as the separator" do - $/ = " " + suppress_warning {$/ = " "} result = IO.send(@method, @name, 10, &@object) (result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit end - it "uses the object as a limit if it is a Fixnum" do + it "uses the object as a limit if it is an Integer" do result = IO.send(@method, @name, 10, &@object) (result ? result : ScratchPad.recorded).should == IOSpecs.lines_limit end @@ -96,7 +96,7 @@ end describe "when passed name, object, object" do - describe "when the first object is a Fixnum" do + describe "when the first object is an Integer" do it "uses the second object as an options Hash" do -> do IO.send(@method, @filename, 10, mode: "w", &@object) @@ -113,7 +113,7 @@ end describe "when the first object is a String" do - it "uses the second object as a limit if it is a Fixnum" do + it "uses the second object as a limit if it is an Integer" do result = IO.send(@method, @name, " ", 10, &@object) (result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit end @@ -140,7 +140,7 @@ end end - describe "when the first object is not a String or Fixnum" do + describe "when the first object is not a String or Integer" do it "calls #to_str to convert the object to a String" do sep = mock("io readlines separator") sep.should_receive(:to_str).at_least(1).and_return(" ") @@ -148,7 +148,7 @@ (result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit end - it "uses the second object as a limit if it is a Fixnum" do + it "uses the second object as a limit if it is an Integer" do result = IO.send(@method, @name, " ", 10, mode: "r", &@object) (result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit end diff --git a/ruby/spec/ruby/core/io/sysopen_spec.rb b/ruby/spec/ruby/core/io/sysopen_spec.rb index 4607d1368..7ad379df3 100644 --- a/ruby/spec/ruby/core/io/sysopen_spec.rb +++ b/ruby/spec/ruby/core/io/sysopen_spec.rb @@ -13,7 +13,7 @@ it "returns the file descriptor for a given path" do @fd = IO.sysopen(@filename, "w") - @fd.should be_kind_of(Fixnum) + @fd.should be_kind_of(Integer) @fd.should_not equal(0) end @@ -21,7 +21,7 @@ platform_is_not :windows do it "works on directories" do @fd = IO.sysopen(tmp("")) # /tmp - @fd.should be_kind_of(Fixnum) + @fd.should be_kind_of(Integer) @fd.should_not equal(0) end end diff --git a/ruby/spec/ruby/core/io/sysread_spec.rb b/ruby/spec/ruby/core/io/sysread_spec.rb index 024200efe..8201ad47c 100644 --- a/ruby/spec/ruby/core/io/sysread_spec.rb +++ b/ruby/spec/ruby/core/io/sysread_spec.rb @@ -50,6 +50,11 @@ @file.sysread(5).should == "56789" end + it "raises an error when called after buffered reads" do + @file.readline + -> { @file.sysread(5) }.should raise_error(IOError) + end + it "reads normally even when called immediately after a buffered IO#read" do @file.read(15) @file.sysread(5).should == "56789" diff --git a/ruby/spec/ruby/core/io/sysseek_spec.rb b/ruby/spec/ruby/core/io/sysseek_spec.rb index df894734e..e631939bc 100644 --- a/ruby/spec/ruby/core/io/sysseek_spec.rb +++ b/ruby/spec/ruby/core/io/sysseek_spec.rb @@ -26,6 +26,11 @@ -> { @io.sysseek(-5, IO::SEEK_CUR) }.should raise_error(IOError) end + it "seeks normally even when called immediately after a buffered IO#read" do + @io.read(15) + @io.sysseek(-5, IO::SEEK_CUR).should == 10 + end + it "moves the read position relative to the start with SEEK_SET" do @io.sysseek(43, IO::SEEK_SET) @io.readline.should == "Aquí está la línea tres.\n" diff --git a/ruby/spec/ruby/core/io/ungetbyte_spec.rb b/ruby/spec/ruby/core/io/ungetbyte_spec.rb index 1971dee53..776707205 100644 --- a/ruby/spec/ruby/core/io/ungetbyte_spec.rb +++ b/ruby/spec/ruby/core/io/ungetbyte_spec.rb @@ -36,20 +36,7 @@ @io.getbyte.should == 97 end - ruby_version_is ''...'2.6' do - it "puts back one byte for a Fixnum argument..." do - @io.ungetbyte(4095).should be_nil - @io.getbyte.should == 255 - end - - it "... but not for Bignum argument (eh?)" do - -> { - @io.ungetbyte(0x4f7574206f6620636861722072616e6765) - }.should raise_error(TypeError) - end - end - - ruby_version_is '2.6'...'2.6.1' do + ruby_version_is ''...'2.6.1' do it "is an RangeError if the integer is not in 8bit" do for i in [4095, 0x4f7574206f6620636861722072616e6765] do -> { @io.ungetbyte(i) }.should raise_error(RangeError) @@ -66,6 +53,10 @@ end end + it "raises IOError on stream not opened for reading" do + -> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading") + end + it "raises an IOError if the IO is closed" do @io.close -> { @io.ungetbyte(42) }.should raise_error(IOError) diff --git a/ruby/spec/ruby/core/io/ungetc_spec.rb b/ruby/spec/ruby/core/io/ungetc_spec.rb index 34d4caf74..a05d80ee9 100644 --- a/ruby/spec/ruby/core/io/ungetc_spec.rb +++ b/ruby/spec/ruby/core/io/ungetc_spec.rb @@ -74,10 +74,10 @@ touch(@empty) File.open(@empty) { |empty| - empty.eof?.should == true + empty.should.eof? empty.getc.should == nil empty.ungetc(100) - empty.eof?.should == false + empty.should_not.eof? } end @@ -103,10 +103,19 @@ -> { @io.sysread(1) }.should raise_error(IOError) end - it "does not affect the stream and returns nil when passed nil" do - @io.getc.should == ?V - @io.ungetc(nil) - @io.getc.should == ?o + ruby_version_is "0"..."3.0" do + it "does not affect the stream and returns nil when passed nil" do + @io.getc.should == ?V + @io.ungetc(nil) + @io.getc.should == ?o + end + end + + ruby_version_is "3.0" do + it "raises TypeError if passed nil" do + @io.getc.should == ?V + proc{@io.ungetc(nil)}.should raise_error(TypeError) + end end it "puts one or more characters back in the stream" do @@ -127,6 +136,10 @@ @io.ungetc(100).should be_nil end + it "raises IOError on stream not opened for reading" do + -> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading") + end + it "raises IOError on closed stream" do @io.getc @io.close diff --git a/ruby/spec/ruby/core/io/write_nonblock_spec.rb b/ruby/spec/ruby/core/io/write_nonblock_spec.rb index 5474e5c6c..a8b9ce0a3 100644 --- a/ruby/spec/ruby/core/io/write_nonblock_spec.rb +++ b/ruby/spec/ruby/core/io/write_nonblock_spec.rb @@ -79,7 +79,7 @@ it 'sets the IO in nonblock mode' do require 'io/nonblock' @write.write_nonblock('a') - @write.nonblock?.should == true + @write.should.nonblock? end end end diff --git a/ruby/spec/ruby/core/io/write_spec.rb b/ruby/spec/ruby/core/io/write_spec.rb index b28b58201..60e66e998 100644 --- a/ruby/spec/ruby/core/io/write_spec.rb +++ b/ruby/spec/ruby/core/io/write_spec.rb @@ -90,6 +90,12 @@ IO.write(@filename, 'hi', mode: "w", encoding: Encoding::UTF_32LE).should == 8 end + it "writes the file with the permissions in the :perm parameter" do + rm_r @filename + IO.write(@filename, 'write :perm spec', mode: "w", perm: 0o755).should == 16 + (File.stat(@filename).mode & 0o777) == 0o755 + end + it "writes binary data if no encoding is given" do IO.write(@filename, 'Hëllö'.encode('ISO-8859-1')) xEB = [235].pack('C*') @@ -126,14 +132,12 @@ describe "IO#write" do it_behaves_like :io_write, :write - ruby_version_is "2.5" do - it "accepts multiple arguments" do - IO.pipe do |r, w| - w.write("foo", "bar") - w.close + it "accepts multiple arguments" do + IO.pipe do |r, w| + w.write("foo", "bar") + w.close - r.read.should == "foobar" - end + r.read.should == "foobar" end end end diff --git a/ruby/spec/ruby/core/kernel/Complex_spec.rb b/ruby/spec/ruby/core/kernel/Complex_spec.rb index 37f984393..4f043526b 100644 --- a/ruby/spec/ruby/core/kernel/Complex_spec.rb +++ b/ruby/spec/ruby/core/kernel/Complex_spec.rb @@ -139,48 +139,46 @@ end end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and [Numeric]" do - it "returns a complex number" do - Complex("123", exception: false).should == Complex(123) - end + describe "when passed exception: false" do + describe "and [Numeric]" do + it "returns a complex number" do + Complex("123", exception: false).should == Complex(123) end + end - describe "and [non-Numeric]" do - it "swallows an error" do - Complex(:sym, exception: false).should == nil - end + describe "and [non-Numeric]" do + it "swallows an error" do + Complex(:sym, exception: false).should == nil end + end - describe "and [non-Numeric, Numeric] argument" do - it "throws a TypeError" do - -> { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real") - end + describe "and [non-Numeric, Numeric] argument" do + it "throws a TypeError" do + -> { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real") end + end - describe "and [anything, non-Numeric] argument" do - it "swallows an error" do - Complex("a", :sym, exception: false).should == nil - Complex(:sym, :sym, exception: false).should == nil - Complex(0, :sym, exception: false).should == nil - end + describe "and [anything, non-Numeric] argument" do + it "swallows an error" do + Complex("a", :sym, exception: false).should == nil + Complex(:sym, :sym, exception: false).should == nil + Complex(0, :sym, exception: false).should == nil end + end - describe "and non-numeric String arguments" do - it "swallows an error" do - Complex("a", "b", exception: false).should == nil - Complex("a", 0, exception: false).should == nil - Complex(0, "b", exception: false).should == nil - end + describe "and non-numeric String arguments" do + it "swallows an error" do + Complex("a", "b", exception: false).should == nil + Complex("a", 0, exception: false).should == nil + Complex(0, "b", exception: false).should == nil end + end - describe "and nil arguments" do - it "swallows an error" do - Complex(nil, exception: false).should == nil - Complex(0, nil, exception: false).should == nil - Complex(nil, 0, exception: false).should == nil - end + describe "and nil arguments" do + it "swallows an error" do + Complex(nil, exception: false).should == nil + Complex(0, nil, exception: false).should == nil + Complex(nil, 0, exception: false).should == nil end end end diff --git a/ruby/spec/ruby/core/kernel/Float_spec.rb b/ruby/spec/ruby/core/kernel/Float_spec.rb index 6580c3813..015bcb33d 100644 --- a/ruby/spec/ruby/core/kernel/Float_spec.rb +++ b/ruby/spec/ruby/core/kernel/Float_spec.rb @@ -54,6 +54,12 @@ -> { @object.send(:Float, "float") }.should raise_error(ArgumentError) end + it "raises an ArgumentError for a String with string in error message" do + -> { @object.send(:Float, "foo") }.should raise_error(ArgumentError) { |e| + e.message.should == 'invalid value for Float(): "foo"' + } + end + it "raises an ArgumentError if there are two decimal points in the String" do -> { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError) end @@ -300,27 +306,25 @@ def to_f() 1.2 end -> { @object.send(:Float, c) }.should raise_error(RangeError) end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and valid input" do - it "returns a Float number" do - @object.send(:Float, 1, exception: false).should == 1.0 - @object.send(:Float, "1", exception: false).should == 1.0 - @object.send(:Float, "1.23", exception: false).should == 1.23 - end + describe "when passed exception: false" do + describe "and valid input" do + it "returns a Float number" do + @object.send(:Float, 1, exception: false).should == 1.0 + @object.send(:Float, "1", exception: false).should == 1.0 + @object.send(:Float, "1.23", exception: false).should == 1.23 end + end - describe "and invalid input" do - it "swallows an error" do - @object.send(:Float, "abc", exception: false).should == nil - @object.send(:Float, :sym, exception: false).should == nil - end + describe "and invalid input" do + it "swallows an error" do + @object.send(:Float, "abc", exception: false).should == nil + @object.send(:Float, :sym, exception: false).should == nil end + end - describe "and nil" do - it "swallows it" do - @object.send(:Float, nil, exception: false).should == nil - end + describe "and nil" do + it "swallows it" do + @object.send(:Float, nil, exception: false).should == nil end end end diff --git a/ruby/spec/ruby/core/kernel/Integer_spec.rb b/ruby/spec/ruby/core/kernel/Integer_spec.rb index 59b41d37e..2c78e2742 100644 --- a/ruby/spec/ruby/core/kernel/Integer_spec.rb +++ b/ruby/spec/ruby/core/kernel/Integer_spec.rb @@ -10,38 +10,27 @@ Integer(100).should == 100 end - ruby_version_is ""..."2.6" do - it "uncritically return the value of to_int even if it is not an Integer" do - obj = mock("object") - obj.should_receive(:to_int).and_return("1") - obj.should_not_receive(:to_i) - Integer(obj).should == "1" - end + it "raises a TypeError when to_int returns not-an-Integer object and to_i returns nil" do + obj = mock("object") + obj.should_receive(:to_int).and_return("1") + obj.should_receive(:to_i).and_return(nil) + -> { Integer(obj) }.should raise_error(TypeError) end - ruby_version_is "2.6" do - it "raises a TypeError when to_int returns not-an-Integer object and to_i returns nil" do - obj = mock("object") - obj.should_receive(:to_int).and_return("1") - obj.should_receive(:to_i).and_return(nil) - -> { Integer(obj) }.should raise_error(TypeError) - end - - it "return a result of to_i when to_int does not return an Integer" do - obj = mock("object") - obj.should_receive(:to_int).and_return("1") - obj.should_receive(:to_i).and_return(42) - Integer(obj).should == 42 - end + it "return a result of to_i when to_int does not return an Integer" do + obj = mock("object") + obj.should_receive(:to_int).and_return("1") + obj.should_receive(:to_i).and_return(42) + Integer(obj).should == 42 end it "raises a TypeError when passed nil" do -> { Integer(nil) }.should raise_error(TypeError) end - it "returns a Fixnum or Bignum object" do - Integer(2).should be_an_instance_of(Fixnum) - Integer(9**99).should be_an_instance_of(Bignum) + it "returns an Integer object" do + Integer(2).should be_an_instance_of(Integer) + Integer(9**99).should be_an_instance_of(Integer) end it "truncates Floats" do @@ -100,59 +89,57 @@ -> { Integer(infinity_value) }.should raise_error(FloatDomainError) end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and to_i returns a value that is not an Integer" do - it "swallows an error" do - obj = mock("object") - obj.should_receive(:to_i).and_return("1") - Integer(obj, exception: false).should == nil - end + describe "when passed exception: false" do + describe "and to_i returns a value that is not an Integer" do + it "swallows an error" do + obj = mock("object") + obj.should_receive(:to_i).and_return("1") + Integer(obj, exception: false).should == nil end + end - describe "and no to_int or to_i methods exist" do - it "swallows an error" do - obj = mock("object") - Integer(obj, exception: false).should == nil - end + describe "and no to_int or to_i methods exist" do + it "swallows an error" do + obj = mock("object") + Integer(obj, exception: false).should == nil end + end - describe "and to_int returns nil and no to_i exists" do - it "swallows an error" do - obj = mock("object") - obj.should_receive(:to_i).and_return(nil) - Integer(obj, exception: false).should == nil - end + describe "and to_int returns nil and no to_i exists" do + it "swallows an error" do + obj = mock("object") + obj.should_receive(:to_i).and_return(nil) + Integer(obj, exception: false).should == nil end + end - describe "and passed NaN" do - it "swallows an error" do - Integer(nan_value, exception: false).should == nil - end + describe "and passed NaN" do + it "swallows an error" do + Integer(nan_value, exception: false).should == nil end + end - describe "and passed Infinity" do - it "swallows an error" do - Integer(infinity_value, exception: false).should == nil - end + describe "and passed Infinity" do + it "swallows an error" do + Integer(infinity_value, exception: false).should == nil end + end - describe "and passed nil" do - it "swallows an error" do - Integer(nil, exception: false).should == nil - end + describe "and passed nil" do + it "swallows an error" do + Integer(nil, exception: false).should == nil end + end - describe "and passed a String that contains numbers" do - it "normally parses it and returns an Integer" do - Integer("42", exception: false).should == 42 - end + describe "and passed a String that contains numbers" do + it "normally parses it and returns an Integer" do + Integer("42", exception: false).should == 42 end + end - describe "and passed a String that can't be converted to an Integer" do - it "swallows an error" do - Integer("abc", exception: false).should == nil - end + describe "and passed a String that can't be converted to an Integer" do + it "swallows an error" do + Integer("abc", exception: false).should == nil end end end @@ -246,30 +233,28 @@ -> { Integer("") }.should raise_error(ArgumentError) end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and multiple leading -s" do - it "swallows an error" do - Integer("---1", exception: false).should == nil - end + describe "when passed exception: false" do + describe "and multiple leading -s" do + it "swallows an error" do + Integer("---1", exception: false).should == nil end + end - describe "and multiple trailing -s" do - it "swallows an error" do - Integer("1---", exception: false).should == nil - end + describe "and multiple trailing -s" do + it "swallows an error" do + Integer("1---", exception: false).should == nil end + end - describe "and an argument that contains a period" do - it "swallows an error" do - Integer("0.0", exception: false).should == nil - end + describe "and an argument that contains a period" do + it "swallows an error" do + Integer("0.0", exception: false).should == nil end + end - describe "and an empty string" do - it "swallows an error" do - Integer("", exception: false).should == nil - end + describe "and an empty string" do + it "swallows an error" do + Integer("", exception: false).should == nil end end end @@ -594,20 +579,18 @@ end end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and valid argument" do - it "returns an Integer number" do - Integer("100", 10, exception: false).should == 100 - Integer("100", 2, exception: false).should == 4 - end + describe "when passed exception: false" do + describe "and valid argument" do + it "returns an Integer number" do + Integer("100", 10, exception: false).should == 100 + Integer("100", 2, exception: false).should == 4 end + end - describe "and invalid argument" do - it "swallows an error" do - Integer("999", 2, exception: false).should == nil - Integer("abc", 10, exception: false).should == nil - end + describe "and invalid argument" do + it "swallows an error" do + Integer("999", 2, exception: false).should == nil + Integer("abc", 10, exception: false).should == nil end end end diff --git a/ruby/spec/ruby/core/kernel/__dir___spec.rb b/ruby/spec/ruby/core/kernel/__dir___spec.rb index 3c3427727..324792a40 100644 --- a/ruby/spec/ruby/core/kernel/__dir___spec.rb +++ b/ruby/spec/ruby/core/kernel/__dir___spec.rb @@ -5,6 +5,13 @@ __dir__.should == File.realpath(File.dirname(__FILE__)) end + it "returns the expanded path of the directory when used in the main script" do + fixtures_dir = File.dirname(fixture(__FILE__, '__dir__.rb')) + Dir.chdir(fixtures_dir) do + ruby_exe("__dir__.rb").should == "__dir__.rb\n#{fixtures_dir}\n" + end + end + context "when used in eval with a given filename" do it "returns File.dirname(filename)" do eval("__dir__", nil, "foo.rb").should == "." @@ -12,9 +19,19 @@ end end - context "when used in eval with top level binding" do - it "returns the real name of the directory containing the currently-executing file" do - eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__)) + ruby_version_is ""..."3.0" do + context "when used in eval with top level binding" do + it "returns the real name of the directory containing the currently-executing file" do + eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__)) + end + end + end + + ruby_version_is "3.0" do + context "when used in eval with top level binding" do + it "returns nil" do + eval("__dir__", binding).should == nil + end end end end diff --git a/ruby/spec/ruby/core/kernel/at_exit_spec.rb b/ruby/spec/ruby/core/kernel/at_exit_spec.rb index 21149f965..a784c1ae1 100644 --- a/ruby/spec/ruby/core/kernel/at_exit_spec.rb +++ b/ruby/spec/ruby/core/kernel/at_exit_spec.rb @@ -23,7 +23,7 @@ it "gives access to the last raised exception" do code = <<-EOC at_exit do - puts "The exception matches: \#{$! == $exception}" + puts "The exception matches: \#{$! == $exception} (message=\#{$!.message})" end begin @@ -33,10 +33,36 @@ end EOC - result = ruby_exe(code, args: "2>&1", escape: true) - result.should =~ /The exception matches: true/ + result = ruby_exe(code, args: "2>&1", exit_status: 1) + result.lines.should.include?("The exception matches: true (message=foo)\n") end + it "both exceptions in at_exit and in the main script are printed" do + code = 'at_exit { raise "at_exit_error" }; raise "main_script_error"' + result = ruby_exe(code, args: "2>&1", exit_status: 1) + result.should.include?('at_exit_error (RuntimeError)') + result.should.include?('main_script_error (RuntimeError)') + end + + it "decides the exit status if both at_exit and the main script raise SystemExit" do + ruby_exe('at_exit { exit 43 }; exit 42', args: "2>&1", exit_status: 43) + $?.exitstatus.should == 43 + end + + it "runs all at_exit even if some raise exceptions" do + code = 'at_exit { STDERR.puts "last" }; at_exit { exit 43 }; at_exit { STDERR.puts "first" }; exit 42' + result = ruby_exe(code, args: "2>&1", exit_status: 43) + result.should == "first\nlast\n" + $?.exitstatus.should == 43 + end + + it "runs at_exit handlers even if the main script fails to parse" do + script = fixture(__FILE__, "at_exit.rb") + result = ruby_exe('{', options: "-r#{script}", args: "2>&1", exit_status: 1) + $?.should_not.success? + result.should.include?("at_exit ran\n") + result.should.include?("syntax error") + end end describe "Kernel#at_exit" do diff --git a/ruby/spec/ruby/core/kernel/autoload_spec.rb b/ruby/spec/ruby/core/kernel/autoload_spec.rb index 68732a69e..0404caec6 100644 --- a/ruby/spec/ruby/core/kernel/autoload_spec.rb +++ b/ruby/spec/ruby/core/kernel/autoload_spec.rb @@ -56,9 +56,24 @@ def check_autoload(const) end end + describe "inside a Class.new method body" do + # NOTE: this spec is being discussed in https://github.com/ruby/spec/pull/839 + it "should define on the new anonymous class" do + cls = Class.new do + def go + autoload :Object, 'bogus' + autoload? :Object + end + end + + cls.new.go.should == 'bogus' + cls.autoload?(:Object).should == 'bogus' + end + end + describe "when Object is frozen" do - it "raises a #{frozen_error_class} before defining the constant" do - ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil" + it "raises a FrozenError before defining the constant" do + ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "FrozenError - nil" end end diff --git a/ruby/spec/ruby/core/kernel/backtick_spec.rb b/ruby/spec/ruby/core/kernel/backtick_spec.rb index 5ab0fb0ee..834d5636c 100644 --- a/ruby/spec/ruby/core/kernel/backtick_spec.rb +++ b/ruby/spec/ruby/core/kernel/backtick_spec.rb @@ -36,20 +36,24 @@ end platform_is_not :windows do + it "handles invalid UTF-8 bytes in command" do + `echo "testing\xC2 a non UTF-8 string"`.b.should == "testing\xC2 a non UTF-8 string\n".b + end + it "sets $? to the exit status of the executed sub-process" do ip = 'world' `echo disc #{ip}` $?.should be_kind_of(Process::Status) - $?.stopped?.should == false - $?.exited?.should == true + $?.should_not.stopped? + $?.should.exited? $?.exitstatus.should == 0 - $?.success?.should == true + $?.should.success? `echo disc #{ip}; exit 99` $?.should be_kind_of(Process::Status) - $?.stopped?.should == false - $?.exited?.should == true + $?.should_not.stopped? + $?.should.exited? $?.exitstatus.should == 99 - $?.success?.should == false + $?.should_not.success? end end @@ -58,16 +62,16 @@ ip = 'world' `echo disc #{ip}` $?.should be_kind_of(Process::Status) - $?.stopped?.should == false - $?.exited?.should == true + $?.should_not.stopped? + $?.should.exited? $?.exitstatus.should == 0 - $?.success?.should == true + $?.should.success? `echo disc #{ip}& exit 99` $?.should be_kind_of(Process::Status) - $?.stopped?.should == false - $?.exited?.should == true + $?.should_not.stopped? + $?.should.exited? $?.exitstatus.should == 99 - $?.success?.should == false + $?.should_not.success? end end end diff --git a/ruby/spec/ruby/core/kernel/caller_locations_spec.rb b/ruby/spec/ruby/core/kernel/caller_locations_spec.rb index 4de6c2ffd..3ec8f0f43 100644 --- a/ruby/spec/ruby/core/kernel/caller_locations_spec.rb +++ b/ruby/spec/ruby/core/kernel/caller_locations_spec.rb @@ -7,7 +7,7 @@ end it 'returns an Array of caller locations' do - KernelSpecs::CallerLocationsTest.locations.empty?.should == false + KernelSpecs::CallerLocationsTest.locations.should_not.empty? end it 'returns an Array of caller locations using a custom offset' do @@ -22,6 +22,44 @@ locations.length.should == 1 end + it "can be called with a range" do + locations1 = caller_locations(0) + locations2 = caller_locations(2..4) + locations1[2..4].map(&:to_s).should == locations2.map(&:to_s) + end + + it "works with endless ranges" do + locations1 = caller_locations(0) + locations2 = caller_locations(eval("(2..)")) + locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s) + end + + ruby_version_is "2.7" do + it "works with beginless ranges" do + locations1 = caller_locations(0) + locations2 = caller_locations(eval("(...5)")) + locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(...5)")].map(&:to_s)[eval("(2..)")] + end + end + + it "can be called with a range whose end is negative" do + locations1 = caller_locations(0) + locations2 = caller_locations(2..-1) + locations3 = caller_locations(2..-2) + locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s) + locations1[2..-2].map(&:to_s).should == locations3.map(&:to_s) + end + + it "must return nil if omitting more locations than available" do + caller_locations(100).should == nil + caller_locations(100..-1).should == nil + end + + it "must return [] if omitting exactly the number of locations available" do + omit = caller_locations(0).length + caller_locations(omit).should == [] + end + it 'returns the locations as Thread::Backtrace::Location instances' do locations = KernelSpecs::CallerLocationsTest.locations @@ -29,4 +67,20 @@ location.kind_of?(Thread::Backtrace::Location).should == true end end + + it "must return the same locations when called with 1..-1 and when called with no arguments" do + caller_locations.map(&:to_s).should == caller_locations(1..-1).map(&:to_s) + end + + guard -> { Kernel.instance_method(:tap).source_location } do + it "includes core library methods defined in Ruby" do + file, line = Kernel.instance_method(:tap).source_location + file.should.start_with?(''\n" ] end + + it "works with endless ranges" do + locations1 = KernelSpecs::CallerTest.locations(0) + locations2 = KernelSpecs::CallerTest.locations(eval("(2..)")) + locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s) + end + + ruby_version_is "2.7" do + it "works with beginless ranges" do + locations1 = KernelSpecs::CallerTest.locations(0) + locations2 = KernelSpecs::CallerTest.locations(eval("(..5)")) + locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(..5)")].map(&:to_s)[eval("(2..)")] + end + end + + guard -> { Kernel.instance_method(:tap).source_location } do + it "includes core library methods defined in Ruby" do + file, line = Kernel.instance_method(:tap).source_location + file.should.start_with?(' { @obj.clone(freeze: nil) }.should raise_error(ArgumentError, /unexpected value for freeze: NilClass/) + end + end + + ruby_version_is "3.0" do + it "copies frozen state from the original, like #clone without arguments" do + o2 = @obj.clone(freeze: nil) + o2.should_not.frozen? + + @obj.freeze + o3 = @obj.clone(freeze: nil) + o3.should.frozen? + end + + it "copies frozen?" do + o = "".freeze.clone(freeze: nil) + o.frozen?.should be_true + end + end + end + + describe "with freeze: true" do + it 'makes a frozen copy if the original is frozen' do + @obj.freeze + @obj.clone(freeze: true).should.frozen? + end + + ruby_version_is ''...'3.0' do + it 'does not freeze the copy even if the original is not frozen' do + @obj.clone(freeze: true).should_not.frozen? + end + + it "calls #initialize_clone with no kwargs" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: true) + ScratchPad.recorded.should == [obj, {}] + end + end + + ruby_version_is '3.0' do + it 'freezes the copy even if the original was not frozen' do + @obj.clone(freeze: true).should.frozen? + end + + it "calls #initialize_clone with kwargs freeze: true" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: true) + ScratchPad.recorded.should == [obj, { freeze: true }] + end + + it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do + obj = KernelSpecs::Clone.new + -> { obj.clone(freeze: true) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') + end + end + end + + describe "with freeze: false" do + it 'does not freeze the copy if the original is frozen' do + @obj.freeze + @obj.clone(freeze: false).should_not.frozen? + end + + it 'does not freeze the copy if the original is not frozen' do + @obj.clone(freeze: false).should_not.frozen? + end + + ruby_version_is ''...'3.0' do + it "calls #initialize_clone with no kwargs" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: false) + ScratchPad.recorded.should == [obj, {}] + end + end + + ruby_version_is '3.0' do + it "calls #initialize_clone with kwargs freeze: false" do + obj = KernelSpecs::CloneFreeze.new + obj.clone(freeze: false) + ScratchPad.recorded.should == [obj, { freeze: false }] + end + + it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do + obj = KernelSpecs::Clone.new + -> { obj.clone(freeze: false) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') + end + end + end + + describe "with freeze: anything else" do + it 'raises ArgumentError when passed not true/false/nil' do + -> { @obj.clone(freeze: 1) }.should raise_error(ArgumentError, /unexpected value for freeze: Integer/) + -> { @obj.clone(freeze: "") }.should raise_error(ArgumentError, /unexpected value for freeze: String/) + -> { @obj.clone(freeze: Object.new) }.should raise_error(ArgumentError, /unexpected value for freeze: Object/) + end end it "copies instance variables" do @@ -108,11 +207,6 @@ def bar cloned.bar.should == ['a'] end - it 'copies frozen?' do - o = ''.freeze.clone - o.frozen?.should be_true - end - ruby_version_is ''...'2.7' do it 'copies tainted?' do o = ''.taint.clone diff --git a/ruby/spec/ruby/core/kernel/dup_spec.rb b/ruby/spec/ruby/core/kernel/dup_spec.rb index fe0a269d6..70198abdb 100644 --- a/ruby/spec/ruby/core/kernel/dup_spec.rb +++ b/ruby/spec/ruby/core/kernel/dup_spec.rb @@ -32,7 +32,7 @@ def klass.allocate @obj.freeze dup = @obj.dup - dup.frozen?.should == false + dup.should_not.frozen? end it "copies instance variables" do diff --git a/ruby/spec/ruby/core/kernel/eval_spec.rb b/ruby/spec/ruby/core/kernel/eval_spec.rb index 340ba23f2..9be0f2dfd 100644 --- a/ruby/spec/ruby/core/kernel/eval_spec.rb +++ b/ruby/spec/ruby/core/kernel/eval_spec.rb @@ -159,13 +159,37 @@ class Object end end - it "uses the filename of the binding if none is provided" do - eval("__FILE__").should == "(eval)" - suppress_warning {eval("__FILE__", binding)}.should == __FILE__ - eval("__FILE__", binding, "success").should == "success" - suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)" - suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__ - suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success' + ruby_version_is ""..."3.0" do + it "uses the filename of the binding if none is provided" do + eval("__FILE__").should == "(eval)" + suppress_warning {eval("__FILE__", binding)}.should == __FILE__ + eval("__FILE__", binding, "success").should == "success" + suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)" + suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__ + suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success' + end + + it 'uses the given binding file and line for __FILE__ and __LINE__' do + suppress_warning { + eval("[__FILE__, __LINE__]", binding).should == [__FILE__, __LINE__] + } + end + end + + ruby_version_is "3.0" do + it "uses (eval) filename if none is provided" do + eval("__FILE__").should == "(eval)" + eval("__FILE__", binding).should == "(eval)" + eval("__FILE__", binding, "success").should == "success" + eval("eval '__FILE__', binding").should == "(eval)" + eval("eval '__FILE__', binding", binding).should == "(eval)" + eval("eval '__FILE__', binding", binding, 'success').should == '(eval)' + eval("eval '__FILE__', binding, 'success'", binding).should == 'success' + end + + it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do + eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1] + end end # Found via Rubinius bug github:#149 @@ -214,6 +238,17 @@ class Object ruby_exe(code).chomp.should == "a,b,c,e,LocalJumpError,f" end + it "can be called with Method#call" do + method(:eval).call("2 * 3").should == 6 + end + + it "has the correct default definee when called through Method#call" do + class EvalSpecs + method(:eval).call("def eval_spec_method_call; end") + EvalSpecs.should have_instance_method(:eval_spec_method_call) + end + end + # See language/magic_comment_spec.rb for more magic comments specs describe "with a magic encoding comment" do it "uses the magic comment encoding for the encoding of literal strings" do @@ -359,4 +394,46 @@ class EvalSpecs EvalSpecs.send :remove_const, :VÏ€string_not_frozen end end + + describe 'with refinements' do + it "activates refinements from the eval scope" do + refinery = Module.new do + refine EvalSpecs::A do + def foo + "bar" + end + end + end + + result = nil + + Module.new do + using refinery + + result = eval "EvalSpecs::A.new.foo" + end + + result.should == "bar" + end + + it "activates refinements from the binding" do + refinery = Module.new do + refine EvalSpecs::A do + def foo + "bar" + end + end + end + + b = nil + m = Module.new do + using refinery + b = binding + end + + result = eval "EvalSpecs::A.new.foo", b + + result.should == "bar" + end + end end diff --git a/ruby/spec/ruby/core/kernel/extend_spec.rb b/ruby/spec/ruby/core/kernel/extend_spec.rb index 9f98b3681..47b22f3a1 100644 --- a/ruby/spec/ruby/core/kernel/extend_spec.rb +++ b/ruby/spec/ruby/core/kernel/extend_spec.rb @@ -72,8 +72,8 @@ def self.append_features(o) -> { @frozen.extend }.should raise_error(ArgumentError) end - it "raises a #{frozen_error_class}" do - -> { @frozen.extend @module }.should raise_error(frozen_error_class) + it "raises a FrozenError" do + -> { @frozen.extend @module }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/kernel/fixtures/__dir__.rb b/ruby/spec/ruby/core/kernel/fixtures/__dir__.rb new file mode 100644 index 000000000..bf9a15e3c --- /dev/null +++ b/ruby/spec/ruby/core/kernel/fixtures/__dir__.rb @@ -0,0 +1,2 @@ +puts __FILE__ +puts __dir__ diff --git a/ruby/spec/ruby/core/kernel/fixtures/at_exit.rb b/ruby/spec/ruby/core/kernel/fixtures/at_exit.rb new file mode 100644 index 000000000..9c11a7ad6 --- /dev/null +++ b/ruby/spec/ruby/core/kernel/fixtures/at_exit.rb @@ -0,0 +1,3 @@ +at_exit do + STDERR.puts "at_exit ran" +end diff --git a/ruby/spec/ruby/core/kernel/fixtures/classes.rb b/ruby/spec/ruby/core/kernel/fixtures/classes.rb index 2f2bbf1b2..541a4c075 100644 --- a/ruby/spec/ruby/core/kernel/fixtures/classes.rb +++ b/ruby/spec/ruby/core/kernel/fixtures/classes.rb @@ -49,7 +49,7 @@ def self.chop(str, method) def self.chomp(str, method, sep="\n") code = "$_ = #{str.inspect}; $/ = #{sep.inspect}; #{method}; print $_" - IO.popen([*ruby_exe, "-n", "-e", code], "r+") do |io| + IO.popen([*ruby_exe, "-W0", "-n", "-e", code], "r+") do |io| io.puts io.close_write io.read @@ -281,14 +281,25 @@ def initialize(one, two) @two = two end - def initialize_copy(other) + def initialize_copy(other, **kw) ScratchPad.record object_id end + + # define to support calling #clone with optional :freeze keyword argument + def initialize_clone(other, **kw) + super(other) # to call #initialize_copy + end end class Clone def initialize_clone(other) - ScratchPad.record other.object_id + ScratchPad.record other + end + end + + class CloneFreeze + def initialize_clone(other, **kwargs) + ScratchPad.record([other, kwargs]) end end @@ -350,7 +361,7 @@ class ForwardBlockWithZSuper module Ampersand def lambda(&block) - super(&block) + suppress_warning {super(&block)} end end @@ -362,18 +373,19 @@ class SuperAmpersand class RespondViaMissing def respond_to_missing?(method, priv=false) case method - when :handled_publicly - true - when :handled_privately - priv - when :not_handled - false - else - raise "Typo in method name" + when :handled_publicly + true + when :handled_privately + priv + when :not_handled + false + else + raise "Typo in method name: #{method.inspect}" end end def method_missing(method, *args) + raise "the method name should be a Symbol" unless Symbol === method "Done #{method}(#{args})" end end diff --git a/ruby/spec/ruby/core/kernel/fixtures/warn_core_method.rb b/ruby/spec/ruby/core/kernel/fixtures/warn_core_method.rb new file mode 100644 index 000000000..f5dee6b66 --- /dev/null +++ b/ruby/spec/ruby/core/kernel/fixtures/warn_core_method.rb @@ -0,0 +1,14 @@ +raise 'should be run without RubyGems' if defined?(Gem) + +def deprecated(n=1) + # puts nil, caller(0), nil + warn "use X instead", uplevel: n +end + +1.times do # to test with a non-empty stack above the reported locations + deprecated + tap(&:deprecated) + tap { deprecated(2) } + # eval sources with a " +end diff --git a/ruby/spec/ruby/core/kernel/fixtures/warn_require.rb b/ruby/spec/ruby/core/kernel/fixtures/warn_require.rb new file mode 100644 index 000000000..c4b073323 --- /dev/null +++ b/ruby/spec/ruby/core/kernel/fixtures/warn_require.rb @@ -0,0 +1 @@ +warn 'warn-require-warning', uplevel: 1 diff --git a/ruby/spec/ruby/core/kernel/fixtures/warn_require_caller.rb b/ruby/spec/ruby/core/kernel/fixtures/warn_require_caller.rb new file mode 100644 index 000000000..35a0f969f --- /dev/null +++ b/ruby/spec/ruby/core/kernel/fixtures/warn_require_caller.rb @@ -0,0 +1,2 @@ +# Use a different line than just 1 +require "#{__dir__}/warn_require" diff --git a/ruby/spec/ruby/core/kernel/format_spec.rb b/ruby/spec/ruby/core/kernel/format_spec.rb index 72fd40b95..e8b031e48 100644 --- a/ruby/spec/ruby/core/kernel/format_spec.rb +++ b/ruby/spec/ruby/core/kernel/format_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +# NOTE: most specs are in sprintf_spec.rb, this is just an alias describe "Kernel#format" do it "is a private method" do Kernel.should have_private_instance_method(:format) diff --git a/ruby/spec/ruby/core/kernel/freeze_spec.rb b/ruby/spec/ruby/core/kernel/freeze_spec.rb index 214b619f9..fa32d321c 100644 --- a/ruby/spec/ruby/core/kernel/freeze_spec.rb +++ b/ruby/spec/ruby/core/kernel/freeze_spec.rb @@ -51,21 +51,19 @@ end end - ruby_version_is "2.5" do - describe "on a Complex" do - it "has no effect since it is already frozen" do - c = Complex(1.3, 3.1) - c.frozen?.should be_true - c.freeze - end + describe "on a Complex" do + it "has no effect since it is already frozen" do + c = Complex(1.3, 3.1) + c.frozen?.should be_true + c.freeze end + end - describe "on a Rational" do - it "has no effect since it is already frozen" do - r = Rational(1, 3) - r.frozen?.should be_true - r.freeze - end + describe "on a Rational" do + it "has no effect since it is already frozen" do + r = Rational(1, 3) + r.frozen?.should be_true + r.freeze end end @@ -82,4 +80,12 @@ def mutate; @foo = 1; end o.freeze -> {o.instance_variable_set(:@foo, 1)}.should raise_error(RuntimeError) end + + it "freezes an object's singleton class" do + o = Object.new + c = o.singleton_class + c.frozen?.should == false + o.freeze + c.frozen?.should == true + end end diff --git a/ruby/spec/ruby/core/kernel/frozen_spec.rb b/ruby/spec/ruby/core/kernel/frozen_spec.rb index 5887ed75b..a4cec4263 100644 --- a/ruby/spec/ruby/core/kernel/frozen_spec.rb +++ b/ruby/spec/ruby/core/kernel/frozen_spec.rb @@ -6,8 +6,8 @@ o = mock('o') p = mock('p') p.freeze - o.frozen?.should == false - p.frozen?.should == true + o.should_not.frozen? + p.should.frozen? end describe "on true, false and nil" do @@ -50,29 +50,27 @@ end end - ruby_version_is "2.5" do - describe "on a Complex" do - it "returns true" do - c = Complex(1.3, 3.1) - c.frozen?.should be_true - end + describe "on a Complex" do + it "returns true" do + c = Complex(1.3, 3.1) + c.frozen?.should be_true + end - it "literal returns true" do - c = eval "1.3i" - c.frozen?.should be_true - end + it "literal returns true" do + c = eval "1.3i" + c.frozen?.should be_true end + end - describe "on a Rational" do - it "returns true" do - r = Rational(1, 3) - r.frozen?.should be_true - end + describe "on a Rational" do + it "returns true" do + r = Rational(1, 3) + r.frozen?.should be_true + end - it "literal returns true" do - r = eval "1/3r" - r.frozen?.should be_true - end + it "literal returns true" do + r = eval "1/3r" + r.frozen?.should be_true end end end diff --git a/ruby/spec/ruby/core/kernel/initialize_clone_spec.rb b/ruby/spec/ruby/core/kernel/initialize_clone_spec.rb new file mode 100644 index 000000000..2d889f5aa --- /dev/null +++ b/ruby/spec/ruby/core/kernel/initialize_clone_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_clone" do + it "is a private instance method" do + Kernel.should have_private_instance_method(:initialize_clone) + end + + it "returns the receiver" do + a = Object.new + b = Object.new + a.send(:initialize_clone, b).should == a + end + + it "calls #initialize_copy" do + a = Object.new + b = Object.new + a.should_receive(:initialize_copy).with(b) + a.send(:initialize_clone, b) + end + + ruby_version_is "3.0" do + it "accepts a :freeze keyword argument for obj.clone(freeze: value)" do + a = Object.new + b = Object.new + a.send(:initialize_clone, b, freeze: true).should == a + end + end +end diff --git a/ruby/spec/ruby/core/kernel/initialize_copy_spec.rb b/ruby/spec/ruby/core/kernel/initialize_copy_spec.rb new file mode 100644 index 000000000..fe08d184a --- /dev/null +++ b/ruby/spec/ruby/core/kernel/initialize_copy_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_copy" do + it "does nothing if the argument is the same as the receiver" do + obj = Object.new + obj.send(:initialize_copy, obj).should.equal?(obj) + obj.freeze + obj.send(:initialize_copy, obj).should.equal?(obj) + 1.send(:initialize_copy, 1).should.equal?(1) + end + + it "raises FrozenError if the receiver is frozen" do + -> { Object.new.freeze.send(:initialize_copy, Object.new) }.should raise_error(FrozenError) + -> { 1.send(:initialize_copy, Object.new) }.should raise_error(FrozenError) + end + + it "raises TypeError if the objects are of different class" do + klass = Class.new + sub = Class.new(klass) + a = klass.new + b = sub.new + message = 'initialize_copy should take same class object' + -> { a.send(:initialize_copy, b) }.should raise_error(TypeError, message) + -> { b.send(:initialize_copy, a) }.should raise_error(TypeError, message) + + -> { a.send(:initialize_copy, 1) }.should raise_error(TypeError, message) + -> { a.send(:initialize_copy, 1.0) }.should raise_error(TypeError, message) + end +end diff --git a/ruby/spec/ruby/core/kernel/initialize_dup_spec.rb b/ruby/spec/ruby/core/kernel/initialize_dup_spec.rb new file mode 100644 index 000000000..6dff34b7a --- /dev/null +++ b/ruby/spec/ruby/core/kernel/initialize_dup_spec.rb @@ -0,0 +1,20 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_dup" do + it "is a private instance method" do + Kernel.should have_private_instance_method(:initialize_dup) + end + + it "returns the receiver" do + a = Object.new + b = Object.new + a.send(:initialize_dup, b).should == a + end + + it "calls #initialize_copy" do + a = Object.new + b = Object.new + a.should_receive(:initialize_copy).with(b) + a.send(:initialize_dup, b) + end +end diff --git a/ruby/spec/ruby/core/kernel/inspect_spec.rb b/ruby/spec/ruby/core/kernel/inspect_spec.rb index a946d032d..e6fca8bf6 100644 --- a/ruby/spec/ruby/core/kernel/inspect_spec.rb +++ b/ruby/spec/ruby/core/kernel/inspect_spec.rb @@ -30,4 +30,12 @@ obj = Object.new obj.inspect.should =~ /^#$/ end + + it "returns a String for an object without #class method" do + obj = Object.new + class << obj + undef_method :class + end + obj.inspect.should be_kind_of(String) + end end diff --git a/ruby/spec/ruby/core/kernel/instance_of_spec.rb b/ruby/spec/ruby/core/kernel/instance_of_spec.rb index 40e856b0d..d1170d504 100644 --- a/ruby/spec/ruby/core/kernel/instance_of_spec.rb +++ b/ruby/spec/ruby/core/kernel/instance_of_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe Kernel, "#instance_of?" do +describe "Kernel#instance_of?" do before :each do @o = KernelSpecs::InstanceClass.new end diff --git a/ruby/spec/ruby/core/kernel/instance_variable_get_spec.rb b/ruby/spec/ruby/core/kernel/instance_variable_get_spec.rb index 84d3188f0..bb6f03d3b 100644 --- a/ruby/spec/ruby/core/kernel/instance_variable_get_spec.rb +++ b/ruby/spec/ruby/core/kernel/instance_variable_get_spec.rb @@ -92,7 +92,7 @@ end end -describe "Kernel#instance_variable_get when passed Fixnum" do +describe "Kernel#instance_variable_get when passed Integer" do before :each do @obj = Object.new @obj.instance_variable_set("@test", :test) diff --git a/ruby/spec/ruby/core/kernel/instance_variable_set_spec.rb b/ruby/spec/ruby/core/kernel/instance_variable_set_spec.rb index c5a408553..7fda30f72 100644 --- a/ruby/spec/ruby/core/kernel/instance_variable_set_spec.rb +++ b/ruby/spec/ruby/core/kernel/instance_variable_set_spec.rb @@ -31,7 +31,7 @@ def initialize(p1, p2) -> { dog_at.new.instance_variable_set(:"@", "cat") }.should raise_error(NameError) end - it "raises a TypeError if the instance variable name is a Fixnum" do + it "raises a TypeError if the instance variable name is an Integer" do -> { "".instance_variable_set(1, 2) }.should raise_error(TypeError) end @@ -82,12 +82,12 @@ def initialize @frozen.ivar.should equal(:origin) end - it "raises a #{frozen_error_class} when passed replacement is identical to stored object" do - -> { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed replacement is identical to stored object" do + -> { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when passed replacement is different from stored object" do - -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed replacement is different from stored object" do + -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/kernel/instance_variables_spec.rb b/ruby/spec/ruby/core/kernel/instance_variables_spec.rb index b6d6e2777..677d8bb7b 100644 --- a/ruby/spec/ruby/core/kernel/instance_variables_spec.rb +++ b/ruby/spec/ruby/core/kernel/instance_variables_spec.rb @@ -4,7 +4,9 @@ describe "Kernel#instance_variables" do describe "immediate values" do it "returns an empty array if no instance variables are defined" do - 0.instance_variables.should == [] + [0, 0.5, true, false, nil].each do |value| + value.instance_variables.should == [] + end end it "returns the correct array if an instance variable is added" do @@ -23,5 +25,16 @@ a.instance_variable_set("@test", 1) a.instance_variables.should == [:@test] end + + it "returns the instances variables in the order declared" do + c = Class.new do + def initialize + @c = 1 + @a = 2 + @b = 3 + end + end + c.new.instance_variables.should == [:@c, :@a, :@b] + end end end diff --git a/ruby/spec/ruby/core/kernel/iterator_spec.rb b/ruby/spec/ruby/core/kernel/iterator_spec.rb index 7fbdade9d..3fe8317f2 100644 --- a/ruby/spec/ruby/core/kernel/iterator_spec.rb +++ b/ruby/spec/ruby/core/kernel/iterator_spec.rb @@ -1,12 +1,14 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "Kernel#iterator?" do - it "is a private method" do - Kernel.should have_private_instance_method(:iterator?) +ruby_version_is ""..."3.0" do + describe "Kernel#iterator?" do + it "is a private method" do + Kernel.should have_private_instance_method(:iterator?) + end end -end -describe "Kernel.iterator?" do - it "needs to be reviewed for spec completeness" + describe "Kernel.iterator?" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/core/kernel/lambda_spec.rb b/ruby/spec/ruby/core/kernel/lambda_spec.rb index 5c3051127..2aa4d4f2f 100644 --- a/ruby/spec/ruby/core/kernel/lambda_spec.rb +++ b/ruby/spec/ruby/core/kernel/lambda_spec.rb @@ -27,23 +27,27 @@ end it "creates a lambda-style Proc if given a literal block via Kernel.public_send" do - l = Kernel.public_send(:lambda) { 42 } - l.lambda?.should be_true + suppress_warning do + l = Kernel.public_send(:lambda) { 42 } + l.lambda?.should be_true + end end it "returns the passed Proc if given an existing Proc" do some_proc = proc {} - l = lambda(&some_proc) + l = suppress_warning {lambda(&some_proc)} l.should equal(some_proc) l.lambda?.should be_false end it "creates a lambda-style Proc when called with zsuper" do - l = KernelSpecs::LambdaSpecs::ForwardBlockWithZSuper.new.lambda { 42 } - l.lambda?.should be_true - l.call.should == 42 + suppress_warning do + l = KernelSpecs::LambdaSpecs::ForwardBlockWithZSuper.new.lambda { 42 } + l.lambda?.should be_true + l.call.should == 42 - lambda { l.call(:extra) }.should raise_error(ArgumentError) + lambda { l.call(:extra) }.should raise_error(ArgumentError) + end end it "returns the passed Proc if given an existing Proc through super" do @@ -55,7 +59,7 @@ it "does not create lambda-style Procs when captured with #method" do kernel_lambda = method(:lambda) - l = kernel_lambda.call { 42 } + l = suppress_warning {kernel_lambda.call { 42 }} l.lambda?.should be_false l.call(:extra).should == 42 end @@ -119,4 +123,28 @@ def test it "allows long returns to flow through it" do KernelSpecs::Lambda.new.outer.should == :good end + + it "treats the block as a Proc when lambda is re-defined" do + klass = Class.new do + def lambda (&block); block; end + def ret + lambda { return 1 }.call + 2 + end + end + klass.new.lambda { 42 }.should be_an_instance_of Proc + klass.new.ret.should == 1 + end + + ruby_version_is "3.0" do + context "when called without a literal block" do + it "warns when proc isn't a lambda" do + -> { lambda(&proc{}) }.should complain("#{__FILE__}:#{__LINE__}: warning: lambda without a literal block is deprecated; use the proc without lambda instead\n") + end + + it "doesn't warn when proc is lambda" do + -> { lambda(&lambda{}) }.should_not complain(verbose: true) + end + end + end end diff --git a/ruby/spec/ruby/core/kernel/match_spec.rb b/ruby/spec/ruby/core/kernel/match_spec.rb index 6dc1eb7de..fbfc77f95 100644 --- a/ruby/spec/ruby/core/kernel/match_spec.rb +++ b/ruby/spec/ruby/core/kernel/match_spec.rb @@ -14,11 +14,9 @@ end end - ruby_version_is "2.6" do - it "is deprecated" do - -> do - Object.new =~ /regexp/ - end.should complain(/deprecated Object#=~ is called on Object/, verbose: true) - end + it "is deprecated" do + -> do + Object.new =~ /regexp/ + end.should complain(/deprecated Object#=~ is called on Object/, verbose: true) end end diff --git a/ruby/spec/ruby/core/kernel/nil_spec.rb b/ruby/spec/ruby/core/kernel/nil_spec.rb index b63705f7b..7418245f2 100644 --- a/ruby/spec/ruby/core/kernel/nil_spec.rb +++ b/ruby/spec/ruby/core/kernel/nil_spec.rb @@ -1,6 +1,12 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "Kernel#nil?" do - it "needs to be reviewed for spec completeness" +describe 'Kernel#nil?' do + it 'returns false' do + Object.should_not.nil? + Object.new.should_not.nil? + ''.should_not.nil? + [].should_not.nil? + {}.should_not.nil? + end end diff --git a/ruby/spec/ruby/core/kernel/open_spec.rb b/ruby/spec/ruby/core/kernel/open_spec.rb index 981b5291b..569f2f6a7 100644 --- a/ruby/spec/ruby/core/kernel/open_spec.rb +++ b/ruby/spec/ruby/core/kernel/open_spec.rb @@ -2,7 +2,6 @@ require_relative 'fixtures/classes' describe "Kernel#open" do - before :each do @name = tmp("kernel_open.txt") @content = "This is a test" @@ -137,6 +136,30 @@ it "accepts nil for mode and permission" do open(@name, nil, nil) { |f| f.gets }.should == @content end + + ruby_version_is ""..."3.0" do + it "works correctly when redefined by open-uri" do + code = <<~RUBY + require 'open-uri' + obj = Object.new + def obj.to_open; self; end + p open(obj) == obj + RUBY + ruby_exe(code, args: "2>&1").should == "true\n" + end + end + + ruby_version_is "3.0" do + it "is not redefined by open-uri" do + code = <<~RUBY + before = Kernel.instance_method(:open) + require 'open-uri' + after = Kernel.instance_method(:open) + p before == after + RUBY + ruby_exe(code, args: "2>&1").should == "true\n" + end + end end describe "Kernel.open" do diff --git a/ruby/spec/ruby/core/kernel/p_spec.rb b/ruby/spec/ruby/core/kernel/p_spec.rb index 798bd47b3..1bdd1740c 100644 --- a/ruby/spec/ruby/core/kernel/p_spec.rb +++ b/ruby/spec/ruby/core/kernel/p_spec.rb @@ -57,10 +57,14 @@ } -> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n") - $\ = " *helicopter sound*\n" + suppress_warning { + $\ = " *helicopter sound*\n" + } -> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n") - $/ = " *helicopter sound*\n" + suppress_warning { + $/ = " *helicopter sound*\n" + } -> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n") end diff --git a/ruby/spec/ruby/core/kernel/pp_spec.rb b/ruby/spec/ruby/core/kernel/pp_spec.rb index e19dc64ca..b5b1c98d3 100644 --- a/ruby/spec/ruby/core/kernel/pp_spec.rb +++ b/ruby/spec/ruby/core/kernel/pp_spec.rb @@ -1,11 +1,9 @@ require_relative '../../spec_helper' -ruby_version_is "2.5" do - describe "Kernel#pp" do - it "lazily loads the 'pp' library and delegates the call to that library" do - # Run in child process to ensure 'pp' hasn't been loaded yet. - output = ruby_exe("pp [1, 2, 3]") - output.should == "[1, 2, 3]\n" - end +describe "Kernel#pp" do + it "lazily loads the 'pp' library and delegates the call to that library" do + # Run in child process to ensure 'pp' hasn't been loaded yet. + output = ruby_exe("pp [1, 2, 3]") + output.should == "[1, 2, 3]\n" end end diff --git a/ruby/spec/ruby/core/kernel/print_spec.rb b/ruby/spec/ruby/core/kernel/print_spec.rb index c8c4453d1..7e7c9b822 100644 --- a/ruby/spec/ruby/core/kernel/print_spec.rb +++ b/ruby/spec/ruby/core/kernel/print_spec.rb @@ -5,6 +5,18 @@ it "is a private method" do Kernel.should have_private_instance_method(:print) end + + it "delegates to $stdout" do + -> { print :arg }.should output("arg") + end + + it "prints $_ when no arguments are given" do + orig_value = $_ + $_ = 'foo' + -> { print }.should output("foo") + ensure + $_ = orig_value + end end describe "Kernel.print" do diff --git a/ruby/spec/ruby/core/kernel/printf_spec.rb b/ruby/spec/ruby/core/kernel/printf_spec.rb index 5d68c0a13..d8f93ce42 100644 --- a/ruby/spec/ruby/core/kernel/printf_spec.rb +++ b/ruby/spec/ruby/core/kernel/printf_spec.rb @@ -1,7 +1,6 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' require_relative 'shared/sprintf' -require "stringio" describe "Kernel#printf" do it "is a private method" do @@ -10,7 +9,6 @@ end describe "Kernel.printf" do - before :each do @stdout = $stdout @name = tmp("kernel_puts.txt") @@ -33,12 +31,18 @@ object.should_receive(:write).with("string") Kernel.printf(object, "%s", "string") end +end +describe "Kernel.printf" do describe "formatting" do + before :each do + require "stringio" + end + context "io is specified" do it_behaves_like :kernel_sprintf, -> format, *args { - io = StringIO.new - printf(io, format, *args) + io = StringIO.new(+"") + Kernel.printf(io, format, *args) io.string } end @@ -46,10 +50,9 @@ context "io is not specified" do it_behaves_like :kernel_sprintf, -> format, *args { stdout = $stdout - begin - $stdout = io = StringIO.new - printf(format, *args) + $stdout = io = StringIO.new(+"") + Kernel.printf(format, *args) io.string ensure $stdout = stdout diff --git a/ruby/spec/ruby/core/kernel/proc_spec.rb b/ruby/spec/ruby/core/kernel/proc_spec.rb index 2a7954831..dfe178420 100644 --- a/ruby/spec/ruby/core/kernel/proc_spec.rb +++ b/ruby/spec/ruby/core/kernel/proc_spec.rb @@ -36,27 +36,31 @@ def test end describe "Kernel#proc" do + def some_method + proc + end + ruby_version_is ""..."2.7" do it "uses the implicit block from an enclosing method" do - def some_method - proc - end - prc = some_method { "hello" } prc.call.should == "hello" end end - ruby_version_is "2.7" do + ruby_version_is "2.7"..."3.0" do it "can be created when called with no block" do - def some_method - proc - end - -> { some_method { "hello" } }.should complain(/Capturing the given block using Kernel#proc is deprecated/) end end + + ruby_version_is "3.0" do + it "raises an ArgumentError when passed no block" do + -> { + some_method { "hello" } + }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + end + end end diff --git a/ruby/spec/ruby/core/kernel/public_send_spec.rb b/ruby/spec/ruby/core/kernel/public_send_spec.rb index 6b942a2e4..4dae419ff 100644 --- a/ruby/spec/ruby/core/kernel/public_send_spec.rb +++ b/ruby/spec/ruby/core/kernel/public_send_spec.rb @@ -104,5 +104,13 @@ def bar }.should raise_error(NoMethodError) end + it "includes `public_send` in the backtrace when passed not enough arguments" do + -> { public_send() }.should raise_error(ArgumentError) { |e| e.backtrace[0].should.include?("`public_send'") } + end + + it "includes `public_send` in the backtrace when passed a single incorrect argument" do + -> { public_send(Object.new) }.should raise_error(TypeError) { |e| e.backtrace[0].should.include?("`public_send'") } + end + it_behaves_like :basicobject_send, :public_send end diff --git a/ruby/spec/ruby/core/kernel/raise_spec.rb b/ruby/spec/ruby/core/kernel/raise_spec.rb index bf2656024..4f190c120 100644 --- a/ruby/spec/ruby/core/kernel/raise_spec.rb +++ b/ruby/spec/ruby/core/kernel/raise_spec.rb @@ -6,6 +6,46 @@ it "is a private method" do Kernel.should have_private_instance_method(:raise) end + + it "re-raises the previously rescued exception if no exception is specified" do + ScratchPad.record nil + + -> do + begin + raise Exception, "outer" + ScratchPad.record :no_abort + rescue Exception + begin + raise StandardError, "inner" + rescue StandardError + end + + raise + ScratchPad.record :no_reraise + end + end.should raise_error(Exception, "outer") + + ScratchPad.recorded.should be_nil + end + + it "accepts a cause keyword argument that sets the cause" do + cause = StandardError.new + -> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause } + end + + it "accepts a cause keyword argument that overrides the last exception" do + begin + raise "first raise" + rescue => ignored + cause = StandardError.new + -> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause } + end + end + + it "raises an ArgumentError when only cause is given" do + cause = StandardError.new + -> { raise(cause: cause) }.should raise_error(ArgumentError) + end end describe "Kernel#raise" do diff --git a/ruby/spec/ruby/core/kernel/rand_spec.rb b/ruby/spec/ruby/core/kernel/rand_spec.rb index a82b4fba7..355e42579 100644 --- a/ruby/spec/ruby/core/kernel/rand_spec.rb +++ b/ruby/spec/ruby/core/kernel/rand_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "Kernel.rand" do +describe "Kernel#rand" do it "is a private method" do Kernel.should have_private_instance_method(:rand) end @@ -117,6 +117,48 @@ end end + context "given an inclusive range between 0 and 1" do + it "returns an Integer between the two Integers" do + x = rand(0..1) + x.should be_kind_of(Integer) + (0..1).should include(x) + end + + it "returns a Float if at least one side is Float" do + seed = 42 + x1 = Random.new(seed).rand(0..1.0) + x2 = Random.new(seed).rand(0.0..1.0) + x3 = Random.new(seed).rand(0.0..1) + + x3.should be_kind_of(Float) + x1.should eql(x3) + x2.should eql(x3) + + (0.0..1.0).should include(x3) + end + end + + context "given an exclusive range between 0 and 1" do + it "returns zero as an Integer" do + x = rand(0...1) + x.should be_kind_of(Integer) + x.should eql(0) + end + + it "returns a Float if at least one side is Float" do + seed = 42 + x1 = Random.new(seed).rand(0...1.0) + x2 = Random.new(seed).rand(0.0...1.0) + x3 = Random.new(seed).rand(0.0...1) + + x3.should be_kind_of(Float) + x1.should eql(x3) + x2.should eql(x3) + + (0.0...1.0).should include(x3) + end + end + it "returns a numeric for an range argument where max is < 1" do rand(0.25..0.75).should be_kind_of(Numeric) end @@ -150,6 +192,6 @@ end end -describe "Kernel#rand" do +describe "Kernel.rand" do it "needs to be reviewed for spec completeness" end diff --git a/ruby/spec/ruby/core/kernel/require_relative_spec.rb b/ruby/spec/ruby/core/kernel/require_relative_spec.rb index b292a46c6..d4146eb3c 100644 --- a/ruby/spec/ruby/core/kernel/require_relative_spec.rb +++ b/ruby/spec/ruby/core/kernel/require_relative_spec.rb @@ -90,6 +90,16 @@ ScratchPad.recorded.should == [] end + it "raises a LoadError that includes the missing path" do + missing_path = "#{@dir}/nonexistent.rb" + expanded_missing_path = File.expand_path(missing_path, File.dirname(__FILE__)) + -> { require_relative(missing_path) }.should raise_error(LoadError) { |e| + e.message.should include(expanded_missing_path) + e.path.should == expanded_missing_path + } + ScratchPad.recorded.should == [] + end + it "raises a LoadError if basepath does not exist" do -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError) end diff --git a/ruby/spec/ruby/core/kernel/respond_to_spec.rb b/ruby/spec/ruby/core/kernel/respond_to_spec.rb index e7efc9f27..5b3ea3f65 100644 --- a/ruby/spec/ruby/core/kernel/respond_to_spec.rb +++ b/ruby/spec/ruby/core/kernel/respond_to_spec.rb @@ -25,7 +25,7 @@ end it "throws a type error if argument can't be coerced into a Symbol" do - -> { @a.respond_to?(Object.new) }.should raise_error(TypeError) + -> { @a.respond_to?(Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/) end it "returns false if obj responds to the given protected method" do @@ -69,5 +69,4 @@ class KernelSpecs::Foo; def bar; 'done'; end; end KernelSpecs::Foo.new.respond_to?(:bar).should == true KernelSpecs::Foo.new.respond_to?(:invalid_and_silly_method_name).should == false end - end diff --git a/ruby/spec/ruby/core/kernel/shared/dup_clone.rb b/ruby/spec/ruby/core/kernel/shared/dup_clone.rb index a52ccab35..84ad49cbd 100644 --- a/ruby/spec/ruby/core/kernel/shared/dup_clone.rb +++ b/ruby/spec/ruby/core/kernel/shared/dup_clone.rb @@ -59,8 +59,8 @@ def initialize_copy(original) o.taint o3 = o.send(@method) - o2.tainted?.should == false - o3.tainted?.should == true + o2.should_not.tainted? + o3.should.tainted? end end @@ -78,8 +78,8 @@ def initialize_copy(original) o.untrust o3 = o.send(@method) - o2.untrusted?.should == false - o3.untrusted?.should == true + o2.should_not.untrusted? + o3.should.untrusted? end end @@ -103,27 +103,13 @@ def initialize_copy(original) :my_symbol.send(@method).should == :my_symbol end - ruby_version_is ''...'2.5' do - it "raises a TypeError for Complex" do - c = Complex(1.3, 3.1) - -> { c.send(@method) }.should raise_error(TypeError) - end - - it "raises a TypeError for Rational" do - r = Rational(1, 3) - -> { r.send(@method) }.should raise_error(TypeError) - end + it "returns self for Complex" do + c = Complex(1.3, 3.1) + c.send(@method).should equal c end - ruby_version_is '2.5' do - it "returns self for Complex" do - c = Complex(1.3, 3.1) - c.send(@method).should equal c - end - - it "returns self for Rational" do - r = Rational(1, 3) - r.send(@method).should equal r - end + it "returns self for Rational" do + r = Rational(1, 3) + r.send(@method).should equal r end end diff --git a/ruby/spec/ruby/core/kernel/shared/lambda.rb b/ruby/spec/ruby/core/kernel/shared/lambda.rb index c7180e144..c70640082 100644 --- a/ruby/spec/ruby/core/kernel/shared/lambda.rb +++ b/ruby/spec/ruby/core/kernel/shared/lambda.rb @@ -4,6 +4,8 @@ end it "raises an ArgumentError when no block is given" do - -> { send(@method) }.should raise_error(ArgumentError) + suppress_warning do + -> { send(@method) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/core/kernel/shared/method.rb b/ruby/spec/ruby/core/kernel/shared/method.rb index 3418966b1..8b6ab23fd 100644 --- a/ruby/spec/ruby/core/kernel/shared/method.rb +++ b/ruby/spec/ruby/core/kernel/shared/method.rb @@ -15,12 +15,18 @@ class KernelSpecs::Foo; def self.bar; 'class done'; end; end m.call.should == 'class done' end - it "returns a method object if we repond_to_missing? method" do + it "returns a method object if respond_to_missing?(method) is true" do m = KernelSpecs::RespondViaMissing.new.send(@method, :handled_publicly) m.should be_an_instance_of Method m.call(42).should == "Done handled_publicly([42])" end + it "the returned method object if respond_to_missing?(method) calls #method_missing with a Symbol name" do + m = KernelSpecs::RespondViaMissing.new.send(@method, "handled_publicly") + m.should be_an_instance_of Method + m.call(42).should == "Done handled_publicly([42])" + end + it "raises a NameError for an invalid method name" do class KernelSpecs::Foo; def bar; 'done'; end; end -> { diff --git a/ruby/spec/ruby/core/kernel/shared/require.rb b/ruby/spec/ruby/core/kernel/shared/require.rb index 52089f22f..9a2c38be1 100644 --- a/ruby/spec/ruby/core/kernel/shared/require.rb +++ b/ruby/spec/ruby/core/kernel/shared/require.rb @@ -60,7 +60,7 @@ -> { @object.send(@method, nil) }.should raise_error(TypeError) end - it "raises a TypeError if passed a Fixnum" do + it "raises a TypeError if passed an Integer" do -> { @object.send(@method, 42) }.should raise_error(TypeError) end @@ -160,6 +160,14 @@ ScratchPad.recorded.should == [:loaded] end + it "accepts an Object with #to_path in $LOAD_PATH" do + obj = mock("to_path") + obj.should_receive(:to_path).at_least(:once).and_return(CODE_LOADING_DIR) + $LOAD_PATH << obj + @object.send(@method, "load_fixture.rb").should be_true + ScratchPad.recorded.should == [:loaded] + end + it "does not require file twice after $LOAD_PATH change" do $LOAD_PATH << CODE_LOADING_DIR @object.require("load_fixture.rb").should be_true @@ -242,6 +250,15 @@ @object.require("load_fixture").should be_true ScratchPad.recorded.should == [:loaded] end + + ruby_bug "#16926", "2.7"..."3.0" do + it "does not load a feature twice when $LOAD_PATH has been modified" do + $LOAD_PATH.replace [CODE_LOADING_DIR] + @object.require("load_fixture").should be_true + $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR] + @object.require("load_fixture").should be_false + end + end end describe "(file extensions)" do @@ -335,6 +352,21 @@ loaded_feature = $LOADED_FEATURES.last ScratchPad.recorded.should == [loaded_feature] end + + it "requires only once when a new matching file added to path" do + @object.require('load_fixture').should be_true + ScratchPad.recorded.should == [:loaded] + + symlink_to_code_dir_two = tmp("codesymlinktwo") + File.symlink("#{CODE_LOADING_DIR}/b", symlink_to_code_dir_two) + begin + $LOAD_PATH.unshift(symlink_to_code_dir_two) + + @object.require('load_fixture').should be_false + ensure + rm_r symlink_to_code_dir_two + end + end end describe "with symlinks in the required feature and $LOAD_PATH" do @@ -354,26 +386,13 @@ rm_r @dir, @symlink_to_dir end - ruby_version_is ""..."2.4.4" do - it "canonicalizes neither the entry in $LOAD_PATH nor the filename passed to #require" do - $LOAD_PATH.unshift(@symlink_to_dir) - @object.require("symfile").should be_true - loaded_feature = "#{@symlink_to_dir}/symfile.rb" - ScratchPad.recorded.should == [loaded_feature] - $".last.should == loaded_feature - $LOAD_PATH[0].should == @symlink_to_dir - end - end - - ruby_version_is "2.4.4" do - it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do - $LOAD_PATH.unshift(@symlink_to_dir) - @object.require("symfile").should be_true - loaded_feature = "#{@dir}/symfile.rb" - ScratchPad.recorded.should == [loaded_feature] - $".last.should == loaded_feature - $LOAD_PATH[0].should == @symlink_to_dir - end + it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do + $LOAD_PATH.unshift(@symlink_to_dir) + @object.require("symfile").should be_true + loaded_feature = "#{@dir}/symfile.rb" + ScratchPad.recorded.should == [loaded_feature] + $".last.should == loaded_feature + $LOAD_PATH[0].should == @symlink_to_dir end end end @@ -527,41 +546,29 @@ ScratchPad.recorded.should == [] end - ruby_version_is ""..."2.5" do - it "complex, enumerator, rational, thread and unicode_normalize are already required" do - provided = %w[complex enumerator rational thread unicode_normalize] - features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') - provided.each { |feature| - features.should =~ /\b#{feature}\.(rb|so|jar)$/ - } - - code = provided.map { |f| "puts require #{f.inspect}\n" }.join - required = ruby_exe(code, options: '--disable-gems') - required.should == "false\n" * provided.size - end + provided = %w[complex enumerator rational thread] + ruby_version_is "2.7" do + provided << 'ruby2_keywords' end - ruby_version_is "2.5" do - it "complex, enumerator, rational and thread are already required" do - provided = %w[complex enumerator rational thread] - features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') - provided.each { |feature| - features.should =~ /\b#{feature}\.(rb|so|jar)$/ - } + it "#{provided.join(', ')} are already required" do + features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') + provided.each { |feature| + features.should =~ /\b#{feature}\.(rb|so|jar)$/ + } - code = provided.map { |f| "puts require #{f.inspect}\n" }.join - required = ruby_exe(code, options: '--disable-gems') - required.should == "false\n" * provided.size - end + code = provided.map { |f| "puts require #{f.inspect}\n" }.join + required = ruby_exe(code, options: '--disable-gems') + required.should == "false\n" * provided.size + end - it "unicode_normalize is part of core and not $LOADED_FEATURES" do - features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') - features.lines.each { |feature| - feature.should_not include("unicode_normalize") - } + it "unicode_normalize is part of core and not $LOADED_FEATURES" do + features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') + features.lines.each { |feature| + feature.should_not include("unicode_normalize") + } - -> { @object.require("unicode_normalize") }.should raise_error(LoadError) - end + -> { @object.require("unicode_normalize") }.should raise_error(LoadError) end end diff --git a/ruby/spec/ruby/core/kernel/shared/sprintf.rb b/ruby/spec/ruby/core/kernel/shared/sprintf.rb index 989968428..84d472b0d 100644 --- a/ruby/spec/ruby/core/kernel/shared/sprintf.rb +++ b/ruby/spec/ruby/core/kernel/shared/sprintf.rb @@ -1,10 +1,4 @@ -require_relative '../../../shared/hash/key_error' - describe :kernel_sprintf, shared: true do - def format(*args) - @method.call(*args) - end - describe "integer formats" do it "converts argument into Integer with to_int" do obj = Object.new @@ -12,7 +6,7 @@ def obj.to_i; 10; end def obj.to_int; 10; end obj.should_receive(:to_int).and_return(10) - format("%b", obj).should == "1010" + @method.call("%b", obj).should == "1010" end it "converts argument into Integer with to_i if to_int isn't available" do @@ -20,35 +14,35 @@ def obj.to_int; 10; end def obj.to_i; 10; end obj.should_receive(:to_i).and_return(10) - format("%b", obj).should == "1010" + @method.call("%b", obj).should == "1010" end it "converts String argument with Kernel#Integer" do - format("%d", "0b1010").should == "10" - format("%d", "112").should == "112" - format("%d", "0127").should == "87" - format("%d", "0xc4").should == "196" + @method.call("%d", "0b1010").should == "10" + @method.call("%d", "112").should == "112" + @method.call("%d", "0127").should == "87" + @method.call("%d", "0xc4").should == "196" end it "raises TypeError exception if cannot convert to Integer" do -> { - format("%b", Object.new) + @method.call("%b", Object.new) }.should raise_error(TypeError) end ["b", "B"].each do |f| describe f do it "converts argument as a binary number" do - format("%#{f}", 10).should == "1010" + @method.call("%#{f}", 10).should == "1010" end it "displays negative number as a two's complement prefixed with '..1'" do - format("%#{f}", -10).should == "..1" + "0110" + @method.call("%#{f}", -10).should == "..1" + "0110" end it "collapse negative number representation if it equals 1" do - format("%#{f}", -1).should_not == "..11" - format("%#{f}", -1).should == "..1" + @method.call("%#{f}", -1).should_not == "..11" + @method.call("%#{f}", -1).should == "..1" end end end @@ -56,58 +50,58 @@ def obj.to_i; 10; end ["d", "i", "u"].each do |f| describe f do it "converts argument as a decimal number" do - format("%#{f}", 112).should == "112" - format("%#{f}", -112).should == "-112" + @method.call("%#{f}", 112).should == "112" + @method.call("%#{f}", -112).should == "-112" end it "works well with large numbers" do - format("%#{f}", 1234567890987654321).should == "1234567890987654321" + @method.call("%#{f}", 1234567890987654321).should == "1234567890987654321" end end end describe "o" do it "converts argument as an octal number" do - format("%o", 87).should == "127" + @method.call("%o", 87).should == "127" end it "displays negative number as a two's complement prefixed with '..7'" do - format("%o", -87).should == "..7" + "651" + @method.call("%o", -87).should == "..7" + "651" end it "collapse negative number representation if it equals 7" do - format("%o", -1).should_not == "..77" - format("%o", -1).should == "..7" + @method.call("%o", -1).should_not == "..77" + @method.call("%o", -1).should == "..7" end end describe "x" do it "converts argument as a hexadecimal number" do - format("%x", 196).should == "c4" + @method.call("%x", 196).should == "c4" end it "displays negative number as a two's complement prefixed with '..f'" do - format("%x", -196).should == "..f" + "3c" + @method.call("%x", -196).should == "..f" + "3c" end it "collapse negative number representation if it equals f" do - format("%x", -1).should_not == "..ff" - format("%x", -1).should == "..f" + @method.call("%x", -1).should_not == "..ff" + @method.call("%x", -1).should == "..f" end end describe "X" do it "converts argument as a hexadecimal number with uppercase letters" do - format("%X", 196).should == "C4" + @method.call("%X", 196).should == "C4" end it "displays negative number as a two's complement prefixed with '..f'" do - format("%X", -196).should == "..F" + "3C" + @method.call("%X", -196).should == "..F" + "3C" end it "collapse negative number representation if it equals F" do - format("%X", -1).should_not == "..FF" - format("%X", -1).should == "..F" + @method.call("%X", -1).should_not == "..FF" + @method.call("%X", -1).should == "..F" end end end @@ -116,70 +110,70 @@ def obj.to_i; 10; end it "converts argument into Float" do obj = mock("float") obj.should_receive(:to_f).and_return(9.6) - format("%f", obj).should == "9.600000" + @method.call("%f", obj).should == "9.600000" end it "raises TypeError exception if cannot convert to Float" do -> { - format("%f", Object.new) + @method.call("%f", Object.new) }.should raise_error(TypeError) end {"e" => "e", "E" => "E"}.each_pair do |f, exp| describe f do it "converts argument into exponential notation [-]d.dddddde[+-]dd" do - format("%#{f}", 109.52).should == "1.095200#{exp}+02" - format("%#{f}", -109.52).should == "-1.095200#{exp}+02" - format("%#{f}", 0.10952).should == "1.095200#{exp}-01" - format("%#{f}", -0.10952).should == "-1.095200#{exp}-01" + @method.call("%#{f}", 109.52).should == "1.095200#{exp}+02" + @method.call("%#{f}", -109.52).should == "-1.095200#{exp}+02" + @method.call("%#{f}", 0.10952).should == "1.095200#{exp}-01" + @method.call("%#{f}", -0.10952).should == "-1.095200#{exp}-01" end it "cuts excessive digits and keeps only 6 ones" do - format("%#{f}", 1.123456789).should == "1.123457#{exp}+00" + @method.call("%#{f}", 1.123456789).should == "1.123457#{exp}+00" end it "rounds the last significant digit to the closest one" do - format("%#{f}", 1.555555555).should == "1.555556#{exp}+00" - format("%#{f}", -1.555555555).should == "-1.555556#{exp}+00" - format("%#{f}", 1.444444444).should == "1.444444#{exp}+00" + @method.call("%#{f}", 1.555555555).should == "1.555556#{exp}+00" + @method.call("%#{f}", -1.555555555).should == "-1.555556#{exp}+00" + @method.call("%#{f}", 1.444444444).should == "1.444444#{exp}+00" end it "displays Float::INFINITY as Inf" do - format("%#{f}", Float::INFINITY).should == "Inf" - format("%#{f}", -Float::INFINITY).should == "-Inf" + @method.call("%#{f}", Float::INFINITY).should == "Inf" + @method.call("%#{f}", -Float::INFINITY).should == "-Inf" end it "displays Float::NAN as NaN" do - format("%#{f}", Float::NAN).should == "NaN" - format("%#{f}", -Float::NAN).should == "NaN" + @method.call("%#{f}", Float::NAN).should == "NaN" + @method.call("%#{f}", -Float::NAN).should == "NaN" end end end describe "f" do it "converts floating point argument as [-]ddd.dddddd" do - format("%f", 10.952).should == "10.952000" - format("%f", -10.952).should == "-10.952000" + @method.call("%f", 10.952).should == "10.952000" + @method.call("%f", -10.952).should == "-10.952000" end it "cuts excessive digits and keeps only 6 ones" do - format("%f", 1.123456789).should == "1.123457" + @method.call("%f", 1.123456789).should == "1.123457" end it "rounds the last significant digit to the closest one" do - format("%f", 1.555555555).should == "1.555556" - format("%f", -1.555555555).should == "-1.555556" - format("%f", 1.444444444).should == "1.444444" + @method.call("%f", 1.555555555).should == "1.555556" + @method.call("%f", -1.555555555).should == "-1.555556" + @method.call("%f", 1.444444444).should == "1.444444" end it "displays Float::INFINITY as Inf" do - format("%f", Float::INFINITY).should == "Inf" - format("%f", -Float::INFINITY).should == "-Inf" + @method.call("%f", Float::INFINITY).should == "Inf" + @method.call("%f", -Float::INFINITY).should == "-Inf" end it "displays Float::NAN as NaN" do - format("%f", Float::NAN).should == "NaN" - format("%f", -Float::NAN).should == "NaN" + @method.call("%f", Float::NAN).should == "NaN" + @method.call("%f", -Float::NAN).should == "NaN" end end @@ -187,100 +181,100 @@ def obj.to_i; 10; end describe f do context "the exponent is less than -4" do it "converts a floating point number using exponential form" do - format("%#{f}", 0.0000123456).should == "1.23456#{exp}-05" - format("%#{f}", -0.0000123456).should == "-1.23456#{exp}-05" + @method.call("%#{f}", 0.0000123456).should == "1.23456#{exp}-05" + @method.call("%#{f}", -0.0000123456).should == "-1.23456#{exp}-05" - format("%#{f}", 0.000000000123456).should == "1.23456#{exp}-10" - format("%#{f}", -0.000000000123456).should == "-1.23456#{exp}-10" + @method.call("%#{f}", 0.000000000123456).should == "1.23456#{exp}-10" + @method.call("%#{f}", -0.000000000123456).should == "-1.23456#{exp}-10" end end context "the exponent is greater than or equal to the precision (6 by default)" do it "converts a floating point number using exponential form" do - format("%#{f}", 1234567).should == "1.23457#{exp}+06" - format("%#{f}", 1234567890123).should == "1.23457#{exp}+12" - format("%#{f}", -1234567).should == "-1.23457#{exp}+06" + @method.call("%#{f}", 1234567).should == "1.23457#{exp}+06" + @method.call("%#{f}", 1234567890123).should == "1.23457#{exp}+12" + @method.call("%#{f}", -1234567).should == "-1.23457#{exp}+06" end end context "otherwise" do it "converts a floating point number in dd.dddd form" do - format("%#{f}", 0.0001).should == "0.0001" - format("%#{f}", -0.0001).should == "-0.0001" - format("%#{f}", 123456).should == "123456" - format("%#{f}", -123456).should == "-123456" + @method.call("%#{f}", 0.0001).should == "0.0001" + @method.call("%#{f}", -0.0001).should == "-0.0001" + @method.call("%#{f}", 123456).should == "123456" + @method.call("%#{f}", -123456).should == "-123456" end it "cuts excessive digits in fractional part and keeps only 4 ones" do - format("%#{f}", 12.12341111).should == "12.1234" - format("%#{f}", -12.12341111).should == "-12.1234" + @method.call("%#{f}", 12.12341111).should == "12.1234" + @method.call("%#{f}", -12.12341111).should == "-12.1234" end it "rounds the last significant digit to the closest one in fractional part" do - format("%#{f}", 1.555555555).should == "1.55556" - format("%#{f}", -1.555555555).should == "-1.55556" - format("%#{f}", 1.444444444).should == "1.44444" + @method.call("%#{f}", 1.555555555).should == "1.55556" + @method.call("%#{f}", -1.555555555).should == "-1.55556" + @method.call("%#{f}", 1.444444444).should == "1.44444" end it "cuts fraction part to have only 6 digits at all" do - format("%#{f}", 1.1234567).should == "1.12346" - format("%#{f}", 12.1234567).should == "12.1235" - format("%#{f}", 123.1234567).should == "123.123" - format("%#{f}", 1234.1234567).should == "1234.12" - format("%#{f}", 12345.1234567).should == "12345.1" - format("%#{f}", 123456.1234567).should == "123456" + @method.call("%#{f}", 1.1234567).should == "1.12346" + @method.call("%#{f}", 12.1234567).should == "12.1235" + @method.call("%#{f}", 123.1234567).should == "123.123" + @method.call("%#{f}", 1234.1234567).should == "1234.12" + @method.call("%#{f}", 12345.1234567).should == "12345.1" + @method.call("%#{f}", 123456.1234567).should == "123456" end end it "displays Float::INFINITY as Inf" do - format("%#{f}", Float::INFINITY).should == "Inf" - format("%#{f}", -Float::INFINITY).should == "-Inf" + @method.call("%#{f}", Float::INFINITY).should == "Inf" + @method.call("%#{f}", -Float::INFINITY).should == "-Inf" end it "displays Float::NAN as NaN" do - format("%#{f}", Float::NAN).should == "NaN" - format("%#{f}", -Float::NAN).should == "NaN" + @method.call("%#{f}", Float::NAN).should == "NaN" + @method.call("%#{f}", -Float::NAN).should == "NaN" end end end describe "a" do it "converts floating point argument as [-]0xh.hhhhp[+-]dd" do - format("%a", 196).should == "0x1.88p+7" - format("%a", -196).should == "-0x1.88p+7" - format("%a", 196.1).should == "0x1.8833333333333p+7" - format("%a", 0.01).should == "0x1.47ae147ae147bp-7" - format("%a", -0.01).should == "-0x1.47ae147ae147bp-7" + @method.call("%a", 196).should == "0x1.88p+7" + @method.call("%a", -196).should == "-0x1.88p+7" + @method.call("%a", 196.1).should == "0x1.8833333333333p+7" + @method.call("%a", 0.01).should == "0x1.47ae147ae147bp-7" + @method.call("%a", -0.01).should == "-0x1.47ae147ae147bp-7" end it "displays Float::INFINITY as Inf" do - format("%a", Float::INFINITY).should == "Inf" - format("%a", -Float::INFINITY).should == "-Inf" + @method.call("%a", Float::INFINITY).should == "Inf" + @method.call("%a", -Float::INFINITY).should == "-Inf" end it "displays Float::NAN as NaN" do - format("%a", Float::NAN).should == "NaN" - format("%a", -Float::NAN).should == "NaN" + @method.call("%a", Float::NAN).should == "NaN" + @method.call("%a", -Float::NAN).should == "NaN" end end describe "A" do it "converts floating point argument as [-]0xh.hhhhp[+-]dd and use uppercase X and P" do - format("%A", 196).should == "0X1.88P+7" - format("%A", -196).should == "-0X1.88P+7" - format("%A", 196.1).should == "0X1.8833333333333P+7" - format("%A", 0.01).should == "0X1.47AE147AE147BP-7" - format("%A", -0.01).should == "-0X1.47AE147AE147BP-7" + @method.call("%A", 196).should == "0X1.88P+7" + @method.call("%A", -196).should == "-0X1.88P+7" + @method.call("%A", 196.1).should == "0X1.8833333333333P+7" + @method.call("%A", 0.01).should == "0X1.47AE147AE147BP-7" + @method.call("%A", -0.01).should == "-0X1.47AE147AE147BP-7" end it "displays Float::INFINITY as Inf" do - format("%A", Float::INFINITY).should == "Inf" - format("%A", -Float::INFINITY).should == "-Inf" + @method.call("%A", Float::INFINITY).should == "Inf" + @method.call("%A", -Float::INFINITY).should == "-Inf" end it "displays Float::NAN as NaN" do - format("%A", Float::NAN).should == "NaN" - format("%A", -Float::NAN).should == "NaN" + @method.call("%A", Float::NAN).should == "NaN" + @method.call("%A", -Float::NAN).should == "NaN" end end end @@ -288,28 +282,28 @@ def obj.to_i; 10; end describe "other formats" do describe "c" do it "displays character if argument is a numeric code of character" do - format("%c", 97).should == "a" + @method.call("%c", 97).should == "a" end it "displays character if argument is a single character string" do - format("%c", "a").should == "a" + @method.call("%c", "a").should == "a" end it "raises ArgumentError if argument is a string of several characters" do -> { - format("%c", "abc") + @method.call("%c", "abc") }.should raise_error(ArgumentError) end it "raises ArgumentError if argument is an empty string" do -> { - format("%c", "") + @method.call("%c", "") }.should raise_error(ArgumentError) end it "supports Unicode characters" do - format("%c", 1286).should == "Ô†" - format("%c", "Ø´").should == "Ø´" + @method.call("%c", 1286).should == "Ô†" + @method.call("%c", "Ø´").should == "Ø´" end end @@ -317,19 +311,23 @@ def obj.to_i; 10; end it "displays argument.inspect value" do obj = mock("object") obj.should_receive(:inspect).and_return("") - format("%p", obj).should == "" + @method.call("%p", obj).should == "" end end describe "s" do it "substitute argument passes as a string" do - format("%s", "abc").should == "abc" + @method.call("%s", "abc").should == "abc" + end + + it "substitutes '' for nil" do + @method.call("%s", nil).should == "" end it "converts argument to string with to_s" do obj = mock("string") obj.should_receive(:to_s).and_return("abc") - format("%s", obj).should == "abc" + @method.call("%s", obj).should == "abc" end it "does not try to convert with to_str" do @@ -339,29 +337,66 @@ def obj.to_str end -> { - format("%s", obj) + @method.call("%s", obj) }.should raise_error(NoMethodError) end - end - describe "%" do - ruby_version_is ""..."2.5" do - it "alone displays the percent sign" do - format("%").should == "%" - end + it "formats a partial substring without including omitted characters" do + long_string = "aabbccddhelloddccbbaa" + sub_string = long_string[8, 5] + sprintf("%.#{1 * 3}s", sub_string).should == "hel" end - ruby_version_is "2.5" do - it "alone raises an ArgumentError" do - -> { - format("%") - }.should raise_error(ArgumentError) - end + it "formats string with precision" do + Kernel.format("%.3s", "hello").should == "hel" + Kernel.format("%-3.3s", "hello").should == "hel" + end + + it "formats string with width" do + @method.call("%6s", "abc").should == " abc" + @method.call("%6s", "abcdefg").should == "abcdefg" + end + + it "formats string with width and precision" do + @method.call("%4.6s", "abc").should == " abc" + @method.call("%4.6s", "abcdefg").should == "abcdef" + end + + it "formats nli with width" do + @method.call("%6s", nil).should == " " + end + + it "formats nli with precision" do + @method.call("%.6s", nil).should == "" + end + + it "formats nil with width and precision" do + @method.call("%4.6s", nil).should == " " + end + + it "formats multibyte string with precision" do + Kernel.format("%.2s", "été").should == "ét" + end + + it "preserves encoding of the format string" do + str = format('%s'.encode(Encoding::UTF_8), 'foobar') + str.encoding.should == Encoding::UTF_8 + + str = format('%s'.encode(Encoding::US_ASCII), 'foobar') + str.encoding.should == Encoding::US_ASCII + end + end + + describe "%" do + it "alone raises an ArgumentError" do + -> { + @method.call("%") + }.should raise_error(ArgumentError) end it "is escaped by %" do - format("%%").should == "%" - format("%%d", 10).should == "%d" + @method.call("%%").should == "%" + @method.call("%%d", 10).should == "%d" end end end @@ -370,110 +405,110 @@ def obj.to_str describe "space" do context "applies to numeric formats bBdiouxXeEfgGaA" do it "leaves a space at the start of non-negative numbers" do - format("% b", 10).should == " 1010" - format("% B", 10).should == " 1010" - format("% d", 112).should == " 112" - format("% i", 112).should == " 112" - format("% o", 87).should == " 127" - format("% u", 112).should == " 112" - format("% x", 196).should == " c4" - format("% X", 196).should == " C4" - - format("% e", 109.52).should == " 1.095200e+02" - format("% E", 109.52).should == " 1.095200E+02" - format("% f", 10.952).should == " 10.952000" - format("% g", 12.1234).should == " 12.1234" - format("% G", 12.1234).should == " 12.1234" - format("% a", 196).should == " 0x1.88p+7" - format("% A", 196).should == " 0X1.88P+7" + @method.call("% b", 10).should == " 1010" + @method.call("% B", 10).should == " 1010" + @method.call("% d", 112).should == " 112" + @method.call("% i", 112).should == " 112" + @method.call("% o", 87).should == " 127" + @method.call("% u", 112).should == " 112" + @method.call("% x", 196).should == " c4" + @method.call("% X", 196).should == " C4" + + @method.call("% e", 109.52).should == " 1.095200e+02" + @method.call("% E", 109.52).should == " 1.095200E+02" + @method.call("% f", 10.952).should == " 10.952000" + @method.call("% g", 12.1234).should == " 12.1234" + @method.call("% G", 12.1234).should == " 12.1234" + @method.call("% a", 196).should == " 0x1.88p+7" + @method.call("% A", 196).should == " 0X1.88P+7" end it "does not leave a space at the start of negative numbers" do - format("% b", -10).should == "-1010" - format("% B", -10).should == "-1010" - format("% d", -112).should == "-112" - format("% i", -112).should == "-112" - format("% o", -87).should == "-127" - format("% u", -112).should == "-112" - format("% x", -196).should == "-c4" - format("% X", -196).should == "-C4" - - format("% e", -109.52).should == "-1.095200e+02" - format("% E", -109.52).should == "-1.095200E+02" - format("% f", -10.952).should == "-10.952000" - format("% g", -12.1234).should == "-12.1234" - format("% G", -12.1234).should == "-12.1234" - format("% a", -196).should == "-0x1.88p+7" - format("% A", -196).should == "-0X1.88P+7" + @method.call("% b", -10).should == "-1010" + @method.call("% B", -10).should == "-1010" + @method.call("% d", -112).should == "-112" + @method.call("% i", -112).should == "-112" + @method.call("% o", -87).should == "-127" + @method.call("% u", -112).should == "-112" + @method.call("% x", -196).should == "-c4" + @method.call("% X", -196).should == "-C4" + + @method.call("% e", -109.52).should == "-1.095200e+02" + @method.call("% E", -109.52).should == "-1.095200E+02" + @method.call("% f", -10.952).should == "-10.952000" + @method.call("% g", -12.1234).should == "-12.1234" + @method.call("% G", -12.1234).should == "-12.1234" + @method.call("% a", -196).should == "-0x1.88p+7" + @method.call("% A", -196).should == "-0X1.88P+7" end it "prevents converting negative argument to two's complement form" do - format("% b", -10).should == "-1010" - format("% B", -10).should == "-1010" - format("% o", -87).should == "-127" - format("% x", -196).should == "-c4" - format("% X", -196).should == "-C4" + @method.call("% b", -10).should == "-1010" + @method.call("% B", -10).should == "-1010" + @method.call("% o", -87).should == "-127" + @method.call("% x", -196).should == "-c4" + @method.call("% X", -196).should == "-C4" end it "treats several white spaces as one" do - format("% b", 10).should == " 1010" - format("% B", 10).should == " 1010" - format("% d", 112).should == " 112" - format("% i", 112).should == " 112" - format("% o", 87).should == " 127" - format("% u", 112).should == " 112" - format("% x", 196).should == " c4" - format("% X", 196).should == " C4" - - format("% e", 109.52).should == " 1.095200e+02" - format("% E", 109.52).should == " 1.095200E+02" - format("% f", 10.952).should == " 10.952000" - format("% g", 12.1234).should == " 12.1234" - format("% G", 12.1234).should == " 12.1234" - format("% a", 196).should == " 0x1.88p+7" - format("% A", 196).should == " 0X1.88P+7" + @method.call("% b", 10).should == " 1010" + @method.call("% B", 10).should == " 1010" + @method.call("% d", 112).should == " 112" + @method.call("% i", 112).should == " 112" + @method.call("% o", 87).should == " 127" + @method.call("% u", 112).should == " 112" + @method.call("% x", 196).should == " c4" + @method.call("% X", 196).should == " C4" + + @method.call("% e", 109.52).should == " 1.095200e+02" + @method.call("% E", 109.52).should == " 1.095200E+02" + @method.call("% f", 10.952).should == " 10.952000" + @method.call("% g", 12.1234).should == " 12.1234" + @method.call("% G", 12.1234).should == " 12.1234" + @method.call("% a", 196).should == " 0x1.88p+7" + @method.call("% A", 196).should == " 0X1.88P+7" end end end describe "(digit)$" do it "specifies the absolute argument number for this field" do - format("%2$b", 0, 10).should == "1010" - format("%2$B", 0, 10).should == "1010" - format("%2$d", 0, 112).should == "112" - format("%2$i", 0, 112).should == "112" - format("%2$o", 0, 87).should == "127" - format("%2$u", 0, 112).should == "112" - format("%2$x", 0, 196).should == "c4" - format("%2$X", 0, 196).should == "C4" - - format("%2$e", 0, 109.52).should == "1.095200e+02" - format("%2$E", 0, 109.52).should == "1.095200E+02" - format("%2$f", 0, 10.952).should == "10.952000" - format("%2$g", 0, 12.1234).should == "12.1234" - format("%2$G", 0, 12.1234).should == "12.1234" - format("%2$a", 0, 196).should == "0x1.88p+7" - format("%2$A", 0, 196).should == "0X1.88P+7" - - format("%2$c", 1, 97).should == "a" - format("%2$p", "a", []).should == "[]" - format("%2$s", "-", "abc").should == "abc" + @method.call("%2$b", 0, 10).should == "1010" + @method.call("%2$B", 0, 10).should == "1010" + @method.call("%2$d", 0, 112).should == "112" + @method.call("%2$i", 0, 112).should == "112" + @method.call("%2$o", 0, 87).should == "127" + @method.call("%2$u", 0, 112).should == "112" + @method.call("%2$x", 0, 196).should == "c4" + @method.call("%2$X", 0, 196).should == "C4" + + @method.call("%2$e", 0, 109.52).should == "1.095200e+02" + @method.call("%2$E", 0, 109.52).should == "1.095200E+02" + @method.call("%2$f", 0, 10.952).should == "10.952000" + @method.call("%2$g", 0, 12.1234).should == "12.1234" + @method.call("%2$G", 0, 12.1234).should == "12.1234" + @method.call("%2$a", 0, 196).should == "0x1.88p+7" + @method.call("%2$A", 0, 196).should == "0X1.88P+7" + + @method.call("%2$c", 1, 97).should == "a" + @method.call("%2$p", "a", []).should == "[]" + @method.call("%2$s", "-", "abc").should == "abc" end it "raises exception if argument number is bigger than actual arguments list" do -> { - format("%4$d", 1, 2, 3) + @method.call("%4$d", 1, 2, 3) }.should raise_error(ArgumentError) end it "ignores '-' sign" do - format("%2$d", 1, 2, 3).should == "2" - format("%-2$d", 1, 2, 3).should == "2" + @method.call("%2$d", 1, 2, 3).should == "2" + @method.call("%-2$d", 1, 2, 3).should == "2" end it "raises ArgumentError exception when absolute and relative argument numbers are mixed" do -> { - format("%1$d %d", 1, 2) + @method.call("%1$d %d", 1, 2) }.should raise_error(ArgumentError) end end @@ -481,62 +516,62 @@ def obj.to_str describe "#" do context "applies to format o" do it "increases the precision until the first digit will be `0' if it is not formatted as complements" do - format("%#o", 87).should == "0127" + @method.call("%#o", 87).should == "0127" end it "does nothing for negative argument" do - format("%#o", -87).should == "..7651" + @method.call("%#o", -87).should == "..7651" end end context "applies to formats bBxX" do it "prefixes the result with 0x, 0X, 0b and 0B respectively for non-zero argument" do - format("%#b", 10).should == "0b1010" - format("%#b", -10).should == "0b..10110" - format("%#B", 10).should == "0B1010" - format("%#B", -10).should == "0B..10110" - - format("%#x", 196).should == "0xc4" - format("%#x", -196).should == "0x..f3c" - format("%#X", 196).should == "0XC4" - format("%#X", -196).should == "0X..F3C" + @method.call("%#b", 10).should == "0b1010" + @method.call("%#b", -10).should == "0b..10110" + @method.call("%#B", 10).should == "0B1010" + @method.call("%#B", -10).should == "0B..10110" + + @method.call("%#x", 196).should == "0xc4" + @method.call("%#x", -196).should == "0x..f3c" + @method.call("%#X", 196).should == "0XC4" + @method.call("%#X", -196).should == "0X..F3C" end it "does nothing for zero argument" do - format("%#b", 0).should == "0" - format("%#B", 0).should == "0" + @method.call("%#b", 0).should == "0" + @method.call("%#B", 0).should == "0" - format("%#o", 0).should == "0" + @method.call("%#o", 0).should == "0" - format("%#x", 0).should == "0" - format("%#X", 0).should == "0" + @method.call("%#x", 0).should == "0" + @method.call("%#X", 0).should == "0" end end context "applies to formats aAeEfgG" do it "forces a decimal point to be added, even if no digits follow" do - format("%#.0a", 16.25).should == "0x1.p+4" - format("%#.0A", 16.25).should == "0X1.P+4" + @method.call("%#.0a", 16.25).should == "0x1.p+4" + @method.call("%#.0A", 16.25).should == "0X1.P+4" - format("%#.0e", 100).should == "1.e+02" - format("%#.0E", 100).should == "1.E+02" + @method.call("%#.0e", 100).should == "1.e+02" + @method.call("%#.0E", 100).should == "1.E+02" - format("%#.0f", 123.4).should == "123." + @method.call("%#.0f", 123.4).should == "123." - format("%#g", 123456).should == "123456." - format("%#G", 123456).should == "123456." + @method.call("%#g", 123456).should == "123456." + @method.call("%#G", 123456).should == "123456." end it "changes format from dd.dddd to exponential form for gG" do - format("%#.0g", 123.4).should_not == "123." - format("%#.0g", 123.4).should == "1.e+02" + @method.call("%#.0g", 123.4).should_not == "123." + @method.call("%#.0g", 123.4).should == "1.e+02" end end context "applies to gG" do it "does not remove trailing zeros" do - format("%#g", 123.4).should == "123.400" - format("%#g", 123.4).should == "123.400" + @method.call("%#g", 123.4).should == "123.400" + @method.call("%#g", 123.4).should == "123.400" end end end @@ -544,186 +579,186 @@ def obj.to_str describe "+" do context "applies to numeric formats bBdiouxXaAeEfgG" do it "adds a leading plus sign to non-negative numbers" do - format("%+b", 10).should == "+1010" - format("%+B", 10).should == "+1010" - format("%+d", 112).should == "+112" - format("%+i", 112).should == "+112" - format("%+o", 87).should == "+127" - format("%+u", 112).should == "+112" - format("%+x", 196).should == "+c4" - format("%+X", 196).should == "+C4" - - format("%+e", 109.52).should == "+1.095200e+02" - format("%+E", 109.52).should == "+1.095200E+02" - format("%+f", 10.952).should == "+10.952000" - format("%+g", 12.1234).should == "+12.1234" - format("%+G", 12.1234).should == "+12.1234" - format("%+a", 196).should == "+0x1.88p+7" - format("%+A", 196).should == "+0X1.88P+7" + @method.call("%+b", 10).should == "+1010" + @method.call("%+B", 10).should == "+1010" + @method.call("%+d", 112).should == "+112" + @method.call("%+i", 112).should == "+112" + @method.call("%+o", 87).should == "+127" + @method.call("%+u", 112).should == "+112" + @method.call("%+x", 196).should == "+c4" + @method.call("%+X", 196).should == "+C4" + + @method.call("%+e", 109.52).should == "+1.095200e+02" + @method.call("%+E", 109.52).should == "+1.095200E+02" + @method.call("%+f", 10.952).should == "+10.952000" + @method.call("%+g", 12.1234).should == "+12.1234" + @method.call("%+G", 12.1234).should == "+12.1234" + @method.call("%+a", 196).should == "+0x1.88p+7" + @method.call("%+A", 196).should == "+0X1.88P+7" end it "does not use two's complement form for negative numbers for formats bBoxX" do - format("%+b", -10).should == "-1010" - format("%+B", -10).should == "-1010" - format("%+o", -87).should == "-127" - format("%+x", -196).should == "-c4" - format("%+X", -196).should == "-C4" + @method.call("%+b", -10).should == "-1010" + @method.call("%+B", -10).should == "-1010" + @method.call("%+o", -87).should == "-127" + @method.call("%+x", -196).should == "-c4" + @method.call("%+X", -196).should == "-C4" end end end describe "-" do it "left-justifies the result of conversion if width is specified" do - format("%-10b", 10).should == "1010 " - format("%-10B", 10).should == "1010 " - format("%-10d", 112).should == "112 " - format("%-10i", 112).should == "112 " - format("%-10o", 87).should == "127 " - format("%-10u", 112).should == "112 " - format("%-10x", 196).should == "c4 " - format("%-10X", 196).should == "C4 " + @method.call("%-10b", 10).should == "1010 " + @method.call("%-10B", 10).should == "1010 " + @method.call("%-10d", 112).should == "112 " + @method.call("%-10i", 112).should == "112 " + @method.call("%-10o", 87).should == "127 " + @method.call("%-10u", 112).should == "112 " + @method.call("%-10x", 196).should == "c4 " + @method.call("%-10X", 196).should == "C4 " - format("%-20e", 109.52).should == "1.095200e+02 " - format("%-20E", 109.52).should == "1.095200E+02 " - format("%-20f", 10.952).should == "10.952000 " - format("%-20g", 12.1234).should == "12.1234 " - format("%-20G", 12.1234).should == "12.1234 " - format("%-20a", 196).should == "0x1.88p+7 " - format("%-20A", 196).should == "0X1.88P+7 " + @method.call("%-20e", 109.52).should == "1.095200e+02 " + @method.call("%-20E", 109.52).should == "1.095200E+02 " + @method.call("%-20f", 10.952).should == "10.952000 " + @method.call("%-20g", 12.1234).should == "12.1234 " + @method.call("%-20G", 12.1234).should == "12.1234 " + @method.call("%-20a", 196).should == "0x1.88p+7 " + @method.call("%-20A", 196).should == "0X1.88P+7 " - format("%-10c", 97).should == "a " - format("%-10p", []).should == "[] " - format("%-10s", "abc").should == "abc " + @method.call("%-10c", 97).should == "a " + @method.call("%-10p", []).should == "[] " + @method.call("%-10s", "abc").should == "abc " end end describe "0 (zero)" do context "applies to numeric formats bBdiouxXaAeEfgG and width is specified" do it "pads with zeros, not spaces" do - format("%010b", 10).should == "0000001010" - format("%010B", 10).should == "0000001010" - format("%010d", 112).should == "0000000112" - format("%010i", 112).should == "0000000112" - format("%010o", 87).should == "0000000127" - format("%010u", 112).should == "0000000112" - format("%010x", 196).should == "00000000c4" - format("%010X", 196).should == "00000000C4" - - format("%020e", 109.52).should == "000000001.095200e+02" - format("%020E", 109.52).should == "000000001.095200E+02" - format("%020f", 10.952).should == "0000000000010.952000" - format("%020g", 12.1234).should == "000000000000012.1234" - format("%020G", 12.1234).should == "000000000000012.1234" - format("%020a", 196).should == "0x000000000001.88p+7" - format("%020A", 196).should == "0X000000000001.88P+7" + @method.call("%010b", 10).should == "0000001010" + @method.call("%010B", 10).should == "0000001010" + @method.call("%010d", 112).should == "0000000112" + @method.call("%010i", 112).should == "0000000112" + @method.call("%010o", 87).should == "0000000127" + @method.call("%010u", 112).should == "0000000112" + @method.call("%010x", 196).should == "00000000c4" + @method.call("%010X", 196).should == "00000000C4" + + @method.call("%020e", 109.52).should == "000000001.095200e+02" + @method.call("%020E", 109.52).should == "000000001.095200E+02" + @method.call("%020f", 10.952).should == "0000000000010.952000" + @method.call("%020g", 12.1234).should == "000000000000012.1234" + @method.call("%020G", 12.1234).should == "000000000000012.1234" + @method.call("%020a", 196).should == "0x000000000001.88p+7" + @method.call("%020A", 196).should == "0X000000000001.88P+7" end it "uses radix-1 when displays negative argument as a two's complement" do - format("%010b", -10).should == "..11110110" - format("%010B", -10).should == "..11110110" - format("%010o", -87).should == "..77777651" - format("%010x", -196).should == "..ffffff3c" - format("%010X", -196).should == "..FFFFFF3C" + @method.call("%010b", -10).should == "..11110110" + @method.call("%010B", -10).should == "..11110110" + @method.call("%010o", -87).should == "..77777651" + @method.call("%010x", -196).should == "..ffffff3c" + @method.call("%010X", -196).should == "..FFFFFF3C" end end end describe "*" do it "uses the previous argument as the field width" do - format("%*b", 10, 10).should == " 1010" - format("%*B", 10, 10).should == " 1010" - format("%*d", 10, 112).should == " 112" - format("%*i", 10, 112).should == " 112" - format("%*o", 10, 87).should == " 127" - format("%*u", 10, 112).should == " 112" - format("%*x", 10, 196).should == " c4" - format("%*X", 10, 196).should == " C4" - - format("%*e", 20, 109.52).should == " 1.095200e+02" - format("%*E", 20, 109.52).should == " 1.095200E+02" - format("%*f", 20, 10.952).should == " 10.952000" - format("%*g", 20, 12.1234).should == " 12.1234" - format("%*G", 20, 12.1234).should == " 12.1234" - format("%*a", 20, 196).should == " 0x1.88p+7" - format("%*A", 20, 196).should == " 0X1.88P+7" - - format("%*c", 10, 97).should == " a" - format("%*p", 10, []).should == " []" - format("%*s", 10, "abc").should == " abc" + @method.call("%*b", 10, 10).should == " 1010" + @method.call("%*B", 10, 10).should == " 1010" + @method.call("%*d", 10, 112).should == " 112" + @method.call("%*i", 10, 112).should == " 112" + @method.call("%*o", 10, 87).should == " 127" + @method.call("%*u", 10, 112).should == " 112" + @method.call("%*x", 10, 196).should == " c4" + @method.call("%*X", 10, 196).should == " C4" + + @method.call("%*e", 20, 109.52).should == " 1.095200e+02" + @method.call("%*E", 20, 109.52).should == " 1.095200E+02" + @method.call("%*f", 20, 10.952).should == " 10.952000" + @method.call("%*g", 20, 12.1234).should == " 12.1234" + @method.call("%*G", 20, 12.1234).should == " 12.1234" + @method.call("%*a", 20, 196).should == " 0x1.88p+7" + @method.call("%*A", 20, 196).should == " 0X1.88P+7" + + @method.call("%*c", 10, 97).should == " a" + @method.call("%*p", 10, []).should == " []" + @method.call("%*s", 10, "abc").should == " abc" end it "left-justifies the result if width is negative" do - format("%*b", -10, 10).should == "1010 " - format("%*B", -10, 10).should == "1010 " - format("%*d", -10, 112).should == "112 " - format("%*i", -10, 112).should == "112 " - format("%*o", -10, 87).should == "127 " - format("%*u", -10, 112).should == "112 " - format("%*x", -10, 196).should == "c4 " - format("%*X", -10, 196).should == "C4 " - - format("%*e", -20, 109.52).should == "1.095200e+02 " - format("%*E", -20, 109.52).should == "1.095200E+02 " - format("%*f", -20, 10.952).should == "10.952000 " - format("%*g", -20, 12.1234).should == "12.1234 " - format("%*G", -20, 12.1234).should == "12.1234 " - format("%*a", -20, 196).should == "0x1.88p+7 " - format("%*A", -20, 196).should == "0X1.88P+7 " - - format("%*c", -10, 97).should == "a " - format("%*p", -10, []).should == "[] " - format("%*s", -10, "abc").should == "abc " + @method.call("%*b", -10, 10).should == "1010 " + @method.call("%*B", -10, 10).should == "1010 " + @method.call("%*d", -10, 112).should == "112 " + @method.call("%*i", -10, 112).should == "112 " + @method.call("%*o", -10, 87).should == "127 " + @method.call("%*u", -10, 112).should == "112 " + @method.call("%*x", -10, 196).should == "c4 " + @method.call("%*X", -10, 196).should == "C4 " + + @method.call("%*e", -20, 109.52).should == "1.095200e+02 " + @method.call("%*E", -20, 109.52).should == "1.095200E+02 " + @method.call("%*f", -20, 10.952).should == "10.952000 " + @method.call("%*g", -20, 12.1234).should == "12.1234 " + @method.call("%*G", -20, 12.1234).should == "12.1234 " + @method.call("%*a", -20, 196).should == "0x1.88p+7 " + @method.call("%*A", -20, 196).should == "0X1.88P+7 " + + @method.call("%*c", -10, 97).should == "a " + @method.call("%*p", -10, []).should == "[] " + @method.call("%*s", -10, "abc").should == "abc " end it "uses the specified argument as the width if * is followed by a number and $" do - format("%1$*2$b", 10, 10).should == " 1010" - format("%1$*2$B", 10, 10).should == " 1010" - format("%1$*2$d", 112, 10).should == " 112" - format("%1$*2$i", 112, 10).should == " 112" - format("%1$*2$o", 87, 10).should == " 127" - format("%1$*2$u", 112, 10).should == " 112" - format("%1$*2$x", 196, 10).should == " c4" - format("%1$*2$X", 196, 10).should == " C4" - - format("%1$*2$e", 109.52, 20).should == " 1.095200e+02" - format("%1$*2$E", 109.52, 20).should == " 1.095200E+02" - format("%1$*2$f", 10.952, 20).should == " 10.952000" - format("%1$*2$g", 12.1234, 20).should == " 12.1234" - format("%1$*2$G", 12.1234, 20).should == " 12.1234" - format("%1$*2$a", 196, 20).should == " 0x1.88p+7" - format("%1$*2$A", 196, 20).should == " 0X1.88P+7" - - format("%1$*2$c", 97, 10).should == " a" - format("%1$*2$p", [], 10).should == " []" - format("%1$*2$s", "abc", 10).should == " abc" + @method.call("%1$*2$b", 10, 10).should == " 1010" + @method.call("%1$*2$B", 10, 10).should == " 1010" + @method.call("%1$*2$d", 112, 10).should == " 112" + @method.call("%1$*2$i", 112, 10).should == " 112" + @method.call("%1$*2$o", 87, 10).should == " 127" + @method.call("%1$*2$u", 112, 10).should == " 112" + @method.call("%1$*2$x", 196, 10).should == " c4" + @method.call("%1$*2$X", 196, 10).should == " C4" + + @method.call("%1$*2$e", 109.52, 20).should == " 1.095200e+02" + @method.call("%1$*2$E", 109.52, 20).should == " 1.095200E+02" + @method.call("%1$*2$f", 10.952, 20).should == " 10.952000" + @method.call("%1$*2$g", 12.1234, 20).should == " 12.1234" + @method.call("%1$*2$G", 12.1234, 20).should == " 12.1234" + @method.call("%1$*2$a", 196, 20).should == " 0x1.88p+7" + @method.call("%1$*2$A", 196, 20).should == " 0X1.88P+7" + + @method.call("%1$*2$c", 97, 10).should == " a" + @method.call("%1$*2$p", [], 10).should == " []" + @method.call("%1$*2$s", "abc", 10).should == " abc" end it "left-justifies the result if specified with $ argument is negative" do - format("%1$*2$b", 10, -10).should == "1010 " - format("%1$*2$B", 10, -10).should == "1010 " - format("%1$*2$d", 112, -10).should == "112 " - format("%1$*2$i", 112, -10).should == "112 " - format("%1$*2$o", 87, -10).should == "127 " - format("%1$*2$u", 112, -10).should == "112 " - format("%1$*2$x", 196, -10).should == "c4 " - format("%1$*2$X", 196, -10).should == "C4 " - - format("%1$*2$e", 109.52, -20).should == "1.095200e+02 " - format("%1$*2$E", 109.52, -20).should == "1.095200E+02 " - format("%1$*2$f", 10.952, -20).should == "10.952000 " - format("%1$*2$g", 12.1234, -20).should == "12.1234 " - format("%1$*2$G", 12.1234, -20).should == "12.1234 " - format("%1$*2$a", 196, -20).should == "0x1.88p+7 " - format("%1$*2$A", 196, -20).should == "0X1.88P+7 " - - format("%1$*2$c", 97, -10).should == "a " - format("%1$*2$p", [], -10).should == "[] " - format("%1$*2$s", "abc", -10).should == "abc " + @method.call("%1$*2$b", 10, -10).should == "1010 " + @method.call("%1$*2$B", 10, -10).should == "1010 " + @method.call("%1$*2$d", 112, -10).should == "112 " + @method.call("%1$*2$i", 112, -10).should == "112 " + @method.call("%1$*2$o", 87, -10).should == "127 " + @method.call("%1$*2$u", 112, -10).should == "112 " + @method.call("%1$*2$x", 196, -10).should == "c4 " + @method.call("%1$*2$X", 196, -10).should == "C4 " + + @method.call("%1$*2$e", 109.52, -20).should == "1.095200e+02 " + @method.call("%1$*2$E", 109.52, -20).should == "1.095200E+02 " + @method.call("%1$*2$f", 10.952, -20).should == "10.952000 " + @method.call("%1$*2$g", 12.1234, -20).should == "12.1234 " + @method.call("%1$*2$G", 12.1234, -20).should == "12.1234 " + @method.call("%1$*2$a", 196, -20).should == "0x1.88p+7 " + @method.call("%1$*2$A", 196, -20).should == "0X1.88P+7 " + + @method.call("%1$*2$c", 97, -10).should == "a " + @method.call("%1$*2$p", [], -10).should == "[] " + @method.call("%1$*2$s", "abc", -10).should == "abc " end it "raises ArgumentError when is mixed with width" do -> { - format("%*10d", 10, 112) + @method.call("%*10d", 10, 112) }.should raise_error(ArgumentError) end end @@ -731,74 +766,74 @@ def obj.to_str describe "width" do it "specifies the minimum number of characters that will be written to the result" do - format("%10b", 10).should == " 1010" - format("%10B", 10).should == " 1010" - format("%10d", 112).should == " 112" - format("%10i", 112).should == " 112" - format("%10o", 87).should == " 127" - format("%10u", 112).should == " 112" - format("%10x", 196).should == " c4" - format("%10X", 196).should == " C4" - - format("%20e", 109.52).should == " 1.095200e+02" - format("%20E", 109.52).should == " 1.095200E+02" - format("%20f", 10.952).should == " 10.952000" - format("%20g", 12.1234).should == " 12.1234" - format("%20G", 12.1234).should == " 12.1234" - format("%20a", 196).should == " 0x1.88p+7" - format("%20A", 196).should == " 0X1.88P+7" - - format("%10c", 97).should == " a" - format("%10p", []).should == " []" - format("%10s", "abc").should == " abc" + @method.call("%10b", 10).should == " 1010" + @method.call("%10B", 10).should == " 1010" + @method.call("%10d", 112).should == " 112" + @method.call("%10i", 112).should == " 112" + @method.call("%10o", 87).should == " 127" + @method.call("%10u", 112).should == " 112" + @method.call("%10x", 196).should == " c4" + @method.call("%10X", 196).should == " C4" + + @method.call("%20e", 109.52).should == " 1.095200e+02" + @method.call("%20E", 109.52).should == " 1.095200E+02" + @method.call("%20f", 10.952).should == " 10.952000" + @method.call("%20g", 12.1234).should == " 12.1234" + @method.call("%20G", 12.1234).should == " 12.1234" + @method.call("%20a", 196).should == " 0x1.88p+7" + @method.call("%20A", 196).should == " 0X1.88P+7" + + @method.call("%10c", 97).should == " a" + @method.call("%10p", []).should == " []" + @method.call("%10s", "abc").should == " abc" end it "is ignored if argument's actual length is greater" do - format("%5d", 1234567890).should == "1234567890" + @method.call("%5d", 1234567890).should == "1234567890" end end describe "precision" do context "integer types" do it "controls the number of decimal places displayed" do - format("%.6b", 10).should == "001010" - format("%.6B", 10).should == "001010" - format("%.5d", 112).should == "00112" - format("%.5i", 112).should == "00112" - format("%.5o", 87).should == "00127" - format("%.5u", 112).should == "00112" + @method.call("%.6b", 10).should == "001010" + @method.call("%.6B", 10).should == "001010" + @method.call("%.5d", 112).should == "00112" + @method.call("%.5i", 112).should == "00112" + @method.call("%.5o", 87).should == "00127" + @method.call("%.5u", 112).should == "00112" - format("%.5x", 196).should == "000c4" - format("%.5X", 196).should == "000C4" + @method.call("%.5x", 196).should == "000c4" + @method.call("%.5X", 196).should == "000C4" end end context "float types" do it "controls the number of decimal places displayed in fraction part" do - format("%.10e", 109.52).should == "1.0952000000e+02" - format("%.10E", 109.52).should == "1.0952000000E+02" - format("%.10f", 10.952).should == "10.9520000000" - format("%.10a", 196).should == "0x1.8800000000p+7" - format("%.10A", 196).should == "0X1.8800000000P+7" + @method.call("%.10e", 109.52).should == "1.0952000000e+02" + @method.call("%.10E", 109.52).should == "1.0952000000E+02" + @method.call("%.10f", 10.952).should == "10.9520000000" + @method.call("%.10a", 196).should == "0x1.8800000000p+7" + @method.call("%.10A", 196).should == "0X1.8800000000P+7" end it "does not affect G format" do - format("%.10g", 12.1234).should == "12.1234" - format("%.10g", 123456789).should == "123456789" + @method.call("%.10g", 12.1234).should == "12.1234" + @method.call("%.10g", 123456789).should == "123456789" end end context "string formats" do it "determines the maximum number of characters to be copied from the string" do - format("%.1p", [1]).should == "[" - format("%.2p", [1]).should == "[1" - format("%.10p", [1]).should == "[1]" - format("%.0p", [1]).should == "" + @method.call("%.1p", [1]).should == "[" + @method.call("%.2p", [1]).should == "[1" + @method.call("%.10p", [1]).should == "[1]" + @method.call("%.0p", [1]).should == "" - format("%.1s", "abc").should == "a" - format("%.2s", "abc").should == "ab" - format("%.10s", "abc").should == "abc" - format("%.0s", "abc").should == "" + @method.call("%.1s", "abc").should == "a" + @method.call("%.2s", "abc").should == "ab" + @method.call("%.10s", "abc").should == "abc" + @method.call("%.0s", "abc").should == "" end end end @@ -806,49 +841,49 @@ def obj.to_str describe "reference by name" do describe "%s style" do it "uses value passed in a hash argument" do - format("%d", foo: 123).should == "123" + @method.call("%d", foo: 123).should == "123" end it "supports flags, width, precision and type" do - format("%+20.10f", foo: 10.952).should == " +10.9520000000" + @method.call("%+20.10f", foo: 10.952).should == " +10.9520000000" end it "allows to place name in any position" do - format("%+15.5f", foo: 10.952).should == " +10.95200" - format("%+15.5f", foo: 10.952).should == " +10.95200" - format("%+15.5f", foo: 10.952).should == " +10.95200" - format("%+15.5f", foo: 10.952).should == " +10.95200" + @method.call("%+15.5f", foo: 10.952).should == " +10.95200" + @method.call("%+15.5f", foo: 10.952).should == " +10.95200" + @method.call("%+15.5f", foo: 10.952).should == " +10.95200" + @method.call("%+15.5f", foo: 10.952).should == " +10.95200" end it "cannot be mixed with unnamed style" do -> { - format("%d %d", 1, foo: "123") + @method.call("%d %d", 1, foo: "123") }.should raise_error(ArgumentError) end end describe "%{name} style" do it "uses value passed in a hash argument" do - format("%{foo}", foo: 123).should == "123" + @method.call("%{foo}", foo: 123).should == "123" end it "does not support type style" do - format("%{foo}d", foo: 123).should == "123d" + @method.call("%{foo}d", foo: 123).should == "123d" end it "supports flags, width and precision" do - format("%-20.5{foo}", foo: "123456789").should == "12345 " + @method.call("%-20.5{foo}", foo: "123456789").should == "12345 " end it "cannot be mixed with unnamed style" do -> { - format("%d %{foo}", 1, foo: "123") + @method.call("%d %{foo}", 1, foo: "123") }.should raise_error(ArgumentError) end it "raises KeyError when there is no matching key" do -> { - format("%{foo}", {}) + @method.call("%{foo}", {}) }.should raise_error(KeyError) end @@ -860,18 +895,36 @@ def obj.to_str; end obj.should_receive(:to_s).and_return("42") obj.should_not_receive(:to_str) - format("%{foo}", foo: obj).should == "42" + @method.call("%{foo}", foo: obj).should == "42" end end end describe "faulty key" do - before :all do - @base_method = @method + before :each do + @object = { foooo: 1 } + end + + it "raises a KeyError" do + -> { + @method.call("%s", @object) + }.should raise_error(KeyError) end - it_behaves_like :key_error, -> obj, key { - @base_method.call("%<#{key}>s", obj) - }, { foooo: 1 } + it "sets the Hash as the receiver of KeyError" do + -> { + @method.call("%s", @object) + }.should raise_error(KeyError) { |err| + err.receiver.should equal(@object) + } + end + + it "sets the unmatched key as the key of KeyError" do + -> { + @method.call("%s", @object) + }.should raise_error(KeyError) { |err| + err.key.to_s.should == 'foo' + } + end end end diff --git a/ruby/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/ruby/spec/ruby/core/kernel/shared/sprintf_encoding.rb index c3d62bf3b..5ca66b908 100644 --- a/ruby/spec/ruby/core/kernel/shared/sprintf_encoding.rb +++ b/ruby/spec/ruby/core/kernel/shared/sprintf_encoding.rb @@ -1,11 +1,19 @@ describe :kernel_sprintf_encoding, shared: true do - def format(*args) - @method.call(*args) + it "can produce a string with valid encoding" do + string = @method.call("good day %{valid}", valid: "e") + string.encoding.should == Encoding::UTF_8 + string.valid_encoding?.should be_true + end + + it "can produce a string with invalid encoding" do + string = @method.call("good day %{invalid}", invalid: "\x80") + string.encoding.should == Encoding::UTF_8 + string.valid_encoding?.should be_false end it "returns a String in the same encoding as the format String if compatible" do string = "%s".force_encoding(Encoding::KOI8_U) - result = format(string, "dogs") + result = @method.call(string, "dogs") result.encoding.should equal(Encoding::KOI8_U) end @@ -13,7 +21,7 @@ def format(*args) string = "foo %s".force_encoding(Encoding::US_ASCII) argument = "b\303\274r".force_encoding(Encoding::UTF_8) - result = format(string, argument) + result = @method.call(string, argument) result.encoding.should equal(Encoding::UTF_8) end @@ -22,7 +30,7 @@ def format(*args) argument = "Ђ".encode('windows-1251') -> { - format(string, argument) + @method.call(string, argument) }.should raise_error(Encoding::CompatibilityError) end end diff --git a/ruby/spec/ruby/core/kernel/singleton_class_spec.rb b/ruby/spec/ruby/core/kernel/singleton_class_spec.rb index 5dbb4f8c0..a8bcd916d 100644 --- a/ruby/spec/ruby/core/kernel/singleton_class_spec.rb +++ b/ruby/spec/ruby/core/kernel/singleton_class_spec.rb @@ -17,7 +17,7 @@ false.singleton_class.should == FalseClass end - it "raises TypeError for Fixnum" do + it "raises TypeError for Integer" do -> { 123.singleton_class }.should raise_error(TypeError) end diff --git a/ruby/spec/ruby/core/kernel/sleep_spec.rb b/ruby/spec/ruby/core/kernel/sleep_spec.rb index 387dc4787..32da6344c 100644 --- a/ruby/spec/ruby/core/kernel/sleep_spec.rb +++ b/ruby/spec/ruby/core/kernel/sleep_spec.rb @@ -14,7 +14,7 @@ sleep(0.001).should >= 0 end - it "accepts a Fixnum" do + it "accepts an Integer" do sleep(0).should >= 0 end @@ -22,6 +22,12 @@ sleep(Rational(1, 999)).should >= 0 end + it "accepts any Object that reponds to divmod" do + o = Object.new + def o.divmod(*); [0, 0.001]; end + sleep(o).should >= 0 + end + it "raises an ArgumentError when passed a negative duration" do -> { sleep(-0.1) }.should raise_error(ArgumentError) -> { sleep(-1) }.should raise_error(ArgumentError) diff --git a/ruby/spec/ruby/core/kernel/srand_spec.rb b/ruby/spec/ruby/core/kernel/srand_spec.rb index 5454aae8c..95bb406f4 100644 --- a/ruby/spec/ruby/core/kernel/srand_spec.rb +++ b/ruby/spec/ruby/core/kernel/srand_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -describe "Kernel.srand" do +describe "Kernel#srand" do + before :each do + @seed = srand + end + + after :each do + srand(@seed) + end + it "is a private method" do Kernel.should have_private_instance_method(:srand) end @@ -11,6 +19,10 @@ srand(20).should == 10 end + it "returns the system-initialized seed value on the first call" do + ruby_exe('print srand(10)', options: '--disable-gems').should =~ /\A\d+\z/ + end + it "seeds the RNG correctly and repeatably" do srand(10) x = rand @@ -33,7 +45,7 @@ srand.should == -17 end - it "accepts a Bignum as a seed" do + it "accepts an Integer as a seed" do srand(0x12345678901234567890) srand.should == 0x12345678901234567890 end @@ -56,6 +68,6 @@ end end -describe "Kernel#srand" do +describe "Kernel.srand" do it "needs to be reviewed for spec completeness" end diff --git a/ruby/spec/ruby/core/kernel/system_spec.rb b/ruby/spec/ruby/core/kernel/system_spec.rb index 96c0496dd..9671a650c 100644 --- a/ruby/spec/ruby/core/kernel/system_spec.rb +++ b/ruby/spec/ruby/core/kernel/system_spec.rb @@ -6,14 +6,14 @@ -> { @object.system("echo a") }.should output_to_fd("a\n") $?.should be_an_instance_of Process::Status - $?.success?.should == true + $?.should.success? end it "returns true when the command exits with a zero exit status" do @object.system(ruby_cmd('exit 0')).should == true $?.should be_an_instance_of Process::Status - $?.success?.should == true + $?.should.success? $?.exitstatus.should == 0 end @@ -21,18 +21,16 @@ @object.system(ruby_cmd('exit 1')).should == false $?.should be_an_instance_of Process::Status - $?.success?.should == false + $?.should_not.success? $?.exitstatus.should == 1 end - ruby_version_is "2.6" do - it "raises RuntimeError when `exception: true` is given and the command exits with a non-zero exit status" do - -> { @object.system(ruby_cmd('exit 1'), exception: true) }.should raise_error(RuntimeError) - end + it "raises RuntimeError when `exception: true` is given and the command exits with a non-zero exit status" do + -> { @object.system(ruby_cmd('exit 1'), exception: true) }.should raise_error(RuntimeError) + end - it "raises Errno::ENOENT when `exception: true` is given and the specified command does not exist" do - -> { @object.system('feature_14386', exception: true) }.should raise_error(Errno::ENOENT) - end + it "raises Errno::ENOENT when `exception: true` is given and the specified command does not exist" do + -> { @object.system('feature_14386', exception: true) }.should raise_error(Errno::ENOENT) end it "returns nil when command execution fails" do @@ -40,7 +38,7 @@ $?.should be_an_instance_of Process::Status $?.pid.should be_kind_of(Integer) - $?.exitstatus.should == 127 + $?.should_not.success? end it "does not write to stderr when command execution fails" do diff --git a/ruby/spec/ruby/core/kernel/taint_spec.rb b/ruby/spec/ruby/core/kernel/taint_spec.rb index 6de009a46..8ba9869af 100644 --- a/ruby/spec/ruby/core/kernel/taint_spec.rb +++ b/ruby/spec/ruby/core/kernel/taint_spec.rb @@ -11,12 +11,12 @@ it "sets the tainted bit" do o = Object.new o.taint - o.tainted?.should == true + o.should.tainted? end - it "raises #{frozen_error_class} on an untainted, frozen object" do + it "raises FrozenError on an untainted, frozen object" do o = Object.new.freeze - -> { o.taint }.should raise_error(frozen_error_class) + -> { o.taint }.should raise_error(FrozenError) end it "does not raise an error on a tainted, frozen object" do @@ -27,21 +27,36 @@ it "has no effect on immediate values" do [nil, true, false].each do |v| v.taint - v.tainted?.should == false + v.should_not.tainted? end end it "no raises a RuntimeError on symbols" do v = :sym -> { v.taint }.should_not raise_error(RuntimeError) - v.tainted?.should == false + v.should_not.tainted? end - it "no raises error on fixnum values" do + it "no raises error on integer values" do [1].each do |v| -> { v.taint }.should_not raise_error(RuntimeError) - v.tainted?.should == false + v.should_not.tainted? end end end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = Object.new + o.taint + o.should_not.tainted? + end + + it "warns in verbose mode" do + -> { + obj = mock("tainted") + obj.taint + }.should complain(/Object#taint is deprecated and will be removed in Ruby 3.2/, verbose: true) + end + end end diff --git a/ruby/spec/ruby/core/kernel/tainted_spec.rb b/ruby/spec/ruby/core/kernel/tainted_spec.rb index 72ce346dd..022938bfc 100644 --- a/ruby/spec/ruby/core/kernel/tainted_spec.rb +++ b/ruby/spec/ruby/core/kernel/tainted_spec.rb @@ -7,8 +7,25 @@ o = mock('o') p = mock('p') p.taint - o.tainted?.should == false - p.tainted?.should == true + o.should_not.tainted? + p.should.tainted? + end + end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = mock('o') + p = mock('p') + p.taint + o.should_not.tainted? + p.should_not.tainted? + end + + it "warns in verbose mode" do + -> { + o = mock('o') + o.tainted? + }.should complain(/Object#tainted\? is deprecated and will be removed in Ruby 3.2/, verbose: true) end end end diff --git a/ruby/spec/ruby/core/kernel/then_spec.rb b/ruby/spec/ruby/core/kernel/then_spec.rb index fa896b52b..8109a2960 100644 --- a/ruby/spec/ruby/core/kernel/then_spec.rb +++ b/ruby/spec/ruby/core/kernel/then_spec.rb @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/then' -ruby_version_is "2.6" do - describe "Kernel#then" do - it_behaves_like :kernel_then, :then - end +describe "Kernel#then" do + it_behaves_like :kernel_then, :then end diff --git a/ruby/spec/ruby/core/kernel/trap_spec.rb b/ruby/spec/ruby/core/kernel/trap_spec.rb index 465aacb0f..4c801a721 100644 --- a/ruby/spec/ruby/core/kernel/trap_spec.rb +++ b/ruby/spec/ruby/core/kernel/trap_spec.rb @@ -1,12 +1,9 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' describe "Kernel#trap" do it "is a private method" do Kernel.should have_private_instance_method(:trap) end -end -describe "Kernel.trap" do - it "needs to be reviewed for spec completeness" + # Behaviour is specified for Signal.trap end diff --git a/ruby/spec/ruby/core/kernel/trust_spec.rb b/ruby/spec/ruby/core/kernel/trust_spec.rb index 13f085f42..399983f74 100644 --- a/ruby/spec/ruby/core/kernel/trust_spec.rb +++ b/ruby/spec/ruby/core/kernel/trust_spec.rb @@ -11,12 +11,12 @@ it "clears the untrusted bit" do o = Object.new.untrust o.trust - o.untrusted?.should == false + o.should_not.untrusted? end - it "raises #{frozen_error_class} on an untrusted, frozen object" do + it "raises FrozenError on an untrusted, frozen object" do o = Object.new.untrust.freeze - -> { o.trust }.should raise_error(frozen_error_class) + -> { o.trust }.should raise_error(FrozenError) end it "does not raise an error on a trusted, frozen object" do @@ -24,4 +24,20 @@ o.trust.should equal(o) end end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = Object.new.untrust + o.should_not.untrusted? + o.trust + o.should_not.untrusted? + end + + it "warns in verbose mode" do + -> { + o = Object.new.untrust + o.trust + }.should complain(/Object#trust is deprecated and will be removed in Ruby 3.2/, verbose: true) + end + end end diff --git a/ruby/spec/ruby/core/kernel/untaint_spec.rb b/ruby/spec/ruby/core/kernel/untaint_spec.rb index 58485fcc5..44d87da5d 100644 --- a/ruby/spec/ruby/core/kernel/untaint_spec.rb +++ b/ruby/spec/ruby/core/kernel/untaint_spec.rb @@ -11,12 +11,12 @@ it "clears the tainted bit" do o = Object.new.taint o.untaint - o.tainted?.should == false + o.should_not.tainted? end - it "raises #{frozen_error_class} on a tainted, frozen object" do + it "raises FrozenError on a tainted, frozen object" do o = Object.new.taint.freeze - -> { o.untaint }.should raise_error(frozen_error_class) + -> { o.untaint }.should raise_error(FrozenError) end it "does not raise an error on an untainted, frozen object" do @@ -24,4 +24,20 @@ o.untaint.should equal(o) end end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = Object.new.taint + o.should_not.tainted? + o.untaint + o.should_not.tainted? + end + + it "warns in verbose mode" do + -> { + o = Object.new.taint + o.untaint + }.should complain(/Object#untaint is deprecated and will be removed in Ruby 3.2/, verbose: true) + end + end end diff --git a/ruby/spec/ruby/core/kernel/untrust_spec.rb b/ruby/spec/ruby/core/kernel/untrust_spec.rb index c6eb79af1..aff0fec57 100644 --- a/ruby/spec/ruby/core/kernel/untrust_spec.rb +++ b/ruby/spec/ruby/core/kernel/untrust_spec.rb @@ -11,12 +11,12 @@ it "sets the untrusted bit" do o = Object.new o.untrust - o.untrusted?.should == true + o.should.untrusted? end - it "raises #{frozen_error_class} on a trusted, frozen object" do + it "raises FrozenError on a trusted, frozen object" do o = Object.new.freeze - -> { o.untrust }.should raise_error(frozen_error_class) + -> { o.untrust }.should raise_error(FrozenError) end it "does not raise an error on an untrusted, frozen object" do @@ -24,4 +24,19 @@ o.untrust.should equal(o) end end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = Object.new + o.untrust + o.should_not.untrusted? + end + + it "warns in verbose mode" do + -> { + o = Object.new + o.untrust + }.should complain(/Object#untrust is deprecated and will be removed in Ruby 3.2/, verbose: true) + end + end end diff --git a/ruby/spec/ruby/core/kernel/untrusted_spec.rb b/ruby/spec/ruby/core/kernel/untrusted_spec.rb index ccebfe38b..5347c9009 100644 --- a/ruby/spec/ruby/core/kernel/untrusted_spec.rb +++ b/ruby/spec/ruby/core/kernel/untrusted_spec.rb @@ -5,9 +5,9 @@ ruby_version_is ''...'2.7' do it "returns the untrusted status of an object" do o = mock('o') - o.untrusted?.should == false + o.should_not.untrusted? o.untrust - o.untrusted?.should == true + o.should.untrusted? end it "has no effect on immediate values" do @@ -17,9 +17,9 @@ a.untrust b.untrust c.untrust - a.untrusted?.should == false - b.untrusted?.should == false - c.untrusted?.should == false + a.should_not.untrusted? + b.should_not.untrusted? + c.should_not.untrusted? end it "has effect on immediate values" do @@ -27,4 +27,20 @@ -> { d.untrust }.should_not raise_error(RuntimeError) end end + + ruby_version_is "2.7"..."3.0" do + it "is a no-op" do + o = mock('o') + o.should_not.untrusted? + o.untrust + o.should_not.untrusted? + end + + it "warns in verbose mode" do + -> { + o = mock('o') + o.untrusted? + }.should complain(/Object#untrusted\? is deprecated and will be removed in Ruby 3.2/, verbose: true) + end + end end diff --git a/ruby/spec/ruby/core/kernel/warn_spec.rb b/ruby/spec/ruby/core/kernel/warn_spec.rb index 2a404a2a3..7df6fa72d 100644 --- a/ruby/spec/ruby/core/kernel/warn_spec.rb +++ b/ruby/spec/ruby/core/kernel/warn_spec.rb @@ -8,15 +8,16 @@ end after :each do - $VERBOSE = @before_verbose + $VERBOSE = nil $/ = @before_separator + $VERBOSE = @before_verbose end it "is a private method" do Kernel.should have_private_instance_method(:warn) end - it "requires multiple arguments" do + it "accepts multiple arguments" do Kernel.method(:warn).arity.should < 0 end @@ -86,71 +87,223 @@ }.should output(nil, "to_s called\n") end - ruby_version_is "2.5" do - describe ":uplevel keyword argument" do - before :each do - $VERBOSE = true - end + describe ":uplevel keyword argument" do + before :each do + $VERBOSE = true + end + + it "prepends a message with specified line from the backtrace" do + w = KernelSpecs::WarnInNestedCall.new - it "prepends a message with specified line from the backtrace" do - w = KernelSpecs::WarnInNestedCall.new + -> { w.f4("foo", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: foo|) + -> { w.f4("foo", 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: foo|) + -> { w.f4("foo", 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: foo|) + -> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|) + end - -> { w.f4("foo", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: foo|) - -> { w.f4("foo", 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: foo|) - -> { w.f4("foo", 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: foo|) - -> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|) + # Test both explicitly without and with RubyGems as RubyGems overrides Kernel#warn + it "shows the caller of #require and not #require itself without RubyGems" do + file = fixture(__FILE__ , "warn_require_caller.rb") + ruby_exe(file, options: "--disable-gems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" + end + + it "shows the caller of #require and not #require itself with RubyGems loaded" do + file = fixture(__FILE__ , "warn_require_caller.rb") + ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" + end + + guard -> { Kernel.instance_method(:tap).source_location } do + it "skips &1").lines.should == [ + "#{file}:#{n+0}: warning: use X instead\n", + "#{file}:#{n+1}: warning: use X instead\n", + "#{file}:#{n+2}: warning: use X instead\n", + "#{file}:#{n+4}: warning: use X instead\n", + ] end + end - it "converts first arg using to_s" do - w = KernelSpecs::WarnInNestedCall.new + ruby_version_is "3.0" do + it "accepts :category keyword with a symbol" do + -> { + $VERBOSE = true + warn("message", category: :deprecated) + }.should output(nil, "message\n") + end + + it "accepts :category keyword with nil" do + -> { + $VERBOSE = true + warn("message", category: nil) + }.should output(nil, "message\n") + end - -> { w.f4(false, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: false|) - -> { w.f4(nil, 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: |) - obj = mock("obj") - obj.should_receive(:to_s).and_return("to_s called") - -> { w.f4(obj, 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: to_s called|) + it "accepts :category keyword with object convertible to symbol" do + o = Object.new + def o.to_sym; :deprecated; end + -> { + $VERBOSE = true + warn("message", category: o) + }.should output(nil, "message\n") end - it "does not prepend caller information if line number is too big" do - w = KernelSpecs::WarnInNestedCall.new - -> { w.f4("foo", 100) }.should output(nil, "warning: foo\n") + it "raises if :category keyword is not nil and not convertible to symbol" do + -> { + $VERBOSE = true + warn("message", category: Object.new) + }.should raise_error(TypeError) end + end + + it "converts first arg using to_s" do + w = KernelSpecs::WarnInNestedCall.new + + -> { w.f4(false, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: false|) + -> { w.f4(nil, 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: |) + obj = mock("obj") + obj.should_receive(:to_s).and_return("to_s called") + -> { w.f4(obj, 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: to_s called|) + end + + it "does not prepend caller information if the uplevel argument is too large" do + w = KernelSpecs::WarnInNestedCall.new + -> { w.f4("foo", 100) }.should output(nil, "warning: foo\n") + end + + it "prepends even if a message is empty or nil" do + w = KernelSpecs::WarnInNestedCall.new + + -> { w.f4("", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|) + -> { w.f4(nil, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|) + end - it "prepends even if a message is empty or nil" do - w = KernelSpecs::WarnInNestedCall.new + it "converts value to Integer" do + w = KernelSpecs::WarnInNestedCall.new - -> { w.f4("", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|) - -> { w.f4(nil, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|) + -> { w.f4(0.1) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|) + -> { w.f4(Rational(1, 2)) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|) + end + + it "raises ArgumentError if passed negative value" do + -> { warn "", uplevel: -2 }.should raise_error(ArgumentError) + -> { warn "", uplevel: -100 }.should raise_error(ArgumentError) + end + + it "raises ArgumentError if passed -1" do + -> { warn "", uplevel: -1 }.should raise_error(ArgumentError) + end + + it "raises TypeError if passed not Integer" do + -> { warn "", uplevel: "" }.should raise_error(TypeError) + -> { warn "", uplevel: [] }.should raise_error(TypeError) + -> { warn "", uplevel: {} }.should raise_error(TypeError) + -> { warn "", uplevel: Object.new }.should raise_error(TypeError) + end + end + + it "treats empty hash as no keyword argument" do + h = {} + -> { warn(**h) }.should_not complain(verbose: true) + -> { warn('foo', **h) }.should complain("foo\n") + end + + ruby_version_is '3.0' do + it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do + verbose = $VERBOSE + $VERBOSE = false + class << Warning + alias_method :_warn, :warn + def warn(message) + ScratchPad.record(message) + end end - it "converts value to Integer" do - w = KernelSpecs::WarnInNestedCall.new + begin + ScratchPad.clear + Kernel.warn("Chunky bacon!") + ScratchPad.recorded.should == "Chunky bacon!\n" - -> { w.f4(0.1) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|) - -> { w.f4(Rational(1, 2)) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|) + Kernel.warn("Deprecated bacon!", category: :deprecated) + ScratchPad.recorded.should == "Deprecated bacon!\n" + ensure + class << Warning + remove_method :warn + alias_method :warn, :_warn + remove_method :_warn + end + $VERBOSE = verbose end + end - it "raises ArgumentError if passed negative value" do - -> { warn "", uplevel: -2 }.should raise_error(ArgumentError) - -> { warn "", uplevel: -100 }.should raise_error(ArgumentError) + it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose end + end - it "raises ArgumentError if passed -1" do - -> { warn "", uplevel: -1 }.should raise_error(ArgumentError) + it "calls Warning.warn with given category keyword converted to a symbol" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!", category: 'deprecated') + ensure + $VERBOSE = verbose end + end + end - it "raises TypeError if passed not Integer" do - -> { warn "", uplevel: "" }.should raise_error(TypeError) - -> { warn "", uplevel: [] }.should raise_error(TypeError) - -> { warn "", uplevel: {} }.should raise_error(TypeError) - -> { warn "", uplevel: Object.new }.should raise_error(TypeError) + ruby_version_is ''...'3.0' do + it "calls Warning.warn with no keyword arguments" do + Warning.should_receive(:warn).with("Chunky bacon!\n") + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose end end + end + + it "does not call Warning.warn if self is the Warning module" do + # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here + code = <<-RUBY + def Warning.warn(*args, **kwargs) + raise 'should not be called' + end + Kernel.instance_method(:warn).bind(Warning).call('Kernel#warn spec edge case') + RUBY + out = ruby_exe(code, args: "2>&1", options: "--disable-gems") + out.should == "Kernel#warn spec edge case\n" + $?.should.success? + end - it "treats empty hash as no keyword argument" do - h = {} - -> { warn(**h) }.should_not complain(verbose: true) - -> { warn('foo', **h) }.should complain("foo\n") + it "avoids recursion if Warning#warn is redefined and calls super" do + # This works because of the spec above, which is the workaround for it. + # Note that redefining Warning#warn is a mistake which would naturally end in infinite recursion, + # Warning.extend Module.new { def warn } should be used instead. + # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here + code = <<-RUBY + module Warning + def warn(*args, **kwargs) + super + end end + warn "avoid infinite recursion" + RUBY + out = ruby_exe(code, args: "2>&1", options: "--disable-gems") + out.should == "avoid infinite recursion\n" + $?.should.success? end end diff --git a/ruby/spec/ruby/core/kernel/yield_self_spec.rb b/ruby/spec/ruby/core/kernel/yield_self_spec.rb index affedae14..e311dcee4 100644 --- a/ruby/spec/ruby/core/kernel/yield_self_spec.rb +++ b/ruby/spec/ruby/core/kernel/yield_self_spec.rb @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/then' -ruby_version_is "2.5" do - describe "Kernel#yield_self" do - it_behaves_like :kernel_then, :yield_self - end +describe "Kernel#yield_self" do + it_behaves_like :kernel_then, :yield_self end diff --git a/ruby/spec/ruby/core/main/fixtures/classes.rb b/ruby/spec/ruby/core/main/fixtures/classes.rb index 6aba948ce..757cee4e4 100644 --- a/ruby/spec/ruby/core/main/fixtures/classes.rb +++ b/ruby/spec/ruby/core/main/fixtures/classes.rb @@ -13,6 +13,14 @@ def main_public_method end public :main_public_method +def main_public_method2 +end +public :main_public_method2 + def main_private_method end private :main_private_method + +def main_private_method2 +end +private :main_private_method2 diff --git a/ruby/spec/ruby/core/main/private_spec.rb b/ruby/spec/ruby/core/main/private_spec.rb index e34e0c7b7..cac0645b4 100644 --- a/ruby/spec/ruby/core/main/private_spec.rb +++ b/ruby/spec/ruby/core/main/private_spec.rb @@ -4,20 +4,49 @@ describe "main#private" do after :each do Object.send(:public, :main_public_method) + Object.send(:public, :main_public_method2) end - it "sets the visibility of the given method to private" do - eval "private :main_public_method", TOPLEVEL_BINDING - Object.should have_private_method(:main_public_method) + context "when single argument is passed and it is not an array" do + it "sets the visibility of the given methods to private" do + eval "private :main_public_method", TOPLEVEL_BINDING + Object.should have_private_method(:main_public_method) + end end - it "returns Object" do - eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object) + context "when multiple arguments are passed" do + it "sets the visibility of the given methods to private" do + eval "private :main_public_method, :main_public_method2", TOPLEVEL_BINDING + Object.should have_private_method(:main_public_method) + Object.should have_private_method(:main_public_method2) + end end - it "raises a NameError when given an undefined name" do + ruby_version_is "3.0" do + context "when single argument is passed and is an array" do + it "sets the visibility of the given methods to private" do + eval "private [:main_public_method, :main_public_method2]", TOPLEVEL_BINDING + Object.should have_private_method(:main_public_method) + Object.should have_private_method(:main_public_method2) + end + end + end + + ruby_version_is ''...'3.1' do + it "returns Object" do + eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object) + end + end + + ruby_version_is '3.1' do + it "returns argument" do + eval("private :main_public_method", TOPLEVEL_BINDING).should equal(:main_public_method) + end + end + + it "raises a NameError when at least one of given method names is undefined" do -> do - eval "private :main_undefined_method", TOPLEVEL_BINDING + eval "private :main_public_method, :main_undefined_method", TOPLEVEL_BINDING end.should raise_error(NameError) end end diff --git a/ruby/spec/ruby/core/main/public_spec.rb b/ruby/spec/ruby/core/main/public_spec.rb index afe25c705..91f045dba 100644 --- a/ruby/spec/ruby/core/main/public_spec.rb +++ b/ruby/spec/ruby/core/main/public_spec.rb @@ -4,17 +4,47 @@ describe "main#public" do after :each do Object.send(:private, :main_private_method) + Object.send(:private, :main_private_method2) end - it "sets the visibility of the given method to public" do - eval "public :main_private_method", TOPLEVEL_BINDING - Object.should_not have_private_method(:main_private_method) + context "when single argument is passed and it is not an array" do + it "sets the visibility of the given methods to public" do + eval "public :main_private_method", TOPLEVEL_BINDING + Object.should_not have_private_method(:main_private_method) + end end - it "returns Object" do - eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object) + context "when multiple arguments are passed" do + it "sets the visibility of the given methods to public" do + eval "public :main_private_method, :main_private_method2", TOPLEVEL_BINDING + Object.should_not have_private_method(:main_private_method) + Object.should_not have_private_method(:main_private_method2) + end end + ruby_version_is "3.0" do + context "when single argument is passed and is an array" do + it "sets the visibility of the given methods to public" do + eval "public [:main_private_method, :main_private_method2]", TOPLEVEL_BINDING + Object.should_not have_private_method(:main_private_method) + Object.should_not have_private_method(:main_private_method2) + end + end + end + + ruby_version_is ''...'3.1' do + it "returns Object" do + eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object) + end + end + + ruby_version_is '3.1' do + it "returns argument" do + eval("public :main_private_method", TOPLEVEL_BINDING).should equal(:main_private_method) + end + end + + it "raises a NameError when given an undefined name" do -> do eval "public :main_undefined_method", TOPLEVEL_BINDING diff --git a/ruby/spec/ruby/core/main/ruby2_keywords_spec.rb b/ruby/spec/ruby/core/main/ruby2_keywords_spec.rb new file mode 100644 index 000000000..0999cddee --- /dev/null +++ b/ruby/spec/ruby/core/main/ruby2_keywords_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "2.7" do + describe "main.ruby2_keywords" do + it "is the same as Object.ruby2_keywords" do + main = TOPLEVEL_BINDING.receiver + main.should have_private_method(:ruby2_keywords) + end + end +end diff --git a/ruby/spec/ruby/core/marshal/dump_spec.rb b/ruby/spec/ruby/core/marshal/dump_spec.rb index fc78ca4ff..a54a4c673 100644 --- a/ruby/spec/ruby/core/marshal/dump_spec.rb +++ b/ruby/spec/ruby/core/marshal/dump_spec.rb @@ -78,6 +78,20 @@ s = "\u2192".force_encoding("binary").to_sym Marshal.dump(s).should == "\x04\b:\b\xE2\x86\x92" end + + it "dumps multiple Symbols sharing the same encoding" do + # Note that the encoding is a link for the second Symbol + symbol1 = "I:\t\xE2\x82\xACa\x06:\x06ET" + symbol2 = "I:\t\xE2\x82\xACb\x06;\x06T" + value = [ + "€a".force_encoding(Encoding::UTF_8).to_sym, + "€b".force_encoding(Encoding::UTF_8).to_sym + ] + Marshal.dump(value).should == "\x04\b[\a#{symbol1}#{symbol2}" + + value = [*value, value[0]] + Marshal.dump(value).should == "\x04\b[\b#{symbol1}#{symbol2};\x00" + end end describe "with an object responding to #marshal_dump" do @@ -235,13 +249,13 @@ end it "dumps a Regexp with instance variables" do - o = // + o = Regexp.new("") o.instance_variable_set(:@ivar, :ivar) Marshal.dump(o).should == "\x04\bI/\x00\x00\a:\x06EF:\n@ivar:\tivar" end it "dumps an extended Regexp" do - Marshal.dump(//.extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF" + Marshal.dump(Regexp.new("").extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF" end it "dumps a Regexp subclass" do @@ -343,8 +357,13 @@ end it "dumps an extended Struct" do - st = Struct.new("Extended", :a, :b).new - Marshal.dump(st.extend(Meths)).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0" + obj = Struct.new("Extended", :a, :b).new.extend(Meths) + Marshal.dump(obj).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0" + + s = 'hi' + obj.a = [:a, s] + obj.b = [:Meths, s] + Marshal.dump(obj).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a" Struct.send(:remove_const, :Extended) end end @@ -411,13 +430,15 @@ def obj.foo; end load.should == (1...2) end - it "dumps a Range with extra instance variables" do - range = (1...3) - range.instance_variable_set :@foo, 42 - dump = Marshal.dump(range) - load = Marshal.load(dump) - load.should == range - load.instance_variable_get(:@foo).should == 42 + ruby_version_is ""..."3.0" do + it "dumps a Range with extra instance variables" do + range = (1...3) + range.instance_variable_set :@foo, 42 + dump = Marshal.dump(range) + load = Marshal.load(dump) + load.should == range + load.instance_variable_get(:@foo).should == 42 + end end end @@ -556,13 +577,10 @@ def obj.foo; end end describe "when passed a StringIO" do - it "should raise an error" do require "stringio" - -> { Marshal.dump(StringIO.new) }.should raise_error(TypeError) end - end it "raises a TypeError if marshalling a Method instance" do diff --git a/ruby/spec/ruby/core/marshal/fixtures/marshal_data.rb b/ruby/spec/ruby/core/marshal/fixtures/marshal_data.rb index 293127829..9373ef7ba 100644 --- a/ruby/spec/ruby/core/marshal/fixtures/marshal_data.rb +++ b/ruby/spec/ruby/core/marshal/fixtures/marshal_data.rb @@ -83,7 +83,7 @@ class UserPreviouslyDefinedWithInitializedIvar end class UserMarshal - attr_reader :data + attr_accessor :data def initialize @data = 'stuff' @@ -227,36 +227,36 @@ def self.reset_swapped_class "\004\b:\010big"], "Symbol big" => [('big' * 100).to_sym, "\004\b:\002,\001#{'big' * 100}"], - "Bignum -2**64" => [-2**64, + "Integer -2**64" => [-2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"], - "Bignum -2**63" => [-2**63, + "Integer -2**63" => [-2**63, "\004\bl-\t\000\000\000\000\000\000\000\200"], - "Fixnum -2**24" => [-2**24, + "Integer -2**24" => [-2**24, "\004\bi\375\000\000\000"], - "Fixnum -4516727" => [-4516727, + "Integer -4516727" => [-4516727, "\004\bi\375\211\024\273"], - "Fixnum -2**16" => [-2**16, + "Integer -2**16" => [-2**16, "\004\bi\376\000\000"], - "Fixnum -2**8" => [-2**8, + "Integer -2**8" => [-2**8, "\004\bi\377\000"], - "Fixnum -123" => [-123, + "Integer -123" => [-123, "\004\bi\200"], - "Fixnum -124" => [-124, "\004\bi\377\204"], - "Fixnum 0" => [0, + "Integer -124" => [-124, "\004\bi\377\204"], + "Integer 0" => [0, "\004\bi\000"], - "Fixnum 5" => [5, + "Integer 5" => [5, "\004\bi\n"], - "Fixnum 122" => [122, "\004\bi\177"], - "Fixnum 123" => [123, "\004\bi\001{"], - "Fixnum 2**8" => [2**8, + "Integer 122" => [122, "\004\bi\177"], + "Integer 123" => [123, "\004\bi\001{"], + "Integer 2**8" => [2**8, "\004\bi\002\000\001"], - "Fixnum 2**16" => [2**16, + "Integer 2**16" => [2**16, "\004\bi\003\000\000\001"], - "Fixnum 2**24" => [2**24, + "Integer 2**24" => [2**24, "\004\bi\004\000\000\000\001"], - "Bignum 2**64" => [2**64, + "Integer 2**64" => [2**64, "\004\bl+\n\000\000\000\000\000\000\000\000\001\000"], - "Bignum 2**90" => [2**90, + "Integer 2**90" => [2**90, "\004\bl+\v#{"\000" * 11}\004"], "Class String" => [String, "\004\bc\vString"], @@ -334,31 +334,31 @@ def self.reset_swapped_class "\004\b:\010big"], "Symbol big" => [('big' * 100).to_sym, "\004\b:\002,\001#{'big' * 100}"], - "Bignum -2**64" => [-2**64, + "Integer -2**64" => [-2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"], - "Bignum -2**63" => [-2**63, + "Integer -2**63" => [-2**63, "\004\bl-\t\000\000\000\000\000\000\000\200"], - "Fixnum -2**24" => [-2**24, + "Integer -2**24" => [-2**24, "\004\bi\375\000\000\000"], - "Fixnum -2**16" => [-2**16, + "Integer -2**16" => [-2**16, "\004\bi\376\000\000"], - "Fixnum -2**8" => [-2**8, + "Integer -2**8" => [-2**8, "\004\bi\377\000"], - "Fixnum -123" => [-123, + "Integer -123" => [-123, "\004\bi\200"], - "Fixnum 0" => [0, + "Integer 0" => [0, "\004\bi\000"], - "Fixnum 5" => [5, + "Integer 5" => [5, "\004\bi\n"], - "Fixnum 2**8" => [2**8, + "Integer 2**8" => [2**8, "\004\bi\002\000\001"], - "Fixnum 2**16" => [2**16, + "Integer 2**16" => [2**16, "\004\bi\003\000\000\001"], - "Fixnum 2**24" => [2**24, + "Integer 2**24" => [2**24, "\004\bi\004\000\000\000\001"], - "Bignum 2**64" => [2**64, + "Integer 2**64" => [2**64, "\004\bl+\n\000\000\000\000\000\000\000\000\001\000"], - "Bignum 2**90" => [2**90, + "Integer 2**90" => [2**90, "\004\bl+\v#{"\000" * 11}\004"], "Class String" => [String, "\004\bc\vString"], diff --git a/ruby/spec/ruby/core/marshal/shared/load.rb b/ruby/spec/ruby/core/marshal/shared/load.rb index 302d3d5bd..b70bca55b 100644 --- a/ruby/spec/ruby/core/marshal/shared/load.rb +++ b/ruby/spec/ruby/core/marshal/shared/load.rb @@ -1,6 +1,5 @@ # -*- encoding: binary -*- require_relative '../fixtures/marshal_data' -require 'stringio' describe :marshal_load, shared: true do before :all do @@ -20,43 +19,157 @@ -> { Marshal.send(@method, kaboom) }.should raise_error(ArgumentError) end - describe "when called with a proc" do - it "returns the value of the proc" do - Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4] - end + ruby_version_is "3.1" do + describe "when called with freeze: true" do + it "returns frozen strings" do + string = Marshal.send(@method, Marshal.dump("foo"), freeze: true) + string.should == "foo" + string.should.frozen? + + utf8_string = "foo".encode(Encoding::UTF_8) + string = Marshal.send(@method, Marshal.dump(utf8_string), freeze: true) + string.should == utf8_string + string.should.frozen? + end - it "calls the proc for recursively visited data" do - a = [1] - a << a - ret = [] - Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg; arg }) - ret.first.should == 1 - ret[1].should == [1,a] - ret[2].should == a - ret.size.should == 3 + it "returns frozen arrays" do + array = Marshal.send(@method, Marshal.dump([1, 2, 3]), freeze: true) + array.should == [1, 2, 3] + array.should.frozen? + end + + it "returns frozen hashes" do + hash = Marshal.send(@method, Marshal.dump({foo: 42}), freeze: true) + hash.should == {foo: 42} + hash.should.frozen? + end + + it "returns frozen regexps" do + regexp = Marshal.send(@method, Marshal.dump(/foo/), freeze: true) + regexp.should == /foo/ + regexp.should.frozen? + end + + it "returns frozen objects" do + source_object = Object.new + source_object.instance_variable_set(:@foo, "bar") + + object = Marshal.send(@method, Marshal.dump(source_object), freeze: true) + object.should.frozen? + object.instance_variable_get(:@foo).should.frozen? + end + + it "does not freeze modules" do + Marshal.send(@method, Marshal.dump(Kernel), freeze: true) + Kernel.should_not.frozen? + end + + it "does not freeze classes" do + Marshal.send(@method, Marshal.dump(Object), freeze: true) + Object.should_not.frozen? + end + + describe "when called with a proc" do + it "call the proc with frozen objects" do + arr = [] + s = 'hi' + s.instance_variable_set(:@foo, 5) + st = Struct.new("Brittle", :a).new + st.instance_variable_set(:@clue, 'none') + st.a = 0.0 + h = Hash.new('def') + h['nine'] = 9 + a = [:a, :b, :c] + a.instance_variable_set(:@two, 2) + obj = [s, 10, s, s, st, a] + obj.instance_variable_set(:@zoo, 'ant') + proc = Proc.new { |o| arr << o; o} + + Marshal.send( + @method, + "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", + proc, + freeze: true, + ) + + arr.should == [ + false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st, + :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]], + ] + + arr.each do |v| + v.should.frozen? + end + + Struct.send(:remove_const, :Brittle) + end + + it "does not freeze the object returned by the proc" do + string = Marshal.send(@method, Marshal.dump("foo"), proc { |o| o.upcase }, freeze: true) + string.should == "FOO" + string.should_not.frozen? + end + end end + end - it "loads an Array with proc" do - arr = [] - s = 'hi' - s.instance_variable_set(:@foo, 5) - st = Struct.new("Brittle", :a).new - st.instance_variable_set(:@clue, 'none') - st.a = 0.0 - h = Hash.new('def') - h['nine'] = 9 - a = [:a, :b, :c] - a.instance_variable_set(:@two, 2) - obj = [s, 10, s, s, st, a] - obj.instance_variable_set(:@zoo, 'ant') - proc = Proc.new { |o| arr << o; o} + describe "when called with a proc" do + ruby_bug "#18141", ""..."3.1" do + it "call the proc with fully initialized strings" do + utf8_string = "foo".encode(Encoding::UTF_8) + Marshal.send(@method, Marshal.dump(utf8_string), proc { |arg| + if arg.is_a?(String) + arg.should == utf8_string + arg.encoding.should == Encoding::UTF_8 + end + arg + }) + end - Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc) + it "no longer mutate the object after it was passed to the proc" do + string = Marshal.load(Marshal.dump("foo"), :freeze.to_proc) + string.should.frozen? + end + end - arr.should == ["hi", false, 5, 10, "hi", "hi", 0.0, st, "none", false, - :b, :c, a, 2, ["hi", 10, "hi", "hi", st, [:a, :b, :c]], "ant", false] + it "returns the value of the proc" do + Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4] + end + + ruby_bug "#18141", ""..."3.1" do + it "calls the proc for recursively visited data" do + a = [1] + a << a + ret = [] + Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg }) + ret[0].should == 1.inspect + ret[1].should == a.inspect + ret.size.should == 2 + end - Struct.send(:remove_const, :Brittle) + it "loads an Array with proc" do + arr = [] + s = 'hi' + s.instance_variable_set(:@foo, 5) + st = Struct.new("Brittle", :a).new + st.instance_variable_set(:@clue, 'none') + st.a = 0.0 + h = Hash.new('def') + h['nine'] = 9 + a = [:a, :b, :c] + a.instance_variable_set(:@two, 2) + obj = [s, 10, s, s, st, a] + obj.instance_variable_set(:@zoo, 'ant') + proc = Proc.new { |o| arr << o.dup; o} + + Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc) + + arr.should == [ + false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st, + :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]], + ] + Struct.send(:remove_const, :Brittle) + end end end @@ -120,28 +233,39 @@ end end - it "loads an array containing objects having _dump method, and with proc" do - arr = [] - myproc = Proc.new { |o| arr << o; o } - o1 = UserDefined.new; - o2 = UserDefinedWithIvar.new - obj = [o1, o2, o1, o2] + ruby_bug "#18141", ""..."3.1" do + it "loads an array containing objects having _dump method, and with proc" do + arr = [] + myproc = Proc.new { |o| arr << o.dup; o } + o1 = UserDefined.new; + o2 = UserDefinedWithIvar.new + obj = [o1, o2, o1, o2] - Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc) + Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc) - arr.should == [o1, o2, o1, o2, obj] - end + arr[0].should == o1 + arr[1].should == o2 + arr[2].should == obj + arr.size.should == 3 + end + + it "loads an array containing objects having marshal_dump method, and with proc" do + arr = [] + proc = Proc.new { |o| arr << o.dup; o } + o1 = UserMarshal.new + o2 = UserMarshalWithIvar.new - it "loads an array containing objects having marshal_dump method, and with proc" do - arr = [] - proc = Proc.new { |o| arr << o; o } - o1 = UserMarshal.new - o2 = UserMarshalWithIvar.new - obj = [o1, o2, o1, o2] + Marshal.send(@method, "\004\b[\tU:\020UserMarshal\"\nstuffU:\030UserMarshalWithIvar[\006\"\fmy data@\006@\b", proc) - Marshal.send(@method, "\004\b[\tU:\020UserMarshal\"\nstuffU:\030UserMarshalWithIvar[\006\"\fmy data@\006@\b", proc) + arr[0].should == 'stuff' + arr[1].should == o1 + arr[2].should == 'my data' + arr[3].should == ['my data'] + arr[4].should == o2 + arr[5].should == [o1, o2, o1, o2] - arr.should == ['stuff', o1, 'my data', ['my data'], o2, o1, o2, obj] + arr.size.should == 6 + end end it "assigns classes to nested subclasses of Array correctly" do @@ -310,7 +434,8 @@ it "loads an extended Array object containing a user-marshaled object" do obj = [UserMarshal.new, UserMarshal.new].extend(Meths) - new_obj = Marshal.send(@method, "\x04\be:\nMeths[\ao:\x10UserMarshal\x06:\n@dataI\"\nstuff\x06:\x06ETo;\x06\x06;\aI\"\nstuff\x06;\bT") + dump = "\x04\be:\nMeths[\ao:\x10UserMarshal\x06:\n@dataI\"\nstuff\x06:\x06ETo;\x06\x06;\aI\"\nstuff\x06;\bT" + new_obj = Marshal.send(@method, dump) new_obj.should == obj obj_ancestors = class << obj; ancestors[1..-1]; end @@ -400,6 +525,24 @@ sym.should == s sym.encoding.should == Encoding::BINARY end + + it "loads multiple Symbols sharing the same encoding" do + # Note that the encoding is a link for the second Symbol + symbol1 = "I:\t\xE2\x82\xACa\x06:\x06ET" + symbol2 = "I:\t\xE2\x82\xACb\x06;\x06T" + dump = "\x04\b[\a#{symbol1}#{symbol2}" + value = Marshal.send(@method, dump) + value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8] + expected = [ + "€a".force_encoding(Encoding::UTF_8).to_sym, + "€b".force_encoding(Encoding::UTF_8).to_sym + ] + value.should == expected + + value = Marshal.send(@method, "\x04\b[\b#{symbol1}#{symbol2};\x00") + value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8] + value.should == [*expected, expected[0]] + end end describe "for a String" do @@ -410,8 +553,9 @@ end it "loads a string through StringIO stream" do - obj = "This is a string which should be unmarshalled through StringIO stream!" - Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj + require 'stringio' + obj = "This is a string which should be unmarshalled through StringIO stream!" + Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj end it "loads a string with an ivar" do @@ -460,20 +604,23 @@ describe "for a Struct" do it "loads a extended_struct having fields with same objects" do s = 'hi' - obj = Struct.new("Ure2", :a, :b).new.extend(Meths) + obj = Struct.new("Extended", :a, :b).new.extend(Meths) + dump = "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0" + Marshal.send(@method, dump).should == obj + obj.a = [:a, s] obj.b = [:Meths, s] - - Marshal.send(@method, - "\004\be:\nMethsS:\021Struct::Ure2\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a" - ).should == obj - Struct.send(:remove_const, :Ure2) + dump = "\004\be:\nMethsS:\025Struct::Extended\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a" + Marshal.send(@method, dump).should == obj + Struct.send(:remove_const, :Extended) end it "loads a struct having ivar" do obj = Struct.new("Thick").new obj.instance_variable_set(:@foo, 5) - Marshal.send(@method, "\004\bIS:\022Struct::Thick\000\006:\t@fooi\n").should == obj + reloaded = Marshal.send(@method, "\004\bIS:\022Struct::Thick\000\006:\t@fooi\n") + reloaded.should == obj + reloaded.instance_variable_get(:@foo).should == 5 Struct.send(:remove_const, :Thick) end @@ -588,6 +735,18 @@ end end + describe "for an object responding to #marshal_dump and #marshal_load" do + it "loads a user-marshaled object" do + obj = UserMarshal.new + obj.data = :data + value = [obj, :data] + dump = Marshal.dump(value) + dump.should == "\x04\b[\aU:\x10UserMarshal:\tdata;\x06" + reloaded = Marshal.load(dump) + reloaded.should == value + end + end + describe "for a user object" do it "loads a user-marshaled extended object" do obj = UserMarshal.new.extend(Meths) @@ -623,7 +782,7 @@ describe "for a Regexp" do it "loads an extended Regexp" do - obj = /[a-z]/.extend(Meths, MethsMore) + obj = /[a-z]/.dup.extend(Meths, MethsMore) new_obj = Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000") new_obj.should == obj @@ -667,7 +826,7 @@ end end - describe "for a Integer" do + describe "for an Integer" do it "loads 0" do Marshal.send(@method, "\004\bi\000").should == 0 Marshal.send(@method, "\004\bi\005").should == 0 @@ -746,13 +905,13 @@ it "dumps a Fixnum" do val = Marshal.send(@method, "\004\bl+\ab:wU") val.should == 1433877090 - val.class.should == Fixnum + val.class.should == Integer end it "dumps an array containing multiple references to the Bignum as an array of Fixnum" do arr = Marshal.send(@method, "\004\b[\al+\a\223BwU@\006") arr.should == [1433879187, 1433879187] - arr.each { |v| v.class.should == Fixnum } + arr.each { |v| v.class.should == Integer } end end end diff --git a/ruby/spec/ruby/core/matchdata/captures_spec.rb b/ruby/spec/ruby/core/matchdata/captures_spec.rb index 8c0d2978b..58d462070 100644 --- a/ruby/spec/ruby/core/matchdata/captures_spec.rb +++ b/ruby/spec/ruby/core/matchdata/captures_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#captures" do it "returns an array of the match captures" do /(.)(.)(\d+)(\d)/.match("THX1138.").captures.should == ["H","X","113","8"] end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).captures.each { |c| c.should be_an_instance_of(String) } + end + end end diff --git a/ruby/spec/ruby/core/matchdata/element_reference_spec.rb b/ruby/spec/ruby/core/matchdata/element_reference_spec.rb index 26550ac94..3b976cb1c 100644 --- a/ruby/spec/ruby/core/matchdata/element_reference_spec.rb +++ b/ruby/spec/ruby/core/matchdata/element_reference_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#[]" do it "acts as normal array indexing [index]" do @@ -20,6 +21,13 @@ it "supports ranges [start..end]" do /(.)(.)(\d+)(\d)/.match("THX1138.")[1..3].should == %w|H X 113| end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str)[0..-1].each { |m| m.should be_an_instance_of(String) } + end + end end describe "MatchData#[Symbol]" do diff --git a/ruby/spec/ruby/core/matchdata/fixtures/classes.rb b/ruby/spec/ruby/core/matchdata/fixtures/classes.rb new file mode 100644 index 000000000..54795636e --- /dev/null +++ b/ruby/spec/ruby/core/matchdata/fixtures/classes.rb @@ -0,0 +1,3 @@ +module MatchDataSpecs + class MyString < String; end +end diff --git a/ruby/spec/ruby/core/matchdata/match_length_spec.rb b/ruby/spec/ruby/core/matchdata/match_length_spec.rb new file mode 100644 index 000000000..f7785ab1a --- /dev/null +++ b/ruby/spec/ruby/core/matchdata/match_length_spec.rb @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "MatchData#match_length" do + it "returns the length of the corresponding match when given an Integer" do + md = /(.)(.)(\d+)(\d)/.match("THX1138.") + + md.match_length(0).should == 6 + md.match_length(1).should == 1 + md.match_length(2).should == 1 + md.match_length(3).should == 3 + md.match_length(4).should == 1 + end + + it "returns nil on non-matching index matches" do + md = /\d+(\w)?/.match("THX1138.") + md.match_length(1).should == nil + end + + it "returns the length of the corresponding named match when given a Symbol" do + md = 'haystack'.match(/(?t(?ack))/) + md.match_length(:a).should == 3 + md.match_length(:t).should == 4 + end + + it "returns nil on non-matching index matches" do + md = 'haystack'.match(/(?t)(?all)?/) + md.match_length(:t).should == 1 + md.match_length(:a).should == nil + end + end +end diff --git a/ruby/spec/ruby/core/matchdata/match_spec.rb b/ruby/spec/ruby/core/matchdata/match_spec.rb new file mode 100644 index 000000000..545de6f93 --- /dev/null +++ b/ruby/spec/ruby/core/matchdata/match_spec.rb @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "MatchData#match" do + it "returns the corresponding match when given an Integer" do + md = /(.)(.)(\d+)(\d)/.match("THX1138.") + + md.match(0).should == 'HX1138' + md.match(1).should == 'H' + md.match(2).should == 'X' + md.match(3).should == '113' + md.match(4).should == '8' + end + + it "returns nil on non-matching index matches" do + md = /\d+(\w)?/.match("THX1138.") + md.match(1).should == nil + end + + it "returns the corresponding named match when given a Symbol" do + md = 'haystack'.match(/(?t(?ack))/) + md.match(:a).should == 'ack' + md.match(:t).should == 'tack' + end + + it "returns nil on non-matching index matches" do + md = 'haystack'.match(/(?t)(?all)?/) + md.match(:t).should == 't' + md.match(:a).should == nil + end + end +end diff --git a/ruby/spec/ruby/core/matchdata/post_match_spec.rb b/ruby/spec/ruby/core/matchdata/post_match_spec.rb index 4ae51f107..1a4ca0a83 100644 --- a/ruby/spec/ruby/core/matchdata/post_match_spec.rb +++ b/ruby/spec/ruby/core/matchdata/post_match_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#post_match" do it "returns the string after the match equiv. special var $'" do @@ -33,4 +34,11 @@ str = "abc".force_encoding Encoding::ISO_8859_1 str.match(/c/).post_match.encoding.should equal(Encoding::ISO_8859_1) end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).post_match.should be_an_instance_of(String) + end + end end diff --git a/ruby/spec/ruby/core/matchdata/pre_match_spec.rb b/ruby/spec/ruby/core/matchdata/pre_match_spec.rb index 824612c84..9b50336c7 100644 --- a/ruby/spec/ruby/core/matchdata/pre_match_spec.rb +++ b/ruby/spec/ruby/core/matchdata/pre_match_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#pre_match" do it "returns the string before the match, equiv. special var $`" do @@ -33,4 +34,11 @@ str = "abc".force_encoding Encoding::ISO_8859_1 str.match(/a/).pre_match.encoding.should equal(Encoding::ISO_8859_1) end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).pre_match.should be_an_instance_of(String) + end + end end diff --git a/ruby/spec/ruby/core/matchdata/string_spec.rb b/ruby/spec/ruby/core/matchdata/string_spec.rb index db0d5dfbd..420233e1f 100644 --- a/ruby/spec/ruby/core/matchdata/string_spec.rb +++ b/ruby/spec/ruby/core/matchdata/string_spec.rb @@ -9,7 +9,7 @@ it "returns a frozen copy of the match string" do str = /(.)(.)(\d+)(\d)/.match("THX1138.").string str.should == "THX1138." - str.frozen?.should == true + str.should.frozen? end it "returns the same frozen string for every call" do @@ -20,6 +20,6 @@ it "returns a frozen copy of the matched string for gsub(String)" do 'he[[o'.gsub!('[', ']') $~.string.should == 'he[[o' - $~.string.frozen?.should == true + $~.string.should.frozen? end end diff --git a/ruby/spec/ruby/core/matchdata/to_a_spec.rb b/ruby/spec/ruby/core/matchdata/to_a_spec.rb index 6231d096f..50f5a161a 100644 --- a/ruby/spec/ruby/core/matchdata/to_a_spec.rb +++ b/ruby/spec/ruby/core/matchdata/to_a_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#to_a" do it "returns an array of matches" do /(.)(.)(\d+)(\d)/.match("THX1138.").to_a.should == ["HX1138", "H", "X", "113", "8"] end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str)[0..-1].to_a.each { |m| m.should be_an_instance_of(String) } + end + end end diff --git a/ruby/spec/ruby/core/matchdata/to_s_spec.rb b/ruby/spec/ruby/core/matchdata/to_s_spec.rb index 9e213bb34..aab0955ae 100644 --- a/ruby/spec/ruby/core/matchdata/to_s_spec.rb +++ b/ruby/spec/ruby/core/matchdata/to_s_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#to_s" do it "returns the entire matched string" do /(.)(.)(\d+)(\d)/.match("THX1138.").to_s.should == "HX1138" end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str).to_s.should be_an_instance_of(String) + end + end end diff --git a/ruby/spec/ruby/core/math/tan_spec.rb b/ruby/spec/ruby/core/math/tan_spec.rb index c7b188cd8..67307f1e6 100644 --- a/ruby/spec/ruby/core/math/tan_spec.rb +++ b/ruby/spec/ruby/core/math/tan_spec.rb @@ -14,8 +14,8 @@ end it "returns NaN if called with +-Infinity" do - Math.tan(infinity_value).nan?.should == true - Math.tan(-infinity_value).nan?.should == true + Math.tan(infinity_value).should.nan? + Math.tan(-infinity_value).should.nan? end it "raises a TypeError if the argument cannot be coerced with Float()" do diff --git a/ruby/spec/ruby/core/method/case_compare_spec.rb b/ruby/spec/ruby/core/method/case_compare_spec.rb index 17785b5c1..a78953e8a 100644 --- a/ruby/spec/ruby/core/method/case_compare_spec.rb +++ b/ruby/spec/ruby/core/method/case_compare_spec.rb @@ -2,8 +2,6 @@ require_relative 'fixtures/classes' require_relative 'shared/call' -ruby_version_is "2.5" do - describe "Method#===" do - it_behaves_like :method_call, :=== - end +describe "Method#===" do + it_behaves_like :method_call, :=== end diff --git a/ruby/spec/ruby/core/method/compose_spec.rb b/ruby/spec/ruby/core/method/compose_spec.rb index aa0aded77..87cf61f7a 100644 --- a/ruby/spec/ruby/core/method/compose_spec.rb +++ b/ruby/spec/ruby/core/method/compose_spec.rb @@ -2,100 +2,99 @@ require_relative 'fixtures/classes' require_relative '../proc/shared/compose' -ruby_version_is "2.6" do - describe "Method#<<" do - it "returns a Proc that is the composition of self and the passed Proc" do - succ = MethodSpecs::Composition.new.method(:succ) - upcase = proc { |s| s.upcase } +describe "Method#<<" do + it "returns a Proc that is the composition of self and the passed Proc" do + succ = MethodSpecs::Composition.new.method(:succ) + upcase = proc { |s| s.upcase } - (succ << upcase).call('Ruby').should == "RUBZ" - end + (succ << upcase).call('Ruby').should == "RUBZ" + end - it "calls passed Proc with arguments and then calls self with result" do - pow_2_proc = proc { |x| x * x } - double_proc = proc { |x| x + x } + it "calls passed Proc with arguments and then calls self with result" do + pow_2_proc = proc { |x| x * x } + double_proc = proc { |x| x + x } - pow_2_method = MethodSpecs::Composition.new.method(:pow_2) - double_method = MethodSpecs::Composition.new.method(:double) + pow_2_method = MethodSpecs::Composition.new.method(:pow_2) + double_method = MethodSpecs::Composition.new.method(:double) - (pow_2_method << double_proc).call(2).should == 16 - (double_method << pow_2_proc).call(2).should == 8 - end + (pow_2_method << double_proc).call(2).should == 16 + (double_method << pow_2_proc).call(2).should == 8 + end - it "accepts any callable object" do - inc = MethodSpecs::Composition.new.method(:inc) + it "accepts any callable object" do + inc = MethodSpecs::Composition.new.method(:inc) - double = Object.new - def double.call(n); n * 2; end + double = Object.new + def double.call(n); n * 2; end - (inc << double).call(3).should == 7 - end + (inc << double).call(3).should == 7 + end - it_behaves_like :proc_compose, :<<, -> { MethodSpecs::Composition.new.method(:upcase) } + it_behaves_like :proc_compose, :<<, -> { MethodSpecs::Composition.new.method(:upcase) } - describe "composition" do - it "is a lambda" do - pow_2 = MethodSpecs::Composition.new.method(:pow_2) - double = proc { |x| x + x } + describe "composition" do + it "is a lambda" do + pow_2 = MethodSpecs::Composition.new.method(:pow_2) + double = proc { |x| x + x } - (pow_2 << double).is_a?(Proc).should == true - (pow_2 << double).lambda?.should == true - end + (pow_2 << double).is_a?(Proc).should == true + ruby_version_is(''...'3.0') { (pow_2 << double).should.lambda? } + ruby_version_is('3.0') { (pow_2 << double).should_not.lambda? } + end - it "may accept multiple arguments" do - inc = MethodSpecs::Composition.new.method(:inc) - mul = proc { |n, m| n * m } + it "may accept multiple arguments" do + inc = MethodSpecs::Composition.new.method(:inc) + mul = proc { |n, m| n * m } - (inc << mul).call(2, 3).should == 7 - end + (inc << mul).call(2, 3).should == 7 end end +end - describe "Method#>>" do - it "returns a Proc that is the composition of self and the passed Proc" do - upcase = proc { |s| s.upcase } - succ = MethodSpecs::Composition.new.method(:succ) +describe "Method#>>" do + it "returns a Proc that is the composition of self and the passed Proc" do + upcase = proc { |s| s.upcase } + succ = MethodSpecs::Composition.new.method(:succ) - (succ >> upcase).call('Ruby').should == "RUBZ" - end + (succ >> upcase).call('Ruby').should == "RUBZ" + end - it "calls passed Proc with arguments and then calls self with result" do - pow_2_proc = proc { |x| x * x } - double_proc = proc { |x| x + x } + it "calls passed Proc with arguments and then calls self with result" do + pow_2_proc = proc { |x| x * x } + double_proc = proc { |x| x + x } - pow_2_method = MethodSpecs::Composition.new.method(:pow_2) - double_method = MethodSpecs::Composition.new.method(:double) + pow_2_method = MethodSpecs::Composition.new.method(:pow_2) + double_method = MethodSpecs::Composition.new.method(:double) - (pow_2_method >> double_proc).call(2).should == 8 - (double_method >> pow_2_proc).call(2).should == 16 - end + (pow_2_method >> double_proc).call(2).should == 8 + (double_method >> pow_2_proc).call(2).should == 16 + end - it "accepts any callable object" do - inc = MethodSpecs::Composition.new.method(:inc) + it "accepts any callable object" do + inc = MethodSpecs::Composition.new.method(:inc) - double = Object.new - def double.call(n); n * 2; end + double = Object.new + def double.call(n); n * 2; end - (inc >> double).call(3).should == 8 - end + (inc >> double).call(3).should == 8 + end - it_behaves_like :proc_compose, :>>, -> { MethodSpecs::Composition.new.method(:upcase) } + it_behaves_like :proc_compose, :>>, -> { MethodSpecs::Composition.new.method(:upcase) } - describe "composition" do - it "is a lambda" do - pow_2 = MethodSpecs::Composition.new.method(:pow_2) - double = proc { |x| x + x } + describe "composition" do + it "is a lambda" do + pow_2 = MethodSpecs::Composition.new.method(:pow_2) + double = proc { |x| x + x } - (pow_2 >> double).is_a?(Proc).should == true - (pow_2 >> double).lambda?.should == true - end + (pow_2 >> double).is_a?(Proc).should == true + (pow_2 >> double).should.lambda? + end - it "may accept multiple arguments" do - mul = MethodSpecs::Composition.new.method(:mul) - inc = proc { |n| n + 1 } + it "may accept multiple arguments" do + mul = MethodSpecs::Composition.new.method(:mul) + inc = proc { |n| n + 1 } - (mul >> inc).call(2, 3).should == 7 - end + (mul >> inc).call(2, 3).should == 7 end end end diff --git a/ruby/spec/ruby/core/method/fixtures/classes.rb b/ruby/spec/ruby/core/method/fixtures/classes.rb index f3b7ff921..be96f65e2 100644 --- a/ruby/spec/ruby/core/method/fixtures/classes.rb +++ b/ruby/spec/ruby/core/method/fixtures/classes.rb @@ -50,6 +50,8 @@ def zero; end def one_req(a); end def two_req(a, b); end + def one_req_named(a:); end + def zero_with_block(&blk); end def one_req_with_block(a, &blk); end def two_req_with_block(a, b, &blk); end @@ -59,6 +61,8 @@ def one_req_one_opt(a, b=nil); end def one_req_two_opt(a, b=nil, c=nil); end def two_req_one_opt(a, b, c=nil); end + def one_opt_named(a: nil); end + def one_opt_with_block(a=nil, &blk); end def one_req_one_opt_with_block(a, b=nil, &blk); end def one_req_two_opt_with_block(a, b=nil, c=nil, &blk); end @@ -71,6 +75,8 @@ def one_req_one_opt_with_splat(a, b=nil, *c); end def two_req_one_opt_with_splat(a, b, c=nil, *d); end def one_req_two_opt_with_splat(a, b=nil, c=nil, *d); end + def zero_with_double_splat(**a); end + def zero_with_splat_and_block(*a, &blk); end def one_req_with_splat_and_block(a, *b, &blk); end def two_req_with_splat_and_block(a, b, *c, &blk); end diff --git a/ruby/spec/ruby/core/method/shared/to_s.rb b/ruby/spec/ruby/core/method/shared/to_s.rb index 766632293..0dcae41b5 100644 --- a/ruby/spec/ruby/core/method/shared/to_s.rb +++ b/ruby/spec/ruby/core/method/shared/to_s.rb @@ -4,7 +4,7 @@ describe :method_to_s, shared: true do before :each do @m = MethodSpecs::MySub.new.method :bar - @string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX') + @string = @m.send(@method) end it "returns a String" do @@ -24,6 +24,21 @@ @string.should =~ /\#bar/ end + ruby_version_is "2.7" do + it "returns a String containing method arguments" do + obj = MethodSpecs::Methods.new + obj.method(:zero).send(@method).should.include?("()") + obj.method(:one_req).send(@method).should.include?("(a)") + obj.method(:one_req_named).send(@method).should.include?("(a:)") + obj.method(:zero_with_block).send(@method).should.include?("(&blk)") + obj.method(:one_opt).send(@method).should.include?("(a=...)") + obj.method(:one_opt_named).send(@method).should.include?("(a: ...)") + obj.method(:zero_with_splat).send(@method).should.include?("(*a)") + obj.method(:zero_with_double_splat).send(@method).should.include?("(**a)") + obj.method(:one_req_one_opt_with_splat_and_block).send(@method).should.include?("(a, b=..., *c, &blk)") + end + end + it "returns a String containing the Module the method is defined in" do @string.should =~ /MethodSpecs::MyMod/ end @@ -32,13 +47,27 @@ @string.should =~ /MethodSpecs::MySub/ end - ruby_version_is '2.8' do + it "returns a String including all details" do + @string.should.start_with? "#(#{m.inspect})#bar" end end @@ -46,7 +75,15 @@ obj = MethodSpecs::MySub.new def obj.bar; end @m = obj.method(:bar) - @string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX') - @string.should =~ /\A#\.bar/ + @string = @m.send(@method).sub(/0x\h+/, '0xXXXXXX') + @string.should.start_with? "#.bar" + end + + ruby_version_is '2.7' do + ruby_bug '#17428', '2.7'...'3.0' do + it "shows the metaclass and the owner for a Module instance method retrieved from a class" do + String.method(:include).inspect.should.start_with?("#(Module)#include") + end + end end end diff --git a/ruby/spec/ruby/core/method/source_location_spec.rb b/ruby/spec/ruby/core/method/source_location_spec.rb index dd81b02c7..1f476aaa9 100644 --- a/ruby/spec/ruby/core/method/source_location_spec.rb +++ b/ruby/spec/ruby/core/method/source_location_spec.rb @@ -16,9 +16,9 @@ file.should == File.realpath('../fixtures/classes.rb', __FILE__) end - it "sets the last value to a Fixnum representing the line on which the method was defined" do + it "sets the last value to an Integer representing the line on which the method was defined" do line = @method.source_location.last - line.should be_an_instance_of(Fixnum) + line.should be_an_instance_of(Integer) line.should == 5 end @@ -86,6 +86,24 @@ def f method.source_location[1].should == line end + it "works for core methods where it returns nil or { @class.make_alias :ni, :san }.should raise_error(NameError) { |e| # a NameError and not a NoMethodError @@ -49,9 +61,9 @@ } end - it "raises #{frozen_error_class} if frozen" do + it "raises FrozenError if frozen" do @class.freeze - -> { @class.make_alias :uno, :public_one }.should raise_error(frozen_error_class) + -> { @class.make_alias :uno, :public_one }.should raise_error(FrozenError) end it "converts the names using #to_str" do @@ -69,19 +81,23 @@ -> { @class.make_alias mock('x'), :public_one }.should raise_error(TypeError) end - ruby_version_is ''...'2.5' do - it "is a private method" do - -> { @class.alias_method :ichi, :public_one }.should raise_error(NoMethodError) - end + it "is a public method" do + Module.should have_public_instance_method(:alias_method, false) end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:alias_method, false) + + describe "returned value" do + ruby_version_is ""..."3.0" do + it "returns self" do + @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class) + end end - end - it "returns self" do - @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class) + ruby_version_is "3.0" do + it "returns symbol of the defined method name" do + @class.send(:alias_method, :checking_return_value, :public_one).should equal(:checking_return_value) + @class.send(:alias_method, 'checking_return_value', :public_one).should equal(:checking_return_value) + end + end end it "works in module" do diff --git a/ruby/spec/ruby/core/module/allocate_spec.rb b/ruby/spec/ruby/core/module/allocate_spec.rb deleted file mode 100644 index 3b2c4119c..000000000 --- a/ruby/spec/ruby/core/module/allocate_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../spec_helper' - -describe "Module.allocate" do - it "returns an instance of Module" do - mod = Module.allocate - mod.should be_an_instance_of(Module) - end - - it "returns a fully-formed instance of Module" do - mod = Module.allocate - mod.constants.should_not == nil - mod.methods.should_not == nil - end -end diff --git a/ruby/spec/ruby/core/module/append_features_spec.rb b/ruby/spec/ruby/core/module/append_features_spec.rb index 8fb3febc0..d960798ee 100644 --- a/ruby/spec/ruby/core/module/append_features_spec.rb +++ b/ruby/spec/ruby/core/module/append_features_spec.rb @@ -67,8 +67,8 @@ def self.append_features(mod) @other = Module.new.freeze end - it "raises a #{frozen_error_class} before appending self" do - -> { @receiver.send(:append_features, @other) }.should raise_error(frozen_error_class) + it "raises a FrozenError before appending self" do + -> { @receiver.send(:append_features, @other) }.should raise_error(FrozenError) @other.ancestors.should_not include(@receiver) end end diff --git a/ruby/spec/ruby/core/module/attr_accessor_spec.rb b/ruby/spec/ruby/core/module/attr_accessor_spec.rb index ce95ccd48..ba5289cbe 100644 --- a/ruby/spec/ruby/core/module/attr_accessor_spec.rb +++ b/ruby/spec/ruby/core/module/attr_accessor_spec.rb @@ -33,10 +33,23 @@ class TrueClass attr_accessor :spec_attr_accessor end - -> { true.spec_attr_accessor = "a" }.should raise_error(RuntimeError) + -> { true.spec_attr_accessor = "a" }.should raise_error(FrozenError) end - it "converts non string/symbol/fixnum names to strings using to_str" do + it "raises FrozenError if the receiver if frozen" do + c = Class.new do + attr_accessor :foo + end + obj = c.new + obj.foo = 1 + obj.foo.should == 1 + + obj.freeze + -> { obj.foo = 42 }.should raise_error(FrozenError) + obj.foo.should == 1 + end + + it "converts non string/symbol names to strings using to_str" do (o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test") c = Class.new do attr_accessor o @@ -63,30 +76,39 @@ class TrueClass -> { c.new.foo=1 }.should raise_error(NoMethodError) end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:attr_accessor, false) + it "is a public method" do + Module.should have_public_instance_method(:attr_accessor, false) + end + + ruby_version_is ""..."3.0" do + it "returns nil" do + Class.new do + (attr_accessor :foo, 'bar').should == nil + end end end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:attr_accessor, false) + + ruby_version_is "3.0" do + it "returns an array of defined method names as symbols" do + Class.new do + (attr_accessor :foo, 'bar').should == [:foo, :foo=, :bar, :bar=] + end end end describe "on immediates" do before :each do - class Fixnum + class Integer attr_accessor :foobar end end after :each do - if Fixnum.method_defined?(:foobar) - Fixnum.send(:remove_method, :foobar) + if Integer.method_defined?(:foobar) + Integer.send(:remove_method, :foobar) end - if Fixnum.method_defined?(:foobar=) - Fixnum.send(:remove_method, :foobar=) + if Integer.method_defined?(:foobar=) + Integer.send(:remove_method, :foobar=) end end diff --git a/ruby/spec/ruby/core/module/attr_reader_spec.rb b/ruby/spec/ruby/core/module/attr_reader_spec.rb index 082bc03b6..b0ae906ab 100644 --- a/ruby/spec/ruby/core/module/attr_reader_spec.rb +++ b/ruby/spec/ruby/core/module/attr_reader_spec.rb @@ -32,7 +32,7 @@ class TrueClass -> { true.instance_variable_set("@spec_attr_reader", "a") }.should raise_error(RuntimeError) end - it "converts non string/symbol/fixnum names to strings using to_str" do + it "converts non string/symbol names to strings using to_str" do (o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test") c = Class.new do attr_reader o @@ -58,14 +58,23 @@ class TrueClass -> { c.new.foo }.should raise_error(NoMethodError) end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:attr_reader, false) + it "is a public method" do + Module.should have_public_instance_method(:attr_reader, false) + end + + ruby_version_is ""..."3.0" do + it "returns nil" do + Class.new do + (attr_reader :foo, 'bar').should == nil + end end end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:attr_reader, false) + + ruby_version_is "3.0" do + it "returns an array of defined method names as symbols" do + Class.new do + (attr_reader :foo, 'bar').should == [:foo, :bar] + end end end end diff --git a/ruby/spec/ruby/core/module/attr_spec.rb b/ruby/spec/ruby/core/module/attr_spec.rb index 20316a3d3..33e0eb862 100644 --- a/ruby/spec/ruby/core/module/attr_spec.rb +++ b/ruby/spec/ruby/core/module/attr_spec.rb @@ -124,7 +124,7 @@ def initialize -> { c.new.bar }.should raise_error(NoMethodError) end - it "converts non string/symbol/fixnum names to strings using to_str" do + it "converts non string/symbol names to strings using to_str" do (o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test") Class.new { attr o }.new.respond_to?("test").should == true end @@ -142,14 +142,27 @@ def initialize }.should complain(/boolean argument is obsoleted/, verbose: true) end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:attr, false) + it "is a public method" do + Module.should have_public_instance_method(:attr, false) + end + + ruby_version_is ""..."3.0" do + it "returns nil" do + Class.new do + (attr :foo, 'bar').should == nil + (attr :baz, false).should == nil + (attr :qux, true).should == nil + end end end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:attr, false) + + ruby_version_is "3.0" do + it "returns an array of defined method names as symbols" do + Class.new do + (attr :foo, 'bar').should == [:foo, :bar] + (attr :baz, false).should == [:baz] + (attr :qux, true).should == [:qux, :qux=] + end end end end diff --git a/ruby/spec/ruby/core/module/attr_writer_spec.rb b/ruby/spec/ruby/core/module/attr_writer_spec.rb index 3b110cecf..0e9d20131 100644 --- a/ruby/spec/ruby/core/module/attr_writer_spec.rb +++ b/ruby/spec/ruby/core/module/attr_writer_spec.rb @@ -29,10 +29,20 @@ class TrueClass attr_writer :spec_attr_writer end - -> { true.spec_attr_writer = "a" }.should raise_error(RuntimeError) + -> { true.spec_attr_writer = "a" }.should raise_error(FrozenError) end - it "converts non string/symbol/fixnum names to strings using to_str" do + it "raises FrozenError if the receiver if frozen" do + c = Class.new do + attr_writer :foo + end + obj = c.new + obj.freeze + + -> { obj.foo = 42 }.should raise_error(FrozenError) + end + + it "converts non string/symbol names to strings using to_str" do (o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test") c = Class.new do attr_writer o @@ -58,14 +68,23 @@ class TrueClass -> { c.new.foo=1 }.should raise_error(NoMethodError) end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:attr_writer, false) + it "is a public method" do + Module.should have_public_instance_method(:attr_writer, false) + end + + ruby_version_is ""..."3.0" do + it "returns nil" do + Class.new do + (attr_writer :foo, 'bar').should == nil + end end end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:attr_writer, false) + + ruby_version_is "3.0" do + it "returns an array of defined method names as symbols" do + Class.new do + (attr_writer :foo, 'bar').should == [:foo=, :bar=] + end end end end diff --git a/ruby/spec/ruby/core/module/autoload_spec.rb b/ruby/spec/ruby/core/module/autoload_spec.rb index 996460234..1d61646db 100644 --- a/ruby/spec/ruby/core/module/autoload_spec.rb +++ b/ruby/spec/ruby/core/module/autoload_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative '../../fixtures/code_loading' require_relative 'fixtures/classes' require 'thread' @@ -33,14 +34,7 @@ describe "Module#autoload" do before :all do @non_existent = fixture __FILE__, "no_autoload.rb" - - # Require RubyGems eagerly, to ensure #require is already the RubyGems - # version, before starting #autoload specs which snapshot #require, and - # could end up redefining #require as the original core Kernel#require. - begin - require "rubygems" - rescue LoadError - end + CodeLoadingSpecs.preload_rubygems end before :each do @@ -210,6 +204,13 @@ class ModuleSpecs::Autoload::HClass ModuleSpecs::Autoload.use_ex1.should == :good end + it "considers an autoload constant as loaded when autoload is called for/from the current file" do + filename = fixture(__FILE__, "autoload_during_require_current_file.rb") + require filename + + ScratchPad.recorded.should be_nil + end + describe "interacting with defined?" do it "does not load the file when referring to the constant in defined?" do module ModuleSpecs::Autoload::Dog @@ -294,6 +295,32 @@ module ModuleSpecs::Autoload ScratchPad.recorded.should == [nil, nil] @check.call.should == ["constant", nil] end + + it "does not raise an error if the autoload constant was not defined" do + module ModuleSpecs::Autoload + autoload :RequiredDirectlyNoConstant, fixture(__FILE__, "autoload_required_directly_no_constant.rb") + end + @path = fixture(__FILE__, "autoload_required_directly_no_constant.rb") + @remove << :RequiredDirectlyNoConstant + @check = -> { + [ + defined?(ModuleSpecs::Autoload::RequiredDirectlyNoConstant), + ModuleSpecs::Autoload.constants(false).include?(:RequiredDirectlyNoConstant), + ModuleSpecs::Autoload.const_defined?(:RequiredDirectlyNoConstant), + ModuleSpecs::Autoload.autoload?(:RequiredDirectlyNoConstant) + ] + } + ScratchPad.record @check + @check.call.should == ["constant", true, true, @path] + $:.push File.dirname(@path) + begin + require "autoload_required_directly_no_constant.rb" + ensure + $:.pop + end + ScratchPad.recorded.should == [nil, true, false, nil] + @check.call.should == [nil, true, false, nil] + end end describe "after the autoload is triggered by require" do @@ -414,21 +441,42 @@ def check_before_during_thread_after(&check) ScratchPad.recorded.should == [:raise, :raise] end - it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do - path = fixture(__FILE__, "autoload_o.rb") - ScratchPad.record [] - ModuleSpecs::Autoload.autoload :O, path + ruby_version_is "3.1" do + it "removes the constant from Module#constants if the loaded file does not define it" do + path = fixture(__FILE__, "autoload_o.rb") + ScratchPad.record [] + ModuleSpecs::Autoload.autoload :O, path + + ModuleSpecs::Autoload.const_defined?(:O).should == true + ModuleSpecs::Autoload.should have_constant(:O) + ModuleSpecs::Autoload.autoload?(:O).should == path + + -> { ModuleSpecs::Autoload::O }.should raise_error(NameError) + + ModuleSpecs::Autoload.const_defined?(:O).should == false + ModuleSpecs::Autoload.should_not have_constant(:O) + ModuleSpecs::Autoload.autoload?(:O).should == nil + -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError) + end + end - ModuleSpecs::Autoload.const_defined?(:O).should == true - ModuleSpecs::Autoload.should have_constant(:O) - ModuleSpecs::Autoload.autoload?(:O).should == path + ruby_version_is ""..."3.1" do + it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do + path = fixture(__FILE__, "autoload_o.rb") + ScratchPad.record [] + ModuleSpecs::Autoload.autoload :O, path + + ModuleSpecs::Autoload.const_defined?(:O).should == true + ModuleSpecs::Autoload.should have_constant(:O) + ModuleSpecs::Autoload.autoload?(:O).should == path - -> { ModuleSpecs::Autoload::O }.should raise_error(NameError) + -> { ModuleSpecs::Autoload::O }.should raise_error(NameError) - ModuleSpecs::Autoload.should have_constant(:O) - ModuleSpecs::Autoload.const_defined?(:O).should == false - ModuleSpecs::Autoload.autoload?(:O).should == nil - -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError) + ModuleSpecs::Autoload.const_defined?(:O).should == false + ModuleSpecs::Autoload.should have_constant(:O) + ModuleSpecs::Autoload.autoload?(:O).should == nil + -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError) + end end it "does not try to load the file again if the loaded file did not define the constant" do @@ -527,31 +575,54 @@ class LexicalScope # Basically, the parent autoload constant remains in a "undefined" state self.autoload?(:DeclaredInParentDefinedInCurrent).should == nil const_defined?(:DeclaredInParentDefinedInCurrent).should == false - self.should have_constant(:DeclaredInParentDefinedInCurrent) -> { DeclaredInParentDefinedInCurrent }.should raise_error(NameError) ModuleSpecs::Autoload::LexicalScope.send(:remove_const, :DeclaredInParentDefinedInCurrent) end end - it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do - @remove << :DeclaredInCurrentDefinedInParent - module ModuleSpecs::Autoload - ScratchPad.record -> { - DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent - } + ruby_version_is "3.1" do + it "looks up in parent scope after failed autoload" do + @remove << :DeclaredInCurrentDefinedInParent + module ModuleSpecs::Autoload + ScratchPad.record -> { + DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent + } - class LexicalScope - autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb") - -> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError) - # Basically, the autoload constant remains in a "undefined" state - self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil - const_defined?(:DeclaredInCurrentDefinedInParent).should == false - self.should have_constant(:DeclaredInCurrentDefinedInParent) - -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError) + class LexicalScope + autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb") + -> { DeclaredInCurrentDefinedInParent }.should_not raise_error(NameError) + # Basically, the autoload constant remains in a "undefined" state + self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil + const_defined?(:DeclaredInCurrentDefinedInParent).should == false + -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError) + end + + DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent end + end + end - DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent + ruby_version_is ""..."3.1" do + it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do + @remove << :DeclaredInCurrentDefinedInParent + module ModuleSpecs::Autoload + ScratchPad.record -> { + DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent + } + + class LexicalScope + autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb") + -> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError) + # Basically, the autoload constant remains in a "undefined" state + self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil + const_defined?(:DeclaredInCurrentDefinedInParent).should == false + self.should have_constant(:DeclaredInCurrentDefinedInParent) + -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError) + end + + DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent + end end end @@ -737,9 +808,9 @@ class ModuleSpecs::Autoload::Z < ModuleSpecs::Autoload::ZZ end describe "on a frozen module" do - it "raises a #{frozen_error_class} before setting the name" do + it "raises a FrozenError before setting the name" do frozen_module = Module.new.freeze - -> { frozen_module.autoload :Foo, @non_existent }.should raise_error(frozen_error_class) + -> { frozen_module.autoload :Foo, @non_existent }.should raise_error(FrozenError) frozen_module.should_not have_constant(:Foo) end end diff --git a/ruby/spec/ruby/core/module/class_variable_defined_spec.rb b/ruby/spec/ruby/core/module/class_variable_defined_spec.rb index f867d383c..c0f2072a3 100644 --- a/ruby/spec/ruby/core/module/class_variable_defined_spec.rb +++ b/ruby/spec/ruby/core/module/class_variable_defined_spec.rb @@ -51,7 +51,7 @@ }.should raise_error(NameError) end - it "converts a non string/symbol/fixnum name to string using to_str" do + it "converts a non string/symbol name to string using to_str" do c = Class.new { class_variable_set :@@class_var, "test" } (o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var") c.class_variable_defined?(o).should == true diff --git a/ruby/spec/ruby/core/module/class_variable_get_spec.rb b/ruby/spec/ruby/core/module/class_variable_get_spec.rb index 79d22a506..e5d06731e 100644 --- a/ruby/spec/ruby/core/module/class_variable_get_spec.rb +++ b/ruby/spec/ruby/core/module/class_variable_get_spec.rb @@ -60,7 +60,7 @@ -> { c.send(:class_variable_get, "@invalid_name") }.should raise_error(NameError) end - it "converts a non string/symbol/fixnum name to string using to_str" do + it "converts a non string/symbol name to string using to_str" do c = Class.new { class_variable_set :@@class_var, "test" } (o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var") c.send(:class_variable_get, o).should == "test" diff --git a/ruby/spec/ruby/core/module/class_variable_set_spec.rb b/ruby/spec/ruby/core/module/class_variable_set_spec.rb index 204bbaf75..63f32f538 100644 --- a/ruby/spec/ruby/core/module/class_variable_set_spec.rb +++ b/ruby/spec/ruby/core/module/class_variable_set_spec.rb @@ -25,13 +25,13 @@ c.send(:class_variable_get, "@@mvar").should == :new_mvar end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do -> { Class.new.freeze.send(:class_variable_set, :@@test, "test") - }.should raise_error(frozen_error_class) + }.should raise_error(FrozenError) -> { Module.new.freeze.send(:class_variable_set, :@@test, "test") - }.should raise_error(frozen_error_class) + }.should raise_error(FrozenError) end it "raises a NameError when the given name is not allowed" do @@ -45,7 +45,7 @@ }.should raise_error(NameError) end - it "converts a non string/symbol/fixnum name to string using to_str" do + it "converts a non string/symbol name to string using to_str" do (o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var") c = Class.new c.send(:class_variable_set, o, "test") diff --git a/ruby/spec/ruby/core/module/const_defined_spec.rb b/ruby/spec/ruby/core/module/const_defined_spec.rb index 0673adca3..75730395e 100644 --- a/ruby/spec/ruby/core/module/const_defined_spec.rb +++ b/ruby/spec/ruby/core/module/const_defined_spec.rb @@ -40,6 +40,11 @@ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, true).should be_true end + it "coerces the inherit flag to a boolean" do + ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, nil).should be_false + ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, :true).should be_true + end + it "returns true if the given String names a constant defined in the receiver" do ConstantSpecs.const_defined?("CS_CONST2").should == true ConstantSpecs.const_defined?("ModuleA").should == true diff --git a/ruby/spec/ruby/core/module/const_get_spec.rb b/ruby/spec/ruby/core/module/const_get_spec.rb index 0a6702903..9f9fafe5b 100644 --- a/ruby/spec/ruby/core/module/const_get_spec.rb +++ b/ruby/spec/ruby/core/module/const_get_spec.rb @@ -88,6 +88,14 @@ end.should raise_error(NameError) end + it "coerces the inherit flag to a boolean" do + ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST4, :true).should == :const4 + + -> do + ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST1, nil) + end.should raise_error(NameError) + end + it "accepts a toplevel scope qualifier" do ConstantSpecs.const_get("::CS_CONST1").should == :const1 end diff --git a/ruby/spec/ruby/core/module/const_set_spec.rb b/ruby/spec/ruby/core/module/const_set_spec.rb index 1b8b86dd0..ba7810d17 100644 --- a/ruby/spec/ruby/core/module/const_set_spec.rb +++ b/ruby/spec/ruby/core/module/const_set_spec.rb @@ -20,10 +20,20 @@ m.name.should == "ConstantSpecs::CS_CONST1000" end - it "does not set the name of a module scoped by an anonymous module" do - a, b = Module.new, Module.new - a.const_set :B, b - b.name.should be_nil + ruby_version_is ""..."3.0" do + it "does not set the name of a module scoped by an anonymous module" do + a, b = Module.new, Module.new + a.const_set :B, b + b.name.should be_nil + end + end + + ruby_version_is "3.0" do + it "sets the name of a module scoped by an anonymous module" do + a, b = Module.new, Module.new + a.const_set :B, b + b.name.should.end_with? '::B' + end end it "sets the name of contained modules when assigning a toplevel anonymous module" do @@ -91,7 +101,7 @@ mod.const_get(:Foo).should == 1 end - it "does not warn if the previous value was undefined" do + it "does not warn after a failed autoload" do path = fixture(__FILE__, "autoload_o.rb") ScratchPad.record [] mod = Module.new @@ -99,7 +109,6 @@ mod.autoload :Foo, path -> { mod::Foo }.should raise_error(NameError) - mod.should have_constant(:Foo) mod.const_defined?(:Foo).should == false mod.autoload?(:Foo).should == nil @@ -125,8 +134,8 @@ @name = :Foo end - it "raises a #{frozen_error_class} before setting the name" do - -> { @frozen.const_set @name, nil }.should raise_error(frozen_error_class) + it "raises a FrozenError before setting the name" do + -> { @frozen.const_set @name, nil }.should raise_error(FrozenError) @frozen.should_not have_constant(@name) end end diff --git a/ruby/spec/ruby/core/module/const_source_location_spec.rb b/ruby/spec/ruby/core/module/const_source_location_spec.rb new file mode 100644 index 000000000..9e1f2c1c4 --- /dev/null +++ b/ruby/spec/ruby/core/module/const_source_location_spec.rb @@ -0,0 +1,220 @@ +require_relative '../../spec_helper' +require_relative '../../fixtures/constants' + +describe "Module#const_source_location" do + before do + @constants_fixture_path = File.expand_path('../../fixtures/constants.rb', __dir__) + end + + ruby_version_is "2.7" do + describe "with dynamically assigned constants" do + it "searches a path in the immediate class or module first" do + ConstantSpecs::ClassA::CSL_CONST301 = :const301_1 + ConstantSpecs::ClassA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1] + + ConstantSpecs::ModuleA::CSL_CONST301 = :const301_2 + ConstantSpecs::ModuleA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1] + + ConstantSpecs::ParentA::CSL_CONST301 = :const301_3 + ConstantSpecs::ParentA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1] + + ConstantSpecs::ContainerA::ChildA::CSL_CONST301 = :const301_5 + ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1] + end + + it "searches a path in a module included in the immediate class before the superclass" do + ConstantSpecs::ParentB::CSL_CONST302 = :const302_1 + ConstantSpecs::ModuleF::CSL_CONST302 = :const302_2 + ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST302).should == [__FILE__, __LINE__ - 1] + end + + it "searches a path in the superclass before a module included in the superclass" do + ConstantSpecs::ModuleE::CSL_CONST303 = :const303_1 + ConstantSpecs::ParentB::CSL_CONST303 = :const303_2 + ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST303).should == [__FILE__, __LINE__ - 1] + end + + it "searches a path in a module included in the superclass" do + ConstantSpecs::ModuleA::CSL_CONST304 = :const304_1 + ConstantSpecs::ModuleE::CSL_CONST304 = :const304_2 + ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST304).should == [__FILE__, __LINE__ - 1] + end + + it "searches a path in the superclass chain" do + ConstantSpecs::ModuleA::CSL_CONST305 = :const305 + ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST305).should == [__FILE__, __LINE__ - 1] + end + + it "returns path to a toplevel constant when the receiver is a Class" do + Object::CSL_CONST306 = :const306 + ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST306).should == [__FILE__, __LINE__ - 1] + end + + it "returns path to a toplevel constant when the receiver is a Module" do + Object::CSL_CONST308 = :const308 + ConstantSpecs.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 1] + ConstantSpecs::ModuleA.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 2] + end + + it "returns path to the updated value of a constant" do + ConstantSpecs::ClassB::CSL_CONST309 = :const309_1 + ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 1] + + -> { + ConstantSpecs::ClassB::CSL_CONST309 = :const309_2 + }.should complain(/already initialized constant/) + ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2] + end + end + + describe "with statically assigned constants" do + it "searches location path the immediate class or module first" do + ConstantSpecs::ClassA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE] + ConstantSpecs::ModuleA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST10_LINE] + ConstantSpecs::ParentA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST10_LINE] + ConstantSpecs::ContainerA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::CS_CONST10_LINE] + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::ChildA::CS_CONST10_LINE] + end + + it "searches location path a module included in the immediate class before the superclass" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST15).should == [@constants_fixture_path, ConstantSpecs::ModuleC::CS_CONST15_LINE] + end + + it "searches location path the superclass before a module included in the superclass" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST11).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST11_LINE] + end + + it "searches location path a module included in the superclass" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST12).should == [@constants_fixture_path, ConstantSpecs::ModuleB::CS_CONST12_LINE] + end + + it "searches location path the superclass chain" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST13).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST13_LINE] + end + + it "returns location path a toplevel constant when the receiver is a Class" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE] + end + + it "returns location path a toplevel constant when the receiver is a Module" do + ConstantSpecs.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE] + ConstantSpecs::ModuleA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE] + end + end + + it "return empty path if constant defined in C code" do + Object.const_source_location(:String).should == [] + end + + it "accepts a String or Symbol name" do + Object.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE] + Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE] + end + + it "returns nil if no constant is defined in the search path" do + ConstantSpecs.const_source_location(:CS_CONSTX).should == nil + end + + it "raises a NameError if the name does not start with a capital letter" do + -> { ConstantSpecs.const_source_location "name" }.should raise_error(NameError) + end + + it "raises a NameError if the name starts with a non-alphabetic character" do + -> { ConstantSpecs.const_source_location "__CONSTX__" }.should raise_error(NameError) + -> { ConstantSpecs.const_source_location "@CS_CONST1" }.should raise_error(NameError) + -> { ConstantSpecs.const_source_location "!CS_CONST1" }.should raise_error(NameError) + end + + it "raises a NameError if the name contains non-alphabetic characters except '_'" do + Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE] + -> { ConstantSpecs.const_source_location "CS_CONST1=" }.should raise_error(NameError) + -> { ConstantSpecs.const_source_location "CS_CONST1?" }.should raise_error(NameError) + end + + it "calls #to_str to convert the given name to a String" do + name = mock("ClassA") + name.should_receive(:to_str).and_return("ClassA") + ConstantSpecs.const_source_location(name).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CLASS_A_LINE] + end + + it "raises a TypeError if conversion to a String by calling #to_str fails" do + name = mock('123') + -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError) + + name.should_receive(:to_str).and_return(123) + -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError) + end + + it "does not search the singleton class of a Class or Module" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST14).should == nil + ConstantSpecs.const_source_location(:CS_CONST14).should == nil + end + + it "does not search the containing scope" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST20).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST20_LINE] + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST5) == nil + end + + it "returns nil if the constant is defined in the receiver's superclass and the inherit flag is false" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, false).should == nil + end + + it "searches into the receiver superclasses if the inherit flag is true" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, true).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST4_LINE] + end + + it "returns nil when the receiver is a Module, the constant is defined at toplevel and the inherit flag is false" do + ConstantSpecs::ModuleA.const_source_location(:CS_CONST1, false).should == nil + end + + it "returns nil when the receiver is a Class, the constant is defined at toplevel and the inherit flag is false" do + ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1, false).should == nil + end + + it "accepts a toplevel scope qualifier" do + ConstantSpecs.const_source_location("::CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE] + end + + it "accepts a scoped constant name" do + ConstantSpecs.const_source_location("ClassA::CS_CONST10").should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE] + end + + it "raises a NameError if the name includes two successive scope separators" do + -> { ConstantSpecs.const_source_location("ClassA::::CS_CONST10") }.should raise_error(NameError) + end + + it "raises a NameError if only '::' is passed" do + -> { ConstantSpecs.const_source_location("::") }.should raise_error(NameError) + end + + it "raises a NameError if a Symbol has a toplevel scope qualifier" do + -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should raise_error(NameError) + end + + it "raises a NameError if a Symbol is a scoped constant name" do + -> { ConstantSpecs.const_source_location(:'ClassA::CS_CONST10') }.should raise_error(NameError) + end + + it "does search private constants path" do + ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE] + end + + context 'autoload' do + before :all do + ConstantSpecs.autoload :CSL_CONST1, "#{__dir__}/notexisting.rb" + @line = __LINE__ - 1 + end + + it 'returns the autoload location while not resolved' do + ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line] + end + + it 'returns where the constant was resolved when resolved' do + file = fixture(__FILE__, 'autoload_location.rb') + ConstantSpecs.autoload :CONST_LOCATION, file + line = ConstantSpecs::CONST_LOCATION + ConstantSpecs.const_source_location('CONST_LOCATION').should == [file, line] + end + end + end +end diff --git a/ruby/spec/ruby/core/module/constants_spec.rb b/ruby/spec/ruby/core/module/constants_spec.rb index 4538e828d..330da1cc8 100644 --- a/ruby/spec/ruby/core/module/constants_spec.rb +++ b/ruby/spec/ruby/core/module/constants_spec.rb @@ -13,9 +13,9 @@ module ConstantSpecsAdded it "returns an array of Symbol names" do # This in NOT an exhaustive list - Module.constants.should include(:Array, :Bignum, :Class, :Comparable, :Dir, + Module.constants.should include(:Array, :Class, :Comparable, :Dir, :Enumerable, :ENV, :Exception, :FalseClass, - :File, :Fixnum, :Float, :Hash, :Integer, :IO, + :File, :Float, :Hash, :Integer, :IO, :Kernel, :Math, :Method, :Module, :NilClass, :Numeric, :Object, :Range, :Regexp, :String, :Symbol, :Thread, :Time, :TrueClass) @@ -43,37 +43,43 @@ class Module describe "Module#constants" do it "returns an array of Symbol names of all constants defined in the module and all included modules" do ConstantSpecs::ContainerA.constants.sort.should == [ - :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA + :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA ] end it "returns all constants including inherited when passed true" do ConstantSpecs::ContainerA.constants(true).sort.should == [ - :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA + :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA ] end it "returns all constants including inherited when passed some object" do ConstantSpecs::ContainerA.constants(Object.new).sort.should == [ - :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA + :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA ] end it "doesn't returns inherited constants when passed false" do ConstantSpecs::ContainerA.constants(false).sort.should == [ - :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA + :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA ] end it "doesn't returns inherited constants when passed nil" do ConstantSpecs::ContainerA.constants(nil).sort.should == [ - :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA + :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA ] end it "returns only public constants" do ModuleSpecs::PrivConstModule.constants.should == [:PUBLIC_CONSTANT] end + + it "returns only constants starting with an uppercase letter" do + # e.g. fatal, IO::generic_readable and IO::generic_writable should not be returned by Module#constants + Object.constants.each { |c| c[0].should == c[0].upcase } + IO.constants.each { |c| c[0].should == c[0].upcase } + end end describe "Module#constants" do diff --git a/ruby/spec/ruby/core/module/define_method_spec.rb b/ruby/spec/ruby/core/module/define_method_spec.rb index 29394e5b9..c65b30de2 100644 --- a/ruby/spec/ruby/core/module/define_method_spec.rb +++ b/ruby/spec/ruby/core/module/define_method_spec.rb @@ -88,6 +88,23 @@ def ziggy end end +describe "Module#define_method" do + describe "when the default definee is not the same as the module" do + it "sets the visibility of the method to public" do + klass = Class.new + class << klass + private + define_method(:meta) do + define_method(:foo) { :foo } + end + end + + klass.send :meta + klass.new.foo.should == :foo + end + end +end + describe "Module#define_method when name is not a special private name" do describe "given an UnboundMethod" do describe "and called from the target module" do @@ -245,10 +262,10 @@ class DefineMethodSpecClass -> { obj.proc_style_test :arg }.should raise_error(ArgumentError) end - it "raises a #{frozen_error_class} if frozen" do + it "raises a FrozenError if frozen" do -> { Class.new { freeze; define_method(:foo) {} } - }.should raise_error(frozen_error_class) + }.should raise_error(FrozenError) end it "accepts a Method (still bound)" do @@ -333,6 +350,14 @@ def cool_method object2.other_cool_method.should == "data is foo" end + it "accepts a proc from a Symbol" do + symbol_proc = :+.to_proc + klass = Class.new do + define_method :foo, &symbol_proc + end + klass.new.foo(1, 2).should == 3 + end + it "maintains the Proc's scope" do class DefineMethodByProcClass in_scope = true @@ -355,15 +380,8 @@ class DefineMethodByProcClass klass.new.string_test.should == "string_test result" end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:define_method) - end - end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:define_method) - end + it "is a public method" do + Module.should have_public_instance_method(:define_method) end it "returns its symbol" do @@ -498,7 +516,36 @@ def foo it "receives the value passed as the argument when passed one argument" do @klass.new.m(1).should == 1 end + end + + describe "passed { |a,| } creates a method that" do + before :each do + @klass = Class.new do + define_method(:m) { |a,| a } + end + end + + it "raises an ArgumentError when passed zero arguments" do + -> { @klass.new.m }.should raise_error(ArgumentError) + end + it "raises an ArgumentError when passed zero arguments and a block" do + -> { @klass.new.m { :computed } }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when passed two arguments" do + -> { @klass.new.m 1, 2 }.should raise_error(ArgumentError) + end + + it "receives the value passed as the argument when passed one argument" do + @klass.new.m(1).should == 1 + end + + it "does not destructure the passed argument" do + @klass.new.m([1, 2]).should == [1, 2] + # for comparison: + proc { |a,| a }.call([1, 2]).should == 1 + end end describe "passed { |*a| } creates a method that" do @@ -676,3 +723,46 @@ def nested_method_in_proc_for_define_method end end end + +describe "Method#define_method when passed a block" do + describe "behaves exactly like a lambda" do + it "for return" do + Class.new do + define_method(:foo) do + return 42 + end + end.new.foo.should == 42 + end + + it "for break" do + Class.new do + define_method(:foo) do + break 42 + end + end.new.foo.should == 42 + end + + it "for next" do + Class.new do + define_method(:foo) do + next 42 + end + end.new.foo.should == 42 + end + + it "for redo" do + Class.new do + result = [] + define_method(:foo) do + if result.empty? + result << :first + redo + else + result << :second + result + end + end + end.new.foo.should == [:first, :second] + end + end +end diff --git a/ruby/spec/ruby/core/module/deprecate_constant_spec.rb b/ruby/spec/ruby/core/module/deprecate_constant_spec.rb index 7bcced981..faacbea03 100644 --- a/ruby/spec/ruby/core/module/deprecate_constant_spec.rb +++ b/ruby/spec/ruby/core/module/deprecate_constant_spec.rb @@ -9,7 +9,6 @@ @module::PRIVATE = @value @module.private_constant :PRIVATE @module.deprecate_constant :PRIVATE - @pattern = /deprecated/ end describe "when accessing the deprecated module" do @@ -19,7 +18,7 @@ value = nil -> { value = @module::PUBLIC1 - }.should complain(@pattern) + }.should complain(/warning: constant .+::PUBLIC1 is deprecated/) value.should equal(@value) -> { @module::PRIVATE }.should raise_error(NameError) @@ -28,16 +27,30 @@ it "warns with a message" do @module.deprecate_constant :PUBLIC1 - -> { @module::PUBLIC1 }.should complain(@pattern) - -> { @module.const_get :PRIVATE }.should complain(@pattern) + -> { @module::PUBLIC1 }.should complain(/warning: constant .+::PUBLIC1 is deprecated/) + -> { @module.const_get :PRIVATE }.should complain(/warning: constant .+::PRIVATE is deprecated/) + end + + ruby_version_is '2.7' do + it "does not warn if Warning[:deprecated] is false" do + @module.deprecate_constant :PUBLIC1 + + deprecated = Warning[:deprecated] + begin + Warning[:deprecated] = false + -> { @module::PUBLIC1 }.should_not complain + ensure + Warning[:deprecated] = deprecated + end + end end end it "accepts multiple symbols and strings as constant names" do @module.deprecate_constant "PUBLIC1", :PUBLIC2 - -> { @module::PUBLIC1 }.should complain(@pattern) - -> { @module::PUBLIC2 }.should complain(@pattern) + -> { @module::PUBLIC1 }.should complain(/warning: constant .+::PUBLIC1 is deprecated/) + -> { @module::PUBLIC2 }.should complain(/warning: constant .+::PUBLIC2 is deprecated/) end it "returns self" do diff --git a/ruby/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb b/ruby/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb new file mode 100644 index 000000000..5aa859506 --- /dev/null +++ b/ruby/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb @@ -0,0 +1,5 @@ +module ModuleSpecs::Autoload + autoload(:AutoloadCurrentFile, __FILE__) + + ScratchPad.record autoload?(:AutoloadCurrentFile) +end diff --git a/ruby/spec/ruby/core/module/fixtures/autoload_location.rb b/ruby/spec/ruby/core/module/fixtures/autoload_location.rb new file mode 100644 index 000000000..318851b2d --- /dev/null +++ b/ruby/spec/ruby/core/module/fixtures/autoload_location.rb @@ -0,0 +1,3 @@ +module ConstantSpecs + CONST_LOCATION = __LINE__ +end diff --git a/ruby/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb b/ruby/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb new file mode 100644 index 000000000..25e08c112 --- /dev/null +++ b/ruby/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb @@ -0,0 +1,2 @@ +block = ScratchPad.recorded +ScratchPad.record(block.call) diff --git a/ruby/spec/ruby/core/module/fixtures/refine.rb b/ruby/spec/ruby/core/module/fixtures/refine.rb index 46975361d..e8215aa64 100644 --- a/ruby/spec/ruby/core/module/fixtures/refine.rb +++ b/ruby/spec/ruby/core/module/fixtures/refine.rb @@ -3,6 +3,10 @@ class ClassWithFoo def foo; "foo" end end + class ClassWithSuperFoo + def foo; [:C] end + end + module PrependedModule def foo; "foo from prepended module"; end end @@ -10,4 +14,12 @@ def foo; "foo from prepended module"; end module IncludedModule def foo; "foo from included module"; end end + + def self.build_refined_class(for_super: false) + if for_super + Class.new(ClassWithSuperFoo) + else + Class.new(ClassWithFoo) + end + end end diff --git a/ruby/spec/ruby/core/module/include_spec.rb b/ruby/spec/ruby/core/module/include_spec.rb index e7f99a598..128b9af2b 100644 --- a/ruby/spec/ruby/core/module/include_spec.rb +++ b/ruby/spec/ruby/core/module/include_spec.rb @@ -234,6 +234,304 @@ class C remove_const :C end end + + it "updates the method when an included module is updated" do + a_class = Class.new do + def foo + 'a' + end + end + + m_module = Module.new + + b_class = Class.new(a_class) do + include m_module + end + + b = b_class.new + + foo = -> { b.foo } + + foo.call.should == 'a' + + m_module.module_eval do + def foo + 'm' + end + end + + foo.call.should == 'm' + end + + + it "updates the method when a module included after a call is later updated" do + m_module = Module.new + a_class = Class.new do + def foo + 'a' + end + end + b_class = Class.new(a_class) + b = b_class.new + foo = -> { b.foo } + foo.call.should == 'a' + + b_class.include m_module + foo.call.should == 'a' + + m_module.module_eval do + def foo + "m" + end + end + foo.call.should == 'm' + end + + it "updates the method when a nested included module is updated" do + a_class = Class.new do + def foo + 'a' + end + end + + n_module = Module.new + + m_module = Module.new do + include n_module + end + + b_class = Class.new(a_class) do + include m_module + end + + b = b_class.new + + foo = -> { b.foo } + + foo.call.should == 'a' + + n_module.module_eval do + def foo + 'n' + end + end + + foo.call.should == 'n' + end + + it "updates the method when a new module is included" do + a_class = Class.new do + def foo + 'a' + end + end + + m_module = Module.new do + def foo + 'm' + end + end + + b_class = Class.new(a_class) + b = b_class.new + + foo = -> { b.foo } + + foo.call.should == 'a' + + b_class.class_eval do + include m_module + end + + foo.call.should == 'm' + end + + it "updates the method when a new module with nested module is included" do + a_class = Class.new do + def foo + 'a' + end + end + + n_module = Module.new do + def foo + 'n' + end + end + + m_module = Module.new do + include n_module + end + + b_class = Class.new(a_class) + b = b_class.new + + foo = -> { b.foo } + + foo.call.should == 'a' + + b_class.class_eval do + include m_module + end + + foo.call.should == 'n' + end + + it "updates the constant when an included module is updated" do + module ModuleSpecs::ConstUpdated + module A + FOO = 'a' + end + + module M + end + + module B + include A + include M + def self.foo + FOO + end + end + + B.foo.should == 'a' + + M.const_set(:FOO, 'm') + B.foo.should == 'm' + end + end + + it "updates the constant when a module included after a call is later updated" do + module ModuleSpecs::ConstLaterUpdated + module A + FOO = 'a' + end + + module B + include A + def self.foo + FOO + end + end + + B.foo.should == 'a' + + module M + end + B.include M + + B.foo.should == 'a' + + M.const_set(:FOO, 'm') + B.foo.should == 'm' + end + end + + it "updates the constant when a module included in another module after a call is later updated" do + module ModuleSpecs::ConstModuleLaterUpdated + module A + FOO = 'a' + end + + module B + include A + def self.foo + FOO + end + end + + B.foo.should == 'a' + + module M + end + B.include M + + B.foo.should == 'a' + + M.const_set(:FOO, 'm') + B.foo.should == 'm' + end + end + + it "updates the constant when a nested included module is updated" do + module ModuleSpecs::ConstUpdatedNestedIncludeUpdated + module A + FOO = 'a' + end + + module N + end + + module M + include N + end + + module B + include A + include M + def self.foo + FOO + end + end + + B.foo.should == 'a' + + N.const_set(:FOO, 'n') + B.foo.should == 'n' + end + end + + it "updates the constant when a new module is included" do + module ModuleSpecs::ConstUpdatedNewInclude + module A + FOO = 'a' + end + + module M + FOO = 'm' + end + + module B + include A + def self.foo + FOO + end + end + + B.foo.should == 'a' + + B.include(M) + B.foo.should == 'm' + end + end + + it "updates the constant when a new module with nested module is included" do + module ModuleSpecs::ConstUpdatedNestedIncluded + module A + FOO = 'a' + end + + module N + FOO = 'n' + end + + module M + include N + end + + module B + include A + def self.foo + FOO + end + end + + B.foo.should == 'a' + + B.include M + B.foo.should == 'n' + end + end end describe "Module#include?" do diff --git a/ruby/spec/ruby/core/module/included_spec.rb b/ruby/spec/ruby/core/module/included_spec.rb index f8dbad1d3..2fdd4325f 100644 --- a/ruby/spec/ruby/core/module/included_spec.rb +++ b/ruby/spec/ruby/core/module/included_spec.rb @@ -39,6 +39,6 @@ def test it "works with super using a singleton class" do ModuleSpecs::SingletonOnModuleCase::Bar.include ModuleSpecs::SingletonOnModuleCase::Foo - ModuleSpecs::SingletonOnModuleCase::Bar.included_called?.should == true + ModuleSpecs::SingletonOnModuleCase::Bar.should.included_called? end end diff --git a/ruby/spec/ruby/core/module/method_added_spec.rb b/ruby/spec/ruby/core/module/method_added_spec.rb index e1b1eda43..b983c8da7 100644 --- a/ruby/spec/ruby/core/module/method_added_spec.rb +++ b/ruby/spec/ruby/core/module/method_added_spec.rb @@ -59,4 +59,25 @@ def self.method_added(name) end m.should_not have_method(:method_to_undef) end + + it "is called with a precise caller location with the line of the 'def'" do + ScratchPad.record [] + line = nil + + Module.new do + def self.method_added(name) + location = caller_locations(1, 1)[0] + ScratchPad << location.lineno + end + + line = __LINE__ + def first + end + + def second + end + end + + ScratchPad.recorded.should == [line + 1, line + 4] + end end diff --git a/ruby/spec/ruby/core/module/method_defined_spec.rb b/ruby/spec/ruby/core/module/method_defined_spec.rb index c2a8702d9..bc5b420e1 100644 --- a/ruby/spec/ruby/core/module/method_defined_spec.rb +++ b/ruby/spec/ruby/core/module/method_defined_spec.rb @@ -30,7 +30,7 @@ m.method_defined?(:module_specs_public_method_on_kernel).should be_false end - it "raises a TypeError when the given object is not a string/symbol/fixnum" do + it "raises a TypeError when the given object is not a string/symbol" do c = Class.new o = mock('123') @@ -47,54 +47,52 @@ c.method_defined?(o).should == true end - ruby_version_is "2.6" do - # works as method_defined?(method_name) - describe "when passed true as a second optional argument" do - it "performs a lookup in ancestors" do - ModuleSpecs::Child.method_defined?(:public_child, true).should == true - ModuleSpecs::Child.method_defined?(:protected_child, true).should == true - ModuleSpecs::Child.method_defined?(:accessor_method, true).should == true - ModuleSpecs::Child.method_defined?(:private_child, true).should == false - - # Defined in Parent - ModuleSpecs::Child.method_defined?(:public_parent, true).should == true - ModuleSpecs::Child.method_defined?(:protected_parent, true).should == true - ModuleSpecs::Child.method_defined?(:private_parent, true).should == false - - # Defined in Module - ModuleSpecs::Child.method_defined?(:public_module, true).should == true - ModuleSpecs::Child.method_defined?(:protected_module, true).should == true - ModuleSpecs::Child.method_defined?(:private_module, true).should == false - - # Defined in SuperModule - ModuleSpecs::Child.method_defined?(:public_super_module, true).should == true - ModuleSpecs::Child.method_defined?(:protected_super_module, true).should == true - ModuleSpecs::Child.method_defined?(:private_super_module, true).should == false - end + # works as method_defined?(method_name) + describe "when passed true as a second optional argument" do + it "performs a lookup in ancestors" do + ModuleSpecs::Child.method_defined?(:public_child, true).should == true + ModuleSpecs::Child.method_defined?(:protected_child, true).should == true + ModuleSpecs::Child.method_defined?(:accessor_method, true).should == true + ModuleSpecs::Child.method_defined?(:private_child, true).should == false + + # Defined in Parent + ModuleSpecs::Child.method_defined?(:public_parent, true).should == true + ModuleSpecs::Child.method_defined?(:protected_parent, true).should == true + ModuleSpecs::Child.method_defined?(:private_parent, true).should == false + + # Defined in Module + ModuleSpecs::Child.method_defined?(:public_module, true).should == true + ModuleSpecs::Child.method_defined?(:protected_module, true).should == true + ModuleSpecs::Child.method_defined?(:private_module, true).should == false + + # Defined in SuperModule + ModuleSpecs::Child.method_defined?(:public_super_module, true).should == true + ModuleSpecs::Child.method_defined?(:protected_super_module, true).should == true + ModuleSpecs::Child.method_defined?(:private_super_module, true).should == false end + end - describe "when passed false as a second optional argument" do - it "checks only the class itself" do - ModuleSpecs::Child.method_defined?(:public_child, false).should == true - ModuleSpecs::Child.method_defined?(:protected_child, false).should == true - ModuleSpecs::Child.method_defined?(:accessor_method, false).should == true - ModuleSpecs::Child.method_defined?(:private_child, false).should == false - - # Defined in Parent - ModuleSpecs::Child.method_defined?(:public_parent, false).should == false - ModuleSpecs::Child.method_defined?(:protected_parent, false).should == false - ModuleSpecs::Child.method_defined?(:private_parent, false).should == false - - # Defined in Module - ModuleSpecs::Child.method_defined?(:public_module, false).should == false - ModuleSpecs::Child.method_defined?(:protected_module, false).should == false - ModuleSpecs::Child.method_defined?(:private_module, false).should == false - - # Defined in SuperModule - ModuleSpecs::Child.method_defined?(:public_super_module, false).should == false - ModuleSpecs::Child.method_defined?(:protected_super_module, false).should == false - ModuleSpecs::Child.method_defined?(:private_super_module, false).should == false - end + describe "when passed false as a second optional argument" do + it "checks only the class itself" do + ModuleSpecs::Child.method_defined?(:public_child, false).should == true + ModuleSpecs::Child.method_defined?(:protected_child, false).should == true + ModuleSpecs::Child.method_defined?(:accessor_method, false).should == true + ModuleSpecs::Child.method_defined?(:private_child, false).should == false + + # Defined in Parent + ModuleSpecs::Child.method_defined?(:public_parent, false).should == false + ModuleSpecs::Child.method_defined?(:protected_parent, false).should == false + ModuleSpecs::Child.method_defined?(:private_parent, false).should == false + + # Defined in Module + ModuleSpecs::Child.method_defined?(:public_module, false).should == false + ModuleSpecs::Child.method_defined?(:protected_module, false).should == false + ModuleSpecs::Child.method_defined?(:private_module, false).should == false + + # Defined in SuperModule + ModuleSpecs::Child.method_defined?(:public_super_module, false).should == false + ModuleSpecs::Child.method_defined?(:protected_super_module, false).should == false + ModuleSpecs::Child.method_defined?(:private_super_module, false).should == false end end end diff --git a/ruby/spec/ruby/core/module/module_function_spec.rb b/ruby/spec/ruby/core/module/module_function_spec.rb index 407237d48..0602e95ca 100644 --- a/ruby/spec/ruby/core/module/module_function_spec.rb +++ b/ruby/spec/ruby/core/module/module_function_spec.rb @@ -38,14 +38,23 @@ def test3() end m.respond_to?(:test3).should == false end - it "returns the current module" do - x = nil - m = Module.new do - def test() end - x = module_function :test + ruby_version_is ""..."3.1" do + it "returns self" do + Module.new do + def foo; end + module_function(:foo).should equal(self) + end end + end - x.should == m + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + Module.new do + def foo; end + module_function(:foo).should equal(:foo) + module_function(:foo, :foo).should == [:foo, :foo] + end + end end it "creates an independent copy of the method, not a redirect" do @@ -160,13 +169,20 @@ def test2() end m.respond_to?(:test2).should == true end - it "returns the current module" do - x = nil - m = Module.new { - x = module_function - } + ruby_version_is ""..."3.1" do + it "returns self" do + Module.new do + module_function.should equal(self) + end + end + end - x.should == m + ruby_version_is "3.1" do + it "returns nil" do + Module.new do + module_function.should equal(nil) + end + end end it "stops creating module functions if the body encounters another toggle " \ diff --git a/ruby/spec/ruby/core/module/name_spec.rb b/ruby/spec/ruby/core/module/name_spec.rb index 36a91f5be..ca9106a97 100644 --- a/ruby/spec/ruby/core/module/name_spec.rb +++ b/ruby/spec/ruby/core/module/name_spec.rb @@ -6,10 +6,20 @@ Module.new.name.should be_nil end - it "is nil when assigned to a constant in an anonymous module" do - m = Module.new - m::N = Module.new - m::N.name.should be_nil + ruby_version_is ""..."3.0" do + it "is nil when assigned to a constant in an anonymous module" do + m = Module.new + m::N = Module.new + m::N.name.should be_nil + end + end + + ruby_version_is "3.0" do + it "is not nil when assigned to a constant in an anonymous module" do + m = Module.new + m::N = Module.new + m::N.name.should.end_with? '::N' + end end it "is not nil for a nested module created with the module keyword" do @@ -18,6 +28,12 @@ module m::N; end m::N.name.should =~ /\A#::N\z/ end + it "returns nil for a singleton class" do + Module.new.singleton_class.name.should be_nil + String.singleton_class.name.should be_nil + Object.new.singleton_class.name.should be_nil + end + it "changes when the module is reachable through a constant path" do m = Module.new module m::N; end @@ -116,7 +132,7 @@ module ModuleSpecs::Anonymous ruby_version_is "2.7" do it "returns a frozen String" do - ModuleSpecs.name.frozen?.should == true + ModuleSpecs.name.should.frozen? end it "always returns the same String for a given Module" do diff --git a/ruby/spec/ruby/core/module/prepend_spec.rb b/ruby/spec/ruby/core/module/prepend_spec.rb index e143f5167..04cc27d47 100644 --- a/ruby/spec/ruby/core/module/prepend_spec.rb +++ b/ruby/spec/ruby/core/module/prepend_spec.rb @@ -36,6 +36,377 @@ def self.prepend_features(mod) ScratchPad.recorded.should == [ [ m3, c], [ m2, c ], [ m, c ] ] end + it "updates the method when a module is prepended" do + m_module = Module.new do + def foo + "m" + end + end + a_class = Class.new do + def foo + 'a' + end + end + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + a_class.class_eval do + prepend m_module + end + foo.call.should == 'm' + end + + it "updates the method when a prepended module is updated" do + m_module = Module.new + a_class = Class.new do + prepend m_module + def foo + 'a' + end + end + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + m_module.module_eval do + def foo + "m" + end + end + foo.call.should == 'm' + end + + it "updates the method when there is a base included method and the prepended module overrides it" do + base_module = Module.new do + def foo + 'a' + end + end + a_class = Class.new do + include base_module + end + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + + m_module = Module.new do + def foo + "m" + end + end + a_class.prepend m_module + foo.call.should == 'm' + end + + it "updates the method when there is a base included method and the prepended module is later updated" do + base_module = Module.new do + def foo + 'a' + end + end + a_class = Class.new do + include base_module + end + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + + m_module = Module.new + a_class.prepend m_module + foo.call.should == 'a' + + m_module.module_eval do + def foo + "m" + end + end + foo.call.should == 'm' + end + + it "updates the method when a module prepended after a call is later updated" do + m_module = Module.new + a_class = Class.new do + def foo + 'a' + end + end + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + + a_class.prepend m_module + foo.call.should == 'a' + + m_module.module_eval do + def foo + "m" + end + end + foo.call.should == 'm' + end + + it "updates the method when a module is prepended after another and the method is defined later on that module" do + m_module = Module.new do + def foo + 'a' + end + end + a_class = Class.new + a_class.prepend m_module + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + + n_module = Module.new + a_class.prepend n_module + foo.call.should == 'a' + + n_module.module_eval do + def foo + "n" + end + end + foo.call.should == 'n' + end + + it "updates the method when a module is included in a prepended module and the method is defined later" do + a_class = Class.new + base_module = Module.new do + def foo + 'a' + end + end + a_class.prepend base_module + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + + m_module = Module.new + n_module = Module.new + m_module.include n_module + a_class.prepend m_module + + n_module.module_eval do + def foo + "n" + end + end + foo.call.should == 'n' + end + + it "updates the method when a new module with an included module is prepended" do + a_class = Class.new do + def foo + 'a' + end + end + + n_module = Module.new do + def foo + 'n' + end + end + + m_module = Module.new do + include n_module + end + + a = a_class.new + foo = -> { a.foo } + + foo.call.should == 'a' + + a_class.class_eval do + prepend m_module + end + + foo.call.should == 'n' + end + + it "updates the constant when a module is prepended" do + module ModuleSpecs::ConstUpdatePrepended + module M + FOO = 'm' + end + module A + FOO = 'a' + end + module B + include A + def self.foo + FOO + end + end + + B.foo.should == 'a' + B.prepend M + B.foo.should == 'm' + end + end + + it "updates the constant when a prepended module is updated" do + module ModuleSpecs::ConstPrependedUpdated + module M + end + module A + FOO = 'a' + end + module B + include A + prepend M + def self.foo + FOO + end + end + B.foo.should == 'a' + M.const_set(:FOO, 'm') + B.foo.should == 'm' + end + end + + it "updates the constant when there is a base included constant and the prepended module overrides it" do + module ModuleSpecs::ConstIncludedPrependedOverride + module Base + FOO = 'a' + end + module A + include Base + def self.foo + FOO + end + end + A.foo.should == 'a' + + module M + FOO = 'm' + end + A.prepend M + A.foo.should == 'm' + end + end + + it "updates the constant when there is a base included constant and the prepended module is later updated" do + module ModuleSpecs::ConstIncludedPrependedLaterUpdated + module Base + FOO = 'a' + end + module A + include Base + def self.foo + FOO + end + end + A.foo.should == 'a' + + module M + end + A.prepend M + A.foo.should == 'a' + + M.const_set(:FOO, 'm') + A.foo.should == 'm' + end + end + + it "updates the constant when a module prepended after a constant is later updated" do + module ModuleSpecs::ConstUpdatedPrependedAfterLaterUpdated + module M + end + module A + FOO = 'a' + end + module B + include A + def self.foo + FOO + end + end + B.foo.should == 'a' + + B.prepend M + B.foo.should == 'a' + + M.const_set(:FOO, 'm') + B.foo.should == 'm' + end + end + + it "updates the constant when a module is prepended after another and the constant is defined later on that module" do + module ModuleSpecs::ConstUpdatedPrependedAfterConstDefined + module M + FOO = 'm' + end + module A + prepend M + def self.foo + FOO + end + end + + A.foo.should == 'm' + + module N + end + A.prepend N + A.foo.should == 'm' + + N.const_set(:FOO, 'n') + A.foo.should == 'n' + end + end + + it "updates the constant when a module is included in a prepended module and the constant is defined later" do + module ModuleSpecs::ConstUpdatedIncludedInPrependedConstDefinedLater + module A + def self.foo + FOO + end + end + module Base + FOO = 'a' + end + + A.prepend Base + A.foo.should == 'a' + + module N + end + module M + include N + end + + A.prepend M + + N.const_set(:FOO, 'n') + A.foo.should == 'n' + end + end + + it "updates the constant when a new module with an included module is prepended" do + module ModuleSpecs::ConstUpdatedNewModuleIncludedPrepended + module A + FOO = 'a' + end + module B + include A + def self.foo + FOO + end + end + module N + FOO = 'n' + end + + module M + include N + end + + B.foo.should == 'a' + + B.prepend M + B.foo.should == 'n' + end + end + it "raises a TypeError when the argument is not a Module" do -> { ModuleSpecs::Basic.prepend(Class.new) }.should raise_error(TypeError) end @@ -128,17 +499,34 @@ def self.prepend_features(mod) c.dup.new.should be_kind_of(m) end - it "keeps the module in the chain when dupping an intermediate module" do - m1 = Module.new { def calc(x) x end } - m2 = Module.new { prepend(m1) } - c1 = Class.new { prepend(m2) } - m2dup = m2.dup - m2dup.ancestors.should == [m2dup,m1,m2] - c2 = Class.new { prepend(m2dup) } - c1.ancestors[0,3].should == [m1,m2,c1] - c1.new.should be_kind_of(m1) - c2.ancestors[0,4].should == [m2dup,m1,m2,c2] - c2.new.should be_kind_of(m1) + ruby_version_is '0'...'3.0' do + it "keeps the module in the chain when dupping an intermediate module" do + m1 = Module.new { def calc(x) x end } + m2 = Module.new { prepend(m1) } + c1 = Class.new { prepend(m2) } + m2dup = m2.dup + m2dup.ancestors.should == [m2dup,m1,m2] + c2 = Class.new { prepend(m2dup) } + c1.ancestors[0,3].should == [m1,m2,c1] + c1.new.should be_kind_of(m1) + c2.ancestors[0,4].should == [m2dup,m1,m2,c2] + c2.new.should be_kind_of(m1) + end + end + + ruby_version_is '3.0' do + it "uses only new module when dupping the module" do + m1 = Module.new { def calc(x) x end } + m2 = Module.new { prepend(m1) } + c1 = Class.new { prepend(m2) } + m2dup = m2.dup + m2dup.ancestors.should == [m1,m2dup] + c2 = Class.new { prepend(m2dup) } + c1.ancestors[0,3].should == [m1,m2,c1] + c1.new.should be_kind_of(m1) + c2.ancestors[0,3].should == [m1,m2dup,c2] + c2.new.should be_kind_of(m1) + end end it "depends on prepend_features to add the module" do diff --git a/ruby/spec/ruby/core/module/private_class_method_spec.rb b/ruby/spec/ruby/core/module/private_class_method_spec.rb index e35b50d98..407779ccc 100644 --- a/ruby/spec/ruby/core/module/private_class_method_spec.rb +++ b/ruby/spec/ruby/core/module/private_class_method_spec.rb @@ -78,4 +78,16 @@ def foo() "foo" end end end.should raise_error(NameError) end + + ruby_version_is "3.0" do + context "when single argument is passed and is an array" do + it "sets the visibility of the given methods to private" do + c = Class.new do + def self.foo() "foo" end + private_class_method [:foo] + end + -> { c.foo }.should raise_error(NoMethodError) + end + end + end end diff --git a/ruby/spec/ruby/core/module/private_method_defined_spec.rb b/ruby/spec/ruby/core/module/private_method_defined_spec.rb index 515542d9d..01fc8f8fb 100644 --- a/ruby/spec/ruby/core/module/private_method_defined_spec.rb +++ b/ruby/spec/ruby/core/module/private_method_defined_spec.rb @@ -31,7 +31,7 @@ ModuleSpecs::CountsMixin.private_method_defined?(:private_3).should == true end - it "raises a TypeError if passed a Fixnum" do + it "raises a TypeError if passed an Integer" do -> do ModuleSpecs::CountsMixin.private_method_defined?(1) end.should raise_error(TypeError) @@ -70,53 +70,51 @@ def str.to_str() 'private_3' end ModuleSpecs::CountsMixin.private_method_defined?(str).should == true end - ruby_version_is "2.6" do - describe "when passed true as a second optional argument" do - it "performs a lookup in ancestors" do - ModuleSpecs::Child.private_method_defined?(:public_child, true).should == false - ModuleSpecs::Child.private_method_defined?(:protected_child, true).should == false - ModuleSpecs::Child.private_method_defined?(:accessor_method, true).should == false - ModuleSpecs::Child.private_method_defined?(:private_child, true).should == true - - # Defined in Parent - ModuleSpecs::Child.private_method_defined?(:public_parent, true).should == false - ModuleSpecs::Child.private_method_defined?(:protected_parent, true).should == false - ModuleSpecs::Child.private_method_defined?(:private_parent, true).should == true - - # Defined in Module - ModuleSpecs::Child.private_method_defined?(:public_module, true).should == false - ModuleSpecs::Child.private_method_defined?(:protected_module, true).should == false - ModuleSpecs::Child.private_method_defined?(:private_module, true).should == true - - # Defined in SuperModule - ModuleSpecs::Child.private_method_defined?(:public_super_module, true).should == false - ModuleSpecs::Child.private_method_defined?(:protected_super_module, true).should == false - ModuleSpecs::Child.private_method_defined?(:private_super_module, true).should == true - end + describe "when passed true as a second optional argument" do + it "performs a lookup in ancestors" do + ModuleSpecs::Child.private_method_defined?(:public_child, true).should == false + ModuleSpecs::Child.private_method_defined?(:protected_child, true).should == false + ModuleSpecs::Child.private_method_defined?(:accessor_method, true).should == false + ModuleSpecs::Child.private_method_defined?(:private_child, true).should == true + + # Defined in Parent + ModuleSpecs::Child.private_method_defined?(:public_parent, true).should == false + ModuleSpecs::Child.private_method_defined?(:protected_parent, true).should == false + ModuleSpecs::Child.private_method_defined?(:private_parent, true).should == true + + # Defined in Module + ModuleSpecs::Child.private_method_defined?(:public_module, true).should == false + ModuleSpecs::Child.private_method_defined?(:protected_module, true).should == false + ModuleSpecs::Child.private_method_defined?(:private_module, true).should == true + + # Defined in SuperModule + ModuleSpecs::Child.private_method_defined?(:public_super_module, true).should == false + ModuleSpecs::Child.private_method_defined?(:protected_super_module, true).should == false + ModuleSpecs::Child.private_method_defined?(:private_super_module, true).should == true end + end - describe "when passed false as a second optional argument" do - it "checks only the class itself" do - ModuleSpecs::Child.private_method_defined?(:public_child, false).should == false - ModuleSpecs::Child.private_method_defined?(:protected_child, false).should == false - ModuleSpecs::Child.private_method_defined?(:accessor_method, false).should == false - ModuleSpecs::Child.private_method_defined?(:private_child, false).should == true - - # Defined in Parent - ModuleSpecs::Child.private_method_defined?(:public_parent, false).should == false - ModuleSpecs::Child.private_method_defined?(:protected_parent, false).should == false - ModuleSpecs::Child.private_method_defined?(:private_parent, false).should == false - - # Defined in Module - ModuleSpecs::Child.private_method_defined?(:public_module, false).should == false - ModuleSpecs::Child.private_method_defined?(:protected_module, false).should == false - ModuleSpecs::Child.private_method_defined?(:private_module, false).should == false - - # Defined in SuperModule - ModuleSpecs::Child.private_method_defined?(:public_super_module, false).should == false - ModuleSpecs::Child.private_method_defined?(:protected_super_module, false).should == false - ModuleSpecs::Child.private_method_defined?(:private_super_module, false).should == false - end + describe "when passed false as a second optional argument" do + it "checks only the class itself" do + ModuleSpecs::Child.private_method_defined?(:public_child, false).should == false + ModuleSpecs::Child.private_method_defined?(:protected_child, false).should == false + ModuleSpecs::Child.private_method_defined?(:accessor_method, false).should == false + ModuleSpecs::Child.private_method_defined?(:private_child, false).should == true + + # Defined in Parent + ModuleSpecs::Child.private_method_defined?(:public_parent, false).should == false + ModuleSpecs::Child.private_method_defined?(:protected_parent, false).should == false + ModuleSpecs::Child.private_method_defined?(:private_parent, false).should == false + + # Defined in Module + ModuleSpecs::Child.private_method_defined?(:public_module, false).should == false + ModuleSpecs::Child.private_method_defined?(:protected_module, false).should == false + ModuleSpecs::Child.private_method_defined?(:private_module, false).should == false + + # Defined in SuperModule + ModuleSpecs::Child.private_method_defined?(:public_super_module, false).should == false + ModuleSpecs::Child.private_method_defined?(:protected_super_module, false).should == false + ModuleSpecs::Child.private_method_defined?(:private_super_module, false).should == false end end end diff --git a/ruby/spec/ruby/core/module/private_spec.rb b/ruby/spec/ruby/core/module/private_spec.rb index e893c24f3..ead806637 100644 --- a/ruby/spec/ruby/core/module/private_spec.rb +++ b/ruby/spec/ruby/core/module/private_spec.rb @@ -38,11 +38,25 @@ class << obj :module_specs_public_method_on_object_for_kernel_private) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - private(:foo).should equal(self) - private.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + private(:foo).should equal(self) + private.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + private(:foo).should equal(:foo) + private([:foo, :foo]).should == [:foo, :foo] + private(:foo, :foo).should == [:foo, :foo] + private.should equal(nil) + end end end diff --git a/ruby/spec/ruby/core/module/protected_method_defined_spec.rb b/ruby/spec/ruby/core/module/protected_method_defined_spec.rb index 7be7bdd3c..31e24a16c 100644 --- a/ruby/spec/ruby/core/module/protected_method_defined_spec.rb +++ b/ruby/spec/ruby/core/module/protected_method_defined_spec.rb @@ -31,7 +31,7 @@ ModuleSpecs::CountsMixin.protected_method_defined?(:protected_3).should == true end - it "raises a TypeError if passed a Fixnum" do + it "raises a TypeError if passed an Integer" do -> do ModuleSpecs::CountsMixin.protected_method_defined?(1) end.should raise_error(TypeError) @@ -70,53 +70,51 @@ def sym.to_sym() :protected_3 end ModuleSpecs::CountsMixin.protected_method_defined?(str).should == true end - ruby_version_is "2.6" do - describe "when passed true as a second optional argument" do - it "performs a lookup in ancestors" do - ModuleSpecs::Child.protected_method_defined?(:public_child, true).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_child, true).should == true - ModuleSpecs::Child.protected_method_defined?(:accessor_method, true).should == false - ModuleSpecs::Child.protected_method_defined?(:private_child, true).should == false - - # Defined in Parent - ModuleSpecs::Child.protected_method_defined?(:public_parent, true).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_parent, true).should == true - ModuleSpecs::Child.protected_method_defined?(:private_parent, true).should == false - - # Defined in Module - ModuleSpecs::Child.protected_method_defined?(:public_module, true).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_module, true).should == true - ModuleSpecs::Child.protected_method_defined?(:private_module, true).should == false - - # Defined in SuperModule - ModuleSpecs::Child.protected_method_defined?(:public_super_module, true).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_super_module, true).should == true - ModuleSpecs::Child.protected_method_defined?(:private_super_module, true).should == false - end + describe "when passed true as a second optional argument" do + it "performs a lookup in ancestors" do + ModuleSpecs::Child.protected_method_defined?(:public_child, true).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_child, true).should == true + ModuleSpecs::Child.protected_method_defined?(:accessor_method, true).should == false + ModuleSpecs::Child.protected_method_defined?(:private_child, true).should == false + + # Defined in Parent + ModuleSpecs::Child.protected_method_defined?(:public_parent, true).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_parent, true).should == true + ModuleSpecs::Child.protected_method_defined?(:private_parent, true).should == false + + # Defined in Module + ModuleSpecs::Child.protected_method_defined?(:public_module, true).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_module, true).should == true + ModuleSpecs::Child.protected_method_defined?(:private_module, true).should == false + + # Defined in SuperModule + ModuleSpecs::Child.protected_method_defined?(:public_super_module, true).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_super_module, true).should == true + ModuleSpecs::Child.protected_method_defined?(:private_super_module, true).should == false end + end - describe "when passed false as a second optional argument" do - it "checks only the class itself" do - ModuleSpecs::Child.protected_method_defined?(:public_child, false).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_child, false).should == true - ModuleSpecs::Child.protected_method_defined?(:accessor_method, false).should == false - ModuleSpecs::Child.protected_method_defined?(:private_child, false).should == false - - # Defined in Parent - ModuleSpecs::Child.protected_method_defined?(:public_parent, false).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_parent, false).should == false - ModuleSpecs::Child.protected_method_defined?(:private_parent, false).should == false - - # Defined in Module - ModuleSpecs::Child.protected_method_defined?(:public_module, false).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_module, false).should == false - ModuleSpecs::Child.protected_method_defined?(:private_module, false).should == false - - # Defined in SuperModule - ModuleSpecs::Child.protected_method_defined?(:public_super_module, false).should == false - ModuleSpecs::Child.protected_method_defined?(:protected_super_module, false).should == false - ModuleSpecs::Child.protected_method_defined?(:private_super_module, false).should == false - end + describe "when passed false as a second optional argument" do + it "checks only the class itself" do + ModuleSpecs::Child.protected_method_defined?(:public_child, false).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_child, false).should == true + ModuleSpecs::Child.protected_method_defined?(:accessor_method, false).should == false + ModuleSpecs::Child.protected_method_defined?(:private_child, false).should == false + + # Defined in Parent + ModuleSpecs::Child.protected_method_defined?(:public_parent, false).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_parent, false).should == false + ModuleSpecs::Child.protected_method_defined?(:private_parent, false).should == false + + # Defined in Module + ModuleSpecs::Child.protected_method_defined?(:public_module, false).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_module, false).should == false + ModuleSpecs::Child.protected_method_defined?(:private_module, false).should == false + + # Defined in SuperModule + ModuleSpecs::Child.protected_method_defined?(:public_super_module, false).should == false + ModuleSpecs::Child.protected_method_defined?(:protected_super_module, false).should == false + ModuleSpecs::Child.protected_method_defined?(:private_super_module, false).should == false end end end diff --git a/ruby/spec/ruby/core/module/protected_spec.rb b/ruby/spec/ruby/core/module/protected_spec.rb index aa04a42fb..058d49d75 100644 --- a/ruby/spec/ruby/core/module/protected_spec.rb +++ b/ruby/spec/ruby/core/module/protected_spec.rb @@ -39,11 +39,25 @@ class << ModuleSpecs::Parent :module_specs_public_method_on_object_for_kernel_protected) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - protected(:foo).should equal(self) - protected.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + protected(:foo).should equal(self) + protected.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + protected(:foo).should equal(:foo) + protected([:foo, :foo]).should == [:foo, :foo] + protected(:foo, :foo).should == [:foo, :foo] + protected.should equal(nil) + end end end diff --git a/ruby/spec/ruby/core/module/public_class_method_spec.rb b/ruby/spec/ruby/core/module/public_class_method_spec.rb index c09cc6486..b5d76e7b7 100644 --- a/ruby/spec/ruby/core/module/public_class_method_spec.rb +++ b/ruby/spec/ruby/core/module/public_class_method_spec.rb @@ -77,4 +77,20 @@ def foo() "foo" end end end.should raise_error(NameError) end + + ruby_version_is "3.0" do + context "when single argument is passed and is an array" do + it "makes a class method public" do + c = Class.new do + class << self + private + def foo() "foo" end + end + public_class_method [:foo] + end + + c.foo.should == "foo" + end + end + end end diff --git a/ruby/spec/ruby/core/module/public_method_defined_spec.rb b/ruby/spec/ruby/core/module/public_method_defined_spec.rb index d2fcfd1e7..5c9bdf1cc 100644 --- a/ruby/spec/ruby/core/module/public_method_defined_spec.rb +++ b/ruby/spec/ruby/core/module/public_method_defined_spec.rb @@ -31,7 +31,7 @@ ModuleSpecs::CountsMixin.public_method_defined?(:public_3).should == true end - it "raises a TypeError if passed a Fixnum" do + it "raises a TypeError if passed an Integer" do -> do ModuleSpecs::CountsMixin.public_method_defined?(1) end.should raise_error(TypeError) diff --git a/ruby/spec/ruby/core/module/public_spec.rb b/ruby/spec/ruby/core/module/public_spec.rb index e7059f6aa..e3b183f22 100644 --- a/ruby/spec/ruby/core/module/public_spec.rb +++ b/ruby/spec/ruby/core/module/public_spec.rb @@ -27,12 +27,25 @@ :module_specs_private_method_on_object_for_kernel_public) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - private :foo - public(:foo).should equal(self) - public.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + public(:foo).should equal(self) + public.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + public(:foo).should equal(:foo) + public([:foo, :foo]).should == [:foo, :foo] + public(:foo, :foo).should == [:foo, :foo] + public.should equal(nil) + end end end diff --git a/ruby/spec/ruby/core/module/refine_spec.rb b/ruby/spec/ruby/core/module/refine_spec.rb index 66c19ddb6..f6751a42d 100644 --- a/ruby/spec/ruby/core/module/refine_spec.rb +++ b/ruby/spec/ruby/core/module/refine_spec.rb @@ -87,6 +87,31 @@ def blah inner_self.public_instance_methods.should include(:blah) end + it "applies refinements to the module" do + refinement = Module.new do + refine(Enumerable) do + def foo? + self.any? ? "yes" : "no" + end + end + end + + foo = Class.new do + using refinement + + def initialize(items) + @items = items + end + + def result + @items.foo? + end + end + + foo.new([]).result.should == "no" + foo.new([1]).result.should == "yes" + end + it "raises ArgumentError if not given a block" do -> do Module.new do @@ -196,8 +221,10 @@ def to_json_format # * The included modules of C describe "method lookup" do it "looks in the object singleton class first" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -206,7 +233,7 @@ def foo; "foo from refinement"; end Module.new do using refinement - obj = ModuleSpecs::ClassWithFoo.new + obj = refined_class.new class << obj def foo; "foo from singleton class"; end end @@ -216,68 +243,133 @@ def foo; "foo from singleton class"; end result.should == "foo from singleton class" end - it "looks in prepended modules from the refinement first" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do - include ModuleSpecs::IncludedModule - prepend ModuleSpecs::PrependedModule + it "looks in the included modules for builtin methods" do + result = ruby_exe(<<-RUBY) + a = Module.new do + def /(other) quo(other) end + end - def foo; "foo from refinement"; end + refinement = Module.new do + refine Integer do + include a + end end - end - result = nil - Module.new do - using refinement - result = ModuleSpecs::ClassWithFoo.new.foo - end + result = nil + Module.new do + using refinement + result = 1 / 2 + end + + print result.class + RUBY - result.should == "foo from prepended module" + result.should == 'Rational' end - it "looks in refinement then" do - refinement = Module.new do - refine(ModuleSpecs::ClassWithFoo) do - include ModuleSpecs::IncludedModule + it "looks in later included modules of the refined module first" do + a = Module.new do + def foo + "foo from A" + end + end - def foo; "foo from refinement"; end + include_me_later = Module.new do + def foo + "foo from IncludeMeLater" end end + c = Class.new do + include a + end + + refinement = Module.new do + refine c do; end + end + result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + c.include include_me_later + result = c.new.foo end - result.should == "foo from refinement" + result.should == "foo from IncludeMeLater" end - it "looks in included modules from the refinement then" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do - include ModuleSpecs::IncludedModule + ruby_version_is ""..."3.1" do + it "looks in prepended modules from the refinement first" do + refined_class = ModuleSpecs.build_refined_class + + refinement = Module.new do + refine refined_class do + include ModuleSpecs::IncludedModule + prepend ModuleSpecs::PrependedModule + + def foo; "foo from refinement"; end + end + end + + result = nil + Module.new do + using refinement + result = refined_class.new.foo end + + result.should == "foo from prepended module" end - result = nil - Module.new do - using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + it "looks in refinement then" do + refined_class = ModuleSpecs.build_refined_class + + refinement = Module.new do + refine(refined_class) do + include ModuleSpecs::IncludedModule + + def foo; "foo from refinement"; end + end + end + + result = nil + Module.new do + using refinement + result = refined_class.new.foo + end + + result.should == "foo from refinement" end - result.should == "foo from included module" + it "looks in included modules from the refinement then" do + refined_class = ModuleSpecs.build_refined_class + + refinement = Module.new do + refine refined_class do + include ModuleSpecs::IncludedModule + end + end + + result = nil + Module.new do + using refinement + result = refined_class.new.foo + end + + result.should == "foo from included module" + end end it "looks in the class then" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine(ModuleSpecs::ClassWithFoo) { } + refine(refined_class) { } end result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo" @@ -287,12 +379,14 @@ def foo; "foo from refinement"; end # methods in a subclass have priority over refinements in a superclass it "does not override methods in subclasses" do - subclass = Class.new(ModuleSpecs::ClassWithFoo) do + refined_class = ModuleSpecs.build_refined_class + + subclass = Class.new(refined_class) do def foo; "foo from subclass"; end end refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -308,8 +402,10 @@ def foo; "foo from refinement"; end context "for methods accessed indirectly" do it "is honored by Kernel#send" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -317,15 +413,17 @@ def foo; "foo from refinement"; end result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.send :foo + result = refined_class.new.send :foo end result.should == "foo from refinement" end it "is honored by BasicObject#__send__" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -333,7 +431,7 @@ def foo; "foo from refinement"; end result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.__send__ :foo + result = refined_class.new.__send__ :foo end result.should == "foo from refinement" @@ -357,80 +455,40 @@ def to_s result.should == ["(1)", "(2)", "(3)"] end - ruby_version_is "" ... "2.6" do - it "is not honored by Kernel#public_send" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do - def foo; "foo from refinement"; end - end - end + it "is honored by Kernel#public_send" do + refined_class = ModuleSpecs.build_refined_class - result = nil - Module.new do - using refinement - result = ModuleSpecs::ClassWithFoo.new.public_send :foo + refinement = Module.new do + refine refined_class do + def foo; "foo from refinement"; end end - - result.should == "foo" end - end - ruby_version_is "2.6" do - it "is honored by Kernel#public_send" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do - def foo; "foo from refinement"; end - end - end - - result = nil - Module.new do - using refinement - result = ModuleSpecs::ClassWithFoo.new.public_send :foo - end - - result.should == "foo from refinement" + result = nil + Module.new do + using refinement + result = refined_class.new.public_send :foo end - end - - ruby_version_is "" ... "2.5" do - it "is not honored by string interpolation" do - refinement = Module.new do - refine Integer do - def to_s - "foo" - end - end - end - - result = nil - Module.new do - using refinement - result = "#{1}" - end - result.should == "1" - end + result.should == "foo from refinement" end - ruby_version_is "2.5" do - it "is honored by string interpolation" do - refinement = Module.new do - refine Integer do - def to_s - "foo" - end + it "is honored by string interpolation" do + refinement = Module.new do + refine Integer do + def to_s + "foo" end end + end - result = nil - Module.new do - using refinement - result = "#{1}" - end - - result.should == "foo" + result = nil + Module.new do + using refinement + result = "#{1}" end + + result.should == "foo" end it "is honored by Kernel#binding" do @@ -496,7 +554,7 @@ def foo; end end ruby_version_is "" ... "2.7" do - it "is not honored by Kernel#instance_method" do + it "is not honored by Kernel#public_method" do klass = Class.new refinement = Module.new do refine klass do @@ -507,14 +565,14 @@ def foo; end -> { Module.new do using refinement - klass.instance_method(:foo) + klass.new.public_method(:foo) end }.should raise_error(NameError, /undefined method `foo'/) end end ruby_version_is "2.7" do - it "is honored by Kernel#method" do + it "is honored by Kernel#public_method" do klass = Class.new refinement = Module.new do refine klass do @@ -525,15 +583,15 @@ def foo; end result = nil Module.new do using refinement - result = klass.instance_method(:foo).class + result = klass.new.public_method(:foo).class end - result.should == UnboundMethod + result.should == Method end end - ruby_version_is "" ... "2.6" do - it "is not honored by Kernel#respond_to?" do + ruby_version_is "" ... "2.7" do + it "is not honored by Kernel#instance_method" do klass = Class.new refinement = Module.new do refine klass do @@ -541,18 +599,17 @@ def foo; end end end - result = nil - Module.new do - using refinement - result = klass.new.respond_to?(:foo) - end - - result.should == false + -> { + Module.new do + using refinement + klass.instance_method(:foo) + end + }.should raise_error(NameError, /undefined method `foo'/) end end - ruby_version_is "2.6" do - it "is honored by Kernel#respond_to?" do + ruby_version_is "2.7" do + it "is honored by Kernel#instance_method" do klass = Class.new refinement = Module.new do refine klass do @@ -563,38 +620,60 @@ def foo; end result = nil Module.new do using refinement - result = klass.new.respond_to?(:foo) + result = klass.instance_method(:foo).class end - result.should == true + result.should == UnboundMethod end end - ruby_version_is ""..."2.6" do - it "is not honored by &" do - refinement = Module.new do - refine String do - def to_proc(*args) - -> * { 'foo' } - end - end + it "is honored by Kernel#respond_to?" do + klass = Class.new + refinement = Module.new do + refine klass do + def foo; end end + end - -> do - Module.new do - using refinement - ["hola"].map(&"upcase") + result = nil + Module.new do + using refinement + result = klass.new.respond_to?(:foo) + end + + result.should == true + end + + it "is honored by &" do + refinement = Module.new do + refine String do + def to_proc(*args) + -> * { 'foo' } end - end.should raise_error(TypeError, /wrong argument type String \(expected Proc\)/) + end end + + result = nil + Module.new do + using refinement + result = ["hola"].map(&"upcase") + end + + result.should == ['foo'] end + end + + context "when super is called in a refinement" do + ruby_version_is ""..."3.1" do + it "looks in the included to refinery module" do + refined_class = ModuleSpecs.build_refined_class - ruby_version_is "2.6" do - it "is honored by &" do refinement = Module.new do - refine String do - def to_proc(*args) - -> * { 'foo' } + refine refined_class do + include ModuleSpecs::IncludedModule + + def foo + super end end end @@ -602,20 +681,18 @@ def to_proc(*args) result = nil Module.new do using refinement - result = ["hola"].map(&"upcase") + result = refined_class.new.foo end - result.should == ['foo'] + result.should == "foo from included module" end end - end - context "when super is called in a refinement" do - it "looks in the included to refinery module" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do - include ModuleSpecs::IncludedModule + it "looks in the refined class" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do + refine refined_class do def foo super end @@ -625,46 +702,83 @@ def foo result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end - result.should == "foo from included module" + result.should == "foo" end - it "looks in the refined class" do - refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + ruby_version_is ""..."3.1" do + it "looks in the refined class from included module" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + + a = Module.new do def foo - super + [:A] + super end end - end - result = nil - Module.new do - using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + refinement = Module.new do + refine refined_class do + include a + end + end + + result = nil + Module.new do + using refinement + + result = refined_class.new.foo + end + + result.should == [:A, :C] end - result.should == "foo" + it "looks in the refined ancestors from included module" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + subclass = Class.new(refined_class) + + a = Module.new do + def foo + [:A] + super + end + end + + refinement = Module.new do + refine refined_class do + include a + end + end + + result = nil + Module.new do + using refinement + + result = subclass.new.foo + end + + result.should == [:A, :C] + end end # super in a method of a refinement invokes the method in the refined # class even if there is another refinement which has been activated # in the same context. - it "looks in the refined class even if there is another active refinement" do + it "looks in the refined class first if called from refined method" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo - "foo from refinement" + [:R1] end end end refinement_with_super = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo - super + [:R2] + super end end end @@ -673,10 +787,212 @@ def foo Module.new do using refinement using refinement_with_super - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end - result.should == "foo" + result.should == [:R2, :C] + end + + it "looks only in the refined class even if there is another active refinement" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + + refinement = Module.new do + refine refined_class do + def bar + "you cannot see me from super because I belong to another active R" + end + end + end + + refinement_with_super = Module.new do + refine refined_class do + def bar + super + end + end + end + + + Module.new do + using refinement + using refinement_with_super + -> { + refined_class.new.bar + }.should raise_error(NoMethodError) + end + end + + ruby_version_is ""..."3.1" do + it "does't have access to active refinements for C from included module" do + refined_class = ModuleSpecs.build_refined_class + + a = Module.new do + def foo + super + bar + end + end + + refinement = Module.new do + refine refined_class do + include a + + def bar + "bar is not seen from A methods" + end + end + end + + Module.new do + using refinement + -> { + refined_class.new.foo + }.should raise_error(NameError) { |e| e.name.should == :bar } + end + end + + it "does't have access to other active refinements from included module" do + refined_class = ModuleSpecs.build_refined_class + + refinement_integer = Module.new do + refine Integer do + def bar + "bar is not seen from A methods" + end + end + end + + a = Module.new do + def foo + super + 1.bar + end + end + + refinement = Module.new do + refine refined_class do + include a + end + end + + Module.new do + using refinement + using refinement_integer + -> { + refined_class.new.foo + }.should raise_error(NameError) { |e| e.name.should == :bar } + end + end + + # https://bugs.ruby-lang.org/issues/16977 + it "looks in the another active refinement if super called from included modules" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + + a = Module.new do + def foo + [:A] + super + end + end + + b = Module.new do + def foo + [:B] + super + end + end + + refinement_a = Module.new do + refine refined_class do + include a + end + end + + refinement_b = Module.new do + refine refined_class do + include b + end + end + + result = nil + Module.new do + using refinement_a + using refinement_b + result = refined_class.new.foo + end + + result.should == [:B, :A, :C] + end + + it "looks in the current active refinement from included modules" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + + a = Module.new do + def foo + [:A] + super + end + end + + b = Module.new do + def foo + [:B] + super + end + end + + refinement = Module.new do + refine refined_class do + def foo + [:LAST] + super + end + end + end + + refinement_a_b = Module.new do + refine refined_class do + include a + include b + end + end + + result = nil + Module.new do + using refinement + using refinement_a_b + result = refined_class.new.foo + end + + result.should == [:B, :A, :LAST, :C] + end + + it "looks in the lexical scope refinements before other active refinements" do + refined_class = ModuleSpecs.build_refined_class(for_super: true) + + refinement_local = Module.new do + refine refined_class do + def foo + [:LOCAL] + super + end + end + end + + a = Module.new do + using refinement_local + + def foo + [:A] + super + end + end + + refinement = Module.new do + refine refined_class do + include a + end + end + + result = nil + Module.new do + using refinement + result = refined_class.new.foo + end + + result.should == [:A, :LOCAL, :C] + end end end @@ -704,6 +1020,17 @@ def foo -> { [1,2].orig_count }.should raise_error(NoMethodError) end + it "and instance_methods returns a list of methods including those of the refined module" do + methods = Array.instance_methods + methods_2 = [] + Module.new do + refine Array do + methods_2 = instance_methods + end + end + methods.should == methods_2 + end + # Refinements are inherited by module inclusion. # That is, using activates all refinements in the ancestors of the specified module. # Refinements in a descendant have priority over refinements in an ancestor. diff --git a/ruby/spec/ruby/core/module/remove_const_spec.rb b/ruby/spec/ruby/core/module/remove_const_spec.rb index 20eb2dc3e..0ac23f05a 100644 --- a/ruby/spec/ruby/core/module/remove_const_spec.rb +++ b/ruby/spec/ruby/core/module/remove_const_spec.rb @@ -81,4 +81,25 @@ ConstantSpecs.autoload :AutoloadedConstant, 'a_file' ConstantSpecs.send(:remove_const, :AutoloadedConstant).should be_nil end + + it "updates the constant value" do + module ConstantSpecs::RemovedConstantUpdate + module M + FOO = 'm' + end + + module A + include M + FOO = 'a' + def self.foo + FOO + end + end + + A.foo.should == 'a' + + A.send(:remove_const,:FOO) + A.foo.should == 'm' + end + end end diff --git a/ruby/spec/ruby/core/module/remove_method_spec.rb b/ruby/spec/ruby/core/module/remove_method_spec.rb index ba08cc9b4..94b255df6 100644 --- a/ruby/spec/ruby/core/module/remove_method_spec.rb +++ b/ruby/spec/ruby/core/module/remove_method_spec.rb @@ -20,15 +20,8 @@ def method_to_remove; 2; end @module = Module.new { def method_to_remove; end } end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:remove_method, false) - end - end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:remove_method, false) - end + it "is a public method" do + Module.should have_public_instance_method(:remove_method, false) end it "removes the method from a class" do @@ -50,6 +43,28 @@ def method_to_remove; 2; end x.method_to_remove.should == 1 end + it "updates the method implementation" do + m_module = Module.new do + def foo + 'm' + end + end + + a_class = Class.new do + include m_module + + def foo + 'a' + end + end + + a = a_class.new + foo = -> { a.foo } + foo.call.should == 'a' + a_class.remove_method(:foo) + foo.call.should == 'm' + end + it "removes multiple methods with 1 call" do klass = Class.new do def method_to_remove_1; 1; end @@ -97,12 +112,12 @@ def method_to_remove_2; 2; end @frozen = @module.dup.freeze end - it "raises a #{frozen_error_class} when passed a name" do - -> { @frozen.send :remove_method, :method_to_remove }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a name" do + -> { @frozen.send :remove_method, :method_to_remove }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when passed a missing name" do - -> { @frozen.send :remove_method, :not_exist }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a missing name" do + -> { @frozen.send :remove_method, :not_exist }.should raise_error(FrozenError) end it "raises a TypeError when passed a not name" do diff --git a/ruby/spec/ruby/core/module/ruby2_keywords_spec.rb b/ruby/spec/ruby/core/module/ruby2_keywords_spec.rb new file mode 100644 index 000000000..34c45cb1b --- /dev/null +++ b/ruby/spec/ruby/core/module/ruby2_keywords_spec.rb @@ -0,0 +1,112 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "2.7" do + describe "Module#ruby2_keywords" do + it "marks the final hash argument as keyword hash" do + obj = Object.new + + obj.singleton_class.class_exec do + def foo(*a) a.last end + ruby2_keywords :foo + end + + last = obj.foo(1, 2, a: "a") + Hash.ruby2_keywords_hash?(last).should == true + end + + ruby_version_is "2.7" ... "3.0" do + it "fixes delegation warnings when calling a method accepting keywords" do + obj = Object.new + + obj.singleton_class.class_exec do + def foo(*a) bar(*a) end + def bar(*a, **b) end + end + + -> { obj.foo(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/) + + obj.singleton_class.class_exec do + ruby2_keywords :foo + end + + -> { obj.foo(1, 2, {a: "a"}) }.should_not complain + end + end + + it "returns nil" do + obj = Object.new + + obj.singleton_class.class_exec do + def foo(*a) end + + ruby2_keywords(:foo).should == nil + end + end + + it "raises NameError when passed not existing method name" do + obj = Object.new + + -> { + obj.singleton_class.class_exec do + ruby2_keywords :not_existing + end + }.should raise_error(NameError, /undefined method `not_existing'/) + end + + it "acceps String as well" do + obj = Object.new + + obj.singleton_class.class_exec do + def foo(*a) a.last end + ruby2_keywords "foo" + end + + last = obj.foo(1, 2, a: "a") + Hash.ruby2_keywords_hash?(last).should == true + end + + it "raises TypeError when passed not Symbol or String" do + obj = Object.new + + -> { + obj.singleton_class.class_exec do + ruby2_keywords Object.new + end + }.should raise_error(TypeError, /is not a symbol nor a string/) + end + + it "prints warning when a method does not accept argument splat" do + obj = Object.new + def obj.foo(a, b, c) end + + -> { + obj.singleton_class.class_exec do + ruby2_keywords :foo + end + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a method accepts keywords" do + obj = Object.new + def obj.foo(a:, b:) end + + -> { + obj.singleton_class.class_exec do + ruby2_keywords :foo + end + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a method accepts keyword splat" do + obj = Object.new + def obj.foo(**a) end + + -> { + obj.singleton_class.class_exec do + ruby2_keywords :foo + end + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + end +end diff --git a/ruby/spec/ruby/core/module/shared/class_eval.rb b/ruby/spec/ruby/core/module/shared/class_eval.rb index 08f8ff759..224078ae5 100644 --- a/ruby/spec/ruby/core/module/shared/class_eval.rb +++ b/ruby/spec/ruby/core/module/shared/class_eval.rb @@ -112,4 +112,48 @@ def foo a.attribute.should == "A" b.attribute.should == "B" end + + it "activates refinements from the eval scope" do + refinery = Module.new do + refine ModuleSpecs::NamedClass do + def foo + "bar" + end + end + end + + mid = @method + result = nil + + Class.new do + using refinery + + result = send(mid, "ModuleSpecs::NamedClass.new.foo") + end + + result.should == "bar" + end + + it "activates refinements from the eval scope with block" do + refinery = Module.new do + refine ModuleSpecs::NamedClass do + def foo + "bar" + end + end + end + + mid = @method + result = nil + + Class.new do + using refinery + + result = send(mid) do + ModuleSpecs::NamedClass.new.foo + end + end + + result.should == "bar" + end end diff --git a/ruby/spec/ruby/core/module/shared/set_visibility.rb b/ruby/spec/ruby/core/module/shared/set_visibility.rb index a04b1a54a..9f31e230c 100644 --- a/ruby/spec/ruby/core/module/shared/set_visibility.rb +++ b/ruby/spec/ruby/core/module/shared/set_visibility.rb @@ -6,6 +6,40 @@ end describe "with argument" do + describe "one or more arguments" do + it "sets visibility of given method names" do + visibility = @method + old_visibility = [:protected, :private].find {|vis| vis != visibility } + + mod = Module.new { + send old_visibility + def test1() end + def test2() end + send visibility, :test1, :test2 + } + mod.should send(:"have_#{visibility}_instance_method", :test1, false) + mod.should send(:"have_#{visibility}_instance_method", :test2, false) + end + end + + ruby_version_is "3.0" do + describe "array as a single argument" do + it "sets visibility of given method names" do + visibility = @method + old_visibility = [:protected, :private].find {|vis| vis != visibility } + + mod = Module.new { + send old_visibility + def test1() end + def test2() end + send visibility, [:test1, :test2] + } + mod.should send(:"have_#{visibility}_instance_method", :test1, false) + mod.should send(:"have_#{visibility}_instance_method", :test2, false) + end + end + end + it "does not clone method from the ancestor when setting to the same visibility in a child" do visibility = @method parent = Module.new { diff --git a/ruby/spec/ruby/core/module/singleton_class_spec.rb b/ruby/spec/ruby/core/module/singleton_class_spec.rb index b9f78eeb2..052755b73 100644 --- a/ruby/spec/ruby/core/module/singleton_class_spec.rb +++ b/ruby/spec/ruby/core/module/singleton_class_spec.rb @@ -3,25 +3,25 @@ describe "Module#singleton_class?" do it "returns true for singleton classes" do xs = self.singleton_class - xs.singleton_class?.should == true + xs.should.singleton_class? end it "returns false for other classes" do c = Class.new - c.singleton_class?.should == false + c.should_not.singleton_class? end describe "with singleton values" do it "returns false for nil's singleton class" do - NilClass.singleton_class?.should == false + NilClass.should_not.singleton_class? end it "returns false for true's singleton class" do - TrueClass.singleton_class?.should == false + TrueClass.should_not.singleton_class? end it "returns false for false's singleton class" do - FalseClass.singleton_class?.should == false + FalseClass.should_not.singleton_class? end end end diff --git a/ruby/spec/ruby/core/module/to_s_spec.rb b/ruby/spec/ruby/core/module/to_s_spec.rb index 29f6ecf72..6b1a615ef 100644 --- a/ruby/spec/ruby/core/module/to_s_spec.rb +++ b/ruby/spec/ruby/core/module/to_s_spec.rb @@ -42,4 +42,27 @@ obj = ModuleSpecs::NamedClass.new obj.singleton_class.to_s.should =~ /\A#>\z/ end + + it "always show the refinement name, even if the module is named" do + module ModuleSpecs::RefinementInspect + R = refine String do + end + end + + ModuleSpecs::RefinementInspect::R.name.should == 'ModuleSpecs::RefinementInspect::R' + ModuleSpecs::RefinementInspect::R.to_s.should == '#' + end + + it 'does not call #inspect or #to_s for singleton classes' do + klass = Class.new + obj = klass.new + def obj.to_s + "to_s" + end + def obj.inspect + "inspect" + end + sclass = obj.singleton_class + sclass.to_s.should =~ /\A#>\z/ + end end diff --git a/ruby/spec/ruby/core/module/undef_method_spec.rb b/ruby/spec/ruby/core/module/undef_method_spec.rb index b10177896..c2ad20053 100644 --- a/ruby/spec/ruby/core/module/undef_method_spec.rb +++ b/ruby/spec/ruby/core/module/undef_method_spec.rb @@ -18,15 +18,8 @@ def another_method_to_undef() 1 end @module = Module.new { def method_to_undef; end } end - ruby_version_is ''...'2.5' do - it "is a private method" do - Module.should have_private_instance_method(:undef_method, false) - end - end - ruby_version_is '2.5' do - it "is a public method" do - Module.should have_public_instance_method(:undef_method, false) - end + it "is a public method" do + Module.should have_public_instance_method(:undef_method, false) end it "requires multiple arguments" do @@ -97,12 +90,12 @@ def another_method_to_undef() 1 end @frozen = @module.dup.freeze end - it "raises a #{frozen_error_class} when passed a name" do - -> { @frozen.send :undef_method, :method_to_undef }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a name" do + -> { @frozen.send :undef_method, :method_to_undef }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when passed a missing name" do - -> { @frozen.send :undef_method, :not_exist }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a missing name" do + -> { @frozen.send :undef_method, :not_exist }.should raise_error(FrozenError) end it "raises a TypeError when passed a not name" do diff --git a/ruby/spec/ruby/core/module/using_spec.rb b/ruby/spec/ruby/core/module/using_spec.rb index 533d87d08..4781b99bb 100644 --- a/ruby/spec/ruby/core/module/using_spec.rb +++ b/ruby/spec/ruby/core/module/using_spec.rb @@ -243,6 +243,96 @@ def self.call_foo(c) mod.call_foo(c).should == "foo from refinement" end + it "is active for module defined via Module.new {}" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + result = nil + + Module.new do + using refinement + + Module.new do + result = 1.foo + end + end + + result.should == "foo from refinement" + end + + it "is active for class defined via Class.new {}" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + result = nil + + Module.new do + using refinement + + Class.new do + result = 1.foo + end + end + + result.should == "foo from refinement" + end + + it "is active for block called via instance_exec" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + c = Class.new do + using refinement + + def abc + block = -> { + 1.foo + } + + self.instance_exec(&block) + end + end + + c.new.abc.should == "foo from refinement" + end + + it "is active for block called via instance_eval" do + refinement = Module.new do + refine String do + def foo; "foo from refinement"; end + end + end + + c = Class.new do + using refinement + + def initialize + @a = "1703" + + @a.instance_eval do + def abc + "#{self}: #{self.foo}" + end + end + end + + def abc + @a.abc + end + end + + c.new.abc.should == "1703: foo from refinement" + end + it "is not active if `using` call is not evaluated" do result = nil diff --git a/ruby/spec/ruby/core/mutex/owned_spec.rb b/ruby/spec/ruby/core/mutex/owned_spec.rb index e66062534..1f843cd57 100644 --- a/ruby/spec/ruby/core/mutex/owned_spec.rb +++ b/ruby/spec/ruby/core/mutex/owned_spec.rb @@ -40,4 +40,16 @@ m.owned?.should be_false end end + + ruby_version_is "3.0" do + it "is held per Fiber" do + m = Mutex.new + m.lock + + Fiber.new do + m.locked?.should == true + m.owned?.should == false + end.resume + end + end end diff --git a/ruby/spec/ruby/core/mutex/sleep_spec.rb b/ruby/spec/ruby/core/mutex/sleep_spec.rb index f5e0d5303..9832e3125 100644 --- a/ruby/spec/ruby/core/mutex/sleep_spec.rb +++ b/ruby/spec/ruby/core/mutex/sleep_spec.rb @@ -37,7 +37,7 @@ locked = false th = Thread.new { m.lock; locked = true; m.sleep } Thread.pass until locked - Thread.pass while th.status and th.status != "sleep" + Thread.pass until th.stop? m.locked?.should be_false th.run th.join @@ -63,15 +63,23 @@ end end Thread.pass until locked - Thread.pass while th.status and th.status != "sleep" + Thread.pass until th.stop? th.raise(Exception) th.value.should be_true end it "returns the rounded number of seconds asleep" do m = Mutex.new - m.lock - m.sleep(0.001).should be_kind_of(Integer) + locked = false + th = Thread.start do + m.lock + locked = true + m.sleep + end + Thread.pass until locked + Thread.pass until th.stop? + th.wakeup + th.value.should be_kind_of(Integer) end it "wakes up when requesting sleep times near or equal to zero" do @@ -89,7 +97,7 @@ m.lock times.each do |time| # just testing that sleep completes - m.sleep(time).should_not == nil + -> {m.sleep(time)}.should_not raise_error end end end diff --git a/ruby/spec/ruby/core/mutex/unlock_spec.rb b/ruby/spec/ruby/core/mutex/unlock_spec.rb index c9c3bfe14..d999e6684 100644 --- a/ruby/spec/ruby/core/mutex/unlock_spec.rb +++ b/ruby/spec/ruby/core/mutex/unlock_spec.rb @@ -17,7 +17,7 @@ # avoid race on mutex.lock Thread.pass until mutex.locked? - Thread.pass while th.status and th.status != "sleep" + Thread.pass until th.stop? -> { mutex.unlock }.should raise_error(ThreadError) diff --git a/ruby/spec/ruby/core/nil/case_compare_spec.rb b/ruby/spec/ruby/core/nil/case_compare_spec.rb new file mode 100644 index 000000000..142560c6f --- /dev/null +++ b/ruby/spec/ruby/core/nil/case_compare_spec.rb @@ -0,0 +1,13 @@ +require_relative '../../spec_helper' + +describe "NilClass#===" do + it "returns true for nil" do + (nil === nil).should == true + end + + it "returns false for non-nil object" do + (nil === 1).should == false + (nil === "").should == false + (nil === Object).should == false + end +end diff --git a/ruby/spec/ruby/core/nil/match_spec.rb b/ruby/spec/ruby/core/nil/match_spec.rb index 3f69312bf..2e2b5d1c1 100644 --- a/ruby/spec/ruby/core/nil/match_spec.rb +++ b/ruby/spec/ruby/core/nil/match_spec.rb @@ -1,19 +1,21 @@ require_relative '../../spec_helper' -ruby_version_is "2.6" do - describe "NilClass#=~" do - it "returns nil matching any object" do - o = Object.new +describe "NilClass#=~" do + it "returns nil matching any object" do + o = Object.new - suppress_warning do - (o =~ /Object/).should be_nil - (o =~ 'Object').should be_nil - (o =~ Object).should be_nil - (o =~ Object.new).should be_nil - (o =~ nil).should be_nil - (o =~ false).should be_nil - (o =~ true).should be_nil - end + suppress_warning do + (o =~ /Object/).should be_nil + (o =~ 'Object').should be_nil + (o =~ Object).should be_nil + (o =~ Object.new).should be_nil + (o =~ nil).should be_nil + (o =~ false).should be_nil + (o =~ true).should be_nil end end + + it "should not warn" do + -> { nil =~ /a/ }.should_not complain(verbose: true) + end end diff --git a/ruby/spec/ruby/core/nil/nil_spec.rb b/ruby/spec/ruby/core/nil/nil_spec.rb index 47db0c5cf..2cf97621c 100644 --- a/ruby/spec/ruby/core/nil/nil_spec.rb +++ b/ruby/spec/ruby/core/nil/nil_spec.rb @@ -2,6 +2,6 @@ describe "NilClass#nil?" do it "returns true" do - nil.nil?.should == true + nil.should.nil? end end diff --git a/ruby/spec/ruby/core/nil/to_i_spec.rb b/ruby/spec/ruby/core/nil/to_i_spec.rb index 099792ef6..d3d088e99 100644 --- a/ruby/spec/ruby/core/nil/to_i_spec.rb +++ b/ruby/spec/ruby/core/nil/to_i_spec.rb @@ -5,7 +5,7 @@ nil.to_i.should == 0 end - it "does not cause NilClass to be coerced to Fixnum" do + it "does not cause NilClass to be coerced to Integer" do (0 == nil).should == false end end diff --git a/ruby/spec/ruby/core/nil/to_s_spec.rb b/ruby/spec/ruby/core/nil/to_s_spec.rb index 4b61f589f..283d26477 100644 --- a/ruby/spec/ruby/core/nil/to_s_spec.rb +++ b/ruby/spec/ruby/core/nil/to_s_spec.rb @@ -7,7 +7,7 @@ ruby_version_is "2.7" do it "returns a frozen string" do - nil.to_s.frozen?.should == true + nil.to_s.should.frozen? end it "always returns the same string" do diff --git a/ruby/spec/ruby/core/numeric/clone_spec.rb b/ruby/spec/ruby/core/numeric/clone_spec.rb new file mode 100644 index 000000000..c3b06ca0c --- /dev/null +++ b/ruby/spec/ruby/core/numeric/clone_spec.rb @@ -0,0 +1,32 @@ +require_relative '../../spec_helper' + +describe "Numeric#clone" do + it "returns self" do + value = 1 + value.clone.should equal(value) + + subclass = Class.new(Numeric) + value = subclass.new + value.clone.should equal(value) + end + + it "does not change frozen status" do + 1.clone.frozen?.should == true + end + + it "accepts optonal keyword argument :freeze" do + value = 1 + value.clone(freeze: true).should equal(value) + end + + it "raises ArgumentError if passed freeze: false" do + -> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/) + end + + ruby_version_is "3.0" do + it "does not change frozen status if passed freeze: nil" do + value = 1 + value.clone(freeze: nil).should equal(value) + end + end +end diff --git a/ruby/spec/ruby/core/numeric/dup_spec.rb b/ruby/spec/ruby/core/numeric/dup_spec.rb new file mode 100644 index 000000000..189a7ef44 --- /dev/null +++ b/ruby/spec/ruby/core/numeric/dup_spec.rb @@ -0,0 +1,16 @@ +require_relative '../../spec_helper' + +describe "Numeric#dup" do + it "returns self" do + value = 1 + value.dup.should equal(value) + + subclass = Class.new(Numeric) + value = subclass.new + value.dup.should equal(value) + end + + it "does not change frozen status" do + 1.dup.frozen?.should == true + end +end diff --git a/ruby/spec/ruby/core/numeric/integer_spec.rb b/ruby/spec/ruby/core/numeric/integer_spec.rb index 5d4bf0036..adbac4d7a 100644 --- a/ruby/spec/ruby/core/numeric/integer_spec.rb +++ b/ruby/spec/ruby/core/numeric/integer_spec.rb @@ -3,6 +3,6 @@ describe "Numeric#integer?" do it "returns false" do - NumericSpecs::Subclass.new.integer?.should == false + NumericSpecs::Subclass.new.should_not.integer? end end diff --git a/ruby/spec/ruby/core/numeric/negative_spec.rb b/ruby/spec/ruby/core/numeric/negative_spec.rb index da464a909..9c6f95fd8 100644 --- a/ruby/spec/ruby/core/numeric/negative_spec.rb +++ b/ruby/spec/ruby/core/numeric/negative_spec.rb @@ -31,11 +31,11 @@ it "returns true if self is less than 0" do @obj.should_receive(:<).with(0).and_return(true) - @obj.negative?.should == true + @obj.should.negative? end it "returns false if self is greater than 0" do @obj.should_receive(:<).with(0).and_return(false) - @obj.negative?.should == false + @obj.should_not.negative? end end diff --git a/ruby/spec/ruby/core/numeric/positive_spec.rb b/ruby/spec/ruby/core/numeric/positive_spec.rb index 8f98fbfa2..3b831b4d3 100644 --- a/ruby/spec/ruby/core/numeric/positive_spec.rb +++ b/ruby/spec/ruby/core/numeric/positive_spec.rb @@ -31,11 +31,11 @@ it "returns true if self is greater than 0" do @obj.should_receive(:>).with(0).and_return(true) - @obj.positive?.should == true + @obj.should.positive? end it "returns false if self is less than 0" do @obj.should_receive(:>).with(0).and_return(false) - @obj.positive?.should == false + @obj.should_not.positive? end end diff --git a/ruby/spec/ruby/core/numeric/quo_spec.rb b/ruby/spec/ruby/core/numeric/quo_spec.rb index 5c952b11a..b4a23fd47 100644 --- a/ruby/spec/ruby/core/numeric/quo_spec.rb +++ b/ruby/spec/ruby/core/numeric/quo_spec.rb @@ -52,4 +52,13 @@ obj.quo(19).should == 1.quo(20) end + + it "raises a ZeroDivisionError if the given argument is zero and not a Float" do + -> { 1.quo(0) }.should raise_error(ZeroDivisionError) + end + + it "returns infinity if the given argument is zero and is a Float" do + (1.quo(0.0)).to_s.should == 'Infinity' + (-1.quo(0.0)).to_s.should == '-Infinity' + end end diff --git a/ruby/spec/ruby/core/numeric/real_spec.rb b/ruby/spec/ruby/core/numeric/real_spec.rb index caa8dcec6..2d2499bcc 100644 --- a/ruby/spec/ruby/core/numeric/real_spec.rb +++ b/ruby/spec/ruby/core/numeric/real_spec.rb @@ -32,6 +32,6 @@ describe "Numeric#real?" do it "returns true" do - NumericSpecs::Subclass.new.real?.should == true + NumericSpecs::Subclass.new.should.real? end end diff --git a/ruby/spec/ruby/core/numeric/shared/step.rb b/ruby/spec/ruby/core/numeric/shared/step.rb index 364d4769a..a4fe74f9d 100644 --- a/ruby/spec/ruby/core/numeric/shared/step.rb +++ b/ruby/spec/ruby/core/numeric/shared/step.rb @@ -24,9 +24,9 @@ 1.0.step.first(5).should == [1.0, 2.0, 3.0, 4.0, 5.0] end - describe "when self, stop and step are Fixnums" do - it "yields only Fixnums" do - @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Fixnum) } + describe "when self, stop and step are Integers" do + it "yields only Integers" do + @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Integer) } end describe "with a positive step" do @@ -224,33 +224,25 @@ end describe "when step is a String" do - error = nil - ruby_version_is "2.4"..."2.5" do - error = TypeError - end - ruby_version_is "2.5" do - error = ArgumentError - end - - describe "with self and stop as Fixnums" do - it "raises an #{error} when step is a numeric representation" do - -> { @step.call(1, 5, "1") {} }.should raise_error(error) - -> { @step.call(1, 5, "0.1") {} }.should raise_error(error) - -> { @step.call(1, 5, "1/3") {} }.should raise_error(error) + describe "with self and stop as Integers" do + it "raises an ArgumentError when step is a numeric representation" do + -> { @step.call(1, 5, "1") {} }.should raise_error(ArgumentError) + -> { @step.call(1, 5, "0.1") {} }.should raise_error(ArgumentError) + -> { @step.call(1, 5, "1/3") {} }.should raise_error(ArgumentError) end - it "raises an #{error} with step as an alphanumeric string" do - -> { @step.call(1, 5, "foo") {} }.should raise_error(error) + it "raises an ArgumentError with step as an alphanumeric string" do + -> { @step.call(1, 5, "foo") {} }.should raise_error(ArgumentError) end end describe "with self and stop as Floats" do - it "raises an #{error} when step is a numeric representation" do - -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(error) - -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(error) - -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(error) + it "raises an ArgumentError when step is a numeric representation" do + -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(ArgumentError) + -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(ArgumentError) + -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(ArgumentError) end - it "raises an #{error} with step as an alphanumeric string" do - -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(error) + it "raises an ArgumentError with step as an alphanumeric string" do + -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(ArgumentError) end end end @@ -265,12 +257,12 @@ describe "when no block is given" do step_enum_class = Enumerator - ruby_version_is "2.6" do - step_enum_class = Enumerator::ArithmeticSequence - end + step_enum_class = Enumerator::ArithmeticSequence - it "returns an #{step_enum_class} when step is 0" do - @step.call(1, 2, 0).should be_an_instance_of(step_enum_class) + ruby_version_is ""..."3.0" do + it "returns an #{step_enum_class} when step is 0" do + @step.call(1, 2, 0).should be_an_instance_of(step_enum_class) + end end it "returns an #{step_enum_class} when not passed a block and self > stop" do @@ -286,7 +278,7 @@ end describe "when step is a String" do - describe "with self and stop as Fixnums" do + describe "with self and stop as Integers" do it "returns an Enumerator" do @step.call(1, 5, "foo").should be_an_instance_of(Enumerator) end @@ -302,38 +294,30 @@ describe "returned Enumerator" do describe "size" do describe "when step is a String" do - error = nil - ruby_version_is "2.4"..."2.5" do - error = TypeError - end - ruby_version_is "2.5" do - error = ArgumentError - end - - describe "with self and stop as Fixnums" do - it "raises an #{error} when step is a numeric representation" do - -> { @step.call(1, 5, "1").size }.should raise_error(error) - -> { @step.call(1, 5, "0.1").size }.should raise_error(error) - -> { @step.call(1, 5, "1/3").size }.should raise_error(error) + describe "with self and stop as Integers" do + it "raises an ArgumentError when step is a numeric representation" do + -> { @step.call(1, 5, "1").size }.should raise_error(ArgumentError) + -> { @step.call(1, 5, "0.1").size }.should raise_error(ArgumentError) + -> { @step.call(1, 5, "1/3").size }.should raise_error(ArgumentError) end - it "raises an #{error} with step as an alphanumeric string" do - -> { @step.call(1, 5, "foo").size }.should raise_error(error) + it "raises an ArgumentError with step as an alphanumeric string" do + -> { @step.call(1, 5, "foo").size }.should raise_error(ArgumentError) end end describe "with self and stop as Floats" do - it "raises an #{error} when step is a numeric representation" do - -> { @step.call(1.1, 5.1, "1").size }.should raise_error(error) - -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(error) - -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(error) + it "raises an ArgumentError when step is a numeric representation" do + -> { @step.call(1.1, 5.1, "1").size }.should raise_error(ArgumentError) + -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(ArgumentError) + -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(ArgumentError) end - it "raises an #{error} with step as an alphanumeric string" do - -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(error) + it "raises an ArgumentError with step as an alphanumeric string" do + -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(ArgumentError) end end end - describe "when self, stop and step are Fixnums and step is positive" do + describe "when self, stop and step are Integers and step is positive" do it "returns the difference between self and stop divided by the number of steps" do @step.call(5, 10, 11).size.should == 1 @step.call(5, 10, 6).size.should == 1 @@ -350,7 +334,7 @@ end end - describe "when self, stop and step are Fixnums and step is negative" do + describe "when self, stop and step are Integers and step is negative" do it "returns the difference between self and stop divided by the number of steps" do @step.call(10, 5, -11).size.should == 1 @step.call(10, 5, -6).size.should == 1 diff --git a/ruby/spec/ruby/core/numeric/step_spec.rb b/ruby/spec/ruby/core/numeric/step_spec.rb index e9067864c..03af8b0e4 100644 --- a/ruby/spec/ruby/core/numeric/step_spec.rb +++ b/ruby/spec/ruby/core/numeric/step_spec.rb @@ -22,33 +22,21 @@ describe "when no block is given" do step_enum_class = Enumerator - ruby_version_is "2.6" do - step_enum_class = Enumerator::ArithmeticSequence - end + step_enum_class = Enumerator::ArithmeticSequence - it "returns an #{step_enum_class} when step is 0" do - 1.step(5, 0).should be_an_instance_of(step_enum_class) - end + ruby_version_is ""..."3.0" do + it "returns an #{step_enum_class} when step is 0" do + 1.step(5, 0).should be_an_instance_of(step_enum_class) + end - it "returns an #{step_enum_class} when step is 0.0" do - 1.step(2, 0.0).should be_an_instance_of(step_enum_class) + it "returns an #{step_enum_class} when step is 0.0" do + 1.step(2, 0.0).should be_an_instance_of(step_enum_class) + end end describe "returned #{step_enum_class}" do describe "size" do - ruby_version_is ""..."2.6" do - it "raises an ArgumentError when step is 0" do - enum = 1.step(5, 0) - -> { enum.size }.should raise_error(ArgumentError) - end - - it "raises an ArgumentError when step is 0.0" do - enum = 1.step(2, 0.0) - -> { enum.size }.should raise_error(ArgumentError) - end - end - - ruby_version_is "2.6" do + ruby_version_is ""..."3.0" do it "is infinity when step is 0" do enum = 1.step(5, 0) enum.size.should == Float::INFINITY @@ -67,16 +55,8 @@ end describe "type" do - ruby_version_is ""..."2.6" do - it "returns an instance of Enumerator" do - 1.step(10).class.should == Enumerator - end - end - - ruby_version_is "2.6" do - it "returns an instance of Enumerator::ArithmeticSequence" do - 1.step(10).class.should == Enumerator::ArithmeticSequence - end + it "returns an instance of Enumerator::ArithmeticSequence" do + 1.step(10).class.should == Enumerator::ArithmeticSequence end end end @@ -85,18 +65,20 @@ end describe 'with keyword arguments' do - it "doesn't raise an error when step is 0" do - -> { 1.step(to: 5, by: 0) { break } }.should_not raise_error - end + ruby_version_is ""..."3.0" do + it "doesn't raise an error when step is 0" do + -> { 1.step(to: 5, by: 0) { break } }.should_not raise_error + end - it "doesn't raise an error when step is 0.0" do - -> { 1.step(to: 2, by: 0.0) { break } }.should_not raise_error - end + it "doesn't raise an error when step is 0.0" do + -> { 1.step(to: 2, by: 0.0) { break } }.should_not raise_error + end - it "should loop over self when step is 0 or 0.0" do - 1.step(to: 2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0] - 1.step(to: 2, by: 0).take(5).should eql [1, 1, 1, 1, 1] - 1.1.step(to: 2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1] + it "should loop over self when step is 0 or 0.0" do + 1.step(to: 2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0] + 1.step(to: 2, by: 0).take(5).should eql [1, 1, 1, 1, 1] + 1.1.step(to: 2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1] + end end describe "when no block is given" do @@ -106,12 +88,14 @@ 1.step(by: 42).size.should == infinity_value end - it "should return infinity_value when step is 0" do - 1.step(to: 5, by: 0).size.should == infinity_value - end + ruby_version_is ""..."3.0" do + it "should return infinity_value when step is 0" do + 1.step(to: 5, by: 0).size.should == infinity_value + end - it "should return infinity_value when step is 0.0" do - 1.step(to: 2, by: 0.0).size.should == infinity_value + it "should return infinity_value when step is 0.0" do + 1.step(to: 2, by: 0.0).size.should == infinity_value + end end it "should return infinity_value when ascending towards a limit of Float::INFINITY" do @@ -146,12 +130,24 @@ end describe 'with mixed arguments' do - it "doesn't raise an error when step is 0" do - -> { 1.step(5, by: 0) { break } }.should_not raise_error + ruby_version_is ""..."3.0" do + it "doesn't raise an error when step is 0" do + -> { 1.step(5, by: 0) { break } }.should_not raise_error + end + + it "doesn't raise an error when step is 0.0" do + -> { 1.step(2, by: 0.0) { break } }.should_not raise_error + end end - it "doesn't raise an error when step is 0.0" do - -> { 1.step(2, by: 0.0) { break } }.should_not raise_error + ruby_version_is "3.0" do + it " raises an ArgumentError when step is 0" do + -> { 1.step(5, by: 0) { break } }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when step is 0.0" do + -> { 1.step(2, by: 0.0) { break } }.should raise_error(ArgumentError) + end end it "raises a ArgumentError when limit and to are defined" do @@ -162,21 +158,25 @@ -> { 1.step(5, 1, by: 5) { break } }.should raise_error(ArgumentError) end - it "should loop over self when step is 0 or 0.0" do - 1.step(2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0] - 1.step(2, by: 0).take(5).should eql [1, 1, 1, 1, 1] - 1.1.step(2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1] + ruby_version_is ""..."3.0" do + it "should loop over self when step is 0 or 0.0" do + 1.step(2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0] + 1.step(2, by: 0).take(5).should eql [1, 1, 1, 1, 1] + 1.1.step(2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1] + end end describe "when no block is given" do describe "returned Enumerator" do describe "size" do - it "should return infinity_value when step is 0" do - 1.step(5, by: 0).size.should == infinity_value - end + ruby_version_is ""..."3.0" do + it "should return infinity_value when step is 0" do + 1.step(5, by: 0).size.should == infinity_value + end - it "should return infinity_value when step is 0.0" do - 1.step(2, by: 0.0).size.should == infinity_value + it "should return infinity_value when step is 0.0" do + 1.step(2, by: 0.0).size.should == infinity_value + end end end end diff --git a/ruby/spec/ruby/core/numeric/zero_spec.rb b/ruby/spec/ruby/core/numeric/zero_spec.rb index 9de71d1dc..0fb7619bc 100644 --- a/ruby/spec/ruby/core/numeric/zero_spec.rb +++ b/ruby/spec/ruby/core/numeric/zero_spec.rb @@ -8,11 +8,11 @@ it "returns true if self is 0" do @obj.should_receive(:==).with(0).and_return(true) - @obj.zero?.should == true + @obj.should.zero? end it "returns false if self is not 0" do @obj.should_receive(:==).with(0).and_return(false) - @obj.zero?.should == false + @obj.should_not.zero? end end diff --git a/ruby/spec/ruby/core/objectspace/_id2ref_spec.rb b/ruby/spec/ruby/core/objectspace/_id2ref_spec.rb index 1d8ad02de..c088ae274 100644 --- a/ruby/spec/ruby/core/objectspace/_id2ref_spec.rb +++ b/ruby/spec/ruby/core/objectspace/_id2ref_spec.rb @@ -7,16 +7,43 @@ r.should == s end - it "retrieves a Fixnum by object_id" do - f = 1 - r = ObjectSpace._id2ref(f.object_id) - r.should == f + it "retrieves true by object_id" do + ObjectSpace._id2ref(true.object_id).should == true + end + + it "retrieves false by object_id" do + ObjectSpace._id2ref(false.object_id).should == false + end + + it "retrieves nil by object_id" do + ObjectSpace._id2ref(nil.object_id).should == nil + end + + it "retrieves a small Integer by object_id" do + ObjectSpace._id2ref(1.object_id).should == 1 + ObjectSpace._id2ref((-42).object_id).should == -42 + end + + it "retrieves a large Integer by object_id" do + obj = 1 << 88 + ObjectSpace._id2ref(obj.object_id).should.equal?(obj) end it "retrieves a Symbol by object_id" do - s = :sym - r = ObjectSpace._id2ref(s.object_id) - r.should == s + ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym) + end + + it "retrieves a String by object_id" do + obj = "str" + ObjectSpace._id2ref(obj.object_id).should.equal?(obj) + end + + it "retrieves a frozen literal String by object_id" do + ObjectSpace._id2ref("frozen string literal _id2ref".freeze.object_id).should.equal?("frozen string literal _id2ref".freeze) + end + + it "retrieves an Encoding by object_id" do + ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8) end it 'raises RangeError when an object could not be found' do diff --git a/ruby/spec/ruby/core/objectspace/define_finalizer_spec.rb b/ruby/spec/ruby/core/objectspace/define_finalizer_spec.rb index 3f7b1ae57..281785b0a 100644 --- a/ruby/spec/ruby/core/objectspace/define_finalizer_spec.rb +++ b/ruby/spec/ruby/core/objectspace/define_finalizer_spec.rb @@ -1,24 +1,42 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -# NOTE: A call to define_finalizer does not guarantee that the -# passed proc or callable will be called at any particular time. +# Why do we not test that finalizers are run by the GC? The documentation +# says that finalizers are never guaranteed to be run, so we can't +# spec that they are. On some implementations of Ruby the finalizers may +# run asynchronously, meaning that we can't predict when they'll run, +# even if they were guaranteed to do so. Even on MRI finalizers can be +# very unpredictable, due to conservative stack scanning and references +# left in unused memory. + describe "ObjectSpace.define_finalizer" do it "raises an ArgumentError if the action does not respond to call" do -> { - ObjectSpace.define_finalizer("", mock("ObjectSpace.define_finalizer no #call")) + ObjectSpace.define_finalizer(Object.new, mock("ObjectSpace.define_finalizer no #call")) }.should raise_error(ArgumentError) end it "accepts an object and a proc" do - handler = -> obj { obj } - ObjectSpace.define_finalizer("garbage", handler).should == [0, handler] + handler = -> id { id } + ObjectSpace.define_finalizer(Object.new, handler).should == [0, handler] + end + + it "accepts an object and a bound method" do + handler = mock("callable") + def handler.finalize(id) end + finalize = handler.method(:finalize) + ObjectSpace.define_finalizer(Object.new, finalize).should == [0, finalize] end it "accepts an object and a callable" do handler = mock("callable") - def handler.call(obj) end - ObjectSpace.define_finalizer("garbage", handler).should == [0, handler] + def handler.call(id) end + ObjectSpace.define_finalizer(Object.new, handler).should == [0, handler] + end + + it "accepts an object and a block" do + handler = -> id { id } + ObjectSpace.define_finalizer(Object.new, &handler).should == [0, handler] end it "raises ArgumentError trying to define a finalizer on a non-reference" do @@ -31,7 +49,7 @@ def handler.call(obj) end it "calls finalizer on process termination" do code = <<-RUBY def scoped - Proc.new { puts "finalized" } + Proc.new { puts "finalizer run" } end handler = scoped obj = "Test" @@ -39,18 +57,104 @@ def scoped exit 0 RUBY - ruby_exe(code).should == "finalized\n" + ruby_exe(code, :args => "2>&1").should include("finalizer run\n") end - it "calls finalizer at exit even if it is self-referencing" do + ruby_version_is "3.0" do + it "warns if the finalizer has the object as the receiver" do + code = <<-RUBY + class CapturesSelf + def initialize + ObjectSpace.define_finalizer(self, proc { + puts "finalizer run" + }) + end + end + CapturesSelf.new + exit 0 + RUBY + + ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n") + end + + it "warns if the finalizer is a method bound to the receiver" do + code = <<-RUBY + class CapturesSelf + def initialize + ObjectSpace.define_finalizer(self, method(:finalize)) + end + def finalize(id) + puts "finalizer run" + end + end + CapturesSelf.new + exit 0 + RUBY + + ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n") + end + + it "warns if the finalizer was a block in the receiver" do + code = <<-RUBY + class CapturesSelf + def initialize + ObjectSpace.define_finalizer(self) do + puts "finalizer run" + end + end + end + CapturesSelf.new + exit 0 + RUBY + + ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n") + end + end + + it "calls a finalizer at exit even if it is self-referencing" do code = <<-RUBY obj = "Test" - handler = Proc.new { puts "finalized" } + handler = Proc.new { puts "finalizer run" } + ObjectSpace.define_finalizer(obj, handler) + exit 0 + RUBY + + ruby_exe(code).should include("finalizer run\n") + end + + it "calls a finalizer at exit even if it is indirectly self-referencing" do + code = <<-RUBY + class CapturesSelf + def initialize + ObjectSpace.define_finalizer(self, finalizer(self)) + end + def finalizer(zelf) + proc do + puts "finalizer run" + end + end + end + CapturesSelf.new + exit 0 + RUBY + + ruby_exe(code, :args => "2>&1").should include("finalizer run\n") + end + + it "calls a finalizer defined in a finalizer running at exit" do + code = <<-RUBY + obj = "Test" + handler = Proc.new do + obj2 = "Test" + handler2 = Proc.new { puts "finalizer 2 run" } + ObjectSpace.define_finalizer(obj2, handler2) + exit 0 + end ObjectSpace.define_finalizer(obj, handler) exit 0 RUBY - ruby_exe(code).should == "finalized\n" + ruby_exe(code, :args => "2>&1").should include("finalizer 2 run\n") end it "allows multiple finalizers with different 'callables' to be defined" do diff --git a/ruby/spec/ruby/core/objectspace/garbage_collect_spec.rb b/ruby/spec/ruby/core/objectspace/garbage_collect_spec.rb index 1aec3ea07..521eaa878 100644 --- a/ruby/spec/ruby/core/objectspace/garbage_collect_spec.rb +++ b/ruby/spec/ruby/core/objectspace/garbage_collect_spec.rb @@ -6,8 +6,8 @@ -> { ObjectSpace.garbage_collect }.should_not raise_error end - it "doesn't accept any arguments" do - -> { ObjectSpace.garbage_collect(1) }.should raise_error(ArgumentError) + it "accepts keyword arguments" do + ObjectSpace.garbage_collect(full_mark: true, immediate_sweep: true).should == nil end it "ignores the supplied block" do diff --git a/ruby/spec/ruby/core/objectspace/weakmap/each_key_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/each_key_spec.rb new file mode 100644 index 000000000..df971deeb --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/each_key_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_key{ |k| a << k }; a }, %w[A B] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_key +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb new file mode 100644 index 000000000..ea29edbd2 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_pair" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_pair{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_pair +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/each_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/each_spec.rb new file mode 100644 index 000000000..46fcb66a6 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/each_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each" do + it_behaves_like :weakmap_members, -> map { a = []; map.each{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/each_value_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/each_value_spec.rb new file mode 100644 index 000000000..65a1a7f6f --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/each_value_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_value" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_value{ |k| a << k }; a }, %w[x y] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_value +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb new file mode 100644 index 000000000..cb3174cbf --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#[]" do + it "is faithful to the map's content" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + map[key1] = ref1 + map[key1].should == ref1 + map[key1] = ref1 + map[key1].should == ref1 + map[key2] = ref2 + map[key1].should == ref1 + map[key2].should == ref2 + end + + it "matches using identity semantics" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a a].map(&:upcase) + ref = "x" + map[key1] = ref + map[key2].should == nil + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/element_set_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/element_set_spec.rb new file mode 100644 index 000000000..2b5365014 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/element_set_spec.rb @@ -0,0 +1,61 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#[]=" do + def should_accept(map, key, value) + (map[key] = value).should == value + map.should.key?(key) + map[key].should == value + end + + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + should_accept(map, key1, ref1) + should_accept(map, key1, ref1) + should_accept(map, key2, ref2) + map[key1].should == ref1 + end + + ruby_version_is ""..."2.7" do + it "does not accept primitive or frozen keys or values" do + map = ObjectSpace::WeakMap.new + x = Object.new + -> { map[true] = x }.should raise_error(ArgumentError) + -> { map[false] = x }.should raise_error(ArgumentError) + -> { map[nil] = x }.should raise_error(ArgumentError) + -> { map[42] = x }.should raise_error(ArgumentError) + -> { map[:foo] = x }.should raise_error(ArgumentError) + -> { map[x] = true }.should raise_error(ArgumentError) + -> { map[x] = false }.should raise_error(ArgumentError) + -> { map[x] = nil }.should raise_error(ArgumentError) + -> { map[x] = 42 }.should raise_error(ArgumentError) + -> { map[x] = :foo }.should raise_error(ArgumentError) + + y = Object.new.freeze + -> { map[x] = y}.should raise_error(FrozenError) + -> { map[y] = x}.should raise_error(FrozenError) + end + end + + ruby_version_is "2.7" do + it "accepts primitive or frozen keys or values" do + map = ObjectSpace::WeakMap.new + x = Object.new + should_accept(map, true, x) + should_accept(map, false, x) + should_accept(map, nil, x) + should_accept(map, 42, x) + should_accept(map, :foo, x) + + should_accept(map, x, true) + should_accept(map, x, false) + should_accept(map, x, 42) + should_accept(map, x, :foo) + + y = Object.new.freeze + should_accept(map, x, y) + should_accept(map, y, x) + end + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/include_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/include_spec.rb new file mode 100644 index 000000000..54ca6b303 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/include_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#include?" do + it_behaves_like :weakmap_include?, :include? +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/inspect_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/inspect_spec.rb new file mode 100644 index 000000000..f064f6e3e --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/inspect_spec.rb @@ -0,0 +1,25 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#inspect" do + it "displays object pointers in output" do + map = ObjectSpace::WeakMap.new + # important to test with BasicObject (without Kernel) here to test edge cases + key1, key2 = [BasicObject.new, Object.new] + ref1, ref2 = [BasicObject.new, Object.new] + map.inspect.should =~ /\A\#\z/ + map[key1] = ref1 + map.inspect.should =~ /\A\# => \#>\z/ + map[key1] = ref1 + map.inspect.should =~ /\A\# => \#>\z/ + map[key2] = ref2 + + regexp1 = /\A\# => \#, \# => \#>\z/ + regexp2 = /\A\# => \#, \# => \#>\z/ + str = map.inspect + if str =~ regexp1 + str.should =~ regexp1 + else + str.should =~ regexp2 + end + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/key_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/key_spec.rb new file mode 100644 index 000000000..999685ff9 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/key_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#key?" do + it_behaves_like :weakmap_include?, :key? +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/keys_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/keys_spec.rb new file mode 100644 index 000000000..7b1494bdd --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/keys_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' + +describe "ObjectSpace::WeakMap#keys" do + it_behaves_like :weakmap_members, -> map { map.keys }, %w[A B] +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/length_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/length_spec.rb new file mode 100644 index 000000000..3a935648b --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/length_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/size' + +describe "ObjectSpace::WeakMap#length" do + it_behaves_like :weakmap_size, :length +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/member_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/member_spec.rb new file mode 100644 index 000000000..cefb190ce --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/member_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#member?" do + it_behaves_like :weakmap_include?, :member? +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/shared/each.rb b/ruby/spec/ruby/core/objectspace/weakmap/shared/each.rb new file mode 100644 index 000000000..3d43a1934 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/shared/each.rb @@ -0,0 +1,10 @@ +describe :weakmap_each, shared: true do + it "must take a block, except when empty" do + map = ObjectSpace::WeakMap.new + key = "a".upcase + ref = "x" + map.send(@method).should == map + map[key] = ref + -> { map.send(@method) }.should raise_error(LocalJumpError) + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/shared/include.rb b/ruby/spec/ruby/core/objectspace/weakmap/shared/include.rb new file mode 100644 index 000000000..f9c174b6d --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/shared/include.rb @@ -0,0 +1,34 @@ +describe :weakmap_include?, shared: true do + it "recognizes keys in use" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + + map[key1] = ref1 + map.send(@method, key1).should == true + map[key1] = ref1 + map.send(@method, key1).should == true + map[key2] = ref2 + map.send(@method, key2).should == true + end + + it "matches using identity semantics" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a a].map(&:upcase) + ref = "x" + map[key1] = ref + map.send(@method, key2).should == false + end + + ruby_version_is "2.7" do + ruby_bug "#16826", "2.7.0"..."2.7.2" do + it "reports true if the pair exists and the value is nil" do + map = ObjectSpace::WeakMap.new + key = Object.new + map[key] = nil + map.size.should == 1 + map.send(@method, key).should == true + end + end + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/shared/members.rb b/ruby/spec/ruby/core/objectspace/weakmap/shared/members.rb new file mode 100644 index 000000000..57226c8d7 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/shared/members.rb @@ -0,0 +1,14 @@ +describe :weakmap_members, shared: true do + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + @method.call(map).should == [] + map[key1] = ref1 + @method.call(map).should == @object[0..0] + map[key1] = ref1 + @method.call(map).should == @object[0..0] + map[key2] = ref2 + @method.call(map).sort.should == @object + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/shared/size.rb b/ruby/spec/ruby/core/objectspace/weakmap/shared/size.rb new file mode 100644 index 000000000..1064f99d1 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/shared/size.rb @@ -0,0 +1,14 @@ +describe :weakmap_size, shared: true do + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + map.send(@method).should == 0 + map[key1] = ref1 + map.send(@method).should == 1 + map[key1] = ref1 + map.send(@method).should == 1 + map[key2] = ref2 + map.send(@method).should == 2 + end +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/size_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/size_spec.rb new file mode 100644 index 000000000..1446abaa2 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/size_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/size' + +describe "ObjectSpace::WeakMap#size" do + it_behaves_like :weakmap_size, :size +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap/values_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap/values_spec.rb new file mode 100644 index 000000000..6f6f90d0b --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap/values_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' + +describe "ObjectSpace::WeakMap#values" do + it_behaves_like :weakmap_members, -> map { map.values }, %w[x y] +end diff --git a/ruby/spec/ruby/core/objectspace/weakmap_spec.rb b/ruby/spec/ruby/core/objectspace/weakmap_spec.rb new file mode 100644 index 000000000..2f3f93c29 --- /dev/null +++ b/ruby/spec/ruby/core/objectspace/weakmap_spec.rb @@ -0,0 +1,12 @@ +require_relative '../../spec_helper' + +describe "ObjectSpace::WeakMap" do + + # Note that we can't really spec the most important aspect of this class: that entries get removed when the values + # become unreachable. This is because Ruby does not offer a way to reliable invoke GC (GC.start is not enough, neither + # on MRI or on alternative implementations). + + it "includes Enumerable" do + ObjectSpace::WeakMap.include?(Enumerable).should == true + end +end diff --git a/ruby/spec/ruby/core/proc/compose_spec.rb b/ruby/spec/ruby/core/proc/compose_spec.rb index ef9c125ae..803a32af7 100644 --- a/ruby/spec/ruby/core/proc/compose_spec.rb +++ b/ruby/spec/ruby/core/proc/compose_spec.rb @@ -1,156 +1,154 @@ require_relative '../../spec_helper' require_relative 'shared/compose' -ruby_version_is "2.6" do - describe "Proc#<<" do - it "returns a Proc that is the composition of self and the passed Proc" do - upcase = proc { |s| s.upcase } - succ = proc { |s| s.succ } +describe "Proc#<<" do + it "returns a Proc that is the composition of self and the passed Proc" do + upcase = proc { |s| s.upcase } + succ = proc { |s| s.succ } - (succ << upcase).call('Ruby').should == "RUBZ" - end + (succ << upcase).call('Ruby').should == "RUBZ" + end - it "calls passed Proc with arguments and then calls self with result" do - f = proc { |x| x * x } - g = proc { |x| x + x } + it "calls passed Proc with arguments and then calls self with result" do + f = proc { |x| x * x } + g = proc { |x| x + x } - (f << g).call(2).should == 16 - (g << f).call(2).should == 8 - end + (f << g).call(2).should == 16 + (g << f).call(2).should == 8 + end - it "accepts any callable object" do - inc = proc { |n| n + 1 } + it "accepts any callable object" do + inc = proc { |n| n + 1 } - double = Object.new - def double.call(n); n * 2; end + double = Object.new + def double.call(n); n * 2; end - (inc << double).call(3).should == 7 - end + (inc << double).call(3).should == 7 + end + + it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } } + + describe "composition" do + it "is a Proc" do + f = proc { |x| x * x } + g = proc { |x| x + x } - it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } } + (f << g).is_a?(Proc).should == true + (f << g).should_not.lambda? + end - describe "composition" do - it "is a Proc" do + ruby_version_is(''...'3.0') do + it "is a Proc when other is lambda" do f = proc { |x| x * x } - g = proc { |x| x + x } + g = -> x { x + x } (f << g).is_a?(Proc).should == true - (f << g).lambda?.should == false + (f << g).should_not.lambda? end - ruby_version_is(''...'2.8') do - it "is a Proc when other is lambda" do - f = proc { |x| x * x } - g = -> x { x + x } - - (f << g).is_a?(Proc).should == true - (f << g).lambda?.should == false - end - - it "is a lambda when self is lambda" do - f = -> x { x * x } - g = proc { |x| x + x } + it "is a lambda when self is lambda" do + f = -> x { x * x } + g = proc { |x| x + x } - (f << g).is_a?(Proc).should == true - (f << g).lambda?.should == true - end + (f << g).is_a?(Proc).should == true + (f << g).should.lambda? end + end - ruby_version_is('2.8') do - it "is a lambda when parameter is lambda" do - f = -> x { x * x } - g = proc { |x| x + x } - lambda_proc = -> x { x } + ruby_version_is('3.0') do + it "is a lambda when parameter is lambda" do + f = -> x { x * x } + g = proc { |x| x + x } + lambda_proc = -> x { x } - (f << g).is_a?(Proc).should == true - (f << g).lambda?.should == false - (f << lambda_proc).lambda?.should == true - end + (f << g).is_a?(Proc).should == true + (f << g).should_not.lambda? + (f << lambda_proc).should.lambda? end + end - it "may accept multiple arguments" do - inc = proc { |n| n + 1 } - mul = proc { |n, m| n * m } + it "may accept multiple arguments" do + inc = proc { |n| n + 1 } + mul = proc { |n, m| n * m } - (inc << mul).call(2, 3).should == 7 - end + (inc << mul).call(2, 3).should == 7 + end - it "passes blocks to the second proc" do - ScratchPad.record [] - one = proc { |&arg| arg.call :one if arg } - two = proc { |&arg| arg.call :two if arg } - (one << two).call { |x| ScratchPad << x } - ScratchPad.recorded.should == [:two] - end + it "passes blocks to the second proc" do + ScratchPad.record [] + one = proc { |&arg| arg.call :one if arg } + two = proc { |&arg| arg.call :two if arg } + (one << two).call { |x| ScratchPad << x } + ScratchPad.recorded.should == [:two] end end +end - describe "Proc#>>" do - it "returns a Proc that is the composition of self and the passed Proc" do - upcase = proc { |s| s.upcase } - succ = proc { |s| s.succ } +describe "Proc#>>" do + it "returns a Proc that is the composition of self and the passed Proc" do + upcase = proc { |s| s.upcase } + succ = proc { |s| s.succ } - (succ >> upcase).call('Ruby').should == "RUBZ" - end + (succ >> upcase).call('Ruby').should == "RUBZ" + end - it "calls passed Proc with arguments and then calls self with result" do - f = proc { |x| x * x } - g = proc { |x| x + x } + it "calls passed Proc with arguments and then calls self with result" do + f = proc { |x| x * x } + g = proc { |x| x + x } - (f >> g).call(2).should == 8 - (g >> f).call(2).should == 16 - end + (f >> g).call(2).should == 8 + (g >> f).call(2).should == 16 + end - it "accepts any callable object" do - inc = proc { |n| n + 1 } + it "accepts any callable object" do + inc = proc { |n| n + 1 } - double = Object.new - def double.call(n); n * 2; end + double = Object.new + def double.call(n); n * 2; end - (inc >> double).call(3).should == 8 - end + (inc >> double).call(3).should == 8 + end - it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } } + it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } } - describe "composition" do - it "is a Proc" do - f = proc { |x| x * x } - g = proc { |x| x + x } + describe "composition" do + it "is a Proc" do + f = proc { |x| x * x } + g = proc { |x| x + x } - (f >> g).is_a?(Proc).should == true - (f >> g).lambda?.should == false - end + (f >> g).is_a?(Proc).should == true + (f >> g).should_not.lambda? + end - it "is a Proc when other is lambda" do - f = proc { |x| x * x } - g = -> x { x + x } + it "is a Proc when other is lambda" do + f = proc { |x| x * x } + g = -> x { x + x } - (f >> g).is_a?(Proc).should == true - (f >> g).lambda?.should == false - end + (f >> g).is_a?(Proc).should == true + (f >> g).should_not.lambda? + end - it "is a lambda when self is lambda" do - f = -> x { x * x } - g = proc { |x| x + x } + it "is a lambda when self is lambda" do + f = -> x { x * x } + g = proc { |x| x + x } - (f >> g).is_a?(Proc).should == true - (f >> g).lambda?.should == true - end + (f >> g).is_a?(Proc).should == true + (f >> g).should.lambda? + end - it "may accept multiple arguments" do - inc = proc { |n| n + 1 } - mul = proc { |n, m| n * m } + it "may accept multiple arguments" do + inc = proc { |n| n + 1 } + mul = proc { |n, m| n * m } - (mul >> inc).call(2, 3).should == 7 - end + (mul >> inc).call(2, 3).should == 7 + end - it "passes blocks to the first proc" do - ScratchPad.record [] - one = proc { |&arg| arg.call :one if arg } - two = proc { |&arg| arg.call :two if arg } - (one >> two).call { |x| ScratchPad << x } - ScratchPad.recorded.should == [:one] - end + it "passes blocks to the first proc" do + ScratchPad.record [] + one = proc { |&arg| arg.call :one if arg } + two = proc { |&arg| arg.call :two if arg } + (one >> two).call { |x| ScratchPad << x } + ScratchPad.recorded.should == [:one] end end end diff --git a/ruby/spec/ruby/core/proc/eql_spec.rb b/ruby/spec/ruby/core/proc/eql_spec.rb index a3c5a5658..5f38af72d 100644 --- a/ruby/spec/ruby/core/proc/eql_spec.rb +++ b/ruby/spec/ruby/core/proc/eql_spec.rb @@ -2,5 +2,11 @@ require_relative 'shared/equal' describe "Proc#eql?" do - it_behaves_like :proc_equal_undefined, :eql? + ruby_version_is "0"..."3.0" do + it_behaves_like :proc_equal_undefined, :eql? + end + + ruby_version_is "3.0" do + it_behaves_like :proc_equal, :eql? + end end diff --git a/ruby/spec/ruby/core/proc/equal_value_spec.rb b/ruby/spec/ruby/core/proc/equal_value_spec.rb index 1b6ac792c..4c336331d 100644 --- a/ruby/spec/ruby/core/proc/equal_value_spec.rb +++ b/ruby/spec/ruby/core/proc/equal_value_spec.rb @@ -2,5 +2,11 @@ require_relative 'shared/equal' describe "Proc#==" do - it_behaves_like :proc_equal_undefined, :== + ruby_version_is "0"..."3.0" do + it_behaves_like :proc_equal_undefined, :== + end + + ruby_version_is "3.0" do + it_behaves_like :proc_equal, :== + end end diff --git a/ruby/spec/ruby/core/proc/fixtures/source_location.rb b/ruby/spec/ruby/core/proc/fixtures/source_location.rb index 688dac1e2..557209463 100644 --- a/ruby/spec/ruby/core/proc/fixtures/source_location.rb +++ b/ruby/spec/ruby/core/proc/fixtures/source_location.rb @@ -44,7 +44,7 @@ def self.my_detached_proc def self.my_detached_lambda body = -> { true } - lambda(&body) + suppress_warning {lambda(&body)} end def self.my_detached_proc_new diff --git a/ruby/spec/ruby/core/proc/hash_spec.rb b/ruby/spec/ruby/core/proc/hash_spec.rb index d780c1ceb..ebe0fde1a 100644 --- a/ruby/spec/ruby/core/proc/hash_spec.rb +++ b/ruby/spec/ruby/core/proc/hash_spec.rb @@ -7,7 +7,7 @@ end it "returns an Integer" do - proc { 1 + 489 }.hash.should be_kind_of(Fixnum) + proc { 1 + 489 }.hash.should be_kind_of(Integer) end it "is stable" do diff --git a/ruby/spec/ruby/core/proc/lambda_spec.rb b/ruby/spec/ruby/core/proc/lambda_spec.rb index fe2ceb427..b2d3f5035 100644 --- a/ruby/spec/ruby/core/proc/lambda_spec.rb +++ b/ruby/spec/ruby/core/proc/lambda_spec.rb @@ -15,8 +15,8 @@ end it "is preserved when passing a Proc with & to the lambda keyword" do - lambda(&->{}).lambda?.should be_true - lambda(&proc{}).lambda?.should be_false + suppress_warning {lambda(&->{})}.lambda?.should be_true + suppress_warning {lambda(&proc{})}.lambda?.should be_false end it "is preserved when passing a Proc with & to the proc keyword" do diff --git a/ruby/spec/ruby/core/proc/new_spec.rb b/ruby/spec/ruby/core/proc/new_spec.rb index cc033467e..6d5eb67a4 100644 --- a/ruby/spec/ruby/core/proc/new_spec.rb +++ b/ruby/spec/ruby/core/proc/new_spec.rb @@ -203,7 +203,7 @@ def some_method end end - ruby_version_is "2.7" do + ruby_version_is "2.7"..."3.0" do it "can be created if invoked from within a method with a block" do -> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/) end @@ -223,4 +223,16 @@ def some_method }.should complain(/Capturing the given block using Proc.new is deprecated/) end end + + ruby_version_is "3.0" do + it "raises an ArgumentError when passed no block" do + def some_method + Proc.new + end + + -> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + -> { some_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + end + end end diff --git a/ruby/spec/ruby/core/proc/parameters_spec.rb b/ruby/spec/ruby/core/proc/parameters_spec.rb index 2bc5f1325..5fb5cf418 100644 --- a/ruby/spec/ruby/core/proc/parameters_spec.rb +++ b/ruby/spec/ruby/core/proc/parameters_spec.rb @@ -57,7 +57,7 @@ end it "sets the first element of each sub-Array to :block for parameters prefixed with ampersands" do - ->&x { }.parameters.first.first.should == :block + -> &x { }.parameters.first.first.should == :block -> x, &y { }.parameters.last.first.should == :block proc {|&x| }.parameters.first.first.should == :block proc {|x,&y| }.parameters.last.first.should == :block @@ -68,7 +68,7 @@ -> x=Math::PI { }.parameters.first.last.should == :x -> an_argument, glark, &foo { }.parameters[1].last.should == :glark -> *rest { }.parameters.first.last.should == :rest - ->&block { }.parameters.first.last.should == :block + -> &block { }.parameters.first.last.should == :block proc {|x| }.parameters.first.last.should == :x proc {|x=Math::PI| }.parameters.first.last.should == :x proc {|an_argument, glark, &foo| }.parameters[1].last.should == :glark diff --git a/ruby/spec/ruby/core/proc/ruby2_keywords_spec.rb b/ruby/spec/ruby/core/proc/ruby2_keywords_spec.rb new file mode 100644 index 000000000..4f6bc151b --- /dev/null +++ b/ruby/spec/ruby/core/proc/ruby2_keywords_spec.rb @@ -0,0 +1,64 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Proc#ruby2_keywords" do + it "marks the final hash argument as keyword hash" do + f = -> *a { a.last } + f.ruby2_keywords + + last = f.call(1, 2, a: "a") + Hash.ruby2_keywords_hash?(last).should == true + end + + ruby_version_is "2.7" ... "3.0" do + it "fixes delegation warnings when calling a method accepting keywords" do + obj = Object.new + def obj.foo(*a, **b) end + + f = -> *a { obj.foo(*a) } + + -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/) + f.ruby2_keywords + -> { f.call(1, 2, {a: "a"}) }.should_not complain + end + + it "fixes delegation warnings when calling a proc accepting keywords" do + g = -> *a, **b { } + f = -> *a { g.call(*a) } + + -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/) + f.ruby2_keywords + -> { f.call(1, 2, {a: "a"}) }.should_not complain + end + end + + it "returns self" do + f = -> *a { } + f.ruby2_keywords.should equal f + end + + it "prints warning when a proc does not accept argument splat" do + f = -> a, b, c { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a proc accepts keywords" do + f = -> a:, b: { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a proc accepts keyword splat" do + f = -> **a { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + end +end diff --git a/ruby/spec/ruby/core/proc/shared/call.rb b/ruby/spec/ruby/core/proc/shared/call.rb index c30ea84b2..dbec34df4 100644 --- a/ruby/spec/ruby/core/proc/shared/call.rb +++ b/ruby/spec/ruby/core/proc/shared/call.rb @@ -49,6 +49,9 @@ a = proc {|x| x}.send(@method, 1, 2, 3) a.should == 1 + + a = proc {|x:| x}.send(@method, 2, x: 1) + a.should == 1 end it "will call #to_ary on argument and return self if return is nil" do diff --git a/ruby/spec/ruby/core/proc/shared/call_arguments.rb b/ruby/spec/ruby/core/proc/shared/call_arguments.rb index ef6ec0462..91ada3439 100644 --- a/ruby/spec/ruby/core/proc/shared/call_arguments.rb +++ b/ruby/spec/ruby/core/proc/shared/call_arguments.rb @@ -1,7 +1,7 @@ describe :proc_call_block_args, shared: true do it "can receive block arguments" do Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 - ->&b { b.send(@method)}.send(@method) {1 + 1}.should == 2 + -> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2 proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 end diff --git a/ruby/spec/ruby/core/proc/shared/compose.rb b/ruby/spec/ruby/core/proc/shared/compose.rb index 64338cada..e3ae7f76b 100644 --- a/ruby/spec/ruby/core/proc/shared/compose.rb +++ b/ruby/spec/ruby/core/proc/shared/compose.rb @@ -1,5 +1,5 @@ describe :proc_compose, shared: true do - ruby_version_is "2.6"..."2.7" do + ruby_version_is ""..."2.7" do it "raises NoMethodError when called if passed not callable object" do not_callable = Object.new composed = @object.call.send(@method, not_callable) diff --git a/ruby/spec/ruby/core/proc/shared/equal.rb b/ruby/spec/ruby/core/proc/shared/equal.rb index 46a189442..0c0020ca7 100644 --- a/ruby/spec/ruby/core/proc/shared/equal.rb +++ b/ruby/spec/ruby/core/proc/shared/equal.rb @@ -36,26 +36,26 @@ a.send(@method, b).should be_false end - it "returns true if both procs have the same body and environment" do + it "returns false if procs are distinct but have the same body and environment" do p = proc { :foo } p2 = proc { :foo } - p.send(@method, p2).should be_true + p.send(@method, p2).should be_false end - it "returns true if both lambdas with the same body and environment" do + it "returns false if lambdas are distinct but have same body and environment" do x = -> { :foo } x2 = -> { :foo } - x.send(@method, x2).should be_true + x.send(@method, x2).should be_false end - it "returns true if both different kinds of procs with the same body and env" do + it "returns false if using comparing lambda to proc, even with the same body and env" do p = -> { :foo } p2 = proc { :foo } - p.send(@method, p2).should be_true + p.send(@method, p2).should be_false x = proc { :bar } x2 = -> { :bar } - x.send(@method, x2).should be_true + x.send(@method, x2).should be_false end it "returns false if other is not a Proc" do diff --git a/ruby/spec/ruby/core/proc/shared/to_s.rb b/ruby/spec/ruby/core/proc/shared/to_s.rb index 8b9c83927..7f167a3d9 100644 --- a/ruby/spec/ruby/core/proc/shared/to_s.rb +++ b/ruby/spec/ruby/core/proc/shared/to_s.rb @@ -33,8 +33,13 @@ describe "for a proc created with UnboundMethod#to_proc" do it "returns a description including '(lambda)' and optionally including file and line number" do - def hello; end - method("hello").to_proc.send(@method).should =~ /^#$/ + def hello; end + s = method("hello").to_proc.send(@method) + if s.include? __FILE__ + s.should =~ /^#$/ + else + s.should =~ /^#$/ + end end it "has a binary encoding" do @@ -46,7 +51,7 @@ def hello; end describe "for a proc created with Symbol#to_proc" do it "returns a description including '(&:symbol)'" do proc = :foobar.to_proc - proc.send(@method).should =~ /^#$/ + proc.send(@method).should.include?('(&:foobar)') end it "has a binary encoding" do diff --git a/ruby/spec/ruby/core/proc/source_location_spec.rb b/ruby/spec/ruby/core/proc/source_location_spec.rb index b5b8178df..f268499b8 100644 --- a/ruby/spec/ruby/core/proc/source_location_spec.rb +++ b/ruby/spec/ruby/core/proc/source_location_spec.rb @@ -34,21 +34,21 @@ file.should == File.realpath('../fixtures/source_location.rb', __FILE__) end - it "sets the last value to a Fixnum representing the line on which the proc was defined" do + it "sets the last value to an Integer representing the line on which the proc was defined" do line = @proc.source_location.last - line.should be_an_instance_of(Fixnum) + line.should be_an_instance_of(Integer) line.should == 4 line = @proc_new.source_location.last - line.should be_an_instance_of(Fixnum) + line.should be_an_instance_of(Integer) line.should == 12 line = @lambda.source_location.last - line.should be_an_instance_of(Fixnum) + line.should be_an_instance_of(Integer) line.should == 8 line = @method.source_location.last - line.should be_an_instance_of(Fixnum) + line.should be_an_instance_of(Integer) line.should == 15 end diff --git a/ruby/spec/ruby/core/process/clock_getres_spec.rb b/ruby/spec/ruby/core/process/clock_getres_spec.rb index f1ecb7401..85aa2b25f 100644 --- a/ruby/spec/ruby/core/process/clock_getres_spec.rb +++ b/ruby/spec/ruby/core/process/clock_getres_spec.rb @@ -1,34 +1,6 @@ require_relative '../../spec_helper' -require_relative 'fixtures/clocks' describe "Process.clock_getres" do - # clock_getres() seems completely buggy on FreeBSD: - # https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd11zfs/ruby-trunk/log/20190428T093003Z.fail.html.gz - platform_is_not :freebsd, :openbsd do - # NOTE: Look at fixtures/clocks.rb for clock and OS-specific exclusions - ProcessSpecs.clock_constants_for_resolution_checks.each do |name, value| - it "matches the clock in practice for Process::#{name}" do - times = 10_000.times.map { Process.clock_gettime(value, :nanosecond) } - reported = Process.clock_getres(value, :nanosecond) - - # The clock should not be more accurate than reported (times should be - # a multiple of reported precision.) - times.select { |t| t % reported > 0 }.should be_empty - - # We're assuming precision is a multiple of ten - it may or may not - # be an incompatibility if it isn't but we'd like to notice this, - # and the spec following these wouldn't work if it isn't. - reported.should > 0 - (reported == 1 || reported % 10 == 0).should be_true - - # The clock should not be less accurate than reported (times should - # not all be a multiple of the next precision up, assuming precisions - # are multiples of ten.) - times.select { |t| t % (reported * 10) == 0 }.size.should_not == times.size - end - end - end - # These are documented it "with :GETTIMEOFDAY_BASED_CLOCK_REALTIME reports 1 microsecond" do @@ -47,15 +19,15 @@ # These are observed - platform_is_not :solaris, :aix, :openbsd do - it "with Process::CLOCK_REALTIME reports at least 1 microsecond" do - Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 1_000 + platform_is :linux, :darwin, :windows do + it "with Process::CLOCK_REALTIME reports at least 10 millisecond" do + Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 10_000_000 end end - platform_is_not :aix, :openbsd do - it "with Process::CLOCK_MONOTONIC reports at least 1 microsecond" do - Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 1_000 + platform_is :linux, :darwin, :windows do + it "with Process::CLOCK_MONOTONIC reports at least 10 millisecond" do + Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 10_000_000 end end end diff --git a/ruby/spec/ruby/core/process/constants_spec.rb b/ruby/spec/ruby/core/process/constants_spec.rb index 2fa93ad8b..b61f5ab64 100644 --- a/ruby/spec/ruby/core/process/constants_spec.rb +++ b/ruby/spec/ruby/core/process/constants_spec.rb @@ -60,4 +60,26 @@ Process::RLIMIT_AS.should == 10 end end + + platform_is :windows do + it "does not define RLIMIT constants" do + %i[ + RLIMIT_CPU + RLIMIT_FSIZE + RLIMIT_DATA + RLIMIT_STACK + RLIMIT_CORE + RLIMIT_RSS + RLIMIT_NPROC + RLIMIT_NOFILE + RLIMIT_MEMLOCK + RLIMIT_AS + RLIM_INFINITY + RLIM_SAVED_MAX + RLIM_SAVED_CUR + ].each do |const| + Process.const_defined?(const).should be_false + end + end + end end diff --git a/ruby/spec/ruby/core/process/euid_spec.rb b/ruby/spec/ruby/core/process/euid_spec.rb index 7bbacfadf..a2f1bbf42 100644 --- a/ruby/spec/ruby/core/process/euid_spec.rb +++ b/ruby/spec/ruby/core/process/euid_spec.rb @@ -2,7 +2,7 @@ describe "Process.euid" do it "returns the effective user ID for this process" do - Process.euid.should be_kind_of(Fixnum) + Process.euid.should be_kind_of(Integer) end it "also goes by Process::UID.eid" do diff --git a/ruby/spec/ruby/core/process/exec_spec.rb b/ruby/spec/ruby/core/process/exec_spec.rb index 5a6e3fc1a..deb8913b6 100644 --- a/ruby/spec/ruby/core/process/exec_spec.rb +++ b/ruby/spec/ruby/core/process/exec_spec.rb @@ -29,16 +29,8 @@ end end - platform_is_not :openbsd do - it "raises Errno::EACCES when passed a directory" do - -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES) - end - end - - platform_is :openbsd do - it "raises Errno::EISDIR when passed a directory" do - -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EISDIR) - end + it "raises Errno::EACCES when passed a directory" do + -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES) end it "runs the specified command, replacing current process" do @@ -201,9 +193,11 @@ map_fd_fixture = fixture __FILE__, "map_fd.rb" cmd = <<-EOC f = File.open(#{@name.inspect}, "w+") - child_fd = f.fileno + 1 - File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd } - Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f } + File.open(#{__FILE__.inspect}, "r") do |io| + child_fd = io.fileno + File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd } + Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f } + end EOC ruby_exe(cmd, escape: true) diff --git a/ruby/spec/ruby/core/process/fixtures/clocks.rb b/ruby/spec/ruby/core/process/fixtures/clocks.rb index 7537cfaba..f043f6ac1 100644 --- a/ruby/spec/ruby/core/process/fixtures/clocks.rb +++ b/ruby/spec/ruby/core/process/fixtures/clocks.rb @@ -15,46 +15,4 @@ def self.clock_constants [c, Process.const_get(c)] } end - - def self.clock_constants_for_resolution_checks - clocks = clock_constants - - # These clocks in practice on Linux do not seem to match their reported resolution. - platform_is :linux do - clocks = clocks.reject { |clock, value| - [:CLOCK_REALTIME_COARSE, :CLOCK_MONOTONIC_COARSE].include?(clock) - } - end - - # These clocks in practice on macOS seem to be less precise than advertised by clock_getres - platform_is :darwin do - clocks = clocks.reject { |clock, value| - [:CLOCK_UPTIME_RAW_APPROX, :CLOCK_MONOTONIC_RAW_APPROX].include?(clock) - } - end - - # These clocks in practice on ARM on Linux do not seem to match their reported resolution. - platform_is :armv7, :armv8, :aarch64 do - clocks = clocks.reject { |clock, value| - [:CLOCK_PROCESS_CPUTIME_ID, :CLOCK_THREAD_CPUTIME_ID, :CLOCK_MONOTONIC_RAW].include?(clock) - } - end - - # These clocks in practice on AIX seem to be more precise than their reported resolution. - platform_is :aix do - clocks = clocks.reject { |clock, value| - [:CLOCK_REALTIME, :CLOCK_MONOTONIC].include?(clock) - } - end - - # On a Hyper-V Linux guest machine, these clocks in practice - # seem to be less precise than advertised by clock_getres - platform_is :linux do - clocks = clocks.reject { |clock, value| - clock == :CLOCK_MONOTONIC_RAW - } - end - - clocks - end end diff --git a/ruby/spec/ruby/core/process/getpriority_spec.rb b/ruby/spec/ruby/core/process/getpriority_spec.rb index 4b66e1867..a35e5956a 100644 --- a/ruby/spec/ruby/core/process/getpriority_spec.rb +++ b/ruby/spec/ruby/core/process/getpriority_spec.rb @@ -5,19 +5,19 @@ it "coerces arguments to Integers" do ret = Process.getpriority mock_int(Process::PRIO_PROCESS), mock_int(0) - ret.should be_kind_of(Fixnum) + ret.should be_kind_of(Integer) end it "gets the scheduling priority for a specified process" do - Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Fixnum) + Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Integer) end it "gets the scheduling priority for a specified process group" do - Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Fixnum) + Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Integer) end it "gets the scheduling priority for a specified user" do - Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Fixnum) + Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Integer) end end end diff --git a/ruby/spec/ruby/core/process/getrlimit_spec.rb b/ruby/spec/ruby/core/process/getrlimit_spec.rb index f77a61a47..883b8fac4 100644 --- a/ruby/spec/ruby/core/process/getrlimit_spec.rb +++ b/ruby/spec/ruby/core/process/getrlimit_spec.rb @@ -11,8 +11,8 @@ Process.getrlimit(:DATA) end -platform_is_not :windows do - describe "Process.getrlimit" do +describe "Process.getrlimit" do + platform_is_not :windows do it "returns a two-element Array of Integers" do result = Process.getrlimit Process::RLIMIT_CORE result.size.should == 2 @@ -88,4 +88,13 @@ end end end + + platform_is :windows do + it "is not implemented" do + Process.respond_to?(:getrlimit).should be_false + -> do + Process.getrlimit(nil) + end.should raise_error NotImplementedError + end + end end diff --git a/ruby/spec/ruby/core/process/groups_spec.rb b/ruby/spec/ruby/core/process/groups_spec.rb index cbbe4fed2..33e0f9d7b 100644 --- a/ruby/spec/ruby/core/process/groups_spec.rb +++ b/ruby/spec/ruby/core/process/groups_spec.rb @@ -4,6 +4,10 @@ platform_is_not :windows do it "gets an Array of the gids of groups in the supplemental group access list" do groups = `id -G`.scan(/\d+/).map { |i| i.to_i } + # Include the standard `id` command output. On macOS, GNU + # coreutils `id` is limited to NGROUPS_MAX groups, because of + # the backward compatibility of getgroups(2). + (groups |= `/usr/bin/id -G`.scan(/\d+/).map { |i| i.to_i }) rescue nil gid = Process.gid expected = (groups.sort - [gid]).uniq.sort diff --git a/ruby/spec/ruby/core/process/kill_spec.rb b/ruby/spec/ruby/core/process/kill_spec.rb index 4bd64a1fe..af9c9e6de 100644 --- a/ruby/spec/ruby/core/process/kill_spec.rb +++ b/ruby/spec/ruby/core/process/kill_spec.rb @@ -16,7 +16,7 @@ -> { Process.kill("term", @pid) }.should raise_error(ArgumentError) end - it "raises an ArgumentError if signal is not a Fixnum or String" do + it "raises an ArgumentError if signal is not an Integer or String" do signal = mock("process kill signal") signal.should_not_receive(:to_int) diff --git a/ruby/spec/ruby/core/process/last_status_spec.rb b/ruby/spec/ruby/core/process/last_status_spec.rb index 3898dd6b9..2372f2aae 100644 --- a/ruby/spec/ruby/core/process/last_status_spec.rb +++ b/ruby/spec/ruby/core/process/last_status_spec.rb @@ -1,20 +1,18 @@ require_relative '../../spec_helper' -ruby_version_is '2.5' do - describe 'Process#last_status' do - it 'returns the status of the last executed child process in the current thread' do - pid = Process.wait Process.spawn("exit 0") - Process.last_status.pid.should == pid - end +describe 'Process#last_status' do + it 'returns the status of the last executed child process in the current thread' do + pid = Process.wait Process.spawn("exit 0") + Process.last_status.pid.should == pid + end - it 'returns nil if no child process has been ever executed in the current thread' do - Thread.new do - Process.last_status.should == nil - end.join - end + it 'returns nil if no child process has been ever executed in the current thread' do + Thread.new do + Process.last_status.should == nil + end.join + end - it 'raises an ArgumentError if any arguments are provided' do - -> { Process.last_status(1) }.should raise_error(ArgumentError) - end + it 'raises an ArgumentError if any arguments are provided' do + -> { Process.last_status(1) }.should raise_error(ArgumentError) end end diff --git a/ruby/spec/ruby/core/process/maxgroups_spec.rb b/ruby/spec/ruby/core/process/maxgroups_spec.rb index 362f788ab..2549a7a97 100644 --- a/ruby/spec/ruby/core/process/maxgroups_spec.rb +++ b/ruby/spec/ruby/core/process/maxgroups_spec.rb @@ -3,7 +3,7 @@ platform_is_not :windows do describe "Process.maxgroups" do it "returns the maximum number of gids allowed in the supplemental group access list" do - Process.maxgroups.should be_kind_of(Fixnum) + Process.maxgroups.should be_kind_of(Integer) end it "sets the maximum number of gids allowed in the supplemental group access list" do diff --git a/ruby/spec/ruby/core/process/pid_spec.rb b/ruby/spec/ruby/core/process/pid_spec.rb index c5947ab50..2d008bc4b 100644 --- a/ruby/spec/ruby/core/process/pid_spec.rb +++ b/ruby/spec/ruby/core/process/pid_spec.rb @@ -3,7 +3,7 @@ describe "Process.pid" do it "returns the process id of this process" do pid = Process.pid - pid.should be_kind_of(Fixnum) + pid.should be_kind_of(Integer) Process.pid.should == pid end end diff --git a/ruby/spec/ruby/core/process/setrlimit_spec.rb b/ruby/spec/ruby/core/process/setrlimit_spec.rb index 8bc035a4f..b92f98fd4 100644 --- a/ruby/spec/ruby/core/process/setrlimit_spec.rb +++ b/ruby/spec/ruby/core/process/setrlimit_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -platform_is_not :windows do - describe "Process.setrlimit" do +describe "Process.setrlimit" do + platform_is_not :windows do context "when passed an Object" do before do @resource = Process::RLIMIT_CORE @@ -229,4 +229,13 @@ end end end + + platform_is :windows do + it "is not implemented" do + Process.respond_to?(:setrlimit).should be_false + -> do + Process.setrlimit(nil, nil) + end.should raise_error NotImplementedError + end + end end diff --git a/ruby/spec/ruby/core/process/spawn_spec.rb b/ruby/spec/ruby/core/process/spawn_spec.rb index 06ad9a251..6be3f41a8 100644 --- a/ruby/spec/ruby/core/process/spawn_spec.rb +++ b/ruby/spec/ruby/core/process/spawn_spec.rb @@ -48,10 +48,10 @@ -> { Process.wait Process.spawn("echo spawn") }.should output_to_fd("spawn\n") end - it "returns the process ID of the new process as a Fixnum" do + it "returns the process ID of the new process as an Integer" do pid = Process.spawn(*ruby_exe, "-e", "exit") Process.wait pid - pid.should be_an_instance_of(Fixnum) + pid.should be_an_instance_of(Integer) end it "returns immediately" do @@ -207,13 +207,29 @@ it "unsets environment variables whose value is nil" do ENV["FOO"] = "BAR" - Process.wait Process.spawn({"FOO" => nil}, "echo #{@var}>#{@name}") - expected = "\n" - platform_is :windows do - # Windows does not expand the variable if it is unset - expected = "#{@var}\n" + -> do + Process.wait Process.spawn({"FOO" => nil}, ruby_cmd("p ENV['FOO']")) + end.should output_to_fd("nil\n") + end + + platform_is_not :windows do + it "uses the passed env['PATH'] to search the executable" do + dir = tmp("spawn_path_dir") + mkdir_p dir + begin + exe = 'process-spawn-executable-in-path' + path = "#{dir}/#{exe}" + File.write(path, "#!/bin/sh\necho $1") + File.chmod(0755, path) + + env = { "PATH" => "#{dir}#{File::PATH_SEPARATOR}#{ENV['PATH']}" } + Process.wait Process.spawn(env, exe, 'OK', out: @name) + $?.should.success? + File.read(@name).should == "OK\n" + ensure + rm_r dir + end end - File.read(@name).should == expected end it "calls #to_hash to convert the environment" do @@ -419,7 +435,7 @@ def child_pids(pid) it "kills extra chdir processes" do pid = nil - Dir.chdir("/tmp") do + Dir.chdir("/") do pid = Process.spawn("sleep 10") end @@ -461,7 +477,7 @@ def child_pids(pid) # redirection - it "redirects STDOUT to the given file descriptor if out: Fixnum" do + it "redirects STDOUT to the given file descriptor if out: Integer" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark", out: file.fileno) @@ -487,7 +503,7 @@ def child_pids(pid) File.read(@name).should == "glark\n" end - it "redirects STDERR to the given file descriptor if err: Fixnum" do + it "redirects STDERR to the given file descriptor if err: Integer" do File.open(@name, 'w') do |file| -> do Process.wait Process.spawn("echo glark>&2", err: file.fileno) @@ -540,31 +556,29 @@ def child_pids(pid) File.read(@name).should == "glarkbang" end + platform_is_not :windows, :android do + it "closes STDERR in the child if :err => :close" do + File.open(@name, 'w') do |file| + -> do + code = "begin; STDOUT.puts 'out'; STDERR.puts 'hello'; rescue => e; puts 'rescued'; end" + Process.wait Process.spawn(ruby_cmd(code), :out => file, :err => :close) + end.should output_to_fd("out\nrescued\n", file) + end + end + end + # :close_others platform_is_not :windows do context "defaults :close_others to" do - ruby_version_is ""..."2.6" do - it "true" do - IO.pipe do |r, w| - w.close_on_exec = false - code = "begin; IO.new(#{w.fileno}).close; rescue Errno::EBADF; puts 'not inherited'; end" - Process.wait Process.spawn(ruby_cmd(code), :out => @name) - File.read(@name).should == "not inherited\n" - end - end - end - - ruby_version_is "2.6" do - it "false" do - IO.pipe do |r, w| - w.close_on_exec = false - code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close" - pid = Process.spawn(ruby_cmd(code)) - w.close - Process.wait(pid) - r.read.should == "inherited\n" - end + it "false" do + IO.pipe do |r, w| + w.close_on_exec = false + code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close" + pid = Process.spawn(ruby_cmd(code)) + w.close + Process.wait(pid) + r.read.should == "inherited\n" end end end @@ -699,13 +713,15 @@ def child_pids(pid) end it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do - child_fd = find_unused_fd - args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s]) - pid = Process.spawn(*args, { child_fd => @io }) - Process.waitpid pid - @io.rewind - - @io.read.should == "writing to fd: #{child_fd}" + File.open(__FILE__, "r") do |f| + child_fd = f.fileno + args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s]) + pid = Process.spawn(*args, { child_fd => @io }) + Process.waitpid pid + @io.rewind + + @io.read.should == "writing to fd: #{child_fd}" + end end end end diff --git a/ruby/spec/ruby/core/process/status/equal_value_spec.rb b/ruby/spec/ruby/core/process/status/equal_value_spec.rb index 444ce1775..d85bb2221 100644 --- a/ruby/spec/ruby/core/process/status/equal_value_spec.rb +++ b/ruby/spec/ruby/core/process/status/equal_value_spec.rb @@ -2,13 +2,13 @@ describe "Process::Status#==" do it "returns true when compared to the integer status of an exited child" do - ruby_exe("exit(29)") + ruby_exe("exit(29)", exit_status: 29) $?.to_i.should == $? $?.should == $?.to_i end it "returns true when compared to the integer status of a terminated child" do - ruby_exe("Process.kill(:KILL, $$); exit(29)") + ruby_exe("Process.kill(:KILL, $$); exit(29)", exit_status: platform_is(:windows) ? 0 : nil) $?.to_i.should == $? $?.should == $?.to_i end diff --git a/ruby/spec/ruby/core/process/status/exited_spec.rb b/ruby/spec/ruby/core/process/status/exited_spec.rb index 0ae3f9e7a..059cd5b1a 100644 --- a/ruby/spec/ruby/core/process/status/exited_spec.rb +++ b/ruby/spec/ruby/core/process/status/exited_spec.rb @@ -1,9 +1,7 @@ require_relative '../../../spec_helper' describe "Process::Status#exited?" do - describe "for a child that exited normally" do - before :each do ruby_exe("exit(0)") end @@ -15,9 +13,8 @@ describe "for a terminated child" do - before :each do - ruby_exe("Process.kill(:KILL, $$); exit(42)") + ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil) end platform_is_not :windows do @@ -31,7 +28,5 @@ $?.exited?.should be_true end end - end - end diff --git a/ruby/spec/ruby/core/process/status/exitstatus_spec.rb b/ruby/spec/ruby/core/process/status/exitstatus_spec.rb index d6c6965b9..3087bd619 100644 --- a/ruby/spec/ruby/core/process/status/exitstatus_spec.rb +++ b/ruby/spec/ruby/core/process/status/exitstatus_spec.rb @@ -2,7 +2,7 @@ describe "Process::Status#exitstatus" do before :each do - ruby_exe("exit(42)") + ruby_exe("exit(42)", exit_status: 42) end it "returns the process exit code" do @@ -11,7 +11,7 @@ describe "for a child that raised SignalException" do before :each do - ruby_exe("Process.kill(:KILL, $$); exit(42)") + ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil) end platform_is_not :windows do diff --git a/ruby/spec/ruby/core/process/status/signaled_spec.rb b/ruby/spec/ruby/core/process/status/signaled_spec.rb index f23c95025..389092a53 100644 --- a/ruby/spec/ruby/core/process/status/signaled_spec.rb +++ b/ruby/spec/ruby/core/process/status/signaled_spec.rb @@ -1,9 +1,7 @@ require_relative '../../../spec_helper' describe "Process::Status#signaled?" do - describe "for a cleanly exited child" do - before :each do ruby_exe("exit(0)") end @@ -14,9 +12,8 @@ end describe "for a terminated child" do - before :each do - ruby_exe("Process.kill(:KILL, $$); exit(42)") + ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil) end platform_is_not :windows do @@ -30,6 +27,5 @@ $?.signaled?.should be_false end end - end end diff --git a/ruby/spec/ruby/core/process/status/success_spec.rb b/ruby/spec/ruby/core/process/status/success_spec.rb index 28a172180..c531121f0 100644 --- a/ruby/spec/ruby/core/process/status/success_spec.rb +++ b/ruby/spec/ruby/core/process/status/success_spec.rb @@ -1,9 +1,7 @@ require_relative '../../../spec_helper' describe "Process::Status#success?" do - describe "for a child that exited normally" do - before :each do ruby_exe("exit(0)") end @@ -14,9 +12,8 @@ end describe "for a child that exited with a non zero status" do - before :each do - ruby_exe("exit(42)") + ruby_exe("exit(42)", exit_status: 42) end it "returns false" do @@ -25,27 +22,20 @@ end describe "for a child that was terminated" do - before :each do - ruby_exe("Process.kill(:KILL, $$); exit(42)") + ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil) end platform_is_not :windows do - it "returns nil" do $?.success?.should be_nil end - end platform_is :windows do - it "always returns true" do $?.success?.should be_true end - end - end - end diff --git a/ruby/spec/ruby/core/process/status/termsig_spec.rb b/ruby/spec/ruby/core/process/status/termsig_spec.rb index 204708bc1..1c87a6f45 100644 --- a/ruby/spec/ruby/core/process/status/termsig_spec.rb +++ b/ruby/spec/ruby/core/process/status/termsig_spec.rb @@ -13,7 +13,7 @@ describe "for a child that raised SignalException" do before :each do - ruby_exe("raise SignalException, 'SIGTERM'") + ruby_exe("raise SignalException, 'SIGTERM'", exit_status: nil) end platform_is_not :windows do @@ -25,7 +25,7 @@ describe "for a child that was sent a signal" do before :each do - ruby_exe("Process.kill(:KILL, $$); exit(42)") + ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil) end platform_is_not :windows do diff --git a/ruby/spec/ruby/core/process/status/to_i_spec.rb b/ruby/spec/ruby/core/process/status/to_i_spec.rb index a284f64f8..7cde9b915 100644 --- a/ruby/spec/ruby/core/process/status/to_i_spec.rb +++ b/ruby/spec/ruby/core/process/status/to_i_spec.rb @@ -2,12 +2,12 @@ describe "Process::Status#to_i" do it "returns an integer when the child exits" do - ruby_exe('exit 48') + ruby_exe('exit 48', exit_status: 48) $?.to_i.should be_an_instance_of(Integer) end it "returns an integer when the child is signaled" do - ruby_exe('raise SignalException, "TERM"') + ruby_exe('raise SignalException, "TERM"', exit_status: platform_is(:windows) ? 3 : nil) $?.to_i.should be_an_instance_of(Integer) end end diff --git a/ruby/spec/ruby/core/process/status/wait_spec.rb b/ruby/spec/ruby/core/process/status/wait_spec.rb new file mode 100644 index 000000000..b9d80e31f --- /dev/null +++ b/ruby/spec/ruby/core/process/status/wait_spec.rb @@ -0,0 +1,102 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/common' + +ruby_version_is "3.0" do + describe "Process::Status.wait" do + ProcessSpecs.use_system_ruby(self) + + before :all do + begin + leaked = Process.waitall + # Ruby-space should not see PIDs used by mjit + raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty? + rescue NotImplementedError + end + end + + it "returns a status with pid -1 if there are no child processes" do + Process::Status.wait.pid.should == -1 + end + + platform_is_not :windows do + it "returns a status with its child pid" do + pid = Process.spawn(ruby_cmd('exit')) + status = Process::Status.wait + status.should be_an_instance_of(Process::Status) + status.pid.should == pid + end + + it "should not set $? to the Process::Status" do + pid = Process.spawn(ruby_cmd('exit')) + status = Process::Status.wait + $?.should_not equal(status) + end + + it "should not change the value of $?" do + pid = Process.spawn(ruby_cmd('exit')) + Process.wait + status = $? + Process::Status.wait + status.should equal($?) + end + + it "waits for any child process if no pid is given" do + pid = Process.spawn(ruby_cmd('exit')) + Process::Status.wait.pid.should == pid + -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + end + + it "waits for a specific child if a pid is given" do + pid1 = Process.spawn(ruby_cmd('exit')) + pid2 = Process.spawn(ruby_cmd('exit')) + Process::Status.wait(pid2).pid.should == pid2 + Process::Status.wait(pid1).pid.should == pid1 + -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) + -> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH) + end + + it "coerces the pid to an Integer" do + pid1 = Process.spawn(ruby_cmd('exit')) + Process::Status.wait(mock_int(pid1)).pid.should == pid1 + -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) + end + + # This spec is probably system-dependent. + it "waits for a child whose process group ID is that of the calling process" do + pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true) + pid2 = Process.spawn(ruby_cmd('exit')) + + Process::Status.wait(0).pid.should == pid2 + Process::Status.wait.pid.should == pid1 + end + + # This spec is probably system-dependent. + it "doesn't block if no child is available when WNOHANG is used" do + read, write = IO.pipe + pid = Process.fork do + read.close + Signal.trap("TERM") { Process.exit! } + write << 1 + write.close + sleep + end + + Process::Status.wait(pid, Process::WNOHANG).should be_nil + + # wait for the child to setup its TERM handler + write.close + read.read(1) + read.close + + Process.kill("TERM", pid) + Process::Status.wait.pid.should == pid + end + + it "always accepts flags=0" do + pid = Process.spawn(ruby_cmd('exit')) + Process::Status.wait(-1, 0).pid.should == pid + -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + end + end + end +end diff --git a/ruby/spec/ruby/core/process/times_spec.rb b/ruby/spec/ruby/core/process/times_spec.rb index 35a7f5b34..b47189a7e 100644 --- a/ruby/spec/ruby/core/process/times_spec.rb +++ b/ruby/spec/ruby/core/process/times_spec.rb @@ -13,18 +13,23 @@ Process.times.utime.should > user end - ruby_version_is "2.5" do - platform_is_not :windows do - it "uses getrusage when available to improve precision beyond milliseconds" do - times = 1000.times.map { Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) } - if times.count { |t| !('%.6f' % t).end_with?('000') } == 0 - skip "getrusage is not supported on this environment" - end + platform_is_not :windows do + it "uses getrusage when available to improve precision beyond milliseconds" do + max = 10_000 + has_getrusage = max.times.find do + time = Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) + ('%.6f' % time).end_with?('000') + end + unless has_getrusage + skip "getrusage is not supported on this environment" + end - times = 1000.times.map { Process.times } - times.count { |t| !('%.6f' % t.utime).end_with?('000') }.should > 0 - times.count { |t| !('%.6f' % t.stime).end_with?('000') }.should > 0 + found = (max * 100).times.find do + time = Process.times.utime + ('%.6f' % time).end_with?('000') end + + found.should_not == nil end end end diff --git a/ruby/spec/ruby/core/process/wait_spec.rb b/ruby/spec/ruby/core/process/wait_spec.rb index f393a99e0..44c95d630 100644 --- a/ruby/spec/ruby/core/process/wait_spec.rb +++ b/ruby/spec/ruby/core/process/wait_spec.rb @@ -7,9 +7,8 @@ before :all do begin leaked = Process.waitall - puts "leaked before wait specs: #{leaked}" unless leaked.empty? # Ruby-space should not see PIDs used by mjit - leaked.should be_empty + raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty? rescue NotImplementedError end end diff --git a/ruby/spec/ruby/core/queue/initialize_spec.rb b/ruby/spec/ruby/core/queue/initialize_spec.rb new file mode 100644 index 000000000..83c7e595f --- /dev/null +++ b/ruby/spec/ruby/core/queue/initialize_spec.rb @@ -0,0 +1,38 @@ +require_relative '../../spec_helper' + +describe "Queue#initialize" do + it "can be passed no arguments for an empty Queue" do + q = Queue.new + q.size.should == 0 + q.should.empty? + end + + ruby_version_is '3.1' do + it "adds all elements of the passed Enumerable to self" do + q = Queue.new([1, 2, 3]) + q.size.should == 3 + q.should_not.empty? + q.pop.should == 1 + q.pop.should == 2 + q.pop.should == 3 + q.should.empty? + end + + it "uses #to_a on the provided Enumerable" do + enumerable = MockObject.new('mock-enumerable') + enumerable.should_receive(:to_a).and_return([1, 2, 3]) + q = Queue.new(enumerable) + q.size.should == 3 + q.should_not.empty? + q.pop.should == 1 + q.pop.should == 2 + q.pop.should == 3 + q.should.empty? + end + + it "raises if the provided Enumerable does not respond to #to_a" do + enumerable = MockObject.new('mock-enumerable') + -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array") + end + end +end diff --git a/ruby/spec/ruby/core/random/bytes_spec.rb b/ruby/spec/ruby/core/random/bytes_spec.rb index 2caf18fbd..06e84d03b 100644 --- a/ruby/spec/ruby/core/random/bytes_spec.rb +++ b/ruby/spec/ruby/core/random/bytes_spec.rb @@ -25,8 +25,6 @@ end end -ruby_version_is "2.6" do - describe "Random.bytes" do - it_behaves_like :random_bytes, :bytes, Random - end +describe "Random.bytes" do + it_behaves_like :random_bytes, :bytes, Random end diff --git a/ruby/spec/ruby/core/random/default_spec.rb b/ruby/spec/ruby/core/random/default_spec.rb index 1d8b1ce5e..db444d203 100644 --- a/ruby/spec/ruby/core/random/default_spec.rb +++ b/ruby/spec/ruby/core/random/default_spec.rb @@ -1,7 +1,37 @@ require_relative '../../spec_helper' describe "Random::DEFAULT" do - it "returns a Random instance" do - Random::DEFAULT.should be_an_instance_of(Random) + it "returns a random number generator" do + suppress_warning do + Random::DEFAULT.should respond_to(:rand) + end + end + + ruby_version_is ''...'3.0' do + it "returns a Random instance" do + suppress_warning do + Random::DEFAULT.should be_an_instance_of(Random) + end + end + end + + ruby_version_is '3.0' do + it "refers to the Random class" do + suppress_warning do + Random::DEFAULT.should.equal?(Random) + end + end + + it "is deprecated" do + -> { + Random::DEFAULT.should.equal?(Random) + }.should complain(/constant Random::DEFAULT is deprecated/) + end + end + + it "changes seed on reboot" do + seed1 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems') + seed2 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems') + seed1.should != seed2 end end diff --git a/ruby/spec/ruby/core/random/new_seed_spec.rb b/ruby/spec/ruby/core/random/new_seed_spec.rb index 4b34e871a..7a93da99a 100644 --- a/ruby/spec/ruby/core/random/new_seed_spec.rb +++ b/ruby/spec/ruby/core/random/new_seed_spec.rb @@ -1,8 +1,8 @@ require_relative '../../spec_helper' describe "Random.new_seed" do - it "returns a Bignum" do - Random.new_seed.should be_an_instance_of(Bignum) + it "returns an Integer" do + Random.new_seed.should be_an_instance_of(Integer) end it "returns an arbitrary seed value each time" do diff --git a/ruby/spec/ruby/core/random/new_spec.rb b/ruby/spec/ruby/core/random/new_spec.rb index 07d7b439c..4280b5b9c 100644 --- a/ruby/spec/ruby/core/random/new_spec.rb +++ b/ruby/spec/ruby/core/random/new_spec.rb @@ -4,7 +4,7 @@ end it "uses a random seed value if none is supplied" do - Random.new.seed.should be_an_instance_of(Bignum) + Random.new.seed.should be_an_instance_of(Integer) end it "returns Random instances initialized with different seeds" do diff --git a/ruby/spec/ruby/core/random/rand_spec.rb b/ruby/spec/ruby/core/random/rand_spec.rb index 0e423301f..6ea7eece5 100644 --- a/ruby/spec/ruby/core/random/rand_spec.rb +++ b/ruby/spec/ruby/core/random/rand_spec.rb @@ -51,7 +51,7 @@ describe "Random#rand with Fixnum" do it "returns an Integer" do - Random.new.rand(20).should be_an_instance_of(Fixnum) + Random.new.rand(20).should be_an_instance_of(Integer) end it "returns a Fixnum greater than or equal to 0" do @@ -95,7 +95,7 @@ describe "Random#rand with Bignum" do it "typically returns a Bignum" do rnd = Random.new(1) - 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Bignum) + 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Integer) end it "returns a Bignum greater than or equal to 0" do @@ -159,7 +159,7 @@ describe "Random#rand with Range" do it "returns an element from the Range" do - Random.new.rand(20..43).should be_an_instance_of(Fixnum) + Random.new.rand(20..43).should be_an_instance_of(Integer) end it "supports custom object types" do diff --git a/ruby/spec/ruby/core/random/random_number_spec.rb b/ruby/spec/ruby/core/random/random_number_spec.rb index 60a80ae1b..bad81aeff 100644 --- a/ruby/spec/ruby/core/random/random_number_spec.rb +++ b/ruby/spec/ruby/core/random/random_number_spec.rb @@ -4,7 +4,5 @@ describe "Random.random_number" do it_behaves_like :random_number, :random_number, Random.new - ruby_version_is "2.6" do - it_behaves_like :random_number, :random_number, Random - end + it_behaves_like :random_number, :random_number, Random end diff --git a/ruby/spec/ruby/core/random/raw_seed_spec.rb b/ruby/spec/ruby/core/random/raw_seed_spec.rb index c1a1eb1f4..0e40ed079 100644 --- a/ruby/spec/ruby/core/random/raw_seed_spec.rb +++ b/ruby/spec/ruby/core/random/raw_seed_spec.rb @@ -1,9 +1,6 @@ -# -*- encoding: binary -*- require_relative '../../spec_helper' require_relative 'shared/urandom' -ruby_version_is "2.5" do - describe "Random.urandom" do - it_behaves_like :random_urandom, :urandom - end +describe "Random.urandom" do + it_behaves_like :random_urandom, :urandom end diff --git a/ruby/spec/ruby/core/random/urandom_spec.rb b/ruby/spec/ruby/core/random/urandom_spec.rb deleted file mode 100644 index e27f83cdc..000000000 --- a/ruby/spec/ruby/core/random/urandom_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -# -*- encoding: binary -*- -require_relative '../../spec_helper' -require_relative 'shared/urandom' - -ruby_version_is ""..."2.5" do - describe "Random.raw_seed" do - it_behaves_like :random_urandom, :raw_seed - end -end diff --git a/ruby/spec/ruby/core/range/bsearch_spec.rb b/ruby/spec/ruby/core/range/bsearch_spec.rb index 009cafb00..438c7ce31 100644 --- a/ruby/spec/ruby/core/range/bsearch_spec.rb +++ b/ruby/spec/ruby/core/range/bsearch_spec.rb @@ -81,6 +81,19 @@ [1, 2].should include(result) end end + + it "returns nil for empty ranges" do + (0...0).bsearch { true }.should == nil + (0...0).bsearch { false }.should == nil + (0...0).bsearch { 1 }.should == nil + (0...0).bsearch { 0 }.should == nil + (0...0).bsearch { -1 }.should == nil + + (4..2).bsearch { true }.should == nil + (4..2).bsearch { 1 }.should == nil + (4..2).bsearch { 0 }.should == nil + (4..2).bsearch { -1 }.should == nil + end end context "with Float values" do @@ -94,13 +107,46 @@ end it "returns minimum element if the block returns true for every element" do - (-0.2..4.8).bsearch { |x| x < 4 }.should == -0.2 + (-0.2..4.8).bsearch { |x| x < 5 }.should == -0.2 end it "returns the smallest element for which block returns true" do (0..4.2).bsearch { |x| x >= 2 }.should == 2 (-1.2..4.3).bsearch { |x| x >= 1 }.should == 1 end + + it "returns a boundary element if appropriate" do + (1.0..3.0).bsearch { |x| x >= 3.0 }.should == 3.0 + (1.0...3.0).bsearch { |x| x >= 3.0.prev_float }.should == 3.0.prev_float + (1.0..3.0).bsearch { |x| x >= 1.0 }.should == 1.0 + (1.0...3.0).bsearch { |x| x >= 1.0 }.should == 1.0 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + (0..inf).bsearch { |x| x == inf }.should == inf + (0...inf).bsearch { |x| x == inf }.should == nil + (-inf..0).bsearch { |x| x != -inf }.should == -Float::MAX + (-inf...0).bsearch { |x| x != -inf }.should == -Float::MAX + (inf..inf).bsearch { |x| true }.should == inf + (inf...inf).bsearch { |x| true }.should == nil + (-inf..-inf).bsearch { |x| true }.should == -inf + (-inf...-inf).bsearch { |x| true }.should == nil + (inf..0).bsearch { true }.should == nil + (inf...0).bsearch { true }.should == nil + (0..-inf).bsearch { true }.should == nil + (0...-inf).bsearch { true }.should == nil + (inf..-inf).bsearch { true }.should == nil + (inf...-inf).bsearch { true }.should == nil + (0..inf).bsearch { |x| x >= 3 }.should == 3.0 + (0...inf).bsearch { |x| x >= 3 }.should == 3.0 + (-inf..0).bsearch { |x| x >= -3 }.should == -3.0 + (-inf...0).bsearch { |x| x >= -3 }.should == -3.0 + (-inf..inf).bsearch { |x| x >= 3 }.should == 3.0 + (-inf...inf).bsearch { |x| x >= 3 }.should == 3.0 + (0..inf).bsearch { |x| x >= Float::MAX }.should == Float::MAX + (0...inf).bsearch { |x| x >= Float::MAX }.should == Float::MAX + end end context "with a block returning negative, zero, positive numbers" do @@ -130,7 +176,262 @@ it "returns an element at an index for which block returns 0" do result = (0.1..4.9).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } result.should >= 1 - result.should <= 2 + result.should <= 3 + end + + it "returns an element at an index for which block returns 0 (small numbers)" do + result = (0.1..0.3).bsearch { |x| x < 0.1 ? 1 : x > 0.3 ? -1 : 0 } + result.should >= 0.1 + result.should <= 0.3 + end + + it "returns a boundary element if appropriate" do + (1.0..3.0).bsearch { |x| 3.0 - x }.should == 3.0 + (1.0...3.0).bsearch { |x| 3.0.prev_float - x }.should == 3.0.prev_float + (1.0..3.0).bsearch { |x| 1.0 - x }.should == 1.0 + (1.0...3.0).bsearch { |x| 1.0 - x }.should == 1.0 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + (0..inf).bsearch { |x| x == inf ? 0 : 1 }.should == inf + (0...inf).bsearch { |x| x == inf ? 0 : 1 }.should == nil + (-inf...0).bsearch { |x| x == -inf ? 0 : -1 }.should == -inf + (-inf..0).bsearch { |x| x == -inf ? 0 : -1 }.should == -inf + (inf..inf).bsearch { 0 }.should == inf + (inf...inf).bsearch { 0 }.should == nil + (-inf..-inf).bsearch { 0 }.should == -inf + (-inf...-inf).bsearch { 0 }.should == nil + (inf..0).bsearch { 0 }.should == nil + (inf...0).bsearch { 0 }.should == nil + (0..-inf).bsearch { 0 }.should == nil + (0...-inf).bsearch { 0 }.should == nil + (inf..-inf).bsearch { 0 }.should == nil + (inf...-inf).bsearch { 0 }.should == nil + (-inf..inf).bsearch { |x| 3 - x }.should == 3.0 + (-inf...inf).bsearch { |x| 3 - x }.should == 3.0 + (0...inf).bsearch { |x| x >= Float::MAX ? 0 : 1 }.should == Float::MAX + end + end + end + + context "with endless ranges and Integer values" do + context "with a block returning true or false" do + it "returns minimum element if the block returns true for every element" do + eval("(-2..)").bsearch { |x| true }.should == -2 + end + + it "returns the smallest element for which block returns true" do + eval("(0..)").bsearch { |x| x >= 2 }.should == 2 + eval("(-1..)").bsearch { |x| x >= 1 }.should == 1 + end + end + + context "with a block returning negative, zero, positive numbers" do + it "returns nil if the block returns less than zero for every element" do + eval("(0..)").bsearch { |x| -1 }.should be_nil + end + + it "returns nil if the block never returns zero" do + eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil + end + + it "accepts -Float::INFINITY from the block" do + eval("(0..)").bsearch { |x| -Float::INFINITY }.should be_nil + end + + it "returns an element at an index for which block returns 0.0" do + result = eval("(0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 } + result.should == 2 + end + + it "returns an element at an index for which block returns 0" do + result = eval("(0..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } + [1, 2, 3].should include(result) + end + end + end + + context "with endless ranges and Float values" do + context "with a block returning true or false" do + it "returns nil if the block returns false for every element" do + eval("(0.1..)").bsearch { |x| x < 0.0 }.should be_nil + eval("(0.1...)").bsearch { |x| x < 0.0 }.should be_nil + end + + it "returns nil if the block returns nil for every element" do + eval("(-0.0..)").bsearch { |x| nil }.should be_nil + eval("(-0.0...)").bsearch { |x| nil }.should be_nil + end + + it "returns minimum element if the block returns true for every element" do + eval("(-0.2..)").bsearch { |x| true }.should == -0.2 + eval("(-0.2...)").bsearch { |x| true }.should == -0.2 + end + + it "returns the smallest element for which block returns true" do + eval("(0..)").bsearch { |x| x >= 2 }.should == 2 + eval("(-1.2..)").bsearch { |x| x >= 1 }.should == 1 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + eval("(inf..)").bsearch { |x| true }.should == inf + eval("(inf...)").bsearch { |x| true }.should == nil + eval("(-inf..)").bsearch { |x| true }.should == -inf + eval("(-inf...)").bsearch { |x| true }.should == -inf + end + end + + context "with a block returning negative, zero, positive numbers" do + it "returns nil if the block returns less than zero for every element" do + eval("(-2.0..)").bsearch { |x| -1 }.should be_nil + eval("(-2.0...)").bsearch { |x| -1 }.should be_nil + end + + it "returns nil if the block returns greater than zero for every element" do + eval("(0.3..)").bsearch { |x| 1 }.should be_nil + eval("(0.3...)").bsearch { |x| 1 }.should be_nil + end + + it "returns nil if the block never returns zero" do + eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil + end + + it "accepts (+/-)Float::INFINITY from the block" do + eval("(0.1..)").bsearch { |x| Float::INFINITY }.should be_nil + eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should be_nil + end + + it "returns an element at an index for which block returns 0.0" do + result = eval("(0.0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 } + result.should == 2 + end + + it "returns an element at an index for which block returns 0" do + result = eval("(0.1..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } + result.should >= 1 + result.should <= 3 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + eval("(inf..)").bsearch { |x| 1 }.should == nil + eval("(inf...)").bsearch { |x| 1 }.should == nil + eval("(inf..)").bsearch { |x| x == inf ? 0 : 1 }.should == inf + eval("(inf...)").bsearch { |x| x == inf ? 0 : 1 }.should == nil + eval("(-inf..)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf + eval("(-inf...)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf + eval("(-inf..)").bsearch { |x| 3 - x }.should == 3 + eval("(-inf...)").bsearch { |x| 3 - x }.should == 3 + eval("(0.0...)").bsearch { 0 }.should != inf + end + end + end + + + ruby_version_is "2.7" do + context "with beginless ranges and Integer values" do + context "with a block returning true or false" do + it "returns the smallest element for which block returns true" do + eval("(..10)").bsearch { |x| x >= 2 }.should == 2 + eval("(...-1)").bsearch { |x| x >= -10 }.should == -10 + end + end + + context "with a block returning negative, zero, positive numbers" do + it "returns nil if the block returns greater than zero for every element" do + eval("(..0)").bsearch { |x| 1 }.should be_nil + end + + it "returns nil if the block never returns zero" do + eval("(..0)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil + end + + it "accepts Float::INFINITY from the block" do + eval("(..0)").bsearch { |x| Float::INFINITY }.should be_nil + end + + it "returns an element at an index for which block returns 0.0" do + result = eval("(..10)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 } + result.should == 2 + end + + it "returns an element at an index for which block returns 0" do + result = eval("(...10)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } + [1, 2, 3].should include(result) + end + end + end + + context "with beginless ranges and Float values" do + context "with a block returning true or false" do + it "returns nil if the block returns true for every element" do + eval("(..-0.1)").bsearch { |x| x > 0.0 }.should be_nil + eval("(...-0.1)").bsearch { |x| x > 0.0 }.should be_nil + end + + it "returns nil if the block returns nil for every element" do + eval("(..-0.1)").bsearch { |x| nil }.should be_nil + eval("(...-0.1)").bsearch { |x| nil }.should be_nil + end + + it "returns the smallest element for which block returns true" do + eval("(..10)").bsearch { |x| x >= 2 }.should == 2 + eval("(..10)").bsearch { |x| x >= 1 }.should == 1 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + eval("(..inf)").bsearch { |x| true }.should == -inf + eval("(...inf)").bsearch { |x| true }.should == -inf + eval("(..-inf)").bsearch { |x| true }.should == -inf + eval("(...-inf)").bsearch { |x| true }.should == nil + end + end + + context "with a block returning negative, zero, positive numbers" do + it "returns nil if the block returns less than zero for every element" do + eval("(..5.0)").bsearch { |x| -1 }.should be_nil + eval("(...5.0)").bsearch { |x| -1 }.should be_nil + end + + it "returns nil if the block returns greater than zero for every element" do + eval("(..1.1)").bsearch { |x| 1 }.should be_nil + eval("(...1.1)").bsearch { |x| 1 }.should be_nil + end + + it "returns nil if the block never returns zero" do + eval("(..6.3)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil + end + + it "accepts (+/-)Float::INFINITY from the block" do + eval("(..5.0)").bsearch { |x| Float::INFINITY }.should be_nil + eval("(..7.0)").bsearch { |x| -Float::INFINITY }.should be_nil + end + + it "returns an element at an index for which block returns 0.0" do + result = eval("(..8.0)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 } + result.should == 2 + end + + it "returns an element at an index for which block returns 0" do + result = eval("(..8.0)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } + result.should >= 1 + result.should <= 3 + end + + it "works with infinity bounds" do + inf = Float::INFINITY + eval("(..-inf)").bsearch { |x| 1 }.should == nil + eval("(...-inf)").bsearch { |x| 1 }.should == nil + eval("(..inf)").bsearch { |x| x == inf ? 0 : 1 }.should == inf + eval("(...inf)").bsearch { |x| x == inf ? 0 : 1 }.should == nil + eval("(..-inf)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf + eval("(...-inf)").bsearch { |x| x == -inf ? 0 : -1 }.should == nil + eval("(..inf)").bsearch { |x| 3 - x }.should == 3 + eval("(...inf)").bsearch { |x| 3 - x }.should == 3 + end end end end diff --git a/ruby/spec/ruby/core/range/case_compare_spec.rb b/ruby/spec/ruby/core/range/case_compare_spec.rb index 0ca03f6a3..e79502623 100644 --- a/ruby/spec/ruby/core/range/case_compare_spec.rb +++ b/ruby/spec/ruby/core/range/case_compare_spec.rb @@ -3,26 +3,13 @@ require_relative 'shared/cover' describe "Range#===" do - ruby_version_is ""..."2.6" do - it "returns the result of calling #include? on self" do - range = 0...10 - range.should_receive(:include?).with(2).and_return(:true) - (range === 2).should == :true - end - - it "requires #succ method to be implemented" do - range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10) - - -> do - range === RangeSpecs::WithoutSucc.new(2) - end.should raise_error(TypeError, /can't iterate from/) - end + it "returns the result of calling #cover? on self" do + range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10) + (range === RangeSpecs::WithoutSucc.new(2)).should == true end - ruby_version_is "2.6" do - it "returns the result of calling #cover? on self" do - range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10) - (range === RangeSpecs::WithoutSucc.new(2)).should == true - end + ruby_version_is "2.7" do + it_behaves_like :range_cover_and_include, :=== + it_behaves_like :range_cover, :=== end end diff --git a/ruby/spec/ruby/core/range/count_spec.rb b/ruby/spec/ruby/core/range/count_spec.rb new file mode 100644 index 000000000..f6f60fa05 --- /dev/null +++ b/ruby/spec/ruby/core/range/count_spec.rb @@ -0,0 +1,14 @@ +require_relative '../../spec_helper' + +describe "Range#count" do + ruby_version_is "2.7" do + it "returns Infinity for beginless ranges without arguments or blocks" do + inf = Float::INFINITY + eval("('a'...)").count.should == inf + eval("(7..)").count.should == inf + eval("(...'a')").count.should == inf + eval("(...nil)").count.should == inf + eval("(..10.0)").count.should == inf + end + end +end diff --git a/ruby/spec/ruby/core/range/cover_spec.rb b/ruby/spec/ruby/core/range/cover_spec.rb index 29c0e0bfa..fa881607e 100644 --- a/ruby/spec/ruby/core/range/cover_spec.rb +++ b/ruby/spec/ruby/core/range/cover_spec.rb @@ -6,4 +6,5 @@ describe "Range#cover?" do it_behaves_like :range_cover_and_include, :cover? it_behaves_like :range_cover, :cover? + it_behaves_like :range_cover_subrange, :cover? end diff --git a/ruby/spec/ruby/core/range/dup_spec.rb b/ruby/spec/ruby/core/range/dup_spec.rb index d1c029c6b..6c9d0c954 100644 --- a/ruby/spec/ruby/core/range/dup_spec.rb +++ b/ruby/spec/ruby/core/range/dup_spec.rb @@ -5,11 +5,11 @@ copy = (1..3).dup copy.begin.should == 1 copy.end.should == 3 - copy.exclude_end?.should == false + copy.should_not.exclude_end? copy = ("a"..."z").dup copy.begin.should == "a" copy.end.should == "z" - copy.exclude_end?.should == true + copy.should.exclude_end? end end diff --git a/ruby/spec/ruby/core/range/each_spec.rb b/ruby/spec/ruby/core/range/each_spec.rb index 110b0602d..6b33f5773 100644 --- a/ruby/spec/ruby/core/range/each_spec.rb +++ b/ruby/spec/ruby/core/range/each_spec.rb @@ -32,6 +32,38 @@ a.should == [x, y] end + it "works for non-ASCII ranges" do + a = [] + ('Σ'..'Ω').each { |i| a << i } + a.should == ["Σ", "Τ", "Î¥", "Φ", "Χ", "Ψ", "Ω"] + end + + it "works with endless ranges" do + a = [] + eval("(-2..)").each { |x| break if x > 2; a << x } + a.should == [-2, -1, 0, 1, 2] + + a = [] + eval("(-2...)").each { |x| break if x > 2; a << x } + a.should == [-2, -1, 0, 1, 2] + end + + it "works with String endless ranges" do + a = [] + eval("('A'..)").each { |x| break if x > "D"; a << x } + a.should == ["A", "B", "C", "D"] + + a = [] + eval("('A'...)").each { |x| break if x > "D"; a << x } + a.should == ["A", "B", "C", "D"] + end + + ruby_version_is "2.7" do + it "raises a TypeError beginless ranges" do + -> { eval("(..2)").each { |x| x } }.should raise_error(TypeError) + end + end + it "raises a TypeError if the first element does not respond to #succ" do -> { (0.5..2.4).each { |i| i } }.should raise_error(TypeError) @@ -52,9 +84,27 @@ enum.to_a.should == [1, 2, 3] end - it "raises a TypeError if the first element is a Time object" do - t = Time.now - -> { (t..t+1).each { |i| i } }.should raise_error(TypeError) + ruby_version_is "3.1" do + it "supports Time objects that respond to #succ" do + t = Time.utc(1970) + def t.succ; self + 1 end + t_succ = t.succ + def t_succ.succ; self + 1; end + + (t..t_succ).to_a.should == [Time.utc(1970), Time.utc(1970, nil, nil, nil, nil, 1)] + (t...t_succ).to_a.should == [Time.utc(1970)] + end + end + + ruby_version_is ""..."3.1" do + it "raises a TypeError if the first element is a Time object even if it responds to #succ" do + t = Time.utc(1970) + def t.succ; self + 1 end + t_succ = t.succ + def t_succ.succ; self + 1; end + + -> { (t..t_succ).each { |i| i } }.should raise_error(TypeError) + end end it "passes each Symbol element by using #succ" do diff --git a/ruby/spec/ruby/core/range/equal_value_spec.rb b/ruby/spec/ruby/core/range/equal_value_spec.rb index 889557fc2..0aaebfb59 100644 --- a/ruby/spec/ruby/core/range/equal_value_spec.rb +++ b/ruby/spec/ruby/core/range/equal_value_spec.rb @@ -7,4 +7,14 @@ it "returns true if the endpoints are ==" do (0..1).should == (0..1.0) end + + it "returns true if the endpoints are == for endless ranges" do + eval("(1.0..)").should == eval("(1.0..)") + end + + ruby_version_is "2.7" do + it "returns true if the endpoints are == for beginless ranges" do + eval("(...10)").should == eval("(...10)") + end + end end diff --git a/ruby/spec/ruby/core/range/exclude_end_spec.rb b/ruby/spec/ruby/core/range/exclude_end_spec.rb index a209603d1..c4006fea7 100644 --- a/ruby/spec/ruby/core/range/exclude_end_spec.rb +++ b/ruby/spec/ruby/core/range/exclude_end_spec.rb @@ -2,18 +2,18 @@ describe "Range#exclude_end?" do it "returns false if the range does not exclude the end value" do - (-2..2).exclude_end?.should == false - ('A'..'B').exclude_end?.should == false - (0.5..2.4).exclude_end?.should == false - (0xfffd..0xffff).exclude_end?.should == false - Range.new(0, 1).exclude_end?.should == false + (-2..2).should_not.exclude_end? + ('A'..'B').should_not.exclude_end? + (0.5..2.4).should_not.exclude_end? + (0xfffd..0xffff).should_not.exclude_end? + Range.new(0, 1).should_not.exclude_end? end it "returns true if the range excludes the end value" do - (0...5).exclude_end?.should == true - ('A'...'B').exclude_end?.should == true - (0.5...2.4).exclude_end?.should == true - (0xfffd...0xffff).exclude_end?.should == true - Range.new(0, 1, true).exclude_end?.should == true + (0...5).should.exclude_end? + ('A'...'B').should.exclude_end? + (0.5...2.4).should.exclude_end? + (0xfffd...0xffff).should.exclude_end? + Range.new(0, 1, true).should.exclude_end? end end diff --git a/ruby/spec/ruby/core/range/first_spec.rb b/ruby/spec/ruby/core/range/first_spec.rb index 5f073b48e..c5c90800a 100644 --- a/ruby/spec/ruby/core/range/first_spec.rb +++ b/ruby/spec/ruby/core/range/first_spec.rb @@ -46,4 +46,10 @@ it "raises a TypeError when passed a String" do -> { (2..3).first("1") }.should raise_error(TypeError) end + + ruby_version_is "2.7" do + it "raises a RangeError when called on an beginless range" do + -> { eval("(..1)").first }.should raise_error(RangeError) + end + end end diff --git a/ruby/spec/ruby/core/range/hash_spec.rb b/ruby/spec/ruby/core/range/hash_spec.rb index 90aeee789..4f2681e86 100644 --- a/ruby/spec/ruby/core/range/hash_spec.rb +++ b/ruby/spec/ruby/core/range/hash_spec.rb @@ -14,11 +14,11 @@ (0..10).hash.should_not == (0...10).hash end - it "generates a Fixnum for the hash value" do - (0..0).hash.should be_an_instance_of(Fixnum) - (0..1).hash.should be_an_instance_of(Fixnum) - (0...10).hash.should be_an_instance_of(Fixnum) - (0..10).hash.should be_an_instance_of(Fixnum) + it "generates an Integer for the hash value" do + (0..0).hash.should be_an_instance_of(Integer) + (0..1).hash.should be_an_instance_of(Integer) + (0...10).hash.should be_an_instance_of(Integer) + (0..10).hash.should be_an_instance_of(Integer) end end diff --git a/ruby/spec/ruby/core/range/initialize_spec.rb b/ruby/spec/ruby/core/range/initialize_spec.rb index 8caf12baa..8a6ca65da 100644 --- a/ruby/spec/ruby/core/range/initialize_spec.rb +++ b/ruby/spec/ruby/core/range/initialize_spec.rb @@ -27,9 +27,18 @@ -> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should raise_error(ArgumentError) end - it "raises a NameError if called on an already initialized Range" do - -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError) - -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError) + ruby_version_is ""..."3.0" do + it "raises a NameError if called on an already initialized Range" do + -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError) + -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError) + end + end + + ruby_version_is "3.0" do + it "raises a FrozenError if called on an already initialized Range" do + -> { (0..1).send(:initialize, 1, 3) }.should raise_error(FrozenError) + -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError) + end end it "raises an ArgumentError if arguments don't respond to <=>" do diff --git a/ruby/spec/ruby/core/range/inspect_spec.rb b/ruby/spec/ruby/core/range/inspect_spec.rb index 837f7e69a..f49882e6c 100644 --- a/ruby/spec/ruby/core/range/inspect_spec.rb +++ b/ruby/spec/ruby/core/range/inspect_spec.rb @@ -12,6 +12,23 @@ (0.5..2.4).inspect.should == "0.5..2.4" end + it "works for endless ranges" do + eval("(1..)").inspect.should == "1.." + eval("(0.1...)").inspect.should == "0.1..." + end + + ruby_version_is '2.7' do + it "works for beginless ranges" do + eval("(..1)").inspect.should == "..1" + eval("(...0.1)").inspect.should == "...0.1" + end + + it "works for nil ... nil ranges" do + eval("(..nil)").inspect.should == "nil..nil" + eval("(nil...)").inspect.should == "nil...nil" + end + end + ruby_version_is ''...'2.7' do it "returns a tainted string if either end is tainted" do (("a".taint)..."c").inspect.tainted?.should be_true diff --git a/ruby/spec/ruby/core/range/last_spec.rb b/ruby/spec/ruby/core/range/last_spec.rb index c7e629e62..d7ef776b4 100644 --- a/ruby/spec/ruby/core/range/last_spec.rb +++ b/ruby/spec/ruby/core/range/last_spec.rb @@ -46,4 +46,8 @@ it "raises a TypeError when passed a String" do -> { (2..3).last("1") }.should raise_error(TypeError) end + + it "raises a RangeError when called on an endless range" do + -> { eval("(1..)").last }.should raise_error(RangeError) + end end diff --git a/ruby/spec/ruby/core/range/max_spec.rb b/ruby/spec/ruby/core/range/max_spec.rb index faac0a203..a970144d6 100644 --- a/ruby/spec/ruby/core/range/max_spec.rb +++ b/ruby/spec/ruby/core/range/max_spec.rb @@ -45,6 +45,23 @@ time_end = Time.now + 1.0 -> { (time_start...time_end).max }.should raise_error(TypeError) end + + it "raises RangeError when called on an endless range" do + -> { eval("(1..)").max }.should raise_error(RangeError) + end + + ruby_version_is "3.0" do + it "returns the end point for beginless ranges" do + eval("(..1)").max.should == 1 + eval("(..1.0)").max.should == 1.0 + end + + it "raises for an exclusive beginless range" do + -> { + eval("(...1)").max + }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value') + end + end end describe "Range#max given a block" do @@ -79,4 +96,10 @@ ('z'..'l').max {|x,y| x <=> y}.should be_nil (5...5).max {|x,y| x <=> y}.should be_nil end + + ruby_version_is "2.7" do + it "raises RangeError when called with custom comparison method on an beginless range" do + -> { eval("(..1)").max {|a, b| a} }.should raise_error(RangeError) + end + end end diff --git a/ruby/spec/ruby/core/range/min_spec.rb b/ruby/spec/ruby/core/range/min_spec.rb index 424bd1dc8..6e56cc733 100644 --- a/ruby/spec/ruby/core/range/min_spec.rb +++ b/ruby/spec/ruby/core/range/min_spec.rb @@ -38,6 +38,17 @@ time_end = Time.now + 1.0 (time_start...time_end).min.should equal(time_start) end + + it "returns the start point for endless ranges" do + eval("(1..)").min.should == 1 + eval("(1.0...)").min.should == 1.0 + end + + ruby_version_is "2.7" do + it "raises RangeError when called on an beginless range" do + -> { eval("(..1)").min }.should raise_error(RangeError) + end + end end describe "Range#min given a block" do @@ -72,4 +83,8 @@ ('z'..'l').min {|x,y| x <=> y}.should be_nil (7...7).min {|x,y| x <=> y}.should be_nil end + + it "raises RangeError when called with custom comparison method on an endless range" do + -> { eval("(1..)").min {|a, b| a} }.should raise_error(RangeError) + end end diff --git a/ruby/spec/ruby/core/range/minmax_spec.rb b/ruby/spec/ruby/core/range/minmax_spec.rb new file mode 100644 index 000000000..1db9bfce3 --- /dev/null +++ b/ruby/spec/ruby/core/range/minmax_spec.rb @@ -0,0 +1,170 @@ +require_relative '../../spec_helper' + +# These specs use Range.new instead of the literal notation for beginless Ranges so they parse fine on Ruby < 2.7 +describe 'Range#minmax' do + before(:each) do + @x = mock('x') + @y = mock('y') + + @x.should_receive(:<=>).with(@y).any_number_of_times.and_return(-1) # x < y + @x.should_receive(:<=>).with(@x).any_number_of_times.and_return(0) # x == x + @y.should_receive(:<=>).with(@x).any_number_of_times.and_return(1) # y > x + @y.should_receive(:<=>).with(@y).any_number_of_times.and_return(0) # y == y + end + + describe 'on an inclusive range' do + ruby_version_is ''...'2.7' do + it 'should try to iterate endlessly on an endless range' do + @x.should_receive(:succ).once.and_return(@y) + range = (@x..) + + -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/) + end + end + + ruby_version_is '2.7' do + it 'should raise RangeError on an endless range without iterating the range' do + @x.should_not_receive(:succ) + + range = (@x..) + + -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range') + end + + it 'raises RangeError or ArgumentError on a beginless range' do + range = Range.new(nil, @x) + + -> { range.minmax }.should raise_error(StandardError) { |e| + if RangeError === e + # error from #min + -> { raise e }.should raise_error(RangeError, 'cannot get the minimum of beginless range') + else + # error from #max + -> { raise e }.should raise_error(ArgumentError, 'comparison of NilClass with MockObject failed') + end + } + end + end + + it 'should return beginning of range if beginning and end are equal without iterating the range' do + @x.should_not_receive(:succ) + + (@x..@x).minmax.should == [@x, @x] + end + + it 'should return nil pair if beginning is greater than end without iterating the range' do + @y.should_not_receive(:succ) + + (@y..@x).minmax.should == [nil, nil] + end + + ruby_version_is ''...'2.7' do + it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do + @x.should_receive(:succ).once.and_return(@y) + + (@x..@y).minmax.should == [@x, @y] + end + end + + ruby_version_is '2.7' do + it 'should return the minimum and maximum values for a non-numeric range without iterating the range' do + @x.should_not_receive(:succ) + + (@x..@y).minmax.should == [@x, @y] + end + end + + it 'should return the minimum and maximum values for a numeric range' do + (1..3).minmax.should == [1, 3] + end + + ruby_version_is '2.7' do + it 'should return the minimum and maximum values for a numeric range without iterating the range' do + # We cannot set expectations on integers, + # so we "prevent" iteration by picking a value that would iterate until the spec times out. + range_end = Float::INFINITY + + (1..range_end).minmax.should == [1, range_end] + end + end + + it 'should return the minimum and maximum values according to the provided block by iterating the range' do + @x.should_receive(:succ).once.and_return(@y) + + (@x..@y).minmax { |x, y| - (x <=> y) }.should == [@y, @x] + end + end + + describe 'on an exclusive range' do + ruby_version_is ''...'2.7' do + # Endless ranges introduced in 2.6 + it 'should try to iterate endlessly on an endless range' do + @x.should_receive(:succ).once.and_return(@y) + range = (@x...) + + -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/) + end + end + + ruby_version_is '2.7' do + it 'should raise RangeError on an endless range' do + @x.should_not_receive(:succ) + range = (@x...) + + -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range') + end + + it 'should raise RangeError on a beginless range' do + range = Range.new(nil, @x, true) + + -> { range.minmax }.should raise_error(RangeError, + /cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/) + end + end + + ruby_bug "#17014", "2.7.0"..."3.0" do + it 'should return nil pair if beginning and end are equal without iterating the range' do + @x.should_not_receive(:succ) + + (@x...@x).minmax.should == [nil, nil] + end + + it 'should return nil pair if beginning is greater than end without iterating the range' do + @y.should_not_receive(:succ) + + (@y...@x).minmax.should == [nil, nil] + end + + it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do + @x.should_receive(:succ).once.and_return(@y) + + (@x...@y).minmax.should == [@x, @x] + end + end + + it 'should return the minimum and maximum values for a numeric range' do + (1...3).minmax.should == [1, 2] + end + + ruby_version_is '2.7' do + it 'should return the minimum and maximum values for a numeric range without iterating the range' do + # We cannot set expectations on integers, + # so we "prevent" iteration by picking a value that would iterate until the spec times out. + range_end = bignum_value + + (1...range_end).minmax.should == [1, range_end - 1] + end + + it 'raises TypeError if the end value is not an integer' do + range = (0...Float::INFINITY) + -> { range.minmax }.should raise_error(TypeError, 'cannot exclude non Integer end value') + end + end + + it 'should return the minimum and maximum values according to the provided block by iterating the range' do + @x.should_receive(:succ).once.and_return(@y) + + (@x...@y).minmax { |x, y| - (x <=> y) }.should == [@x, @x] + end + end +end diff --git a/ruby/spec/ruby/core/range/new_spec.rb b/ruby/spec/ruby/core/range/new_spec.rb index 9ed2b65d5..a4de4963e 100644 --- a/ruby/spec/ruby/core/range/new_spec.rb +++ b/ruby/spec/ruby/core/range/new_spec.rb @@ -33,14 +33,12 @@ -> { Range.new(a, b) }.should raise_error(ArgumentError) end - ruby_version_is "2.5" do - it "does not rescue exception raised in #<=> when compares the given start and end" do - b = mock('a') - a = mock('b') - a.should_receive(:<=>).with(b).and_raise(RangeSpecs::ComparisonError) + it "does not rescue exception raised in #<=> when compares the given start and end" do + b = mock('a') + a = mock('b') + a.should_receive(:<=>).with(b).and_raise(RangeSpecs::ComparisonError) - -> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError) - end + -> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError) end describe "beginless/endless range" do @@ -64,24 +62,16 @@ end end - ruby_version_is ""..."2.6" do - it "does not allow range without right boundary" do - -> { Range.new(1, nil) }.should raise_error(ArgumentError, /bad value for range/) - end + it "allows endless right boundary" do + range = Range.new(1, nil) + range.end.should == nil end - ruby_version_is "2.6" do - it "allows endless right boundary" do - range = Range.new(1, nil) - range.end.should == nil - end + it "distinguishes ranges with included and excluded right boundary" do + range_exclude = Range.new(1, nil, true) + range_include = Range.new(1, nil, false) - it "distinguishes ranges with included and excluded right boundary" do - range_exclude = Range.new(1, nil, true) - range_include = Range.new(1, nil, false) - - range_exclude.should_not == range_include - end + range_exclude.should_not == range_include end end end diff --git a/ruby/spec/ruby/core/range/percent_spec.rb b/ruby/spec/ruby/core/range/percent_spec.rb index 41badd4f7..5ec6770dd 100644 --- a/ruby/spec/ruby/core/range/percent_spec.rb +++ b/ruby/spec/ruby/core/range/percent_spec.rb @@ -1,18 +1,16 @@ require_relative '../../spec_helper' -ruby_version_is "2.6" do - describe "Range#%" do - it "works as a Range#step" do - aseq = (1..10) % 2 - aseq.class.should == Enumerator::ArithmeticSequence - aseq.begin.should == 1 - aseq.end.should == 10 - aseq.step.should == 2 - aseq.to_a.should == [1, 3, 5, 7, 9] - end +describe "Range#%" do + it "works as a Range#step" do + aseq = (1..10) % 2 + aseq.class.should == Enumerator::ArithmeticSequence + aseq.begin.should == 1 + aseq.end.should == 10 + aseq.step.should == 2 + aseq.to_a.should == [1, 3, 5, 7, 9] + end - it "produces an arithmetic sequence with a percent sign in #inspect" do - ((1..10) % 2).inspect.should == "((1..10).%(2))" - end + it "produces an arithmetic sequence with a percent sign in #inspect" do + ((1..10) % 2).inspect.should == "((1..10).%(2))" end end diff --git a/ruby/spec/ruby/core/range/shared/cover.rb b/ruby/spec/ruby/core/range/shared/cover.rb index 33d416fef..f3c7d2266 100644 --- a/ruby/spec/ruby/core/range/shared/cover.rb +++ b/ruby/spec/ruby/core/range/shared/cover.rb @@ -90,64 +90,106 @@ end end end +end - ruby_version_is "2.6" do - context "range argument" do - it "accepts range argument" do - (0..10).send(@method, (3..7)).should be_true - (0..10).send(@method, (3..15)).should be_false - (0..10).send(@method, (-2..7)).should be_false - - (1.1..7.9).send(@method, (2.5..6.5)).should be_true - (1.1..7.9).send(@method, (2.5..8.5)).should be_false - (1.1..7.9).send(@method, (0.5..6.5)).should be_false - - ('c'..'i').send(@method, ('d'..'f')).should be_true - ('c'..'i').send(@method, ('d'..'z')).should be_false - ('c'..'i').send(@method, ('a'..'f')).should be_false - - range_10_100 = RangeSpecs::TenfoldSucc.new(10)..RangeSpecs::TenfoldSucc.new(100) - range_20_90 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(90) - range_20_110 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(110) - range_0_90 = RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(90) - - range_10_100.send(@method, range_20_90).should be_true - range_10_100.send(@method, range_20_110).should be_false - range_10_100.send(@method, range_0_90).should be_false - end +describe :range_cover_subrange, shared: true do + context "range argument" do + it "accepts range argument" do + (0..10).send(@method, (3..7)).should be_true + (0..10).send(@method, (3..15)).should be_false + (0..10).send(@method, (-2..7)).should be_false + + (1.1..7.9).send(@method, (2.5..6.5)).should be_true + (1.1..7.9).send(@method, (2.5..8.5)).should be_false + (1.1..7.9).send(@method, (0.5..6.5)).should be_false + + ('c'..'i').send(@method, ('d'..'f')).should be_true + ('c'..'i').send(@method, ('d'..'z')).should be_false + ('c'..'i').send(@method, ('a'..'f')).should be_false + + range_10_100 = RangeSpecs::TenfoldSucc.new(10)..RangeSpecs::TenfoldSucc.new(100) + range_20_90 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(90) + range_20_110 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(110) + range_0_90 = RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(90) + + range_10_100.send(@method, range_20_90).should be_true + range_10_100.send(@method, range_20_110).should be_false + range_10_100.send(@method, range_0_90).should be_false + end - it "supports boundaries of different comparable types" do - (0..10).send(@method, (3.1..7.9)).should be_true - (0..10).send(@method, (3.1..15.9)).should be_false - (0..10).send(@method, (-2.1..7.9)).should be_false - end + it "supports boundaries of different comparable types" do + (0..10).send(@method, (3.1..7.9)).should be_true + (0..10).send(@method, (3.1..15.9)).should be_false + (0..10).send(@method, (-2.1..7.9)).should be_false + end - it "returns false if types are not comparable" do - (0..10).send(@method, ('a'..'z')).should be_false - (0..10).send(@method, (RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(100))).should be_false - end + it "returns false if types are not comparable" do + (0..10).send(@method, ('a'..'z')).should be_false + (0..10).send(@method, (RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(100))).should be_false + end - it "honors exclusion of right boundary (:exclude_end option)" do - # Integer - (0..10).send(@method, (0..10)).should be_true - (0...10).send(@method, (0...10)).should be_true + it "honors exclusion of right boundary (:exclude_end option)" do + # Integer + (0..10).send(@method, (0..10)).should be_true + (0...10).send(@method, (0...10)).should be_true - (0..10).send(@method, (0...10)).should be_true - (0...10).send(@method, (0..10)).should be_false + (0..10).send(@method, (0...10)).should be_true + (0...10).send(@method, (0..10)).should be_false - (0...11).send(@method, (0..10)).should be_true - (0..10).send(@method, (0...11)).should be_true + (0...11).send(@method, (0..10)).should be_true + (0..10).send(@method, (0...11)).should be_true - # Float - (0..10.1).send(@method, (0..10.1)).should be_true - (0...10.1).send(@method, (0...10.1)).should be_true + # Float + (0..10.1).send(@method, (0..10.1)).should be_true + (0...10.1).send(@method, (0...10.1)).should be_true - (0..10.1).send(@method, (0...10.1)).should be_true - (0...10.1).send(@method, (0..10.1)).should be_false + (0..10.1).send(@method, (0...10.1)).should be_true + (0...10.1).send(@method, (0..10.1)).should be_false - (0...11.1).send(@method, (0..10.1)).should be_true - (0..10.1).send(@method, (0...11.1)).should be_false - end + (0...11.1).send(@method, (0..10.1)).should be_true + (0..10.1).send(@method, (0...11.1)).should be_false + end + end + + ruby_version_is "2.7" do + it "allows self to be a beginless range" do + eval("(...10)").send(@method, (3..7)).should be_true + eval("(...10)").send(@method, (3..15)).should be_false + + eval("(..7.9)").send(@method, (2.5..6.5)).should be_true + eval("(..7.9)").send(@method, (2.5..8.5)).should be_false + + eval("(..'i')").send(@method, ('d'..'f')).should be_true + eval("(..'i')").send(@method, ('d'..'z')).should be_false + end + + it "allows self to be a endless range" do + eval("(0...)").send(@method, (3..7)).should be_true + eval("(5...)").send(@method, (3..15)).should be_false + + eval("(1.1..)").send(@method, (2.5..6.5)).should be_true + eval("(3.3..)").send(@method, (2.5..8.5)).should be_false + + eval("('a'..)").send(@method, ('d'..'f')).should be_true + eval("('p'..)").send(@method, ('d'..'z')).should be_false + end + + it "accepts beginless range argument" do + eval("(..10)").send(@method, eval("(...10)")).should be_true + (0..10).send(@method, eval("(...10)")).should be_false + + (1.1..7.9).send(@method, eval("(...10.5)")).should be_false + + ('c'..'i').send(@method, eval("(..'i')")).should be_false + end + + it "accepts endless range argument" do + eval("(0..)").send(@method, eval("(0...)")).should be_true + (0..10).send(@method, eval("(0...)")).should be_false + + (1.1..7.9).send(@method, eval("(0.8...)")).should be_false + + ('c'..'i').send(@method, eval("('a'..)")).should be_false end end end diff --git a/ruby/spec/ruby/core/range/shared/cover_and_include.rb b/ruby/spec/ruby/core/range/shared/cover_and_include.rb index a19e2c6ea..e978e39af 100644 --- a/ruby/spec/ruby/core/range/shared/cover_and_include.rb +++ b/ruby/spec/ruby/core/range/shared/cover_and_include.rb @@ -19,6 +19,18 @@ (0.5...2.4).send(@method, 2.4).should == false end + it "returns true if other is an element of self for endless ranges" do + eval("(1..)").send(@method, 2.4).should == true + eval("(0.5...)").send(@method, 2.4).should == true + end + + ruby_version_is "2.7" do + it "returns true if other is an element of self for beginless ranges" do + eval("(..10)").send(@method, 2.4).should == true + eval("(...10.5)").send(@method, 2.4).should == true + end + end + it "compares values using <=>" do rng = (1..5) m = mock("int") diff --git a/ruby/spec/ruby/core/range/shared/equal_value.rb b/ruby/spec/ruby/core/range/shared/equal_value.rb index 9d8bb1335..363c6be55 100644 --- a/ruby/spec/ruby/core/range/shared/equal_value.rb +++ b/ruby/spec/ruby/core/range/shared/equal_value.rb @@ -42,4 +42,10 @@ b = RangeSpecs::MyRange.new(RangeSpecs::Xs.new(3), RangeSpecs::Xs.new(5)) a.send(@method, b).should == true end + + it "works for endless Ranges" do + eval("(1..)").send(@method, eval("(1..)")).should == true + eval("(0.5...)").send(@method, eval("(0.5...)")).should == true + eval("(1..)").send(@method, eval("(1...)")).should == false + end end diff --git a/ruby/spec/ruby/core/range/size_spec.rb b/ruby/spec/ruby/core/range/size_spec.rb index 09759940d..0019c5ff0 100644 --- a/ruby/spec/ruby/core/range/size_spec.rb +++ b/ruby/spec/ruby/core/range/size_spec.rb @@ -24,6 +24,25 @@ (-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY end + it 'returns Float::INFINITY for endless ranges if the start is numeric' do + eval("(1..)").size.should == Float::INFINITY + eval("(0.5...)").size.should == Float::INFINITY + end + + it 'returns nil for endless ranges if the start is not numeric' do + eval("('z'..)").size.should == nil + eval("([]...)").size.should == nil + end + + ruby_version_is "2.7" do + it 'returns Float::INFINITY for all beginless ranges' do + eval("(..1)").size.should == Float::INFINITY + eval("(...0.5)").size.should == Float::INFINITY + eval("(..nil)").size.should == Float::INFINITY + eval("(...'o')").size.should == Float::INFINITY + end + end + it "returns nil if first and last are not Numeric" do (:a..:z).size.should be_nil ('a'..'z').size.should be_nil diff --git a/ruby/spec/ruby/core/range/step_spec.rb b/ruby/spec/ruby/core/range/step_spec.rb index d564e4a5c..4c6907385 100644 --- a/ruby/spec/ruby/core/range/step_spec.rb +++ b/ruby/spec/ruby/core/range/step_spec.rb @@ -209,8 +209,16 @@ it "returns Float values of 'step * n + begin < end'" do (1.0...6.4).step(1.8) { |x| ScratchPad << x } - (1.0...55.6).step(18.2) { |x| ScratchPad << x } - ScratchPad.recorded.should eql([1.0, 2.8, 4.6, 1.0, 19.2, 37.4]) + ScratchPad.recorded.should eql([1.0, 2.8, 4.6]) + end + + ruby_version_is '3.1' do + it "correctly handles values near the upper limit" do # https://bugs.ruby-lang.org/issues/16612 + (1.0...55.6).step(18.2) { |x| ScratchPad << x } + ScratchPad.recorded.should eql([1.0, 19.2, 37.4, 55.599999999999994]) + + (1.0...55.6).step(18.2).size.should == 4 + end end it "handles infinite values at either end" do @@ -274,41 +282,139 @@ end end + describe "with an endless range" do + describe "and Integer values" do + it "yield Integer values incremented by 1 when not passed a step" do + eval("(-2..)").step { |x| break if x > 2; ScratchPad << x } + ScratchPad.recorded.should eql([-2, -1, 0, 1, 2]) + + ScratchPad.record [] + eval("(-2...)").step { |x| break if x > 2; ScratchPad << x } + ScratchPad.recorded.should eql([-2, -1, 0, 1, 2]) + end + + it "yields Integer values incremented by an Integer step" do + eval("(-5..)").step(2) { |x| break if x > 3; ScratchPad << x } + ScratchPad.recorded.should eql([-5, -3, -1, 1, 3]) + + ScratchPad.record [] + eval("(-5...)").step(2) { |x| break if x > 3; ScratchPad << x } + ScratchPad.recorded.should eql([-5, -3, -1, 1, 3]) + end + + it "yields Float values incremented by a Float step" do + eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x } + ScratchPad.recorded.should eql([-2.0, -0.5, 1.0]) + + ScratchPad.record [] + eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x } + ScratchPad.recorded.should eql([-2.0, -0.5, 1.0]) + end + end + + describe "and Float values" do + it "yields Float values incremented by 1 and less than end when not passed a step" do + eval("(-2.0..)").step { |x| break if x > 1.5; ScratchPad << x } + ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0]) + + ScratchPad.record [] + eval("(-2.0...)").step { |x| break if x > 1.5; ScratchPad << x } + ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0]) + end + + it "yields Float values incremented by an Integer step" do + eval("(-5.0..)").step(2) { |x| break if x > 3.5; ScratchPad << x } + ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0]) + + ScratchPad.record [] + eval("(-5.0...)").step(2) { |x| break if x > 3.5; ScratchPad << x } + ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0]) + end + + it "yields Float values incremented by a Float step" do + eval("(-1.0..)").step(0.5) { |x| break if x > 0.6; ScratchPad << x } + ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5]) + + ScratchPad.record [] + eval("(-1.0...)").step(0.5) { |x| break if x > 0.6; ScratchPad << x } + ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5]) + end + + it "handles infinite values at the start" do + eval("(-Float::INFINITY..)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 } + ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY]) + + ScratchPad.record [] + eval("(-Float::INFINITY...)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 } + ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY]) + end + end + + describe "and String values" do + it "yields String values incremented by #succ and less than or equal to end when not passed a step" do + eval("('A'..)").step { |x| break if x > "D"; ScratchPad << x } + ScratchPad.recorded.should == ["A", "B", "C", "D"] + + ScratchPad.record [] + eval("('A'...)").step { |x| break if x > "D"; ScratchPad << x } + ScratchPad.recorded.should == ["A", "B", "C", "D"] + end + + it "yields String values incremented by #succ called Integer step times" do + eval("('A'..)").step(2) { |x| break if x > "F"; ScratchPad << x } + ScratchPad.recorded.should == ["A", "C", "E"] + + ScratchPad.record [] + eval("('A'...)").step(2) { |x| break if x > "F"; ScratchPad << x } + ScratchPad.recorded.should == ["A", "C", "E"] + end + + it "raises a TypeError when passed a Float step" do + -> { eval("('A'..)").step(2.0) { } }.should raise_error(TypeError) + -> { eval("('A'...)").step(2.0) { } }.should raise_error(TypeError) + end + end + end + describe "when no block is given" do + ruby_version_is "3.0" do + it "raises an ArgumentError if step is 0" do + -> { (-1..1).step(0) }.should raise_error(ArgumentError) + end + end + describe "returned Enumerator" do describe "size" do - it "raises a TypeError if step does not respond to #to_int" do - obj = mock("Range#step non-integer") - enum = (1..2).step(obj) - -> { enum.size }.should raise_error(TypeError) - end - - it "raises a TypeError if #to_int does not return an Integer" do - obj = mock("Range#step non-integer") - obj.should_receive(:to_int).and_return("1") - enum = (1..2).step(obj) + ruby_version_is ""..."3.0" do + it "raises a TypeError if step does not respond to #to_int" do + obj = mock("Range#step non-integer") + enum = (1..2).step(obj) + -> { enum.size }.should raise_error(TypeError) + end - -> { enum.size }.should raise_error(TypeError) - end + it "raises a TypeError if #to_int does not return an Integer" do + obj = mock("Range#step non-integer") + obj.should_receive(:to_int).and_return("1") + enum = (1..2).step(obj) - ruby_version_is ""..."2.6" do - it "raises an ArgumentError if step is 0" do - enum = (-1..1).step(0) - -> { enum.size }.should raise_error(ArgumentError) + -> { enum.size }.should raise_error(TypeError) end + end - it "raises an ArgumentError if step is 0.0" do - enum = (-1..1).step(0.0) - -> { enum.size }.should raise_error(ArgumentError) + ruby_version_is "3.0" do + it "raises a TypeError if step does not respond to #to_int" do + obj = mock("Range#step non-integer") + -> { (1..2).step(obj) }.should raise_error(TypeError) end - it "raises an ArgumentError if step is negative" do - enum = (-1..1).step(-2) - -> { enum.size }.should raise_error(ArgumentError) + it "raises a TypeError if #to_int does not return an Integer" do + obj = mock("Range#step non-integer") + obj.should_receive(:to_int).and_return("1") + -> { (1..2).step(obj) }.should raise_error(TypeError) end end - ruby_version_is "2.6" do + ruby_version_is ""..."3.0" do it "returns Float::INFINITY for zero step" do (-1..1).step(0).size.should == Float::INFINITY (-1..1).step(0.0).size.should == Float::INFINITY @@ -328,11 +434,9 @@ (-5...5).step(2).size.should == 5 end - ruby_version_is "2.6" do - it "returns the ceil of range size divided by the number of steps even if step is negative" do - (-1..1).step(-1).size.should == 0 - (1..-1).step(-1).size.should == 3 - end + it "returns the ceil of range size divided by the number of steps even if step is negative" do + (-1..1).step(-1).size.should == 0 + (1..-1).step(-1).size.should == 3 end it "returns the correct number of steps when one of the arguments is a float" do @@ -352,7 +456,6 @@ (-2...2.0).step.size.should == 4 (-2.0...2).step.size.should == 4 (1.0...6.4).step(1.8).size.should == 3 - (1.0...55.6).step(18.2).size.should == 3 end it "returns nil with begin and end are String" do @@ -372,25 +475,43 @@ end describe "type" do - ruby_version_is ""..."2.6" do - it "returns an instance of Enumerator" do - (1..10).step.class.should == Enumerator + context "when both begin and end are numerics" do + it "returns an instance of Enumerator::ArithmeticSequence" do + (1..10).step.class.should == Enumerator::ArithmeticSequence end end - ruby_version_is "2.6" do - context "when both begin and end are numerics" do + ruby_version_is "2.7" do + context "when begin is not defined and end is numeric" do it "returns an instance of Enumerator::ArithmeticSequence" do - (1..10).step.class.should == Enumerator::ArithmeticSequence + eval("(..10)").step.class.should == Enumerator::ArithmeticSequence end end + end + + context "when range is endless" do + it "returns an instance of Enumerator::ArithmeticSequence when begin is numeric" do + (1..).step.class.should == Enumerator::ArithmeticSequence + end - context "when begin and end are not numerics" do + it "returns an instance of Enumerator when begin is not numeric" do + ("a"..).step.class.should == Enumerator + end + end + + ruby_version_is "2.7" do + context "when range is beginless and endless" do it "returns an instance of Enumerator" do - ("a".."z").step.class.should == Enumerator + Range.new(nil, nil).step.class.should == Enumerator end end end + + context "when begin and end are not numerics" do + it "returns an instance of Enumerator" do + ("a".."z").step.class.should == Enumerator + end + end end end end diff --git a/ruby/spec/ruby/core/range/to_a_spec.rb b/ruby/spec/ruby/core/range/to_a_spec.rb index 15f0b44a9..52ebc0294 100644 --- a/ruby/spec/ruby/core/range/to_a_spec.rb +++ b/ruby/spec/ruby/core/range/to_a_spec.rb @@ -16,7 +16,26 @@ (0xffff...0xfffd).to_a.should == [] end + it "works with Ranges of 64-bit integers" do + large = 1 << 40 + (large..large+1).to_a.should == [1099511627776, 1099511627777] + end + it "works with Ranges of Symbols" do (:A..:z).to_a.size.should == 58 end + + it "works for non-ASCII ranges" do + ('Σ'..'Ω').to_a.should == ["Σ", "Τ", "Î¥", "Φ", "Χ", "Ψ", "Ω"] + end + + it "throws an exception for endless ranges" do + -> { eval("(1..)").to_a }.should raise_error(RangeError) + end + + ruby_version_is "2.7" do + it "throws an exception for beginless ranges" do + -> { eval("(..1)").to_a }.should raise_error(TypeError) + end + end end diff --git a/ruby/spec/ruby/core/range/to_s_spec.rb b/ruby/spec/ruby/core/range/to_s_spec.rb index 7392aa989..581c2e7d9 100644 --- a/ruby/spec/ruby/core/range/to_s_spec.rb +++ b/ruby/spec/ruby/core/range/to_s_spec.rb @@ -11,6 +11,18 @@ (0.5..2.4).to_s.should == "0.5..2.4" end + it "can show endless ranges" do + eval("(1..)").to_s.should == "1.." + eval("(1.0...)").to_s.should == "1.0..." + end + + ruby_version_is "2.7" do + it "can show beginless ranges" do + eval("(..1)").to_s.should == "..1" + eval("(...1.0)").to_s.should == "...1.0" + end + end + ruby_version_is ''...'2.7' do it "returns a tainted string if either end is tainted" do (("a".taint)..."c").to_s.tainted?.should be_true diff --git a/ruby/spec/ruby/core/rational/comparison_spec.rb b/ruby/spec/ruby/core/rational/comparison_spec.rb index b2784f3e7..9d8e7fd7e 100644 --- a/ruby/spec/ruby/core/rational/comparison_spec.rb +++ b/ruby/spec/ruby/core/rational/comparison_spec.rb @@ -4,7 +4,7 @@ it_behaves_like :rational_cmp_rat, :<=> end -describe "Rational#<=> when passed a Integer object" do +describe "Rational#<=> when passed an Integer object" do it_behaves_like :rational_cmp_int, :<=> end diff --git a/ruby/spec/ruby/core/rational/rational_spec.rb b/ruby/spec/ruby/core/rational/rational_spec.rb index 704e49354..482deab38 100644 --- a/ruby/spec/ruby/core/rational/rational_spec.rb +++ b/ruby/spec/ruby/core/rational/rational_spec.rb @@ -4,4 +4,8 @@ it "includes Comparable" do Rational.include?(Comparable).should == true end + + it "does not respond to new" do + -> { Rational.new(1) }.should raise_error(NoMethodError) + end end diff --git a/ruby/spec/ruby/core/regexp/case_compare_spec.rb b/ruby/spec/ruby/core/regexp/case_compare_spec.rb index a621713f6..5ae8b56c6 100644 --- a/ruby/spec/ruby/core/regexp/case_compare_spec.rb +++ b/ruby/spec/ruby/core/regexp/case_compare_spec.rb @@ -22,4 +22,14 @@ (/abc/ === nil).should be_false (/abc/ === /abc/).should be_false end + + it "uses #to_str on string-like objects" do + stringlike = Class.new do + def to_str + "abc" + end + end.new + + (/abc/ === stringlike).should be_true + end end diff --git a/ruby/spec/ruby/core/regexp/casefold_spec.rb b/ruby/spec/ruby/core/regexp/casefold_spec.rb index d84a2d63c..d36467a98 100644 --- a/ruby/spec/ruby/core/regexp/casefold_spec.rb +++ b/ruby/spec/ruby/core/regexp/casefold_spec.rb @@ -2,7 +2,7 @@ describe "Regexp#casefold?" do it "returns the value of the case-insensitive flag" do - /abc/i.casefold?.should == true - /xyz/.casefold?.should == false + /abc/i.should.casefold? + /xyz/.should_not.casefold? end end diff --git a/ruby/spec/ruby/core/regexp/initialize_spec.rb b/ruby/spec/ruby/core/regexp/initialize_spec.rb index 36fd5c7bf..772a233e8 100644 --- a/ruby/spec/ruby/core/regexp/initialize_spec.rb +++ b/ruby/spec/ruby/core/regexp/initialize_spec.rb @@ -5,8 +5,16 @@ Regexp.should have_private_method(:initialize) end - it "raises a SecurityError on a Regexp literal" do - -> { //.send(:initialize, "") }.should raise_error(SecurityError) + ruby_version_is ""..."3.0" do + it "raises a SecurityError on a Regexp literal" do + -> { //.send(:initialize, "") }.should raise_error(SecurityError) + end + end + + ruby_version_is "3.0" do + it "raises a FrozenError on a Regexp literal" do + -> { //.send(:initialize, "") }.should raise_error(FrozenError) + end end it "raises a TypeError on an initialized non-literal Regexp" do diff --git a/ruby/spec/ruby/core/regexp/last_match_spec.rb b/ruby/spec/ruby/core/regexp/last_match_spec.rb index ed496b794..0bfed3205 100644 --- a/ruby/spec/ruby/core/regexp/last_match_spec.rb +++ b/ruby/spec/ruby/core/regexp/last_match_spec.rb @@ -7,8 +7,50 @@ Regexp.last_match.should be_kind_of(MatchData) end - it "returns the nth field in this MatchData when passed a Fixnum" do + it "returns the nth field in this MatchData when passed an Integer" do /c(.)t/ =~ 'cat' Regexp.last_match(1).should == 'a' end + + it "returns nil when there is no match" do + /foo/ =~ "TEST123" + Regexp.last_match(:test).should == nil + Regexp.last_match(1).should == nil + Regexp.last_match(Object.new).should == nil + Regexp.last_match("test").should == nil + end + + describe "when given a Symbol" do + it "returns a named capture" do + /(?[A-Z]+.*)/ =~ "TEST123" + Regexp.last_match(:test).should == "TEST123" + end + + it "raises an IndexError when given a missing name" do + /(?[A-Z]+.*)/ =~ "TEST123" + -> { Regexp.last_match(:missing) }.should raise_error(IndexError) + end + end + + describe "when given a String" do + it "returns a named capture" do + /(?[A-Z]+.*)/ =~ "TEST123" + Regexp.last_match("test").should == "TEST123" + end + end + + describe "when given an Object" do + it "coerces argument to an index using #to_int" do + obj = mock("converted to int") + obj.should_receive(:to_int).and_return(1) + /(?[A-Z]+.*)/ =~ "TEST123" + Regexp.last_match(obj).should == "TEST123" + end + + it "raises a TypeError when unable to coerce" do + obj = Object.new + /(?[A-Z]+.*)/ =~ "TEST123" + -> { Regexp.last_match(obj) }.should raise_error(TypeError) + end + end end diff --git a/ruby/spec/ruby/core/regexp/new_spec.rb b/ruby/spec/ruby/core/regexp/new_spec.rb index d2d867b3d..ce662b7a4 100644 --- a/ruby/spec/ruby/core/regexp/new_spec.rb +++ b/ruby/spec/ruby/core/regexp/new_spec.rb @@ -14,7 +14,7 @@ it_behaves_like :regexp_new_string_binary, :compile end -describe "Regexp.new given a Fixnum" do +describe "Regexp.new given an Integer" do it "raises a TypeError" do -> { Regexp.new(1) }.should raise_error(TypeError) end diff --git a/ruby/spec/ruby/core/regexp/options_spec.rb b/ruby/spec/ruby/core/regexp/options_spec.rb index fb4853a01..527b51a3b 100644 --- a/ruby/spec/ruby/core/regexp/options_spec.rb +++ b/ruby/spec/ruby/core/regexp/options_spec.rb @@ -1,10 +1,10 @@ require_relative '../../spec_helper' describe "Regexp#options" do - it "returns a Fixnum bitvector of regexp options for the Regexp object" do - /cat/.options.should be_kind_of(Fixnum) + it "returns an Integer bitvector of regexp options for the Regexp object" do + /cat/.options.should be_kind_of(Integer) not_supported_on :opal do - /cat/ix.options.should be_kind_of(Fixnum) + /cat/ix.options.should be_kind_of(Integer) end end diff --git a/ruby/spec/ruby/core/regexp/shared/new.rb b/ruby/spec/ruby/core/regexp/shared/new.rb index bb5df7bc2..9cbf89cd8 100644 --- a/ruby/spec/ruby/core/regexp/shared/new.rb +++ b/ruby/spec/ruby/core/regexp/shared/new.rb @@ -58,7 +58,7 @@ class RegexpSpecsSubclassTwo < Regexp; end end end - it "sets options from second argument if it is one of the Fixnum option constants" do + it "sets options from second argument if it is one of the Integer option constants" do r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE) (r.options & Regexp::IGNORECASE).should_not == 0 (r.options & Regexp::MULTILINE).should == 0 @@ -81,14 +81,14 @@ class RegexpSpecsSubclassTwo < Regexp; end end end - it "accepts a Fixnum of two or more options ORed together as the second argument" do + it "accepts an Integer of two or more options ORed together as the second argument" do r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE | Regexp::EXTENDED) (r.options & Regexp::IGNORECASE).should_not == 0 (r.options & Regexp::MULTILINE).should == 0 (r.options & Regexp::EXTENDED).should_not == 0 end - it "treats any non-Fixnum, non-nil, non-false second argument as IGNORECASE" do + it "treats any non-Integer, non-nil, non-false second argument as IGNORECASE" do r = Regexp.send(@method, 'Hi', Object.new) (r.options & Regexp::IGNORECASE).should_not == 0 (r.options & Regexp::MULTILINE).should == 0 diff --git a/ruby/spec/ruby/core/regexp/union_spec.rb b/ruby/spec/ruby/core/regexp/union_spec.rb index 81a31d89b..807683647 100644 --- a/ruby/spec/ruby/core/regexp/union_spec.rb +++ b/ruby/spec/ruby/core/regexp/union_spec.rb @@ -139,6 +139,16 @@ Regexp.union(obj, "bar").should == /foo|bar/ end + it "uses to_regexp to convert argument" do + obj = mock('pattern') + obj.should_receive(:to_regexp).and_return(/foo/) + Regexp.union(obj).should == /foo/ + end + + it "accepts a Symbol as argument" do + Regexp.union(:foo).should == /foo/ + end + it "accepts a single array of patterns as arguments" do Regexp.union(["skiing", "sledding"]).should == /skiing|sledding/ not_supported_on :opal do diff --git a/ruby/spec/ruby/core/signal/trap_spec.rb b/ruby/spec/ruby/core/signal/trap_spec.rb index 91ce1f134..3c7892269 100644 --- a/ruby/spec/ruby/core/signal/trap_spec.rb +++ b/ruby/spec/ruby/core/signal/trap_spec.rb @@ -1,11 +1,12 @@ require_relative '../../spec_helper' -platform_is_not :windows do - describe "Signal.trap" do +describe "Signal.trap" do + platform_is_not :windows do before :each do ScratchPad.clear @proc = -> {} @saved_trap = Signal.trap(:HUP, @proc) + @hup_number = Signal.list["HUP"] end after :each do @@ -16,10 +17,11 @@ Signal.trap(:HUP, @saved_trap).should equal(@proc) end - it "accepts a block in place of a proc/command argument" do + it "accepts a block" do done = false - Signal.trap(:HUP) do + Signal.trap(:HUP) do |signo| + signo.should == @hup_number ScratchPad.record :block_trap done = true end @@ -30,6 +32,94 @@ ScratchPad.recorded.should == :block_trap end + it "accepts a proc" do + done = false + + handler = -> signo { + signo.should == @hup_number + ScratchPad.record :proc_trap + done = true + } + + Signal.trap(:HUP, handler) + + Process.kill :HUP, Process.pid + Thread.pass until done + + ScratchPad.recorded.should == :proc_trap + end + + it "accepts a method" do + done = false + + handler_class = Class.new + hup_number = @hup_number + + handler_class.define_method :handler_method do |signo| + signo.should == hup_number + ScratchPad.record :method_trap + done = true + end + + handler_method = handler_class.new.method(:handler_method) + + Signal.trap(:HUP, handler_method) + + Process.kill :HUP, Process.pid + Thread.pass until done + + ScratchPad.recorded.should == :method_trap + end + + it "accepts anything you can call" do + done = false + + callable = Object.new + hup_number = @hup_number + + callable.singleton_class.define_method :call do |signo| + signo.should == hup_number + ScratchPad.record :callable_trap + done = true + end + + Signal.trap(:HUP, callable) + + Process.kill :HUP, Process.pid + Thread.pass until done + + ScratchPad.recorded.should == :callable_trap + end + + it "raises an exception for a non-callable at the point of use" do + not_callable = Object.new + Signal.trap(:HUP, not_callable) + -> { + Process.kill :HUP, Process.pid + loop { Thread.pass } + }.should raise_error(NoMethodError) + end + + it "accepts a non-callable that becomes callable when used" do + done = false + + late_callable = Object.new + hup_number = @hup_number + + Signal.trap(:HUP, late_callable) + + late_callable.singleton_class.define_method :call do |signo| + signo.should == hup_number + ScratchPad.record :late_callable_trap + done = true + end + + Process.kill :HUP, Process.pid + Thread.pass until done + + ScratchPad.recorded.should == :late_callable_trap + end + it "is possible to create a new Thread when the handler runs" do done = false @@ -49,7 +139,21 @@ it "registers an handler doing nothing with :IGNORE" do Signal.trap :HUP, :IGNORE + Signal.trap(:HUP, @saved_trap).should == "IGNORE" + end + + it "can register a new handler after :IGNORE" do + Signal.trap :HUP, :IGNORE + + done = false + Signal.trap(:HUP) do + ScratchPad.record :block_trap + done = true + end + Process.kill(:HUP, Process.pid).should == 1 + Thread.pass until done + ScratchPad.recorded.should == :block_trap end it "ignores the signal when passed nil" do @@ -116,14 +220,12 @@ Signal.trap :HUP, @proc Signal.trap(:HUP, @saved_trap).should equal(@proc) end - end - describe "Signal.trap" do # See man 2 signal %w[KILL STOP].each do |signal| it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do -> { - trap(signal, -> {}) + Signal.trap(signal, -> {}) }.should raise_error(StandardError) { |e| [ArgumentError, Errno::EINVAL].should include(e.class) e.message.should =~ /Invalid argument|Signal already used by VM or OS/ @@ -138,7 +240,7 @@ end it "returns 'DEFAULT' for the initial SIGINT handler" do - ruby_exe('print trap(:INT) { abort }').should == 'DEFAULT' + ruby_exe("print Signal.trap(:INT) { abort }").should == 'DEFAULT' end it "returns SYSTEM_DEFAULT if passed DEFAULT and no handler was ever set" do @@ -152,31 +254,30 @@ r.close loop { w.write("a"*1024) } RUBY - out = ruby_exe(code) + out = ruby_exe(code, exit_status: nil) status = $? out.should == "nil\n" - status.signaled?.should == true + status.should.signaled? status.termsig.should be_kind_of(Integer) Signal.signame(status.termsig).should == "PIPE" end end -end -describe "Signal.trap" do describe "the special EXIT signal code" do it "accepts the EXIT code" do - code = "trap(:EXIT, proc { print 1 })" + code = "Signal.trap(:EXIT, proc { print 1 })" ruby_exe(code).should == "1" end it "runs the proc before at_exit handlers" do - code = "at_exit {print 1}; trap(:EXIT, proc {print 2}); at_exit {print 3}" + code = "at_exit {print 1}; Signal.trap(:EXIT, proc {print 2}); at_exit {print 3}" ruby_exe(code).should == "231" end it "can unset the handler" do - code = "trap(:EXIT, proc { print 1 }); trap(:EXIT, 'DEFAULT')" + code = "Signal.trap(:EXIT, proc { print 1 }); Signal.trap(:EXIT, 'DEFAULT')" ruby_exe(code).should == "" end end + end diff --git a/ruby/spec/ruby/core/string/bytes_spec.rb b/ruby/spec/ruby/core/string/bytes_spec.rb index 96f1ae9cf..859b34655 100644 --- a/ruby/spec/ruby/core/string/bytes_spec.rb +++ b/ruby/spec/ruby/core/string/bytes_spec.rb @@ -22,9 +22,9 @@ @utf8_ascii.bytes.to_a.size.should == @utf8_ascii.bytesize end - it "returns bytes as Fixnums" do - @ascii.bytes.to_a.each {|b| b.should be_an_instance_of(Fixnum)} - @utf8_ascii.bytes { |b| b.should be_an_instance_of(Fixnum) } + it "returns bytes as Integers" do + @ascii.bytes.to_a.each {|b| b.should be_an_instance_of(Integer)} + @utf8_ascii.bytes { |b| b.should be_an_instance_of(Integer) } end it "agrees with #unpack('C*')" do diff --git a/ruby/spec/ruby/core/string/capitalize_spec.rb b/ruby/spec/ruby/core/string/capitalize_spec.rb index 41dd63f63..21df18a5a 100644 --- a/ruby/spec/ruby/core/string/capitalize_spec.rb +++ b/ruby/spec/ruby/core/string/capitalize_spec.rb @@ -14,8 +14,8 @@ ruby_version_is ''...'2.7' do it "taints resulting string when self is tainted" do - "".taint.capitalize.tainted?.should == true - "hello".taint.capitalize.tainted?.should == true + "".taint.capitalize.should.tainted? + "hello".taint.capitalize.should.tainted? end end @@ -80,9 +80,18 @@ -> { "abc".capitalize(:invalid_option) }.should raise_error(ArgumentError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(String) + StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String) + end end end @@ -93,6 +102,12 @@ a.should == "Hello" end + it "modifies self in place for non-ascii-compatible encodings" do + a = "heLLo".encode("utf-16le") + a.capitalize! + a.should == "Hello".encode("utf-16le") + end + describe "full Unicode case mapping" do it "modifies self in place for all of Unicode with no option" do a = "äöÜ" @@ -106,6 +121,12 @@ a.should == "Ss" end + it "works for non-ascii-compatible encodings" do + a = "äöü".encode("utf-16le") + a.capitalize! + a.should == "Äöü".encode("utf-16le") + end + it "updates string metadata" do capitalized = "ßeT" capitalized.capitalize! @@ -123,6 +144,12 @@ a.capitalize!(:ascii) a.should == "ßet" end + + it "works for non-ascii-compatible encodings" do + a = "aBc".encode("utf-16le") + a.capitalize!(:ascii) + a.should == "Abc".encode("utf-16le") + end end describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do @@ -178,10 +205,10 @@ "H".capitalize!.should == nil end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do ["", "Hello", "hello"].each do |a| a.freeze - -> { a.capitalize! }.should raise_error(frozen_error_class) + -> { a.capitalize! }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/string/casecmp_spec.rb b/ruby/spec/ruby/core/string/casecmp_spec.rb index 01b22e8f1..986fbc871 100644 --- a/ruby/spec/ruby/core/string/casecmp_spec.rb +++ b/ruby/spec/ruby/core/string/casecmp_spec.rb @@ -25,16 +25,8 @@ "abc".casecmp(other).should == 0 end - ruby_version_is ""..."2.5" do - it "raises a TypeError if other can't be converted to a string" do - -> { "abc".casecmp(mock('abc')) }.should raise_error(TypeError) - end - end - - ruby_version_is "2.5" do - it "returns nil if other can't be converted to a string" do - "abc".casecmp(mock('abc')).should be_nil - end + it "returns nil if other can't be converted to a string" do + "abc".casecmp(mock('abc')).should be_nil end it "returns nil if incompatible encodings" do @@ -196,15 +188,7 @@ "ß".casecmp?("ss").should be_true end - ruby_version_is "2.4"..."2.5" do - it "raises a TypeError if other can't be converted to a string" do - -> { "abc".casecmp?(mock('abc')) }.should raise_error(TypeError) - end - end - - ruby_version_is "2.5" do - it "returns nil if other can't be converted to a string" do - "abc".casecmp?(mock('abc')).should be_nil - end + it "returns nil if other can't be converted to a string" do + "abc".casecmp?(mock('abc')).should be_nil end end diff --git a/ruby/spec/ruby/core/string/center_spec.rb b/ruby/spec/ruby/core/string/center_spec.rb index 0284fc28d..b66015172 100644 --- a/ruby/spec/ruby/core/string/center_spec.rb +++ b/ruby/spec/ruby/core/string/center_spec.rb @@ -49,11 +49,11 @@ ruby_version_is ''...'2.7' do it "taints result when self or padstr is tainted" do - "x".taint.center(4).tainted?.should == true - "x".taint.center(0).tainted?.should == true - "".taint.center(0).tainted?.should == true - "x".taint.center(4, "*").tainted?.should == true - "x".center(4, "*".taint).tainted?.should == true + "x".taint.center(4).should.tainted? + "x".taint.center(0).should.tainted? + "".taint.center(0).should.tainted? + "x".taint.center(4, "*").should.tainted? + "x".center(4, "*".taint).should.tainted? end end @@ -91,13 +91,26 @@ -> { "hello".center(0, "") }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) - "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").center(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/string/chomp_spec.rb b/ruby/spec/ruby/core/string/chomp_spec.rb index 20a092595..3d6207f87 100644 --- a/ruby/spec/ruby/core/string/chomp_spec.rb +++ b/ruby/spec/ruby/core/string/chomp_spec.rb @@ -6,11 +6,13 @@ describe "when passed no argument" do before do # Ensure that $/ is set to the default value + @verbose, $VERBOSE = $VERBOSE, nil @dollar_slash, $/ = $/, "\n" end after do $/ = @dollar_slash + $VERBOSE = @verbose end it "does not modify a String with no trailing carriage return or newline" do @@ -44,15 +46,28 @@ end end - it "returns subclass instances when called on a subclass" do - str = StringSpecs::MyString.new("hello\n").chomp - str.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + str = StringSpecs::MyString.new("hello\n").chomp + str.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + str = StringSpecs::MyString.new("hello\n").chomp + str.should be_an_instance_of(String) + end end it "removes trailing characters that match $/ when it has been assigned a value" do $/ = "cdef" "abcdef".chomp.should == "ab" end + + it "removes one trailing newline for string with invalid encoding" do + "\xa0\xa1\n".chomp.should == "\xa0\xa1" + end end describe "when passed nil" do @@ -106,6 +121,10 @@ it "returns an empty String when self is empty" do "".chomp("").should == "" end + + it "removes one trailing newline for string with invalid encoding" do + "\xa0\xa1\n".chomp("").should == "\xa0\xa1" + end end describe "when passed '\\n'" do @@ -179,11 +198,13 @@ describe "when passed no argument" do before do # Ensure that $/ is set to the default value + @verbose, $VERBOSE = $VERBOSE, nil @dollar_slash, $/ = $/, "\n" end after do $/ = @dollar_slash + $VERBOSE = @verbose end it "modifies self" do @@ -332,29 +353,31 @@ end end - it "raises a #{frozen_error_class} on a frozen instance when it is modified" do + it "raises a FrozenError on a frozen instance when it is modified" do a = "string\n\r" a.freeze - -> { a.chomp! }.should raise_error(frozen_error_class) + -> { a.chomp! }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen instance when it would not be modified" do + it "raises a FrozenError on a frozen instance when it would not be modified" do a = "string\n\r" a.freeze - -> { a.chomp!(nil) }.should raise_error(frozen_error_class) - -> { a.chomp!("x") }.should raise_error(frozen_error_class) + -> { a.chomp!(nil) }.should raise_error(FrozenError) + -> { a.chomp!("x") }.should raise_error(FrozenError) end end describe "String#chomp" do before :each do + @verbose, $VERBOSE = $VERBOSE, nil @before_separator = $/ end after :each do $/ = @before_separator + $VERBOSE = @verbose end it "does not modify a multi-byte character" do @@ -379,11 +402,13 @@ describe "String#chomp!" do before :each do + @verbose, $VERBOSE = $VERBOSE, nil @before_separator = $/ end after :each do $/ = @before_separator + $VERBOSE = @verbose end it "returns nil when the String is not modified" do diff --git a/ruby/spec/ruby/core/string/chop_spec.rb b/ruby/spec/ruby/core/string/chop_spec.rb index 9e893c3be..9b4e7363c 100644 --- a/ruby/spec/ruby/core/string/chop_spec.rb +++ b/ruby/spec/ruby/core/string/chop_spec.rb @@ -51,18 +51,26 @@ ruby_version_is ''...'2.7' do it "taints result when self is tainted" do - "hello".taint.chop.tainted?.should == true - "".taint.chop.tainted?.should == true + "hello".taint.chop.should.tainted? + "".taint.chop.should.tainted? end it "untrusts result when self is untrusted" do - "hello".untrust.chop.untrusted?.should == true - "".untrust.chop.untrusted?.should == true + "hello".untrust.chop.should.untrusted? + "".untrust.chop.should.untrusted? end end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String) + end end end @@ -113,14 +121,14 @@ "".chop!.should be_nil end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { "string\n\r".freeze.chop! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { "string\n\r".freeze.chop! }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do + it "raises a FrozenError on a frozen instance that would not be modified" do a = "" a.freeze - -> { a.chop! }.should raise_error(frozen_error_class) + -> { a.chop! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/clear_spec.rb b/ruby/spec/ruby/core/string/clear_spec.rb index 0b5b8e699..e1d68e03b 100644 --- a/ruby/spec/ruby/core/string/clear_spec.rb +++ b/ruby/spec/ruby/core/string/clear_spec.rb @@ -29,9 +29,9 @@ s.should == "" end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do @s.freeze - -> { @s.clear }.should raise_error(frozen_error_class) - -> { "".freeze.clear }.should raise_error(frozen_error_class) + -> { @s.clear }.should raise_error(FrozenError) + -> { "".freeze.clear }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/crypt_spec.rb b/ruby/spec/ruby/core/string/crypt_spec.rb index 6a9a4ae23..b94770249 100644 --- a/ruby/spec/ruby/core/string/crypt_spec.rb +++ b/ruby/spec/ruby/core/string/crypt_spec.rb @@ -33,10 +33,10 @@ tainted_salt.taint tainted_str.taint - "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == false - tainted_str.crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == true - "mypassword".crypt(tainted_salt).tainted?.should == true - tainted_str.crypt(tainted_salt).tainted?.should == true + "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should_not.tainted? + tainted_str.crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should.tainted? + "mypassword".crypt(tainted_salt).should.tainted? + tainted_str.crypt(tainted_salt).should.tainted? end end @@ -93,10 +93,10 @@ tainted_salt.taint tainted_str.taint - "hello".crypt("aa").tainted?.should == false - tainted_str.crypt("aa").tainted?.should == true - "hello".crypt(tainted_salt).tainted?.should == true - tainted_str.crypt(tainted_salt).tainted?.should == true + "hello".crypt("aa").should_not.tainted? + tainted_str.crypt("aa").should.tainted? + "hello".crypt(tainted_salt).should.tainted? + tainted_str.crypt(tainted_salt).should.tainted? end end diff --git a/ruby/spec/ruby/core/string/delete_prefix_spec.rb b/ruby/spec/ruby/core/string/delete_prefix_spec.rb index 92c301b44..8469791f7 100644 --- a/ruby/spec/ruby/core/string/delete_prefix_spec.rb +++ b/ruby/spec/ruby/core/string/delete_prefix_spec.rb @@ -2,82 +2,89 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is '2.5' do - describe "String#delete_prefix" do - it "returns a copy of the string, with the given prefix removed" do - 'hello'.delete_prefix('hell').should == 'o' - 'hello'.delete_prefix('hello').should == '' - end +describe "String#delete_prefix" do + it "returns a copy of the string, with the given prefix removed" do + 'hello'.delete_prefix('hell').should == 'o' + 'hello'.delete_prefix('hello').should == '' + end - it "returns a copy of the string, when the prefix isn't found" do - s = 'hello' - r = s.delete_prefix('hello!') - r.should_not equal s - r.should == s - r = s.delete_prefix('ell') - r.should_not equal s - r.should == s - r = s.delete_prefix('') - r.should_not equal s - r.should == s - end + it "returns a copy of the string, when the prefix isn't found" do + s = 'hello' + r = s.delete_prefix('hello!') + r.should_not equal s + r.should == s + r = s.delete_prefix('ell') + r.should_not equal s + r.should == s + r = s.delete_prefix('') + r.should_not equal s + r.should == s + end - ruby_version_is ''...'2.7' do - it "taints resulting strings when other is tainted" do - 'hello'.taint.delete_prefix('hell').tainted?.should == true - 'hello'.taint.delete_prefix('').tainted?.should == true - end + ruby_version_is ''...'2.7' do + it "taints resulting strings when other is tainted" do + 'hello'.taint.delete_prefix('hell').should.tainted? + 'hello'.taint.delete_prefix('').should.tainted? end + end - it "doesn't set $~" do - $~ = nil + it "doesn't set $~" do + $~ = nil - 'hello'.delete_prefix('hell') - $~.should == nil - end + 'hello'.delete_prefix('hell') + $~.should == nil + end - it "calls to_str on its argument" do - o = mock('x') - o.should_receive(:to_str).and_return 'hell' - 'hello'.delete_prefix(o).should == 'o' - end + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'hell' + 'hello'.delete_prefix(o).should == 'o' + end + ruby_version_is ''...'3.0' do it "returns a subclass instance when called on a subclass instance" do s = StringSpecs::MyString.new('hello') s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString) end end - describe "String#delete_prefix!" do - it "removes the found prefix" do - s = 'hello' - s.delete_prefix!('hell').should equal(s) - s.should == 'o' + ruby_version_is '3.0' do + it "returns a String instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_prefix('hell').should be_an_instance_of(String) end + end +end - it "returns nil if no change is made" do - s = 'hello' - s.delete_prefix!('ell').should == nil - s.delete_prefix!('').should == nil - end +describe "String#delete_prefix!" do + it "removes the found prefix" do + s = 'hello' + s.delete_prefix!('hell').should equal(s) + s.should == 'o' + end - it "doesn't set $~" do - $~ = nil + it "returns nil if no change is made" do + s = 'hello' + s.delete_prefix!('ell').should == nil + s.delete_prefix!('').should == nil + end - 'hello'.delete_prefix!('hell') - $~.should == nil - end + it "doesn't set $~" do + $~ = nil - it "calls to_str on its argument" do - o = mock('x') - o.should_receive(:to_str).and_return 'hell' - 'hello'.delete_prefix!(o).should == 'o' - end + 'hello'.delete_prefix!('hell') + $~.should == nil + end - it "raises a #{frozen_error_class} when self is frozen" do - -> { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(frozen_error_class) - -> { 'hello'.freeze.delete_prefix!('') }.should raise_error(frozen_error_class) - -> { ''.freeze.delete_prefix!('') }.should raise_error(frozen_error_class) - end + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'hell' + 'hello'.delete_prefix!(o).should == 'o' + end + + it "raises a FrozenError when self is frozen" do + -> { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(FrozenError) + -> { 'hello'.freeze.delete_prefix!('') }.should raise_error(FrozenError) + -> { ''.freeze.delete_prefix!('') }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/delete_spec.rb b/ruby/spec/ruby/core/string/delete_spec.rb index 130228041..ebca0b7da 100644 --- a/ruby/spec/ruby/core/string/delete_spec.rb +++ b/ruby/spec/ruby/core/string/delete_spec.rb @@ -70,10 +70,10 @@ ruby_version_is ''...'2.7' do it "taints result when self is tainted" do - "hello".taint.delete("e").tainted?.should == true - "hello".taint.delete("a-z").tainted?.should == true + "hello".taint.delete("e").should.tainted? + "hello".taint.delete("a-z").should.tainted? - "hello".delete("e".taint).tainted?.should == false + "hello".delete("e".taint).should_not.tainted? end end @@ -93,8 +93,16 @@ -> { "hello world".delete(mock('x')) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String) + end end end @@ -111,11 +119,11 @@ a.should == "hello" end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "hello" a.freeze - -> { a.delete!("") }.should raise_error(frozen_error_class) - -> { a.delete!("aeiou", "^e") }.should raise_error(frozen_error_class) + -> { a.delete!("") }.should raise_error(FrozenError) + -> { a.delete!("aeiou", "^e") }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/delete_suffix_spec.rb b/ruby/spec/ruby/core/string/delete_suffix_spec.rb index edc0f7315..12d0ee175 100644 --- a/ruby/spec/ruby/core/string/delete_suffix_spec.rb +++ b/ruby/spec/ruby/core/string/delete_suffix_spec.rb @@ -2,82 +2,89 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is '2.5' do - describe "String#delete_suffix" do - it "returns a copy of the string, with the given suffix removed" do - 'hello'.delete_suffix('ello').should == 'h' - 'hello'.delete_suffix('hello').should == '' - end +describe "String#delete_suffix" do + it "returns a copy of the string, with the given suffix removed" do + 'hello'.delete_suffix('ello').should == 'h' + 'hello'.delete_suffix('hello').should == '' + end - it "returns a copy of the string, when the suffix isn't found" do - s = 'hello' - r = s.delete_suffix('!hello') - r.should_not equal s - r.should == s - r = s.delete_suffix('ell') - r.should_not equal s - r.should == s - r = s.delete_suffix('') - r.should_not equal s - r.should == s - end + it "returns a copy of the string, when the suffix isn't found" do + s = 'hello' + r = s.delete_suffix('!hello') + r.should_not equal s + r.should == s + r = s.delete_suffix('ell') + r.should_not equal s + r.should == s + r = s.delete_suffix('') + r.should_not equal s + r.should == s + end - ruby_version_is ''...'2.7' do - it "taints resulting strings when other is tainted" do - 'hello'.taint.delete_suffix('ello').tainted?.should == true - 'hello'.taint.delete_suffix('').tainted?.should == true - end + ruby_version_is ''...'2.7' do + it "taints resulting strings when other is tainted" do + 'hello'.taint.delete_suffix('ello').should.tainted? + 'hello'.taint.delete_suffix('').should.tainted? end + end - it "doesn't set $~" do - $~ = nil + it "doesn't set $~" do + $~ = nil - 'hello'.delete_suffix('ello') - $~.should == nil - end + 'hello'.delete_suffix('ello') + $~.should == nil + end - it "calls to_str on its argument" do - o = mock('x') - o.should_receive(:to_str).and_return 'ello' - 'hello'.delete_suffix(o).should == 'h' - end + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'ello' + 'hello'.delete_suffix(o).should == 'h' + end + ruby_version_is ''...'3.0' do it "returns a subclass instance when called on a subclass instance" do s = StringSpecs::MyString.new('hello') s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString) end end - describe "String#delete_suffix!" do - it "removes the found prefix" do - s = 'hello' - s.delete_suffix!('ello').should equal(s) - s.should == 'h' + ruby_version_is '3.0' do + it "returns a String instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_suffix('ello').should be_an_instance_of(String) end + end +end - it "returns nil if no change is made" do - s = 'hello' - s.delete_suffix!('ell').should == nil - s.delete_suffix!('').should == nil - end +describe "String#delete_suffix!" do + it "removes the found prefix" do + s = 'hello' + s.delete_suffix!('ello').should equal(s) + s.should == 'h' + end - it "doesn't set $~" do - $~ = nil + it "returns nil if no change is made" do + s = 'hello' + s.delete_suffix!('ell').should == nil + s.delete_suffix!('').should == nil + end - 'hello'.delete_suffix!('ello') - $~.should == nil - end + it "doesn't set $~" do + $~ = nil - it "calls to_str on its argument" do - o = mock('x') - o.should_receive(:to_str).and_return 'ello' - 'hello'.delete_suffix!(o).should == 'h' - end + 'hello'.delete_suffix!('ello') + $~.should == nil + end - it "raises a #{frozen_error_class} when self is frozen" do - -> { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(frozen_error_class) - -> { 'hello'.freeze.delete_suffix!('') }.should raise_error(frozen_error_class) - -> { ''.freeze.delete_suffix!('') }.should raise_error(frozen_error_class) - end + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'ello' + 'hello'.delete_suffix!(o).should == 'h' + end + + it "raises a FrozenError when self is frozen" do + -> { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(FrozenError) + -> { 'hello'.freeze.delete_suffix!('') }.should raise_error(FrozenError) + -> { ''.freeze.delete_suffix!('') }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/downcase_spec.rb b/ruby/spec/ruby/core/string/downcase_spec.rb index 84e94ee10..4427c9df1 100644 --- a/ruby/spec/ruby/core/string/downcase_spec.rb +++ b/ruby/spec/ruby/core/string/downcase_spec.rb @@ -70,14 +70,22 @@ ruby_version_is ''...'2.7' do it "taints result when self is tainted" do - "".taint.downcase.tainted?.should == true - "x".taint.downcase.tainted?.should == true - "X".taint.downcase.tainted?.should == true + "".taint.downcase.should.tainted? + "x".taint.downcase.should.tainted? + "X".taint.downcase.should.tainted? end end - it "returns a subclass instance for subclasses" do - StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance for subclasses" do + StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance for subclasses" do + StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(String) + end end end @@ -88,6 +96,12 @@ a.should == "hello" end + it "modifies self in place for non-ascii-compatible encodings" do + a = "HeLlO".encode("utf-16le") + a.downcase! + a.should == "hello".encode("utf-16le") + end + describe "full Unicode case mapping" do it "modifies self in place for all of Unicode with no option" do a = "ÄÖÜ" @@ -112,6 +126,12 @@ a.downcase!(:ascii) a.should == "câ„«r" end + + it "works for non-ascii-compatible encodings" do + a = "ABC".encode("utf-16le") + a.downcase!(:ascii) + a.should == "abc".encode("utf-16le") + end end describe "full Unicode case mapping adapted for Turkic languages" do @@ -171,9 +191,9 @@ a.should == "hello" end - it "raises a #{frozen_error_class} when self is frozen" do - -> { "HeLlo".freeze.downcase! }.should raise_error(frozen_error_class) - -> { "hello".freeze.downcase! }.should raise_error(frozen_error_class) + it "raises a FrozenError when self is frozen" do + -> { "HeLlo".freeze.downcase! }.should raise_error(FrozenError) + -> { "hello".freeze.downcase! }.should raise_error(FrozenError) end it "sets the result String encoding to the source String encoding" do diff --git a/ruby/spec/ruby/core/string/dump_spec.rb b/ruby/spec/ruby/core/string/dump_spec.rb index 260ee37ad..817dec6c4 100644 --- a/ruby/spec/ruby/core/string/dump_spec.rb +++ b/ruby/spec/ruby/core/string/dump_spec.rb @@ -5,22 +5,30 @@ describe "String#dump" do ruby_version_is ''...'2.7' do it "taints the result if self is tainted" do - "foo".taint.dump.tainted?.should == true - "foo\n".taint.dump.tainted?.should == true + "foo".taint.dump.should.tainted? + "foo\n".taint.dump.should.tainted? end it "untrusts the result if self is untrusted" do - "foo".untrust.dump.untrusted?.should == true - "foo\n".untrust.dump.untrusted?.should == true + "foo".untrust.dump.should.untrusted? + "foo\n".untrust.dump.should.untrusted? end end it "does not take into account if a string is frozen" do - "foo".freeze.dump.frozen?.should == false + "foo".freeze.dump.should_not.frozen? end - it "returns a subclass instance" do - StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance" do + StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance" do + StringSpecs::MyString.new.dump.should be_an_instance_of(String) + end end it "wraps string with \"" do diff --git a/ruby/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/ruby/spec/ruby/core/string/each_grapheme_cluster_spec.rb index 5367f8488..b45d89ecb 100644 --- a/ruby/spec/ruby/core/string/each_grapheme_cluster_spec.rb +++ b/ruby/spec/ruby/core/string/each_grapheme_cluster_spec.rb @@ -2,10 +2,16 @@ require_relative 'shared/grapheme_clusters' require_relative 'shared/each_char_without_block' -ruby_version_is "2.5" do - describe "String#each_grapheme_cluster" do - it_behaves_like :string_chars, :each_grapheme_cluster - it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster - it_behaves_like :string_each_char_without_block, :each_grapheme_cluster +describe "String#each_grapheme_cluster" do + it_behaves_like :string_chars, :each_grapheme_cluster + it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster + it_behaves_like :string_each_char_without_block, :each_grapheme_cluster + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("abc").each_grapheme_cluster { |s| a << s.class } + a.should == [String, String, String] + end end end diff --git a/ruby/spec/ruby/core/string/element_set_spec.rb b/ruby/spec/ruby/core/string/element_set_spec.rb index 608efc23b..c9e02a738 100644 --- a/ruby/spec/ruby/core/string/element_set_spec.rb +++ b/ruby/spec/ruby/core/string/element_set_spec.rb @@ -5,7 +5,7 @@ # TODO: Add missing String#[]= specs: # String#[re, idx] = obj -describe "String#[]= with Fixnum index" do +describe "String#[]= with Integer index" do it "replaces the char at idx with other_str" do a = "hello" a[0] = "bam" @@ -18,11 +18,11 @@ it "taints self if other_str is tainted" do a = "hello" a[0] = "".taint - a.tainted?.should == true + a.should.tainted? a = "hello" a[0] = "x".taint - a.tainted?.should == true + a.should.tainted? end end @@ -52,11 +52,11 @@ str.should == "hello" end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "hello" a.freeze - -> { a[0] = "bam" }.should raise_error(frozen_error_class) + -> { a[0] = "bam" }.should raise_error(FrozenError) end it "calls to_int on index" do @@ -85,7 +85,7 @@ -> { "test"[1] = nil }.should raise_error(TypeError) end - it "raises a TypeError if passed a Fixnum replacement" do + it "raises a TypeError if passed an Integer replacement" do -> { "abc"[1] = 65 }.should raise_error(TypeError) end @@ -102,7 +102,7 @@ str.should == "ã‚a" end - it "raises a TypeError if #to_int does not return an Fixnum" do + it "raises a TypeError if #to_int does not return an Integer" do index = mock("string element set") index.should_receive(:to_int).and_return('1') @@ -243,7 +243,7 @@ str.should == "axc" end - it "raises a TypeError if #to_int does not return a Fixnum" do + it "raises a TypeError if #to_int does not return an Integer" do ref = mock("string element set regexp ref") ref.should_receive(:to_int).and_return(nil) @@ -438,7 +438,7 @@ end end -describe "String#[]= with Fixnum index, count" do +describe "String#[]= with Integer index, count" do it "starts at idx and overwrites count characters before inserting the rest of other_str" do a = "hello" a[0, 2] = "xx" @@ -491,11 +491,11 @@ it "taints self if other_str is tainted" do a = "hello" a[0, 0] = "".taint - a.tainted?.should == true + a.should.tainted? a = "hello" a[1, 4] = "x".taint - a.tainted?.should == true + a.should.tainted? end end diff --git a/ruby/spec/ruby/core/string/empty_spec.rb b/ruby/spec/ruby/core/string/empty_spec.rb index fb5207072..8e53a16af 100644 --- a/ruby/spec/ruby/core/string/empty_spec.rb +++ b/ruby/spec/ruby/core/string/empty_spec.rb @@ -3,10 +3,10 @@ describe "String#empty?" do it "returns true if the string has a length of zero" do - "hello".empty?.should == false - " ".empty?.should == false - "\x00".empty?.should == false - "".empty?.should == true - StringSpecs::MyString.new("").empty?.should == true + "hello".should_not.empty? + " ".should_not.empty? + "\x00".should_not.empty? + "".should.empty? + StringSpecs::MyString.new("").should.empty? end end diff --git a/ruby/spec/ruby/core/string/encode_spec.rb b/ruby/spec/ruby/core/string/encode_spec.rb index 1c0c93935..5604ab721 100644 --- a/ruby/spec/ruby/core/string/encode_spec.rb +++ b/ruby/spec/ruby/core/string/encode_spec.rb @@ -19,13 +19,17 @@ it "returns a copy when Encoding.default_internal is nil" do Encoding.default_internal = nil str = "ã‚" - str.encode.should_not equal(str) + encoded = str.encode + encoded.should_not equal(str) + encoded.should == str end it "returns a copy for a ASCII-only String when Encoding.default_internal is nil" do Encoding.default_internal = nil str = "abc" - str.encode.should_not equal(str) + encoded = str.encode + encoded.should_not equal(str) + encoded.should == str end it "encodes an ascii substring of a binary string to UTF-8" do @@ -39,7 +43,9 @@ describe "when passed to encoding" do it "returns a copy when passed the same encoding as the String" do str = "ã‚" - str.encode(Encoding::UTF_8).should_not equal(str) + encoded = str.encode(Encoding::UTF_8) + encoded.should_not equal(str) + encoded.should == str end it "round trips a String" do @@ -61,10 +67,52 @@ "\rfoo".encode(universal_newline: true).should == "\nfoo" end - it "replaces invalid encoding" do - encoded = "ã¡\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "?") - encoded.should == "\u3061??".encode("UTF-16LE") - encoded.encode("UTF-8").should == "ã¡??" + it "replaces invalid encoding in source with default replacement" do + encoded = "ã¡\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace) + encoded.should == "\u3061\ufffd\ufffd".encode("UTF-16LE") + encoded.encode("UTF-8").should == "ã¡\ufffd\ufffd" + end + + it "replaces invalid encoding in source with a specified replacement" do + encoded = "ã¡\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo") + encoded.should == "\u3061foofoo".encode("UTF-16LE") + encoded.encode("UTF-8").should == "ã¡foofoo" + end + + it "replaces invalid encoding in source using a specified replacement even when a fallback is given" do + encoded = "ã¡\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo", fallback: -> c { "bar" }) + encoded.should == "\u3061foofoo".encode("UTF-16LE") + encoded.encode("UTF-8").should == "ã¡foofoo" + end + + it "replaces undefined encoding in destination with default replacement" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace) + encoded.should == "B?".encode(Encoding::US_ASCII) + encoded.encode("UTF-8").should == "B?" + end + + it "replaces undefined encoding in destination with a specified replacement" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace, replace: "foo") + encoded.should == "Bfoo".encode(Encoding::US_ASCII) + encoded.encode("UTF-8").should == "Bfoo" + end + + it "replaces undefined encoding in destination with a specified replacement even if a fallback is given" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace, replace: "foo", fallback: proc {|x| "bar"}) + encoded.should == "Bfoo".encode(Encoding::US_ASCII) + encoded.encode("UTF-8").should == "Bfoo" + end + + it "replaces undefined encoding in destination using a fallback proc" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc {|x| "bar"}) + encoded.should == "Bbar".encode(Encoding::US_ASCII) + encoded.encode("UTF-8").should == "Bbar" + end + + it "replaces invalid encoding in source using replace even when fallback is given as proc" do + encoded = "ã¡\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo", fallback: proc {|x| "bar"}) + encoded.should == "\u3061foofoo".encode("UTF-16LE") + encoded.encode("UTF-8").should == "ã¡foofoo" end end @@ -75,6 +123,7 @@ encoded = str.encode("utf-8", "utf-8") encoded.should_not equal(str) + encoded.should == str.force_encoding("utf-8") encoded.encoding.should == Encoding::UTF_8 end @@ -87,14 +136,28 @@ describe "when passed to, options" do it "returns a copy when the destination encoding is the same as the String encoding" do str = "ã‚" - str.encode(Encoding::UTF_8, undef: :replace).should_not equal(str) + encoded = str.encode(Encoding::UTF_8, undef: :replace) + encoded.should_not equal(str) + encoded.should == str end end describe "when passed to, from, options" do it "returns a copy when both encodings are the same" do str = "ã‚" - str.encode("utf-8", "utf-8", invalid: :replace).should_not equal(str) + encoded = str.encode("utf-8", "utf-8", invalid: :replace) + encoded.should_not equal(str) + encoded.should == str + end + + it "returns a copy in the destination encoding when both encodings are the same" do + str = "ã‚" + str.force_encoding("binary") + encoded = str.encode("utf-8", "utf-8", invalid: :replace) + + encoded.should_not equal(str) + encoded.should == str.force_encoding("utf-8") + encoded.encoding.should == Encoding::UTF_8 end end end @@ -112,13 +175,13 @@ it_behaves_like :string_encode, :encode! - it "raises a #{frozen_error_class} when called on a frozen String" do - -> { "foo".freeze.encode!("euc-jp") }.should raise_error(frozen_error_class) + it "raises a FrozenError when called on a frozen String" do + -> { "foo".freeze.encode!("euc-jp") }.should raise_error(FrozenError) end # http://redmine.ruby-lang.org/issues/show/1836 - it "raises a #{frozen_error_class} when called on a frozen String when it's a no-op" do - -> { "foo".freeze.encode!("utf-8") }.should raise_error(frozen_error_class) + it "raises a FrozenError when called on a frozen String when it's a no-op" do + -> { "foo".freeze.encode!("utf-8") }.should raise_error(FrozenError) end describe "when passed no options" do diff --git a/ruby/spec/ruby/core/string/end_with_spec.rb b/ruby/spec/ruby/core/string/end_with_spec.rb index 9ced0ca3d..ac4fff72a 100644 --- a/ruby/spec/ruby/core/string/end_with_spec.rb +++ b/ruby/spec/ruby/core/string/end_with_spec.rb @@ -1,56 +1,8 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative '../../shared/string/end_with' describe "String#end_with?" do - it "returns true only if ends match" do - s = "hello" - s.should.end_with?('o') - s.should.end_with?('llo') - end - - it 'returns false if the end does not match' do - s = 'hello' - s.should_not.end_with?('ll') - end - - it "returns true if the search string is empty" do - "hello".should.end_with?("") - "".should.end_with?("") - end - - it "returns true only if any ending match" do - "hello".should.end_with?('x', 'y', 'llo', 'z') - end - - it "converts its argument using :to_str" do - s = "hello" - find = mock('o') - find.should_receive(:to_str).and_return("o") - s.should.end_with?(find) - end - - it "ignores arguments not convertible to string" do - "hello".should_not.end_with?() - -> { "hello".end_with?(1) }.should raise_error(TypeError) - -> { "hello".end_with?(["o"]) }.should raise_error(TypeError) - -> { "hello".end_with?(1, nil, "o") }.should raise_error(TypeError) - end - - it "uses only the needed arguments" do - find = mock('h') - find.should_not_receive(:to_str) - "hello".should.end_with?("o",find) - end - - it "works for multibyte strings" do - "céréale".should.end_with?("réale") - end - - it "raises an Encoding::CompatibilityError if the encodings are incompatible" do - pat = "ã‚¢".encode Encoding::EUC_JP - -> do - "ã‚れ".end_with?(pat) - end.should raise_error(Encoding::CompatibilityError) - end + it_behaves_like :end_with, :to_s end diff --git a/ruby/spec/ruby/core/string/fixtures/classes.rb b/ruby/spec/ruby/core/string/fixtures/classes.rb index 1cc7600ab..26fcd51b5 100644 --- a/ruby/spec/ruby/core/string/fixtures/classes.rb +++ b/ruby/spec/ruby/core/string/fixtures/classes.rb @@ -46,4 +46,15 @@ def initialize(str) self.replace(str) end end + + class SpecialVarProcessor + def process(match) + if $~ != nil + str = $~[0] + else + str = "unset" + end + "<#{str}>" + end + end end diff --git a/ruby/spec/ruby/core/string/force_encoding_spec.rb b/ruby/spec/ruby/core/string/force_encoding_spec.rb index 56d9b1e9b..f37aaf9eb 100644 --- a/ruby/spec/ruby/core/string/force_encoding_spec.rb +++ b/ruby/spec/ruby/core/string/force_encoding_spec.rb @@ -60,12 +60,12 @@ end it "does not transcode self" do - str = "\u{8612}" + str = "é" str.dup.force_encoding('utf-16le').should_not == str.encode('utf-16le') end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do str = "abcd".freeze - -> { str.force_encoding(str.encoding) }.should raise_error(frozen_error_class) + -> { str.force_encoding(str.encoding) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/grapheme_clusters_spec.rb b/ruby/spec/ruby/core/string/grapheme_clusters_spec.rb index 0cba0e421..3046265a1 100644 --- a/ruby/spec/ruby/core/string/grapheme_clusters_spec.rb +++ b/ruby/spec/ruby/core/string/grapheme_clusters_spec.rb @@ -1,15 +1,13 @@ require_relative 'shared/chars' require_relative 'shared/grapheme_clusters' -ruby_version_is "2.5" do - describe "String#grapheme_clusters" do - it_behaves_like :string_chars, :grapheme_clusters - it_behaves_like :string_grapheme_clusters, :grapheme_clusters +describe "String#grapheme_clusters" do + it_behaves_like :string_chars, :grapheme_clusters + it_behaves_like :string_grapheme_clusters, :grapheme_clusters - it "returns an array when no block given" do - string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}" - string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"] + it "returns an array when no block given" do + string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}" + string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"] - end end end diff --git a/ruby/spec/ruby/core/string/gsub_spec.rb b/ruby/spec/ruby/core/string/gsub_spec.rb index f1d2d5ac0..ad41b7e0a 100644 --- a/ruby/spec/ruby/core/string/gsub_spec.rb +++ b/ruby/spec/ruby/core/string/gsub_spec.rb @@ -171,14 +171,14 @@ hello_t.taint; a_t.taint; empty_t.taint - hello_t.gsub(/./, a).tainted?.should == true - hello_t.gsub(/./, empty).tainted?.should == true + hello_t.gsub(/./, a).should.tainted? + hello_t.gsub(/./, empty).should.tainted? - hello.gsub(/./, a_t).tainted?.should == true - hello.gsub(/./, empty_t).tainted?.should == true - hello.gsub(//, empty_t).tainted?.should == true + hello.gsub(/./, a_t).should.tainted? + hello.gsub(/./, empty_t).should.tainted? + hello.gsub(//, empty_t).should.tainted? - hello.gsub(//.taint, "foo").tainted?.should == false + hello.gsub(//.taint, "foo").should_not.tainted? end end @@ -199,14 +199,14 @@ hello_t.untrust; a_t.untrust; empty_t.untrust - hello_t.gsub(/./, a).untrusted?.should == true - hello_t.gsub(/./, empty).untrusted?.should == true + hello_t.gsub(/./, a).should.untrusted? + hello_t.gsub(/./, empty).should.untrusted? - hello.gsub(/./, a_t).untrusted?.should == true - hello.gsub(/./, empty_t).untrusted?.should == true - hello.gsub(//, empty_t).untrusted?.should == true + hello.gsub(/./, a_t).should.untrusted? + hello.gsub(/./, empty_t).should.untrusted? + hello.gsub(//, empty_t).should.untrusted? - hello.gsub(//.untrust, "foo").untrusted?.should == false + hello.gsub(//.untrust, "foo").should_not.untrusted? end end @@ -236,11 +236,22 @@ def replacement.to_str() "hello_replacement" end -> { "hello".gsub(/[aeiou]/, nil) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(String) + StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(String) + end end # Note: $~ cannot be tested because mspec messes with it @@ -464,6 +475,11 @@ def replacement.to_str() "hello_replacement" end offsets.should == [[1, 2], [4, 5]] end + it "does not set $~ for procs created from methods" do + str = "hello" + str.gsub("l", &StringSpecs::SpecialVarProcessor.new.method(:process)).should == "heo" + end + it "restores $~ after leaving the block" do [/./, "l"].each do |pattern| old_md = nil @@ -521,14 +537,14 @@ def obj.to_s() "ok" end hello_t.untrust; a_t.untrust; empty_t.untrust - hello_t.gsub(/./) { a }.untrusted?.should == true - hello_t.gsub(/./) { empty }.untrusted?.should == true + hello_t.gsub(/./) { a }.should.untrusted? + hello_t.gsub(/./) { empty }.should.untrusted? - hello.gsub(/./) { a_t }.untrusted?.should == true - hello.gsub(/./) { empty_t }.untrusted?.should == true - hello.gsub(//) { empty_t }.untrusted?.should == true + hello.gsub(/./) { a_t }.should.untrusted? + hello.gsub(/./) { empty_t }.should.untrusted? + hello.gsub(//) { empty_t }.should.untrusted? - hello.gsub(//.untrust) { "foo" }.untrusted?.should == false + hello.gsub(//.untrust) { "foo" }.should_not.untrusted? end end @@ -578,6 +594,14 @@ def obj.to_s() "ok" end end end +describe "String#gsub with a string pattern" do + it "handles multibyte characters" do + "é".gsub("é", "â").should == "â" + "aé".gsub("é", "â").should == "aâ" + "éa".gsub("é", "â").should == "âa" + end +end + describe "String#gsub! with pattern and replacement" do it "modifies self in place and returns self" do a = "hello" @@ -594,14 +618,14 @@ def obj.to_s() "ok" end ruby_version_is ''...'2.7' do it "taints self if replacement is tainted" do a = "hello" - a.gsub!(/./.taint, "foo").tainted?.should == false - a.gsub!(/./, "foo".taint).tainted?.should == true + a.gsub!(/./.taint, "foo").should_not.tainted? + a.gsub!(/./, "foo".taint).should.tainted? end it "untrusts self if replacement is untrusted" do a = "hello" - a.gsub!(/./.untrust, "foo").untrusted?.should == false - a.gsub!(/./, "foo".untrust).untrusted?.should == true + a.gsub!(/./.untrust, "foo").should_not.untrusted? + a.gsub!(/./, "foo".untrust).should.untrusted? end end @@ -613,13 +637,13 @@ def obj.to_s() "ok" end end # See [ruby-core:23666] - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do s = "hello" s.freeze - -> { s.gsub!(/ROAR/, "x") }.should raise_error(frozen_error_class) - -> { s.gsub!(/e/, "e") }.should raise_error(frozen_error_class) - -> { s.gsub!(/[aeiou]/, '*') }.should raise_error(frozen_error_class) + -> { s.gsub!(/ROAR/, "x") }.should raise_error(FrozenError) + -> { s.gsub!(/e/, "e") }.should raise_error(FrozenError) + -> { s.gsub!(/[aeiou]/, '*') }.should raise_error(FrozenError) end end @@ -633,14 +657,14 @@ def obj.to_s() "ok" end ruby_version_is ''...'2.7' do it "taints self if block's result is tainted" do a = "hello" - a.gsub!(/./.taint) { "foo" }.tainted?.should == false - a.gsub!(/./) { "foo".taint }.tainted?.should == true + a.gsub!(/./.taint) { "foo" }.should_not.tainted? + a.gsub!(/./) { "foo".taint }.should.tainted? end it "untrusts self if block's result is untrusted" do a = "hello" - a.gsub!(/./.untrust) { "foo" }.untrusted?.should == false - a.gsub!(/./) { "foo".untrust }.untrusted?.should == true + a.gsub!(/./.untrust) { "foo" }.should_not.untrusted? + a.gsub!(/./) { "foo".untrust }.should.untrusted? end end @@ -652,13 +676,13 @@ def obj.to_s() "ok" end end # See [ruby-core:23663] - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do s = "hello" s.freeze - -> { s.gsub!(/ROAR/) { "x" } }.should raise_error(frozen_error_class) - -> { s.gsub!(/e/) { "e" } }.should raise_error(frozen_error_class) - -> { s.gsub!(/[aeiou]/) { '*' } }.should raise_error(frozen_error_class) + -> { s.gsub!(/ROAR/) { "x" } }.should raise_error(FrozenError) + -> { s.gsub!(/e/) { "e" } }.should raise_error(FrozenError) + -> { s.gsub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError) end it "uses the compatible encoding if they are compatible" do diff --git a/ruby/spec/ruby/core/string/index_spec.rb b/ruby/spec/ruby/core/string/index_spec.rb index ca62911db..5d77a88e4 100644 --- a/ruby/spec/ruby/core/string/index_spec.rb +++ b/ruby/spec/ruby/core/string/index_spec.rb @@ -27,7 +27,7 @@ "abc".index("c", offset).should == 2 end - it "raises a TypeError if passed a Fixnum" do + it "raises a TypeError if passed an Integer" do -> { "abc".index 97 }.should raise_error(TypeError) end end @@ -146,6 +146,7 @@ it "returns the character index after offset" do "ã‚れã‚れ".index("ã‚", 1).should == 2 + "ã‚りãŒã¨ã†ã‚りãŒã¨ã†".index("ãŒ", 3).should == 7 end it "returns the character index after a partial first match" do diff --git a/ruby/spec/ruby/core/string/insert_spec.rb b/ruby/spec/ruby/core/string/insert_spec.rb index de7c12423..752cbb2f3 100644 --- a/ruby/spec/ruby/core/string/insert_spec.rb +++ b/ruby/spec/ruby/core/string/insert_spec.rb @@ -44,12 +44,12 @@ ruby_version_is ''...'2.7' do it "taints self if string to insert is tainted" do str = "abcd" - str.insert(0, "T".taint).tainted?.should == true + str.insert(0, "T".taint).should.tainted? str = "abcd" other = mock('T') def other.to_str() "T".taint end - str.insert(0, other).tainted?.should == true + str.insert(0, other).should.tainted? end end @@ -59,10 +59,10 @@ def other.to_str() "T".taint end -> { "abcd".insert(-6, mock('x')) }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do str = "abcd".freeze - -> { str.insert(4, '') }.should raise_error(frozen_error_class) - -> { str.insert(4, 'X') }.should raise_error(frozen_error_class) + -> { str.insert(4, '') }.should raise_error(FrozenError) + -> { str.insert(4, 'X') }.should raise_error(FrozenError) end it "inserts a character into a multibyte encoded string" do diff --git a/ruby/spec/ruby/core/string/inspect_spec.rb b/ruby/spec/ruby/core/string/inspect_spec.rb index 8ddbae132..98b5b32b6 100644 --- a/ruby/spec/ruby/core/string/inspect_spec.rb +++ b/ruby/spec/ruby/core/string/inspect_spec.rb @@ -5,13 +5,13 @@ describe "String#inspect" do ruby_version_is ''...'2.7' do it "taints the result if self is tainted" do - "foo".taint.inspect.tainted?.should == true - "foo\n".taint.inspect.tainted?.should == true + "foo".taint.inspect.should.tainted? + "foo\n".taint.inspect.should.tainted? end it "untrusts the result if self is untrusted" do - "foo".untrust.inspect.untrusted?.should == true - "foo\n".untrust.inspect.untrusted?.should == true + "foo".untrust.inspect.should.untrusted? + "foo\n".untrust.inspect.should.untrusted? end end @@ -319,6 +319,10 @@ 0.chr.inspect.should == '"\\x00"' end + it "uses \\x notation for broken UTF-8 sequences" do + "\xF0\x9F".inspect.should == '"\\xF0\\x9F"' + end + describe "when default external is UTF-8" do before :each do @extenc, Encoding.default_external = Encoding.default_external, Encoding::UTF_8 @@ -498,5 +502,11 @@ "\u{3042}".encode("EUC-JP").inspect.should == '"\\x{A4A2}"' end end + + describe "and the string has both ASCII-compatible and ASCII-incompatible chars" do + it "returns a string with the non-ASCII characters replaced by \\u notation" do + "hello привет".encode("utf-16le").inspect.should == '"hello \\u043F\\u0440\\u0438\\u0432\\u0435\\u0442"' + end + end end end diff --git a/ruby/spec/ruby/core/string/ljust_spec.rb b/ruby/spec/ruby/core/string/ljust_spec.rb index f377e3977..0c3b2a2f4 100644 --- a/ruby/spec/ruby/core/string/ljust_spec.rb +++ b/ruby/spec/ruby/core/string/ljust_spec.rb @@ -33,11 +33,11 @@ ruby_version_is ''...'2.7' do it "taints result when self or padstr is tainted" do - "x".taint.ljust(4).tainted?.should == true - "x".taint.ljust(0).tainted?.should == true - "".taint.ljust(0).tainted?.should == true - "x".taint.ljust(4, "*").tainted?.should == true - "x".ljust(4, "*".taint).tainted?.should == true + "x".taint.ljust(4).should.tainted? + "x".taint.ljust(0).should.tainted? + "".taint.ljust(0).should.tainted? + "x".taint.ljust(4, "*").should.tainted? + "x".ljust(4, "*".taint).should.tainted? end end @@ -74,13 +74,26 @@ -> { "hello".ljust(10, '') }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) - "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/string/lstrip_spec.rb b/ruby/spec/ruby/core/string/lstrip_spec.rb index b1a4e8541..20e4cdeab 100644 --- a/ruby/spec/ruby/core/string/lstrip_spec.rb +++ b/ruby/spec/ruby/core/string/lstrip_spec.rb @@ -1,24 +1,29 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#lstrip" do + it_behaves_like :string_strip, :lstrip + it "returns a copy of self with leading whitespace removed" do " hello ".lstrip.should == "hello " " hello world ".lstrip.should == "hello world " "\n\r\t\n\v\r hello world ".lstrip.should == "hello world " "hello".lstrip.should == "hello" - "\000 \000hello\000 \000".lstrip.should == "\000 \000hello\000 \000" end - it "does not strip leading \\0" do - "\x00hello".lstrip.should == "\x00hello" + ruby_version_is '3.1' do + it "strips leading \\0" do + "\x00hello".lstrip.should == "hello" + "\000 \000hello\000 \000".lstrip.should == "hello\000 \000" + end end ruby_version_is ''...'2.7' do it "taints the result when self is tainted" do - "".taint.lstrip.tainted?.should == true - "ok".taint.lstrip.tainted?.should == true - " ok".taint.lstrip.tainted?.should == true + "".taint.lstrip.should.tainted? + "ok".taint.lstrip.should.tainted? + " ok".taint.lstrip.should.tainted? end end end @@ -28,10 +33,14 @@ a = " hello " a.lstrip!.should equal(a) a.should == "hello " + end - a = "\000 \000hello\000 \000" - a.lstrip! - a.should == "\000 \000hello\000 \000" + ruby_version_is '3.1' do + it "strips leading \\0" do + a = "\000 \000hello\000 \000" + a.lstrip! + a.should == "hello\000 \000" + end end it "returns nil if no modifications were made" do @@ -40,13 +49,13 @@ a.should == "hello" end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { " hello ".freeze.lstrip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { " hello ".freeze.lstrip! }.should raise_error(FrozenError) end # see [ruby-core:23657] - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> { "hello".freeze.lstrip! }.should raise_error(frozen_error_class) - -> { "".freeze.lstrip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> { "hello".freeze.lstrip! }.should raise_error(FrozenError) + -> { "".freeze.lstrip! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/match_spec.rb b/ruby/spec/ruby/core/string/match_spec.rb index 78b94baa4..5e988f34c 100644 --- a/ruby/spec/ruby/core/string/match_spec.rb +++ b/ruby/spec/ruby/core/string/match_spec.rb @@ -137,7 +137,7 @@ def obj.method_missing(*args) "." end end it "calls match on the regular expression" do - regexp = /./ + regexp = /./.dup regexp.should_receive(:match).and_return(:foo) 'hello'.match(regexp).should == :foo end diff --git a/ruby/spec/ruby/core/string/modulo_spec.rb b/ruby/spec/ruby/core/string/modulo_spec.rb index a16112bf4..dc11ced4e 100644 --- a/ruby/spec/ruby/core/string/modulo_spec.rb +++ b/ruby/spec/ruby/core/string/modulo_spec.rb @@ -1,7 +1,21 @@ require_relative '../../spec_helper' +require_relative '../kernel/shared/sprintf' +require_relative '../kernel/shared/sprintf_encoding' require_relative 'fixtures/classes' require_relative '../../shared/hash/key_error' +describe "String#%" do + it_behaves_like :kernel_sprintf, -> format, *args { + format % args + } + + it_behaves_like :kernel_sprintf_encoding, -> format, *args { + format % args + } +end + +# TODO: these specs are mostly redundant with kernel/shared/sprintf.rb specs. +# These specs should be moved there and deduplicated. describe "String#%" do context "when key is missing from passed-in hash" do it_behaves_like :key_error, -> obj, key { "%{#{key}}" % obj }, { a: 5 } @@ -36,18 +50,9 @@ end end - ruby_version_is ""..."2.5" do - it "formats single % character at the end as literal %" do - ("%" % []).should == "%" - ("foo%" % []).should == "foo%" - end - end - - ruby_version_is "2.5" do - it "raises an error if single % appears at the end" do - -> { ("%" % []) }.should raise_error(ArgumentError) - -> { ("foo%" % [])}.should raise_error(ArgumentError) - end + it "raises an error if single % appears at the end" do + -> { ("%" % []) }.should raise_error(ArgumentError) + -> { ("foo%" % [])}.should raise_error(ArgumentError) end it "formats single % character before a newline as literal %" do @@ -314,8 +319,8 @@ def universal.to_f() 0.0 end subcls_format.taint format.taint - (format % universal).tainted?.should == true - (subcls_format % universal).tainted?.should == true + (format % universal).should.tainted? + (subcls_format % universal).should.tainted? end end end @@ -578,12 +583,12 @@ def obj.inspect() "obj" end obj = mock('x') def obj.inspect() "x".taint end - ("%p" % obj).tainted?.should == true + ("%p" % obj).should.tainted? obj = mock('x'); obj.taint def obj.inspect() "x" end - ("%p" % obj).tainted?.should == false + ("%p" % obj).should_not.tainted? end end @@ -617,8 +622,8 @@ def obj.to_s() "obj" end ruby_version_is ''...'2.7' do it "taints result for %s when argument is tainted" do - ("%s" % "x".taint).tainted?.should == true - ("%s" % mock('x').taint).tainted?.should == true + ("%s" % "x".taint).should.tainted? + ("%s" % mock('x').taint).should.tainted? end end @@ -784,7 +789,7 @@ def obj.to_s() "obj" end ruby_version_is ''...'2.7' do it "doesn't taint the result for #{format} when argument is tainted" do - (format % "5".taint).tainted?.should == false + (format % "5".taint).should_not.tainted? end end end diff --git a/ruby/spec/ruby/core/string/ord_spec.rb b/ruby/spec/ruby/core/string/ord_spec.rb index 0f5a3f6a3..cfc630a12 100644 --- a/ruby/spec/ruby/core/string/ord_spec.rb +++ b/ruby/spec/ruby/core/string/ord_spec.rb @@ -1,8 +1,8 @@ require_relative '../../spec_helper' describe "String#ord" do - it "returns a Fixnum" do - 'a'.ord.should be_an_instance_of(Fixnum) + it "returns an Integer" do + 'a'.ord.should be_an_instance_of(Integer) end it "returns the codepoint of the first character in the String" do diff --git a/ruby/spec/ruby/core/string/partition_spec.rb b/ruby/spec/ruby/core/string/partition_spec.rb index 996368d6a..98311f2be 100644 --- a/ruby/spec/ruby/core/string/partition_spec.rb +++ b/ruby/spec/ruby/core/string/partition_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/partition' describe "String#partition with String" do + it_behaves_like :string_partition, :partition + it "returns an array of substrings based on splitting on the given string" do "hello world".partition("o").should == ["hell", "o", " world"] end diff --git a/ruby/spec/ruby/core/string/percent_spec.rb b/ruby/spec/ruby/core/string/percent_spec.rb deleted file mode 100644 index e3460522b..000000000 --- a/ruby/spec/ruby/core/string/percent_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require_relative '../../spec_helper' -require_relative '../kernel/shared/sprintf' -require_relative '../kernel/shared/sprintf_encoding' - -describe "String#%" do - it_behaves_like :kernel_sprintf, -> format, *args { - format % args - } - - it_behaves_like :kernel_sprintf_encoding, -> format, *args { - format % args - } -end diff --git a/ruby/spec/ruby/core/string/prepend_spec.rb b/ruby/spec/ruby/core/string/prepend_spec.rb index c20c5a9e5..a6074be3c 100644 --- a/ruby/spec/ruby/core/string/prepend_spec.rb +++ b/ruby/spec/ruby/core/string/prepend_spec.rb @@ -20,12 +20,12 @@ -> { 'hello '.prepend mock('x') }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "hello" a.freeze - -> { a.prepend "" }.should raise_error(frozen_error_class) - -> { a.prepend "test" }.should raise_error(frozen_error_class) + -> { a.prepend "" }.should raise_error(FrozenError) + -> { a.prepend "test" }.should raise_error(FrozenError) end it "works when given a subclass instance" do diff --git a/ruby/spec/ruby/core/string/reverse_spec.rb b/ruby/spec/ruby/core/string/reverse_spec.rb index eef46063a..b45ff2cf6 100644 --- a/ruby/spec/ruby/core/string/reverse_spec.rb +++ b/ruby/spec/ruby/core/string/reverse_spec.rb @@ -10,17 +10,32 @@ "".reverse.should == "" end + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(String) + StringSpecs::MyString.new("m").reverse.should be_an_instance_of(String) + StringSpecs::MyString.new("").reverse.should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("m").reverse.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").reverse.should be_an_instance_of(StringSpecs::MyString) + end + end + ruby_version_is ''...'2.7' do it "taints the result if self is tainted" do - "".taint.reverse.tainted?.should == true - "m".taint.reverse.tainted?.should == true + "".taint.reverse.should.tainted? + "m".taint.reverse.should.tainted? end end it "reverses a string with multi byte characters" do "微軟正黑體".reverse.should == "體黑正軟微" end - end describe "String#reverse!" do @@ -32,14 +47,14 @@ "".reverse!.should == "" end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { "anna".freeze.reverse! }.should raise_error(frozen_error_class) - -> { "hello".freeze.reverse! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { "anna".freeze.reverse! }.should raise_error(FrozenError) + -> { "hello".freeze.reverse! }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> { "".freeze.reverse! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> { "".freeze.reverse! }.should raise_error(FrozenError) end it "reverses a string with multi byte characters" do diff --git a/ruby/spec/ruby/core/string/rindex_spec.rb b/ruby/spec/ruby/core/string/rindex_spec.rb index e021486bc..7a6af0c9d 100644 --- a/ruby/spec/ruby/core/string/rindex_spec.rb +++ b/ruby/spec/ruby/core/string/rindex_spec.rb @@ -4,7 +4,7 @@ require_relative 'fixtures/utf-8-encoding' describe "String#rindex with object" do - it "raises a TypeError if obj isn't a String, Fixnum or Regexp" do + it "raises a TypeError if obj isn't a String, Integer or Regexp" do not_supported_on :opal do -> { "hello".rindex(:sym) }.should raise_error(TypeError) end diff --git a/ruby/spec/ruby/core/string/rjust_spec.rb b/ruby/spec/ruby/core/string/rjust_spec.rb index 9285ecb6a..f51aacff4 100644 --- a/ruby/spec/ruby/core/string/rjust_spec.rb +++ b/ruby/spec/ruby/core/string/rjust_spec.rb @@ -33,11 +33,11 @@ ruby_version_is ''...'2.7' do it "taints result when self or padstr is tainted" do - "x".taint.rjust(4).tainted?.should == true - "x".taint.rjust(0).tainted?.should == true - "".taint.rjust(0).tainted?.should == true - "x".taint.rjust(4, "*").tainted?.should == true - "x".rjust(4, "*".taint).tainted?.should == true + "x".taint.rjust(4).should.tainted? + "x".taint.rjust(0).should.tainted? + "".taint.rjust(0).should.tainted? + "x".taint.rjust(4, "*").should.tainted? + "x".rjust(4, "*".taint).should.tainted? end end @@ -74,13 +74,26 @@ -> { "hello".rjust(10, '') }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) - "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/ruby/spec/ruby/core/string/rpartition_spec.rb b/ruby/spec/ruby/core/string/rpartition_spec.rb index c6428636f..c8f9afaee 100644 --- a/ruby/spec/ruby/core/string/rpartition_spec.rb +++ b/ruby/spec/ruby/core/string/rpartition_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/partition' describe "String#rpartition with String" do + it_behaves_like :string_partition, :rpartition + it "returns an array of substrings based on splitting on the given string" do "hello world".rpartition("o").should == ["hello w", "o", "rld"] end @@ -11,6 +14,19 @@ "hello".rpartition("hello").should == ["", "hello", ""] end + it "returns original string if regexp doesn't match" do + "hello".rpartition("/x/").should == ["", "", "hello"] + end + + it "returns new object if doesn't match" do + str = "hello" + str.rpartition("/no_match/").last.should_not.equal?(str) + end + + it "handles multibyte string correctly" do + "ユーザ@ドメイン".rpartition(/@/).should == ["ユーザ", "@", "ドメイン"] + end + it "accepts regexp" do "hello!".rpartition(/l./).should == ["hel", "lo", "!"] end diff --git a/ruby/spec/ruby/core/string/rstrip_spec.rb b/ruby/spec/ruby/core/string/rstrip_spec.rb index 9482765e8..a1453f91f 100644 --- a/ruby/spec/ruby/core/string/rstrip_spec.rb +++ b/ruby/spec/ruby/core/string/rstrip_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#rstrip" do + it_behaves_like :string_strip, :rstrip + it "returns a copy of self with trailing whitespace removed" do " hello ".rstrip.should == " hello" " hello world ".rstrip.should == " hello world" @@ -16,9 +19,9 @@ ruby_version_is ''...'2.7' do it "taints the result when self is tainted" do - "".taint.rstrip.tainted?.should == true - "ok".taint.rstrip.tainted?.should == true - "ok ".taint.rstrip.tainted?.should == true + "".taint.rstrip.should.tainted? + "ok".taint.rstrip.should.tainted? + "ok ".taint.rstrip.should.tainted? end end end @@ -42,13 +45,13 @@ a.should == "hello" end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { " hello ".freeze.rstrip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { " hello ".freeze.rstrip! }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> { "hello".freeze.rstrip! }.should raise_error(frozen_error_class) - -> { "".freeze.rstrip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> { "hello".freeze.rstrip! }.should raise_error(FrozenError) + -> { "".freeze.rstrip! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/scan_spec.rb b/ruby/spec/ruby/core/string/scan_spec.rb index 024e97022..5f86dbbec 100644 --- a/ruby/spec/ruby/core/string/scan_spec.rb +++ b/ruby/spec/ruby/core/string/scan_spec.rb @@ -198,4 +198,12 @@ third.should == 'c'; end end + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("abc").scan(/./) { |s| a << s.class } + a.should == [String, String, String] + end + end end diff --git a/ruby/spec/ruby/core/string/scrub_spec.rb b/ruby/spec/ruby/core/string/scrub_spec.rb index 390035ef3..313739929 100644 --- a/ruby/spec/ruby/core/string/scrub_spec.rb +++ b/ruby/spec/ruby/core/string/scrub_spec.rb @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "String#scrub with a default replacement" do it "returns self for valid strings" do @@ -19,12 +20,25 @@ input.scrub.should == "foo" end - it "replaces invalid byte sequences when using ASCII as the input encoding" do xE3x80 = [0xE3, 0x80].pack('CC').force_encoding 'utf-8' input = "abc\u3042#{xE3x80}".force_encoding('ASCII') input.scrub.should == "abc?????" end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub.should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(StringSpecs::MyString) + end + end end describe "String#scrub with a custom replacement" do @@ -39,6 +53,15 @@ "abc\u3042#{x81}".scrub("*").should == "abc\u3042*" end + it "replaces invalid byte sequences in frozen strings" do + x81 = [0x81].pack('C').force_encoding('utf-8') + (-"abc\u3042#{x81}").scrub("*").should == "abc\u3042*" + + leading_surrogate = [0x00, 0xD8] + utf16_str = ("abc".encode('UTF-16LE').bytes + leading_surrogate).pack('c*').force_encoding('UTF-16LE') + (-(utf16_str)).scrub("*".encode('UTF-16LE')).should == "abc*".encode('UTF-16LE') + end + it "replaces an incomplete character at the end with a single replacement" do xE3x80 = [0xE3, 0x80].pack('CC').force_encoding 'utf-8' xE3x80.scrub("*").should == "*" @@ -58,6 +81,14 @@ block.should raise_error(TypeError) end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub("*").should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub("*").should be_an_instance_of(String) + end + end end describe "String#scrub with a block" do @@ -82,6 +113,14 @@ replaced.should == "€€" end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub { |b| "*" }.should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub { |b| "<#{b.unpack("H*")[0]}>" }.should be_an_instance_of(String) + end + end end describe "String#scrub!" do @@ -98,4 +137,24 @@ input.scrub! { |b| "" } input.should == "a" end + + it "maintains the state of frozen strings that are already valid" do + input = "a" + input.freeze + input.scrub! + input.frozen?.should be_true + end + + it "preserves the instance variables of already valid strings" do + input = "a" + input.instance_variable_set(:@a, 'b') + input.scrub! + input.instance_variable_get(:@a).should == 'b' + end + + it "accepts a frozen string as a replacement" do + input = "a\xE2" + input.scrub!('.'.freeze) + input.should == 'a.' + end end diff --git a/ruby/spec/ruby/core/string/setbyte_spec.rb b/ruby/spec/ruby/core/string/setbyte_spec.rb index 6912b1b66..03e5bad88 100644 --- a/ruby/spec/ruby/core/string/setbyte_spec.rb +++ b/ruby/spec/ruby/core/string/setbyte_spec.rb @@ -75,10 +75,10 @@ str1.should_not == "ledgehog" end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do str = "cold".freeze str.frozen?.should be_true - -> { str.setbyte(3,96) }.should raise_error(frozen_error_class) + -> { str.setbyte(3,96) }.should raise_error(FrozenError) end it "raises a TypeError unless the second argument is an Integer" do diff --git a/ruby/spec/ruby/core/string/shared/chars.rb b/ruby/spec/ruby/core/string/shared/chars.rb index 9c7a4deb8..1f045e453 100644 --- a/ruby/spec/ruby/core/string/shared/chars.rb +++ b/ruby/spec/ruby/core/string/shared/chars.rb @@ -69,11 +69,11 @@ str = "hello" str.send(@method) do |x| - x.tainted?.should == false + x.should_not.tainted? end str.dup.taint.send(@method) do |x| - x.tainted?.should == true + x.should.tainted? end end end diff --git a/ruby/spec/ruby/core/string/shared/codepoints.rb b/ruby/spec/ruby/core/string/shared/codepoints.rb index e94a57f48..0b2e078e0 100644 --- a/ruby/spec/ruby/core/string/shared/codepoints.rb +++ b/ruby/spec/ruby/core/string/shared/codepoints.rb @@ -26,9 +26,9 @@ -> { s.send(@method) { } }.should raise_error(ArgumentError) end - it "yields codepoints as Fixnums" do + it "yields codepoints as Integers" do "glark\u{20}".send(@method).to_a.each do |codepoint| - codepoint.should be_an_instance_of(Fixnum) + codepoint.should be_an_instance_of(Integer) end end diff --git a/ruby/spec/ruby/core/string/shared/concat.rb b/ruby/spec/ruby/core/string/shared/concat.rb index 435158496..d6ffad7d4 100644 --- a/ruby/spec/ruby/core/string/shared/concat.rb +++ b/ruby/spec/ruby/core/string/shared/concat.rb @@ -17,12 +17,12 @@ -> { 'hello '.send(@method, mock('x')) }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "hello" a.freeze - -> { a.send(@method, "") }.should raise_error(frozen_error_class) - -> { a.send(@method, "test") }.should raise_error(frozen_error_class) + -> { a.send(@method, "") }.should raise_error(FrozenError) + -> { a.send(@method, "test") }.should raise_error(FrozenError) end it "returns a String when given a subclass instance" do @@ -41,13 +41,13 @@ ruby_version_is ''...'2.7' do it "taints self if other is tainted" do - "x".send(@method, "".taint).tainted?.should == true - "x".send(@method, "y".taint).tainted?.should == true + "x".send(@method, "".taint).should.tainted? + "x".send(@method, "y".taint).should.tainted? end it "untrusts self if other is untrusted" do - "x".send(@method, "".untrust).untrusted?.should == true - "x".send(@method, "y".untrust).untrusted?.should == true + "x".send(@method, "".untrust).should.untrusted? + "x".send(@method, "y".untrust).should.untrusted? end end @@ -89,12 +89,12 @@ -> { "".send(@method, x) }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "hello" a.freeze - -> { a.send(@method, 0) }.should raise_error(frozen_error_class) - -> { a.send(@method, 33) }.should raise_error(frozen_error_class) + -> { a.send(@method, 0) }.should raise_error(FrozenError) + -> { a.send(@method, 33) }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/string/shared/each_line.rb b/ruby/spec/ruby/core/string/shared/each_line.rb index 843b123f5..f9c910596 100644 --- a/ruby/spec/ruby/core/string/shared/each_line.rb +++ b/ruby/spec/ruby/core/string/shared/each_line.rb @@ -42,9 +42,9 @@ ruby_version_is ''...'2.7' do it "taints substrings that are passed to the block if self is tainted" do - "one\ntwo\r\nthree".taint.send(@method) { |s| s.tainted?.should == true } + "one\ntwo\r\nthree".taint.send(@method) { |s| s.should.tainted? } - "x.y.".send(@method, ".".taint) { |s| s.tainted?.should == false } + "x.y.".send(@method, ".".taint) { |s| s.should_not.tainted? } end end @@ -54,28 +54,14 @@ a.should == ["one\ntwo\r\nthree"] end - ruby_version_is ''...'2.5' do - it "yields paragraphs (broken by 2 or more successive newlines) when passed ''" do - a = [] - "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s } - a.should == ["hello\nworld\n\n\n", "and\nuniverse\n\n\n\n\n"] - - a = [] - "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s } - a.should == ["hello\nworld\n\n\n", "and\nuniverse\n\n\n\n\n", "dog"] - end - end - - ruby_version_is '2.5' do - it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do - a = [] - "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s } - a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"] + it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do + a = [] + "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s } + a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"] - a = [] - "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s } - a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"] - end + a = [] + "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s } + a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"] end describe "uses $/" do @@ -84,7 +70,7 @@ end after :each do - $/ = @before_separator + suppress_warning {$/ = @before_separator} end it "as the separator when none is given" do @@ -96,10 +82,10 @@ expected = [] str.send(@method, sep) { |x| expected << x } - $/ = sep + suppress_warning {$/ = sep} actual = [] - str.send(@method) { |x| actual << x } + suppress_warning {str.send(@method) { |x| actual << x }} actual.should == expected end @@ -107,10 +93,20 @@ end end - it "yields subclass instances for subclasses" do - a = [] - StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } - a.should == [StringSpecs::MyString, StringSpecs::MyString] + ruby_version_is ''...'3.0' do + it "yields subclass instances for subclasses" do + a = [] + StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } + a.should == [StringSpecs::MyString, StringSpecs::MyString] + end + end + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } + a.should == [String, String] + end end it "returns self" do diff --git a/ruby/spec/ruby/core/string/shared/eql.rb b/ruby/spec/ruby/core/string/shared/eql.rb index 85b861f4f..b57d6895f 100644 --- a/ruby/spec/ruby/core/string/shared/eql.rb +++ b/ruby/spec/ruby/core/string/shared/eql.rb @@ -21,7 +21,7 @@ end it "considers encoding compatibility" do - "hello".force_encoding("utf-8").send(@method, "hello".force_encoding("utf-32le")).should be_false + "abcd".force_encoding("utf-8").send(@method, "abcd".force_encoding("utf-32le")).should be_false end it "ignores subclass differences" do diff --git a/ruby/spec/ruby/core/string/shared/length.rb b/ruby/spec/ruby/core/string/shared/length.rb index f387fb251..e93196145 100644 --- a/ruby/spec/ruby/core/string/shared/length.rb +++ b/ruby/spec/ruby/core/string/shared/length.rb @@ -23,4 +23,33 @@ str.force_encoding('BINARY').send(@method).should == 12 end + + it "returns the correct length after force_encoding(BINARY)" do + utf8 = "ã‚" + ascii = "a" + concat = utf8 + ascii + + concat.encoding.should == Encoding::UTF_8 + concat.bytesize.should == 4 + + concat.size.should == 2 + concat.force_encoding(Encoding::ASCII_8BIT) + concat.size.should == 4 + end + + it "adds 1 for every invalid byte in UTF-8" do + "\xF4\x90\x80\x80".size.should == 4 + "a\xF4\x90\x80\x80b".size.should == 6 + "é\xF4\x90\x80\x80è".size.should == 6 + end + + it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do + "\x00\xd8".force_encoding("UTF-16LE").size.should == 1 + "\xd8\x00".force_encoding("UTF-16BE").size.should == 1 + end + + it "adds 1 for a broken sequence in UTF-32" do + "\x04\x03\x02\x01".force_encoding("UTF-32LE").size.should == 1 + "\x01\x02\x03\x04".force_encoding("UTF-32BE").size.should == 1 + end end diff --git a/ruby/spec/ruby/core/string/shared/partition.rb b/ruby/spec/ruby/core/string/shared/partition.rb new file mode 100644 index 000000000..7dc3d9cc0 --- /dev/null +++ b/ruby/spec/ruby/core/string/shared/partition.rb @@ -0,0 +1,36 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :string_partition, shared: true do + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").send(@method, "l").each do |item| + item.should be_an_instance_of(String) + end + + StringSpecs::MyString.new("hello").send(@method, "x").each do |item| + item.should be_an_instance_of(String) + end + + StringSpecs::MyString.new("hello").send(@method, /l./).each do |item| + item.should be_an_instance_of(String) + end + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").send(@method, StringSpecs::MyString.new("l")).each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + + StringSpecs::MyString.new("hello").send(@method, "x").each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + + StringSpecs::MyString.new("hello").send(@method, /l./).each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + end + end +end diff --git a/ruby/spec/ruby/core/string/shared/replace.rb b/ruby/spec/ruby/core/string/shared/replace.rb index 620021eb9..8dfac49f0 100644 --- a/ruby/spec/ruby/core/string/shared/replace.rb +++ b/ruby/spec/ruby/core/string/shared/replace.rb @@ -15,28 +15,28 @@ a = "" b = "".taint a.send(@method, b) - a.tainted?.should == true + a.should.tainted? end it "does not untaint self if other is untainted" do a = "".taint b = "" a.send(@method, b) - a.tainted?.should == true + a.should.tainted? end it "untrusts self if other is untrusted" do a = "" b = "".untrust a.send(@method, b) - a.untrusted?.should == true + a.should.untrusted? end it "does not trust self if other is trusted" do a = "".untrust b = "" a.send(@method, b) - a.untrusted?.should == true + a.should.untrusted? end end @@ -64,14 +64,14 @@ -> { "hello".send(@method, mock('x')) }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do + it "raises a FrozenError on a frozen instance that is modified" do a = "hello".freeze - -> { a.send(@method, "world") }.should raise_error(frozen_error_class) + -> { a.send(@method, "world") }.should raise_error(FrozenError) end # see [ruby-core:23666] - it "raises a #{frozen_error_class} on a frozen instance when self-replacing" do + it "raises a FrozenError on a frozen instance when self-replacing" do a = "hello".freeze - -> { a.send(@method, a) }.should raise_error(frozen_error_class) + -> { a.send(@method, a) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/shared/slice.rb b/ruby/spec/ruby/core/string/shared/slice.rb index b19200536..1db8fd673 100644 --- a/ruby/spec/ruby/core/string/shared/slice.rb +++ b/ruby/spec/ruby/core/string/shared/slice.rb @@ -85,9 +85,9 @@ str = "hello world" str.taint - str.send(@method, 0,0).tainted?.should == true - str.send(@method, 0,1).tainted?.should == true - str.send(@method, 2,1).tainted?.should == true + str.send(@method, 0,0).should.tainted? + str.send(@method, 0,1).should.tainted? + str.send(@method, 2,1).should.tainted? end end @@ -121,6 +121,8 @@ "x".send(@method, -2,0).should == nil "x".send(@method, -2,1).should == nil + + "x".send(@method, fixnum_max, 1).should == nil end it "returns nil if the length is negative" do @@ -161,11 +163,22 @@ -> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0,0).should be_an_instance_of(String) + s.send(@method, 0,4).should be_an_instance_of(String) + s.send(@method, 1,4).should be_an_instance_of(String) + end end it "handles repeated application" do @@ -241,20 +254,31 @@ str = "hello world" str.taint - str.send(@method, 0..0).tainted?.should == true - str.send(@method, 0...0).tainted?.should == true - str.send(@method, 0..1).tainted?.should == true - str.send(@method, 0...1).tainted?.should == true - str.send(@method, 2..3).tainted?.should == true - str.send(@method, 2..0).tainted?.should == true + str.send(@method, 0..0).should.tainted? + str.send(@method, 0...0).should.tainted? + str.send(@method, 0..1).should.tainted? + str.send(@method, 0...1).should.tainted? + str.send(@method, 2..3).should.tainted? + str.send(@method, 2..0).should.tainted? + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString) end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0...0).should be_an_instance_of(String) + s.send(@method, 0..4).should be_an_instance_of(String) + s.send(@method, 1..4).should be_an_instance_of(String) + end end it "calls to_int on range arguments" do @@ -293,6 +317,32 @@ "hello world".send(@method, 6..5).send(@method, -1..-1).should == nil "hello world".send(@method, 6..5).send(@method, 1..1).should == nil end + + it "raises a type error if a range is passed with a length" do + ->{ "hello".send(@method, 1..2, 1) }.should raise_error(TypeError) + end + + it "raises a RangeError if one of the bound is too big" do + -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError) + -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError) + end + + it "works with endless ranges" do + "hello there".send(@method, eval("(2..)")).should == "llo there" + "hello there".send(@method, eval("(2...)")).should == "llo there" + "hello there".send(@method, eval("(-4..)")).should == "here" + "hello there".send(@method, eval("(-4...)")).should == "here" + end + + ruby_version_is "2.7" do + it "works with beginless ranges" do + "hello there".send(@method, eval("(..5)")).should == "hello " + "hello there".send(@method, eval("(...5)")).should == "hello" + "hello there".send(@method, eval("(..-4)")).should == "hello th" + "hello there".send(@method, eval("(...-4)")).should == "hello t" + "hello there".send(@method, eval("(...nil)")).should == "hello there" + end + end end describe :string_slice_regexp, shared: true do @@ -318,7 +368,7 @@ tainted_re = /./ tainted_re.taint - str.send(@method, tainted_re).tainted?.should == true + str.send(@method, tainted_re).should.tainted? end end @@ -328,10 +378,20 @@ end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, //).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, //).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, //).should be_an_instance_of(String) + s.send(@method, /../).should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do @@ -375,9 +435,9 @@ tainted_re = /(.)(.)(.)/ tainted_re.taint - str.send(@method, tainted_re, 0).tainted?.should == true - str.send(@method, tainted_re, 1).tainted?.should == true - str.send(@method, tainted_re, -1).tainted?.should == true + str.send(@method, tainted_re, 0).should.tainted? + str.send(@method, tainted_re, 1).should.tainted? + str.send(@method, tainted_re, -1).should.tainted? end end @@ -416,10 +476,20 @@ -> { "hello".send(@method, /(.)(.)(.)/, nil) }.should raise_error(TypeError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(.)(.)/, 0).should be_an_instance_of(String) + s.send(@method, /(.)(.)/, 1).should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do @@ -473,11 +543,22 @@ -> { "hello".send(@method, o) }.should raise_error(TypeError) end - it "returns a subclass instance when given a subclass instance" do - s = StringSpecs::MyString.new("el") - r = "hello".send(@method, s) - r.should == "el" - r.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".send(@method, s) + r.should == "el" + r.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".send(@method, s) + r.should == "el" + r.should be_an_instance_of(String) + end end end @@ -547,9 +628,18 @@ -> { "hello".send(@method, /(?)/, '') }.should raise_error(IndexError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, /(?.)/, 'q').should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(?.)/, 'q').should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(?.)/, 'q').should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do diff --git a/ruby/spec/ruby/core/string/shared/strip.rb b/ruby/spec/ruby/core/string/shared/strip.rb new file mode 100644 index 000000000..9c232b469 --- /dev/null +++ b/ruby/spec/ruby/core/string/shared/strip.rb @@ -0,0 +1,20 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :string_strip, shared: true do + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) + end + end +end diff --git a/ruby/spec/ruby/core/string/shared/succ.rb b/ruby/spec/ruby/core/string/shared/succ.rb index 80e465910..25602103b 100644 --- a/ruby/spec/ruby/core/string/shared/succ.rb +++ b/ruby/spec/ruby/core/string/shared/succ.rb @@ -59,16 +59,26 @@ "\xFF\xFF".send(@method).should == "\x01\x00\x00" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do it "taints the result if self is tainted" do ["", "a", "z", "Z", "9", "\xFF", "\xFF\xFF"].each do |s| - s.taint.send(@method).tainted?.should == true + s.taint.send(@method).should.tainted? end end end @@ -83,8 +93,8 @@ end end - it "raises a #{frozen_error_class} if self is frozen" do - -> { "".freeze.send(@method) }.should raise_error(frozen_error_class) - -> { "abcd".freeze.send(@method) }.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { "".freeze.send(@method) }.should raise_error(FrozenError) + -> { "abcd".freeze.send(@method) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/shared/to_s.rb b/ruby/spec/ruby/core/string/shared/to_s.rb index 36283be4d..b8c9b8ab4 100644 --- a/ruby/spec/ruby/core/string/shared/to_s.rb +++ b/ruby/spec/ruby/core/string/shared/to_s.rb @@ -13,8 +13,8 @@ ruby_version_is ''...'2.7' do it "taints the result when self is tainted" do - "x".taint.send(@method).tainted?.should == true - StringSpecs::MyString.new("x").taint.send(@method).tainted?.should == true + "x".taint.send(@method).should.tainted? + StringSpecs::MyString.new("x").taint.send(@method).should.tainted? end end end diff --git a/ruby/spec/ruby/core/string/shared/to_sym.rb b/ruby/spec/ruby/core/string/shared/to_sym.rb index 1180d6471..416f302ae 100644 --- a/ruby/spec/ruby/core/string/shared/to_sym.rb +++ b/ruby/spec/ruby/core/string/shared/to_sym.rb @@ -55,7 +55,7 @@ it "raises an EncodingError for UTF-8 String containing invalid bytes" do invalid_utf8 = "\xC3" - invalid_utf8.valid_encoding?.should == false + invalid_utf8.should_not.valid_encoding? -> { invalid_utf8.send(@method) }.should raise_error(EncodingError, /invalid/) diff --git a/ruby/spec/ruby/core/string/slice_spec.rb b/ruby/spec/ruby/core/string/slice_spec.rb index f9f4938af..83b475c8b 100644 --- a/ruby/spec/ruby/core/string/slice_spec.rb +++ b/ruby/spec/ruby/core/string/slice_spec.rb @@ -53,10 +53,10 @@ a.should == "hello" end - it "raises a #{frozen_error_class} if self is frozen" do - -> { "hello".freeze.slice!(1) }.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(10) }.should raise_error(frozen_error_class) - -> { "".freeze.slice!(0) }.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { "hello".freeze.slice!(1) }.should raise_error(FrozenError) + -> { "hello".freeze.slice!(10) }.should raise_error(FrozenError) + -> { "".freeze.slice!(0) }.should raise_error(FrozenError) end it "calls to_int on index" do @@ -99,8 +99,8 @@ str = "hello world" str.taint - str.slice!(0, 0).tainted?.should == true - str.slice!(2, 1).tainted?.should == true + str.slice!(0, 0).should.tainted? + str.slice!(2, 1).should.tainted? end end @@ -119,14 +119,14 @@ a.should == "hello" end - it "raises a #{frozen_error_class} if self is frozen" do - -> { "hello".freeze.slice!(1, 2) }.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(10, 3) }.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(-10, 3)}.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(4, -3) }.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(10, 3) }.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(-10, 3)}.should raise_error(frozen_error_class) - -> { "hello".freeze.slice!(4, -3) }.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { "hello".freeze.slice!(1, 2) }.should raise_error(FrozenError) + -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError) + -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError) + -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError) + -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError) + -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError) + -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError) end it "calls to_int on idx and length" do @@ -142,12 +142,21 @@ def obj.method_missing(name, *) name == :to_int ? 2 : super; end "hello".slice!(obj, obj).should == "ll" end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString) + end end + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0, 0).should be_an_instance_of(String) + s.slice!(0, 4).should be_an_instance_of(String) + end + end it "returns the substring given by the character offsets" do "hellö there".slice!(1,0).should == "" @@ -191,15 +200,25 @@ def obj.method_missing(name, *) name == :to_int ? 2 : super; end str = "hello world" str.taint - str.slice!(0..0).tainted?.should == true - str.slice!(2..3).tainted?.should == true + str.slice!(0..0).should.tainted? + str.slice!(2..3).should.tainted? + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString) end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0...0).should be_an_instance_of(String) + s.slice!(0..4).should be_an_instance_of(String) + end end it "calls to_int on range arguments" do @@ -248,13 +267,13 @@ def to.method_missing(name) name == :to_int ? -2 : super; end end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { "hello".freeze.slice!(1..3) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { "hello".freeze.slice!(1..3) }.should raise_error(FrozenError) end # see redmine #1551 - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> { "hello".freeze.slice!(10..20)}.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> { "hello".freeze.slice!(10..20)}.should raise_error(FrozenError) end end @@ -288,21 +307,31 @@ def to.method_missing(name) name == :to_int ? -2 : super; end tainted_re = /./ tainted_re.taint - str.slice!(tainted_re).tainted?.should == true + str.slice!(tainted_re).should.tainted? end end it "doesn't taint self when regexp is tainted" do s = "hello" s.slice!(/./.taint) - s.tainted?.should == false + s.should_not.tainted? end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(//).should be_an_instance_of(StringSpecs::MyString) - s.slice!(/../).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(//).should be_an_instance_of(StringSpecs::MyString) + s.slice!(/../).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(//).should be_an_instance_of(String) + s.slice!(/../).should be_an_instance_of(String) + end end it "returns the matching portion of self with a multi byte character" do @@ -318,12 +347,12 @@ def to.method_missing(name) name == :to_int ? -2 : super; end $~.should == nil end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> { "this is a string".freeze.slice!(/zzz/) }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> { "this is a string".freeze.slice!(/zzz/) }.should raise_error(FrozenError) end end @@ -349,14 +378,14 @@ def to.method_missing(name) name == :to_int ? -2 : super; end tainted_re = /(.)(.)(.)/ tainted_re.taint - str.slice!(tainted_re, 1).tainted?.should == true + str.slice!(tainted_re, 1).should.tainted? end end it "doesn't taint self when regexp is tainted" do s = "hello" s.slice!(/(.)(.)/.taint, 1) - s.tainted?.should == false + s.should_not.tainted? end end @@ -383,10 +412,20 @@ def to.method_missing(name) name == :to_int ? -2 : super; end "har".slice!(/(.)(.)(.)/, obj).should == "a" end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(/(.)(.)/, 0).should be_an_instance_of(String) + s.slice!(/(.)(.)/, 1).should be_an_instance_of(String) + end end it "returns the encoding aware capture for the given index" do @@ -410,10 +449,10 @@ def to.method_missing(name) name == :to_int ? -2 : super; end $~.should == nil end - it "raises a #{frozen_error_class} if self is frozen" do - -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(frozen_error_class) - -> { "this is a string".freeze.slice!(/zzz/, 0)}.should raise_error(frozen_error_class) - -> { "this is a string".freeze.slice!(/(.)/, 2)}.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError) + -> { "this is a string".freeze.slice!(/zzz/, 0)}.should raise_error(FrozenError) + -> { "this is a string".freeze.slice!(/(.)/, 2)}.should raise_error(FrozenError) end end @@ -461,16 +500,27 @@ def to.method_missing(name) name == :to_int ? -2 : super; end -> { "hello".slice!(o) }.should raise_error(TypeError) end - it "returns a subclass instance when given a subclass instance" do - s = StringSpecs::MyString.new("el") - r = "hello".slice!(s) - r.should == "el" - r.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".slice!(s) + r.should == "el" + r.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".slice!(s) + r.should == "el" + r.should be_an_instance_of(String) + end end - it "raises a #{frozen_error_class} if self is frozen" do - -> { "hello hello".freeze.slice!('llo') }.should raise_error(frozen_error_class) - -> { "this is a string".freeze.slice!('zzz')}.should raise_error(frozen_error_class) - -> { "this is a string".freeze.slice!('zzz')}.should raise_error(frozen_error_class) + it "raises a FrozenError if self is frozen" do + -> { "hello hello".freeze.slice!('llo') }.should raise_error(FrozenError) + -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError) + -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/split_spec.rb b/ruby/spec/ruby/core/string/split_spec.rb index cfb030ad8..a373be360 100644 --- a/ruby/spec/ruby/core/string/split_spec.rb +++ b/ruby/spec/ruby/core/string/split_spec.rb @@ -84,6 +84,24 @@ $; = old_fs end end + + ruby_version_is "2.7" do + context "when $; is not nil" do + before do + suppress_warning do + @old_value, $; = $;, 'foobar' + end + end + + after do + $; = @old_value + end + + it "warns" do + -> { "".split }.should complain(/warning: \$; is set to non-nil value/) + end + end + end end it "ignores leading and continuous whitespace when string is a single space" do @@ -141,28 +159,48 @@ "foo".split("bar", 3).should == ["foo"] end - it "returns subclass instances based on self" do - ["", "x.y.z.", " x y "].each do |str| - ["", ".", " "].each do |pat| - [-1, 0, 1, 2].each do |limit| - StringSpecs::MyString.new(str).split(pat, limit).each do |x| - x.should be_an_instance_of(StringSpecs::MyString) - end + ruby_version_is ''...'3.0' do + it "returns subclass instances based on self" do + ["", "x.y.z.", " x y "].each do |str| + ["", ".", " "].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(StringSpecs::MyString) + end - str.split(StringSpecs::MyString.new(pat), limit).each do |x| - x.should be_an_instance_of(String) + str.split(StringSpecs::MyString.new(pat), limit).each do |x| + x.should be_an_instance_of(String) + end end end end end + + it "does not call constructor on created subclass instances" do + # can't call should_not_receive on an object that doesn't yet exist + # so failure here is signalled by exception, not expectation failure + + s = StringSpecs::StringWithRaisingConstructor.new('silly:string') + s.split(':').first.should == 'silly' + end end - it "does not call constructor on created subclass instances" do - # can't call should_not_receive on an object that doesn't yet exist - # so failure here is signalled by exception, not expectation failure + ruby_version_is '3.0' do + it "returns String instances based on self" do + ["", "x.y.z.", " x y "].each do |str| + ["", ".", " "].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(String) + end - s = StringSpecs::StringWithRaisingConstructor.new('silly:string') - s.split(':').first.should == 'silly' + str.split(StringSpecs::MyString.new(pat), limit).each do |x| + x.should be_an_instance_of(String) + end + end + end + end + end end ruby_version_is ''...'2.7' do @@ -171,11 +209,11 @@ ["", ".", " "].each do |pat| [-1, 0, 1, 2].each do |limit| str.dup.taint.split(pat).each do |x| - x.tainted?.should == true + x.should.tainted? end str.split(pat.dup.taint).each do |x| - x.tainted?.should == false + x.should_not.tainted? end end end @@ -337,24 +375,40 @@ "foo".split(/bar/, 3).should == ["foo"] end - it "returns subclass instances based on self" do - ["", "x:y:z:", " x y "].each do |str| - [//, /:/, /\s+/].each do |pat| - [-1, 0, 1, 2].each do |limit| - StringSpecs::MyString.new(str).split(pat, limit).each do |x| - x.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances based on self" do + ["", "x:y:z:", " x y "].each do |str| + [//, /:/, /\s+/].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(StringSpecs::MyString) + end end end end end - end - it "does not call constructor on created subclass instances" do - # can't call should_not_receive on an object that doesn't yet exist - # so failure here is signalled by exception, not expectation failure + it "does not call constructor on created subclass instances" do + # can't call should_not_receive on an object that doesn't yet exist + # so failure here is signalled by exception, not expectation failure - s = StringSpecs::StringWithRaisingConstructor.new('silly:string') - s.split(/:/).first.should == 'silly' + s = StringSpecs::StringWithRaisingConstructor.new('silly:string') + s.split(/:/).first.should == 'silly' + end + end + + ruby_version_is '3.0' do + it "returns String instances based on self" do + ["", "x:y:z:", " x y "].each do |str| + [//, /:/, /\s+/].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(String) + end + end + end + end + end end ruby_version_is ''...'2.7' do @@ -407,16 +461,92 @@ ->{ broken_str.split(/\r\n|\r|\n/) }.should raise_error(ArgumentError) end - ruby_version_is "2.6" do - it "yields each split substrings if a block is given" do + # See https://bugs.ruby-lang.org/issues/12689 and https://github.com/jruby/jruby/issues/4868 + it "allows concurrent Regexp calls in a shared context" do + str = 'a,b,c,d,e' + + p = proc { str.split(/,/) } + results = 10.times.map { Thread.new { x = nil; 100.times { x = p.call }; x } }.map(&:value) + + results.should == [%w[a b c d e]] * 10 + end + + context "when a block is given" do + it "yields each split substring with default pattern" do a = [] - returned_object = "chunky bacon".split(" ") { |str| a << str.capitalize } + returned_object = "chunky bacon".split { |str| a << str.capitalize } returned_object.should == "chunky bacon" a.should == ["Chunky", "Bacon"] end - describe "for a String subclass" do + it "yields each split substring with default pattern for a non-ASCII string" do + a = [] + returned_object = "l'été arrive bientôt".split { |str| a << str } + + returned_object.should == "l'été arrive bientôt" + a.should == ["l'été", "arrive", "bientôt"] + end + + it "yields the string when limit is 1" do + a = [] + returned_object = "chunky bacon".split("", 1) { |str| a << str.capitalize } + + returned_object.should == "chunky bacon" + a.should == ["Chunky bacon"] + end + + it "yields each split letter" do + a = [] + returned_object = "chunky".split("", 0) { |str| a << str.capitalize } + + returned_object.should == "chunky" + a.should == %w(C H U N K Y) + end + + it "yields each split substring with a pattern" do + a = [] + returned_object = "chunky-bacon".split("-", 0) { |str| a << str.capitalize } + + returned_object.should == "chunky-bacon" + a.should == ["Chunky", "Bacon"] + end + + it "yields each split substring with empty regexp pattern" do + a = [] + returned_object = "chunky".split(//) { |str| a << str.capitalize } + + returned_object.should == "chunky" + a.should == %w(C H U N K Y) + end + + it "yields each split substring with empty regexp pattern and limit" do + a = [] + returned_object = "chunky".split(//, 3) { |str| a << str.capitalize } + + returned_object.should == "chunky" + a.should == %w(C H Unky) + end + + it "yields each split substring with a regexp pattern" do + a = [] + returned_object = "chunky:bacon".split(/:/) { |str| a << str.capitalize } + + returned_object.should == "chunky:bacon" + a.should == ["Chunky", "Bacon"] + end + + it "returns a string as is (and doesn't call block) if it is empty" do + a = [] + returned_object = "".split { |str| a << str.capitalize } + + returned_object.should == "" + a.should == [] + end + end + + describe "for a String subclass" do + ruby_version_is ''...'3.0' do it "yields instances of the same subclass" do a = [] StringSpecs::MyString.new("a|b").split("|") { |str| a << str } @@ -429,5 +559,19 @@ last.should == "b" end end + + ruby_version_is '3.0' do + it "yields instances of String" do + a = [] + StringSpecs::MyString.new("a|b").split("|") { |str| a << str } + first, last = a + + first.should be_an_instance_of(String) + first.should == "a" + + last.should be_an_instance_of(String) + last.should == "b" + end + end end end diff --git a/ruby/spec/ruby/core/string/squeeze_spec.rb b/ruby/spec/ruby/core/string/squeeze_spec.rb index 2e96684b9..6f75402c9 100644 --- a/ruby/spec/ruby/core/string/squeeze_spec.rb +++ b/ruby/spec/ruby/core/string/squeeze_spec.rb @@ -56,11 +56,11 @@ ruby_version_is ''...'2.7' do it "taints the result when self is tainted" do - "hello".taint.squeeze("e").tainted?.should == true - "hello".taint.squeeze("a-z").tainted?.should == true + "hello".taint.squeeze("e").should.tainted? + "hello".taint.squeeze("a-z").should.tainted? - "hello".squeeze("e".taint).tainted?.should == false - "hello".squeeze("l".taint).tainted?.should == false + "hello".squeeze("e".taint).should_not.tainted? + "hello".squeeze("l".taint).should_not.tainted? end end @@ -80,8 +80,16 @@ -> { "hello world".squeeze(mock('x')) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(String) + end end end @@ -105,11 +113,11 @@ -> { s.squeeze!("^e-b") }.should raise_error(ArgumentError) end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do a = "yellow moon" a.freeze - -> { a.squeeze!("") }.should raise_error(frozen_error_class) - -> { a.squeeze! }.should raise_error(frozen_error_class) + -> { a.squeeze!("") }.should raise_error(FrozenError) + -> { a.squeeze! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/start_with_spec.rb b/ruby/spec/ruby/core/string/start_with_spec.rb index 1000db180..aaed197ff 100644 --- a/ruby/spec/ruby/core/string/start_with_spec.rb +++ b/ruby/spec/ruby/core/string/start_with_spec.rb @@ -1,76 +1,8 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative '../../shared/string/start_with' describe "String#start_with?" do - it "returns true only if beginning match" do - s = "hello" - s.should.start_with?('h') - s.should.start_with?('hel') - s.should_not.start_with?('el') - end - - it "returns true only if any beginning match" do - "hello".should.start_with?('x', 'y', 'he', 'z') - end - - it "returns true if the search string is empty" do - "hello".should.start_with?("") - "".should.start_with?("") - end - - it "converts its argument using :to_str" do - s = "hello" - find = mock('h') - find.should_receive(:to_str).and_return("h") - s.should.start_with?(find) - end - - it "ignores arguments not convertible to string" do - "hello".should_not.start_with?() - -> { "hello".start_with?(1) }.should raise_error(TypeError) - -> { "hello".start_with?(["h"]) }.should raise_error(TypeError) - -> { "hello".start_with?(1, nil, "h") }.should raise_error(TypeError) - end - - it "uses only the needed arguments" do - find = mock('h') - find.should_not_receive(:to_str) - "hello".should.start_with?("h",find) - end - - it "works for multibyte strings" do - "céréale".should.start_with?("cér") - end - - ruby_version_is "2.5" do - it "supports regexps" do - regexp = /[h1]/ - "hello".should.start_with?(regexp) - "1337".should.start_with?(regexp) - "foxes are 1337".should_not.start_with?(regexp) - "chunky\n12bacon".should_not.start_with?(/12/) - end - - it "supports regexps with ^ and $ modifiers" do - regexp1 = /^\d{2}/ - regexp2 = /\d{2}$/ - "12test".should.start_with?(regexp1) - "test12".should_not.start_with?(regexp1) - "12test".should_not.start_with?(regexp2) - "test12".should_not.start_with?(regexp2) - end - - it "sets Regexp.last_match if it returns true" do - regexp = /test-(\d+)/ - "test-1337".start_with?(regexp).should be_true - Regexp.last_match.should_not be_nil - Regexp.last_match[1].should == "1337" - $1.should == "1337" - - "test-asdf".start_with?(regexp).should be_false - Regexp.last_match.should be_nil - $1.should be_nil - end - end + it_behaves_like :start_with, :to_s end diff --git a/ruby/spec/ruby/core/string/strip_spec.rb b/ruby/spec/ruby/core/string/strip_spec.rb index 728b3104f..8517bf2d2 100644 --- a/ruby/spec/ruby/core/string/strip_spec.rb +++ b/ruby/spec/ruby/core/string/strip_spec.rb @@ -1,23 +1,27 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#strip" do + it_behaves_like :string_strip, :strip + it "returns a new string with leading and trailing whitespace removed" do " hello ".strip.should == "hello" " hello world ".strip.should == "hello world" "\tgoodbye\r\v\n".strip.should == "goodbye" - "\x00 goodbye \x00".strip.should == "\x00 goodbye" end - it "returns a copy of self with trailing NULL bytes and whitespace" do - " \x00 goodbye \x00 ".strip.should == "\x00 goodbye" + ruby_version_is '3.1' do + it "returns a copy of self without leading and trailing NULL bytes and whitespace" do + " \x00 goodbye \x00 ".strip.should == "goodbye" + end end ruby_version_is ''...'2.7' do it "taints the result when self is tainted" do - "".taint.strip.tainted?.should == true - "ok".taint.strip.tainted?.should == true - " ok ".taint.strip.tainted?.should == true + "".taint.strip.should.tainted? + "ok".taint.strip.should.tainted? + " ok ".taint.strip.should.tainted? end end end @@ -31,11 +35,6 @@ a = "\tgoodbye\r\v\n" a.strip! a.should == "goodbye" - - a = "\000 goodbye \000" - a.strip! - a.should == "\000 goodbye" - end it "returns nil if no modifications where made" do @@ -44,19 +43,21 @@ a.should == "hello" end - it "modifies self removing trailing NULL bytes and whitespace" do - a = " \x00 goodbye \x00 " - a.strip! - a.should == "\x00 goodbye" + ruby_version_is '3.1' do + it "removes leading and trailing NULL bytes and whitespace" do + a = "\000 goodbye \000" + a.strip! + a.should == "goodbye" + end end - it "raises a #{frozen_error_class} on a frozen instance that is modified" do - -> { " hello ".freeze.strip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that is modified" do + -> { " hello ".freeze.strip! }.should raise_error(FrozenError) end # see #1552 - it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do - -> {"hello".freeze.strip! }.should raise_error(frozen_error_class) - -> {"".freeze.strip! }.should raise_error(frozen_error_class) + it "raises a FrozenError on a frozen instance that would not be modified" do + -> {"hello".freeze.strip! }.should raise_error(FrozenError) + -> {"".freeze.strip! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/sub_spec.rb b/ruby/spec/ruby/core/string/sub_spec.rb index 2a859c2fc..5ae9a4bbf 100644 --- a/ruby/spec/ruby/core/string/sub_spec.rb +++ b/ruby/spec/ruby/core/string/sub_spec.rb @@ -148,14 +148,14 @@ hello_t.taint; a_t.taint; empty_t.taint - hello_t.sub(/./, a).tainted?.should == true - hello_t.sub(/./, empty).tainted?.should == true + hello_t.sub(/./, a).should.tainted? + hello_t.sub(/./, empty).should.tainted? - hello.sub(/./, a_t).tainted?.should == true - hello.sub(/./, empty_t).tainted?.should == true - hello.sub(//, empty_t).tainted?.should == true + hello.sub(/./, a_t).should.tainted? + hello.sub(/./, empty_t).should.tainted? + hello.sub(//, empty_t).should.tainted? - hello.sub(//.taint, "foo").tainted?.should == false + hello.sub(//.taint, "foo").should_not.tainted? end end @@ -192,11 +192,22 @@ -> { "hello".sub(/[aeiou]/, 99) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(String) + StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(String) + end end it "sets $~ to MatchData of match and nil when there's none" do @@ -298,14 +309,14 @@ hello_t.taint; a_t.taint; empty_t.taint - hello_t.sub(/./) { a }.tainted?.should == true - hello_t.sub(/./) { empty }.tainted?.should == true + hello_t.sub(/./) { a }.should.tainted? + hello_t.sub(/./) { empty }.should.tainted? - hello.sub(/./) { a_t }.tainted?.should == true - hello.sub(/./) { empty_t }.tainted?.should == true - hello.sub(//) { empty_t }.tainted?.should == true + hello.sub(/./) { a_t }.should.tainted? + hello.sub(/./) { empty_t }.should.tainted? + hello.sub(//) { empty_t }.should.tainted? - hello.sub(//.taint) { "foo" }.tainted?.should == false + hello.sub(//.taint) { "foo" }.should_not.tainted? end end end @@ -320,8 +331,8 @@ ruby_version_is ''...'2.7' do it "taints self if replacement is tainted" do a = "hello" - a.sub!(/./.taint, "foo").tainted?.should == false - a.sub!(/./, "foo".taint).tainted?.should == true + a.sub!(/./.taint, "foo").should_not.tainted? + a.sub!(/./, "foo".taint).should.tainted? end end @@ -332,13 +343,13 @@ a.should == "hello" end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do s = "hello" s.freeze - -> { s.sub!(/ROAR/, "x") }.should raise_error(frozen_error_class) - -> { s.sub!(/e/, "e") }.should raise_error(frozen_error_class) - -> { s.sub!(/[aeiou]/, '*') }.should raise_error(frozen_error_class) + -> { s.sub!(/ROAR/, "x") }.should raise_error(FrozenError) + -> { s.sub!(/e/, "e") }.should raise_error(FrozenError) + -> { s.sub!(/[aeiou]/, '*') }.should raise_error(FrozenError) end end @@ -370,8 +381,8 @@ ruby_version_is ''...'2.7' do it "taints self if block's result is tainted" do a = "hello" - a.sub!(/./.taint) { "foo" }.tainted?.should == false - a.sub!(/./) { "foo".taint }.tainted?.should == true + a.sub!(/./.taint) { "foo" }.should_not.tainted? + a.sub!(/./) { "foo".taint }.should.tainted? end end @@ -387,13 +398,13 @@ -> { str.sub!(//) { str << 'x' } }.should raise_error(RuntimeError) end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do s = "hello" s.freeze - -> { s.sub!(/ROAR/) { "x" } }.should raise_error(frozen_error_class) - -> { s.sub!(/e/) { "e" } }.should raise_error(frozen_error_class) - -> { s.sub!(/[aeiou]/) { '*' } }.should raise_error(frozen_error_class) + -> { s.sub!(/ROAR/) { "x" } }.should raise_error(FrozenError) + -> { s.sub!(/e/) { "e" } }.should raise_error(FrozenError) + -> { s.sub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/swapcase_spec.rb b/ruby/spec/ruby/core/string/swapcase_spec.rb index c1a1608a8..32b358607 100644 --- a/ruby/spec/ruby/core/string/swapcase_spec.rb +++ b/ruby/spec/ruby/core/string/swapcase_spec.rb @@ -11,8 +11,8 @@ ruby_version_is ''...'2.7' do it "taints resulting string when self is tainted" do - "".taint.swapcase.tainted?.should == true - "hello".taint.swapcase.tainted?.should == true + "".taint.swapcase.should.tainted? + "hello".taint.swapcase.should.tainted? end end @@ -73,9 +73,18 @@ -> { "abc".swapcase(:invalid_option) }.should raise_error(ArgumentError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").swapcase.should be_an_instance_of(String) + StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(String) + end end end @@ -86,6 +95,12 @@ a.should == "CyBeR_pUnK11" end + it "modifies self in place for non-ascii-compatible encodings" do + a = "cYbEr_PuNk11".encode("utf-16le") + a.swapcase! + a.should == "CyBeR_pUnK11".encode("utf-16le") + end + describe "full Unicode case mapping" do it "modifies self in place for all of Unicode with no option" do a = "äÖü" @@ -93,6 +108,12 @@ a.should == "ÄöÜ" end + it "works for non-ascii-compatible encodings" do + a = "äÖü".encode("utf-16le") + a.swapcase! + a.should == "ÄöÜ".encode("utf-16le") + end + it "updates string metadata" do swapcased = "Aßet" swapcased.swapcase! @@ -110,6 +131,12 @@ a.swapcase!(:ascii) a.should == "AßET" end + + it "works for non-ascii-compatible encodings" do + a = "aBc".encode("utf-16le") + a.swapcase!(:ascii) + a.should == "AbC".encode("utf-16le") + end end describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do @@ -164,10 +191,10 @@ "".swapcase!.should == nil end - it "raises a #{frozen_error_class} when self is frozen" do + it "raises a FrozenError when self is frozen" do ["", "hello"].each do |a| a.freeze - -> { a.swapcase! }.should raise_error(frozen_error_class) + -> { a.swapcase! }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/core/string/to_i_spec.rb b/ruby/spec/ruby/core/string/to_i_spec.rb index a37be4777..e4fa89aab 100644 --- a/ruby/spec/ruby/core/string/to_i_spec.rb +++ b/ruby/spec/ruby/core/string/to_i_spec.rb @@ -131,29 +131,29 @@ -> { "".to_i(37) }.should raise_error(ArgumentError) end - it "returns a Fixnum for long strings with trailing spaces" do + it "returns an Integer for long strings with trailing spaces" do "0 ".to_i.should == 0 - "0 ".to_i.should be_an_instance_of(Fixnum) + "0 ".to_i.should be_an_instance_of(Integer) "10 ".to_i.should == 10 - "10 ".to_i.should be_an_instance_of(Fixnum) + "10 ".to_i.should be_an_instance_of(Integer) "-10 ".to_i.should == -10 - "-10 ".to_i.should be_an_instance_of(Fixnum) + "-10 ".to_i.should be_an_instance_of(Integer) end - it "returns a Fixnum for long strings with leading spaces" do + it "returns an Integer for long strings with leading spaces" do " 0".to_i.should == 0 - " 0".to_i.should be_an_instance_of(Fixnum) + " 0".to_i.should be_an_instance_of(Integer) " 10".to_i.should == 10 - " 10".to_i.should be_an_instance_of(Fixnum) + " 10".to_i.should be_an_instance_of(Integer) " -10".to_i.should == -10 - " -10".to_i.should be_an_instance_of(Fixnum) + " -10".to_i.should be_an_instance_of(Integer) end - it "returns the correct Bignum for long strings" do + it "returns the correct Integer for long strings" do "245789127594125924165923648312749312749327482".to_i.should == 245789127594125924165923648312749312749327482 "-245789127594125924165923648312749312749327482".to_i.should == -245789127594125924165923648312749312749327482 end diff --git a/ruby/spec/ruby/core/string/tr_s_spec.rb b/ruby/spec/ruby/core/string/tr_s_spec.rb index a05e421e9..c6ad12139 100644 --- a/ruby/spec/ruby/core/string/tr_s_spec.rb +++ b/ruby/spec/ruby/core/string/tr_s_spec.rb @@ -45,8 +45,16 @@ "bla".tr_s(from_str, to_str).should == "BlA" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do @@ -54,10 +62,10 @@ ["h", "hello"].each do |str| tainted_str = str.dup.taint - tainted_str.tr_s("e", "a").tainted?.should == true + tainted_str.tr_s("e", "a").should.tainted? - str.tr_s("e".taint, "a").tainted?.should == false - str.tr_s("e", "a".taint).tainted?.should == false + str.tr_s("e".taint, "a").should_not.tainted? + str.tr_s("e", "a".taint).should_not.tainted? end end end @@ -127,10 +135,10 @@ s.should == "hello" end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do s = "hello".freeze - -> { s.tr_s!("el", "ar") }.should raise_error(frozen_error_class) - -> { s.tr_s!("l", "r") }.should raise_error(frozen_error_class) - -> { s.tr_s!("", "") }.should raise_error(frozen_error_class) + -> { s.tr_s!("el", "ar") }.should raise_error(FrozenError) + -> { s.tr_s!("l", "r") }.should raise_error(FrozenError) + -> { s.tr_s!("", "") }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/tr_spec.rb b/ruby/spec/ruby/core/string/tr_spec.rb index ae826fd79..06be1e664 100644 --- a/ruby/spec/ruby/core/string/tr_spec.rb +++ b/ruby/spec/ruby/core/string/tr_spec.rb @@ -57,8 +57,16 @@ "bla".tr(from_str, to_str).should == "BlA" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns Stringinstances when called on a subclass" do + StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do @@ -66,10 +74,10 @@ ["h", "hello"].each do |str| tainted_str = str.dup.taint - tainted_str.tr("e", "a").tainted?.should == true + tainted_str.tr("e", "a").should.tainted? - str.tr("e".taint, "a").tainted?.should == false - str.tr("e", "a".taint).tainted?.should == false + str.tr("e".taint, "a").should_not.tainted? + str.tr("e", "a".taint).should_not.tainted? end end end @@ -122,10 +130,10 @@ s.should == "hello" end - it "raises a #{frozen_error_class} if self is frozen" do + it "raises a FrozenError if self is frozen" do s = "abcdefghijklmnopqR".freeze - -> { s.tr!("cdefg", "12") }.should raise_error(frozen_error_class) - -> { s.tr!("R", "S") }.should raise_error(frozen_error_class) - -> { s.tr!("", "") }.should raise_error(frozen_error_class) + -> { s.tr!("cdefg", "12") }.should raise_error(FrozenError) + -> { s.tr!("R", "S") }.should raise_error(FrozenError) + -> { s.tr!("", "") }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/uminus_spec.rb b/ruby/spec/ruby/core/string/uminus_spec.rb index dace04846..800dca504 100644 --- a/ruby/spec/ruby/core/string/uminus_spec.rb +++ b/ruby/spec/ruby/core/string/uminus_spec.rb @@ -6,69 +6,44 @@ output = -input output.should equal(input) - output.frozen?.should == true + output.should.frozen? end it 'returns a frozen copy if the String is not frozen' do input = 'foo' output = -input - output.frozen?.should == true + output.should.frozen? output.should_not equal(input) output.should == 'foo' end - ruby_version_is "2.5" do - it "returns the same object for equal unfrozen strings" do - origin = "this is a string" - dynamic = %w(this is a string).join(' ') + it "returns the same object for equal unfrozen strings" do + origin = "this is a string" + dynamic = %w(this is a string).join(' ') - origin.should_not equal(dynamic) - (-origin).should equal(-dynamic) - end - - it "returns the same object when it's called on the same String literal" do - (-"unfrozen string").should equal(-"unfrozen string") - (-"unfrozen string").should_not equal(-"another unfrozen string") - end + origin.should_not equal(dynamic) + (-origin).should equal(-dynamic) end - ruby_version_is "2.5"..."2.6" do - it "does not deduplicate already frozen strings" do - dynamic = %w(this string is frozen).join(' ').freeze - - dynamic.should_not equal("this string is frozen".freeze) + it "returns the same object when it's called on the same String literal" do + (-"unfrozen string").should equal(-"unfrozen string") + (-"unfrozen string").should_not equal(-"another unfrozen string") + end - (-dynamic).should_not equal("this string is frozen".freeze) - (-dynamic).should_not equal(-"this string is frozen".freeze) - (-dynamic).should == "this string is frozen" - end + it "deduplicates frozen strings" do + dynamic = %w(this string is frozen).join(' ').freeze - it "does not deduplicate tainted strings" do - dynamic = %w(this string is frozen).join(' ') - dynamic.taint - (-dynamic).should_not equal("this string is frozen".freeze) - (-dynamic).should_not equal(-"this string is frozen".freeze) - (-dynamic).should == "this string is frozen" - end + dynamic.should_not equal("this string is frozen".freeze) - it "does not deduplicate strings with additional instance variables" do - dynamic = %w(this string is frozen).join(' ') - dynamic.instance_variable_set(:@foo, :bar) - (-dynamic).should_not equal("this string is frozen".freeze) - (-dynamic).should_not equal(-"this string is frozen".freeze) - (-dynamic).should == "this string is frozen" - end + (-dynamic).should equal("this string is frozen".freeze) + (-dynamic).should equal(-"this string is frozen".freeze) end - ruby_version_is "2.6" do - it "deduplicates frozen strings" do - dynamic = %w(this string is frozen).join(' ').freeze - - dynamic.should_not equal("this string is frozen".freeze) - - (-dynamic).should equal("this string is frozen".freeze) - (-dynamic).should equal(-"this string is frozen".freeze) + ruby_version_is "3.0" do + it "interns the provided string if it is frozen" do + dynamic = "this string is unique and frozen #{rand}".freeze + (-dynamic).should equal(dynamic) end end end diff --git a/ruby/spec/ruby/core/string/undump_spec.rb b/ruby/spec/ruby/core/string/undump_spec.rb index d45c4bae1..b990aa25e 100644 --- a/ruby/spec/ruby/core/string/undump_spec.rb +++ b/ruby/spec/ruby/core/string/undump_spec.rb @@ -2,452 +2,450 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is '2.5' do - describe "String#undump" do - ruby_version_is ''...'2.7' do - it "taints the result if self is tainted" do - '"foo"'.taint.undump.tainted?.should == true - end - - it "untrusts the result if self is untrusted" do - '"foo"'.untrust.undump.untrusted?.should == true - end +describe "String#undump" do + ruby_version_is ''...'2.7' do + it "taints the result if self is tainted" do + '"foo"'.taint.undump.should.tainted? end - it "does not take into account if a string is frozen" do - '"foo"'.freeze.undump.frozen?.should == false + it "untrusts the result if self is untrusted" do + '"foo"'.untrust.undump.should.untrusted? end + end - it "always returns String instance" do - StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String) - end + it "does not take into account if a string is frozen" do + '"foo"'.freeze.undump.should_not.frozen? + end - it "strips outer \"" do - '"foo"'.undump.should == 'foo' - end + it "always returns String instance" do + StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String) + end - it "returns a string with special characters in \\ notation replaced with the characters" do - [ ['"\\a"', "\a"], - ['"\\b"', "\b"], - ['"\\t"', "\t"], - ['"\\n"', "\n"], - ['"\\v"', "\v"], - ['"\\f"', "\f"], - ['"\\r"', "\r"], - ['"\\e"', "\e"] - ].should be_computed_by(:undump) - end + it "strips outer \"" do + '"foo"'.undump.should == 'foo' + end - it "returns a string with unescaped sequences \" and \\" do - [ ['"\\""' , "\""], - ['"\\\\"', "\\"] - ].should be_computed_by(:undump) - end + it "returns a string with special characters in \\ notation replaced with the characters" do + [ ['"\\a"', "\a"], + ['"\\b"', "\b"], + ['"\\t"', "\t"], + ['"\\n"', "\n"], + ['"\\v"', "\v"], + ['"\\f"', "\f"], + ['"\\r"', "\r"], + ['"\\e"', "\e"] + ].should be_computed_by(:undump) + end - it "returns a string with unescaped sequences \\# when # is followed by $, @, {" do - [ ['"\\#$PATH"', "\#$PATH"], - ['"\\#@a"', "\#@a"], - ['"\\#@@a"', "\#@@a"], - ['"\\#{a}"', "\#{a}"] - ].should be_computed_by(:undump) - end + it "returns a string with unescaped sequences \" and \\" do + [ ['"\\""' , "\""], + ['"\\\\"', "\\"] + ].should be_computed_by(:undump) + end - it "returns a string with # not escaped when followed by any other character" do - [ ['"#"', '#'], - ['"#1"', '#1'] - ].should be_computed_by(:undump) - end + it "returns a string with unescaped sequences \\# when # is followed by $, @, {" do + [ ['"\\#$PATH"', "\#$PATH"], + ['"\\#@a"', "\#@a"], + ['"\\#@@a"', "\#@@a"], + ['"\\#{a}"', "\#{a}"] + ].should be_computed_by(:undump) + end - it "returns a string with printable non-alphanumeric characters" do - [ ['" "', ' '], - ['"!"', '!'], - ['"$"', '$'], - ['"%"', '%'], - ['"&"', '&'], - ['"\'"', '\''], - ['"("', '('], - ['")"', ')'], - ['"*"', '*'], - ['"+"', '+'], - ['","', ','], - ['"-"', '-'], - ['"."', '.'], - ['"/"', '/'], - ['":"', ':'], - ['";"', ';'], - ['"<"', '<'], - ['"="', '='], - ['">"', '>'], - ['"?"', '?'], - ['"@"', '@'], - ['"["', '['], - ['"]"', ']'], - ['"^"', '^'], - ['"_"', '_'], - ['"`"', '`'], - ['"{"', '{'], - ['"|"', '|'], - ['"}"', '}'], - ['"~"', '~'] - ].should be_computed_by(:undump) - end + it "returns a string with # not escaped when followed by any other character" do + [ ['"#"', '#'], + ['"#1"', '#1'] + ].should be_computed_by(:undump) + end - it "returns a string with numeric characters unescaped" do - [ ['"0"', "0"], - ['"1"', "1"], - ['"2"', "2"], - ['"3"', "3"], - ['"4"', "4"], - ['"5"', "5"], - ['"6"', "6"], - ['"7"', "7"], - ['"8"', "8"], - ['"9"', "9"], - ].should be_computed_by(:undump) - end + it "returns a string with printable non-alphanumeric characters" do + [ ['" "', ' '], + ['"!"', '!'], + ['"$"', '$'], + ['"%"', '%'], + ['"&"', '&'], + ['"\'"', '\''], + ['"("', '('], + ['")"', ')'], + ['"*"', '*'], + ['"+"', '+'], + ['","', ','], + ['"-"', '-'], + ['"."', '.'], + ['"/"', '/'], + ['":"', ':'], + ['";"', ';'], + ['"<"', '<'], + ['"="', '='], + ['">"', '>'], + ['"?"', '?'], + ['"@"', '@'], + ['"["', '['], + ['"]"', ']'], + ['"^"', '^'], + ['"_"', '_'], + ['"`"', '`'], + ['"{"', '{'], + ['"|"', '|'], + ['"}"', '}'], + ['"~"', '~'] + ].should be_computed_by(:undump) + end - it "returns a string with upper-case alpha characters unescaped" do - [ ['"A"', 'A'], - ['"B"', 'B'], - ['"C"', 'C'], - ['"D"', 'D'], - ['"E"', 'E'], - ['"F"', 'F'], - ['"G"', 'G'], - ['"H"', 'H'], - ['"I"', 'I'], - ['"J"', 'J'], - ['"K"', 'K'], - ['"L"', 'L'], - ['"M"', 'M'], - ['"N"', 'N'], - ['"O"', 'O'], - ['"P"', 'P'], - ['"Q"', 'Q'], - ['"R"', 'R'], - ['"S"', 'S'], - ['"T"', 'T'], - ['"U"', 'U'], - ['"V"', 'V'], - ['"W"', 'W'], - ['"X"', 'X'], - ['"Y"', 'Y'], - ['"Z"', 'Z'] - ].should be_computed_by(:undump) - end + it "returns a string with numeric characters unescaped" do + [ ['"0"', "0"], + ['"1"', "1"], + ['"2"', "2"], + ['"3"', "3"], + ['"4"', "4"], + ['"5"', "5"], + ['"6"', "6"], + ['"7"', "7"], + ['"8"', "8"], + ['"9"', "9"], + ].should be_computed_by(:undump) + end - it "returns a string with lower-case alpha characters unescaped" do - [ ['"a"', 'a'], - ['"b"', 'b'], - ['"c"', 'c'], - ['"d"', 'd'], - ['"e"', 'e'], - ['"f"', 'f'], - ['"g"', 'g'], - ['"h"', 'h'], - ['"i"', 'i'], - ['"j"', 'j'], - ['"k"', 'k'], - ['"l"', 'l'], - ['"m"', 'm'], - ['"n"', 'n'], - ['"o"', 'o'], - ['"p"', 'p'], - ['"q"', 'q'], - ['"r"', 'r'], - ['"s"', 's'], - ['"t"', 't'], - ['"u"', 'u'], - ['"v"', 'v'], - ['"w"', 'w'], - ['"x"', 'x'], - ['"y"', 'y'], - ['"z"', 'z'] - ].should be_computed_by(:undump) - end + it "returns a string with upper-case alpha characters unescaped" do + [ ['"A"', 'A'], + ['"B"', 'B'], + ['"C"', 'C'], + ['"D"', 'D'], + ['"E"', 'E'], + ['"F"', 'F'], + ['"G"', 'G'], + ['"H"', 'H'], + ['"I"', 'I'], + ['"J"', 'J'], + ['"K"', 'K'], + ['"L"', 'L'], + ['"M"', 'M'], + ['"N"', 'N'], + ['"O"', 'O'], + ['"P"', 'P'], + ['"Q"', 'Q'], + ['"R"', 'R'], + ['"S"', 'S'], + ['"T"', 'T'], + ['"U"', 'U'], + ['"V"', 'V'], + ['"W"', 'W'], + ['"X"', 'X'], + ['"Y"', 'Y'], + ['"Z"', 'Z'] + ].should be_computed_by(:undump) + end - it "returns a string with \\x notation replaced with non-printing ASCII character" do - [ ['"\\x00"', 0000.chr.force_encoding('utf-8')], - ['"\\x01"', 0001.chr.force_encoding('utf-8')], - ['"\\x02"', 0002.chr.force_encoding('utf-8')], - ['"\\x03"', 0003.chr.force_encoding('utf-8')], - ['"\\x04"', 0004.chr.force_encoding('utf-8')], - ['"\\x05"', 0005.chr.force_encoding('utf-8')], - ['"\\x06"', 0006.chr.force_encoding('utf-8')], - ['"\\x0E"', 0016.chr.force_encoding('utf-8')], - ['"\\x0F"', 0017.chr.force_encoding('utf-8')], - ['"\\x10"', 0020.chr.force_encoding('utf-8')], - ['"\\x11"', 0021.chr.force_encoding('utf-8')], - ['"\\x12"', 0022.chr.force_encoding('utf-8')], - ['"\\x13"', 0023.chr.force_encoding('utf-8')], - ['"\\x14"', 0024.chr.force_encoding('utf-8')], - ['"\\x15"', 0025.chr.force_encoding('utf-8')], - ['"\\x16"', 0026.chr.force_encoding('utf-8')], - ['"\\x17"', 0027.chr.force_encoding('utf-8')], - ['"\\x18"', 0030.chr.force_encoding('utf-8')], - ['"\\x19"', 0031.chr.force_encoding('utf-8')], - ['"\\x1A"', 0032.chr.force_encoding('utf-8')], - ['"\\x1C"', 0034.chr.force_encoding('utf-8')], - ['"\\x1D"', 0035.chr.force_encoding('utf-8')], - ['"\\x1E"', 0036.chr.force_encoding('utf-8')], - ['"\\x1F"', 0037.chr.force_encoding('utf-8')], - ['"\\x7F"', 0177.chr.force_encoding('utf-8')], - ['"\\x80"', 0200.chr.force_encoding('utf-8')], - ['"\\x81"', 0201.chr.force_encoding('utf-8')], - ['"\\x82"', 0202.chr.force_encoding('utf-8')], - ['"\\x83"', 0203.chr.force_encoding('utf-8')], - ['"\\x84"', 0204.chr.force_encoding('utf-8')], - ['"\\x85"', 0205.chr.force_encoding('utf-8')], - ['"\\x86"', 0206.chr.force_encoding('utf-8')], - ['"\\x87"', 0207.chr.force_encoding('utf-8')], - ['"\\x88"', 0210.chr.force_encoding('utf-8')], - ['"\\x89"', 0211.chr.force_encoding('utf-8')], - ['"\\x8A"', 0212.chr.force_encoding('utf-8')], - ['"\\x8B"', 0213.chr.force_encoding('utf-8')], - ['"\\x8C"', 0214.chr.force_encoding('utf-8')], - ['"\\x8D"', 0215.chr.force_encoding('utf-8')], - ['"\\x8E"', 0216.chr.force_encoding('utf-8')], - ['"\\x8F"', 0217.chr.force_encoding('utf-8')], - ['"\\x90"', 0220.chr.force_encoding('utf-8')], - ['"\\x91"', 0221.chr.force_encoding('utf-8')], - ['"\\x92"', 0222.chr.force_encoding('utf-8')], - ['"\\x93"', 0223.chr.force_encoding('utf-8')], - ['"\\x94"', 0224.chr.force_encoding('utf-8')], - ['"\\x95"', 0225.chr.force_encoding('utf-8')], - ['"\\x96"', 0226.chr.force_encoding('utf-8')], - ['"\\x97"', 0227.chr.force_encoding('utf-8')], - ['"\\x98"', 0230.chr.force_encoding('utf-8')], - ['"\\x99"', 0231.chr.force_encoding('utf-8')], - ['"\\x9A"', 0232.chr.force_encoding('utf-8')], - ['"\\x9B"', 0233.chr.force_encoding('utf-8')], - ['"\\x9C"', 0234.chr.force_encoding('utf-8')], - ['"\\x9D"', 0235.chr.force_encoding('utf-8')], - ['"\\x9E"', 0236.chr.force_encoding('utf-8')], - ['"\\x9F"', 0237.chr.force_encoding('utf-8')], - ['"\\xA0"', 0240.chr.force_encoding('utf-8')], - ['"\\xA1"', 0241.chr.force_encoding('utf-8')], - ['"\\xA2"', 0242.chr.force_encoding('utf-8')], - ['"\\xA3"', 0243.chr.force_encoding('utf-8')], - ['"\\xA4"', 0244.chr.force_encoding('utf-8')], - ['"\\xA5"', 0245.chr.force_encoding('utf-8')], - ['"\\xA6"', 0246.chr.force_encoding('utf-8')], - ['"\\xA7"', 0247.chr.force_encoding('utf-8')], - ['"\\xA8"', 0250.chr.force_encoding('utf-8')], - ['"\\xA9"', 0251.chr.force_encoding('utf-8')], - ['"\\xAA"', 0252.chr.force_encoding('utf-8')], - ['"\\xAB"', 0253.chr.force_encoding('utf-8')], - ['"\\xAC"', 0254.chr.force_encoding('utf-8')], - ['"\\xAD"', 0255.chr.force_encoding('utf-8')], - ['"\\xAE"', 0256.chr.force_encoding('utf-8')], - ['"\\xAF"', 0257.chr.force_encoding('utf-8')], - ['"\\xB0"', 0260.chr.force_encoding('utf-8')], - ['"\\xB1"', 0261.chr.force_encoding('utf-8')], - ['"\\xB2"', 0262.chr.force_encoding('utf-8')], - ['"\\xB3"', 0263.chr.force_encoding('utf-8')], - ['"\\xB4"', 0264.chr.force_encoding('utf-8')], - ['"\\xB5"', 0265.chr.force_encoding('utf-8')], - ['"\\xB6"', 0266.chr.force_encoding('utf-8')], - ['"\\xB7"', 0267.chr.force_encoding('utf-8')], - ['"\\xB8"', 0270.chr.force_encoding('utf-8')], - ['"\\xB9"', 0271.chr.force_encoding('utf-8')], - ['"\\xBA"', 0272.chr.force_encoding('utf-8')], - ['"\\xBB"', 0273.chr.force_encoding('utf-8')], - ['"\\xBC"', 0274.chr.force_encoding('utf-8')], - ['"\\xBD"', 0275.chr.force_encoding('utf-8')], - ['"\\xBE"', 0276.chr.force_encoding('utf-8')], - ['"\\xBF"', 0277.chr.force_encoding('utf-8')], - ['"\\xC0"', 0300.chr.force_encoding('utf-8')], - ['"\\xC1"', 0301.chr.force_encoding('utf-8')], - ['"\\xC2"', 0302.chr.force_encoding('utf-8')], - ['"\\xC3"', 0303.chr.force_encoding('utf-8')], - ['"\\xC4"', 0304.chr.force_encoding('utf-8')], - ['"\\xC5"', 0305.chr.force_encoding('utf-8')], - ['"\\xC6"', 0306.chr.force_encoding('utf-8')], - ['"\\xC7"', 0307.chr.force_encoding('utf-8')], - ['"\\xC8"', 0310.chr.force_encoding('utf-8')], - ['"\\xC9"', 0311.chr.force_encoding('utf-8')], - ['"\\xCA"', 0312.chr.force_encoding('utf-8')], - ['"\\xCB"', 0313.chr.force_encoding('utf-8')], - ['"\\xCC"', 0314.chr.force_encoding('utf-8')], - ['"\\xCD"', 0315.chr.force_encoding('utf-8')], - ['"\\xCE"', 0316.chr.force_encoding('utf-8')], - ['"\\xCF"', 0317.chr.force_encoding('utf-8')], - ['"\\xD0"', 0320.chr.force_encoding('utf-8')], - ['"\\xD1"', 0321.chr.force_encoding('utf-8')], - ['"\\xD2"', 0322.chr.force_encoding('utf-8')], - ['"\\xD3"', 0323.chr.force_encoding('utf-8')], - ['"\\xD4"', 0324.chr.force_encoding('utf-8')], - ['"\\xD5"', 0325.chr.force_encoding('utf-8')], - ['"\\xD6"', 0326.chr.force_encoding('utf-8')], - ['"\\xD7"', 0327.chr.force_encoding('utf-8')], - ['"\\xD8"', 0330.chr.force_encoding('utf-8')], - ['"\\xD9"', 0331.chr.force_encoding('utf-8')], - ['"\\xDA"', 0332.chr.force_encoding('utf-8')], - ['"\\xDB"', 0333.chr.force_encoding('utf-8')], - ['"\\xDC"', 0334.chr.force_encoding('utf-8')], - ['"\\xDD"', 0335.chr.force_encoding('utf-8')], - ['"\\xDE"', 0336.chr.force_encoding('utf-8')], - ['"\\xDF"', 0337.chr.force_encoding('utf-8')], - ['"\\xE0"', 0340.chr.force_encoding('utf-8')], - ['"\\xE1"', 0341.chr.force_encoding('utf-8')], - ['"\\xE2"', 0342.chr.force_encoding('utf-8')], - ['"\\xE3"', 0343.chr.force_encoding('utf-8')], - ['"\\xE4"', 0344.chr.force_encoding('utf-8')], - ['"\\xE5"', 0345.chr.force_encoding('utf-8')], - ['"\\xE6"', 0346.chr.force_encoding('utf-8')], - ['"\\xE7"', 0347.chr.force_encoding('utf-8')], - ['"\\xE8"', 0350.chr.force_encoding('utf-8')], - ['"\\xE9"', 0351.chr.force_encoding('utf-8')], - ['"\\xEA"', 0352.chr.force_encoding('utf-8')], - ['"\\xEB"', 0353.chr.force_encoding('utf-8')], - ['"\\xEC"', 0354.chr.force_encoding('utf-8')], - ['"\\xED"', 0355.chr.force_encoding('utf-8')], - ['"\\xEE"', 0356.chr.force_encoding('utf-8')], - ['"\\xEF"', 0357.chr.force_encoding('utf-8')], - ['"\\xF0"', 0360.chr.force_encoding('utf-8')], - ['"\\xF1"', 0361.chr.force_encoding('utf-8')], - ['"\\xF2"', 0362.chr.force_encoding('utf-8')], - ['"\\xF3"', 0363.chr.force_encoding('utf-8')], - ['"\\xF4"', 0364.chr.force_encoding('utf-8')], - ['"\\xF5"', 0365.chr.force_encoding('utf-8')], - ['"\\xF6"', 0366.chr.force_encoding('utf-8')], - ['"\\xF7"', 0367.chr.force_encoding('utf-8')], - ['"\\xF8"', 0370.chr.force_encoding('utf-8')], - ['"\\xF9"', 0371.chr.force_encoding('utf-8')], - ['"\\xFA"', 0372.chr.force_encoding('utf-8')], - ['"\\xFB"', 0373.chr.force_encoding('utf-8')], - ['"\\xFC"', 0374.chr.force_encoding('utf-8')], - ['"\\xFD"', 0375.chr.force_encoding('utf-8')], - ['"\\xFE"', 0376.chr.force_encoding('utf-8')], - ['"\\xFF"', 0377.chr.force_encoding('utf-8')] - ].should be_computed_by(:undump) - end + it "returns a string with lower-case alpha characters unescaped" do + [ ['"a"', 'a'], + ['"b"', 'b'], + ['"c"', 'c'], + ['"d"', 'd'], + ['"e"', 'e'], + ['"f"', 'f'], + ['"g"', 'g'], + ['"h"', 'h'], + ['"i"', 'i'], + ['"j"', 'j'], + ['"k"', 'k'], + ['"l"', 'l'], + ['"m"', 'm'], + ['"n"', 'n'], + ['"o"', 'o'], + ['"p"', 'p'], + ['"q"', 'q'], + ['"r"', 'r'], + ['"s"', 's'], + ['"t"', 't'], + ['"u"', 'u'], + ['"v"', 'v'], + ['"w"', 'w'], + ['"x"', 'x'], + ['"y"', 'y'], + ['"z"', 'z'] + ].should be_computed_by(:undump) + end - it "returns a string with \\u{} notation replaced with multi-byte UTF-8 characters" do - [ ['"\u{80}"', 0200.chr('utf-8')], - ['"\u{81}"', 0201.chr('utf-8')], - ['"\u{82}"', 0202.chr('utf-8')], - ['"\u{83}"', 0203.chr('utf-8')], - ['"\u{84}"', 0204.chr('utf-8')], - ['"\u{86}"', 0206.chr('utf-8')], - ['"\u{87}"', 0207.chr('utf-8')], - ['"\u{88}"', 0210.chr('utf-8')], - ['"\u{89}"', 0211.chr('utf-8')], - ['"\u{8a}"', 0212.chr('utf-8')], - ['"\u{8b}"', 0213.chr('utf-8')], - ['"\u{8c}"', 0214.chr('utf-8')], - ['"\u{8d}"', 0215.chr('utf-8')], - ['"\u{8e}"', 0216.chr('utf-8')], - ['"\u{8f}"', 0217.chr('utf-8')], - ['"\u{90}"', 0220.chr('utf-8')], - ['"\u{91}"', 0221.chr('utf-8')], - ['"\u{92}"', 0222.chr('utf-8')], - ['"\u{93}"', 0223.chr('utf-8')], - ['"\u{94}"', 0224.chr('utf-8')], - ['"\u{95}"', 0225.chr('utf-8')], - ['"\u{96}"', 0226.chr('utf-8')], - ['"\u{97}"', 0227.chr('utf-8')], - ['"\u{98}"', 0230.chr('utf-8')], - ['"\u{99}"', 0231.chr('utf-8')], - ['"\u{9a}"', 0232.chr('utf-8')], - ['"\u{9b}"', 0233.chr('utf-8')], - ['"\u{9c}"', 0234.chr('utf-8')], - ['"\u{9d}"', 0235.chr('utf-8')], - ['"\u{9e}"', 0236.chr('utf-8')], - ['"\u{9f}"', 0237.chr('utf-8')], - ].should be_computed_by(:undump) - end + it "returns a string with \\x notation replaced with non-printing ASCII character" do + [ ['"\\x00"', 0000.chr.force_encoding('utf-8')], + ['"\\x01"', 0001.chr.force_encoding('utf-8')], + ['"\\x02"', 0002.chr.force_encoding('utf-8')], + ['"\\x03"', 0003.chr.force_encoding('utf-8')], + ['"\\x04"', 0004.chr.force_encoding('utf-8')], + ['"\\x05"', 0005.chr.force_encoding('utf-8')], + ['"\\x06"', 0006.chr.force_encoding('utf-8')], + ['"\\x0E"', 0016.chr.force_encoding('utf-8')], + ['"\\x0F"', 0017.chr.force_encoding('utf-8')], + ['"\\x10"', 0020.chr.force_encoding('utf-8')], + ['"\\x11"', 0021.chr.force_encoding('utf-8')], + ['"\\x12"', 0022.chr.force_encoding('utf-8')], + ['"\\x13"', 0023.chr.force_encoding('utf-8')], + ['"\\x14"', 0024.chr.force_encoding('utf-8')], + ['"\\x15"', 0025.chr.force_encoding('utf-8')], + ['"\\x16"', 0026.chr.force_encoding('utf-8')], + ['"\\x17"', 0027.chr.force_encoding('utf-8')], + ['"\\x18"', 0030.chr.force_encoding('utf-8')], + ['"\\x19"', 0031.chr.force_encoding('utf-8')], + ['"\\x1A"', 0032.chr.force_encoding('utf-8')], + ['"\\x1C"', 0034.chr.force_encoding('utf-8')], + ['"\\x1D"', 0035.chr.force_encoding('utf-8')], + ['"\\x1E"', 0036.chr.force_encoding('utf-8')], + ['"\\x1F"', 0037.chr.force_encoding('utf-8')], + ['"\\x7F"', 0177.chr.force_encoding('utf-8')], + ['"\\x80"', 0200.chr.force_encoding('utf-8')], + ['"\\x81"', 0201.chr.force_encoding('utf-8')], + ['"\\x82"', 0202.chr.force_encoding('utf-8')], + ['"\\x83"', 0203.chr.force_encoding('utf-8')], + ['"\\x84"', 0204.chr.force_encoding('utf-8')], + ['"\\x85"', 0205.chr.force_encoding('utf-8')], + ['"\\x86"', 0206.chr.force_encoding('utf-8')], + ['"\\x87"', 0207.chr.force_encoding('utf-8')], + ['"\\x88"', 0210.chr.force_encoding('utf-8')], + ['"\\x89"', 0211.chr.force_encoding('utf-8')], + ['"\\x8A"', 0212.chr.force_encoding('utf-8')], + ['"\\x8B"', 0213.chr.force_encoding('utf-8')], + ['"\\x8C"', 0214.chr.force_encoding('utf-8')], + ['"\\x8D"', 0215.chr.force_encoding('utf-8')], + ['"\\x8E"', 0216.chr.force_encoding('utf-8')], + ['"\\x8F"', 0217.chr.force_encoding('utf-8')], + ['"\\x90"', 0220.chr.force_encoding('utf-8')], + ['"\\x91"', 0221.chr.force_encoding('utf-8')], + ['"\\x92"', 0222.chr.force_encoding('utf-8')], + ['"\\x93"', 0223.chr.force_encoding('utf-8')], + ['"\\x94"', 0224.chr.force_encoding('utf-8')], + ['"\\x95"', 0225.chr.force_encoding('utf-8')], + ['"\\x96"', 0226.chr.force_encoding('utf-8')], + ['"\\x97"', 0227.chr.force_encoding('utf-8')], + ['"\\x98"', 0230.chr.force_encoding('utf-8')], + ['"\\x99"', 0231.chr.force_encoding('utf-8')], + ['"\\x9A"', 0232.chr.force_encoding('utf-8')], + ['"\\x9B"', 0233.chr.force_encoding('utf-8')], + ['"\\x9C"', 0234.chr.force_encoding('utf-8')], + ['"\\x9D"', 0235.chr.force_encoding('utf-8')], + ['"\\x9E"', 0236.chr.force_encoding('utf-8')], + ['"\\x9F"', 0237.chr.force_encoding('utf-8')], + ['"\\xA0"', 0240.chr.force_encoding('utf-8')], + ['"\\xA1"', 0241.chr.force_encoding('utf-8')], + ['"\\xA2"', 0242.chr.force_encoding('utf-8')], + ['"\\xA3"', 0243.chr.force_encoding('utf-8')], + ['"\\xA4"', 0244.chr.force_encoding('utf-8')], + ['"\\xA5"', 0245.chr.force_encoding('utf-8')], + ['"\\xA6"', 0246.chr.force_encoding('utf-8')], + ['"\\xA7"', 0247.chr.force_encoding('utf-8')], + ['"\\xA8"', 0250.chr.force_encoding('utf-8')], + ['"\\xA9"', 0251.chr.force_encoding('utf-8')], + ['"\\xAA"', 0252.chr.force_encoding('utf-8')], + ['"\\xAB"', 0253.chr.force_encoding('utf-8')], + ['"\\xAC"', 0254.chr.force_encoding('utf-8')], + ['"\\xAD"', 0255.chr.force_encoding('utf-8')], + ['"\\xAE"', 0256.chr.force_encoding('utf-8')], + ['"\\xAF"', 0257.chr.force_encoding('utf-8')], + ['"\\xB0"', 0260.chr.force_encoding('utf-8')], + ['"\\xB1"', 0261.chr.force_encoding('utf-8')], + ['"\\xB2"', 0262.chr.force_encoding('utf-8')], + ['"\\xB3"', 0263.chr.force_encoding('utf-8')], + ['"\\xB4"', 0264.chr.force_encoding('utf-8')], + ['"\\xB5"', 0265.chr.force_encoding('utf-8')], + ['"\\xB6"', 0266.chr.force_encoding('utf-8')], + ['"\\xB7"', 0267.chr.force_encoding('utf-8')], + ['"\\xB8"', 0270.chr.force_encoding('utf-8')], + ['"\\xB9"', 0271.chr.force_encoding('utf-8')], + ['"\\xBA"', 0272.chr.force_encoding('utf-8')], + ['"\\xBB"', 0273.chr.force_encoding('utf-8')], + ['"\\xBC"', 0274.chr.force_encoding('utf-8')], + ['"\\xBD"', 0275.chr.force_encoding('utf-8')], + ['"\\xBE"', 0276.chr.force_encoding('utf-8')], + ['"\\xBF"', 0277.chr.force_encoding('utf-8')], + ['"\\xC0"', 0300.chr.force_encoding('utf-8')], + ['"\\xC1"', 0301.chr.force_encoding('utf-8')], + ['"\\xC2"', 0302.chr.force_encoding('utf-8')], + ['"\\xC3"', 0303.chr.force_encoding('utf-8')], + ['"\\xC4"', 0304.chr.force_encoding('utf-8')], + ['"\\xC5"', 0305.chr.force_encoding('utf-8')], + ['"\\xC6"', 0306.chr.force_encoding('utf-8')], + ['"\\xC7"', 0307.chr.force_encoding('utf-8')], + ['"\\xC8"', 0310.chr.force_encoding('utf-8')], + ['"\\xC9"', 0311.chr.force_encoding('utf-8')], + ['"\\xCA"', 0312.chr.force_encoding('utf-8')], + ['"\\xCB"', 0313.chr.force_encoding('utf-8')], + ['"\\xCC"', 0314.chr.force_encoding('utf-8')], + ['"\\xCD"', 0315.chr.force_encoding('utf-8')], + ['"\\xCE"', 0316.chr.force_encoding('utf-8')], + ['"\\xCF"', 0317.chr.force_encoding('utf-8')], + ['"\\xD0"', 0320.chr.force_encoding('utf-8')], + ['"\\xD1"', 0321.chr.force_encoding('utf-8')], + ['"\\xD2"', 0322.chr.force_encoding('utf-8')], + ['"\\xD3"', 0323.chr.force_encoding('utf-8')], + ['"\\xD4"', 0324.chr.force_encoding('utf-8')], + ['"\\xD5"', 0325.chr.force_encoding('utf-8')], + ['"\\xD6"', 0326.chr.force_encoding('utf-8')], + ['"\\xD7"', 0327.chr.force_encoding('utf-8')], + ['"\\xD8"', 0330.chr.force_encoding('utf-8')], + ['"\\xD9"', 0331.chr.force_encoding('utf-8')], + ['"\\xDA"', 0332.chr.force_encoding('utf-8')], + ['"\\xDB"', 0333.chr.force_encoding('utf-8')], + ['"\\xDC"', 0334.chr.force_encoding('utf-8')], + ['"\\xDD"', 0335.chr.force_encoding('utf-8')], + ['"\\xDE"', 0336.chr.force_encoding('utf-8')], + ['"\\xDF"', 0337.chr.force_encoding('utf-8')], + ['"\\xE0"', 0340.chr.force_encoding('utf-8')], + ['"\\xE1"', 0341.chr.force_encoding('utf-8')], + ['"\\xE2"', 0342.chr.force_encoding('utf-8')], + ['"\\xE3"', 0343.chr.force_encoding('utf-8')], + ['"\\xE4"', 0344.chr.force_encoding('utf-8')], + ['"\\xE5"', 0345.chr.force_encoding('utf-8')], + ['"\\xE6"', 0346.chr.force_encoding('utf-8')], + ['"\\xE7"', 0347.chr.force_encoding('utf-8')], + ['"\\xE8"', 0350.chr.force_encoding('utf-8')], + ['"\\xE9"', 0351.chr.force_encoding('utf-8')], + ['"\\xEA"', 0352.chr.force_encoding('utf-8')], + ['"\\xEB"', 0353.chr.force_encoding('utf-8')], + ['"\\xEC"', 0354.chr.force_encoding('utf-8')], + ['"\\xED"', 0355.chr.force_encoding('utf-8')], + ['"\\xEE"', 0356.chr.force_encoding('utf-8')], + ['"\\xEF"', 0357.chr.force_encoding('utf-8')], + ['"\\xF0"', 0360.chr.force_encoding('utf-8')], + ['"\\xF1"', 0361.chr.force_encoding('utf-8')], + ['"\\xF2"', 0362.chr.force_encoding('utf-8')], + ['"\\xF3"', 0363.chr.force_encoding('utf-8')], + ['"\\xF4"', 0364.chr.force_encoding('utf-8')], + ['"\\xF5"', 0365.chr.force_encoding('utf-8')], + ['"\\xF6"', 0366.chr.force_encoding('utf-8')], + ['"\\xF7"', 0367.chr.force_encoding('utf-8')], + ['"\\xF8"', 0370.chr.force_encoding('utf-8')], + ['"\\xF9"', 0371.chr.force_encoding('utf-8')], + ['"\\xFA"', 0372.chr.force_encoding('utf-8')], + ['"\\xFB"', 0373.chr.force_encoding('utf-8')], + ['"\\xFC"', 0374.chr.force_encoding('utf-8')], + ['"\\xFD"', 0375.chr.force_encoding('utf-8')], + ['"\\xFE"', 0376.chr.force_encoding('utf-8')], + ['"\\xFF"', 0377.chr.force_encoding('utf-8')] + ].should be_computed_by(:undump) + end - it "returns a string with \\uXXXX notation replaced with multi-byte UTF-8 characters" do - [ ['"\u0080"', 0200.chr('utf-8')], - ['"\u0081"', 0201.chr('utf-8')], - ['"\u0082"', 0202.chr('utf-8')], - ['"\u0083"', 0203.chr('utf-8')], - ['"\u0084"', 0204.chr('utf-8')], - ['"\u0086"', 0206.chr('utf-8')], - ['"\u0087"', 0207.chr('utf-8')], - ['"\u0088"', 0210.chr('utf-8')], - ['"\u0089"', 0211.chr('utf-8')], - ['"\u008a"', 0212.chr('utf-8')], - ['"\u008b"', 0213.chr('utf-8')], - ['"\u008c"', 0214.chr('utf-8')], - ['"\u008d"', 0215.chr('utf-8')], - ['"\u008e"', 0216.chr('utf-8')], - ['"\u008f"', 0217.chr('utf-8')], - ['"\u0090"', 0220.chr('utf-8')], - ['"\u0091"', 0221.chr('utf-8')], - ['"\u0092"', 0222.chr('utf-8')], - ['"\u0093"', 0223.chr('utf-8')], - ['"\u0094"', 0224.chr('utf-8')], - ['"\u0095"', 0225.chr('utf-8')], - ['"\u0096"', 0226.chr('utf-8')], - ['"\u0097"', 0227.chr('utf-8')], - ['"\u0098"', 0230.chr('utf-8')], - ['"\u0099"', 0231.chr('utf-8')], - ['"\u009a"', 0232.chr('utf-8')], - ['"\u009b"', 0233.chr('utf-8')], - ['"\u009c"', 0234.chr('utf-8')], - ['"\u009d"', 0235.chr('utf-8')], - ['"\u009e"', 0236.chr('utf-8')], - ['"\u009f"', 0237.chr('utf-8')], - ].should be_computed_by(:undump) - end + it "returns a string with \\u{} notation replaced with multi-byte UTF-8 characters" do + [ ['"\u{80}"', 0200.chr('utf-8')], + ['"\u{81}"', 0201.chr('utf-8')], + ['"\u{82}"', 0202.chr('utf-8')], + ['"\u{83}"', 0203.chr('utf-8')], + ['"\u{84}"', 0204.chr('utf-8')], + ['"\u{86}"', 0206.chr('utf-8')], + ['"\u{87}"', 0207.chr('utf-8')], + ['"\u{88}"', 0210.chr('utf-8')], + ['"\u{89}"', 0211.chr('utf-8')], + ['"\u{8a}"', 0212.chr('utf-8')], + ['"\u{8b}"', 0213.chr('utf-8')], + ['"\u{8c}"', 0214.chr('utf-8')], + ['"\u{8d}"', 0215.chr('utf-8')], + ['"\u{8e}"', 0216.chr('utf-8')], + ['"\u{8f}"', 0217.chr('utf-8')], + ['"\u{90}"', 0220.chr('utf-8')], + ['"\u{91}"', 0221.chr('utf-8')], + ['"\u{92}"', 0222.chr('utf-8')], + ['"\u{93}"', 0223.chr('utf-8')], + ['"\u{94}"', 0224.chr('utf-8')], + ['"\u{95}"', 0225.chr('utf-8')], + ['"\u{96}"', 0226.chr('utf-8')], + ['"\u{97}"', 0227.chr('utf-8')], + ['"\u{98}"', 0230.chr('utf-8')], + ['"\u{99}"', 0231.chr('utf-8')], + ['"\u{9a}"', 0232.chr('utf-8')], + ['"\u{9b}"', 0233.chr('utf-8')], + ['"\u{9c}"', 0234.chr('utf-8')], + ['"\u{9d}"', 0235.chr('utf-8')], + ['"\u{9e}"', 0236.chr('utf-8')], + ['"\u{9f}"', 0237.chr('utf-8')], + ].should be_computed_by(:undump) + end - it "undumps correctly string produced from non ASCII-compatible one" do - s = "\u{876}".encode('utf-16be') - s.dump.undump.should == s + it "returns a string with \\uXXXX notation replaced with multi-byte UTF-8 characters" do + [ ['"\u0080"', 0200.chr('utf-8')], + ['"\u0081"', 0201.chr('utf-8')], + ['"\u0082"', 0202.chr('utf-8')], + ['"\u0083"', 0203.chr('utf-8')], + ['"\u0084"', 0204.chr('utf-8')], + ['"\u0086"', 0206.chr('utf-8')], + ['"\u0087"', 0207.chr('utf-8')], + ['"\u0088"', 0210.chr('utf-8')], + ['"\u0089"', 0211.chr('utf-8')], + ['"\u008a"', 0212.chr('utf-8')], + ['"\u008b"', 0213.chr('utf-8')], + ['"\u008c"', 0214.chr('utf-8')], + ['"\u008d"', 0215.chr('utf-8')], + ['"\u008e"', 0216.chr('utf-8')], + ['"\u008f"', 0217.chr('utf-8')], + ['"\u0090"', 0220.chr('utf-8')], + ['"\u0091"', 0221.chr('utf-8')], + ['"\u0092"', 0222.chr('utf-8')], + ['"\u0093"', 0223.chr('utf-8')], + ['"\u0094"', 0224.chr('utf-8')], + ['"\u0095"', 0225.chr('utf-8')], + ['"\u0096"', 0226.chr('utf-8')], + ['"\u0097"', 0227.chr('utf-8')], + ['"\u0098"', 0230.chr('utf-8')], + ['"\u0099"', 0231.chr('utf-8')], + ['"\u009a"', 0232.chr('utf-8')], + ['"\u009b"', 0233.chr('utf-8')], + ['"\u009c"', 0234.chr('utf-8')], + ['"\u009d"', 0235.chr('utf-8')], + ['"\u009e"', 0236.chr('utf-8')], + ['"\u009f"', 0237.chr('utf-8')], + ].should be_computed_by(:undump) + end - '"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be') - end + it "undumps correctly string produced from non ASCII-compatible one" do + s = "\u{876}".encode('utf-16be') + s.dump.undump.should == s - it "keeps origin encoding" do - '"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1 - '"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251 - end + '"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be') + end + + it "keeps origin encoding" do + '"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1 + '"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251 + end - describe "Limitations" do - it "cannot undump non ASCII-compatible string" do - -> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError) - end + describe "Limitations" do + it "cannot undump non ASCII-compatible string" do + -> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError) end + end - describe "invalid dump" do - it "raises RuntimeError exception if wrapping \" are missing" do - -> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/) - -> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/) - -> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/) - -> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/) - end + describe "invalid dump" do + it "raises RuntimeError exception if wrapping \" are missing" do + -> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/) + -> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/) + -> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/) + -> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/) + end - it "raises RuntimeError if there is incorrect \\x sequence" do - -> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/) - -> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/) - end + it "raises RuntimeError if there is incorrect \\x sequence" do + -> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/) + -> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/) + end - it "raises RuntimeError in there is incorrect \\u sequence" do - -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) - -> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) - -> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) - -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) - end + it "raises RuntimeError in there is incorrect \\u sequence" do + -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) + -> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) + -> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) + -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/) + end - it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do - -> { '"".force_encoding("BINARY"'.undump }.should raise_error(RuntimeError, /invalid dumped string/) - -> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/) - -> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/) - end + it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do + -> { '"".force_encoding("BINARY"'.undump }.should raise_error(RuntimeError, /invalid dumped string/) + -> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/) + -> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/) + end - it "raises RuntimeError if string contains \0 character" do - -> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/) - end + it "raises RuntimeError if string contains \0 character" do + -> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/) + end - it "raises RuntimeError if string contains non ASCII character" do - -> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/) - end + it "raises RuntimeError if string contains non ASCII character" do + -> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/) + end - it "raises RuntimeError if there are some excessive \"" do - -> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/) - end + it "raises RuntimeError if there are some excessive \"" do + -> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/) end end end diff --git a/ruby/spec/ruby/core/string/unicode_normalized_spec.rb b/ruby/spec/ruby/core/string/unicode_normalized_spec.rb index 25c810a98..87f374045 100644 --- a/ruby/spec/ruby/core/string/unicode_normalized_spec.rb +++ b/ruby/spec/ruby/core/string/unicode_normalized_spec.rb @@ -24,16 +24,16 @@ end it "defaults to the nfc normalization form if no forms are specified" do - @nfc_normalized_str.unicode_normalized?.should == true - @nfd_normalized_str.unicode_normalized?.should == false + @nfc_normalized_str.should.unicode_normalized? + @nfd_normalized_str.should_not.unicode_normalized? end it "returns true if string is empty" do - "".unicode_normalized?.should == true + "".should.unicode_normalized? end it "returns true if string does not contain any unicode codepoints" do - "abc".unicode_normalized?.should == true + "abc".should.unicode_normalized? end it "raises an Encoding::CompatibilityError if the string is not in an unicode encoding" do diff --git a/ruby/spec/ruby/core/string/unpack/m_spec.rb b/ruby/spec/ruby/core/string/unpack/m_spec.rb index 96841f24c..21134514a 100644 --- a/ruby/spec/ruby/core/string/unpack/m_spec.rb +++ b/ruby/spec/ruby/core/string/unpack/m_spec.rb @@ -170,4 +170,18 @@ "".unpack("m").first.encoding.should == Encoding::BINARY "Ojs8PT4/QA==\n".unpack("m").first.encoding.should == Encoding::BINARY end + + it "does not raise an error for an invalid base64 character" do + "dGV%zdA==".unpack("m").should == ["test"] + end + + describe "when given count 0" do + it "decodes base64" do + "dGVzdA==".unpack("m0").should == ["test"] + end + + it "raises an ArgumentError for an invalid base64 character" do + -> { "dGV%zdA==".unpack("m0") }.should raise_error(ArgumentError) + end + end end diff --git a/ruby/spec/ruby/core/string/unpack/shared/basic.rb b/ruby/spec/ruby/core/string/unpack/shared/basic.rb index 332e39d8d..f636f4689 100644 --- a/ruby/spec/ruby/core/string/unpack/shared/basic.rb +++ b/ruby/spec/ruby/core/string/unpack/shared/basic.rb @@ -16,6 +16,12 @@ it "raises a TypeError when passed an Integer" do -> { "abc".unpack(1) }.should raise_error(TypeError) end + + ruby_version_is "3.1" do + it "starts unpacking from the given offset" do + "abc".unpack("CC", offset: 1).should == [98, 99] + end + end end describe :string_unpack_no_platform, shared: true do @@ -26,4 +32,18 @@ it "raises an ArgumentError when the format modifier is '!'" do -> { "abcdefgh".unpack(unpack_format("!")) }.should raise_error(ArgumentError) end + + ruby_version_is "3.1" do + it "raises an ArgumentError when the offset is negative" do + -> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError) + end + + it "returns nil if the offset is at the end of the string" do + "a".unpack("C", offset: 1).should == [nil] + end + + it "raises an ArgumentError when the offset is larget than the string" do + -> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError) + end + end end diff --git a/ruby/spec/ruby/core/string/unpack/w_spec.rb b/ruby/spec/ruby/core/string/unpack/w_spec.rb index 166ae5886..011c75f5c 100644 --- a/ruby/spec/ruby/core/string/unpack/w_spec.rb +++ b/ruby/spec/ruby/core/string/unpack/w_spec.rb @@ -23,3 +23,13 @@ "\x01\x02\x03".unpack("w w").should == [1, 2] end end + +describe "String#unpack with directive 'w*'" do + + it "decodes BER-compressed integers" do + "\x01\x02\x03\x04".unpack("w*").should == [1, 2, 3, 4] + "\x00\xCE\x0F\x84\x80\x80\x80\x80\x80\x80\x80\x80\x00\x01\x00".unpack("w*").should == [0, 9999, 2**65, 1, 0] + "\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00\x90\x80\x80\x80\x80\x80\x80\x80\x03\x01\x02".unpack("w*").should == [2**63, (2**60 + 3), 1, 2] + end + +end diff --git a/ruby/spec/ruby/core/string/unpack1_spec.rb b/ruby/spec/ruby/core/string/unpack1_spec.rb index 5fe81733f..f59bd92d6 100644 --- a/ruby/spec/ruby/core/string/unpack1_spec.rb +++ b/ruby/spec/ruby/core/string/unpack1_spec.rb @@ -7,4 +7,24 @@ "aG9nZWZ1Z2E=".unpack1("m").should == "hogefuga" "A".unpack1("B*").should == "01000001" end + + ruby_version_is "3.1" do + it "starts unpacking from the given offset" do + "ZZABCD".unpack1('x3C', offset: 2).should == "ABCD".unpack('x3C')[0] + "ZZZZaG9nZWZ1Z2E=".unpack1("m", offset: 4).should == "hogefuga" + "ZA".unpack1("B*", offset: 1).should == "01000001" + end + + it "raises an ArgumentError when the offset is negative" do + -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError) + end + + it "returns nil if the offset is at the end of the string" do + "a".unpack1("C", offset: 1).should == nil + end + + it "raises an ArgumentError when the offset is larget than the string" do + -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError) + end + end end diff --git a/ruby/spec/ruby/core/string/upcase_spec.rb b/ruby/spec/ruby/core/string/upcase_spec.rb index eb7d708fe..6cf44b470 100644 --- a/ruby/spec/ruby/core/string/upcase_spec.rb +++ b/ruby/spec/ruby/core/string/upcase_spec.rb @@ -67,14 +67,22 @@ ruby_version_is ''...'2.7' do it "taints result when self is tainted" do - "".taint.upcase.tainted?.should == true - "X".taint.upcase.tainted?.should == true - "x".taint.upcase.tainted?.should == true + "".taint.upcase.should.tainted? + "X".taint.upcase.should.tainted? + "x".taint.upcase.should.tainted? end end - it "returns a subclass instance for subclasses" do - StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance for subclasses" do + StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance for subclasses" do + StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(String) + end end end @@ -85,6 +93,12 @@ a.should == "HELLO" end + it "modifies self in place for non-ascii-compatible encodings" do + a = "HeLlO".encode("utf-16le") + a.upcase! + a.should == "HELLO".encode("utf-16le") + end + describe "full Unicode case mapping" do it "modifies self in place for all of Unicode with no option" do a = "äöü" @@ -92,6 +106,12 @@ a.should == "ÄÖÜ" end + it "works for non-ascii-compatible encodings" do + a = "äöü".encode("utf-16le") + a.upcase! + a.should == "ÄÖÜ".encode("utf-16le") + end + it "updates string metadata for self" do upcased = "aßet" upcased.upcase! @@ -109,6 +129,12 @@ a.upcase!(:ascii) a.should == "AßET" end + + it "works for non-ascii-compatible encodings" do + a = "abc".encode("utf-16le") + a.upcase!(:ascii) + a.should == "ABC".encode("utf-16le") + end end describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do @@ -161,8 +187,8 @@ a.should == "HELLO" end - it "raises a #{frozen_error_class} when self is frozen" do - -> { "HeLlo".freeze.upcase! }.should raise_error(frozen_error_class) - -> { "HELLO".freeze.upcase! }.should raise_error(frozen_error_class) + it "raises a FrozenError when self is frozen" do + -> { "HeLlo".freeze.upcase! }.should raise_error(FrozenError) + -> { "HELLO".freeze.upcase! }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/core/string/uplus_spec.rb b/ruby/spec/ruby/core/string/uplus_spec.rb index a7402b454..038b283c9 100644 --- a/ruby/spec/ruby/core/string/uplus_spec.rb +++ b/ruby/spec/ruby/core/string/uplus_spec.rb @@ -5,7 +5,7 @@ input = 'foo'.freeze output = +input - output.frozen?.should == false + output.should_not.frozen? output.should == 'foo' end diff --git a/ruby/spec/ruby/core/string/upto_spec.rb b/ruby/spec/ruby/core/string/upto_spec.rb index b988613a8..f8529b1d2 100644 --- a/ruby/spec/ruby/core/string/upto_spec.rb +++ b/ruby/spec/ruby/core/string/upto_spec.rb @@ -74,6 +74,12 @@ def other.to_str() "abd" end a.should == ["a", "b", "c"] end + it "works with non-ASCII ranges" do + a = [] + 'Σ'.upto('Ω') { |s| a << s } + a.should == ["Σ", "Τ", "Î¥", "Φ", "Χ", "Ψ", "Ω"] + end + describe "on sequence of numbers" do it "calls the block as Integer#upto" do "8".upto("11").to_a.should == 8.upto(11).map(&:to_s) diff --git a/ruby/spec/ruby/core/string/valid_encoding_spec.rb b/ruby/spec/ruby/core/string/valid_encoding_spec.rb index 09916df07..be7cef7a8 100644 --- a/ruby/spec/ruby/core/string/valid_encoding_spec.rb +++ b/ruby/spec/ruby/core/string/valid_encoding_spec.rb @@ -13,7 +13,7 @@ end it "returns true for all encodings self is valid in" do - str = "\u{6754}" + str = "\xE6\x9D\x94" str.force_encoding('BINARY').valid_encoding?.should be_true str.force_encoding('UTF-8').valid_encoding?.should be_true str.force_encoding('US-ASCII').valid_encoding?.should be_false @@ -43,10 +43,10 @@ str.force_encoding('KOI8-R').valid_encoding?.should be_true str.force_encoding('KOI8-U').valid_encoding?.should be_true str.force_encoding('Shift_JIS').valid_encoding?.should be_false - str.force_encoding('UTF-16BE').valid_encoding?.should be_false - str.force_encoding('UTF-16LE').valid_encoding?.should be_false - str.force_encoding('UTF-32BE').valid_encoding?.should be_false - str.force_encoding('UTF-32LE').valid_encoding?.should be_false + "\xD8\x00".force_encoding('UTF-16BE').valid_encoding?.should be_false + "\x00\xD8".force_encoding('UTF-16LE').valid_encoding?.should be_false + "\x04\x03\x02\x01".force_encoding('UTF-32BE').valid_encoding?.should be_false + "\x01\x02\x03\x04".force_encoding('UTF-32LE').valid_encoding?.should be_false str.force_encoding('Windows-1251').valid_encoding?.should be_true str.force_encoding('IBM437').valid_encoding?.should be_true str.force_encoding('IBM737').valid_encoding?.should be_true @@ -100,6 +100,14 @@ str.force_encoding('UTF8-MAC').valid_encoding?.should be_true end + ruby_version_is '3.0' do + it "returns true for IBM720 encoding self is valid in" do + str = "\xE6\x9D\x94" + str.force_encoding('IBM720').valid_encoding?.should be_true + str.force_encoding('CP720').valid_encoding?.should be_true + end + end + it "returns false if self is valid in one encoding, but invalid in the one it's tagged with" do str = "\u{8765}" str.valid_encoding?.should be_true diff --git a/ruby/spec/ruby/core/struct/deconstruct_keys_spec.rb b/ruby/spec/ruby/core/struct/deconstruct_keys_spec.rb new file mode 100644 index 000000000..f0a1f50ad --- /dev/null +++ b/ruby/spec/ruby/core/struct/deconstruct_keys_spec.rb @@ -0,0 +1,78 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Struct#deconstruct_keys" do + it "returns a hash of attributes" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2} + end + + it "requires one argument" do + struct = Struct.new(:x) + obj = struct.new(1) + + -> { + obj.deconstruct_keys + }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/) + end + + it "returns only specified keys" do + struct = Struct.new(:x, :y, :z) + s = struct.new(1, 2, 3) + + s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2} + s.deconstruct_keys([:x] ).should == {x: 1} + s.deconstruct_keys([] ).should == {} + end + + it "accepts string attribute names" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + s.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2} + end + + it "accepts argument position number as well but returns them as keys" do + struct = Struct.new(:x, :y, :z) + s = struct.new(10, 20, 30) + + s.deconstruct_keys([0, 1, 2]).should == {0 => 10, 1 => 20, 2 => 30} + s.deconstruct_keys([0, 1] ).should == {0 => 10, 1 => 20} + s.deconstruct_keys([0] ).should == {0 => 10} + end + + it "returns an empty hash when there are more keys than attributes" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + s.deconstruct_keys([:x, :y, :a]).should == {} + end + + it "returns at first not existing attribute name" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + s.deconstruct_keys([:a, :x]).should == {} + s.deconstruct_keys([:x, :a]).should == {x: 1} + end + + it "accepts nil argument and return all the attributes" do + struct = Struct.new(:x, :y) + obj = struct.new(1, 2) + + obj.deconstruct_keys(nil).should == {x: 1, y: 2} + end + + it "raise TypeError if passed anything accept nil or array" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + -> { s.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/) + -> { s.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/) + -> { s.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/) + -> { s.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/) + end + end +end diff --git a/ruby/spec/ruby/core/struct/deconstruct_spec.rb b/ruby/spec/ruby/core/struct/deconstruct_spec.rb new file mode 100644 index 000000000..7518a4098 --- /dev/null +++ b/ruby/spec/ruby/core/struct/deconstruct_spec.rb @@ -0,0 +1,12 @@ +require_relative '../../spec_helper' + +ruby_version_is "2.7" do + describe "Struct#deconstruct" do + it "returns an array of attribute values" do + struct = Struct.new(:x, :y) + s = struct.new(1, 2) + + s.deconstruct.should == [1, 2] + end + end +end diff --git a/ruby/spec/ruby/core/struct/dig_spec.rb b/ruby/spec/ruby/core/struct/dig_spec.rb index 4e39e5a4e..93a52dbbe 100644 --- a/ruby/spec/ruby/core/struct/dig_spec.rb +++ b/ruby/spec/ruby/core/struct/dig_spec.rb @@ -10,6 +10,16 @@ @instance.dig(:a, :a).should == { b: [1, 2, 3] } end + it "accepts String keys" do + @instance.dig('a', 'a').should == { b: [1, 2, 3] } + end + + it "returns the value by the index" do + instance = Struct.new(:a, :b).new(:one, :two) + instance.dig(0).should == :one + instance.dig(1).should == :two + end + it "returns the nested value specified if the sequence includes an index" do @instance.dig(:a, :a, :b, 0).should == 1 end diff --git a/ruby/spec/ruby/core/struct/filter_spec.rb b/ruby/spec/ruby/core/struct/filter_spec.rb index 1105ed064..0ccd8ad6b 100644 --- a/ruby/spec/ruby/core/struct/filter_spec.rb +++ b/ruby/spec/ruby/core/struct/filter_spec.rb @@ -3,10 +3,8 @@ require_relative 'shared/accessor' require_relative '../enumerable/shared/enumeratorized' -ruby_version_is "2.6" do - describe "Struct#filter" do - it_behaves_like :struct_select, :filter - it_behaves_like :struct_accessor, :filter - it_behaves_like :enumeratorized_with_origin_size, :filter, Struct.new(:foo).new - end +describe "Struct#filter" do + it_behaves_like :struct_select, :filter + it_behaves_like :struct_accessor, :filter + it_behaves_like :enumeratorized_with_origin_size, :filter, Struct.new(:foo).new end diff --git a/ruby/spec/ruby/core/struct/hash_spec.rb b/ruby/spec/ruby/core/struct/hash_spec.rb index 71e8ccbd3..53361eb7a 100644 --- a/ruby/spec/ruby/core/struct/hash_spec.rb +++ b/ruby/spec/ruby/core/struct/hash_spec.rb @@ -4,11 +4,11 @@ describe "Struct#hash" do - it "returns the same fixnum for structs with the same content" do + it "returns the same integer for structs with the same content" do [StructClasses::Ruby.new("1.8.6", "PPC"), StructClasses::Car.new("Hugo", "Foo", "1972")].each do |stc| stc.hash.should == stc.dup.hash - stc.hash.should be_kind_of(Fixnum) + stc.hash.should be_kind_of(Integer) end end @@ -19,6 +19,20 @@ car.hash.should == similar_car.hash end + it "returns different hashes for structs with different values" do + s1 = StructClasses::Ruby.new('2.7.0', 'linux') + s2 = StructClasses::Ruby.new('2.7.0', 'macos') + s1.hash.should_not == s2.hash + end + + it "returns different hashes for structs with different values when using keyword_init: true" do + key = :"1 non symbol member" + struct_class = Struct.new(key, keyword_init: true) + t1 = struct_class.new(key => 1) + t2 = struct_class.new(key => 2) + t1.hash.should_not == t2.hash + end + it "allows for overriding methods in an included module" do mod = Module.new do def hash @@ -42,5 +56,9 @@ def hash # See the Struct#eql? specs end + it "returns different hashes for different struct classes" do + Struct.new(:x).new(1).hash.should != Struct.new(:y).new(1).hash + end + it_behaves_like :struct_accessor, :hash end diff --git a/ruby/spec/ruby/core/struct/new_spec.rb b/ruby/spec/ruby/core/struct/new_spec.rb index 564c49af0..cbbec829d 100644 --- a/ruby/spec/ruby/core/struct/new_spec.rb +++ b/ruby/spec/ruby/core/struct/new_spec.rb @@ -15,7 +15,7 @@ second = nil -> { second = Struct.new('Person', :hair, :sex) - }.should complain(/redefining constant/) + }.should complain(/constant/) second.should == Struct::Person first.members.should_not == second.members @@ -62,16 +62,8 @@ def obj.to_str() "Foo" end -> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError) end - ruby_version_is ""..."2.5" do - it "raises a TypeError if an argument is a Hash" do - -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError) - end - end - - ruby_version_is "2.5" do - it "raises a ArgumentError if passed a Hash with an unknown key" do - -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError) - end + it "raises a ArgumentError if passed a Hash with an unknown key" do + -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError) end it "raises ArgumentError when there is a duplicate member" do @@ -135,83 +127,96 @@ def platform -> { StructClasses::Ruby.new('2.0', 'i686', true) }.should raise_error(ArgumentError) end - it "passes a hash as a normal argument" do - type = Struct.new(:args) + ruby_version_is ''...'3.1' do + it "passes a hash as a normal argument" do + type = Struct.new(:args) - obj = type.new(keyword: :arg) - obj2 = type.new(*[{keyword: :arg}]) + obj = suppress_warning {type.new(keyword: :arg)} + obj2 = type.new(*[{keyword: :arg}]) - obj.should == obj2 - obj.args.should == {keyword: :arg} - obj2.args.should == {keyword: :arg} + obj.should == obj2 + obj.args.should == {keyword: :arg} + obj2.args.should == {keyword: :arg} + end end - end - ruby_version_is "2.5" do - context "keyword_init: true option" do - before :all do - @struct_with_kwa = Struct.new(:name, :legs, keyword_init: true) + ruby_version_is '3.2' do + it "accepts keyword arguments to initialize" do + type = Struct.new(:args) + + obj = type.new(args: 42) + obj2 = type.new(42) + + obj.should == obj2 + obj.args.should == 42 + obj2.args.should == 42 end + end + end + + context "keyword_init: true option" do + before :all do + @struct_with_kwa = Struct.new(:name, :legs, keyword_init: true) + end + + it "creates a class that accepts keyword arguments to initialize" do + obj = @struct_with_kwa.new(name: "elefant", legs: 4) + obj.name.should == "elefant" + obj.legs.should == 4 + end + + it "raises when there is a duplicate member" do + -> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo") + end - it "creates a class that accepts keyword arguments to initialize" do - obj = @struct_with_kwa.new(name: "elefant", legs: 4) + describe "new class instantiation" do + it "accepts arguments as hash as well" do + obj = @struct_with_kwa.new({name: "elefant", legs: 4}) obj.name.should == "elefant" obj.legs.should == 4 end - it "raises when there is a duplicate member" do - -> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo") + it "allows missing arguments" do + obj = @struct_with_kwa.new(name: "elefant") + obj.name.should == "elefant" + obj.legs.should be_nil end - describe "new class instantiation" do - it "accepts arguments as hash as well" do - obj = @struct_with_kwa.new({name: "elefant", legs: 4}) - obj.name.should == "elefant" - obj.legs.should == 4 - end - - it "allows missing arguments" do - obj = @struct_with_kwa.new(name: "elefant") - obj.name.should == "elefant" - obj.legs.should be_nil - end - - it "allows no arguments" do - obj = @struct_with_kwa.new - obj.name.should be_nil - obj.legs.should be_nil - end + it "allows no arguments" do + obj = @struct_with_kwa.new + obj.name.should be_nil + obj.legs.should be_nil + end - it "raises ArgumentError when passed not declared keyword argument" do - -> { - @struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar") - }.should raise_error(ArgumentError, /unknown keywords: foo/) - end + it "raises ArgumentError when passed not declared keyword argument" do + -> { + @struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar") + }.should raise_error(ArgumentError, /unknown keywords: foo/) + end - it "raises ArgumentError when passed a list of arguments" do - -> { - @struct_with_kwa.new("elefant", 4) - }.should raise_error(ArgumentError, /wrong number of arguments/) - end + it "raises ArgumentError when passed a list of arguments" do + -> { + @struct_with_kwa.new("elefant", 4) + }.should raise_error(ArgumentError, /wrong number of arguments/) + end - it "raises ArgumentError when passed a single non-hash argument" do - -> { - @struct_with_kwa.new("elefant") - }.should raise_error(ArgumentError, /wrong number of arguments/) - end + it "raises ArgumentError when passed a single non-hash argument" do + -> { + @struct_with_kwa.new("elefant") + }.should raise_error(ArgumentError, /wrong number of arguments/) end end + end - context "keyword_init: false option" do - before :all do - @struct_without_kwa = Struct.new(:name, :legs, keyword_init: false) - end + context "keyword_init: false option" do + before :all do + @struct_without_kwa = Struct.new(:name, :legs, keyword_init: false) + end - it "behaves like it does without :keyword_init option" do - obj = @struct_without_kwa.new("elefant", 4) - obj.name.should == "elefant" - obj.legs.should == 4 - end + it "behaves like it does without :keyword_init option" do + obj = @struct_without_kwa.new("elefant", 4) + obj.name.should == "elefant" + obj.legs.should == 4 end end end diff --git a/ruby/spec/ruby/core/struct/to_h_spec.rb b/ruby/spec/ruby/core/struct/to_h_spec.rb index b5f4e4070..bfb0af07b 100644 --- a/ruby/spec/ruby/core/struct/to_h_spec.rb +++ b/ruby/spec/ruby/core/struct/to_h_spec.rb @@ -13,46 +13,44 @@ car.make.should == 'Ford' end - ruby_version_is "2.6" do - context "with block" do - it "converts [key, value] pairs returned by the block to a hash" do - car = StructClasses::Car.new('Ford', 'Ranger') - - h = car.to_h { |k, v| [k.to_s, "#{v}".downcase] } - h.should == { "make" => "ford", "model" => "ranger", "year" => "" } - end - - it "raises ArgumentError if block returns longer or shorter array" do - -> do - StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) - - -> do - StructClasses::Car.new.to_h { |k, v| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end - - it "raises TypeError if block returns something other than Array" do - -> do - StructClasses::Car.new.to_h { |k, v| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end - - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) - - StructClasses::Car.new.to_h { |k| x }.should == { :b => 'b' } - end - - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) - - -> do - StructClasses::Car.new.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end + context "with block" do + it "converts [key, value] pairs returned by the block to a hash" do + car = StructClasses::Car.new('Ford', 'Ranger') + + h = car.to_h { |k, v| [k.to_s, "#{v}".downcase] } + h.should == { "make" => "ford", "model" => "ranger", "year" => "" } + end + + it "raises ArgumentError if block returns longer or shorter array" do + -> do + StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) + + -> do + StructClasses::Car.new.to_h { |k, v| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end + + it "raises TypeError if block returns something other than Array" do + -> do + StructClasses::Car.new.to_h { |k, v| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end + + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) + + StructClasses::Car.new.to_h { |k| x }.should == { :b => 'b' } + end + + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) + + -> do + StructClasses::Car.new.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) end end end diff --git a/ruby/spec/ruby/core/struct/values_at_spec.rb b/ruby/spec/ruby/core/struct/values_at_spec.rb index 7e517cdb4..e7d287cba 100644 --- a/ruby/spec/ruby/core/struct/values_at_spec.rb +++ b/ruby/spec/ruby/core/struct/values_at_spec.rb @@ -4,9 +4,9 @@ describe "Struct#values_at" do it "returns an array of values" do clazz = Struct.new(:name, :director, :year) - movie = clazz.new('Sympathy for Mr. Vengence', 'Chan-wook Park', 2002) - movie.values_at(0, 1).should == ['Sympathy for Mr. Vengence', 'Chan-wook Park'] - movie.values_at(0..2).should == ['Sympathy for Mr. Vengence', 'Chan-wook Park', 2002] + movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002) + movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park'] + movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002] end it "fails when passed unsupported types" do diff --git a/ruby/spec/ruby/core/symbol/all_symbols_spec.rb b/ruby/spec/ruby/core/symbol/all_symbols_spec.rb index ef2b4f85e..1e2180909 100644 --- a/ruby/spec/ruby/core/symbol/all_symbols_spec.rb +++ b/ruby/spec/ruby/core/symbol/all_symbols_spec.rb @@ -1,14 +1,19 @@ require_relative '../../spec_helper' describe "Symbol.all_symbols" do - it "returns an array containing all the Symbols in the symbol table" do + it "returns an array of Symbols" do all_symbols = Symbol.all_symbols all_symbols.should be_an_instance_of(Array) - all_symbols.all? { |s| s.is_a?(Symbol) ? true : (p s; false) }.should == true + all_symbols.each { |s| s.should be_an_instance_of(Symbol) } end - it "returns an Array containing Symbols that have been created" do + it "includes symbols that are strongly referenced" do symbol = "symbol_specs_#{rand(5_000_000)}".to_sym Symbol.all_symbols.should include(symbol) end + + it "includes symbols that are referenced in source code but not yet executed" do + Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should be_true + :symbol_specs_referenced_in_source_code + end end diff --git a/ruby/spec/ruby/core/symbol/casecmp_spec.rb b/ruby/spec/ruby/core/symbol/casecmp_spec.rb index b485101d6..80ea51e91 100644 --- a/ruby/spec/ruby/core/symbol/casecmp_spec.rb +++ b/ruby/spec/ruby/core/symbol/casecmp_spec.rb @@ -63,7 +63,7 @@ :abc.casecmp("abc").should be_nil end - it "returns nil if other is a Fixnum" do + it "returns nil if other is an Integer" do :abc.casecmp(1).should be_nil end diff --git a/ruby/spec/ruby/core/symbol/comparison_spec.rb b/ruby/spec/ruby/core/symbol/comparison_spec.rb index 173a7da62..613177be0 100644 --- a/ruby/spec/ruby/core/symbol/comparison_spec.rb +++ b/ruby/spec/ruby/core/symbol/comparison_spec.rb @@ -40,7 +40,7 @@ (:abc <=> "abc").should be_nil end - it "returns nil if other is a Fixnum" do + it "returns nil if other is an Integer" do (:abc <=> 1).should be_nil end diff --git a/ruby/spec/ruby/core/symbol/end_with_spec.rb b/ruby/spec/ruby/core/symbol/end_with_spec.rb new file mode 100644 index 000000000..77dc4caf7 --- /dev/null +++ b/ruby/spec/ruby/core/symbol/end_with_spec.rb @@ -0,0 +1,10 @@ +# -*- encoding: utf-8 -*- + +require_relative '../../spec_helper' +require_relative '../../shared/string/end_with' + +ruby_version_is "2.7" do + describe "Symbol#end_with?" do + it_behaves_like :end_with, :to_sym + end +end diff --git a/ruby/spec/ruby/core/symbol/match_spec.rb b/ruby/spec/ruby/core/symbol/match_spec.rb index d37155537..41e058f97 100644 --- a/ruby/spec/ruby/core/symbol/match_spec.rb +++ b/ruby/spec/ruby/core/symbol/match_spec.rb @@ -34,6 +34,23 @@ :a.match(/(.)/)[0].should == 'a' $1.should == "a" end + + describe "when passed a block" do + it "yields the MatchData" do + :abc.match(/./) {|m| ScratchPad.record m } + ScratchPad.recorded.should be_kind_of(MatchData) + end + + it "returns the block result" do + :abc.match(/./) { :result }.should == :result + end + + it "does not yield if there is no match" do + ScratchPad.record [] + :b.match(/a/) {|m| ScratchPad << m } + ScratchPad.recorded.should == [] + end + end end describe "Symbol#match?" do diff --git a/ruby/spec/ruby/core/symbol/name_spec.rb b/ruby/spec/ruby/core/symbol/name_spec.rb new file mode 100644 index 000000000..15b9aa75e --- /dev/null +++ b/ruby/spec/ruby/core/symbol/name_spec.rb @@ -0,0 +1,19 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.0" do + describe "Symbol#name" do + it "returns string" do + :ruby.name.should == "ruby" + :ルビー.name.should == "ルビー" + end + + it "returns same string instance" do + :"ruby_3".name.should.equal?(:ruby_3.name) + :"ruby_#{1+2}".name.should.equal?(:ruby_3.name) + end + + it "returns frozen string" do + :symbol.name.should.frozen? + end + end +end diff --git a/ruby/spec/ruby/core/symbol/start_with_spec.rb b/ruby/spec/ruby/core/symbol/start_with_spec.rb new file mode 100644 index 000000000..f54b3e499 --- /dev/null +++ b/ruby/spec/ruby/core/symbol/start_with_spec.rb @@ -0,0 +1,10 @@ +# -*- encoding: utf-8 -*- +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative '../../shared/string/start_with' + +ruby_version_is "2.7" do + describe "Symbol#start_with?" do + it_behaves_like :start_with, :to_sym + end +end diff --git a/ruby/spec/ruby/core/symbol/to_proc_spec.rb b/ruby/spec/ruby/core/symbol/to_proc_spec.rb index 60e33d7cb..47f2a939a 100644 --- a/ruby/spec/ruby/core/symbol/to_proc_spec.rb +++ b/ruby/spec/ruby/core/symbol/to_proc_spec.rb @@ -12,18 +12,44 @@ :to_s.to_proc.call(obj).should == "Received #to_s" end - it "produces a proc with arity -1" do - pr = :to_s.to_proc - pr.arity.should == -1 + ruby_version_is ""..."3.0" do + it "returns a Proc with #lambda? false" do + pr = :to_s.to_proc + pr.should_not.lambda? + end + + it "produces a Proc with arity -1" do + pr = :to_s.to_proc + pr.arity.should == -1 + end + + it "produces a Proc that always returns [[:rest]] for #parameters" do + pr = :to_s.to_proc + pr.parameters.should == [[:rest]] + end end - it "raises an ArgumentError when calling #call on the Proc without receiver" do - -> { :object_id.to_proc.call }.should raise_error(ArgumentError, "no receiver given") + ruby_version_is "3.0" do + it "returns a Proc with #lambda? true" do + pr = :to_s.to_proc + pr.should.lambda? + end + + it "produces a Proc with arity -2" do + pr = :to_s.to_proc + pr.arity.should == -2 + end + + it "produces a Proc that always returns [[:req], [:rest]] for #parameters" do + pr = :to_s.to_proc + pr.parameters.should == [[:req], [:rest]] + end end - it "produces a proc that always returns [[:rest]] for #parameters" do - pr = :to_s.to_proc - pr.parameters.should == [[:rest]] + it "raises an ArgumentError when calling #call on the Proc without receiver" do + -> { + :object_id.to_proc.call + }.should raise_error(ArgumentError, /no receiver given|wrong number of arguments \(given 0, expected 1\+\)/) end it "passes along the block passed to Proc#call" do @@ -38,4 +64,9 @@ def to_proc end klass.new.to_proc.should == :value end + + it "produces a proc with source location nil" do + pr = :to_s.to_proc + pr.source_location.should == nil + end end diff --git a/ruby/spec/ruby/core/systemexit/success_spec.rb b/ruby/spec/ruby/core/systemexit/success_spec.rb index 6d36509c8..ba2fd22de 100644 --- a/ruby/spec/ruby/core/systemexit/success_spec.rb +++ b/ruby/spec/ruby/core/systemexit/success_spec.rb @@ -3,11 +3,11 @@ describe "SystemExit#success?" do it "returns true when the status is 0" do s = SystemExit.new 0 - s.success?.should == true + s.should.success? end it "returns false when the status is not 0" do s = SystemExit.new 1 - s.success?.should == false + s.should_not.success? end end diff --git a/ruby/spec/ruby/core/thread/alive_spec.rb b/ruby/spec/ruby/core/thread/alive_spec.rb index d4ba149d8..c2f5f5371 100644 --- a/ruby/spec/ruby/core/thread/alive_spec.rb +++ b/ruby/spec/ruby/core/thread/alive_spec.rb @@ -3,39 +3,39 @@ describe "Thread#alive?" do it "can check it's own status" do - ThreadSpecs.status_of_current_thread.alive?.should == true + ThreadSpecs.status_of_current_thread.should.alive? end it "describes a running thread" do - ThreadSpecs.status_of_running_thread.alive?.should == true + ThreadSpecs.status_of_running_thread.should.alive? end it "describes a sleeping thread" do - ThreadSpecs.status_of_sleeping_thread.alive?.should == true + ThreadSpecs.status_of_sleeping_thread.should.alive? end it "describes a blocked thread" do - ThreadSpecs.status_of_blocked_thread.alive?.should == true + ThreadSpecs.status_of_blocked_thread.should.alive? end it "describes a completed thread" do - ThreadSpecs.status_of_completed_thread.alive?.should == false + ThreadSpecs.status_of_completed_thread.should_not.alive? end it "describes a killed thread" do - ThreadSpecs.status_of_killed_thread.alive?.should == false + ThreadSpecs.status_of_killed_thread.should_not.alive? end it "describes a thread with an uncaught exception" do - ThreadSpecs.status_of_thread_with_uncaught_exception.alive?.should == false + ThreadSpecs.status_of_thread_with_uncaught_exception.should_not.alive? end it "describes a dying running thread" do - ThreadSpecs.status_of_dying_running_thread.alive?.should == true + ThreadSpecs.status_of_dying_running_thread.should.alive? end it "describes a dying sleeping thread" do - ThreadSpecs.status_of_dying_sleeping_thread.alive?.should == true + ThreadSpecs.status_of_dying_sleeping_thread.should.alive? end it "returns true for a killed but still running thread" do @@ -51,7 +51,7 @@ ThreadSpecs.spin_until_sleeping(t) t.kill - t.alive?.should == true + t.should.alive? exit = true t.join end diff --git a/ruby/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb b/ruby/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb index d38659c25..4136f0934 100644 --- a/ruby/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb @@ -10,11 +10,28 @@ @frame.absolute_path.should == File.realpath(__FILE__) end + it 'returns an absolute path when using a relative main script path' do + script = fixture(__FILE__, 'absolute_path_main.rb') + Dir.chdir(File.dirname(script)) do + ruby_exe('absolute_path_main.rb').should == "absolute_path_main.rb\n#{script}\n" + end + end + context "when used in eval with a given filename" do - it "returns filename" do - code = "caller_locations(0)[0].absolute_path" - eval(code, nil, "foo.rb").should == "foo.rb" - eval(code, nil, "foo/bar.rb").should == "foo/bar.rb" + code = "caller_locations(0)[0].absolute_path" + + ruby_version_is ""..."3.1" do + it "returns filename with absolute_path" do + eval(code, nil, "foo.rb").should == "foo.rb" + eval(code, nil, "foo/bar.rb").should == "foo/bar.rb" + end + end + + ruby_version_is "3.1" do + it "returns nil with absolute_path" do + eval(code, nil, "foo.rb").should == nil + eval(code, nil, "foo/bar.rb").should == nil + end end end @@ -29,33 +46,48 @@ end end - platform_is_not :windows do - before :each do - @file = fixture(__FILE__, "absolute_path.rb") - @symlink = tmp("symlink.rb") - File.symlink(@file, @symlink) - ScratchPad.record [] + context "when used in a core method" do + it "returns nil" do + location = nil + tap { location = caller_locations(1, 1)[0] } + location.label.should == "tap" + if location.path.start_with?(" { rm_r(@symlink) } - load @symlink - ScratchPad.recorded.should == [@symlink, realpath] + ScratchPad << -> { rm_r(@symlink) } + load @symlink + ScratchPad.recorded.should == [@symlink, realpath] + end end end end diff --git a/ruby/spec/ruby/core/thread/backtrace/location/base_label_spec.rb b/ruby/spec/ruby/core/thread/backtrace/location/base_label_spec.rb index 139a68e2c..739f62f42 100644 --- a/ruby/spec/ruby/core/thread/backtrace/location/base_label_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace/location/base_label_spec.rb @@ -19,4 +19,31 @@ @frame.base_label.should == 'block_location' end end + + it "is for a module body" do + module ThreadBacktraceLocationSpecs + module ModuleLabel + ScratchPad.record caller_locations(0, 1)[0].base_label + end + end + ScratchPad.recorded.should == '' + end + + it "is for a class body" do + module ThreadBacktraceLocationSpecs + class ClassLabel + ScratchPad.record caller_locations(0, 1)[0].base_label + end + end + ScratchPad.recorded.should == '' + end + + it "is 'singleton class' for a singleton class body" do + module ThreadBacktraceLocationSpecs + class << Object.new + ScratchPad.record caller_locations(0, 1)[0].base_label + end + end + ScratchPad.recorded.should =~ /\A(singleton class|)\z/ + end end diff --git a/ruby/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb b/ruby/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb new file mode 100644 index 000000000..d2b23393d --- /dev/null +++ b/ruby/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb @@ -0,0 +1,2 @@ +puts __FILE__ +puts caller_locations(0)[0].absolute_path diff --git a/ruby/spec/ruby/core/thread/backtrace/location/fixtures/path.rb b/ruby/spec/ruby/core/thread/backtrace/location/fixtures/path.rb new file mode 100644 index 000000000..fba34cb0b --- /dev/null +++ b/ruby/spec/ruby/core/thread/backtrace/location/fixtures/path.rb @@ -0,0 +1,2 @@ +ScratchPad << __FILE__ +ScratchPad << caller_locations(0)[0].path diff --git a/ruby/spec/ruby/core/thread/backtrace/location/lineno_spec.rb b/ruby/spec/ruby/core/thread/backtrace/location/lineno_spec.rb index dc93d32d7..d14cf1751 100644 --- a/ruby/spec/ruby/core/thread/backtrace/location/lineno_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace/location/lineno_spec.rb @@ -10,4 +10,14 @@ it 'returns the absolute path of the call frame' do @frame.lineno.should == @line end + + it 'should be the same line number as in #to_s, including for core methods' do + # Get the caller_locations from a call made into a core library method + locations = [:non_empty].map { caller_locations }[0] + + locations.each do |location| + line_number = location.to_s[/:(\d+):/, 1] + location.lineno.should == Integer(line_number) + end + end end diff --git a/ruby/spec/ruby/core/thread/backtrace/location/path_spec.rb b/ruby/spec/ruby/core/thread/backtrace/location/path_spec.rb index b1a343974..7863c055d 100644 --- a/ruby/spec/ruby/core/thread/backtrace/location/path_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace/location/path_spec.rb @@ -86,4 +86,39 @@ end end end + + it 'should be the same path as in #to_s, including for core methods' do + # Get the caller_locations from a call made into a core library method + locations = [:non_empty].map { caller_locations }[0] + + locations.each do |location| + filename = location.to_s[/^(.+):\d+:/, 1] + path = location.path + + path.should == filename + end + end + + context "canonicalization" do + platform_is_not :windows do + before :each do + @file = fixture(__FILE__, "path.rb") + @symlink = tmp("symlink.rb") + File.symlink(@file, @symlink) + ScratchPad.record [] + end + + after :each do + rm_r @symlink + end + + it "returns a non-canonical path with symlinks, the same as __FILE__" do + realpath = File.realpath(@symlink) + realpath.should_not == @symlink + + load @symlink + ScratchPad.recorded.should == [@symlink, @symlink] + end + end + end end diff --git a/ruby/spec/ruby/core/thread/backtrace_locations_spec.rb b/ruby/spec/ruby/core/thread/backtrace_locations_spec.rb index 66947f8ea..237941c21 100644 --- a/ruby/spec/ruby/core/thread/backtrace_locations_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace_locations_spec.rb @@ -19,6 +19,54 @@ locations.each { |loc| loc.should be_an_instance_of(Thread::Backtrace::Location) } end + it "can be called with a number of locations to omit" do + locations1 = Thread.current.backtrace_locations + locations2 = Thread.current.backtrace_locations(2) + locations2.length.should == locations1[2..-1].length + locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s) + end + + it "can be called with a maximum number of locations to return as second parameter" do + locations1 = Thread.current.backtrace_locations + locations2 = Thread.current.backtrace_locations(2, 3) + locations2.map(&:to_s).should == locations1[2..4].map(&:to_s) + end + + it "can be called with a range" do + locations1 = Thread.current.backtrace_locations + locations2 = Thread.current.backtrace_locations(2..4) + locations2.map(&:to_s).should == locations1[2..4].map(&:to_s) + end + + it "can be called with a range whose end is negative" do + Thread.current.backtrace_locations(2..-1).map(&:to_s).should == Thread.current.backtrace_locations[2..-1].map(&:to_s) + Thread.current.backtrace_locations(2..-2).map(&:to_s).should == Thread.current.backtrace_locations[2..-2].map(&:to_s) + end + + it "can be called with an endless range" do + locations1 = Thread.current.backtrace_locations(0) + locations2 = Thread.current.backtrace_locations(eval("(2..)")) + locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s) + end + + ruby_version_is "2.7" do + it "can be called with an beginless range" do + locations1 = Thread.current.backtrace_locations(0) + locations2 = Thread.current.backtrace_locations(eval("(..5)")) + locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(..5)")].map(&:to_s)[eval("(2..)")] + end + end + + it "returns nil if omitting more locations than available" do + Thread.current.backtrace_locations(100).should == nil + Thread.current.backtrace_locations(100..-1).should == nil + end + + it "returns [] if omitting exactly the number of locations available" do + omit = Thread.current.backtrace_locations.length + Thread.current.backtrace_locations(omit).should == [] + end + it "without argument is the same as showing all locations with 0..-1" do Thread.current.backtrace_locations.map(&:to_s).should == Thread.current.backtrace_locations(0..-1).map(&:to_s) end diff --git a/ruby/spec/ruby/core/thread/backtrace_spec.rb b/ruby/spec/ruby/core/thread/backtrace_spec.rb index 84ed574d5..9001b1b7e 100644 --- a/ruby/spec/ruby/core/thread/backtrace_spec.rb +++ b/ruby/spec/ruby/core/thread/backtrace_spec.rb @@ -32,4 +32,38 @@ t.join backtrace.should be_kind_of(Array) end + + it "can be called with a number of locations to omit" do + locations1 = Thread.current.backtrace + locations2 = Thread.current.backtrace(2) + locations1[2..-1].length.should == locations2.length + locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s) + end + + it "can be called with a maximum number of locations to return as second parameter" do + locations1 = Thread.current.backtrace + locations2 = Thread.current.backtrace(2, 3) + locations1[2..4].map(&:to_s).should == locations2.map(&:to_s) + end + + it "can be called with a range" do + locations1 = Thread.current.backtrace + locations2 = Thread.current.backtrace(2..4) + locations1[2..4].map(&:to_s).should == locations2.map(&:to_s) + end + + it "can be called with a range whose end is negative" do + Thread.current.backtrace(2..-1).should == Thread.current.backtrace[2..-1] + Thread.current.backtrace(2..-2).should == Thread.current.backtrace[2..-2] + end + + it "returns nil if omitting more locations than available" do + Thread.current.backtrace(100).should == nil + Thread.current.backtrace(100..-1).should == nil + end + + it "returns [] if omitting exactly the number of locations available" do + omit = Thread.current.backtrace.length + Thread.current.backtrace(omit).should == [] + end end diff --git a/ruby/spec/ruby/core/thread/element_set_spec.rb b/ruby/spec/ruby/core/thread/element_set_spec.rb index d974b5e1c..c7498f7ac 100644 --- a/ruby/spec/ruby/core/thread/element_set_spec.rb +++ b/ruby/spec/ruby/core/thread/element_set_spec.rb @@ -6,13 +6,13 @@ Thread.current[:value] = nil end - it "raises a #{frozen_error_class} if the thread is frozen" do + it "raises a FrozenError if the thread is frozen" do Thread.new do th = Thread.current th.freeze -> { th[:foo] = "bar" - }.should raise_error(frozen_error_class, /frozen/) + }.should raise_error(FrozenError, /frozen/) end.join end diff --git a/ruby/spec/ruby/core/thread/exclusive_spec.rb b/ruby/spec/ruby/core/thread/exclusive_spec.rb index ca8f105da..37c4b19d1 100644 --- a/ruby/spec/ruby/core/thread/exclusive_spec.rb +++ b/ruby/spec/ruby/core/thread/exclusive_spec.rb @@ -1,47 +1,49 @@ require_relative '../../spec_helper' -describe "Thread.exclusive" do - before :each do - ScratchPad.clear - $VERBOSE, @verbose = nil, $VERBOSE - end +ruby_version_is ''...'3.0' do + describe "Thread.exclusive" do + before :each do + ScratchPad.clear + $VERBOSE, @verbose = nil, $VERBOSE + end - after :each do - $VERBOSE = @verbose - end + after :each do + $VERBOSE = @verbose + end - it "yields to the block" do - Thread.exclusive { ScratchPad.record true } - ScratchPad.recorded.should == true - end + it "yields to the block" do + Thread.exclusive { ScratchPad.record true } + ScratchPad.recorded.should == true + end - it "returns the result of yielding" do - Thread.exclusive { :result }.should == :result - end + it "returns the result of yielding" do + Thread.exclusive { :result }.should == :result + end - it "blocks the caller if another thread is also in an exclusive block" do - m = Mutex.new - q1 = Queue.new - q2 = Queue.new + it "blocks the caller if another thread is also in an exclusive block" do + m = Mutex.new + q1 = Queue.new + q2 = Queue.new - t = Thread.new { - Thread.exclusive { - q1.push :ready - q2.pop + t = Thread.new { + Thread.exclusive { + q1.push :ready + q2.pop + } } - } - q1.pop.should == :ready + q1.pop.should == :ready - -> { Thread.exclusive { } }.should block_caller + -> { Thread.exclusive { } }.should block_caller - q2.push :done - t.join - end + q2.push :done + t.join + end - it "is not recursive" do - Thread.exclusive do - -> { Thread.exclusive { } }.should raise_error(ThreadError) + it "is not recursive" do + Thread.exclusive do + -> { Thread.exclusive { } }.should raise_error(ThreadError) + end end end end diff --git a/ruby/spec/ruby/core/thread/fetch_spec.rb b/ruby/spec/ruby/core/thread/fetch_spec.rb index d71c93888..6b37d4cfc 100644 --- a/ruby/spec/ruby/core/thread/fetch_spec.rb +++ b/ruby/spec/ruby/core/thread/fetch_spec.rb @@ -1,38 +1,36 @@ require_relative '../../spec_helper' -ruby_version_is '2.5' do - describe 'Thread#fetch' do - describe 'with 2 arguments' do - it 'returns the value of the fiber-local variable if value has been assigned' do - th = Thread.new { Thread.current[:cat] = 'meow' } - th.join - th.fetch(:cat, true).should == 'meow' - end - - it "returns the default value if fiber-local variable hasn't been assigned" do - th = Thread.new {} - th.join - th.fetch(:cat, true).should == true - end +describe 'Thread#fetch' do + describe 'with 2 arguments' do + it 'returns the value of the fiber-local variable if value has been assigned' do + th = Thread.new { Thread.current[:cat] = 'meow' } + th.join + th.fetch(:cat, true).should == 'meow' end - describe 'with 1 argument' do - it 'raises a KeyError when the Thread does not have a fiber-local variable of the same name' do - th = Thread.new {} - th.join - -> { th.fetch(:cat) }.should raise_error(KeyError) - end + it "returns the default value if fiber-local variable hasn't been assigned" do + th = Thread.new {} + th.join + th.fetch(:cat, true).should == true + end + end - it 'returns the value of the fiber-local variable if value has been assigned' do - th = Thread.new { Thread.current[:cat] = 'meow' } - th.join - th.fetch(:cat).should == 'meow' - end + describe 'with 1 argument' do + it 'raises a KeyError when the Thread does not have a fiber-local variable of the same name' do + th = Thread.new {} + th.join + -> { th.fetch(:cat) }.should raise_error(KeyError) end - it 'raises an ArgumentError when not passed one or two arguments' do - -> { Thread.current.fetch() }.should raise_error(ArgumentError) - -> { Thread.current.fetch(1, 2, 3) }.should raise_error(ArgumentError) + it 'returns the value of the fiber-local variable if value has been assigned' do + th = Thread.new { Thread.current[:cat] = 'meow' } + th.join + th.fetch(:cat).should == 'meow' end end + + it 'raises an ArgumentError when not passed one or two arguments' do + -> { Thread.current.fetch() }.should raise_error(ArgumentError) + -> { Thread.current.fetch(1, 2, 3) }.should raise_error(ArgumentError) + end end diff --git a/ruby/spec/ruby/core/thread/handle_interrupt_spec.rb b/ruby/spec/ruby/core/thread/handle_interrupt_spec.rb new file mode 100644 index 000000000..ea7e81cb9 --- /dev/null +++ b/ruby/spec/ruby/core/thread/handle_interrupt_spec.rb @@ -0,0 +1,125 @@ +require_relative '../../spec_helper' + +describe "Thread.handle_interrupt" do + def make_handle_interrupt_thread(interrupt_config, blocking = true) + interrupt_class = Class.new(RuntimeError) + + ScratchPad.record [] + + in_handle_interrupt = Queue.new + can_continue = Queue.new + + thread = Thread.new do + begin + Thread.handle_interrupt(interrupt_config) do + begin + in_handle_interrupt << true + if blocking + Thread.pass # Make it clearer the other thread needs to wait for this one to be in #pop + can_continue.pop + else + begin + can_continue.pop(true) + rescue ThreadError + Thread.pass + retry + end + end + rescue interrupt_class + ScratchPad << :interrupted + end + end + rescue interrupt_class + ScratchPad << :deferred + end + end + + in_handle_interrupt.pop + if blocking + # Ensure the thread is inside Thread#pop, as if thread.raise is done before it would be deferred + Thread.pass until thread.stop? + end + thread.raise interrupt_class, "interrupt" + can_continue << true + thread.join + + ScratchPad.recorded + end + + before :each do + Thread.pending_interrupt?.should == false # sanity check + end + + it "with :never defers interrupts until exiting the handle_interrupt block" do + make_handle_interrupt_thread(RuntimeError => :never).should == [:deferred] + end + + it "with :on_blocking defers interrupts until the next blocking call" do + make_handle_interrupt_thread(RuntimeError => :on_blocking).should == [:interrupted] + make_handle_interrupt_thread({ RuntimeError => :on_blocking }, false).should == [:deferred] + end + + it "with :immediate handles interrupts immediately" do + make_handle_interrupt_thread(RuntimeError => :immediate).should == [:interrupted] + end + + it "with :immediate immediately runs pending interrupts, before the block" do + Thread.handle_interrupt(RuntimeError => :never) do + current = Thread.current + Thread.new { + current.raise "interrupt immediate" + }.join + + Thread.pending_interrupt?.should == true + -> { + Thread.handle_interrupt(RuntimeError => :immediate) { + flunk "not reached" + } + }.should raise_error(RuntimeError, "interrupt immediate") + Thread.pending_interrupt?.should == false + end + end + + it "also works with suspended Fibers and does not duplicate interrupts" do + fiber = Fiber.new { Fiber.yield } + fiber.resume + + Thread.handle_interrupt(RuntimeError => :never) do + current = Thread.current + Thread.new { + current.raise "interrupt with fibers" + }.join + + Thread.pending_interrupt?.should == true + -> { + Thread.handle_interrupt(RuntimeError => :immediate) { + flunk "not reached" + } + }.should raise_error(RuntimeError, "interrupt with fibers") + Thread.pending_interrupt?.should == false + end + + fiber.resume + end + + it "runs pending interrupts at the end of the block, even if there was an exception raised in the block" do + executed = false + -> { + Thread.handle_interrupt(RuntimeError => :never) do + current = Thread.current + Thread.new { + current.raise "interrupt exception" + }.join + + Thread.pending_interrupt?.should == true + executed = true + raise "regular exception" + end + }.should raise_error(RuntimeError, "interrupt exception") + executed.should == true + end + + it "supports multiple pairs in the Hash" do + make_handle_interrupt_thread(ArgumentError => :never, RuntimeError => :never).should == [:deferred] + end +end diff --git a/ruby/spec/ruby/core/thread/ignore_deadlock_spec.rb b/ruby/spec/ruby/core/thread/ignore_deadlock_spec.rb new file mode 100644 index 000000000..53cc2a7f5 --- /dev/null +++ b/ruby/spec/ruby/core/thread/ignore_deadlock_spec.rb @@ -0,0 +1,21 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.0" do + describe "Thread.ignore_deadlock" do + it "returns false by default" do + Thread.ignore_deadlock.should == false + end + end + + describe "Thread.ignore_deadlock=" do + it "changes the value of Thread.ignore_deadlock" do + ignore_deadlock = Thread.ignore_deadlock + Thread.ignore_deadlock = true + begin + Thread.ignore_deadlock.should == true + ensure + Thread.ignore_deadlock = ignore_deadlock + end + end + end +end diff --git a/ruby/spec/ruby/core/thread/join_spec.rb b/ruby/spec/ruby/core/thread/join_spec.rb index f3c5cdc1e..213fe2e50 100644 --- a/ruby/spec/ruby/core/thread/join_spec.rb +++ b/ruby/spec/ruby/core/thread/join_spec.rb @@ -19,6 +19,11 @@ t.join(0).should equal(t) t.join(0.0).should equal(t) t.join(nil).should equal(t) + end + + it "raises TypeError if the argument is not a valid timeout" do + t = Thread.new { } + t.join -> { t.join(:foo) }.should raise_error TypeError -> { t.join("bar") }.should raise_error TypeError end diff --git a/ruby/spec/ruby/core/thread/list_spec.rb b/ruby/spec/ruby/core/thread/list_spec.rb index a0bf83185..3c6f70c13 100644 --- a/ruby/spec/ruby/core/thread/list_spec.rb +++ b/ruby/spec/ruby/core/thread/list_spec.rb @@ -43,11 +43,11 @@ end end - while spawner.alive? + begin Thread.list.each { |th| th.should be_kind_of(Thread) } - end + end while spawner.alive? threads = spawner.value threads.each(&:join) diff --git a/ruby/spec/ruby/core/thread/new_spec.rb b/ruby/spec/ruby/core/thread/new_spec.rb index 3a5714938..47a836201 100644 --- a/ruby/spec/ruby/core/thread/new_spec.rb +++ b/ruby/spec/ruby/core/thread/new_spec.rb @@ -58,13 +58,13 @@ def initialize m2 = Mutex.new t = Thread.new { m1.lock - m1.locked?.should == true + m1.should.locked? m2.lock - m2.locked?.should == true + m2.should.locked? } t.join - m1.locked?.should == false - m2.locked?.should == false + m1.should_not.locked? + m2.should_not.locked? end it "releases Mutexes held by the Thread when the Thread finishes, also with Mutex#synchronize" do @@ -75,9 +75,9 @@ def initialize m.lock } m.lock - m.locked?.should == true + m.should.locked? } t.join - m.locked?.should == false + m.should_not.locked? end end diff --git a/ruby/spec/ruby/core/thread/pending_interrupt_spec.rb b/ruby/spec/ruby/core/thread/pending_interrupt_spec.rb new file mode 100644 index 000000000..cd565d92a --- /dev/null +++ b/ruby/spec/ruby/core/thread/pending_interrupt_spec.rb @@ -0,0 +1,32 @@ +require_relative '../../spec_helper' + +describe "Thread.pending_interrupt?" do + it "returns false if there are no pending interrupts, e.g., outside any Thread.handle_interrupt block" do + Thread.pending_interrupt?.should == false + end + + it "returns true if there are pending interrupts, e.g., Thread#raise inside Thread.handle_interrupt" do + executed = false + -> { + Thread.handle_interrupt(RuntimeError => :never) do + Thread.pending_interrupt?.should == false + + current = Thread.current + Thread.new { + current.raise "interrupt" + }.join + + Thread.pending_interrupt?.should == true + executed = true + end + }.should raise_error(RuntimeError, "interrupt") + executed.should == true + Thread.pending_interrupt?.should == false + end +end + +describe "Thread#pending_interrupt?" do + it "returns whether the given threads has pending interrupts" do + Thread.current.pending_interrupt?.should == false + end +end diff --git a/ruby/spec/ruby/core/thread/raise_spec.rb b/ruby/spec/ruby/core/thread/raise_spec.rb index 88a96d5f4..27de3cc62 100644 --- a/ruby/spec/ruby/core/thread/raise_spec.rb +++ b/ruby/spec/ruby/core/thread/raise_spec.rb @@ -203,6 +203,6 @@ Thread.current.raise end end - -> { t.value }.should raise_error(RuntimeError) + -> { t.value }.should raise_error(RuntimeError, '') end end diff --git a/ruby/spec/ruby/core/thread/report_on_exception_spec.rb b/ruby/spec/ruby/core/thread/report_on_exception_spec.rb index a6042ba75..bf50a167d 100644 --- a/ruby/spec/ruby/core/thread/report_on_exception_spec.rb +++ b/ruby/spec/ruby/core/thread/report_on_exception_spec.rb @@ -1,16 +1,8 @@ require_relative '../../spec_helper' describe "Thread.report_on_exception" do - ruby_version_is "2.4"..."2.5" do - it "defaults to false" do - ruby_exe("p Thread.report_on_exception").should == "false\n" - end - end - - ruby_version_is "2.5" do - it "defaults to true" do - ruby_exe("p Thread.report_on_exception").should == "true\n" - end + it "defaults to true" do + ruby_exe("p Thread.report_on_exception").should == "true\n" end end @@ -33,14 +25,12 @@ end describe "Thread#report_on_exception" do - ruby_version_is "2.5" do - it "returns true for the main Thread" do - Thread.current.report_on_exception.should == true - end + it "returns true for the main Thread" do + Thread.current.report_on_exception.should == true + end - it "returns true for new Threads" do - Thread.new { Thread.current.report_on_exception }.value.should == true - end + it "returns true for new Threads" do + Thread.new { Thread.current.report_on_exception }.value.should == true end it "returns whether the Thread will print a backtrace if it exits with an exception" do diff --git a/ruby/spec/ruby/core/thread/shared/to_s.rb b/ruby/spec/ruby/core/thread/shared/to_s.rb index e47426cf3..45c04af62 100644 --- a/ruby/spec/ruby/core/thread/shared/to_s.rb +++ b/ruby/spec/ruby/core/thread/shared/to_s.rb @@ -4,11 +4,13 @@ sep = ruby_version_is("2.7") ? " " : "@" it "returns a description including file and line number" do - Thread.new { "hello" }.send(@method).should =~ /^#$/ + thread, line = Thread.new { "hello" }, __LINE__ + thread.join + thread.send(@method).should =~ /^#$/ end it "has a binary encoding" do - Thread.new { "hello" }.send(@method).encoding.should == Encoding::BINARY + ThreadSpecs.status_of_current_thread.send(@method).encoding.should == Encoding::BINARY end it "can check it's own status" do diff --git a/ruby/spec/ruby/core/thread/shared/wakeup.rb b/ruby/spec/ruby/core/thread/shared/wakeup.rb index f111edf0f..6f010fea2 100644 --- a/ruby/spec/ruby/core/thread/shared/wakeup.rb +++ b/ruby/spec/ruby/core/thread/shared/wakeup.rb @@ -36,7 +36,7 @@ it "does not result in a deadlock" do t = Thread.new do - 100.times { Thread.stop } + 10.times { Thread.stop } end while t.status @@ -47,6 +47,7 @@ t.status.should == false end Thread.pass + sleep 0.001 end t.status.should == false diff --git a/ruby/spec/ruby/core/thread/stop_spec.rb b/ruby/spec/ruby/core/thread/stop_spec.rb index 33cf8f7b5..084ab46ef 100644 --- a/ruby/spec/ruby/core/thread/stop_spec.rb +++ b/ruby/spec/ruby/core/thread/stop_spec.rb @@ -13,42 +13,42 @@ describe "Thread#stop?" do it "can check it's own status" do - ThreadSpecs.status_of_current_thread.stop?.should == false + ThreadSpecs.status_of_current_thread.should_not.stop? end it "describes a running thread" do - ThreadSpecs.status_of_running_thread.stop?.should == false + ThreadSpecs.status_of_running_thread.should_not.stop? end it "describes a sleeping thread" do - ThreadSpecs.status_of_sleeping_thread.stop?.should == true + ThreadSpecs.status_of_sleeping_thread.should.stop? end it "describes a blocked thread" do - ThreadSpecs.status_of_blocked_thread.stop?.should == true + ThreadSpecs.status_of_blocked_thread.should.stop? end it "describes a completed thread" do - ThreadSpecs.status_of_completed_thread.stop?.should == true + ThreadSpecs.status_of_completed_thread.should.stop? end it "describes a killed thread" do - ThreadSpecs.status_of_killed_thread.stop?.should == true + ThreadSpecs.status_of_killed_thread.should.stop? end it "describes a thread with an uncaught exception" do - ThreadSpecs.status_of_thread_with_uncaught_exception.stop?.should == true + ThreadSpecs.status_of_thread_with_uncaught_exception.should.stop? end it "describes a dying running thread" do - ThreadSpecs.status_of_dying_running_thread.stop?.should == false + ThreadSpecs.status_of_dying_running_thread.should_not.stop? end it "describes a dying sleeping thread" do - ThreadSpecs.status_of_dying_sleeping_thread.stop?.should == true + ThreadSpecs.status_of_dying_sleeping_thread.should.stop? end it "describes a dying thread after sleep" do - ThreadSpecs.status_of_dying_thread_after_sleep.stop?.should == false + ThreadSpecs.status_of_dying_thread_after_sleep.should_not.stop? end end diff --git a/ruby/spec/ruby/core/thread/to_s_spec.rb b/ruby/spec/ruby/core/thread/to_s_spec.rb index 85976177d..cb182a017 100644 --- a/ruby/spec/ruby/core/thread/to_s_spec.rb +++ b/ruby/spec/ruby/core/thread/to_s_spec.rb @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/to_s' -ruby_version_is "2.5" do - describe "Thread#to_s" do - it_behaves_like :thread_to_s, :to_s - end +describe "Thread#to_s" do + it_behaves_like :thread_to_s, :to_s end diff --git a/ruby/spec/ruby/core/time/_dump_spec.rb b/ruby/spec/ruby/core/time/_dump_spec.rb index 6941a1531..4dc1c43cd 100644 --- a/ruby/spec/ruby/core/time/_dump_spec.rb +++ b/ruby/spec/ruby/core/time/_dump_spec.rb @@ -15,11 +15,11 @@ # http://redmine.ruby-lang.org/issues/show/627 it "preserves the GMT flag" do - @t.gmt?.should == true + @t.should.gmt? dump = @t.send(:_dump).unpack("VV").first ((dump >> 30) & 0x1).should == 1 - @local.gmt?.should == false + @local.should_not.gmt? dump = @local.send(:_dump).unpack("VV").first ((dump >> 30) & 0x1).should == 0 end diff --git a/ruby/spec/ruby/core/time/at_spec.rb b/ruby/spec/ruby/core/time/at_spec.rb index 368eeb7fc..2cc46ab8c 100644 --- a/ruby/spec/ruby/core/time/at_spec.rb +++ b/ruby/spec/ruby/core/time/at_spec.rb @@ -14,7 +14,7 @@ end it "returns a non-UTC Time" do - Time.at(1184027924).utc?.should == false + Time.at(1184027924).should_not.utc? end it "returns a subclass instance on a Time subclass" do @@ -38,6 +38,20 @@ Time.at(BigDecimal('1.1')).to_f.should == 1.1 end end + + describe "passed Rational" do + it "returns Time with correct microseconds" do + t = Time.at(Rational(1_486_570_508_539_759, 1_000_000)) + t.usec.should == 539_759 + t.nsec.should == 539_759_000 + end + + it "returns Time with correct nanoseconds" do + t = Time.at(Rational(1_486_570_508_539_759_123, 1_000_000_000)) + t.usec.should == 539_759 + t.nsec.should == 539_759_123 + end + end end describe "passed Time" do @@ -54,12 +68,12 @@ it "returns a UTC time if the argument is UTC" do t = Time.now.getgm - Time.at(t).utc?.should == true + Time.at(t).should.utc? end it "returns a non-UTC time if the argument is non-UTC" do t = Time.now - Time.at(t).utc?.should == false + Time.at(t).should_not.utc? end it "returns a subclass instance" do @@ -92,6 +106,12 @@ o.should_receive(:to_r).and_return(Rational(5, 2)) Time.at(o).should == Time.at(Rational(5, 2)) end + + it "needs for the argument to respond to #to_int too" do + o = mock('rational-but-no-to_int') + o.should_receive(:to_r).and_return(Rational(5, 2)) + -> { Time.at(o) }.should raise_error(TypeError) + end end end @@ -144,111 +164,107 @@ end end - ruby_version_is "2.5" do - describe "passed [Time, Numeric, format]" do - context ":nanosecond format" do - it "treats second argument as nanoseconds" do - Time.at(0, 123456789, :nanosecond).nsec.should == 123456789 - end + describe "passed [Time, Numeric, format]" do + context ":nanosecond format" do + it "treats second argument as nanoseconds" do + Time.at(0, 123456789, :nanosecond).nsec.should == 123456789 end + end - context ":nsec format" do - it "treats second argument as nanoseconds" do - Time.at(0, 123456789, :nsec).nsec.should == 123456789 - end + context ":nsec format" do + it "treats second argument as nanoseconds" do + Time.at(0, 123456789, :nsec).nsec.should == 123456789 end + end - context ":microsecond format" do - it "treats second argument as microseconds" do - Time.at(0, 123456, :microsecond).nsec.should == 123456000 - end + context ":microsecond format" do + it "treats second argument as microseconds" do + Time.at(0, 123456, :microsecond).nsec.should == 123456000 end + end - context ":usec format" do - it "treats second argument as microseconds" do - Time.at(0, 123456, :usec).nsec.should == 123456000 - end + context ":usec format" do + it "treats second argument as microseconds" do + Time.at(0, 123456, :usec).nsec.should == 123456000 end + end - context ":millisecond format" do - it "treats second argument as milliseconds" do - Time.at(0, 123, :millisecond).nsec.should == 123000000 - end + context ":millisecond format" do + it "treats second argument as milliseconds" do + Time.at(0, 123, :millisecond).nsec.should == 123000000 end + end - context "not supported format" do - it "raises ArgumentError" do - -> { Time.at(0, 123456, 2) }.should raise_error(ArgumentError) - -> { Time.at(0, 123456, nil) }.should raise_error(ArgumentError) - -> { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError) - end - - it "does not try to convert format to Symbol with #to_sym" do - format = "usec" - format.should_not_receive(:to_sym) - -> { Time.at(0, 123456, format) }.should raise_error(ArgumentError) - end + context "not supported format" do + it "raises ArgumentError" do + -> { Time.at(0, 123456, 2) }.should raise_error(ArgumentError) + -> { Time.at(0, 123456, nil) }.should raise_error(ArgumentError) + -> { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError) end - it "supports Float second argument" do - Time.at(0, 123456789.500, :nanosecond).nsec.should == 123456789 - Time.at(0, 123456789.500, :nsec).nsec.should == 123456789 - Time.at(0, 123456.500, :microsecond).nsec.should == 123456500 - Time.at(0, 123456.500, :usec).nsec.should == 123456500 - Time.at(0, 123.500, :millisecond).nsec.should == 123500000 + it "does not try to convert format to Symbol with #to_sym" do + format = "usec" + format.should_not_receive(:to_sym) + -> { Time.at(0, 123456, format) }.should raise_error(ArgumentError) end end + + it "supports Float second argument" do + Time.at(0, 123456789.500, :nanosecond).nsec.should == 123456789 + Time.at(0, 123456789.500, :nsec).nsec.should == 123456789 + Time.at(0, 123456.500, :microsecond).nsec.should == 123456500 + Time.at(0, 123456.500, :usec).nsec.should == 123456500 + Time.at(0, 123.500, :millisecond).nsec.should == 123500000 + end end - ruby_version_is "2.6" do - describe ":in keyword argument" do - before do - @epoch_time = Time.now.to_i - end + describe ":in keyword argument" do + before do + @epoch_time = Time.now.to_i + end - it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do - time = Time.at(@epoch_time, in: "+05:00") + it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do + time = Time.at(@epoch_time, in: "+05:00") - time.utc_offset.should == 5*60*60 - time.zone.should == nil - time.to_i.should == @epoch_time + time.utc_offset.should == 5*60*60 + time.zone.should == nil + time.to_i.should == @epoch_time - time = Time.at(@epoch_time, in: "-09:00") + time = Time.at(@epoch_time, in: "-09:00") - time.utc_offset.should == -9*60*60 - time.zone.should == nil - time.to_i.should == @epoch_time - end + time.utc_offset.should == -9*60*60 + time.zone.should == nil + time.to_i.should == @epoch_time + end - it "could be UTC offset as a number of seconds" do - time = Time.at(@epoch_time, in: 5*60*60) + it "could be UTC offset as a number of seconds" do + time = Time.at(@epoch_time, in: 5*60*60) - time.utc_offset.should == 5*60*60 - time.zone.should == nil - time.to_i.should == @epoch_time + time.utc_offset.should == 5*60*60 + time.zone.should == nil + time.to_i.should == @epoch_time - time = Time.at(@epoch_time, in: -9*60*60) + time = Time.at(@epoch_time, in: -9*60*60) - time.utc_offset.should == -9*60*60 - time.zone.should == nil - time.to_i.should == @epoch_time - end + time.utc_offset.should == -9*60*60 + time.zone.should == nil + time.to_i.should == @epoch_time + end - it "could be a timezone object" do - zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") - time = Time.at(@epoch_time, in: zone) + it "could be a timezone object" do + zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") + time = Time.at(@epoch_time, in: zone) - time.utc_offset.should == 5*3600+30*60 - time.zone.should == zone - time.to_i.should == @epoch_time + time.utc_offset.should == 5*3600+30*60 + time.zone.should == zone + time.to_i.should == @epoch_time - zone = TimeSpecs::TimezoneWithName.new(name: "PST") - time = Time.at(@epoch_time, in: zone) + zone = TimeSpecs::TimezoneWithName.new(name: "PST") + time = Time.at(@epoch_time, in: zone) - time.utc_offset.should == -9*60*60 - time.zone.should == zone - time.to_i.should == @epoch_time - end + time.utc_offset.should == -9*60*60 + time.zone.should == zone + time.to_i.should == @epoch_time end end end diff --git a/ruby/spec/ruby/core/time/ceil_spec.rb b/ruby/spec/ruby/core/time/ceil_spec.rb index 29dcec5d7..86029554d 100644 --- a/ruby/spec/ruby/core/time/ceil_spec.rb +++ b/ruby/spec/ruby/core/time/ceil_spec.rb @@ -36,10 +36,11 @@ it "copies own timezone to the returning value" do @time.zone.should == @time.ceil.zone - with_timezone "JST-9" do - time = Time.at 0, 1 - time.zone.should == time.ceil.zone + time = with_timezone "JST-9" do + Time.at 0, 1 end + + time.zone.should == time.ceil.zone end end end diff --git a/ruby/spec/ruby/core/time/dup_spec.rb b/ruby/spec/ruby/core/time/dup_spec.rb index ee2ff7dbb..5d6621bea 100644 --- a/ruby/spec/ruby/core/time/dup_spec.rb +++ b/ruby/spec/ruby/core/time/dup_spec.rb @@ -7,7 +7,7 @@ end it "copies the gmt state flag" do - Time.now.gmtime.dup.gmt?.should == true + Time.now.gmtime.dup.should.gmt? end it "returns an independent Time object" do @@ -15,7 +15,7 @@ t2 = t.dup t.gmtime - t2.gmt?.should == false + t2.should_not.gmt? end it "returns a subclass instance" do diff --git a/ruby/spec/ruby/core/time/floor_spec.rb b/ruby/spec/ruby/core/time/floor_spec.rb index 763ed1ba5..a19585b78 100644 --- a/ruby/spec/ruby/core/time/floor_spec.rb +++ b/ruby/spec/ruby/core/time/floor_spec.rb @@ -28,10 +28,11 @@ it "copies own timezone to the returning value" do @time.zone.should == @time.floor.zone - with_timezone "JST-9" do - time = Time.at 0, 1 - time.zone.should == time.floor.zone + time = with_timezone "JST-9" do + Time.at 0, 1 end + + time.zone.should == time.floor.zone end end end diff --git a/ruby/spec/ruby/core/time/friday_spec.rb b/ruby/spec/ruby/core/time/friday_spec.rb index 27f9e1dbe..8bee7f755 100644 --- a/ruby/spec/ruby/core/time/friday_spec.rb +++ b/ruby/spec/ruby/core/time/friday_spec.rb @@ -2,10 +2,10 @@ describe "Time#friday?" do it "returns true if time represents Friday" do - Time.local(2000, 1, 7).friday?.should == true + Time.local(2000, 1, 7).should.friday? end it "returns false if time doesn't represent Friday" do - Time.local(2000, 1, 1).friday?.should == false + Time.local(2000, 1, 1).should_not.friday? end end diff --git a/ruby/spec/ruby/core/time/getlocal_spec.rb b/ruby/spec/ruby/core/time/getlocal_spec.rb index 7196577da..926a6dbf4 100644 --- a/ruby/spec/ruby/core/time/getlocal_spec.rb +++ b/ruby/spec/ruby/core/time/getlocal_spec.rb @@ -97,71 +97,69 @@ -> { t.getlocal(86400) }.should raise_error(ArgumentError) end - ruby_version_is "2.6" do - describe "with a timezone argument" do - it "returns a Time in the timezone" do - zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone) - - time.zone.should == zone - time.utc_offset.should == 5*3600+30*60 - end + describe "with a timezone argument" do + it "returns a Time in the timezone" do + zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) + time = Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone) - it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do - zone = Object.new - def zone.utc_to_local(time) - time - end - def zone.local_to_utc(time) - time - end + time.zone.should == zone + time.utc_offset.should == 5*3600+30*60 + end - -> { - Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time) - }.should_not raise_error + it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do + zone = Object.new + def zone.utc_to_local(time) + time + end + def zone.local_to_utc(time) + time end - it "raises TypeError if timezone does not implement #utc_to_local method" do - zone = Object.new - def zone.local_to_utc(time) - time - end + -> { + Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time) + }.should_not raise_error + end - -> { - Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone) - }.should raise_error(TypeError, /can't convert \w+ into an exact number/) + it "raises TypeError if timezone does not implement #utc_to_local method" do + zone = Object.new + def zone.local_to_utc(time) + time end - it "does not raise exception if timezone does not implement #local_to_utc method" do - zone = Object.new - def zone.utc_to_local(time) - time - end + -> { + Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone) + }.should raise_error(TypeError, /can't convert \w+ into an exact number/) + end - -> { - Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time) - }.should_not raise_error + it "does not raise exception if timezone does not implement #local_to_utc method" do + zone = Object.new + def zone.utc_to_local(time) + time end - context "subject's class implements .find_timezone method" do - it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do - time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("Asia/Colombo") - time.zone.should be_kind_of TimeSpecs::TimezoneWithName - time.zone.name.should == "Asia/Colombo" + -> { + Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time) + }.should_not raise_error + end + + context "subject's class implements .find_timezone method" do + it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do + time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("Asia/Colombo") + time.zone.should be_kind_of TimeSpecs::TimezoneWithName + time.zone.name.should == "Asia/Colombo" - time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("some invalid zone name") - time.zone.should be_kind_of TimeSpecs::TimezoneWithName - time.zone.name.should == "some invalid zone name" - end + time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("some invalid zone name") + time.zone.should be_kind_of TimeSpecs::TimezoneWithName + time.zone.name.should == "some invalid zone name" + end - it "does not call .find_timezone if passed any not string/numeric/timezone timezone argument" do - [Object.new, [], {}, :"some zone"].each do |zone| - time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0) + it "does not call .find_timezone if passed any not string/numeric/timezone timezone argument" do + [Object.new, [], {}, :"some zone"].each do |zone| + time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0) - -> { - time.getlocal(zone) - }.should raise_error(TypeError, /can't convert \w+ into an exact number/) - end + -> { + time.getlocal(zone) + }.should raise_error(TypeError, /can't convert \w+ into an exact number/) end end end diff --git a/ruby/spec/ruby/core/time/gmt_spec.rb b/ruby/spec/ruby/core/time/gmt_spec.rb index 7e85749d5..840f59e0e 100644 --- a/ruby/spec/ruby/core/time/gmt_spec.rb +++ b/ruby/spec/ruby/core/time/gmt_spec.rb @@ -2,7 +2,7 @@ describe "Time#gmt?" do it "returns true if time represents a time in UTC (GMT)" do - Time.now.gmt?.should == false - Time.now.gmtime.gmt?.should == true + Time.now.should_not.gmt? + Time.now.gmtime.should.gmt? end end diff --git a/ruby/spec/ruby/core/time/hash_spec.rb b/ruby/spec/ruby/core/time/hash_spec.rb index 577aaf9b0..4f4d11a2c 100644 --- a/ruby/spec/ruby/core/time/hash_spec.rb +++ b/ruby/spec/ruby/core/time/hash_spec.rb @@ -1,8 +1,8 @@ require_relative '../../spec_helper' describe "Time#hash" do - it "returns a Fixnum" do - Time.at(100).hash.should be_an_instance_of(Fixnum) + it "returns an Integer" do + Time.at(100).hash.should be_an_instance_of(Integer) end it "is stable" do diff --git a/ruby/spec/ruby/core/time/inspect_spec.rb b/ruby/spec/ruby/core/time/inspect_spec.rb index 01e1dfdaa..6f1b2e3ef 100644 --- a/ruby/spec/ruby/core/time/inspect_spec.rb +++ b/ruby/spec/ruby/core/time/inspect_spec.rb @@ -3,4 +3,33 @@ describe "Time#inspect" do it_behaves_like :inspect, :inspect + + ruby_version_is "2.7" do + it "preserves microseconds" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456) + t.inspect.should == "2007-11-01 15:25:00.123456 UTC" + end + + it "omits trailing zeros from microseconds" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 100000) + t.inspect.should == "2007-11-01 15:25:00.1 UTC" + end + + it "uses the correct time zone without microseconds" do + t = Time.utc(2000, 1, 1) + t = t.localtime(9*3600) + t.inspect.should == "2000-01-01 09:00:00 +0900" + end + + it "uses the correct time zone with microseconds" do + t = Time.utc(2000, 1, 1, 0, 0, 0, 123456) + t = t.localtime(9*3600) + t.inspect.should == "2000-01-01 09:00:00.123456 +0900" + end + + it "preserves nanoseconds" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) + t.inspect.should == "2007-11-01 15:25:00.123456789 UTC" + end + end end diff --git a/ruby/spec/ruby/core/time/minus_spec.rb b/ruby/spec/ruby/core/time/minus_spec.rb index e0fbf94cb..844977846 100644 --- a/ruby/spec/ruby/core/time/minus_spec.rb +++ b/ruby/spec/ruby/core/time/minus_spec.rb @@ -79,11 +79,11 @@ end it "returns a UTC time if self is UTC" do - (Time.utc(2012) - 10).utc?.should == true + (Time.utc(2012) - 10).should.utc? end it "returns a non-UTC time if self is non-UTC" do - (Time.local(2012) - 10).utc?.should == false + (Time.local(2012) - 10).should_not.utc? end it "returns a time with the same fixed offset as self" do @@ -92,20 +92,18 @@ it "preserves time zone" do time_with_zone = Time.now.utc - time_with_zone.zone.should == (time_with_zone - 60*60).zone + time_with_zone.zone.should == (time_with_zone - 1).zone time_with_zone = Time.now - time_with_zone.zone.should == (time_with_zone - 60*60).zone + time_with_zone.zone.should == (time_with_zone - 1).zone end - ruby_version_is "2.6" do - context "zone is a timezone object" do - it "preserves time zone" do - zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 60*60 + context "zone is a timezone object" do + it "preserves time zone" do + zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) + time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 1 - time.zone.should == zone - end + time.zone.should == zone end end diff --git a/ruby/spec/ruby/core/time/monday_spec.rb b/ruby/spec/ruby/core/time/monday_spec.rb index c5c43a5c3..47ecaeb1d 100644 --- a/ruby/spec/ruby/core/time/monday_spec.rb +++ b/ruby/spec/ruby/core/time/monday_spec.rb @@ -2,10 +2,10 @@ describe "Time#monday?" do it "returns true if time represents Monday" do - Time.local(2000, 1, 3).monday?.should == true + Time.local(2000, 1, 3).should.monday? end it "returns false if time doesn't represent Monday" do - Time.local(2000, 1, 1).monday?.should == false + Time.local(2000, 1, 1).should_not.monday? end end diff --git a/ruby/spec/ruby/core/time/new_spec.rb b/ruby/spec/ruby/core/time/new_spec.rb index a5cfa2a7d..09b4d03a4 100644 --- a/ruby/spec/ruby/core/time/new_spec.rb +++ b/ruby/spec/ruby/core/time/new_spec.rb @@ -15,7 +15,7 @@ describe "Time.new with a utc_offset argument" do it "returns a non-UTC time" do - Time.new(2000, 1, 1, 0, 0, 0, 0).utc?.should == false + Time.new(2000, 1, 1, 0, 0, 0, 0).should_not.utc? end it "returns a Time with a UTC offset of the specified number of Integer seconds" do @@ -121,212 +121,214 @@ end end -ruby_version_is "2.6" do - describe "Time.new with a timezone argument" do - it "returns a Time in the timezone" do - zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.new(2000, 1, 1, 12, 0, 0, zone) +describe "Time.new with a timezone argument" do + it "returns a Time in the timezone" do + zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) + time = Time.new(2000, 1, 1, 12, 0, 0, zone) + + time.zone.should == zone + time.utc_offset.should == 5*3600+30*60 + ruby_version_is "3.0" do + time.wday.should == 6 + time.yday.should == 1 + end + end - time.zone.should == zone - time.utc_offset.should == 5*3600+30*60 + it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do + zone = Object.new + def zone.utc_to_local(time) + time end + def zone.local_to_utc(time) + time + end + + -> { + Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) + }.should_not raise_error + end - it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do + it "raises TypeError if timezone does not implement #local_to_utc method" do + zone = Object.new + def zone.utc_to_local(time) + time + end + + -> { + Time.new(2000, 1, 1, 12, 0, 0, zone) + }.should raise_error(TypeError, /can't convert \w+ into an exact number/) + end + + it "does not raise exception if timezone does not implement #utc_to_local method" do + zone = Object.new + def zone.local_to_utc(time) + time + end + + -> { + Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) + }.should_not raise_error + end + + # The result also should be a Time or Time-like object (not necessary to be the same class) + # The zone of the result is just ignored + describe "returned value by #utc_to_local and #local_to_utc methods" do + it "could be Time instance" do zone = Object.new - def zone.utc_to_local(time) - time - end - def zone.local_to_utc(time) - time + def zone.local_to_utc(t) + Time.utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec) end -> { Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) + Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 }.should_not raise_error end - it "raises TypeError if timezone does not implement #local_to_utc method" do + it "could be Time subclass instance" do zone = Object.new - def zone.utc_to_local(time) - time + def zone.local_to_utc(t) + Class.new(Time).utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec) end -> { - Time.new(2000, 1, 1, 12, 0, 0, zone) - }.should raise_error(TypeError, /can't convert \w+ into an exact number/) + Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) + Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 + }.should_not raise_error end - it "does not raise exception if timezone does not implement #utc_to_local method" do + it "could be any object with #to_i method" do zone = Object.new def zone.local_to_utc(time) - time + Struct.new(:to_i).new(time.to_i - 60*60) end -> { Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) + Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 }.should_not raise_error end - # The result also should be a Time or Time-like object (not necessary to be the same class) - # The zone of the result is just ignored - describe "returned value by #utc_to_local and #local_to_utc methods" do - it "could be Time instance" do - zone = Object.new - def zone.local_to_utc(t) - Time.utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec) - end - - -> { - Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) - Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 - }.should_not raise_error - end - - it "could be Time subclass instance" do - zone = Object.new - def zone.local_to_utc(t) - Class.new(Time).utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec) - end - - -> { - Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) - Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 - }.should_not raise_error - end - - it "could be any object with #to_i method" do - zone = Object.new - def zone.local_to_utc(time) - Struct.new(:to_i).new(time.to_i - 60*60) - end - - -> { - Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time) - Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60 - }.should_not raise_error - end - - it "could have any #zone and #utc_offset because they are ignored" do - zone = Object.new - def zone.local_to_utc(time) - Struct.new(:to_i, :zone, :utc_offset).new(time.to_i, 'America/New_York', -5*60*60) - end - Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0 - - zone = Object.new - def zone.local_to_utc(time) - Struct.new(:to_i, :zone, :utc_offset).new(time.to_i, 'Asia/Tokyo', 9*60*60) - end - Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0 + it "could have any #zone and #utc_offset because they are ignored" do + zone = Object.new + def zone.local_to_utc(time) + Struct.new(:to_i, :zone, :utc_offset).new(time.to_i, 'America/New_York', -5*60*60) end + Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0 - it "leads to raising Argument error if difference between argument and result is too large" do - zone = Object.new - def zone.local_to_utc(t) - Time.utc(t.year, t.mon, t.day + 1, t.hour, t.min, t.sec) - end - - -> { - Time.new(2000, 1, 1, 12, 0, 0, zone) - }.should raise_error(ArgumentError, "utc_offset out of range") + zone = Object.new + def zone.local_to_utc(time) + Struct.new(:to_i, :zone, :utc_offset).new(time.to_i, 'Asia/Tokyo', 9*60*60) end + Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0 end - # https://github.com/ruby/ruby/blob/v2_6_0/time.c#L5330 - # - # Time-like argument to these methods is similar to a Time object in UTC without sub-second; - # it has attribute readers for the parts, e.g. year, month, and so on, and epoch time readers, to_i - # - # The sub-second attributes are fixed as 0, and utc_offset, zone, isdst, and their aliases are same as a Time object in UTC - describe "Time-like argument of #utc_to_local and #local_to_utc methods" do - before do - @obj = TimeSpecs::TimeLikeArgumentRecorder.result - @obj.should_not == nil + it "leads to raising Argument error if difference between argument and result is too large" do + zone = Object.new + def zone.local_to_utc(t) + Time.utc(t.year, t.mon, t.day + 1, t.hour, t.min, t.sec) end - it "implements subset of Time methods" do - [ - :year, :mon, :month, :mday, :hour, :min, :sec, - :tv_sec, :tv_usec, :usec, :tv_nsec, :nsec, :subsec, - :to_i, :to_f, :to_r, :+, :-, - :isdst, :dst?, :zone, :gmtoff, :gmt_offset, :utc_offset, :utc?, :gmt?, - :to_s, :inspect, :to_a, :to_time, - ].each do |name| - @obj.respond_to?(name).should == true - end - end + -> { + Time.new(2000, 1, 1, 12, 0, 0, zone) + }.should raise_error(ArgumentError, "utc_offset out of range") + end + end - it "has attribute values the same as a Time object in UTC" do - @obj.usec.should == 0 - @obj.nsec.should == 0 - @obj.subsec.should == 0 - @obj.tv_usec.should == 0 - @obj.tv_nsec.should == 0 + # https://github.com/ruby/ruby/blob/v2_6_0/time.c#L5330 + # + # Time-like argument to these methods is similar to a Time object in UTC without sub-second; + # it has attribute readers for the parts, e.g. year, month, and so on, and epoch time readers, to_i + # + # The sub-second attributes are fixed as 0, and utc_offset, zone, isdst, and their aliases are same as a Time object in UTC + describe "Time-like argument of #utc_to_local and #local_to_utc methods" do + before do + @obj = TimeSpecs::TimeLikeArgumentRecorder.result + @obj.should_not == nil + end - @obj.utc_offset.should == 0 - @obj.zone.should == "UTC" - @obj.isdst.should == Time.new.utc.isdst + it "implements subset of Time methods" do + [ + :year, :mon, :month, :mday, :hour, :min, :sec, + :tv_sec, :tv_usec, :usec, :tv_nsec, :nsec, :subsec, + :to_i, :to_f, :to_r, :+, :-, + :isdst, :dst?, :zone, :gmtoff, :gmt_offset, :utc_offset, :utc?, :gmt?, + :to_s, :inspect, :to_a, :to_time, + ].each do |name| + @obj.respond_to?(name).should == true end end - context "#name method" do - it "uses the optional #name method for marshaling" do - zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") - time = Time.new(2000, 1, 1, 12, 0, 0, zone) - time_loaded = Marshal.load(Marshal.dump(time)) + it "has attribute values the same as a Time object in UTC" do + @obj.usec.should == 0 + @obj.nsec.should == 0 + @obj.subsec.should == 0 + @obj.tv_usec.should == 0 + @obj.tv_nsec.should == 0 - time_loaded.zone.should == "Asia/Colombo" - time_loaded.utc_offset.should == 5*3600+30*60 - end + @obj.utc_offset.should == 0 + @obj.zone.should == "UTC" + @obj.isdst.should == Time.new.utc.isdst + end + end - it "cannot marshal Time if #name method isn't implemented" do - zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.new(2000, 1, 1, 12, 0, 0, zone) + context "#name method" do + it "uses the optional #name method for marshaling" do + zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") + time = Time.new(2000, 1, 1, 12, 0, 0, zone) + time_loaded = Marshal.load(Marshal.dump(time)) - -> { - Marshal.dump(time) - }.should raise_error(NoMethodError, /undefined method `name' for/) - end + time_loaded.zone.should == "Asia/Colombo" + time_loaded.utc_offset.should == 5*3600+30*60 end - it "the #abbr method is used by '%Z' in #strftime" do - zone = TimeSpecs::TimezoneWithAbbr.new(name: "Asia/Colombo") + it "cannot marshal Time if #name method isn't implemented" do + zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) time = Time.new(2000, 1, 1, 12, 0, 0, zone) - time.strftime("%Z").should == "MMT" + -> { + Marshal.dump(time) + }.should raise_error(NoMethodError, /undefined method `name' for/) end + end - # At loading marshaled data, a timezone name will be converted to a timezone object - # by find_timezone class method, if the method is defined. - # Similarly, that class method will be called when a timezone argument does not have - # the necessary methods mentioned above. - context "subject's class implements .find_timezone method" do - it "calls .find_timezone to build a time object at loading marshaled data" do - zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") - time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone) - time_loaded = Marshal.load(Marshal.dump(time)) - - time_loaded.zone.should be_kind_of TimeSpecs::TimezoneWithName - time_loaded.zone.name.should == "Asia/Colombo" - time_loaded.utc_offset.should == 5*3600+30*60 - end + it "the #abbr method is used by '%Z' in #strftime" do + zone = TimeSpecs::TimezoneWithAbbr.new(name: "Asia/Colombo") + time = Time.new(2000, 1, 1, 12, 0, 0, zone) - it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do - time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "Asia/Colombo") - time.zone.should be_kind_of TimeSpecs::TimezoneWithName - time.zone.name.should == "Asia/Colombo" + time.strftime("%Z").should == "MMT" + end - time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "some invalid zone name") - time.zone.should be_kind_of TimeSpecs::TimezoneWithName - time.zone.name.should == "some invalid zone name" - end + # At loading marshaled data, a timezone name will be converted to a timezone object + # by find_timezone class method, if the method is defined. + # Similarly, that class method will be called when a timezone argument does not have + # the necessary methods mentioned above. + context "subject's class implements .find_timezone method" do + it "calls .find_timezone to build a time object at loading marshaled data" do + zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") + time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone) + time_loaded = Marshal.load(Marshal.dump(time)) + + time_loaded.zone.should be_kind_of TimeSpecs::TimezoneWithName + time_loaded.zone.name.should == "Asia/Colombo" + time_loaded.utc_offset.should == 5*3600+30*60 + end - it "does not call .find_timezone if passed any not string/numeric/timezone timezone argument" do - [Object.new, [], {}, :"some zone"].each do |zone| - -> { - TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone) - }.should raise_error(TypeError, /can't convert \w+ into an exact number/) - end + it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do + time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "Asia/Colombo") + time.zone.should be_kind_of TimeSpecs::TimezoneWithName + time.zone.name.should == "Asia/Colombo" + + time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "some invalid zone name") + time.zone.should be_kind_of TimeSpecs::TimezoneWithName + time.zone.name.should == "some invalid zone name" + end + + it "does not call .find_timezone if passed any not string/numeric/timezone timezone argument" do + [Object.new, [], {}, :"some zone"].each do |zone| + -> { + TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone) + }.should raise_error(TypeError, /can't convert \w+ into an exact number/) end end end diff --git a/ruby/spec/ruby/core/time/plus_spec.rb b/ruby/spec/ruby/core/time/plus_spec.rb index 0a9984f18..642393b61 100644 --- a/ruby/spec/ruby/core/time/plus_spec.rb +++ b/ruby/spec/ruby/core/time/plus_spec.rb @@ -37,11 +37,11 @@ end it "returns a UTC time if self is UTC" do - (Time.utc(2012) + 10).utc?.should == true + (Time.utc(2012) + 10).should.utc? end it "returns a non-UTC time if self is non-UTC" do - (Time.local(2012) + 10).utc?.should == false + (Time.local(2012) + 10).should_not.utc? end it "returns a time with the same fixed offset as self" do @@ -50,20 +50,18 @@ it "preserves time zone" do time_with_zone = Time.now.utc - time_with_zone.zone.should == (time_with_zone + 60*60).zone + time_with_zone.zone.should == (time_with_zone + 1).zone time_with_zone = Time.now - time_with_zone.zone.should == (time_with_zone + 60*60).zone + time_with_zone.zone.should == (time_with_zone + 1).zone end - ruby_version_is "2.6" do - context "zone is a timezone object" do - it "preserves time zone" do - zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.new(2012, 1, 1, 12, 0, 0, zone) + 60*60 + context "zone is a timezone object" do + it "preserves time zone" do + zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) + time = Time.new(2012, 1, 1, 12, 0, 0, zone) + 1 - time.zone.should == zone - end + time.zone.should == zone end end diff --git a/ruby/spec/ruby/core/time/saturday_spec.rb b/ruby/spec/ruby/core/time/saturday_spec.rb index 60ffea419..0e5140736 100644 --- a/ruby/spec/ruby/core/time/saturday_spec.rb +++ b/ruby/spec/ruby/core/time/saturday_spec.rb @@ -2,10 +2,10 @@ describe "Time#saturday?" do it "returns true if time represents Saturday" do - Time.local(2000, 1, 1).saturday?.should == true + Time.local(2000, 1, 1).should.saturday? end it "returns false if time doesn't represent Saturday" do - Time.local(2000, 1, 2).saturday?.should == false + Time.local(2000, 1, 2).should_not.saturday? end end diff --git a/ruby/spec/ruby/core/time/shared/now.rb b/ruby/spec/ruby/core/time/shared/now.rb index d8e5ac9d5..f4018d72f 100644 --- a/ruby/spec/ruby/core/time/shared/now.rb +++ b/ruby/spec/ruby/core/time/shared/now.rb @@ -18,18 +18,16 @@ end end - guard_not -> { platform_is :windows and ruby_version_is ""..."2.5" } do - it "has at least microsecond precision" do - times = [] - 10_000.times do - times << Time.now.nsec - end - - # The clock should not be less accurate than expected (times should - # not all be a multiple of the next precision up, assuming precisions - # are multiples of ten.) - expected = 1_000 - times.select { |t| t % (expected * 10) == 0 }.size.should_not == times.size + it "has at least microsecond precision" do + # The clock should not be less accurate than expected (times should + # not all be a multiple of the next precision up, assuming precisions + # are multiples of ten.) + expected = 1_000 + t = 0 + 10_000.times.find do + t = Time.now.nsec + t % (expected * 10) != 0 end + (t % (expected * 10)).should != 0 end end diff --git a/ruby/spec/ruby/core/time/shared/to_i.rb b/ruby/spec/ruby/core/time/shared/to_i.rb index 03497c700..06c966b70 100644 --- a/ruby/spec/ruby/core/time/shared/to_i.rb +++ b/ruby/spec/ruby/core/time/shared/to_i.rb @@ -6,4 +6,11 @@ it "doesn't return an actual number of seconds in time" do Time.at(65.5).send(@method).should == 65 end + + it "rounds fractional seconds toward zero" do + t = Time.utc(1960, 1, 1, 0, 0, 0, 999_999) + + t.to_f.to_i.should == -315619199 + t.to_i.should == -315619200 + end end diff --git a/ruby/spec/ruby/core/time/subsec_spec.rb b/ruby/spec/ruby/core/time/subsec_spec.rb index 583a26412..0f2c4eb85 100644 --- a/ruby/spec/ruby/core/time/subsec_spec.rb +++ b/ruby/spec/ruby/core/time/subsec_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Time#subsec" do - it "returns 0 as a Fixnum for a Time with a whole number of seconds" do + it "returns 0 as an Integer for a Time with a whole number of seconds" do Time.at(100).subsec.should eql(0) end diff --git a/ruby/spec/ruby/core/time/succ_spec.rb b/ruby/spec/ruby/core/time/succ_spec.rb index e68e64b0c..e8249059d 100644 --- a/ruby/spec/ruby/core/time/succ_spec.rb +++ b/ruby/spec/ruby/core/time/succ_spec.rb @@ -1,36 +1,36 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/classes' +ruby_version_is ""..."3.0" do + require_relative '../../spec_helper' + require_relative 'fixtures/classes' -describe "Time#succ" do - it "returns a new time one second later than time" do - suppress_warning { - @result = Time.at(100).succ - } + describe "Time#succ" do + it "returns a new time one second later than time" do + suppress_warning { + @result = Time.at(100).succ + } - @result.should == Time.at(101) - end + @result.should == Time.at(101) + end - it "returns a new instance" do - time = Time.at(100) + it "returns a new instance" do + time = Time.at(100) - suppress_warning { - @result = time.succ - } + suppress_warning { + @result = time.succ + } - @result.should_not equal time - end + @result.should_not equal time + end - it "is obsolete" do - -> { - Time.at(100).succ - }.should complain(/Time#succ is obsolete/) - end + it "is obsolete" do + -> { + Time.at(100).succ + }.should complain(/Time#succ is obsolete/) + end - ruby_version_is "2.6" do context "zone is a timezone object" do it "preserves time zone" do zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60)) - time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 60*60 + time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 1 time.zone.should == zone end diff --git a/ruby/spec/ruby/core/time/sunday_spec.rb b/ruby/spec/ruby/core/time/sunday_spec.rb index 228558357..0d4642113 100644 --- a/ruby/spec/ruby/core/time/sunday_spec.rb +++ b/ruby/spec/ruby/core/time/sunday_spec.rb @@ -2,10 +2,10 @@ describe "Time#sunday?" do it "returns true if time represents Sunday" do - Time.local(2000, 1, 2).sunday?.should == true + Time.local(2000, 1, 2).should.sunday? end it "returns false if time doesn't represent Sunday" do - Time.local(2000, 1, 1).sunday?.should == false + Time.local(2000, 1, 1).should_not.sunday? end end diff --git a/ruby/spec/ruby/core/time/thursday_spec.rb b/ruby/spec/ruby/core/time/thursday_spec.rb index c82d51751..c11e79d2f 100644 --- a/ruby/spec/ruby/core/time/thursday_spec.rb +++ b/ruby/spec/ruby/core/time/thursday_spec.rb @@ -2,10 +2,10 @@ describe "Time#thursday?" do it "returns true if time represents Thursday" do - Time.local(2000, 1, 6).thursday?.should == true + Time.local(2000, 1, 6).should.thursday? end it "returns false if time doesn't represent Thursday" do - Time.local(2000, 1, 1).thursday?.should == false + Time.local(2000, 1, 1).should_not.thursday? end end diff --git a/ruby/spec/ruby/core/time/tuesday_spec.rb b/ruby/spec/ruby/core/time/tuesday_spec.rb index 7abbdc92c..0e7b9e750 100644 --- a/ruby/spec/ruby/core/time/tuesday_spec.rb +++ b/ruby/spec/ruby/core/time/tuesday_spec.rb @@ -2,10 +2,10 @@ describe "Time#tuesday?" do it "returns true if time represents Tuesday" do - Time.local(2000, 1, 4).tuesday?.should == true + Time.local(2000, 1, 4).should.tuesday? end it "returns false if time doesn't represent Tuesday" do - Time.local(2000, 1, 1).tuesday?.should == false + Time.local(2000, 1, 1).should_not.tuesday? end end diff --git a/ruby/spec/ruby/core/time/utc_spec.rb b/ruby/spec/ruby/core/time/utc_spec.rb index 5074c8d54..74c17a93d 100644 --- a/ruby/spec/ruby/core/time/utc_spec.rb +++ b/ruby/spec/ruby/core/time/utc_spec.rb @@ -5,7 +5,7 @@ describe "Time#utc?" do it "returns true if time represents a time in UTC (GMT)" do - Time.now.utc?.should == false + Time.now.should_not.utc? end end diff --git a/ruby/spec/ruby/core/time/wednesday_spec.rb b/ruby/spec/ruby/core/time/wednesday_spec.rb index 6a52c3577..cc686681d 100644 --- a/ruby/spec/ruby/core/time/wednesday_spec.rb +++ b/ruby/spec/ruby/core/time/wednesday_spec.rb @@ -2,10 +2,10 @@ describe "Time#wednesday?" do it "returns true if time represents Wednesday" do - Time.local(2000, 1, 5).wednesday?.should == true + Time.local(2000, 1, 5).should.wednesday? end it "returns false if time doesn't represent Wednesday" do - Time.local(2000, 1, 1).wednesday?.should == false + Time.local(2000, 1, 1).should_not.wednesday? end end diff --git a/ruby/spec/ruby/core/tracepoint/binding_spec.rb b/ruby/spec/ruby/core/tracepoint/binding_spec.rb index f37753602..6a7ef5f85 100644 --- a/ruby/spec/ruby/core/tracepoint/binding_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/binding_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#binding' do def test @@ -8,6 +9,7 @@ def test it 'return the generated binding object from event' do bindings = [] TracePoint.new(:return) { |tp| + next unless TracePointSpec.target_thread? bindings << tp.binding }.enable { test diff --git a/ruby/spec/ruby/core/tracepoint/callee_id_spec.rb b/ruby/spec/ruby/core/tracepoint/callee_id_spec.rb index d340290d8..cc08a4550 100644 --- a/ruby/spec/ruby/core/tracepoint/callee_id_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/callee_id_spec.rb @@ -7,6 +7,7 @@ obj = TracePointSpec::ClassWithMethodAlias.new TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? a << tp.callee_id end.enable do obj.m_alias diff --git a/ruby/spec/ruby/core/tracepoint/defined_class_spec.rb b/ruby/spec/ruby/core/tracepoint/defined_class_spec.rb index 72536e6a5..4593db6d1 100644 --- a/ruby/spec/ruby/core/tracepoint/defined_class_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/defined_class_spec.rb @@ -5,6 +5,7 @@ it 'returns class or module of the method being called' do last_class_name = nil TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? last_class_name = tp.defined_class end.enable do TracePointSpec::B.new.foo diff --git a/ruby/spec/ruby/core/tracepoint/disable_spec.rb b/ruby/spec/ruby/core/tracepoint/disable_spec.rb index 612ca3c25..73a31b3b8 100644 --- a/ruby/spec/ruby/core/tracepoint/disable_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/disable_spec.rb @@ -1,9 +1,11 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#disable' do it 'returns true if trace was enabled' do called = false trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? called = true end @@ -25,6 +27,7 @@ it 'returns false if trace was disabled' do called = false trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? called = true end @@ -41,7 +44,7 @@ begin trace.disable { enabled = trace.enabled? } enabled.should == false - trace.enabled?.should == true + trace.should.enabled? ensure trace.disable end @@ -52,7 +55,7 @@ trace.enable begin trace.disable { 42 }.should == 42 - trace.enabled?.should == true + trace.should.enabled? ensure trace.disable end @@ -65,7 +68,7 @@ trace.disable do |*args| args.should == [] end - trace.enabled?.should == true + trace.should.enabled? ensure trace.disable end diff --git a/ruby/spec/ruby/core/tracepoint/enable_spec.rb b/ruby/spec/ruby/core/tracepoint/enable_spec.rb index b0fe38c55..ab392c758 100644 --- a/ruby/spec/ruby/core/tracepoint/enable_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/enable_spec.rb @@ -1,20 +1,21 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#enable' do - # def test; end - describe 'without a block' do - it 'returns true if trace was enabled' do + it 'returns false if trace was disabled' do called = false trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? called = true end line_event = true called.should == false - trace.enable + ret = trace.enable begin + ret.should == false line_event = true called.should == true ensure @@ -22,30 +23,27 @@ end end - it 'returns false if trace was disabled' do + it 'returns true if trace was already enabled' do called = false trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? called = true end - trace.enable.should == false - begin - line_event = true - called.should == true - ensure - trace.disable - end - - called = false line_event = true called.should == false - trace.enable.should == false + ret = trace.enable begin + ret.should == false + + trace.enable.should == true + line_event = true called.should == true ensure trace.disable + trace.should_not.enabled? end end end @@ -54,18 +52,43 @@ it 'enables the trace object within a block' do event_name = nil TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? event_name = tp.event end.enable { event_name.should equal(:line) } end + it 'enables the trace object for any thread' do + threads = [] + trace = TracePoint.new(:line) do |tp| + # Runs on purpose on any Thread + threads << Thread.current + end + + thread = nil + trace.enable do + line_event = true + thread = Thread.new do + event_in_other_thread = true + end + thread.join + end + + threads = threads.uniq + threads.should.include?(Thread.current) + threads.should.include?(thread) + end + it 'can accept arguments within a block but it should not yield arguments' do event_name = nil - trace = TracePoint.new(:line) { |tp| event_name = tp.event } + trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? + event_name = tp.event + end trace.enable do |*args| event_name.should equal(:line) args.should == [] end - trace.enabled?.should == false + trace.should_not.enabled? end it 'enables trace object on calling with a block if it was already enabled' do @@ -87,394 +110,440 @@ it 'disables the trace object outside the block' do called = false - trace = TracePoint.new(:line) { called = true } + trace = TracePoint.new(:line) do + next unless TracePointSpec.target_thread? + called = true + end trace.enable { line_event = true } called.should == true - trace.enabled?.should == false + trace.should_not.enabled? end end - ruby_version_is "2.6" do - describe 'target: option' do - before :each do - ScratchPad.record [] + describe "when nested" do + before do + ruby_version_is ""..."3.0" do + @path_prefix = '@' end - it 'enables trace point for specific location' do - trace = TracePoint.new(:call) do |tp| - ScratchPad << tp.method_id - end + ruby_version_is "3.0" do + @path_prefix = ' ' + end + end - obj = Object.new - def obj.foo; end - def obj.bar; end + it "enables both TracePoints but only calls the respective callbacks" do + called = false + first = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? + called = true + end - trace.enable(target: obj.method(:foo)) do - obj.foo - obj.bar + all = [] + inspects = [] + second = TracePoint.new(:line) { |tp| + next unless TracePointSpec.target_thread? + all << tp + inspects << tp.inspect + } + + line = nil + first.enable do + second.enable do + line = __LINE__ end + end - ScratchPad.recorded.should == [:foo] + all.uniq.should == [second] + inspects.uniq.should == ["#"] + called.should == true + end + end + + describe 'target: option' do + before :each do + ScratchPad.record [] + end + + it 'enables trace point for specific location' do + trace = TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.method_id end - it 'traces all the events triggered in specified location' do - trace = TracePoint.new(:line, :call, :return, :b_call, :b_return) do |tp| - ScratchPad << tp.event - end + obj = Object.new + def obj.foo; end + def obj.bar; end - obj = Object.new - def obj.foo - bar - -> {}.call - end - def obj.bar; end + trace.enable(target: obj.method(:foo)) do + obj.foo + obj.bar + end - trace.enable(target: obj.method(:foo)) do - obj.foo - end + ScratchPad.recorded.should == [:foo] + end - ScratchPad.recorded.uniq.sort.should == [:call, :return, :b_call, :b_return, :line].sort + it 'traces all the events triggered in specified location' do + trace = TracePoint.new(:line, :call, :return, :b_call, :b_return) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.event end - it 'does not trace events in nested locations' do - trace = TracePoint.new(:call) do |tp| - ScratchPad << tp.method_id - end + obj = Object.new + def obj.foo + bar + -> {}.call + end + def obj.bar; end - obj = Object.new - def obj.foo - bar - end - def obj.bar - baz - end - def obj.baz - end + trace.enable(target: obj.method(:foo)) do + obj.foo + end - trace.enable(target: obj.method(:foo)) do - obj.foo - end + ScratchPad.recorded.uniq.sort.should == [:call, :return, :b_call, :b_return, :line].sort + end - ScratchPad.recorded.should == [:foo] + it 'does not trace events in nested locations' do + trace = TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.method_id end - it "traces some events in nested blocks" do - klass = Class.new do - def foo + obj = Object.new + def obj.foo + bar + end + def obj.bar + baz + end + def obj.baz + end + + trace.enable(target: obj.method(:foo)) do + obj.foo + end + + ScratchPad.recorded.should == [:foo] + end + + it "traces some events in nested blocks" do + klass = Class.new do + def foo + 1.times do 1.times do - 1.times do - bar do - end + bar do end end end + end - def bar(&blk) - blk.call - end + def bar(&blk) + blk.call end + end - trace = TracePoint.new(:b_call) do |tp| - ScratchPad << tp.lineno + trace = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.lineno + end + + obj = klass.new + _, lineno = obj.method(:foo).source_location + + trace.enable(target: obj.method(:foo)) do + obj.foo + end + + ScratchPad.recorded.should == (lineno+1..lineno+3).to_a + end + + describe 'option value' do + it 'accepts Method' do + trace = TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.method_id end - obj = klass.new - _, lineno = obj.method(:foo).source_location + obj = Object.new + def obj.foo; end trace.enable(target: obj.method(:foo)) do obj.foo end - ScratchPad.recorded.should == (lineno+1..lineno+3).to_a + ScratchPad.recorded.should == [:foo] end - describe 'option value' do - it 'accepts Method' do - trace = TracePoint.new(:call) do |tp| - ScratchPad << tp.method_id - end - - obj = Object.new - def obj.foo; end + it 'accepts UnboundMethod' do + trace = TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.method_id + end - trace.enable(target: obj.method(:foo)) do - obj.foo - end + klass = Class.new do + def foo; end + end - ScratchPad.recorded.should == [:foo] + unbound_method = klass.instance_method(:foo) + trace.enable(target: unbound_method) do + klass.new.foo end - it 'accepts UnboundMethod' do - trace = TracePoint.new(:call) do |tp| - ScratchPad << tp.method_id - end + ScratchPad.recorded.should == [:foo] + end - klass = Class.new do - def foo; end - end + it 'accepts Proc' do + trace = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.lineno + end - unbound_method = klass.instance_method(:foo) - trace.enable(target: unbound_method) do - klass.new.foo - end + block = proc {} + _, lineno = block.source_location - ScratchPad.recorded.should == [:foo] + trace.enable(target: block) do + block.call end - it 'accepts Proc' do - trace = TracePoint.new(:b_call) do |tp| - ScratchPad << tp.lineno - end + ScratchPad.recorded.should == [lineno] + lineno.should be_kind_of(Integer) + end + end - block = proc {} - _, lineno = block.source_location + it "raises ArgumentError if target object cannot trigger specified event" do + trace = TracePoint.new(:call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.method_id + end - trace.enable(target: block) do - block.call - end + block = proc {} - ScratchPad.recorded.should == [lineno] - lineno.should be_kind_of(Integer) + -> { + trace.enable(target: block) do + block.call # triggers :b_call and :b_return events end - end + }.should raise_error(ArgumentError, /can not enable any hooks/) + end - it "raises ArgumentError if target object cannot trigger specified event" do - trace = TracePoint.new(:call) do |tp| - ScratchPad << tp.method_id + it "raises ArgumentError if passed not Method/UnboundMethod/Proc" do + trace = TracePoint.new(:call) {} + + -> { + trace.enable(target: Object.new) do end + }.should raise_error(ArgumentError, /specified target is not supported/) + end - block = proc {} + context "nested enabling and disabling" do + it "raises ArgumentError if trace point already enabled with target is re-enabled with target" do + trace = TracePoint.new(:b_call) {} -> { - trace.enable(target: block) do - block.call # triggers :b_call and :b_return events + trace.enable(target: -> {}) do + trace.enable(target: -> {}) do + end end - }.should raise_error(ArgumentError, /can not enable any hooks/) + }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) end - it "raises ArgumentError if passed not Method/UnboundMethod/Proc" do - trace = TracePoint.new(:call) do |tp| - end + it "raises ArgumentError if trace point already enabled without target is re-enabled with target" do + trace = TracePoint.new(:b_call) {} -> { - trace.enable(target: Object.new) do + trace.enable do + trace.enable(target: -> {}) do + end end - }.should raise_error(ArgumentError, /specified target is not supported/) + }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) end - context "nested enabling and disabling" do - it "raises ArgumentError if trace point already enabled with target is re-enabled with target" do - trace = TracePoint.new(:b_call) do - end + it "raises ArgumentError if trace point already enabled with target is re-enabled without target" do + trace = TracePoint.new(:b_call) {} - -> { - trace.enable(target: -> {}) do - trace.enable(target: -> {}) do - end + -> { + trace.enable(target: -> {}) do + trace.enable do end - }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) - end - - it "raises ArgumentError if trace point already enabled without target is re-enabled with target" do - trace = TracePoint.new(:b_call) do end + }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) + end - -> { - trace.enable do - trace.enable(target: -> {}) do - end - end - }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) - end + it "raises ArgumentError if trace point already enabled with target is disabled with block" do + trace = TracePoint.new(:b_call) {} - it "raises ArgumentError if trace point already enabled with target is re-enabled without target" do - trace = TracePoint.new(:b_call) do + -> { + trace.enable(target: -> {}) do + trace.disable do + end end + }.should raise_error(ArgumentError, /can't disable a targett?ing TracePoint in a block/) + end - -> { - trace.enable(target: -> {}) do - trace.enable do - end - end - }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/) + it "traces events when trace point with target is enabled in another trace point enabled without target" do + trace_outer = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :outer end - it "raises ArgumentError if trace point already enabled with target is disabled with block" do - trace = TracePoint.new(:b_call) do - end - - -> { - trace.enable(target: -> {}) do - trace.disable do - end - end - }.should raise_error(ArgumentError, /can't disable a targett?ing TracePoint in a block/) + trace_inner = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :inner end - it "traces events when trace point with target is enabled in another trace point enabled without target" do - trace_outer = TracePoint.new(:b_call) do |tp| - ScratchPad << :outer - end + target = -> {} - trace_inner = TracePoint.new(:b_call) do |tp| - ScratchPad << :inner + trace_outer.enable do + trace_inner.enable(target: target) do + target.call end + end - target = -> {} + ScratchPad.recorded.should == [:outer, :outer, :outer, :inner] + end - trace_outer.enable do - trace_inner.enable(target: target) do - target.call - end - end + it "traces events when trace point with target is enabled in another trace point enabled with target" do + trace_outer = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :outer + end - ScratchPad.recorded.should == [:outer, :outer, :outer, :inner] + trace_inner = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :inner end - it "traces events when trace point with target is enabled in another trace point enabled with target" do - trace_outer = TracePoint.new(:b_call) do |tp| - ScratchPad << :outer - end + target = -> {} - trace_inner = TracePoint.new(:b_call) do |tp| - ScratchPad << :inner + trace_outer.enable(target: target) do + trace_inner.enable(target: target) do + target.call end + end - target = -> {} - - trace_outer.enable(target: target) do - trace_inner.enable(target: target) do - target.call - end - end + ScratchPad.recorded.should == [:inner, :outer] + end - ScratchPad.recorded.should == [:inner, :outer] + it "traces events when trace point without target is enabled in another trace point enabled with target" do + trace_outer = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :outer end - it "traces events when trace point without target is enabled in another trace point enabled with target" do - trace_outer = TracePoint.new(:b_call) do |tp| - ScratchPad << :outer - end - - trace_inner = TracePoint.new(:b_call) do |tp| - ScratchPad << :inner - end + trace_inner = TracePoint.new(:b_call) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << :inner + end - target = -> {} + target = -> {} - trace_outer.enable(target: target) do - trace_inner.enable do - target.call - end + trace_outer.enable(target: target) do + trace_inner.enable do + target.call end - - ScratchPad.recorded.should == [:inner, :inner, :outer] end - end - end - describe 'target_line: option' do - before :each do - ScratchPad.record [] + ScratchPad.recorded.should == [:inner, :inner, :outer] end + end + end - it "traces :line events only on specified line of code" do - trace = TracePoint.new(:line) do |tp| - ScratchPad << tp.lineno - end + describe 'target_line: option' do + before :each do + ScratchPad.record [] + end - target = -> { - x = 1 - y = 2 # <= this line is target - z = x + y - } - _, lineno = target.source_location - target_line = lineno + 2 + it "traces :line events only on specified line of code" do + trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.lineno + end - trace.enable(target_line: target_line, target: target) do - target.call - end + target = -> { + x = 1 + y = 2 # <= this line is target + z = x + y + } + _, lineno = target.source_location + target_line = lineno + 2 - ScratchPad.recorded.should == [target_line] + trace.enable(target_line: target_line, target: target) do + target.call end - it "raises ArgumentError if :target option isn't specified" do - trace = TracePoint.new(:line) do |tp| - end + ScratchPad.recorded.should == [target_line] + end - -> { - trace.enable(target_line: 67) do - end - }.should raise_error(ArgumentError, /only target_line is specified/) - end + it "raises ArgumentError if :target option isn't specified" do + trace = TracePoint.new(:line) {} - it "raises ArgumentError if :line event isn't registered" do - trace = TracePoint.new(:call) do |tp| + -> { + trace.enable(target_line: 67) do end + }.should raise_error(ArgumentError, /only target_line is specified/) + end - target = -> { - x = 1 - y = 2 # <= this line is target - z = x + y - } - _, lineno = target.source_location - target_line = lineno + 2 + it "raises ArgumentError if :line event isn't registered" do + trace = TracePoint.new(:call) {} - -> { - trace.enable(target_line: target_line, target: target) do - end - }.should raise_error(ArgumentError, /target_line is specified, but line event is not specified/) - end + target = -> { + x = 1 + y = 2 # <= this line is target + z = x + y + } + _, lineno = target.source_location + target_line = lineno + 2 - it "raises ArgumentError if :target_line value is out of target code lines range" do - trace = TracePoint.new(:line) do |tp| + -> { + trace.enable(target_line: target_line, target: target) do end + }.should raise_error(ArgumentError, /target_line is specified, but line event is not specified/) + end - -> { - trace.enable(target_line: 1, target: -> { }) do - end - }.should raise_error(ArgumentError, /can not enable any hooks/) - end + it "raises ArgumentError if :target_line value is out of target code lines range" do + trace = TracePoint.new(:line) {} - it "raises TypeError if :target_line value couldn't be coerced to Integer" do - trace = TracePoint.new(:line) do |tp| + -> { + trace.enable(target_line: 1, target: -> { }) do end + }.should raise_error(ArgumentError, /can not enable any hooks/) + end - -> { - trace.enable(target_line: Object.new, target: -> { }) do - end - }.should raise_error(TypeError, /no implicit conversion of \w+? into Integer/) - end + it "raises TypeError if :target_line value couldn't be coerced to Integer" do + trace = TracePoint.new(:line) {} - it "raises ArgumentError if :target_line value is negative" do - trace = TracePoint.new(:line) do |tp| + -> { + trace.enable(target_line: Object.new, target: -> { }) do end + }.should raise_error(TypeError, /no implicit conversion of \w+? into Integer/) + end - -> { - trace.enable(target_line: -2, target: -> { }) do - end - }.should raise_error(ArgumentError, /can not enable any hooks/) - end + it "raises ArgumentError if :target_line value is negative" do + trace = TracePoint.new(:line) {} - it "accepts value that could be coerced to Integer" do - trace = TracePoint.new(:line) do |tp| - ScratchPad << tp.lineno + -> { + trace.enable(target_line: -2, target: -> { }) do end + }.should raise_error(ArgumentError, /can not enable any hooks/) + end - target = -> { - x = 1 # <= this line is target - } - _, lineno = target.source_location - target_line = lineno + 1 + it "accepts value that could be coerced to Integer" do + trace = TracePoint.new(:line) do |tp| + next unless TracePointSpec.target_thread? + ScratchPad << tp.lineno + end - trace.enable(target_line: target_line.to_r, target: target) do - target.call - end + target = -> { + x = 1 # <= this line is target + } + _, lineno = target.source_location + target_line = lineno + 1 - ScratchPad.recorded.should == [target_line] + trace.enable(target_line: target_line.to_r, target: target) do + target.call end + + ScratchPad.recorded.should == [target_line] end end end diff --git a/ruby/spec/ruby/core/tracepoint/enabled_spec.rb b/ruby/spec/ruby/core/tracepoint/enabled_spec.rb index 0167d32fb..0e9566a02 100644 --- a/ruby/spec/ruby/core/tracepoint/enabled_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/enabled_spec.rb @@ -1,14 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#enabled?' do it 'returns true when current status of the trace is enable' do trace = TracePoint.new(:line) {} trace.enable do - trace.enabled?.should == true + trace.should.enabled? end end it 'returns false when current status of the trace is disabled' do - TracePoint.new(:line) {}.enabled?.should == false + TracePoint.new(:line) {}.should_not.enabled? end end diff --git a/ruby/spec/ruby/core/tracepoint/eval_script_spec.rb b/ruby/spec/ruby/core/tracepoint/eval_script_spec.rb index 1d8e425a9..7ec53e709 100644 --- a/ruby/spec/ruby/core/tracepoint/eval_script_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/eval_script_spec.rb @@ -1,24 +1,23 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "2.6" do - describe "TracePoint#eval_script" do - it "is the evald source code" do - ScratchPad.record [] +describe "TracePoint#eval_script" do + it "is the evald source code" do + ScratchPad.record [] - script = <<-CODE - def foo - p :hello - end - CODE - - TracePoint.new(:script_compiled) do |e| - ScratchPad << e.eval_script - end.enable do - eval script + script = <<-CODE + def foo + p :hello end + CODE - ScratchPad.recorded.should == [script] + TracePoint.new(:script_compiled) do |e| + next unless TracePointSpec.target_thread? + ScratchPad << e.eval_script + end.enable do + eval script end + + ScratchPad.recorded.should == [script] end end diff --git a/ruby/spec/ruby/core/tracepoint/event_spec.rb b/ruby/spec/ruby/core/tracepoint/event_spec.rb index 019d0c325..9dea24d12 100644 --- a/ruby/spec/ruby/core/tracepoint/event_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/event_spec.rb @@ -5,6 +5,7 @@ it 'returns the type of event' do event_name = nil TracePoint.new(:end, :call) do |tp| + next unless TracePointSpec.target_thread? event_name = tp.event end.enable do TracePointSpec.test diff --git a/ruby/spec/ruby/core/tracepoint/fixtures/classes.rb b/ruby/spec/ruby/core/tracepoint/fixtures/classes.rb index 49c70e191..3ab1b00b1 100644 --- a/ruby/spec/ruby/core/tracepoint/fixtures/classes.rb +++ b/ruby/spec/ruby/core/tracepoint/fixtures/classes.rb @@ -1,4 +1,10 @@ module TracePointSpec + @thread = Thread.current + + def self.target_thread? + Thread.current == @thread + end + class ClassWithMethodAlias def m end diff --git a/ruby/spec/ruby/core/tracepoint/inspect_spec.rb b/ruby/spec/ruby/core/tracepoint/inspect_spec.rb index 9ff1653ae..b9d7f35c3 100644 --- a/ruby/spec/ruby/core/tracepoint/inspect_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/inspect_spec.rb @@ -2,27 +2,124 @@ require_relative 'fixtures/classes' describe 'TracePoint#inspect' do + before do + ruby_version_is ""..."3.0" do + @path_prefix = '@' + end + + ruby_version_is "3.0" do + @path_prefix = ' ' + end + end + it 'returns a string containing a human-readable TracePoint status' do - TracePoint.new(:line) {}.inspect.should == - '#' + TracePoint.new(:line) {}.inspect.should == '#' end it 'returns a String showing the event, path and line' do inspect = nil - line = __LINE__ - TracePoint.new(:line) { |tp| inspect = tp.inspect }.enable do - inspect.should == "#" + line = nil + TracePoint.new(:line) { |tp| + next unless TracePointSpec.target_thread? + inspect ||= tp.inspect + }.enable do + line = __LINE__ + end + + inspect.should == "#" + end + + it 'returns a String showing the event, method, path and line for a :call event' do + inspect = nil + line = nil + TracePoint.new(:call) { |tp| + next unless TracePointSpec.target_thread? + inspect ||= tp.inspect + }.enable do + line = __LINE__ + 1 + def trace_point_spec_test_call; end + trace_point_spec_test_call + end + + inspect.should == "#" + end + + it 'returns a String showing the event, method, path and line for a :return event' do + inspect = nil + line = nil + TracePoint.new(:return) { |tp| + next unless TracePointSpec.target_thread? + inspect ||= tp.inspect + }.enable do + line = __LINE__ + 4 + def trace_point_spec_test_return + a = 1 + return a + end + trace_point_spec_test_return + end + + inspect.should == "#" + end + + it 'returns a String showing the event, method, path and line for a :c_call event' do + inspect = nil + tracepoint = TracePoint.new(:c_call) { |tp| + next unless TracePointSpec.target_thread? + inspect ||= tp.inspect + } + line = __LINE__ + 2 + tracepoint.enable do + [0, 1].max end + + inspect.should == "#" end it 'returns a String showing the event, path and line for a :class event' do inspect = nil - line = __LINE__ - TracePoint.new(:class) { |tp| inspect = tp.inspect }.enable do + line = nil + TracePoint.new(:class) { |tp| + next unless TracePointSpec.target_thread? + inspect ||= tp.inspect + }.enable do + line = __LINE__ + 1 class TracePointSpec::C end end - inspect.should == "#" + inspect.should == "#" + end + + it 'returns a String showing the event and thread for :thread_begin event' do + inspect = nil + thread = nil + thread_inspection = nil + TracePoint.new(:thread_begin) { |tp| + next unless Thread.current == thread + inspect ||= tp.inspect + }.enable do + thread = Thread.new {} + thread_inspection = thread.inspect + thread.join + end + + inspect.should == "#" + end + + it 'returns a String showing the event and thread for :thread_end event' do + inspect = nil + thread = nil + thread_inspection = nil + TracePoint.new(:thread_end) { |tp| + next unless Thread.current == thread + inspect ||= tp.inspect + }.enable do + thread = Thread.new {} + thread_inspection = thread.inspect + thread.join + end + + inspect.should == "#" end end diff --git a/ruby/spec/ruby/core/tracepoint/lineno_spec.rb b/ruby/spec/ruby/core/tracepoint/lineno_spec.rb index a4d7e77e8..77b3ac8b5 100644 --- a/ruby/spec/ruby/core/tracepoint/lineno_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/lineno_spec.rb @@ -1,10 +1,20 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#lineno' do it 'returns the line number of the event' do lineno = nil - TracePoint.new(:line) { |tp| lineno = tp.lineno }.enable do - lineno.should == 7 + TracePoint.new(:line) { |tp| + next unless TracePointSpec.target_thread? + lineno = tp.lineno + }.enable do + line_event = true end + lineno.should == __LINE__ - 2 + end + + it 'raises RuntimeError if accessed from outside' do + tp = TracePoint.new(:line) {} + -> { tp.lineno }.should raise_error(RuntimeError, 'access from outside') end end diff --git a/ruby/spec/ruby/core/tracepoint/method_id_spec.rb b/ruby/spec/ruby/core/tracepoint/method_id_spec.rb index 82254d129..43e23248b 100644 --- a/ruby/spec/ruby/core/tracepoint/method_id_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/method_id_spec.rb @@ -1,12 +1,14 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#method_id' do - def test; end - it 'returns the name at the definition of the method being called' do method_name = nil - TracePoint.new(:call) { |tp| method_name = tp.method_id}.enable do - test + TracePoint.new(:call) { |tp| + next unless TracePointSpec.target_thread? + method_name = tp.method_id + }.enable do + TracePointSpec.test method_name.should equal(:test) end end diff --git a/ruby/spec/ruby/core/tracepoint/new_spec.rb b/ruby/spec/ruby/core/tracepoint/new_spec.rb index 916d826fd..e53c2b04a 100644 --- a/ruby/spec/ruby/core/tracepoint/new_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/new_spec.rb @@ -8,7 +8,10 @@ it 'includes :line event when event is not specified' do event_name = nil - TracePoint.new() { |tp| event_name = tp.event }.enable do + TracePoint.new { |tp| + next unless TracePointSpec.target_thread? + event_name = tp.event + }.enable do event_name.should equal(:line) event_name = nil @@ -25,7 +28,10 @@ event_name = nil (o = mock('line')).should_receive(:to_sym).and_return(:line) - TracePoint.new(o) { |tp| event_name = tp.event }.enable do + TracePoint.new(o) { |tp| + next unless TracePointSpec.target_thread? + event_name = tp.event + }.enable do line_event = true event_name.should == :line end @@ -34,6 +40,7 @@ it 'includes multiple events when multiple event names are passed as params' do event_name = nil TracePoint.new(:end, :call) do |tp| + next unless TracePointSpec.target_thread? event_name = tp.event end.enable do TracePointSpec.test @@ -49,16 +56,14 @@ class TracePointSpec::B; end it 'raises a TypeError when the given object is not a string/symbol' do o = mock('123') - -> { TracePoint.new(o) {}}.should raise_error(TypeError) + -> { TracePoint.new(o) {} }.should raise_error(TypeError) o.should_receive(:to_sym).and_return(123) - -> { TracePoint.new(o) {}}.should raise_error(TypeError) + -> { TracePoint.new(o) {} }.should raise_error(TypeError) end - ruby_version_is "2.5" do - it 'expects to be called with a block' do - -> { TracePoint.new(:line) }.should raise_error(ArgumentError, "must be called with a block") - end + it 'expects to be called with a block' do + -> { TracePoint.new(:line) }.should raise_error(ArgumentError, "must be called with a block") end it "raises a Argument error when the given argument doesn't match an event name" do diff --git a/ruby/spec/ruby/core/tracepoint/parameters_spec.rb b/ruby/spec/ruby/core/tracepoint/parameters_spec.rb index f901c184f..82aee3caa 100644 --- a/ruby/spec/ruby/core/tracepoint/parameters_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/parameters_spec.rb @@ -1,23 +1,28 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' -ruby_version_is "2.6" do - describe 'TracePoint#parameters' do - it 'returns the parameters of block' do - f = proc {|x, y, z| } - parameters = nil - TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do - f.call - parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]] - end +describe 'TracePoint#parameters' do + it 'returns the parameters of block' do + f = proc {|x, y, z| } + parameters = nil + TracePoint.new(:b_call) { |tp| + next unless TracePointSpec.target_thread? + parameters = tp.parameters + }.enable do + f.call + parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]] end + end - it 'returns the parameters of lambda block' do - f = -> x, y, z { } - parameters = nil - TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do - f.call(1, 2, 3) - parameters.should == [[:req, :x], [:req, :y], [:req, :z]] - end + it 'returns the parameters of lambda block' do + f = -> x, y, z { } + parameters = nil + TracePoint.new(:b_call) { |tp| + next unless TracePointSpec.target_thread? + parameters = tp.parameters + }.enable do + f.call(1, 2, 3) + parameters.should == [[:req, :x], [:req, :y], [:req, :z]] end end end diff --git a/ruby/spec/ruby/core/tracepoint/path_spec.rb b/ruby/spec/ruby/core/tracepoint/path_spec.rb index 1e31c1bb6..5b6c6d4cf 100644 --- a/ruby/spec/ruby/core/tracepoint/path_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/path_spec.rb @@ -1,18 +1,26 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#path' do it 'returns the path of the file being run' do path = nil - TracePoint.new(:line) { |tp| path = tp.path }.enable do - path.should == "#{__FILE__}" + TracePoint.new(:line) { |tp| + next unless TracePointSpec.target_thread? + path = tp.path + }.enable do + line_event = true end + path.should == "#{__FILE__}" end it 'equals (eval) inside an eval for :end event' do path = nil - TracePoint.new(:end) { |tp| path = tp.path }.enable do + TracePoint.new(:end) { |tp| + next unless TracePointSpec.target_thread? + path = tp.path + }.enable do eval("module TracePointSpec; end") - path.should == '(eval)' end + path.should == '(eval)' end end diff --git a/ruby/spec/ruby/core/tracepoint/raised_exception_spec.rb b/ruby/spec/ruby/core/tracepoint/raised_exception_spec.rb index 450717b95..ca2f50abb 100644 --- a/ruby/spec/ruby/core/tracepoint/raised_exception_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/raised_exception_spec.rb @@ -1,9 +1,13 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#raised_exception' do it 'returns value from exception raised on the :raise event' do raised_exception, error_result = nil - trace = TracePoint.new(:raise) { |tp| raised_exception = tp.raised_exception } + trace = TracePoint.new(:raise) { |tp| + next unless TracePointSpec.target_thread? + raised_exception = tp.raised_exception + } trace.enable do begin raise StandardError diff --git a/ruby/spec/ruby/core/tracepoint/return_value_spec.rb b/ruby/spec/ruby/core/tracepoint/return_value_spec.rb index f0ed86bd0..e84c7dd76 100644 --- a/ruby/spec/ruby/core/tracepoint/return_value_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/return_value_spec.rb @@ -1,11 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint#return_value' do def test; 'test' end it 'returns value from :return event' do trace_value = nil - TracePoint.new(:return) { |tp| trace_value = tp.return_value}.enable do + TracePoint.new(:return) { |tp| + next unless TracePointSpec.target_thread? + trace_value = tp.return_value + }.enable do test trace_value.should == 'test' end diff --git a/ruby/spec/ruby/core/tracepoint/self_spec.rb b/ruby/spec/ruby/core/tracepoint/self_spec.rb index 8bfd09301..2098860e5 100644 --- a/ruby/spec/ruby/core/tracepoint/self_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/self_spec.rb @@ -4,14 +4,20 @@ describe 'TracePoint#self' do it 'return the trace object from event' do trace = nil - TracePoint.new(:line) { |tp| trace = tp.self }.enable do + TracePoint.new(:line) { |tp| + next unless TracePointSpec.target_thread? + trace = tp.self + }.enable do trace.equal?(self).should be_true end end it 'return the class object from a class event' do trace = nil - TracePoint.new(:class) { |tp| trace = tp.self }.enable do + TracePoint.new(:class) { |tp| + next unless TracePointSpec.target_thread? + trace = tp.self + }.enable do class TracePointSpec::C end end diff --git a/ruby/spec/ruby/core/tracepoint/trace_spec.rb b/ruby/spec/ruby/core/tracepoint/trace_spec.rb index ea6c85bcc..167f594bb 100644 --- a/ruby/spec/ruby/core/tracepoint/trace_spec.rb +++ b/ruby/spec/ruby/core/tracepoint/trace_spec.rb @@ -1,9 +1,10 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe 'TracePoint.trace' do it 'activates the trace automatically' do trace = TracePoint.trace(:line) {} - trace.enabled?.should == true + trace.should.enabled? trace.disable end end diff --git a/ruby/spec/ruby/core/true/case_compare_spec.rb b/ruby/spec/ruby/core/true/case_compare_spec.rb new file mode 100644 index 000000000..dee6dd022 --- /dev/null +++ b/ruby/spec/ruby/core/true/case_compare_spec.rb @@ -0,0 +1,13 @@ +require_relative '../../spec_helper' + +describe "TrueClass#===" do + it "returns true for true" do + (true === true).should == true + end + + it "returns false for non-true object" do + (true === 1).should == false + (true === "").should == false + (true === Object).should == false + end +end diff --git a/ruby/spec/ruby/core/true/to_s_spec.rb b/ruby/spec/ruby/core/true/to_s_spec.rb index 68b0052c5..f26cd138e 100644 --- a/ruby/spec/ruby/core/true/to_s_spec.rb +++ b/ruby/spec/ruby/core/true/to_s_spec.rb @@ -7,7 +7,7 @@ ruby_version_is "2.7" do it "returns a frozen string" do - true.to_s.frozen?.should == true + true.to_s.should.frozen? end it "always returns the same string" do diff --git a/ruby/spec/ruby/core/unboundmethod/shared/to_s.rb b/ruby/spec/ruby/core/unboundmethod/shared/to_s.rb index 3987611d3..38503c3c6 100644 --- a/ruby/spec/ruby/core/unboundmethod/shared/to_s.rb +++ b/ruby/spec/ruby/core/unboundmethod/shared/to_s.rb @@ -22,4 +22,13 @@ @from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/ @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/ end + + it "returns a String including all details" do + @from_module.send(@method).should.start_with? "# { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/) + end + + it "raises for non-Symbol category" do + -> { Warning[42] }.should raise_error(TypeError) + -> { Warning[false] }.should raise_error(TypeError) + -> { Warning["noop"] }.should raise_error(TypeError) + end + end +end diff --git a/ruby/spec/ruby/core/warning/element_set_spec.rb b/ruby/spec/ruby/core/warning/element_set_spec.rb new file mode 100644 index 000000000..611060fb3 --- /dev/null +++ b/ruby/spec/ruby/core/warning/element_set_spec.rb @@ -0,0 +1,37 @@ +require_relative '../../spec_helper' + +ruby_version_is '2.7' do + describe "Warning.[]=" do + it "emits and suppresses warnings for :deprecated" do + ruby_exe('Warning[:deprecated] = true; $; = ""', args: "2>&1").should =~ /is deprecated/ + ruby_exe('Warning[:deprecated] = false; $; = ""', args: "2>&1").should == "" + end + + describe ":experimental" do + before do + ruby_version_is ""..."3.0" do + @src = 'case [0, 1]; in [a, b]; end' + end + + ruby_version_is "3.0" do + @src = 'warn "This is experimental warning.", category: :experimental' + end + end + + it "emits and suppresses warnings for :experimental" do + ruby_exe("Warning[:experimental] = true; eval('#{@src}')", args: "2>&1").should =~ /is experimental/ + ruby_exe("Warning[:experimental] = false; eval('#{@src}')", args: "2>&1").should == "" + end + end + + it "raises for unknown category" do + -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/) + end + + it "raises for non-Symbol category" do + -> { Warning[42] = false }.should raise_error(TypeError) + -> { Warning[false] = false }.should raise_error(TypeError) + -> { Warning["noop"] = false }.should raise_error(TypeError) + end + end +end diff --git a/ruby/spec/ruby/core/warning/warn_spec.rb b/ruby/spec/ruby/core/warning/warn_spec.rb index 7daf6323c..5ccff3aa2 100644 --- a/ruby/spec/ruby/core/warning/warn_spec.rb +++ b/ruby/spec/ruby/core/warning/warn_spec.rb @@ -51,7 +51,31 @@ def Warning.warn(msg) end end - ruby_version_is "2.5" do + ruby_version_is '3.0' do + it "is called by Kernel.warn with nil category keyword" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose + end + end + + it "is called by Kernel.warn with given category keyword converted to a symbol" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!", category: "deprecated") + ensure + $VERBOSE = verbose + end + end + end + + ruby_version_is ''...'3.0' do it "is called by Kernel.warn" do Warning.should_receive(:warn).with("Chunky bacon!\n") verbose = $VERBOSE diff --git a/ruby/spec/ruby/default.mspec b/ruby/spec/ruby/default.mspec index 6fd6d2bf9..a0dc69c03 100644 --- a/ruby/spec/ruby/default.mspec +++ b/ruby/spec/ruby/default.mspec @@ -45,5 +45,6 @@ class MSpecScript set :toplevel_constants_excludes, [ /\wSpecs?$/, /^CS_CONST/, + /^CSL_CONST/, ] end diff --git a/ruby/spec/ruby/fixtures/code/concurrent.rb b/ruby/spec/ruby/fixtures/code/concurrent.rb index 054b8fc05..b3602a3db 100644 --- a/ruby/spec/ruby/fixtures/code/concurrent.rb +++ b/ruby/spec/ruby/fixtures/code/concurrent.rb @@ -2,7 +2,7 @@ Thread.current[:in_concurrent_rb] = true if t = Thread.current[:wait_for] - Thread.pass until t.backtrace && t.backtrace.any? { |call| call.include? 'require' } + Thread.pass until t.backtrace && t.backtrace.any? { |call| call.include? 'require' } && t.stop? end if Thread.current[:con_raise] diff --git a/ruby/spec/ruby/fixtures/code_loading.rb b/ruby/spec/ruby/fixtures/code_loading.rb index d6cf0edb4..decd56a35 100644 --- a/ruby/spec/ruby/fixtures/code_loading.rb +++ b/ruby/spec/ruby/fixtures/code_loading.rb @@ -12,7 +12,22 @@ def load(name, wrap=false) end end + def self.preload_rubygems + # Require RubyGems eagerly, to ensure #require is already the RubyGems + # version and RubyGems is only loaded once, before starting #require/#autoload specs + # which snapshot $LOADED_FEATURES and could cause RubyGems to load twice. + # #require specs also snapshot #require, and could end up redefining #require as the original core Kernel#require. + @rubygems ||= begin + require "rubygems" + true + rescue LoadError + true + end + end + def self.spec_setup + preload_rubygems + @saved_loaded_features = $LOADED_FEATURES.clone @saved_load_path = $LOAD_PATH.clone ScratchPad.record [] diff --git a/ruby/spec/ruby/fixtures/constants.rb b/ruby/spec/ruby/fixtures/constants.rb index e5b20596e..37271ddcc 100644 --- a/ruby/spec/ruby/fixtures/constants.rb +++ b/ruby/spec/ruby/fixtures/constants.rb @@ -1,7 +1,7 @@ # Contains all static code examples of all constants behavior in language and # library specs. The specs include language/constants_spec.rb and the specs -# for Module#const_defined?, Module#const_get, Module#const_set, -# Module#remove_const, Module#const_missing and Module#constants. +# for Module#const_defined?, Module#const_get, Module#const_set, Module#remove_const, +# Module#const_source_location, Module#const_missing and Module#constants. # # Rather than defining a class structure for each example, a canonical set of # classes is used along with numerous constants, in most cases, a unique @@ -28,14 +28,17 @@ # for completeness. No other constant of this name should be defined in the # specs. CS_CONST1 = :const1 # only defined here +CS_CONST1_LINE = __LINE__ - 1 module ConstantSpecs # Included at toplevel module ModuleA CS_CONST10 = :const10_1 + CS_CONST10_LINE = __LINE__ - 1 CS_CONST12 = :const12_2 CS_CONST13 = :const13 + CS_CONST13_LINE = __LINE__ - 1 CS_CONST21 = :const21_2 end @@ -44,12 +47,14 @@ module ModuleB CS_CONST10 = :const10_9 CS_CONST11 = :const11_2 CS_CONST12 = :const12_1 + CS_CONST12_LINE = __LINE__ - 1 end # Included in ChildA module ModuleC CS_CONST10 = :const10_4 CS_CONST15 = :const15_1 + CS_CONST15_LINE = __LINE__ - 1 end # Included in ChildA metaclass @@ -75,7 +80,9 @@ module ModuleD # are run. class ClassA + CS_CLASS_A_LINE = __LINE__ - 1 CS_CONST10 = :const10_10 + CS_CONST10_LINE = __LINE__ - 1 CS_CONST16 = :const16 CS_CONST17 = :const17_2 CS_CONST22 = :const22_1 @@ -97,10 +104,14 @@ class ParentA include ModuleB CS_CONST4 = :const4 + CS_CONST4_LINE = __LINE__ - 1 CS_CONST10 = :const10_5 + CS_CONST10_LINE = __LINE__ - 1 CS_CONST11 = :const11_1 + CS_CONST11_LINE = __LINE__ - 1 CS_CONST15 = :const15_2 CS_CONST20 = :const20_2 + CS_CONST20_LINE = __LINE__ - 1 CS_CONST21 = :const21_1 CS_CONST22 = :const22_2 @@ -118,6 +129,7 @@ class ContainerA CS_CONST5 = :const5 CS_CONST10 = :const10_2 + CS_CONST10_LINE = __LINE__ - 1 CS_CONST23 = :const23 class ChildA < ParentA @@ -135,6 +147,7 @@ def const19; CS_CONST19; end CS_CONST6 = :const6 CS_CONST10 = :const10_3 + CS_CONST10_LINE = __LINE__ - 1 CS_CONST19 = :const19_2 def self.const10; CS_CONST10; end @@ -282,6 +295,7 @@ class ClassD < ClassC end CS_PRIVATE = :cs_private + CS_PRIVATE_LINE = __LINE__ - 1 private_constant :CS_PRIVATE end diff --git a/ruby/spec/ruby/language/BEGIN_spec.rb b/ruby/spec/ruby/language/BEGIN_spec.rb index 58cc2bebf..5aef5a1d7 100644 --- a/ruby/spec/ruby/language/BEGIN_spec.rb +++ b/ruby/spec/ruby/language/BEGIN_spec.rb @@ -18,6 +18,11 @@ -> { eval "1.times { BEGIN { 1 } }" }.should raise_error(SyntaxError) end + it "uses top-level for self" do + eval("BEGIN { ScratchPad << self.to_s }", TOPLEVEL_BINDING) + ScratchPad.recorded.should == ['main'] + end + it "runs first in a given code unit" do eval "ScratchPad << 'foo'; BEGIN { ScratchPad << 'bar' }" diff --git a/ruby/spec/ruby/language/END_spec.rb b/ruby/spec/ruby/language/END_spec.rb new file mode 100644 index 000000000..762a8db0c --- /dev/null +++ b/ruby/spec/ruby/language/END_spec.rb @@ -0,0 +1,15 @@ +require_relative '../spec_helper' + +describe "The END keyword" do + it "runs only once for multiple calls" do + ruby_exe("10.times { END { puts 'foo' }; } ").should == "foo\n" + end + + it "runs last in a given code unit" do + ruby_exe("END { puts 'bar' }; puts'foo'; ").should == "foo\nbar\n" + end + + it "runs multiple ends in LIFO order" do + ruby_exe("END { puts 'foo' }; END { puts 'bar' }").should == "bar\nfoo\n" + end +end diff --git a/ruby/spec/ruby/language/README b/ruby/spec/ruby/language/README index 74eaf5870..ae08e17fb 100644 --- a/ruby/spec/ruby/language/README +++ b/ruby/spec/ruby/language/README @@ -4,7 +4,7 @@ words. These words significantly describe major elements of the language, including flow control constructs like 'for' and 'while', conditional execution like 'if' and 'unless', exceptional execution control like 'rescue', etc. There are also literals for the basic "types" like String, Regexp, Array -and Fixnum. +and Integer. Behavioral specifications describe the behavior of concrete entities. Rather than using concepts of computation to organize these spec files, we use diff --git a/ruby/spec/ruby/language/alias_spec.rb b/ruby/spec/ruby/language/alias_spec.rb index 79348f70c..d1d06e3fa 100644 --- a/ruby/spec/ruby/language/alias_spec.rb +++ b/ruby/spec/ruby/language/alias_spec.rb @@ -218,7 +218,7 @@ def test_with_check(*args) subclass.new.test("testing").should == 4 end - it "is not allowed against Fixnum or String instances" do + it "is not allowed against Integer or String instances" do -> do 1.instance_eval do alias :foo :to_s @@ -255,4 +255,9 @@ def test_with_check(*args) code = '$a = 1; $b = 2; alias $b $a; p [$a, $b]; $b = 3; p [$a, $b]' ruby_exe(code).should == "[1, 1]\n[3, 3]\n" end + + it "supports aliasing twice the same global variables" do + code = '$a = 1; alias $b $a; alias $b $a; p [$a, $b]' + ruby_exe(code).should == "[1, 1]\n" + end end diff --git a/ruby/spec/ruby/language/block_spec.rb b/ruby/spec/ruby/language/block_spec.rb index 6f92383af..b2a3cc84c 100644 --- a/ruby/spec/ruby/language/block_spec.rb +++ b/ruby/spec/ruby/language/block_spec.rb @@ -44,27 +44,51 @@ def m(a) yield a end m([1, 2]) { |a, **k| [a, k] }.should == [1, {}] end - it "assigns elements to mixed argument types" do - suppress_keyword_warning do - result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] } - result.should == [1, 2, [], 3, 2, {x: 9}] + ruby_version_is ''..."3.0" do + it "assigns elements to mixed argument types" do + suppress_keyword_warning do + result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] } + result.should == [1, 2, [], 3, 2, {x: 9}] + end + end + + it "assigns symbol keys from a Hash to keyword arguments" do + suppress_keyword_warning do + result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] } + result.should == [{"a" => 1}, a: 10] + end + end + + it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do + suppress_keyword_warning do + obj = mock("coerce block keyword arguments") + obj.should_receive(:to_hash).and_return({"a" => 1, b: 2}) + + result = m([obj]) { |a=nil, **b| [a, b] } + result.should == [{"a" => 1}, b: 2] + end end end - it "assigns symbol keys from a Hash to keyword arguments" do - suppress_keyword_warning do + ruby_version_is "3.0" do + it "assigns elements to mixed argument types" do + result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] } + result.should == [1, 2, [3], {x: 9}, 2, {}] + end + + it "does not treat final Hash as keyword arguments and does not autosplat" do result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 1}, a: 10] + result.should == [[{"a" => 1, a: 10}], {}] end - end - it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do - suppress_keyword_warning do - obj = mock("coerce block keyword arguments") - obj.should_receive(:to_hash).and_return({"a" => 1, b: 2}) + it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do + suppress_keyword_warning do + obj = mock("coerce block keyword arguments") + obj.should_not_receive(:to_hash) - result = m([obj]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 1}, b: 2] + result = m([obj]) { |a=nil, **b| [a, b] } + result.should == [[obj], {}] + end end end @@ -78,7 +102,7 @@ def m(a) yield a end end end - ruby_version_is "2.7" do + ruby_version_is "2.7"...'3.0' do it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do obj = mock("coerce block keyword arguments") obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2}) @@ -88,65 +112,114 @@ def m(a) yield a end end end + ruby_version_is "3.0" do + it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do + obj = mock("coerce block keyword arguments") + obj.should_not_receive(:to_hash) + + result = m([obj]) { |a=nil, **b| [a, b] } + result.should == [[obj], {}] + end + end + describe "when non-symbol keys are in a keyword arguments Hash" do - it "separates non-symbol keys and symbol keys" do - suppress_keyword_warning do - result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 10}, {b: 2}] + ruby_version_is ""..."3.0" do + it "separates non-symbol keys and symbol keys" do + suppress_keyword_warning do + result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] } + result.should == [{"a" => 10}, {b: 2}] + end + end + end + ruby_version_is "3.0" do + it "does not separate non-symbol keys and symbol keys and does not autosplat" do + suppress_keyword_warning do + result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] } + result.should == [[{"a" => 10, b: 2}], {}] + end end end end - it "does not treat hashes with string keys as keyword arguments" do - result = m(["a" => 10]) { |a = nil, **b| [a, b] } - result.should == [{"a" => 10}, {}] + ruby_version_is ""..."3.0" do + it "does not treat hashes with string keys as keyword arguments" do + result = m(["a" => 10]) { |a = nil, **b| [a, b] } + result.should == [{"a" => 10}, {}] + end + end + + ruby_version_is "3.0" do + it "does not treat hashes with string keys as keyword arguments and does not autosplat" do + result = m(["a" => 10]) { |a = nil, **b| [a, b] } + result.should == [[{"a" => 10}], {}] + end end - it "calls #to_hash on the last element if keyword arguments are present" do - suppress_keyword_warning do + ruby_version_is ''...'3.0' do + it "calls #to_hash on the last element if keyword arguments are present" do + suppress_keyword_warning do + obj = mock("destructure block keyword arguments") + obj.should_receive(:to_hash).and_return({x: 9}) + + result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } + result.should == [1, [2], 3, {x: 9}] + end + end + + it "assigns the last element to a non-keyword argument if #to_hash returns nil" do + suppress_keyword_warning do + obj = mock("destructure block keyword arguments") + obj.should_receive(:to_hash).and_return(nil) + + result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } + result.should == [1, [2, 3], obj, {}] + end + end + + it "calls #to_hash on the last element when there are more arguments than parameters" do + suppress_keyword_warning do + x = mock("destructure matching block keyword argument") + x.should_receive(:to_hash).and_return({x: 9}) + + result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] } + result.should == [1, 2, 3, {x: 9}] + end + end + + it "raises a TypeError if #to_hash does not return a Hash" do obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return({x: 9}) + obj.should_receive(:to_hash).and_return(1) - result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } - result.should == [1, [2], 3, {x: 9}] + -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError) + end + + it "raises the error raised inside #to_hash" do + obj = mock("destructure block keyword arguments") + error = RuntimeError.new("error while converting to a hash") + obj.should_receive(:to_hash).and_raise(error) + + -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error) end end - it "assigns the last element to a non-keyword argument if #to_hash returns nil" do - suppress_keyword_warning do + ruby_version_is '3.0' do + it "does not call #to_hash on the last element if keyword arguments are present" do obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return(nil) + obj.should_not_receive(:to_hash) result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } result.should == [1, [2, 3], obj, {}] end - end - it "calls #to_hash on the last element when there are more arguments than parameters" do - suppress_keyword_warning do + it "does not call #to_hash on the last element when there are more arguments than parameters" do x = mock("destructure matching block keyword argument") - x.should_receive(:to_hash).and_return({x: 9}) + x.should_not_receive(:to_hash) result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] } - result.should == [1, 2, 3, {x: 9}] + result.should == [1, 2, 3, {}] end end - it "raises a TypeError if #to_hash does not return a Hash" do - obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return(1) - - -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError) - end - - it "raises the error raised inside #to_hash" do - obj = mock("destructure block keyword arguments") - error = RuntimeError.new("error while converting to a hash") - obj.should_receive(:to_hash).and_raise(error) - - -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error) - end - it "does not call #to_ary on the Array" do ary = [1, 2] ary.should_not_receive(:to_ary) @@ -244,10 +317,8 @@ def m(a) yield a end @y.s(0) { 1 }.should == 1 end - ruby_version_is "2.5" do - it "may include a rescue clause" do - eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7 - end + it "may include a rescue clause" do + eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7 end end @@ -260,10 +331,8 @@ def m(a) yield a end @y.s(0) { || 1 }.should == 1 end - ruby_version_is "2.5" do - it "may include a rescue clause" do - eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7 - end + it "may include a rescue clause" do + eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7 end end @@ -291,10 +360,8 @@ def m(a) yield a end @y.s([1, 2]) { |a| a }.should == [1, 2] end - ruby_version_is "2.5" do - it "may include a rescue clause" do - eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7 - end + it "may include a rescue clause" do + eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7 end end @@ -806,7 +873,7 @@ def m(a) yield a end end.call(1, 2, 3).should == [[], 1, 2, 3] end - it "are required" do + it "are required for a lambda" do -> { -> *a, b do [a, b] @@ -814,6 +881,12 @@ def m(a) yield a end }.should raise_error(ArgumentError) end + it "are assigned to nil when not enough arguments are given to a proc" do + proc do |a, *b, c| + [a, b, c] + end.call.should == [nil, [], nil] + end + describe "with required args" do it "gathers remaining args in the splat" do diff --git a/ruby/spec/ruby/language/break_spec.rb b/ruby/spec/ruby/language/break_spec.rb index 754d5d3c4..627cb4a07 100644 --- a/ruby/spec/ruby/language/break_spec.rb +++ b/ruby/spec/ruby/language/break_spec.rb @@ -362,4 +362,22 @@ def three bt2.three ScratchPad.recorded.should == [:two_ensure, :three_post, :three_ensure] end + + it "works when passing through a super call" do + cls1 = Class.new { def foo; yield; end } + cls2 = Class.new(cls1) { def foo; super { break 1 }; end } + + -> do + cls2.new.foo.should == 1 + end.should_not raise_error + end + + it "raises LocalJumpError when converted into a proc during a a super call" do + cls1 = Class.new { def foo(&b); b; end } + cls2 = Class.new(cls1) { def foo; super { break 1 }.call; end } + + -> do + cls2.new.foo + end.should raise_error(LocalJumpError) + end end diff --git a/ruby/spec/ruby/language/case_spec.rb b/ruby/spec/ruby/language/case_spec.rb index 1475e20f7..410cb9afb 100644 --- a/ruby/spec/ruby/language/case_spec.rb +++ b/ruby/spec/ruby/language/case_spec.rb @@ -424,4 +424,13 @@ def ===(o) :called end.should == :called end + + # Homogeneous cases are often optimized to avoid === using a jump table, and should be tested separately. + # See https://github.com/jruby/jruby/issues/6440 + it "handles homogeneous cases" do + case + when 1; 'foo' + when 2; 'bar' + end.should == 'foo' + end end diff --git a/ruby/spec/ruby/language/class_spec.rb b/ruby/spec/ruby/language/class_spec.rb index 88b7a6a74..83db164e1 100644 --- a/ruby/spec/ruby/language/class_spec.rb +++ b/ruby/spec/ruby/language/class_spec.rb @@ -285,6 +285,16 @@ def xyz }.should raise_error(TypeError) end + it "raises a TypeError when trying to extend non-Class" do + error_msg = /superclass must be a.* Class/ + -> { class TestClass < ""; end }.should raise_error(TypeError, error_msg) + -> { class TestClass < 1; end }.should raise_error(TypeError, error_msg) + -> { class TestClass < :symbol; end }.should raise_error(TypeError, error_msg) + -> { class TestClass < mock('o'); end }.should raise_error(TypeError, error_msg) + -> { class TestClass < Module.new; end }.should raise_error(TypeError, error_msg) + -> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg) + end + ruby_version_is ""..."3.0" do it "allows accessing the block of the original scope" do suppress_warning do @@ -293,6 +303,14 @@ def xyz end end + ruby_version_is "3.0" do + it "does not allow accessing the block of the original scope" do + -> { + ClassSpecs.sclass_with_block { 123 } + }.should raise_error(SyntaxError) + end + end + it "can use return to cause the enclosing method to return" do ClassSpecs.sclass_with_return.should == :inner end diff --git a/ruby/spec/ruby/language/class_variable_spec.rb b/ruby/spec/ruby/language/class_variable_spec.rb index dffab47a6..f98deaa08 100644 --- a/ruby/spec/ruby/language/class_variable_spec.rb +++ b/ruby/spec/ruby/language/class_variable_spec.rb @@ -82,3 +82,35 @@ c.class_variable_get(:@@cv).should == :next end end + +ruby_version_is "3.0" do + describe 'Accessing a class variable' do + it "raises a RuntimeError when accessed from the toplevel scope (not in some module or class)" do + -> { + eval "@@cvar_toplevel1" + }.should raise_error(RuntimeError, 'class variable access from toplevel') + -> { + eval "@@cvar_toplevel2 = 2" + }.should raise_error(RuntimeError, 'class variable access from toplevel') + end + + it "does not raise an error when checking if defined from the toplevel scope" do + -> { + eval "defined?(@@cvar_toplevel1)" + }.should_not raise_error + end + + it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do + parent = Class.new() + subclass = Class.new(parent) + subclass.class_variable_set(:@@cvar_overtaken, :subclass) + parent.class_variable_set(:@@cvar_overtaken, :parent) + + -> { + subclass.class_variable_get(:@@cvar_overtaken) + }.should raise_error(RuntimeError, /class variable @@cvar_overtaken of .+ is overtaken by .+/) + + parent.class_variable_get(:@@cvar_overtaken).should == :parent + end + end +end diff --git a/ruby/spec/ruby/language/comment_spec.rb b/ruby/spec/ruby/language/comment_spec.rb new file mode 100644 index 000000000..690e844dc --- /dev/null +++ b/ruby/spec/ruby/language/comment_spec.rb @@ -0,0 +1,15 @@ +require_relative '../spec_helper' + +describe "The comment" do + ruby_version_is "2.7" do + it "can be placed between fluent dot now" do + code = <<~CODE + 10 + # some comment + .to_s + CODE + + eval(code).should == '10' + end + end +end diff --git a/ruby/spec/ruby/language/constants_spec.rb b/ruby/spec/ruby/language/constants_spec.rb index c4cf940cb..03f127240 100644 --- a/ruby/spec/ruby/language/constants_spec.rb +++ b/ruby/spec/ruby/language/constants_spec.rb @@ -154,6 +154,36 @@ module ConstantSpecsRHS; end -> { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError) end + ruby_version_is "3.0" do + it "uses the module or class #name to craft the error message" do + mod = Module.new do + def self.name + "ModuleName" + end + + def self.inspect + "" + end + end + + -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/) + end + + it "uses the module or class #inspect to craft the error message if they are anonymous" do + mod = Module.new do + def self.name + nil + end + + def self.inspect + "" + end + end + + -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ::DOES_NOT_EXIST/) + end + end + it "sends #const_missing to the original class or module scope" do ConstantSpecs::ClassA::CS_CONSTX.should == :CS_CONSTX end @@ -351,52 +381,6 @@ class << self ConstantSpecs::ClassA.constx.should == :CS_CONSTX ConstantSpecs::ClassA.new.constx.should == :CS_CONSTX end - - describe "with ||=" do - it "assigns a scoped constant if previously undefined" do - ConstantSpecs.should_not have_constant(:OpAssignUndefined) - module ConstantSpecs - OpAssignUndefined ||= 42 - end - ConstantSpecs::OpAssignUndefined.should == 42 - ConstantSpecs::OpAssignUndefinedOutside ||= 42 - ConstantSpecs::OpAssignUndefinedOutside.should == 42 - ConstantSpecs.send(:remove_const, :OpAssignUndefined) - ConstantSpecs.send(:remove_const, :OpAssignUndefinedOutside) - end - - it "assigns a global constant if previously undefined" do - OpAssignGlobalUndefined ||= 42 - ::OpAssignGlobalUndefinedExplicitScope ||= 42 - OpAssignGlobalUndefined.should == 42 - ::OpAssignGlobalUndefinedExplicitScope.should == 42 - Object.send :remove_const, :OpAssignGlobalUndefined - Object.send :remove_const, :OpAssignGlobalUndefinedExplicitScope - end - - end - - describe "with &&=" do - it "re-assigns a scoped constant if already true" do - module ConstantSpecs - OpAssignTrue = true - end - suppress_warning do - ConstantSpecs::OpAssignTrue &&= 1 - end - ConstantSpecs::OpAssignTrue.should == 1 - ConstantSpecs.send :remove_const, :OpAssignTrue - end - - it "leaves scoped constant if not true" do - module ConstantSpecs - OpAssignFalse = false - end - ConstantSpecs::OpAssignFalse &&= 1 - ConstantSpecs::OpAssignFalse.should == false - ConstantSpecs.send :remove_const, :OpAssignFalse - end - end end describe "Constant resolution within a singleton class (class << obj)" do @@ -425,18 +409,8 @@ module ConstantSpecs describe "top-level constant lookup" do context "on a class" do - ruby_version_is "" ... "2.5" do - it "searches Object successfully after searching other scopes" do - -> { - String::Hash.should == Hash - }.should complain(/toplevel constant Hash referenced by/) - end - end - - ruby_version_is "2.5" do - it "does not search Object after searching other scopes" do - -> { String::Hash }.should raise_error(NameError) - end + it "does not search Object after searching other scopes" do + -> { String::Hash }.should raise_error(NameError) end end @@ -458,17 +432,15 @@ module ConstantSpecs -> {mod::Foo}.should raise_error(NameError) end - ruby_version_is "2.6" do - it "sends #const_missing to the original class or module" do - mod = Module.new - mod.const_set :Foo, true - mod.send :private_constant, :Foo - def mod.const_missing(name) - name == :Foo ? name : super - end - - mod::Foo.should == :Foo + it "sends #const_missing to the original class or module" do + mod = Module.new + mod.const_set :Foo, true + mod.send :private_constant, :Foo + def mod.const_missing(name) + name == :Foo ? name : super end + + mod::Foo.should == :Foo end describe "in a module" do @@ -531,11 +503,24 @@ class PrivateClass end it "can be accessed from classes that include the module" do - ConstantVisibility::PrivConstModuleChild.new.private_constant_from_include.should be_true + ConstantVisibility::ClassIncludingPrivConstModule.new.private_constant_from_include.should be_true + end + + it "can be accessed from modules that include the module" do + ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_from_include.should be_true + end + + it "raises a NameError when accessed directly from modules that include the module" do + -> do + ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_self_from_include + end.should raise_error(NameError) + -> do + ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_named_from_include + end.should raise_error(NameError) end it "is defined? from classes that include the module" do - ConstantVisibility::PrivConstModuleChild.new.defined_from_include.should == "constant" + ConstantVisibility::ClassIncludingPrivConstModule.new.defined_from_include.should == "constant" end end @@ -653,7 +638,7 @@ class PrivateClass } -> do - ConstantVisibility::PrivConstModuleChild::PRIVATE_CONSTANT_MODULE + ConstantVisibility::ClassIncludingPrivConstModule::PRIVATE_CONSTANT_MODULE end.should raise_error(NameError) {|e| e.receiver.should == ConstantVisibility::PrivConstModule e.name.should == :PRIVATE_CONSTANT_MODULE @@ -726,20 +711,10 @@ class PrivateClass end.should raise_error(NameError, /wrong constant name/) end - ruby_version_is ""..."2.6" do - it 'does not allow not ASCII upcased characters at the beginning' do - -> do - Module.new.const_set("á¼BB", 1) - end.should raise_error(NameError, /wrong constant name/) - end - end - - ruby_version_is "2.6" do - it 'allows not ASCII upcased characters at the beginning' do - mod = Module.new - mod.const_set("á¼BB", 1) + it 'allows not ASCII upcased characters at the beginning' do + mod = Module.new + mod.const_set("á¼BB", 1) - eval("mod::á¼BB").should == 1 - end + eval("mod::á¼BB").should == 1 end end diff --git a/ruby/spec/ruby/language/def_spec.rb b/ruby/spec/ruby/language/def_spec.rb index fc5693a2f..6b0be19d9 100644 --- a/ruby/spec/ruby/language/def_spec.rb +++ b/ruby/spec/ruby/language/def_spec.rb @@ -89,6 +89,26 @@ def foo(a, b); end def foo(a); end -> { foo 1, 2 }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') end + + it "raises FrozenError with the correct class name" do + -> { + Module.new do + self.freeze + def foo; end + end + }.should raise_error(FrozenError) { |e| + e.message.should.start_with? "can't modify frozen module" + } + + -> { + Class.new do + self.freeze + def foo; end + end + }.should raise_error(FrozenError){ |e| + e.message.should.start_with? "can't modify frozen class" + } + end end describe "An instance method definition with a splat" do @@ -261,10 +281,29 @@ def obj.==(other) (obj==2).should == 2 end - it "raises #{frozen_error_class} if frozen" do + it "raises FrozenError if frozen" do + obj = Object.new + obj.freeze + -> { def obj.foo; end }.should raise_error(FrozenError) + end + + it "raises FrozenError with the correct class name" do obj = Object.new obj.freeze - -> { def obj.foo; end }.should raise_error(frozen_error_class) + -> { def obj.foo; end }.should raise_error(FrozenError){ |e| + e.message.should.start_with? "can't modify frozen object" + } + + c = obj.singleton_class + -> { def c.foo; end }.should raise_error(FrozenError){ |e| + e.message.should.start_with? "can't modify frozen Class" + } + + m = Module.new + m.freeze + -> { def m.foo; end }.should raise_error(FrozenError){ |e| + e.message.should.start_with? "can't modify frozen Module" + } end end @@ -412,12 +451,12 @@ def a_singleton_method;self;end -> { Object.new.a_singleton_method }.should raise_error(NoMethodError) end - it "raises #{frozen_error_class} if frozen" do + it "raises FrozenError if frozen" do obj = Object.new obj.freeze class << obj - -> { def foo; end }.should raise_error(frozen_error_class) + -> { def foo; end }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/language/defined_spec.rb b/ruby/spec/ruby/language/defined_spec.rb index 02c69d27b..38345c372 100644 --- a/ruby/spec/ruby/language/defined_spec.rb +++ b/ruby/spec/ruby/language/defined_spec.rb @@ -5,21 +5,25 @@ it "returns 'self' for self" do ret = defined?(self) ret.should == "self" + ret.frozen?.should == true end it "returns 'nil' for nil" do ret = defined?(nil) ret.should == "nil" + ret.frozen?.should == true end it "returns 'true' for true" do ret = defined?(true) ret.should == "true" + ret.frozen?.should == true end it "returns 'false' for false" do ret = defined?(false) ret.should == "false" + ret.frozen?.should == true end describe "for a literal Array" do @@ -27,6 +31,7 @@ it "returns 'expression' if each element is defined" do ret = defined?([Object, Array]) ret.should == "expression" + ret.frozen?.should == true end it "returns nil if one element is not defined" do @@ -45,7 +50,9 @@ describe "The defined? keyword when called with a method name" do describe "without a receiver" do it "returns 'method' if the method is defined" do - defined?(puts).should == "method" + ret = defined?(puts) + ret.should == "method" + ret.frozen?.should == true end it "returns nil if the method is not defined" do @@ -167,7 +174,9 @@ end it "returns 'assignment' for assigning a local variable" do - defined?(x = 2).should == "assignment" + ret = defined?(x = 2) + ret.should == "assignment" + ret.frozen?.should == true end it "returns 'assignment' for assigning an instance variable" do @@ -275,9 +284,7 @@ end it "returns nil for an expression with '!' and an unset class variable" do - -> { - @result = defined?(!@@defined_specs_undefined_class_variable) - }.should complain(/class variable access from toplevel/) + @result = eval("class singleton_class::A; defined?(!@@doesnt_exist) end", binding, __FILE__, __LINE__) @result.should be_nil end @@ -286,9 +293,7 @@ end it "returns nil for an expression with 'not' and an unset class variable" do - -> { - @result = defined?(not @@defined_specs_undefined_class_variable) - }.should complain(/class variable access from toplevel/) + @result = eval("class singleton_class::A; defined?(not @@doesnt_exist) end", binding, __FILE__, __LINE__) @result.should be_nil end @@ -474,7 +479,9 @@ describe "The defined? keyword for variables" do it "returns 'local-variable' when called with the name of a local variable" do - DefinedSpecs::Basic.new.local_variable_defined.should == "local-variable" + ret = DefinedSpecs::Basic.new.local_variable_defined + ret.should == "local-variable" + ret.frozen?.should == true end it "returns 'local-variable' when called with the name of a local variable assigned to nil" do @@ -490,7 +497,9 @@ end it "returns 'instance-variable' for an instance variable that has been assigned" do - DefinedSpecs::Basic.new.instance_variable_defined.should == "instance-variable" + ret = DefinedSpecs::Basic.new.instance_variable_defined + ret.should == "instance-variable" + ret.frozen?.should == true end it "returns 'instance-variable' for an instance variable that has been assigned to nil" do @@ -506,7 +515,9 @@ end it "returns 'global-variable' for a global variable that has been assigned nil" do - DefinedSpecs::Basic.new.global_variable_defined_as_nil.should == "global-variable" + ret = DefinedSpecs::Basic.new.global_variable_defined_as_nil + ret.should == "global-variable" + ret.frozen?.should == true end # MRI appears to special case defined? for $! and $~ in that it returns @@ -678,7 +689,9 @@ # get to the defined? call so it really has nothing to do with 'defined?'. it "returns 'class variable' when called with the name of a class variable" do - DefinedSpecs::Basic.new.class_variable_defined.should == "class variable" + ret = DefinedSpecs::Basic.new.class_variable_defined + ret.should == "class variable" + ret.frozen?.should == true end it "returns 'local-variable' when called with the name of a block local" do @@ -689,7 +702,9 @@ describe "The defined? keyword for a simple constant" do it "returns 'constant' when the constant is defined" do - defined?(DefinedSpecs).should == "constant" + ret = defined?(DefinedSpecs) + ret.should == "constant" + ret.frozen?.should == true end it "returns nil when the constant is not defined" do @@ -756,16 +771,8 @@ defined?(DefinedSpecs::String).should be_nil end - ruby_version_is ""..."2.5" do - it "returns 'constant' when a constant is defined on top-level but not on the class" do - defined?(DefinedSpecs::Basic::String).should == 'constant' - end - end - - ruby_version_is "2.5" do - it "returns nil when a constant is defined on top-level but not on the class" do - defined?(DefinedSpecs::Basic::String).should be_nil - end + it "returns nil when a constant is defined on top-level but not on the class" do + defined?(DefinedSpecs::Basic::String).should be_nil end it "returns 'constant' if the scoped-scoped constant is defined" do @@ -905,17 +912,21 @@ end it "returns nil if the class scoped constant is not defined" do - -> { - @@defined_specs_obj = DefinedSpecs::Basic - defined?(@@defined_specs_obj::Undefined).should be_nil - }.should complain(/class variable access from toplevel/) + eval(<<-END, binding, __FILE__, __LINE__) + class singleton_class::A + @@defined_specs_obj = DefinedSpecs::Basic + defined?(@@defined_specs_obj::Undefined).should be_nil + end + END end it "returns 'constant' if the constant is defined in the scope of the class variable" do - -> { - @@defined_specs_obj = DefinedSpecs::Basic - defined?(@@defined_specs_obj::A).should == "constant" - }.should complain(/class variable access from toplevel/) + eval(<<-END, binding, __FILE__, __LINE__) + class singleton_class::A + @@defined_specs_obj = DefinedSpecs::Basic + defined?(@@defined_specs_obj::A).should == "constant" + end + END end it "returns nil if the local scoped constant is not defined" do @@ -949,12 +960,26 @@ end it "returns 'yield' if a block is passed to a method not taking a block parameter" do - DefinedSpecs::Basic.new.yield_block.should == "yield" + ret = DefinedSpecs::Basic.new.yield_block + ret.should == "yield" + ret.frozen?.should == true end it "returns 'yield' if a block is passed to a method taking a block parameter" do DefinedSpecs::Basic.new.yield_block_parameter.should == "yield" end + + it "returns 'yield' when called within a block" do + def yielder + yield + end + + def call_defined + yielder { defined?(yield) } + end + + call_defined() { }.should == "yield" + end end describe "The defined? keyword for super" do @@ -980,7 +1005,9 @@ end it "returns 'super' when a superclass method exists" do - DefinedSpecs::Super.new.method_no_args.should == "super" + ret = DefinedSpecs::Super.new.method_no_args + ret.should == "super" + ret.frozen?.should == true end it "returns 'super' from a block when a superclass method exists" do diff --git a/ruby/spec/ruby/language/delegation_spec.rb b/ruby/spec/ruby/language/delegation_spec.rb new file mode 100644 index 000000000..8e4183cbc --- /dev/null +++ b/ruby/spec/ruby/language/delegation_spec.rb @@ -0,0 +1,68 @@ +require_relative '../spec_helper' +require_relative 'fixtures/delegation' + +ruby_version_is "2.7" do + describe "delegation with def(...)" do + it "delegates rest and kwargs" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate(...) + target(...) + end + RUBY + + a.new.delegate(1, b: 2).should == [[1], {b: 2}] + end + + it "delegates block" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate_block(...) + target_block(...) + end + RUBY + + a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]] + end + + it "parses as open endless Range when brackets are omitted" do + a = Class.new(DelegationSpecs::Target) + suppress_warning do + a.class_eval(<<-RUBY) + def delegate(...) + target ... + end + RUBY + end + + a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true) + end + end +end + +ruby_version_is "2.7.3" do + describe "delegation with def(x, ...)" do + it "delegates rest and kwargs" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate(x, ...) + target(...) + end + RUBY + + a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}] + end + + it "delegates block" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate_block(x, ...) + target_block(...) + end + RUBY + + a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]] + end + + end +end diff --git a/ruby/spec/ruby/language/ensure_spec.rb b/ruby/spec/ruby/language/ensure_spec.rb index a930bda36..e893904bc 100644 --- a/ruby/spec/ruby/language/ensure_spec.rb +++ b/ruby/spec/ruby/language/ensure_spec.rb @@ -74,9 +74,9 @@ ensure raise "from ensure" end - }.should raise_error(RuntimeError, "from ensure") do |e| + }.should raise_error(RuntimeError, "from ensure") { |e| e.cause.message.should == "from block" - end + } end end @@ -251,83 +251,81 @@ class EnsureInClassExample end end -ruby_version_is "2.5" do - describe "An ensure block inside 'do end' block" do - before :each do - ScratchPad.record [] - end - - it "is executed when an exception is raised in it's corresponding begin block" do - -> { - eval(<<-ruby).call - lambda do - ScratchPad << :begin - raise EnsureSpec::Error - ensure - ScratchPad << :ensure - end - ruby - }.should raise_error(EnsureSpec::Error) - - ScratchPad.recorded.should == [:begin, :ensure] - end +describe "An ensure block inside 'do end' block" do + before :each do + ScratchPad.record [] + end - it "is executed when an exception is raised and rescued in it's corresponding begin block" do + it "is executed when an exception is raised in it's corresponding begin block" do + -> { eval(<<-ruby).call lambda do ScratchPad << :begin - raise "An exception occurred!" - rescue - ScratchPad << :rescue + raise EnsureSpec::Error ensure ScratchPad << :ensure end ruby + }.should raise_error(EnsureSpec::Error) - ScratchPad.recorded.should == [:begin, :rescue, :ensure] - end + ScratchPad.recorded.should == [:begin, :ensure] + end - it "is executed even when a symbol is thrown in it's corresponding begin block" do - catch(:symbol) do - eval(<<-ruby).call - lambda do - ScratchPad << :begin - throw(:symbol) - rescue - ScratchPad << :rescue - ensure - ScratchPad << :ensure - end - ruby + it "is executed when an exception is raised and rescued in it's corresponding begin block" do + eval(<<-ruby).call + lambda do + ScratchPad << :begin + raise "An exception occurred!" + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure end + ruby - ScratchPad.recorded.should == [:begin, :ensure] - end + ScratchPad.recorded.should == [:begin, :rescue, :ensure] + end - it "is executed when nothing is raised or thrown in it's corresponding begin block" do + it "is executed even when a symbol is thrown in it's corresponding begin block" do + catch(:symbol) do eval(<<-ruby).call lambda do ScratchPad << :begin + throw(:symbol) rescue ScratchPad << :rescue ensure ScratchPad << :ensure end ruby - - ScratchPad.recorded.should == [:begin, :ensure] end - it "has no return value" do - result = eval(<<-ruby).call - lambda do - :begin - ensure - :ensure - end - ruby + ScratchPad.recorded.should == [:begin, :ensure] + end - result.should == :begin - end + it "is executed when nothing is raised or thrown in it's corresponding begin block" do + eval(<<-ruby).call + lambda do + ScratchPad << :begin + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + + ScratchPad.recorded.should == [:begin, :ensure] + end + + it "has no return value" do + result = eval(<<-ruby).call + lambda do + :begin + ensure + :ensure + end + ruby + + result.should == :begin end end diff --git a/ruby/spec/ruby/language/fixtures/constant_visibility.rb b/ruby/spec/ruby/language/fixtures/constant_visibility.rb index 022554430..af38b2d8f 100644 --- a/ruby/spec/ruby/language/fixtures/constant_visibility.rb +++ b/ruby/spec/ruby/language/fixtures/constant_visibility.rb @@ -65,7 +65,7 @@ def self.defined_from_scope end end - class PrivConstModuleChild + class ClassIncludingPrivConstModule include PrivConstModule def private_constant_from_include @@ -77,6 +77,22 @@ def defined_from_include end end + module ModuleIncludingPrivConstModule + include PrivConstModule + + def self.private_constant_from_include + PRIVATE_CONSTANT_MODULE + end + + def self.private_constant_self_from_include + self::PRIVATE_CONSTANT_MODULE + end + + def self.private_constant_named_from_include + PrivConstModule::PRIVATE_CONSTANT_MODULE + end + end + class PrivConstClassChild < PrivConstClass def private_constant_from_subclass PRIVATE_CONSTANT_CLASS diff --git a/ruby/spec/ruby/language/fixtures/delegation.rb b/ruby/spec/ruby/language/fixtures/delegation.rb new file mode 100644 index 000000000..527d92839 --- /dev/null +++ b/ruby/spec/ruby/language/fixtures/delegation.rb @@ -0,0 +1,11 @@ +module DelegationSpecs + class Target + def target(*args, **kwargs) + [args, kwargs] + end + + def target_block(*args, **kwargs) + yield [kwargs, args] + end + end +end diff --git a/ruby/spec/ruby/language/fixtures/rescue_captures.rb b/ruby/spec/ruby/language/fixtures/rescue_captures.rb new file mode 100644 index 000000000..69f9b8390 --- /dev/null +++ b/ruby/spec/ruby/language/fixtures/rescue_captures.rb @@ -0,0 +1,107 @@ +module RescueSpecs + class Captor + attr_accessor :captured_error + + def self.should_capture_exception + captor = new + captor.capture('some text').should == :caught # Ensure rescue body still runs + captor.captured_error.message.should == 'some text' + end + end + + class ClassVariableCaptor < Captor + def capture(msg) + raise msg + rescue => @@captured_error + :caught + end + + def captured_error + self.class.remove_class_variable(:@@captured_error) + end + end + + class ConstantCaptor < Captor + # Using lambda gets around the dynamic constant assignment warning + CAPTURE = -> msg { + begin + raise msg + rescue => CapturedError + :caught + end + } + + def capture(msg) + CAPTURE.call(msg) + end + + def captured_error + self.class.send(:remove_const, :CapturedError) + end + end + + class GlobalVariableCaptor < Captor + def capture(msg) + raise msg + rescue => $captured_error + :caught + end + + def captured_error + $captured_error.tap do + $captured_error = nil # Can't remove globals, only nil them out + end + end + end + + class InstanceVariableCaptor < Captor + def capture(msg) + raise msg + rescue => @captured_error + :caught + end + end + + class LocalVariableCaptor < Captor + def capture(msg) + raise msg + rescue => captured_error + @captured_error = captured_error + :caught + end + end + + class SafeNavigationSetterCaptor < Captor + def capture(msg) + raise msg + rescue => self&.captured_error + :caught + end + end + + class SetterCaptor < Captor + def capture(msg) + raise msg + rescue => self.captured_error + :caught + end + end + + class SquareBracketsCaptor < Captor + def capture(msg) + @hash = {} + + raise msg + rescue => self[:error] + :caught + end + + def []=(key, value) + @hash[key] = value + end + + def captured_error + @hash[:error] + end + end +end diff --git a/ruby/spec/ruby/language/fixtures/return.rb b/ruby/spec/ruby/language/fixtures/return.rb index 0414c356e..f6b143f3f 100644 --- a/ruby/spec/ruby/language/fixtures/return.rb +++ b/ruby/spec/ruby/language/fixtures/return.rb @@ -101,18 +101,14 @@ def outer # return value will go into val before we run the ensure. # # If lamb's return keeps unwinding incorrectly, val will still - # have it's old value. + # have its old value. # # We can therefore use val to figure out what happened. begin val = foo() ensure - if val != :good - return :bad - end + return val end - - return val end end diff --git a/ruby/spec/ruby/language/fixtures/squiggly_heredoc.rb b/ruby/spec/ruby/language/fixtures/squiggly_heredoc.rb index afc87514c..984a629e5 100644 --- a/ruby/spec/ruby/language/fixtures/squiggly_heredoc.rb +++ b/ruby/spec/ruby/language/fixtures/squiggly_heredoc.rb @@ -29,6 +29,22 @@ def self.singlequoted HERE end + def self.backslash + <<~HERE + a + b\ + c + HERE + end + + def self.least_indented_on_the_first_line + <<~HERE + a + b + c + HERE + end + def self.least_indented_on_the_last_line <<~HERE a @@ -36,4 +52,20 @@ def self.least_indented_on_the_last_line c HERE end + + def self.least_indented_on_the_first_line_single + <<~'HERE' + a + b + c + HERE + end + + def self.least_indented_on_the_last_line_single + <<~'HERE' + a + b + c + HERE + end end diff --git a/ruby/spec/ruby/language/fixtures/super.rb b/ruby/spec/ruby/language/fixtures/super.rb index 6a024cae2..218f1e497 100644 --- a/ruby/spec/ruby/language/fixtures/super.rb +++ b/ruby/spec/ruby/language/fixtures/super.rb @@ -455,6 +455,52 @@ def m_modified(a, b, *args) end end + module ZSuperWithRestAndPost + class A + def m(*args, a, b) + args + end + + def m_modified(*args, a, b) + args + end + end + + class B < A + def m(*args, a, b) + super + end + + def m_modified(*args, a, b) + args[1] = 14 + super + end + end + end + + module ZSuperWithRestOthersAndPost + class A + def m(a, *args, b) + args + end + + def m_modified(a, *args, b) + args + end + end + + class B < A + def m(a, *args, b) + super + end + + def m_modified(a, *args, b) + args[1] = 14 + super + end + end + end + module ZSuperWithRestReassigned class A def a(*args) diff --git a/ruby/spec/ruby/language/hash_spec.rb b/ruby/spec/ruby/language/hash_spec.rb index 6f2e8e5cf..2f8b97199 100644 --- a/ruby/spec/ruby/language/hash_spec.rb +++ b/ruby/spec/ruby/language/hash_spec.rb @@ -38,7 +38,7 @@ key.reverse! h["foo"].should == "bar" h.keys.first.should == "foo" - h.keys.first.frozen?.should == true + h.keys.first.should.frozen? key.should == "oof" end @@ -48,6 +48,26 @@ }.should complain(/key :foo is duplicated|duplicated key/) @h.keys.size.should == 1 @h.should == {foo: :foo} + -> { + @h = eval "{%q{a} => :bar, %q{a} => :foo}" + }.should complain(/key "a" is duplicated|duplicated key/) + @h.keys.size.should == 1 + @h.should == {%q{a} => :foo} + -> { + @h = eval "{1000 => :bar, 1000 => :foo}" + }.should complain(/key 1000 is duplicated|duplicated key/) + @h.keys.size.should == 1 + @h.should == {1000 => :foo} + end + + ruby_version_is "3.1" do + it "checks duplicated float keys on initialization" do + -> { + @h = eval "{1.0 => :bar, 1.0 => :foo}" + }.should complain(/key 1.0 is duplicated|duplicated key/) + @h.keys.size.should == 1 + @h.should == {1.0 => :foo} + end end it "accepts a hanging comma" do @@ -149,6 +169,12 @@ def h.to_hash; {:b => 2, :c => 3}; end -> { {**obj} }.should raise_error(TypeError) end + it "raises a TypeError if the object does not respond to #to_hash" do + obj = 42 + -> { {**obj} }.should raise_error(TypeError) + -> { {a: 1, **obj} }.should raise_error(TypeError) + end + it "does not change encoding of literal string keys during creation" do binary_hash = HashStringsBinary.literal_hash utf8_hash = HashStringsUTF8.literal_hash @@ -161,3 +187,81 @@ def h.to_hash; {:b => 2, :c => 3}; end usascii_hash.keys.first.encoding.should == Encoding::US_ASCII end end + +describe "The ** operator" do + it "makes a copy when calling a method taking a keyword rest argument" do + def m(**h) + h.delete(:one); h + end + + h = { one: 1, two: 2 } + m(**h).should == { two: 2 } + m(**h).should_not.equal?(h) + h.should == { one: 1, two: 2 } + end + + ruby_version_is ""..."3.0" do + it "makes a caller-side copy when calling a method taking a positional Hash" do + def m(h) + h.delete(:one); h + end + + h = { one: 1, two: 2 } + m(**h).should == { two: 2 } + m(**h).should_not.equal?(h) + h.should == { one: 1, two: 2 } + end + end + + ruby_version_is "3.0" do + it "does not copy when calling a method taking a positional Hash" do + def m(h) + h.delete(:one); h + end + + h = { one: 1, two: 2 } + m(**h).should == { two: 2 } + m(**h).should.equal?(h) + h.should == { two: 2 } + end + end + + ruby_version_is "3.1" do + describe "hash with omitted value" do + it "accepts short notation 'key' for 'key: value' syntax" do + a, b, c = 1, 2, 3 + h = eval('{a:}') + {a: 1}.should == h + h = eval('{a:, b:, c:}') + {a: 1, b: 2, c: 3}.should == h + end + + it "ignores hanging comma on short notation" do + a, b, c = 1, 2, 3 + h = eval('{a:, b:, c:,}') + {a: 1, b: 2, c: 3}.should == h + end + + it "accepts mixed syntax" do + a, e = 1, 5 + h = eval('{a:, b: 2, "c" => 3, :d => 4, e:}') + eval('{a: 1, :b => 2, "c" => 3, "d": 4, e: 5}').should == h + end + + it "works with methods and local vars" do + a = Class.new + a.class_eval(<<-RUBY) + def bar + "baz" + end + + def foo(val) + {bar:, val:} + end + RUBY + + a.new.foo(1).should == {bar: "baz", val: 1} + end + end + end +end diff --git a/ruby/spec/ruby/language/heredoc_spec.rb b/ruby/spec/ruby/language/heredoc_spec.rb index e7655a921..61a27ad8e 100644 --- a/ruby/spec/ruby/language/heredoc_spec.rb +++ b/ruby/spec/ruby/language/heredoc_spec.rb @@ -59,6 +59,22 @@ s.encoding.should == Encoding::US_ASCII end + ruby_version_is "2.7" do + it 'raises SyntaxError if quoted HEREDOC identifier is ending not on same line' do + -> { + eval %{<<"HERE\n"\nraises syntax error\nHERE} + }.should raise_error(SyntaxError) + end + end + + ruby_version_is ""..."2.7" do + it 'prints a warning if quoted HEREDOC identifier is ending not on same line' do + -> { + eval %{<<"HERE\n"\nit warns\nHERE} + }.should complain(/here document identifier ends with a newline/) + end + end + it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do require_relative 'fixtures/squiggly_heredoc' SquigglyHeredocSpecs.message.should == "character density, n.:\n The number of very weird people in the office.\n" @@ -84,8 +100,20 @@ SquigglyHeredocSpecs.singlequoted.should == "singlequoted \#{\"interpolated\"}\n" end + it "allows HEREDOC with <<~'identifier', no interpolation, with backslash" do + require_relative 'fixtures/squiggly_heredoc' + SquigglyHeredocSpecs.backslash.should == "a\nbc\n" + end + it "selects the least-indented line and removes its indentation from all the lines" do require_relative 'fixtures/squiggly_heredoc' + SquigglyHeredocSpecs.least_indented_on_the_first_line.should == "a\n b\n c\n" SquigglyHeredocSpecs.least_indented_on_the_last_line.should == " a\n b\nc\n" end + + it "selects the least-indented line and removes its indentation from all the lines for <<~'identifier'" do + require_relative 'fixtures/squiggly_heredoc' + SquigglyHeredocSpecs.least_indented_on_the_first_line_single.should == "a\n b\n c\n" + SquigglyHeredocSpecs.least_indented_on_the_last_line_single.should == " a\n b\nc\n" + end end diff --git a/ruby/spec/ruby/language/lambda_spec.rb b/ruby/spec/ruby/language/lambda_spec.rb index ddd0b574b..6393fb5c4 100644 --- a/ruby/spec/ruby/language/lambda_spec.rb +++ b/ruby/spec/ruby/language/lambda_spec.rb @@ -22,14 +22,12 @@ def create_lambda -> { }.lambda?.should be_true end - ruby_version_is "2.6" do - it "may include a rescue clause" do - eval('-> do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc) - end + it "may include a rescue clause" do + eval('-> do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc) + end - it "may include a ensure clause" do - eval('-> do 1; ensure; 2; end').should be_an_instance_of(Proc) - end + it "may include a ensure clause" do + eval('-> do 1; ensure; 2; end').should be_an_instance_of(Proc) end it "has its own scope for local variables" do @@ -179,17 +177,33 @@ def create_lambda result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12] end - evaluate <<-ruby do - @a = -> (*, **k) { k } - ruby + ruby_version_is ''...'3.0' do + evaluate <<-ruby do + @a = -> (*, **k) { k } + ruby - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} + @a.().should == {} + @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} + + suppress_keyword_warning do + h = mock("keyword splat") + h.should_receive(:to_hash).and_return({a: 1}) + @a.(h).should == {a: 1} + end + end + end + + ruby_version_is '3.0' do + evaluate <<-ruby do + @a = -> (*, **k) { k } + ruby + + @a.().should == {} + @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - suppress_keyword_warning do h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - @a.(h).should == {a: 1} + h.should_not_receive(:to_hash) + @a.(h).should == {} end end @@ -332,15 +346,14 @@ def obj.define end it "requires a block" do - lambda { lambda }.should raise_error(ArgumentError) - end - - ruby_version_is "2.5" do - it "may include a rescue clause" do - eval('lambda do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc) + suppress_warning do + lambda { lambda }.should raise_error(ArgumentError) end end + it "may include a rescue clause" do + eval('lambda do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc) + end context "with an implicit block" do before do @@ -362,9 +375,11 @@ def meth; lambda; end ruby_version_is "2.7" do it "raises ArgumentError" do implicit_lambda = nil - -> { - meth { 1 } - }.should raise_error(ArgumentError, /tried to create Proc object without a block/) + suppress_warning do + -> { + meth { 1 } + }.should raise_error(ArgumentError, /tried to create Proc object without a block/) + end end end end @@ -533,17 +548,33 @@ def m2() yield end result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12] end - evaluate <<-ruby do - @a = lambda { |*, **k| k } - ruby + ruby_version_is ''...'3.0' do + evaluate <<-ruby do + @a = lambda { |*, **k| k } + ruby - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} + @a.().should == {} + @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} + + suppress_keyword_warning do + h = mock("keyword splat") + h.should_receive(:to_hash).and_return({a: 1}) + @a.(h).should == {a: 1} + end + end + end + + ruby_version_is '3.0' do + evaluate <<-ruby do + @a = lambda { |*, **k| k } + ruby + + @a.().should == {} + @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - suppress_keyword_warning do h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - @a.(h).should == {a: 1} + h.should_not_receive(:to_hash) + @a.(h).should == {} end end diff --git a/ruby/spec/ruby/language/method_spec.rb b/ruby/spec/ruby/language/method_spec.rb index 048602579..0a5bb99d0 100644 --- a/ruby/spec/ruby/language/method_spec.rb +++ b/ruby/spec/ruby/language/method_spec.rb @@ -156,6 +156,26 @@ def m(a, *b, c) [a, b, c] end -> { m(1, 2, *x) }.should raise_error(TypeError) end end + + context "with a block argument" do + before :all do + def m(x) + if block_given? + [true, yield(x + 'b')] + else + [false] + end + end + end + + it "that refers to a proc passes the proc as the block" do + m('a', &-> y { y + 'c'}).should == [true, 'abc'] + end + + it "that is nil passes no block" do + m('a', &nil).should == [false] + end + end end describe "An element assignment method send" do @@ -576,10 +596,21 @@ def m(**k) k end m(a: 1, b: 2).should == { a: 1, b: 2 } m(*[]).should == {} m(**{}).should == {} - m(**{a: 1, b: 2}, **{a: 4, c: 7}).should == { a: 4, b: 2, c: 7 } + suppress_warning { + eval "m(**{a: 1, b: 2}, **{a: 4, c: 7})" + }.should == { a: 4, b: 2, c: 7 } -> { m(2) }.should raise_error(ArgumentError) end + ruby_version_is "2.7" do + evaluate <<-ruby do + def m(**k); k end; + ruby + + m("a" => 1).should == { "a" => 1 } + end + end + evaluate <<-ruby do def m(&b) b end ruby @@ -713,36 +744,67 @@ def m(a, b:) [a, b] end end end - evaluate <<-ruby do - def m(a, b: 1) [a, b] end - ruby + ruby_version_is ""..."3.0" do + evaluate <<-ruby do + def m(a, b: 1) [a, b] end + ruby - m(2).should == [2, 1] - m(1, b: 2).should == [1, 2] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1] + m(2).should == [2, 1] + m(1, b: 2).should == [1, 2] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1] + end end - end - evaluate <<-ruby do - def m(a, **) a end - ruby + evaluate <<-ruby do + def m(a, **) a end + ruby - m(1).should == 1 - m(1, a: 2, b: 3).should == 1 - suppress_keyword_warning do - m("a" => 1, b: 2).should == {"a" => 1, b: 2} + m(1).should == 1 + m(1, a: 2, b: 3).should == 1 + suppress_keyword_warning do + m("a" => 1, b: 2).should == {"a" => 1, b: 2} + end + end + + evaluate <<-ruby do + def m(a, **k) [a, k] end + ruby + + m(1).should == [1, {}] + m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}] + end end end - evaluate <<-ruby do - def m(a, **k) [a, k] end - ruby + ruby_version_is "3.0" do + evaluate <<-ruby do + def m(a, b: 1) [a, b] end + ruby - m(1).should == [1, {}] - m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}] + m(2).should == [2, 1] + m(1, b: 2).should == [1, 2] + -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + end + + evaluate <<-ruby do + def m(a, **) a end + ruby + + m(1).should == 1 + m(1, a: 2, b: 3).should == 1 + -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + end + + evaluate <<-ruby do + def m(a, **k) [a, k] end + ruby + + m(1).should == [1, {}] + m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] + -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) end end @@ -854,26 +916,49 @@ def m(a=1, (b, *c), (d, (*e, f))) result.should == [[1, 2, 3], 4, [5, 6], 7, [], 8] end - evaluate <<-ruby do - def m(a=1, b:) [a, b] end - ruby + ruby_version_is ""..."3.0" do + evaluate <<-ruby do + def m(a=1, b:) [a, b] end + ruby - m(b: 2).should == [1, 2] - m(2, b: 1).should == [2, 1] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1}, 2] + m(b: 2).should == [1, 2] + m(2, b: 1).should == [2, 1] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [{"a" => 1}, 2] + end + end + + evaluate <<-ruby do + def m(a=1, b: 2) [a, b] end + ruby + + m().should == [1, 2] + m(2).should == [2, 2] + m(b: 3).should == [1, 3] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [{"a" => 1}, 2] + end end end - evaluate <<-ruby do - def m(a=1, b: 2) [a, b] end - ruby + ruby_version_is "3.0" do + evaluate <<-ruby do + def m(a=1, b:) [a, b] end + ruby - m().should == [1, 2] - m(2).should == [2, 2] - m(b: 3).should == [1, 3] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1}, 2] + m(b: 2).should == [1, 2] + m(2, b: 1).should == [2, 1] + -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) + end + + evaluate <<-ruby do + def m(a=1, b: 2) [a, b] end + ruby + + m().should == [1, 2] + m(2).should == [2, 2] + m(b: 3).should == [1, 3] + -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) end end @@ -936,77 +1021,77 @@ def m(*a, b) [a, b] end m(1, 2, 3).should == [[1, 2], 3] end - evaluate <<-ruby do - def m(*, a:) a end - ruby + ruby_version_is ""..."2.7" do + evaluate <<-ruby do + def m(*, a:) a end + ruby - m(a: 1).should == 1 - m(1, 2, a: 3).should == 3 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 + m(a: 1).should == 1 + m(1, 2, a: 3).should == 3 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end end - end - evaluate <<-ruby do - def m(*a, b:) [a, b] end - ruby + evaluate <<-ruby do + def m(*a, b:) [a, b] end + ruby - m(b: 1).should == [[], 1] - m(1, 2, b: 3).should == [[1, 2], 3] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + m(b: 1).should == [[], 1] + m(1, 2, b: 3).should == [[1, 2], 3] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end end - end - evaluate <<-ruby do - def m(*, a: 1) a end - ruby + evaluate <<-ruby do + def m(*, a: 1) a end + ruby - m().should == 1 - m(1, 2).should == 1 - m(a: 2).should == 2 - m(1, a: 2).should == 2 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 + m().should == 1 + m(1, 2).should == 1 + m(a: 2).should == 2 + m(1, a: 2).should == 2 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end end - end - evaluate <<-ruby do - def m(*a, b: 1) [a, b] end - ruby + evaluate <<-ruby do + def m(*a, b: 1) [a, b] end + ruby - m().should == [[], 1] - m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + m().should == [[], 1] + m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end + + a = mock("splat") + a.should_not_receive(:to_ary) + m(*a).should == [[a], 1] end - a = mock("splat") - a.should_not_receive(:to_ary) - m(*a).should == [[a], 1] - end + evaluate <<-ruby do + def m(*, **) end + ruby - evaluate <<-ruby do - def m(*, **) end - ruby + m().should be_nil + m(a: 1, b: 2).should be_nil + m(1, 2, 3, a: 4, b: 5).should be_nil - m().should be_nil - m(a: 1, b: 2).should be_nil - m(1, 2, 3, a: 4, b: 5).should be_nil + h = mock("keyword splat") + h.should_receive(:to_hash).and_return({a: 1}) + suppress_keyword_warning do + m(h).should be_nil + end - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - suppress_keyword_warning do - m(h).should be_nil + h = mock("keyword splat") + error = RuntimeError.new("error while converting to a hash") + h.should_receive(:to_hash).and_raise(error) + -> { m(h) }.should raise_error(error) end - h = mock("keyword splat") - error = RuntimeError.new("error while converting to a hash") - h.should_receive(:to_hash).and_raise(error) - -> { m(h) }.should raise_error(error) - end - - ruby_version_is ""..."2.7" do evaluate <<-ruby do def m(*a, **) a end ruby @@ -1093,7 +1178,57 @@ def bo.to_hash; {:b => 2, :c => 3}; end end end - ruby_version_is "2.7" do + ruby_version_is "2.7"...'3.0' do + evaluate <<-ruby do + def m(*, a:) a end + ruby + + m(a: 1).should == 1 + m(1, 2, a: 3).should == 3 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end + end + + evaluate <<-ruby do + def m(*a, b:) [a, b] end + ruby + + m(b: 1).should == [[], 1] + m(1, 2, b: 3).should == [[1, 2], 3] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end + end + + evaluate <<-ruby do + def m(*, a: 1) a end + ruby + + m().should == 1 + m(1, 2).should == 1 + m(a: 2).should == 2 + m(1, a: 2).should == 2 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end + end + + evaluate <<-ruby do + def m(*a, b: 1) [a, b] end + ruby + + m().should == [[], 1] + m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end + + a = mock("splat") + a.should_not_receive(:to_ary) + m(*a).should == [[a], 1] + end + evaluate <<-ruby do def m(*a, **) a end ruby @@ -1184,6 +1319,149 @@ def bo.to_hash; {:b => 2, :c => 3}; end m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}] end + + evaluate <<-ruby do + def m(*, a:) a end + ruby + + m(a: 1).should == 1 + m(1, 2, a: 3).should == 3 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end + end + + evaluate <<-ruby do + def m(*a, b:) [a, b] end + ruby + + m(b: 1).should == [[], 1] + m(1, 2, b: 3).should == [[1, 2], 3] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end + end + + evaluate <<-ruby do + def m(*, a: 1) a end + ruby + + m().should == 1 + m(1, 2).should == 1 + m(a: 2).should == 2 + m(1, a: 2).should == 2 + suppress_keyword_warning do + m("a" => 1, a: 2).should == 2 + end + end + + evaluate <<-ruby do + def m(*a, b: 1) [a, b] end + ruby + + m().should == [[], 1] + m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] + suppress_keyword_warning do + m("a" => 1, b: 2).should == [[{"a" => 1}], 2] + end + + a = mock("splat") + a.should_not_receive(:to_ary) + m(*a).should == [[a], 1] + end + + evaluate <<-ruby do + def m(*a, **) a end + ruby + + m().should == [] + m(1, 2, 3, a: 4, b: 5).should == [1, 2, 3] + m("a" => 1, a: 1).should == [] + m(1, **{a: 2}).should == [1] + + h = mock("keyword splat") + h.should_receive(:to_hash) + -> { m(**h) }.should raise_error(TypeError) + end + + evaluate <<-ruby do + def m(*, **k) k end + ruby + + m().should == {} + m(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} + m("a" => 1, a: 1).should == {"a" => 1, a: 1} + + h = mock("keyword splat") + h.should_receive(:to_hash).and_return({a: 1}) + suppress_keyword_warning do + m(h).should == {a: 1} + end + end + + evaluate <<-ruby do + def m(a = nil, **k) [a, k] end + ruby + + m().should == [nil, {}] + m("a" => 1).should == [nil, {"a" => 1}] + m(a: 1).should == [nil, {a: 1}] + m("a" => 1, a: 1).should == [nil, {"a" => 1, a: 1}] + m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}] + suppress_keyword_warning do + m({a: 1}, {}).should == [{a: 1}, {}] + end + + h = {"a" => 1, b: 2} + suppress_keyword_warning do + m(h).should == [{"a" => 1}, {b: 2}] + end + h.should == {"a" => 1, b: 2} + + h = {"a" => 1} + m(h).first.should == h + + h = {} + suppress_keyword_warning do + m(h).should == [nil, {}] + end + + hh = {} + h = mock("keyword splat empty hash") + h.should_receive(:to_hash).and_return({a: 1}) + suppress_keyword_warning do + m(h).should == [nil, {a: 1}] + end + + h = mock("keyword splat") + h.should_receive(:to_hash).and_return({"a" => 1}) + m(h).should == [h, {}] + end + + evaluate <<-ruby do + def m(*a, **k) [a, k] end + ruby + + m().should == [[], {}] + m(1).should == [[1], {}] + m(a: 1, b: 2).should == [[], {a: 1, b: 2}] + m(1, 2, 3, a: 2).should == [[1, 2, 3], {a: 2}] + + m("a" => 1).should == [[], {"a" => 1}] + m(a: 1).should == [[], {a: 1}] + m("a" => 1, a: 1).should == [[], {"a" => 1, a: 1}] + m({ "a" => 1 }, a: 1).should == [[{"a" => 1}], {a: 1}] + suppress_keyword_warning do + m({a: 1}, {}).should == [[{a: 1}], {}] + end + m({a: 1}, {"a" => 1}).should == [[{a: 1}, {"a" => 1}], {}] + + bo = BasicObject.new + def bo.to_a; [1, 2, 3]; end + def bo.to_hash; {:b => 2, :c => 3}; end + + m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}] + end end evaluate <<-ruby do @@ -1261,9 +1539,7 @@ def m(a:, **k) [a, k] end m(a: 1).should == [1, {}] m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}] - suppress_warning do - m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}] - end + m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}] end end @@ -1361,39 +1637,138 @@ def m(a, b=1, *c, d, e:, f: 2, g:, **k, &l) result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l] end - evaluate <<-ruby do - def m(a, b = nil, c = nil, d, e: nil, **f) - [a, b, c, d, e, f] + ruby_version_is "2.7" do + evaluate <<-ruby do + def m(a, **nil); a end; + ruby + + m({a: 1}).should == {a: 1} + m({"a" => 1}).should == {"a" => 1} + + -> { m(a: 1) }.should raise_error(ArgumentError) + -> { m(**{a: 1}) }.should raise_error(ArgumentError) + -> { m("a" => 1) }.should raise_error(ArgumentError) + end + end + + ruby_version_is ''...'3.0' do + evaluate <<-ruby do + def m(a, b = nil, c = nil, d, e: nil, **f) + [a, b, c, d, e, f] + end + ruby + + result = m(1, 2) + result.should == [1, nil, nil, 2, nil, {}] + + suppress_warning do + result = m(1, 2, {foo: :bar}) + result.should == [1, nil, nil, 2, nil, {foo: :bar}] end - ruby - result = m(1, 2) - result.should == [1, nil, nil, 2, nil, {}] + result = m(1, {foo: :bar}) + result.should == [1, nil, nil, {foo: :bar}, nil, {}] + end + end + + ruby_version_is '3.0' do + evaluate <<-ruby do + def m(a, b = nil, c = nil, d, e: nil, **f) + [a, b, c, d, e, f] + end + ruby + + result = m(1, 2) + result.should == [1, nil, nil, 2, nil, {}] - suppress_warning do result = m(1, 2, {foo: :bar}) - result.should == [1, nil, nil, 2, nil, {foo: :bar}] + result.should == [1, 2, nil, {foo: :bar}, nil, {}] + + result = m(1, {foo: :bar}) + result.should == [1, nil, nil, {foo: :bar}, nil, {}] end + end + end + + ruby_version_is '2.7' do + context 'when passing an empty keyword splat to a method that does not accept keywords' do + evaluate <<-ruby do + def m(*a); a; end + ruby - result = m(1, {foo: :bar}) - result.should == [1, nil, nil, {foo: :bar}, nil, {}] + h = {} + m(**h).should == [] + end end end - context "assigns keyword arguments from a passed Hash without modifying it" do - evaluate <<-ruby do - def m(a: nil); a; end - ruby + ruby_version_is '2.7'...'3.0' do + context 'when passing an empty keyword splat to a method that does not accept keywords' do + evaluate <<-ruby do + def m(a); a; end + ruby + h = {} - options = {a: 1}.freeze - -> do - suppress_warning do - m(options).should == 1 - end - end.should_not raise_error - options.should == {a: 1} + -> do + m(**h).should == {} + end.should complain(/warning: Passing the keyword argument as the last hash parameter is deprecated/) + end + end + end + + ruby_version_is ''...'3.0' do + context "assigns keyword arguments from a passed Hash without modifying it" do + evaluate <<-ruby do + def m(a: nil); a; end + ruby + + options = {a: 1}.freeze + -> do + suppress_warning do + m(options).should == 1 + end + end.should_not raise_error + options.should == {a: 1} + end + end + end + + ruby_version_is '3.0' do + context 'when passing an empty keyword splat to a method that does not accept keywords' do + evaluate <<-ruby do + def m(a); a; end + ruby + h = {} + + -> do + m(**h).should == {} + end.should raise_error(ArgumentError) + end + end + + context "raises ArgumentError if passing hash as keyword arguments" do + evaluate <<-ruby do + def m(a: nil); a; end + ruby + + options = {a: 1}.freeze + -> do + m(options) + end.should raise_error(ArgumentError) + end end end + + it "assigns the last Hash to the last optional argument if the Hash contains non-Symbol keys and is not passed as keywords" do + def m(a = nil, b = {}, v: false) + [a, b, v] + end + + h = { "key" => "value" } + m(:a, h).should == [:a, h, false] + m(:a, h, v: true).should == [:a, h, true] + m(v: true).should == [nil, {}, true] + end end describe "A method call with a space between method name and parentheses" do @@ -1485,3 +1860,159 @@ def [](*) end end end + +ruby_version_is "3.0" do + describe "An endless method definition" do + context "without arguments" do + evaluate <<-ruby do + def m() = 42 + ruby + + m.should == 42 + end + end + + context "with arguments" do + evaluate <<-ruby do + def m(a, b) = a + b + ruby + + m(1, 4).should == 5 + end + end + + context "with multiline body" do + evaluate <<-ruby do + def m(n) = + if n > 2 + m(n - 2) + m(n - 1) + else + 1 + end + ruby + + m(6).should == 8 + end + end + + context "with args forwarding" do + evaluate <<-ruby do + def mm(word, num:) + word * num + end + + def m(...) = mm(...) + mm(...) + ruby + + m("meow", num: 2).should == "meow" * 4 + end + end + end + + describe "Keyword arguments are now separated from positional arguments" do + context "when the method has only positional parameters" do + it "treats incoming keyword arguments as positional for compatibility" do + def foo(a, b, c, hsh) + hsh[:key] + end + + foo(1, 2, 3, key: 42).should == 42 + end + end + + context "when the method takes a ** parameter" do + it "captures the passed literal keyword arguments" do + def foo(a, b, c, **hsh) + hsh[:key] + end + + foo(1, 2, 3, key: 42).should == 42 + end + + it "captures the passed ** keyword arguments" do + def foo(a, b, c, **hsh) + hsh[:key] + end + + h = { key: 42 } + foo(1, 2, 3, **h).should == 42 + end + + it "does not convert a positional Hash to keyword arguments" do + def foo(a, b, c, **hsh) + hsh[:key] + end + + -> { + foo(1, 2, 3, { key: 42 }) + }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)') + end + end + + context "when the method takes a key: parameter" do + context "when it's called with a positional Hash and no **" do + it "raises ArgumentError" do + def foo(a, b, c, key: 1) + key + end + + -> { + foo(1, 2, 3, { key: 42 }) + }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)') + end + end + + context "when it's called with **" do + it "captures the passed keyword arguments" do + def foo(a, b, c, key: 1) + key + end + + h = { key: 42 } + foo(1, 2, 3, **h).should == 42 + end + end + end + end +end + +ruby_version_is "3.1" do + describe "kwarg with omitted value in a method call" do + context "accepts short notation 'kwarg' in method call" do + evaluate <<-ruby do + def call(*args, **kwargs) = [args, kwargs] + ruby + + a, b, c = 1, 2, 3 + arr, h = eval('call a:') + h.should == {a: 1} + arr.should == [] + + arr, h = eval('call(a:, b:, c:)') + h.should == {a: 1, b: 2, c: 3} + arr.should == [] + + arr, h = eval('call(a:, b: 10, c:)') + h.should == {a: 1, b: 10, c: 3} + arr.should == [] + end + end + + context "with methods and local variables" do + evaluate <<-ruby do + def call(*args, **kwargs) = [args, kwargs] + + def bar + "baz" + end + + def foo(val) + call bar:, val: + end + ruby + + foo(1).should == [[], {bar: "baz", val: 1}] + end + end + end +end diff --git a/ruby/spec/ruby/language/module_spec.rb b/ruby/spec/ruby/language/module_spec.rb index 1b41e184b..1a5fcaf46 100644 --- a/ruby/spec/ruby/language/module_spec.rb +++ b/ruby/spec/ruby/language/module_spec.rb @@ -43,7 +43,7 @@ module ModuleSpecs::Modules::Klass; end -> { module ModuleSpecs::Modules::A; end }.should raise_error(TypeError) end - it "raises a TypeError if the constant is a Fixnum" do + it "raises a TypeError if the constant is an Integer" do -> { module ModuleSpecs::Modules::B; end }.should raise_error(TypeError) end @@ -69,10 +69,20 @@ module ModuleSpecs::Modules::Klass; end mod.name.should == "ModuleSpecs_CS1" end - it "does not set the name of a module scoped by an anonymous module" do - a, b = Module.new, Module.new - a::B = b - b.name.should be_nil + ruby_version_is ""..."3.0" do + it "does not set the name of a module scoped by an anonymous module" do + a, b = Module.new, Module.new + a::B = b + b.name.should be_nil + end + end + + ruby_version_is "3.0" do + it "sets the name of a module scoped by an anonymous module" do + a, b = Module.new, Module.new + a::B = b + b.name.should.end_with? '::B' + end end it "sets the name of contained modules when assigning a toplevel anonymous module" do diff --git a/ruby/spec/ruby/language/numbered_parameters_spec.rb b/ruby/spec/ruby/language/numbered_parameters_spec.rb new file mode 100644 index 000000000..838822b2d --- /dev/null +++ b/ruby/spec/ruby/language/numbered_parameters_spec.rb @@ -0,0 +1,120 @@ +require_relative '../spec_helper' + +ruby_version_is "2.7" do + describe "Numbered parameters" do + it "provides default parameters _1, _2, ... in a block" do + -> { _1 }.call("a").should == "a" + proc { _1 }.call("a").should == "a" + lambda { _1 }.call("a").should == "a" + ["a"].map { _1 }.should == ["a"] + end + + it "assigns nil to not passed parameters" do + proc { [_1, _2] }.call("a").should == ["a", nil] + proc { [_1, _2] }.call("a", "b").should == ["a", "b"] + end + + it "supports variables _1-_9 only for the first 9 passed parameters" do + block = proc { [_1, _2, _3, _4, _5, _6, _7, _8, _9] } + result = block.call(1, 2, 3, 4, 5, 6, 7, 8, 9) + result.should == [1, 2, 3, 4, 5, 6, 7, 8, 9] + end + + it "does not support more than 9 parameters" do + -> { + proc { [_10] }.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + }.should raise_error(NameError, /undefined local variable or method `_10'/) + end + + it "can not be used in both outer and nested blocks at the same time" do + -> { + eval("-> { _1; -> { _2 } }") + }.should raise_error(SyntaxError, /numbered parameter is already used in/m) + end + + ruby_version_is '2.7'...'3.0' do + it "can be overwritten with local variable" do + suppress_warning do + eval <<~CODE + _1 = 0 + proc { _1 }.call("a").should == 0 + CODE + end + end + + it "warns when numbered parameter is overwritten with local variable" do + -> { + eval("_1 = 0") + }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/) + end + end + + ruby_version_is '3.0' do + it "cannot be overwritten with local variable" do + -> { + eval <<~CODE + _1 = 0 + proc { _1 }.call("a").should == 0 + CODE + }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) + end + + it "errors when numbered parameter is overwritten with local variable" do + -> { + eval("_1 = 0") + }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) + end + end + + it "raises SyntaxError when block parameters are specified explicitly" do + -> { eval("-> () { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + -> { eval("-> (x) { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + + -> { eval("proc { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + -> { eval("proc { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + + -> { eval("lambda { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + -> { eval("lambda { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + + -> { eval("['a'].map { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + -> { eval("['a'].map { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/) + end + + describe "assigning to a numbered parameter" do + ruby_version_is '2.7'...'3.0' do + it "warns" do + -> { eval("proc { _1 = 0 }") }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/) + end + end + + ruby_version_is '3.0' do + it "raises SyntaxError" do + -> { eval("proc { _1 = 0 }") }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) + end + end + end + + it "affects block arity" do + -> { _1 }.arity.should == 1 + -> { _2 }.arity.should == 2 + -> { _3 }.arity.should == 3 + -> { _4 }.arity.should == 4 + -> { _5 }.arity.should == 5 + -> { _6 }.arity.should == 6 + -> { _7 }.arity.should == 7 + -> { _8 }.arity.should == 8 + -> { _9 }.arity.should == 9 + + -> { _9 }.arity.should == 9 + proc { _9 }.arity.should == 9 + lambda { _9 }.arity.should == 9 + end + + it "does not work in methods" do + obj = Object.new + def obj.foo; _1 end + + -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/) + end + end +end diff --git a/ruby/spec/ruby/language/numbers_spec.rb b/ruby/spec/ruby/language/numbers_spec.rb index c82a63063..2d8e19c40 100644 --- a/ruby/spec/ruby/language/numbers_spec.rb +++ b/ruby/spec/ruby/language/numbers_spec.rb @@ -45,6 +45,14 @@ eval('-3r').should == Rational(-3, 1) end + it "can be an float literal with trailing 'r' to represent a Rational in a canonical form" do + eval('1.0r').should == Rational(1, 1) + end + + it "can be a float literal with trailing 'r' to represent a Rational" do + eval('0.0174532925199432957r').should == Rational(174532925199432957, 10000000000000000000) + end + it "can be an bignum literal with trailing 'r' to represent a Rational" do eval('1111111111111111111111111111111111111111111111r').should == Rational(1111111111111111111111111111111111111111111111, 1) eval('-1111111111111111111111111111111111111111111111r').should == Rational(-1111111111111111111111111111111111111111111111, 1) diff --git a/ruby/spec/ruby/language/optional_assignments_spec.rb b/ruby/spec/ruby/language/optional_assignments_spec.rb index 3d9e0dbb6..217dcab74 100644 --- a/ruby/spec/ruby/language/optional_assignments_spec.rb +++ b/ruby/spec/ruby/language/optional_assignments_spec.rb @@ -1,4 +1,5 @@ require_relative '../spec_helper' +require_relative '../fixtures/constants' describe 'Optional variable assignments' do describe 'using ||=' do @@ -351,3 +352,107 @@ def []=(k, v) end end end + +describe 'Optional constant assignment' do + describe 'with ||=' do + it "assigns a scoped constant if previously undefined" do + ConstantSpecs.should_not have_constant(:OpAssignUndefined) + module ConstantSpecs + OpAssignUndefined ||= 42 + end + ConstantSpecs::OpAssignUndefined.should == 42 + ConstantSpecs::OpAssignUndefinedOutside ||= 42 + ConstantSpecs::OpAssignUndefinedOutside.should == 42 + ConstantSpecs.send(:remove_const, :OpAssignUndefined) + ConstantSpecs.send(:remove_const, :OpAssignUndefinedOutside) + end + + it "assigns a global constant if previously undefined" do + OpAssignGlobalUndefined ||= 42 + ::OpAssignGlobalUndefinedExplicitScope ||= 42 + OpAssignGlobalUndefined.should == 42 + ::OpAssignGlobalUndefinedExplicitScope.should == 42 + Object.send :remove_const, :OpAssignGlobalUndefined + Object.send :remove_const, :OpAssignGlobalUndefinedExplicitScope + end + + it 'correctly defines non-existing constants' do + ConstantSpecs::ClassA::OR_ASSIGNED_CONSTANT1 ||= :assigned + ConstantSpecs::ClassA::OR_ASSIGNED_CONSTANT1.should == :assigned + end + + it 'correctly overwrites nil constants' do + suppress_warning do # already initialized constant + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT1 = nil + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT1 ||= :assigned + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT1.should == :assigned + end + end + + it 'causes side-effects of the module part to be applied only once (for undefined constant)' do + x = 0 + (x += 1; ConstantSpecs::ClassA)::OR_ASSIGNED_CONSTANT2 ||= :assigned + x.should == 1 + ConstantSpecs::ClassA::OR_ASSIGNED_CONSTANT2.should == :assigned + end + + it 'causes side-effects of the module part to be applied (for nil constant)' do + suppress_warning do # already initialized constant + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT2 = nil + x = 0 + (x += 1; ConstantSpecs::ClassA)::NIL_OR_ASSIGNED_CONSTANT2 ||= :assigned + x.should == 1 + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT2.should == :assigned + end + end + + it 'does not evaluate the right-hand side if the module part raises an exception (for undefined constant)' do + x = 0 + y = 0 + + -> { + (x += 1; raise Exception; ConstantSpecs::ClassA)::OR_ASSIGNED_CONSTANT3 ||= (y += 1; :assigned) + }.should raise_error(Exception) + + x.should == 1 + y.should == 0 + defined?(ConstantSpecs::ClassA::OR_ASSIGNED_CONSTANT3).should == nil + end + + it 'does not evaluate the right-hand side if the module part raises an exception (for nil constant)' do + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT3 = nil + x = 0 + y = 0 + + -> { + (x += 1; raise Exception; ConstantSpecs::ClassA)::NIL_OR_ASSIGNED_CONSTANT3 ||= (y += 1; :assigned) + }.should raise_error(Exception) + + x.should == 1 + y.should == 0 + ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT3.should == nil + end + end + + describe "with &&=" do + it "re-assigns a scoped constant if already true" do + module ConstantSpecs + OpAssignTrue = true + end + suppress_warning do + ConstantSpecs::OpAssignTrue &&= 1 + end + ConstantSpecs::OpAssignTrue.should == 1 + ConstantSpecs.send :remove_const, :OpAssignTrue + end + + it "leaves scoped constant if not true" do + module ConstantSpecs + OpAssignFalse = false + end + ConstantSpecs::OpAssignFalse &&= 1 + ConstantSpecs::OpAssignFalse.should == false + ConstantSpecs.send :remove_const, :OpAssignFalse + end + end +end diff --git a/ruby/spec/ruby/language/pattern_matching_spec.rb b/ruby/spec/ruby/language/pattern_matching_spec.rb new file mode 100644 index 000000000..e4abae941 --- /dev/null +++ b/ruby/spec/ruby/language/pattern_matching_spec.rb @@ -0,0 +1,1302 @@ +require_relative '../spec_helper' + +ruby_version_is "2.7" do + describe "Pattern matching" do + # TODO: Remove excessive eval calls when support of previous version + # Ruby 2.6 will be dropped + + before :each do + ScratchPad.record [] + end + + ruby_version_is "3.0" do + it "can be standalone assoc operator that deconstructs value" do + suppress_warning do + eval(<<-RUBY).should == [0, 1] + [0, 1] => [a, b] + [a, b] + RUBY + end + end + + describe "find pattern" do + it "captures preceding elements to the pattern" do + eval(<<~RUBY).should == [0, 1] + case [0, 1, 2, 3] + in [*pre, 2, 3] + pre + else + false + end + RUBY + end + + it "captures following elements to the pattern" do + eval(<<~RUBY).should == [2, 3] + case [0, 1, 2, 3] + in [0, 1, *post] + post + else + false + end + RUBY + end + + it "captures both preceding and following elements to the pattern" do + eval(<<~RUBY).should == [[0, 1], [3, 4]] + case [0, 1, 2, 3, 4] + in [*pre, 2, *post] + [pre, post] + else + false + end + RUBY + end + + it "can capture the entirety of the pattern" do + eval(<<~RUBY).should == [0, 1, 2, 3, 4] + case [0, 1, 2, 3, 4] + in [*everything] + everything + else + false + end + RUBY + end + + it "will match an empty Array-like structure" do + eval(<<~RUBY).should == [] + case [] + in [*everything] + everything + else + false + end + RUBY + end + end + end + + it "extends case expression with case/in construction" do + eval(<<~RUBY).should == :bar + case [0, 1] + in [0] + :foo + in [0, 1] + :bar + end + RUBY + end + + it "allows using then operator" do + eval(<<~RUBY).should == :bar + case [0, 1] + in [0] then :foo + in [0, 1] then :bar + end + RUBY + end + + describe "warning" do + before :each do + @experimental, Warning[:experimental] = Warning[:experimental], true + end + + after :each do + Warning[:experimental] = @experimental + end + + context 'when regular form' do + before :each do + @src = 'case [0, 1]; in [a, b]; end' + end + + ruby_version_is ""..."3.0" do + it "warns about pattern matching is experimental feature" do + -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i) + end + end + + ruby_version_is "3.0" do + it "does not warn about pattern matching is experimental feature" do + -> { eval @src }.should_not complain + end + end + end + + context 'when one-line form' do + ruby_version_is '3.0' do + before :each do + @src = '[0, 1] => [a, b]' + end + + ruby_version_is ""..."3.1" do + it "warns about pattern matching is experimental feature" do + -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i) + end + end + + ruby_version_is "3.1" do + it "does not warn about pattern matching is experimental feature" do + -> { eval @src }.should_not complain + end + end + end + end + end + + it "binds variables" do + eval(<<~RUBY).should == 1 + case [0, 1] + in [0, a] + a + end + RUBY + end + + it "cannot mix in and when operators" do + -> { + eval <<~RUBY + case [] + when 1 == 1 + in [] + end + RUBY + }.should raise_error(SyntaxError, /syntax error, unexpected `in'/) + + -> { + eval <<~RUBY + case [] + in [] + when 1 == 1 + end + RUBY + }.should raise_error(SyntaxError, /syntax error, unexpected `when'/) + end + + it "checks patterns until the first matching" do + eval(<<~RUBY).should == :bar + case [0, 1] + in [0] + :foo + in [0, 1] + :bar + in [0, 1] + :baz + end + RUBY + end + + it "executes else clause if no pattern matches" do + eval(<<~RUBY).should == false + case [0, 1] + in [0] + true + else + false + end + RUBY + end + + it "raises NoMatchingPatternError if no pattern matches and no else clause" do + -> { + eval <<~RUBY + case [0, 1] + in [0] + end + RUBY + }.should raise_error(NoMatchingPatternError, /\[0, 1\]/) + end + + it "does not allow calculation or method calls in a pattern" do + -> { + eval <<~RUBY + case 0 + in 1 + 1 + true + end + RUBY + }.should raise_error(SyntaxError, /unexpected/) + end + + it "evaluates the case expression once for multiple patterns, caching the result" do + eval(<<~RUBY).should == true + case (ScratchPad << :foo; 1) + in 0 + false + in 1 + true + end + RUBY + + ScratchPad.recorded.should == [:foo] + end + + describe "guards" do + it "supports if guard" do + eval(<<~RUBY).should == false + case 0 + in 0 if false + true + else + false + end + RUBY + + eval(<<~RUBY).should == true + case 0 + in 0 if true + true + else + false + end + RUBY + end + + it "supports unless guard" do + eval(<<~RUBY).should == false + case 0 + in 0 unless true + true + else + false + end + RUBY + + eval(<<~RUBY).should == true + case 0 + in 0 unless false + true + else + false + end + RUBY + end + + it "makes bound variables visible in guard" do + eval(<<~RUBY).should == true + case [0, 1] + in [a, 1] if a >= 0 + true + end + RUBY + end + + it "does not evaluate guard if pattern does not match" do + eval <<~RUBY + case 0 + in 1 if (ScratchPad << :foo) || true + else + end + RUBY + + ScratchPad.recorded.should == [] + end + + it "takes guards into account when there are several matching patterns" do + eval(<<~RUBY).should == :bar + case 0 + in 0 if false + :foo + in 0 if true + :bar + end + RUBY + end + + it "executes else clause if no guarded pattern matches" do + eval(<<~RUBY).should == false + case 0 + in 0 if false + true + else + false + end + RUBY + end + + it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do + -> { + eval <<~RUBY + case [0, 1] + in [0, 1] if false + end + RUBY + }.should raise_error(NoMatchingPatternError, /\[0, 1\]/) + end + end + + describe "value pattern" do + it "matches an object such that pattern === object" do + eval(<<~RUBY).should == true + case 0 + in 0 + true + end + RUBY + + eval(<<~RUBY).should == true + case 0 + in (-1..1) + true + end + RUBY + + eval(<<~RUBY).should == true + case 0 + in Integer + true + end + RUBY + + eval(<<~RUBY).should == true + case "0" + in /0/ + true + end + RUBY + + eval(<<~RUBY).should == true + case "0" + in ->(s) { s == "0" } + true + end + RUBY + end + + it "allows string literal with interpolation" do + x = "x" + + eval(<<~RUBY).should == true + case "x" + in "#{x + ""}" + true + end + RUBY + end + end + + describe "variable pattern" do + it "matches a value and binds variable name to this value" do + eval(<<~RUBY).should == 0 + case 0 + in a + a + end + RUBY + end + + it "makes bounded variable visible outside a case statement scope" do + eval(<<~RUBY).should == 0 + case 0 + in a + end + + a + RUBY + end + + it "create local variables even if a pattern doesn't match" do + eval(<<~RUBY).should == [0, nil, nil] + case 0 + in a + in b + in c + end + + [a, b, c] + RUBY + end + + it "allow using _ name to drop values" do + eval(<<~RUBY).should == 0 + case [0, 1] + in [a, _] + a + end + RUBY + end + + it "supports using _ in a pattern several times" do + eval(<<~RUBY).should == true + case [0, 1, 2] + in [0, _, _] + true + end + RUBY + end + + it "supports using any name with _ at the beginning in a pattern several times" do + eval(<<~RUBY).should == true + case [0, 1, 2] + in [0, _x, _x] + true + end + RUBY + + eval(<<~RUBY).should == true + case {a: 0, b: 1, c: 2} + in {a: 0, b: _x, c: _x} + true + end + RUBY + end + + it "does not support using variable name (except _) several times" do + -> { + eval <<~RUBY + case [0] + in [a, a] + end + RUBY + }.should raise_error(SyntaxError, /duplicated variable name/) + end + + it "supports existing variables in a pattern specified with ^ operator" do + a = 0 + + eval(<<~RUBY).should == true + case 0 + in ^a + true + end + RUBY + end + + it "allows applying ^ operator to bound variables" do + eval(<<~RUBY).should == 1 + case [1, 1] + in [n, ^n] + n + end + RUBY + + eval(<<~RUBY).should == false + case [1, 2] + in [n, ^n] + true + else + false + end + RUBY + end + + it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do + -> { + eval <<~RUBY + case [1, 2] + in [^n, n] + true + else + false + end + RUBY + }.should raise_error(SyntaxError, /n: no such local variable/) + end + end + + describe "alternative pattern" do + it "matches if any of patterns matches" do + eval(<<~RUBY).should == true + case 0 + in 0 | 1 | 2 + true + end + RUBY + end + + it "does not support variable binding" do + -> { + eval <<~RUBY + case [0, 1] + in [0, 0] | [0, a] + end + RUBY + }.should raise_error(SyntaxError, /illegal variable in alternative pattern/) + end + + it "support underscore prefixed variables in alternation" do + eval(<<~RUBY).should == true + case [0, 1] + in [1, _] + false + in [0, 0] | [0, _a] + true + end + RUBY + end + + it "can be used as a nested pattern" do + eval(<<~RUBY).should == true + case [[1], ["2"]] + in [[0] | nil, _] + false + in [[1], [1]] + false + in [[1], [2 | "2"]] + true + end + RUBY + + eval(<<~RUBY).should == true + case [1, 2] + in [0, _] | {a: 0} + false + in {a: 1, b: 2} | [1, 2] + true + end + RUBY + end + end + + describe "AS pattern" do + it "binds a variable to a value if pattern matches" do + eval(<<~RUBY).should == 0 + case 0 + in Integer => n + n + end + RUBY + end + + it "can be used as a nested pattern" do + eval(<<~RUBY).should == [2, 3] + case [1, [2, 3]] + in [1, Array => ary] + ary + end + RUBY + end + end + + describe "Array pattern" do + it "supports form Constant(pat, pat, ...)" do + eval(<<~RUBY).should == true + case [0, 1, 2] + in Array(0, 1, 2) + true + end + RUBY + end + + it "supports form Constant[pat, pat, ...]" do + eval(<<~RUBY).should == true + case [0, 1, 2] + in Array[0, 1, 2] + true + end + RUBY + end + + it "supports form [pat, pat, ...]" do + eval(<<~RUBY).should == true + case [0, 1, 2] + in [0, 1, 2] + true + end + RUBY + end + + it "supports form pat, pat, ..." do + eval(<<~RUBY).should == true + case [0, 1, 2] + in 0, 1, 2 + true + end + RUBY + + eval(<<~RUBY).should == 1 + case [0, 1, 2] + in 0, a, 2 + a + end + RUBY + + eval(<<~RUBY).should == [1, 2] + case [0, 1, 2] + in 0, *rest + rest + end + RUBY + end + + it "matches an object with #deconstruct method which returns an array and each element in array matches element in pattern" do + obj = Object.new + def obj.deconstruct; [0, 1] end + + eval(<<~RUBY).should == true + case obj + in [Integer, Integer] + true + end + RUBY + end + + ruby_version_is "3.0" do + it "calls #deconstruct once for multiple patterns, caching the result" do + obj = Object.new + + def obj.deconstruct + ScratchPad << :deconstruct + [0, 1] + end + + eval(<<~RUBY).should == true + case obj + in [1, 2] + false + in [0, 1] + true + end + RUBY + + ScratchPad.recorded.should == [:deconstruct] + end + end + + it "calls #deconstruct even on objects that are already an array" do + obj = [1, 2] + def obj.deconstruct + ScratchPad << :deconstruct + [3, 4] + end + + eval(<<~RUBY).should == true + case obj + in [3, 4] + true + else + false + end + RUBY + + ScratchPad.recorded.should == [:deconstruct] + end + + it "does not match object if Constant === object returns false" do + eval(<<~RUBY).should == false + case [0, 1, 2] + in String[0, 1, 2] + true + else + false + end + RUBY + end + + it "does not match object without #deconstruct method" do + obj = Object.new + obj.should_receive(:respond_to?).with(:deconstruct) + + eval(<<~RUBY).should == false + case obj + in Object[] + true + else + false + end + RUBY + end + + it "raises TypeError if #deconstruct method does not return array" do + obj = Object.new + def obj.deconstruct; "" end + + -> { + eval <<~RUBY + case obj + in Object[] + else + end + RUBY + }.should raise_error(TypeError, /deconstruct must return Array/) + end + + it "accepts a subclass of Array from #deconstruct" do + obj = Object.new + def obj.deconstruct + subarray = Class.new(Array).new(2) + def subarray.[](n) + n + end + subarray + end + + eval(<<~RUBY).should == true + case obj + in [1, 2] + false + in [0, 1] + true + end + RUBY + end + + it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do + obj = Object.new + def obj.deconstruct; [1] end + + eval(<<~RUBY).should == false + case obj + in Object[0] + true + else + false + end + RUBY + end + + it "binds variables" do + eval(<<~RUBY).should == [0, 1, 2] + case [0, 1, 2] + in [a, b, c] + [a, b, c] + end + RUBY + end + + it "supports splat operator *rest" do + eval(<<~RUBY).should == [1, 2] + case [0, 1, 2] + in [0, *rest] + rest + end + RUBY + end + + it "does not match partially by default" do + eval(<<~RUBY).should == false + case [0, 1, 2, 3] + in [1, 2] + true + else + false + end + RUBY + end + + it "does match partially from the array beginning if list + , syntax used" do + eval(<<~RUBY).should == true + case [0, 1, 2, 3] + in [0, 1,] + true + end + RUBY + + eval(<<~RUBY).should == true + case [0, 1, 2, 3] + in 0, 1,; + true + end + RUBY + end + + it "matches [] with []" do + eval(<<~RUBY).should == true + case [] + in [] + true + end + RUBY + end + + it "matches anything with *" do + eval(<<~RUBY).should == true + case [0, 1] + in *; + true + end + RUBY + end + + it "can be used as a nested pattern" do + eval(<<~RUBY).should == true + case [[1], ["2"]] + in [[0] | nil, _] + false + in [[1], [1]] + false + in [[1], [2 | "2"]] + true + end + RUBY + + eval(<<~RUBY).should == true + case [1, 2] + in [0, _] | {a: 0} + false + in {a: 1, b: 2} | [1, 2] + true + end + RUBY + end + end + + describe "Hash pattern" do + it "supports form Constant(id: pat, id: pat, ...)" do + eval(<<~RUBY).should == true + case {a: 0, b: 1} + in Hash(a: 0, b: 1) + true + end + RUBY + end + + it "supports form Constant[id: pat, id: pat, ...]" do + eval(<<~RUBY).should == true + case {a: 0, b: 1} + in Hash[a: 0, b: 1] + true + end + RUBY + end + + it "supports form {id: pat, id: pat, ...}" do + eval(<<~RUBY).should == true + case {a: 0, b: 1} + in {a: 0, b: 1} + true + end + RUBY + end + + it "supports form id: pat, id: pat, ..." do + eval(<<~RUBY).should == true + case {a: 0, b: 1} + in a: 0, b: 1 + true + end + RUBY + + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in a: a, b: b + [a, b] + end + RUBY + + eval(<<~RUBY).should == { b: 1, c: 2 } + case {a: 0, b: 1, c: 2} + in a: 0, **rest + rest + end + RUBY + end + + it "supports a: which means a: a" do + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in Hash(a:, b:) + [a, b] + end + RUBY + + a = b = nil + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in Hash[a:, b:] + [a, b] + end + RUBY + + a = b = nil + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in {a:, b:} + [a, b] + end + RUBY + + a = nil + eval(<<~RUBY).should == [0, {b: 1, c: 2}] + case {a: 0, b: 1, c: 2} + in {a:, **rest} + [a, rest] + end + RUBY + + a = b = nil + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in a:, b: + [a, b] + end + RUBY + end + + it "can mix key (a:) and key-value (a: b) declarations" do + eval(<<~RUBY).should == [0, 1] + case {a: 0, b: 1} + in Hash(a:, b: x) + [a, x] + end + RUBY + end + + it "supports 'string': key literal" do + eval(<<~RUBY).should == true + case {a: 0} + in {"a": 0} + true + end + RUBY + end + + it "does not support non-symbol keys" do + -> { + eval <<~RUBY + case {a: 1} + in {"a" => 1} + end + RUBY + }.should raise_error(SyntaxError, /unexpected/) + end + + it "does not support string interpolation in keys" do + x = "a" + + -> { + eval <<~'RUBY' + case {a: 1} + in {"#{x}": 1} + end + RUBY + }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/) + end + + it "raise SyntaxError when keys duplicate in pattern" do + -> { + eval <<~RUBY + case {a: 1} + in {a: 1, b: 2, a: 3} + end + RUBY + }.should raise_error(SyntaxError, /duplicated key name/) + end + + it "matches an object with #deconstruct_keys method which returns a Hash with equal keys and each value in Hash matches value in pattern" do + obj = Object.new + def obj.deconstruct_keys(*); {a: 1} end + + eval(<<~RUBY).should == true + case obj + in {a: 1} + true + end + RUBY + end + + it "calls #deconstruct_keys per pattern" do + obj = Object.new + + def obj.deconstruct_keys(*) + ScratchPad << :deconstruct_keys + {a: 1} + end + + eval(<<~RUBY).should == true + case obj + in {b: 1} + false + in {a: 1} + true + end + RUBY + + ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys] + end + + it "does not match object if Constant === object returns false" do + eval(<<~RUBY).should == false + case {a: 1} + in String[a: 1] + true + else + false + end + RUBY + end + + it "does not match object without #deconstruct_keys method" do + obj = Object.new + obj.should_receive(:respond_to?).with(:deconstruct_keys) + + eval(<<~RUBY).should == false + case obj + in Object[a: 1] + true + else + false + end + RUBY + end + + it "does not match object if #deconstruct_keys method does not return Hash" do + obj = Object.new + def obj.deconstruct_keys(*); "" end + + -> { + eval <<~RUBY + case obj + in Object[a: 1] + end + RUBY + }.should raise_error(TypeError, /deconstruct_keys must return Hash/) + end + + it "does not match object if #deconstruct_keys method returns Hash with non-symbol keys" do + obj = Object.new + def obj.deconstruct_keys(*); {"a" => 1} end + + eval(<<~RUBY).should == false + case obj + in Object[a: 1] + true + else + false + end + RUBY + end + + it "does not match object if elements of Hash returned by #deconstruct_keys method does not match values in pattern" do + obj = Object.new + def obj.deconstruct_keys(*); {a: 1} end + + eval(<<~RUBY).should == false + case obj + in Object[a: 2] + true + else + false + end + RUBY + end + + it "passes keys specified in pattern as arguments to #deconstruct_keys method" do + obj = Object.new + + def obj.deconstruct_keys(*args) + ScratchPad << args + {a: 1, b: 2, c: 3} + end + + eval <<~RUBY + case obj + in Object[a: 1, b: 2, c: 3] + end + RUBY + + ScratchPad.recorded.sort.should == [[[:a, :b, :c]]] + end + + it "passes keys specified in pattern to #deconstruct_keys method if pattern contains double splat operator **" do + obj = Object.new + + def obj.deconstruct_keys(*args) + ScratchPad << args + {a: 1, b: 2, c: 3} + end + + eval <<~RUBY + case obj + in Object[a: 1, b: 2, **] + end + RUBY + + ScratchPad.recorded.sort.should == [[[:a, :b]]] + end + + it "passes nil to #deconstruct_keys method if pattern contains double splat operator **rest" do + obj = Object.new + + def obj.deconstruct_keys(*args) + ScratchPad << args + {a: 1, b: 2} + end + + eval <<~RUBY + case obj + in Object[a: 1, **rest] + end + RUBY + + ScratchPad.recorded.should == [[nil]] + end + + it "binds variables" do + eval(<<~RUBY).should == [0, 1, 2] + case {a: 0, b: 1, c: 2} + in {a: x, b: y, c: z} + [x, y, z] + end + RUBY + end + + it "supports double splat operator **rest" do + eval(<<~RUBY).should == {b: 1, c: 2} + case {a: 0, b: 1, c: 2} + in {a: 0, **rest} + rest + end + RUBY + end + + it "treats **nil like there should not be any other keys in a matched Hash" do + eval(<<~RUBY).should == true + case {a: 1, b: 2} + in {a: 1, b: 2, **nil} + true + end + RUBY + + eval(<<~RUBY).should == false + case {a: 1, b: 2} + in {a: 1, **nil} + true + else + false + end + RUBY + end + + it "can match partially" do + eval(<<~RUBY).should == true + case {a: 1, b: 2} + in {a: 1} + true + end + RUBY + end + + it "matches {} with {}" do + eval(<<~RUBY).should == true + case {} + in {} + true + end + RUBY + end + + it "matches anything with **" do + eval(<<~RUBY).should == true + case {a: 1} + in **; + true + end + RUBY + end + + it "can be used as a nested pattern" do + eval(<<~RUBY).should == true + case {a: {a: 1, b: 1}, b: {a: 1, b: 2}} + in {a: {a: 0}} + false + in {a: {a: 1}, b: {b: 1}} + false + in {a: {a: 1}, b: {b: 2}} + true + end + RUBY + + eval(<<~RUBY).should == true + case [{a: 1, b: [1]}, {a: 1, c: ["2"]}] + in [{a:, c:},] + false + in [{a: 1, b:}, {a: 1, c: [Integer]}] + false + in [_, {a: 1, c: [String]}] + true + end + RUBY + end + end + + describe "refinements" do + it "are used for #deconstruct" do + refinery = Module.new do + refine Array do + def deconstruct + [0] + end + end + end + + result = nil + Module.new do + using refinery + + result = eval(<<~RUBY) + case [] + in [0] + true + end + RUBY + end + + result.should == true + end + + it "are used for #deconstruct_keys" do + refinery = Module.new do + refine Hash do + def deconstruct_keys(_) + {a: 0} + end + end + end + + result = nil + Module.new do + using refinery + + result = eval(<<~RUBY) + case {} + in a: 0 + true + end + RUBY + end + + result.should == true + end + + it "are used for #=== in constant pattern" do + refinery = Module.new do + refine Array.singleton_class do + def ===(obj) + obj.is_a?(Hash) + end + end + end + + result = nil + Module.new do + using refinery + + result = eval(<<~RUBY) + case {} + in Array + true + end + RUBY + end + + result.should == true + end + end + + ruby_version_is "3.1" do + it "can omit parentheses in one line pattern matching" do + eval(<<~RUBY).should == [1, 2] + [1, 2] => a, b + [a, b] + RUBY + + eval(<<~RUBY).should == 1 + {a: 1} => a: + a + RUBY + end + end + end +end diff --git a/ruby/spec/ruby/language/predefined_spec.rb b/ruby/spec/ruby/language/predefined_spec.rb index cec6bc852..d31175020 100644 --- a/ruby/spec/ruby/language/predefined_spec.rb +++ b/ruby/spec/ruby/language/predefined_spec.rb @@ -53,10 +53,10 @@ it "is set to nil if the last match was unsuccessful" do /foo/ =~ 'foo' - $~.nil?.should == false + $~.should_not.nil? /foo/ =~ 'bar' - $~.nil?.should == true + $~.should.nil? end it "is set at the method-scoped level rather than block-scoped" do @@ -398,6 +398,22 @@ def bar $!.should == nil end + it "should be cleared when an exception is rescued even when a non-local return from block" do + def foo + [ 1 ].each do + begin + raise StandardError.new('err') + rescue => e + $!.should == e + return + end + end + end + + foo + $!.should == nil + end + it "should not be cleared when an exception is not rescued" do e = StandardError.new begin @@ -502,7 +518,7 @@ def bar Kernel#print and IO#write. The default value is nil. $, String The separator string output between the parameters to methods such as Kernel#print and Array#join. Defaults to nil, which adds no text. -$. Fixnum The number of the last line read from the current input file. +$. Integer The number of the last line read from the current input file. $; String The default separator pattern used by String#split. May be set from the command line using the -F flag. $< Object An object that provides access to the concatenation of the contents of all @@ -528,6 +544,7 @@ def bar describe "Predefined global $/" do before :each do + @verbose, $VERBOSE = $VERBOSE, nil @dollar_slash = $/ @dollar_dash_zero = $-0 end @@ -535,6 +552,7 @@ def bar after :each do $/ = @dollar_slash $-0 = @dollar_dash_zero + $VERBOSE = @verbose end it "can be assigned a String" do @@ -565,7 +583,7 @@ def bar -> { $/ = obj }.should raise_error(TypeError) end - it "raises a TypeError if assigned a Fixnum" do + it "raises a TypeError if assigned an Integer" do -> { $/ = 1 }.should raise_error(TypeError) end @@ -576,6 +594,7 @@ def bar describe "Predefined global $-0" do before :each do + @verbose, $VERBOSE = $VERBOSE, nil @dollar_slash = $/ @dollar_dash_zero = $-0 end @@ -583,6 +602,7 @@ def bar after :each do $/ = @dollar_slash $-0 = @dollar_dash_zero + $VERBOSE = @verbose end it "can be assigned a String" do @@ -612,7 +632,7 @@ def bar -> { $-0 = obj }.should raise_error(TypeError) end - it "raises a TypeError if assigned a Fixnum" do + it "raises a TypeError if assigned an Integer" do -> { $-0 = 1 }.should raise_error(TypeError) end @@ -633,6 +653,12 @@ def bar it "raises TypeError if assigned a non-String" do -> { $, = Object.new }.should raise_error(TypeError) end + + ruby_version_is "2.7" do + it "warns if assigned non-nil" do + -> { $, = "_" }.should complain(/warning: `\$,' is deprecated/) + end + end end describe "Predefined global $." do @@ -662,6 +688,18 @@ def bar end end +describe "Predefined global $;" do + after :each do + $; = nil + end + + ruby_version_is "2.7" do + it "warns if assigned non-nil" do + -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/) + end + end +end + describe "Predefined global $_" do it "is set to the last line read by e.g. StringIO#gets" do stdin = StringIO.new("foo\nbar\n", "r") @@ -743,7 +781,7 @@ def obj.foo2; yield; end tion of the program. Options used by the Ruby interpreter will have been removed. [r/o] $" Array An array containing the filenames of modules loaded by require. [r/o] -$$ Fixnum The process number of the program being executed. [r/o] +$$ Integer The process number of the program being executed. [r/o] $? Process::Status The exit status of the last child process to terminate. [r/o, thread] $: Array An array of strings, where each string specifies a directory to be searched for Ruby scripts and binary extensions used by the load and require methods. @@ -895,6 +933,14 @@ def obj.foo2; yield; end end describe "Global variable $VERBOSE" do + before :each do + @verbose = $VERBOSE + end + + after :each do + $VERBOSE = @verbose + end + it "converts truthy values to true" do [true, 1, 0, [], ""].each do |true_value| $VERBOSE = true_value @@ -1053,8 +1099,8 @@ def obj.foo2; yield; end DATA IO If the main program file contains the directive __END__, then the constant DATA will be initialized so that reading from it will return lines following __END__ from the source file. -FALSE FalseClass Synonym for false. -NIL NilClass Synonym for nil. +FALSE FalseClass Synonym for false (deprecated, removed in Ruby 3). +NIL NilClass Synonym for nil (deprecated, removed in Ruby 3). RUBY_PLATFORM String The identifier of the platform running this program. This string is in the same form as the platform identifier used by the GNU configure utility (which is not a coincidence). @@ -1072,29 +1118,53 @@ def obj.foo2; yield; end the value. TOPLEVEL_BINDING Binding A Binding object representing the binding at Ruby’s top level— the level where programs are initially executed. -TRUE TrueClass Synonym for true. +TRUE TrueClass Synonym for true (deprecated, removed in Ruby 3). =end describe "The predefined global constants" do - it "includes TRUE" do - Object.const_defined?(:TRUE).should == true - -> { - TRUE.should equal(true) - }.should complain(/constant ::TRUE is deprecated/) + describe "TRUE" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:TRUE).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes TRUE" do + Object.const_defined?(:TRUE).should == true + -> { TRUE }.should complain(/constant ::TRUE is deprecated/) + end + end end - it "includes FALSE" do - Object.const_defined?(:FALSE).should == true - -> { - FALSE.should equal(false) - }.should complain(/constant ::FALSE is deprecated/) + describe "FALSE" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:FALSE).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes FALSE" do + Object.const_defined?(:FALSE).should == true + -> { FALSE }.should complain(/constant ::FALSE is deprecated/) + end + end end - it "includes NIL" do - Object.const_defined?(:NIL).should == true - -> { - NIL.should equal(nil) - }.should complain(/constant ::NIL is deprecated/) + describe "NIL" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:NIL).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes NIL" do + Object.const_defined?(:NIL).should == true + -> { NIL }.should complain(/constant ::NIL is deprecated/) + end + end end it "includes STDIN" do @@ -1124,7 +1194,6 @@ def obj.foo2; yield; end it "includes TOPLEVEL_BINDING" do Object.const_defined?(:TOPLEVEL_BINDING).should == true end - end describe "The predefined global constant" do @@ -1139,13 +1208,24 @@ def obj.foo2; yield; end end describe "STDIN" do - it "has the same external encoding as Encoding.default_external" do - STDIN.external_encoding.should equal(Encoding.default_external) - end + platform_is_not :windows do + it "has the same external encoding as Encoding.default_external" do + STDIN.external_encoding.should equal(Encoding.default_external) + end + + it "has the same external encoding as Encoding.default_external when that encoding is changed" do + Encoding.default_external = Encoding::ISO_8859_16 + STDIN.external_encoding.should equal(Encoding::ISO_8859_16) + end - it "has the same external encoding as Encoding.default_external when that encoding is changed" do - Encoding.default_external = Encoding::ISO_8859_16 - STDIN.external_encoding.should equal(Encoding::ISO_8859_16) + it "has nil for the internal encoding" do + STDIN.internal_encoding.should be_nil + end + + it "has nil for the internal encoding despite Encoding.default_internal being changed" do + Encoding.default_internal = Encoding::IBM437 + STDIN.internal_encoding.should be_nil + end end it "has the encodings set by #set_encoding" do @@ -1160,15 +1240,6 @@ def obj.foo2; yield; end "p [STDIN.external_encoding.name, STDIN.internal_encoding.name]" ruby_exe(code).chomp.should == %{["IBM775", "IBM866"]} end - - it "has nil for the internal encoding" do - STDIN.internal_encoding.should be_nil - end - - it "has nil for the internal encoding despite Encoding.default_internal being changed" do - Encoding.default_internal = Encoding::IBM437 - STDIN.internal_encoding.should be_nil - end end describe "STDOUT" do @@ -1232,3 +1303,33 @@ def obj.foo2; yield; end end end end + +ruby_version_is "2.7" do + describe "$LOAD_PATH.resolve_feature_path" do + it "returns what will be loaded without actual loading, .rb file" do + extension, path = $LOAD_PATH.resolve_feature_path('set') + extension.should == :rb + path.should.end_with?('/set.rb') + end + + it "returns what will be loaded without actual loading, .so file" do + require 'rbconfig' + + extension, path = $LOAD_PATH.resolve_feature_path('etc') + extension.should == :so + path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}") + end + + ruby_version_is "2.7"..."3.1" do + it "raises LoadError if feature cannot be found" do + -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError) + end + end + + ruby_version_is "3.1" do + it "return nil if feature cannot be found" do + $LOAD_PATH.resolve_feature_path('noop').should be_nil + end + end + end +end diff --git a/ruby/spec/ruby/language/proc_spec.rb b/ruby/spec/ruby/language/proc_spec.rb index c44e711d2..ef4a43bed 100644 --- a/ruby/spec/ruby/language/proc_spec.rb +++ b/ruby/spec/ruby/language/proc_spec.rb @@ -217,4 +217,30 @@ lambda { @l.call(obj) }.should raise_error(TypeError) end end + + describe "taking |*a, **kw| arguments" do + before :each do + @p = proc { |*a, **kw| [a, kw] } + end + + ruby_version_is ""..."2.7" do + it 'autosplats keyword arguments' do + @p.call([1, {a: 1}]).should == [[1], {a: 1}] + end + end + + ruby_version_is "2.7"..."3.0" do + it 'autosplats keyword arguments and warns' do + -> { + @p.call([1, {a: 1}]).should == [[1], {a: 1}] + }.should complain(/warning: Using the last argument as keyword parameters is deprecated; maybe \*\* should be added to the call/) + end + end + + ruby_version_is "3.0" do + it 'does not autosplat keyword arguments' do + @p.call([1, {a: 1}]).should == [[[1, {a: 1}]], {}] + end + end + end end diff --git a/ruby/spec/ruby/language/range_spec.rb b/ruby/spec/ruby/language/range_spec.rb index c720c5b98..4cde7e948 100644 --- a/ruby/spec/ruby/language/range_spec.rb +++ b/ruby/spec/ruby/language/range_spec.rb @@ -10,10 +10,21 @@ (1...10).should == Range.new(1, 10, true) end - ruby_version_is "2.6" do - it "creates endless ranges" do - eval("(1..)").should == Range.new(1, nil) - eval("(1...)").should == Range.new(1, nil, true) + it "creates endless ranges" do + (1..).should == Range.new(1, nil) + (1...).should == Range.new(1, nil, true) + end + + ruby_version_is "3.0" do + it "is frozen" do + (42..).should.frozen? + end + end + + ruby_version_is "2.7" do + it "creates beginless ranges" do + eval("(..1)").should == Range.new(nil, 1) + eval("(...1)").should == Range.new(nil, 1, true) end end end diff --git a/ruby/spec/ruby/language/regexp/back-references_spec.rb b/ruby/spec/ruby/language/regexp/back-references_spec.rb index 81015ac21..26750c20c 100644 --- a/ruby/spec/ruby/language/regexp/back-references_spec.rb +++ b/ruby/spec/ruby/language/regexp/back-references_spec.rb @@ -47,7 +47,94 @@ /(a\1?){2}/.match("aaaa").to_a.should == ["aa", "a"] end + it "does not reset enclosed capture groups" do + /((a)|(b))+/.match("ab").captures.should == [ "b", "a", "b" ] + end + it "can match an optional quote, followed by content, followed by a matching quote, as the whole string" do /^("|)(.*)\1$/.match('x').to_a.should == ["x", "", "x"] end + + it "allows forward references" do + /(?:(\2)|(.))+/.match("aa").to_a.should == [ "aa", "a", "a" ] + end + + it "disallows forward references >= 10" do + (/\10()()()()()()()()()()/ =~ "\x08").should == 0 + end + + it "fails when trying to match a backreference to an unmatched capture group" do + /\1()/.match("").should == nil + /(?:(a)|b)\1/.match("b").should == nil + end + + it "ignores backreferences > 1000" do + /\99999/.match("99999")[0].should == "99999" + end + + it "0 is not a valid backreference" do + -> { Regexp.new("\\k<0>") }.should raise_error(RegexpError) + end + + it "allows numeric conditional backreferences" do + /(a)(?(1)a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?(<1>)a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?('1')a|b)/.match("aa").to_a.should == [ "aa", "a" ] + end + + it "allows either <> or '' in named conditional backreferences" do + -> { Regexp.new("(?a)(?(a)a|b)") }.should raise_error(RegexpError) + /(?a)(?()a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)(?('a')a|b)/.match("aa").to_a.should == [ "aa", "a" ] + end + + it "allows negative numeric backreferences" do + /(a)\k<-1>/.match("aa").to_a.should == [ "aa", "a" ] + /(a)\g<-1>/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?(<-1>)a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?('-1')a|b)/.match("aa").to_a.should == [ "aa", "a" ] + end + + it "delimited numeric backreferences can start with 0" do + /(a)\k<01>/.match("aa").to_a.should == [ "aa", "a" ] + /(a)\g<01>/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?(01)a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?(<01>)a|b)/.match("aa").to_a.should == [ "aa", "a" ] + /(a)(?('01')a|b)/.match("aa").to_a.should == [ "aa", "a" ] + end + + it "regular numeric backreferences cannot start with 0" do + /(a)\01/.match("aa").should == nil + /(a)\01/.match("a\x01").to_a.should == [ "a\x01", "a" ] + end + + it "named capture groups invalidate numeric backreferences" do + -> { Regexp.new("(?a)\\1") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k<1>") }.should raise_error(RegexpError) + -> { Regexp.new("(a)(?a)\\1") }.should raise_error(RegexpError) + -> { Regexp.new("(a)(?a)\\k<1>") }.should raise_error(RegexpError) + end + + it "treats + or - as the beginning of a level specifier in \\k<> backreferences and (?(...)...|...) conditional backreferences" do + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)\\k") }.should raise_error(RegexpError) + + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?()a|b)") }.should raise_error(RegexpError) + + -> { Regexp.new("(?a)(?('a+')a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?('a+b')a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?('a+1')a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?('a-')a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?('a-b')a|b)") }.should raise_error(RegexpError) + -> { Regexp.new("(?a)(?('a-1')a|b)") }.should raise_error(RegexpError) + end end diff --git a/ruby/spec/ruby/language/regexp/character_classes_spec.rb b/ruby/spec/ruby/language/regexp/character_classes_spec.rb index 5f4221e21..0cf1e9b6f 100644 --- a/ruby/spec/ruby/language/regexp/character_classes_spec.rb +++ b/ruby/spec/ruby/language/regexp/character_classes_spec.rb @@ -609,6 +609,12 @@ "루비(Ruby)".match(/\p{Hangul}+/u).to_a.should == ["루비"] end + ruby_bug "#17340", ''...'3.0' do + it "raises a RegexpError for an unterminated unicode property" do + -> { Regexp.new('\p{') }.should raise_error(RegexpError) + end + end + it "supports \\X (unicode 9.0 with UTR #51 workarounds)" do # simple emoji without any fancy modifier or ZWJ /\X/.match("\u{1F98A}").to_a.should == ["🦊"] diff --git a/ruby/spec/ruby/language/regexp/empty_checks_spec.rb b/ruby/spec/ruby/language/regexp/empty_checks_spec.rb new file mode 100644 index 000000000..391e65b00 --- /dev/null +++ b/ruby/spec/ruby/language/regexp/empty_checks_spec.rb @@ -0,0 +1,135 @@ +require_relative '../../spec_helper' +require_relative '../fixtures/classes' + +describe "empty checks in Regexps" do + + it "allow extra empty iterations" do + /()?/.match("").to_a.should == ["", ""] + /(a*)?/.match("").to_a.should == ["", ""] + /(a*)*/.match("").to_a.should == ["", ""] + # The bounds are high to avoid DFA-based matchers in implementations + # and to check backtracking behavior. + /(?:a|()){500,1000}/.match("a" * 500).to_a.should == ["a" * 500, ""] + + # Variations with non-greedy loops. + /()??/.match("").to_a.should == ["", nil] + /(a*?)?/.match("").to_a.should == ["", ""] + /(a*)??/.match("").to_a.should == ["", nil] + /(a*?)??/.match("").to_a.should == ["", nil] + /(a*?)*/.match("").to_a.should == ["", ""] + /(a*)*?/.match("").to_a.should == ["", nil] + /(a*?)*?/.match("").to_a.should == ["", nil] + end + + it "allow empty iterations in the middle of a loop" do + # One empty iteration between a's and b's. + /(a|\2b|())*/.match("aaabbb").to_a.should == ["aaabbb", "", ""] + /(a|\2b|()){2,4}/.match("aaabbb").to_a.should == ["aaa", "", ""] + + # Two empty iterations between a's and b's. + /(a|\2b|\3()|())*/.match("aaabbb").to_a.should == ["aaabbb", "", "", ""] + /(a|\2b|\3()|()){2,4}/.match("aaabbb").to_a.should == ["aaa", "", nil, ""] + + # Check that the empty iteration correctly updates the loop counter. + /(a|\2b|()){20,24}/.match("a" * 20 + "b" * 5).to_a.should == ["a" * 20 + "b" * 3, "b", ""] + + # Variations with non-greedy loops. + /(a|\2b|())*?/.match("aaabbb").to_a.should == ["", nil, nil] + /(a|\2b|()){2,4}/.match("aaabbb").to_a.should == ["aaa", "", ""] + /(a|\2b|\3()|())*?/.match("aaabbb").to_a.should == ["", nil, nil, nil] + /(a|\2b|\3()|()){2,4}/.match("aaabbb").to_a.should == ["aaa", "", nil, ""] + /(a|\2b|()){20,24}/.match("a" * 20 + "b" * 5).to_a.should == ["a" * 20 + "b" * 3, "b", ""] + end + + it "make the Regexp proceed past the quantified expression on failure" do + # If the contents of the ()* quantified group are empty (i.e., they fail + # the empty check), the loop will abort. It will not try to backtrack + # and try other alternatives (e.g. matching the "a") like in other Regexp + # dialects such as ECMAScript. + /(?:|a)*/.match("aaa").to_a.should == [""] + /(?:()|a)*/.match("aaa").to_a.should == ["", ""] + /(|a)*/.match("aaa").to_a.should == ["", ""] + /(()|a)*/.match("aaa").to_a.should == ["", "", ""] + + # Same expressions, but with backreferences, to force the use of non-DFA-based + # engines. + /()\1(?:|a)*/.match("aaa").to_a.should == ["", ""] + /()\1(?:()|a)*/.match("aaa").to_a.should == ["", "", ""] + /()\1(|a)*/.match("aaa").to_a.should == ["", "", ""] + /()\1(()|a)*/.match("aaa").to_a.should == ["", "", "", ""] + + # Variations with other zero-width contents of the quantified + # group: backreferences, capture groups, lookarounds + /()(?:\1|a)*/.match("aaa").to_a.should == ["", ""] + /()(?:()\1|a)*/.match("aaa").to_a.should == ["", "", ""] + /()(?:(\1)|a)*/.match("aaa").to_a.should == ["", "", ""] + /()(?:\1()|a)*/.match("aaa").to_a.should == ["", "", ""] + /()(\1|a)*/.match("aaa").to_a.should == ["", "", ""] + /()(()\1|a)*/.match("aaa").to_a.should == ["", "", "", ""] + /()((\1)|a)*/.match("aaa").to_a.should == ["", "", "", ""] + /()(\1()|a)*/.match("aaa").to_a.should == ["", "", "", ""] + + /(?:(?=a)|a)*/.match("aaa").to_a.should == [""] + /(?:(?=a)()|a)*/.match("aaa").to_a.should == ["", ""] + /(?:()(?=a)|a)*/.match("aaa").to_a.should == ["", ""] + /(?:((?=a))|a)*/.match("aaa").to_a.should == ["", ""] + /()\1(?:(?=a)|a)*/.match("aaa").to_a.should == ["", ""] + /()\1(?:(?=a)()|a)*/.match("aaa").to_a.should == ["", "", ""] + /()\1(?:()(?=a)|a)*/.match("aaa").to_a.should == ["", "", ""] + /()\1(?:((?=a))|a)*/.match("aaa").to_a.should == ["", "", ""] + + # Variations with non-greedy loops. + /(?:|a)*?/.match("aaa").to_a.should == [""] + /(?:()|a)*?/.match("aaa").to_a.should == ["", nil] + /(|a)*?/.match("aaa").to_a.should == ["", nil] + /(()|a)*?/.match("aaa").to_a.should == ["", nil, nil] + + /()\1(?:|a)*?/.match("aaa").to_a.should == ["", ""] + /()\1(?:()|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()\1(|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()\1(()|a)*?/.match("aaa").to_a.should == ["", "", nil, nil] + + /()(?:\1|a)*?/.match("aaa").to_a.should == ["", ""] + /()(?:()\1|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()(?:(\1)|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()(?:\1()|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()(\1|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()(()\1|a)*?/.match("aaa").to_a.should == ["", "", nil, nil] + /()((\1)|a)*?/.match("aaa").to_a.should == ["", "", nil, nil] + /()(\1()|a)*?/.match("aaa").to_a.should == ["", "", nil, nil] + + /(?:(?=a)|a)*?/.match("aaa").to_a.should == [""] + /(?:(?=a)()|a)*?/.match("aaa").to_a.should == ["", nil] + /(?:()(?=a)|a)*?/.match("aaa").to_a.should == ["", nil] + /(?:((?=a))|a)*?/.match("aaa").to_a.should == ["", nil] + /()\1(?:(?=a)|a)*?/.match("aaa").to_a.should == ["", ""] + /()\1(?:(?=a)()|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()\1(?:()(?=a)|a)*?/.match("aaa").to_a.should == ["", "", nil] + /()\1(?:((?=a))|a)*?/.match("aaa").to_a.should == ["", "", nil] + end + + it "shouldn't cause the Regexp parser to get stuck in a loop" do + /(|a|\2b|())*/.match("aaabbb").to_a.should == ["", "", nil] + /(a||\2b|())*/.match("aaabbb").to_a.should == ["aaa", "", nil] + /(a|\2b||())*/.match("aaabbb").to_a.should == ["aaa", "", nil] + /(a|\2b|()|)*/.match("aaabbb").to_a.should == ["aaabbb", "", ""] + /(()|a|\3b|())*/.match("aaabbb").to_a.should == ["", "", "", nil] + /(a|()|\3b|())*/.match("aaabbb").to_a.should == ["aaa", "", "", nil] + /(a|\2b|()|())*/.match("aaabbb").to_a.should == ["aaabbb", "", "", nil] + /(a|\3b|()|())*/.match("aaabbb").to_a.should == ["aaa", "", "", nil] + /(a|()|())*/.match("aaa").to_a.should == ["aaa", "", "", nil] + /^(()|a|())*$/.match("aaa").to_a.should == ["aaa", "", "", nil] + + # Variations with non-greedy loops. + /(|a|\2b|())*?/.match("aaabbb").to_a.should == ["", nil, nil] + /(a||\2b|())*?/.match("aaabbb").to_a.should == ["", nil, nil] + /(a|\2b||())*?/.match("aaabbb").to_a.should == ["", nil, nil] + /(a|\2b|()|)*?/.match("aaabbb").to_a.should == ["", nil, nil] + /(()|a|\3b|())*?/.match("aaabbb").to_a.should == ["", nil, nil, nil] + /(a|()|\3b|())*?/.match("aaabbb").to_a.should == ["", nil, nil, nil] + /(a|\2b|()|())*?/.match("aaabbb").to_a.should == ["", nil, nil, nil] + /(a|\3b|()|())*?/.match("aaabbb").to_a.should == ["", nil, nil, nil] + /(a|()|())*?/.match("aaa").to_a.should == ["", nil, nil, nil] + /^(()|a|())*?$/.match("aaa").to_a.should == ["aaa", "a", "", nil] + end +end diff --git a/ruby/spec/ruby/language/regexp/encoding_spec.rb b/ruby/spec/ruby/language/regexp/encoding_spec.rb index b8559c6b2..febc3fdb3 100644 --- a/ruby/spec/ruby/language/regexp/encoding_spec.rb +++ b/ruby/spec/ruby/language/regexp/encoding_spec.rb @@ -38,6 +38,10 @@ /#{/./}/n.match("\303\251").to_a.should == ["\303"] end + it "warns when using /n with a match string with non-ASCII characters and an encoding other than ASCII-8BIT" do + -> { /./n.match("\303\251".force_encoding('utf-8')) }.should complain(%r{historical binary regexp match /.../n against UTF-8 string}) + end + it 'uses US-ASCII as /n encoding if all chars are 7-bit' do /./n.encoding.should == Encoding::US_ASCII end @@ -116,4 +120,29 @@ it "raises Encoding::CompatibilityError when trying =~ against different encodings" do -> { /\A[[:space:]]*\z/ =~ " ".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError) end + + it "raises Encoding::CompatibilityError when the regexp has a fixed, non-ASCII-compatible encoding" do + -> { Regexp.new("".force_encoding("UTF-16LE"), Regexp::FIXEDENCODING) =~ " ".encode("UTF-8") }.should raise_error(Encoding::CompatibilityError) + end + + it "raises Encoding::CompatibilityError when the regexp has a fixed encoding and the match string has non-ASCII characters" do + -> { Regexp.new("".force_encoding("US-ASCII"), Regexp::FIXEDENCODING) =~ "\303\251".force_encoding('UTF-8') }.should raise_error(Encoding::CompatibilityError) + end + + it "raises ArgumentError when trying to match a broken String" do + s = "\x80".force_encoding('UTF-8') + -> { s =~ /./ }.should raise_error(ArgumentError, "invalid byte sequence in UTF-8") + end + + it "computes the Regexp Encoding for each interpolated Regexp instance" do + make_regexp = -> str { /#{str}/ } + + r = make_regexp.call("été".force_encoding(Encoding::UTF_8)) + r.should.fixed_encoding? + r.encoding.should == Encoding::UTF_8 + + r = make_regexp.call("abc".force_encoding(Encoding::UTF_8)) + r.should_not.fixed_encoding? + r.encoding.should == Encoding::US_ASCII + end end diff --git a/ruby/spec/ruby/language/regexp/escapes_spec.rb b/ruby/spec/ruby/language/regexp/escapes_spec.rb index 14e1424d4..2e5fe5ad2 100644 --- a/ruby/spec/ruby/language/regexp/escapes_spec.rb +++ b/ruby/spec/ruby/language/regexp/escapes_spec.rb @@ -78,4 +78,20 @@ # \M-x meta (x|0x80) (character code point value) # \M-\C-x meta control char (character code point value) end + + it "handles three digit octal escapes starting with 0" do + /[\000-\b]/.match("\x00")[0].should == "\x00" + end + + it "handles control escapes with \\C-x syntax" do + /\C-*\C-J\C-j/.match("\n\n\n")[0].should == "\n\n\n" + end + + it "supports the \\K keep operator" do + /a\Kb/.match("ab")[0].should == "b" + end + + it "supports the \\R line break escape" do + /\R/.match("\n")[0].should == "\n" + end end diff --git a/ruby/spec/ruby/language/regexp/grouping_spec.rb b/ruby/spec/ruby/language/regexp/grouping_spec.rb index 8806d0674..2f04a0401 100644 --- a/ruby/spec/ruby/language/regexp/grouping_spec.rb +++ b/ruby/spec/ruby/language/regexp/grouping_spec.rb @@ -20,4 +20,44 @@ # Parsing precedence /(?:xdigit:)/.match("xdigit:").to_a.should == ["xdigit:"] end + + it "group names cannot start with digits or minus" do + -> { Regexp.new("(?<1a>a)") }.should raise_error(RegexpError) + -> { Regexp.new("(?<-a>a)") }.should raise_error(RegexpError) + end + + it "ignore capture groups in line comments" do + /^ + (a) # there is a capture group on this line + b # there is no capture group on this line (not even here) + $/x.match("ab").to_a.should == [ "ab", "a" ] + end + + it "does not consider # inside a character class as a comment" do + # From https://github.com/rubocop/rubocop/blob/39fcf1c568/lib/rubocop/cop/utils/format_string.rb#L18 + regexp = / + % (?%) # line comment + | % (?(?-mix:[ #0+-]|(?-mix:(\d+)\$))*) (?#group comment) + (?: + (?: (?-mix:(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:<(?\w+)>)? + | (?-mix:(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:<(?\w+)>) (?-mix:\.(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? + | (?-mix:<(?\w+)>) (?(?-mix:[ #0+-]|(?-mix:(\d+)\$))*) (?-mix:(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? + ) (?-mix:(?[bBdiouxXeEfgGaAcps])) + | (?-mix:(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\{(?\w+)\}) + ) + /x + regexp.named_captures.should == { + "type" => [1, 13], + "flags" => [2], + "width" => [3, 6, 11, 14], + "precision" => [4, 8, 12, 15], + "name" => [5, 7, 9, 16], + "more_flags" => [10] + } + match = regexp.match("%6.3f") + match[:width].should == '6' + match[:precision].should == '3' + match[:type].should == 'f' + match.to_a.should == [ "%6.3f", nil, "", "6", "3"] + [nil] * 8 + ["f"] + [nil] * 3 + end end diff --git a/ruby/spec/ruby/language/regexp/interpolation_spec.rb b/ruby/spec/ruby/language/regexp/interpolation_spec.rb index ed0b72476..6951fd38c 100644 --- a/ruby/spec/ruby/language/regexp/interpolation_spec.rb +++ b/ruby/spec/ruby/language/regexp/interpolation_spec.rb @@ -36,7 +36,7 @@ def o.to_s it "gives precedence to escape sequences over substitution" do str = "J" - /\c#{str}/.to_s.should == '(?-mix:\c#' + '{str})' + /\c#{str}/.to_s.should include('{str}') end it "throws RegexpError for malformed interpolation" do diff --git a/ruby/spec/ruby/language/regexp/repetition_spec.rb b/ruby/spec/ruby/language/regexp/repetition_spec.rb index 7bb767cca..9a191d74e 100644 --- a/ruby/spec/ruby/language/regexp/repetition_spec.rb +++ b/ruby/spec/ruby/language/regexp/repetition_spec.rb @@ -45,4 +45,98 @@ /a?/.match("aaa").to_a.should == ["a"] /a?/.match("bbb").to_a.should == [""] end + + it "handles incomplete range quantifiers" do + /a{}/.match("a{}")[0].should == "a{}" + /a{,}/.match("a{,}")[0].should == "a{,}" + /a{1/.match("a{1")[0].should == "a{1" + /a{1,2/.match("a{1,2")[0].should == "a{1,2" + /a{,5}/.match("aaa")[0].should == "aaa" + end + + it "lets us use quantifiers on assertions" do + /a^?b/.match("ab")[0].should == "ab" + /a$?b/.match("ab")[0].should == "ab" + /a\A?b/.match("ab")[0].should == "ab" + /a\Z?b/.match("ab")[0].should == "ab" + /a\z?b/.match("ab")[0].should == "ab" + /a\G?b/.match("ab")[0].should == "ab" + /a\b?b/.match("ab")[0].should == "ab" + /a\B?b/.match("ab")[0].should == "ab" + /a(?=c)?b/.match("ab")[0].should == "ab" + /a(?!=b)?b/.match("ab")[0].should == "ab" + /a(?<=c)?b/.match("ab")[0].should == "ab" + /a(?/.match("aa").to_a.should == [ "aa", "a" ] + end + + it "treats subexpression calls as distinct from simple back-references" do + # Back-references only match a string which is equal to the original captured string. + /(?[0-9]{3})-\k/.match("123-123")[0].should == "123-123" + /(?[0-9]{3})-\k/.match("123-456").should == nil + # However, subexpression calls reuse the previous expression and can match a different + # string. + /(?[0-9]{3})-\g/.match("123-456")[0].should == "123-456" + end + + it "allows recursive subexpression calls" do + # This pattern matches well-nested parenthesized expression. + parens = /^ (? (?: \( \g \) | [^()] )* ) $/x + parens.match("((a)(b))c(d)")[0].should == "((a)(b))c(d)" + parens.match("((a)(b)c(d)").should == nil + end + + it "allows access to back-references from the current level" do + # Using \\k accesses the last value captured in first_char + # on the current stack level. + mirror = /^ (? (?: (?.) \g \k )? ) $/x + mirror.match("abccba")[0].should == "abccba" + mirror.match("abccbd").should == nil + + # OTOH, using \\k accesses the last value captured in first_char, + # regardless of the stack level. Therefore, it can't be used to implement + # the mirror language. + broken_mirror = /^ (? (?: (?.) \g \k )? ) $/x + broken_mirror.match("abccba").should == nil + # This matches because the 'c' is captured in first_char and that value is + # then used for all subsequent back-references, regardless of nesting. + broken_mirror.match("abcccc")[0].should == "abcccc" + end + + it "allows + and - in group names and referential constructs that don't use levels, i.e. subexpression calls" do + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + /(?a)\g/.match("aa").to_a.should == [ "aa", "a" ] + end +end diff --git a/ruby/spec/ruby/language/regexp_spec.rb b/ruby/spec/ruby/language/regexp_spec.rb index 67c7c034e..f607fa601 100644 --- a/ruby/spec/ruby/language/regexp_spec.rb +++ b/ruby/spec/ruby/language/regexp_spec.rb @@ -18,6 +18,12 @@ /Hello/.should be_kind_of(Regexp) end + ruby_version_is "3.0" do + it "is frozen" do + /Hello/.should.frozen? + end + end + it "caches the Regexp object" do rs = [] 2.times do |i| @@ -109,6 +115,13 @@ /foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"] end + ruby_bug "#13671", ""..."3.2" do # https://bugs.ruby-lang.org/issues/13671 + it "handles a lookbehind with ss characters" do + r = Regexp.new("(? e - e.message.should == "some text" + describe 'can capture the raised exception' do + before :all do + require_relative 'fixtures/rescue_captures' + end + + it 'in a local variable' do + RescueSpecs::LocalVariableCaptor.should_capture_exception + end + + it 'in a class variable' do + RescueSpecs::ClassVariableCaptor.should_capture_exception + end + + it 'in a constant' do + RescueSpecs::ConstantCaptor.should_capture_exception + end + + it 'in a global variable' do + RescueSpecs::GlobalVariableCaptor.should_capture_exception + end + + it 'in an instance variable' do + RescueSpecs::InstanceVariableCaptor.should_capture_exception + end + + it 'using a safely navigated setter method' do + RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception + end + + it 'using a setter method' do + RescueSpecs::SetterCaptor.should_capture_exception + end + + it 'using a square brackets setter' do + RescueSpecs::SquareBracketsCaptor.should_capture_exception end end @@ -208,34 +238,16 @@ class ArbitraryException < StandardError ScratchPad.recorded.should == [:one, :else_ran, :ensure_ran, :outside_begin] end - ruby_version_is ''...'2.6' do - it "will execute an else block even without rescue and ensure" do - -> { - eval <<-ruby - begin - ScratchPad << :begin - else - ScratchPad << :else - end - ruby - }.should complain(/else without rescue is useless/) - - ScratchPad.recorded.should == [:begin, :else] - end - end - - ruby_version_is '2.6' do - it "raises SyntaxError when else is used without rescue and ensure" do - -> { - eval <<-ruby - begin - ScratchPad << :begin - else - ScratchPad << :else - end - ruby - }.should raise_error(SyntaxError, /else without rescue is useless/) - end + it "raises SyntaxError when else is used without rescue and ensure" do + -> { + eval <<-ruby + begin + ScratchPad << :begin + else + ScratchPad << :else + end + ruby + }.should raise_error(SyntaxError, /else without rescue is useless/) end it "will not execute an else block if an exception was raised" do @@ -398,9 +410,9 @@ def rescuer.===(exception) raise "from block" rescue (raise "from rescue expression") end - }.should raise_error(RuntimeError, "from rescue expression") do |e| + }.should raise_error(RuntimeError, "from rescue expression") { |e| e.cause.message.should == "from block" - end + } end it "should splat the handling Error classes" do @@ -435,18 +447,16 @@ class RescueInClassExample }.should raise_error(SyntaxError) end - ruby_version_is "2.5" do - it "allows rescue in 'do end' block" do - lambda = eval <<-ruby - lambda do - raise SpecificExampleException - rescue SpecificExampleException - ScratchPad << :caught - end.call - ruby + it "allows rescue in 'do end' block" do + lambda = eval <<-ruby + lambda do + raise SpecificExampleException + rescue SpecificExampleException + ScratchPad << :caught + end.call + ruby - ScratchPad.recorded.should == [:caught] - end + ScratchPad.recorded.should == [:caught] end it "allows 'rescue' in method arguments" do @@ -481,5 +491,15 @@ class RescueInClassExample a = raise(Exception) rescue 1 }.should raise_error(Exception) end + + ruby_version_is "2.7" do + it "rescues with multiple assignment" do + + a, b = raise rescue [1, 2] + + a.should == 1 + b.should == 2 + end + end end end diff --git a/ruby/spec/ruby/language/return_spec.rb b/ruby/spec/ruby/language/return_spec.rb index 7eef6d06c..d8506834c 100644 --- a/ruby/spec/ruby/language/return_spec.rb +++ b/ruby/spec/ruby/language/return_spec.rb @@ -250,260 +250,238 @@ def f end end - ruby_version_is '2.4.2' do - describe "at top level" do - before :each do - @filename = tmp("top_return.rb") - ScratchPad.record [] - end + describe "at top level" do + before :each do + @filename = tmp("top_return.rb") + ScratchPad.record [] + end - after do - rm_r @filename - end + after do + rm_r @filename + end - it "stops file execution" do - ruby_exe(<<-END_OF_CODE).should == "before return\n" - puts "before return" - return + it "stops file execution" do + ruby_exe(<<-END_OF_CODE).should == "before return\n" + puts "before return" + return - puts "after return" - END_OF_CODE + puts "after return" + END_OF_CODE - $?.exitstatus.should == 0 - end + $?.exitstatus.should == 0 + end - describe "within if" do - it "is allowed" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before if" - if true - return - end + describe "within if" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before if" + if true + return + end - ScratchPad << "after if" - END_OF_CODE + ScratchPad << "after if" + END_OF_CODE - load @filename - ScratchPad.recorded.should == ["before if"] - end + load @filename + ScratchPad.recorded.should == ["before if"] end + end - describe "within while loop" do - it "is allowed" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before while" - while true - return - end + describe "within while loop" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before while" + while true + return + end - ScratchPad << "after while" - END_OF_CODE + ScratchPad << "after while" + END_OF_CODE - load @filename - ScratchPad.recorded.should == ["before while"] - end + load @filename + ScratchPad.recorded.should == ["before while"] end + end - describe "within a begin" do - it "is allowed in begin block" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before begin" - begin - return - end - - ScratchPad << "after begin" - END_OF_CODE - - load @filename - ScratchPad.recorded.should == ["before begin"] - end + describe "within a begin" do + it "is allowed in begin block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + return + end - it "is allowed in ensure block" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before begin" - begin - ensure - return - end + ScratchPad << "after begin" + END_OF_CODE - ScratchPad << "after begin" - END_OF_CODE + load @filename + ScratchPad.recorded.should == ["before begin"] + end - load @filename - ScratchPad.recorded.should == ["before begin"] - end + it "is allowed in ensure block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + ensure + return + end - it "is allowed in rescue block" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before begin" - begin - raise - rescue RuntimeError - return - end + ScratchPad << "after begin" + END_OF_CODE - ScratchPad << "after begin" - END_OF_CODE + load @filename + ScratchPad.recorded.should == ["before begin"] + end - load @filename - ScratchPad.recorded.should == ["before begin"] - end + it "is allowed in rescue block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + raise + rescue RuntimeError + return + end - it "fires ensure block before returning" do - ruby_exe(<<-END_OF_CODE).should == "within ensure\n" - begin - return - ensure - puts "within ensure" - end + ScratchPad << "after begin" + END_OF_CODE - puts "after begin" - END_OF_CODE - end + load @filename + ScratchPad.recorded.should == ["before begin"] + end - ruby_bug "#14061", "2.4"..."2.5" do - it "fires ensure block before returning while loads file" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before begin" - begin - return - ensure - ScratchPad << "within ensure" - end - - ScratchPad << "after begin" - END_OF_CODE - - load @filename - ScratchPad.recorded.should == ["before begin", "within ensure"] + it "fires ensure block before returning" do + ruby_exe(<<-END_OF_CODE).should == "within ensure\n" + begin + return + ensure + puts "within ensure" end - end - it "swallows exception if returns in ensure block" do - File.write(@filename, <<-END_OF_CODE) - begin - raise - ensure - ScratchPad << "before return" - return - end - END_OF_CODE - - load @filename - ScratchPad.recorded.should == ["before return"] - end + puts "after begin" + END_OF_CODE end - describe "within a block" do - it "is allowed" do - File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before call" - proc { return }.call + it "fires ensure block before returning while loads file" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + return + ensure + ScratchPad << "within ensure" + end - ScratchPad << "after call" - END_OF_CODE + ScratchPad << "after begin" + END_OF_CODE - load @filename - ScratchPad.recorded.should == ["before call"] - end + load @filename + ScratchPad.recorded.should == ["before begin", "within ensure"] end - describe "within a class" do - ruby_version_is ""..."2.5" do - it "is allowed" do - File.write(@filename, <<-END_OF_CODE) - class ReturnSpecs::A - ScratchPad << "before return" - return - - ScratchPad << "after return" - end - END_OF_CODE - - load @filename - ScratchPad.recorded.should == ["before return"] + it "swallows exception if returns in ensure block" do + File.write(@filename, <<-END_OF_CODE) + begin + raise + ensure + ScratchPad << "before return" + return end - end + END_OF_CODE - ruby_version_is "2.5" do - it "raises a SyntaxError" do - File.write(@filename, <<-END_OF_CODE) - class ReturnSpecs::A - ScratchPad << "before return" - return + load @filename + ScratchPad.recorded.should == ["before return"] + end + end - ScratchPad << "after return" - end - END_OF_CODE + describe "within a block" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before call" + proc { return }.call - -> { load @filename }.should raise_error(SyntaxError) - end - end - end + ScratchPad << "after call" + END_OF_CODE - describe "within a block within a class" do - ruby_version_is "2.7" do - it "is not allowed" do - File.write(@filename, <<-END_OF_CODE) - class ReturnSpecs::A - ScratchPad << "before return" - 1.times { return } - ScratchPad << "after return" - end - END_OF_CODE - - -> { load @filename }.should raise_error(LocalJumpError) - end - end + load @filename + ScratchPad.recorded.should == ["before call"] end + end - describe "file loading" do - it "stops file loading and execution" do - File.write(@filename, <<-END_OF_CODE) + describe "within a class" do + it "raises a SyntaxError" do + File.write(@filename, <<-END_OF_CODE) + class ReturnSpecs::A ScratchPad << "before return" return + ScratchPad << "after return" - END_OF_CODE + end + END_OF_CODE - load @filename - ScratchPad.recorded.should == ["before return"] - end + -> { load @filename }.should raise_error(SyntaxError) end + end - describe "file requiring" do - it "stops file loading and execution" do + describe "within a block within a class" do + ruby_version_is "2.7" do + it "is not allowed" do File.write(@filename, <<-END_OF_CODE) - ScratchPad << "before return" - return - ScratchPad << "after return" + class ReturnSpecs::A + ScratchPad << "before return" + 1.times { return } + ScratchPad << "after return" + end END_OF_CODE - require @filename - ScratchPad.recorded.should == ["before return"] + -> { load @filename }.should raise_error(LocalJumpError) end end + end - describe "return with argument" do - ruby_version_is ""..."2.7" do - it "does not affect exit status" do - ruby_exe(<<-END_OF_CODE).should == "" - return 10 - END_OF_CODE + describe "file loading" do + it "stops file loading and execution" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before return" + return + ScratchPad << "after return" + END_OF_CODE - $?.exitstatus.should == 0 - end + load @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "file requiring" do + it "stops file loading and execution" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before return" + return + ScratchPad << "after return" + END_OF_CODE + + require @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "return with argument" do + ruby_version_is ""..."2.7" do + it "does not affect exit status" do + ruby_exe(<<-END_OF_CODE).should == "" + return 10 + END_OF_CODE + + $?.exitstatus.should == 0 end + end - ruby_version_is "2.7" do - it "warns but does not affect exit status" do - err = ruby_exe(<<-END_OF_CODE, args: "2>&1") - return 10 - END_OF_CODE - $?.exitstatus.should == 0 + ruby_version_is "2.7" do + it "warns but does not affect exit status" do + err = ruby_exe(<<-END_OF_CODE, args: "2>&1") + return 10 + END_OF_CODE + $?.exitstatus.should == 0 - err.should =~ /warning: argument of top-level return is ignored/ - end + err.should =~ /warning: argument of top-level return is ignored/ end end end diff --git a/ruby/spec/ruby/language/safe_spec.rb b/ruby/spec/ruby/language/safe_spec.rb index 53ab4f956..89830a206 100644 --- a/ruby/spec/ruby/language/safe_spec.rb +++ b/ruby/spec/ruby/language/safe_spec.rb @@ -2,10 +2,8 @@ describe "The $SAFE variable" do ruby_version_is ""..."2.7" do - ruby_version_is "2.6" do - after :each do - $SAFE = 0 - end + after :each do + $SAFE = 0 end it "is 0 by default" do @@ -39,24 +37,12 @@ end end - ruby_version_is ""..."2.6" do - it "cannot be set to values below 0" do - -> { - proc { - $SAFE = -100 - }.call - }.should raise_error(SecurityError, /tried to downgrade safe level from 0 to -100/) - end - end - - ruby_version_is "2.6" do - it "raises ArgumentError when set to values below 0" do - -> { - proc { - $SAFE = -100 - }.call - }.should raise_error(ArgumentError, "$SAFE should be >= 0") - end + it "raises ArgumentError when set to values below 0" do + -> { + proc { + $SAFE = -100 + }.call + }.should raise_error(ArgumentError, "$SAFE should be >= 0") end it "cannot be set to values above 4" do @@ -67,61 +53,32 @@ }.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/) end - ruby_version_is ""..."2.6" do - it "cannot be manually lowered" do - proc { - $SAFE = 1 - -> { - $SAFE = 0 - }.should raise_error(SecurityError, /tried to downgrade safe level from 1 to 0/) - }.call - end - - it "is automatically lowered when leaving a proc" do - $SAFE.should == 0 - proc { - $SAFE = 1 - }.call - $SAFE.should == 0 - end - - it "is automatically lowered when leaving a lambda" do - $SAFE.should == 0 - -> { - $SAFE = 1 - }.call - $SAFE.should == 0 - end + it "can be manually lowered" do + $SAFE = 1 + $SAFE = 0 + $SAFE.should == 0 end - ruby_version_is "2.6" do - it "can be manually lowered" do + it "is not Proc local" do + $SAFE.should == 0 + proc { $SAFE = 1 - $SAFE = 0 - $SAFE.should == 0 - end - - it "is not Proc local" do - $SAFE.should == 0 - proc { - $SAFE = 1 - }.call - $SAFE.should == 1 - end - - it "is not lambda local" do - $SAFE.should == 0 - -> { - $SAFE = 1 - }.call - $SAFE.should == 1 - end + }.call + $SAFE.should == 1 + end - it "is global like regular global variables" do - Thread.new { $SAFE }.value.should == 0 + it "is not lambda local" do + $SAFE.should == 0 + -> { $SAFE = 1 - Thread.new { $SAFE }.value.should == 1 - end + }.call + $SAFE.should == 1 + end + + it "is global like regular global variables" do + Thread.new { $SAFE }.value.should == 0 + $SAFE = 1 + Thread.new { $SAFE }.value.should == 1 end it "can be read when default from Thread#safe_level" do @@ -135,4 +92,28 @@ }.call end end + + ruby_version_is "2.7"..."3.0" do + it "warn when access" do + -> { + $SAFE + }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/) + end + + it "warn when set" do + -> { + $SAFE = 1 + }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/) + end + end + + ruby_version_is "3.0" do + it "$SAFE is a regular global variable" do + $SAFE.should == nil + $SAFE = 42 + $SAFE.should == 42 + ensure + $SAFE = nil + end + end end diff --git a/ruby/spec/ruby/language/send_spec.rb b/ruby/spec/ruby/language/send_spec.rb index c56d5e8c2..e57e2c65d 100644 --- a/ruby/spec/ruby/language/send_spec.rb +++ b/ruby/spec/ruby/language/send_spec.rb @@ -421,18 +421,36 @@ def []=(*) specs.rest_len(0,*a,4,*5,6,7,*c,-1).should == 11 end - it "expands the Array elements from the splat after executing the arguments and block if no other arguments follow the splat" do - def self.m(*args, &block) - [args, block] + ruby_version_is ""..."3.0" do + it "expands the Array elements from the splat after executing the arguments and block if no other arguments follow the splat" do + def self.m(*args, &block) + [args, block] + end + + args = [1, nil] + m(*args, &args.pop).should == [[1], nil] + + args = [1, nil] + order = [] + m(*(order << :args; args), &(order << :block; args.pop)).should == [[1], nil] + order.should == [:args, :block] end + end - args = [1, nil] - m(*args, &args.pop).should == [[1], nil] + ruby_version_is "3.0" do + it "expands the Array elements from the splat before applying block argument operations" do + def self.m(*args, &block) + [args, block] + end - args = [1, nil] - order = [] - m(*(order << :args; args), &(order << :block; args.pop)).should == [[1], nil] - order.should == [:args, :block] + args = [1, nil] + m(*args, &args.pop).should == [[1, nil], nil] + + args = [1, nil] + order = [] + m(*(order << :args; args), &(order << :block; args.pop)).should == [[1, nil], nil] + order.should == [:args, :block] + end end it "evaluates the splatted arguments before the block if there are other arguments after the splat" do diff --git a/ruby/spec/ruby/language/singleton_class_spec.rb b/ruby/spec/ruby/language/singleton_class_spec.rb index df735018a..c1fb682ea 100644 --- a/ruby/spec/ruby/language/singleton_class_spec.rb +++ b/ruby/spec/ruby/language/singleton_class_spec.rb @@ -14,7 +14,7 @@ nil.singleton_class.should == NilClass end - it "raises a TypeError for Fixnum's" do + it "raises a TypeError for Integer's" do -> { 1.singleton_class }.should raise_error(TypeError) end @@ -74,7 +74,7 @@ end it "doesn't have singleton class" do - -> { bignum_value.singleton_class.superclass.should == Bignum }.should raise_error(TypeError) + -> { bignum_value.singleton_class }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/language/source_encoding_spec.rb b/ruby/spec/ruby/language/source_encoding_spec.rb index a0a29f63d..19364fc67 100644 --- a/ruby/spec/ruby/language/source_encoding_spec.rb +++ b/ruby/spec/ruby/language/source_encoding_spec.rb @@ -29,7 +29,7 @@ touch(path, "wb") { |f| f.write source } begin - ruby_exe(path, args: "2>&1").should =~ /invalid multibyte char/ + ruby_exe(path, args: "2>&1", exit_status: 1).should =~ /invalid multibyte char/ ensure rm_r path end @@ -51,7 +51,7 @@ touch(path, "wb") { |f| f.write source } begin - ruby_exe(path, args: "2>&1").should =~ /invalid multibyte char/ + ruby_exe(path, args: "2>&1", exit_status: 1).should =~ /invalid multibyte char/ ensure rm_r path end diff --git a/ruby/spec/ruby/language/string_spec.rb b/ruby/spec/ruby/language/string_spec.rb index d0f62ff3c..ce4941569 100644 --- a/ruby/spec/ruby/language/string_spec.rb +++ b/ruby/spec/ruby/language/string_spec.rb @@ -32,6 +32,11 @@ "#@my_ip".should == 'xxx' end + it "does not interpolate invalid variable names" do + "#@".should == '#@' + "#$%".should == '#$%' + end + it "has characters [.(=?!# end simple # interpolation" do "#@ip[".should == 'xxx[' "#@ip.".should == 'xxx.' @@ -260,24 +265,24 @@ def long_string_literals end describe "Ruby String interpolation" do - it "creates a String having an Encoding compatible with all components" do - a = "\u3042" - b = "abc".encode("binary") - - str = "#{a} x #{b}" + it "permits an empty expression" do + s = "#{}" # rubocop:disable Lint/EmptyInterpolation + s.should.empty? + s.should_not.frozen? + end - str.should == "\xe3\x81\x82\x20\x78\x20\x61\x62\x63".force_encoding("utf-8") - str.encoding.should == Encoding::UTF_8 + it "returns a string with the source encoding by default" do + "a#{"b"}c".encoding.should == Encoding::BINARY + eval('"a#{"b"}c"'.force_encoding("us-ascii")).encoding.should == Encoding::US_ASCII + eval("# coding: US-ASCII \n 'a#{"b"}c'").encoding.should == Encoding::US_ASCII end - it "creates a String having the Encoding of the components when all are the same Encoding" do + it "returns a string with the source encoding, even if the components have another encoding" do a = "abc".force_encoding("euc-jp") - b = "def".force_encoding("euc-jp") - str = '"#{a} x #{b}"'.force_encoding("euc-jp") + "#{a}".encoding.should == Encoding::BINARY - result = eval(str) - result.should == "\x61\x62\x63\x20\x78\x20\x64\x65\x66".force_encoding("euc-jp") - result.encoding.should == Encoding::EUC_JP + b = "abc".encode("utf-8") + "#{b}".encoding.should == Encoding::BINARY end it "raises an Encoding::CompatibilityError if the Encodings are not compatible" do @@ -286,4 +291,31 @@ def long_string_literals -> { "#{a} #{b}" }.should raise_error(Encoding::CompatibilityError) end + + it "creates a non-frozen String" do + code = <<~'RUBY' + "a#{6*7}c" + RUBY + eval(code).should_not.frozen? + end + + ruby_version_is "3.0" do + it "creates a non-frozen String when # frozen-string-literal: true is used" do + code = <<~'RUBY' + # frozen-string-literal: true + "a#{6*7}c" + RUBY + eval(code).should_not.frozen? + end + end + + ruby_version_is ""..."3.0" do + it "creates a frozen String when # frozen-string-literal: true is used" do + code = <<~'RUBY' + # frozen-string-literal: true + "a#{6*7}c" + RUBY + eval(code).should.frozen? + end + end end diff --git a/ruby/spec/ruby/language/super_spec.rb b/ruby/spec/ruby/language/super_spec.rb index 66a1ec759..1ac5c5e1b 100644 --- a/ruby/spec/ruby/language/super_spec.rb +++ b/ruby/spec/ruby/language/super_spec.rb @@ -102,6 +102,37 @@ def m(v) c2.new.m(:dump) { :value }.should == :value end + it "can pass an explicit block" do + c1 = Class.new do + def m(v) + yield(v) + end + end + c2 = Class.new(c1) do + def m(v) + block = -> w { yield(w + 'b') } + super(v, &block) + end + end + + c2.new.m('a') { |x| x + 'c' }.should == 'abc' + end + + it "can pass no block using &nil" do + c1 = Class.new do + def m(v) + block_given? + end + end + c2 = Class.new(c1) do + def m(v) + super(v, &nil) + end + end + + c2.new.m('a') { raise }.should be_false + end + it "uses block argument given to method when used in a block" do c1 = Class.new do def m @@ -262,6 +293,21 @@ def obj.foobar(array) it "without explicit arguments passes arguments and rest arguments" do SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2, 3, 4, 5).should == [3, 4, 5] + SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2).should == [] + end + + it "without explicit arguments passes arguments, rest arguments, and post arguments" do + SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2, 3, 4, 5).should == [1, 2, 3] + SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2, 3, 4, 5).should == [2, 3, 4] + SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2).should == [] + SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2).should == [] + end + + it "without explicit arguments passes arguments, rest arguments including modifications, and post arguments" do + SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [1, 14, 3] + SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [2, 14, 4] + SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2).should == [nil, 14] + SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2).should == [nil, 14] end it "without explicit arguments passes arguments and rest arguments including any modifications" do diff --git a/ruby/spec/ruby/language/variables_spec.rb b/ruby/spec/ruby/language/variables_spec.rb index 868603eb8..699187335 100644 --- a/ruby/spec/ruby/language/variables_spec.rb +++ b/ruby/spec/ruby/language/variables_spec.rb @@ -354,6 +354,16 @@ module VariableSpecs a.should be_an_instance_of(Array) end + it "unfreezes the array returned from calling 'to_a' on the splatted value" do + obj = Object.new + def obj.to_a + [1,2].freeze + end + res = *obj + res.should == [1,2] + res.should_not.frozen? + end + it "consumes values for an anonymous splat" do a = 1 (* = *a).should == [1] @@ -705,6 +715,18 @@ module VariableSpecs x.should == [1, 2, 3, 4, 5] end + it "can be used to swap array elements" do + a = [1, 2] + a[0], a[1] = a[1], a[0] + a.should == [2, 1] + end + + it "can be used to swap range of array elements" do + a = [1, 2, 3, 4] + a[0, 2], a[2, 2] = a[2, 2], a[0, 2] + a.should == [3, 4, 1, 2] + end + it "assigns RHS values to LHS constants" do module VariableSpecs MRHS_VALUES_1, MRHS_VALUES_2 = 1, 2 @@ -760,29 +782,72 @@ module VariableSpecs end describe 'Local variable shadowing' do - ruby_version_is ""..."2.6" do - it "leads to warning in verbose mode" do - -> do - eval <<-CODE - a = [1, 2, 3] - a.each { |a| a = 3 } - CODE - end.should complain(/shadowing outer local variable/, verbose: true) - end + it "does not warn in verbose mode" do + result = nil + + -> do + eval <<-CODE + a = [1, 2, 3] + result = a.map { |a| a = 3 } + CODE + end.should_not complain(verbose: true) + + result.should == [3, 3, 3] end +end + +describe 'Allowed characters' do + # new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770 + it 'does not allow non-ASCII upcased characters at the beginning' do + -> do + eval <<-CODE + def test + á¼BB = 1 + end + CODE + end.should raise_error(SyntaxError, /dynamic constant assignment/) + end + + it 'allows non-ASCII lowercased characters at the beginning' do + result = nil - ruby_version_is "2.6" do - it "does not warn in verbose mode" do - result = nil + eval <<-CODE + def test + μ = 1 + end + + result = test + CODE + + result.should == 1 + end +end + +describe "Instance variables" do + context "when instance variable is uninitialized" do + ruby_version_is ""..."3.0" do + it "warns about accessing uninitialized instance variable" do + obj = Object.new + def obj.foobar; a = @a; end + + -> { obj.foobar }.should complain(/warning: instance variable @a not initialized/, verbose: true) + end + end + + ruby_version_is "3.0" do + it "doesn't warn about accessing uninitialized instance variable" do + obj = Object.new + def obj.foobar; a = @a; end + + -> { obj.foobar }.should_not complain(verbose: true) + end + end - -> do - eval <<-CODE - a = [1, 2, 3] - result = a.map { |a| a = 3 } - CODE - end.should_not complain(verbose: true) + it "doesn't warn at lazy initialization" do + obj = Object.new + def obj.foobar; @a ||= 42; end - result.should == [3, 3, 3] + -> { obj.foobar }.should_not complain(verbose: true) end end end diff --git a/ruby/spec/ruby/language/yield_spec.rb b/ruby/spec/ruby/language/yield_spec.rb index 5fad7cb17..3db6d353a 100644 --- a/ruby/spec/ruby/language/yield_spec.rb +++ b/ruby/spec/ruby/language/yield_spec.rb @@ -183,5 +183,33 @@ it "uses captured block of a block used in define_method" do @y.deep(2).should == 4 end +end + +describe "Using yield in a singleton class literal" do + ruby_version_is "2.7"..."3.0" do + it 'emits a deprecation warning' do + code = <<~RUBY + def m + class << Object.new + yield + end + end + m { :ok } + RUBY + + -> { eval(code) }.should complain(/warning: `yield' in class syntax will not be supported from Ruby 3.0/) + end + end + + ruby_version_is "3.0" do + it 'raises a SyntaxError' do + code = <<~RUBY + class << Object.new + yield + end + RUBY + -> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/) + end + end end diff --git a/ruby/spec/ruby/library/English/English_spec.rb b/ruby/spec/ruby/library/English/English_spec.rb index f6153ec7c..480602d5e 100644 --- a/ruby/spec/ruby/library/English/English_spec.rb +++ b/ruby/spec/ruby/library/English/English_spec.rb @@ -67,18 +67,18 @@ it "aliases $ORS to $\\" do original = $\ - $\ = "\t" + suppress_warning {$\ = "\t"} $ORS.should_not be_nil $ORS.should == $\ - $\ = original + suppress_warning {$\ = original} end it "aliases $OUTPUT_RECORD_SEPARATOR to $\\" do original = $\ - $\ = "\t" + suppress_warning {$\ = "\t"} $OUTPUT_RECORD_SEPARATOR.should_not be_nil $OUTPUT_RECORD_SEPARATOR.should == $\ - $\ = original + suppress_warning {$\ = original} end it "aliases $INPUT_LINE_NUMBER to $." do diff --git a/ruby/spec/ruby/library/English/alias_spec.rb b/ruby/spec/ruby/library/English/alias_spec.rb new file mode 100644 index 000000000..78ccfb439 --- /dev/null +++ b/ruby/spec/ruby/library/English/alias_spec.rb @@ -0,0 +1,14 @@ +require_relative '../../spec_helper' +require 'English' + +describe "English" do + it "aliases $! to $ERROR_INFO and $ERROR_INFO still returns an Exception with a backtrace" do + exception = (1 / 0 rescue $ERROR_INFO) + exception.should be_kind_of(Exception) + exception.backtrace.should be_kind_of(Array) + end + + it "aliases $@ to $ERROR_POSITION and $ERROR_POSITION still returns a backtrace" do + (1 / 0 rescue $ERROR_POSITION).should be_kind_of(Array) + end +end diff --git a/ruby/spec/ruby/library/base64/decode64_spec.rb b/ruby/spec/ruby/library/base64/decode64_spec.rb index f6cd26d78..6dd33dddf 100644 --- a/ruby/spec/ruby/library/base64/decode64_spec.rb +++ b/ruby/spec/ruby/library/base64/decode64_spec.rb @@ -22,4 +22,8 @@ it "returns a binary encoded string" do Base64.decode64("SEk=").encoding.should == Encoding::BINARY end + + it "decodes without padding suffix ==" do + Base64.decode64("eyJrZXkiOnsibiI6InR0dCJ9fQ").should == "{\"key\":{\"n\":\"ttt\"}}" + end end diff --git a/ruby/spec/ruby/library/bigdecimal/BigDecimal_spec.rb b/ruby/spec/ruby/library/bigdecimal/BigDecimal_spec.rb index 179bde1ae..43a779b42 100644 --- a/ruby/spec/ruby/library/bigdecimal/BigDecimal_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/BigDecimal_spec.rb @@ -31,37 +31,36 @@ end it "accepts significant digits >= given precision" do - BigDecimal("3.1415923", 10).precs[1].should >= 10 + suppress_warning do + BigDecimal("3.1415923", 10).precs[1].should >= 10 + end end it "determines precision from initial value" do pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043" - BigDecimal(pi_string).precs[1].should >= pi_string.size-1 + suppress_warning { + BigDecimal(pi_string).precs[1] + }.should >= pi_string.size-1 end it "ignores leading and trailing whitespace" do BigDecimal(" \t\n \r1234\t\r\n ").should == BigDecimal("1234") - BigDecimal(" \t\n \rNaN \n").nan?.should == true + BigDecimal(" \t\n \rNaN \n").should.nan? BigDecimal(" \t\n \rInfinity \n").infinite?.should == 1 BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1 end - ruby_version_is ""..."2.6" do - it "ignores trailing garbage" do - BigDecimal("123E45ruby").should == BigDecimal("123E45") - BigDecimal("123x45").should == BigDecimal("123") - BigDecimal("123.4%E5").should == BigDecimal("123.4") - BigDecimal("1E2E3E4E5E").should == BigDecimal("100") - end + it "coerces the value argument with #to_str" do + initial = mock("value") + initial.should_receive(:to_str).and_return("123") + BigDecimal(initial).should == BigDecimal("123") end - ruby_version_is "2.6" do - it "does not ignores trailing garbage" do - -> { BigDecimal("123E45ruby") }.should raise_error(ArgumentError) - -> { BigDecimal("123x45") }.should raise_error(ArgumentError) - -> { BigDecimal("123.4%E5") }.should raise_error(ArgumentError) - -> { BigDecimal("1E2E3E4E5E") }.should raise_error(ArgumentError) - end + it "does not ignores trailing garbage" do + -> { BigDecimal("123E45ruby") }.should raise_error(ArgumentError) + -> { BigDecimal("123x45") }.should raise_error(ArgumentError) + -> { BigDecimal("123.4%E5") }.should raise_error(ArgumentError) + -> { BigDecimal("1E2E3E4E5E") }.should raise_error(ArgumentError) end it "raises ArgumentError for invalid strings" do @@ -73,63 +72,60 @@ BigDecimal(".123").should == BigDecimal("0.123") end - ruby_version_is ""..."2.6" do - it "allows for underscores in all parts" do - reference = BigDecimal("12345.67E89") - - BigDecimal("12_345.67E89").should == reference - BigDecimal("1_2_3_4_5_._6____7_E89").should == reference - BigDecimal("12345_.67E_8__9_").should == reference - end - end - - ruby_version_is "2.6" do - it "process underscores as Float()" do - reference = BigDecimal("12345.67E89") + it "process underscores as Float()" do + reference = BigDecimal("12345.67E89") - BigDecimal("12_345.67E89").should == reference - -> { BigDecimal("1_2_3_4_5_._6____7_E89") }.should raise_error(ArgumentError) - -> { BigDecimal("12345_.67E_8__9_") }.should raise_error(ArgumentError) - end + BigDecimal("12_345.67E89").should == reference + -> { BigDecimal("1_2_3_4_5_._6____7_E89") }.should raise_error(ArgumentError) + -> { BigDecimal("12345_.67E_8__9_") }.should raise_error(ArgumentError) end it "accepts NaN and [+-]Infinity" do - BigDecimal("NaN").nan?.should == true + BigDecimal("NaN").should.nan? pos_inf = BigDecimal("Infinity") - pos_inf.finite?.should == false + pos_inf.should_not.finite? pos_inf.should > 0 pos_inf.should == BigDecimal("+Infinity") neg_inf = BigDecimal("-Infinity") - neg_inf.finite?.should == false + neg_inf.should_not.finite? neg_inf.should < 0 end + describe "with exception: false" do + it "returns nil for invalid strings" do + BigDecimal("invalid", exception: false).should be_nil + BigDecimal("0invalid", exception: false).should be_nil + BigDecimal("invalid0", exception: false).should be_nil + BigDecimal("0.", exception: false).should be_nil + end + end + describe "accepts NaN and [+-]Infinity as Float values" do it "works without an explicit precision" do - BigDecimal(Float::NAN).nan?.should == true + BigDecimal(Float::NAN).should.nan? pos_inf = BigDecimal(Float::INFINITY) - pos_inf.finite?.should == false + pos_inf.should_not.finite? pos_inf.should > 0 pos_inf.should == BigDecimal("+Infinity") neg_inf = BigDecimal(-Float::INFINITY) - neg_inf.finite?.should == false + neg_inf.should_not.finite? neg_inf.should < 0 end it "works with an explicit precision" do - BigDecimal(Float::NAN, Float::DIG).nan?.should == true + BigDecimal(Float::NAN, Float::DIG).should.nan? pos_inf = BigDecimal(Float::INFINITY, Float::DIG) - pos_inf.finite?.should == false + pos_inf.should_not.finite? pos_inf.should > 0 pos_inf.should == BigDecimal("+Infinity") neg_inf = BigDecimal(-Float::INFINITY, Float::DIG) - neg_inf.finite?.should == false + neg_inf.should_not.finite? neg_inf.should < 0 end end @@ -169,6 +165,22 @@ BigDecimal(3).add(1 << 50, 3).should == BigDecimal('0.113e16') end + it "does not call to_s when calling inspect" do + value = BigDecimal('44.44') + value.to_s.should == '0.4444e2' + value.inspect.should == '0.4444e2' + + ruby_exe( <<-'EOF').should == "cheese 0.4444e2" + require 'bigdecimal' + module BigDecimalOverride + def to_s; "cheese"; end + end + BigDecimal.prepend BigDecimalOverride + value = BigDecimal('44.44') + print "#{value.to_s} #{value.inspect}" + EOF + end + describe "when interacting with Rational" do before :each do @a = BigDecimal('166.666666666') @@ -191,11 +203,11 @@ end it "has the expected precision on the LHS" do - @a.precs[0].should == 18 + suppress_warning { @a.precs[0] }.should == 18 end it "has the expected maximum precision on the LHS" do - @a.precs[1].should == 27 + suppress_warning { @a.precs[1] }.should == 27 end it "produces the expected result when done via Float" do @@ -211,21 +223,21 @@ it "BigDecimal precision is the number of digits rounded up to a multiple of nine" do 1.upto(100) do |n| b = BigDecimal('4' * n) - precs, _ = b.precs + precs, _ = suppress_warning { b.precs } (precs >= 9).should be_true (precs >= n).should be_true (precs % 9).should == 0 end - BigDecimal('NaN').precs[0].should == 9 + suppress_warning { BigDecimal('NaN').precs[0] }.should == 9 end it "BigDecimal maximum precision is nine more than precision except for abnormals" do 1.upto(100) do |n| b = BigDecimal('4' * n) - precs, max = b.precs + precs, max = suppress_warning { b.precs } max.should == precs + 9 end - BigDecimal('NaN').precs[1].should == 9 + suppress_warning { BigDecimal('NaN').precs[1] }.should == 9 end it "BigDecimal(Rational, 18) produces the result we expect" do @@ -233,7 +245,7 @@ end it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do - BigDecimal(@b, @a.precs[0]).to_s.should == "0.166666666666666667e3" + BigDecimal(@b, suppress_warning { @a.precs[0] }).to_s.should == "0.166666666666666667e3" end # Check the top-level expression works as we expect diff --git a/ruby/spec/ruby/library/bigdecimal/abs_spec.rb b/ruby/spec/ruby/library/bigdecimal/abs_spec.rb index ddd2bae9a..95dc45a90 100644 --- a/ruby/spec/ruby/library/bigdecimal/abs_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/abs_spec.rb @@ -38,7 +38,7 @@ it "properly handles special values" do @infinity.abs.should == @infinity @infinity_minus.abs.should == @infinity - @nan.abs.nan?.should == true # have to do it this way, since == doesn't work on NaN + @nan.abs.should.nan? # have to do it this way, since == doesn't work on NaN @zero.abs.should == 0 @zero.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO @zero_pos.abs.should == 0 diff --git a/ruby/spec/ruby/library/bigdecimal/add_spec.rb b/ruby/spec/ruby/library/bigdecimal/add_spec.rb index 5b874687f..bea8b8f76 100644 --- a/ruby/spec/ruby/library/bigdecimal/add_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/add_spec.rb @@ -136,8 +136,8 @@ end it "returns NaN if NaN is involved" do - @one.add(@nan, 10000).nan?.should == true - @nan.add(@one, 1).nan?.should == true + @one.add(@nan, 10000).should.nan? + @nan.add(@one, 1).should.nan? end it "returns Infinity or -Infinity if these are involved" do @@ -166,8 +166,8 @@ end it "returns NaN if Infinity + (- Infinity)" do - @infinity.add(@infinity_minus, 10000).nan?.should == true - @infinity_minus.add(@infinity, 10000).nan?.should == true + @infinity.add(@infinity_minus, 10000).should.nan? + @infinity_minus.add(@infinity, 10000).should.nan? end it "raises TypeError when adds nil" do diff --git a/ruby/spec/ruby/library/bigdecimal/comparison_spec.rb b/ruby/spec/ruby/library/bigdecimal/comparison_spec.rb index a1e09b601..c53187b72 100644 --- a/ruby/spec/ruby/library/bigdecimal/comparison_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/comparison_spec.rb @@ -18,7 +18,7 @@ class << @int_mock def coerce(other) return [other, BigDecimal('123')] end - def >= (other) + def >=(other) BigDecimal('123') >= other end end diff --git a/ruby/spec/ruby/library/bigdecimal/constants_spec.rb b/ruby/spec/ruby/library/bigdecimal/constants_spec.rb index 1eb24d85c..8d879c036 100644 --- a/ruby/spec/ruby/library/bigdecimal/constants_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/constants_spec.rb @@ -2,10 +2,8 @@ require 'bigdecimal' describe "BigDecimal constants" do - ruby_version_is "2.5" do - it "defines a VERSION value" do - BigDecimal.const_defined?(:VERSION).should be_true - end + it "defines a VERSION value" do + BigDecimal.const_defined?(:VERSION).should be_true end it "has a BASE value" do diff --git a/ruby/spec/ruby/library/bigdecimal/div_spec.rb b/ruby/spec/ruby/library/bigdecimal/div_spec.rb index 0c9eb2dde..53ad6d041 100644 --- a/ruby/spec/ruby/library/bigdecimal/div_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/div_spec.rb @@ -80,13 +80,13 @@ end it "returns NaN if zero is divided by zero" do - @zero.div(@zero, 0).nan?.should == true - @zero_minus.div(@zero_plus, 0).nan?.should == true - @zero_plus.div(@zero_minus, 0).nan?.should == true + @zero.div(@zero, 0).should.nan? + @zero_minus.div(@zero_plus, 0).should.nan? + @zero_plus.div(@zero_minus, 0).should.nan? - @zero.div(@zero, 10).nan?.should == true - @zero_minus.div(@zero_plus, 10).nan?.should == true - @zero_plus.div(@zero_minus, 10).nan?.should == true + @zero.div(@zero, 10).should.nan? + @zero_minus.div(@zero_plus, 10).should.nan? + @zero_plus.div(@zero_minus, 10).should.nan? end it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do @@ -102,8 +102,8 @@ end it "returns NaN if Infinity / ((+|-) Infinity)" do - @infinity.div(@infinity_minus, 100000).nan?.should == true - @infinity_minus.div(@infinity, 1).nan?.should == true + @infinity.div(@infinity_minus, 100000).should.nan? + @infinity_minus.div(@infinity, 1).should.nan? end diff --git a/ruby/spec/ruby/library/bigdecimal/divmod_spec.rb b/ruby/spec/ruby/library/bigdecimal/divmod_spec.rb index ae8b84983..294f01cba 100644 --- a/ruby/spec/ruby/library/bigdecimal/divmod_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/divmod_spec.rb @@ -5,8 +5,8 @@ module DivmodSpecs def self.check_both_nan(array) array.length.should == 2 - array[0].nan?.should == true - array[1].nan?.should == true + array[0].should.nan? + array[1].should.nan? end def self.check_both_bigdecimal(array) array.length.should == 2 @@ -150,7 +150,7 @@ class BigDecimal array = @infinity.divmod(val) array.length.should == 2 array[0].infinite?.should == (val > 0 ? 1 : -1) - array[1].nan?.should == true + array[1].should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/exponent_spec.rb b/ruby/spec/ruby/library/bigdecimal/exponent_spec.rb index a349ac093..f63c4e579 100644 --- a/ruby/spec/ruby/library/bigdecimal/exponent_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/exponent_spec.rb @@ -22,7 +22,7 @@ =begin platform_is wordsize: 32 do # TODO: write specs for both 32 and 64 bit - it "returns 0 if exponent can't be represented as Fixnum" do + it "returns 0 if exponent can't be represented as Integer" do BigDecimal("2E1000000000000000").exponent.should == 0 BigDecimal("-5E-999999999999999").exponent.should == 0 end diff --git a/ruby/spec/ruby/library/bigdecimal/finite_spec.rb b/ruby/spec/ruby/library/bigdecimal/finite_spec.rb index 6685d589b..8fc06029b 100644 --- a/ruby/spec/ruby/library/bigdecimal/finite_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/finite_spec.rb @@ -21,14 +21,14 @@ end it "is false if Infinity or NaN" do - @infinity.finite?.should == false - @infinity_minus.finite?.should == false - @nan.finite?.should == false + @infinity.should_not.finite? + @infinity_minus.should_not.finite? + @nan.should_not.finite? end it "returns true for finite values" do @finite_vals.each do |val| - val.finite?.should == true + val.should.finite? end end end diff --git a/ruby/spec/ruby/library/bigdecimal/fix_spec.rb b/ruby/spec/ruby/library/bigdecimal/fix_spec.rb index 53b30cbf8..231c9a587 100644 --- a/ruby/spec/ruby/library/bigdecimal/fix_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/fix_spec.rb @@ -34,7 +34,7 @@ it "correctly handles special values" do @infinity.fix.should == @infinity @infinity_neg.fix.should == @infinity_neg - @nan.fix.nan?.should == true + @nan.fix.should.nan? end it "returns 0 if the absolute value is < 1" do diff --git a/ruby/spec/ruby/library/bigdecimal/frac_spec.rb b/ruby/spec/ruby/library/bigdecimal/frac_spec.rb index 4a023b4ff..11ccf03c2 100644 --- a/ruby/spec/ruby/library/bigdecimal/frac_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/frac_spec.rb @@ -42,7 +42,7 @@ it "correctly handles special values" do @infinity.frac.should == @infinity @infinity_neg.frac.should == @infinity_neg - @nan.frac.nan?.should == true + @nan.frac.should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/gt_spec.rb b/ruby/spec/ruby/library/bigdecimal/gt_spec.rb index 4717cfdd9..78547fb85 100644 --- a/ruby/spec/ruby/library/bigdecimal/gt_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/gt_spec.rb @@ -17,7 +17,7 @@ class << @int_mock def coerce(other) return [other, BigDecimal('123')] end - def > (other) + def >(other) BigDecimal('123') > other end end diff --git a/ruby/spec/ruby/library/bigdecimal/gte_spec.rb b/ruby/spec/ruby/library/bigdecimal/gte_spec.rb index 8dc81707f..2a5cc025b 100644 --- a/ruby/spec/ruby/library/bigdecimal/gte_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/gte_spec.rb @@ -17,7 +17,7 @@ class << @int_mock def coerce(other) return [other, BigDecimal('123')] end - def >= (other) + def >=(other) BigDecimal('123') >= other end end diff --git a/ruby/spec/ruby/library/bigdecimal/lt_spec.rb b/ruby/spec/ruby/library/bigdecimal/lt_spec.rb index 61f4f1991..02390e76e 100644 --- a/ruby/spec/ruby/library/bigdecimal/lt_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/lt_spec.rb @@ -17,7 +17,7 @@ class << @int_mock def coerce(other) return [other, BigDecimal('123')] end - def < (other) + def <(other) BigDecimal('123') < other end end diff --git a/ruby/spec/ruby/library/bigdecimal/lte_spec.rb b/ruby/spec/ruby/library/bigdecimal/lte_spec.rb index fc632315f..b92be0412 100644 --- a/ruby/spec/ruby/library/bigdecimal/lte_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/lte_spec.rb @@ -17,7 +17,7 @@ class << @int_mock def coerce(other) return [other, BigDecimal('123')] end - def <= (other) + def <=(other) BigDecimal('123') <= other end end diff --git a/ruby/spec/ruby/library/bigdecimal/minus_spec.rb b/ruby/spec/ruby/library/bigdecimal/minus_spec.rb index 267a0f7ea..bd3c19584 100644 --- a/ruby/spec/ruby/library/bigdecimal/minus_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/minus_spec.rb @@ -26,18 +26,18 @@ end it "returns NaN if NaN is involved" do - (@one - @nan).nan?.should == true - (@nan - @one).nan?.should == true - (@nan - @nan).nan?.should == true - (@nan - @infinity).nan?.should == true - (@nan - @infinity_minus).nan?.should == true - (@infinity - @nan).nan?.should == true - (@infinity_minus - @nan).nan?.should == true + (@one - @nan).should.nan? + (@nan - @one).should.nan? + (@nan - @nan).should.nan? + (@nan - @infinity).should.nan? + (@nan - @infinity_minus).should.nan? + (@infinity - @nan).should.nan? + (@infinity_minus - @nan).should.nan? end it "returns NaN both operands are infinite with the same sign" do - (@infinity - @infinity).nan?.should == true - (@infinity_minus - @infinity_minus).nan?.should == true + (@infinity - @infinity).should.nan? + (@infinity_minus - @infinity_minus).should.nan? end it "returns Infinity or -Infinity if these are involved" do diff --git a/ruby/spec/ruby/library/bigdecimal/mode_spec.rb b/ruby/spec/ruby/library/bigdecimal/mode_spec.rb index f57028ae5..73fa1a118 100644 --- a/ruby/spec/ruby/library/bigdecimal/mode_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/mode_spec.rb @@ -12,7 +12,7 @@ end it "returns the appropriate value and continue the computation if the flag is false" do - BigDecimal("NaN").add(BigDecimal("1"),0).nan?.should == true + BigDecimal("NaN").add(BigDecimal("1"),0).should.nan? BigDecimal("0").add(BigDecimal("Infinity"),0).should == BigDecimal("Infinity") BigDecimal("1").quo(BigDecimal("0")).should == BigDecimal("Infinity") end diff --git a/ruby/spec/ruby/library/bigdecimal/nan_spec.rb b/ruby/spec/ruby/library/bigdecimal/nan_spec.rb index 705492614..9eaf69b61 100644 --- a/ruby/spec/ruby/library/bigdecimal/nan_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/nan_spec.rb @@ -4,20 +4,20 @@ describe "BigDecimal#nan?" do it "returns true if self is not a number" do - BigDecimal("NaN").nan?.should == true + BigDecimal("NaN").should.nan? end it "returns false if self is not a NaN" do - BigDecimal("Infinity").nan?.should == false - BigDecimal("-Infinity").nan?.should == false - BigDecimal("0").nan?.should == false - BigDecimal("+0").nan?.should == false - BigDecimal("-0").nan?.should == false - BigDecimal("2E40001").nan?.should == false - BigDecimal("3E-20001").nan?.should == false - BigDecimal("0E-200000000").nan?.should == false - BigDecimal("0E200000000000").nan?.should == false - BigDecimal("0.000000000000000000000000").nan?.should == false + BigDecimal("Infinity").should_not.nan? + BigDecimal("-Infinity").should_not.nan? + BigDecimal("0").should_not.nan? + BigDecimal("+0").should_not.nan? + BigDecimal("-0").should_not.nan? + BigDecimal("2E40001").should_not.nan? + BigDecimal("3E-20001").should_not.nan? + BigDecimal("0E-200000000").should_not.nan? + BigDecimal("0E200000000000").should_not.nan? + BigDecimal("0.000000000000000000000000").should_not.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/plus_spec.rb b/ruby/spec/ruby/library/bigdecimal/plus_spec.rb index cefc43aea..d1934841c 100644 --- a/ruby/spec/ruby/library/bigdecimal/plus_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/plus_spec.rb @@ -30,8 +30,8 @@ end it "returns NaN if NaN is involved" do - (@one + @nan).nan?.should == true - (@nan + @one).nan?.should == true + (@one + @nan).should.nan? + (@nan + @one).should.nan? end it "returns Infinity or -Infinity if these are involved" do @@ -41,7 +41,7 @@ end it "returns NaN if Infinity + (- Infinity)" do - (@infinity + @infinity_minus).nan?.should == true + (@infinity + @infinity_minus).should.nan? end describe "with Object" do diff --git a/ruby/spec/ruby/library/bigdecimal/precs_spec.rb b/ruby/spec/ruby/library/bigdecimal/precs_spec.rb index f9320f2b9..5fda8d308 100644 --- a/ruby/spec/ruby/library/bigdecimal/precs_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/precs_spec.rb @@ -2,7 +2,6 @@ require 'bigdecimal' describe "BigDecimal#precs" do - before :each do @infinity = BigDecimal("Infinity") @infinity_neg = BigDecimal("-Infinity") @@ -16,33 +15,41 @@ end it "returns array of two values" do - @arr.each do |x| - x.precs.kind_of?(Array).should == true - x.precs.size.should == 2 + suppress_warning do + @arr.each do |x| + x.precs.kind_of?(Array).should == true + x.precs.size.should == 2 + end end end it "returns Integers as array values" do - @arr.each do |x| - x.precs[0].kind_of?(Integer).should == true - x.precs[1].kind_of?(Integer).should == true + suppress_warning do + @arr.each do |x| + x.precs[0].kind_of?(Integer).should == true + x.precs[1].kind_of?(Integer).should == true + end end end it "returns the current value of significant digits as the first value" do - BigDecimal("3.14159").precs[0].should >= 6 - BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0] - [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| - value.precs[0].should <= @precision + suppress_warning do + BigDecimal("3.14159").precs[0].should >= 6 + BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0] + [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| + value.precs[0].should <= @precision + end end end it "returns the maximum number of significant digits as the second value" do - BigDecimal("3.14159").precs[1].should >= 6 - BigDecimal('1').precs[1].should >= 1 - BigDecimal('1' + '0' * 100).precs[1] >= 101 - [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| - value.precs[1].should >= 1 + suppress_warning do + BigDecimal("3.14159").precs[1].should >= 6 + BigDecimal('1').precs[1].should >= 1 + BigDecimal('1' + '0' * 100).precs[1].should >= 101 + [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| + value.precs[1].should >= 1 + end end end end diff --git a/ruby/spec/ruby/library/bigdecimal/quo_spec.rb b/ruby/spec/ruby/library/bigdecimal/quo_spec.rb index a5c565177..65a433030 100644 --- a/ruby/spec/ruby/library/bigdecimal/quo_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/quo_spec.rb @@ -6,7 +6,7 @@ it_behaves_like :bigdecimal_quo, :quo, [] it "returns NaN if NaN is involved" do - BigDecimal("1").quo(BigDecimal("NaN")).nan?.should == true - BigDecimal("NaN").quo(BigDecimal("1")).nan?.should == true + BigDecimal("1").quo(BigDecimal("NaN")).should.nan? + BigDecimal("NaN").quo(BigDecimal("1")).should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/remainder_spec.rb b/ruby/spec/ruby/library/bigdecimal/remainder_spec.rb index 04233edec..1866f665c 100644 --- a/ruby/spec/ruby/library/bigdecimal/remainder_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/remainder_spec.rb @@ -38,8 +38,8 @@ end it "returns NaN used with zero" do - @mixed.remainder(@zero).nan?.should == true - @zero.remainder(@zero).nan?.should == true + @mixed.remainder(@zero).should.nan? + @zero.remainder(@zero).should.nan? end it "returns zero if used on zero" do @@ -47,28 +47,28 @@ end it "returns NaN if NaN is involved" do - @nan.remainder(@nan).nan?.should == true - @nan.remainder(@one).nan?.should == true - @one.remainder(@nan).nan?.should == true - @infinity.remainder(@nan).nan?.should == true - @nan.remainder(@infinity).nan?.should == true + @nan.remainder(@nan).should.nan? + @nan.remainder(@one).should.nan? + @one.remainder(@nan).should.nan? + @infinity.remainder(@nan).should.nan? + @nan.remainder(@infinity).should.nan? end it "returns NaN if Infinity is involved" do - @infinity.remainder(@infinity).nan?.should == true - @infinity.remainder(@one).nan?.should == true - @infinity.remainder(@mixed).nan?.should == true - @infinity.remainder(@one_minus).nan?.should == true - @infinity.remainder(@frac_1).nan?.should == true - @one.remainder(@infinity).nan?.should == true + @infinity.remainder(@infinity).should.nan? + @infinity.remainder(@one).should.nan? + @infinity.remainder(@mixed).should.nan? + @infinity.remainder(@one_minus).should.nan? + @infinity.remainder(@frac_1).should.nan? + @one.remainder(@infinity).should.nan? - @infinity_minus.remainder(@infinity_minus).nan?.should == true - @infinity_minus.remainder(@one).nan?.should == true - @one.remainder(@infinity_minus).nan?.should == true - @frac_2.remainder(@infinity_minus).nan?.should == true + @infinity_minus.remainder(@infinity_minus).should.nan? + @infinity_minus.remainder(@one).should.nan? + @one.remainder(@infinity_minus).should.nan? + @frac_2.remainder(@infinity_minus).should.nan? - @infinity.remainder(@infinity_minus).nan?.should == true - @infinity_minus.remainder(@infinity).nan?.should == true + @infinity.remainder(@infinity_minus).should.nan? + @infinity_minus.remainder(@infinity).should.nan? end it "coerces arguments to BigDecimal if possible" do diff --git a/ruby/spec/ruby/library/bigdecimal/shared/clone.rb b/ruby/spec/ruby/library/bigdecimal/shared/clone.rb index e58df3a94..935ef76e7 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/clone.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/clone.rb @@ -5,20 +5,9 @@ @obj = BigDecimal("1.2345") end - ruby_version_is "" ... "2.5" do - it "copies the BigDecimal's value to a newly allocated object" do - copy = @obj.public_send(@method) + it "returns self" do + copy = @obj.public_send(@method) - copy.should_not equal(@obj) - copy.should == @obj - end - end - - ruby_version_is "2.5" do - it "returns self" do - copy = @obj.public_send(@method) - - copy.should equal(@obj) - end + copy.should equal(@obj) end end diff --git a/ruby/spec/ruby/library/bigdecimal/shared/modulo.rb b/ruby/spec/ruby/library/bigdecimal/shared/modulo.rb index 67c0ecf2f..aa5c5a640 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/modulo.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/modulo.rb @@ -80,25 +80,25 @@ end it "returns NaN if NaN is involved" do - @nan.send(@method, @nan).nan?.should == true - @nan.send(@method, @one).nan?.should == true - @one.send(@method, @nan).nan?.should == true - @infinity.send(@method, @nan).nan?.should == true - @nan.send(@method, @infinity).nan?.should == true + @nan.send(@method, @nan).should.nan? + @nan.send(@method, @one).should.nan? + @one.send(@method, @nan).should.nan? + @infinity.send(@method, @nan).should.nan? + @nan.send(@method, @infinity).should.nan? end it "returns NaN if the dividend is Infinity" do - @infinity.send(@method, @infinity).nan?.should == true - @infinity.send(@method, @one).nan?.should == true - @infinity.send(@method, @mixed).nan?.should == true - @infinity.send(@method, @one_minus).nan?.should == true - @infinity.send(@method, @frac_1).nan?.should == true + @infinity.send(@method, @infinity).should.nan? + @infinity.send(@method, @one).should.nan? + @infinity.send(@method, @mixed).should.nan? + @infinity.send(@method, @one_minus).should.nan? + @infinity.send(@method, @frac_1).should.nan? - @infinity_minus.send(@method, @infinity_minus).nan?.should == true - @infinity_minus.send(@method, @one).nan?.should == true + @infinity_minus.send(@method, @infinity_minus).should.nan? + @infinity_minus.send(@method, @one).should.nan? - @infinity.send(@method, @infinity_minus).nan?.should == true - @infinity_minus.send(@method, @infinity).nan?.should == true + @infinity.send(@method, @infinity_minus).should.nan? + @infinity_minus.send(@method, @infinity).should.nan? end it "returns the dividend if the divisor is Infinity" do diff --git a/ruby/spec/ruby/library/bigdecimal/shared/mult.rb b/ruby/spec/ruby/library/bigdecimal/shared/mult.rb index b94c9385d..c613df04c 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/mult.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/mult.rb @@ -51,8 +51,8 @@ values = @regular_vals + @zeroes values.each do |val| - @nan.send(@method, val, *@object).nan?.should == true - val.send(@method, @nan, *@object).nan?.should == true + @nan.send(@method, val, *@object).should.nan? + val.send(@method, @nan, *@object).should.nan? end end @@ -62,9 +62,9 @@ values.each do |val| @zeroes.each do |zero| zero.send(@method, val, *@object).should == 0 - zero.send(@method, val, *@object).zero?.should == true + zero.send(@method, val, *@object).should.zero? val.send(@method, zero, *@object).should == 0 - val.send(@method, zero, *@object).zero?.should == true + val.send(@method, zero, *@object).should.zero? end end end @@ -75,8 +75,8 @@ values.each do |val| infs.each do |inf| - inf.send(@method, val, *@object).finite?.should == false - val.send(@method, inf, *@object).finite?.should == false + inf.send(@method, val, *@object).should_not.finite? + val.send(@method, inf, *@object).should_not.finite? end end @@ -89,9 +89,9 @@ end it "returns NaN if the result is undefined" do - @zero.send(@method, @infinity, *@object).nan?.should == true - @zero.send(@method, @infinity_minus, *@object).nan?.should == true - @infinity.send(@method, @zero, *@object).nan?.should == true - @infinity_minus.send(@method, @zero, *@object).nan?.should == true + @zero.send(@method, @infinity, *@object).should.nan? + @zero.send(@method, @infinity_minus, *@object).should.nan? + @infinity.send(@method, @zero, *@object).should.nan? + @infinity_minus.send(@method, @zero, *@object).should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/shared/power.rb b/ruby/spec/ruby/library/bigdecimal/shared/power.rb index a4848fb2e..568a08589 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/power.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/power.rb @@ -53,8 +53,8 @@ end it "returns NaN if self is NaN" do - BigDecimal("NaN").send(@method, -5).nan?.should == true - BigDecimal("NaN").send(@method, 5).nan?.should == true + BigDecimal("NaN").send(@method, -5).should.nan? + BigDecimal("NaN").send(@method, 5).should.nan? end it "returns 0.0 if self is infinite and argument is negative" do diff --git a/ruby/spec/ruby/library/bigdecimal/shared/quo.rb b/ruby/spec/ruby/library/bigdecimal/shared/quo.rb index 4d6d64b78..46e6d62bf 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/quo.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/quo.rb @@ -49,8 +49,8 @@ end it "returns NaN if Infinity / ((+|-) Infinity)" do - @infinity.send(@method, @infinity_minus, *@object).nan?.should == true - @infinity_minus.send(@method, @infinity, *@object).nan?.should == true + @infinity.send(@method, @infinity_minus, *@object).should.nan? + @infinity_minus.send(@method, @infinity, *@object).should.nan? end it "returns (+|-) Infinity if divided by zero" do @@ -60,8 +60,8 @@ end it "returns NaN if zero is divided by zero" do - @zero.send(@method, @zero, *@object).nan?.should == true - @zero_minus.send(@method, @zero_plus, *@object).nan?.should == true - @zero_plus.send(@method, @zero_minus, *@object).nan?.should == true + @zero.send(@method, @zero, *@object).should.nan? + @zero_minus.send(@method, @zero_plus, *@object).should.nan? + @zero_plus.send(@method, @zero_minus, *@object).should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/shared/to_int.rb b/ruby/spec/ruby/library/bigdecimal/shared/to_int.rb index 02f6092f2..0f1625161 100644 --- a/ruby/spec/ruby/library/bigdecimal/shared/to_int.rb +++ b/ruby/spec/ruby/library/bigdecimal/shared/to_int.rb @@ -6,7 +6,7 @@ -> { BigDecimal("NaN").send(@method) }.should raise_error(FloatDomainError) end - it "returns Integer or Bignum otherwise" do + it "returns Integer otherwise" do BigDecimal("3E-20001").send(@method).should == 0 BigDecimal("2E4000").send(@method).should == 2 * 10 ** 4000 BigDecimal("2").send(@method).should == 2 diff --git a/ruby/spec/ruby/library/bigdecimal/sub_spec.rb b/ruby/spec/ruby/library/bigdecimal/sub_spec.rb index 29ec85119..bddfec218 100644 --- a/ruby/spec/ruby/library/bigdecimal/sub_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/sub_spec.rb @@ -50,13 +50,13 @@ end it "returns NaN if NaN is involved" do - @one.sub(@nan, 1).nan?.should == true - @nan.sub(@one, 1).nan?.should == true + @one.sub(@nan, 1).should.nan? + @nan.sub(@one, 1).should.nan? end it "returns NaN if both values are infinite with the same signs" do - @infinity.sub(@infinity, 1).nan?.should == true - @infinity_minus.sub(@infinity_minus, 1).nan?.should == true + @infinity.sub(@infinity, 1).should.nan? + @infinity_minus.sub(@infinity_minus, 1).should.nan? end it "returns Infinity or -Infinity if these are involved" do diff --git a/ruby/spec/ruby/library/bigdecimal/to_f_spec.rb b/ruby/spec/ruby/library/bigdecimal/to_f_spec.rb index 1cc25d5c4..84d4d49de 100644 --- a/ruby/spec/ruby/library/bigdecimal/to_f_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/to_f_spec.rb @@ -41,7 +41,7 @@ @zero.to_f.should == 0 @zero.to_f.to_s.should == "0.0" - @nan.to_f.nan?.should == true + @nan.to_f.should.nan? @infinity.to_f.infinite?.should == 1 @infinity_minus.to_f.infinite?.should == -1 diff --git a/ruby/spec/ruby/library/bigdecimal/to_s_spec.rb b/ruby/spec/ruby/library/bigdecimal/to_s_spec.rb index b6154c680..4f1054d38 100644 --- a/ruby/spec/ruby/library/bigdecimal/to_s_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/to_s_spec.rb @@ -8,6 +8,11 @@ @bigneg_str = "-3.1415926535897932384626433832795028841971693993" @bigdec = BigDecimal(@bigdec_str) @bigneg = BigDecimal(@bigneg_str) + @internal = Encoding.default_internal + end + + after :each do + Encoding.default_internal = @internal end it "return type is of class String" do @@ -41,6 +46,7 @@ str1 = '-123.45678 90123 45678 9' BigDecimal("-123.45678901234567890").to_s('5F').should == str1 + BigDecimal('1000010').to_s('5F').should == "10000 10.0" # trailing zeroes removed BigDecimal("1.00000000000").to_s('1F').should == "1.0" # 0 is treated as no spaces @@ -77,4 +83,15 @@ end end + ruby_version_is "3.0" do + it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do + Encoding.default_internal = nil + BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do + Encoding.default_internal = Encoding::IBM437 + BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) + end + end end diff --git a/ruby/spec/ruby/library/bigdecimal/truncate_spec.rb b/ruby/spec/ruby/library/bigdecimal/truncate_spec.rb index d3a15f62c..4ad9eb92d 100644 --- a/ruby/spec/ruby/library/bigdecimal/truncate_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/truncate_spec.rb @@ -58,9 +58,9 @@ end it "returns NaN if self is NaN" do - @nan.truncate(-1).nan?.should == true - @nan.truncate(+1).nan?.should == true - @nan.truncate(0).nan?.should == true + @nan.truncate(-1).should.nan? + @nan.truncate(+1).should.nan? + @nan.truncate(0).should.nan? end it "returns Infinity if self is infinite" do diff --git a/ruby/spec/ruby/library/bigdecimal/uminus_spec.rb b/ruby/spec/ruby/library/bigdecimal/uminus_spec.rb index 5e2a786c4..c780cdfac 100644 --- a/ruby/spec/ruby/library/bigdecimal/uminus_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/uminus_spec.rb @@ -53,6 +53,6 @@ @zero_neg.send(:-@).should == @zero @zero_neg.send(:-@).sign.should == 1 - @nan.send(:-@).nan?.should == true + @nan.send(:-@).should.nan? end end diff --git a/ruby/spec/ruby/library/bigdecimal/util_spec.rb b/ruby/spec/ruby/library/bigdecimal/util_spec.rb index f41e13114..fc67fcf20 100644 --- a/ruby/spec/ruby/library/bigdecimal/util_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/util_spec.rb @@ -27,10 +27,8 @@ Rational(22, 7).to_d(3).should == BigDecimal(3.14, 3) end - ruby_version_is "2.6" do - it "should define #to_d on nil" do - nil.to_d.should == BigDecimal(0) - end + it "should define #to_d on nil" do + nil.to_d.should == BigDecimal(0) end end diff --git a/ruby/spec/ruby/library/bigdecimal/zero_spec.rb b/ruby/spec/ruby/library/bigdecimal/zero_spec.rb index c5d3acb8c..256321093 100644 --- a/ruby/spec/ruby/library/bigdecimal/zero_spec.rb +++ b/ruby/spec/ruby/library/bigdecimal/zero_spec.rb @@ -6,22 +6,22 @@ it "returns true if self does equal zero" do really_small_zero = BigDecimal("0E-200000000") really_big_zero = BigDecimal("0E200000000000") - really_small_zero.zero?.should == true - really_big_zero.zero?.should == true - BigDecimal("0.000000000000000000000000").zero?.should == true - BigDecimal("0").zero?.should == true - BigDecimal("0E0").zero?.should == true - BigDecimal("+0").zero?.should == true - BigDecimal("-0").zero?.should == true + really_small_zero.should.zero? + really_big_zero.should.zero? + BigDecimal("0.000000000000000000000000").should.zero? + BigDecimal("0").should.zero? + BigDecimal("0E0").should.zero? + BigDecimal("+0").should.zero? + BigDecimal("-0").should.zero? end it "returns false otherwise" do - BigDecimal("0000000001").zero?.should == false - BigDecimal("2E40001").zero?.should == false - BigDecimal("3E-20001").zero?.should == false - BigDecimal("Infinity").zero?.should == false - BigDecimal("-Infinity").zero?.should == false - BigDecimal("NaN").zero?.should == false + BigDecimal("0000000001").should_not.zero? + BigDecimal("2E40001").should_not.zero? + BigDecimal("3E-20001").should_not.zero? + BigDecimal("Infinity").should_not.zero? + BigDecimal("-Infinity").should_not.zero? + BigDecimal("NaN").should_not.zero? end end diff --git a/ruby/spec/ruby/library/cgi/cookie/to_s_spec.rb b/ruby/spec/ruby/library/cgi/cookie/to_s_spec.rb index 978c2d33e..da15e6ed2 100644 --- a/ruby/spec/ruby/library/cgi/cookie/to_s_spec.rb +++ b/ruby/spec/ruby/library/cgi/cookie/to_s_spec.rb @@ -27,16 +27,7 @@ cookie.to_s.should == "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D; path=" end - ruby_version_is ""..."2.5" do - it "escapes tilde" do - cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=%7E; path=" - end + it "does not escape tilde" do + cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path=" end - - ruby_version_is "2.5" do - it "does not escape tilde" do - cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path=" - end - end - end diff --git a/ruby/spec/ruby/library/cgi/escapeHTML_spec.rb b/ruby/spec/ruby/library/cgi/escapeHTML_spec.rb index dcbfebe72..421aac5d4 100644 --- a/ruby/spec/ruby/library/cgi/escapeHTML_spec.rb +++ b/ruby/spec/ruby/library/cgi/escapeHTML_spec.rb @@ -6,6 +6,10 @@ CGI.escapeHTML(%[& < > " ']).should == '& < > " '' end + it "escapes invalid encoding" do + CGI.escapeHTML(%[<\xA4??>]).should == "<\xA4??>" + end + it "does not escape any other characters" do chars = " !\#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" CGI.escapeHTML(chars).should == chars diff --git a/ruby/spec/ruby/library/cgi/escape_spec.rb b/ruby/spec/ruby/library/cgi/escape_spec.rb index 351bfe107..c599a73cf 100644 --- a/ruby/spec/ruby/library/cgi/escape_spec.rb +++ b/ruby/spec/ruby/library/cgi/escape_spec.rb @@ -7,20 +7,12 @@ expected = "+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D" CGI.escape(input).should == expected - input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" - expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' + input = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" + expected = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' CGI.escape(input).should == expected end - ruby_version_is ""..."2.5" do - it "escapes tilde" do - CGI.escape("~").should == "%7E" - end - end - - ruby_version_is "2.5" do - it "does not escape tilde" do - CGI.escape("~").should == "~" - end + it "does not escape tilde" do + CGI.escape("~").should == "~" end end diff --git a/ruby/spec/ruby/library/cgi/unescapeHTML_spec.rb b/ruby/spec/ruby/library/cgi/unescapeHTML_spec.rb index 46387d4f0..84b30c6aa 100644 --- a/ruby/spec/ruby/library/cgi/unescapeHTML_spec.rb +++ b/ruby/spec/ruby/library/cgi/unescapeHTML_spec.rb @@ -36,4 +36,9 @@ input = "fooooooo&#" CGI.unescapeHTML(input).should == input end + + it "unescapes invalid encoding" do + input = "\xFF&" + CGI.unescapeHTML(input).should == input + end end diff --git a/ruby/spec/ruby/library/cgi/unescape_spec.rb b/ruby/spec/ruby/library/cgi/unescape_spec.rb index db4834e7e..c593e24b4 100644 --- a/ruby/spec/ruby/library/cgi/unescape_spec.rb +++ b/ruby/spec/ruby/library/cgi/unescape_spec.rb @@ -8,8 +8,8 @@ expected = " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" CGI.unescape(input).should == expected - input = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' - expected = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" + input = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' + expected = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" CGI.unescape(input).should == expected end end diff --git a/ruby/spec/ruby/library/conditionvariable/broadcast_spec.rb b/ruby/spec/ruby/library/conditionvariable/broadcast_spec.rb deleted file mode 100644 index a31a0443b..000000000 --- a/ruby/spec/ruby/library/conditionvariable/broadcast_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require_relative '../../spec_helper' -require 'thread' - -describe "ConditionVariable#broadcast" do - it "returns self if nothing to broadcast to" do - cv = ConditionVariable.new - cv.broadcast.should == cv - end - - it "returns self if something is waiting for a broadcast" do - m = Mutex.new - cv = ConditionVariable.new - in_synchronize = false - - th = Thread.new do - m.synchronize do - in_synchronize = true - cv.wait(m) - end - end - - # wait for m to acquire the mutex - Thread.pass until in_synchronize - # wait until th is sleeping (ie waiting) - Thread.pass while th.status and th.status != "sleep" - - m.synchronize { cv.broadcast }.should == cv - - th.join - end - - it "releases all threads waiting in line for this resource" do - m = Mutex.new - cv = ConditionVariable.new - threads = [] - r1 = [] - r2 = [] - - # large number to attempt to cause race conditions - 100.times do |i| - threads << Thread.new(i) do |tid| - m.synchronize do - r1 << tid - cv.wait(m) - r2 << tid - end - end - end - - # wait for all threads to acquire the mutex the first time - Thread.pass until m.synchronize { r1.size == threads.size } - # wait until all threads are sleeping (ie waiting) - Thread.pass until threads.all? {|th| th.status == "sleep" } - - r2.should be_empty - m.synchronize do - cv.broadcast - end - - threads.each {|t| t.join } - - # ensure that all threads that enter cv.wait are released - r2.sort.should == r1.sort - # note that order is not specified as broadcast results in a race - # condition on regaining the lock m - end -end diff --git a/ruby/spec/ruby/library/conditionvariable/signal_spec.rb b/ruby/spec/ruby/library/conditionvariable/signal_spec.rb deleted file mode 100644 index 04b249a6c..000000000 --- a/ruby/spec/ruby/library/conditionvariable/signal_spec.rb +++ /dev/null @@ -1,104 +0,0 @@ -require_relative '../../spec_helper' -require 'thread' - -describe "ConditionVariable#signal" do - it "returns self if nothing to signal" do - cv = ConditionVariable.new - cv.signal.should == cv - end - - it "returns self if something is waiting for a signal" do - m = Mutex.new - cv = ConditionVariable.new - in_synchronize = false - - th = Thread.new do - m.synchronize do - in_synchronize = true - cv.wait(m) - end - end - - # wait for m to acquire the mutex - Thread.pass until in_synchronize - # wait until th is sleeping (ie waiting) - Thread.pass while th.status and th.status != "sleep" - - m.synchronize { cv.signal }.should == cv - - th.join - end - - it "releases the first thread waiting in line for this resource" do - m = Mutex.new - cv = ConditionVariable.new - threads = [] - r1 = [] - r2 = [] - - # large number to attempt to cause race conditions - 100.times do |i| - threads << Thread.new(i) do |tid| - m.synchronize do - r1 << tid - cv.wait(m) - r2 << tid - end - end - end - - # wait for all threads to acquire the mutex the first time - Thread.pass until m.synchronize { r1.size == threads.size } - # wait until all threads are sleeping (ie waiting) - Thread.pass until threads.all? {|th| th.status == "sleep" } - - r2.should be_empty - 100.times do |i| - m.synchronize do - cv.signal - end - Thread.pass until r2.size == i+1 - end - - threads.each {|t| t.join } - - # ensure that all the threads that went into the cv.wait are - # released in the same order - r2.should == r1 - end - - it "allows control to be passed between a pair of threads" do - m = Mutex.new - cv = ConditionVariable.new - repeats = 100 - in_synchronize = false - - t1 = Thread.new do - m.synchronize do - in_synchronize = true - repeats.times do - cv.wait(m) - cv.signal - end - end - end - - # Make sure t1 is waiting for a signal before launching t2. - Thread.pass until in_synchronize - Thread.pass until t1.status == 'sleep' - - t2 = Thread.new do - m.synchronize do - repeats.times do - cv.signal - cv.wait(m) - end - end - end - - # Check that both threads terminated without exception - t1.join - t2.join - m.locked?.should == false - end -end diff --git a/ruby/spec/ruby/library/conditionvariable/wait_spec.rb b/ruby/spec/ruby/library/conditionvariable/wait_spec.rb deleted file mode 100644 index f57ab4c77..000000000 --- a/ruby/spec/ruby/library/conditionvariable/wait_spec.rb +++ /dev/null @@ -1,132 +0,0 @@ -require_relative '../../spec_helper' -require 'thread' - -describe "ConditionVariable#wait" do - it "calls #sleep on the given object" do - o = Object.new - o.should_receive(:sleep).with(1234) - - cv = ConditionVariable.new - - cv.wait(o, 1234) - end - - it "returns self" do - m = Mutex.new - cv = ConditionVariable.new - in_synchronize = false - - th = Thread.new do - m.synchronize do - in_synchronize = true - cv.wait(m).should == cv - end - end - - # wait for m to acquire the mutex - Thread.pass until in_synchronize - # wait until th is sleeping (ie waiting) - Thread.pass while th.status and th.status != "sleep" - - m.synchronize { cv.signal } - th.join - end - - it "reacquires the lock even if the thread is killed" do - m = Mutex.new - cv = ConditionVariable.new - in_synchronize = false - owned = nil - - th = Thread.new do - m.synchronize do - in_synchronize = true - begin - cv.wait(m) - ensure - owned = m.owned? - $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned - end - end - end - - # wait for m to acquire the mutex - Thread.pass until in_synchronize - # wait until th is sleeping (ie waiting) - Thread.pass while th.status and th.status != "sleep" - - th.kill - th.join - - owned.should == true - end - - ruby_bug '#14999', ''...'2.5' do - it "reacquires the lock even if the thread is killed after being signaled" do - m = Mutex.new - cv = ConditionVariable.new - in_synchronize = false - owned = nil - - th = Thread.new do - m.synchronize do - in_synchronize = true - begin - cv.wait(m) - ensure - owned = m.owned? - $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned - end - end - end - - # wait for m to acquire the mutex - Thread.pass until in_synchronize - # wait until th is sleeping (ie waiting) - Thread.pass while th.status and th.status != "sleep" - - m.synchronize { - cv.signal - # Wait that the thread is blocked on acquiring the Mutex - sleep 0.001 - # Kill the thread, yet the thread should first acquire the Mutex before going on - th.kill - } - - th.join - owned.should == true - end - end - - it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do - m = Mutex.new - cv = ConditionVariable.new - n_threads = 4 - events = [] - - threads = n_threads.times.map { - Thread.new { - m.synchronize { - events << :t_in_synchronize - cv.wait(m) - } - } - } - - Thread.pass until m.synchronize { events.size } == n_threads - Thread.pass while threads.any? { |th| th.status and th.status != "sleep" } - m.synchronize do - threads.each { |t| - # Cause interactions with the waiting threads. - # On TruffleRuby, this causes a safepoint which has interesting - # interactions with the ConditionVariable. - bt = t.backtrace - bt.should be_kind_of(Array) - bt.size.should >= 2 - } - end - - cv.broadcast - threads.each(&:join) - end -end diff --git a/ruby/spec/ruby/library/coverage/fixtures/eval_code.rb b/ruby/spec/ruby/library/coverage/fixtures/eval_code.rb new file mode 100644 index 000000000..8ab82218f --- /dev/null +++ b/ruby/spec/ruby/library/coverage/fixtures/eval_code.rb @@ -0,0 +1,11 @@ +5 + 5 + +module CoverageSpecs + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + attr_reader :ok + RUBY + +end + +4 + 4 diff --git a/ruby/spec/ruby/library/coverage/result_spec.rb b/ruby/spec/ruby/library/coverage/result_spec.rb index 9b8453007..4cc43e846 100644 --- a/ruby/spec/ruby/library/coverage/result_spec.rb +++ b/ruby/spec/ruby/library/coverage/result_spec.rb @@ -5,11 +5,13 @@ before :all do @class_file = fixture __FILE__, 'some_class.rb' @config_file = fixture __FILE__, 'start_coverage.rb' + @eval_code_file = fixture __FILE__, 'eval_code.rb' end after :each do $LOADED_FEATURES.delete(@class_file) $LOADED_FEATURES.delete(@config_file) + $LOADED_FEATURES.delete(@eval_code_file) end it 'gives the covered files as a hash with arrays of count or nil' do @@ -63,16 +65,41 @@ result.should == {} end - it 'second Coverage.start does nothing' do - Coverage.start - require @config_file.chomp('.rb') - result = Coverage.result + ruby_version_is ''...'3.1' do + it 'second Coverage.start does nothing' do + Coverage.start + require @config_file.chomp('.rb') + result = Coverage.result - result.should == { @config_file => [1, 1, 1] } + result.should == { @config_file => [1, 1, 1] } + end + end + + ruby_version_is '3.1' do + it 'second Coverage.start give exception' do + Coverage.start + -> { + require @config_file.chomp('.rb') + }.should raise_error(RuntimeError, 'coverage measurement is already setup') + ensure + Coverage.result + end end it 'does not include the file starting coverage since it is not tracked' do require @config_file.chomp('.rb') Coverage.result.should_not include(@config_file) end + + it 'returns the correct results when eval is used' do + Coverage.start + require @eval_code_file.chomp('.rb') + result = Coverage.result + + result.should == { + @eval_code_file => [ + 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1 + ] + } + end end diff --git a/ruby/spec/ruby/library/csv/liberal_parsing_spec.rb b/ruby/spec/ruby/library/csv/liberal_parsing_spec.rb index 2929d6e2a..987865802 100644 --- a/ruby/spec/ruby/library/csv/liberal_parsing_spec.rb +++ b/ruby/spec/ruby/library/csv/liberal_parsing_spec.rb @@ -4,16 +4,16 @@ describe "CSV#liberal_parsing?" do it "returns true if illegal input is handled" do csv = CSV.new("", liberal_parsing: true) - csv.liberal_parsing?.should == true + csv.should.liberal_parsing? end it "returns false if illegal input is not handled" do csv = CSV.new("", liberal_parsing: false) - csv.liberal_parsing?.should == false + csv.should_not.liberal_parsing? end it "returns false by default" do csv = CSV.new("") - csv.liberal_parsing?.should == false + csv.should_not.liberal_parsing? end end diff --git a/ruby/spec/ruby/library/date/constants_spec.rb b/ruby/spec/ruby/library/date/constants_spec.rb index fc1dba499..1d18dd1b0 100644 --- a/ruby/spec/ruby/library/date/constants_spec.rb +++ b/ruby/spec/ruby/library/date/constants_spec.rb @@ -36,11 +36,11 @@ [Date::MONTHNAMES, Date::DAYNAMES, Date::ABBR_MONTHNAMES, Date::ABBR_DAYNAMES].each do |ary| -> { ary << "Unknown" - }.should raise_error(frozen_error_class, /frozen/) + }.should raise_error(FrozenError, /frozen/) ary.compact.each do |name| -> { name << "modified" - }.should raise_error(frozen_error_class, /frozen/) + }.should raise_error(FrozenError, /frozen/) end end end diff --git a/ruby/spec/ruby/library/date/gregorian_spec.rb b/ruby/spec/ruby/library/date/gregorian_spec.rb index 8b7033fe7..ea7ece2ad 100644 --- a/ruby/spec/ruby/library/date/gregorian_spec.rb +++ b/ruby/spec/ruby/library/date/gregorian_spec.rb @@ -9,7 +9,7 @@ end it "marks a day after the calendar reform as Julian" do - Date.civil(2007, 2, 27).gregorian?.should == true + Date.civil(2007, 2, 27).should.gregorian? Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).gregorian?.should be_true end diff --git a/ruby/spec/ruby/library/date/infinity_spec.rb b/ruby/spec/ruby/library/date/infinity_spec.rb index 81d67ae24..721fd7606 100644 --- a/ruby/spec/ruby/library/date/infinity_spec.rb +++ b/ruby/spec/ruby/library/date/infinity_spec.rb @@ -5,16 +5,16 @@ it "should be able to check whether Infinity is zero" do i = Date::Infinity.new - i.zero?.should == false + i.should_not.zero? end it "should be able to check whether Infinity is finite" do i1 = Date::Infinity.new - i1.finite?.should == false + i1.should_not.finite? i2 = Date::Infinity.new(-1) - i2.finite?.should == false + i2.should_not.finite? i3 = Date::Infinity.new(0) - i3.finite?.should == false + i3.should_not.finite? end it "should be able to check whether Infinity is infinite" do @@ -28,11 +28,11 @@ it "should be able to check whether Infinity is not a number" do i1 = Date::Infinity.new - i1.nan?.should == false + i1.should_not.nan? i2 = Date::Infinity.new(-1) - i2.nan?.should == false + i2.should_not.nan? i3 = Date::Infinity.new(0) - i3.nan?.should == true + i3.should.nan? end it "should be able to compare Infinity objects" do diff --git a/ruby/spec/ruby/library/date/julian_spec.rb b/ruby/spec/ruby/library/date/julian_spec.rb index 637a4739e..db2629d1e 100644 --- a/ruby/spec/ruby/library/date/julian_spec.rb +++ b/ruby/spec/ruby/library/date/julian_spec.rb @@ -4,12 +4,12 @@ describe "Date#julian?" do it "marks a day before the calendar reform as Julian" do - Date.civil(1007, 2, 27).julian?.should == true + Date.civil(1007, 2, 27).should.julian? Date.civil(1907, 2, 27, Date.civil(1930, 1, 1).jd).julian?.should be_true end it "marks a day after the calendar reform as Julian" do - Date.civil(2007, 2, 27).julian?.should == false + Date.civil(2007, 2, 27).should_not.julian? Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).julian?.should be_false end diff --git a/ruby/spec/ruby/library/date/parse_spec.rb b/ruby/spec/ruby/library/date/parse_spec.rb index 379847a6f..ef72ba3f4 100644 --- a/ruby/spec/ruby/library/date/parse_spec.rb +++ b/ruby/spec/ruby/library/date/parse_spec.rb @@ -69,6 +69,23 @@ -> { Date.parse(1) }.should raise_error(TypeError) -> { Date.parse(:invalid) }.should raise_error(TypeError) end + + it "coerces using to_str" do + c = Class.new do + attr_accessor :string + def to_str + @string + end + end + o = c.new + o.string = "19101101" + + d = Date.parse(o) + d.should == Date.civil(1910, 11, 1) + + # parse should not modify string value + o.to_str.should == "19101101" + end end describe "Date#parse with '.' separator" do diff --git a/ruby/spec/ruby/library/date/shared/civil.rb b/ruby/spec/ruby/library/date/shared/civil.rb index 4c8ba2362..bbed4a886 100644 --- a/ruby/spec/ruby/library/date/shared/civil.rb +++ b/ruby/spec/ruby/library/date/shared/civil.rb @@ -5,7 +5,7 @@ d.year.should == -4712 d.month.should == 1 d.day.should == 1 - d.julian?.should == true + d.should.julian? d.jd.should == 0 end @@ -14,7 +14,7 @@ d.year.should == 2000 d.month.should == 3 d.day.should == 5 - d.julian?.should == false + d.should_not.julian? d.jd.should == 2451609 # Should also work with years far in the past and future @@ -23,14 +23,14 @@ d.year.should == -9000 d.month.should == 7 d.day.should == 5 - d.julian?.should == true + d.should.julian? d.jd.should == -1566006 d = Date.send(@method, 9000, 10, 14) d.year.should == 9000 d.month.should == 10 d.day.should == 14 - d.julian?.should == false + d.should_not.julian? d.jd.should == 5008529 end diff --git a/ruby/spec/ruby/library/date/strftime_spec.rb b/ruby/spec/ruby/library/date/strftime_spec.rb index 9d298e42e..8b1ebe061 100644 --- a/ruby/spec/ruby/library/date/strftime_spec.rb +++ b/ruby/spec/ruby/library/date/strftime_spec.rb @@ -22,9 +22,18 @@ end # %v is %e-%b-%Y for Date/DateTime - it "should be able to show the commercial week" do - @date.strftime("%v").should == " 9-Apr-2000" - @date.strftime("%v").should == @date.strftime('%e-%b-%Y') + ruby_version_is ""..."3.1" do + it "should be able to show the commercial week" do + @date.strftime("%v").should == " 9-Apr-2000" + @date.strftime("%v").should == @date.strftime('%e-%b-%Y') + end + end + + ruby_version_is "3.1" do + it "should be able to show the commercial week" do + @date.strftime("%v").should == " 9-APR-2000" + @date.strftime("%v").should != @date.strftime('%e-%b-%Y') + end end # additional conversion specifiers only in Date/DateTime diff --git a/ruby/spec/ruby/library/datetime/strftime_spec.rb b/ruby/spec/ruby/library/datetime/strftime_spec.rb index 1c925f92e..725bcafb0 100644 --- a/ruby/spec/ruby/library/datetime/strftime_spec.rb +++ b/ruby/spec/ruby/library/datetime/strftime_spec.rb @@ -1,3 +1,4 @@ +require_relative '../../spec_helper' require 'date' require_relative '../../shared/time/strftime_for_date' require_relative '../../shared/time/strftime_for_time' @@ -32,9 +33,18 @@ end # %v is %e-%b-%Y for Date/DateTime - it "should be able to show the commercial week" do - @time.strftime("%v").should == " 3-Feb-2001" - @time.strftime("%v").should == @time.strftime('%e-%b-%Y') + ruby_version_is ""..."3.1" do + it "should be able to show the commercial week" do + @time.strftime("%v").should == " 3-Feb-2001" + @time.strftime("%v").should == @time.strftime('%e-%b-%Y') + end + end + + ruby_version_is "3.1" do + it "should be able to show the commercial week" do + @time.strftime("%v").should == " 3-FEB-2001" + @time.strftime("%v").should != @time.strftime('%e-%b-%Y') + end end # additional conversion specifiers only in Date/DateTime diff --git a/ruby/spec/ruby/library/delegate/delegator/eql_spec.rb b/ruby/spec/ruby/library/delegate/delegator/eql_spec.rb index 3170d5727..34f56f44c 100644 --- a/ruby/spec/ruby/library/delegate/delegator/eql_spec.rb +++ b/ruby/spec/ruby/library/delegate/delegator/eql_spec.rb @@ -2,45 +2,34 @@ require_relative '../fixtures/classes' describe "Delegator#eql?" do - ruby_version_is ""..."2.5" do - it "is delegated" do - base = mock('base') - delegator = DelegateSpecs::Delegator.new(base) - base.should_receive(:eql?).with(42).and_return(:foo) - delegator.eql?(42).should == :foo - end - end - - ruby_version_is "2.5" do - it "returns true when compared with same delegator" do - base = mock('base') - delegator = DelegateSpecs::Delegator.new(base) + it "returns true when compared with same delegator" do + base = mock('base') + delegator = DelegateSpecs::Delegator.new(base) - delegator.eql?(delegator).should be_true - end + delegator.eql?(delegator).should be_true + end - it "returns true when compared with the inner object" do - base = mock('base') - delegator = DelegateSpecs::Delegator.new(base) + it "returns true when compared with the inner object" do + base = mock('base') + delegator = DelegateSpecs::Delegator.new(base) - delegator.eql?(base).should be_true - end + delegator.eql?(base).should be_true + end - it "returns false when compared with the delegator with other object" do - base = mock('base') - other = mock('other') - delegator0 = DelegateSpecs::Delegator.new(base) - delegator1 = DelegateSpecs::Delegator.new(other) + it "returns false when compared with the delegator with other object" do + base = mock('base') + other = mock('other') + delegator0 = DelegateSpecs::Delegator.new(base) + delegator1 = DelegateSpecs::Delegator.new(other) - delegator0.eql?(delegator1).should be_false - end + delegator0.eql?(delegator1).should be_false + end - it "returns false when compared with the other object" do - base = mock('base') - other = mock('other') - delegator = DelegateSpecs::Delegator.new(base) + it "returns false when compared with the other object" do + base = mock('base') + other = mock('other') + delegator = DelegateSpecs::Delegator.new(base) - delegator.eql?(other).should be_false - end + delegator.eql?(other).should be_false end end diff --git a/ruby/spec/ruby/library/digest/bubblebabble_spec.rb b/ruby/spec/ruby/library/digest/bubblebabble_spec.rb index e65167110..bbc11ceec 100644 --- a/ruby/spec/ruby/library/digest/bubblebabble_spec.rb +++ b/ruby/spec/ruby/library/digest/bubblebabble_spec.rb @@ -23,7 +23,7 @@ -> { Digest.bubblebabble(nil) }.should raise_error(TypeError) end - it "raises a TypeError when passed a Fixnum" do + it "raises a TypeError when passed an Integer" do -> { Digest.bubblebabble(9001) }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/library/digest/hexencode_spec.rb b/ruby/spec/ruby/library/digest/hexencode_spec.rb index fcbbf4846..4b6db6eaf 100644 --- a/ruby/spec/ruby/library/digest/hexencode_spec.rb +++ b/ruby/spec/ruby/library/digest/hexencode_spec.rb @@ -25,7 +25,7 @@ -> { Digest.hexencode(nil) }.should raise_error(TypeError) end - it "raises a TypeError when passed a Fixnum" do + it "raises a TypeError when passed an Integer" do -> { Digest.hexencode(9001) }.should raise_error(TypeError) end end diff --git a/ruby/spec/ruby/library/digest/instance/append_spec.rb b/ruby/spec/ruby/library/digest/instance/append_spec.rb new file mode 100644 index 000000000..249957929 --- /dev/null +++ b/ruby/spec/ruby/library/digest/instance/append_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../../spec_helper' +require 'digest' +require_relative 'shared/update' + +describe "Digest::Instance#<<" do + it_behaves_like :digest_instance_update, :<< +end diff --git a/ruby/spec/ruby/library/digest/instance/new_spec.rb b/ruby/spec/ruby/library/digest/instance/new_spec.rb new file mode 100644 index 000000000..3f7939844 --- /dev/null +++ b/ruby/spec/ruby/library/digest/instance/new_spec.rb @@ -0,0 +1,19 @@ +require_relative '../../../spec_helper' +require 'digest' +require_relative '../md5/shared/constants' + +describe "Digest::Instance#new" do + it "returns a copy of the digest instance" do + digest = Digest::MD5.new + copy = digest.new + copy.should_not.equal?(digest) + end + + it "calls reset" do + digest = Digest::MD5.new + digest << "test" + digest.hexdigest.should != MD5Constants::BlankHexdigest + copy = digest.new + copy.hexdigest.should == MD5Constants::BlankHexdigest + end +end diff --git a/ruby/spec/ruby/library/digest/instance/shared/update.rb b/ruby/spec/ruby/library/digest/instance/shared/update.rb new file mode 100644 index 000000000..dccc8f80d --- /dev/null +++ b/ruby/spec/ruby/library/digest/instance/shared/update.rb @@ -0,0 +1,8 @@ +describe :digest_instance_update, shared: true do + it "raises a RuntimeError if called" do + c = Class.new do + include Digest::Instance + end + -> { c.new.update("test") }.should raise_error(RuntimeError) + end +end diff --git a/ruby/spec/ruby/library/digest/instance/update_spec.rb b/ruby/spec/ruby/library/digest/instance/update_spec.rb new file mode 100644 index 000000000..3bb4dd7f1 --- /dev/null +++ b/ruby/spec/ruby/library/digest/instance/update_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../../spec_helper' +require 'digest' +require_relative 'shared/update' + +describe "Digest::Instance#update" do + it_behaves_like :digest_instance_update, :update +end diff --git a/ruby/spec/ruby/library/digest/md5/shared/constants.rb b/ruby/spec/ruby/library/digest/md5/shared/constants.rb index fdfae56d6..e807b96f9 100644 --- a/ruby/spec/ruby/library/digest/md5/shared/constants.rb +++ b/ruby/spec/ruby/library/digest/md5/shared/constants.rb @@ -12,5 +12,6 @@ module MD5Constants Digest = "\2473\267qw\276\364\343\345\320\304\350\313\314\217n" BlankHexdigest = "d41d8cd98f00b204e9800998ecf8427e" Hexdigest = "a733b77177bef4e3e5d0c4e8cbcc8f6e" + Base64digest = "pzO3cXe+9OPl0MToy8yPbg==" end diff --git a/ruby/spec/ruby/library/digest/sha1/shared/constants.rb b/ruby/spec/ruby/library/digest/sha1/shared/constants.rb index add86b1dd..169438747 100644 --- a/ruby/spec/ruby/library/digest/sha1/shared/constants.rb +++ b/ruby/spec/ruby/library/digest/sha1/shared/constants.rb @@ -12,6 +12,7 @@ module SHA1Constants BlankDigest = "\3329\243\356^kK\r2U\277\357\225`\030\220\257\330\a\t" Digest = "X!\255b\323\035\352\314a|q\344+\376\317\361V9\324\343" BlankHexdigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709" - Hexdigest = "e907d2ba21c6c74bc0efd76e44d11fb9bbb7a75e" + Hexdigest = "5821ad62d31deacc617c71e42bfecff15639d4e3" + Base64digest = "WCGtYtMd6sxhfHHkK/7P8VY51OM=" end diff --git a/ruby/spec/ruby/library/digest/sha2/hexdigest_spec.rb b/ruby/spec/ruby/library/digest/sha2/hexdigest_spec.rb new file mode 100644 index 000000000..79beca578 --- /dev/null +++ b/ruby/spec/ruby/library/digest/sha2/hexdigest_spec.rb @@ -0,0 +1,32 @@ +require_relative '../../../spec_helper' +require_relative '../sha256/shared/constants' + +describe "Digest::SHA2#hexdigest" do + + it "returns a SHA256 hexdigest by default" do + cur_digest = Digest::SHA2.new + cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest + + # add something to check that the state is reset later + cur_digest << "test" + + cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest + # second invocation is intentional, to make sure there are no side-effects + cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest + + # after all is done, verify that the digest is in the original, blank state + cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest + end + +end + +describe "Digest::SHA2.hexdigest" do + + it "returns a SHA256 hexdigest by default" do + Digest::SHA2.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest + # second invocation is intentional, to make sure there are no side-effects + Digest::SHA2.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest + Digest::SHA2.hexdigest("").should == SHA256Constants::BlankHexdigest + end + +end diff --git a/ruby/spec/ruby/library/digest/sha256/file_spec.rb b/ruby/spec/ruby/library/digest/sha256/file_spec.rb index 6103971b5..8cbc5a275 100644 --- a/ruby/spec/ruby/library/digest/sha256/file_spec.rb +++ b/ruby/spec/ruby/library/digest/sha256/file_spec.rb @@ -22,6 +22,10 @@ Digest::SHA256.file(@file).digest.should == SHA256Constants::Digest end + it "can be used with frozen-string-literal" do + ruby_exe("require 'digest'; puts Digest::SHA256.file(#{@file.inspect}).digest.inspect", options: "--enable=frozen-string-literal").chomp.should == SHA256Constants::Digest.inspect + end + it "calls #to_str on an object and returns the Digest::SHA256 with the result" do obj = mock("to_str") obj.should_receive(:to_str).and_return(@file) diff --git a/ruby/spec/ruby/library/digest/sha256/shared/constants.rb b/ruby/spec/ruby/library/digest/sha256/shared/constants.rb index dd5b48dca..351679f34 100644 --- a/ruby/spec/ruby/library/digest/sha256/shared/constants.rb +++ b/ruby/spec/ruby/library/digest/sha256/shared/constants.rb @@ -13,5 +13,6 @@ module SHA256Constants Digest = "\230b\265\344_\337\357\337\242\004\314\311A\211jb\350\373\254\370\365M\230B\002\372\020j\as\270\376" BlankHexdigest = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" Hexdigest = "9862b5e45fdfefdfa204ccc941896a62e8fbacf8f54d984202fa106a0773b8fe" + Base64digest = "mGK15F/f79+iBMzJQYlqYuj7rPj1TZhCAvoQagdzuP4=" end diff --git a/ruby/spec/ruby/library/digest/sha384/shared/constants.rb b/ruby/spec/ruby/library/digest/sha384/shared/constants.rb index 3697384fc..2050f03f2 100644 --- a/ruby/spec/ruby/library/digest/sha384/shared/constants.rb +++ b/ruby/spec/ruby/library/digest/sha384/shared/constants.rb @@ -14,5 +14,6 @@ module SHA384Constants Digest = "B&\266:\314\216z\361!TD\001{`\355\323\320MW%\270\272\0034n\034\026g\a\217\"\333s\202\275\002Y*\217]\207u\f\034\244\231\266f" BlankHexdigest = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" Hexdigest = "4226b63acc8e7af1215444017b60edd3d04d5725b8ba03346e1c1667078f22db7382bd02592a8f5d87750c1ca499b666" + Base64digest = "Qia2OsyOevEhVEQBe2Dt09BNVyW4ugM0bhwWZwePIttzgr0CWSqPXYd1DBykmbZm" end diff --git a/ruby/spec/ruby/library/digest/sha512/shared/constants.rb b/ruby/spec/ruby/library/digest/sha512/shared/constants.rb index 80f5b7bc1..2765a1ec1 100644 --- a/ruby/spec/ruby/library/digest/sha512/shared/constants.rb +++ b/ruby/spec/ruby/library/digest/sha512/shared/constants.rb @@ -13,5 +13,6 @@ module SHA512Constants Digest = "\241\231\232\365\002z\241\331\242\310=\367F\272\004\326\331g\315n\251Q\222\250\374E\257\254=\325\225\003SM\350\244\234\220\233=\031\230A;\000\203\233\340\323t\333\271\222w\266\307\2678\344\255j\003\216\300" BlankHexdigest = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" Hexdigest = "a1999af5027aa1d9a2c83df746ba04d6d967cd6ea95192a8fc45afac3dd59503534de8a49c909b3d1998413b00839be0d374dbb99277b6c7b738e4ad6a038ec0" + Base64digest = "oZma9QJ6odmiyD33RroE1tlnzW6pUZKo/EWvrD3VlQNTTeiknJCbPRmYQTsAg5vg03TbuZJ3tse3OOStagOOwA==" end diff --git a/ruby/spec/ruby/library/erb/fixtures/classes.rb b/ruby/spec/ruby/library/erb/fixtures/classes.rb index 03da88994..e07a6ed68 100644 --- a/ruby/spec/ruby/library/erb/fixtures/classes.rb +++ b/ruby/spec/ruby/library/erb/fixtures/classes.rb @@ -1,9 +1,5 @@ module ERBSpecs def self.new_erb(input, trim_mode: nil) - if ruby_version_is "2.6" - ERB.new(input, trim_mode: trim_mode) - else - ERB.new(input, nil, trim_mode) - end + ERB.new(input, trim_mode: trim_mode) end end diff --git a/ruby/spec/ruby/library/erb/new_spec.rb b/ruby/spec/ruby/library/erb/new_spec.rb index 3bb870dd3..f18e25939 100644 --- a/ruby/spec/ruby/library/erb/new_spec.rb +++ b/ruby/spec/ruby/library/erb/new_spec.rb @@ -36,12 +36,10 @@ end end - ruby_version_is "2.6" do - it "warns invalid trim_mode" do - -> do - ERBSpecs.new_erb(@eruby_str, trim_mode: '') - end.should complain(/Invalid ERB trim mode/) - end + it "warns invalid trim_mode" do + -> do + ERBSpecs.new_erb(@eruby_str, trim_mode: '') + end.should complain(/Invalid ERB trim mode/) end it "removes '\n' when trim_mode is 1 or '>'" do @@ -120,13 +118,8 @@ it "changes '_erbout' variable name in the produced source" do input = @eruby_str - if RUBY_VERSION >= '2.6' - match_erbout = ERB.new(input, trim_mode: nil).src - match_buf = ERB.new(input, trim_mode: nil, eoutvar: 'buf').src - else - match_erbout = ERB.new(input, nil, nil).src - match_buf = ERB.new(input, nil, nil, 'buf').src - end + match_erbout = ERB.new(input, trim_mode: nil).src + match_buf = ERB.new(input, trim_mode: nil, eoutvar: 'buf').src match_erbout.gsub("_erbout", "buf").should == match_buf end diff --git a/ruby/spec/ruby/library/erb/util/shared/url_encode.rb b/ruby/spec/ruby/library/erb/util/shared/url_encode.rb index 5ac621552..34009c490 100644 --- a/ruby/spec/ruby/library/erb/util/shared/url_encode.rb +++ b/ruby/spec/ruby/library/erb/util/shared/url_encode.rb @@ -6,21 +6,13 @@ ERB::Util.__send__(@method, input).should == expected end - ruby_version_is ""..."2.5" do - it "escapes tilde" do - ERB::Util.__send__(@method, "~").should == "%7E" - end - end - - ruby_version_is "2.5" do - it "does not escape tilde" do - ERB::Util.__send__(@method, "~").should == "~" - end + it "does not escape tilde" do + ERB::Util.__send__(@method, "~").should == "~" end it "encode unicode string" do - input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" - expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' + input = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277" + expected = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF' ERB::Util.__send__(@method, input).should == expected end diff --git a/ruby/spec/ruby/library/etc/confstr_spec.rb b/ruby/spec/ruby/library/etc/confstr_spec.rb index 0c922a3a7..41a970a91 100644 --- a/ruby/spec/ruby/library/etc/confstr_spec.rb +++ b/ruby/spec/ruby/library/etc/confstr_spec.rb @@ -1,7 +1,7 @@ require File.expand_path('../../../spec_helper', __FILE__) require 'etc' -platform_is_not :windows do +platform_is_not :windows, :android do describe "Etc.confstr" do it "returns a String for Etc::CS_PATH" do Etc.confstr(Etc::CS_PATH).should be_an_instance_of(String) diff --git a/ruby/spec/ruby/library/etc/getgrgid_spec.rb b/ruby/spec/ruby/library/etc/getgrgid_spec.rb index c7bd55b20..14da5e041 100644 --- a/ruby/spec/ruby/library/etc/getgrgid_spec.rb +++ b/ruby/spec/ruby/library/etc/getgrgid_spec.rb @@ -46,13 +46,6 @@ gr.name.should == @name end - it "returns the Group for a given gid if it exists" do - grp = Etc.getgrgid(@gid) - grp.should be_kind_of(Struct::Group) - grp.gid.should == @gid - grp.name.should == @name - end - it "raises if the group does not exist" do -> { Etc.getgrgid(9876)}.should raise_error(ArgumentError) end diff --git a/ruby/spec/ruby/library/etc/getgrnam_spec.rb b/ruby/spec/ruby/library/etc/getgrnam_spec.rb index a7c624efb..fa49f1534 100644 --- a/ruby/spec/ruby/library/etc/getgrnam_spec.rb +++ b/ruby/spec/ruby/library/etc/getgrnam_spec.rb @@ -11,7 +11,7 @@ end end -platform_is_not :windows do +platform_is_not :windows, :android do describe "Etc.getgrnam" do it "returns a Etc::Group struct instance for the given group" do gr_name = Etc.getgrent.name diff --git a/ruby/spec/ruby/library/etc/group_spec.rb b/ruby/spec/ruby/library/etc/group_spec.rb index fdd39bda1..fda808eec 100644 --- a/ruby/spec/ruby/library/etc/group_spec.rb +++ b/ruby/spec/ruby/library/etc/group_spec.rb @@ -5,7 +5,7 @@ describe "Etc.group" do it_behaves_like :etc_on_windows, :group - platform_is_not :windows do + platform_is_not :windows, :android do it "returns a Etc::Group struct" do group = Etc.group begin diff --git a/ruby/spec/ruby/library/etc/struct_group_spec.rb b/ruby/spec/ruby/library/etc/struct_group_spec.rb index 0b50ff578..b2147e306 100644 --- a/ruby/spec/ruby/library/etc/struct_group_spec.rb +++ b/ruby/spec/ruby/library/etc/struct_group_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' require 'etc' -describe "Struct::Group" do +describe "Etc::Group" do platform_is_not :windows do grpname = IO.popen(%w'id -gn', err: IO::NULL, &:read) next unless $?.success? diff --git a/ruby/spec/ruby/library/etc/struct_passwd_spec.rb b/ruby/spec/ruby/library/etc/struct_passwd_spec.rb index 93ad9dfa2..dc37c17e7 100644 --- a/ruby/spec/ruby/library/etc/struct_passwd_spec.rb +++ b/ruby/spec/ruby/library/etc/struct_passwd_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' require 'etc' -describe "Struct::Passwd" do +describe "Etc::Passwd" do platform_is_not :windows do before :all do @pw = Etc.getpwuid(`id -u`.strip.to_i) diff --git a/ruby/spec/ruby/library/fiber/current_spec.rb b/ruby/spec/ruby/library/fiber/current_spec.rb index 52dff3dea..e67d7d050 100644 --- a/ruby/spec/ruby/library/fiber/current_spec.rb +++ b/ruby/spec/ruby/library/fiber/current_spec.rb @@ -42,10 +42,22 @@ fiber3 = Fiber.new do states << :fiber3 fiber2.transfer - flunk + ruby_version_is '3.0' do + states << :fiber3_terminated + end + ruby_version_is '' ... '3.0' do + flunk + end end fiber3.resume - states.should == [:fiber3, :fiber2, :fiber] + + ruby_version_is "" ... "3.0" do + states.should == [:fiber3, :fiber2, :fiber] + end + + ruby_version_is "3.0" do + states.should == [:fiber3, :fiber2, :fiber, :fiber3_terminated] + end end end diff --git a/ruby/spec/ruby/library/fiber/resume_spec.rb b/ruby/spec/ruby/library/fiber/resume_spec.rb index dae717c8a..8b7c104a6 100644 --- a/ruby/spec/ruby/library/fiber/resume_spec.rb +++ b/ruby/spec/ruby/library/fiber/resume_spec.rb @@ -3,10 +3,33 @@ require 'fiber' describe "Fiber#resume" do - it "raises a FiberError if the Fiber has transferred control to another Fiber" do - fiber1 = Fiber.new { true } - fiber2 = Fiber.new { fiber1.transfer; Fiber.yield } - fiber2.resume - -> { fiber2.resume }.should raise_error(FiberError) + ruby_version_is '' ... '3.0' do + it "raises a FiberError if the Fiber has transferred control to another Fiber" do + fiber1 = Fiber.new { true } + fiber2 = Fiber.new { fiber1.transfer; Fiber.yield } + fiber2.resume + -> { fiber2.resume }.should raise_error(FiberError) + end + + it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do + root_fiber = Fiber.current + fiber1 = Fiber.new { root_fiber.resume } + -> { fiber1.resume }.should raise_error(FiberError, /double resume/) + end + end + + ruby_version_is '3.0' do + it "can work with Fiber#transfer" do + fiber1 = Fiber.new { true } + fiber2 = Fiber.new { fiber1.transfer; Fiber.yield 10 ; Fiber.yield 20; raise } + fiber2.resume.should == 10 + fiber2.resume.should == 20 + end + + it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do + root_fiber = Fiber.current + fiber1 = Fiber.new { root_fiber.resume } + -> { fiber1.resume }.should raise_error(FiberError, /attempt to resume a resuming fiber/) + end end end diff --git a/ruby/spec/ruby/library/fiber/transfer_spec.rb b/ruby/spec/ruby/library/fiber/transfer_spec.rb index d13053666..7af548da1 100644 --- a/ruby/spec/ruby/library/fiber/transfer_spec.rb +++ b/ruby/spec/ruby/library/fiber/transfer_spec.rb @@ -11,7 +11,13 @@ it "transfers control from one Fiber to another when called from a Fiber" do fiber1 = Fiber.new { :fiber1 } fiber2 = Fiber.new { fiber1.transfer; :fiber2 } - fiber2.resume.should == :fiber1 + + ruby_version_is '' ... '3.0' do + fiber2.resume.should == :fiber1 + end + ruby_version_is '3.0' do + fiber2.resume.should == :fiber2 + end end it "returns to the root Fiber when finished" do @@ -34,12 +40,24 @@ states.should == [:start, :end] end - it "can transfer control to a Fiber that has transferred to another Fiber" do - states = [] - fiber1 = Fiber.new { states << :fiber1 } - fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end} - fiber2.resume.should == [:fiber2_start, :fiber1] - fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end] + ruby_version_is '' ... '3.0' do + it "can transfer control to a Fiber that has transferred to another Fiber" do + states = [] + fiber1 = Fiber.new { states << :fiber1 } + fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end} + fiber2.resume.should == [:fiber2_start, :fiber1] + fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end] + end + end + + ruby_version_is '3.0' do + it "can not transfer control to a Fiber that has suspended by Fiber.yield" do + states = [] + fiber1 = Fiber.new { states << :fiber1 } + fiber2 = Fiber.new { states << :fiber2_start; Fiber.yield fiber1.transfer; states << :fiber2_end} + fiber2.resume.should == [:fiber2_start, :fiber1] + -> { fiber2.transfer }.should raise_error(FiberError) + end end it "raises a FiberError when transferring to a Fiber which resumes itself" do @@ -83,4 +101,28 @@ thread.join states.should == [0, 1, 2, 3] end + + ruby_version_is "" ... "3.0" do + it "runs until Fiber.yield" do + obj = mock('obj') + obj.should_not_receive(:do) + fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do } + fiber.transfer + end + + it "resumes from the last call to Fiber.yield on subsequent invocations" do + fiber = Fiber.new { Fiber.yield :first; :second } + fiber.transfer.should == :first + fiber.transfer.should == :second + end + + it "sets the block parameters to its arguments on the first invocation" do + first = mock('first') + first.should_receive(:arg).with(:first).twice + + fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; } + fiber.transfer :first + fiber.transfer :second + end + end end diff --git a/ruby/spec/ruby/library/getoptlong/shared/get.rb b/ruby/spec/ruby/library/getoptlong/shared/get.rb index 772a7f677..f44cf583d 100644 --- a/ruby/spec/ruby/library/getoptlong/shared/get.rb +++ b/ruby/spec/ruby/library/getoptlong/shared/get.rb @@ -53,12 +53,10 @@ end end - ruby_version_is "2.5" do - # https://bugs.ruby-lang.org/issues/13858 - it "returns multiline argument" do - argv [ "--size=\n10k\n" ] do - @opts.send(@method).should == [ "--size", "\n10k\n" ] - end + # https://bugs.ruby-lang.org/issues/13858 + it "returns multiline argument" do + argv [ "--size=\n10k\n" ] do + @opts.send(@method).should == [ "--size", "\n10k\n" ] end end end diff --git a/ruby/spec/ruby/library/getoptlong/terminated_spec.rb b/ruby/spec/ruby/library/getoptlong/terminated_spec.rb index 01a8fedde..6108a7f6e 100644 --- a/ruby/spec/ruby/library/getoptlong/terminated_spec.rb +++ b/ruby/spec/ruby/library/getoptlong/terminated_spec.rb @@ -5,13 +5,13 @@ it "returns true if option processing has terminated" do argv [ "--size", "10k" ] do opts = GetoptLong.new(["--size", GetoptLong::REQUIRED_ARGUMENT]) - opts.terminated?.should == false + opts.should_not.terminated? opts.get.should == ["--size", "10k"] - opts.terminated?.should == false + opts.should_not.terminated? opts.get.should == nil - opts.terminated?.should == true + opts.should.terminated? end end end diff --git a/ruby/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb b/ruby/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb index 9d45055d7..1128c16dd 100644 --- a/ruby/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb +++ b/ruby/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb @@ -8,11 +8,11 @@ a.to_s.should == "::192.168.1.2" a.to_string.should == "0000:0000:0000:0000:0000:0000:c0a8:0102" a.family.should == Socket::AF_INET6 - a.ipv4_compat?.should == true + a.should.ipv4_compat? b = a.native b.to_s.should == "192.168.1.2" b.family.should == Socket::AF_INET - b.ipv4_compat?.should == false + b.should_not.ipv4_compat? a = IPAddr.new("192.168.1.2") b = a.ipv4_compat @@ -29,11 +29,11 @@ a.to_s.should == "::ffff:192.168.1.2" a.to_string.should == "0000:0000:0000:0000:0000:ffff:c0a8:0102" a.family.should == Socket::AF_INET6 - a.ipv4_mapped?.should == true + a.should.ipv4_mapped? b = a.native b.to_s.should == "192.168.1.2" b.family.should == Socket::AF_INET - b.ipv4_mapped?.should == false + b.should_not.ipv4_mapped? a = IPAddr.new("192.168.1.2") b = a.ipv4_mapped diff --git a/ruby/spec/ruby/library/ipaddr/new_spec.rb b/ruby/spec/ruby/library/ipaddr/new_spec.rb index c8c8bc80b..053928c3c 100644 --- a/ruby/spec/ruby/library/ipaddr/new_spec.rb +++ b/ruby/spec/ruby/library/ipaddr/new_spec.rb @@ -27,8 +27,8 @@ a.to_s.should == "3ffe:505:2::" a.to_string.should == "3ffe:0505:0002:0000:0000:0000:0000:0000" a.family.should == Socket::AF_INET6 - a.ipv4?.should == false - a.ipv6?.should == true + a.should_not.ipv4? + a.should.ipv6? a.inspect.should == "#" end @@ -51,8 +51,8 @@ a.to_s.should == "192.168.1.2" a.to_string.should == "192.168.1.2" a.family.should == Socket::AF_INET - a.ipv4?.should == true - a.ipv6?.should == false + a.should.ipv4? + a.should_not.ipv6? end it "initializes IPAddr ipv4 address with / subnet notation" do @@ -77,17 +77,34 @@ a.family.should == Socket::AF_INET6 end - it "raises on incorrect IPAddr strings" do - [ - ["fe80::1%fxp0"], - ["::1/255.255.255.0"], - [IPAddr.new("::1").to_i], - ["::ffff:192.168.1.2/120", Socket::AF_INET], - ["[192.168.1.2]/120"], - ].each { |args| - ->{ - IPAddr.new(*args) - }.should raise_error(ArgumentError) - } + ruby_version_is ""..."3.1" do + it "raises on incorrect IPAddr strings" do + [ + ["fe80::1%fxp0"], + ["::1/255.255.255.0"], + [IPAddr.new("::1").to_i], + ["::ffff:192.168.1.2/120", Socket::AF_INET], + ["[192.168.1.2]/120"], + ].each { |args| + ->{ + IPAddr.new(*args) + }.should raise_error(ArgumentError) + } + end + end + + ruby_version_is "3.1" do + it "raises on incorrect IPAddr strings" do + [ + ["::1/255.255.255.0"], + [IPAddr.new("::1").to_i], + ["::ffff:192.168.1.2/120", Socket::AF_INET], + ["[192.168.1.2]/120"], + ].each { |args| + ->{ + IPAddr.new(*args) + }.should raise_error(ArgumentError) + } + end end end diff --git a/ruby/spec/ruby/library/logger/logger/debug_spec.rb b/ruby/spec/ruby/library/logger/logger/debug_spec.rb index d92c33923..9375ab0cc 100644 --- a/ruby/spec/ruby/library/logger/logger/debug_spec.rb +++ b/ruby/spec/ruby/library/logger/logger/debug_spec.rb @@ -16,12 +16,12 @@ it "returns true if severity level allows debug messages" do @logger.level = Logger::DEBUG - @logger.debug?.should == true + @logger.should.debug? end it "returns false if severity level does not allow debug messages" do @logger.level = Logger::WARN - @logger.debug?.should == false + @logger.should_not.debug? end end diff --git a/ruby/spec/ruby/library/logger/logger/error_spec.rb b/ruby/spec/ruby/library/logger/logger/error_spec.rb index d5d0bd2d2..42f1dbd88 100644 --- a/ruby/spec/ruby/library/logger/logger/error_spec.rb +++ b/ruby/spec/ruby/library/logger/logger/error_spec.rb @@ -16,12 +16,12 @@ it "returns true if severity level allows printing errors" do @logger.level = Logger::INFO - @logger.error?.should == true + @logger.should.error? end it "returns false if severity level does not allow errors" do @logger.level = Logger::FATAL - @logger.error?.should == false + @logger.should_not.error? end end diff --git a/ruby/spec/ruby/library/logger/logger/fatal_spec.rb b/ruby/spec/ruby/library/logger/logger/fatal_spec.rb index 42d434131..f12fa3a89 100644 --- a/ruby/spec/ruby/library/logger/logger/fatal_spec.rb +++ b/ruby/spec/ruby/library/logger/logger/fatal_spec.rb @@ -16,12 +16,12 @@ it "returns true if severity level allows fatal messages" do @logger.level = Logger::FATAL - @logger.fatal?.should == true + @logger.should.fatal? end it "returns false if severity level does not allow fatal messages" do @logger.level = Logger::UNKNOWN - @logger.fatal?.should == false + @logger.should_not.fatal? end end diff --git a/ruby/spec/ruby/library/logger/logger/info_spec.rb b/ruby/spec/ruby/library/logger/logger/info_spec.rb index 21eacbbb3..eb5dca48d 100644 --- a/ruby/spec/ruby/library/logger/logger/info_spec.rb +++ b/ruby/spec/ruby/library/logger/logger/info_spec.rb @@ -16,12 +16,12 @@ it "returns true if severity level allows info messages" do @logger.level = Logger::INFO - @logger.info?.should == true + @logger.should.info? end it "returns false if severity level does not allow info messages" do @logger.level = Logger::FATAL - @logger.info?.should == false + @logger.should_not.info? end end diff --git a/ruby/spec/ruby/library/logger/logger/warn_spec.rb b/ruby/spec/ruby/library/logger/logger/warn_spec.rb index 6617b2b41..0bca34824 100644 --- a/ruby/spec/ruby/library/logger/logger/warn_spec.rb +++ b/ruby/spec/ruby/library/logger/logger/warn_spec.rb @@ -16,12 +16,12 @@ it "returns true if severity level allows printing warn messages" do @logger.level = Logger::WARN - @logger.warn?.should == true + @logger.should.warn? end it "returns false if severity level does not allow printing warn messages" do @logger.level = Logger::FATAL - @logger.warn?.should == false + @logger.should_not.warn? end end diff --git a/ruby/spec/ruby/library/mathn/bignum/exponent_spec.rb b/ruby/spec/ruby/library/mathn/bignum/exponent_spec.rb deleted file mode 100644 index ddd19ffdb..000000000 --- a/ruby/spec/ruby/library/mathn/bignum/exponent_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Bignum#**" do - before :each do - @bignum = bignum_value(47) - end - - it "returns self raised to other (positive) power" do - (@bignum ** 4).should == 7237005577332262361485077344629993318496048279512298547155833600056910050625 - (@bignum ** 1.2).should be_close(57262152889751597425762.57804, TOLERANCE) - end - - it "returns a complex number when negative and raised to a fractional power" do - ((-@bignum) ** (1/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE) - ((-@bignum) ** (1.0/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/complex/Complex_spec.rb b/ruby/spec/ruby/library/mathn/complex/Complex_spec.rb deleted file mode 100644 index 105902ed5..000000000 --- a/ruby/spec/ruby/library/mathn/complex/Complex_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Kernel#Complex" do - it "returns an Integer if imaginary part is 0" do - Complex(42,0).should == 42 - Complex(42,0).should be_kind_of(Fixnum) - Complex(bignum_value,0).should == bignum_value - Complex(bignum_value,0).should be_kind_of(Bignum) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/fixnum/exponent_spec.rb b/ruby/spec/ruby/library/mathn/fixnum/exponent_spec.rb deleted file mode 100644 index 160bf7f11..000000000 --- a/ruby/spec/ruby/library/mathn/fixnum/exponent_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Fixnum#**" do - it "returns self raised to other (positive) power" do - (2 ** 4).should == 16 - (2 ** 1.2).should be_close(2.2973967, TOLERANCE) - end - - it "returns a complex number when negative and raised to a fractional power" do - ((-8) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE) - ((-8) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/float/exponent_spec.rb b/ruby/spec/ruby/library/mathn/float/exponent_spec.rb deleted file mode 100644 index 312119db0..000000000 --- a/ruby/spec/ruby/library/mathn/float/exponent_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Float#**" do - it "returns self raised to other (positive) power" do - (2.0 ** 4).should == 16.0 - (2.0 ** 1.2).should be_close(2.2973967, TOLERANCE) - end - - it "returns a complex number when negative and raised to a fractional power" do - ((-8.0) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE) - ((-8.0) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/integer/from_prime_division_spec.rb b/ruby/spec/ruby/library/mathn/integer/from_prime_division_spec.rb deleted file mode 100644 index df2db6d8c..000000000 --- a/ruby/spec/ruby/library/mathn/integer/from_prime_division_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Integer.from_prime_division" do - it "reverses a prime factorization of an integer" do - Integer.from_prime_division([[2, 1], [3, 2], [7, 1]]).should == 126 - end - end -end diff --git a/ruby/spec/ruby/library/mathn/integer/prime_division_spec.rb b/ruby/spec/ruby/library/mathn/integer/prime_division_spec.rb deleted file mode 100644 index fb4a1c3fe..000000000 --- a/ruby/spec/ruby/library/mathn/integer/prime_division_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Integer#prime_division" do - it "performs a prime factorization of a positive integer" do - 100.prime_division.should == [[2, 2], [5, 2]] - end - - # Proper handling of negative integers has been added to MRI trunk - # in revision 24091. Prior to that, all versions of MRI returned nonsense. - it "performs a prime factorization of a negative integer" do - -26.prime_division.should == [[-1, 1], [2, 1], [13, 1]] - end - - it "raises a ZeroDivisionError when is called on zero" do - -> { 0.prime_division }.should raise_error(ZeroDivisionError) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/math/fixtures/classes.rb b/ruby/spec/ruby/library/mathn/math/fixtures/classes.rb deleted file mode 100644 index 024732fa7..000000000 --- a/ruby/spec/ruby/library/mathn/math/fixtures/classes.rb +++ /dev/null @@ -1,3 +0,0 @@ -class IncludesMath - include Math -end diff --git a/ruby/spec/ruby/library/mathn/math/rsqrt_spec.rb b/ruby/spec/ruby/library/mathn/math/rsqrt_spec.rb deleted file mode 100644 index 6cb7595af..000000000 --- a/ruby/spec/ruby/library/mathn/math/rsqrt_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require_relative 'shared/rsqrt' - - describe "Math#rsqrt" do - it_behaves_like :mathn_math_rsqrt, :_, IncludesMath.new - - it "is a private instance method" do - IncludesMath.should have_private_instance_method(:rsqrt) - end - end - - describe "Math.rsqrt" do - it_behaves_like :mathn_math_rsqrt, :_, Math - end -end diff --git a/ruby/spec/ruby/library/mathn/math/shared/rsqrt.rb b/ruby/spec/ruby/library/mathn/math/shared/rsqrt.rb deleted file mode 100644 index ea3d1b0cf..000000000 --- a/ruby/spec/ruby/library/mathn/math/shared/rsqrt.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'mathn' -require_relative '../fixtures/classes' - -describe :mathn_math_rsqrt, shared: true do - it "returns the square root for Rational numbers" do - @object.send(:rsqrt, Rational(9, 25)).should == Rational(3, 5) - @object.send(:rsqrt, 16/64).should == Rational(1, 2) - end - - it "returns the square root for positive numbers" do - @object.send(:rsqrt, 1).should == 1 - @object.send(:rsqrt, 4.0).should == 2.0 - @object.send(:rsqrt, 12.34).should == Math.sqrt!(12.34) - end - - it "raises an Math::DomainError if the argument is a negative number" do - -> { @object.send(:rsqrt, -1) }.should raise_error(Math::DomainError) - -> { @object.send(:rsqrt, -4.0) }.should raise_error(Math::DomainError) - -> { @object.send(:rsqrt, -16/64) }.should raise_error(Math::DomainError) - end -end diff --git a/ruby/spec/ruby/library/mathn/math/shared/sqrt.rb b/ruby/spec/ruby/library/mathn/math/shared/sqrt.rb deleted file mode 100644 index 5e6dae1d4..000000000 --- a/ruby/spec/ruby/library/mathn/math/shared/sqrt.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'mathn' -require_relative '../fixtures/classes' - -describe :mathn_math_sqrt, shared: true do - it "returns the square root for Rational numbers" do - @object.send(:sqrt, Rational(9, 25)).should == Rational(3, 5) - @object.send(:sqrt, 16/64).should == Rational(1, 2) - end - - it "returns the square root for Complex numbers" do - @object.send(:sqrt, Complex(1, 0)).should == 1 - end - - it "returns the square root for positive numbers" do - @object.send(:sqrt, 1).should == 1 - @object.send(:sqrt, 4.0).should == 2.0 - @object.send(:sqrt, 12.34).should == Math.sqrt!(12.34) - end - - it "returns the square root for negative numbers" do - @object.send(:sqrt, -9).should == Complex(0, 3) - @object.send(:sqrt, -5.29).should == Complex(0, 2.3) - @object.send(:sqrt, -16/64).should == Complex(0, 1/2) - end -end diff --git a/ruby/spec/ruby/library/mathn/math/sqrt_spec.rb b/ruby/spec/ruby/library/mathn/math/sqrt_spec.rb deleted file mode 100644 index 49cfe3600..000000000 --- a/ruby/spec/ruby/library/mathn/math/sqrt_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require_relative 'shared/sqrt' - - describe "Math#rsqrt" do - it_behaves_like :mathn_math_sqrt, :_, IncludesMath.new - - it "is a private instance method" do - IncludesMath.should have_private_instance_method(:sqrt) - end - end - - describe "Math.rsqrt" do - it_behaves_like :mathn_math_sqrt, :_, Math - end -end diff --git a/ruby/spec/ruby/library/mathn/mathn_spec.rb b/ruby/spec/ruby/library/mathn/mathn_spec.rb deleted file mode 100644 index 129c8f328..000000000 --- a/ruby/spec/ruby/library/mathn/mathn_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require_relative '../../spec_helper' - -describe "mathn" do - ruby_version_is "2.5" do - it "is no longer part of the standard library" do - -> { - require "mathn" - }.should raise_error(LoadError) { |e| - e.path.should == 'mathn' - } - end - end -end diff --git a/ruby/spec/ruby/library/mathn/rational/Rational_spec.rb b/ruby/spec/ruby/library/mathn/rational/Rational_spec.rb deleted file mode 100644 index 9a34c9975..000000000 --- a/ruby/spec/ruby/library/mathn/rational/Rational_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Kernel#Rational" do - it "returns an Integer if denominator divides numerator evenly" do - Rational(42,6).should == 7 - Rational(42,6).should be_kind_of(Fixnum) - Rational(bignum_value,1).should == bignum_value - Rational(bignum_value,1).should be_kind_of(Bignum) - end - end -end diff --git a/ruby/spec/ruby/library/mathn/rational/inspect_spec.rb b/ruby/spec/ruby/library/mathn/rational/inspect_spec.rb deleted file mode 100644 index cbf67ec0f..000000000 --- a/ruby/spec/ruby/library/mathn/rational/inspect_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative '../../../spec_helper' - -ruby_version_is ''...'2.5' do - require 'mathn' - - describe "Rational#inspect" do - it "returns a string representation of self" do - Rational(3, 4).inspect.should == "(3/4)" - Rational(-5, 8).inspect.should == "(-5/8)" - Rational(-1, -2).inspect.should == "(1/2)" - Rational(0, 2).inspect.should == "0" - Rational(bignum_value, 1).inspect.should == "#{bignum_value}" - end - end -end diff --git a/ruby/spec/ruby/library/matrix/I_spec.rb b/ruby/spec/ruby/library/matrix/I_spec.rb index 6eeffe8e9..aa064ed54 100644 --- a/ruby/spec/ruby/library/matrix/I_spec.rb +++ b/ruby/spec/ruby/library/matrix/I_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/identity' -describe "Matrix.I" do - it_behaves_like :matrix_identity, :I +ruby_version_is ""..."3.1" do + require_relative 'shared/identity' + + describe "Matrix.I" do + it_behaves_like :matrix_identity, :I + end end diff --git a/ruby/spec/ruby/library/matrix/antisymmetric_spec.rb b/ruby/spec/ruby/library/matrix/antisymmetric_spec.rb index 3eb0f8b72..dcc3c30f3 100644 --- a/ruby/spec/ruby/library/matrix/antisymmetric_spec.rb +++ b/ruby/spec/ruby/library/matrix/antisymmetric_spec.rb @@ -1,7 +1,8 @@ require_relative '../../spec_helper' -require 'matrix' -ruby_version_is "2.6" do +ruby_version_is ""..."3.1" do + require 'matrix' + describe "Matrix#antisymmetric?" do it "returns true for an antisymmetric Matrix" do Matrix[[0, -2, Complex(1, 3)], [2, 0, 5], [-Complex(1, 3), -5, 0]].antisymmetric?.should be_true diff --git a/ruby/spec/ruby/library/matrix/build_spec.rb b/ruby/spec/ruby/library/matrix/build_spec.rb index 6d8017a3d..d3055a1aa 100644 --- a/ruby/spec/ruby/library/matrix/build_spec.rb +++ b/ruby/spec/ruby/library/matrix/build_spec.rb @@ -1,73 +1,76 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.build" do +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a Matrix object of the given size" do - m = Matrix.build(3, 4){1} - m.should be_an_instance_of(Matrix) - m.row_size.should == 3 - m.column_size.should == 4 - end + describe "Matrix.build" do - it "builds the Matrix using the given block" do - Matrix.build(2, 3){|col, row| 10*col - row}.should == - Matrix[[0, -1, -2], [10, 9, 8]] - end + it "returns a Matrix object of the given size" do + m = Matrix.build(3, 4){1} + m.should be_an_instance_of(Matrix) + m.row_size.should == 3 + m.column_size.should == 4 + end - it "iterates through the first row, then the second, ..." do - acc = [] - Matrix.build(2, 3){|*args| acc << args} - acc.should == [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]] - end + it "builds the Matrix using the given block" do + Matrix.build(2, 3){|col, row| 10*col - row}.should == + Matrix[[0, -1, -2], [10, 9, 8]] + end - it "returns an Enumerator is no block is given" do - enum = Matrix.build(2, 1) - enum.should be_an_instance_of(Enumerator) - enum.each{1}.should == Matrix[[1], [1]] - end + it "iterates through the first row, then the second, ..." do + acc = [] + Matrix.build(2, 3){|*args| acc << args} + acc.should == [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]] + end - it "requires integers as parameters" do - -> { Matrix.build("1", "2"){1} }.should raise_error(TypeError) - -> { Matrix.build(nil, nil){1} }.should raise_error(TypeError) - -> { Matrix.build(1..2){1} }.should raise_error(TypeError) - end + it "returns an Enumerator is no block is given" do + enum = Matrix.build(2, 1) + enum.should be_an_instance_of(Enumerator) + enum.each{1}.should == Matrix[[1], [1]] + end - it "requires non-negative integers" do - -> { Matrix.build(-1, 1){1} }.should raise_error(ArgumentError) - -> { Matrix.build(+1,-1){1} }.should raise_error(ArgumentError) - end + it "requires integers as parameters" do + -> { Matrix.build("1", "2"){1} }.should raise_error(TypeError) + -> { Matrix.build(nil, nil){1} }.should raise_error(TypeError) + -> { Matrix.build(1..2){1} }.should raise_error(TypeError) + end - it "returns empty Matrix if one argument is zero" do - m = Matrix.build(0, 3){ - raise "Should not yield" - } - m.should be_empty - m.column_size.should == 3 + it "requires non-negative integers" do + -> { Matrix.build(-1, 1){1} }.should raise_error(ArgumentError) + -> { Matrix.build(+1,-1){1} }.should raise_error(ArgumentError) + end - m = Matrix.build(3, 0){ - raise "Should not yield" - } - m.should be_empty - m.row_size.should == 3 - end + it "returns empty Matrix if one argument is zero" do + m = Matrix.build(0, 3){ + raise "Should not yield" + } + m.should be_empty + m.column_size.should == 3 - it "tries to calls :to_int on arguments" do - int = mock('int') - int.should_receive(:to_int).twice.and_return(2) - Matrix.build(int, int){ 1 }.should == Matrix[ [1,1], [1,1] ] - end + m = Matrix.build(3, 0){ + raise "Should not yield" + } + m.should be_empty + m.row_size.should == 3 + end - it "builds an nxn Matrix when given only one argument" do - m = Matrix.build(3){1} - m.row_size.should == 3 - m.column_size.should == 3 + it "tries to calls :to_int on arguments" do + int = mock('int') + int.should_receive(:to_int).twice.and_return(2) + Matrix.build(int, int){ 1 }.should == Matrix[ [1,1], [1,1] ] + end + + it "builds an nxn Matrix when given only one argument" do + m = Matrix.build(3){1} + m.row_size.should == 3 + m.column_size.should == 3 + end end -end -describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.build(3){1}.should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.build(3){1}.should be_an_instance_of(MatrixSub) + end end end diff --git a/ruby/spec/ruby/library/matrix/clone_spec.rb b/ruby/spec/ruby/library/matrix/clone_spec.rb index 74e5bf157..bde119988 100644 --- a/ruby/spec/ruby/library/matrix/clone_spec.rb +++ b/ruby/spec/ruby/library/matrix/clone_spec.rb @@ -1,25 +1,28 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#clone" do - before :each do - @a = Matrix[[1, 2], [3, 4], [5, 6]] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a shallow copy of the matrix" do - b = @a.clone - @a.should_not equal(b) - b.should be_kind_of(Matrix) - b.should == @a - 0.upto(@a.row_size - 1) do |i| - @a.row(i).should_not equal(b.row(i)) + describe "Matrix#clone" do + before :each do + @a = Matrix[[1, 2], [3, 4], [5, 6]] + end + + it "returns a shallow copy of the matrix" do + b = @a.clone + @a.should_not equal(b) + b.should be_kind_of(Matrix) + b.should == @a + 0.upto(@a.row_size - 1) do |i| + @a.row(i).should_not equal(b.row(i)) + end end - end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.ins.clone.should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.ins.clone.should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/coerce_spec.rb b/ruby/spec/ruby/library/matrix/coerce_spec.rb index 280243d37..aa3a32765 100644 --- a/ruby/spec/ruby/library/matrix/coerce_spec.rb +++ b/ruby/spec/ruby/library/matrix/coerce_spec.rb @@ -1,8 +1,11 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#coerce" do - it "allows the division of fixnum by a Matrix " do - (1/Matrix[[0,1],[-1,0]]).should == Matrix[[0,-1],[1,0]] +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix#coerce" do + it "allows the division of integer by a Matrix " do + (1/Matrix[[0,1],[-1,0]]).should == Matrix[[0,-1],[1,0]] + end end end diff --git a/ruby/spec/ruby/library/matrix/collect_spec.rb b/ruby/spec/ruby/library/matrix/collect_spec.rb index bba640213..66ec3486c 100644 --- a/ruby/spec/ruby/library/matrix/collect_spec.rb +++ b/ruby/spec/ruby/library/matrix/collect_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/collect' -describe "Matrix#collect" do - it_behaves_like :collect, :collect +ruby_version_is ""..."3.1" do + require_relative 'shared/collect' + + describe "Matrix#collect" do + it_behaves_like :collect, :collect + end end diff --git a/ruby/spec/ruby/library/matrix/column_size_spec.rb b/ruby/spec/ruby/library/matrix/column_size_spec.rb index 041914e5b..e7b42b101 100644 --- a/ruby/spec/ruby/library/matrix/column_size_spec.rb +++ b/ruby/spec/ruby/library/matrix/column_size_spec.rb @@ -1,13 +1,16 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#column_size" do - it "returns the number of columns" do - Matrix[ [1,2], [3,4] ].column_size.should == 2 - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix#column_size" do + it "returns the number of columns" do + Matrix[ [1,2], [3,4] ].column_size.should == 2 + end - it "returns 0 for empty matrices" do - Matrix[ [], [] ].column_size.should == 0 - Matrix[ ].column_size.should == 0 + it "returns 0 for empty matrices" do + Matrix[ [], [] ].column_size.should == 0 + Matrix[ ].column_size.should == 0 + end end end diff --git a/ruby/spec/ruby/library/matrix/column_spec.rb b/ruby/spec/ruby/library/matrix/column_spec.rb index 1f3c80964..98a767ad0 100644 --- a/ruby/spec/ruby/library/matrix/column_spec.rb +++ b/ruby/spec/ruby/library/matrix/column_spec.rb @@ -1,35 +1,38 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#column" do - before :all do - @m = Matrix[[1,2,3], [2,3,4]] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns a Vector when called without a block" do - @m.column(1).should == Vector[2,3] - end + describe "Matrix#column" do + before :all do + @m = Matrix[[1,2,3], [2,3,4]] + end - it "yields each element in the column to the block" do - a = [] - @m.column(1) {|n| a << n } - a.should == [2,3] - end + it "returns a Vector when called without a block" do + @m.column(1).should == Vector[2,3] + end - it "counts backwards for negative argument" do - @m.column(-1).should == Vector[3, 4] - end + it "yields each element in the column to the block" do + a = [] + @m.column(1) {|n| a << n } + a.should == [2,3] + end - it "returns self when called with a block" do - @m.column(0) { |x| x }.should equal(@m) - end + it "counts backwards for negative argument" do + @m.column(-1).should == Vector[3, 4] + end - it "returns nil when out of bounds" do - @m.column(3).should == nil - end + it "returns self when called with a block" do + @m.column(0) { |x| x }.should equal(@m) + end + + it "returns nil when out of bounds" do + @m.column(3).should == nil + end - it "never yields when out of bounds" do - -> { @m.column(3){ raise } }.should_not raise_error - -> { @m.column(-4){ raise } }.should_not raise_error + it "never yields when out of bounds" do + -> { @m.column(3){ raise } }.should_not raise_error + -> { @m.column(-4){ raise } }.should_not raise_error + end end end diff --git a/ruby/spec/ruby/library/matrix/column_vector_spec.rb b/ruby/spec/ruby/library/matrix/column_vector_spec.rb index 47e866a8d..afdeaced4 100644 --- a/ruby/spec/ruby/library/matrix/column_vector_spec.rb +++ b/ruby/spec/ruby/library/matrix/column_vector_spec.rb @@ -1,25 +1,28 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.column_vector" do +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a single column Matrix when called with an Array" do - m = Matrix.column_vector([4,5,6]) - m.should be_an_instance_of(Matrix) - m.should == Matrix[ [4],[5],[6] ] - end + describe "Matrix.column_vector" do - it "returns an empty Matrix when called with an empty Array" do - m = Matrix.column_vector([]) - m.should be_an_instance_of(Matrix) - m.row_size.should == 0 - m.column_size.should == 1 - end + it "returns a single column Matrix when called with an Array" do + m = Matrix.column_vector([4,5,6]) + m.should be_an_instance_of(Matrix) + m.should == Matrix[ [4],[5],[6] ] + end + + it "returns an empty Matrix when called with an empty Array" do + m = Matrix.column_vector([]) + m.should be_an_instance_of(Matrix) + m.row_size.should == 0 + m.column_size.should == 1 + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.column_vector([4,5,6]).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.column_vector([4,5,6]).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/column_vectors_spec.rb b/ruby/spec/ruby/library/matrix/column_vectors_spec.rb index b0cb6f914..7bec095b9 100644 --- a/ruby/spec/ruby/library/matrix/column_vectors_spec.rb +++ b/ruby/spec/ruby/library/matrix/column_vectors_spec.rb @@ -1,26 +1,29 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#column_vectors" do +ruby_version_is ""..."3.1" do + require 'matrix' - before :each do - @vectors = Matrix[ [1,2], [3,4] ].column_vectors - end + describe "Matrix#column_vectors" do - it "returns an Array" do - Matrix[ [1,2], [3,4] ].column_vectors.should be_an_instance_of(Array) - end + before :each do + @vectors = Matrix[ [1,2], [3,4] ].column_vectors + end - it "returns an Array of Vectors" do - @vectors.all? {|v| v.should be_an_instance_of(Vector)} - end + it "returns an Array" do + Matrix[ [1,2], [3,4] ].column_vectors.should be_an_instance_of(Array) + end - it "returns each column as a Vector" do - @vectors.should == [Vector[1,3], Vector[2,4]] - end + it "returns an Array of Vectors" do + @vectors.all? {|v| v.should be_an_instance_of(Vector)} + end - it "returns an empty Array for empty matrices" do - Matrix[ [] ].column_vectors.should == [] - end + it "returns each column as a Vector" do + @vectors.should == [Vector[1,3], Vector[2,4]] + end + + it "returns an empty Array for empty matrices" do + Matrix[ [] ].column_vectors.should == [] + end + end end diff --git a/ruby/spec/ruby/library/matrix/columns_spec.rb b/ruby/spec/ruby/library/matrix/columns_spec.rb index 3095fdd7a..757086c14 100644 --- a/ruby/spec/ruby/library/matrix/columns_spec.rb +++ b/ruby/spec/ruby/library/matrix/columns_spec.rb @@ -1,42 +1,45 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.columns" do - before :each do - @a = [1, 2] - @b = [3, 4] - @m = Matrix.columns([@a, @b]) - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "creates a Matrix from argument columns" do - @m.should be_an_instance_of(Matrix) - @m.column(0).to_a.should == @a - @m.column(1).to_a.should == @b - end + describe "Matrix.columns" do + before :each do + @a = [1, 2] + @b = [3, 4] + @m = Matrix.columns([@a, @b]) + end - it "accepts Vectors as argument columns" do - m = Matrix.columns([Vector[*@a], Vector[*@b]]) - m.should == @m - m.column(0).to_a.should == @a - m.column(1).to_a.should == @b - end + it "creates a Matrix from argument columns" do + @m.should be_an_instance_of(Matrix) + @m.column(0).to_a.should == @a + @m.column(1).to_a.should == @b + end - it "handles empty matrices" do - e = Matrix.columns([]) - e.row_size.should == 0 - e.column_size.should == 0 - e.should == Matrix[] + it "accepts Vectors as argument columns" do + m = Matrix.columns([Vector[*@a], Vector[*@b]]) + m.should == @m + m.column(0).to_a.should == @a + m.column(1).to_a.should == @b + end - v = Matrix.columns([[],[],[]]) - v.row_size.should == 0 - v.column_size.should == 3 - v.should == Matrix[[], [], []].transpose - end + it "handles empty matrices" do + e = Matrix.columns([]) + e.row_size.should == 0 + e.column_size.should == 0 + e.should == Matrix[] + + v = Matrix.columns([[],[],[]]) + v.row_size.should == 0 + v.column_size.should == 3 + v.should == Matrix[[], [], []].transpose + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.columns([[1]]).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.columns([[1]]).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/conj_spec.rb b/ruby/spec/ruby/library/matrix/conj_spec.rb index ecee95c25..a92258039 100644 --- a/ruby/spec/ruby/library/matrix/conj_spec.rb +++ b/ruby/spec/ruby/library/matrix/conj_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/conjugate' -describe "Matrix#conj" do - it_behaves_like :matrix_conjugate, :conj +ruby_version_is ""..."3.1" do + require_relative 'shared/conjugate' + + describe "Matrix#conj" do + it_behaves_like :matrix_conjugate, :conj + end end diff --git a/ruby/spec/ruby/library/matrix/conjugate_spec.rb b/ruby/spec/ruby/library/matrix/conjugate_spec.rb index 682bd41d9..b99792a24 100644 --- a/ruby/spec/ruby/library/matrix/conjugate_spec.rb +++ b/ruby/spec/ruby/library/matrix/conjugate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/conjugate' -describe "Matrix#conjugate" do - it_behaves_like :matrix_conjugate, :conjugate +ruby_version_is ""..."3.1" do + require_relative 'shared/conjugate' + + describe "Matrix#conjugate" do + it_behaves_like :matrix_conjugate, :conjugate + end end diff --git a/ruby/spec/ruby/library/matrix/constructor_spec.rb b/ruby/spec/ruby/library/matrix/constructor_spec.rb index 70d77babb..d8224b443 100644 --- a/ruby/spec/ruby/library/matrix/constructor_spec.rb +++ b/ruby/spec/ruby/library/matrix/constructor_spec.rb @@ -1,65 +1,68 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.[]" do +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "requires arrays as parameters" do - -> { Matrix[5] }.should raise_error(TypeError) - -> { Matrix[nil] }.should raise_error(TypeError) - -> { Matrix[1..2] }.should raise_error(TypeError) - -> { Matrix[[1, 2], 3] }.should raise_error(TypeError) - end + describe "Matrix.[]" do - it "creates an empty Matrix with no arguments" do - m = Matrix[] - m.column_size.should == 0 - m.row_size.should == 0 - end + it "requires arrays as parameters" do + -> { Matrix[5] }.should raise_error(TypeError) + -> { Matrix[nil] }.should raise_error(TypeError) + -> { Matrix[1..2] }.should raise_error(TypeError) + -> { Matrix[[1, 2], 3] }.should raise_error(TypeError) + end - it "raises for non-rectangular matrices" do - ->{ Matrix[ [0], [0,1] ] }.should \ - raise_error(Matrix::ErrDimensionMismatch) - ->{ Matrix[ [0,1], [0,1,2], [0,1] ]}.should \ - raise_error(Matrix::ErrDimensionMismatch) - end + it "creates an empty Matrix with no arguments" do + m = Matrix[] + m.column_size.should == 0 + m.row_size.should == 0 + end - it "accepts vector arguments" do - a = Matrix[Vector[1, 2], Vector[3, 4]] - a.should be_an_instance_of(Matrix) - a.should == Matrix[ [1, 2], [3, 4] ] - end + it "raises for non-rectangular matrices" do + ->{ Matrix[ [0], [0,1] ] }.should \ + raise_error(Matrix::ErrDimensionMismatch) + ->{ Matrix[ [0,1], [0,1,2], [0,1] ]}.should \ + raise_error(Matrix::ErrDimensionMismatch) + end - it "tries to calls :to_ary on arguments" do - array = mock('ary') - array.should_receive(:to_ary).and_return([1,2]) - Matrix[array, [3,4] ].should == Matrix[ [1,2], [3,4] ] - end + it "accepts vector arguments" do + a = Matrix[Vector[1, 2], Vector[3, 4]] + a.should be_an_instance_of(Matrix) + a.should == Matrix[ [1, 2], [3, 4] ] + end + it "tries to calls :to_ary on arguments" do + array = mock('ary') + array.should_receive(:to_ary).and_return([1,2]) + Matrix[array, [3,4] ].should == Matrix[ [1,2], [3,4] ] + end - it "returns a Matrix object" do - Matrix[ [1] ].should be_an_instance_of(Matrix) - end - it "can create an nxn Matrix" do - m = Matrix[ [20,30], [40.5, 9] ] - m.row_size.should == 2 - m.column_size.should == 2 - m.column(0).should == Vector[20, 40.5] - m.column(1).should == Vector[30, 9] - m.row(0).should == Vector[20, 30] - m.row(1).should == Vector[40.5, 9] - end + it "returns a Matrix object" do + Matrix[ [1] ].should be_an_instance_of(Matrix) + end - it "can create a 0xn Matrix" do - m = Matrix[ [], [], [] ] - m.row_size.should == 3 - m.column_size.should == 0 - end + it "can create an nxn Matrix" do + m = Matrix[ [20,30], [40.5, 9] ] + m.row_size.should == 2 + m.column_size.should == 2 + m.column(0).should == Vector[20, 40.5] + m.column(1).should == Vector[30, 9] + m.row(0).should == Vector[20, 30] + m.row(1).should == Vector[40.5, 9] + end + + it "can create a 0xn Matrix" do + m = Matrix[ [], [], [] ] + m.row_size.should == 3 + m.column_size.should == 0 + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub[ [20,30], [40.5, 9] ].should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub[ [20,30], [40.5, 9] ].should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/det_spec.rb b/ruby/spec/ruby/library/matrix/det_spec.rb index aa7086cac..7d3d54773 100644 --- a/ruby/spec/ruby/library/matrix/det_spec.rb +++ b/ruby/spec/ruby/library/matrix/det_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/determinant' -require 'matrix' -describe "Matrix#det" do - it_behaves_like :determinant, :det +ruby_version_is ""..."3.1" do + require_relative 'shared/determinant' + require 'matrix' + + describe "Matrix#det" do + it_behaves_like :determinant, :det + end end diff --git a/ruby/spec/ruby/library/matrix/determinant_spec.rb b/ruby/spec/ruby/library/matrix/determinant_spec.rb index 825c9907b..bfd91fcf6 100644 --- a/ruby/spec/ruby/library/matrix/determinant_spec.rb +++ b/ruby/spec/ruby/library/matrix/determinant_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/determinant' -require 'matrix' -describe "Matrix#determinant" do - it_behaves_like :determinant, :determinant +ruby_version_is ""..."3.1" do + require_relative 'shared/determinant' + require 'matrix' + + describe "Matrix#determinant" do + it_behaves_like :determinant, :determinant + end end diff --git a/ruby/spec/ruby/library/matrix/diagonal_spec.rb b/ruby/spec/ruby/library/matrix/diagonal_spec.rb index ef9738e73..8c82433fd 100644 --- a/ruby/spec/ruby/library/matrix/diagonal_spec.rb +++ b/ruby/spec/ruby/library/matrix/diagonal_spec.rb @@ -1,72 +1,75 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.diagonal" do - before :each do - @m = Matrix.diagonal(10, 11, 12, 13, 14) - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns an object of type Matrix" do - @m.should be_kind_of(Matrix) - end + describe "Matrix.diagonal" do + before :each do + @m = Matrix.diagonal(10, 11, 12, 13, 14) + end - it "returns a square Matrix of the right size" do - @m.column_size.should == 5 - @m.row_size.should == 5 - end + it "returns an object of type Matrix" do + @m.should be_kind_of(Matrix) + end - it "sets the diagonal to the arguments" do - (0..4).each do |i| - @m[i, i].should == i + 10 + it "returns a square Matrix of the right size" do + @m.column_size.should == 5 + @m.row_size.should == 5 end - end - it "fills all non-diagonal cells with 0" do - (0..4).each do |i| - (0..4).each do |j| - if i != j - @m[i, j].should == 0 + it "sets the diagonal to the arguments" do + (0..4).each do |i| + @m[i, i].should == i + 10 + end + end + + it "fills all non-diagonal cells with 0" do + (0..4).each do |i| + (0..4).each do |j| + if i != j + @m[i, j].should == 0 + end end end end - end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.diagonal(1).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.diagonal(1).should be_an_instance_of(MatrixSub) + end end end -end -describe "Matrix.diagonal?" do - it "returns true for a diagonal Matrix" do - Matrix.diagonal([1, 2, 3]).diagonal?.should be_true - end + describe "Matrix.diagonal?" do + it "returns true for a diagonal Matrix" do + Matrix.diagonal([1, 2, 3]).diagonal?.should be_true + end - it "returns true for a zero square Matrix" do - Matrix.zero(3).diagonal?.should be_true - end + it "returns true for a zero square Matrix" do + Matrix.zero(3).diagonal?.should be_true + end - it "returns false for a non diagonal square Matrix" do - Matrix[[0, 1], [0, 0]].diagonal?.should be_false - Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].diagonal?.should be_false - end + it "returns false for a non diagonal square Matrix" do + Matrix[[0, 1], [0, 0]].diagonal?.should be_false + Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].diagonal?.should be_false + end - it "returns true for an empty 0x0 matrix" do - Matrix.empty(0,0).diagonal?.should be_true - end + it "returns true for an empty 0x0 matrix" do + Matrix.empty(0,0).diagonal?.should be_true + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.diagonal? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.diagonal? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/divide_spec.rb b/ruby/spec/ruby/library/matrix/divide_spec.rb index 2e3bb85bf..68e6f1fde 100644 --- a/ruby/spec/ruby/library/matrix/divide_spec.rb +++ b/ruby/spec/ruby/library/matrix/divide_spec.rb @@ -1,54 +1,57 @@ require_relative '../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/classes' -require 'matrix' - -describe "Matrix#/" do - before :each do - @a = Matrix[ [1, 2], [3, 4] ] - @b = Matrix[ [4, 5], [6, 7] ] - @c = Matrix[ [1.2, 2.4], [3.6, 4.8] ] - end - it "returns the result of dividing self by another Matrix" do - (@a / @b).should be_close_to_matrix([[2.5, -1.5], [1.5, -0.5]]) - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/classes' + require 'matrix' - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - it "returns the result of dividing self by a Fixnum" do - (@a / 2).should == Matrix[ [0, 1], [1, 2] ] + describe "Matrix#/" do + before :each do + @a = Matrix[ [1, 2], [3, 4] ] + @b = Matrix[ [4, 5], [6, 7] ] + @c = Matrix[ [1.2, 2.4], [3.6, 4.8] ] end - it "returns the result of dividing self by a Bignum" do - (@a / bignum_value).should == Matrix[ [0, 0], [0, 0] ] + it "returns the result of dividing self by another Matrix" do + (@a / @b).should be_close_to_matrix([[2.5, -1.5], [1.5, -0.5]]) end - end - it "returns the result of dividing self by a Float" do - (@c / 1.2).should == Matrix[ [1, 2], [3, 4] ] - end + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + it "returns the result of dividing self by a Fixnum" do + (@a / 2).should == Matrix[ [0, 1], [1, 2] ] + end - it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do - -> { @a / Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "returns the result of dividing self by a Bignum" do + (@a / bignum_value).should == Matrix[ [0, 0], [0, 0] ] + end + end - it "returns an instance of Matrix" do - (@a / @b).should be_kind_of(Matrix) - end + it "returns the result of dividing self by a Float" do + (@c / 1.2).should == Matrix[ [1, 2], [3, 4] ] + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - m = MatrixSub.ins - (m/m).should be_an_instance_of(MatrixSub) - (m/1).should be_an_instance_of(MatrixSub) + it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do + -> { @a / Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) + end + + it "returns an instance of Matrix" do + (@a / @b).should be_kind_of(Matrix) end - end - it "raises a TypeError if other is of wrong type" do - -> { @a / nil }.should raise_error(TypeError) - -> { @a / "a" }.should raise_error(TypeError) - -> { @a / [ [1, 2] ] }.should raise_error(TypeError) - -> { @a / Object.new }.should raise_error(TypeError) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + m = MatrixSub.ins + (m/m).should be_an_instance_of(MatrixSub) + (m/1).should be_an_instance_of(MatrixSub) + end + end + + it "raises a TypeError if other is of wrong type" do + -> { @a / nil }.should raise_error(TypeError) + -> { @a / "a" }.should raise_error(TypeError) + -> { @a / [ [1, 2] ] }.should raise_error(TypeError) + -> { @a / Object.new }.should raise_error(TypeError) + end end end diff --git a/ruby/spec/ruby/library/matrix/each_spec.rb b/ruby/spec/ruby/library/matrix/each_spec.rb index f3b0f0186..d2b13c80b 100644 --- a/ruby/spec/ruby/library/matrix/each_spec.rb +++ b/ruby/spec/ruby/library/matrix/each_spec.rb @@ -1,74 +1,77 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#each" do - before :all do - @m = Matrix[ [1, 2, 3], [4, 5, 6] ] - @result = (1..6).to_a - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an Enumerator when called without a block" do - enum = @m.each - enum.should be_an_instance_of(Enumerator) - enum.to_a.should == @result - end + describe "Matrix#each" do + before :all do + @m = Matrix[ [1, 2, 3], [4, 5, 6] ] + @result = (1..6).to_a + end - it "returns self" do - @m.each{}.should equal(@m) - end + it "returns an Enumerator when called without a block" do + enum = @m.each + enum.should be_an_instance_of(Enumerator) + enum.to_a.should == @result + end - it "yields the elements starting with the those of the first row" do - a = [] - @m.each {|x| a << x} - a.should == @result - end -end + it "returns self" do + @m.each{}.should equal(@m) + end -describe "Matrix#each with an argument" do - before :all do - @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] - @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ] + it "yields the elements starting with the those of the first row" do + a = [] + @m.each {|x| a << x} + a.should == @result + end end - it "raises an ArgumentError for unrecognized argument" do - -> { - @m.each("all"){} - }.should raise_error(ArgumentError) - -> { - @m.each(nil){} - }.should raise_error(ArgumentError) - -> { - @m.each(:left){} - }.should raise_error(ArgumentError) - end + describe "Matrix#each with an argument" do + before :all do + @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] + @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ] + end - it "yields the rights elements when passed :diagonal" do - @m.each(:diagonal).to_a.should == [1, 6] - @t.each(:diagonal).to_a.should == [1, 4] - end + it "raises an ArgumentError for unrecognized argument" do + -> { + @m.each("all"){} + }.should raise_error(ArgumentError) + -> { + @m.each(nil){} + }.should raise_error(ArgumentError) + -> { + @m.each(:left){} + }.should raise_error(ArgumentError) + end - it "yields the rights elements when passed :off_diagonal" do - @m.each(:off_diagonal).to_a.should == [2, 3, 4, 5, 7, 8] - @t.each(:off_diagonal).to_a.should == [2, 3, 5, 6, 7, 8] - end + it "yields the rights elements when passed :diagonal" do + @m.each(:diagonal).to_a.should == [1, 6] + @t.each(:diagonal).to_a.should == [1, 4] + end - it "yields the rights elements when passed :lower" do - @m.each(:lower).to_a.should == [1, 5, 6] - @t.each(:lower).to_a.should == [1, 3, 4, 5, 6, 7, 8] - end + it "yields the rights elements when passed :off_diagonal" do + @m.each(:off_diagonal).to_a.should == [2, 3, 4, 5, 7, 8] + @t.each(:off_diagonal).to_a.should == [2, 3, 5, 6, 7, 8] + end - it "yields the rights elements when passed :strict_lower" do - @m.each(:strict_lower).to_a.should == [5] - @t.each(:strict_lower).to_a.should == [3, 5, 6, 7, 8] - end + it "yields the rights elements when passed :lower" do + @m.each(:lower).to_a.should == [1, 5, 6] + @t.each(:lower).to_a.should == [1, 3, 4, 5, 6, 7, 8] + end - it "yields the rights elements when passed :strict_upper" do - @m.each(:strict_upper).to_a.should == [2, 3, 4, 7, 8] - @t.each(:strict_upper).to_a.should == [2] - end + it "yields the rights elements when passed :strict_lower" do + @m.each(:strict_lower).to_a.should == [5] + @t.each(:strict_lower).to_a.should == [3, 5, 6, 7, 8] + end + + it "yields the rights elements when passed :strict_upper" do + @m.each(:strict_upper).to_a.should == [2, 3, 4, 7, 8] + @t.each(:strict_upper).to_a.should == [2] + end - it "yields the rights elements when passed :upper" do - @m.each(:upper).to_a.should == [1, 2, 3, 4, 6, 7, 8] - @t.each(:upper).to_a.should == [1, 2, 4] + it "yields the rights elements when passed :upper" do + @m.each(:upper).to_a.should == [1, 2, 3, 4, 6, 7, 8] + @t.each(:upper).to_a.should == [1, 2, 4] + end end end diff --git a/ruby/spec/ruby/library/matrix/each_with_index_spec.rb b/ruby/spec/ruby/library/matrix/each_with_index_spec.rb index a005b8862..59549f77b 100644 --- a/ruby/spec/ruby/library/matrix/each_with_index_spec.rb +++ b/ruby/spec/ruby/library/matrix/each_with_index_spec.rb @@ -1,81 +1,84 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#each_with_index" do - before :all do - @m = Matrix[ [1, 2, 3], [4, 5, 6] ] - @result = [ - [1, 0, 0], - [2, 0, 1], - [3, 0, 2], - [4, 1, 0], - [5, 1, 1], - [6, 1, 2] - ] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an Enumerator when called without a block" do - enum = @m.each_with_index - enum.should be_an_instance_of(Enumerator) - enum.to_a.should == @result - end + describe "Matrix#each_with_index" do + before :all do + @m = Matrix[ [1, 2, 3], [4, 5, 6] ] + @result = [ + [1, 0, 0], + [2, 0, 1], + [3, 0, 2], + [4, 1, 0], + [5, 1, 1], + [6, 1, 2] + ] + end - it "returns self" do - @m.each_with_index{}.should equal(@m) - end + it "returns an Enumerator when called without a block" do + enum = @m.each_with_index + enum.should be_an_instance_of(Enumerator) + enum.to_a.should == @result + end - it "yields the elements starting with the those of the first row" do - a = [] - @m.each_with_index {|x, r, c| a << [x, r, c]} - a.should == @result - end -end + it "returns self" do + @m.each_with_index{}.should equal(@m) + end -describe "Matrix#each_with_index with an argument" do - before :all do - @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] - @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ] + it "yields the elements starting with the those of the first row" do + a = [] + @m.each_with_index {|x, r, c| a << [x, r, c]} + a.should == @result + end end - it "raises an ArgumentError for unrecognized argument" do - -> { - @m.each_with_index("all"){} - }.should raise_error(ArgumentError) - -> { - @m.each_with_index(nil){} - }.should raise_error(ArgumentError) - -> { - @m.each_with_index(:left){} - }.should raise_error(ArgumentError) - end + describe "Matrix#each_with_index with an argument" do + before :all do + @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] + @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ] + end - it "yields the rights elements when passed :diagonal" do - @m.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [6, 1, 1]] - @t.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [4, 1, 1]] - end + it "raises an ArgumentError for unrecognized argument" do + -> { + @m.each_with_index("all"){} + }.should raise_error(ArgumentError) + -> { + @m.each_with_index(nil){} + }.should raise_error(ArgumentError) + -> { + @m.each_with_index(:left){} + }.should raise_error(ArgumentError) + end - it "yields the rights elements when passed :off_diagonal" do - @m.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [5, 1, 0], [7, 1, 2], [8, 1, 3]] - @t.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] - end + it "yields the rights elements when passed :diagonal" do + @m.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [6, 1, 1]] + @t.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [4, 1, 1]] + end - it "yields the rights elements when passed :lower" do - @m.each_with_index(:lower).to_a.should == [[1, 0, 0], [5, 1, 0], [6, 1, 1]] - @t.each_with_index(:lower).to_a.should == [[1, 0, 0], [3, 1, 0], [4, 1, 1], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] - end + it "yields the rights elements when passed :off_diagonal" do + @m.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [5, 1, 0], [7, 1, 2], [8, 1, 3]] + @t.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] + end - it "yields the rights elements when passed :strict_lower" do - @m.each_with_index(:strict_lower).to_a.should == [[5, 1, 0]] - @t.each_with_index(:strict_lower).to_a.should == [[3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] - end + it "yields the rights elements when passed :lower" do + @m.each_with_index(:lower).to_a.should == [[1, 0, 0], [5, 1, 0], [6, 1, 1]] + @t.each_with_index(:lower).to_a.should == [[1, 0, 0], [3, 1, 0], [4, 1, 1], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] + end - it "yields the rights elements when passed :strict_upper" do - @m.each_with_index(:strict_upper).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [7, 1, 2], [8, 1, 3]] - @t.each_with_index(:strict_upper).to_a.should == [[2, 0, 1]] - end + it "yields the rights elements when passed :strict_lower" do + @m.each_with_index(:strict_lower).to_a.should == [[5, 1, 0]] + @t.each_with_index(:strict_lower).to_a.should == [[3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]] + end + + it "yields the rights elements when passed :strict_upper" do + @m.each_with_index(:strict_upper).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [7, 1, 2], [8, 1, 3]] + @t.each_with_index(:strict_upper).to_a.should == [[2, 0, 1]] + end - it "yields the rights elements when passed :upper" do - @m.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [3, 0, 2], [4, 0, 3], [6, 1, 1], [7, 1, 2], [8, 1, 3]] - @t.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [4, 1, 1]] + it "yields the rights elements when passed :upper" do + @m.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [3, 0, 2], [4, 0, 3], [6, 1, 1], [7, 1, 2], [8, 1, 3]] + @t.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [4, 1, 1]] + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb index 67f9dd1c1..f9ffca012 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb @@ -1,9 +1,12 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#eigenvalue_matrix" do - it "returns a diagonal matrix with the eigenvalues on the diagonal" do - Matrix[[14, 16], [-6, -6]].eigensystem.eigenvalue_matrix.should == Matrix[[6, 0],[0, 2]] - Matrix[[1, 1], [-1, 1]].eigensystem.eigenvalue_matrix.should == Matrix[[Complex(1,1), 0],[0, Complex(1,-1)]] +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::EigenvalueDecomposition#eigenvalue_matrix" do + it "returns a diagonal matrix with the eigenvalues on the diagonal" do + Matrix[[14, 16], [-6, -6]].eigensystem.eigenvalue_matrix.should == Matrix[[6, 0],[0, 2]] + Matrix[[1, 1], [-1, 1]].eigensystem.eigenvalue_matrix.should == Matrix[[Complex(1,1), 0],[0, Complex(1,-1)]] + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb index 7552b7616..650d43d90 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb @@ -1,22 +1,25 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#eigenvalues" do - it "returns an array of complex eigenvalues for a rotation matrix" do - Matrix[[ 1, 1], - [-1, 1]].eigensystem.eigenvalues.sort_by{|v| v.imag}.should == - [ Complex(1, -1), Complex(1, 1)] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an array of real eigenvalues for a symmetric matrix" do - Matrix[[1, 2], - [2, 1]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should == - [ -1, 3 ] - end + describe "Matrix::EigenvalueDecomposition#eigenvalues" do + it "returns an array of complex eigenvalues for a rotation matrix" do + Matrix[[ 1, 1], + [-1, 1]].eigensystem.eigenvalues.sort_by{|v| v.imag}.should == + [ Complex(1, -1), Complex(1, 1)] + end + + it "returns an array of real eigenvalues for a symmetric matrix" do + Matrix[[1, 2], + [2, 1]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should == + [ -1, 3 ] + end - it "returns an array of real eigenvalues for a matrix" do - Matrix[[14, 16], - [-6, -6]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should == - [ 2, 6 ] + it "returns an array of real eigenvalues for a matrix" do + Matrix[[14, 16], + [-6, -6]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should == + [ 2, 6 ] + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb index 09f229ee1..57299ce69 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb @@ -1,20 +1,23 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#eigenvector_matrix" do - it "returns a complex eigenvector matrix given a rotation matrix" do - # Fix me: should test for linearity, not for equality - Matrix[[ 1, 1], - [-1, 1]].eigensystem.eigenvector_matrix.should == - Matrix[[1, 1], - [Complex(0, 1), Complex(0, -1)]] - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::EigenvalueDecomposition#eigenvector_matrix" do + it "returns a complex eigenvector matrix given a rotation matrix" do + # Fix me: should test for linearity, not for equality + Matrix[[ 1, 1], + [-1, 1]].eigensystem.eigenvector_matrix.should == + Matrix[[1, 1], + [Complex(0, 1), Complex(0, -1)]] + end - it "returns an real eigenvector matrix for a symmetric matrix" do - # Fix me: should test for linearity, not for equality - Matrix[[1, 2], - [2, 1]].eigensystem.eigenvector_matrix.should == - Matrix[[0.7071067811865475, 0.7071067811865475], - [-0.7071067811865475, 0.7071067811865475]] + it "returns an real eigenvector matrix for a symmetric matrix" do + # Fix me: should test for linearity, not for equality + Matrix[[1, 2], + [2, 1]].eigensystem.eigenvector_matrix.should == + Matrix[[0.7071067811865475, 0.7071067811865475], + [-0.7071067811865475, 0.7071067811865475]] + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb index 2b6ce74ea..54e6857bf 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb @@ -1,22 +1,25 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#eigenvectors" do - it "returns an array of complex eigenvectors for a rotation matrix" do - # Fix me: should test for linearity, not for equality - Matrix[[ 1, 1], - [-1, 1]].eigensystem.eigenvectors.should == - [ Vector[1, Complex(0, 1)], - Vector[1, Complex(0, -1)] - ] - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::EigenvalueDecomposition#eigenvectors" do + it "returns an array of complex eigenvectors for a rotation matrix" do + # Fix me: should test for linearity, not for equality + Matrix[[ 1, 1], + [-1, 1]].eigensystem.eigenvectors.should == + [ Vector[1, Complex(0, 1)], + Vector[1, Complex(0, -1)] + ] + end - it "returns an array of real eigenvectors for a symmetric matrix" do - # Fix me: should test for linearity, not for equality - Matrix[[1, 2], - [2, 1]].eigensystem.eigenvectors.should == - [ Vector[0.7071067811865475, -0.7071067811865475], - Vector[0.7071067811865475, 0.7071067811865475] - ] + it "returns an array of real eigenvectors for a symmetric matrix" do + # Fix me: should test for linearity, not for equality + Matrix[[1, 2], + [2, 1]].eigensystem.eigenvectors.should == + [ Vector[0.7071067811865475, -0.7071067811865475], + Vector[0.7071067811865475, 0.7071067811865475] + ] + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb index 8438f6313..02aad65c4 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#initialize" do - it "raises an error if argument is not a matrix" do - -> { - Matrix::EigenvalueDecomposition.new([[]]) - }.should raise_error(TypeError) - -> { - Matrix::EigenvalueDecomposition.new(42) - }.should raise_error(TypeError) - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "raises an error if matrix is not square" do - -> { - Matrix::EigenvalueDecomposition.new(Matrix[[1, 2]]) - }.should raise_error(Matrix::ErrDimensionMismatch) - end + describe "Matrix::EigenvalueDecomposition#initialize" do + it "raises an error if argument is not a matrix" do + -> { + Matrix::EigenvalueDecomposition.new([[]]) + }.should raise_error(TypeError) + -> { + Matrix::EigenvalueDecomposition.new(42) + }.should raise_error(TypeError) + end + + it "raises an error if matrix is not square" do + -> { + Matrix::EigenvalueDecomposition.new(Matrix[[1, 2]]) + }.should raise_error(Matrix::ErrDimensionMismatch) + end - it "never hangs" do - m = Matrix[ [0,0,0,0,0], [0,0,0,0,1], [0,0,0,1,0], [1,1,0,0,1], [1,0,1,0,1] ] - Matrix::EigenvalueDecomposition.new(m).should_not == "infinite loop" + it "never hangs" do + m = Matrix[ [0,0,0,0,0], [0,0,0,0,1], [0,0,0,1,0], [1,1,0,0,1], [1,0,1,0,1] ] + Matrix::EigenvalueDecomposition.new(m).should_not == "infinite loop" + end end end diff --git a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb index 8be41a572..352ae274b 100644 --- a/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb +++ b/ruby/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::EigenvalueDecomposition#to_a" do - before :each do - @a = Matrix[[14, 16], [-6, -6]] - @e = Matrix::EigenvalueDecomposition.new(@a) - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an array of with [V, D, V.inv]" do - @e.to_a.should == [@e.v, @e.d, @e.v_inv] - end + describe "Matrix::EigenvalueDecomposition#to_a" do + before :each do + @a = Matrix[[14, 16], [-6, -6]] + @e = Matrix::EigenvalueDecomposition.new(@a) + end + + it "returns an array of with [V, D, V.inv]" do + @e.to_a.should == [@e.v, @e.d, @e.v_inv] + end - it "returns a factorization" do - v, d, v_inv = @e.to_a - (v * d * v_inv).map{|e| e.round(10)}.should == @a + it "returns a factorization" do + v, d, v_inv = @e.to_a + (v * d * v_inv).map{|e| e.round(10)}.should == @a + end end end diff --git a/ruby/spec/ruby/library/matrix/element_reference_spec.rb b/ruby/spec/ruby/library/matrix/element_reference_spec.rb index b950d1c39..286ab851b 100644 --- a/ruby/spec/ruby/library/matrix/element_reference_spec.rb +++ b/ruby/spec/ruby/library/matrix/element_reference_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#[]" do +ruby_version_is ""..."3.1" do + require 'matrix' - before :all do - @m = Matrix[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]] - end + describe "Matrix#[]" do + + before :all do + @m = Matrix[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]] + end - it "returns element at (i, j)" do - (0..3).each do |i| - (0..2).each do |j| - @m[i, j].should == (i * 3) + j + it "returns element at (i, j)" do + (0..3).each do |i| + (0..2).each do |j| + @m[i, j].should == (i * 3) + j + end end end - end - it "returns nil for an invalid index pair" do - @m[8,1].should be_nil - @m[1,8].should be_nil - end + it "returns nil for an invalid index pair" do + @m[8,1].should be_nil + @m[1,8].should be_nil + end + end end diff --git a/ruby/spec/ruby/library/matrix/empty_spec.rb b/ruby/spec/ruby/library/matrix/empty_spec.rb index 5f294711d..0b5d5ffe0 100644 --- a/ruby/spec/ruby/library/matrix/empty_spec.rb +++ b/ruby/spec/ruby/library/matrix/empty_spec.rb @@ -1,68 +1,71 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#empty?" do - it "returns true when the Matrix is empty" do - Matrix[ ].empty?.should be_true - Matrix[ [], [], [] ].empty?.should be_true - Matrix[ [], [], [] ].transpose.empty?.should be_true - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns false when the Matrix has elements" do - Matrix[ [1, 2] ].empty?.should be_false - Matrix[ [1], [2] ].empty?.should be_false - end + describe "Matrix#empty?" do + it "returns true when the Matrix is empty" do + Matrix[ ].empty?.should be_true + Matrix[ [], [], [] ].empty?.should be_true + Matrix[ [], [], [] ].transpose.empty?.should be_true + end + + it "returns false when the Matrix has elements" do + Matrix[ [1, 2] ].empty?.should be_false + Matrix[ [1], [2] ].empty?.should be_false + end - it "doesn't accept any parameter" do - ->{ - Matrix[ [1, 2] ].empty?(42) - }.should raise_error(ArgumentError) + it "doesn't accept any parameter" do + ->{ + Matrix[ [1, 2] ].empty?(42) + }.should raise_error(ArgumentError) + end end -end -describe "Matrix.empty" do - it "returns an empty matrix of the requested size" do - m = Matrix.empty(3, 0) - m.row_size.should == 3 - m.column_size.should == 0 + describe "Matrix.empty" do + it "returns an empty matrix of the requested size" do + m = Matrix.empty(3, 0) + m.row_size.should == 3 + m.column_size.should == 0 - m = Matrix.empty(0, 3) - m.row_size.should == 0 - m.column_size.should == 3 - end + m = Matrix.empty(0, 3) + m.row_size.should == 0 + m.column_size.should == 3 + end - it "has arguments defaulting to 0" do - Matrix.empty.should == Matrix.empty(0, 0) - Matrix.empty(42).should == Matrix.empty(42, 0) - end + it "has arguments defaulting to 0" do + Matrix.empty.should == Matrix.empty(0, 0) + Matrix.empty(42).should == Matrix.empty(42, 0) + end - it "does not accept more than two parameters" do - ->{ - Matrix.empty(1, 2, 3) - }.should raise_error(ArgumentError) - end + it "does not accept more than two parameters" do + ->{ + Matrix.empty(1, 2, 3) + }.should raise_error(ArgumentError) + end - it "raises an error if both dimensions are > 0" do - ->{ - Matrix.empty(1, 2) - }.should raise_error(ArgumentError) - end + it "raises an error if both dimensions are > 0" do + ->{ + Matrix.empty(1, 2) + }.should raise_error(ArgumentError) + end - it "raises an error if any dimension is < 0" do - ->{ - Matrix.empty(-2, 0) - }.should raise_error(ArgumentError) + it "raises an error if any dimension is < 0" do + ->{ + Matrix.empty(-2, 0) + }.should raise_error(ArgumentError) - ->{ - Matrix.empty(0, -2) - }.should raise_error(ArgumentError) - end + ->{ + Matrix.empty(0, -2) + }.should raise_error(ArgumentError) + end -end + end -describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.empty(0, 1).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.empty(0, 1).should be_an_instance_of(MatrixSub) + end end end diff --git a/ruby/spec/ruby/library/matrix/eql_spec.rb b/ruby/spec/ruby/library/matrix/eql_spec.rb index ea26c3320..d3f03dd6f 100644 --- a/ruby/spec/ruby/library/matrix/eql_spec.rb +++ b/ruby/spec/ruby/library/matrix/eql_spec.rb @@ -1,11 +1,14 @@ require_relative '../../spec_helper' -require_relative 'shared/equal_value' -require 'matrix' -describe "Matrix#eql?" do - it_behaves_like :equal, :eql? +ruby_version_is ""..."3.1" do + require_relative 'shared/equal_value' + require 'matrix' - it "returns false if some elements are == but not eql?" do - Matrix[[1, 2],[3, 4]].eql?(Matrix[[1, 2],[3, 4.0]]).should be_false + describe "Matrix#eql?" do + it_behaves_like :equal, :eql? + + it "returns false if some elements are == but not eql?" do + Matrix[[1, 2],[3, 4]].eql?(Matrix[[1, 2],[3, 4.0]]).should be_false + end end end diff --git a/ruby/spec/ruby/library/matrix/equal_value_spec.rb b/ruby/spec/ruby/library/matrix/equal_value_spec.rb index 10cf1e6c2..0408a8ef3 100644 --- a/ruby/spec/ruby/library/matrix/equal_value_spec.rb +++ b/ruby/spec/ruby/library/matrix/equal_value_spec.rb @@ -1,11 +1,14 @@ require_relative '../../spec_helper' -require_relative 'shared/equal_value' -require 'matrix' -describe "Matrix#==" do - it_behaves_like :equal, :== +ruby_version_is ""..."3.1" do + require_relative 'shared/equal_value' + require 'matrix' - it "returns true if some elements are == but not eql?" do - Matrix[[1, 2],[3, 4]].should == Matrix[[1, 2],[3, 4.0]] + describe "Matrix#==" do + it_behaves_like :equal, :== + + it "returns true if some elements are == but not eql?" do + Matrix[[1, 2],[3, 4]].should == Matrix[[1, 2],[3, 4.0]] + end end end diff --git a/ruby/spec/ruby/library/matrix/exponent_spec.rb b/ruby/spec/ruby/library/matrix/exponent_spec.rb index 447c96296..5262627fd 100644 --- a/ruby/spec/ruby/library/matrix/exponent_spec.rb +++ b/ruby/spec/ruby/library/matrix/exponent_spec.rb @@ -1,51 +1,67 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' - -describe "Matrix#**" do - - describe "given an integer _n_" do - it "multiples the Matrix by itself _n_ times" do - m = Matrix[ [7,6], [3,9] ] - (m ** 1).should == m - (m ** 2).should == Matrix[ [67, 96], [48,99] ] - (m ** 2).should == m * m - (m ** 3).should == m * m * m - (m ** 4).should == m * m * m * m - (m ** 5).should == m * m * m * m * m - end - it "raises a ErrDimensionMismatch for non square matrices" do - m = Matrix[ [1, 1], [1, 2], [2, 3]] - -> { m ** 3 }.should raise_error(Matrix::ErrDimensionMismatch) - -> { m ** 0 }.should raise_error(Matrix::ErrDimensionMismatch) - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - describe "that is <= 0" do - it "returns the inverse of **(-n)" do - m = Matrix[ [1, 1], [1, 2] ] - (m ** -2).should == Matrix[ [5, -3], [-3, 2]] - (m ** -4).should == (m.inverse ** 4) + describe "Matrix#**" do + + describe "given an integer _n_" do + it "multiples the Matrix by itself _n_ times" do + m = Matrix[ [7,6], [3,9] ] + (m ** 1).should == m + (m ** 2).should == Matrix[ [67, 96], [48,99] ] + (m ** 2).should == m * m + (m ** 3).should == m * m * m + (m ** 4).should == m * m * m * m + (m ** 5).should == m * m * m * m * m end - it "raises a ErrDimensionMismatch for irregular matrices" do - m = Matrix[ [1, 1], [1, 1] ] - -> { m ** -2 }.should raise_error(Matrix::ErrNotRegular) - -> { m ** 0 }.should raise_error(Matrix::ErrNotRegular) + it "raises a ErrDimensionMismatch for non square matrices" do + m = Matrix[ [1, 1], [1, 2], [2, 3]] + -> { m ** 3 }.should raise_error(Matrix::ErrDimensionMismatch) + -> { m ** 0 }.should raise_error(Matrix::ErrDimensionMismatch) + end + + describe "that is < 0" do + it "returns the inverse of **(-n)" do + m = Matrix[ [1, 1], [1, 2] ] + (m ** -2).should == Matrix[ [5, -3], [-3, 2]] + (m ** -4).should == (m.inverse ** 4) + end + + it "raises a ErrNotRegular for irregular matrices" do + m = Matrix[ [1, 1], [1, 1] ] + -> { m ** -2 }.should raise_error(Matrix::ErrNotRegular) + end + end + + ruby_version_is '3.1.0' do # https://bugs.ruby-lang.org/issues/17521 + describe "that is 0" do + it "returns the identity for square matrices" do + m = Matrix[ [1, 1], [1, 1] ] + (m ** 0).should == Matrix.identity(2) + end + + it "raises an ErrDimensionMismatch for non-square matrices" do + m = Matrix[ [1, 1] ] + -> { m ** 0 }.should raise_error(Matrix::ErrDimensionMismatch) + end + end end end - end - it "returns the power for non integer powers" do - a = Matrix[[5, 4], [4, 5]] - ((a ** 0.5) ** 2).round(8).should == a - a = Matrix[[7, 10], [15, 22]] - ((a ** 0.25) ** 4).round(8).should == a - end + it "returns the power for non integer powers" do + a = Matrix[[5, 4], [4, 5]] + ((a ** 0.5) ** 2).round(8).should == a + a = Matrix[[7, 10], [15, 22]] + ((a ** 0.25) ** 4).round(8).should == a + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - (MatrixSub.ins ** 1).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + (MatrixSub.ins ** 1).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/find_index_spec.rb b/ruby/spec/ruby/library/matrix/find_index_spec.rb index c2bfa6d61..a0e3679ae 100644 --- a/ruby/spec/ruby/library/matrix/find_index_spec.rb +++ b/ruby/spec/ruby/library/matrix/find_index_spec.rb @@ -1,146 +1,149 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#find_index without any argument" do - before :all do - @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an Enumerator when called without a block" do - enum = @m.find_index - enum.should be_an_instance_of(Enumerator) - enum.to_a.should == [1, 2, 3, 4, 5, 6, 7, 8] - end + describe "Matrix#find_index without any argument" do + before :all do + @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ] + end - it "returns nil if the block is always false" do - @m.find_index{false}.should be_nil - end + it "returns an Enumerator when called without a block" do + enum = @m.find_index + enum.should be_an_instance_of(Enumerator) + enum.to_a.should == [1, 2, 3, 4, 5, 6, 7, 8] + end - it "returns the first index for which the block is true" do - @m.find_index{|x| x >= 3}.should == [0, 2] - end -end + it "returns nil if the block is always false" do + @m.find_index{false}.should be_nil + end -describe "Matrix#find_index with a subselection argument" do - before :all do - @tests = [ - [ Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ], { - diagonal: [1, 6] , - off_diagonal: [2, 3, 4, 5, 7, 8], - lower: [1, 5, 6] , - strict_lower: [5] , - strict_upper: [2, 3, 4, 7, 8] , - upper: [1, 2, 3, 4, 6, 7, 8] , - } - ], - [ Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ], { - diagonal: [1, 4] , - off_diagonal: [2, 3, 5, 6, 7, 8], - lower: [1, 3, 4, 5, 6, 7, 8] , - strict_lower: [3, 5, 6, 7, 8] , - strict_upper: [2] , - upper: [1, 2, 4] , - } - ]] + it "returns the first index for which the block is true" do + @m.find_index{|x| x >= 3}.should == [0, 2] + end end - describe "and no generic argument" do - it "returns an Enumerator when called without a block" do - @tests.each do |matrix, h| - h.each do |selector, result| - matrix.find_index(selector).should be_an_instance_of(Enumerator) - end - end + describe "Matrix#find_index with a subselection argument" do + before :all do + @tests = [ + [ Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ], { + diagonal: [1, 6] , + off_diagonal: [2, 3, 4, 5, 7, 8], + lower: [1, 5, 6] , + strict_lower: [5] , + strict_upper: [2, 3, 4, 7, 8] , + upper: [1, 2, 3, 4, 6, 7, 8] , + } + ], + [ Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ], { + diagonal: [1, 4] , + off_diagonal: [2, 3, 5, 6, 7, 8], + lower: [1, 3, 4, 5, 6, 7, 8] , + strict_lower: [3, 5, 6, 7, 8] , + strict_upper: [2] , + upper: [1, 2, 4] , + } + ]] end - it "yields the rights elements" do - @tests.each do |matrix, h| - h.each do |selector, result| - matrix.find_index(selector).to_a.should == result + describe "and no generic argument" do + it "returns an Enumerator when called without a block" do + @tests.each do |matrix, h| + h.each do |selector, result| + matrix.find_index(selector).should be_an_instance_of(Enumerator) + end end end - end - it "returns the first index for which the block returns true" do - @tests.each do |matrix, h| - h.each do |selector, result| - cnt = result.size.div 2 - which = result[cnt] - idx = matrix.find_index(selector){|x| cnt -= 1; x == which} - matrix[*idx].should == which - cnt.should == -1 + it "yields the rights elements" do + @tests.each do |matrix, h| + h.each do |selector, result| + matrix.find_index(selector).to_a.should == result + end end end - end - it "returns nil if the block is always false" do - @tests.each do |matrix, h| - h.each do |selector, result| - matrix.find_index(selector){ nil }.should == nil + it "returns the first index for which the block returns true" do + @tests.each do |matrix, h| + h.each do |selector, result| + cnt = result.size.div 2 + which = result[cnt] + idx = matrix.find_index(selector){|x| cnt -= 1; x == which} + matrix[*idx].should == which + cnt.should == -1 + end end end - end - end + it "returns nil if the block is always false" do + @tests.each do |matrix, h| + h.each do |selector, result| + matrix.find_index(selector){ nil }.should == nil + end + end + end - describe "and a generic argument" do - it "ignores a block" do - @m.find_index(42, :diagonal){raise "oups"}.should == nil end - it "returns the index of the requested value" do - @tests.each do |matrix, h| - h.each do |selector, result| - cnt = result.size / 2 - which = result[cnt] - idx = matrix.find_index(which, selector) - matrix[*idx].should == which + describe "and a generic argument" do + it "ignores a block" do + @m.find_index(42, :diagonal){raise "oups"}.should == nil + end + + it "returns the index of the requested value" do + @tests.each do |matrix, h| + h.each do |selector, result| + cnt = result.size / 2 + which = result[cnt] + idx = matrix.find_index(which, selector) + matrix[*idx].should == which + end end end - end - it "returns nil if the requested value is not found" do - @tests.each do |matrix, h| - h.each do |selector, result| - matrix.find_index(42, selector).should == nil + it "returns nil if the requested value is not found" do + @tests.each do |matrix, h| + h.each do |selector, result| + matrix.find_index(42, selector).should == nil + end end end end - end -end - -describe "Matrix#find_index with only a generic argument" do - before :all do - @m = Matrix[ [1, 2, 3, 4], [1, 2, 3, 4] ] end - it "returns nil if the value is not found" do - @m.find_index(42).should be_nil - end + describe "Matrix#find_index with only a generic argument" do + before :all do + @m = Matrix[ [1, 2, 3, 4], [1, 2, 3, 4] ] + end - it "returns the first index for of the requested value" do - @m.find_index(3).should == [0, 2] - end + it "returns nil if the value is not found" do + @m.find_index(42).should be_nil + end + + it "returns the first index for of the requested value" do + @m.find_index(3).should == [0, 2] + end - it "ignores a block" do - @m.find_index(4){raise "oups"}.should == [0, 3] + it "ignores a block" do + @m.find_index(4){raise "oups"}.should == [0, 3] + end end -end -describe "Matrix#find_index with two arguments" do - it "raises an ArgumentError for an unrecognized last argument" do - -> { - @m.find_index(1, "all"){} - }.should raise_error(ArgumentError) - -> { - @m.find_index(1, nil){} - }.should raise_error(ArgumentError) - -> { - @m.find_index(1, :left){} - }.should raise_error(ArgumentError) - -> { - @m.find_index(:diagonal, 1){} - }.should raise_error(ArgumentError) + describe "Matrix#find_index with two arguments" do + it "raises an ArgumentError for an unrecognized last argument" do + -> { + @m.find_index(1, "all"){} + }.should raise_error(ArgumentError) + -> { + @m.find_index(1, nil){} + }.should raise_error(ArgumentError) + -> { + @m.find_index(1, :left){} + }.should raise_error(ArgumentError) + -> { + @m.find_index(:diagonal, 1){} + }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/matrix/hash_spec.rb b/ruby/spec/ruby/library/matrix/hash_spec.rb index fac9a0652..7c1970511 100644 --- a/ruby/spec/ruby/library/matrix/hash_spec.rb +++ b/ruby/spec/ruby/library/matrix/hash_spec.rb @@ -1,15 +1,18 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#hash" do +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns a Fixnum" do - Matrix[ [1,2] ].hash.should be_an_instance_of(Fixnum) - end + describe "Matrix#hash" do - it "returns the same value for the same matrix" do - data = [ [40,5], [2,7] ] - Matrix[ *data ].hash.should == Matrix[ *data ].hash - end + it "returns an Integer" do + Matrix[ [1,2] ].hash.should be_an_instance_of(Integer) + end + it "returns the same value for the same matrix" do + data = [ [40,5], [2,7] ] + Matrix[ *data ].hash.should == Matrix[ *data ].hash + end + + end end diff --git a/ruby/spec/ruby/library/matrix/hermitian_spec.rb b/ruby/spec/ruby/library/matrix/hermitian_spec.rb index 177ca64d8..4038ee3fa 100644 --- a/ruby/spec/ruby/library/matrix/hermitian_spec.rb +++ b/ruby/spec/ruby/library/matrix/hermitian_spec.rb @@ -1,34 +1,37 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.hermitian?" do - it "returns true for a hermitian Matrix" do - Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, -3), 5, 6]].hermitian?.should be_true - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for a 0x0 empty matrix" do - Matrix.empty.hermitian?.should be_true - end + describe "Matrix.hermitian?" do + it "returns true for a hermitian Matrix" do + Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, -3), 5, 6]].hermitian?.should be_true + end - it "returns false for an asymmetric Matrix" do - Matrix[[1, 2],[-2, 1]].hermitian?.should be_false - end + it "returns true for a 0x0 empty matrix" do + Matrix.empty.hermitian?.should be_true + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.hermitian? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "returns false for an asymmetric Matrix" do + Matrix[[1, 2],[-2, 1]].hermitian?.should be_false + end + + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.hermitian? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end - end - it "returns false for a matrix with complex values on the diagonal" do - Matrix[[Complex(1,1)]].hermitian?.should be_false - Matrix[[Complex(1,0)]].hermitian?.should be_true + it "returns false for a matrix with complex values on the diagonal" do + Matrix[[Complex(1,1)]].hermitian?.should be_false + Matrix[[Complex(1,0)]].hermitian?.should be_true + end end end diff --git a/ruby/spec/ruby/library/matrix/identity_spec.rb b/ruby/spec/ruby/library/matrix/identity_spec.rb index 646462bc4..14f51c402 100644 --- a/ruby/spec/ruby/library/matrix/identity_spec.rb +++ b/ruby/spec/ruby/library/matrix/identity_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/identity' -describe "Matrix.identity" do - it_behaves_like :matrix_identity, :identity +ruby_version_is ""..."3.1" do + require_relative 'shared/identity' + + describe "Matrix.identity" do + it_behaves_like :matrix_identity, :identity + end end diff --git a/ruby/spec/ruby/library/matrix/imag_spec.rb b/ruby/spec/ruby/library/matrix/imag_spec.rb index 1c988753d..a89186ec0 100644 --- a/ruby/spec/ruby/library/matrix/imag_spec.rb +++ b/ruby/spec/ruby/library/matrix/imag_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/imaginary' -describe "Matrix#imag" do - it_behaves_like :matrix_imaginary, :imag +ruby_version_is ""..."3.1" do + require_relative 'shared/imaginary' + + describe "Matrix#imag" do + it_behaves_like :matrix_imaginary, :imag + end end diff --git a/ruby/spec/ruby/library/matrix/imaginary_spec.rb b/ruby/spec/ruby/library/matrix/imaginary_spec.rb index ceae4bbe8..e7f0e49d3 100644 --- a/ruby/spec/ruby/library/matrix/imaginary_spec.rb +++ b/ruby/spec/ruby/library/matrix/imaginary_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/imaginary' -describe "Matrix#imaginary" do - it_behaves_like :matrix_imaginary, :imaginary +ruby_version_is ""..."3.1" do + require_relative 'shared/imaginary' + + describe "Matrix#imaginary" do + it_behaves_like :matrix_imaginary, :imaginary + end end diff --git a/ruby/spec/ruby/library/matrix/inspect_spec.rb b/ruby/spec/ruby/library/matrix/inspect_spec.rb index 508f47825..d754c0fe7 100644 --- a/ruby/spec/ruby/library/matrix/inspect_spec.rb +++ b/ruby/spec/ruby/library/matrix/inspect_spec.rb @@ -1,27 +1,30 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#inspect" do +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a stringified representation of the Matrix" do - Matrix[ [1,2], [2,1] ].inspect.should == "Matrix[[1, 2], [2, 1]]" - end + describe "Matrix#inspect" do - it "returns 'Matrix.empty(...)' for empty matrices" do - Matrix[ [], [], [] ].inspect.should == "Matrix.empty(3, 0)" - Matrix.columns([ [], [], [] ]).inspect.should == "Matrix.empty(0, 3)" - end + it "returns a stringified representation of the Matrix" do + Matrix[ [1,2], [2,1] ].inspect.should == "Matrix[[1, 2], [2, 1]]" + end - it "calls inspect on its contents" do - obj = mock("some_value") - obj.should_receive(:inspect).and_return("some_value") - Matrix[ [1, 2], [3, obj] ].inspect.should == "Matrix[[1, 2], [3, some_value]]" - end + it "returns 'Matrix.empty(...)' for empty matrices" do + Matrix[ [], [], [] ].inspect.should == "Matrix.empty(3, 0)" + Matrix.columns([ [], [], [] ]).inspect.should == "Matrix.empty(0, 3)" + end + + it "calls inspect on its contents" do + obj = mock("some_value") + obj.should_receive(:inspect).and_return("some_value") + Matrix[ [1, 2], [3, obj] ].inspect.should == "Matrix[[1, 2], [3, some_value]]" + end - describe "for a subclass of Matrix" do - it "returns a string using the subclass' name" do - MatrixSub.ins.inspect.should == "MatrixSub[[1, 0], [0, 1]]" + describe "for a subclass of Matrix" do + it "returns a string using the subclass' name" do + MatrixSub.ins.inspect.should == "MatrixSub[[1, 0], [0, 1]]" + end end end end diff --git a/ruby/spec/ruby/library/matrix/inv_spec.rb b/ruby/spec/ruby/library/matrix/inv_spec.rb index 82879a6d8..0ad817a25 100644 --- a/ruby/spec/ruby/library/matrix/inv_spec.rb +++ b/ruby/spec/ruby/library/matrix/inv_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'spec_helper' -require_relative 'shared/inverse' -describe "Matrix#inv" do - it_behaves_like :inverse, :inv +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'shared/inverse' + + describe "Matrix#inv" do + it_behaves_like :inverse, :inv + end end diff --git a/ruby/spec/ruby/library/matrix/inverse_from_spec.rb b/ruby/spec/ruby/library/matrix/inverse_from_spec.rb index 651d56a24..bca40542f 100644 --- a/ruby/spec/ruby/library/matrix/inverse_from_spec.rb +++ b/ruby/spec/ruby/library/matrix/inverse_from_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#inverse_from" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix#inverse_from" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/inverse_spec.rb b/ruby/spec/ruby/library/matrix/inverse_spec.rb index fa3fa7de8..dd9099bec 100644 --- a/ruby/spec/ruby/library/matrix/inverse_spec.rb +++ b/ruby/spec/ruby/library/matrix/inverse_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'spec_helper' -require_relative 'shared/inverse' -describe "Matrix#inverse" do - it_behaves_like :inverse, :inverse +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'shared/inverse' + + describe "Matrix#inverse" do + it_behaves_like :inverse, :inverse + end end diff --git a/ruby/spec/ruby/library/matrix/lower_triangular_spec.rb b/ruby/spec/ruby/library/matrix/lower_triangular_spec.rb index f3aa4501f..0223b8b61 100644 --- a/ruby/spec/ruby/library/matrix/lower_triangular_spec.rb +++ b/ruby/spec/ruby/library/matrix/lower_triangular_spec.rb @@ -1,24 +1,27 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.lower_triangular?" do - it "returns true for a square lower triangular Matrix" do - Matrix[[1, 0, 0], [1, 2, 0], [1, 2, 3]].lower_triangular?.should be_true - Matrix.diagonal([1, 2, 3]).lower_triangular?.should be_true - Matrix[[1, 0], [1, 2], [1, 2], [1, 2]].lower_triangular?.should be_true - Matrix[[1, 0, 0, 0], [1, 2, 0, 0]].lower_triangular?.should be_true - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for an empty Matrix" do - Matrix.empty(3, 0).lower_triangular?.should be_true - Matrix.empty(0, 3).lower_triangular?.should be_true - Matrix.empty(0, 0).lower_triangular?.should be_true - end + describe "Matrix.lower_triangular?" do + it "returns true for a square lower triangular Matrix" do + Matrix[[1, 0, 0], [1, 2, 0], [1, 2, 3]].lower_triangular?.should be_true + Matrix.diagonal([1, 2, 3]).lower_triangular?.should be_true + Matrix[[1, 0], [1, 2], [1, 2], [1, 2]].lower_triangular?.should be_true + Matrix[[1, 0, 0, 0], [1, 2, 0, 0]].lower_triangular?.should be_true + end + + it "returns true for an empty Matrix" do + Matrix.empty(3, 0).lower_triangular?.should be_true + Matrix.empty(0, 3).lower_triangular?.should be_true + Matrix.empty(0, 0).lower_triangular?.should be_true + end - it "returns false for a non lower triangular square Matrix" do - Matrix[[0, 1], [0, 0]].lower_triangular?.should be_false - Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].lower_triangular?.should be_false - Matrix[[0, 1], [0, 0], [0, 0], [0, 0]].lower_triangular?.should be_false - Matrix[[0, 0, 0, 1], [0, 0, 0, 0]].lower_triangular?.should be_false + it "returns false for a non lower triangular square Matrix" do + Matrix[[0, 1], [0, 0]].lower_triangular?.should be_false + Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].lower_triangular?.should be_false + Matrix[[0, 1], [0, 0], [0, 0], [0, 0]].lower_triangular?.should be_false + Matrix[[0, 0, 0, 1], [0, 0, 0, 0]].lower_triangular?.should be_false + end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb index 9d733066c..1ac4bc971 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#determinant" do - it "returns the determinant when the matrix is square" do - a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - a.lup.determinant.should == 15120 # == a.determinant - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::LUPDecomposition#determinant" do + it "returns the determinant when the matrix is square" do + a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + a.lup.determinant.should == 15120 # == a.determinant + end - it "raises an error for rectangular matrices" do - [ - Matrix[[7, 8, 9], [14, 46, 51]], - Matrix[[7, 8], [14, 46], [28, 82]], - ].each do |m| - lup = m.lup - -> { - lup.determinant - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[7, 8, 9], [14, 46, 51]], + Matrix[[7, 8], [14, 46], [28, 82]], + ].each do |m| + lup = m.lup + -> { + lup.determinant + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb index 36afb349e..42f78c754 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#initialize" do - it "raises an error if argument is not a matrix" do - -> { - Matrix::LUPDecomposition.new([[]]) - }.should raise_error(TypeError) - -> { - Matrix::LUPDecomposition.new(42) - }.should raise_error(TypeError) +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::LUPDecomposition#initialize" do + it "raises an error if argument is not a matrix" do + -> { + Matrix::LUPDecomposition.new([[]]) + }.should raise_error(TypeError) + -> { + Matrix::LUPDecomposition.new(42) + }.should raise_error(TypeError) + end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/l_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/l_spec.rb index 9514ab5d0..6c751f12b 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/l_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/l_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#l" do - before :each do - @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - @lu = Matrix::LUPDecomposition.new(@a) - @l = @lu.l - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns the first element of to_a" do - @l.should == @lu.to_a[0] - end + describe "Matrix::LUPDecomposition#l" do + before :each do + @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + @lu = Matrix::LUPDecomposition.new(@a) + @l = @lu.l + end + + it "returns the first element of to_a" do + @l.should == @lu.to_a[0] + end - it "returns a lower triangular matrix" do - @l.lower_triangular?.should be_true + it "returns a lower triangular matrix" do + @l.lower_triangular?.should be_true + end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/p_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/p_spec.rb index c7b5e9196..481f8a17d 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/p_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/p_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#p" do - before :each do - @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - @lu = Matrix::LUPDecomposition.new(@a) - @p = @lu.p - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns the third element of to_a" do - @p.should == @lu.to_a[2] - end + describe "Matrix::LUPDecomposition#p" do + before :each do + @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + @lu = Matrix::LUPDecomposition.new(@a) + @p = @lu.p + end + + it "returns the third element of to_a" do + @p.should == @lu.to_a[2] + end - it "returns a permutation matrix" do - @p.permutation?.should be_true + it "returns a permutation matrix" do + @p.permutation?.should be_true + end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb index 66242627e..773fcb3e6 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb @@ -1,52 +1,55 @@ require_relative '../../../spec_helper' -require 'matrix' - -describe "Matrix::LUPDecomposition#solve" do - describe "for rectangular matrices" do - it "raises an error for singular matrices" do - a = Matrix[[1, 2, 3], [1, 3, 5], [2, 5, 8]] - lu = Matrix::LUPDecomposition.new(a) - -> { - lu.solve(a) - }.should raise_error(Matrix::ErrNotRegular) - end - describe "for non singular matrices" do - before :each do - @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - @lu = Matrix::LUPDecomposition.new(@a) - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns the appropriate empty matrix when given an empty matrix" do - @lu.solve(Matrix.empty(3,0)).should == Matrix.empty(3,0) - empty = Matrix::LUPDecomposition.new(Matrix.empty(0, 0)) - empty.solve(Matrix.empty(0,3)).should == Matrix.empty(0,3) + describe "Matrix::LUPDecomposition#solve" do + describe "for rectangular matrices" do + it "raises an error for singular matrices" do + a = Matrix[[1, 2, 3], [1, 3, 5], [2, 5, 8]] + lu = Matrix::LUPDecomposition.new(a) + -> { + lu.solve(a) + }.should raise_error(Matrix::ErrNotRegular) end - it "returns the right matrix when given a matrix of the appropriate size" do - solution = Matrix[[1, 2, 3, 4], [0, 1, 2, 3], [-1, -2, -3, -4]] - values = Matrix[[-2, 4, 10, 16], [-37, -28, -19, -10], [-135, -188, -241, -294]] # == @a * solution - @lu.solve(values).should == solution - end + describe "for non singular matrices" do + before :each do + @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + @lu = Matrix::LUPDecomposition.new(@a) + end - it "raises an error when given a matrix of the wrong size" do - values = Matrix[[1, 2, 3, 4], [0, 1, 2, 3]] - -> { - @lu.solve(values) - }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "returns the appropriate empty matrix when given an empty matrix" do + @lu.solve(Matrix.empty(3,0)).should == Matrix.empty(3,0) + empty = Matrix::LUPDecomposition.new(Matrix.empty(0, 0)) + empty.solve(Matrix.empty(0,3)).should == Matrix.empty(0,3) + end - it "returns the right vector when given a vector of the appropriate size" do - solution = Vector[1, 2, -1] - values = Vector[14, 55, 29] # == @a * solution - @lu.solve(values).should == solution - end + it "returns the right matrix when given a matrix of the appropriate size" do + solution = Matrix[[1, 2, 3, 4], [0, 1, 2, 3], [-1, -2, -3, -4]] + values = Matrix[[-2, 4, 10, 16], [-37, -28, -19, -10], [-135, -188, -241, -294]] # == @a * solution + @lu.solve(values).should == solution + end - it "raises an error when given a vector of the wrong size" do - values = Vector[14, 55] - -> { - @lu.solve(values) - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error when given a matrix of the wrong size" do + values = Matrix[[1, 2, 3, 4], [0, 1, 2, 3]] + -> { + @lu.solve(values) + }.should raise_error(Matrix::ErrDimensionMismatch) + end + + it "returns the right vector when given a vector of the appropriate size" do + solution = Vector[1, 2, -1] + values = Vector[14, 55, 29] # == @a * solution + @lu.solve(values).should == solution + end + + it "raises an error when given a vector of the wrong size" do + values = Vector[14, 55] + -> { + @lu.solve(values) + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb index 9b1dccbba..870229286 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#to_a" do - before :each do - @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - @lu = Matrix::LUPDecomposition.new(@a) - @to_a = @lu.to_a - @l, @u, @p = @to_a - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns an array of three matrices" do - @to_a.should be_kind_of(Array) - @to_a.length.should == 3 - @to_a.each{|m| m.should be_kind_of(Matrix)} - end + describe "Matrix::LUPDecomposition#to_a" do + before :each do + @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + @lu = Matrix::LUPDecomposition.new(@a) + @to_a = @lu.to_a + @l, @u, @p = @to_a + end - it "returns [l, u, p] such that l*u == a*p" do - (@l * @u).should == (@p * @a) - end + it "returns an array of three matrices" do + @to_a.should be_kind_of(Array) + @to_a.length.should == 3 + @to_a.each{|m| m.should be_kind_of(Matrix)} + end - it "returns the right values for rectangular matrices" do - [ - Matrix[[7, 8, 9], [14, 46, 51]], - Matrix[[4, 11], [5, 8], [3, 4]], - ].each do |a| - l, u, p = Matrix::LUPDecomposition.new(a).to_a - (l * u).should == (p * a) + it "returns [l, u, p] such that l*u == a*p" do + (@l * @u).should == (@p * @a) + end + + it "returns the right values for rectangular matrices" do + [ + Matrix[[7, 8, 9], [14, 46, 51]], + Matrix[[4, 11], [5, 8], [3, 4]], + ].each do |a| + l, u, p = Matrix::LUPDecomposition.new(a).to_a + (l * u).should == (p * a) + end end - end - it "has other properties implied by the specs of #l, #u and #p" + it "has other properties implied by the specs of #l, #u and #p" + end end diff --git a/ruby/spec/ruby/library/matrix/lup_decomposition/u_spec.rb b/ruby/spec/ruby/library/matrix/lup_decomposition/u_spec.rb index ca3dfc1f0..cd884b88e 100644 --- a/ruby/spec/ruby/library/matrix/lup_decomposition/u_spec.rb +++ b/ruby/spec/ruby/library/matrix/lup_decomposition/u_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::LUPDecomposition#u" do - before :each do - @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] - @lu = Matrix::LUPDecomposition.new(@a) - @u = @lu.u - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns the second element of to_a" do - @u.should == @lu.to_a[1] - end + describe "Matrix::LUPDecomposition#u" do + before :each do + @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]] + @lu = Matrix::LUPDecomposition.new(@a) + @u = @lu.u + end + + it "returns the second element of to_a" do + @u.should == @lu.to_a[1] + end - it "returns an upper triangular matrix" do - @u.upper_triangular?.should be_true + it "returns an upper triangular matrix" do + @u.upper_triangular?.should be_true + end end end diff --git a/ruby/spec/ruby/library/matrix/map_spec.rb b/ruby/spec/ruby/library/matrix/map_spec.rb index bc07c48cd..cde0df544 100644 --- a/ruby/spec/ruby/library/matrix/map_spec.rb +++ b/ruby/spec/ruby/library/matrix/map_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/collect' -describe "Matrix#map" do - it_behaves_like :collect, :map +ruby_version_is ""..."3.1" do + require_relative 'shared/collect' + + describe "Matrix#map" do + it_behaves_like :collect, :map + end end diff --git a/ruby/spec/ruby/library/matrix/minor_spec.rb b/ruby/spec/ruby/library/matrix/minor_spec.rb index 009826c3d..0a6b0823c 100644 --- a/ruby/spec/ruby/library/matrix/minor_spec.rb +++ b/ruby/spec/ruby/library/matrix/minor_spec.rb @@ -1,85 +1,88 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#minor" do - before :each do - @matrix = Matrix[ [1,2], [3,4], [5,6] ] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - describe "with start_row, nrows, start_col, ncols" do - it "returns the given portion of the Matrix" do - @matrix.minor(0,1,0,2).should == Matrix[ [1, 2] ] - @matrix.minor(1,2,1,1).should == Matrix[ [4], [6] ] + describe "Matrix#minor" do + before :each do + @matrix = Matrix[ [1,2], [3,4], [5,6] ] end - it "returns an empty Matrix if nrows or ncols is 0" do - @matrix.minor(0,0,0,0).should == Matrix[] - @matrix.minor(1,0,1,0).should == Matrix[] - @matrix.minor(1,0,1,1).should == Matrix.columns([[]]) - @matrix.minor(1,1,1,0).should == Matrix[[]] - end + describe "with start_row, nrows, start_col, ncols" do + it "returns the given portion of the Matrix" do + @matrix.minor(0,1,0,2).should == Matrix[ [1, 2] ] + @matrix.minor(1,2,1,1).should == Matrix[ [4], [6] ] + end - it "returns nil for out-of-bounds start_row/col" do - r = @matrix.row_size + 1 - c = @matrix.column_size + 1 - @matrix.minor(r,0,0,10).should == nil - @matrix.minor(0,10,c,9).should == nil - @matrix.minor(-r,0,0,10).should == nil - @matrix.minor(0,10,-c,9).should == nil - end + it "returns an empty Matrix if nrows or ncols is 0" do + @matrix.minor(0,0,0,0).should == Matrix[] + @matrix.minor(1,0,1,0).should == Matrix[] + @matrix.minor(1,0,1,1).should == Matrix.columns([[]]) + @matrix.minor(1,1,1,0).should == Matrix[[]] + end - it "returns nil for negative nrows or ncols" do - @matrix.minor(0,1,0,-1).should == nil - @matrix.minor(0,-1,0,1).should == nil - end + it "returns nil for out-of-bounds start_row/col" do + r = @matrix.row_size + 1 + c = @matrix.column_size + 1 + @matrix.minor(r,0,0,10).should == nil + @matrix.minor(0,10,c,9).should == nil + @matrix.minor(-r,0,0,10).should == nil + @matrix.minor(0,10,-c,9).should == nil + end - it "start counting backwards for start_row or start_col below zero" do - @matrix.minor(0, 1, -1, 1).should == @matrix.minor(0, 1, 1, 1) - @matrix.minor(-1, 1, 0, 1).should == @matrix.minor(2, 1, 0, 1) - end + it "returns nil for negative nrows or ncols" do + @matrix.minor(0,1,0,-1).should == nil + @matrix.minor(0,-1,0,1).should == nil + end - it "returns empty matrices for extreme start_row/col" do - @matrix.minor(3,10,1,10).should == Matrix.columns([[]]) - @matrix.minor(1,10,2,10).should == Matrix[[], []] - @matrix.minor(3,0,0,10).should == Matrix.columns([[], []]) - end + it "start counting backwards for start_row or start_col below zero" do + @matrix.minor(0, 1, -1, 1).should == @matrix.minor(0, 1, 1, 1) + @matrix.minor(-1, 1, 0, 1).should == @matrix.minor(2, 1, 0, 1) + end - it "ignores big nrows or ncols" do - @matrix.minor(0,1,0,20).should == Matrix[ [1, 2] ] - @matrix.minor(1,20,1,1).should == Matrix[ [4], [6] ] - end - end + it "returns empty matrices for extreme start_row/col" do + @matrix.minor(3,10,1,10).should == Matrix.columns([[]]) + @matrix.minor(1,10,2,10).should == Matrix[[], []] + @matrix.minor(3,0,0,10).should == Matrix.columns([[], []]) + end - describe "with col_range, row_range" do - it "returns the given portion of the Matrix" do - @matrix.minor(0..0, 0..1).should == Matrix[ [1, 2] ] - @matrix.minor(1..2, 1..2).should == Matrix[ [4], [6] ] - @matrix.minor(1...3, 1...3).should == Matrix[ [4], [6] ] + it "ignores big nrows or ncols" do + @matrix.minor(0,1,0,20).should == Matrix[ [1, 2] ] + @matrix.minor(1,20,1,1).should == Matrix[ [4], [6] ] + end end - it "returns nil if col_range or row_range is out of range" do - r = @matrix.row_size + 1 - c = @matrix.column_size + 1 - @matrix.minor(r..6, c..6).should == nil - @matrix.minor(0..1, c..6).should == nil - @matrix.minor(r..6, 0..1).should == nil - @matrix.minor(-r..6, -c..6).should == nil - @matrix.minor(0..1, -c..6).should == nil - @matrix.minor(-r..6, 0..1).should == nil - end + describe "with col_range, row_range" do + it "returns the given portion of the Matrix" do + @matrix.minor(0..0, 0..1).should == Matrix[ [1, 2] ] + @matrix.minor(1..2, 1..2).should == Matrix[ [4], [6] ] + @matrix.minor(1...3, 1...3).should == Matrix[ [4], [6] ] + end - it "start counting backwards for col_range or row_range below zero" do - @matrix.minor(0..1, -2..-1).should == @matrix.minor(0..1, 0..1) - @matrix.minor(0..1, -2..1).should == @matrix.minor(0..1, 0..1) - @matrix.minor(-2..-1, 0..1).should == @matrix.minor(1..2, 0..1) - @matrix.minor(-2..2, 0..1).should == @matrix.minor(1..2, 0..1) + it "returns nil if col_range or row_range is out of range" do + r = @matrix.row_size + 1 + c = @matrix.column_size + 1 + @matrix.minor(r..6, c..6).should == nil + @matrix.minor(0..1, c..6).should == nil + @matrix.minor(r..6, 0..1).should == nil + @matrix.minor(-r..6, -c..6).should == nil + @matrix.minor(0..1, -c..6).should == nil + @matrix.minor(-r..6, 0..1).should == nil + end + + it "start counting backwards for col_range or row_range below zero" do + @matrix.minor(0..1, -2..-1).should == @matrix.minor(0..1, 0..1) + @matrix.minor(0..1, -2..1).should == @matrix.minor(0..1, 0..1) + @matrix.minor(-2..-1, 0..1).should == @matrix.minor(1..2, 0..1) + @matrix.minor(-2..2, 0..1).should == @matrix.minor(1..2, 0..1) + end end - end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.ins.minor(0, 1, 0, 1).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.ins.minor(0, 1, 0, 1).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/minus_spec.rb b/ruby/spec/ruby/library/matrix/minus_spec.rb index 95cf4a607..27dfbeaea 100644 --- a/ruby/spec/ruby/library/matrix/minus_spec.rb +++ b/ruby/spec/ruby/library/matrix/minus_spec.rb @@ -1,42 +1,45 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#-" do - before :each do - @a = Matrix[ [1, 2], [3, 4] ] - @b = Matrix[ [4, 5], [6, 7] ] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns the result of subtracting the corresponding elements of other from self" do - (@a - @b).should == Matrix[ [-3,-3], [-3,-3] ] - end + describe "Matrix#-" do + before :each do + @a = Matrix[ [1, 2], [3, 4] ] + @b = Matrix[ [4, 5], [6, 7] ] + end - it "returns an instance of Matrix" do - (@a - @b).should be_kind_of(Matrix) - end + it "returns the result of subtracting the corresponding elements of other from self" do + (@a - @b).should == Matrix[ [-3,-3], [-3,-3] ] + end - it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do - -> { @a - Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "returns an instance of Matrix" do + (@a - @b).should be_kind_of(Matrix) + end - it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do - -> { @a - 2 }.should raise_error(Matrix::ErrOperationNotDefined) - -> { @a - 1.2 }.should raise_error(Matrix::ErrOperationNotDefined) - -> { @a - bignum_value }.should raise_error(Matrix::ErrOperationNotDefined) - end + it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do + -> { @a - Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) + end - it "raises a TypeError if other is of wrong type" do - -> { @a - nil }.should raise_error(TypeError) - -> { @a - "a" }.should raise_error(TypeError) - -> { @a - [ [1, 2] ] }.should raise_error(TypeError) - -> { @a - Object.new }.should raise_error(TypeError) - end + it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do + -> { @a - 2 }.should raise_error(Matrix::ErrOperationNotDefined) + -> { @a - 1.2 }.should raise_error(Matrix::ErrOperationNotDefined) + -> { @a - bignum_value }.should raise_error(Matrix::ErrOperationNotDefined) + end + + it "raises a TypeError if other is of wrong type" do + -> { @a - nil }.should raise_error(TypeError) + -> { @a - "a" }.should raise_error(TypeError) + -> { @a - [ [1, 2] ] }.should raise_error(TypeError) + -> { @a - Object.new }.should raise_error(TypeError) + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - m = MatrixSub.ins - (m-m).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + m = MatrixSub.ins + (m-m).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/multiply_spec.rb b/ruby/spec/ruby/library/matrix/multiply_spec.rb index 585f26893..841d9d95b 100644 --- a/ruby/spec/ruby/library/matrix/multiply_spec.rb +++ b/ruby/spec/ruby/library/matrix/multiply_spec.rb @@ -1,68 +1,71 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#*" do - before :each do - @a = Matrix[ [1, 2], [3, 4] ] - @b = Matrix[ [4, 5], [6, 7] ] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns the result of multiplying the corresponding elements of self and a Matrix" do - (@a * @b).should == Matrix[ [16,19], [36,43] ] - end + describe "Matrix#*" do + before :each do + @a = Matrix[ [1, 2], [3, 4] ] + @b = Matrix[ [4, 5], [6, 7] ] + end - it "returns the result of multiplying the corresponding elements of self and a Vector" do - (@a * Vector[1,2]).should == Vector[5, 11] - end + it "returns the result of multiplying the corresponding elements of self and a Matrix" do + (@a * @b).should == Matrix[ [16,19], [36,43] ] + end - it "returns the result of multiplying the elements of self and a Fixnum" do - (@a * 2).should == Matrix[ [2, 4], [6, 8] ] - end + it "returns the result of multiplying the corresponding elements of self and a Vector" do + (@a * Vector[1,2]).should == Vector[5, 11] + end - it "returns the result of multiplying the elements of self and a Bignum" do - (@a * bignum_value).should == Matrix[ - [9223372036854775808, 18446744073709551616], - [27670116110564327424, 36893488147419103232] - ] - end + it "returns the result of multiplying the elements of self and a Fixnum" do + (@a * 2).should == Matrix[ [2, 4], [6, 8] ] + end - it "returns the result of multiplying the elements of self and a Float" do - (@a * 2.0).should == Matrix[ [2.0, 4.0], [6.0, 8.0] ] - end + it "returns the result of multiplying the elements of self and a Bignum" do + (@a * bignum_value).should == Matrix[ + [9223372036854775808, 18446744073709551616], + [27670116110564327424, 36893488147419103232] + ] + end - it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do - -> { @a * Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "returns the result of multiplying the elements of self and a Float" do + (@a * 2.0).should == Matrix[ [2.0, 4.0], [6.0, 8.0] ] + end - it "returns a zero matrix if (nx0) * (0xn)" do - (Matrix[[],[],[]] * Matrix.columns([[],[],[]])).should == Matrix.zero(3) - end + it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do + -> { @a * Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) + end - it "returns an empty matrix if (0xn) * (nx0)" do - (Matrix.columns([[],[],[]]) * Matrix[[],[],[]]).should == Matrix[] - end + it "returns a zero matrix if (nx0) * (0xn)" do + (Matrix[[],[],[]] * Matrix.columns([[],[],[]])).should == Matrix.zero(3) + end - it "returns a mx0 matrix if (mxn) * (nx0)" do - (Matrix[[1,2],[3,4],[5,6]] * Matrix[[],[]]).should == Matrix[[],[],[]] - end + it "returns an empty matrix if (0xn) * (nx0)" do + (Matrix.columns([[],[],[]]) * Matrix[[],[],[]]).should == Matrix[] + end - it "returns a 0xm matrix if (0xm) * (mxn)" do - (Matrix.columns([[], [], []]) * Matrix[[1,2],[3,4],[5,6]]).should == Matrix.columns([[],[]]) - end + it "returns a mx0 matrix if (mxn) * (nx0)" do + (Matrix[[1,2],[3,4],[5,6]] * Matrix[[],[]]).should == Matrix[[],[],[]] + end - it "raises a TypeError if other is of wrong type" do - -> { @a * nil }.should raise_error(TypeError) - -> { @a * "a" }.should raise_error(TypeError) - -> { @a * [ [1, 2] ] }.should raise_error(TypeError) - -> { @a * Object.new }.should raise_error(TypeError) - end + it "returns a 0xm matrix if (0xm) * (mxn)" do + (Matrix.columns([[], [], []]) * Matrix[[1,2],[3,4],[5,6]]).should == Matrix.columns([[],[]]) + end + + it "raises a TypeError if other is of wrong type" do + -> { @a * nil }.should raise_error(TypeError) + -> { @a * "a" }.should raise_error(TypeError) + -> { @a * [ [1, 2] ] }.should raise_error(TypeError) + -> { @a * Object.new }.should raise_error(TypeError) + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - m = MatrixSub.ins - (m*m).should be_an_instance_of(MatrixSub) - (m*1).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + m = MatrixSub.ins + (m*m).should be_an_instance_of(MatrixSub) + (m*1).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/new_spec.rb b/ruby/spec/ruby/library/matrix/new_spec.rb index 300506684..4be2e1711 100644 --- a/ruby/spec/ruby/library/matrix/new_spec.rb +++ b/ruby/spec/ruby/library/matrix/new_spec.rb @@ -1,8 +1,11 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.new" do - it "is private" do - Matrix.should have_private_method(:new) +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix.new" do + it "is private" do + Matrix.should have_private_method(:new) + end end end diff --git a/ruby/spec/ruby/library/matrix/normal_spec.rb b/ruby/spec/ruby/library/matrix/normal_spec.rb index ebd73aaf4..2f2e138c1 100644 --- a/ruby/spec/ruby/library/matrix/normal_spec.rb +++ b/ruby/spec/ruby/library/matrix/normal_spec.rb @@ -1,26 +1,29 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.normal?" do - # it "returns false for non normal matrices" do - # Matrix[[0, 1], [1, 2]].normal?.should == false - # end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for normal matrices" do - Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].normal?.should == true - Matrix[[0, Complex(0, 2)], [Complex(0, -2), 0]].normal?.should == true - end + describe "Matrix.normal?" do + # it "returns false for non normal matrices" do + # Matrix[[0, 1], [1, 2]].should_not.normal? + # end + + it "returns true for normal matrices" do + Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should.normal? + Matrix[[0, Complex(0, 2)], [Complex(0, -2), 0]].should.normal? + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.normal? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.normal? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/orthogonal_spec.rb b/ruby/spec/ruby/library/matrix/orthogonal_spec.rb index 07b098a58..eb0630504 100644 --- a/ruby/spec/ruby/library/matrix/orthogonal_spec.rb +++ b/ruby/spec/ruby/library/matrix/orthogonal_spec.rb @@ -1,26 +1,29 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.orthogonal?" do - it "returns false for non orthogonal matrices" do - Matrix[[0, 1], [1, 2]].orthogonal?.should == false - Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].orthogonal?.should == false - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for orthogonal matrices" do - Matrix[[0, 1], [1, 0]].orthogonal?.should == true - end + describe "Matrix.orthogonal?" do + it "returns false for non orthogonal matrices" do + Matrix[[0, 1], [1, 2]].should_not.orthogonal? + Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should_not.orthogonal? + end + + it "returns true for orthogonal matrices" do + Matrix[[0, 1], [1, 0]].should.orthogonal? + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.orthogonal? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.orthogonal? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/permutation_spec.rb b/ruby/spec/ruby/library/matrix/permutation_spec.rb index 825a9d982..ed8edad75 100644 --- a/ruby/spec/ruby/library/matrix/permutation_spec.rb +++ b/ruby/spec/ruby/library/matrix/permutation_spec.rb @@ -1,32 +1,35 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#permutation?" do - it "returns true for a permutation Matrix" do - Matrix[[0, 1, 0], [0, 0, 1], [1, 0, 0]].permutation?.should be_true - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns false for a non permutation square Matrix" do - Matrix[[0, 1], [0, 0]].permutation?.should be_false - Matrix[[-1, 0], [0, -1]].permutation?.should be_false - Matrix[[1, 0], [1, 0]].permutation?.should be_false - Matrix[[1, 0], [1, 1]].permutation?.should be_false - end + describe "Matrix#permutation?" do + it "returns true for a permutation Matrix" do + Matrix[[0, 1, 0], [0, 0, 1], [1, 0, 0]].permutation?.should be_true + end - it "returns true for an empty 0x0 matrix" do - Matrix.empty(0,0).permutation?.should be_true - end + it "returns false for a non permutation square Matrix" do + Matrix[[0, 1], [0, 0]].permutation?.should be_false + Matrix[[-1, 0], [0, -1]].permutation?.should be_false + Matrix[[1, 0], [1, 0]].permutation?.should be_false + Matrix[[1, 0], [1, 1]].permutation?.should be_false + end + + it "returns true for an empty 0x0 matrix" do + Matrix.empty(0,0).permutation?.should be_true + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.permutation? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.permutation? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/plus_spec.rb b/ruby/spec/ruby/library/matrix/plus_spec.rb index 2706bad06..99e661577 100644 --- a/ruby/spec/ruby/library/matrix/plus_spec.rb +++ b/ruby/spec/ruby/library/matrix/plus_spec.rb @@ -1,42 +1,45 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#+" do - before :each do - @a = Matrix[ [1,2], [3,4] ] - @b = Matrix[ [4,5], [6,7] ] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns the result of adding the corresponding elements of self and other" do - (@a + @b).should == Matrix[ [5,7], [9,11] ] - end + describe "Matrix#+" do + before :each do + @a = Matrix[ [1,2], [3,4] ] + @b = Matrix[ [4,5], [6,7] ] + end - it "returns an instance of Matrix" do - (@a + @b).should be_kind_of(Matrix) - end + it "returns the result of adding the corresponding elements of self and other" do + (@a + @b).should == Matrix[ [5,7], [9,11] ] + end - it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do - -> { @a + Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "returns an instance of Matrix" do + (@a + @b).should be_kind_of(Matrix) + end - it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do - -> { @a + 2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) - -> { @a + 1.2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) - -> { @a + bignum_value }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) - end + it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do + -> { @a + Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch) + end - it "raises a TypeError if other is of wrong type" do - -> { @a + nil }.should raise_error(TypeError) - -> { @a + "a" }.should raise_error(TypeError) - -> { @a + [ [1, 2] ] }.should raise_error(TypeError) - -> { @a + Object.new }.should raise_error(TypeError) - end + it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do + -> { @a + 2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) + -> { @a + 1.2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) + -> { @a + bignum_value }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined) + end + + it "raises a TypeError if other is of wrong type" do + -> { @a + nil }.should raise_error(TypeError) + -> { @a + "a" }.should raise_error(TypeError) + -> { @a + [ [1, 2] ] }.should raise_error(TypeError) + -> { @a + Object.new }.should raise_error(TypeError) + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - m = MatrixSub.ins - (m+m).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + m = MatrixSub.ins + (m+m).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/rank_spec.rb b/ruby/spec/ruby/library/matrix/rank_spec.rb index d4403d23e..fc795b58c 100644 --- a/ruby/spec/ruby/library/matrix/rank_spec.rb +++ b/ruby/spec/ruby/library/matrix/rank_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#rank" do - it "returns the rank of the Matrix" do - Matrix[ [7,6], [3,9] ].rank.should == 2 - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "doesn't loop forever" do - Matrix[ [1,2,3], [4,5,6], [7,8,9] ].rank.should == 2 - Matrix[ [1, 2, 0, 3], [1, -2, 3, 0], [0, 0, 4, 8], [2, 4, 0, 6] ].rank. - should == 3 - end + describe "Matrix#rank" do + it "returns the rank of the Matrix" do + Matrix[ [7,6], [3,9] ].rank.should == 2 + end + + it "doesn't loop forever" do + Matrix[ [1,2,3], [4,5,6], [7,8,9] ].rank.should == 2 + Matrix[ [1, 2, 0, 3], [1, -2, 3, 0], [0, 0, 4, 8], [2, 4, 0, 6] ].rank. + should == 3 + end - it "works for some easy rectangular matrices" do - Matrix[[0,0],[0,0],[1,0]].rank.should == 1 - Matrix[[0,1],[0,0],[1,0]].rank.should == 2 + it "works for some easy rectangular matrices" do + Matrix[[0,0],[0,0],[1,0]].rank.should == 1 + Matrix[[0,1],[0,0],[1,0]].rank.should == 2 + end end end diff --git a/ruby/spec/ruby/library/matrix/real_spec.rb b/ruby/spec/ruby/library/matrix/real_spec.rb index 38033c63c..63a6bde92 100644 --- a/ruby/spec/ruby/library/matrix/real_spec.rb +++ b/ruby/spec/ruby/library/matrix/real_spec.rb @@ -1,43 +1,46 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#real?" do - it "returns true for matrices with all real entries" do - Matrix[ [1, 2], [3, 4] ].real?.should be_true - Matrix[ [1.9, 2], [3, 4] ].real?.should be_true - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns true for empty matrices" do - Matrix.empty.real?.should be_true - end + describe "Matrix#real?" do + it "returns true for matrices with all real entries" do + Matrix[ [1, 2], [3, 4] ].real?.should be_true + Matrix[ [1.9, 2], [3, 4] ].real?.should be_true + end - it "returns false if one element is a Complex" do - Matrix[ [Complex(1,1), 2], [3, 4] ].real?.should be_false - end + it "returns true for empty matrices" do + Matrix.empty.real?.should be_true + end - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - it "returns false if one element is a Complex whose imaginary part is 0" do - Matrix[ [Complex(1,0), 2], [3, 4] ].real?.should be_false + it "returns false if one element is a Complex" do + Matrix[ [Complex(1,1), 2], [3, 4] ].real?.should be_false end - end -end -describe "Matrix#real" do - it "returns a matrix with the real part of the elements of the receiver" do - Matrix[ [1, 2], [3, 4] ].real.should == Matrix[ [1, 2], [3, 4] ] - Matrix[ [1.9, Complex(1,1)], [Complex(-0.42, 0), 4] ].real.should == Matrix[ [1.9, 1], [-0.42, 4] ] + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + it "returns false if one element is a Complex whose imaginary part is 0" do + Matrix[ [Complex(1,0), 2], [3, 4] ].real?.should be_false + end + end end - it "returns empty matrices on the same size if empty" do - Matrix.empty(0, 3).real.should == Matrix.empty(0, 3) - Matrix.empty(3, 0).real.should == Matrix.empty(3, 0) - end + describe "Matrix#real" do + it "returns a matrix with the real part of the elements of the receiver" do + Matrix[ [1, 2], [3, 4] ].real.should == Matrix[ [1, 2], [3, 4] ] + Matrix[ [1.9, Complex(1,1)], [Complex(-0.42, 0), 4] ].real.should == Matrix[ [1.9, 1], [-0.42, 4] ] + end + + it "returns empty matrices on the same size if empty" do + Matrix.empty(0, 3).real.should == Matrix.empty(0, 3) + Matrix.empty(3, 0).real.should == Matrix.empty(3, 0) + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.ins.real.should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.ins.real.should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/rect_spec.rb b/ruby/spec/ruby/library/matrix/rect_spec.rb index 83a0404e4..b3b7ac05c 100644 --- a/ruby/spec/ruby/library/matrix/rect_spec.rb +++ b/ruby/spec/ruby/library/matrix/rect_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/rectangular' -describe "Matrix#rect" do - it_behaves_like :matrix_rectangular, :rect +ruby_version_is ""..."3.1" do + require_relative 'shared/rectangular' + + describe "Matrix#rect" do + it_behaves_like :matrix_rectangular, :rect + end end diff --git a/ruby/spec/ruby/library/matrix/rectangular_spec.rb b/ruby/spec/ruby/library/matrix/rectangular_spec.rb index a235fac64..1fc2e0e60 100644 --- a/ruby/spec/ruby/library/matrix/rectangular_spec.rb +++ b/ruby/spec/ruby/library/matrix/rectangular_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/rectangular' -describe "Matrix#rectangular" do - it_behaves_like :matrix_rectangular, :rectangular +ruby_version_is ""..."3.1" do + require_relative 'shared/rectangular' + + describe "Matrix#rectangular" do + it_behaves_like :matrix_rectangular, :rectangular + end end diff --git a/ruby/spec/ruby/library/matrix/regular_spec.rb b/ruby/spec/ruby/library/matrix/regular_spec.rb index 3699d0ef8..f6688bba3 100644 --- a/ruby/spec/ruby/library/matrix/regular_spec.rb +++ b/ruby/spec/ruby/library/matrix/regular_spec.rb @@ -1,31 +1,34 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#regular?" do +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns false for singular matrices" do - m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ] - m.regular?.should be_false + describe "Matrix#regular?" do - m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ] - m.regular?.should be_false - end + it "returns false for singular matrices" do + m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ] + m.regular?.should be_false - it "returns true if the Matrix is regular" do - Matrix[ [0,1], [1,0] ].regular?.should be_true - end + m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ] + m.regular?.should be_false + end - it "returns true for an empty 0x0 matrix" do - Matrix.empty(0,0).regular?.should be_true - end + it "returns true if the Matrix is regular" do + Matrix[ [0,1], [1,0] ].regular?.should be_true + end + + it "returns true for an empty 0x0 matrix" do + Matrix.empty(0,0).regular?.should be_true + end - it "raises an error for rectangular matrices" do - -> { - Matrix[[1], [2], [3]].regular? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + -> { + Matrix[[1], [2], [3]].regular? + }.should raise_error(Matrix::ErrDimensionMismatch) - -> { - Matrix.empty(3,0).regular? - }.should raise_error(Matrix::ErrDimensionMismatch) + -> { + Matrix.empty(3,0).regular? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end diff --git a/ruby/spec/ruby/library/matrix/round_spec.rb b/ruby/spec/ruby/library/matrix/round_spec.rb index 1dc29df89..db3326841 100644 --- a/ruby/spec/ruby/library/matrix/round_spec.rb +++ b/ruby/spec/ruby/library/matrix/round_spec.rb @@ -1,21 +1,24 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix#round" do - it "returns a matrix with all entries rounded" do - Matrix[ [1, 2.34], [5.67, 8] ].round.should == Matrix[ [1, 2], [6, 8] ] - Matrix[ [1, 2.34], [5.67, 8] ].round(1).should == Matrix[ [1, 2.3], [5.7, 8] ] - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns empty matrices on the same size if empty" do - Matrix.empty(0, 3).round.should == Matrix.empty(0, 3) - Matrix.empty(3, 0).round(42).should == Matrix.empty(3, 0) - end + describe "Matrix#round" do + it "returns a matrix with all entries rounded" do + Matrix[ [1, 2.34], [5.67, 8] ].round.should == Matrix[ [1, 2], [6, 8] ] + Matrix[ [1, 2.34], [5.67, 8] ].round(1).should == Matrix[ [1, 2.3], [5.7, 8] ] + end + + it "returns empty matrices on the same size if empty" do + Matrix.empty(0, 3).round.should == Matrix.empty(0, 3) + Matrix.empty(3, 0).round(42).should == Matrix.empty(3, 0) + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.ins.round.should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.ins.round.should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/row_size_spec.rb b/ruby/spec/ruby/library/matrix/row_size_spec.rb index eb3aef2e2..fca5a846a 100644 --- a/ruby/spec/ruby/library/matrix/row_size_spec.rb +++ b/ruby/spec/ruby/library/matrix/row_size_spec.rb @@ -1,13 +1,16 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#row_size" do - it "returns the number rows" do - Matrix[ [1,2], [3, 4], [5, 6] ].row_size.should == 3 - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns the number rows even for some empty matrices" do - Matrix[ [], [], [] ].row_size.should == 3 - end + describe "Matrix#row_size" do + it "returns the number rows" do + Matrix[ [1,2], [3, 4], [5, 6] ].row_size.should == 3 + end + it "returns the number rows even for some empty matrices" do + Matrix[ [], [], [] ].row_size.should == 3 + end + + end end diff --git a/ruby/spec/ruby/library/matrix/row_spec.rb b/ruby/spec/ruby/library/matrix/row_spec.rb index 00b1f02a8..eb05cd927 100644 --- a/ruby/spec/ruby/library/matrix/row_spec.rb +++ b/ruby/spec/ruby/library/matrix/row_spec.rb @@ -1,36 +1,39 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#row" do - before :all do - @m = Matrix[ [1, 2], [2, 3], [3, 4] ] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns a Vector when called without a block" do - @m.row(0).should == Vector[1,2] - end + describe "Matrix#row" do + before :all do + @m = Matrix[ [1, 2], [2, 3], [3, 4] ] + end - it "yields the elements of the row when called with a block" do - a = [] - @m.row(0) {|x| a << x} - a.should == [1,2] - end + it "returns a Vector when called without a block" do + @m.row(0).should == Vector[1,2] + end - it "counts backwards for negative argument" do - @m.row(-1).should == Vector[3, 4] - end + it "yields the elements of the row when called with a block" do + a = [] + @m.row(0) {|x| a << x} + a.should == [1,2] + end - it "returns self when called with a block" do - @m.row(0) { |x| x }.should equal(@m) - end + it "counts backwards for negative argument" do + @m.row(-1).should == Vector[3, 4] + end - it "returns nil when out of bounds" do - @m.row(3).should == nil - @m.row(-4).should == nil - end + it "returns self when called with a block" do + @m.row(0) { |x| x }.should equal(@m) + end + + it "returns nil when out of bounds" do + @m.row(3).should == nil + @m.row(-4).should == nil + end - it "never yields when out of bounds" do - -> { @m.row(3){ raise } }.should_not raise_error - -> { @m.row(-4){ raise } }.should_not raise_error + it "never yields when out of bounds" do + -> { @m.row(3){ raise } }.should_not raise_error + -> { @m.row(-4){ raise } }.should_not raise_error + end end end diff --git a/ruby/spec/ruby/library/matrix/row_vector_spec.rb b/ruby/spec/ruby/library/matrix/row_vector_spec.rb index 341437ee0..4c97d6013 100644 --- a/ruby/spec/ruby/library/matrix/row_vector_spec.rb +++ b/ruby/spec/ruby/library/matrix/row_vector_spec.rb @@ -1,24 +1,27 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.row_vector" do +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a Matrix" do - Matrix.row_vector([]).should be_an_instance_of(Matrix) - end + describe "Matrix.row_vector" do - it "returns a single-row Matrix with the specified values" do - Matrix.row_vector([1,2]).should == Matrix[ [1,2] ] - end + it "returns a Matrix" do + Matrix.row_vector([]).should be_an_instance_of(Matrix) + end - it "returns a 1x0 matrix when called with an empty Array" do - Matrix.row_vector([]).should == Matrix[ [] ] - end + it "returns a single-row Matrix with the specified values" do + Matrix.row_vector([1,2]).should == Matrix[ [1,2] ] + end + + it "returns a 1x0 matrix when called with an empty Array" do + Matrix.row_vector([]).should == Matrix[ [] ] + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.row_vector([1]).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.row_vector([1]).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/row_vectors_spec.rb b/ruby/spec/ruby/library/matrix/row_vectors_spec.rb index 6f99c439a..d01a4ca10 100644 --- a/ruby/spec/ruby/library/matrix/row_vectors_spec.rb +++ b/ruby/spec/ruby/library/matrix/row_vectors_spec.rb @@ -1,26 +1,29 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#row_vectors" do +ruby_version_is ""..."3.1" do + require 'matrix' - before :each do - @vectors = Matrix[ [1,2], [3,4] ].row_vectors - end + describe "Matrix#row_vectors" do - it "returns an Array" do - Matrix[ [1,2], [3,4] ].row_vectors.should be_an_instance_of(Array) - end + before :each do + @vectors = Matrix[ [1,2], [3,4] ].row_vectors + end - it "returns an Array of Vectors" do - @vectors.all? {|v| v.should be_an_instance_of(Vector)} - end + it "returns an Array" do + Matrix[ [1,2], [3,4] ].row_vectors.should be_an_instance_of(Array) + end - it "returns each row as a Vector" do - @vectors.should == [Vector[1,2], Vector[3,4]] - end + it "returns an Array of Vectors" do + @vectors.all? {|v| v.should be_an_instance_of(Vector)} + end + + it "returns each row as a Vector" do + @vectors.should == [Vector[1,2], Vector[3,4]] + end - it "returns an empty Array for empty matrices" do - Matrix[].row_vectors.should == [] - Matrix[ [] ].row_vectors.should == [ Vector[] ] + it "returns an empty Array for empty matrices" do + Matrix[].row_vectors.should == [] + Matrix[ [] ].row_vectors.should == [ Vector[] ] + end end end diff --git a/ruby/spec/ruby/library/matrix/rows_spec.rb b/ruby/spec/ruby/library/matrix/rows_spec.rb index 41ba63577..5f0515a37 100644 --- a/ruby/spec/ruby/library/matrix/rows_spec.rb +++ b/ruby/spec/ruby/library/matrix/rows_spec.rb @@ -1,41 +1,44 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.rows" do - before :each do - @a = [1, 2] - @b = [3, 4] - @m = Matrix.rows([@a, @b]) - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "returns a Matrix" do - @m.should be_kind_of(Matrix) - end + describe "Matrix.rows" do + before :each do + @a = [1, 2] + @b = [3, 4] + @m = Matrix.rows([@a, @b]) + end - it "creates a matrix from argument rows" do - @m.row(0).to_a.should == @a - @m.row(1).to_a.should == @b - end + it "returns a Matrix" do + @m.should be_kind_of(Matrix) + end - it "copies the original rows by default" do - @a << 3 - @b << 6 - @m.row(0).should_not equal(@a) - @m.row(1).should_not equal(@b) - end + it "creates a matrix from argument rows" do + @m.row(0).to_a.should == @a + @m.row(1).to_a.should == @b + end - it "references the original rows if copy is false" do - @m_ref = Matrix.rows([@a, @b], false) - @a << 3 - @b << 6 - @m_ref.row(0).to_a.should == @a - @m_ref.row(1).to_a.should == @b - end + it "copies the original rows by default" do + @a << 3 + @b << 6 + @m.row(0).should_not equal(@a) + @m.row(1).should_not equal(@b) + end + + it "references the original rows if copy is false" do + @m_ref = Matrix.rows([@a, @b], false) + @a << 3 + @b << 6 + @m_ref.row(0).to_a.should == @a + @m_ref.row(1).to_a.should == @b + end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.rows([[0, 1], [0, 1]]).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.rows([[0, 1], [0, 1]]).should be_an_instance_of(MatrixSub) + end end end end diff --git a/ruby/spec/ruby/library/matrix/scalar/Fail_spec.rb b/ruby/spec/ruby/library/matrix/scalar/Fail_spec.rb index 9d8f9bd5e..4f774eda2 100644 --- a/ruby/spec/ruby/library/matrix/scalar/Fail_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/Fail_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#Fail" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#Fail" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/Raise_spec.rb b/ruby/spec/ruby/library/matrix/scalar/Raise_spec.rb index 27e11c1f7..b405b6d6c 100644 --- a/ruby/spec/ruby/library/matrix/scalar/Raise_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/Raise_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#Raise" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#Raise" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/divide_spec.rb b/ruby/spec/ruby/library/matrix/scalar/divide_spec.rb index 5d726943f..0ef2206bf 100644 --- a/ruby/spec/ruby/library/matrix/scalar/divide_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/divide_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#/" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#/" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/exponent_spec.rb b/ruby/spec/ruby/library/matrix/scalar/exponent_spec.rb index 8e9ef52ff..87eea283d 100644 --- a/ruby/spec/ruby/library/matrix/scalar/exponent_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/exponent_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#**" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#**" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/included_spec.rb b/ruby/spec/ruby/library/matrix/scalar/included_spec.rb index cb3beb2ec..bab80e512 100644 --- a/ruby/spec/ruby/library/matrix/scalar/included_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/included_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar.included" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar.included" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/initialize_spec.rb b/ruby/spec/ruby/library/matrix/scalar/initialize_spec.rb index 23145ad0d..af51562b4 100644 --- a/ruby/spec/ruby/library/matrix/scalar/initialize_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/minus_spec.rb b/ruby/spec/ruby/library/matrix/scalar/minus_spec.rb index c727ea165..966db1d75 100644 --- a/ruby/spec/ruby/library/matrix/scalar/minus_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/minus_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#-" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#-" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/multiply_spec.rb b/ruby/spec/ruby/library/matrix/scalar/multiply_spec.rb index 1a2a83d83..21caac478 100644 --- a/ruby/spec/ruby/library/matrix/scalar/multiply_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/multiply_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#*" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#*" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar/plus_spec.rb b/ruby/spec/ruby/library/matrix/scalar/plus_spec.rb index c94689a70..78cdf9367 100644 --- a/ruby/spec/ruby/library/matrix/scalar/plus_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar/plus_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Matrix::Scalar#+" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix::Scalar#+" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/scalar_spec.rb b/ruby/spec/ruby/library/matrix/scalar_spec.rb index 7fdd64c9d..1ec64d2d7 100644 --- a/ruby/spec/ruby/library/matrix/scalar_spec.rb +++ b/ruby/spec/ruby/library/matrix/scalar_spec.rb @@ -1,65 +1,68 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.scalar" do +ruby_version_is ""..."3.1" do + require 'matrix' - before :each do - @side = 3 - @value = 8 - @a = Matrix.scalar(@side, @value) - end + describe "Matrix.scalar" do - it "returns a Matrix" do - @a.should be_kind_of(Matrix) - end + before :each do + @side = 3 + @value = 8 + @a = Matrix.scalar(@side, @value) + end - it "returns a n x n matrix" do - @a.row_size.should == @side - @a.column_size.should == @side - end + it "returns a Matrix" do + @a.should be_kind_of(Matrix) + end - it "initializes diagonal to value" do - (0...@a.row_size).each do |i| - @a[i, i].should == @value + it "returns a n x n matrix" do + @a.row_size.should == @side + @a.column_size.should == @side + end + + it "initializes diagonal to value" do + (0...@a.row_size).each do |i| + @a[i, i].should == @value + end end - end - it "initializes all non-diagonal values to 0" do - (0...@a.row_size).each do |i| - (0...@a.column_size).each do |j| - if i != j - @a[i, j].should == 0 + it "initializes all non-diagonal values to 0" do + (0...@a.row_size).each do |i| + (0...@a.column_size).each do |j| + if i != j + @a[i, j].should == 0 + end end end end - end - before :each do - @side = 3 - @value = 8 - @a = Matrix.scalar(@side, @value) - end + before :each do + @side = 3 + @value = 8 + @a = Matrix.scalar(@side, @value) + end - it "returns a Matrix" do - @a.should be_kind_of(Matrix) - end + it "returns a Matrix" do + @a.should be_kind_of(Matrix) + end - it "returns a square matrix, where the first argument specifies the side of the square" do - @a.row_size.should == @side - @a.column_size.should == @side - end + it "returns a square matrix, where the first argument specifies the side of the square" do + @a.row_size.should == @side + @a.column_size.should == @side + end - it "puts the second argument in all diagonal values" do - (0...@a.row_size).each do |i| - @a[i, i].should == @value + it "puts the second argument in all diagonal values" do + (0...@a.row_size).each do |i| + @a[i, i].should == @value + end end - end - it "fills all values not on the main diagonal with 0" do - (0...@a.row_size).each do |i| - (0...@a.column_size).each do |j| - if i != j - @a[i, j].should == 0 + it "fills all values not on the main diagonal with 0" do + (0...@a.row_size).each do |i| + (0...@a.column_size).each do |j| + if i != j + @a[i, j].should == 0 + end end end end diff --git a/ruby/spec/ruby/library/matrix/singular_spec.rb b/ruby/spec/ruby/library/matrix/singular_spec.rb index 7bba36a54..341c2675a 100644 --- a/ruby/spec/ruby/library/matrix/singular_spec.rb +++ b/ruby/spec/ruby/library/matrix/singular_spec.rb @@ -1,31 +1,34 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#singular?" do - it "returns true for singular matrices" do - m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ] - m.singular?.should be_true +ruby_version_is ""..."3.1" do + require 'matrix' - m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ] - m.singular?.should be_true - end + describe "Matrix#singular?" do + it "returns true for singular matrices" do + m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ] + m.singular?.should be_true - it "returns false if the Matrix is regular" do - Matrix[ [0,1], [1,0] ].singular?.should be_false - end + m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ] + m.singular?.should be_true + end - it "returns false for an empty 0x0 matrix" do - Matrix.empty(0,0).singular?.should be_false - end + it "returns false if the Matrix is regular" do + Matrix[ [0,1], [1,0] ].singular?.should be_false + end - it "raises an error for rectangular matrices" do - -> { - Matrix[[1], [2], [3]].singular? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "returns false for an empty 0x0 matrix" do + Matrix.empty(0,0).singular?.should be_false + end - -> { - Matrix.empty(3,0).singular? - }.should raise_error(Matrix::ErrDimensionMismatch) - end + it "raises an error for rectangular matrices" do + -> { + Matrix[[1], [2], [3]].singular? + }.should raise_error(Matrix::ErrDimensionMismatch) + + -> { + Matrix.empty(3,0).singular? + }.should raise_error(Matrix::ErrDimensionMismatch) + end + end end diff --git a/ruby/spec/ruby/library/matrix/square_spec.rb b/ruby/spec/ruby/library/matrix/square_spec.rb index 25d2d1ad9..e678f1c70 100644 --- a/ruby/spec/ruby/library/matrix/square_spec.rb +++ b/ruby/spec/ruby/library/matrix/square_spec.rb @@ -1,28 +1,31 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#square?" do +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true when the Matrix is square" do - Matrix[ [1,2], [2,4] ].square?.should be_true - Matrix[ [100,3,5], [9.5, 4.9, 8], [2,0,77] ].square?.should be_true - end + describe "Matrix#square?" do - it "returns true when the Matrix has only one element" do - Matrix[ [9] ].square?.should be_true - end + it "returns true when the Matrix is square" do + Matrix[ [1,2], [2,4] ].square?.should be_true + Matrix[ [100,3,5], [9.5, 4.9, 8], [2,0,77] ].square?.should be_true + end - it "returns false when the Matrix is rectangular" do - Matrix[ [1, 2] ].square?.should be_false - end + it "returns true when the Matrix has only one element" do + Matrix[ [9] ].square?.should be_true + end - it "returns false when the Matrix is rectangular" do - Matrix[ [1], [2] ].square?.should be_false - end + it "returns false when the Matrix is rectangular" do + Matrix[ [1, 2] ].square?.should be_false + end + + it "returns false when the Matrix is rectangular" do + Matrix[ [1], [2] ].square?.should be_false + end - it "returns handles empty matrices" do - Matrix[].square?.should be_true - Matrix[[]].square?.should be_false - Matrix.columns([[]]).square?.should be_false + it "returns handles empty matrices" do + Matrix[].square?.should be_true + Matrix[[]].square?.should be_false + Matrix.columns([[]]).square?.should be_false + end end end diff --git a/ruby/spec/ruby/library/matrix/symmetric_spec.rb b/ruby/spec/ruby/library/matrix/symmetric_spec.rb index 6f2a99276..9eed28ac0 100644 --- a/ruby/spec/ruby/library/matrix/symmetric_spec.rb +++ b/ruby/spec/ruby/library/matrix/symmetric_spec.rb @@ -1,29 +1,32 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.symmetric?" do - it "returns true for a symmetric Matrix" do - Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, 3), 5, 6]].symmetric?.should be_true - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for a 0x0 empty matrix" do - Matrix.empty.symmetric?.should be_true - end + describe "Matrix.symmetric?" do + it "returns true for a symmetric Matrix" do + Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, 3), 5, 6]].symmetric?.should be_true + end - it "returns false for an asymmetric Matrix" do - Matrix[[1, 2],[-2, 1]].symmetric?.should be_false - end + it "returns true for a 0x0 empty matrix" do + Matrix.empty.symmetric?.should be_true + end + + it "returns false for an asymmetric Matrix" do + Matrix[[1, 2],[-2, 1]].symmetric?.should be_false + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.symmetric? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.symmetric? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/t_spec.rb b/ruby/spec/ruby/library/matrix/t_spec.rb index 6f1a5178e..6eb54371e 100644 --- a/ruby/spec/ruby/library/matrix/t_spec.rb +++ b/ruby/spec/ruby/library/matrix/t_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/transpose' -describe "Matrix#transpose" do - it_behaves_like :matrix_transpose, :t +ruby_version_is ""..."3.1" do + require_relative 'shared/transpose' + + describe "Matrix#transpose" do + it_behaves_like :matrix_transpose, :t + end end diff --git a/ruby/spec/ruby/library/matrix/to_a_spec.rb b/ruby/spec/ruby/library/matrix/to_a_spec.rb index b5d55c5d6..0222a663a 100644 --- a/ruby/spec/ruby/library/matrix/to_a_spec.rb +++ b/ruby/spec/ruby/library/matrix/to_a_spec.rb @@ -1,11 +1,14 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#to_a" do - it "returns the array of arrays that describe the rows of the matrix" do - Matrix[].to_a.should == [] - Matrix[[]].to_a.should == [[]] - Matrix[[1]].to_a.should == [[1]] - Matrix[[1, 2], [3, 4]].to_a.should == [[1, 2],[3, 4]] +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix#to_a" do + it "returns the array of arrays that describe the rows of the matrix" do + Matrix[].to_a.should == [] + Matrix[[]].to_a.should == [[]] + Matrix[[1]].to_a.should == [[1]] + Matrix[[1, 2], [3, 4]].to_a.should == [[1, 2],[3, 4]] + end end end diff --git a/ruby/spec/ruby/library/matrix/to_s_spec.rb b/ruby/spec/ruby/library/matrix/to_s_spec.rb index f529fe3bc..7d38655e0 100644 --- a/ruby/spec/ruby/library/matrix/to_s_spec.rb +++ b/ruby/spec/ruby/library/matrix/to_s_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix#to_s" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Matrix#to_s" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/matrix/tr_spec.rb b/ruby/spec/ruby/library/matrix/tr_spec.rb index e17bd790d..bbf274bb5 100644 --- a/ruby/spec/ruby/library/matrix/tr_spec.rb +++ b/ruby/spec/ruby/library/matrix/tr_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/trace' -require 'matrix' -describe "Matrix#tr" do - it_behaves_like :trace, :tr +ruby_version_is ""..."3.1" do + require_relative 'shared/trace' + require 'matrix' + + describe "Matrix#tr" do + it_behaves_like :trace, :tr + end end diff --git a/ruby/spec/ruby/library/matrix/trace_spec.rb b/ruby/spec/ruby/library/matrix/trace_spec.rb index 290e7cb1f..ac6ce7927 100644 --- a/ruby/spec/ruby/library/matrix/trace_spec.rb +++ b/ruby/spec/ruby/library/matrix/trace_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/trace' -require 'matrix' -describe "Matrix#trace" do - it_behaves_like :trace, :trace +ruby_version_is ""..."3.1" do + require_relative 'shared/trace' + require 'matrix' + + describe "Matrix#trace" do + it_behaves_like :trace, :trace + end end diff --git a/ruby/spec/ruby/library/matrix/transpose_spec.rb b/ruby/spec/ruby/library/matrix/transpose_spec.rb index 79600dd43..d7f495b94 100644 --- a/ruby/spec/ruby/library/matrix/transpose_spec.rb +++ b/ruby/spec/ruby/library/matrix/transpose_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/transpose' -describe "Matrix#transpose" do - it_behaves_like :matrix_transpose, :transpose +ruby_version_is ""..."3.1" do + require_relative 'shared/transpose' + + describe "Matrix#transpose" do + it_behaves_like :matrix_transpose, :transpose + end end diff --git a/ruby/spec/ruby/library/matrix/unit_spec.rb b/ruby/spec/ruby/library/matrix/unit_spec.rb index 6a41d729c..439e0d616 100644 --- a/ruby/spec/ruby/library/matrix/unit_spec.rb +++ b/ruby/spec/ruby/library/matrix/unit_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/identity' -describe "Matrix.unit" do - it_behaves_like :matrix_identity, :unit +ruby_version_is ""..."3.1" do + require_relative 'shared/identity' + + describe "Matrix.unit" do + it_behaves_like :matrix_identity, :unit + end end diff --git a/ruby/spec/ruby/library/matrix/unitary_spec.rb b/ruby/spec/ruby/library/matrix/unitary_spec.rb index 9c2a106ea..b579cb244 100644 --- a/ruby/spec/ruby/library/matrix/unitary_spec.rb +++ b/ruby/spec/ruby/library/matrix/unitary_spec.rb @@ -1,28 +1,36 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.unitary?" do - it "returns false for non unitary matrices" do - Matrix[[0, 1], [1, 2]].unitary?.should == false - Matrix[[0, Complex(0, 2)], [Complex(0, 2), 0]].unitary?.should == false - Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].unitary?.should == false - Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].unitary?.should == false - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for unitary matrices" do - Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].unitary?.should == true - end + describe "Matrix.unitary?" do + it "returns false for non unitary matrices" do + Matrix[[0, 1], [1, 2]].should_not.unitary? + Matrix[[0, Complex(0, 2)], [Complex(0, 2), 0]].should_not.unitary? + Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should_not.unitary? + end + + it "returns true for unitary matrices" do + Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].should.unitary? + end + + version_is((Matrix::const_defined?(:VERSION) ? Matrix::VERSION : "0.1.0"), "0.3.0") do + it "returns true for unitary matrices with a Complex and a negative #imag" do + Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].should.unitary? + end + end - it "raises an error for rectangular matrices" do - [ - Matrix[[0], [0]], - Matrix[[0, 0]], - Matrix.empty(0, 2), - Matrix.empty(2, 0), - ].each do |rectangular_matrix| - -> { - rectangular_matrix.unitary? - }.should raise_error(Matrix::ErrDimensionMismatch) + it "raises an error for rectangular matrices" do + [ + Matrix[[0], [0]], + Matrix[[0, 0]], + Matrix.empty(0, 2), + Matrix.empty(2, 0), + ].each do |rectangular_matrix| + -> { + rectangular_matrix.unitary? + }.should raise_error(Matrix::ErrDimensionMismatch) + end end end end diff --git a/ruby/spec/ruby/library/matrix/upper_triangular_spec.rb b/ruby/spec/ruby/library/matrix/upper_triangular_spec.rb index 2514294a8..cc2aeb723 100644 --- a/ruby/spec/ruby/library/matrix/upper_triangular_spec.rb +++ b/ruby/spec/ruby/library/matrix/upper_triangular_spec.rb @@ -1,24 +1,27 @@ require_relative '../../spec_helper' -require 'matrix' -describe "Matrix.upper_triangular?" do - it "returns true for an upper triangular Matrix" do - Matrix[[1, 2, 3], [0, 2, 3], [0, 0, 3]].upper_triangular?.should be_true - Matrix.diagonal([1, 2, 3]).upper_triangular?.should be_true - Matrix[[1, 2], [0, 2], [0, 0], [0, 0]].upper_triangular?.should be_true - Matrix[[1, 2, 3, 4], [0, 2, 3, 4]].upper_triangular?.should be_true - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns false for a non upper triangular square Matrix" do - Matrix[[0, 0], [1, 0]].upper_triangular?.should be_false - Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].upper_triangular?.should be_false - Matrix[[0, 0], [0, 0], [0, 0], [0, 1]].upper_triangular?.should be_false - Matrix[[0, 0, 0, 0], [1, 0, 0, 0]].upper_triangular?.should be_false - end + describe "Matrix.upper_triangular?" do + it "returns true for an upper triangular Matrix" do + Matrix[[1, 2, 3], [0, 2, 3], [0, 0, 3]].upper_triangular?.should be_true + Matrix.diagonal([1, 2, 3]).upper_triangular?.should be_true + Matrix[[1, 2], [0, 2], [0, 0], [0, 0]].upper_triangular?.should be_true + Matrix[[1, 2, 3, 4], [0, 2, 3, 4]].upper_triangular?.should be_true + end + + it "returns false for a non upper triangular square Matrix" do + Matrix[[0, 0], [1, 0]].upper_triangular?.should be_false + Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].upper_triangular?.should be_false + Matrix[[0, 0], [0, 0], [0, 0], [0, 1]].upper_triangular?.should be_false + Matrix[[0, 0, 0, 0], [1, 0, 0, 0]].upper_triangular?.should be_false + end - it "returns true for an empty matrix" do - Matrix.empty(3,0).upper_triangular?.should be_true - Matrix.empty(0,3).upper_triangular?.should be_true - Matrix.empty(0,0).upper_triangular?.should be_true + it "returns true for an empty matrix" do + Matrix.empty(3,0).upper_triangular?.should be_true + Matrix.empty(0,3).upper_triangular?.should be_true + Matrix.empty(0,0).upper_triangular?.should be_true + end end end diff --git a/ruby/spec/ruby/library/matrix/vector/cross_product_spec.rb b/ruby/spec/ruby/library/matrix/vector/cross_product_spec.rb index c2698ade4..88523824c 100644 --- a/ruby/spec/ruby/library/matrix/vector/cross_product_spec.rb +++ b/ruby/spec/ruby/library/matrix/vector/cross_product_spec.rb @@ -1,14 +1,17 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Vector#cross_product" do - it "returns the cross product of a vector" do - Vector[1, 2, 3].cross_product(Vector[0, -4, 5]).should == Vector[22, -5, -4] - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Vector#cross_product" do + it "returns the cross product of a vector" do + Vector[1, 2, 3].cross_product(Vector[0, -4, 5]).should == Vector[22, -5, -4] + end - it "raises an error unless both vectors have dimension 3" do - -> { - Vector[1, 2, 3].cross_product(Vector[0, -4]) - }.should raise_error(Vector::ErrDimensionMismatch) + it "raises an error unless both vectors have dimension 3" do + -> { + Vector[1, 2, 3].cross_product(Vector[0, -4]) + }.should raise_error(Vector::ErrDimensionMismatch) + end end end diff --git a/ruby/spec/ruby/library/matrix/vector/each2_spec.rb b/ruby/spec/ruby/library/matrix/vector/each2_spec.rb index 10d2fc404..bdd696647 100644 --- a/ruby/spec/ruby/library/matrix/vector/each2_spec.rb +++ b/ruby/spec/ruby/library/matrix/vector/each2_spec.rb @@ -1,49 +1,52 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Vector.each2" do - before :all do - @v = Vector[1, 2, 3] - @v2 = Vector[4, 5, 6] - end - - it "requires one argument" do - -> { @v.each2(@v2, @v2){} }.should raise_error(ArgumentError) - -> { @v.each2(){} }.should raise_error(ArgumentError) - end - - describe "given one argument" do - it "accepts an Array argument" do - a = [] - @v.each2([7, 8, 9]){|x, y| a << x << y} - a.should == [1, 7, 2, 8, 3, 9] - end - - it "raises a DimensionMismatch error if the Vector size is different" do - -> { @v.each2(Vector[1,2]){} }.should raise_error(Vector::ErrDimensionMismatch) - -> { @v.each2(Vector[1,2,3,4]){} }.should raise_error(Vector::ErrDimensionMismatch) - end - - it "yields arguments in sequence" do - a = [] - @v.each2(@v2){|first, second| a << [first, second]} - a.should == [[1, 4], [2, 5], [3, 6]] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "yield arguments in pairs" do - a = [] - @v.each2(@v2){|*pair| a << pair} - a.should == [[1, 4], [2, 5], [3, 6]] + describe "Vector.each2" do + before :all do + @v = Vector[1, 2, 3] + @v2 = Vector[4, 5, 6] end - it "returns self when given a block" do - @v.each2(@v2){}.should equal(@v) + it "requires one argument" do + -> { @v.each2(@v2, @v2){} }.should raise_error(ArgumentError) + -> { @v.each2(){} }.should raise_error(ArgumentError) end - it "returns an enumerator if no block given" do - enum = @v.each2(@v2) - enum.should be_an_instance_of(Enumerator) - enum.to_a.should == [[1, 4], [2, 5], [3, 6]] + describe "given one argument" do + it "accepts an Array argument" do + a = [] + @v.each2([7, 8, 9]){|x, y| a << x << y} + a.should == [1, 7, 2, 8, 3, 9] + end + + it "raises a DimensionMismatch error if the Vector size is different" do + -> { @v.each2(Vector[1,2]){} }.should raise_error(Vector::ErrDimensionMismatch) + -> { @v.each2(Vector[1,2,3,4]){} }.should raise_error(Vector::ErrDimensionMismatch) + end + + it "yields arguments in sequence" do + a = [] + @v.each2(@v2){|first, second| a << [first, second]} + a.should == [[1, 4], [2, 5], [3, 6]] + end + + it "yield arguments in pairs" do + a = [] + @v.each2(@v2){|*pair| a << pair} + a.should == [[1, 4], [2, 5], [3, 6]] + end + + it "returns self when given a block" do + @v.each2(@v2){}.should equal(@v) + end + + it "returns an enumerator if no block given" do + enum = @v.each2(@v2) + enum.should be_an_instance_of(Enumerator) + enum.to_a.should == [[1, 4], [2, 5], [3, 6]] + end end end end diff --git a/ruby/spec/ruby/library/matrix/vector/eql_spec.rb b/ruby/spec/ruby/library/matrix/vector/eql_spec.rb index eb2451b55..fa086bd33 100644 --- a/ruby/spec/ruby/library/matrix/vector/eql_spec.rb +++ b/ruby/spec/ruby/library/matrix/vector/eql_spec.rb @@ -1,16 +1,19 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Vector#eql?" do - before do - @vector = Vector[1, 2, 3, 4, 5] - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns true for self" do - @vector.eql?(@vector).should be_true - end + describe "Vector#eql?" do + before do + @vector = Vector[1, 2, 3, 4, 5] + end + + it "returns true for self" do + @vector.eql?(@vector).should be_true + end - it "returns false when there are a pair corresponding elements which are not equal in the sense of Kernel#eql?" do - @vector.eql?(Vector[1, 2, 3, 4, 5.0]).should be_false + it "returns false when there are a pair corresponding elements which are not equal in the sense of Kernel#eql?" do + @vector.eql?(Vector[1, 2, 3, 4, 5.0]).should be_false + end end end diff --git a/ruby/spec/ruby/library/matrix/vector/inner_product_spec.rb b/ruby/spec/ruby/library/matrix/vector/inner_product_spec.rb index 1cf8771e0..95dc4806b 100644 --- a/ruby/spec/ruby/library/matrix/vector/inner_product_spec.rb +++ b/ruby/spec/ruby/library/matrix/vector/inner_product_spec.rb @@ -1,22 +1,25 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Vector#inner_product" do - it "returns the inner product of a vector" do - Vector[1, 2, 3].inner_product(Vector[0, -4, 5]).should == 7 - end +ruby_version_is ""..."3.1" do + require 'matrix' - it "returns 0 for empty vectors" do - Vector[].inner_product(Vector[]).should == 0 - end + describe "Vector#inner_product" do + it "returns the inner product of a vector" do + Vector[1, 2, 3].inner_product(Vector[0, -4, 5]).should == 7 + end - it "raises an error for mismatched vectors" do - -> { - Vector[1, 2, 3].inner_product(Vector[0, -4]) - }.should raise_error(Vector::ErrDimensionMismatch) - end + it "returns 0 for empty vectors" do + Vector[].inner_product(Vector[]).should == 0 + end + + it "raises an error for mismatched vectors" do + -> { + Vector[1, 2, 3].inner_product(Vector[0, -4]) + }.should raise_error(Vector::ErrDimensionMismatch) + end - it "uses the conjugate of its argument" do - Vector[Complex(1,2)].inner_product(Vector[Complex(3,4)]).should == Complex(11, 2) + it "uses the conjugate of its argument" do + Vector[Complex(1,2)].inner_product(Vector[Complex(3,4)]).should == Complex(11, 2) + end end end diff --git a/ruby/spec/ruby/library/matrix/vector/normalize_spec.rb b/ruby/spec/ruby/library/matrix/vector/normalize_spec.rb index 527c9260d..7345e11fa 100644 --- a/ruby/spec/ruby/library/matrix/vector/normalize_spec.rb +++ b/ruby/spec/ruby/library/matrix/vector/normalize_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'matrix' -describe "Vector#normalize" do - it "returns a normalized copy of the vector" do - x = 0.2672612419124244 - Vector[1, 2, 3].normalize.should == Vector[x, x * 2, x * 3] - end +ruby_version_is ""..."3.1" do + require 'matrix' + + describe "Vector#normalize" do + it "returns a normalized copy of the vector" do + x = 0.2672612419124244 + Vector[1, 2, 3].normalize.should == Vector[x, x * 2, x * 3] + end - it "raises an error for zero vectors" do - -> { - Vector[].normalize - }.should raise_error(Vector::ZeroVectorError) - -> { - Vector[0, 0, 0].normalize - }.should raise_error(Vector::ZeroVectorError) + it "raises an error for zero vectors" do + -> { + Vector[].normalize + }.should raise_error(Vector::ZeroVectorError) + -> { + Vector[0, 0, 0].normalize + }.should raise_error(Vector::ZeroVectorError) + end end end diff --git a/ruby/spec/ruby/library/matrix/zero_spec.rb b/ruby/spec/ruby/library/matrix/zero_spec.rb index 643c57acb..80162a03d 100644 --- a/ruby/spec/ruby/library/matrix/zero_spec.rb +++ b/ruby/spec/ruby/library/matrix/zero_spec.rb @@ -1,52 +1,55 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'matrix' -describe "Matrix.zero" do - it "returns an object of type Matrix" do - Matrix.zero(3).should be_kind_of(Matrix) - end +ruby_version_is ""..."3.1" do + require_relative 'fixtures/classes' + require 'matrix' - it "creates a n x n matrix" do - m3 = Matrix.zero(3) - m3.row_size.should == 3 - m3.column_size.should == 3 + describe "Matrix.zero" do + it "returns an object of type Matrix" do + Matrix.zero(3).should be_kind_of(Matrix) + end - m8 = Matrix.zero(8) - m8.row_size.should == 8 - m8.column_size.should == 8 - end + it "creates a n x n matrix" do + m3 = Matrix.zero(3) + m3.row_size.should == 3 + m3.column_size.should == 3 - it "initializes all cells to 0" do - size = 10 - m = Matrix.zero(size) + m8 = Matrix.zero(8) + m8.row_size.should == 8 + m8.column_size.should == 8 + end - (0...size).each do |i| - (0...size).each do |j| - m[i, j].should == 0 + it "initializes all cells to 0" do + size = 10 + m = Matrix.zero(size) + + (0...size).each do |i| + (0...size).each do |j| + m[i, j].should == 0 + end end end - end - describe "for a subclass of Matrix" do - it "returns an instance of that subclass" do - MatrixSub.zero(3).should be_an_instance_of(MatrixSub) + describe "for a subclass of Matrix" do + it "returns an instance of that subclass" do + MatrixSub.zero(3).should be_an_instance_of(MatrixSub) + end end end -end -describe "Matrix.zero?" do - it "returns true for empty matrices" do - Matrix.empty.zero?.should == true - Matrix.empty(3,0).zero?.should == true - Matrix.empty(0,3).zero?.should == true - end + describe "Matrix.zero?" do + it "returns true for empty matrices" do + Matrix.empty.should.zero? + Matrix.empty(3,0).should.zero? + Matrix.empty(0,3).should.zero? + end - it "returns true for matrices with zero entries" do - Matrix.zero(2,3).zero?.should == true - end + it "returns true for matrices with zero entries" do + Matrix.zero(2,3).should.zero? + end - it "returns false for matrices with non zero entries" do - Matrix[[1]].zero?.should == false + it "returns false for matrices with non zero entries" do + Matrix[[1]].should_not.zero? + end end end diff --git a/ruby/spec/ruby/library/monitor/enter_spec.rb b/ruby/spec/ruby/library/monitor/enter_spec.rb new file mode 100644 index 000000000..f523c4208 --- /dev/null +++ b/ruby/spec/ruby/library/monitor/enter_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' +require 'monitor' + +describe "Monitor#enter" do + it "acquires the monitor" do + monitor = Monitor.new + 10.times do + wait_q = Queue.new + continue_q = Queue.new + + thread = Thread.new do + begin + monitor.enter + wait_q << true + continue_q.pop + ensure + monitor.exit + end + end + + wait_q.pop + monitor.mon_locked?.should == true + continue_q << true + thread.join + monitor.mon_locked?.should == false + end + end +end diff --git a/ruby/spec/ruby/library/monitor/new_cond_spec.rb b/ruby/spec/ruby/library/monitor/new_cond_spec.rb new file mode 100644 index 000000000..ec25d3f8a --- /dev/null +++ b/ruby/spec/ruby/library/monitor/new_cond_spec.rb @@ -0,0 +1,88 @@ +require_relative '../../spec_helper' +require 'monitor' + +describe "Monitor#new_cond" do + it "creates a MonitorMixin::ConditionVariable" do + m = Monitor.new + c = m.new_cond + c.class.should == MonitorMixin::ConditionVariable + end + + it 'returns a condition variable which can be waited on by a thread holding the monitor' do + m = Monitor.new + c = m.new_cond + + 10.times do + + wait_q = Queue.new + thread = Thread.new do + m.synchronize do + wait_q << true + c.wait + end + :done + end + + wait_q.pop + + # Synchronize can't happen until the other thread is waiting. + m.synchronize { c.signal } + + thread.join + thread.value.should == :done + end + end + + it 'returns a condition variable which can be waited on by a thread holding the monitor inside multiple synchronize blocks' do + m = Monitor.new + c = m.new_cond + + 10.times do + + wait_q = Queue.new + thread = Thread.new do + m.synchronize do + m.synchronize do + wait_q << true + c.wait + end + end + :done + end + + wait_q.pop + + #No need to wait here as we cannot synchronize until the other thread is waiting. + m.synchronize { c.signal } + + thread.join + thread.value.should == :done + end + end + + it 'returns a condition variable which can be signalled by a thread holding the monitor inside multiple synchronize blocks' do + m = Monitor.new + c = m.new_cond + + 10.times do + + wait_q = Queue.new + thread = Thread.new do + m.synchronize do + wait_q << true + c.wait + end + :done + end + + wait_q.pop + + # Synchronize can't happen until the other thread is waiting. + m.synchronize { m.synchronize { c.signal } } + + thread.join + thread.value.should == :done + end + end + +end diff --git a/ruby/spec/ruby/library/monitor/synchronize_spec.rb b/ruby/spec/ruby/library/monitor/synchronize_spec.rb new file mode 100644 index 000000000..d78393eb3 --- /dev/null +++ b/ruby/spec/ruby/library/monitor/synchronize_spec.rb @@ -0,0 +1,41 @@ +require_relative '../../spec_helper' +require 'monitor' + +describe "Monitor#synchronize" do + it "unlocks after return, even if it was interrupted by Thread#raise" do + exc_class = Class.new(RuntimeError) + + monitor = Monitor.new + 10.times do + wait_q = Queue.new + continue_q = Queue.new + + thread = Thread.new do + begin + monitor.synchronize do + wait_q << true + # Do not wait here, we are trying to interrupt the ensure part of #synchronize + end + continue_q.pop + rescue exc_class + monitor.should_not.mon_locked? + :ok + end + end + + wait_q.pop + thread.raise exc_class, "interrupt" + continue_q << true + thread.value.should == :ok + end + end + + it "raises a LocalJumpError if not passed a block" do + -> { Monitor.new.synchronize }.should raise_error(LocalJumpError) + end + + it "raises a thread error if the monitor is not owned on exiting the block" do + monitor = Monitor.new + -> { monitor.synchronize { monitor.exit } }.should raise_error(ThreadError) + end +end diff --git a/ruby/spec/ruby/library/monitor/try_enter_spec.rb b/ruby/spec/ruby/library/monitor/try_enter_spec.rb new file mode 100644 index 000000000..04b878f72 --- /dev/null +++ b/ruby/spec/ruby/library/monitor/try_enter_spec.rb @@ -0,0 +1,39 @@ +require_relative '../../spec_helper' +require 'monitor' + +describe "Monitor#try_enter" do + it "will acquire a monitor not held by another thread" do + monitor = Monitor.new + 10.times do + + thread = Thread.new do + val = monitor.try_enter + monitor.exit if val + val + end + + thread.join + thread.value.should == true + end + end + + it "will not acquire a monitor already held by another thread" do + monitor = Monitor.new + 10.times do + monitor.enter + begin + thread = Thread.new do + val = monitor.try_enter + monitor.exit if val + val + end + + thread.join + thread.value.should == false + ensure + monitor.exit + end + monitor.mon_locked?.should == false + end + end +end diff --git a/ruby/spec/ruby/library/net/FTPError_spec.rb b/ruby/spec/ruby/library/net/FTPError_spec.rb index 0c31b65dc..84128511d 100644 --- a/ruby/spec/ruby/library/net/FTPError_spec.rb +++ b/ruby/spec/ruby/library/net/FTPError_spec.rb @@ -1,8 +1,11 @@ require_relative '../../spec_helper' -require 'net/ftp' -describe "Net::FTPError" do - it "is an Exception" do - Net::FTPError.should < Exception +ruby_version_is ""..."3.1" do + require 'net/ftp' + + describe "Net::FTPError" do + it "is an Exception" do + Net::FTPError.should < Exception + end end end diff --git a/ruby/spec/ruby/library/net/FTPPermError_spec.rb b/ruby/spec/ruby/library/net/FTPPermError_spec.rb index b43e12c50..0da35e7d8 100644 --- a/ruby/spec/ruby/library/net/FTPPermError_spec.rb +++ b/ruby/spec/ruby/library/net/FTPPermError_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require 'net/ftp' -describe "Net::FTPPermError" do - it "is an Exception" do - Net::FTPPermError.should < Exception - end +ruby_version_is ""..."3.1" do + require 'net/ftp' + + describe "Net::FTPPermError" do + it "is an Exception" do + Net::FTPPermError.should < Exception + end - it "is a subclass of Net::FTPError" do - Net::FTPPermError.should < Net::FTPError + it "is a subclass of Net::FTPError" do + Net::FTPPermError.should < Net::FTPError + end end end diff --git a/ruby/spec/ruby/library/net/FTPProtoError_spec.rb b/ruby/spec/ruby/library/net/FTPProtoError_spec.rb index e7abbc0dd..20e30dd2d 100644 --- a/ruby/spec/ruby/library/net/FTPProtoError_spec.rb +++ b/ruby/spec/ruby/library/net/FTPProtoError_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require 'net/ftp' -describe "Net::FTPProtoError" do - it "is an Exception" do - Net::FTPProtoError.should < Exception - end +ruby_version_is ""..."3.1" do + require 'net/ftp' + + describe "Net::FTPProtoError" do + it "is an Exception" do + Net::FTPProtoError.should < Exception + end - it "is a subclass of Net::FTPError" do - Net::FTPPermError.should < Net::FTPError + it "is a subclass of Net::FTPError" do + Net::FTPPermError.should < Net::FTPError + end end end diff --git a/ruby/spec/ruby/library/net/FTPReplyError_spec.rb b/ruby/spec/ruby/library/net/FTPReplyError_spec.rb index fcc7501fc..cc774aabe 100644 --- a/ruby/spec/ruby/library/net/FTPReplyError_spec.rb +++ b/ruby/spec/ruby/library/net/FTPReplyError_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require 'net/ftp' -describe "Net::FTPReplyError" do - it "is an Exception" do - Net::FTPReplyError.should < Exception - end +ruby_version_is ""..."3.1" do + require 'net/ftp' + + describe "Net::FTPReplyError" do + it "is an Exception" do + Net::FTPReplyError.should < Exception + end - it "is a subclass of Net::FTPError" do - Net::FTPPermError.should < Net::FTPError + it "is a subclass of Net::FTPError" do + Net::FTPPermError.should < Net::FTPError + end end end diff --git a/ruby/spec/ruby/library/net/FTPTempError_spec.rb b/ruby/spec/ruby/library/net/FTPTempError_spec.rb index f4b045dfb..e2fbdfd84 100644 --- a/ruby/spec/ruby/library/net/FTPTempError_spec.rb +++ b/ruby/spec/ruby/library/net/FTPTempError_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require 'net/ftp' -describe "Net::FTPTempError" do - it "is an Exception" do - Net::FTPTempError.should < Exception - end +ruby_version_is ""..."3.1" do + require 'net/ftp' + + describe "Net::FTPTempError" do + it "is an Exception" do + Net::FTPTempError.should < Exception + end - it "is a subclass of Net::FTPError" do - Net::FTPPermError.should < Net::FTPError + it "is a subclass of Net::FTPError" do + Net::FTPPermError.should < Net::FTPError + end end end diff --git a/ruby/spec/ruby/library/net/ftp/abort_spec.rb b/ruby/spec/ruby/library/net/ftp/abort_spec.rb index 57651468d..ebdfed4b1 100644 --- a/ruby/spec/ruby/library/net/ftp/abort_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/abort_spec.rb @@ -1,62 +1,65 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#abort" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#abort" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the ABOR command to the server" do - -> { @ftp.abort }.should_not raise_error - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "ignores the response" do - @ftp.abort - @ftp.last_response.should == "220 Dummy FTP Server ready!\n" - end + it "sends the ABOR command to the server" do + -> { @ftp.abort }.should_not raise_error + end - it "returns the full response" do - @ftp.abort.should == "226 Closing data connection. (ABOR)\n" - end + it "ignores the response" do + @ftp.abort + @ftp.last_response.should == "220 Dummy FTP Server ready!\n" + end - it "does not raise any error when the response code is 225" do - @server.should_receive(:abor).and_respond("225 Data connection open; no transfer in progress.") - -> { @ftp.abort }.should_not raise_error - end + it "returns the full response" do + @ftp.abort.should == "226 Closing data connection. (ABOR)\n" + end - it "does not raise any error when the response code is 226" do - @server.should_receive(:abor).and_respond("226 Closing data connection.") - -> { @ftp.abort }.should_not raise_error - end + it "does not raise any error when the response code is 225" do + @server.should_receive(:abor).and_respond("225 Data connection open; no transfer in progress.") + -> { @ftp.abort }.should_not raise_error + end - it "raises a Net::FTPProtoError when the response code is 500" do - @server.should_receive(:abor).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.abort }.should raise_error(Net::FTPProtoError) - end + it "does not raise any error when the response code is 226" do + @server.should_receive(:abor).and_respond("226 Closing data connection.") + -> { @ftp.abort }.should_not raise_error + end - it "raises a Net::FTPProtoError when the response code is 501" do - @server.should_receive(:abor).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.abort }.should raise_error(Net::FTPProtoError) - end + it "raises a Net::FTPProtoError when the response code is 500" do + @server.should_receive(:abor).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.abort }.should raise_error(Net::FTPProtoError) + end - it "raises a Net::FTPProtoError when the response code is 502" do - @server.should_receive(:abor).and_respond("502 Command not implemented.") - -> { @ftp.abort }.should raise_error(Net::FTPProtoError) - end + it "raises a Net::FTPProtoError when the response code is 501" do + @server.should_receive(:abor).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.abort }.should raise_error(Net::FTPProtoError) + end + + it "raises a Net::FTPProtoError when the response code is 502" do + @server.should_receive(:abor).and_respond("502 Command not implemented.") + -> { @ftp.abort }.should raise_error(Net::FTPProtoError) + end - it "raises a Net::FTPProtoError when the response code is 421" do - @server.should_receive(:abor).and_respond("421 Service not available, closing control connection.") - -> { @ftp.abort }.should raise_error(Net::FTPProtoError) + it "raises a Net::FTPProtoError when the response code is 421" do + @server.should_receive(:abor).and_respond("421 Service not available, closing control connection.") + -> { @ftp.abort }.should raise_error(Net::FTPProtoError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/acct_spec.rb b/ruby/spec/ruby/library/net/ftp/acct_spec.rb index d8068dc81..a960ae20a 100644 --- a/ruby/spec/ruby/library/net/ftp/acct_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/acct_spec.rb @@ -1,58 +1,61 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#acct" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "writes the ACCT command to the server" do - @ftp.acct("my_account") - @ftp.last_response.should == "230 User 'my_account' logged in, proceed. (ACCT)\n" - end - - it "returns nil" do - @ftp.acct("my_account").should == nil - end - - it "does not raise any error when the response code is 230" do - @server.should_receive(:acct).and_respond("230 User logged in, proceed.") - -> { @ftp.acct("my_account") }.should_not raise_error - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:acct).and_respond("530 Not logged in.") - -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 503" do - @server.should_receive(:acct).and_respond("503 Bad sequence of commands.") - -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.") - -> { @ftp.acct("my_account") }.should raise_error(Net::FTPTempError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#acct" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "writes the ACCT command to the server" do + @ftp.acct("my_account") + @ftp.last_response.should == "230 User 'my_account' logged in, proceed. (ACCT)\n" + end + + it "returns nil" do + @ftp.acct("my_account").should == nil + end + + it "does not raise any error when the response code is 230" do + @server.should_receive(:acct).and_respond("230 User logged in, proceed.") + -> { @ftp.acct("my_account") }.should_not raise_error + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:acct).and_respond("530 Not logged in.") + -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 503" do + @server.should_receive(:acct).and_respond("503 Bad sequence of commands.") + -> { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.") + -> { @ftp.acct("my_account") }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/binary_spec.rb b/ruby/spec/ruby/library/net/ftp/binary_spec.rb index 60e312a67..da7e2d6c1 100644 --- a/ruby/spec/ruby/library/net/ftp/binary_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/binary_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#binary" do - it "returns true when self is in binary mode" do - ftp = Net::FTP.new - ftp.binary.should be_true +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - ftp.binary = false - ftp.binary.should be_false + describe "Net::FTP#binary" do + it "returns true when self is in binary mode" do + ftp = Net::FTP.new + ftp.binary.should be_true + + ftp.binary = false + ftp.binary.should be_false + end end -end -describe "Net::FTP#binary=" do - it "sets self to binary mode when passed true" do - ftp = Net::FTP.new + describe "Net::FTP#binary=" do + it "sets self to binary mode when passed true" do + ftp = Net::FTP.new - ftp.binary = true - ftp.binary.should be_true + ftp.binary = true + ftp.binary.should be_true - ftp.binary = false - ftp.binary.should be_false + ftp.binary = false + ftp.binary.should be_false + end end end diff --git a/ruby/spec/ruby/library/net/ftp/chdir_spec.rb b/ruby/spec/ruby/library/net/ftp/chdir_spec.rb index 4c10fa78b..741c3c845 100644 --- a/ruby/spec/ruby/library/net/ftp/chdir_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/chdir_spec.rb @@ -1,99 +1,102 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#chdir" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#chdir" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + describe "when switching to the parent directory" do + it "sends the 'CDUP' command to the server" do + @ftp.chdir("..") + @ftp.last_response.should == "200 Command okay. (CDUP)\n" + end + + it "returns nil" do + @ftp.chdir("..").should be_nil + end + + it "does not raise a Net::FTPPermError when the response code is 500" do + @server.should_receive(:cdup).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.chdir("..") }.should_not raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:cdup).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:cdup).and_respond("502 Command not implemented.") + -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:cdup).and_respond("421 Service not available, closing control connection.") + -> { @ftp.chdir("..") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:cdup).and_respond("530 Not logged in.") + -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:cdup).and_respond("550 Requested action not taken.") + -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + end + end - describe "when switching to the parent directory" do - it "sends the 'CDUP' command to the server" do - @ftp.chdir("..") - @ftp.last_response.should == "200 Command okay. (CDUP)\n" + it "writes the 'CWD' command with the passed directory to the socket" do + @ftp.chdir("test") + @ftp.last_response.should == "200 Command okay. (CWD test)\n" end it "returns nil" do - @ftp.chdir("..").should be_nil + @ftp.chdir("test").should be_nil end - it "does not raise a Net::FTPPermError when the response code is 500" do - @server.should_receive(:cdup).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.chdir("..") }.should_not raise_error(Net::FTPPermError) + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:cwd).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) end it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:cdup).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + @server.should_receive(:cwd).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) end it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:cdup).and_respond("502 Command not implemented.") - -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + @server.should_receive(:cwd).and_respond("502 Command not implemented.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) end it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:cdup).and_respond("421 Service not available, closing control connection.") - -> { @ftp.chdir("..") }.should raise_error(Net::FTPTempError) + @server.should_receive(:cwd).and_respond("421 Service not available, closing control connection.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPTempError) end it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:cdup).and_respond("530 Not logged in.") - -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + @server.should_receive(:cwd).and_respond("530 Not logged in.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) end it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:cdup).and_respond("550 Requested action not taken.") - -> { @ftp.chdir("..") }.should raise_error(Net::FTPPermError) + @server.should_receive(:cwd).and_respond("550 Requested action not taken.") + -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) end end - - it "writes the 'CWD' command with the passed directory to the socket" do - @ftp.chdir("test") - @ftp.last_response.should == "200 Command okay. (CWD test)\n" - end - - it "returns nil" do - @ftp.chdir("test").should be_nil - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:cwd).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:cwd).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:cwd).and_respond("502 Command not implemented.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:cwd).and_respond("421 Service not available, closing control connection.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:cwd).and_respond("530 Not logged in.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:cwd).and_respond("550 Requested action not taken.") - -> { @ftp.chdir("test") }.should raise_error(Net::FTPPermError) - end end diff --git a/ruby/spec/ruby/library/net/ftp/close_spec.rb b/ruby/spec/ruby/library/net/ftp/close_spec.rb index 95c72b29e..49cdf4dea 100644 --- a/ruby/spec/ruby/library/net/ftp/close_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/close_spec.rb @@ -1,30 +1,33 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#close" do - before :each do - @socket = mock("Socket") - @socket.stub!(:closed?).and_return(false) - @socket.stub!(:read_timeout).and_return(60) - @socket.stub!(:read_timeout=).and_return(3) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - @ftp = Net::FTP.new - @ftp.instance_variable_set(:@sock, @socket) - end + describe "Net::FTP#close" do + before :each do + @socket = mock("Socket") + @socket.stub!(:closed?).and_return(false) + @socket.stub!(:read_timeout).and_return(60) + @socket.stub!(:read_timeout=).and_return(3) - it "closes the socket" do - @socket.should_receive(:close) - @ftp.close.should be_nil - end + @ftp = Net::FTP.new + @ftp.instance_variable_set(:@sock, @socket) + end - it "does not try to close the socket if it has already been closed" do - @socket.should_receive(:closed?).and_return(true) - @socket.should_not_receive(:close) - @ftp.close.should be_nil - end + it "closes the socket" do + @socket.should_receive(:close) + @ftp.close.should be_nil + end + + it "does not try to close the socket if it has already been closed" do + @socket.should_receive(:closed?).and_return(true) + @socket.should_not_receive(:close) + @ftp.close.should be_nil + end - it "does not try to close the socket if it is nil" do - @ftp.instance_variable_set(:@sock, nil) - @ftp.close.should be_nil + it "does not try to close the socket if it is nil" do + @ftp.instance_variable_set(:@sock, nil) + @ftp.close.should be_nil + end end end diff --git a/ruby/spec/ruby/library/net/ftp/closed_spec.rb b/ruby/spec/ruby/library/net/ftp/closed_spec.rb index 1f3e69b0c..a81917090 100644 --- a/ruby/spec/ruby/library/net/ftp/closed_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/closed_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#closed?" do - before :each do - @socket = mock("Socket") +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - @ftp = Net::FTP.new - @ftp.instance_variable_set(:@sock, @socket) - end + describe "Net::FTP#closed?" do + before :each do + @socket = mock("Socket") - it "returns true when the socket is closed" do - @socket.should_receive(:closed?).and_return(true) - @ftp.closed?.should be_true - end + @ftp = Net::FTP.new + @ftp.instance_variable_set(:@sock, @socket) + end + + it "returns true when the socket is closed" do + @socket.should_receive(:closed?).and_return(true) + @ftp.closed?.should be_true + end - it "returns true when the socket is nil" do - @ftp.instance_variable_set(:@sock, nil) - @ftp.closed?.should be_true + it "returns true when the socket is nil" do + @ftp.instance_variable_set(:@sock, nil) + @ftp.closed?.should be_true + end end end diff --git a/ruby/spec/ruby/library/net/ftp/connect_spec.rb b/ruby/spec/ruby/library/net/ftp/connect_spec.rb index 9ee9bcd2c..b45e46c53 100644 --- a/ruby/spec/ruby/library/net/ftp/connect_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/connect_spec.rb @@ -1,49 +1,52 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -# TODO: Add specs for using the SOCKSSocket -describe "Net::FTP#connect" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - end - - after :each do - @server.connect_message = nil - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "tries to connect to the FTP Server on the given host and port" do - -> { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error - end - - it "returns nil" do - @ftp.connect(@server.hostname, @server.server_port).should be_nil - end - - it "prints a small debug line when in debug mode" do - @ftp.debug_mode = true - -> { @ftp.connect(@server.hostname, @server.server_port) }.should output(/#{"connect: "}#{@server.hostname}#{", "}#{@server.server_port}#{"\\nget: 220 Dummy FTP Server ready!"}/) - @ftp.debug_mode = false - end - - it "does not raise any error when the response code is 220" do - @server.connect_message = "220 Dummy FTP Server ready!" - -> { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error - end - - it "raises a Net::FTPReplyError when the response code is 120" do - @server.connect_message = "120 Service ready in nnn minutes." - -> { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPReplyError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.connect_message = "421 Service not available, closing control connection." - -> { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPTempError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + # TODO: Add specs for using the SOCKSSocket + describe "Net::FTP#connect" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + end + + after :each do + @server.connect_message = nil + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "tries to connect to the FTP Server on the given host and port" do + -> { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error + end + + it "returns nil" do + @ftp.connect(@server.hostname, @server.server_port).should be_nil + end + + it "prints a small debug line when in debug mode" do + @ftp.debug_mode = true + -> { @ftp.connect(@server.hostname, @server.server_port) }.should output(/#{"connect: "}#{@server.hostname}#{", "}#{@server.server_port}#{"\\nget: 220 Dummy FTP Server ready!"}/) + @ftp.debug_mode = false + end + + it "does not raise any error when the response code is 220" do + @server.connect_message = "220 Dummy FTP Server ready!" + -> { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error + end + + it "raises a Net::FTPReplyError when the response code is 120" do + @server.connect_message = "120 Service ready in nnn minutes." + -> { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPReplyError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.connect_message = "421 Service not available, closing control connection." + -> { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/debug_mode_spec.rb b/ruby/spec/ruby/library/net/ftp/debug_mode_spec.rb index f49da55ed..46d207bbe 100644 --- a/ruby/spec/ruby/library/net/ftp/debug_mode_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/debug_mode_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#debug_mode" do - it "returns true when self is in debug mode" do - ftp = Net::FTP.new - ftp.debug_mode.should be_false +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - ftp.debug_mode = true - ftp.debug_mode.should be_true + describe "Net::FTP#debug_mode" do + it "returns true when self is in debug mode" do + ftp = Net::FTP.new + ftp.debug_mode.should be_false + + ftp.debug_mode = true + ftp.debug_mode.should be_true + end end -end -describe "Net::FTP#debug_mode=" do - it "sets self into debug mode when passed true" do - ftp = Net::FTP.new - ftp.debug_mode = true - ftp.debug_mode.should be_true + describe "Net::FTP#debug_mode=" do + it "sets self into debug mode when passed true" do + ftp = Net::FTP.new + ftp.debug_mode = true + ftp.debug_mode.should be_true - ftp.debug_mode = false - ftp.debug_mode.should be_false + ftp.debug_mode = false + ftp.debug_mode.should be_false + end end end diff --git a/ruby/spec/ruby/library/net/ftp/default_passive_spec.rb b/ruby/spec/ruby/library/net/ftp/default_passive_spec.rb index 30eb8f9da..9348d3294 100644 --- a/ruby/spec/ruby/library/net/ftp/default_passive_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/default_passive_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#default_passive" do - it "is true by default" do - ruby_exe(fixture(__FILE__, "default_passive.rb")).should == "true\ntrue\n" +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + + describe "Net::FTP#default_passive" do + it "is true by default" do + ruby_exe(fixture(__FILE__, "default_passive.rb")).should == "true\ntrue\n" + end end end diff --git a/ruby/spec/ruby/library/net/ftp/delete_spec.rb b/ruby/spec/ruby/library/net/ftp/delete_spec.rb index cf8f9332e..43bfcc154 100644 --- a/ruby/spec/ruby/library/net/ftp/delete_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/delete_spec.rb @@ -1,59 +1,62 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#delete" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the DELE command with the passed filename to the server" do - @ftp.delete("test.file") - @ftp.last_response.should == "250 Requested file action okay, completed. (DELE test.file)\n" - end - - it "raises a Net::FTPTempError when the response code is 450" do - @server.should_receive(:dele).and_respond("450 Requested file action not taken.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:dele).and_respond("550 Requested action not taken.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:dele).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:dele).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:dele).and_respond("502 Command not implemented.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:dele).and_respond("421 Service not available, closing control connection.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:dele).and_respond("530 Not logged in.") - -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#delete" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the DELE command with the passed filename to the server" do + @ftp.delete("test.file") + @ftp.last_response.should == "250 Requested file action okay, completed. (DELE test.file)\n" + end + + it "raises a Net::FTPTempError when the response code is 450" do + @server.should_receive(:dele).and_respond("450 Requested file action not taken.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:dele).and_respond("550 Requested action not taken.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:dele).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:dele).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:dele).and_respond("502 Command not implemented.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:dele).and_respond("421 Service not available, closing control connection.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:dele).and_respond("530 Not logged in.") + -> { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/dir_spec.rb b/ruby/spec/ruby/library/net/ftp/dir_spec.rb index 47ac7b8d9..dce50a5ac 100644 --- a/ruby/spec/ruby/library/net/ftp/dir_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/dir_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/list' -describe "Net::FTP#dir" do - it_behaves_like :net_ftp_list, :dir +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/list' + + describe "Net::FTP#dir" do + it_behaves_like :net_ftp_list, :dir + end end diff --git a/ruby/spec/ruby/library/net/ftp/get_spec.rb b/ruby/spec/ruby/library/net/ftp/get_spec.rb index c4672b55a..892b30061 100644 --- a/ruby/spec/ruby/library/net/ftp/get_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/get_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/gettextfile' -require_relative 'shared/getbinaryfile' -describe "Net::FTP#get (binary mode)" do - before :each do - @binary_mode = true - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/gettextfile' + require_relative 'shared/getbinaryfile' - it_behaves_like :net_ftp_getbinaryfile, :get -end + describe "Net::FTP#get (binary mode)" do + before :each do + @binary_mode = true + end -describe "Net::FTP#get (text mode)" do - before :each do - @binary_mode = false + it_behaves_like :net_ftp_getbinaryfile, :get end - it_behaves_like :net_ftp_gettextfile, :get + describe "Net::FTP#get (text mode)" do + before :each do + @binary_mode = false + end + + it_behaves_like :net_ftp_gettextfile, :get + end end diff --git a/ruby/spec/ruby/library/net/ftp/getbinaryfile_spec.rb b/ruby/spec/ruby/library/net/ftp/getbinaryfile_spec.rb index 155851b53..c5abdd67e 100644 --- a/ruby/spec/ruby/library/net/ftp/getbinaryfile_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/getbinaryfile_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/getbinaryfile' -describe "Net::FTP#getbinaryfile" do - it_behaves_like :net_ftp_getbinaryfile, :getbinaryfile +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/getbinaryfile' + + describe "Net::FTP#getbinaryfile" do + it_behaves_like :net_ftp_getbinaryfile, :getbinaryfile + end end diff --git a/ruby/spec/ruby/library/net/ftp/getdir_spec.rb b/ruby/spec/ruby/library/net/ftp/getdir_spec.rb index eea35ac13..8f6fca5bf 100644 --- a/ruby/spec/ruby/library/net/ftp/getdir_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/getdir_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'shared/pwd' -describe "Net::FTP#getdir" do - it_behaves_like :net_ftp_pwd, :getdir +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'shared/pwd' + + describe "Net::FTP#getdir" do + it_behaves_like :net_ftp_pwd, :getdir + end end diff --git a/ruby/spec/ruby/library/net/ftp/gettextfile_spec.rb b/ruby/spec/ruby/library/net/ftp/gettextfile_spec.rb index 79395ae00..e272ae73b 100644 --- a/ruby/spec/ruby/library/net/ftp/gettextfile_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/gettextfile_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/gettextfile' -describe "Net::FTP#gettextfile" do - it_behaves_like :net_ftp_gettextfile, :gettextfile +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/gettextfile' + + describe "Net::FTP#gettextfile" do + it_behaves_like :net_ftp_gettextfile, :gettextfile + end end diff --git a/ruby/spec/ruby/library/net/ftp/help_spec.rb b/ruby/spec/ruby/library/net/ftp/help_spec.rb index d2e9fe7ee..9b15f42ed 100644 --- a/ruby/spec/ruby/library/net/ftp/help_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/help_spec.rb @@ -1,66 +1,69 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#help" do - def with_connection - yield - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once + describe "Net::FTP#help" do + def with_connection + yield + end - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "writes the HELP command to the server" do - @ftp.help - @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns the server's response" do - @ftp.help.should == "211 System status, or system help reply. (HELP)\n" - end + it "writes the HELP command to the server" do + @ftp.help + @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" + end - it "writes the HELP command with an optional parameter to the socket" do - @ftp.help("some parameter").should == "211 System status, or system help reply. (HELP some parameter)\n" - end + it "returns the server's response" do + @ftp.help.should == "211 System status, or system help reply. (HELP)\n" + end - it "does not raise any error when the response code is 211" do - @server.should_receive(:help).and_respond("211 System status, or system help reply.") - -> { @ftp.help }.should_not raise_error - end + it "writes the HELP command with an optional parameter to the socket" do + @ftp.help("some parameter").should == "211 System status, or system help reply. (HELP some parameter)\n" + end - it "does not raise any error when the response code is 214" do - @server.should_receive(:help).and_respond("214 Help message.") - -> { @ftp.help }.should_not raise_error - end + it "does not raise any error when the response code is 211" do + @server.should_receive(:help).and_respond("211 System status, or system help reply.") + -> { @ftp.help }.should_not raise_error + end - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.help }.should raise_error(Net::FTPPermError) - end + it "does not raise any error when the response code is 214" do + @server.should_receive(:help).and_respond("214 Help message.") + -> { @ftp.help }.should_not raise_error + end - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:help).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.help }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.help }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:help).and_respond("502 Command not implemented.") - -> { @ftp.help }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:help).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.help }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:help).and_respond("502 Command not implemented.") + -> { @ftp.help }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:help).and_respond("421 Service not available, closing control connection.") - -> { @ftp.help }.should raise_error(Net::FTPTempError) + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:help).and_respond("421 Service not available, closing control connection.") + -> { @ftp.help }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/initialize_spec.rb b/ruby/spec/ruby/library/net/ftp/initialize_spec.rb index 507320e49..80f71a916 100644 --- a/ruby/spec/ruby/library/net/ftp/initialize_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/initialize_spec.rb @@ -1,404 +1,405 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' - -describe "Net::FTP#initialize" do - before :each do - @ftp = Net::FTP.allocate - @ftp.stub!(:connect) - @port_args = [] - ruby_version_is "2.5" do - @port_args << 21 - end - end - - it "is private" do - Net::FTP.should have_private_instance_method(:initialize) - end - it "sets self into binary mode" do - @ftp.binary.should be_nil - @ftp.send(:initialize) - @ftp.binary.should be_true - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - it "sets self into active mode" do - @ftp.passive.should be_nil - @ftp.send(:initialize) - @ftp.passive.should be_false - end + describe "Net::FTP#initialize" do + before :each do + @ftp = Net::FTP.allocate + @ftp.stub!(:connect) + @port_args = [] + @port_args << 21 + end - it "sets self into non-debug mode" do - @ftp.debug_mode.should be_nil - @ftp.send(:initialize) - @ftp.debug_mode.should be_false - end + it "is private" do + Net::FTP.should have_private_instance_method(:initialize) + end - it "sets self to not resume file uploads/downloads" do - @ftp.resume.should be_nil - @ftp.send(:initialize) - @ftp.resume.should be_false - end + it "sets self into binary mode" do + @ftp.binary.should be_nil + @ftp.send(:initialize) + @ftp.binary.should be_true + end - describe "when passed no arguments" do - it "does not try to connect" do - @ftp.should_not_receive(:connect) + it "sets self into active mode" do + @ftp.passive.should be_nil @ftp.send(:initialize) + @ftp.passive.should be_false end - end - describe "when passed host" do - it "tries to connect to the passed host" do - @ftp.should_receive(:connect).with("localhost", *@port_args) - @ftp.send(:initialize, "localhost") + it "sets self into non-debug mode" do + @ftp.debug_mode.should be_nil + @ftp.send(:initialize) + @ftp.debug_mode.should be_false end - end - describe "when passed host, user" do - it "tries to connect to the passed host" do - @ftp.should_receive(:connect).with("localhost", *@port_args) - @ftp.send(:initialize, "localhost") + it "sets self to not resume file uploads/downloads" do + @ftp.resume.should be_nil + @ftp.send(:initialize) + @ftp.resume.should be_false end - it "tries to login with the passed username" do - @ftp.should_receive(:login).with("rubyspec", nil, nil) - @ftp.send(:initialize, "localhost", "rubyspec") + describe "when passed no arguments" do + it "does not try to connect" do + @ftp.should_not_receive(:connect) + @ftp.send(:initialize) + end end - end - describe "when passed host, user, password" do - it "tries to connect to the passed host" do - @ftp.should_receive(:connect).with("localhost", *@port_args) - @ftp.send(:initialize, "localhost") + describe "when passed host" do + it "tries to connect to the passed host" do + @ftp.should_receive(:connect).with("localhost", *@port_args) + @ftp.send(:initialize, "localhost") + end end - it "tries to login with the passed username and password" do - @ftp.should_receive(:login).with("rubyspec", "rocks", nil) - @ftp.send(:initialize, "localhost", "rubyspec", "rocks") + describe "when passed host, user" do + it "tries to connect to the passed host" do + @ftp.should_receive(:connect).with("localhost", *@port_args) + @ftp.send(:initialize, "localhost") + end + + it "tries to login with the passed username" do + @ftp.should_receive(:login).with("rubyspec", nil, nil) + @ftp.send(:initialize, "localhost", "rubyspec") + end end - end - describe "when passed host, user" do - it "tries to connect to the passed host" do - @ftp.should_receive(:connect).with("localhost", *@port_args) - @ftp.send(:initialize, "localhost") + describe "when passed host, user, password" do + it "tries to connect to the passed host" do + @ftp.should_receive(:connect).with("localhost", *@port_args) + @ftp.send(:initialize, "localhost") + end + + it "tries to login with the passed username and password" do + @ftp.should_receive(:login).with("rubyspec", "rocks", nil) + @ftp.send(:initialize, "localhost", "rubyspec", "rocks") + end end - it "tries to login with the passed username, password and account" do - @ftp.should_receive(:login).with("rubyspec", "rocks", "account") - @ftp.send(:initialize, "localhost", "rubyspec", "rocks", "account") + describe "when passed host, user" do + it "tries to connect to the passed host" do + @ftp.should_receive(:connect).with("localhost", *@port_args) + @ftp.send(:initialize, "localhost") + end + + it "tries to login with the passed username, password and account" do + @ftp.should_receive(:login).with("rubyspec", "rocks", "account") + @ftp.send(:initialize, "localhost", "rubyspec", "rocks", "account") + end end - end - before :each do - @ftp.stub!(:login) - end + before :each do + @ftp.stub!(:login) + end - describe 'when the host' do - describe 'is set' do - describe 'and port option' do - describe 'is set' do - it 'tries to connect to the host on the specified port' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ port: 8080 }) - @ftp.should_receive(:connect).with('localhost', 8080) + describe 'when the host' do + describe 'is set' do + describe 'and port option' do + describe 'is set' do + it 'tries to connect to the host on the specified port' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ port: 8080 }) + @ftp.should_receive(:connect).with('localhost', 8080) - @ftp.send(:initialize, 'localhost', options) + @ftp.send(:initialize, 'localhost', options) + end end - end - describe 'is not set' do - it 'tries to connect to the host without a port' do - @ftp.should_receive(:connect).with("localhost", *@port_args) + describe 'is not set' do + it 'tries to connect to the host without a port' do + @ftp.should_receive(:connect).with("localhost", *@port_args) - @ftp.send(:initialize, 'localhost') + @ftp.send(:initialize, 'localhost') + end end end - end - describe 'when the username option' do - describe 'is set' do - describe 'and the password option' do - describe 'is set' do - describe 'and the account option' do - describe 'is set' do - it 'tries to log in with the supplied parameters' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ username: 'a', password: 'topsecret', account: 'b' }) - @ftp.should_receive(:login).with('a', 'topsecret', 'b') - - @ftp.send(:initialize, 'localhost', options) + describe 'when the username option' do + describe 'is set' do + describe 'and the password option' do + describe 'is set' do + describe 'and the account option' do + describe 'is set' do + it 'tries to log in with the supplied parameters' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ username: 'a', password: 'topsecret', account: 'b' }) + @ftp.should_receive(:login).with('a', 'topsecret', 'b') + + @ftp.send(:initialize, 'localhost', options) + end end - end - describe 'is unset' do - it 'tries to log in with the supplied parameters' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ username: 'a', password: 'topsecret' }) - @ftp.should_receive(:login).with('a', 'topsecret', nil) + describe 'is unset' do + it 'tries to log in with the supplied parameters' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ username: 'a', password: 'topsecret' }) + @ftp.should_receive(:login).with('a', 'topsecret', nil) - @ftp.send(:initialize, 'localhost', options) + @ftp.send(:initialize, 'localhost', options) + end end end end - end - describe 'is unset' do - describe 'and the account option' do - describe 'is set' do - it 'tries to log in with the supplied parameters' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ username: 'a', account: 'b' }) - @ftp.should_receive(:login).with('a', nil, 'b') + describe 'is unset' do + describe 'and the account option' do + describe 'is set' do + it 'tries to log in with the supplied parameters' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ username: 'a', account: 'b' }) + @ftp.should_receive(:login).with('a', nil, 'b') - @ftp.send(:initialize, 'localhost', options) + @ftp.send(:initialize, 'localhost', options) + end end - end - describe 'is unset' do - it 'tries to log in with the supplied parameters' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ username: 'a'}) - @ftp.should_receive(:login).with('a', nil, nil) + describe 'is unset' do + it 'tries to log in with the supplied parameters' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ username: 'a'}) + @ftp.should_receive(:login).with('a', nil, nil) - @ftp.send(:initialize, 'localhost', options) + @ftp.send(:initialize, 'localhost', options) + end end end end end end - end - describe 'is not set' do - it 'does not try to log in' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({}) - @ftp.should_not_receive(:login) + describe 'is not set' do + it 'does not try to log in' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({}) + @ftp.should_not_receive(:login) - @ftp.send(:initialize, 'localhost', options) + @ftp.send(:initialize, 'localhost', options) + end end end end - end - describe 'is unset' do - it 'does not try to connect' do - @ftp.should_not_receive(:connect) + describe 'is unset' do + it 'does not try to connect' do + @ftp.should_not_receive(:connect) - @ftp.send(:initialize) - end + @ftp.send(:initialize) + end - it 'does not try to log in' do - @ftp.should_not_receive(:login) + it 'does not try to log in' do + @ftp.should_not_receive(:login) - @ftp.send(:initialize) + @ftp.send(:initialize) + end end end - end - describe 'when the passive option' do - describe 'is set' do - describe 'to true' do - it 'sets passive to true' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ passive: true }) + describe 'when the passive option' do + describe 'is set' do + describe 'to true' do + it 'sets passive to true' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ passive: true }) - @ftp.send(:initialize, nil, options) - @ftp.passive.should == true + @ftp.send(:initialize, nil, options) + @ftp.passive.should == true + end + end + + describe 'to false' do + it 'sets passive to false' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ passive: false }) + + @ftp.send(:initialize, nil, options) + @ftp.passive.should == false + end end end - describe 'to false' do + describe 'is unset' do it 'sets passive to false' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ passive: false }) - - @ftp.send(:initialize, nil, options) + @ftp.send(:initialize) @ftp.passive.should == false end end end - describe 'is unset' do - it 'sets passive to false' do - @ftp.send(:initialize) - @ftp.passive.should == false - end - end - end + describe 'when the debug_mode option' do + describe 'is set' do + describe 'to true' do + it 'sets debug_mode to true' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ debug_mode: true }) - describe 'when the debug_mode option' do - describe 'is set' do - describe 'to true' do - it 'sets debug_mode to true' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ debug_mode: true }) + @ftp.send(:initialize, nil, options) + @ftp.debug_mode.should == true + end + end - @ftp.send(:initialize, nil, options) - @ftp.debug_mode.should == true + describe 'to false' do + it 'sets debug_mode to false' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ debug_mode: false }) + + @ftp.send(:initialize, nil, options) + @ftp.debug_mode.should == false + end end end - describe 'to false' do + describe 'is unset' do it 'sets debug_mode to false' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ debug_mode: false }) - - @ftp.send(:initialize, nil, options) + @ftp.send(:initialize) @ftp.debug_mode.should == false end end end - describe 'is unset' do - it 'sets debug_mode to false' do - @ftp.send(:initialize) - @ftp.debug_mode.should == false - end - end - end - - describe 'when the open_timeout option' do - describe 'is set' do - it 'sets open_timeout to the specified value' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ open_timeout: 42 }) + describe 'when the open_timeout option' do + describe 'is set' do + it 'sets open_timeout to the specified value' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ open_timeout: 42 }) - @ftp.send(:initialize, nil, options) - @ftp.open_timeout.should == 42 + @ftp.send(:initialize, nil, options) + @ftp.open_timeout.should == 42 + end end - end - describe 'is not set' do - it 'sets open_timeout to nil' do - @ftp.send(:initialize) - @ftp.open_timeout.should == nil + describe 'is not set' do + it 'sets open_timeout to nil' do + @ftp.send(:initialize) + @ftp.open_timeout.should == nil + end end end - end - describe 'when the read_timeout option' do - describe 'is set' do - it 'sets read_timeout to the specified value' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ read_timeout: 100 }) + describe 'when the read_timeout option' do + describe 'is set' do + it 'sets read_timeout to the specified value' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ read_timeout: 100 }) - @ftp.send(:initialize, nil, options) - @ftp.read_timeout.should == 100 + @ftp.send(:initialize, nil, options) + @ftp.read_timeout.should == 100 + end end - end - describe 'is not set' do - it 'sets read_timeout to the default value' do - @ftp.send(:initialize) - @ftp.read_timeout.should == 60 + describe 'is not set' do + it 'sets read_timeout to the default value' do + @ftp.send(:initialize) + @ftp.read_timeout.should == 60 + end end end - end - describe 'when the ssl_handshake_timeout option' do - describe 'is set' do - it 'sets ssl_handshake_timeout to the specified value' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ ssl_handshake_timeout: 23 }) + describe 'when the ssl_handshake_timeout option' do + describe 'is set' do + it 'sets ssl_handshake_timeout to the specified value' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ ssl_handshake_timeout: 23 }) - @ftp.send(:initialize, nil, options) - @ftp.ssl_handshake_timeout.should == 23 + @ftp.send(:initialize, nil, options) + @ftp.ssl_handshake_timeout.should == 23 + end end - end - describe 'is not set' do - it 'sets ssl_handshake_timeout to nil' do - @ftp.send(:initialize) - @ftp.ssl_handshake_timeout.should == nil + describe 'is not set' do + it 'sets ssl_handshake_timeout to nil' do + @ftp.send(:initialize) + @ftp.ssl_handshake_timeout.should == nil + end end end - end - describe 'when the ssl option' do - describe 'is set' do - describe "and the ssl option's value is true" do - it 'initializes ssl_context to a blank SSLContext object' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ ssl: true }) + describe 'when the ssl option' do + describe 'is set' do + describe "and the ssl option's value is true" do + it 'initializes ssl_context to a blank SSLContext object' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ ssl: true }) - ssl_context = OpenSSL::SSL::SSLContext.allocate - ssl_context.stub!(:set_params) + ssl_context = OpenSSL::SSL::SSLContext.allocate + ssl_context.stub!(:set_params) - OpenSSL::SSL::SSLContext.should_receive(:new).and_return(ssl_context) - ssl_context.should_receive(:set_params).with({}) + OpenSSL::SSL::SSLContext.should_receive(:new).and_return(ssl_context) + ssl_context.should_receive(:set_params).with({}) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@ssl_context).should == ssl_context + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@ssl_context).should == ssl_context + end end - end - describe "and the ssl option's value is a hash" do - it 'initializes ssl_context to a configured SSLContext object' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ ssl: {key: 'value'} }) + describe "and the ssl option's value is a hash" do + it 'initializes ssl_context to a configured SSLContext object' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ ssl: {key: 'value'} }) - ssl_context = OpenSSL::SSL::SSLContext.allocate - ssl_context.stub!(:set_params) + ssl_context = OpenSSL::SSL::SSLContext.allocate + ssl_context.stub!(:set_params) - OpenSSL::SSL::SSLContext.should_receive(:new).and_return(ssl_context) - ssl_context.should_receive(:set_params).with({key: 'value'}) + OpenSSL::SSL::SSLContext.should_receive(:new).and_return(ssl_context) + ssl_context.should_receive(:set_params).with({key: 'value'}) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@ssl_context).should == ssl_context + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@ssl_context).should == ssl_context + end end - end - describe 'and private_data_connection' do - describe 'is set' do - it 'sets private_data_connection to that value' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ ssl: true, private_data_connection: 'true' }) + describe 'and private_data_connection' do + describe 'is set' do + it 'sets private_data_connection to that value' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ ssl: true, private_data_connection: 'true' }) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@private_data_connection).should == 'true' + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@private_data_connection).should == 'true' + end end - end - describe 'is not set' do - it 'sets private_data_connection to nil' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ ssl: true }) + describe 'is not set' do + it 'sets private_data_connection to nil' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ ssl: true }) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@private_data_connection).should == true + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@private_data_connection).should == true + end end end end - end - describe 'is not set' do - it 'sets ssl_context to nil' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({}) + describe 'is not set' do + it 'sets ssl_context to nil' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({}) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@ssl_context).should == nil - end + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@ssl_context).should == nil + end - describe 'private_data_connection' do - describe 'is set' do - it 'raises an ArgumentError' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({ private_data_connection: true }) + describe 'private_data_connection' do + describe 'is set' do + it 'raises an ArgumentError' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({ private_data_connection: true }) - -> { - @ftp.send(:initialize, nil, options) - }.should raise_error(ArgumentError, /private_data_connection can be set to true only when ssl is enabled/) + -> { + @ftp.send(:initialize, nil, options) + }.should raise_error(ArgumentError, /private_data_connection can be set to true only when ssl is enabled/) + end end - end - describe 'is not set' do - it 'sets private_data_connection to false' do - options = mock('ftp initialize options') - options.should_receive(:to_hash).and_return({}) + describe 'is not set' do + it 'sets private_data_connection to false' do + options = mock('ftp initialize options') + options.should_receive(:to_hash).and_return({}) - @ftp.send(:initialize, nil, options) - @ftp.instance_variable_get(:@private_data_connection).should == false + @ftp.send(:initialize, nil, options) + @ftp.instance_variable_get(:@private_data_connection).should == false + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/last_response_code_spec.rb b/ruby/spec/ruby/library/net/ftp/last_response_code_spec.rb index 3eb20f7ad..86f2b9a69 100644 --- a/ruby/spec/ruby/library/net/ftp/last_response_code_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/last_response_code_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'shared/last_response_code' -require_relative 'fixtures/server' -describe "Net::FTP#last_response_code" do - it_behaves_like :net_ftp_last_response_code, :last_response_code +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'shared/last_response_code' + require_relative 'fixtures/server' + + describe "Net::FTP#last_response_code" do + it_behaves_like :net_ftp_last_response_code, :last_response_code + end end diff --git a/ruby/spec/ruby/library/net/ftp/last_response_spec.rb b/ruby/spec/ruby/library/net/ftp/last_response_spec.rb index ada665d59..1d29b9b73 100644 --- a/ruby/spec/ruby/library/net/ftp/last_response_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/last_response_spec.rb @@ -1,25 +1,28 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#last_response" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#last_response" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns the last response" do - @ftp.last_response.should == "220 Dummy FTP Server ready!\n" - @ftp.help - @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" + it "returns the last response" do + @ftp.last_response.should == "220 Dummy FTP Server ready!\n" + @ftp.help + @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" + end end end diff --git a/ruby/spec/ruby/library/net/ftp/lastresp_spec.rb b/ruby/spec/ruby/library/net/ftp/lastresp_spec.rb index 273e216e8..9d26efb8f 100644 --- a/ruby/spec/ruby/library/net/ftp/lastresp_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/lastresp_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'shared/last_response_code' -require_relative 'fixtures/server' -describe "Net::FTP#lastresp" do - it_behaves_like :net_ftp_last_response_code, :lastresp +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'shared/last_response_code' + require_relative 'fixtures/server' + + describe "Net::FTP#lastresp" do + it_behaves_like :net_ftp_last_response_code, :lastresp + end end diff --git a/ruby/spec/ruby/library/net/ftp/list_spec.rb b/ruby/spec/ruby/library/net/ftp/list_spec.rb index 617517292..6cffafeb4 100644 --- a/ruby/spec/ruby/library/net/ftp/list_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/list_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/list' -describe "Net::FTP#list" do - it_behaves_like :net_ftp_list, :list +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/list' + + describe "Net::FTP#list" do + it_behaves_like :net_ftp_list, :list + end end diff --git a/ruby/spec/ruby/library/net/ftp/login_spec.rb b/ruby/spec/ruby/library/net/ftp/login_spec.rb index 46736851e..981b43908 100644 --- a/ruby/spec/ruby/library/net/ftp/login_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/login_spec.rb @@ -1,195 +1,198 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#login" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - describe "when passed no arguments" do - it "sends the USER command with 'anonymous' as name to the server" do - @ftp.login - @server.login_user.should == "anonymous" - end - - it "sends 'anonymous@' as a password when required" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @ftp.login - @server.login_pass.should == "anonymous@" - end - - it "raises a Net::FTPReplyError when the server requests an account" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @server.should_receive(:pass).and_respond("332 Need account for login.") - -> { @ftp.login }.should raise_error(Net::FTPReplyError) - end - end - - describe "when passed name" do - it "sends the USER command with the passed name to the server" do - @ftp.login("rubyspec") - @server.login_user.should == "rubyspec" - end - - it "raises a Net::FTPReplyError when the server requests a password, but none was given" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - -> { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError) - end - - it "raises a Net::FTPReplyError when the server requests an account, but none was given" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @server.should_receive(:pass).and_respond("332 Need account for login.") - -> { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError) - end - end - - describe "when passed name, password" do - it "sends the USER command with the passed name to the server" do - @ftp.login("rubyspec", "rocks") - @server.login_user.should == "rubyspec" - end - - it "sends the passed password when required" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @ftp.login("rubyspec", "rocks") - @server.login_pass.should == "rocks" - end - - it "raises a Net::FTPReplyError when the server requests an account" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @server.should_receive(:pass).and_respond("332 Need account for login.") - -> { @ftp.login("rubyspec", "rocks") }.should raise_error(Net::FTPReplyError) - end - end - - describe "when passed name, password, account" do - it "sends the USER command with the passed name to the server" do - @ftp.login("rubyspec", "rocks", "account") - @server.login_user.should == "rubyspec" - end - - it "sends the passed password when required" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @ftp.login("rubyspec", "rocks", "account") - @server.login_pass.should == "rocks" - end - - it "sends the passed account when required" do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @server.should_receive(:pass).and_respond("332 Need account for login.") - @ftp.login("rubyspec", "rocks", "account") - @server.login_acct.should == "account" - end - end - - describe "when the USER command fails" do - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:user).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:user).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:user).and_respond("502 Command not implemented.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:user).and_respond("421 Service not available, closing control connection.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:user).and_respond("530 Not logged in.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - end - - describe "when the PASS command fails" do + describe "Net::FTP#login" do before :each do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - end - - it "does not raise an Error when the response code is 202" do - @server.should_receive(:pass).and_respond("202 Command not implemented, superfluous at this site.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:pass).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:pass).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:pass).and_respond("502 Command not implemented.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:pass).and_respond("421 Service not available, closing control connection.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:pass).and_respond("530 Not logged in.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - end - - describe "when the ACCT command fails" do - before :each do - @server.should_receive(:user).and_respond("331 User name okay, need password.") - @server.should_receive(:pass).and_respond("332 Need account for login.") - end - - it "does not raise an Error when the response code is 202" do - @server.should_receive(:acct).and_respond("202 Command not implemented, superfluous at this site.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:acct).and_respond("502 Command not implemented.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:acct).and_respond("530 Not logged in.") - -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + describe "when passed no arguments" do + it "sends the USER command with 'anonymous' as name to the server" do + @ftp.login + @server.login_user.should == "anonymous" + end + + it "sends 'anonymous@' as a password when required" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @ftp.login + @server.login_pass.should == "anonymous@" + end + + it "raises a Net::FTPReplyError when the server requests an account" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @server.should_receive(:pass).and_respond("332 Need account for login.") + -> { @ftp.login }.should raise_error(Net::FTPReplyError) + end + end + + describe "when passed name" do + it "sends the USER command with the passed name to the server" do + @ftp.login("rubyspec") + @server.login_user.should == "rubyspec" + end + + it "raises a Net::FTPReplyError when the server requests a password, but none was given" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + -> { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError) + end + + it "raises a Net::FTPReplyError when the server requests an account, but none was given" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @server.should_receive(:pass).and_respond("332 Need account for login.") + -> { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError) + end + end + + describe "when passed name, password" do + it "sends the USER command with the passed name to the server" do + @ftp.login("rubyspec", "rocks") + @server.login_user.should == "rubyspec" + end + + it "sends the passed password when required" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @ftp.login("rubyspec", "rocks") + @server.login_pass.should == "rocks" + end + + it "raises a Net::FTPReplyError when the server requests an account" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @server.should_receive(:pass).and_respond("332 Need account for login.") + -> { @ftp.login("rubyspec", "rocks") }.should raise_error(Net::FTPReplyError) + end + end + + describe "when passed name, password, account" do + it "sends the USER command with the passed name to the server" do + @ftp.login("rubyspec", "rocks", "account") + @server.login_user.should == "rubyspec" + end + + it "sends the passed password when required" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @ftp.login("rubyspec", "rocks", "account") + @server.login_pass.should == "rocks" + end + + it "sends the passed account when required" do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @server.should_receive(:pass).and_respond("332 Need account for login.") + @ftp.login("rubyspec", "rocks", "account") + @server.login_acct.should == "account" + end + end + + describe "when the USER command fails" do + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:user).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:user).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:user).and_respond("502 Command not implemented.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:user).and_respond("421 Service not available, closing control connection.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:user).and_respond("530 Not logged in.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + end + + describe "when the PASS command fails" do + before :each do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + end + + it "does not raise an Error when the response code is 202" do + @server.should_receive(:pass).and_respond("202 Command not implemented, superfluous at this site.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:pass).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:pass).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:pass).and_respond("502 Command not implemented.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:pass).and_respond("421 Service not available, closing control connection.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:pass).and_respond("530 Not logged in.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + end + + describe "when the ACCT command fails" do + before :each do + @server.should_receive(:user).and_respond("331 User name okay, need password.") + @server.should_receive(:pass).and_respond("332 Need account for login.") + end + + it "does not raise an Error when the response code is 202" do + @server.should_receive(:acct).and_respond("202 Command not implemented, superfluous at this site.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:acct).and_respond("502 Command not implemented.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:acct).and_respond("530 Not logged in.") + -> { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError) + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/ls_spec.rb b/ruby/spec/ruby/library/net/ftp/ls_spec.rb index e729eb948..f26251586 100644 --- a/ruby/spec/ruby/library/net/ftp/ls_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/ls_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/list' -describe "Net::FTP#ls" do - it_behaves_like :net_ftp_list, :ls +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/list' + + describe "Net::FTP#ls" do + it_behaves_like :net_ftp_list, :ls + end end diff --git a/ruby/spec/ruby/library/net/ftp/mdtm_spec.rb b/ruby/spec/ruby/library/net/ftp/mdtm_spec.rb index b74cf8d3c..ea55533c4 100644 --- a/ruby/spec/ruby/library/net/ftp/mdtm_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/mdtm_spec.rb @@ -1,38 +1,41 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#mdtm" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#mdtm" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the MDTM with the passed filename command to the server" do - @ftp.mdtm("test.file") - @ftp.last_response.should == "213 19980705132316\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns the last modification time of the passed file" do - @ftp.mdtm("test.file").should == "19980705132316" - end + it "sends the MDTM with the passed filename command to the server" do + @ftp.mdtm("test.file") + @ftp.last_response.should == "213 19980705132316\n" + end - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:mdtm).and_respond("550 Requested action not taken.") - -> { @ftp.mdtm("test.file") }.should raise_error(Net::FTPPermError) - end + it "returns the last modification time of the passed file" do + @ftp.mdtm("test.file").should == "19980705132316" + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:mdtm).and_respond("550 Requested action not taken.") + -> { @ftp.mdtm("test.file") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.") - -> { @ftp.mdtm("test.file") }.should raise_error(Net::FTPTempError) + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.") + -> { @ftp.mdtm("test.file") }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/mkdir_spec.rb b/ruby/spec/ruby/library/net/ftp/mkdir_spec.rb index 7dc45b571..2cb437a07 100644 --- a/ruby/spec/ruby/library/net/ftp/mkdir_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/mkdir_spec.rb @@ -1,61 +1,64 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#mkdir" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#mkdir" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the MKD command with the passed pathname to the server" do - @ftp.mkdir("test.folder") - @ftp.last_response.should == %{257 "test.folder" created.\n} - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns the path to the newly created directory" do - @ftp.mkdir("test.folder").should == "test.folder" - @ftp.mkdir("/absolute/path/to/test.folder").should == "/absolute/path/to/test.folder" - @ftp.mkdir("relative/path/to/test.folder").should == "relative/path/to/test.folder" - @ftp.mkdir('/usr/dm/foo"bar').should == '/usr/dm/foo"bar' - end + it "sends the MKD command with the passed pathname to the server" do + @ftp.mkdir("test.folder") + @ftp.last_response.should == %{257 "test.folder" created.\n} + end - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:mkd).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) - end + it "returns the path to the newly created directory" do + @ftp.mkdir("test.folder").should == "test.folder" + @ftp.mkdir("/absolute/path/to/test.folder").should == "/absolute/path/to/test.folder" + @ftp.mkdir("relative/path/to/test.folder").should == "relative/path/to/test.folder" + @ftp.mkdir('/usr/dm/foo"bar').should == '/usr/dm/foo"bar' + end - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:mkd).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:mkd).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:mkd).and_respond("502 Command not implemented.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:mkd).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:mkd).and_respond("421 Service not available, closing control connection.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPTempError) - end + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:mkd).and_respond("502 Command not implemented.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:mkd).and_respond("530 Not logged in.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:mkd).and_respond("421 Service not available, closing control connection.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:mkd).and_respond("530 Not logged in.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:mkd).and_respond("550 Requested action not taken.") - -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:mkd).and_respond("550 Requested action not taken.") + -> { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/mtime_spec.rb b/ruby/spec/ruby/library/net/ftp/mtime_spec.rb index 0f6cc1ba2..7265667a5 100644 --- a/ruby/spec/ruby/library/net/ftp/mtime_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/mtime_spec.rb @@ -1,50 +1,53 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#mtime" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#mtime" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the MDTM with the passed filename command to the server" do - @ftp.mtime("test.file") - @ftp.last_response.should == "213 19980705132316\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - describe "when passed filename" do - it "returns the last modification time of the passed file as a Time object in the local time" do - @ftp.mtime("test.file").should == Time.gm("1998", "07", "05", "13", "23", "16") + it "sends the MDTM with the passed filename command to the server" do + @ftp.mtime("test.file") + @ftp.last_response.should == "213 19980705132316\n" end - end - describe "when passed filename, local_time" do - it "returns the last modification time as a Time object in UTC when local_time is true" do - @ftp.mtime("test.file", true).should == Time.local("1998", "07", "05", "13", "23", "16") + describe "when passed filename" do + it "returns the last modification time of the passed file as a Time object in the local time" do + @ftp.mtime("test.file").should == Time.gm("1998", "07", "05", "13", "23", "16") + end end - it "returns the last modification time as a Time object in the local time when local_time is false" do - @ftp.mtime("test.file", false).should == Time.gm("1998", "07", "05", "13", "23", "16") + describe "when passed filename, local_time" do + it "returns the last modification time as a Time object in UTC when local_time is true" do + @ftp.mtime("test.file", true).should == Time.local("1998", "07", "05", "13", "23", "16") + end + + it "returns the last modification time as a Time object in the local time when local_time is false" do + @ftp.mtime("test.file", false).should == Time.gm("1998", "07", "05", "13", "23", "16") + end end - end - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:mdtm).and_respond("550 Requested action not taken.") - -> { @ftp.mtime("test.file") }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:mdtm).and_respond("550 Requested action not taken.") + -> { @ftp.mtime("test.file") }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.") - -> { @ftp.mtime("test.file") }.should raise_error(Net::FTPTempError) + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.") + -> { @ftp.mtime("test.file") }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/nlst_spec.rb b/ruby/spec/ruby/library/net/ftp/nlst_spec.rb index 34384fb8c..0de84b3a7 100644 --- a/ruby/spec/ruby/library/net/ftp/nlst_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/nlst_spec.rb @@ -1,92 +1,95 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#nlst" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.passive = false - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + describe "Net::FTP#nlst" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - describe "when passed no arguments" do - it "returns an Array containing a list of files in the current dir" do - @ftp.nlst.should == ["last_response_code.rb", "list.rb", "pwd.rb"] - @ftp.last_response.should == "226 transfer complete (NLST)\n" + @ftp = Net::FTP.new + @ftp.passive = false + @ftp.connect(@server.hostname, @server.server_port) end - end - describe "when passed dir" do - it "returns an Array containing a list of files in the passed dir" do - @ftp.nlst("test.folder").should == ["last_response_code.rb", "list.rb", "pwd.rb"] - @ftp.last_response.should == "226 transfer complete (NLST test.folder)\n" + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop end - end - describe "when the NLST command fails" do - it "raises a Net::FTPTempError when the response code is 450" do - @server.should_receive(:nlst).and_respond("450 Requested file action not taken..") - -> { @ftp.nlst }.should raise_error(Net::FTPTempError) + describe "when passed no arguments" do + it "returns an Array containing a list of files in the current dir" do + @ftp.nlst.should == ["last_response_code.rb", "list.rb", "pwd.rb"] + @ftp.last_response.should == "226 transfer complete (NLST)\n" + end end - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:nlst).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + describe "when passed dir" do + it "returns an Array containing a list of files in the passed dir" do + @ftp.nlst("test.folder").should == ["last_response_code.rb", "list.rb", "pwd.rb"] + @ftp.last_response.should == "226 transfer complete (NLST test.folder)\n" + end end - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:nlst).and_respond("501 Syntax error, command unrecognized.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) - end + describe "when the NLST command fails" do + it "raises a Net::FTPTempError when the response code is 450" do + @server.should_receive(:nlst).and_respond("450 Requested file action not taken..") + -> { @ftp.nlst }.should raise_error(Net::FTPTempError) + end - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:nlst).and_respond("502 Command not implemented.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:nlst).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:nlst).and_respond("421 Service not available, closing control connection.") - -> { @ftp.nlst }.should raise_error(Net::FTPTempError) - end + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:nlst).and_respond("501 Syntax error, command unrecognized.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:nlst).and_respond("530 Not logged in.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) - end - end + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:nlst).and_respond("502 Command not implemented.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end - describe "when opening the data port fails" do - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.") - @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:nlst).and_respond("421 Service not available, closing control connection.") + -> { @ftp.nlst }.should raise_error(Net::FTPTempError) + end - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.") - @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:nlst).and_respond("530 Not logged in.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.") - @server.should_receive(:port).and_respond("421 Service not available, closing control connection.") - -> { @ftp.nlst }.should raise_error(Net::FTPTempError) - end + describe "when opening the data port fails" do + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.") + @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.") + @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.") + @server.should_receive(:port).and_respond("421 Service not available, closing control connection.") + -> { @ftp.nlst }.should raise_error(Net::FTPTempError) + end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:eprt).and_respond("530 Not logged in.") - @server.should_receive(:port).and_respond("530 Not logged in.") - -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:eprt).and_respond("530 Not logged in.") + @server.should_receive(:port).and_respond("530 Not logged in.") + -> { @ftp.nlst }.should raise_error(Net::FTPPermError) + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/noop_spec.rb b/ruby/spec/ruby/library/net/ftp/noop_spec.rb index 070750ced..71011d4af 100644 --- a/ruby/spec/ruby/library/net/ftp/noop_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/noop_spec.rb @@ -1,38 +1,41 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#noop" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#noop" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the NOOP command to the server" do - @ftp.noop - @ftp.last_response.should == "200 Command okay. (NOOP)\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns nil" do - @ftp.noop.should be_nil - end + it "sends the NOOP command to the server" do + @ftp.noop + @ftp.last_response.should == "200 Command okay. (NOOP)\n" + end - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:noop).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.noop }.should raise_error(Net::FTPPermError) - end + it "returns nil" do + @ftp.noop.should be_nil + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:noop).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.noop }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:noop).and_respond("421 Service not available, closing control connection.") - -> { @ftp.noop }.should raise_error(Net::FTPTempError) + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:noop).and_respond("421 Service not available, closing control connection.") + -> { @ftp.noop }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/open_spec.rb b/ruby/spec/ruby/library/net/ftp/open_spec.rb index 7be02ff37..89187b980 100644 --- a/ruby/spec/ruby/library/net/ftp/open_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/open_spec.rb @@ -1,55 +1,58 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP.open" do - before :each do - @ftp = mock("Net::FTP instance") - Net::FTP.stub!(:new).and_return(@ftp) - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - describe "when passed no block" do - it "returns a new Net::FTP instance" do - Net::FTP.open("localhost").should equal(@ftp) + describe "Net::FTP.open" do + before :each do + @ftp = mock("Net::FTP instance") + Net::FTP.stub!(:new).and_return(@ftp) end - it "passes the passed arguments down to Net::FTP.new" do - Net::FTP.should_receive(:new).with("localhost", "user", "password", "account") - Net::FTP.open("localhost", "user", "password", "account") - end - end + describe "when passed no block" do + it "returns a new Net::FTP instance" do + Net::FTP.open("localhost").should equal(@ftp) + end - describe "when passed a block" do - before :each do - @ftp.stub!(:close) + it "passes the passed arguments down to Net::FTP.new" do + Net::FTP.should_receive(:new).with("localhost", "user", "password", "account") + Net::FTP.open("localhost", "user", "password", "account") + end end - it "yields a new Net::FTP instance to the passed block" do - yielded = false - Net::FTP.open("localhost") do |ftp| - yielded = true - ftp.should equal(@ftp) + describe "when passed a block" do + before :each do + @ftp.stub!(:close) end - yielded.should be_true - end - it "closes the Net::FTP instance after yielding" do - Net::FTP.open("localhost") do |ftp| - ftp.should_receive(:close) + it "yields a new Net::FTP instance to the passed block" do + yielded = false + Net::FTP.open("localhost") do |ftp| + yielded = true + ftp.should equal(@ftp) + end + yielded.should be_true end - end - it "closes the Net::FTP instance even if an exception is raised while yielding" do - begin + it "closes the Net::FTP instance after yielding" do Net::FTP.open("localhost") do |ftp| ftp.should_receive(:close) - raise ArgumentError, "some exception" end - rescue ArgumentError end - end - it "returns the block's return value" do - Net::FTP.open("localhost") { :test }.should == :test + it "closes the Net::FTP instance even if an exception is raised while yielding" do + begin + Net::FTP.open("localhost") do |ftp| + ftp.should_receive(:close) + raise ArgumentError, "some exception" + end + rescue ArgumentError + end + end + + it "returns the block's return value" do + Net::FTP.open("localhost") { :test }.should == :test + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/passive_spec.rb b/ruby/spec/ruby/library/net/ftp/passive_spec.rb index e8db030cb..f9c34efb7 100644 --- a/ruby/spec/ruby/library/net/ftp/passive_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/passive_spec.rb @@ -1,28 +1,31 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#passive" do - it "returns true when self is in passive mode" do - ftp = Net::FTP.new - ftp.passive.should be_false +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - ftp.passive = true - ftp.passive.should be_true - end + describe "Net::FTP#passive" do + it "returns true when self is in passive mode" do + ftp = Net::FTP.new + ftp.passive.should be_false + + ftp.passive = true + ftp.passive.should be_true + end - it "is the value of Net::FTP.default_value by default" do - ruby_exe(fixture(__FILE__, "passive.rb")).should == "true" + it "is the value of Net::FTP.default_value by default" do + ruby_exe(fixture(__FILE__, "passive.rb")).should == "true" + end end -end -describe "Net::FTP#passive=" do - it "sets self to passive mode when passed true" do - ftp = Net::FTP.new + describe "Net::FTP#passive=" do + it "sets self to passive mode when passed true" do + ftp = Net::FTP.new - ftp.passive = true - ftp.passive.should be_true + ftp.passive = true + ftp.passive.should be_true - ftp.passive = false - ftp.passive.should be_false + ftp.passive = false + ftp.passive.should be_false + end end end diff --git a/ruby/spec/ruby/library/net/ftp/put_spec.rb b/ruby/spec/ruby/library/net/ftp/put_spec.rb index f1f85b5d0..36ba6c196 100644 --- a/ruby/spec/ruby/library/net/ftp/put_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/put_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/puttextfile' -require_relative 'shared/putbinaryfile' -describe "Net::FTP#put (binary mode)" do - before :each do - @binary_mode = true - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/puttextfile' + require_relative 'shared/putbinaryfile' - it_behaves_like :net_ftp_putbinaryfile, :put -end + describe "Net::FTP#put (binary mode)" do + before :each do + @binary_mode = true + end -describe "Net::FTP#put (text mode)" do - before :each do - @binary_mode = false + it_behaves_like :net_ftp_putbinaryfile, :put end - it_behaves_like :net_ftp_puttextfile, :put + describe "Net::FTP#put (text mode)" do + before :each do + @binary_mode = false + end + + it_behaves_like :net_ftp_puttextfile, :put + end end diff --git a/ruby/spec/ruby/library/net/ftp/putbinaryfile_spec.rb b/ruby/spec/ruby/library/net/ftp/putbinaryfile_spec.rb index cb1c7bef5..6ced5246f 100644 --- a/ruby/spec/ruby/library/net/ftp/putbinaryfile_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/putbinaryfile_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/putbinaryfile' -describe "Net::FTP#putbinaryfile" do - it_behaves_like :net_ftp_putbinaryfile, :putbinaryfile +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/putbinaryfile' + + describe "Net::FTP#putbinaryfile" do + it_behaves_like :net_ftp_putbinaryfile, :putbinaryfile + end end diff --git a/ruby/spec/ruby/library/net/ftp/puttextfile_spec.rb b/ruby/spec/ruby/library/net/ftp/puttextfile_spec.rb index 00a930afd..0cab6bd3c 100644 --- a/ruby/spec/ruby/library/net/ftp/puttextfile_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/puttextfile_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -require_relative 'shared/puttextfile' -describe "Net::FTP#puttextfile" do - it_behaves_like :net_ftp_puttextfile, :puttextfile +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + require_relative 'shared/puttextfile' + + describe "Net::FTP#puttextfile" do + it_behaves_like :net_ftp_puttextfile, :puttextfile + end end diff --git a/ruby/spec/ruby/library/net/ftp/pwd_spec.rb b/ruby/spec/ruby/library/net/ftp/pwd_spec.rb index a3998cc73..856ff5ff9 100644 --- a/ruby/spec/ruby/library/net/ftp/pwd_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/pwd_spec.rb @@ -1,53 +1,56 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#pwd" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the PWD command to the server" do - @ftp.pwd - @ftp.last_response.should == "257 \"/some/dir/\" - current directory\n" - end - - it "returns the current directory" do - @ftp.pwd.should == "/some/dir/" - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:pwd).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.pwd }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:pwd).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.pwd }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:pwd).and_respond("502 Command not implemented.") - -> { @ftp.pwd }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:pwd).and_respond("421 Service not available, closing control connection.") - -> { @ftp.pwd }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:pwd).and_respond("550 Requested action not taken.") - -> { @ftp.pwd }.should raise_error(Net::FTPPermError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#pwd" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the PWD command to the server" do + @ftp.pwd + @ftp.last_response.should == "257 \"/some/dir/\" - current directory\n" + end + + it "returns the current directory" do + @ftp.pwd.should == "/some/dir/" + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:pwd).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.pwd }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:pwd).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.pwd }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:pwd).and_respond("502 Command not implemented.") + -> { @ftp.pwd }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:pwd).and_respond("421 Service not available, closing control connection.") + -> { @ftp.pwd }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:pwd).and_respond("550 Requested action not taken.") + -> { @ftp.pwd }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/quit_spec.rb b/ruby/spec/ruby/library/net/ftp/quit_spec.rb index 8e3cb28b9..12b9fd3ce 100644 --- a/ruby/spec/ruby/library/net/ftp/quit_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/quit_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#quit" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#quit" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the QUIT command to the server" do - @ftp.quit - @ftp.last_response.should == "221 OK, bye\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "does not close the socket automatically" do - @ftp.quit - @ftp.closed?.should be_false - end + it "sends the QUIT command to the server" do + @ftp.quit + @ftp.last_response.should == "221 OK, bye\n" + end + + it "does not close the socket automatically" do + @ftp.quit + @ftp.closed?.should be_false + end - it "returns nil" do - @ftp.quit.should be_nil + it "returns nil" do + @ftp.quit.should be_nil + end end end diff --git a/ruby/spec/ruby/library/net/ftp/rename_spec.rb b/ruby/spec/ruby/library/net/ftp/rename_spec.rb index 376b203ac..aa7c1360b 100644 --- a/ruby/spec/ruby/library/net/ftp/rename_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/rename_spec.rb @@ -1,94 +1,97 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#rename" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - describe "when passed from_name, to_name" do - it "sends the RNFR command with the passed from_name and the RNTO command with the passed to_name to the server" do - @ftp.rename("from.file", "to.file") - @ftp.last_response.should == "250 Requested file action okay, completed. (Renamed from.file to to.file)\n" - end - - it "returns something" do - @ftp.rename("from.file", "to.file").should be_nil - end - end - - describe "when the RNFR command fails" do - it "raises a Net::FTPTempError when the response code is 450" do - @server.should_receive(:rnfr).and_respond("450 Requested file action not taken.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:rnfr).and_respond("550 Requested action not taken.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:rnfr).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end + describe "Net::FTP#rename" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:rnfr).and_respond("502 Command not implemented.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:rnfr).and_respond("421 Service not available, closing control connection.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:rnfr).and_respond("530 Not logged in.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end - end - - describe "when the RNTO command fails" do - it "raises a Net::FTPPermError when the response code is 532" do - @server.should_receive(:rnfr).and_respond("532 Need account for storing files.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 553" do - @server.should_receive(:rnto).and_respond("553 Requested action not taken.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:rnto).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) - end + describe "when passed from_name, to_name" do + it "sends the RNFR command with the passed from_name and the RNTO command with the passed to_name to the server" do + @ftp.rename("from.file", "to.file") + @ftp.last_response.should == "250 Requested file action okay, completed. (Renamed from.file to to.file)\n" + end - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:rnto).and_respond("502 Command not implemented.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + it "returns something" do + @ftp.rename("from.file", "to.file").should be_nil + end end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:rnto).and_respond("421 Service not available, closing control connection.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) + describe "when the RNFR command fails" do + it "raises a Net::FTPTempError when the response code is 450" do + @server.should_receive(:rnfr).and_respond("450 Requested file action not taken.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:rnfr).and_respond("550 Requested action not taken.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:rnfr).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:rnfr).and_respond("502 Command not implemented.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:rnfr).and_respond("421 Service not available, closing control connection.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:rnfr).and_respond("530 Not logged in.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:rnto).and_respond("530 Not logged in.") - -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + describe "when the RNTO command fails" do + it "raises a Net::FTPPermError when the response code is 532" do + @server.should_receive(:rnfr).and_respond("532 Need account for storing files.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 553" do + @server.should_receive(:rnto).and_respond("553 Requested action not taken.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:rnto).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:rnto).and_respond("502 Command not implemented.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:rnto).and_respond("421 Service not available, closing control connection.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:rnto).and_respond("530 Not logged in.") + -> { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError) + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/resume_spec.rb b/ruby/spec/ruby/library/net/ftp/resume_spec.rb index 51b1cff2a..1b575c29f 100644 --- a/ruby/spec/ruby/library/net/ftp/resume_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/resume_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#resume" do - it "returns true when self is set to resume uploads/downloads" do - ftp = Net::FTP.new - ftp.resume.should be_false +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - ftp.resume = true - ftp.resume.should be_true + describe "Net::FTP#resume" do + it "returns true when self is set to resume uploads/downloads" do + ftp = Net::FTP.new + ftp.resume.should be_false + + ftp.resume = true + ftp.resume.should be_true + end end -end -describe "Net::FTP#resume=" do - it "sets self to resume uploads/downloads when set to true" do - ftp = Net::FTP.new - ftp.resume = true - ftp.resume.should be_true + describe "Net::FTP#resume=" do + it "sets self to resume uploads/downloads when set to true" do + ftp = Net::FTP.new + ftp.resume = true + ftp.resume.should be_true - ftp.resume = false - ftp.resume.should be_false + ftp.resume = false + ftp.resume.should be_false + end end end diff --git a/ruby/spec/ruby/library/net/ftp/retrbinary_spec.rb b/ruby/spec/ruby/library/net/ftp/retrbinary_spec.rb index 30e2484af..1f89f0d45 100644 --- a/ruby/spec/ruby/library/net/ftp/retrbinary_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/retrbinary_spec.rb @@ -1,30 +1,33 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#retrbinary" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#retrbinary" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the passed command to the server" do - @ftp.retrbinary("RETR test", 4096) {} - @ftp.last_response.should == "226 Closing data connection. (RETR test)\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the passed command to the server" do + @ftp.retrbinary("RETR test", 4096) {} + @ftp.last_response.should == "226 Closing data connection. (RETR test)\n" + end - it "yields the received content as binary blocks of the passed size" do - res = [] - @ftp.retrbinary("RETR test", 10) { |bin| res << bin } - res.should == [ "This is th", "e content\n", "of the fil", "e named 't", "est'.\n" ] + it "yields the received content as binary blocks of the passed size" do + res = [] + @ftp.retrbinary("RETR test", 10) { |bin| res << bin } + res.should == [ "This is th", "e content\n", "of the fil", "e named 't", "est'.\n" ] + end end end diff --git a/ruby/spec/ruby/library/net/ftp/retrlines_spec.rb b/ruby/spec/ruby/library/net/ftp/retrlines_spec.rb index 546df3844..f26b00868 100644 --- a/ruby/spec/ruby/library/net/ftp/retrlines_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/retrlines_spec.rb @@ -1,34 +1,37 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#retrlines" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#retrlines" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the passed command over the socket" do - @ftp.retrlines("LIST test.dir") {} - @ftp.last_response.should == "226 transfer complete (LIST test.dir)\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the passed command over the socket" do + @ftp.retrlines("LIST test.dir") {} + @ftp.last_response.should == "226 transfer complete (LIST test.dir)\n" + end - it "yields each received line to the passed block" do - res = [] - @ftp.retrlines("LIST test.dir") { |x| res << x } - res.should == [ - "-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb", - "-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb", - "-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb" - ] + it "yields each received line to the passed block" do + res = [] + @ftp.retrlines("LIST test.dir") { |x| res << x } + res.should == [ + "-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb", + "-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb", + "-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb" + ] + end end end diff --git a/ruby/spec/ruby/library/net/ftp/return_code_spec.rb b/ruby/spec/ruby/library/net/ftp/return_code_spec.rb index e4b98c803..67fc9d3b1 100644 --- a/ruby/spec/ruby/library/net/ftp/return_code_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/return_code_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#return_code" do - before :each do - @ftp = Net::FTP.new - end +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' - it "outputs a warning and returns a newline" do - -> do - @ftp.return_code.should == "\n" - end.should complain(/warning: Net::FTP#return_code is obsolete and do nothing/) - end -end + describe "Net::FTP#return_code" do + before :each do + @ftp = Net::FTP.new + end -describe "Net::FTP#return_code=" do - before :each do - @ftp = Net::FTP.new + it "outputs a warning and returns a newline" do + -> do + @ftp.return_code.should == "\n" + end.should complain(/warning: Net::FTP#return_code is obsolete and do nothing/) + end end - it "outputs a warning" do - -> { @ftp.return_code = 123 }.should complain(/warning: Net::FTP#return_code= is obsolete and do nothing/) + describe "Net::FTP#return_code=" do + before :each do + @ftp = Net::FTP.new + end + + it "outputs a warning" do + -> { @ftp.return_code = 123 }.should complain(/warning: Net::FTP#return_code= is obsolete and do nothing/) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/rmdir_spec.rb b/ruby/spec/ruby/library/net/ftp/rmdir_spec.rb index 051589799..5b9586c6f 100644 --- a/ruby/spec/ruby/library/net/ftp/rmdir_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/rmdir_spec.rb @@ -1,58 +1,61 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#rmdir" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the RMD command with the passed pathname to the server" do - @ftp.rmdir("test.folder") - @ftp.last_response.should == "250 Requested file action okay, completed. (RMD test.folder)\n" - end - - it "returns nil" do - @ftp.rmdir("test.folder").should be_nil - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:rmd).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:rmd).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:rmd).and_respond("502 Command not implemented.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:rmd).and_respond("421 Service not available, closing control connection.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:rmd).and_respond("530 Not logged in.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:rmd).and_respond("550 Requested action not taken.") - -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#rmdir" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the RMD command with the passed pathname to the server" do + @ftp.rmdir("test.folder") + @ftp.last_response.should == "250 Requested file action okay, completed. (RMD test.folder)\n" + end + + it "returns nil" do + @ftp.rmdir("test.folder").should be_nil + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:rmd).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:rmd).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:rmd).and_respond("502 Command not implemented.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:rmd).and_respond("421 Service not available, closing control connection.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:rmd).and_respond("530 Not logged in.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:rmd).and_respond("550 Requested action not taken.") + -> { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/sendcmd_spec.rb b/ruby/spec/ruby/library/net/ftp/sendcmd_spec.rb index dafa36e03..fefb89ae0 100644 --- a/ruby/spec/ruby/library/net/ftp/sendcmd_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/sendcmd_spec.rb @@ -1,54 +1,57 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#sendcmd" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the passed command to the server" do - @ftp.sendcmd("HELP") - @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" - end - - it "returns the server's response" do - @ftp.sendcmd("HELP").should == "211 System status, or system help reply. (HELP)\n" - end - - it "raises no error when the response code is 1xx, 2xx or 3xx" do - @server.should_receive(:help).and_respond("120 Service ready in nnn minutes.") - -> { @ftp.sendcmd("HELP") }.should_not raise_error - - @server.should_receive(:help).and_respond("200 Command okay.") - -> { @ftp.sendcmd("HELP") }.should_not raise_error - - @server.should_receive(:help).and_respond("350 Requested file action pending further information.") - -> { @ftp.sendcmd("HELP") }.should_not raise_error - end - - it "raises a Net::FTPTempError when the response code is 4xx" do - @server.should_receive(:help).and_respond("421 Service not available, closing control connection.") - -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 5xx" do - @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPProtoError when the response code is not between 1xx-5xx" do - @server.should_receive(:help).and_respond("999 Invalid response.") - -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPProtoError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#sendcmd" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the passed command to the server" do + @ftp.sendcmd("HELP") + @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n" + end + + it "returns the server's response" do + @ftp.sendcmd("HELP").should == "211 System status, or system help reply. (HELP)\n" + end + + it "raises no error when the response code is 1xx, 2xx or 3xx" do + @server.should_receive(:help).and_respond("120 Service ready in nnn minutes.") + -> { @ftp.sendcmd("HELP") }.should_not raise_error + + @server.should_receive(:help).and_respond("200 Command okay.") + -> { @ftp.sendcmd("HELP") }.should_not raise_error + + @server.should_receive(:help).and_respond("350 Requested file action pending further information.") + -> { @ftp.sendcmd("HELP") }.should_not raise_error + end + + it "raises a Net::FTPTempError when the response code is 4xx" do + @server.should_receive(:help).and_respond("421 Service not available, closing control connection.") + -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 5xx" do + @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPProtoError when the response code is not between 1xx-5xx" do + @server.should_receive(:help).and_respond("999 Invalid response.") + -> { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPProtoError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/set_socket_spec.rb b/ruby/spec/ruby/library/net/ftp/set_socket_spec.rb index 7ca3bbbe2..6c8b58fb7 100644 --- a/ruby/spec/ruby/library/net/ftp/set_socket_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/set_socket_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -describe "Net::FTP#set_socket" do - # TODO: I won't spec this method, as it is not used - # anywhere and it should be private anyway. - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + + describe "Net::FTP#set_socket" do + # TODO: I won't spec this method, as it is not used + # anywhere and it should be private anyway. + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/net/ftp/site_spec.rb b/ruby/spec/ruby/library/net/ftp/site_spec.rb index 4d6a9b4a0..ca4f49911 100644 --- a/ruby/spec/ruby/library/net/ftp/site_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/site_spec.rb @@ -1,53 +1,56 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#site" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the SITE command with the passed argument to the server" do - @ftp.site("param") - @ftp.last_response.should == "200 Command okay. (SITE param)\n" - end - - it "returns nil" do - @ftp.site("param").should be_nil - end - - it "does not raise an error when the response code is 202" do - @server.should_receive(:site).and_respond("202 Command not implemented, superfluous at this site.") - -> { @ftp.site("param") }.should_not raise_error - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:site).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:site).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:site).and_respond("421 Service not available, closing control connection.") - -> { @ftp.site("param") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:site).and_respond("530 Requested action not taken.") - -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#site" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the SITE command with the passed argument to the server" do + @ftp.site("param") + @ftp.last_response.should == "200 Command okay. (SITE param)\n" + end + + it "returns nil" do + @ftp.site("param").should be_nil + end + + it "does not raise an error when the response code is 202" do + @server.should_receive(:site).and_respond("202 Command not implemented, superfluous at this site.") + -> { @ftp.site("param") }.should_not raise_error + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:site).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:site).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:site).and_respond("421 Service not available, closing control connection.") + -> { @ftp.site("param") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:site).and_respond("530 Requested action not taken.") + -> { @ftp.site("param") }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/size_spec.rb b/ruby/spec/ruby/library/net/ftp/size_spec.rb index 17615079e..0c20b1054 100644 --- a/ruby/spec/ruby/library/net/ftp/size_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/size_spec.rb @@ -1,48 +1,51 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#size" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the SIZE command to the server" do - @ftp.size("test.file") - @ftp.last_response.should == "213 1024\n" - end - - it "returns the size of the passed file as Integer" do - @ftp.size("test.file").should eql(1024) - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:size).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:size).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:size).and_respond("421 Service not available, closing control connection.") - -> { @ftp.size("test.file") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 550" do - @server.should_receive(:size).and_respond("550 Requested action not taken.") - -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#size" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the SIZE command to the server" do + @ftp.size("test.file") + @ftp.last_response.should == "213 1024\n" + end + + it "returns the size of the passed file as Integer" do + @ftp.size("test.file").should eql(1024) + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:size).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:size).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:size).and_respond("421 Service not available, closing control connection.") + -> { @ftp.size("test.file") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 550" do + @server.should_receive(:size).and_respond("550 Requested action not taken.") + -> { @ftp.size("test.file") }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/status_spec.rb b/ruby/spec/ruby/library/net/ftp/status_spec.rb index 6e3840bf9..03bc5d6e0 100644 --- a/ruby/spec/ruby/library/net/ftp/status_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/status_spec.rb @@ -1,67 +1,70 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#status" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#status" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - it "sends the STAT command to the server" do - @ftp.status - @ftp.last_response.should == "211 System status, or system help reply. (STAT)\n" - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "sends the STAT command with an optional parameter to the server" do - @ftp.status("/pub").should == "211 System status, or system help reply. (STAT /pub)\n" - end + it "sends the STAT command to the server" do + @ftp.status + @ftp.last_response.should == "211 System status, or system help reply. (STAT)\n" + end - it "returns the received information" do - @ftp.status.should == "211 System status, or system help reply. (STAT)\n" - end + it "sends the STAT command with an optional parameter to the server" do + @ftp.status("/pub").should == "211 System status, or system help reply. (STAT /pub)\n" + end - it "does not raise an error when the response code is 212" do - @server.should_receive(:stat).and_respond("212 Directory status.") - -> { @ftp.status }.should_not raise_error - end + it "returns the received information" do + @ftp.status.should == "211 System status, or system help reply. (STAT)\n" + end - it "does not raise an error when the response code is 213" do - @server.should_receive(:stat).and_respond("213 File status.") - -> { @ftp.status }.should_not raise_error - end + it "does not raise an error when the response code is 212" do + @server.should_receive(:stat).and_respond("212 Directory status.") + -> { @ftp.status }.should_not raise_error + end - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:stat).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.status }.should raise_error(Net::FTPPermError) - end + it "does not raise an error when the response code is 213" do + @server.should_receive(:stat).and_respond("213 File status.") + -> { @ftp.status }.should_not raise_error + end - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:stat).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.status }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:stat).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.status }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:stat).and_respond("502 Command not implemented.") - -> { @ftp.status }.should raise_error(Net::FTPPermError) - end + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:stat).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.status }.should raise_error(Net::FTPPermError) + end - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:stat).and_respond("421 Service not available, closing control connection.") - -> { @ftp.status }.should raise_error(Net::FTPTempError) - end + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:stat).and_respond("502 Command not implemented.") + -> { @ftp.status }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:stat).and_respond("421 Service not available, closing control connection.") + -> { @ftp.status }.should raise_error(Net::FTPTempError) + end - it "raises a Net::FTPPermError when the response code is 530" do - @server.should_receive(:stat).and_respond("530 Requested action not taken.") - -> { @ftp.status }.should raise_error(Net::FTPPermError) + it "raises a Net::FTPPermError when the response code is 530" do + @server.should_receive(:stat).and_respond("530 Requested action not taken.") + -> { @ftp.status }.should raise_error(Net::FTPPermError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/storbinary_spec.rb b/ruby/spec/ruby/library/net/ftp/storbinary_spec.rb index eb65db1e8..64c909076 100644 --- a/ruby/spec/ruby/library/net/ftp/storbinary_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/storbinary_spec.rb @@ -1,48 +1,51 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#storbinary" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @local_fixture_file = File.dirname(__FILE__) + "/fixtures/putbinaryfile" - @tmp_file = tmp("binaryfile", false) + describe "Net::FTP#storbinary" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + @local_fixture_file = File.dirname(__FILE__) + "/fixtures/putbinaryfile" + @tmp_file = tmp("binaryfile", false) - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - rm_r @tmp_file - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop - it "sends the passed command and the passed File object's content to the server" do - File.open(@local_fixture_file) do |f| - f.binmode + rm_r @tmp_file + end + + it "sends the passed command and the passed File object's content to the server" do + File.open(@local_fixture_file) do |f| + f.binmode - @ftp.storbinary("STOR binary", f, 4096) {} - @ftp.last_response.should == "200 OK, Data received. (STOR binary)\n" + @ftp.storbinary("STOR binary", f, 4096) {} + @ftp.last_response.should == "200 OK, Data received. (STOR binary)\n" + end end - end - it "yields the transmitted content as binary blocks of the passed size" do - File.open(@local_fixture_file) do |f| - f.binmode - - res = [] - @ftp.storbinary("STOR binary", f, 10) { |x| res << x } - res.should == [ - "This is an", " example f", - "ile\nwhich ", "is going t", - "o be trans", "mitted\nusi", - "ng #putbin", "aryfile.\n" - ] + it "yields the transmitted content as binary blocks of the passed size" do + File.open(@local_fixture_file) do |f| + f.binmode + + res = [] + @ftp.storbinary("STOR binary", f, 10) { |x| res << x } + res.should == [ + "This is an", " example f", + "ile\nwhich ", "is going t", + "o be trans", "mitted\nusi", + "ng #putbin", "aryfile.\n" + ] + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/storlines_spec.rb b/ruby/spec/ruby/library/net/ftp/storlines_spec.rb index 4affa37ee..a4bb7af79 100644 --- a/ruby/spec/ruby/library/net/ftp/storlines_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/storlines_spec.rb @@ -1,43 +1,46 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#storlines" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @local_fixture_file = File.dirname(__FILE__) + "/fixtures/puttextfile" - @tmp_file = tmp("textfile", false) + describe "Net::FTP#storlines" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + @local_fixture_file = File.dirname(__FILE__) + "/fixtures/puttextfile" + @tmp_file = tmp("textfile", false) - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end - rm_r @tmp_file - end + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop - it "sends the passed command and the passed File object's content to the server" do - File.open(@local_fixture_file) do |f| - @ftp.storlines("STOR text", f) {} - @ftp.last_response.should == "200 OK, Data received. (STOR text)\n" + rm_r @tmp_file + end + + it "sends the passed command and the passed File object's content to the server" do + File.open(@local_fixture_file) do |f| + @ftp.storlines("STOR text", f) {} + @ftp.last_response.should == "200 OK, Data received. (STOR text)\n" + end end - end - it "yields each line of the transmitted content" do - File.open(@local_fixture_file) do |f| - res = [] - @ftp.storlines("STOR text", f) { |x| res << x } - res.should == [ - "This is an example file\r\n", - "which is going to be transmitted\r\n", - "using #puttextfile.\r\n" - ] + it "yields each line of the transmitted content" do + File.open(@local_fixture_file) do |f| + res = [] + @ftp.storlines("STOR text", f) { |x| res << x } + res.should == [ + "This is an example file\r\n", + "which is going to be transmitted\r\n", + "using #puttextfile.\r\n" + ] + end end end end diff --git a/ruby/spec/ruby/library/net/ftp/system_spec.rb b/ruby/spec/ruby/library/net/ftp/system_spec.rb index 749258622..0630bbe1f 100644 --- a/ruby/spec/ruby/library/net/ftp/system_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/system_spec.rb @@ -1,48 +1,51 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#system" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the SYST command to the server" do - @ftp.system - @ftp.last_response.should =~ /\A215 FTP Dummy Server \(SYST\)\Z/ - end - - it "returns the received information" do - @ftp.system.should =~ /\AFTP Dummy Server \(SYST\)\Z/ - end - - it "raises a Net::FTPPermError when the response code is 500" do - @server.should_receive(:syst).and_respond("500 Syntax error, command unrecognized.") - -> { @ftp.system }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 501" do - @server.should_receive(:syst).and_respond("501 Syntax error in parameters or arguments.") - -> { @ftp.system }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPPermError when the response code is 502" do - @server.should_receive(:syst).and_respond("502 Command not implemented.") - -> { @ftp.system }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPTempError when the response code is 421" do - @server.should_receive(:syst).and_respond("421 Service not available, closing control connection.") - -> { @ftp.system }.should raise_error(Net::FTPTempError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#system" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the SYST command to the server" do + @ftp.system + @ftp.last_response.should =~ /\A215 FTP Dummy Server \(SYST\)\Z/ + end + + it "returns the received information" do + @ftp.system.should =~ /\AFTP Dummy Server \(SYST\)\Z/ + end + + it "raises a Net::FTPPermError when the response code is 500" do + @server.should_receive(:syst).and_respond("500 Syntax error, command unrecognized.") + -> { @ftp.system }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 501" do + @server.should_receive(:syst).and_respond("501 Syntax error in parameters or arguments.") + -> { @ftp.system }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPPermError when the response code is 502" do + @server.should_receive(:syst).and_respond("502 Command not implemented.") + -> { @ftp.system }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPTempError when the response code is 421" do + @server.should_receive(:syst).and_respond("421 Service not available, closing control connection.") + -> { @ftp.system }.should raise_error(Net::FTPTempError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/voidcmd_spec.rb b/ruby/spec/ruby/library/net/ftp/voidcmd_spec.rb index 3673c7fd5..ee74455d6 100644 --- a/ruby/spec/ruby/library/net/ftp/voidcmd_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/voidcmd_spec.rb @@ -1,54 +1,57 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#voidcmd" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once - - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end - - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end - - it "sends the passed command to the server" do - @server.should_receive(:help).and_respond("2xx Does not raise.") - -> { @ftp.voidcmd("HELP") }.should_not raise_error - end - - it "returns nil" do - @server.should_receive(:help).and_respond("2xx Does not raise.") - @ftp.voidcmd("HELP").should be_nil - end - - it "raises a Net::FTPReplyError when the response code is 1xx" do - @server.should_receive(:help).and_respond("1xx Does raise a Net::FTPReplyError.") - -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError) - end - - it "raises a Net::FTPReplyError when the response code is 3xx" do - @server.should_receive(:help).and_respond("3xx Does raise a Net::FTPReplyError.") - -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError) - end - - it "raises a Net::FTPTempError when the response code is 4xx" do - @server.should_receive(:help).and_respond("4xx Does raise a Net::FTPTempError.") - -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPTempError) - end - - it "raises a Net::FTPPermError when the response code is 5xx" do - @server.should_receive(:help).and_respond("5xx Does raise a Net::FTPPermError.") - -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPPermError) - end - - it "raises a Net::FTPProtoError when the response code is not valid" do - @server.should_receive(:help).and_respond("999 Does raise a Net::FTPProtoError.") - -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPProtoError) +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' + + describe "Net::FTP#voidcmd" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once + + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end + + it "sends the passed command to the server" do + @server.should_receive(:help).and_respond("2xx Does not raise.") + -> { @ftp.voidcmd("HELP") }.should_not raise_error + end + + it "returns nil" do + @server.should_receive(:help).and_respond("2xx Does not raise.") + @ftp.voidcmd("HELP").should be_nil + end + + it "raises a Net::FTPReplyError when the response code is 1xx" do + @server.should_receive(:help).and_respond("1xx Does raise a Net::FTPReplyError.") + -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError) + end + + it "raises a Net::FTPReplyError when the response code is 3xx" do + @server.should_receive(:help).and_respond("3xx Does raise a Net::FTPReplyError.") + -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError) + end + + it "raises a Net::FTPTempError when the response code is 4xx" do + @server.should_receive(:help).and_respond("4xx Does raise a Net::FTPTempError.") + -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPTempError) + end + + it "raises a Net::FTPPermError when the response code is 5xx" do + @server.should_receive(:help).and_respond("5xx Does raise a Net::FTPPermError.") + -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPPermError) + end + + it "raises a Net::FTPProtoError when the response code is not valid" do + @server.should_receive(:help).and_respond("999 Does raise a Net::FTPProtoError.") + -> { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPProtoError) + end end end diff --git a/ruby/spec/ruby/library/net/ftp/welcome_spec.rb b/ruby/spec/ruby/library/net/ftp/welcome_spec.rb index a0d748394..e5414ef60 100644 --- a/ruby/spec/ruby/library/net/ftp/welcome_spec.rb +++ b/ruby/spec/ruby/library/net/ftp/welcome_spec.rb @@ -1,25 +1,28 @@ require_relative '../../../spec_helper' -require_relative 'spec_helper' -require_relative 'fixtures/server' -describe "Net::FTP#welcome" do - before :each do - @server = NetFTPSpecs::DummyFTP.new - @server.serve_once +ruby_version_is ""..."3.1" do + require_relative 'spec_helper' + require_relative 'fixtures/server' - @ftp = Net::FTP.new - @ftp.connect(@server.hostname, @server.server_port) - end + describe "Net::FTP#welcome" do + before :each do + @server = NetFTPSpecs::DummyFTP.new + @server.serve_once - after :each do - @ftp.quit rescue nil - @ftp.close - @server.stop - end + @ftp = Net::FTP.new + @ftp.connect(@server.hostname, @server.server_port) + end + + after :each do + @ftp.quit rescue nil + @ftp.close + @server.stop + end - it "returns the server's welcome message" do - @ftp.welcome.should be_nil - @ftp.login - @ftp.welcome.should == "230 User logged in, proceed. (USER anonymous)\n" + it "returns the server's welcome message" do + @ftp.welcome.should be_nil + @ftp.login + @ftp.welcome.should == "230 User logged in, proceed. (USER anonymous)\n" + end end end diff --git a/ruby/spec/ruby/library/net/http/HTTPClientExcepton_spec.rb b/ruby/spec/ruby/library/net/http/HTTPClientExcepton_spec.rb index 08347464e..d576349a5 100644 --- a/ruby/spec/ruby/library/net/http/HTTPClientExcepton_spec.rb +++ b/ruby/spec/ruby/library/net/http/HTTPClientExcepton_spec.rb @@ -1,14 +1,12 @@ require_relative '../../../spec_helper' require 'net/http' -ruby_version_is "2.6" do - describe "Net::HTTPClientException" do - it "is a subclass of Net::ProtoServerError" do - Net::HTTPClientException.should < Net::ProtoServerError - end +describe "Net::HTTPClientException" do + it "is a subclass of Net::ProtoServerError" do + Net::HTTPClientException.should < Net::ProtoServerError + end - it "includes the Net::HTTPExceptions module" do - Net::HTTPClientException.should < Net::HTTPExceptions - end + it "includes the Net::HTTPExceptions module" do + Net::HTTPClientException.should < Net::HTTPExceptions end end diff --git a/ruby/spec/ruby/library/net/http/HTTPServerException_spec.rb b/ruby/spec/ruby/library/net/http/HTTPServerException_spec.rb index 87841ab49..23b065736 100644 --- a/ruby/spec/ruby/library/net/http/HTTPServerException_spec.rb +++ b/ruby/spec/ruby/library/net/http/HTTPServerException_spec.rb @@ -1,26 +1,12 @@ require_relative '../../../spec_helper' require 'net/http' -ruby_version_is ""..."2.6" do - describe "Net::HTTPServerException" do - it "is a subclass of Net::ProtoServerError" do - Net::HTTPServerException.should < Net::ProtoServerError - end - - it "includes the Net::HTTPExceptions module" do - Net::HTTPServerException.should < Net::HTTPExceptions - end +describe "Net::HTTPServerException" do + it "is a subclass of Net::ProtoServerError and is warned as deprecated" do + -> { Net::HTTPServerException.should < Net::ProtoServerError }.should complain(/warning: constant Net::HTTPServerException is deprecated/) end -end - -ruby_version_is "2.6" do - describe "Net::HTTPServerException" do - it "is a subclass of Net::ProtoServerError and is warned as deprecated" do - -> { Net::HTTPServerException.should < Net::ProtoServerError }.should complain(/warning: constant Net::HTTPServerException is deprecated/) - end - it "includes the Net::HTTPExceptions module and is warned as deprecated" do - -> { Net::HTTPServerException.should < Net::HTTPExceptions }.should complain(/warning: constant Net::HTTPServerException is deprecated/) - end + it "includes the Net::HTTPExceptions module and is warned as deprecated" do + -> { Net::HTTPServerException.should < Net::HTTPExceptions }.should complain(/warning: constant Net::HTTPServerException is deprecated/) end end diff --git a/ruby/spec/ruby/library/net/http/http/fixtures/http_server.rb b/ruby/spec/ruby/library/net/http/http/fixtures/http_server.rb index 49e8f437c..c1cedbfa7 100644 --- a/ruby/spec/ruby/library/net/http/http/fixtures/http_server.rb +++ b/ruby/spec/ruby/library/net/http/http/fixtures/http_server.rb @@ -1,5 +1,4 @@ -require 'webrick' -require 'webrick/httpservlet/abstract' +require 'socket' module NetHTTPSpecs class NullWriter @@ -9,97 +8,116 @@ def print(*args) end def printf(*args) end end - class SpecServlet < WEBrick::HTTPServlet::AbstractServlet - def handle(req, res) - reply(req, res) + class SmallHTTPServer + def initialize(bind_address) + @server = TCPServer.new(bind_address, 0) + @thread = Thread.new { + Thread.current.abort_on_exception = true + listen + } end - %w{ do_GET do_HEAD do_POST do_PUT do_PROPPATCH do_LOCK do_UNLOCK - do_OPTIONS do_PROPFIND do_DELETE do_MOVE do_COPY - do_MKCOL do_TRACE }.each do |method| - alias_method method.to_sym, :handle + def ip + @server.addr[3] end - end - class RequestServlet < SpecServlet - def reply(req, res) - res.content_type = "text/plain" - res.body = "Request type: #{req.request_method}" + def port + @server.addr[1] end - end - class RequestBodyServlet < SpecServlet - def reply(req, res) - res.content_type = "text/plain" - res.body = req.body + def listen + until @server.closed? + client = @server.accept + handle_client(client) + end + end + + def handle_client(client) + begin + until client.closed? + request = client.gets("\r\n\r\n") + break unless request + if request == "CLOSE" + @server.close + break + end + handle_request(client, request) + end + ensure + client.close + end end - end - class RequestHeaderServlet < SpecServlet - def reply(req, res) - res.content_type = "text/plain" - res.body = req.header.inspect + def parse_request(request) + request, *headers = request.chomp.lines.map { |line| line.chomp } + request_method, request_uri, _http_version = request.split + headers = headers.map { |line| line.split(': ', 2) }.to_h + [request_method, request_uri, headers] end - end - class RequestBasicAuthServlet < SpecServlet - def reply(req, res) - res.content_type = "text/plain" + def handle_request(client, request) + request_method, request_uri, headers = parse_request(request) + + if headers.include? 'Content-Length' + request_body_size = Integer(headers['Content-Length']) + request_body = client.read(request_body_size) + end + + case request_uri + when '/' + raise request_method unless request_method == 'GET' + reply(client, "This is the index page.", request_method) + when '/request' + reply(client, "Request type: #{request_method}", request_method) + when '/request/body' + reply(client, request_body, request_method) + when '/request/header' + reply(client, headers.inspect, request_method) + when '/request/basic_auth' + reply(client, "username: \npassword: ", request_method) + else + raise request_uri + end + end - WEBrick::HTTPAuth.basic_auth(req, res, "realm") do |user, pass| - res.body = "username: #{user}\npassword: #{pass}" - true + def reply(client, body, request_method) + client.print "HTTP/1.1 200 OK\r\n" + if request_method == 'HEAD' + client.close + else + client.print "Content-Type: text/plain\r\n" + client.print "Content-Length: #{body.bytesize}\r\n" + client.print "\r\n" + client.print body end end + + def close + TCPSocket.open(ip, port) do |socket| + socket.write "CLOSE" + end + @thread.join + end end - class << self - @server = nil - @server_thread = nil + @server = nil + class << self def port raise "server not started" unless @server - @server.config[:Port] + @server.port end def start_server - server_config = { - BindAddress: "127.0.0.1", - Port: 0, - Logger: WEBrick::Log.new(NullWriter.new), - AccessLog: [], - ServerType: Thread - } - - @server = WEBrick::HTTPServer.new(server_config) - - @server.mount_proc('/') do |req, res| - res.content_type = "text/plain" - res.body = "This is the index page." - end - @server.mount('/request', RequestServlet) - @server.mount("/request/body", RequestBodyServlet) - @server.mount("/request/header", RequestHeaderServlet) - @server.mount("/request/basic_auth", RequestBasicAuthServlet) - - @server_thread = @server.start + bind_address = platform_is(:windows) ? "localhost" : "127.0.0.1" + @server = SmallHTTPServer.new(bind_address) end def stop_server if @server - begin - @server.shutdown - rescue Errno::EPIPE - # Because WEBrick is not thread-safe and only catches IOError - end + @server.close @server = nil end - if @server_thread - @server_thread.join - @server_thread = nil - end - timeout = WEBrick::Utils::TimeoutHandler - timeout.terminate if timeout.respond_to?(:terminate) end end end diff --git a/ruby/spec/ruby/library/net/http/http/get2_spec.rb b/ruby/spec/ruby/library/net/http/http/get2_spec.rb index 71dfc3d39..519e4c259 100644 --- a/ruby/spec/ruby/library/net/http/http/get2_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/get2_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_get' describe "Net::HTTP#get2" do - it_behaves_like :net_ftp_request_get, :get2 + it_behaves_like :net_http_request_get, :get2 end diff --git a/ruby/spec/ruby/library/net/http/http/get_spec.rb b/ruby/spec/ruby/library/net/http/http/get_spec.rb index 4b8af5950..9f6c45f26 100644 --- a/ruby/spec/ruby/library/net/http/http/get_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/get_spec.rb @@ -2,7 +2,7 @@ require 'net/http' require_relative 'fixtures/http_server' -describe "Net::HTTP.get when passed URI" do +describe "Net::HTTP.get" do before :each do NetHTTPSpecs.start_server @port = NetHTTPSpecs.port @@ -24,3 +24,73 @@ end end end + +quarantine! do # These specs fail frequently with CHECK_LEAKS=true +describe "Net::HTTP.get" do + describe "when reading gzipped contents" do + def start_threads + require 'zlib' + require 'stringio' + + server = nil + server_thread = Thread.new do + server = TCPServer.new("127.0.0.1", 0) + begin + c = server.accept + ensure + server.close + end + c.print "HTTP/1.1 200\r\n" + c.print "Content-Type: text/plain\r\n" + c.print "Content-Encoding: gzip\r\n" + s = StringIO.new + z = Zlib::GzipWriter.new(s) + begin + z.write 'Hello World!' + ensure + z.close + end + c.print "Content-Length: #{s.length}\r\n\r\n" + # Write partial gzip content + c.write s.string.byteslice(0..-2) + c.flush + c + end + Thread.pass until server && server_thread.stop? + + client_thread = Thread.new do + Thread.current.report_on_exception = false + Net::HTTP.get("127.0.0.1", '/', server.connect_address.ip_port) + end + + socket = server_thread.value + Thread.pass until client_thread.stop? + + [socket, client_thread] + end + + it "propagates exceptions interrupting the thread and does not replace it with Zlib::BufError" do + my_exception = Class.new(RuntimeError) + socket, client_thread = start_threads + begin + client_thread.raise my_exception, "my exception" + -> { client_thread.value }.should raise_error(my_exception) + ensure + socket.close + end + end + + ruby_version_is "3.0" do # https://bugs.ruby-lang.org/issues/13882#note-6 + it "lets the kill Thread exception goes through and does not replace it with Zlib::BufError" do + socket, client_thread = start_threads + begin + client_thread.kill + client_thread.value.should == nil + ensure + socket.close + end + end + end + end +end +end diff --git a/ruby/spec/ruby/library/net/http/http/head2_spec.rb b/ruby/spec/ruby/library/net/http/http/head2_spec.rb index 606798e4a..6958204ee 100644 --- a/ruby/spec/ruby/library/net/http/http/head2_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/head2_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_head' describe "Net::HTTP#head2" do - it_behaves_like :net_ftp_request_head, :head2 + it_behaves_like :net_http_request_head, :head2 end diff --git a/ruby/spec/ruby/library/net/http/http/post2_spec.rb b/ruby/spec/ruby/library/net/http/http/post2_spec.rb index eab9a6a1d..ccc95068f 100644 --- a/ruby/spec/ruby/library/net/http/http/post2_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/post2_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_post' describe "Net::HTTP#post2" do - it_behaves_like :net_ftp_request_post, :post2 + it_behaves_like :net_http_request_post, :post2 end diff --git a/ruby/spec/ruby/library/net/http/http/post_spec.rb b/ruby/spec/ruby/library/net/http/http/post_spec.rb index 9f20a03c8..891e20aac 100644 --- a/ruby/spec/ruby/library/net/http/http/post_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/post_spec.rb @@ -27,7 +27,7 @@ it "sends Content-Type: application/x-www-form-urlencoded by default" do response = Net::HTTP.post(URI("http://localhost:#{NetHTTPSpecs.port}/request/header"), "test=test") - response.body.should include('"content-type"=>["application/x-www-form-urlencoded"]') + response.body.should include('"Content-Type"=>"application/x-www-form-urlencoded"') end it "does not support HTTP Basic Auth" do diff --git a/ruby/spec/ruby/library/net/http/http/put2_spec.rb b/ruby/spec/ruby/library/net/http/http/put2_spec.rb index 0ee359063..99329a5fd 100644 --- a/ruby/spec/ruby/library/net/http/http/put2_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/put2_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_put' describe "Net::HTTP#put2" do - it_behaves_like :net_ftp_request_put, :put2 + it_behaves_like :net_http_request_put, :put2 end diff --git a/ruby/spec/ruby/library/net/http/http/request_get_spec.rb b/ruby/spec/ruby/library/net/http/http/request_get_spec.rb index f53a2e9d6..9932ef0be 100644 --- a/ruby/spec/ruby/library/net/http/http/request_get_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/request_get_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_get' describe "Net::HTTP#request_get" do - it_behaves_like :net_ftp_request_get, :get2 + it_behaves_like :net_http_request_get, :get2 end diff --git a/ruby/spec/ruby/library/net/http/http/request_head_spec.rb b/ruby/spec/ruby/library/net/http/http/request_head_spec.rb index dc47557b9..788101c95 100644 --- a/ruby/spec/ruby/library/net/http/http/request_head_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/request_head_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_head' describe "Net::HTTP#request_head" do - it_behaves_like :net_ftp_request_head, :request_head + it_behaves_like :net_http_request_head, :request_head end diff --git a/ruby/spec/ruby/library/net/http/http/request_post_spec.rb b/ruby/spec/ruby/library/net/http/http/request_post_spec.rb index 0b408fa84..7ac67cf95 100644 --- a/ruby/spec/ruby/library/net/http/http/request_post_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/request_post_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_post' describe "Net::HTTP#request_post" do - it_behaves_like :net_ftp_request_post, :request_post + it_behaves_like :net_http_request_post, :request_post end diff --git a/ruby/spec/ruby/library/net/http/http/request_put_spec.rb b/ruby/spec/ruby/library/net/http/http/request_put_spec.rb index 987b52ceb..110ac43ca 100644 --- a/ruby/spec/ruby/library/net/http/http/request_put_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/request_put_spec.rb @@ -4,5 +4,5 @@ require_relative 'shared/request_put' describe "Net::HTTP#request_put" do - it_behaves_like :net_ftp_request_put, :request_put + it_behaves_like :net_http_request_put, :request_put end diff --git a/ruby/spec/ruby/library/net/http/http/send_request_spec.rb b/ruby/spec/ruby/library/net/http/http/send_request_spec.rb index 03fd32e47..83e9448b8 100644 --- a/ruby/spec/ruby/library/net/http/http/send_request_spec.rb +++ b/ruby/spec/ruby/library/net/http/http/send_request_spec.rb @@ -26,7 +26,7 @@ response = @http.send_request("HEAD", "/request") response.body.should be_nil - @methods.each do |method| + (@methods - %w[POST PUT]).each do |method| response = @http.send_request(method, "/request") response.body.should == "Request type: #{method}" end @@ -54,7 +54,7 @@ @methods.each do |method| response = @http.send_request(method, "/request/header", "test=test", "referer" => referer) - response.body.should include('"referer"=>["' + referer + '"]') + response.body.should include('"Referer"=>"' + referer + '"') end end end diff --git a/ruby/spec/ruby/library/net/http/http/shared/request_get.rb b/ruby/spec/ruby/library/net/http/http/shared/request_get.rb index b0eca665d..d25f32049 100644 --- a/ruby/spec/ruby/library/net/http/http/shared/request_get.rb +++ b/ruby/spec/ruby/library/net/http/http/shared/request_get.rb @@ -1,4 +1,4 @@ -describe :net_ftp_request_get, shared: true do +describe :net_http_request_get, shared: true do before :each do NetHTTPSpecs.start_server @http = Net::HTTP.start("localhost", NetHTTPSpecs.port) diff --git a/ruby/spec/ruby/library/net/http/http/shared/request_head.rb b/ruby/spec/ruby/library/net/http/http/shared/request_head.rb index 0e669de9a..78b555884 100644 --- a/ruby/spec/ruby/library/net/http/http/shared/request_head.rb +++ b/ruby/spec/ruby/library/net/http/http/shared/request_head.rb @@ -1,4 +1,4 @@ -describe :net_ftp_request_head, shared: true do +describe :net_http_request_head, shared: true do before :each do NetHTTPSpecs.start_server @http = Net::HTTP.start("localhost", NetHTTPSpecs.port) diff --git a/ruby/spec/ruby/library/net/http/http/shared/request_post.rb b/ruby/spec/ruby/library/net/http/http/shared/request_post.rb index 06c5e139f..e832411c4 100644 --- a/ruby/spec/ruby/library/net/http/http/shared/request_post.rb +++ b/ruby/spec/ruby/library/net/http/http/shared/request_post.rb @@ -1,4 +1,4 @@ -describe :net_ftp_request_post, shared: true do +describe :net_http_request_post, shared: true do before :each do NetHTTPSpecs.start_server @http = Net::HTTP.start("localhost", NetHTTPSpecs.port) diff --git a/ruby/spec/ruby/library/net/http/http/shared/request_put.rb b/ruby/spec/ruby/library/net/http/http/shared/request_put.rb index 6ae791d7e..3b902f495 100644 --- a/ruby/spec/ruby/library/net/http/http/shared/request_put.rb +++ b/ruby/spec/ruby/library/net/http/http/shared/request_put.rb @@ -1,4 +1,4 @@ -describe :net_ftp_request_put, shared: true do +describe :net_http_request_put, shared: true do before :each do NetHTTPSpecs.start_server @http = Net::HTTP.start("localhost", NetHTTPSpecs.port) diff --git a/ruby/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb index 68a0454f7..8ade46689 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb @@ -3,11 +3,11 @@ describe "Net::HTTPResponse.body_permitted?" do it "returns true if this response type can have a response body" do - Net::HTTPUnknownResponse.body_permitted?.should == true - Net::HTTPInformation.body_permitted?.should == false - Net::HTTPSuccess.body_permitted?.should == true - Net::HTTPRedirection.body_permitted?.should == true - Net::HTTPClientError.body_permitted?.should == true - Net::HTTPServerError.body_permitted?.should == true + Net::HTTPUnknownResponse.should.body_permitted? + Net::HTTPInformation.should_not.body_permitted? + Net::HTTPSuccess.should.body_permitted? + Net::HTTPRedirection.should.body_permitted? + Net::HTTPClientError.should.body_permitted? + Net::HTTPServerError.should.body_permitted? end end diff --git a/ruby/spec/ruby/library/net/http/httpresponse/error_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/error_spec.rb index d2b2f53d8..89f4a47f6 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/error_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/error_spec.rb @@ -16,12 +16,7 @@ -> { res.error! }.should raise_error(Net::HTTPRetriableError) res = Net::HTTPClientError.new("1.0", "4xx", "test response") - ruby_version_is ""..."2.6" do - -> { res.error! }.should raise_error(Net::HTTPServerException) - end - ruby_version_is "2.6" do - -> { res.error! }.should raise_error(Net::HTTPClientException) - end + -> { res.error! }.should raise_error(Net::HTTPClientException) res = Net::HTTPServerError.new("1.0", "5xx", "test response") -> { res.error! }.should raise_error(Net::HTTPFatalError) diff --git a/ruby/spec/ruby/library/net/http/httpresponse/error_type_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/error_type_spec.rb index 6705f8b1a..8885b7706 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/error_type_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/error_type_spec.rb @@ -16,12 +16,7 @@ res.error_type.should == Net::HTTPRetriableError res = Net::HTTPClientError.new("1.0", "4xx", "test response") - ruby_version_is ""..."2.6" do - res.error_type.should == Net::HTTPServerException - end - ruby_version_is "2.6" do - res.error_type.should == Net::HTTPClientException - end + res.error_type.should == Net::HTTPClientException res = Net::HTTPServerError.new("1.0", "5xx", "test response") res.error_type.should == Net::HTTPFatalError diff --git a/ruby/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb index c0812cd32..0c9c11291 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb @@ -7,12 +7,7 @@ Net::HTTPInformation.exception_type.should == Net::HTTPError Net::HTTPSuccess.exception_type.should == Net::HTTPError Net::HTTPRedirection.exception_type.should == Net::HTTPRetriableError - ruby_version_is ""..."2.6" do - Net::HTTPClientError.exception_type.should == Net::HTTPServerException - end - ruby_version_is "2.6" do - Net::HTTPClientError.exception_type.should == Net::HTTPClientException - end + Net::HTTPClientError.exception_type.should == Net::HTTPClientException Net::HTTPServerError.exception_type.should == Net::HTTPFatalError end end diff --git a/ruby/spec/ruby/library/net/http/httpresponse/read_body_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/read_body_spec.rb index 99d8e5fa8..ec9b42f91 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/read_body_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/read_body_spec.rb @@ -1,5 +1,6 @@ require_relative '../../../../spec_helper' require 'net/http' +require 'stringio' describe "Net::HTTPResponse#read_body" do before :each do diff --git a/ruby/spec/ruby/library/net/http/httpresponse/read_new_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/read_new_spec.rb index 73c7ddc10..dc2cdc962 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/read_new_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/read_new_spec.rb @@ -1,5 +1,6 @@ require_relative '../../../../spec_helper' require 'net/http' +require 'stringio' describe "Net::HTTPResponse.read_new" do it "creates a HTTPResponse object based on the response read from the passed socket" do diff --git a/ruby/spec/ruby/library/net/http/httpresponse/shared/body.rb b/ruby/spec/ruby/library/net/http/httpresponse/shared/body.rb index 91d5fe637..618e3936f 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/shared/body.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/shared/body.rb @@ -1,3 +1,5 @@ +require 'stringio' + describe :net_httpresponse_body, shared: true do before :each do @res = Net::HTTPUnknownResponse.new("1.0", "???", "test response") diff --git a/ruby/spec/ruby/library/net/http/httpresponse/value_spec.rb b/ruby/spec/ruby/library/net/http/httpresponse/value_spec.rb index 4a5930d4e..5cd58316e 100644 --- a/ruby/spec/ruby/library/net/http/httpresponse/value_spec.rb +++ b/ruby/spec/ruby/library/net/http/httpresponse/value_spec.rb @@ -16,12 +16,7 @@ -> { res.value }.should raise_error(Net::HTTPRetriableError) res = Net::HTTPClientError.new("1.0", "4xx", "test response") - ruby_version_is ""..."2.6" do - -> { res.value }.should raise_error(Net::HTTPServerException) - end - ruby_version_is "2.6" do - -> { res.value }.should raise_error(Net::HTTPClientException) - end + -> { res.value }.should raise_error(Net::HTTPClientException) res = Net::HTTPServerError.new("1.0", "5xx", "test response") -> { res.value }.should raise_error(Net::HTTPFatalError) diff --git a/ruby/spec/ruby/library/objectspace/memsize_of_all_spec.rb b/ruby/spec/ruby/library/objectspace/memsize_of_all_spec.rb new file mode 100644 index 000000000..c5a48165c --- /dev/null +++ b/ruby/spec/ruby/library/objectspace/memsize_of_all_spec.rb @@ -0,0 +1,22 @@ +require_relative '../../spec_helper' +require 'objspace' + +describe "ObjectSpace.memsize_of_all" do + it "returns a non-zero Integer for all objects" do + ObjectSpace.memsize_of_all.should be_kind_of(Integer) + ObjectSpace.memsize_of_all.should > 0 + end + + it "returns a non-zero Integer for Class" do + ObjectSpace.memsize_of_all(Class).should be_kind_of(Integer) + ObjectSpace.memsize_of_all(Class).should > 0 + end + + it "increases when a new object is allocated" do + c = Class.new + before = ObjectSpace.memsize_of_all(c) + o = c.new + after = ObjectSpace.memsize_of_all(c) + after.should > before + end +end diff --git a/ruby/spec/ruby/library/objectspace/memsize_of_spec.rb b/ruby/spec/ruby/library/objectspace/memsize_of_spec.rb index 06a80d9f9..eefafbb33 100644 --- a/ruby/spec/ruby/library/objectspace/memsize_of_spec.rb +++ b/ruby/spec/ruby/library/objectspace/memsize_of_spec.rb @@ -12,7 +12,11 @@ ObjectSpace.memsize_of(42).should == 0 end - it "returns an Integer for an Object" do + it "returns 0 for literal Symbols" do + ObjectSpace.memsize_of(:abc).should == 0 + end + + it "returns a positive Integer for an Object" do obj = Object.new ObjectSpace.memsize_of(obj).should be_kind_of(Integer) ObjectSpace.memsize_of(obj).should > 0 diff --git a/ruby/spec/ruby/library/objectspace/trace_object_allocations_spec.rb b/ruby/spec/ruby/library/objectspace/trace_object_allocations_spec.rb new file mode 100644 index 000000000..3100511dc --- /dev/null +++ b/ruby/spec/ruby/library/objectspace/trace_object_allocations_spec.rb @@ -0,0 +1,131 @@ +require_relative '../../spec_helper' +require 'objspace' + +describe "ObjectSpace.trace_object_allocations" do + it "runs a block" do + ScratchPad.clear + ObjectSpace.trace_object_allocations do + ScratchPad.record :a + end + ScratchPad.recorded.should == :a + end + + it "records info for allocation_class_path" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + a = [1, 2, 3] + ObjectSpace.allocation_class_path(a).should == nil + end + end + + it "records info for allocation_generation" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_generation(o).should.kind_of?(Integer) + a = [1, 2, 3] + ObjectSpace.allocation_generation(a).should.kind_of?(Integer) + end + end + + it "records info for allocation_method_id" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_method_id(o).should == :new + a = [1, 2, 3] + ObjectSpace.allocation_method_id(a).should == nil + end + end + + it "records info for allocation_sourcefile" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_sourcefile(o).should == __FILE__ + a = [1, 2, 3] + ObjectSpace.allocation_sourcefile(a).should == __FILE__ + end + end + + it "records info for allocation_sourceline" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_sourceline(o).should == __LINE__ - 1 + a = [1, 2, 3] + ObjectSpace.allocation_sourceline(a).should == __LINE__ - 1 + end + end + + it "can be cleared using trace_object_allocations_clear" do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + ObjectSpace.trace_object_allocations_clear + ObjectSpace.allocation_class_path(o).should be_nil + end + end + + it "does not clears allocation data after returning" do + o = nil + ObjectSpace.trace_object_allocations do + o = Object.new + end + ObjectSpace.allocation_class_path(o).should == "Class" + end + + it "can be used without a block using trace_object_allocations_start and _stop" do + ObjectSpace.trace_object_allocations_start + begin + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + a = [1, 2, 3] + ObjectSpace.allocation_class_path(a).should == nil + ensure + ObjectSpace.trace_object_allocations_stop + end + end + + it "does not clears allocation data after trace_object_allocations_stop" do + ObjectSpace.trace_object_allocations_start + begin + o = Object.new + ensure + ObjectSpace.trace_object_allocations_stop + end + ObjectSpace.allocation_class_path(o).should == "Class" + end + + it "can be nested" do + ObjectSpace.trace_object_allocations do + ObjectSpace.trace_object_allocations do + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + end + end + end + + it "can be nested without a block using trace_object_allocations_start and _stop" do + ObjectSpace.trace_object_allocations_start + begin + ObjectSpace.trace_object_allocations_start + begin + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + ensure + ObjectSpace.trace_object_allocations_stop + end + ensure + ObjectSpace.trace_object_allocations_stop + end + end + + it "can be nested with more _stop than _start" do + ObjectSpace.trace_object_allocations_start + begin + o = Object.new + ObjectSpace.allocation_class_path(o).should == "Class" + ObjectSpace.trace_object_allocations_stop + ensure + ObjectSpace.trace_object_allocations_stop + end + end +end diff --git a/ruby/spec/ruby/library/openssl/config/freeze_spec.rb b/ruby/spec/ruby/library/openssl/config/freeze_spec.rb index 1876095d9..c814341b8 100644 --- a/ruby/spec/ruby/library/openssl/config/freeze_spec.rb +++ b/ruby/spec/ruby/library/openssl/config/freeze_spec.rb @@ -3,18 +3,20 @@ require 'openssl' -describe "OpenSSL::Config#freeze" do - it "needs to be reviewed for completeness" +version_is(OpenSSL::VERSION, ""..."2.2") do + describe "OpenSSL::Config#freeze" do + it "needs to be reviewed for completeness" - it "freezes" do - c = OpenSSL::Config.new - -> { - c['foo'] = [ ['key', 'value'] ] - }.should_not raise_error - c.freeze - c.frozen?.should be_true - -> { - c['foo'] = [ ['key', 'value'] ] - }.should raise_error(TypeError) + it "freezes" do + c = OpenSSL::Config.new + -> { + c['foo'] = [ ['key', 'value'] ] + }.should_not raise_error + c.freeze + c.frozen?.should be_true + -> { + c['foo'] = [ ['key', 'value'] ] + }.should raise_error(TypeError) + end end end diff --git a/ruby/spec/ruby/library/openssl/digest_spec.rb b/ruby/spec/ruby/library/openssl/digest_spec.rb new file mode 100644 index 000000000..b8e82d073 --- /dev/null +++ b/ruby/spec/ruby/library/openssl/digest_spec.rb @@ -0,0 +1,63 @@ +require_relative '../../spec_helper' +require_relative '../../library/digest/sha1/shared/constants' +require_relative '../../library/digest/sha256/shared/constants' +require_relative '../../library/digest/sha384/shared/constants' +require_relative '../../library/digest/sha512/shared/constants' +require 'openssl' + +describe "OpenSSL::Digest" do + + describe ".digest" do + it "returns a SHA1 digest" do + OpenSSL::Digest.digest('sha1', SHA1Constants::Contents).should == SHA1Constants::Digest + end + + it "returns a SHA256 digest" do + OpenSSL::Digest.digest('sha256', SHA256Constants::Contents).should == SHA256Constants::Digest + end + + it "returns a SHA384 digest" do + OpenSSL::Digest.digest('sha384', SHA384Constants::Contents).should == SHA384Constants::Digest + end + + it "returns a SHA512 digest" do + OpenSSL::Digest.digest('sha512', SHA512Constants::Contents).should == SHA512Constants::Digest + end + end + + describe ".hexdigest" do + it "returns a SHA1 hexdigest" do + OpenSSL::Digest.hexdigest('sha1', SHA1Constants::Contents).should == SHA1Constants::Hexdigest + end + + it "returns a SHA256 hexdigest" do + OpenSSL::Digest.hexdigest('sha256', SHA256Constants::Contents).should == SHA256Constants::Hexdigest + end + + it "returns a SHA384 hexdigest" do + OpenSSL::Digest.hexdigest('sha384', SHA384Constants::Contents).should == SHA384Constants::Hexdigest + end + + it "returns a SHA512 hexdigest" do + OpenSSL::Digest.hexdigest('sha512', SHA512Constants::Contents).should == SHA512Constants::Hexdigest + end + end + + describe ".base64digest" do + it "returns a SHA1 base64digest" do + OpenSSL::Digest.base64digest('sha1', SHA1Constants::Contents).should == SHA1Constants::Base64digest + end + + it "returns a SHA256 base64digest" do + OpenSSL::Digest.base64digest('sha256', SHA256Constants::Contents).should == SHA256Constants::Base64digest + end + + it "returns a SHA384 base64digest" do + OpenSSL::Digest.base64digest('sha384', SHA384Constants::Contents).should == SHA384Constants::Base64digest + end + + it "returns a SHA512 base64digest" do + OpenSSL::Digest.base64digest('sha512', SHA512Constants::Contents).should == SHA512Constants::Base64digest + end + end +end diff --git a/ruby/spec/ruby/library/openssl/hmac/digest_spec.rb b/ruby/spec/ruby/library/openssl/hmac/digest_spec.rb index 22bc7023b..03ed136e6 100644 --- a/ruby/spec/ruby/library/openssl/hmac/digest_spec.rb +++ b/ruby/spec/ruby/library/openssl/hmac/digest_spec.rb @@ -4,7 +4,7 @@ describe "OpenSSL::HMAC.digest" do it "returns an SHA1 digest" do - cur_digest = OpenSSL::Digest::SHA1.new + cur_digest = OpenSSL::Digest.new("SHA1") cur_digest.digest.should == HMACConstants::BlankSHA1Digest digest = OpenSSL::HMAC.digest(cur_digest, HMACConstants::Key, diff --git a/ruby/spec/ruby/library/openssl/hmac/hexdigest_spec.rb b/ruby/spec/ruby/library/openssl/hmac/hexdigest_spec.rb index 7f73b2db0..3508c1bbd 100644 --- a/ruby/spec/ruby/library/openssl/hmac/hexdigest_spec.rb +++ b/ruby/spec/ruby/library/openssl/hmac/hexdigest_spec.rb @@ -4,7 +4,7 @@ describe "OpenSSL::HMAC.hexdigest" do it "returns an SHA1 hex digest" do - cur_digest = OpenSSL::Digest::SHA1.new + cur_digest = OpenSSL::Digest.new("SHA1") cur_digest.hexdigest.should == HMACConstants::BlankSHA1HexDigest hexdigest = OpenSSL::HMAC.hexdigest(cur_digest, HMACConstants::Key, diff --git a/ruby/spec/ruby/library/openstruct/frozen_spec.rb b/ruby/spec/ruby/library/openstruct/frozen_spec.rb index 63767bb54..c14a4bac5 100644 --- a/ruby/spec/ruby/library/openstruct/frozen_spec.rb +++ b/ruby/spec/ruby/library/openstruct/frozen_spec.rb @@ -24,6 +24,7 @@ it "creates a frozen clone" do f = @os.clone + f.frozen?.should == true f.age.should == 70 ->{ f.age = 0 }.should raise_error( RuntimeError ) ->{ f.state = :newer }.should raise_error( RuntimeError ) @@ -31,6 +32,7 @@ it "creates an unfrozen dup" do d = @os.dup + d.frozen?.should == false d.age.should == 70 d.age = 42 d.age.should == 42 diff --git a/ruby/spec/ruby/library/openstruct/marshal_load_spec.rb b/ruby/spec/ruby/library/openstruct/marshal_load_spec.rb index e07c4cef0..342e5e68c 100644 --- a/ruby/spec/ruby/library/openstruct/marshal_load_spec.rb +++ b/ruby/spec/ruby/library/openstruct/marshal_load_spec.rb @@ -4,7 +4,7 @@ describe "OpenStruct#marshal_load when passed [Hash]" do it "defines methods based on the passed Hash" do os = OpenStruct.new - os.marshal_load(age: 20, name: "John") + os.send :marshal_load, age: 20, name: "John" os.age.should eql(20) os.name.should == "John" diff --git a/ruby/spec/ruby/library/openstruct/method_missing_spec.rb b/ruby/spec/ruby/library/openstruct/method_missing_spec.rb index 1992b7255..212db015a 100644 --- a/ruby/spec/ruby/library/openstruct/method_missing_spec.rb +++ b/ruby/spec/ruby/library/openstruct/method_missing_spec.rb @@ -7,43 +7,20 @@ end it "raises an ArgumentError when not passed any additional arguments" do - -> { @os.method_missing(:test=) }.should raise_error(ArgumentError) - end - - it "raises a TypeError when self is frozen" do - @os.freeze - -> { @os.method_missing(:test=, "test") }.should raise_error(RuntimeError) - end - - it "creates accessor methods" do - @os.method_missing(:test=, "test") - @os.respond_to?(:test=).should be_true - @os.respond_to?(:test).should be_true - - @os.test.should == "test" - @os.test = "changed" - @os.test.should == "changed" + -> { @os.send(:test=) }.should raise_error(ArgumentError) end end describe "OpenStruct#method_missing when passed additional arguments" do it "raises a NoMethodError when the key does not exist" do os = OpenStruct.new - -> { os.method_missing(:test, 1, 2, 3) }.should raise_error(NoMethodError) + -> { os.test(1, 2, 3) }.should raise_error(NoMethodError) end ruby_version_is "2.7" do it "raises an ArgumentError when the key exists" do os = OpenStruct.new(test: 20) - -> { os.method_missing(:test, 1, 2, 3) }.should raise_error(ArgumentError) + -> { os.test(1, 2, 3) }.should raise_error(ArgumentError) end end end - -describe "OpenStruct#method_missing when not passed any additional arguments" do - it "returns the value for the passed method from the method/value table" do - os = OpenStruct.new(age: 20) - os.method_missing(:age).should eql(20) - os.method_missing(:name).should be_nil - end -end diff --git a/ruby/spec/ruby/library/openstruct/to_h_spec.rb b/ruby/spec/ruby/library/openstruct/to_h_spec.rb index ebdec1617..6c272bcc7 100644 --- a/ruby/spec/ruby/library/openstruct/to_h_spec.rb +++ b/ruby/spec/ruby/library/openstruct/to_h_spec.rb @@ -27,44 +27,42 @@ @os.age.should == 70 end - ruby_version_is "2.6" do - context "with block" do - it "converts [key, value] pairs returned by the block to a hash" do - h = @os.to_h { |k, v| [k.to_s, v*2] } - h.should == { "name" => "John SmithJohn Smith", "age" => 140, "pension" => 600 } - end + context "with block" do + it "converts [key, value] pairs returned by the block to a hash" do + h = @os.to_h { |k, v| [k.to_s, v*2] } + h.should == { "name" => "John SmithJohn Smith", "age" => 140, "pension" => 600 } + end - it "raises ArgumentError if block returns longer or shorter array" do - -> do - @os.to_h { |k, v| [k.to_s, v*2, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) + it "raises ArgumentError if block returns longer or shorter array" do + -> do + @os.to_h { |k, v| [k.to_s, v*2, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) - -> do - @os.to_h { |k, v| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end + -> do + @os.to_h { |k, v| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end - it "raises TypeError if block returns something other than Array" do - -> do - @os.to_h { |k, v| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end + it "raises TypeError if block returns something other than Array" do + -> do + @os.to_h { |k, v| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) - @os.to_h { |k| x }.should == { :b => 'b' } - end + @os.to_h { |k| x }.should == { :b => 'b' } + end - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) - -> do - @os.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end + -> do + @os.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) end end end diff --git a/ruby/spec/ruby/library/pathname/absolute_spec.rb b/ruby/spec/ruby/library/pathname/absolute_spec.rb index dce3ae72e..109abb8ee 100644 --- a/ruby/spec/ruby/library/pathname/absolute_spec.rb +++ b/ruby/spec/ruby/library/pathname/absolute_spec.rb @@ -4,19 +4,19 @@ describe "Pathname#absolute?" do it "returns true for the root directory" do - Pathname.new('/').absolute?.should == true + Pathname.new('/').should.absolute? end it "returns true for a dir starting with a slash" do - Pathname.new('/usr/local/bin').absolute?.should == true + Pathname.new('/usr/local/bin').should.absolute? end it "returns false for a dir not starting with a slash" do - Pathname.new('fish').absolute?.should == false + Pathname.new('fish').should_not.absolute? end it "returns false for a dir not starting with a slash" do - Pathname.new('fish/dog/cow').absolute?.should == false + Pathname.new('fish/dog/cow').should_not.absolute? end end diff --git a/ruby/spec/ruby/library/pathname/divide_spec.rb b/ruby/spec/ruby/library/pathname/divide_spec.rb new file mode 100644 index 000000000..8af79d0c8 --- /dev/null +++ b/ruby/spec/ruby/library/pathname/divide_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative 'shared/plus' + +describe "Pathname#/" do + it_behaves_like :pathname_plus, :/ +end diff --git a/ruby/spec/ruby/library/pathname/glob_spec.rb b/ruby/spec/ruby/library/pathname/glob_spec.rb new file mode 100644 index 000000000..f6dfd6cd5 --- /dev/null +++ b/ruby/spec/ruby/library/pathname/glob_spec.rb @@ -0,0 +1,57 @@ +require_relative '../../spec_helper' +require 'pathname' + +describe 'Pathname.glob' do + before :all do + @dir = tmp('pathname_glob') + '/' + @file_1 = @dir + 'lib/ipaddr.rb' + @file_2 = @dir + 'lib/irb.rb' + @file_3 = @dir + 'lib/.hidden.rb' + + touch @file_1 + touch @file_2 + touch @file_3 + end + + after :all do + rm_r @dir[0...-1] + end + + it 'returns [] for no match' do + Pathname.glob(@dir + 'lib/*.js').should == [] + end + + it 'returns matching file paths' do + Pathname.glob(@dir + 'lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort + end + + it 'returns matching file paths when a flag is provided' do + expected = [Pathname.new(@file_1), Pathname.new(@file_2), Pathname.new(@file_3)].sort + Pathname.glob(@dir + 'lib/*i*.rb', File::FNM_DOTMATCH).sort.should == expected + end + + it 'returns matching file paths when supplied :base keyword argument' do + Pathname.glob('*i*.rb', base: @dir + 'lib').sort.should == [Pathname.new('ipaddr.rb'), Pathname.new('irb.rb')].sort + end + + it "raises an ArgumentError when supplied a keyword argument other than :base" do + -> { + Pathname.glob('*i*.rb', foo: @dir + 'lib') + }.should raise_error(ArgumentError, /unknown keyword: :?foo/) + end + + ruby_version_is ''...'2.7' do + it 'raises an ArgumentError when supplied a flag and :base keyword argument' do + -> { + Pathname.glob(@dir + 'lib/*i*.rb', File::FNM_DOTMATCH, base: 'lib') + }.should raise_error(ArgumentError, 'wrong number of arguments (given 3, expected 1..2)') + end + end + + ruby_version_is "2.7" do + it "does not raise an ArgumentError when supplied a flag and :base keyword argument" do + expected = [Pathname.new('ipaddr.rb'), Pathname.new('irb.rb'), Pathname.new('.hidden.rb')].sort + Pathname.glob('*i*.rb', File::FNM_DOTMATCH, base: @dir + 'lib').sort.should == expected + end + end +end diff --git a/ruby/spec/ruby/library/pathname/inspect_spec.rb b/ruby/spec/ruby/library/pathname/inspect_spec.rb new file mode 100644 index 000000000..304746fbe --- /dev/null +++ b/ruby/spec/ruby/library/pathname/inspect_spec.rb @@ -0,0 +1,10 @@ +require_relative '../../spec_helper' +require 'pathname' + +describe "Pathname#inspect" do + it "returns a consistent String" do + result = Pathname.new('/tmp').inspect + result.should be_an_instance_of(String) + result.should == "#" + end +end diff --git a/ruby/spec/ruby/library/pathname/new_spec.rb b/ruby/spec/ruby/library/pathname/new_spec.rb index dcb770149..760fd8638 100644 --- a/ruby/spec/ruby/library/pathname/new_spec.rb +++ b/ruby/spec/ruby/library/pathname/new_spec.rb @@ -13,7 +13,7 @@ ruby_version_is ''...'2.7' do it "is tainted if path is tainted" do path = '/usr/local/bin'.taint - Pathname.new(path).tainted?.should == true + Pathname.new(path).should.tainted? end end diff --git a/ruby/spec/ruby/library/pathname/pathname_spec.rb b/ruby/spec/ruby/library/pathname/pathname_spec.rb new file mode 100644 index 000000000..7d63fe86e --- /dev/null +++ b/ruby/spec/ruby/library/pathname/pathname_spec.rb @@ -0,0 +1,30 @@ +require_relative '../../spec_helper' +require 'pathname' + +describe "Kernel#Pathname" do + it "is a private instance method" do + Kernel.should have_private_instance_method(:Pathname) + end + + it "is also a public method" do + Kernel.should have_method(:Pathname) + end + + ruby_version_is ''...'2.7' do + it "returns a new pathname when called with a pathname argument" do + path = Pathname('foo') + new_path = Pathname(path) + + path.should_not.equal?(new_path) + end + end + + ruby_version_is '2.7' do + it "returns same argument when called with a pathname argument" do + path = Pathname('foo') + new_path = Pathname(path) + + path.should.equal?(new_path) + end + end +end diff --git a/ruby/spec/ruby/library/pathname/plus_spec.rb b/ruby/spec/ruby/library/pathname/plus_spec.rb new file mode 100644 index 000000000..57e472c26 --- /dev/null +++ b/ruby/spec/ruby/library/pathname/plus_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative 'shared/plus' + +describe "Pathname#+" do + it_behaves_like :pathname_plus, :+ +end diff --git a/ruby/spec/ruby/library/pathname/relative_spec.rb b/ruby/spec/ruby/library/pathname/relative_spec.rb index 1a08891e6..0fab9a7b9 100644 --- a/ruby/spec/ruby/library/pathname/relative_spec.rb +++ b/ruby/spec/ruby/library/pathname/relative_spec.rb @@ -4,19 +4,19 @@ describe "Pathname#relative?" do it "returns false for the root directory" do - Pathname.new('/').relative?.should == false + Pathname.new('/').should_not.relative? end it "returns false for a dir starting with a slash" do - Pathname.new('/usr/local/bin').relative?.should == false + Pathname.new('/usr/local/bin').should_not.relative? end it "returns true for a dir not starting with a slash" do - Pathname.new('fish').relative?.should == true + Pathname.new('fish').should.relative? end it "returns true for a dir not starting with a slash" do - Pathname.new('fish/dog/cow').relative?.should == true + Pathname.new('fish/dog/cow').should.relative? end end diff --git a/ruby/spec/ruby/library/pathname/root_spec.rb b/ruby/spec/ruby/library/pathname/root_spec.rb index 5fec0ee95..cd2be2451 100644 --- a/ruby/spec/ruby/library/pathname/root_spec.rb +++ b/ruby/spec/ruby/library/pathname/root_spec.rb @@ -4,23 +4,23 @@ describe "Pathname#root?" do it "returns true for root directories" do - Pathname.new('/').root?.should == true + Pathname.new('/').should.root? end it "returns false for empty string" do - Pathname.new('').root?.should == false + Pathname.new('').should_not.root? end it "returns false for a top level directory" do - Pathname.new('/usr').root?.should == false + Pathname.new('/usr').should_not.root? end it "returns false for a top level with .. appended directory" do - Pathname.new('/usr/..').root?.should == false + Pathname.new('/usr/..').should_not.root? end it "returns false for a directory below top level" do - Pathname.new('/usr/local/bin/').root?.should == false + Pathname.new('/usr/local/bin/').should_not.root? end end diff --git a/ruby/spec/ruby/library/pathname/shared/plus.rb b/ruby/spec/ruby/library/pathname/shared/plus.rb new file mode 100644 index 000000000..b3b896ea4 --- /dev/null +++ b/ruby/spec/ruby/library/pathname/shared/plus.rb @@ -0,0 +1,8 @@ +require 'pathname' + +describe :pathname_plus, shared: true do + it "appends a pathname to self" do + p = Pathname.new("/usr") + p.send(@method, "bin/ruby").should == Pathname.new("/usr/bin/ruby") + end +end diff --git a/ruby/spec/ruby/library/prime/each_spec.rb b/ruby/spec/ruby/library/prime/each_spec.rb index b99cf7cf0..c89e87158 100644 --- a/ruby/spec/ruby/library/prime/each_spec.rb +++ b/ruby/spec/ruby/library/prime/each_spec.rb @@ -1,167 +1,170 @@ require_relative '../../spec_helper' -require 'prime' -describe :prime_each, shared: true do - before :each do - ScratchPad.record [] - end +ruby_version_is ""..."3.1" do + require 'prime' - it "enumerates primes" do - primes = Prime.instance - result = [] + describe :prime_each, shared: true do + before :each do + ScratchPad.record [] + end - primes.each { |p| - result << p - break if p > 10 - } + it "enumerates primes" do + primes = Prime.instance + result = [] - result.should == [2, 3, 5, 7, 11] - end + primes.each { |p| + result << p + break if p > 10 + } - it "yields ascending primes to the block" do - previous = 1 - @object.each do |prime| - break if prime > 1000 - ScratchPad << prime - prime.should > previous - previous = prime + result.should == [2, 3, 5, 7, 11] end - all_prime = true - ScratchPad.recorded.all? do |prime| - all_prime &&= (2..Math.sqrt(prime)).all? { |d| prime % d != 0 } + it "yields ascending primes to the block" do + previous = 1 + @object.each do |prime| + break if prime > 1000 + ScratchPad << prime + prime.should > previous + previous = prime + end + + all_prime = true + ScratchPad.recorded.all? do |prime| + all_prime &&= (2..Math.sqrt(prime)).all? { |d| prime % d != 0 } + end + + all_prime.should be_true end - all_prime.should be_true - end + it "returns the last evaluated expression in the passed block" do + @object.each { break :value }.should equal(:value) + end - it "returns the last evaluated expression in the passed block" do - @object.each { break :value }.should equal(:value) - end + describe "when not passed a block" do + before :each do + @prime_enum = @object.each + end - describe "when not passed a block" do - before :each do - @prime_enum = @object.each - end + it "returns an object that is Enumerable" do + @prime_enum.each.should be_kind_of(Enumerable) + end - it "returns an object that is Enumerable" do - @prime_enum.each.should be_kind_of(Enumerable) - end + it "returns an object that responds to #with_index" do + @prime_enum.should respond_to(:with_index) + end - it "returns an object that responds to #with_index" do - @prime_enum.should respond_to(:with_index) - end + it "returns an object that responds to #with_object" do + @prime_enum.should respond_to(:with_object) + end - it "returns an object that responds to #with_object" do - @prime_enum.should respond_to(:with_object) - end + it "returns an object that responds to #next" do + @prime_enum.should respond_to(:next) + end - it "returns an object that responds to #next" do - @prime_enum.should respond_to(:next) - end + it "returns an object that responds to #rewind" do + @prime_enum.should respond_to(:rewind) + end - it "returns an object that responds to #rewind" do - @prime_enum.should respond_to(:rewind) - end + it "yields primes starting at 2 independent of prior enumerators" do + @prime_enum.next.should == 2 + @prime_enum.next.should == 3 - it "yields primes starting at 2 independent of prior enumerators" do - @prime_enum.next.should == 2 - @prime_enum.next.should == 3 + @object.each { |prime| break prime }.should == 2 + end - @object.each { |prime| break prime }.should == 2 + it "returns an enumerator that yields previous primes when #rewind is called" do + @prime_enum.next.should == 2 + @prime_enum.next.should == 3 + @prime_enum.rewind + @prime_enum.next.should == 2 + end + + it "returns independent enumerators" do + enum = @object.each + enum.next.should == 2 + enum.next.should == 3 + + @prime_enum.next.should == 2 + + enum.next.should == 5 + end end + end - it "returns an enumerator that yields previous primes when #rewind is called" do - @prime_enum.next.should == 2 - @prime_enum.next.should == 3 - @prime_enum.rewind - @prime_enum.next.should == 2 + describe :prime_each_with_arguments, shared: true do + before :each do + ScratchPad.record [] end - it "returns independent enumerators" do - enum = @object.each - enum.next.should == 2 - enum.next.should == 3 + it "yields ascending primes less than or equal to the argument" do + bound = 1000 + previous = 1 + @object.each(bound) do |prime| + ScratchPad << prime + prime.should > previous + previous = prime + end - @prime_enum.next.should == 2 + ScratchPad.recorded.all? do |prime| + (2..Math.sqrt(prime)).all? { |d| prime % d != 0 } + end.should be_true - enum.next.should == 5 + ScratchPad.recorded.all? { |prime| prime <= bound }.should be_true end - end -end -describe :prime_each_with_arguments, shared: true do - before :each do - ScratchPad.record [] - end + it "returns nil when no prime is generated" do + @object.each(1) { :value }.should be_nil + end - it "yields ascending primes less than or equal to the argument" do - bound = 1000 - previous = 1 - @object.each(bound) do |prime| - ScratchPad << prime - prime.should > previous - previous = prime + it "yields primes starting at 2 independent of prior enumeration" do + @object.each(10) { |prime| prime }.should == 7 + @object.each(10) { |prime| break prime }.should == 2 end - ScratchPad.recorded.all? do |prime| - (2..Math.sqrt(prime)).all? { |d| prime % d != 0 } - end.should be_true + it "accepts a pseudo-prime generator as the second argument" do + generator = mock('very bad pseudo-prime generator') + generator.should_receive(:upper_bound=).with(100) + generator.should_receive(:each).and_yield(2).and_yield(3).and_yield(4) - ScratchPad.recorded.all? { |prime| prime <= bound }.should be_true - end + @object.each(100, generator) { |prime| ScratchPad << prime } + ScratchPad.recorded.should == [2, 3, 4] + end - it "returns nil when no prime is generated" do - @object.each(1) { :value }.should be_nil + describe "when not passed a block" do + it "returns an object that returns primes less than or equal to the bound" do + bound = 100 + @object.each(bound).all? { |prime| prime <= bound }.should be_true + end + end end - it "yields primes starting at 2 independent of prior enumeration" do - @object.each(10) { |prime| prime }.should == 7 - @object.each(10) { |prime| break prime }.should == 2 + describe "Prime.each" do + it_behaves_like :prime_each, :each, Prime end - it "accepts a pseudo-prime generator as the second argument" do - generator = mock('very bad pseudo-prime generator') - generator.should_receive(:upper_bound=).with(100) - generator.should_receive(:each).and_yield(2).and_yield(3).and_yield(4) - - @object.each(100, generator) { |prime| ScratchPad << prime } - ScratchPad.recorded.should == [2, 3, 4] + describe "Prime.each" do + it_behaves_like :prime_each_with_arguments, :each, Prime end - describe "when not passed a block" do - it "returns an object that returns primes less than or equal to the bound" do - bound = 100 - @object.each(bound).all? { |prime| prime <= bound }.should be_true - end + describe "Prime#each with Prime.instance" do + it_behaves_like :prime_each, :each, Prime.instance end -end -describe "Prime.each" do - it_behaves_like :prime_each, :each, Prime -end - -describe "Prime.each" do - it_behaves_like :prime_each_with_arguments, :each, Prime -end - -describe "Prime#each with Prime.instance" do - it_behaves_like :prime_each, :each, Prime.instance -end - -describe "Prime#each with Prime.instance" do - it_behaves_like :prime_each_with_arguments, :each, Prime.instance -end - -describe "Prime#each with Prime.instance" do - before :each do - @object = Prime.instance + describe "Prime#each with Prime.instance" do + it_behaves_like :prime_each_with_arguments, :each, Prime.instance end - it_behaves_like :prime_each, :each + describe "Prime#each with Prime.instance" do + before :each do + @object = Prime.instance + end + + it_behaves_like :prime_each, :each - it "resets the enumerator with each call" do - @object.each { |prime| break if prime > 10 } - @object.each { |prime| break prime }.should == 2 + it "resets the enumerator with each call" do + @object.each { |prime| break if prime > 10 } + @object.each { |prime| break prime }.should == 2 + end end end diff --git a/ruby/spec/ruby/library/prime/instance_spec.rb b/ruby/spec/ruby/library/prime/instance_spec.rb index 5183f3690..82f21913b 100644 --- a/ruby/spec/ruby/library/prime/instance_spec.rb +++ b/ruby/spec/ruby/library/prime/instance_spec.rb @@ -1,21 +1,24 @@ require_relative '../../spec_helper' -require 'prime' -describe "Prime.instance" do - it "returns a object representing the set of prime numbers" do - Prime.instance.should be_kind_of(Prime) - end +ruby_version_is ""..."3.1" do + require 'prime' - it "returns a object with no obsolete features" do - Prime.instance.should_not respond_to(:succ) - Prime.instance.should_not respond_to(:next) - end + describe "Prime.instance" do + it "returns a object representing the set of prime numbers" do + Prime.instance.should be_kind_of(Prime) + end - it "does not complain anything" do - -> { Prime.instance }.should_not complain - end + it "returns a object with no obsolete features" do + Prime.instance.should_not respond_to(:succ) + Prime.instance.should_not respond_to(:next) + end + + it "does not complain anything" do + -> { Prime.instance }.should_not complain + end - it "raises a ArgumentError when is called with some arguments" do - -> { Prime.instance(1) }.should raise_error(ArgumentError) + it "raises a ArgumentError when is called with some arguments" do + -> { Prime.instance(1) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/prime/int_from_prime_division_spec.rb b/ruby/spec/ruby/library/prime/int_from_prime_division_spec.rb index 5abb7221d..5c881aefa 100644 --- a/ruby/spec/ruby/library/prime/int_from_prime_division_spec.rb +++ b/ruby/spec/ruby/library/prime/int_from_prime_division_spec.rb @@ -1,13 +1,16 @@ require_relative '../../spec_helper' -require 'prime' -describe "Prime.int_from_prime_division" do - it "returns the product of the given factorization" do - Prime.int_from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]). - should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3 - end +ruby_version_is ""..."3.1" do + require 'prime' + + describe "Prime.int_from_prime_division" do + it "returns the product of the given factorization" do + Prime.int_from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]). + should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3 + end - it "returns 1 for an empty factorization" do - Prime.int_from_prime_division([]).should == 1 + it "returns 1 for an empty factorization" do + Prime.int_from_prime_division([]).should == 1 + end end end diff --git a/ruby/spec/ruby/library/prime/integer/each_prime_spec.rb b/ruby/spec/ruby/library/prime/integer/each_prime_spec.rb index a71296b0d..6034802e7 100644 --- a/ruby/spec/ruby/library/prime/integer/each_prime_spec.rb +++ b/ruby/spec/ruby/library/prime/integer/each_prime_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'prime' -describe "Integer.each_prime" do - it "is transferred to Prime.each" do - Prime.should_receive(:each).with(100).and_yield(2).and_yield(3).and_yield(5) - yielded = [] - Integer.each_prime(100) do |prime| - yielded << prime +ruby_version_is ""..."3.1" do + require 'prime' + + describe "Integer.each_prime" do + it "is transferred to Prime.each" do + Prime.should_receive(:each).with(100).and_yield(2).and_yield(3).and_yield(5) + yielded = [] + Integer.each_prime(100) do |prime| + yielded << prime + end + yielded.should == [2,3,5] end - yielded.should == [2,3,5] end end diff --git a/ruby/spec/ruby/library/prime/integer/from_prime_division_spec.rb b/ruby/spec/ruby/library/prime/integer/from_prime_division_spec.rb index e0e74fb33..5422bc651 100644 --- a/ruby/spec/ruby/library/prime/integer/from_prime_division_spec.rb +++ b/ruby/spec/ruby/library/prime/integer/from_prime_division_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'prime' -describe "Integer.from_prime_division" do - it "returns the product of the given factorization" do - Integer.from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]). - should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3 - end +ruby_version_is ""..."3.1" do + require 'prime' + + describe "Integer.from_prime_division" do + it "returns the product of the given factorization" do + Integer.from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]). + should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3 + end - it "returns 1 for an empty factorization" do - Integer.from_prime_division([]).should == 1 + it "returns 1 for an empty factorization" do + Integer.from_prime_division([]).should == 1 + end end end diff --git a/ruby/spec/ruby/library/prime/integer/prime_division_spec.rb b/ruby/spec/ruby/library/prime/integer/prime_division_spec.rb index be03438a6..03be0be27 100644 --- a/ruby/spec/ruby/library/prime/integer/prime_division_spec.rb +++ b/ruby/spec/ruby/library/prime/integer/prime_division_spec.rb @@ -1,19 +1,22 @@ require_relative '../../../spec_helper' -require 'prime' -describe "Integer#prime_division" do - it "returns an array of a prime factor and a corresponding exponent" do - (2*3*5*7*11*13*17).prime_division.should == - [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]] - end +ruby_version_is ""..."3.1" do + require 'prime' - it "returns an empty array for 1" do - 1.prime_division.should == [] - end - it "returns an empty array for -1" do - -1.prime_division.should == [[-1, 1]] - end - it "raises ZeroDivisionError for 0" do - -> { 0.prime_division }.should raise_error(ZeroDivisionError) + describe "Integer#prime_division" do + it "returns an array of a prime factor and a corresponding exponent" do + (2*3*5*7*11*13*17).prime_division.should == + [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]] + end + + it "returns an empty array for 1" do + 1.prime_division.should == [] + end + it "returns an empty array for -1" do + -1.prime_division.should == [[-1, 1]] + end + it "raises ZeroDivisionError for 0" do + -> { 0.prime_division }.should raise_error(ZeroDivisionError) + end end end diff --git a/ruby/spec/ruby/library/prime/integer/prime_spec.rb b/ruby/spec/ruby/library/prime/integer/prime_spec.rb index 53de76d5a..65b779e31 100644 --- a/ruby/spec/ruby/library/prime/integer/prime_spec.rb +++ b/ruby/spec/ruby/library/prime/integer/prime_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'prime' -describe "Integer#prime?" do - it "returns a true value for prime numbers" do - 2.prime?.should be_true - 3.prime?.should be_true - (2**31-1).prime?.should be_true # 8th Mersenne prime (M8) - end +ruby_version_is ""..."3.1" do + require 'prime' + + describe "Integer#prime?" do + it "returns a true value for prime numbers" do + 2.prime?.should be_true + 3.prime?.should be_true + (2**31-1).prime?.should be_true # 8th Mersenne prime (M8) + end - it "returns a false value for composite numbers" do - 4.prime?.should be_false - 15.prime?.should be_false - (2**32-1).prime?.should be_false - ( (2**17-1)*(2**19-1) ).prime?.should be_false # M6*M7 + it "returns a false value for composite numbers" do + 4.prime?.should be_false + 15.prime?.should be_false + (2**32-1).prime?.should be_false + ( (2**17-1)*(2**19-1) ).prime?.should be_false # M6*M7 + end end end diff --git a/ruby/spec/ruby/library/prime/next_spec.rb b/ruby/spec/ruby/library/prime/next_spec.rb index 39c4ae16a..8e805ed04 100644 --- a/ruby/spec/ruby/library/prime/next_spec.rb +++ b/ruby/spec/ruby/library/prime/next_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/next' -require 'prime' -describe "Prime#next" do - it_behaves_like :prime_next, :next +ruby_version_is ""..."3.1" do + require_relative 'shared/next' + require 'prime' + + describe "Prime#next" do + it_behaves_like :prime_next, :next + end end diff --git a/ruby/spec/ruby/library/prime/prime_division_spec.rb b/ruby/spec/ruby/library/prime/prime_division_spec.rb index 6293478f5..4c93d5936 100644 --- a/ruby/spec/ruby/library/prime/prime_division_spec.rb +++ b/ruby/spec/ruby/library/prime/prime_division_spec.rb @@ -1,25 +1,28 @@ require_relative '../../spec_helper' -require 'prime' -describe "Prime.prime_division" do - it "returns an array of a prime factor and a corresponding exponent" do - Prime.prime_division(2*3*5*7*11*13*17).should == - [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]] - end +ruby_version_is ""..."3.1" do + require 'prime' - it "returns an empty array for 1" do - Prime.prime_division(1).should == [] - end + describe "Prime.prime_division" do + it "returns an array of a prime factor and a corresponding exponent" do + Prime.prime_division(2*3*5*7*11*13*17).should == + [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]] + end - it "returns [[-1, 1]] for -1" do - Prime.prime_division(-1).should == [[-1, 1]] - end + it "returns an empty array for 1" do + Prime.prime_division(1).should == [] + end - it "includes [[-1, 1]] in the divisors of a negative number" do - Prime.prime_division(-10).should include([-1, 1]) - end + it "returns [[-1, 1]] for -1" do + Prime.prime_division(-1).should == [[-1, 1]] + end + + it "includes [[-1, 1]] in the divisors of a negative number" do + Prime.prime_division(-10).should include([-1, 1]) + end - it "raises ZeroDivisionError for 0" do - -> { Prime.prime_division(0) }.should raise_error(ZeroDivisionError) + it "raises ZeroDivisionError for 0" do + -> { Prime.prime_division(0) }.should raise_error(ZeroDivisionError) + end end end diff --git a/ruby/spec/ruby/library/prime/prime_spec.rb b/ruby/spec/ruby/library/prime/prime_spec.rb index 0896c7f0f..e2afddd5b 100644 --- a/ruby/spec/ruby/library/prime/prime_spec.rb +++ b/ruby/spec/ruby/library/prime/prime_spec.rb @@ -1,17 +1,20 @@ require_relative '../../spec_helper' -require 'prime' -describe "Prime#prime?" do - it "returns a true value for prime numbers" do - Prime.prime?(2).should be_true - Prime.prime?(3).should be_true - Prime.prime?(2**31-1).should be_true # 8th Mersenne prime (M8) - end +ruby_version_is ""..."3.1" do + require 'prime' + + describe "Prime#prime?" do + it "returns a true value for prime numbers" do + Prime.prime?(2).should be_true + Prime.prime?(3).should be_true + Prime.prime?(2**31-1).should be_true # 8th Mersenne prime (M8) + end - it "returns a false value for composite numbers" do - Prime.prime?(4).should be_false - Prime.prime?(15).should be_false - Prime.prime?(2**32-1).should be_false - Prime.prime?( (2**17-1)*(2**19-1) ).should be_false # M6*M7 + it "returns a false value for composite numbers" do + Prime.prime?(4).should be_false + Prime.prime?(15).should be_false + Prime.prime?(2**32-1).should be_false + Prime.prime?( (2**17-1)*(2**19-1) ).should be_false # M6*M7 + end end end diff --git a/ruby/spec/ruby/library/prime/succ_spec.rb b/ruby/spec/ruby/library/prime/succ_spec.rb index 34c18d2ba..9843dae25 100644 --- a/ruby/spec/ruby/library/prime/succ_spec.rb +++ b/ruby/spec/ruby/library/prime/succ_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/next' -require 'prime' -describe "Prime#succ" do - it_behaves_like :prime_next, :succ +ruby_version_is ""..."3.1" do + require_relative 'shared/next' + require 'prime' + + describe "Prime#succ" do + it_behaves_like :prime_next, :succ + end end diff --git a/ruby/spec/ruby/library/rbconfig/rbconfig_spec.rb b/ruby/spec/ruby/library/rbconfig/rbconfig_spec.rb index 35b465d10..b90cc9097 100644 --- a/ruby/spec/ruby/library/rbconfig/rbconfig_spec.rb +++ b/ruby/spec/ruby/library/rbconfig/rbconfig_spec.rb @@ -22,6 +22,12 @@ File.directory?(archdir).should == true File.should.exist?("#{archdir}/etc.#{RbConfig::CONFIG['DLEXT']}") end + + it "['sitelibdir'] is set and is part of $LOAD_PATH" do + sitelibdir = RbConfig::CONFIG['sitelibdir'] + sitelibdir.should be_kind_of String + $LOAD_PATH.map{|path| File.realpath(path) rescue path }.should.include? sitelibdir + end end it "contains no frozen strings even with --enable-frozen-string-literal" do @@ -35,6 +41,53 @@ puts 'Done' RUBY end + + platform_is_not :windows do + it "['LIBRUBY'] is the same as LIBRUBY_SO if and only if ENABLE_SHARED" do + case RbConfig::CONFIG['ENABLE_SHARED'] + when 'yes' + RbConfig::CONFIG['LIBRUBY'].should == RbConfig::CONFIG['LIBRUBY_SO'] + when 'no' + RbConfig::CONFIG['LIBRUBY'].should_not == RbConfig::CONFIG['LIBRUBY_SO'] + end + end + end + + guard -> { RbConfig::TOPDIR } do + it "libdir/LIBRUBY_SO is the path to libruby and it exists if and only if ENABLE_SHARED" do + libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' : + RbConfig::CONFIG['libdirname'] + libdir = RbConfig::CONFIG[libdirname] + libruby_so = "#{libdir}/#{RbConfig::CONFIG['LIBRUBY_SO']}" + case RbConfig::CONFIG['ENABLE_SHARED'] + when 'yes' + File.should.exist?(libruby_so) + when 'no' + File.should_not.exist?(libruby_so) + end + end + end + + platform_is :linux do + it "['AR'] exists and can be executed" do + ar = RbConfig::CONFIG.fetch('AR') + out = `#{ar} --version` + $?.should.success? + out.should_not be_empty + end + + it "['STRIP'] exists and can be executed" do + strip = RbConfig::CONFIG.fetch('STRIP') + copy = tmp("sh") + cp '/bin/sh', copy + begin + out = `#{strip} #{copy}` + $?.should.success? + ensure + rm_r copy + end + end + end end describe "RbConfig::TOPDIR" do diff --git a/ruby/spec/ruby/library/rbconfig/sizeof/limits_spec.rb b/ruby/spec/ruby/library/rbconfig/sizeof/limits_spec.rb index a026135ee..776099da2 100644 --- a/ruby/spec/ruby/library/rbconfig/sizeof/limits_spec.rb +++ b/ruby/spec/ruby/library/rbconfig/sizeof/limits_spec.rb @@ -1,42 +1,40 @@ require_relative '../../../spec_helper' require 'rbconfig/sizeof' -ruby_version_is "2.5" do - describe "RbConfig::LIMITS" do - it "is a Hash" do - RbConfig::LIMITS.should be_kind_of(Hash) - end +describe "RbConfig::LIMITS" do + it "is a Hash" do + RbConfig::LIMITS.should be_kind_of(Hash) + end - it "has string keys and numeric values" do - RbConfig::LIMITS.each do |key, value| - key.should be_kind_of String - value.should be_kind_of Numeric - end + it "has string keys and numeric values" do + RbConfig::LIMITS.each do |key, value| + key.should be_kind_of String + value.should be_kind_of Numeric end + end - it "contains FIXNUM_MIN and FIXNUM_MAX" do - RbConfig::LIMITS["FIXNUM_MIN"].should < 0 - RbConfig::LIMITS["FIXNUM_MAX"].should > 0 - end + it "contains FIXNUM_MIN and FIXNUM_MAX" do + RbConfig::LIMITS["FIXNUM_MIN"].should < 0 + RbConfig::LIMITS["FIXNUM_MAX"].should > 0 + end - it "contains CHAR_MIN and CHAR_MAX" do - RbConfig::LIMITS["CHAR_MIN"].should <= 0 - RbConfig::LIMITS["CHAR_MAX"].should > 0 - end + it "contains CHAR_MIN and CHAR_MAX" do + RbConfig::LIMITS["CHAR_MIN"].should <= 0 + RbConfig::LIMITS["CHAR_MAX"].should > 0 + end - it "contains SHRT_MIN and SHRT_MAX" do - RbConfig::LIMITS["SHRT_MIN"].should == -32768 - RbConfig::LIMITS["SHRT_MAX"].should == 32767 - end + it "contains SHRT_MIN and SHRT_MAX" do + RbConfig::LIMITS["SHRT_MIN"].should == -32768 + RbConfig::LIMITS["SHRT_MAX"].should == 32767 + end - it "contains INT_MIN and INT_MAX" do - RbConfig::LIMITS["INT_MIN"].should < 0 - RbConfig::LIMITS["INT_MAX"].should > 0 - end + it "contains INT_MIN and INT_MAX" do + RbConfig::LIMITS["INT_MIN"].should < 0 + RbConfig::LIMITS["INT_MAX"].should > 0 + end - it "contains LONG_MIN and LONG_MAX" do - RbConfig::LIMITS["LONG_MIN"].should < 0 - RbConfig::LIMITS["LONG_MAX"].should > 0 - end + it "contains LONG_MIN and LONG_MAX" do + RbConfig::LIMITS["LONG_MIN"].should < 0 + RbConfig::LIMITS["LONG_MAX"].should > 0 end end diff --git a/ruby/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb b/ruby/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb index d3df8b731..b7d9c7a8e 100644 --- a/ruby/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb +++ b/ruby/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb @@ -14,9 +14,15 @@ end end - ruby_version_is "2.7" do - it "is 12.1 for Ruby 2.7" do + ruby_version_is "2.7"..."3.1" do + it "is 12.1 for Ruby 2.7 and 3.0" do RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.1" end end + + ruby_version_is "3.1" do + it "is 13.1 for Ruby 3.1" do + RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "13.1" + end + end end diff --git a/ruby/spec/ruby/library/rbconfig/unicode_version_spec.rb b/ruby/spec/ruby/library/rbconfig/unicode_version_spec.rb index 44216700c..fe19b1029 100644 --- a/ruby/spec/ruby/library/rbconfig/unicode_version_spec.rb +++ b/ruby/spec/ruby/library/rbconfig/unicode_version_spec.rb @@ -2,18 +2,6 @@ require 'rbconfig' describe "RbConfig::CONFIG['UNICODE_VERSION']" do - ruby_version_is ""..."2.5" do - it "is 9.0.0 for Ruby 2.4" do - RbConfig::CONFIG['UNICODE_VERSION'].should == "9.0.0" - end - end - - ruby_version_is "2.5"..."2.6" do - it "is 10.0.0 for Ruby 2.5" do - RbConfig::CONFIG['UNICODE_VERSION'].should == "10.0.0" - end - end - ruby_version_is "2.6"..."2.6.2" do it "is 11.0.0 for Ruby 2.6.0 and 2.6.1" do RbConfig::CONFIG['UNICODE_VERSION'].should == "11.0.0" @@ -26,9 +14,15 @@ end end - ruby_version_is "2.6.3" do - it "is 12.1.0 for Ruby 2.6.3+ and Ruby 2.7" do + ruby_version_is "2.6.3"..."3.1" do + it "is 12.1.0 for Ruby 2.6.3+, Ruby 2.7, and Ruby 3.0" do RbConfig::CONFIG['UNICODE_VERSION'].should == "12.1.0" end end + + ruby_version_is "3.1" do + it "is 13.0.0 for Ruby 3.1" do + RbConfig::CONFIG['UNICODE_VERSION'].should == "13.0.0" + end + end end diff --git a/ruby/spec/ruby/library/rexml/attribute/clone_spec.rb b/ruby/spec/ruby/library/rexml/attribute/clone_spec.rb index 9a4a4079e..5c86468d4 100644 --- a/ruby/spec/ruby/library/rexml/attribute/clone_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/clone_spec.rb @@ -1,11 +1,14 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#clone" do - it "returns a copy of this Attribute" do - orig = REXML::Attribute.new("name", "value&&") - orig.should == orig.clone - orig.clone.to_s.should == orig.to_s - orig.clone.to_string.should == orig.to_string +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attribute#clone" do + it "returns a copy of this Attribute" do + orig = REXML::Attribute.new("name", "value&&") + orig.should == orig.clone + orig.clone.to_s.should == orig.to_s + orig.clone.to_string.should == orig.to_string + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/element_spec.rb b/ruby/spec/ruby/library/rexml/attribute/element_spec.rb index 832e7e9a4..0e4ce46a4 100644 --- a/ruby/spec/ruby/library/rexml/attribute/element_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/element_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#element" do - it "returns the parent element" do - e = REXML::Element.new "root" +ruby_version_is ''...'3.0' do + require 'rexml/document' - REXML::Attribute.new("name", "value", e).element.should == e - REXML::Attribute.new("name", "default_constructor").element.should == nil + describe "REXML::Attribute#element" do + it "returns the parent element" do + e = REXML::Element.new "root" + + REXML::Attribute.new("name", "value", e).element.should == e + REXML::Attribute.new("name", "default_constructor").element.should == nil + end end -end -describe "REXML::Attribute#element=" do - it "sets the parent element" do - e = REXML::Element.new "root" - f = REXML::Element.new "temp" - a = REXML::Attribute.new("name", "value", e) - a.element.should == e + describe "REXML::Attribute#element=" do + it "sets the parent element" do + e = REXML::Element.new "root" + f = REXML::Element.new "temp" + a = REXML::Attribute.new("name", "value", e) + a.element.should == e - a.element = f - a.element.should == f + a.element = f + a.element.should == f + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/equal_value_spec.rb b/ruby/spec/ruby/library/rexml/attribute/equal_value_spec.rb index 8bf2c0a3a..1498bae62 100644 --- a/ruby/spec/ruby/library/rexml/attribute/equal_value_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/equal_value_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#==" do - it "returns true if other has equal name and value" do - a1 = REXML::Attribute.new("foo", "bar") - a1.should == a1.clone +ruby_version_is ''...'3.0' do + require 'rexml/document' - a2 = REXML::Attribute.new("foo", "bar") - a1.should == a2 + describe "REXML::Attribute#==" do + it "returns true if other has equal name and value" do + a1 = REXML::Attribute.new("foo", "bar") + a1.should == a1.clone - a3 = REXML::Attribute.new("foo", "bla") - a1.should_not == a3 + a2 = REXML::Attribute.new("foo", "bar") + a1.should == a2 - a4 = REXML::Attribute.new("baz", "bar") - a1.should_not == a4 + a3 = REXML::Attribute.new("foo", "bla") + a1.should_not == a3 + + a4 = REXML::Attribute.new("baz", "bar") + a1.should_not == a4 + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/hash_spec.rb b/ruby/spec/ruby/library/rexml/attribute/hash_spec.rb index dd71b2810..7e0cbcc1e 100644 --- a/ruby/spec/ruby/library/rexml/attribute/hash_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/hash_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#hash" do - # These are not really complete, any idea on how to make them more - # "testable" will be appreciated. - it "returns a hashcode made of the name and value of self" do - a = REXML::Attribute.new("name", "value") - a.hash.should be_kind_of(Numeric) - b = REXML::Attribute.new(a) - a.hash.should == b.hash +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attribute#hash" do + # These are not really complete, any idea on how to make them more + # "testable" will be appreciated. + it "returns a hashcode made of the name and value of self" do + a = REXML::Attribute.new("name", "value") + a.hash.should be_kind_of(Numeric) + b = REXML::Attribute.new(a) + a.hash.should == b.hash + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/initialize_spec.rb b/ruby/spec/ruby/library/rexml/attribute/initialize_spec.rb index 9f5e30c51..35b87b073 100644 --- a/ruby/spec/ruby/library/rexml/attribute/initialize_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/initialize_spec.rb @@ -1,29 +1,32 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#initialize" do - before :each do - @e = REXML::Element.new "root" - @name = REXML::Attribute.new("name", "Nicko") - @e.add_attribute @name - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "receives two strings for name and value" do - @e.attributes["name"].should == "Nicko" - @e.add_attribute REXML::Attribute.new("last_name", nil) - @e.attributes["last_name"].should == "" - end + describe "REXML::Attribute#initialize" do + before :each do + @e = REXML::Element.new "root" + @name = REXML::Attribute.new("name", "Nicko") + @e.add_attribute @name + end - it "receives an Attribute and clones it" do - copy = REXML::Attribute.new(@name) - copy.should == @name - end + it "receives two strings for name and value" do + @e.attributes["name"].should == "Nicko" + @e.add_attribute REXML::Attribute.new("last_name", nil) + @e.attributes["last_name"].should == "" + end + + it "receives an Attribute and clones it" do + copy = REXML::Attribute.new(@name) + copy.should == @name + end - it "receives a parent node" do - last_name = REXML::Attribute.new("last_name", "McBrain", @e) - last_name.element.should == @e + it "receives a parent node" do + last_name = REXML::Attribute.new("last_name", "McBrain", @e) + last_name.element.should == @e - last_name = REXML::Attribute.new(@name, @e) - last_name.element.should == @e + last_name = REXML::Attribute.new(@name, @e) + last_name.element.should == @e + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/inspect_spec.rb b/ruby/spec/ruby/library/rexml/attribute/inspect_spec.rb index 632b477cc..ee5236b98 100644 --- a/ruby/spec/ruby/library/rexml/attribute/inspect_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/inspect_spec.rb @@ -1,19 +1,22 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#inspect" do - it "returns the name and value as a string" do - a = REXML::Attribute.new("my_name", "my_value") - a.inspect.should == "my_name='my_value'" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "accepts attributes with no value" do - a = REXML::Attribute.new("my_name") - a.inspect.should == "my_name=''" - end + describe "REXML::Attribute#inspect" do + it "returns the name and value as a string" do + a = REXML::Attribute.new("my_name", "my_value") + a.inspect.should == "my_name='my_value'" + end + + it "accepts attributes with no value" do + a = REXML::Attribute.new("my_name") + a.inspect.should == "my_name=''" + end - it "does not escape text" do - a = REXML::Attribute.new("name", "<>") - a.inspect.should == "name='<>'" + it "does not escape text" do + a = REXML::Attribute.new("name", "<>") + a.inspect.should == "name='<>'" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/namespace_spec.rb b/ruby/spec/ruby/library/rexml/attribute/namespace_spec.rb index 9d5077073..645b3cd1b 100644 --- a/ruby/spec/ruby/library/rexml/attribute/namespace_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/namespace_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#namespace" do - it "returns the namespace url" do - e = REXML::Element.new("root") - e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri") - e.namespace("ns").should == "http://some_uri" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns nil if namespace is not defined" do - e = REXML::Element.new("root") - e.add_attribute REXML::Attribute.new("test", "value") - e.namespace("test").should == nil - e.namespace("ns").should == nil - end + describe "REXML::Attribute#namespace" do + it "returns the namespace url" do + e = REXML::Element.new("root") + e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri") + e.namespace("ns").should == "http://some_uri" + end + + it "returns nil if namespace is not defined" do + e = REXML::Element.new("root") + e.add_attribute REXML::Attribute.new("test", "value") + e.namespace("test").should == nil + e.namespace("ns").should == nil + end - it "defaults arg to nil" do - e = REXML::Element.new("root") - e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri") - e.namespace.should == "" - e.namespace("ns").should == "http://some_uri" + it "defaults arg to nil" do + e = REXML::Element.new("root") + e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri") + e.namespace.should == "" + e.namespace("ns").should == "http://some_uri" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/node_type_spec.rb b/ruby/spec/ruby/library/rexml/attribute/node_type_spec.rb index 664d7cfa0..da055ae8f 100644 --- a/ruby/spec/ruby/library/rexml/attribute/node_type_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/node_type_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#node_type" do - it "always returns :attribute" do - attr = REXML::Attribute.new("foo", "bar") - attr.node_type.should == :attribute - REXML::Attribute.new(attr).node_type.should == :attribute +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attribute#node_type" do + it "always returns :attribute" do + attr = REXML::Attribute.new("foo", "bar") + attr.node_type.should == :attribute + REXML::Attribute.new(attr).node_type.should == :attribute + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/prefix_spec.rb b/ruby/spec/ruby/library/rexml/attribute/prefix_spec.rb index 2a47f74ad..87bff4822 100644 --- a/ruby/spec/ruby/library/rexml/attribute/prefix_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/prefix_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#prefix" do - it "returns the namespace of the Attribute" do - ans = REXML::Attribute.new("ns:someattr", "some_value") - out = REXML::Attribute.new("out:something", "some_other_value") +ruby_version_is ''...'3.0' do + require 'rexml/document' - ans.prefix.should == "ns" - out.prefix.should == "out" - end + describe "REXML::Attribute#prefix" do + it "returns the namespace of the Attribute" do + ans = REXML::Attribute.new("ns:someattr", "some_value") + out = REXML::Attribute.new("out:something", "some_other_value") + + ans.prefix.should == "ns" + out.prefix.should == "out" + end - it "returns an empty string for Attributes with no prefixes" do - attr = REXML::Attribute.new("foo", "bar") + it "returns an empty string for Attributes with no prefixes" do + attr = REXML::Attribute.new("foo", "bar") - attr.prefix.should == "" + attr.prefix.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/remove_spec.rb b/ruby/spec/ruby/library/rexml/attribute/remove_spec.rb index 08d22cb6b..5f928b128 100644 --- a/ruby/spec/ruby/library/rexml/attribute/remove_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/remove_spec.rb @@ -1,20 +1,23 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#remove" do - before :each do - @e = REXML::Element.new "Root" - @attr = REXML::Attribute.new("foo", "bar") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "deletes this Attribute from parent" do - @e.add_attribute(@attr) - @e.attributes["foo"].should_not == nil - @attr.remove - @e.attributes["foo"].should == nil - end + describe "REXML::Attribute#remove" do + before :each do + @e = REXML::Element.new "Root" + @attr = REXML::Attribute.new("foo", "bar") + end + + it "deletes this Attribute from parent" do + @e.add_attribute(@attr) + @e.attributes["foo"].should_not == nil + @attr.remove + @e.attributes["foo"].should == nil + end - it "does not anything if element has no parent" do - -> {@attr.remove}.should_not raise_error(Exception) + it "does not anything if element has no parent" do + -> {@attr.remove}.should_not raise_error(Exception) + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/to_s_spec.rb b/ruby/spec/ruby/library/rexml/attribute/to_s_spec.rb index e1ce48ec3..e362cee8f 100644 --- a/ruby/spec/ruby/library/rexml/attribute/to_s_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/to_s_spec.rb @@ -1,14 +1,17 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#to_s" do - it "returns the value of the Attribute" do - REXML::Attribute.new("name", "some_value").to_s.should == "some_value" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attribute#to_s" do + it "returns the value of the Attribute" do + REXML::Attribute.new("name", "some_value").to_s.should == "some_value" + end - it "returns the escaped value if it was created from Attribute" do - orig = REXML::Attribute.new("name", "<&>") - copy = REXML::Attribute.new(orig) - copy.to_s.should == "<&>" + it "returns the escaped value if it was created from Attribute" do + orig = REXML::Attribute.new("name", "<&>") + copy = REXML::Attribute.new(orig) + copy.to_s.should == "<&>" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/to_string_spec.rb b/ruby/spec/ruby/library/rexml/attribute/to_string_spec.rb index 420913afe..a9d249f5b 100644 --- a/ruby/spec/ruby/library/rexml/attribute/to_string_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/to_string_spec.rb @@ -1,14 +1,17 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#to_string" do - it "returns the attribute as XML" do - attr = REXML::Attribute.new("name", "value") - attr_empty = REXML::Attribute.new("name") - attr_ns = REXML::Attribute.new("xmlns:ns", "http://uri") +ruby_version_is ''...'3.0' do + require 'rexml/document' - attr.to_string.should == "name='value'" - attr_empty.to_string.should == "name=''" - attr_ns.to_string.should == "xmlns:ns='http://uri'" + describe "REXML::Attribute#to_string" do + it "returns the attribute as XML" do + attr = REXML::Attribute.new("name", "value") + attr_empty = REXML::Attribute.new("name") + attr_ns = REXML::Attribute.new("xmlns:ns", "http://uri") + + attr.to_string.should == "name='value'" + attr_empty.to_string.should == "name=''" + attr_ns.to_string.should == "xmlns:ns='http://uri'" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/value_spec.rb b/ruby/spec/ruby/library/rexml/attribute/value_spec.rb index 776397688..77071f6f7 100644 --- a/ruby/spec/ruby/library/rexml/attribute/value_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/value_spec.rb @@ -1,14 +1,17 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#value" do - it "returns the value of the Attribute unnormalized" do - attr = REXML::Attribute.new("name", "value") - attr_ents = REXML::Attribute.new("name", "<&>") - attr_empty = REXML::Attribute.new("name") +ruby_version_is ''...'3.0' do + require 'rexml/document' - attr.value.should == "value" - attr_ents.value.should == "<&>" - attr_empty.value.should == "" + describe "REXML::Attribute#value" do + it "returns the value of the Attribute unnormalized" do + attr = REXML::Attribute.new("name", "value") + attr_ents = REXML::Attribute.new("name", "<&>") + attr_empty = REXML::Attribute.new("name") + + attr.value.should == "value" + attr_ents.value.should == "<&>" + attr_empty.value.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/write_spec.rb b/ruby/spec/ruby/library/rexml/attribute/write_spec.rb index 7ada7460f..0012b3cc7 100644 --- a/ruby/spec/ruby/library/rexml/attribute/write_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/write_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#write" do - before :each do - @attr = REXML::Attribute.new("name", "Charlotte") - @s = "" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "writes the name and value to output" do - @attr.write(@s) - @s.should == "name='Charlotte'" - end + describe "REXML::Attribute#write" do + before :each do + @attr = REXML::Attribute.new("name", "Charlotte") + @s = "" + end + + it "writes the name and value to output" do + @attr.write(@s) + @s.should == "name='Charlotte'" + end - it "currently ignores the second argument" do - @attr.write(@s, 3) - @s.should == "name='Charlotte'" + it "currently ignores the second argument" do + @attr.write(@s, 3) + @s.should == "name='Charlotte'" - @s = "" - @attr.write(@s, "foo") - @s.should == "name='Charlotte'" + @s = "" + @attr.write(@s, "foo") + @s.should == "name='Charlotte'" + end end end diff --git a/ruby/spec/ruby/library/rexml/attribute/xpath_spec.rb b/ruby/spec/ruby/library/rexml/attribute/xpath_spec.rb index 8335e0a8e..0a09046b0 100644 --- a/ruby/spec/ruby/library/rexml/attribute/xpath_spec.rb +++ b/ruby/spec/ruby/library/rexml/attribute/xpath_spec.rb @@ -1,19 +1,22 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attribute#xpath" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - before :each do - @e = REXML::Element.new "root" - @attr = REXML::Attribute.new("year", "1989") - end + describe "REXML::Attribute#xpath" do - it "returns the path for Attribute" do - @e.add_attribute @attr - @attr.xpath.should == "root/@year" - end + before :each do + @e = REXML::Element.new "root" + @attr = REXML::Attribute.new("year", "1989") + end + + it "returns the path for Attribute" do + @e.add_attribute @attr + @attr.xpath.should == "root/@year" + end - it "raises an error if attribute has no parent" do - -> { @attr.xpath }.should raise_error(Exception) + it "raises an error if attribute has no parent" do + -> { @attr.xpath }.should raise_error(Exception) + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/add_spec.rb b/ruby/spec/ruby/library/rexml/attributes/add_spec.rb index 32a927e10..e24e9fabb 100644 --- a/ruby/spec/ruby/library/rexml/attributes/add_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/add_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/add' -require 'rexml/document' -describe "REXML::Attributes#add" do - it_behaves_like :rexml_attribute_add, :add +ruby_version_is ''...'3.0' do + require_relative 'shared/add' + require 'rexml/document' + + describe "REXML::Attributes#add" do + it_behaves_like :rexml_attribute_add, :add + end end diff --git a/ruby/spec/ruby/library/rexml/attributes/append_spec.rb b/ruby/spec/ruby/library/rexml/attributes/append_spec.rb index f1b08f7d6..f96a727f4 100644 --- a/ruby/spec/ruby/library/rexml/attributes/append_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/append_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/add' -require 'rexml/document' -describe "REXML::Attributes#<<" do - it_behaves_like :rexml_attribute_add, :<< +ruby_version_is ''...'3.0' do + require_relative 'shared/add' + require 'rexml/document' + + describe "REXML::Attributes#<<" do + it_behaves_like :rexml_attribute_add, :<< + end end diff --git a/ruby/spec/ruby/library/rexml/attributes/delete_all_spec.rb b/ruby/spec/ruby/library/rexml/attributes/delete_all_spec.rb index 9340b5693..707baa235 100644 --- a/ruby/spec/ruby/library/rexml/attributes/delete_all_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/delete_all_spec.rb @@ -1,31 +1,34 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#delete_all" do - before :each do - @e = REXML::Element.new("root") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "deletes all attributes that match name" do - uri = REXML::Attribute.new("uri", "http://something") - @e.attributes << uri - @e.attributes.delete_all("uri") - @e.attributes.should be_empty - @e.attributes["uri"].should == nil - end + describe "REXML::Attributes#delete_all" do + before :each do + @e = REXML::Element.new("root") + end - it "deletes all attributes that match name with a namespace" do - ns_uri = REXML::Attribute.new("xmlns:uri", "http://something_here_too") - @e.attributes << ns_uri - @e.attributes.delete_all("xmlns:uri") - @e.attributes.should be_empty - @e.attributes["xmlns:uri"].should == nil - end + it "deletes all attributes that match name" do + uri = REXML::Attribute.new("uri", "http://something") + @e.attributes << uri + @e.attributes.delete_all("uri") + @e.attributes.should be_empty + @e.attributes["uri"].should == nil + end + + it "deletes all attributes that match name with a namespace" do + ns_uri = REXML::Attribute.new("xmlns:uri", "http://something_here_too") + @e.attributes << ns_uri + @e.attributes.delete_all("xmlns:uri") + @e.attributes.should be_empty + @e.attributes["xmlns:uri"].should == nil + end - it "returns the removed attribute" do - uri = REXML::Attribute.new("uri", "http://something_here_too") - @e.attributes << uri - attrs = @e.attributes.delete_all("uri") - attrs.first.should == uri + it "returns the removed attribute" do + uri = REXML::Attribute.new("uri", "http://something_here_too") + @e.attributes << uri + attrs = @e.attributes.delete_all("uri") + attrs.first.should == uri + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/delete_spec.rb b/ruby/spec/ruby/library/rexml/attributes/delete_spec.rb index 495e4085e..723fa7075 100644 --- a/ruby/spec/ruby/library/rexml/attributes/delete_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/delete_spec.rb @@ -1,27 +1,30 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#delete" do - before :each do - @e = REXML::Element.new("root") - @name = REXML::Attribute.new("name", "Pepe") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "takes an attribute name and deletes the attribute" do - @e.attributes.delete("name") - @e.attributes["name"].should be_nil - @e.attributes.should be_empty - end + describe "REXML::Attributes#delete" do + before :each do + @e = REXML::Element.new("root") + @name = REXML::Attribute.new("name", "Pepe") + end - it "takes an Attribute and deletes it" do - @e.attributes.delete(@name) - @e.attributes["name"].should be_nil - @e.attributes.should be_empty - end + it "takes an attribute name and deletes the attribute" do + @e.attributes.delete("name") + @e.attributes["name"].should be_nil + @e.attributes.should be_empty + end + + it "takes an Attribute and deletes it" do + @e.attributes.delete(@name) + @e.attributes["name"].should be_nil + @e.attributes.should be_empty + end - it "returns the element with the attribute removed" do - ret_val = @e.attributes.delete(@name) - ret_val.should == @e - ret_val.attributes.should be_empty + it "returns the element with the attribute removed" do + ret_val = @e.attributes.delete(@name) + ret_val.should == @e + ret_val.attributes.should be_empty + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/each_attribute_spec.rb b/ruby/spec/ruby/library/rexml/attributes/each_attribute_spec.rb index e84c8dbf5..692cf4f94 100644 --- a/ruby/spec/ruby/library/rexml/attributes/each_attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/each_attribute_spec.rb @@ -1,22 +1,25 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#each_attribute" do - it "iterates over the attributes yielding actual Attribute objects" do - e = REXML::Element.new("root") - name = REXML::Attribute.new("name", "Joe") - ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri") - e.add_attribute name - e.add_attribute ns_uri +ruby_version_is ''...'3.0' do + require 'rexml/document' - attributes = [] + describe "REXML::Attributes#each_attribute" do + it "iterates over the attributes yielding actual Attribute objects" do + e = REXML::Element.new("root") + name = REXML::Attribute.new("name", "Joe") + ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri") + e.add_attribute name + e.add_attribute ns_uri - e.attributes.each_attribute do |attr| - attributes << attr - end + attributes = [] + + e.attributes.each_attribute do |attr| + attributes << attr + end - attributes = attributes.sort_by {|a| a.name } - attributes.first.should == name - attributes.last.should == ns_uri + attributes = attributes.sort_by {|a| a.name } + attributes.first.should == name + attributes.last.should == ns_uri + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/each_spec.rb b/ruby/spec/ruby/library/rexml/attributes/each_spec.rb index ed60634b9..49add3b77 100644 --- a/ruby/spec/ruby/library/rexml/attributes/each_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/each_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#each" do - before :each do - @e = REXML::Element.new("root") - @name = REXML::Attribute.new("name", "Joe") - @ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri") - @e.add_attribute @name - @e.add_attribute @ns_uri - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attributes#each" do + before :each do + @e = REXML::Element.new("root") + @name = REXML::Attribute.new("name", "Joe") + @ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri") + @e.add_attribute @name + @e.add_attribute @ns_uri + end - it "iterates over the attributes yielding expanded-name/value" do - attributes = [] - @e.attributes.each do |attr| - attr.should be_kind_of(Array) - attributes << attr + it "iterates over the attributes yielding expanded-name/value" do + attributes = [] + @e.attributes.each do |attr| + attr.should be_kind_of(Array) + attributes << attr + end + attributes = attributes.sort_by {|a| a.first } + attributes.first.should == ["name", "Joe"] + attributes.last.should == ["xmlns:ns", "http://some_uri"] end - attributes = attributes.sort_by {|a| a.first } - attributes.first.should == ["name", "Joe"] - attributes.last.should == ["xmlns:ns", "http://some_uri"] end end diff --git a/ruby/spec/ruby/library/rexml/attributes/element_reference_spec.rb b/ruby/spec/ruby/library/rexml/attributes/element_reference_spec.rb index dac795266..0d089eaab 100644 --- a/ruby/spec/ruby/library/rexml/attributes/element_reference_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/element_reference_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#[]" do - before :each do - @e = REXML::Element.new("root") - @lang = REXML::Attribute.new("language", "english") - @e.attributes << @lang - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the value of an attribute" do - @e.attributes["language"].should == "english" - end + describe "REXML::Attributes#[]" do + before :each do + @e = REXML::Element.new("root") + @lang = REXML::Attribute.new("language", "english") + @e.attributes << @lang + end + + it "returns the value of an attribute" do + @e.attributes["language"].should == "english" + end - it "returns nil if the attribute does not exist" do - @e.attributes["chunky bacon"].should == nil + it "returns nil if the attribute does not exist" do + @e.attributes["chunky bacon"].should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/element_set_spec.rb b/ruby/spec/ruby/library/rexml/attributes/element_set_spec.rb index 1ed94dd2a..834ad682a 100644 --- a/ruby/spec/ruby/library/rexml/attributes/element_set_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/element_set_spec.rb @@ -1,25 +1,28 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#[]=" do - before :each do - @e = REXML::Element.new("song") - @name = REXML::Attribute.new("name", "Holy Smoke!") - @e.attributes << @name - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "sets an attribute" do - @e.attributes["author"] = "_why's foxes" - @e.attributes["author"].should == "_why's foxes" - end + describe "REXML::Attributes#[]=" do + before :each do + @e = REXML::Element.new("song") + @name = REXML::Attribute.new("name", "Holy Smoke!") + @e.attributes << @name + end - it "overwrites an existing attribute" do - @e.attributes["name"] = "Chunky Bacon" - @e.attributes["name"].should == "Chunky Bacon" - end + it "sets an attribute" do + @e.attributes["author"] = "_why's foxes" + @e.attributes["author"].should == "_why's foxes" + end + + it "overwrites an existing attribute" do + @e.attributes["name"] = "Chunky Bacon" + @e.attributes["name"].should == "Chunky Bacon" + end - it "deletes an attribute is value is nil" do - @e.attributes["name"] = nil - @e.attributes.length.should == 0 + it "deletes an attribute is value is nil" do + @e.attributes["name"] = nil + @e.attributes.length.should == 0 + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb b/ruby/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb index 1664d6e42..1109ff519 100644 --- a/ruby/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb @@ -1,14 +1,17 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#get_attribute_ns" do - it "returns an attribute by name and namespace" do - e = REXML::Element.new("root") - attr = REXML::Attribute.new("xmlns:ns", "http://some_url") - e.attributes << attr - attr.prefix.should == "xmlns" - # This might be a bug in Attribute, commenting until those specs - # are ready - # e.attributes.get_attribute_ns(attr.prefix, "name").should == "http://some_url" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attributes#get_attribute_ns" do + it "returns an attribute by name and namespace" do + e = REXML::Element.new("root") + attr = REXML::Attribute.new("xmlns:ns", "http://some_url") + e.attributes << attr + attr.prefix.should == "xmlns" + # This might be a bug in Attribute, commenting until those specs + # are ready + # e.attributes.get_attribute_ns(attr.prefix, "name").should == "http://some_url" + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/get_attribute_spec.rb b/ruby/spec/ruby/library/rexml/attributes/get_attribute_spec.rb index cfe58c1b9..cc9419172 100644 --- a/ruby/spec/ruby/library/rexml/attributes/get_attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/get_attribute_spec.rb @@ -1,29 +1,32 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#get_attribute" do - before :each do - @e = REXML::Element.new("root") - @name = REXML::Attribute.new("name", "Dave") - @e.attributes << @name - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "fetches an attributes" do - @e.attributes.get_attribute("name").should == @name - end + describe "REXML::Attributes#get_attribute" do + before :each do + @e = REXML::Element.new("root") + @name = REXML::Attribute.new("name", "Dave") + @e.attributes << @name + end - it "fetches an namespaced attribute" do - ns_name = REXML::Attribute.new("im:name", "Murray") - @e.attributes << ns_name - @e.attributes.get_attribute("name").should == @name - @e.attributes.get_attribute("im:name").should == ns_name - end + it "fetches an attributes" do + @e.attributes.get_attribute("name").should == @name + end - it "returns an Attribute" do - @e.attributes.get_attribute("name").should be_kind_of(REXML::Attribute) - end + it "fetches an namespaced attribute" do + ns_name = REXML::Attribute.new("im:name", "Murray") + @e.attributes << ns_name + @e.attributes.get_attribute("name").should == @name + @e.attributes.get_attribute("im:name").should == ns_name + end + + it "returns an Attribute" do + @e.attributes.get_attribute("name").should be_kind_of(REXML::Attribute) + end - it "returns nil if it attribute does not exist" do - @e.attributes.get_attribute("fake").should be_nil + it "returns nil if it attribute does not exist" do + @e.attributes.get_attribute("fake").should be_nil + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/initialize_spec.rb b/ruby/spec/ruby/library/rexml/attributes/initialize_spec.rb index f18bd20c6..42ec742e6 100644 --- a/ruby/spec/ruby/library/rexml/attributes/initialize_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/initialize_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#initialize" do - it "is auto initialized by Element" do - e = REXML::Element.new "root" - e.attributes.should be_kind_of(REXML::Attributes) +ruby_version_is ''...'3.0' do + require 'rexml/document' - e.attributes << REXML::Attribute.new("name", "Paul") - e.attributes["name"].should == "Paul" - end + describe "REXML::Attributes#initialize" do + it "is auto initialized by Element" do + e = REXML::Element.new "root" + e.attributes.should be_kind_of(REXML::Attributes) + + e.attributes << REXML::Attribute.new("name", "Paul") + e.attributes["name"].should == "Paul" + end - it "receives a parent node" do - e = REXML::Element.new "root" - e.attributes << REXML::Attribute.new("name", "Vic") - e.attributes["name"].should == "Vic" + it "receives a parent node" do + e = REXML::Element.new "root" + e.attributes << REXML::Attribute.new("name", "Vic") + e.attributes["name"].should == "Vic" + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/length_spec.rb b/ruby/spec/ruby/library/rexml/attributes/length_spec.rb index 3a8361b8d..81733b4a9 100644 --- a/ruby/spec/ruby/library/rexml/attributes/length_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/length_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/length' -require 'rexml/document' -describe "REXML::Attributes#length" do - it_behaves_like :rexml_attribute_length, :length +ruby_version_is ''...'3.0' do + require_relative 'shared/length' + require 'rexml/document' + + describe "REXML::Attributes#length" do + it_behaves_like :rexml_attribute_length, :length + end end diff --git a/ruby/spec/ruby/library/rexml/attributes/namespaces_spec.rb b/ruby/spec/ruby/library/rexml/attributes/namespaces_spec.rb index 9e329fef6..b88346854 100644 --- a/ruby/spec/ruby/library/rexml/attributes/namespaces_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/namespaces_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#namespaces" do - it "needs to be reviewed for spec completeness" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Attributes#namespaces" do + it "needs to be reviewed for spec completeness" + end end diff --git a/ruby/spec/ruby/library/rexml/attributes/prefixes_spec.rb b/ruby/spec/ruby/library/rexml/attributes/prefixes_spec.rb index 4675095aa..574b7ffba 100644 --- a/ruby/spec/ruby/library/rexml/attributes/prefixes_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/prefixes_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#prefixes" do - before :each do - @e = REXML::Element.new("root") - a1 = REXML::Attribute.new("xmlns:a", "bar") - a2 = REXML::Attribute.new("xmlns:b", "bla") - a3 = REXML::Attribute.new("xmlns:c", "baz") - @e.attributes << a1 - @e.attributes << a2 - @e.attributes << a3 +ruby_version_is ''...'3.0' do + require 'rexml/document' - @e.attributes << REXML::Attribute.new("xmlns", "foo") - end + describe "REXML::Attributes#prefixes" do + before :each do + @e = REXML::Element.new("root") + a1 = REXML::Attribute.new("xmlns:a", "bar") + a2 = REXML::Attribute.new("xmlns:b", "bla") + a3 = REXML::Attribute.new("xmlns:c", "baz") + @e.attributes << a1 + @e.attributes << a2 + @e.attributes << a3 - it "returns an array with the prefixes of each attribute" do - @e.attributes.prefixes.sort.should == ["a", "b", "c"] - end + @e.attributes << REXML::Attribute.new("xmlns", "foo") + end + + it "returns an array with the prefixes of each attribute" do + @e.attributes.prefixes.sort.should == ["a", "b", "c"] + end - it "does not include the default namespace" do - @e.attributes.prefixes.include?("xmlns").should == false + it "does not include the default namespace" do + @e.attributes.prefixes.include?("xmlns").should == false + end end end diff --git a/ruby/spec/ruby/library/rexml/attributes/size_spec.rb b/ruby/spec/ruby/library/rexml/attributes/size_spec.rb index 3b1df9510..13ef08f64 100644 --- a/ruby/spec/ruby/library/rexml/attributes/size_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/size_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/length' -require 'rexml/document' -describe "REXML::Attributes#size" do - it_behaves_like :rexml_attribute_length, :size +ruby_version_is ''...'3.0' do + require_relative 'shared/length' + require 'rexml/document' + + describe "REXML::Attributes#size" do + it_behaves_like :rexml_attribute_length, :size + end end diff --git a/ruby/spec/ruby/library/rexml/attributes/to_a_spec.rb b/ruby/spec/ruby/library/rexml/attributes/to_a_spec.rb index 1fbf71b68..902cd86a2 100644 --- a/ruby/spec/ruby/library/rexml/attributes/to_a_spec.rb +++ b/ruby/spec/ruby/library/rexml/attributes/to_a_spec.rb @@ -1,19 +1,22 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Attributes#to_a" do - it "returns an array with the attributes" do - e = REXML::Element.new("root") - name = REXML::Attribute.new("name", "Dave") - last = REXML::Attribute.new("last_name", "Murray") +ruby_version_is ''...'3.0' do + require 'rexml/document' - e.attributes << name - e.attributes << last + describe "REXML::Attributes#to_a" do + it "returns an array with the attributes" do + e = REXML::Element.new("root") + name = REXML::Attribute.new("name", "Dave") + last = REXML::Attribute.new("last_name", "Murray") - e.attributes.to_a.sort{|a,b|a.to_s<=>b.to_s}.should == [name, last] - end + e.attributes << name + e.attributes << last + + e.attributes.to_a.sort{|a,b|a.to_s<=>b.to_s}.should == [name, last] + end - it "returns an empty array if it has no attributes" do - REXML::Element.new("root").attributes.to_a.should == [] + it "returns an empty array if it has no attributes" do + REXML::Element.new("root").attributes.to_a.should == [] + end end end diff --git a/ruby/spec/ruby/library/rexml/cdata/clone_spec.rb b/ruby/spec/ruby/library/rexml/cdata/clone_spec.rb index 7d3cfda90..abe1a0b06 100644 --- a/ruby/spec/ruby/library/rexml/cdata/clone_spec.rb +++ b/ruby/spec/ruby/library/rexml/cdata/clone_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::CData#clone" do - it "makes a copy of itself" do - c = REXML::CData.new("some text") - c.clone.to_s.should == c.to_s - c.clone.should == c +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::CData#clone" do + it "makes a copy of itself" do + c = REXML::CData.new("some text") + c.clone.to_s.should == c.to_s + c.clone.should == c + end end end diff --git a/ruby/spec/ruby/library/rexml/cdata/initialize_spec.rb b/ruby/spec/ruby/library/rexml/cdata/initialize_spec.rb index 0184440d8..1393d97f4 100644 --- a/ruby/spec/ruby/library/rexml/cdata/initialize_spec.rb +++ b/ruby/spec/ruby/library/rexml/cdata/initialize_spec.rb @@ -1,24 +1,27 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::CData#initialize" do - it "creates a new CData object" do - c = REXML::CData.new("some text") - c.should be_kind_of(REXML::CData) - c.should be_kind_of(REXML::Text) - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "respects whitespace if whitespace is true" do - c = REXML::CData.new("whitespace test", true) - c1 = REXML::CData.new("whitespace test", false) + describe "REXML::CData#initialize" do + it "creates a new CData object" do + c = REXML::CData.new("some text") + c.should be_kind_of(REXML::CData) + c.should be_kind_of(REXML::Text) + end - c.to_s.should == "whitespace test" - c1.to_s.should == "whitespace test" - end + it "respects whitespace if whitespace is true" do + c = REXML::CData.new("whitespace test", true) + c1 = REXML::CData.new("whitespace test", false) + + c.to_s.should == "whitespace test" + c1.to_s.should == "whitespace test" + end - it "receives parent as third argument" do - e = REXML::Element.new("root") - REXML::CData.new("test", true, e) - e.to_s.should == "" + it "receives parent as third argument" do + e = REXML::Element.new("root") + REXML::CData.new("test", true, e) + e.to_s.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/cdata/to_s_spec.rb b/ruby/spec/ruby/library/rexml/cdata/to_s_spec.rb index ff3076e55..a5c061f11 100644 --- a/ruby/spec/ruby/library/rexml/cdata/to_s_spec.rb +++ b/ruby/spec/ruby/library/rexml/cdata/to_s_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/to_s' -require 'rexml/document' -describe "REXML::CData#to_s" do - it_behaves_like :rexml_cdata_to_s, :to_s +ruby_version_is ''...'3.0' do + require_relative 'shared/to_s' + require 'rexml/document' + + describe "REXML::CData#to_s" do + it_behaves_like :rexml_cdata_to_s, :to_s + end end diff --git a/ruby/spec/ruby/library/rexml/cdata/value_spec.rb b/ruby/spec/ruby/library/rexml/cdata/value_spec.rb index 6e8f8587a..9f3622697 100644 --- a/ruby/spec/ruby/library/rexml/cdata/value_spec.rb +++ b/ruby/spec/ruby/library/rexml/cdata/value_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/to_s' -require 'rexml/document' -describe "REXML::CData#value" do - it_behaves_like :rexml_cdata_to_s, :value +ruby_version_is ''...'3.0' do + require_relative 'shared/to_s' + require 'rexml/document' + + describe "REXML::CData#value" do + it_behaves_like :rexml_cdata_to_s, :value + end end diff --git a/ruby/spec/ruby/library/rexml/document/add_element_spec.rb b/ruby/spec/ruby/library/rexml/document/add_element_spec.rb index 42981d646..29dec0b24 100644 --- a/ruby/spec/ruby/library/rexml/document/add_element_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/add_element_spec.rb @@ -1,31 +1,34 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#add_element" do - it "adds arg1 with attributes arg2 as root node" do - d = REXML::Document.new - e = REXML::Element.new("root") - d.add_element e - d.root.should == e - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "sets arg2 as arg1's attributes" do - d = REXML::Document.new - e = REXML::Element.new("root") - attr = {"foo" => "bar"} - d.add_element(e,attr) - d.root.attributes["foo"].should == attr["foo"] - end + describe "REXML::Document#add_element" do + it "adds arg1 with attributes arg2 as root node" do + d = REXML::Document.new + e = REXML::Element.new("root") + d.add_element e + d.root.should == e + end - it "accepts a node name as arg1 and adds it as root" do - d = REXML::Document.new - d.add_element "foo" - d.root.name.should == "foo" - end + it "sets arg2 as arg1's attributes" do + d = REXML::Document.new + e = REXML::Element.new("root") + attr = {"foo" => "bar"} + d.add_element(e,attr) + d.root.attributes["foo"].should == attr["foo"] + end + + it "accepts a node name as arg1 and adds it as root" do + d = REXML::Document.new + d.add_element "foo" + d.root.name.should == "foo" + end - it "sets arg1's context to the root's context" do - d = REXML::Document.new("", {"foo" => "bar"}) - d.add_element "foo" - d.root.context.should == d.context + it "sets arg1's context to the root's context" do + d = REXML::Document.new("", {"foo" => "bar"}) + d.add_element "foo" + d.root.context.should == d.context + end end end diff --git a/ruby/spec/ruby/library/rexml/document/add_spec.rb b/ruby/spec/ruby/library/rexml/document/add_spec.rb index db95114e7..8666d3dbf 100644 --- a/ruby/spec/ruby/library/rexml/document/add_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/add_spec.rb @@ -1,57 +1,60 @@ -require 'rexml/document' require_relative '../../../spec_helper' -# This spec defines Document#add and Document#<< +ruby_version_is ''...'3.0' do + require 'rexml/document' -describe :rexml_document_add, shared: true do - before :each do - @doc = REXML::Document.new("") - @decl = REXML::XMLDecl.new("1.0") - end + # This spec defines Document#add and Document#<< - it "sets document's XML declaration" do - @doc.send(@method, @decl) - @doc.xml_decl.should == @decl - end + describe :rexml_document_add, shared: true do + before :each do + @doc = REXML::Document.new("") + @decl = REXML::XMLDecl.new("1.0") + end - it "inserts XML declaration as first node" do - @doc.send(@method, @decl) - @doc.children[0].version.should == "1.0" - end + it "sets document's XML declaration" do + @doc.send(@method, @decl) + @doc.xml_decl.should == @decl + end - it "overwrites existing XML declaration" do - @doc.send(@method, @decl) - @doc.send(@method, REXML::XMLDecl.new("2.0")) - @doc.xml_decl.version.should == "2.0" - end + it "inserts XML declaration as first node" do + @doc.send(@method, @decl) + @doc.children[0].version.should == "1.0" + end - it "sets document DocType" do - @doc.send(@method, REXML::DocType.new("transitional")) - @doc.doctype.name.should == "transitional" - end + it "overwrites existing XML declaration" do + @doc.send(@method, @decl) + @doc.send(@method, REXML::XMLDecl.new("2.0")) + @doc.xml_decl.version.should == "2.0" + end - it "overwrites existing DocType" do - @doc.send(@method, REXML::DocType.new("transitional")) - @doc.send(@method, REXML::DocType.new("strict")) - @doc.doctype.name.should == "strict" - end + it "sets document DocType" do + @doc.send(@method, REXML::DocType.new("transitional")) + @doc.doctype.name.should == "transitional" + end - it "adds root node unless it exists" do - d = REXML::Document.new("") - elem = REXML::Element.new "root" - d.send(@method, elem) - d.root.should == elem - end + it "overwrites existing DocType" do + @doc.send(@method, REXML::DocType.new("transitional")) + @doc.send(@method, REXML::DocType.new("strict")) + @doc.doctype.name.should == "strict" + end + + it "adds root node unless it exists" do + d = REXML::Document.new("") + elem = REXML::Element.new "root" + d.send(@method, elem) + d.root.should == elem + end - it "refuses to add second root" do - -> { @doc.send(@method, REXML::Element.new("foo")) }.should raise_error(RuntimeError) + it "refuses to add second root" do + -> { @doc.send(@method, REXML::Element.new("foo")) }.should raise_error(RuntimeError) + end end -end -describe "REXML::Document#add" do - it_behaves_like :rexml_document_add, :add -end + describe "REXML::Document#add" do + it_behaves_like :rexml_document_add, :add + end -describe "REXML::Document#<<" do - it_behaves_like :rexml_document_add, :<< + describe "REXML::Document#<<" do + it_behaves_like :rexml_document_add, :<< + end end diff --git a/ruby/spec/ruby/library/rexml/document/clone_spec.rb b/ruby/spec/ruby/library/rexml/document/clone_spec.rb index 4aebb6f15..137fe8a07 100644 --- a/ruby/spec/ruby/library/rexml/document/clone_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/clone_spec.rb @@ -1,20 +1,23 @@ -require 'rexml/document' require_relative '../../../spec_helper' -# According to the MRI documentation (http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html), -# clone's behavior "should be obvious". Apparently "obvious" means cloning -# only the attributes and the context of the document, not its children. -describe "REXML::Document#clone" do - it "clones document attributes" do - d = REXML::Document.new("foo") - d.attributes["foo"] = "bar" - e = d.clone - e.attributes.should == d.attributes - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + # According to the MRI documentation (http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html), + # clone's behavior "should be obvious". Apparently "obvious" means cloning + # only the attributes and the context of the document, not its children. + describe "REXML::Document#clone" do + it "clones document attributes" do + d = REXML::Document.new("foo") + d.attributes["foo"] = "bar" + e = d.clone + e.attributes.should == d.attributes + end - it "clones document context" do - d = REXML::Document.new("foo", {"foo" => "bar"}) - e = d.clone - e.context.should == d.context + it "clones document context" do + d = REXML::Document.new("foo", {"foo" => "bar"}) + e = d.clone + e.context.should == d.context + end end end diff --git a/ruby/spec/ruby/library/rexml/document/doctype_spec.rb b/ruby/spec/ruby/library/rexml/document/doctype_spec.rb index b919b071e..e1b7ba491 100644 --- a/ruby/spec/ruby/library/rexml/document/doctype_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/doctype_spec.rb @@ -1,15 +1,18 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#doctype" do - it "returns the doctype" do - d = REXML::Document.new - dt = REXML::DocType.new("foo") - d.add dt - d.doctype.should == dt - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Document#doctype" do + it "returns the doctype" do + d = REXML::Document.new + dt = REXML::DocType.new("foo") + d.add dt + d.doctype.should == dt + end - it "returns nil if there's no doctype" do - REXML::Document.new.doctype.should == nil + it "returns nil if there's no doctype" do + REXML::Document.new.doctype.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/document/encoding_spec.rb b/ruby/spec/ruby/library/rexml/document/encoding_spec.rb index 343e0ee45..2cc947f06 100644 --- a/ruby/spec/ruby/library/rexml/document/encoding_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/encoding_spec.rb @@ -1,22 +1,25 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#encoding" do - before :each do - @doc = REXML::Document.new - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns encoding from XML declaration" do - @doc.add REXML::XMLDecl.new(nil, "UTF-16", nil) - @doc.encoding.should == "UTF-16" - end + describe "REXML::Document#encoding" do + before :each do + @doc = REXML::Document.new + end - it "returns encoding from XML declaration (for UTF-16 as well)" do - @doc.add REXML::XMLDecl.new("1.0", "UTF-8", nil) - @doc.encoding.should == "UTF-8" - end + it "returns encoding from XML declaration" do + @doc.add REXML::XMLDecl.new(nil, "UTF-16", nil) + @doc.encoding.should == "UTF-16" + end + + it "returns encoding from XML declaration (for UTF-16 as well)" do + @doc.add REXML::XMLDecl.new("1.0", "UTF-8", nil) + @doc.encoding.should == "UTF-8" + end - it "uses UTF-8 as default encoding" do - @doc.encoding.should == "UTF-8" + it "uses UTF-8 as default encoding" do + @doc.encoding.should == "UTF-8" + end end end diff --git a/ruby/spec/ruby/library/rexml/document/expanded_name_spec.rb b/ruby/spec/ruby/library/rexml/document/expanded_name_spec.rb index 1225d13fb..9d1025b5e 100644 --- a/ruby/spec/ruby/library/rexml/document/expanded_name_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/expanded_name_spec.rb @@ -1,16 +1,19 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe :document_expanded_name, shared: true do - it "returns an empty string for root" do # root nodes have no expanded name - REXML::Document.new.send(@method).should == "" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe :document_expanded_name, shared: true do + it "returns an empty string for root" do # root nodes have no expanded name + REXML::Document.new.send(@method).should == "" + end end -end -describe "REXML::Document#expanded_name" do - it_behaves_like :document_expanded_name, :expanded_name -end + describe "REXML::Document#expanded_name" do + it_behaves_like :document_expanded_name, :expanded_name + end -describe "REXML::Document#name" do - it_behaves_like :document_expanded_name, :name + describe "REXML::Document#name" do + it_behaves_like :document_expanded_name, :name + end end diff --git a/ruby/spec/ruby/library/rexml/document/new_spec.rb b/ruby/spec/ruby/library/rexml/document/new_spec.rb index 3ff5e99b2..4e24b6f5a 100644 --- a/ruby/spec/ruby/library/rexml/document/new_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/new_spec.rb @@ -1,36 +1,39 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Document#new" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "initializes context of {} unless specified" do - d = REXML::Document.new("") - d.context.should == {} - end + describe "REXML::Document#new" do - it "has empty attributes if source is nil" do - d = REXML::Document.new(nil) - d.elements.should be_empty - end + it "initializes context of {} unless specified" do + d = REXML::Document.new("") + d.context.should == {} + end - it "can use other document context" do - s = REXML::Document.new("") - d = REXML::Document.new(s) - d.context.should == s.context - end + it "has empty attributes if source is nil" do + d = REXML::Document.new(nil) + d.elements.should be_empty + end - it "clones source attributes" do - s = REXML::Document.new("") - s.attributes["some_attr"] = "some_val" - d = REXML::Document.new(s) - d.attributes.should == s.attributes - end + it "can use other document context" do + s = REXML::Document.new("") + d = REXML::Document.new(s) + d.context.should == s.context + end - it "raises an error if source is not a Document, String or IO" do - -> {REXML::Document.new(3)}.should raise_error(RuntimeError) - end + it "clones source attributes" do + s = REXML::Document.new("") + s.attributes["some_attr"] = "some_val" + d = REXML::Document.new(s) + d.attributes.should == s.attributes + end + + it "raises an error if source is not a Document, String or IO" do + -> {REXML::Document.new(3)}.should raise_error(RuntimeError) + end - it "does not perform XML validation" do - REXML::Document.new("Invalid document").should be_kind_of(REXML::Document) + it "does not perform XML validation" do + REXML::Document.new("Invalid document").should be_kind_of(REXML::Document) + end end end diff --git a/ruby/spec/ruby/library/rexml/document/node_type_spec.rb b/ruby/spec/ruby/library/rexml/document/node_type_spec.rb index 85a4d507a..b6d7e7a7d 100644 --- a/ruby/spec/ruby/library/rexml/document/node_type_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/node_type_spec.rb @@ -1,8 +1,11 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#node_type" do - it "returns :document" do - REXML::Document.new.node_type.should == :document +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Document#node_type" do + it "returns :document" do + REXML::Document.new.node_type.should == :document + end end end diff --git a/ruby/spec/ruby/library/rexml/document/root_spec.rb b/ruby/spec/ruby/library/rexml/document/root_spec.rb index 3c24e79b2..1a584a720 100644 --- a/ruby/spec/ruby/library/rexml/document/root_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/root_spec.rb @@ -1,12 +1,15 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#root" do - it "returns document root tag name" do - REXML::Document.new("").root.name.should == "foo" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Document#root" do + it "returns document root tag name" do + REXML::Document.new("").root.name.should == "foo" + end - it "returns nil if there is not root" do - REXML::Document.new.root.should == nil + it "returns nil if there is not root" do + REXML::Document.new.root.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/document/stand_alone_spec.rb b/ruby/spec/ruby/library/rexml/document/stand_alone_spec.rb index 4ac24329d..e1c721e78 100644 --- a/ruby/spec/ruby/library/rexml/document/stand_alone_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/stand_alone_spec.rb @@ -1,19 +1,22 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#stand_alone?" do - it "returns the XMLDecl standalone value" do - d = REXML::Document.new - decl = REXML::XMLDecl.new("1.0", "UTF-8", "yes") - d.add decl - d.stand_alone?.should == "yes" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - # According to the docs this should return the default XMLDecl but that - # will carry some more problems when printing the document. Currently, it - # returns nil. See http://www.ruby-forum.com/topic/146812#650061 - it "returns the default value when no XML declaration present" do - REXML::Document.new.stand_alone?.should == nil - end + describe "REXML::Document#stand_alone?" do + it "returns the XMLDecl standalone value" do + d = REXML::Document.new + decl = REXML::XMLDecl.new("1.0", "UTF-8", "yes") + d.add decl + d.stand_alone?.should == "yes" + end + # According to the docs this should return the default XMLDecl but that + # will carry some more problems when printing the document. Currently, it + # returns nil. See http://www.ruby-forum.com/topic/146812#650061 + it "returns the default value when no XML declaration present" do + REXML::Document.new.stand_alone?.should == nil + end + + end end diff --git a/ruby/spec/ruby/library/rexml/document/version_spec.rb b/ruby/spec/ruby/library/rexml/document/version_spec.rb index 983b4b9af..4f6b40551 100644 --- a/ruby/spec/ruby/library/rexml/document/version_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/version_spec.rb @@ -1,14 +1,17 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#version" do - it "returns XML version from declaration" do - d = REXML::Document.new - d.add REXML::XMLDecl.new("1.1") - d.version.should == "1.1" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Document#version" do + it "returns XML version from declaration" do + d = REXML::Document.new + d.add REXML::XMLDecl.new("1.1") + d.version.should == "1.1" + end - it "returns the default version when declaration is not present" do - REXML::Document.new.version.should == REXML::XMLDecl::DEFAULT_VERSION + it "returns the default version when declaration is not present" do + REXML::Document.new.version.should == REXML::XMLDecl::DEFAULT_VERSION + end end end diff --git a/ruby/spec/ruby/library/rexml/document/write_spec.rb b/ruby/spec/ruby/library/rexml/document/write_spec.rb index efa94b711..00c22141b 100644 --- a/ruby/spec/ruby/library/rexml/document/write_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/write_spec.rb @@ -1,35 +1,38 @@ -require 'rexml/document' -require 'rexml/formatters/transitive' require_relative '../../../spec_helper' -# Maybe this can be cleaned -describe "REXML::Document#write" do - before :each do - @d = REXML::Document.new - city = REXML::Element.new "Springfield" - street = REXML::Element.new "EvergreenTerrace" - address = REXML::Element.new "House742" - @d << city << street << address - @str = "" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + require 'rexml/formatters/transitive' - it "returns document source as string" do - @d.write(@str) - @str.should == "" - end + # Maybe this can be cleaned + describe "REXML::Document#write" do + before :each do + @d = REXML::Document.new + city = REXML::Element.new "Springfield" + street = REXML::Element.new "EvergreenTerrace" + address = REXML::Element.new "House742" + @d << city << street << address + @str = "" + end - it "returns document indented" do - @d.write(@str, 2) - @str.should =~ /\s*\s*\s*\s*<\/EvergreenTerrace>\s*<\/Springfield>/ - end + it "returns document source as string" do + @d.write(@str) + @str.should == "" + end - it "returns document with transitive support" do - @d.write(@str, 2, true) - @str.should =~ /\s*<\/EvergreenTerrace\s*><\/Springfield\s*>/ - end + it "returns document indented" do + @d.write(@str, 2) + @str.should =~ /\s*\s*\s*\s*<\/EvergreenTerrace>\s*<\/Springfield>/ + end + + it "returns document with transitive support" do + @d.write(@str, 2, true) + @str.should =~ /\s*<\/EvergreenTerrace\s*><\/Springfield\s*>/ + end - it "returns document with support for IE" do - @d.write(@str, -1, false, true) - @str.should == "" + it "returns document with support for IE" do + @d.write(@str, -1, false, true) + @str.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/document/xml_decl_spec.rb b/ruby/spec/ruby/library/rexml/document/xml_decl_spec.rb index 30288a150..8ac47510b 100644 --- a/ruby/spec/ruby/library/rexml/document/xml_decl_spec.rb +++ b/ruby/spec/ruby/library/rexml/document/xml_decl_spec.rb @@ -1,15 +1,18 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Document#xml_decl" do - it "returns XML declaration of the document" do - d = REXML::Document.new - decl = REXML::XMLDecl.new("1.0", "UTF-16", "yes") - d.add decl - d.xml_decl.should == decl - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Document#xml_decl" do + it "returns XML declaration of the document" do + d = REXML::Document.new + decl = REXML::XMLDecl.new("1.0", "UTF-16", "yes") + d.add decl + d.xml_decl.should == decl + end - it "returns default XML declaration unless present" do - REXML::Document.new.xml_decl.should == REXML::XMLDecl.new + it "returns default XML declaration unless present" do + REXML::Document.new.xml_decl.should == REXML::XMLDecl.new + end end end diff --git a/ruby/spec/ruby/library/rexml/element/add_attribute_spec.rb b/ruby/spec/ruby/library/rexml/element/add_attribute_spec.rb index d15fb81ef..64f2ec84a 100644 --- a/ruby/spec/ruby/library/rexml/element/add_attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/add_attribute_spec.rb @@ -1,41 +1,44 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#add_attribute" do - before :each do - @person = REXML::Element.new "person" - @person.attributes["name"] = "Bill" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "adds a new attribute" do - @person.add_attribute("age", "17") - @person.attributes["age"].should == "17" - end + describe "REXML::Element#add_attribute" do + before :each do + @person = REXML::Element.new "person" + @person.attributes["name"] = "Bill" + end - it "overwrites an existing attribute" do - @person.add_attribute("name", "Bill") - @person.attributes["name"].should == "Bill" - end + it "adds a new attribute" do + @person.add_attribute("age", "17") + @person.attributes["age"].should == "17" + end - it "accepts a pair of strings" do - @person.add_attribute("male", "true") - @person.attributes["male"].should == "true" - end + it "overwrites an existing attribute" do + @person.add_attribute("name", "Bill") + @person.attributes["name"].should == "Bill" + end - it "accepts an Attribute for key" do - attr = REXML::Attribute.new("male", "true") - @person.add_attribute attr - @person.attributes["male"].should == "true" - end + it "accepts a pair of strings" do + @person.add_attribute("male", "true") + @person.attributes["male"].should == "true" + end - it "ignores value if key is an Attribute" do - attr = REXML::Attribute.new("male", "true") - @person.add_attribute(attr, "false") - @person.attributes["male"].should == "true" - end + it "accepts an Attribute for key" do + attr = REXML::Attribute.new("male", "true") + @person.add_attribute attr + @person.attributes["male"].should == "true" + end + + it "ignores value if key is an Attribute" do + attr = REXML::Attribute.new("male", "true") + @person.add_attribute(attr, "false") + @person.attributes["male"].should == "true" + end - it "returns the attribute added" do - attr = REXML::Attribute.new("name", "Tony") - @person.add_attribute(attr).should == attr + it "returns the attribute added" do + attr = REXML::Attribute.new("name", "Tony") + @person.add_attribute(attr).should == attr + end end end diff --git a/ruby/spec/ruby/library/rexml/element/add_attributes_spec.rb b/ruby/spec/ruby/library/rexml/element/add_attributes_spec.rb index b462fdf5f..f331803dd 100644 --- a/ruby/spec/ruby/library/rexml/element/add_attributes_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/add_attributes_spec.rb @@ -1,22 +1,25 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#add_attributes" do - before :each do - @person = REXML::Element.new "person" - @person.attributes["name"] = "Bill" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "adds multiple attributes from a hash" do - @person.add_attributes({"name" => "Joe", "age" => "27"}) - @person.attributes["name"].should == "Joe" - @person.attributes["age"].should == "27" - end + describe "REXML::Element#add_attributes" do + before :each do + @person = REXML::Element.new "person" + @person.attributes["name"] = "Bill" + end + + it "adds multiple attributes from a hash" do + @person.add_attributes({"name" => "Joe", "age" => "27"}) + @person.attributes["name"].should == "Joe" + @person.attributes["age"].should == "27" + end - it "adds multiple attributes from an array" do - attrs = { "name" => "Joe", "age" => "27"} - @person.add_attributes attrs.to_a - @person.attributes["name"].should == "Joe" - @person.attributes["age"].should == "27" + it "adds multiple attributes from an array" do + attrs = { "name" => "Joe", "age" => "27"} + @person.add_attributes attrs.to_a + @person.attributes["name"].should == "Joe" + @person.attributes["age"].should == "27" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/add_element_spec.rb b/ruby/spec/ruby/library/rexml/element/add_element_spec.rb index 8e2ffe314..8ba023f2c 100644 --- a/ruby/spec/ruby/library/rexml/element/add_element_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/add_element_spec.rb @@ -1,39 +1,41 @@ -require 'rexml/document' require_relative '../../../spec_helper' +ruby_version_is ''...'3.0' do + require 'rexml/document' -describe "REXML::Element#add_element" do - before :each do - @root = REXML::Element.new("root") - end + describe "REXML::Element#add_element" do + before :each do + @root = REXML::Element.new("root") + end - it "adds a child without attributes" do - name = REXML::Element.new("name") - @root.add_element name - @root.elements["name"].name.should == name.name - @root.elements["name"].attributes.should == name.attributes - @root.elements["name"].context.should == name.context - end + it "adds a child without attributes" do + name = REXML::Element.new("name") + @root.add_element name + @root.elements["name"].name.should == name.name + @root.elements["name"].attributes.should == name.attributes + @root.elements["name"].context.should == name.context + end - it "adds a child with attributes" do - person = REXML::Element.new("person") - @root.add_element(person, {"name" => "Madonna"}) - @root.elements["person"].name.should == person.name - @root.elements["person"].attributes.should == person.attributes - @root.elements["person"].context.should == person.context - end + it "adds a child with attributes" do + person = REXML::Element.new("person") + @root.add_element(person, {"name" => "Madonna"}) + @root.elements["person"].name.should == person.name + @root.elements["person"].attributes.should == person.attributes + @root.elements["person"].context.should == person.context + end - it "adds a child with name" do - @root.add_element "name" - @root.elements["name"].name.should == "name" - @root.elements["name"].attributes.should == {} - @root.elements["name"].context.should == nil - end + it "adds a child with name" do + @root.add_element "name" + @root.elements["name"].name.should == "name" + @root.elements["name"].attributes.should == {} + @root.elements["name"].context.should == nil + end - it "returns the added child" do - name = @root.add_element "name" - @root.elements["name"].name.should == name.name - @root.elements["name"].attributes.should == name.attributes - @root.elements["name"].context.should == name.context + it "returns the added child" do + name = @root.add_element "name" + @root.elements["name"].name.should == name.name + @root.elements["name"].attributes.should == name.attributes + @root.elements["name"].context.should == name.context + end end end diff --git a/ruby/spec/ruby/library/rexml/element/add_namespace_spec.rb b/ruby/spec/ruby/library/rexml/element/add_namespace_spec.rb index 77c00eec4..44b074bac 100644 --- a/ruby/spec/ruby/library/rexml/element/add_namespace_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/add_namespace_spec.rb @@ -1,23 +1,26 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#add_namespace" do - before :each do - @elem = REXML::Element.new("person") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "adds a namespace to element" do - @elem.add_namespace("foo", "bar") - @elem.namespace("foo").should == "bar" - end + describe "REXML::Element#add_namespace" do + before :each do + @elem = REXML::Element.new("person") + end - it "accepts a prefix string as prefix" do - @elem.add_namespace("xmlns:foo", "bar") - @elem.namespace("foo").should == "bar" - end + it "adds a namespace to element" do + @elem.add_namespace("foo", "bar") + @elem.namespace("foo").should == "bar" + end + + it "accepts a prefix string as prefix" do + @elem.add_namespace("xmlns:foo", "bar") + @elem.namespace("foo").should == "bar" + end - it "uses prefix as URI if uri is nil" do - @elem.add_namespace("some_uri", nil) - @elem.namespace.should == "some_uri" + it "uses prefix as URI if uri is nil" do + @elem.add_namespace("some_uri", nil) + @elem.namespace.should == "some_uri" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/add_text_spec.rb b/ruby/spec/ruby/library/rexml/element/add_text_spec.rb index 54e127bf4..3a0531ad4 100644 --- a/ruby/spec/ruby/library/rexml/element/add_text_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/add_text_spec.rb @@ -1,24 +1,27 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#add_text" do - before :each do - @name = REXML::Element.new "Name" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "adds text to an element" do - @name.add_text "Ringo" - @name.to_s.should == "Ringo" - end + describe "REXML::Element#add_text" do + before :each do + @name = REXML::Element.new "Name" + end - it "accepts a Text" do - @name.add_text(REXML::Text.new("Ringo")) - @name.to_s.should == "Ringo" - end + it "adds text to an element" do + @name.add_text "Ringo" + @name.to_s.should == "Ringo" + end + + it "accepts a Text" do + @name.add_text(REXML::Text.new("Ringo")) + @name.to_s.should == "Ringo" + end - it "joins the new text with the old one" do - @name.add_text "Ringo" - @name.add_text " Starr" - @name.to_s.should == "Ringo Starr" + it "joins the new text with the old one" do + @name.add_text "Ringo" + @name.add_text " Starr" + @name.to_s.should == "Ringo Starr" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/attribute_spec.rb b/ruby/spec/ruby/library/rexml/element/attribute_spec.rb index e40d612ef..b223d3440 100644 --- a/ruby/spec/ruby/library/rexml/element/attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/attribute_spec.rb @@ -1,17 +1,20 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#attribute" do - it "returns an attribute by name" do - person = REXML::Element.new "Person" - attribute = REXML::Attribute.new("drink", "coffee") - person.add_attribute(attribute) - person.attribute("drink").should == attribute - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Element#attribute" do + it "returns an attribute by name" do + person = REXML::Element.new "Person" + attribute = REXML::Attribute.new("drink", "coffee") + person.add_attribute(attribute) + person.attribute("drink").should == attribute + end - it "supports attributes inside namespaces" do - e = REXML::Element.new("element") - e.add_attributes({"xmlns:ns" => "http://some_uri"}) - e.attribute("ns", "ns").to_s.should == "http://some_uri" + it "supports attributes inside namespaces" do + e = REXML::Element.new("element") + e.add_attributes({"xmlns:ns" => "http://some_uri"}) + e.attribute("ns", "ns").to_s.should == "http://some_uri" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/attributes_spec.rb b/ruby/spec/ruby/library/rexml/element/attributes_spec.rb index 8959b769a..92bcecc40 100644 --- a/ruby/spec/ruby/library/rexml/element/attributes_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/attributes_spec.rb @@ -1,19 +1,22 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#attributes" do - it "returns element's Attributes" do - p = REXML::Element.new "Person" +ruby_version_is ''...'3.0' do + require 'rexml/document' - name = REXML::Attribute.new("name", "John") - attrs = REXML::Attributes.new(p) - attrs.add name + describe "REXML::Element#attributes" do + it "returns element's Attributes" do + p = REXML::Element.new "Person" - p.add_attribute name - p.attributes.should == attrs - end + name = REXML::Attribute.new("name", "John") + attrs = REXML::Attributes.new(p) + attrs.add name + + p.add_attribute name + p.attributes.should == attrs + end - it "returns an empty hash if element has no attributes" do - REXML::Element.new("Person").attributes.should == {} + it "returns an empty hash if element has no attributes" do + REXML::Element.new("Person").attributes.should == {} + end end end diff --git a/ruby/spec/ruby/library/rexml/element/cdatas_spec.rb b/ruby/spec/ruby/library/rexml/element/cdatas_spec.rb index a371a5734..988b2cb42 100644 --- a/ruby/spec/ruby/library/rexml/element/cdatas_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/cdatas_spec.rb @@ -1,24 +1,27 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#cdatas" do - before :each do - @e = REXML::Element.new("Root") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the array of children cdatas" do - c = REXML::CData.new("Primary") - d = REXML::CData.new("Secondary") - @e << c - @e << d - @e.cdatas.should == [c, d] - end + describe "REXML::Element#cdatas" do + before :each do + @e = REXML::Element.new("Root") + end - it "freezes the returned array" do - @e.cdatas.frozen?.should == true - end + it "returns the array of children cdatas" do + c = REXML::CData.new("Primary") + d = REXML::CData.new("Secondary") + @e << c + @e << d + @e.cdatas.should == [c, d] + end + + it "freezes the returned array" do + @e.cdatas.should.frozen? + end - it "returns an empty array if element has no cdata" do - @e.cdatas.should == [] + it "returns an empty array if element has no cdata" do + @e.cdatas.should == [] + end end end diff --git a/ruby/spec/ruby/library/rexml/element/clone_spec.rb b/ruby/spec/ruby/library/rexml/element/clone_spec.rb index d26392db4..490e43181 100644 --- a/ruby/spec/ruby/library/rexml/element/clone_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/clone_spec.rb @@ -1,29 +1,32 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#clone" do - before :each do - @e = REXML::Element.new "a" - end - it "creates a copy of element" do - @e.clone.to_s.should == @e.to_s - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "copies the attributes" do - @e.add_attribute("foo", "bar") - @e.clone.to_s.should == @e.to_s - end + describe "REXML::Element#clone" do + before :each do + @e = REXML::Element.new "a" + end + it "creates a copy of element" do + @e.clone.to_s.should == @e.to_s + end - it "does not copy the text" do - @e.add_text "some text..." - @e.clone.to_s.should_not == @e - @e.clone.to_s.should == "" - end + it "copies the attributes" do + @e.add_attribute("foo", "bar") + @e.clone.to_s.should == @e.to_s + end + + it "does not copy the text" do + @e.add_text "some text..." + @e.clone.to_s.should_not == @e + @e.clone.to_s.should == "" + end - it "does not copy the child elements" do - b = REXML::Element.new "b" - @e << b - @e.clone.should_not == @e - @e.clone.to_s.should == "" + it "does not copy the child elements" do + b = REXML::Element.new "b" + @e << b + @e.clone.should_not == @e + @e.clone.to_s.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/comments_spec.rb b/ruby/spec/ruby/library/rexml/element/comments_spec.rb index 9dac2cc5b..84ab9a746 100644 --- a/ruby/spec/ruby/library/rexml/element/comments_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/comments_spec.rb @@ -1,20 +1,23 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#comments" do - before :each do - @e = REXML::Element.new "root" - @c1 = REXML::Comment.new "this is a comment" - @c2 = REXML::Comment.new "this is another comment" - @e << @c1 - @e << @c2 - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the array of comments" do - @e.comments.should == [@c1, @c2] - end + describe "REXML::Element#comments" do + before :each do + @e = REXML::Element.new "root" + @c1 = REXML::Comment.new "this is a comment" + @c2 = REXML::Comment.new "this is another comment" + @e << @c1 + @e << @c2 + end + + it "returns the array of comments" do + @e.comments.should == [@c1, @c2] + end - it "returns a frozen object" do - @e.comments.frozen?.should == true + it "returns a frozen object" do + @e.comments.should.frozen? + end end end diff --git a/ruby/spec/ruby/library/rexml/element/delete_attribute_spec.rb b/ruby/spec/ruby/library/rexml/element/delete_attribute_spec.rb index 5c55c5efd..e2ba81eb0 100644 --- a/ruby/spec/ruby/library/rexml/element/delete_attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/delete_attribute_spec.rb @@ -1,39 +1,42 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#delete_attribute" do - before :each do - @e = REXML::Element.new("Person") - @attr = REXML::Attribute.new("name", "Sean") - @e.add_attribute(@attr) - end - - it "deletes an attribute from the element" do - @e.delete_attribute("name") - @e.attributes["name"].should be_nil - end +ruby_version_is ''...'3.0' do + require 'rexml/document' -# Bug was filled with a patch in Ruby's tracker #20298 - quarantine! do - it "receives an Attribute" do + describe "REXML::Element#delete_attribute" do + before :each do + @e = REXML::Element.new("Person") + @attr = REXML::Attribute.new("name", "Sean") @e.add_attribute(@attr) - @e.delete_attribute(@attr) + end + + it "deletes an attribute from the element" do + @e.delete_attribute("name") @e.attributes["name"].should be_nil end - end - # Docs say that it returns the removed attribute but then examples - # show it returns the element with the attribute removed. - # Also fixed in #20298 - it "returns the element with the attribute removed" do - elem = @e.delete_attribute("name") - elem.attributes.should be_empty - elem.to_s.should eql("") - end + # Bug was filled with a patch in Ruby's tracker #20298 + quarantine! do + it "receives an Attribute" do + @e.add_attribute(@attr) + @e.delete_attribute(@attr) + @e.attributes["name"].should be_nil + end + end - it "returns nil if the attribute does not exist" do - @e.delete_attribute("name") - at = @e.delete_attribute("name") - at.should be_nil + # Docs say that it returns the removed attribute but then examples + # show it returns the element with the attribute removed. + # Also fixed in #20298 + it "returns the element with the attribute removed" do + elem = @e.delete_attribute("name") + elem.attributes.should be_empty + elem.to_s.should eql("") + end + + it "returns nil if the attribute does not exist" do + @e.delete_attribute("name") + at = @e.delete_attribute("name") + at.should be_nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/delete_element_spec.rb b/ruby/spec/ruby/library/rexml/element/delete_element_spec.rb index 9417229bd..c0b486a6f 100644 --- a/ruby/spec/ruby/library/rexml/element/delete_element_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/delete_element_spec.rb @@ -1,49 +1,52 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#delete_element" do - before :each do - @root = REXML::Element.new("root") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "deletes the child element" do - node = REXML::Element.new("some_node") - @root.add_element node - @root.delete_element node - @root.elements.size.should == 0 - end + describe "REXML::Element#delete_element" do + before :each do + @root = REXML::Element.new("root") + end - it "deletes a child via XPath" do - @root.add_element "some_node" - @root.delete_element "some_node" - @root.elements.size.should == 0 - end + it "deletes the child element" do + node = REXML::Element.new("some_node") + @root.add_element node + @root.delete_element node + @root.elements.size.should == 0 + end - it "deletes the child at index" do - @root.add_element "some_node" - @root.delete_element 1 - @root.elements.size.should == 0 - end + it "deletes a child via XPath" do + @root.add_element "some_node" + @root.delete_element "some_node" + @root.elements.size.should == 0 + end - # According to the docs this should return the deleted element - # but it won't if it's an Element. - it "deletes Element and returns it" do - node = REXML::Element.new("some_node") - @root.add_element node - del_node = @root.delete_element node - del_node.should == node - end + it "deletes the child at index" do + @root.add_element "some_node" + @root.delete_element 1 + @root.elements.size.should == 0 + end - # Note how passing the string will return the removed element - # but passing the Element as above won't. - it "deletes an element and returns it" do - node = REXML::Element.new("some_node") - @root.add_element node - del_node = @root.delete_element "some_node" - del_node.should == node - end + # According to the docs this should return the deleted element + # but it won't if it's an Element. + it "deletes Element and returns it" do + node = REXML::Element.new("some_node") + @root.add_element node + del_node = @root.delete_element node + del_node.should == node + end + + # Note how passing the string will return the removed element + # but passing the Element as above won't. + it "deletes an element and returns it" do + node = REXML::Element.new("some_node") + @root.add_element node + del_node = @root.delete_element "some_node" + del_node.should == node + end - it "returns nil unless element exists" do - @root.delete_element("something").should == nil + it "returns nil unless element exists" do + @root.delete_element("something").should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/delete_namespace_spec.rb b/ruby/spec/ruby/library/rexml/element/delete_namespace_spec.rb index 8683a40ca..a7763d51e 100644 --- a/ruby/spec/ruby/library/rexml/element/delete_namespace_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/delete_namespace_spec.rb @@ -1,25 +1,28 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#delete_namespace" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - before :each do - @doc = REXML::Document.new "" - end + describe "REXML::Element#delete_namespace" do - it "deletes a namespace from the element" do - @doc.root.delete_namespace 'foo' - @doc.root.namespace("foo").should be_nil - @doc.root.to_s.should == "" - end + before :each do + @doc = REXML::Document.new "" + end - it "deletes default namespace when called with no args" do - @doc.root.delete_namespace - @doc.root.namespace.should be_empty - @doc.root.to_s.should == "" - end + it "deletes a namespace from the element" do + @doc.root.delete_namespace 'foo' + @doc.root.namespace("foo").should be_nil + @doc.root.to_s.should == "" + end + + it "deletes default namespace when called with no args" do + @doc.root.delete_namespace + @doc.root.namespace.should be_empty + @doc.root.to_s.should == "" + end - it "returns the element" do - @doc.root.delete_namespace.should == @doc.root + it "returns the element" do + @doc.root.delete_namespace.should == @doc.root + end end end diff --git a/ruby/spec/ruby/library/rexml/element/document_spec.rb b/ruby/spec/ruby/library/rexml/element/document_spec.rb index 24773580f..754f27d8a 100644 --- a/ruby/spec/ruby/library/rexml/element/document_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/document_spec.rb @@ -1,16 +1,19 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#document" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the element's document" do - d = REXML::Document.new("") - d << REXML::XMLDecl.new - d.root.document.should == d - d.root.document.to_s.should == d.to_s - end + describe "REXML::Element#document" do + + it "returns the element's document" do + d = REXML::Document.new("") + d << REXML::XMLDecl.new + d.root.document.should == d + d.root.document.to_s.should == d.to_s + end - it "returns nil if it belongs to no document" do - REXML::Element.new("standalone").document.should be_nil + it "returns nil if it belongs to no document" do + REXML::Element.new("standalone").document.should be_nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb b/ruby/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb index 3c5da3f01..dcc6dbbf1 100644 --- a/ruby/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb @@ -1,35 +1,38 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#each_element_with_attributes" do - before :each do - @document = REXML::Element.new("people") - @father = REXML::Element.new("Person") - @father.attributes["name"] = "Joe" - @son = REXML::Element.new("Child") - @son.attributes["name"] = "Fred" - @document.root << @father - @document.root << @son - @childs = [] - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns childs with attribute" do - @document.each_element_with_attribute("name") { |elem| @childs << elem } - @childs[0].should == @father - @childs[1].should == @son - end + describe "REXML::Element#each_element_with_attributes" do + before :each do + @document = REXML::Element.new("people") + @father = REXML::Element.new("Person") + @father.attributes["name"] = "Joe" + @son = REXML::Element.new("Child") + @son.attributes["name"] = "Fred" + @document.root << @father + @document.root << @son + @children = [] + end - it "takes attribute value as second argument" do - @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son } - end + it "returns children with attribute" do + @document.each_element_with_attribute("name") { |elem| @children << elem } + @children[0].should == @father + @children[1].should == @son + end - it "takes max number of childs as third argument" do - @document.each_element_with_attribute("name", nil, 1) { |elem| @childs << elem } - @childs.size.should == 1 - @childs[0].should == @father - end + it "takes attribute value as second argument" do + @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son } + end + + it "takes max number of children as third argument" do + @document.each_element_with_attribute("name", nil, 1) { |elem| @children << elem } + @children.size.should == 1 + @children[0].should == @father + end - it "takes XPath filter as fourth argument" do - @document.each_element_with_attribute("name", nil, 0, "Child"){ |elem| elem.should == @son} + it "takes XPath filter as fourth argument" do + @document.each_element_with_attribute("name", nil, 0, "Child"){ |elem| elem.should == @son} + end end end diff --git a/ruby/spec/ruby/library/rexml/element/each_element_with_text_spec.rb b/ruby/spec/ruby/library/rexml/element/each_element_with_text_spec.rb index 5f9e5b85d..a4a200d23 100644 --- a/ruby/spec/ruby/library/rexml/element/each_element_with_text_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/each_element_with_text_spec.rb @@ -1,31 +1,34 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#each_element_with_text" do - before :each do - @document = REXML::Element.new("people") +ruby_version_is ''...'3.0' do + require 'rexml/document' - @joe = REXML::Element.new("Person") - @joe.text = "Joe" - @fred = REXML::Element.new("Person") - @fred.text = "Fred" - @another = REXML::Element.new("AnotherPerson") - @another.text = "Fred" - @document.root << @joe - @document.root << @fred - @document.root << @another - @childs = [] - end + describe "REXML::Element#each_element_with_text" do + before :each do + @document = REXML::Element.new("people") - it "returns childs with text" do - @document.each_element_with_text("Joe"){|c| c.should == @joe} - end + @joe = REXML::Element.new("Person") + @joe.text = "Joe" + @fred = REXML::Element.new("Person") + @fred.text = "Fred" + @another = REXML::Element.new("AnotherPerson") + @another.text = "Fred" + @document.root << @joe + @document.root << @fred + @document.root << @another + @children = [] + end - it "takes max as second argument" do - @document.each_element_with_text("Fred", 1){ |c| c.should == @fred} - end + it "returns children with text" do + @document.each_element_with_text("Joe"){|c| c.should == @joe} + end + + it "takes max as second argument" do + @document.each_element_with_text("Fred", 1){ |c| c.should == @fred} + end - it "takes XPath filter as third argument" do - @document.each_element_with_text("Fred", 0, "Person"){ |c| c.should == @fred} + it "takes XPath filter as third argument" do + @document.each_element_with_text("Fred", 0, "Person"){ |c| c.should == @fred} + end end end diff --git a/ruby/spec/ruby/library/rexml/element/element_reference_spec.rb b/ruby/spec/ruby/library/rexml/element/element_reference_spec.rb index 9660ff750..9e5d371ce 100644 --- a/ruby/spec/ruby/library/rexml/element/element_reference_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/element_reference_spec.rb @@ -1,20 +1,23 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#[]" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - before :each do - @doc = REXML::Document.new("") - @child = REXML::Element.new("child") - @doc.root.add_element @child - end + describe "REXML::Element#[]" do - it "return attribute value if argument is string or symbol" do - @doc.root[:foo].should == 'bar' - @doc.root['foo'].should == 'bar' - end + before :each do + @doc = REXML::Document.new("") + @child = REXML::Element.new("child") + @doc.root.add_element @child + end + + it "return attribute value if argument is string or symbol" do + @doc.root[:foo].should == 'bar' + @doc.root['foo'].should == 'bar' + end - it "return nth element if argument is int" do - @doc.root[0].should == @child + it "return nth element if argument is int" do + @doc.root[0].should == @child + end end end diff --git a/ruby/spec/ruby/library/rexml/element/get_text_spec.rb b/ruby/spec/ruby/library/rexml/element/get_text_spec.rb index 8ee9ea082..0fa8d7cb3 100644 --- a/ruby/spec/ruby/library/rexml/element/get_text_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/get_text_spec.rb @@ -1,18 +1,21 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#get_text" do - before :each do - @doc = REXML::Document.new "

      some textthis is bold! more text

      " - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the first text child node" do - @doc.root.get_text.value.should == "some text" - @doc.root.get_text.should be_kind_of(REXML::Text) - end + describe "REXML::Element#get_text" do + before :each do + @doc = REXML::Document.new "

      some textthis is bold! more text

      " + end + + it "returns the first text child node" do + @doc.root.get_text.value.should == "some text" + @doc.root.get_text.should be_kind_of(REXML::Text) + end - it "returns text from an element matching path" do - @doc.root.get_text("b").value.should == "this is bold!" - @doc.root.get_text("b").should be_kind_of(REXML::Text) + it "returns text from an element matching path" do + @doc.root.get_text("b").value.should == "this is bold!" + @doc.root.get_text("b").should be_kind_of(REXML::Text) + end end end diff --git a/ruby/spec/ruby/library/rexml/element/has_attributes_spec.rb b/ruby/spec/ruby/library/rexml/element/has_attributes_spec.rb index f89ec675f..af3ce8ce1 100644 --- a/ruby/spec/ruby/library/rexml/element/has_attributes_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/has_attributes_spec.rb @@ -1,17 +1,20 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#has_attributes?" do - before :each do - @e = REXML::Element.new("test_elem") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns true when element has any attributes" do - @e.add_attribute("name", "Joe") - @e.has_attributes?.should be_true - end + describe "REXML::Element#has_attributes?" do + before :each do + @e = REXML::Element.new("test_elem") + end + + it "returns true when element has any attributes" do + @e.add_attribute("name", "Joe") + @e.has_attributes?.should be_true + end - it "returns false if element has no attributes" do - @e.has_attributes?.should be_false + it "returns false if element has no attributes" do + @e.has_attributes?.should be_false + end end end diff --git a/ruby/spec/ruby/library/rexml/element/has_elements_spec.rb b/ruby/spec/ruby/library/rexml/element/has_elements_spec.rb index dc5fc9c25..04c7fe01a 100644 --- a/ruby/spec/ruby/library/rexml/element/has_elements_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/has_elements_spec.rb @@ -1,18 +1,21 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#has_elements?" do - before :each do - @e = REXML::Element.new("root") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns true if element has child elements" do - child = REXML::Element.new("child") - @e << child - @e.has_elements?.should be_true - end + describe "REXML::Element#has_elements?" do + before :each do + @e = REXML::Element.new("root") + end + + it "returns true if element has child elements" do + child = REXML::Element.new("child") + @e << child + @e.has_elements?.should be_true + end - it "returns false if element doesn't have child elements" do - @e.has_elements?.should be_false + it "returns false if element doesn't have child elements" do + @e.has_elements?.should be_false + end end end diff --git a/ruby/spec/ruby/library/rexml/element/has_text_spec.rb b/ruby/spec/ruby/library/rexml/element/has_text_spec.rb index e9d5a176c..206c167ae 100644 --- a/ruby/spec/ruby/library/rexml/element/has_text_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/has_text_spec.rb @@ -1,16 +1,19 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#has_text?" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns true if element has a Text child" do - e = REXML::Element.new("Person") - e.text = "My text" - e.has_text?.should be_true - end + describe "REXML::Element#has_text?" do + + it "returns true if element has a Text child" do + e = REXML::Element.new("Person") + e.text = "My text" + e.has_text?.should be_true + end - it "returns false if it has no Text childs" do - e = REXML::Element.new("Person") - e.has_text?.should be_false + it "returns false if it has no Text children" do + e = REXML::Element.new("Person") + e.has_text?.should be_false + end end end diff --git a/ruby/spec/ruby/library/rexml/element/inspect_spec.rb b/ruby/spec/ruby/library/rexml/element/inspect_spec.rb index f45edd0b1..ec16c136e 100644 --- a/ruby/spec/ruby/library/rexml/element/inspect_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/inspect_spec.rb @@ -1,27 +1,30 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#inspect" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - before :each do - @name = REXML::Element.new "name" - end + describe "REXML::Element#inspect" do - it "returns the node as a string" do - @name.inspect.should == "" - end + before :each do + @name = REXML::Element.new "name" + end - it "inserts '...' if the node has children" do - e = REXML::Element.new "last_name" - @name << e - @name.inspect.should == " ... " - # This might make more sense but differs from MRI's default behavior - # @name.inspect.should == " ... " - end + it "returns the node as a string" do + @name.inspect.should == "" + end + + it "inserts '...' if the node has children" do + e = REXML::Element.new "last_name" + @name << e + @name.inspect.should == " ... " + # This might make more sense but differs from MRI's default behavior + # @name.inspect.should == " ... " + end - it "inserts the attributes in the string" do - @name.add_attribute "language" - @name.attributes["language"] = "english" - @name.inspect.should == "" + it "inserts the attributes in the string" do + @name.add_attribute "language" + @name.attributes["language"] = "english" + @name.inspect.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/instructions_spec.rb b/ruby/spec/ruby/library/rexml/element/instructions_spec.rb index aa2d192e7..11f1396df 100644 --- a/ruby/spec/ruby/library/rexml/element/instructions_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/instructions_spec.rb @@ -1,21 +1,24 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#instructions" do - before :each do - @elem = REXML::Element.new("root") - end - it "returns the Instruction children nodes" do - inst = REXML::Instruction.new("xml-stylesheet", "href='headlines.css'") - @elem << inst - @elem.instructions.first.should == inst - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns an empty array if it has no Instruction children" do - @elem.instructions.should be_empty - end + describe "REXML::Element#instructions" do + before :each do + @elem = REXML::Element.new("root") + end + it "returns the Instruction children nodes" do + inst = REXML::Instruction.new("xml-stylesheet", "href='headlines.css'") + @elem << inst + @elem.instructions.first.should == inst + end + + it "returns an empty array if it has no Instruction children" do + @elem.instructions.should be_empty + end - it "freezes the returned array" do - @elem.instructions.frozen?.should be_true + it "freezes the returned array" do + @elem.instructions.frozen?.should be_true + end end end diff --git a/ruby/spec/ruby/library/rexml/element/namespace_spec.rb b/ruby/spec/ruby/library/rexml/element/namespace_spec.rb index 89662f359..28966289c 100644 --- a/ruby/spec/ruby/library/rexml/element/namespace_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/namespace_spec.rb @@ -1,27 +1,30 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#namespace" do - before :each do - @doc = REXML::Document.new("
      ") - @elem = @doc.elements["//b"] - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the default namespace" do - @elem.namespace.should == "1" - end + describe "REXML::Element#namespace" do + before :each do + @doc = REXML::Document.new("") + @elem = @doc.elements["//b"] + end - it "accepts a namespace prefix" do - @elem.namespace("y").should == "2" - @doc.elements["//c"].namespace("z").should == "3" - end + it "returns the default namespace" do + @elem.namespace.should == "1" + end - it "returns an empty String if default namespace is not defined" do - e = REXML::Document.new("") - e.root.namespace.should be_empty - end + it "accepts a namespace prefix" do + @elem.namespace("y").should == "2" + @doc.elements["//c"].namespace("z").should == "3" + end + + it "returns an empty String if default namespace is not defined" do + e = REXML::Document.new("") + e.root.namespace.should be_empty + end - it "returns nil if namespace is not defined" do - @elem.namespace("z").should be_nil + it "returns nil if namespace is not defined" do + @elem.namespace("z").should be_nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/namespaces_spec.rb b/ruby/spec/ruby/library/rexml/element/namespaces_spec.rb index a84c1d1da..454454017 100644 --- a/ruby/spec/ruby/library/rexml/element/namespaces_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/namespaces_spec.rb @@ -1,32 +1,35 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#namespaces" do - before :each do - doc = REXML::Document.new("") - @elem = doc.elements["//c"] - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns a hash of the namespaces" do - ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"} - @elem.namespaces.keys.sort.should == ns.keys.sort - @elem.namespaces.values.sort.should == ns.values.sort - end + describe "REXML::Element#namespaces" do + before :each do + doc = REXML::Document.new("") + @elem = doc.elements["//c"] + end - it "returns an empty hash if no namespaces exist" do - e = REXML::Element.new "element" - e.namespaces.kind_of?(Hash).should == true - e.namespaces.should be_empty - end + it "returns a hash of the namespaces" do + ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"} + @elem.namespaces.keys.sort.should == ns.keys.sort + @elem.namespaces.values.sort.should == ns.values.sort + end - it "uses namespace prefixes as keys" do - prefixes = ["y", "z", "xmlns"] - @elem.namespaces.keys.sort.should == prefixes.sort - end + it "returns an empty hash if no namespaces exist" do + e = REXML::Element.new "element" + e.namespaces.kind_of?(Hash).should == true + e.namespaces.should be_empty + end - it "uses namespace values as the hash values" do - values = ["2", "3", "1"] - @elem.namespaces.values.sort.should == values.sort - end + it "uses namespace prefixes as keys" do + prefixes = ["y", "z", "xmlns"] + @elem.namespaces.keys.sort.should == prefixes.sort + end + + it "uses namespace values as the hash values" do + values = ["2", "3", "1"] + @elem.namespaces.values.sort.should == values.sort + end + end end diff --git a/ruby/spec/ruby/library/rexml/element/new_spec.rb b/ruby/spec/ruby/library/rexml/element/new_spec.rb index 4ffdf4dab..c6ab28947 100644 --- a/ruby/spec/ruby/library/rexml/element/new_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/new_spec.rb @@ -1,35 +1,38 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#new" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "creates element from tag name" do - REXML::Element.new("foo").name.should == "foo" - end + describe "REXML::Element#new" do - it "creates element with default attributes" do - e = REXML::Element.new - e.name.should == REXML::Element::UNDEFINED - e.context.should == nil - e.parent.should == nil - end + it "creates element from tag name" do + REXML::Element.new("foo").name.should == "foo" + end - it "creates element from another element" do - e = REXML::Element.new "foo" - f = REXML::Element.new e - e.name.should == f.name - e.context.should == f.context - e.parent.should == f.parent - end + it "creates element with default attributes" do + e = REXML::Element.new + e.name.should == REXML::Element::UNDEFINED + e.context.should == nil + e.parent.should == nil + end - it "takes parent as second argument" do - parent = REXML::Element.new "foo" - child = REXML::Element.new "bar", parent - child.parent.should == parent - end + it "creates element from another element" do + e = REXML::Element.new "foo" + f = REXML::Element.new e + e.name.should == f.name + e.context.should == f.context + e.parent.should == f.parent + end + + it "takes parent as second argument" do + parent = REXML::Element.new "foo" + child = REXML::Element.new "bar", parent + child.parent.should == parent + end - it "takes context as third argument" do - context = {"some_key" => "some_value"} - REXML::Element.new("foo", nil, context).context.should == context + it "takes context as third argument" do + context = {"some_key" => "some_value"} + REXML::Element.new("foo", nil, context).context.should == context + end end end diff --git a/ruby/spec/ruby/library/rexml/element/next_element_spec.rb b/ruby/spec/ruby/library/rexml/element/next_element_spec.rb index 5b6d6cad9..46d8f7476 100644 --- a/ruby/spec/ruby/library/rexml/element/next_element_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/next_element_spec.rb @@ -1,19 +1,22 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#next_element" do - before :each do - @a = REXML::Element.new "a" - @b = REXML::Element.new "b" - @c = REXML::Element.new "c" - @a.root << @b - @a.root << @c - end - it "returns next existing element" do - @a.elements["b"].next_element.should == @c - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Element#next_element" do + before :each do + @a = REXML::Element.new "a" + @b = REXML::Element.new "b" + @c = REXML::Element.new "c" + @a.root << @b + @a.root << @c + end + it "returns next existing element" do + @a.elements["b"].next_element.should == @c + end - it "returns nil on last element" do - @a.elements["c"].next_element.should == nil + it "returns nil on last element" do + @a.elements["c"].next_element.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/node_type_spec.rb b/ruby/spec/ruby/library/rexml/element/node_type_spec.rb index bcab9e126..a39c2deca 100644 --- a/ruby/spec/ruby/library/rexml/element/node_type_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/node_type_spec.rb @@ -1,8 +1,11 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#node_type" do - it "returns :element" do - REXML::Element.new("MyElem").node_type.should == :element +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Element#node_type" do + it "returns :element" do + REXML::Element.new("MyElem").node_type.should == :element + end end end diff --git a/ruby/spec/ruby/library/rexml/element/prefixes_spec.rb b/ruby/spec/ruby/library/rexml/element/prefixes_spec.rb index b6edf9a84..ea4caab4b 100644 --- a/ruby/spec/ruby/library/rexml/element/prefixes_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/prefixes_spec.rb @@ -1,23 +1,26 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#prefixes" do - before :each do - doc = REXML::Document.new("") - @elem = doc.elements["//c"] - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns an array of the prefixes of the namespaces" do - @elem.prefixes.should == ["y", "z"] - end + describe "REXML::Element#prefixes" do + before :each do + doc = REXML::Document.new("") + @elem = doc.elements["//c"] + end - it "does not include the default namespace" do - @elem.prefixes.include?("xmlns").should == false - end + it "returns an array of the prefixes of the namespaces" do + @elem.prefixes.should == ["y", "z"] + end + + it "does not include the default namespace" do + @elem.prefixes.include?("xmlns").should == false + end - it "returns an empty array if no namespace was defined" do - doc = REXML::Document.new "" - root = doc.elements["//root"] - root.prefixes.should == [] + it "returns an empty array if no namespace was defined" do + doc = REXML::Document.new "" + root = doc.elements["//root"] + root.prefixes.should == [] + end end end diff --git a/ruby/spec/ruby/library/rexml/element/previous_element_spec.rb b/ruby/spec/ruby/library/rexml/element/previous_element_spec.rb index 2fe79d955..a43b1ddd1 100644 --- a/ruby/spec/ruby/library/rexml/element/previous_element_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/previous_element_spec.rb @@ -1,20 +1,23 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#previous_element" do - before :each do - @a = REXML::Element.new "a" - @b = REXML::Element.new "b" - @c = REXML::Element.new "c" - @a.root << @b - @a.root << @c - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns previous element" do - @a.elements["c"].previous_element.should == @b - end + describe "REXML::Element#previous_element" do + before :each do + @a = REXML::Element.new "a" + @b = REXML::Element.new "b" + @c = REXML::Element.new "c" + @a.root << @b + @a.root << @c + end + + it "returns previous element" do + @a.elements["c"].previous_element.should == @b + end - it "returns nil on first element" do - @a.elements["b"].previous_element.should == nil + it "returns nil on first element" do + @a.elements["b"].previous_element.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/raw_spec.rb b/ruby/spec/ruby/library/rexml/element/raw_spec.rb index 404ccce5f..200a99d19 100644 --- a/ruby/spec/ruby/library/rexml/element/raw_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/raw_spec.rb @@ -1,24 +1,27 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#raw" do - it "returns true if raw mode is set to all" do - REXML::Element.new("MyElem", nil, {raw: :all}).raw.should == true - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns true if raw mode is set to expanded_name" do - REXML::Element.new("MyElem", nil, {raw: "MyElem"}).raw.should == true - end + describe "REXML::Element#raw" do + it "returns true if raw mode is set to all" do + REXML::Element.new("MyElem", nil, {raw: :all}).raw.should == true + end - it "returns false if raw mode is not set" do - REXML::Element.new("MyElem", nil, {raw: ""}).raw.should == false - end + it "returns true if raw mode is set to expanded_name" do + REXML::Element.new("MyElem", nil, {raw: "MyElem"}).raw.should == true + end - it "returns false if raw is not :all or expanded_name" do - REXML::Element.new("MyElem", nil, {raw: "Something"}).raw.should == false - end + it "returns false if raw mode is not set" do + REXML::Element.new("MyElem", nil, {raw: ""}).raw.should == false + end + + it "returns false if raw is not :all or expanded_name" do + REXML::Element.new("MyElem", nil, {raw: "Something"}).raw.should == false + end - it "returns nil if context is not set" do - REXML::Element.new("MyElem").raw.should == nil + it "returns nil if context is not set" do + REXML::Element.new("MyElem").raw.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/element/root_spec.rb b/ruby/spec/ruby/library/rexml/element/root_spec.rb index 1e0669033..52aa4571b 100644 --- a/ruby/spec/ruby/library/rexml/element/root_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/root_spec.rb @@ -1,28 +1,31 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Element#root" do - before :each do - @doc = REXML::Document.new - @root = REXML::Element.new "root" - @node = REXML::Element.new "node" - @doc << @root << @node - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns first child on documents" do - @doc.root.should == @root - end + describe "REXML::Element#root" do + before :each do + @doc = REXML::Document.new + @root = REXML::Element.new "root" + @node = REXML::Element.new "node" + @doc << @root << @node + end - it "returns self on root nodes" do - @root.root.should == @root - end + it "returns first child on documents" do + @doc.root.should == @root + end - it "returns parent's root on child nodes" do - @node.root.should == @root - end + it "returns self on root nodes" do + @root.root.should == @root + end + + it "returns parent's root on child nodes" do + @node.root.should == @root + end - it "returns self on standalone nodes" do - e = REXML::Element.new "Elem" # Note that it doesn't have a parent node - e.root.should == e + it "returns self on standalone nodes" do + e = REXML::Element.new "Elem" # Note that it doesn't have a parent node + e.root.should == e + end end end diff --git a/ruby/spec/ruby/library/rexml/element/text_spec.rb b/ruby/spec/ruby/library/rexml/element/text_spec.rb index 7c290c4cd..3234bba15 100644 --- a/ruby/spec/ruby/library/rexml/element/text_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/text_spec.rb @@ -1,46 +1,49 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#text" do - before :each do - @e = REXML::Element.new "name" - @e.text = "John" - end - - it "returns the text node of element" do - @e.text.should == "John" - end - - it "returns the text node value" do - t = REXML::Text.new "Joe" - @e.text = t - @e.text.should == "Joe" - @e.text.should_not == t - end - - it "returns nil if no text is attached" do - elem = REXML::Element.new "name" - elem.text.should == nil - end -end - -describe "REXML::Element#text=" do - before :each do - @e = REXML::Element.new "name" - @e.text = "John" - end - - it "sets the text node" do - @e.to_s.should == "John" - end - - it "replaces existing text" do - @e.text = "Joe" - @e.to_s.should == "Joe" - end - - it "receives nil as an argument" do - @e.text = nil - @e.to_s.should == "" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Element#text" do + before :each do + @e = REXML::Element.new "name" + @e.text = "John" + end + + it "returns the text node of element" do + @e.text.should == "John" + end + + it "returns the text node value" do + t = REXML::Text.new "Joe" + @e.text = t + @e.text.should == "Joe" + @e.text.should_not == t + end + + it "returns nil if no text is attached" do + elem = REXML::Element.new "name" + elem.text.should == nil + end + end + + describe "REXML::Element#text=" do + before :each do + @e = REXML::Element.new "name" + @e.text = "John" + end + + it "sets the text node" do + @e.to_s.should == "John" + end + + it "replaces existing text" do + @e.text = "Joe" + @e.to_s.should == "Joe" + end + + it "receives nil as an argument" do + @e.text = nil + @e.to_s.should == "" + end end end diff --git a/ruby/spec/ruby/library/rexml/element/texts_spec.rb b/ruby/spec/ruby/library/rexml/element/texts_spec.rb index 7975833c8..2d374d5e6 100644 --- a/ruby/spec/ruby/library/rexml/element/texts_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/texts_spec.rb @@ -1,16 +1,19 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#texts" do +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns an array of the Text children" do - e = REXML::Element.new("root") - e.add_text "First" - e.add_text "Second" - e.texts.should == ["FirstSecond"] - end + describe "REXML::Element#texts" do + + it "returns an array of the Text children" do + e = REXML::Element.new("root") + e.add_text "First" + e.add_text "Second" + e.texts.should == ["FirstSecond"] + end - it "returns an empty array if it has no Text children" do - REXML::Element.new("root").texts.should == [] + it "returns an empty array if it has no Text children" do + REXML::Element.new("root").texts.should == [] + end end end diff --git a/ruby/spec/ruby/library/rexml/element/whitespace_spec.rb b/ruby/spec/ruby/library/rexml/element/whitespace_spec.rb index dc785ae5c..f45506792 100644 --- a/ruby/spec/ruby/library/rexml/element/whitespace_spec.rb +++ b/ruby/spec/ruby/library/rexml/element/whitespace_spec.rb @@ -1,23 +1,26 @@ -require 'rexml/document' require_relative '../../../spec_helper' -describe "REXML::Element#whitespace" do - it "returns true if whitespace is respected in the element" do - e = REXML::Element.new("root") - e.whitespace.should be_true +ruby_version_is ''...'3.0' do + require 'rexml/document' - e = REXML::Element.new("root", nil, respect_whitespace: :all) - e.whitespace.should be_true + describe "REXML::Element#whitespace" do + it "returns true if whitespace is respected in the element" do + e = REXML::Element.new("root") + e.whitespace.should be_true - e = REXML::Element.new("root", nil, respect_whitespace: ["root"]) - e.whitespace.should be_true - end + e = REXML::Element.new("root", nil, respect_whitespace: :all) + e.whitespace.should be_true + + e = REXML::Element.new("root", nil, respect_whitespace: ["root"]) + e.whitespace.should be_true + end - it "returns false if whitespace is ignored inside element" do - e = REXML::Element.new("root", nil, compress_whitespace: :all) - e.whitespace.should be_false + it "returns false if whitespace is ignored inside element" do + e = REXML::Element.new("root", nil, compress_whitespace: :all) + e.whitespace.should be_false - e = REXML::Element.new("root", nil, compress_whitespace: ["root"]) - e.whitespace.should be_false + e = REXML::Element.new("root", nil, compress_whitespace: ["root"]) + e.whitespace.should be_false + end end end diff --git a/ruby/spec/ruby/library/rexml/node/each_recursive_spec.rb b/ruby/spec/ruby/library/rexml/node/each_recursive_spec.rb index dd4aa9a2f..da347b138 100644 --- a/ruby/spec/ruby/library/rexml/node/each_recursive_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/each_recursive_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#each_recursive" do - before :each do - @doc = REXML::Document.new - @doc << REXML::XMLDecl.new - @root = REXML::Element.new "root" - @child1 = REXML::Element.new "child1" - @child2 = REXML::Element.new "child2" - @root << @child1 - @root << @child2 - @doc << @root - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Node#each_recursive" do + before :each do + @doc = REXML::Document.new + @doc << REXML::XMLDecl.new + @root = REXML::Element.new "root" + @child1 = REXML::Element.new "child1" + @child2 = REXML::Element.new "child2" + @root << @child1 + @root << @child2 + @doc << @root + end - it "visits all subnodes of self" do - nodes = [] - @doc.each_recursive { |node| nodes << node} - nodes.should == [@root, @child1, @child2] + it "visits all subnodes of self" do + nodes = [] + @doc.each_recursive { |node| nodes << node} + nodes.should == [@root, @child1, @child2] + end end end diff --git a/ruby/spec/ruby/library/rexml/node/find_first_recursive_spec.rb b/ruby/spec/ruby/library/rexml/node/find_first_recursive_spec.rb index ba46f2ca3..2a4f1097a 100644 --- a/ruby/spec/ruby/library/rexml/node/find_first_recursive_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/find_first_recursive_spec.rb @@ -1,25 +1,28 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#find_first_recursive" do - before :each do - @e = REXML::Element.new("root") - @node1 = REXML::Element.new("node") - @node2 = REXML::Element.new("another node") - @subnode = REXML::Element.new("another node") - @node1 << @subnode - @e << @node1 - @e << @node2 - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "finds the first element that matches block" do - found = @e.find_first_recursive { |n| n.to_s == ""} - found.should == @node1 - end + describe "REXML::Node#find_first_recursive" do + before :each do + @e = REXML::Element.new("root") + @node1 = REXML::Element.new("node") + @node2 = REXML::Element.new("another node") + @subnode = REXML::Element.new("another node") + @node1 << @subnode + @e << @node1 + @e << @node2 + end + + it "finds the first element that matches block" do + found = @e.find_first_recursive { |n| n.to_s == ""} + found.should == @node1 + end - it "visits the nodes in preorder" do - found = @e.find_first_recursive { |n| n.to_s == ""} - found.should == @subnode - found.should_not == @node2 + it "visits the nodes in preorder" do + found = @e.find_first_recursive { |n| n.to_s == ""} + found.should == @subnode + found.should_not == @node2 + end end end diff --git a/ruby/spec/ruby/library/rexml/node/index_in_parent_spec.rb b/ruby/spec/ruby/library/rexml/node/index_in_parent_spec.rb index 092851e3e..55909f86d 100644 --- a/ruby/spec/ruby/library/rexml/node/index_in_parent_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/index_in_parent_spec.rb @@ -1,15 +1,18 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#index_in_parent" do - it "returns the index (starting from 1) of self in parent" do - e = REXML::Element.new("root") - node1 = REXML::Element.new("node") - node2 = REXML::Element.new("another node") - e << node1 - e << node2 +ruby_version_is ''...'3.0' do + require 'rexml/document' - node1.index_in_parent.should == 1 - node2.index_in_parent.should == 2 + describe "REXML::Node#index_in_parent" do + it "returns the index (starting from 1) of self in parent" do + e = REXML::Element.new("root") + node1 = REXML::Element.new("node") + node2 = REXML::Element.new("another node") + e << node1 + e << node2 + + node1.index_in_parent.should == 1 + node2.index_in_parent.should == 2 + end end end diff --git a/ruby/spec/ruby/library/rexml/node/next_sibling_node_spec.rb b/ruby/spec/ruby/library/rexml/node/next_sibling_node_spec.rb index 2e8601627..7aae861d7 100644 --- a/ruby/spec/ruby/library/rexml/node/next_sibling_node_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/next_sibling_node_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#next_sibling_node" do - before :each do - @e = REXML::Element.new("root") - @node1 = REXML::Element.new("node") - @node2 = REXML::Element.new("another node") - @e << @node1 - @e << @node2 - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the next child node in parent" do - @node1.next_sibling_node.should == @node2 - end + describe "REXML::Node#next_sibling_node" do + before :each do + @e = REXML::Element.new("root") + @node1 = REXML::Element.new("node") + @node2 = REXML::Element.new("another node") + @e << @node1 + @e << @node2 + end + + it "returns the next child node in parent" do + @node1.next_sibling_node.should == @node2 + end - it "returns nil if there are no more child nodes next" do - @node2.next_sibling_node.should == nil - @e.next_sibling_node.should == nil + it "returns nil if there are no more child nodes next" do + @node2.next_sibling_node.should == nil + @e.next_sibling_node.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/node/parent_spec.rb b/ruby/spec/ruby/library/rexml/node/parent_spec.rb index d88ba6965..43c3a747e 100644 --- a/ruby/spec/ruby/library/rexml/node/parent_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/parent_spec.rb @@ -1,20 +1,23 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#parent?" do - it "returns true for Elements" do - e = REXML::Element.new("foo") - e.parent?.should == true - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns true for Documents" do - e = REXML::Document.new - e.parent?.should == true - end + describe "REXML::Node#parent?" do + it "returns true for Elements" do + e = REXML::Element.new("foo") + e.should.parent? + end + + it "returns true for Documents" do + e = REXML::Document.new + e.should.parent? + end - # This includes attributes, CDatas and declarations. - it "returns false for Texts" do - e = REXML::Text.new("foo") - e.parent?.should == false + # This includes attributes, CData and declarations. + it "returns false for Texts" do + e = REXML::Text.new("foo") + e.should_not.parent? + end end end diff --git a/ruby/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb b/ruby/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb index 8b96f1565..11263968a 100644 --- a/ruby/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb +++ b/ruby/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb @@ -1,21 +1,24 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Node#previous_sibling_node" do - before :each do - @e = REXML::Element.new("root") - @node1 = REXML::Element.new("node") - @node2 = REXML::Element.new("another node") - @e << @node1 - @e << @node2 - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns the previous child node in parent" do - @node2.previous_sibling_node.should == @node1 - end + describe "REXML::Node#previous_sibling_node" do + before :each do + @e = REXML::Element.new("root") + @node1 = REXML::Element.new("node") + @node2 = REXML::Element.new("another node") + @e << @node1 + @e << @node2 + end + + it "returns the previous child node in parent" do + @node2.previous_sibling_node.should == @node1 + end - it "returns nil if there are no more child nodes before" do - @node1.previous_sibling_node.should == nil - @e.previous_sibling_node.should == nil + it "returns nil if there are no more child nodes before" do + @node1.previous_sibling_node.should == nil + @e.previous_sibling_node.should == nil + end end end diff --git a/ruby/spec/ruby/library/rexml/shared/elements_to_a.rb b/ruby/spec/ruby/library/rexml/shared/elements_to_a.rb index 388250d8b..b7169f0b2 100644 --- a/ruby/spec/ruby/library/rexml/shared/elements_to_a.rb +++ b/ruby/spec/ruby/library/rexml/shared/elements_to_a.rb @@ -19,7 +19,7 @@ # always needs the first param (even if it's nil). # A patch was submitted: # http://rubyforge.org/tracker/index.php?func=detail&aid=19354&group_id=426&atid=1698 - it "returns all childs if xpath is nil" do + it "returns all children if xpath is nil" do @e.elements.send(@method).should == [@first, @second] end diff --git a/ruby/spec/ruby/library/rexml/text/append_spec.rb b/ruby/spec/ruby/library/rexml/text/append_spec.rb index de281fb0b..5e7a5bae7 100644 --- a/ruby/spec/ruby/library/rexml/text/append_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/append_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#<<" do - it "appends a string to this text node" do - text = REXML::Text.new("foo") - text << "bar" - text.should == "foobar" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text#<<" do + it "appends a string to this text node" do + text = REXML::Text.new("foo") + text << "bar" + text.should == "foobar" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/clone_spec.rb b/ruby/spec/ruby/library/rexml/text/clone_spec.rb index 8031e140c..7801782ff 100644 --- a/ruby/spec/ruby/library/rexml/text/clone_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/clone_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#clone" do - it "creates a copy of this node" do - text = REXML::Text.new("foo") - text.clone.should == "foo" - text.clone.should == text +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text#clone" do + it "creates a copy of this node" do + text = REXML::Text.new("foo") + text.clone.should == "foo" + text.clone.should == text + end end end diff --git a/ruby/spec/ruby/library/rexml/text/comparison_spec.rb b/ruby/spec/ruby/library/rexml/text/comparison_spec.rb index 8bc5d66a0..119dd050a 100644 --- a/ruby/spec/ruby/library/rexml/text/comparison_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/comparison_spec.rb @@ -1,25 +1,28 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#<=>" do - before :each do - @first = REXML::Text.new("abc") - @last = REXML::Text.new("def") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "returns -1 if lvalue is less than rvalue" do - val = @first <=> @last - val.should == -1 - end + describe "REXML::Text#<=>" do + before :each do + @first = REXML::Text.new("abc") + @last = REXML::Text.new("def") + end - it "returns -1 if lvalue is greater than rvalue" do - val = @last <=> @first - val.should == 1 - end + it "returns -1 if lvalue is less than rvalue" do + val = @first <=> @last + val.should == -1 + end + + it "returns -1 if lvalue is greater than rvalue" do + val = @last <=> @first + val.should == 1 + end - it "returns 0 if both values are equal" do - tmp = REXML::Text.new("tmp") - val = tmp <=> tmp - val.should == 0 + it "returns 0 if both values are equal" do + tmp = REXML::Text.new("tmp") + val = tmp <=> tmp + val.should == 0 + end end end diff --git a/ruby/spec/ruby/library/rexml/text/empty_spec.rb b/ruby/spec/ruby/library/rexml/text/empty_spec.rb index d0b66b7a2..4c9c899bc 100644 --- a/ruby/spec/ruby/library/rexml/text/empty_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/empty_spec.rb @@ -1,12 +1,15 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#empty?" do - it "returns true if the text is empty" do - REXML::Text.new("").empty?.should == true - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text#empty?" do + it "returns true if the text is empty" do + REXML::Text.new("").should.empty? + end - it "returns false if the text is not empty" do - REXML::Text.new("some_text").empty?.should == false + it "returns false if the text is not empty" do + REXML::Text.new("some_text").should_not.empty? + end end end diff --git a/ruby/spec/ruby/library/rexml/text/indent_text_spec.rb b/ruby/spec/ruby/library/rexml/text/indent_text_spec.rb index 1b0ee5ab1..73065c37d 100644 --- a/ruby/spec/ruby/library/rexml/text/indent_text_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/indent_text_spec.rb @@ -1,23 +1,26 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#indent_text" do - before :each do - @t = REXML::Text.new("") - end - it "indents a string with default parameters" do - @t.indent_text("foo").should == "\tfoo" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "accepts a custom indentation level as second argument" do - @t.indent_text("foo", 2, "\t", true).should == "\t\tfoo" - end + describe "REXML::Text#indent_text" do + before :each do + @t = REXML::Text.new("") + end + it "indents a string with default parameters" do + @t.indent_text("foo").should == "\tfoo" + end - it "accepts a custom separator as third argument" do - @t.indent_text("foo", 1, "\n", true).should == "\nfoo" - end + it "accepts a custom indentation level as second argument" do + @t.indent_text("foo", 2, "\t", true).should == "\t\tfoo" + end + + it "accepts a custom separator as third argument" do + @t.indent_text("foo", 1, "\n", true).should == "\nfoo" + end - it "accepts a fourth parameter to skip the first line" do - @t.indent_text("foo", 1, "\t", false).should == "foo" + it "accepts a fourth parameter to skip the first line" do + @t.indent_text("foo", 1, "\t", false).should == "foo" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/inspect_spec.rb b/ruby/spec/ruby/library/rexml/text/inspect_spec.rb index 0d66088a6..af389890e 100644 --- a/ruby/spec/ruby/library/rexml/text/inspect_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/inspect_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#inspect" do - it "inspects the string attribute as a string" do - REXML::Text.new("a text").inspect.should == "a text".inspect +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text#inspect" do + it "inspects the string attribute as a string" do + REXML::Text.new("a text").inspect.should == "a text".inspect + end end end diff --git a/ruby/spec/ruby/library/rexml/text/new_spec.rb b/ruby/spec/ruby/library/rexml/text/new_spec.rb index 3c081dec3..8b33da929 100644 --- a/ruby/spec/ruby/library/rexml/text/new_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/new_spec.rb @@ -1,48 +1,51 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text.new" do - - it "creates a Text child node with no parent" do - t = REXML::Text.new("test") - t.should be_kind_of(REXML::Child) - t.should == "test" - t.parent.should == nil - end - - it "respects whitespace if second argument is true" do - t = REXML::Text.new("testing whitespace", true) - t.should == "testing whitespace" - t = REXML::Text.new(" ", true) - t.should == " " - end - - it "receives a parent as third argument" do - e = REXML::Element.new("root") - t = REXML::Text.new("test", false, e) - t.parent.should == e - e.to_s.should == "test" - end - - it "expects escaped text if raw is true" do - t = REXML::Text.new("<&>", false, nil, true) - t.should == "<&>" - - ->{ REXML::Text.new("<&>", false, nil, true)}.should raise_error(Exception) - end - - it "uses raw value of the parent if raw is nil" do - e1 = REXML::Element.new("root", nil, { raw: :all}) - -> {REXML::Text.new("<&>", false, e1)}.should raise_error(Exception) - - e2 = REXML::Element.new("root", nil, { raw: []}) - e2.raw.should be_false - t1 = REXML::Text.new("<&>", false, e2) - t1.should == "<&>" - end - - it "escapes the values if raw is false" do - t = REXML::Text.new("<&>", false, nil, false) - t.should == "<&>" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text.new" do + + it "creates a Text child node with no parent" do + t = REXML::Text.new("test") + t.should be_kind_of(REXML::Child) + t.should == "test" + t.parent.should == nil + end + + it "respects whitespace if second argument is true" do + t = REXML::Text.new("testing whitespace", true) + t.should == "testing whitespace" + t = REXML::Text.new(" ", true) + t.should == " " + end + + it "receives a parent as third argument" do + e = REXML::Element.new("root") + t = REXML::Text.new("test", false, e) + t.parent.should == e + e.to_s.should == "test" + end + + it "expects escaped text if raw is true" do + t = REXML::Text.new("<&>", false, nil, true) + t.should == "<&>" + + ->{ REXML::Text.new("<&>", false, nil, true)}.should raise_error(Exception) + end + + it "uses raw value of the parent if raw is nil" do + e1 = REXML::Element.new("root", nil, { raw: :all}) + -> {REXML::Text.new("<&>", false, e1)}.should raise_error(Exception) + + e2 = REXML::Element.new("root", nil, { raw: []}) + e2.raw.should be_false + t1 = REXML::Text.new("<&>", false, e2) + t1.should == "<&>" + end + + it "escapes the values if raw is false" do + t = REXML::Text.new("<&>", false, nil, false) + t.should == "<&>" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/node_type_spec.rb b/ruby/spec/ruby/library/rexml/text/node_type_spec.rb index 1c25a74da..f44a1ede3 100644 --- a/ruby/spec/ruby/library/rexml/text/node_type_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/node_type_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#node_type" do - it "returns :text" do - REXML::Text.new("test").node_type.should == :text +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text#node_type" do + it "returns :text" do + REXML::Text.new("test").node_type.should == :text + end end end diff --git a/ruby/spec/ruby/library/rexml/text/normalize_spec.rb b/ruby/spec/ruby/library/rexml/text/normalize_spec.rb index ce3b2b3b5..cde11ec3c 100644 --- a/ruby/spec/ruby/library/rexml/text/normalize_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/normalize_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text.normalize" do - it "escapes a string with <, >, &, ' and \" " do - REXML::Text.normalize("< > & \" '").should == "< > & " '" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text.normalize" do + it "escapes a string with <, >, &, ' and \" " do + REXML::Text.normalize("< > & \" '").should == "< > & " '" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/read_with_substitution_spec.rb b/ruby/spec/ruby/library/rexml/text/read_with_substitution_spec.rb index 83b42f6d6..7ff26f4d5 100644 --- a/ruby/spec/ruby/library/rexml/text/read_with_substitution_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/read_with_substitution_spec.rb @@ -1,12 +1,15 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text.read_with_substitution" do - it "reads a text and escapes entities" do - REXML::Text.read_with_substitution("< > & " '").should == "< > & \" '" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text.read_with_substitution" do + it "reads a text and escapes entities" do + REXML::Text.read_with_substitution("< > & " '").should == "< > & \" '" + end - it "accepts an regex for invalid expressions and raises an error if text matches" do - -> {REXML::Text.read_with_substitution("this is illegal", /illegal/)}.should raise_error(Exception) + it "accepts an regex for invalid expressions and raises an error if text matches" do + -> {REXML::Text.read_with_substitution("this is illegal", /illegal/)}.should raise_error(Exception) + end end end diff --git a/ruby/spec/ruby/library/rexml/text/to_s_spec.rb b/ruby/spec/ruby/library/rexml/text/to_s_spec.rb index 14d7399a6..e67632c9a 100644 --- a/ruby/spec/ruby/library/rexml/text/to_s_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/to_s_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#to_s" do - it "returns the string of this Text node" do - u = REXML::Text.new("sean russell", false, nil, true) - u.to_s.should == "sean russell" +ruby_version_is ''...'3.0' do + require 'rexml/document' - t = REXML::Text.new("some test text") - t.to_s.should == "some test text" - end + describe "REXML::Text#to_s" do + it "returns the string of this Text node" do + u = REXML::Text.new("sean russell", false, nil, true) + u.to_s.should == "sean russell" + + t = REXML::Text.new("some test text") + t.to_s.should == "some test text" + end - it "escapes the text" do - t = REXML::Text.new("& < >") - t.to_s.should == "& < >" + it "escapes the text" do + t = REXML::Text.new("& < >") + t.to_s.should == "& < >" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/unnormalize_spec.rb b/ruby/spec/ruby/library/rexml/text/unnormalize_spec.rb index 3072809c1..7b507194d 100644 --- a/ruby/spec/ruby/library/rexml/text/unnormalize_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/unnormalize_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text.unnormalize" do - it "unescapes a string with the values defined in SETUTITSBUS" do - REXML::Text.unnormalize("< > & " '").should == "< > & \" '" +ruby_version_is ''...'3.0' do + require 'rexml/document' + + describe "REXML::Text.unnormalize" do + it "unescapes a string with the values defined in SETUTITSBUS" do + REXML::Text.unnormalize("< > & " '").should == "< > & \" '" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/value_spec.rb b/ruby/spec/ruby/library/rexml/text/value_spec.rb index b0545b3cb..53d40c765 100644 --- a/ruby/spec/ruby/library/rexml/text/value_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/value_spec.rb @@ -1,37 +1,40 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#value" do - it "returns the text value of this node" do - REXML::Text.new("test").value.should == "test" - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "does not escape entities" do - REXML::Text.new("& \"").value.should == "& \"" - end + describe "REXML::Text#value" do + it "returns the text value of this node" do + REXML::Text.new("test").value.should == "test" + end - it "follows the respect_whitespace attribute" do - REXML::Text.new("test bar", false).value.should == "test bar" - REXML::Text.new("test bar", true).value.should == "test bar" - end + it "does not escape entities" do + REXML::Text.new("& \"").value.should == "& \"" + end - it "ignores the raw attribute" do - REXML::Text.new("sean russell", false, nil, true).value.should == "sean russell" - end -end + it "follows the respect_whitespace attribute" do + REXML::Text.new("test bar", false).value.should == "test bar" + REXML::Text.new("test bar", true).value.should == "test bar" + end -describe "REXML::Text#value=" do - before :each do - @t = REXML::Text.new("new") + it "ignores the raw attribute" do + REXML::Text.new("sean russell", false, nil, true).value.should == "sean russell" + end end - it "sets the text of the node" do - @t.value = "another text" - @t.to_s.should == "another text" - end + describe "REXML::Text#value=" do + before :each do + @t = REXML::Text.new("new") + end + + it "sets the text of the node" do + @t.value = "another text" + @t.to_s.should == "another text" + end - it "escapes entities" do - @t.value = "" - @t.to_s.should == "<a>" + it "escapes entities" do + @t.value = "" + @t.to_s.should == "<a>" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/wrap_spec.rb b/ruby/spec/ruby/library/rexml/text/wrap_spec.rb index 0b60fd415..331a8439e 100644 --- a/ruby/spec/ruby/library/rexml/text/wrap_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/wrap_spec.rb @@ -1,20 +1,23 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#wrap" do - before :each do - @t = REXML::Text.new("abc def") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - it "wraps the text at width" do - @t.wrap("abc def", 3, false).should == "abc\ndef" - end + describe "REXML::Text#wrap" do + before :each do + @t = REXML::Text.new("abc def") + end - it "returns the string if width is greater than the size of the string" do - @t.wrap("abc def", 10, false).should == "abc def" - end + it "wraps the text at width" do + @t.wrap("abc def", 3, false).should == "abc\ndef" + end + + it "returns the string if width is greater than the size of the string" do + @t.wrap("abc def", 10, false).should == "abc def" + end - it "takes a newline at the beginning option as the third parameter" do - @t.wrap("abc def", 3, true).should == "\nabc\ndef" + it "takes a newline at the beginning option as the third parameter" do + @t.wrap("abc def", 3, true).should == "\nabc\ndef" + end end end diff --git a/ruby/spec/ruby/library/rexml/text/write_with_substitution_spec.rb b/ruby/spec/ruby/library/rexml/text/write_with_substitution_spec.rb index ee79489d8..840f141e3 100644 --- a/ruby/spec/ruby/library/rexml/text/write_with_substitution_spec.rb +++ b/ruby/spec/ruby/library/rexml/text/write_with_substitution_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'rexml/document' -describe "REXML::Text#write_with_substitution" do - before :each do - @t = REXML::Text.new("test") - @f = tmp("rexml_spec") - @file = File.open(@f, "w+") - end +ruby_version_is ''...'3.0' do + require 'rexml/document' - after :each do - @file.close - rm_r @f - end + describe "REXML::Text#write_with_substitution" do + before :each do + @t = REXML::Text.new("test") + @f = tmp("rexml_spec") + @file = File.open(@f, "w+") + end - it "writes out the input to a String" do - s = "" - @t.write_with_substitution(s, "some text") - s.should == "some text" - end + after :each do + @file.close + rm_r @f + end - it "writes out the input to an IO" do - @t.write_with_substitution(@file, "some text") - @file.rewind - @file.gets.should == "some text" - end + it "writes out the input to a String" do + s = "" + @t.write_with_substitution(s, "some text") + s.should == "some text" + end + + it "writes out the input to an IO" do + @t.write_with_substitution(@file, "some text") + @file.rewind + @file.gets.should == "some text" + end - it "escapes characters" do - @t.write_with_substitution(@file, "& < >") - @file.rewind - @file.gets.should == "& < >" + it "escapes characters" do + @t.write_with_substitution(@file, "& < >") + @file.rewind + @file.gets.should == "& < >" + end end end diff --git a/ruby/spec/ruby/library/ripper/lex_spec.rb b/ruby/spec/ruby/library/ripper/lex_spec.rb new file mode 100644 index 000000000..97cfb0690 --- /dev/null +++ b/ruby/spec/ruby/library/ripper/lex_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../spec_helper' +require 'ripper' + +describe "Ripper.lex" do + it "lexes a simple method declaration" do + expected = [ + [[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'] + ] + lexed = Ripper.lex("def m(a) nil end") + lexed.map { |e| + e[0...-1] + [e[-1].to_s.split('|').map { |s| s.sub(/^EXPR_/, '') }.join('|')] + }.should == expected + end +end diff --git a/ruby/spec/ruby/library/ripper/sexp_spec.rb b/ruby/spec/ruby/library/ripper/sexp_spec.rb new file mode 100644 index 000000000..6c69624c6 --- /dev/null +++ b/ruby/spec/ruby/library/ripper/sexp_spec.rb @@ -0,0 +1,13 @@ +require_relative '../../spec_helper' +require 'ripper' + +describe "Ripper.sexp" do + it "returns an s-expression for a method declaration" do + expected = [:program, + [[:def, + [:@ident, "hello", [1, 4]], + [:params, nil, nil, nil, nil, nil, nil, nil], + [:bodystmt, [[:@int, "42", [1, 11]]], nil, nil, nil]]]] + Ripper.sexp("def hello; 42; end").should == expected + end +end diff --git a/ruby/spec/ruby/library/rubygems/gem/load_path_insert_index_spec.rb b/ruby/spec/ruby/library/rubygems/gem/load_path_insert_index_spec.rb new file mode 100644 index 000000000..58913cdda --- /dev/null +++ b/ruby/spec/ruby/library/rubygems/gem/load_path_insert_index_spec.rb @@ -0,0 +1,10 @@ +require_relative '../../../spec_helper' +require 'rubygems' + +describe "Gem.load_path_insert_index" do + guard -> { RbConfig::TOPDIR } do + it "is set for an installed an installed Ruby" do + Gem.load_path_insert_index.should be_kind_of Integer + end + end +end diff --git a/ruby/spec/ruby/library/securerandom/random_number_spec.rb b/ruby/spec/ruby/library/securerandom/random_number_spec.rb index 3e1812c6e..03781f490 100644 --- a/ruby/spec/ruby/library/securerandom/random_number_spec.rb +++ b/ruby/spec/ruby/library/securerandom/random_number_spec.rb @@ -10,7 +10,7 @@ it "generates a random positive number smaller then the positive integer argument" do (1..64).each do |idx| num = SecureRandom.random_number(idx) - num.should be_kind_of(Fixnum) + num.should be_kind_of(Integer) (0 <= num).should == true (num < idx).should == true end diff --git a/ruby/spec/ruby/library/set/case_compare_spec.rb b/ruby/spec/ruby/library/set/case_compare_spec.rb index 193006dbd..70d392a27 100644 --- a/ruby/spec/ruby/library/set/case_compare_spec.rb +++ b/ruby/spec/ruby/library/set/case_compare_spec.rb @@ -2,13 +2,11 @@ require_relative 'shared/include' require 'set' -ruby_version_is "2.5" do - describe "Set#===" do - it_behaves_like :set_include, :=== +describe "Set#===" do + it_behaves_like :set_include, :=== - it "is an alias for include?" do - set = Set.new - set.method(:===).should == set.method(:include?) - end + it "is an alias for include?" do + set = Set.new + set.method(:===).should == set.method(:include?) end end diff --git a/ruby/spec/ruby/library/set/case_equality_spec.rb b/ruby/spec/ruby/library/set/case_equality_spec.rb index 875630612..10cbfd380 100644 --- a/ruby/spec/ruby/library/set/case_equality_spec.rb +++ b/ruby/spec/ruby/library/set/case_equality_spec.rb @@ -2,8 +2,6 @@ require_relative 'shared/include' require 'set' -ruby_version_is "2.5" do - describe "Set#===" do - it_behaves_like :set_include, :=== - end +describe "Set#===" do + it_behaves_like :set_include, :=== end diff --git a/ruby/spec/ruby/library/set/compare_by_identity_spec.rb b/ruby/spec/ruby/library/set/compare_by_identity_spec.rb index a6ad794ad..9ed160218 100644 --- a/ruby/spec/ruby/library/set/compare_by_identity_spec.rb +++ b/ruby/spec/ruby/library/set/compare_by_identity_spec.rb @@ -42,7 +42,7 @@ def o.hash; 123; end set = Set.new.compare_by_identity set << :foo set.compare_by_identity.should equal(set) - set.compare_by_identity?.should == true + set.should.compare_by_identity? set.to_a.should == [:foo] end @@ -91,11 +91,11 @@ def o.hash; 123; end set.to_a.sort.should == [a1, a2].sort end - it "raises a #{frozen_error_class} on frozen sets" do + it "raises a FrozenError on frozen sets" do set = Set.new.freeze -> { set.compare_by_identity - }.should raise_error(frozen_error_class, /frozen Hash/) + }.should raise_error(FrozenError, /frozen Hash/) end it "persists over #dups" do @@ -124,20 +124,20 @@ def o.hash; 123; end describe "Set#compare_by_identity?" do it "returns false by default" do - Set.new.compare_by_identity?.should == false + Set.new.should_not.compare_by_identity? end it "returns true once #compare_by_identity has been invoked on self" do set = Set.new set.compare_by_identity - set.compare_by_identity?.should == true + set.should.compare_by_identity? end it "returns true when called multiple times on the same set" do set = Set.new set.compare_by_identity - set.compare_by_identity?.should == true - set.compare_by_identity?.should == true - set.compare_by_identity?.should == true + set.should.compare_by_identity? + set.should.compare_by_identity? + set.should.compare_by_identity? end end diff --git a/ruby/spec/ruby/library/set/comparison_spec.rb b/ruby/spec/ruby/library/set/comparison_spec.rb new file mode 100644 index 000000000..b851ea3d5 --- /dev/null +++ b/ruby/spec/ruby/library/set/comparison_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../spec_helper' +require 'set' + +ruby_version_is "3.0" do + describe "Set#<=>" do + it "returns 0 if the sets are equal" do + (Set[] <=> Set[]).should == 0 + (Set[:a, :b, :c] <=> Set[:a, :b, :c]).should == 0 + end + + it "returns -1 if the set is a proper subset of the other set" do + (Set[] <=> Set[1]).should == -1 + (Set[1, 2] <=> Set[1, 2, 3]).should == -1 + end + + it "returns +1 if the set is a proper superset of other set" do + (Set[1] <=> Set[]).should == +1 + (Set[1, 2, 3] <=> Set[1, 2]).should == +1 + end + + it "returns nil if the set has unique elements" do + (Set[1, 2, 3] <=> Set[:a, :b, :c]).should be_nil + end + + it "returns nil when the argument is not set-like" do + (Set[] <=> false).should be_nil + end + end +end diff --git a/ruby/spec/ruby/library/set/enumerable/to_set_spec.rb b/ruby/spec/ruby/library/set/enumerable/to_set_spec.rb index 0f5504fef..3790d8dee 100644 --- a/ruby/spec/ruby/library/set/enumerable/to_set_spec.rb +++ b/ruby/spec/ruby/library/set/enumerable/to_set_spec.rb @@ -7,10 +7,12 @@ {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]] end - it "allows passing an alternate class for Set" do - sorted_set = [1, 2, 3].to_set(SortedSet) - sorted_set.should == SortedSet[1, 2, 3] - sorted_set.instance_of?(SortedSet).should == true + ruby_version_is ''...'3.0' do + it "allows passing an alternate class for Set" do + sorted_set = [1, 2, 3].to_set(SortedSet) + sorted_set.should == SortedSet[1, 2, 3] + sorted_set.instance_of?(SortedSet).should == true + end end it "passes down passed blocks" do diff --git a/ruby/spec/ruby/library/set/filter_spec.rb b/ruby/spec/ruby/library/set/filter_spec.rb index a4dfe70d5..779254ad6 100644 --- a/ruby/spec/ruby/library/set/filter_spec.rb +++ b/ruby/spec/ruby/library/set/filter_spec.rb @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/select' -ruby_version_is "2.6" do - describe "Set#filter!" do - it_behaves_like :set_select_bang, :filter! - end +describe "Set#filter!" do + it_behaves_like :set_select_bang, :filter! end diff --git a/ruby/spec/ruby/library/set/initialize_clone_spec.rb b/ruby/spec/ruby/library/set/initialize_clone_spec.rb new file mode 100644 index 000000000..62985987f --- /dev/null +++ b/ruby/spec/ruby/library/set/initialize_clone_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require 'set' + +describe "Set#initialize_clone" do + ruby_version_is "3.0" do + # See https://bugs.ruby-lang.org/issues/14266 + it "does not freeze the new Set when called from clone(freeze: false)" do + set1 = Set[1, 2] + set1.freeze + set2 = set1.clone(freeze: false) + set1.frozen?.should == true + set2.frozen?.should == false + set2.add 3 + set1.should == Set[1, 2] + set2.should == Set[1, 2, 3] + end + end +end diff --git a/ruby/spec/ruby/library/set/initialize_spec.rb b/ruby/spec/ruby/library/set/initialize_spec.rb index 887cae45f..76ebc0a20 100644 --- a/ruby/spec/ruby/library/set/initialize_spec.rb +++ b/ruby/spec/ruby/library/set/initialize_spec.rb @@ -14,6 +14,31 @@ s.should include(3) end + it "uses #each_entry on the provided Enumerable" do + enumerable = MockObject.new('mock-enumerable') + enumerable.should_receive(:each_entry).and_yield(1).and_yield(2).and_yield(3) + s = Set.new(enumerable) + s.size.should eql(3) + s.should include(1) + s.should include(2) + s.should include(3) + end + + it "uses #each on the provided Enumerable if it does not respond to #each_entry" do + enumerable = MockObject.new('mock-enumerable') + enumerable.should_receive(:each).and_yield(1).and_yield(2).and_yield(3) + s = Set.new(enumerable) + s.size.should eql(3) + s.should include(1) + s.should include(2) + s.should include(3) + end + + it "raises if the provided Enumerable does not respond to #each_entry or #each" do + enumerable = MockObject.new('mock-enumerable') + -> { Set.new(enumerable) }.should raise_error(ArgumentError, "value must be enumerable") + end + it "should initialize with empty array and set" do s = Set.new([]) s.size.should eql(0) diff --git a/ruby/spec/ruby/library/set/join_spec.rb b/ruby/spec/ruby/library/set/join_spec.rb new file mode 100644 index 000000000..7498a91d9 --- /dev/null +++ b/ruby/spec/ruby/library/set/join_spec.rb @@ -0,0 +1,31 @@ +require_relative '../../spec_helper' +require 'set' + +ruby_version_is "3.0" do + describe "Set#join" do + it "returns an empty string if the Set is empty" do + Set[].join.should == '' + end + + it "returns a new string formed by joining elements after conversion" do + set = Set[:a, :b, :c] + set.join.should == "abc" + end + + it "does not separate elements when the passed separator is nil" do + set = Set[:a, :b, :c] + set.join(nil).should == "abc" + end + + it "returns a string formed by concatenating each element separated by the separator" do + set = Set[:a, :b, :c] + set.join(' | ').should == "a | b | c" + end + + it "calls #to_a to convert the Set in to an Array" do + set = Set[:a, :b, :c] + set.should_receive(:to_a).and_return([:a, :b, :c]) + set.join.should == "abc" + end + end +end diff --git a/ruby/spec/ruby/library/set/pretty_print_spec.rb b/ruby/spec/ruby/library/set/pretty_print_spec.rb index f2392e696..ea9ead0df 100644 --- a/ruby/spec/ruby/library/set/pretty_print_spec.rb +++ b/ruby/spec/ruby/library/set/pretty_print_spec.rb @@ -1,17 +1,19 @@ require_relative '../../spec_helper' require 'set' -describe "Set#pretty_print" do - it "passes the 'pretty print' representation of self to the pretty print writer" do - pp = mock("PrettyPrint") - set = Set[1, 2, 3] +ruby_version_is ""..."3.1" do + describe "Set#pretty_print" do + it "passes the 'pretty print' representation of self to the pretty print writer" do + pp = mock("PrettyPrint") + set = Set[1, 2, 3] - pp.should_receive(:text).with("#") + pp.should_receive(:text).with("#") - pp.should_receive(:nest).with(1).and_yield - pp.should_receive(:seplist).with(set) + pp.should_receive(:nest).with(1).and_yield + pp.should_receive(:seplist).with(set) - set.pretty_print(pp) + set.pretty_print(pp) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/add_spec.rb b/ruby/spec/ruby/library/set/sortedset/add_spec.rb index 5f8bde02f..4f3bb252e 100644 --- a/ruby/spec/ruby/library/set/sortedset/add_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/add_spec.rb @@ -1,39 +1,42 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/add' -describe "SortedSet#add" do - it_behaves_like :sorted_set_add, :add +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/add' - it "takes only values which responds <=>" do - obj = mock('no_comparison_operator') - obj.stub!(:respond_to?).with(:<=>).and_return(false) - -> { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError) - end + describe "SortedSet#add" do + it_behaves_like :sorted_set_add, :add - it "raises on incompatible <=> comparison" do - # Use #to_a here as elements are sorted only when needed. - # Therefore the <=> incompatibility is only noticed on sorting. - -> { SortedSet['1', '2'].add(3).to_a }.should raise_error(ArgumentError) - end -end + it "takes only values which responds <=>" do + obj = mock('no_comparison_operator') + obj.stub!(:respond_to?).with(:<=>).and_return(false) + -> { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError) + end -describe "SortedSet#add?" do - before :each do - @set = SortedSet.new + it "raises on incompatible <=> comparison" do + # Use #to_a here as elements are sorted only when needed. + # Therefore the <=> incompatibility is only noticed on sorting. + -> { SortedSet['1', '2'].add(3).to_a }.should raise_error(ArgumentError) + end end - it "adds the passed Object to self" do - @set.add?("cat") - @set.should include("cat") - end + describe "SortedSet#add?" do + before :each do + @set = SortedSet.new + end - it "returns self when the Object has not yet been added to self" do - @set.add?("cat").should equal(@set) - end + it "adds the passed Object to self" do + @set.add?("cat") + @set.should include("cat") + end + + it "returns self when the Object has not yet been added to self" do + @set.add?("cat").should equal(@set) + end - it "returns nil when the Object has already been added to self" do - @set.add?("cat") - @set.add?("cat").should be_nil + it "returns nil when the Object has already been added to self" do + @set.add?("cat") + @set.add?("cat").should be_nil + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/append_spec.rb b/ruby/spec/ruby/library/set/sortedset/append_spec.rb index ebcceba96..d72d70b21 100644 --- a/ruby/spec/ruby/library/set/sortedset/append_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/append_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/add' -describe "SortedSet#<<" do - it_behaves_like :sorted_set_add, :<< +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/add' + + describe "SortedSet#<<" do + it_behaves_like :sorted_set_add, :<< + end end diff --git a/ruby/spec/ruby/library/set/sortedset/case_equality_spec.rb b/ruby/spec/ruby/library/set/sortedset/case_equality_spec.rb index 562791767..d7c296b62 100644 --- a/ruby/spec/ruby/library/set/sortedset/case_equality_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/case_equality_spec.rb @@ -1,8 +1,9 @@ require_relative '../../../spec_helper' -require_relative 'shared/include' -require 'set' -ruby_version_is "2.5" do +ruby_version_is ""..."3.0" do + require_relative 'shared/include' + require 'set' + describe "SortedSet#===" do it_behaves_like :sorted_set_include, :=== end diff --git a/ruby/spec/ruby/library/set/sortedset/classify_spec.rb b/ruby/spec/ruby/library/set/sortedset/classify_spec.rb index 62b26d5d2..4011e58b8 100644 --- a/ruby/spec/ruby/library/set/sortedset/classify_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/classify_spec.rb @@ -1,27 +1,30 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#classify" do - before :each do - @set = SortedSet["one", "two", "three", "four"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - res = [] - @set.classify { |x| res << x } - res.should == ["one", "two", "three", "four"].sort - end + describe "SortedSet#classify" do + before :each do + @set = SortedSet["one", "two", "three", "four"] + end - it "returns an Enumerator when passed no block" do - enum = @set.classify - enum.should be_an_instance_of(Enumerator) + it "yields each Object in self in sorted order" do + res = [] + @set.classify { |x| res << x } + res.should == ["one", "two", "three", "four"].sort + end - classified = enum.each { |x| x.length } - classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] } - end + it "returns an Enumerator when passed no block" do + enum = @set.classify + enum.should be_an_instance_of(Enumerator) + + classified = enum.each { |x| x.length } + classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] } + end - it "classifies the Objects in self based on the block's return value" do - classified = @set.classify { |x| x.length } - classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] } + it "classifies the Objects in self based on the block's return value" do + classified = @set.classify { |x| x.length } + classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] } + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/clear_spec.rb b/ruby/spec/ruby/library/set/sortedset/clear_spec.rb index 11b5db209..879aa824d 100644 --- a/ruby/spec/ruby/library/set/sortedset/clear_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/clear_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#clear" do - before :each do - @set = SortedSet["one", "two", "three", "four"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "removes all elements from self" do - @set.clear - @set.should be_empty - end + describe "SortedSet#clear" do + before :each do + @set = SortedSet["one", "two", "three", "four"] + end + + it "removes all elements from self" do + @set.clear + @set.should be_empty + end - it "returns self" do - @set.clear.should equal(@set) + it "returns self" do + @set.clear.should equal(@set) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/collect_spec.rb b/ruby/spec/ruby/library/set/sortedset/collect_spec.rb index 21ead4fe5..0674f0d13 100644 --- a/ruby/spec/ruby/library/set/sortedset/collect_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/collect_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/collect' -describe "SortedSet#collect!" do - it_behaves_like :sorted_set_collect_bang, :collect! +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/collect' + + describe "SortedSet#collect!" do + it_behaves_like :sorted_set_collect_bang, :collect! + end end diff --git a/ruby/spec/ruby/library/set/sortedset/constructor_spec.rb b/ruby/spec/ruby/library/set/sortedset/constructor_spec.rb index 953144dbd..31f30fd89 100644 --- a/ruby/spec/ruby/library/set/sortedset/constructor_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/constructor_spec.rb @@ -1,15 +1,18 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet[]" do - it "returns a new SortedSet populated with the passed Objects" do - set = SortedSet[1, 2, 3] +ruby_version_is ""..."3.0" do + require 'set' - set.instance_of?(SortedSet).should be_true - set.size.should eql(3) + describe "SortedSet[]" do + it "returns a new SortedSet populated with the passed Objects" do + set = SortedSet[1, 2, 3] - set.should include(1) - set.should include(2) - set.should include(3) + set.instance_of?(SortedSet).should be_true + set.size.should eql(3) + + set.should include(1) + set.should include(2) + set.should include(3) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/delete_if_spec.rb b/ruby/spec/ruby/library/set/sortedset/delete_if_spec.rb index 1ff689376..787639ae1 100644 --- a/ruby/spec/ruby/library/set/sortedset/delete_if_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/delete_if_spec.rb @@ -1,38 +1,41 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#delete_if" do - before :each do - @set = SortedSet["one", "two", "three"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - ret = [] - @set.delete_if { |x| ret << x } - ret.should == ["one", "two", "three"].sort - end + describe "SortedSet#delete_if" do + before :each do + @set = SortedSet["one", "two", "three"] + end - it "deletes every element from self for which the passed block returns true" do - @set.delete_if { |x| x.size == 3 } - @set.size.should eql(1) + it "yields each Object in self in sorted order" do + ret = [] + @set.delete_if { |x| ret << x } + ret.should == ["one", "two", "three"].sort + end - @set.should_not include("one") - @set.should_not include("two") - @set.should include("three") - end + it "deletes every element from self for which the passed block returns true" do + @set.delete_if { |x| x.size == 3 } + @set.size.should eql(1) - it "returns self" do - @set.delete_if { |x| x }.should equal(@set) - end + @set.should_not include("one") + @set.should_not include("two") + @set.should include("three") + end + + it "returns self" do + @set.delete_if { |x| x }.should equal(@set) + end - it "returns an Enumerator when passed no block" do - enum = @set.delete_if - enum.should be_an_instance_of(Enumerator) + it "returns an Enumerator when passed no block" do + enum = @set.delete_if + enum.should be_an_instance_of(Enumerator) - enum.each { |x| x.size == 3 } + enum.each { |x| x.size == 3 } - @set.should_not include("one") - @set.should_not include("two") - @set.should include("three") + @set.should_not include("one") + @set.should_not include("two") + @set.should include("three") + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/delete_spec.rb b/ruby/spec/ruby/library/set/sortedset/delete_spec.rb index 71583c7f1..0e2a6accf 100644 --- a/ruby/spec/ruby/library/set/sortedset/delete_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/delete_spec.rb @@ -1,37 +1,40 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#delete" do - before :each do - @set = SortedSet["a", "b", "c"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "deletes the passed Object from self" do - @set.delete("a") - @set.should_not include("a") - end + describe "SortedSet#delete" do + before :each do + @set = SortedSet["a", "b", "c"] + end - it "returns self" do - @set.delete("a").should equal(@set) - @set.delete("x").should equal(@set) - end -end + it "deletes the passed Object from self" do + @set.delete("a") + @set.should_not include("a") + end -describe "SortedSet#delete?" do - before :each do - @set = SortedSet["a", "b", "c"] + it "returns self" do + @set.delete("a").should equal(@set) + @set.delete("x").should equal(@set) + end end - it "deletes the passed Object from self" do - @set.delete?("a") - @set.should_not include("a") - end + describe "SortedSet#delete?" do + before :each do + @set = SortedSet["a", "b", "c"] + end - it "returns self when the passed Object is in self" do - @set.delete?("a").should equal(@set) - end + it "deletes the passed Object from self" do + @set.delete?("a") + @set.should_not include("a") + end + + it "returns self when the passed Object is in self" do + @set.delete?("a").should equal(@set) + end - it "returns nil when the passed Object is not in self" do - @set.delete?("x").should be_nil + it "returns nil when the passed Object is not in self" do + @set.delete?("x").should be_nil + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/difference_spec.rb b/ruby/spec/ruby/library/set/sortedset/difference_spec.rb index c3d679aff..fb064bdff 100644 --- a/ruby/spec/ruby/library/set/sortedset/difference_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/difference_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/difference' -describe "SortedSet#difference" do - it_behaves_like :sorted_set_difference, :difference +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/difference' + + describe "SortedSet#difference" do + it_behaves_like :sorted_set_difference, :difference + end end diff --git a/ruby/spec/ruby/library/set/sortedset/divide_spec.rb b/ruby/spec/ruby/library/set/sortedset/divide_spec.rb index 4b2135a8c..31ab6037e 100644 --- a/ruby/spec/ruby/library/set/sortedset/divide_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/divide_spec.rb @@ -1,34 +1,37 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#divide" do - it "divides self into a set of subsets based on the blocks return values" do - set = SortedSet["one", "two", "three", "four", "five"].divide { |x| x.length } - set.map { |x| x.to_a }.to_a.sort.should == [["five", "four"], ["one", "two"], ["three"]] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - ret = [] - SortedSet["one", "two", "three", "four", "five"].divide { |x| ret << x } - ret.should == ["one", "two", "three", "four", "five"].sort - end + describe "SortedSet#divide" do + it "divides self into a set of subsets based on the blocks return values" do + set = SortedSet["one", "two", "three", "four", "five"].divide { |x| x.length } + set.map { |x| x.to_a }.to_a.sort.should == [["five", "four"], ["one", "two"], ["three"]] + end - # BUG: Does not raise a LocalJumpError, but a NoMethodError - # - # it "raises a LocalJumpError when not passed a block" do - # lambda { SortedSet[1].divide }.should raise_error(LocalJumpError) - # end -end + it "yields each Object in self in sorted order" do + ret = [] + SortedSet["one", "two", "three", "four", "five"].divide { |x| ret << x } + ret.should == ["one", "two", "three", "four", "five"].sort + end -describe "SortedSet#divide when passed a block with an arity of 2" do - it "divides self into a set of subsets based on the blocks return values" do - set = SortedSet[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 } - set.map { |x| x.to_a }.to_a.sort.should == [[1], [3, 4], [6], [9, 10, 11]] + # BUG: Does not raise a LocalJumpError, but a NoMethodError + # + # it "raises a LocalJumpError when not passed a block" do + # lambda { SortedSet[1].divide }.should raise_error(LocalJumpError) + # end end - it "yields each two Objects to the block" do - ret = [] - SortedSet[1, 2].divide { |x, y| ret << [x, y] } - ret.should == [[1, 1], [1, 2], [2, 1], [2, 2]] + describe "SortedSet#divide when passed a block with an arity of 2" do + it "divides self into a set of subsets based on the blocks return values" do + set = SortedSet[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 } + set.map { |x| x.to_a }.to_a.sort.should == [[1], [3, 4], [6], [9, 10, 11]] + end + + it "yields each two Objects to the block" do + ret = [] + SortedSet[1, 2].divide { |x, y| ret << [x, y] } + ret.should == [[1, 1], [1, 2], [2, 1], [2, 2]] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/each_spec.rb b/ruby/spec/ruby/library/set/sortedset/each_spec.rb index bcf0d74d1..79d8aee22 100644 --- a/ruby/spec/ruby/library/set/sortedset/each_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/each_spec.rb @@ -1,26 +1,29 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#each" do - before :each do - @set = SortedSet[1, 2, 3] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - ret = [] - SortedSet["one", "two", "three"].each { |x| ret << x } - ret.should == ["one", "two", "three"].sort - end + describe "SortedSet#each" do + before :each do + @set = SortedSet[1, 2, 3] + end - it "returns self" do - @set.each { |x| x }.should equal(@set) - end + it "yields each Object in self in sorted order" do + ret = [] + SortedSet["one", "two", "three"].each { |x| ret << x } + ret.should == ["one", "two", "three"].sort + end + + it "returns self" do + @set.each { |x| x }.should equal(@set) + end - it "returns an Enumerator when not passed a block" do - enum = @set.each + it "returns an Enumerator when not passed a block" do + enum = @set.each - ret = [] - enum.each { |x| ret << x } - ret.sort.should == [1, 2, 3] + ret = [] + enum.each { |x| ret << x } + ret.sort.should == [1, 2, 3] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/empty_spec.rb b/ruby/spec/ruby/library/set/sortedset/empty_spec.rb index deb3b567f..2e52c3e81 100644 --- a/ruby/spec/ruby/library/set/sortedset/empty_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/empty_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#empty?" do - it "returns true if self is empty" do - SortedSet[].empty?.should be_true - SortedSet[1].empty?.should be_false - SortedSet[1,2,3].empty?.should be_false +ruby_version_is ""..."3.0" do + require 'set' + + describe "SortedSet#empty?" do + it "returns true if self is empty" do + SortedSet[].empty?.should be_true + SortedSet[1].empty?.should be_false + SortedSet[1,2,3].empty?.should be_false + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/eql_spec.rb b/ruby/spec/ruby/library/set/sortedset/eql_spec.rb index b22858a36..050464994 100644 --- a/ruby/spec/ruby/library/set/sortedset/eql_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/eql_spec.rb @@ -1,16 +1,19 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#eql?" do - it "returns true when the passed argument is a SortedSet and contains the same elements" do - SortedSet[].should eql(SortedSet[]) - SortedSet[1, 2, 3].should eql(SortedSet[1, 2, 3]) - SortedSet[1, 2, 3].should eql(SortedSet[3, 2, 1]) +ruby_version_is ""..."3.0" do + require 'set' -# SortedSet["a", :b, ?c].should eql(SortedSet[?c, :b, "a"]) + describe "SortedSet#eql?" do + it "returns true when the passed argument is a SortedSet and contains the same elements" do + SortedSet[].should eql(SortedSet[]) + SortedSet[1, 2, 3].should eql(SortedSet[1, 2, 3]) + SortedSet[1, 2, 3].should eql(SortedSet[3, 2, 1]) - SortedSet[1, 2, 3].should_not eql(SortedSet[1.0, 2, 3]) - SortedSet[1, 2, 3].should_not eql(SortedSet[2, 3]) - SortedSet[1, 2, 3].should_not eql(SortedSet[]) + # SortedSet["a", :b, ?c].should eql(SortedSet[?c, :b, "a"]) + + SortedSet[1, 2, 3].should_not eql(SortedSet[1.0, 2, 3]) + SortedSet[1, 2, 3].should_not eql(SortedSet[2, 3]) + SortedSet[1, 2, 3].should_not eql(SortedSet[]) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/equal_value_spec.rb b/ruby/spec/ruby/library/set/sortedset/equal_value_spec.rb index cb1b7c944..30422f5b9 100644 --- a/ruby/spec/ruby/library/set/sortedset/equal_value_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/equal_value_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#==" do - it "returns true when the passed Object is a SortedSet and self and the Object contain the same elements" do - SortedSet[].should == SortedSet[] - SortedSet[1, 2, 3].should == SortedSet[1, 2, 3] - SortedSet["1", "2", "3"].should == SortedSet["1", "2", "3"] +ruby_version_is ""..."3.0" do + require 'set' - SortedSet[1, 2, 3].should_not == SortedSet[1.0, 2, 3] - SortedSet[1, 2, 3].should_not == [1, 2, 3] + describe "SortedSet#==" do + it "returns true when the passed Object is a SortedSet and self and the Object contain the same elements" do + SortedSet[].should == SortedSet[] + SortedSet[1, 2, 3].should == SortedSet[1, 2, 3] + SortedSet["1", "2", "3"].should == SortedSet["1", "2", "3"] + + SortedSet[1, 2, 3].should_not == SortedSet[1.0, 2, 3] + SortedSet[1, 2, 3].should_not == [1, 2, 3] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/exclusion_spec.rb b/ruby/spec/ruby/library/set/sortedset/exclusion_spec.rb index d0f1ab95c..1967dfbfa 100644 --- a/ruby/spec/ruby/library/set/sortedset/exclusion_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/exclusion_spec.rb @@ -1,18 +1,21 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#^" do - before :each do - @set = SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns a new SortedSet containing elements that are not in both self and the passed Enumerable" do - (@set ^ SortedSet[3, 4, 5]).should == SortedSet[1, 2, 5] - (@set ^ [3, 4, 5]).should == SortedSet[1, 2, 5] - end + describe "SortedSet#^" do + before :each do + @set = SortedSet[1, 2, 3, 4] + end + + it "returns a new SortedSet containing elements that are not in both self and the passed Enumerable" do + (@set ^ SortedSet[3, 4, 5]).should == SortedSet[1, 2, 5] + (@set ^ [3, 4, 5]).should == SortedSet[1, 2, 5] + end - it "raises an ArgumentError when passed a non-Enumerable" do - -> { @set ^ 3 }.should raise_error(ArgumentError) - -> { @set ^ Object.new }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-Enumerable" do + -> { @set ^ 3 }.should raise_error(ArgumentError) + -> { @set ^ Object.new }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/filter_spec.rb b/ruby/spec/ruby/library/set/sortedset/filter_spec.rb index cfaa8b272..3b9dcb63c 100644 --- a/ruby/spec/ruby/library/set/sortedset/filter_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/filter_spec.rb @@ -1,8 +1,9 @@ require_relative '../../../spec_helper' -require_relative 'shared/select' -require 'set' -ruby_version_is "2.6" do +ruby_version_is ""..."3.0" do + require_relative 'shared/select' + require 'set' + describe "SortedSet#filter!" do it_behaves_like :sorted_set_select_bang, :filter! end diff --git a/ruby/spec/ruby/library/set/sortedset/flatten_merge_spec.rb b/ruby/spec/ruby/library/set/sortedset/flatten_merge_spec.rb index 9a8ed13f0..0d67cb331 100644 --- a/ruby/spec/ruby/library/set/sortedset/flatten_merge_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/flatten_merge_spec.rb @@ -1,8 +1,11 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#flatten_merge" do - it "is protected" do - SortedSet.should have_protected_instance_method("flatten_merge") +ruby_version_is ""..."3.0" do + require 'set' + + describe "SortedSet#flatten_merge" do + it "is protected" do + SortedSet.should have_protected_instance_method("flatten_merge") + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/flatten_spec.rb b/ruby/spec/ruby/library/set/sortedset/flatten_spec.rb index ca4e4637e..e83ad1044 100644 --- a/ruby/spec/ruby/library/set/sortedset/flatten_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/flatten_spec.rb @@ -1,44 +1,47 @@ require_relative '../../../spec_helper' -require 'set' -# Note: Flatten make little sens on sorted sets, because SortedSets are not (by default) -# comparable. For a SortedSet to be both valid and nested, we need to define a comparison operator: -module SortedSet_FlattenSpecs - class ComparableSortedSet < SortedSet - def <=>(other) - return puts "#{other} vs #{self}" unless other.is_a?(ComparableSortedSet) - to_a <=> other.to_a +ruby_version_is ""..."3.0" do + require 'set' + + # Note: Flatten make little sens on sorted sets, because SortedSets are not (by default) + # comparable. For a SortedSet to be both valid and nested, we need to define a comparison operator: + module SortedSet_FlattenSpecs + class ComparableSortedSet < SortedSet + def <=>(other) + return puts "#{other} vs #{self}" unless other.is_a?(ComparableSortedSet) + to_a <=> other.to_a + end end end -end -describe "SortedSet#flatten" do - it "returns a copy of self with each included SortedSet flattened" do - klass = SortedSet_FlattenSpecs::ComparableSortedSet - set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]] - flattened_set = set.flatten + describe "SortedSet#flatten" do + it "returns a copy of self with each included SortedSet flattened" do + klass = SortedSet_FlattenSpecs::ComparableSortedSet + set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]] + flattened_set = set.flatten - flattened_set.should_not equal(set) - flattened_set.should == klass[1, 2, 3, 4, 5, 6, 7, 8] + flattened_set.should_not equal(set) + flattened_set.should == klass[1, 2, 3, 4, 5, 6, 7, 8] + end end -end -describe "SortedSet#flatten!" do - it "flattens self" do - klass = SortedSet_FlattenSpecs::ComparableSortedSet - set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]] - set.flatten! - set.should == klass[1, 2, 3, 4, 5, 6, 7, 8] - end + describe "SortedSet#flatten!" do + it "flattens self" do + klass = SortedSet_FlattenSpecs::ComparableSortedSet + set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]] + set.flatten! + set.should == klass[1, 2, 3, 4, 5, 6, 7, 8] + end - it "returns self when self was modified" do - klass = SortedSet_FlattenSpecs::ComparableSortedSet - set = klass[klass[1,2], klass[3,4]] - set.flatten!.should equal(set) - end + it "returns self when self was modified" do + klass = SortedSet_FlattenSpecs::ComparableSortedSet + set = klass[klass[1,2], klass[3,4]] + set.flatten!.should equal(set) + end - it "returns nil when self was not modified" do - set = SortedSet[1, 2, 3, 4] - set.flatten!.should be_nil + it "returns nil when self was not modified" do + set = SortedSet[1, 2, 3, 4] + set.flatten!.should be_nil + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/hash_spec.rb b/ruby/spec/ruby/library/set/sortedset/hash_spec.rb index 7833c68a1..40676de7f 100644 --- a/ruby/spec/ruby/library/set/sortedset/hash_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/hash_spec.rb @@ -1,13 +1,16 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#hash" do - it "is static" do - SortedSet[].hash.should == SortedSet[].hash - SortedSet[1, 2, 3].hash.should == SortedSet[1, 2, 3].hash - SortedSet["a", "b", "c"].hash.should == SortedSet["c", "b", "a"].hash +ruby_version_is ""..."3.0" do + require 'set' - SortedSet[].hash.should_not == SortedSet[1, 2, 3].hash - SortedSet[1, 2, 3].hash.should_not == SortedSet["a", "b", "c"].hash + describe "SortedSet#hash" do + it "is static" do + SortedSet[].hash.should == SortedSet[].hash + SortedSet[1, 2, 3].hash.should == SortedSet[1, 2, 3].hash + SortedSet["a", "b", "c"].hash.should == SortedSet["c", "b", "a"].hash + + SortedSet[].hash.should_not == SortedSet[1, 2, 3].hash + SortedSet[1, 2, 3].hash.should_not == SortedSet["a", "b", "c"].hash + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/include_spec.rb b/ruby/spec/ruby/library/set/sortedset/include_spec.rb index 030a9e146..ec2ad987d 100644 --- a/ruby/spec/ruby/library/set/sortedset/include_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/include_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/include' -require 'set' -describe "SortedSet#include?" do - it_behaves_like :sorted_set_include, :include? +ruby_version_is ""..."3.0" do + require_relative 'shared/include' + require 'set' + + describe "SortedSet#include?" do + it_behaves_like :sorted_set_include, :include? + end end diff --git a/ruby/spec/ruby/library/set/sortedset/initialize_spec.rb b/ruby/spec/ruby/library/set/sortedset/initialize_spec.rb index 1238f4efc..4d1707b72 100644 --- a/ruby/spec/ruby/library/set/sortedset/initialize_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/initialize_spec.rb @@ -1,30 +1,33 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#initialize" do - it "is private" do - SortedSet.should have_private_instance_method("initialize") - end +ruby_version_is ""..."3.0" do + require 'set' - it "adds all elements of the passed Enumerable to self" do - s = SortedSet.new([1, 2, 3]) - s.size.should eql(3) - s.should include(1) - s.should include(2) - s.should include(3) - end + describe "SortedSet#initialize" do + it "is private" do + SortedSet.should have_private_instance_method("initialize") + end - it "preprocesses all elements by a passed block before adding to self" do - s = SortedSet.new([1, 2, 3]) { |x| x * x } - s.size.should eql(3) - s.should include(1) - s.should include(4) - s.should include(9) - end + it "adds all elements of the passed Enumerable to self" do + s = SortedSet.new([1, 2, 3]) + s.size.should eql(3) + s.should include(1) + s.should include(2) + s.should include(3) + end + + it "preprocesses all elements by a passed block before adding to self" do + s = SortedSet.new([1, 2, 3]) { |x| x * x } + s.size.should eql(3) + s.should include(1) + s.should include(4) + s.should include(9) + end - it "raises on incompatible <=> comparison" do - # Use #to_a here as elements are sorted only when needed. - # Therefore the <=> incompatibility is only noticed on sorting. - -> { SortedSet.new(['00', nil]).to_a }.should raise_error(ArgumentError) + it "raises on incompatible <=> comparison" do + # Use #to_a here as elements are sorted only when needed. + # Therefore the <=> incompatibility is only noticed on sorting. + -> { SortedSet.new(['00', nil]).to_a }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/inspect_spec.rb b/ruby/spec/ruby/library/set/sortedset/inspect_spec.rb index 7103bee3f..1c4dd9e6e 100644 --- a/ruby/spec/ruby/library/set/sortedset/inspect_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/inspect_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#inspect" do - it "returns a String representation of self" do - SortedSet[].inspect.should be_kind_of(String) - SortedSet[1, 2, 3].inspect.should be_kind_of(String) - SortedSet["1", "2", "3"].inspect.should be_kind_of(String) +ruby_version_is ""..."3.0" do + require 'set' + + describe "SortedSet#inspect" do + it "returns a String representation of self" do + SortedSet[].inspect.should be_kind_of(String) + SortedSet[1, 2, 3].inspect.should be_kind_of(String) + SortedSet["1", "2", "3"].inspect.should be_kind_of(String) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/intersection_spec.rb b/ruby/spec/ruby/library/set/sortedset/intersection_spec.rb index 6ff9c80ce..6daa271b7 100644 --- a/ruby/spec/ruby/library/set/sortedset/intersection_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/intersection_spec.rb @@ -1,11 +1,14 @@ require_relative '../../../spec_helper' -require_relative 'shared/intersection' -require 'set' -describe "SortedSet#intersection" do - it_behaves_like :sorted_set_intersection, :intersection -end +ruby_version_is ""..."3.0" do + require_relative 'shared/intersection' + require 'set' + + describe "SortedSet#intersection" do + it_behaves_like :sorted_set_intersection, :intersection + end -describe "SortedSet#&" do - it_behaves_like :sorted_set_intersection, :& + describe "SortedSet#&" do + it_behaves_like :sorted_set_intersection, :& + end end diff --git a/ruby/spec/ruby/library/set/sortedset/keep_if_spec.rb b/ruby/spec/ruby/library/set/sortedset/keep_if_spec.rb index 2235eb376..3e5f3bbc4 100644 --- a/ruby/spec/ruby/library/set/sortedset/keep_if_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/keep_if_spec.rb @@ -1,31 +1,34 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#keep_if" do - before :each do - @set = SortedSet["one", "two", "three"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - ret = [] - @set.keep_if { |x| ret << x } - ret.should == ["one", "two", "three"].sort - end + describe "SortedSet#keep_if" do + before :each do + @set = SortedSet["one", "two", "three"] + end - it "keeps every element from self for which the passed block returns true" do - @set.keep_if { |x| x.size != 3 } - @set.to_a.should == ["three"] - end + it "yields each Object in self in sorted order" do + ret = [] + @set.keep_if { |x| ret << x } + ret.should == ["one", "two", "three"].sort + end - it "returns self" do - @set.keep_if {}.should equal(@set) - end + it "keeps every element from self for which the passed block returns true" do + @set.keep_if { |x| x.size != 3 } + @set.to_a.should == ["three"] + end + + it "returns self" do + @set.keep_if {}.should equal(@set) + end - it "returns an Enumerator when passed no block" do - enum = @set.keep_if - enum.should be_an_instance_of(Enumerator) + it "returns an Enumerator when passed no block" do + enum = @set.keep_if + enum.should be_an_instance_of(Enumerator) - enum.each { |x| x.size != 3 } - @set.to_a.should == ["three"] + enum.each { |x| x.size != 3 } + @set.to_a.should == ["three"] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/length_spec.rb b/ruby/spec/ruby/library/set/sortedset/length_spec.rb index 5f138dd6f..de6791f6b 100644 --- a/ruby/spec/ruby/library/set/sortedset/length_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/length_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/length' -require 'set' -describe "SortedSet#length" do - it_behaves_like :sorted_set_length, :length +ruby_version_is ""..."3.0" do + require_relative 'shared/length' + require 'set' + + describe "SortedSet#length" do + it_behaves_like :sorted_set_length, :length + end end diff --git a/ruby/spec/ruby/library/set/sortedset/map_spec.rb b/ruby/spec/ruby/library/set/sortedset/map_spec.rb index 1d7b5954e..4971b9529 100644 --- a/ruby/spec/ruby/library/set/sortedset/map_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/map_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/collect' -describe "SortedSet#map!" do - it_behaves_like :sorted_set_collect_bang, :map! +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/collect' + + describe "SortedSet#map!" do + it_behaves_like :sorted_set_collect_bang, :map! + end end diff --git a/ruby/spec/ruby/library/set/sortedset/member_spec.rb b/ruby/spec/ruby/library/set/sortedset/member_spec.rb index d6005557a..142b09b65 100644 --- a/ruby/spec/ruby/library/set/sortedset/member_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/member_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/include' -require 'set' -describe "SortedSet#member?" do - it_behaves_like :sorted_set_include, :member? +ruby_version_is ""..."3.0" do + require_relative 'shared/include' + require 'set' + + describe "SortedSet#member?" do + it_behaves_like :sorted_set_include, :member? + end end diff --git a/ruby/spec/ruby/library/set/sortedset/merge_spec.rb b/ruby/spec/ruby/library/set/sortedset/merge_spec.rb index 31570ad4d..c4cbc6d2b 100644 --- a/ruby/spec/ruby/library/set/sortedset/merge_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/merge_spec.rb @@ -1,19 +1,22 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#merge" do - it "adds the elements of the passed Enumerable to self" do - SortedSet["a", "b"].merge(SortedSet["b", "c", "d"]).should == SortedSet["a", "b", "c", "d"] - SortedSet[1, 2].merge([3, 4]).should == SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns self" do - set = SortedSet[1, 2] - set.merge([3, 4]).should equal(set) - end + describe "SortedSet#merge" do + it "adds the elements of the passed Enumerable to self" do + SortedSet["a", "b"].merge(SortedSet["b", "c", "d"]).should == SortedSet["a", "b", "c", "d"] + SortedSet[1, 2].merge([3, 4]).should == SortedSet[1, 2, 3, 4] + end + + it "returns self" do + set = SortedSet[1, 2] + set.merge([3, 4]).should equal(set) + end - it "raises an ArgumentError when passed a non-Enumerable" do - -> { SortedSet[1, 2].merge(1) }.should raise_error(ArgumentError) - -> { SortedSet[1, 2].merge(Object.new) }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-Enumerable" do + -> { SortedSet[1, 2].merge(1) }.should raise_error(ArgumentError) + -> { SortedSet[1, 2].merge(Object.new) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/minus_spec.rb b/ruby/spec/ruby/library/set/sortedset/minus_spec.rb index ffb8ee85d..d6abc5e20 100644 --- a/ruby/spec/ruby/library/set/sortedset/minus_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/minus_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require 'set' -require_relative 'shared/difference' -describe "SortedSet#-" do - it_behaves_like :sorted_set_difference, :- +ruby_version_is ""..."3.0" do + require 'set' + require_relative 'shared/difference' + + describe "SortedSet#-" do + it_behaves_like :sorted_set_difference, :- + end end diff --git a/ruby/spec/ruby/library/set/sortedset/plus_spec.rb b/ruby/spec/ruby/library/set/sortedset/plus_spec.rb index 355c775d7..13fc873ad 100644 --- a/ruby/spec/ruby/library/set/sortedset/plus_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/plus_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/union' -require 'set' -describe "SortedSet#+" do - it_behaves_like :sorted_set_union, :+ +ruby_version_is ""..."3.0" do + require_relative 'shared/union' + require 'set' + + describe "SortedSet#+" do + it_behaves_like :sorted_set_union, :+ + end end diff --git a/ruby/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb b/ruby/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb index fe15f1bf7..e97f50940 100644 --- a/ruby/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb @@ -1,10 +1,13 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#pretty_print_cycle" do - it "passes the 'pretty print' representation of a self-referencing SortedSet to the pretty print writer" do - pp = mock("PrettyPrint") - pp.should_receive(:text).with("#") - SortedSet[1, 2, 3].pretty_print_cycle(pp) +ruby_version_is ""..."3.0" do + require 'set' + + describe "SortedSet#pretty_print_cycle" do + it "passes the 'pretty print' representation of a self-referencing SortedSet to the pretty print writer" do + pp = mock("PrettyPrint") + pp.should_receive(:text).with("#") + SortedSet[1, 2, 3].pretty_print_cycle(pp) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/pretty_print_spec.rb b/ruby/spec/ruby/library/set/sortedset/pretty_print_spec.rb index 601ff4d18..a8088bf79 100644 --- a/ruby/spec/ruby/library/set/sortedset/pretty_print_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/pretty_print_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#pretty_print" do - it "passes the 'pretty print' representation of self to the pretty print writer" do - pp = mock("PrettyPrint") - set = SortedSet[1, 2, 3] +ruby_version_is ""..."3.0" do + require 'set' - pp.should_receive(:text).with("#") + describe "SortedSet#pretty_print" do + it "passes the 'pretty print' representation of self to the pretty print writer" do + pp = mock("PrettyPrint") + set = SortedSet[1, 2, 3] - pp.should_receive(:nest).with(1).and_yield - pp.should_receive(:seplist).with(set) + pp.should_receive(:text).with("#") - set.pretty_print(pp) + pp.should_receive(:nest).with(1).and_yield + pp.should_receive(:seplist).with(set) + + set.pretty_print(pp) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/proper_subset_spec.rb b/ruby/spec/ruby/library/set/sortedset/proper_subset_spec.rb index 818173a7f..34fb89d13 100644 --- a/ruby/spec/ruby/library/set/sortedset/proper_subset_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/proper_subset_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#proper_subset?" do - before :each do - @set = SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns true if passed a SortedSet that self is a proper subset of" do - SortedSet[].proper_subset?(@set).should be_true - SortedSet[].proper_subset?(SortedSet[1, 2, 3]).should be_true - SortedSet[].proper_subset?(SortedSet["a", "b", "c"]).should be_true + describe "SortedSet#proper_subset?" do + before :each do + @set = SortedSet[1, 2, 3, 4] + end - SortedSet[1, 2, 3].proper_subset?(@set).should be_true - SortedSet[1, 3].proper_subset?(@set).should be_true - SortedSet[1, 2].proper_subset?(@set).should be_true - SortedSet[1].proper_subset?(@set).should be_true + it "returns true if passed a SortedSet that self is a proper subset of" do + SortedSet[].proper_subset?(@set).should be_true + SortedSet[].proper_subset?(SortedSet[1, 2, 3]).should be_true + SortedSet[].proper_subset?(SortedSet["a", "b", "c"]).should be_true - SortedSet[5].proper_subset?(@set).should be_false - SortedSet[1, 5].proper_subset?(@set).should be_false - SortedSet["test"].proper_subset?(@set).should be_false + SortedSet[1, 2, 3].proper_subset?(@set).should be_true + SortedSet[1, 3].proper_subset?(@set).should be_true + SortedSet[1, 2].proper_subset?(@set).should be_true + SortedSet[1].proper_subset?(@set).should be_true - @set.proper_subset?(@set).should be_false - SortedSet[].proper_subset?(SortedSet[]).should be_false - end + SortedSet[5].proper_subset?(@set).should be_false + SortedSet[1, 5].proper_subset?(@set).should be_false + SortedSet["test"].proper_subset?(@set).should be_false + + @set.proper_subset?(@set).should be_false + SortedSet[].proper_subset?(SortedSet[]).should be_false + end - it "raises an ArgumentError when passed a non-SortedSet" do - -> { SortedSet[].proper_subset?([]) }.should raise_error(ArgumentError) - -> { SortedSet[].proper_subset?(1) }.should raise_error(ArgumentError) - -> { SortedSet[].proper_subset?("test") }.should raise_error(ArgumentError) - -> { SortedSet[].proper_subset?(Object.new) }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-SortedSet" do + -> { SortedSet[].proper_subset?([]) }.should raise_error(ArgumentError) + -> { SortedSet[].proper_subset?(1) }.should raise_error(ArgumentError) + -> { SortedSet[].proper_subset?("test") }.should raise_error(ArgumentError) + -> { SortedSet[].proper_subset?(Object.new) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/proper_superset_spec.rb b/ruby/spec/ruby/library/set/sortedset/proper_superset_spec.rb index 2699290f0..8b92444f7 100644 --- a/ruby/spec/ruby/library/set/sortedset/proper_superset_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/proper_superset_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#proper_superset?" do - before :each do - @set = SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns true if passed a SortedSet that self is a proper superset of" do - @set.proper_superset?(SortedSet[]).should be_true - SortedSet[1, 2, 3].proper_superset?(SortedSet[]).should be_true - SortedSet["a", "b", "c"].proper_superset?(SortedSet[]).should be_true + describe "SortedSet#proper_superset?" do + before :each do + @set = SortedSet[1, 2, 3, 4] + end - @set.proper_superset?(SortedSet[1, 2, 3]).should be_true - @set.proper_superset?(SortedSet[1, 3]).should be_true - @set.proper_superset?(SortedSet[1, 2]).should be_true - @set.proper_superset?(SortedSet[1]).should be_true + it "returns true if passed a SortedSet that self is a proper superset of" do + @set.proper_superset?(SortedSet[]).should be_true + SortedSet[1, 2, 3].proper_superset?(SortedSet[]).should be_true + SortedSet["a", "b", "c"].proper_superset?(SortedSet[]).should be_true - @set.proper_superset?(SortedSet[5]).should be_false - @set.proper_superset?(SortedSet[1, 5]).should be_false - @set.proper_superset?(SortedSet["test"]).should be_false + @set.proper_superset?(SortedSet[1, 2, 3]).should be_true + @set.proper_superset?(SortedSet[1, 3]).should be_true + @set.proper_superset?(SortedSet[1, 2]).should be_true + @set.proper_superset?(SortedSet[1]).should be_true - @set.proper_superset?(@set).should be_false - SortedSet[].proper_superset?(SortedSet[]).should be_false - end + @set.proper_superset?(SortedSet[5]).should be_false + @set.proper_superset?(SortedSet[1, 5]).should be_false + @set.proper_superset?(SortedSet["test"]).should be_false + + @set.proper_superset?(@set).should be_false + SortedSet[].proper_superset?(SortedSet[]).should be_false + end - it "raises an ArgumentError when passed a non-SortedSet" do - -> { SortedSet[].proper_superset?([]) }.should raise_error(ArgumentError) - -> { SortedSet[].proper_superset?(1) }.should raise_error(ArgumentError) - -> { SortedSet[].proper_superset?("test") }.should raise_error(ArgumentError) - -> { SortedSet[].proper_superset?(Object.new) }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-SortedSet" do + -> { SortedSet[].proper_superset?([]) }.should raise_error(ArgumentError) + -> { SortedSet[].proper_superset?(1) }.should raise_error(ArgumentError) + -> { SortedSet[].proper_superset?("test") }.should raise_error(ArgumentError) + -> { SortedSet[].proper_superset?(Object.new) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/reject_spec.rb b/ruby/spec/ruby/library/set/sortedset/reject_spec.rb index da2a76e7a..396b864cc 100644 --- a/ruby/spec/ruby/library/set/sortedset/reject_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/reject_spec.rb @@ -1,42 +1,45 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#reject!" do - before :each do - @set = SortedSet["one", "two", "three"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "yields each Object in self in sorted order" do - res = [] - @set.reject! { |x| res << x } - res.should == ["one", "two", "three"].sort - end + describe "SortedSet#reject!" do + before :each do + @set = SortedSet["one", "two", "three"] + end - it "deletes every element from self for which the passed block returns true" do - @set.reject! { |x| x.size == 3 } - @set.size.should eql(1) + it "yields each Object in self in sorted order" do + res = [] + @set.reject! { |x| res << x } + res.should == ["one", "two", "three"].sort + end - @set.should_not include("one") - @set.should_not include("two") - @set.should include("three") - end + it "deletes every element from self for which the passed block returns true" do + @set.reject! { |x| x.size == 3 } + @set.size.should eql(1) - it "returns self when self was modified" do - @set.reject! { |x| true }.should equal(@set) - end + @set.should_not include("one") + @set.should_not include("two") + @set.should include("three") + end - it "returns nil when self was not modified" do - @set.reject! { |x| false }.should be_nil - end + it "returns self when self was modified" do + @set.reject! { |x| true }.should equal(@set) + end + + it "returns nil when self was not modified" do + @set.reject! { |x| false }.should be_nil + end - it "returns an Enumerator when passed no block" do - enum = @set.reject! - enum.should be_an_instance_of(Enumerator) + it "returns an Enumerator when passed no block" do + enum = @set.reject! + enum.should be_an_instance_of(Enumerator) - enum.each { |x| x.size == 3 } + enum.each { |x| x.size == 3 } - @set.should_not include("one") - @set.should_not include("two") - @set.should include("three") + @set.should_not include("one") + @set.should_not include("two") + @set.should include("three") + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/replace_spec.rb b/ruby/spec/ruby/library/set/sortedset/replace_spec.rb index 2a7fa73ef..2900221c0 100644 --- a/ruby/spec/ruby/library/set/sortedset/replace_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/replace_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#replace" do - before :each do - @set = SortedSet["a", "b", "c"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "replaces the contents with other and returns self" do - @set.replace(SortedSet[1, 2, 3]).should == @set - @set.should == SortedSet[1, 2, 3] - end + describe "SortedSet#replace" do + before :each do + @set = SortedSet["a", "b", "c"] + end + + it "replaces the contents with other and returns self" do + @set.replace(SortedSet[1, 2, 3]).should == @set + @set.should == SortedSet[1, 2, 3] + end - it "accepts any enumerable as other" do - @set.replace([1, 2, 3]).should == SortedSet[1, 2, 3] + it "accepts any enumerable as other" do + @set.replace([1, 2, 3]).should == SortedSet[1, 2, 3] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/select_spec.rb b/ruby/spec/ruby/library/set/sortedset/select_spec.rb index 68326cd02..fc4c15ee4 100644 --- a/ruby/spec/ruby/library/set/sortedset/select_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/select_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/select' -require 'set' -describe "SortedSet#select!" do - it_behaves_like :sorted_set_select_bang, :select! +ruby_version_is ""..."3.0" do + require_relative 'shared/select' + require 'set' + + describe "SortedSet#select!" do + it_behaves_like :sorted_set_select_bang, :select! + end end diff --git a/ruby/spec/ruby/library/set/sortedset/size_spec.rb b/ruby/spec/ruby/library/set/sortedset/size_spec.rb index 13e5085b0..d908b33b5 100644 --- a/ruby/spec/ruby/library/set/sortedset/size_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/size_spec.rb @@ -1,7 +1,10 @@ require_relative '../../../spec_helper' -require_relative 'shared/length' -require 'set' -describe "SortedSet#size" do - it_behaves_like :sorted_set_length, :size +ruby_version_is ""..."3.0" do + require_relative 'shared/length' + require 'set' + + describe "SortedSet#size" do + it_behaves_like :sorted_set_length, :size + end end diff --git a/ruby/spec/ruby/library/set/sortedset/sortedset_spec.rb b/ruby/spec/ruby/library/set/sortedset/sortedset_spec.rb new file mode 100644 index 000000000..3ead5495f --- /dev/null +++ b/ruby/spec/ruby/library/set/sortedset/sortedset_spec.rb @@ -0,0 +1,22 @@ +require_relative '../../../spec_helper' +require 'set' + +ruby_version_is "3.0" do + describe "SortedSet" do + it "raises error including message that it has been extracted from the set stdlib" do + -> { + SortedSet + }.should raise_error(RuntimeError) { |e| + e.message.should.include?("The `SortedSet` class has been extracted from the `set` library") + } + end + end +end + +ruby_version_is ""..."3.0" do + describe "SortedSet" do + it "is part of the set stdlib" do + SortedSet.superclass.should == Set + end + end +end diff --git a/ruby/spec/ruby/library/set/sortedset/subset_spec.rb b/ruby/spec/ruby/library/set/sortedset/subset_spec.rb index 7768692df..272e3f985 100644 --- a/ruby/spec/ruby/library/set/sortedset/subset_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/subset_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#subset?" do - before :each do - @set = SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns true if passed a SortedSet that is equal to self or self is a subset of" do - @set.subset?(@set).should be_true - SortedSet[].subset?(SortedSet[]).should be_true + describe "SortedSet#subset?" do + before :each do + @set = SortedSet[1, 2, 3, 4] + end - SortedSet[].subset?(@set).should be_true - SortedSet[].subset?(SortedSet[1, 2, 3]).should be_true - SortedSet[].subset?(SortedSet["a", "b", "c"]).should be_true + it "returns true if passed a SortedSet that is equal to self or self is a subset of" do + @set.subset?(@set).should be_true + SortedSet[].subset?(SortedSet[]).should be_true - SortedSet[1, 2, 3].subset?(@set).should be_true - SortedSet[1, 3].subset?(@set).should be_true - SortedSet[1, 2].subset?(@set).should be_true - SortedSet[1].subset?(@set).should be_true + SortedSet[].subset?(@set).should be_true + SortedSet[].subset?(SortedSet[1, 2, 3]).should be_true + SortedSet[].subset?(SortedSet["a", "b", "c"]).should be_true - SortedSet[5].subset?(@set).should be_false - SortedSet[1, 5].subset?(@set).should be_false - SortedSet["test"].subset?(@set).should be_false - end + SortedSet[1, 2, 3].subset?(@set).should be_true + SortedSet[1, 3].subset?(@set).should be_true + SortedSet[1, 2].subset?(@set).should be_true + SortedSet[1].subset?(@set).should be_true + + SortedSet[5].subset?(@set).should be_false + SortedSet[1, 5].subset?(@set).should be_false + SortedSet["test"].subset?(@set).should be_false + end - it "raises an ArgumentError when passed a non-SortedSet" do - -> { SortedSet[].subset?([]) }.should raise_error(ArgumentError) - -> { SortedSet[].subset?(1) }.should raise_error(ArgumentError) - -> { SortedSet[].subset?("test") }.should raise_error(ArgumentError) - -> { SortedSet[].subset?(Object.new) }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-SortedSet" do + -> { SortedSet[].subset?([]) }.should raise_error(ArgumentError) + -> { SortedSet[].subset?(1) }.should raise_error(ArgumentError) + -> { SortedSet[].subset?("test") }.should raise_error(ArgumentError) + -> { SortedSet[].subset?(Object.new) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/subtract_spec.rb b/ruby/spec/ruby/library/set/sortedset/subtract_spec.rb index 64d66c368..b2af127f8 100644 --- a/ruby/spec/ruby/library/set/sortedset/subtract_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/subtract_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#subtract" do - before :each do - @set = SortedSet["a", "b", "c"] - end +ruby_version_is ""..."3.0" do + require 'set' - it "deletes any elements contained in other and returns self" do - @set.subtract(SortedSet["b", "c"]).should == @set - @set.should == SortedSet["a"] - end + describe "SortedSet#subtract" do + before :each do + @set = SortedSet["a", "b", "c"] + end + + it "deletes any elements contained in other and returns self" do + @set.subtract(SortedSet["b", "c"]).should == @set + @set.should == SortedSet["a"] + end - it "accepts any enumerable as other" do - @set.subtract(["c"]).should == SortedSet["a", "b"] + it "accepts any enumerable as other" do + @set.subtract(["c"]).should == SortedSet["a", "b"] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/superset_spec.rb b/ruby/spec/ruby/library/set/sortedset/superset_spec.rb index 823781b86..a1bbacb96 100644 --- a/ruby/spec/ruby/library/set/sortedset/superset_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/superset_spec.rb @@ -1,33 +1,36 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#superset?" do - before :each do - @set = SortedSet[1, 2, 3, 4] - end +ruby_version_is ""..."3.0" do + require 'set' - it "returns true if passed a SortedSet that equals self or self is a proper superset of" do - @set.superset?(@set).should be_true - SortedSet[].superset?(SortedSet[]).should be_true + describe "SortedSet#superset?" do + before :each do + @set = SortedSet[1, 2, 3, 4] + end - @set.superset?(SortedSet[]).should be_true - SortedSet[1, 2, 3].superset?(SortedSet[]).should be_true - SortedSet["a", "b", "c"].superset?(SortedSet[]).should be_true + it "returns true if passed a SortedSet that equals self or self is a proper superset of" do + @set.superset?(@set).should be_true + SortedSet[].superset?(SortedSet[]).should be_true - @set.superset?(SortedSet[1, 2, 3]).should be_true - @set.superset?(SortedSet[1, 3]).should be_true - @set.superset?(SortedSet[1, 2]).should be_true - @set.superset?(SortedSet[1]).should be_true + @set.superset?(SortedSet[]).should be_true + SortedSet[1, 2, 3].superset?(SortedSet[]).should be_true + SortedSet["a", "b", "c"].superset?(SortedSet[]).should be_true - @set.superset?(SortedSet[5]).should be_false - @set.superset?(SortedSet[1, 5]).should be_false - @set.superset?(SortedSet["test"]).should be_false - end + @set.superset?(SortedSet[1, 2, 3]).should be_true + @set.superset?(SortedSet[1, 3]).should be_true + @set.superset?(SortedSet[1, 2]).should be_true + @set.superset?(SortedSet[1]).should be_true + + @set.superset?(SortedSet[5]).should be_false + @set.superset?(SortedSet[1, 5]).should be_false + @set.superset?(SortedSet["test"]).should be_false + end - it "raises an ArgumentError when passed a non-SortedSet" do - -> { SortedSet[].superset?([]) }.should raise_error(ArgumentError) - -> { SortedSet[].superset?(1) }.should raise_error(ArgumentError) - -> { SortedSet[].superset?("test") }.should raise_error(ArgumentError) - -> { SortedSet[].superset?(Object.new) }.should raise_error(ArgumentError) + it "raises an ArgumentError when passed a non-SortedSet" do + -> { SortedSet[].superset?([]) }.should raise_error(ArgumentError) + -> { SortedSet[].superset?(1) }.should raise_error(ArgumentError) + -> { SortedSet[].superset?("test") }.should raise_error(ArgumentError) + -> { SortedSet[].superset?(Object.new) }.should raise_error(ArgumentError) + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/to_a_spec.rb b/ruby/spec/ruby/library/set/sortedset/to_a_spec.rb index ba37d18cd..bb54cd7cd 100644 --- a/ruby/spec/ruby/library/set/sortedset/to_a_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/to_a_spec.rb @@ -1,17 +1,20 @@ require_relative '../../../spec_helper' -require 'set' -describe "SortedSet#to_a" do - it "returns an array containing elements" do - set = SortedSet.new [1, 2, 3] - set.to_a.should == [1, 2, 3] - end +ruby_version_is ""..."3.0" do + require 'set' + + describe "SortedSet#to_a" do + it "returns an array containing elements" do + set = SortedSet.new [1, 2, 3] + set.to_a.should == [1, 2, 3] + end - it "returns a sorted array containing elements" do - set = SortedSet[2, 3, 1] - set.to_a.should == [1, 2, 3] + it "returns a sorted array containing elements" do + set = SortedSet[2, 3, 1] + set.to_a.should == [1, 2, 3] - set = SortedSet.new [5, 6, 4, 4] - set.to_a.should == [4, 5, 6] + set = SortedSet.new [5, 6, 4, 4] + set.to_a.should == [4, 5, 6] + end end end diff --git a/ruby/spec/ruby/library/set/sortedset/union_spec.rb b/ruby/spec/ruby/library/set/sortedset/union_spec.rb index eb77600fe..c942f20d3 100644 --- a/ruby/spec/ruby/library/set/sortedset/union_spec.rb +++ b/ruby/spec/ruby/library/set/sortedset/union_spec.rb @@ -1,11 +1,14 @@ require_relative '../../../spec_helper' -require_relative 'shared/union' -require 'set' -describe "SortedSet#union" do - it_behaves_like :sorted_set_union, :union -end +ruby_version_is ""..."3.0" do + require_relative 'shared/union' + require 'set' + + describe "SortedSet#union" do + it_behaves_like :sorted_set_union, :union + end -describe "SortedSet#|" do - it_behaves_like :sorted_set_union, :| + describe "SortedSet#|" do + it_behaves_like :sorted_set_union, :| + end end diff --git a/ruby/spec/ruby/library/set/to_s_spec.rb b/ruby/spec/ruby/library/set/to_s_spec.rb index ca2806d66..7b9f7b660 100644 --- a/ruby/spec/ruby/library/set/to_s_spec.rb +++ b/ruby/spec/ruby/library/set/to_s_spec.rb @@ -1,13 +1,11 @@ require_relative 'shared/inspect' require 'set' -ruby_version_is "2.5" do - describe "Set#to_s" do - it_behaves_like :set_inspect, :to_s +describe "Set#to_s" do + it_behaves_like :set_inspect, :to_s - it "is an alias of inspect" do - set = Set.new - set.method(:to_s).should == set.method(:inspect) - end + it "is an alias of inspect" do + set = Set.new + set.method(:to_s).should == set.method(:inspect) end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb index c5284f1c0..76579de74 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb @@ -21,18 +21,20 @@ end platform_is :linux do - with_feature :unix_socket do - describe 'using a UNIX Addrinfo' do - before do - @addr = Addrinfo.unix('cats') - @host = Socket.gethostname - end + platform_is_not :android do + with_feature :unix_socket do + describe 'using a UNIX Addrinfo' do + before do + @addr = Addrinfo.unix('cats') + @host = Socket.gethostname + end - it 'returns the hostname and UNIX socket path' do - host, path = @addr.getnameinfo + it 'returns the hostname and UNIX socket path' do + host, path = @addr.getnameinfo - host.should == @host - path.should == 'cats' + host.should == @host + path.should == 'cats' + end end end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/initialize_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/initialize_spec.rb index 8354553f6..00250439f 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/initialize_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/initialize_spec.rb @@ -274,15 +274,17 @@ end end - with_feature :sock_packet do - [:SOCK_SEQPACKET].each do |type| - it "overwrites the socket type #{type}" do - sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1'] + platform_is_not :android do + with_feature :sock_packet do + [:SOCK_SEQPACKET].each do |type| + it "overwrites the socket type #{type}" do + sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1'] - value = Socket.const_get(type) - addr = Addrinfo.new(sockaddr, nil, value) + value = Socket.const_get(type) + addr = Addrinfo.new(sockaddr, nil, value) - addr.socktype.should == value + addr.socktype.should == value + end end end end @@ -448,28 +450,30 @@ end platform_is :linux do - describe 'and the socket type is set to SOCK_SEQPACKET' do - before do - @socktype = Socket::SOCK_SEQPACKET - end + platform_is_not :android do + describe 'and the socket type is set to SOCK_SEQPACKET' do + before do + @socktype = Socket::SOCK_SEQPACKET + end - valid = [:IPPROTO_IP, :IPPROTO_HOPOPTS] + valid = [:IPPROTO_IP, :IPPROTO_HOPOPTS] - valid.each do |type| - it "overwrites the protocol when using #{type}" do - value = Socket.const_get(type) - addr = Addrinfo.new(@sockaddr, nil, @socktype, value) + valid.each do |type| + it "overwrites the protocol when using #{type}" do + value = Socket.const_get(type) + addr = Addrinfo.new(@sockaddr, nil, @socktype, value) - addr.protocol.should == value + addr.protocol.should == value + end end - end - (Socket.constants.grep(/^IPPROTO/) - valid).each do |type| - it "raises SocketError when using #{type}" do - value = Socket.const_get(type) - block = -> { Addrinfo.new(@sockaddr, nil, @socktype, value) } + (Socket.constants.grep(/^IPPROTO/) - valid).each do |type| + it "raises SocketError when using #{type}" do + value = Socket.const_get(type) + block = -> { Addrinfo.new(@sockaddr, nil, @socktype, value) } - block.should raise_error(SocketError) + block.should raise_error(SocketError) + end end end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb index f5bab711d..10ad084fc 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb @@ -3,10 +3,10 @@ describe "Addrinfo#ipv4_loopback?" do describe "for an ipv4 socket" do it "returns true for the loopback address" do - Addrinfo.ip('127.0.0.1').ipv4_loopback?.should == true - Addrinfo.ip('127.0.0.2').ipv4_loopback?.should == true - Addrinfo.ip('127.255.0.1').ipv4_loopback?.should == true - Addrinfo.ip('127.255.255.255').ipv4_loopback?.should == true + Addrinfo.ip('127.0.0.1').should.ipv4_loopback? + Addrinfo.ip('127.0.0.2').should.ipv4_loopback? + Addrinfo.ip('127.255.0.1').should.ipv4_loopback? + Addrinfo.ip('127.255.255.255').should.ipv4_loopback? end it "returns false for another address" do diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb index bdd14c1b0..f7fead864 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb @@ -2,17 +2,17 @@ describe "Addrinfo#ipv4_multicast?" do it 'returns true for a multicast address' do - Addrinfo.ip('224.0.0.0').ipv4_multicast?.should == true - Addrinfo.ip('224.0.0.9').ipv4_multicast?.should == true - Addrinfo.ip('239.255.255.250').ipv4_multicast?.should == true + Addrinfo.ip('224.0.0.0').should.ipv4_multicast? + Addrinfo.ip('224.0.0.9').should.ipv4_multicast? + Addrinfo.ip('239.255.255.250').should.ipv4_multicast? end it 'returns false for a regular address' do - Addrinfo.ip('8.8.8.8').ipv4_multicast?.should == false + Addrinfo.ip('8.8.8.8').should_not.ipv4_multicast? end it 'returns false for an IPv6 address' do - Addrinfo.ip('::1').ipv4_multicast?.should == false + Addrinfo.ip('::1').should_not.ipv4_multicast? end with_feature :unix_socket do diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb index 733577609..e5a33b495 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb @@ -8,14 +8,14 @@ end it "returns true for a private address" do - Addrinfo.ip('10.0.0.0').ipv4_private?.should == true - Addrinfo.ip('10.0.0.5').ipv4_private?.should == true + Addrinfo.ip('10.0.0.0').should.ipv4_private? + Addrinfo.ip('10.0.0.5').should.ipv4_private? - Addrinfo.ip('172.16.0.0').ipv4_private?.should == true - Addrinfo.ip('172.16.0.5').ipv4_private?.should == true + Addrinfo.ip('172.16.0.0').should.ipv4_private? + Addrinfo.ip('172.16.0.5').should.ipv4_private? - Addrinfo.ip('192.168.0.0').ipv4_private?.should == true - Addrinfo.ip('192.168.0.5').ipv4_private?.should == true + Addrinfo.ip('192.168.0.0').should.ipv4_private? + Addrinfo.ip('192.168.0.5').should.ipv4_private? end it "returns false for a public address" do diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb index 291b4d7d6..bfef39638 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb @@ -5,19 +5,19 @@ describe 'Addrinfo#ipv6_linklocal?' do platform_is_not :aix do it 'returns true for a link-local address' do - Addrinfo.ip('fe80::').ipv6_linklocal?.should == true - Addrinfo.ip('fe81::').ipv6_linklocal?.should == true - Addrinfo.ip('fe8f::').ipv6_linklocal?.should == true - Addrinfo.ip('fe80::1').ipv6_linklocal?.should == true + Addrinfo.ip('fe80::').should.ipv6_linklocal? + Addrinfo.ip('fe81::').should.ipv6_linklocal? + Addrinfo.ip('fe8f::').should.ipv6_linklocal? + Addrinfo.ip('fe80::1').should.ipv6_linklocal? end end it 'returns false for a regular address' do - Addrinfo.ip('::1').ipv6_linklocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_linklocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_linklocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_linklocal? end end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb index 9c8e4dccb..01fa0992b 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb @@ -2,19 +2,19 @@ describe 'Addrinfo#ipv6_mc_global?' do it 'returns true for a multi-cast address in the global scope' do - Addrinfo.ip('ff1e::').ipv6_mc_global?.should == true - Addrinfo.ip('fffe::').ipv6_mc_global?.should == true - Addrinfo.ip('ff0e::').ipv6_mc_global?.should == true - Addrinfo.ip('ff1e::1').ipv6_mc_global?.should == true + Addrinfo.ip('ff1e::').should.ipv6_mc_global? + Addrinfo.ip('fffe::').should.ipv6_mc_global? + Addrinfo.ip('ff0e::').should.ipv6_mc_global? + Addrinfo.ip('ff1e::1').should.ipv6_mc_global? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_mc_global?.should == false - Addrinfo.ip('ff1a::').ipv6_mc_global?.should == false - Addrinfo.ip('ff1f::1').ipv6_mc_global?.should == false + Addrinfo.ip('::1').should_not.ipv6_mc_global? + Addrinfo.ip('ff1a::').should_not.ipv6_mc_global? + Addrinfo.ip('ff1f::1').should_not.ipv6_mc_global? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_mc_global?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_global? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb index dd52a9ad8..a1298919e 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb @@ -2,18 +2,18 @@ describe 'Addrinfo#ipv6_mc_linklocal?' do it 'returns true for a multi-cast link-local address' do - Addrinfo.ip('ff12::').ipv6_mc_linklocal?.should == true - Addrinfo.ip('ff02::').ipv6_mc_linklocal?.should == true - Addrinfo.ip('fff2::').ipv6_mc_linklocal?.should == true - Addrinfo.ip('ff12::1').ipv6_mc_linklocal?.should == true + Addrinfo.ip('ff12::').should.ipv6_mc_linklocal? + Addrinfo.ip('ff02::').should.ipv6_mc_linklocal? + Addrinfo.ip('fff2::').should.ipv6_mc_linklocal? + Addrinfo.ip('ff12::1').should.ipv6_mc_linklocal? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_mc_linklocal?.should == false - Addrinfo.ip('fff1::').ipv6_mc_linklocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_mc_linklocal? + Addrinfo.ip('fff1::').should_not.ipv6_mc_linklocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_mc_linklocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_linklocal? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb index b3cf5ffba..0aee952d8 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb @@ -2,17 +2,17 @@ describe 'Addrinfo#ipv6_mc_nodelocal?' do it 'returns true for a multi-cast node-local address' do - Addrinfo.ip('ff11::').ipv6_mc_nodelocal?.should == true - Addrinfo.ip('ff01::').ipv6_mc_nodelocal?.should == true - Addrinfo.ip('fff1::').ipv6_mc_nodelocal?.should == true - Addrinfo.ip('ff11::1').ipv6_mc_nodelocal?.should == true + Addrinfo.ip('ff11::').should.ipv6_mc_nodelocal? + Addrinfo.ip('ff01::').should.ipv6_mc_nodelocal? + Addrinfo.ip('fff1::').should.ipv6_mc_nodelocal? + Addrinfo.ip('ff11::1').should.ipv6_mc_nodelocal? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_mc_nodelocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_mc_nodelocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_mc_nodelocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_nodelocal? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb index 90653dd49..2977a98d3 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb @@ -2,17 +2,17 @@ describe 'Addrinfo#ipv6_mc_orglocal?' do it 'returns true for a multi-cast org-local address' do - Addrinfo.ip('ff18::').ipv6_mc_orglocal?.should == true - Addrinfo.ip('ff08::').ipv6_mc_orglocal?.should == true - Addrinfo.ip('fff8::').ipv6_mc_orglocal?.should == true - Addrinfo.ip('ff18::1').ipv6_mc_orglocal?.should == true + Addrinfo.ip('ff18::').should.ipv6_mc_orglocal? + Addrinfo.ip('ff08::').should.ipv6_mc_orglocal? + Addrinfo.ip('fff8::').should.ipv6_mc_orglocal? + Addrinfo.ip('ff18::1').should.ipv6_mc_orglocal? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_mc_orglocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_mc_orglocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_mc_orglocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_orglocal? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb index 686b625e0..58e5976a4 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb @@ -2,17 +2,17 @@ describe 'Addrinfo#ipv6_mc_sitelocal?' do it 'returns true for a multi-cast site-local address' do - Addrinfo.ip('ff15::').ipv6_mc_sitelocal?.should == true - Addrinfo.ip('ff05::').ipv6_mc_sitelocal?.should == true - Addrinfo.ip('fff5::').ipv6_mc_sitelocal?.should == true - Addrinfo.ip('ff15::1').ipv6_mc_sitelocal?.should == true + Addrinfo.ip('ff15::').should.ipv6_mc_sitelocal? + Addrinfo.ip('ff05::').should.ipv6_mc_sitelocal? + Addrinfo.ip('fff5::').should.ipv6_mc_sitelocal? + Addrinfo.ip('ff15::1').should.ipv6_mc_sitelocal? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_mc_sitelocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_mc_sitelocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_mc_sitelocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_sitelocal? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb index c25322869..2c987b592 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb @@ -18,19 +18,19 @@ describe "for an ipv6 socket" do it "returns true for a multicast address" do - Addrinfo.ip('ff00::').ipv6_multicast?.should == true - Addrinfo.ip('ff00::1').ipv6_multicast?.should == true - Addrinfo.ip('ff08::1').ipv6_multicast?.should == true - Addrinfo.ip('fff8::1').ipv6_multicast?.should == true - - Addrinfo.ip('ff02::').ipv6_multicast?.should == true - Addrinfo.ip('ff02::1').ipv6_multicast?.should == true - Addrinfo.ip('ff0f::').ipv6_multicast?.should == true + Addrinfo.ip('ff00::').should.ipv6_multicast? + Addrinfo.ip('ff00::1').should.ipv6_multicast? + Addrinfo.ip('ff08::1').should.ipv6_multicast? + Addrinfo.ip('fff8::1').should.ipv6_multicast? + + Addrinfo.ip('ff02::').should.ipv6_multicast? + Addrinfo.ip('ff02::1').should.ipv6_multicast? + Addrinfo.ip('ff0f::').should.ipv6_multicast? end it "returns false for another address" do - Addrinfo.ip('::1').ipv6_multicast?.should == false - Addrinfo.ip('fe80::').ipv6_multicast?.should == false + Addrinfo.ip('::1').should_not.ipv6_multicast? + Addrinfo.ip('fe80::').should_not.ipv6_multicast? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb index dd202a174..9158eb580 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb @@ -5,19 +5,19 @@ describe 'Addrinfo#ipv6_sitelocal?' do platform_is_not :aix do it 'returns true for a site-local address' do - Addrinfo.ip('feef::').ipv6_sitelocal?.should == true - Addrinfo.ip('fee0::').ipv6_sitelocal?.should == true - Addrinfo.ip('fee2::').ipv6_sitelocal?.should == true - Addrinfo.ip('feef::1').ipv6_sitelocal?.should == true + Addrinfo.ip('feef::').should.ipv6_sitelocal? + Addrinfo.ip('fee0::').should.ipv6_sitelocal? + Addrinfo.ip('fee2::').should.ipv6_sitelocal? + Addrinfo.ip('feef::1').should.ipv6_sitelocal? end end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_sitelocal?.should == false + Addrinfo.ip('::1').should_not.ipv6_sitelocal? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_sitelocal?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_sitelocal? end end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb index b80a15fcb..22f0fa3b7 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb @@ -2,17 +2,17 @@ describe 'Addrinfo#ipv6_unique_local?' do it 'returns true for an unique local IPv6 address' do - Addrinfo.ip('fc00::').ipv6_unique_local?.should == true - Addrinfo.ip('fd00::').ipv6_unique_local?.should == true - Addrinfo.ip('fcff::').ipv6_unique_local?.should == true + Addrinfo.ip('fc00::').should.ipv6_unique_local? + Addrinfo.ip('fd00::').should.ipv6_unique_local? + Addrinfo.ip('fcff::').should.ipv6_unique_local? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_unique_local?.should == false - Addrinfo.ip('fe00::').ipv6_unique_local?.should == false + Addrinfo.ip('::1').should_not.ipv6_unique_local? + Addrinfo.ip('fe00::').should_not.ipv6_unique_local? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_unique_local?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_unique_local? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb index dd79d5750..d63979ced 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb @@ -2,14 +2,14 @@ describe 'Addrinfo#ipv6_unspecified?' do it 'returns true for an unspecified IPv6 address' do - Addrinfo.ip('::').ipv6_unspecified?.should == true + Addrinfo.ip('::').should.ipv6_unspecified? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_unspecified?.should == false + Addrinfo.ip('::1').should_not.ipv6_unspecified? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_unspecified?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_unspecified? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb index ab8388a21..21ca85af9 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb @@ -2,19 +2,19 @@ describe 'Addrinfo#ipv6_v4compat?' do it 'returns true for an IPv4 compatible address' do - Addrinfo.ip('::127.0.0.1').ipv6_v4compat?.should == true - Addrinfo.ip('::192.168.1.1').ipv6_v4compat?.should == true + Addrinfo.ip('::127.0.0.1').should.ipv6_v4compat? + Addrinfo.ip('::192.168.1.1').should.ipv6_v4compat? end it 'returns false for an IPv4 mapped address' do - Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4compat?.should == false + Addrinfo.ip('::ffff:192.168.1.1').should_not.ipv6_v4compat? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_v4compat?.should == false + Addrinfo.ip('::1').should_not.ipv6_v4compat? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_v4compat?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_v4compat? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb index 82b272c16..7dac0e75d 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb @@ -2,19 +2,19 @@ describe 'Addrinfo#ipv6_v4mapped?' do it 'returns true for an IPv4 compatible address' do - Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4mapped?.should == true + Addrinfo.ip('::ffff:192.168.1.1').should.ipv6_v4mapped? end it 'returns false for an IPv4 compatible address' do - Addrinfo.ip('::192.168.1.1').ipv6_v4mapped?.should == false - Addrinfo.ip('::127.0.0.1').ipv6_v4mapped?.should == false + Addrinfo.ip('::192.168.1.1').should_not.ipv6_v4mapped? + Addrinfo.ip('::127.0.0.1').should_not.ipv6_v4mapped? end it 'returns false for a regular IPv6 address' do - Addrinfo.ip('::1').ipv6_v4mapped?.should == false + Addrinfo.ip('::1').should_not.ipv6_v4mapped? end it 'returns false for an IPv4 address' do - Addrinfo.ip('127.0.0.1').ipv6_v4mapped?.should == false + Addrinfo.ip('127.0.0.1').should_not.ipv6_v4mapped? end end diff --git a/ruby/spec/ruby/library/socket/addrinfo/listen_spec.rb b/ruby/spec/ruby/library/socket/addrinfo/listen_spec.rb index 714a96ed6..931093f73 100644 --- a/ruby/spec/ruby/library/socket/addrinfo/listen_spec.rb +++ b/ruby/spec/ruby/library/socket/addrinfo/listen_spec.rb @@ -29,6 +29,6 @@ socket = sock end - socket.closed?.should == true + socket.should.closed? end end diff --git a/ruby/spec/ruby/library/socket/basicsocket/local_address_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/local_address_spec.rb new file mode 100644 index 000000000..0bd60a44c --- /dev/null +++ b/ruby/spec/ruby/library/socket/basicsocket/local_address_spec.rb @@ -0,0 +1,10 @@ +require_relative '../spec_helper' +require_relative '../shared/address' + +describe 'BasicSocket#local_address' do + it_behaves_like :socket_local_remote_address, :local_address, -> socket { + a2 = BasicSocket.for_fd(socket.fileno) + a2.autoclose = false + a2.local_address + } +end diff --git a/ruby/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb index 1823f3d75..df44a50af 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb @@ -1,45 +1,43 @@ require_relative '../spec_helper' require_relative '../fixtures/classes' -ruby_version_is "2.5" do - describe "BasicSocket#read_nonblock" do - SocketSpecs.each_ip_protocol do |family, ip_address| - before :each do - @r = Socket.new(family, :DGRAM) - @w = Socket.new(family, :DGRAM) +describe "BasicSocket#read_nonblock" do + SocketSpecs.each_ip_protocol do |family, ip_address| + before :each do + @r = Socket.new(family, :DGRAM) + @w = Socket.new(family, :DGRAM) - @r.bind(Socket.pack_sockaddr_in(0, ip_address)) - @w.send("aaa", 0, @r.getsockname) - end + @r.bind(Socket.pack_sockaddr_in(0, ip_address)) + @w.send("aaa", 0, @r.getsockname) + end - after :each do - @r.close unless @r.closed? - @w.close unless @w.closed? - end + after :each do + @r.close unless @r.closed? + @w.close unless @w.closed? + end - it "receives data after it's ready" do - IO.select([@r], nil, nil, 2) - @r.recv_nonblock(5).should == "aaa" - end + it "receives data after it's ready" do + IO.select([@r], nil, nil, 2) + @r.recv_nonblock(5).should == "aaa" + end - platform_is :linux do - it 'does not set the IO in nonblock mode' do - require 'io/nonblock' - @r.nonblock?.should == false - IO.select([@r], nil, nil, 2) - @r.read_nonblock(3).should == "aaa" - @r.nonblock?.should == false - end + platform_is :linux do + it 'does not set the IO in nonblock mode' do + require 'io/nonblock' + @r.nonblock = false + IO.select([@r], nil, nil, 2) + @r.read_nonblock(3).should == "aaa" + @r.should_not.nonblock? end + end - platform_is_not :linux, :windows do - it 'sets the IO in nonblock mode' do - require 'io/nonblock' - @r.nonblock?.should == false - IO.select([@r], nil, nil, 2) - @r.read_nonblock(3).should == "aaa" - @r.nonblock?.should == true - end + platform_is_not :linux, :windows do + it 'sets the IO in nonblock mode' do + require 'io/nonblock' + @r.nonblock = false + IO.select([@r], nil, nil, 2) + @r.read_nonblock(3).should == "aaa" + @r.should.nonblock? end end end diff --git a/ruby/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb index 0363f2f8d..b6ab8a9ce 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb @@ -67,4 +67,25 @@ }.should raise_error(IO::WaitReadable) end end + + SocketSpecs.each_ip_protocol do |family, ip_address| + describe 'using a connected but not bound socket' do + before do + @server = Socket.new(family, :STREAM) + end + + after do + @server.close + end + + it "raises Errno::ENOTCONN" do + -> { @server.recv_nonblock(1) }.should raise_error { |e| + [Errno::ENOTCONN, Errno::EINVAL].should.include?(e.class) + } + -> { @server.recv_nonblock(1, exception: false) }.should raise_error { |e| + [Errno::ENOTCONN, Errno::EINVAL].should.include?(e.class) + } + end + end + end end diff --git a/ruby/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb index 8e6c232c5..cc4275c41 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb @@ -114,6 +114,21 @@ end platform_is_not :windows do + describe 'using a connected but not bound socket' do + before do + @server = Socket.new(family, :STREAM) + end + + after do + @server.close + end + + it "raises Errno::ENOTCONN" do + -> { @server.recvmsg_nonblock }.should raise_error(Errno::ENOTCONN) + -> { @server.recvmsg_nonblock(exception: false) }.should raise_error(Errno::ENOTCONN) + end + end + describe 'using a connected socket' do before do @client = Socket.new(family, :STREAM) diff --git a/ruby/spec/ruby/library/socket/basicsocket/remote_address_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/remote_address_spec.rb new file mode 100644 index 000000000..439bf3159 --- /dev/null +++ b/ruby/spec/ruby/library/socket/basicsocket/remote_address_spec.rb @@ -0,0 +1,10 @@ +require_relative '../spec_helper' +require_relative '../shared/address' + +describe 'BasicSocket#remote_address' do + it_behaves_like :socket_local_remote_address, :remote_address, -> socket { + a2 = BasicSocket.for_fd(socket.fileno) + a2.autoclose = false + a2.remote_address + } +end diff --git a/ruby/spec/ruby/library/socket/basicsocket/send_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/send_spec.rb index 041ee4699..868801df3 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/send_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/send_spec.rb @@ -99,6 +99,14 @@ @server.close end + describe 'with an object implementing #to_str' do + it 'returns the amount of sent bytes' do + data = mock('message') + data.should_receive(:to_str).and_return('hello') + @client.send(data, 0, @server.getsockname).should == 5 + end + end + describe 'without a destination address' do it "raises #{SocketSpecs.dest_addr_req_error}" do -> { @client.send('hello', 0) }.should raise_error(SocketSpecs.dest_addr_req_error) diff --git a/ruby/spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb index c112f2ab4..7acfc659b 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb @@ -18,7 +18,12 @@ describe 'without a destination address' do it "raises #{SocketSpecs.dest_addr_req_error}" do - -> { @client.sendmsg_nonblock('hello') }.should raise_error(SocketSpecs.dest_addr_req_error) + -> { + @client.sendmsg_nonblock('hello') + }.should raise_error(SocketSpecs.dest_addr_req_error) + -> { + @client.sendmsg_nonblock('hello', exception: false) + }.should raise_error(SocketSpecs.dest_addr_req_error) end end diff --git a/ruby/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb b/ruby/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb index f2e7366eb..523e73295 100644 --- a/ruby/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb @@ -1,44 +1,42 @@ require_relative '../spec_helper' require_relative '../fixtures/classes' -ruby_version_is "2.5" do - describe "BasicSocket#write_nonblock" do - SocketSpecs.each_ip_protocol do |family, ip_address| - before :each do - @r = Socket.new(family, :DGRAM) - @w = Socket.new(family, :DGRAM) +describe "BasicSocket#write_nonblock" do + SocketSpecs.each_ip_protocol do |family, ip_address| + before :each do + @r = Socket.new(family, :DGRAM) + @w = Socket.new(family, :DGRAM) - @r.bind(Socket.pack_sockaddr_in(0, ip_address)) - @w.connect(@r.getsockname) - end + @r.bind(Socket.pack_sockaddr_in(0, ip_address)) + @w.connect(@r.getsockname) + end - after :each do - @r.close unless @r.closed? - @w.close unless @w.closed? - end + after :each do + @r.close unless @r.closed? + @w.close unless @w.closed? + end - it "sends data" do - @w.write_nonblock("aaa").should == 3 - IO.select([@r], nil, nil, 2) - @r.recv_nonblock(5).should == "aaa" - end + it "sends data" do + @w.write_nonblock("aaa").should == 3 + IO.select([@r], nil, nil, 2) + @r.recv_nonblock(5).should == "aaa" + end - platform_is :linux do - it 'does not set the IO in nonblock mode' do - require 'io/nonblock' - @w.nonblock?.should == false - @w.write_nonblock("aaa").should == 3 - @w.nonblock?.should == false - end + platform_is :linux do + it 'does not set the IO in nonblock mode' do + require 'io/nonblock' + @w.nonblock = false + @w.write_nonblock("aaa").should == 3 + @w.should_not.nonblock? end + end - platform_is_not :linux, :windows do - it 'sets the IO in nonblock mode' do - require 'io/nonblock' - @w.nonblock?.should == false - @w.write_nonblock("aaa").should == 3 - @w.nonblock?.should == true - end + platform_is_not :linux, :windows do + it 'sets the IO in nonblock mode' do + require 'io/nonblock' + @w.nonblock = false + @w.write_nonblock("aaa").should == 3 + @w.should.nonblock? end end end diff --git a/ruby/spec/ruby/library/socket/constants/constants_spec.rb b/ruby/spec/ruby/library/socket/constants/constants_spec.rb index 710af1282..637bc6740 100644 --- a/ruby/spec/ruby/library/socket/constants/constants_spec.rb +++ b/ruby/spec/ruby/library/socket/constants/constants_spec.rb @@ -68,7 +68,7 @@ end end - platform_is_not :solaris, :windows, :aix do + platform_is_not :solaris, :windows, :aix, :android do it "defines multicast options" do consts = ["IP_MAX_MEMBERSHIPS"] consts.each do |c| diff --git a/ruby/spec/ruby/library/socket/shared/address.rb b/ruby/spec/ruby/library/socket/shared/address.rb new file mode 100644 index 000000000..f3be9cfb9 --- /dev/null +++ b/ruby/spec/ruby/library/socket/shared/address.rb @@ -0,0 +1,249 @@ +require_relative '../fixtures/classes' + +describe :socket_local_remote_address, shared: true do + describe 'using TCPSocket' do + before :each do + @s = TCPServer.new('127.0.0.1', 0) + @a = TCPSocket.new('127.0.0.1', @s.addr[1]) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + end + + it 'uses AF_INET as the address family' do + @addr.afamily.should == Socket::AF_INET + end + + it 'uses PF_INET as the protocol family' do + @addr.pfamily.should == Socket::PF_INET + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '127.0.0.1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + + guard -> { SocketSpecs.ipv6_available? } do + describe 'using IPv6' do + before :each do + @s = TCPServer.new('::1', 0) + @a = TCPSocket.new('::1', @s.addr[1]) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + end + + it 'uses AF_INET6 as the address family' do + @addr.afamily.should == Socket::AF_INET6 + end + + it 'uses PF_INET6 as the protocol family' do + @addr.pfamily.should == Socket::PF_INET6 + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '::1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + end + + with_feature :unix_socket do + describe 'using UNIXSocket' do + before :each do + @path = SocketSpecs.socket_path + @s = UNIXServer.new(@path) + @a = UNIXSocket.new(@path) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + rm_r(@path) + end + + it 'uses AF_UNIX as the address family' do + @addr.afamily.should == Socket::AF_UNIX + end + + it 'uses PF_UNIX as the protocol family' do + @addr.pfamily.should == Socket::PF_UNIX + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct socket path' do + if @method == :local_address + @addr.unix_path.should == "" + else + @addr.unix_path.should == @path + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + end + + describe 'using UDPSocket' do + before :each do + @s = UDPSocket.new + @s.bind("127.0.0.1", 0) + @a = UDPSocket.new + @a.connect("127.0.0.1", @s.addr[1]) + @addr = @object.call(@a) + end + + after :each do + [@a, @s].each(&:close) + end + + it 'uses the correct address family' do + @addr.afamily.should == Socket::AF_INET + end + + it 'uses the correct protocol family' do + @addr.pfamily.should == Socket::PF_INET + end + + it 'uses SOCK_DGRAM as the socket type' do + @addr.socktype.should == Socket::SOCK_DGRAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '127.0.0.1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the peer' do + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end +end diff --git a/ruby/spec/ruby/library/socket/socket/accept_nonblock_spec.rb b/ruby/spec/ruby/library/socket/socket/accept_nonblock_spec.rb index 3221f0b12..011622988 100644 --- a/ruby/spec/ruby/library/socket/socket/accept_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/accept_nonblock_spec.rb @@ -46,6 +46,7 @@ describe 'using an unbound socket' do it 'raises Errno::EINVAL' do -> { @server.accept_nonblock }.should raise_error(Errno::EINVAL) + -> { @server.accept_nonblock(exception: false) }.should raise_error(Errno::EINVAL) end end @@ -56,6 +57,7 @@ it 'raises Errno::EINVAL' do -> { @server.accept_nonblock }.should raise_error(Errno::EINVAL) + -> { @server.accept_nonblock(exception: false) }.should raise_error(Errno::EINVAL) end end @@ -64,6 +66,7 @@ @server.close -> { @server.accept_nonblock }.should raise_error(IOError) + -> { @server.accept_nonblock(exception: false) }.should raise_error(IOError) end end diff --git a/ruby/spec/ruby/library/socket/socket/bind_spec.rb b/ruby/spec/ruby/library/socket/socket/bind_spec.rb index 0349df84a..4465a3daf 100644 --- a/ruby/spec/ruby/library/socket/socket/bind_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/bind_spec.rb @@ -33,6 +33,7 @@ platform_is_not :windows, :cygwin do as_user do + break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil it "raises Errno::EACCES when the current user does not have permission to bind" do sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1") -> { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES) @@ -74,6 +75,7 @@ platform_is_not :windows, :cygwin do as_user do + break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil it "raises Errno::EACCES when the current user does not have permission to bind" do sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1") -> { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES) @@ -113,6 +115,8 @@ platform_is_not :windows do as_user do + break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil + it 'raises Errno::EACCES when the user is not allowed to bind to the port' do sockaddr1 = Socket.pack_sockaddr_in(1, ip_address) diff --git a/ruby/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb b/ruby/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb index 5d9734110..a4c835552 100644 --- a/ruby/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb @@ -10,12 +10,12 @@ describe 'without an explicit address family' do it 'returns an Array' do - Socket.gethostbyaddr(@addr).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr) }.should be_an_instance_of(Array) end describe 'the returned Array' do before do - @array = Socket.gethostbyaddr(@addr) + @array = suppress_warning { Socket.gethostbyaddr(@addr) } end # RubyCI Solaris 11x defines 127.0.0.1 as unstable11x @@ -49,15 +49,15 @@ describe 'with an explicit address family' do it 'returns an Array when using an Integer as the address family' do - Socket.gethostbyaddr(@addr, Socket::AF_INET).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr, Socket::AF_INET) }.should be_an_instance_of(Array) end it 'returns an Array when using a Symbol as the address family' do - Socket.gethostbyaddr(@addr, :INET).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr, :INET) }.should be_an_instance_of(Array) end it 'raises SocketError when the address is not supported by the family' do - -> { Socket.gethostbyaddr(@addr, :INET6) }.should raise_error(SocketError) + -> { suppress_warning { Socket.gethostbyaddr(@addr, :INET6) } }.should raise_error(SocketError) end end end @@ -70,12 +70,12 @@ describe 'without an explicit address family' do it 'returns an Array' do - Socket.gethostbyaddr(@addr).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr) }.should be_an_instance_of(Array) end describe 'the returned Array' do before do - @array = Socket.gethostbyaddr(@addr) + @array = suppress_warning { Socket.gethostbyaddr(@addr) } end it 'includes the hostname as the first value' do @@ -106,16 +106,16 @@ describe 'with an explicit address family' do it 'returns an Array when using an Integer as the address family' do - Socket.gethostbyaddr(@addr, Socket::AF_INET6).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr, Socket::AF_INET6) }.should be_an_instance_of(Array) end it 'returns an Array when using a Symbol as the address family' do - Socket.gethostbyaddr(@addr, :INET6).should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyaddr(@addr, :INET6) }.should be_an_instance_of(Array) end - platform_is_not :windows do + platform_is_not :windows, :wsl do it 'raises SocketError when the address is not supported by the family' do - -> { Socket.gethostbyaddr(@addr, :INET) }.should raise_error(SocketError) + -> { suppress_warning { Socket.gethostbyaddr(@addr, :INET) } }.should raise_error(SocketError) end end end diff --git a/ruby/spec/ruby/library/socket/socket/gethostbyname_spec.rb b/ruby/spec/ruby/library/socket/socket/gethostbyname_spec.rb index 2696f4456..0858e255e 100644 --- a/ruby/spec/ruby/library/socket/socket/gethostbyname_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/gethostbyname_spec.rb @@ -4,24 +4,24 @@ describe "Socket.gethostbyname" do it "returns broadcast address info for ''" do - addr = Socket.gethostbyname(''); + addr = suppress_warning { Socket.gethostbyname('') } addr.should == ["255.255.255.255", [], 2, "\xFF\xFF\xFF\xFF"] end it "returns broadcast address info for ''" do - addr = Socket.gethostbyname(''); + addr = suppress_warning { Socket.gethostbyname('') } addr.should == ["0.0.0.0", [], 2, "\x00\x00\x00\x00"] end end describe 'Socket.gethostbyname' do it 'returns an Array' do - Socket.gethostbyname('127.0.0.1').should be_an_instance_of(Array) + suppress_warning { Socket.gethostbyname('127.0.0.1') }.should be_an_instance_of(Array) end describe 'the returned Array' do before do - @array = Socket.gethostbyname('127.0.0.1') + @array = suppress_warning { Socket.gethostbyname('127.0.0.1') } end it 'includes the hostname as the first value' do @@ -54,7 +54,7 @@ describe 'using as the input address' do describe 'the returned Array' do before do - @addr = Socket.gethostbyname('') + @addr = suppress_warning { Socket.gethostbyname('') } end it 'includes the broadcast address as the first value' do @@ -74,7 +74,7 @@ describe 'using as the input address' do describe 'the returned Array' do before do - @addr = Socket.gethostbyname('') + @addr = suppress_warning { Socket.gethostbyname('') } end it 'includes the wildcard address as the first value' do @@ -94,7 +94,7 @@ describe 'using an IPv4 address' do describe 'the returned Array' do before do - @addr = Socket.gethostbyname('127.0.0.1') + @addr = suppress_warning { Socket.gethostbyname('127.0.0.1') } end it 'includes the IP address as the first value' do @@ -115,7 +115,7 @@ describe 'using an IPv6 address' do describe 'the returned Array' do before do - @addr = Socket.gethostbyname('::1') + @addr = suppress_warning { Socket.gethostbyname('::1') } end it 'includes the IP address as the first value' do diff --git a/ruby/spec/ruby/library/socket/socket/listen_spec.rb b/ruby/spec/ruby/library/socket/socket/listen_spec.rb index 5de70d6db..4d2aedab1 100644 --- a/ruby/spec/ruby/library/socket/socket/listen_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/listen_spec.rb @@ -34,8 +34,10 @@ @server.close end - it 'raises Errno::EOPNOTSUPP' do - -> { @server.listen(1) }.should raise_error(Errno::EOPNOTSUPP) + it 'raises Errno::EOPNOTSUPP or Errno::EACCES' do + -> { @server.listen(1) }.should raise_error { |e| + [Errno::EOPNOTSUPP, Errno::EACCES].should.include?(e.class) + } end end diff --git a/ruby/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb b/ruby/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb index 10c030a8c..bd496d301 100644 --- a/ruby/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb @@ -32,7 +32,7 @@ Socket.tcp_server_sockets(0) { |socks| sockets = socks } sockets.each do |socket| - socket.closed?.should == true + socket.should.closed? end end end diff --git a/ruby/spec/ruby/library/socket/socket/tcp_spec.rb b/ruby/spec/ruby/library/socket/socket/tcp_spec.rb index d36e3e6ad..faf020b1e 100644 --- a/ruby/spec/ruby/library/socket/socket/tcp_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/tcp_spec.rb @@ -36,7 +36,7 @@ @socket = socket end - @socket.closed?.should == true + @socket.should.closed? end it 'binds to a local address and port when specified' do diff --git a/ruby/spec/ruby/library/socket/socket/udp_server_loop_spec.rb b/ruby/spec/ruby/library/socket/socket/udp_server_loop_spec.rb index 66563bc74..fc030e75b 100644 --- a/ruby/spec/ruby/library/socket/socket/udp_server_loop_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/udp_server_loop_spec.rb @@ -21,7 +21,7 @@ it 'yields the message and a Socket::UDPSource' do msg, src = nil - Thread.new do + thread = Thread.new do SocketSpecs::ServerLoopPortFinder.udp_server_loop('127.0.0.1', 0) do |message, source| msg = message src = source @@ -52,6 +52,8 @@ msg.should == 'hello' src.should be_an_instance_of(Socket::UDPSource) + + thread.join end end end diff --git a/ruby/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb b/ruby/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb index 3aeb472dd..f8be67261 100644 --- a/ruby/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb @@ -32,7 +32,7 @@ Socket.udp_server_sockets(0) { |socks| sockets = socks } sockets.each do |socket| - socket.closed?.should == true + socket.should.closed? end end end diff --git a/ruby/spec/ruby/library/socket/socket/unix_spec.rb b/ruby/spec/ruby/library/socket/socket/unix_spec.rb index add54a097..4bff59bd4 100644 --- a/ruby/spec/ruby/library/socket/socket/unix_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/unix_spec.rb @@ -38,7 +38,7 @@ socket = sock end - socket.closed?.should == true + socket.should.closed? end end end diff --git a/ruby/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb b/ruby/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb index bd95f1db0..12f970f89 100644 --- a/ruby/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb +++ b/ruby/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb @@ -13,7 +13,7 @@ Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock' end - it 'raises an ArgumentError when the sin_family is not AF_UNIX' do + it 'raises an ArgumentError when the sa_family is not AF_UNIX' do sockaddr = Socket.sockaddr_in(0, '127.0.0.1') -> { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError) end diff --git a/ruby/spec/ruby/library/socket/tcpserver/accept_spec.rb b/ruby/spec/ruby/library/socket/tcpserver/accept_spec.rb index 0da4e2218..d38d95e0e 100644 --- a/ruby/spec/ruby/library/socket/tcpserver/accept_spec.rb +++ b/ruby/spec/ruby/library/socket/tcpserver/accept_spec.rb @@ -58,6 +58,26 @@ t.join end + it "is automatically retried when interrupted by SIGVTALRM" do + t = Thread.new do + client = @server.accept + value = client.read(2) + client.close + value + end + + Thread.pass while t.status and t.status != "sleep" + # Thread#backtrace uses SIGVTALRM on TruffleRuby and potentially other implementations. + # Sending a signal to a thread is not possible with Ruby APIs. + t.backtrace.join("\n").should.include?("in `accept'") + + socket = TCPSocket.new('127.0.0.1', @port) + socket.write("OK") + socket.close + + t.value.should == "OK" + end + it "raises an IOError if the socket is closed" do @server.close -> { @server.accept }.should raise_error(IOError) diff --git a/ruby/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb b/ruby/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb index 703abff81..f0e98778f 100644 --- a/ruby/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb +++ b/ruby/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb @@ -4,7 +4,9 @@ # TODO: verify these for windows describe "TCPSocket#gethostbyname" do before :each do - @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname) + suppress_warning do + @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname) + end end it "returns an array elements of information on the hostname" do @@ -52,13 +54,17 @@ describe 'TCPSocket#gethostbyname' do it 'returns an Array' do - TCPSocket.gethostbyname('127.0.0.1').should be_an_instance_of(Array) + suppress_warning do + TCPSocket.gethostbyname('127.0.0.1').should be_an_instance_of(Array) + end end describe 'using a hostname' do describe 'the returned Array' do before do - @array = TCPSocket.gethostbyname('127.0.0.1') + suppress_warning do + @array = TCPSocket.gethostbyname('127.0.0.1') + end end it 'includes the canonical name as the 1st value' do @@ -88,7 +94,9 @@ SocketSpecs.each_ip_protocol do |family, ip_address| describe 'the returned Array' do before do - @array = TCPSocket.gethostbyname(ip_address) + suppress_warning do + @array = TCPSocket.gethostbyname(ip_address) + end end it 'includes the IP address as the 1st value' do diff --git a/ruby/spec/ruby/library/socket/tcpsocket/initialize_spec.rb b/ruby/spec/ruby/library/socket/tcpsocket/initialize_spec.rb index a3cee0541..065c8f419 100644 --- a/ruby/spec/ruby/library/socket/tcpsocket/initialize_spec.rb +++ b/ruby/spec/ruby/library/socket/tcpsocket/initialize_spec.rb @@ -1,5 +1,10 @@ require_relative '../spec_helper' require_relative '../fixtures/classes' +require_relative 'shared/new' + +describe 'TCPSocket#initialize' do + it_behaves_like :tcpsocket_new, :new +end describe 'TCPSocket#initialize' do SocketSpecs.each_ip_protocol do |family, ip_address| diff --git a/ruby/spec/ruby/library/socket/tcpsocket/new_spec.rb b/ruby/spec/ruby/library/socket/tcpsocket/new_spec.rb deleted file mode 100644 index 4924468be..000000000 --- a/ruby/spec/ruby/library/socket/tcpsocket/new_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require_relative 'shared/new' - -describe "TCPSocket.new" do - it_behaves_like :tcpsocket_new, :new -end diff --git a/ruby/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb b/ruby/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb index bfd815c65..6ce5a41b5 100644 --- a/ruby/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb @@ -27,6 +27,20 @@ @socket.recv_nonblock(50).should == "TCPSocket#recv_nonblock" end + it 'writes the read to a buffer from the socket' do + @socket = TCPSocket.new @hostname, @server.port + @socket.write "TCPSocket#recv_nonblock" + + # Wait for the server to echo. This spec is testing the return + # value, not the non-blocking behavior. + # + # TODO: Figure out a good way to test non-blocking. + IO.select([@socket]) + buffer = "".b + @socket.recv_nonblock(50, 0, buffer) + buffer.should == 'TCPSocket#recv_nonblock' + end + it 'returns :wait_readable in exceptionless mode' do @socket = TCPSocket.new @hostname, @server.port @socket.recv_nonblock(50, exception: false).should == :wait_readable diff --git a/ruby/spec/ruby/library/socket/tcpsocket/shared/new.rb b/ruby/spec/ruby/library/socket/tcpsocket/shared/new.rb index 5ca3a0e6c..4189acc2f 100644 --- a/ruby/spec/ruby/library/socket/tcpsocket/shared/new.rb +++ b/ruby/spec/ruby/library/socket/tcpsocket/shared/new.rb @@ -14,6 +14,14 @@ } end + ruby_version_is "3.0" do + it 'raises Errno::ETIMEDOUT with :connect_timeout when no server is listening on the given address' do + -> { + TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0) + }.should raise_error(Errno::ETIMEDOUT) + end + end + describe "with a running server" do before :each do @server = SocketSpecs::SpecTCPServer.new @@ -75,5 +83,12 @@ @socket.addr[1].should be_kind_of(Integer) @socket.addr[2].should =~ /^#{@hostname}/ end + + ruby_version_is "3.0" do + it "connects to a server when passed connect_timeout argument" do + @socket = TCPSocket.send(@method, @hostname, @server.port, connect_timeout: 1) + @socket.should be_an_instance_of(TCPSocket) + end + end end end diff --git a/ruby/spec/ruby/library/socket/udpsocket/inspect_spec.rb b/ruby/spec/ruby/library/socket/udpsocket/inspect_spec.rb index 201e8b3fc..e212120b1 100644 --- a/ruby/spec/ruby/library/socket/udpsocket/inspect_spec.rb +++ b/ruby/spec/ruby/library/socket/udpsocket/inspect_spec.rb @@ -10,16 +10,8 @@ @socket.close end - ruby_version_is ""..."2.5" do - it 'returns a String with the fd' do - @socket.inspect.should == "#" - end - end - - ruby_version_is "2.5" do - it 'returns a String with the fd, family, address and port' do - port = @socket.addr[1] - @socket.inspect.should == "#" - end + it 'returns a String with the fd, family, address and port' do + port = @socket.addr[1] + @socket.inspect.should == "#" end end diff --git a/ruby/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb b/ruby/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb index c66d1df84..650a06122 100644 --- a/ruby/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb +++ b/ruby/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb @@ -51,6 +51,13 @@ @server.recvfrom_nonblock(1).should be_an_instance_of(Array) end + it 'writes the data to the buffer when one is present' do + buffer = "".b + IO.select([@server]) + @server.recvfrom_nonblock(1, 0, buffer) + buffer.should == 'h' + end + describe 'the returned Array' do before do IO.select([@server]) diff --git a/ruby/spec/ruby/library/socket/unixsocket/open_spec.rb b/ruby/spec/ruby/library/socket/unixsocket/open_spec.rb index ad5048fed..99ad151bb 100644 --- a/ruby/spec/ruby/library/socket/unixsocket/open_spec.rb +++ b/ruby/spec/ruby/library/socket/unixsocket/open_spec.rb @@ -21,7 +21,7 @@ it "opens a unix socket on the specified file and yields it to the block" do UNIXSocket.open(@path) do |client| client.addr[0].should == "AF_UNIX" - client.closed?.should == false + client.should_not.closed? end end end diff --git a/ruby/spec/ruby/library/socket/unixsocket/shared/new.rb b/ruby/spec/ruby/library/socket/unixsocket/shared/new.rb index 76a4e1701..bfb7ed388 100644 --- a/ruby/spec/ruby/library/socket/unixsocket/shared/new.rb +++ b/ruby/spec/ruby/library/socket/unixsocket/shared/new.rb @@ -18,7 +18,7 @@ @client = UNIXSocket.send(@method, @path) @client.addr[0].should == "AF_UNIX" - @client.closed?.should == false + @client.should_not.closed? end end end diff --git a/ruby/spec/ruby/library/stringio/append_spec.rb b/ruby/spec/ruby/library/stringio/append_spec.rb index c46dc59ee..d0cf5550c 100644 --- a/ruby/spec/ruby/library/stringio/append_spec.rb +++ b/ruby/spec/ruby/library/stringio/append_spec.rb @@ -36,9 +36,11 @@ end end - it "does not taint self when the passed argument is tainted" do - (@io << "test".taint) - @io.tainted?.should be_false + ruby_version_is ""..."3.0" do + it "does not taint self when the passed argument is tainted" do + (@io << "test".taint) + @io.tainted?.should be_false + end end it "updates self's position" do diff --git a/ruby/spec/ruby/library/stringio/binmode_spec.rb b/ruby/spec/ruby/library/stringio/binmode_spec.rb index 5d9a8c41d..853d9c9bd 100644 --- a/ruby/spec/ruby/library/stringio/binmode_spec.rb +++ b/ruby/spec/ruby/library/stringio/binmode_spec.rb @@ -6,4 +6,18 @@ io = StringIO.new("example") io.binmode.should equal(io) end + + it "changes external encoding to BINARY" do + io = StringIO.new + io.external_encoding.should == Encoding.find('external') + io.binmode + io.external_encoding.should == Encoding::BINARY + end + + it "does not set internal encoding" do + io = StringIO.new + io.internal_encoding.should == nil + io.binmode + io.internal_encoding.should == nil + end end diff --git a/ruby/spec/ruby/library/stringio/bytes_spec.rb b/ruby/spec/ruby/library/stringio/bytes_spec.rb index 692fba997..4ef7a490a 100644 --- a/ruby/spec/ruby/library/stringio/bytes_spec.rb +++ b/ruby/spec/ruby/library/stringio/bytes_spec.rb @@ -2,10 +2,28 @@ require 'stringio' require_relative 'shared/each_byte' -describe "StringIO#bytes" do - it_behaves_like :stringio_each_byte, :bytes -end +ruby_version_is ''...'3.0' do + describe "StringIO#bytes" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :stringio_each_byte, :bytes + end + + describe "StringIO#bytes when self is not readable" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end -describe "StringIO#bytes when self is not readable" do - it_behaves_like :stringio_each_byte_not_readable, :bytes + it_behaves_like :stringio_each_byte_not_readable, :bytes + end end diff --git a/ruby/spec/ruby/library/stringio/chars_spec.rb b/ruby/spec/ruby/library/stringio/chars_spec.rb index 7dc55d4b3..58cba7763 100644 --- a/ruby/spec/ruby/library/stringio/chars_spec.rb +++ b/ruby/spec/ruby/library/stringio/chars_spec.rb @@ -2,10 +2,28 @@ require 'stringio' require_relative 'shared/each_char' -describe "StringIO#chars" do - it_behaves_like :stringio_each_char, :chars -end +ruby_version_is ''...'3.0' do + describe "StringIO#chars" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :stringio_each_char, :chars + end + + describe "StringIO#chars when self is not readable" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end -describe "StringIO#chars when self is not readable" do - it_behaves_like :stringio_each_char_not_readable, :chars + it_behaves_like :stringio_each_char_not_readable, :chars + end end diff --git a/ruby/spec/ruby/library/stringio/codepoints_spec.rb b/ruby/spec/ruby/library/stringio/codepoints_spec.rb index cc2e5d1b5..ceaadefc3 100644 --- a/ruby/spec/ruby/library/stringio/codepoints_spec.rb +++ b/ruby/spec/ruby/library/stringio/codepoints_spec.rb @@ -3,7 +3,17 @@ require_relative 'fixtures/classes' require_relative 'shared/codepoints' -# See redmine #1667 -describe "StringIO#codepoints" do - it_behaves_like :stringio_codepoints, :codepoints +ruby_version_is ''...'3.0' do + # See redmine #1667 + describe "StringIO#codepoints" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :stringio_codepoints, :codepoints + end end diff --git a/ruby/spec/ruby/library/stringio/each_char_spec.rb b/ruby/spec/ruby/library/stringio/each_char_spec.rb index 7305162ee..14b2f09a1 100644 --- a/ruby/spec/ruby/library/stringio/each_char_spec.rb +++ b/ruby/spec/ruby/library/stringio/each_char_spec.rb @@ -7,5 +7,5 @@ end describe "StringIO#each_char when self is not readable" do - it_behaves_like :stringio_each_char_not_readable, :chars + it_behaves_like :stringio_each_char_not_readable, :each_char end diff --git a/ruby/spec/ruby/library/stringio/each_codepoint_spec.rb b/ruby/spec/ruby/library/stringio/each_codepoint_spec.rb index 85aa34d9d..f18de22aa 100644 --- a/ruby/spec/ruby/library/stringio/each_codepoint_spec.rb +++ b/ruby/spec/ruby/library/stringio/each_codepoint_spec.rb @@ -5,5 +5,5 @@ # See redmine #1667 describe "StringIO#each_codepoint" do - it_behaves_like :stringio_codepoints, :codepoints + it_behaves_like :stringio_codepoints, :each_codepoint end diff --git a/ruby/spec/ruby/library/stringio/getpass_spec.rb b/ruby/spec/ruby/library/stringio/getpass_spec.rb new file mode 100644 index 000000000..60fc64f0c --- /dev/null +++ b/ruby/spec/ruby/library/stringio/getpass_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require 'stringio' + +# This method is added by io/console on require. +describe "StringIO#getpass" do + require 'io/console' + + it "is defined by io/console" do + StringIO.new("example").should.respond_to?(:getpass) + end +end diff --git a/ruby/spec/ruby/library/stringio/gets_spec.rb b/ruby/spec/ruby/library/stringio/gets_spec.rb index 69880672a..97429e6a2 100644 --- a/ruby/spec/ruby/library/stringio/gets_spec.rb +++ b/ruby/spec/ruby/library/stringio/gets_spec.rb @@ -76,12 +76,13 @@ @io.gets.should == "this is\n" begin - old_sep, $/ = $/, " " + old_sep = $/ + suppress_warning {$/ = " "} @io.gets.should == "an " @io.gets.should == "example\nfor " @io.gets.should == "StringIO#gets" ensure - $/ = old_sep + suppress_warning {$/ = old_sep} end end diff --git a/ruby/spec/ruby/library/stringio/initialize_spec.rb b/ruby/spec/ruby/library/stringio/initialize_spec.rb index 8aae47dac..1e8096e3b 100644 --- a/ruby/spec/ruby/library/stringio/initialize_spec.rb +++ b/ruby/spec/ruby/library/stringio/initialize_spec.rb @@ -110,9 +110,9 @@ io.closed_write?.should be_false end - it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do + it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do io = StringIO.allocate - -> { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class) + -> { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(FrozenError) end it "tries to convert the passed mode to a String using #to_str" do @@ -184,7 +184,7 @@ end end -describe "StringIO#initialize sets the encoding to" do +describe "StringIO#initialize sets" do before :each do @external = Encoding.default_external @internal = Encoding.default_internal @@ -197,16 +197,26 @@ Encoding.default_internal = @internal end - it "Encoding.default_external when passed no arguments" do + it "the encoding to Encoding.default_external when passed no arguments" do io = StringIO.new io.external_encoding.should == Encoding::ISO_8859_2 io.string.encoding.should == Encoding::ISO_8859_2 end - it "the same as the encoding of the String when passed a String" do + it "the encoding to the encoding of the String when passed a String" do s = ''.force_encoding(Encoding::EUC_JP) io = StringIO.new(s) - io.external_encoding.should == Encoding::EUC_JP io.string.encoding.should == Encoding::EUC_JP end + + guard_not -> { # [Bug #16497] + stringio_version = StringIO.const_defined?(:VERSION) ? StringIO::VERSION : "0.0.2" + version_is(stringio_version, "0.0.3"..."0.1.1") + } do + it "the #external_encoding to the encoding of the String when passed a String" do + s = ''.force_encoding(Encoding::EUC_JP) + io = StringIO.new(s) + io.external_encoding.should == Encoding::EUC_JP + end + end end diff --git a/ruby/spec/ruby/library/stringio/inspect_spec.rb b/ruby/spec/ruby/library/stringio/inspect_spec.rb new file mode 100644 index 000000000..7c02f8d36 --- /dev/null +++ b/ruby/spec/ruby/library/stringio/inspect_spec.rb @@ -0,0 +1,19 @@ +require_relative '../../spec_helper' +require "stringio" + +describe "StringIO#inspect" do + it "returns the same as #to_s" do + io = StringIO.new("example") + io.inspect.should == io.to_s + end + + it "does not include the contents" do + io = StringIO.new("contents") + io.inspect.should_not include("contents") + end + + it "uses the regular Object#inspect without any instance variable" do + io = StringIO.new("example") + io.inspect.should =~ /\A#\z/ + end +end diff --git a/ruby/spec/ruby/library/stringio/lines_spec.rb b/ruby/spec/ruby/library/stringio/lines_spec.rb index d9dd26c2e..42d11772a 100644 --- a/ruby/spec/ruby/library/stringio/lines_spec.rb +++ b/ruby/spec/ruby/library/stringio/lines_spec.rb @@ -2,18 +2,52 @@ require 'stringio' require_relative 'shared/each' -describe "StringIO#lines when passed a separator" do - it_behaves_like :stringio_each_separator, :lines -end +ruby_version_is ''...'3.0' do + describe "StringIO#lines when passed a separator" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end -describe "StringIO#lines when passed no arguments" do - it_behaves_like :stringio_each_no_arguments, :lines -end + after :each do + $VERBOSE = @verbose + end -describe "StringIO#lines when self is not readable" do - it_behaves_like :stringio_each_not_readable, :lines -end + it_behaves_like :stringio_each_separator, :lines + end + + describe "StringIO#lines when passed no arguments" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :stringio_each_no_arguments, :lines + end + + describe "StringIO#lines when self is not readable" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end + + it_behaves_like :stringio_each_not_readable, :lines + end + + describe "StringIO#lines when passed chomp" do + before :each do + @verbose, $VERBOSE = $VERBOSE, nil + end + + after :each do + $VERBOSE = @verbose + end -describe "StringIO#lines when passed chomp" do - it_behaves_like :stringio_each_chomp, :lines + it_behaves_like :stringio_each_chomp, :lines + end end diff --git a/ruby/spec/ruby/library/stringio/open_spec.rb b/ruby/spec/ruby/library/stringio/open_spec.rb index adb784c89..acab6e905 100644 --- a/ruby/spec/ruby/library/stringio/open_spec.rb +++ b/ruby/spec/ruby/library/stringio/open_spec.rb @@ -134,8 +134,8 @@ io.closed_write?.should be_false end - it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do - -> { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do + -> { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(FrozenError) end it "tries to convert the passed mode to a String using #to_str" do diff --git a/ruby/spec/ruby/library/stringio/print_spec.rb b/ruby/spec/ruby/library/stringio/print_spec.rb index d0f07d1e5..6ac643090 100644 --- a/ruby/spec/ruby/library/stringio/print_spec.rb +++ b/ruby/spec/ruby/library/stringio/print_spec.rb @@ -39,13 +39,14 @@ end it "honors the output record separator global" do - old_rs, $\ = $\, 'x' + old_rs = $\ + suppress_warning {$\ = 'x'} begin @io.print(5, 6, 7, 8) @io.string.should == '5678xle' ensure - $\ = old_rs + suppress_warning {$\ = old_rs} end end @@ -58,13 +59,14 @@ end it "correctly updates the current position when honoring the output record separator global" do - old_rs, $\ = $\, 'x' + old_rs = $\ + suppress_warning {$\ = 'x'} begin @io.print(5, 6, 7, 8) @io.pos.should eql(5) ensure - $\ = old_rs + suppress_warning {$\ = old_rs} end end end diff --git a/ruby/spec/ruby/library/stringio/printf_spec.rb b/ruby/spec/ruby/library/stringio/printf_spec.rb index f88ca1eb2..9dd1a3b41 100644 --- a/ruby/spec/ruby/library/stringio/printf_spec.rb +++ b/ruby/spec/ruby/library/stringio/printf_spec.rb @@ -32,7 +32,7 @@ describe "formatting" do it_behaves_like :kernel_sprintf, -> format, *args { - io = StringIO.new + io = StringIO.new(+"") io.printf(format, *args) io.string } diff --git a/ruby/spec/ruby/library/stringio/puts_spec.rb b/ruby/spec/ruby/library/stringio/puts_spec.rb index 2d3db25c5..a9f289a5a 100644 --- a/ruby/spec/ruby/library/stringio/puts_spec.rb +++ b/ruby/spec/ruby/library/stringio/puts_spec.rb @@ -30,11 +30,12 @@ it "does not honor the global output record separator $\\" do begin - old_rs, $\ = $\, "test" + old_rs = $\ + suppress_warning {$\ = "test"} @io.puts([1, 2, 3, 4]) @io.string.should == "1\n2\n3\n4\n" ensure - $\ = old_rs + suppress_warning {$\ = old_rs} end end @@ -68,11 +69,12 @@ it "does not honor the global output record separator $\\" do begin - old_rs, $\ = $\, "test" + old_rs = $\ + suppress_warning {$\ = "test"} @io.puts(1, 2, 3, 4) @io.string.should == "1\n2\n3\n4\n" ensure - $\ = old_rs + suppress_warning {$\ = old_rs} end end @@ -117,11 +119,12 @@ it "does not honor the global output record separator $\\" do begin - old_rs, $\ = $\, "test" + old_rs = $\ + suppress_warning {$\ = "test"} @io.puts @io.string.should == "\n" ensure - $\ = old_rs + suppress_warning {$\ = old_rs} end end end diff --git a/ruby/spec/ruby/library/stringio/readline_spec.rb b/ruby/spec/ruby/library/stringio/readline_spec.rb index 9af633472..94b67bc92 100644 --- a/ruby/spec/ruby/library/stringio/readline_spec.rb +++ b/ruby/spec/ruby/library/stringio/readline_spec.rb @@ -64,12 +64,13 @@ @io.readline.should == "this is\n" begin - old_sep, $/ = $/, " " + old_sep = $/ + suppress_warning {$/ = " "} @io.readline.should == "an " @io.readline.should == "example\nfor " @io.readline.should == "StringIO#readline" ensure - $/ = old_sep + suppress_warning {$/ = old_sep} end end diff --git a/ruby/spec/ruby/library/stringio/readlines_spec.rb b/ruby/spec/ruby/library/stringio/readlines_spec.rb index 7f9f9f584..4b007787e 100644 --- a/ruby/spec/ruby/library/stringio/readlines_spec.rb +++ b/ruby/spec/ruby/library/stringio/readlines_spec.rb @@ -51,10 +51,11 @@ it "returns an Array containing lines based on $/" do begin - old_sep, $/ = $/, " " + old_sep = $/; + suppress_warning {$/ = " "} @io.readlines.should == ["this ", "is\nan ", "example\nfor ", "StringIO#readlines"] ensure - $/ = old_sep + suppress_warning {$/ = old_sep} end end diff --git a/ruby/spec/ruby/library/stringio/reopen_spec.rb b/ruby/spec/ruby/library/stringio/reopen_spec.rb index 34e38a63b..6752cf997 100644 --- a/ruby/spec/ruby/library/stringio/reopen_spec.rb +++ b/ruby/spec/ruby/library/stringio/reopen_spec.rb @@ -23,13 +23,15 @@ @io.string.should == "reopened, another time" end - # NOTE: WEIRD! - it "does not taint self when the passed Object was tainted" do - @io.reopen("reopened".taint, IO::RDONLY) - @io.tainted?.should be_false - - @io.reopen("reopened".taint, IO::WRONLY) - @io.tainted?.should be_false + ruby_version_is ""..."3.0" do + # NOTE: WEIRD! + it "does not taint self when the passed Object was tainted" do + @io.reopen("reopened".taint, IO::RDONLY) + @io.tainted?.should be_false + + @io.reopen("reopened".taint, IO::WRONLY) + @io.tainted?.should be_false + end end it "tries to convert the passed Object to a String using #to_str" do @@ -48,8 +50,8 @@ -> { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES) end - it "raises a #{frozen_error_class} when trying to reopen self with a frozen String in truncate-mode" do - -> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(frozen_error_class) + it "raises a FrozenError when trying to reopen self with a frozen String in truncate-mode" do + -> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(FrozenError) end it "does not raise IOError when passed a frozen String in read-mode" do @@ -90,13 +92,15 @@ str.should == "" end - # NOTE: WEIRD! - it "does not taint self when the passed Object was tainted" do - @io.reopen("reopened".taint, "r") - @io.tainted?.should be_false + ruby_version_is ""..."3.0" do + # NOTE: WEIRD! + it "does not taint self when the passed Object was tainted" do + @io.reopen("reopened".taint, "r") + @io.tainted?.should be_false - @io.reopen("reopened".taint, "w") - @io.tainted?.should be_false + @io.reopen("reopened".taint, "w") + @io.tainted?.should be_false + end end it "tries to convert the passed Object to a String using #to_str" do @@ -160,10 +164,12 @@ @io.string.should == "reopened" end - # NOTE: WEIRD! - it "does not taint self when the passed Object was tainted" do - @io.reopen("reopened".taint) - @io.tainted?.should be_false + ruby_version_is ""..."3.0" do + # NOTE: WEIRD! + it "does not taint self when the passed Object was tainted" do + @io.reopen("reopened".taint) + @io.tainted?.should be_false + end end it "resets self's position to 0" do @@ -277,7 +283,7 @@ new_io = StringIO.new("tainted") new_io.taint @io.reopen(new_io) - @io.tainted?.should == true + @io.should.tainted? end end diff --git a/ruby/spec/ruby/library/stringio/shared/each.rb b/ruby/spec/ruby/library/stringio/shared/each.rb index c08d40344..14b0a013b 100644 --- a/ruby/spec/ruby/library/stringio/shared/each.rb +++ b/ruby/spec/ruby/library/stringio/shared/each.rb @@ -71,11 +71,12 @@ it "uses $/ as the default line separator" do seen = [] begin - old_rs, $/ = $/, " " + old_rs = $/ + suppress_warning {$/ = " "} @io.send(@method) {|s| seen << s } seen.should eql(["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"]) ensure - $/ = old_rs + suppress_warning {$/ = old_rs} end end diff --git a/ruby/spec/ruby/library/stringio/shared/read.rb b/ruby/spec/ruby/library/stringio/shared/read.rb index 15ce58ae6..c60677bba 100644 --- a/ruby/spec/ruby/library/stringio/shared/read.rb +++ b/ruby/spec/ruby/library/stringio/shared/read.rb @@ -27,8 +27,8 @@ -> { @io.send(@method, 7, Object.new) }.should raise_error(TypeError) end - it "raises a #{frozen_error_class} error when passed a frozen String as buffer" do - -> { @io.send(@method, 7, "".freeze) }.should raise_error(frozen_error_class) + it "raises a FrozenError error when passed a frozen String as buffer" do + -> { @io.send(@method, 7, "".freeze) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/library/stringio/shared/write.rb b/ruby/spec/ruby/library/stringio/shared/write.rb index 28683e3cb..080729217 100644 --- a/ruby/spec/ruby/library/stringio/shared/write.rb +++ b/ruby/spec/ruby/library/stringio/shared/write.rb @@ -52,9 +52,11 @@ end end - it "does not taint self when the passed argument is tainted" do - @io.send(@method, "test".taint) - @io.tainted?.should be_false + ruby_version_is ""..."3.0" do + it "does not taint self when the passed argument is tainted" do + @io.send(@method, "test".taint) + @io.tainted?.should be_false + end end end diff --git a/ruby/spec/ruby/library/stringio/ungetbyte_spec.rb b/ruby/spec/ruby/library/stringio/ungetbyte_spec.rb index 701463e62..87b27b837 100644 --- a/ruby/spec/ruby/library/stringio/ungetbyte_spec.rb +++ b/ruby/spec/ruby/library/stringio/ungetbyte_spec.rb @@ -1,6 +1,42 @@ +# frozen_string_literal: false require_relative '../../spec_helper' require 'stringio' describe "StringIO#ungetbyte" do - it "needs to be reviewed for spec completeness" + it "ungets a single byte from a string starting with a single byte character" do + str = 'This is a simple string.' + io = StringIO.new("#{str}") + c = io.getc + c.should == 'T' + io.ungetbyte(83) + io.string.should == 'Shis is a simple string.' + end + + it "ungets a single byte from a string in the middle of a multibyte character" do + str = "\u01a9" + io = StringIO.new(str) + b = io.getbyte + b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9 + io.ungetbyte(0xce) # First byte of UTF-8 encoding of \u03a9 + io.string.should == "\u03a9" + end + + it "constrains the value of a numeric argument to a single byte" do + str = 'This is a simple string.' + io = StringIO.new("#{str}") + c = io.getc + c.should == 'T' + io.ungetbyte(83 | 0xff00) + io.string.should == 'Shis is a simple string.' + end + + it "ungets the bytes of a string if given a string as an argument" do + str = "\u01a9" + io = StringIO.new(str) + b = io.getbyte + b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9 + io.ungetbyte("\u01a9") + io.string.bytes.should == [198, 169, 169] + end + end diff --git a/ruby/spec/ruby/library/stringscanner/append_spec.rb b/ruby/spec/ruby/library/stringscanner/append_spec.rb index 378c62e2b..fef5dcf2b 100644 --- a/ruby/spec/ruby/library/stringscanner/append_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/append_spec.rb @@ -6,6 +6,6 @@ it_behaves_like :strscan_concat, :<< end -describe "StringScanner#<< when passed a Fixnum" do +describe "StringScanner#<< when passed an Integer" do it_behaves_like :strscan_concat_fixnum, :<< end diff --git a/ruby/spec/ruby/library/stringscanner/check_spec.rb b/ruby/spec/ruby/library/stringscanner/check_spec.rb index c7f788f0b..21da78551 100644 --- a/ruby/spec/ruby/library/stringscanner/check_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/check_spec.rb @@ -13,4 +13,15 @@ @s.check(/is/).should == nil @s.matched.should == nil end + + ruby_version_is "2.7" do + it "treats String as the pattern itself" do + @s.check("This").should == "This" + @s.matched.should == "This" + @s.pos.should == 0 + @s.check(/is/).should == nil + @s.matched.should == nil + end + end + end diff --git a/ruby/spec/ruby/library/stringscanner/check_until_spec.rb b/ruby/spec/ruby/library/stringscanner/check_until_spec.rb index e92ae5a2e..ad222fd76 100644 --- a/ruby/spec/ruby/library/stringscanner/check_until_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/check_until_spec.rb @@ -12,4 +12,10 @@ @s.matched.should == "a" @s.check_until(/test/).should == "This is a test" end + + it "raises TypeError if given a String" do + -> { + @s.check_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/ruby/spec/ruby/library/stringscanner/concat_spec.rb b/ruby/spec/ruby/library/stringscanner/concat_spec.rb index 17a699dd2..4f790e250 100644 --- a/ruby/spec/ruby/library/stringscanner/concat_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/concat_spec.rb @@ -6,6 +6,6 @@ it_behaves_like :strscan_concat, :concat end -describe "StringScanner#concat when passed a Fixnum" do +describe "StringScanner#concat when passed an Integer" do it_behaves_like :strscan_concat_fixnum, :concat end diff --git a/ruby/spec/ruby/library/stringscanner/exist_spec.rb b/ruby/spec/ruby/library/stringscanner/exist_spec.rb index beafadc07..ff860a0d3 100644 --- a/ruby/spec/ruby/library/stringscanner/exist_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/exist_spec.rb @@ -21,4 +21,10 @@ @s.scan(/This is/) @s.exist?(/i/).should == nil end + + it "raises TypeError if given a String" do + -> { + @s.exist?('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/ruby/spec/ruby/library/stringscanner/matched_size_spec.rb b/ruby/spec/ruby/library/stringscanner/matched_size_spec.rb index a36bd3aaf..d9c338a07 100644 --- a/ruby/spec/ruby/library/stringscanner/matched_size_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/matched_size_spec.rb @@ -1,7 +1,24 @@ require_relative '../../spec_helper' -require_relative 'shared/matched_size' require 'strscan' describe "StringScanner#matched_size" do - it_behaves_like :strscan_matched_size, :matched_size + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the size of the most recent match" do + @s.check(/This/) + @s.matched_size.should == 4 + @s.matched_size.should == 4 + @s.scan(//) + @s.matched_size.should == 0 + end + + it "returns nil if there was no recent match" do + @s.matched_size.should == nil + @s.check(/\d+/) + @s.matched_size.should == nil + @s.terminate + @s.matched_size.should == nil + end end diff --git a/ruby/spec/ruby/library/stringscanner/scan_until_spec.rb b/ruby/spec/ruby/library/stringscanner/scan_until_spec.rb index 94239db50..6b7782572 100644 --- a/ruby/spec/ruby/library/stringscanner/scan_until_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/scan_until_spec.rb @@ -20,4 +20,10 @@ @s.scan(/T/) @s.scan_until(/^h/).should == "h" end + + it "raises TypeError if given a String" do + -> { + @s.scan_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/ruby/spec/ruby/library/stringscanner/search_full_spec.rb b/ruby/spec/ruby/library/stringscanner/search_full_spec.rb index da9067e01..7d2a714fa 100644 --- a/ruby/spec/ruby/library/stringscanner/search_full_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/search_full_spec.rb @@ -27,4 +27,10 @@ @s.search_full(/This/, true, true).should == "This" @s.pos.should == 4 end + + it "raises TypeError if given a String" do + -> { + @s.search_full('T', true, true) + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/ruby/spec/ruby/library/stringscanner/shared/matched_size.rb b/ruby/spec/ruby/library/stringscanner/shared/matched_size.rb deleted file mode 100644 index 92174733f..000000000 --- a/ruby/spec/ruby/library/stringscanner/shared/matched_size.rb +++ /dev/null @@ -1,21 +0,0 @@ -describe :strscan_matched_size, shared: true do - before :each do - @s = StringScanner.new("This is a test") - end - - it "returns the size of the most recent match" do - @s.check(/This/) - @s.send(@method).should == 4 - @s.send(@method).should == 4 - @s.scan(//) - @s.send(@method).should == 0 - end - - it "returns nil if there was no recent match" do - @s.send(@method).should == nil - @s.check(/\d+/) - @s.send(@method).should == nil - @s.terminate - @s.send(@method).should == nil - end -end diff --git a/ruby/spec/ruby/library/stringscanner/size_spec.rb b/ruby/spec/ruby/library/stringscanner/size_spec.rb new file mode 100644 index 000000000..3e475489e --- /dev/null +++ b/ruby/spec/ruby/library/stringscanner/size_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#size" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of captures groups of the last match" do + @s.scan(/(.)(.)(.)/) + @s.size.should == 4 + end + + it "returns nil if there is no last match" do + @s.size.should == nil + end +end diff --git a/ruby/spec/ruby/library/stringscanner/skip_until_spec.rb b/ruby/spec/ruby/library/stringscanner/skip_until_spec.rb index 73eb91b8a..7b56f13e4 100644 --- a/ruby/spec/ruby/library/stringscanner/skip_until_spec.rb +++ b/ruby/spec/ruby/library/stringscanner/skip_until_spec.rb @@ -15,4 +15,10 @@ it "returns nil if no match was found" do @s.skip_until(/d+/).should == nil end + + it "raises TypeError if given a String" do + -> { + @s.skip_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/ruby/spec/ruby/library/syslog/close_spec.rb b/ruby/spec/ruby/library/syslog/close_spec.rb index 8186ecf12..8c3b67c05 100644 --- a/ruby/spec/ruby/library/syslog/close_spec.rb +++ b/ruby/spec/ruby/library/syslog/close_spec.rb @@ -30,7 +30,7 @@ -> { Syslog.open { |s| s.close } }.should raise_error(RuntimeError) - Syslog.opened?.should == false + Syslog.should_not.opened? end it "sets the identity to nil" do diff --git a/ruby/spec/ruby/library/syslog/ident_spec.rb b/ruby/spec/ruby/library/syslog/ident_spec.rb index e8345ebb4..3b0832714 100644 --- a/ruby/spec/ruby/library/syslog/ident_spec.rb +++ b/ruby/spec/ruby/library/syslog/ident_spec.rb @@ -21,7 +21,7 @@ end it "returns nil if the log is closed" do - Syslog.opened?.should == false + Syslog.should_not.opened? Syslog.ident.should == nil end diff --git a/ruby/spec/ruby/library/syslog/log_spec.rb b/ruby/spec/ruby/library/syslog/log_spec.rb index ee62d484a..8589fb1f7 100644 --- a/ruby/spec/ruby/library/syslog/log_spec.rb +++ b/ruby/spec/ruby/library/syslog/log_spec.rb @@ -4,7 +4,7 @@ require 'syslog' describe "Syslog.log" do - platform_is_not :windows, :darwin, :solaris, :aix do + platform_is_not :windows, :darwin, :solaris, :aix, :android do before :each do Syslog.opened?.should be_false @@ -20,7 +20,7 @@ s.log(Syslog::LOG_ALERT, "Hello") s.log(Syslog::LOG_CRIT, "World") end - }.should output_to_fd("rubyspec: Hello\nrubyspec: World\n", $stderr) + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\nrubyspec(?::| \d+ - -) World\n\z/, $stderr) end it "accepts undefined priorities" do @@ -29,7 +29,7 @@ s.log(1337, "Hello") end # use a regex since it'll output unknown facility/priority messages - }.should output_to_fd(/rubyspec: Hello/, $stderr) + }.should output_to_fd(/rubyspec(?::| \d+ - -) Hello\n\z/, $stderr) end it "fails with TypeError on nil log messages" do @@ -49,7 +49,7 @@ Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| s.log(Syslog::LOG_ALERT, "%s x %d", "chunky bacon", 2) end - }.should output_to_fd("rubyspec: chunky bacon x 2\n", $stderr) + }.should output_to_fd(/rubyspec(?::| \d+ - -) chunky bacon x 2\n\z/, $stderr) end end end diff --git a/ruby/spec/ruby/library/syslog/mask_spec.rb b/ruby/spec/ruby/library/syslog/mask_spec.rb index 6581f6a75..b3f1250b2 100644 --- a/ruby/spec/ruby/library/syslog/mask_spec.rb +++ b/ruby/spec/ruby/library/syslog/mask_spec.rb @@ -32,7 +32,7 @@ end it "returns nil if the log is closed" do - Syslog.opened?.should == false + Syslog.should_not.opened? Syslog.mask.should == nil end diff --git a/ruby/spec/ruby/library/syslog/shared/log.rb b/ruby/spec/ruby/library/syslog/shared/log.rb index b19c2eae0..12e4ea836 100644 --- a/ruby/spec/ruby/library/syslog/shared/log.rb +++ b/ruby/spec/ruby/library/syslog/shared/log.rb @@ -1,5 +1,5 @@ describe :syslog_log, shared: true do - platform_is_not :windows, :darwin, :solaris, :aix do + platform_is_not :windows, :darwin, :solaris, :aix, :android do before :each do Syslog.opened?.should be_false end @@ -13,7 +13,7 @@ Syslog.open("rubyspec", Syslog::LOG_PERROR) do Syslog.send(@method, "Hello") end - }.should output_to_fd("rubyspec: Hello\n", $stderr) + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\n\z/, $stderr) end it "accepts sprintf arguments" do @@ -22,19 +22,18 @@ Syslog.send(@method, "Hello %s", "world") Syslog.send(@method, "%d dogs", 2) end - }.should output_to_fd("rubyspec: Hello world\nrubyspec: 2 dogs\n", $stderr) + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello world\nrubyspec(?::| \d+ - -) 2 dogs\n\z/, $stderr) end it "works as an alias for Syslog.log" do level = Syslog.const_get "LOG_#{@method.to_s.upcase}" - response = "rubyspec: Hello\n" -> { Syslog.open("rubyspec", Syslog::LOG_PERROR) do Syslog.send(@method, "Hello") Syslog.log(level, "Hello") end # make sure the same thing is written to $stderr. - }.should output_to_fd(response * 2, $stderr) + }.should output_to_fd(/\A(?:rubyspec(?::| \d+ - -) Hello\n){2}\z/, $stderr) end end end diff --git a/ruby/spec/ruby/library/timeout/timeout_spec.rb b/ruby/spec/ruby/library/timeout/timeout_spec.rb index a9a60fdeb..584b38d8e 100644 --- a/ruby/spec/ruby/library/timeout/timeout_spec.rb +++ b/ruby/spec/ruby/library/timeout/timeout_spec.rb @@ -18,6 +18,22 @@ end.should raise_error(StandardError) end + it "raises specified error type with specified message when it times out" do + -> do + Timeout.timeout(1, StandardError, "foobar") do + sleep + end + end.should raise_error(StandardError, "foobar") + end + + it "raises specified error type with a default message when it times out if message is nil" do + -> do + Timeout.timeout(1, StandardError, nil) do + sleep + end + end.should raise_error(StandardError, "execution expired") + end + it "returns back the last value in the block" do Timeout.timeout(1) do 42 diff --git a/ruby/spec/ruby/library/weakref/fixtures/classes.rb b/ruby/spec/ruby/library/weakref/fixtures/classes.rb index 560c58b04..041afab14 100644 --- a/ruby/spec/ruby/library/weakref/fixtures/classes.rb +++ b/ruby/spec/ruby/library/weakref/fixtures/classes.rb @@ -13,9 +13,11 @@ def self.make_weakref(level = 10) def self.make_dead_weakref weaks = [] weak = nil - 10_000.times do + 1000.times do weaks << make_weakref - GC.start + end + + 1000.times do GC.start break if weak = weaks.find { |w| !w.weakref_alive? } end diff --git a/ruby/spec/ruby/library/weakref/weakref_alive_spec.rb b/ruby/spec/ruby/library/weakref/weakref_alive_spec.rb index 173ea0148..1ebf9c1ee 100644 --- a/ruby/spec/ruby/library/weakref/weakref_alive_spec.rb +++ b/ruby/spec/ruby/library/weakref/weakref_alive_spec.rb @@ -5,7 +5,7 @@ it "returns true if the object is reachable" do obj = Object.new ref = WeakRef.new(obj) - ref.weakref_alive?.should == true + ref.weakref_alive?.should be_true end it "returns a falsy value if the object is no longer reachable" do diff --git a/ruby/spec/ruby/library/win32ole/win32ole_param/input_spec.rb b/ruby/spec/ruby/library/win32ole/win32ole_param/input_spec.rb index a0022fef1..e2a90daa5 100644 --- a/ruby/spec/ruby/library/win32ole/win32ole_param/input_spec.rb +++ b/ruby/spec/ruby/library/win32ole/win32ole_param/input_spec.rb @@ -13,7 +13,7 @@ end it "returns true for 3rd parameter of FileSystemObject's 'CopyFile' method" do - @param_overwritefiles.input?.should == true + @param_overwritefiles.should.input? end end diff --git a/ruby/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb b/ruby/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb index c15f64c2c..4f240b561 100644 --- a/ruby/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb +++ b/ruby/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb @@ -9,7 +9,7 @@ @var = ole_type.variables[0] end - it "returns a Integer" do + it "returns an Integer" do # according to doc, this could return nil @var.value.should be_kind_of Integer end diff --git a/ruby/spec/ruby/library/yaml/add_builtin_type_spec.rb b/ruby/spec/ruby/library/yaml/add_builtin_type_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/add_builtin_type_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/add_domain_type_spec.rb b/ruby/spec/ruby/library/yaml/add_domain_type_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/add_domain_type_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/add_private_type_spec.rb b/ruby/spec/ruby/library/yaml/add_private_type_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/add_private_type_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/add_ruby_type_spec.rb b/ruby/spec/ruby/library/yaml/add_ruby_type_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/add_ruby_type_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/detect_implicit_spec.rb b/ruby/spec/ruby/library/yaml/detect_implicit_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/detect_implicit_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/dump_spec.rb b/ruby/spec/ruby/library/yaml/dump_spec.rb index 5af794b7f..3107a8f51 100644 --- a/ruby/spec/ruby/library/yaml/dump_spec.rb +++ b/ruby/spec/ruby/library/yaml/dump_spec.rb @@ -37,7 +37,12 @@ it "dumps an OpenStruct" do require "ostruct" os = OpenStruct.new("age" => 20, "name" => "John") - YAML.dump(os).should match_yaml("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n") + yaml_dump = YAML.dump(os) + + [ + "--- !ruby/object:OpenStruct\nage: 20\nname: John\n", + "--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n", + ].should.include?(yaml_dump) end it "dumps a File without any state" do diff --git a/ruby/spec/ruby/library/yaml/each_node_spec.rb b/ruby/spec/ruby/library/yaml/each_node_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/each_node_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/emitter_spec.rb b/ruby/spec/ruby/library/yaml/emitter_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/emitter_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/fixtures/common.rb b/ruby/spec/ruby/library/yaml/fixtures/common.rb index 1d868806f..f7fb4037e 100644 --- a/ruby/spec/ruby/library/yaml/fixtures/common.rb +++ b/ruby/spec/ruby/library/yaml/fixtures/common.rb @@ -1,9 +1,3 @@ -begin - require 'syck' -rescue LoadError - # do nothing -end - require 'yaml' $test_file = tmp("yaml_test_file") diff --git a/ruby/spec/ruby/library/yaml/generic_parser_spec.rb b/ruby/spec/ruby/library/yaml/generic_parser_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/generic_parser_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/load_documents_spec.rb b/ruby/spec/ruby/library/yaml/load_documents_spec.rb deleted file mode 100644 index 27edbcaa8..000000000 --- a/ruby/spec/ruby/library/yaml/load_documents_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' -require_relative 'fixtures/strings' -require_relative 'shared/each_document' - -ruby_version_is ''...'2.5' do - describe "YAML.load_documents" do - it_behaves_like :yaml_each_document, :load_documents - end -end diff --git a/ruby/spec/ruby/library/yaml/load_spec.rb b/ruby/spec/ruby/library/yaml/load_spec.rb index 0b6bef2da..56700a85f 100644 --- a/ruby/spec/ruby/library/yaml/load_spec.rb +++ b/ruby/spec/ruby/library/yaml/load_spec.rb @@ -1,137 +1,10 @@ require_relative '../../spec_helper' -require_relative 'fixtures/common' -require_relative 'fixtures/strings' +require_relative 'shared/load' describe "YAML.load" do - after :each do - rm_r $test_file - end - - it "returns a document from current io stream when io provided" do - File.open($test_file, 'w') do |io| - YAML.dump( ['badger', 'elephant', 'tiger'], io ) - end - File.open($test_file) { |yf| YAML.load( yf ) }.should == ['badger', 'elephant', 'tiger'] - end - - it "loads strings" do - strings = ["str", - " str", - "'str'", - "str", - " str", - "'str'", - "\"str\"", - "\n str", - "--- str", - "---\nstr", - "--- \nstr", - "--- \n str", - "--- 'str'" - ] - strings.each do |str| - YAML.load(str).should == "str" - end - end - - it "loads strings with chars from non-base Unicode plane" do - # We add these strings as bytes and force the encoding for safety - # as bugs in parsing unicode characters can obscure bugs in this - # area. - - yaml_and_strings = { - # "--- 🌵" => "🌵" - [45, 45, 45, 32, 240, 159, 140, 181] => - [240, 159, 140, 181], - # "--- 🌵 and some text" => "🌵 and some text" - [45, 45, 45, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => - [240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116], - # "--- Some text 🌵 and some text" => "Some text 🌵 and some text" - [45, 45, 45, 32, 83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => - [83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] - } - yaml_and_strings.each do |yaml, str| - YAML.load(yaml.pack("C*").force_encoding("UTF-8")).should == str.pack("C*").force_encoding("UTF-8") - end - end - - it "fails on invalid keys" do - if YAML.to_s == "Psych" - error = Psych::SyntaxError - else - error = ArgumentError - end - -> { YAML.load("key1: value\ninvalid_key") }.should raise_error(error) - end - - it "accepts symbols" do - YAML.load( "--- :locked" ).should == :locked - end - - it "accepts numbers" do - YAML.load("47").should == 47 - YAML.load("-1").should == -1 - end - - it "accepts collections" do - expected = ["a", "b", "c"] - YAML.load("--- \n- a\n- b\n- c\n").should == expected - YAML.load("--- [a, b, c]").should == expected - YAML.load("[a, b, c]").should == expected - end - - it "parses start markers" do - YAML.load("---\n").should == nil - YAML.load("--- ---\n").should == "---" - YAML.load("--- abc").should == "abc" - end - - it "works with block sequence shortcuts" do - block_seq = "- - - one\n - two\n - three" - YAML.load(block_seq).should == [[["one", "two", "three"]]] - end - - it "works on complex keys" do - require 'date' - expected = { - [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ], - [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), - Date.new( 2001, 8, 12 ), - Date.new( 2001, 8, 14 ) ] - } - YAML.load($complex_key_1).should == expected - end - - it "loads a symbol key that contains spaces" do - string = ":user name: This is the user name." - expected = { :"user name" => "This is the user name."} - YAML.load(string).should == expected - end - - describe "with iso8601 timestamp" do - it "computes the microseconds" do - [ [YAML.load("2011-03-22t23:32:11.2233+01:00"), 223300], - [YAML.load("2011-03-22t23:32:11.0099+01:00"), 9900], - [YAML.load("2011-03-22t23:32:11.000076+01:00"), 76] - ].should be_computed_by(:usec) - end - - it "rounds values smaller than 1 usec to 0 " do - YAML.load("2011-03-22t23:32:11.000000342222+01:00").usec.should == 0 - end - end - - it "loads an OpenStruct" do - require "ostruct" - os = OpenStruct.new("age" => 20, "name" => "John") - loaded = YAML.load("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n") - loaded.should == os - end + it_behaves_like :yaml_load_safe, :load - it "loads a File but raise an error when used as it is uninitialized" do - loaded = YAML.load("--- !ruby/object:File {}\n") - -> { - loaded.read(1) - }.should raise_error(IOError) + guard -> { Psych::VERSION < "4.0.0" } do + it_behaves_like :yaml_load_unsafe, :load end end diff --git a/ruby/spec/ruby/library/yaml/object_maker_spec.rb b/ruby/spec/ruby/library/yaml/object_maker_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/object_maker_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/parse_documents_spec.rb b/ruby/spec/ruby/library/yaml/parse_documents_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/parse_documents_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/parser_spec.rb b/ruby/spec/ruby/library/yaml/parser_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/parser_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/quick_emit_spec.rb b/ruby/spec/ruby/library/yaml/quick_emit_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/quick_emit_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/read_type_class_spec.rb b/ruby/spec/ruby/library/yaml/read_type_class_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/read_type_class_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/shared/load.rb b/ruby/spec/ruby/library/yaml/shared/load.rb new file mode 100644 index 000000000..185a5a60c --- /dev/null +++ b/ruby/spec/ruby/library/yaml/shared/load.rb @@ -0,0 +1,136 @@ +require_relative '../fixtures/common' +require_relative '../fixtures/strings' + +describe :yaml_load_safe, shared: true do + it "returns a document from current io stream when io provided" do + File.open($test_file, 'w') do |io| + YAML.dump( ['badger', 'elephant', 'tiger'], io ) + end + File.open($test_file) { |yf| YAML.send(@method, yf ) }.should == ['badger', 'elephant', 'tiger'] + ensure + rm_r $test_file + end + + it "loads strings" do + strings = ["str", + " str", + "'str'", + "str", + " str", + "'str'", + "\"str\"", + "\n str", + "--- str", + "---\nstr", + "--- \nstr", + "--- \n str", + "--- 'str'" + ] + strings.each do |str| + YAML.send(@method, str).should == "str" + end + end + + it "loads strings with chars from non-base Unicode plane" do + # We add these strings as bytes and force the encoding for safety + # as bugs in parsing unicode characters can obscure bugs in this + # area. + + yaml_and_strings = { + # "--- 🌵" => "🌵" + [45, 45, 45, 32, 240, 159, 140, 181] => + [240, 159, 140, 181], + # "--- 🌵 and some text" => "🌵 and some text" + [45, 45, 45, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => + [240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116], + # "--- Some text 🌵 and some text" => "Some text 🌵 and some text" + [45, 45, 45, 32, 83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => + [83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] + } + yaml_and_strings.each do |yaml, str| + YAML.send(@method, yaml.pack("C*").force_encoding("UTF-8")).should == str.pack("C*").force_encoding("UTF-8") + end + end + + it "fails on invalid keys" do + if YAML.to_s == "Psych" + error = Psych::SyntaxError + else + error = ArgumentError + end + -> { YAML.send(@method, "key1: value\ninvalid_key") }.should raise_error(error) + end + + it "accepts symbols" do + YAML.send(@method, "--- :locked" ).should == :locked + end + + it "accepts numbers" do + YAML.send(@method, "47").should == 47 + YAML.send(@method, "-1").should == -1 + end + + it "accepts collections" do + expected = ["a", "b", "c"] + YAML.send(@method, "--- \n- a\n- b\n- c\n").should == expected + YAML.send(@method, "--- [a, b, c]").should == expected + YAML.send(@method, "[a, b, c]").should == expected + end + + it "parses start markers" do + YAML.send(@method, "---\n").should == nil + YAML.send(@method, "--- ---\n").should == "---" + YAML.send(@method, "--- abc").should == "abc" + end + + it "works with block sequence shortcuts" do + block_seq = "- - - one\n - two\n - three" + YAML.send(@method, block_seq).should == [[["one", "two", "three"]]] + end + + it "loads a symbol key that contains spaces" do + string = ":user name: This is the user name." + expected = { :"user name" => "This is the user name."} + YAML.send(@method, string).should == expected + end +end + +describe :yaml_load_unsafe, shared: true do + it "works on complex keys" do + require 'date' + expected = { + [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ], + [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), + Date.new( 2001, 8, 12 ), + Date.new( 2001, 8, 14 ) ] + } + YAML.send(@method, $complex_key_1).should == expected + end + + describe "with iso8601 timestamp" do + it "computes the microseconds" do + [ [YAML.send(@method, "2011-03-22t23:32:11.2233+01:00"), 223300], + [YAML.send(@method, "2011-03-22t23:32:11.0099+01:00"), 9900], + [YAML.send(@method, "2011-03-22t23:32:11.000076+01:00"), 76] + ].should be_computed_by(:usec) + end + + it "rounds values smaller than 1 usec to 0 " do + YAML.send(@method, "2011-03-22t23:32:11.000000342222+01:00").usec.should == 0 + end + end + + it "loads an OpenStruct" do + require "ostruct" + os = OpenStruct.new("age" => 20, "name" => "John") + loaded = YAML.send(@method, "--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n") + loaded.should == os + end + + it "loads a File but raise an error when used as it is uninitialized" do + loaded = YAML.send(@method, "--- !ruby/object:File {}\n") + -> { + loaded.read(1) + }.should raise_error(IOError) + end +end diff --git a/ruby/spec/ruby/library/yaml/tagurize_spec.rb b/ruby/spec/ruby/library/yaml/tagurize_spec.rb deleted file mode 100644 index cc1b757ce..000000000 --- a/ruby/spec/ruby/library/yaml/tagurize_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' - -ruby_version_is ''...'2.5' do - describe "YAML.tagurize" do - it "converts a type_id to a taguri" do - YAML.tagurize('wtf').should == "tag:yaml.org,2002:wtf" - YAML.tagurize(1).should == 1 - end - end -end diff --git a/ruby/spec/ruby/library/yaml/transfer_spec.rb b/ruby/spec/ruby/library/yaml/transfer_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/transfer_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/try_implicit_spec.rb b/ruby/spec/ruby/library/yaml/try_implicit_spec.rb deleted file mode 100644 index 44c820940..000000000 --- a/ruby/spec/ruby/library/yaml/try_implicit_spec.rb +++ /dev/null @@ -1,2 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'fixtures/common' diff --git a/ruby/spec/ruby/library/yaml/unsafe_load_spec.rb b/ruby/spec/ruby/library/yaml/unsafe_load_spec.rb new file mode 100644 index 000000000..385cd2a6e --- /dev/null +++ b/ruby/spec/ruby/library/yaml/unsafe_load_spec.rb @@ -0,0 +1,9 @@ +require_relative '../../spec_helper' +require_relative 'shared/load' + +guard -> { Psych::VERSION >= "4.0.0" } do + describe "YAML.unsafe_load" do + it_behaves_like :yaml_load_safe, :unsafe_load + it_behaves_like :yaml_load_unsafe, :unsafe_load + end +end diff --git a/ruby/spec/ruby/library/zlib/adler32_spec.rb b/ruby/spec/ruby/library/zlib/adler32_spec.rb index 62240e2de..226aa1852 100644 --- a/ruby/spec/ruby/library/zlib/adler32_spec.rb +++ b/ruby/spec/ruby/library/zlib/adler32_spec.rb @@ -22,7 +22,7 @@ -> { Zlib.adler32(test_string, 2**128) }.should raise_error(RangeError) end - it "calculates the Adler checksum for string and initial Adler value for Bignums" do + it "calculates the Adler checksum for string and initial Adler value for Integers" do test_string = "This is a test string! How exciting!%?" Zlib.adler32(test_string, 2**30).should == 1137642779 end diff --git a/ruby/spec/ruby/library/zlib/crc32_spec.rb b/ruby/spec/ruby/library/zlib/crc32_spec.rb index 4c1d6ce2e..d5f5c199c 100644 --- a/ruby/spec/ruby/library/zlib/crc32_spec.rb +++ b/ruby/spec/ruby/library/zlib/crc32_spec.rb @@ -29,7 +29,7 @@ -> { Zlib.crc32(test_string, 2**128) }.should raise_error(RangeError) end - it "calculates the CRC checksum for string and initial CRC value for Bignums" do + it "calculates the CRC checksum for string and initial CRC value for Integers" do test_string = "This is a test string! How exciting!%?" # Zlib.crc32(test_string, -2**30).should == 277228695 Zlib.crc32(test_string, 2**30).should == 46597132 diff --git a/ruby/spec/ruby/library/zlib/gzipfile/close_spec.rb b/ruby/spec/ruby/library/zlib/gzipfile/close_spec.rb index 870870f2f..964b5ffb4 100644 --- a/ruby/spec/ruby/library/zlib/gzipfile/close_spec.rb +++ b/ruby/spec/ruby/library/zlib/gzipfile/close_spec.rb @@ -8,7 +8,7 @@ Zlib::GzipWriter.wrap io do |gzio| gzio.close - gzio.closed?.should == true + gzio.should.closed? -> { gzio.orig_name }.should \ raise_error(Zlib::GzipFile::Error, 'closed gzip stream') diff --git a/ruby/spec/ruby/library/zlib/gzipfile/closed_spec.rb b/ruby/spec/ruby/library/zlib/gzipfile/closed_spec.rb index b885add48..726f391b4 100644 --- a/ruby/spec/ruby/library/zlib/gzipfile/closed_spec.rb +++ b/ruby/spec/ruby/library/zlib/gzipfile/closed_spec.rb @@ -6,11 +6,11 @@ it "returns the closed status" do io = StringIO.new Zlib::GzipWriter.wrap io do |gzio| - gzio.closed?.should == false + gzio.should_not.closed? gzio.close - gzio.closed?.should == true + gzio.should.closed? end end end diff --git a/ruby/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb b/ruby/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb index 59a062290..63676a820 100644 --- a/ruby/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb +++ b/ruby/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb @@ -8,7 +8,7 @@ zs << [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*') zs.flush_next_out.should == 'foo' - zs.finished?.should == true + zs.should.finished? zs.flush_next_out.should == '' end end diff --git a/ruby/spec/ruby/optional/capi/README b/ruby/spec/ruby/optional/capi/README index 57b0c51f0..069ca3c10 100644 --- a/ruby/spec/ruby/optional/capi/README +++ b/ruby/spec/ruby/optional/capi/README @@ -8,9 +8,6 @@ specs: optional/capi/array_spec.rb 2. Put the C file containing the C functions for array_spec.rb in optional/capi/ext/array_spec.c -3. Add a '#define HAVE_RB_ARY_NEW 1' to rubyspec.h -4. Name the C extension class 'CApiArraySpecs'. -5. Name the C functions 'array_spec_rb_ary_new'. -6. Wrap the code in the optional/capi/ext/array_spec.c in - '#ifdef HAVE_RB_ARY_NEW' -7. Attach the C function to the class using the name 'rb_ary_new' +3. Name the C extension class 'CApiArraySpecs'. +4. Name the C functions 'array_spec_rb_ary_new'. +5. Attach the C function to the class using the name 'rb_ary_new' diff --git a/ruby/spec/ruby/optional/capi/array_spec.rb b/ruby/spec/ruby/optional/capi/array_spec.rb index cf65bc19b..8e90980c6 100644 --- a/ruby/spec/ruby/optional/capi/array_spec.rb +++ b/ruby/spec/ruby/optional/capi/array_spec.rb @@ -83,8 +83,8 @@ @s.rb_ary_cat([1, 2], 3, 4).should == [1, 2, 3, 4] end - it "raises a #{frozen_error_class} if the array is frozen" do - -> { @s.rb_ary_cat([].freeze, 1) }.should raise_error(frozen_error_class) + it "raises a FrozenError if the array is frozen" do + -> { @s.rb_ary_cat([].freeze, 1) }.should raise_error(FrozenError) end end @@ -130,8 +130,8 @@ @s.rb_ary_rotate([1, 2, 3, 4], -3).should == [2, 3, 4, 1] end - it "raises a #{frozen_error_class} if the array is frozen" do - -> { @s.rb_ary_rotate([].freeze, 1) }.should raise_error(frozen_error_class) + it "raises a FrozenError if the array is frozen" do + -> { @s.rb_ary_rotate([].freeze, 1) }.should raise_error(FrozenError) end end @@ -190,6 +190,22 @@ end end + describe "rb_ary_sort" do + it "returns a new sorted array" do + a = [2, 1, 3] + @s.rb_ary_sort(a).should == [1, 2, 3] + a.should == [2, 1, 3] + end + end + + describe "rb_ary_sort_bang" do + it "sorts the given array" do + a = [2, 1, 3] + @s.rb_ary_sort_bang(a).should == [1, 2, 3] + a.should == [1, 2, 3] + end + end + describe "rb_ary_store" do it "overwrites the element at the given position" do a = [1, 2, 3] @@ -214,9 +230,9 @@ a.should == [nil, nil, 7] end - it "raises a #{frozen_error_class} if the array is frozen" do + it "raises a FrozenError if the array is frozen" do a = [1, 2, 3].freeze - -> { @s.rb_ary_store(a, 1, 5) }.should raise_error(frozen_error_class) + -> { @s.rb_ary_store(a, 1, 5) }.should raise_error(FrozenError) end end @@ -272,6 +288,16 @@ end end + describe "RARRAY_ASET" do + # This macro does NOT do any bounds checking! + it "writes an element in the array" do + ary = [1, 2, 3] + @s.RARRAY_ASET(ary, 0, 0) + @s.RARRAY_ASET(ary, 2, 42) + ary.should == [0, 2, 42] + end + end + describe "rb_assoc_new" do it "returns an array containing the two elements" do @s.rb_assoc_new(1, 2).should == [1, 2] @@ -317,10 +343,10 @@ end end - describe "rb_iterate" do + describe "rb_block_call" do it "calls an callback function as a block passed to an method" do s = [1,2,3,4] - s2 = @s.rb_iterate(s) + s2 = @s.rb_block_call(s) s2.should == s @@ -331,7 +357,7 @@ it "calls a function with the other function available as a block" do h = {a: 1, b: 2} - @s.rb_iterate_each_pair(h).sort.should == [1,2] + @s.rb_block_call_each_pair(h).sort.should == [1,2] end it "calls a function which can yield into the original block" do @@ -345,7 +371,7 @@ def o.each yield 4 end - @s.rb_iterate_then_yield(o) { |x| s2 << x } + @s.rb_block_call_then_yield(o) { |x| s2 << x } s2.should == [1,2,3,4] end diff --git a/ruby/spec/ruby/optional/capi/basic_object_spec.rb b/ruby/spec/ruby/optional/capi/basic_object_spec.rb new file mode 100644 index 000000000..2922a421d --- /dev/null +++ b/ruby/spec/ruby/optional/capi/basic_object_spec.rb @@ -0,0 +1,24 @@ +require_relative 'spec_helper' + +load_extension("basic_object") + +describe "C-API basic object" do + before :each do + @s = CApiBasicObjectSpecs.new + end + + describe "RBASIC_CLASS" do + it "returns the class of an object" do + c = Class.new + o = c.new + @s.RBASIC_CLASS(o).should == c + end + + it "returns the singleton class" do + o = Object.new + @s.RBASIC_CLASS(o).should == Object + singleton_class = o.singleton_class + @s.RBASIC_CLASS(o).should == singleton_class + end + end +end diff --git a/ruby/spec/ruby/optional/capi/bignum_spec.rb b/ruby/spec/ruby/optional/capi/bignum_spec.rb index b20275b8f..cde929af2 100644 --- a/ruby/spec/ruby/optional/capi/bignum_spec.rb +++ b/ruby/spec/ruby/optional/capi/bignum_spec.rb @@ -187,14 +187,14 @@ def ensure_bignum(n) it "returns a Fixnum for a Fixnum input value" do val = @s.rb_dbl2big(2) - val.kind_of?(Fixnum).should == true + val.kind_of?(Integer).should == true val.should == 2 end it "returns a Fixnum for a Float input value" do val = @s.rb_dbl2big(2.5) - val.kind_of?(Fixnum).should == true + val.kind_of?(Integer).should == true val.should == 2 end @@ -202,7 +202,7 @@ def ensure_bignum(n) input = 219238102380912830988.5 # chosen by fair dice roll val = @s.rb_dbl2big(input) - val.kind_of?(Bignum).should == true + val.kind_of?(Integer).should == true # This value is based on the output of a simple C extension that uses # rb_dbl2big() to convert the above input value to a Bignum. diff --git a/ruby/spec/ruby/optional/capi/binding_spec.rb b/ruby/spec/ruby/optional/capi/binding_spec.rb new file mode 100644 index 000000000..966d650c4 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/binding_spec.rb @@ -0,0 +1,19 @@ +require_relative 'spec_helper' + +load_extension("binding") + +describe "CApiBindingSpecs" do + before :each do + @b = CApiBindingSpecs.new + end + + describe "Kernel#binding" do + it "gives the top-most Ruby binding when called from C" do + foo = 14 + b = @b.get_binding + b.local_variable_get(:foo).should == 14 + b.local_variable_set :foo, 12 + foo.should == 12 + end + end +end diff --git a/ruby/spec/ruby/optional/capi/class_spec.rb b/ruby/spec/ruby/optional/capi/class_spec.rb index 0b03fb9e6..a2d8b3e38 100644 --- a/ruby/spec/ruby/optional/capi/class_spec.rb +++ b/ruby/spec/ruby/optional/capi/class_spec.rb @@ -1,5 +1,6 @@ require_relative 'spec_helper' require_relative 'fixtures/class' +require_relative '../../core/module/fixtures/classes' load_extension("class") compile_extension("class_under_autoload") @@ -11,6 +12,7 @@ describe :rb_path_to_class, shared: true do it "returns a class or module from a scoped String" do @s.send(@method, "CApiClassSpecs::A::B").should equal(CApiClassSpecs::A::B) + @s.send(@method, "CApiClassSpecs::A::M").should equal(CApiClassSpecs::A::M) end it "resolves autoload constants" do @@ -26,7 +28,9 @@ end it "raises a TypeError if the constant is not a class or module" do - -> { @s.send(@method, "CApiClassSpecs::A::C") }.should raise_error(TypeError) + -> { + @s.send(@method, "CApiClassSpecs::A::C") + }.should raise_error(TypeError, 'CApiClassSpecs::A::C does not refer to class/module') end it "raises an ArgumentError even if a constant in the path exists on toplevel" do @@ -39,6 +43,69 @@ @s = CApiClassSpecs.new end + describe "rb_class_instance_methods" do + it "returns the public and protected methods of self and its ancestors" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic) + methods.should include(:protected_module, :public_module) + + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic, true) + methods.should include(:protected_module, :public_module) + end + + it "when passed false as a parameter, returns the instance methods of the class" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Child, false) + methods.should include(:protected_child, :public_child) + end + end + + describe "rb_class_public_instance_methods" do + it "returns a list of public methods in module and its ancestors" do + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild) + methods.should include(:public_3) + methods.should include(:public_2) + methods.should include(:public_1) + + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, true) + methods.should include(:public_3) + methods.should include(:public_2) + methods.should include(:public_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_protected_instance_methods" do + it "returns a list of protected methods in module and its ancestors" do + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild) + methods.should include(:protected_3) + methods.should include(:protected_2) + methods.should include(:protected_1) + + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild, true) + methods.should include(:protected_3) + methods.should include(:protected_2) + methods.should include(:protected_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_private_instance_methods" do + it "returns a list of private methods in module and its ancestors" do + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild).should == ModuleSpecs::CountsChild.private_instance_methods + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, true).should == ModuleSpecs::CountsChild.private_instance_methods + end + + it "when passed false as a parameter, should return only methods defined in that module" do + methods = @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, false) + methods.should == [:private_1] + end + end + describe "rb_class_new_instance" do it "allocates and initializes a new object" do o = @s.rb_class_new_instance(0, nil, CApiClassSpecs::Alloc) @@ -338,7 +405,7 @@ end describe "rb_class_new" do - it "returns an new subclass of the superclass" do + it "returns a new subclass of the superclass" do subclass = @s.rb_class_new(CApiClassSpecs::NewClass) CApiClassSpecs::NewClass.should be_ancestor_of(subclass) end diff --git a/ruby/spec/ruby/optional/capi/constants_spec.rb b/ruby/spec/ruby/optional/capi/constants_spec.rb index 11a328a91..172d10a78 100644 --- a/ruby/spec/ruby/optional/capi/constants_spec.rb +++ b/ruby/spec/ruby/optional/capi/constants_spec.rb @@ -11,24 +11,42 @@ @s.rb_cArray.should == Array end + specify "rb_cBasicObject references the BasicObject class" do + @s.rb_cBasicObject.should == BasicObject + end + + specify "rb_cBinding references the Binding class" do + @s.rb_cBinding.should == Binding + end + specify "rb_cClass references the Class class" do @s.rb_cClass.should == Class end + specify "rb_cComplex references the Complex class" do + @s.rb_cComplex.should == Complex + end + specify "rb_mComparable references the Comparable module" do @s.rb_mComparable.should == Comparable end - ruby_version_is ""..."2.5" do - specify "rb_cData references the Data class" do - @s.rb_cData.should == Data - end + specify "rb_cDir references the Dir class" do + @s.rb_cDir.should == Dir + end + + specify "rb_cEncoding references the Encoding class" do + @s.rb_cEncoding.should == Encoding end specify "rb_mEnumerable references the Enumerable module" do @s.rb_mEnumerable.should == Enumerable end + specify "rb_cEnumerator references the Enumerator class" do + @s.rb_cEnumerator.should == Enumerator + end + specify "rb_cFalseClass references the FalseClass class" do @s.rb_cFalseClass.should == FalseClass end @@ -37,10 +55,18 @@ @s.rb_cFile.should == File end + specify "rb_mFileTest references the FileTest module" do + @s.rb_mFileTest.should == FileTest + end + specify "rb_cFloat references the Float class" do @s.rb_cFloat.should == Float end + specify "rb_mGC references the GC module" do + @s.rb_mGC.should == GC + end + specify "rb_cHash references the Hash class" do @s.rb_cHash.should == Hash end @@ -57,10 +83,18 @@ @s.rb_mKernel.should == Kernel end + specify "rb_mMath references the Math module" do + @s.rb_mMath.should == Math + end + specify "rb_cMatch references the MatchData class" do @s.rb_cMatch.should == MatchData end + specify "rb_cMethod references the Method class" do + @s.rb_cMethod.should == Method + end + specify "rb_cModule references the Module class" do @s.rb_cModule.should == Module end @@ -77,14 +111,34 @@ @s.rb_cObject.should == Object end + specify "rb_cProc references the Proc class" do + @s.rb_cProc.should == Proc + end + + specify "rb_mProcess references the Process module" do + @s.rb_mProcess.should == Process + end + + specify "rb_cRandom references the Random class" do + @s.rb_cRandom.should == Random + end + specify "rb_cRange references the Range class" do @s.rb_cRange.should == Range end + specify "rb_cRational references the Rational class" do + @s.rb_cRational.should == Rational + end + specify "rb_cRegexp references the Regexp class" do @s.rb_cRegexp.should == Regexp end + specify "rb_cStat references the File::Stat class" do + @s.rb_cStat.should == File::Stat + end + specify "rb_cString references the String class" do @s.rb_cString.should == String end @@ -109,18 +163,9 @@ @s.rb_cTrueClass.should == TrueClass end - specify "rb_cProc references the Proc class" do - @s.rb_cProc.should == Proc - end - - specify "rb_cMethod references the Method class" do - @s.rb_cMethod.should == Method - end - - specify "rb_cDir references the Dir class" do - @s.rb_cDir.should == Dir + specify "rb_cUnboundMethod references the UnboundMethod class" do + @s.rb_cUnboundMethod.should == UnboundMethod end - end describe "C-API exception constant" do @@ -132,6 +177,14 @@ @s.rb_eArgError.should == ArgumentError end + specify "rb_eEncodingError references the EncodingError class" do + @s.rb_eEncodingError.should == EncodingError + end + + specify "rb_eEncCompatError references the Encoding::CompatibilityError" do + @s.rb_eEncCompatError.should == Encoding::CompatibilityError + end + specify "rb_eEOFError references the EOFError class" do @s.rb_eEOFError.should == EOFError end @@ -144,10 +197,20 @@ @s.rb_eException.should == Exception end + specify "rb_eFatal references the fatal class" do + fatal = @s.rb_eFatal + fatal.should be_kind_of(Class) + fatal.should < Exception + end + specify "rb_eFloatDomainError references the FloatDomainError class" do @s.rb_eFloatDomainError.should == FloatDomainError end + specify "rb_eFrozenError references the FrozenError class" do + @s.rb_eFrozenError.should == FrozenError + end + specify "rb_eIndexError references the IndexError class" do @s.rb_eIndexError.should == IndexError end @@ -160,6 +223,10 @@ @s.rb_eIOError.should == IOError end + specify "rb_eKeyError references the KeyError class" do + @s.rb_eKeyError.should == KeyError + end + specify "rb_eLoadError references the LoadError class" do @s.rb_eLoadError.should == LoadError end @@ -172,10 +239,6 @@ @s.rb_eMathDomainError.should == Math::DomainError end - specify "rb_eEncCompatError references the Encoding::CompatibilityError" do - @s.rb_eEncCompatError.should == Encoding::CompatibilityError - end - specify "rb_eNameError references the NameError class" do @s.rb_eNameError.should == NameError end @@ -220,6 +283,10 @@ @s.rb_eStandardError.should == StandardError end + specify "rb_eStopIteration references the StopIteration class" do + @s.rb_eStopIteration.should == StopIteration + end + specify "rb_eSyntaxError references the SyntaxError class" do @s.rb_eSyntaxError.should == SyntaxError end diff --git a/ruby/spec/ruby/optional/capi/data_spec.rb b/ruby/spec/ruby/optional/capi/data_spec.rb index c03b86367..18c769332 100644 --- a/ruby/spec/ruby/optional/capi/data_spec.rb +++ b/ruby/spec/ruby/optional/capi/data_spec.rb @@ -36,6 +36,13 @@ end end + describe "rb_check_type" do + it "does not raise an exception when checking data objects" do + a = @s.wrap_struct(1024) + @s.rb_check_type(a, a).should == true + end + end + describe "DATA_PTR" do it "returns the struct data" do a = @s.wrap_struct(1024) diff --git a/ruby/spec/ruby/optional/capi/debug_spec.rb b/ruby/spec/ruby/optional/capi/debug_spec.rb new file mode 100644 index 000000000..c8c91417d --- /dev/null +++ b/ruby/spec/ruby/optional/capi/debug_spec.rb @@ -0,0 +1,66 @@ +require_relative 'spec_helper' + +load_extension('debug') + +describe "C-API Debug function" do + before :each do + @o = CApiDebugSpecs.new + end + + describe "rb_debug_inspector_open" do + it "creates a debug context and calls the given callback" do + @o.rb_debug_inspector_open(42).should be_kind_of(Array) + @o.debug_spec_callback_data.should == 42 + end + end + + describe "rb_debug_inspector_frame_self_get" do + it "returns self" do + @o.rb_debug_inspector_frame_self_get(0).should == @o + end + end + + describe "rb_debug_inspector_frame_class_get" do + it "returns the frame class" do + @o.rb_debug_inspector_frame_class_get(0).should == CApiDebugSpecs + end + end + + describe "rb_debug_inspector_frame_binding_get" do + it "returns the current binding" do + a = "test" + b = @o.rb_debug_inspector_frame_binding_get(1) + b.should be_an_instance_of(Binding) + b.local_variable_get(:a).should == "test" + end + + it "matches the locations in rb_debug_inspector_backtrace_locations" do + frames = @o.rb_debug_inspector_open(42); + frames.each do |_s, _klass, binding, _iseq, backtrace_location| + if binding + "#{backtrace_location.path}:#{backtrace_location.lineno}".should == "#{binding.source_location[0]}:#{binding.source_location[1]}" + end + end + end + end + + describe "rb_debug_inspector_frame_iseq_get" do + it "returns an InstructionSequence" do + if defined?(RubyVM::InstructionSequence) + @o.rb_debug_inspector_frame_iseq_get(1).should be_an_instance_of(RubyVM::InstructionSequence) + else + @o.rb_debug_inspector_frame_iseq_get(1).should == nil + end + end + end + + describe "rb_debug_inspector_backtrace_locations" do + it "returns an array of Thread::Backtrace::Location" do + bts = @o.rb_debug_inspector_backtrace_locations + bts.should_not.empty? + bts.each { |bt| bt.should be_kind_of(Thread::Backtrace::Location) } + location = "#{__FILE__}:#{__LINE__ - 3}" + bts[1].to_s.should include(location) + end + end +end diff --git a/ruby/spec/ruby/optional/capi/encoding_spec.rb b/ruby/spec/ruby/optional/capi/encoding_spec.rb index 003edc966..66c2dd40d 100644 --- a/ruby/spec/ruby/optional/capi/encoding_spec.rb +++ b/ruby/spec/ruby/optional/capi/encoding_spec.rb @@ -31,13 +31,11 @@ result.first.should == result.last end - ruby_version_is "2.6" do - it "raises an ArgumentError for a non-encoding capable object" do - obj = Object.new - -> { - result = @s.send(@method, obj, 1) - }.should raise_error(ArgumentError, "cannot set encoding on non-encoding capable object") - end + it "raises an ArgumentError for a non-encoding capable object" do + obj = Object.new + -> { + result = @s.send(@method, obj, 1) + }.should raise_error(ArgumentError, "cannot set encoding on non-encoding capable object") end end @@ -48,13 +46,20 @@ @s = CApiEncodingSpecs.new end - ruby_version_is "2.6" do - describe "rb_enc_alias" do - it "creates an alias for an existing Encoding" do - name = "ZOMGWTFBBQ#{@n += 1}" - @s.rb_enc_alias(name, "UTF-8").should >= 0 - Encoding.find(name).name.should == "UTF-8" - end + describe "rb_enc_alias" do + it "creates an alias for an existing Encoding" do + name = "ZOMGWTFBBQ#{@n += 1}" + @s.rb_enc_alias(name, "UTF-8").should >= 0 + Encoding.find(name).name.should == "UTF-8" + end + end + + describe "rb_enc_codelen" do + it "returns the correct length for the given codepoint" do + @s.rb_enc_codelen(0x24, Encoding::UTF_8).should == 1 + @s.rb_enc_codelen(0xA2, Encoding::UTF_8).should == 2 + @s.rb_enc_codelen(0x20AC, Encoding::UTF_8).should == 3 + @s.rb_enc_codelen(0x24B62, Encoding::UTF_8).should == 4 end end @@ -82,12 +87,66 @@ end end + describe "rb_enc_isalnum" do + it "returns non-zero for alpha-numeric characters" do + @s.rb_enc_isalnum("a".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isalnum("2".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isalnum("a".ord, Encoding::UTF_8).should == true + @s.rb_enc_isalnum("2".ord, Encoding::UTF_8).should == true + @s.rb_enc_isalnum("é".encode(Encoding::ISO_8859_1).ord, Encoding::ISO_8859_1).should == true + end + + it "returns zero for non alpha-numeric characters" do + @s.rb_enc_isalnum("-".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isalnum(" ".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isalnum("-".ord, Encoding::UTF_8).should == false + @s.rb_enc_isalnum(" ".ord, Encoding::UTF_8).should == false + end + end + + describe "rb_enc_isspace" do + it "returns non-zero for space characters" do + @s.rb_enc_isspace(" ".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isspace(" ".ord, Encoding::UTF_8).should == true + end + + it "returns zero for non space characters" do + @s.rb_enc_isspace("-".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("A".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("3".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("-".ord, Encoding::UTF_8).should == false + @s.rb_enc_isspace("A".ord, Encoding::UTF_8).should == false + @s.rb_enc_isspace("3".ord, Encoding::UTF_8).should == false + end + end + describe "rb_enc_from_index" do it "returns an Encoding" do @s.rb_enc_from_index(0).should be_an_instance_of(String) end end + describe "rb_enc_mbc_to_codepoint" do + it "returns the correct codepoint for the given character and size" do + @s.rb_enc_mbc_to_codepoint("é", 2).should == 0x00E9 + @s.rb_enc_mbc_to_codepoint("éa", 2).should == 0x00E9 + @s.rb_enc_mbc_to_codepoint("éa", 1).should == 0xC3 + @s.rb_enc_mbc_to_codepoint("éa", 3).should == 0x00E9 + end + end + + describe "rb_enc_mbcput" do + it "writes the correct bytes to the buffer" do + @s.rb_enc_mbcput(0x24, Encoding::UTF_8).should == "$" + @s.rb_enc_mbcput(0xA2, Encoding::UTF_8).should == "¢" + @s.rb_enc_mbcput(0x20AC, Encoding::UTF_8).should == "€" + @s.rb_enc_mbcput(0x24B62, Encoding::UTF_8).should == "𤭢" + + @s.rb_enc_mbcput(0x24, Encoding::UTF_16BE).bytes.should == [0, 0x24] + @s.rb_enc_mbcput(0x24B62, Encoding::UTF_16LE).bytes.should == [82, 216, 98, 223] + end + end + describe "rb_usascii_encoding" do it "returns the encoding for Encoding::US_ASCII" do @s.rb_usascii_encoding.should == "US-ASCII" @@ -131,6 +190,29 @@ end end + describe "rb_enc_precise_mbclen" do + it "returns the correct length for single byte characters" do + @s.rb_enc_precise_mbclen("hello", 7).should == 1 + @s.rb_enc_precise_mbclen("hello", 5).should == 1 + @s.rb_enc_precise_mbclen("hello", 1).should == 1 + @s.rb_enc_precise_mbclen("hello", 0).should == -2 + @s.rb_enc_precise_mbclen("hello", -1).should == -2 + @s.rb_enc_precise_mbclen("hello", -5).should == -2 + end + + it "returns the correct length for multi-byte characters" do + @s.rb_enc_precise_mbclen("ésumé", 2).should == 2 + @s.rb_enc_precise_mbclen("ésumé", 3).should == 2 + @s.rb_enc_precise_mbclen("ésumé", 0).should == -2 + @s.rb_enc_precise_mbclen("ésumé", 1).should == -2 + @s.rb_enc_precise_mbclen("ã‚", 20).should == 3 + @s.rb_enc_precise_mbclen("ã‚", 3).should == 3 + @s.rb_enc_precise_mbclen("ã‚", 2).should == -2 + @s.rb_enc_precise_mbclen("ã‚", 0).should == -2 + @s.rb_enc_precise_mbclen("ã‚", -2).should == -2 + end + end + describe "rb_obj_encoding" do it "returns the encoding associated with an object" do str = "abc".encode Encoding::BINARY @@ -153,11 +235,9 @@ @s.rb_enc_get_index(1).should == -1 end - ruby_version_is "2.6" do - it "returns -1 for an object without an encoding" do - obj = Object.new - @s.rb_enc_get_index(obj).should == -1 - end + it "returns -1 for an object without an encoding" do + obj = Object.new + @s.rb_enc_get_index(obj).should == -1 end end @@ -173,6 +253,26 @@ end end + describe "rb_enc_str_new_cstr" do + it "creates a new ruby string from a c string literal" do + result = @s.rb_enc_str_new_cstr_constant(Encoding::US_ASCII) + result.should == "test string literal" + result.encoding.should == Encoding::US_ASCII + end + + it "creates a new ruby string from a c string variable" do + result = @s.rb_enc_str_new_cstr("test string", Encoding::US_ASCII) + result.should == "test string" + result.encoding.should == Encoding::US_ASCII + end + + it "when null encoding is given with a c string literal, it creates a new ruby string with ASCII_8BIT encoding" do + result = @s.rb_enc_str_new_cstr_constant(nil) + result.should == "test string literal" + result.encoding.should == Encoding::ASCII_8BIT + end + end + describe "rb_enc_str_coderange" do describe "when the encoding is BINARY" do it "returns ENC_CODERANGE_7BIT if there are no high bits set" do @@ -217,6 +317,17 @@ end end + describe "MBCLEN_CHARFOUND_P" do + it "returns non-zero for valid character" do + @s.MBCLEN_CHARFOUND_P("a".ord).should == 1 + end + + it "returns zero for invalid characters" do + @s.MBCLEN_CHARFOUND_P(0).should == 0 + @s.MBCLEN_CHARFOUND_P(-1).should == 0 + end + end + describe "ENCODING_GET" do it_behaves_like :rb_enc_get_index, :ENCODING_GET end @@ -257,6 +368,14 @@ @s.rb_to_encoding(obj).should == "UTF-8" end + + describe "when the rb_encoding struct is stored in native memory" do + it "can still read the name of the encoding" do + address = @s.rb_to_encoding_native_store(Encoding::UTF_8) + address.should be_kind_of(Integer) + @s.rb_to_encoding_native_name(address).should == "UTF-8" + end + end end describe "rb_to_encoding_index" do @@ -312,7 +431,7 @@ end it "sets the encoding of a Regexp to that of the second argument" do - @s.rb_enc_copy(/regexp/, @obj).encoding.should == Encoding::US_ASCII + @s.rb_enc_copy(/regexp/.dup, @obj).encoding.should == Encoding::US_ASCII end end @@ -363,7 +482,7 @@ end it "sets the encoding of a Regexp to the encoding" do - @s.rb_enc_associate(/regexp/, "BINARY").encoding.should == Encoding::BINARY + @s.rb_enc_associate(/regexp/.dup, "BINARY").encoding.should == Encoding::BINARY end it "sets the encoding of a String to a default when the encoding is NULL" do @@ -380,7 +499,7 @@ it "sets the encoding of a Regexp to the encoding" do index = @s.rb_enc_find_index("UTF-8") - enc = @s.rb_enc_associate_index(/regexp/, index).encoding + enc = @s.rb_enc_associate_index(/regexp/.dup, index).encoding enc.should == Encoding::UTF_8 end @@ -479,4 +598,48 @@ length.should == 4 end end + + describe "rb_enc_str_asciionly_p" do + it "returns true for an ASCII string" do + @s.rb_enc_str_asciionly_p("hello").should be_true + end + + it "returns false for a non-ASCII string" do + @s.rb_enc_str_asciionly_p("hüllo").should be_false + end + end + + describe "rb_uv_to_utf8" do + it 'converts a Unicode codepoint to a UTF-8 C string' do + str = ' ' * 6 + { + 0 => "\x01", + 0x7f => "\xC2\x80", + 0x7ff => "\xE0\xA0\x80", + 0xffff => "\xF0\x90\x80\x80", + 0x1fffff => "\xF8\x88\x80\x80\x80", + 0x3ffffff => "\xFC\x84\x80\x80\x80\x80", + }.each do |num, result| + len = @s.rb_uv_to_utf8(str, num + 1) + str[0..len-1].should == result + end + end + end + + describe "ONIGENC_MBC_CASE_FOLD" do + it "returns the correct case fold for the given string" do + @s.ONIGENC_MBC_CASE_FOLD("lower").should == ["l", 1] + @s.ONIGENC_MBC_CASE_FOLD("Upper").should == ["u", 1] + end + + it "works with other encodings" do + @s.ONIGENC_MBC_CASE_FOLD("lower".force_encoding("binary")).should == ["l", 1] + @s.ONIGENC_MBC_CASE_FOLD("Upper".force_encoding("binary")).should == ["u", 1] + @s.ONIGENC_MBC_CASE_FOLD("É").should == ["é", 2] + + str, length = @s.ONIGENC_MBC_CASE_FOLD('$'.encode(Encoding::UTF_16BE)) + length.should == 2 + str.bytes.should == [0, 0x24] + end + end end diff --git a/ruby/spec/ruby/optional/capi/exception_spec.rb b/ruby/spec/ruby/optional/capi/exception_spec.rb index 62d7d3706..b0a8a2860 100644 --- a/ruby/spec/ruby/optional/capi/exception_spec.rb +++ b/ruby/spec/ruby/optional/capi/exception_spec.rb @@ -36,6 +36,50 @@ runtime_error.set_backtrace [] -> { @s.rb_exc_raise(runtime_error) }.should raise_error(RuntimeError, '42') end + + it "sets $! to the raised exception when not rescuing from an another exception" do + runtime_error = RuntimeError.new '42' + runtime_error.set_backtrace [] + begin + @s.rb_exc_raise(runtime_error) + rescue + $!.should == runtime_error + end + end + + it "sets $! to the raised exception when $! when rescuing from an another exception" do + runtime_error = RuntimeError.new '42' + runtime_error.set_backtrace [] + begin + begin + raise StandardError + rescue + @s.rb_exc_raise(runtime_error) + end + rescue + $!.should == runtime_error + end + end + end + + describe "rb_errinfo" do + it "is cleared when entering a C method" do + begin + raise StandardError + rescue + $!.class.should == StandardError + @s.rb_errinfo().should == nil + end + end + + it "does not clear $! in the calling method" do + begin + raise StandardError + rescue + @s.rb_errinfo() + $!.class.should == StandardError + end + end end describe "rb_set_errinfo" do @@ -55,4 +99,49 @@ -> { @s.rb_set_errinfo("error") }.should raise_error(TypeError) end end + + describe "rb_make_exception" do + it "returns a RuntimeError when given a String argument" do + e = @s.rb_make_exception(["Message"]) + e.class.should == RuntimeError + e.message.should == "Message" + end + + it "returns the exception when given an Exception argument" do + exc = Exception.new + e = @s.rb_make_exception([exc]) + e.should == exc + end + + it "returns the exception with the given class and message" do + e = @s.rb_make_exception([Exception, "Message"]) + e.class.should == Exception + e.message.should == "Message" + end + + it "returns the exception with the given class, message, and backtrace" do + e = @s.rb_make_exception([Exception, "Message", ["backtrace 1"]]) + e.class.should == Exception + e.message.should == "Message" + e.backtrace.should == ["backtrace 1"] + end + + it "raises a TypeError for incorrect types" do + -> { @s.rb_make_exception([nil]) }.should raise_error(TypeError) + -> { @s.rb_make_exception([Object.new]) }.should raise_error(TypeError) + obj = Object.new + def obj.exception + "not exception type" + end + -> { @s.rb_make_exception([obj]) }.should raise_error(TypeError) + end + + it "raises an ArgumentError for too many arguments" do + -> { @s.rb_make_exception([Exception, "Message", ["backtrace 1"], "extra"]) }.should raise_error(ArgumentError) + end + + it "returns nil for empty arguments" do + @s.rb_make_exception([]).should == nil + end + end end diff --git a/ruby/spec/ruby/optional/capi/ext/array_spec.c b/ruby/spec/ruby/optional/capi/ext/array_spec.c index 454cf0330..938623981 100644 --- a/ruby/spec/ruby/optional/capi/ext/array_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/array_spec.c @@ -54,6 +54,11 @@ static VALUE array_spec_RARRAY_AREF(VALUE self, VALUE array, VALUE index) { return RARRAY_AREF(array, FIX2INT(index)); } +static VALUE array_spec_RARRAY_ASET(VALUE self, VALUE array, VALUE index, VALUE value) { + RARRAY_ASET(array, FIX2INT(index), value); + return value; +} + static VALUE array_spec_rb_ary_aref(int argc, VALUE *argv, VALUE self) { VALUE ary, args; rb_scan_args(argc, argv, "1*", &ary, &args); @@ -157,6 +162,14 @@ static VALUE array_spec_rb_ary_shift(VALUE self, VALUE array) { return rb_ary_shift(array); } +static VALUE array_spec_rb_ary_sort(VALUE self, VALUE array) { + return rb_ary_sort(array); +} + +static VALUE array_spec_rb_ary_sort_bang(VALUE self, VALUE array) { + return rb_ary_sort_bang(array); +} + static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) { rb_ary_store(array, FIX2INT(offset), value); @@ -183,10 +196,10 @@ static VALUE copy_ary(RB_BLOCK_CALL_FUNC_ARGLIST(el, new_ary)) { return rb_ary_push(new_ary, el); } -static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) { +static VALUE array_spec_rb_block_call(VALUE self, VALUE ary) { VALUE new_ary = rb_ary_new(); - rb_iterate(rb_each, ary, copy_ary, new_ary); + rb_block_call(ary, rb_intern("each"), 0, 0, copy_ary, new_ary); return new_ary; } @@ -195,14 +208,10 @@ static VALUE sub_pair(RB_BLOCK_CALL_FUNC_ARGLIST(el, holder)) { return rb_ary_push(holder, rb_ary_entry(el, 1)); } -static VALUE each_pair(VALUE obj) { - return rb_funcall(obj, rb_intern("each_pair"), 0); -} - -static VALUE array_spec_rb_iterate_each_pair(VALUE self, VALUE obj) { +static VALUE array_spec_rb_block_call_each_pair(VALUE self, VALUE obj) { VALUE new_ary = rb_ary_new(); - rb_iterate(each_pair, obj, sub_pair, new_ary); + rb_block_call(obj, rb_intern("each_pair"), 0, 0, sub_pair, new_ary); return new_ary; } @@ -212,8 +221,8 @@ static VALUE iter_yield(RB_BLOCK_CALL_FUNC_ARGLIST(el, ary)) { return Qnil; } -static VALUE array_spec_rb_iterate_then_yield(VALUE self, VALUE obj) { - rb_iterate(rb_each, obj, iter_yield, obj); +static VALUE array_spec_rb_block_call_then_yield(VALUE self, VALUE obj) { + rb_block_call(obj, rb_intern("each"), 0, 0, iter_yield, obj); return Qnil; } @@ -244,6 +253,7 @@ void Init_array_spec(void) { rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2); rb_define_method(cls, "RARRAY_PTR_memcpy", array_spec_RARRAY_PTR_memcpy, 2); rb_define_method(cls, "RARRAY_AREF", array_spec_RARRAY_AREF, 2); + rb_define_method(cls, "RARRAY_ASET", array_spec_RARRAY_ASET, 3); rb_define_method(cls, "rb_ary_aref", array_spec_rb_ary_aref, -1); rb_define_method(cls, "rb_ary_clear", array_spec_rb_ary_clear, 1); rb_define_method(cls, "rb_ary_delete", array_spec_rb_ary_delete, 2); @@ -266,14 +276,16 @@ void Init_array_spec(void) { rb_define_method(cls, "rb_ary_reverse", array_spec_rb_ary_reverse, 1); rb_define_method(cls, "rb_ary_rotate", array_spec_rb_ary_rotate, 2); rb_define_method(cls, "rb_ary_shift", array_spec_rb_ary_shift, 1); + rb_define_method(cls, "rb_ary_sort", array_spec_rb_ary_sort, 1); + rb_define_method(cls, "rb_ary_sort_bang", array_spec_rb_ary_sort_bang, 1); rb_define_method(cls, "rb_ary_store", array_spec_rb_ary_store, 3); rb_define_method(cls, "rb_ary_concat", array_spec_rb_ary_concat, 2); rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2); rb_define_method(cls, "rb_ary_unshift", array_spec_rb_ary_unshift, 2); rb_define_method(cls, "rb_assoc_new", array_spec_rb_assoc_new, 2); - rb_define_method(cls, "rb_iterate", array_spec_rb_iterate, 1); - rb_define_method(cls, "rb_iterate_each_pair", array_spec_rb_iterate_each_pair, 1); - rb_define_method(cls, "rb_iterate_then_yield", array_spec_rb_iterate_then_yield, 1); + rb_define_method(cls, "rb_block_call", array_spec_rb_block_call, 1); + rb_define_method(cls, "rb_block_call_each_pair", array_spec_rb_block_call_each_pair, 1); + rb_define_method(cls, "rb_block_call_then_yield", array_spec_rb_block_call_then_yield, 1); rb_define_method(cls, "rb_mem_clear", array_spec_rb_mem_clear, 1); rb_define_method(cls, "rb_ary_freeze", array_spec_rb_ary_freeze, 1); rb_define_method(cls, "rb_ary_to_ary", array_spec_rb_ary_to_ary, 1); diff --git a/ruby/spec/ruby/optional/capi/ext/basic_object_spec.c b/ruby/spec/ruby/optional/capi/ext/basic_object_spec.c new file mode 100644 index 000000000..1618670ce --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/basic_object_spec.c @@ -0,0 +1,19 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE basic_object_spec_RBASIC_CLASS(VALUE self, VALUE obj) { + return RBASIC_CLASS(obj); +} + +void Init_basic_object_spec(void) { + VALUE cls = rb_define_class("CApiBasicObjectSpecs", rb_cObject); + rb_define_method(cls, "RBASIC_CLASS", basic_object_spec_RBASIC_CLASS, 1); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/bignum_spec.c b/ruby/spec/ruby/optional/capi/ext/bignum_spec.c index 14a51f509..a950d8b16 100644 --- a/ruby/spec/ruby/optional/capi/ext/bignum_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/bignum_spec.c @@ -65,7 +65,7 @@ static VALUE bignum_spec_rb_big_pack_array(VALUE self, VALUE val, VALUE len) { long long_len = NUM2LONG(len); VALUE ary = rb_ary_new_capa(long_len); - unsigned long *buf = malloc(long_len * SIZEOF_LONG); + unsigned long *buf = (unsigned long*) malloc(long_len * SIZEOF_LONG); /* The array should be filled with recognisable junk so we can check it is all cleared properly. */ @@ -102,5 +102,5 @@ void Init_bignum_spec(void) { } #ifdef __cplusplus -extern "C" { +} #endif diff --git a/ruby/spec/ruby/optional/capi/ext/binding_spec.c b/ruby/spec/ruby/optional/capi/ext/binding_spec.c new file mode 100644 index 000000000..b2e3c88b6 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/binding_spec.c @@ -0,0 +1,19 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE binding_spec_get_binding(VALUE self) { + return rb_funcall(self, rb_intern("binding"), 0); +} + +void Init_binding_spec(void) { + VALUE cls = rb_define_class("CApiBindingSpecs", rb_cObject); + rb_define_method(cls, "get_binding", binding_spec_get_binding, 0); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/boolean_spec.c b/ruby/spec/ruby/optional/capi/ext/boolean_spec.c index 7bb6fe569..081cffa10 100644 --- a/ruby/spec/ruby/optional/capi/ext/boolean_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/boolean_spec.c @@ -29,5 +29,5 @@ void Init_boolean_spec(void) { } #ifdef __cplusplus -extern "C" { +} #endif diff --git a/ruby/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c b/ruby/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c index 64393a939..cc5550f04 100644 --- a/ruby/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c @@ -1,5 +1,13 @@ #include "ruby.h" +#ifdef __cplusplus +extern "C" { +#endif + void Init_class_id_under_autoload_spec(void) { rb_define_class_id_under(rb_cObject, rb_intern("ClassIdUnderAutoload"), rb_cObject); } + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/class_spec.c b/ruby/spec/ruby/optional/capi/ext/class_spec.c index 6e5c02e65..36b8c8f2f 100644 --- a/ruby/spec/ruby/optional/capi/ext/class_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/class_spec.c @@ -37,6 +37,26 @@ static VALUE class_spec_rb_path_to_class(VALUE self, VALUE path) { return rb_path_to_class(path); } +static VALUE class_spec_rb_class_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_public_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_public_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_protected_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_protected_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_private_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_private_instance_methods(--argc, ++argv, mod); +} + static VALUE class_spec_rb_class_new(VALUE self, VALUE super) { return rb_class_new(super); } @@ -45,7 +65,7 @@ static VALUE class_spec_rb_class_new_instance(VALUE self, VALUE nargs, VALUE args, VALUE klass) { int c_nargs = FIX2INT(nargs); - VALUE *c_args = alloca(sizeof(VALUE) * c_nargs); + VALUE *c_args = (VALUE*)alloca(sizeof(VALUE) * c_nargs); int i; for (i = 0; i < c_nargs; i++) @@ -146,6 +166,10 @@ void Init_class_spec(void) { rb_define_method(cls, "rb_class2name", class_spec_rb_class2name, 1); rb_define_method(cls, "rb_path2class", class_spec_rb_path2class, 1); rb_define_method(cls, "rb_path_to_class", class_spec_rb_path_to_class, 1); + rb_define_method(cls, "rb_class_instance_methods", class_spec_rb_class_instance_methods, -1); + rb_define_method(cls, "rb_class_public_instance_methods", class_spec_rb_class_public_instance_methods, -1); + rb_define_method(cls, "rb_class_protected_instance_methods", class_spec_rb_class_protected_instance_methods, -1); + rb_define_method(cls, "rb_class_private_instance_methods", class_spec_rb_class_private_instance_methods, -1); rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1); rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 3); rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1); diff --git a/ruby/spec/ruby/optional/capi/ext/class_under_autoload_spec.c b/ruby/spec/ruby/optional/capi/ext/class_under_autoload_spec.c index 120dec732..e0b1f249c 100644 --- a/ruby/spec/ruby/optional/capi/ext/class_under_autoload_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/class_under_autoload_spec.c @@ -1,5 +1,13 @@ #include "ruby.h" +#ifdef __cplusplus +extern "C" { +#endif + void Init_class_under_autoload_spec(void) { rb_define_class_under(rb_cObject, "ClassUnderAutoload", rb_cObject); } + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/constants_spec.c b/ruby/spec/ruby/optional/capi/ext/constants_spec.c index c8ae84301..9aee8db37 100644 --- a/ruby/spec/ruby/optional/capi/ext/constants_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/constants_spec.c @@ -5,310 +5,151 @@ extern "C" { #endif -static VALUE constants_spec_rb_cArray(VALUE self) { - return rb_cArray; -} - -#ifndef RUBY_INTEGER_UNIFICATION -static VALUE constants_spec_rb_cBignum(VALUE self) { - return rb_cBignum; -} +#define defconstfunc(name) \ +static VALUE constants_spec_##name(VALUE self) { return name; } + +defconstfunc(rb_cArray) +defconstfunc(rb_cBasicObject) +defconstfunc(rb_cBinding) +defconstfunc(rb_cClass) +defconstfunc(rb_cComplex) +defconstfunc(rb_mComparable) +#ifndef RUBY_VERSION_IS_3_0 +defconstfunc(rb_cData) #endif - -static VALUE constants_spec_rb_cClass(VALUE self) { - return rb_cClass; -} - -static VALUE constants_spec_rb_cData(VALUE self) { - return rb_cData; -} - -static VALUE constants_spec_rb_cFalseClass(VALUE self) { - return rb_cFalseClass; -} - -static VALUE constants_spec_rb_cFile(VALUE self) { - return rb_cFile; -} - -#ifndef RUBY_INTEGER_UNIFICATION -static VALUE constants_spec_rb_cFixnum(VALUE self) { - return rb_cFixnum; -} -#endif - -static VALUE constants_spec_rb_cFloat(VALUE self) { - return rb_cFloat; -} - -static VALUE constants_spec_rb_cHash(VALUE self) { - return rb_cHash; -} - -static VALUE constants_spec_rb_cInteger(VALUE self) { - return rb_cInteger; -} - -static VALUE constants_spec_rb_cIO(VALUE self) { - return rb_cIO; -} - -static VALUE constants_spec_rb_cModule(VALUE self) { - return rb_cModule; -} - -static VALUE constants_spec_rb_cMatch(VALUE self) { - return rb_cMatch; -} - -static VALUE constants_spec_rb_cNilClass(VALUE self) { - return rb_cNilClass; -} - -static VALUE constants_spec_rb_cNumeric(VALUE self) { - return rb_cNumeric; -} - -static VALUE constants_spec_rb_cObject(VALUE self) { - return rb_cObject; -} - -static VALUE constants_spec_rb_cRange(VALUE self) { - return rb_cRange; -} - -static VALUE constants_spec_rb_cRegexp(VALUE self) { - return rb_cRegexp; -} - -static VALUE constants_spec_rb_cString(VALUE self) { - return rb_cString; -} - -static VALUE constants_spec_rb_cStruct(VALUE self) { - return rb_cStruct; -} - -static VALUE constants_spec_rb_cSymbol(VALUE self) { - return rb_cSymbol; -} - -static VALUE constants_spec_rb_cTime(VALUE self) { - return rb_cTime; -} - -static VALUE constants_spec_rb_cThread(VALUE self) { - return rb_cThread; -} - -static VALUE constants_spec_rb_cTrueClass(VALUE self) { - return rb_cTrueClass; -} - -static VALUE constants_spec_rb_cProc(VALUE self) { - return rb_cProc; -} - -static VALUE constants_spec_rb_cMethod(VALUE self) { - return rb_cMethod; -} - -static VALUE constants_spec_rb_cEnumerator(VALUE self) { - return rb_cEnumerator; -} - -static VALUE constants_spec_rb_mComparable(VALUE self) { - return rb_mComparable; -} - -static VALUE constants_spec_rb_mEnumerable(VALUE self) { - return rb_mEnumerable; -} - -static VALUE constants_spec_rb_mKernel(VALUE self) { - return rb_mKernel; -} - -static VALUE constants_spec_rb_eArgError(VALUE self) { - return rb_eArgError; -} - -static VALUE constants_spec_rb_eEOFError(VALUE self) { - return rb_eEOFError; -} - -static VALUE constants_spec_rb_mErrno(VALUE self) { - return rb_mErrno; -} - -static VALUE constants_spec_rb_eException(VALUE self) { - return rb_eException; -} - -static VALUE constants_spec_rb_eFloatDomainError(VALUE self) { - return rb_eFloatDomainError; -} - -static VALUE constants_spec_rb_eIndexError(VALUE self) { - return rb_eIndexError; -} - -static VALUE constants_spec_rb_eInterrupt(VALUE self) { - return rb_eInterrupt; -} - -static VALUE constants_spec_rb_eIOError(VALUE self) { - return rb_eIOError; -} - -static VALUE constants_spec_rb_eLoadError(VALUE self) { - return rb_eLoadError; -} - -static VALUE constants_spec_rb_eLocalJumpError(VALUE self) { - return rb_eLocalJumpError; -} - -static VALUE constants_spec_rb_eNameError(VALUE self) { - return rb_eNameError; -} - -static VALUE constants_spec_rb_eNoMemError(VALUE self) { - return rb_eNoMemError; -} - -static VALUE constants_spec_rb_eNoMethodError(VALUE self) { - return rb_eNoMethodError; -} - -static VALUE constants_spec_rb_eNotImpError(VALUE self) { - return rb_eNotImpError; -} - -static VALUE constants_spec_rb_eRangeError(VALUE self) { - return rb_eRangeError; -} - -static VALUE constants_spec_rb_eRegexpError(VALUE self) { - return rb_eRegexpError; -} - -static VALUE constants_spec_rb_eRuntimeError(VALUE self) { - return rb_eRuntimeError; -} - -static VALUE constants_spec_rb_eScriptError(VALUE self) { - return rb_eScriptError; -} - -static VALUE constants_spec_rb_eSecurityError(VALUE self) { - return rb_eSecurityError; -} - -static VALUE constants_spec_rb_eSignal(VALUE self) { - return rb_eSignal; -} - -static VALUE constants_spec_rb_eStandardError(VALUE self) { - return rb_eStandardError; -} - -static VALUE constants_spec_rb_eSyntaxError(VALUE self) { - return rb_eSyntaxError; -} - -static VALUE constants_spec_rb_eSystemCallError(VALUE self) { - return rb_eSystemCallError; -} - -static VALUE constants_spec_rb_eSystemExit(VALUE self) { - return rb_eSystemExit; -} - -static VALUE constants_spec_rb_eSysStackError(VALUE self) { - return rb_eSysStackError; -} - -static VALUE constants_spec_rb_eTypeError(VALUE self) { - return rb_eTypeError; -} - -static VALUE constants_spec_rb_eThreadError(VALUE self) { - return rb_eThreadError; -} - -static VALUE constants_spec_rb_eZeroDivError(VALUE self) { - return rb_eZeroDivError; -} - -static VALUE constants_spec_rb_eMathDomainError(VALUE self) { - return rb_eMathDomainError; -} - -static VALUE constants_spec_rb_eEncCompatError(VALUE self) { - return rb_eEncCompatError; -} - -static VALUE constants_spec_rb_mWaitReadable(VALUE self) { - return rb_mWaitReadable; -} - -static VALUE constants_spec_rb_mWaitWritable(VALUE self) { - return rb_mWaitWritable; -} - -static VALUE constants_spec_rb_cDir(VALUE self) { - return rb_cDir; -} +defconstfunc(rb_cDir) +defconstfunc(rb_cEncoding) +defconstfunc(rb_mEnumerable) +defconstfunc(rb_cEnumerator) +defconstfunc(rb_cFalseClass) +defconstfunc(rb_cFile) +defconstfunc(rb_mFileTest) +defconstfunc(rb_cFloat) +defconstfunc(rb_mGC) +defconstfunc(rb_cHash) +defconstfunc(rb_cInteger) +defconstfunc(rb_cIO) +defconstfunc(rb_mKernel) +defconstfunc(rb_mMath) +defconstfunc(rb_cMatch) +defconstfunc(rb_cMethod) +defconstfunc(rb_cModule) +defconstfunc(rb_cNilClass) +defconstfunc(rb_cNumeric) +defconstfunc(rb_cObject) +defconstfunc(rb_cProc) +defconstfunc(rb_mProcess) +defconstfunc(rb_cRandom) +defconstfunc(rb_cRange) +defconstfunc(rb_cRational) +defconstfunc(rb_cRegexp) +defconstfunc(rb_cStat) +defconstfunc(rb_cString) +defconstfunc(rb_cStruct) +defconstfunc(rb_cSymbol) +defconstfunc(rb_cTime) +defconstfunc(rb_cThread) +defconstfunc(rb_cTrueClass) +defconstfunc(rb_cUnboundMethod) +defconstfunc(rb_eArgError) +defconstfunc(rb_eEncodingError) +defconstfunc(rb_eEncCompatError) +defconstfunc(rb_eEOFError) +defconstfunc(rb_mErrno) +defconstfunc(rb_eException) +defconstfunc(rb_eFatal) +defconstfunc(rb_eFloatDomainError) +defconstfunc(rb_eFrozenError) +defconstfunc(rb_eIndexError) +defconstfunc(rb_eInterrupt) +defconstfunc(rb_eIOError) +defconstfunc(rb_eKeyError) +defconstfunc(rb_eLoadError) +defconstfunc(rb_eLocalJumpError) +defconstfunc(rb_eMathDomainError) +defconstfunc(rb_eNameError) +defconstfunc(rb_eNoMemError) +defconstfunc(rb_eNoMethodError) +defconstfunc(rb_eNotImpError) +defconstfunc(rb_eRangeError) +defconstfunc(rb_eRegexpError) +defconstfunc(rb_eRuntimeError) +defconstfunc(rb_eScriptError) +defconstfunc(rb_eSecurityError) +defconstfunc(rb_eSignal) +defconstfunc(rb_eStandardError) +defconstfunc(rb_eStopIteration) +defconstfunc(rb_eSyntaxError) +defconstfunc(rb_eSystemCallError) +defconstfunc(rb_eSystemExit) +defconstfunc(rb_eSysStackError) +defconstfunc(rb_eTypeError) +defconstfunc(rb_eThreadError) +defconstfunc(rb_mWaitReadable) +defconstfunc(rb_mWaitWritable) +defconstfunc(rb_eZeroDivError) void Init_constants_spec(void) { VALUE cls = rb_define_class("CApiConstantsSpecs", rb_cObject); rb_define_method(cls, "rb_cArray", constants_spec_rb_cArray, 0); -#ifndef RUBY_INTEGER_UNIFICATION - rb_define_method(cls, "rb_cBignum", constants_spec_rb_cBignum, 0); -#endif - + rb_define_method(cls, "rb_cBasicObject", constants_spec_rb_cBasicObject, 0); + rb_define_method(cls, "rb_cBinding", constants_spec_rb_cBinding, 0); rb_define_method(cls, "rb_cClass", constants_spec_rb_cClass, 0); + rb_define_method(cls, "rb_cComplex", constants_spec_rb_cComplex, 0); + rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0); + #ifndef RUBY_VERSION_IS_3_0 rb_define_method(cls, "rb_cData", constants_spec_rb_cData, 0); + #endif + rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0); + rb_define_method(cls, "rb_cEncoding", constants_spec_rb_cEncoding, 0); + rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0); + rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0); rb_define_method(cls, "rb_cFalseClass", constants_spec_rb_cFalseClass, 0); rb_define_method(cls, "rb_cFile", constants_spec_rb_cFile, 0); -#ifndef RUBY_INTEGER_UNIFICATION - rb_define_method(cls, "rb_cFixnum", constants_spec_rb_cFixnum, 0); -#endif - + rb_define_method(cls, "rb_mFileTest", constants_spec_rb_mFileTest, 0); rb_define_method(cls, "rb_cFloat", constants_spec_rb_cFloat, 0); + rb_define_method(cls, "rb_mGC", constants_spec_rb_mGC, 0); rb_define_method(cls, "rb_cHash", constants_spec_rb_cHash, 0); rb_define_method(cls, "rb_cInteger", constants_spec_rb_cInteger, 0); rb_define_method(cls, "rb_cIO", constants_spec_rb_cIO, 0); + rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0); + rb_define_method(cls, "rb_mMath", constants_spec_rb_mMath, 0); rb_define_method(cls, "rb_cMatch", constants_spec_rb_cMatch, 0); + rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0); rb_define_method(cls, "rb_cModule", constants_spec_rb_cModule, 0); rb_define_method(cls, "rb_cNilClass", constants_spec_rb_cNilClass, 0); rb_define_method(cls, "rb_cNumeric", constants_spec_rb_cNumeric, 0); rb_define_method(cls, "rb_cObject", constants_spec_rb_cObject, 0); + rb_define_method(cls, "rb_cProc", constants_spec_rb_cProc, 0); + rb_define_method(cls, "rb_mProcess", constants_spec_rb_mProcess, 0); + rb_define_method(cls, "rb_cRandom", constants_spec_rb_cRandom, 0); rb_define_method(cls, "rb_cRange", constants_spec_rb_cRange, 0); + rb_define_method(cls, "rb_cRational", constants_spec_rb_cRational, 0); rb_define_method(cls, "rb_cRegexp", constants_spec_rb_cRegexp, 0); + rb_define_method(cls, "rb_cStat", constants_spec_rb_cStat, 0); rb_define_method(cls, "rb_cString", constants_spec_rb_cString, 0); rb_define_method(cls, "rb_cStruct", constants_spec_rb_cStruct, 0); rb_define_method(cls, "rb_cSymbol", constants_spec_rb_cSymbol, 0); rb_define_method(cls, "rb_cTime", constants_spec_rb_cTime, 0); rb_define_method(cls, "rb_cThread", constants_spec_rb_cThread, 0); rb_define_method(cls, "rb_cTrueClass", constants_spec_rb_cTrueClass, 0); - rb_define_method(cls, "rb_cProc", constants_spec_rb_cProc, 0); - rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0); - rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0); - rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0); - rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0); - rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0); + rb_define_method(cls, "rb_cUnboundMethod", constants_spec_rb_cUnboundMethod, 0); rb_define_method(cls, "rb_eArgError", constants_spec_rb_eArgError, 0); + rb_define_method(cls, "rb_eEncodingError", constants_spec_rb_eEncodingError, 0); + rb_define_method(cls, "rb_eEncCompatError", constants_spec_rb_eEncCompatError, 0); rb_define_method(cls, "rb_eEOFError", constants_spec_rb_eEOFError, 0); rb_define_method(cls, "rb_mErrno", constants_spec_rb_mErrno, 0); rb_define_method(cls, "rb_eException", constants_spec_rb_eException, 0); + rb_define_method(cls, "rb_eFatal", constants_spec_rb_eFatal, 0); rb_define_method(cls, "rb_eFloatDomainError", constants_spec_rb_eFloatDomainError, 0); + rb_define_method(cls, "rb_eFrozenError", constants_spec_rb_eFrozenError, 0); rb_define_method(cls, "rb_eIndexError", constants_spec_rb_eIndexError, 0); rb_define_method(cls, "rb_eInterrupt", constants_spec_rb_eInterrupt, 0); rb_define_method(cls, "rb_eIOError", constants_spec_rb_eIOError, 0); + rb_define_method(cls, "rb_eKeyError", constants_spec_rb_eKeyError, 0); rb_define_method(cls, "rb_eLoadError", constants_spec_rb_eLoadError, 0); rb_define_method(cls, "rb_eLocalJumpError", constants_spec_rb_eLocalJumpError, 0); + rb_define_method(cls, "rb_eMathDomainError", constants_spec_rb_eMathDomainError, 0); rb_define_method(cls, "rb_eNameError", constants_spec_rb_eNameError, 0); rb_define_method(cls, "rb_eNoMemError", constants_spec_rb_eNoMemError, 0); rb_define_method(cls, "rb_eNoMethodError", constants_spec_rb_eNoMethodError, 0); @@ -320,18 +161,16 @@ void Init_constants_spec(void) { rb_define_method(cls, "rb_eSecurityError", constants_spec_rb_eSecurityError, 0); rb_define_method(cls, "rb_eSignal", constants_spec_rb_eSignal, 0); rb_define_method(cls, "rb_eStandardError", constants_spec_rb_eStandardError, 0); + rb_define_method(cls, "rb_eStopIteration", constants_spec_rb_eStopIteration, 0); rb_define_method(cls, "rb_eSyntaxError", constants_spec_rb_eSyntaxError, 0); rb_define_method(cls, "rb_eSystemCallError", constants_spec_rb_eSystemCallError, 0); rb_define_method(cls, "rb_eSystemExit", constants_spec_rb_eSystemExit, 0); rb_define_method(cls, "rb_eSysStackError", constants_spec_rb_eSysStackError, 0); rb_define_method(cls, "rb_eTypeError", constants_spec_rb_eTypeError, 0); rb_define_method(cls, "rb_eThreadError", constants_spec_rb_eThreadError, 0); - rb_define_method(cls, "rb_eZeroDivError", constants_spec_rb_eZeroDivError, 0); - rb_define_method(cls, "rb_eMathDomainError", constants_spec_rb_eMathDomainError, 0); - rb_define_method(cls, "rb_eEncCompatError", constants_spec_rb_eEncCompatError, 0); rb_define_method(cls, "rb_mWaitReadable", constants_spec_rb_mWaitReadable, 0); rb_define_method(cls, "rb_mWaitWritable", constants_spec_rb_mWaitWritable, 0); - rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0); + rb_define_method(cls, "rb_eZeroDivError", constants_spec_rb_eZeroDivError, 0); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/data_spec.c b/ruby/spec/ruby/optional/capi/ext/data_spec.c index a41666f65..ef069ef0b 100644 --- a/ruby/spec/ruby/optional/capi/ext/data_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/data_spec.c @@ -19,7 +19,7 @@ void sample_wrapped_struct_mark(void* st) { } VALUE sdaf_alloc_func(VALUE klass) { - struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct)); + struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct)); bar->foo = 42; return Data_Wrap_Struct(klass, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar); } @@ -32,7 +32,7 @@ VALUE sdaf_get_struct(VALUE self) { } VALUE sws_wrap_struct(VALUE self, VALUE val) { - struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct)); + struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct)); bar->foo = FIX2INT(val); return Data_Wrap_Struct(rb_cObject, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar); } @@ -58,14 +58,19 @@ VALUE sws_get_struct_data_ptr(VALUE self, VALUE obj) { VALUE sws_change_struct(VALUE self, VALUE obj, VALUE new_val) { struct sample_wrapped_struct *old_struct, *new_struct; - new_struct = malloc(sizeof(struct sample_wrapped_struct)); + new_struct = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct)); new_struct->foo = FIX2INT(new_val); - old_struct = RDATA(obj)->data; + old_struct = (struct sample_wrapped_struct*) RDATA(obj)->data; free(old_struct); RDATA(obj)->data = new_struct; return Qnil; } +VALUE sws_rb_check_type(VALUE self, VALUE obj, VALUE other) { + rb_check_type(obj, TYPE(other)); + return Qtrue; +} + void Init_data_spec(void) { VALUE cls = rb_define_class("CApiAllocSpecs", rb_cObject); rb_define_alloc_func(cls, sdaf_alloc_func); @@ -76,6 +81,7 @@ void Init_data_spec(void) { rb_define_method(cls, "get_struct_rdata", sws_get_struct_rdata, 1); rb_define_method(cls, "get_struct_data_ptr", sws_get_struct_data_ptr, 1); rb_define_method(cls, "change_struct", sws_change_struct, 2); + rb_define_method(cls, "rb_check_type", sws_rb_check_type, 2); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/debug_spec.c b/ruby/spec/ruby/optional/capi/ext/debug_spec.c new file mode 100644 index 000000000..344dfc33f --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/debug_spec.c @@ -0,0 +1,93 @@ +#include "ruby.h" +#include "rubyspec.h" +#include "ruby/debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE callback_data = Qfalse; + +static VALUE rb_debug_inspector_open_callback(const rb_debug_inspector_t *dc, void *ptr) { + if (!dc) { + rb_raise(rb_eRuntimeError, "rb_debug_inspector_t should not be NULL"); + } + + VALUE locations = rb_debug_inspector_backtrace_locations(dc); + int len = RARRAY_LENINT(locations); + VALUE results = rb_ary_new2(len); + for (int i = 0; i < len; i++) { + VALUE ary = rb_ary_new2(5); // [self, klass, binding, iseq, backtrace_location] + rb_ary_store(ary, 0, rb_debug_inspector_frame_self_get(dc, i)); + rb_ary_store(ary, 1, rb_debug_inspector_frame_class_get(dc, i)); + rb_ary_store(ary, 2, rb_debug_inspector_frame_binding_get(dc, i)); + rb_ary_store(ary, 3, rb_debug_inspector_frame_iseq_get(dc, i)); + rb_ary_store(ary, 4, rb_ary_entry(locations, i)); + rb_ary_push(results, ary); + } + callback_data = (VALUE)ptr; + return results; +} + +static VALUE rb_debug_inspector_frame_self_get_callback(const rb_debug_inspector_t *dc, void *ptr) { + return rb_debug_inspector_frame_self_get(dc, NUM2LONG((VALUE) ptr)); +} + +static VALUE rb_debug_inspector_frame_class_get_callback(const rb_debug_inspector_t *dc, void *ptr) { + return rb_debug_inspector_frame_class_get(dc, NUM2LONG((VALUE) ptr)); +} + +static VALUE rb_debug_inspector_frame_binding_get_callback(const rb_debug_inspector_t *dc, void *ptr) { + return rb_debug_inspector_frame_binding_get(dc, NUM2LONG((VALUE) ptr)); +} + +static VALUE rb_debug_inspector_frame_iseq_get_callback(const rb_debug_inspector_t *dc, void *ptr) { + return rb_debug_inspector_frame_iseq_get(dc, NUM2LONG((VALUE) ptr)); +} + +static VALUE debug_spec_callback_data(VALUE self){ + return callback_data; +} + +VALUE debug_spec_rb_debug_inspector_open(VALUE self, VALUE index) { + return rb_debug_inspector_open(rb_debug_inspector_open_callback, (void *)index); +} + +VALUE debug_spec_rb_debug_inspector_frame_self_get(VALUE self, VALUE index) { + return rb_debug_inspector_open(rb_debug_inspector_frame_self_get_callback, (void *)index); +} + +VALUE debug_spec_rb_debug_inspector_frame_class_get(VALUE self, VALUE index) { + return rb_debug_inspector_open(rb_debug_inspector_frame_class_get_callback, (void *)index); +} + +VALUE debug_spec_rb_debug_inspector_frame_binding_get(VALUE self, VALUE index) { + return rb_debug_inspector_open(rb_debug_inspector_frame_binding_get_callback, (void *)index); +} + +VALUE debug_spec_rb_debug_inspector_frame_iseq_get(VALUE self, VALUE index) { + return rb_debug_inspector_open(rb_debug_inspector_frame_iseq_get_callback, (void *)index); +} + +static VALUE rb_debug_inspector_backtrace_locations_func(const rb_debug_inspector_t *dc, void *ptr) { + return rb_debug_inspector_backtrace_locations(dc); +} + +VALUE debug_spec_rb_debug_inspector_backtrace_locations(VALUE self) { + return rb_debug_inspector_open(rb_debug_inspector_backtrace_locations_func, (void *)self); +} + +void Init_debug_spec(void) { + VALUE cls = rb_define_class("CApiDebugSpecs", rb_cObject); + rb_define_method(cls, "rb_debug_inspector_open", debug_spec_rb_debug_inspector_open, 1); + rb_define_method(cls, "rb_debug_inspector_frame_self_get", debug_spec_rb_debug_inspector_frame_self_get, 1); + rb_define_method(cls, "rb_debug_inspector_frame_class_get", debug_spec_rb_debug_inspector_frame_class_get, 1); + rb_define_method(cls, "rb_debug_inspector_frame_binding_get", debug_spec_rb_debug_inspector_frame_binding_get, 1); + rb_define_method(cls, "rb_debug_inspector_frame_iseq_get", debug_spec_rb_debug_inspector_frame_iseq_get, 1); + rb_define_method(cls, "rb_debug_inspector_backtrace_locations", debug_spec_rb_debug_inspector_backtrace_locations, 0); + rb_define_method(cls, "debug_spec_callback_data", debug_spec_callback_data, 0); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/encoding_spec.c b/ruby/spec/ruby/optional/capi/ext/encoding_spec.c index 3cde88422..cde4d0c35 100644 --- a/ruby/spec/ruby/optional/capi/ext/encoding_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/encoding_spec.c @@ -7,6 +7,10 @@ extern "C" { #endif +static VALUE encoding_spec_MBCLEN_CHARFOUND_P(VALUE self, VALUE obj) { + return INT2FIX(MBCLEN_CHARFOUND_P(FIX2INT(obj))); +} + static VALUE encoding_spec_ENC_CODERANGE_ASCIIONLY(VALUE self, VALUE obj) { if(ENC_CODERANGE_ASCIIONLY(obj)) { return Qtrue; @@ -102,10 +106,39 @@ static VALUE encoding_spec_rb_enc_find_index(VALUE self, VALUE name) { return INT2NUM(rb_enc_find_index(RSTRING_PTR(name))); } +static VALUE encoding_spec_rb_enc_isalnum(VALUE self, VALUE chr, VALUE encoding) { + rb_encoding *e = rb_to_encoding(encoding); + return rb_enc_isalnum(FIX2INT(chr), e) ? Qtrue : Qfalse; +} + +static VALUE encoding_spec_rb_enc_isspace(VALUE self, VALUE chr, VALUE encoding) { + rb_encoding *e = rb_to_encoding(encoding); + return rb_enc_isspace(FIX2INT(chr), e) ? Qtrue : Qfalse; +} + static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) { return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name); } +static VALUE encoding_spec_rb_enc_mbc_to_codepoint(VALUE self, VALUE str, VALUE offset) { + int o = FIX2INT(offset); + char *p = RSTRING_PTR(str); + char *e = p + o; + return INT2FIX(rb_enc_mbc_to_codepoint(p, e, rb_enc_get(str))); +} + +static VALUE encoding_spec_rb_enc_mbcput(VALUE self, VALUE code, VALUE encoding) { + unsigned int c = FIX2UINT(code); + rb_encoding *enc = rb_to_encoding(encoding); + char buf[ONIGENC_CODE_TO_MBC_MAXLEN]; + memset(buf, '\1', sizeof(buf)); + int len = rb_enc_mbcput(c, buf, enc); + if (buf[len] != '\1') { + rb_raise(rb_eRuntimeError, "should not change bytes after len"); + } + return rb_enc_str_new(buf, len, enc); +} + static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) { return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(name))); } @@ -114,6 +147,13 @@ static VALUE encoding_spec_rb_enc_get(VALUE self, VALUE obj) { return rb_str_new2(rb_enc_get(obj)->name); } +static VALUE encoding_spec_rb_enc_precise_mbclen(VALUE self, VALUE str, VALUE offset) { + int o = FIX2INT(offset); + char *p = RSTRING_PTR(str); + char *e = p + o; + return INT2FIX(rb_enc_precise_mbclen(p, e, rb_enc_get(str))); +} + static VALUE encoding_spec_rb_obj_encoding(VALUE self, VALUE obj) { return rb_obj_encoding(obj); } @@ -149,6 +189,21 @@ static VALUE encoding_spec_rb_enc_str_coderange(VALUE self, VALUE str) { } } +static VALUE encoding_spec_rb_enc_str_new_cstr(VALUE self, VALUE str, VALUE enc) { + rb_encoding *e = rb_to_encoding(enc); + return rb_enc_str_new_cstr(StringValueCStr(str), e); +} + +static VALUE encoding_spec_rb_enc_str_new_cstr_constant(VALUE self, VALUE enc) { + if (NIL_P(enc)) { + rb_encoding *e = NULL; + return rb_enc_str_new_static("test string literal", strlen("test string literal"), e); + } else { + rb_encoding *e = rb_to_encoding(enc); + return rb_enc_str_new_cstr("test string literal", e); + } +} + static VALUE encoding_spec_rb_enc_str_new(VALUE self, VALUE str, VALUE len, VALUE enc) { return rb_enc_str_new(RSTRING_PTR(str), FIX2INT(len), rb_to_encoding(enc)); } @@ -175,6 +230,21 @@ static VALUE encoding_spec_rb_to_encoding(VALUE self, VALUE obj) { return rb_str_new2(rb_to_encoding(obj)->name); } +static rb_encoding** native_rb_encoding_pointer; + +static VALUE encoding_spec_rb_to_encoding_native_store(VALUE self, VALUE obj) { + rb_encoding* enc = rb_to_encoding(obj); + VALUE address = SIZET2NUM((size_t) native_rb_encoding_pointer); + *native_rb_encoding_pointer = enc; + return address; +} + +static VALUE encoding_spec_rb_to_encoding_native_name(VALUE self, VALUE address) { + rb_encoding** ptr = (rb_encoding**) NUM2SIZET(address); + rb_encoding* enc = *ptr; + return rb_str_new2(enc->name); +} + static VALUE encoding_spec_rb_to_encoding_index(VALUE self, VALUE obj) { return INT2NUM(rb_to_encoding_index(obj)); } @@ -196,8 +266,45 @@ static VALUE encoding_spec_rb_enc_codepoint_len(VALUE self, VALUE str) { return rb_ary_new3(2, LONG2NUM(codepoint), LONG2NUM(len)); } +static VALUE encoding_spec_rb_enc_str_asciionly_p(VALUE self, VALUE str) { + if (rb_enc_str_asciionly_p(str)) { + return Qtrue; + } else { + return Qfalse; + } +} + +static VALUE encoding_spec_rb_uv_to_utf8(VALUE self, VALUE buf, VALUE num) { + return INT2NUM(rb_uv_to_utf8(RSTRING_PTR(buf), NUM2INT(num))); +} + +static VALUE encoding_spec_ONIGENC_MBC_CASE_FOLD(VALUE self, VALUE str) { + char *beg = RSTRING_PTR(str); + char *beg_initial = beg; + char *end = beg + 2; + OnigUChar fold[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; + memset(fold, '\1', sizeof(fold)); + rb_encoding *enc = rb_enc_get(str); + int r = ONIGENC_MBC_CASE_FOLD(enc, ONIGENC_CASE_FOLD, &beg, (const OnigUChar *)end, fold); + if (r > 0 && fold[r] != '\1') { + rb_raise(rb_eRuntimeError, "should not change bytes after len"); + } + VALUE str_result = r <= 0 ? Qnil : rb_enc_str_new((char *)fold, r, enc); + long bytes_used = beg - beg_initial; + return rb_ary_new3(2, str_result, INT2FIX(bytes_used)); +} + +static VALUE encoding_spec_rb_enc_codelen(VALUE self, VALUE code, VALUE encoding) { + unsigned int c = FIX2UINT(code); + rb_encoding *enc = rb_to_encoding(encoding); + return INT2FIX(rb_enc_codelen(c, enc)); +} + void Init_encoding_spec(void) { - VALUE cls = rb_define_class("CApiEncodingSpecs", rb_cObject); + VALUE cls; + native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*)); + + cls = rb_define_class("CApiEncodingSpecs", rb_cObject); rb_define_method(cls, "ENC_CODERANGE_ASCIIONLY", encoding_spec_ENC_CODERANGE_ASCIIONLY, 1); @@ -221,27 +328,41 @@ void Init_encoding_spec(void) { rb_define_method(cls, "rb_enc_alias", encoding_spec_rb_enc_alias, 2); #endif + rb_define_method(cls, "MBCLEN_CHARFOUND_P", encoding_spec_MBCLEN_CHARFOUND_P, 1); rb_define_method(cls, "rb_enc_associate", encoding_spec_rb_enc_associate, 2); rb_define_method(cls, "rb_enc_associate_index", encoding_spec_rb_enc_associate_index, 2); rb_define_method(cls, "rb_enc_compatible", encoding_spec_rb_enc_compatible, 2); rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2); + rb_define_method(cls, "rb_enc_codelen", encoding_spec_rb_enc_codelen, 2); rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1); rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1); + rb_define_method(cls, "rb_enc_isalnum", encoding_spec_rb_enc_isalnum, 2); + rb_define_method(cls, "rb_enc_isspace", encoding_spec_rb_enc_isspace, 2); rb_define_method(cls, "rb_enc_from_index", encoding_spec_rb_enc_from_index, 1); + rb_define_method(cls, "rb_enc_mbc_to_codepoint", encoding_spec_rb_enc_mbc_to_codepoint, 2); + rb_define_method(cls, "rb_enc_mbcput", encoding_spec_rb_enc_mbcput, 2); rb_define_method(cls, "rb_enc_from_encoding", encoding_spec_rb_enc_from_encoding, 1); rb_define_method(cls, "rb_enc_get", encoding_spec_rb_enc_get, 1); + rb_define_method(cls, "rb_enc_precise_mbclen", encoding_spec_rb_enc_precise_mbclen, 2); rb_define_method(cls, "rb_obj_encoding", encoding_spec_rb_obj_encoding, 1); rb_define_method(cls, "rb_enc_get_index", encoding_spec_rb_enc_get_index, 1); rb_define_method(cls, "rb_enc_set_index", encoding_spec_rb_enc_set_index, 2); rb_define_method(cls, "rb_enc_str_coderange", encoding_spec_rb_enc_str_coderange, 1); + rb_define_method(cls, "rb_enc_str_new_cstr", encoding_spec_rb_enc_str_new_cstr, 2); + rb_define_method(cls, "rb_enc_str_new_cstr_constant", encoding_spec_rb_enc_str_new_cstr_constant, 1); rb_define_method(cls, "rb_enc_str_new", encoding_spec_rb_enc_str_new, 3); rb_define_method(cls, "ENCODING_GET", encoding_spec_ENCODING_GET, 1); rb_define_method(cls, "ENCODING_SET", encoding_spec_ENCODING_SET, 2); rb_define_method(cls, "rb_enc_to_index", encoding_spec_rb_enc_to_index, 1); rb_define_method(cls, "rb_to_encoding", encoding_spec_rb_to_encoding, 1); + rb_define_method(cls, "rb_to_encoding_native_store", encoding_spec_rb_to_encoding_native_store, 1); + rb_define_method(cls, "rb_to_encoding_native_name", encoding_spec_rb_to_encoding_native_name, 1); rb_define_method(cls, "rb_to_encoding_index", encoding_spec_rb_to_encoding_index, 1); rb_define_method(cls, "rb_enc_nth", encoding_spec_rb_enc_nth, 2); rb_define_method(cls, "rb_enc_codepoint_len", encoding_spec_rb_enc_codepoint_len, 1); + rb_define_method(cls, "rb_enc_str_asciionly_p", encoding_spec_rb_enc_str_asciionly_p, 1); + rb_define_method(cls, "rb_uv_to_utf8", encoding_spec_rb_uv_to_utf8, 2); + rb_define_method(cls, "ONIGENC_MBC_CASE_FOLD", encoding_spec_ONIGENC_MBC_CASE_FOLD, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/exception_spec.c b/ruby/spec/ruby/optional/capi/ext/exception_spec.c index cdd86b183..e1114aabb 100644 --- a/ruby/spec/ruby/optional/capi/ext/exception_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/exception_spec.c @@ -8,6 +8,10 @@ extern "C" { #endif +VALUE exception_spec_rb_errinfo(VALUE self) { + return rb_errinfo(); +} + VALUE exception_spec_rb_exc_new(VALUE self, VALUE str) { char *cstr = StringValuePtr(str); return rb_exc_new(rb_eException, cstr, strlen(cstr)); @@ -32,13 +36,22 @@ VALUE exception_spec_rb_set_errinfo(VALUE self, VALUE exc) { return Qnil; } + +VALUE exception_spec_rb_make_exception(VALUE self, VALUE ary) { + int argc = RARRAY_LENINT(ary); + VALUE *argv = RARRAY_PTR(ary); + return rb_make_exception(argc, argv); +} + void Init_exception_spec(void) { VALUE cls = rb_define_class("CApiExceptionSpecs", rb_cObject); + rb_define_method(cls, "rb_errinfo", exception_spec_rb_errinfo, 0); rb_define_method(cls, "rb_exc_new", exception_spec_rb_exc_new, 1); rb_define_method(cls, "rb_exc_new2", exception_spec_rb_exc_new2, 1); rb_define_method(cls, "rb_exc_new3", exception_spec_rb_exc_new3, 1); rb_define_method(cls, "rb_exc_raise", exception_spec_rb_exc_raise, 1); rb_define_method(cls, "rb_set_errinfo", exception_spec_rb_set_errinfo, 1); + rb_define_method(cls, "rb_make_exception", exception_spec_rb_make_exception, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/fiber_spec.c b/ruby/spec/ruby/optional/capi/ext/fiber_spec.c new file mode 100644 index 000000000..f06a54494 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/fiber_spec.c @@ -0,0 +1,69 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +VALUE fiber_spec_rb_fiber_current(VALUE self) { + return rb_fiber_current(); +} + +VALUE fiber_spec_rb_fiber_alive_p(VALUE self, VALUE fiber) { + return rb_fiber_alive_p(fiber); +} + +VALUE fiber_spec_rb_fiber_resume(VALUE self, VALUE fiber, VALUE ary) { + long argc = RARRAY_LEN(ary); + VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc); + int i; + + for (i = 0; i < argc; i++) { + argv[i] = rb_ary_entry(ary, i); + } + + return rb_fiber_resume(fiber, (int)argc, argv); +} + +VALUE fiber_spec_rb_fiber_yield(VALUE self, VALUE ary) { + long argc = RARRAY_LEN(ary); + VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc); + int i; + + for (i = 0; i < argc; i++) { + argv[i] = rb_ary_entry(ary, i); + } + return rb_fiber_yield((int)argc, argv); +} + +VALUE fiber_spec_rb_fiber_new_function(RB_BLOCK_CALL_FUNC_ARGLIST(args, dummy)) { + return rb_funcall(args, rb_intern("inspect"), 0); +} + +VALUE fiber_spec_rb_fiber_new(VALUE self) { + return rb_fiber_new(fiber_spec_rb_fiber_new_function, Qnil); +} + +#ifdef RUBY_VERSION_IS_3_1 +VALUE fiber_spec_rb_fiber_raise(int argc, VALUE *argv, VALUE self) { + VALUE fiber = argv[0]; + return rb_fiber_raise(fiber, argc-1, argv+1); +} +#endif + +void Init_fiber_spec(void) { + VALUE cls = rb_define_class("CApiFiberSpecs", rb_cObject); + rb_define_method(cls, "rb_fiber_current", fiber_spec_rb_fiber_current, 0); + rb_define_method(cls, "rb_fiber_alive_p", fiber_spec_rb_fiber_alive_p, 1); + rb_define_method(cls, "rb_fiber_resume", fiber_spec_rb_fiber_resume, 2); + rb_define_method(cls, "rb_fiber_yield", fiber_spec_rb_fiber_yield, 1); + rb_define_method(cls, "rb_fiber_new", fiber_spec_rb_fiber_new, 0); + +#ifdef RUBY_VERSION_IS_3_1 + rb_define_method(cls, "rb_fiber_raise", fiber_spec_rb_fiber_raise, -1); +#endif +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/float_spec.c b/ruby/spec/ruby/optional/capi/ext/float_spec.c index 34be91796..3db05cef8 100644 --- a/ruby/spec/ruby/optional/capi/ext/float_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/float_spec.c @@ -25,12 +25,21 @@ static VALUE float_spec_RFLOAT_VALUE(VALUE self, VALUE float_h) { return rb_float_new(RFLOAT_VALUE(float_h)); } +static VALUE float_spec_RB_FLOAT_TYPE_P(VALUE self, VALUE val) { + if (RB_FLOAT_TYPE_P(val)) { + return Qtrue; + } else { + return Qfalse; + } +} + void Init_float_spec(void) { VALUE cls = rb_define_class("CApiFloatSpecs", rb_cObject); rb_define_method(cls, "new_zero", float_spec_new_zero, 0); rb_define_method(cls, "new_point_five", float_spec_new_point_five, 0); rb_define_method(cls, "rb_Float", float_spec_rb_Float, 1); rb_define_method(cls, "RFLOAT_VALUE", float_spec_RFLOAT_VALUE, 1); + rb_define_method(cls, "RB_FLOAT_TYPE_P", float_spec_RB_FLOAT_TYPE_P, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/gc_spec.c b/ruby/spec/ruby/optional/capi/ext/gc_spec.c index 57b1f11fa..7dc9c347c 100644 --- a/ruby/spec/ruby/optional/capi/ext/gc_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/gc_spec.c @@ -16,24 +16,33 @@ static VALUE registered_reference_address(VALUE self) { return registered_reference_value; } -static VALUE gc_spec_rb_gc_enable() { +static VALUE gc_spec_rb_gc_enable(VALUE self) { return rb_gc_enable(); } -static VALUE gc_spec_rb_gc_disable() { +static VALUE gc_spec_rb_gc_disable(VALUE self) { return rb_gc_disable(); } -static VALUE gc_spec_rb_gc() { +static VALUE gc_spec_rb_gc(VALUE self) { rb_gc(); return Qnil; } +static VALUE gc_spec_rb_gc_latest_gc_info(VALUE self, VALUE hash_or_key){ + return rb_gc_latest_gc_info(hash_or_key); +} + static VALUE gc_spec_rb_gc_adjust_memory_usage(VALUE self, VALUE diff) { rb_gc_adjust_memory_usage(NUM2SSIZET(diff)); return Qnil; } +static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) { + rb_gc_register_mark_object(obj); + return Qnil; +} + void Init_gc_spec(void) { VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject); registered_tagged_value = INT2NUM(10); @@ -48,6 +57,8 @@ void Init_gc_spec(void) { rb_define_method(cls, "rb_gc_disable", gc_spec_rb_gc_disable, 0); rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0); rb_define_method(cls, "rb_gc_adjust_memory_usage", gc_spec_rb_gc_adjust_memory_usage, 1); + rb_define_method(cls, "rb_gc_register_mark_object", gc_spec_rb_gc_register_mark_object, 1); + rb_define_method(cls, "rb_gc_latest_gc_info", gc_spec_rb_gc_latest_gc_info, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/globals_spec.c b/ruby/spec/ruby/optional/capi/ext/globals_spec.c index f70622f66..28a9633f9 100644 --- a/ruby/spec/ruby/optional/capi/ext/globals_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/globals_spec.c @@ -7,12 +7,16 @@ extern "C" { VALUE g_hooked_var; +VALUE var_2x_getter(ID id, VALUE *data) { + return *data; +} + void var_2x_setter(VALUE val, ID id, VALUE *var) { - *var = INT2NUM(NUM2INT(val) * 2); + *var = INT2NUM(NUM2INT(val) * 2); } static VALUE sb_define_hooked_variable(VALUE self, VALUE var_name) { - rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, 0, var_2x_setter); + rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, var_2x_getter, var_2x_setter); return Qnil; } @@ -64,6 +68,10 @@ static VALUE global_spec_rb_defout(VALUE self) { return rb_defout; } +static VALUE global_spec_rb_fs(VALUE self) { + return rb_fs; +} + static VALUE global_spec_rb_rs(VALUE self) { return rb_rs; } @@ -105,6 +113,7 @@ void Init_globals_spec(void) { rb_define_method(cls, "rb_stdout", global_spec_rb_stdout, 0); rb_define_method(cls, "rb_stderr", global_spec_rb_stderr, 0); rb_define_method(cls, "rb_defout", global_spec_rb_defout, 0); + rb_define_method(cls, "rb_fs", global_spec_rb_fs, 0); rb_define_method(cls, "rb_rs", global_spec_rb_rs, 0); rb_define_method(cls, "rb_default_rs", global_spec_rb_default_rs, 0); rb_define_method(cls, "rb_output_rs", global_spec_rb_output_rs, 0); diff --git a/ruby/spec/ruby/optional/capi/ext/hash_spec.c b/ruby/spec/ruby/optional/capi/ext/hash_spec.c index c8735cec2..7f3870891 100644 --- a/ruby/spec/ruby/optional/capi/ext/hash_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/hash_spec.c @@ -105,6 +105,12 @@ VALUE hash_spec_rb_hash_new(VALUE self) { return rb_hash_new(); } +VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */ + +VALUE hash_spec_rb_ident_hash_new(VALUE self) { + return rb_ident_hash_new(); +} + VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) { return rb_hash_size(hash); } @@ -113,6 +119,15 @@ VALUE hash_spec_rb_hash_set_ifnone(VALUE self, VALUE hash, VALUE def) { return rb_hash_set_ifnone(hash, def); } +VALUE hash_spec_compute_a_hash_code(VALUE self, VALUE seed) { + int int_seed = FIX2INT(seed); + st_index_t h = rb_hash_start(int_seed); + h = rb_hash_uint32(h, 540u); + h = rb_hash_uint32(h, 340u); + h = rb_hash_end(h); + return ULONG2NUM(h); +} + void Init_hash_spec(void) { VALUE cls = rb_define_class("CApiHashSpecs", rb_cObject); rb_define_method(cls, "rb_hash", hash_spec_rb_hash, 1); @@ -134,8 +149,10 @@ void Init_hash_spec(void) { rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3); rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2); rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0); + rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0); rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1); rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2); + rb_define_method(cls, "compute_a_hash_code", hash_spec_compute_a_hash_code, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/integer_spec.c b/ruby/spec/ruby/optional/capi/ext/integer_spec.c index 7e9e8b26b..16cd95f11 100644 --- a/ruby/spec/ruby/optional/capi/ext/integer_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/integer_spec.c @@ -13,6 +13,12 @@ static VALUE integer_spec_rb_integer_pack(VALUE self, VALUE value, return INT2FIX(result); } +RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); /* internal.h, used in ripper */ + +static VALUE integer_spec_rb_int_positive_pow(VALUE self, VALUE a, VALUE b){ + return rb_int_positive_pow(FIX2INT(a), FIX2INT(b)); +} + void Init_integer_spec(void) { VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject); rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST)); @@ -27,8 +33,9 @@ void Init_integer_spec(void) { rb_define_const(cls, "NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE)); rb_define_method(cls, "rb_integer_pack", integer_spec_rb_integer_pack, 6); + rb_define_method(cls, "rb_int_positive_pow", integer_spec_rb_int_positive_pow, 2); } #ifdef __cplusplus -extern "C" { +} #endif diff --git a/ruby/spec/ruby/optional/capi/ext/io_spec.c b/ruby/spec/ruby/optional/capi/ext/io_spec.c index b656de081..b4ffe9207 100644 --- a/ruby/spec/ruby/optional/capi/ext/io_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/io_spec.c @@ -43,7 +43,7 @@ VALUE io_spec_rb_io_addstr(VALUE self, VALUE io, VALUE str) { VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) { long argc = RARRAY_LEN(ary); - VALUE *argv = alloca(sizeof(VALUE) * argc); + VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc); int i; for (i = 0; i < argc; i++) { @@ -55,7 +55,7 @@ VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) { VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) { long argc = RARRAY_LEN(ary); - VALUE *argv = alloca(sizeof(VALUE) * argc); + VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc); int i; for (i = 0; i < argc; i++) { @@ -67,7 +67,7 @@ VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) { VALUE io_spec_rb_io_puts(VALUE self, VALUE io, VALUE ary) { long argc = RARRAY_LEN(ary); - VALUE *argv = alloca(sizeof(VALUE) * argc); + VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc); int i; for (i = 0; i < argc; i++) { @@ -201,6 +201,21 @@ VALUE io_spec_rb_io_close(VALUE self, VALUE io) { return rb_io_close(io); } +VALUE io_spec_rb_io_set_nonblock(VALUE self, VALUE io) { + rb_io_t* fp; +#ifdef F_GETFL + int flags; +#endif + GetOpenFile(io, fp); + rb_io_set_nonblock(fp); +#ifdef F_GETFL + flags = fcntl(fp->fd, F_GETFL, 0); + return flags & O_NONBLOCK ? Qtrue : Qfalse; +#else + return Qfalse; +#endif +} + /* * this is needed to ensure rb_io_wait_*able functions behave * predictably because errno may be set to unexpected values @@ -212,6 +227,16 @@ static VALUE io_spec_errno_set(VALUE self, VALUE val) { return val; } +VALUE io_spec_mode_sync_flag(VALUE self, VALUE io) { + rb_io_t *fp; + GetOpenFile(io, fp); + if (fp->mode & FMODE_SYNC) { + return Qtrue; + } else { + return Qfalse; + } +} + void Init_io_spec(void) { VALUE cls = rb_define_class("CApiIOSpecs", rb_cObject); rb_define_method(cls, "GetOpenFile_fd", io_spec_GetOpenFile_fd, 1); @@ -225,6 +250,7 @@ void Init_io_spec(void) { rb_define_method(cls, "rb_io_check_readable", io_spec_rb_io_check_readable, 1); rb_define_method(cls, "rb_io_check_writable", io_spec_rb_io_check_writable, 1); rb_define_method(cls, "rb_io_check_closed", io_spec_rb_io_check_closed, 1); + rb_define_method(cls, "rb_io_set_nonblock", io_spec_rb_io_set_nonblock, 1); rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1); rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2); rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1); @@ -235,6 +261,7 @@ void Init_io_spec(void) { rb_define_method(cls, "rb_fd_fix_cloexec", io_spec_rb_fd_fix_cloexec, 1); rb_define_method(cls, "rb_cloexec_open", io_spec_rb_cloexec_open, 3); rb_define_method(cls, "errno=", io_spec_errno_set, 1); + rb_define_method(cls, "rb_io_mode_sync_flag", io_spec_mode_sync_flag, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/kernel_spec.c b/ruby/spec/ruby/optional/capi/ext/kernel_spec.c index e98ae3506..bbfeb198b 100644 --- a/ruby/spec/ruby/optional/capi/ext/kernel_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/kernel_spec.c @@ -68,7 +68,7 @@ VALUE rb_block_call_extra_data(VALUE self, VALUE object) { } VALUE kernel_spec_rb_block_call_no_func(VALUE self, VALUE ary) { - return rb_block_call(ary, rb_intern("map"), 0, NULL, NULL, Qnil); + return rb_block_call(ary, rb_intern("map"), 0, NULL, (rb_block_call_func_t)NULL, Qnil); } @@ -153,6 +153,10 @@ VALUE kernel_spec_rb_rescue(VALUE self, VALUE main_proc, VALUE arg, rb_ary_push(main_array, main_proc); rb_ary_push(main_array, arg); + if (raise_proc == Qnil) { + return rb_rescue(kernel_spec_call_proc, main_array, NULL, arg2); + } + raise_array = rb_ary_new(); rb_ary_push(raise_array, raise_proc); rb_ary_push(raise_array, arg2); @@ -187,6 +191,18 @@ static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) { return res; } +static VALUE kernel_spec_rb_protect_errinfo(VALUE self, VALUE obj, VALUE ary) { + int status = 0; + VALUE res = rb_protect(rb_yield, obj, &status); + rb_ary_store(ary, 0, INT2NUM(23)); + rb_ary_store(ary, 1, res); + return rb_errinfo(); +} + +static VALUE kernel_spec_rb_protect_null_status(VALUE self, VALUE obj) { + return rb_protect(rb_yield, obj, NULL); +} + static VALUE kernel_spec_rb_eval_string_protect(VALUE self, VALUE str, VALUE ary) { int status = 0; VALUE res = rb_eval_string_protect(RSTRING_PTR(str), &status); @@ -262,6 +278,15 @@ static VALUE kernel_spec_rb_yield_values(VALUE self, VALUE obj1, VALUE obj2) { return rb_yield_values(2, obj1, obj2); } +static VALUE kernel_spec_rb_yield_values2(VALUE self, VALUE ary) { + long len = RARRAY_LEN(ary); + VALUE *args = (VALUE*)alloca(sizeof(VALUE) * len); + for (int i = 0; i < len; i++) { + args[i] = rb_ary_entry(ary, i); + } + return rb_yield_values2((int)len, args); +} + static VALUE do_rec(VALUE obj, VALUE arg, int is_rec) { if(is_rec) { return obj; @@ -277,7 +302,7 @@ static VALUE kernel_spec_rb_exec_recursive(VALUE self, VALUE obj) { } static void write_io(VALUE io) { - rb_funcall(io, rb_intern("write"), 1, rb_str_new2("e")); + rb_funcall(io, rb_intern("write"), 1, rb_str_new2("in write_io")); } static VALUE kernel_spec_rb_set_end_proc(VALUE self, VALUE io) { @@ -293,10 +318,6 @@ static VALUE kernel_spec_rb_make_backtrace(VALUE self) { return rb_make_backtrace(); } -static VALUE kernel_spec_rb_obj_method(VALUE self, VALUE obj, VALUE method) { - return rb_obj_method(obj, method); -} - static VALUE kernel_spec_rb_funcall3(VALUE self, VALUE obj, VALUE method) { return rb_funcall3(obj, SYM2ID(method), 0, NULL); } @@ -305,6 +326,13 @@ static VALUE kernel_spec_rb_funcall_with_block(VALUE self, VALUE obj, VALUE meth return rb_funcall_with_block(obj, SYM2ID(method), 0, NULL, block); } +static VALUE kernel_spec_rb_funcall_many_args(VALUE self, VALUE obj, VALUE method) { + return rb_funcall(obj, SYM2ID(method), 15, + INT2FIX(15), INT2FIX(14), INT2FIX(13), INT2FIX(12), INT2FIX(11), + INT2FIX(10), INT2FIX(9), INT2FIX(8), INT2FIX(7), INT2FIX(6), + INT2FIX(5), INT2FIX(4), INT2FIX(3), INT2FIX(2), INT2FIX(1)); +} + void Init_kernel_spec(void) { VALUE cls = rb_define_class("CApiKernelSpecs", rb_cObject); rb_define_method(cls, "rb_block_given_p", kernel_spec_rb_block_given_p, 0); @@ -325,6 +353,8 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4); rb_define_method(cls, "rb_rescue2", kernel_spec_rb_rescue2, -1); rb_define_method(cls, "rb_protect_yield", kernel_spec_rb_protect_yield, 2); + rb_define_method(cls, "rb_protect_errinfo", kernel_spec_rb_protect_errinfo, 2); + rb_define_method(cls, "rb_protect_null_status", kernel_spec_rb_protect_null_status, 1); rb_define_method(cls, "rb_eval_string_protect", kernel_spec_rb_eval_string_protect, 2); rb_define_method(cls, "rb_catch", kernel_spec_rb_catch, 2); rb_define_method(cls, "rb_catch_obj", kernel_spec_rb_catch_obj, 2); @@ -335,13 +365,14 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_yield_indirected", kernel_spec_rb_yield_indirected, 1); rb_define_method(cls, "rb_yield_define_each", kernel_spec_rb_yield_define_each, 1); rb_define_method(cls, "rb_yield_values", kernel_spec_rb_yield_values, 2); + rb_define_method(cls, "rb_yield_values2", kernel_spec_rb_yield_values2, 1); rb_define_method(cls, "rb_yield_splat", kernel_spec_rb_yield_splat, 1); rb_define_method(cls, "rb_exec_recursive", kernel_spec_rb_exec_recursive, 1); rb_define_method(cls, "rb_set_end_proc", kernel_spec_rb_set_end_proc, 1); rb_define_method(cls, "rb_f_sprintf", kernel_spec_rb_f_sprintf, 1); rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0); - rb_define_method(cls, "rb_obj_method", kernel_spec_rb_obj_method, 2); rb_define_method(cls, "rb_funcall3", kernel_spec_rb_funcall3, 2); + rb_define_method(cls, "rb_funcall_many_args", kernel_spec_rb_funcall_many_args, 2); rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 3); } diff --git a/ruby/spec/ruby/optional/capi/ext/language_spec.c b/ruby/spec/ruby/optional/capi/ext/language_spec.c new file mode 100644 index 000000000..749c18895 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/language_spec.c @@ -0,0 +1,42 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE language_spec_switch(VALUE self, VALUE value) { + if (value == ID2SYM(rb_intern("undef"))) { + value = Qundef; + } + + switch (value) { + case Qtrue: + return ID2SYM(rb_intern("true")); + case Qfalse: + return ID2SYM(rb_intern("false")); + case Qnil: + return ID2SYM(rb_intern("nil")); + case Qundef: + return ID2SYM(rb_intern("undef")); + default: + return ID2SYM(rb_intern("default")); + } +} + +/* Defining a local variable rb_mProcess which already exists as a global variable + * For instance eventmachine does this in Init_rubyeventmachine() */ +static VALUE language_spec_global_local_var(VALUE self) { + VALUE rb_mProcess = rb_const_get(rb_cObject, rb_intern("Process")); + return rb_mProcess; +} + +void Init_language_spec(void) { + VALUE cls = rb_define_class("CApiLanguageSpecs", rb_cObject); + rb_define_method(cls, "switch", language_spec_switch, 1); + rb_define_method(cls, "global_local_var", language_spec_global_local_var, 0); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/module_spec.c b/ruby/spec/ruby/optional/capi/ext/module_spec.c index 3c8455a94..7475994fa 100644 --- a/ruby/spec/ruby/optional/capi/ext/module_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/module_spec.c @@ -9,6 +9,18 @@ static VALUE module_specs_test_method(VALUE self) { return ID2SYM(rb_intern("test_method")); } +static VALUE module_specs_test_method_2required(VALUE self, VALUE arg1, VALUE arg2) { + return ID2SYM(rb_intern("test_method_2required")); +} + +static VALUE module_specs_test_method_c_array(int argc, VALUE *argv, VALUE self) { + return ID2SYM(rb_intern("test_method_c_array")); +} + +static VALUE module_specs_test_method_ruby_array(VALUE self, VALUE args) { + return ID2SYM(rb_intern("test_method_ruby_array")); +} + static VALUE module_specs_const_defined(VALUE self, VALUE klass, VALUE id) { return rb_const_defined(klass, SYM2ID(id)) ? Qtrue : Qfalse; } @@ -76,6 +88,21 @@ static VALUE module_specs_rb_define_method(VALUE self, VALUE cls, VALUE str_name return Qnil; } +static VALUE module_specs_rb_define_method_2required(VALUE self, VALUE cls, VALUE str_name) { + rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_2required, 2); + return Qnil; +} + +static VALUE module_specs_rb_define_method_c_array(VALUE self, VALUE cls, VALUE str_name) { + rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_c_array, -1); + return Qnil; +} + +static VALUE module_specs_rb_define_method_ruby_array(VALUE self, VALUE cls, VALUE str_name) { + rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_ruby_array, -2); + return Qnil; +} + static VALUE module_specs_rb_define_module_function(VALUE self, VALUE cls, VALUE str_name) { rb_define_module_function(cls, RSTRING_PTR(str_name), module_specs_test_method, 0); return Qnil; @@ -132,6 +159,10 @@ void Init_module_spec(void) { module_specs_rb_define_global_function, 1); rb_define_method(cls, "rb_define_method", module_specs_rb_define_method, 2); + rb_define_method(cls, "rb_define_method_2required", module_specs_rb_define_method_2required, 2); + rb_define_method(cls, "rb_define_method_c_array", module_specs_rb_define_method_c_array, 2); + rb_define_method(cls, "rb_define_method_ruby_array", module_specs_rb_define_method_ruby_array, 2); + rb_define_method(cls, "rb_define_module_function", module_specs_rb_define_module_function, 2); diff --git a/ruby/spec/ruby/optional/capi/ext/module_under_autoload_spec.c b/ruby/spec/ruby/optional/capi/ext/module_under_autoload_spec.c index c8f19a287..b19466e55 100644 --- a/ruby/spec/ruby/optional/capi/ext/module_under_autoload_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/module_under_autoload_spec.c @@ -1,7 +1,15 @@ #include "ruby.h" +#ifdef __cplusplus +extern "C" { +#endif + void Init_module_under_autoload_spec(void) { VALUE specs = rb_const_get(rb_cObject, rb_intern("CApiModuleSpecs")); rb_define_module_under(specs, "ModuleUnderAutoload"); rb_define_module_under(specs, "RubyUnderAutoload"); } + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/numeric_spec.c b/ruby/spec/ruby/optional/capi/ext/numeric_spec.c index 556c71a58..d3639580a 100644 --- a/ruby/spec/ruby/optional/capi/ext/numeric_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/numeric_spec.c @@ -54,13 +54,17 @@ static VALUE numeric_spec_NUM2INT(VALUE self, VALUE num) { } static VALUE numeric_spec_INT2NUM(VALUE self, VALUE num) { - return INT2NUM(NUM2LONG(num)); + return INT2NUM(NUM2INT(num)); } static VALUE numeric_spec_NUM2LONG(VALUE self, VALUE num) { return LONG2NUM(NUM2LONG(num)); } +static VALUE numeric_spec_NUM2SHORT(VALUE self, VALUE num) { + return LONG2NUM(NUM2SHORT(num)); +} + static VALUE numeric_spec_NUM2UINT(VALUE self, VALUE num) { return ULONG2NUM(NUM2UINT(num)); } @@ -109,6 +113,7 @@ void Init_numeric_spec(void) { rb_define_method(cls, "NUM2DBL", numeric_spec_NUM2DBL, 1); rb_define_method(cls, "NUM2INT", numeric_spec_NUM2INT, 1); rb_define_method(cls, "NUM2LONG", numeric_spec_NUM2LONG, 1); + rb_define_method(cls, "NUM2SHORT", numeric_spec_NUM2SHORT, 1); rb_define_method(cls, "INT2NUM", numeric_spec_INT2NUM, 1); rb_define_method(cls, "NUM2UINT", numeric_spec_NUM2UINT, 1); rb_define_method(cls, "NUM2ULONG", numeric_spec_NUM2ULONG, 1); diff --git a/ruby/spec/ruby/optional/capi/ext/object_spec.c b/ruby/spec/ruby/optional/capi/ext/object_spec.c index cd32050f1..c1f3b09ff 100644 --- a/ruby/spec/ruby/optional/capi/ext/object_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/object_spec.c @@ -15,9 +15,12 @@ static VALUE object_spec_FL_ABLE(VALUE self, VALUE obj) { static int object_spec_FL_TEST_flag(VALUE flag_string) { char *flag_cstr = StringValueCStr(flag_string); +#ifndef RUBY_VERSION_IS_3_1 if (strcmp(flag_cstr, "FL_TAINT") == 0) { return FL_TAINT; - } else if (strcmp(flag_cstr, "FL_FREEZE") == 0) { + } +#endif + if (strcmp(flag_cstr, "FL_FREEZE") == 0) { return FL_FREEZE; } return 0; @@ -27,6 +30,7 @@ static VALUE object_spec_FL_TEST(VALUE self, VALUE obj, VALUE flag) { return INT2FIX(FL_TEST(obj, object_spec_FL_TEST_flag(flag))); } +#ifndef RUBY_VERSION_IS_3_1 static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) { OBJ_TAINT(obj); return Qnil; @@ -40,6 +44,7 @@ static VALUE object_spec_OBJ_INFECT(VALUE self, VALUE host, VALUE source) { OBJ_INFECT(host, source); return Qnil; } +#endif static VALUE object_spec_rb_any_to_s(VALUE self, VALUE obj) { return rb_any_to_s(obj); @@ -102,7 +107,7 @@ static VALUE so_rb_obj_dup(VALUE self, VALUE klass) { static VALUE so_rb_obj_call_init(VALUE self, VALUE object, VALUE nargs, VALUE args) { int c_nargs = FIX2INT(nargs); - VALUE *c_args = alloca(sizeof(VALUE) * c_nargs); + VALUE *c_args = (VALUE*) alloca(sizeof(VALUE) * c_nargs); int i; for (i = 0; i < c_nargs; i++) @@ -142,10 +147,32 @@ static VALUE object_specs_rb_obj_method_arity(VALUE self, VALUE obj, VALUE mid) return INT2FIX(rb_obj_method_arity(obj, SYM2ID(mid))); } +static VALUE object_specs_rb_obj_method(VALUE self, VALUE obj, VALUE method) { + return rb_obj_method(obj, method); +} + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated-declarations") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) { return rb_obj_taint(obj); } +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic pop +#elif defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated-declarations") +# pragma clang diagnostic pop +# endif +#endif + static VALUE so_require(VALUE self) { rb_require("fixtures/foo"); return Qnil; @@ -180,6 +207,11 @@ static VALUE object_spec_RTEST(VALUE self, VALUE value) { return RTEST(value) ? Qtrue : Qfalse; } +static VALUE so_check_type(VALUE self, VALUE obj, VALUE other) { + rb_check_type(obj, TYPE(other)); + return Qtrue; +} + static VALUE so_is_type_nil(VALUE self, VALUE obj) { if(TYPE(obj) == T_NIL) { return Qtrue; @@ -315,6 +347,10 @@ static VALUE object_spec_rb_iv_set(VALUE self, VALUE obj, VALUE name, VALUE valu return rb_iv_set(obj, RSTRING_PTR(name), value); } +static VALUE object_spec_rb_ivar_count(VALUE self, VALUE obj) { + return ULONG2NUM(rb_ivar_count(obj)); +} + static VALUE object_spec_rb_ivar_get(VALUE self, VALUE obj, VALUE sym_name) { return rb_ivar_get(obj, SYM2ID(sym_name)); } @@ -345,14 +381,50 @@ static VALUE object_spec_rb_class_inherited_p(VALUE self, VALUE mod, VALUE arg) return rb_class_inherited_p(mod, arg); } +static VALUE speced_allocator(VALUE klass) { + VALUE flags = 0; + VALUE instance; + if (RTEST(rb_class_inherited_p(klass, rb_cString))) { + flags = T_STRING; + } else if (RTEST(rb_class_inherited_p(klass, rb_cArray))) { + flags = T_ARRAY; + } else { + flags = T_OBJECT; + } + instance = rb_newobj_of(klass, flags); + rb_iv_set(instance, "@from_custom_allocator", Qtrue); + return instance; +} + +static VALUE define_alloc_func(VALUE self, VALUE klass) { + rb_define_alloc_func(klass, speced_allocator); + return Qnil; +} + +static VALUE undef_alloc_func(VALUE self, VALUE klass) { + rb_undef_alloc_func(klass); + return Qnil; +} + +static VALUE speced_allocator_p(VALUE self, VALUE klass) { + rb_alloc_func_t allocator = rb_get_alloc_func(klass); + return (allocator == speced_allocator) ? Qtrue : Qfalse; +} + +static VALUE custom_alloc_func_p(VALUE self, VALUE klass) { + rb_alloc_func_t allocator = rb_get_alloc_func(klass); + return allocator ? Qtrue : Qfalse; +} void Init_object_spec(void) { VALUE cls = rb_define_class("CApiObjectSpecs", rb_cObject); rb_define_method(cls, "FL_ABLE", object_spec_FL_ABLE, 1); rb_define_method(cls, "FL_TEST", object_spec_FL_TEST, 2); +#ifndef RUBY_VERSION_IS_3_1 rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1); rb_define_method(cls, "OBJ_TAINTED", object_spec_OBJ_TAINTED, 1); rb_define_method(cls, "OBJ_INFECT", object_spec_OBJ_INFECT, 2); +#endif rb_define_method(cls, "rb_any_to_s", object_spec_rb_any_to_s, 1); rb_define_method(cls, "rb_attr_get", so_attr_get, 2); rb_define_method(cls, "rb_obj_instance_variables", object_spec_rb_obj_instance_variables, 1); @@ -375,6 +447,7 @@ void Init_object_spec(void) { rb_define_method(cls, "rb_obj_is_instance_of", so_instance_of, 2); rb_define_method(cls, "rb_obj_is_kind_of", so_kind_of, 2); rb_define_method(cls, "rb_obj_method_arity", object_specs_rb_obj_method_arity, 2); + rb_define_method(cls, "rb_obj_method", object_specs_rb_obj_method, 2); rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1); rb_define_method(cls, "rb_require", so_require, 0); rb_define_method(cls, "rb_respond_to", so_respond_to, 2); @@ -384,6 +457,7 @@ void Init_object_spec(void) { rb_define_method(cls, "rb_to_id", so_to_id, 1); rb_define_method(cls, "RTEST", object_spec_RTEST, 1); + rb_define_method(cls, "rb_check_type", so_check_type, 2); rb_define_method(cls, "rb_is_type_nil", so_is_type_nil, 1); rb_define_method(cls, "rb_is_type_object", so_is_type_object, 1); rb_define_method(cls, "rb_is_type_array", so_is_type_array, 1); @@ -407,11 +481,17 @@ void Init_object_spec(void) { rb_define_method(cls, "rb_obj_instance_eval", object_spec_rb_obj_instance_eval, 1); rb_define_method(cls, "rb_iv_get", object_spec_rb_iv_get, 2); rb_define_method(cls, "rb_iv_set", object_spec_rb_iv_set, 3); + rb_define_method(cls, "rb_ivar_count", object_spec_rb_ivar_count, 1); rb_define_method(cls, "rb_ivar_get", object_spec_rb_ivar_get, 2); rb_define_method(cls, "rb_ivar_set", object_spec_rb_ivar_set, 3); rb_define_method(cls, "rb_ivar_defined", object_spec_rb_ivar_defined, 2); rb_define_method(cls, "rb_copy_generic_ivar", object_spec_rb_copy_generic_ivar, 2); rb_define_method(cls, "rb_free_generic_ivar", object_spec_rb_free_generic_ivar, 1); + rb_define_method(cls, "rb_define_alloc_func", define_alloc_func, 1); + rb_define_method(cls, "rb_undef_alloc_func", undef_alloc_func, 1); + rb_define_method(cls, "speced_allocator?", speced_allocator_p, 1); + rb_define_method(cls, "custom_alloc_func?", custom_alloc_func_p, 1); + rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/proc_spec.c b/ruby/spec/ruby/optional/capi/ext/proc_spec.c index 18fd1997e..e0bd8b1bb 100644 --- a/ruby/spec/ruby/optional/capi/ext/proc_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/proc_spec.c @@ -23,6 +23,10 @@ VALUE proc_spec_rb_proc_call(VALUE self, VALUE prc, VALUE args) { return rb_proc_call(prc, args); } +VALUE proc_spec_rb_obj_is_proc(VALUE self, VALUE prc) { + return rb_obj_is_proc(prc); +} + /* This helper is not strictly necessary but reflects the code in wxRuby that * originally exposed issues with this Proc.new behavior. */ @@ -61,6 +65,7 @@ void Init_proc_spec(void) { rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1); rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2); rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1); + rb_define_method(cls, "rb_obj_is_proc", proc_spec_rb_obj_is_proc, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/rbasic_spec.c b/ruby/spec/ruby/optional/capi/ext/rbasic_spec.c new file mode 100644 index 000000000..9178e5f63 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/rbasic_spec.c @@ -0,0 +1,100 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef FL_SHAREABLE +static const VALUE VISIBLE_BITS = FL_TAINT | FL_FREEZE; +static const VALUE DATA_VISIBLE_BITS = FL_TAINT | FL_FREEZE | ~(FL_USER0 - 1); +#else +static const VALUE VISIBLE_BITS = FL_FREEZE; +static const VALUE DATA_VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1); +#endif + +#if SIZEOF_VALUE == SIZEOF_LONG +#define VALUE2NUM(v) ULONG2NUM(v) +#define NUM2VALUE(n) NUM2ULONG(n) +#elif SIZEOF_VALUE == SIZEOF_LONG_LONG +#define VALUE2NUM(v) ULL2NUM(v) +#define NUM2VALUE(n) NUM2ULL(n) +#else +#error "unsupported" +#endif + + +#ifndef RUBY_VERSION_IS_3_1 +VALUE rbasic_spec_taint_flag(VALUE self) { + return VALUE2NUM(RUBY_FL_TAINT); +} +#endif + +VALUE rbasic_spec_freeze_flag(VALUE self) { + return VALUE2NUM(RUBY_FL_FREEZE); +} + + static VALUE spec_get_flags(const struct RBasic *b, VALUE visible_bits) { + VALUE flags = b->flags & visible_bits; + return VALUE2NUM(flags); +} + +static VALUE spec_set_flags(struct RBasic *b, VALUE flags, VALUE visible_bits) { + flags &= visible_bits; + b->flags = (b->flags & ~visible_bits) | flags; + return VALUE2NUM(flags); +} + +VALUE rbasic_spec_get_flags(VALUE self, VALUE val) { + return spec_get_flags(RBASIC(val), VISIBLE_BITS); +} + +VALUE rbasic_spec_set_flags(VALUE self, VALUE val, VALUE flags) { + return spec_set_flags(RBASIC(val), NUM2VALUE(flags), VISIBLE_BITS); +} + +VALUE rbasic_spec_copy_flags(VALUE self, VALUE to, VALUE from) { + return spec_set_flags(RBASIC(to), RBASIC(from)->flags, VISIBLE_BITS); +} + +VALUE rbasic_spec_get_klass(VALUE self, VALUE val) { + return RBASIC(val)->klass; +} + +VALUE rbasic_rdata_spec_get_flags(VALUE self, VALUE structure) { + return spec_get_flags(&RDATA(structure)->basic, DATA_VISIBLE_BITS); +} + +VALUE rbasic_rdata_spec_set_flags(VALUE self, VALUE structure, VALUE flags) { + return spec_set_flags(&RDATA(structure)->basic, NUM2VALUE(flags), DATA_VISIBLE_BITS); +} + +VALUE rbasic_rdata_spec_copy_flags(VALUE self, VALUE to, VALUE from) { + return spec_set_flags(&RDATA(to)->basic, RDATA(from)->basic.flags, DATA_VISIBLE_BITS); +} + +VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) { + return RDATA(structure)->basic.klass; +} + +void Init_rbasic_spec(void) { + VALUE cls = rb_define_class("CApiRBasicSpecs", rb_cObject); +#ifndef RUBY_VERSION_IS_3_1 + rb_define_method(cls, "taint_flag", rbasic_spec_taint_flag, 0); +#endif + rb_define_method(cls, "freeze_flag", rbasic_spec_freeze_flag, 0); + rb_define_method(cls, "get_flags", rbasic_spec_get_flags, 1); + rb_define_method(cls, "set_flags", rbasic_spec_set_flags, 2); + rb_define_method(cls, "copy_flags", rbasic_spec_copy_flags, 2); + rb_define_method(cls, "get_klass", rbasic_spec_get_klass, 1); + + cls = rb_define_class("CApiRBasicRDataSpecs", rb_cObject); + rb_define_method(cls, "get_flags", rbasic_rdata_spec_get_flags, 1); + rb_define_method(cls, "set_flags", rbasic_rdata_spec_set_flags, 2); + rb_define_method(cls, "copy_flags", rbasic_rdata_spec_copy_flags, 2); + rb_define_method(cls, "get_klass", rbasic_rdata_spec_get_klass, 1); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/regexp_spec.c b/ruby/spec/ruby/optional/capi/ext/regexp_spec.c index fc1c8b1e6..0a62616f3 100644 --- a/ruby/spec/ruby/optional/capi/ext/regexp_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/regexp_spec.c @@ -9,8 +9,10 @@ extern "C" { #endif -VALUE regexp_spec_re(VALUE self) { - return rb_reg_new("a", 1, 0); +VALUE regexp_spec_re(VALUE self, VALUE str, VALUE options) { + char *cstr = StringValueCStr(str); + int opts = FIX2INT(options); + return rb_reg_new(cstr, strlen(cstr), opts); } VALUE regexp_spec_reg_1st_match(VALUE self, VALUE md) { @@ -33,6 +35,16 @@ VALUE regexp_spec_backref_get(VALUE self) { return rb_backref_get(); } +static VALUE regexp_spec_backref_set(VALUE self, VALUE backref) { + rb_backref_set(backref); + return Qnil; +} + +VALUE regexp_spec_reg_match_backref_get(VALUE self, VALUE re, VALUE str) { + rb_reg_match(re, str); + return rb_backref_get(); +} + VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) { return rb_funcall(regexp, rb_intern("match"), 1, str); } @@ -40,10 +52,12 @@ VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) { void Init_regexp_spec(void) { VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject); rb_define_method(cls, "match", regexp_spec_match, 2); - rb_define_method(cls, "a_re", regexp_spec_re, 0); + rb_define_method(cls, "a_re", regexp_spec_re, 2); rb_define_method(cls, "a_re_1st_match", regexp_spec_reg_1st_match, 1); rb_define_method(cls, "rb_reg_match", regexp_spec_reg_match, 2); rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0); + rb_define_method(cls, "rb_backref_set", regexp_spec_backref_set, 1); + rb_define_method(cls, "rb_reg_match_backref_get", regexp_spec_reg_match_backref_get, 2); rb_define_method(cls, "rb_reg_options", regexp_spec_rb_reg_options, 1); rb_define_method(cls, "rb_reg_regcomp", regexp_spec_rb_reg_regcomp, 1); } diff --git a/ruby/spec/ruby/optional/capi/ext/rubyspec.h b/ruby/spec/ruby/optional/capi/ext/rubyspec.h index 78e298fdd..7e4a252b3 100644 --- a/ruby/spec/ruby/optional/capi/ext/rubyspec.h +++ b/ruby/spec/ruby/optional/capi/ext/rubyspec.h @@ -1,9 +1,8 @@ #ifndef RUBYSPEC_H #define RUBYSPEC_H -/* Define convenience macros similar to the mspec guards to assist - * with version incompatibilities. - */ +/* Define convenience macros similar to the mspec + * guards to assist with version incompatibilities. */ #include #ifdef HAVE_RUBY_VERSION_H @@ -23,12 +22,42 @@ (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \ (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny))) +#if RUBY_VERSION_MAJOR > 3 || (RUBY_VERSION_MAJOR == 3 && RUBY_VERSION_MINOR >= 1) +#define RUBY_VERSION_IS_3_1 +#endif + +#if RUBY_VERSION_MAJOR > 3 || (RUBY_VERSION_MAJOR == 3 && RUBY_VERSION_MINOR >= 0) +#define RUBY_VERSION_IS_3_0 +#endif + +#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 7) +#define RUBY_VERSION_IS_2_7 +#endif + #if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 6) #define RUBY_VERSION_IS_2_6 #endif -#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 4) -#define RUBY_VERSION_IS_2_4 +#if defined(__cplusplus) && !defined(RUBY_VERSION_IS_2_7) +/* Ruby < 2.7 needs this to let these function with callbacks and compile in C++ code */ +#define rb_define_method(mod, name, func, argc) rb_define_method(mod, name, RUBY_METHOD_FUNC(func), argc) +#define rb_define_protected_method(mod, name, func, argc) rb_define_protected_method(mod, name, RUBY_METHOD_FUNC(func), argc) +#define rb_define_private_method(mod, name, func, argc) rb_define_private_method(mod, name, RUBY_METHOD_FUNC(func), argc) +#define rb_define_singleton_method(mod, name, func, argc) rb_define_singleton_method(mod, name, RUBY_METHOD_FUNC(func), argc) +#define rb_define_module_function(mod, name, func, argc) rb_define_module_function(mod, name, RUBY_METHOD_FUNC(func), argc) +#define rb_define_global_function(name, func, argc) rb_define_global_function(name, RUBY_METHOD_FUNC(func), argc) +#define rb_hash_foreach(hash, func, farg) rb_hash_foreach(hash, (int (*)(...))func, farg) +#define st_foreach(tab, func, arg) st_foreach(tab, (int (*)(...))func, arg) +#define rb_block_call(object, name, args_count, args, block_call_func, data) rb_block_call(object, name, args_count, args, RUBY_METHOD_FUNC(block_call_func), data) +#define rb_ensure(b_proc, data1, e_proc, data2) rb_ensure(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2) +#define rb_rescue(b_proc, data1, e_proc, data2) rb_rescue(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2) +#define rb_rescue2(b_proc, data1, e_proc, data2, ...) rb_rescue2(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2, __VA_ARGS__) +#define rb_catch(tag, func, data) rb_catch(tag, RUBY_METHOD_FUNC(func), data) +#define rb_catch_obj(tag, func, data) rb_catch_obj(tag, RUBY_METHOD_FUNC(func), data) +#define rb_proc_new(fn, arg) rb_proc_new(RUBY_METHOD_FUNC(fn), arg) +#define rb_fiber_new(fn, arg) rb_fiber_new(RUBY_METHOD_FUNC(fn), arg) +#define rb_thread_create(fn, arg) rb_thread_create(RUBY_METHOD_FUNC(fn), arg) +#define rb_define_hooked_variable(name, var, getter, setter) rb_define_hooked_variable(name, var, RUBY_METHOD_FUNC(getter), (void (*)(...))setter) #endif #endif diff --git a/ruby/spec/ruby/optional/capi/ext/string_spec.c b/ruby/spec/ruby/optional/capi/ext/string_spec.c index a44e437bb..2a21304a1 100644 --- a/ruby/spec/ruby/optional/capi/ext/string_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/string_spec.c @@ -1,8 +1,10 @@ #include "ruby.h" #include "rubyspec.h" +#include #include #include +#include #include "ruby/encoding.h" @@ -49,6 +51,12 @@ VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) { return INT2FIX(RSTRING_LEN(str)); } +VALUE rb_fstring(VALUE str); /* internal.h, used in ripper */ + +VALUE string_spec_rb_str_fstring(VALUE self, VALUE str) { + return rb_fstring(str); +} + VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) { VALUE buf; @@ -69,12 +77,28 @@ VALUE string_spec_rb_str_buf_new2(VALUE self) { return rb_str_buf_new2("hello\0invisible"); } +VALUE string_spec_rb_str_tmp_new(VALUE self, VALUE len) { + VALUE str = rb_str_tmp_new(NUM2LONG(len)); + rb_obj_reveal(str, rb_cString); + return str; +} + +VALUE string_spec_rb_str_tmp_new_klass(VALUE self, VALUE len) { + return RBASIC_CLASS(rb_str_tmp_new(NUM2LONG(len))); +} + VALUE string_spec_rb_str_buf_cat(VALUE self, VALUE str) { const char *question_mark = "?"; rb_str_buf_cat(str, question_mark, strlen(question_mark)); return str; } +VALUE string_spec_rb_enc_str_buf_cat(VALUE self, VALUE str, VALUE other, VALUE encoding) { + char *cstr = StringValueCStr(other); + rb_encoding* enc = rb_to_encoding(encoding); + return rb_enc_str_buf_cat(str, cstr, strlen(cstr), enc); +} + VALUE string_spec_rb_str_cat(VALUE self, VALUE str) { return rb_str_cat(str, "?", 1); } @@ -83,6 +107,14 @@ VALUE string_spec_rb_str_cat2(VALUE self, VALUE str) { return rb_str_cat2(str, "?"); } +VALUE string_spec_rb_str_cat_cstr(VALUE self, VALUE str, VALUE other) { + return rb_str_cat_cstr(str, StringValueCStr(other)); +} + +VALUE string_spec_rb_str_cat_cstr_constant(VALUE self, VALUE str) { + return rb_str_cat_cstr(str, "?"); +} + VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) { return INT2NUM(rb_str_cmp(str1, str2)); } @@ -219,6 +251,16 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) { return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len)); } +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated-declarations") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) { return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len)); } @@ -227,6 +269,14 @@ VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) { return rb_tainted_str_new2(RSTRING_PTR(str)); } +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic pop +#elif defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated-declarations") +# pragma clang diagnostic pop +# endif +#endif + VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) { return rb_str_plus(str1, str2); } @@ -249,6 +299,16 @@ VALUE string_spec_rb_str_resize_RSTRING_LEN(VALUE self, VALUE str, VALUE size) { return INT2FIX(RSTRING_LEN(modified)); } +VALUE string_spec_rb_str_resize_copy(VALUE self, VALUE str) { + rb_str_modify_expand(str, 5); + char *buffer = RSTRING_PTR(str); + buffer[1] = 'e'; + buffer[2] = 's'; + buffer[3] = 't'; + rb_str_resize(str, 4); + return str; +} + VALUE string_spec_rb_str_split(VALUE self, VALUE str) { return rb_str_split(str, ","); } @@ -284,6 +344,25 @@ VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) { return Qnil; } +VALUE string_spec_RSTRING_PTR_iterate_uint32(VALUE self, VALUE str) { + uint32_t* ptr; + long i, l = RSTRING_LEN(str) / sizeof(uint32_t); + + ptr = (uint32_t *)RSTRING_PTR(str); + for(i = 0; i < l; i++) { + rb_yield(UINT2NUM(ptr[i])); + } + return Qnil; +} + +VALUE string_spec_RSTRING_PTR_short_memcpy(VALUE self, VALUE str) { + /* Short memcpy operations may be optimised by the compiler to a single write. */ + if (RSTRING_LEN(str) >= 8) { + memcpy(RSTRING_PTR(str), "Infinity", 8); + } + return str; +} + VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) { int i; char c; @@ -325,6 +404,33 @@ VALUE string_spec_RSTRING_PTR_after_yield(VALUE self, VALUE str) { return from_rstring_ptr; } +VALUE string_spec_RSTRING_PTR_read(VALUE self, VALUE str, VALUE path) { + char *cpath = StringValueCStr(path); + int fd = open(cpath, O_RDONLY); + VALUE capacities = rb_ary_new(); + if (fd < 0) { + rb_syserr_fail(errno, "open"); + } + + rb_str_modify_expand(str, 30); + rb_ary_push(capacities, SIZET2NUM(rb_str_capacity(str))); + char *buffer = RSTRING_PTR(str); + if (read(fd, buffer, 30) < 0) { + rb_syserr_fail(errno, "read"); + } + + rb_str_modify_expand(str, 53); + rb_ary_push(capacities, SIZET2NUM(rb_str_capacity(str))); + char *buffer2 = RSTRING_PTR(str); + if (read(fd, buffer2 + 30, 53 - 30) < 0) { + rb_syserr_fail(errno, "read"); + } + + rb_str_set_len(str, 53); + close(fd); + return capacities; +} + VALUE string_spec_StringValue(VALUE self, VALUE str) { return StringValue(str); } @@ -337,11 +443,7 @@ static VALUE string_spec_SafeStringValue(VALUE self, VALUE str) { static VALUE string_spec_rb_str_hash(VALUE self, VALUE str) { st_index_t val = rb_str_hash(str); -#if SIZEOF_LONG == SIZEOF_VOIDP || SIZEOF_LONG_LONG == SIZEOF_VOIDP - return LONG2FIX((long)val); -#else -#error unsupported platform -#endif + return ST2FIX(val); } static VALUE string_spec_rb_str_update(VALUE self, VALUE str, VALUE beg, VALUE end, VALUE replacement) { @@ -362,13 +464,40 @@ static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE r } static VALUE string_spec_rb_sprintf3(VALUE self, VALUE str) { - return rb_sprintf("Result: %"PRIsVALUE".", str); + return rb_sprintf("Result: %" PRIsVALUE ".", str); } static VALUE string_spec_rb_sprintf4(VALUE self, VALUE str) { - return rb_sprintf("Result: %+"PRIsVALUE".", str); + return rb_sprintf("Result: %+" PRIsVALUE ".", str); +} + +static VALUE string_spec_rb_sprintf5(VALUE self, VALUE width, VALUE precision, VALUE str) { + return rb_sprintf("Result: %*.*s.", FIX2INT(width), FIX2INT(precision), RSTRING_PTR(str)); +} + +static VALUE string_spec_rb_sprintf6(VALUE self, VALUE width, VALUE precision, VALUE str) { + return rb_sprintf("Result: %*.*" PRIsVALUE ".", FIX2INT(width), FIX2INT(precision), str); +} + +static VALUE string_spec_rb_sprintf7(VALUE self, VALUE str, VALUE obj) { + VALUE results = rb_ary_new(); + rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), obj)); + char cstr[256]; + int len = snprintf(cstr, 256, RSTRING_PTR(str), obj); + rb_ary_push(results, rb_str_new(cstr, len)); + return results; +} + +static VALUE string_spec_rb_sprintf8(VALUE self, VALUE str, VALUE num) { + VALUE results = rb_ary_new(); + rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), FIX2LONG(num))); + char cstr[256]; + int len = snprintf(cstr, 256, RSTRING_PTR(str), FIX2LONG(num)); + rb_ary_push(results, rb_str_new(cstr, len)); + return results; } +PRINTF_ARGS(static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...), 1, 2); static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) { va_list varargs; VALUE str; @@ -393,6 +522,14 @@ static VALUE string_spec_rb_usascii_str_new(VALUE self, VALUE str, VALUE len) { return rb_usascii_str_new(RSTRING_PTR(str), NUM2INT(len)); } +static VALUE string_spec_rb_usascii_str_new_lit(VALUE self) { + return rb_usascii_str_new_lit("nokogiri"); +} + +static VALUE string_spec_rb_usascii_str_new_lit_non_ascii(VALUE self) { + return rb_usascii_str_new_lit("r\xc3\xa9sum\xc3\xa9"); +} + static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) { return rb_usascii_str_new_cstr(RSTRING_PTR(str)); } @@ -423,18 +560,49 @@ static VALUE string_spec_rb_utf8_str_new_cstr(VALUE self) { return rb_utf8_str_new_cstr("nokogiri"); } +PRINTF_ARGS(static VALUE call_rb_str_vcatf(VALUE mesg, const char *fmt, ...), 2, 3); +static VALUE call_rb_str_vcatf(VALUE mesg, const char *fmt, ...){ + va_list ap; + va_start(ap, fmt); + VALUE result = rb_str_vcatf(mesg, fmt, ap); + va_end(ap); + return result; +} + +static VALUE string_spec_rb_str_vcatf(VALUE self, VALUE mesg) { + return call_rb_str_vcatf(mesg, "fmt %d %d number", 42, 7); +} + +static VALUE string_spec_rb_str_catf(VALUE self, VALUE mesg) { + return rb_str_catf(mesg, "fmt %d %d number", 41, 6); +} + +static VALUE string_spec_rb_str_locktmp(VALUE self, VALUE str) { + return rb_str_locktmp(str); +} + +static VALUE string_spec_rb_str_unlocktmp(VALUE self, VALUE str) { + return rb_str_unlocktmp(str); +} + void Init_string_spec(void) { VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject); rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2); rb_define_method(cls, "rb_cstr_to_inum", string_spec_rb_cstr_to_inum, 3); + rb_define_method(cls, "rb_fstring", string_spec_rb_str_fstring, 1); rb_define_method(cls, "rb_str2inum", string_spec_rb_str2inum, 2); rb_define_method(cls, "rb_str_append", string_spec_rb_str_append, 2); rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2); rb_define_method(cls, "rb_str_capacity", string_spec_rb_str_capacity, 1); rb_define_method(cls, "rb_str_buf_new2", string_spec_rb_str_buf_new2, 0); + rb_define_method(cls, "rb_str_tmp_new", string_spec_rb_str_tmp_new, 1); + rb_define_method(cls, "rb_str_tmp_new_klass", string_spec_rb_str_tmp_new_klass, 1); rb_define_method(cls, "rb_str_buf_cat", string_spec_rb_str_buf_cat, 1); + rb_define_method(cls, "rb_enc_str_buf_cat", string_spec_rb_enc_str_buf_cat, 3); rb_define_method(cls, "rb_str_cat", string_spec_rb_str_cat, 1); rb_define_method(cls, "rb_str_cat2", string_spec_rb_str_cat2, 1); + rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2); + rb_define_method(cls, "rb_str_cat_cstr_constant", string_spec_rb_str_cat_cstr_constant, 1); rb_define_method(cls, "rb_str_cmp", string_spec_rb_str_cmp, 2); rb_define_method(cls, "rb_str_conv_enc", string_spec_rb_str_conv_enc, 3); rb_define_method(cls, "rb_str_conv_enc_opts", string_spec_rb_str_conv_enc_opts, 5); @@ -468,6 +636,7 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_modify_expand", string_spec_rb_str_modify_expand, 2); rb_define_method(cls, "rb_str_resize", string_spec_rb_str_resize, 2); rb_define_method(cls, "rb_str_resize_RSTRING_LEN", string_spec_rb_str_resize_RSTRING_LEN, 2); + rb_define_method(cls, "rb_str_resize_copy", string_spec_rb_str_resize_copy, 1); rb_define_method(cls, "rb_str_set_len", string_spec_rb_str_set_len, 2); rb_define_method(cls, "rb_str_set_len_RSTRING_LEN", string_spec_rb_str_set_len_RSTRING_LEN, 2); rb_define_method(cls, "rb_str_split", string_spec_rb_str_split, 1); @@ -477,10 +646,13 @@ void Init_string_spec(void) { rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1); rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1); rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1); + rb_define_method(cls, "RSTRING_PTR_iterate_uint32", string_spec_RSTRING_PTR_iterate_uint32, 1); + rb_define_method(cls, "RSTRING_PTR_short_memcpy", string_spec_RSTRING_PTR_short_memcpy, 1); rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2); rb_define_method(cls, "RSTRING_PTR_set", string_spec_RSTRING_PTR_set, 3); rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2); rb_define_method(cls, "RSTRING_PTR_after_yield", string_spec_RSTRING_PTR_after_yield, 1); + rb_define_method(cls, "RSTRING_PTR_read", string_spec_RSTRING_PTR_read, 2); rb_define_method(cls, "StringValue", string_spec_StringValue, 1); rb_define_method(cls, "SafeStringValue", string_spec_SafeStringValue, 1); rb_define_method(cls, "rb_str_hash", string_spec_rb_str_hash, 1); @@ -490,9 +662,15 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_sprintf2", string_spec_rb_sprintf2, 3); rb_define_method(cls, "rb_sprintf3", string_spec_rb_sprintf3, 1); rb_define_method(cls, "rb_sprintf4", string_spec_rb_sprintf4, 1); + rb_define_method(cls, "rb_sprintf5", string_spec_rb_sprintf5, 3); + rb_define_method(cls, "rb_sprintf6", string_spec_rb_sprintf6, 3); + rb_define_method(cls, "rb_sprintf7", string_spec_rb_sprintf7, 2); + rb_define_method(cls, "rb_sprintf8", string_spec_rb_sprintf8, 2); rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4); rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2); rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2); + rb_define_method(cls, "rb_usascii_str_new_lit", string_spec_rb_usascii_str_new_lit, 0); + rb_define_method(cls, "rb_usascii_str_new_lit_non_ascii", string_spec_rb_usascii_str_new_lit_non_ascii, 0); rb_define_method(cls, "rb_usascii_str_new_cstr", string_spec_rb_usascii_str_new_cstr, 1); rb_define_method(cls, "rb_String", string_spec_rb_String, 1); rb_define_method(cls, "rb_string_value_cstr", string_spec_rb_string_value_cstr, 1); @@ -500,6 +678,10 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_utf8_str_new_static", string_spec_rb_utf8_str_new_static, 0); rb_define_method(cls, "rb_utf8_str_new", string_spec_rb_utf8_str_new, 0); rb_define_method(cls, "rb_utf8_str_new_cstr", string_spec_rb_utf8_str_new_cstr, 0); + rb_define_method(cls, "rb_str_vcatf", string_spec_rb_str_vcatf, 1); + rb_define_method(cls, "rb_str_catf", string_spec_rb_str_catf, 1); + rb_define_method(cls, "rb_str_locktmp", string_spec_rb_str_locktmp, 1); + rb_define_method(cls, "rb_str_unlocktmp", string_spec_rb_str_unlocktmp, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/struct_spec.c b/ruby/spec/ruby/optional/capi/ext/struct_spec.c index b9c3b902b..0393d6937 100644 --- a/ruby/spec/ruby/optional/capi/ext/struct_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/struct_spec.c @@ -62,12 +62,10 @@ static VALUE struct_spec_rb_struct_new(VALUE self, VALUE klass, return rb_struct_new(klass, a, b, c); } -#ifdef RUBY_VERSION_IS_2_4 static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st) { return rb_struct_size(st); } -#endif void Init_struct_spec(void) { VALUE cls = rb_define_class("CApiStructSpecs", rb_cObject); @@ -79,9 +77,7 @@ void Init_struct_spec(void) { rb_define_method(cls, "rb_struct_define", struct_spec_struct_define, 4); rb_define_method(cls, "rb_struct_define_under", struct_spec_struct_define_under, 5); rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4); -#ifdef RUBY_VERSION_IS_2_4 rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1); -#endif } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/symbol_spec.c b/ruby/spec/ruby/optional/capi/ext/symbol_spec.c index 28da69ea3..7d9a7b437 100644 --- a/ruby/spec/ruby/optional/capi/ext/symbol_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/symbol_spec.c @@ -7,6 +7,10 @@ extern "C" { #endif +VALUE symbol_spec_SYMBOL_P(VALUE self, VALUE obj) { + return SYMBOL_P(obj) ? Qtrue : Qfalse; +} + VALUE symbol_spec_rb_intern(VALUE self, VALUE string) { return ID2SYM(rb_intern(RSTRING_PTR(string))); } @@ -51,6 +55,10 @@ VALUE symbol_spec_rb_intern_str(VALUE self, VALUE str) { return ID2SYM(rb_intern_str(str)); } +VALUE symbol_spec_rb_check_symbol_cstr(VALUE self, VALUE str) { + return rb_check_symbol_cstr(RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str)); +} + VALUE symbol_spec_rb_is_class_id(VALUE self, VALUE sym) { return rb_is_class_id(SYM2ID(sym)) ? Qtrue : Qfalse; } @@ -67,8 +75,13 @@ VALUE symbol_spec_rb_sym2str(VALUE self, VALUE sym) { return rb_sym2str(sym); } +VALUE symbol_spec_rb_to_symbol(VALUE self, VALUE val) { + return rb_to_symbol(val); +} + void Init_symbol_spec(void) { VALUE cls = rb_define_class("CApiSymbolSpecs", rb_cObject); + rb_define_method(cls, "SYMBOL_P", symbol_spec_SYMBOL_P, 1); rb_define_method(cls, "rb_intern", symbol_spec_rb_intern, 1); rb_define_method(cls, "rb_intern2", symbol_spec_rb_intern2, 2); rb_define_method(cls, "rb_intern_const", symbol_spec_rb_intern_const, 1); @@ -79,10 +92,12 @@ void Init_symbol_spec(void) { rb_define_method(cls, "rb_id2name", symbol_spec_rb_id2name, 1); rb_define_method(cls, "rb_id2str", symbol_spec_rb_id2str, 1); rb_define_method(cls, "rb_intern_str", symbol_spec_rb_intern_str, 1); + rb_define_method(cls, "rb_check_symbol_cstr", symbol_spec_rb_check_symbol_cstr, 1); rb_define_method(cls, "rb_is_class_id", symbol_spec_rb_is_class_id, 1); rb_define_method(cls, "rb_is_const_id", symbol_spec_rb_is_const_id, 1); rb_define_method(cls, "rb_is_instance_id", symbol_spec_rb_is_instance_id, 1); rb_define_method(cls, "rb_sym2str", symbol_spec_rb_sym2str, 1); + rb_define_method(cls, "rb_to_symbol", symbol_spec_rb_to_symbol, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/thread_spec.c b/ruby/spec/ruby/optional/capi/ext/thread_spec.c index 139652e32..21f98dec5 100644 --- a/ruby/spec/ruby/optional/capi/ext/thread_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/thread_spec.c @@ -15,11 +15,13 @@ extern "C" { #endif -static VALUE thread_spec_rb_thread_alone() { +static VALUE thread_spec_rb_thread_alone(VALUE self) { return rb_thread_alone() ? Qtrue : Qfalse; } +#if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif /* This is unblocked by unblock_func(). */ static void* blocking_gvl_func(void* data) { @@ -89,7 +91,7 @@ static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) { return (VALUE)ret; } -static VALUE thread_spec_rb_thread_current() { +static VALUE thread_spec_rb_thread_current(VALUE self) { return rb_thread_current(); } diff --git a/ruby/spec/ruby/optional/capi/ext/tracepoint_spec.c b/ruby/spec/ruby/optional/capi/ext/tracepoint_spec.c new file mode 100644 index 000000000..78c459d6c --- /dev/null +++ b/ruby/spec/ruby/optional/capi/ext/tracepoint_spec.c @@ -0,0 +1,49 @@ +#include "ruby.h" +#include "rubyspec.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE callback_called = Qnil; + +static void callback(VALUE tpval, void *data) { + callback_called = (VALUE) data; +} + +static VALUE tracepoint_spec_rb_tracepoint_new(VALUE self, VALUE data) { + return rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, callback, (void*) data); +} + +static VALUE tracepoint_spec_callback_called(VALUE self){ + return callback_called; +} + +static VALUE tracepoint_spec_rb_tracepoint_disable(VALUE self, VALUE trace) { + rb_tracepoint_disable(trace); + return rb_tracepoint_enabled_p(trace); +} + +static VALUE tracepoint_spec_rb_tracepoint_enable(VALUE self, VALUE trace) { + rb_tracepoint_enable(trace); + return rb_tracepoint_enabled_p(trace); +} + +static VALUE tracepoint_spec_rb_tracepoint_enabled_p(VALUE self, VALUE trace) { + return rb_tracepoint_enabled_p(trace); +} + +void Init_tracepoint_spec(void) { + VALUE cls = rb_define_class("CApiTracePointSpecs", rb_cObject); + rb_define_method(cls, "rb_tracepoint_new", tracepoint_spec_rb_tracepoint_new, 1); + rb_define_method(cls, "rb_tracepoint_disable", tracepoint_spec_rb_tracepoint_disable, 1); + rb_define_method(cls, "rb_tracepoint_enable", tracepoint_spec_rb_tracepoint_enable, 1); + rb_define_method(cls, "rb_tracepoint_enabled_p", tracepoint_spec_rb_tracepoint_enabled_p, 1); + rb_define_method(cls, "callback_called?", tracepoint_spec_callback_called, 0); +} + +#ifdef __cplusplus +} +#endif diff --git a/ruby/spec/ruby/optional/capi/ext/typed_data_spec.c b/ruby/spec/ruby/optional/capi/ext/typed_data_spec.c index a2cc53f54..eca2b667c 100644 --- a/ruby/spec/ruby/optional/capi/ext/typed_data_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/typed_data_spec.c @@ -8,7 +8,7 @@ extern "C" { #endif struct sample_typed_wrapped_struct_parent { - int foo; + int foo; }; void sample_typed_wrapped_struct_parent_free(void* st) { @@ -32,7 +32,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_parent_data_type = { }; struct sample_typed_wrapped_struct { - int foo; + int foo; }; void sample_typed_wrapped_struct_free(void* st) { @@ -61,7 +61,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_data_type = { }; struct sample_typed_wrapped_struct_other { - int foo; + int foo; }; void sample_typed_wrapped_struct_other_free(void* st) { @@ -86,43 +86,45 @@ static const rb_data_type_t sample_typed_wrapped_struct_other_data_type = { VALUE sdaf_alloc_typed_func(VALUE klass) { - struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct)); - bar->foo = 42; - return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar); + struct sample_typed_wrapped_struct* bar; + bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct)); + bar->foo = 42; + return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar); } VALUE sdaf_typed_get_struct(VALUE self) { - struct sample_typed_wrapped_struct* bar; - TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar); + struct sample_typed_wrapped_struct* bar; + TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar); - return INT2FIX((*bar).foo); + return INT2FIX((*bar).foo); } VALUE sws_typed_wrap_struct(VALUE self, VALUE val) { - struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct)); - bar->foo = FIX2INT(val); - return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar); + struct sample_typed_wrapped_struct* bar; + bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct)); + bar->foo = FIX2INT(val); + return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar); } VALUE sws_typed_get_struct(VALUE self, VALUE obj) { - struct sample_typed_wrapped_struct* bar; - TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar); + struct sample_typed_wrapped_struct* bar; + TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar); - return INT2FIX((*bar).foo); + return INT2FIX((*bar).foo); } VALUE sws_typed_get_struct_different_type(VALUE self, VALUE obj) { - struct sample_typed_wrapped_struct_other* bar; - TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar); + struct sample_typed_wrapped_struct_other* bar; + TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar); - return INT2FIX((*bar).foo); + return INT2FIX((*bar).foo); } VALUE sws_typed_get_struct_parent_type(VALUE self, VALUE obj) { - struct sample_typed_wrapped_struct_parent* bar; - TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar); + struct sample_typed_wrapped_struct_parent* bar; + TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar); - return INT2FIX((*bar).foo); + return INT2FIX((*bar).foo); } VALUE sws_typed_get_struct_rdata(VALUE self, VALUE obj) { @@ -138,15 +140,31 @@ VALUE sws_typed_get_struct_data_ptr(VALUE self, VALUE obj) { } VALUE sws_typed_change_struct(VALUE self, VALUE obj, VALUE new_val) { - struct sample_typed_wrapped_struct *old_struct, *new_struct; - new_struct = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct)); + struct sample_typed_wrapped_struct *new_struct; + new_struct = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct)); new_struct->foo = FIX2INT(new_val); - old_struct = RTYPEDDATA(obj)->data; - free(old_struct); + free(RTYPEDDATA(obj)->data); RTYPEDDATA(obj)->data = new_struct; return Qnil; } +VALUE sws_typed_rb_check_type(VALUE self, VALUE obj, VALUE other) { + rb_check_type(obj, TYPE(other)); + return Qtrue; +} + +VALUE sws_typed_rb_check_typeddata_same_type(VALUE self, VALUE obj) { + return rb_check_typeddata(obj, &sample_typed_wrapped_struct_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse; +} + +VALUE sws_typed_rb_check_typeddata_same_type_parent(VALUE self, VALUE obj) { + return rb_check_typeddata(obj, &sample_typed_wrapped_struct_parent_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse; +} + +VALUE sws_typed_rb_check_typeddata_different_type(VALUE self, VALUE obj) { + return rb_check_typeddata(obj, &sample_typed_wrapped_struct_other_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse; +} + void Init_typed_data_spec(void) { VALUE cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject); rb_define_alloc_func(cls, sdaf_alloc_typed_func); @@ -159,6 +177,10 @@ void Init_typed_data_spec(void) { rb_define_method(cls, "typed_get_struct_rdata", sws_typed_get_struct_rdata, 1); rb_define_method(cls, "typed_get_struct_data_ptr", sws_typed_get_struct_data_ptr, 1); rb_define_method(cls, "typed_change_struct", sws_typed_change_struct, 2); + rb_define_method(cls, "rb_check_type", sws_typed_rb_check_type, 2); + rb_define_method(cls, "rb_check_typeddata_same_type", sws_typed_rb_check_typeddata_same_type, 1); + rb_define_method(cls, "rb_check_typeddata_same_type_parent", sws_typed_rb_check_typeddata_same_type_parent, 1); + rb_define_method(cls, "rb_check_typeddata_different_type", sws_typed_rb_check_typeddata_different_type, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/ext/util_spec.c b/ruby/spec/ruby/optional/capi/ext/util_spec.c index f3c6a1ba5..a7269353c 100644 --- a/ruby/spec/ruby/optional/capi/ext/util_spec.c +++ b/ruby/spec/ruby/optional/capi/ext/util_spec.c @@ -1,4 +1,5 @@ #include "ruby.h" +#include "ruby/util.h" #include "rubyspec.h" #ifdef __cplusplus @@ -60,8 +61,8 @@ static VALUE util_spec_rb_get_kwargs(VALUE self, VALUE keyword_hash, VALUE keys, int values_len = req + (opt < 0 ? -1 - opt : opt); int i = 0; - ID *ids = malloc(sizeof(VALUE) * len); - VALUE *results = malloc(sizeof(VALUE) * values_len); + ID *ids = (ID*) malloc(sizeof(VALUE) * len); + VALUE *results = (VALUE*) malloc(sizeof(VALUE) * values_len); int extracted = 0; VALUE ary = Qundef; @@ -93,6 +94,18 @@ static VALUE util_spec_rb_sourceline(VALUE self) { return INT2NUM(rb_sourceline()); } +static VALUE util_spec_strtod(VALUE self, VALUE string) { + char *endptr = NULL; + double value = strtod(RSTRING_PTR(string), &endptr); + return rb_ary_new_from_args(2, rb_float_new(value), endptr ? rb_str_new2(endptr) : Qnil); +} + +static VALUE util_spec_ruby_strtod(VALUE self, VALUE string) { + char *endptr = NULL; + double value = ruby_strtod(RSTRING_PTR(string), &endptr); + return rb_ary_new_from_args(2, rb_float_new(value), endptr ? rb_str_new2(endptr) : Qnil); +} + void Init_util_spec(void) { VALUE cls = rb_define_class("CApiUtilSpecs", rb_cObject); rb_define_method(cls, "rb_scan_args", util_spec_rb_scan_args, 4); @@ -101,6 +114,8 @@ void Init_util_spec(void) { rb_define_method(cls, "rb_iter_break", util_spec_rb_iter_break, 0); rb_define_method(cls, "rb_sourcefile", util_spec_rb_sourcefile, 0); rb_define_method(cls, "rb_sourceline", util_spec_rb_sourceline, 0); + rb_define_method(cls, "strtod", util_spec_strtod, 1); + rb_define_method(cls, "ruby_strtod", util_spec_ruby_strtod, 1); } #ifdef __cplusplus diff --git a/ruby/spec/ruby/optional/capi/fiber_spec.rb b/ruby/spec/ruby/optional/capi/fiber_spec.rb new file mode 100644 index 000000000..357033f86 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/fiber_spec.rb @@ -0,0 +1,89 @@ +require_relative 'spec_helper' +require 'fiber' + +load_extension('fiber') + +describe "C-API Fiber function" do + before :each do + @s = CApiFiberSpecs.new + end + + describe "rb_fiber_current" do + it "returns the current fiber" do + result = @s.rb_fiber_current() + result.should be_an_instance_of(Fiber) + result.should == Fiber.current + end + end + + describe "rb_fiber_alive_p" do + it "returns the fibers alive status" do + fiber = Fiber.new { Fiber.yield } + fiber.resume + @s.rb_fiber_alive_p(fiber).should be_true + fiber.resume + @s.rb_fiber_alive_p(fiber).should be_false + end + end + + describe "rb_fiber_resume" do + it "resumes the fiber" do + fiber = Fiber.new { |arg| Fiber.yield arg } + @s.rb_fiber_resume(fiber, [1]).should == 1 + @s.rb_fiber_resume(fiber, [2]).should == 2 + end + end + + describe "rb_fiber_yield" do + it "yields the fiber" do + fiber = Fiber.new { @s.rb_fiber_yield([1]) } + fiber.resume.should == 1 + end + end + + describe "rb_fiber_new" do + it "returns a new fiber" do + fiber = @s.rb_fiber_new + fiber.should be_an_instance_of(Fiber) + fiber.resume(42).should == "42" + end + end + + ruby_version_is '3.1' do + describe "rb_fiber_raise" do + it "raises an exception on the resumed fiber" do + fiber = Fiber.new do + begin + Fiber.yield + rescue => error + error + end + end + + fiber.resume + + result = @s.rb_fiber_raise(fiber, "Boom!") + result.should be_an_instance_of(RuntimeError) + result.message.should == "Boom!" + end + + it "raises an exception on the transferred fiber" do + main = Fiber.current + + fiber = Fiber.new do + begin + main.transfer + rescue => error + error + end + end + + fiber.transfer + + result = @s.rb_fiber_raise(fiber, "Boom!") + result.should be_an_instance_of(RuntimeError) + result.message.should == "Boom!" + end + end + end +end diff --git a/ruby/spec/ruby/optional/capi/fixtures/class.rb b/ruby/spec/ruby/optional/capi/fixtures/class.rb index dbb0b6996..193c7174e 100644 --- a/ruby/spec/ruby/optional/capi/fixtures/class.rb +++ b/ruby/spec/ruby/optional/capi/fixtures/class.rb @@ -87,5 +87,8 @@ class A class B end + + module M + end end end diff --git a/ruby/spec/ruby/optional/capi/fixtures/module.rb b/ruby/spec/ruby/optional/capi/fixtures/module.rb index ba90eb718..aac8bfbfb 100644 --- a/ruby/spec/ruby/optional/capi/fixtures/module.rb +++ b/ruby/spec/ruby/optional/capi/fixtures/module.rb @@ -13,6 +13,10 @@ class A autoload :D, File.expand_path('../const_get.rb', __FILE__) X = 1 + Q = 1 + R = 2 + S = 3 + T = 5 end class B < A diff --git a/ruby/spec/ruby/optional/capi/fixtures/read.txt b/ruby/spec/ruby/optional/capi/fixtures/read.txt new file mode 100644 index 000000000..f7065a35d --- /dev/null +++ b/ruby/spec/ruby/optional/capi/fixtures/read.txt @@ -0,0 +1 @@ +fixture file contents to test read() with RSTRING_PTR diff --git a/ruby/spec/ruby/optional/capi/float_spec.rb b/ruby/spec/ruby/optional/capi/float_spec.rb index 838194531..4b98902b5 100644 --- a/ruby/spec/ruby/optional/capi/float_spec.rb +++ b/ruby/spec/ruby/optional/capi/float_spec.rb @@ -27,4 +27,17 @@ f.should eql(101.99) end end + + describe "RB_FLOAT_TYPE_P" do + it "returns true for floats" do + @f.RB_FLOAT_TYPE_P(2.0).should == true + end + + it "returns false for non-floats" do + @f.RB_FLOAT_TYPE_P(nil).should == false + @f.RB_FLOAT_TYPE_P(10).should == false + @f.RB_FLOAT_TYPE_P("string").should == false + @f.RB_FLOAT_TYPE_P(Object.new).should == false + end + end end diff --git a/ruby/spec/ruby/optional/capi/gc_spec.rb b/ruby/spec/ruby/optional/capi/gc_spec.rb index 46c03156e..23e2b7c9a 100644 --- a/ruby/spec/ruby/optional/capi/gc_spec.rb +++ b/ruby/spec/ruby/optional/capi/gc_spec.rb @@ -58,4 +58,30 @@ }.should_not raise_error end end + + describe "rb_gc_register_mark_object" do + it "can be called with an object" do + @f.rb_gc_register_mark_object(Object.new).should be_nil + end + end + + describe "rb_gc_latest_gc_info" do + it "raises a TypeError when hash or symbol not given" do + -> { @f.rb_gc_latest_gc_info("foo") }.should raise_error(TypeError) + end + + it "raises an ArgumentError when unknown symbol given" do + -> { @f.rb_gc_latest_gc_info(:unknown) }.should raise_error(ArgumentError) + end + + it "returns the populated hash when a hash is given" do + h = {} + @f.rb_gc_latest_gc_info(h).should == h + h.size.should_not == 0 + end + + it "returns a value when symbol is given" do + @f.rb_gc_latest_gc_info(:state).should be_kind_of(Symbol) + end + end end diff --git a/ruby/spec/ruby/optional/capi/globals_spec.rb b/ruby/spec/ruby/optional/capi/globals_spec.rb index 84694b137..cc6f6ef3a 100644 --- a/ruby/spec/ruby/optional/capi/globals_spec.rb +++ b/ruby/spec/ruby/optional/capi/globals_spec.rb @@ -53,13 +53,32 @@ $hooked_gvar.should == 4 end + describe "rb_fs" do + before :each do + @field_separator = $; + end + + after :each do + suppress_warning { $; = @field_separator } + end + + it "returns nil by default" do + @f.rb_fs.should == nil + end + + it "returns the value of $;" do + suppress_warning { $; = "foo" } + @f.rb_fs.should == "foo" + end + end + describe "rb_rs" do before :each do @dollar_slash = $/ end after :each do - $/ = @dollar_slash + suppress_warning { $/ = @dollar_slash } end it "returns \\n by default" do @@ -67,7 +86,7 @@ end it "returns the value of $/" do - $/ = "foo" + suppress_warning { $/ = "foo" } @f.rb_rs.should == "foo" end end @@ -121,7 +140,7 @@ $stdout = STDOUT end - it "returns $stdout" do + it "is an alias of rb_stdout" do $stdout = @stream @f.rb_defout.should equal($stdout) end @@ -140,7 +159,7 @@ end after :each do - $\ = @dollar_backslash + suppress_warning {$\ = @dollar_backslash} end it "returns nil by default" do @@ -148,7 +167,7 @@ end it "returns the value of $\\" do - $\ = "foo" + suppress_warning {$\ = "foo"} @f.rb_output_rs.should == "foo" end end diff --git a/ruby/spec/ruby/optional/capi/hash_spec.rb b/ruby/spec/ruby/optional/capi/hash_spec.rb index 2923faf7d..a60467a66 100644 --- a/ruby/spec/ruby/optional/capi/hash_spec.rb +++ b/ruby/spec/ruby/optional/capi/hash_spec.rb @@ -21,7 +21,7 @@ # The actual conversion is an implementation detail. # We only care that ultimately we get a Fixnum instance. - @s.rb_hash(obj).should be_an_instance_of(Fixnum) + @s.rb_hash(obj).should.between?(fixnum_min, fixnum_max) end it "calls #to_int to converts a value returned by #hash to a Fixnum" do @@ -50,6 +50,14 @@ end end + describe "rb_ident_hash_new" do + it "returns a new compare by identity hash" do + result = @s.rb_ident_hash_new + result.should == {} + result.compare_by_identity?.should == true + end + end + describe "rb_hash_dup" do it "returns a copy of the hash" do hsh = {} @@ -254,4 +262,13 @@ def h.to_hash; 42; end -> { @s.rb_Hash(h) }.should raise_error(TypeError) end end + + describe "hash code functions" do + it "computes a deterministic number" do + hash_code = @s.compute_a_hash_code(53) + hash_code.should be_an_instance_of(Integer) + hash_code.should == @s.compute_a_hash_code(53) + @s.compute_a_hash_code(90).should == @s.compute_a_hash_code(90) + end + end end diff --git a/ruby/spec/ruby/optional/capi/integer_spec.rb b/ruby/spec/ruby/optional/capi/integer_spec.rb index 56f7ca303..e26735824 100644 --- a/ruby/spec/ruby/optional/capi/integer_spec.rb +++ b/ruby/spec/ruby/optional/capi/integer_spec.rb @@ -272,4 +272,19 @@ end end end + + describe "rb_int_positive_pow" do + it "raises an integer to given power" do + @s.rb_int_positive_pow(2, 3).should == 8 + end + + it "raises a negative integer to given power" do + @s.rb_int_positive_pow(-2, 3).should == -8 + @s.rb_int_positive_pow(-2, 4).should == 16 + end + + it "overflows for large inputs" do + @s.rb_int_positive_pow(8, 23).should == 590295810358705651712 + end + end end diff --git a/ruby/spec/ruby/optional/capi/io_spec.rb b/ruby/spec/ruby/optional/capi/io_spec.rb index 4d61fc875..489a01c51 100644 --- a/ruby/spec/ruby/optional/capi/io_spec.rb +++ b/ruby/spec/ruby/optional/capi/io_spec.rb @@ -151,6 +151,16 @@ end end + describe "rb_io_set_nonblock" do + platform_is_not :windows do + it "returns true when nonblock flag is set" do + require 'io/nonblock' + @o.rb_io_set_nonblock(@io) + @io.nonblock?.should be_true + end + end + end + # NOTE: unlike the name might suggest in MRI this function checks if an # object is frozen, *not* if it's tainted. describe "rb_io_taint_check" do @@ -365,3 +375,29 @@ @io.close_on_exec?.should be_true end end + +describe "rb_io_t modes flags" do + before :each do + @o = CApiIOSpecs.new + @name = tmp("c_api_rb_io_specs") + touch @name + end + + after :each do + rm_r @name + end + + it "has the sync flag set if the IO object is synced in Ruby" do + File.open(@name) { |io| + io.sync = true + @o.rb_io_mode_sync_flag(io).should == true + } + end + + it "has the sync flag unset if the IO object is not synced in Ruby" do + File.open(@name) { |io| + io.sync = false + @o.rb_io_mode_sync_flag(io).should == false + } + end +end diff --git a/ruby/spec/ruby/optional/capi/kernel_spec.rb b/ruby/spec/ruby/optional/capi/kernel_spec.rb index 32cdd3f42..758d944da 100644 --- a/ruby/spec/ruby/optional/capi/kernel_spec.rb +++ b/ruby/spec/ruby/optional/capi/kernel_spec.rb @@ -1,6 +1,6 @@ require_relative 'spec_helper' -load_extension("kernel") +kernel_path = load_extension("kernel") describe "C-API Kernel function" do before :each do @@ -9,7 +9,7 @@ describe "rb_block_given_p" do it "returns false if no block is passed" do - @s.rb_block_given_p.should == false + @s.should_not.rb_block_given_p end it "returns true if a block is passed" do @@ -238,6 +238,18 @@ end end + describe "rb_yield_values2" do + it "yields passed arguments" do + ret = nil + @s.rb_yield_values2([1, 2]) { |x, y| ret = x + y } + ret.should == 3 + end + + it "returns the result from block evaluation" do + @s.rb_yield_values2([1, 2]) { |x, y| x + y }.should == 3 + end + end + describe "rb_yield_splat" do it "yields with passed array's contents" do ret = nil @@ -261,28 +273,28 @@ describe "rb_protect" do it "will run a function with an argument" do proof = [] # Hold proof of work performed after the yield. - res = @s.rb_protect_yield(7, proof) { |x| x + 1 } - res.should == 8 + res = @s.rb_protect_yield(77, proof) { |x| x + 1 } + res.should == 78 proof[0].should == 23 end it "will allow cleanup code to run after break" do proof = [] # Hold proof of work performed after the yield. - @s.rb_protect_yield(7, proof) { |x| break } + @s.rb_protect_yield(77, proof) { |x| break } proof[0].should == 23 end it "will allow cleanup code to run after break with value" do proof = [] # Hold proof of work performed after the yield. - res = @s.rb_protect_yield(7, proof) { |x| break x + 1 } - res.should == 8 + res = @s.rb_protect_yield(77, proof) { |x| break x + 1 } + res.should == 78 proof[0].should == 23 end it "will allow cleanup code to run after a raise" do proof = [] # Hold proof of work performed after the yield. -> do - @s.rb_protect_yield(7, proof) { |x| raise NameError} + @s.rb_protect_yield(77, proof) { |x| raise NameError} end.should raise_error(NameError) proof[0].should == 23 end @@ -290,11 +302,24 @@ it "will return nil if an error was raised" do proof = [] # Hold proof of work performed after the yield. -> do - @s.rb_protect_yield(7, proof) { |x| raise NameError} + @s.rb_protect_yield(77, proof) { |x| raise NameError} end.should raise_error(NameError) proof[0].should == 23 proof[1].should == nil end + + it "accepts NULL as status and returns nil if it failed" do + @s.rb_protect_null_status(42) { |x| x + 1 }.should == 43 + @s.rb_protect_null_status(42) { |x| raise }.should == nil + end + + it "populates errinfo with the captured exception" do + proof = [] + @s.rb_protect_errinfo(77, proof) { |x| raise NameError }.class.should == NameError + proof[0].should == 23 + proof[1].should == nil + end + end describe "rb_eval_string_protect" do @@ -316,47 +341,47 @@ describe "rb_rescue" do before :each do @proc = -> x { x } - @raise_proc_returns_sentinel = -> *_ { :raise_proc_executed } - @raise_proc_returns_arg = -> *a { a } + @rescue_proc_returns_sentinel = -> *_ { :rescue_proc_executed } + @rescue_proc_returns_arg = -> *a { a } @arg_error_proc = -> *_ { raise ArgumentError, '' } @std_error_proc = -> *_ { raise StandardError, '' } @exc_error_proc = -> *_ { raise Exception, '' } end it "executes passed function" do - @s.rb_rescue(@proc, :no_exc, @raise_proc_returns_arg, :exc).should == :no_exc + @s.rb_rescue(@proc, :no_exc, @rescue_proc_returns_arg, :exc).should == :no_exc end - it "executes passed 'raise function' if a StandardError exception is raised" do - @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed - @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed + it "executes the passed 'rescue function' if a StandardError exception is raised" do + @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed + @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed end - it "passes the user supplied argument to the 'raise function' if a StandardError exception is raised" do - arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc1) + it "passes the user supplied argument to the 'rescue function' if a StandardError exception is raised" do + arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc1) arg1.should == :exc1 - arg2, _ = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc2) + arg2, _ = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc2) arg2.should == :exc2 end - it "passes the raised exception to the 'raise function' if a StandardError exception is raised" do - _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc) + it "passes the raised exception to the 'rescue function' if a StandardError exception is raised" do + _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc) exc1.class.should == ArgumentError - _, exc2 = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc) + _, exc2 = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc) exc2.class.should == StandardError end it "raises an exception if passed function raises an exception other than StandardError" do - -> { @s.rb_rescue(@exc_error_proc, nil, @raise_proc_returns_arg, nil) }.should raise_error(Exception) + -> { @s.rb_rescue(@exc_error_proc, nil, @rescue_proc_returns_arg, nil) }.should raise_error(Exception) end - it "raises an exception if any exception is raised inside 'raise function'" do + it "raises an exception if any exception is raised inside the 'rescue function'" do -> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError) end - it "makes $! available only during 'raise function' execution" do + it "makes $! available only during the 'rescue function' execution" do @s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError $!.should == nil end @@ -368,6 +393,10 @@ def proc_caller proc_caller { break :value }.should == :value end + + it "returns nil if the 'rescue function' is null" do + @s.rb_rescue(@std_error_proc, nil, nil, nil).should == nil + end end describe "rb_rescue2" do @@ -375,12 +404,20 @@ def proc_caller proc = -> x { x } arg_error_proc = -> *_ { raise ArgumentError, '' } run_error_proc = -> *_ { raise RuntimeError, '' } - type_error_proc = -> *_ { raise TypeError, '' } + type_error_proc = -> *_ { raise Exception, 'custom error' } @s.rb_rescue2(arg_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc @s.rb_rescue2(run_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc -> { @s.rb_rescue2(type_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError) - }.should raise_error(TypeError) + }.should raise_error(Exception, 'custom error') + end + + ruby_bug "#17305", ""..."2.7" do + it "raises TypeError if one of the passed exceptions is not a Module" do + -> { + @s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42) + }.should raise_error(TypeError, /class or module required/) + end end end @@ -474,7 +511,7 @@ def proc_caller proc = @s.rb_block_proc { 1+1 } proc.should be_kind_of(Proc) proc.call.should == 2 - proc.lambda?.should == false + proc.should_not.lambda? end it "passes through an existing lambda and does not convert to a proc" do @@ -482,7 +519,7 @@ def proc_caller proc = @s.rb_block_proc(&b) proc.should equal(b) proc.call.should == 2 - proc.lambda?.should == true + proc.should.lambda? end end @@ -491,7 +528,7 @@ def proc_caller proc = @s.rb_block_lambda { 1+1 } proc.should be_kind_of(Proc) proc.call.should == 2 - proc.lambda?.should == true + proc.should.lambda? end it "passes through an existing Proc and does not convert to a lambda" do @@ -499,7 +536,7 @@ def proc_caller proc = @s.rb_block_lambda(&b) proc.should equal(b) proc.call.should == 2 - proc.lambda?.should == false + proc.should_not.lambda? end end @@ -510,25 +547,9 @@ def proc_caller end end - platform_is_not :windows do - describe "rb_set_end_proc" do - before :each do - @r, @w = IO.pipe - end - - after :each do - @r.close - @w.close - Process.wait @pid - end - - it "runs a C function on shutdown" do - @pid = fork { - @s.rb_set_end_proc(@w) - } - - @r.read(1).should == "e" - end + describe "rb_set_end_proc" do + it "runs a C function on shutdown" do + ruby_exe("require #{kernel_path.inspect}; CApiKernelSpecs.new.rb_set_end_proc(STDOUT)").should == "in write_io" end end @@ -546,20 +567,6 @@ def proc_caller end end - describe "rb_obj_method" do - it "returns the method object for a symbol" do - method = @s.rb_obj_method("test", :size) - method.owner.should == String - method.name.to_sym.should == :size - end - - it "returns the method object for a string" do - method = @s.rb_obj_method("test", "size") - method.owner.should == String - method.name.to_sym.should == :size - end - end - describe "rb_funcall3" do before :each do @obj = Object.new @@ -578,6 +585,20 @@ def method_private; :method_private end end end + describe 'rb_funcall' do + before :each do + @obj = Object.new + class << @obj + def many_args(*args) + args + end + end + end + + it "can call a public method with 15 arguments" do + @s.rb_funcall_many_args(@obj, :many_args).should == 15.downto(1).to_a + end + end describe 'rb_funcall_with_block' do before :each do @obj = Object.new diff --git a/ruby/spec/ruby/optional/capi/language_spec.rb b/ruby/spec/ruby/optional/capi/language_spec.rb new file mode 100644 index 000000000..f59b87f2a --- /dev/null +++ b/ruby/spec/ruby/optional/capi/language_spec.rb @@ -0,0 +1,37 @@ +require_relative 'spec_helper' + +load_extension("language") + +describe "C language construct" do + before :each do + @s = CApiLanguageSpecs.new + end + + describe "switch (VALUE)" do + it "works for Qtrue" do + @s.switch(true).should == :true + end + + it "works for Qfalse" do + @s.switch(false).should == :false + end + + it "works for Qnil" do + @s.switch(nil).should == :nil + end + + it "works for Qundef" do + @s.switch(:undef).should == :undef + end + + it "works for the default case" do + @s.switch(Object.new).should == :default + end + end + + describe "local variable assignment with the same name as a global" do + it "works for rb_mProcess" do + @s.global_local_var.should.equal?(Process) + end + end +end diff --git a/ruby/spec/ruby/optional/capi/module_spec.rb b/ruby/spec/ruby/optional/capi/module_spec.rb index bf09e9d8a..acf4d1fe4 100644 --- a/ruby/spec/ruby/optional/capi/module_spec.rb +++ b/ruby/spec/ruby/optional/capi/module_spec.rb @@ -134,8 +134,12 @@ @m.rb_const_get(CApiModuleSpecs::A, :X).should == 1 end + it "returns a constant defined in the module for multiple constants" do + [:Q, :R, :S, :T].each { |x| @m.rb_const_get(CApiModuleSpecs::A, x).should == CApiModuleSpecs::A.const_get(x) } + end + it "returns a constant defined at toplevel" do - @m.rb_const_get(CApiModuleSpecs::A, :Fixnum).should == Fixnum + @m.rb_const_get(CApiModuleSpecs::A, :Integer).should == Integer end it "returns a constant defined in a superclass" do @@ -176,8 +180,8 @@ end it "calls #const_missing if the constant is not defined in the class or ancestors" do - CApiModuleSpecs::M.should_receive(:const_missing).with(:Fixnum) - @m.rb_const_get_from(CApiModuleSpecs::M, :Fixnum) + CApiModuleSpecs::M.should_receive(:const_missing).with(:Integer) + @m.rb_const_get_from(CApiModuleSpecs::M, :Integer) end it "resolves autoload constants" do @@ -242,11 +246,41 @@ def method_to_be_aliased cls.new.test_method.should == :test_method end + it "returns the correct arity when argc of the method in class is 0" do + cls = Class.new + @m.rb_define_method(cls, "test_method") + cls.new.method(:test_method).arity.should == 0 + end + + it "returns the correct arity when argc of the method in class is -1" do + cls = Class.new + @m.rb_define_method_c_array(cls, "test_method_c_array") + cls.new.method(:test_method_c_array).arity.should == -1 + end + + it "returns the correct arity when argc of the method in class is -2" do + cls = Class.new + @m.rb_define_method_ruby_array(cls, "test_method_ruby_array") + cls.new.method(:test_method_ruby_array).arity.should == -1 + end + + it "returns the correct arity when argc of the method in class is 2" do + cls = Class.new + @m.rb_define_method_2required(cls, "test_method_2required") + cls.new.method(:test_method_2required).arity.should == 2 + end + it "defines a method on a module" do mod = Module.new @m.rb_define_method(mod, "test_method") mod.should have_instance_method(:test_method) end + + it "returns the correct arity of the method in module" do + mod = Module.new + @m.rb_define_method(mod, "test_method") + mod.instance_method(:test_method).arity.should == 0 + end end describe "rb_define_module_function" do @@ -259,12 +293,23 @@ def method_to_be_aliased @mod.test_module_function.should == :test_method end + it "returns the correct arity of the module function" do + @mod.method(:test_module_function).arity.should == 0 + end + it "defines a private instance method" do cls = Class.new cls.include(@mod) cls.should have_private_instance_method(:test_module_function) end + + it "returns the correct arity for private instance method" do + cls = Class.new + cls.include(@mod) + + @mod.instance_method(:test_module_function).arity.should == 0 + end end describe "rb_define_private_method" do @@ -336,12 +381,12 @@ def ruby_test_method @frozen = @class.dup.freeze end - it "raises a #{frozen_error_class} when passed a name" do - -> { @m.rb_undef_method @frozen, "ruby_test_method" }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a name" do + -> { @m.rb_undef_method @frozen, "ruby_test_method" }.should raise_error(FrozenError) end - it "raises a #{frozen_error_class} when passed a missing name" do - -> { @m.rb_undef_method @frozen, "not_exist" }.should raise_error(frozen_error_class) + it "raises a FrozenError when passed a missing name" do + -> { @m.rb_undef_method @frozen, "not_exist" }.should raise_error(FrozenError) end end end diff --git a/ruby/spec/ruby/optional/capi/numeric_spec.rb b/ruby/spec/ruby/optional/capi/numeric_spec.rb index d76f35385..95213d3f2 100644 --- a/ruby/spec/ruby/optional/capi/numeric_spec.rb +++ b/ruby/spec/ruby/optional/capi/numeric_spec.rb @@ -143,6 +143,34 @@ end end + describe "NUM2SHORT" do + it "raises a TypeError if passed nil" do + -> { @s.NUM2SHORT(nil) }.should raise_error(TypeError) + end + + it "converts a Float" do + @s.NUM2SHORT(4.2).should == 4 + end + + it "converts a Fixnum" do + @s.NUM2SHORT(5).should == 5 + end + + it "converts -1 to an signed number" do + @s.NUM2SHORT(-1).should == -1 + end + + it "raises a RangeError if the value is more than 32bits" do + -> { @s.NUM2SHORT(0xffff_ffff+1) }.should raise_error(RangeError) + end + + it "calls #to_int to coerce the value" do + obj = mock("number") + obj.should_receive(:to_int).and_return(2) + @s.NUM2SHORT(obj).should == 2 + end + end + describe "INT2NUM" do it "raises a TypeError if passed nil" do -> { @s.INT2NUM(nil) }.should raise_error(TypeError) @@ -236,52 +264,45 @@ describe "rb_Integer" do it "creates an Integer from a String" do i = @s.rb_Integer("8675309") - i.should be_kind_of(Integer) - i.should eql(8675309) + i.should == 8675309 end end describe "rb_ll2inum" do it "creates a Fixnum from a small signed long long" do i = @s.rb_ll2inum_14() - i.should be_kind_of(Fixnum) - i.should eql(14) + i.should == 14 end end describe "rb_ull2inum" do it "creates a Fixnum from a small unsigned long long" do i = @s.rb_ull2inum_14() - i.should be_kind_of(Fixnum) - i.should eql(14) + i.should == 14 end it "creates a positive Bignum from a negative long long" do i = @s.rb_ull2inum_n14() - i.should be_kind_of(Bignum) - i.should eql(2 ** (@s.size_of_long_long * 8) - 14) + i.should == (2 ** (@s.size_of_long_long * 8) - 14) end end describe "rb_int2inum" do it "creates a Fixnum from a long" do i = @s.rb_int2inum_14() - i.should be_kind_of(Fixnum) - i.should eql(14) + i.should == 14 end end describe "rb_uint2inum" do it "creates a Fixnum from a long" do i = @s.rb_uint2inum_14() - i.should be_kind_of(Fixnum) - i.should eql(14) + i.should == 14 end it "creates a positive Bignum from a negative long" do i = @s.rb_uint2inum_n14() - i.should be_kind_of(Bignum) - i.should eql(2 ** (@s.size_of_VALUE * 8) - 14) + i.should == (2 ** (@s.size_of_VALUE * 8) - 14) end end @@ -409,23 +430,12 @@ @s.rb_num_coerce_cmp(2, obj, :<=>).should == -1 end - ruby_version_is ""..."2.5" do - it "returns nil if passed nil" do - -> { - @result = @s.rb_num_coerce_cmp(nil, 2, :<=>) - }.should complain(/comparison operators will no more rescue exceptions/) - @result.should be_nil - end - end - - ruby_version_is "2.5" do - it "lets the exception go through if #coerce raises an exception" do - obj = mock("rb_num_coerce_cmp") - obj.should_receive(:coerce).with(2).and_raise(RuntimeError.new("my error")) - -> { - @s.rb_num_coerce_cmp(2, obj, :<=>) - }.should raise_error(RuntimeError, "my error") - end + it "lets the exception go through if #coerce raises an exception" do + obj = mock("rb_num_coerce_cmp") + obj.should_receive(:coerce).with(2).and_raise(RuntimeError.new("my error")) + -> { + @s.rb_num_coerce_cmp(2, obj, :<=>) + }.should raise_error(RuntimeError, "my error") end it "returns nil if #coerce does not return an Array" do diff --git a/ruby/spec/ruby/optional/capi/object_spec.rb b/ruby/spec/ruby/optional/capi/object_spec.rb index 30abe715e..ab1136706 100644 --- a/ruby/spec/ruby/optional/capi/object_spec.rb +++ b/ruby/spec/ruby/optional/capi/object_spec.rb @@ -110,6 +110,16 @@ def six(a, b, *c, &d); end @o.rb_respond_to(ObjectTest.new, :foo).should == true @o.rb_respond_to(ObjectTest.new, :bar).should == false end + + it "can be used with primitives" do + @o.rb_respond_to(true, :object_id).should == true + @o.rb_respond_to(14, :succ).should == true + end + + it "returns 0 if the method has been defined as rb_f_notimplement" do + @o.respond_to?(:not_implemented_method).should == false + @o.rb_respond_to(@o, :not_implemented_method).should == false + end end describe "rb_obj_respond_to" do @@ -151,6 +161,20 @@ def six(a, b, *c, &d); end end end + describe "rb_obj_method" do + it "returns the method object for a symbol" do + method = @o.rb_obj_method("test", :size) + method.owner.should == String + method.name.to_sym.should == :size + end + + it "returns the method object for a string" do + method = @o.rb_obj_method("test", "size") + method.owner.should == String + method.name.to_sym.should == :size + end + end + describe "rb_method_boundp" do it "returns true when the given method is bound" do @o.rb_method_boundp(Object, :class, true).should == true @@ -313,8 +337,8 @@ def six(a, b, *c, &d); end it "does not rescue exceptions raised by #to_ary" do obj = mock("to_ary") - obj.should_receive(:to_ary).and_raise(frozen_error_class) - -> { @o.rb_check_array_type obj }.should raise_error(frozen_error_class) + obj.should_receive(:to_ary).and_raise(FrozenError) + -> { @o.rb_check_array_type obj }.should raise_error(FrozenError) end end @@ -443,7 +467,7 @@ def six(a, b, *c, &d); end describe "rb_class_of" do it "returns the class of an object" do @o.rb_class_of(nil).should == NilClass - @o.rb_class_of(0).should == Fixnum + @o.rb_class_of(0).should == Integer @o.rb_class_of(0.1).should == Float @o.rb_class_of(ObjectTest.new).should == ObjectTest end @@ -459,7 +483,7 @@ def six(a, b, *c, &d); end describe "rb_obj_classname" do it "returns the class name of an object" do @o.rb_obj_classname(nil).should == 'NilClass' - @o.rb_obj_classname(0).should == Fixnum.to_s + @o.rb_obj_classname(0).should == 'Integer' @o.rb_obj_classname(0.1).should == 'Float' @o.rb_obj_classname(ObjectTest.new).should == 'ObjectTest' end @@ -475,20 +499,43 @@ class DescArray < Array @o.rb_is_type_array([]).should == true @o.rb_is_type_array(DescArray.new).should == true @o.rb_is_type_module(ObjectTest).should == false + @o.rb_is_type_module(Module.new).should == true @o.rb_is_type_class(ObjectTest).should == true @o.rb_is_type_data(Time.now).should == true end end + describe "rb_check_type" do + it "checks if the object is of the given type" do + @o.rb_check_type(nil, nil).should == true + @o.rb_check_type(ObjectTest.new, Object.new).should == true + @o.rb_check_type([], []).should == true + @o.rb_check_type(Class.new(Array).new, []).should == true + @o.rb_check_type(ObjectTest, Object).should == true + end + + it "raises an exception if the object is not of the expected type" do + -> { + @o.rb_check_type([], Object.new) + }.should raise_error(TypeError, 'wrong argument type Array (expected Object)') + + -> { + @o.rb_check_type(ObjectTest, Module.new) + }.should raise_error(TypeError, 'wrong argument type Class (expected Module)') + + -> { + @o.rb_check_type(nil, "string") + }.should raise_error(TypeError, 'wrong argument type nil (expected String)') + end + end + describe "rb_type_p" do it "returns whether object is of the given type" do - class DescArray < Array - end @o.rb_is_rb_type_p_nil(nil).should == true @o.rb_is_rb_type_p_object([]).should == false @o.rb_is_rb_type_p_object(ObjectTest.new).should == true @o.rb_is_rb_type_p_array([]).should == true - @o.rb_is_rb_type_p_array(DescArray.new).should == true + @o.rb_is_rb_type_p_array(Class.new(Array).new).should == true @o.rb_is_rb_type_p_module(ObjectTest).should == false @o.rb_is_rb_type_p_class(ObjectTest).should == true @o.rb_is_rb_type_p_data(Time.now).should == true @@ -497,12 +544,10 @@ class DescArray < Array describe "BUILTIN_TYPE" do it "returns the type constant for the object" do - class DescArray < Array - end @o.rb_is_builtin_type_object([]).should == false @o.rb_is_builtin_type_object(ObjectTest.new).should == true @o.rb_is_builtin_type_array([]).should == true - @o.rb_is_builtin_type_array(DescArray.new).should == true + @o.rb_is_builtin_type_array(Class.new(Array).new).should == true @o.rb_is_builtin_type_module(ObjectTest).should == false @o.rb_is_builtin_type_class(ObjectTest).should == true @o.rb_is_builtin_type_data(Time.now).should == true @@ -670,20 +715,20 @@ def reach ruby_version_is ''...'2.7' do it "marks the object passed as tainted" do obj = "" - obj.tainted?.should == false + obj.should_not.tainted? @o.rb_obj_taint(obj) - obj.tainted?.should == true + obj.should.tainted? end - it "raises a #{frozen_error_class} if the object passed is frozen" do - -> { @o.rb_obj_taint("".freeze) }.should raise_error(frozen_error_class) + it "raises a FrozenError if the object passed is frozen" do + -> { @o.rb_obj_taint("".freeze) }.should raise_error(FrozenError) end end end describe "rb_check_frozen" do - it "raises a #{frozen_error_class} if the obj is frozen" do - -> { @o.rb_check_frozen("".freeze) }.should raise_error(frozen_error_class) + it "raises a FrozenError if the obj is frozen" do + -> { @o.rb_check_frozen("".freeze) }.should raise_error(FrozenError) end it "does nothing when object isn't frozen" do @@ -815,6 +860,15 @@ def reach end end + describe "rb_ivar_count" do + it "returns the number of instance variables" do + obj = Object.new + @o.rb_ivar_count(obj).should == 0 + obj.instance_variable_set(:@foo, 42) + @o.rb_ivar_count(obj).should == 1 + end + end + describe "rb_ivar_get" do it "returns the instance variable on an object" do @o.rb_ivar_get(@test, :@foo).should == @test.instance_eval { @foo } @@ -826,6 +880,7 @@ def reach it "returns nil if the instance variable has not been initialized and is not a valid Ruby name" do @o.rb_ivar_get(@test, :bar).should == nil + @o.rb_ivar_get(@test, :mesg).should == nil end it 'returns the instance variable when it is not a valid Ruby name' do @@ -861,6 +916,7 @@ def reach it "does not throw an error if the instance variable is not a valid Ruby name" do @o.rb_ivar_defined(@test, :bar).should == false + @o.rb_ivar_defined(@test, :mesg).should == false end end @@ -887,4 +943,78 @@ def reach end end end + + describe "allocator accessors" do + describe "rb_define_alloc_func" do + it "sets up the allocator" do + klass = Class.new + @o.rb_define_alloc_func(klass) + obj = klass.allocate + obj.class.should.equal?(klass) + obj.should have_instance_variable(:@from_custom_allocator) + end + + it "sets up the allocator for a subclass of String" do + klass = Class.new(String) + @o.rb_define_alloc_func(klass) + obj = klass.allocate + obj.class.should.equal?(klass) + obj.should have_instance_variable(:@from_custom_allocator) + obj.should == "" + end + + it "sets up the allocator for a subclass of Array" do + klass = Class.new(Array) + @o.rb_define_alloc_func(klass) + obj = klass.allocate + obj.class.should.equal?(klass) + obj.should have_instance_variable(:@from_custom_allocator) + obj.should == [] + end + end + + describe "rb_get_alloc_func" do + it "gets the allocator that is defined directly on a class" do + klass = Class.new + @o.rb_define_alloc_func(klass) + @o.speced_allocator?(Object).should == false + @o.speced_allocator?(klass).should == true + end + + it "gets the allocator that is inherited" do + parent = Class.new + @o.rb_define_alloc_func(parent) + klass = Class.new(parent) + @o.speced_allocator?(Object).should == false + @o.speced_allocator?(klass).should == true + end + end + + describe "rb_undef_alloc_func" do + it "makes rb_get_alloc_func() return NULL for a class without a custom allocator" do + klass = Class.new + @o.rb_undef_alloc_func(klass) + @o.custom_alloc_func?(klass).should == false + end + + it "undefs the allocator for the class" do + klass = Class.new + @o.rb_define_alloc_func(klass) + @o.speced_allocator?(klass).should == true + @o.rb_undef_alloc_func(klass) + @o.custom_alloc_func?(klass).should == false + end + + it "undefs the allocator for a class that inherits a allocator" do + parent = Class.new + @o.rb_define_alloc_func(parent) + klass = Class.new(parent) + @o.speced_allocator?(klass).should == true + @o.rb_undef_alloc_func(klass) + @o.custom_alloc_func?(klass).should == false + + @o.speced_allocator?(parent).should == true + end + end + end end diff --git a/ruby/spec/ruby/optional/capi/proc_spec.rb b/ruby/spec/ruby/optional/capi/proc_spec.rb index 9f9a37cc9..6e797fdeb 100644 --- a/ruby/spec/ruby/optional/capi/proc_spec.rb +++ b/ruby/spec/ruby/optional/capi/proc_spec.rb @@ -54,6 +54,25 @@ @p.rb_proc_call(prc, [6, 7]).should == 42 end end + + describe "rb_obj_is_proc" do + it "returns true for Proc" do + prc = Proc.new {|a,b| a * b } + @p.rb_obj_is_proc(prc).should be_true + end + + it "returns true for subclass of Proc" do + prc = Class.new(Proc).new {} + @p.rb_obj_is_proc(prc).should be_true + end + + it "returns false for non Proc instances" do + @p.rb_obj_is_proc("aoeui").should be_false + @p.rb_obj_is_proc(123).should be_false + @p.rb_obj_is_proc(true).should be_false + @p.rb_obj_is_proc([]).should be_false + end + end end describe "C-API when calling Proc.new from a C function" do @@ -85,8 +104,9 @@ # Ruby -> C -> Ruby -> Proc.new it "raises an ArgumentError when the C function calls a Ruby method that calls Proc.new" do - def @p.Proc_new() Proc.new end - -> { @p.rb_Proc_new(2) { :called } }.should raise_error(ArgumentError) + -> { + @p.rb_Proc_new(2) { :called } + }.should raise_error(ArgumentError) end # Ruby -> C -> Ruby -> C -> rb_funcall(Proc.new) diff --git a/ruby/spec/ruby/optional/capi/rbasic_spec.rb b/ruby/spec/ruby/optional/capi/rbasic_spec.rb new file mode 100644 index 000000000..6300680d9 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/rbasic_spec.rb @@ -0,0 +1,43 @@ +require_relative 'spec_helper' +require_relative 'shared/rbasic' +load_extension("rbasic") +return if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning +load_extension("data") +load_extension("array") + +describe "RBasic support for regular objects" do + before :all do + @specs = CApiRBasicSpecs.new + @data = -> { [Object.new, Object.new] } + end + it_should_behave_like :rbasic +end + +describe "RBasic support for RData" do + before :all do + @specs = CApiRBasicRDataSpecs.new + @wrapping = CApiWrappedStructSpecs.new + @data = -> { [@wrapping.wrap_struct(1024), @wrapping.wrap_struct(1025)] } + end + it_should_behave_like :rbasic + + it "supports user flags" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + @specs.set_flags(obj, 1 << 14 | 1 << 16 | initial).should == 1 << 14 | 1 << 16 | initial + @specs.get_flags(obj).should == 1 << 14 | 1 << 16 | initial + @specs.set_flags(obj, initial).should == initial + end + + it "supports copying the flags from one object over to the other" do + obj1, obj2 = @data.call + initial = @specs.get_flags(obj1) + @specs.get_flags(obj2).should == initial + @specs.set_flags(obj1, 1 << 14 | 1 << 16 | initial) + @specs.copy_flags(obj2, obj1) + @specs.get_flags(obj2).should == 1 << 14 | 1 << 16 | initial + @specs.set_flags(obj1, initial) + @specs.copy_flags(obj2, obj1) + @specs.get_flags(obj2).should == initial + end +end diff --git a/ruby/spec/ruby/optional/capi/regexp_spec.rb b/ruby/spec/ruby/optional/capi/regexp_spec.rb index 52aae6bb0..81844e2a6 100644 --- a/ruby/spec/ruby/optional/capi/regexp_spec.rb +++ b/ruby/spec/ruby/optional/capi/regexp_spec.rb @@ -9,12 +9,20 @@ describe "rb_reg_new" do it "returns a new valid Regexp" do - my_re = @p.a_re + my_re = @p.a_re("a", 0) my_re.kind_of?(Regexp).should == true ('1a' =~ my_re).should == 1 ('1b' =~ my_re).should == nil my_re.source.should == 'a' end + + it "returns a Regexp with the given options" do + @p.a_re("a", 0).options == 0 + @p.a_re("a", Regexp::IGNORECASE).options.should == Regexp::IGNORECASE + @p.a_re("a", Regexp::EXTENDED).options.should == Regexp::EXTENDED + @p.a_re("a", Regexp::EXTENDED | Regexp::IGNORECASE).options.should == Regexp::EXTENDED | Regexp::IGNORECASE + @p.a_re("a", Regexp::MULTILINE).options.should == Regexp::MULTILINE + end end describe "rb_reg_nth_match" do @@ -67,5 +75,38 @@ md = /c/.match('ab') @p.rb_backref_get.should == md end + + it "returns MatchData when used with rb_reg_match" do + @p.rb_reg_match_backref_get(/a/, 'ab')[0].should == 'a' + end + end + + describe "rb_backref_set" do + before :each do + @md = "foo".match(/foo/) + $~ = nil + end + + it "sets the value of $~" do + @p.rb_backref_set(@md) + @p.rb_backref_get.should == @md + $~.should == @md + end + + it "sets a Thread-local value" do + running = false + + thr = Thread.new do + @p.rb_backref_set(@md) + @p.rb_backref_get.should == @md + $~.should == @md + running = true + end + + Thread.pass while thr.status and !running + $~.should be_nil + + thr.join + end end end diff --git a/ruby/spec/ruby/optional/capi/shared/rbasic.rb b/ruby/spec/ruby/optional/capi/shared/rbasic.rb new file mode 100644 index 000000000..5ef63e81e --- /dev/null +++ b/ruby/spec/ruby/optional/capi/shared/rbasic.rb @@ -0,0 +1,63 @@ +describe :rbasic, shared: true do + + before :all do + specs = CApiRBasicSpecs.new + @taint = ruby_version_is(''...'3.1') ? specs.taint_flag : 0 + @freeze = specs.freeze_flag + end + + it "reports the appropriate FREEZE flag for the object when reading" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + obj.freeze + @specs.get_flags(obj).should == @freeze | initial + end + + it "supports setting the FREEZE flag" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + @specs.set_flags(obj, @freeze | initial).should == @freeze | initial + obj.should.frozen? + end + + ruby_version_is ""..."2.7" do + it "reports the appropriate FREEZE and TAINT flags for the object when reading" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + obj.taint + @specs.get_flags(obj).should == @taint | initial + obj.untaint + @specs.get_flags(obj).should == initial + obj.freeze + @specs.get_flags(obj).should == @freeze | initial + + obj, _ = @data.call + obj.taint + obj.freeze + @specs.get_flags(obj).should == @freeze | @taint | initial + end + + it "supports setting the FREEZE and TAINT flags" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + @specs.set_flags(obj, @taint | initial).should == @taint | initial + obj.should.tainted? + @specs.set_flags(obj, initial).should == initial + obj.should_not.tainted? + @specs.set_flags(obj, @freeze | initial).should == @freeze | initial + obj.should.frozen? + + obj, _ = @data.call + @specs.set_flags(obj, @freeze | @taint | initial).should == @freeze | @taint | initial + obj.should.tainted? + obj.should.frozen? + end + end + + it "supports retrieving the (meta)class" do + obj, _ = @data.call + @specs.get_klass(obj).should == obj.class + obj.singleton_class # ensure the singleton class exists + @specs.get_klass(obj).should == obj.singleton_class + end +end diff --git a/ruby/spec/ruby/optional/capi/spec_helper.rb b/ruby/spec/ruby/optional/capi/spec_helper.rb index eda4964b6..9bd2d9791 100644 --- a/ruby/spec/ruby/optional/capi/spec_helper.rb +++ b/ruby/spec/ruby/optional/capi/spec_helper.rb @@ -8,12 +8,17 @@ OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__) def object_path - mkdir_p(OBJDIR) - OBJDIR + path = OBJDIR + if ENV['SPEC_CAPI_CXX'] == 'true' + path = "#{path}/cxx" + end + mkdir_p(path) + path end def compile_extension(name) debug = false + cxx = ENV['SPEC_CAPI_CXX'] == 'true' run_mkmf_in_process = RUBY_ENGINE == 'truffleruby' core_ext_dir = File.expand_path("../ext", __FILE__) @@ -27,11 +32,8 @@ def compile_extension(name) ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h" if RbConfig::CONFIG["ENABLE_SHARED"] == "yes" - if PlatformGuard.windows? - libruby_so = "#{RbConfig::CONFIG['bindir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}" - else - libruby_so = "#{RbConfig::CONFIG['libdir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}" - end + libdirname = RbConfig::CONFIG['libdirname'] # defined since 2.1 + libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}" end begin @@ -43,7 +45,7 @@ def compile_extension(name) when mtime <= File.mtime("#{core_ext_dir}/rubyspec.h") when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c") when mtime <= File.mtime(ruby_header) - when libruby_so && mtime <= File.mtime(libruby_so) + when libruby && mtime <= File.mtime(libruby) else return lib # up-to-date end @@ -54,7 +56,11 @@ def compile_extension(name) Dir.mkdir(tmpdir) begin ["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"].each do |file| - cp file, "#{tmpdir}/#{File.basename(file)}" + if cxx and file.end_with?('.c') + cp file, "#{tmpdir}/#{File.basename(file, '.c')}.cpp" + else + cp file, "#{tmpdir}/#{File.basename(file)}" + end end Dir.chdir(tmpdir) do @@ -64,11 +70,14 @@ def compile_extension(name) init_mkmf unless required create_makefile(ext, tmpdir) else - File.write("extconf.rb", "require 'mkmf'\n" + - "$ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')\n" + + File.write("extconf.rb", <<-RUBY) + require 'mkmf' + $ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ') # MRI magic to consider building non-bundled extensions - "$extout = nil\n" + - "create_makefile(#{ext.inspect})\n") + $extout = nil + append_cflags '-Wno-declaration-after-statement' + create_makefile(#{ext.inspect}) + RUBY output = ruby_exe("extconf.rb") raise "extconf failed:\n#{output}" unless $?.success? $stderr.puts output if debug @@ -116,7 +125,9 @@ def setup_make end def load_extension(name) - require compile_extension(name) + ext_path = compile_extension(name) + require ext_path + ext_path rescue LoadError => e if %r{/usr/sbin/execerror ruby "\(ld 3 1 main ([/a-zA-Z0-9_\-.]+_spec\.so)"} =~ e.message system('/usr/sbin/execerror', "#{RbConfig::CONFIG["bindir"]}/ruby", "(ld 3 1 main #{$1}") diff --git a/ruby/spec/ruby/optional/capi/string_spec.rb b/ruby/spec/ruby/optional/capi/string_spec.rb index 1ad35b9e8..ce387ffa4 100644 --- a/ruby/spec/ruby/optional/capi/string_spec.rb +++ b/ruby/spec/ruby/optional/capi/string_spec.rb @@ -76,7 +76,7 @@ def inspect it "invalidates the code range" do @s.rb_str_set_len(@str, 4) - @str.ascii_only?.should == true + @str.should.ascii_only? end it "updates the string's attributes visible in C code" do @@ -108,7 +108,7 @@ def inspect it "returns a string with the given capacity" do buf = @s.rb_str_buf_new(256, nil) - @s.rb_str_capacity(buf).should == 256 + @s.rb_str_capacity(buf).should >= 256 end it "returns a string that can be appended to" do @@ -158,6 +158,20 @@ def inspect end end + describe "rb_str_tmp_new" do + it "returns a hidden string (RBasic->klass is NULL)" do + @s.rb_str_tmp_new_klass(4).should == false + end + + it "returns a new String object filled with \\0 bytes" do + s = @s.rb_str_tmp_new(4) + s.encoding.should == Encoding::BINARY + s.bytesize.should == 4 + s.size.should == 4 + s.should == "\x00\x00\x00\x00" + end + end + describe "rb_str_new" do it "creates a new String with BINARY Encoding" do @s.rb_str_new("", 0).encoding.should == Encoding::BINARY @@ -169,7 +183,7 @@ def inspect ruby_version_is ''...'2.7' do it "returns a non-tainted string" do - @s.rb_str_new("hello", 5).tainted?.should == false + @s.rb_str_new("hello", 5).should_not.tainted? end end @@ -204,6 +218,20 @@ def inspect end end + describe "rb_usascii_str_new_lit" do + it "returns a US-ASCII string of the correct characters" do + str = @s.rb_usascii_str_new_lit + str.should == "nokogiri" + str.encoding.should == Encoding::US_ASCII + end + + it "returns US-ASCII string for non-US-ASCII string literal" do + str = @s.rb_usascii_str_new_lit_non_ascii + str.should == "r\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::US_ASCII) + str.encoding.should == Encoding::US_ASCII + end + end + describe "rb_usascii_str_new_cstr" do it "creates a new String with US-ASCII Encoding" do str = "abc".force_encoding("us-ascii") @@ -274,8 +302,8 @@ def inspect str2 = @s.rb_str_new4 str1 str1.should == str2 str1.should equal(str2) - str1.frozen?.should == true - str2.frozen?.should == true + str1.should.frozen? + str2.should.frozen? end it "returns a frozen copy of the string" do @@ -283,7 +311,7 @@ def inspect str2 = @s.rb_str_new4 str1 str1.should == str2 str1.should_not equal(str2) - str2.frozen?.should == true + str2.should.frozen? end end @@ -368,6 +396,26 @@ def inspect end end + describe "rb_str_cat_cstr" do + it "concatenates a C string literal to a ruby string" do + @s.rb_str_cat_cstr_constant("Your house is on fire").should == "Your house is on fire?" + end + + it "concatenates a variable C string to a ruby string" do + @s.rb_str_cat_cstr("Your house is on fire", "?").should == "Your house is on fire?" + end + end + + describe "rb_enc_str_buf_cat" do + it "concatenates a C string literal to a ruby string with the given encoding" do + input = "hello ".force_encoding(Encoding::US_ASCII) + result = @s.rb_enc_str_buf_cat(input, "résumé", Encoding::UTF_8) + result.should == "hello résumé" + result.encoding.should == Encoding::UTF_8 + result.object_id.should == input.object_id + end + end + describe "rb_str_cmp" do it "returns 0 if two strings are identical" do @s.rb_str_cmp("ppp", "ppp").should == 0 @@ -440,6 +488,25 @@ def inspect end end + describe "rb_fstring" do + it 'returns self if the String is frozen' do + input = 'foo'.freeze + output = @s.rb_fstring(input) + + output.should equal(input) + output.should.frozen? + end + + it 'returns a frozen copy if the String is not frozen' do + input = 'foo' + output = @s.rb_fstring(input) + + output.should.frozen? + output.should_not equal(input) + output.should == 'foo' + end + end + describe "rb_str_subseq" do it "returns a byte-indexed substring" do str = "\x00\x01\x02\x03\x04".force_encoding("binary") @@ -513,6 +580,32 @@ def inspect end chars.should == [55, 48, 227, 131, 145, 227, 130, 175] end + + it "returns a pointer which can be cast and used as another type" do + s = "70パク". + encode(Encoding::UTF_16LE). + force_encoding(Encoding::UTF_16LE). + encode(Encoding::UTF_8) + + ints = [] + @s.RSTRING_PTR_iterate_uint32(s) do |i| + ints << i + end + ints.should == s.unpack('LL') + end + + it "allows a short memcpy to the string which may be converted to a single write operation by the compiler" do + str = " " + @s.RSTRING_PTR_short_memcpy(str).should == "Infinity" + end + + it "allows read() to update the string contents" do + filename = fixture(__FILE__, "read.txt") + str = "" + capacities = @s.RSTRING_PTR_read(str, filename) + capacities.should == [30, 53] + str.should == "fixture file contents to test read() with RSTRING_PTR" + end end describe "RSTRING_LEN" do @@ -580,25 +673,40 @@ def inspect end end + describe "rb_str_modify" do + it "raises an error if the string is frozen" do + -> { @s.rb_str_modify("frozen".freeze) }.should raise_error(FrozenError) + end + end + describe "rb_str_modify_expand" do it "grows the capacity to bytesize + expand, not changing the bytesize" do str = @s.rb_str_buf_new(256, "abcd") - @s.rb_str_capacity(str).should == 256 + @s.rb_str_capacity(str).should >= 256 @s.rb_str_set_len(str, 3) str.bytesize.should == 3 @s.RSTRING_LEN(str).should == 3 - @s.rb_str_capacity(str).should == 256 + @s.rb_str_capacity(str).should >= 256 @s.rb_str_modify_expand(str, 4) str.bytesize.should == 3 @s.RSTRING_LEN(str).should == 3 - @s.rb_str_capacity(str).should == 7 + @s.rb_str_capacity(str).should >= 7 @s.rb_str_modify_expand(str, 1024) str.bytesize.should == 3 @s.RSTRING_LEN(str).should == 3 - @s.rb_str_capacity(str).should == 1027 + @s.rb_str_capacity(str).should >= 1027 + + @s.rb_str_modify_expand(str, 1) + str.bytesize.should == 3 + @s.RSTRING_LEN(str).should == 3 + @s.rb_str_capacity(str).should >= 4 + end + + it "raises an error if the string is frozen" do + -> { @s.rb_str_modify_expand("frozen".freeze, 10) }.should raise_error(FrozenError) end end @@ -615,6 +723,11 @@ def inspect @s.rb_str_resize_RSTRING_LEN("test", 2).should == 2 end + it "copies the existing bytes" do + str = "t" + @s.rb_str_resize_copy(str).should == "test" + end + it "increases the size of the string" do expected = "test".force_encoding("US-ASCII") str = @s.rb_str_resize(expected.dup, 12) @@ -942,6 +1055,51 @@ def inspect s = 'Result: true.' @s.rb_sprintf4(true.class).should == s end + + it "truncates a string to a supplied precision if that is shorter than the string" do + s = 'Result: Hel.' + @s.rb_sprintf5(0, 3, "Hello").should == s + end + + it "does not truncates a string to a supplied precision if that is longer than the string" do + s = 'Result: Hello.' + @s.rb_sprintf5(0, 8, "Hello").should == s + end + + it "pads a string to a supplied width if that is longer than the string" do + s = 'Result: Hello.' + @s.rb_sprintf5(8, 5, "Hello").should == s + end + + it "truncates a VALUE string to a supplied precision if that is shorter than the VALUE string" do + s = 'Result: Hel.' + @s.rb_sprintf6(0, 3, "Hello").should == s + end + + it "does not truncates a VALUE string to a supplied precision if that is longer than the VALUE string" do + s = 'Result: Hello.' + @s.rb_sprintf6(0, 8, "Hello").should == s + end + + it "pads a VALUE string to a supplied width if that is longer than the VALUE string" do + s = 'Result: Hello.' + @s.rb_sprintf6(8, 5, "Hello").should == s + end + + it "can format a nil VALUE as a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", nil); + res[0].should == res[1] + end + + it "can format a string VALUE as a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", "Hello") + res[0].should == res[1] + end + + it "can format a raw number a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", 0x223643); + res[0].should == res[1] + end end describe "rb_vsprintf" do @@ -1031,4 +1189,51 @@ def inspect str.encoding.should == Encoding::UTF_8 end end + + describe "rb_str_vcatf" do + it "appends the message to the string" do + @s.rb_str_vcatf("").should == "fmt 42 7 number" + + str = "test " + @s.rb_str_vcatf(str) + str.should == "test fmt 42 7 number" + end + end + + describe "rb_str_catf" do + it "appends the message to the string" do + @s.rb_str_catf("").should == "fmt 41 6 number" + + str = "test " + @s.rb_str_catf(str) + str.should == "test fmt 41 6 number" + end + end + + describe "rb_str_locktmp" do + it "raises an error when trying to lock an already locked string" do + str = "test" + @s.rb_str_locktmp(str).should == str + -> { @s.rb_str_locktmp(str) }.should raise_error(RuntimeError, 'temporal locking already locked string') + end + + it "locks a string so that modifications would raise an error" do + str = "test" + @s.rb_str_locktmp(str).should == str + -> { str.upcase! }.should raise_error(RuntimeError, 'can\'t modify string; temporarily locked') + end + end + + describe "rb_str_unlocktmp" do + it "unlocks a locked string" do + str = "test" + @s.rb_str_locktmp(str) + @s.rb_str_unlocktmp(str).should == str + str.upcase!.should == "TEST" + end + + it "raises an error when trying to unlock an already unlocked string" do + -> { @s.rb_str_unlocktmp("test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string') + end + end end diff --git a/ruby/spec/ruby/optional/capi/struct_spec.rb b/ruby/spec/ruby/optional/capi/struct_spec.rb index 6254b098a..0e9e36690 100644 --- a/ruby/spec/ruby/optional/capi/struct_spec.rb +++ b/ruby/spec/ruby/optional/capi/struct_spec.rb @@ -62,7 +62,7 @@ end describe "C-API Struct function" do - before :each do + before :all do @s = CApiStructSpecs.new @struct = @s.rb_struct_define_under(CApiStructSpecs, "CAPIStructUnder", "a", "b", "c") end @@ -188,9 +188,9 @@ -> { @s.rb_struct_aset(@struct, 3, 1) }.should raise_error(IndexError) end - it "raises a #{frozen_error_class} if the struct is frozen" do + it "raises a FrozenError if the struct is frozen" do @struct.freeze - -> { @s.rb_struct_aset(@struct, :a, 1) }.should raise_error(frozen_error_class) + -> { @s.rb_struct_aset(@struct, :a, 1) }.should raise_error(FrozenError) end end diff --git a/ruby/spec/ruby/optional/capi/symbol_spec.rb b/ruby/spec/ruby/optional/capi/symbol_spec.rb index ddc748c8d..b8fda34c0 100644 --- a/ruby/spec/ruby/optional/capi/symbol_spec.rb +++ b/ruby/spec/ruby/optional/capi/symbol_spec.rb @@ -8,6 +8,16 @@ @s = CApiSymbolSpecs.new end + describe "SYMBOL_P" do + it "returns true for a Symbol" do + @s.SYMBOL_P(:foo).should == true + end + + it "returns false for non-Symbols" do + @s.SYMBOL_P('bar').should == false + end + end + describe "rb_intern" do it "converts a string to a symbol, uniquely" do @s.rb_intern("test_symbol").should == :test_symbol @@ -71,6 +81,19 @@ end end + describe "rb_check_symbol_cstr" do + it "returns a Symbol if a Symbol already exists for the given C string" do + sym = :test_symbol + @s.rb_check_symbol_cstr('test_symbol').should == sym + end + + it "returns nil if the Symbol does not exist yet and does not create it" do + str = "symbol_does_not_exist_#{Object.new.object_id}_#{rand}" + @s.rb_check_symbol_cstr(str).should == nil # does not create the Symbol + @s.rb_check_symbol_cstr(str).should == nil + end + end + describe "rb_is_const_id" do it "returns true given a const-like symbol" do @s.rb_is_const_id(:Foo).should == true @@ -130,4 +153,20 @@ @s.rb_sym2str(:bacon).should == "bacon" end end + + describe "rb_to_symbol" do + it "returns a Symbol for a Symbol" do + @s.rb_to_symbol(:foo).should == :foo + end + + it "returns a Symbol for a String" do + @s.rb_to_symbol("foo").should == :foo + end + + it "coerces to Symbol using to_str" do + o = mock('o') + o.should_receive(:to_str).and_return("foo") + @s.rb_to_symbol(o).should == :foo + end + end end diff --git a/ruby/spec/ruby/optional/capi/thread_spec.rb b/ruby/spec/ruby/optional/capi/thread_spec.rb index df454d1ea..30e29681e 100644 --- a/ruby/spec/ruby/optional/capi/thread_spec.rb +++ b/ruby/spec/ruby/optional/capi/thread_spec.rb @@ -102,13 +102,13 @@ def call_capi_rb_thread_wakeup end describe "rb_thread_call_without_gvl" do - it "runs a C function with the global lock unlocked" do + it "runs a C function with the global lock unlocked and can be woken by Thread#wakeup" do thr = Thread.new do @t.rb_thread_call_without_gvl end # Wait until it's blocking... - Thread.pass while thr.status and thr.status != "sleep" + Thread.pass until thr.stop? # The thread status is set to sleep by rb_thread_call_without_gvl(), # but the thread might not be in the blocking read(2) yet, so wait a bit. @@ -121,14 +121,48 @@ def call_capi_rb_thread_wakeup thr.value.should be_true end - guard -> { platform_is :mingw and ruby_version_is ""..."2.7" } do + platform_is_not :windows do + it "runs a C function with the global lock unlocked and can be woken by a signal" do + # Ruby signal handlers run on the main thread, so we need to reverse roles here and have a thread interrupt us + thr = Thread.current + thr.should == Thread.main + + going_to_block = false + interrupter = Thread.new do + # Wait until it's blocking... + Thread.pass until going_to_block and thr.stop? + + # The thread status is set to sleep by rb_thread_call_without_gvl(), + # but the thread might not be in the blocking read(2) yet, so wait a bit. + sleep 0.1 + + # Wake it up by sending a signal + done = false + prev_handler = Signal.trap(:HUP) { done = true } + begin + Process.kill :HUP, Process.pid + sleep 0.001 until done + ensure + Signal.trap(:HUP, prev_handler) + end + end + + going_to_block = true + # Make sure it stopped and we got a proper value + @t.rb_thread_call_without_gvl.should be_true + + interrupter.join + end + end + + platform_is_not :mingw do it "runs a C function with the global lock unlocked and unlocks IO with the generic RUBY_UBF_IO" do thr = Thread.new do @t.rb_thread_call_without_gvl_with_ubf_io end # Wait until it's blocking... - Thread.pass while thr.status and thr.status != "sleep" + Thread.pass until thr.stop? # The thread status is set to sleep by rb_thread_call_without_gvl(), # but the thread might not be in the blocking read(2) yet, so wait a bit. diff --git a/ruby/spec/ruby/optional/capi/time_spec.rb b/ruby/spec/ruby/optional/capi/time_spec.rb index 2c824bb56..579e81fc1 100644 --- a/ruby/spec/ruby/optional/capi/time_spec.rb +++ b/ruby/spec/ruby/optional/capi/time_spec.rb @@ -165,30 +165,28 @@ usec.should == 500000 end - guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do - it "creates a timeval for a negative Fixnum" do - sec, usec = @s.rb_time_timeval(-1232141421) - sec.should be_kind_of(Integer) - sec.should == -1232141421 - usec.should be_kind_of(Integer) - usec.should == 0 - end + it "creates a timeval for a negative Fixnum" do + sec, usec = @s.rb_time_timeval(-1232141421) + sec.should be_kind_of(Integer) + sec.should == -1232141421 + usec.should be_kind_of(Integer) + usec.should == 0 + end - it "creates a timeval for a negative Float" do - sec, usec = @s.rb_time_timeval(-1.5) - sec.should be_kind_of(Integer) - sec.should == -2 - usec.should be_kind_of(Integer) - usec.should == 500000 - end + it "creates a timeval for a negative Float" do + sec, usec = @s.rb_time_timeval(-1.5) + sec.should be_kind_of(Integer) + sec.should == -2 + usec.should be_kind_of(Integer) + usec.should == 500000 + end - it "creates a timeval for a negative Rational" do - sec, usec = @s.rb_time_timeval(Rational(-3, 2)) - sec.should be_kind_of(Integer) - sec.should == -2 - usec.should be_kind_of(Integer) - usec.should == 500000 - end + it "creates a timeval for a negative Rational" do + sec, usec = @s.rb_time_timeval(Rational(-3, 2)) + sec.should be_kind_of(Integer) + sec.should == -2 + usec.should be_kind_of(Integer) + usec.should == 500000 end it "creates a timeval from a Time object" do @@ -224,30 +222,28 @@ nsec.should == 500000000 end - guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do - it "creates a timespec for a negative Fixnum" do - sec, nsec = @s.rb_time_timespec(-1232141421) - sec.should be_kind_of(Integer) - sec.should == -1232141421 - nsec.should be_kind_of(Integer) - nsec.should == 0 - end + it "creates a timespec for a negative Fixnum" do + sec, nsec = @s.rb_time_timespec(-1232141421) + sec.should be_kind_of(Integer) + sec.should == -1232141421 + nsec.should be_kind_of(Integer) + nsec.should == 0 + end - it "creates a timespec for a negative Float" do - sec, nsec = @s.rb_time_timespec(-1.5) - sec.should be_kind_of(Integer) - sec.should == -2 - nsec.should be_kind_of(Integer) - nsec.should == 500000000 - end + it "creates a timespec for a negative Float" do + sec, nsec = @s.rb_time_timespec(-1.5) + sec.should be_kind_of(Integer) + sec.should == -2 + nsec.should be_kind_of(Integer) + nsec.should == 500000000 + end - it "creates a timespec for a negative Rational" do - sec, nsec = @s.rb_time_timespec(Rational(-3, 2)) - sec.should be_kind_of(Integer) - sec.should == -2 - nsec.should be_kind_of(Integer) - nsec.should == 500000000 - end + it "creates a timespec for a negative Rational" do + sec, nsec = @s.rb_time_timespec(Rational(-3, 2)) + sec.should be_kind_of(Integer) + sec.should == -2 + nsec.should be_kind_of(Integer) + nsec.should == 500000000 end it "creates a timespec from a Time object" do diff --git a/ruby/spec/ruby/optional/capi/tracepoint_spec.rb b/ruby/spec/ruby/optional/capi/tracepoint_spec.rb new file mode 100644 index 000000000..2043b7c94 --- /dev/null +++ b/ruby/spec/ruby/optional/capi/tracepoint_spec.rb @@ -0,0 +1,56 @@ +require_relative 'spec_helper' + +load_extension("tracepoint") + +describe "CApiTracePointSpecs" do + before :each do + @s = CApiTracePointSpecs.new + end + + after :each do + @trace.disable if @trace and @trace.enabled? + end + + describe "rb_tracepoint_new" do + it "returns a tracepoint object" do + @trace = @s.rb_tracepoint_new(7) + @trace.should be_an_instance_of(TracePoint) + @trace.should_not.enabled? + end + + it "traces lines when given RUBY_EVENT_LINE" do + @trace = @s.rb_tracepoint_new(8) + @trace.enable + @s.callback_called?.should == 8 + end + end + + describe "rb_tracepoint_disable" do + it "disables an enabled TracePoint" do + @trace = @s.rb_tracepoint_new(9) + @trace.should_not.enabled? + @trace.enable + @trace.should.enabled? + @s.rb_tracepoint_disable(@trace).should == false + @trace.should_not.enabled? + end + end + + describe "rb_tracepoint_enable" do + it "enables a disabled TracePoint" do + @trace = @s.rb_tracepoint_new(10) + @trace.should_not.enabled? + @s.rb_tracepoint_enable(@trace).should == true + @trace.should.enabled? + end + end + + describe "rb_tracepoint_enabled_p" do + it "returns correct enabled status" do + @trace = @s.rb_tracepoint_new(11) + @s.rb_tracepoint_enabled_p(@trace).should == false + @trace.enable + @s.rb_tracepoint_enabled_p(@trace).should == true + end + end +end diff --git a/ruby/spec/ruby/optional/capi/typed_data_spec.rb b/ruby/spec/ruby/optional/capi/typed_data_spec.rb index da56a050f..23b7c157e 100644 --- a/ruby/spec/ruby/optional/capi/typed_data_spec.rb +++ b/ruby/spec/ruby/optional/capi/typed_data_spec.rb @@ -57,4 +57,32 @@ @s.typed_get_struct_data_ptr(a).should == 1024 end end + + describe "rb_check_type" do + it "raises an exception when checking typed data objects" do + -> { + a = @s.typed_wrap_struct(1024) + @s.rb_check_type(a, a) + }.should raise_error(TypeError) { |e| + e.message.should == 'wrong argument type Object (expected Data)' + } + end + end + + describe "rb_check_typeddata" do + it "returns data pointer when the struct has the given type" do + a = @s.typed_wrap_struct(1024) + @s.rb_check_typeddata_same_type(a).should == true + end + + it "returns data pointer when the parent struct has the given type" do + a = @s.typed_wrap_struct(1024) + @s.rb_check_typeddata_same_type_parent(a).should == true + end + + it "raises an error for different types" do + a = @s.typed_wrap_struct(1024) + -> { @s.rb_check_typeddata_different_type(a) }.should raise_error(TypeError) + end + end end diff --git a/ruby/spec/ruby/optional/capi/util_spec.rb b/ruby/spec/ruby/optional/capi/util_spec.rb index 3556c8c01..a90c28a78 100644 --- a/ruby/spec/ruby/optional/capi/util_spec.rb +++ b/ruby/spec/ruby/optional/capi/util_spec.rb @@ -115,11 +115,22 @@ ScratchPad.recorded.should == [1, nil] end - it "assigns required and Hash arguments with nil Hash" do - suppress_warning do - @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1 + ruby_version_is ''...'3.0' do + it "assigns required and Hash arguments with nil Hash" do + suppress_warning do + @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1 + end + ScratchPad.recorded.should == [1, nil] + end + end + + ruby_version_is '3.0' do + it "rejects the use of nil as a hash" do + -> { + @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1 + }.should raise_error(ArgumentError) + ScratchPad.recorded.should == [] end - ScratchPad.recorded.should == [1, nil] end it "assigns required and optional arguments with no hash argument given" do @@ -133,33 +144,55 @@ ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc] end - # r43934 - it "rejects non-keyword arguments" do - h = {1 => 2, 3 => 4} - -> { - suppress_warning do - @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc) - end - }.should raise_error(ArgumentError) - ScratchPad.recorded.should == [] - end + ruby_version_is ''...'3.0' do + # r43934 + it "rejects non-keyword arguments" do + h = {1 => 2, 3 => 4} + -> { + suppress_warning do + @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc) + end + }.should raise_error(ArgumentError) + ScratchPad.recorded.should == [] + end - it "rejects required and non-keyword arguments" do - h = {1 => 2, 3 => 4} - -> { + it "rejects required and non-keyword arguments" do + h = {1 => 2, 3 => 4} + -> { + suppress_warning do + @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc) + end + }.should raise_error(ArgumentError) + ScratchPad.recorded.should == [] + end + + it "considers the hash as a post argument when there is a splat" do + h = {1 => 2, 3 => 4} suppress_warning do - @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc) + @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 6 end - }.should raise_error(ArgumentError) - ScratchPad.recorded.should == [] + ScratchPad.recorded.should == [1, 2, [3, 4, 5], h, nil, @prc] + end end - it "considers the hash as a post argument when there is a splat" do - h = {1 => 2, 3 => 4} - suppress_warning do - @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 6 + ruby_version_is '3.0' do + it "does not reject non-symbol keys in keyword arguments" do + h = {1 => 2, 3 => 4} + @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc).should == 0 + ScratchPad.recorded.should == [h] + end + + it "does not reject non-symbol keys in keyword arguments with required argument" do + h = {1 => 2, 3 => 4} + @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc).should == 1 + ScratchPad.recorded.should == [1, h] + end + + it "considers keyword arguments with non-symbol keys as keywords when using splat and post arguments" do + h = {1 => 2, 3 => 4} + @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 5 + ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc] end - ScratchPad.recorded.should == [1, 2, [3, 4, 5], h, nil, @prc] end end @@ -256,7 +289,37 @@ describe "rb_sourceline" do it "returns the current ruby file" do - @o.rb_sourceline.should be_kind_of(Fixnum) + @o.rb_sourceline.should be_kind_of(Integer) + end + end + + # ruby/util.h redefines strtod as a macro calling ruby_strtod + + describe "strtod" do + it "converts a string to a double and returns the remaining string" do + d, s = @o.strtod("14.25test") + d.should == 14.25 + s.should == "test" + end + + it "returns 0 and the full string if there's no numerical value" do + d, s = @o.strtod("test") + d.should == 0 + s.should == "test" + end + end + + describe "ruby_strtod" do + it "converts a string to a double and returns the remaining string" do + d, s = @o.ruby_strtod("14.25test") + d.should == 14.25 + s.should == "test" + end + + it "returns 0 and the full string if there's no numerical value" do + d, s = @o.ruby_strtod("test") + d.should == 0 + s.should == "test" end end diff --git a/ruby/spec/ruby/security/cve_2010_1330_spec.rb b/ruby/spec/ruby/security/cve_2010_1330_spec.rb index fa4c756c6..33e88d652 100644 --- a/ruby/spec/ruby/security/cve_2010_1330_spec.rb +++ b/ruby/spec/ruby/security/cve_2010_1330_spec.rb @@ -1,7 +1,6 @@ require_relative '../spec_helper' describe "String#gsub" do - it "resists CVE-2010-1330 by raising an exception on invalid UTF-8 bytes" do # This original vulnerability talked about KCODE, which is no longer # used. Instead we are forcing encodings here. But I think the idea is the @@ -17,5 +16,4 @@ str.gsub(/ - - - - - - - - - - - ]> - - %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9; - + it "resists CVE-2014-8080 by raising an exception when entity expansion has grown too large" do + xml = < + + + + + + + + + + + ]> + + %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9; + XML - -> { - REXML::Document.new(xml).doctype.entities['x9'].value - }.should raise_error(REXML::ParseException, /entity expansion has grown too large/) - end + -> { + REXML::Document.new(xml).doctype.entities['x9'].value + }.should raise_error(REXML::ParseException, /entity expansion has grown too large/) + end + end end diff --git a/ruby/spec/ruby/security/cve_2017_17742_spec.rb b/ruby/spec/ruby/security/cve_2017_17742_spec.rb index 72776cb49..b0d93e42b 100644 --- a/ruby/spec/ruby/security/cve_2017_17742_spec.rb +++ b/ruby/spec/ruby/security/cve_2017_17742_spec.rb @@ -1,34 +1,37 @@ require_relative '../spec_helper' -require "webrick" -require "stringio" -require "net/http" +# webrick is no longer in stdlib in Ruby 3+ +ruby_version_is ""..."3.0" do + require "webrick" + require "stringio" + require "net/http" -describe "WEBrick" do - describe "resists CVE-2017-17742" do - it "for a response splitting headers" do - config = WEBrick::Config::HTTP - res = WEBrick::HTTPResponse.new config - res['X-header'] = "malicious\r\nCookie: hack" - io = StringIO.new - res.send_response io - io.rewind - res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) - res.code.should == '500' - io.string.should_not =~ /hack/ - end + describe "WEBrick" do + describe "resists CVE-2017-17742" do + it "for a response splitting headers" do + config = WEBrick::Config::HTTP + res = WEBrick::HTTPResponse.new config + res['X-header'] = "malicious\r\nCookie: hack" + io = StringIO.new + res.send_response io + io.rewind + res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) + res.code.should == '500' + io.string.should_not =~ /hack/ + end - it "for a response splitting cookie headers" do - user_input = "malicious\r\nCookie: hack" - config = WEBrick::Config::HTTP - res = WEBrick::HTTPResponse.new config - res.cookies << WEBrick::Cookie.new('author', user_input) - io = StringIO.new - res.send_response io - io.rewind - res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) - res.code.should == '500' - io.string.should_not =~ /hack/ + it "for a response splitting cookie headers" do + user_input = "malicious\r\nCookie: hack" + config = WEBrick::Config::HTTP + res = WEBrick::HTTPResponse.new config + res.cookies << WEBrick::Cookie.new('author', user_input) + io = StringIO.new + res.send_response io + io.rewind + res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) + res.code.should == '500' + io.string.should_not =~ /hack/ + end end end end diff --git a/ruby/spec/ruby/security/cve_2018_16396_spec.rb b/ruby/spec/ruby/security/cve_2018_16396_spec.rb index 303c47a8c..c9624e9c6 100644 --- a/ruby/spec/ruby/security/cve_2018_16396_spec.rb +++ b/ruby/spec/ruby/security/cve_2018_16396_spec.rb @@ -1,7 +1,6 @@ require_relative '../spec_helper' describe "Array#pack" do - ruby_version_is ''...'2.7' do it "resists CVE-2018-16396 by tainting output based on input" do "aAZBbHhuMmPp".each_char do |f| @@ -9,11 +8,9 @@ end end end - end describe "String#unpack" do - ruby_version_is ''...'2.7' do it "resists CVE-2018-16396 by tainting output based on input" do "aAZBbHhuMm".each_char do |f| @@ -21,5 +18,4 @@ end end end - end diff --git a/ruby/spec/ruby/security/cve_2018_8778_spec.rb b/ruby/spec/ruby/security/cve_2018_8778_spec.rb index 628159a4d..62057faa5 100644 --- a/ruby/spec/ruby/security/cve_2018_8778_spec.rb +++ b/ruby/spec/ruby/security/cve_2018_8778_spec.rb @@ -1,12 +1,10 @@ require_relative '../spec_helper' describe "String#unpack" do - it "resists CVE-2018-8778 by raising an exception when a position indicator is larger than a native integer" do pos = (1 << PlatformGuard::POINTER_SIZE) - 99 -> { "0123456789".unpack("@#{pos}C10") }.should raise_error(RangeError, /pack length too big/) end - end diff --git a/ruby/spec/ruby/security/cve_2018_8780_spec.rb b/ruby/spec/ruby/security/cve_2018_8780_spec.rb index 555ce9365..9942e07ee 100644 --- a/ruby/spec/ruby/security/cve_2018_8780_spec.rb +++ b/ruby/spec/ruby/security/cve_2018_8780_spec.rb @@ -29,17 +29,15 @@ }.should raise_error(ArgumentError, /(path name|string) contains null byte/) end - ruby_version_is "2.5" do - it "Dir.children by raising an exception when there is a NUL byte" do - -> { - Dir.children(@root+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) - end + it "Dir.children by raising an exception when there is a NUL byte" do + -> { + Dir.children(@root+"\0") + }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + end - it "Dir.each_child by raising an exception when there is a NUL byte" do - -> { - Dir.each_child(@root+"\0").to_a - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) - end + it "Dir.each_child by raising an exception when there is a NUL byte" do + -> { + Dir.each_child(@root+"\0").to_a + }.should raise_error(ArgumentError, /(path name|string) contains null byte/) end end diff --git a/ruby/spec/ruby/security/cve_2019_8321_spec.rb b/ruby/spec/ruby/security/cve_2019_8321_spec.rb index affcd00e0..a8a86e7d9 100644 --- a/ruby/spec/ruby/security/cve_2019_8321_spec.rb +++ b/ruby/spec/ruby/security/cve_2019_8321_spec.rb @@ -3,20 +3,18 @@ require 'rubygems' require 'rubygems/user_interaction' -ruby_version_is "2.5.5" do - describe "CVE-2019-8321 is resisted by" do - it "sanitising verbose messages" do - ui = Class.new { - include Gem::UserInteraction - }.new - ui.should_receive(:say).with(".]2;nyan.") - verbose_before = Gem.configuration.verbose - begin - Gem.configuration.verbose = :really_verbose - ui.verbose("\e]2;nyan\a") - ensure - Gem.configuration.verbose = verbose_before - end +describe "CVE-2019-8321 is resisted by" do + it "sanitising verbose messages" do + ui = Class.new { + include Gem::UserInteraction + }.new + ui.should_receive(:say).with(".]2;nyan.") + verbose_before = Gem.configuration.verbose + begin + Gem.configuration.verbose = :really_verbose + ui.verbose("\e]2;nyan\a") + ensure + Gem.configuration.verbose = verbose_before end end end diff --git a/ruby/spec/ruby/security/cve_2019_8322_spec.rb b/ruby/spec/ruby/security/cve_2019_8322_spec.rb index 04fb1a7a2..b70d78c03 100644 --- a/ruby/spec/ruby/security/cve_2019_8322_spec.rb +++ b/ruby/spec/ruby/security/cve_2019_8322_spec.rb @@ -5,19 +5,17 @@ require 'rubygems/safe_yaml' require 'rubygems/commands/owner_command' -ruby_version_is "2.5.5" do - describe "CVE-2019-8322 is resisted by" do - it "sanitising owner names" do - command = Gem::Commands::OwnerCommand.new - def command.rubygems_api_request(*args) - Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n") - end - def command.with_response(response) - yield response - end - command.should_receive(:say).with("Owners for gem: name") - command.should_receive(:say).with("- .]2;nyan.") - command.show_owners "name" +describe "CVE-2019-8322 is resisted by" do + it "sanitising owner names" do + command = Gem::Commands::OwnerCommand.new + def command.rubygems_api_request(*args) + Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n") end + def command.with_response(response) + yield response + end + command.should_receive(:say).with("Owners for gem: name") + command.should_receive(:say).with("- .]2;nyan.") + command.show_owners "name" end end diff --git a/ruby/spec/ruby/security/cve_2019_8323_spec.rb b/ruby/spec/ruby/security/cve_2019_8323_spec.rb index af0b27088..3632d3b02 100644 --- a/ruby/spec/ruby/security/cve_2019_8323_spec.rb +++ b/ruby/spec/ruby/security/cve_2019_8323_spec.rb @@ -1,11 +1,11 @@ require_relative '../spec_helper' -require 'optparse' +platform_is_not :darwin do # frequent timeout/hang on macOS + require 'optparse' -require 'rubygems' -require 'rubygems/gemcutter_utilities' + require 'rubygems' + require 'rubygems/gemcutter_utilities' -ruby_version_is "2.5.5" do describe "CVE-2019-8323 is resisted by" do describe "sanitising the body" do it "for success codes" do diff --git a/ruby/spec/ruby/security/cve_2019_8325_spec.rb b/ruby/spec/ruby/security/cve_2019_8325_spec.rb index dcdbe3421..309445a50 100644 --- a/ruby/spec/ruby/security/cve_2019_8325_spec.rb +++ b/ruby/spec/ruby/security/cve_2019_8325_spec.rb @@ -1,9 +1,9 @@ require_relative '../spec_helper' -require 'rubygems' -require 'rubygems/command_manager' +platform_is_not :darwin do # frequent timeout/hang on macOS + require 'rubygems' + require 'rubygems/command_manager' -ruby_version_is "2.5.5" do describe "CVE-2019-8325 is resisted by" do describe "sanitising error message components" do it "for the 'while executing' message" do diff --git a/ruby/spec/ruby/security/cve_2020_10663_spec.rb b/ruby/spec/ruby/security/cve_2020_10663_spec.rb new file mode 100644 index 000000000..766590d50 --- /dev/null +++ b/ruby/spec/ruby/security/cve_2020_10663_spec.rb @@ -0,0 +1,42 @@ +require_relative '../spec_helper' +require 'json' + +module JSONSpecs + class MyClass + def initialize(foo) + @foo = foo + end + + def self.json_create(hash) + new(*hash['args']) + end + + def to_json(*args) + { 'json_class' => self.class.name, 'args' => [ @foo ] }.to_json(*args) + end + end +end + +guard -> { + ruby_version_is "2.6.6" or + JSON.const_defined?(:Pure) or + version_is(JSON::VERSION, '2.3.0') +} do + platform_is_not :darwin do # frequent timeout/hang on macOS + describe "CVE-2020-10663 is resisted by" do + it "only creating custom objects if passed create_additions: true or using JSON.load" do + obj = JSONSpecs::MyClass.new("bar") + JSONSpecs::MyClass.should.json_creatable? + json = JSON.dump(obj) + + JSON.parse(json, create_additions: true).class.should == JSONSpecs::MyClass + JSON(json, create_additions: true).class.should == JSONSpecs::MyClass + JSON.load(json).class.should == JSONSpecs::MyClass + + JSON.parse(json).class.should == Hash + JSON.parse(json, nil).class.should == Hash + JSON(json).class.should == Hash + end + end + end +end diff --git a/ruby/spec/ruby/shared/enumerable/minmax.rb b/ruby/spec/ruby/shared/enumerable/minmax.rb new file mode 100644 index 000000000..8af2626d2 --- /dev/null +++ b/ruby/spec/ruby/shared/enumerable/minmax.rb @@ -0,0 +1,24 @@ +describe :enumerable_minmax, shared: true do + it "min should return the minimum element" do + @enum.minmax.should == [4, 10] + @strs.minmax.should == ["1010", "60"] + end + + it "returns the minimum when using a block rule" do + @enum.minmax {|a,b| b <=> a }.should == [10, 4] + @strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"] + end + + it "returns [nil, nil] for an empty Enumerable" do + @empty_enum.minmax.should == [nil, nil] + end + + it "raises a NoMethodError for elements without #<=>" do + -> { @incomparable_enum.minmax }.should raise_error(NoMethodError) + end + + it "raises an ArgumentError when elements are incompatible" do + -> { @incompatible_enum.minmax }.should raise_error(ArgumentError) + -> { @enum.minmax{ |a, b| nil } }.should raise_error(ArgumentError) + end +end diff --git a/ruby/spec/ruby/shared/enumerator/enum_for.rb b/ruby/spec/ruby/shared/enumerator/enum_for.rb index 9030ffbd7..a67a76c46 100644 --- a/ruby/spec/ruby/shared/enumerator/enum_for.rb +++ b/ruby/spec/ruby/shared/enumerator/enum_for.rb @@ -12,6 +12,13 @@ enum.map { |v| v }.should == [1,2].each { |v| v } end + it "sets regexp matches in the caller" do + "wawa".send(@method, :scan, /./).map {|o| $& }.should == ["w", "a", "w", "a"] + a = [] + "wawa".send(@method, :scan, /./).each {|o| a << $& } + a.should == ["w", "a", "w", "a"] + end + it "exposes multi-arg yields as an array" do o = Object.new def o.each diff --git a/ruby/spec/ruby/shared/fiber/resume.rb b/ruby/spec/ruby/shared/fiber/resume.rb index d3dc438ae..f3477804a 100644 --- a/ruby/spec/ruby/shared/fiber/resume.rb +++ b/ruby/spec/ruby/shared/fiber/resume.rb @@ -35,32 +35,11 @@ fiber.send(@method) end - it "runs until Fiber.yield" do - obj = mock('obj') - obj.should_not_receive(:do) - fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do } - fiber.send(@method) - end - - it "resumes from the last call to Fiber.yield on subsequent invocations" do - fiber = Fiber.new { Fiber.yield :first; :second } - fiber.send(@method).should == :first - fiber.send(@method).should == :second - end - it "accepts any number of arguments" do fiber = Fiber.new { |a| } -> { fiber.send(@method, *(1..10).to_a) }.should_not raise_error end - it "sets the block parameters to its arguments on the first invocation" do - first = mock('first') - first.should_receive(:arg).with(:first).twice - fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; } - fiber.send(@method, :first) - fiber.send(@method, :second) - end - it "raises a FiberError if the Fiber is dead" do fiber = Fiber.new { true } fiber.send(@method) diff --git a/ruby/spec/ruby/shared/file/executable.rb b/ruby/spec/ruby/shared/file/executable.rb index 2987d0aab..7b5c4c580 100644 --- a/ruby/spec/ruby/shared/file/executable.rb +++ b/ruby/spec/ruby/shared/file/executable.rb @@ -13,7 +13,7 @@ rm_r @file1, @file2 end - platform_is_not :windows do + platform_is_not :windows, :android do it "returns true if named file is executable by the effective user id of the process, otherwise false" do @object.send(@method, '/etc/passwd').should == false @object.send(@method, @file1).should == true diff --git a/ruby/spec/ruby/shared/file/identical.rb b/ruby/spec/ruby/shared/file/identical.rb index ecc21727c..b7a290483 100644 --- a/ruby/spec/ruby/shared/file/identical.rb +++ b/ruby/spec/ruby/shared/file/identical.rb @@ -9,7 +9,11 @@ touch(@file2) { |f| f.puts "file2" } rm_r @link - File.link(@file1, @link) + begin + File.link(@file1, @link) + rescue Errno::EACCES + File.symlink(@file1, @link) + end end after :each do diff --git a/ruby/spec/ruby/shared/file/readable.rb b/ruby/spec/ruby/shared/file/readable.rb index 74f58caaf..eb2ca0681 100644 --- a/ruby/spec/ruby/shared/file/readable.rb +++ b/ruby/spec/ruby/shared/file/readable.rb @@ -4,9 +4,12 @@ platform_is :windows do @file2 = File.join(ENV["WINDIR"], "system32/drivers/etc/services").tr(File::SEPARATOR, File::ALT_SEPARATOR) end - platform_is_not :windows do + platform_is_not :windows, :android do @file2 = "/etc/passwd" end + platform_is :android do + @file2 = "/system/bin/sh" + end end after :each do diff --git a/ruby/spec/ruby/shared/file/world_readable.rb b/ruby/spec/ruby/shared/file/world_readable.rb index 85761e633..1dce7a580 100644 --- a/ruby/spec/ruby/shared/file/world_readable.rb +++ b/ruby/spec/ruby/shared/file/world_readable.rb @@ -28,18 +28,18 @@ end end - # We don't specify what the Fixnum is because it's system dependent - it "returns a Fixnum if the file is chmod 644" do + # We don't specify what the Integer is because it's system dependent + it "returns an Integer if the file is chmod 644" do File.chmod(0644, @file) - @object.world_readable?(@file).should be_an_instance_of(Fixnum) + @object.world_readable?(@file).should be_an_instance_of(Integer) end - it "returns a Fixnum if the file is a directory and chmod 644" do - dir = rand().to_s + '-ww' + it "returns an Integer if the file is a directory and chmod 644" do + dir = tmp(rand().to_s + '-ww') Dir.mkdir(dir) Dir.should.exist?(dir) File.chmod(0644, dir) - @object.world_readable?(dir).should be_an_instance_of(Fixnum) + @object.world_readable?(dir).should be_an_instance_of(Integer) Dir.rmdir(dir) end diff --git a/ruby/spec/ruby/shared/file/world_writable.rb b/ruby/spec/ruby/shared/file/world_writable.rb index 61b691bcb..7ed252dcf 100644 --- a/ruby/spec/ruby/shared/file/world_writable.rb +++ b/ruby/spec/ruby/shared/file/world_writable.rb @@ -27,18 +27,18 @@ @object.world_writable?(@file).should be_nil end - # We don't specify what the Fixnum is because it's system dependent - it "returns a Fixnum if the file is chmod 777" do + # We don't specify what the Integer is because it's system dependent + it "returns an Integer if the file is chmod 777" do File.chmod(0777, @file) - @object.world_writable?(@file).should be_an_instance_of(Fixnum) + @object.world_writable?(@file).should be_an_instance_of(Integer) end - it "returns a Fixnum if the file is a directory and chmod 777" do - dir = rand().to_s + '-ww' + it "returns an Integer if the file is a directory and chmod 777" do + dir = tmp(rand().to_s + '-ww') Dir.mkdir(dir) Dir.should.exist?(dir) File.chmod(0777, dir) - @object.world_writable?(dir).should be_an_instance_of(Fixnum) + @object.world_writable?(dir).should be_an_instance_of(Integer) Dir.rmdir(dir) end end diff --git a/ruby/spec/ruby/shared/file/writable.rb b/ruby/spec/ruby/shared/file/writable.rb index 902d545da..4bb8aedce 100644 --- a/ruby/spec/ruby/shared/file/writable.rb +++ b/ruby/spec/ruby/shared/file/writable.rb @@ -8,7 +8,7 @@ end it "returns true if named file is writable by the effective user id of the process, otherwise false" do - platform_is_not :windows do + platform_is_not :windows, :android do as_user do @object.send(@method, "/etc/passwd").should == false end diff --git a/ruby/spec/ruby/shared/hash/key_error.rb b/ruby/spec/ruby/shared/hash/key_error.rb index 061c88c48..54dcb89e9 100644 --- a/ruby/spec/ruby/shared/hash/key_error.rb +++ b/ruby/spec/ruby/shared/hash/key_error.rb @@ -5,21 +5,19 @@ }.should raise_error(KeyError) end - ruby_version_is "2.5" do - it "sets the Hash as the receiver of KeyError" do - -> { - @method.call(@object, 'foo') - }.should raise_error(KeyError) { |err| - err.receiver.should equal(@object) - } - end + it "sets the Hash as the receiver of KeyError" do + -> { + @method.call(@object, 'foo') + }.should raise_error(KeyError) { |err| + err.receiver.should equal(@object) + } + end - it "sets the unmatched key as the key of KeyError" do - -> { - @method.call(@object, 'foo') - }.should raise_error(KeyError) { |err| - err.key.to_s.should == 'foo' - } - end + it "sets the unmatched key as the key of KeyError" do + -> { + @method.call(@object, 'foo') + }.should raise_error(KeyError) { |err| + err.key.to_s.should == 'foo' + } end end diff --git a/ruby/spec/ruby/shared/io/putc.rb b/ruby/spec/ruby/shared/io/putc.rb index fac14886e..e6012c009 100644 --- a/ruby/spec/ruby/shared/io/putc.rb +++ b/ruby/spec/ruby/shared/io/putc.rb @@ -6,7 +6,7 @@ rm_r @name end - describe "with a Fixnum argument" do + describe "with an Integer argument" do it "writes one character as a String" do @io.should_receive(:write).with("A") @io_object.send(@method, 65).should == 65 diff --git a/ruby/spec/ruby/shared/kernel/raise.rb b/ruby/spec/ruby/shared/kernel/raise.rb index d4553775f..765ba0f92 100644 --- a/ruby/spec/ruby/shared/kernel/raise.rb +++ b/ruby/spec/ruby/shared/kernel/raise.rb @@ -12,6 +12,28 @@ ScratchPad.recorded.should be_nil end + it "accepts an exception that implements to_hash" do + custom_error = Class.new(StandardError) do + def to_hash + {} + end + end + error = custom_error.new + -> { @object.raise(error) }.should raise_error(custom_error) + end + + it "allows the message parameter to be a hash" do + data_error = Class.new(StandardError) do + attr_reader :data + def initialize(data) + @data = data + end + end + -> { @object.raise(data_error, {:data => 42}) }.should raise_error(data_error) do |ex| + ex.data.should == {:data => 42} + end + end + it "raises RuntimeError if no exception class is given" do -> { @object.raise }.should raise_error(RuntimeError, "") end @@ -25,6 +47,14 @@ -> { @object.raise("a bad thing") }.should raise_error(RuntimeError) end + it "passes no arguments to the constructor when given only an exception class" do + klass = Class.new(Exception) do + def initialize + end + end + -> { @object.raise(klass) }.should raise_error(klass) { |e| e.message.should == klass.to_s } + end + it "raises a TypeError when passed a non-Exception object" do -> { @object.raise(Object.new) }.should raise_error(TypeError) end @@ -41,40 +71,44 @@ -> { @object.raise(nil) }.should raise_error(TypeError) end - it "re-raises the previously rescued exception if no exception is specified" do - -> do - begin - @object.raise Exception, "outer" - ScratchPad.record :no_abort - rescue + it "re-raises a previously rescued exception without overwriting the backtrace" do + # This spec is written using #backtrace and matching the line number + # from the string, as backtrace_locations is a more advanced + # method that is not always supported by implementations. + # + initial_raise_line = nil + raise_again_line = nil + raised_again = nil + + if defined?(FiberSpecs::NewFiberToRaise) and @object == FiberSpecs::NewFiberToRaise + fiber = Fiber.new do begin - @object.raise StandardError, "inner" - rescue + initial_raise_line = __LINE__; Fiber.yield + rescue => raised + begin + raise_again_line = __LINE__; Fiber.yield raised + rescue => raised_again + raised_again + end end - - @object.raise - ScratchPad.record :no_reraise end - end.should raise_error(Exception, "outer") - - ScratchPad.recorded.should be_nil - end - - it "re-raises a previously rescued exception without overwriting the backtrace" do - begin - initial_raise_line = __LINE__; @object.raise 'raised' - rescue => raised + fiber.resume + raised = fiber.raise 'raised' + raised_again = fiber.raise raised + else begin - raise_again_line = __LINE__; @object.raise raised - rescue => raised_again - # This spec is written using #backtrace and matching the line number - # from the string, as backtrace_locations is a more advanced - # method that is not always supported by implementations. - - raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:") - raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:") + initial_raise_line = __LINE__; @object.raise 'raised' + rescue => raised + begin + raise_again_line = __LINE__; @object.raise raised + rescue => raised_again + raised_again + end end end + + raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:") + raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:") end it "allows Exception, message, and backtrace parameters" do diff --git a/ruby/spec/ruby/shared/process/exit.rb b/ruby/spec/ruby/shared/process/exit.rb index 1820dd17f..ae8abaea4 100644 --- a/ruby/spec/ruby/shared/process/exit.rb +++ b/ruby/spec/ruby/shared/process/exit.rb @@ -75,20 +75,40 @@ describe :process_exit!, shared: true do it "exits with the given status" do - out = ruby_exe("#{@object}.send(:exit!, 21)", args: '2>&1') + out = ruby_exe("#{@object}.send(:exit!, 21)", args: '2>&1', exit_status: 21) out.should == "" $?.exitstatus.should == 21 end it "exits when called from a thread" do - out = ruby_exe("Thread.new { #{@object}.send(:exit!, 21) }.join; sleep", args: '2>&1') + out = ruby_exe("Thread.new { #{@object}.send(:exit!, 21) }.join; sleep", args: '2>&1', exit_status: 21) out.should == "" $?.exitstatus.should == 21 end it "exits when called from a fiber" do - out = ruby_exe("Fiber.new { #{@object}.send(:exit!, 21) }.resume", args: '2>&1') + out = ruby_exe("Fiber.new { #{@object}.send(:exit!, 21) }.resume", args: '2>&1', exit_status: 21) out.should == "" $?.exitstatus.should == 21 end + + it "skips at_exit handlers" do + out = ruby_exe("at_exit { STDERR.puts 'at_exit' }; #{@object}.send(:exit!, 21)", args: '2>&1', exit_status: 21) + out.should == "" + $?.exitstatus.should == 21 + end + + it "overrides the original exception and exit status when called from #at_exit" do + code = <<-RUBY + at_exit do + STDERR.puts 'in at_exit' + STDERR.puts "$! is \#{$!.class}:\#{$!.message}" + #{@object}.send(:exit!, 21) + end + raise 'original error' + RUBY + out = ruby_exe(code, args: '2>&1', exit_status: 21) + out.should == "in at_exit\n$! is RuntimeError:original error\n" + $?.exitstatus.should == 21 + end end diff --git a/ruby/spec/ruby/shared/rational/Rational.rb b/ruby/spec/ruby/shared/rational/Rational.rb index 2c36243dc..936a90c08 100644 --- a/ruby/spec/ruby/shared/rational/Rational.rb +++ b/ruby/spec/ruby/shared/rational/Rational.rb @@ -101,42 +101,40 @@ end end - ruby_version_is "2.6" do - describe "when passed exception: false" do - describe "and [non-Numeric]" do - it "swallows an error" do - Rational(:sym, exception: false).should == nil - Rational("abc", exception: false).should == nil - end + describe "when passed exception: false" do + describe "and [non-Numeric]" do + it "swallows an error" do + Rational(:sym, exception: false).should == nil + Rational("abc", exception: false).should == nil end + end - describe "and [non-Numeric, Numeric]" do - it "swallows an error" do - Rational(:sym, 1, exception: false).should == nil - Rational("abc", 1, exception: false).should == nil - end + describe "and [non-Numeric, Numeric]" do + it "swallows an error" do + Rational(:sym, 1, exception: false).should == nil + Rational("abc", 1, exception: false).should == nil end + end - describe "and [anything, non-Numeric]" do - it "swallows an error" do - Rational(:sym, :sym, exception: false).should == nil - Rational("abc", :sym, exception: false).should == nil - end + describe "and [anything, non-Numeric]" do + it "swallows an error" do + Rational(:sym, :sym, exception: false).should == nil + Rational("abc", :sym, exception: false).should == nil end + end - describe "and non-Numeric String arguments" do - it "swallows an error" do - Rational("a", "b", exception: false).should == nil - Rational("a", 0, exception: false).should == nil - Rational(0, "b", exception: false).should == nil - end + describe "and non-Numeric String arguments" do + it "swallows an error" do + Rational("a", "b", exception: false).should == nil + Rational("a", 0, exception: false).should == nil + Rational(0, "b", exception: false).should == nil end + end - describe "and nil arguments" do - it "swallows an error" do - Rational(nil, exception: false).should == nil - Rational(nil, nil, exception: false).should == nil - end + describe "and nil arguments" do + it "swallows an error" do + Rational(nil, exception: false).should == nil + Rational(nil, nil, exception: false).should == nil end end end diff --git a/ruby/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb b/ruby/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb index 937781473..0dff91d52 100644 --- a/ruby/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb +++ b/ruby/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb @@ -1,33 +1,11 @@ require_relative '../../fixtures/rational' describe :rational_arithmetic_exception_in_coerce, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) + it "does not rescue exception raised in other#coerce" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) - # e.g. Rational(3, 4) + b - -> { Rational(3, 4).send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Rational/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. Rational(3, 4) + b - -> { Rational(3, 4).send(@method, b) }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) - - # e.g. Rational(3, 4) + b - -> { Rational(3, 4).send(@method, b) }.should raise_error(RationalSpecs::CoerceError) - end + # e.g. Rational(3, 4) + b + -> { Rational(3, 4).send(@method, b) }.should raise_error(RationalSpecs::CoerceError) end end diff --git a/ruby/spec/ruby/shared/rational/coerce.rb b/ruby/spec/ruby/shared/rational/coerce.rb index ffb118e2a..ccc8901ba 100644 --- a/ruby/spec/ruby/shared/rational/coerce.rb +++ b/ruby/spec/ruby/shared/rational/coerce.rb @@ -17,6 +17,11 @@ result.last.is_a?(Rational).should be_true end + it "coerces to Rational, when given a Complex" do + Rational(3, 4).coerce(Complex(5)).should == [Rational(5, 1), Rational(3, 4)] + Rational(12, 4).coerce(Complex(5, 1)).should == [Complex(5, 1), Complex(3)] + end + it "returns [argument, self] when given a Rational" do Rational(3, 7).coerce(Rational(9, 2)).should == [Rational(9, 2), Rational(3, 7)] end diff --git a/ruby/spec/ruby/shared/rational/comparison.rb b/ruby/spec/ruby/shared/rational/comparison.rb index 0c8b3d0ac..860462f57 100644 --- a/ruby/spec/ruby/shared/rational/comparison.rb +++ b/ruby/spec/ruby/shared/rational/comparison.rb @@ -80,33 +80,11 @@ end describe :rational_cmp_coerce_exception, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and returns nil" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) - - -> { - (Rational(3, 4) <=> b).should == nil - }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - -> { Rational(3, 4) <=> b }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) + it "does not rescue exception raised in other#coerce" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) - -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError) - end + -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError) end end diff --git a/ruby/spec/ruby/shared/rational/divmod.rb b/ruby/spec/ruby/shared/rational/divmod.rb index 5b319a95f..471cd7a96 100644 --- a/ruby/spec/ruby/shared/rational/divmod.rb +++ b/ruby/spec/ruby/shared/rational/divmod.rb @@ -9,7 +9,7 @@ Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([1729382256910270464, Rational(0, 1)]) end - it "raises a ZeroDivisonError when passed a Rational with a numerator of 0" do + it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do -> { Rational(7, 4).divmod(Rational(0, 3)) }.should raise_error(ZeroDivisionError) end end diff --git a/ruby/spec/ruby/shared/rational/exponent.rb b/ruby/spec/ruby/shared/rational/exponent.rb index 1d808177e..3fd02de08 100644 --- a/ruby/spec/ruby/shared/rational/exponent.rb +++ b/ruby/spec/ruby/shared/rational/exponent.rb @@ -85,26 +85,44 @@ end it "returns positive Infinity when self is > 1" do - (Rational(2) ** bignum_value).infinite?.should == 1 - (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 + -> { + (Rational(2) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) end it "returns 0.0 when self is > 1 and the exponent is negative" do - (Rational(2) ** -bignum_value).should eql(0.0) - (Rational(fixnum_max) ** -bignum_value).should eql(0.0) + -> { + (Rational(2) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_max) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) end # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866 platform_is_not :linux do it "returns positive Infinity when self < -1" do - (Rational(-2) ** bignum_value).infinite?.should == 1 - (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 - (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 + -> { + (Rational(-2) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) end it "returns 0.0 when self is < -1 and the exponent is negative" do - (Rational(-2) ** -bignum_value).should eql(0.0) - (Rational(fixnum_min) ** -bignum_value).should eql(0.0) + -> { + (Rational(-2) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) end end end diff --git a/ruby/spec/ruby/shared/string/end_with.rb b/ruby/spec/ruby/shared/string/end_with.rb new file mode 100644 index 000000000..5f2a01123 --- /dev/null +++ b/ruby/spec/ruby/shared/string/end_with.rb @@ -0,0 +1,54 @@ +describe :end_with, shared: true do + # the @method should either be :to_s or :to_sym + + it "returns true only if ends match" do + s = "hello".send(@method) + s.should.end_with?('o') + s.should.end_with?('llo') + end + + it 'returns false if the end does not match' do + s = 'hello'.send(@method) + s.should_not.end_with?('ll') + end + + it "returns true if the search string is empty" do + "hello".send(@method).should.end_with?("") + "".send(@method).should.end_with?("") + end + + it "returns true only if any ending match" do + "hello".send(@method).should.end_with?('x', 'y', 'llo', 'z') + end + + it "converts its argument using :to_str" do + s = "hello".send(@method) + find = mock('o') + find.should_receive(:to_str).and_return("o") + s.should.end_with?(find) + end + + it "ignores arguments not convertible to string" do + "hello".send(@method).should_not.end_with?() + -> { "hello".send(@method).end_with?(1) }.should raise_error(TypeError) + -> { "hello".send(@method).end_with?(["o"]) }.should raise_error(TypeError) + -> { "hello".send(@method).end_with?(1, nil, "o") }.should raise_error(TypeError) + end + + it "uses only the needed arguments" do + find = mock('h') + find.should_not_receive(:to_str) + "hello".send(@method).should.end_with?("o",find) + end + + it "works for multibyte strings" do + "céréale".send(@method).should.end_with?("réale") + end + + it "raises an Encoding::CompatibilityError if the encodings are incompatible" do + pat = "ã‚¢".encode Encoding::EUC_JP + -> do + "ã‚れ".send(@method).end_with?(pat) + end.should raise_error(Encoding::CompatibilityError) + end +end diff --git a/ruby/spec/ruby/shared/string/start_with.rb b/ruby/spec/ruby/shared/string/start_with.rb new file mode 100644 index 000000000..d8d6e13f6 --- /dev/null +++ b/ruby/spec/ruby/shared/string/start_with.rb @@ -0,0 +1,72 @@ +describe :start_with, shared: true do + # the @method should either be :to_s or :to_sym + + it "returns true only if beginning match" do + s = "hello".send(@method) + s.should.start_with?('h') + s.should.start_with?('hel') + s.should_not.start_with?('el') + end + + it "returns true only if any beginning match" do + "hello".send(@method).should.start_with?('x', 'y', 'he', 'z') + end + + it "returns true if the search string is empty" do + "hello".send(@method).should.start_with?("") + "".send(@method).should.start_with?("") + end + + it "converts its argument using :to_str" do + s = "hello".send(@method) + find = mock('h') + find.should_receive(:to_str).and_return("h") + s.should.start_with?(find) + end + + it "ignores arguments not convertible to string" do + "hello".send(@method).should_not.start_with?() + -> { "hello".send(@method).start_with?(1) }.should raise_error(TypeError) + -> { "hello".send(@method).start_with?(["h"]) }.should raise_error(TypeError) + -> { "hello".send(@method).start_with?(1, nil, "h") }.should raise_error(TypeError) + end + + it "uses only the needed arguments" do + find = mock('h') + find.should_not_receive(:to_str) + "hello".send(@method).should.start_with?("h",find) + end + + it "works for multibyte strings" do + "céréale".send(@method).should.start_with?("cér") + end + + it "supports regexps" do + regexp = /[h1]/ + "hello".send(@method).should.start_with?(regexp) + "1337".send(@method).should.start_with?(regexp) + "foxes are 1337".send(@method).should_not.start_with?(regexp) + "chunky\n12bacon".send(@method).should_not.start_with?(/12/) + end + + it "supports regexps with ^ and $ modifiers" do + regexp1 = /^\d{2}/ + regexp2 = /\d{2}$/ + "12test".send(@method).should.start_with?(regexp1) + "test12".send(@method).should_not.start_with?(regexp1) + "12test".send(@method).should_not.start_with?(regexp2) + "test12".send(@method).should_not.start_with?(regexp2) + end + + it "sets Regexp.last_match if it returns true" do + regexp = /test-(\d+)/ + "test-1337".send(@method).start_with?(regexp).should be_true + Regexp.last_match.should_not be_nil + Regexp.last_match[1].should == "1337" + $1.should == "1337" + + "test-asdf".send(@method).start_with?(regexp).should be_false + Regexp.last_match.should be_nil + $1.should be_nil + end +end diff --git a/ruby/spec/ruby/shared/string/times.rb b/ruby/spec/ruby/shared/string/times.rb index 6b45f7aa1..cd4edf534 100644 --- a/ruby/spec/ruby/shared/string/times.rb +++ b/ruby/spec/ruby/shared/string/times.rb @@ -20,16 +20,32 @@ class MyString < String; end it "raises an ArgumentError when given integer is negative" do -> { @object.call("cool", -3) }.should raise_error(ArgumentError) -> { @object.call("cool", -3.14) }.should raise_error(ArgumentError) + -> { @object.call("cool", min_long) }.should raise_error(ArgumentError) end it "raises a RangeError when given integer is a Bignum" do -> { @object.call("cool", 999999999999999999999) }.should raise_error(RangeError) + -> { @object.call("", 999999999999999999999) }.should raise_error(RangeError) end - it "returns subclass instances" do - @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString) - @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString) - @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString) + it "works with huge long values when string is empty" do + @object.call("", max_long).should == "" + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString) + @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString) + @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + @object.call(MyString.new("cool"), 0).should be_an_instance_of(String) + @object.call(MyString.new("cool"), 1).should be_an_instance_of(String) + @object.call(MyString.new("cool"), 2).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do @@ -38,7 +54,7 @@ class MyString < String; end str.taint [0, 1, 2].each do |arg| - @object.call(str, arg).tainted?.should == true + @object.call(str, arg).should.tainted? end end end diff --git a/ruby/spec/ruby/shared/time/strftime_for_time.rb b/ruby/spec/ruby/shared/time/strftime_for_time.rb index 49cd09051..9f4d08d72 100644 --- a/ruby/spec/ruby/shared/time/strftime_for_time.rb +++ b/ruby/spec/ruby/shared/time/strftime_for_time.rb @@ -170,4 +170,12 @@ time.strftime("%-k%p").should == "8AM" time.strftime("%-l%p").should == "8AM" end + + it "should be able to show default Logger format" do + default_logger_format = "%Y-%m-%dT%H:%M:%S.%6N " + @new_time[2001, 2, 3, 4, 5, 6].strftime(default_logger_format).should == "2001-02-03T04:05:06.000000 " + @new_time[2001, 12, 3, 4, 5, 6 + 1/10r].strftime(default_logger_format).should == "2001-12-03T04:05:06.100000 " + @new_time[2001, 2, 13, 4, 5, 6 + 1/100r].strftime(default_logger_format).should == "2001-02-13T04:05:06.010000 " + @new_time[2001, 2, 3, 14, 5, 6 + 1/1000r].strftime(default_logger_format).should == "2001-02-03T14:05:06.001000 " + end end diff --git a/ruby/sprintf.c b/ruby/sprintf.c index 23eb39a73..f4aa7f6d1 100644 --- a/ruby/sprintf.c +++ b/ruby/sprintf.c @@ -11,17 +11,27 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/re.h" -#include "internal.h" -#include "id.h" +#include "ruby/internal/config.h" + #include #include #ifdef HAVE_IEEEFP_H -#include +# include #endif +#include "id.h" +#include "internal.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/sanitizers.h" +#include "internal/symbol.h" +#include "ruby/encoding.h" +#include "ruby/re.h" +#include "ruby/util.h" + #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ static char *fmt_setup(char*,size_t,int,int,int,int); @@ -247,7 +257,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) blen = 0; bsiz = 120; result = rb_str_buf_new(bsiz); - rb_enc_copy(result, fmt); + rb_enc_associate(result, enc); buf = RSTRING_PTR(result); memset(buf, 0, bsiz); ENC_CODERANGE_SET(result, coderange); @@ -865,7 +875,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) double fval; fval = RFLOAT_VALUE(rb_Float(val)); - if (isnan(fval) || isinf(fval)) { + if (!isfinite(fval)) { const char *expr; int need; int elen; @@ -964,14 +974,12 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) #undef ferror #undef clearerr #undef fileno -#if SIZEOF_LONG < SIZEOF_VOIDP -# if SIZEOF_LONG_LONG == SIZEOF_VOIDP -# define _HAVE_SANE_QUAD_ -# define _HAVE_LLP64_ -# define quad_t LONG_LONG -# define u_quad_t unsigned LONG_LONG +#if SIZEOF_LONG < SIZEOF_LONG_LONG +# if SIZEOF_LONG_LONG == SIZEOF_VOIDP +/* actually this doesn't mean a pointer is strictly 64bit, but just + * quad_t size */ +# define _HAVE_LLP64_ # endif -#elif SIZEOF_LONG != SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == 8 # define _HAVE_SANE_QUAD_ # define quad_t LONG_LONG # define u_quad_t unsigned LONG_LONG @@ -984,10 +992,6 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) #endif #define lower_hexdigits (ruby_hexdigits+0) #define upper_hexdigits (ruby_hexdigits+16) -#if defined RUBY_USE_SETJMPEX && RUBY_USE_SETJMPEX -# undef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x = 0 -#endif #include "vsnprintf.c" static char * @@ -1117,7 +1121,7 @@ ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int s else if (SYMBOL_P(value)) { value = rb_sym2str(value); if (sign == ' ' && !rb_str_symname_p(value)) { - value = rb_str_inspect(value); + value = rb_str_escape(value); } } else { diff --git a/ruby/squash.h b/ruby/squash.h deleted file mode 100644 index 571388957..000000000 --- a/ruby/squash.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) 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. - * - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef SQFS_SQUASH_H -#define SQFS_SQUASH_H - -#include -#include -#include - -#include "squash/dir.h" -#include "squash/file.h" -#include "squash/fs.h" -#include "squash/traverse.h" -#include "squash/util.h" -#include "squash/private.h" -#include "squash/fdtable.h" -#include "squash/dirent.h" - -#define SQUASH_SEEK_SET 0 /* set file offset to offset */ -#define SQUASH_SEEK_CUR 1 /* set file offset to current plus offset */ -#define SQUASH_SEEK_END 2 /* set file offset to EOF plus offset */ - -#define SQUASH_VALID_VFD(vfd) ((vfd) < squash_global_fdtable.nr && NULL != squash_global_fdtable.fds[(vfd)]) -#define SQUASH_VFD_FILE(vfd) (squash_global_fdtable.fds[(vfd)]) - -extern sqfs_err squash_errno; - -sqfs_err squash_start(); -ssize_t squash_readlink_inode(sqfs *fs, sqfs_inode *node, char *buf, size_t bufsize); -sqfs_err squash_follow_link(sqfs *fs, const char *path, sqfs_inode *node); -struct squash_file * squash_find_entry(void *ptr); - -/* - * Obtains information about the file pointed to by path of a SquashFS fs. - * The buf argument is a pointer to a stat structure as defined by - * and into which information is placed concerning the file. - * Upon successful completion a value of 0 is returned. - * Otherwise, a value of -1 is returned and - * error is set to the reason of the error. - */ -int squash_stat(sqfs *fs, const char *path, struct stat *buf); - -/* - * Acts like squash_stat() except in the case where the named file - * is a symbolic link; squash_lstat() returns information about the link, - * while squash_stat() returns information about the file the link references. - */ -int squash_lstat(sqfs *fs, const char *path, struct stat *buf); - -/* - * Obtains the same information as squash_stat() - * about an open file known by the virtual file descriptor vfd. - */ -int squash_fstat(int vfd, struct stat *buf); - -/* - * Opens the file name specified by path of fs for reading. - * If successful, squash_open() returns a non-negative integer, - * termed a vfd(virtual file descriptor). - * It returns -1 on failure and sets error to the reason of the error. - * The file pointer (used to mark the current position within the file) - * is set to the beginning of the file. - * The returned vfd should later be closed by squash_close(). - */ -int squash_open(sqfs *fs, const char *path); - -int squash_open_inner(sqfs *fs, const char *path, short follow_link); - -/* - * Deletes a vfd(virtual file descriptor) from - * the per-process object reference table. - * Upon successful completion, a value of 0 is returned. - * Otherwise, a value of -1 is returned and error is set to - * the reason of the error. - */ -int squash_close(int vfd); - -/* - * Attempts to read nbyte bytes of data from the object - * referenced by vfs into the buffer pointed to by buf, - * starting at a position given by the pointer - * associated with vfd (see squash_lseek), - * which is then incremented by the number of bytes actually read upon return. - * When successful it returns the number of bytes actually read - * and placed in the buffer; - * upon reading end-of-file, zero is returned; - * Otherwise, a value of -1 is returned and error is set to - * the reason of the error. - */ -ssize_t squash_read(int vfd, void *buf, sqfs_off_t nbyte); - -/* - * Repositions the offset of vfs to the argument offset, - * according to the directive whence. - * If whence is SQUASH_SEEK_SET then the offset is set to offset bytes; - * if whence is SQUASH_SEEK_CUR, the offset is set to - * its current location plus offset bytes; - * if whence is SQUASH_SEEK_END, the offset is set to - * the size of the file and - * subsequent reads of the data return bytes of zeros. - * The argument fildes` must be an open virtual file descriptor. - * Upon successful completion, - * it returns the resulting offset location as measured in bytes - * from the beginning of the file. - * Otherwise, a value of -1 is returned and - * error is set to the reason of the error. - */ -off_t squash_lseek(int vfd, off_t offset, int whence); - -/* - * Places the contents of the symbolic link path of a SquashFS fs - * in the buffer buf, which has size bufsize. - * It does not append a NUL character to buf. - * If it succeeds the call returns the count of characters placed in the buffer; - * otherwise -1 is returned and error is set to the reason of the error. - */ -ssize_t squash_readlink(sqfs *fs, const char *path, char *buf, size_t bufsize); - -/* - * Opens the directory named by filename of a SquashFS fs, - * associates a directory stream with it and returns a pointer - * to be used to identify the directory stream in subsequent operations. - * The pointer NULL is returned if filename cannot be accessed, - * or if it cannot allocate enough memory to hold the whole thing, - * and sets error to the reason of the error. - * The returned resource should later be closed by squash_closedir(). - */ -SQUASH_DIR * squash_opendir(sqfs *fs, const char *filename); - -SQUASH_DIR * squash_opendir_inner(sqfs *fs, const char *filename, short follow_link); - -/* - * Closes the named directory stream and - * frees the structure associated with the dirp pointer, - * returning 0 on success. - * On failure, -1 is returned and error is set to the reason of the error. - */ -int squash_closedir(SQUASH_DIR *dirp); - -/* - * Returns a pointer to the next directory entry. - * It returns NULL upon reaching the end of the directory or on error. - * In the event of an error, error is set to the reason of the error. - */ -struct SQUASH_DIRENT * squash_readdir(SQUASH_DIR *dirp); - -/* - * Returns the current location associated with the named directory stream. - */ -long squash_telldir(SQUASH_DIR *dirp); - -/* - * Sets the position of the next squash_readdir() operation - * on the directory stream. - * The new position reverts to the one associated with the directory stream - * when the squash_telldir() operation was performed. - */ -void squash_seekdir(SQUASH_DIR *dirp, long loc); - -/* - * Resets the position of the named directory stream to - * the beginning of the directory. - */ -void squash_rewinddir(SQUASH_DIR *dirp); - -/* - * Returns the integer virtual file descriptor - * associated with the named directory stream. - * On failure, -1 is returned and error is set to the reason of the error. - */ -int squash_dirfd(SQUASH_DIR *dirp); - -/* - * Reads the directory dirname of a SquashFS fs and - * builds an array of pointers to directory entries using malloc. - * If successful it returns the number of entries in the array; - * otherwise -1 is returned and error is set to the reason of the error. - * A pointer to the array of directory entries is stored - * in the location referenced by namelist (even if the number of entries is 0), - * which should later be freed via free() by freeing each pointer - * in the array and then the array itself. - * The select argument is a pointer to a user supplied subroutine which is - * called by scandir to select which entries are to be included in the array. - * The select routine is passed a pointer to a directory entry - * and should return a non-zero value if the directory entry - * is to be included in the array. - * If select is NULL, then all the directory entries will be included. - * The compar argument is a pointer to a user supplied subroutine - * which is passed to qsort to sort the completed array. - * If this pointer is NULL, then the array is not sorted. - */ -int squash_scandir(sqfs *fs, const char *dirname, struct SQUASH_DIRENT ***namelist, - int (*select)(const struct SQUASH_DIRENT *), - int (*compar)(const struct SQUASH_DIRENT **, const struct SQUASH_DIRENT **)); - -/* - * Extracts the file `path` from `fs` to a temporary file - * inside the temporary folder. - * Upon successful completion the path of the extracted temporary file - * is returned. - * Otherwise, a value of `NULL` is returned - * and `errno` is set to the reason of the error. - * The returned path is referenced by an internal cache and must not be freed. - */ -#ifdef _WIN32 -#define SQUASH_OS_PATH const wchar_t* -#else -#define SQUASH_OS_PATH const char* -#endif -SQUASH_OS_PATH squash_tmpdir(); -SQUASH_OS_PATH squash_tmpf(SQUASH_OS_PATH tmpdir, const char *ext_name); -SQUASH_OS_PATH squash_extract(sqfs *fs, const char *path, const char *ext_name); -void squash_extract_clear_cache(); - -#endif diff --git a/ruby/squash/cache.h b/ruby/squash/cache.h deleted file mode 100644 index e60a5924f..000000000 --- a/ruby/squash/cache.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_CACHE_H -#define SQFS_CACHE_H - -#include "squash/common.h" - -/* Really simplistic cache - * - Linear search - * - Linear eviction - * - No thread safety - * - Misses are caller's responsibility - */ -#define SQFS_CACHE_IDX_INVALID 0 - -typedef uint64_t sqfs_cache_idx; -typedef void (*sqfs_cache_dispose)(void* data); - -typedef struct { - sqfs_cache_idx *idxs; - uint8_t *buf; - - sqfs_cache_dispose dispose; - - size_t size, count; - size_t next; /* next block to evict */ - - MUTEX mutex; -} sqfs_cache; - -sqfs_err sqfs_cache_init(sqfs_cache *cache, size_t size, size_t count, - sqfs_cache_dispose dispose); -void sqfs_cache_destroy(sqfs_cache *cache); - -void *sqfs_cache_get(sqfs_cache *cache, sqfs_cache_idx idx); -void *sqfs_cache_add(sqfs_cache *cache, sqfs_cache_idx idx); - - -typedef struct { - sqfs_block *block; - size_t data_size; -} sqfs_block_cache_entry; - -sqfs_err sqfs_block_cache_init(sqfs_cache *cache, size_t count); - -#endif diff --git a/ruby/squash/common.h b/ruby/squash/common.h deleted file mode 100644 index 91154e812..000000000 --- a/ruby/squash/common.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_COMMON_H -#define SQFS_COMMON_H - -#include -#include -#include -#include "squash/mutex.h" - -#ifdef _WIN32 - #include "squash/windows.h" - struct squash_windows_dirent - { - long d_namlen; - ino_t d_ino; - char d_name[256 + 1]; // i.e. SQUASHFS_NAME_LEN + 1 - uint8_t d_type; - }; - #define SQUASH_DIRENT squash_windows_dirent -#else - #include - #include - typedef mode_t sqfs_mode_t; - typedef uid_t sqfs_id_t; - typedef off_t sqfs_off_t; - #define SQUASH_DIRENT dirent -#endif -typedef const uint8_t * sqfs_fd_t; - -typedef enum { - SQFS_OK, - SQFS_ERR, - SQFS_BADFORMAT, /* unsupported file format */ - SQFS_BADVERSION, /* unsupported squashfs version */ - SQFS_BADCOMP, /* unsupported compression method */ - SQFS_UNSUP /* unsupported feature */ -} sqfs_err; - -#define SQFS_INODE_ID_BYTES 6 -typedef uint64_t sqfs_inode_id; -typedef uint32_t sqfs_inode_num; - -typedef struct sqfs sqfs; -typedef struct sqfs_inode sqfs_inode; - -typedef struct { - size_t size; - void *data; - short data_need_freeing; -} sqfs_block; - -typedef struct { - sqfs_off_t block; - size_t offset; -} sqfs_md_cursor; - -#endif diff --git a/ruby/squash/decompress.h b/ruby/squash/decompress.h deleted file mode 100644 index 1d951bca5..000000000 --- a/ruby/squash/decompress.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_DECOMPRESS_H -#define SQFS_DECOMPRESS_H - -#include "squash/common.h" - -#define SQFS_COMP_UNKNOWN 0 -#define SQFS_COMP_MAX 16 - -typedef int sqfs_compression_type; - -char *sqfs_compression_name(sqfs_compression_type type); - -typedef sqfs_err (*sqfs_decompressor)(void *in, size_t insz, - void *out, size_t *outsz); - -sqfs_decompressor sqfs_decompressor_get(sqfs_compression_type type); - -#endif diff --git a/ruby/squash/dir.h b/ruby/squash/dir.h deleted file mode 100644 index d3bf71a90..000000000 --- a/ruby/squash/dir.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_DIR_H -#define SQFS_DIR_H - -#include "squash/common.h" - -#include "squash/squashfs_fs.h" - -typedef struct { - sqfs_md_cursor cur; - sqfs_off_t offset, total; - struct squashfs_dir_header header; -} sqfs_dir; - -typedef struct { - sqfs_inode_id inode; - sqfs_inode_num inode_number; - int type; - char *name; - size_t name_size; - sqfs_off_t offset, next_offset; -} sqfs_dir_entry; - -typedef char sqfs_name[SQUASHFS_NAME_LEN + 1]; - -typedef char sqfs_path[SQUASHFS_PATH_LEN + 1]; - -/* Begin a directory traversal, initializing the dir structure. - If offset is non-zero, fast-forward to that offset in the directory. */ -sqfs_err sqfs_dir_open(sqfs *fs, sqfs_inode *inode, sqfs_dir *dir, - off_t offset); - -/* Initialize a dir_entry structure before use. - 'namebuf' should be a character buffer of enough size to hold any name, - see sqfs_name. It may also be NULL, in which case no names will be placed - into this dir_entry. */ -void sqfs_dentry_init(sqfs_dir_entry *entry, char *namebuf); - -/* Get the next directory entry, filling in the dir_entry. - Returns 0 when out of entries, or on error. */ -short sqfs_dir_next(sqfs *fs, sqfs_dir *dir, sqfs_dir_entry *entry, - sqfs_err *err); - -/* Lookup an entry in a directory inode. - The dir_entry must have been initialized with a buffer. */ -sqfs_err sqfs_dir_lookup(sqfs *fs, sqfs_inode *inode, - const char *name, size_t namelen, sqfs_dir_entry *entry, short *found); - -/* Lookup a complete path, and replace *inode with the results. - Uses / (slash) as the directory separator. */ -sqfs_err sqfs_lookup_path_inner(sqfs *fs, sqfs_inode *inode, const char *path, - short *found, short follow_link); -sqfs_err sqfs_lookup_path(sqfs *fs, sqfs_inode *inode, const char *path, - short *found); - - -/* Accessors on sqfs_dir_entry */ -sqfs_off_t sqfs_dentry_offset (sqfs_dir_entry *entry); -sqfs_off_t sqfs_dentry_next_offset (sqfs_dir_entry *entry); -int sqfs_dentry_type (sqfs_dir_entry *entry); -sqfs_mode_t sqfs_dentry_mode (sqfs_dir_entry *entry); -sqfs_inode_id sqfs_dentry_inode (sqfs_dir_entry *entry); -sqfs_inode_num sqfs_dentry_inode_num (sqfs_dir_entry *entry); -size_t sqfs_dentry_name_size (sqfs_dir_entry *entry); -short sqfs_dentry_is_dir (sqfs_dir_entry *entry); - -/* Yields the name of this directory entry, or NULL if the dir_entry structure - was initialized without a name buffer. Name will be nul-terminated. */ -const char * sqfs_dentry_name (sqfs_dir_entry *entry); - -#endif diff --git a/ruby/squash/dirent.h b/ruby/squash/dirent.h deleted file mode 100644 index dab4a9e0d..000000000 --- a/ruby/squash/dirent.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef DIRENT_H_245C4278 -#define DIRENT_H_245C4278 - -#include - -#define SQUASH_DIR_MAGIC_LEN 18 -#define MAX_DIR_ENT 1024 - -typedef struct { - sqfs *fs; - int fd; /* virtual file descriptor associated with directory */ - sqfs_inode node; - sqfs_dir dir; - // CAUTION: this is a big struct, mind the SQUASHFS_NAME_LEN size - struct { - sqfs_dir_entry entry; - struct SQUASH_DIRENT sysentry; - sqfs_name name; - short not_eof; - } *entries; - size_t nr; /* allocated size for entries */ - int actual_nr; /* actual number of entries read */ - long loc; /* offset in current buffer */ - char *filename; - void *payload; -} SQUASH_DIR; - -#endif /* end of include guard: DIRENT_H_245C4278 */ diff --git a/ruby/squash/fdtable.h b/ruby/squash/fdtable.h deleted file mode 100644 index 8a0ce14e3..000000000 --- a/ruby/squash/fdtable.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef FDTABLE_H_60F13289 -#define FDTABLE_H_60F13289 - -#include "squash/common.h" - -struct squash_file { - int fd; - sqfs *fs; - sqfs_inode node; - struct stat st; - uint64_t pos; - char *filename; - void *payload; -}; - -struct squash_fdtable { - size_t nr; - struct squash_file **fds; - size_t end; -}; - -extern struct squash_fdtable squash_global_fdtable; - -#endif /* end of include guard: FDTABLE_H_60F13289 */ diff --git a/ruby/squash/file.h b/ruby/squash/file.h deleted file mode 100644 index eafd8ed46..000000000 --- a/ruby/squash/file.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_FILE_H -#define SQFS_FILE_H - -#include "squash/common.h" - -#include "squash/squashfs_fs.h" - -#include "squash/cache.h" - -sqfs_err sqfs_frag_entry(sqfs *fs, struct squashfs_fragment_entry *frag, - uint32_t idx); - -sqfs_err sqfs_frag_block(sqfs *fs, sqfs_inode *inode, - size_t *offset, size_t *size, sqfs_block **block); - -typedef uint32_t sqfs_blocklist_entry; -typedef struct { - sqfs *fs; - size_t remain; /* How many blocks left in the file? */ - sqfs_md_cursor cur; /* Points to next blocksize in MD */ - short started; - - uint64_t pos; - - uint64_t block; /* Points to next data block location */ - sqfs_blocklist_entry header; /* Packed blocksize data */ - uint32_t input_size; /* Extracted size of this block */ -} sqfs_blocklist; - -size_t sqfs_blocklist_count(sqfs *fs, sqfs_inode *inode); - -void sqfs_blocklist_init(sqfs *fs, sqfs_inode *inode, sqfs_blocklist *bl); -sqfs_err sqfs_blocklist_next(sqfs_blocklist *bl); - - -sqfs_err sqfs_read_range(sqfs *fs, sqfs_inode *inode, sqfs_off_t start, - sqfs_off_t *size, void *buf); - - -/*** Block index for skipping to the middle of large files ***/ - -typedef struct { - uint64_t data_block; /* A data block where the file continues */ - uint32_t md_block; /* A metadata block with blocksizes that continue from - data_block */ -} sqfs_blockidx_entry; - -sqfs_err sqfs_blockidx_init(sqfs_cache *cache); - -/* Get a blocklist fast-forwarded to the correct location */ -sqfs_err sqfs_blockidx_blocklist(sqfs *fs, sqfs_inode *inode, - sqfs_blocklist *bl, sqfs_off_t start); - -#endif diff --git a/ruby/squash/fs.h b/ruby/squash/fs.h deleted file mode 100644 index 9c3c6998b..000000000 --- a/ruby/squash/fs.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_FS_H -#define SQFS_FS_H - -#include "squash/common.h" - -#include "squash/squashfs_fs.h" - -#include "squash/cache.h" -#include "squash/decompress.h" -#include "squash/table.h" - -struct sqfs { - sqfs_fd_t fd; - size_t offset; - struct squashfs_super_block *sb; - sqfs_table id_table; - sqfs_table frag_table; - sqfs_table export_table; - sqfs_cache md_cache; - sqfs_cache data_cache; - sqfs_cache frag_cache; - sqfs_cache blockidx; - sqfs_decompressor decompressor; - const char *root_alias; - const char *root_alias2; -}; - -struct sqfs_inode { - struct squashfs_base_inode base; - int nlink; - - sqfs_md_cursor next; - - union { - struct { - int major, minor; - } dev; - size_t symlink_size; - struct { - uint64_t start_block; - uint64_t file_size; - uint32_t frag_idx; - uint32_t frag_off; - } reg; - struct { - uint32_t start_block; - uint16_t offset; - uint32_t dir_size; - uint16_t idx_count; - uint32_t parent_inode; - } dir; - } xtra; -}; - -void sqfs_version_supported(int *min_major, int *min_minor, int *max_major, - int *max_minor); - -/* Number of groups of size 'group' required to hold size 'total' */ -size_t sqfs_divceil(uint64_t total, size_t group); - - -sqfs_err sqfs_init(sqfs *fs, sqfs_fd_t fd, size_t offset); -void sqfs_destroy(sqfs *fs); - -/* Ok to call these even on incompletely constructed filesystems */ -void sqfs_version(sqfs *fs, int *major, int *minor); -sqfs_compression_type sqfs_compression(sqfs *fs); - - -void sqfs_md_header(uint16_t hdr, short *compressed, uint16_t *size); -void sqfs_data_header(uint32_t hdr, short *compressed, uint32_t *size); - -sqfs_err sqfs_block_read(sqfs *fs, sqfs_off_t pos, short compressed, uint32_t size, - size_t outsize, sqfs_block **block); -void sqfs_block_dispose(sqfs_block *block); - -sqfs_err sqfs_md_block_read(sqfs *fs, sqfs_off_t pos, size_t *data_size, - sqfs_block **block); -sqfs_err sqfs_data_block_read(sqfs *fs, sqfs_off_t pos, uint32_t hdr, - sqfs_block **block); - -/* Don't dispose after getting block, it's in the cache */ -sqfs_err sqfs_md_cache(sqfs *fs, sqfs_off_t *pos, sqfs_block **block); -sqfs_err sqfs_data_cache(sqfs *fs, sqfs_cache *cache, sqfs_off_t pos, - uint32_t hdr, sqfs_block **block); - -void sqfs_md_cursor_inode(sqfs_md_cursor *cur, sqfs_inode_id id, sqfs_off_t base); - -sqfs_err sqfs_md_read(sqfs *fs, sqfs_md_cursor *cur, void *buf, size_t size); - - -sqfs_err sqfs_inode_get(sqfs *fs, sqfs_inode *inode, sqfs_inode_id id); - -sqfs_mode_t sqfs_mode(int inode_type); -sqfs_err sqfs_id_get(sqfs *fs, uint16_t idx, sqfs_id_t *id); - -/* Puts up to *size characters of the link name into buf. Always null- - * terminates the buffer. Pass null as buf to have the size returned. */ -sqfs_err sqfs_readlink(sqfs *fs, sqfs_inode *inode, char *buf, size_t *size); - -/* Find inode_id by inode_num */ -int sqfs_export_ok(sqfs *fs); -sqfs_err sqfs_export_inode(sqfs *fs, sqfs_inode_num n, sqfs_inode_id *i); - -/* Find the root inode */ -sqfs_inode_id sqfs_inode_root(sqfs *fs); - -#endif diff --git a/ruby/squash/hash.h b/ruby/squash/hash.h deleted file mode 100644 index c0eaed0a4..000000000 --- a/ruby/squash/hash.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_HASH_H -#define SQFS_HASH_H - -#include "squash/common.h" - -/* Simple hashtable - * - Keys are integers - * - Values are opaque data - * - * Implementation - * - Hash function is modulus - * - Chaining for duplicates - * - Sizes are powers of two - */ -typedef uint32_t sqfs_hash_key; -typedef void *sqfs_hash_value; - -typedef struct sqfs_hash_bucket { - struct sqfs_hash_bucket *next; - sqfs_hash_key key; - char value[1]; /* extended to size */ -} sqfs_hash_bucket; - -typedef struct { - size_t value_size; - size_t capacity; - size_t size; - sqfs_hash_bucket **buckets; -} sqfs_hash; - -sqfs_err sqfs_hash_init(sqfs_hash *h, size_t vsize, size_t initial); -void sqfs_hash_destroy(sqfs_hash *h); - -sqfs_hash_value sqfs_hash_get(sqfs_hash *h, sqfs_hash_key k); - -sqfs_err sqfs_hash_add(sqfs_hash *h, sqfs_hash_key k, sqfs_hash_value v); -sqfs_err sqfs_hash_remove(sqfs_hash *h, sqfs_hash_key k); - -#endif diff --git a/ruby/squash/mutex.h b/ruby/squash/mutex.h deleted file mode 100644 index bba30cc42..000000000 --- a/ruby/squash/mutex.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef LIBSQUASH_MUTEX_H -#define LIBSQUASH_MUTEX_H - -#ifdef _WIN32 - #include - #include -#else - #include -#endif - -#ifdef _WIN32 - #define MUTEX HANDLE -#else - #define MUTEX pthread_mutex_t -#endif - -extern MUTEX squash_global_mutex; - -int MUTEX_INIT(MUTEX *mutex); -int MUTEX_LOCK(MUTEX *mutex); -int MUTEX_UNLOCK(MUTEX *mutex); -int MUTEX_DESTORY(MUTEX *mutex); - -#endif //LIBSQUASH_MUTEX_H diff --git a/ruby/squash/nonstd.h b/ruby/squash/nonstd.h deleted file mode 100644 index f14b6fed4..000000000 --- a/ruby/squash/nonstd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_STD_H -#define SQFS_STD_H - -#include "squash/common.h" - -/* Non-standard functions that we need */ - -dev_t sqfs_makedev(int maj, int min); - -#endif diff --git a/ruby/squash/private.h b/ruby/squash/private.h deleted file mode 100644 index 3d39ce06d..000000000 --- a/ruby/squash/private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_PRIVATE_H -#define SQFS_PRIVATE_H - -#include "squash.h" - -#include - -/* Fill in a stat structure. Does not set st_ino */ -sqfs_err sqfs_stat(sqfs *fs, sqfs_inode *inode, struct stat *st); - -#endif diff --git a/ruby/squash/squashfs_fs.h b/ruby/squash/squashfs_fs.h deleted file mode 100644 index fda66667b..000000000 --- a/ruby/squash/squashfs_fs.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * squashfs_fs.h - * - * Copyright (c) 2012 Phillip Lougher - * - * 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(S) ``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(S) 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. - */ -#ifndef SQUASHFS_FS -#define SQUASHFS_FS - -#ifdef __linux__ - #include -#else - #include - typedef uint16_t __le16; - typedef uint32_t __le32; - typedef uint64_t __le64; -#endif - -#define SQUASHFS_MAGIC 0x73717368 - - -#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE -#define SQUASHFS_MAJOR 4 -#define SQUASHFS_MINOR 0 -#define SQUASHFS_START 0 - -/* size of metadata (inode and directory) blocks */ -#define SQUASHFS_METADATA_SIZE 8192 -#define SQUASHFS_METADATA_LOG 13 - -/* default size of data blocks */ -#define SQUASHFS_FILE_SIZE 131072 -#define SQUASHFS_FILE_LOG 17 - -#define SQUASHFS_FILE_MAX_SIZE 1048576 -#define SQUASHFS_FILE_MAX_LOG 20 - -/* Max number of uids and gids */ -#define SQUASHFS_IDS 65536 - -/* Max length of filename (not 255) */ -#define SQUASHFS_NAME_LEN 256 -#define SQUASHFS_PATH_LEN 2048 -#define SQUASHFS_MAX_LINK_LEVEL 32 -#define SQUASHFS_INVALID_FRAG (0xffffffffU) -#define SQUASHFS_INVALID_XATTR (0xffffffffU) -#define SQUASHFS_INVALID_BLK ((int64_t)-1) - -/* Filesystem flags */ -#define SQUASHFS_NOI 0 -#define SQUASHFS_NOD 1 -#define SQUASHFS_NOF 3 -#define SQUASHFS_NO_FRAG 4 -#define SQUASHFS_ALWAYS_FRAG 5 -#define SQUASHFS_DUPLICATE 6 -#define SQUASHFS_EXPORT 7 -#define SQUASHFS_COMP_OPT 10 - -/* Max number of types and file types */ -#define SQUASHFS_DIR_TYPE 1 -#define SQUASHFS_REG_TYPE 2 -#define SQUASHFS_SYMLINK_TYPE 3 -#define SQUASHFS_BLKDEV_TYPE 4 -#define SQUASHFS_CHRDEV_TYPE 5 -#define SQUASHFS_FIFO_TYPE 6 -#define SQUASHFS_SOCKET_TYPE 7 -#define SQUASHFS_LDIR_TYPE 8 -#define SQUASHFS_LREG_TYPE 9 -#define SQUASHFS_LSYMLINK_TYPE 10 -#define SQUASHFS_LBLKDEV_TYPE 11 -#define SQUASHFS_LCHRDEV_TYPE 12 -#define SQUASHFS_LFIFO_TYPE 13 -#define SQUASHFS_LSOCKET_TYPE 14 - -/* Xattr types */ -#define SQUASHFS_XATTR_USER 0 -#define SQUASHFS_XATTR_TRUSTED 1 -#define SQUASHFS_XATTR_SECURITY 2 -#define SQUASHFS_XATTR_VALUE_OOL 256 -#define SQUASHFS_XATTR_PREFIX_MASK 0xff - -#define SQUASHFS_COMPRESSED_BIT (1 << 15) - -#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) - - -/* cached data constants for filesystem */ -#define SQUASHFS_CACHED_BLKS 8 - -#define SQUASHFS_MAX_FILE_SIZE_LOG 64 - -#define SQUASHFS_MAX_FILE_SIZE (1LL << \ - (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) - -/* meta index cache */ -#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) -#define SQUASHFS_META_ENTRIES 127 -#define SQUASHFS_META_SLOTS 8 - - -/* - * definitions for structures on disk - */ -#define ZLIB_COMPRESSION 1 - -struct squashfs_super_block { - __le32 s_magic; - __le32 inodes; - __le32 mkfs_time; - __le32 block_size; - __le32 fragments; - __le16 compression; - __le16 block_log; - __le16 flags; - __le16 no_ids; - __le16 s_major; - __le16 s_minor; - __le64 root_inode; - __le64 bytes_used; - __le64 id_table_start; - __le64 xattr_id_table_start; - __le64 inode_table_start; - __le64 directory_table_start; - __le64 fragment_table_start; - __le64 lookup_table_start; -}; - -struct squashfs_dir_index { - __le32 index; - __le32 start_block; - __le32 size; -}; - -struct squashfs_base_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; -}; - -struct squashfs_ipc_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; -}; - -struct squashfs_lipc_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; - __le32 xattr; -}; - -struct squashfs_dev_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; - __le32 rdev; -}; - -struct squashfs_ldev_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; - __le32 rdev; - __le32 xattr; -}; - -struct squashfs_symlink_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; - __le32 symlink_size; -}; - -struct squashfs_reg_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 start_block; - __le32 fragment; - __le32 offset; - __le32 file_size; -}; - -struct squashfs_lreg_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le64 start_block; - __le64 file_size; - __le64 sparse; - __le32 nlink; - __le32 fragment; - __le32 offset; - __le32 xattr; -}; - -struct squashfs_dir_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 start_block; - __le32 nlink; - __le16 file_size; - __le16 offset; - __le32 parent_inode; -}; - -struct squashfs_ldir_inode { - __le16 inode_type; - __le16 mode; - __le16 uid; - __le16 guid; - __le32 mtime; - __le32 inode_number; - __le32 nlink; - __le32 file_size; - __le32 start_block; - __le32 parent_inode; - __le16 i_count; - __le16 offset; - __le32 xattr; -}; - -struct squashfs_dir_entry { - __le16 offset; - __le16 inode_number; - __le16 type; - __le16 size; -}; - -struct squashfs_dir_header { - __le32 count; - __le32 start_block; - __le32 inode_number; -}; - -struct squashfs_fragment_entry { - __le64 start_block; - __le32 size; - unsigned int unused; -}; - -struct squashfs_xattr_entry { - __le16 type; - __le16 size; -}; - -struct squashfs_xattr_val { - __le32 vsize; -}; - -struct squashfs_xattr_id { - __le64 xattr; - __le32 count; - __le32 size; -}; - -struct squashfs_xattr_id_table { - __le64 xattr_table_start; - __le32 xattr_ids; - __le32 unused; -}; - -#endif diff --git a/ruby/squash/stack.h b/ruby/squash/stack.h deleted file mode 100644 index 997821284..000000000 --- a/ruby/squash/stack.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_STACK_H -#define SQFS_STACK_H - -#include "squash/common.h" - -typedef void (*sqfs_stack_free_t)(void *v); - -typedef struct { - size_t value_size; - size_t size; - size_t capacity; - char *items; - sqfs_stack_free_t freer; -} sqfs_stack; - -/* Ensures the struct is in a safe state */ -void sqfs_stack_init(sqfs_stack *s); - -sqfs_err sqfs_stack_create(sqfs_stack *s, size_t vsize, size_t initial, - sqfs_stack_free_t freer); -void sqfs_stack_destroy(sqfs_stack *s); - -sqfs_err sqfs_stack_push(sqfs_stack *s, void *vout); -short sqfs_stack_pop(sqfs_stack *s); - -size_t sqfs_stack_size(sqfs_stack *s); -sqfs_err sqfs_stack_at(sqfs_stack *s, size_t i, void *vout); -sqfs_err sqfs_stack_top(sqfs_stack *s, void *vout); - -#endif diff --git a/ruby/squash/table.h b/ruby/squash/table.h deleted file mode 100644 index 7dea081f8..000000000 --- a/ruby/squash/table.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_TABLE_H -#define SQFS_TABLE_H - -#include "squash/common.h" - -typedef struct { - size_t each; - uint64_t *blocks; -} sqfs_table; - -sqfs_err sqfs_table_init(sqfs_table *table, sqfs_fd_t fd, sqfs_off_t start, size_t each, - size_t count); -void sqfs_table_destroy(sqfs_table *table); - -sqfs_err sqfs_table_get(sqfs_table *table, sqfs *fs, size_t idx, void *buf); - -#endif diff --git a/ruby/squash/traverse.h b/ruby/squash/traverse.h deleted file mode 100644 index 23a9c84fe..000000000 --- a/ruby/squash/traverse.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_TRAVERSE_H -#define SQFS_TRAVERSE_H - -#include "squash/common.h" - -#include "squash/dir.h" -#include "squash/stack.h" - -typedef struct { - short dir_end; - sqfs_dir_entry entry; - char *path; - - - /* private */ - int state; - sqfs *fs; - sqfs_name namebuf; - sqfs_stack stack; - - size_t path_size, path_cap; - size_t path_last_size; -} sqfs_traverse; - -/* Begin a recursive traversal of a filesystem tree. - Every sub-item of the given inode will be traversed in-order, but not - this inode itself. */ -sqfs_err sqfs_traverse_open(sqfs_traverse *trv, sqfs *fs, sqfs_inode_id iid); -sqfs_err sqfs_traverse_open_inode(sqfs_traverse *trv, sqfs *fs, - sqfs_inode *inode); - -/* Clean up at any point during or after a traversal */ -void sqfs_traverse_close(sqfs_traverse *trv); - -/* Get the next item in the traversal. An item may be: - - A directory entry, in which case trv->entry will be filled - - A marker that a directory is finished, in which case trv->dir_end will - be 1. - Returns 0 if there are no more items. */ -short sqfs_traverse_next(sqfs_traverse *trv, sqfs_err *err); - -/* Don't recurse into the directory just returned. */ -sqfs_err sqfs_traverse_prune(sqfs_traverse *trv); - -#endif diff --git a/ruby/squash/util.h b/ruby/squash/util.h deleted file mode 100644 index a7f14e695..000000000 --- a/ruby/squash/util.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) 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. - */ -#ifndef SQFS_UTIL_H -#define SQFS_UTIL_H - -#include "squash/common.h" - -#include - -/* Open a file, and optionally print a message on failure */ -sqfs_err sqfs_fd_open(const uint8_t *path, sqfs_fd_t *fd); - -/* Close a file */ -void sqfs_fd_close(sqfs_fd_t fd); - -/* Open a filesystem and print errors to stderr. */ -sqfs_err sqfs_open_image(sqfs *fs, const uint8_t *image, size_t offset); - -#endif diff --git a/ruby/squash/windows.h b/ruby/squash/windows.h deleted file mode 100644 index 9b629b2c3..000000000 --- a/ruby/squash/windows.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#ifndef WINDOWS_H_A80B5674 -#define WINDOWS_H_A80B5674 - -#include -#include -#include - -typedef unsigned short sqfs_mode_t; -typedef uint32_t sqfs_id_t; /* Internal uids/gids are 32-bits */ - -typedef SSIZE_T ssize_t; -typedef DWORD64 sqfs_off_t; -typedef uint32_t uid_t; /* [???] user IDs */ - -#ifndef S_IFIFO -#define S_IFIFO 0010000 /* [XSI] named pipe (fifo) */ -#endif - -#ifndef S_IFBLK -#define S_IFBLK 0060000 /* [XSI] block special */ -#endif - -#ifndef S_IFLNK -#define S_IFLNK 0120000 /* [XSI] symbolic link */ -#endif - -#ifndef S_IFSOCK -#define S_IFSOCK 0140000 /* [XSI] socket */ -#endif - -#ifndef S_ISBLK -#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* block special */ -#endif - -#ifndef S_ISCHR -#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* char special */ -#endif - -#ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* directory */ -#endif - -#ifndef S_ISFIFO -#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */ -#endif - -#ifndef S_ISREG -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */ -#endif - -#ifndef S_ISLNK -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* symbolic link */ -#endif - -#ifndef S_ISSOCK -#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* socket */ -#endif - -#ifndef makedev -#define makedev(x,y) ((dev_t)(((x) << 24) | (y))) -#endif - -#ifndef DT_UNKNOWN -#define DT_UNKNOWN 0 -#endif - -#ifndef DT_FIFO -#define DT_FIFO 1 -#endif - -#ifndef DT_CHR -#define DT_CHR 2 -#endif - -#ifndef DT_DIR -#define DT_DIR 4 -#endif - -#ifndef DT_BLK -#define DT_BLK 6 -#endif - -#ifndef DT_REG -#define DT_REG 8 -#endif - -#ifndef DT_LNK -#define DT_LNK 10 -#endif - -#ifndef DT_SOCK -#define DT_SOCK 12 -#endif - -#ifndef DT_WHT -#define DT_WHT 14 -#endif - -#endif /* end of include guard: WINDOWS_H_A80B5674 */ diff --git a/ruby/squash_cache.c b/ruby/squash_cache.c deleted file mode 100644 index 5a999cc8a..000000000 --- a/ruby/squash_cache.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/cache.h" - -#include "squash/fs.h" - -#include - -sqfs_err sqfs_cache_init(sqfs_cache *cache, size_t size, size_t count, - sqfs_cache_dispose dispose) { - cache->size = size; - cache->count = count; - cache->dispose = dispose; - cache->next = 0; - - MUTEX_INIT(&cache->mutex); - - cache->idxs = calloc(count, sizeof(sqfs_cache_idx)); - cache->buf = calloc(count, size); - if (cache->idxs && cache->buf) - return SQFS_OK; - - sqfs_cache_destroy(cache); - return SQFS_ERR; -} - -static void *sqfs_cache_entry(sqfs_cache *cache, size_t i) { - return cache->buf + i * cache->size; -} - -void sqfs_cache_destroy(sqfs_cache *cache) { - MUTEX_DESTORY(&cache->mutex); - - if (cache->buf && cache->idxs) { - size_t i; - for (i = 0; i < cache->count; ++i) { - if (cache->idxs[i] != SQFS_CACHE_IDX_INVALID) - cache->dispose(sqfs_cache_entry(cache, i)); - } - } - free(cache->buf); - free(cache->idxs); -} - -void *sqfs_cache_get(sqfs_cache *cache, sqfs_cache_idx idx) { - size_t i; - void *ret = NULL; - for (i = 0; i < cache->count; ++i) { - if (cache->idxs[i] == idx){ - ret = sqfs_cache_entry(cache, i); - break; - } - - } - return ret; -} - -void *sqfs_cache_add(sqfs_cache *cache, sqfs_cache_idx idx) { - size_t i = (cache->next++); - cache->next %= cache->count; - - if (cache->idxs[i] != SQFS_CACHE_IDX_INVALID) - cache->dispose(sqfs_cache_entry(cache, i)); - - cache->idxs[i] = idx; - return sqfs_cache_entry(cache, i); -} - -static void sqfs_block_cache_dispose(void *data) { - sqfs_block_cache_entry *entry = (sqfs_block_cache_entry*)data; - sqfs_block_dispose(entry->block); -} - -sqfs_err sqfs_block_cache_init(sqfs_cache *cache, size_t count) { - return sqfs_cache_init(cache, sizeof(sqfs_block_cache_entry), count, - &sqfs_block_cache_dispose); -} diff --git a/ruby/squash_decompress.c b/ruby/squash_decompress.c deleted file mode 100644 index aa85602ab..000000000 --- a/ruby/squash_decompress.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/decompress.h" -#include "squash/squashfs_fs.h" - -#include -#include - -static sqfs_err sqfs_decompressor_zlib(void *in, size_t insz, - void *out, size_t *outsz) { - uLongf zout = *outsz; - int zerr = uncompress((Bytef*)out, &zout, in, insz); - if (zerr != Z_OK) - return SQFS_ERR; - *outsz = zout; - return SQFS_OK; -} - -sqfs_decompressor sqfs_decompressor_get(sqfs_compression_type type) { - assert(ZLIB_COMPRESSION == type); - return &sqfs_decompressor_zlib; -} diff --git a/ruby/squash_dir.c b/ruby/squash_dir.c deleted file mode 100644 index e9842af89..000000000 --- a/ruby/squash_dir.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash.h" - -#include "squash/dir.h" - -#include "squash/fs.h" - -#include -#include - -/* Read some directory metadata, updating the dir structure as necessary */ -static sqfs_err sqfs_dir_md_read(sqfs *fs, sqfs_dir *dir, void *buf, - size_t size); - -/* Fast forwards to a directory header. */ -typedef sqfs_err sqfs_dir_header_f(sqfs *fs, sqfs_md_cursor *cur, - struct squashfs_dir_index *index, short *stop, void *arg); -static sqfs_err sqfs_dir_ff_header(sqfs *fs, sqfs_inode *inode, sqfs_dir *dir, - sqfs_dir_header_f func, void *arg); - -/* Fast forward a directory to the given offset. Return error if it doesn't - exist. */ -static sqfs_err sqfs_dir_ff_offset(sqfs *fs, sqfs_inode *inode, sqfs_dir *dir, - sqfs_off_t offset); - - -static sqfs_err sqfs_dir_md_read(sqfs *fs, sqfs_dir *dir, void *buf, - size_t size) { - dir->offset += size; - return sqfs_md_read(fs, &dir->cur, buf, size); -} - - -sqfs_err sqfs_dir_open(sqfs *fs, sqfs_inode *inode, sqfs_dir *dir, - off_t offset) { - if (!S_ISDIR(inode->base.mode)) - return SQFS_ERR; - - memset(dir, 0, sizeof(*dir)); - dir->cur.block = inode->xtra.dir.start_block + - fs->sb->directory_table_start; - dir->cur.offset = inode->xtra.dir.offset; - dir->offset = 0; - dir->total = inode->xtra.dir.dir_size - 3; - - if (offset) { - /* Fast forward to the given offset */ - sqfs_err err = sqfs_dir_ff_offset(fs, inode, dir, offset); - if (err) - return err; - } - - return SQFS_OK; -} - - -void sqfs_dentry_init(sqfs_dir_entry *entry, char *namebuf) { - entry->name = namebuf; -} - -sqfs_off_t sqfs_dentry_offset(sqfs_dir_entry *entry) { - return entry->offset; -} - -sqfs_off_t sqfs_dentry_next_offset(sqfs_dir_entry *entry) { - return entry->next_offset; -} - -int sqfs_dentry_type(sqfs_dir_entry *entry) { - return entry->type; -} -sqfs_mode_t sqfs_dentry_mode(sqfs_dir_entry *entry) { - return sqfs_mode(sqfs_dentry_type(entry)); -} - -sqfs_inode_id sqfs_dentry_inode(sqfs_dir_entry *entry) { - return entry->inode; -} - -sqfs_inode_num sqfs_dentry_inode_num(sqfs_dir_entry *entry) { - return entry->inode_number; -} - -size_t sqfs_dentry_name_size(sqfs_dir_entry *entry) { - return entry->name_size; -} - -const char *sqfs_dentry_name(sqfs_dir_entry *entry) { - if (!entry->name) - return NULL; - - entry->name[sqfs_dentry_name_size(entry)] = '\0'; - return entry->name; -} - -short sqfs_dentry_is_dir(sqfs_dir_entry *entry) { - return S_ISDIR(sqfs_dentry_mode(entry)); -} - - - -short sqfs_dir_next(sqfs *fs, sqfs_dir *dir, sqfs_dir_entry *entry, - sqfs_err *err) { - struct squashfs_dir_entry e; - - *err = SQFS_OK; - entry->offset = dir->offset; - - while (dir->header.count == 0) { - if (dir->offset >= dir->total) - return 0; - - if ((*err = sqfs_dir_md_read(fs, dir, &dir->header, sizeof(dir->header)))) - return 0; - ++(dir->header.count); /* biased by one */ - } - - if ((*err = sqfs_dir_md_read(fs, dir, &e, sizeof(e)))) - return 0; - --(dir->header.count); - - entry->type = e.type; - entry->name_size = e.size + 1; - entry->inode = ((uint64_t)dir->header.start_block << 16) + e.offset; - /* e.inode_number is signed */ - entry->inode_number = dir->header.inode_number + (int16_t)e.inode_number; - - *err = sqfs_dir_md_read(fs, dir, entry->name, sqfs_dentry_name_size(entry)); - if (*err) - return 0; - - entry->next_offset = dir->offset; - - return 1; -} - - -static sqfs_err sqfs_dir_ff_header(sqfs *fs, sqfs_inode *inode, - sqfs_dir *dir, sqfs_dir_header_f func, void *arg) { - struct squashfs_dir_index idx; - sqfs_md_cursor cur = inode->next; - size_t count = inode->xtra.dir.idx_count; - - if (count == 0) - return SQFS_OK; - - while (count--) { - sqfs_err err; - short stop = 0; - - if ((err = sqfs_md_read(fs, &cur, &idx, sizeof(idx)))) - return err; - - if ((err = func(fs, &cur, &idx, &stop, arg))) - return err; - if (stop) - break; - - dir->cur.block = idx.start_block + fs->sb->directory_table_start; - dir->offset = idx.index; - } - - dir->cur.offset = (dir->cur.offset + dir->offset) % SQUASHFS_METADATA_SIZE; - return SQFS_OK; -} - - -/* Helper for sqfs_dir_ff_offset */ -static sqfs_err sqfs_dir_ff_offset_f(sqfs *fs, sqfs_md_cursor *cur, - struct squashfs_dir_index *index, short *stop, void *arg) { - sqfs_off_t offset = *(sqfs_off_t*)arg; - - if (index->index >= offset) { - *stop = 1; - return SQFS_OK; - } - - return sqfs_md_read(fs, cur, NULL, index->size + 1); /* skip name */ -} - -static sqfs_err sqfs_dir_ff_offset(sqfs *fs, sqfs_inode *inode, sqfs_dir *dir, - sqfs_off_t offset) { - sqfs_err err; - sqfs_dir_entry entry; - - err = sqfs_dir_ff_header(fs, inode, dir, sqfs_dir_ff_offset_f, &offset); - if (err) - return err; - - sqfs_dentry_init(&entry, NULL); - while (dir->offset < offset && sqfs_dir_next(fs, dir, &entry, &err)) - ; /* pass */ - - if (err) - return err; - return dir->offset == offset ? SQFS_OK : SQFS_ERR; -} - - -/* Helper for sqfs_dir_lookup */ -typedef struct { - const char *cmp; - size_t cmplen; - char *name; -} sqfs_dir_ff_name_t; - -static sqfs_err sqfs_dir_ff_name_f(sqfs *fs, sqfs_md_cursor *cur, - struct squashfs_dir_index *index, short *stop, void *arg) { - sqfs_err err; - sqfs_dir_ff_name_t *args = (sqfs_dir_ff_name_t*)arg; - size_t name_size = index->size + 1; - int order; - - if ((err = sqfs_md_read(fs, cur, args->name, name_size))) - return err; - args->name[name_size] = '\0'; - - order = strncmp(args->name, args->cmp, args->cmplen); - if (order > 0 || (order == 0 && name_size > args->cmplen)) - *stop = 1; - - return SQFS_OK; -} - -sqfs_err sqfs_dir_lookup(sqfs *fs, sqfs_inode *inode, - const char *name, size_t namelen, sqfs_dir_entry *entry, short *found) { - sqfs_err err; - sqfs_dir dir; - sqfs_dir_ff_name_t arg; - - *found = 0; - - if ((err = sqfs_dir_open(fs, inode, &dir, 0))) - return err; - - /* Fast forward to header */ - arg.cmp = name; - arg.cmplen = namelen; - arg.name = entry->name; - if ((err = sqfs_dir_ff_header(fs, inode, &dir, sqfs_dir_ff_name_f, &arg))) - return err; - - /* Iterate to find the right entry */ - while (sqfs_dir_next(fs, &dir, entry, &err)) { - int order = strncmp(sqfs_dentry_name(entry), name, namelen); - if (order == 0 && sqfs_dentry_name_size(entry) == namelen) - *found = 1; - if (order >= 0) - break; - } - - return err; -} - -static sqfs_err clear_dot_dot(char *path) -{ - char *dot_dot, *dot_dot_left; - - // we might get a path like /a/b/../../c/d - // in which case we need to interpret dot-dot's - while ((dot_dot = strstr(path, "/../"))) { - dot_dot_left = dot_dot - 1; - do { - if (dot_dot_left < path) { - return SQFS_ERR; - } - if ('/' == *dot_dot_left) { - break; - } - --dot_dot_left; - } while (1); - memmove(dot_dot_left, dot_dot + 3, strlen(dot_dot + 3) + 1); - } - // what about /a/b/c/d/.. - if (strlen(path) >= 3 && 0 == strcmp(path + strlen(path) - 3, "/..")) { - dot_dot_left = path + strlen(path) - 4; - do { - if (dot_dot_left < path) { - return SQFS_ERR; - } - if ('/' == *dot_dot_left) { - break; - } - --dot_dot_left; - } while (1); - *dot_dot_left = '\0'; - } - return SQFS_OK; -} - -sqfs_err squash_follow_link(sqfs *fs, const char *path, sqfs_inode *node) { - - sqfs_err error; - short found; - char base_path[SQUASHFS_PATH_LEN]; - char new_path[SQUASHFS_PATH_LEN]; - int inode_num; - - if(strlen(path) > SQUASHFS_PATH_LEN){ - errno = ENAMETOOLONG; - return SQFS_ERR; - } - - strncpy(base_path, path, SQUASHFS_PATH_LEN); - inode_num = 0; - do { - char buf_link[SQUASHFS_PATH_LEN]; // is enough for path? - ssize_t link_length = squash_readlink_inode(fs, node, buf_link, sizeof(buf_link)); - if (link_length > 0) { - if (buf_link[0] == '/') { // is Absolute Path - // find node from / - error = sqfs_inode_get(fs, node, sqfs_inode_root(fs)); - if (SQFS_OK != error) { - return error; - } - error = sqfs_lookup_path(fs, node, buf_link, &found); - strncpy(new_path, buf_link, SQUASHFS_PATH_LEN); - if (SQFS_OK != error) { - return error; - } else if (!found) { - errno = ENOENT; - return SQFS_ERR; - } - } else { // is Relative Path - size_t pos = strlen(base_path) - 1; - // find the last / "/a/b/cb" - while (base_path[pos--] != '/') { } - - memcpy(new_path, base_path, pos + 2); - memcpy(new_path + pos + 2, buf_link, link_length); - new_path[pos + 2 + link_length] = '\0'; - - error = clear_dot_dot(new_path); - if (SQFS_OK != error) { - errno = ENOENT; - return SQFS_ERR; - } - - // find node from / - error = sqfs_inode_get(fs, node, sqfs_inode_root(fs)); - if (SQFS_OK != error) { - return error; - } - error = sqfs_lookup_path(fs, node, new_path, &found); - if (SQFS_OK != error) { - return error; - } else if (!found) { - errno = ENOENT; - return SQFS_ERR; - } - } - - inode_num++; - if (inode_num > SQUASHFS_MAX_LINK_LEVEL) { - errno = ELOOP; - return SQFS_ERR; - } - strncpy(base_path, new_path, SQUASHFS_PATH_LEN); - - } else { - return SQFS_ERR; - } - - - } while (S_ISLNK(node->base.mode)); - - return SQFS_OK; -} - -sqfs_err sqfs_lookup_path_inner(sqfs *fs, sqfs_inode *inode, const char *incoming_path, - short *found, short follow_link) { - sqfs_err err, ret; - sqfs_name buf; - sqfs_path path_here; - sqfs_dir_entry entry; - char *path, *path0; - short is_last_component; - memset(&buf, 0, sizeof(sqfs_name)); - memset(&entry, 0, sizeof(sqfs_dir_entry)); - - *found = 0; - sqfs_dentry_init(&entry, buf); - - path = strdup(incoming_path); - if (NULL == path) { - return SQFS_ERR; - } - path0 = path; - - err = clear_dot_dot(path); - if (SQFS_OK != err) { - ret = SQFS_OK; /* not found */ - goto exit; - } - - while (*path) { - const char *name; - size_t size; - - /* Find next path component */ - while (*path == '/') /* skip leading slashes */ - ++path; - - name = path; - while (*path && *path != '/') - ++path; - size = path - name; - if (0 == size) { - /* we're done */ - break; - } - if (1 == size && '.' == *name) { - /* interpret dot */ - continue; - } - if ((err = sqfs_dir_lookup(fs, inode, name, size, &entry, found))) { - ret = err; - goto exit; - } - if (!(*found)) { - ret = SQFS_OK; /* not found */ - goto exit; - } - if ((err = sqfs_inode_get(fs, inode, sqfs_dentry_inode(&entry)))) { - ret = err; - goto exit; - } - if (!*path) { - is_last_component = 1; - } else if (path0 + strlen(path0) - 1 == path) { - assert('/' == *path); - is_last_component = 1; - } else { - is_last_component = 0; - } - - if (S_ISLNK(inode->base.mode)) { - if (!(is_last_component && !follow_link)) { - size_t size_here = path - path0; - if (size_here > SQUASHFS_PATH_LEN) { - size_here = SQUASHFS_PATH_LEN; - } - memcpy(path_here, path0, size_here); - path_here[size_here] = '\0'; - err = squash_follow_link(fs, path_here, inode); - if (SQFS_OK != err) { - ret = err; - goto exit; - } - } - } - } - - *found = 1; - ret = SQFS_OK; -exit: - free(path0); - return ret; -} - -sqfs_err sqfs_lookup_path(sqfs *fs, sqfs_inode *inode, const char *path, - short *found) { - return sqfs_lookup_path_inner(fs, inode, path, found, 0); -} diff --git a/ruby/squash_dirent.c b/ruby/squash_dirent.c deleted file mode 100644 index 4e5d692e8..000000000 --- a/ruby/squash_dirent.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" -#include - -#include - -SQUASH_DIR *squash_opendir_inner(sqfs *fs, const char *filename, short follow_link) -{ - sqfs_err error; - short found; - SQUASH_DIR *dir = calloc(1, sizeof(SQUASH_DIR)); - int *handle; - - if (NULL == dir) - { - errno = ENOMEM; - return NULL; - } - dir->fs = fs; - dir->entries = NULL; - dir->nr = 0; - dir->filename = strdup(filename); - dir->fd = squash_open(fs, filename); - if (-1 == dir->fd) - { - goto failure; - } - handle = (int *)(squash_global_fdtable.fds[dir->fd]->payload); - - MUTEX_LOCK(&squash_global_mutex); - free(handle); - squash_global_fdtable.fds[dir->fd]->payload = (void *)dir; - MUTEX_UNLOCK(&squash_global_mutex); - - dir->actual_nr = 0; - dir->loc = 0; - error = sqfs_inode_get(fs, &dir->node, sqfs_inode_root(fs)); - if (SQFS_OK != error) - { - goto failure; - } - error = sqfs_lookup_path_inner(fs, &dir->node, filename, &found, follow_link); - if (SQFS_OK != error) - { - goto failure; - } - if (!found) - { - errno = ENOENT; - goto failure; - } - error = sqfs_dir_open(fs, &dir->node, &dir->dir, 0); - if (SQFS_OK != error) - { - goto failure; - } - return dir; -failure: - if (!errno) { - errno = ENOENT; - } - free(dir); - return NULL; -} - -SQUASH_DIR *squash_opendir(sqfs *fs, const char *filename) -{ - return squash_opendir_inner(fs, filename, 1); -} - -int squash_closedir(SQUASH_DIR *dirp) -{ - int ret; - - assert(-1 != dirp->fd); - free(dirp->entries); - free(dirp->filename); - if (dirp->payload) { - free(dirp->payload); - } - // dirp itself will be freed by squash_close as `payload` - ret = squash_close(dirp->fd); - if (0 != ret) { - if (!errno) { - errno = EBADF; - } - return -1; - } - return 0; -} - -struct SQUASH_DIRENT * squash_readdir(SQUASH_DIR *dirp) -{ - sqfs_err error; - size_t nr = dirp->loc + 1; - if (dirp->nr < nr) { - // we secretly extend the requested size - // in order to minimize the number of realloc calls - nr *= 10; - dirp->entries = realloc(dirp->entries, nr * sizeof(*dirp->entries)); - if (NULL == dirp->entries) - { - errno = ENOMEM; - return NULL; - } - dirp->nr = nr; - } - - while (dirp->actual_nr < dirp->loc + 1) - { - sqfs_dentry_init(&dirp->entries[dirp->actual_nr].entry, - dirp->entries[dirp->actual_nr].name); - dirp->entries[dirp->actual_nr].not_eof = sqfs_dir_next( - dirp->fs, - &dirp->dir, - &dirp->entries[dirp->actual_nr].entry, - &error); - if (SQFS_OK != error) - { - return NULL; - } - else if (!dirp->entries[dirp->actual_nr].not_eof) - { - return NULL; - } - else { - sqfs_dir_entry *entry = &dirp->entries[dirp->actual_nr].entry; - struct SQUASH_DIRENT *sysentry = &dirp->entries[dirp->actual_nr].sysentry; - size_t minsize; - - sysentry->d_ino = entry->inode_number; - minsize = entry->name_size; - if (SQUASHFS_NAME_LEN < minsize) { - minsize = SQUASHFS_NAME_LEN; - } - if (sizeof(sysentry->d_name) < minsize) { - minsize = sizeof(sysentry->d_name); - } - memcpy(sysentry->d_name, dirp->entries[dirp->actual_nr].name, minsize); -#ifndef __linux__ - sysentry->d_namlen = minsize; -#endif - sysentry->d_name[minsize] = '\0'; - // TODO special treatment of L types - switch (entry->type) - { - case SQUASHFS_DIR_TYPE: - case SQUASHFS_LDIR_TYPE: - sysentry->d_type = DT_DIR; - break; - case SQUASHFS_REG_TYPE: - case SQUASHFS_LREG_TYPE: - sysentry->d_type = DT_REG; - break; - case SQUASHFS_SYMLINK_TYPE: - case SQUASHFS_LSYMLINK_TYPE: - sysentry->d_type = DT_LNK; - break; - case SQUASHFS_BLKDEV_TYPE: - case SQUASHFS_LBLKDEV_TYPE: - sysentry->d_type = DT_BLK; - break; - case SQUASHFS_CHRDEV_TYPE: - case SQUASHFS_LCHRDEV_TYPE: - sysentry->d_type = DT_CHR; - break; - case SQUASHFS_FIFO_TYPE: - case SQUASHFS_LFIFO_TYPE: - sysentry->d_type = DT_FIFO; - break; - case SQUASHFS_SOCKET_TYPE: - case SQUASHFS_LSOCKET_TYPE: - sysentry->d_type = DT_SOCK; - break; - default: - sysentry->d_type = DT_UNKNOWN; - break; - } - dirp->actual_nr += 1; - } - } - if (!dirp->entries[dirp->loc].not_eof) - { - return NULL; - } - dirp->loc += 1; - return &dirp->entries[dirp->loc - 1].sysentry; -} - -long squash_telldir(SQUASH_DIR *dirp) -{ - return dirp->loc; -} - -void squash_seekdir(SQUASH_DIR *dirp, long loc) -{ - dirp->loc = loc; -} - -void squash_rewinddir(SQUASH_DIR *dirp) -{ - dirp->loc = 0; -} - -int squash_dirfd(SQUASH_DIR *dirp) -{ - return dirp->fd; -} diff --git a/ruby/squash_extract.c b/ruby/squash_extract.c deleted file mode 100644 index 042861ef1..000000000 --- a/ruby/squash_extract.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" -#include -#include - -#ifdef _WIN32 -#include -#include -SQUASH_OS_PATH squash_tmpdir() -{ - const int squash_win32_buf_sz = 32767; - wchar_t squash_win32_buf[32767 + 1]; - DWORD length; - - length = GetEnvironmentVariableW(L"TEMP", squash_win32_buf, squash_win32_buf_sz); - if (length) { - goto out; - } - length = GetEnvironmentVariableW(L"TMP", squash_win32_buf, squash_win32_buf_sz); - if (length) { - goto out; - } - length = GetEnvironmentVariableW(L"SystemRoot", squash_win32_buf, squash_win32_buf_sz); - if (!length) { - length = GetEnvironmentVariableW(L"windir", squash_win32_buf, squash_win32_buf_sz); - } - if (length) { - if (length + 5 >= squash_win32_buf_sz) { - return NULL; - } - squash_win32_buf[length] = L'\\'; - squash_win32_buf[length + 1] = L't'; - squash_win32_buf[length + 2] = L'e'; - squash_win32_buf[length + 3] = L'm'; - squash_win32_buf[length + 4] = L'p'; - squash_win32_buf[length + 5] = 0; - length += 5; - goto out; - } - return NULL; -out: - if (length >= 2 && L'\\' == squash_win32_buf[length - 1] && L':' != squash_win32_buf[length - 2]) { - squash_win32_buf[length - 1] = 0; - length -= 1; - } - return wcsdup(squash_win32_buf); -} -SQUASH_OS_PATH squash_tmpf(SQUASH_OS_PATH tmpdir, const char *ext_name) -{ - const int squash_win32_buf_sz = 32767; - wchar_t squash_win32_buf[32767 + 1]; - size_t curlen, size_ret; - int ret, try_cnt = 0; - srand(time(NULL) * getpid()); - squash_win32_buf[squash_win32_buf_sz] = 0; - while (try_cnt < 3) { - squash_win32_buf[0] = 0; - assert(0 == wcslen(squash_win32_buf)); - wcsncat(squash_win32_buf + wcslen(squash_win32_buf), tmpdir, squash_win32_buf_sz - wcslen(squash_win32_buf)); - wcsncat(squash_win32_buf + wcslen(squash_win32_buf), L"\\libsquash-", squash_win32_buf_sz - wcslen(squash_win32_buf)); - // up to 33 characters for _itoa - if (squash_win32_buf_sz - wcslen(squash_win32_buf) <= 33) { - return NULL; - } - _itow(rand(), squash_win32_buf + wcslen(squash_win32_buf), 10); - if (ext_name) { - wcsncat(squash_win32_buf + wcslen(squash_win32_buf), L".", squash_win32_buf_sz - wcslen(squash_win32_buf)); - } - if (ext_name) { - curlen = wcslen(squash_win32_buf); - size_ret = mbstowcs((wchar_t*)(squash_win32_buf) + curlen, ext_name, squash_win32_buf_sz - curlen); - if ((size_t)-1 == size_ret) { - return NULL; - } - *((wchar_t*)(squash_win32_buf) + curlen + size_ret) = 0; - } - if (!PathFileExistsW(squash_win32_buf)) { - return wcsdup(squash_win32_buf); - } - ++try_cnt; - } - return NULL; -} -#else // _WIN32 - -#include -#include -#include - -SQUASH_OS_PATH squash_tmpdir() -{ - char *try_try; - size_t length; - try_try = getenv("TMPDIR"); - if (try_try) { - goto out; - } - try_try = getenv("TMP"); - if (try_try) { - goto out; - } - try_try = getenv("TEMP"); - if (try_try) { - goto out; - } - try_try = "/tmp"; -out: - try_try = strdup(try_try); - length = strlen(try_try); - if (length >= 2 && '/' == try_try[length - 1]) { - try_try[length - 1] = 0; - } - return try_try; -} -SQUASH_OS_PATH squash_tmpf(SQUASH_OS_PATH tmpdir, const char *ext_name) -{ - const int squash_buf_sz = 32767; - char squash_buf[squash_buf_sz + 1]; - int ret, try_cnt = 0; - struct stat statbuf; - - srand(time(NULL) * getpid()); - while (try_cnt < 3) { - if (ext_name) { - ret = snprintf(squash_buf, squash_buf_sz, "%s/libsquash-%d.%s", tmpdir, rand(), ext_name); - } else { - ret = snprintf(squash_buf, squash_buf_sz, "%s/libsquash-%d", tmpdir, rand()); - } - if (-1 == ret) { - return NULL; - } - if (-1 == stat(squash_buf, &statbuf)) { - return strdup(squash_buf); - } - ++try_cnt; - } - return NULL; -} -#endif // _WIN32 - -static SQUASH_OS_PATH squash_uncached_extract(sqfs *fs, const char *path, const char *ext_name) -{ - static SQUASH_OS_PATH tmpdir = NULL; - FILE *fp; - int fd; - SQUASH_OS_PATH tmpf; - size_t size; - ssize_t ssize; - char buffer[16 * 1024]; - sqfs_off_t offset; - struct squash_file *file; - - fd = squash_open(fs, path); - if (-1 == fd) { - return NULL; - } - if (NULL == tmpdir) { - tmpdir = squash_tmpdir(); - } - if (NULL == tmpdir) { - return NULL; - } - tmpf = squash_tmpf(tmpdir, ext_name); - if (NULL == tmpf) { - return NULL; - } -#ifdef _WIN32 - fp = _wfopen(tmpf, L"wb"); -#else - fp = fopen(tmpf, "wb"); -#endif - if (NULL == fp) { - free(tmpf); - return NULL; - } - file = SQUASH_VFD_FILE(fd); - offset = file->node.xtra.reg.file_size; - while (offset > 0) { - ssize = squash_read(fd, buffer, 16 * 1024); - if (ssize <= 0) { - fclose(fp); - free(tmpf); - return NULL; - } - offset -= ssize; - size = fwrite(buffer, ssize, 1, fp); - if (size != 1) { - fclose(fp); - free(tmpf); - return NULL; - } - } - assert(0 == offset); - fclose(fp); - return tmpf; -} - -struct SquashExtractEntry { - sqfs *fs; - const char *path; - SQUASH_OS_PATH ret; - struct SquashExtractEntry *next; -}; - -static struct SquashExtractEntry* squash_extract_cache = NULL; - -static const struct SquashExtractEntry* squash_extract_cache_find(sqfs *fs, const char *path) -{ - struct SquashExtractEntry* ptr = squash_extract_cache; - while (NULL != ptr) { - if (fs == ptr->fs && 0 == strcmp(path, ptr->path)) { - return ptr; - } - ptr = ptr->next; - } - return ptr; -} -static void squash_extract_cache_insert(sqfs *fs, const char *path, SQUASH_OS_PATH ret) -{ - struct SquashExtractEntry* ptr = malloc(sizeof(struct SquashExtractEntry)); - if (NULL == ptr) { - return; - } - ptr->fs = fs; - ptr->path = path; - ptr->ret = ret; - ptr->next = squash_extract_cache; - squash_extract_cache = ptr; -} - -SQUASH_OS_PATH squash_extract(sqfs *fs, const char *path, const char *ext_name) -{ - SQUASH_OS_PATH ret; - static struct SquashExtractEntry* found; - - found = squash_extract_cache_find(fs, path); - if (NULL != found) { - return found->ret; - } - ret = squash_uncached_extract(fs, path, ext_name); - if (NULL != ret) { - squash_extract_cache_insert(fs, path, ret); - } - return ret; -} - -void squash_extract_clear_cache() -{ - struct SquashExtractEntry* ptr = squash_extract_cache; - while (NULL != ptr) { -#ifdef _WIN32 - DeleteFileW(ptr->ret); -#else - unlink(ptr->ret); -#endif - ptr = ptr->next; - } -} diff --git a/ruby/squash_fd.c b/ruby/squash_fd.c deleted file mode 100644 index 9b0bb1a19..000000000 --- a/ruby/squash_fd.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" -#include - -struct squash_fdtable squash_global_fdtable; -MUTEX squash_global_mutex; - -int squash_open_inner(sqfs *fs, const char *path, short follow_link) -{ - sqfs_err error; - struct squash_file *file = calloc(1, sizeof(struct squash_file)); - short found; - int fd; - size_t nr; - int *handle; - - // try locating the file and fetching its stat - if (NULL == file) - { - errno = ENOMEM; - return -1; - } - error = sqfs_inode_get(fs, &file->node, sqfs_inode_root(fs)); - if (SQFS_OK != error) - { - goto failure; - } - error = sqfs_lookup_path_inner(fs, &file->node, path, &found, follow_link); - if (SQFS_OK != error) - { - goto failure; - } - file->filename = strdup(path); - - if (!found) - { - errno = ENOENT; - goto failure; - } - error = sqfs_stat(fs, &file->node, &file->st); - if (SQFS_OK != error) - { - goto failure; - } - file->fs = fs; - file->pos = 0; - - // get a dummy fd from the system - fd = dup(0); - if (-1 == fd) { - goto failure; - } - // make sure that our global fd table is large enough - nr = fd + 1; - - MUTEX_LOCK(&squash_global_mutex); - if (squash_global_fdtable.nr < nr) - { - // we secretly extend the requested size - // in order to minimize the number of realloc calls - nr *= 10; - squash_global_fdtable.fds = realloc(squash_global_fdtable.fds, - nr * sizeof(struct squash_file *)); - if (NULL == squash_global_fdtable.fds) - { - errno = ENOMEM; - goto failure; - } - memset(squash_global_fdtable.fds + squash_global_fdtable.nr, - 0, - (nr - squash_global_fdtable.nr) * sizeof(struct squash_file *)); - squash_global_fdtable.nr = nr; - } - MUTEX_UNLOCK(&squash_global_mutex); - - // construct a handle (mainly) for win32 - handle = (int *)malloc(sizeof(int)); - if (NULL == handle) { - errno = ENOMEM; - goto failure; - } - *handle = fd; - file->payload = (void *)handle; - - // insert the fd into the global fd table - file->fd = fd; - MUTEX_LOCK(&squash_global_mutex); - squash_global_fdtable.fds[fd] = file; - if (squash_global_fdtable.end < fd + 1) { - squash_global_fdtable.end = fd + 1; - } - MUTEX_UNLOCK(&squash_global_mutex); - return fd; - -failure: - if (!errno) { - errno = ENOENT; - } - free(file); - return -1; -} - -int squash_open(sqfs *fs, const char *path) -{ - return squash_open_inner(fs, path, 1); -} - -int squash_close(int vfd) -{ - int ret; - struct squash_file *file; - - if (!SQUASH_VALID_VFD(vfd)) { - errno = EBADF; - return -1; - } - ret = close(vfd); - if (-1 == ret) { - return -1; - } - MUTEX_LOCK(&squash_global_mutex); - if (S_ISDIR(squash_global_fdtable.fds[vfd]->st.st_mode)) { - SQUASH_DIR *dir = (SQUASH_DIR *) (squash_global_fdtable.fds[vfd]->payload); - free(dir); - } else { - int *handle = (int *) (squash_global_fdtable.fds[vfd]->payload); - free(handle); - } - - file = squash_global_fdtable.fds[vfd]; - free(file->filename); - free(file); - - squash_global_fdtable.fds[vfd] = NULL; - if (vfd + 1 == squash_global_fdtable.end) { - while (vfd >= 0 && NULL == squash_global_fdtable.fds[vfd]) { - vfd -= 1; - } - squash_global_fdtable.end = vfd + 1; - } else { - assert(squash_global_fdtable.end > vfd + 1); - } - MUTEX_UNLOCK(&squash_global_mutex); - return 0; -} - -ssize_t squash_read(int vfd, void *buf, sqfs_off_t nbyte) -{ - sqfs_err error; - struct squash_file *file; - - if (!SQUASH_VALID_VFD(vfd)) - { - errno = EBADF; - goto failure; - } - file = squash_global_fdtable.fds[vfd]; - - error = sqfs_read_range(file->fs, &file->node, file->pos, &nbyte, buf); - if (SQFS_OK != error) - { - goto failure; - } - file->pos += nbyte; - return nbyte; -failure: - if (!errno) { - errno = EBADF; - } - return -1; -} - -off_t squash_lseek(int vfd, off_t offset, int whence) -{ - struct squash_file *file; - if (!SQUASH_VALID_VFD(vfd)) - { - errno = EBADF; - return -1; - } - file = squash_global_fdtable.fds[vfd]; - if (SQUASH_SEEK_SET == whence) - { - file->pos = offset; - } - else if (SQUASH_SEEK_CUR == whence) - { - file->pos += offset; - } - else if (SQUASH_SEEK_END == whence) - { - assert(S_ISREG(file->node.base.mode)); - file->pos = file->node.xtra.reg.file_size; - } - return file->pos; -} - -static void squash_halt() -{ - if (squash_global_fdtable.fds) { - free(squash_global_fdtable.fds); - } - MUTEX_DESTORY(&squash_global_mutex); - squash_extract_clear_cache(); -} - -sqfs_err squash_start() -{ - int ret; - squash_global_fdtable.nr = 0; - squash_global_fdtable.fds = NULL; - MUTEX_INIT(&squash_global_mutex); - ret = atexit(squash_halt); - if (0 == ret) { - return SQFS_OK; - } else { - return SQFS_ERR; - } -} - -struct squash_file * squash_find_entry(void *ptr) -{ - size_t i; - struct squash_file * ret = NULL; - MUTEX_LOCK(&squash_global_mutex); - for (i = 0; i < squash_global_fdtable.end; ++i) { - if (squash_global_fdtable.fds[i] && ptr == squash_global_fdtable.fds[i]->payload) { - ret = squash_global_fdtable.fds[i]; - break; - } - } - MUTEX_UNLOCK(&squash_global_mutex); - return ret; -} \ No newline at end of file diff --git a/ruby/squash_file.c b/ruby/squash_file.c deleted file mode 100644 index d680b5fcc..000000000 --- a/ruby/squash_file.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/file.h" - -#include "squash/fs.h" - -#include -#include - -sqfs_err sqfs_frag_entry(sqfs *fs, struct squashfs_fragment_entry *frag, - uint32_t idx) { - sqfs_err err = SQFS_OK; - - if (idx == SQUASHFS_INVALID_FRAG) - return SQFS_ERR; - - err = sqfs_table_get(&fs->frag_table, fs, idx, frag); - return err; -} - -sqfs_err sqfs_frag_block(sqfs *fs, sqfs_inode *inode, - size_t *offset, size_t *size, sqfs_block **block) { - struct squashfs_fragment_entry frag; - sqfs_err err = SQFS_OK; - - if (!S_ISREG(inode->base.mode)) - return SQFS_ERR; - - err = sqfs_frag_entry(fs, &frag, inode->xtra.reg.frag_idx); - if (err) - return err; - - err = sqfs_data_cache(fs, &fs->frag_cache, frag.start_block, - frag.size, block); - if (err) - return SQFS_ERR; - - *offset = inode->xtra.reg.frag_off; - *size = inode->xtra.reg.file_size % fs->sb->block_size; - return SQFS_OK; -} - -size_t sqfs_blocklist_count(sqfs *fs, sqfs_inode *inode) { - uint64_t size = inode->xtra.reg.file_size; - size_t block = fs->sb->block_size; - if (inode->xtra.reg.frag_idx == SQUASHFS_INVALID_FRAG) { - return sqfs_divceil(size, block); - } else { - return (size_t)(size / block); - } -} - -void sqfs_blocklist_init(sqfs *fs, sqfs_inode *inode, sqfs_blocklist *bl) { - bl->fs = fs; - bl->remain = sqfs_blocklist_count(fs, inode); - bl->cur = inode->next; - bl->started = 0; - bl->pos = 0; - bl->block = inode->xtra.reg.start_block; - bl->input_size = 0; -} - -sqfs_err sqfs_blocklist_next(sqfs_blocklist *bl) { - sqfs_err err = SQFS_OK; - short compressed; - - if (bl->remain == 0) - return SQFS_ERR; - --(bl->remain); - - err = sqfs_md_read(bl->fs, &bl->cur, &bl->header, - sizeof(bl->header)); - if (err) - return err; - - bl->block += bl->input_size; - sqfs_data_header(bl->header, &compressed, &bl->input_size); - - if (bl->started) - bl->pos += bl->fs->sb->block_size; - bl->started = 1; - - return SQFS_OK; -} - -sqfs_err sqfs_read_range(sqfs *fs, sqfs_inode *inode, sqfs_off_t start, - sqfs_off_t *size, void *buf) { - sqfs_err err = SQFS_OK; - - sqfs_off_t file_size; - size_t block_size; - sqfs_blocklist bl; - - size_t read_off; - char *buf_orig; - - if (!S_ISREG(inode->base.mode)) - return SQFS_ERR; - - file_size = inode->xtra.reg.file_size; - block_size = fs->sb->block_size; - - if (*size < 0 || start > file_size) - return SQFS_ERR; - if (start == file_size) { - *size = 0; - return SQFS_OK; - } - - err = sqfs_blockidx_blocklist(fs, inode, &bl, start); - if (err) - return err; - - read_off = start % block_size; - buf_orig = buf; - while (*size > 0) { - sqfs_block *block = NULL; - size_t data_off, data_size; - size_t take; - - short fragment = (bl.remain == 0); - if (fragment) { /* fragment */ - if (inode->xtra.reg.frag_idx == SQUASHFS_INVALID_FRAG) - break; - err = sqfs_frag_block(fs, inode, &data_off, &data_size, &block); - if (err) - return err; - } else { - if ((err = sqfs_blocklist_next(&bl))) - return err; - if (bl.pos + block_size <= start) - continue; - - data_off = 0; - if (bl.input_size == 0) { /* Hole! */ - data_size = (size_t)(file_size - bl.pos); - if (data_size > block_size) - data_size = block_size; - } else { - err = sqfs_data_cache(fs, &fs->data_cache, bl.block, - bl.header, &block); - if (err) - return err; - data_size = block->size; - } - } - - take = data_size - read_off; - if (take > *size) - take = (size_t)(*size); - if (block) { - memcpy(buf, (char*)block->data + data_off + read_off, take); - /* BLOCK CACHED, DON'T DISPOSE */ - } else { - memset(buf, 0, take); - } - read_off = 0; - *size -= take; - buf = (char*)buf + take; - - if (fragment) - break; - } - - *size = (char*)buf - buf_orig; - return *size ? SQFS_OK : SQFS_ERR; -} - - -/* -To read block N of a M-block file, we have to read N blocksizes from the, -metadata. This is a lot of work for large files! So for those files, we use -an index to speed it up. - -The M blocksizes are split between M / SQUASHFS_METADATA_SIZE MD-blocks. -For each of these blocks, we maintain in the index the location of the -MD-block, and the location of the data block corresponding to the start -of that MD-block. - -Then to read block N, we just calculate which metadata block index -("metablock") we want, and get that block-index entry. Then we -only need to read that one MD-block to seek within the file. -*/ - -/* Is a file worth indexing? */ -static short sqfs_blockidx_indexable(sqfs *fs, sqfs_inode *inode) { - size_t blocks = sqfs_blocklist_count(fs, inode); - size_t md_size = blocks * sizeof(sqfs_blocklist_entry); - return md_size >= SQUASHFS_METADATA_SIZE; -} - -static void sqfs_blockidx_dispose(void *data) { - free(*(sqfs_blockidx_entry**)data); -} - -sqfs_err sqfs_blockidx_init(sqfs_cache *cache) { - return sqfs_cache_init(cache, sizeof(sqfs_blockidx_entry**), - SQUASHFS_META_SLOTS, &sqfs_blockidx_dispose); -} - -/* Fill *out with all the block-index entries for this file */ -static sqfs_err sqfs_blockidx_add(sqfs *fs, sqfs_inode *inode, - sqfs_blockidx_entry **out) { - size_t blocks; /* Number of blocks in the file */ - size_t md_size; /* Amount of metadata necessary to hold the blocksizes */ - size_t count; /* Number of block-index entries necessary */ - - sqfs_blockidx_entry *blockidx; - sqfs_blocklist bl; - - /* For the cache */ - sqfs_cache_idx idx; - sqfs_blockidx_entry **cachep; - - size_t i = 0; - short first = 1; - - *out = NULL; - - blocks = sqfs_blocklist_count(fs, inode); - md_size = blocks * sizeof(sqfs_blocklist_entry); - count = (inode->next.offset + md_size - 1) - / SQUASHFS_METADATA_SIZE; - blockidx = malloc(count * sizeof(sqfs_blockidx_entry)); - if (!blockidx) - return SQFS_ERR; - - sqfs_blocklist_init(fs, inode, &bl); - while (bl.remain && i < count) { - sqfs_err err = SQFS_OK; - /* If the MD cursor offset is small, we found a new MD-block. - * Skip the first MD-block, because we already know where it is: - * inode->next.offset */ - if (bl.cur.offset < sizeof(sqfs_blocklist_entry) && !first) { - blockidx[i].data_block = bl.block + bl.input_size; - blockidx[i++].md_block = (uint32_t)(bl.cur.block - fs->sb->inode_table_start); - } - first = 0; - - err = sqfs_blocklist_next(&bl); - if (err) { - free(blockidx); - return SQFS_ERR; - } - } - - idx = inode->base.inode_number + 1; /* zero means invalid */ - cachep = sqfs_cache_add(&fs->blockidx, idx); - *out = *cachep = blockidx; - return SQFS_OK; -} - -sqfs_err sqfs_blockidx_blocklist(sqfs *fs, sqfs_inode *inode, sqfs_blocklist *bl, sqfs_off_t start) { - size_t block, metablock, skipped; - sqfs_blockidx_entry *blockidx, **bp; - sqfs_cache_idx idx; - sqfs_err ret; - - MUTEX_LOCK(&fs->blockidx.mutex); - - sqfs_blocklist_init(fs, inode, bl); - block = (size_t)(start / fs->sb->block_size); - if (block > bl->remain) { /* fragment */ - bl->remain = 0; - ret = SQFS_OK; - goto exit; - } - - /* How many MD-blocks do we want to skip? */ - metablock = (bl->cur.offset + block * sizeof(sqfs_blocklist_entry)) - / SQUASHFS_METADATA_SIZE; - if (metablock == 0) { - ret = SQFS_OK; /* no skip needed, don't want an index */ - goto exit; - } - if (!sqfs_blockidx_indexable(fs, inode)) { - ret = SQFS_OK; /* too small to index */ - goto exit; - } - - /* Get the index, creating it if necessary */ - idx = inode->base.inode_number + 1; /* zero means invalid index */ - if ((bp = sqfs_cache_get(&fs->blockidx, idx))) { - blockidx = *bp; - } else { - ret = sqfs_blockidx_add(fs, inode, &blockidx); - if (ret) { - goto exit; - } - } - - skipped = (metablock * SQUASHFS_METADATA_SIZE / sizeof(sqfs_blocklist_entry)) - - (bl->cur.offset / sizeof(sqfs_blocklist_entry)); - - blockidx += metablock - 1; - bl->cur.block = blockidx->md_block + fs->sb->inode_table_start; - bl->cur.offset %= sizeof(sqfs_blocklist_entry); - bl->remain -= skipped; - bl->pos = (uint64_t)skipped * fs->sb->block_size; - bl->block = blockidx->data_block; - ret = SQFS_OK; - -exit: - MUTEX_UNLOCK(&fs->blockidx.mutex); - return ret; -} - diff --git a/ruby/squash_fs.c b/ruby/squash_fs.c deleted file mode 100644 index d51ea265e..000000000 --- a/ruby/squash_fs.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/fs.h" - -#include "squash/file.h" - - -#include -#include - - - -#define DATA_CACHED_BLKS 1 -#define FRAG_CACHED_BLKS 3 - -void sqfs_version_supported(int *min_major, int *min_minor, int *max_major, - int *max_minor) { - *min_major = *max_major = SQUASHFS_MAJOR; - *min_minor = 0; - *max_minor = SQUASHFS_MINOR; -} - -void sqfs_version(sqfs *fs, int *major, int *minor) { - *major = fs->sb->s_major; - *minor = fs->sb->s_minor; -} - -sqfs_compression_type sqfs_compression(sqfs *fs) { - return fs->sb->compression; -} - -sqfs_err sqfs_init(sqfs *fs, sqfs_fd_t fd, size_t offset) { - sqfs_err err; - memset(fs, 0, sizeof(*fs)); - - fs->fd = fd; - fs->offset = offset; - - fs->sb = (struct squashfs_super_block *)(fd + fs->offset); - - if (fs->sb->s_magic != SQUASHFS_MAGIC) { - return SQFS_BADFORMAT; - } - if (fs->sb->s_major != SQUASHFS_MAJOR || fs->sb->s_minor > SQUASHFS_MINOR) - return SQFS_BADVERSION; - - if (!(fs->decompressor = sqfs_decompressor_get(fs->sb->compression))) - return SQFS_BADCOMP; - - err = sqfs_table_init(&fs->id_table, fd, fs->sb->id_table_start + fs->offset, - sizeof(uint32_t), fs->sb->no_ids); - err |= sqfs_table_init(&fs->frag_table, fd, fs->sb->fragment_table_start + fs->offset, - sizeof(struct squashfs_fragment_entry), fs->sb->fragments); - if (sqfs_export_ok(fs)) { - err |= sqfs_table_init(&fs->export_table, fd, fs->sb->lookup_table_start + fs->offset, - sizeof(uint64_t), fs->sb->inodes); - } - err |= sqfs_block_cache_init(&fs->md_cache, SQUASHFS_CACHED_BLKS); - err |= sqfs_block_cache_init(&fs->data_cache, DATA_CACHED_BLKS); - err |= sqfs_block_cache_init(&fs->frag_cache, FRAG_CACHED_BLKS); - err |= sqfs_blockidx_init(&fs->blockidx); - if (err) { - sqfs_destroy(fs); - return SQFS_ERR; - } - - return SQFS_OK; -} - -void sqfs_destroy(sqfs *fs) { - sqfs_table_destroy(&fs->id_table); - sqfs_table_destroy(&fs->frag_table); - if (sqfs_export_ok(fs)) - sqfs_table_destroy(&fs->export_table); - sqfs_cache_destroy(&fs->md_cache); - sqfs_cache_destroy(&fs->data_cache); - sqfs_cache_destroy(&fs->frag_cache); - sqfs_cache_destroy(&fs->blockidx); -} - -void sqfs_md_header(uint16_t hdr, short *compressed, uint16_t *size) { - *compressed = !(hdr & SQUASHFS_COMPRESSED_BIT); - *size = hdr & ~SQUASHFS_COMPRESSED_BIT; - if (!*size) - *size = SQUASHFS_COMPRESSED_BIT; -} - -void sqfs_data_header(uint32_t hdr, short *compressed, uint32_t *size) { - *compressed = !(hdr & SQUASHFS_COMPRESSED_BIT_BLOCK); - *size = hdr & ~SQUASHFS_COMPRESSED_BIT_BLOCK; -} - -sqfs_err sqfs_block_read(sqfs *fs, sqfs_off_t pos, short compressed, - uint32_t size, size_t outsize, sqfs_block **block) { - sqfs_err err = SQFS_ERR; - if (!(*block = malloc(sizeof(**block)))) - return SQFS_ERR; - - (*block)->data = (void *)((fs->fd) + (pos + fs->offset)); - (*block)->data_need_freeing = 0; - - if (compressed) { - char *decomp = malloc(outsize); - if (!decomp) - goto error; - - err = fs->decompressor((*block)->data, size, decomp, &outsize); - if (err) { - free(decomp); - goto error; - } - (*block)->data = decomp; - (*block)->size = outsize; - (*block)->data_need_freeing = 1; - } else { - (*block)->size = size; - } - - return SQFS_OK; - -error: - sqfs_block_dispose(*block); - *block = NULL; - return err; -} - -sqfs_err sqfs_md_block_read(sqfs *fs, sqfs_off_t pos, size_t *data_size, - sqfs_block **block) { - sqfs_err err; - uint16_t hdr; - short compressed; - uint16_t size; - - *data_size = 0; - - hdr = *(uint16_t *)(fs->fd + pos + fs->offset); - pos += sizeof(hdr); - *data_size += sizeof(hdr); - - sqfs_md_header(hdr, &compressed, &size); - - err = sqfs_block_read(fs, pos, compressed, size, - SQUASHFS_METADATA_SIZE, block); - *data_size += size; - return err; -} - -sqfs_err sqfs_data_block_read(sqfs *fs, sqfs_off_t pos, uint32_t hdr, - sqfs_block **block) { - short compressed; - uint32_t size; - sqfs_data_header(hdr, &compressed, &size); - return sqfs_block_read(fs, pos, compressed, size, - fs->sb->block_size, block); -} - -sqfs_err sqfs_md_cache(sqfs *fs, sqfs_off_t *pos, sqfs_block **block) { - sqfs_block_cache_entry *entry; - sqfs_err ret; - MUTEX_LOCK(&fs->md_cache.mutex); - - entry = sqfs_cache_get(&fs->md_cache, *pos); - if (!entry) { - entry = sqfs_cache_add(&fs->md_cache, *pos); - ret = sqfs_md_block_read(fs, *pos, &entry->data_size, &entry->block); - if (ret) { - goto exit; - } - } - *block = entry->block; - *pos += entry->data_size; - ret = SQFS_OK; -exit: - MUTEX_UNLOCK(&fs->md_cache.mutex); - return ret; -} - -sqfs_err sqfs_data_cache(sqfs *fs, sqfs_cache *cache, sqfs_off_t pos, - uint32_t hdr, sqfs_block **block) { - sqfs_block_cache_entry *entry; - sqfs_err ret; - MUTEX_LOCK(&cache->mutex); - - entry = sqfs_cache_get(cache, pos); - if (!entry) { - entry = sqfs_cache_add(cache, pos); - ret = sqfs_data_block_read(fs, pos, hdr, &entry->block); - if (ret) { - goto exit; - } - } - *block = entry->block; - ret = SQFS_OK; -exit: - MUTEX_UNLOCK(&cache->mutex); - return ret; -} - -void sqfs_block_dispose(sqfs_block *block) { - if (block->data_need_freeing) { - free(block->data); - } - free(block); -} - -void sqfs_md_cursor_inode(sqfs_md_cursor *cur, sqfs_inode_id id, sqfs_off_t base) { - cur->block = (id >> 16) + base; - cur->offset = id & 0xffff; -} - -sqfs_err sqfs_md_read(sqfs *fs, sqfs_md_cursor *cur, void *buf, size_t size) { - sqfs_off_t pos = cur->block; - while (size > 0) { - sqfs_block *block; - size_t take; - sqfs_err err = sqfs_md_cache(fs, &pos, &block); - if (err) - return err; - - take = block->size - cur->offset; - if (take > size) - take = size; - if (buf) - memcpy(buf, (char*)block->data + cur->offset, take); - /* BLOCK CACHED, DON'T DISPOSE */ - - if (buf) - buf = (char*)buf + take; - size -= take; - cur->offset += take; - if (cur->offset == block->size) { - cur->block = pos; - cur->offset = 0; - } - } - return SQFS_OK; -} - -size_t sqfs_divceil(uint64_t total, size_t group) { - size_t q = (size_t)(total / group); - if (total % group) - q += 1; - return q; -} - -sqfs_err sqfs_id_get(sqfs *fs, uint16_t idx, sqfs_id_t *id) { - uint32_t rid; - sqfs_err err = sqfs_table_get(&fs->id_table, fs, idx, &rid); - if (err) - return err; - *id = (sqfs_id_t)rid; - return SQFS_OK; -} - -sqfs_err sqfs_readlink(sqfs *fs, sqfs_inode *inode, char *buf, size_t *size) { - size_t want; - sqfs_md_cursor cur; - sqfs_err err; - if (!S_ISLNK(inode->base.mode)) - return SQFS_ERR; - - want = inode->xtra.symlink_size; - if (!buf) { - *size = want + 1; - return SQFS_OK; - } - - if (want > *size - 1) - want = *size - 1; - cur = inode->next; - err = sqfs_md_read(fs, &cur, buf, want); - buf[want] = '\0'; - return err; -} - -int sqfs_export_ok(sqfs *fs) { - return fs->sb->lookup_table_start != SQUASHFS_INVALID_BLK; -} - -sqfs_err sqfs_export_inode(sqfs *fs, sqfs_inode_num n, sqfs_inode_id *i) { - uint64_t r; - sqfs_err err; - - if (!sqfs_export_ok(fs)) - return SQFS_UNSUP; - - err = sqfs_table_get(&fs->export_table, fs, n - 1, &r); - if (err) - return err; - *i = r; - return SQFS_OK; -} - -sqfs_inode_id sqfs_inode_root(sqfs *fs) { - return fs->sb->root_inode; -} - -/* Turn the internal format of a device number to our system's dev_t - * It looks like rdev is just what the Linux kernel uses: 20 bit minor, - * split in two around a 12 bit major - */ -static void sqfs_decode_dev(sqfs_inode *i, uint32_t rdev) { - i->xtra.dev.major = (rdev >> 8) & 0xfff; - i->xtra.dev.minor = (rdev & 0xff) | ((rdev >> 12) & 0xfff00); -} - -#define INODE_TYPE(_type) \ - struct squashfs_##_type##_inode x; \ - err = sqfs_md_read(fs, &inode->next, &x, sizeof(x)); \ - if (err) return err - -sqfs_err sqfs_inode_get(sqfs *fs, sqfs_inode *inode, sqfs_inode_id id) { - sqfs_md_cursor cur; - sqfs_err err; - - memset(inode, 0, sizeof(*inode)); - - sqfs_md_cursor_inode(&cur, id, fs->sb->inode_table_start); - inode->next = cur; - - err = sqfs_md_read(fs, &cur, &inode->base, sizeof(inode->base)); - if (err) - return err; - - inode->base.mode |= sqfs_mode(inode->base.inode_type); - switch (inode->base.inode_type) { - case SQUASHFS_REG_TYPE: { - INODE_TYPE(reg); - inode->nlink = 1; - inode->xtra.reg.start_block = x.start_block; - inode->xtra.reg.file_size = x.file_size; - inode->xtra.reg.frag_idx = x.fragment; - inode->xtra.reg.frag_off = x.offset; - break; - } - case SQUASHFS_LREG_TYPE: { - INODE_TYPE(lreg); - inode->nlink = x.nlink; - inode->xtra.reg.start_block = x.start_block; - inode->xtra.reg.file_size = x.file_size; - inode->xtra.reg.frag_idx = x.fragment; - inode->xtra.reg.frag_off = x.offset; - break; - } - case SQUASHFS_DIR_TYPE: { - INODE_TYPE(dir); - inode->nlink = x.nlink; - inode->xtra.dir.start_block = x.start_block; - inode->xtra.dir.offset = x.offset; - inode->xtra.dir.dir_size = x.file_size; - inode->xtra.dir.idx_count = 0; - inode->xtra.dir.parent_inode = x.parent_inode; - break; - } - case SQUASHFS_LDIR_TYPE: { - INODE_TYPE(ldir); - inode->nlink = x.nlink; - inode->xtra.dir.start_block = x.start_block; - inode->xtra.dir.offset = x.offset; - inode->xtra.dir.dir_size = x.file_size; - inode->xtra.dir.idx_count = x.i_count; - inode->xtra.dir.parent_inode = x.parent_inode; - break; - } - case SQUASHFS_SYMLINK_TYPE: - case SQUASHFS_LSYMLINK_TYPE: { - INODE_TYPE(symlink); - inode->nlink = x.nlink; - inode->xtra.symlink_size = x.symlink_size; - - if (inode->base.inode_type == SQUASHFS_LSYMLINK_TYPE) { - /* skip symlink target */ - cur = inode->next; - err = sqfs_md_read(fs, &cur, NULL, inode->xtra.symlink_size); - if (err) - return err; - } - break; - } - case SQUASHFS_BLKDEV_TYPE: - case SQUASHFS_CHRDEV_TYPE: { - INODE_TYPE(dev); - inode->nlink = x.nlink; - sqfs_decode_dev(inode, x.rdev); - break; - } - case SQUASHFS_LBLKDEV_TYPE: - case SQUASHFS_LCHRDEV_TYPE: { - INODE_TYPE(ldev); - inode->nlink = x.nlink; - sqfs_decode_dev(inode, x.rdev); - break; - } - case SQUASHFS_SOCKET_TYPE: - case SQUASHFS_FIFO_TYPE: { - INODE_TYPE(ipc); - inode->nlink = x.nlink; - break; - } - case SQUASHFS_LSOCKET_TYPE: - case SQUASHFS_LFIFO_TYPE: { - INODE_TYPE(lipc); - inode->nlink = x.nlink; - break; - } - - default: return SQFS_ERR; - } - - return SQFS_OK; -} -#undef INODE_TYPE diff --git a/ruby/squash_hash.c b/ruby/squash_hash.c deleted file mode 100644 index 2996a24d0..000000000 --- a/ruby/squash_hash.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/hash.h" - -#include -#include - -static sqfs_err sqfs_hash_add_internal(sqfs_hash *h, int doubling, - sqfs_hash_key k, sqfs_hash_value v) { - size_t hash = (k & (h->capacity - 1)); - sqfs_hash_bucket *b = malloc(sizeof(sqfs_hash_bucket) + h->value_size); - if (!b) - return SQFS_ERR; - b->key = k; - memcpy(&b->value, v, h->value_size); - b->next = h->buckets[hash]; - h->buckets[hash] = b; - ++h->size; - - return SQFS_OK; -} - -static sqfs_err sqfs_hash_double(sqfs_hash *h) { - sqfs_hash_bucket **ob = h->buckets; - size_t oc = h->capacity; - size_t i; - sqfs_err err; - - if ((err = sqfs_hash_init(h, h->value_size, oc * 2))) - return err; - - for (i = 0; i < oc; ++i) { - sqfs_hash_bucket *b = ob[i]; - while (b) { - sqfs_hash_bucket *n; - if (!err) - err = sqfs_hash_add_internal(h, 1, b->key, &b->value); - n = b->next; - free(b); - b = n; - } - } - - free(ob); - return err; -} - -sqfs_err sqfs_hash_init(sqfs_hash *h, size_t vsize, size_t initial) { - memset(h, 0, sizeof(*h)); - if ((initial & (initial - 1))) /* not power of two? */ - return SQFS_ERR; - - h->buckets = calloc(initial, sizeof(sqfs_hash_bucket*)); - if (!h->buckets) - return SQFS_ERR; - h->capacity = initial; - h->size = 0; - h->value_size = vsize; - return SQFS_OK; -} - -void sqfs_hash_destroy(sqfs_hash *h) { - size_t i; - for (i = 0; i < h->capacity; ++i) { - sqfs_hash_bucket *b = h->buckets[i]; - while (b) { - sqfs_hash_bucket *n = b->next; - free(b); - b = n; - } - } - free(h->buckets); -} - -sqfs_hash_value sqfs_hash_get(sqfs_hash *h, sqfs_hash_key k) { - size_t hash = (k & (h->capacity - 1)); - sqfs_hash_bucket *b = h->buckets[hash]; - while (b) { - if (b->key == k) - return &b->value; - b = b->next; - } - return NULL; -} - -sqfs_err sqfs_hash_add(sqfs_hash *h, sqfs_hash_key k, sqfs_hash_value v) { - if (h->size >= h->capacity) { - sqfs_err err = sqfs_hash_double(h); - if (err) - return err; - } - return sqfs_hash_add_internal(h, 0, k, v); -} - -sqfs_err sqfs_hash_remove(sqfs_hash *h, sqfs_hash_key k) { - size_t hash = (k & (h->capacity - 1)); - sqfs_hash_bucket **bp = &h->buckets[hash]; - while (*bp) { - if ((*bp)->key == k) { - sqfs_hash_bucket *b = *bp; - *bp = b->next; - free(b); - --h->size; - return SQFS_OK; - } - bp = &(*bp)->next; - } - return SQFS_OK; -} diff --git a/ruby/squash_mutex.c b/ruby/squash_mutex.c deleted file mode 100644 index c113bc180..000000000 --- a/ruby/squash_mutex.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash/mutex.h" - - -int MUTEX_INIT(MUTEX *mutex) -{ - -#ifdef _WIN32 - *mutex = CreateMutex(0, FALSE, 0); - return (*mutex==0); -#else - return pthread_mutex_init(mutex, NULL); -#endif - -} - -int MUTEX_LOCK(MUTEX *mutex) -{ -#ifdef _WIN32 - return (WaitForSingleObject(*mutex, INFINITE)==WAIT_FAILED?1:0); -#else - return pthread_mutex_lock(mutex); -#endif -} - -int MUTEX_UNLOCK(MUTEX *mutex) -{ -#ifdef _WIN32 - return (ReleaseMutex(*mutex)==0); -#else - return pthread_mutex_unlock(mutex); -#endif -} - -int MUTEX_DESTORY(MUTEX *mutex) -{ -#ifdef _WIN32 - return CloseHandle(*mutex); -#else - return pthread_mutex_destroy(mutex); -#endif -} diff --git a/ruby/squash_nonstd-makedev.c b/ruby/squash_nonstd-makedev.c deleted file mode 100644 index d5c2d380d..000000000 --- a/ruby/squash_nonstd-makedev.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#ifdef __linux__ - #include -#endif - -#include "squash/common.h" - -dev_t sqfs_makedev(int maj, int min) { - return makedev(maj, min); -} diff --git a/ruby/squash_nonstd-stat.c b/ruby/squash_nonstd-stat.c deleted file mode 100644 index 31552971b..000000000 --- a/ruby/squash_nonstd-stat.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "squash/common.h" -#include "squash/squashfs_fs.h" - -/* S_IF* are not standard */ -sqfs_mode_t sqfs_mode(int inode_type) { - switch (inode_type) { - case SQUASHFS_DIR_TYPE: - case SQUASHFS_LDIR_TYPE: - return S_IFDIR; - case SQUASHFS_REG_TYPE: - case SQUASHFS_LREG_TYPE: - return S_IFREG; - case SQUASHFS_SYMLINK_TYPE: - case SQUASHFS_LSYMLINK_TYPE: - return S_IFLNK; - case SQUASHFS_BLKDEV_TYPE: - case SQUASHFS_LBLKDEV_TYPE: - return S_IFBLK; - case SQUASHFS_CHRDEV_TYPE: - case SQUASHFS_LCHRDEV_TYPE: - return S_IFCHR; - case SQUASHFS_FIFO_TYPE: - case SQUASHFS_LFIFO_TYPE: - return S_IFIFO; - case SQUASHFS_SOCKET_TYPE: - case SQUASHFS_LSOCKET_TYPE: - return S_IFSOCK; - } - return 0; -} - diff --git a/ruby/squash_private.c b/ruby/squash_private.c deleted file mode 100644 index c87bea1d4..000000000 --- a/ruby/squash_private.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/private.h" - - -#include "squash/nonstd.h" - -sqfs_err sqfs_stat(sqfs *fs, sqfs_inode *inode, struct stat *st) { - memset(st, 0, sizeof(*st)); - st->st_mode = inode->base.mode; - st->st_nlink = inode->nlink; - st->st_mtime = st->st_ctime = st->st_atime = inode->base.mtime; - - if (S_ISREG(st->st_mode)) { - /* FIXME: do symlinks, dirs, etc have a size? */ - st->st_size = inode->xtra.reg.file_size; - } else if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) { - st->st_rdev = sqfs_makedev(inode->xtra.dev.major, - inode->xtra.dev.minor); - } else if (S_ISLNK(st->st_mode)) { - st->st_size = inode->xtra.symlink_size; - } - - return SQFS_OK; -} diff --git a/ruby/squash_readlink.c b/ruby/squash_readlink.c deleted file mode 100644 index 2f2d26642..000000000 --- a/ruby/squash_readlink.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" - -ssize_t squash_readlink_inode(sqfs *fs, sqfs_inode *node, char *buf, size_t bufsize) { - sqfs_err error; - size_t want = 0; - sqfs_md_cursor cur; - - if (!S_ISLNK(node->base.mode)) { - errno = EINVAL; - return -1; - } - - want = node->xtra.symlink_size; - - if (want > bufsize - 1) { - errno = ENAMETOOLONG; - return -1; //bufsize is too small - } - else if (want == 0) { - errno = EBADF; - return -1; - } - cur = node->next; - error = sqfs_md_read(fs, &cur, buf, want); - if (SQFS_OK != error) { - errno = EIO; - return -1; - } - buf[want] = '\0'; - if (fs->root_alias && - strlen(buf) >= strlen(fs->root_alias) && - buf == strstr(buf, fs->root_alias)) { - char *buf_ptr = buf + strlen(fs->root_alias) - 1; - assert('/' == buf_ptr[0]); // still is Absolute Path - memmove(buf, buf_ptr, strlen(buf_ptr) + 1); - want = strlen(buf); - } else if (fs->root_alias2 && - strlen(buf) >= strlen(fs->root_alias2) && - buf == strstr(buf, fs->root_alias2)) { - char *buf_ptr = buf + strlen(fs->root_alias2) - 1; - assert('/' == buf_ptr[0]); // still is Absolute Path - memmove(buf, buf_ptr, strlen(buf_ptr) + 1); - want = strlen(buf); - } - return want; -} - -ssize_t squash_readlink(sqfs *fs, const char *path, char *buf, size_t bufsize) { - sqfs_err error; - sqfs_inode node; - short found; - - assert(buf && path && fs); - memset(&node, 0, sizeof(sqfs_inode)); - - found = 0; - - error = sqfs_inode_get(fs, &node, sqfs_inode_root(fs)); - if (SQFS_OK != error) - goto failure; - error = sqfs_lookup_path(fs, &node, path, &found); - if (SQFS_OK != error) - goto failure; - - if (found) { - return squash_readlink_inode(fs, &node, buf, bufsize); - } else { - errno = ENOENT; - goto failure; - } - -failure: - if (!errno) { - errno = ENOENT; - } - return -1; -} diff --git a/ruby/squash_scandir.c b/ruby/squash_scandir.c deleted file mode 100644 index 3fddff1b7..000000000 --- a/ruby/squash_scandir.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" -#include - - -typedef int(*qsort_compar)(const void *, const void *); - -int squash_scandir(sqfs *fs, const char *dirname, struct SQUASH_DIRENT ***namelist, - int (*select)(const struct SQUASH_DIRENT *), - int (*compar)(const struct SQUASH_DIRENT **, const struct SQUASH_DIRENT **)) -{ - SQUASH_DIR * openeddir = 0; - size_t n = 0; - struct SQUASH_DIRENT **list = NULL; - struct SQUASH_DIRENT *ent = 0 ,*p = 0; - - if((dirname == NULL) || (namelist == NULL)) - return -1; - - openeddir = squash_opendir(fs, dirname); - if(openeddir == NULL) - return -1; - - - list = (struct SQUASH_DIRENT **)malloc(MAX_DIR_ENT*sizeof(struct SQUASH_DIRENT *)); - - - while(( ent = squash_readdir(openeddir)) != NULL) - { - if( select && !select(ent)) - continue; - - p = (struct SQUASH_DIRENT *)malloc(sizeof(struct SQUASH_DIRENT)); - - memcpy((void *)p,(void *)ent,sizeof(struct SQUASH_DIRENT)); - list[n] = p; - - n++; - if(n >= MAX_DIR_ENT) - break; - - } - - //close the squash_dir - squash_closedir(openeddir); - - //realloc the array - *namelist = realloc((void *)list,n*sizeof(struct SQUASH_DIRENT *)); - if(*namelist == NULL) - *namelist = list; - - - //sort the array - if(compar) - qsort((void *)*namelist,n,sizeof(struct SQUASH_DIRENT *),(qsort_compar)compar); - - return n; - -} \ No newline at end of file diff --git a/ruby/squash_stack.c b/ruby/squash_stack.c deleted file mode 100644 index fe748c390..000000000 --- a/ruby/squash_stack.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/stack.h" - -#include - -/* Ensure a capacity of cap */ -static sqfs_err sqfs_stack_capacity(sqfs_stack *s, size_t cap) { - char *items; - if (cap <= s->capacity) - return SQFS_OK; - - items = realloc(s->items, cap * s->value_size); - if (!items) - return SQFS_ERR; - - s->items = items; - s->capacity = cap; - return SQFS_OK; -} - -/* Calculate the next capacity to use */ -#define CAPACITY_DEFAULT 8 -#define CAPACITY_RATIO 3 / 2 -static size_t sqfs_stack_next_capacity(size_t cap) { - size_t n; - - if (cap == 0) - return CAPACITY_DEFAULT; - - n = cap * CAPACITY_RATIO; - if (n <= cap) - return cap + 1; - return n; -} - -/* Grow by one */ -static sqfs_err sqfs_stack_grow(sqfs_stack *s) { - if (s->size == s->capacity) { - sqfs_err err = sqfs_stack_capacity(s, - sqfs_stack_next_capacity(s->capacity)); - if (err) - return err; - } - s->size++; - return SQFS_OK; -} - - -sqfs_err sqfs_stack_create(sqfs_stack *s, size_t vsize, size_t initial, - sqfs_stack_free_t freer) { - s->value_size = vsize; - s->freer = freer; - s->items = NULL; - s->capacity = s->size = 0; - return sqfs_stack_capacity(s, initial); -} - -void sqfs_stack_init(sqfs_stack *s) { - s->items = NULL; - s->capacity = 0; -} - -void sqfs_stack_destroy(sqfs_stack *s) { - while (sqfs_stack_pop(s)) - ; /* pass */ - free(s->items); - sqfs_stack_init(s); -} - -sqfs_err sqfs_stack_push(sqfs_stack *s, void *vout) { - sqfs_err err = sqfs_stack_grow(s); - if (err) - return err; - return sqfs_stack_top(s, vout); -} - -short sqfs_stack_pop(sqfs_stack *s) { - void *v; - - if (s->size == 0) - return 0; - - sqfs_stack_top(s, &v); - if (s->freer) - s->freer(v); - s->size--; - return 1; -} - -size_t sqfs_stack_size(sqfs_stack *s) { - return s->size; -} - -sqfs_err sqfs_stack_at(sqfs_stack *s, size_t i, void *vout) { - if (i >= s->size) - return SQFS_ERR; - - *(void**)vout = s->items + i * s->value_size; - return SQFS_OK; -} - -sqfs_err sqfs_stack_top(sqfs_stack *s, void *vout) { - if (s->size == 0) - return SQFS_ERR; - - return sqfs_stack_at(s, s->size - 1, vout); -} diff --git a/ruby/squash_stat.c b/ruby/squash_stat.c deleted file mode 100644 index f1acba619..000000000 --- a/ruby/squash_stat.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2017 - 2020 Minqi Pan - * Shengyuan Liu - * - * This file is part of libsquash, distributed under the MIT License - * For full terms see the included LICENSE file - */ - -#include "squash.h" - -int squash_stat(sqfs *fs, const char *path, struct stat *buf) -{ - sqfs_err error; - sqfs_inode node; - short found; - - error = sqfs_inode_get(fs, &node, sqfs_inode_root(fs)); - if (SQFS_OK != error) { - goto failure; - } - error = sqfs_lookup_path_inner(fs, &node, path, &found, 1); - if (SQFS_OK != error) { - goto failure; - } - if (!found) { - errno = ENOENT; - goto failure; - } - error = sqfs_stat(fs, &node, buf); - if (SQFS_OK != error) { - goto failure; - } - - return 0; -failure: - if (!errno) { - errno = ENOENT; - } - return -1; -} - -int squash_lstat(sqfs *fs, const char *path, struct stat *buf) -{ - sqfs_err error; - sqfs_inode node; - short found; - - error = sqfs_inode_get(fs, &node, sqfs_inode_root(fs)); - if (SQFS_OK != error) { - goto failure; - } - error = sqfs_lookup_path(fs, &node, path, &found); - if (SQFS_OK != error) { - goto failure; - } - if (!found) { - errno = ENOENT; - goto failure; - } - error = sqfs_stat(fs, &node, buf); - if (SQFS_OK != error) { - goto failure; - } - - return 0; -failure: - if (!errno) { - errno = ENOENT; - } - return -1; -} - -int squash_fstat(int vfd, struct stat *buf) -{ - if (!SQUASH_VALID_VFD(vfd)) - { - errno = EBADF; - return -1; - } - *buf = SQUASH_VFD_FILE(vfd)->st; - return 0; -} diff --git a/ruby/squash_table.c b/ruby/squash_table.c deleted file mode 100644 index e4fbd5cd3..000000000 --- a/ruby/squash_table.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/table.h" - -#include "squash/fs.h" - -#include - -sqfs_err sqfs_table_init(sqfs_table *table, sqfs_fd_t fd, sqfs_off_t start, size_t each, - size_t count) { - //size_t nblocks, bread; - - if (count == 0) - return SQFS_OK; - - //nblocks = sqfs_divceil(each * count, SQUASHFS_METADATA_SIZE); - - //unused - //bread = nblocks * sizeof(uint64_t); - - table->each = each; - table->blocks = (uint64_t *)(fd + start); - - return SQFS_OK; -} - -void sqfs_table_destroy(sqfs_table *table) { - table->blocks = NULL; -} - -sqfs_err sqfs_table_get(sqfs_table *table, sqfs *fs, size_t idx, void *buf) { - sqfs_block *block; - size_t pos = idx * table->each; - size_t bnum = pos / SQUASHFS_METADATA_SIZE, - off = pos % SQUASHFS_METADATA_SIZE; - - sqfs_off_t bpos = table->blocks[bnum]; - if (sqfs_md_cache(fs, &bpos, &block)) - return SQFS_ERR; - - memcpy(buf, (char*)(block->data) + off, table->each); - /* BLOCK CACHED, DON'T DISPOSE */ - return SQFS_OK; -} diff --git a/ruby/squash_traverse.c b/ruby/squash_traverse.c deleted file mode 100644 index 012d98b9a..000000000 --- a/ruby/squash_traverse.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/traverse.h" - -#include "squash/fs.h" - -#include -#include - - -#define TRAVERSE_PATH_SEPARATOR "/" - -/* Default initial capacity of trv.path */ -#define TRAVERSE_DEFAULT_PATH_CAP 32 - - -enum { - /* These states may be set on entry to sqfs_traverse_next(), with real - work to do. */ - TRAVERSE_DESCEND, /* Descend into the current entry (a dir) */ - TRAVERSE_NAME_REMOVE, /* Remove the name from the end of the stored path */ - - /* End states */ - TRAVERSE_ERROR, - TRAVERSE_FINISHED, - - /* Internal */ - TRAVERSE_ASCEND, /* Done with a directory, ascend a level */ - TRAVERSE_NAME_ADD, /* Add a name to the end of the stored path */ - TRAVERSE_GET_ENTRY /* Get the next entry at the same level */ -} sqfs_traverse_state; - -/* The struct stored in trv.stack */ -typedef struct { - sqfs_dir dir; - size_t name_size; -} sqfs_traverse_level; - - -/* Make our structure safe */ -static void sqfs_traverse_init(sqfs_traverse *trv); - -/* Path manipulation functions */ -static sqfs_err sqfs_traverse_path_init(sqfs_traverse *trv); -static sqfs_err sqfs_traverse_path_add(sqfs_traverse *trv, - const char *str, size_t size); -static sqfs_err sqfs_traverse_path_add_name(sqfs_traverse *trv); -static sqfs_err sqfs_traverse_path_add_sep(sqfs_traverse *trv); -static void sqfs_traverse_path_remove(sqfs_traverse *trv, size_t size); -static void sqfs_traverse_path_remove_name(sqfs_traverse *trv); -static void sqfs_traverse_path_remove_sep(sqfs_traverse *trv); -/* Set the size of the last path component */ -static void sqfs_traverse_path_set_name_size(sqfs_traverse *trv, size_t size); -/* Add nul-terminator */ -static void sqfs_traverse_path_terminate(sqfs_traverse *trv); - -/* Descend into new directories, and ascend back */ -static sqfs_err sqfs_traverse_descend_inode(sqfs_traverse *trv, - sqfs_inode *inode); -static sqfs_err sqfs_traverse_descend(sqfs_traverse *trv, sqfs_inode_id iid); -static sqfs_err sqfs_traverse_ascend(sqfs_traverse *trv); - - -static void sqfs_traverse_init(sqfs_traverse *trv) { - sqfs_dentry_init(&trv->entry, trv->namebuf); - sqfs_stack_init(&trv->stack); - trv->state = TRAVERSE_ERROR; - trv->path = NULL; -} - -sqfs_err sqfs_traverse_open_inode(sqfs_traverse *trv, sqfs *fs, - sqfs_inode *inode) { - sqfs_err err; - - sqfs_traverse_init(trv); - if ((err = sqfs_traverse_path_init(trv))) - goto error; - err = sqfs_stack_create(&trv->stack, sizeof(sqfs_traverse_level), 0, NULL); - if (err) - goto error; - - trv->fs = fs; - if ((err = sqfs_traverse_descend_inode(trv, inode))) - goto error; - - sqfs_traverse_path_set_name_size(trv, 0); /* The root has no name */ - trv->state = TRAVERSE_NAME_REMOVE; - return SQFS_OK; - -error: - sqfs_traverse_close(trv); - return err; -} - -sqfs_err sqfs_traverse_open(sqfs_traverse *trv, sqfs *fs, sqfs_inode_id iid) { - sqfs_err err; - sqfs_inode inode; - - if ((err = sqfs_inode_get(fs, &inode, iid))) - return err; - - return sqfs_traverse_open_inode(trv, fs, &inode); -} - -void sqfs_traverse_close(sqfs_traverse *trv) { - sqfs_stack_destroy(&trv->stack); - free(trv->path); - sqfs_traverse_init(trv); -} - - -short sqfs_traverse_next(sqfs_traverse *trv, sqfs_err *err) { - sqfs_traverse_level *level; - short found; - - *err = SQFS_OK; - while (1) { - switch (trv->state) { - case TRAVERSE_GET_ENTRY: - if ((*err = sqfs_stack_top(&trv->stack, &level))) - goto error; - - found = sqfs_dir_next(trv->fs, &level->dir, &trv->entry, err); - if (*err) - goto error; - if (found) - trv->state = TRAVERSE_NAME_ADD; - else - trv->state = TRAVERSE_ASCEND; - break; - - case TRAVERSE_NAME_ADD: - if ((*err = sqfs_traverse_path_add_name(trv))) - goto error; - if (sqfs_dentry_is_dir(&trv->entry)) - trv->state = TRAVERSE_DESCEND; - else - trv->state = TRAVERSE_NAME_REMOVE; - trv->dir_end = 0; - return 1; - - case TRAVERSE_NAME_REMOVE: - sqfs_traverse_path_remove_name(trv); - trv->state = TRAVERSE_GET_ENTRY; - break; - - case TRAVERSE_DESCEND: - *err = sqfs_traverse_descend(trv, sqfs_dentry_inode(&trv->entry)); - if (*err) - goto error; - trv->state = TRAVERSE_GET_ENTRY; - break; - - case TRAVERSE_ASCEND: - if ((*err = sqfs_traverse_ascend(trv))) - goto error; - if (sqfs_stack_size(&trv->stack) > 0) { - trv->dir_end = 1; - trv->state = TRAVERSE_NAME_REMOVE; - return 1; - } - trv->state = TRAVERSE_FINISHED; - break; - - case TRAVERSE_FINISHED: - return 0; - - case TRAVERSE_ERROR: - *err = SQFS_ERR; - goto error; - } - } - -error: - trv->state = TRAVERSE_ERROR; - return 0; -} - -sqfs_err sqfs_traverse_prune(sqfs_traverse *trv) { - trv->state = TRAVERSE_NAME_REMOVE; - return SQFS_OK; -} - - -static sqfs_err sqfs_traverse_path_init(sqfs_traverse *trv) { - trv->path_cap = TRAVERSE_DEFAULT_PATH_CAP; - if (!(trv->path = malloc(trv->path_cap))) - return SQFS_ERR; - trv->path[0] = '\0'; - trv->path_size = 1; /* includes nul-terminator */ - return SQFS_OK; -} - -static void sqfs_traverse_path_terminate(sqfs_traverse *trv) { - trv->path[trv->path_size - 1] = '\0'; -} - -static sqfs_err sqfs_traverse_path_add(sqfs_traverse *trv, - const char *str, size_t size) { - size_t need = trv->path_size + size; - if (need > trv->path_cap) { - char *next_path; - size_t next_cap = trv->path_cap; - while (need > next_cap) - next_cap *= 2; - - if (!(next_path = realloc(trv->path, next_cap))) - return SQFS_ERR; - - trv->path = next_path; - trv->path_cap = next_cap; - } - - memcpy(trv->path + trv->path_size - 1, str, size); - trv->path_size = need; - sqfs_traverse_path_terminate(trv); - return SQFS_OK; -} - -static void sqfs_traverse_path_remove(sqfs_traverse *trv, size_t size) { - if (trv->path_size > size) - trv->path_size -= size; - else - trv->path_size = 1; /* only nul terminator left */ - - sqfs_traverse_path_terminate(trv); -} - -static sqfs_err sqfs_traverse_path_add_name(sqfs_traverse *trv) { - trv->path_last_size = sqfs_dentry_name_size(&trv->entry); - return sqfs_traverse_path_add(trv, sqfs_dentry_name(&trv->entry), - trv->path_last_size); -} - -static sqfs_err sqfs_traverse_path_add_sep(sqfs_traverse *trv) { - return sqfs_traverse_path_add(trv, TRAVERSE_PATH_SEPARATOR, - strlen(TRAVERSE_PATH_SEPARATOR)); -} - -static void sqfs_traverse_path_remove_name(sqfs_traverse *trv) { - sqfs_traverse_path_remove(trv, trv->path_last_size); -} - -static void sqfs_traverse_path_remove_sep(sqfs_traverse *trv) { - sqfs_traverse_path_remove(trv, strlen(TRAVERSE_PATH_SEPARATOR)); -} - -static void sqfs_traverse_path_set_name_size(sqfs_traverse *trv, size_t size) { - trv->path_last_size = size; -} - - -static sqfs_err sqfs_traverse_descend_inode(sqfs_traverse *trv, - sqfs_inode *inode) { - sqfs_err err; - sqfs_traverse_level *level; - short initial; - - initial = (sqfs_stack_size(&trv->stack) == 0); - - if ((err = sqfs_stack_push(&trv->stack, &level))) - return err; - if ((err = sqfs_dir_open(trv->fs, inode, &level->dir, 0))) - return err; - - if (initial) { - /* Don't add the separator or store the size for the root directory */ - level->name_size = 0; - } else { - level->name_size = sqfs_dentry_name_size(&trv->entry); - if ((err = sqfs_traverse_path_add_sep(trv))) - return err; - } - - return err; -} - -static sqfs_err sqfs_traverse_descend(sqfs_traverse *trv, sqfs_inode_id iid) { - sqfs_err err; - sqfs_inode inode; - - if ((err = sqfs_inode_get(trv->fs, &inode, iid))) - return err; - - return sqfs_traverse_descend_inode(trv, &inode); -} - -static sqfs_err sqfs_traverse_ascend(sqfs_traverse *trv) { - sqfs_err err; - sqfs_traverse_level *level; - - if ((err = sqfs_stack_top(&trv->stack, &level))) - return err; - - sqfs_traverse_path_remove_sep(trv); /* safe even if initial */ - sqfs_traverse_path_set_name_size(trv, level->name_size); - - sqfs_stack_pop(&trv->stack); - return SQFS_OK; -} diff --git a/ruby/squash_util.c b/ruby/squash_util.c deleted file mode 100644 index ebccdb976..000000000 --- a/ruby/squash_util.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2014 Dave Vasilevsky - * 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(S) ``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(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "squash/util.h" - -#include "squash/fs.h" - -#include - -sqfs_err sqfs_fd_open(const uint8_t *path, sqfs_fd_t *fd) { - *fd = path; - return SQFS_OK; -} - -void sqfs_fd_close(sqfs_fd_t fd) { - // do nothing -} - - -/* TODO: WIN32 implementation of open/close */ -/* TODO: i18n of error messages */ -sqfs_err sqfs_open_image(sqfs *fs, const uint8_t *image, size_t offset) { - sqfs_err err; - sqfs_fd_t fd; - - if ((err = sqfs_fd_open(image, &fd))) - return err; - - err = sqfs_init(fs, fd, offset); - switch (err) { - case SQFS_OK: - break; - case SQFS_BADFORMAT: - fprintf(stderr, "This doesn't look like a squashfs image.\n"); - break; - case SQFS_BADVERSION: { - int major, minor, mj1, mn1, mj2, mn2; - sqfs_version(fs, &major, &minor); - sqfs_version_supported(&mj1, &mn1, &mj2, &mn2); - fprintf(stderr, "Squashfs version %d.%d detected, only version", - major, minor); - if (mj1 == mj2 && mn1 == mn2) - fprintf(stderr, " %d.%d", mj1, mn1); - else - fprintf(stderr, "s %d.%d to %d.%d", mj1, mn1, mj2, mn2); - fprintf(stderr, " supported.\n"); - break; - } - case SQFS_BADCOMP: { - fprintf(stderr, "Squashfs image uses ? compression"); - fprintf(stderr, ".\n"); - break; - } - default: - fprintf(stderr, "Something went wrong trying to read the squashfs " - "image.\n"); - } - - if (err) - sqfs_fd_close(fd); - return err; -} - diff --git a/ruby/st.c b/ruby/st.c index 2b973ea75..07a083abb 100644 --- a/ruby/st.c +++ b/ruby/st.c @@ -105,6 +105,9 @@ #include "st.h" #else #include "internal.h" +#include "internal/bits.h" +#include "internal/hash.h" +#include "internal/sanitizers.h" #endif #include @@ -124,12 +127,6 @@ #define ATTRIBUTE_UNUSED #endif -#ifdef ST_DEBUG -#define st_assert assert -#else -#define st_assert(cond) ((void)(0 && (cond))) -#endif - /* The type of hashes. */ typedef st_index_t st_hash_t; @@ -316,9 +313,6 @@ static const struct st_features features[] = { #define RESERVED_HASH_VAL (~(st_hash_t) 0) #define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0) -const st_hash_t st_reserved_hash_val = RESERVED_HASH_VAL; -const st_hash_t st_reserved_hash_substitution_val = RESERVED_HASH_SUBSTITUTION_VAL; - /* Return hash value of KEY for table TAB. */ static inline st_hash_t do_hash(st_data_t key, st_table *tab) @@ -405,8 +399,6 @@ set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v) corresponding to deleted entries. */ #define MARK_BIN_DELETED(tab, i) \ do { \ - st_assert(i != UNDEFINED_BIN_IND); \ - st_assert(! IND_EMPTY_OR_DELETED_BIN_P(tab, i)); \ set_bin((tab)->bins, get_size_ind(tab), i, DELETED_BIN); \ } while (0) @@ -487,59 +479,6 @@ make_tab_empty(st_table *tab) initialize_bins(tab); } -#ifdef ST_DEBUG -#define st_assert_notinitial(ent) \ - do { \ - st_assert(ent.hash != (st_hash_t) ST_INIT_VAL); \ - st_assert(ent.key != ST_INIT_VAL); \ - st_assert(ent.record != ST_INIT_VAL); \ - } while (0) -/* Check the table T consistency. It can be extremely slow. So use - it only for debugging. */ -static void -st_check(st_table *tab) -{ - st_index_t d, e, i, n, p; - - for (p = get_allocated_entries(tab), i = 0; p > 1; i++, p>>=1) - ; - p = i; - st_assert(p >= MINIMAL_POWER2); - st_assert(tab->entries_bound <= get_allocated_entries(tab)); - st_assert(tab->entries_start <= tab->entries_bound); - n = 0; - return; - if (tab->entries_bound != 0) - for (i = tab->entries_start; i < tab->entries_bound; i++) { - st_assert_notinitial(tab->entries[i]); - if (! DELETED_ENTRY_P(&tab->entries[i])) - n++; - } - st_assert(n == tab->num_entries); - if (tab->bins == NULL) - st_assert(p <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS); - else { - st_assert(p > MAX_POWER2_FOR_TABLES_WITHOUT_BINS); - for (n = d = i = 0; i < get_bins_num(tab); i++) { - st_assert(get_bin(tab->bins, tab->size_ind, i) != ST_INIT_VAL); - if (IND_DELETED_BIN_P(tab, i)) { - d++; - continue; - } - else if (IND_EMPTY_BIN_P(tab, i)) - continue; - n++; - e = get_bin(tab->bins, tab->size_ind, i) - ENTRY_BASE; - st_assert(tab->entries_start <= e && e < tab->entries_bound); - st_assert(! DELETED_ENTRY_P(&tab->entries[e])); - st_assert_notinitial(tab->entries[e]); - } - st_assert(n == tab->num_entries); - st_assert(n + d < get_bins_num(tab)); - } -} -#endif - #ifdef HASH_LOG #ifdef HAVE_UNISTD_H #include @@ -624,18 +563,9 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) st_free_table(tab); return NULL; } -#endif -#ifdef ST_DEBUG - memset(tab->entries, ST_INIT_VAL_BYTE, - get_allocated_entries(tab) * sizeof(st_table_entry)); - if (tab->bins != NULL) - memset(tab->bins, ST_INIT_VAL_BYTE, bins_size(tab)); #endif make_tab_empty(tab); tab->rebuilds_num = 0; -#ifdef ST_DEBUG - st_check(tab); -#endif return tab; } @@ -699,9 +629,6 @@ st_clear(st_table *tab) { make_tab_empty(tab); tab->rebuilds_num++; -#ifdef ST_DEBUG - st_check(tab); -#endif } /* Free table TAB space. */ @@ -784,7 +711,6 @@ rebuild_table(st_table *tab) st_index_t *bins; st_index_t bin_ind; - st_assert(tab != NULL); bound = tab->entries_bound; entries = tab->entries; if ((2 * tab->num_entries <= get_allocated_entries(tab) @@ -815,9 +741,6 @@ rebuild_table(st_table *tab) if (EXPECT(bins != NULL, 1)) { bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash, curr_entry_ptr->key); - st_assert(bin_ind != UNDEFINED_BIN_IND); - st_assert(tab == new_tab || new_tab->rebuilds_num == 0); - st_assert(IND_EMPTY_BIN_P(new_tab, bin_ind)); set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE); } new_tab->num_entries++; @@ -827,8 +750,6 @@ rebuild_table(st_table *tab) tab->entry_power = new_tab->entry_power; tab->bin_power = new_tab->bin_power; tab->size_ind = new_tab->size_ind; - st_assert(tab->num_entries == ni); - st_assert(new_tab->num_entries == ni); if (tab->bins != NULL) free(tab->bins); tab->bins = new_tab->bins; @@ -839,9 +760,6 @@ rebuild_table(st_table *tab) tab->entries_start = 0; tab->entries_bound = tab->num_entries; tab->rebuilds_num++; -#ifdef ST_DEBUG - st_check(tab); -#endif } /* Return the next secondary hash index for table TAB using previous @@ -850,7 +768,7 @@ rebuild_table(st_table *tab) guarantees traversing all table bins in extreme case. According the Hull-Dobell theorem a generator - "Xnext = (a*Xprev + c) mod m" is a full cycle generator iff + "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if o m and c are relatively prime o a-1 is divisible by all prime factors of m o a-1 is divisible by 4 if m is divisible by 4. @@ -908,8 +826,6 @@ find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key) st_index_t bin; st_table_entry *entries = tab->entries; - st_assert(tab != NULL); - st_assert(tab->bins != NULL); ind = hash_bin(hash_value, tab); #ifdef QUADRATIC_PROBE d = 1; @@ -925,7 +841,8 @@ find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key) return REBUILT_TABLE_ENTRY_IND; if (eq_p) break; - } else if (EMPTY_BIN_P(bin)) + } + else if (EMPTY_BIN_P(bin)) return UNDEFINED_ENTRY_IND; #ifdef QUADRATIC_PROBE ind = hash_bin(ind + d, tab); @@ -955,8 +872,6 @@ find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key) st_index_t bin; st_table_entry *entries = tab->entries; - st_assert(tab != NULL); - st_assert(tab->bins != NULL); ind = hash_bin(hash_value, tab); #ifdef QUADRATIC_PROBE d = 1; @@ -972,7 +887,8 @@ find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key) return REBUILT_TABLE_BIN_IND; if (eq_p) break; - } else if (EMPTY_BIN_P(bin)) + } + else if (EMPTY_BIN_P(bin)) return UNDEFINED_BIN_IND; #ifdef QUADRATIC_PROBE ind = hash_bin(ind + d, tab); @@ -998,10 +914,7 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key) st_index_t peterb; #endif st_index_t bin; - st_table_entry *entries = tab->entries; - st_assert(tab != NULL); - st_assert(tab->bins != NULL); ind = hash_bin(hash_value, tab); #ifdef QUADRATIC_PROBE d = 1; @@ -1013,7 +926,6 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key) bin = get_bin(tab->bins, get_size_ind(tab), ind); if (EMPTY_OR_DELETED_BIN_P(bin)) return ind; - st_assert (entries[bin - ENTRY_BASE].hash != hash_value); #ifdef QUADRATIC_PROBE ind = hash_bin(ind + d, tab); d++; @@ -1049,10 +961,6 @@ find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value, st_index_t first_deleted_bin_ind; st_table_entry *entries; - st_assert(tab != NULL); - st_assert(tab->bins != NULL); - st_assert(tab->entries_bound <= get_allocated_entries(tab)); - st_assert(tab->entries_start <= tab->entries_bound); ind = hash_bin(curr_hash_value, tab); #ifdef QUADRATIC_PROBE d = 1; @@ -1161,11 +1069,10 @@ rebuild_table_if_necessary (st_table *tab) if (bound == get_allocated_entries(tab)) rebuild_table(tab); - st_assert(tab->entries_bound < get_allocated_entries(tab)); } /* Insert (KEY, VALUE) into table TAB and return zero. If there is - already entry with KEY in the table, return nonzero and and update + already entry with KEY in the table, return nonzero and update the value of the found entry. */ int st_insert(st_table *tab, st_data_t key, st_data_t value) @@ -1198,7 +1105,6 @@ st_insert(st_table *tab, st_data_t key, st_data_t value) bin -= ENTRY_BASE; } if (new_p) { - st_assert(tab->entries_bound < get_allocated_entries(tab)); ind = tab->entries_bound++; entry = &tab->entries[ind]; entry->hash = hash_value; @@ -1206,15 +1112,9 @@ st_insert(st_table *tab, st_data_t key, st_data_t value) entry->record = value; if (bin_ind != UNDEFINED_BIN_IND) set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE); -#ifdef ST_DEBUG - st_check(tab); -#endif return 0; } tab->entries[bin].record = value; -#ifdef ST_DEBUG - st_check(tab); -#endif return 1; } @@ -1237,12 +1137,8 @@ st_add_direct_with_hash(st_table *tab, tab->num_entries++; if (tab->bins != NULL) { bin_ind = find_table_bin_ind_direct(tab, hash, key); - st_assert (bin_ind != UNDEFINED_BIN_IND); set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE); } -#ifdef ST_DEBUG - st_check(tab); -#endif } /* Insert (KEY, VALUE) into table TAB. The table should not have @@ -1258,14 +1154,14 @@ st_add_direct(st_table *tab, st_data_t key, st_data_t value) /* Insert (FUNC(KEY), VALUE) into table TAB and return zero. If there is already entry with KEY in the table, return nonzero and - and update the value of the found entry. */ + update the value of the found entry. */ int st_insert2(st_table *tab, st_data_t key, st_data_t value, st_data_t (*func)(st_data_t)) { st_table_entry *entry; st_index_t bin; - st_index_t ind, check; + st_index_t ind; st_hash_t hash_value; st_index_t bin_ind; int new_p; @@ -1291,10 +1187,7 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value, bin -= ENTRY_BASE; } if (new_p) { - st_assert(tab->entries_bound < get_allocated_entries(tab)); - check = tab->rebuilds_num; key = (*func)(key); - st_assert(check == tab->rebuilds_num); ind = tab->entries_bound++; entry = &tab->entries[ind]; entry->hash = hash_value; @@ -1302,16 +1195,9 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value, entry->record = value; if (bin_ind != UNDEFINED_BIN_IND) set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE); - st_assert(do_hash(key, tab) == hash_value); -#ifdef ST_DEBUG - st_check(tab); -#endif return 0; } tab->entries[bin].record = value; -#ifdef ST_DEBUG - st_check(tab); -#endif return 1; } @@ -1350,9 +1236,6 @@ st_copy(st_table *old_tab) get_allocated_entries(old_tab)); if (old_tab->bins != NULL) MEMCPY(new_tab->bins, old_tab->bins, char, bins_size(old_tab)); -#ifdef ST_DEBUG - st_check(new_tab); -#endif return new_tab; } @@ -1363,8 +1246,13 @@ update_range_for_deleted(st_table *tab, st_index_t n) { /* Do not update entries_bound here. Otherwise, we can fill all bins by deleted entry value before rebuilding the table. */ - if (tab->entries_start == n) - tab->entries_start = n + 1; + if (tab->entries_start == n) { + st_index_t start = n + 1; + st_index_t bound = tab->entries_bound; + st_table_entry *entries = tab->entries; + while (start < bound && DELETED_ENTRY_P(&entries[start])) start++; + tab->entries_start = start; + } } /* Delete entry with KEY from table TAB, set up *VALUE (unless @@ -1379,7 +1267,6 @@ st_general_delete(st_table *tab, st_data_t *key, st_data_t *value) st_index_t bin_ind; st_hash_t hash; - st_assert(tab != NULL); hash = do_hash(*key, tab); retry: if (tab->bins == NULL) { @@ -1408,9 +1295,6 @@ st_general_delete(st_table *tab, st_data_t *key, st_data_t *value) MARK_ENTRY_DELETED(entry); tab->num_entries--; update_range_for_deleted(tab, bin); -#ifdef ST_DEBUG - st_check(tab); -#endif return 1; } @@ -1461,7 +1345,6 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value) entries = tab->entries; goto retry; } - st_assert(bin != UNDEFINED_ENTRY_IND); curr_entry_ptr = &entries[bin]; } else { @@ -1470,23 +1353,16 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value) entries = tab->entries; goto retry; } - st_assert(bin_ind != UNDEFINED_BIN_IND); curr_entry_ptr = &entries[get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE]; MARK_BIN_DELETED(tab, bin_ind); } - st_assert(entry_hash != curr_entry_ptr->hash && entry_key == curr_entry_ptr->key); MARK_ENTRY_DELETED(curr_entry_ptr); tab->num_entries--; update_range_for_deleted(tab, i); -#ifdef ST_DEBUG - st_check(tab); -#endif return 1; } } - st_assert(tab->num_entries == 0); - tab->entries_start = tab->entries_bound = 0; if (value != 0) *value = 0; return 0; } @@ -1498,14 +1374,15 @@ st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED, { } -/* Find entry with KEY in table TAB, call FUNC with the key and the - value of the found entry, and non-zero as the 3rd argument. If the - entry is not found, call FUNC with KEY, and 2 zero arguments. If - the call returns ST_CONTINUE, the table will have an entry with key - and value returned by FUNC through the 1st and 2nd parameters. If - the call of FUNC returns ST_DELETE, the table will not have entry - with KEY. The function returns flag of that the entry with KEY was - in the table before the call. */ +/* Find entry with KEY in table TAB, call FUNC with pointers to copies + of the key and the value of the found entry, and non-zero as the + 3rd argument. If the entry is not found, call FUNC with a pointer + to KEY, a pointer to zero, and a zero argument. If the call + returns ST_CONTINUE, the table will have an entry with key and + value returned by FUNC through the 1st and 2nd parameters. If the + call of FUNC returns ST_DELETE, the table will not have entry with + KEY. The function returns flag of that the entry with KEY was in + the table before the call. */ int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg) @@ -1515,7 +1392,6 @@ st_update(st_table *tab, st_data_t key, st_table_entry *entries; st_index_t bin_ind; st_data_t value = 0, old_key; - st_index_t check; int retval, existing; st_hash_t hash = do_hash(key, tab); @@ -1544,9 +1420,7 @@ st_update(st_table *tab, st_data_t key, value = entry->record; } old_key = key; - check = tab->rebuilds_num; retval = (*func)(&key, &value, arg, existing); - st_assert(check == tab->rebuilds_num); switch (retval) { case ST_CONTINUE: if (! existing) { @@ -1565,15 +1439,9 @@ st_update(st_table *tab, st_data_t key, MARK_ENTRY_DELETED(entry); tab->num_entries--; update_range_for_deleted(tab, bin); -#ifdef ST_DEBUG - st_check(tab); -#endif } break; } -#ifdef ST_DEBUG - st_check(tab); -#endif return existing; } @@ -1598,10 +1466,9 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat st_data_t key; int error_p, packed_p = tab->bins == NULL; - st_assert(tab->entries_start <= tab->entries_bound); entries = tab->entries; /* The bound can change inside the loop even without rebuilding - the table, e.g. by an entry inesrtion. */ + the table, e.g. by an entry insertion. */ for (i = tab->entries_start; i < tab->entries_bound; i++) { curr_entry_ptr = &entries[i]; if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0)) @@ -1639,60 +1506,48 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat if (error_p && check_p) { /* call func with error notice */ retval = (*func)(0, 0, arg, 1); -#ifdef ST_DEBUG - st_check(tab); -#endif return 1; } curr_entry_ptr = &entries[i]; } switch (retval) { - case ST_REPLACE: - break; + case ST_REPLACE: + break; case ST_CONTINUE: - break; + break; case ST_CHECK: - if (check_p) - break; + if (check_p) + break; case ST_STOP: -#ifdef ST_DEBUG - st_check(tab); -#endif - return 0; + return 0; case ST_DELETE: { - st_data_t key = curr_entry_ptr->key; + st_data_t key = curr_entry_ptr->key; again: - if (packed_p) { - bin = find_entry(tab, hash, key); - if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) - goto again; - if (bin == UNDEFINED_ENTRY_IND) - break; - } - else { - bin_ind = find_table_bin_ind(tab, hash, key); - if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) - goto again; - if (bin_ind == UNDEFINED_BIN_IND) - break; - bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE; - MARK_BIN_DELETED(tab, bin_ind); - } - curr_entry_ptr = &entries[bin]; - MARK_ENTRY_DELETED(curr_entry_ptr); - tab->num_entries--; - update_range_for_deleted(tab, bin); -#ifdef ST_DEBUG - st_check(tab); -#endif - break; + if (packed_p) { + bin = find_entry(tab, hash, key); + if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) + goto again; + if (bin == UNDEFINED_ENTRY_IND) + break; + } + else { + bin_ind = find_table_bin_ind(tab, hash, key); + if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) + goto again; + if (bin_ind == UNDEFINED_BIN_IND) + break; + bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE; + MARK_BIN_DELETED(tab, bin_ind); + } + curr_entry_ptr = &entries[bin]; + MARK_ENTRY_DELETED(curr_entry_ptr); + tab->num_entries--; + update_range_for_deleted(tab, bin); + break; } } } -#ifdef ST_DEBUG - st_check(tab); -#endif return 0; } @@ -1718,7 +1573,7 @@ int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg) { const struct functor f = { func, arg }; - return st_general_foreach(tab, apply_functor, NULL, (st_data_t)&f, FALSE); + return st_general_foreach(tab, apply_functor, 0, (st_data_t)&f, FALSE); } /* See comments for function st_delete_safe. */ @@ -1726,7 +1581,7 @@ int st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg, st_data_t never ATTRIBUTE_UNUSED) { - return st_general_foreach(tab, func, NULL, arg, TRUE); + return st_general_foreach(tab, func, 0, arg, TRUE); } /* Set up array KEYS by at most SIZE keys of head table TAB entries. @@ -1779,7 +1634,6 @@ st_general_values(st_table *tab, st_data_t *values, st_index_t size) values_start = values; values_end = values + size; bound = tab->entries_bound; - st_assert(bound != 0); for (i = tab->entries_start; i < bound; i++) { if (values == values_end) break; @@ -1815,7 +1669,7 @@ st_values_check(st_table *tab, st_data_t *values, st_index_t size, #ifndef UNALIGNED_WORD_ACCESS # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(__powerpc64__) || \ + defined(__powerpc64__) || defined(__aarch64__) || \ defined(__mc68020__) # define UNALIGNED_WORD_ACCESS 1 # endif @@ -2232,7 +2086,6 @@ st_rehash_linear(st_table *tab) if (EXPECT(rebuilt_p, 0)) return TRUE; if (eq_p) { - st_assert(p < q); *p = *q; MARK_ENTRY_DELETED(q); tab->num_entries--; @@ -2253,7 +2106,6 @@ st_rehash_indexed(st_table *tab) st_index_t const n = bins_size(tab); unsigned int const size_ind = get_size_ind(tab); st_index_t *bins = realloc(tab->bins, n); - st_assert(bins != NULL); tab->bins = bins; initialize_bins(tab); for (i = tab->entries_start; i < tab->entries_bound; i++) { @@ -2269,7 +2121,7 @@ st_rehash_indexed(st_table *tab) continue; ind = hash_bin(p->hash, tab); - for(;;) { + for (;;) { st_index_t bin = get_bin(bins, size_ind, ind); if (EMPTY_OR_DELETED_BIN_P(bin)) { /* ok, new room */ @@ -2283,7 +2135,6 @@ st_rehash_indexed(st_table *tab) return TRUE; if (eq_p) { /* duplicated key; delete it */ - st_assert(q < p); q->record = p->record; MARK_ENTRY_DELETED(p); tab->num_entries--; @@ -2394,4 +2245,19 @@ rb_hash_bulk_insert_into_st_table(long argc, const VALUE *argv, VALUE hash) else st_insert_generic(tab, argc, argv, hash); } + +// to iterate iv_index_tbl +st_data_t +rb_st_nth_key(st_table *tab, st_index_t index) +{ + if (LIKELY(tab->entries_start == 0 && + tab->num_entries == tab->entries_bound && + index < tab->num_entries)) { + return tab->entries[index].key; + } + else { + rb_bug("unreachable"); + } +} + #endif diff --git a/ruby/strftime.c b/ruby/strftime.c index dd2b21f97..a8a688608 100644 --- a/ruby/strftime.c +++ b/ruby/strftime.c @@ -47,10 +47,7 @@ * January 1996 */ -#include "ruby/ruby.h" -#include "ruby/encoding.h" -#include "timev.h" -#include "internal.h" +#include "ruby/internal/config.h" #ifndef GAWK #include @@ -62,12 +59,20 @@ #endif #if defined(TM_IN_SYS_TIME) || !defined(GAWK) #include -#if HAVE_SYS_TIME_H +#ifdef HAVE_SYS_TIME_H #include #endif #endif #include +#include "internal.h" +#include "internal/string.h" +#include "internal/vm.h" +#include "ruby/encoding.h" +#include "ruby/ruby.h" +#include "ruby/util.h" +#include "timev.h" + /* defaults: season to taste */ #define SYSV_EXT 1 /* stuff in System V ascftime routine */ #define SUNOS_EXT 1 /* stuff in SunOS strftime routine */ @@ -214,7 +219,7 @@ case_conv(char *s, ptrdiff_t i, int flags) static VALUE format_value(VALUE val, int base) { - if (!RB_TYPE_P(val, T_BIGNUM)) + if (!RB_BIGNUM_TYPE_P(val)) val = rb_Integer(val); return rb_big2str(val, base); } @@ -261,8 +266,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, static const char ampm[][3] = { "AM", "PM", }; if (format == NULL || format_len == 0 || vtm == NULL) { - err: - return 0; + goto err; } if (enc && @@ -326,7 +330,9 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, s += len; \ if (i > 0) case_conv(s, i, flags); \ if (precision > i) {\ + s += i; \ NEEDS(precision); \ + s -= i; \ memmove(s + precision - i, s, i);\ memset(s, padding ? padding : ' ', precision - i); \ s += precision; \ @@ -383,7 +389,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); flags |= BIT_OF(UPPER); } - if (vtm->wday < 0 || vtm->wday > 6) + if (vtm->wday > 6) i = 1, tp = "?"; else i = 3, tp = days_l[vtm->wday]; @@ -394,7 +400,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); flags |= BIT_OF(UPPER); } - if (vtm->wday < 0 || vtm->wday > 6) + if (vtm->wday > 6) i = 1, tp = "?"; else i = strlen(tp = days_l[vtm->wday]); @@ -541,7 +547,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, else { off = NUM2LONG(rb_funcall(vtm->utc_offset, rb_intern("round"), 0)); } - if (off < 0) { + if (off < 0 || (gmt && (flags & BIT_OF(LEFT)))) { off = -off; sign = -1; } @@ -904,6 +910,9 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, rb_str_set_len(ftime, len); rb_str_resize(ftime, len); return ftime; + +err: + return 0; } static size_t diff --git a/ruby/string.c b/ruby/string.c index d6fd73115..24acdfae0 100644 --- a/ruby/string.c +++ b/ruby/string.c @@ -11,37 +11,53 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/re.h" -#include "internal.h" -#include "encindex.h" -#include "probes.h" -#include "gc.h" -#include "ruby_assert.h" -#include "id.h" -#include "debug_counter.h" -#include "ruby/util.h" - -#define BEG(no) (regs->beg[(no)]) -#define END(no) (regs->end[(no)]) +#include "ruby/internal/config.h" +#include #include #include -#include #ifdef HAVE_UNISTD_H -#include +# include #endif +#include "debug_counter.h" +#include "encindex.h" +#include "gc.h" +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compar.h" +#include "internal/compilers.h" +#include "internal/encoding.h" +#include "internal/error.h" +#include "internal/gc.h" +#include "internal/numeric.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/re.h" +#include "internal/sanitizers.h" +#include "internal/string.h" +#include "internal/transcode.h" +#include "probes.h" +#include "ruby/encoding.h" +#include "ruby/re.h" +#include "ruby/util.h" +#include "ruby_assert.h" +#include "vm_sync.h" + #if defined HAVE_CRYPT_R # if defined HAVE_CRYPT_H -# include +# include # endif #elif !defined HAVE_CRYPT # include "missing/crypt.h" # define HAVE_CRYPT_R 1 #endif +#define BEG(no) (regs->beg[(no)]) +#define END(no) (regs->end[(no)]) + #undef rb_str_new #undef rb_usascii_str_new #undef rb_utf8_str_new @@ -61,8 +77,6 @@ #undef rb_str_cat_cstr #undef rb_fstring_cstr -static VALUE rb_str_clear(VALUE str); - VALUE rb_cString; VALUE rb_cSymbol; @@ -75,12 +89,16 @@ VALUE rb_cSymbol; * other strings that rely on this string's buffer) * 6: STR_BORROWED (when RSTRING_NOEMBED==1 && klass==0, unsafe to recycle * early, specific to rb_str_tmp_frozen_{acquire,release}) - * 7: STR_TMPLOCK + * 7: STR_TMPLOCK (set when a pointer to the buffer is passed to syscall + * such as read(2). Any modification and realloc is prohibited) + * * 8-9: ENC_CODERANGE (2 bits) * 10-16: ENCODING (7 bits == 128) * 17: RSTRING_FSTR - * 18: STR_NOFREE - * 19: STR_FAKESTR + * 18: STR_NOFREE (do not free this string's buffer when a String is freed. + * used for a string object based on C string literal) + * 19: STR_FAKESTR (when RVALUE is not managed by GC. Typically, the string + * object header is temporarily allocated on C stack) */ #define RUBY_MAX_CHAR_LEN 16 @@ -92,14 +110,26 @@ VALUE rb_cSymbol; #define STR_SET_NOEMBED(str) do {\ FL_SET((str), STR_NOEMBED);\ - STR_SET_EMBED_LEN((str), 0);\ + if (USE_RVARGC) {\ + FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\ + }\ + else {\ + STR_SET_EMBED_LEN((str), 0);\ + }\ } while (0) #define STR_SET_EMBED(str) FL_UNSET((str), (STR_NOEMBED|STR_NOFREE)) -#define STR_SET_EMBED_LEN(str, n) do { \ +#if USE_RVARGC +# define STR_SET_EMBED_LEN(str, n) do { \ + assert(str_embed_capa(str) > (n));\ + RSTRING(str)->as.embed.len = (n);\ +} while (0) +#else +# define STR_SET_EMBED_LEN(str, n) do { \ long tmp_n = (n);\ RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\ RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\ } while (0) +#endif #define STR_SET_LEN(str, n) do { \ if (STR_EMBED_P(str)) {\ @@ -136,7 +166,7 @@ VALUE rb_cSymbol; } while (0) #define RESIZE_CAPA_TERM(str,capacity,termlen) do {\ if (STR_EMBED_P(str)) {\ - if (!STR_EMBEDDABLE_P(capacity, termlen)) {\ + if (str_embed_capa(str) < capacity + termlen) {\ char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\ const long tlen = RSTRING_LEN(str);\ memcpy(tmp, RSTRING_PTR(str), tlen);\ @@ -156,6 +186,8 @@ VALUE rb_cSymbol; #define STR_SET_SHARED(str, shared_str) do { \ if (!FL_TEST(str, STR_FAKESTR)) { \ + assert(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \ + assert(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \ RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \ FL_SET((str), STR_SHARED); \ FL_SET((shared_str), STR_SHARED_ROOT); \ @@ -166,6 +198,7 @@ VALUE rb_cSymbol; #define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr) #define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str)) +/* TODO: include the terminator size in capa. */ #define STR_ENC_GET(str) get_encoding(str) @@ -178,13 +211,38 @@ VALUE rb_cSymbol; #define SHARABLE_SUBSTRING_P(beg, len, end) 1 #endif -#define STR_EMBEDDABLE_P(len, termlen) \ - ((len) <= RSTRING_EMBED_LEN_MAX + 1 - (termlen)) + +static inline long +str_embed_capa(VALUE str) +{ +#if USE_RVARGC + return rb_gc_obj_slot_size(str) - offsetof(struct RString, as.embed.ary); +#else + return RSTRING_EMBED_LEN_MAX + 1; +#endif +} + +static inline size_t +str_embed_size(long capa) +{ + return offsetof(struct RString, as.embed.ary) + capa; +} + +static inline bool +STR_EMBEDDABLE_P(long len, long termlen) +{ +#if USE_RVARGC + return rb_gc_size_allocatable_p(str_embed_size(len + termlen)); +#else + return len <= RSTRING_EMBED_LEN_MAX + 1 - termlen; +#endif +} static VALUE str_replace_shared_without_enc(VALUE str2, VALUE str); -static VALUE str_new_shared(VALUE klass, VALUE str); static VALUE str_new_frozen(VALUE klass, VALUE orig); +static VALUE str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding); static VALUE str_new_static(VALUE klass, const char *ptr, long len, int encindex); +static VALUE str_new(VALUE klass, const char *ptr, long len); static void str_make_independent_expand(VALUE str, long len, long expand, const int termlen); static inline void str_modifiable(VALUE str); static VALUE rb_str_downcase(int argc, VALUE *argv, VALUE str); @@ -197,6 +255,26 @@ str_make_independent(VALUE str) str_make_independent_expand((str), len, 0L, termlen); } +static inline int str_dependent_p(VALUE str); + +void +rb_str_make_independent(VALUE str) +{ + if (str_dependent_p(str)) { + str_make_independent(str); + } +} + +void +rb_debug_rstring_null_ptr(const char *func) +{ + fprintf(stderr, "%s is returning NULL!! " + "SIGSEGV is highly expected to follow immediately. " + "If you could reproduce, attach your debugger here, " + "and look at the passed string.", + func); +} + /* symbols for [up|down|swap]case/capitalize options */ static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold; @@ -255,7 +333,7 @@ mustnot_wchar(VALUE str) static int fstring_cmp(VALUE a, VALUE b); -static VALUE register_fstring(VALUE str); +static VALUE register_fstring(VALUE str, bool copy); const struct st_hash_type rb_fstring_hash_type = { fstring_cmp, @@ -264,10 +342,16 @@ const struct st_hash_type rb_fstring_hash_type = { #define BARE_STRING_P(str) (!FL_ANY_RAW(str, FL_EXIVAR) && RBASIC_CLASS(str) == rb_cString) +struct fstr_update_arg { + VALUE fstr; + bool copy; +}; + static int -fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing) +fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int existing) { - VALUE *fstr = (VALUE *)arg; + + struct fstr_update_arg *arg = (struct fstr_update_arg *)data; VALUE str = (VALUE)*key; if (existing) { @@ -275,25 +359,33 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi * at next time */ if (rb_objspace_garbage_object_p(str)) { - *fstr = Qundef; + arg->fstr = Qundef; return ST_DELETE; } - *fstr = str; + arg->fstr = str; return ST_STOP; } else { if (FL_TEST_RAW(str, STR_FAKESTR)) { - str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr, - RSTRING(str)->as.heap.len, - ENCODING_GET(str)); + if (arg->copy) { + VALUE new_str = str_new(rb_cString, RSTRING(str)->as.heap.ptr, RSTRING(str)->as.heap.len); + rb_enc_copy(new_str, str); + str = new_str; + } + else { + str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr, + RSTRING(str)->as.heap.len, + ENCODING_GET(str)); + } OBJ_FREEZE_RAW(str); } else { - str = str_new_frozen(rb_cString, str); + if (!OBJ_FROZEN(str)) + str = str_new_frozen(rb_cString, str); if (STR_SHARED_P(str)) { /* str should not be shared */ /* shared substring */ - str_make_independent(str); + str_make_independent(str); assert(OBJ_FROZEN(str)); } if (!BARE_STRING_P(str)) { @@ -302,7 +394,7 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi } RBASIC(str)->flags |= RSTRING_FSTR; - *key = *value = *fstr = str; + *key = *value = arg->fstr = str; return ST_CONTINUE; } } @@ -334,7 +426,7 @@ rb_fstring(VALUE str) if (!OBJ_FROZEN(str)) rb_str_resize(str, RSTRING_LEN(str)); - fstr = register_fstring(str); + fstr = register_fstring(str, FALSE); if (!bare) { str_replace_shared_without_enc(str, fstr); @@ -345,22 +437,26 @@ rb_fstring(VALUE str) } static VALUE -register_fstring(VALUE str) +register_fstring(VALUE str, bool copy) { - VALUE ret; - st_table *frozen_strings = rb_vm_fstring_table(); + struct fstr_update_arg args; + args.copy = copy; - do { - ret = str; - st_update(frozen_strings, (st_data_t)str, - fstr_update_callback, (st_data_t)&ret); - } while (ret == Qundef); - - assert(OBJ_FROZEN(ret)); - assert(!FL_TEST_RAW(ret, STR_FAKESTR)); - assert(!FL_TEST_RAW(ret, FL_EXIVAR)); - assert(RBASIC_CLASS(ret) == rb_cString); - return ret; + RB_VM_LOCK_ENTER(); + { + st_table *frozen_strings = rb_vm_fstring_table(); + do { + args.fstr = str; + st_update(frozen_strings, (st_data_t)str, fstr_update_callback, (st_data_t)&args); + } while (args.fstr == Qundef); + } + RB_VM_LOCK_LEAVE(); + + assert(OBJ_FROZEN(args.fstr)); + assert(!FL_TEST_RAW(args.fstr, STR_FAKESTR)); + assert(!FL_TEST_RAW(args.fstr, FL_EXIVAR)); + assert(RBASIC_CLASS(args.fstr) == rb_cString); + return args.fstr; } static VALUE @@ -369,6 +465,11 @@ setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx) fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR; /* SHARED to be allocated by the callback */ + if (!name) { + RUBY_ASSERT_ALWAYS(len == 0); + name = ""; + } + ENCODING_SET_INLINED((VALUE)fake_str, encidx); RBASIC_SET_CLASS_RAW((VALUE)fake_str, rb_cString); @@ -396,14 +497,14 @@ MJIT_FUNC_EXPORTED VALUE rb_fstring_new(const char *ptr, long len) { struct RString fake_str; - return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII)); + return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), FALSE); } VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc) { struct RString fake_str; - return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc)); + return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), FALSE); } VALUE @@ -653,6 +754,24 @@ rb_enc_cr_str_exact_copy(VALUE dest, VALUE src) ENC_CODERANGE_SET(dest, ENC_CODERANGE(src)); } +static int +enc_coderange_scan(VALUE str, rb_encoding *enc, int encidx) +{ + if (rb_enc_mbminlen(enc) > 1 && rb_enc_dummy_p(enc) && + rb_enc_mbminlen(enc = get_actual_encoding(encidx, str)) == 1) { + return ENC_CODERANGE_BROKEN; + } + else { + return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc); + } +} + +int +rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc) +{ + return enc_coderange_scan(str, enc, rb_enc_to_index(enc)); +} + int rb_enc_str_coderange(VALUE str) { @@ -661,14 +780,7 @@ rb_enc_str_coderange(VALUE str) if (cr == ENC_CODERANGE_UNKNOWN) { int encidx = ENCODING_GET(str); rb_encoding *enc = rb_enc_from_index(encidx); - if (rb_enc_mbminlen(enc) > 1 && rb_enc_dummy_p(enc) && - rb_enc_mbminlen(enc = get_actual_encoding(encidx, str)) == 1) { - cr = ENC_CODERANGE_BROKEN; - } - else { - cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), - enc); - } + cr = enc_coderange_scan(str, enc, encidx); ENC_CODERANGE_SET(str, cr); } return cr; @@ -698,7 +810,11 @@ static size_t str_capacity(VALUE str, const int termlen) { if (STR_EMBED_P(str)) { +#if USE_RVARGC + return str_embed_capa(str) - termlen; +#else return (RSTRING_EMBED_LEN_MAX + 1 - termlen); +#endif } else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) { return RSTRING(str)->as.heap.len; @@ -723,17 +839,38 @@ must_not_null(const char *ptr) } static inline VALUE -str_alloc(VALUE klass) +str_alloc(VALUE klass, size_t size) { - NEWOBJ_OF(str, struct RString, klass, T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0)); + assert(size > 0); + RVARGC_NEWOBJ_OF(str, struct RString, klass, + T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size); return (VALUE)str; } +static inline VALUE +str_alloc_embed(VALUE klass, size_t capa) +{ + size_t size = str_embed_size(capa); + assert(rb_gc_size_allocatable_p(size)); +#if !USE_RVARGC + assert(size <= sizeof(struct RString)); +#endif + return str_alloc(klass, size); +} + +static inline VALUE +str_alloc_heap(VALUE klass) +{ + return str_alloc(klass, sizeof(struct RString)); +} + static inline VALUE empty_str_alloc(VALUE klass) { RUBY_DTRACE_CREATE_HOOK(STRING, 0); - return str_alloc(klass); + VALUE str = str_alloc_embed(klass, 0); + memset(RSTRING(str)->as.embed.ary, 0, str_embed_capa(str)); + return str; } static VALUE @@ -747,15 +884,22 @@ str_new0(VALUE klass, const char *ptr, long len, int termlen) RUBY_DTRACE_CREATE_HOOK(STRING, len); - str = str_alloc(klass); - if (!STR_EMBEDDABLE_P(len, termlen)) { + if (STR_EMBEDDABLE_P(len, termlen)) { + str = str_alloc_embed(klass, len + termlen); + if (len == 0) { + ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); + } + } + else { + str = str_alloc_heap(klass); RSTRING(str)->as.heap.aux.capa = len; - RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)len + termlen); + /* :FIXME: @shyouhei guesses `len + termlen` is guaranteed to never + * integer overflow. If we can STATIC_ASSERT that, the following + * mul_add_mul can be reverted to a simple ALLOC_N. */ + RSTRING(str)->as.heap.ptr = + rb_xmalloc_mul_add_mul(sizeof(char), len, sizeof(char), termlen); STR_SET_NOEMBED(str); } - else if (len == 0) { - ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); - } if (ptr) { memcpy(RSTRING_PTR(str), ptr, len); } @@ -857,7 +1001,7 @@ str_new_static(VALUE klass, const char *ptr, long len, int encindex) } else { RUBY_DTRACE_CREATE_HOOK(STRING, len); - str = str_alloc(klass); + str = str_alloc_heap(klass); RSTRING(str)->as.heap.len = len; RSTRING(str)->as.heap.ptr = (char *)ptr; RSTRING(str)->as.heap.aux.capa = len; @@ -895,14 +1039,14 @@ rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc) VALUE rb_tainted_str_new(const char *ptr, long len) { - rb_warning("rb_tainted_str_new is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_tainted_str_new", NULL); return rb_str_new(ptr, len); } VALUE rb_tainted_str_new_cstr(const char *ptr) { - rb_warning("rb_tainted_str_new_cstr is deprecated and will be removed in Ruby 3.2."); + rb_warn_deprecated_to_remove_at(3.2, "rb_tainted_str_new_cstr", NULL); return rb_str_new_cstr(ptr); } @@ -910,6 +1054,15 @@ static VALUE str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); +static inline bool +is_enc_ascii_string(VALUE str, rb_encoding *enc) +{ + int encidx = rb_enc_to_index(enc); + if (rb_enc_get_index(str) == encidx) + return is_ascii_string(str); + return enc_coderange_scan(str, enc, encidx) == ENC_CODERANGE_7BIT; +} + VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts) { @@ -920,7 +1073,7 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, if (!to) return str; if (!from) from = rb_enc_get(str); if (from == to) return str; - if ((rb_enc_asciicompat(to) && is_ascii_string(str)) || + if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) || to == rb_ascii8bit_encoding()) { if (STR_ENC_GET(str) != to) { str = rb_str_dup(str); @@ -1013,7 +1166,6 @@ str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, } DATA_PTR(econv_wrapper) = 0; rb_econv_close(ec); - rb_gc_force_recycle(econv_wrapper); switch (ret) { case econv_finished: len = dp - (unsigned char*)RSTRING_PTR(newstr); @@ -1122,13 +1274,13 @@ rb_filesystem_str_new_cstr(const char *ptr) VALUE rb_str_export(VALUE str) { - return rb_str_conv_enc(str, STR_ENC_GET(str), rb_default_external_encoding()); + return rb_str_export_to_enc(str, rb_default_external_encoding()); } VALUE rb_str_export_locale(VALUE str) { - return rb_str_conv_enc(str, STR_ENC_GET(str), rb_locale_encoding()); + return rb_str_export_to_enc(str, rb_locale_encoding()); } VALUE @@ -1145,8 +1297,8 @@ str_replace_shared_without_enc(VALUE str2, VALUE str) long len; RSTRING_GETMEM(str, ptr, len); - if (STR_EMBEDDABLE_P(len, termlen)) { - char *ptr2 = RSTRING(str2)->as.ary; + if (str_embed_capa(str2) >= len + termlen) { + char *ptr2 = RSTRING(str2)->as.embed.ary; STR_SET_EMBED(str2); memcpy(ptr2, RSTRING_PTR(str), len); STR_SET_EMBED_LEN(str2, len); @@ -1162,6 +1314,7 @@ str_replace_shared_without_enc(VALUE str2, VALUE str) root = rb_str_new_frozen(str); RSTRING_GETMEM(root, ptr, len); } + assert(OBJ_FROZEN(root)); if (!STR_EMBED_P(str2) && !FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) { if (FL_TEST_RAW(str2, STR_SHARED_ROOT)) { rb_fatal("about to free a possible shared root"); @@ -1190,7 +1343,7 @@ str_replace_shared(VALUE str2, VALUE str) static VALUE str_new_shared(VALUE klass, VALUE str) { - return str_replace_shared(str_alloc(klass), str); + return str_replace_shared(str_alloc_heap(klass), str); } VALUE @@ -1206,11 +1359,18 @@ rb_str_new_frozen(VALUE orig) return str_new_frozen(rb_obj_class(orig), orig); } +static VALUE +rb_str_new_frozen_String(VALUE orig) +{ + if (OBJ_FROZEN(orig) && rb_obj_class(orig) == rb_cString) return orig; + return str_new_frozen(rb_cString, orig); +} + VALUE rb_str_tmp_frozen_acquire(VALUE orig) { if (OBJ_FROZEN_RAW(orig)) return orig; - return str_new_frozen(0, orig); + return str_new_frozen_buffer(0, orig, FALSE); } void @@ -1221,44 +1381,82 @@ rb_str_tmp_frozen_release(VALUE orig, VALUE tmp) if (STR_EMBED_P(tmp)) { assert(OBJ_FROZEN_RAW(tmp)); - rb_gc_force_recycle(tmp); } else if (FL_TEST_RAW(orig, STR_SHARED) && !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) { VALUE shared = RSTRING(orig)->as.heap.aux.shared; if (shared == tmp && !FL_TEST_RAW(tmp, STR_BORROWED)) { + assert(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr); + assert(RSTRING(orig)->as.heap.len == RSTRING(tmp)->as.heap.len); + + /* Unshare orig since the root (tmp) only has this one child. */ FL_UNSET_RAW(orig, STR_SHARED); - assert(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr); - assert(RSTRING(orig)->as.heap.len == RSTRING(tmp)->as.heap.len); RSTRING(orig)->as.heap.aux.capa = RSTRING(tmp)->as.heap.aux.capa; RBASIC(orig)->flags |= RBASIC(tmp)->flags & STR_NOFREE; assert(OBJ_FROZEN_RAW(tmp)); - rb_gc_force_recycle(tmp); + + /* Make tmp embedded and empty so it is safe for sweeping. */ + STR_SET_EMBED(tmp); + STR_SET_EMBED_LEN(tmp, 0); } } } static VALUE str_new_frozen(VALUE klass, VALUE orig) +{ + return str_new_frozen_buffer(klass, orig, TRUE); +} + +static VALUE +heap_str_make_shared(VALUE klass, VALUE orig) +{ + assert(!STR_EMBED_P(orig)); + assert(!STR_SHARED_P(orig)); + + VALUE str = str_alloc_heap(klass); + STR_SET_NOEMBED(str); + RSTRING(str)->as.heap.len = RSTRING_LEN(orig); + RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig); + RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa; + RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE; + RBASIC(orig)->flags &= ~STR_NOFREE; + STR_SET_SHARED(orig, str); + if (klass == 0) + FL_UNSET_RAW(str, STR_BORROWED); + return str; +} + +static VALUE +str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding) { VALUE str; - if (STR_EMBED_P(orig)) { - str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig)); + long len = RSTRING_LEN(orig); + + if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(len, 1)) { + str = str_new(klass, RSTRING_PTR(orig), len); + assert(STR_EMBED_P(str)); } else { if (FL_TEST_RAW(orig, STR_SHARED)) { VALUE shared = RSTRING(orig)->as.heap.aux.shared; - long ofs = RSTRING(orig)->as.heap.ptr - RSTRING(shared)->as.heap.ptr; - long rest = RSTRING(shared)->as.heap.len - ofs - RSTRING(orig)->as.heap.len; + long ofs = RSTRING(orig)->as.heap.ptr - RSTRING_PTR(shared); + long rest = RSTRING_LEN(shared) - ofs - RSTRING(orig)->as.heap.len; + assert(ofs >= 0); + assert(rest >= 0); + assert(ofs + rest <= RSTRING_LEN(shared)); +#if !USE_RVARGC assert(!STR_EMBED_P(shared)); +#endif assert(OBJ_FROZEN(shared)); if ((ofs > 0) || (rest > 0) || (klass != RBASIC(shared)->klass) || ENCODING_GET(shared) != ENCODING_GET(orig)) { str = str_new_shared(klass, shared); + assert(!STR_EMBED_P(str)); RSTRING(str)->as.heap.ptr += ofs; RSTRING(str)->as.heap.len -= ofs + rest; } @@ -1268,28 +1466,19 @@ str_new_frozen(VALUE klass, VALUE orig) return shared; } } - else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) { - str = str_alloc(klass); + else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) { + str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig)); STR_SET_EMBED(str); memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig)); STR_SET_EMBED_LEN(str, RSTRING_LEN(orig)); TERM_FILL(RSTRING_END(str), TERM_LEN(orig)); } else { - str = str_alloc(klass); - STR_SET_NOEMBED(str); - RSTRING(str)->as.heap.len = RSTRING_LEN(orig); - RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig); - RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa; - RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE; - RBASIC(orig)->flags &= ~STR_NOFREE; - STR_SET_SHARED(orig, str); - if (klass == 0) - FL_UNSET_RAW(str, STR_BORROWED); + str = heap_str_make_shared(klass, orig); } } - rb_enc_cr_str_exact_copy(str, orig); + if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig); OBJ_FREEZE(str); return str; } @@ -1301,24 +1490,32 @@ rb_str_new_with_class(VALUE obj, const char *ptr, long len) } static VALUE -str_new_empty(VALUE str) +str_new_empty_String(VALUE str) { - VALUE v = rb_str_new_with_class(str, 0, 0); + VALUE v = rb_str_new(0, 0); rb_enc_copy(v, str); return v; } #define STR_BUF_MIN_SIZE 63 +#if !USE_RVARGC STATIC_ASSERT(STR_BUF_MIN_SIZE, STR_BUF_MIN_SIZE > RSTRING_EMBED_LEN_MAX); +#endif VALUE rb_str_buf_new(long capa) { - VALUE str = str_alloc(rb_cString); + if (STR_EMBEDDABLE_P(capa, 1)) { + return str_alloc_embed(rb_cString, capa + 1); + } + + VALUE str = str_alloc_heap(rb_cString); +#if !USE_RVARGC if (capa < STR_BUF_MIN_SIZE) { capa = STR_BUF_MIN_SIZE; } +#endif FL_SET(str, STR_NOEMBED); RSTRING(str)->as.heap.aux.capa = capa; RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + 1); @@ -1350,8 +1547,13 @@ rb_str_free(VALUE str) { if (FL_TEST(str, RSTRING_FSTR)) { st_data_t fstr = (st_data_t)str; - st_delete(rb_vm_fstring_table(), &fstr, NULL); - RB_DEBUG_COUNTER_INC(obj_str_fstr); + + RB_VM_LOCK_ENTER(); + { + st_delete(rb_vm_fstring_table(), &fstr, NULL); + RB_DEBUG_COUNTER_INC(obj_str_fstr); + } + RB_VM_LOCK_LEAVE(); } if (STR_EMBED_P(str)) { @@ -1406,7 +1608,7 @@ str_shared_replace(VALUE str, VALUE str2) str_discard(str); termlen = rb_enc_mbminlen(enc); - if (STR_EMBEDDABLE_P(RSTRING_LEN(str2), termlen)) { + if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) { STR_SET_EMBED(str); memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (size_t)RSTRING_LEN(str2) + termlen); STR_SET_EMBED_LEN(str, RSTRING_LEN(str2)); @@ -1414,6 +1616,21 @@ str_shared_replace(VALUE str, VALUE str2) ENC_CODERANGE_SET(str, cr); } else { +#if USE_RVARGC + if (STR_EMBED_P(str2)) { + assert(!FL_TEST(str2, STR_SHARED)); + long len = RSTRING(str2)->as.embed.len; + assert(len + termlen <= str_embed_capa(str2)); + + char *new_ptr = ALLOC_N(char, len + termlen); + memcpy(new_ptr, RSTRING(str2)->as.embed.ary, len + termlen); + RSTRING(str2)->as.heap.ptr = new_ptr; + RSTRING(str2)->as.heap.len = len; + RSTRING(str2)->as.heap.aux.capa = len; + STR_SET_NOEMBED(str2); + } +#endif + STR_SET_NOEMBED(str); FL_UNSET(str, STR_SHARED); RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); @@ -1479,39 +1696,114 @@ str_replace(VALUE str, VALUE str2) } static inline VALUE -str_duplicate(VALUE klass, VALUE str) +ec_str_alloc(struct rb_execution_context_struct *ec, VALUE klass, size_t size) +{ + assert(size > 0); + RB_RVARGC_EC_NEWOBJ_OF(ec, str, struct RString, klass, + T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size); + return (VALUE)str; +} + +static inline VALUE +ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t capa) +{ + size_t size = str_embed_size(capa); + assert(rb_gc_size_allocatable_p(size)); +#if !USE_RVARGC + assert(size <= sizeof(struct RString)); +#endif + return ec_str_alloc(ec, klass, size); +} + +static inline VALUE +ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass) +{ + return ec_str_alloc(ec, klass, sizeof(struct RString)); +} + +static inline VALUE +str_duplicate_setup(VALUE klass, VALUE str, VALUE dup) { - enum {embed_size = RSTRING_EMBED_LEN_MAX + 1}; const VALUE flag_mask = +#if !USE_RVARGC RSTRING_NOEMBED | RSTRING_EMBED_LEN_MASK | - ENC_CODERANGE_MASK | ENCODING_MASK | +#endif + ENC_CODERANGE_MASK | ENCODING_MASK | FL_FREEZE ; VALUE flags = FL_TEST_RAW(str, flag_mask); - VALUE dup = str_alloc(klass); - MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary, - char, embed_size); - if (flags & STR_NOEMBED) { + int encidx = 0; + if (STR_EMBED_P(str)) { + long len = RSTRING_EMBED_LEN(str); + + assert(str_embed_capa(dup) >= len + 1); + STR_SET_EMBED_LEN(dup, len); + MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + 1); + } + else { + VALUE root = str; if (FL_TEST_RAW(str, STR_SHARED)) { - str = RSTRING(str)->as.heap.aux.shared; + root = RSTRING(str)->as.heap.aux.shared; } else if (UNLIKELY(!(flags & FL_FREEZE))) { - str = str_new_frozen(klass, str); + root = str = str_new_frozen(klass, str); flags = FL_TEST_RAW(str, flag_mask); - } - if (flags & STR_NOEMBED) { - RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, str); - flags |= STR_SHARED; - } - else { - MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary, - char, embed_size); - } + } + assert(!STR_SHARED_P(root)); + assert(RB_OBJ_FROZEN_RAW(root)); +#if USE_RVARGC + if (1) { +#else + if (STR_EMBED_P(root)) { + MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(root)->as.embed.ary, + char, RSTRING_EMBED_LEN_MAX + 1); + } + else { +#endif + RSTRING(dup)->as.heap.len = RSTRING_LEN(str); + RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str); + RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, root); + flags |= RSTRING_NOEMBED | STR_SHARED; + } + } + + if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX< new_str - * String.new(str="", encoding: enc) -> new_str - * String.new(str="", capacity: size) -> new_str + * String.new(string = '') -> new_string + * String.new(string = '', encoding: encoding) -> new_string + * String.new(string = '', capacity: size) -> new_string + * + * Returns a new \String that is a copy of +string+. + * + * With no arguments, returns the empty string with the Encoding ASCII-8BIT: + * s = String.new + * s # => "" + * s.encoding # => # + * + * With the single \String argument +string+, returns a copy of +string+ + * with the same encoding as +string+: + * s = String.new("Que veut dire \u{e7}a?") + * s # => "Que veut dire \u{e7}a?" + * s.encoding # => # + * + * Literal strings like "" or here-documents always use + * {script encoding}[Encoding.html#class-Encoding-label-Script+encoding], unlike String.new. + * + * With keyword +encoding+, returns a copy of +str+ + * with the specified encoding: + * s = String.new(encoding: 'ASCII') + * s.encoding # => # + * s = String.new('foo', encoding: 'ASCII') + * s.encoding # => # + * + * Note that these are equivalent: + * s0 = String.new('foo', encoding: 'ASCII') + * s1 = 'foo'.force_encoding('ASCII') + * s0.encoding == s1.encoding # => true + * + * With keyword +capacity+, returns a copy of +str+; + * the given +capacity+ may set the size of the internal buffer, + * which may affect performance: + * String.new(capacity: 1) # => "" + * String.new(capacity: 4096) # => "" * - * Returns a new string object containing a copy of str. + * The +string+, +encoding+, and +capacity+ arguments may all be used together: * - * The optional encoding keyword argument specifies the encoding - * of the new string. - * If not specified, the encoding of str is used - * (or ASCII-8BIT, if str is not specified). + * String.new('hello', encoding: 'UTF-8', capacity: 25) * - * The optional capacity keyword argument specifies the size - * of the internal buffer. - * This may improve performance, when the string will be concatenated many - * times (causing many realloc calls). */ static VALUE @@ -1585,7 +1911,12 @@ rb_str_init(int argc, VALUE *argv, VALUE str) str_modifiable(str); if (STR_EMBED_P(str)) { /* make noembed always */ char *new_ptr = ALLOC_N(char, (size_t)capa + termlen); - memcpy(new_ptr, RSTRING(str)->as.ary, RSTRING_EMBED_LEN_MAX + 1); +#if USE_RVARGC + assert(RSTRING(str)->as.embed.len + 1 <= str_embed_capa(str)); + memcpy(new_ptr, RSTRING(str)->as.embed.ary, RSTRING(str)->as.embed.len + 1); +#else + memcpy(new_ptr, RSTRING(str)->as.embed.ary, RSTRING_EMBED_LEN_MAX + 1); +#endif RSTRING(str)->as.heap.ptr = new_ptr; } else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) { @@ -1594,7 +1925,7 @@ rb_str_init(int argc, VALUE *argv, VALUE str) const size_t osize = RSTRING(str)->as.heap.len + TERM_LEN(str); char *new_ptr = ALLOC_N(char, (size_t)capa + termlen); memcpy(new_ptr, old_ptr, osize < size ? osize : size); - FL_UNSET_RAW(str, STR_SHARED); + FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE); RSTRING(str)->as.heap.ptr = new_ptr; } else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) { @@ -1629,7 +1960,7 @@ rb_str_init(int argc, VALUE *argv, VALUE str) /* * UTF-8 leading bytes have either 0xxxxxxx or 11xxxxxx - * bit representation. (see http://en.wikipedia.org/wiki/UTF-8) + * bit representation. (see https://en.wikipedia.org/wiki/UTF-8) * Therefore, the following pseudocode can detect UTF-8 leading bytes. * * if (!(byte & 0x80)) @@ -1833,10 +2164,16 @@ rb_str_strlen(VALUE str) /* * call-seq: - * str.length -> integer - * str.size -> integer + * length -> integer + * + * Returns the count of characters (not bytes) in +self+: + * + * "\x80\u3042".length # => 2 + * "hello".length # => 5 * - * Returns the character length of str. + * String#size is an alias for String#length. + * + * Related: String#bytesize. */ VALUE @@ -1847,12 +2184,14 @@ rb_str_length(VALUE str) /* * call-seq: - * str.bytesize -> integer + * bytesize -> integer + * + * Returns the count of bytes in +self+: * - * Returns the length of +str+ in bytes. + * "\x80\u3042".bytesize # => 4 + * "hello".bytesize # => 5 * - * "\x80\u3042".bytesize #=> 4 - * "hello".bytesize #=> 5 + * Related: String#length. */ static VALUE @@ -1863,31 +2202,30 @@ rb_str_bytesize(VALUE str) /* * call-seq: - * str.empty? -> true or false + * empty? -> true or false * - * Returns true if str has a length of zero. + * Returns +true+ if the length of +self+ is zero, +false+ otherwise: + * + * "hello".empty? # => false + * " ".empty? # => false + * "".empty? # => true * - * "hello".empty? #=> false - * " ".empty? #=> false - * "".empty? #=> true */ static VALUE rb_str_empty(VALUE str) { - if (RSTRING_LEN(str) == 0) - return Qtrue; - return Qfalse; + return RBOOL(RSTRING_LEN(str) == 0); } /* * call-seq: - * str + other_str -> new_str + * string + other_string -> new_string * - * Concatenation---Returns a new String containing - * other_str concatenated to str. + * Returns a new \String containing +other_string+ concatenated to +self+: + * + * "Hello from " + self.to_s # => "Hello from main" * - * "Hello from " + self.to_s #=> "Hello from main" */ VALUE @@ -1953,13 +2291,13 @@ rb_str_opt_plus(VALUE str1, VALUE str2) /* * call-seq: - * str * integer -> new_str + * string * integer -> new_string + * + * Returns a new \String containing +integer+ copies of +self+: * - * Copy --- Returns a new String containing +integer+ copies of the receiver. - * +integer+ must be greater than or equal to 0. + * "Ho! " * 3 # => "Ho! Ho! Ho! " + * "Ho! " * 0 # => "" * - * "Ho! " * 3 #=> "Ho! Ho! Ho! " - * "Ho! " * 0 #=> "" */ VALUE @@ -1971,10 +2309,10 @@ rb_str_times(VALUE str, VALUE times) int termlen; if (times == INT2FIX(1)) { - return rb_str_dup(str); + return str_duplicate(rb_cString, str); } if (times == INT2FIX(0)) { - str2 = str_alloc(rb_obj_class(str)); + str2 = str_alloc_embed(rb_cString, 0); rb_enc_copy(str2, str); return str2; } @@ -1983,15 +2321,19 @@ rb_str_times(VALUE str, VALUE times) rb_raise(rb_eArgError, "negative argument"); } if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) { - str2 = str_alloc(rb_obj_class(str)); - if (!STR_EMBEDDABLE_P(len, 1)) { - RSTRING(str2)->as.heap.aux.capa = len; - RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1); - STR_SET_NOEMBED(str2); - } - STR_SET_LEN(str2, len); - rb_enc_copy(str2, str); - return str2; + if (STR_EMBEDDABLE_P(len, 1)) { + str2 = str_alloc_embed(rb_cString, len + 1); + memset(RSTRING_PTR(str2), 0, len + 1); + } + else { + str2 = str_alloc_heap(rb_cString); + RSTRING(str2)->as.heap.aux.capa = len; + RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1); + STR_SET_NOEMBED(str2); + } + STR_SET_LEN(str2, len); + rb_enc_copy(str2, str); + return str2; } if (len && LONG_MAX/len < RSTRING_LEN(str)) { rb_raise(rb_eArgError, "argument too big"); @@ -1999,7 +2341,7 @@ rb_str_times(VALUE str, VALUE times) len *= RSTRING_LEN(str); termlen = TERM_LEN(str); - str2 = str_new0(rb_obj_class(str), 0, len, termlen); + str2 = str_new0(rb_cString, 0, len, termlen); ptr2 = RSTRING_PTR(str2); if (len) { n = RSTRING_LEN(str); @@ -2019,17 +2361,20 @@ rb_str_times(VALUE str, VALUE times) /* * call-seq: - * str % arg -> new_str + * string % object -> new_string + * + * Returns the result of formatting +object+ into the format specification +self+ + * (see Kernel#sprintf for formatting details): + * + * "%05d" % 123 # => "00123" * - * Format---Uses str as a format specification, and returns - * the result of applying it to arg. If the format - * specification contains more than one substitution, then arg - * must be an Array or Hash containing the values to be - * substituted. See Kernel#sprintf for details of the format string. + * If +self+ contains multiple substitutions, +object+ must be + * an \Array or \Hash containing the values to be substituted: + * + * "%-5s: %016x" % [ "ID", self.object_id ] # => "ID : 00002b054ec93168" + * "foo = %{foo}" % {foo: 'bar'} # => "foo = bar" + * "foo = %{foo}, baz = %{baz}" % {foo: 'bar', baz: 'bat'} # => "foo = bar, baz = bat" * - * "%05d" % 123 #=> "00123" - * "%-5s: %016x" % [ "ID", self.object_id ] #=> "ID : 00002b054ec93168" - * "foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar" */ static VALUE @@ -2085,11 +2430,11 @@ str_make_independent_expand(VALUE str, long len, long expand, const int termlen) if (len > capa) len = capa; - if (!STR_EMBED_P(str) && STR_EMBEDDABLE_P(capa, termlen)) { + if (!STR_EMBED_P(str) && str_embed_capa(str) >= capa + termlen) { ptr = RSTRING(str)->as.heap.ptr; STR_SET_EMBED(str); - memcpy(RSTRING(str)->as.ary, ptr, len); - TERM_FILL(RSTRING(str)->as.ary + len, termlen); + memcpy(RSTRING(str)->as.embed.ary, ptr, len); + TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen); STR_SET_EMBED_LEN(str, len); return; } @@ -2319,14 +2664,16 @@ rb_check_string_type(VALUE str) /* * call-seq: - * String.try_convert(obj) -> string or nil + * String.try_convert(object) -> object, new_string, or nil + * + * If +object+ is a \String object, returns +object+. * - * Try to convert obj into a String, using to_str method. - * Returns converted string or nil if obj cannot be converted - * for any reason. + * Otherwise if +object+ responds to :to_str, + * calls object.to_str and returns the result. * - * String.try_convert("str") #=> "str" - * String.try_convert(/re/) #=> nil + * Returns +nil+ if +object+ does not respond to :to_str. + * + * Raises an exception unless object.to_str returns a \String object. */ static VALUE rb_str_s_try_convert(VALUE dummy, VALUE str) @@ -2478,14 +2825,14 @@ rb_str_subseq(VALUE str, long beg, long len) if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) && SHARABLE_SUBSTRING_P(beg, len, RSTRING_LEN(str))) { long olen; - str2 = rb_str_new_shared(rb_str_new_frozen(str)); + str2 = rb_str_new_shared(rb_str_new_frozen_String(str)); RSTRING(str2)->as.heap.ptr += beg; olen = RSTRING(str2)->as.heap.len; if (olen > len) RSTRING(str2)->as.heap.len = len; } else { - str2 = rb_str_new_with_class(str, RSTRING_PTR(str)+beg, len); - RB_GC_GUARD(str); + str2 = rb_str_new(RSTRING_PTR(str)+beg, len); + RB_GC_GUARD(str); } rb_enc_cr_str_copy_for_substr(str2, str); @@ -2597,14 +2944,14 @@ str_substr(VALUE str, long beg, long len, int empty) SHARABLE_SUBSTRING_P(p, len, RSTRING_END(str))) { long ofs = p - RSTRING_PTR(str); str2 = rb_str_new_frozen(str); - str2 = str_new_shared(rb_obj_class(str2), str2); + str2 = str_new_shared(rb_cString, str2); RSTRING(str2)->as.heap.ptr += ofs; RSTRING(str2)->as.heap.len = len; ENC_CODERANGE_CLEAR(str2); } else { if (!len && !empty) return Qnil; - str2 = rb_str_new_with_class(str, p, len); + str2 = rb_str_new(p, len); RB_GC_GUARD(str); } rb_enc_cr_str_copy_for_substr(str2, str); @@ -2623,11 +2970,11 @@ rb_str_freeze(VALUE str) /* * call-seq: - * +str -> str (mutable) + * +string -> new_string or self * - * If the string is frozen, then return duplicated mutable string. + * Returns +self+ if +self+ is not frozen. * - * If the string is not frozen, then return the string itself. + * Otherwise. returns self.dup, which is not frozen. */ static VALUE str_uplus(VALUE str) @@ -2642,11 +2989,11 @@ str_uplus(VALUE str) /* * call-seq: - * -str -> str (frozen) + * -string -> frozen_string * * Returns a frozen, possibly pre-existing copy of the string. * - * The string will be deduplicated as long as it does not have + * The returned \String will be deduplicated as long as it does not have * any instance variables set on it. */ static VALUE @@ -2724,19 +3071,19 @@ rb_str_resize(VALUE str, long len) const int termlen = TERM_LEN(str); if (STR_EMBED_P(str)) { if (len == slen) return str; - if (STR_EMBEDDABLE_P(len, termlen)) { + if (str_embed_capa(str) >= len + termlen) { STR_SET_EMBED_LEN(str, len); - TERM_FILL(RSTRING(str)->as.ary + len, termlen); + TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen); return str; } str_make_independent_expand(str, slen, len - slen, termlen); } - else if (STR_EMBEDDABLE_P(len, termlen)) { + else if (str_embed_capa(str) >= len + termlen) { char *ptr = STR_HEAP_PTR(str); STR_SET_EMBED(str); if (slen > len) slen = len; - if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, slen); - TERM_FILL(RSTRING(str)->as.ary + len, termlen); + if (slen > 0) MEMCPY(RSTRING(str)->as.embed.ary, ptr, char, slen); + TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen); STR_SET_EMBED_LEN(str, len); if (independent) ruby_xfree(ptr); return str; @@ -2764,7 +3111,9 @@ str_buf_cat(VALUE str, const char *ptr, long len) long capa, total, olen, off = -1; char *sptr; const int termlen = TERM_LEN(str); +#if !USE_RVARGC assert(termlen < RSTRING_EMBED_LEN_MAX + 1); /* < (LONG_MAX/2) */ +#endif RSTRING_GETMEM(str, sptr, olen); if (ptr >= sptr && ptr <= sptr + olen) { @@ -2773,8 +3122,8 @@ str_buf_cat(VALUE str, const char *ptr, long len) rb_str_modify(str); if (len == 0) return 0; if (STR_EMBED_P(str)) { - capa = RSTRING_EMBED_LEN_MAX + 1 - termlen; - sptr = RSTRING(str)->as.ary; + capa = str_embed_capa(str) - termlen; + sptr = RSTRING(str)->as.embed.ary; olen = RSTRING_EMBED_LEN(str); } else { @@ -2875,9 +3224,7 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len, ptr_cr != ENC_CODERANGE_7BIT) { str_enc = rb_enc_from_index(str_encindex); ptr_enc = rb_enc_from_index(ptr_encindex); - incompatible: - rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", - rb_enc_name(str_enc), rb_enc_name(ptr_enc)); + goto incompatible; } if (str_cr == ENC_CODERANGE_UNKNOWN) { @@ -2913,6 +3260,11 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len, str_buf_cat(str, ptr, len); ENCODING_CODERANGE_SET(str, res_encindex, res_cr); return str; + + incompatible: + rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", + rb_enc_name(str_enc), rb_enc_name(ptr_enc)); + UNREACHABLE_RETURN(Qundef); } VALUE @@ -3007,23 +3359,21 @@ rb_str_concat_literals(size_t num, const VALUE *strary) /* * call-seq: - * str.concat(obj1, obj2, ...) -> str + * concat(*objects) -> string * - * Concatenates the given object(s) to str. If an object is an - * Integer, it is considered a codepoint and converted to a character - * before concatenation. + * Concatenates each object in +objects+ to +self+ and returns +self+: * - * +concat+ can take multiple arguments, and all the arguments are - * concatenated in order. + * s = 'foo' + * s.concat('bar', 'baz') # => "foobarbaz" + * s # => "foobarbaz" * - * a = "hello " - * a.concat("world", 33) #=> "hello world!" - * a #=> "hello world!" + * For each given object +object+ that is an \Integer, + * the value is considered a codepoint and converted to a character before concatenation: * - * b = "sn" - * b.concat("_", b, "_", b) #=> "sn_sn_sn" + * s = 'foo' + * s.concat(32, 'bar', 32, 'baz') # => "foo bar baz" * - * See also String#<<, which takes a single argument. + * Related: String#<<, which takes a single argument. */ static VALUE rb_str_concat_multi(int argc, VALUE *argv, VALUE str) @@ -3048,18 +3398,21 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str << obj -> str - * str << integer -> str + * string << object -> string + * + * Concatenates +object+ to +self+ and returns +self+: + * + * s = 'foo' + * s << 'bar' # => "foobar" + * s # => "foobar" * - * Appends the given object to str. If the object is an - * Integer, it is considered a codepoint and converted to a character - * before being appended. + * If +object+ is an \Integer, + * the value is considered a codepoint and converted to a character before concatenation: * - * a = "hello " - * a << "world" #=> "hello world" - * a << 33 #=> "hello world!" + * s = 'foo' + * s << 33 # => "foo!" * - * See also String#concat, which takes multiple arguments. + * Related: String#concat, which takes multiple arguments. */ VALUE rb_str_concat(VALUE str1, VALUE str2) @@ -3127,15 +3480,15 @@ rb_str_concat(VALUE str1, VALUE str2) /* * call-seq: - * str.prepend(other_str1, other_str2, ...) -> str + * prepend(*other_strings) -> string * - * Prepend---Prepend the given strings to str. + * Prepends each string in +other_strings+ to +self+ and returns +self+: * - * a = "!" - * a.prepend("hello ", "world") #=> "hello world!" - * a #=> "hello world!" + * s = 'foo' + * s.prepend('bar', 'baz') # => "barbazfoo" + * s # => "barbazfoo" * - * See also String#concat. + * Related: String#concat. */ static VALUE @@ -3183,11 +3536,12 @@ rb_str_hash_cmp(VALUE str1, VALUE str2) /* * call-seq: - * str.hash -> integer + * hash -> integer * - * Returns a hash based on the string's length, content and encoding. + * Returns the integer hash value for +self+. + * The value is based on the length, content and encoding of +self+. * - * See also Object#hash. + * Related: Object#hash. */ static VALUE @@ -3252,15 +3606,22 @@ rb_str_cmp(VALUE str1, VALUE str2) /* * call-seq: - * str == obj -> true or false - * str === obj -> true or false + * string == object -> true or false + * string === object -> true or false * - * Equality---Returns whether +str+ == +obj+, similar to Object#==. + * Returns +true+ if +object+ has the same length and content; + * as +self+; +false+ otherwise: * - * If +obj+ is not an instance of String but responds to +to_str+, then the - * two strings are compared using obj.==. + * s = 'foo' + * s == 'foo' # => true + * s == 'food' # => false + * s == 'FOO' # => false * - * Otherwise, returns similarly to String#eql?, comparing length and content. + * Returns +false+ if the two strings' encodings are not compatible: + * "\u{e4 f6 fc}".encode("ISO-8859-1") == ("\u{c4 d6 dc}") # => false + * + * If +object+ is not an instance of \String but responds to +to_str+, then the + * two strings are compared using object.==. */ VALUE @@ -3278,9 +3639,20 @@ rb_str_equal(VALUE str1, VALUE str2) /* * call-seq: - * str.eql?(other) -> true or false + * eql?(object) -> true or false + * + * Returns +true+ if +object+ has the same length and content; + * as +self+; +false+ otherwise: + * + * s = 'foo' + * s.eql?('foo') # => true + * s.eql?('food') # => false + * s.eql?('FOO') # => false + * + * Returns +false+ if the two strings' encodings are not compatible: + * + * "\u{e4 f6 fc}".encode("ISO-8859-1").eql?("\u{c4 d6 dc}") # => false * - * Two strings are equal if they have the same length and content. */ MJIT_FUNC_EXPORTED VALUE @@ -3293,27 +3665,24 @@ rb_str_eql(VALUE str1, VALUE str2) /* * call-seq: - * string <=> other_string -> -1, 0, +1, or nil + * string <=> other_string -> -1, 0, 1, or nil * - * Comparison---Returns -1, 0, +1, or +nil+ depending on whether +string+ is - * less than, equal to, or greater than +other_string+. + * Compares +self+ and +other_string+, returning: * - * +nil+ is returned if the two values are incomparable. + * - -1 if +other_string+ is larger. + * - 0 if the two are equal. + * - 1 if +other_string+ is smaller. + * - +nil+ if the two are incomparable. * - * If the strings are of different lengths, and the strings are equal when - * compared up to the shortest length, then the longer string is considered - * greater than the shorter one. + * Examples: * - * <=> is the basis for the methods <, - * <=, >, >=, and - * between?, included from module Comparable. The method - * String#== does not use Comparable#==. + * 'foo' <=> 'foo' # => 0 + * 'foo' <=> 'food' # => -1 + * 'food' <=> 'foo' # => 1 + * 'FOO' <=> 'foo' # => -1 + * 'foo' <=> 'FOO' # => 1 + * 'foo' <=> 1 # => nil * - * "abcdef" <=> "abcde" #=> 1 - * "abcdef" <=> "abcdef" #=> 0 - * "abcdef" <=> "abcdefg" #=> -1 - * "abcdef" <=> "ABCDEF" #=> 1 - * "abcdef" <=> 1 #=> nil */ static VALUE @@ -3333,22 +3702,28 @@ static VALUE str_casecmp_p(VALUE str1, VALUE str2); /* * call-seq: - * str.casecmp(other_str) -> -1, 0, +1, or nil + * casecmp(other_string) -> -1, 0, 1, or nil * - * Case-insensitive version of String#<=>. - * Currently, case-insensitivity only works on characters A-Z/a-z, - * not all of Unicode. This is different from String#casecmp?. + * Compares self.downcase and other_string.downcase; returns: + * + * - -1 if other_string.downcase is larger. + * - 0 if the two are equal. + * - 1 if other_string.downcase is smaller. + * - +nil+ if the two are incomparable. + * + * Examples: * - * "aBcDeF".casecmp("abcde") #=> 1 - * "aBcDeF".casecmp("abcdef") #=> 0 - * "aBcDeF".casecmp("abcdefg") #=> -1 - * "abcdef".casecmp("ABCDEF") #=> 0 + * 'foo'.casecmp('foo') # => 0 + * 'foo'.casecmp('food') # => -1 + * 'food'.casecmp('foo') # => 1 + * 'FOO'.casecmp('foo') # => 0 + * 'foo'.casecmp('FOO') # => 0 + * 'foo'.casecmp(1) # => nil * - * +nil+ is returned if the two strings have incompatible encodings, - * or if +other_str+ is not a string. + * See {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#casecmp?. * - * "foo".casecmp(2) #=> nil - * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp("\u{c4 d6 dc}") #=> nil */ static VALUE @@ -3366,7 +3741,7 @@ str_casecmp(VALUE str1, VALUE str2) { long len; rb_encoding *enc; - char *p1, *p1end, *p2, *p2end; + const char *p1, *p1end, *p2, *p2end; enc = rb_enc_compatible(str1, str2); if (!enc) { @@ -3420,22 +3795,25 @@ str_casecmp(VALUE str1, VALUE str2) /* * call-seq: - * str.casecmp?(other_str) -> true, false, or nil + * casecmp?(other_string) -> true, false, or nil + * + * Returns +true+ if +self+ and +other_string+ are equal after + * Unicode case folding, otherwise +false+: + * + * 'foo'.casecmp?('foo') # => true + * 'foo'.casecmp?('food') # => false + * 'food'.casecmp?('foo') # => false + * 'FOO'.casecmp?('foo') # => true + * 'foo'.casecmp?('FOO') # => true + * + * Returns +nil+ if the two values are incomparable: * - * Returns +true+ if +str+ and +other_str+ are equal after - * Unicode case folding, +false+ if they are not equal. + * 'foo'.casecmp?(1) # => nil * - * "aBcDeF".casecmp?("abcde") #=> false - * "aBcDeF".casecmp?("abcdef") #=> true - * "aBcDeF".casecmp?("abcdefg") #=> false - * "abcdef".casecmp?("ABCDEF") #=> true - * "\u{e4 f6 fc}".casecmp?("\u{c4 d6 dc}") #=> true + * See {Case Mapping}[doc/case_mapping_rdoc.html]. * - * +nil+ is returned if the two strings have incompatible encodings, - * or if +other_str+ is not a string. + * Related: String#casecmp. * - * "foo".casecmp?(2) #=> nil - * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp?("\u{c4 d6 dc}") #=> nil */ static VALUE @@ -3494,7 +3872,6 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte) { const char *str_ptr, *str_ptr_end, *sub_ptr; long str_len, sub_len; - int single_byte = single_byte_optimizable(str); rb_encoding *enc; enc = rb_enc_check(str, sub); @@ -3510,6 +3887,7 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte) if (offset != 0) { long str_len_char, sub_len_char; + int single_byte = single_byte_optimizable(str); str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc); sub_len_char = in_byte ? sub_len : str_strlen(sub, enc); if (offset < 0) { @@ -3529,19 +3907,40 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte) /* * call-seq: - * str.index(substring [, offset]) -> integer or nil - * str.index(regexp [, offset]) -> integer or nil + * index(substring, offset = 0) -> integer or nil + * index(regexp, offset = 0) -> integer or nil + * + * Returns the \Integer index of the first occurrence of the given +substring+, + * or +nil+ if none found: + * + * 'foo'.index('f') # => 0 + * 'foo'.index('o') # => 1 + * 'foo'.index('oo') # => 1 + * 'foo'.index('ooo') # => nil + * + * Returns the \Integer index of the first match for the given \Regexp +regexp+, + * or +nil+ if none found: + * + * 'foo'.index(/f/) # => 0 + * 'foo'.index(/o/) # => 1 + * 'foo'.index(/oo/) # => 1 + * 'foo'.index(/ooo/) # => nil * - * Returns the index of the first occurrence of the given substring or - * pattern (regexp) in str. Returns nil if not - * found. If the second parameter is present, it specifies the position in the - * string to begin the search. + * \Integer argument +offset+, if given, specifies the position in the + * string to begin the search: * - * "hello".index('e') #=> 1 - * "hello".index('lo') #=> 3 - * "hello".index('a') #=> nil - * "hello".index(?e) #=> 1 - * "hello".index(/[aeiou]/, -3) #=> 4 + * 'foo'.index('o', 1) # => 1 + * 'foo'.index('o', 2) # => 2 + * 'foo'.index('o', 3) # => nil + * + * If +offset+ is negative, counts backward from the end of +self+: + * + * 'foo'.index('o', -1) # => 2 + * 'foo'.index('o', -2) # => 1 + * 'foo'.index('o', -3) # => 1 + * 'foo'.index('o', -4) # => nil + * + * Related: String#rindex. */ static VALUE @@ -3567,34 +3966,26 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str) } } - if (SPECIAL_CONST_P(sub)) goto generic; - switch (BUILTIN_TYPE(sub)) { - case T_REGEXP: + if (RB_TYPE_P(sub, T_REGEXP)) { if (pos > str_strlen(str, NULL)) return Qnil; pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, rb_enc_check(str, sub), single_byte_optimizable(str)); - pos = rb_reg_search(sub, str, pos, 0); - pos = rb_str_sublen(str, pos); - break; - - generic: - default: { - VALUE tmp; - - tmp = rb_check_string_type(sub); - if (NIL_P(tmp)) { - rb_raise(rb_eTypeError, "type mismatch: %s given", - rb_obj_classname(sub)); - } - sub = tmp; - } - /* fall through */ - case T_STRING: + if (rb_reg_search(sub, str, pos, 0) < 0) { + return Qnil; + } + else { + VALUE match = rb_backref_get(); + struct re_registers *regs = RMATCH_REGS(match); + pos = rb_str_sublen(str, BEG(0)); + return LONG2NUM(pos); + } + } + else { + StringValue(sub); pos = rb_str_index(str, sub, pos); pos = rb_str_sublen(str, pos); - break; } if (pos == -1) return Qnil; @@ -3690,23 +4081,61 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) return str_rindex(str, sub, s, pos, enc); } - /* * call-seq: - * str.rindex(substring [, integer]) -> integer or nil - * str.rindex(regexp [, integer]) -> integer or nil + * rindex(substring, offset = self.length) -> integer or nil + * rindex(regexp, offset = self.length) -> integer or nil + * + * Returns the \Integer index of the _last_ occurrence of the given +substring+, + * or +nil+ if none found: + * + * 'foo'.rindex('f') # => 0 + * 'foo'.rindex('o') # => 2 + * 'foo'.rindex('oo') # => 1 + * 'foo'.rindex('ooo') # => nil + * + * Returns the \Integer index of the _last_ match for the given \Regexp +regexp+, + * or +nil+ if none found: + * + * 'foo'.rindex(/f/) # => 0 + * 'foo'.rindex(/o/) # => 2 + * 'foo'.rindex(/oo/) # => 1 + * 'foo'.rindex(/ooo/) # => nil + * + * The _last_ match means starting at the possible last position, not + * the last of longest matches. + * + * 'foo'.rindex(/o+/) # => 2 + * $~ #=> # * - * Returns the index of the last occurrence of the given substring or - * pattern (regexp) in str. Returns nil if not - * found. If the second parameter is present, it specifies the position in the - * string to end the search---characters beyond this point will not be - * considered. + * To get the last longest match, needs to combine with negative + * lookbehind. * - * "hello".rindex('e') #=> 1 - * "hello".rindex('l') #=> 3 - * "hello".rindex('a') #=> nil - * "hello".rindex(?e) #=> 1 - * "hello".rindex(/[aeiou]/, -2) #=> 1 + * 'foo'.rindex(/(? 1 + * $~ #=> # + * + * Or String#index with negative lookforward. + * + * 'foo'.index(/o+(?!.*o)/) # => 1 + * $~ #=> # + * + * \Integer argument +offset+, if given and non-negative, specifies the maximum starting position in the + * string to _end_ the search: + * + * 'foo'.rindex('o', 0) # => nil + * 'foo'.rindex('o', 1) # => 1 + * 'foo'.rindex('o', 2) # => 2 + * 'foo'.rindex('o', 3) # => 2 + * + * If +offset+ is a negative \Integer, the maximum starting position in the + * string to _end_ the search is the sum of the string's length and +offset+: + * + * 'foo'.rindex('o', -1) # => 2 + * 'foo'.rindex('o', -2) # => 1 + * 'foo'.rindex('o', -3) # => nil + * 'foo'.rindex('o', -4) # => nil + * + * Related: String#index. */ static VALUE @@ -3734,68 +4163,65 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str) pos = len; } - if (SPECIAL_CONST_P(sub)) goto generic; - switch (BUILTIN_TYPE(sub)) { - case T_REGEXP: + if (RB_TYPE_P(sub, T_REGEXP)) { /* enc = rb_get_check(str, sub); */ pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, enc, single_byte_optimizable(str)); - pos = rb_reg_search(sub, str, pos, 1); - pos = rb_str_sublen(str, pos); - if (pos >= 0) return LONG2NUM(pos); - break; - - generic: - default: { - VALUE tmp; - - tmp = rb_check_string_type(sub); - if (NIL_P(tmp)) { - rb_raise(rb_eTypeError, "type mismatch: %s given", - rb_obj_classname(sub)); - } - sub = tmp; - } - /* fall through */ - case T_STRING: + if (rb_reg_search(sub, str, pos, 1) >= 0) { + VALUE match = rb_backref_get(); + struct re_registers *regs = RMATCH_REGS(match); + pos = rb_str_sublen(str, BEG(0)); + return LONG2NUM(pos); + } + } + else { + StringValue(sub); pos = rb_str_rindex(str, sub, pos); if (pos >= 0) return LONG2NUM(pos); - break; } return Qnil; } /* * call-seq: - * str =~ obj -> integer or nil + * string =~ regexp -> integer or nil + * string =~ object -> integer or nil + * + * Returns the \Integer index of the first substring that matches + * the given +regexp+, or +nil+ if no match found: + * + * 'foo' =~ /f/ # => 0 + * 'foo' =~ /o/ # => 1 + * 'foo' =~ /x/ # => nil + * + * Note: also updates + * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables]. * - * Match---If obj is a Regexp, use it as a pattern to match - * against str,and returns the position the match starts, or - * nil if there is no match. Otherwise, invokes - * obj.=~, passing str as an argument. The default - * =~ in Object returns nil. + * If the given +object+ is not a \Regexp, returns the value + * returned by object =~ self. * - * Note: str =~ regexp is not the same as - * regexp =~ str. Strings captured from named capture groups - * are assigned to local variables only in the second case. + * Note that string =~ regexp is different from regexp =~ string + * (see {Regexp#=~}[https://ruby-doc.org/core-2.7.1/Regexp.html#method-i-3D-7E]): + * + * number= nil + * "no. 9" =~ /(?\d+)/ + * number # => nil (not assigned) + * /(?\d+)/ =~ "no. 9" + * number #=> "9" * - * "cat o' 9 tails" =~ /\d/ #=> 7 - * "cat o' 9 tails" =~ 9 #=> nil */ static VALUE rb_str_match(VALUE x, VALUE y) { - if (SPECIAL_CONST_P(y)) goto generic; - switch (BUILTIN_TYPE(y)) { + switch (OBJ_BUILTIN_TYPE(y)) { case T_STRING: rb_raise(rb_eTypeError, "type mismatch: String given"); case T_REGEXP: return rb_reg_match(y, x); - generic: default: return rb_funcall(y, idEqTilde, 1, x); } @@ -3807,32 +4233,38 @@ static VALUE get_pat(VALUE); /* * call-seq: - * str.match(pattern) -> matchdata or nil - * str.match(pattern, pos) -> matchdata or nil + * match(pattern, offset = 0) -> matchdata or nil + * match(pattern, offset = 0) {|matchdata| ... } -> object * - * Converts pattern to a Regexp (if it isn't already one), - * then invokes its match method on str. If the second - * parameter is present, it specifies the position in the string to begin the - * search. + * Returns a \Matchdata object (or +nil+) based on +self+ and the given +pattern+. * - * 'hello'.match('(.)\1') #=> # - * 'hello'.match('(.)\1')[0] #=> "ll" - * 'hello'.match(/(.)\1/)[0] #=> "ll" - * 'hello'.match(/(.)\1/, 3) #=> nil - * 'hello'.match('xx') #=> nil + * Note: also updates + * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables]. * - * If a block is given, invoke the block with MatchData if match succeed, so - * that you can write + * - Computes +regexp+ by converting +pattern+ (if not already a \Regexp). + * regexp = Regexp.new(pattern) + * - Computes +matchdata+, which will be either a \MatchData object or +nil+ + * (see Regexp#match): + * matchdata = regexp.match(self) * - * str.match(pat) {|m| ...} + * With no block given, returns the computed +matchdata+: * - * instead of + * 'foo'.match('f') # => # + * 'foo'.match('o') # => # + * 'foo'.match('x') # => nil * - * if m = str.match(pat) - * ... - * end + * If \Integer argument +offset+ is given, the search begins at index +offset+: + * + * 'foo'.match('f', 1) # => nil + * 'foo'.match('o', 1) # => # + * + * With a block given, calls the block with the computed +matchdata+ + * and returns the block's return value: + * + * 'foo'.match(/o/) {|matchdata| matchdata } # => # + * 'foo'.match(/x/) {|matchdata| matchdata } # => nil + * 'foo'.match(/f/, 1) {|matchdata| matchdata } # => nil * - * The return value is a value from block execution in this case. */ static VALUE @@ -3852,19 +4284,27 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.match?(pattern) -> true or false - * str.match?(pattern, pos) -> true or false + * match?(pattern, offset = 0) -> true or false + * + * Returns +true+ or +false+ based on whether a match is found for +self+ and +pattern+. + * + * Note: does not update + * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables]. * - * Converts _pattern_ to a +Regexp+ (if it isn't already one), then - * returns a +true+ or +false+ indicates whether the regexp is - * matched _str_ or not without updating $~ and other - * related variables. If the second parameter is present, it - * specifies the position in the string to begin the search. + * Computes +regexp+ by converting +pattern+ (if not already a \Regexp). + * regexp = Regexp.new(pattern) + * + * Returns +true+ if self+.match(regexp) returns a \Matchdata object, + * +false+ otherwise: + * + * 'foo'.match?(/o/) # => true + * 'foo'.match?('o') # => true + * 'foo'.match?(/x/) # => false + * + * If \Integer argument +offset+ is given, the search begins at index +offset+: + * 'foo'.match?('f', 1) # => false + * 'foo'.match?('o', 1) # => true * - * "Ruby".match?(/R.../) #=> true - * "Ruby".match?(/R.../, 1) #=> false - * "Ruby".match?(/P.../) #=> false - * $& #=> nil */ static VALUE @@ -4063,34 +4503,68 @@ static VALUE str_succ(VALUE str); /* * call-seq: - * str.succ -> new_str - * str.next -> new_str + * succ -> new_str + * + * Returns the successor to +self+. The successor is calculated by + * incrementing characters. + * + * The first character to be incremented is the rightmost alphanumeric: + * or, if no alphanumerics, the rightmost character: + * + * 'THX1138'.succ # => "THX1139" + * '<>'.succ # => "<>" + * '***'.succ # => '**+' + * + * The successor to a digit is another digit, "carrying" to the next-left + * character for a "rollover" from 9 to 0, and prepending another digit + * if necessary: + * + * '00'.succ # => "01" + * '09'.succ # => "10" + * '99'.succ # => "100" * - * Returns the successor to str. The successor is calculated by - * incrementing characters starting from the rightmost alphanumeric (or - * the rightmost character if there are no alphanumerics) in the - * string. Incrementing a digit always results in another digit, and - * incrementing a letter results in another letter of the same case. - * Incrementing nonalphanumerics uses the underlying character set's - * collating sequence. + * The successor to a letter is another letter of the same case, + * carrying to the next-left character for a rollover, + * and prepending another same-case letter if necessary: * - * If the increment generates a ``carry,'' the character to the left of - * it is incremented. This process repeats until there is no carry, - * adding an additional character if necessary. + * 'aa'.succ # => "ab" + * 'az'.succ # => "ba" + * 'zz'.succ # => "aaa" + * 'AA'.succ # => "AB" + * 'AZ'.succ # => "BA" + * 'ZZ'.succ # => "AAA" * - * "abcd".succ #=> "abce" - * "THX1138".succ #=> "THX1139" - * "<>".succ #=> "<>" - * "1999zzz".succ #=> "2000aaa" - * "ZZZ9999".succ #=> "AAAA0000" - * "***".succ #=> "**+" + * The successor to a non-alphanumeric character is the next character + * in the underlying character set's collating sequence, + * carrying to the next-left character for a rollover, + * and prepending another character if necessary: + * + * s = 0.chr * 3 + * s # => "\x00\x00\x00" + * s.succ # => "\x00\x00\x01" + * s = 255.chr * 3 + * s # => "\xFF\xFF\xFF" + * s.succ # => "\x01\x00\x00\x00" + * + * Carrying can occur between and among mixtures of alphanumeric characters: + * + * s = 'zz99zz99' + * s.succ # => "aaa00aa00" + * s = '99zz99zz' + * s.succ # => "100aa00aa" + * + * The successor to an empty \String is a new empty \String: + * + * ''.succ # => "" + * + * String#next is an alias for String#succ. */ VALUE rb_str_succ(VALUE orig) { VALUE str; - str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig)); + str = rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig)); rb_enc_cr_str_copy_for_substr(str, orig); return str_succ(str); } @@ -4185,10 +4659,11 @@ str_succ(VALUE str) /* * call-seq: - * str.succ! -> str - * str.next! -> str + * succ! -> self + * + * Equivalent to String#succ, but modifies +self+ in place; returns +self+. * - * Equivalent to String#succ, but modifies the receiver in place. + * String#next! is an alias for String#succ!. */ static VALUE @@ -4218,35 +4693,37 @@ str_upto_i(VALUE str, VALUE arg) /* * call-seq: - * str.upto(other_str, exclusive=false) {|s| block } -> str - * str.upto(other_str, exclusive=false) -> an_enumerator + * upto(other_string, exclusive = false) {|string| ... } -> self + * upto(other_string, exclusive = false) -> new_enumerator * - * Iterates through successive values, starting at str and - * ending at other_str inclusive, passing each value in turn - * to the block. The String#succ method is used to generate each - * value. If optional second argument exclusive is omitted or is - * false, the last value will be included; otherwise it will be - * excluded. + * With a block given, calls the block with each \String value + * returned by successive calls to String#succ; + * the first value is +self+, the next is self.succ, and so on; + * the sequence terminates when value +other_string+ is reached; + * returns +self+: * - * If no block is given, an enumerator is returned instead. + * 'a8'.upto('b6') {|s| print s, ' ' } # => "a8" + * Output: * - * "a8".upto("b6") {|s| print s, ' ' } - * for s in "a8".."b6" - * print s, ' ' - * end + * a8 a9 b0 b1 b2 b3 b4 b5 b6 * - * produces: + * If argument +exclusive+ is given as a truthy object, the last value is omitted: + * + * 'a8'.upto('b6', true) {|s| print s, ' ' } # => "a8" + * + * Output: + * + * a8 a9 b0 b1 b2 b3 b4 b5 + * + * If +other_string+ would not be reached, does not call the block: + * + * '25'.upto('5') {|s| fail s } + * 'aa'.upto('a') {|s| fail s } * - * a8 a9 b0 b1 b2 b3 b4 b5 b6 - * a8 a9 b0 b1 b2 b3 b4 b5 b6 + * With no block given, returns a new \Enumerator: * - * If str and other_str contains only ascii numeric characters, - * both are recognized as decimal numbers. In addition, the width of - * string (e.g. leading zeros) is handled appropriately. + * 'a8'.upto('b6') # => # * - * "9".upto("11").to_a #=> ["9", "10", "11"] - * "25".upto("5").to_a #=> [] - * "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"] */ static VALUE @@ -4324,7 +4801,7 @@ rb_str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALU if (n > 0 || (excl && n == 0)) return beg; after_end = rb_funcallv(end, succ, 0, 0); - current = rb_str_dup(beg); + current = str_duplicate(rb_cString, beg); while (!rb_str_equal(current, after_end)) { VALUE next = Qnil; if (excl || !rb_str_equal(current, end)) @@ -4372,7 +4849,7 @@ rb_str_upto_endless_each(VALUE beg, int (*each)(VALUE, VALUE), VALUE arg) } } /* normal case */ - current = rb_str_dup(beg); + current = str_duplicate(rb_cString, beg); while (1) { VALUE next = rb_funcallv(current, succ, 0, 0); if ((*each)(current, arg)) break; @@ -4419,8 +4896,7 @@ rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive) if (ISASCII(b) && ISASCII(e) && ISASCII(v)) { if (b <= v && v < e) return Qtrue; - if (!RTEST(exclusive) && v == e) return Qtrue; - return Qfalse; + return RBOOL(!RTEST(exclusive) && v == e); } } } @@ -4435,7 +4911,7 @@ rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive) } rb_str_upto_each(beg, end, RTEST(exclusive), include_range_i, (VALUE)&val); - return NIL_P(val) ? Qtrue : Qfalse; + return RBOOL(NIL_P(val)); } static VALUE @@ -4462,7 +4938,7 @@ rb_str_aref(VALUE str, VALUE indx) } else if (RB_TYPE_P(indx, T_STRING)) { if (rb_str_index(str, indx, 0) != -1) - return rb_str_dup(indx); + return str_duplicate(rb_cString, indx); return Qnil; } else { @@ -4485,71 +4961,93 @@ rb_str_aref(VALUE str, VALUE indx) /* * call-seq: - * str[index] -> new_str or nil - * str[start, length] -> new_str or nil - * str[range] -> new_str or nil - * str[regexp] -> new_str or nil - * str[regexp, capture] -> new_str or nil - * str[match_str] -> new_str or nil - * str.slice(index) -> new_str or nil - * str.slice(start, length) -> new_str or nil - * str.slice(range) -> new_str or nil - * str.slice(regexp) -> new_str or nil - * str.slice(regexp, capture) -> new_str or nil - * str.slice(match_str) -> new_str or nil - * - * Element Reference --- If passed a single +index+, returns a substring of - * one character at that index. If passed a +start+ index and a +length+, - * returns a substring containing +length+ characters starting at the - * +start+ index. If passed a +range+, its beginning and end are interpreted as - * offsets delimiting the substring to be returned. - * - * In these three cases, if an index is negative, it is counted from the end - * of the string. For the +start+ and +range+ cases the starting index - * is just before a character and an index matching the string's size. - * Additionally, an empty string is returned when the starting index for a - * character range is at the end of the string. - * - * Returns +nil+ if the initial index falls outside the string or the length - * is negative. - * - * If a +Regexp+ is supplied, the matching portion of the string is - * returned. If a +capture+ follows the regular expression, which may be a - * capture group index or name, follows the regular expression that component - * of the MatchData is returned instead. - * - * If a +match_str+ is given, that string is returned if it occurs in - * the string. - * - * Returns +nil+ if the regular expression does not match or the match string - * cannot be found. - * - * a = "hello there" - * - * a[1] #=> "e" - * a[2, 3] #=> "llo" - * a[2..3] #=> "ll" - * - * a[-3, 2] #=> "er" - * a[7..-2] #=> "her" - * a[-4..-2] #=> "her" - * a[-2..-4] #=> "" - * - * a[11, 0] #=> "" - * a[11] #=> nil - * a[12, 0] #=> nil - * a[12..-1] #=> nil - * - * a[/[aeiou](.)\1/] #=> "ell" - * a[/[aeiou](.)\1/, 0] #=> "ell" - * a[/[aeiou](.)\1/, 1] #=> "l" - * a[/[aeiou](.)\1/, 2] #=> nil - * - * a[/(?[aeiou])(?[^aeiou])/, "non_vowel"] #=> "l" - * a[/(?[aeiou])(?[^aeiou])/, "vowel"] #=> "e" - * - * a["lo"] #=> "lo" - * a["bye"] #=> nil + * string[index] -> new_string or nil + * string[start, length] -> new_string or nil + * string[range] -> new_string or nil + * string[regexp, capture = 0] -> new_string or nil + * string[substring] -> new_string or nil + * + * Returns the substring of +self+ specified by the arguments. + * + * When the single \Integer argument +index+ is given, + * returns the 1-character substring found in +self+ at offset +index+: + * + * 'bar'[2] # => "r" + * + * Counts backward from the end of +self+ if +index+ is negative: + * + * 'foo'[-3] # => "f" + * + * Returns +nil+ if +index+ is out of range: + * + * 'foo'[3] # => nil + * 'foo'[-4] # => nil + * + * When the two \Integer arguments +start+ and +length+ are given, + * returns the substring of the given +length+ found in +self+ at offset +start+: + * + * 'foo'[0, 2] # => "fo" + * 'foo'[0, 0] # => "" + * + * Counts backward from the end of +self+ if +start+ is negative: + * + * 'foo'[-2, 2] # => "oo" + * + * Special case: returns a new empty \String if +start+ is equal to the length of +self+: + * + * 'foo'[3, 2] # => "" + * + * Returns +nil+ if +start+ is out of range: + * + * 'foo'[4, 2] # => nil + * 'foo'[-4, 2] # => nil + * + * Returns the trailing substring of +self+ if +length+ is large: + * + * 'foo'[1, 50] # => "oo" + * + * Returns +nil+ if +length+ is negative: + * + * 'foo'[0, -1] # => nil + * + * When the single \Range argument +range+ is given, + * derives +start+ and +length+ values from the given +range+, + * and returns values as above: + * + * - 'foo'[0..1] is equivalent to 'foo'[0, 2]. + * - 'foo'[0...1] is equivalent to 'foo'[0, 1]. + * + * When the \Regexp argument +regexp+ is given, + * and the +capture+ argument is 0, + * returns the first matching substring found in +self+, + * or +nil+ if none found: + * + * 'foo'[/o/] # => "o" + * 'foo'[/x/] # => nil + * s = 'hello there' + * s[/[aeiou](.)\1/] # => "ell" + * s[/[aeiou](.)\1/, 0] # => "ell" + * + * If argument +capture+ is given and not 0, + * it should be either an \Integer capture group index or a \String or \Symbol capture group name; + * the method call returns only the specified capture + * (see {Regexp Capturing}[Regexp.html#class-Regexp-label-Capturing]): + * + * 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, +nil+ is returned. If an invalid + * capture group name is given, +IndexError+ is raised. + * + * When the single \String argument +substring+ is given, + * returns the substring from +self+ if found, otherwise +nil+: + * + * 'foo'['oo'] # => "oo" + * 'foo'['xx'] # => nil + * + * String#slice is an alias for String#[]. */ static VALUE @@ -4578,17 +5076,21 @@ rb_str_drop_bytes(VALUE str, long len) str_modifiable(str); if (len > olen) len = olen; nlen = olen - len; - if (STR_EMBEDDABLE_P(nlen, TERM_LEN(str))) { + if (str_embed_capa(str) >= nlen + TERM_LEN(str)) { char *oldptr = ptr; int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE)); STR_SET_EMBED(str); STR_SET_EMBED_LEN(str, nlen); - ptr = RSTRING(str)->as.ary; + ptr = RSTRING(str)->as.embed.ary; memmove(ptr, oldptr + len, nlen); if (fl == STR_NOEMBED) xfree(oldptr); } else { - if (!STR_SHARED_P(str)) rb_str_new_frozen(str); + if (!STR_SHARED_P(str)) { + VALUE shared = heap_str_make_shared(rb_obj_class(str), str); + rb_enc_cr_str_exact_copy(shared, str); + OBJ_FREEZE(shared); + } ptr = RSTRING(str)->as.heap.ptr += len; RSTRING(str)->as.heap.len = nlen; } @@ -4654,14 +5156,10 @@ rb_str_update(VALUE str, long beg, long len, VALUE val) enc = rb_enc_check(str, val); slen = str_strlen(str, enc); /* rb_enc_check */ - if (slen < beg) { - out_of_range: + if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) { rb_raise(rb_eIndexError, "index %ld out of string", beg); } if (beg < 0) { - if (beg + slen < 0) { - goto out_of_range; - } beg += slen; } assert(beg >= 0); @@ -4701,14 +5199,10 @@ rb_str_subpat_set(VALUE str, VALUE re, VALUE backref, VALUE val) match = rb_backref_get(); nth = rb_reg_backref_number(match, backref); regs = RMATCH_REGS(match); - if (nth >= regs->num_regs) { - out_of_range: + if ((nth >= regs->num_regs) || ((nth < 0) && (-nth >= regs->num_regs))) { rb_raise(rb_eIndexError, "index %d out of regexp", nth); } if (nth < 0) { - if (-nth >= regs->num_regs) { - goto out_of_range; - } nth += regs->num_regs; } @@ -4729,15 +5223,7 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val) { long idx, beg; - if (FIXNUM_P(indx)) { - idx = FIX2LONG(indx); - num_index: - rb_str_splice(str, idx, 1, val); - return val; - } - - if (SPECIAL_CONST_P(indx)) goto generic; - switch (BUILTIN_TYPE(indx)) { + switch (TYPE(indx)) { case T_REGEXP: rb_str_subpat_set(str, indx, INT2FIX(0), val); return val; @@ -4751,7 +5237,6 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val) rb_str_splice(str, beg, str_strlen(indx, NULL), val); return val; - generic: default: /* check if indx is Range */ { @@ -4761,8 +5246,12 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val) return val; } } + /* FALLTHROUGH */ + + case T_FIXNUM: idx = NUM2LONG(indx); - goto num_index; + rb_str_splice(str, idx, 1, val); + return val; } } @@ -4808,19 +5297,20 @@ rb_str_aset_m(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.insert(index, other_str) -> str + * insert(index, other_string) -> self * - * Inserts other_str before the character at the given - * index, modifying str. Negative indices count from the - * end of the string, and insert after the given character. - * The intent is insert aString so that it starts at the given - * index. + * Inserts the given +other_string+ into +self+; returns +self+. + * + * If the \Integer +index+ is positive, inserts +other_string+ at offset +index+: + * + * 'foo'.insert(1, 'bar') # => "fbaroo" + * + * If the \Integer +index+ is negative, counts backward from the end of +self+ + * and inserts +other_string+ at offset index+1 + * (that is, _after_ self[index]): + * + * 'foo'.insert(-2, 'bar') # => "fobaro" * - * "abcd".insert(0, 'X') #=> "Xabcd" - * "abcd".insert(3, 'X') #=> "abcXd" - * "abcd".insert(4, 'X') #=> "abcdX" - * "abcd".insert(-3, 'X') #=> "abXcd" - * "abcd".insert(-1, 'X') #=> "abcdX" */ static VALUE @@ -4841,39 +5331,111 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2) /* * call-seq: - * str.slice!(integer) -> new_str or nil - * str.slice!(integer, integer) -> new_str or nil - * str.slice!(range) -> new_str or nil - * str.slice!(regexp) -> new_str or nil - * str.slice!(other_str) -> new_str or nil + * slice!(index) -> new_string or nil + * slice!(start, length) -> new_string or nil + * slice!(range) -> new_string or nil + * slice!(regexp, capture = 0) -> new_string or nil + * slice!(substring) -> new_string or nil * - * Deletes the specified portion from str, and returns the portion - * deleted. + * Removes the substring of +self+ specified by the arguments; + * returns the removed substring. * - * string = "this is a string" + * See String#[] for details about the arguments that specify the substring. + * + * A few examples: + * + * string = "This is a string" * string.slice!(2) #=> "i" * string.slice!(3..6) #=> " is " * string.slice!(/s.*t/) #=> "sa st" * string.slice!("r") #=> "r" - * string #=> "thing" + * string #=> "Thing" + * */ static VALUE rb_str_slice_bang(int argc, VALUE *argv, VALUE str) { - VALUE result; - VALUE buf[3]; - int i; + VALUE result = Qnil; + VALUE indx; + long beg, len = 1; + char *p; rb_check_arity(argc, 1, 2); - for (i=0; i 1 && (nth = rb_reg_backref_number(match, argv[1])) < 0) { + if ((nth += regs->num_regs) <= 0) return Qnil; + } + else if (nth >= regs->num_regs) return Qnil; + beg = BEG(nth); + len = END(nth) - beg; + goto subseq; + } + else if (argc == 2) { + beg = NUM2LONG(indx); + len = NUM2LONG(argv[1]); + goto num_index; + } + else if (FIXNUM_P(indx)) { + beg = FIX2LONG(indx); + if (!(p = rb_str_subpos(str, beg, &len))) return Qnil; + if (!len) return Qnil; + beg = p - RSTRING_PTR(str); + goto subseq; + } + else if (RB_TYPE_P(indx, T_STRING)) { + beg = rb_str_index(str, indx, 0); + if (beg == -1) return Qnil; + len = RSTRING_LEN(indx); + result = str_duplicate(rb_cString, indx); + goto squash; + } + else { + switch (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 0)) { + case Qnil: + return Qnil; + case Qfalse: + beg = NUM2LONG(indx); + if (!(p = rb_str_subpos(str, beg, &len))) return Qnil; + if (!len) return Qnil; + beg = p - RSTRING_PTR(str); + goto subseq; + default: + goto num_index; + } + } + + num_index: + if (!(p = rb_str_subpos(str, beg, &len))) return Qnil; + beg = p - RSTRING_PTR(str); + + subseq: + result = rb_str_new(RSTRING_PTR(str)+beg, len); + rb_enc_cr_str_copy_for_substr(result, str); + + squash: + if (len > 0) { + if (beg == 0) { + rb_str_drop_bytes(str, len); + } + else { + char *sptr = RSTRING_PTR(str); + long slen = RSTRING_LEN(str); + if (beg + len > slen) /* pathological check */ + len = slen - beg; + memmove(sptr + beg, + sptr + beg + len, + slen - (beg + len)); + slen -= len; + STR_SET_LEN(str, slen); + TERM_FILL(&sptr[slen], TERM_LEN(str)); + } } return result; } @@ -4883,8 +5445,7 @@ get_pat(VALUE pat) { VALUE val; - if (SPECIAL_CONST_P(pat)) goto to_string; - switch (BUILTIN_TYPE(pat)) { + switch (OBJ_BUILTIN_TYPE(pat)) { case T_REGEXP: return pat; @@ -4892,7 +5453,6 @@ get_pat(VALUE pat) break; default: - to_string: val = rb_check_string_type(pat); if (NIL_P(val)) { Check_Type(pat, T_REGEXP); @@ -4908,8 +5468,7 @@ get_pat_quoted(VALUE pat, int check) { VALUE val; - if (SPECIAL_CONST_P(pat)) goto to_string; - switch (BUILTIN_TYPE(pat)) { + switch (OBJ_BUILTIN_TYPE(pat)) { case T_REGEXP: return pat; @@ -4917,7 +5476,6 @@ get_pat_quoted(VALUE pat, int check) break; default: - to_string: val = rb_check_string_type(pat); if (NIL_P(val)) { Check_Type(pat, T_REGEXP); @@ -4937,7 +5495,7 @@ rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str) pos = rb_strseq_index(str, pat, pos, 1); if (set_backref_str) { if (pos >= 0) { - str = rb_str_new_frozen(str); + str = rb_str_new_frozen_String(str); rb_backref_set_string(str, pos, RSTRING_LEN(pat)); } else { @@ -4954,13 +5512,16 @@ rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str) /* * call-seq: - * str.sub!(pattern, replacement) -> str or nil - * str.sub!(pattern) {|match| block } -> str or nil + * sub!(pattern, replacement) -> self or nil + * sub!(pattern) {|match| ... } -> self or nil + * + * Returns +self+ with only the first occurrence + * (not all occurrences) of the given +pattern+ replaced. + * + * See {Substitution Methods}[#class-String-label-Substitution+Methods]. * - * Performs the same substitution as String#sub in-place. + * Related: String#sub, String#gsub, String#gsub!. * - * Returns +str+ if a substitution was performed or +nil+ if no substitution - * was performed. */ static VALUE @@ -5074,64 +5635,22 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.sub(pattern, replacement) -> new_str - * str.sub(pattern, hash) -> new_str - * str.sub(pattern) {|match| block } -> new_str - * - * Returns a copy of +str+ with the _first_ occurrence of +pattern+ - * replaced by the second argument. The +pattern+ is typically a Regexp; if - * given as a String, any regular expression metacharacters it contains will - * be interpreted literally, e.g. \d will match a backslash - * followed by 'd', instead of a digit. - * - * If +replacement+ is a String it will be substituted for the matched text. - * It may contain back-references to the pattern's capture groups of the form - * \d, where d is a group number, or - * \k, where n is a group name. - * Similarly, \&, \', \`, and - * \+ correspond to special variables, $&, - * $', $`, and $+, respectively. - * (See rdoc-ref:regexp.rdoc for details.) - * \0 is the same as \&. - * \\\\ is interpreted as an escape, i.e., a single backslash. - * Note that, within +replacement+ the special match variables, such as - * $&, will not refer to the current match. - * - * If the second argument is a Hash, and the matched text is one of its keys, - * the corresponding value is the replacement string. - * - * In the block form, the current match string is passed in as a parameter, - * and variables such as $1, $2, $`, - * $&, and $' will be set appropriately. - * (See rdoc-ref:regexp.rdoc for details.) - * The value returned by the block will be substituted for the match on each - * call. - * - * "hello".sub(/[aeiou]/, '*') #=> "h*llo" - * "hello".sub(/([aeiou])/, '<\1>') #=> "hllo" - * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello" - * "hello".sub(/(?[aeiou])/, '*\k*') #=> "h*e*llo" - * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV) - * #=> "Is /bin/bash your preferred shell?" - * - * Note that a string literal consumes backslashes. - * (See rdoc-ref:syntax/literals.rdoc for details about string literals.) - * Back-references are 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 first to 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 a lot of backslashes. + * sub(pattern, replacement) -> new_string + * sub(pattern) {|match| ... } -> new_string + * + * Returns a copy of +self+ with only the first occurrence + * (not all occurrences) of the given +pattern+ replaced. + * + * See {Substitution Methods}[#class-String-label-Substitution+Methods]. + * + * Related: String#sub!, String#gsub, String#gsub!. + * */ static VALUE rb_str_sub(int argc, VALUE *argv, VALUE str) { - str = rb_str_dup(str); + str = str_duplicate(rb_cString, str); rb_str_sub_bang(argc, argv, str); return str; } @@ -5171,7 +5690,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang) beg = rb_pat_search(pat, str, 0, need_backref); if (beg < 0) { if (bang) return Qnil; /* no match, no substitution */ - return rb_str_dup(str); + return str_duplicate(rb_cString, str); } offset = 0; @@ -5252,7 +5771,6 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang) str_shared_replace(str, dest); } else { - RBASIC_SET_CLASS(dest, rb_obj_class(str)); str = dest; } @@ -5262,15 +5780,19 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang) /* * call-seq: - * str.gsub!(pattern, replacement) -> str or nil - * str.gsub!(pattern, hash) -> str or nil - * str.gsub!(pattern) {|match| block } -> str or nil - * str.gsub!(pattern) -> an_enumerator + * gsub!(pattern, replacement) -> self or nil + * gsub!(pattern) {|match| ... } -> self or nil + * gsub!(pattern) -> an_enumerator + * + * Performs the specified substring replacement(s) on +self+; + * returns +self+ if any replacement occurred, +nil+ otherwise. + * + * See {Substitution Methods}[#class-String-label-Substitution+Methods]. + * + * Returns an Enumerator if no +replacement+ and no block given. + * + * Related: String#sub, String#gsub, String#sub!. * - * Performs the substitutions of String#gsub in place, returning - * str, or nil if no substitutions were - * performed. If no block and no replacement is given, an - * enumerator is returned instead. */ static VALUE @@ -5283,62 +5805,18 @@ rb_str_gsub_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.gsub(pattern, replacement) -> new_str - * str.gsub(pattern, hash) -> new_str - * str.gsub(pattern) {|match| block } -> new_str - * str.gsub(pattern) -> enumerator - * - * Returns a copy of str with all occurrences of - * pattern substituted for the second argument. The pattern is - * typically a Regexp; if given as a String, any - * regular expression metacharacters it contains will be interpreted - * literally, e.g. \d will match a backslash followed by 'd', - * instead of a digit. - * - * If +replacement+ is a String it will be substituted for the matched text. - * It may contain back-references to the pattern's capture groups of the form - * \d, where d is a group number, or - * \k, where n is a group name. - * Similarly, \&, \', \`, and - * \+ correspond to special variables, $&, - * $', $`, and $+, respectively. - * (See rdoc-ref:regexp.rdoc for details.) - * \0 is the same as \&. - * \\\\ is interpreted as an escape, i.e., a single backslash. - * Note that, within +replacement+ the special match variables, such as - * $&, will not refer to the current match. - * - * If the second argument is a Hash, and the matched text is one - * of its keys, the corresponding value is the replacement string. - * - * In the block form, the current match string is passed in as a parameter, - * and variables such as $1, $2, $`, - * $&, and $' will be set appropriately. - * (See rdoc-ref:regexp.rdoc for details.) - * The value returned by the block will be substituted for the match on each - * call. - * - * When neither a block nor a second argument is supplied, an - * Enumerator is returned. - * - * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*" - * "hello".gsub(/([aeiou])/, '<\1>') #=> "hll" - * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 " - * "hello".gsub(/(?[aeiou])/, '{\k}') #=> "h{e}ll{o}" - * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" - * - * Note that a string literal consumes backslashes. - * (See rdoc-ref:syntax/literals.rdoc for details on string literals.) - * Back-references are 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 first to 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 a lot of backslashes. + * gsub(pattern, replacement) -> new_string + * gsub(pattern) {|match| ... } -> new_string + * gsub(pattern) -> enumerator + * + * Returns a copy of +self+ with all occurrences of the given +pattern+ replaced. + * + * See {Substitution Methods}[#class-String-label-Substitution+Methods]. + * + * Returns an Enumerator if no +replacement+ and no block given. + * + * Related: String#sub, String#sub!, String#gsub!. + * */ static VALUE @@ -5350,13 +5828,13 @@ rb_str_gsub(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.replace(other_str) -> str + * replace(other_string) -> self + * + * Replaces the contents of +self+ with the contents of +other_string+: * - * Replaces the contents of str with the corresponding - * values in other_str. + * s = 'foo' # => "foo" + * s.replace('bar') # => "bar" * - * s = "hello" #=> "hello" - * s.replace "world" #=> "world" */ VALUE @@ -5372,12 +5850,13 @@ rb_str_replace(VALUE str, VALUE str2) /* * call-seq: - * string.clear -> string + * clear -> self * - * Makes string empty. + * Removes the contents of +self+: + * + * s = 'foo' # => "foo" + * s.clear # => "" * - * a = "abcde" - * a.clear #=> "" */ static VALUE @@ -5396,12 +5875,13 @@ rb_str_clear(VALUE str) /* * call-seq: - * string.chr -> string + * chr -> string + * + * Returns a string containing the first character of +self+: * - * Returns a one-character string at the beginning of the string. + * s = 'foo' # => "foo" + * s.chr # => "f" * - * a = "abcde" - * a.chr #=> "a" */ static VALUE @@ -5412,9 +5892,15 @@ rb_str_chr(VALUE str) /* * call-seq: - * str.getbyte(index) -> 0 .. 255 + * getbyte(index) -> integer + * + * Returns the byte at zero-based +index+ as an integer: + * + * s = 'abcde' # => "abcde" + * s.getbyte(0) # => 97 + * s.getbyte(1) # => 98 * - * returns the indexth byte as an integer. + * Related: String#setbyte. */ static VALUE rb_str_getbyte(VALUE str, VALUE index) @@ -5431,17 +5917,22 @@ rb_str_getbyte(VALUE str, VALUE index) /* * call-seq: - * str.setbyte(index, integer) -> integer + * setbyte(index, integer) -> integer * - * modifies the indexth byte as integer. + * Sets the byte at zero-based +index+ to +integer+; returns +integer+: + * + * s = 'abcde' # => "abcde" + * s.setbyte(0, 98) # => 98 + * s # => "bbcde" + * + * Related: String#getbyte. */ static VALUE rb_str_setbyte(VALUE str, VALUE index, VALUE value) { long pos = NUM2LONG(index); long len = RSTRING_LEN(str); - char *head, *left = 0; - unsigned char *ptr; + char *ptr, *head, *left = 0; rb_encoding *enc; int cr = ENC_CODERANGE_UNKNOWN, width, nlen; @@ -5452,18 +5943,18 @@ rb_str_setbyte(VALUE str, VALUE index, VALUE value) VALUE v = rb_to_int(value); VALUE w = rb_int_and(v, INT2FIX(0xff)); - unsigned char byte = NUM2INT(w) & 0xFF; + char byte = (char)(NUM2INT(w) & 0xFF); if (!str_independent(str)) str_make_independent(str); enc = STR_ENC_GET(str); head = RSTRING_PTR(str); - ptr = (unsigned char *)&head[pos]; + ptr = &head[pos]; if (!STR_EMBED_P(str)) { cr = ENC_CODERANGE(str); switch (cr) { case ENC_CODERANGE_7BIT: - left = (char *)ptr; + left = ptr; *ptr = byte; if (ISASCII(byte)) goto end; nlen = rb_enc_precise_mbclen(left, head+len, enc); @@ -5515,12 +6006,12 @@ str_byte_substr(VALUE str, long beg, long len, int empty) if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) && SHARABLE_SUBSTRING_P(beg, len, n)) { str2 = rb_str_new_frozen(str); - str2 = str_new_shared(rb_obj_class(str2), str2); + str2 = str_new_shared(rb_cString, str2); RSTRING(str2)->as.heap.ptr += beg; RSTRING(str2)->as.heap.len = len; } else { - str2 = rb_str_new_with_class(str, p, len); + str2 = rb_str_new(p, len); } str_enc_copy(str2, str); @@ -5572,25 +6063,45 @@ str_byte_aref(VALUE str, VALUE indx) /* * call-seq: - * str.byteslice(integer) -> new_str or nil - * str.byteslice(integer, integer) -> new_str or nil - * str.byteslice(range) -> new_str or nil + * byteslice(index, length = 1) -> string or nil + * byteslice(range) -> string or nil + * + * Returns a substring of +self+, or +nil+ if the substring cannot be constructed. * - * Byte Reference---If passed a single Integer, returns a - * substring of one byte at that position. If passed two Integer - * objects, returns a substring starting at the offset given by the first, and - * a length given by the second. If given a Range, a substring containing - * bytes at offsets given by the range is returned. In all three cases, if - * an offset is negative, it is counted from the end of str. Returns - * nil if the initial offset falls outside the string, the length - * is negative, or the beginning of the range is greater than the end. - * The encoding of the resulted string keeps original encoding. + * With integer arguments +index+ and +length+ given, + * returns the substring beginning at the given +index+ + * of the given +length+ (if possible), + * or +nil+ if +length+ is negative or +index+ falls outside of +self+: + * + * s = '0123456789' # => "0123456789" + * s.byteslice(2) # => "2" + * s.byteslice(200) # => nil + * s.byteslice(4, 3) # => "456" + * s.byteslice(4, 30) # => "456789" + * s.byteslice(4, -1) # => nil + * s.byteslice(40, 2) # => nil + * + * In either case above, counts backwards from the end of +self+ + * if +index+ 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 + * + * In all cases, a returned string has the same encoding as +self+: + * + * s.encoding # => # + * s.byteslice(4).encoding # => # * - * "hello".byteslice(1) #=> "e" - * "hello".byteslice(-1) #=> "o" - * "hello".byteslice(1, 2) #=> "el" - * "\x80\u3042".byteslice(1, 3) #=> "\u3042" - * "\x03\u3042\xff".byteslice(1..3) #=> "\u3042" */ static VALUE @@ -5607,11 +6118,12 @@ rb_str_byteslice(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.reverse -> new_str + * reverse -> string + * + * Returns a new string with the characters from +self+ in reverse order. * - * Returns a new string with the characters from str in reverse order. + * 'stressed'.reverse # => "desserts" * - * "stressed".reverse #=> "desserts" */ static VALUE @@ -5622,9 +6134,9 @@ rb_str_reverse(VALUE str) char *s, *e, *p; int cr; - if (RSTRING_LEN(str) <= 1) return rb_str_dup(str); + if (RSTRING_LEN(str) <= 1) return str_duplicate(rb_cString, str); enc = STR_ENC_GET(str); - rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); + rev = rb_str_new(0, RSTRING_LEN(str)); s = RSTRING_PTR(str); e = RSTRING_END(str); p = RSTRING_END(rev); cr = ENC_CODERANGE(str); @@ -5667,9 +6179,14 @@ rb_str_reverse(VALUE str) /* * call-seq: - * str.reverse! -> str + * reverse! -> self + * + * Returns +self+ with its characters reversed: + * + * s = 'stressed' + * s.reverse! # => "desserts" + * s # => "desserts" * - * Reverses str in place. */ static VALUE @@ -5701,14 +6218,15 @@ rb_str_reverse_bang(VALUE str) /* * call-seq: - * str.include? other_str -> true or false + * include? other_string -> true or false * - * Returns true if str contains the given string or - * character. + * Returns +true+ if +self+ contains +other_string+, +false+ otherwise: + * + * s = 'foo' + * s.include?('f') # => true + * s.include?('fo') # => true + * s.include?('food') # => false * - * "hello".include? "lo" #=> true - * "hello".include? "ol" #=> false - * "hello".include? ?h #=> true */ static VALUE @@ -5719,30 +6237,30 @@ rb_str_include(VALUE str, VALUE arg) StringValue(arg); i = rb_str_index(str, arg, 0); - if (i == -1) return Qfalse; - return Qtrue; + return RBOOL(i != -1); } /* * call-seq: - * str.to_i(base=10) -> integer + * to_i(base = 10) -> integer + * + * Returns the result of interpreting leading characters in +self+ + * as an integer in the given +base+ (which must be in (2..36)): + * + * '123456'.to_i # => 123456 + * '123def'.to_i(16) # => 1195503 + * + * Characters past a leading valid number (in the given +base+) are ignored: + * + * '12.345'.to_i # => 12 + * '12345'.to_i(2) # => 1 * - * Returns the result of interpreting leading characters in str as an - * integer base base (between 2 and 36). Extraneous characters past the - * end of a valid number are ignored. If there is not a valid number at the - * start of str, 0 is returned. This method never raises an - * exception when base is valid. + * Returns zero if there is no leading valid number: + * + * 'abcdef'.to_i # => 0 + * '2'.to_i(2) # => 0 * - * "12345".to_i #=> 12345 - * "99 red balloons".to_i #=> 99 - * "0a".to_i #=> 0 - * "0a".to_i(16) #=> 10 - * "hello".to_i #=> 0 - * "1100101".to_i(2) #=> 101 - * "1100101".to_i(8) #=> 294977 - * "1100101".to_i(10) #=> 1100101 - * "1100101".to_i(16) #=> 17826049 */ static VALUE @@ -5759,16 +6277,21 @@ rb_str_to_i(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.to_f -> float + * to_f -> float + * + * Returns the result of interpreting leading characters in +self+ as a Float: + * + * '3.14159'.to_f # => 3.14159 + '1.234e-2'.to_f # => 0.01234 + * + * Characters past a leading valid number (in the given +base+) are ignored: * - * Returns the result of interpreting leading characters in str as a - * floating point number. Extraneous characters past the end of a valid number - * are ignored. If there is not a valid number at the start of str, - * 0.0 is returned. This method never raises an exception. + * '3.14 (pi to two places)'.to_f # => 3.14 + * + * Returns zero if there is no leading valid number: + * + * 'abcdef'.to_f # => 0.0 * - * "123.45e1".to_f #=> 1234.5 - * "45.67 degrees".to_f #=> 45.67 - * "thx1138".to_f #=> 0.0 */ static VALUE @@ -5780,12 +6303,13 @@ rb_str_to_f(VALUE str) /* * call-seq: - * str.to_s -> str - * str.to_str -> str + * to_s -> self or string * - * Returns +self+. + * Returns +self+ if +self+ is a \String, + * or +self+ converted to a \String if +self+ is a subclass of \String. + * + * String#to_str is an alias for String#to_s. * - * If called on a subclass of String, converts the receiver to a String object. */ static VALUE @@ -5915,15 +6439,17 @@ rb_str_escape(VALUE str) } /* - * call-seq: - * str.inspect -> string + * call-seq: + * inspect -> string + * + * Returns a printable version of +self+, enclosed in double-quotes, + * and with special characters escaped: * - * Returns a printable version of _str_, surrounded by quote marks, - * with special characters escaped. + * s = "foo\tbar\tbaz\n" + * # => "foo\tbar\tbaz\n" + * s.inspect + * # => "\"foo\\tbar\\tbaz\\n\"" * - * str = "hello" - * str[3] = "\b" - * str.inspect #=> "\"hel\\bo\"" */ VALUE @@ -6024,18 +6550,17 @@ rb_str_inspect(VALUE str) /* * call-seq: - * str.dump -> new_str + * dump -> string * - * Returns a quoted version of the string with all non-printing characters - * replaced by \xHH notation and all special characters escaped. + * Returns a printable version of +self+, enclosed in double-quotes, + * with special characters escaped, and with non-printing characters + * replaced by hexadecimal notation: * - * This method can be used for round-trip: if the resulting +new_str+ is - * eval'ed, it will produce the original string. + * "hello \n ''".dump # => "\"hello \\n ''\"" + * "\f\x00\xff\\\"".dump # => "\"\\f\\x00\\xFF\\\\\\\"\"" * - * "hello \n ''".dump #=> "\"hello \\n ''\"" - * "\f\x00\xff\\\"".dump #=> "\"\\f\\x00\\xFF\\\\\\\"\"" + * Related: String#undump (inverse of String#dump). * - * See also String#undump. */ VALUE @@ -6103,7 +6628,7 @@ rb_str_dump(VALUE str) len += clen; } - result = rb_str_new_with_class(str, 0, len); + result = rb_str_new(0, len); p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); q = RSTRING_PTR(result); qend = q + len + 1; @@ -6205,9 +6730,8 @@ unescape_ascii(unsigned int c) return '\007'; case 'e': return 033; - default: - UNREACHABLE; } + UNREACHABLE_RETURN(-1); } static void @@ -6321,12 +6845,17 @@ static VALUE rb_str_is_ascii_only_p(VALUE str); /* * call-seq: - * str.undump -> new_str + * undump -> string + * + * Returns an unescaped version of +self+: * - * Returns an unescaped version of the string. - * This does the inverse of String#dump. + * s_orig = "\f\x00\xff\\\"" # => "\f\u0000\xFF\\\"" + * s_dumped = s_orig.dump # => "\"\\f\\x00\\xFF\\\\\\\"\"" + * s_undumped = s_dumped.undump # => "\f\u0000\xFF\\\"" + * s_undumped == s_orig # => true + * + * Related: String#dump (inverse of String#undump). * - * "\"hello \\n ''\"".undump #=> "hello \n ''" */ static VALUE @@ -6345,7 +6874,7 @@ str_undump(VALUE str) rb_raise(rb_eRuntimeError, "non-ASCII character detected"); } if (!str_null_check(str, &w)) { - rb_raise(rb_eRuntimeError, "string contains null byte"); + rb_raise(rb_eRuntimeError, "string contains null byte"); } if (RSTRING_LEN(str) < 2) goto invalid_format; if (*s != '"') goto invalid_format; @@ -6527,7 +7056,7 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc) size_t buffer_count = 0; int buffer_length_or_invalid; - if (RSTRING_LEN(source) == 0) return rb_str_dup(source); + if (RSTRING_LEN(source) == 0) return str_duplicate(rb_cString, source); source_current = (OnigUChar*)RSTRING_PTR(source); source_end = (OnigUChar*)RSTRING_END(source); @@ -6546,7 +7075,7 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc) current_buffer->next = NULL; current_buffer->capa = capa; buffer_length_or_invalid = enc->case_map(flags, - (const OnigUChar**)&source_current, source_end, + &source_current, source_end, current_buffer->space, current_buffer->space+current_buffer->capa, enc); @@ -6563,12 +7092,12 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc) } if (buffer_count==1) { - target = rb_str_new_with_class(source, (const char*)current_buffer->space, target_length); + target = rb_str_new((const char*)current_buffer->space, target_length); } else { char *target_current; - target = rb_str_new_with_class(source, 0, target_length); + target = rb_str_new(0, target_length); target_current = RSTRING_PTR(target); current_buffer = DATA_PTR(buffer_anchor); while (current_buffer) { @@ -6635,7 +7164,7 @@ upcase_single(VALUE str) while (s < send) { unsigned int c = *(unsigned char*)s; - if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') { + if ('a' <= c && c <= 'z') { *s = 'A' + (c - 'a'); modified = true; } @@ -6646,13 +7175,21 @@ upcase_single(VALUE str) /* * call-seq: - * str.upcase! -> str or nil - * str.upcase!([options]) -> str or nil + * upcase!(*options) -> self or nil * - * Upcases the contents of str, returning nil if no changes - * were made. + * Upcases the characters in +self+; + * returns +self+ if any changes were made, +nil+ otherwise: + * + * s = 'Hello World!' # => "Hello World!" + * s.upcase! # => "HELLO WORLD!" + * s # => "HELLO WORLD!" + * s.upcase! # => nil + * + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#upcase, String#downcase, String#downcase!. * - * See String#downcase for meaning of +options+ and use with different encodings. */ static VALUE @@ -6680,15 +7217,18 @@ rb_str_upcase_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.upcase -> new_str - * str.upcase([options]) -> new_str + * upcase(*options) -> string + * + * Returns a string containing the upcased characters in +self+: + * + * s = 'Hello World!' # => "Hello World!" + * s.upcase # => "HELLO WORLD!" * - * Returns a copy of str with all lowercase letters replaced with their - * uppercase counterparts. + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. * - * See String#downcase for meaning of +options+ and use with different encodings. + * Related: String#upcase!, String#downcase, String#downcase!. * - * "hEllO".upcase #=> "HELLO" */ static VALUE @@ -6701,12 +7241,12 @@ rb_str_upcase(int argc, VALUE *argv, VALUE str) flags = check_case_options(argc, argv, flags); enc = str_true_enc(str); if (case_option_single_p(flags, enc, str)) { - ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str)); + ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str)); str_enc_copy(ret, str); upcase_single(ret); } else if (flags&ONIGENC_CASE_ASCII_ONLY) { - ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); + ret = rb_str_new(0, RSTRING_LEN(str)); rb_str_ascii_casemap(str, ret, &flags, enc); } else { @@ -6725,7 +7265,7 @@ downcase_single(VALUE str) while (s < send) { unsigned int c = *(unsigned char*)s; - if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') { + if ('A' <= c && c <= 'Z') { *s = 'a' + (c - 'A'); modified = true; } @@ -6737,13 +7277,21 @@ downcase_single(VALUE str) /* * call-seq: - * str.downcase! -> str or nil - * str.downcase!([options]) -> str or nil + * downcase!(*options) -> self or nil * - * Downcases the contents of str, returning nil if no - * changes were made. + * Downcases the characters in +self+; + * returns +self+ if any changes were made, +nil+ otherwise: + * + * s = 'Hello World!' # => "Hello World!" + * s.downcase! # => "hello world!" + * s # => "hello world!" + * s.downcase! # => nil + * + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#downcase, String#upcase, String#upcase!. * - * See String#downcase for meaning of +options+ and use with different encodings. */ static VALUE @@ -6771,52 +7319,18 @@ rb_str_downcase_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.downcase -> new_str - * str.downcase([options]) -> new_str - * - * Returns a copy of str with all uppercase letters replaced with their - * lowercase counterparts. Which letters exactly are replaced, and by which - * other letters, depends on the presence or absence of options, and on the - * +encoding+ of the string. - * - * The meaning of the +options+ is as follows: - * - * No option :: - * Full Unicode case mapping, suitable for most languages - * (see :turkic and :lithuanian options below for exceptions). - * Context-dependent case mapping as described in Table 3-14 of the - * Unicode standard is currently not supported. - * :ascii :: - * Only the ASCII region, i.e. the characters ``A'' to ``Z'' and - * ``a'' to ``z'', are affected. - * This option cannot be combined with any other option. - * :turkic :: - * Full Unicode case mapping, adapted for Turkic languages - * (Turkish, Azerbaijani, ...). This means that upper case I is mapped to - * lower case dotless i, and so on. - * :lithuanian :: - * Currently, just full Unicode case mapping. In the future, full Unicode - * case mapping adapted for Lithuanian (keeping the dot on the lower case - * i even if there is an accent on top). - * :fold :: - * Only available on +downcase+ and +downcase!+. Unicode case folding, - * which is more far-reaching than Unicode case mapping. - * This option currently cannot be combined with any other option - * (i.e. there is currently no variant for turkic languages). - * - * Please note that several assumptions that are valid for ASCII-only case - * conversions do not hold for more general case conversions. For example, - * the length of the result may not be the same as the length of the input - * (neither in characters nor in bytes), some roundtrip assumptions - * (e.g. str.downcase == str.upcase.downcase) may not apply, and Unicode - * normalization (i.e. String#unicode_normalize) is not necessarily maintained - * by case mapping operations. - * - * Non-ASCII case mapping/folding is currently supported for UTF-8, - * UTF-16BE/LE, UTF-32BE/LE, and ISO-8859-1~16 Strings/Symbols. - * This support will be extended to other encodings. - * - * "hEllO".downcase #=> "hello" + * downcase(*options) -> string + * + * Returns a string containing the downcased characters in +self+: + * + * s = 'Hello World!' # => "Hello World!" + * s.downcase # => "hello world!" + * + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#downcase!, String#upcase, String#upcase!. + * */ static VALUE @@ -6829,12 +7343,12 @@ rb_str_downcase(int argc, VALUE *argv, VALUE str) flags = check_case_options(argc, argv, flags); enc = str_true_enc(str); if (case_option_single_p(flags, enc, str)) { - ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str)); + ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str)); str_enc_copy(ret, str); downcase_single(ret); } else if (flags&ONIGENC_CASE_ASCII_ONLY) { - ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); + ret = rb_str_new(0, RSTRING_LEN(str)); rb_str_ascii_casemap(str, ret, &flags, enc); } else { @@ -6847,20 +7361,22 @@ rb_str_downcase(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.capitalize! -> str or nil - * str.capitalize!([options]) -> str or nil + * capitalize!(*options) -> self or nil * - * Modifies str by converting the first character to uppercase and the - * remainder to lowercase. Returns nil if no changes are made. - * There is an exception for modern Georgian (mkhedruli/MTAVRULI), where - * the result is the same as for String#downcase, to avoid mixed case. + * Upcases the first character in +self+; + * downcases the remaining characters; + * returns +self+ if any changes were made, +nil+ otherwise: * - * See String#downcase for meaning of +options+ and use with different encodings. + * s = 'hello World!' # => "hello World!" + * s.capitalize! # => "Hello world!" + * s # => "Hello world!" + * s.capitalize! # => nil + * + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#capitalize. * - * a = "hello" - * a.capitalize! #=> "Hello" - * a #=> "Hello" - * a.capitalize! #=> nil */ static VALUE @@ -6885,17 +7401,20 @@ rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.capitalize -> new_str - * str.capitalize([options]) -> new_str + * capitalize(*options) -> string + * + * Returns a string containing the characters in +self+; + * the first character is upcased; + * the remaining characters are downcased: * - * Returns a copy of str with the first character converted to uppercase - * and the remainder to lowercase. + * s = 'hello World!' # => "hello World!" + * s.capitalize # => "Hello world!" * - * See String#downcase for meaning of +options+ and use with different encodings. + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#capitalize!. * - * "hello".capitalize #=> "Hello" - * "HELLO".capitalize #=> "Hello" - * "123ABC".capitalize #=> "123abc" */ static VALUE @@ -6909,7 +7428,7 @@ rb_str_capitalize(int argc, VALUE *argv, VALUE str) enc = str_true_enc(str); if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str; if (flags&ONIGENC_CASE_ASCII_ONLY) { - ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); + ret = rb_str_new(0, RSTRING_LEN(str)); rb_str_ascii_casemap(str, ret, &flags, enc); } else { @@ -6921,14 +7440,22 @@ rb_str_capitalize(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.swapcase! -> str or nil - * str.swapcase!([options]) -> str or nil + * swapcase!(*options) -> self or nil * - * Equivalent to String#swapcase, but modifies the receiver in place, - * returning str, or nil if no changes were made. + * Upcases each lowercase character in +self+; + * downcases uppercase character; + * returns +self+ if any changes were made, +nil+ otherwise: + * + * s = 'Hello World!' # => "Hello World!" + * s.swapcase! # => "hELLO wORLD!" + * s # => "Hello World!" + * ''.swapcase! # => nil + * + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#swapcase. * - * See String#downcase for meaning of +options+ and use with - * different encodings. */ static VALUE @@ -6952,16 +7479,20 @@ rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str) /* * call-seq: - * str.swapcase -> new_str - * str.swapcase([options]) -> new_str + * swapcase(*options) -> string + * + * Returns a string containing the characters in +self+, with cases reversed; + * each uppercase character is downcased; + * each lowercase character is upcased: * - * Returns a copy of str with uppercase alphabetic characters converted - * to lowercase and lowercase characters converted to uppercase. + * s = 'Hello World!' # => "Hello World!" + * s.swapcase # => "hELLO wORLD!" * - * See String#downcase for meaning of +options+ and use with different encodings. + * The casing may be affected by the given +options+; + * see {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: String#swapcase!. * - * "Hello".swapcase #=> "hELLO" - * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" */ static VALUE @@ -6973,9 +7504,9 @@ rb_str_swapcase(int argc, VALUE *argv, VALUE str) flags = check_case_options(argc, argv, flags); enc = str_true_enc(str); - if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str; + if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str_duplicate(rb_cString, str); if (flags&ONIGENC_CASE_ASCII_ONLY) { - ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); + ret = rb_str_new(0, RSTRING_LEN(str)); rb_str_ascii_casemap(str, ret, &flags, enc); } else { @@ -6998,8 +7529,8 @@ trnext(struct tr *t, rb_encoding *enc) int n; for (;;) { + nextpart: if (!t->gen) { -nextpart: if (t->p == t->pend) return -1; if (rb_enc_ascget(t->p, t->pend, &n, enc) == '\\' && t->p + n < t->pend) { t->p += n; @@ -7349,18 +7880,19 @@ rb_str_tr_bang(VALUE str, VALUE src, VALUE repl) static VALUE rb_str_tr(VALUE str, VALUE src, VALUE repl) { - str = rb_str_dup(str); + str = str_duplicate(rb_cString, str); tr_trans(str, src, repl, 0); return str; } -#define TR_TABLE_SIZE 257 +#define TR_TABLE_MAX (UCHAR_MAX+1) +#define TR_TABLE_SIZE (TR_TABLE_MAX+1) static void tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first, VALUE *tablep, VALUE *ctablep, rb_encoding *enc) { const unsigned int errc = -1; - char buf[256]; + char buf[TR_TABLE_MAX]; struct tr tr; unsigned int c; VALUE table = 0, ptable = 0; @@ -7374,26 +7906,26 @@ tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first, tr.p += l; } if (first) { - for (i=0; i<256; i++) { + for (i=0; i 0); } else { do { - rb_yield(str_new_empty(str)); + rb_yield(str_new_empty_String(str)); } while (--empty_count > 0); } } @@ -7836,6 +8367,35 @@ split_string(VALUE result, VALUE str, long beg, long len, long empty_count) return empty_count; } +typedef enum { + SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS +} split_type_t; + +static split_type_t +literal_split_pattern(VALUE spat, split_type_t default_type) +{ + rb_encoding *enc = STR_ENC_GET(spat); + const char *ptr; + long len; + RSTRING_GETMEM(spat, ptr, len); + if (len == 0) { + /* Special case - split into chars */ + return SPLIT_TYPE_CHARS; + } + else if (rb_enc_asciicompat(enc)) { + if (len == 1 && ptr[0] == ' ') { + return SPLIT_TYPE_AWK; + } + } + else { + int l; + if (rb_enc_ascget(ptr, ptr + len, &l, enc) == ' ' && len == l) { + return SPLIT_TYPE_AWK; + } + } + return default_type; +} + /* * call-seq: * str.split(pattern=nil, [limit]) -> an_array @@ -7897,7 +8457,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) rb_encoding *enc; VALUE spat; VALUE limit; - enum {awk, string, regexp, chars} split_type; + split_type_t split_type; long beg, end, i = 0, empty_count = -1; int lim = 0; VALUE result, tmp; @@ -7908,11 +8468,11 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) if (lim <= 0) limit = Qnil; else if (lim == 1) { if (RSTRING_LEN(str) == 0) - return result ? rb_ary_new2(0) : str; - tmp = rb_str_dup(str); + return result ? rb_ary_new2(0) : str; + tmp = str_duplicate(rb_cString, str); if (!result) { rb_yield(tmp); - return str; + return str; } return rb_ary_new3(1, tmp); } @@ -7921,41 +8481,38 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) if (NIL_P(limit) && !lim) empty_count = 0; enc = STR_ENC_GET(str); - split_type = regexp; + split_type = SPLIT_TYPE_REGEXP; if (!NIL_P(spat)) { spat = get_pat_quoted(spat, 0); } else if (NIL_P(spat = rb_fs)) { - split_type = awk; + split_type = SPLIT_TYPE_AWK; } else if (!(spat = rb_fs_check(spat))) { rb_raise(rb_eTypeError, "value of $; must be String or Regexp"); } else { - rb_warn("$; is set to non-nil value"); - } - if (split_type != awk) { - if (BUILTIN_TYPE(spat) == T_STRING) { - rb_encoding *enc2 = STR_ENC_GET(spat); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$; is set to non-nil value"); + } + if (split_type != SPLIT_TYPE_AWK) { + switch (BUILTIN_TYPE(spat)) { + case T_REGEXP: + rb_reg_options(spat); /* check if uninitialized */ + tmp = RREGEXP_SRC(spat); + split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP); + if (split_type == SPLIT_TYPE_AWK) { + spat = tmp; + split_type = SPLIT_TYPE_STRING; + } + break; + case T_STRING: mustnot_broken(spat); - split_type = string; - if (RSTRING_LEN(spat) == 0) { - /* Special case - split into chars */ - split_type = chars; - } - else if (rb_enc_asciicompat(enc2) == 1) { - if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') { - split_type = awk; - } - } - else { - int l; - if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' && - RSTRING_LEN(spat) == l) { - split_type = awk; - } - } + split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING); + break; + + default: + UNREACHABLE_RETURN(Qnil); } } @@ -7965,7 +8522,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) beg = 0; char *ptr = RSTRING_PTR(str); char *eptr = RSTRING_END(str); - if (split_type == awk) { + if (split_type == SPLIT_TYPE_AWK) { char *bptr = ptr; int skip = 1; unsigned int c; @@ -8023,7 +8580,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) } } } - else if (split_type == string) { + else if (split_type == SPLIT_TYPE_STRING) { char *str_start = ptr; char *substr_start = ptr; char *sptr = RSTRING_PTR(spat); @@ -8046,7 +8603,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) } beg = ptr - str_start; } - else if (split_type == chars) { + else if (split_type == SPLIT_TYPE_CHARS) { char *str_start = ptr; int n; @@ -8068,11 +8625,12 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) struct re_registers *regs; VALUE match = 0; - for (; (end = rb_reg_search(spat, str, start, 0)) >= 0; + for (; rb_reg_search(spat, str, start, 0) >= 0; (match ? (rb_match_unbusy(match), rb_backref_set(match)) : (void)0)) { match = rb_backref_get(); if (!result) rb_match_busy(match); regs = RMATCH_REGS(match); + end = BEG(0); if (start == end && BEG(0) == END(0)) { if (!ptr) { SPLIT_STR(0, 0); @@ -8152,6 +8710,21 @@ chomp_newline(const char *p, const char *e, rb_encoding *enc) return e; } +static VALUE +get_rs(void) +{ + VALUE rs = rb_rs; + if (!NIL_P(rs) && + (!RB_TYPE_P(rs, T_STRING) || + RSTRING_LEN(rs) != 1 || + RSTRING_PTR(rs)[0] != '\n')) { + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$/ is set to non-default value"); + } + return rs; +} + +#define rb_rs get_rs() + static VALUE rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary) { @@ -8379,7 +8952,7 @@ rb_str_enumerate_bytes(VALUE str, VALUE ary) long i; for (i=0; i 1) { + const char *pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc); + if (rb_enc_is_newline(pp, e, enc)) { + e = pp; + } + pp = e - rb_enc_mbminlen(enc); + if (pp >= p) { + pp = rb_enc_left_char_head(p, pp, e, enc); + if (rb_enc_ascget(pp, e, 0, enc) == '\r') { + e = pp; + } + } + } + else { + switch (*(e-1)) { /* not e[-1] to get rid of VC bug */ + case '\n': + if (--e > p && *(e-1) == '\r') { + --e; + } + break; + case '\r': + --e; + break; + } + } + return e - p; +} static long chompped_length(VALUE str, VALUE rs) @@ -8812,34 +9416,7 @@ chompped_length(VALUE str, VALUE rs) if (len == 0) return 0; e = p + len; if (rs == rb_default_rs) { - smart_chomp: - enc = rb_enc_get(str); - if (rb_enc_mbminlen(enc) > 1) { - pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc); - if (rb_enc_is_newline(pp, e, enc)) { - e = pp; - } - pp = e - rb_enc_mbminlen(enc); - if (pp >= p) { - pp = rb_enc_left_char_head(p, pp, e, enc); - if (rb_enc_ascget(pp, e, 0, enc) == '\r') { - e = pp; - } - } - } - else { - switch (*(e-1)) { /* not e[-1] to get rid of VC bug */ - case '\n': - if (--e > p && *(e-1) == '\r') { - --e; - } - break; - case '\r': - --e; - break; - } - } - return e - p; + return smart_chomp(str, e, p); } enc = rb_enc_get(str); @@ -8875,11 +9452,11 @@ chompped_length(VALUE str, VALUE rs) if (rslen == rb_enc_mbminlen(enc)) { if (rslen == 1) { if (newline == '\n') - goto smart_chomp; + return smart_chomp(str, e, p); } else { if (rb_enc_is_newline(rsptr, rsptr+rslen, enc)) - goto smart_chomp; + return smart_chomp(str, e, p); } } @@ -8960,7 +9537,7 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str) * Returns a new String with the given record separator removed * from the end of str (if present). If $/ has not been * changed from the default Ruby record separator, then chomp also - * removes carriage return characters (that is it will remove \n, + * removes carriage return characters (that is, it will remove \n, * \r, and \r\n). If $/ is an empty string, * it will remove all trailing newlines from the string. * @@ -8979,7 +9556,7 @@ static VALUE rb_str_chomp(int argc, VALUE *argv, VALUE str) { VALUE rs = chomp_rs(argc, argv); - if (NIL_P(rs)) return rb_str_dup(str); + if (NIL_P(rs)) return str_duplicate(rb_cString, str); return rb_str_subseq(str, 0, chompped_length(str, rs)); } @@ -8992,14 +9569,14 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc) /* remove spaces at head */ if (single_byte_optimizable(str)) { - while (s < e && ascii_isspace(*s)) s++; + while (s < e && (*s == '\0' || ascii_isspace(*s))) s++; } else { while (s < e) { int n; unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc); - if (!rb_isspace(cc)) break; + if (cc && !rb_isspace(cc)) break; s += n; } } @@ -9037,9 +9614,7 @@ rb_str_lstrip_bang(VALUE str) s = start + loffset; memmove(start, s, len); STR_SET_LEN(str, len); -#if !SHARABLE_MIDDLE_SUBSTRING TERM_FILL(start+len, rb_enc_mbminlen(enc)); -#endif return str; } return Qnil; @@ -9066,7 +9641,7 @@ rb_str_lstrip(VALUE str) long len, loffset; RSTRING_GETMEM(str, start, len); loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str)); - if (loffset <= 0) return rb_str_dup(str); + if (loffset <= 0) return str_duplicate(rb_cString, str); return rb_str_subseq(str, loffset, len - loffset); } @@ -9126,9 +9701,7 @@ rb_str_rstrip_bang(VALUE str) long len = olen - roffset; STR_SET_LEN(str, len); -#if !SHARABLE_MIDDLE_SUBSTRING TERM_FILL(start+len, rb_enc_mbminlen(enc)); -#endif return str; } return Qnil; @@ -9159,7 +9732,7 @@ rb_str_rstrip(VALUE str) RSTRING_GETMEM(str, start, olen); roffset = rstrip_offset(str, start, start+olen, enc); - if (roffset <= 0) return rb_str_dup(str); + if (roffset <= 0) return str_duplicate(rb_cString, str); return rb_str_subseq(str, 0, olen-roffset); } @@ -9197,9 +9770,7 @@ rb_str_strip_bang(VALUE str) memmove(start, start + loffset, len); } STR_SET_LEN(str, len); -#if !SHARABLE_MIDDLE_SUBSTRING TERM_FILL(start+len, rb_enc_mbminlen(enc)); -#endif return str; } return Qnil; @@ -9232,7 +9803,7 @@ rb_str_strip(VALUE str) loffset = lstrip_offset(str, start, start+olen, enc); roffset = rstrip_offset(str, start+loffset, start+olen, enc); - if (loffset <= 0 && roffset <= 0) return rb_str_dup(str); + if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str); return rb_str_subseq(str, loffset, olen-loffset-roffset); } @@ -9396,6 +9967,42 @@ rb_str_oct(VALUE str) return rb_str_to_inum(str, -8, FALSE); } +#ifndef HAVE_CRYPT_R +# include "ruby/thread_native.h" +# include "ruby/atomic.h" + +static struct { + rb_atomic_t initialized; + rb_nativethread_lock_t lock; +} crypt_mutex; + +static void +crypt_mutex_destroy(void) +{ + RUBY_ASSERT_ALWAYS(crypt_mutex.initialized == 1); + rb_nativethread_lock_destroy(&crypt_mutex.lock); + crypt_mutex.initialized = 0; +} + +static void +crypt_mutex_initialize(void) +{ + rb_atomic_t i; + while ((i = RUBY_ATOMIC_CAS(crypt_mutex.initialized, 0, 2)) == 2); + switch (i) { + case 0: + rb_nativethread_lock_initialize(&crypt_mutex.lock); + atexit(crypt_mutex_destroy); + RUBY_ASSERT(crypt_mutex.initialized == 2); + RUBY_ATOMIC_CAS(crypt_mutex.initialized, 2, 1); + break; + case 1: + break; + default: + rb_bug("crypt_mutex.initialized: %d->%d", i, crypt_mutex.initialized); + } +} +#endif /* * call-seq: @@ -9440,7 +10047,7 @@ rb_str_oct(VALUE str) * * Even in the "modular" mode, some hash functions are considered * archaic and no longer recommended at all; for instance module * $1$ is officially abandoned by its author: see - * http://phk.freebsd.dk/sagas/md5crypt_eol.html . For another + * http://phk.freebsd.dk/sagas/md5crypt_eol/ . For another * instance module $3$ is considered completely * broken: see the manpage of FreeBSD. * @@ -9466,7 +10073,7 @@ rb_str_crypt(VALUE str, VALUE salt) # define CRYPT_END() ALLOCV_END(databuf) #else extern char *crypt(const char *, const char *); -# define CRYPT_END() (void)0 +# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock) #endif VALUE result; const char *s, *saltp; @@ -9478,14 +10085,12 @@ rb_str_crypt(VALUE str, VALUE salt) StringValue(salt); mustnot_wchar(str); mustnot_wchar(salt); - if (RSTRING_LEN(salt) < 2) { - short_salt: + s = StringValueCStr(str); + saltp = RSTRING_PTR(salt); + if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) { rb_raise(rb_eArgError, "salt too short (need >=2 bytes)"); } - s = StringValueCStr(str); - saltp = RSTRING_PTR(salt); - if (!saltp[0] || !saltp[1]) goto short_salt; #ifdef BROKEN_CRYPT if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) { salt_8bit_clean[0] = saltp[0] & 0x7f; @@ -9501,6 +10106,8 @@ rb_str_crypt(VALUE str, VALUE salt) # endif res = crypt_r(s, saltp, data); #else + crypt_mutex_initialize(); + rb_nativethread_lock_lock(&crypt_mutex.lock); res = crypt(s, saltp); #endif if (!res) { @@ -9523,7 +10130,7 @@ rb_str_crypt(VALUE str, VALUE salt) * "a".ord #=> 97 */ -VALUE +static VALUE rb_str_ord(VALUE s) { unsigned int c; @@ -9625,7 +10232,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag) } } len = str_strlen(str, enc); /* rb_enc_check */ - if (width < 0 || len >= width) return rb_str_dup(str); + if (width < 0 || len >= width) return str_duplicate(rb_cString, str); n = width - len; llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2); rlen = n - llen; @@ -9641,7 +10248,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag) rb_raise(rb_eArgError, "argument too big"); } len += size; - res = str_new0(rb_obj_class(str), 0, len, termlen); + res = str_new0(rb_cString, 0, len, termlen); p = RSTRING_PTR(res); if (flen <= 1) { memset(p, *f, llen); @@ -9769,13 +10376,14 @@ rb_str_partition(VALUE str, VALUE sep) sep = get_pat_quoted(sep, 0); if (RB_TYPE_P(sep, T_REGEXP)) { - pos = rb_reg_search(sep, str, 0, 0); - if (pos < 0) { - failed: - return rb_ary_new3(3, rb_str_dup(str), str_new_empty(str), str_new_empty(str)); + if (rb_reg_search(sep, str, 0, 0) < 0) { + goto failed; } - sep = rb_str_subpat(str, sep, INT2FIX(0)); - if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed; + VALUE match = rb_backref_get(); + struct re_registers *regs = RMATCH_REGS(match); + + pos = BEG(0); + sep = rb_str_subseq(str, pos, END(0) - pos); } else { pos = rb_str_index(str, sep, 0); @@ -9785,6 +10393,9 @@ rb_str_partition(VALUE str, VALUE sep) sep, rb_str_subseq(str, pos+RSTRING_LEN(sep), RSTRING_LEN(str)-pos-RSTRING_LEN(sep))); + + failed: + return rb_ary_new3(3, str_duplicate(rb_cString, str), str_new_empty_String(str), str_new_empty_String(str)); } /* @@ -9800,43 +10411,53 @@ rb_str_partition(VALUE str, VALUE sep) * "hello".rpartition("l") #=> ["hel", "l", "o"] * "hello".rpartition("x") #=> ["", "", "hello"] * "hello".rpartition(/.l/) #=> ["he", "ll", "o"] + * + * The match from the end means starting at the possible last position, not + * the last of longest matches. + * + * "hello".rpartition(/l+/) #=> ["hel", "l", "o"] + * + * To partition at the last longest match, needs to combine with + * negative lookbehind. + * + * "hello".rpartition(/(? ["he", "ll", "o"] + * + * Or String#partition with negative lookforward. + * + * "hello".partition(/l+(?!.*l)/) #=> ["he", "ll", "o"] */ static VALUE rb_str_rpartition(VALUE str, VALUE sep) { long pos = RSTRING_LEN(str); - int regex = FALSE; + sep = get_pat_quoted(sep, 0); if (RB_TYPE_P(sep, T_REGEXP)) { - pos = rb_reg_search(sep, str, pos, 1); - regex = TRUE; + if (rb_reg_search(sep, str, pos, 1) < 0) { + goto failed; + } + VALUE match = rb_backref_get(); + struct re_registers *regs = RMATCH_REGS(match); + + pos = BEG(0); + sep = rb_str_subseq(str, pos, END(0) - pos); } else { - VALUE tmp; - - tmp = rb_check_string_type(sep); - if (NIL_P(tmp)) { - rb_raise(rb_eTypeError, "type mismatch: %s given", - rb_obj_classname(sep)); - } - sep = tmp; pos = rb_str_sublen(str, pos); pos = rb_str_rindex(str, sep, pos); + if (pos < 0) { + goto failed; + } + pos = rb_str_offset(str, pos); } - if (pos < 0) { - return rb_ary_new3(3, str_new_empty(str), str_new_empty(str), rb_str_dup(str)); - } - if (regex) { - sep = rb_reg_nth_match(0, rb_backref_get()); - } - else { - pos = rb_str_offset(str, pos); - } + return rb_ary_new3(3, rb_str_subseq(str, 0, pos), sep, rb_str_subseq(str, pos+RSTRING_LEN(sep), RSTRING_LEN(str)-pos-RSTRING_LEN(sep))); + failed: + return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(rb_cString, str)); } /* @@ -9898,12 +10519,14 @@ rb_str_end_with(int argc, VALUE *argv, VALUE str) for (i=0; i "abc\u3042\uFFFD" * "abc\u3042\x81".scrub("*") #=> "abc\u3042*" - * "abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042" + * "abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack1('H*')+'>' } #=> "abc\u3042" */ static VALUE str_scrub(int argc, VALUE *argv, VALUE str) { VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil; VALUE new = rb_str_scrub(str, repl); - return NIL_P(new) ? rb_str_dup(str): new; + return NIL_P(new) ? str_duplicate(rb_cString, str): new; } /* @@ -10539,7 +11149,7 @@ str_scrub(int argc, VALUE *argv, VALUE str) * * "abc\u3042\x81".scrub! #=> "abc\u3042\uFFFD" * "abc\u3042\x81".scrub!("*") #=> "abc\u3042*" - * "abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042" + * "abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack1('H*')+'>' } #=> "abc\u3042" */ static VALUE str_scrub_bang(int argc, VALUE *argv, VALUE str) @@ -10636,15 +11246,18 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str) /********************************************************************** * Document-class: Symbol * - * Symbol objects represent names inside the Ruby interpreter. They - * are generated using the :name and - * :"string" literals syntax, and by the various - * to_sym methods. The same Symbol object will be - * created for a given name or string for the duration of a program's - * execution, regardless of the context or meaning of that name. Thus - * if Fred is a constant in one context, a method in - * another, and a class in a third, the Symbol :Fred - * will be the same object in all three contexts. + * Symbol objects represent named identifiers inside the Ruby interpreter. + * + * You can create a \Symbol object explicitly with: + * + * - A {symbol literal}[doc/syntax/literals_rdoc.html#label-Symbol+Literals]. + * + * The same Symbol object will be + * created for a given name or string for the duration of a program's + * execution, regardless of the context or meaning of that name. Thus + * if Fred is a constant in one context, a method in + * another, and a class in a third, the Symbol :Fred + * will be the same object in all three contexts. * * module One * class Fred @@ -10662,6 +11275,93 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str) * $f2.object_id #=> 2514190 * $f3.object_id #=> 2514190 * + * Constant, method, and variable names are returned as symbols: + * + * module One + * Two = 2 + * def three; 3 end + * @four = 4 + * @@five = 5 + * $six = 6 + * end + * seven = 7 + * + * One.constants + * # => [:Two] + * One.instance_methods(true) + * # => [:three] + * One.instance_variables + * # => [:@four] + * One.class_variables + * # => [:@@five] + * global_variables.grep(/six/) + * # => [:$six] + * local_variables + * # => [:seven] + * + * Symbol objects are different from String objects in that + * Symbol objects represent identifiers, while String objects + * represent text or data. + * + * == What's Here + * + * First, what's elsewhere. \Class \Symbol: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here]. + * + * Here, class \Symbol provides methods that are useful for: + * + * - {Querying}[#class-Symbol-label-Methods+for+Querying] + * - {Comparing}[#class-Symbol-label-Methods+for+Comparing] + * - {Converting}[#class-Symbol-label-Methods+for+Converting] + * + * === Methods for Querying + * + * - ::all_symbols:: Returns an array of the symbols currently in Ruby's symbol table. + * - {#=~}[#method-i-3D~]:: Returns the index of the first substring + * in symbol that matches a given Regexp + * or other object; returns +nil+ if no match is found. + * - #[], #slice :: Returns a substring of symbol + * determined by a given index, start/length, or range, or string. + * - #empty?:: Returns +true+ if +self.length+ is zero; +false+ otherwise. + * - #encoding:: Returns the Encoding object that represents the encoding + * of symbol. + * - #end_with?:: Returns +true+ if symbol ends with + * any of the given strings. + * - #match:: Returns a MatchData object if symbol + * matches a given Regexp; +nil+ otherwise. + * - #match?:: Returns +true+ if symbol + * matches a given Regexp; +false+ otherwise. + * - #length, #size:: Returns the number of characters in symbol. + * - #start_with?:: Returns +true+ if symbol starts with + * any of the given strings. + * + * === Methods for Comparing + * + * - {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1 as a given symbol is smaller than, equal to, or larger than symbol. + * - {#==, #===}[#method-i-3D-3D]:: Returns +true+ if a given symbol + * has the same content and encoding. + * - #casecmp:: Ignoring case, returns -1, 0, or 1 as a given + * symbol is smaller than, equal to, or larger than symbol. + * - #casecmp?:: Returns +true+ if symbol is equal to a given symbol + * after Unicode case folding; +false+ otherwise. + * + * === Methods for Converting + * + * - #capitalize:: Returns symbol with the first character upcased + * and all other characters downcased. + * - #downcase:: Returns symbol with all characters downcased. + * - #inspect:: Returns the string representation of +self+ as a symbol literal. + * - #name:: Returns the frozen string corresponding to symbol. + * - #succ, #next:: Returns the symbol that is the successor to symbol. + * - #swapcase:: Returns symbol with all upcase characters downcased + * and all downcase characters upcased. + * - #to_proc:: Returns a Proc object which responds to the method named by symbol. + * - #to_s, #id2name:: Returns the string corresponding to +self+. + * - #to_sym, #intern:: Returns +self+. + * - #upcase:: Returns symbol with all characters upcased. + * */ @@ -10726,7 +11426,7 @@ rb_str_quote_unprintable(VALUE str) len = RSTRING_LEN(str); if ((resenc != enc && !rb_str_is_ascii_only_p(str)) || !sym_printable(ptr, ptr + len, enc)) { - return rb_str_inspect(str); + return rb_str_escape(str); } return str; } @@ -10736,7 +11436,7 @@ rb_id_quote_unprintable(ID id) { VALUE str = rb_id2str(id); if (!rb_str_symname_p(str)) { - return rb_str_inspect(str); + return rb_str_escape(str); } return str; } @@ -10776,6 +11476,26 @@ sym_inspect(VALUE sym) return str; } +#if 0 /* for RDoc */ +/* + * call-seq: + * sym.name -> string + * + * Returns the name or string corresponding to sym. Unlike #to_s, the + * returned string is frozen. + * + * :fred.name #=> "fred" + * :fred.name.frozen? #=> true + * :fred.to_s #=> "fred" + * :fred.to_s.frozen? #=> false + */ +VALUE +rb_sym2str(VALUE sym) +{ + +} +#endif + /* * call-seq: @@ -10786,6 +11506,9 @@ sym_inspect(VALUE sym) * * :fred.id2name #=> "fred" * :ginger.to_s #=> "ginger" + * + * Note that this string is not frozen (unlike the symbol itself). + * To get a frozen string, use #name. */ @@ -10878,23 +11601,29 @@ sym_cmp(VALUE sym, VALUE other) } /* - * call-seq: - * sym.casecmp(other_symbol) -> -1, 0, +1, or nil + * call-seq: + * casecmp(other_symbol) -> -1, 0, 1, or nil + * + * Case-insensitive version of {Symbol#<=>}[#method-i-3C-3D-3E]: * - * Case-insensitive version of Symbol#<=>. - * Currently, case-insensitivity only works on characters A-Z/a-z, - * not all of Unicode. This is different from Symbol#casecmp?. + * :aBcDeF.casecmp(:abcde) # => 1 + * :aBcDeF.casecmp(:abcdef) # => 0 + * :aBcDeF.casecmp(:abcdefg) # => -1 + * :abcdef.casecmp(:ABCDEF) # => 0 * - * :aBcDeF.casecmp(:abcde) #=> 1 - * :aBcDeF.casecmp(:abcdef) #=> 0 - * :aBcDeF.casecmp(:abcdefg) #=> -1 - * :abcdef.casecmp(:ABCDEF) #=> 0 + * Returns +nil+ if the two symbols have incompatible encodings, + * or if +other_symbol+ is not a symbol: * - * +nil+ is returned if the two symbols have incompatible encodings, - * or if +other_symbol+ is not a symbol. + * sym = "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym + * other_sym = :"\u{c4 d6 dc}" + * sym.casecmp(other_sym) # => nil + * :foo.casecmp(2) # => nil + * + * Currently, case-insensitivity only works on characters A-Z/a-z, + * not all of Unicode. This is different from Symbol#casecmp?. + * + * Related: Symbol#casecmp?. * - * :foo.casecmp(2) #=> nil - * "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym.casecmp(:"\u{c4 d6 dc}") #=> nil */ static VALUE @@ -10907,23 +11636,30 @@ sym_casecmp(VALUE sym, VALUE other) } /* - * call-seq: - * sym.casecmp?(other_symbol) -> true, false, or nil + * call-seq: + * casecmp?(other_symbol) -> true, false, or nil * - * Returns +true+ if +sym+ and +other_symbol+ are equal after - * Unicode case folding, +false+ if they are not equal. + * Returns +true+ if +sym+ and +other_symbol+ are equal after + * Unicode case folding, +false+ if they are not equal: * - * :aBcDeF.casecmp?(:abcde) #=> false - * :aBcDeF.casecmp?(:abcdef) #=> true - * :aBcDeF.casecmp?(:abcdefg) #=> false - * :abcdef.casecmp?(:ABCDEF) #=> true - * :"\u{e4 f6 fc}".casecmp?(:"\u{c4 d6 dc}") #=> true + * :aBcDeF.casecmp?(:abcde) # => false + * :aBcDeF.casecmp?(:abcdef) # => true + * :aBcDeF.casecmp?(:abcdefg) # => false + * :abcdef.casecmp?(:ABCDEF) # => true + * :"\u{e4 f6 fc}".casecmp?(:"\u{c4 d6 dc}") #=> true * - * +nil+ is returned if the two symbols have incompatible encodings, - * or if +other_symbol+ is not a symbol. + * Returns +nil+ if the two symbols have incompatible encodings, + * or if +other_symbol+ is not a symbol: + * + * sym = "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym + * other_sym = :"\u{c4 d6 dc}" + * sym.casecmp?(other_sym) # => nil + * :foo.casecmp?(2) # => nil + * + * See {Case Mapping}[doc/case_mapping_rdoc.html]. + * + * Related: Symbol#casecmp. * - * :foo.casecmp?(2) #=> nil - * "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym.casecmp?(:"\u{c4 d6 dc}") #=> nil */ static VALUE @@ -11020,11 +11756,13 @@ sym_empty(VALUE sym) } /* - * call-seq: - * sym.upcase -> symbol - * sym.upcase([options]) -> symbol + * call-seq: + * upcase(*options) -> symbol + * + * Equivalent to sym.to_s.upcase.to_sym. + * + * See String#upcase. * - * Same as sym.to_s.upcase.intern. */ static VALUE @@ -11034,11 +11772,15 @@ sym_upcase(int argc, VALUE *argv, VALUE sym) } /* - * call-seq: - * sym.downcase -> symbol - * sym.downcase([options]) -> symbol + * call-seq: + * downcase(*options) -> symbol + * + * Equivalent to sym.to_s.downcase.to_sym. + * + * See String#downcase. + * + * Related: Symbol#upcase. * - * Same as sym.to_s.downcase.intern. */ static VALUE @@ -11048,11 +11790,13 @@ sym_downcase(int argc, VALUE *argv, VALUE sym) } /* - * call-seq: - * sym.capitalize -> symbol - * sym.capitalize([options]) -> symbol + * call-seq: + * capitalize(*options) -> symbol + * + * Equivalent to sym.to_s.capitalize.to_sym. + * + * See String#capitalize. * - * Same as sym.to_s.capitalize.intern. */ static VALUE @@ -11062,11 +11806,13 @@ sym_capitalize(int argc, VALUE *argv, VALUE sym) } /* - * call-seq: - * sym.swapcase -> symbol - * sym.swapcase([options]) -> symbol + * call-seq: + * swapcase(*options) -> symbol + * + * Equivalent to sym.to_s.swapcase.to_sym. + * + * See String#swapcase. * - * Same as sym.to_s.swapcase.intern. */ static VALUE @@ -11184,25 +11930,438 @@ sym_all_symbols(VALUE _) return rb_sym_all_symbols(); } +VALUE +rb_str_to_interned_str(VALUE str) +{ + return rb_fstring(str); +} + +VALUE +rb_interned_str(const char *ptr, long len) +{ + struct RString fake_str; + return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), TRUE); +} + +VALUE +rb_interned_str_cstr(const char *ptr) +{ + return rb_interned_str(ptr, strlen(ptr)); +} + +VALUE +rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc) +{ + if (UNLIKELY(rb_enc_autoload_p(enc))) { + rb_enc_autoload(enc); + } + + struct RString fake_str; + return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), TRUE); +} + +VALUE +rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc) +{ + return rb_enc_interned_str(ptr, strlen(ptr), enc); +} + /* - * A String object holds and manipulates an arbitrary sequence of - * bytes, typically representing characters. String objects may be created - * using String::new or as literals. + * 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}[doc/syntax/literals_rdoc.html#label-String+Literals]. + * - A {heredoc literal}[doc/syntax/literals_rdoc.html#label-Here+Document+Literals]. + * + * You can convert certain objects to Strings with: + * + * - \Method {String}[Kernel.html#method-i-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 there exist both bang and non-bang version of method, + * the bang! mutates and the non-bang! 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+. + * - String#gsub: Zero or more substitutions; returns a new string. + * - String#gsub!: Zero or more substitutions; returns +self+. + * + * Each of these methods takes: + * + * - A first argument, +pattern+ (string or regexp), + * that specifies the substring(s) to be replaced. * - * Because of aliasing issues, users of strings should be aware of the methods - * that modify the contents of a String object. Typically, - * methods with names ending in ``!'' modify their receiver, while those - * without a ``!'' return a new String. However, there are - * exceptions, such as String#[]=. + * - Either of these: * + * - 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 methods String#sub and String#gsub; + * 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 will determine + * the replacing string that is to be 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_ a non-negative integer) refers to $n. + * - \k refers to the named capture +name+. + * + * See rdoc-ref:regexp.rdoc for details. + * + * Note that within the string +replacement+, a character combination + * such as $& is treated as ordinary text, and 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 string after match. + * - \` corresponds to $`, + * which contains string before match. + * - \+ corresponds to $+, + * which contains last capture group. + * + * See rdoc-ref:regexp.rdoc 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}[doc/syntax/literals_rdoc.html#label-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 first to 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 a lot of backslashes. + * + * \Hash +replacement+ + * + * If 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. + * + * + * == What's Here + * + * First, what's elsewhere. \Class \String: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here]. + * + * Here, class \String provides methods that are useful for: + * + * - {Creating a String}[#class-String-label-Methods+for+Creating+a+String] + * - {Frozen/Unfrozen Strings}[#class-String-label-Methods+for+a+Frozen-2FUnfrozen+String] + * - {Querying}[#class-String-label-Methods+for+Querying] + * - {Comparing}[#class-String-label-Methods+for+Comparing] + * - {Modifying a String}[#class-String-label-Methods+for+Modifying+a+String] + * - {Converting to New String}[#class-String-label-Methods+for+Converting+to+New+String] + * - {Converting to Non-String}[#class-String-label-Methods+for+Converting+to+Non--5CString] + * - {Iterating}[#class-String-label-Methods+for+Iterating] + * + * === Methods for Creating a \String + * + * - ::new:: Returns a new string. + * - ::try_convert:: Returns a new string created from a given object. + * + * === Methods for a Frozen/Unfrozen String + * + * - {#+string}[#method-i-2B-40]:: Returns a string that is not frozen: + * +self+, if not frozen; +self.dup+ otherwise. + * - {#-string}[#method-i-2D-40]:: Returns a string that is frozen: + * +self+, if already frozen; +self.freeze+ otherwise. + * - #freeze:: Freezes +self+, if not already frozen; returns +self+. + * + * === Methods for Querying + * + * _Counts_ + * + * - #length, #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_ + * + * - {#=~}[#method-i-3D~]:: Returns the index of the first substring that matches a given Regexp or other object; + * returns +nil+ if no match is found. + * - #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. + * + * === Methods for Comparing + * + * - {#==, #===}[#method-i-3D-3D]:: 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. + * - {#<=>}[#method-i-3C-3D-3E]:: 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 a given + * other string is smaller than, equal to, or larger than +self+. + * - #casecmp?:: Returns +true+ if the string is equal to a given string after Unicode case folding; + * +false+ otherwise. + * + * === Methods for Modifying a \String + * + * Each of these methods modifies +self+. + * + * _Insertion_ + * + * - #insert:: Returns +self+ with a given string inserted at a given offset. + * - #<<:: Returns +self+ concatenated with a given string or integer. + * + * _Substitution_ + * + * - #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!, #next!:: Returns +self+ modified to become its own successor. + * - #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 given encoding into 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. + * - #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 trailing record separator, if found; returns +self+ if any changes, +nil+ otherwise. + * - #chop!:: Removes trailing whitespace if found, otherwise removes the last character; + * returns +self+ if any changes, +nil+ otherwise. + * + * === Methods for 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 between pad substring. + * - #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 given encoding into 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 notation replace by \uNNNN notation + * 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, #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 whitespace or the last character removed. + * - #squeeze:: Returns a copy of +self+ with contiguous duplicate characters removed. + * - #[], #slice:: Returns a substring determined by a given index, start/length, or range, or string. + * - #byteslice:: Returns a substring determined by a given index, start/length, or range. + * - #chr:: Returns the first character. + * + * _Duplication_ + * + * - #to_s, $to_str:: If +self+ is a subclass of \String, returns +self+ copied into a \String; + * otherwise, returns +self+. + * + * === Methods for 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 an integer byte as determined by a given index. + * - #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 given, passes those substrings to the block. + * + * _Matching_ + * + * - #scan:: Returns an array of substrings matching a given regexp or string, or, + * if a block 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 copy of +self+, enclosed in double-quotes, with special characters escaped. + * - #to_sym, #intern:: Returns the symbol corresponding to +self+. + * + * === Methods for 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. */ void Init_String(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - rb_cString = rb_define_class("String", rb_cObject); assert(rb_vm_fstring_table()); st_foreach(rb_vm_fstring_table(), fstring_set_class_i, rb_cString); @@ -11258,10 +12417,10 @@ Init_String(void) rb_define_method(rb_cString, "dump", rb_str_dump, 0); rb_define_method(rb_cString, "undump", str_undump, 0); - sym_ascii = ID2SYM(rb_intern("ascii")); - sym_turkic = ID2SYM(rb_intern("turkic")); - sym_lithuanian = ID2SYM(rb_intern("lithuanian")); - sym_fold = ID2SYM(rb_intern("fold")); + sym_ascii = ID2SYM(rb_intern_const("ascii")); + sym_turkic = ID2SYM(rb_intern_const("turkic")); + sym_lithuanian = ID2SYM(rb_intern_const("lithuanian")); + sym_fold = ID2SYM(rb_intern_const("fold")); rb_define_method(rb_cString, "upcase", rb_str_upcase, -1); rb_define_method(rb_cString, "downcase", rb_str_downcase, -1); @@ -11354,8 +12513,8 @@ Init_String(void) /* define UnicodeNormalize module here so that we don't have to look it up */ mUnicodeNormalize = rb_define_module("UnicodeNormalize"); - id_normalize = rb_intern("normalize"); - id_normalized_p = rb_intern("normalized?"); + id_normalize = rb_intern_const("normalize"); + id_normalized_p = rb_intern_const("normalized?"); rb_define_method(rb_cString, "unicode_normalize", rb_str_unicode_normalize, -1); rb_define_method(rb_cString, "unicode_normalize!", rb_str_unicode_normalize_bang, -1); @@ -11377,6 +12536,7 @@ Init_String(void) rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0); rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0); rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0); + rb_define_method(rb_cSymbol, "name", rb_sym2str, 0); rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0); rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0); rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0); diff --git a/ruby/struct.c b/ruby/struct.c index d1aa7c278..716bc7f4f 100644 --- a/ruby/struct.c +++ b/ruby/struct.c @@ -9,10 +9,18 @@ **********************************************************************/ -#include "internal.h" -#include "vm_core.h" #include "id.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "internal/struct.h" +#include "internal/symbol.h" #include "transient_heap.h" +#include "vm_core.h" +#include "builtin.h" /* only for struct[:field] access */ enum { @@ -20,9 +28,6 @@ enum { AREF_HASH_THRESHOLD = 10 }; -const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func); -const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func); - VALUE rb_cStruct; static ID id_members, id_back_members, id_keyword_init; @@ -182,6 +187,17 @@ struct_member_pos(VALUE s, VALUE name) } } +/* + * call-seq: + * StructClass::members -> array_of_symbols + * + * Returns the member names of the Struct descendant as an array: + * + * Customer = Struct.new(:name, :address, :zip) + * Customer.members # => [:name, :address, :zip] + * + */ + static VALUE rb_struct_s_members_m(VALUE klass) { @@ -192,13 +208,14 @@ rb_struct_s_members_m(VALUE klass) /* * call-seq: - * struct.members -> array + * members -> array_of_symbols * - * Returns the struct members as an array of symbols: + * Returns the member names from +self+ as an array: * * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.members #=> [:name, :address, :zip] + * Customer.new.members # => [:name, :address, :zip] + * + * Related: #to_a. */ static VALUE @@ -220,32 +237,6 @@ rb_struct_getmember(VALUE obj, ID id) UNREACHABLE_RETURN(Qnil); } -static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);} -static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);} -static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);} -static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);} -static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);} -static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);} -static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);} -static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);} -static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);} -static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);} - -#define N_REF_FUNC numberof(ref_func) - -static VALUE (*const ref_func[])(VALUE) = { - rb_struct_ref0, - rb_struct_ref1, - rb_struct_ref2, - rb_struct_ref3, - rb_struct_ref4, - rb_struct_ref5, - rb_struct_ref6, - rb_struct_ref7, - rb_struct_ref8, - rb_struct_ref9, -}; - static void rb_struct_modify(VALUE s) { @@ -281,22 +272,18 @@ new_struct(VALUE name, VALUE super) return rb_define_class_id_under(super, id, super); } +NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx)); + static void define_aref_method(VALUE nstr, VALUE name, VALUE off) { - rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_execution_context_t *, rb_control_frame_t *); - const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref); - - rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC); + rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_AREF, FIX2UINT(off), METHOD_VISI_PUBLIC); } static void define_aset_method(VALUE nstr, VALUE name, VALUE off) { - rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_execution_context_t *, rb_control_frame_t *); - const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset); - - rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC); + rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_ASET, FIX2UINT(off), METHOD_VISI_PUBLIC); } static VALUE @@ -309,40 +296,53 @@ rb_struct_s_inspect(VALUE klass) return inspect; } +#if 0 /* for RDoc */ + +/* + * call-seq: + * StructClass::keyword_init? -> true or falsy value + * + * Returns +true+ if the class was initialized with keyword_init: true. + * Otherwise returns +nil+ or +false+. + * + * Examples: + * Foo = Struct.new(:a) + * Foo.keyword_init? # => nil + * Bar = Struct.new(:a, keyword_init: true) + * Bar.keyword_init? # => true + * Baz = Struct.new(:a, keyword_init: false) + * Baz.keyword_init? # => false + */ static VALUE -struct_new_kw(int argc, const VALUE *argv, VALUE klass) +rb_struct_s_keyword_init_p(VALUE obj) { - return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS); } +#endif + +#define rb_struct_s_keyword_init_p rb_struct_s_keyword_init static VALUE -setup_struct(VALUE nstr, VALUE members, int keyword_init) +setup_struct(VALUE nstr, VALUE members) { long i, len; - VALUE (*new_func)(int, const VALUE *, VALUE) = rb_class_new_instance; - - if (keyword_init) new_func = struct_new_kw; members = struct_set_members(nstr, members); rb_define_alloc_func(nstr, struct_alloc); - rb_define_singleton_method(nstr, "new", new_func, -1); - rb_define_singleton_method(nstr, "[]", new_func, -1); + rb_define_singleton_method(nstr, "new", rb_class_new_instance_pass_kw, -1); + rb_define_singleton_method(nstr, "[]", rb_class_new_instance_pass_kw, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); rb_define_singleton_method(nstr, "inspect", rb_struct_s_inspect, 0); + rb_define_singleton_method(nstr, "keyword_init?", rb_struct_s_keyword_init_p, 0); + len = RARRAY_LEN(members); for (i=0; i< len; i++) { VALUE sym = RARRAY_AREF(members, i); ID id = SYM2ID(sym); VALUE off = LONG2NUM(i); - if (i < N_REF_FUNC) { - rb_define_method_id(nstr, id, ref_func[i], 0); - } - else { - define_aref_method(nstr, sym, off); - } - define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off); + define_aref_method(nstr, sym, off); + define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off); } return nstr; @@ -359,9 +359,10 @@ struct_make_members_list(va_list ar) { char *mem; VALUE ary, list = rb_ident_hash_new(); - st_table *tbl = RHASH_TBL(list); + st_table *tbl = RHASH_TBL_RAW(list); RBASIC_CLEAR_CLASS(list); + OBJ_WB_UNPROTECT(list); while ((mem = va_arg(ar, char*)) != 0) { VALUE sym = rb_sym_intern_ascii_cstr(mem); if (st_insert(tbl, sym, Qtrue)) { @@ -442,7 +443,7 @@ rb_struct_define(const char *name, ...) if (!name) st = anonymous_struct(rb_cStruct); else st = new_struct(rb_str_new2(name), rb_cStruct); - return setup_struct(st, ary, 0); + return setup_struct(st, ary); } VALUE @@ -455,76 +456,123 @@ rb_struct_define_under(VALUE outer, const char *name, ...) ary = struct_make_members_list(ar); va_end(ar); - return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary, 0); + return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary); } /* * call-seq: - * Struct.new([class_name] [, member_name]+) -> StructClass - * Struct.new([class_name] [, member_name]+, keyword_init: true) -> StructClass - * Struct.new([class_name] [, member_name]+) {|StructClass| block } -> StructClass - * StructClass.new(value, ...) -> object - * StructClass[value, ...] -> object - * - * The first two forms are used to create a new Struct subclass +class_name+ - * that can contain a value for each +member_name+. This subclass can be - * used to create instances of the structure like any other Class. - * - * If the +class_name+ is omitted an anonymous structure class will be - * created. Otherwise, the name of this struct will appear as a constant in - * class Struct, so it must be unique for all Structs in the system and - * must start with a capital letter. Assigning a structure class to a - * constant also gives the class the name of the constant. - * - * # Create a structure with a name under Struct - * Struct.new("Customer", :name, :address) - * #=> Struct::Customer - * Struct::Customer.new("Dave", "123 Main") - * #=> # - * - * # Create a structure named by its constant - * Customer = Struct.new(:name, :address) - * #=> Customer - * Customer.new("Dave", "123 Main") - * #=> # - * - * If the optional +keyword_init+ keyword argument is set to +true+, - * .new takes keyword arguments instead of normal arguments. - * - * Customer = Struct.new(:name, :address, keyword_init: true) - * Customer.new(name: "Dave", address: "123 Main") - * #=> # - * - * If a block is given it will be evaluated in the context of - * +StructClass+, passing the created class as a parameter: - * - * Customer = Struct.new(:name, :address) do - * def greeting - * "Hello #{name}!" - * end - * end - * Customer.new("Dave", "123 Main").greeting #=> "Hello Dave!" - * - * This is the recommended way to customize a struct. Subclassing an - * anonymous struct creates an extra anonymous class that will never be used. - * - * The last two forms create a new instance of a struct subclass. The number - * of +value+ parameters must be less than or equal to the number of - * attributes defined for the structure. Unset parameters default to +nil+. - * Passing more parameters than number of attributes will raise - * an ArgumentError. - * - * Customer = Struct.new(:name, :address) - * Customer.new("Dave", "123 Main") - * #=> # - * Customer["Dave"] - * #=> # + * Struct.new(*member_names, keyword_init: false){|Struct_subclass| ... } -> Struct_subclass + * Struct.new(class_name, *member_names, keyword_init: false){|Struct_subclass| ... } -> Struct_subclass + * Struct_subclass.new(*member_names) -> Struct_subclass_instance + * Struct_subclass.new(**member_names) -> Struct_subclass_instance + * + * Struct.new returns a new subclass of +Struct+. The new subclass: + * + * - May be anonymous, or may have the name given by +class_name+. + * - May have members as given by +member_names+. + * - May have initialization via ordinary arguments (the default) + * or via keyword arguments (if keyword_init: true is given). + * + * The new subclass has its own method ::new; thus: + * + * Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo + * f = Foo.new(0, 1) # => # + * + * \Class Name + * + * With string argument +class_name+, + * returns a new subclass of +Struct+ named Struct::class_name: + * + * Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo + * Foo.name # => "Struct::Foo" + * Foo.superclass # => Struct + * + * Without string argument +class_name+, + * returns a new anonymous subclass of +Struct+: + * + * Struct.new(:foo, :bar).name # => nil + * + * Block + * + * With a block given, the created subclass is yielded to the block: + * + * Customer = Struct.new('Customer', :name, :address) do |new_class| + * p "The new subclass is #{new_class}" + * def greeting + * "Hello #{name} at #{address}" + * end + * end # => Struct::Customer + * dave = Customer.new('Dave', '123 Main') + * dave # => # + * dave.greeting # => "Hello Dave at 123 Main" + * + * Output, from Struct.new: + * + * "The new subclass is Struct::Customer" + * + * Member Names + * + * \Symbol arguments +member_names+ + * determines the members of the new subclass: + * + * Struct.new(:foo, :bar).members # => [:foo, :bar] + * Struct.new('Foo', :foo, :bar).members # => [:foo, :bar] + * + * The new subclass has instance methods corresponding to +member_names+: + * + * Foo = Struct.new('Foo', :foo, :bar) + * Foo.instance_methods(false) # => [:foo, :bar, :foo=, :bar=] + * f = Foo.new # => # + * f.foo # => nil + * f.foo = 0 # => 0 + * f.bar # => nil + * f.bar = 1 # => 1 + * f # => # + * + * Singleton Methods + * + * A subclass returned by Struct.new has these singleton methods: + * + * - \Method ::new creates an instance of the subclass: + * + * Foo.new # => # + * Foo.new(0) # => # + * Foo.new(0, 1) # => # + * Foo.new(0, 1, 2) # Raises ArgumentError: struct size differs + * + * \Method ::[] is an alias for method ::new. + * + * - \Method :inspect returns a string representation of the subclass: + * + * Foo.inspect + * # => "Struct::Foo" + * + * - \Method ::members returns an array of the member names: + * + * Foo.members # => [:foo, :bar] + * + * Keyword Argument + * + * By default, the arguments for initializing an instance of the new subclass + * are ordinary arguments (not keyword arguments). + * With optional keyword argument keyword_init: true, + * the new subclass is initialized with keyword arguments: + * + * # Without keyword_init: true. + * Foo = Struct.new('Foo', :foo, :bar) + * Foo # => Struct::Foo + * Foo.new(0, 1) # => # + * # With keyword_init: true. + * Bar = Struct.new(:foo, :bar, keyword_init: true) + * Bar # => # => Bar(keyword_init: true) + * Bar.new(bar: 1, foo: 0) # => # + * */ static VALUE rb_struct_s_def(int argc, VALUE *argv, VALUE klass) { - VALUE name, rest, keyword_init = Qfalse; + VALUE name, rest, keyword_init = Qnil; long i; VALUE st; st_table *tbl; @@ -547,14 +595,18 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass) } rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init); if (keyword_init == Qundef) { - keyword_init = Qfalse; + keyword_init = Qnil; + } + else if (RTEST(keyword_init)) { + keyword_init = Qtrue; } --argc; } rest = rb_ident_hash_new(); RBASIC_CLEAR_CLASS(rest); - tbl = RHASH_TBL(rest); + OBJ_WB_UNPROTECT(rest); + tbl = RHASH_TBL_RAW(rest); for (i=0; iself, &key); if (i < 0) { - if (args->unknown_keywords == Qnil) { + if (NIL_P(args->unknown_keywords)) { args->unknown_keywords = rb_ary_new(); } rb_ary_push(args->unknown_keywords, key); @@ -626,11 +678,15 @@ static VALUE rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self) { VALUE klass = rb_obj_class(self); - long i, n; - rb_struct_modify(self); - n = num_members(klass); - if (argc > 0 && RTEST(rb_struct_s_keyword_init(klass))) { + long n = num_members(klass); + if (argc == 0) { + rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n); + return Qnil; + } + + VALUE keyword_init = rb_struct_s_keyword_init(klass); + if (RTEST(keyword_init)) { struct struct_hash_set_arg arg; if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) { rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0)", argc); @@ -648,7 +704,11 @@ rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self) if (n < argc) { rb_raise(rb_eArgError, "struct size differs"); } - for (i=0; i argc) { @@ -661,7 +721,9 @@ rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self) VALUE rb_struct_initialize(VALUE self, VALUE values) { - return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self); + rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self); + RB_GC_GUARD(values); + return Qnil; } static VALUE * @@ -732,7 +794,7 @@ rb_struct_alloc(VALUE klass, VALUE values) VALUE rb_struct_new(VALUE klass, ...) { - VALUE tmpargs[N_REF_FUNC], *mem = tmpargs; + VALUE tmpargs[16], *mem = tmpargs; int size, i; va_list args; @@ -758,21 +820,24 @@ struct_enum_size(VALUE s, VALUE args, VALUE eobj) /* * call-seq: - * struct.each {|obj| block } -> struct - * struct.each -> enumerator + * each {|value| ... } -> self + * each -> enumerator * - * Yields the value of each struct member in order. If no block is given an - * enumerator is returned. + * Calls the given block with the value of each member; returns +self+: * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.each {|x| puts(x) } + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.each {|value| p value } + * + * Output: * - * Produces: + * "Joe Smith" + * "123 Maple, Anytown NC" + * 12345 * - * Joe Smith - * 123 Maple, Anytown NC - * 12345 + * Returns an Enumerator if no block is given. + * + * Related: #each_pair. */ static VALUE @@ -789,21 +854,25 @@ rb_struct_each(VALUE s) /* * call-seq: - * struct.each_pair {|sym, obj| block } -> struct - * struct.each_pair -> enumerator + * each_pair {|(name, value)| ... } -> self + * each_pair -> enumerator * - * Yields the name and value of each struct member in order. If no block is - * given an enumerator is returned. + * Calls the given block with each member name/value pair; returns +self+: * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.each_pair {|name, value| puts("#{name} => #{value}") } + * Customer = Struct.new(:name, :address, :zip) # => Customer + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.each_pair {|(name, value)| p "#{name} => #{value}" } * - * Produces: + * Output: + * + * "name => Joe Smith" + * "address => 123 Maple, Anytown NC" + * "zip => 12345" + * + * Returns an Enumerator if no block is given. + * + * Related: #each. * - * name => Joe Smith - * address => 123 Maple, Anytown NC - * zip => 12345 */ static VALUE @@ -814,7 +883,7 @@ rb_struct_each_pair(VALUE s) RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size); members = rb_struct_members(s); - if (rb_block_arity() > 1) { + if (rb_block_pair_yield_optimizable()) { for (i=0; i string - * struct.inspect -> string + * call-seq: + * inspect -> string + * + * Returns a string representation of +self+: + * + * Customer = Struct.new(:name, :address, :zip) # => Customer + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.inspect # => "#" + * + * Struct#to_s is an alias for Struct#inspect. * - * Returns a description of this struct as a string. */ static VALUE @@ -891,14 +966,17 @@ rb_struct_inspect(VALUE s) /* * call-seq: - * struct.to_a -> array - * struct.values -> array + * to_a -> array * - * Returns the values for this struct as an Array. + * Returns the values in +self+ as an array: * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.to_a[1] #=> "123 Maple, Anytown NC" + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.to_a # => ["Joe Smith", "123 Maple, Anytown NC", 12345] + * + * Struct#values and Struct#deconstruct are aliases for Struct#to_a. + * + * Related: #members. */ static VALUE @@ -909,19 +987,25 @@ rb_struct_to_a(VALUE s) /* * call-seq: - * struct.to_h -> hash - * struct.to_h {|name, value| block } -> hash + * to_h -> hash + * to_h {|name, value| ... } -> hash * - * Returns a Hash containing the names and values for the struct's members. + * Returns a hash containing the name and value for each member: * - * If a block is given, the results of the block on each pair of the receiver - * will be used as pairs. + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * h = joe.to_h + * h # => {:name=>"Joe Smith", :address=>"123 Maple, Anytown NC", :zip=>12345} + * + * If a block is given, it is called with each name/value pair; + * the block should return a 2-element array whose elements will become + * a key/value pair in the returned hash: + * + * h = joe.to_h{|name, value| [name.upcase, value.to_s.upcase]} + * h # => {:NAME=>"JOE SMITH", :ADDRESS=>"123 MAPLE, ANYTOWN NC", :ZIP=>"12345"} + * + * Raises ArgumentError if the block returns an inappropriate value. * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.to_h[:address] #=> "123 Maple, Anytown NC" - * joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}[:ADDRESS] - * #=> "123 MAPLE, ANYTOWN NC" */ static VALUE @@ -942,6 +1026,23 @@ rb_struct_to_h(VALUE s) return h; } +/* + * call-seq: + * deconstruct_keys(array_of_names) -> hash + * + * Returns a hash of the name/value pairs for the given member names. + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * h = joe.deconstruct_keys([:zip, :address]) + * h # => {:zip=>12345, :address=>"123 Maple, Anytown NC"} + * + * Returns all names and values if +array_of_names+ is +nil+: + * + * h = joe.deconstruct_keys(nil) + * h # => {:name=>"Joseph Smith, Jr.", :address=>"123 Maple, Anytown NC", :zip=>12345} + * + */ static VALUE rb_struct_deconstruct_keys(VALUE s, VALUE keys) { @@ -996,7 +1097,7 @@ rb_struct_pos(VALUE s, VALUE *name) long i; VALUE idx = *name; - if (RB_TYPE_P(idx, T_SYMBOL)) { + if (SYMBOL_P(idx)) { return struct_member_pos(s, idx); } else if (RB_TYPE_P(idx, T_STRING)) { @@ -1023,7 +1124,6 @@ rb_struct_pos(VALUE s, VALUE *name) } } -NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx)); static void invalid_struct_pos(VALUE s, VALUE idx) { @@ -1045,19 +1145,28 @@ invalid_struct_pos(VALUE s, VALUE idx) /* * call-seq: - * struct[member] -> object - * struct[index] -> object + * struct[name] -> object + * struct[n] -> object * - * Attribute Reference---Returns the value of the given struct +member+ or - * the member at the given +index+. Raises NameError if the +member+ does - * not exist and IndexError if the +index+ is out of range. + * Returns a value from +self+. * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * With symbol or string argument +name+ given, returns the value for the named member: + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe[:zip] # => 12345 + * + * Raises NameError if +name+ is not the name of a member. + * + * With integer argument +n+ given, returns self.values[n] + * if +n+ is in range; + * see {Array Indexes}[Array.html#class-Array-label-Array+Indexes]: + * + * joe[2] # => 12345 + * joe[-2] # => "123 Maple, Anytown NC" + * + * Raises IndexError if +n+ is out of range. * - * joe["name"] #=> "Joe Smith" - * joe[:name] #=> "Joe Smith" - * joe[0] #=> "Joe Smith" */ VALUE @@ -1070,21 +1179,32 @@ rb_struct_aref(VALUE s, VALUE idx) /* * call-seq: - * struct[member] = obj -> obj - * struct[index] = obj -> obj + * struct[name] = value -> value + * struct[n] = value -> value * - * Attribute Assignment---Sets the value of the given struct +member+ or - * the member at the given +index+. Raises NameError if the +member+ does not - * exist and IndexError if the +index+ is out of range. + * Assigns a value to a member. * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * With symbol or string argument +name+ given, assigns the given +value+ + * to the named member; returns +value+: * - * joe["name"] = "Luke" - * joe[:zip] = "90210" + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe[:zip] = 54321 # => 54321 + * joe # => # + * + * Raises NameError if +name+ is not the name of a member. + * + * With integer argument +n+ given, assigns the given +value+ + * to the +n+-th member if +n+ is in range; + * see {Array Indexes}[Array.html#class-Array-label-Array+Indexes]: + * + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe[2] = 54321 # => 54321 + * joe[-3] = 'Joseph Smith' # => "Joseph Smith" + * joe # => # + * + * Raises IndexError if +n+ is out of range. * - * joe.name #=> "Luke" - * joe.zip #=> "90210" */ VALUE @@ -1122,15 +1242,36 @@ struct_entry(VALUE s, long n) /* * call-seq: - * struct.values_at(selector, ...) -> array + * values_at(*integers) -> array + * values_at(integer_range) -> array * - * Returns the struct member values for each +selector+ as an Array. A - * +selector+ may be either an Integer offset or a Range of offsets (as in - * Array#values_at). + * Returns an array of values from +self+. * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.values_at(0, 2) #=> ["Joe Smith", 12345] + * With integer arguments +integers+ given, + * returns an array containing each value given by one of +integers+: + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.values_at(0, 2) # => ["Joe Smith", 12345] + * joe.values_at(2, 0) # => [12345, "Joe Smith"] + * joe.values_at(2, 1, 0) # => [12345, "123 Maple, Anytown NC", "Joe Smith"] + * joe.values_at(0, -3) # => ["Joe Smith", "Joe Smith"] + * + * Raises IndexError if any of +integers+ is out of range; + * see {Array Indexes}[Array.html#class-Array-label-Array+Indexes]. + * + * With integer range argument +integer_range+ given, + * returns an array containing each value given by the elements of the range; + * fills with +nil+ values for range elements larger than the structure: + * + * joe.values_at(0..2) + * # => ["Joe Smith", "123 Maple, Anytown NC", 12345] + * joe.values_at(-3..-1) + * # => ["Joe Smith", "123 Maple, Anytown NC", 12345] + * joe.values_at(1..4) # => ["123 Maple, Anytown NC", 12345, nil, nil] + * + * Raises RangeError if any element of the range is negative and out of range; + * see {Array Indexes}[Array.html#class-Array-label-Array+Indexes]. * */ @@ -1142,18 +1283,20 @@ rb_struct_values_at(int argc, VALUE *argv, VALUE s) /* * call-seq: - * struct.select {|obj| block } -> array - * struct.select -> enumerator - * struct.filter {|obj| block } -> array - * struct.filter -> enumerator + * select {|value| ... } -> array + * select -> enumerator * - * Yields each member value from the struct to the block and returns an Array - * containing the member values from the +struct+ for which the given block - * returns a true value (equivalent to Enumerable#select). + * With a block given, returns an array of values from +self+ + * for which the block returns a truthy value: * - * Lots = Struct.new(:a, :b, :c, :d, :e, :f) - * l = Lots.new(11, 22, 33, 44, 55, 66) - * l.select {|v| v.even? } #=> [22, 44, 66] + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * a = joe.select {|value| value.is_a?(String) } + * a # => ["Joe Smith", "123 Maple, Anytown NC"] + * a = joe.select {|value| value.is_a?(Integer) } + * a # => [12345] + * + * With no block given, returns an Enumerator. * * Struct#filter is an alias for Struct#select. */ @@ -1189,19 +1332,25 @@ recursive_equal(VALUE s, VALUE s2, int recur) return Qtrue; } + /* * call-seq: - * struct == other -> true or false + * self == other -> true or false * - * Equality---Returns +true+ if +other+ has the same struct subclass and has - * equal member values (according to Object#==). + * Returns +true+ if and only if the following are true; otherwise returns +false+: * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345) - * joe == joejr #=> true - * joe == jane #=> false + * - other.class == self.class. + * - For each member name +name+, other.name == self.name. + * + * Examples: + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe_jr == joe # => true + * joe_jr[:name] = 'Joe Smith, Jr.' + * # => "Joe Smith, Jr." + * joe_jr == joe # => false */ static VALUE @@ -1218,12 +1367,22 @@ rb_struct_equal(VALUE s, VALUE s2) } /* - * call-seq: - * struct.hash -> integer + * call-seq: + * hash -> integer + * + * Returns the integer hash value for +self+. * - * Returns a hash value based on this struct's contents. + * Two structs of the same class and with the same content + * will have the same hash code (and will compare using Struct#eql?): * - * See also Object#hash. + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.hash == joe_jr.hash # => true + * joe_jr[:name] = 'Joe Smith, Jr.' + * joe.hash == joe_jr.hash # => false + * + * Related: Object#hash. */ static VALUE @@ -1258,11 +1417,21 @@ recursive_eql(VALUE s, VALUE s2, int recur) /* * call-seq: - * struct.eql?(other) -> true or false + * eql?(other) -> true or false + * + * Returns +true+ if and only if the following are true; otherwise returns +false+: * - * Hash equality---+other+ and +struct+ refer to the same hash key if they - * have the same struct subclass and have equal member values (according to - * Object#eql?). + * - other.class == self.class. + * - For each member name +name+, other.name.eql?(self.name). + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe_jr.eql?(joe) # => true + * joe_jr[:name] = 'Joe Smith, Jr.' + * joe_jr.eql?(joe) # => false + * + * Related: Object#==. */ static VALUE @@ -1280,14 +1449,15 @@ rb_struct_eql(VALUE s, VALUE s2) /* * call-seq: - * struct.length -> integer - * struct.size -> integer + * size -> integer * - * Returns the number of struct members. + * Returns the number of members. * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.length #=> 3 + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.size #=> 3 + * + * Struct#length is an alias for Struct#size. */ VALUE @@ -1298,18 +1468,34 @@ rb_struct_size(VALUE s) /* * call-seq: - * struct.dig(key, ...) -> object + * dig(name, *identifiers) -> object + * dig(n, *identifiers) -> object + * + * Finds and returns an object among nested objects. + * The nested objects may be instances of various classes. + * See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. * - * Extracts the nested value specified by the sequence of +key+ - * objects by calling +dig+ at each step, returning +nil+ if any - * intermediate step is +nil+. + * + * Given symbol or string argument +name+, + * returns the object that is specified by +name+ and +identifiers+: * * Foo = Struct.new(:a) * f = Foo.new(Foo.new({b: [1, 2, 3]})) + * f.dig(:a) # => #[1, 2, 3]}> + * f.dig(:a, :a) # => {:b=>[1, 2, 3]} + * f.dig(:a, :a, :b) # => [1, 2, 3] + * f.dig(:a, :a, :b, 0) # => 1 + * f.dig(:b, 0) # => nil + * + * Given integer argument +n+, + * returns the object that is specified by +n+ and +identifiers+: + * + * f.dig(0) # => #[1, 2, 3]}> + * f.dig(0, 0) # => {:b=>[1, 2, 3]} + * f.dig(0, 0, :b) # => [1, 2, 3] + * f.dig(0, 0, :b, 0) # => 1 + * f.dig(:b, 0) # => nil * - * f.dig(:a, :a, :b, 0) # => 1 - * f.dig(:b, 0) # => nil - * f.dig(:a, :a, :b, :c) # TypeError: no implicit conversion of Symbol into Integer */ static VALUE @@ -1325,29 +1511,105 @@ rb_struct_dig(int argc, VALUE *argv, VALUE self) /* * Document-class: Struct * - * A Struct is a convenient way to bundle a number of attributes together, - * using accessor methods, without having to write an explicit class. + * \Class \Struct provides a convenient way to create a simple class + * that can store and fetch values. + * + * This example creates a subclass of +Struct+, Struct::Customer; + * the first argument, a string, is the name of the subclass; + * the other arguments, symbols, determine the _members_ of the new subclass. + * + * Customer = Struct.new('Customer', :name, :address, :zip) + * Customer.name # => "Struct::Customer" + * Customer.class # => Class + * Customer.superclass # => Struct + * + * Corresponding to each member are two methods, a writer and a reader, + * that store and fetch values: + * + * methods = Customer.instance_methods false + * methods # => [:zip, :address=, :zip=, :address, :name, :name=] + * + * An instance of the subclass may be created, + * and its members assigned values, via method ::new: + * + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe # => # + * + * The member values may be managed thus: * - * The Struct class generates new subclasses that hold a set of members and - * their values. For each member a reader and writer method is created - * similar to Module#attr_accessor. + * joe.name # => "Joe Smith" + * joe.name = 'Joseph Smith' + * joe.name # => "Joseph Smith" * - * Customer = Struct.new(:name, :address) do - * def greeting - * "Hello #{name}!" - * end - * end + * And thus; note that member name may be expressed as either a string or a symbol: * - * dave = Customer.new("Dave", "123 Main") - * dave.name #=> "Dave" - * dave.greeting #=> "Hello Dave!" + * joe[:name] # => "Joseph Smith" + * joe[:name] = 'Joseph Smith, Jr.' + * joe['name'] # => "Joseph Smith, Jr." * - * See Struct::new for further examples of creating struct subclasses and - * instances. + * See Struct::new. + * + * == What's Here + * + * First, what's elsewhere. \Class \Struct: + * + * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. + * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here], + * which provides dozens of additional methods. + * + * Here, class \Struct provides methods that are useful for: + * + * - {Creating a Struct Subclass}[#class-Struct-label-Methods+for+Creating+a+Struct+Subclass] + * - {Querying}[#class-Struct-label-Methods+for+Querying] + * - {Comparing}[#class-Struct-label-Methods+for+Comparing] + * - {Fetching}[#class-Struct-label-Methods+for+Fetching] + * - {Assigning}[#class-Struct-label-Methods+for+Assigning] + * - {Iterating}[#class-Struct-label-Methods+for+Iterating] + * - {Converting}[#class-Struct-label-Methods+for+Converting] + * + * === Methods for Creating a Struct Subclass + * + * ::new:: Returns a new subclass of \Struct. + * + * === Methods for Querying + * + * #hash:: Returns the integer hash code. + * #length, #size:: Returns the number of members. + * + * === Methods for Comparing + * + * {#==}[#method-i-3D-3D]:: Returns whether a given object is equal to +self+, + * using == to compare member values. + * #eql?:: Returns whether a given object is equal to +self+, + * using eql? to compare member values. + * + * === Methods for Fetching + * + * #[]:: Returns the value associated with a given member name. + * #to_a, #values, #deconstruct:: Returns the member values in +self+ as an array. + * #deconstruct_keys:: Returns a hash of the name/value pairs + * for given member names. + * #dig:: Returns the object in nested objects that is specified + * by a given member name and additional arguments. + * #members:: Returns an array of the member names. + * #select, #filter:: Returns an array of member values from +self+, + * as selected by the given block. + * #values_at:: Returns an array containing values for given member names. + * + * === Methods for Assigning + * + * #[]=:: Assigns a given value to a given member name. + * + * === Methods for Iterating + * + * #each:: Calls a given block with each member name. + * #each_pair:: Calls a given block with each member name/value pair. + * + * === Methods for Converting + * + * #inspect, #to_s:: Returns a string representation of +self+. + * #to_h:: Returns a hash of the member name/value pairs in +self+. * - * In the method descriptions that follow, a "member" parameter refers to a - * struct member which is either a quoted string ("name") or a - * Symbol (:name). */ void InitVM_Struct(void) @@ -1357,6 +1619,10 @@ InitVM_Struct(void) rb_undef_alloc_func(rb_cStruct); rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1); +#if 0 /* for RDoc */ + rb_define_singleton_method(rb_cStruct, "keyword_init?", rb_struct_s_keyword_init_p, 0); + rb_define_singleton_method(rb_cStruct, "members", rb_struct_s_members_m, 0); +#endif rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1); rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1); diff --git a/ruby/symbol.c b/ruby/symbol.c index 14517df01..5ce95f5b0 100644 --- a/ruby/symbol.c +++ b/ruby/symbol.c @@ -9,13 +9,23 @@ **********************************************************************/ +#include "gc.h" +#include "internal.h" +#include "internal/error.h" +#include "internal/gc.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/symbol.h" +#include "internal/vm.h" +#include "probes.h" #include "ruby/encoding.h" #include "ruby/st.h" -#include "internal.h" #include "symbol.h" -#include "gc.h" -#include "probes.h" +#include "vm_sync.h" +#ifndef USE_SYMBOL_GC +# define USE_SYMBOL_GC 1 +#endif #ifndef SYMBOL_DEBUG # define SYMBOL_DEBUG 0 #endif @@ -25,7 +35,7 @@ #define SYMBOL_PINNED_P(sym) (RSYMBOL(sym)->id&~ID_SCOPE_MASK) -#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT) +#define STATIC_SYM2ID(sym) RSHIFT((VALUE)(sym), RUBY_SPECIAL_SHIFT) static ID register_static_symid(ID, const char *, long, rb_encoding *); static ID register_static_symid_str(ID, VALUE); @@ -64,7 +74,6 @@ enum id_entry_type { }; rb_symbols_t ruby_global_symbols = {tNEXT_ID-1}; -#define global_symbols ruby_global_symbols static const struct st_hash_type symhash = { rb_str_hash_cmp, @@ -74,26 +83,32 @@ static const struct st_hash_type symhash = { void Init_sym(void) { + rb_symbols_t *symbols = &ruby_global_symbols; + VALUE dsym_fstrs = rb_ident_hash_new(); - global_symbols.dsymbol_fstr_hash = dsym_fstrs; + symbols->dsymbol_fstr_hash = dsym_fstrs; rb_gc_register_mark_object(dsym_fstrs); rb_obj_hide(dsym_fstrs); - global_symbols.str_sym = st_init_table_with_size(&symhash, 1000); - global_symbols.ids = rb_ary_tmp_new(0); - rb_gc_register_mark_object(global_symbols.ids); + symbols->str_sym = st_init_table_with_size(&symhash, 1000); + symbols->ids = rb_ary_tmp_new(0); + rb_gc_register_mark_object(symbols->ids); Init_op_tbl(); Init_id(); } -WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type)); -WARN_UNUSED_RESULT(static VALUE dsymbol_check(const VALUE sym)); +WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type)); +WARN_UNUSED_RESULT(static VALUE dsymbol_check(rb_symbols_t *symbols, const VALUE sym)); WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str)); +WARN_UNUSED_RESULT(static VALUE lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str)); WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str)); WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id)); WARN_UNUSED_RESULT(static ID intern_str(VALUE str, int mutable)); +#define GLOBAL_SYMBOLS_ENTER(symbols) rb_symbols_t *symbols = &ruby_global_symbols; RB_VM_LOCK_ENTER() +#define GLOBAL_SYMBOLS_LEAVE() RB_VM_LOCK_LEAVE() + ID rb_id_attrset(ID id) { @@ -229,109 +244,161 @@ rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc) #define IDSET_ATTRSET_FOR_SYNTAX ((1U<') ++m; break; - default: break; + default: return (t) { stophere, ID_JUNK, 1, }; + case '<': return (t) { stophere, ID_JUNK, 2, }; + case '=': + switch (*++m) { + default: return (t) { stophere, ID_JUNK, 2, }; + case '>': return (t) { stophere, ID_JUNK, 3, }; + } } - break; case '>': switch (*++m) { - case '>': case '=': ++m; break; + default: return (t) { stophere, ID_JUNK, 1, }; + case '>': case '=': return (t) { stophere, ID_JUNK, 2, }; } - break; case '=': switch (*++m) { - case '~': ++m; break; - case '=': if (*++m == '=') ++m; break; - default: return -1; + default: return (t) { invalid, 0, 1, }; + case '~': return (t) { stophere, ID_JUNK, 2, }; + case '=': + switch (*++m) { + default: return (t) { stophere, ID_JUNK, 2, }; + case '=': return (t) { stophere, ID_JUNK, 3, }; + } } - break; case '*': - if (*++m == '*') ++m; - break; + switch (*++m) { + default: return (t) { stophere, ID_JUNK, 1, }; + case '*': return (t) { stophere, ID_JUNK, 2, }; + } case '+': case '-': - if (*++m == '@') ++m; - break; + switch (*++m) { + default: return (t) { stophere, ID_JUNK, 1, }; + case '@': return (t) { stophere, ID_JUNK, 2, }; + } case '|': case '^': case '&': case '/': case '%': case '~': case '`': - ++m; - break; + return (t) { stophere, ID_JUNK, 1, }; case '[': - if (m[1] != ']') goto id; - ++m; - if (*++m == '=') ++m; - break; + switch (*++m) { + default: return (t) { needmore, ID_JUNK, 0, }; + case ']': + switch (*++m) { + default: return (t) { stophere, ID_JUNK, 2, }; + case '=': return (t) { stophere, ID_JUNK, 3, }; + } + } case '!': - if (len == 1) return ID_JUNK; switch (*++m) { - case '=': case '~': ++m; break; + case '=': case '~': return (t) { stophere, ID_JUNK, 2, }; default: - if (allowed_attrset & (1U << ID_JUNK)) goto id; - return -1; + if (allowed_attrset & (1U << ID_JUNK)) { + return (t) { needmore, ID_JUNK, 1, }; + } + else { + return (t) { stophere, ID_JUNK, 1, }; + } } - break; default: - type = rb_sym_constant_char_p(m, e-m, enc) ? ID_CONST : ID_LOCAL; - id: - if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) { - if (len > 1 && *(e-1) == '=') { - type = rb_enc_symname_type(name, len-1, enc, allowed_attrset); - if (type != ID_ATTRSET) return ID_ATTRSET; - } - return -1; - } - while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc); - if (m >= e) break; - switch (*m) { - case '!': case '?': - if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1; - type = ID_JUNK; - ++m; - if (m + 1 < e || *m != '=') break; - /* fall through */ - case '=': - if (!(allowed_attrset & (1U << type))) return -1; - type = ID_ATTRSET; - ++m; - break; - } - break; + if (rb_sym_constant_char_p(name, len, enc)) { + return (t) { needmore, ID_CONST, 0, }; + } + else { + return (t) { needmore, ID_LOCAL, 0, }; + } } +} +#undef t + +int +rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset) +{ + const struct enc_synmane_type_leading_chars_tag f = + enc_synmane_type_leading_chars(name, len, enc, allowed_attrset); + const char *m = name + f.nread; + const char *e = name + len; + int type = (int)f.type; + + switch (f.kind) { + case invalid: return -1; + case stophere: break; + case needmore: + + if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) { + if (len > 1 && *(e-1) == '=') { + type = rb_enc_symname_type(name, len-1, enc, allowed_attrset); + if (type != ID_ATTRSET) return ID_ATTRSET; + } + return -1; + } + while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc); + if (m >= e) break; + switch (*m) { + case '!': case '?': + if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1; + type = ID_JUNK; + ++m; + if (m + 1 < e || *m != '=') break; + /* fall through */ + case '=': + if (!(allowed_attrset & (1U << type))) return -1; + type = ID_ATTRSET; + ++m; + break; + } + } + return m == e ? type : -1; } @@ -352,10 +419,12 @@ rb_str_symname_type(VALUE name, unsigned int allowed_attrset) } static void -set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym) +set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym) { + ASSERT_vm_locking(); size_t idx = num / ID_ENTRY_UNIT; - VALUE ary, ids = global_symbols.ids; + + VALUE ary, ids = symbols->ids; if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(ary = rb_ary_entry(ids, (long)idx))) { ary = rb_ary_tmp_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE); rb_ary_store(ids, (long)idx, ary); @@ -368,31 +437,42 @@ set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym) static VALUE get_id_serial_entry(rb_id_serial_t num, ID id, const enum id_entry_type t) { - if (num && num <= global_symbols.last_id) { - size_t idx = num / ID_ENTRY_UNIT; - VALUE ids = global_symbols.ids; - VALUE ary; - if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) { - long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE; - VALUE result = rb_ary_entry(ary, pos + t); - if (NIL_P(result)) return 0; -#if CHECK_ID_SERIAL - if (id) { - VALUE sym = result; - if (t != ID_ENTRY_SYM) - sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM); - if (STATIC_SYM_P(sym)) { - if (STATIC_SYM2ID(sym) != id) return 0; + VALUE result = 0; + + GLOBAL_SYMBOLS_ENTER(symbols); + { + if (num && num <= symbols->last_id) { + size_t idx = num / ID_ENTRY_UNIT; + VALUE ids = symbols->ids; + VALUE ary; + if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) { + long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE; + result = rb_ary_entry(ary, pos + t); + + if (NIL_P(result)) { + result = 0; } else { - if (RSYMBOL(sym)->id != id) return 0; +#if CHECK_ID_SERIAL + if (id) { + VALUE sym = result; + if (t != ID_ENTRY_SYM) + sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM); + if (STATIC_SYM_P(sym)) { + if (STATIC_SYM2ID(sym) != id) result = 0; + } + else { + if (RSYMBOL(sym)->id != id) result = 0; + } + } +#endif } } -#endif - return result; - } + } } - return 0; + GLOBAL_SYMBOLS_LEAVE(); + + return result; } static VALUE @@ -402,14 +482,12 @@ get_id_entry(ID id, const enum id_entry_type t) } static inline ID -#ifdef __GNUC__ -__attribute__((unused)) -#endif rb_id_serial_to_id(rb_id_serial_t num) { if (is_notop_id((ID)num)) { VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM); - return SYM2ID(sym); + if (sym) return SYM2ID(sym); + return ((ID)num << ID_SCOPE_SHIFT) | ID_INTERNAL | ID_STATIC_SYM; } else { return (ID)num; @@ -430,22 +508,26 @@ register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, in #endif static void -register_sym(VALUE str, VALUE sym) +register_sym(rb_symbols_t *symbols, VALUE str, VALUE sym) { + ASSERT_vm_locking(); + #if SYMBOL_DEBUG - st_update(global_symbols.str_sym, (st_data_t)str, - register_sym_update_callback, (st_data_t)sym); + st_update(symbols->str_sym, (st_data_t)str, + register_sym_update_callback, (st_data_t)sym); #else - st_add_direct(global_symbols.str_sym, (st_data_t)str, (st_data_t)sym); + st_add_direct(symbols->str_sym, (st_data_t)str, (st_data_t)sym); #endif } static void -unregister_sym(VALUE str, VALUE sym) +unregister_sym(rb_symbols_t *symbols, VALUE str, VALUE sym) { + ASSERT_vm_locking(); + st_data_t str_data = (st_data_t)str; - if (!st_delete(global_symbols.str_sym, &str_data, NULL)) { - rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str)); + if (!st_delete(symbols->str_sym, &str_data, NULL)) { + rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str)); } } @@ -467,8 +549,12 @@ register_static_symid_str(ID id, VALUE str) RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(str)); - register_sym(str, sym); - set_id_entry(num, str, sym); + GLOBAL_SYMBOLS_ENTER(symbols) + { + register_sym(symbols, str, sym); + set_id_entry(symbols, num, str, sym); + } + GLOBAL_SYMBOLS_LEAVE(); return id; } @@ -516,8 +602,10 @@ must_be_dynamic_symbol(VALUE x) #endif static VALUE -dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type) +dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type) { + ASSERT_vm_locking(); + const VALUE dsym = rb_newobj_of(klass, T_SYMBOL | FL_WB_PROTECTED); long hashval; @@ -529,25 +617,24 @@ dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const /* we want hashval to be in Fixnum range [ruby-core:15713] r15672 */ hashval = (long)rb_str_hash(str); RSYMBOL(dsym)->hashval = RSHIFT((long)hashval, 1); - - register_sym(str, dsym); - rb_hash_aset(global_symbols.dsymbol_fstr_hash, str, Qtrue); - + register_sym(symbols, str, dsym); + rb_hash_aset(symbols->dsymbol_fstr_hash, str, Qtrue); RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(RSYMBOL(dsym)->fstr)); return dsym; } static inline VALUE -dsymbol_check(const VALUE sym) +dsymbol_check(rb_symbols_t *symbols, const VALUE sym) { + ASSERT_vm_locking(); + if (UNLIKELY(rb_objspace_garbage_object_p(sym))) { const VALUE fstr = RSYMBOL(sym)->fstr; const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK; RSYMBOL(sym)->fstr = 0; - - unregister_sym(fstr, sym); - return dsymbol_alloc(rb_cSymbol, fstr, rb_enc_get(fstr), type); + unregister_sym(symbols, fstr, sym); + return dsymbol_alloc(symbols, rb_cSymbol, fstr, rb_enc_get(fstr), type); } else { return sym; @@ -558,7 +645,15 @@ static ID lookup_str_id(VALUE str) { st_data_t sym_data; - if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) { + int found; + + GLOBAL_SYMBOLS_ENTER(symbols); + { + found = st_lookup(symbols->str_sym, (st_data_t)str, &sym_data); + } + GLOBAL_SYMBOLS_LEAVE(); + + if (found) { const VALUE sym = (VALUE)sym_data; if (STATIC_SYM_P(sym)) { @@ -577,22 +672,35 @@ lookup_str_id(VALUE str) } static VALUE -lookup_str_sym(const VALUE str) +lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str) { st_data_t sym_data; - if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) { - VALUE sym = (VALUE)sym_data; - - if (DYNAMIC_SYM_P(sym)) { - sym = dsymbol_check(sym); - } - return sym; + if (st_lookup(symbols->str_sym, (st_data_t)str, &sym_data)) { + VALUE sym = (VALUE)sym_data; + if (DYNAMIC_SYM_P(sym)) { + sym = dsymbol_check(symbols, sym); + } + return sym; } else { - return (VALUE)0; + return Qfalse; } } +static VALUE +lookup_str_sym(const VALUE str) +{ + VALUE sym; + + GLOBAL_SYMBOLS_ENTER(symbols); + { + sym = lookup_str_sym_with_lock(symbols, str); + } + GLOBAL_SYMBOLS_LEAVE(); + + return sym; +} + static VALUE lookup_id_str(ID id) { @@ -606,7 +714,6 @@ rb_intern3(const char *name, long len, rb_encoding *enc) struct RString fake_str; VALUE str = rb_setup_fake_str(&fake_str, name, len, enc); OBJ_FREEZE(str); - sym = lookup_str_sym(str); if (sym) return rb_sym2id(sym); str = rb_enc_str_new(name, len, enc); /* make true string */ @@ -614,17 +721,32 @@ rb_intern3(const char *name, long len, rb_encoding *enc) } static ID -next_id_base(void) +next_id_base_with_lock(rb_symbols_t *symbols) { - rb_id_serial_t next_serial = global_symbols.last_id + 1; + ID id; + rb_id_serial_t next_serial = symbols->last_id + 1; if (next_serial == 0) { - return (ID)-1; + id = (ID)-1; } else { - const size_t num = ++global_symbols.last_id; - return num << ID_SCOPE_SHIFT; + const size_t num = ++symbols->last_id; + id = num << ID_SCOPE_SHIFT; } + + return id; +} + +static ID +next_id_base(void) +{ + ID id; + GLOBAL_SYMBOLS_ENTER(symbols); + { + id = next_id_base_with_lock(symbols); + } + GLOBAL_SYMBOLS_LEAVE(); + return id; } static ID @@ -681,8 +803,13 @@ rb_gc_free_dsymbol(VALUE sym) if (str) { RSYMBOL(sym)->fstr = 0; - unregister_sym(str, sym); - rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, str); + + GLOBAL_SYMBOLS_ENTER(symbols); + { + unregister_sym(symbols, str, sym); + rb_hash_delete_entry(symbols->dsymbol_fstr_hash, str); + } + GLOBAL_SYMBOLS_LEAVE(); } } @@ -709,39 +836,46 @@ rb_gc_free_dsymbol(VALUE sym) VALUE rb_str_intern(VALUE str) { + VALUE sym; #if USE_SYMBOL_GC rb_encoding *enc, *ascii; int type; #else ID id; #endif - VALUE sym = lookup_str_sym(str); - - if (sym) { - return sym; - } - + GLOBAL_SYMBOLS_ENTER(symbols); + { + sym = lookup_str_sym_with_lock(symbols, str); + + if (sym) { + // ok + } + else { #if USE_SYMBOL_GC - enc = rb_enc_get(str); - ascii = rb_usascii_encoding(); - if (enc != ascii && sym_check_asciionly(str)) { - str = rb_str_dup(str); - rb_enc_associate(str, ascii); - OBJ_FREEZE(str); - enc = ascii; - } - else { - str = rb_str_dup(str); - OBJ_FREEZE(str); - } - str = rb_fstring(str); - type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); - if (type < 0) type = ID_JUNK; - return dsymbol_alloc(rb_cSymbol, str, enc, type); + enc = rb_enc_get(str); + ascii = rb_usascii_encoding(); + if (enc != ascii && sym_check_asciionly(str)) { + str = rb_str_dup(str); + rb_enc_associate(str, ascii); + OBJ_FREEZE(str); + enc = ascii; + } + else { + str = rb_str_dup(str); + OBJ_FREEZE(str); + } + str = rb_fstring(str); + type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); + if (type < 0) type = ID_JUNK; + sym = dsymbol_alloc(symbols, rb_cSymbol, str, enc, type); #else - id = intern_str(str, 0); - return ID2SYM(id); + id = intern_str(str, 0); + sym = ID2SYM(id); #endif + } + } + GLOBAL_SYMBOLS_LEAVE(); + return sym; } ID @@ -752,17 +886,23 @@ rb_sym2id(VALUE sym) id = STATIC_SYM2ID(sym); } else if (DYNAMIC_SYM_P(sym)) { - sym = dsymbol_check(sym); - id = RSYMBOL(sym)->id; - if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) { - VALUE fstr = RSYMBOL(sym)->fstr; - ID num = next_id_base(); - - RSYMBOL(sym)->id = id |= num; - /* make it permanent object */ - set_id_entry(rb_id_to_serial(num), fstr, sym); - rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, fstr); + GLOBAL_SYMBOLS_ENTER(symbols); + { + sym = dsymbol_check(symbols, sym); + id = RSYMBOL(sym)->id; + + if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) { + VALUE fstr = RSYMBOL(sym)->fstr; + ID num = next_id_base_with_lock(symbols); + + RSYMBOL(sym)->id = id |= num; + /* make it permanent object */ + + set_id_entry(symbols, rb_id_to_serial(num), fstr, sym); + rb_hash_delete_entry(symbols->dsymbol_fstr_hash, fstr); + } } + GLOBAL_SYMBOLS_LEAVE(); } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)", @@ -812,6 +952,17 @@ rb_make_internal_id(void) return next_id_base() | ID_INTERNAL | ID_STATIC_SYM; } +ID +rb_make_temporary_id(size_t n) +{ + const ID max_id = RB_ID_SERIAL_MAX & ~0xffff; + const ID id = max_id - (ID)n; + if (id <= ruby_global_symbols.last_id) { + rb_raise(rb_eRuntimeError, "too big to make temporary ID: %" PRIdSIZE, n); + } + return (id << ID_SCOPE_SHIFT) | ID_STATIC_SYM | ID_INTERNAL; +} + static int symbols_i(st_data_t key, st_data_t value, st_data_t arg) { @@ -839,15 +990,22 @@ symbols_i(st_data_t key, st_data_t value, st_data_t arg) VALUE rb_sym_all_symbols(void) { - VALUE ary = rb_ary_new2(global_symbols.str_sym->num_entries); - st_foreach(global_symbols.str_sym, symbols_i, ary); + VALUE ary; + + GLOBAL_SYMBOLS_ENTER(symbols); + { + ary = rb_ary_new2(symbols->str_sym->num_entries); + st_foreach(symbols->str_sym, symbols_i, ary); + } + GLOBAL_SYMBOLS_LEAVE(); + return ary; } size_t rb_sym_immortal_count(void) { - return (size_t)global_symbols.last_id; + return (size_t)ruby_global_symbols.last_id; } int @@ -904,17 +1062,6 @@ rb_is_attrset_sym(VALUE sym) return is_attrset_sym(sym); } -/** - * Returns ID for the given name if it is interned already, or 0. - * - * \param namep the pointer to the name object - * \return the ID for *namep - * \pre the object referred by \p namep must be a Symbol or - * a String, or possible to convert with to_str method. - * \post the object referred by \p namep is a Symbol or a - * String if non-zero value is returned, or is a String - * if 0 is returned. - */ ID rb_check_id(volatile VALUE *namep) { @@ -960,8 +1107,13 @@ rb_check_symbol(volatile VALUE *namep) } else if (DYNAMIC_SYM_P(name)) { if (!SYMBOL_PINNED_P(name)) { - name = dsymbol_check(name); - *namep = name; + GLOBAL_SYMBOLS_ENTER(symbols); + { + name = dsymbol_check(symbols, name); + } + GLOBAL_SYMBOLS_LEAVE(); + + *namep = name; } return name; } diff --git a/ruby/symbol.h b/ruby/symbol.h index 4b5c676d5..e2710ba61 100644 --- a/ruby/symbol.h +++ b/ruby/symbol.h @@ -1,3 +1,5 @@ +#ifndef RUBY_SYMBOL_H +#define RUBY_SYMBOL_H 1 /********************************************************************** symbol.h - @@ -9,10 +11,8 @@ **********************************************************************/ -#ifndef RUBY_SYMBOL_H -#define RUBY_SYMBOL_H 1 - #include "id.h" +#include "ruby/encoding.h" #define DYNAMIC_ID_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_OP_ID) #define STATIC_ID2SYM(id) (((VALUE)(id)<tLAST_OP_ID) #define is_local_id(id) (id_type(id)==ID_LOCAL) diff --git a/ruby/template/Doxyfile.tmpl b/ruby/template/Doxyfile.tmpl index a16e43bc6..36c0b1c8d 100644 --- a/ruby/template/Doxyfile.tmpl +++ b/ruby/template/Doxyfile.tmpl @@ -1,4 +1,18 @@ -# Doxyfile 1.5.7 +# Doxyfile 1.9.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + <% srcdir = miniruby = nil opt = OptionParser.new do |o| @@ -15,251 +29,2658 @@ end dot = RbConfig::CONFIG['DOT'] || "" have_dot = dot.empty? ? "NO" : "YES" %> + #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -PROJECT_NAME = Ruby -PROJECT_NUMBER = <%=RUBY_VERSION%><%= RUBY_PATCHLEVEL < 0 ? 'dev' : "p#{RUBY_PATCHLEVEL}" %> (<%=RUBY_RELEASE_DATE%> revision <%=RUBY_REVISION%>) -STRIP_FROM_PATH = <%=srcdir%> -FILE_VERSION_FILTER = "<%=miniruby%> <%=srcdir%>/tool/file2lastrev.rb -q --srcdir=<%=srcdir%>" -INPUT = <%=srcdir%> . -INPUT_FILTER = "<%=miniruby%> <%=srcdir%>/tool/strip-rdoc.rb" + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Ruby + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "<%=RUBY_VERSION%><%= RUBY_PATCHLEVEL < 0 ? 'dev' : "p#{RUBY_PATCHLEVEL}" %> (<%=RUBY_RELEASE_DATE%> revision <%=RUBY_REVISION%>)" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + OUTPUT_DIRECTORY = doc/capi + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + CREATE_SUBDIRS = YES + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = <%=srcdir%> + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + QT_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + ALIASES = +ALIASES += "alias{1}=Just another name of @ref \1" +ALIASES += "old{1}=Old name of @ref \1.^^@deprecated Use @ref \1 instead.^^@ingroup deprecated_macros" +ALIASES += "shyouhei=\@shyouhei" +ALIASES += "ko1=\@ko1" +ALIASES += "matz=\@matz" + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + TYPEDEF_HIDES_STRUCT = NO -SYMBOL_CACHE_SIZE = 0 + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -EXTRACT_ALL = YES + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + HIDE_IN_BODY_DOCS = YES + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = "<%=miniruby%> <%=srcdir%>/tool/file2lastrev.rb -q --srcdir=<%=srcdir%>" + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + WARN_LOGFILE = + #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = +INPUT += <%=srcdir%> +INPUT += . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c *.h *.hpp *.y *.def + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = +FILE_PATTERNS += *.c +FILE_PATTERNS += *.h +FILE_PATTERNS += *.hpp +FILE_PATTERNS += *.y +FILE_PATTERNS +=*.def + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + RECURSIVE = YES -EXCLUDE = <%=srcdir%>/ext/dl/callback <%=srcdir%>/ccan <%=srcdir%>/ext/psych/yaml + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = +EXCLUDE += <%=srcdir%>/ccan +EXCLUDE += <%=srcdir%>/ext + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + EXCLUDE_SYMLINKS = YES -EXCLUDE_PATTERNS = *.src doc enc build */ext/-test-/* tmp test yarvtest lib bootstraptest spec .ext .git .svn extconf.h *prelude.c encdb.h transdb.h insns.def rb_mjit_header.h + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS += *.src +EXCLUDE_PATTERNS += *prelude.c +EXCLUDE_PATTERNS += .ext +EXCLUDE_PATTERNS += .git +EXCLUDE_PATTERNS += .svn +EXCLUDE_PATTERNS += bootstraptest +EXCLUDE_PATTERNS += build +EXCLUDE_PATTERNS += doc +EXCLUDE_PATTERNS += enc +EXCLUDE_PATTERNS += encdb.h +EXCLUDE_PATTERNS += extconf.h +EXCLUDE_PATTERNS += insns.def +EXCLUDE_PATTERNS += lib +EXCLUDE_PATTERNS += rb_mjit_header.h +EXCLUDE_PATTERNS += spec +EXCLUDE_PATTERNS += test +EXCLUDE_PATTERNS += tmp +EXCLUDE_PATTERNS += transdb.h +EXCLUDE_PATTERNS += yarvtest + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + IMAGE_PATH = <%=srcdir%>/doc/images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = "<%=miniruby%> <%=srcdir%>/tool/strip-rdoc.rb" + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + FILTER_SOURCE_FILES = YES + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -COLS_IN_ALPHA_INDEX = 5 + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + IGNORE_PREFIX = + #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + GENERATE_TREEVIEW = NO + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATOR_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /', unescape_element(escapeHTML('
      '), ["A", "IMG"])) end end + +class CGIUtilPureRubyTest < Test::Unit::TestCase + def setup + CGI::Escape.module_eval do + alias _escapeHTML escapeHTML + remove_method :escapeHTML + alias _unescapeHTML unescapeHTML + remove_method :unescapeHTML + end + end + + def teardown + CGI::Escape.module_eval do + alias escapeHTML _escapeHTML + remove_method :_escapeHTML + alias unescapeHTML _unescapeHTML + remove_method :_unescapeHTML + end + end + + def test_cgi_escapeHTML_with_invalid_byte_sequence + assert_equal("<\xA4??>", CGI.escapeHTML(%[<\xA4??>])) + end + + def test_cgi_unescapeHTML_with_invalid_byte_sequence + input = "\xFF&" + assert_equal(input, CGI.unescapeHTML(input)) + end +end diff --git a/ruby/test/coverage/test_coverage.rb b/ruby/test/coverage/test_coverage.rb index 1de39bf56..882368363 100644 --- a/ruby/test/coverage/test_coverage.rb +++ b/ruby/test/coverage/test_coverage.rb @@ -740,4 +740,184 @@ def test_stop_wrong_peephole_optimization end end; end + + def test_branch_coverage_in_ensure_clause + result = { + :branches => { + [:if, 0, 4, 2, 4, 11] => { + [:then, 1, 4, 2, 4, 5] => 1, + [:else, 2, 4, 2, 4, 11] => 1, + } + } + } + assert_coverage(<<~"end;", { branches: true }, result) # Bug #16967 + def foo + yield + ensure + :ok if $! + end + foo {} + foo { raise } rescue nil + end; + end + + def test_coverage_with_asan + result = { :lines => [1, 1, 0, 0, nil, nil, nil] } + + assert_coverage(<<~"end;", { lines: true }, result) # Bug #18001 + class Foo + def bar + baz do |x| + next unless Integer == x + end + end + end + end; + end + + def test_coverage_suspendable + Dir.mktmpdir {|tmp| + Dir.chdir(tmp) { + File.open("test.rb", "w") do |f| + f.puts <<-EOS + def foo + :ok + end + + def bar + :ok + end + + def baz + :ok + end + EOS + end + + cov1 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil]" + cov2 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil]" + assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], []) + Coverage.setup + tmp = Dir.pwd + require tmp + "/test.rb" + foo + Coverage.resume + bar + Coverage.suspend + baz + p Coverage.peek_result[tmp + "/test.rb"] + Coverage.resume + baz + p Coverage.result[tmp + "/test.rb"] + end; + + cov1 = "{:lines=>[0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil], :branches=>{}, :methods=>{[Object, :baz, 9, 12, 11, 15]=>0, [Object, :bar, 5, 12, 7, 15]=>1, [Object, :foo, 1, 12, 3, 15]=>0}}" + cov2 = "{:lines=>[0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil], :branches=>{}, :methods=>{[Object, :baz, 9, 12, 11, 15]=>1, [Object, :bar, 5, 12, 7, 15]=>1, [Object, :foo, 1, 12, 3, 15]=>0}}" + assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], []) + Coverage.setup(:all) + tmp = Dir.pwd + require tmp + "/test.rb" + foo + Coverage.resume + bar + Coverage.suspend + baz + p Coverage.peek_result[tmp + "/test.rb"] + Coverage.resume + baz + p Coverage.result[tmp + "/test.rb"] + end; + + cov1 = "{:oneshot_lines=>[6]}" + cov2 = "{:oneshot_lines=>[6, 10]}" + assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], []) + Coverage.setup(oneshot_lines: true) + tmp = Dir.pwd + require tmp + "/test.rb" + foo + Coverage.resume + bar + Coverage.suspend + baz + p Coverage.peek_result[tmp + "/test.rb"] + Coverage.resume + baz + p Coverage.result[tmp + "/test.rb"] + end; + } + } + end + + def test_coverage_state + assert_in_out_err(%w[-rcoverage], <<-"end;", [":idle", ":running", ":running", ":idle"], []) + p Coverage.state + Coverage.start + p Coverage.state + Coverage.peek_result + p Coverage.state + Coverage.result + p Coverage.state + end; + + assert_in_out_err(%w[-rcoverage], <<-"end;", [":idle", ":suspended", ":running", ":suspended", ":running", ":suspended", ":idle"], []) + p Coverage.state + Coverage.setup + p Coverage.state + Coverage.resume + p Coverage.state + Coverage.suspend + p Coverage.state + Coverage.resume + p Coverage.state + Coverage.suspend + p Coverage.state + Coverage.result + p Coverage.state + end; + end + + def test_result_without_resume + assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], []) + Coverage.setup + p Coverage.result + end; + end + + def test_result_after_suspend + assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], []) + Coverage.start + Coverage.suspend + p Coverage.result + end; + end + + def test_resume_without_setup + assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not set up yet/) + Coverage.resume + p :NG + end; + end + + def test_suspend_without_setup + assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/) + Coverage.suspend + p :NG + end; + end + + def test_double_resume + assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is already running/) + Coverage.start + Coverage.resume + p :NG + end; + end + + def test_double_suspend + assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/) + Coverage.setup + Coverage.suspend + p :NG + end; + end end diff --git a/ruby/test/csv/helper.rb b/ruby/test/csv/helper.rb index eadff5440..1f9cf9697 100644 --- a/ruby/test/csv/helper.rb +++ b/ruby/test/csv/helper.rb @@ -15,4 +15,28 @@ def with_chunk_size(chunk_size) ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size_keep end end + + def with_verbose(verbose) + original = $VERBOSE + begin + $VERBOSE = verbose + yield + ensure + $VERBOSE = original + end + end + + def with_default_internal(encoding) + original = Encoding.default_internal + begin + with_verbose(false) do + Encoding.default_internal = encoding + end + yield + ensure + with_verbose(false) do + Encoding.default_internal = original + end + end + end end diff --git a/ruby/test/csv/interface/test_read.rb b/ruby/test/csv/interface/test_read.rb index 58ec188f9..d73622d55 100644 --- a/ruby/test/csv/interface/test_read.rb +++ b/ruby/test/csv/interface/test_read.rb @@ -32,6 +32,24 @@ def test_foreach assert_equal(@rows, rows) end + if respond_to?(:ractor) + ractor + def test_foreach_in_ractor + ractor = Ractor.new(@input.path) do |path| + rows = [] + CSV.foreach(path, col_sep: "\t", row_sep: "\r\n").each do |row| + rows << row + end + rows + end + rows = [ + ["1", "2", "3"], + ["4", "5"], + ] + assert_equal(rows, ractor.take) + end + end + def test_foreach_mode rows = [] CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n").each do |row| @@ -125,6 +143,68 @@ def test_open_encoding_utf_8_with_bom end end + def test_open_invalid_byte_sequence_in_utf_8 + CSV.open(@input.path, "w", encoding: Encoding::CP932) do |rows| + error = assert_raise(Encoding::InvalidByteSequenceError) do + rows << ["\x82\xa0"] + end + assert_equal('"\x82" on UTF-8', + error.message) + end + end + + def test_open_with_invalid_nil + CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: nil) do |rows| + error = assert_raise(Encoding::InvalidByteSequenceError) do + rows << ["\x82\xa0"] + end + assert_equal('"\x82" on UTF-8', + error.message) + end + end + + def test_open_with_invalid_replace + CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace) do |rows| + rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["??"]], + csv.to_a) + end + end + + def test_open_with_invalid_replace_and_replace_string + CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace, replace: "X") do |rows| + rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["XX"]], + csv.to_a) + end + end + + def test_open_with_undef_replace + # U+00B7 Middle Dot + CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace) do |rows| + rows << ["\u00B7"] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["?"]], + csv.to_a) + end + end + + def test_open_with_undef_replace_and_replace_string + # U+00B7 Middle Dot + CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace, replace: "X") do |rows| + rows << ["\u00B7"] + end + CSV.open(@input.path, encoding: Encoding::CP932) do |csv| + assert_equal([["X"]], + csv.to_a) + end + end + def test_parse assert_equal(@rows, CSV.parse(@data, col_sep: "\t", row_sep: "\r\n")) @@ -178,6 +258,20 @@ def test_read CSV.read(@input.path, col_sep: "\t", row_sep: "\r\n")) end + if respond_to?(:ractor) + ractor + def test_read_in_ractor + ractor = Ractor.new(@input.path) do |path| + CSV.read(path, col_sep: "\t", row_sep: "\r\n") + end + rows = [ + ["1", "2", "3"], + ["4", "5"], + ] + assert_equal(rows, ractor.take) + end + end + def test_readlines assert_equal(@rows, CSV.readlines(@input.path, col_sep: "\t", row_sep: "\r\n")) diff --git a/ruby/test/csv/interface/test_read_write.rb b/ruby/test/csv/interface/test_read_write.rb index 877e5f355..c371e9c5f 100644 --- a/ruby/test/csv/interface/test_read_write.rb +++ b/ruby/test/csv/interface/test_read_write.rb @@ -6,7 +6,7 @@ class TestCSVInterfaceReadWrite < Test::Unit::TestCase extend DifferentOFS def test_filter - input = <<-CSV + input = <<-CSV.freeze 1;2;3 4;5 CSV @@ -24,6 +24,71 @@ def test_filter CSV end + def test_filter_headers_true + input = <<-CSV.freeze +Name,Value +foo,0 +bar,1 +baz,2 + CSV + output = "" + CSV.filter(input, output, headers: true) do |row| + row[0] += "X" + row[1] = row[1].to_i + 1 + end + assert_equal(<<-CSV, output) +fooX,1 +barX,2 +bazX,3 + CSV + end + + def test_filter_headers_true_write_headers + input = <<-CSV.freeze +Name,Value +foo,0 +bar,1 +baz,2 + CSV + output = "" + CSV.filter(input, output, headers: true, out_write_headers: true) do |row| + if row.is_a?(Array) + row[0] += "X" + row[1] += "Y" + else + row[0] += "X" + row[1] = row[1].to_i + 1 + end + end + assert_equal(<<-CSV, output) +NameX,ValueY +fooX,1 +barX,2 +bazX,3 + CSV + end + + def test_filter_headers_array_write_headers + input = <<-CSV.freeze +foo,0 +bar,1 +baz,2 + CSV + output = "" + CSV.filter(input, output, + headers: ["Name", "Value"], + out_write_headers: true) do |row| + row[0] += "X" + row[1] = row[1].to_i + 1 + end + assert_equal(<<-CSV, output) +Name,Value +fooX,1 +barX,2 +bazX,3 + CSV + end + def test_instance_same data = "" assert_equal(CSV.instance(data, col_sep: ";").object_id, @@ -47,4 +112,13 @@ def test_instance_shortcut assert_equal(CSV.instance, CSV {|csv| csv}) end + + def test_instance_shortcut_with_io + io = StringIO.new + from_instance = CSV.instance(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] } + from_shortcut = CSV(io, col_sep: ";") { |csv| csv << ["e", "f", "g"] } + + assert_equal(from_instance, from_shortcut) + assert_equal(from_instance.string, "a;b;c\ne;f;g\n") + end end diff --git a/ruby/test/csv/interface/test_write.rb b/ruby/test/csv/interface/test_write.rb index 8650ecd62..02c2c5c5c 100644 --- a/ruby/test/csv/interface/test_write.rb +++ b/ruby/test/csv/interface/test_write.rb @@ -25,6 +25,21 @@ def test_generate_default CSV end + if respond_to?(:ractor) + ractor + def test_generate_default_in_ractor + ractor = Ractor.new do + CSV.generate do |csv| + csv << [1, 2, 3] << [4, nil, 5] + end + end + assert_equal(<<-CSV, ractor.take) +1,2,3 +4,,5 + CSV + end + end + def test_generate_append csv_text = <<-CSV 1,2,3 @@ -101,6 +116,25 @@ def test_append_row CSV end + + if respond_to?(:ractor) + ractor + def test_append_row_in_ractor + ractor = Ractor.new(@output.path) do |path| + CSV.open(path, "wb") do |csv| + csv << + CSV::Row.new([], ["1", "2", "3"]) << + CSV::Row.new([], ["a", "b", "c"]) + end + end + ractor.take + assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) +1,2,3 +a,b,c + CSV + end + end + def test_append_hash CSV.open(@output.path, "wb", headers: true) do |csv| csv << [:a, :b, :c] diff --git a/ruby/test/csv/parse/test_convert.rb b/ruby/test/csv/parse/test_convert.rb index bfe6ddd52..21d9f20b2 100644 --- a/ruby/test/csv/parse/test_convert.rb +++ b/ruby/test/csv/parse/test_convert.rb @@ -43,7 +43,7 @@ def test_integer_float @parser.shift) end - def test_numberic + def test_numeric @parser.convert(:numeric) assert_equal(["Numbers", ":integer", 1, ":float", 3.015], @parser.shift) diff --git a/ruby/test/csv/parse/test_general.rb b/ruby/test/csv/parse/test_general.rb index 655bb2656..d2b74008e 100644 --- a/ruby/test/csv/parse/test_general.rb +++ b/ruby/test/csv/parse/test_general.rb @@ -14,7 +14,7 @@ class TestCSVParseGeneral < Test::Unit::TestCase extend DifferentOFS - BIG_DATA = "123456789\n" * 1024 + BIG_DATA = "123456789\n" * 512 def test_mastering_regex_example ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K} @@ -246,7 +246,11 @@ def test_seeked_string_io private def assert_parse_errors_out(data, **options) assert_raise(CSV::MalformedCSVError) do - Timeout.timeout(0.2) do + timeout = 0.2 + if defined?(RubyVM::MJIT.enabled?) and RubyVM::MJIT.enabled? + timeout = 5 # for --jit-wait + end + Timeout.timeout(timeout) do CSV.parse(data, **options) fail("Parse didn't error out") end diff --git a/ruby/test/csv/parse/test_invalid.rb b/ruby/test/csv/parse/test_invalid.rb index 9dfd08138..ddb59e2b9 100644 --- a/ruby/test/csv/parse/test_invalid.rb +++ b/ruby/test/csv/parse/test_invalid.rb @@ -36,4 +36,17 @@ def test_ignore_invalid_line csv.shift) assert_equal(true, csv.eof?) end + + def test_ignore_invalid_line_cr_lf + data = <<-CSV +"1","OK"\r +"2",""NOT" OK"\r +"3","OK"\r +CSV + csv = CSV.new(data) + + assert_equal(['1', 'OK'], csv.shift) + assert_raise(CSV::MalformedCSVError) { csv.shift } + assert_equal(['3', 'OK'], csv.shift) + end end diff --git a/ruby/test/csv/parse/test_skip_lines.rb b/ruby/test/csv/parse/test_skip_lines.rb index 196858f1b..98d67ae51 100644 --- a/ruby/test/csv/parse/test_skip_lines.rb +++ b/ruby/test/csv/parse/test_skip_lines.rb @@ -102,4 +102,17 @@ def test_multibyte_data :skip_lines => /\A#/)) end end + + def test_empty_line_and_liberal_parsing + assert_equal([["a", "b"]], + CSV.parse("a,b\n", + :liberal_parsing => true, + :skip_lines => /^$/)) + end + + def test_crlf + assert_equal([["a", "b"]], + CSV.parse("a,b\r\n,\r\n", + :skip_lines => /^,+$/)) + end end diff --git a/ruby/test/csv/parse/test_strip.rb b/ruby/test/csv/parse/test_strip.rb index 0255bb9a3..c5e35209c 100644 --- a/ruby/test/csv/parse/test_strip.rb +++ b/ruby/test/csv/parse/test_strip.rb @@ -21,6 +21,11 @@ def test_right CSV.parse_line(%Q{a ,b }, strip: true)) end + def test_middle + assert_equal(["a b"], + CSV.parse_line(%Q{a b}, strip: true)) + end + def test_quoted assert_equal([" a ", " b "], CSV.parse_line(%Q{" a "," b "}, strip: true)) @@ -75,4 +80,33 @@ def test_do_not_strip_crlf %Q{"a" ,"b " \r\n}, strip: true)) end + + def test_col_sep_incompatible_true + message = "The provided strip (true) and " \ + "col_sep (\\t) options are incompatible." + assert_raise_with_message(ArgumentError, message) do + CSV.parse_line(%Q{"a"\t"b"\n}, + col_sep: "\t", + strip: true) + end + end + + def test_col_sep_incompatible_string + message = "The provided strip (\\t) and " \ + "col_sep (\\t) options are incompatible." + assert_raise_with_message(ArgumentError, message) do + CSV.parse_line(%Q{"a"\t"b"\n}, + col_sep: "\t", + strip: "\t") + end + end + + def test_col_sep_compatible_string + assert_equal( + ["a", "b"], + CSV.parse_line(%Q{\va\tb\v\n}, + col_sep: "\t", + strip: "\v") + ) + end end diff --git a/ruby/test/csv/test_encodings.rb b/ruby/test/csv/test_encodings.rb index acee03db4..8d228c05f 100644 --- a/ruby/test/csv/test_encodings.rb +++ b/ruby/test/csv/test_encodings.rb @@ -5,6 +5,7 @@ class TestCSVEncodings < Test::Unit::TestCase extend DifferentOFS + include Helper def setup super @@ -241,6 +242,18 @@ def test_encoding_is_upgraded_for_ascii_content_during_writing_as_needed assert_equal("UTF-8", data.to_csv.encoding.name) end + def test_encoding_is_not_upgraded_for_non_ascii_content_during_writing_as_needed + data = ["\u00c0".encode("ISO-8859-1"), "\u3042"] + assert_equal([ + "ISO-8859-1", + "UTF-8", + ], + data.collect {|field| field.encoding.name}) + assert_raise(Encoding::CompatibilityError) do + data.to_csv + end + end + def test_explicit_encoding bug9766 = '[ruby-core:62113] [Bug #9766]' s = CSV.generate(encoding: "Windows-31J") do |csv| @@ -249,6 +262,15 @@ def test_explicit_encoding assert_equal(["foo,\u3042\n".encode(Encoding::Windows_31J), Encoding::Windows_31J], [s, s.encoding], bug9766) end + def test_encoding_with_default_internal + with_default_internal(Encoding::UTF_8) do + s = CSV.generate(String.new(encoding: Encoding::Big5), encoding: Encoding::Big5) do |csv| + csv << ["漢字"] + end + assert_equal(["漢字\n".encode(Encoding::Big5), Encoding::Big5], [s, s.encoding]) + end + end + def test_row_separator_detection_with_invalid_encoding csv = CSV.new("invalid,\xF8\r\nvalid,x\r\n".force_encoding("UTF-8"), encoding: "UTF-8") diff --git a/ruby/test/csv/test_row.rb b/ruby/test/csv/test_row.rb index f709dd3f1..b71794504 100644 --- a/ruby/test/csv/test_row.rb +++ b/ruby/test/csv/test_row.rb @@ -425,6 +425,9 @@ def test_dig_cell_no_dig def test_dup row = CSV::Row.new(["A"], ["foo"]) dupped_row = row.dup + dupped_row["A"] = "bar" + assert_equal(["foo", "bar"], + [row["A"], dupped_row["A"]]) dupped_row.delete("A") assert_equal(["foo", nil], [row["A"], dupped_row["A"]]) diff --git a/ruby/test/csv/test_table.rb b/ruby/test/csv/test_table.rb index 50edc77e4..968e64eae 100644 --- a/ruby/test/csv/test_table.rb +++ b/ruby/test/csv/test_table.rb @@ -16,11 +16,11 @@ def setup @header_table = CSV::Table.new( [CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows ) - + @header_only_table = CSV::Table.new([], headers: %w{A B C}) end - def test_initialze + def test_initialize assert_not_nil(@table) assert_instance_of(CSV::Table, @table) end diff --git a/ruby/test/csv/write/test_converters.rb b/ruby/test/csv/write/test_converters.rb index a93b1040a..0e0080b4c 100644 --- a/ruby/test/csv/write/test_converters.rb +++ b/ruby/test/csv/write/test_converters.rb @@ -20,14 +20,14 @@ def test_multiple end def test_nil_value - assert_equal(%Q[a,NaN,c\n], - generate_line(["a", nil, "c"], + assert_equal(%Q[a,NaN,29\n], + generate_line(["a", nil, 29], write_nil_value: "NaN")) end def test_empty_value - assert_equal(%Q[a,,c\n], - generate_line(["a", "", "c"], + assert_equal(%Q[a,,29\n], + generate_line(["a", "", 29], write_empty_value: nil)) end end diff --git a/ruby/test/csv/write/test_force_quotes.rb b/ruby/test/csv/write/test_force_quotes.rb new file mode 100644 index 000000000..622dcb021 --- /dev/null +++ b/ruby/test/csv/write/test_force_quotes.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: false + +require_relative "../helper" + +module TestCSVWriteForceQuotes + def test_default + assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}], + generate_line(["1", "2", "3"])) + end + + def test_true + assert_equal(%Q["1","2","3"#{$INPUT_RECORD_SEPARATOR}], + generate_line(["1", "2", "3"], + force_quotes: true)) + end + + def test_false + assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}], + generate_line(["1", "2", "3"], + force_quotes: false)) + end + + def test_field_name + assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}], + generate_line(["1", "2", "3"], + headers: ["a", "b", "c"], + force_quotes: ["a", :c])) + end + + def test_field_name_without_headers + force_quotes = ["a", "c"] + error = assert_raise(ArgumentError) do + generate_line(["1", "2", "3"], + force_quotes: force_quotes) + end + assert_equal(":headers is required when you use field name " + + "in :force_quotes: " + + "#{force_quotes.first.inspect}: #{force_quotes.inspect}", + error.message) + end + + def test_field_index + assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}], + generate_line(["1", "2", "3"], + force_quotes: [0, 2])) + end + + def test_field_unknown + force_quotes = [1.1] + error = assert_raise(ArgumentError) do + generate_line(["1", "2", "3"], + force_quotes: force_quotes) + end + assert_equal(":force_quotes element must be field index or field name: " + + "#{force_quotes.first.inspect}: #{force_quotes.inspect}", + error.message) + end +end + +class TestCSVWriteForceQuotesGenerateLine < Test::Unit::TestCase + include TestCSVWriteForceQuotes + extend DifferentOFS + + def generate_line(row, **kwargs) + CSV.generate_line(row, **kwargs) + end +end + +class TestCSVWriteForceQuotesGenerate < Test::Unit::TestCase + include TestCSVWriteForceQuotes + extend DifferentOFS + + def generate_line(row, **kwargs) + CSV.generate(**kwargs) do |csv| + csv << row + end + end +end diff --git a/ruby/test/csv/write/test_general.rb b/ruby/test/csv/write/test_general.rb index f39456b98..677119e1a 100644 --- a/ruby/test/csv/write/test_general.rb +++ b/ruby/test/csv/write/test_general.rb @@ -4,6 +4,8 @@ require_relative "../helper" module TestCSVWriteGeneral + include Helper + def test_tab assert_equal("\t#{$INPUT_RECORD_SEPARATOR}", generate_line(["\t"])) @@ -221,20 +223,6 @@ def test_with_default_internal generate_line(row)) end end - - def with_default_internal(encoding) - original = Encoding.default_internal - begin - $VERBOSE, verbose_bak = nil, $VERBOSE - Encoding.default_internal = encoding - $VERBOSE = verbose_bak - yield - ensure - $VERBOSE, verbose_bak = nil, $VERBOSE - Encoding.default_internal = original - $VERBOSE = verbose_bak - end - end end class TestCSVWriteGeneralGenerateLine < Test::Unit::TestCase diff --git a/ruby/test/date/test_date.rb b/ruby/test/date/test_date.rb index ebd75ae12..6e99bc562 100644 --- a/ruby/test/date/test_date.rb +++ b/ruby/test/date/test_date.rb @@ -163,4 +163,16 @@ def test_submillisecond_comparison assert_equal(1, d2 <=> d1) end + def test_infinity_comparison + assert_equal(0, Float::INFINITY <=> Date::Infinity.new) + assert_equal(0, Date::Infinity.new <=> Float::INFINITY) + assert_equal(0, -Float::INFINITY <=> -Date::Infinity.new) + assert_equal(0, -Date::Infinity.new <=> -Float::INFINITY) + + assert_equal(1, Float::INFINITY <=> -Date::Infinity.new) + assert_equal(1, Date::Infinity.new <=> -Float::INFINITY) + + assert_equal(-1, -Float::INFINITY <=> Date::Infinity.new) + assert_equal(-1, -Date::Infinity.new <=> Float::INFINITY) + end end diff --git a/ruby/test/date/test_date_marshal.rb b/ruby/test/date/test_date_marshal.rb index c7ce737aa..fa8b2d91f 100644 --- a/ruby/test/date/test_date_marshal.rb +++ b/ruby/test/date/test_date_marshal.rb @@ -39,6 +39,13 @@ def test_marshal assert(d.frozen?) expected_error = defined?(FrozenError) ? FrozenError : RuntimeError assert_raise(expected_error){d.marshal_load(a)} + + d = Date.new + 1/2r + 2304/65437r/86400 + m = Marshal.dump(d) + d2 = Marshal.load(m) + assert_equal(d, d2) + assert_equal(d.start, d2.start) + assert_instance_of(String, d2.to_s) end def test_memsize diff --git a/ruby/test/date/test_date_parse.rb b/ruby/test/date/test_date_parse.rb index 9f9263538..34a672b06 100644 --- a/ruby/test/date/test_date_parse.rb +++ b/ruby/test/date/test_date_parse.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'test/unit' require 'date' +require 'timeout' class TestDateParse < Test::Unit::TestCase @@ -847,6 +848,13 @@ def test__iso8601 h = Date._iso8601('') assert_equal({}, h) + + h = Date._iso8601(nil) + assert_equal({}, h) + + h = Date._iso8601('01-02-03T04:05:06Z'.to_sym) + assert_equal([2001, 2, 3, 4, 5, 6, 0], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test__rfc3339 @@ -862,6 +870,13 @@ def test__rfc3339 h = Date._rfc3339('') assert_equal({}, h) + + h = Date._rfc3339(nil) + assert_equal({}, h) + + h = Date._rfc3339('2001-02-03T04:05:06Z'.to_sym) + assert_equal([2001, 2, 3, 4, 5, 6, 0], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test__xmlschema @@ -944,6 +959,13 @@ def test__xmlschema h = Date._xmlschema('') assert_equal({}, h) + + h = Date._xmlschema(nil) + assert_equal({}, h) + + h = Date._xmlschema('2001-02-03'.to_sym) + assert_equal([2001, 2, 3, nil, nil, nil, nil], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test__rfc2822 @@ -976,6 +998,13 @@ def test__rfc2822 h = Date._rfc2822('') assert_equal({}, h) + + h = Date._rfc2822(nil) + assert_equal({}, h) + + h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT'.to_sym) + assert_equal([2001, 2, 3, 4, 5, 6, 0], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test__httpdate @@ -996,6 +1025,13 @@ def test__httpdate h = Date._httpdate('') assert_equal({}, h) + + h = Date._httpdate(nil) + assert_equal({}, h) + + h = Date._httpdate('Sat, 03 Feb 2001 04:05:06 GMT'.to_sym) + assert_equal([2001, 2, 3, 4, 5, 6, 0], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test__jisx0301 @@ -1072,6 +1108,13 @@ def test__jisx0301 h = Date._jisx0301('') assert_equal({}, h) + + h = Date._jisx0301(nil) + assert_equal({}, h) + + h = Date._jisx0301('H13.02.03T04:05:06.07+0100'.to_sym) + assert_equal([2001, 2, 3, 4, 5, 6, 3600], + h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset)) end def test_iso8601 @@ -1228,4 +1271,32 @@ def test_given_string assert_equal(s0, s) end + def test_length_limit + assert_raise(ArgumentError) { Date._parse("1" * 1000) } + assert_raise(ArgumentError) { Date._iso8601("1" * 1000) } + assert_raise(ArgumentError) { Date._rfc3339("1" * 1000) } + assert_raise(ArgumentError) { Date._xmlschema("1" * 1000) } + assert_raise(ArgumentError) { Date._rfc2822("1" * 1000) } + assert_raise(ArgumentError) { Date._rfc822("1" * 1000) } + assert_raise(ArgumentError) { Date._jisx0301("1" * 1000) } + + assert_raise(ArgumentError) { Date.parse("1" * 1000) } + assert_raise(ArgumentError) { Date.iso8601("1" * 1000) } + assert_raise(ArgumentError) { Date.rfc3339("1" * 1000) } + assert_raise(ArgumentError) { Date.xmlschema("1" * 1000) } + assert_raise(ArgumentError) { Date.rfc2822("1" * 1000) } + assert_raise(ArgumentError) { Date.rfc822("1" * 1000) } + assert_raise(ArgumentError) { Date.jisx0301("1" * 1000) } + + assert_raise(ArgumentError) { DateTime.parse("1" * 1000) } + assert_raise(ArgumentError) { DateTime.iso8601("1" * 1000) } + assert_raise(ArgumentError) { DateTime.rfc3339("1" * 1000) } + assert_raise(ArgumentError) { DateTime.xmlschema("1" * 1000) } + assert_raise(ArgumentError) { DateTime.rfc2822("1" * 1000) } + assert_raise(ArgumentError) { DateTime.rfc822("1" * 1000) } + assert_raise(ArgumentError) { DateTime.jisx0301("1" * 1000) } + + assert_raise(ArgumentError) { Date._parse("Jan " + "9" * 1000000) } + assert_raise(Timeout::Error) { Timeout.timeout(1) { Date._parse("Jan " + "9" * 1000000, limit: nil) } } + end end diff --git a/ruby/test/date/test_date_ractor.rb b/ruby/test/date/test_date_ractor.rb new file mode 100644 index 000000000..7b0c3f491 --- /dev/null +++ b/ruby/test/date/test_date_ractor.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true +require 'test/unit' +require 'date' + +class TestDateParse < Test::Unit::TestCase + def code(klass = Date, share: false) + <<~RUBY.gsub('Date', klass.name) + share = #{share} + d = Date.parse('Aug 23:55') + Ractor.make_shareable(d) if share + d2, d3 = Ractor.new(d) { |d| [d, Date.parse(d.to_s)] }.take + if share + assert_same d, d2 + else + assert_equal d, d2 + end + assert_equal d, d3 + RUBY + end + + def test_date_ractor + assert_ractor(code , require: 'date') + assert_ractor(code( share: true), require: 'date') + assert_ractor(code(DateTime ), require: 'date') + assert_ractor(code(DateTime, share: true), require: 'date') + end +end diff --git a/ruby/test/date/test_date_strftime.rb b/ruby/test/date/test_date_strftime.rb index f82874d26..be9354504 100644 --- a/ruby/test/date/test_date_strftime.rb +++ b/ruby/test/date/test_date_strftime.rb @@ -48,7 +48,7 @@ class TestDateStrftime < Test::Unit::TestCase '%t'=>["\t",{}], '%u'=>['6',{:cwday=>6}], '%V'=>['05',{:cweek=>5}], - '%v'=>[' 3-Feb-2001',{:mday=>3,:mon=>2,:year=>2001}], + '%v'=>[' 3-FEB-2001',{:mday=>3,:mon=>2,:year=>2001}], '%z'=>['+0000',{:zone=>'+0000',:offset=>0}], '%+'=>['Sat Feb 3 00:00:00 +00:00 2001', {:wday=>6,:mon=>2,:mday=>3, diff --git a/ruby/test/dbm/test_dbm.rb b/ruby/test/dbm/test_dbm.rb deleted file mode 100644 index dcbe57851..000000000 --- a/ruby/test/dbm/test_dbm.rb +++ /dev/null @@ -1,634 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'tmpdir' - -begin - require 'dbm' -rescue LoadError -end - -if defined? DBM - require 'tmpdir' - require 'fileutils' - - class TestDBM_RDONLY < Test::Unit::TestCase - def TestDBM_RDONLY.uname_s - require 'rbconfig' - case RbConfig::CONFIG['target_os'] - when 'cygwin' - require 'etc' - Etc.uname[:sysname] - else - RbConfig::CONFIG['target_os'] - end - end - SYSTEM = uname_s - - def setup - @tmpdir = Dir.mktmpdir("tmptest_dbm") - @prefix = "tmptest_dbm_#{$$}" - @path = "#{@tmpdir}/#{@prefix}_" - - # prepare to make readonly DBM file - DBM.open("#{@tmpdir}/#{@prefix}_rdonly") {|dbm| - dbm['foo'] = 'FOO' - } - - File.chmod(0400, *Dir.glob("#{@tmpdir}/#{@prefix}_rdonly.*")) - - assert_instance_of(DBM, @dbm_rdonly = DBM.new("#{@tmpdir}/#{@prefix}_rdonly", nil)) - end - def teardown - assert_nil(@dbm_rdonly.close) - ObjectSpace.each_object(DBM) do |obj| - obj.close unless obj.closed? - end - FileUtils.remove_entry_secure @tmpdir - end - - def test_delete_rdonly - skip("skipped because root can read anything") if Process.uid == 0 - - if /^CYGWIN_9/ !~ SYSTEM - assert_raise(DBMError) { - @dbm_rdonly.delete("foo") - } - - assert_nil(@dbm_rdonly.delete("bar")) - end - end - - def test_fetch_not_found - notfound = nil - result = Object.new - assert_same(result, @dbm_rdonly.fetch("bar") {|k| notfound = k; result}) - assert_equal("bar", notfound) - end - end - - class TestDBM < Test::Unit::TestCase - def setup - @tmpdir = Dir.mktmpdir("tmptest_dbm") - @prefix = "tmptest_dbm_#{$$}" - @path = "#{@tmpdir}/#{@prefix}_" - assert_instance_of(DBM, @dbm = DBM.new(@path)) - end - def teardown - assert_nil(@dbm.close) unless @dbm.closed? - ObjectSpace.each_object(DBM) do |obj| - obj.close unless obj.closed? - end - FileUtils.remove_entry_secure @tmpdir - end - - def check_size(expect, dbm=@dbm) - assert_equal(expect, dbm.size) - n = 0 - dbm.each { n+=1 } - assert_equal(expect, n) - if expect == 0 - assert_equal(true, dbm.empty?) - else - assert_equal(false, dbm.empty?) - end - end - - def test_dbmfile_suffix - @dbm.close - prefix = File.basename(@path) - suffixes = Dir.entries(@tmpdir).grep(/\A#{Regexp.escape prefix}/) { $' }.sort - pagname = "#{@path}.pag" - dirname = "#{@path}.dir" - dbname = "#{@path}.db" - case DBM::VERSION - when /\bNDBM\b/ - assert_equal(%w[.dir .pag], suffixes) - assert(File.zero?(pagname)) - assert(File.zero?(dirname)) - when /\bGDBM\b/ - assert_equal(%w[.dir .pag], suffixes) - assert(!File.zero?(pagname)) - assert(!File.zero?(dirname)) - pag = File.binread(pagname, 16) - pag_magics = [ - 0x13579ace, # GDBM_OMAGIC - 0x13579acd, # GDBM_MAGIC32 - 0x13579acf, # GDBM_MAGIC64 - ] - assert_operator(pag_magics, :include?, - pag.unpack("i")[0]) # native endian, native int. - if !File.identical?(pagname, dirname) - dir = File.binread(dirname, 16) - assert_equal("GDBM", dir[0, 4]) - end - when /\bBerkeley DB\b/ - assert_equal(%w[.db], suffixes) - assert(!File.zero?(dbname)) - db = File.binread(dbname, 16) - assert(db[0,4].unpack("N") == [0x00061561] || # Berkeley DB 1 - db[12,4].unpack("L") == [0x00061561]) # Berkeley DBM 2 or later. - when /\bQDBM\b/ - assert_equal(%w[.dir .pag], suffixes) - assert(!File.zero?(pagname)) - assert(!File.zero?(dirname)) - dir = File.binread(dirname, 16) - assert_equal("[depot]\0\v", dir[0, 9]) - pag = File.binread(pagname, 16) - if [1].pack("s") == "\x00\x01" # big endian - assert_equal("[DEPOT]\n\f", pag[0, 9]) - else # little endian - assert_equal("[depot]\n\f", pag[0, 9]) - end - end - if suffixes == %w[.db] - assert_match(/\bBerkeley DB\b/, DBM::VERSION) - end - end - - def test_s_new_has_no_block - # DBM.new ignore the block - foo = true - assert_instance_of(DBM, dbm = DBM.new("#{@tmpdir}/#{@prefix}") { foo = false }) - assert_equal(foo, true) - assert_nil(dbm.close) - end - - def test_s_open_no_create - skip "dbm_open() is broken on libgdbm 1.8.0 or prior (#{DBM::VERSION})" if /GDBM version 1\.(?:[0-7]\b|8\.0)/ =~ DBM::VERSION - assert_nil(dbm = DBM.open("#{@tmpdir}/#{@prefix}", nil)) - ensure - dbm.close if dbm - end - - def test_s_open_with_block - assert_equal(DBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo) - end - - def test_close - assert_instance_of(DBM, dbm = DBM.open("#{@tmpdir}/#{@prefix}")) - assert_nil(dbm.close) - - # closed DBM file - assert_raise(DBMError) { dbm.close } - end - - def test_aref - assert_equal('bar', @dbm['foo'] = 'bar') - assert_equal('bar', @dbm['foo']) - - assert_nil(@dbm['bar']) - end - - def test_fetch - assert_equal('bar', @dbm['foo']='bar') - assert_equal('bar', @dbm.fetch('foo')) - - # key not found - assert_raise(IndexError) { - @dbm.fetch('bar') - } - - # test for `ifnone' arg - assert_equal('baz', @dbm.fetch('bar', 'baz')) - - # test for `ifnone' block - assert_equal('foobar', @dbm.fetch('bar') {|key| 'foo' + key }) - end - - def test_aset - num = 0 - 2.times {|i| - assert_equal('foo', @dbm['foo'] = 'foo') - assert_equal('foo', @dbm['foo']) - assert_equal('bar', @dbm['foo'] = 'bar') - assert_equal('bar', @dbm['foo']) - - num += 1 if i == 0 - assert_equal(num, @dbm.size) - - # assign nil - assert_equal('', @dbm['bar'] = '') - assert_equal('', @dbm['bar']) - - num += 1 if i == 0 - assert_equal(num, @dbm.size) - - # empty string - assert_equal('', @dbm[''] = '') - assert_equal('', @dbm['']) - - num += 1 if i == 0 - assert_equal(num, @dbm.size) - - # Integer - assert_equal('200', @dbm['100'] = '200') - assert_equal('200', @dbm['100']) - - num += 1 if i == 0 - assert_equal(num, @dbm.size) - - # Big key and value - assert_equal('y' * 100, @dbm['x' * 100] = 'y' * 100) - assert_equal('y' * 100, @dbm['x' * 100]) - - num += 1 if i == 0 - assert_equal(num, @dbm.size) - } - end - - def test_key - assert_equal('bar', @dbm['foo'] = 'bar') - assert_equal('foo', @dbm.key('bar')) - assert_nil(@dbm['bar']) - end - - def test_values_at - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - assert_equal(values.reverse, @dbm.values_at(*keys.reverse)) - end - - def test_select_with_block - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - ret = @dbm.select {|k,v| - assert_equal(k.upcase, v) - k != "bar" - } - assert_equal([['baz', 'BAZ'], ['foo', 'FOO']], - ret.sort) - end - - def test_length - num = 10 - assert_equal(0, @dbm.size) - num.times {|i| - i = i.to_s - @dbm[i] = i - } - assert_equal(num, @dbm.size) - - @dbm.shift - - assert_equal(num - 1, @dbm.size) - end - - def test_empty? - assert_equal(true, @dbm.empty?) - @dbm['foo'] = 'FOO' - assert_equal(false, @dbm.empty?) - end - - def test_each_pair - n = 0 - @dbm.each_pair { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - n = 0 - ret = @dbm.each_pair {|key, val| - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@dbm, ret) - end - - def test_each_value - n = 0 - @dbm.each_value { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - n = 0 - ret = @dbm.each_value {|val| - assert_not_nil(key = @dbm.key(val)) - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@dbm, ret) - end - - def test_each_key - n = 0 - @dbm.each_key { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - n = 0 - ret = @dbm.each_key {|key| - assert_not_nil(i = keys.index(key)) - assert_equal(@dbm[key], values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@dbm, ret) - end - - def test_keys - assert_equal([], @dbm.keys) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - assert_equal(keys.sort, @dbm.keys.sort) - assert_equal(values.sort, @dbm.values.sort) - end - - def test_values - test_keys - end - - def test_shift - assert_nil(@dbm.shift) - assert_equal(0, @dbm.size) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - ret_keys = [] - ret_values = [] - while ret = @dbm.shift - ret_keys.push ret[0] - ret_values.push ret[1] - - assert_equal(keys.size - ret_keys.size, @dbm.size) - end - - assert_equal(keys.sort, ret_keys.sort) - assert_equal(values.sort, ret_values.sort) - end - - def test_delete - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - key = keys[1] - - assert_nil(@dbm.delete(key)) - assert_equal(0, @dbm.size) - - @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values - - assert_equal('BAR', @dbm.delete(key)) - assert_nil(@dbm[key]) - assert_equal(2, @dbm.size) - - assert_nil(@dbm.delete(key)) - end - - def test_delete_with_block - key = 'no called block' - @dbm[key] = 'foo' - assert_equal('foo', @dbm.delete(key) {|k| k.replace 'called block'; :blockval}) - assert_equal(0, @dbm.size) - - key = 'no called block'.dup - assert_equal(:blockval, @dbm.delete(key) {|k| k.replace 'called block'; :blockval}) - assert_equal(0, @dbm.size) - end - - def test_delete_if - v = "0" - 100.times {@dbm[v] = v; v = v.next} - - ret = @dbm.delete_if {|key, val| key.to_i < 50} - assert_equal(@dbm, ret) - check_size(50, @dbm) - - ret = @dbm.delete_if {|key, val| key.to_i >= 50} - assert_equal(@dbm, ret) - check_size(0, @dbm) - - # break - v = "0" - 100.times {@dbm[v] = v; v = v.next} - check_size(100, @dbm) - n = 0; - @dbm.delete_if {|key, val| - break if n > 50 - n+=1 - true - } - assert_equal(51, n) - check_size(49, @dbm) - - @dbm.clear - - # raise - v = "0" - 100.times {@dbm[v] = v; v = v.next} - check_size(100, @dbm) - n = 0; - begin - @dbm.delete_if {|key, val| - raise "runtime error" if n > 50 - n+=1 - true - } - rescue RuntimeError - end - assert_equal(51, n) - check_size(49, @dbm) - end - - def test_reject - v = "0" - 100.times {@dbm[v] = v; v = v.next} - - hash = @dbm.reject {|key, val| key.to_i < 50} - assert_instance_of(Hash, hash) - assert_equal(100, @dbm.size) - - assert_equal(50, hash.size) - hash.each_pair {|key,val| - assert_equal(false, key.to_i < 50) - assert_equal(key, val) - } - - hash = @dbm.reject {|key, val| key.to_i < 100} - assert_instance_of(Hash, hash) - assert_equal(true, hash.empty?) - end - - def test_clear - v = "1" - 100.times {v = v.next; @dbm[v] = v} - - assert_equal(@dbm, @dbm.clear) - - # validate DBM#size - i = 0 - @dbm.each { i += 1 } - assert_equal(@dbm.size, i) - assert_equal(0, i) - end - - def test_invert - v = "0" - 100.times {@dbm[v] = v; v = v.next} - - hash = @dbm.invert - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_update - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @dbm["101"] = "101" - @dbm.update hash - assert_equal(101, @dbm.size) - @dbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_replace - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @dbm["101"] = "101" - @dbm.replace hash - assert_equal(100, @dbm.size) - @dbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_haskey? - assert_equal('bar', @dbm['foo']='bar') - assert_equal(true, @dbm.has_key?('foo')) - assert_equal(false, @dbm.has_key?('bar')) - end - - def test_has_value? - assert_equal('bar', @dbm['foo']='bar') - assert_equal(true, @dbm.has_value?('bar')) - assert_equal(false, @dbm.has_value?('foo')) - end - - def test_to_a - v = "0" - 100.times {v = v.next; @dbm[v] = v} - - ary = @dbm.to_a - assert_instance_of(Array, ary) - assert_equal(100, ary.size) - ary.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_to_hash - v = "0" - 100.times {v = v.next; @dbm[v] = v} - - hash = @dbm.to_hash - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - end - - class TestDBM2 < Test::Unit::TestCase - def setup - @tmproot = Dir.mktmpdir('ruby-dbm') - end - - def teardown - FileUtils.remove_entry_secure @tmproot if File.directory?(@tmproot) - end - - def test_version - assert_instance_of(String, DBM::VERSION) - end - - def test_reader_open_notexist - assert_raise(Errno::ENOENT) { - DBM.open("#{@tmproot}/a", 0666, DBM::READER) - } - end - - def test_writer_open_notexist - skip "dbm_open() is broken on libgdbm 1.8.0 or prior (#{DBM::VERSION})" if /GDBM version 1\.(?:[0-7]\b|8\.0)/ =~ DBM::VERSION - assert_raise(Errno::ENOENT) { - DBM.open("#{@tmproot}/a", 0666, DBM::WRITER) - } - end - - def test_wrcreat_open_notexist - v = DBM.open("#{@tmproot}/a", 0666, DBM::WRCREAT) - assert_instance_of(DBM, v) - v.close - end - - def test_newdb_open_notexist - v = DBM.open("#{@tmproot}/a", 0666, DBM::NEWDB) - assert_instance_of(DBM, v) - v.close - end - - def test_reader_open - DBM.open("#{@tmproot}/a") {} # create a db. - v = DBM.open("#{@tmproot}/a", nil, DBM::READER) {|d| - # Errno::EPERM is raised on Solaris which use ndbm. - # DBMError is raised on Debian which use gdbm. - assert_raise(Errno::EPERM, DBMError) { d["k"] = "v" } - true - } - assert(v) - end - - def test_newdb_open - DBM.open("#{@tmproot}/a") {|dbm| - dbm["k"] = "v" - } - v = DBM.open("#{@tmproot}/a", nil, DBM::NEWDB) {|d| - assert_equal(0, d.length) - assert_nil(d["k"]) - true - } - assert(v) - end - - def test_freeze - expected_error = defined?(FrozenError) ? FrozenError : RuntimeError - DBM.open("#{@tmproot}/a") {|d| - d.freeze - assert_raise(expected_error) { d["k"] = "v" } - } - end - end -end diff --git a/ruby/test/did_you_mean/core_ext/test_name_error_extension.rb b/ruby/test/did_you_mean/core_ext/test_name_error_extension.rb index 9dc08dbde..91871cda9 100644 --- a/ruby/test/did_you_mean/core_ext/test_name_error_extension.rb +++ b/ruby/test/did_you_mean/core_ext/test_name_error_extension.rb @@ -1,7 +1,7 @@ require_relative '../helper' class NameErrorExtensionTest < Test::Unit::TestCase - SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS + SPELL_CHECKERS = DidYouMean.spell_checkers class TestSpellChecker def initialize(*); end @@ -9,13 +9,14 @@ def corrections; ["does_exist"]; end end def setup - @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker + @original_spell_checker = DidYouMean.spell_checkers['NameError'] + DidYouMean.correct_error(NameError, TestSpellChecker) @error = assert_raise(NameError){ doesnt_exist } end def teardown - SPELL_CHECKERS['NameError'] = @org + DidYouMean.correct_error(NameError, @original_spell_checker) end def test_message diff --git a/ruby/test/did_you_mean/fixtures/book.rb b/ruby/test/did_you_mean/fixtures/book.rb index e6644a626..e31e629d4 100644 --- a/ruby/test/did_you_mean/fixtures/book.rb +++ b/ruby/test/did_you_mean/fixtures/book.rb @@ -1,4 +1,4 @@ class Book - class Cover + class Spine end end diff --git a/ruby/test/did_you_mean/helper.rb b/ruby/test/did_you_mean/helper.rb index d8aa41c3d..7cb7b1028 100644 --- a/ruby/test/did_you_mean/helper.rb +++ b/ruby/test/did_you_mean/helper.rb @@ -4,6 +4,10 @@ module DidYouMean module TestHelper class << self attr_reader :root + + def ractor_compatible? + defined?(Ractor) && RUBY_VERSION >= "3.1.0" + end end if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__)) diff --git a/ruby/test/did_you_mean/spell_checking/test_class_name_check.rb b/ruby/test/did_you_mean/spell_checking/test_class_name_check.rb index ffe7a4c31..1b863ee27 100644 --- a/ruby/test/did_you_mean/spell_checking/test_class_name_check.rb +++ b/ruby/test/did_you_mean/spell_checking/test_class_name_check.rb @@ -66,7 +66,9 @@ def test_corrections_should_work_from_within_instance_method_on_nested_class end def test_does_not_suggest_user_input - error = assert_raise(NameError) { ::Book::Cover } + Book.send(:remove_const, :Spine) if Book.constants.include?(:Spine) + + error = assert_raise(NameError) { ::Book::Spine } # This is a weird require, but in a multi-threaded condition, a constant may # be loaded between when a NameError occurred and when the spell checker diff --git a/ruby/test/did_you_mean/spell_checking/test_method_name_check.rb b/ruby/test/did_you_mean/spell_checking/test_method_name_check.rb index f3a6b1c7c..6e14e6acc 100644 --- a/ruby/test/did_you_mean/spell_checking/test_method_name_check.rb +++ b/ruby/test/did_you_mean/spell_checking/test_method_name_check.rb @@ -137,4 +137,11 @@ def test_suggests_yield assert_correction :yield, error.corrections assert_match "Did you mean? yield", error.to_s end + + def test_does_not_suggest_yield + error = assert_raise(NoMethodError) { 1.yeild } + + assert_correction [], error.corrections + assert_not_match(/Did you mean\? +yield/, error.to_s) + end if RUBY_ENGINE != "jruby" end diff --git a/ruby/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb b/ruby/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb new file mode 100644 index 000000000..2b0752a56 --- /dev/null +++ b/ruby/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb @@ -0,0 +1,20 @@ +require_relative '../helper' + +return if !defined?(::NoMatchingPatternKeyError) + +class PatternKeyNameCheckTest < Test::Unit::TestCase + include DidYouMean::TestHelper + + def test_corrects_hash_key_name_with_single_pattern_match + error = assert_raise(NoMatchingPatternKeyError) do + eval(<<~RUBY, binding, __FILE__, __LINE__) + hash = {foo: 1, bar: 2, baz: 3} + hash => {fooo:} + fooo = 1 # suppress "unused variable: fooo" warning + RUBY + end + + assert_correction ":foo", error.corrections + assert_match "Did you mean? :foo", error.to_s + end +end diff --git a/ruby/test/did_you_mean/spell_checking/test_require_path_check.rb b/ruby/test/did_you_mean/spell_checking/test_require_path_check.rb new file mode 100644 index 000000000..f67fab056 --- /dev/null +++ b/ruby/test/did_you_mean/spell_checking/test_require_path_check.rb @@ -0,0 +1,32 @@ +require_relative '../helper' + +return if !(RUBY_VERSION >= '2.8.0') + +class RequirePathCheckTest < Test::Unit::TestCase + include DidYouMean::TestHelper + + def test_load_error_from_require_has_suggestions + error = assert_raise LoadError do + require 'open_struct' + end + + assert_correction 'ostruct', error.corrections + assert_match "Did you mean? ostruct", error.to_s + end + + def test_load_error_from_require_for_nested_files_has_suggestions + error = assert_raise LoadError do + require 'net/htt' + end + + assert_correction 'net/http', error.corrections + assert_match "Did you mean? net/http", error.to_s + + error = assert_raise LoadError do + require 'net-http' + end + + assert_correction ['net/http', 'net/https'], error.corrections + assert_match "Did you mean? net/http", error.to_s + end +end diff --git a/ruby/test/did_you_mean/spell_checking/test_uncorrectable_name_check.rb b/ruby/test/did_you_mean/spell_checking/test_uncorrectable_name_check.rb index 5d934e5f7..9e83f6eb5 100644 --- a/ruby/test/did_you_mean/spell_checking/test_uncorrectable_name_check.rb +++ b/ruby/test/did_you_mean/spell_checking/test_uncorrectable_name_check.rb @@ -10,6 +10,6 @@ def setup end def test_message - assert_equal "Other name error", @error.message + assert_not_match(/Did you mean\?/, @error.message) end end diff --git a/ruby/test/did_you_mean/test_spell_checker.rb b/ruby/test/did_you_mean/test_spell_checker.rb index 98460b4d9..8445380de 100644 --- a/ruby/test/did_you_mean/test_spell_checker.rb +++ b/ruby/test/did_you_mean/test_spell_checker.rb @@ -10,6 +10,7 @@ def test_spell_checker_corrects_mistypes assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval'] assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!'] assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!'] + assert_spell 'Foo', input: 'FOo', dictionary: ['Foo', 'FOo'] assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!) assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!) diff --git a/ruby/test/did_you_mean/test_tree_spell_checker.rb b/ruby/test/did_you_mean/test_tree_spell_checker.rb index b61a491e2..9ab1c1bc9 100644 --- a/ruby/test/did_you_mean/test_tree_spell_checker.rb +++ b/ruby/test/did_you_mean/test_tree_spell_checker.rb @@ -1,11 +1,12 @@ -require 'set' -require 'yaml' +# frozen_string_literal: true -require_relative './helper' +require "yaml" + +require_relative "./helper" class TreeSpellCheckerTest < Test::Unit::TestCase - MINI_DIRECTORIES = YAML.load_file(File.expand_path('fixtures/mini_dir.yml', __dir__)) - RSPEC_DIRECTORIES = YAML.load_file(File.expand_path('fixtures/rspec_dir.yml', __dir__)) + MINI_DIRECTORIES = YAML.load_file(File.expand_path("fixtures/mini_dir.yml", __dir__)) + RSPEC_DIRECTORIES = YAML.load_file(File.expand_path("fixtures/rspec_dir.yml", __dir__)) def setup @dictionary = @@ -20,154 +21,150 @@ def setup spec/models/gfsga_spec.rb spec/controllers/vixen_controller_spec.rb ) - @test_str = 'spek/modeks/confirns/viken_spec.rb' - @tsp = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary) + @test_str = "spek/modeks/confirns/viken_spec.rb" + @tree_spell_checker = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary) end def test_corrupt_root - word = 'test/verbose_formatter_test.rb' - word_error = 'btets/cverbose_formatter_etst.rb suggestions' - tsp = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES) - s = tsp.correct(word_error).first - assert_match s, word + assert_tree_spell "test/verbose_formatter_test.rb", + input: "btets/cverbose_formatter_etst.rb suggestions", + dictionary: MINI_DIRECTORIES end def test_leafless_state - tsp = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary.push('spec/features')) - word = 'spec/modals/confirms/efgh_spec.rb' - word_error = 'spec/modals/confirXX/efgh_spec.rb' - s = tsp.correct(word_error).first - assert_equal s, word - s = tsp.correct('spec/featuresXX') - assert_equal 'spec/features', s.first + assert_tree_spell "spec/modals/confirms/efgh_spec.rb", + input: "spec/modals/confirXX/efgh_spec.rb", + dictionary: [*@dictionary, "spec/features"] + + assert_tree_spell "spec/features", + input: "spec/featuresXX", + dictionary: [*@dictionary, "spec/features"] end def test_rake_dictionary - dict = %w(parallel:prepare parallel:create parallel:rake parallel:migrate) - word_error = 'parallel:preprare' - tsp = DidYouMean::TreeSpellChecker.new(dictionary: dict, separator: ':') - s = tsp.correct(word_error).first - assert_match s, 'parallel:prepare' + assert_tree_spell "parallel:prepare", + input: "parallel:preprare", + dictionary: %w[parallel:prepare parallel:create parallel:rake parallel:migrate], + separator: ":" end def test_special_words_mini - tsp = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES) - special_words_mini.each do |word, word_error| - s = tsp.correct(word_error).first - assert_match s, word + [ + %w(test/fixtures/book.rb test/fixture/book.rb), + %w(test/edit_distance/jaro_winkler_test.rb test/edit_distace/jaro_winkler_test.rb), + %w(test/edit_distance/jaro_winkler_test.rb teste/dit_distane/jaro_winkler_test.rb), + %w(test/fixtures/book.rb test/fixturWes/book.rb), + %w(test/test_helper.rb tes!t/test_helper.rb), + %w(test/fixtures/book.rb test/hfixtures/book.rb), + %w(test/edit_distance/jaro_winkler_test.rb test/eidt_distance/jaro_winkler_test.@rb), + %w(test/spell_checker_test.rb test/spell_checke@r_test.rb), + %w(test/tree_spell_human_typo_test.rb testt/ree_spell_human_typo_test.rb), + %w(test/edit_distance/jaro_winkler_test.rb test/edit_distance/jaro_winkler_tuest.rb), + ].each do |expected, user_input| + assert_tree_spell expected, input: user_input, dictionary: MINI_DIRECTORIES end - end - def test_special_words_rspec - tsp = DidYouMean::TreeSpellChecker.new(dictionary: RSPEC_DIRECTORIES) - special_words_rspec.each do |word, word_error| - s = tsp.correct(word_error) - assert_match s.first, word - end - end - - def special_words_rspec [ - ['spec/rspec/core/formatters/exception_presenter_spec.rb','spec/rspec/core/formatters/eception_presenter_spec.rb'], - ['spec/rspec/core/ordering_spec.rb', 'spec/spec/core/odrering_spec.rb'], - ['spec/rspec/core/metadata_spec.rb', 'spec/rspec/core/metadata_spe.crb'], - ['spec/support/mathn_integration_support.rb', 'spec/support/mathn_itegrtion_support.rb'] - ] + %w(test/spell_checking/variable_name_check_test.rb test/spell_checking/vriabl_ename_check_test.rb), + %w(test/spell_checking/key_name_check_test.rb tesit/spell_checking/key_name_choeck_test.rb), + ].each do |expected, user_input| + assert_equal expected, DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct(user_input)[0] + end end - def special_words_mini + def test_special_words_rspec [ - ['test/fixtures/book.rb', 'test/fixture/book.rb'], - ['test/fixtures/book.rb', 'test/fixture/book.rb'], - ['test/edit_distance/jaro_winkler_test.rb', 'test/edit_distace/jaro_winkler_test.rb'], - ['test/edit_distance/jaro_winkler_test.rb', 'teste/dit_distane/jaro_winkler_test.rb'], - ['test/fixtures/book.rb', 'test/fixturWes/book.rb'], - ['test/test_helper.rb', 'tes!t/test_helper.rb'], - ['test/fixtures/book.rb', 'test/hfixtures/book.rb'], - ['test/edit_distance/jaro_winkler_test.rb', 'test/eidt_distance/jaro_winkler_test.@rb'], - ['test/spell_checker_test.rb', 'test/spell_checke@r_test.rb'], - ['test/tree_spell_human_typo_test.rb', 'testt/ree_spell_human_typo_test.rb'], - ['test/spell_checking/variable_name_check_test.rb', 'test/spell_checking/vriabl_ename_check_test.rb'], - ['test/spell_checking/key_name_check_test.rb', 'tesit/spell_checking/key_name_choeck_test.rb'], - ['test/edit_distance/jaro_winkler_test.rb', 'test/edit_distance/jaro_winkler_tuest.rb'] - ] + %w(spec/rspec/core/formatters/exception_presenter_spec.rb spec/rspec/core/formatters/eception_presenter_spec.rb), + %w(spec/rspec/core/metadata_spec.rb spec/rspec/core/metadata_spe.crb), + %w(spec/rspec/core/ordering_spec.rb spec/spec/core/odrering_spec.rb), + %w(spec/support/mathn_integration_support.rb spec/support/mathn_itegrtion_support.rb), + ].each do |expected, user_input| + assert_tree_spell expected, input: user_input, dictionary: RSPEC_DIRECTORIES + end end def test_file_in_root - word = 'test/spell_checker_test.rb' - word_error = 'test/spell_checker_test.r' - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error - assert_equal word, suggestions.first + assert_tree_spell "test/spell_checker_test.rb", input: "test/spell_checker_test.r", dictionary: MINI_DIRECTORIES end def test_no_plausible_states - word_error = 'testspell_checker_test.rb' - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error - assert_equal [], suggestions + assert_tree_spell [], input: "testspell_checker_test.rb", dictionary: MINI_DIRECTORIES end def test_no_plausible_states_with_augmentation - word_error = 'testspell_checker_test.rb' - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error - assert_equal [], suggestions - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct word_error - assert_equal 'test/spell_checker_test.rb', suggestions.first + assert_tree_spell [], input: "testspell_checker_test.rb", dictionary: MINI_DIRECTORIES + + suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct("testspell_checker_test.rb") + + assert_equal suggestions.first, "test/spell_checker_test.rb" end def test_no_idea_with_augmentation - word_error = 'test/spell_checking/key_name.rb' - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error - assert_equal [], suggestions - suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct word_error - assert_equal 'test/spell_checking/key_name_check_test.rb', suggestions.first + assert_tree_spell [], input: "test/spell_checking/key_name.rb", dictionary: MINI_DIRECTORIES + + suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct("test/spell_checking/key_name.rb") + + assert_equal suggestions.first, "test/spell_checking/key_name_check_test.rb" end def test_works_out_suggestions - exp = ['spec/models/concerns/vixen_spec.rb', - 'spec/models/concerns/vixenus_spec.rb'] - suggestions = @tsp.correct(@test_str) - assert_equal suggestions.to_set, exp.to_set + assert_tree_spell %w(spec/models/concerns/vixen_spec.rb spec/models/concerns/vixenus_spec.rb), + input: "spek/modeks/confirns/viken_spec.rb", + dictionary: %w(spec/models/concerns/vixen_spec.rb spec/models/concerns/vixenus_spec.rb) end def test_works_when_input_is_correct - correct_input = 'spec/models/concerns/vixenus_spec.rb' - suggestions = @tsp.correct correct_input - assert_equal suggestions.first, correct_input + assert_tree_spell "spec/models/concerns/vixenus_spec.rb", + input: "spec/models/concerns/vixenus_spec.rb", + dictionary: @dictionary end def test_find_out_leaves_in_a_path - path = 'spec/modals/confirms' - names = @tsp.send(:find_leaves, path) - assert_equal names.to_set, %w(abcd_spec.rb efgh_spec.rb).to_set + names = @tree_spell_checker.find_leaves("spec/modals/confirms") + + assert_equal %w[abcd_spec.rb efgh_spec.rb], names end def test_works_out_nodes - exp_paths = ['spec/models/concerns', - 'spec/models/confirms', - 'spec/modals/concerns', - 'spec/modals/confirms', - 'spec/controllers/concerns', - 'spec/controllers/confirms'].to_set - states = @tsp.send(:parse_dimensions) - nodes = states[0].product(*states[1..-1]) - paths = @tsp.send(:possible_paths, nodes) - assert_equal paths.to_set, exp_paths.to_set + exp_paths = ["spec/models/concerns", + "spec/models/confirms", + "spec/modals/concerns", + "spec/modals/confirms", + "spec/controllers/concerns", + "spec/controllers/confirms"] + + states = @tree_spell_checker.dimensions + nodes = states[0].product(*states[1..-1]) + paths = @tree_spell_checker.possible_paths(nodes) + + assert_equal paths, exp_paths end def test_works_out_state_space - suggestions = @tsp.send(:plausible_dimensions, @test_str) - assert_equal suggestions, [["spec"], ["models", "modals"], ["confirms", "concerns"]] + suggestions = @tree_spell_checker.plausible_dimensions(@test_str) + + assert_equal [["spec"], %w[models modals], %w[confirms concerns]], suggestions end def test_parses_dictionary - states = @tsp.send(:parse_dimensions) - assert_equal states, [["spec"], ["models", "modals", "controllers"], ["concerns", "confirms"]] + states = @tree_spell_checker.dimensions + + assert_equal [["spec"], %w[models modals controllers], %w[concerns confirms]], states end def test_parses_elementary_dictionary - dictionary = ['spec/models/user_spec.rb', 'spec/services/account_spec.rb'] - tsp = DidYouMean::TreeSpellChecker.new(dictionary: dictionary) - states = tsp.send(:parse_dimensions) - assert_equal states, [['spec'], ['models', 'services']] + dimensions = DidYouMean::TreeSpellChecker + .new(dictionary: %w(spec/models/user_spec.rb spec/services/account_spec.rb)) + .dimensions + + assert_equal [["spec"], %w[models services]], dimensions + end + + private + + def assert_tree_spell(expected, input:, dictionary:, separator: "/") + suggestions = DidYouMean::TreeSpellChecker.new(dictionary: dictionary, separator: separator).correct(input) + + assert_equal Array(expected), suggestions, "Expected to suggest #{expected}, but got #{suggestions.inspect}" end end diff --git a/ruby/test/did_you_mean/test_verbose_formatter.rb b/ruby/test/did_you_mean/test_verbose_formatter.rb deleted file mode 100644 index 6639d60a4..000000000 --- a/ruby/test/did_you_mean/test_verbose_formatter.rb +++ /dev/null @@ -1,21 +0,0 @@ -require_relative './helper' - -class VerboseFormatterTest < Test::Unit::TestCase - def setup - require_relative File.join(DidYouMean::TestHelper.root, 'verbose') - end - - def teardown - DidYouMean.formatter = DidYouMean::PlainFormatter.new - end - - def test_message - @error = assert_raise(NoMethodError){ 1.zeor? } - - assert_match <<~MESSAGE.strip, @error.message - undefined method `zeor?' for 1:Integer - - Did you mean? zero? - MESSAGE - end -end diff --git a/ruby/test/did_you_mean/tree_spell/human_typo.rb b/ruby/test/did_you_mean/tree_spell/human_typo.rb index 302d4d690..9d410a17c 100644 --- a/ruby/test/did_you_mean/tree_spell/human_typo.rb +++ b/ruby/test/did_you_mean/tree_spell/human_typo.rb @@ -4,6 +4,9 @@ module TreeSpell # Simulate an error prone human typist # see doc/human_typo_api.md for the api description class HumanTypo + POPULAR_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?<>,.!`+=-_":;@#$%^&*()'.split("").freeze + ACTION_TYPES = %i(insert transpose delete substitute).freeze + def initialize(input, lambda: 0.05) @input = input check_input @@ -15,7 +18,7 @@ def call @word = input.dup i_place = initialize_i_place loop do - action = action_type + action = ACTION_TYPES.sample @word = make_change action, i_place @len = word.length i_place += exponential @@ -41,40 +44,17 @@ def exponential (rand / (lambda / 2)).to_i end - def rand_char - popular_chars = alphabetic_characters + special_characters - n = popular_chars.length - popular_chars[rand(n)] - end - - def alphabetic_characters - ('a'..'z').to_a.join + ('A'..'Z').to_a.join - end - - def special_characters - '?<>,.!`+=-_":;@#$%^&*()' - end - - def toss - return +1 if rand >= 0.5 - -1 - end - - def action_type - [:insert, :transpose, :delete, :substitute][rand(4)] - end - def make_change(action, i_place) cw = ChangeWord.new(word) case action when :delete cw.deletion(i_place) when :insert - cw.insertion(i_place, rand_char) + cw.insertion(i_place, POPULAR_CHARS.sample) when :substitute - cw.substitution(i_place, rand_char) + cw.substitution(i_place, POPULAR_CHARS.sample) when :transpose - cw.transposition(i_place, toss) + cw.transposition(i_place, rand >= 0.5 ? +1 : -1) end end diff --git a/ruby/test/did_you_mean/tree_spell/test_change_word.rb b/ruby/test/did_you_mean/tree_spell/test_change_word.rb index 613e11b86..7855b3de5 100644 --- a/ruby/test/did_you_mean/tree_spell/test_change_word.rb +++ b/ruby/test/did_you_mean/tree_spell/test_change_word.rb @@ -8,7 +8,7 @@ def setup @len = @input.length end - def test_deleletion + def test_deletion assert_match @cw.deletion(5), 'spec/ervices/anything_spec' assert_match @cw.deletion(@len - 1), 'spec/services/anything_spe' assert_match @cw.deletion(0), 'pec/services/anything_spec' diff --git a/ruby/test/digest/test_digest.rb b/ruby/test/digest/test_digest.rb index 4cae45507..c9b2c6805 100644 --- a/ruby/test/digest/test_digest.rb +++ b/ruby/test/digest/test_digest.rb @@ -247,10 +247,10 @@ def test_no_lib_no_def end def test_race - assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;') + assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;") assert_nothing_raised { t = Thread.start { - sleep 0.1 + sleep #{ EnvUtil.apply_timeout_scale(0.1) } Digest(:Foo).new } Digest(:Foo).new @@ -260,10 +260,10 @@ def test_race end def test_race_mixed - assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;') + assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;") assert_nothing_raised { t = Thread.start { - sleep 0.1 + sleep #{ EnvUtil.apply_timeout_scale(0.1) } Thread.current.report_on_exception = false Digest::Foo.new } diff --git a/ruby/test/digest/test_ractor.rb b/ruby/test/digest/test_ractor.rb new file mode 100644 index 000000000..0dbdcb9c8 --- /dev/null +++ b/ruby/test/digest/test_ractor.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true +require 'test/unit' + +require 'digest' +%w[digest/md5 digest/rmd160 digest/sha1 digest/sha2 digest/bubblebabble].each do |lib| + begin + require lib + rescue LoadError + end +end + +module TestDigestRactor + Data1 = "abc" + Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + + def setup + pend unless defined?(Ractor) + end + + def test_s_hexdigest + assert_in_out_err([], <<-"end;", ["true", "true"], []) + $VERBOSE = nil + require "digest" + require "#{self.class::LIB}" + DATA = #{self.class::DATA.inspect} + rs = DATA.map do |str, hexdigest| + r = Ractor.new str do |x| + #{self.class::ALGO}.hexdigest(x) + end + [r, hexdigest] + end + rs.each do |r, hexdigest| + puts r.take == hexdigest + end + end; + end + + class TestMD5Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/md5" + ALGO = Digest::MD5 + DATA = { + Data1 => "900150983cd24fb0d6963f7d28e17f72", + Data2 => "8215ef0796a20bcaaae116d3876c664a", + } + end if defined?(Digest::MD5) + + class TestSHA1Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/sha1" + ALGO = Digest::SHA1 + DATA = { + Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d", + Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1", + } + end if defined?(Digest::SHA1) + + class TestSHA256Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/sha2" + ALGO = Digest::SHA256 + DATA = { + Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + } + end if defined?(Digest::SHA256) + + class TestSHA384Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/sha2" + ALGO = Digest::SHA384 + DATA = { + Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"\ + "8086072ba1e7cc2358baeca134c825a7", + Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6"\ + "b0455a8520bc4e6f5fe95b1fe3c8452b", + } + end if defined?(Digest::SHA384) + + class TestSHA512Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/sha2" + ALGO = Digest::SHA512 + DATA = { + Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"\ + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"\ + "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", + } + end if defined?(Digest::SHA512) + + class TestRMD160Ractor < Test::Unit::TestCase + include TestDigestRactor + LIB = "digest/rmd160" + ALGO = Digest::RMD160 + DATA = { + Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", + Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b", + } + end if defined?(Digest::RMD160) +end diff --git a/ruby/test/drb/drbtest.rb b/ruby/test/drb/drbtest.rb index a8363b0c4..3c33aedb6 100644 --- a/ruby/test/drb/drbtest.rb +++ b/ruby/test/drb/drbtest.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require 'test/unit' +require 'envutil' require 'drb/drb' require 'drb/extservm' require 'timeout' @@ -213,8 +214,9 @@ def test_05_eq end def test_06_timeout - skip if RUBY_PLATFORM.include?("armv7l-linux") - skip if RUBY_PLATFORM.include?("sparc-solaris2.10") + omit if RUBY_PLATFORM.include?("armv7l-linux") + omit if RUBY_PLATFORM.include?("sparc-solaris2.10") + omit if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # expecting a certain delay is difficult for --jit-wait CI Timeout.timeout(60) do ten = Onecky.new(10) assert_raise(Timeout::Error) do diff --git a/ruby/test/drb/test_drb.rb b/ruby/test/drb/test_drb.rb index 47b2966ae..1ee1b265d 100644 --- a/ruby/test/drb/test_drb.rb +++ b/ruby/test/drb/test_drb.rb @@ -323,7 +323,7 @@ class BO < BasicObject end def test_any_to_s - server = DRb::DRbServer.new('druby://:0') + server = DRb::DRbServer.new('druby://localhost:0') server.singleton_class.send(:public, :any_to_s) assert_equal("foo:String", server.any_to_s("foo")) assert_match(/\A#\z/, server.any_to_s(BO.new)) @@ -335,14 +335,16 @@ def test_any_to_s class TestDRbTCP < Test::Unit::TestCase def test_immediate_close - server = DRb::DRbServer.new('druby://:0') + server = DRb::DRbServer.new('druby://localhost:0') host, port, = DRb::DRbTCPSocket.send(:parse_uri, server.uri) socket = TCPSocket.open host, port socket.shutdown socket.close client = DRb::DRbTCPSocket.new(server.uri, socket) assert client - client.close + ensure + client&.close + socket&.close server.stop_service server.thread.join DRb::DRbConn.stop_pool diff --git a/ruby/test/drb/test_drbssl.rb b/ruby/test/drb/test_drbssl.rb index 8ab010e1c..0254c7ab5 100644 --- a/ruby/test/drb/test_drbssl.rb +++ b/ruby/test/drb/test_drbssl.rb @@ -34,7 +34,7 @@ def start [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ] end - @server = DRb::DRbServer.new('drbssl://:0', manager, config) + @server = DRb::DRbServer.new('drbssl://localhost:0', manager, config) end end @@ -59,6 +59,7 @@ def test_05_eq class TestDRbSSLAry < Test::Unit::TestCase include DRbAry def setup + LeakChecker.skip if defined?(LeakChecker) @drb_service = DRbSSLService.new super setup_service 'ut_array_drbssl.rb' diff --git a/ruby/test/drb/ut_drb.rb b/ruby/test/drb/ut_drb.rb index e7bd2dff7..7c0603b00 100644 --- a/ruby/test/drb/ut_drb.rb +++ b/ruby/test/drb/ut_drb.rb @@ -69,7 +69,7 @@ def foo; 1 end private def priv; 3; end end def basic_object - BO.new + @basic_object = BO.new end def unknown_class diff --git a/ruby/test/erb/test_erb.rb b/ruby/test/erb/test_erb.rb index d3e9b6c94..fb5e9b611 100644 --- a/ruby/test/erb/test_erb.rb +++ b/ruby/test/erb/test_erb.rb @@ -663,26 +663,20 @@ def test_half_working_comment_backward_compatibility # [deprecated] These interfaces will be removed later def test_deprecated_interface_warnings - [nil, 0].each do |safe| - assert_warning(/2nd argument of ERB.new is deprecated/) do - ERB.new('', safe) - end - end - - [1, 2].each do |safe| + [nil, 0, 1, 2].each do |safe| assert_warn(/2nd argument of ERB.new is deprecated/) do ERB.new('', safe) end end [nil, '', '%', '%<>'].each do |trim| - assert_warning(/3rd argument of ERB.new is deprecated/) do + assert_warn(/3rd argument of ERB.new is deprecated/) do ERB.new('', nil, trim) end end [nil, '_erbout', '_hamlout'].each do |eoutvar| - assert_warning(/4th argument of ERB.new is deprecated/) do + assert_warn(/4th argument of ERB.new is deprecated/) do ERB.new('', nil, nil, eoutvar) end end diff --git a/ruby/test/erb/test_erb_command.rb b/ruby/test/erb/test_erb_command.rb index ed13c29c9..0baa59ddd 100644 --- a/ruby/test/erb/test_erb_command.rb +++ b/ruby/test/erb/test_erb_command.rb @@ -4,15 +4,15 @@ class TestErbCommand < Test::Unit::TestCase def test_var - assert_in_out_err(["-w", - File.expand_path("../../../bin/erb", __FILE__), + assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w", + File.expand_path("../../libexec/erb", __dir__), "var=hoge"], "<%=var%>", ["hoge"]) end def test_template_file_encoding - assert_in_out_err(["-w", - File.expand_path("../../../bin/erb", __FILE__)], + assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w", + File.expand_path("../../libexec/erb", __dir__)], "<%=''.encoding.to_s%>", ["UTF-8"]) end @@ -20,10 +20,10 @@ def test_template_file_encoding def test_deprecated_option warnings = [ "warning: -S option of erb command is deprecated. Please do not use this.", - /\n.+\/bin\/erb:\d+: warning: Passing safe_level with the 2nd argument of ERB\.new is deprecated\. Do not use it, and specify other arguments as keyword arguments\.\n/, + /\n.+\/libexec\/erb:\d+: warning: Passing safe_level with the 2nd argument of ERB\.new is deprecated\. Do not use it, and specify other arguments as keyword arguments\.\n/, ] - assert_in_out_err(["-w", - File.expand_path("../../../bin/erb", __FILE__), + assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w", + File.expand_path("../../libexec/erb", __dir__), "-S", "0"], "hoge", ["hoge"], warnings) end diff --git a/ruby/test/error_highlight/test_error_highlight.rb b/ruby/test/error_highlight/test_error_highlight.rb new file mode 100644 index 000000000..08036bca5 --- /dev/null +++ b/ruby/test/error_highlight/test_error_highlight.rb @@ -0,0 +1,1197 @@ +require "test/unit" + +require "error_highlight" +require "tempfile" + +class ErrorHighlightTest < Test::Unit::TestCase + class DummyFormatter + def self.message_for(corrections) + "" + end + end + + def setup + if defined?(DidYouMean) + @did_you_mean_old_formatter = DidYouMean.formatter + DidYouMean.formatter = DummyFormatter + end + end + + def teardown + if defined?(DidYouMean) + DidYouMean.formatter = @did_you_mean_old_formatter + end + end + + def assert_error_message(klass, expected_msg, &blk) + err = assert_raise(klass, &blk) + assert_equal(expected_msg.chomp, err.message) + end + + def test_CALL_noarg_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.foo + 1 + ^^^^ + END + + nil.foo + 1 + end + end + + def test_CALL_noarg_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + .foo + 1 + ^^^^ + END + + nil + .foo + 1 + end + end + + def test_CALL_noarg_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo + 1 + ^^^ + END + + nil. + foo + 1 + end + end + + def test_CALL_noarg_4 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + (nil).foo + 1 + ^^^^ + END + + (nil).foo + 1 + end + end + + def test_CALL_arg_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.foo (42) + ^^^^ + END + + nil.foo (42) + end + end + + def test_CALL_arg_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + .foo ( + ^^^^ + END + + nil + .foo ( + 42 + ) + end + end + + def test_CALL_arg_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo ( + ^^^ + END + + nil. + foo ( + 42 + ) + end + end + + def test_CALL_arg_4 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.foo(42) + ^^^^ + END + + nil.foo(42) + end + end + + def test_CALL_arg_5 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + .foo( + ^^^^ + END + + nil + .foo( + 42 + ) + end + end + + def test_CALL_arg_6 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + foo( + ^^^ + END + + nil. + foo( + 42 + ) + end + end + + def test_QCALL_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for 1:Integer + + 1&.foo + ^^^^^ + END + + 1&.foo + end + end + + def test_QCALL_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for 1:Integer + + 1&.foo(42) + ^^^^^ + END + + 1&.foo(42) + end + end + + def test_CALL_aref_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + nil [ ] + ^^^ + END + + nil [ ] + end + end + + def test_CALL_aref_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + nil [0] + ^^^ + END + + nil [0] + end + end + + def test_CALL_aref_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + END + + nil [ + 0 + ] + end + end + + def test_CALL_aref_4 + v = Object.new + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for #{ v.inspect } + + v &.[](0) + ^^^^ + END + + v &.[](0) + end + end + + def test_CALL_aref_5 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + (nil)[ ] + ^^^ + END + + (nil)[ ] + end + end + + def test_CALL_aset + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + nil.[]= + ^^^^ + END + + nil.[]= + end + end + + def test_CALL_op_asgn + v = nil + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v += 42 + ^ + END + + v += 42 + end + end + + def test_CALL_special_call_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `call' for nil:NilClass + END + + nil.() + end + end + + def test_CALL_special_call_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `call' for nil:NilClass + END + + nil.(42) + end + end + + def test_CALL_send + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.send(:foo, 42) + ^^^^^ + END + + nil.send(:foo, 42) + end + end + + def test_ATTRASGN_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + nil [ ] = 42 + ^^^^^ + END + + nil [ ] = 42 + end + end + + def test_ATTRASGN_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + nil [0] = 42 + ^^^^^ + END + + nil [0] = 42 + end + end + + def test_ATTRASGN_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for nil:NilClass + + nil.foo = 42 + ^^^^^^ + END + + nil.foo = 42 + end + end + + def test_ATTRASGN_4 + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for nil:NilClass + + (nil)[0] = 42 + ^^^^^ + END + + (nil)[0] = 42 + end + end + + def test_ATTRASGN_5 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for nil:NilClass + + (nil).foo = 42 + ^^^^^^ + END + + (nil).foo = 42 + end + end + + def test_OPCALL_binary_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + nil + 42 + ^ + END + + nil + 42 + end + end + + def test_OPCALL_binary_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + nil + # comment + ^ + END + + nil + # comment + 42 + end + end + + def test_OPCALL_binary_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + (nil) + 42 + ^ + END + + (nil) + 42 + end + end + + def test_OPCALL_unary_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `+@' for nil:NilClass + + + nil + ^ + END + + + nil + end + end + + def test_OPCALL_unary_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `+@' for nil:NilClass + + +(nil) + ^ + END + + +(nil) + end + end + + def test_FCALL_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.instance_eval { foo() } + ^^^ + END + + nil.instance_eval { foo() } + end + end + + def test_FCALL_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + nil.instance_eval { foo(42) } + ^^^ + END + + nil.instance_eval { foo(42) } + end + end + + def test_VCALL_2 + assert_error_message(NameError, <<~END) do +undefined local variable or method `foo' for nil:NilClass + + nil.instance_eval { foo } + ^^^ + END + + nil.instance_eval { foo } + end + end + + def test_OP_ASGN1_aref_1 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + v [0] += 42 + ^^^ + END + + v [0] += 42 + end + end + + def test_OP_ASGN1_aref_2 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + v [0] += # comment + ^^^ + END + + v [0] += # comment + 42 + end + end + + def test_OP_ASGN1_aref_3 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + END + + v [ + 0 + ] += # comment + 42 + end + end + + def test_OP_ASGN1_aref_4 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]' for nil:NilClass + + (v)[0] += 42 + ^^^ + END + + (v)[0] += 42 + end + end + + def test_OP_ASGN1_op_1 + v = Object.new + def v.[](x); nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v [0] += 42 + ^ + END + + v [0] += 42 + end + end + + def test_OP_ASGN1_op_2 + v = Object.new + def v.[](x); nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v [0 ] += # comment + ^ + END + + v [0 ] += # comment + 42 + end + end + + def test_OP_ASGN1_op_3 + v = Object.new + def v.[](x); nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + END + + v [ + 0 + ] += + 42 + end + end + + def test_OP_ASGN1_op_4 + v = Object.new + def v.[](x); nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + (v)[0] += 42 + ^ + END + + (v)[0] += 42 + end + end + + def test_OP_ASGN1_aset_1 + v = Object.new + def v.[](x); 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for #{ v.inspect } + + v [0] += 42 + ^^^^^^ + END + + v [0] += 42 + end + end + + def test_OP_ASGN1_aset_2 + v = Object.new + def v.[](x); 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for #{ v.inspect } + + v [0] += # comment + ^^^^^^ + END + + v [0] += # comment + 42 + end + end + + def test_OP_ASGN1_aset_3 + v = Object.new + def v.[](x); 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for #{ v.inspect } + END + + v [ + 0 + ] += + 42 + end + end + + def test_OP_ASGN1_aset_4 + v = Object.new + def v.[](x); 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `[]=' for #{ v.inspect } + + (v)[0] += 42 + ^^^^^^ + END + + (v)[0] += 42 + end + end + + def test_OP_ASGN2_read_1 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + v.foo += 42 + ^^^^ + END + + v.foo += 42 + end + end + + def test_OP_ASGN2_read_2 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + v.foo += # comment + ^^^^ + END + + v.foo += # comment + 42 + end + end + + def test_OP_ASGN2_read_3 + v = nil + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo' for nil:NilClass + + (v).foo += 42 + ^^^^ + END + + (v).foo += 42 + end + end + + def test_OP_ASGN2_op_1 + v = Object.new + def v.foo; nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v.foo += 42 + ^ + END + + v.foo += 42 + end + end + + def test_OP_ASGN2_op_2 + v = Object.new + def v.foo; nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + v.foo += # comment + ^ + END + + v.foo += # comment + 42 + end + end + + def test_OP_ASGN2_op_3 + v = Object.new + def v.foo; nil; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + (v).foo += 42 + ^ + END + + (v).foo += 42 + end + end + + def test_OP_ASGN2_write_1 + v = Object.new + def v.foo; 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for #{ v.inspect } + + v.foo += 42 + ^^^^^^^ + END + + v.foo += 42 + end + end + + def test_OP_ASGN2_write_2 + v = Object.new + def v.foo; 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for #{ v.inspect } + + v.foo += # comment + ^^^^^^^ + END + + v.foo += # comment + 42 + end + end + + def test_OP_ASGN2_write_3 + v = Object.new + def v.foo; 1; end + + assert_error_message(NoMethodError, <<~END) do +undefined method `foo=' for #{ v.inspect } + + (v).foo += 42 + ^^^^^^^ + END + + (v).foo += 42 + end + end + + def test_CONST + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::NotDefined + + 1 + NotDefined + 1 + ^^^^^^^^^^ + END + + 1 + NotDefined + 1 + end + end + + def test_COLON2_1 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::NotDefined + + ErrorHighlightTest::NotDefined + ^^^^^^^^^^^^ + END + + ErrorHighlightTest::NotDefined + end + end + + def test_COLON2_2 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::NotDefined + + NotDefined + ^^^^^^^^^^ + END + + ErrorHighlightTest:: + NotDefined + end + end + + def test_COLON3 + assert_error_message(NameError, <<~END) do +uninitialized constant NotDefined + + ::NotDefined + ^^^^^^^^^^^^ + END + + ::NotDefined + end + end + + module OP_CDECL_TEST + Nil = nil + end + + def test_OP_CDECL_read_1 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined + + OP_CDECL_TEST::NotDefined += 1 + ^^^^^^^^^^^^ + END + + OP_CDECL_TEST::NotDefined += 1 + end + end + + def test_OP_CDECL_read_2 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined + + OP_CDECL_TEST::NotDefined += # comment + ^^^^^^^^^^^^ + END + + OP_CDECL_TEST::NotDefined += # comment + 1 + end + end + + def test_OP_CDECL_read_3 + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined + END + + OP_CDECL_TEST:: + NotDefined += 1 + end + end + + def test_OP_CDECL_op_1 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + OP_CDECL_TEST::Nil += 1 + ^ + END + + OP_CDECL_TEST::Nil += 1 + end + end + + def test_OP_CDECL_op_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + OP_CDECL_TEST::Nil += # comment + ^ + END + + OP_CDECL_TEST::Nil += # comment + 1 + end + end + + def test_OP_CDECL_op_3 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for nil:NilClass + + Nil += 1 + ^ + END + + OP_CDECL_TEST:: + Nil += 1 + end + end + + def test_OP_CDECL_toplevel_1 + assert_error_message(NameError, <<~END) do +uninitialized constant NotDefined + + ::NotDefined += 1 + ^^^^^^^^^^^^ + END + + ::NotDefined += 1 + end + end + + def test_OP_CDECL_toplevel_2 + assert_error_message(NoMethodError, <<~END) do +undefined method `+' for ErrorHighlightTest:Class + + ::ErrorHighlightTest += 1 + ^ + END + + ::ErrorHighlightTest += 1 + end + end + + def test_explicit_raise_name_error + assert_error_message(NameError, <<~END) do +NameError + + raise NameError + ^^^^^ + END + + raise NameError + end + end + + def test_explicit_raise_no_method_error + assert_error_message(NoMethodError, <<~END) do +NoMethodError + + raise NoMethodError + ^^^^^ + END + + raise NoMethodError + end + end + + def test_const_get + assert_error_message(NameError, <<~END) do +uninitialized constant ErrorHighlightTest::NotDefined + + ErrorHighlightTest.const_get(:NotDefined) + ^^^^^^^^^^ + END + + ErrorHighlightTest.const_get(:NotDefined) + end + end + + def test_local_variable_get + b = binding + assert_error_message(NameError, <<~END) do +local variable `foo' is not defined for #{ b.inspect } + + b.local_variable_get(:foo) + ^^^^^^^^^^^^^^^^^^^ + END + + b.local_variable_get(:foo) + end + end + + def test_multibyte + assert_error_message(NoMethodError, <<~END) do +undefined method `ã‚ã„ã†ãˆãŠ' for nil:NilClass + END + + nil.ã‚ã„ã†ãˆãŠ + end + end + + if false + + def test_args_CALL_1 + assert_error_message(TypeError, <<~END) do +nil can't be coerced into Integer + + 1.+(nil) + ^^^ + END + + 1.+(nil) + end + end + + def test_args_CALL_2 + v = [] + assert_error_message(TypeError, <<~END) do +no implicit conversion from nil to integer + + v[nil] + ^^^ + END + + v[nil] + end + end + + def test_args_ATTRASGN_1 + v = [] + assert_error_message(ArgumentError, <<~END) do +wrong number of arguments (given 1, expected 2..3) + + v [ ] = 1 + ^^^^^^ + END + + v [ ] = 1 + end + end + + def test_args_ATTRASGN_2 + v = [] + assert_error_message(TypeError, <<~END) do +no implicit conversion from nil to integer + + v [nil] = 1 + ^^^^^^^^ + END + + v [nil] = 1 + end + end + + def test_args_ATTRASGN_3 + assert_error_message(TypeError, <<~END) do +no implicit conversion of String into Integer + + $stdin.lineno = "str" + ^^^^^ + END + + $stdin.lineno = "str" + end + end + + def test_args_OPCALL + assert_error_message(TypeError, <<~END) do +nil can't be coerced into Integer + + 1 + nil + ^^^ + END + + 1 + nil + end + end + + def test_args_FCALL_1 + assert_error_message(TypeError, <<~END) do +no implicit conversion of Symbol into String + + "str".instance_eval { gsub("foo", :sym) } + ^^^^^^^^^^^ + END + + "str".instance_eval { gsub("foo", :sym) } + end + end + + def test_args_FCALL_2 + assert_error_message(TypeError, <<~END) do +no implicit conversion of Symbol into String + + "str".instance_eval { gsub "foo", :sym } + ^^^^^^^^^^^ + END + + "str".instance_eval { gsub "foo", :sym } + end + end + + def test_args_OP_ASGN1_aref_1 + v = [] + + assert_error_message(TypeError, <<~END) do +no implicit conversion from nil to integer + + v [nil] += 42 + ^^^^^^^^^^ + END + + v [nil] += 42 + end + end + + def test_args_OP_ASGN1_aref_2 + v = [] + + assert_error_message(ArgumentError, <<~END) do +wrong number of arguments (given 0, expected 1..2) + + v [ ] += 42 + ^^^^^^^^ + END + + v [ ] += 42 + end + end + + def test_args_OP_ASGN1_op + v = [1] + + assert_error_message(TypeError, <<~END) do +nil can't be coerced into Integer + + v [0] += nil + ^^^^^^^^^ + END + + v [0] += nil + end + end + + def test_args_OP_ASGN2 + v = Object.new + def v.foo; 1; end + + assert_error_message(TypeError, <<~END) do +nil can't be coerced into Integer + + v.foo += nil + ^^^ + END + + v.foo += nil + end + end + + end + + def test_custom_formatter + custom_formatter = Object.new + def custom_formatter.message_for(spot) + "\n\n" + spot.inspect + end + + original_formatter, ErrorHighlight.formatter = ErrorHighlight.formatter, custom_formatter + + assert_error_message(NoMethodError, <<~END) do +undefined method `time' for 1:Integer + +{:first_lineno=>#{ __LINE__ + 3 }, :first_column=>7, :last_lineno=>#{ __LINE__ + 3 }, :last_column=>12, :snippet=>" 1.time {}\\n"} + END + + 1.time {} + end + + ensure + ErrorHighlight.formatter = original_formatter + end + + def test_hard_tabs + Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp| + tmp << "\t \t1.time {}\n" + tmp.close + + assert_error_message(NoMethodError, <<~END.gsub("_", "\t")) do +undefined method `time' for 1:Integer + +_ _1.time {} +_ _ ^^^^^ + END + + load tmp.path + end + end + end + + def test_no_final_newline + Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp| + tmp << "1.time {}" + tmp.close + + assert_error_message(NoMethodError, <<~END) do +undefined method `time' for 1:Integer + +1.time {} + ^^^^^ + END + + load tmp.path + end + end + end +end diff --git a/ruby/test/etc/test_etc.rb b/ruby/test/etc/test_etc.rb index 365c27021..2eddcf49d 100644 --- a/ruby/test/etc/test_etc.rb +++ b/ruby/test/etc/test_etc.rb @@ -44,7 +44,7 @@ def test_getpwuid unless s.empty? assert_include(s, Etc.getpwuid) end - end + end unless RUBY_PLATFORM.include?("android") def test_getpwnam passwd = {} @@ -54,7 +54,7 @@ def test_getpwnam passwd.each_value do |s| assert_equal(s, Etc.getpwnam(s.name)) end - end + end unless RUBY_PLATFORM.include?("android") def test_passwd_with_low_level_api a = [] @@ -169,4 +169,28 @@ def test_nprocessors assert_operator(1, :<=, n) end + def test_ractor + return unless Etc.passwd # => skip test if no platform support + Etc.endpwent + + assert_ractor(<<~RUBY, require: 'etc') + ractor = Ractor.new do + Etc.passwd do |s| + Ractor.yield :sync + Ractor.yield s.name + break :done + end + end + ractor.take # => :sync + assert_raise RuntimeError, /parallel/ do + Etc.passwd {} + end + name = ractor.take # => first name + ractor.take # => :done + name2 = Etc.passwd do |s| + break s.name + end + assert_equal(name2, name) + RUBY + end end diff --git a/ruby/test/excludes/TestArray.rb b/ruby/test/excludes/TestArray.rb new file mode 100644 index 000000000..73da27200 --- /dev/null +++ b/ruby/test/excludes/TestArray.rb @@ -0,0 +1 @@ +exclude(:test_shared_marking, "The target code has already been changed") diff --git a/ruby/test/fiber/http.rb b/ruby/test/fiber/http.rb new file mode 100644 index 000000000..53a4602bd --- /dev/null +++ b/ruby/test/fiber/http.rb @@ -0,0 +1,54 @@ + +require 'benchmark' + +TOPICS = ["cats", "dogs", "pigs", "skeletons", "zombies", "ocelots", "villagers", "pillagers"] + +require 'net/http' +require 'uri' +require 'json' + +require_relative 'scheduler' + +def fetch_topics(topics) + responses = {} + + topics.each do |topic| + Fiber.new(blocking: Fiber.current.blocking?) do + uri = URI("https://www.google.com/search?q=#{topic}") + response = Net::HTTP.get(uri) + responses[topic] = response.scan(topic).size + end.resume + end + + Fiber.scheduler&.run + + return responses +end + +def sweep(repeats: 3, **options) + times = (1..8).map do |i| + $stderr.puts "Measuring #{i} topic(s) #{options.inspect}..." + topics = TOPICS[0...i] + + Thread.new do + Benchmark.realtime do + scheduler = Scheduler.new + Fiber.set_scheduler(scheduler) + + repeats.times do + Fiber.new(**options) do + pp fetch_topics(topics) + end.resume + + scheduler.run + end + end + end.value / repeats + end + + puts options.inspect + puts JSON.dump(times.map{|value| value.round(3)}) +end + +# sweep(blocking: true) +sweep(blocking: false) diff --git a/ruby/test/fiber/scheduler.rb b/ruby/test/fiber/scheduler.rb new file mode 100644 index 000000000..4138015e4 --- /dev/null +++ b/ruby/test/fiber/scheduler.rb @@ -0,0 +1,358 @@ +# frozen_string_literal: true + +# This is an example and simplified scheduler for test purposes. +# It is not efficient for a large number of file descriptors as it uses IO.select(). +# Production Fiber schedulers should use epoll/kqueue/etc. + +require 'fiber' +require 'socket' + +begin + require 'io/nonblock' +rescue LoadError + # Ignore. +end + +class Scheduler + experimental = Warning[:experimental] + begin + Warning[:experimental] = false + IO::Buffer.new(0) + ensure + Warning[:experimental] = experimental + end + + def initialize + @readable = {} + @writable = {} + @waiting = {} + + @closed = false + + @lock = Thread::Mutex.new + @blocking = 0 + @ready = [] + + @urgent = IO.pipe + end + + attr :readable + attr :writable + attr :waiting + + def next_timeout + _fiber, timeout = @waiting.min_by{|key, value| value} + + if timeout + offset = timeout - current_time + + if offset < 0 + return 0 + else + return offset + end + end + end + + def run + # $stderr.puts [__method__, Fiber.current].inspect + + while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? + # Can only handle file descriptors up to 1024... + readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout) + + # puts "readable: #{readable}" if readable&.any? + # puts "writable: #{writable}" if writable&.any? + + selected = {} + + readable&.each do |io| + if fiber = @readable.delete(io) + @writable.delete(io) if @writable[io] == fiber + selected[fiber] = IO::READABLE + elsif io == @urgent.first + @urgent.first.read_nonblock(1024) + end + end + + writable&.each do |io| + if fiber = @writable.delete(io) + @readable.delete(io) if @readable[io] == fiber + selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE + end + end + + selected.each do |fiber, events| + fiber.resume(events) + end + + if @waiting.any? + time = current_time + waiting, @waiting = @waiting, {} + + waiting.each do |fiber, timeout| + if fiber.alive? + if timeout <= time + fiber.resume + else + @waiting[fiber] = timeout + end + end + end + end + + if @ready.any? + ready = nil + + @lock.synchronize do + ready, @ready = @ready, [] + end + + ready.each do |fiber| + fiber.resume + end + end + end + end + + def scheduler_close + close(true) + end + + def close(internal = false) + # $stderr.puts [__method__, Fiber.current].inspect + + unless internal + if Fiber.scheduler == self + return Fiber.set_scheduler(nil) + end + end + + if @closed + raise "Scheduler already closed!" + end + + self.run + ensure + if @urgent + @urgent.each(&:close) + @urgent = nil + end + + @closed ||= true + + # We freeze to detect any unintended modifications after the scheduler is closed: + self.freeze + end + + def closed? + @closed + end + + def current_time + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + + def timeout_after(duration, klass, message, &block) + fiber = Fiber.current + + self.fiber do + sleep(duration) + + if fiber&.alive? + fiber.raise(klass, message) + end + end + + begin + yield(duration) + ensure + fiber = nil + end + end + + def process_wait(pid, flags) + # $stderr.puts [__method__, pid, flags, Fiber.current].inspect + + # This is a very simple way to implement a non-blocking wait: + Thread.new do + Process::Status.wait(pid, flags) + end.value + end + + def io_wait(io, events, duration) + # $stderr.puts [__method__, io, events, duration, Fiber.current].inspect + + unless (events & IO::READABLE).zero? + @readable[io] = Fiber.current + end + + unless (events & IO::WRITABLE).zero? + @writable[io] = Fiber.current + end + + Fiber.yield + ensure + @readable.delete(io) + @writable.delete(io) + end + + # Used for Kernel#sleep and Thread::Mutex#sleep + def kernel_sleep(duration = nil) + # $stderr.puts [__method__, duration, Fiber.current].inspect + + self.block(:sleep, duration) + + return true + end + + # Used when blocking on synchronization (Thread::Mutex#lock, + # Thread::Queue#pop, Thread::SizedQueue#push, ...) + def block(blocker, timeout = nil) + # $stderr.puts [__method__, blocker, timeout].inspect + + if timeout + @waiting[Fiber.current] = current_time + timeout + begin + Fiber.yield + ensure + # Remove from @waiting in the case #unblock was called before the timeout expired: + @waiting.delete(Fiber.current) + end + else + @blocking += 1 + begin + Fiber.yield + ensure + @blocking -= 1 + end + end + end + + # Used when synchronization wakes up a previously-blocked fiber + # (Thread::Mutex#unlock, Thread::Queue#push, ...). + # This might be called from another thread. + def unblock(blocker, fiber) + # $stderr.puts [__method__, blocker, fiber].inspect + # $stderr.puts blocker.backtrace.inspect + # $stderr.puts fiber.backtrace.inspect + + @lock.synchronize do + @ready << fiber + end + + io = @urgent.last + io.write_nonblock('.') + end + + def fiber(&block) + fiber = Fiber.new(blocking: false, &block) + + fiber.resume + + return fiber + end + + def address_resolve(hostname) + Thread.new do + Addrinfo.getaddrinfo(hostname, nil).map(&:ip_address).uniq + end.value + end +end + +class IOBufferScheduler < Scheduler + EAGAIN = Errno::EAGAIN::Errno + + def io_read(io, buffer, length) + offset = 0 + + while true + maximum_size = buffer.size - offset + result = blocking{io.read_nonblock(maximum_size, exception: false)} + + # blocking{pp read: maximum_size, result: result, length: length} + + case result + when :wait_readable + if length > 0 + self.io_wait(io, IO::READABLE, nil) + else + return -EAGAIN + end + when :wait_writable + if length > 0 + self.io_wait(io, IO::WRITABLE, nil) + else + return -EAGAIN + end + else + break unless result + + buffer.set_string(result, offset) + + size = result.bytesize + offset += size + break if size >= length + length -= size + end + end + + return offset + end + + def io_write(io, buffer, length) + offset = 0 + + while true + maximum_size = buffer.size - offset + + chunk = buffer.get_string(offset, maximum_size) + result = blocking{io.write_nonblock(chunk, exception: false)} + + # blocking{pp write: maximum_size, result: result, length: length} + + case result + when :wait_readable + if length > 0 + self.io_wait(io, IO::READABLE, nil) + else + return -EAGAIN + end + when :wait_writable + if length > 0 + self.io_wait(io, IO::WRITABLE, nil) + else + return -EAGAIN + end + else + offset += result + break if result >= length + length -= result + end + end + + return offset + end + + def blocking(&block) + Fiber.new(blocking: true, &block).resume + end +end + +class BrokenUnblockScheduler < Scheduler + def unblock(blocker, fiber) + super + + raise "Broken unblock!" + end +end + +class SleepingUnblockScheduler < Scheduler + # This method is invoked when the thread is exiting. + def unblock(blocker, fiber) + super + + # This changes the current thread state to `THREAD_RUNNING` which causes `thread_join_sleep` to hang. + sleep(0.1) + end +end diff --git a/ruby/test/fiber/test_address_resolve.rb b/ruby/test/fiber/test_address_resolve.rb new file mode 100644 index 000000000..457221b9b --- /dev/null +++ b/ruby/test/fiber/test_address_resolve.rb @@ -0,0 +1,278 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestAddressResolve < Test::Unit::TestCase + class NullScheduler < Scheduler + def address_resolve(*) + end + end + + class StubScheduler < Scheduler + def address_resolve(hostname) + ["1.2.3.4", "1234::1"] + end + end + + def test_addrinfo_getaddrinfo_ipv4_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Addrinfo.getaddrinfo("example.com", 80, :AF_INET, :STREAM) + assert_equal(1, result.count) + + ai = result.first + assert_equal("1.2.3.4", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_ipv6_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Addrinfo.getaddrinfo("example.com", 80, :AF_INET6, :STREAM) + assert_equal(1, result.count) + + ai = result.first + assert_equal("1234::1", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET6, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_pf_unspec_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + results = Addrinfo.getaddrinfo("example.com", 80, :PF_UNSPEC, :STREAM) + assert_equal(2, results.count) + + ai_ipv4 = results.first + assert_equal("1.2.3.4", ai_ipv4.ip_address) + assert_equal(80, ai_ipv4.ip_port) + assert_equal(Socket::AF_INET, ai_ipv4.afamily) + assert_equal(Socket::SOCK_STREAM, ai_ipv4.socktype) + + ai_ipv6 = results.last + assert_equal("1234::1", ai_ipv6.ip_address) + assert_equal(80, ai_ipv6.ip_port) + assert_equal(Socket::AF_INET6, ai_ipv6.afamily) + assert_equal(Socket::SOCK_STREAM, ai_ipv6.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_full_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + results = Addrinfo.getaddrinfo("example.com", 80) + assert_equal(6, results.count) + + ai_ipv4_tcp = results[0] + assert_equal("1.2.3.4", ai_ipv4_tcp.ip_address) + assert_equal(80, ai_ipv4_tcp.ip_port) + assert_equal(Socket::AF_INET, ai_ipv4_tcp.afamily) + assert_equal(Socket::SOCK_STREAM, ai_ipv4_tcp.socktype) + + ai_ipv4_udp = results[1] + assert_equal("1.2.3.4", ai_ipv4_udp.ip_address) + assert_equal(80, ai_ipv4_udp.ip_port) + assert_equal(Socket::AF_INET, ai_ipv4_udp.afamily) + assert_equal(Socket::SOCK_DGRAM, ai_ipv4_udp.socktype) + + ai_ipv4_sock_raw = results[2] + assert_equal("1.2.3.4", ai_ipv4_sock_raw.ip_address) + assert_equal(80, ai_ipv4_sock_raw.ip_port) + assert_equal(Socket::AF_INET, ai_ipv4_sock_raw.afamily) + assert_equal(Socket::SOCK_RAW, ai_ipv4_sock_raw.socktype) + + ai_ipv6_tcp = results[3] + assert_equal("1234::1", ai_ipv6_tcp.ip_address) + assert_equal(80, ai_ipv6_tcp.ip_port) + assert_equal(Socket::AF_INET6, ai_ipv6_tcp.afamily) + assert_equal(Socket::SOCK_STREAM, ai_ipv6_tcp.socktype) + + ai_ipv6_udp = results[4] + assert_equal("1234::1", ai_ipv6_udp.ip_address) + assert_equal(80, ai_ipv6_udp.ip_port) + assert_equal(Socket::AF_INET6, ai_ipv6_udp.afamily) + assert_equal(Socket::SOCK_DGRAM, ai_ipv6_udp.socktype) + + ai_ipv6_sock_raw = results[5] + assert_equal("1234::1", ai_ipv6_sock_raw.ip_address) + assert_equal(80, ai_ipv6_sock_raw.ip_port) + assert_equal(Socket::AF_INET6, ai_ipv6_sock_raw.afamily) + assert_equal(Socket::SOCK_RAW, ai_ipv6_sock_raw.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_numeric_non_blocking + Thread.new do + scheduler = NullScheduler.new # scheduler hook not invoked + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Addrinfo.getaddrinfo("1.2.3.4", 80, :AF_INET, :STREAM) + assert_equal(1, result.count) + + ai = result.first + assert_equal("1.2.3.4", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_any_non_blocking + Thread.new do + scheduler = NullScheduler.new # scheduler hook not invoked + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Addrinfo.getaddrinfo("", 80, :AF_INET, :STREAM) + assert_equal(1, result.count) + + ai = result.first + assert_equal("0.0.0.0", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_getaddrinfo_localhost + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + results = Addrinfo.getaddrinfo("localhost", 80, :AF_INET, :STREAM) + assert_equal(1, results.count) + + ai = results.first + assert_equal("1.2.3.4", ai.ip_address) + end + end.join + end + + def test_addrinfo_getaddrinfo_non_existing_domain_blocking + Thread.new do + scheduler = NullScheduler.new # invoked, returns nil + Fiber.set_scheduler scheduler + + Fiber.schedule do + assert_raise(SocketError) { + Addrinfo.getaddrinfo("non-existing-domain.abc", nil) + } + end + end.join + end + + def test_addrinfo_getaddrinfo_no_host_non_blocking + Thread.new do + scheduler = NullScheduler.new # scheduler hook not invoked + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Addrinfo.getaddrinfo(nil, 80, :AF_INET, :STREAM) + assert_equal(1, result.count) + + ai = result.first + assert_equal("127.0.0.1", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_ip_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + ai = Addrinfo.ip("example.com") + + assert_equal("1.2.3.4", ai.ip_address) + end + end.join + end + + def test_addrinfo_tcp_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + ai = Addrinfo.tcp("example.com", 80) + + assert_equal("1.2.3.4", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_STREAM, ai.socktype) + end + end.join + end + + def test_addrinfo_udp_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + ai = Addrinfo.udp("example.com", 80) + + assert_equal("1.2.3.4", ai.ip_address) + assert_equal(80, ai.ip_port) + assert_equal(Socket::AF_INET, ai.afamily) + assert_equal(Socket::SOCK_DGRAM, ai.socktype) + end + end.join + end + + def test_ip_socket_getaddress_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + ip = IPSocket.getaddress("example.com") + + assert_equal("1.2.3.4", ip) + end + end.join + end + + # This test "hits deep" into C function call chain. + def test_socket_getnameinfo_domain_blocking + Thread.new do + scheduler = StubScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + result = Socket.getnameinfo(["AF_INET", 80, "example.com"], Socket::NI_NUMERICSERV) + + assert_equal(["1.2.3.4", "80"], result) + end + end.join + end +end diff --git a/ruby/test/fiber/test_backtrace.rb b/ruby/test/fiber/test_backtrace.rb new file mode 100644 index 000000000..ba05ca298 --- /dev/null +++ b/ruby/test/fiber/test_backtrace.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +require 'test/unit' +require 'fiber' + +class TestFiberBacktrace < Test::Unit::TestCase + def test_backtrace + backtrace = Fiber.current.backtrace + assert_kind_of Array, backtrace + assert_match(/test_backtrace/, backtrace[0]) + end + + def test_backtrace_locations + backtrace = Fiber.current.backtrace_locations + assert_kind_of Array, backtrace + assert_match(/test_backtrace_locations/, backtrace[1].label) + end + + def test_local_backtrace + backtrace = Fiber.current.backtrace(2) + assert_equal backtrace, caller + end +end diff --git a/ruby/test/fiber/test_enumerator.rb b/ruby/test/fiber/test_enumerator.rb new file mode 100644 index 000000000..cd4ccd1de --- /dev/null +++ b/ruby/test/fiber/test_enumerator.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberEnumerator < Test::Unit::TestCase + MESSAGE = "Hello World" + + def test_read_characters + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + + unless i.nonblock? && o.nonblock? + i.close + o.close + skip "I/O is not non-blocking!" + end + + message = String.new + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + e = i.to_enum(:each_char) + + Fiber.schedule do + o.write("Hello World") + o.close + end + + Fiber.schedule do + begin + while c = e.next + message << c + end + rescue StopIteration + # Ignore. + end + + i.close + end + end + + thread.join + + assert_equal(MESSAGE, message) + assert_predicate(i, :closed?) + assert_predicate(o, :closed?) + end +end diff --git a/ruby/test/fiber/test_io.rb b/ruby/test/fiber/test_io.rb new file mode 100644 index 000000000..06a3c0dd1 --- /dev/null +++ b/ruby/test/fiber/test_io.rb @@ -0,0 +1,175 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberIO < Test::Unit::TestCase + MESSAGE = "Hello World" + + def test_read + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + + unless i.nonblock? && o.nonblock? + i.close + o.close + skip "I/O is not non-blocking!" + end + + message = nil + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + message = i.read(20) + i.close + end + + Fiber.schedule do + o.write("Hello World") + o.close + end + end + + thread.join + + assert_equal MESSAGE, message + assert_predicate(i, :closed?) + assert_predicate(o, :closed?) + end + + def test_heavy_read + skip unless defined?(UNIXSocket) + + 16.times.map do + Thread.new do + i, o = UNIXSocket.pair + + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + i.read(20) + i.close + end + + Fiber.schedule do + o.write("Hello World") + o.close + end + end + end.each(&:join) + end + + def test_epipe_on_read + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + + unless i.nonblock? && o.nonblock? + i.close + o.close + skip "I/O is not non-blocking!" + end + + error = nil + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + begin + i.close + o.write(MESSAGE) + rescue => error + # Saved into error. + end + end + end + + thread.join + + i.close + o.close + + assert_kind_of Errno::EPIPE, error + end + + def test_tcp_accept + server = TCPServer.new('localhost', 0) + + th = Thread.new do + Fiber.set_scheduler(Scheduler.new) + + Fiber.schedule do + sender = server.accept + sender.wait_writable + sender.write "hello" + sender.close + end + end + + recver = TCPSocket.new('localhost', server.local_address.ip_port) + assert "hello", recver.read + + recver.close + server.close + th.join + end + + def test_tcp_connect + server = TCPServer.new('localhost', 0) + + th = Thread.new do + Fiber.set_scheduler(Scheduler.new) + + Fiber.schedule do + sender = TCPSocket.new('localhost', server.local_address.ip_port) + sender.write "hello" + sender.close + end + end + + recver = server.accept + assert "hello", recver.read + + recver.close + server.close + th.join + end + + def test_read_write_blocking + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + i.nonblock = false + o.nonblock = false + + message = nil + + thread = Thread.new do + # This scheduler provides non-blocking `io_read`/`io_write`: + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + message = i.read(20) + i.close + end + + Fiber.schedule do + o.write("Hello World") + o.close + end + end + + thread.join + + assert_equal MESSAGE, message + assert_predicate(i, :closed?) + assert_predicate(o, :closed?) + end +end diff --git a/ruby/test/fiber/test_io_buffer.rb b/ruby/test/fiber/test_io_buffer.rb new file mode 100644 index 000000000..5b34a3733 --- /dev/null +++ b/ruby/test/fiber/test_io_buffer.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +require 'timeout' + +class TestFiberIOBuffer < Test::Unit::TestCase + MESSAGE = "Hello World" + + def test_read_write_blocking + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + i.nonblock = false + o.nonblock = false + + message = nil + + thread = Thread.new do + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + message = i.read(20) + i.close + end + + Fiber.schedule do + o.write(MESSAGE) + o.close + end + end + + thread.join + + assert_equal MESSAGE, message + assert_predicate(i, :closed?) + assert_predicate(o, :closed?) + ensure + i&.close + o&.close + end + + def test_timeout_after + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + i.nonblock = false + o.nonblock = false + + message = nil + error = nil + + thread = Thread.new do + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + Timeout.timeout(0.1) do + message = i.read(20) + end + rescue Timeout::Error => error + # Assertions below. + ensure + i.close + end + end + + thread.join + + assert_nil message + assert_kind_of Timeout::Error, error + ensure + i&.close + o&.close + end + + def test_read_nonblock + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + + message = nil + + thread = Thread.new do + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + message = i.read_nonblock(20, exception: false) + i.close + end + end + + thread.join + + assert_equal :wait_readable, message + ensure + i&.close + o&.close + end + + def test_write_nonblock + skip "UNIXSocket is not defined!" unless defined?(UNIXSocket) + + i, o = UNIXSocket.pair + + thread = Thread.new do + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + o.write_nonblock(MESSAGE, exception: false) + o.close + end + end + + thread.join + + assert_equal MESSAGE, i.read + ensure + i&.close + o&.close + end +end diff --git a/ruby/test/fiber/test_mutex.rb b/ruby/test/fiber/test_mutex.rb new file mode 100644 index 000000000..b0655f06a --- /dev/null +++ b/ruby/test/fiber/test_mutex.rb @@ -0,0 +1,220 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberMutex < Test::Unit::TestCase + def test_mutex_synchronize + mutex = Thread::Mutex.new + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + assert_not_predicate Fiber, :blocking? + + mutex.synchronize do + assert_not_predicate Fiber, :blocking? + end + end + end + + thread.join + end + + def test_mutex_interleaved_locking + mutex = Thread::Mutex.new + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + mutex.lock + sleep 0.1 + mutex.unlock + end + + Fiber.schedule do + mutex.lock + sleep 0.1 + mutex.unlock + end + + scheduler.run + end + + thread.join + end + + def test_mutex_thread + mutex = Thread::Mutex.new + mutex.lock + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + mutex.lock + sleep 0.1 + mutex.unlock + end + + scheduler.run + end + + sleep 0.1 + mutex.unlock + + thread.join + end + + def test_mutex_fiber_raise + mutex = Thread::Mutex.new + ran = false + + main = Thread.new do + mutex.lock + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + f = Fiber.schedule do + assert_raise_with_message(RuntimeError, "bye") do + mutex.lock + end + + ran = true + end + + Fiber.schedule do + f.raise "bye" + end + end + + thread.join + end + + main.join # causes mutex to be released + assert_equal false, mutex.locked? + assert_equal true, ran + end + + def test_condition_variable + mutex = Thread::Mutex.new + condition = Thread::ConditionVariable.new + + signalled = 0 + + Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + mutex.synchronize do + 3.times do + condition.wait(mutex) + signalled += 1 + end + end + end + + Fiber.schedule do + 3.times do + mutex.synchronize do + condition.signal + end + + sleep 0.1 + end + end + + scheduler.run + end.join + + assert_equal 3, signalled + end + + def test_queue + queue = Thread::Queue.new + processed = 0 + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + 3.times do |i| + queue << i + sleep 0.1 + end + + queue.close + end + + Fiber.schedule do + while item = queue.pop + processed += 1 + end + end + + scheduler.run + end + + thread.join + + assert_equal 3, processed + end + + def test_queue_pop_waits + queue = Thread::Queue.new + running = false + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + result = nil + Fiber.schedule do + result = queue.pop + end + + running = true + scheduler.run + result + end + + Thread.pass until running + sleep 0.1 + + queue << :done + assert_equal :done, thread.value + end + + def test_mutex_deadlock + error_pattern = /No live threads left. Deadlock\?/ + + assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], error_pattern, success: false + require 'scheduler' + mutex = Thread::Mutex.new + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + mutex.synchronize do + puts 'in synchronize' + Fiber.yield + end + end + + mutex.lock + end + + thread.join + RUBY + end +end diff --git a/ruby/test/fiber/test_process.rb b/ruby/test/fiber/test_process.rb new file mode 100644 index 000000000..a5990be20 --- /dev/null +++ b/ruby/test/fiber/test_process.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberProcess < Test::Unit::TestCase + def test_process_wait + Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + pid = Process.spawn("true") + Process.wait(pid) + + # TODO test that scheduler was invoked. + + assert_predicate $?, :success? + end + end.join + end + + def test_system + Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + system("true") + + # TODO test that scheduler was invoked (currently it's not). + + assert_predicate $?, :success? + end + end.join + end + + def test_fork + omit 'fork not supported' unless Process.respond_to?(:fork) + Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + pid = Process.fork {} + Process.wait(pid) + + assert_predicate $?, :success? + end + end.join + end +end diff --git a/ruby/test/fiber/test_ractor.rb b/ruby/test/fiber/test_ractor.rb new file mode 100644 index 000000000..d03455a9f --- /dev/null +++ b/ruby/test/fiber/test_ractor.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +require "test/unit" +require "fiber" + +class TestFiberCurrentRactor < Test::Unit::TestCase + def setup + skip unless defined? Ractor + end + + def test_ractor_shareable + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + $VERBOSE = nil + require "fiber" + r = Ractor.new do + Fiber.new do + Fiber.current.class + end.resume + end + assert_equal(Fiber, r.take) + end; + end +end diff --git a/ruby/test/fiber/test_scheduler.rb b/ruby/test/fiber/test_scheduler.rb new file mode 100644 index 000000000..1870ab1c3 --- /dev/null +++ b/ruby/test/fiber/test_scheduler.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberScheduler < Test::Unit::TestCase + def test_fiber_without_scheduler + # Cannot create fiber without scheduler. + assert_raise RuntimeError do + Fiber.schedule do + end + end + end + + def test_fiber_new + f = Fiber.new{} + refute f.blocking? + end + + def test_fiber_new_with_options + f = Fiber.new(blocking: true){} + assert f.blocking? + + f = Fiber.new(blocking: false){} + refute f.blocking? + + f = Fiber.new(pool: nil){} + refute f.blocking? + end + + def test_closed_at_thread_exit + scheduler = Scheduler.new + + thread = Thread.new do + Fiber.set_scheduler scheduler + end + + thread.join + + assert scheduler.closed? + end + + def test_closed_when_set_to_nil + scheduler = Scheduler.new + + thread = Thread.new do + Fiber.set_scheduler scheduler + Fiber.set_scheduler nil + + assert scheduler.closed? + end + + thread.join + end + + def test_close_at_exit + assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['Running Fiber'], [], success: true + require 'scheduler' + Warning[:experimental] = false + + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + sleep(0) + puts "Running Fiber" + end + RUBY + end + + def test_minimal_interface + scheduler = Object.new + + def scheduler.block + end + + def scheduler.unblock + end + + def scheduler.io_wait + end + + def scheduler.kernel_sleep + end + + thread = Thread.new do + Fiber.set_scheduler scheduler + end + + thread.join + end + + def test_current_scheduler + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + assert Fiber.scheduler + refute Fiber.current_scheduler + + Fiber.schedule do + assert Fiber.current_scheduler + end + end + + thread.join + end +end diff --git a/ruby/test/fiber/test_sleep.rb b/ruby/test/fiber/test_sleep.rb new file mode 100644 index 000000000..a7e88c036 --- /dev/null +++ b/ruby/test/fiber/test_sleep.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +class TestFiberSleep < Test::Unit::TestCase + ITEMS = [0, 1, 2, 3, 4] + + def test_sleep + items = [] + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + 5.times do |i| + Fiber.schedule do + assert_operator sleep(i/100.0), :>=, 0 + items << i + end + end + + # Should be 5 fibers waiting: + assert_equal scheduler.waiting.size, 5 + end + + thread.join + + assert_equal ITEMS, items + end + + def test_sleep_returns_seconds_slept + seconds = nil + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + Fiber.schedule do + seconds = sleep(2) + end + end + + thread.join + + assert_operator seconds, :>=, 2, "actual: %p" % seconds + end + + def test_broken_sleep + thread = Thread.new do + Thread.current.report_on_exception = false + + scheduler = Scheduler.new + + def scheduler.kernel_sleep(duration = nil) + raise "Broken sleep!" + end + + Fiber.set_scheduler scheduler + + Fiber.schedule do + sleep 0 + end + + ensure + scheduler.close + end + + assert_raise(RuntimeError) do + thread.join + end + end +end diff --git a/ruby/test/fiber/test_thread.rb b/ruby/test/fiber/test_thread.rb new file mode 100644 index 000000000..5c25c43de --- /dev/null +++ b/ruby/test/fiber/test_thread.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true +require "test/unit" +require_relative 'scheduler' + +class TestFiberThread < Test::Unit::TestCase + def test_thread_join + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + result = nil + Fiber.schedule do + result = Thread.new{:done}.value + end + + scheduler.run + result + end + + assert_equal :done, thread.value + end + + def test_thread_join_implicit + sleeping = false + finished = false + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + sleeping = true + sleep(0.1) + finished = true + end + + :done + end + + Thread.pass until sleeping + + thread.join + + assert_equal :done, thread.value + assert finished, "Scheduler thread's task should be finished!" + end + + def test_thread_join_blocking + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + result = nil + Fiber.schedule do + Fiber.new(blocking: true) do + # This can deadlock if the blocking state is not taken into account: + Thread.new do + sleep(0) + result = :done + end.join + end.resume + end + + scheduler.run + result + end + + assert_equal :done, thread.value + end + + def test_broken_unblock + thread = Thread.new do + Thread.current.report_on_exception = false + + scheduler = BrokenUnblockScheduler.new + + Fiber.set_scheduler scheduler + + Fiber.schedule do + Thread.new{ + Thread.current.report_on_exception = false + }.join + end + + scheduler.run + ensure + scheduler.close + end + + assert_raise(RuntimeError) do + thread.join + end + end + + def test_thread_join_hang + thread = Thread.new do + scheduler = SleepingUnblockScheduler.new + + Fiber.set_scheduler scheduler + + Fiber.schedule do + Thread.new{sleep(0.01)}.value + end + end + + thread.join + end +end diff --git a/ruby/test/fiber/test_timeout.rb b/ruby/test/fiber/test_timeout.rb new file mode 100644 index 000000000..5493606be --- /dev/null +++ b/ruby/test/fiber/test_timeout.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative 'scheduler' + +require 'timeout' + +class TestFiberTimeout < Test::Unit::TestCase + def test_timeout_after + error = nil + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + begin + Timeout.timeout(0.001) do + sleep(1) + end + rescue + error = $! + end + end + end + + thread.join + + assert_kind_of(Timeout::Error, error) + end + + MESSAGE = "Hello World" + + def test_timeout_on_main_fiber + message = nil + + thread = Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + assert_nil Fiber.current_scheduler + + Timeout.timeout(1) do + message = MESSAGE + end + end + + thread.join + + assert_equal MESSAGE, message + end +end diff --git a/ruby/test/fiddle/helper.rb b/ruby/test/fiddle/helper.rb index 57ded4951..0ea3bf57f 100644 --- a/ruby/test/fiddle/helper.rb +++ b/ruby/test/fiddle/helper.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true + +require 'rbconfig/sizeof' require 'test/unit' require 'fiddle' @@ -17,6 +19,10 @@ end libc_so = File.join(libdir, "libc.so") libm_so = File.join(libdir, "libm.so") +when /linux-musl/ + Dir.glob('/lib/ld-musl-*.so.1') do |ld| + libc_so = libm_so = ld + end when /linux/ libdir = '/lib' case RbConfig::SIZEOF['void*'] @@ -27,8 +33,8 @@ # In the ARM 32-bit libc package such as libc6:armhf libc6:armel, # libc.so and libm.so are installed to /lib/arm-linux-gnu*. # It's not installed to /lib32. - dirs = Dir.glob('/lib/arm-linux-gnu*') - libdir = dirs[0] if dirs && File.directory?(dirs[0]) + dir, = Dir.glob('/lib/arm-linux-gnu*') + libdir = dir if dir && File.directory?(dir) else libdir = '/lib32' if File.directory? '/lib32' end @@ -36,15 +42,24 @@ # 64-bit ruby libdir = '/lib64' if File.directory? '/lib64' end - libc_so = File.join(libdir, "libc.so.6") - libm_so = File.join(libdir, "libm.so.6") + + # Handle musl libc + libc_so, = Dir.glob(File.join(libdir, "libc.musl*.so*")) + if libc_so + libm_so = libc_so + else + # glibc + libc_so = "libc.so.6" + libm_so = "libm.so.6" + end when /mingw/, /mswin/ require "rbconfig" crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase' libc_so = libm_so = "#{crtname}.dll" when /darwin/ - libc_so = "/usr/lib/libc.dylib" - libm_so = "/usr/lib/libm.dylib" + libc_so = libm_so = "/usr/lib/libSystem.B.dylib" + # macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen. + rigid_path = true when /kfreebsd/ libc_so = "/lib/libc.so.0.1" libm_so = "/lib/libm.so.1" @@ -81,9 +96,9 @@ funcs=%w!sin sinf strcpy strncpy! expfile='dltest.exp' require 'tmpdir' - Dir.mktmpdir do |dir| + Dir.mktmpdir do |_dir| begin - Dir.chdir dir + Dir.chdir _dir %x!/usr/bin/ar x /usr/lib/libc.a #{cobjs.join(' ')}! %x!/usr/bin/ar x /usr/lib/libm.a #{mobjs.join(' ')}! %x!echo "#{funcs.join("\n")}\n" > #{expfile}! @@ -100,6 +115,18 @@ end end end +when /haiku/ + libdir = '/system/lib' + case [0].pack('L!').size + when 4 + # 32-bit ruby + libdir = '/system/lib/x86' if File.directory? '/system/lib/x86' + when 8 + # 64-bit ruby + libdir = '/system/lib/' if File.directory? '/system/lib/' + end + libc_so = File.join(libdir, "libroot.so") + libm_so = File.join(libdir, "libroot.so") else libc_so = ARGV[0] if ARGV[0] && ARGV[0][0] == ?/ libm_so = ARGV[1] if ARGV[1] && ARGV[1][0] == ?/ @@ -108,8 +135,10 @@ end end -libc_so = nil if !libc_so || (libc_so[0] == ?/ && !File.file?(libc_so)) -libm_so = nil if !libm_so || (libm_so[0] == ?/ && !File.file?(libm_so)) +unless rigid_path + libc_so = nil if libc_so && libc_so[0] == ?/ && !File.file?(libc_so) + libm_so = nil if libm_so && libm_so[0] == ?/ && !File.file?(libm_so) +end if !libc_so || !libm_so ruby = EnvUtil.rubybin @@ -138,5 +167,12 @@ def teardown GC.start end end + + def under_gc_stress + stress, GC.stress = GC.stress, true + yield + ensure + GC.stress = stress + end end end diff --git a/ruby/test/fiddle/test_c_struct_builder.rb b/ruby/test/fiddle/test_c_struct_builder.rb new file mode 100644 index 000000000..ca44c6cf7 --- /dev/null +++ b/ruby/test/fiddle/test_c_struct_builder.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true +begin + require_relative 'helper' + require 'fiddle/struct' + require 'fiddle/cparser' + require 'fiddle/import' +rescue LoadError +end + +module Fiddle + class TestCStructBuilder < TestCase + include Fiddle::CParser + extend Fiddle::Importer + + RBasic = struct ['void * flags', + 'void * klass' ] + + + RObject = struct [ + { 'basic' => RBasic }, + { 'as' => union([ + { 'heap'=> struct([ 'uint32_t numiv', + 'void * ivptr', + 'void * iv_index_tbl' ]) }, + 'void *ary[3]' ])} + ] + + + def test_basic_embedded_members + assert_equal 0, RObject.offsetof("basic.flags") + assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass") + end + + def test_embedded_union_members + assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as") + assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap") + assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv") + assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr") + assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl") + end + + def test_as_ary + assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary") + end + + def test_offsetof + types, members = parse_struct_signature(['int64_t i','char c']) + my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) + assert_equal 0, my_struct.offsetof("i") + assert_equal Fiddle::SIZEOF_INT64_T, my_struct.offsetof("c") + end + + def test_offset_with_gap + types, members = parse_struct_signature(['void *p', 'char c', 'long x']) + my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) + + assert_equal PackInfo.align(0, ALIGN_VOIDP), my_struct.offsetof("p") + assert_equal PackInfo.align(SIZEOF_VOIDP, ALIGN_CHAR), my_struct.offsetof("c") + assert_equal SIZEOF_VOIDP + PackInfo.align(SIZEOF_CHAR, ALIGN_LONG), my_struct.offsetof("x") + end + + def test_union_offsetof + types, members = parse_struct_signature(['int64_t i','char c']) + my_struct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) + assert_equal 0, my_struct.offsetof("i") + assert_equal 0, my_struct.offsetof("c") + end + end +end if defined?(Fiddle) diff --git a/ruby/test/fiddle/test_c_struct_entry.rb b/ruby/test/fiddle/test_c_struct_entry.rb index 8ece438f5..9fd16d710 100644 --- a/ruby/test/fiddle/test_c_struct_entry.rb +++ b/ruby/test/fiddle/test_c_struct_entry.rb @@ -43,35 +43,123 @@ def test_class_size_with_count end def test_set_ctypes - union = CStructEntity.malloc [TYPE_INT, TYPE_LONG] - union.assign_names %w[int long] + CStructEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |struct| + struct.assign_names %w[int long] - # this test is roundabout because the stored ctypes are not accessible - union['long'] = 1 - union['int'] = 2 + # this test is roundabout because the stored ctypes are not accessible + struct['long'] = 1 + struct['int'] = 2 - assert_equal 1, union['long'] - assert_equal 2, union['int'] + assert_equal 1, struct['long'] + assert_equal 2, struct['int'] + end end def test_aref_pointer_array - team = CStructEntity.malloc([[TYPE_VOIDP, 2]]) - team.assign_names(["names"]) - alice = Fiddle::Pointer.malloc(6) - alice[0, 6] = "Alice\0" - bob = Fiddle::Pointer.malloc(4) - bob[0, 4] = "Bob\0" - team["names"] = [alice, bob] - assert_equal(["Alice", "Bob"], team["names"].map(&:to_s)) + CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE) do |team| + team.assign_names(["names"]) + Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| + alice[0, 6] = "Alice\0" + Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE) do |bob| + bob[0, 4] = "Bob\0" + team["names"] = [alice, bob] + assert_equal(["Alice", "Bob"], team["names"].map(&:to_s)) + end + end + end end def test_aref_pointer - user = CStructEntity.malloc([TYPE_VOIDP]) - user.assign_names(["name"]) - alice = Fiddle::Pointer.malloc(6) - alice[0, 6] = "Alice\0" - user["name"] = alice - assert_equal("Alice", user["name"].to_s) + CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE) do |user| + user.assign_names(["name"]) + Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| + alice[0, 6] = "Alice\0" + user["name"] = alice + assert_equal("Alice", user["name"].to_s) + end + end + end + + def test_new_double_free + types = [TYPE_INT] + Pointer.malloc(CStructEntity.size(types), Fiddle::RUBY_FREE) do |pointer| + assert_raise ArgumentError do + CStructEntity.new(pointer, types, Fiddle::RUBY_FREE) + end + end + end + + def test_malloc_block + escaped_struct = nil + returned = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| + assert_equal Fiddle::SIZEOF_INT, struct.size + assert_equal Fiddle::RUBY_FREE, struct.free.to_i + escaped_struct = struct + :returned + end + assert_equal :returned, returned + assert escaped_struct.freed? + end + + def test_malloc_block_no_free + assert_raise ArgumentError do + CStructEntity.malloc([TYPE_INT]) { |struct| } + end + end + + def test_free + struct = CStructEntity.malloc([TYPE_INT]) + begin + assert_nil struct.free + ensure + Fiddle.free struct + end + end + + def test_free_with_func + struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) + refute struct.freed? + struct.call_free + assert struct.freed? + struct.call_free # you can safely run it again + assert struct.freed? + GC.start # you can safely run the GC routine + assert struct.freed? + end + + def test_free_with_no_func + struct = CStructEntity.malloc([TYPE_INT]) + refute struct.freed? + struct.call_free + refute struct.freed? + struct.call_free # you can safely run it again + refute struct.freed? + end + + def test_freed? + struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) + refute struct.freed? + struct.call_free + assert struct.freed? + end + + def test_null? + struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) + refute struct.null? + end + + def test_size + CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| + assert_equal Fiddle::SIZEOF_INT, struct.size + end + end + + def test_size= + CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| + assert_raise NoMethodError do + struct.size = 1 + end + end end end end if defined?(Fiddle) diff --git a/ruby/test/fiddle/test_c_union_entity.rb b/ruby/test/fiddle/test_c_union_entity.rb index 5727a20e3..e0a375756 100644 --- a/ruby/test/fiddle/test_c_union_entity.rb +++ b/ruby/test/fiddle/test_c_union_entity.rb @@ -21,15 +21,16 @@ def test_class_size_with_count end def test_set_ctypes - union = CUnionEntity.malloc [TYPE_INT, TYPE_LONG] - union.assign_names %w[int long] + CUnionEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |union| + union.assign_names %w[int long] - # this test is roundabout because the stored ctypes are not accessible - union['long'] = 1 - assert_equal 1, union['long'] + # this test is roundabout because the stored ctypes are not accessible + union['long'] = 1 + assert_equal 1, union['long'] - union['int'] = 1 - assert_equal 1, union['int'] + union['int'] = 1 + assert_equal 1, union['int'] + end end end end if defined?(Fiddle) diff --git a/ruby/test/fiddle/test_closure.rb b/ruby/test/fiddle/test_closure.rb index 2de066072..9e748bf5e 100644 --- a/ruby/test/fiddle/test_closure.rb +++ b/ruby/test/fiddle/test_closure.rb @@ -20,6 +20,18 @@ def test_argument_errors end end + def test_type_symbol + closure = Closure.new(:int, [:void]) + assert_equal([ + TYPE_INT, + [TYPE_VOID], + ], + [ + closure.instance_variable_get(:@ctype), + closure.instance_variable_get(:@args), + ]) + end + def test_call closure = Class.new(Closure) { def call @@ -42,6 +54,19 @@ def call thing assert_equal 10, func.call(10) end + def test_const_string + closure_class = Class.new(Closure) do + def call(string) + @return_string = "Hello! #{string}" + @return_string + end + end + closure = closure_class.new(:const_string, [:const_string]) + + func = Function.new(closure, [:const_string], :const_string) + assert_equal("Hello! World!", func.call("World!")) + end + def test_block_caller cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| one diff --git a/ruby/test/fiddle/test_cparser.rb b/ruby/test/fiddle/test_cparser.rb index 5d9ac3c81..ae319197a 100644 --- a/ruby/test/fiddle/test_cparser.rb +++ b/ruby/test/fiddle/test_cparser.rb @@ -2,6 +2,7 @@ begin require_relative 'helper' require 'fiddle/cparser' + require 'fiddle/import' rescue LoadError end @@ -11,53 +12,77 @@ class TestCParser < TestCase def test_char_ctype assert_equal(TYPE_CHAR, parse_ctype('char')) + assert_equal(TYPE_CHAR, parse_ctype('const char')) assert_equal(TYPE_CHAR, parse_ctype('signed char')) + assert_equal(TYPE_CHAR, parse_ctype('const signed char')) assert_equal(-TYPE_CHAR, parse_ctype('unsigned char')) + assert_equal(-TYPE_CHAR, parse_ctype('const unsigned char')) end def test_short_ctype assert_equal(TYPE_SHORT, parse_ctype('short')) + assert_equal(TYPE_SHORT, parse_ctype('const short')) assert_equal(TYPE_SHORT, parse_ctype('short int')) + assert_equal(TYPE_SHORT, parse_ctype('const short int')) assert_equal(TYPE_SHORT, parse_ctype('signed short')) + assert_equal(TYPE_SHORT, parse_ctype('const signed short')) assert_equal(TYPE_SHORT, parse_ctype('signed short int')) + assert_equal(TYPE_SHORT, parse_ctype('const signed short int')) assert_equal(-TYPE_SHORT, parse_ctype('unsigned short')) + assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short')) assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int')) + assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short int')) end def test_int_ctype assert_equal(TYPE_INT, parse_ctype('int')) + assert_equal(TYPE_INT, parse_ctype('const int')) assert_equal(TYPE_INT, parse_ctype('signed int')) + assert_equal(TYPE_INT, parse_ctype('const signed int')) assert_equal(-TYPE_INT, parse_ctype('uint')) + assert_equal(-TYPE_INT, parse_ctype('const uint')) assert_equal(-TYPE_INT, parse_ctype('unsigned int')) + assert_equal(-TYPE_INT, parse_ctype('const unsigned int')) end def test_long_ctype assert_equal(TYPE_LONG, parse_ctype('long')) + assert_equal(TYPE_LONG, parse_ctype('const long')) assert_equal(TYPE_LONG, parse_ctype('long int')) + assert_equal(TYPE_LONG, parse_ctype('const long int')) assert_equal(TYPE_LONG, parse_ctype('signed long')) + assert_equal(TYPE_LONG, parse_ctype('const signed long')) assert_equal(TYPE_LONG, parse_ctype('signed long int')) + assert_equal(TYPE_LONG, parse_ctype('const signed long int')) assert_equal(-TYPE_LONG, parse_ctype('unsigned long')) + assert_equal(-TYPE_LONG, parse_ctype('const unsigned long')) assert_equal(-TYPE_LONG, parse_ctype('unsigned long int')) + assert_equal(-TYPE_LONG, parse_ctype('const unsigned long int')) end def test_size_t_ctype assert_equal(TYPE_SIZE_T, parse_ctype("size_t")) + assert_equal(TYPE_SIZE_T, parse_ctype("const size_t")) end def test_ssize_t_ctype assert_equal(TYPE_SSIZE_T, parse_ctype("ssize_t")) + assert_equal(TYPE_SSIZE_T, parse_ctype("const ssize_t")) end def test_ptrdiff_t_ctype assert_equal(TYPE_PTRDIFF_T, parse_ctype("ptrdiff_t")) + assert_equal(TYPE_PTRDIFF_T, parse_ctype("const ptrdiff_t")) end def test_intptr_t_ctype assert_equal(TYPE_INTPTR_T, parse_ctype("intptr_t")) + assert_equal(TYPE_INTPTR_T, parse_ctype("const intptr_t")) end def test_uintptr_t_ctype assert_equal(TYPE_UINTPTR_T, parse_ctype("uintptr_t")) + assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t")) end def test_undefined_ctype @@ -65,27 +90,147 @@ def test_undefined_ctype end def test_undefined_ctype_with_type_alias - assert_equal(-TYPE_LONG, parse_ctype('DWORD', {"DWORD" => "unsigned long"})) + assert_equal(-TYPE_LONG, + parse_ctype('DWORD', {"DWORD" => "unsigned long"})) + assert_equal(-TYPE_LONG, + parse_ctype('const DWORD', {"DWORD" => "unsigned long"})) + end + + def expand_struct_types(types) + types.collect do |type| + case type + when Class + [expand_struct_types(type.types)] + when Array + [expand_struct_types([type[0]])[0][0], type[1]] + else + type + end + end end def test_struct_basic - assert_equal [[TYPE_INT, TYPE_CHAR], ['i', 'c']], parse_struct_signature(['int i', 'char c']) + assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], + parse_struct_signature(['int i', 'char c'])) + assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], + parse_struct_signature(['const int i', 'const char c'])) end def test_struct_array - assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature(['char buffer[80]', 'int[5] x']) + assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], + ['buffer', 'x']], + parse_struct_signature(['char buffer[80]', + 'int[5] x'])) + assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], + ['buffer', 'x']], + parse_struct_signature(['const char buffer[80]', + 'const int[5] x'])) + end + + def test_struct_nested_struct + types, members = parse_struct_signature([ + 'int x', + {inner: ['int i', 'char c']}, + ]) + assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]], + ['x', ['inner', ['i', 'c']]]], + [expand_struct_types(types), + members]) + end + + def test_struct_nested_defined_struct + inner = Fiddle::Importer.struct(['int i', 'char c']) + assert_equal([[TYPE_INT, inner], + ['x', ['inner', ['i', 'c']]]], + parse_struct_signature([ + 'int x', + {inner: inner}, + ])) + end + + def test_struct_double_nested_struct + types, members = parse_struct_signature([ + 'int x', + { + outer: [ + 'int y', + {inner: ['int i', 'char c']}, + ], + }, + ]) + assert_equal([[TYPE_INT, [[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]]]], + ['x', ['outer', ['y', ['inner', ['i', 'c']]]]]], + [expand_struct_types(types), + members]) + end + + def test_struct_nested_struct_array + types, members = parse_struct_signature([ + 'int x', + { + 'inner[2]' => [ + 'int i', + 'char c', + ], + }, + ]) + assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]], + ['x', ['inner', ['i', 'c']]]], + [expand_struct_types(types), + members]) + end + + def test_struct_double_nested_struct_inner_array + types, members = parse_struct_signature(outer: [ + 'int x', + { + 'inner[2]' => [ + 'int i', + 'char c', + ], + }, + ]) + assert_equal([[[[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]]]], + [['outer', ['x', ['inner', ['i', 'c']]]]]], + [expand_struct_types(types), + members]) + end + + def test_struct_double_nested_struct_outer_array + types, members = parse_struct_signature([ + 'int x', + { + 'outer[2]' => { + inner: [ + 'int i', + 'char c', + ], + }, + }, + ]) + assert_equal([[TYPE_INT, [[[[TYPE_INT, TYPE_CHAR]]], 2]], + ['x', ['outer', [['inner', ['i', 'c']]]]]], + [expand_struct_types(types), + members]) end def test_struct_array_str - assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature('char buffer[80], int[5] x') + assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], + ['buffer', 'x']], + parse_struct_signature('char buffer[80], int[5] x')) + assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], + ['buffer', 'x']], + parse_struct_signature('const char buffer[80], const int[5] x')) end def test_struct_function_pointer - assert_equal [[TYPE_VOIDP], ['cb']], parse_struct_signature(['void (*cb)(const char*)']) + assert_equal([[TYPE_VOIDP], ['cb']], + parse_struct_signature(['void (*cb)(const char*)'])) end def test_struct_function_pointer_str - assert_equal [[TYPE_VOIDP,TYPE_VOIDP], ['cb', 'data']], parse_struct_signature('void (*cb)(const char*), const char* data') + assert_equal([[TYPE_VOIDP, TYPE_VOIDP], ['cb', 'data']], + parse_struct_signature('void (*cb)(const char*), const char* data')) end def test_struct_string @@ -179,6 +324,18 @@ def test_signature_function_pointer assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args end + def test_signature_variadic_arguments + unless Fiddle.const_defined?("TYPE_VARIADIC") + omit "libffi doesn't support variadic arguments" + end + assert_equal([ + "printf", + TYPE_INT, + [TYPE_VOIDP, TYPE_VARIADIC], + ], + parse_signature('int printf(const char *format, ...)')) + end + def test_signature_return_pointer func, ret, args = parse_signature('void* malloc(size_t)') assert_equal 'malloc', func diff --git a/ruby/test/fiddle/test_func.rb b/ruby/test/fiddle/test_func.rb index ca8917376..44893017e 100644 --- a/ruby/test/fiddle/test_func.rb +++ b/ruby/test/fiddle/test_func.rb @@ -15,7 +15,7 @@ def test_sinf begin f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT) rescue Fiddle::DLError - skip "libm may not have sinf()" + omit "libm may not have sinf()" end assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 end @@ -26,14 +26,13 @@ def test_sin end def test_string - stress, GC.stress = GC.stress, true - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff = +"000" - str = f.call(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - ensure - GC.stress = stress + under_gc_stress do + f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) + buff = +"000" + str = f.call(buff, "123") + assert_equal("123", buff) + assert_equal("123", str.to_s) + end end def test_isdigit @@ -76,8 +75,65 @@ def call(x, y) bug4929 = '[ruby-core:37395]' buff = "9341" - EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)} + under_gc_stress do + qsort.call(buff, buff.size, 1, cb) + end assert_equal("1349", buff, bug4929) end + + def test_snprintf + unless Fiddle.const_defined?("TYPE_VARIADIC") + omit "libffi doesn't support variadic arguments" + end + if Fiddle::WINDOWS + snprintf_name = "_snprintf" + else + snprintf_name = "snprintf" + end + begin + snprintf_pointer = @libc[snprintf_name] + rescue Fiddle::DLError + omit "Can't find #{snprintf_name}: #{$!.message}" + end + snprintf = Function.new(snprintf_pointer, + [ + :voidp, + :size_t, + :const_string, + :variadic, + ], + :int) + output_buffer = " " * 1024 + output = Pointer[output_buffer] + + written = snprintf.call(output, + output.size, + "int: %d, string: %.*s, const string: %s\n", + :int, -29, + :int, 4, + :voidp, "Hello", + :const_string, "World") + assert_equal("int: -29, string: Hell, const string: World\n", + output_buffer[0, written]) + + string_like_class = Class.new do + def initialize(string) + @string = string + end + + def to_str + @string + end + end + written = snprintf.call(output, + output.size, + "string: %.*s, const string: %s, uint: %u\n", + :int, 2, + :voidp, "Hello", + :const_string, string_like_class.new("World"), + :int, 29) + assert_equal("string: He, const string: World, uint: 29\n", + output_buffer[0, written]) + end end end if defined?(Fiddle) diff --git a/ruby/test/fiddle/test_function.rb b/ruby/test/fiddle/test_function.rb index a58d7afcb..8ac4f60aa 100644 --- a/ruby/test/fiddle/test_function.rb +++ b/ruby/test/fiddle/test_function.rb @@ -9,6 +9,10 @@ class TestFunction < Fiddle::TestCase def setup super Fiddle.last_error = nil + if WINDOWS + Fiddle.win32_last_error = nil + Fiddle.win32_last_socket_error = nil + end end def test_default_abi @@ -21,6 +25,17 @@ def test_name assert_equal 'sin', func.name end + def test_need_gvl? + libruby = Fiddle.dlopen(nil) + rb_str_dup = Function.new(libruby['rb_str_dup'], + [:voidp], + :voidp, + need_gvl: true) + assert(rb_str_dup.need_gvl?) + assert_equal('Hello', + Fiddle.dlunwrap(rb_str_dup.call(Fiddle.dlwrap('Hello')))) + end + def test_argument_errors assert_raise(TypeError) do Function.new(@libm['sin'], TYPE_DOUBLE, TYPE_DOUBLE) @@ -35,6 +50,25 @@ def test_argument_errors end end + def test_argument_type_conversion + type = Struct.new(:int, :call_count) do + def initialize(int) + super(int, 0) + end + def to_int + raise "exhausted" if (self.call_count += 1) > 1 + self.int + end + end + type_arg = type.new(TYPE_DOUBLE) + type_result = type.new(TYPE_DOUBLE) + assert_nothing_raised(RuntimeError) do + Function.new(@libm['sin'], [type_arg], type_result) + end + assert_equal(1, type_arg.call_count) + assert_equal(1, type_result.call_count) + end + def test_call func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) assert_in_delta 1.0, func.call(90 * Math::PI / 180), 0.0001 @@ -64,6 +98,30 @@ def test_last_error refute_nil Fiddle.last_error end + if WINDOWS + def test_win32_last_error + kernel32 = Fiddle.dlopen("kernel32") + args = [kernel32["SetLastError"], [-TYPE_LONG], TYPE_VOID] + args << Function::STDCALL if Function.const_defined?(:STDCALL) + set_last_error = Function.new(*args) + assert_nil(Fiddle.win32_last_error) + n = 1 << 29 | 1 + set_last_error.call(n) + assert_equal(n, Fiddle.win32_last_error) + end + + def test_win32_last_socket_error + ws2_32 = Fiddle.dlopen("ws2_32") + args = [ws2_32["WSASetLastError"], [TYPE_INT], TYPE_VOID] + args << Function::STDCALL if Function.const_defined?(:STDCALL) + wsa_set_last_error = Function.new(*args) + assert_nil(Fiddle.win32_last_socket_error) + n = 1 << 29 | 1 + wsa_set_last_error.call(n) + assert_equal(n, Fiddle.win32_last_socket_error) + end + end + def test_strcpy f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) buff = +"000" @@ -72,6 +130,30 @@ def test_strcpy assert_equal("123", str.to_s) end + def call_proc(string_to_copy) + buff = +"000" + str = yield(buff, string_to_copy) + [buff, str] + end + + def test_function_as_proc + f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) + buff, str = call_proc("123", &f) + assert_equal("123", buff) + assert_equal("123", str.to_s) + end + + def test_function_as_method + f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) + klass = Class.new do + define_singleton_method(:strcpy, &f) + end + buff = +"000" + str = klass.strcpy(buff, "123") + assert_equal("123", buff) + assert_equal("123", str.to_s) + end + def test_nogvl_poll # XXX hack to quiet down CI errors on EINTR from r64353 # [ruby-core:88360] [Misc #14937] @@ -82,7 +164,7 @@ def test_nogvl_poll begin poll = @libc['poll'] rescue Fiddle::DLError - skip 'poll(2) not available' + omit 'poll(2) not available' end f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT) @@ -98,9 +180,37 @@ def test_nogvl_poll end def test_no_memory_leak - prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"' - code = 'begin r.call(a); rescue TypeError; end' - assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2) + if respond_to?(:assert_nothing_leaked_memory) + rb_obj_frozen_p_symbol = Fiddle.dlopen(nil)["rb_obj_frozen_p"] + rb_obj_frozen_p = Fiddle::Function.new(rb_obj_frozen_p_symbol, + [Fiddle::TYPE_UINTPTR_T], + Fiddle::TYPE_UINTPTR_T) + a = "a" + n_tries = 100_000 + n_tries.times do + begin + a + 1 + rescue TypeError + end + end + n_arguments = 1 + sizeof_fiddle_generic = Fiddle::SIZEOF_VOIDP # Rough + size_per_try = + (sizeof_fiddle_generic * n_arguments) + + (Fiddle::SIZEOF_VOIDP * (n_arguments + 1)) + assert_nothing_leaked_memory(size_per_try * n_tries) do + n_tries.times do + begin + rb_obj_frozen_p.call(a) + rescue TypeError + end + end + end + else + prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"' + code = 'begin r.call(a); rescue TypeError; end' + assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2) + end end private diff --git a/ruby/test/fiddle/test_handle.rb b/ruby/test/fiddle/test_handle.rb index 17f9c92a1..7e3ff9d84 100644 --- a/ruby/test/fiddle/test_handle.rb +++ b/ruby/test/fiddle/test_handle.rb @@ -13,6 +13,12 @@ def test_to_i assert_kind_of Integer, handle.to_i end + def test_to_ptr + handle = Fiddle::Handle.new(LIBC_SO) + ptr = handle.to_ptr + assert_equal ptr.to_i, handle.to_i + end + def test_static_sym_unknown assert_raise(DLError) { Fiddle::Handle.sym('fooo') } assert_raise(DLError) { Fiddle::Handle['fooo'] } @@ -106,6 +112,24 @@ def test_disable_close assert !handle.close_enabled?, 'close is enabled' end + def test_file_name + file_name = Handle.new(LIBC_SO).file_name + if file_name + assert_kind_of String, file_name + expected = [File.basename(LIBC_SO)] + begin + expected << File.basename(File.realpath(LIBC_SO, File.dirname(file_name))) + rescue Errno::ENOENT + end + basename = File.basename(file_name) + unless File::FNM_SYSCASE.zero? + basename.downcase! + expected.each(&:downcase!) + end + assert_include expected, basename + end + end + def test_NEXT begin # Linux / Darwin @@ -161,7 +185,16 @@ def test_dlerror end if /freebsd/=~ RUBY_PLATFORM def test_no_memory_leak - assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true) + if respond_to?(:assert_nothing_leaked_memory) + n_tries = 100_000 + assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do + n_tries.times do + Fiddle::Handle.allocate + end + end + else + assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true) + end end if /cygwin|mingw|mswin/ =~ RUBY_PLATFORM diff --git a/ruby/test/fiddle/test_import.rb b/ruby/test/fiddle/test_import.rb index 99294ea16..afa8df9e0 100644 --- a/ruby/test/fiddle/test_import.rb +++ b/ruby/test/fiddle/test_import.rb @@ -36,6 +36,29 @@ module LIBC "char c", "unsigned char buff[7]", ] + StructNestedStruct = struct [ + { + "vertices[2]" => { + position: ["float x", "float y", "float z"], + texcoord: ["float u", "float v"] + }, + object: ["int id", "void *user_data"], + }, + "int id" + ] + UnionNestedStruct = union [ + { + keyboard: [ + 'unsigned int state', + 'char key' + ], + mouse: [ + 'unsigned int button', + 'unsigned short x', + 'unsigned short y' + ] + } + ] CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2| f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID) @@ -54,25 +77,61 @@ def test_ensure_call_dlload assert_match(/call dlload before/, err.message) end + def test_struct_memory_access() + # check memory operations performed directly on struct + Fiddle::Importer.struct(['int id']).malloc(Fiddle::RUBY_FREE) do |my_struct| + my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT + assert_equal 0x01010101, my_struct.id + + my_struct.id = 0 + assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT] + end + end + + def test_struct_ptr_array_subscript_multiarg() + # check memory operations performed on struct#to_ptr + Fiddle::Importer.struct([ 'int x' ]).malloc(Fiddle::RUBY_FREE) do |struct| + ptr = struct.to_ptr + + struct.x = 0x02020202 + assert_equal("\x02".b * Fiddle::SIZEOF_INT, ptr[0, Fiddle::SIZEOF_INT]) + + ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT + assert_equal 0x01010101, struct.x + end + end + def test_malloc() - s1 = LIBC::Timeval.malloc() - s2 = LIBC::Timeval.malloc() - refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i) + LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s1| + LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s2| + refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i) + end + end end def test_sizeof() assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*")) assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct)) - assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct.malloc())) + LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |my_struct| + assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(my_struct)) + end assert_equal(SIZEOF_LONG_LONG, LIBC.sizeof("long long")) if defined?(SIZEOF_LONG_LONG) + assert_equal(LIBC::StructNestedStruct.size(), LIBC.sizeof(LIBC::StructNestedStruct)) end - Fiddle.constants.grep(/\ATYPE_(?!VOID\z)(.*)/) do + Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(.*)/) do type = $& - size = Fiddle.const_get("SIZEOF_#{$1}") - name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase + const_type_name = $1 + size = Fiddle.const_get("SIZEOF_#{const_type_name}") + if const_type_name == "CONST_STRING" + name = "const_string" + type_name = "const char*" + else + name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase + type_name = name + end define_method("test_sizeof_#{name}") do - assert_equal(size, Fiddle::Importer.sizeof(name), type) + assert_equal(size, Fiddle::Importer.sizeof(type_name), type) end end @@ -107,23 +166,292 @@ def test_value() assert_equal([0,1,2], ary.value) end + def test_struct_array_assignment() + Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc(Fiddle::RUBY_FREE) do |instance| + instance.stages[0] = 1024 + instance.stages[1] = 10 + instance.stages[2] = 100 + assert_equal 1024, instance.stages[0] + assert_equal 10, instance.stages[1] + assert_equal 100, instance.stages[2] + assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3), + instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT] + assert_raise(IndexError) { instance.stages[-1] = 5 } + assert_raise(IndexError) { instance.stages[3] = 5 } + end + end + + def test_nested_struct_reusing_other_structs() + position_struct = Fiddle::Importer.struct(['float x', 'float y', 'float z']) + texcoord_struct = Fiddle::Importer.struct(['float u', 'float v']) + vertex_struct = Fiddle::Importer.struct(position: position_struct, texcoord: texcoord_struct) + mesh_struct = Fiddle::Importer.struct([ + { + "vertices[2]" => vertex_struct, + object: [ + "int id", + "void *user_data", + ], + }, + "int id", + ]) + assert_equal LIBC::StructNestedStruct.size, mesh_struct.size + + + keyboard_event_struct = Fiddle::Importer.struct(['unsigned int state', 'char key']) + mouse_event_struct = Fiddle::Importer.struct(['unsigned int button', 'unsigned short x', 'unsigned short y']) + event_union = Fiddle::Importer.union([{ keboard: keyboard_event_struct, mouse: mouse_event_struct}]) + assert_equal LIBC::UnionNestedStruct.size, event_union.size + end + + def test_nested_struct_alignment_is_not_its_size() + inner = Fiddle::Importer.struct(['int x', 'int y', 'int z', 'int w']) + outer = Fiddle::Importer.struct(['char a', { 'nested' => inner }, 'char b']) + outer.malloc(Fiddle::RUBY_FREE) do |instance| + offset = instance.to_ptr.instance_variable_get(:"@offset") + assert_equal Fiddle::SIZEOF_INT * 5, offset.last + assert_equal Fiddle::SIZEOF_INT * 6, outer.size + assert_equal instance.to_ptr.size, outer.size + end + end + + def test_struct_nested_struct_members() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + Fiddle::Pointer.malloc(24, Fiddle::RUBY_FREE) do |user_data| + s.vertices[0].position.x = 1 + s.vertices[0].position.y = 2 + s.vertices[0].position.z = 3 + s.vertices[0].texcoord.u = 4 + s.vertices[0].texcoord.v = 5 + s.vertices[1].position.x = 6 + s.vertices[1].position.y = 7 + s.vertices[1].position.z = 8 + s.vertices[1].texcoord.u = 9 + s.vertices[1].texcoord.v = 10 + s.object.id = 100 + s.object.user_data = user_data + s.id = 101 + assert_equal({ + "vertices" => [ + { + "position" => { + "x" => 1, + "y" => 2, + "z" => 3, + }, + "texcoord" => { + "u" => 4, + "v" => 5, + }, + }, + { + "position" => { + "x" => 6, + "y" => 7, + "z" => 8, + }, + "texcoord" => { + "u" => 9, + "v" => 10, + }, + }, + ], + "object" => { + "id" => 100, + "user_data" => user_data, + }, + "id" => 101, + }, + s.to_h) + end + end + end + + def test_union_nested_struct_members() + LIBC::UnionNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + s.keyboard.state = 100 + s.keyboard.key = 101 + assert_equal(100, s.mouse.button) + refute_equal( 0, s.mouse.x) + end + end + + def test_struct_nested_struct_replace_array_element() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + s.vertices[0].position.x = 5 + + vertex_struct = Fiddle::Importer.struct [{ + position: ["float x", "float y", "float z"], + texcoord: ["float u", "float v"] + }] + vertex_struct.malloc(Fiddle::RUBY_FREE) do |vertex| + vertex.position.x = 100 + s.vertices[0] = vertex + + # make sure element was copied by value, but things like memory address + # should not be changed + assert_equal(100, s.vertices[0].position.x) + refute_equal(vertex.object_id, s.vertices[0].object_id) + refute_equal(vertex.to_ptr, s.vertices[0].to_ptr) + end + end + end + + def test_struct_nested_struct_replace_array_element_nil() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + s.vertices[0].position.x = 5 + s.vertices[0] = nil + assert_equal({ + "position" => { + "x" => 0.0, + "y" => 0.0, + "z" => 0.0, + }, + "texcoord" => { + "u" => 0.0, + "v" => 0.0, + }, + }, + s.vertices[0].to_h) + end + end + + def test_struct_nested_struct_replace_array_element_hash() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + s.vertices[0] = { + position: { + x: 10, + y: 100, + } + } + assert_equal({ + "position" => { + "x" => 10.0, + "y" => 100.0, + "z" => 0.0, + }, + "texcoord" => { + "u" => 0.0, + "v" => 0.0, + }, + }, + s.vertices[0].to_h) + end + end + + def test_struct_nested_struct_replace_entire_array() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + vertex_struct = Fiddle::Importer.struct [{ + position: ["float x", "float y", "float z"], + texcoord: ["float u", "float v"] + }] + + vertex_struct.malloc(Fiddle::RUBY_FREE) do |same0| + vertex_struct.malloc(Fiddle::RUBY_FREE) do |same1| + same = [same0, same1] + same[0].position.x = 1; same[1].position.x = 6 + same[0].position.y = 2; same[1].position.y = 7 + same[0].position.z = 3; same[1].position.z = 8 + same[0].texcoord.u = 4; same[1].texcoord.u = 9 + same[0].texcoord.v = 5; same[1].texcoord.v = 10 + s.vertices = same + assert_equal([ + { + "position" => { + "x" => 1.0, + "y" => 2.0, + "z" => 3.0, + }, + "texcoord" => { + "u" => 4.0, + "v" => 5.0, + }, + }, + { + "position" => { + "x" => 6.0, + "y" => 7.0, + "z" => 8.0, + }, + "texcoord" => { + "u" => 9.0, + "v" => 10.0, + }, + } + ], + s.vertices.collect(&:to_h)) + end + end + end + end + + def test_struct_nested_struct_replace_entire_array_with_different_struct() + LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| + different_struct_same_size = Fiddle::Importer.struct [{ + a: ['float i', 'float j', 'float k'], + b: ['float l', 'float m'] + }] + + different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different0| + different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different1| + different = [different0, different1] + different[0].a.i = 11; different[1].a.i = 16 + different[0].a.j = 12; different[1].a.j = 17 + different[0].a.k = 13; different[1].a.k = 18 + different[0].b.l = 14; different[1].b.l = 19 + different[0].b.m = 15; different[1].b.m = 20 + s.vertices[0][0, s.vertices[0].class.size] = different[0].to_ptr + s.vertices[1][0, s.vertices[1].class.size] = different[1].to_ptr + assert_equal([ + { + "position" => { + "x" => 11.0, + "y" => 12.0, + "z" => 13.0, + }, + "texcoord" => { + "u" => 14.0, + "v" => 15.0, + }, + }, + { + "position" => { + "x" => 16.0, + "y" => 17.0, + "z" => 18.0, + }, + "texcoord" => { + "u" => 19.0, + "v" => 20.0, + }, + } + ], + s.vertices.collect(&:to_h)) + end + end + end + end + def test_struct() - s = LIBC::MyStruct.malloc() - s.num = [0,1,2,3,4] - s.c = ?a.ord - s.buff = "012345\377" - assert_equal([0,1,2,3,4], s.num) - assert_equal(?a.ord, s.c) - assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff) + LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |s| + s.num = [0,1,2,3,4] + s.c = ?a.ord + s.buff = "012345\377" + assert_equal([0,1,2,3,4], s.num) + assert_equal(?a.ord, s.c) + assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff) + end end def test_gettimeofday() if( defined?(LIBC.gettimeofday) ) - timeval = LIBC::Timeval.malloc() - timezone = LIBC::Timezone.malloc() - LIBC.gettimeofday(timeval, timezone) - cur = Time.now() - assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i) + LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |timeval| + LIBC::Timezone.malloc(Fiddle::RUBY_FREE) do |timezone| + LIBC.gettimeofday(timeval, timezone) + end + cur = Time.now() + assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i) + end end end @@ -147,9 +475,5 @@ def test_atof r = LIBC.atof("12.34") assert_includes(12.00..13.00, r) end - - def test_no_message_with_debug - assert_in_out_err(%w[--debug --disable=gems -rfiddle/import], 'p Fiddle::Importer', ['Fiddle::Importer']) - end end end if defined?(Fiddle) diff --git a/ruby/test/fiddle/test_memory_view.rb b/ruby/test/fiddle/test_memory_view.rb new file mode 100644 index 000000000..240cda37d --- /dev/null +++ b/ruby/test/fiddle/test_memory_view.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true +begin + require_relative 'helper' +rescue LoadError + return +end + +begin + require '-test-/memory_view' +rescue LoadError + return +end + +module Fiddle + class TestMemoryView < TestCase + def setup + omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView + end + + def test_null_ptr + assert_raise(ArgumentError) do + MemoryView.new(Fiddle::NULL) + end + end + + def test_memory_view_from_unsupported_obj + obj = Object.new + assert_raise(ArgumentError) do + MemoryView.new(obj) + end + end + + def test_memory_view_from_pointer + str = Marshal.load(Marshal.dump("hello world")) + ptr = Pointer[str] + mview = MemoryView.new(ptr) + assert_same(ptr, mview.obj) + assert_equal(str.bytesize, mview.byte_size) + assert_equal(true, mview.readonly?) + assert_equal(nil, mview.format) + assert_equal(1, mview.item_size) + assert_equal(1, mview.ndim) + assert_equal(nil, mview.shape) + assert_equal(nil, mview.strides) + assert_equal(nil, mview.sub_offsets) + + codes = str.codepoints + assert_equal(codes, (0...str.bytesize).map {|i| mview[i] }) + end + + def test_memory_view_multi_dimensional + omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils + + buf = [ 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12 ].pack("l!*") + shape = [3, 4] + md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil) + mview = Fiddle::MemoryView.new(md) + assert_equal(buf.bytesize, mview.byte_size) + assert_equal("l!", mview.format) + assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) + assert_equal(2, mview.ndim) + assert_equal(shape, mview.shape) + assert_equal([Fiddle::SIZEOF_LONG*4, Fiddle::SIZEOF_LONG], mview.strides) + assert_equal(nil, mview.sub_offsets) + assert_equal(1, mview[0, 0]) + assert_equal(4, mview[0, 3]) + assert_equal(6, mview[1, 1]) + assert_equal(10, mview[2, 1]) + end + + def test_memory_view_multi_dimensional_with_strides + omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils + + buf = [ 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*") + shape = [2, 8] + strides = [4*Fiddle::SIZEOF_LONG*2, Fiddle::SIZEOF_LONG*2] + md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, strides) + mview = Fiddle::MemoryView.new(md) + assert_equal("l!", mview.format) + assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) + assert_equal(buf.bytesize, mview.byte_size) + assert_equal(2, mview.ndim) + assert_equal(shape, mview.shape) + assert_equal(strides, mview.strides) + assert_equal(nil, mview.sub_offsets) + assert_equal(1, mview[0, 0]) + assert_equal(5, mview[0, 2]) + assert_equal(9, mview[1, 0]) + assert_equal(15, mview[1, 3]) + end + + def test_memory_view_multi_dimensional_with_multiple_members + omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils + + buf = [ 1, 2, 3, 4, 5, 6, 7, 8, + -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") + shape = [2, 4] + strides = [4*Fiddle::SIZEOF_SHORT*2, Fiddle::SIZEOF_SHORT*2] + md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) + mview = Fiddle::MemoryView.new(md) + assert_equal("ss", mview.format) + assert_equal(Fiddle::SIZEOF_SHORT*2, mview.item_size) + assert_equal(buf.bytesize, mview.byte_size) + assert_equal(2, mview.ndim) + assert_equal(shape, mview.shape) + assert_equal(strides, mview.strides) + assert_equal(nil, mview.sub_offsets) + assert_equal([1, 2], mview[0, 0]) + assert_equal([5, 6], mview[0, 2]) + assert_equal([-1, -2], mview[1, 0]) + assert_equal([-7, -8], mview[1, 3]) + end + + def test_export + str = "hello world" + mview_str = MemoryView.export(Pointer[str]) do |mview| + mview.to_s + end + assert_equal(str, mview_str) + end + + def test_release + ptr = Pointer["hello world"] + mview = MemoryView.new(ptr) + assert_same(ptr, mview.obj) + mview.release + assert_nil(mview.obj) + end + + def test_to_s + # U+3042 HIRAGANA LETTER A + data = "\u{3042}" + ptr = Pointer[data] + mview = MemoryView.new(ptr) + string = mview.to_s + assert_equal([data.b, true], + [string, string.frozen?]) + end + end +end diff --git a/ruby/test/fiddle/test_pinned.rb b/ruby/test/fiddle/test_pinned.rb new file mode 100644 index 000000000..f0d375b1c --- /dev/null +++ b/ruby/test/fiddle/test_pinned.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true +begin + require_relative 'helper' +rescue LoadError + return +end + +module Fiddle + class TestPinned < Fiddle::TestCase + def test_pin_object + x = Object.new + pinner = Pinned.new x + assert_same x, pinner.ref + end + + def test_clear + pinner = Pinned.new Object.new + refute pinner.cleared? + pinner.clear + assert pinner.cleared? + ex = assert_raise(Fiddle::ClearedReferenceError) do + pinner.ref + end + assert_match "called on", ex.message + end + end +end + diff --git a/ruby/test/fiddle/test_pointer.rb b/ruby/test/fiddle/test_pointer.rb index 5581c1dea..7d708ee41 100644 --- a/ruby/test/fiddle/test_pointer.rb +++ b/ruby/test/fiddle/test_pointer.rb @@ -32,6 +32,31 @@ def test_malloc_free_func assert_equal free.to_i, ptr.free.to_i end + def test_malloc_block + escaped_ptr = nil + returned = Pointer.malloc(10, Fiddle::RUBY_FREE) do |ptr| + assert_equal 10, ptr.size + assert_equal Fiddle::RUBY_FREE, ptr.free.to_i + escaped_ptr = ptr + :returned + end + assert_equal :returned, returned + assert escaped_ptr.freed? + end + + def test_malloc_block_no_free + assert_raise ArgumentError do + Pointer.malloc(10) { |ptr| } + end + end + + def test_malloc_subclass + subclass = Class.new(Pointer) + subclass.malloc(10, Fiddle::RUBY_FREE) do |ptr| + assert ptr.is_a?(subclass) + end + end + def test_to_str str = Marshal.load(Marshal.dump("hello world")) ptr = Pointer[str] @@ -84,17 +109,18 @@ def test_to_ptr_string end def test_to_ptr_io - buf = Pointer.malloc(10) - File.open(__FILE__, 'r') do |f| - ptr = Pointer.to_ptr f - fread = Function.new(@libc['fread'], - [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP], - TYPE_INT) - fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i) - end - - File.open(__FILE__, 'r') do |f| - assert_equal f.read(9), buf.to_s + Pointer.malloc(10, Fiddle::RUBY_FREE) do |buf| + File.open(__FILE__, 'r') do |f| + ptr = Pointer.to_ptr f + fread = Function.new(@libc['fread'], + [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP], + TYPE_INT) + fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i) + end + + File.open(__FILE__, 'r') do |f| + assert_equal f.read(9), buf.to_s + end end end @@ -145,20 +171,14 @@ def test_to_value def test_free ptr = Pointer.malloc(4) - assert_nil ptr.free + begin + assert_nil ptr.free + ensure + Fiddle.free ptr + end end def test_free= - assert_normal_exit(<<-"End", '[ruby-dev:39269]') - require 'fiddle' - include Fiddle - free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - ptr = Fiddle::Pointer.malloc(4) - ptr.free = free - free.ptr - ptr.free.ptr - End - free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) ptr = Pointer.malloc(4) ptr.free = free @@ -166,22 +186,49 @@ def test_free= assert_equal free.ptr, ptr.free.ptr end + def test_free_with_func + ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) + refute ptr.freed? + ptr.call_free + assert ptr.freed? + ptr.call_free # you can safely run it again + assert ptr.freed? + GC.start # you can safely run the GC routine + assert ptr.freed? + end + + def test_free_with_no_func + ptr = Pointer.malloc(4) + refute ptr.freed? + ptr.call_free + refute ptr.freed? + ptr.call_free # you can safely run it again + refute ptr.freed? + end + + def test_freed? + ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) + refute ptr.freed? + ptr.call_free + assert ptr.freed? + end + def test_null? ptr = Pointer.new(0) assert ptr.null? end def test_size - ptr = Pointer.malloc(4) - assert_equal 4, ptr.size - Fiddle.free ptr.to_i + Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| + assert_equal 4, ptr.size + end end def test_size= - ptr = Pointer.malloc(4) - ptr.size = 10 - assert_equal 10, ptr.size - Fiddle.free ptr.to_i + Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| + ptr.size = 10 + assert_equal 10, ptr.size + end end def test_aref_aset @@ -225,7 +272,16 @@ def test_null_pointer end def test_no_memory_leak - assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true) + if respond_to?(:assert_nothing_leaked_memory) + n_tries = 100_000 + assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do + n_tries.times do + Fiddle::Pointer.allocate + end + end + else + assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true) + end end end end if defined?(Fiddle) diff --git a/ruby/test/fileutils/test_fileutils.rb b/ruby/test/fileutils/test_fileutils.rb index ca435ed1f..36b5d6ef5 100644 --- a/ruby/test/fileutils/test_fileutils.rb +++ b/ruby/test/fileutils/test_fileutils.rb @@ -51,7 +51,11 @@ def have_symlink? end def check_have_symlink? - File.symlink "", "" + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + File.symlink "symlink", "symlink" + end + end rescue NotImplementedError, Errno::EACCES return false rescue @@ -68,8 +72,13 @@ def have_hardlink? end def check_have_hardlink? - File.link nil, nil - rescue NotImplementedError + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + File.write "dummy", "dummy" + File.link "dummy", "hardlink" + end + end + rescue NotImplementedError, Errno::EACCES return false rescue return true @@ -233,7 +242,7 @@ def each_srcdest # def test_assert_output_lines - assert_raise(MiniTest::Assertion) { + assert_raise(Test::Unit::AssertionFailedError) { Timeout.timeout(0.5) { assert_output_lines([]) { Thread.current.report_on_exception = false @@ -741,6 +750,34 @@ def test_rm_r_pathname assert_file_not_exist 'tmp/tmpdir3' end + def test_remove_entry_cjk_path + dir = "tmpdir\u3042" + my_rm_rf dir + + Dir.mkdir dir + File.write("#{dir}/\u3042.txt", "test_remove_entry_cjk_path") + + remove_entry dir + assert_file_not_exist dir + end + + def test_remove_entry_multibyte_path + c = "\u00a7" + begin + c = c.encode('filesystem') + rescue EncodingError + c = c.b + end + dir = "tmpdir#{c}" + my_rm_rf dir + + Dir.mkdir dir + File.write("#{dir}/#{c}.txt", "test_remove_entry_multibyte_path") + + remove_entry dir + assert_file_not_exist dir + end + def test_remove_entry_secure check_singleton :remove_entry_secure @@ -1182,6 +1219,8 @@ def test_install_mode_option assert_filemode 04500, 'tmp/j' install 'tmp/j', 'tmp/k', :mode => "+s" assert_filemode 06500, 'tmp/k' + install 'tmp/a', 'tmp/l', :mode => "o+X" + assert_equal_filemode 'tmp/a', 'tmp/l' end if have_file_perm? def test_chmod @@ -1709,16 +1748,16 @@ def test_chdir_verbose_frozen o.extend(FileUtils) o.singleton_class.send(:public, :chdir) o.freeze - orig_stderr = $stderr - $stderr = StringIO.new + orig_stdout = $stdout + $stdout = StringIO.new o.chdir('.', verbose: true){} - $stderr.rewind - assert_equal(<<-END, $stderr.read) + $stdout.rewind + assert_equal(<<-END, $stdout.read) cd . cd - END ensure - $stderr = orig_stderr if orig_stderr + $stdout = orig_stdout if orig_stdout end def test_getwd diff --git a/ruby/test/fixtures/fake_sorted_set_gem/sorted_set.rb b/ruby/test/fixtures/fake_sorted_set_gem/sorted_set.rb new file mode 100644 index 000000000..f45a76630 --- /dev/null +++ b/ruby/test/fixtures/fake_sorted_set_gem/sorted_set.rb @@ -0,0 +1,9 @@ +Object.instance_exec do + # Remove the constant to cancel autoload that would be fired by + # `class SortedSet` and cause circular require. + remove_const :SortedSet if const_defined?(:SortedSet) +end + +class SortedSet < Set + # ... +end diff --git a/ruby/test/gdbm/test_gdbm.rb b/ruby/test/gdbm/test_gdbm.rb deleted file mode 100644 index 64692a446..000000000 --- a/ruby/test/gdbm/test_gdbm.rb +++ /dev/null @@ -1,734 +0,0 @@ -# frozen_string_literal: false -begin - require 'gdbm' -rescue LoadError -end - -if defined? GDBM - require 'test/unit' - require 'envutil' unless defined?(EnvUtil) - require 'tmpdir' - require 'fileutils' - - class TestGDBM_RDONLY < Test::Unit::TestCase - def TestGDBM_RDONLY.uname_s - require 'rbconfig' - case RbConfig::CONFIG['target_os'] - when 'cygwin' - require 'etc' - Etc.uname[:sysname] - else - RbConfig::CONFIG['target_os'] - end - end - SYSTEM = uname_s - - def setup - @tmpdir = Dir.mktmpdir("tmptest_gdbm") - @prefix = "tmptest_gdbm_#{$$}" - @path = "#{@tmpdir}/#{@prefix}_" - - # prepare to make readonly GDBM file - GDBM.open("#{@tmpdir}/#{@prefix}_rdonly", 0400) {|gdbm| - gdbm['foo'] = 'FOO' - } - assert_instance_of(GDBM, @gdbm_rdonly = GDBM.new("#{@tmpdir}/#{@prefix}_rdonly", nil)) - end - def teardown - assert_nil(@gdbm_rdonly.close) - ObjectSpace.each_object(GDBM) do |obj| - obj.close unless obj.closed? - end - FileUtils.remove_entry_secure @tmpdir - end - - def test_delete_rdonly - skip("skipped because root can open anything") if Process.uid == 0 - - if /^CYGWIN_9/ !~ SYSTEM - assert_raise(GDBMError) { - @gdbm_rdonly.delete("foo") - } - - assert_nil(@gdbm_rdonly.delete("bar")) - end - end - end - - class TestGDBM < Test::Unit::TestCase - SYSTEM = TestGDBM_RDONLY::SYSTEM - - def setup - @tmpdir = Dir.mktmpdir("tmptest_gdbm") - @prefix = "tmptest_gdbm_#{$$}" - @path = "#{@tmpdir}/#{@prefix}_" - assert_instance_of(GDBM, @gdbm = GDBM.new(@path)) - end - def teardown - assert_nil(@gdbm.close) - ObjectSpace.each_object(GDBM) do |obj| - obj.close unless obj.closed? - end - begin - FileUtils.remove_entry_secure @tmpdir - rescue - system("fuser", *Dir.entries(@tmpdir).grep(/\A(?!\.\.?\z)/), chdir: @tmpdir) - else - return - end - FileUtils.remove_entry_secure @tmpdir - end - - def check_size(expect, gdbm=@gdbm) - assert_equal(expect, gdbm.size) - n = 0 - gdbm.each { n+=1 } - assert_equal(expect, n) - if expect == 0 - assert_equal(true, gdbm.empty?) - else - assert_equal(false, gdbm.empty?) - end - end - - def test_s_new_has_no_block - # GDBM.new ignore the block - foo = true - assert_instance_of(GDBM, gdbm = GDBM.new("#{@tmpdir}/#{@prefix}") { foo = false }) - assert_equal(foo, true) - assert_nil(gdbm.close) - end - def test_s_open_create_new - return if /^CYGWIN_9/ =~ SYSTEM - - save_mask = File.umask(0) - begin - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}")) - gdbm.close - assert_equal(File.stat("#{@tmpdir}/#{@prefix}").mode & 0777, 0666) unless /mswin|mingw/ =~ RUBY_PLATFORM - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}2", 0644)) - gdbm.close - assert_equal(File.stat("#{@tmpdir}/#{@prefix}2").mode & 0777, 0644) - ensure - File.umask save_mask - end - end - def test_s_open_no_create - skip "gdbm_open(GDBM_WRITER) is broken on libgdbm 1.8.0" if /1\.8\.0/ =~ GDBM::VERSION - assert_nil(gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", nil)) - ensure - gdbm.close if gdbm - end - def test_s_open_3rd_arg - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644, - GDBM::FAST)) - gdbm.close - - # gdbm 1.8.0 specific - if defined? GDBM::SYNC - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644, - GDBM::SYNC)) - gdbm.close - end - # gdbm 1.8.0 specific - if defined? GDBM::NOLOCK - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644, - GDBM::NOLOCK)) - gdbm.close - end - end - def test_s_open_with_block - assert_equal(GDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo) - end - - def open_db_child(dbname, *opts) - opts = [0644, *opts].map(&:inspect).join(', ') - args = [EnvUtil.rubybin, "-rgdbm", "-e", <<-SRC, dbname] - STDOUT.sync = true - gdbm = GDBM.open(ARGV.shift, #{opts}) - puts gdbm.class - gets - SRC - IO.popen(args, "r+") do |f| - dbclass = f.gets - assert_equal("GDBM", dbclass.chomp) - yield - end - end - - def test_s_open_lock - skip "GDBM.open would block when opening already locked gdbm file on platforms without flock and with lockf" if /solaris|aix/ =~ RUBY_PLATFORM - - dbname = "#{@tmpdir}/#{@prefix}" - - open_db_child(dbname) do - assert_raise(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) { - GDBM.open(dbname, 0644) {|gdbm| - assert(false) - } - } - end - end - -=begin - # Is it guaranteed on many OS? - def test_s_open_lock_one_process - # locking on one process - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644)) - assert_raise(Errno::EWOULDBLOCK) { - begin - GDBM.open("#{@tmpdir}/#{@prefix}", 0644) - rescue Errno::EAGAIN - raise Errno::EWOULDBLOCK - end - } - end -=end - - def test_s_open_nolock - dbname = "#{@tmpdir}/#{@prefix}" - - open_db_child(dbname, GDBM::NOLOCK) do - assert_nothing_raised(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) { - GDBM.open(dbname, 0644) {|gdbm2| - assert_instance_of(GDBM, gdbm2) - } - } - end - - STDERR.puts Dir.glob("#{dbname}*") if $DEBUG - - # The following test fails on Windows because flock() implementation - # is different from Unix. - return if /mswin|mingw/ =~ RUBY_PLATFORM - - open_db_child(dbname) do - assert_nothing_raised(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) { - # this test is failed on Cygwin98 (???) - GDBM.open(dbname, 0644, GDBM::NOLOCK) {|gdbm2| - assert_instance_of(GDBM, gdbm2) - } - } - end - end if defined? GDBM::NOLOCK # gdbm 1.8.0 specific - - def test_s_open_error - skip "because root can open anything" if Process.uid == 0 - - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0)) - assert_raise(Errno::EACCES, Errno::EWOULDBLOCK) { - GDBM.open("#{@tmpdir}/#{@prefix}", 0) - } - gdbm.close - end - - def test_close - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}")) - assert_nil(gdbm.close) - - # closed GDBM file - assert_raise(RuntimeError) { gdbm.close } - end - - def test_aref - assert_equal('bar', @gdbm['foo'] = 'bar') - assert_equal('bar', @gdbm['foo']) - - assert_nil(@gdbm['bar']) - end - - def test_fetch - assert_equal('bar', @gdbm['foo']='bar') - assert_equal('bar', @gdbm.fetch('foo')) - - # key not found - assert_raise(IndexError) { - @gdbm.fetch('bar') - } - - # test for `ifnone' arg - assert_equal('baz', @gdbm.fetch('bar', 'baz')) - - # test for `ifnone' block - assert_equal('foobar', @gdbm.fetch('bar') {|key| 'foo' + key }) - end - - def test_aset - num = 0 - 2.times {|i| - assert_equal('foo', @gdbm['foo'] = 'foo') - assert_equal('foo', @gdbm['foo']) - assert_equal('bar', @gdbm['foo'] = 'bar') - assert_equal('bar', @gdbm['foo']) - - num += 1 if i == 0 - assert_equal(num, @gdbm.size) - - # assign nil - assert_equal('', @gdbm['bar'] = '') - assert_equal('', @gdbm['bar']) - - num += 1 if i == 0 - assert_equal(num, @gdbm.size) - - # empty string - assert_equal('', @gdbm[''] = '') - assert_equal('', @gdbm['']) - - num += 1 if i == 0 - assert_equal(num, @gdbm.size) - - # Integer - assert_equal('200', @gdbm['100'] = '200') - assert_equal('200', @gdbm['100']) - - num += 1 if i == 0 - assert_equal(num, @gdbm.size) - - # Big key and value - assert_equal('y' * 100, @gdbm['x' * 100] = 'y' * 100) - assert_equal('y' * 100, @gdbm['x' * 100]) - - num += 1 if i == 0 - assert_equal(num, @gdbm.size) - } - end - - def test_key - assert_equal('bar', @gdbm['foo'] = 'bar') - assert_equal('foo', @gdbm.key('bar')) - assert_nil(@gdbm['bar']) - end - - def test_values_at - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - assert_equal(values.reverse, @gdbm.values_at(*keys.reverse)) - end - - def test_select_with_block - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - ret = @gdbm.select {|k,v| - assert_equal(k.upcase, v) - k != "bar" - } - assert_equal([['baz', 'BAZ'], ['foo', 'FOO']], - ret.sort) - end - - def test_length - num = 10 - assert_equal(0, @gdbm.size) - num.times {|i| - i = i.to_s - @gdbm[i] = i - } - assert_equal(num, @gdbm.size) - - @gdbm.shift - - assert_equal(num - 1, @gdbm.size) - end - - def test_empty? - assert_equal(true, @gdbm.empty?) - @gdbm['foo'] = 'FOO' - assert_equal(false, @gdbm.empty?) - end - - def test_each_pair - n = 0 - @gdbm.each_pair { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - n = 0 - ret = @gdbm.each_pair {|key, val| - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@gdbm, ret) - end - - def test_each_value - n = 0 - @gdbm.each_value { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - n = 0 - ret = @gdbm.each_value {|val| - assert_not_nil(key = @gdbm.key(val)) - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@gdbm, ret) - end - - def test_each_key - n = 0 - @gdbm.each_key { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - n = 0 - ret = @gdbm.each_key {|key| - assert_not_nil(i = keys.index(key)) - assert_equal(@gdbm[key], values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@gdbm, ret) - end - - def test_each_key_without_block - assert_kind_of Enumerator, @gdbm.each_key - end - - def test_keys - assert_equal([], @gdbm.keys) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - assert_equal(keys.sort, @gdbm.keys.sort) - assert_equal(values.sort, @gdbm.values.sort) - end - - def test_values - test_keys - end - - def test_shift - assert_nil(@gdbm.shift) - assert_equal(0, @gdbm.size) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - ret_keys = [] - ret_values = [] - while ret = @gdbm.shift - ret_keys.push ret[0] - ret_values.push ret[1] - - assert_equal(keys.size - ret_keys.size, @gdbm.size) - end - - assert_equal(keys.sort, ret_keys.sort) - assert_equal(values.sort, ret_values.sort) - end - - def test_delete - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - key = keys[1] - - assert_nil(@gdbm.delete(key)) - assert_equal(0, @gdbm.size) - - @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values - - assert_equal('BAR', @gdbm.delete(key)) - assert_nil(@gdbm[key]) - assert_equal(2, @gdbm.size) - - assert_nil(@gdbm.delete(key)) - end - - def test_delete_with_block - key = 'no called block' - @gdbm[key] = 'foo' - assert_equal('foo', @gdbm.delete(key) {|k| k.replace 'called block'}) - assert_equal('no called block', key) - assert_equal(0, @gdbm.size) - - key = 'no called block' - assert_equal(:blockval, - @gdbm.delete(key) {|k| k.replace 'called block'; :blockval}) - assert_equal('called block', key) - assert_equal(0, @gdbm.size) - end - - def test_delete_if - v = "0" - 100.times {@gdbm[v] = v; v = v.next} - - ret = @gdbm.delete_if {|key, val| key.to_i < 50} - assert_equal(@gdbm, ret) - check_size(50, @gdbm) - - ret = @gdbm.delete_if {|key, val| key.to_i >= 50} - assert_equal(@gdbm, ret) - check_size(0, @gdbm) - - # break - v = "0" - 100.times {@gdbm[v] = v; v = v.next} - check_size(100, @gdbm) - n = 0; - @gdbm.delete_if {|key, val| - break if n > 50 - n+=1 - true - } - assert_equal(51, n) - check_size(49, @gdbm) - - @gdbm.clear - - # raise - v = "0" - 100.times {@gdbm[v] = v; v = v.next} - check_size(100, @gdbm) - n = 0; - begin - @gdbm.delete_if {|key, val| - raise "runtime error" if n > 50 - n+=1 - true - } - rescue RuntimeError - end - assert_equal(51, n) - check_size(49, @gdbm) - end - - def test_reject - v = "0" - 100.times {@gdbm[v] = v; v = v.next} - - hash = @gdbm.reject {|key, val| key.to_i < 50} - assert_instance_of(Hash, hash) - assert_equal(100, @gdbm.size) - - assert_equal(50, hash.size) - hash.each_pair {|key,val| - assert_equal(false, key.to_i < 50) - assert_equal(key, val) - } - - hash = @gdbm.reject {|key, val| key.to_i < 100} - assert_instance_of(Hash, hash) - assert_equal(true, hash.empty?) - end - - def test_clear - v = "1" - 100.times {v = v.next; @gdbm[v] = v} - - assert_equal(@gdbm, @gdbm.clear) - - # validate GDBM#size - i = 0 - @gdbm.each { i += 1 } - assert_equal(@gdbm.size, i) - assert_equal(0, i) - end - - def test_invert - v = "0" - 100.times {@gdbm[v] = v; v = v.next} - - hash = @gdbm.invert - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_update - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @gdbm["101"] = "101" - @gdbm.update hash - assert_equal(101, @gdbm.size) - @gdbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_replace - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @gdbm["101"] = "101" - @gdbm.replace hash - assert_equal(100, @gdbm.size) - @gdbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_reorganize - size1 = File.size(@path) - i = "1" - 1000.times {i = i.next; @gdbm[i] = i} - @gdbm.clear - @gdbm.sync - - size2 = File.size(@path) - @gdbm.reorganize - @gdbm.sync - size3 = File.size(@path) - - # p [size1, size2, size3] - assert_equal(true, size1 < size2) - # this test is failed on Cygwin98. `GDBM version 1.8.0, as of May 19, 1999' - assert_equal(true, size3 < size2) - assert_equal(size1, size3) - end - - def test_sync - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0666, GDBM::FAST)) - assert_equal(gdbm.sync, gdbm) - gdbm.close - assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0666)) - assert_equal(gdbm.sync, gdbm) - gdbm.close - end - - def test_cachesize= - assert_equal(@gdbm.cachesize = 1024, 1024) - end - - def test_fastmode= - assert_equal(@gdbm.fastmode = true, true) - end - - def test_syncmode= - assert_equal(@gdbm.syncmode = true, true) - end - - def test_haskey? - assert_equal('bar', @gdbm['foo']='bar') - assert_equal(true, @gdbm.has_key?('foo')) - assert_equal(false, @gdbm.has_key?('bar')) - end - - def test_has_value? - assert_equal('bar', @gdbm['foo']='bar') - assert_equal(true, @gdbm.has_value?('bar')) - assert_equal(false, @gdbm.has_value?('foo')) - end - - def test_to_a - v = "0" - 100.times {v = v.next; @gdbm[v] = v} - - ary = @gdbm.to_a - assert_instance_of(Array, ary) - assert_equal(100, ary.size) - ary.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_to_hash - v = "0" - 100.times {v = v.next; @gdbm[v] = v} - - hash = @gdbm.to_hash - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - end - - class TestGDBM2 < Test::Unit::TestCase - def setup - @tmproot = Dir.mktmpdir('ruby-gdbm') - end - - def teardown - FileUtils.remove_entry_secure @tmproot if File.directory?(@tmproot) - end - - def test_reader_open_notexist - assert_raise(Errno::ENOENT) { - GDBM.open("#{@tmproot}/a", 0666, GDBM::READER) - } - end - - def test_writer_open_notexist - skip "gdbm_open(GDBM_WRITER) is broken on libgdbm 1.8.0" if /1\.8\.0/ =~ GDBM::VERSION - - assert_raise(Errno::ENOENT) { - GDBM.open("#{@tmproot}/a", 0666, GDBM::WRITER) - } - end - - def test_wrcreat_open_notexist - v = GDBM.open("#{@tmproot}/a", 0666, GDBM::WRCREAT) - assert_instance_of(GDBM, v) - v.close - end - - def test_newdb_open_notexist - v = GDBM.open("#{@tmproot}/a", 0666, GDBM::NEWDB) - assert_instance_of(GDBM, v) - v.close - end - - def test_reader_open - GDBM.open("#{@tmproot}/a.dbm") {} # create a db. - v = GDBM.open("#{@tmproot}/a.dbm", nil, GDBM::READER) {|d| - assert_raise(GDBMError) { d["k"] = "v" } - true - } - assert(v) - end - - def test_newdb_open - GDBM.open("#{@tmproot}/a.dbm") {|dbm| - dbm["k"] = "v" - } - v = GDBM.open("#{@tmproot}/a.dbm", nil, GDBM::NEWDB) {|d| - assert_equal(0, d.length) - assert_nil(d["k"]) - true - } - assert(v) - end - - def test_freeze - GDBM.open("#{@tmproot}/a.dbm") {|d| - d.freeze - expected_error = defined?(FrozenError) ? FrozenError : RuntimeError - assert_raise(expected_error) { d["k"] = "v" } - } - end - end -end diff --git a/ruby/test/io/console/test_io_console.rb b/ruby/test/io/console/test_io_console.rb index a02605dd1..3c29f9f2b 100644 --- a/ruby/test/io/console/test_io_console.rb +++ b/ruby/test/io/console/test_io_console.rb @@ -7,7 +7,13 @@ end class TestIO_Console < Test::Unit::TestCase - PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|/\w+\.rb)\z") {$`} + begin + PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`} + rescue Encoding::CompatibilityError + $stderr.puts "test_io_console.rb debug" + $LOADED_FEATURES.each{|path| $stderr.puts [path, path.encoding].inspect} + raise + end PATHS.uniq! # FreeBSD seems to hang on TTOU when running parallel tests @@ -29,6 +35,20 @@ def set_winsize_setup def set_winsize_teardown trap(:TTOU, @old_ttou) if defined?(@old_ttou) and @old_ttou end + + def test_failed_path + exceptions = %w[ENODEV ENOTTY EBADF ENXIO].map {|e| + Errno.const_get(e) if Errno.const_defined?(e) + } + exceptions.compact! + omit if exceptions.empty? + File.open(IO::NULL) do |f| + e = assert_raise(*exceptions) do + f.echo? + end + assert_include(e.message, IO::NULL) + end + end end defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do @@ -212,7 +232,7 @@ def test_setecho2 end def test_getpass - skip unless IO.method_defined?("getpass") + omit unless IO.method_defined?("getpass") run_pty("p IO.console.getpass('> ')") do |r, w| assert_equal("> ", r.readpartial(10)) sleep 0.1 @@ -221,6 +241,15 @@ def test_getpass assert_equal("\r\n", r.gets) assert_equal("\"asdf\"", r.gets.chomp) end + + run_pty("p IO.console.getpass('> ')") do |r, w| + assert_equal("> ", r.readpartial(10)) + sleep 0.1 + w.print "asdf\C-D\C-D" + sleep 0.1 + assert_equal("\r\n", r.gets) + assert_equal("\"asdf\"", r.gets.chomp) + end end def test_iflush @@ -352,7 +381,7 @@ def test_intr if cc = ctrl["intr"] assert_ctrl("#{cc.ord}", cc, r, w) assert_ctrl("#{cc.ord}", cc, r, w) - assert_ctrl("Interrupt", cc, r, w) unless /linux/ =~ RUBY_PLATFORM + assert_ctrl("Interrupt", cc, r, w) unless /linux|solaris/ =~ RUBY_PLATFORM end if cc = ctrl["dsusp"] assert_ctrl("#{cc.ord}", cc, r, w) @@ -378,6 +407,10 @@ def test_close assert_equal(["true"], run_pty("IO.console(:close); p IO.console(:tty?)")) end + def test_console_kw + assert_equal(["File"], run_pty("IO.console.close; p IO.console(:clone, freeze: true).class")) + end + def test_sync assert_equal(["true"], run_pty("p IO.console.sync")) end @@ -387,7 +420,7 @@ def test_sync def helper m, s = PTY.open rescue RuntimeError - skip $! + omit $! else yield m, s ensure @@ -396,9 +429,11 @@ def helper end def run_pty(src, n = 1) + pend("PTY.spawn cannot control terminal on JRuby") if RUBY_ENGINE == 'jruby' + r, w, pid = PTY.spawn(EnvUtil.rubybin, "-I#{TestIO_Console::PATHS.join(File::PATH_SEPARATOR)}", "-rio/console", "-e", src) rescue RuntimeError - skip $! + omit $! else if block_given? yield r, w, pid @@ -429,10 +464,14 @@ def test_set_winsize_console s = IO.console.winsize assert_nothing_raised(TypeError) {IO.console.winsize = s} bug = '[ruby-core:82741] [Bug #13888]' - IO.console.winsize = [s[0], s[1]+1] - assert_equal([s[0], s[1]+1], IO.console.winsize, bug) - IO.console.winsize = s - assert_equal(s, IO.console.winsize, bug) + begin + IO.console.winsize = [s[0], s[1]+1] + assert_equal([s[0], s[1]+1], IO.console.winsize, bug) + rescue Errno::EINVAL # Error if run on an actual console. + else + IO.console.winsize = s + assert_equal(s, IO.console.winsize, bug) + end ensure set_winsize_teardown end @@ -448,11 +487,21 @@ def test_close IO.console(:close) end + def test_console_kw + io = IO.console(:clone, freeze: true) + io.close + assert_kind_of(IO, io) + end + def test_sync assert(IO.console.sync, "console should be unbuffered") ensure IO.console(:close) end + + def test_getch_timeout + assert_nil(IO.console.getch(intr: true, time: 0.1, min: 0)) + end end end @@ -514,14 +563,14 @@ def test_pressed_invalid TestIO_Console.class_eval do def test_stringio_getch - assert_separately %w"--disable=gems -rstringio -rio/console", %q{ - assert_operator(StringIO, :method_defined?, :getch) + assert_ruby_status %w"--disable=gems -rstringio -rio/console", %q{ + abort unless StringIO.method_defined?(:getch) } - assert_separately %w"--disable=gems -rio/console -rstringio", %q{ - assert_operator(StringIO, :method_defined?, :getch) + assert_ruby_status %w"--disable=gems -rio/console -rstringio", %q{ + abort unless StringIO.method_defined?(:getch) } - assert_separately %w"--disable=gems -rstringio", %q{ - assert_not_operator(StringIO, :method_defined?, :getch) + assert_ruby_status %w"--disable=gems -rstringio", %q{ + abort if StringIO.method_defined?(:getch) } end end diff --git a/ruby/test/io/wait/test_io_wait_uncommon.rb b/ruby/test/io/wait/test_io_wait_uncommon.rb index e7f222c57..75cd33580 100644 --- a/ruby/test/io/wait/test_io_wait_uncommon.rb +++ b/ruby/test/io/wait/test_io_wait_uncommon.rb @@ -6,19 +6,15 @@ # We may optimize IO#wait_*able for non-Linux kernels in the future class TestIOWaitUncommon < Test::Unit::TestCase def test_tty_wait - begin - tty = File.open('/dev/tty', 'w+') - rescue Errno::ENOENT, Errno::ENXIO => e - skip "/dev/tty: #{e.message} (#{e.class})" + check_dev('/dev/tty', mode: 'w+') do |tty| + assert_include [ nil, tty ], tty.wait_readable(0) + assert_equal tty, tty.wait_writable(1), 'portability test' end - assert_include [ nil, tty ], tty.wait_readable(0) - assert_equal tty, tty.wait_writable(1), 'portability test' - ensure - tty&.close end def test_fifo_wait skip 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK) + require 'tmpdir' Dir.mktmpdir('rubytest-fifo') do |dir| fifo = "#{dir}/fifo" assert_equal 0, File.mkfifo(fifo) @@ -43,36 +39,40 @@ def test_fifo_wait # used to find portability problems because some ppoll implementations # are incomplete and do not work for certain "file" types - def check_dev(dev, m = :wait_readable) + def check_dev(dev, m = :wait_readable, mode: m == :wait_readable ? 'r' : 'w', &block) begin - fp = File.open("/dev/#{dev}", m == :wait_readable ? 'r' : 'w') + fp = File.open(dev, mode) + rescue Errno::ENOENT + return # Ignore silently rescue SystemCallError => e - skip "#{dev} could not be opened #{e.message} (#{e.class})" + omit "#{dev} could not be opened #{e.message} (#{e.class})" + end + if block + yield fp + else + assert_same fp, fp.__send__(m) end - assert_same fp, fp.__send__(m) ensure fp&.close end def test_wait_readable_urandom - check_dev 'urandom' + check_dev('/dev/urandom') end def test_wait_readable_random - File.open('/dev/random') do |fp| + check_dev('/dev/random') do |fp| assert_nothing_raised do fp.wait_readable(0) end end - rescue SystemCallError => e - skip "/dev/random could not be opened #{e.message} (#{e.class})" end def test_wait_readable_zero - check_dev 'zero' + check_dev('/dev/zero') end def test_wait_writable_null - check_dev 'null', :wait_writable + check_dev(IO::NULL, :wait_writable) end end diff --git a/ruby/test/io/wait/test_ractor.rb b/ruby/test/io/wait/test_ractor.rb new file mode 100644 index 000000000..3742680cf --- /dev/null +++ b/ruby/test/io/wait/test_ractor.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true +require 'test/unit' +require 'rbconfig' +require 'io/wait' + +class TestIOWaitInRactor < Test::Unit::TestCase + def test_ractor + ext = "/io/wait.#{RbConfig::CONFIG['DLEXT']}" + path = $".find {|path| path.end_with?(ext)} + assert_in_out_err(%W[-r#{path}], <<-"end;", ["true"], []) + $VERBOSE = nil + r = Ractor.new do + $stdout.equal?($stdout.wait_writable) + end + puts r.take + end; + end +end if defined? Ractor diff --git a/ruby/test/irb/test_cmd.rb b/ruby/test/irb/test_cmd.rb new file mode 100644 index 000000000..7b7ab55a6 --- /dev/null +++ b/ruby/test/irb/test_cmd.rb @@ -0,0 +1,558 @@ +# frozen_string_literal: false +require "test/unit" +require "irb" +require "irb/extend-command" + +module TestIRB + class ExtendCommand < Test::Unit::TestCase + class TestInputMethod < ::IRB::InputMethod + attr_reader :list, :line_no + + def initialize(list = []) + super("test") + @line_no = 0 + @list = list + end + + def gets + @list[@line_no]&.tap {@line_no += 1} + end + + def eof? + @line_no >= @list.size + end + + def encoding + Encoding.default_external + end + + def reset + @line_no = 0 + end + end + + def setup + @pwd = Dir.pwd + @tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}") + begin + Dir.mkdir(@tmpdir) + rescue Errno::EEXIST + FileUtils.rm_rf(@tmpdir) + Dir.mkdir(@tmpdir) + end + Dir.chdir(@tmpdir) + @home_backup = ENV["HOME"] + ENV["HOME"] = @tmpdir + @xdg_config_home_backup = ENV.delete("XDG_CONFIG_HOME") + @default_encoding = [Encoding.default_external, Encoding.default_internal] + @stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] } + IRB.instance_variable_get(:@CONF).clear + @is_win = (RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/) + end + + def teardown + ENV["XDG_CONFIG_HOME"] = @xdg_config_home_backup + ENV["HOME"] = @home_backup + Dir.chdir(@pwd) + FileUtils.rm_rf(@tmpdir) + EnvUtil.suppress_warning { + Encoding.default_external, Encoding.default_internal = *@default_encoding + [STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs| + io.set_encoding(*encs) + end + } + end + + def test_irb_info_multiline + FileUtils.touch("#{@tmpdir}/.inputrc") + FileUtils.touch("#{@tmpdir}/.irbrc") + IRB.setup(__FILE__, argv: []) + IRB.conf[:USE_MULTILINE] = true + IRB.conf[:USE_SINGLELINE] = false + IRB.conf[:VERBOSE] = false + lang_backup = ENV.delete("LANG") + lc_all_backup = ENV.delete("LC_ALL") + workspace = IRB::WorkSpace.new(self) + irb = IRB::Irb.new(workspace, TestInputMethod.new([])) + IRB.conf[:MAIN_CONTEXT] = irb.context + expected = %r{ + Ruby\sversion:\s.+\n + IRB\sversion:\sirb\s.+\n + InputMethod:\sAbstract\sInputMethod\n + \.irbrc\spath:\s.+\n + RUBY_PLATFORM:\s.+\n + East\sAsian\sAmbiguous\sWidth:\s\d\n + #{@is_win ? 'Code\spage:\s\d+\n' : ''} + }x + assert_match expected, irb.context.main.irb_info.to_s + ensure + ENV["LANG"] = lang_backup + ENV["LC_ALL"] = lc_all_backup + end + + def test_irb_info_singleline + FileUtils.touch("#{@tmpdir}/.inputrc") + FileUtils.touch("#{@tmpdir}/.irbrc") + IRB.setup(__FILE__, argv: []) + IRB.conf[:USE_MULTILINE] = false + IRB.conf[:USE_SINGLELINE] = true + IRB.conf[:VERBOSE] = false + lang_backup = ENV.delete("LANG") + lc_all_backup = ENV.delete("LC_ALL") + workspace = IRB::WorkSpace.new(self) + irb = IRB::Irb.new(workspace, TestInputMethod.new([])) + IRB.conf[:MAIN_CONTEXT] = irb.context + expected = %r{ + Ruby\sversion:\s.+\n + IRB\sversion:\sirb\s.+\n + InputMethod:\sAbstract\sInputMethod\n + \.irbrc\spath:\s.+\n + RUBY_PLATFORM:\s.+\n + East\sAsian\sAmbiguous\sWidth:\s\d\n + #{@is_win ? 'Code\spage:\s\d+\n' : ''} + }x + assert_match expected, irb.context.main.irb_info.to_s + ensure + ENV["LANG"] = lang_backup + ENV["LC_ALL"] = lc_all_backup + end + + def test_irb_info_multiline_without_rc_files + inputrc_backup = ENV["INPUTRC"] + ENV["INPUTRC"] = "unknown_inpurc" + ext_backup = IRB::IRBRC_EXT + IRB.__send__(:remove_const, :IRBRC_EXT) + IRB.const_set(:IRBRC_EXT, "unknown_ext") + IRB.setup(__FILE__, argv: []) + IRB.conf[:USE_MULTILINE] = true + IRB.conf[:USE_SINGLELINE] = false + IRB.conf[:VERBOSE] = false + lang_backup = ENV.delete("LANG") + lc_all_backup = ENV.delete("LC_ALL") + workspace = IRB::WorkSpace.new(self) + irb = IRB::Irb.new(workspace, TestInputMethod.new([])) + IRB.conf[:MAIN_CONTEXT] = irb.context + expected = %r{ + Ruby\sversion:\s.+\n + IRB\sversion:\sirb\s.+\n + InputMethod:\sAbstract\sInputMethod\n + RUBY_PLATFORM:\s.+\n + East\sAsian\sAmbiguous\sWidth:\s\d\n + #{@is_win ? 'Code\spage:\s\d+\n' : ''} + \z + }x + assert_match expected, irb.context.main.irb_info.to_s + ensure + ENV["INPUTRC"] = inputrc_backup + IRB.__send__(:remove_const, :IRBRC_EXT) + IRB.const_set(:IRBRC_EXT, ext_backup) + ENV["LANG"] = lang_backup + ENV["LC_ALL"] = lc_all_backup + end + + def test_irb_info_singleline_without_rc_files + inputrc_backup = ENV["INPUTRC"] + ENV["INPUTRC"] = "unknown_inpurc" + ext_backup = IRB::IRBRC_EXT + IRB.__send__(:remove_const, :IRBRC_EXT) + IRB.const_set(:IRBRC_EXT, "unknown_ext") + IRB.setup(__FILE__, argv: []) + IRB.conf[:USE_MULTILINE] = false + IRB.conf[:USE_SINGLELINE] = true + IRB.conf[:VERBOSE] = false + lang_backup = ENV.delete("LANG") + lc_all_backup = ENV.delete("LC_ALL") + workspace = IRB::WorkSpace.new(self) + irb = IRB::Irb.new(workspace, TestInputMethod.new([])) + IRB.conf[:MAIN_CONTEXT] = irb.context + expected = %r{ + Ruby\sversion:\s.+\n + IRB\sversion:\sirb\s.+\n + InputMethod:\sAbstract\sInputMethod\n + RUBY_PLATFORM:\s.+\n + East\sAsian\sAmbiguous\sWidth:\s\d\n + #{@is_win ? 'Code\spage:\s\d+\n' : ''} + \z + }x + assert_match expected, irb.context.main.irb_info.to_s + ensure + ENV["INPUTRC"] = inputrc_backup + IRB.__send__(:remove_const, :IRBRC_EXT) + IRB.const_set(:IRBRC_EXT, ext_backup) + ENV["LANG"] = lang_backup + ENV["LC_ALL"] = lc_all_backup + end + + def test_irb_info_lang + FileUtils.touch("#{@tmpdir}/.inputrc") + FileUtils.touch("#{@tmpdir}/.irbrc") + IRB.setup(__FILE__, argv: []) + IRB.conf[:USE_MULTILINE] = true + IRB.conf[:USE_SINGLELINE] = false + IRB.conf[:VERBOSE] = false + lang_backup = ENV.delete("LANG") + lc_all_backup = ENV.delete("LC_ALL") + ENV["LANG"] = "ja_JP.UTF-8" + ENV["LC_ALL"] = "en_US.UTF-8" + workspace = IRB::WorkSpace.new(self) + irb = IRB::Irb.new(workspace, TestInputMethod.new([])) + IRB.conf[:MAIN_CONTEXT] = irb.context + expected = %r{ + Ruby\sversion: .+\n + IRB\sversion:\sirb .+\n + InputMethod:\sAbstract\sInputMethod\n + \.irbrc\spath: .+\n + RUBY_PLATFORM: .+\n + LANG\senv:\sja_JP\.UTF-8\n + LC_ALL\senv:\sen_US\.UTF-8\n + East\sAsian\sAmbiguous\sWidth:\s\d\n + }x + assert_match expected, irb.context.main.irb_info.to_s + ensure + ENV["LANG"] = lang_backup + ENV["LC_ALL"] = lc_all_backup + end + + def test_measure + IRB.init_config(nil) + IRB.conf[:PROMPT] = { + DEFAULT: { + PROMPT_I: '> ', + PROMPT_S: '> ', + PROMPT_C: '> ', + PROMPT_N: '> ' + } + } + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :DEFAULT + IRB.conf[:MEASURE] = false + input = TestInputMethod.new([ + "3\n", + "measure\n", + "3\n", + "measure :off\n", + "3\n", + ]) + c = Class.new(Object) + irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input) + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\A=> 3\nTIME is added\.\n=> nil\nprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out) + assert_empty(c.class_variables) + end + + def test_measure_enabled_by_rc + IRB.init_config(nil) + IRB.conf[:PROMPT] = { + DEFAULT: { + PROMPT_I: '> ', + PROMPT_S: '> ', + PROMPT_C: '> ', + PROMPT_N: '> ' + } + } + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :DEFAULT + IRB.conf[:MEASURE] = true + input = TestInputMethod.new([ + "3\n", + "measure :off\n", + "3\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\Aprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out) + end + + def test_measure_enabled_by_rc_with_custom + IRB.init_config(nil) + IRB.conf[:PROMPT] = { + DEFAULT: { + PROMPT_I: '> ', + PROMPT_S: '> ', + PROMPT_C: '> ', + PROMPT_N: '> ' + } + } + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :DEFAULT + IRB.conf[:MEASURE] = true + IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block| + time = Time.now + result = block.() + puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE] + result + } + input = TestInputMethod.new([ + "3\n", + "measure :off\n", + "3\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\Acustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out) + end + + def test_measure_with_custom + IRB.init_config(nil) + IRB.conf[:PROMPT] = { + DEFAULT: { + PROMPT_I: '> ', + PROMPT_S: '> ', + PROMPT_C: '> ', + PROMPT_N: '> ' + } + } + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :DEFAULT + IRB.conf[:MEASURE] = false + IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block| + time = Time.now + result = block.() + puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE] + result + } + input = TestInputMethod.new([ + "3\n", + "measure\n", + "3\n", + "measure :off\n", + "3\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\A=> 3\nCUSTOM is added\.\n=> nil\ncustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out) + end + + def test_measure_with_proc + IRB.init_config(nil) + IRB.conf[:PROMPT] = { + DEFAULT: { + PROMPT_I: '> ', + PROMPT_S: '> ', + PROMPT_C: '> ', + PROMPT_N: '> ' + } + } + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :DEFAULT + IRB.conf[:MEASURE] = false + input = TestInputMethod.new([ + "3\n", + "measure { |context, code, line_no, &block|\n", + " result = block.()\n", + " puts 'aaa' if IRB.conf[:MEASURE]\n", + " result\n", + "}\n", + "3\n", + "measure { |context, code, line_no, &block|\n", + " result = block.()\n", + " puts 'bbb' if IRB.conf[:MEASURE]\n", + " result\n", + "}\n", + "3\n", + "measure :off\n", + "3\n", + ]) + c = Class.new(Object) + irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input) + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\A=> 3\nBLOCK is added\.\n=> nil\naaa\n=> 3\nBLOCK is added.\naaa\n=> nil\nbbb\n=> 3\n=> nil\n=> 3\n/, out) + assert_empty(c.class_variables) + end + + def test_irb_source + IRB.init_config(nil) + File.write("#{@tmpdir}/a.rb", "a = 'hi'\n") + input = TestInputMethod.new([ + "a = 'bug17564'\n", + "a\n", + "irb_source '#{@tmpdir}/a.rb'\n", + "a\n", + ]) + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :SIMPLE + irb = IRB::Irb.new(IRB::WorkSpace.new(self), input) + IRB.conf[:MAIN_CONTEXT] = irb.context + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_pattern_list([ + /=> "bug17564"\n/, + /=> "bug17564"\n/, + / => "hi"\n/, + / => nil\n/, + /=> "hi"\n/, + ], out) + end + + def test_irb_load + IRB.init_config(nil) + File.write("#{@tmpdir}/a.rb", "a = 'hi'\n") + input = TestInputMethod.new([ + "a = 'bug17564'\n", + "a\n", + "irb_load '#{@tmpdir}/a.rb'\n", + "a\n", + ]) + IRB.conf[:VERBOSE] = false + IRB.conf[:PROMPT_MODE] = :SIMPLE + irb = IRB::Irb.new(IRB::WorkSpace.new(self), input) + IRB.conf[:MAIN_CONTEXT] = irb.context + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_pattern_list([ + /=> "bug17564"\n/, + /=> "bug17564"\n/, + / => "hi"\n/, + / => nil\n/, + /=> "bug17564"\n/, + ], out) + end + + def test_ls + input = TestInputMethod.new([ + "class P\n", + " def m() end\n", + " def m2() end\n", + "end\n", + + "class C < P\n", + " def m1() end\n", + " def m2() end\n", + "end\n", + + "module M\n", + " def m1() end\n", + " def m3() end\n", + "end\n", + + "module M2\n", + " include M\n", + " def m4() end\n", + "end\n", + + "obj = C.new\n", + "obj.instance_variable_set(:@a, 1)\n", + "obj.extend M2\n", + "def obj.m5() end\n", + "ls obj\n", + ]) + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(self) + IRB.conf[:VERBOSE] = false + irb = IRB::Irb.new(workspace, input) + IRB.conf[:MAIN_CONTEXT] = irb.context + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/^instance variables:\s+@a\n/m, out) + assert_match(/P#methods:\s+m\n/m, out) + assert_match(/C#methods:\s+m2\n/m, out) + assert_match(/M#methods:\s+m1\s+m3\n/m, out) + assert_match(/M2#methods:\s+m4\n/m, out) + assert_match(/C.methods:\s+m5\n/m, out) + end + + def test_ls_with_no_singleton_class + input = TestInputMethod.new([ + "ls 42", + ]) + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(self) + IRB.conf[:VERBOSE] = false + irb = IRB::Irb.new(workspace, input) + IRB.conf[:MAIN_CONTEXT] = irb.context + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/Comparable#methods:\s+/, out) + assert_match(/Numeric#methods:\s+/, out) + assert_match(/Integer#methods:\s+/, out) + end + + def test_show_source + input = TestInputMethod.new([ + "show_source 'IRB.conf'\n", + ]) + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(self) + IRB.conf[:VERBOSE] = false + irb = IRB::Irb.new(workspace, input) + IRB.conf[:MAIN_CONTEXT] = irb.context + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(%r[/irb\.rb], out) + end + + def test_show_source_end_finder + pend if RUBY_ENGINE == 'truffleruby' + eval(code = <<-EOS, binding, __FILE__, __LINE__ + 1) + def show_source_test_method + unless true + end + end + EOS + input = TestInputMethod.new([ + "show_source 'TestIRB::ExtendCommand#show_source_test_method'\n", + ]) + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(self) + IRB.conf[:VERBOSE] = false + irb = IRB::Irb.new(workspace, input) + IRB.conf[:MAIN_CONTEXT] = irb.context + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_include(out, code) + end + + def test_whereami + input = TestInputMethod.new([ + "whereami\n", + ]) + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(self) + IRB.conf[:VERBOSE] = false + irb = IRB::Irb.new(workspace, input) + IRB.conf[:MAIN_CONTEXT] = irb.context + irb.context.return_format = "=> %s\n" + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/^From: .+ @ line \d+ :\n/, out) + end + end +end diff --git a/ruby/test/irb/test_color.rb b/ruby/test/irb/test_color.rb index cb90d29c9..6ad64a0ae 100644 --- a/ruby/test/irb/test_color.rb +++ b/ruby/test/irb/test_color.rb @@ -17,6 +17,27 @@ class TestColor < Test::Unit::TestCase MAGENTA = "\e[35m" CYAN = "\e[36m" + def test_colorize + text = "text" + { + [:BOLD] => "#{BOLD}#{text}#{CLEAR}", + [:UNDERLINE] => "#{UNDERLINE}#{text}#{CLEAR}", + [:REVERSE] => "#{REVERSE}#{text}#{CLEAR}", + [:RED] => "#{RED}#{text}#{CLEAR}", + [:GREEN] => "#{GREEN}#{text}#{CLEAR}", + [:YELLOW] => "#{YELLOW}#{text}#{CLEAR}", + [:BLUE] => "#{BLUE}#{text}#{CLEAR}", + [:MAGENTA] => "#{MAGENTA}#{text}#{CLEAR}", + [:CYAN] => "#{CYAN}#{text}#{CLEAR}", + }.each do |seq, result| + assert_equal_with_term(result, text, seq: seq) + + assert_equal_with_term(text, text, seq: seq, tty: false) + assert_equal_with_term(text, text, seq: seq, colorable: false) + assert_equal_with_term(result, text, seq: seq, tty: false, colorable: true) + end + end + def test_colorize_code # Common behaviors. Warn parser error, but do not warn compile error. tests = { @@ -34,7 +55,6 @@ def test_colorize_code '"foo#{a} #{b}"' => "#{RED}#{BOLD}\"#{CLEAR}#{RED}foo#{CLEAR}#{RED}\#{#{CLEAR}a#{RED}}#{CLEAR}#{RED} #{CLEAR}#{RED}\#{#{CLEAR}b#{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}", '/r#{e}g/' => "#{RED}#{BOLD}/#{CLEAR}#{RED}r#{CLEAR}#{RED}\#{#{CLEAR}e#{RED}}#{CLEAR}#{RED}g#{CLEAR}#{RED}#{BOLD}/#{CLEAR}", "'a\nb'" => "#{RED}#{BOLD}'#{CLEAR}#{RED}a#{CLEAR}\n#{RED}b#{CLEAR}#{RED}#{BOLD}'#{CLEAR}", - "[1]]]\u0013" => "[1]]]^S", "%[str]" => "#{RED}#{BOLD}%[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}", "%Q[str]" => "#{RED}#{BOLD}%Q[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}", "%q[str]" => "#{RED}#{BOLD}%q[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}", @@ -50,7 +70,7 @@ def test_colorize_code '"#{}"' => "#{RED}#{BOLD}\"#{CLEAR}#{RED}\#{#{CLEAR}#{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}", ':"a#{}b"' => "#{YELLOW}:\"#{CLEAR}#{YELLOW}a#{CLEAR}#{YELLOW}\#{#{CLEAR}#{YELLOW}}#{CLEAR}#{YELLOW}b#{CLEAR}#{YELLOW}\"#{CLEAR}", ':"a#{ def b; end; \'c\' + "#{ :d }" }e"' => "#{YELLOW}:\"#{CLEAR}#{YELLOW}a#{CLEAR}#{YELLOW}\#{#{CLEAR} #{GREEN}def#{CLEAR} #{BLUE}#{BOLD}b#{CLEAR}; #{GREEN}end#{CLEAR}; #{RED}#{BOLD}'#{CLEAR}#{RED}c#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}\"#{CLEAR}#{RED}\#{#{CLEAR} #{YELLOW}:#{CLEAR}#{YELLOW}d#{CLEAR} #{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR} #{YELLOW}}#{CLEAR}#{YELLOW}e#{CLEAR}#{YELLOW}\"#{CLEAR}", - "[__FILE__, __LINE__]" => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}]", + "[__FILE__, __LINE__, __ENCODING__]" => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]", ":self" => "#{YELLOW}:#{CLEAR}#{YELLOW}self#{CLEAR}", ":class" => "#{YELLOW}:#{CLEAR}#{YELLOW}class#{CLEAR}", "[:end, 2]" => "[#{YELLOW}:#{CLEAR}#{YELLOW}end#{CLEAR}, #{BLUE}#{BOLD}2#{CLEAR}]", @@ -67,6 +87,7 @@ def test_colorize_code "\t" => "\t", # not ^I "foo(*%W(bar))" => "foo(*#{RED}#{BOLD}%W(#{CLEAR}#{RED}bar#{CLEAR}#{RED}#{BOLD})#{CLEAR})", "$stdout" => "#{GREEN}#{BOLD}$stdout#{CLEAR}", + "__END__" => "#{GREEN}__END__#{CLEAR}", } # specific to Ruby 2.7+ @@ -78,23 +99,55 @@ def test_colorize_code }) end + # specific to Ruby 3.0+ + if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') + tests.merge!({ + "[1]]]\u0013" => "[#{BLUE}#{BOLD}1#{CLEAR}]#{RED}#{REVERSE}]#{CLEAR}#{RED}#{REVERSE}]#{CLEAR}#{RED}#{REVERSE}^S#{CLEAR}", + }) + tests.merge!({ + "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}) #{RED}#{REVERSE}end#{CLEAR}", + "nil = 1" => "#{RED}#{REVERSE}nil#{CLEAR} = #{BLUE}#{BOLD}1#{CLEAR}", + "alias $x $1" => "#{GREEN}alias#{CLEAR} #{GREEN}#{BOLD}$x#{CLEAR} #{RED}#{REVERSE}$1#{CLEAR}", + "class bad; end" => "#{GREEN}class#{CLEAR} #{RED}#{REVERSE}bad#{CLEAR}; #{GREEN}end#{CLEAR}", + "def req(@a) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}@a#{CLEAR}) #{GREEN}end#{CLEAR}", + }) + else + tests.merge!({ + "[1]]]\u0013" => "[1]]]^S", + }) + tests.merge!({ + "def req(true) end" => "def req(true) end", + "nil = 1" => "#{CYAN}#{BOLD}nil#{CLEAR} = #{BLUE}#{BOLD}1#{CLEAR}", + "alias $x $1" => "#{GREEN}alias#{CLEAR} #{GREEN}#{BOLD}$x#{CLEAR} $1", + "class bad; end" => "#{GREEN}class#{CLEAR} bad; #{GREEN}end#{CLEAR}", + "def req(@a) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(@a) #{GREEN}end#{CLEAR}", + }) + end + tests.each do |code, result| if colorize_code_supported? - actual = with_term { IRB::Color.colorize_code(code, complete: true) } - assert_equal(result, actual, "Case: IRB::Color.colorize_code(#{code.dump}, complete: true)\nResult: #{humanized_literal(actual)}") + assert_equal_with_term(result, code, complete: true) + assert_equal_with_term(result, code, complete: false) + + assert_equal_with_term(code, code, complete: true, tty: false) + assert_equal_with_term(code, code, complete: false, tty: false) + + assert_equal_with_term(code, code, complete: true, colorable: false) + + assert_equal_with_term(code, code, complete: false, colorable: false) - actual = with_term { IRB::Color.colorize_code(code, complete: false) } - assert_equal(result, actual, "Case: IRB::Color.colorize_code(#{code.dump}, complete: false)\nResult: #{humanized_literal(actual)}") + assert_equal_with_term(result, code, complete: true, tty: false, colorable: true) + + assert_equal_with_term(result, code, complete: false, tty: false, colorable: true) else - actual = with_term { IRB::Color.colorize_code(code) } - assert_equal(code, actual) + assert_equal_with_term(code, code) end end end def test_colorize_code_complete_true unless complete_option_supported? - skip '`complete: true` is the same as `complete: false` in Ruby 2.6-' + pend '`complete: true` is the same as `complete: false` in Ruby 2.6-' end # `complete: true` behaviors. Warn end-of-file. @@ -102,8 +155,13 @@ def test_colorize_code_complete_true "'foo' + 'bar" => "#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}'#{CLEAR}#{RED}#{REVERSE}bar#{CLEAR}", "('foo" => "(#{RED}#{BOLD}'#{CLEAR}#{RED}#{REVERSE}foo#{CLEAR}", }.each do |code, result| - actual = with_term { IRB::Color.colorize_code(code, complete: true) } - assert_equal(result, actual, "Case: colorize_code(#{code.dump}, complete: true)\nResult: #{humanized_literal(actual)}") + assert_equal_with_term(result, code, complete: true) + + assert_equal_with_term(code, code, complete: true, tty: false) + + assert_equal_with_term(code, code, complete: true, colorable: false) + + assert_equal_with_term(result, code, complete: true, tty: false, colorable: true) end end @@ -114,16 +172,25 @@ def test_colorize_code_complete_false "('foo" => "(#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}", }.each do |code, result| if colorize_code_supported? - actual = with_term { IRB::Color.colorize_code(code, complete: false) } - assert_equal(result, actual, "Case: colorize_code(#{code.dump}, complete: false)\nResult: #{humanized_literal(actual)}") + assert_equal_with_term(result, code, complete: false) + + assert_equal_with_term(code, code, complete: false, tty: false) + + assert_equal_with_term(code, code, complete: false, colorable: false) + + assert_equal_with_term(result, code, complete: false, tty: false, colorable: true) unless complete_option_supported? - actual = with_term { IRB::Color.colorize_code(code, complete: true) } - assert_equal(result, actual, "Case: colorize_code(#{code.dump}, complete: false)\nResult: #{humanized_literal(actual)}") + assert_equal_with_term(result, code, complete: true) + + assert_equal_with_term(code, code, complete: true, tty: false) + + assert_equal_with_term(code, code, complete: true, colorable: false) + + assert_equal_with_term(result, code, complete: true, tty: false, colorable: true) end else - actual = with_term { IRB::Color.colorize_code(code) } - assert_equal(code, actual) + assert_equal_with_term(code, code) end end end @@ -160,10 +227,10 @@ def complete_option_supported? Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0') end - def with_term + def with_term(tty: true) stdout = $stdout io = StringIO.new - def io.tty?; true; end + def io.tty?; true; end if tty $stdout = io env = ENV.to_h.dup @@ -175,6 +242,23 @@ def io.tty?; true; end ENV.replace(env) if env end + def assert_equal_with_term(result, code, seq: nil, tty: true, **opts) + actual = with_term(tty: tty) do + if seq + IRB::Color.colorize(code, seq, **opts) + else + IRB::Color.colorize_code(code, **opts) + end + end + message = -> { + args = [code.dump] + args << seq.inspect if seq + opts.each {|kwd, val| args << "#{kwd}: #{val}"} + "Case: colorize#{seq ? "" : "_code"}(#{args.join(', ')})\nResult: #{humanized_literal(actual)}" + } + assert_equal(result, actual, message) + end + def humanized_literal(str) str .gsub(CLEAR, '@@@{CLEAR}') diff --git a/ruby/test/irb/test_color_printer.rb b/ruby/test/irb/test_color_printer.rb new file mode 100644 index 000000000..93ec70014 --- /dev/null +++ b/ruby/test/irb/test_color_printer.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: false +require 'test/unit' +require 'irb/color_printer' +require 'rubygems' +require 'stringio' + +module TestIRB + class TestColorPrinter < Test::Unit::TestCase + CLEAR = "\e[0m" + BOLD = "\e[1m" + RED = "\e[31m" + GREEN = "\e[32m" + BLUE = "\e[34m" + CYAN = "\e[36m" + + def setup + @get_screen_size = Reline.method(:get_screen_size) + Reline.instance_eval { undef :get_screen_size } + def Reline.get_screen_size + [36, 80] + end + end + + def teardown + Reline.instance_eval { undef :get_screen_size } + Reline.define_singleton_method(:get_screen_size, @get_screen_size) + end + + IRBTestColorPrinter = Struct.new(:a) + + def test_color_printer + unless ripper_lexer_scan_supported? + pend 'Ripper::Lexer#scan is supported in Ruby 2.7+' + end + { + 1 => "#{BLUE}#{BOLD}1#{CLEAR}\n", + "a\nb" => %[#{RED}#{BOLD}"#{CLEAR}#{RED}a\\nb#{CLEAR}#{RED}#{BOLD}"#{CLEAR}\n], + IRBTestColorPrinter.new('test') => "#{GREEN}##{CLEAR}\n", + Ripper::Lexer.new('1').scan => "[#{GREEN}##{CLEAR}]\n", + Class.new{define_method(:pretty_print){|q| q.text("[__FILE__, __LINE__, __ENCODING__]")}}.new => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]\n", + }.each do |object, result| + actual = with_term { IRB::ColorPrinter.pp(object, '') } + assert_equal(result, actual, "Case: IRB::ColorPrinter.pp(#{object.inspect}, '')") + end + end + + private + + def ripper_lexer_scan_supported? + Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0') + end + + def with_term + stdout = $stdout + io = StringIO.new + def io.tty?; true; end + $stdout = io + + env = ENV.to_h.dup + ENV['TERM'] = 'xterm-256color' + + yield + ensure + $stdout = stdout + ENV.replace(env) if env + end + end +end diff --git a/ruby/test/irb/test_completion.rb b/ruby/test/irb/test_completion.rb index a765bbf3a..3aa99d74d 100644 --- a/ruby/test/irb/test_completion.rb +++ b/ruby/test/irb/test_completion.rb @@ -17,7 +17,7 @@ def test_nonstring_module_name status = assert_in_out_err(cmds, "", //, [], bug5938) assert(status.success?, bug5938) rescue LoadError - skip "cannot load irb/completion" + pend "cannot load irb/completion" end end @@ -27,11 +27,27 @@ def test_complete_numeric end def test_complete_symbol + %w"UTF-16LE UTF-7".each do |enc| + "K".force_encoding(enc).to_sym + rescue + end _ = :aiueo assert_include(IRB::InputCompletor.retrieve_completion_data(":a", bind: binding), ":aiueo") assert_empty(IRB::InputCompletor.retrieve_completion_data(":irb_unknown_symbol_abcdefg", bind: binding)) end + def test_complete_invalid_three_colons + assert_empty(IRB::InputCompletor.retrieve_completion_data(":::A", bind: binding)) + assert_empty(IRB::InputCompletor.retrieve_completion_data(":::", bind: binding)) + end + + def test_complete_absolute_constants_with_special_characters + assert_empty(IRB::InputCompletor.retrieve_completion_data("::A:", bind: binding)) + assert_empty(IRB::InputCompletor.retrieve_completion_data("::A.", bind: binding)) + assert_empty(IRB::InputCompletor.retrieve_completion_data("::A(", bind: binding)) + assert_empty(IRB::InputCompletor.retrieve_completion_data("::A)", bind: binding)) + end + def test_complete_symbol_failure assert_nil(IRB::InputCompletor::PerfectMatchedProc.(":aiueo", bind: binding)) end @@ -47,5 +63,60 @@ def test_complete_reserved_words assert_include candidates, word end end + + def test_complete_predicate? + candidates = IRB::InputCompletor.retrieve_completion_data("1.posi", bind: binding) + assert_include candidates, '1.positive?' + + namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true) + assert_equal "Integer.positive?", namespace + end + + def test_complete_require + candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") + %w['irb/init 'irb/ruby-lex].each do |word| + assert_include candidates, word + end + # Test cache + candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") + %w['irb/init 'irb/ruby-lex].each do |word| + assert_include candidates, word + end + end + + def test_complete_require_library_name_first + pend 'Need to use virtual library paths' + candidates = IRB::InputCompletor::CompletionProc.("'csv", "require ", "") + assert_equal "'csv", candidates.first + end + + def test_complete_require_relative + candidates = Dir.chdir(__dir__ + "/../..") do + IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") + end + %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| + assert_include candidates, word + end + # Test cache + candidates = Dir.chdir(__dir__ + "/../..") do + IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") + end + %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| + assert_include candidates, word + end + end + + def test_complete_variable + str_example = '' + str_example.clear # suppress "assigned but unused variable" warning + assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example") + assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true), "String") + assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") + end + + def test_complete_class_method + assert_include(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding), "String.new") + assert_equal(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true), "String.new") + end end end diff --git a/ruby/test/irb/test_context.rb b/ruby/test/irb/test_context.rb index d03cc30c7..42f82fc37 100644 --- a/ruby/test/irb/test_context.rb +++ b/ruby/test/irb/test_context.rb @@ -30,6 +30,10 @@ def encoding def reset @line_no = 0 end + + def winsize + [10, 20] + end end def setup @@ -38,6 +42,17 @@ def setup IRB.conf[:VERBOSE] = false workspace = IRB::WorkSpace.new(Object.new) @context = IRB::Context.new(nil, workspace, TestInputMethod.new) + + @get_screen_size = Reline.method(:get_screen_size) + Reline.instance_eval { undef :get_screen_size } + def Reline.get_screen_size + [36, 80] + end + end + + def teardown + Reline.instance_eval { undef :get_screen_size } + Reline.define_singleton_method(:get_screen_size, @get_screen_size) end def test_last_value @@ -64,6 +79,7 @@ def test_evaluate_with_exception end def test_evaluate_with_encoding_error_without_lineno + pend if RUBY_ENGINE == 'truffleruby' assert_raise_with_message(EncodingError, /invalid symbol/) { @context.evaluate(%q[{"\xAE": 1}], 1) # The backtrace of this invalid encoding hash doesn't contain lineno. @@ -71,12 +87,14 @@ def test_evaluate_with_encoding_error_without_lineno end def test_evaluate_with_onigmo_warning + pend if RUBY_ENGINE == 'truffleruby' assert_warning("(irb):1: warning: character class has duplicated range: /[aa]/\n") do @context.evaluate('/[aa]/', 1) end end def test_eval_input + pend if RUBY_ENGINE == 'truffleruby' verbose, $VERBOSE = $VERBOSE, nil input = TestInputMethod.new([ "raise 'Foo'\n", @@ -89,7 +107,7 @@ def test_eval_input irb.eval_input end assert_empty err - assert_pattern_list([:*, /RuntimeError \(.*Foo.*\).*\n/, + assert_pattern_list([:*, /\(irb\):1:in `
      ': Foo \(RuntimeError\)\n/, :*, /#\n/, :*, /0$/, :*, /0$/, @@ -98,8 +116,50 @@ def test_eval_input $VERBOSE = verbose end + def test_eval_input_raise2x + pend if RUBY_ENGINE == 'truffleruby' + input = TestInputMethod.new([ + "raise 'Foo'\n", + "raise 'Bar'\n", + "_\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_pattern_list([ + :*, /\(irb\):1:in `
      ': Foo \(RuntimeError\)\n/, + :*, /\(irb\):2:in `
      ': Bar \(RuntimeError\)\n/, + :*, /#\n/, + ], out) + end + + def test_eval_object_without_inspect_method + verbose, $VERBOSE = $VERBOSE, nil + all_assertions do |all| + IRB::Inspector::INSPECTORS.invert.each_value do |mode| + all.for(mode) do + input = TestInputMethod.new([ + "[BasicObject.new, Class.new]\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.inspect_mode = mode + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/\(Object doesn't support #inspect\)\n(=> )?\n/, out) + end + end + end + ensure + $VERBOSE = verbose + end + def test_default_config assert_equal(true, @context.use_colorize?) + assert_equal(true, @context.use_autocomplete?) end def test_assignment_expression @@ -161,7 +221,7 @@ def test_echo_on_assignment # The default irb.context.echo = true irb.context.echo_on_assignment = false - out, err = capture_io do + out, err = capture_output do irb.eval_input end assert_empty err @@ -171,7 +231,7 @@ def test_echo_on_assignment input.reset irb.context.echo = true irb.context.echo_on_assignment = true - out, err = capture_io do + out, err = capture_output do irb.eval_input end assert_empty err @@ -181,7 +241,7 @@ def test_echo_on_assignment input.reset irb.context.echo = false irb.context.echo_on_assignment = false - out, err = capture_io do + out, err = capture_output do irb.eval_input end assert_empty err @@ -191,37 +251,173 @@ def test_echo_on_assignment input.reset irb.context.echo = false irb.context.echo_on_assignment = true - out, err = capture_io do + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + end + + def test_omit_on_assignment + IRB.conf[:USE_COLORIZE] = false + input = TestInputMethod.new([ + "a = [1] * 100\n", + "a\n", + ]) + value = [1] * 100 + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.return_format = "=> %s\n" + + irb.context.echo = true + irb.context.echo_on_assignment = false + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> \n#{value.pretty_inspect}", out) + + input.reset + irb.context.echo = true + irb.context.echo_on_assignment = :truncate + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> \n#{value.pretty_inspect[0..3]}...\n=> \n#{value.pretty_inspect}", out) + + input.reset + irb.context.echo = true + irb.context.echo_on_assignment = true + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> \n#{value.pretty_inspect}=> \n#{value.pretty_inspect}", out) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = false + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = :truncate + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = true + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + end + + def test_omit_multiline_on_assignment + IRB.conf[:USE_COLORIZE] = false + input = TestInputMethod.new([ + "class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n", + "a\n" + ]) + value = ([?* * 1000] * 3).join(%{\n}) + value_first_line = (?* * 1000).to_s + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + irb.context.return_format = "=> %s\n" + + irb.context.echo = true + irb.context.echo_on_assignment = false + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> \n#{value}\n", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) + + input.reset + irb.context.echo = true + irb.context.echo_on_assignment = :truncate + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\n=> \n#{value}\n", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) + + input.reset + irb.context.echo = true + irb.context.echo_on_assignment = true + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("=> \n#{value}\n=> \n#{value}\n", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = false + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = :truncate + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) + + input.reset + irb.context.echo = false + irb.context.echo_on_assignment = true + out, err = capture_output do irb.eval_input end assert_empty err assert_equal("", out) + irb.context.evaluate('A.remove_method(:inspect)', 0) end def test_echo_on_assignment_conf # Default IRB.conf[:ECHO] = nil IRB.conf[:ECHO_ON_ASSIGNMENT] = nil + IRB.conf[:USE_COLORIZE] = false input = TestInputMethod.new() irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) assert(irb.context.echo?, "echo? should be true by default") - refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default") + assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default") # Explicitly set :ECHO to false IRB.conf[:ECHO] = false irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false") - refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default") + assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default") # Explicitly set :ECHO_ON_ASSIGNMENT to true IRB.conf[:ECHO] = nil - IRB.conf[:ECHO_ON_ASSIGNMENT] = true + IRB.conf[:ECHO_ON_ASSIGNMENT] = false irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) assert(irb.context.echo?, "echo? should be true by default") - assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to true") + refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false") end def test_multiline_output_on_default_inspector @@ -229,6 +425,7 @@ def test_multiline_output_on_default_inspector def main.inspect "abc\ndef" end + IRB.conf[:USE_COLORIZE] = false input = TestInputMethod.new([ "self" ]) @@ -237,7 +434,7 @@ def main.inspect # The default irb.context.newline_before_multiline_output = true - out, err = capture_io do + out, err = capture_output do irb.eval_input end assert_empty err @@ -247,12 +444,183 @@ def main.inspect # No newline before multiline output input.reset irb.context.newline_before_multiline_output = false - out, err = capture_io do + out, err = capture_output do irb.eval_input end assert_empty err assert_equal("=> abc\ndef\n", out) end + + def test_default_return_format + IRB.conf[:PROMPT][:MY_PROMPT] = { + :PROMPT_I => "%03n> ", + :PROMPT_N => "%03n> ", + :PROMPT_S => "%03n> ", + :PROMPT_C => "%03n> " + # without :RETURN + # :RETURN => "%s\n" + } + IRB.conf[:PROMPT_MODE] = :MY_PROMPT + input = TestInputMethod.new([ + "3" + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_equal("3\n", + out) + end + + def test_eval_input_with_exception + pend if RUBY_ENGINE == 'truffleruby' + verbose, $VERBOSE = $VERBOSE, nil + input = TestInputMethod.new([ + "def hoge() fuga; end; def fuga() raise; end; hoge\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty? + expected = [ + :*, /Traceback \(most recent call last\):\n/, + :*, /\t 2: from \(irb\):1:in `
      '\n/, + :*, /\t 1: from \(irb\):1:in `hoge'\n/, + :*, /\(irb\):1:in `fuga': unhandled exception\n/, + ] + else + expected = [ + :*, /\(irb\):1:in `fuga': unhandled exception\n/, + :*, /\tfrom \(irb\):1:in `hoge'\n/, + :*, /\tfrom \(irb\):1:in `
      '\n/, + :* + ] + end + assert_pattern_list(expected, out) + ensure + $VERBOSE = verbose + end + + def test_eval_input_with_invalid_byte_sequence_exception + pend if RUBY_ENGINE == 'truffleruby' + verbose, $VERBOSE = $VERBOSE, nil + input = TestInputMethod.new([ + %Q{def hoge() fuga; end; def fuga() raise "A\\xF3B"; end; hoge\n}, + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty? + expected = [ + :*, /Traceback \(most recent call last\):\n/, + :*, /\t 2: from \(irb\):1:in `
      '\n/, + :*, /\t 1: from \(irb\):1:in `hoge'\n/, + :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/, + ] + else + expected = [ + :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/, + :*, /\tfrom \(irb\):1:in `hoge'\n/, + :*, /\tfrom \(irb\):1:in `
      '\n/, + :* + ] + end + assert_pattern_list(expected, out) + ensure + $VERBOSE = verbose + end + + def test_eval_input_with_long_exception + pend if RUBY_ENGINE == 'truffleruby' + verbose, $VERBOSE = $VERBOSE, nil + nesting = 20 + generated_code = '' + nesting.times do |i| + generated_code << "def a#{i}() a#{i + 1}; end; " + end + generated_code << "def a#{nesting}() raise; end; a0\n" + input = TestInputMethod.new([ + generated_code + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty? + expected = [ + :*, /Traceback \(most recent call last\):\n/, + :*, /\t... \d+ levels...\n/, + :*, /\t16: from \(irb\):1:in `a4'\n/, + :*, /\t15: from \(irb\):1:in `a5'\n/, + :*, /\t14: from \(irb\):1:in `a6'\n/, + :*, /\t13: from \(irb\):1:in `a7'\n/, + :*, /\t12: from \(irb\):1:in `a8'\n/, + :*, /\t11: from \(irb\):1:in `a9'\n/, + :*, /\t10: from \(irb\):1:in `a10'\n/, + :*, /\t 9: from \(irb\):1:in `a11'\n/, + :*, /\t 8: from \(irb\):1:in `a12'\n/, + :*, /\t 7: from \(irb\):1:in `a13'\n/, + :*, /\t 6: from \(irb\):1:in `a14'\n/, + :*, /\t 5: from \(irb\):1:in `a15'\n/, + :*, /\t 4: from \(irb\):1:in `a16'\n/, + :*, /\t 3: from \(irb\):1:in `a17'\n/, + :*, /\t 2: from \(irb\):1:in `a18'\n/, + :*, /\t 1: from \(irb\):1:in `a19'\n/, + :*, /\(irb\):1:in `a20': unhandled exception\n/, + ] + else + expected = [ + :*, /\(irb\):1:in `a20': unhandled exception\n/, + :*, /\tfrom \(irb\):1:in `a19'\n/, + :*, /\tfrom \(irb\):1:in `a18'\n/, + :*, /\tfrom \(irb\):1:in `a17'\n/, + :*, /\tfrom \(irb\):1:in `a16'\n/, + :*, /\tfrom \(irb\):1:in `a15'\n/, + :*, /\tfrom \(irb\):1:in `a14'\n/, + :*, /\tfrom \(irb\):1:in `a13'\n/, + :*, /\tfrom \(irb\):1:in `a12'\n/, + :*, /\tfrom \(irb\):1:in `a11'\n/, + :*, /\tfrom \(irb\):1:in `a10'\n/, + :*, /\tfrom \(irb\):1:in `a9'\n/, + :*, /\tfrom \(irb\):1:in `a8'\n/, + :*, /\tfrom \(irb\):1:in `a7'\n/, + :*, /\tfrom \(irb\):1:in `a6'\n/, + :*, /\tfrom \(irb\):1:in `a5'\n/, + :*, /\tfrom \(irb\):1:in `a4'\n/, + :*, /\t... \d+ levels...\n/, + ] + end + assert_pattern_list(expected, out) + ensure + $VERBOSE = verbose + end + + def test_lineno + input = TestInputMethod.new([ + "\n", + "__LINE__\n", + "__LINE__\n", + "\n", + "\n", + "__LINE__\n", + ]) + irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input) + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_pattern_list([ + :*, /\b2\n/, + :*, /\b3\n/, + :*, /\b6\n/, + ], out) + end end end diff --git a/ruby/test/irb/test_history.rb b/ruby/test/irb/test_history.rb new file mode 100644 index 000000000..81b7fe867 --- /dev/null +++ b/ruby/test/irb/test_history.rb @@ -0,0 +1,211 @@ +# frozen_string_literal: false +require 'test/unit' +require 'irb' +require 'irb/ext/save-history' +require 'readline' + +module TestIRB + class TestHistory < Test::Unit::TestCase + def setup + IRB.conf[:RC_NAME_GENERATOR] = nil + end + + def teardown + IRB.conf[:RC_NAME_GENERATOR] = nil + end + + class TestInputMethod < ::IRB::InputMethod + HISTORY = Array.new + + include IRB::HistorySavingAbility + + attr_reader :list, :line_no + + def initialize(list = []) + super("test") + @line_no = 0 + @list = list + end + + def gets + @list[@line_no]&.tap {@line_no += 1} + end + + def eof? + @line_no >= @list.size + end + + def encoding + Encoding.default_external + end + + def reset + @line_no = 0 + end + + def winsize + [10, 20] + end + end + + def test_history_save_1 + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + IRB.conf[:SAVE_HISTORY] = 1 + assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) + exit + EXPECTED_HISTORY + 1 + 2 + 3 + 4 + INITIAL_HISTORY + 5 + exit + INPUT + end + + def test_history_save_100 + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + IRB.conf[:SAVE_HISTORY] = 100 + assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) + 1 + 2 + 3 + 4 + 5 + exit + EXPECTED_HISTORY + 1 + 2 + 3 + 4 + INITIAL_HISTORY + 5 + exit + INPUT + end + + def test_history_save_bignum + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + IRB.conf[:SAVE_HISTORY] = 10 ** 19 + assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) + 1 + 2 + 3 + 4 + 5 + exit + EXPECTED_HISTORY + 1 + 2 + 3 + 4 + INITIAL_HISTORY + 5 + exit + INPUT + end + + def test_history_save_minus_as_infinity + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + IRB.conf[:SAVE_HISTORY] = -1 # infinity + assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) + 1 + 2 + 3 + 4 + 5 + exit + EXPECTED_HISTORY + 1 + 2 + 3 + 4 + INITIAL_HISTORY + 5 + exit + INPUT + end + + def test_history_concurrent_use + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + IRB.conf[:SAVE_HISTORY] = 1 + assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) do |history_file| + exit + 5 + exit + EXPECTED_HISTORY + 1 + 2 + 3 + 4 + INITIAL_HISTORY + 5 + exit + INPUT + assert_history(<<~EXPECTED_HISTORY2, <<~INITIAL_HISTORY2, <<~INPUT2) + exit + EXPECTED_HISTORY2 + 1 + 2 + 3 + 4 + INITIAL_HISTORY2 + 5 + exit + INPUT2 + File.utime(File.atime(history_file), File.mtime(history_file) + 2, history_file) + end + end + + private + + def assert_history(expected_history, initial_irb_history, input) + backup_verbose, $VERBOSE = $VERBOSE, nil + backup_home = ENV["HOME"] + backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME") + IRB.conf[:LC_MESSAGES] = IRB::Locale.new + actual_history = nil + Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir| + ENV["HOME"] = tmpdir + open(IRB.rc_file("_history"), "w") do |f| + f.write(initial_irb_history) + end + + io = TestInputMethod.new + io.class::HISTORY.clear + io.load_history + if block_given? + history = io.class::HISTORY.dup + yield IRB.rc_file("_history") + io.class::HISTORY.replace(history) + end + io.class::HISTORY.concat(input.split) + io.save_history + + io.load_history + open(IRB.rc_file("_history"), "r") do |f| + actual_history = f.read + end + end + assert_equal(expected_history, actual_history, <<~MESSAGE) + expected: + #{expected_history} + but actual: + #{actual_history} + MESSAGE + ensure + $VERBOSE = backup_verbose + ENV["HOME"] = backup_home + ENV["XDG_CONFIG_HOME"] = backup_xdg_config_home + end + + def with_temp_stdio + Tempfile.create("test_readline_stdin") do |stdin| + Tempfile.create("test_readline_stdout") do |stdout| + yield stdin, stdout + end + end + end + end +end if not RUBY_PLATFORM.match?(/solaris|mswin|mingw/i) diff --git a/ruby/test/irb/test_init.rb b/ruby/test/irb/test_init.rb index b51d01096..d8c7c7926 100644 --- a/ruby/test/irb/test_init.rb +++ b/ruby/test/irb/test_init.rb @@ -5,6 +5,19 @@ module TestIRB class TestInit < Test::Unit::TestCase + def setup + # IRBRC is for RVM... + @backup_env = %w[HOME XDG_CONFIG_HOME IRBRC].each_with_object({}) do |env, hash| + hash[env] = ENV.delete(env) + end + ENV["HOME"] = @tmpdir = Dir.mktmpdir("test_irb_init_#{$$}") + end + + def teardown + ENV.update(@backup_env) + FileUtils.rm_rf(@tmpdir) + end + def test_setup_with_argv_preserves_global_argv argv = ["foo", "bar"] with_argv(argv) do @@ -20,11 +33,8 @@ def test_setup_with_minimum_argv_does_not_change_dollar0 end def test_rc_file - backup_irbrc = ENV.delete("IRBRC") # This is for RVM... - backup_home = ENV["HOME"] - Dir.mktmpdir("test_irb_init_#{$$}") do |tmpdir| - ENV["HOME"] = tmpdir - + tmpdir = @tmpdir + Dir.chdir(tmpdir) do IRB.conf[:RC_NAME_GENERATOR] = nil assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file) assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history")) @@ -33,17 +43,11 @@ def test_rc_file assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file) assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history")) end - ensure - ENV["HOME"] = backup_home - ENV["IRBRC"] = backup_irbrc end def test_rc_file_in_subdir - backup_irbrc = ENV.delete("IRBRC") # This is for RVM... - backup_home = ENV["HOME"] - Dir.mktmpdir("test_irb_init_#{$$}") do |tmpdir| - ENV["HOME"] = tmpdir - + tmpdir = @tmpdir + Dir.chdir(tmpdir) do FileUtils.mkdir_p("#{tmpdir}/mydir") Dir.chdir("#{tmpdir}/mydir") do IRB.conf[:RC_NAME_GENERATOR] = nil @@ -55,9 +59,32 @@ def test_rc_file_in_subdir assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history")) end end + end + + def test_recovery_sigint + pend "This test gets stuck on Solaris for unknown reason; contribution is welcome" if RUBY_PLATFORM =~ /solaris/ + bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] + status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e binding.irb;loop{Process.kill("SIGINT",$$)} -- -f --], "exit\n", //, //) + Process.kill("SIGKILL", status.pid) if !status.exited? && !status.stopped? && !status.signaled? + end + + def test_no_color_environment_variable + orig_no_color = ENV['NO_COLOR'] + orig_use_colorize = IRB.conf[:USE_COLORIZE] + IRB.conf[:USE_COLORIZE] = true + + assert IRB.conf[:USE_COLORIZE] + + ENV['NO_COLOR'] = 'true' + IRB.setup(__FILE__) + refute IRB.conf[:USE_COLORIZE] + + ENV['NO_COLOR'] = nil + IRB.setup(__FILE__) + assert IRB.conf[:USE_COLORIZE] ensure - ENV["HOME"] = backup_home - ENV["IRBRC"] = backup_irbrc + ENV['NO_COLOR'] = orig_no_color + IRB.conf[:USE_COLORIZE] = orig_use_colorize end private diff --git a/ruby/test/irb/test_raise_no_backtrace_exception.rb b/ruby/test/irb/test_raise_no_backtrace_exception.rb index 217460008..530adc0cb 100644 --- a/ruby/test/irb/test_raise_no_backtrace_exception.rb +++ b/ruby/test/irb/test_raise_no_backtrace_exception.rb @@ -4,6 +4,7 @@ module TestIRB class TestRaiseNoBacktraceException < Test::Unit::TestCase def test_raise_exception + pend if RUBY_ENGINE == 'truffleruby' bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, []) e = Exception.new("foo") @@ -12,5 +13,42 @@ def e.backtrace; nil; end raise e IRB end + + def test_raise_exception_with_invalid_byte_sequence + pend if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM + bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] + assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<~IRB, /A\\xF3B \(StandardError\)/, []) + raise StandardError, "A\\xf3B" + IRB + end + + def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence + pend if RUBY_ENGINE == 'truffleruby' + backup_home = ENV["HOME"] + Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir| + ENV["HOME"] = tmpdir + + bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] + File.open("#{tmpdir}/euc.rb", 'w') do |f| + f.write(<<~EOF) + # encoding: euc-jp + + def raise_euc_with_invalid_byte_sequence + raise "\xA4\xA2\\xFF" + end + EOF + end + env = {} + %w(LC_MESSAGES LC_ALL LC_CTYPE LANG).each {|n| env[n] = "ja_JP.UTF-8" } + args = [env] + bundle_exec + %W[-rirb -C #{tmpdir} -W0 -e IRB.start(__FILE__) -- -f --] + error = /`raise_euc_with_invalid_byte_sequence': ã‚\\xFF \(RuntimeError\)/ + assert_in_out_err(args, <<~IRB, error, [], encoding: "UTF-8") + require_relative 'euc' + raise_euc_with_invalid_byte_sequence + IRB + end + ensure + ENV["HOME"] = backup_home + end end end diff --git a/ruby/test/irb/test_ruby_lex.rb b/ruby/test/irb/test_ruby_lex.rb index dd5a1f7ca..47435d675 100644 --- a/ruby/test/irb/test_ruby_lex.rb +++ b/ruby/test/irb/test_ruby_lex.rb @@ -5,9 +5,9 @@ module TestIRB class TestRubyLex < Test::Unit::TestCase - Row = Struct.new(:content, :current_line_spaces, :new_line_spaces) + Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level) - class MockIO + class MockIO_AutoIndent def initialize(params, &assertion) @params = params @assertion = assertion @@ -25,7 +25,7 @@ def assert_indenting(lines, correct_space_count, add_new_line) byte_pointer = lines.last.length ruby_lex = RubyLex.new() - io = MockIO.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent| + io = MockIO_AutoIndent.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent| error_message = "Calculated the wrong number of spaces for:\n #{lines.join("\n")}" assert_equal(correct_space_count, auto_indent, error_message) end @@ -34,6 +34,15 @@ def assert_indenting(lines, correct_space_count, add_new_line) ruby_lex.set_auto_indent(context) end + def assert_nesting_level(lines, expected) + ruby_lex = RubyLex.new() + io = proc{ lines.join("\n") } + ruby_lex.set_input(io, io) + ruby_lex.lex + error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}" + assert_equal(expected, ruby_lex.instance_variable_get(:@indent), error_message) + end + def test_auto_indent input_with_correct_indents = [ Row.new(%q(def each_top_level_statement), nil, 2), @@ -100,8 +109,8 @@ def test_multiple_braces_in_a_line Row.new(%q( ]), 4, 4), Row.new(%q( ]), 2, 2), Row.new(%q(]), 0, 0), - Row.new(%q([< ', %q(a = 3..)), + PromptRow.new('002:0: :* ', %q()), + ] + + lines = input_with_prompt.map(&:content) + expected_prompt_list = input_with_prompt.map(&:prompt) + assert_dynamic_prompt(lines, expected_prompt_list) + end + + def test_incomplete_coding_magic_comment + input_with_correct_indents = [ + Row.new(%q(#coding:u), nil, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_incomplete_encoding_magic_comment + input_with_correct_indents = [ + Row.new(%q(#encoding:u), nil, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_incomplete_emacs_coding_magic_comment + input_with_correct_indents = [ + Row.new(%q(# -*- coding: u), nil, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_incomplete_vim_coding_magic_comment + input_with_correct_indents = [ + Row.new(%q(# vim:set fileencoding=u), nil, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_mixed_rescue + input_with_correct_indents = [ + Row.new(%q(def m), nil, 2), + Row.new(%q( begin), nil, 4), + Row.new(%q( begin), nil, 6), + Row.new(%q( x = a rescue 4), nil, 6), + Row.new(%q( y = [(a rescue 5)]), nil, 6), + Row.new(%q( [x, y]), nil, 6), + Row.new(%q( rescue => e), 4, 6), + Row.new(%q( raise e rescue 8), nil, 6), + Row.new(%q( end), 4, 4), + Row.new(%q( rescue), 2, 4), + Row.new(%q( raise rescue 11), nil, 4), + Row.new(%q( end), 2, 2), + Row.new(%q(rescue => e), 0, 2), + Row.new(%q( raise e rescue 14), nil, 2), + Row.new(%q(end), 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_oneliner_method_definition + input_with_correct_indents = [ + Row.new(%q(class A), nil, 2), + Row.new(%q( def foo0), nil, 4), + Row.new(%q( 3), nil, 4), + Row.new(%q( end), 2, 2), + Row.new(%q( def foo1()), nil, 4), + Row.new(%q( 3), nil, 4), + Row.new(%q( end), 2, 2), + Row.new(%q( def foo2(a, b)), nil, 4), + Row.new(%q( a + b), nil, 4), + Row.new(%q( end), 2, 2), + Row.new(%q( def foo3 a, b), nil, 4), + Row.new(%q( a + b), nil, 4), + Row.new(%q( end), 2, 2), + Row.new(%q( def bar0() = 3), nil, 2), + Row.new(%q( def bar1(a) = a), nil, 2), + Row.new(%q( def bar2(a, b) = a + b), nil, 2), + Row.new(%q( def bar3() = :s), nil, 2), + Row.new(%q( def bar4() = Time.now), nil, 2), + Row.new(%q(end), 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + end + end + + def test_tlambda + input_with_correct_indents = [ + Row.new(%q(if true), nil, 2, 1), + Row.new(%q( -> {), nil, 4, 2), + Row.new(%q( }), 2, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_corresponding_syntax_to_keyword_do_in_class + input_with_correct_indents = [ + Row.new(%q(class C), nil, 2, 1), + Row.new(%q( while method_name do), nil, 4, 2), + Row.new(%q( 3), nil, 4, 2), + Row.new(%q( end), 2, 2, 1), + Row.new(%q( foo do), nil, 4, 2), + Row.new(%q( 3), nil, 4, 2), + Row.new(%q( end), 2, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_corresponding_syntax_to_keyword_do + input_with_correct_indents = [ + Row.new(%q(while i > 0), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while true), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while ->{i > 0}.call), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while ->{true}.call), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while i > 0 do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while true do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while ->{i > 0}.call do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(while ->{true}.call do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(foo do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(foo true do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(foo ->{true} do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(foo ->{i > 0} do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_corresponding_syntax_to_keyword_for + input_with_correct_indents = [ + Row.new(%q(for i in [1]), nil, 2, 1), + Row.new(%q( puts i), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_corresponding_syntax_to_keyword_for_with_do + input_with_correct_indents = [ + Row.new(%q(for i in [1] do), nil, 2, 1), + Row.new(%q( puts i), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_corresponding_syntax_to_keyword_in + input_with_correct_indents = [ + Row.new(%q(module E), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + Row.new(%q(class A), nil, 2, 1), + Row.new(%q( in), nil, 4, 1) + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_bracket_corresponding_to_times + input_with_correct_indents = [ + Row.new(%q(3.times { |i|), nil, 2, 1), + Row.new(%q( puts i), nil, 2, 1), + Row.new(%q(}), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_do_corresponding_to_times + input_with_correct_indents = [ + Row.new(%q(3.times do |i|), nil, 2, 1), + #Row.new(%q( puts i), nil, 2, 1), + #Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_bracket_corresponding_to_loop + input_with_correct_indents = [ + Row.new(%q(loop {), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(}), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_do_corresponding_to_loop + input_with_correct_indents = [ + Row.new(%q(loop do), nil, 2, 1), + Row.new(%q( 3), nil, 2, 1), + Row.new(%q(end), 0, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_heredoc_with_indent + input_with_correct_indents = [ + Row.new(%q(<<~Q), 0, 0, 0), + Row.new(%q({), 0, 0, 0), + Row.new(%q( #), 2, 0, 0), + Row.new(%q(}), 0, 0, 0) + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_oneliner_def_in_multiple_lines + input_with_correct_indents = [ + Row.new(%q(def a()=[), nil, 4, 2), + Row.new(%q( 1,), nil, 4, 1), + Row.new(%q(].), 0, 0, 0), + Row.new(%q(to_s), nil, 0, 0), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + def test_broken_heredoc + if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') + pend 'This test needs Ripper::Lexer#scan to take broken tokens' + end + input_with_correct_indents = [ + Row.new(%q(def foo), nil, 2, 1), + Row.new(%q( <<~Q), 2, 2, 1), + Row.new(%q( Qend), 2, 2, 1), + ] + + lines = [] + input_with_correct_indents.each do |row| + lines << row.content + assert_indenting(lines, row.current_line_spaces, false) + assert_indenting(lines, row.new_line_spaces, true) + assert_nesting_level(lines, row.nesting_level) + end + end + + PromptRow = Struct.new(:prompt, :content) + + class MockIO_DynamicPrompt + def initialize(params, &assertion) + @params = params + @assertion = assertion + end + + def dynamic_prompt(&block) + result = block.call(@params) + @assertion.call(result) + end + end + + def assert_dynamic_prompt(lines, expected_prompt_list) + pend if RUBY_ENGINE == 'truffleruby' + ruby_lex = RubyLex.new() + io = MockIO_DynamicPrompt.new(lines) do |prompt_list| + error_message = <<~EOM + Expected dynamic prompt: + #{expected_prompt_list.join("\n")} + + Actual dynamic prompt: + #{prompt_list.join("\n")} + EOM + assert_equal(expected_prompt_list, prompt_list, error_message) + end + ruby_lex.set_prompt do |ltype, indent, continue, line_no| + '%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>'] + end + ruby_lex.set_input(io) + end + + def test_dyanmic_prompt + input_with_prompt = [ + PromptRow.new('001:1: :* ', %q(def hoge)), + PromptRow.new('002:1: :* ', %q( 3)), + PromptRow.new('003:0: :> ', %q(end)), + ] + + lines = input_with_prompt.map(&:content) + expected_prompt_list = input_with_prompt.map(&:prompt) + assert_dynamic_prompt(lines, expected_prompt_list) + end + + def test_dyanmic_prompt_with_blank_line + input_with_prompt = [ + PromptRow.new('001:0:]:* ', %q(%w[)), + PromptRow.new('002:0:]:* ', %q()), + PromptRow.new('003:0: :> ', %q(])), + ] + + lines = input_with_prompt.map(&:content) + expected_prompt_list = input_with_prompt.map(&:prompt) + assert_dynamic_prompt(lines, expected_prompt_list) + end + + def test_broken_percent_literal + if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') + pend 'This test needs Ripper::Lexer#scan to take broken tokens' + end + + tokens = RubyLex.ripper_lex_without_warning('%wwww') + pos_to_index = {} + tokens.each_with_index { |t, i| + assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.") + pos_to_index[t.pos] = i + } + end + + def test_broken_percent_literal_in_method + if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') + pend 'This test needs Ripper::Lexer#scan to take broken tokens' + end + + tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp) + def foo + %wwww + end + EOC + pos_to_index = {} + tokens.each_with_index { |t, i| + assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.") + pos_to_index[t.pos] = i + } + end end end diff --git a/ruby/test/irb/test_workspace.rb b/ruby/test/irb/test_workspace.rb index 992cdd451..1a1dc1f49 100644 --- a/ruby/test/irb/test_workspace.rb +++ b/ruby/test/irb/test_workspace.rb @@ -1,6 +1,7 @@ # frozen_string_literal: false require 'test/unit' require 'tempfile' +require 'rubygems' require 'irb' require 'irb/workspace' require 'irb/color' @@ -8,6 +9,7 @@ module TestIRB class TestWorkSpace < Test::Unit::TestCase def test_code_around_binding + IRB.conf[:USE_COLORIZE] = false Tempfile.create('irb') do |f| code = <<~RUBY # 1 @@ -32,11 +34,13 @@ def test_code_around_binding EOS end + ensure + IRB.conf.delete(:USE_COLORIZE) end def test_code_around_binding_with_existing_unreadable_file - skip 'chmod cannot make file unreadable on windows' if windows? - skip 'skipped in root privilege' if Process.uid == 0 + pend 'chmod cannot make file unreadable on windows' if windows? + pend 'skipped in root privilege' if Process.uid == 0 Tempfile.create('irb') do |f| code = "IRB::WorkSpace.new(binding)\n" @@ -51,6 +55,7 @@ def test_code_around_binding_with_existing_unreadable_file end def test_code_around_binding_with_script_lines__ + IRB.conf[:USE_COLORIZE] = false with_script_lines do |script_lines| Tempfile.create('irb') do |f| code = "IRB::WorkSpace.new(binding)\n" @@ -66,6 +71,8 @@ def test_code_around_binding_with_script_lines__ EOS end end + ensure + IRB.conf.delete(:USE_COLORIZE) end def test_code_around_binding_on_irb @@ -73,6 +80,23 @@ def test_code_around_binding_on_irb assert_equal(nil, workspace.code_around_binding) end + + def test_toplevel_binding_local_variables + pend if RUBY_ENGINE == 'truffleruby' + bug17623 = '[ruby-core:102468]' + bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] + top_srcdir = "#{__dir__}/../.." + irb_path = nil + %w[exe libexec].find do |dir| + irb_path = "#{top_srcdir}/#{dir}/irb" + File.exist?(irb_path) + end or omit 'irb command not found' + assert_in_out_err(bundle_exec + ['-W0', "-C#{top_srcdir}", '-e', <<~RUBY , '--', '-f', '--'], 'binding.local_variables', /\[:_\]/, [], bug17623) + version = 'xyz' # typical rubygems loading file + load('#{irb_path}') + RUBY + end + private def with_script_lines diff --git a/ruby/test/irb/yamatanooroti/test_rendering.rb b/ruby/test/irb/yamatanooroti/test_rendering.rb new file mode 100644 index 000000000..7ed98b11c --- /dev/null +++ b/ruby/test/irb/yamatanooroti/test_rendering.rb @@ -0,0 +1,228 @@ +require 'irb' + +begin + require 'yamatanooroti' + + class IRB::TestRendering < Yamatanooroti::TestCase + def setup + @pwd = Dir.pwd + suffix = '%010d' % Random.rand(0..65535) + @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}") + begin + Dir.mkdir(@tmpdir) + rescue Errno::EEXIST + FileUtils.rm_rf(@tmpdir) + Dir.mkdir(@tmpdir) + end + @irbrc_backup = ENV['IRBRC'] + @irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc') + File.unlink(@irbrc_file) if File.exist?(@irbrc_file) + end + + def teardown + FileUtils.rm_rf(@tmpdir) + ENV['IRBRC'] = @irbrc_backup + ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT'] + end + + def test_launch + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write(<<~EOC) + 'Hello, World!' + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001:0> 'Hello, World!' + => "Hello, World!" + irb(main):002:0> + EOC + end + + def test_multiline_paste + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write(<<~EOC) + class A + def inspect; '#'; end + def a; self; end + def b; true; end + end + + a = A.new + + a + .a + .b + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001:1* class A + irb(main):002:1* def inspect; '#'; end + irb(main):003:1* def a; self; end + irb(main):004:1* def b; true; end + irb(main):005:0> end + => :b + irb(main):006:0> + irb(main):007:0> a = A.new + => # + irb(main):008:0> + irb(main):009:0> a + irb(main):010:0> .a + irb(main):011:0> .b + => true + irb(main):012:0> + EOC + end + + def test_evaluate_each_toplevel_statement_by_multiline_paste + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write(<<~EOC) + class A + def inspect; '#'; end + def b; self; end + def c; true; end + end + + a = A.new + + a + .b + # aaa + .c + + (a) + &.b() + + + class A def b; self; end; def c; true; end; end; + a = A.new + a + .b + # aaa + .c + (a) + &.b() + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001:1* class A + irb(main):002:1* def inspect; '#'; end + irb(main):003:1* def b; self; end + irb(main):004:1* def c; true; end + irb(main):005:0> end + => :c + irb(main):006:0> + irb(main):007:0> a = A.new + => # + irb(main):008:0> + irb(main):009:0> a + irb(main):010:0> .b + irb(main):011:0> # aaa + irb(main):012:0> .c + => true + irb(main):013:0> + irb(main):014:0> (a) + irb(main):015:0> &.b() + => # + irb(main):016:0> + irb(main):017:0> + irb(main):018:0> class A def b; self; end; def c; true; end; end; + => :c + irb(main):019:0> a = A.new + => # + irb(main):020:0> a + irb(main):021:0> .b + irb(main):022:0> # aaa + irb(main):023:0> .c + => true + irb(main):024:0> (a) + irb(main):025:0> &.b() + => # + irb(main):026:0> + EOC + end + + def test_symbol_with_backtick + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write(<<~EOC) + :` + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001:0> :` + => :` + irb(main):002:0> + EOC + end + + def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right + pend "Needs a dummy document to show doc" + write_irbrc <<~'LINES' + IRB.conf[:PROMPT][:MY_PROMPT] = { + :PROMPT_I => "%03n> ", + :PROMPT_N => "%03n> ", + :PROMPT_S => "%03n> ", + :PROMPT_C => "%03n> " + } + IRB.conf[:PROMPT_MODE] = :MY_PROMPT + puts 'start IRB' + LINES + start_terminal(4, 19, %W{ruby -I/home/aycabta/ruby/reline/lib -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("Str\C-i") + close + assert_screen(<<~EOC) + 001> String + StringPress A + StructString + of byte + EOC + end + + def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_left + pend "Needs a dummy document to show doc" + write_irbrc <<~'LINES' + IRB.conf[:PROMPT][:MY_PROMPT] = { + :PROMPT_I => "%03n> ", + :PROMPT_N => "%03n> ", + :PROMPT_S => "%03n> ", + :PROMPT_C => "%03n> " + } + IRB.conf[:PROMPT_MODE] = :MY_PROMPT + puts 'start IRB' + LINES + start_terminal(4, 12, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("Str\C-i") + close + assert_screen(<<~EOC) + 001> String + PressString + StrinStruct + of by + EOC + end + + private def write_irbrc(content) + File.open(@irbrc_file, 'w') do |f| + f.write content + end + end + end +rescue LoadError, NameError + # On Ruby repository, this test suit doesn't run because Ruby repo doesn't + # have the yamatanooroti gem. +end diff --git a/ruby/test/json/fixtures/fail29.json b/ruby/test/json/fixtures/fail29.json new file mode 100644 index 000000000..98232c64f --- /dev/null +++ b/ruby/test/json/fixtures/fail29.json @@ -0,0 +1 @@ +{ diff --git a/ruby/test/json/fixtures/fail30.json b/ruby/test/json/fixtures/fail30.json new file mode 100644 index 000000000..558ed37d9 --- /dev/null +++ b/ruby/test/json/fixtures/fail30.json @@ -0,0 +1 @@ +[ diff --git a/ruby/test/json/fixtures/fail31.json b/ruby/test/json/fixtures/fail31.json new file mode 100644 index 000000000..70773e47f --- /dev/null +++ b/ruby/test/json/fixtures/fail31.json @@ -0,0 +1 @@ +[1, 2, 3, diff --git a/ruby/test/json/fixtures/fail32.json b/ruby/test/json/fixtures/fail32.json new file mode 100644 index 000000000..b18d550ca --- /dev/null +++ b/ruby/test/json/fixtures/fail32.json @@ -0,0 +1 @@ +{"foo": "bar" diff --git a/ruby/test/json/json_addition_test.rb b/ruby/test/json/json_addition_test.rb index 61625f89e..e95ace837 100644 --- a/ruby/test/json/json_addition_test.rb +++ b/ruby/test/json/json_addition_test.rb @@ -195,9 +195,5 @@ def test_ostruct def test_set s = Set.new([:a, :b, :c, :a]) assert_equal s, JSON.parse(JSON(s), :create_additions => true) - ss = SortedSet.new([:d, :b, :a, :c]) - ss_again = JSON.parse(JSON(ss), :create_additions => true) - assert_kind_of ss.class, ss_again - assert_equal ss, ss_again end end diff --git a/ruby/test/json/json_common_interface_test.rb b/ruby/test/json/json_common_interface_test.rb index 53f335ed3..9148b78c8 100644 --- a/ruby/test/json/json_common_interface_test.rb +++ b/ruby/test/json/json_common_interface_test.rb @@ -123,4 +123,47 @@ def test_JSON assert_equal @json, JSON(@hash) assert_equal @hash, JSON(@json) end + + def test_load_file + test_load_shared(:load_file) + end + + def test_load_file! + test_load_shared(:load_file!) + end + + def test_load_file_with_option + test_load_file_with_option_shared(:load_file) + end + + def test_load_file_with_option! + test_load_file_with_option_shared(:load_file!) + end + + private + + def test_load_shared(method_name) + temp_file_containing(@json) do |filespec| + assert_equal JSON.public_send(method_name, filespec), @hash + end + end + + def test_load_file_with_option_shared(method_name) + temp_file_containing(@json) do |filespec| + parsed_object = JSON.public_send(method_name, filespec, symbolize_names: true) + key_classes = parsed_object.keys.map(&:class) + assert_include(key_classes, Symbol) + assert_not_include(key_classes, String) + end + end + + def temp_file_containing(text, file_prefix = '') + raise "This method must be called with a code block." unless block_given? + + Tempfile.create(file_prefix) do |file| + file << text + file.close + yield file.path + end + end end diff --git a/ruby/test/json/json_fixtures_test.rb b/ruby/test/json/json_fixtures_test.rb index 01954fe70..845abb486 100644 --- a/ruby/test/json/json_fixtures_test.rb +++ b/ruby/test/json/json_fixtures_test.rb @@ -3,13 +3,14 @@ class JSONFixturesTest < Test::Unit::TestCase def setup - fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}.json') + fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json') passed, failed = Dir[fixtures].partition { |f| f['pass'] } @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort end def test_passing + verbose_bak, $VERBOSE = $VERBOSE, nil for name, source in @passed begin assert JSON.parse(source), @@ -19,6 +20,8 @@ def test_passing raise e end end + ensure + $VERBOSE = verbose_bak end def test_failing @@ -29,4 +32,9 @@ def test_failing end end end + + def test_sanity + assert(@passed.size > 5) + assert(@failed.size > 20) + end end diff --git a/ruby/test/json/json_generator_test.rb b/ruby/test/json/json_generator_test.rb index ee19fa5e6..f31b6b290 100644 --- a/ruby/test/json/json_generator_test.rb +++ b/ruby/test/json/json_generator_test.rb @@ -48,36 +48,6 @@ def silence $VERBOSE = v end - def test_remove_const_segv - return if RUBY_ENGINE == 'jruby' - stress = GC.stress - const = JSON::SAFE_STATE_PROTOTYPE.dup - - bignum_too_long_to_embed_as_string = 1234567890123456789012345 - expect = bignum_too_long_to_embed_as_string.to_s - GC.stress = true - - 10.times do |i| - tmp = bignum_too_long_to_embed_as_string.to_json - raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect - end - - silence do - JSON.const_set :SAFE_STATE_PROTOTYPE, nil - end - - 10.times do |i| - assert_raise TypeError do - bignum_too_long_to_embed_as_string.to_json - end - end - ensure - GC.stress = stress - silence do - JSON.const_set :SAFE_STATE_PROTOTYPE, const - end - end if JSON.const_defined?("Ext") - def test_generate json = generate(@hash) assert_equal(parse(@json2), parse(json)) @@ -93,6 +63,11 @@ def test_generate end def test_generate_pretty + json = pretty_generate({}) + assert_equal(<<'EOT'.chomp, json) +{ +} +EOT json = pretty_generate(@hash) # hashes aren't (insertion) ordered on every ruby implementation # assert_equal(@json3, json) @@ -167,13 +142,14 @@ def test_states end def test_pretty_state - state = PRETTY_STATE_PROTOTYPE.dup + state = JSON.create_pretty_state assert_equal({ :allow_nan => false, :array_nl => "\n", :ascii_only => false, :buffer_initial_length => 1024, :depth => 0, + :escape_slash => false, :indent => " ", :max_nesting => 100, :object_nl => "\n", @@ -183,13 +159,14 @@ def test_pretty_state end def test_safe_state - state = SAFE_STATE_PROTOTYPE.dup + state = JSON::State.new assert_equal({ :allow_nan => false, :array_nl => "", :ascii_only => false, :buffer_initial_length => 1024, :depth => 0, + :escape_slash => false, :indent => "", :max_nesting => 100, :object_nl => "", @@ -199,13 +176,14 @@ def test_safe_state end def test_fast_state - state = FAST_STATE_PROTOTYPE.dup + state = JSON.create_fast_state assert_equal({ :allow_nan => false, :array_nl => "", :ascii_only => false, :buffer_initial_length => 1024, :depth => 0, + :escape_slash => false, :indent => "", :max_nesting => 0, :object_nl => "", @@ -234,12 +212,8 @@ def test_allow_nan def test_depth ary = []; ary << ary - assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth assert_raise(JSON::NestingError) { generate(ary) } - assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth - assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) } - assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth s = JSON.state.new assert_equal 0, s.depth assert_raise(JSON::NestingError) { ary.to_json(s) } @@ -258,7 +232,7 @@ def test_buffer_initial_length end def test_gc - if respond_to?(:assert_in_out_err) + if respond_to?(:assert_in_out_err) && !(RUBY_PLATFORM =~ /java/) assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], []) bignum_too_long_to_embed_as_string = 1234567890123456789012345 expect = bignum_too_long_to_embed_as_string.to_s @@ -394,6 +368,10 @@ def test_backslash json = '["/"]' assert_equal json, generate(data) # + data = [ '/' ] + json = '["\/"]' + assert_equal json, generate(data, :escape_slash => true) + # data = ['"'] json = '["\""]' assert_equal json, generate(data) diff --git a/ruby/test/json/json_parser_test.rb b/ruby/test/json/json_parser_test.rb index 9946dd93e..dce693e54 100644 --- a/ruby/test/json/json_parser_test.rb +++ b/ruby/test/json/json_parser_test.rb @@ -218,6 +218,17 @@ def test_symbolize_names end end + def test_freeze + assert_predicate parse('{}', :freeze => true), :frozen? + assert_predicate parse('[]', :freeze => true), :frozen? + assert_predicate parse('"foo"', :freeze => true), :frozen? + + if string_deduplication_available? + assert_same(-'foo', parse('"foo"', :freeze => true)) + assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first) + end + end + def test_parse_comments json = < 2, + 'b' => 3.141, + 'c' => 'c', + 'd' => [ 1, "b", 3.14 ], + 'e' => { 'foo' => 'bar' }, + 'g' => "\"\0\037", + 'h' => 1000.0, + 'i' => 0.001 + }) + JSON.parse(json) + end + expected_json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' + + '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}' + assert_equal(JSON.parse(expected_json), r.take) + end; + end +end if defined?(Ractor) diff --git a/ruby/test/json/test_helper.rb b/ruby/test/json/test_helper.rb index c5ec0fca7..446c020e8 100644 --- a/ruby/test/json/test_helper.rb +++ b/ruby/test/json/test_helper.rb @@ -1,12 +1,12 @@ case ENV['JSON'] when 'pure' - $:.unshift 'lib' + $:.unshift File.join(__dir__, '../lib') require 'json/pure' when 'ext' - $:.unshift 'ext', 'lib' + $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib') require 'json/ext' else - $:.unshift 'ext', 'lib' + $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib') require 'json' end diff --git a/ruby/test/lib/jit_support.rb b/ruby/test/lib/jit_support.rb index 82c4a8938..6ad68f75b 100644 --- a/ruby/test/lib/jit_support.rb +++ b/ruby/test/lib/jit_support.rb @@ -3,14 +3,25 @@ module JITSupport JIT_TIMEOUT = 600 # 10min for each... JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)' + JIT_RECOMPILE_PREFIX = 'JIT recompile' JIT_COMPACTION_PREFIX = 'JIT compaction \(\d+\.\dms\)' UNSUPPORTED_COMPILERS = [ - %r[\A/opt/intel/.*/bin/intel64/icc\b], + %r[\A.*/bin/intel64/icc\b], %r[\A/opt/developerstudio\d+\.\d+/bin/cc\z], ] + # debian-riscv64: "gcc: internal compiler error: Segmentation fault signal terminated program cc1" https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian-riscv64/ruby-master/log/20200420T083601Z.fail.html.gz + # freebsd12: cc1 internal failure https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd12/ruby-master/log/20200306T103003Z.fail.html.gz + # rhel8: one or more PCH files were found, but they were invalid https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20200306T153003Z.fail.html.gz + # centos8: ditto https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos8/ruby-master/log/20200512T003004Z.fail.html.gz + PENDING_RUBYCI_NICKNAMES = %w[ + debian-riscv64 + freebsd12 + rhel8 + centos8 + ] module_function - # Run Ruby script with --jit-wait (Synchronous JIT compilation). + # Run Ruby script with --mjit-wait (Synchronous JIT compilation). # Returns [stdout, stderr] def eval_with_jit(env = nil, script, **opts) stdout, stderr = nil, nil @@ -25,12 +36,13 @@ def eval_with_jit(env = nil, script, **opts) def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT) args = [ - '--disable-gems', "--jit-verbose=#{verbose}", - "--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}", + '--disable-gems', "--mjit-verbose=#{verbose}", + "--mjit-min-calls=#{min_calls}", "--mjit-max-cache=#{max_cache}", ] - args << '--jit-wait' if wait - args << '--jit-save-temps' if save_temps - args << '--jit-debug' if defined?(@jit_debug) && @jit_debug + args << '--disable-yjit' + args << '--mjit-wait' if wait + args << '--mjit-save-temps' if save_temps + args << '--mjit-debug' if defined?(@mjit_debug) && @mjit_debug args << '-e' << script base_env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } # workaround to skip requiring `make install` for `make test-all` if preloadenv = RbConfig::CONFIG['PRELOADENV'] and !preloadenv.empty? @@ -45,13 +57,25 @@ def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, sav def supported? return @supported if defined?(@supported) - @supported = UNSUPPORTED_COMPILERS.all? do |regexp| + @supported = RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' && UNSUPPORTED_COMPILERS.all? do |regexp| !regexp.match?(RbConfig::CONFIG['MJIT_CC']) - end && RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' + end && !appveyor_pdb_corrupted? && !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME']) + end + + # AppVeyor's Visual Studio 2013 / 2015 are known to spuriously generate broken pch / pdb, like: + # error C2859: c:\projects\ruby\x64-mswin_120\include\ruby-2.8.0\x64-mswin64_120\rb_mjit_header-2.8.0.pdb + # is not the pdb file that was used when this precompiled header was created, recreate the precompiled header. + # https://ci.appveyor.com/project/ruby/ruby/builds/32159878/job/l2p38snw8yxxpp8h + # + # Until we figure out why, this allows us to skip testing JIT when it happens. + def appveyor_pdb_corrupted? + return false unless ENV.key?('APPVEYOR') + stdout, _stderr, _status = eval_with_jit_without_retry('proc {}.call', verbose: 2, min_calls: 1) + stdout.include?('.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.') end def remove_mjit_logs(stderr) - if RubyVM::MJIT.enabled? # utility for -DFORCE_MJIT_ENABLE + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # utility for -DFORCE_MJIT_ENABLE stderr.gsub(/^MJIT warning: Skipped to compile unsupported instruction: \w+\n/m, '') else stderr diff --git a/ruby/test/logger/helper.rb b/ruby/test/logger/helper.rb deleted file mode 100644 index 9eaeb205b..000000000 --- a/ruby/test/logger/helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -ROOT_DIR = File.dirname(__dir__) -$LOAD_PATH.unshift File.join(ROOT_DIR, 'lib') # to use logger in this repo instead of ruby built-in logger -$LOAD_PATH.unshift File.join(ROOT_DIR, 'test', 'lib') # to use custom test-unit in this repo -require 'logger' -require 'test/unit' - -begin - # for standalone test suite on ruby/logger - require 'core_assertions' - - Test::Unit::TestCase.include Test::Unit::CoreAssertions -rescue LoadError -end diff --git a/ruby/test/logger/test_formatter.rb b/ruby/test/logger/test_formatter.rb new file mode 100644 index 000000000..946572299 --- /dev/null +++ b/ruby/test/logger/test_formatter.rb @@ -0,0 +1,35 @@ +# coding: US-ASCII +# frozen_string_literal: false +require 'logger' + +class TestFormatter < Test::Unit::TestCase + def test_call + severity = 'INFO' + time = Time.now + progname = 'ruby' + msg = 'This is a test' + formatter = Logger::Formatter.new + + result = formatter.call(severity, time, progname, msg) + time_matcher = /\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}/ + matcher = /#{severity[0..0]}, \[#{time_matcher} #\d+\] #{severity} -- #{progname}: #{msg}\n/ + + assert_match(matcher, result) + end + + class CustomFormatter < Logger::Formatter + def call(time) + format_datetime(time) + end + end + + def test_format_datetime + time = Time.now + formatter = CustomFormatter.new + + result = formatter.call(time) + matcher = /^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$/ + + assert_match(matcher, result) + end +end diff --git a/ruby/test/logger/test_logdevice.rb b/ruby/test/logger/test_logdevice.rb index 2a01dab17..d360fa210 100644 --- a/ruby/test/logger/test_logdevice.rb +++ b/ruby/test/logger/test_logdevice.rb @@ -1,6 +1,6 @@ # coding: US-ASCII # frozen_string_literal: false -require_relative 'helper' +require 'logger' require 'tempfile' require 'tmpdir' @@ -451,7 +451,7 @@ def test_shifting_size_not_rotate_too_much end ensure logdev0.close - end unless /mswin|mingw/ =~ RUBY_PLATFORM + end unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM def test_shifting_midnight Dir.mktmpdir do |tmpdir| diff --git a/ruby/test/logger/test_logger.rb b/ruby/test/logger/test_logger.rb index 521b5627d..37d0f5862 100644 --- a/ruby/test/logger/test_logger.rb +++ b/ruby/test/logger/test_logger.rb @@ -1,6 +1,6 @@ # coding: US-ASCII # frozen_string_literal: false -require_relative 'helper' +require 'logger' require 'tempfile' class TestLogger < Test::Unit::TestCase @@ -13,7 +13,7 @@ def setup class Log attr_reader :label, :datetime, :pid, :severity, :progname, :msg def initialize(line) - /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line + /\A(\w+), \[([^#]*) #(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6 end end @@ -124,7 +124,7 @@ def test_datetime_format dummy = STDERR logger = Logger.new(dummy) log = log_add(logger, INFO, "foo") - assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime) + assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime) logger.datetime_format = "%d%b%Y@%H:%M:%S" log = log_add(logger, INFO, "foo") assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime) @@ -203,7 +203,7 @@ def test_initialize_with_datetime_format # default logger = Logger.new(STDERR) log = log_add(logger, INFO, "foo") - assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime) + assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime) # config logger = Logger.new(STDERR, datetime_format: "%d%b%Y@%H:%M:%S") log = log_add(logger, INFO, "foo") @@ -216,6 +216,13 @@ def test_reopen assert_equal(STDOUT, logger.instance_variable_get(:@logdev).dev) end + def test_reopen_nil_logdevice + logger = Logger.new(File::NULL) + assert_nothing_raised do + logger.reopen(STDOUT) + end + end + def test_add logger = Logger.new(nil) logger.progname = "my_progname" @@ -378,4 +385,9 @@ def test_overriding_level log = log(logger, :debug) { "msg" } assert_nil log.msg end + + def test_does_not_instantiate_log_device_for_File_NULL + l = Logger.new(File::NULL) + assert_nil(l.instance_variable_get(:@logdev)) + end end diff --git a/ruby/test/logger/test_logperiod.rb b/ruby/test/logger/test_logperiod.rb index 3c5cbbcd9..6e6e5e953 100644 --- a/ruby/test/logger/test_logperiod.rb +++ b/ruby/test/logger/test_logperiod.rb @@ -1,6 +1,6 @@ # coding: US-ASCII # frozen_string_literal: false -require_relative 'helper' +require 'logger' require 'time' class TestLogPeriod < Test::Unit::TestCase diff --git a/ruby/test/logger/test_severity.rb b/ruby/test/logger/test_severity.rb index 1197e8abb..dad63472a 100644 --- a/ruby/test/logger/test_severity.rb +++ b/ruby/test/logger/test_severity.rb @@ -1,6 +1,6 @@ # coding: US-ASCII # frozen_string_literal: false -require_relative 'helper' +require 'logger' class TestLoggerSeverity < Test::Unit::TestCase def test_enum diff --git a/ruby/test/matrix/test_matrix.rb b/ruby/test/matrix/test_matrix.rb deleted file mode 100644 index 7dbb1000d..000000000 --- a/ruby/test/matrix/test_matrix.rb +++ /dev/null @@ -1,795 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'matrix' - -class SubMatrix < Matrix -end - -class TestMatrix < Test::Unit::TestCase - def setup - @m1 = Matrix[[1,2,3], [4,5,6]] - @m2 = Matrix[[1,2,3], [4,5,6]] - @m3 = @m1.clone - @m4 = Matrix[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] - @n1 = Matrix[[2,3,4], [5,6,7]] - @c1 = Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]] - @e1 = Matrix.empty(2,0) - @e2 = Matrix.empty(0,3) - @a3 = Matrix[[4, 1, -3], [0, 3, 7], [11, -4, 2]] - @a5 = Matrix[[2, 0, 9, 3, 9], [8, 7, 0, 1, 9], [7, 5, 6, 6, 5], [0, 7, 8, 3, 0], [7, 8, 2, 3, 1]] - @b3 = Matrix[[-7, 7, -10], [9, -3, -2], [-1, 3, 9]] - end - - def test_matrix - assert_equal(1, @m1[0, 0]) - assert_equal(2, @m1[0, 1]) - assert_equal(3, @m1[0, 2]) - assert_equal(4, @m1[1, 0]) - assert_equal(5, @m1[1, 1]) - assert_equal(6, @m1[1, 2]) - end - - def test_identity - assert_same @m1, @m1 - assert_not_same @m1, @m2 - assert_not_same @m1, @m3 - assert_not_same @m1, @m4 - assert_not_same @m1, @n1 - end - - def test_equality - assert_equal @m1, @m1 - assert_equal @m1, @m2 - assert_equal @m1, @m3 - assert_equal @m1, @m4 - assert_not_equal @m1, @n1 - end - - def test_hash_equality - assert @m1.eql?(@m1) - assert @m1.eql?(@m2) - assert @m1.eql?(@m3) - assert !@m1.eql?(@m4) - assert !@m1.eql?(@n1) - - hash = { @m1 => :value } - assert hash.key?(@m1) - assert hash.key?(@m2) - assert hash.key?(@m3) - assert !hash.key?(@m4) - assert !hash.key?(@n1) - end - - def test_hash - assert_equal @m1.hash, @m1.hash - assert_equal @m1.hash, @m2.hash - assert_equal @m1.hash, @m3.hash - end - - def test_uplus - assert_equal(@m1, +@m1) - end - - def test_negate - assert_equal(Matrix[[-1, -2, -3], [-4, -5, -6]], -@m1) - assert_equal(@m1, -(-@m1)) - end - - def test_rank - [ - [[0]], - [[0], [0]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0], [0, 0]], - [[0, 0, 0]], - [[0, 0, 0], [0, 0, 0]], - [[0, 0, 0], [0, 0, 0], [0, 0, 0]], - [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], - ].each do |rows| - assert_equal 0, Matrix[*rows].rank - end - - [ - [[1], [0]], - [[1, 0], [0, 0]], - [[1, 0], [1, 0]], - [[0, 0], [1, 0]], - [[1, 0], [0, 0], [0, 0]], - [[0, 0], [1, 0], [0, 0]], - [[0, 0], [0, 0], [1, 0]], - [[1, 0], [1, 0], [0, 0]], - [[0, 0], [1, 0], [1, 0]], - [[1, 0], [1, 0], [1, 0]], - [[1, 0, 0]], - [[1, 0, 0], [0, 0, 0]], - [[0, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0]], - [[1, 0, 0], [0, 0, 0], [0, 0, 0]], - [[0, 0, 0], [1, 0, 0], [0, 0, 0]], - [[0, 0, 0], [0, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0], [0, 0, 0]], - [[0, 0, 0], [1, 0, 0], [1, 0, 0]], - [[1, 0, 0], [0, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0], [1, 0, 0]], - [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], - [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], - [[1, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0]], - [[1, 0, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]], - [[1, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0], [1, 0, 0], [0, 0, 0]], - [[1, 0, 0], [0, 0, 0], [1, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0], [0, 0, 0], [1, 0, 0]], - [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 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, 1]], - [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]], - ].each do |rows| - matrix = Matrix[*rows] - assert_equal 1, matrix.rank - assert_equal 1, matrix.transpose.rank - end - - [ - [[1, 0], [0, 1]], - [[1, 0], [0, 1], [0, 0]], - [[1, 0], [0, 1], [0, 1]], - [[1, 0], [0, 1], [1, 1]], - [[1, 0, 0], [0, 1, 0]], - [[1, 0, 0], [0, 0, 1]], - [[1, 0, 0], [0, 1, 0], [0, 0, 0]], - [[1, 0, 0], [0, 0, 1], [0, 0, 0]], - - [[1, 0, 0], [0, 0, 0], [0, 1, 0]], - [[1, 0, 0], [0, 0, 0], [0, 0, 1]], - - [[1, 0], [1, 1]], - [[1, 2], [1, 1]], - [[1, 2], [0, 1], [1, 1]], - ].each do |rows| - m = Matrix[*rows] - assert_equal 2, m.rank - assert_equal 2, m.transpose.rank - end - - [ - [[1, 0, 0], [0, 1, 0], [0, 0, 1]], - [[1, 1, 0], [0, 1, 1], [1, 0, 1]], - [[1, 1, 0], [0, 1, 1], [1, 0, 1]], - [[1, 1, 0], [0, 1, 1], [1, 0, 1], [0, 0, 0]], - [[1, 1, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]], - [[1, 1, 1], [1, 1, 2], [1, 3, 1], [4, 1, 1]], - ].each do |rows| - m = Matrix[*rows] - assert_equal 3, m.rank - assert_equal 3, m.transpose.rank - end - end - - def test_inverse - assert_equal(Matrix.empty(0, 0), Matrix.empty.inverse) - assert_equal(Matrix[[-1, 1], [0, -1]], Matrix[[-1, -1], [0, -1]].inverse) - assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.inverse } - end - - def test_determinant - assert_equal(0, Matrix[[0,0],[0,0]].determinant) - assert_equal(45, Matrix[[7,6], [3,9]].determinant) - assert_equal(-18, Matrix[[2,0,1],[0,-2,2],[1,2,3]].determinant) - assert_equal(-7, Matrix[[0,0,1],[0,7,6],[1,3,9]].determinant) - assert_equal(42, Matrix[[7,0,1,0,12],[8,1,1,9,1],[4,0,0,-7,17],[-1,0,0,-4,8],[10,1,1,8,6]].determinant) - end - - def test_new_matrix - assert_raise(TypeError) { Matrix[Object.new] } - o = Object.new - def o.to_ary; [1,2,3]; end - assert_equal(@m1, Matrix[o, [4,5,6]]) - end - - def test_round - a = Matrix[[1.0111, 2.32320, 3.04343], [4.81, 5.0, 6.997]] - b = Matrix[[1.01, 2.32, 3.04], [4.81, 5.0, 7.0]] - assert_equal(a.round(2), b) - end - - def test_rows - assert_equal(@m1, Matrix.rows([[1, 2, 3], [4, 5, 6]])) - end - - def test_rows_copy - rows1 = [[1], [1]] - rows2 = [[1], [1]] - - m1 = Matrix.rows(rows1, copy = false) - m2 = Matrix.rows(rows2, copy = true) - - rows1.uniq! - rows2.uniq! - - assert_equal([[1]], m1.to_a) - assert_equal([[1], [1]], m2.to_a) - end - - def test_to_matrix - assert @m1.equal? @m1.to_matrix - end - - def test_columns - assert_equal(@m1, Matrix.columns([[1, 4], [2, 5], [3, 6]])) - end - - def test_diagonal - assert_equal(Matrix.empty(0, 0), Matrix.diagonal( )) - assert_equal(Matrix[[3,0,0],[0,2,0],[0,0,1]], Matrix.diagonal(3, 2, 1)) - assert_equal(Matrix[[4,0,0,0],[0,3,0,0],[0,0,2,0],[0,0,0,1]], Matrix.diagonal(4, 3, 2, 1)) - end - - def test_scalar - assert_equal(Matrix.empty(0, 0), Matrix.scalar(0, 1)) - assert_equal(Matrix[[2,0,0],[0,2,0],[0,0,2]], Matrix.scalar(3, 2)) - assert_equal(Matrix[[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,2]], Matrix.scalar(4, 2)) - end - - def test_identity2 - assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.identity(3)) - assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.unit(3)) - assert_equal(Matrix[[1,0,0],[0,1,0],[0,0,1]], Matrix.I(3)) - assert_equal(Matrix[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]], Matrix.identity(4)) - end - - def test_zero - assert_equal(Matrix[[0,0,0],[0,0,0],[0,0,0]], Matrix.zero(3)) - assert_equal(Matrix[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], Matrix.zero(4)) - assert_equal(Matrix[[0]], Matrix.zero(1)) - end - - def test_row_vector - assert_equal(Matrix[[1,2,3,4]], Matrix.row_vector([1,2,3,4])) - end - - def test_column_vector - assert_equal(Matrix[[1],[2],[3],[4]], Matrix.column_vector([1,2,3,4])) - end - - def test_empty - m = Matrix.empty(2, 0) - assert_equal(Matrix[ [], [] ], m) - n = Matrix.empty(0, 3) - assert_equal(Matrix.columns([ [], [], [] ]), n) - assert_equal(Matrix[[0, 0, 0], [0, 0, 0]], m * n) - end - - def test_row - assert_equal(Vector[1, 2, 3], @m1.row(0)) - assert_equal(Vector[4, 5, 6], @m1.row(1)) - a = []; @m1.row(0) {|x| a << x } - assert_equal([1, 2, 3], a) - end - - def test_column - assert_equal(Vector[1, 4], @m1.column(0)) - assert_equal(Vector[2, 5], @m1.column(1)) - assert_equal(Vector[3, 6], @m1.column(2)) - a = []; @m1.column(0) {|x| a << x } - assert_equal([1, 4], a) - end - - def test_collect - m1 = Matrix.zero(2,2) - m2 = Matrix.build(3,4){|row, col| 1} - - assert_equal(Matrix[[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]], m2.collect{|e| e * 5}) - assert_equal(Matrix[[7, 0],[0, 7]], m1.collect(:diagonal){|e| e + 7}) - assert_equal(Matrix[[0, 5],[5, 0]], m1.collect(:off_diagonal){|e| e + 5}) - assert_equal(Matrix[[8, 1, 1, 1], [8, 8, 1, 1], [8, 8, 8, 1]], m2.collect(:lower){|e| e + 7}) - assert_equal(Matrix[[1, 1, 1, 1], [-11, 1, 1, 1], [-11, -11, 1, 1]], m2.collect(:strict_lower){|e| e - 12}) - assert_equal(Matrix[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], m2.collect(:strict_upper){|e| e ** 2}) - assert_equal(Matrix[[-1, -1, -1, -1], [1, -1, -1, -1], [1, 1, -1, -1]], m2.collect(:upper){|e| -e}) - assert_raise(ArgumentError) {m1.collect(:test){|e| e + 7}} - assert_not_equal(m2, m2.collect {|e| e * 2 }) - end - - def test_minor - assert_equal(Matrix[[1, 2], [4, 5]], @m1.minor(0..1, 0..1)) - assert_equal(Matrix[[2], [5]], @m1.minor(0..1, 1..1)) - assert_equal(Matrix[[4, 5]], @m1.minor(1..1, 0..1)) - assert_equal(Matrix[[1, 2], [4, 5]], @m1.minor(0, 2, 0, 2)) - assert_equal(Matrix[[4, 5]], @m1.minor(1, 1, 0, 2)) - assert_equal(Matrix[[2], [5]], @m1.minor(0, 2, 1, 1)) - assert_raise(ArgumentError) { @m1.minor(0) } - end - - def test_first_minor - assert_equal(Matrix.empty(0, 0), Matrix[[1]].first_minor(0, 0)) - assert_equal(Matrix.empty(0, 2), Matrix[[1, 4, 2]].first_minor(0, 1)) - assert_equal(Matrix[[1, 3]], @m1.first_minor(1, 1)) - assert_equal(Matrix[[4, 6]], @m1.first_minor(0, 1)) - assert_equal(Matrix[[1, 2]], @m1.first_minor(1, 2)) - assert_raise(RuntimeError) { Matrix.empty(0, 0).first_minor(0, 0) } - assert_raise(ArgumentError) { @m1.first_minor(4, 0) } - assert_raise(ArgumentError) { @m1.first_minor(0, -1) } - assert_raise(ArgumentError) { @m1.first_minor(-1, 4) } - end - - def test_cofactor - assert_equal(1, Matrix[[1]].cofactor(0, 0)) - assert_equal(9, Matrix[[7,6],[3,9]].cofactor(0, 0)) - assert_equal(0, Matrix[[0,0],[0,0]].cofactor(0, 0)) - assert_equal(3, Matrix[[0,0,1],[0,7,6],[1,3,9]].cofactor(1, 0)) - assert_equal(-21, Matrix[[7,0,1,0,12],[8,1,1,9,1],[4,0,0,-7,17],[-1,0,0,-4,8],[10,1,1,8,6]].cofactor(2, 3)) - assert_raise(RuntimeError) { Matrix.empty(0, 0).cofactor(0, 0) } - assert_raise(ArgumentError) { Matrix[[0,0],[0,0]].cofactor(-1, 4) } - assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { Matrix[[2,0,1],[0,-2,2]].cofactor(0, 0) } - end - - def test_adjugate - assert_equal(Matrix.empty, Matrix.empty.adjugate) - assert_equal(Matrix[[1]], Matrix[[5]].adjugate) - assert_equal(Matrix[[9,-6],[-3,7]], Matrix[[7,6],[3,9]].adjugate) - assert_equal(Matrix[[45,3,-7],[6,-1,0],[-7,0,0]], Matrix[[0,0,1],[0,7,6],[1,3,9]].adjugate) - assert_equal(Matrix.identity(5), (@a5.adjugate * @a5) / @a5.det) - assert_equal(Matrix.I(3), Matrix.I(3).adjugate) - assert_equal((@a3 * @b3).adjugate, @b3.adjugate * @a3.adjugate) - assert_equal(4**(@a3.row_count-1) * @a3.adjugate, (4 * @a3).adjugate) - assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.adjugate } - end - - def test_laplace_expansion - assert_equal(1, Matrix[[1]].laplace_expansion(row: 0)) - assert_equal(45, Matrix[[7,6], [3,9]].laplace_expansion(row: 1)) - assert_equal(0, Matrix[[0,0],[0,0]].laplace_expansion(column: 0)) - assert_equal(-7, Matrix[[0,0,1],[0,7,6],[1,3,9]].laplace_expansion(column: 2)) - - assert_equal(Vector[3, -2], Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0)) - - assert_raise(ExceptionForMatrix::ErrDimensionMismatch) { @m1.laplace_expansion(row: 1) } - assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion() } - assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(foo: 1) } - assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(row: 1, column: 1) } - assert_raise(ArgumentError) { Matrix[[7,6], [3,9]].laplace_expansion(row: 2) } - assert_raise(ArgumentError) { Matrix[[0,0,1],[0,7,6],[1,3,9]].laplace_expansion(column: -1) } - - assert_raise(RuntimeError) { Matrix.empty(0, 0).laplace_expansion(row: 0) } - end - - def test_regular? - assert(Matrix[[1, 0], [0, 1]].regular?) - assert(Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].regular?) - assert(!Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].regular?) - end - - def test_singular? - assert(!Matrix[[1, 0], [0, 1]].singular?) - assert(!Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].singular?) - assert(Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].singular?) - end - - def test_square? - assert(Matrix[[1, 0], [0, 1]].square?) - assert(Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]].square?) - assert(Matrix[[1, 0, 0], [0, 0, 1], [0, 0, 1]].square?) - assert(!Matrix[[1, 0, 0], [0, 1, 0]].square?) - end - - def test_mul - assert_equal(Matrix[[2,4],[6,8]], Matrix[[2,4],[6,8]] * Matrix.I(2)) - assert_equal(Matrix[[4,8],[12,16]], Matrix[[2,4],[6,8]] * 2) - assert_equal(Matrix[[4,8],[12,16]], 2 * Matrix[[2,4],[6,8]]) - assert_equal(Matrix[[14,32],[32,77]], @m1 * @m1.transpose) - assert_equal(Matrix[[17,22,27],[22,29,36],[27,36,45]], @m1.transpose * @m1) - assert_equal(Vector[14,32], @m1 * Vector[1,2,3]) - o = Object.new - def o.coerce(m) - [m, m.transpose] - end - assert_equal(Matrix[[14,32],[32,77]], @m1 * o) - end - - def test_add - assert_equal(Matrix[[6,0],[-4,12]], Matrix.scalar(2,5) + Matrix[[1,0],[-4,7]]) - assert_equal(Matrix[[3,5,7],[9,11,13]], @m1 + @n1) - assert_equal(Matrix[[3,5,7],[9,11,13]], @n1 + @m1) - assert_equal(Matrix[[2],[4],[6]], Matrix[[1],[2],[3]] + Vector[1,2,3]) - assert_raise(Matrix::ErrOperationNotDefined) { @m1 + 1 } - o = Object.new - def o.coerce(m) - [m, m] - end - assert_equal(Matrix[[2,4,6],[8,10,12]], @m1 + o) - end - - def test_sub - assert_equal(Matrix[[4,0],[4,-2]], Matrix.scalar(2,5) - Matrix[[1,0],[-4,7]]) - assert_equal(Matrix[[-1,-1,-1],[-1,-1,-1]], @m1 - @n1) - assert_equal(Matrix[[1,1,1],[1,1,1]], @n1 - @m1) - assert_equal(Matrix[[0],[0],[0]], Matrix[[1],[2],[3]] - Vector[1,2,3]) - assert_raise(Matrix::ErrOperationNotDefined) { @m1 - 1 } - o = Object.new - def o.coerce(m) - [m, m] - end - assert_equal(Matrix[[0,0,0],[0,0,0]], @m1 - o) - end - - def test_div - assert_equal(Matrix[[0,1,1],[2,2,3]], @m1 / 2) - assert_equal(Matrix[[1,1],[1,1]], Matrix[[2,2],[2,2]] / Matrix.scalar(2,2)) - o = Object.new - def o.coerce(m) - [m, Matrix.scalar(2,2)] - end - assert_equal(Matrix[[1,1],[1,1]], Matrix[[2,2],[2,2]] / o) - end - - def test_hadamard_product - assert_equal(Matrix[[1,4], [9,16]], Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,4]])) - assert_equal(Matrix[[2, 6, 12], [20, 30, 42]], @m1.hadamard_product(@n1)) - o = Object.new - def o.to_matrix - Matrix[[1, 2, 3], [-1, 0, 1]] - end - assert_equal(Matrix[[1, 4, 9], [-4, 0, 6]], @m1.hadamard_product(o)) - e = Matrix.empty(3, 0) - assert_equal(e, e.hadamard_product(e)) - e = Matrix.empty(0, 3) - assert_equal(e, e.hadamard_product(e)) - end - - def test_exp - assert_equal(Matrix[[67,96],[48,99]], Matrix[[7,6],[3,9]] ** 2) - assert_equal(Matrix.I(5), Matrix.I(5) ** -1) - assert_raise(Matrix::ErrOperationNotDefined) { Matrix.I(5) ** Object.new } - end - - def test_det - assert_equal(Matrix.instance_method(:determinant), Matrix.instance_method(:det)) - end - - def test_rank2 - assert_equal(2, Matrix[[7,6],[3,9]].rank) - assert_equal(0, Matrix[[0,0],[0,0]].rank) - assert_equal(3, Matrix[[0,0,1],[0,7,6],[1,3,9]].rank) - assert_equal(1, Matrix[[0,1],[0,1],[0,1]].rank) - assert_equal(2, @m1.rank) - end - - def test_trace - assert_equal(1+5+9, Matrix[[1,2,3],[4,5,6],[7,8,9]].trace) - end - - def test_transpose - assert_equal(Matrix[[1,4],[2,5],[3,6]], @m1.transpose) - end - - def test_conjugate - assert_equal(Matrix[[Complex(1,-2), Complex(0,-1), 0], [1, 2, 3]], @c1.conjugate) - end - - def test_eigensystem - m = Matrix[[1, 2], [3, 4]] - v, d, v_inv = m.eigensystem - assert(d.diagonal?) - assert_equal(v.inv, v_inv) - assert_equal((v * d * v_inv).round(5), m) - end - - def test_imaginary - assert_equal(Matrix[[2, 1, 0], [0, 0, 0]], @c1.imaginary) - end - - def test_lup - m = Matrix[[1, 2], [3, 4]] - l, u, p = m.lup - assert(l.lower_triangular?) - assert(u.upper_triangular?) - assert(p.permutation?) - assert(l * u == p * m) - assert_equal(m.lup.solve([2, 5]), Vector[1, Rational(1,2)]) - end - - def test_real - assert_equal(Matrix[[1, 0, 0], [1, 2, 3]], @c1.real) - end - - def test_rect - assert_equal([Matrix[[1, 0, 0], [1, 2, 3]], Matrix[[2, 1, 0], [0, 0, 0]]], @c1.rect) - end - - def test_row_vectors - assert_equal([Vector[1,2,3], Vector[4,5,6]], @m1.row_vectors) - end - - def test_column_vectors - assert_equal([Vector[1,4], Vector[2,5], Vector[3,6]], @m1.column_vectors) - end - - def test_to_s - assert_equal("Matrix[[1, 2, 3], [4, 5, 6]]", @m1.to_s) - assert_equal("Matrix.empty(0, 0)", Matrix[].to_s) - assert_equal("Matrix.empty(1, 0)", Matrix[[]].to_s) - end - - def test_inspect - assert_equal("Matrix[[1, 2, 3], [4, 5, 6]]", @m1.inspect) - assert_equal("Matrix.empty(0, 0)", Matrix[].inspect) - assert_equal("Matrix.empty(1, 0)", Matrix[[]].inspect) - end - - def test_scalar_add - s1 = @m1.coerce(1).first - assert_equal(Matrix[[1]], (s1 + 0) * Matrix[[1]]) - assert_raise(Matrix::ErrOperationNotDefined) { s1 + Vector[0] } - assert_raise(Matrix::ErrOperationNotDefined) { s1 + Matrix[[0]] } - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(2, s1 + o) - end - - def test_scalar_sub - s1 = @m1.coerce(1).first - assert_equal(Matrix[[1]], (s1 - 0) * Matrix[[1]]) - assert_raise(Matrix::ErrOperationNotDefined) { s1 - Vector[0] } - assert_raise(Matrix::ErrOperationNotDefined) { s1 - Matrix[[0]] } - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(0, s1 - o) - end - - def test_scalar_mul - s1 = @m1.coerce(1).first - assert_equal(Matrix[[1]], (s1 * 1) * Matrix[[1]]) - assert_equal(Vector[2], s1 * Vector[2]) - assert_equal(Matrix[[2]], s1 * Matrix[[2]]) - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(1, s1 * o) - end - - def test_scalar_div - s1 = @m1.coerce(1).first - assert_equal(Matrix[[1]], (s1 / 1) * Matrix[[1]]) - assert_raise(Matrix::ErrOperationNotDefined) { s1 / Vector[0] } - assert_equal(Matrix[[Rational(1,2)]], s1 / Matrix[[2]]) - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(1, s1 / o) - end - - def test_scalar_pow - s1 = @m1.coerce(1).first - assert_equal(Matrix[[1]], (s1 ** 1) * Matrix[[1]]) - assert_raise(Matrix::ErrOperationNotDefined) { s1 ** Vector[0] } - assert_raise(Matrix::ErrOperationNotImplemented) { s1 ** Matrix[[1]] } - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(1, s1 ** o) - end - - def test_abs - s1 = @a3.abs - assert_equal(s1, Matrix[[4, 1, 3], [0, 3, 7], [11, 4, 2]]) - end - - def test_hstack - assert_equal Matrix[[1,2,3,2,3,4,1,2,3], [4,5,6,5,6,7,4,5,6]], - @m1.hstack(@n1, @m1) - # Error checking: - assert_raise(TypeError) { @m1.hstack(42) } - assert_raise(TypeError) { Matrix.hstack(42, @m1) } - assert_raise(Matrix::ErrDimensionMismatch) { @m1.hstack(Matrix.identity(3)) } - assert_raise(Matrix::ErrDimensionMismatch) { @e1.hstack(@e2) } - # Corner cases: - assert_equal @m1, @m1.hstack - assert_equal @e1, @e1.hstack(@e1) - assert_equal Matrix.empty(0,6), @e2.hstack(@e2) - assert_equal SubMatrix, SubMatrix.hstack(@e1).class - # From Vectors: - assert_equal Matrix[[1, 3],[2, 4]], Matrix.hstack(Vector[1,2], Vector[3, 4]) - end - - def test_vstack - assert_equal Matrix[[1,2,3], [4,5,6], [2,3,4], [5,6,7], [1,2,3], [4,5,6]], - @m1.vstack(@n1, @m1) - # Error checking: - assert_raise(TypeError) { @m1.vstack(42) } - assert_raise(TypeError) { Matrix.vstack(42, @m1) } - assert_raise(Matrix::ErrDimensionMismatch) { @m1.vstack(Matrix.identity(2)) } - assert_raise(Matrix::ErrDimensionMismatch) { @e1.vstack(@e2) } - # Corner cases: - assert_equal @m1, @m1.vstack - assert_equal Matrix.empty(4,0), @e1.vstack(@e1) - assert_equal @e2, @e2.vstack(@e2) - assert_equal SubMatrix, SubMatrix.vstack(@e1).class - # From Vectors: - assert_equal Matrix[[1],[2],[3]], Matrix.vstack(Vector[1,2], Vector[3]) - end - - def test_combine - x = Matrix[[6, 6], [4, 4]] - y = Matrix[[1, 2], [3, 4]] - assert_equal Matrix[[5, 4], [1, 0]], Matrix.combine(x, y) {|a, b| a - b} - assert_equal Matrix[[5, 4], [1, 0]], x.combine(y) {|a, b| a - b} - # Without block - assert_equal Matrix[[5, 4], [1, 0]], Matrix.combine(x, y).each {|a, b| a - b} - # With vectors - assert_equal Matrix[[111], [222]], Matrix.combine(Matrix[[1], [2]], Vector[10,20], Vector[100,200], &:sum) - # Basic checks - assert_raise(Matrix::ErrDimensionMismatch) { @m1.combine(x) { raise } } - # Edge cases - assert_equal Matrix.empty, Matrix.combine{ raise } - assert_equal Matrix.empty(3,0), Matrix.combine(Matrix.empty(3,0), Matrix.empty(3,0)) { raise } - assert_equal Matrix.empty(0,3), Matrix.combine(Matrix.empty(0,3), Matrix.empty(0,3)) { raise } - end - - def test_set_element - src = Matrix[ - [1, 2, 3, 4], - [5, 6, 7, 8], - [9, 10, 11, 12], - ] - rows = { - range: [1..2, 1...3, 1..-1, -2..2, 1.., 1..., -2.., -2...], - int: [2, -1], - invalid: [-4, 4, -4..2, 2..-4, 0...0, 2..0, -4..], - } - columns = { - range: [2..3, 2...4, 2..-1, -2..3, 2.., 2..., -2..., -2..], - int: [3, -1], - invalid: [-5, 5, -5..2, 2..-5, 0...0, -5..], - } - values = { - element: 42, - matrix: Matrix[[20, 21], [22, 23]], - vector: Vector[30, 31], - row: Matrix[[60, 61]], - column: Matrix[[50], [51]], - mismatched_matrix: Matrix.identity(3), - mismatched_vector: Vector[0, 1, 2, 3], - } - solutions = { - [:int, :int] => { - element: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 42]], - }, - [:range , :int] => { - element: Matrix[[1, 2, 3, 4], [5, 6, 7, 42], [9, 10, 11, 42]], - column: Matrix[[1, 2, 3, 4], [5, 6, 7, 50], [9, 10, 11, 51]], - vector: Matrix[[1, 2, 3, 4], [5, 6, 7, 30], [9, 10, 11, 31]], - }, - [:int, :range] => { - element: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 42, 42]], - row: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 60, 61]], - vector: Matrix[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 30, 31]], - }, - [:range , :range] => { - element: Matrix[[1, 2, 3, 4], [5, 6, 42, 42], [9, 10, 42, 42]], - matrix: Matrix[[1, 2, 3, 4], [5, 6, 20, 21], [9, 10, 22, 23]], - }, - } - solutions.default = Hash.new(IndexError) - - rows.each do |row_style, row_arguments| - row_arguments.each do |row_argument| - columns.each do |column_style, column_arguments| - column_arguments.each do |column_argument| - values.each do |value_type, value| - expected = solutions[[row_style, column_style]][value_type] || Matrix::ErrDimensionMismatch - - result = src.clone - begin - result[row_argument, column_argument] = value - assert_equal expected, result, - "m[#{row_argument.inspect}][#{column_argument.inspect}] = #{value.inspect} failed" - rescue Exception => e - raise if e.class != expected - end - end - end - end - end - end - end - - def test_map! - m1 = Matrix.zero(2,2) - m2 = Matrix.build(3,4){|row, col| 1} - m3 = Matrix.zero(3,5).freeze - m4 = Matrix.empty.freeze - - assert_equal Matrix[[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]], m2.map!{|e| e * 5} - assert_equal Matrix[[7, 0],[0, 7]], m1.map!(:diagonal){|e| e + 7} - assert_equal Matrix[[7, 5],[5, 7]], m1.map!(:off_diagonal){|e| e + 5} - assert_equal Matrix[[12, 5, 5, 5], [12, 12, 5, 5], [12, 12, 12, 5]], m2.map!(:lower){|e| e + 7} - assert_equal Matrix[[12, 5, 5, 5], [0, 12, 5, 5], [0, 0, 12, 5]], m2.map!(:strict_lower){|e| e - 12} - assert_equal Matrix[[12, 25, 25, 25], [0, 12, 25, 25], [0, 0, 12, 25]], m2.map!(:strict_upper){|e| e ** 2} - assert_equal Matrix[[-12, -25, -25, -25], [0, -12, -25, -25], [0, 0, -12, -25]], m2.map!(:upper){|e| -e} - assert_equal m1, m1.map!{|e| e ** 2 } - assert_equal m2, m2.map!(:lower){ |e| e - 3 } - assert_raise(ArgumentError) {m1.map!(:test){|e| e + 7}} - assert_raise(FrozenError) { m3.map!{|e| e * 2} } - assert_raise(FrozenError) { m4.map!{} } - end - - def test_freeze - m = Matrix[[1, 2, 3],[4, 5, 6]] - f = m.freeze - assert_equal true, f.frozen? - assert m.equal?(f) - assert m.equal?(f.freeze) - assert_raise(FrozenError){ m[0, 1] = 56 } - assert_equal m.dup, m - end - - def test_clone - a = Matrix[[4]] - def a.foo - 42 - end - - m = a.clone - m[0, 0] = 2 - assert_equal a, m * 2 - assert_equal 42, m.foo - - a.freeze - m = a.clone - assert m.frozen? - assert_equal 42, m.foo - end - - def test_dup - a = Matrix[[4]] - def a.foo - 42 - end - a.freeze - - m = a.dup - m[0, 0] = 2 - assert_equal a, m * 2 - assert !m.respond_to?(:foo) - end - - def test_eigenvalues_and_eigenvectors_symmetric - m = Matrix[ - [8, 1], - [1, 8] - ] - values = m.eigensystem.eigenvalues - assert_in_epsilon(7.0, values[0]) - assert_in_epsilon(9.0, values[1]) - vectors = m.eigensystem.eigenvectors - assert_in_epsilon(-vectors[0][0], vectors[0][1]) - assert_in_epsilon(vectors[1][0], vectors[1][1]) - end - - def test_eigenvalues_and_eigenvectors_nonsymmetric - m = Matrix[ - [8, 1], - [4, 5] - ] - values = m.eigensystem.eigenvalues - assert_in_epsilon(9.0, values[0]) - assert_in_epsilon(4.0, values[1]) - vectors = m.eigensystem.eigenvectors - assert_in_epsilon(vectors[0][0], vectors[0][1]) - assert_in_epsilon(-4 * vectors[1][0], vectors[1][1]) - end -end diff --git a/ruby/test/matrix/test_vector.rb b/ruby/test/matrix/test_vector.rb deleted file mode 100644 index 8b771efee..000000000 --- a/ruby/test/matrix/test_vector.rb +++ /dev/null @@ -1,335 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'matrix' - -class TestVector < Test::Unit::TestCase - def setup - @v1 = Vector[1,2,3] - @v2 = Vector[1,2,3] - @v3 = @v1.clone - @v4 = Vector[1.0, 2.0, 3.0] - @w1 = Vector[2,3,4] - end - - def test_zero - assert_equal Vector[0, 0, 0, 0], Vector.zero(4) - assert_equal Vector[], Vector.zero(0) - assert_raise(ArgumentError) { Vector.zero(-1) } - assert Vector[0, 0, 0, 0].zero? - end - - def test_basis - assert_equal(Vector[1, 0, 0], Vector.basis(size: 3, index: 0)) - assert_raise(ArgumentError) { Vector.basis(size: -1, index: 2) } - assert_raise(ArgumentError) { Vector.basis(size: 4, index: -1) } - assert_raise(ArgumentError) { Vector.basis(size: 3, index: 3) } - assert_raise(ArgumentError) { Vector.basis(size: 3) } - assert_raise(ArgumentError) { Vector.basis(index: 3) } - end - - def test_get_element - assert_equal(@v1[0..], [1, 2, 3]) - assert_equal(@v1[0..1], [1, 2]) - assert_equal(@v1[2], 3) - assert_equal(@v1[4], nil) - end - - def test_set_element - - assert_block do - v = Vector[5, 6, 7, 8, 9] - v[1..2] = Vector[1, 2] - v == Vector[5, 1, 2, 8, 9] - end - - assert_block do - v = Vector[6, 7, 8] - v[1..2] = Matrix[[1, 3]] - v == Vector[6, 1, 3] - end - - assert_block do - v = Vector[1, 2, 3, 4, 5, 6] - v[0..2] = 8 - v == Vector[8, 8, 8, 4, 5, 6] - end - - assert_block do - v = Vector[1, 3, 4, 5] - v[2] = 5 - v == Vector[1, 3, 5, 5] - end - - assert_block do - v = Vector[2, 3, 5] - v[-2] = 13 - v == Vector[2, 13, 5] - end - - assert_block do - v = Vector[4, 8, 9, 11, 30] - v[1..-2] = Vector[1, 2, 3] - v == Vector[4, 1, 2, 3, 30] - end - - assert_raise(IndexError) {Vector[1, 3, 4, 5][5..6] = 17} - assert_raise(IndexError) {Vector[1, 3, 4, 5][6] = 17} - assert_raise(Matrix::ErrDimensionMismatch) {Vector[1, 3, 4, 5][0..2] = Matrix[[1], [2], [3]]} - assert_raise(ArgumentError) {Vector[1, 2, 3, 4, 5, 6][0..2] = Vector[1, 2, 3, 4, 5, 6]} - assert_raise(FrozenError) { Vector[7, 8, 9].freeze[0..1] = 5} - end - - def test_map! - v1 = Vector[1, 2, 3] - v2 = Vector[1, 3, 5].freeze - v3 = Vector[].freeze - assert_equal Vector[1, 4, 9], v1.map!{|e| e ** 2} - assert_equal v1, v1.map!{|e| e - 8} - assert_raise(FrozenError) { v2.map!{|e| e + 2 }} - assert_raise(FrozenError){ v3.map!{} } - end - - def test_freeze - v = Vector[1,2,3] - f = v.freeze - assert_equal true, f.frozen? - assert v.equal?(f) - assert v.equal?(f.freeze) - assert_raise(FrozenError){ v[1] = 56 } - assert_equal v.dup, v - end - - def test_clone - a = Vector[4] - def a.foo - 42 - end - - v = a.clone - v[0] = 2 - assert_equal a, v * 2 - assert_equal 42, v.foo - - a.freeze - v = a.clone - assert v.frozen? - assert_equal 42, v.foo - end - - def test_dup - a = Vector[4] - def a.foo - 42 - end - a.freeze - - v = a.dup - v[0] = 2 - assert_equal a, v * 2 - assert !v.respond_to?(:foo) - end - - def test_identity - assert_same @v1, @v1 - assert_not_same @v1, @v2 - assert_not_same @v1, @v3 - assert_not_same @v1, @v4 - assert_not_same @v1, @w1 - end - - def test_equality - assert_equal @v1, @v1 - assert_equal @v1, @v2 - assert_equal @v1, @v3 - assert_equal @v1, @v4 - assert_not_equal @v1, @w1 - end - - def test_hash_equality - assert @v1.eql?(@v1) - assert @v1.eql?(@v2) - assert @v1.eql?(@v3) - assert !@v1.eql?(@v4) - assert !@v1.eql?(@w1) - - hash = { @v1 => :value } - assert hash.key?(@v1) - assert hash.key?(@v2) - assert hash.key?(@v3) - assert !hash.key?(@v4) - assert !hash.key?(@w1) - end - - def test_hash - assert_equal @v1.hash, @v1.hash - assert_equal @v1.hash, @v2.hash - assert_equal @v1.hash, @v3.hash - end - - def test_aref - assert_equal(1, @v1[0]) - assert_equal(2, @v1[1]) - assert_equal(3, @v1[2]) - assert_equal(3, @v1[-1]) - assert_equal(nil, @v1[3]) - end - - def test_size - assert_equal(3, @v1.size) - end - - def test_each2 - a = [] - @v1.each2(@v4) {|x, y| a << [x, y] } - assert_equal([[1,1.0],[2,2.0],[3,3.0]], a) - end - - def test_collect - a = @v1.collect {|x| x + 1 } - assert_equal(Vector[2,3,4], a) - end - - def test_collect2 - a = @v1.collect2(@v4) {|x, y| x + y } - assert_equal([2.0,4.0,6.0], a) - end - - def test_map2 - a = @v1.map2(@v4) {|x, y| x + y } - assert_equal(Vector[2.0,4.0,6.0], a) - end - - def test_independent? - assert(Vector.independent?(@v1, @w1)) - assert( - Vector.independent?( - Vector.basis(size: 3, index: 0), - Vector.basis(size: 3, index: 1), - Vector.basis(size: 3, index: 2), - ) - ) - - refute(Vector.independent?(@v1, Vector[2,4,6])) - refute(Vector.independent?(Vector[2,4], Vector[1,3], Vector[5,6])) - - assert_raise(TypeError) { Vector.independent?(@v1, 3) } - assert_raise(Vector::ErrDimensionMismatch) { Vector.independent?(@v1, Vector[2,4]) } - - assert(@v1.independent?(Vector[1,2,4], Vector[1,3,4])) - end - - def test_mul - assert_equal(Vector[2,4,6], @v1 * 2) - assert_equal(Matrix[[1, 4, 9], [2, 8, 18], [3, 12, 27]], @v1 * Matrix[[1,4,9]]) - assert_raise(Matrix::ErrOperationNotDefined) { @v1 * Vector[1,4,9] } - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(1, Vector[1, 2, 3] * o) - end - - def test_add - assert_equal(Vector[2,4,6], @v1 + @v1) - assert_equal(Matrix[[2],[6],[12]], @v1 + Matrix[[1],[4],[9]]) - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(2, Vector[1, 2, 3] + o) - end - - def test_sub - assert_equal(Vector[0,0,0], @v1 - @v1) - assert_equal(Matrix[[0],[-2],[-6]], @v1 - Matrix[[1],[4],[9]]) - o = Object.new - def o.coerce(x) - [1, 1] - end - assert_equal(0, Vector[1, 2, 3] - o) - end - - def test_uplus - assert_equal(@v1, +@v1) - end - - def test_negate - assert_equal(Vector[-1, -2, -3], -@v1) - assert_equal(@v1, -(-@v1)) - end - - def test_inner_product - assert_equal(1+4+9, @v1.inner_product(@v1)) - assert_equal(1+4+9, @v1.dot(@v1)) - end - - def test_r - assert_equal(5, Vector[3, 4].r) - end - - def test_round - assert_equal(Vector[1.234, 2.345, 3.40].round(2), Vector[1.23, 2.35, 3.4]) - end - - def test_covector - assert_equal(Matrix[[1,2,3]], @v1.covector) - end - - def test_to_s - assert_equal("Vector[1, 2, 3]", @v1.to_s) - end - - def test_to_matrix - assert_equal Matrix[[1], [2], [3]], @v1.to_matrix - end - - def test_inspect - assert_equal("Vector[1, 2, 3]", @v1.inspect) - end - - def test_magnitude - assert_in_epsilon(3.7416573867739413, @v1.norm) - assert_in_epsilon(3.7416573867739413, @v4.norm) - end - - def test_complex_magnitude - bug6966 = '[ruby-dev:46100]' - v = Vector[Complex(0,1), 0] - assert_equal(1.0, v.norm, bug6966) - end - - def test_rational_magnitude - v = Vector[Rational(1,2), 0] - assert_equal(0.5, v.norm) - end - - def test_cross_product - v = Vector[1, 0, 0].cross_product Vector[0, 1, 0] - assert_equal(Vector[0, 0, 1], v) - v2 = Vector[1, 2].cross_product - assert_equal(Vector[-2, 1], v2) - v3 = Vector[3, 5, 2, 1].cross(Vector[4, 3, 1, 8], Vector[2, 9, 4, 3]) - assert_equal(Vector[16, -65, 139, -1], v3) - assert_equal Vector[0, 0, 0, 1], - Vector[1, 0, 0, 0].cross(Vector[0, 1, 0, 0], Vector[0, 0, 1, 0]) - assert_equal Vector[0, 0, 0, 0, 1], - Vector[1, 0, 0, 0, 0].cross(Vector[0, 1, 0, 0, 0], Vector[0, 0, 1, 0, 0], Vector[0, 0, 0, 1, 0]) - assert_raise(Vector::ErrDimensionMismatch) { Vector[1, 2, 3].cross_product(Vector[1, 4]) } - assert_raise(TypeError) { Vector[1, 2, 3].cross_product(42) } - assert_raise(ArgumentError) { Vector[1, 2].cross_product(Vector[2, -1]) } - assert_raise(Vector::ErrOperationNotDefined) { Vector[1].cross_product } - end - - def test_angle_with - assert_in_epsilon(Math::PI, Vector[1, 0].angle_with(Vector[-1, 0])) - assert_in_epsilon(Math::PI/2, Vector[1, 0].angle_with(Vector[0, -1])) - assert_in_epsilon(Math::PI/4, Vector[2, 2].angle_with(Vector[0, 1])) - assert_in_delta(0.0, Vector[1, 1].angle_with(Vector[1, 1]), 0.00001) - assert_equal(Vector[6, 6].angle_with(Vector[7, 7]), 0.0) - assert_equal(Vector[6, 6].angle_with(Vector[-7, -7]), Math::PI) - - assert_raise(Vector::ZeroVectorError) { Vector[1, 1].angle_with(Vector[0, 0]) } - assert_raise(Vector::ZeroVectorError) { Vector[0, 0].angle_with(Vector[1, 1]) } - assert_raise(Matrix::ErrDimensionMismatch) { Vector[1, 2, 3].angle_with(Vector[0, 1]) } - end -end diff --git a/ruby/test/misc/test_ruby_mode.rb b/ruby/test/misc/test_ruby_mode.rb deleted file mode 100644 index bc5101911..000000000 --- a/ruby/test/misc/test_ruby_mode.rb +++ /dev/null @@ -1,183 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tempfile' - -class TestRubyMode < Test::Unit::TestCase - MISCDIR = File.expand_path("../../../misc", __FILE__) - e = ENV["EMACS"] || "emacs" - emacs = %W"#{e} -q --no-site-file --batch --load #{MISCDIR}/ruby-mode.el" - begin - raise if IO.popen([e, "--version", :err=>[:child, :out]]) {|f| f.read}[/[0-9]+/].to_i < 23 - IO.popen([*emacs, :err=>[:child, :out]]) {|f| f.read} - rescue - EMACS = nil - else - EMACS = (emacs if $? and $?.success?) - end -end - -class TestRubyMode - EVAL_OPT = "--eval" - EXPR_SAVE = "(save-buffer 0)" - finish_mark = "ok-#{$$}" - FINISH_MARK = /^#{finish_mark}$/ - EXPR_FINISH = "(print \'#{finish_mark})" - EXPR_RUBYMODE = "(ruby-mode)" - - def run_emacs(src, *exprs) - tmp = Tempfile.new(%w"ruby-mode.test. .rb") - tmp.puts(src) - tmp.close - exprs = exprs.map {|expr| [EVAL_OPT, expr]}.flatten - exprs.unshift(EVAL_OPT, EXPR_RUBYMODE) - exprs.push(EVAL_OPT, EXPR_SAVE) - exprs.push(EVAL_OPT, EXPR_FINISH) - output = IO.popen([*EMACS, tmp.path, *exprs, err:[:child, :out]], "r") {|e| e.read} - tmp.open - result = tmp.read - return result, output - ensure - tmp.close! - end - - class TestIndent < self - EXPR_INDENT = "(indent-region (point-min) (point-max))" - - def assert_indent(expected, source, *message) - if space = expected[/\A\n?(\s*\|)/, 1] - space = /^#{Regexp.quote(space)}/m - expected.gsub!(space, '') - source.gsub!(space, '') - end - result, output = run_emacs(source, EXPR_INDENT) - assert_match(FINISH_MARK, output) - assert_equal(expected, result, message(*message) {diff expected, result}) - end - - def test_simple - assert_indent(' - |if foo - | bar - |end - |zot - |', ' - |if foo - |bar - | end - | zot - |') - end - - def test_keyword_label - assert_indent(' - |bar(class: XXX) do - | foo - |end - |bar - |', ' - |bar(class: XXX) do - | foo - | end - | bar - |') - end - - def test_method_with_question_mark - assert_indent(' - |if x.is_a?(XXX) - | foo - |end - |', ' - |if x.is_a?(XXX) - | foo - | end - |') - end - - def test_expr_in_regexp - assert_indent(' - |if /#{foo}/ =~ s - | x = 1 - |end - |', ' - |if /#{foo}/ =~ s - | x = 1 - | end - |') - end - - def test_singleton_class - skip("pending") - assert_indent(' - |class< port, - :ssl => true) - rescue SystemCallError - skip $! - end - end - end - end - - def test_tls_with_ca_file - assert_nothing_raised do - tls_test do |port| - begin - Net::FTP.new(SERVER_NAME, - :port => port, - :ssl => { :ca_file => CA_FILE }) - rescue SystemCallError - skip $! - end - end - end - end - - def test_tls_verify_none - assert_nothing_raised do - tls_test do |port| - Net::FTP.new(SERVER_ADDR, - :port => port, - :ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE }) - end - end - end - - def test_tls_post_connection_check - assert_raise(OpenSSL::SSL::SSLError) do - tls_test do |port| - # SERVER_ADDR is different from the hostname in the certificate, - # so the following code should raise a SSLError. - Net::FTP.new(SERVER_ADDR, - :port => port, - :ssl => { :ca_file => CA_FILE }) - end - end - end - - def test_active_private_data_connection - server = TCPServer.new(SERVER_ADDR, 0) - port = server.addr[1] - commands = [] - session_reused_for_data_connection = nil - binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3 - @thread = Thread.start do - sock = server.accept - begin - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - begin - sock.accept - commands.push(sock.gets) - sock.print("200 PSBZ success.\r\n") - commands.push(sock.gets) - sock.print("200 PROT success.\r\n") - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - line = sock.gets - commands.push(line) - host, port = process_port_or_eprt(sock, line) - commands.push(sock.gets) - sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n") - conn = TCPSocket.new(host, port) - conn = OpenSSL::SSL::SSLSocket.new(conn, ctx) - conn.sync_close = true - conn.accept - session_reused_for_data_connection = conn.session_reused? - binary_data.scan(/.{1,1024}/nm) do |s| - conn.print(s) - end - conn.close - sock.print("226 Transfer complete.\r\n") - rescue OpenSSL::SSL::SSLError - end - ensure - sock.close - server.close - end - end - ftp = Net::FTP.new(SERVER_NAME, - port: port, - ssl: { ca_file: CA_FILE }, - passive: false) - begin - assert_equal("AUTH TLS\r\n", commands.shift) - assert_equal("PBSZ 0\r\n", commands.shift) - assert_equal("PROT P\r\n", commands.shift) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - buf = ftp.getbinaryfile("foo", nil) - assert_equal(binary_data, buf) - assert_equal(Encoding::ASCII_8BIT, buf.encoding) - assert_match(/\A(PORT|EPRT) /, commands.shift) - assert_equal("RETR foo\r\n", commands.shift) - assert_equal(nil, commands.shift) - # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. - # See https://github.com/openssl/openssl/pull/5967 for details. - if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h/ - assert_equal(true, session_reused_for_data_connection) - end - ensure - ftp.close - end - end - - def test_passive_private_data_connection - server = TCPServer.new(SERVER_ADDR, 0) - port = server.addr[1] - commands = [] - session_reused_for_data_connection = nil - binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3 - @thread = Thread.start do - sock = server.accept - begin - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - begin - sock.accept - commands.push(sock.gets) - sock.print("200 PSBZ success.\r\n") - commands.push(sock.gets) - sock.print("200 PROT success.\r\n") - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - commands.push(sock.gets) - data_server = create_data_connection_server(sock) - commands.push(sock.gets) - sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n") - conn = data_server.accept - conn = OpenSSL::SSL::SSLSocket.new(conn, ctx) - conn.sync_close = true - conn.accept - session_reused_for_data_connection = conn.session_reused? - binary_data.scan(/.{1,1024}/nm) do |s| - conn.print(s) - end - conn.close - data_server.close - sock.print("226 Transfer complete.\r\n") - rescue OpenSSL::SSL::SSLError - end - ensure - sock.close - server.close - end - end - ftp = Net::FTP.new(SERVER_NAME, - port: port, - ssl: { ca_file: CA_FILE }, - passive: true) - begin - assert_equal("AUTH TLS\r\n", commands.shift) - assert_equal("PBSZ 0\r\n", commands.shift) - assert_equal("PROT P\r\n", commands.shift) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - buf = ftp.getbinaryfile("foo", nil) - assert_equal(binary_data, buf) - assert_equal(Encoding::ASCII_8BIT, buf.encoding) - assert_match(/\A(PASV|EPSV)\r\n/, commands.shift) - assert_equal("RETR foo\r\n", commands.shift) - assert_equal(nil, commands.shift) - # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. - if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h/ - assert_equal(true, session_reused_for_data_connection) - end - ensure - ftp.close - end - end - - def test_active_clear_data_connection - server = TCPServer.new(SERVER_ADDR, 0) - port = server.addr[1] - commands = [] - binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3 - @thread = Thread.start do - sock = server.accept - begin - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - begin - sock.accept - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - line = sock.gets - commands.push(line) - host, port = process_port_or_eprt(sock, line) - commands.push(sock.gets) - sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n") - conn = TCPSocket.new(host, port) - binary_data.scan(/.{1,1024}/nm) do |s| - conn.print(s) - end - conn.close - sock.print("226 Transfer complete.\r\n") - rescue OpenSSL::SSL::SSLError - end - ensure - sock.close - server.close - end - end - ftp = Net::FTP.new(SERVER_NAME, - port: port, - ssl: { ca_file: CA_FILE }, - private_data_connection: false, - passive: false) - begin - assert_equal("AUTH TLS\r\n", commands.shift) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - buf = ftp.getbinaryfile("foo", nil) - assert_equal(binary_data, buf) - assert_equal(Encoding::ASCII_8BIT, buf.encoding) - assert_match(/\A(PORT|EPRT) /, commands.shift) - assert_equal("RETR foo\r\n", commands.shift) - assert_equal(nil, commands.shift) - ensure - ftp.close - end - end - - def test_passive_clear_data_connection - server = TCPServer.new(SERVER_ADDR, 0) - port = server.addr[1] - commands = [] - binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3 - @thread = Thread.start do - sock = server.accept - begin - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - begin - sock.accept - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - commands.push(sock.gets) - data_server = create_data_connection_server(sock) - commands.push(sock.gets) - sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n") - conn = data_server.accept - binary_data.scan(/.{1,1024}/nm) do |s| - conn.print(s) - end - conn.close - data_server.close - sock.print("226 Transfer complete.\r\n") - rescue OpenSSL::SSL::SSLError - end - ensure - sock.close - server.close - end - end - ftp = Net::FTP.new(SERVER_NAME, - port: port, - ssl: { ca_file: CA_FILE }, - private_data_connection: false, - passive: true) - begin - assert_equal("AUTH TLS\r\n", commands.shift) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - buf = ftp.getbinaryfile("foo", nil) - assert_equal(binary_data, buf) - assert_equal(Encoding::ASCII_8BIT, buf.encoding) - assert_match(/\A(PASV|EPSV)\r\n/, commands.shift) - assert_equal("RETR foo\r\n", commands.shift) - assert_equal(nil, commands.shift) - ensure - ftp.close - end - end - - def test_tls_connect_timeout - server = TCPServer.new(SERVER_ADDR, 0) - port = server.addr[1] - commands = [] - sock = nil - @thread = Thread.start do - sock = server.accept - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - end - begin - assert_raise(Net::OpenTimeout) do - Net::FTP.new(SERVER_NAME, - port: port, - ssl: { ca_file: CA_FILE }, - ssl_handshake_timeout: 0.1) - end - @thread.join - ensure - sock.close if sock - server.close - end - end - end - - def test_abort_tls - return unless defined?(OpenSSL) - - commands = [] - server = create_ftp_server { |sock| - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - sock.accept - commands.push(sock.gets) - sock.print("200 PSBZ success.\r\n") - commands.push(sock.gets) - sock.print("200 PROT success.\r\n") - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - commands.push(sock.gets) - sock.print("225 No transfer to ABOR.\r\n") - } - begin - begin - ftp = Net::FTP.new(SERVER_NAME, - port: server.port, - ssl: { ca_file: CA_FILE }) - assert_equal("AUTH TLS\r\n", commands.shift) - assert_equal("PBSZ 0\r\n", commands.shift) - assert_equal("PROT P\r\n", commands.shift) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - ftp.abort - assert_equal("ABOR\r\n", commands.shift) - assert_equal(nil, commands.shift) - rescue RuntimeError, LoadError - # skip (require openssl) - ensure - ftp.close if ftp - end - ensure - server.close - end - end - - def test_getbinaryfile_command_injection - skip "| is not allowed in filename on Windows" if windows? - [false, true].each do |resume| - commands = [] - binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3 - server = create_ftp_server { |sock| - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("331 Please specify the password.\r\n") - commands.push(sock.gets) - sock.print("230 Login successful.\r\n") - commands.push(sock.gets) - sock.print("200 Switching to Binary mode.\r\n") - line = sock.gets - commands.push(line) - host, port = process_port_or_eprt(sock, line) - commands.push(sock.gets) - sock.print("150 Opening BINARY mode data connection for |echo hello (#{binary_data.size} bytes)\r\n") - conn = TCPSocket.new(host, port) - binary_data.scan(/.{1,1024}/nm) do |s| - conn.print(s) - end - conn.shutdown(Socket::SHUT_WR) - conn.read - conn.close - sock.print("226 Transfer complete.\r\n") - } - begin - chdir_to_tmpdir do - begin - ftp = Net::FTP.new - ftp.resume = resume - ftp.read_timeout = RubyVM::MJIT.enabled? ? 5 : 0.2 # use large timeout for --jit-wait - ftp.connect(SERVER_ADDR, server.port) - ftp.login - assert_match(/\AUSER /, commands.shift) - assert_match(/\APASS /, commands.shift) - assert_equal("TYPE I\r\n", commands.shift) - ftp.getbinaryfile("|echo hello") - assert_equal(binary_data, File.binread("./|echo hello")) - assert_match(/\A(PORT|EPRT) /, commands.shift) - assert_equal("RETR |echo hello\r\n", commands.shift) - assert_equal(nil, commands.shift) - ensure - ftp.close if ftp - end - end - ensure - server.close - end - end - end - - def test_gettextfile_command_injection - skip "| is not allowed in filename on Windows" if windows? - commands = [] - text_data = <"file"}, "foo").file?) - assert_equal(false, Net::FTP::MLSxEntry.new({"type"=>"dir"}, "foo").file?) - assert_equal(false, Net::FTP::MLSxEntry.new({"type"=>"cdir"}, "foo").file?) - assert_equal(false, Net::FTP::MLSxEntry.new({"type"=>"pdir"}, "foo").file?) - end - - def test_directory? - assert_equal(false, - Net::FTP::MLSxEntry.new({"type"=>"file"}, "foo").directory?) - assert_equal(true, - Net::FTP::MLSxEntry.new({"type"=>"dir"}, "foo").directory?) - assert_equal(true, - Net::FTP::MLSxEntry.new({"type"=>"cdir"}, "foo").directory?) - assert_equal(true, - Net::FTP::MLSxEntry.new({"type"=>"pdir"}, "foo").directory?) - end - - def test_appendable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"a"}, "foo").appendable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").appendable?) - end - - def test_creatable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"c"}, "foo").creatable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").creatable?) - end - - def test_deletable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"d"}, "foo").deletable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").deletable?) - end - - def test_enterable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"e"}, "foo").enterable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").enterable?) - end - - def test_renamable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"f"}, "foo").renamable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").renamable?) - end - - def test_listable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"l"}, "foo").listable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").listable?) - end - - def test_directory_makable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"m"}, "foo"). - directory_makable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo"). - directory_makable?) - end - - def test_purgeable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"p"}, "foo").purgeable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").purgeable?) - end - - def test_readable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"r"}, "foo").readable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").readable?) - end - - def test_writable? - assert_equal(true, - Net::FTP::MLSxEntry.new({"perm"=>"w"}, "foo").writable?) - assert_equal(false, - Net::FTP::MLSxEntry.new({"perm"=>""}, "foo").writable?) - end -end diff --git a/ruby/test/net/http/test_http.rb b/ruby/test/net/http/test_http.rb index 231aa4855..b5156078a 100644 --- a/ruby/test/net/http/test_http.rb +++ b/ruby/test/net/http/test_http.rb @@ -188,6 +188,23 @@ def test_proxy_eh_ENV_with_user end end + def test_proxy_eh_ENV_with_urlencoded_user + TestNetHTTPUtils.clean_http_proxy_env do + ENV['http_proxy'] = 'http://Y%5CX:R%25S%5D%20%3FX@proxy.example:8000' + + http = Net::HTTP.new 'hostname.example' + + assert_equal true, http.proxy? + if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE + assert_equal "Y\\X", http.proxy_user + assert_equal "R%S] ?X", http.proxy_pass + else + assert_nil http.proxy_user + assert_nil http.proxy_pass + end + end + end + def test_proxy_eh_ENV_none_set TestNetHTTPUtils.clean_http_proxy_env do assert_equal false, Net::HTTP.new('hostname.example').proxy? @@ -283,6 +300,27 @@ def test_s_start def test_s_get assert_equal $test_net_http_data, Net::HTTP.get(config('host'), '/', config('port')) + + assert_equal $test_net_http_data, Net::HTTP.get( + URI.parse("http://#{config('host')}:#{config('port')}") + ) + assert_equal $test_net_http_data, Net::HTTP.get( + URI.parse("http://#{config('host')}:#{config('port')}"), "Accept" => "text/plain" + ) + end + + def test_s_get_response + res = Net::HTTP.get_response( + URI.parse("http://#{config('host')}:#{config('port')}") + ) + assert_equal "application/octet-stream", res["Content-Type"] + assert_equal $test_net_http_data, res.body + + res = Net::HTTP.get_response( + URI.parse("http://#{config('host')}:#{config('port')}"), "Accept" => "text/plain" + ) + assert_equal "text/plain", res["Content-Type"] + assert_equal $test_net_http_data, res.body end def test_head @@ -538,6 +576,33 @@ def test_timeout_during_HTTP_session_write th&.join end + def test_timeout_during_non_chunked_streamed_HTTP_session_write + th = nil + # listen for connections... but deliberately do not read + TCPServer.open('localhost', 0) {|server| + port = server.addr[1] + + conn = Net::HTTP.new('localhost', port) + conn.write_timeout = 0.01 + conn.read_timeout = 0.01 if windows? + conn.open_timeout = 0.1 + + req = Net::HTTP::Post.new('/') + data = "a"*50_000_000 + req.content_length = data.size + req['Content-Type'] = 'application/x-www-form-urlencoded' + req.body_stream = StringIO.new(data) + + th = Thread.new do + assert_raise(Net::WriteTimeout) { conn.request(req) } + end + assert th.join(10) + } + ensure + th&.kill + th&.join + end + def test_timeout_during_HTTP_session bug4246 = "expected the HTTP session to have timed out but have not. c.f. [ruby-core:34203]" @@ -548,7 +613,7 @@ def test_timeout_during_HTTP_session conn = Net::HTTP.new('localhost', port) conn.read_timeout = EnvUtil.apply_timeout_scale(0.01) - conn.open_timeout = EnvUtil.apply_timeout_scale(0.1) + conn.open_timeout = EnvUtil.apply_timeout_scale(1) th = Thread.new do assert_raise(Net::ReadTimeout) { @@ -1103,6 +1168,30 @@ def test_keep_alive_get_auto_retry } end + def test_keep_alive_reset_on_new_connection + # Using WEBrick's debug log output on accepting connection: + # + # "[2021-04-29 20:36:46] DEBUG accept: 127.0.0.1:50674\n" + @log_tester = nil + @server.logger.level = WEBrick::BasicLog::DEBUG + + start {|http| + res = http.get('/') + http.keep_alive_timeout = 1 + assert_kind_of Net::HTTPResponse, res + assert_kind_of String, res.body + http.finish + assert_equal 1, @log.grep(/accept/i).size + + sleep 1.5 + http.start + res = http.get('/') + assert_kind_of Net::HTTPResponse, res + assert_kind_of String, res.body + assert_equal 2, @log.grep(/accept/i).size + } + end + class MockSocket attr_reader :count def initialize(success_after: nil) diff --git a/ruby/test/net/http/test_http_request.rb b/ruby/test/net/http/test_http_request.rb index c1ad99a11..7fd82b035 100644 --- a/ruby/test/net/http/test_http_request.rb +++ b/ruby/test/net/http/test_http_request.rb @@ -1,7 +1,6 @@ # frozen_string_literal: false require 'net/http' require 'test/unit' -require 'stringio' class HTTPRequestTest < Test::Unit::TestCase @@ -47,8 +46,9 @@ def test_initialize_HEAD assert_not_predicate req, :response_body_permitted? expected = { - 'accept' => %w[*/*], - 'user-agent' => %w[Ruby], + 'accept' => %w[*/*], + "accept-encoding" => %w[gzip;q=1.0,deflate;q=0.6,identity;q=0.3], + 'user-agent' => %w[Ruby], } assert_equal expected, req.to_hash diff --git a/ruby/test/net/http/test_httpresponse.rb b/ruby/test/net/http/test_httpresponse.rb index a03bb2e15..1a7890728 100644 --- a/ruby/test/net/http/test_httpresponse.rb +++ b/ruby/test/net/http/test_httpresponse.rb @@ -77,6 +77,10 @@ def test_read_body_block end def test_read_body_block_mod + # http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/3019353 + if defined?(RubyVM::MJIT) ? RubyVM::MJIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + omit 'too unstable with --jit-wait, and extending read_timeout did not help it' + end IO.pipe do |r, w| buf = 'x' * 1024 buf.freeze diff --git a/ruby/test/net/http/test_https.rb b/ruby/test/net/http/test_https.rb index 17fabb62d..4dc9f1b02 100644 --- a/ruby/test/net/http/test_https.rb +++ b/ruby/test/net/http/test_https.rb @@ -1,10 +1,8 @@ # frozen_string_literal: false require "test/unit" +require_relative "utils" begin require 'net/https' - require 'stringio' - require 'timeout' - require File.expand_path("utils", File.dirname(__FILE__)) rescue LoadError # should skip this test end @@ -12,18 +10,20 @@ class TestNetHTTPS < Test::Unit::TestCase include TestNetHTTPUtils - def self.fixture(key) + def self.read_fixture(key) File.read(File.expand_path("../fixtures/#{key}", __dir__)) end - CA_CERT = OpenSSL::X509::Certificate.new(fixture("cacert.pem")) - SERVER_KEY = OpenSSL::PKey.read(fixture("server.key")) - SERVER_CERT = OpenSSL::X509::Certificate.new(fixture("server.crt")) - DHPARAMS = OpenSSL::PKey::DH.new(fixture("dhparams.pem")) + HOST = 'localhost' + HOST_IP = '127.0.0.1' + CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem")) + SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key")) + SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt")) + DHPARAMS = OpenSSL::PKey::DH.new(read_fixture("dhparams.pem")) TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) } CONFIG = { - 'host' => '127.0.0.1', + 'host' => HOST, 'proxy_host' => nil, 'proxy_port' => nil, 'ssl_enable' => true, @@ -33,7 +33,7 @@ def self.fixture(key) } def test_get - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE certs = [] @@ -44,14 +44,14 @@ def test_get http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) } - assert_equal(CA_CERT.to_der, certs[0].to_der) - assert_equal(SERVER_CERT.to_der, certs[1].to_der) - rescue SystemCallError - skip $! + # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility + certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| + assert_equal(expected.to_der, actual.to_der) + end end def test_get_SNI - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.ipaddr = config('host') http.use_ssl = true http.cert_store = TEST_STORE @@ -63,15 +63,17 @@ def test_get_SNI http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) } - assert_equal(CA_CERT.to_der, certs[0].to_der) - assert_equal(SERVER_CERT.to_der, certs[1].to_der) + # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility + certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| + assert_equal(expected.to_der, actual.to_der) + end end def test_get_SNI_proxy - TCPServer.open("127.0.0.1", 0) {|serv| + TCPServer.open(HOST_IP, 0) {|serv| _, port, _, _ = serv.addr client_thread = Thread.new { - proxy = Net::HTTP.Proxy("127.0.0.1", port, 'user', 'password') + proxy = Net::HTTP.Proxy(HOST_IP, port, 'user', 'password') http = proxy.new("foo.example.org", 8000) http.ipaddr = "192.0.2.1" http.use_ssl = true @@ -108,7 +110,7 @@ def test_get_SNI_proxy def test_get_SNI_failure TestNetHTTPUtils.clean_http_proxy_env do - http = Net::HTTP.new("invalid_servername", config("port")) + http = Net::HTTP.new("invalidservername", config("port")) http.ipaddr = config('host') http.use_ssl = true http.cert_store = TEST_STORE @@ -123,15 +125,13 @@ def test_get_SNI_failure end def test_post - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE data = config('ssl_private_key').to_der http.request_post("/", data, {'content-type' => 'application/x-www-form-urlencoded'}) {|res| assert_equal(data, res.body) } - rescue SystemCallError - skip $! end def test_session_reuse @@ -139,30 +139,34 @@ def test_session_reuse # See https://github.com/openssl/openssl/pull/5967 for details. skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE + if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /LibreSSL (\d+\.\d+)/ && $1.to_f > 3.19 + # LibreSSL 3.2 defaults to TLSv1.3 in server and client, which doesn't currently + # support session resuse. Limiting the version to the TLSv1.2 stack allows + # this test to continue to work on LibreSSL 3.2+. LibreSSL may eventually + # support session reuse, but there are no current plans to do so. + http.ssl_version = :TLSv1 + end + http.start + assert_equal false, http.instance_variable_get(:@socket).io.session_reused? http.get("/") http.finish http.start - http.get("/") - - socket = http.instance_variable_get(:@socket).io - assert_equal true, socket.session_reused? - + assert_equal true, http.instance_variable_get(:@socket).io.session_reused? + assert_equal $test_net_http_data, http.get("/").body http.finish - rescue SystemCallError - skip $! end def test_session_reuse_but_expire # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @@ -178,8 +182,6 @@ def test_session_reuse_but_expire assert_equal false, socket.session_reused? http.finish - rescue SystemCallError - skip $! end if ENV["RUBY_OPENSSL_TEST_ALL"] @@ -194,25 +196,44 @@ def test_verify end def test_verify_none - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) } - rescue SystemCallError - skip $! + end + + def test_skip_hostname_verification + TestNetHTTPUtils.clean_http_proxy_env do + http = Net::HTTP.new('invalidservername', config('port')) + http.ipaddr = config('host') + http.use_ssl = true + http.cert_store = TEST_STORE + http.verify_hostname = false + assert_nothing_raised { http.start } + ensure + http.finish if http&.started? + end + end + + def test_fail_if_verify_hostname_is_true + TestNetHTTPUtils.clean_http_proxy_env do + http = Net::HTTP.new('invalidservername', config('port')) + http.ipaddr = config('host') + http.use_ssl = true + http.cert_store = TEST_STORE + http.verify_hostname = true + @log_tester = lambda { |_| } + assert_raise(OpenSSL::SSL::SSLError) { http.start } + end end def test_certificate_verify_failure - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true ex = assert_raise(OpenSSL::SSL::SSLError){ - begin - http.request_get("/") {|res| } - rescue SystemCallError - skip $! - end + http.request_get("/") {|res| } } assert_match(/certificate verify failed/, ex.message) unless /mswin|mingw/ =~ RUBY_PLATFORM @@ -227,14 +248,14 @@ def test_certificate_verify_failure def test_identity_verify_failure # the certificate's subject has CN=localhost - http = Net::HTTP.new("127.0.0.1", config("port")) + http = Net::HTTP.new(HOST_IP, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @log_tester = lambda {|_| } ex = assert_raise(OpenSSL::SSL::SSLError){ http.request_get("/") {|res| } } - re_msg = /certificate verify failed|hostname \"127.0.0.1\" does not match/ + re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/ assert_match(re_msg, ex.message) end @@ -242,10 +263,10 @@ def test_timeout_during_SSL_handshake bug4246 = "expected the SSL connection to have timed out but have not. [ruby-core:34203]" # listen for connections... but deliberately do not complete SSL handshake - TCPServer.open('localhost', 0) {|server| + TCPServer.open(HOST, 0) {|server| port = server.addr[1] - conn = Net::HTTP.new('localhost', port) + conn = Net::HTTP.new(HOST, port) conn.use_ssl = true conn.read_timeout = 0.01 conn.open_timeout = 0.01 @@ -260,7 +281,7 @@ def test_timeout_during_SSL_handshake end def test_min_version - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.min_version = :TLS1 http.cert_store = TEST_STORE @@ -270,7 +291,7 @@ def test_min_version end def test_max_version - http = Net::HTTP.new("127.0.0.1", config("port")) + http = Net::HTTP.new(HOST_IP, config("port")) http.use_ssl = true http.max_version = :SSL2 http.verify_callback = Proc.new do |preverify_ok, store_ctx| diff --git a/ruby/test/net/http/utils.rb b/ruby/test/net/http/utils.rb index 53f3be0b8..e343e1671 100644 --- a/ruby/test/net/http/utils.rb +++ b/ruby/test/net/http/utils.rb @@ -81,7 +81,11 @@ def initialize(this, chunked = false) end def do_GET(req, res) - res['Content-Type'] = $test_net_http_data_type + if req['Accept'] != '*/*' + res['Content-Type'] = req['Accept'] + else + res['Content-Type'] = $test_net_http_data_type + end res.body = $test_net_http_data res.chunked = @chunked end diff --git a/ruby/test/net/imap/test_imap.rb b/ruby/test/net/imap/test_imap.rb deleted file mode 100644 index 33b305e11..000000000 --- a/ruby/test/net/imap/test_imap.rb +++ /dev/null @@ -1,794 +0,0 @@ -# frozen_string_literal: true - -require "net/imap" -require "test/unit" - -class IMAPTest < Test::Unit::TestCase - CA_FILE = File.expand_path("../fixtures/cacert.pem", __dir__) - SERVER_KEY = File.expand_path("../fixtures/server.key", __dir__) - SERVER_CERT = File.expand_path("../fixtures/server.crt", __dir__) - - def setup - @do_not_reverse_lookup = Socket.do_not_reverse_lookup - Socket.do_not_reverse_lookup = true - @threads = [] - end - - def teardown - if !@threads.empty? - assert_join_threads(@threads) - end - ensure - Socket.do_not_reverse_lookup = @do_not_reverse_lookup - end - - def test_encode_utf7 - assert_equal("foo", Net::IMAP.encode_utf7("foo")) - assert_equal("&-", Net::IMAP.encode_utf7("&")) - - utf8 = "\357\274\241\357\274\242\357\274\243".dup.force_encoding("UTF-8") - s = Net::IMAP.encode_utf7(utf8) - assert_equal("&,yH,Iv8j-", s) - s = Net::IMAP.encode_utf7("foo&#{utf8}-bar".encode("EUC-JP")) - assert_equal("foo&-&,yH,Iv8j--bar", s) - - utf8 = "\343\201\202&".dup.force_encoding("UTF-8") - s = Net::IMAP.encode_utf7(utf8) - assert_equal("&MEI-&-", s) - s = Net::IMAP.encode_utf7(utf8.encode("EUC-JP")) - assert_equal("&MEI-&-", s) - end - - def test_decode_utf7 - assert_equal("&", Net::IMAP.decode_utf7("&-")) - assert_equal("&-", Net::IMAP.decode_utf7("&--")) - - s = Net::IMAP.decode_utf7("&,yH,Iv8j-") - utf8 = "\357\274\241\357\274\242\357\274\243".dup.force_encoding("UTF-8") - assert_equal(utf8, s) - end - - def test_format_date - time = Time.mktime(2009, 7, 24) - s = Net::IMAP.format_date(time) - assert_equal("24-Jul-2009", s) - end - - def test_format_datetime - time = Time.mktime(2009, 7, 24, 1, 23, 45) - s = Net::IMAP.format_datetime(time) - assert_match(/\A24-Jul-2009 01:23 [+\-]\d{4}\z/, s) - end - - if defined?(OpenSSL::SSL::SSLError) - def test_imaps_unknown_ca - assert_raise(OpenSSL::SSL::SSLError) do - imaps_test do |port| - begin - Net::IMAP.new("localhost", - :port => port, - :ssl => true) - rescue SystemCallError - skip $! - end - end - end - end - - def test_imaps_with_ca_file - assert_nothing_raised do - imaps_test do |port| - begin - Net::IMAP.new("localhost", - :port => port, - :ssl => { :ca_file => CA_FILE }) - rescue SystemCallError - skip $! - end - end - end - end - - def test_imaps_verify_none - assert_nothing_raised do - imaps_test do |port| - Net::IMAP.new(server_addr, - :port => port, - :ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE }) - end - end - end - - def test_imaps_post_connection_check - assert_raise(OpenSSL::SSL::SSLError) do - imaps_test do |port| - # server_addr is different from the hostname in the certificate, - # so the following code should raise a SSLError. - Net::IMAP.new(server_addr, - :port => port, - :ssl => { :ca_file => CA_FILE }) - end - end - end - end - - if defined?(OpenSSL::SSL) - def test_starttls - imap = nil - starttls_test do |port| - imap = Net::IMAP.new("localhost", :port => port) - imap.starttls(:ca_file => CA_FILE) - imap - end - rescue SystemCallError - skip $! - ensure - if imap && !imap.disconnected? - imap.disconnect - end - end - end - - def start_server - th = Thread.new do - yield - end - @threads << th - sleep 0.1 until th.stop? - end - - def test_unexpected_eof - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - sock.gets -# sock.print("* BYE terminating connection\r\n") -# sock.print("RUBY0001 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - assert_raise(EOFError) do - imap.logout - end - ensure - imap.disconnect if imap - end - end - - def test_idle - server = create_tcp_server - port = server.addr[1] - requests = [] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - requests.push(sock.gets) - sock.print("+ idling\r\n") - sock.print("* 3 EXISTS\r\n") - sock.print("* 2 EXPUNGE\r\n") - requests.push(sock.gets) - sock.print("RUBY0001 OK IDLE terminated\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0002 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - - begin - imap = Net::IMAP.new(server_addr, :port => port) - responses = [] - imap.idle do |res| - responses.push(res) - if res.name == "EXPUNGE" - imap.idle_done - end - end - assert_equal(3, responses.length) - assert_instance_of(Net::IMAP::ContinuationRequest, responses[0]) - assert_equal("EXISTS", responses[1].name) - assert_equal(3, responses[1].data) - assert_equal("EXPUNGE", responses[2].name) - assert_equal(2, responses[2].data) - assert_equal(2, requests.length) - assert_equal("RUBY0001 IDLE\r\n", requests[0]) - assert_equal("DONE\r\n", requests[1]) - imap.logout - ensure - imap.disconnect if imap - end - end - - def test_exception_during_idle - server = create_tcp_server - port = server.addr[1] - requests = [] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - requests.push(sock.gets) - sock.print("+ idling\r\n") - sock.print("* 3 EXISTS\r\n") - sock.print("* 2 EXPUNGE\r\n") - requests.push(sock.gets) - sock.print("RUBY0001 OK IDLE terminated\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0002 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - begin - th = Thread.current - m = Monitor.new - in_idle = false - exception_raised = false - c = m.new_cond - raiser = Thread.start do - m.synchronize do - until in_idle - c.wait(0.1) - end - end - th.raise(Interrupt) - m.synchronize do - exception_raised = true - c.signal - end - end - @threads << raiser - imap.idle do |res| - m.synchronize do - in_idle = true - c.signal - until exception_raised - c.wait(0.1) - end - end - end - rescue Interrupt - end - assert_equal(2, requests.length) - assert_equal("RUBY0001 IDLE\r\n", requests[0]) - assert_equal("DONE\r\n", requests[1]) - imap.logout - ensure - imap.disconnect if imap - raiser.kill unless in_idle - end - end - - def test_idle_done_not_during_idle - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - assert_raise(Net::IMAP::Error) do - imap.idle_done - end - ensure - imap.disconnect if imap - end - end - - def test_idle_timeout - server = create_tcp_server - port = server.addr[1] - requests = [] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - requests.push(sock.gets) - sock.print("+ idling\r\n") - sock.print("* 3 EXISTS\r\n") - sock.print("* 2 EXPUNGE\r\n") - requests.push(sock.gets) - sock.print("RUBY0001 OK IDLE terminated\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0002 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - - begin - imap = Net::IMAP.new(server_addr, :port => port) - responses = [] - Thread.pass - imap.idle(0.2) do |res| - responses.push(res) - end - # There is no guarantee that this thread has received all the responses, - # so check the response length. - if responses.length > 0 - assert_instance_of(Net::IMAP::ContinuationRequest, responses[0]) - if responses.length > 1 - assert_equal("EXISTS", responses[1].name) - assert_equal(3, responses[1].data) - if responses.length > 2 - assert_equal("EXPUNGE", responses[2].name) - assert_equal(2, responses[2].data) - end - end - end - # Also, there is no guarantee that the server thread has stored - # all the requests into the array, so check the length. - if requests.length > 0 - assert_equal("RUBY0001 IDLE\r\n", requests[0]) - if requests.length > 1 - assert_equal("DONE\r\n", requests[1]) - end - end - imap.logout - ensure - imap.disconnect if imap - end - end - - def test_unexpected_bye - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK Gimap ready for requests from 75.101.246.151 33if2752585qyk.26\r\n") - sock.gets - sock.print("* BYE System Error 33if2752585qyk.26\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - assert_raise(Net::IMAP::ByeResponseError) do - imap.login("user", "password") - end - end - end - - def test_exception_during_shutdown - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0001 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - imap.instance_eval do - def @sock.shutdown(*args) - super - ensure - raise "error" - end - end - imap.logout - ensure - assert_raise(RuntimeError) do - imap.disconnect - end - end - end - - def test_connection_closed_during_idle - server = create_tcp_server - port = server.addr[1] - requests = [] - sock = nil - threads = [] - started = false - threads << Thread.start do - started = true - begin - sock = server.accept - sock.print("* OK test server\r\n") - requests.push(sock.gets) - sock.print("+ idling\r\n") - rescue IOError # sock is closed by another thread - ensure - server.close - end - end - sleep 0.1 until started - threads << Thread.start do - imap = Net::IMAP.new(server_addr, :port => port) - begin - m = Monitor.new - in_idle = false - closed = false - c = m.new_cond - threads << Thread.start do - m.synchronize do - until in_idle - c.wait(0.1) - end - end - sock.close - m.synchronize do - closed = true - c.signal - end - end - assert_raise(EOFError) do - imap.idle do |res| - m.synchronize do - in_idle = true - c.signal - until closed - c.wait(0.1) - end - end - end - end - assert_equal(1, requests.length) - assert_equal("RUBY0001 IDLE\r\n", requests[0]) - ensure - imap.disconnect if imap - end - end - assert_join_threads(threads) - ensure - if sock && !sock.closed? - sock.close - end - end - - def test_connection_closed_without_greeting - server = create_tcp_server - port = server.addr[1] - h = {'server before close': server.inspect} # inspect info before close - start_server do - begin - sock = server.accept - h[:sock_addr], h[:sock_peeraddr] = sock.addr, sock.peeraddr - sock.close - ensure - server.close - end - end - assert_raise(Net::IMAP::Error) do - #begin - Net::IMAP.new(server_addr, :port => port) - #rescue Net::IMAP::Error - # raise Errno::EINVAL - #end - rescue Errno::EINVAL => e # for debug on OpenCSW - h.merge!({e: e, server: server, port: port, server_addr: server_addr}) - raise(h.inspect) - end - end - - def test_default_port - assert_equal(143, Net::IMAP.default_port) - assert_equal(143, Net::IMAP.default_imap_port) - assert_equal(993, Net::IMAP.default_tls_port) - assert_equal(993, Net::IMAP.default_ssl_port) - assert_equal(993, Net::IMAP.default_imaps_port) - end - - def test_send_invalid_number - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - sock.gets - sock.print("RUBY0001 OK TEST completed\r\n") - sock.gets - sock.print("RUBY0002 OK TEST completed\r\n") - sock.gets - sock.print("RUBY0003 OK TEST completed\r\n") - sock.gets - sock.print("RUBY0004 OK TEST completed\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0005 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - assert_raise(Net::IMAP::DataFormatError) do - imap.send(:send_command, "TEST", -1) - end - imap.send(:send_command, "TEST", 0) - imap.send(:send_command, "TEST", 4294967295) - assert_raise(Net::IMAP::DataFormatError) do - imap.send(:send_command, "TEST", 4294967296) - end - assert_raise(Net::IMAP::DataFormatError) do - imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(-1)) - end - assert_raise(Net::IMAP::DataFormatError) do - imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(0)) - end - imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(1)) - imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967295)) - assert_raise(Net::IMAP::DataFormatError) do - imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967296)) - end - imap.logout - ensure - imap.disconnect - end - end - - def test_send_literal - server = create_tcp_server - port = server.addr[1] - requests = [] - literal = nil - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - line = sock.gets - requests.push(line) - size = line.slice(/{(\d+)}\r\n/, 1).to_i - sock.print("+ Ready for literal data\r\n") - literal = sock.read(size) - requests.push(sock.gets) - sock.print("RUBY0001 OK TEST completed\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0002 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - imap.send(:send_command, "TEST", ["\xDE\xAD\xBE\xEF".b]) - assert_equal(2, requests.length) - assert_equal("RUBY0001 TEST ({4}\r\n", requests[0]) - assert_equal("\xDE\xAD\xBE\xEF".b, literal) - assert_equal(")\r\n", requests[1]) - imap.logout - ensure - imap.disconnect - end - end - - def test_disconnect - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0001 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = Net::IMAP.new(server_addr, :port => port) - imap.logout - imap.disconnect - assert_equal(true, imap.disconnected?) - imap.disconnect - assert_equal(true, imap.disconnected?) - ensure - imap.disconnect if imap && !imap.disconnected? - end - end - - def test_append - server = create_tcp_server - port = server.addr[1] - mail = < port) - imap.append("INBOX", mail) - assert_equal(1, requests.length) - assert_equal("RUBY0001 APPEND INBOX {#{mail.size}}\r\n", requests[0]) - assert_equal(mail, received_mail) - imap.logout - assert_equal(2, requests.length) - assert_equal("RUBY0002 LOGOUT\r\n", requests[1]) - ensure - imap.disconnect if imap - end - end - - def test_append_fail - server = create_tcp_server - port = server.addr[1] - mail = < port) - assert_raise(Net::IMAP::NoResponseError) do - imap.append("INBOX", mail) - end - assert_equal(1, requests.length) - assert_equal("RUBY0001 APPEND INBOX {#{mail.size}}\r\n", requests[0]) - imap.logout - assert_equal(2, requests.length) - assert_equal("RUBY0002 LOGOUT\r\n", requests[1]) - ensure - imap.disconnect if imap - end - end - - private - - def imaps_test - server = create_tcp_server - port = server.addr[1] - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx) - started = false - ths = Thread.start do - Thread.current.report_on_exception = false # always join-ed - begin - started = true - sock = ssl_server.accept - begin - sock.print("* OK test server\r\n") - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0001 OK LOGOUT completed\r\n") - ensure - sock.close - end - rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED - end - end - sleep 0.1 until started - begin - begin - imap = yield(port) - imap.logout - ensure - imap.disconnect if imap - end - ensure - ssl_server.close - ths.join - end - end - - def starttls_test - server = create_tcp_server - port = server.addr[1] - start_server do - sock = server.accept - begin - sock.print("* OK test server\r\n") - sock.gets - sock.print("RUBY0001 OK completed\r\n") - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - sock = OpenSSL::SSL::SSLSocket.new(sock, ctx) - sock.sync_close = true - sock.accept - sock.gets - sock.print("* BYE terminating connection\r\n") - sock.print("RUBY0002 OK LOGOUT completed\r\n") - ensure - sock.close - server.close - end - end - begin - imap = yield(port) - imap.logout if !imap.disconnected? - ensure - imap.disconnect if imap && !imap.disconnected? - end - end - - def create_tcp_server - return TCPServer.new(server_addr, 0) - end - - def server_addr - Addrinfo.tcp("localhost", 0).ip_address - end -end diff --git a/ruby/test/net/imap/test_imap_response_parser.rb b/ruby/test/net/imap/test_imap_response_parser.rb deleted file mode 100644 index 4e470459c..000000000 --- a/ruby/test/net/imap/test_imap_response_parser.rb +++ /dev/null @@ -1,311 +0,0 @@ -# frozen_string_literal: true - -require "net/imap" -require "test/unit" - -class IMAPResponseParserTest < Test::Unit::TestCase - def setup - @do_not_reverse_lookup = Socket.do_not_reverse_lookup - Socket.do_not_reverse_lookup = true - if Net::IMAP.respond_to?(:max_flag_count) - @max_flag_count = Net::IMAP.max_flag_count - Net::IMAP.max_flag_count = 3 - end - end - - def teardown - Socket.do_not_reverse_lookup = @do_not_reverse_lookup - if Net::IMAP.respond_to?(:max_flag_count) - Net::IMAP.max_flag_count = @max_flag_count - end - end - - def test_flag_list_too_many_flags - parser = Net::IMAP::ResponseParser.new - assert_nothing_raised do - 3.times do |i| - parser.parse(< -Envelope-to: info@xxxxxxxx.si -Delivery-date: Tue, 26 Mar 2013 12:42:58 +0100 -Received: from mail by xxxx.xxxxxxxxxxx.net with spam-scanned (Exim 4.76) - id 1UKSHI-000Cwl-AR - for info@xxxxxxxx.si; Tue, 26 Mar 2013 12:42:58 +0100 -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on xxxx.xxxxxxxxxxx.net -X-Spam-Level: ** -X-Spam-Status: No, score=2.1 required=7.0 tests=DKIM_ADSP_NXDOMAIN,RDNS_NONE - autolearn=no version=3.3.1 -Received: from [xx.xxx.xxx.xx] (port=56890 helo=xxxxxx.localdomain) - by xxxx.xxxxxxxxxxx.net with esmtp (Exim 4.76) - id 1UKSHI-000Cwi-9j - for info@xxxxxxxx.si; Tue, 26 Mar 2013 12:42:56 +0100 -Received: by xxxxxx.localdomain (Postfix) - id 72725BEA64A; Tue, 26 Mar 2013 12:42:55 +0100 (CET) -Date: Tue, 26 Mar 2013 12:42:55 +0100 (CET) -From: MAILER-DAEMON@xxxxxx.localdomain (Mail Delivery System) -Subject: Undelivered Mail Returned to Sender -To: info@xxxxxxxx.si -Auto-Submitted: auto-replied -MIME-Version: 1.0 -Content-Type: multipart/report; report-type=delivery-status; - boundary="27797BEA649.1364298175/xxxxxx.localdomain" -Message-Id: <20130326114255.72725BEA64A@xxxxxx.localdomain> - - BODYSTRUCTURE (("text" "plain" ("charset" "us-ascii") NIL "Notification" "7bit" 510 14 NIL NIL NIL NIL)("message" "delivery-status" NIL NIL "Delivery report" "7bit" 410 NIL NIL NIL NIL)("text" "rfc822-headers" ("charset" "us-ascii") NIL "Undelivered Message Headers" "7bit" 612 15 NIL NIL NIL NIL) "report" ("report-type" "delivery-status" "boundary" "27797BEA649.1364298175/xxxxxx.localdomain") NIL NIL NIL)) -EOF - delivery_status = response.data.attr["BODYSTRUCTURE"].parts[1] - assert_equal("MESSAGE", delivery_status.media_type) - assert_equal("DELIVERY-STATUS", delivery_status.subtype) - assert_equal(nil, delivery_status.param) - assert_equal(nil, delivery_status.content_id) - assert_equal("Delivery report", delivery_status.description) - assert_equal("7BIT", delivery_status.encoding) - assert_equal(410, delivery_status.size) - end - - # [Bug #8281] - def test_acl - parser = Net::IMAP::ResponseParser.new - response = parser.parse(<\" " \ - "\"\")" \ - " (\"MIXED\" (\"BOUNDARY\" \"000e0cd29212e3e06a0486590ae2\") NIL NIL)" \ - " 37 NIL NIL NIL)" \ - " \"REPORT\" (\"BOUNDARY\" \"16DuG.4XbaNOvCi.9ggvq.8Ipnyp3\" \"REPORT-TYPE\" \"delivery-status\") NIL NIL))\r\n") - empty_part = response.data.attr['BODYSTRUCTURE'].parts[2] - assert_equal(empty_part.lines, 37) - assert_equal(empty_part.body.media_type, 'MULTIPART') - assert_equal(empty_part.body.subtype, 'MIXED') - assert_equal(empty_part.body.param['BOUNDARY'], '000e0cd29212e3e06a0486590ae2') - end - - # [Bug #10112] - def test_search_modseq - parser = Net::IMAP::ResponseParser.new - response = parser.parse("* SEARCH 87216 87221 (MODSEQ 7667567)\r\n") - assert_equal("SEARCH", response.name) - assert_equal([87216, 87221], response.data) - end - - # [Bug #11128] - def test_body_ext_mpart_without_lang - parser = Net::IMAP::ResponseParser.new - response = parser.parse("* 4 FETCH (BODY (((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 257 9 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"quoted-printable\" 655 9 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"001a1137a5047848dd05157ddaa1\") NIL)(\"application\" \"pdf\" (\"name\" \"test.xml\" \"x-apple-part-url\" \"9D00D9A2-98AB-4EFB-85BA-FB255F8BF3D7\") NIL NIL \"base64\" 4383638 NIL (\"attachment\" (\"filename\" \"test.xml\")) NIL NIL) \"mixed\" (\"boundary\" \"001a1137a5047848e405157ddaa3\") NIL))\r\n") - assert_equal("FETCH", response.name) - body = response.data.attr["BODY"] - assert_equal(nil, body.parts[0].disposition) - assert_equal(nil, body.parts[0].language) - assert_equal("ATTACHMENT", body.parts[1].disposition.dsp_type) - assert_equal("test.xml", body.parts[1].disposition.param["FILENAME"]) - assert_equal(nil, body.parts[1].language) - end - - # [Bug #13649] - def test_status - parser = Net::IMAP::ResponseParser.new - response = parser.parse("* STATUS INBOX (UIDNEXT 1 UIDVALIDITY 1234)\r\n") - assert_equal("STATUS", response.name) - assert_equal("INBOX", response.data.mailbox) - assert_equal(1234, response.data.attr["UIDVALIDITY"]) - response = parser.parse("* STATUS INBOX (UIDNEXT 1 UIDVALIDITY 1234) \r\n") - assert_equal("STATUS", response.name) - assert_equal("INBOX", response.data.mailbox) - assert_equal(1234, response.data.attr["UIDVALIDITY"]) - end - - # [Bug #10119] - def test_msg_att_modseq_data - parser = Net::IMAP::ResponseParser.new - response = parser.parse("* 1 FETCH (FLAGS (\Seen) MODSEQ (12345) UID 5)\r\n") - assert_equal(12345, response.data.attr["MODSEQ"]) - end - - def test_continuation_request_without_response_text - parser = Net::IMAP::ResponseParser.new - response = parser.parse("+\r\n") - assert_instance_of(Net::IMAP::ContinuationRequest, response) - assert_equal(nil, response.data.code) - assert_equal("", response.data.text) - end -end diff --git a/ruby/test/net/pop/test_pop.rb b/ruby/test/net/pop/test_pop.rb deleted file mode 100644 index f4c807a7a..000000000 --- a/ruby/test/net/pop/test_pop.rb +++ /dev/null @@ -1,166 +0,0 @@ -# frozen_string_literal: true -require 'net/pop' -require 'test/unit' -require 'digest/md5' - -class TestPOP < Test::Unit::TestCase - def setup - @users = {'user' => 'pass' } - @ok_user = 'user' - @stamp_base = "#{$$}.#{Time.now.to_i}@localhost" - end - - def test_pop_auth_ok - pop_test(false) do |pop| - assert_instance_of Net::POP3, pop - assert_nothing_raised do - pop.start(@ok_user, @users[@ok_user]) - end - end - end - - def test_pop_auth_ng - pop_test(false) do |pop| - assert_instance_of Net::POP3, pop - assert_raise Net::POPAuthenticationError do - pop.start(@ok_user, 'bad password') - end - end - end - - def test_apop_ok - pop_test(@stamp_base) do |pop| - assert_instance_of Net::APOP, pop - assert_nothing_raised do - pop.start(@ok_user, @users[@ok_user]) - end - end - end - - def test_apop_ng - pop_test(@stamp_base) do |pop| - assert_instance_of Net::APOP, pop - assert_raise Net::POPAuthenticationError do - pop.start(@ok_user, 'bad password') - end - end - end - - def test_apop_invalid - pop_test("\x80"+@stamp_base) do |pop| - assert_instance_of Net::APOP, pop - assert_raise Net::POPAuthenticationError do - pop.start(@ok_user, @users[@ok_user]) - end - end - end - - def test_apop_invalid_at - pop_test(@stamp_base.sub('@', '.')) do |pop| - assert_instance_of Net::APOP, pop - assert_raise Net::POPAuthenticationError do - pop.start(@ok_user, @users[@ok_user]) - end - end - end - - def test_popmail - # totally not representative of real messages, but - # enough to test frozen bugs - lines = [ "[ruby-core:85210]" , "[Bug #14416]" ].freeze - command = Object.new - command.instance_variable_set(:@lines, lines) - - def command.retr(n) - @lines.each { |l| yield "#{l}\r\n" } - end - - def command.top(number, nl) - @lines.each do |l| - yield "#{l}\r\n" - break if (nl -= 1) <= 0 - end - end - - net_pop = :unused - popmail = Net::POPMail.new(1, 123, net_pop, command) - res = popmail.pop - assert_equal "[ruby-core:85210]\r\n[Bug #14416]\r\n", res - assert_not_predicate res, :frozen? - - res = popmail.top(1) - assert_equal "[ruby-core:85210]\r\n", res - assert_not_predicate res, :frozen? - end - - def pop_test(apop=false) - host = 'localhost' - server = TCPServer.new(host, 0) - port = server.addr[1] - server_thread = Thread.start do - sock = server.accept - begin - pop_server_loop(sock, apop) - ensure - sock.close - end - end - client_thread = Thread.start do - begin - begin - pop = Net::POP3::APOP(apop).new(host, port) - #pop.set_debug_output $stderr - yield pop - ensure - begin - pop.finish - rescue IOError - raise unless $!.message == "POP session not yet started" - end - end - ensure - server.close - end - end - assert_join_threads([client_thread, server_thread]) - end - - def pop_server_loop(sock, apop) - if apop - sock.print "+OK ready <#{apop}>\r\n" - else - sock.print "+OK ready\r\n" - end - user = nil - while line = sock.gets - case line - when /^USER (.+)\r\n/ - user = $1 - if @users.key?(user) - sock.print "+OK\r\n" - else - sock.print "-ERR unknown user\r\n" - end - when /^PASS (.+)\r\n/ - if @users[user] == $1 - sock.print "+OK\r\n" - else - sock.print "-ERR invalid password\r\n" - end - when /^APOP (.+) (.+)\r\n/ - user = $1 - if apop && Digest::MD5.hexdigest("<#{apop}>#{@users[user]}") == $2 - sock.print "+OK\r\n" - else - sock.print "-ERR authentication failed\r\n" - end - when /^QUIT/ - sock.print "+OK bye\r\n" - return - else - sock.print "-ERR command not recognized\r\n" - return - end - end - end -end diff --git a/ruby/test/net/smtp/test_response.rb b/ruby/test/net/smtp/test_response.rb deleted file mode 100644 index 3cf909a76..000000000 --- a/ruby/test/net/smtp/test_response.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: true -require 'net/smtp' -require 'test/unit' - -module Net - class SMTP - class TestResponse < Test::Unit::TestCase - def test_capabilities - res = Response.parse("250-ubuntu-desktop\n250-PIPELINING\n250-SIZE 10240000\n250-VRFY\n250-ETRN\n250-STARTTLS\n250-ENHANCEDSTATUSCODES\n250 DSN\n") - - capabilities = res.capabilities - %w{ PIPELINING SIZE VRFY STARTTLS ENHANCEDSTATUSCODES DSN}.each do |str| - assert capabilities.key?(str), str - end - end - - def test_capabilities_default - res = Response.parse("250-ubuntu-desktop\n250-PIPELINING\n250 DSN\n") - assert_equal [], res.capabilities['PIPELINING'] - end - - def test_capabilities_value - res = Response.parse("250-ubuntu-desktop\n250-SIZE 1234\n250 DSN\n") - assert_equal ['1234'], res.capabilities['SIZE'] - end - - def test_capabilities_multi - res = Response.parse("250-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert_equal %w{1 2 3}, res.capabilities['SIZE'] - end - - def test_bad_string - res = Response.parse("badstring") - assert_equal({}, res.capabilities) - end - - def test_success? - res = Response.parse("250-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert res.success? - assert !res.continue? - end - - # RFC 2821, Section 4.2.1 - def test_continue? - res = Response.parse("3yz-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert !res.success? - assert res.continue? - end - - def test_status_type_char - res = Response.parse("3yz-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert_equal '3', res.status_type_char - - res = Response.parse("250-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert_equal '2', res.status_type_char - end - - def test_message - res = Response.parse("250-ubuntu-desktop\n250-SIZE 1 2 3\n250 DSN\n") - assert_equal "250-ubuntu-desktop\n", res.message - end - - def test_server_busy_exception - res = Response.parse("400 omg busy") - assert_equal Net::SMTPServerBusy, res.exception_class - res = Response.parse("410 omg busy") - assert_equal Net::SMTPServerBusy, res.exception_class - end - - def test_syntax_error_exception - res = Response.parse("500 omg syntax error") - assert_equal Net::SMTPSyntaxError, res.exception_class - - res = Response.parse("501 omg syntax error") - assert_equal Net::SMTPSyntaxError, res.exception_class - end - - def test_authentication_exception - res = Response.parse("530 omg auth error") - assert_equal Net::SMTPAuthenticationError, res.exception_class - - res = Response.parse("531 omg auth error") - assert_equal Net::SMTPAuthenticationError, res.exception_class - end - - def test_fatal_error - res = Response.parse("510 omg fatal error") - assert_equal Net::SMTPFatalError, res.exception_class - - res = Response.parse("511 omg fatal error") - assert_equal Net::SMTPFatalError, res.exception_class - end - - def test_default_exception - res = Response.parse("250 omg fatal error") - assert_equal Net::SMTPUnknownError, res.exception_class - end - end - end -end diff --git a/ruby/test/net/smtp/test_smtp.rb b/ruby/test/net/smtp/test_smtp.rb deleted file mode 100644 index 90c92e06f..000000000 --- a/ruby/test/net/smtp/test_smtp.rb +++ /dev/null @@ -1,200 +0,0 @@ -# frozen_string_literal: true -require 'net/smtp' -require 'stringio' -require 'test/unit' - -module Net - class TestSMTP < Test::Unit::TestCase - CA_FILE = File.expand_path("../fixtures/cacert.pem", __dir__) - SERVER_KEY = File.expand_path("../fixtures/server.key", __dir__) - SERVER_CERT = File.expand_path("../fixtures/server.crt", __dir__) - - class FakeSocket - attr_reader :write_io - - def initialize out = "250 OK\n" - @write_io = StringIO.new - @read_io = StringIO.new out - end - - def writeline line - @write_io.write "#{line}\r\n" - end - - def readline - line = @read_io.gets - raise 'ran out of input' unless line - line.chop - end - end - - def test_critical - smtp = Net::SMTP.new 'localhost', 25 - - assert_raise RuntimeError do - smtp.send :critical do - raise 'fail on purpose' - end - end - - assert_kind_of Net::SMTP::Response, smtp.send(:critical), - '[Bug #9125]' - end - - def test_esmtp - smtp = Net::SMTP.new 'localhost', 25 - assert smtp.esmtp - assert smtp.esmtp? - - smtp.esmtp = 'omg' - assert_equal 'omg', smtp.esmtp - assert_equal 'omg', smtp.esmtp? - end - - def test_rset - smtp = Net::SMTP.new 'localhost', 25 - smtp.instance_variable_set :@socket, FakeSocket.new - - assert smtp.rset - end - - def test_mailfrom - sock = FakeSocket.new - smtp = Net::SMTP.new 'localhost', 25 - smtp.instance_variable_set :@socket, sock - assert smtp.mailfrom("foo@example.com").success? - assert_equal "MAIL FROM:\r\n", sock.write_io.string - end - - def test_rcptto - sock = FakeSocket.new - smtp = Net::SMTP.new 'localhost', 25 - smtp.instance_variable_set :@socket, sock - assert smtp.rcptto("foo@example.com").success? - assert_equal "RCPT TO:\r\n", sock.write_io.string - end - - def test_auth_plain - sock = FakeSocket.new - smtp = Net::SMTP.new 'localhost', 25 - smtp.instance_variable_set :@socket, sock - assert smtp.auth_plain("foo", "bar").success? - assert_equal "AUTH PLAIN AGZvbwBiYXI=\r\n", sock.write_io.string - end - - def test_crlf_injection - smtp = Net::SMTP.new 'localhost', 25 - smtp.instance_variable_set :@socket, FakeSocket.new - - assert_raise(ArgumentError) do - smtp.mailfrom("foo\r\nbar") - end - - assert_raise(ArgumentError) do - smtp.mailfrom("foo\rbar") - end - - assert_raise(ArgumentError) do - smtp.mailfrom("foo\nbar") - end - - assert_raise(ArgumentError) do - smtp.rcptto("foo\r\nbar") - end - end - - def test_tls_connect - servers = Socket.tcp_server_sockets("localhost", 0) - ctx = OpenSSL::SSL::SSLContext.new - ctx.ca_file = CA_FILE - ctx.key = File.open(SERVER_KEY) { |f| - OpenSSL::PKey::RSA.new(f) - } - ctx.cert = File.open(SERVER_CERT) { |f| - OpenSSL::X509::Certificate.new(f) - } - begin - sock = nil - Thread.start do - s = accept(servers) - sock = OpenSSL::SSL::SSLSocket.new(s, ctx) - sock.sync_close = true - sock.accept - sock.write("220 localhost Service ready\r\n") - sock.gets - sock.write("250 localhost\r\n") - sock.gets - sock.write("221 localhost Service closing transmission channel\r\n") - end - smtp = Net::SMTP.new("localhost", servers[0].local_address.ip_port) - smtp.enable_tls - smtp.open_timeout = 1 - smtp.start do - end - ensure - sock.close if sock - servers.each(&:close) - end - rescue LoadError - # skip (require openssl) - end - - def test_tls_connect_timeout - servers = Socket.tcp_server_sockets("localhost", 0) - begin - sock = nil - Thread.start do - sock = accept(servers) - end - smtp = Net::SMTP.new("localhost", servers[0].local_address.ip_port) - smtp.enable_tls - smtp.open_timeout = 0.1 - assert_raise(Net::OpenTimeout) do - smtp.start do - end - end - rescue LoadError - # skip (require openssl) - ensure - sock.close if sock - servers.each(&:close) - end - end - - def test_eof_error_backtrace - bug13018 = '[ruby-core:78550] [Bug #13018]' - servers = Socket.tcp_server_sockets("localhost", 0) - begin - sock = nil - t = Thread.start do - sock = accept(servers) - sock.close - end - smtp = Net::SMTP.new("localhost", servers[0].local_address.ip_port) - e = assert_raise(EOFError, bug13018) do - smtp.start do - end - end - assert_equal(EOFError, e.class, bug13018) - assert(e.backtrace.grep(%r"\bnet/smtp\.rb:").size > 0, bug13018) - ensure - sock.close if sock - servers.each(&:close) - t.join - end - end - - private - - def accept(servers) - loop do - readable, = IO.select(servers.map(&:to_io)) - readable.each do |r| - sock, = r.accept_nonblock(exception: false) - next if sock == :wait_readable - return sock - end - end - end - end -end diff --git a/ruby/test/net/smtp/test_ssl_socket.rb b/ruby/test/net/smtp/test_ssl_socket.rb deleted file mode 100644 index 342391f15..000000000 --- a/ruby/test/net/smtp/test_ssl_socket.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: true -require 'net/smtp' -require 'test/unit' - -module Net - class TestSSLSocket < Test::Unit::TestCase - class MySMTP < SMTP - attr_accessor :fake_tcp, :fake_ssl - - def initialize(*args) - super(*args) - @open_timeout = nil - end - - def tcp_socket address, port - fake_tcp - end - - def ssl_socket socket, context - fake_ssl - end - end - - require 'stringio' - class SSLSocket < StringIO - attr_accessor :sync_close, :connected, :closed - - def initialize(*args) - @connected = false - @closed = true - super - end - - def connect - self.connected = true - self.closed = false - end - - def close - self.closed = true - end - - def post_connection_check omg - end - end - - def test_ssl_socket_close_on_post_connection_check_fail - tcp_socket = StringIO.new success_response - - ssl_socket = SSLSocket.new.extend Module.new { - def post_connection_check omg - raise OpenSSL::SSL::SSLError, 'hostname was not match with the server certificate' - end - } - - connection = MySMTP.new('localhost', 25) - connection.enable_starttls_auto - connection.fake_tcp = tcp_socket - connection.fake_ssl = ssl_socket - - assert_raise(OpenSSL::SSL::SSLError) do - connection.start - end - assert_equal true, ssl_socket.closed - end - - def test_ssl_socket_open_on_post_connection_check_success - tcp_socket = StringIO.new success_response - - ssl_socket = SSLSocket.new success_response - - connection = MySMTP.new('localhost', 25) - connection.enable_starttls_auto - connection.fake_tcp = tcp_socket - connection.fake_ssl = ssl_socket - - connection.start - assert_equal false, ssl_socket.closed - end - - def success_response - [ - '220 smtp.example.com ESMTP Postfix', - "250-ubuntu-desktop", - "250-PIPELINING", - "250-SIZE 10240000", - "250-VRFY", - "250-ETRN", - "250-STARTTLS", - "250-ENHANCEDSTATUSCODES", - "250-8BITMIME", - "250 DSN", - "220 2.0.0 Ready to start TLS", - ].join("\r\n") + "\r\n" - end - end -end if defined?(OpenSSL) diff --git a/ruby/test/objspace/test_objspace.rb b/ruby/test/objspace/test_objspace.rb index 336b30f75..a1954d56a 100644 --- a/ruby/test/objspace/test_objspace.rb +++ b/ruby/test/objspace/test_objspace.rb @@ -29,12 +29,12 @@ def test_memsize_of end def test_memsize_of_root_shared_string - a = "hello" * 5 + a = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] b = a.dup c = nil ObjectSpace.each_object(String) {|x| break c = x if x == a and x.frozen?} rv_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] - assert_equal([rv_size, rv_size, 26 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)}) + assert_equal([rv_size, rv_size, a.length + 1 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)}) end def test_argf_memsize @@ -107,7 +107,8 @@ def test_count_imemo_objects def test_memsize_of_iseq iseqw = RubyVM::InstructionSequence.compile('def a; a = :b; a; end') - base_obj_size = ObjectSpace.memsize_of(Object.new) + # Use anonymous class as a basic object size because size of Object.new can be increased + base_obj_size = ObjectSpace.memsize_of(Class.new.new) assert_operator(ObjectSpace.memsize_of(iseqw), :>, base_obj_size) end @@ -164,7 +165,17 @@ def test_reachable_objects_size end; end + def test_trace_object_allocations_stop_first + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + require "objspace" + # Make sure stopping before the tracepoints are initialized doesn't raise. See [Bug #17020] + ObjectSpace.trace_object_allocations_stop + end; + end + def test_trace_object_allocations + ObjectSpace.trace_object_allocations_clear # clear object_table to get rid of erroneous detection for c0 Class.name o0 = Object.new ObjectSpace.trace_object_allocations{ @@ -233,6 +244,15 @@ def test_trace_object_allocations_start_stop_clear GC.enable end + def test_trace_object_allocations_gc_stress + EnvUtil.under_gc_stress do + ObjectSpace.trace_object_allocations{ + proc{} + } + end + assert true # success + end + def test_dump_flags info = ObjectSpace.dump("foo".freeze) assert_match(/"wb_protected":true, "old":true/, info) @@ -275,6 +295,11 @@ def assert_dump_object(info, line) JSON.parse(info) if defined?(JSON) end + def test_dump_control_char + assert_include(ObjectSpace.dump("\x0f"), '"value":"\u000f"') + assert_include(ObjectSpace.dump("\C-?"), '"value":"\u007f"') + end + def test_dump_special_consts # [ruby-core:69692] [Bug #11291] assert_equal('null', ObjectSpace.dump(nil)) @@ -284,6 +309,27 @@ def test_dump_special_consts assert_equal('{"type":"SYMBOL", "value":"foo"}', ObjectSpace.dump(:foo)) end + def test_dump_singleton_class + assert_include(ObjectSpace.dump(Object), '"name":"Object"') + assert_include(ObjectSpace.dump(Kernel), '"name":"Kernel"') + assert_include(ObjectSpace.dump(Object.new.singleton_class), '"real_class_name":"Object"') + + singleton = Object.new.singleton_class + singleton_dump = ObjectSpace.dump(singleton) + assert_include(singleton_dump, '"singleton":true') + if defined?(JSON) + assert_equal(Object, singleton.superclass) + superclass_address = JSON.parse(ObjectSpace.dump(Object)).fetch('address') + assert_equal(superclass_address, JSON.parse(singleton_dump).fetch('superclass')) + end + end + + def test_dump_special_floats + assert_match(/"value":"NaN"/, ObjectSpace.dump(Float::NAN)) + assert_match(/"value":"Inf"/, ObjectSpace.dump(Float::INFINITY)) + assert_match(/"value":"\-Inf"/, ObjectSpace.dump(-Float::INFINITY)) + end + def test_dump_dynamic_symbol dump = ObjectSpace.dump(("foobar%x" % rand(0x10000)).to_sym) assert_match(/"type":"SYMBOL"/, dump) @@ -297,8 +343,9 @@ def dump_my_heap_please ObjectSpace.dump_all(output: :stdout) end - dump_my_heap_please + p dump_my_heap_please end; + assert_equal 'nil', output.pop heap = output.find_all { |l| obj = JSON.parse(l) obj['type'] == "IMEMO" && obj['imemo_type'] @@ -314,13 +361,38 @@ def dump_my_heap_please ObjectSpace.dump_all(output: :stdout, full: true) end - dump_my_heap_please + p dump_my_heap_please end; + assert_equal 'nil', output.pop heap = output.find_all { |l| JSON.parse(l)['type'] == "NONE" } assert_operator heap.length, :>, 0 end end + def test_dump_all_single_generation + assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error| + begin; + def dump_my_heap_please + GC.start + ObjectSpace.trace_object_allocations_start + gc_gen = GC.count + puts gc_gen + @obj1 = Object.new + GC.start + @obj2 = Object.new + ObjectSpace.dump_all(output: :stdout, since: gc_gen) + end + + p dump_my_heap_please + end; + assert_equal 'nil', output.pop + since = output.shift.to_i + assert_operator output.size, :>, 0 + generations = output.map { |l| JSON.parse(l)["generation"] }.uniq.sort + assert_equal [since, since + 1], generations + end + end + def test_dump_addresses_match_dump_all_addresses assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error| begin; @@ -330,8 +402,9 @@ def dump_my_heap_please ObjectSpace.dump_all(output: $stdout) end - dump_my_heap_please + p $stdout == dump_my_heap_please end; + assert_equal 'true', output.pop needle = JSON.parse(output.first) addr = needle['address'] found = output.drop(1).find { |l| JSON.parse(l)['address'] == addr } @@ -348,8 +421,9 @@ def dump_my_heap_please ObjectSpace.dump_all(output: $stdout) end - dump_my_heap_please + p $stdout == dump_my_heap_please end; + assert_equal 'true', output.pop needle = JSON.parse(output.first) addr = needle['class'] found = output.drop(1).find { |l| JSON.parse(l)['address'] == addr } @@ -357,6 +431,24 @@ def dump_my_heap_please end end + def test_dump_escapes_method_name + method_name = "foo\"bar" + klass = Class.new do + define_method(method_name) { "TEST STRING" } + end + ObjectSpace.trace_object_allocations_start + + obj = klass.new.send(method_name) + + dump = ObjectSpace.dump(obj) + assert_includes dump, '"method":"foo\"bar"' + + parsed = JSON.parse(dump) + assert_equal "foo\"bar", parsed["method"] + ensure + ObjectSpace.trace_object_allocations_stop + end + def test_dump_reference_addresses_match_dump_all_addresses assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error| begin; @@ -368,8 +460,9 @@ def dump_my_heap_please ObjectSpace.dump_all(output: $stdout) end - dump_my_heap_please + p $stdout == dump_my_heap_please end; + assert_equal 'true', output.pop needle = JSON.parse(output.first) addr = needle['address'] found = output.drop(1).find { |l| (JSON.parse(l)['references'] || []).include? addr } @@ -390,8 +483,9 @@ def dump_my_heap_please ObjectSpace.dump_all(output: :stdout) end - dump_my_heap_please + p dump_my_heap_please end; + assert_equal 'nil', output.pop assert_match(entry, output.grep(/TEST STRING/).join("\n")) end @@ -454,6 +548,20 @@ def test_internal_class_of assert_operator i, :>, 0 end + def test_internal_class_of_on_ast + children = ObjectSpace.reachable_objects_from(RubyVM::AbstractSyntaxTree.parse("kadomatsu")) + children.each {|child| ObjectSpace.internal_class_of(child).itself} # this used to crash + end + + def test_name_error_message + begin + bar + rescue => err + _, m = ObjectSpace.reachable_objects_from(err) + end + assert_equal(m, m.clone) + end + def traverse_super_classes klass while klass klass = ObjectSpace.internal_super_of(klass) @@ -503,4 +611,25 @@ def test_count_symbols assert_equal h[:immortal_symbol], h[:immortal_dynamic_symbol] + h[:immortal_static_symbol], m ;;; end + + def test_anonymous_class_name + assert_not_include ObjectSpace.dump(Class.new), '"name"' + assert_not_include ObjectSpace.dump(Module.new), '"name"' + end + + def test_objspace_trace + assert_in_out_err(%w[-robjspace/trace], "#{<<-"begin;"}\n#{<<-'end;'}") do |out, err| + begin; + a = "foo" + b = "b" + "a" + "r" + c = 42 + p a, b, c + end; + assert_equal ["objspace/trace is enabled"], err + assert_equal 3, out.size + assert_equal '"foo" @ -:2', out[0] + assert_equal '"bar" @ -:3', out[1] + assert_equal '42', out[2] + end + end end diff --git a/ruby/test/open-uri/test_open-uri.rb b/ruby/test/open-uri/test_open-uri.rb index 0c7d77c30..72ebcdb0d 100644 --- a/ruby/test/open-uri/test_open-uri.rb +++ b/ruby/test/open-uri/test_open-uri.rb @@ -68,18 +68,6 @@ def teardown @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] } end - def test_deprecated_kernel_open - with_http {|srv, dr, url| - srv.mount_proc("/foo200", lambda { |req, res| res.body = "foo200" } ) - assert_warning(/calling URI.open via Kernel#open is deprecated, call URI.open directly/) { - open("#{url}/foo200") {|f| - assert_equal("200", f.status[0]) - assert_equal("foo200", f.read) - } - } - } - end - def test_200_uri_open with_http {|srv, dr, url| srv.mount_proc("/urifoo200", lambda { |req, res| res.body = "urifoo200" } ) @@ -593,7 +581,7 @@ def test_progress_chunked ) {|f| assert_equal(1, length.length) assert_equal(nil, length[0]) - assert(progress.length>1,"maybe test is worng") + assert(progress.length>1,"maybe test is wrong") assert(progress.sort == progress,"monotone increasing expected but was\n#{progress.inspect}") assert_equal(content.length, progress[-1]) assert_equal(content, f.read) @@ -715,143 +703,149 @@ def test_multiple_cookies # 192.0.2.0/24 is TEST-NET. [RFC3330] - def test_ftp_invalid_request - assert_raise(ArgumentError) { URI("ftp://127.0.0.1/").read } - assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db").read } - assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab").read } - assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db/f").read } - assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab/f").read } - assert_nothing_raised(URI::InvalidComponentError) { URI("ftp://127.0.0.1/d/f;type=x") } - end + begin + require 'net/ftp' - def test_ftp - TCPServer.open("127.0.0.1", 0) {|serv| - _, port, _, host = serv.addr - th = Thread.new { - s = serv.accept + def test_ftp_invalid_request + assert_raise(ArgumentError) { URI("ftp://127.0.0.1/").read } + assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db").read } + assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab").read } + assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db/f").read } + assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab/f").read } + assert_nothing_raised(URI::InvalidComponentError) { URI("ftp://127.0.0.1/d/f;type=x") } + end + + def test_ftp + TCPServer.open("127.0.0.1", 0) {|serv| + _, port, _, host = serv.addr + th = Thread.new { + s = serv.accept + begin + s.print "220 Test FTP Server\r\n" + assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" + assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" + assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" + assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n" + assert_equal("PASV\r\n", s.gets) + TCPServer.open("127.0.0.1", 0) {|data_serv| + _, data_serv_port, _, _ = data_serv.addr + hi = data_serv_port >> 8 + lo = data_serv_port & 0xff + s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n" + assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" + data_sock = data_serv.accept + begin + data_sock << "content" + ensure + data_sock.close + end + s.print "226 transfer complete\r\n" + assert_nil(s.gets) + } + ensure + s.close if s + end + } begin - s.print "220 Test FTP Server\r\n" - assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" - assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" - assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" - assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n" - assert_equal("PASV\r\n", s.gets) - TCPServer.open("127.0.0.1", 0) {|data_serv| - _, data_serv_port, _, _ = data_serv.addr - hi = data_serv_port >> 8 - lo = data_serv_port & 0xff - s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n" - assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" - data_sock = data_serv.accept - begin - data_sock << "content" - ensure - data_sock.close - end - s.print "226 transfer complete\r\n" - assert_nil(s.gets) - } + content = URI("ftp://#{host}:#{port}/foo/bar").read + assert_equal("content", content) ensure - s.close if s + Thread.kill(th) + th.join end } - begin - content = URI("ftp://#{host}:#{port}/foo/bar").read - assert_equal("content", content) - ensure - Thread.kill(th) - th.join - end - } - end + end - def test_ftp_active - TCPServer.open("127.0.0.1", 0) {|serv| - _, port, _, host = serv.addr - th = Thread.new { - s = serv.accept + def test_ftp_active + TCPServer.open("127.0.0.1", 0) {|serv| + _, port, _, host = serv.addr + th = Thread.new { + s = serv.accept + begin + content = "content" + s.print "220 Test FTP Server\r\n" + assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" + assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" + assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" + assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n" + assert(m = /\APORT 127,0,0,1,(\d+),(\d+)\r\n\z/.match(s.gets)) + active_port = m[1].to_i << 8 | m[2].to_i + TCPSocket.open("127.0.0.1", active_port) {|data_sock| + s.print "200 data connection opened\r\n" + assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" + begin + data_sock << content + ensure + data_sock.close + end + s.print "226 transfer complete\r\n" + assert_nil(s.gets) + } + ensure + s.close if s + end + } begin - content = "content" - s.print "220 Test FTP Server\r\n" - assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" - assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" - assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" - assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n" - assert(m = /\APORT 127,0,0,1,(\d+),(\d+)\r\n\z/.match(s.gets)) - active_port = m[1].to_i << 8 | m[2].to_i - TCPSocket.open("127.0.0.1", active_port) {|data_sock| - s.print "200 data connection opened\r\n" - assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" - begin - data_sock << content - ensure - data_sock.close - end - s.print "226 transfer complete\r\n" - assert_nil(s.gets) - } + content = URI("ftp://#{host}:#{port}/foo/bar").read(:ftp_active_mode=>true) + assert_equal("content", content) ensure - s.close if s + Thread.kill(th) + th.join end } - begin - content = URI("ftp://#{host}:#{port}/foo/bar").read(:ftp_active_mode=>true) - assert_equal("content", content) - ensure - Thread.kill(th) - th.join - end - } - end + end - def test_ftp_ascii - TCPServer.open("127.0.0.1", 0) {|serv| - _, port, _, host = serv.addr - th = Thread.new { - s = serv.accept + def test_ftp_ascii + TCPServer.open("127.0.0.1", 0) {|serv| + _, port, _, host = serv.addr + th = Thread.new { + s = serv.accept + begin + content = "content" + s.print "220 Test FTP Server\r\n" + assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" + assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" + assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" + assert_equal("CWD /foo\r\n", s.gets); s.print "250 CWD successful\r\n" + assert_equal("TYPE A\r\n", s.gets); s.print "200 type set to A\r\n" + assert_equal("SIZE bar\r\n", s.gets); s.print "213 #{content.bytesize}\r\n" + assert_equal("PASV\r\n", s.gets) + TCPServer.open("127.0.0.1", 0) {|data_serv| + _, data_serv_port, _, _ = data_serv.addr + hi = data_serv_port >> 8 + lo = data_serv_port & 0xff + s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n" + assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" + data_sock = data_serv.accept + begin + data_sock << content + ensure + data_sock.close + end + s.print "226 transfer complete\r\n" + assert_nil(s.gets) + } + ensure + s.close if s + end + } begin - content = "content" - s.print "220 Test FTP Server\r\n" - assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n" - assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n" - assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n" - assert_equal("CWD /foo\r\n", s.gets); s.print "250 CWD successful\r\n" - assert_equal("TYPE A\r\n", s.gets); s.print "200 type set to A\r\n" - assert_equal("SIZE bar\r\n", s.gets); s.print "213 #{content.bytesize}\r\n" - assert_equal("PASV\r\n", s.gets) - TCPServer.open("127.0.0.1", 0) {|data_serv| - _, data_serv_port, _, _ = data_serv.addr - hi = data_serv_port >> 8 - lo = data_serv_port & 0xff - s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n" - assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n" - data_sock = data_serv.accept - begin - data_sock << content - ensure - data_sock.close - end - s.print "226 transfer complete\r\n" - assert_nil(s.gets) - } + length = [] + progress = [] + content = URI("ftp://#{host}:#{port}/%2Ffoo/b%61r;type=a").read( + :content_length_proc => lambda {|n| length << n }, + :progress_proc => lambda {|n| progress << n }) + assert_equal("content", content) + assert_equal([7], length) + assert_equal(7, progress.inject(&:+)) ensure - s.close if s + Thread.kill(th) + th.join end } - begin - length = [] - progress = [] - content = URI("ftp://#{host}:#{port}/%2Ffoo/b%61r;type=a").read( - :content_length_proc => lambda {|n| length << n }, - :progress_proc => lambda {|n| progress << n }) - assert_equal("content", content) - assert_equal([7], length) - assert_equal(7, progress.inject(&:+)) - ensure - Thread.kill(th) - th.join - end - } + end + rescue LoadError + # net-ftp is the bundled gems at Ruby 3.1 end def test_ftp_over_http_proxy diff --git a/ruby/test/openssl/fixtures/pkey/certificate.der b/ruby/test/openssl/fixtures/pkey/certificate.der new file mode 100644 index 000000000..7d44df841 Binary files /dev/null and b/ruby/test/openssl/fixtures/pkey/certificate.der differ diff --git a/ruby/test/openssl/fixtures/pkey/empty.der b/ruby/test/openssl/fixtures/pkey/empty.der new file mode 100644 index 000000000..e69de29bb diff --git a/ruby/test/openssl/fixtures/pkey/empty.pem b/ruby/test/openssl/fixtures/pkey/empty.pem new file mode 100644 index 000000000..e69de29bb diff --git a/ruby/test/openssl/fixtures/pkey/fullchain.pem b/ruby/test/openssl/fixtures/pkey/fullchain.pem new file mode 100644 index 000000000..624785d32 --- /dev/null +++ b/ruby/test/openssl/fixtures/pkey/fullchain.pem @@ -0,0 +1,56 @@ +-----BEGIN CERTIFICATE----- +MIIFKTCCBBGgAwIBAgISBFspP+tJfRaC6xprreB4Rp9KMA0GCSqGSIb3DQEBCwUA +MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD +EwJSMzAeFw0yMTA0MTcwMjQzMTlaFw0yMTA3MTYwMjQzMTlaMBwxGjAYBgNVBAMT +EXd3dy5jb2Rlb3Rha3UuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAx6h5vNPfkkrtYWxn1PWDDLRAwrGmZbkYPttjHBRSwTcd7rsIX4PcSzw9fWxm +K4vIkAYoKAElIvsSE3xRUjyzMrACfdhK5J8rG25fq94iVyoYaNBQV0WMJkO6X47s +hGeIKkK91ohR5b2tMw3/z9zELP0TVo2TPG7rYsBZm34myldqDA8yVEBEOa+Qdpda +9xewPhkkdpAU55qgWTrD21m7vGq9WpsBz4wNKnwVsaugtkRH82VPIfaL4ZI9kox6 +QoPWe/tHUBdlDkuT7ud77eLAWnC/5Clg28/9GU/Z8Nj8SrrKuXL6WUXmxxaAhWUR +Qx4VblZeuIpwd0nHyP0hz4CWKQIDAQABo4ICTTCCAkkwDgYDVR0PAQH/BAQDAgWg +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0G +A1UdDgQWBBTKiSGZuLFSIG2JPbFSZa9TxMu5WTAfBgNVHSMEGDAWgBQULrMXt1hW +y65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUHMAGGFWh0dHA6 +Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3IzLmkubGVuY3Iu +b3JnLzAcBgNVHREEFTATghF3d3cuY29kZW90YWt1LmNvbTBMBgNVHSAERTBDMAgG +BmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3Bz +LmxldHNlbmNyeXB0Lm9yZzCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB3AJQgvB6O +1Y1siHMfgosiLA3R2k1ebE+UPWHbTi9YTaLCAAABeN3s/lgAAAQDAEgwRgIhAKFY +Q+vBe3zyeBazxp8kVN7oLvcQ6Y9PPz199tVhYnEbAiEAhU/xdbQaY/6b93h+7NTF +sPG7X4lq/3UoNgoXcAVGZgoAdgD2XJQv0XcwIhRUGAgwlFaO400TGTO/3wwvIAvM +TvFk4wAAAXjd7P5OAAAEAwBHMEUCIQDWd79+jWaGuf3acm5/yV95jL2KvzeGFfdU +HZlKIeWFmAIgDSZ6ug7AyhYNKjzFV4ZSICln+L4yI92EpOa+8gDG6/0wDQYJKoZI +hvcNAQELBQADggEBAHIhMYm06lLFmJL+cfIg5fFEmFNdHmmZn88Hypv4/MtmqTKv +5asF/z3TvhW4hX2+TY+NdcqGT7cZFo/ZF/tS6oBXPgmBYM1dEfp2FAdnGNOySC5Y +7RC4Uk9TUpP2g101YBmj6dQKQluAwIQk+gO4MSlHE0J0U/lMpjvrLWcuHbV4/xWJ +IdM+iPq8GeYt5epYmNc7XeRIgv7V3RxDQdBv2OVM5mtPVerdiO0ISrdbe5mvz2+Z +rhSg+EJNHlmMwcq5HqtMwS8M8Ax+vLmWCOkPWXhyV8wQaQcFjZJfpIGUvCnMTqsh +kSIYXq2CbSDUUFRFssNN6EdVms0KnmW3BUu0xAk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTIwMTAwNzE5MjE0MFoXDTIxMDkyOTE5MjE0MFow +MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT +AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs +jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp +Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB +U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7 +gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel +/xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R +oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E +BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p +ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE +p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE +AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu +Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0 +LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf +r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B +AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH +ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8 +S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL +qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p +O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw +UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg== +-----END CERTIFICATE----- diff --git a/ruby/test/openssl/fixtures/pkey/garbage.txt b/ruby/test/openssl/fixtures/pkey/garbage.txt new file mode 100644 index 000000000..557db03de --- /dev/null +++ b/ruby/test/openssl/fixtures/pkey/garbage.txt @@ -0,0 +1 @@ +Hello World diff --git a/ruby/test/openssl/test_asn1.rb b/ruby/test/openssl/test_asn1.rb index cc1130180..0fd797158 100644 --- a/ruby/test/openssl/test_asn1.rb +++ b/ruby/test/openssl/test_asn1.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -14,7 +14,7 @@ def test_decode_x509_certificate ["keyUsage","keyCertSign, cRLSign",true], ["subjectKeyIdentifier","hash",false], ] - dgst = OpenSSL::Digest::SHA1.new + dgst = OpenSSL::Digest.new('SHA1') cert = OpenSSL::TestUtils.issue_cert( subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600) @@ -167,10 +167,10 @@ def test_decode_x509_certificate assert_equal(OpenSSL::ASN1::OctetString, ext.value[2].class) extv = OpenSSL::ASN1.decode(ext.value[2].value) assert_equal(OpenSSL::ASN1::BitString, extv.class) - str = "\000"; str[0] = 0b00000110.chr + str = +"\000"; str[0] = 0b00000110.chr assert_equal(str, extv.value) - ext = extensions.value[0].value[2] # subjetKeyIdentifier + ext = extensions.value[0].value[2] # subjectKeyIdentifier assert_equal(OpenSSL::ASN1::Sequence, ext.class) assert_equal(2, ext.value.size) assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class) @@ -178,7 +178,7 @@ def test_decode_x509_certificate assert_equal(OpenSSL::ASN1::OctetString, ext.value[1].class) extv = OpenSSL::ASN1.decode(ext.value[1].value) assert_equal(OpenSSL::ASN1::OctetString, extv.class) - sha1 = OpenSSL::Digest::SHA1.new + sha1 = OpenSSL::Digest.new('SHA1') sha1.update(pkey.value[1].value) assert_equal(sha1.digest, extv.value) @@ -189,7 +189,7 @@ def test_decode_x509_certificate assert_equal(OpenSSL::ASN1::Null, pkey.value[0].value[1].class) assert_equal(OpenSSL::ASN1::BitString, sig_val.class) - cululated_sig = key.sign(OpenSSL::Digest::SHA1.new, tbs_cert.to_der) + cululated_sig = key.sign(OpenSSL::Digest.new('SHA1'), tbs_cert.to_der) assert_equal(cululated_sig, sig_val.value) end @@ -265,10 +265,9 @@ def test_bitstring assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1.decode(B(%w{ 03 00 })) } - # OpenSSL < OpenSSL_1_0_1k and LibreSSL ignore the error - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 03 03 08 FF 00 })) - # } + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 03 03 08 FF 00 })) + } # OpenSSL does not seem to prohibit this, though X.690 8.6.2.3 (15/08) does # assert_raise(OpenSSL::ASN1::ASN1Error) { # OpenSSL::ASN1.decode(B(%w{ 03 01 04 })) @@ -332,6 +331,32 @@ def test_object_identifier pend "OBJ_obj2txt() not working (LibreSSL?)" if $!.message =~ /OBJ_obj2txt/ raise end + + aki = [ + OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier"), + OpenSSL::ASN1::ObjectId.new("X509v3 Authority Key Identifier"), + OpenSSL::ASN1::ObjectId.new("2.5.29.35") + ] + + ski = [ + OpenSSL::ASN1::ObjectId.new("subjectKeyIdentifier"), + OpenSSL::ASN1::ObjectId.new("X509v3 Subject Key Identifier"), + OpenSSL::ASN1::ObjectId.new("2.5.29.14") + ] + + aki.each do |a| + aki.each do |b| + assert a == b + end + + ski.each do |b| + refute a == b + end + end + + assert_raise(TypeError) { + OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier") == nil + } end def test_sequence @@ -635,10 +660,10 @@ def test_constructive_each assert_equal data, seq.entries end - def test_gc_stress - skip "very time consuming test" - assert_ruby_status(['--disable-gems', '-eGC.stress=true', '-erequire "openssl.so"']) - end + # Very time consuming test. + # def test_gc_stress + # assert_ruby_status(['--disable-gems', '-eGC.stress=true', '-erequire "openssl.so"']) + # end private diff --git a/ruby/test/openssl/test_bn.rb b/ruby/test/openssl/test_bn.rb index 0b5cd8424..346602dad 100644 --- a/ruby/test/openssl/test_bn.rb +++ b/ruby/test/openssl/test_bn.rb @@ -1,7 +1,6 @@ # coding: us-ascii -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' -require "prime" if defined?(OpenSSL) @@ -15,6 +14,10 @@ def setup end def test_new + assert_raise(ArgumentError) { OpenSSL::BN.new } + assert_raise(ArgumentError) { OpenSSL::BN.new(nil) } + assert_raise(ArgumentError) { OpenSSL::BN.new(nil, 2) } + assert_equal(@e1, OpenSSL::BN.new("999")) assert_equal(@e1, OpenSSL::BN.new("999", 10)) assert_equal(@e1, OpenSSL::BN.new("\x03\xE7", 2)) @@ -127,6 +130,27 @@ def test_unary_plus_minus assert_equal(-999, +@e2) assert_equal(-999, -@e1) assert_equal(+999, -@e2) + + # These methods create new BN instances due to BN mutability + # Ensure that the instance isn't the same + e1_plus = +@e1 + e1_minus = -@e1 + assert_equal(false, @e1.equal?(e1_plus)) + assert_equal(true, @e1 == e1_plus) + assert_equal(false, @e1.equal?(e1_minus)) + end + + def test_abs + assert_equal(@e1, @e2.abs) + assert_equal(@e3, @e4.abs) + assert_not_equal(@e2, @e2.abs) + assert_not_equal(@e4, @e4.abs) + assert_equal(false, @e2.abs.negative?) + assert_equal(false, @e4.abs.negative?) + assert_equal(true, (-@e1.abs).negative?) + assert_equal(true, (-@e2.abs).negative?) + assert_equal(true, (-@e3.abs).negative?) + assert_equal(true, (-@e4.abs).negative?) end def test_mod @@ -224,25 +248,35 @@ def test_random r5 = OpenSSL::BN.rand_range(256) assert_include(0..255, r5) } + + # Aliases + assert_include(128..255, OpenSSL::BN.pseudo_rand(8)) + assert_include(0..255, OpenSSL::BN.pseudo_rand_range(256)) end - def test_prime - p1 = OpenSSL::BN.generate_prime(32) - assert_include(0...2**32, p1) - assert_equal(true, Prime.prime?(p1.to_i)) - p2 = OpenSSL::BN.generate_prime(32, true) - assert_equal(true, Prime.prime?((p2.to_i - 1) / 2)) - p3 = OpenSSL::BN.generate_prime(32, false, 4) - assert_equal(1, p3 % 4) - p4 = OpenSSL::BN.generate_prime(32, false, 4, 3) - assert_equal(3, p4 % 4) - - assert_equal(true, p1.prime?) - assert_equal(true, p2.prime?) - assert_equal(true, p3.prime?) - assert_equal(true, p4.prime?) - assert_equal(true, @e3.prime?) - assert_equal(true, @e3.prime_fasttest?) + begin + require "prime" + + def test_prime + p1 = OpenSSL::BN.generate_prime(32) + assert_include(0...2**32, p1) + assert_equal(true, Prime.prime?(p1.to_i)) + p2 = OpenSSL::BN.generate_prime(32, true) + assert_equal(true, Prime.prime?((p2.to_i - 1) / 2)) + p3 = OpenSSL::BN.generate_prime(32, false, 4) + assert_equal(1, p3 % 4) + p4 = OpenSSL::BN.generate_prime(32, false, 4, 3) + assert_equal(3, p4 % 4) + + assert_equal(true, p1.prime?) + assert_equal(true, p2.prime?) + assert_equal(true, p3.prime?) + assert_equal(true, p4.prime?) + assert_equal(true, @e3.prime?) + assert_equal(true, @e3.prime_fasttest?) + end + rescue LoadError + # prime is the bundled gems at Ruby 3.1 end def test_num_bits_bytes @@ -273,9 +307,57 @@ def test_comparison assert_instance_of(String, @e1.hash.to_s) end - def test_type_error + def test_argument_error bug15760 = '[ruby-core:92231] [Bug #15760]' - assert_raise(TypeError, bug15760) { OpenSSL::BN.new(nil, 2) } + assert_raise(ArgumentError, bug15760) { OpenSSL::BN.new(nil, 2) } + end + + def test_get_flags_and_set_flags + e = OpenSSL::BN.new(999) + + assert_equal(0, e.get_flags(OpenSSL::BN::CONSTTIME)) + + e.set_flags(OpenSSL::BN::CONSTTIME) + assert_equal(OpenSSL::BN::CONSTTIME, e.get_flags(OpenSSL::BN::CONSTTIME)) + + b = OpenSSL::BN.new(2) + m = OpenSSL::BN.new(99) + assert_equal("17", b.mod_exp(e, m).to_s) + + # mod_exp fails when m is even and any argument has CONSTTIME flag + m = OpenSSL::BN.new(98) + assert_raise(OpenSSL::BNError) do + b.mod_exp(e, m) + end + + # It looks like flags cannot be removed once enabled + e.set_flags(0) + assert_equal(4, e.get_flags(OpenSSL::BN::CONSTTIME)) + end + + if respond_to?(:ractor) + ractor + def test_ractor + assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.take) + assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.take) + assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.take) + assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.take) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) + assert_equal(false, Ractor.new { 1.to_bn.zero? }.take) + assert_equal(true, Ractor.new { 1.to_bn.one? }.take) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) + assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.take) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) + assert_equal(true, Ractor.new { 0.to_bn.zero? }.take) + assert_equal(true, Ractor.new { 1.to_bn.one? }.take ) + assert_equal(false,Ractor.new { 2.to_bn.odd? }.take) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) + assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.take) + assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.take) + assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.take) + end end end diff --git a/ruby/test/openssl/test_buffering.rb b/ruby/test/openssl/test_buffering.rb index c85a6f020..7575c5b4f 100644 --- a/ruby/test/openssl/test_buffering.rb +++ b/ruby/test/openssl/test_buffering.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -10,7 +10,7 @@ class IO attr_accessor :sync def initialize - @io = "" + @io = Buffer.new def @io.sync true end @@ -41,6 +41,13 @@ def setup @io = IO.new end + def test_encoding + @io.write '😊' + @io.flush + + assert_equal @io.string.encoding, Encoding::BINARY + end + def test_flush @io.write 'a' diff --git a/ruby/test/openssl/test_cipher.rb b/ruby/test/openssl/test_cipher.rb index d83fa4ec3..b5fdf0b3d 100644 --- a/ruby/test/openssl/test_cipher.rb +++ b/ruby/test/openssl/test_cipher.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -36,8 +36,8 @@ def test_pkcs5_keyivgen cipher.pkcs5_keyivgen(pass, salt, num, "MD5") s1 = cipher.update(pt) << cipher.final - d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) } - d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) } + d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) } + d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) } key = (d1 + d2)[0, 24] iv = (d1 + d2)[24, 8] cipher = new_encryptor("DES-EDE3-CBC", key: key, iv: iv) @@ -135,25 +135,22 @@ def test_ctr_if_exists end def test_ciphers - OpenSSL::Cipher.ciphers.each{|name| - next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name - begin - assert_kind_of(OpenSSL::Cipher, OpenSSL::Cipher.new(name)) - rescue OpenSSL::Cipher::CipherError => e - raise unless /wrap/ =~ name and /wrap mode not allowed/ =~ e.message - end - } + ciphers = OpenSSL::Cipher.ciphers + assert_kind_of Array, ciphers + assert_include ciphers, "aes-128-cbc" + assert_include ciphers, "aes128" # alias of aes-128-cbc + assert_include ciphers, "aes-128-gcm" end def test_AES pt = File.read(__FILE__) - %w(ECB CBC CFB OFB).each{|mode| - c1 = OpenSSL::Cipher::AES256.new(mode) + %w(ecb cbc cfb ofb).each{|mode| + c1 = OpenSSL::Cipher.new("aes-256-#{mode}") c1.encrypt c1.pkcs5_keyivgen("passwd") ct = c1.update(pt) + c1.final - c2 = OpenSSL::Cipher::AES256.new(mode) + c2 = OpenSSL::Cipher.new("aes-256-#{mode}") c2.decrypt c2.pkcs5_keyivgen("passwd") assert_equal(pt, c2.update(ct) + c2.final) @@ -163,7 +160,7 @@ def test_AES def test_update_raise_if_key_not_set assert_raise(OpenSSL::Cipher::CipherError) do # it caused OpenSSL SEGV by uninitialized key [Bug #2768] - OpenSSL::Cipher::AES128.new("ECB").update "." * 17 + OpenSSL::Cipher.new("aes-128-ecb").update "." * 17 end end @@ -174,6 +171,48 @@ def test_authenticated assert_not_predicate(cipher, :authenticated?) end + def test_aes_ccm + # RFC 3610 Section 8, Test Case 1 + key = ["c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"].pack("H*") + iv = ["00000003020100a0a1a2a3a4a5"].pack("H*") + aad = ["0001020304050607"].pack("H*") + pt = ["08090a0b0c0d0e0f101112131415161718191a1b1c1d1e"].pack("H*") + ct = ["588c979a61c663d2f066d0c2c0f989806d5f6b61dac384"].pack("H*") + tag = ["17e8d12cfdf926e0"].pack("H*") + + kwargs = {auth_tag_len: 8, iv_len: 13, key: key, iv: iv} + cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad) + assert_equal ct, cipher.update(pt) << cipher.final + assert_equal tag, cipher.auth_tag + cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad) + assert_equal pt, cipher.update(ct) << cipher.final + + # truncated tag is accepted + cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad) + assert_equal ct, cipher.update(pt) << cipher.final + assert_equal tag[0, 8], cipher.auth_tag(8) + cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag[0, 8], auth_data: aad) + assert_equal pt, cipher.update(ct) << cipher.final + + # wrong tag is rejected + tag2 = tag.dup + tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff) + cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag2, auth_data: aad) + assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) } + + # wrong aad is rejected + aad2 = aad[0..-2] << aad[-1].succ + cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad2) + assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) } + + # wrong ciphertext is rejected + ct2 = ct[0..-2] << ct[-1].succ + cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct2.length, auth_tag: tag, auth_data: aad) + assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) } + end if has_cipher?("aes-128-ccm") && + OpenSSL::Cipher.new("aes-128-ccm").authenticated? && + OpenSSL::OPENSSL_VERSION_NUMBER >= 0x1010103f # version >= 1.1.1c + def test_aes_gcm # GCM spec Appendix B Test Case 4 key = ["feffe9928665731c6d6a8f9467308308"].pack("H*") @@ -305,6 +344,21 @@ def test_non_aead_cipher_set_auth_data } end + def test_crypt_after_key + key = ["2b7e151628aed2a6abf7158809cf4f3c"].pack("H*") + %w'ecb cbc cfb ctr gcm'.each do |c| + cipher = OpenSSL::Cipher.new("aes-128-#{c}") + cipher.key = key + cipher.encrypt + assert_raise(OpenSSL::Cipher::CipherError) { cipher.update("") } + + cipher = OpenSSL::Cipher.new("aes-128-#{c}") + cipher.key = key + cipher.decrypt + assert_raise(OpenSSL::Cipher::CipherError) { cipher.update("") } + end + end + private def new_encryptor(algo, **kwargs) diff --git a/ruby/test/openssl/test_config.rb b/ruby/test/openssl/test_config.rb index 3606c67d6..24a215a48 100644 --- a/ruby/test/openssl/test_config.rb +++ b/ruby/test/openssl/test_config.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -120,6 +120,54 @@ def test_s_parse_format assert_equal("error in line 7: missing close square bracket", excn.message) end + def test_s_parse_include + if !openssl?(1, 1, 1, 2) + # OpenSSL < 1.1.1 parses .include directive as a normal assignment + pend ".include directive is not supported" + end + + in_tmpdir("ossl-config-include-test") do |dir| + Dir.mkdir("child") + File.write("child/a.conf", <<~__EOC__) + [default] + file-a = a.conf + [sec-a] + a = 123 + __EOC__ + File.write("child/b.cnf", <<~__EOC__) + [default] + file-b = b.cnf + [sec-b] + b = 123 + __EOC__ + File.write("include-child.conf", <<~__EOC__) + key_outside_section = value_a + .include child + __EOC__ + + include_file = <<~__EOC__ + [default] + file-main = unnamed + [sec-main] + main = 123 + .include = include-child.conf + __EOC__ + + # Include a file by relative path + c1 = OpenSSL::Config.parse(include_file) + assert_equal(["default", "sec-a", "sec-b", "sec-main"], c1.sections.sort) + assert_equal(["file-a", "file-b", "file-main"], c1["default"].keys.sort) + assert_equal({"a" => "123"}, c1["sec-a"]) + assert_equal({"b" => "123"}, c1["sec-b"]) + assert_equal({"main" => "123", "key_outside_section" => "value_a"}, c1["sec-main"]) + + # Relative paths are from the working directory + # Inclusion fails, but the error is ignored silently + c2 = Dir.chdir("child") { OpenSSL::Config.parse(include_file) } + assert_equal(["default", "sec-main"], c2.sections.sort) + end + end + def test_s_load # alias of new c = OpenSSL::Config.load @@ -134,6 +182,12 @@ def test_s_load } end + def test_s_parse_config + ret = OpenSSL::Config.parse_config(@it.to_s) + assert_equal(@it.sections.sort, ret.keys.sort) + assert_equal(@it["default"], ret["default"]) + end + def test_initialize c = OpenSSL::Config.new assert_equal("", c.to_s) @@ -166,33 +220,14 @@ def test_get_value end def test_get_value_ENV + # LibreSSL removed support for NCONF_get_string(conf, "ENV", str) + return if libressl? + key = ENV.keys.first assert_not_nil(key) # make sure we have at least one ENV var. assert_equal(ENV[key], @it.get_value('ENV', key)) end - def test_value - # suppress deprecation warnings - EnvUtil.suppress_warning do - assert_equal('CA_default', @it.value('ca', 'default_ca')) - assert_equal(nil, @it.value('ca', 'no such key')) - assert_equal(nil, @it.value('no such section', 'no such key')) - assert_equal('.', @it.value('', 'HOME')) - assert_equal('.', @it.value(nil, 'HOME')) - assert_equal('.', @it.value('HOME')) - # fallback to 'default' ugly... - assert_equal('.', @it.value('unknown', 'HOME')) - end - end - - def test_value_ENV - EnvUtil.suppress_warning do - key = ENV.keys.first - assert_not_nil(key) # make sure we have at least one ENV var. - assert_equal(ENV[key], @it.value('ENV', key)) - end - end - def test_aref assert_equal({'HOME' => '.'}, @it['default']) assert_equal({'dir' => './demoCA', 'certs' => './certs'}, @it['CA_default']) @@ -200,56 +235,19 @@ def test_aref assert_equal({}, @it['']) end - def test_section - EnvUtil.suppress_warning do - assert_equal({'HOME' => '.'}, @it.section('default')) - assert_equal({'dir' => './demoCA', 'certs' => './certs'}, @it.section('CA_default')) - assert_equal({}, @it.section('no_such_section')) - assert_equal({}, @it.section('')) - end - end - def test_sections assert_equal(['CA_default', 'ca', 'default'], @it.sections.sort) - @it['new_section'] = {'foo' => 'bar'} - assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) - @it['new_section'] = {} - assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) - end - - def test_add_value - c = OpenSSL::Config.new - assert_equal("", c.to_s) - # add key - c.add_value('default', 'foo', 'bar') - assert_equal("[ default ]\nfoo=bar\n\n", c.to_s) - # add another key - c.add_value('default', 'baz', 'qux') - assert_equal('bar', c['default']['foo']) - assert_equal('qux', c['default']['baz']) - # update the value - c.add_value('default', 'baz', 'quxxx') - assert_equal('bar', c['default']['foo']) - assert_equal('quxxx', c['default']['baz']) - # add section and key - c.add_value('section', 'foo', 'bar') - assert_equal('bar', c['default']['foo']) - assert_equal('quxxx', c['default']['baz']) - assert_equal('bar', c['section']['foo']) - end - - def test_aset - @it['foo'] = {'bar' => 'baz'} - assert_equal({'bar' => 'baz'}, @it['foo']) - @it['foo'] = {'bar' => 'qux', 'baz' => 'quxx'} - assert_equal({'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) - - # OpenSSL::Config is add only for now. - @it['foo'] = {'foo' => 'foo'} - assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) - # you cannot override or remove any section and key. - @it['foo'] = {} - assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) + Tempfile.create("openssl.cnf") { |f| + f.write File.read(@tmpfile.path) + f.puts "[ new_section ]" + f.puts "foo = bar" + f.puts "[ empty_section ]" + f.close + + c = OpenSSL::Config.new(f.path) + assert_equal(['CA_default', 'ca', 'default', 'empty_section', 'new_section'], + c.sections.sort) + } end def test_each @@ -271,33 +269,23 @@ def test_inspect assert_match(/#/, @it.inspect) end - def test_freeze - c = OpenSSL::Config.new - c['foo'] = [['key', 'value']] - c.freeze - - bug = '[ruby-core:18377]' - # RuntimeError for 1.9, TypeError for 1.8 - e = assert_raise(TypeError, bug) do - c['foo'] = [['key', 'wrong']] - end - assert_match(/can't modify/, e.message, bug) - end - def test_dup - assert(!@it.sections.empty?) - c = @it.dup - assert_equal(@it.sections.sort, c.sections.sort) - @it['newsection'] = {'a' => 'b'} - assert_not_equal(@it.sections.sort, c.sections.sort) + assert_equal(['CA_default', 'ca', 'default'], @it.sections.sort) + c1 = @it.dup + assert_equal(@it.sections.sort, c1.sections.sort) + c2 = @it.clone + assert_equal(@it.sections.sort, c2.sections.sort) end - def test_clone - assert(!@it.sections.empty?) - c = @it.clone - assert_equal(@it.sections.sort, c.sections.sort) - @it['newsection'] = {'a' => 'b'} - assert_not_equal(@it.sections.sort, c.sections.sort) + private + + def in_tmpdir(*args) + Dir.mktmpdir(*args) do |dir| + dir = File.realpath(dir) + Dir.chdir(dir) do + yield dir + end + end end end diff --git a/ruby/test/openssl/test_digest.rb b/ruby/test/openssl/test_digest.rb index 2cb878b6f..84c128c12 100644 --- a/ruby/test/openssl/test_digest.rb +++ b/ruby/test/openssl/test_digest.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -21,8 +21,8 @@ def test_digest @d1 << data assert_equal(bin, @d1.digest) assert_equal(hex, @d1.hexdigest) - assert_equal(bin, OpenSSL::Digest::MD5.digest(data)) - assert_equal(hex, OpenSSL::Digest::MD5.hexdigest(data)) + assert_equal(bin, OpenSSL::Digest.digest('MD5', data)) + assert_equal(hex, OpenSSL::Digest.hexdigest('MD5', data)) end def test_eql @@ -54,13 +54,9 @@ def test_reset end def test_digest_constants - algs = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512) - if !libressl? && !openssl?(1, 1, 0) - algs += %w(DSS1 SHA) - end - algs.each do |alg| - assert_not_nil(OpenSSL::Digest.new(alg)) - klass = OpenSSL::Digest.const_get(alg) + %w{MD5 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name| + assert_not_nil(OpenSSL::Digest.new(name)) + klass = OpenSSL::Digest.const_get(name.tr('-', '_')) assert_not_nil(klass.new) end end @@ -80,15 +76,39 @@ def test_sha2 sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31" sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75" - assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a")) - assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a")) - assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a")) - assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a")) + assert_equal(sha224_a, OpenSSL::Digest.hexdigest('SHA224', "a")) + assert_equal(sha256_a, OpenSSL::Digest.hexdigest('SHA256', "a")) + assert_equal(sha384_a, OpenSSL::Digest.hexdigest('SHA384', "a")) + assert_equal(sha512_a, OpenSSL::Digest.hexdigest('SHA512', "a")) + + assert_equal(sha224_a, encode16(OpenSSL::Digest.digest('SHA224', "a"))) + assert_equal(sha256_a, encode16(OpenSSL::Digest.digest('SHA256', "a"))) + assert_equal(sha384_a, encode16(OpenSSL::Digest.digest('SHA384', "a"))) + assert_equal(sha512_a, encode16(OpenSSL::Digest.digest('SHA512', "a"))) + end + + def test_sha512_truncate + pend "SHA512_224 is not implemented" unless digest_available?('SHA512-224') + sha512_224_a = "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327" + sha512_256_a = "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8" + + assert_equal(sha512_224_a, OpenSSL::Digest.hexdigest('SHA512-224', "a")) + assert_equal(sha512_256_a, OpenSSL::Digest.hexdigest('SHA512-256', "a")) - assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a"))) - assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a"))) - assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a"))) - assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a"))) + assert_equal(sha512_224_a, encode16(OpenSSL::Digest.digest('SHA512-224', "a"))) + assert_equal(sha512_256_a, encode16(OpenSSL::Digest.digest('SHA512-256', "a"))) + end + + def test_sha3 + pend "SHA3 is not implemented" unless digest_available?('SHA3-224') + s224 = '6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7' + s256 = 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a' + s384 = '0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004' + s512 = 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26' + assert_equal(OpenSSL::Digest.hexdigest('SHA3-224', ""), s224) + assert_equal(OpenSSL::Digest.hexdigest('SHA3-256', ""), s256) + assert_equal(OpenSSL::Digest.hexdigest('SHA3-384', ""), s384) + assert_equal(OpenSSL::Digest.hexdigest('SHA3-512', ""), s512) end def test_digest_by_oid_and_name_sha2 @@ -116,6 +136,14 @@ def check_digest(oid) d = OpenSSL::Digest.new(oid.oid) assert_not_nil(d) end + + def digest_available?(name) + begin + OpenSSL::Digest.new(name) + rescue RuntimeError + false + end + end end end diff --git a/ruby/test/openssl/test_engine.rb b/ruby/test/openssl/test_engine.rb index bb1123d51..1ede6ed08 100644 --- a/ruby/test/openssl/test_engine.rb +++ b/ruby/test/openssl/test_engine.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) && defined?(OpenSSL::Engine) @@ -47,7 +47,7 @@ def test_openssl_engine_digest_sha1 digest = engine.digest("SHA1") assert_not_nil(digest) data = "test" - assert_equal(OpenSSL::Digest::SHA1.digest(data), digest.digest(data)) + assert_equal(OpenSSL::Digest.digest('SHA1', data), digest.digest(data)) end; end diff --git a/ruby/test/openssl/test_fips.rb b/ruby/test/openssl/test_fips.rb index a577d7891..8cd474f9a 100644 --- a/ruby/test/openssl/test_fips.rb +++ b/ruby/test/openssl/test_fips.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) diff --git a/ruby/test/openssl/test_hmac.rb b/ruby/test/openssl/test_hmac.rb index 831a5b6b3..47cb3718d 100644 --- a/ruby/test/openssl/test_hmac.rb +++ b/ruby/test/openssl/test_hmac.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -10,15 +10,18 @@ def test_hmac hmac.update("Hi There") assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), hmac.digest assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hmac.hexdigest + assert_equal "kpRyejY4uxwT9I74FYv8nQ==", hmac.base64digest # RFC 4231 4.2. Test Case 1 hmac = OpenSSL::HMAC.new(["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*"), "SHA224") hmac.update("Hi There") assert_equal ["896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"].pack("H*"), hmac.digest assert_equal "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", hmac.hexdigest + assert_equal "iW+xEoq73xloMhB81J3zP0e0sRaZErpPU2hLIg==", hmac.base64digest end def test_dup + pend "HMAC#initialize_copy is currently broken on OpenSSL 3.0.0" if openssl?(3, 0, 0) h1 = OpenSSL::HMAC.new("KEY", "MD5") h1.update("DATA") h = h1.dup @@ -39,6 +42,27 @@ def test_reset_keep_key second = h1.update("test").hexdigest assert_equal first, second end + + def test_eq + h1 = OpenSSL::HMAC.new("KEY", "MD5") + h2 = OpenSSL::HMAC.new("KEY", OpenSSL::Digest.new("MD5")) + h3 = OpenSSL::HMAC.new("FOO", "MD5") + + assert_equal h1, h2 + refute_equal h1, h2.digest + refute_equal h1, h3 + end + + def test_singleton_methods + # RFC 2202 2. Test Cases for HMAC-MD5 + key = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") + digest = OpenSSL::HMAC.digest("MD5", key, "Hi There") + assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), digest + hexdigest = OpenSSL::HMAC.hexdigest("MD5", key, "Hi There") + assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hexdigest + b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") + assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest + end end end diff --git a/ruby/test/openssl/test_kdf.rb b/ruby/test/openssl/test_kdf.rb index 5e1db80c5..f4790c96a 100644 --- a/ruby/test/openssl/test_kdf.rb +++ b/ruby/test/openssl/test_kdf.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) diff --git a/ruby/test/openssl/test_ns_spki.rb b/ruby/test/openssl/test_ns_spki.rb index aa1e61824..ed3be86e2 100644 --- a/ruby/test/openssl/test_ns_spki.rb +++ b/ruby/test/openssl/test_ns_spki.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -9,7 +9,7 @@ def setup # This request data is adopt from the specification of # "Netscape Extensions for User Key Generation". # -- http://wp.netscape.com/eng/security/comm4-keygen.html - @b64 = "MIHFMHEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAnX0TILJrOMUue+PtwBRE6XfV" + @b64 = +"MIHFMHEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAnX0TILJrOMUue+PtwBRE6XfV" @b64 << "WtKQbsshxk5ZhcUwcwyvcnIq9b82QhJdoACdD34rqfCAIND46fXKQUnb0mvKzQID" @b64 << "AQABFhFNb3ppbGxhSXNNeUZyaWVuZDANBgkqhkiG9w0BAQQFAANBAAKv2Eex2n/S" @b64 << "r/7iJNroWlSzSMtTiQTEB+ADWHGj9u1xrUrOilq/o2cuQxIfZcNZkYAkWP4DubqW" @@ -22,7 +22,7 @@ def test_build_data spki = OpenSSL::Netscape::SPKI.new spki.challenge = "RandomString" spki.public_key = key1.public_key - spki.sign(key1, OpenSSL::Digest::SHA1.new) + spki.sign(key1, OpenSSL::Digest.new('SHA1')) assert(spki.verify(spki.public_key)) assert(spki.verify(key1.public_key)) assert(!spki.verify(key2.public_key)) diff --git a/ruby/test/openssl/test_ocsp.rb b/ruby/test/openssl/test_ocsp.rb index 50ad6c31f..ef7321abd 100644 --- a/ruby/test/openssl/test_ocsp.rb +++ b/ruby/test/openssl/test_ocsp.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) @@ -50,26 +50,26 @@ def test_new_certificate_id cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert) assert_kind_of OpenSSL::OCSP::CertificateId, cid assert_equal @cert.serial, cid.serial - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA256.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA256')) assert_kind_of OpenSSL::OCSP::CertificateId, cid assert_equal @cert.serial, cid.serial end def test_certificate_id_issuer_name_hash cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert) - assert_equal OpenSSL::Digest::SHA1.hexdigest(@cert.issuer.to_der), cid.issuer_name_hash + assert_equal OpenSSL::Digest.hexdigest('SHA1', @cert.issuer.to_der), cid.issuer_name_hash assert_equal "d91f736ac4dc3242f0fb9b77a3149bd83c5c43d0", cid.issuer_name_hash end def test_certificate_id_issuer_key_hash cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert) - assert_equal OpenSSL::Digest::SHA1.hexdigest(OpenSSL::ASN1.decode(@ca_cert.to_der).value[0].value[6].value[1].value), cid.issuer_key_hash + assert_equal OpenSSL::Digest.hexdigest('SHA1', OpenSSL::ASN1.decode(@ca_cert.to_der).value[0].value[6].value[1].value), cid.issuer_key_hash assert_equal "d1fef9fbf8ae1bc160cbfa03e2596dd873089213", cid.issuer_key_hash end def test_certificate_id_hash_algorithm - cid_sha1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) - cid_sha256 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA256.new) + cid_sha1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + cid_sha256 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA256')) assert_equal "sha1", cid_sha1.hash_algorithm assert_equal "sha256", cid_sha256.hash_algorithm end @@ -84,6 +84,7 @@ def test_certificate_id_der assert_equal [cid.issuer_key_hash].pack("H*"), asn1.value[2].value assert_equal @cert.serial, asn1.value[3].value assert_equal der, OpenSSL::OCSP::CertificateId.new(der).to_der + assert_equal der, OpenSSL::OCSP::CertificateId.new(asn1).to_der end def test_certificate_id_dup @@ -93,7 +94,7 @@ def test_certificate_id_dup def test_request_der request = OpenSSL::OCSP::Request.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) request.add_certid(cid) request.sign(@cert, @cert_key, [@ca_cert], 0) asn1 = OpenSSL::ASN1.decode(request.to_der) @@ -122,14 +123,7 @@ def test_request_sign_verify assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN) ret = req.verify([@cert], store) - if ret || openssl?(1, 0, 2) - assert_equal true, ret - else - # RT2560; OCSP_request_verify() does not find signer cert from 'certs' when - # OCSP_NOINTERN is not specified. - # fixed by OpenSSL 1.0.1j, 1.0.2 - pend "RT2560: ocsp_req_find_signer" - end + assert_equal true, ret # not signed req = OpenSSL::OCSP::Request.new.add_certid(cid) @@ -163,14 +157,14 @@ def test_request_nonce def test_request_dup request = OpenSSL::OCSP::Request.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) request.add_certid(cid) assert_equal request.to_der, request.dup.to_der end def test_basic_response_der bres = OpenSSL::OCSP::BasicResponse.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, []) bres.add_nonce("NONCE") bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0) @@ -213,7 +207,7 @@ def test_basic_response_sign_verify def test_basic_response_dup bres = OpenSSL::OCSP::BasicResponse.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, []) bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0) assert_equal bres.to_der, bres.dup.to_der @@ -222,9 +216,9 @@ def test_basic_response_dup def test_basic_response_response_operations bres = OpenSSL::OCSP::BasicResponse.new now = Time.at(Time.now.to_i) - cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) - cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest::SHA1.new) - cid3 = OpenSSL::OCSP::CertificateId.new(@ca_cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + cid3 = OpenSSL::OCSP::CertificateId.new(@ca_cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid1, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, now - 400, -300, nil, nil) bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_GOOD, nil, nil, -300, 500, []) @@ -256,8 +250,8 @@ def test_single_response_der def test_single_response_check_validity bres = OpenSSL::OCSP::BasicResponse.new - cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) - cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid1, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, -50, []) bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, nil, []) bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_GOOD, nil, nil, Time.now + 100, nil, nil) @@ -276,7 +270,7 @@ def test_single_response_check_validity def test_response bres = OpenSSL::OCSP::BasicResponse.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, []) bres.sign(@ocsp_cert, @ocsp_key, []) res = OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, bres) @@ -287,7 +281,7 @@ def test_response def test_response_der bres = OpenSSL::OCSP::BasicResponse.new - cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, []) bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0) res = OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, bres) diff --git a/ruby/test/openssl/test_ossl.rb b/ruby/test/openssl/test_ossl.rb new file mode 100644 index 000000000..e1d86bd40 --- /dev/null +++ b/ruby/test/openssl/test_ossl.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true +require_relative "utils" + +require 'benchmark' + +if defined?(OpenSSL) + +class OpenSSL::OSSL < OpenSSL::SSLTestCase + def test_fixed_length_secure_compare + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "a") } + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aa") } + + assert OpenSSL.fixed_length_secure_compare("aaa", "aaa") + assert OpenSSL.fixed_length_secure_compare( + OpenSSL::Digest.digest('SHA256', "aaa"), OpenSSL::Digest::SHA256.digest("aaa") + ) + + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaaa") } + refute OpenSSL.fixed_length_secure_compare("aaa", "baa") + refute OpenSSL.fixed_length_secure_compare("aaa", "aba") + refute OpenSSL.fixed_length_secure_compare("aaa", "aab") + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaab") } + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "b") } + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bb") } + refute OpenSSL.fixed_length_secure_compare("aaa", "bbb") + assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bbbb") } + end + + def test_secure_compare + refute OpenSSL.secure_compare("aaa", "a") + refute OpenSSL.secure_compare("aaa", "aa") + + assert OpenSSL.secure_compare("aaa", "aaa") + + refute OpenSSL.secure_compare("aaa", "aaaa") + refute OpenSSL.secure_compare("aaa", "baa") + refute OpenSSL.secure_compare("aaa", "aba") + refute OpenSSL.secure_compare("aaa", "aab") + refute OpenSSL.secure_compare("aaa", "aaab") + refute OpenSSL.secure_compare("aaa", "b") + refute OpenSSL.secure_compare("aaa", "bb") + refute OpenSSL.secure_compare("aaa", "bbb") + refute OpenSSL.secure_compare("aaa", "bbbb") + end + + def test_memcmp_timing + # Ensure using fixed_length_secure_compare takes almost exactly the same amount of time to compare two different strings. + # Regular string comparison will short-circuit on the first non-matching character, failing this test. + # NOTE: this test may be susceptible to noise if the system running the tests is otherwise under load. + a = "x" * 512_000 + b = "#{a}y" + c = "y#{a}" + a = "#{a}x" + + a_b_time = a_c_time = 0 + 100.times do + a_b_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, b) } }.real + a_c_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, c) } }.real + end + assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed") + assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed") + end +end + +end diff --git a/ruby/test/openssl/test_pair.rb b/ruby/test/openssl/test_pair.rb index 08c15a0f7..4249b4afb 100644 --- a/ruby/test/openssl/test_pair.rb +++ b/ruby/test/openssl/test_pair.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' require_relative 'ut_eof' @@ -23,7 +23,6 @@ def ssl_pair sctx = OpenSSL::SSL::SSLContext.new sctx.cert = @svr_cert sctx.key = @svr_key - sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") } sctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx) ns = ssls.accept @@ -128,11 +127,11 @@ def test_readpartial ssl_pair {|s1, s2| s2.write "a\nbcd" assert_equal("a\n", s1.gets) - result = "" + result = String.new result << s1.readpartial(10) until result.length == 3 assert_equal("bcd", result) s2.write "efg" - result = "" + result = String.new result << s1.readpartial(10) until result.length == 3 assert_equal("efg", result) s2.close @@ -156,20 +155,6 @@ def test_readline } end - def test_puts_meta - ssl_pair {|s1, s2| - begin - old = $/ - $/ = '*' - s1.puts 'a' - ensure - $/ = old - end - s1.close - assert_equal("a\n", s2.read) - } - end - def test_puts_empty ssl_pair {|s1, s2| s1.puts @@ -242,22 +227,22 @@ def test_read_nonblock_no_exception def test_read_with_outbuf ssl_pair { |s1, s2| s1.write("abc\n") - buf = "" + buf = String.new ret = s2.read(2, buf) assert_same ret, buf assert_equal "ab", ret - buf = "garbage" + buf = +"garbage" ret = s2.read(2, buf) assert_same ret, buf assert_equal "c\n", ret - buf = "garbage" + buf = +"garbage" assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false) assert_equal "", buf s1.close - buf = "garbage" + buf = +"garbage" assert_equal nil, s2.read(100, buf) assert_equal "", buf } @@ -397,7 +382,6 @@ def test_connect_accept_nonblock_no_exception ctx2 = OpenSSL::SSL::SSLContext.new ctx2.cert = @svr_cert ctx2.key = @svr_key - ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") } sock1, sock2 = tcp_pair @@ -445,7 +429,6 @@ def test_connect_accept_nonblock ctx = OpenSSL::SSL::SSLContext.new ctx.cert = @svr_cert ctx.key = @svr_key - ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") } sock1, sock2 = tcp_pair diff --git a/ruby/test/openssl/test_pkcs12.rb b/ruby/test/openssl/test_pkcs12.rb index de8e35ed7..ec676743b 100644 --- a/ruby/test/openssl/test_pkcs12.rb +++ b/ruby/test/openssl/test_pkcs12.rb @@ -1,10 +1,13 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) module OpenSSL class TestPKCS12 < OpenSSL::TestCase + DEFAULT_PBE_PKEYS = "PBE-SHA1-3DES" + DEFAULT_PBE_CERTS = "PBE-SHA1-3DES" + def setup super ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @@ -14,47 +17,41 @@ def setup ["subjectKeyIdentifier","hash",false], ["authorityKeyIdentifier","keyid:always",false], ] - @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil) + ca_key = Fixtures.pkey("rsa-1") + @cacert = issue_cert(ca, ca_key, 1, ca_exts, nil, nil) inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA") - inter_ca_key = OpenSSL::PKey.read <<-_EOS_ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDp7hIG0SFMG/VWv1dBUWziAPrNmkMXJgTCAoB7jffzRtyyN04K -oq/89HAszTMStZoMigQURfokzKsjpUp8OYCAEsBtt9d5zPndWMz/gHN73GrXk3LT -ZsxEn7Xv5Da+Y9F/Hx2QZUHarV5cdZixq2NbzWGwrToogOQMh2pxN3Z/0wIDAQAB -AoGBAJysUyx3olpsGzv3OMRJeahASbmsSKTXVLZvoIefxOINosBFpCIhZccAG6UV -5c/xCvS89xBw8aD15uUfziw3AuT8QPEtHCgfSjeT7aWzBfYswEgOW4XPuWr7EeI9 -iNHGD6z+hCN/IQr7FiEBgTp6A+i/hffcSdR83fHWKyb4M7TRAkEA+y4BNd668HmC -G5MPRx25n6LixuBxrNp1umfjEI6UZgEFVpYOg4agNuimN6NqM253kcTR94QNTUs5 -Kj3EhG1YWwJBAO5rUjiOyCNVX2WUQrOMYK/c1lU7fvrkdygXkvIGkhsPoNRzLPeA -HGJszKtrKD8bNihWpWNIyqKRHfKVD7yXT+kCQGCAhVCIGTRoypcDghwljHqLnysf -ci0h5ZdPcIqc7ODfxYhFsJ/Rql5ONgYsT5Ig/+lOQAkjf+TRYM4c2xKx2/8CQBvG -jv6dy70qDgIUgqzONtlmHeYyFzn9cdBO5sShdVYHvRHjFSMEXsosqK9zvW2UqvuK -FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3 -Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= ------END RSA PRIVATE KEY----- - _EOS_ - @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048")) + inter_ca_key = Fixtures.pkey("rsa-2") + @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, ca_key) exts = [ ["keyUsage","digitalSignature",true], ["subjectKeyIdentifier","hash",false], ] ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate") - @mykey = Fixtures.pkey("rsa1024") + @mykey = Fixtures.pkey("rsa-3") @mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key) end - def test_create + def test_create_single_key_single_cert pkcs12 = OpenSSL::PKCS12.create( "omg", "hello", @mykey, - @mycert + @mycert, + nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, ) - assert_equal @mycert.to_der, pkcs12.certificate.to_der + assert_equal @mycert, pkcs12.certificate assert_equal @mykey.to_der, pkcs12.key.to_der assert_nil pkcs12.ca_certs + + der = pkcs12.to_der + decoded = OpenSSL::PKCS12.new(der, "omg") + assert_equal @mykey.to_der, decoded.key.to_der + assert_equal @mycert, decoded.certificate + assert_equal [], Array(decoded.ca_certs) end def test_create_no_pass @@ -62,14 +59,17 @@ def test_create_no_pass nil, "hello", @mykey, - @mycert + @mycert, + nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, ) - assert_equal @mycert.to_der, pkcs12.certificate.to_der + assert_equal @mycert, pkcs12.certificate assert_equal @mykey.to_der, pkcs12.key.to_der assert_nil pkcs12.ca_certs decoded = OpenSSL::PKCS12.new(pkcs12.to_der) - assert_cert @mycert, decoded.certificate + assert_equal @mycert, decoded.certificate end def test_create_with_chain @@ -80,7 +80,9 @@ def test_create_with_chain "hello", @mykey, @mycert, - chain + chain, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, ) assert_equal chain, pkcs12.ca_certs end @@ -95,14 +97,16 @@ def test_create_with_chain_decode "hello", @mykey, @mycert, - chain + chain, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, ) decoded = OpenSSL::PKCS12.new(pkcs12.to_der, passwd) assert_equal chain.size, decoded.ca_certs.size - assert_include_cert @cacert, decoded.ca_certs - assert_include_cert @inter_cacert, decoded.ca_certs - assert_cert @mycert, decoded.certificate + assert_include decoded.ca_certs, @cacert + assert_include decoded.ca_certs, @inter_cacert + assert_equal @mycert, decoded.certificate assert_equal @mykey.to_der, decoded.key.to_der end @@ -126,8 +130,8 @@ def test_create_with_itr @mykey, @mycert, [], - nil, - nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, 2048 ) @@ -138,8 +142,8 @@ def test_create_with_itr @mykey, @mycert, [], - nil, - nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, "omg" ) end @@ -152,7 +156,8 @@ def test_create_with_mac_itr @mykey, @mycert, [], - nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, nil, nil, 2048 @@ -165,148 +170,144 @@ def test_create_with_mac_itr @mykey, @mycert, [], - nil, - nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, nil, "omg" ) end end - def test_new_with_one_key_and_one_cert - # generated with: - # openssl version #=> OpenSSL 1.0.2h 3 May 2016 - # openssl pkcs12 -in <@mycert> -inkey -export -out - str = <<~EOF.unpack("m").first -MIIGQQIBAzCCBgcGCSqGSIb3DQEHAaCCBfgEggX0MIIF8DCCAu8GCSqGSIb3DQEH -BqCCAuAwggLcAgEAMIIC1QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIeZPM -Rh6KiXgCAggAgIICqL6O+LCZmBzdIg6mozPF3FpY0hVbWHvTNMiDHieW3CrAanhN -YCH2/wHqH8WpFpEWwF0qEEXAWjHsIlYB4Cfqo6b7XpuZe5eVESsjNTOTMF1JCUJj -A6iNefXmCFLync1JK5LUodRDhTlKLU1WPK20X9X4vuEwHn8wt5RUb8P0E+Xh6rpS -XC4LkZKT45zF3cJa/n5+dW65ohVGNVnF9D1bCNEKHMOllK1V9omutQ9slW88hpga -LGiFsJoFOb/ESGb78KO+bd6zbX1MdKdBV+WD6t1uF/cgU65y+2A4nXs1urda+MJ7 -7iVqiB7Vnc9cANTbAkTSGNyoUDVM/NZde782/8IvddLAzUZ2EftoRDke6PvuBOVL -ljBhNWmdamrtBqzuzVZCRdWq44KZkF2Xoc9asepwIkdVmntzQF7f1Z+Ta5yg6HFp -xnr7CuM+MlHEShXkMgYtHnwAq10fDMSXIvjhi/AA5XUAusDO3D+hbtcRDcJ4uUes -dm5dhQE2qJ02Ysn4aH3o1F3RYNOzrxejHJwl0D2TCE8Ww2X342xib57+z9u03ufj -jswhiMKxy67f1LhUMq3XrT3uV6kCVXk/KUOUPcXPlPVNA5JmZeFhMp6GrtB5xJJ9 -wwBZD8UL5A2U2Mxi2OZsdUBv8eo3jnjZ284aFpt+mCjIHrLW5O0jwY8OCwSlYUoY -IY00wlabX0s82kBcIQNZbC1RSV2267ro/7A0MClc8YQ/zWN0FKY6apgtUkHJI1cL -1dc77mhnjETjwW94iLMDFy4zQfVu7IfCBqOBzygRNnqqUG66UhTs1xFnWM0mWXl/ -Zh9+AMpbRLIPaKCktIjl5juzzm+KEgkhD+707XRCFIGUYGP5bSHzGaz8PK9hj0u1 -E2SpZHUvYOcawmxtA7pmpSxl5uQjMIIC+QYJKoZIhvcNAQcBoIIC6gSCAuYwggLi -MIIC3gYLKoZIhvcNAQwKAQKgggKmMIICojAcBgoqhkiG9w0BDAEDMA4ECKB338m8 -qSzHAgIIAASCAoACFhJeqA3xx+s1qIH6udNQYY5hAL6oz7SXoGwFhDiceSyJjmAD -Dby9XWM0bPl1Gj5nqdsuI/lAM++fJeoETk+rxw8q6Ofk2zUaRRE39qgpwBwSk44o -0SAFJ6bzHpc5CFh6sZmDaUX5Lm9GtjnGFmmsPTSJT5an5JuJ9WczGBEd0nSBQhJq -xHbTGZiN8i3SXcIH531Sub+CBIFWy5lyCKgDYh/kgJFGQAaWUOjLI+7dCEESonXn -F3Jh2uPbnDF9MGJyAFoNgWFhgSpi1cf6AUi87GY4Oyur88ddJ1o0D0Kz2uw8/bpG -s3O4PYnIW5naZ8mozzbnYByEFk7PoTwM7VhoFBfYNtBoAI8+hBnPY/Y71YUojEXf -SeX6QbtkIANfzS1XuFNKElShC3DPQIHpKzaatEsfxHfP+8VOav6zcn4mioao7NHA -x7Dp6R1enFGoQOq4UNjBT8YjnkG5vW8zQHW2dAHLTJBq6x2Fzm/4Pjo/8vM1FiGl -BQdW5vfDeJ/l6NgQm3xR9ka2E2HaDqIcj1zWbN8jy/bHPFJYuF/HH8MBV/ngMIXE -vFEW/ToYv8eif0+EpUtzBsCKD4a7qYYYh87RmEVoQU96q6m+UbhpD2WztYfAPkfo -OSL9j2QHhVczhL7OAgqNeM95pOsjA9YMe7exTeqK31LYnTX8oH8WJD1xGbRSJYgu -SY6PQbumcJkc/TFPn0GeVUpiDdf83SeG50lo/i7UKQi2l1hi5Y51fQhnBnyMr68D -llSZEvSWqfDxBJkBpeg6PIYvkTpEwKRJpVQoM3uYvdqVSSnW6rydqIb+snfOrlhd -f+xCtq9xr+kHeTSqLIDRRAnMfgFRhY3IBlj6MSUwIwYJKoZIhvcNAQkVMRYEFBdb -8XGWehZ6oPj56Pf/uId46M9AMDEwITAJBgUrDgMCGgUABBRvSCB04/f8f13pp2PF -vyl2WuMdEwQIMWFFphPkIUICAggA - EOF - p12 = OpenSSL::PKCS12.new(str, "abc123") - - assert_equal @mykey.to_der, p12.key.to_der - assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der - assert_equal [], Array(p12.ca_certs) - end - def test_new_with_no_keys # generated with: - # openssl pkcs12 -in <@mycert> -nokeys -export -out + # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export str = <<~EOF.unpack("m").first -MIIDHAIBAzCCAuIGCSqGSIb3DQEHAaCCAtMEggLPMIICyzCCAscGCSqGSIb3DQEH -BqCCArgwggK0AgEAMIICrQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIX4+W -irqwH40CAggAgIICgOaCyo+5+6IOVoGCCL80c50bkkzAwqdXxvkKExJSdcJz2uMU -0gRrKnZEjL5wrUsN8RwZu8DvgQTEhNEkKsUgM7AWainmN/EnwohIdHZAHpm6WD67 -I9kLGp0/DHrqZrV9P2dLfhXLUSQE8PI0tqZPZ8UEABhizkViw4eISTkrOUN7pGbN -Qtx/oqgitXDuX2polbxYYDwt9vfHZhykHoKgew26SeJyZfeMs/WZ6olEI4cQUAFr -mvYGuC1AxEGTo9ERmU8Pm16j9Hr9PFk50WYe+rnk9oX3wJogQ7XUWS5kYf7XRycd -NDkNiwV/ts94bbuaGZp1YA6I48FXpIc8b5fX7t9tY0umGaWy0bARe1L7o0Y89EPe -lMg25rOM7j3uPtFG8whbSfdETSy57UxzzTcJ6UwexeaK6wb2jqEmj5AOoPLWeaX0 -LyOAszR3v7OPAcjIDYZGdrbb3MZ2f2vo2pdQfu9698BrWhXuM7Odh73RLhJVreNI -aezNOAtPyBlvGiBQBGTzRIYHSLL5Y5aVj2vWLAa7hjm5qTL5C5mFdDIo6TkEMr6I -OsexNQofEGs19kr8nARXDlcbEimk2VsPj4efQC2CEXZNzURsKca82pa62MJ8WosB -DTFd8X06zZZ4nED50vLopZvyW4fyW60lELwOyThAdG8UchoAaz2baqP0K4de44yM -Y5/yPFDu4+GoimipJfbiYviRwbzkBxYW8+958ILh0RtagLbvIGxbpaym9PqGjOzx -ShNXjLK2aAFZsEizQ8kd09quJHU/ogq2cUXdqqhmOqPnUWrJVi/VCoRB3Pv1/lE4 -mrUgr2YZ11rYvBw6g5XvNvFcSc53OKyV7SLn0dwwMTAhMAkGBSsOAwIaBQAEFEWP -1WRQykaoD4uJCpTx/wv0SLLBBAiDKI26LJK7xgICCAA= +MIIGJAIBAzCCBeoGCSqGSIb3DQEHAaCCBdsEggXXMIIF0zCCBc8GCSqGSIb3 +DQEHBqCCBcAwggW8AgEAMIIFtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMw +DgQIjv5c3OHvnBgCAggAgIIFiMJa8Z/w7errRvCQPXh9dGQz3eJaFq3S2gXD +rh6oiwsgIRJZvYAWgU6ll9NV7N5SgvS2DDNVuc3tsP8TPWjp+bIxzS9qmGUV +kYWuURWLMKhpF12ZRDab8jcIwBgKoSGiDJk8xHjx6L613/XcRM6ln3VeQK+C +hlW5kXniNAUAgTft25Fn61Xa8xnhmsz/fk1ycGnyGjKCnr7Mgy7KV0C1vs23 +18n8+b1ktDWLZPYgpmXuMFVh0o+HJTV3O86mkIhJonMcnOMgKZ+i8KeXaocN +JQlAPBG4+HOip7FbQT/h6reXv8/J+hgjLfqAb5aV3m03rUX9mXx66nR1tQU0 +Jq+XPfDh5+V4akIczLlMyyo/xZjI1/qupcMjr+giOGnGd8BA3cuXW+ueLQiA +PpTp+DQLVHRfz9XTZbyqOReNEtEXvO9gOlKSEY5lp65ItXVEs2Oqyf9PfU9y +DUltN6fCMilwPyyrsIBKXCu2ZLM5h65KVCXAYEX9lNqj9zrQ7vTqvCNN8RhS +ScYouTX2Eqa4Z+gTZWLHa8RCQFoyP6hd+97/Tg2Gv2UTH0myQxIVcnpdi1wy +cqb+er7tyKbcO96uSlUjpj/JvjlodtjJcX+oinEqGb/caj4UepbBwiG3vv70 +63bS3jTsOLNjDRsR9if3LxIhLa6DW8zOJiGC+EvMD1o4dzHcGVpQ/pZWCHZC ++YiNJpQOBApiZluE+UZ0m3XrtHFQYk7xblTrh+FJF91wBsok0rZXLAKd8m4p +OJsc7quCq3cuHRRTzJQ4nSe01uqbwGDAYwLvi6VWy3svU5qa05eDRmgzEFTG +e84Gp/1LQCtpQFr4txkjFchO2whWS80KoQKqmLPyGm1D9Lv53Q4ZsKMgNihs +rEepuaOZMKHl4yMAYFoOXZCAYzfbhN6b2phcFAHjMUHUw9e3F0QuDk9D0tsr +riYTrkocqlOKfK4QTomx27O0ON2J6f1rtEojGgfl9RNykN7iKGzjS3914QjW +W6gGiZejxHsDPEAa4gUp0WiSUSXtD5WJgoyAzLydR2dKWsQ4WlaUXi01CuGy ++xvncSn2nO3bbot8VD5H6XU1CjREVtnIfbeRYO/uofyLUP3olK5RqN6ne6Xo +eXnJ/bjYphA8NGuuuvuW1SCITmINkZDLC9cGlER9+K65RR/DR3TigkexXMeN +aJ70ivZYAl0OuhZt3TGIlAzS64TIoyORe3z7Ta1Pp9PZQarYJpF9BBIZIFor +757PHHuQKRuugiRkp8B7v4eq1BQ+VeAxCKpyZ7XrgEtbY/AWDiaKcGPKPjc3 +AqQraVeQm7kMBT163wFmZArCphzkDOI3bz2oEO8YArMgLq2Vto9jAZlqKyWr +pi2bSJxuoP1aoD58CHcWMrf8/j1LVdQhKgHQXSik2ID0H2Wc/XnglhzlVFuJ +JsNIW/EGJlZh/5WDez9U0bXqnBlu3uasPEOezdoKlcCmQlmTO5+uLHYLEtNA +EH9MtnGZebi9XS5meTuS6z5LILt8O9IHZxmT3JRPHYj287FEzotlLdcJ4Ee5 +enW41UHjLrfv4OaITO1hVuoLRGdzjESx/fHMWmxroZ1nVClxECOdT42zvIYJ +J3xBZ0gppzQ5fjoYiKjJpxTflRxUuxshk3ih6VUoKtqj/W18tBQ3g5SOlkgT +yCW8r74yZlfYmNrPyDMUQYpLUPWj2n71GF0KyPfTU5yOatRgvheh262w5BG3 +omFY7mb3tCv8/U2jdMIoukRKacpZiagofz3SxojOJq52cHnCri+gTHBMX0cO +j58ygfntHWRzst0pV7Ze2X3fdCAJ4DokH6bNJNthcgmolFJ/y3V1tJjgsdtQ +7Pjn/vE6xUV0HXE2x4yoVYNirbAMIvkN/X+atxrN0dA4AchN+zGp8TAxMCEw +CQYFKw4DAhoFAAQUQ+6XXkyhf6uYgtbibILN2IjKnOAECLiqoY45MPCrAgII +AA== EOF p12 = OpenSSL::PKCS12.new(str, "abc123") assert_equal nil, p12.key assert_equal nil, p12.certificate assert_equal 1, p12.ca_certs.size - assert_equal @mycert.subject.to_der, p12.ca_certs[0].subject.to_der + assert_equal @mycert.subject, p12.ca_certs[0].subject end def test_new_with_no_certs # generated with: - # openssl pkcs12 -inkey -nocerts -export -out + # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export str = <<~EOF.unpack("m").first -MIIDJwIBAzCCAu0GCSqGSIb3DQEHAaCCAt4EggLaMIIC1jCCAtIGCSqGSIb3DQEH -AaCCAsMEggK/MIICuzCCArcGCyqGSIb3DQEMCgECoIICpjCCAqIwHAYKKoZIhvcN -AQwBAzAOBAg6AaYnJs84SwICCAAEggKAQzZH+fWSpcQYD1J7PsGSune85A++fLCQ -V7tacp2iv95GJkxwYmfTP176pJdgs00mceB9UJ/u9EX5nD0djdjjQjwo6sgKjY0q -cpVhZw8CMxw7kBD2dhtui0zT8z5hy03LePxsjEKsGiSbeVeeGbSfw/I6AAYbv+Uh -O/YPBGumeHj/D2WKnfsHJLQ9GAV3H6dv5VKYNxjciK7f/JEyZCuUQGIN64QFHDhJ -7fzLqd/ul3FZzJZO6a+dwvcgux09SKVXDRSeFmRCEX4b486iWhJJVspCo9P2KNne -ORrpybr3ZSwxyoICmjyo8gj0OSnEfdx9790Ej1takPqSA1wIdSdBLekbZqB0RBQg -DEuPOsXNo3QFi8ji1vu0WBRJZZSNC2hr5NL6lNR+DKxG8yzDll2j4W4BBIp22mAE -7QRX7kVxu17QJXQhOUac4Dd1qXmzebP8t6xkAxD9L7BWEN5OdiXWwSWGjVjMBneX -nYObi/3UT/aVc5WHMHK2BhCI1bwH51E6yZh06d5m0TQpYGUTWDJdWGBSrp3A+8jN -N2PMQkWBFrXP3smHoTEN4oZC4FWiPsIEyAkQsfKRhcV9lGKl2Xgq54ROTFLnwKoj -Z3zJScnq9qmNzvVZSMmDLkjLyDq0pxRxGKBvgouKkWY7VFFIwwBIJM39iDJ5NbBY -i1AQFTRsRSsZrNVPasCXrIq7bhMoJZb/YZOGBLNyJVqKUoYXhtwsajzSq54VlWft -JxsPayEd4Vi6O9EU1ahnj6qFEZiKFzsicgK2J1Rb8cYagrp0XWjHW0SBn5GVUWCg -GUokSFG/0JTdeYTo/sQuG4qNgJkOolRjpeI48Fciq5VUWLvVdKioXzAxMCEwCQYF -Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA== +MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3 +DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK +KoZIhvcNAQwBAzAOBAjX5nN8jyRKwQICCAAEgglIBIRLHfiY1mNHpl3FdX6+ +72L+ZOVXnlZ1MY9HSeg0RMkCJcm0mJ2UD7INUOGXvwpK9fr6WJUZM1IqTihQ +1dM0crRC2m23aP7KtAlXh2DYD3otseDtwoN/NE19RsiJzeIiy5TSW1d47weU ++D4Ig/9FYVFPTDgMzdCxXujhvO/MTbZIjqtcS+IOyF+91KkXrHkfkGjZC7KS +WRmYw9BBuIPQEewdTI35sAJcxT8rK7JIiL/9mewbSE+Z28Wq1WXwmjL3oZm9 +lw6+f515b197GYEGomr6LQqJJamSYpwQbTGHonku6Tf3ylB4NLFqOnRCKE4K +zRSSYIqJBlKHmQ4pDm5awoupHYxMZLZKZvXNYyYN3kV8r1iiNVlY7KBR4CsX +rqUkXehRmcPnuqEMW8aOpuYe/HWf8PYI93oiDZjcEZMwW2IZFFrgBbqUeNCM +CQTkjAYxi5FyoaoTnHrj/aRtdLOg1xIJe4KKcmOXAVMmVM9QEPNfUwiXJrE7 +n42gl4NyzcZpxqwWBT++9TnQGZ/lEpwR6dzkZwICNQLdQ+elsdT7mumywP+1 +WaFqg9kpurimaiBu515vJNp9Iqv1Nmke6R8Lk6WVRKPg4Akw0fkuy6HS+LyN +ofdCfVUkPGN6zkjAxGZP9ZBwvXUbLRC5W3N5qZuAy5WcsS75z+oVeX9ePV63 +cue23sClu8JSJcw3HFgPaAE4sfkQ4MoihPY5kezgT7F7Lw/j86S0ebrDNp4N +Y685ec81NRHJ80CAM55f3kGCOEhoifD4VZrvr1TdHZY9Gm3b1RYaJCit2huF +nlOfzeimdcv/tkjb6UsbpXx3JKkF2NFFip0yEBERRCdWRYMUpBRcl3ad6XHy +w0pVTgIjTxGlbbtOCi3siqMOK0GNt6UgjoEFc1xqjsgLwU0Ta2quRu7RFPGM +GoEwoC6VH23p9Hr4uTFOL0uHfkKWKunNN+7YPi6LT6IKmTQwrp+fTO61N6Xh +KlqTpwESKsIJB2iMnc8wBkjXJtmG/e2n5oTqfhICIrxYmEb7zKDyK3eqeTj3 +FhQh2t7cUIiqcT52AckUqniPmlE6hf82yBjhaQUPfi/ExTBtTDSmFfRPUzq+ +Rlla4OHllPRzUXJExyansgCxZbPqlw46AtygSWRGcWoYAKUKwwoYjerqIV5g +JoZICV9BOU9TXco1dHXZQTs/nnTwoRmYiL/Ly5XpvUAnQOhYeCPjBeFnPSBR +R/hRNqrDH2MOV57v5KQIH2+mvy26tRG+tVGHmLMaOJeQkjLdxx+az8RfXIrH +7hpAsoBb+g9jUDY1mUVavPk1T45GMpQH8u3kkzRvChfOst6533GyIZhE7FhN +KanC6ACabVFDUs6P9pK9RPQMp1qJfpA0XJFx5TCbVbPkvnkZd8K5Tl/tzNM1 +n32eRao4MKr9KDwoDL93S1yJgYTlYjy1XW/ewdedtX+B4koAoz/wSXDYO+GQ +Zu6ZSpKSEHTRPhchsJ4oICvpriVaJkn0/Z7H3YjNMB9U5RR9+GiIg1wY1Oa1 +S3WfuwrrI6eqfbQwj6PDNu3IKy6srEgvJwaofQALNBPSYWbauM2brc8qsD+t +n8jC/aD1aMcy00+9t3H/RVCjEOb3yKfUpAldIkEA2NTTnZpoDQDXeNYU2F/W +yhmFjJy8A0O4QOk2xnZK9kcxSRs0v8vI8HivvgWENoVPscsDC4742SSIe6SL +f/T08reIX11f0K70rMtLhtFMQdHdYOTNl6JzhkHPLr/f9MEZsBEQx52depnF +ARb3gXGbCt7BAi0OeCEBSbLr2yWuW4r55N0wRZSOBtgqgjsiHP7CDQSkbL6p +FPlQS1do9gBSHiNYvsmN1LN5bG+mhcVb0UjZub4mL0EqGadjDfDdRJmWqlX0 +r5dyMcOWQVy4O2cPqYFlcP9lk8buc5otcyVI2isrAFdlvBK29oK6jc52Aq5Q +0b2ESDlgX8WRgiOPPxK8dySKEeuIwngCtJyNTecP9Ug06TDsu0znZGCXJ+3P +8JOpykgA8EQdOZOYHbo76ZfB2SkklI5KeRA5IBjGs9G3TZ4PHLy2DIwsbWzS +H1g01o1x264nx1cJ+eEgUN/KIiGFIib42RS8Af4D5e+Vj54Rt3axq+ag3kI+ +53p8uotyu+SpvvXUP7Kv4xpQ/L6k41VM0rfrd9+DrlDVvSfxP2uh6I1TKF7A +CT5n8zguMbng4PGjxvyPBM5k62t6hN5fuw6Af0aZFexh+IjB/5wFQ6onSz23 +fBzMW4St7RgSs8fDg3lrM+5rwXiey1jxY1ddaxOoUsWRMvvdd7rZxRZQoN5v +AcI5iMkK/vvpQgC/sfzhtXtrJ2XOPZ+GVgi7VcuDLKSkdFMcPbGzO8SdxUnS +SLV5XTKqKND+Lrfx7DAoKi5wbDFHu5496/MHK5qP4tBe6sJ5bZc+KDJIH46e +wTV1oWtB5tV4q46hOb5WRcn/Wjz3HSKaGZgx5QbK1MfKTzD5CTUn+ArMockX +2wJhPnFK85U4rgv8iBuh9bRjyw+YaKf7Z3loXRiE1eRG6RzuPF0ZecFiDumk +AC/VUXynJhzePBLqzrQj0exanACdullN+pSfHiRWBxR2VFUkjoFP5X45GK3z +OstSH6FOkMVU4afqEmjsIwozDFIyin5EyWTtdhJe3szdJSGY23Tut+9hUatx +9FDFLESOd8z3tyQSNiLk/Hib+e/lbjxqbXBG/p/oyvP3N999PLUPtpKqtYkV +H0+18sNh9CVfojiJl44fzxe8yCnuefBjut2PxEN0EFRBPv9P2wWlmOxkPKUq +NrCJP0rDj5aONLrNZPrR8bZNdIShkZ/rKkoTuA0WMZ+xUlDRxAupdMkWAlrz +8IcwNcdDjPnkGObpN5Ctm3vK7UGSBmPeNqkXOYf3QTJ9gStJEd0F6+DzTN5C +KGt1IyuGwZqL2Yk51FDIIkr9ykEnBMaA39LS7GFHEDNGlW+fKC7AzA0zfoOr +fXZlHMBuqHtXqk3zrsHRqGGoocigg4ctrhD1UREYKj+eIj1TBiRdf7c6+COf +NIOmej8pX3FmZ4ui+dDA8r2ctgsWHrb4A6iiH+v1DRA61GtoaA/tNRggewXW +VXCZCGWyyTuyHGOqq5ozrv5MlzZLWD/KV/uDsAWmy20RAed1C4AzcXlpX25O +M4SNl47g5VRNJRtMqokc8j6TjZrzMDEwITAJBgUrDgMCGgUABBRrkIRuS5qg +BC8fv38mue8LZVcbHQQIUNrWKEnskCoCAggA EOF p12 = OpenSSL::PKCS12.new(str, "abc123") - assert_equal @mykey.to_der, p12.key.to_der + assert_equal Fixtures.pkey("rsa-1").to_der, p12.key.to_der assert_equal nil, p12.certificate assert_equal [], Array(p12.ca_certs) end def test_dup - p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert) + p12 = OpenSSL::PKCS12.create( + "pass", + "name", + @mykey, + @mycert, + nil, + DEFAULT_PBE_PKEYS, + DEFAULT_PBE_CERTS, + ) assert_equal p12.to_der, p12.dup.to_der end - - private - def assert_cert expected, actual - [ - :subject, - :issuer, - :serial, - :not_before, - :not_after, - ].each do |attribute| - assert_equal expected.send(attribute), actual.send(attribute) - end - assert_equal expected.to_der, actual.to_der - end - - def assert_include_cert cert, ary - der = cert.to_der - ary.each do |candidate| - if candidate.to_der == der - return true - end - end - false - end end end diff --git a/ruby/test/openssl/test_pkcs7.rb b/ruby/test/openssl/test_pkcs7.rb index 6437112b7..ba8b93d03 100644 --- a/ruby/test/openssl/test_pkcs7.rb +++ b/ruby/test/openssl/test_pkcs7.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -89,6 +89,24 @@ def test_signed assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s) end + def test_signed_add_signer + data = "aaaaa\nbbbbb\nccccc\n" + psi = OpenSSL::PKCS7::SignerInfo.new(@ee1_cert, @rsa1024, "sha256") + p7 = OpenSSL::PKCS7.new + p7.type = :signed + p7.add_signer(psi) + p7.add_certificate(@ee1_cert) + p7.add_certificate(@ca_cert) + p7.add_data(data) + + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + + assert_equal(true, p7.verify([], store)) + assert_equal(true, OpenSSL::PKCS7.new(p7.to_der).verify([], store)) + assert_equal(1, p7.signers.size) + end + def test_detached_sign store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) @@ -172,6 +190,28 @@ def test_set_type_encrypted assert_equal(:encrypted, p7.type) end + def test_smime + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + ca_certs = [@ca_cert] + + data = "aaaaa\r\nbbbbb\r\nccccc\r\n" + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) + p7 = OpenSSL::PKCS7.new(tmp.to_der) + smime = OpenSSL::PKCS7.write_smime(p7) + assert_equal(true, smime.start_with?(< "secp384r1", + }) + assert_instance_of OpenSSL::PKey::EC, pkey + assert_equal "secp384r1", pkey.group.curve_name + assert_equal nil, pkey.private_key + + # Invalid options are checked + assert_raise(OpenSSL::PKey::PKeyError) { + OpenSSL::PKey.generate_parameters("EC", "invalid" => "option") + } + + # Parameter generation callback is called + cb_called = [] + assert_raise(RuntimeError) { + OpenSSL::PKey.generate_parameters("DSA") { |*args| + cb_called << args + raise "exit!" if cb_called.size == 3 + } + } + assert_not_empty cb_called + end + + def test_s_generate_key + assert_raise(OpenSSL::PKey::PKeyError) { + # DSA key pair cannot be generated without parameters + OpenSSL::PKey.generate_key("DSA") + } + pkey_params = OpenSSL::PKey.generate_parameters("EC", { + "ec_paramgen_curve" => "secp384r1", + }) + pkey = OpenSSL::PKey.generate_key(pkey_params) + assert_instance_of OpenSSL::PKey::EC, pkey + assert_equal "secp384r1", pkey.group.curve_name + assert_not_equal nil, pkey.private_key + end + + def test_hmac_sign_verify + pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "abcd" }) + + hmac = OpenSSL::HMAC.new("abcd", "SHA256").update("data").digest + assert_equal hmac, pkey.sign("SHA256", "data") + + # EVP_PKEY_HMAC does not support verify + assert_raise(OpenSSL::PKey::PKeyError) { + pkey.verify("SHA256", "data", hmac) + } + end + + def test_ed25519 + # Test vector from RFC 8032 Section 7.1 TEST 2 + priv_pem = <<~EOF + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7 + -----END PRIVATE KEY----- + EOF + pub_pem = <<~EOF + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw= + -----END PUBLIC KEY----- + EOF + begin + priv = OpenSSL::PKey.read(priv_pem) + pub = OpenSSL::PKey.read(pub_pem) + rescue OpenSSL::PKey::PKeyError + # OpenSSL < 1.1.1 + pend "Ed25519 is not implemented" + end + assert_instance_of OpenSSL::PKey::PKey, priv + assert_instance_of OpenSSL::PKey::PKey, pub + assert_equal priv_pem, priv.private_to_pem + assert_equal pub_pem, priv.public_to_pem + assert_equal pub_pem, pub.public_to_pem + + sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*") + 92a009a9f0d4cab8720e820b5f642540 + a2b27b5416503f8fb3762223ebdb69da + 085ac1e43e15996e458f3613d0f11d8c + 387b2eaeb4302aeeb00d291612bb0c00 + EOF + data = ["72"].pack("H*") + assert_equal sig, priv.sign(nil, data) + assert_equal true, priv.verify(nil, sig, data) + assert_equal true, pub.verify(nil, sig, data) + assert_equal false, pub.verify(nil, sig, data.succ) + + # PureEdDSA wants nil as the message digest + assert_raise(OpenSSL::PKey::PKeyError) { priv.sign("SHA512", data) } + assert_raise(OpenSSL::PKey::PKeyError) { pub.verify("SHA512", sig, data) } + + # Ed25519 pkey type does not support key derivation + assert_raise(OpenSSL::PKey::PKeyError) { priv.derive(pub) } + end + + def test_x25519 + # Test vector from RFC 7748 Section 6.1 + alice_pem = <<~EOF + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VuBCIEIHcHbQpzGKV9PBbBclGyZkXfTC+H68CZKrF3+6UduSwq + -----END PRIVATE KEY----- + EOF + bob_pem = <<~EOF + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VuAyEA3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08= + -----END PUBLIC KEY----- + EOF + shared_secret = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" + begin + alice = OpenSSL::PKey.read(alice_pem) + bob = OpenSSL::PKey.read(bob_pem) + rescue OpenSSL::PKey::PKeyError + # OpenSSL < 1.1.0 + pend "X25519 is not implemented" + end + assert_instance_of OpenSSL::PKey::PKey, alice + assert_equal alice_pem, alice.private_to_pem + assert_equal bob_pem, bob.public_to_pem + assert_equal [shared_secret].pack("H*"), alice.derive(bob) + end + + def test_compare? + key1 = Fixtures.pkey("rsa1024") + key2 = Fixtures.pkey("rsa1024") + key3 = Fixtures.pkey("rsa2048") + key4 = Fixtures.pkey("dh-1") + + assert_equal(true, key1.compare?(key2)) + assert_equal(true, key1.public_key.compare?(key2)) + assert_equal(true, key2.compare?(key1)) + assert_equal(true, key2.public_key.compare?(key1)) + + assert_equal(false, key1.compare?(key3)) + + assert_raise(TypeError) do + key1.compare?(key4) + end + end + + def test_to_text + rsa = Fixtures.pkey("rsa1024") + assert_include rsa.to_text, "publicExponent" + end +end diff --git a/ruby/test/openssl/test_pkey_dh.rb b/ruby/test/openssl/test_pkey_dh.rb index 8c8fbaeef..161af1897 100644 --- a/ruby/test/openssl/test_pkey_dh.rb +++ b/ruby/test/openssl/test_pkey_dh.rb @@ -1,15 +1,22 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH) class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase - NEW_KEYLEN = 256 + NEW_KEYLEN = 2048 - def test_new + def test_new_empty + dh = OpenSSL::PKey::DH.new + assert_equal nil, dh.p + assert_equal nil, dh.priv_key + end + + def test_new_generate + # This test is slow dh = OpenSSL::PKey::DH.new(NEW_KEYLEN) assert_key(dh) - end + end if ENV["OSSL_TEST_ALL"] def test_new_break assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) @@ -18,14 +25,34 @@ def test_new_break end end + def test_derive_key + params = Fixtures.pkey("dh1024") + dh1 = OpenSSL::PKey.generate_key(params) + dh2 = OpenSSL::PKey.generate_key(params) + dh1_pub = OpenSSL::PKey.read(dh1.public_to_der) + dh2_pub = OpenSSL::PKey.read(dh2.public_to_der) + + z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2) + assert_equal z, dh1.derive(dh2_pub) + assert_equal z, dh2.derive(dh1_pub) + + assert_raise(OpenSSL::PKey::PKeyError) { params.derive(dh1_pub) } + assert_raise(OpenSSL::PKey::PKeyError) { dh1_pub.derive(params) } + + assert_equal z, dh1.compute_key(dh2.pub_key) + assert_equal z, dh2.compute_key(dh1.pub_key) + end + def test_DHparams dh1024 = Fixtures.pkey("dh1024") + dh1024params = dh1024.public_key + asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(dh1024.p), OpenSSL::ASN1::Integer(dh1024.g) ]) key = OpenSSL::PKey::DH.new(asn1.to_der) - assert_same_dh dup_public(dh1024), key + assert_same_dh dh1024params, key pem = <<~EOF -----BEGIN DH PARAMETERS----- @@ -35,7 +62,9 @@ def test_DHparams -----END DH PARAMETERS----- EOF key = OpenSSL::PKey::DH.new(pem) - assert_same_dh dup_public(dh1024), key + assert_same_dh dh1024params, key + key = OpenSSL::PKey.read(pem) + assert_same_dh dh1024params, key assert_equal asn1.to_der, dh1024.to_der assert_equal pem, dh1024.export @@ -50,37 +79,71 @@ def test_public_key end def test_generate_key - dh = Fixtures.pkey("dh1024").public_key # creates a copy + # Deprecated in v3.0.0; incompatible with OpenSSL 3.0 + dh = Fixtures.pkey("dh1024").public_key # creates a copy with params only assert_no_key(dh) dh.generate_key! assert_key(dh) - end - def test_key_exchange - dh = Fixtures.pkey("dh1024") dh2 = dh.public_key - dh.generate_key! dh2.generate_key! assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key)) + end if !openssl?(3, 0, 0) + + def test_params_ok? + dh0 = Fixtures.pkey("dh1024") + + dh1 = OpenSSL::PKey::DH.new(OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(dh0.p), + OpenSSL::ASN1::Integer(dh0.g) + ])) + assert_equal(true, dh1.params_ok?) + + dh2 = OpenSSL::PKey::DH.new(OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(dh0.p + 1), + OpenSSL::ASN1::Integer(dh0.g) + ])) + assert_equal(false, dh2.params_ok?) end def test_dup - dh = OpenSSL::PKey::DH.new(NEW_KEYLEN) - dh2 = dh.dup - assert_equal dh.to_der, dh2.to_der # params - assert_equal_params dh, dh2 # keys - dh2.set_pqg(dh2.p + 1, nil, dh2.g) - assert_not_equal dh2.p, dh.p - assert_equal dh2.g, dh.g + # Parameters only + dh1 = Fixtures.pkey("dh1024") + dh2 = dh1.dup + assert_equal dh1.to_der, dh2.to_der + assert_not_equal nil, dh1.p + assert_not_equal nil, dh1.g + assert_equal [dh1.p, dh1.g], [dh2.p, dh2.g] + assert_equal nil, dh1.pub_key + assert_equal nil, dh1.priv_key + assert_equal [dh1.pub_key, dh1.priv_key], [dh2.pub_key, dh2.priv_key] + + # PKey is immutable in OpenSSL >= 3.0 + if !openssl?(3, 0, 0) + dh2.set_pqg(dh2.p + 1, nil, dh2.g) + assert_not_equal dh2.p, dh1.p + end + + # With a key pair + dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024")) + dh4 = dh3.dup + assert_equal dh3.to_der, dh4.to_der + assert_equal dh1.to_der, dh4.to_der # encodes parameters only + assert_equal [dh1.p, dh1.g], [dh4.p, dh4.g] + assert_not_equal nil, dh3.pub_key + assert_not_equal nil, dh3.priv_key + assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key] end - private + def test_marshal + dh = Fixtures.pkey("dh1024") + deserialized = Marshal.load(Marshal.dump(dh)) - def assert_equal_params(dh1, dh2) - assert_equal(dh1.g, dh2.g) - assert_equal(dh1.p, dh2.p) + assert_equal dh.to_der, deserialized.to_der end + private + def assert_no_key(dh) assert_equal(false, dh.public?) assert_equal(false, dh.private?) diff --git a/ruby/test/openssl/test_pkey_dsa.rb b/ruby/test/openssl/test_pkey_dsa.rb index d65194984..726b7dbf7 100644 --- a/ruby/test/openssl/test_pkey_dsa.rb +++ b/ruby/test/openssl/test_pkey_dsa.rb @@ -1,35 +1,30 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) && defined?(OpenSSL::PKey::DSA) class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase def test_private - key = OpenSSL::PKey::DSA.new(256) - assert(key.private?) + key = Fixtures.pkey("dsa1024") + assert_equal true, key.private? key2 = OpenSSL::PKey::DSA.new(key.to_der) - assert(key2.private?) + assert_equal true, key2.private? key3 = key.public_key - assert(!key3.private?) + assert_equal false, key3.private? key4 = OpenSSL::PKey::DSA.new(key3.to_der) - assert(!key4.private?) + assert_equal false, key4.private? end def test_new - key = OpenSSL::PKey::DSA.new 256 + key = OpenSSL::PKey::DSA.new(2048) pem = key.public_key.to_pem OpenSSL::PKey::DSA.new pem - if $0 == __FILE__ - assert_nothing_raised { - key = OpenSSL::PKey::DSA.new 2048 - } - end end def test_new_break - assert_nil(OpenSSL::PKey::DSA.new(512) { break }) + assert_nil(OpenSSL::PKey::DSA.new(2048) { break }) assert_raise(RuntimeError) do - OpenSSL::PKey::DSA.new(512) { raise } + OpenSSL::PKey::DSA.new(2048) { raise } end end @@ -37,8 +32,8 @@ def test_sign_verify dsa512 = Fixtures.pkey("dsa512") data = "Sign me!" if defined?(OpenSSL::Digest::DSS1) - signature = dsa512.sign(OpenSSL::Digest::DSS1.new, data) - assert_equal true, dsa512.verify(OpenSSL::Digest::DSS1.new, signature, data) + signature = dsa512.sign(OpenSSL::Digest.new('DSS1'), data) + assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data) end signature = dsa512.sign("SHA1", data) @@ -53,12 +48,31 @@ def test_sign_verify assert_equal false, dsa512.verify("SHA256", signature1, data) end - def test_sys_sign_verify - key = Fixtures.pkey("dsa256") + def test_sign_verify_raw + key = Fixtures.pkey("dsa512") data = 'Sign me!' - digest = OpenSSL::Digest::SHA1.digest(data) + digest = OpenSSL::Digest.digest('SHA1', data) + + invalid_sig = key.sign_raw(nil, digest.succ) + malformed_sig = "*" * invalid_sig.bytesize + + # Sign by #syssign sig = key.syssign(digest) - assert(key.sysverify(digest, sig)) + assert_equal true, key.sysverify(digest, sig) + assert_equal false, key.sysverify(digest, invalid_sig) + assert_raise(OpenSSL::PKey::DSAError) { key.sysverify(digest, malformed_sig) } + assert_equal true, key.verify_raw(nil, sig, digest) + assert_equal false, key.verify_raw(nil, invalid_sig, digest) + assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, digest) } + + # Sign by #sign_raw + sig = key.sign_raw(nil, digest) + assert_equal true, key.sysverify(digest, sig) + assert_equal false, key.sysverify(digest, invalid_sig) + assert_raise(OpenSSL::PKey::DSAError) { key.sysverify(digest, malformed_sig) } + assert_equal true, key.verify_raw(nil, sig, digest) + assert_equal false, key.verify_raw(nil, invalid_sig, digest) + assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, digest) } end def test_DSAPrivateKey @@ -124,6 +138,8 @@ def test_DSAPrivateKey_encrypted def test_PUBKEY dsa512 = Fixtures.pkey("dsa512") + dsa512pub = OpenSSL::PKey::DSA.new(dsa512.public_to_der) + asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("DSA"), @@ -139,7 +155,7 @@ def test_PUBKEY ]) key = OpenSSL::PKey::DSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_dsa dup_public(dsa512), key + assert_same_dsa dsa512pub, key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -152,10 +168,15 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::DSA.new(pem) - assert_same_dsa dup_public(dsa512), key + assert_same_dsa dsa512pub, key + + assert_equal asn1.to_der, key.to_der + assert_equal pem, key.export - assert_equal asn1.to_der, dup_public(dsa512).to_der - assert_equal pem, dup_public(dsa512).export + assert_equal asn1.to_der, dsa512.public_to_der + assert_equal asn1.to_der, key.public_to_der + assert_equal pem, dsa512.public_to_pem + assert_equal pem, key.public_to_pem end def test_read_DSAPublicKey_pem @@ -184,11 +205,22 @@ def test_read_DSAPublicKey_pem end def test_dup - key = OpenSSL::PKey::DSA.new(256) + key = Fixtures.pkey("dsa1024") key2 = key.dup assert_equal key.params, key2.params - key2.set_pqg(key2.p + 1, key2.q, key2.g) - assert_not_equal key.params, key2.params + + # PKey is immutable in OpenSSL >= 3.0 + if !openssl?(3, 0, 0) + key2.set_pqg(key2.p + 1, key2.q, key2.g) + assert_not_equal key.params, key2.params + end + end + + def test_marshal + key = Fixtures.pkey("dsa1024") + deserialized = Marshal.load(Marshal.dump(key)) + + assert_equal key.to_der, deserialized.to_der end private diff --git a/ruby/test/openssl/test_pkey_ec.rb b/ruby/test/openssl/test_pkey_ec.rb index 95b5a6426..ffe5a94e5 100644 --- a/ruby/test/openssl/test_pkey_ec.rb +++ b/ruby/test/openssl/test_pkey_ec.rb @@ -1,7 +1,7 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' -if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC) +if defined?(OpenSSL) class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_ec_key @@ -13,21 +13,23 @@ def test_ec_key # FIPS-selftest failure on some environment, so skip for now. next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) } - key = OpenSSL::PKey::EC.new(curve_name) - key.generate_key! - + key = OpenSSL::PKey::EC.generate(curve_name) assert_predicate key, :private? assert_predicate key, :public? assert_nothing_raised { key.check_key } end - key1 = OpenSSL::PKey::EC.new("prime256v1").generate_key! + key1 = OpenSSL::PKey::EC.generate("prime256v1") - key2 = OpenSSL::PKey::EC.new - key2.group = key1.group - key2.private_key = key1.private_key - key2.public_key = key1.public_key - assert_equal key1.to_der, key2.to_der + # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is + # deprecated + if !openssl?(3, 0, 0) + key2 = OpenSSL::PKey::EC.new + key2.group = key1.group + key2.private_key = key1.private_key + key2.public_key = key1.public_key + assert_equal key1.to_der, key2.to_der + end key3 = OpenSSL::PKey::EC.new(key1) assert_equal key1.to_der, key3.to_der @@ -37,10 +39,14 @@ def test_ec_key key5 = key1.dup assert_equal key1.to_der, key5.to_der - key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key! - key5.private_key = key_tmp.private_key - key5.public_key = key_tmp.public_key - assert_not_equal key1.to_der, key5.to_der + + # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified + if !openssl?(3, 0, 0) + key_tmp = OpenSSL::PKey::EC.generate("prime256v1") + key5.private_key = key_tmp.private_key + key5.public_key = key_tmp.public_key + assert_not_equal key1.to_der, key5.to_der + end end def test_generate @@ -52,23 +58,41 @@ def test_generate assert_equal(true, ec.private?) end + def test_generate_key + ec = OpenSSL::PKey::EC.new("prime256v1") + assert_equal false, ec.private? + ec.generate_key! + assert_equal true, ec.private? + end if !openssl?(3, 0, 0) + + def test_marshal + key = Fixtures.pkey("p256") + deserialized = Marshal.load(Marshal.dump(key)) + + assert_equal key.to_der, deserialized.to_der + end + def test_check_key - key = OpenSSL::PKey::EC.new("prime256v1").generate_key! - assert_equal(true, key.check_key) - assert_equal(true, key.private?) - assert_equal(true, key.public?) - key2 = OpenSSL::PKey::EC.new(key.group) - assert_equal(false, key2.private?) - assert_equal(false, key2.public?) - key2.public_key = key.public_key - assert_equal(false, key2.private?) - assert_equal(true, key2.public?) - key2.private_key = key.private_key + key0 = Fixtures.pkey("p256") + assert_equal(true, key0.check_key) + assert_equal(true, key0.private?) + assert_equal(true, key0.public?) + + key1 = OpenSSL::PKey.read(key0.public_to_der) + assert_equal(true, key1.check_key) + assert_equal(false, key1.private?) + assert_equal(true, key1.public?) + + key2 = OpenSSL::PKey.read(key0.private_to_der) assert_equal(true, key2.private?) assert_equal(true, key2.public?) assert_equal(true, key2.check_key) - key2.private_key += 1 - assert_raise(OpenSSL::PKey::ECError) { key2.check_key } + + # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0 + if !openssl?(3, 0, 0) + key2.private_key += 1 + assert_raise(OpenSSL::PKey::ECError) { key2.check_key } + end end def test_sign_verify @@ -86,17 +110,50 @@ def test_sign_verify assert_equal false, p256.verify("SHA256", signature1, data) end - def test_dsa_sign_verify + def test_derive_key + # NIST CAVP, KAS_ECC_CDH_PrimitiveTest.txt, P-256 COUNT = 0 + qCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287" + qCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac" + dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534" + zIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b" + a = OpenSSL::PKey::EC.new("prime256v1") + a.private_key = OpenSSL::BN.new(dIUT, 16) + b = OpenSSL::PKey::EC.new("prime256v1") + uncompressed = OpenSSL::BN.new("04" + qCAVSx + qCAVSy, 16) + b.public_key = OpenSSL::PKey::EC::Point.new(b.group, uncompressed) + assert_equal [zIUT].pack("H*"), a.derive(b) + + assert_equal a.derive(b), a.dh_compute_key(b.public_key) + end if !openssl?(3, 0, 0) # TODO: Test it without using #private_key= + + def test_sign_verify_raw + key = Fixtures.pkey("p256") data1 = "foo" data2 = "bar" - key = OpenSSL::PKey::EC.new("prime256v1").generate_key! + + malformed_sig = "*" * 30 + + # Sign by #dsa_sign_asn1 sig = key.dsa_sign_asn1(data1) assert_equal true, key.dsa_verify_asn1(data1, sig) assert_equal false, key.dsa_verify_asn1(data2, sig) + assert_raise(OpenSSL::PKey::ECError) { key.dsa_verify_asn1(data1, malformed_sig) } + assert_equal true, key.verify_raw(nil, sig, data1) + assert_equal false, key.verify_raw(nil, sig, data2) + assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, data1) } + + # Sign by #sign_raw + sig = key.sign_raw(nil, data1) + assert_equal true, key.dsa_verify_asn1(data1, sig) + assert_equal false, key.dsa_verify_asn1(data2, sig) + assert_raise(OpenSSL::PKey::ECError) { key.dsa_verify_asn1(data1, malformed_sig) } + assert_equal true, key.verify_raw(nil, sig, data1) + assert_equal false, key.verify_raw(nil, sig, data2) + assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, data1) } end def test_dsa_sign_asn1_FIPS186_3 - key = OpenSSL::PKey::EC.new("prime256v1").generate_key! + key = OpenSSL::PKey::EC.generate("prime256v1") size = key.group.order.num_bits / 8 + 1 dgst = (1..size).to_a.pack('C*') sig = key.dsa_sign_asn1(dgst) @@ -105,8 +162,8 @@ def test_dsa_sign_asn1_FIPS186_3 end def test_dh_compute_key - key_a = OpenSSL::PKey::EC.new("prime256v1").generate_key! - key_b = OpenSSL::PKey::EC.new(key_a.group).generate_key! + key_a = OpenSSL::PKey::EC.generate("prime256v1") + key_b = OpenSSL::PKey::EC.generate(key_a.group) pub_a = key_a.public_key pub_b = key_b.public_key @@ -170,6 +227,8 @@ def test_ECPrivateKey_encrypted def test_PUBKEY p256 = Fixtures.pkey("p256") + p256pub = OpenSSL::PKey::EC.new(p256.public_to_der) + asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("id-ecPublicKey"), @@ -181,7 +240,7 @@ def test_PUBKEY ]) key = OpenSSL::PKey::EC.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_ec dup_public(p256), key + assert_same_ec p256pub, key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -190,10 +249,15 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::EC.new(pem) - assert_same_ec dup_public(p256), key + assert_same_ec p256pub, key + + assert_equal asn1.to_der, key.to_der + assert_equal pem, key.export - assert_equal asn1.to_der, dup_public(p256).to_der - assert_equal pem, dup_public(p256).export + assert_equal asn1.to_der, p256.public_to_der + assert_equal asn1.to_der, key.public_to_der + assert_equal pem, p256.public_to_pem + assert_equal pem, key.public_to_pem end def test_ec_group @@ -229,7 +293,7 @@ def test_ec_group def test_ec_point group = OpenSSL::PKey::EC::Group.new("prime256v1") - key = OpenSSL::PKey::EC.new(group).generate_key! + key = OpenSSL::PKey::EC.generate(group) point = key.public_key point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn) @@ -289,6 +353,27 @@ def test_ec_point assert_equal true, point.on_curve? end + def test_ec_point_add + begin + group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) + group.point_conversion_form = :uncompressed + gen = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 })) + group.set_generator(gen, 19, 1) + + point_a = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 })) + point_b = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 10 0D })) + rescue OpenSSL::PKey::EC::Group::Error + pend "Patched OpenSSL rejected curve" if /unsupported field/ =~ $!.message + raise + end + + result = point_a.add(point_b) + assert_equal B(%w{ 04 0D 07 }), result.to_octet_string(:uncompressed) + + assert_raise(TypeError) { point_a.add(nil) } + assert_raise(ArgumentError) { point_a.add } + end + def test_ec_point_mul begin # y^2 = x^3 + 2x + 2 over F_17 @@ -305,21 +390,28 @@ def test_ec_point_mul # 3 * (6, 3) + 3 * (5, 1) = (7, 6) result_a2 = point_a.mul(3, 3) assert_equal B(%w{ 04 07 06 }), result_a2.to_octet_string(:uncompressed) - # 3 * point_a = 3 * (6, 3) = (16, 13) - result_b1 = point_a.mul([3], []) - assert_equal B(%w{ 04 10 0D }), result_b1.to_octet_string(:uncompressed) - # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) - begin + EnvUtil.suppress_warning do # Point#mul(ary, ary [, bn]) is deprecated + begin + result_b1 = point_a.mul([3], []) + rescue NotImplementedError + # LibreSSL and OpenSSL 3.0 do no longer support this form of calling + next + end + + # 3 * point_a = 3 * (6, 3) = (16, 13) + result_b1 = point_a.mul([3], []) + assert_equal B(%w{ 04 10 0D }), result_b1.to_octet_string(:uncompressed) + # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) result_b1 = point_a.mul([3, 2], [point_a]) - rescue OpenSSL::PKey::EC::Point::Error - # LibreSSL doesn't support multiple entries in first argument - raise if $!.message !~ /called a function you should not call/ - else assert_equal B(%w{ 04 07 0B }), result_b1.to_octet_string(:uncompressed) + # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) + result_b1 = point_a.mul([3], [], 5) + assert_equal B(%w{ 04 0D 0A }), result_b1.to_octet_string(:uncompressed) + + assert_raise(ArgumentError) { point_a.mul([1], [point_a]) } + assert_raise(TypeError) { point_a.mul([1], nil) } + assert_raise(TypeError) { point_a.mul([nil], []) } end - # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) - result_b1 = point_a.mul([3], [], 5) - assert_equal B(%w{ 04 0D 0A }), result_b1.to_octet_string(:uncompressed) rescue OpenSSL::PKey::EC::Group::Error # CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits raise if $!.message !~ /unsupported field/ @@ -332,9 +424,6 @@ def test_ec_point_mul # invalid argument point = p256_key.public_key assert_raise(TypeError) { point.mul(nil) } - assert_raise(ArgumentError) { point.mul([1], [point]) } - assert_raise(TypeError) { point.mul([1], nil) } - assert_raise(TypeError) { point.mul([nil], []) } end # test Group: asn1_flag, point_conversion diff --git a/ruby/test/openssl/test_pkey_rsa.rb b/ruby/test/openssl/test_pkey_rsa.rb index ef02717d8..4bb39ed4a 100644 --- a/ruby/test/openssl/test_pkey_rsa.rb +++ b/ruby/test/openssl/test_pkey_rsa.rb @@ -1,70 +1,73 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase - def test_padding - key = OpenSSL::PKey::RSA.new(512, 3) - - # Need right size for raw mode - plain0 = "x" * (512/8) - cipher = key.private_encrypt(plain0, OpenSSL::PKey::RSA::NO_PADDING) - plain1 = key.public_decrypt(cipher, OpenSSL::PKey::RSA::NO_PADDING) - assert_equal(plain0, plain1) - - # Need smaller size for pkcs1 mode - plain0 = "x" * (512/8 - 11) - cipher1 = key.private_encrypt(plain0, OpenSSL::PKey::RSA::PKCS1_PADDING) - plain1 = key.public_decrypt(cipher1, OpenSSL::PKey::RSA::PKCS1_PADDING) - assert_equal(plain0, plain1) - - cipherdef = key.private_encrypt(plain0) # PKCS1_PADDING is default - plain1 = key.public_decrypt(cipherdef) - assert_equal(plain0, plain1) - assert_equal(cipher1, cipherdef) - - # Failure cases - assert_raise(ArgumentError){ key.private_encrypt() } - assert_raise(ArgumentError){ key.private_encrypt("hi", 1, nil) } - assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt(plain0, 666) } - end + def test_no_private_exp + key = OpenSSL::PKey::RSA.new + rsa = Fixtures.pkey("rsa2048") + key.set_key(rsa.n, rsa.e, nil) + key.set_factors(rsa.p, rsa.q) + assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt("foo") } + assert_raise(OpenSSL::PKey::RSAError){ key.private_decrypt("foo") } + end if !openssl?(3, 0, 0) # Impossible state in OpenSSL 3.0 def test_private + # Generated by key size and public exponent key = OpenSSL::PKey::RSA.new(512, 3) assert(key.private?) + + # Generated by DER key2 = OpenSSL::PKey::RSA.new(key.to_der) assert(key2.private?) + + # public key key3 = key.public_key assert(!key3.private?) + + # Generated by public key DER key4 = OpenSSL::PKey::RSA.new(key3.to_der) assert(!key4.private?) + rsa1024 = Fixtures.pkey("rsa1024") + + if !openssl?(3, 0, 0) + key = OpenSSL::PKey::RSA.new + # Generated by RSA#set_key + key5 = OpenSSL::PKey::RSA.new + key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d) + assert(key5.private?) + + # Generated by RSA#set_key, without d + key6 = OpenSSL::PKey::RSA.new + key6.set_key(rsa1024.n, rsa1024.e, nil) + assert(!key6.private?) + end end def test_new - key = OpenSSL::PKey::RSA.new 512 - pem = key.public_key.to_pem - OpenSSL::PKey::RSA.new pem - assert_equal([], OpenSSL.errors) - end + key = OpenSSL::PKey::RSA.new(512) + assert_equal 512, key.n.num_bits + assert_equal 65537, key.e + assert_not_nil key.d - def test_new_exponent_default - assert_equal(65537, OpenSSL::PKey::RSA.new(512).e) + # Specify public exponent + key2 = OpenSSL::PKey::RSA.new(512, 3) + assert_equal 512, key2.n.num_bits + assert_equal 3, key2.e + assert_not_nil key2.d end - def test_new_with_exponent - 1.upto(30) do |idx| - e = (2 ** idx) + 1 - key = OpenSSL::PKey::RSA.new(512, e) - assert_equal(e, key.e) - end - end + def test_s_generate + key1 = OpenSSL::PKey::RSA.generate(512) + assert_equal 512, key1.n.num_bits + assert_equal 65537, key1.e - def test_generate - key = OpenSSL::PKey::RSA.generate(512, 17) - assert_equal 512, key.n.num_bits - assert_equal 17, key.e - assert_not_nil key.d + # Specify public exponent + key2 = OpenSSL::PKey::RSA.generate(512, 3) + assert_equal 512, key2.n.num_bits + assert_equal 3, key2.e + assert_not_nil key2.d end def test_new_break @@ -90,29 +93,75 @@ def test_sign_verify assert_equal false, rsa1024.verify("SHA256", signature1, data) end - def test_digest_state_irrelevant_sign + def test_sign_verify_options key = Fixtures.pkey("rsa1024") - digest1 = OpenSSL::Digest::SHA1.new - digest2 = OpenSSL::Digest::SHA1.new - data = 'Sign me!' - digest1 << 'Change state of digest1' - sig1 = key.sign(digest1, data) - sig2 = key.sign(digest2, data) - assert_equal(sig1, sig2) + data = "Sign me!" + pssopts = { + "rsa_padding_mode" => "pss", + "rsa_pss_saltlen" => 20, + "rsa_mgf1_md" => "SHA1" + } + sig_pss = key.sign("SHA256", data, pssopts) + assert_equal 128, sig_pss.bytesize + assert_equal true, key.verify("SHA256", sig_pss, data, pssopts) + assert_equal true, key.verify_pss("SHA256", sig_pss, data, + salt_length: 20, mgf1_hash: "SHA1") + # Defaults to PKCS #1 v1.5 padding => verification failure + assert_equal false, key.verify("SHA256", sig_pss, data) end - def test_digest_state_irrelevant_verify - key = Fixtures.pkey("rsa1024") - digest1 = OpenSSL::Digest::SHA1.new - digest2 = OpenSSL::Digest::SHA1.new - data = 'Sign me!' - sig = key.sign(digest1, data) - digest1.reset - digest1 << 'Change state of digest1' - assert(key.verify(digest1, sig, data)) - assert(key.verify(digest2, sig, data)) + def test_sign_verify_raw + key = Fixtures.pkey("rsa-1") + data = "Sign me!" + hash = OpenSSL::Digest.digest("SHA1", data) + signature = key.sign_raw("SHA1", hash) + assert_equal true, key.verify_raw("SHA1", signature, hash) + assert_equal true, key.verify("SHA1", signature, data) + + # Too long data + assert_raise(OpenSSL::PKey::PKeyError) { + key.sign_raw("SHA1", "x" * (key.n.num_bytes + 1)) + } + + # With options + pssopts = { + "rsa_padding_mode" => "pss", + "rsa_pss_saltlen" => 20, + "rsa_mgf1_md" => "SHA256" + } + sig_pss = key.sign_raw("SHA1", hash, pssopts) + assert_equal true, key.verify("SHA1", sig_pss, data, pssopts) + assert_equal true, key.verify_raw("SHA1", sig_pss, hash, pssopts) end + def test_sign_verify_raw_legacy + key = Fixtures.pkey("rsa-1") + bits = key.n.num_bits + + # Need right size for raw mode + plain0 = "x" * (bits/8) + cipher = key.private_encrypt(plain0, OpenSSL::PKey::RSA::NO_PADDING) + plain1 = key.public_decrypt(cipher, OpenSSL::PKey::RSA::NO_PADDING) + assert_equal(plain0, plain1) + + # Need smaller size for pkcs1 mode + plain0 = "x" * (bits/8 - 11) + cipher1 = key.private_encrypt(plain0, OpenSSL::PKey::RSA::PKCS1_PADDING) + plain1 = key.public_decrypt(cipher1, OpenSSL::PKey::RSA::PKCS1_PADDING) + assert_equal(plain0, plain1) + + cipherdef = key.private_encrypt(plain0) # PKCS1_PADDING is default + plain1 = key.public_decrypt(cipherdef) + assert_equal(plain0, plain1) + assert_equal(cipher1, cipherdef) + + # Failure cases + assert_raise(ArgumentError){ key.private_encrypt() } + assert_raise(ArgumentError){ key.private_encrypt("hi", 1, nil) } + assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt(plain0, 666) } + end + + def test_verify_empty_rsa rsa = OpenSSL::PKey::RSA.new assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") { @@ -153,6 +202,90 @@ def test_sign_verify_pss } end + def test_encrypt_decrypt + rsapriv = Fixtures.pkey("rsa-1") + rsapub = OpenSSL::PKey.read(rsapriv.public_to_der) + + # Defaults to PKCS #1 v1.5 + raw = "data" + enc = rsapub.encrypt(raw) + assert_equal raw, rsapriv.decrypt(enc) + + # Invalid options + assert_raise(OpenSSL::PKey::PKeyError) { + rsapub.encrypt(raw, { "nonexistent" => "option" }) + } + end + + def test_encrypt_decrypt_legacy + rsapriv = Fixtures.pkey("rsa-1") + rsapub = OpenSSL::PKey.read(rsapriv.public_to_der) + + # Defaults to PKCS #1 v1.5 + raw = "data" + enc_legacy = rsapub.public_encrypt(raw) + assert_equal raw, rsapriv.decrypt(enc_legacy) + enc_new = rsapub.encrypt(raw) + assert_equal raw, rsapriv.private_decrypt(enc_new) + + # OAEP with default parameters + raw = "data" + enc_legacy = rsapub.public_encrypt(raw, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) + assert_equal raw, rsapriv.decrypt(enc_legacy, { "rsa_padding_mode" => "oaep" }) + enc_new = rsapub.encrypt(raw, { "rsa_padding_mode" => "oaep" }) + assert_equal raw, rsapriv.private_decrypt(enc_legacy, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) + end + + def test_export + rsa1024 = Fixtures.pkey("rsa1024") + + pub = OpenSSL::PKey.read(rsa1024.public_to_der) + assert_not_equal rsa1024.export, pub.export + assert_equal rsa1024.public_to_pem, pub.export + + # PKey is immutable in OpenSSL >= 3.0 + if !openssl?(3, 0, 0) + key = OpenSSL::PKey::RSA.new + + # key has only n, e and d + key.set_key(rsa1024.n, rsa1024.e, rsa1024.d) + assert_equal rsa1024.public_key.export, key.export + + # key has only n, e, d, p and q + key.set_factors(rsa1024.p, rsa1024.q) + assert_equal rsa1024.public_key.export, key.export + + # key has n, e, d, p, q, dmp1, dmq1 and iqmp + key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp) + assert_equal rsa1024.export, key.export + end + end + + def test_to_der + rsa1024 = Fixtures.pkey("rsa1024") + + pub = OpenSSL::PKey.read(rsa1024.public_to_der) + assert_not_equal rsa1024.to_der, pub.to_der + assert_equal rsa1024.public_to_der, pub.to_der + + # PKey is immutable in OpenSSL >= 3.0 + if !openssl?(3, 0, 0) + key = OpenSSL::PKey::RSA.new + + # key has only n, e and d + key.set_key(rsa1024.n, rsa1024.e, rsa1024.d) + assert_equal rsa1024.public_key.to_der, key.to_der + + # key has only n, e, d, p and q + key.set_factors(rsa1024.p, rsa1024.q) + assert_equal rsa1024.public_key.to_der, key.to_der + + # key has n, e, d, p, q, dmp1, dmq1 and iqmp + key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp) + assert_equal rsa1024.to_der, key.to_der + end + end + def test_RSAPrivateKey rsa1024 = Fixtures.pkey("rsa1024") asn1 = OpenSSL::ASN1::Sequence([ @@ -192,6 +325,12 @@ def test_RSAPrivateKey assert_equal asn1.to_der, rsa1024.to_der assert_equal pem, rsa1024.export + + # Unknown PEM prepended + cert = issue_cert(OpenSSL::X509::Name.new([["CN", "nobody"]]), rsa1024, 1, [], nil, nil) + str = cert.to_text + cert.to_pem + rsa1024.to_pem + key = OpenSSL::PKey::RSA.new(str) + assert_same_rsa rsa1024, key end def test_RSAPrivateKey_encrypted @@ -232,13 +371,15 @@ def test_RSAPrivateKey_encrypted def test_RSAPublicKey rsa1024 = Fixtures.pkey("rsa1024") + rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der) + asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(rsa1024.n), OpenSSL::ASN1::Integer(rsa1024.e) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa dup_public(rsa1024), key + assert_same_rsa rsa1024pub, key pem = <<~EOF -----BEGIN RSA PUBLIC KEY----- @@ -248,11 +389,13 @@ def test_RSAPublicKey -----END RSA PUBLIC KEY----- EOF key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa dup_public(rsa1024), key + assert_same_rsa rsa1024pub, key end def test_PUBKEY rsa1024 = Fixtures.pkey("rsa1024") + rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der) + asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("rsaEncryption"), @@ -267,7 +410,7 @@ def test_PUBKEY ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa dup_public(rsa1024), key + assert_same_rsa rsa1024pub, key pem = <<~EOF -----BEGIN PUBLIC KEY----- @@ -278,10 +421,15 @@ def test_PUBKEY -----END PUBLIC KEY----- EOF key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa dup_public(rsa1024), key + assert_same_rsa rsa1024pub, key - assert_equal asn1.to_der, dup_public(rsa1024).to_der - assert_equal pem, dup_public(rsa1024).export + assert_equal asn1.to_der, key.to_der + assert_equal pem, key.export + + assert_equal asn1.to_der, rsa1024.public_to_der + assert_equal asn1.to_der, key.public_to_der + assert_equal pem, rsa1024.public_to_pem + assert_equal pem, key.public_to_pem end def test_pem_passwd @@ -295,12 +443,96 @@ def test_pem_passwd } end + def test_private_encoding + rsa1024 = Fixtures.pkey("rsa1024") + asn1 = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::ObjectId("rsaEncryption"), + OpenSSL::ASN1::Null(nil) + ]), + OpenSSL::ASN1::OctetString(rsa1024.to_der) + ]) + assert_equal asn1.to_der, rsa1024.private_to_der + assert_same_rsa rsa1024, OpenSSL::PKey.read(asn1.to_der) + + pem = <<~EOF + -----BEGIN PRIVATE KEY----- + MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMvCxLDUQKc+1P4+ + Q6AeFwYDvWfALb+cvzlUEadGoPE6qNWHsLFoo8RFgeyTgE8KQTduu1OE9Zz2SMcR + BDu5/1jWtsLPSVrI2ofLLBARUsWanVyki39DeB4u/xkP2mKGjAokPIwOI3oCthSZ + lzO9bj3voxTf6XngTqUX8l8URTmHAgMBAAECgYEApKX8xBqvJ7XI7Kypfo/x8MVC + 3rxW+1eQ2aVKIo4a7PKGjQz5RVIVyzqTUvSZoMTbkAxlSIbO5YfJpTnl3tFcOB6y + QMxqQPW/pl6Ni3EmRJdsRM5MsPBRZOfrXxOCdvXu1TWOS1S1TrvEr/TyL9eh2WCd + CGzpWgdO4KHce7vs7pECQQDv6DGoG5lHnvbvj9qSJb9K5ebRJc8S+LI7Uy5JHC0j + zsHTYPSqBXwPVQdGbgCEycnwwKzXzT2QxAQmJBQKun2ZAkEA2W3aeAE7Xi6zo2eG + 4Cx4UNMHMIdfBRS7VgoekwybGmcapqV0aBew5kHeWAmxP1WUZ/dgZh2QtM1VuiBA + qUqkHwJBAOJLCRvi/JB8N7z82lTk2i3R8gjyOwNQJv6ilZRMyZ9vFZFHcUE27zCf + Kb+bX03h8WPwupjMdfgpjShU+7qq8nECQQDBrmyc16QVyo40sgTgblyiysitvviy + ovwZsZv4q5MCmvOPnPUrwGbRRb2VONUOMOKpFiBl9lIv7HU//nj7FMVLAkBjUXED + 83dA8JcKM+HlioXEAxCzZVVhN+D63QwRwkN08xAPklfqDkcqccWDaZm2hdCtaYlK + funwYkrzI1OikQSs + -----END PRIVATE KEY----- + EOF + assert_equal pem, rsa1024.private_to_pem + assert_same_rsa rsa1024, OpenSSL::PKey.read(pem) + end + + def test_private_encoding_encrypted + rsa1024 = Fixtures.pkey("rsa1024") + encoded = rsa1024.private_to_der("aes-128-cbc", "abcdef") + asn1 = OpenSSL::ASN1.decode(encoded) # PKCS #8 EncryptedPrivateKeyInfo + assert_kind_of OpenSSL::ASN1::Sequence, asn1 + assert_equal 2, asn1.value.size + assert_not_equal rsa1024.private_to_der, encoded + assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef") + assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded) { "abcdef" } + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(encoded, "abcxyz") } + + encoded = rsa1024.private_to_pem("aes-128-cbc", "abcdef") + assert_match (/BEGIN ENCRYPTED PRIVATE KEY/), encoded.lines[0] + assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef") + + # certtool --load-privkey=test/fixtures/pkey/rsa1024.pem --to-p8 --password=abcdef + pem = <<~EOF + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIICojAcBgoqhkiG9w0BDAEDMA4ECLqajUdSNfzwAgIEkQSCAoCDWhxr1HUrKLXA + FsFGGQfPT0aKH4gZipaSXXQRl0KwifHwHoDtfo/mAkJVZMnUVOm1AQ4LTFS3EdTy + JUwICGEQHb7QAiokIRoi0K2yHhOxVO8qgbnWuisWpiT6Ru1jCqTs/wcqlqF7z2jM + oXDk/vuekKst1DDXDcHrzhDkwhCQWj6jt1r2Vwaryy0FyeqsWAgBDiK2LsnCgkGD + 21uhNZ/iWMG6tvY9hB8MDdiBJ41YdSG/AKLulAxQ1ibJz0Tasu66TmwFvWhBlME+ + QbqfgmkgWg5buu53SvDfCA47zXihclbtdfW+U3CJ9OJkx0535TVdZbuC1QgKXvG7 + 4iKGFRMWYJqZvZM3GL4xbC75AxjXZsdCfV81VjZxjeU6ung/NRzCuCUcmBOQzo1D + Vv6COwAa6ttQWM0Ti8oIQHdu5Qi+nuOEHDLxCxD962M37H99sEO5cESjmrGVxhEo + 373L4+11geGSCajdp0yiAGnXQfwaKta8cL693bRObN+b1Y+vqtDKH26N9a4R3qgg + 2XwgQ5GH5CODoXZpi0wxncXO+3YuuhGeArtzKSXLNxHzIMlY7wZX+0e9UU03zfV/ + aOe4/q5DpkNxgHePt0oEpamSKY5W3jzVi1dlFWsRjud1p/Grt2zjSWTYClBlJqG1 + A/3IeDZCu+acaePJjFyv5dFffIj2l4bAYB+LFrZlSu3F/EimO/dCDWJ9JGlMK0aF + l9brh7786Mo+YfyklaqMMEHBbbR2Es7PR6Gt7lrcIXmzy9XSsxT6IiD1rG9KKR3i + CQxTup6JAx9w1q+adL+Ypikoy3gGD/ccUY6TtPoCmkQwSCS+JqQnFlCiThDJbu+V + eqqUNkZq + -----END ENCRYPTED PRIVATE KEY----- + EOF + assert_same_rsa rsa1024, OpenSSL::PKey.read(pem, "abcdef") + end + def test_dup key = Fixtures.pkey("rsa1024") key2 = key.dup assert_equal key.params, key2.params - key2.set_key(key2.n, 3, key2.d) - assert_not_equal key.params, key2.params + + # PKey is immutable in OpenSSL >= 3.0 + if !openssl?(3, 0, 0) + key2.set_key(key2.n, 3, key2.d) + assert_not_equal key.params, key2.params + end + end + + def test_marshal + key = Fixtures.pkey("rsa2048") + deserialized = Marshal.load(Marshal.dump(key)) + + assert_equal key.to_der, deserialized.to_der end private diff --git a/ruby/test/openssl/test_random.rb b/ruby/test/openssl/test_random.rb index d5a374540..33af37572 100644 --- a/ruby/test/openssl/test_random.rb +++ b/ruby/test/openssl/test_random.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) diff --git a/ruby/test/openssl/test_ssl.rb b/ruby/test/openssl/test_ssl.rb index 45a9addf5..a7607da07 100644 --- a/ruby/test/openssl/test_ssl.rb +++ b/ruby/test/openssl/test_ssl.rb @@ -1,9 +1,20 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) class OpenSSL::TestSSL < OpenSSL::SSLTestCase + def test_bad_socket + bad_socket = Struct.new(:sync).new + assert_raise TypeError do + socket = OpenSSL::SSL::SSLSocket.new bad_socket + # if the socket is not a T_FILE, `connect` will segv because it tries + # to get the underlying file descriptor but the API it calls assumes + # the object type is T_FILE + socket.connect + end + end + def test_ctx_options ctx = OpenSSL::SSL::SSLContext.new @@ -56,6 +67,56 @@ def test_ssl_with_server_cert } end + def test_socket_open + start_server { |port| + begin + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port) + ssl.sync_close = true + ssl.connect + + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + ensure + ssl&.close + end + } + end + + def test_socket_open_with_context + start_server { |port| + begin + ctx = OpenSSL::SSL::SSLContext.new + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, context: ctx) + ssl.sync_close = true + ssl.connect + + assert_equal ssl.context, ctx + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + ensure + ssl&.close + end + } + end + + def test_socket_open_with_local_address_port_context + start_server { |port| + begin + # Guess a free port number + random_port = rand(49152..65535) + ctx = OpenSSL::SSL::SSLContext.new + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, "127.0.0.1", random_port, context: ctx) + ssl.sync_close = true + ssl.connect + + assert_equal ctx, ssl.context + assert_equal random_port, ssl.io.local_address.ip_port + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + rescue Errno::EADDRINUSE, Errno::EACCES + ensure + ssl&.close + end + } + end + def test_add_certificate ctx_proc = -> ctx { # Unset values set by start_server @@ -74,24 +135,13 @@ def test_add_certificate end def test_add_certificate_multiple_certs - pend "EC is not supported" unless defined?(OpenSSL::PKey::EC) - pend "TLS 1.2 is not supported" unless tls12_supported? - - # SSL_CTX_set0_chain() is needed for setting multiple certificate chains - add0_chain_supported = openssl?(1, 0, 2) - - if add0_chain_supported - ca2_key = Fixtures.pkey("rsa2048") - ca2_exts = [ - ["basicConstraints", "CA:TRUE", true], - ["keyUsage", "cRLSign, keyCertSign", true], - ] - ca2_dn = OpenSSL::X509::Name.parse_rfc2253("CN=CA2") - ca2_cert = issue_cert(ca2_dn, ca2_key, 123, ca2_exts, nil, nil) - else - # Use the same CA as @svr_cert - ca2_key = @ca_key; ca2_cert = @ca_cert - end + ca2_key = Fixtures.pkey("rsa-3") + ca2_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign, keyCertSign", true], + ] + ca2_dn = OpenSSL::X509::Name.parse_rfc2253("CN=CA2") + ca2_cert = issue_cert(ca2_dn, ca2_key, 123, ca2_exts, nil, nil) ecdsa_key = Fixtures.pkey("p256") exts = [ @@ -100,23 +150,11 @@ def test_add_certificate_multiple_certs ecdsa_dn = OpenSSL::X509::Name.parse_rfc2253("CN=localhost2") ecdsa_cert = issue_cert(ecdsa_dn, ecdsa_key, 456, exts, ca2_cert, ca2_key) - if !add0_chain_supported - # Testing the warning emitted when 'extra' chain is replaced - tctx = OpenSSL::SSL::SSLContext.new - tctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) - assert_warning(/set0_chain/) { - tctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert]) - } - end - ctx_proc = -> ctx { # Unset values set by start_server ctx.cert = ctx.key = ctx.extra_chain_cert = nil - ctx.ecdh_curves = "P-256" unless openssl?(1, 0, 2) ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA - EnvUtil.suppress_warning do # !add0_chain_supported - ctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert]) - end + ctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert]) } start_server(ctx_proc: ctx_proc) do |port| ctx = OpenSSL::SSL::SSLContext.new @@ -142,12 +180,12 @@ def test_add_certificate_multiple_certs def test_sysread_and_syswrite start_server { |port| server_connect(port) { |ssl| - str = "x" * 100 + "\n" + str = +("x" * 100 + "\n") ssl.syswrite(str) newstr = ssl.sysread(str.bytesize) assert_equal(str, newstr) - buf = "" + buf = String.new ssl.syswrite(str) assert_same buf, ssl.sysread(str.size, buf) assert_equal(str, buf) @@ -155,23 +193,21 @@ def test_sysread_and_syswrite } end - def test_sysread_nonblock_and_syswrite_nonblock_keywords - start_server(ignore_listener_error: true) do |port| - sock = TCPSocket.new("127.0.0.1", port) - ssl = OpenSSL::SSL::SSLSocket.new(sock) - - assert_warn ("") do - ssl.send(:syswrite_nonblock, "1", exception: false) - ssl.send(:sysread_nonblock, 1, exception: false) rescue nil - ssl.send(:sysread_nonblock, 1, String.new, exception: false) rescue nil - end - ensure - sock&.close - end + def test_getbyte + start_server { |port| + server_connect(port) { |ssl| + str = +("x" * 100 + "\n") + ssl.syswrite(str) + newstr = str.bytesize.times.map { |i| + ssl.getbyte + }.pack("C*") + assert_equal(str, newstr) + } + } end def test_sync_close - start_server { |port| + start_server do |port| begin sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) @@ -194,7 +230,7 @@ def test_sync_close ensure sock&.close end - } + end end def test_copy_stream @@ -211,7 +247,56 @@ def test_copy_stream end end - def test_client_auth_failure + def test_verify_mode_default + ctx = OpenSSL::SSL::SSLContext.new + assert_equal OpenSSL::SSL::VERIFY_NONE, ctx.verify_mode + end + + def test_verify_mode_server_cert + start_server(ignore_listener_error: true) { |port| + populated_store = OpenSSL::X509::Store.new + populated_store.add_cert(@ca_cert) + empty_store = OpenSSL::X509::Store.new + + # Valid certificate, SSL_VERIFY_PEER + assert_nothing_raised { + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.cert_store = populated_store + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } + + # Invalid certificate, SSL_VERIFY_NONE + assert_nothing_raised { + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + ctx.cert_store = empty_store + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } + + # Invalid certificate, SSL_VERIFY_PEER + assert_handshake_error { + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.cert_store = empty_store + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } + } + end + + def test_verify_mode_client_cert_required + # Optional, client certificate not supplied + vflag = OpenSSL::SSL::VERIFY_PEER + accept_proc = -> ssl { + assert_equal nil, ssl.peer_cert + } + start_server(verify_mode: vflag, accept_proc: accept_proc) { |port| + assert_nothing_raised { + server_connect(port) { |ssl| ssl.puts("abc"); ssl.gets } + } + } + + # Required, client certificate not supplied vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT start_server(verify_mode: vflag, ignore_listener_error: true) { |port| assert_handshake_error { @@ -222,7 +307,10 @@ def test_client_auth_failure def test_client_auth_success vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag) { |port| + start_server(verify_mode: vflag, + ctx_proc: proc { |ctx| + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0) + }) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.key = @cli_key ctx.cert = @cli_cert @@ -247,20 +335,16 @@ def test_client_auth_success } end - def test_client_auth_public_key + def test_client_cert_cb_ignore_error vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT start_server(verify_mode: vflag, ignore_listener_error: true) do |port| - assert_raise(ArgumentError) { - ctx = OpenSSL::SSL::SSLContext.new - ctx.key = @cli_key.public_key - ctx.cert = @cli_cert - server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } - } - ctx = OpenSSL::SSL::SSLContext.new - ctx.client_cert_cb = Proc.new{ |ssl| - [@cli_cert, @cli_key.public_key] + ctx.client_cert_cb = -> ssl { + raise "exception in client_cert_cb must be suppressed" } + # 1. Exception in client_cert_cb is suppressed + # 2. No client certificate will be sent to the server + # 3. SSL_VERIFY_FAIL_IF_NO_PEER_CERT causes the handshake to fail assert_handshake_error { server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } } @@ -268,6 +352,8 @@ def test_client_auth_public_key end def test_client_ca + pend "LibreSSL 3.2 has broken client CA support" if libressl?(3, 2, 0) + ctx_proc = Proc.new do |ctx| ctx.client_ca = [@ca_cert] end @@ -287,59 +373,20 @@ def test_client_ca } end - def test_read_nonblock_without_session - EnvUtil.suppress_warning do - start_server(start_immediately: false) { |port| - sock = TCPSocket.new("127.0.0.1", port) - ssl = OpenSSL::SSL::SSLSocket.new(sock) - ssl.sync_close = true - - assert_equal :wait_readable, ssl.read_nonblock(100, exception: false) - ssl.write("abc\n") - IO.select [ssl] - assert_equal('a', ssl.read_nonblock(1)) - assert_equal("bc\n", ssl.read_nonblock(100)) - assert_equal :wait_readable, ssl.read_nonblock(100, exception: false) - ssl.close - } - end - end - - def test_starttls - server_proc = -> (ctx, ssl) { - while line = ssl.gets - if line =~ /^STARTTLS$/ - ssl.write("x") - ssl.flush - ssl.accept - break - end - ssl.write(line) - end - readwrite_loop(ctx, ssl) - } - - EnvUtil.suppress_warning do # read/write on not started session - start_server(start_immediately: false, - server_proc: server_proc) { |port| - begin - sock = TCPSocket.new("127.0.0.1", port) - ssl = OpenSSL::SSL::SSLSocket.new(sock) - - ssl.puts "plaintext" - assert_equal "plaintext\n", ssl.gets + def test_unstarted_session + start_server do |port| + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock) - ssl.puts("STARTTLS") - ssl.read(1) - ssl.connect + assert_raise(OpenSSL::SSL::SSLError) { ssl.syswrite("data") } + assert_raise(OpenSSL::SSL::SSLError) { ssl.sysread(1) } - ssl.puts "over-tls" - assert_equal "over-tls\n", ssl.gets - ensure - ssl&.close - sock&.close - end - } + ssl.connect + ssl.puts "abc" + assert_equal "abc\n", ssl.gets + ensure + ssl&.close + sock&.close end end @@ -434,6 +481,34 @@ def test_exception_in_verify_callback_is_ignored } end + def test_finished_messages + server_finished = nil + server_peer_finished = nil + client_finished = nil + client_peer_finished = nil + + start_server(accept_proc: proc { |server| + server_finished = server.finished_message + server_peer_finished = server.peer_finished_message + }, ctx_proc: proc { |ctx| + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0) + }) { |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + ctx.max_version = :TLS1_2 if libressl?(3, 2, 0) && !libressl?(3, 3, 0) + server_connect(port, ctx) { |ssl| + ssl.puts "abc"; ssl.gets + + client_finished = ssl.finished_message + client_peer_finished = ssl.peer_finished_message + } + } + assert_not_nil(server_finished) + assert_not_nil(client_finished) + assert_equal(server_finished, client_peer_finished) + assert_equal(server_peer_finished, client_finished) + end + def test_sslctx_set_params ctx = OpenSSL::SSL::SSLContext.new ctx.set_params @@ -448,11 +523,10 @@ def test_sslctx_set_params end def test_post_connect_check_with_anon_ciphers - pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = -> ctx { ctx.ssl_version = :TLSv1_2 ctx.ciphers = "aNULL" + ctx.tmp_dh = Fixtures.pkey("dh-1") ctx.security_level = 0 } @@ -491,8 +565,7 @@ def test_post_connection_check exts = [ ["keyUsage","keyEncipherment,digitalSignature",true], - ["subjectAltName","DNS:localhost.localdomain",false], - ["subjectAltName","IP:127.0.0.1",false], + ["subjectAltName","DNS:localhost.localdomain,IP:127.0.0.1",false], ] @svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) start_server { |port| @@ -727,7 +800,6 @@ def socketpair def test_tlsext_hostname fooctx = OpenSSL::SSL::SSLContext.new - fooctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") } fooctx.cert = @cli_cert fooctx.key = @cli_key @@ -779,7 +851,6 @@ def test_servername_cb_raises_an_exception_on_unknown_objects ctx2 = OpenSSL::SSL::SSLContext.new ctx2.cert = @svr_cert ctx2.key = @svr_key - ctx2.tmp_dh_callback = proc { Fixtures.pkey("dh-1") } ctx2.servername_cb = lambda { |args| Object.new } sock1, sock2 = socketpair @@ -806,19 +877,47 @@ def test_servername_cb_raises_an_exception_on_unknown_objects sock2.close if sock2 end + def test_accept_errors_include_peeraddr + context = OpenSSL::SSL::SSLContext.new + context.cert = @svr_cert + context.key = @svr_key + + server = TCPServer.new("127.0.0.1", 0) + port = server.connect_address.ip_port + + ssl_server = OpenSSL::SSL::SSLServer.new(server, context) + + t = Thread.new do + assert_raise_with_message(OpenSSL::SSL::SSLError, /peeraddr=127\.0\.0\.1/) do + ssl_server.accept + end + end + + sock = TCPSocket.new("127.0.0.1", port) + sock << "\x00" * 1024 + + assert t.join + ensure + sock&.close + server.close + end + def test_verify_hostname_on_connect ctx_proc = proc { |ctx| + san = "DNS:a.example.com,DNS:*.b.example.com" + san += ",DNS:c*.example.com,DNS:d.*.example.com" unless libressl?(3, 2, 2) exts = [ ["keyUsage", "keyEncipherment,digitalSignature", true], - ["subjectAltName", "DNS:a.example.com,DNS:*.b.example.com," \ - "DNS:c*.example.com,DNS:d.*.example.com"], + ["subjectAltName", san], ] + ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) ctx.key = @svr_key } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| ctx = OpenSSL::SSL::SSLContext.new + assert_equal false, ctx.verify_hostname ctx.verify_hostname = true ctx.cert_store = OpenSSL::X509::Store.new ctx.cert_store.add_cert(@ca_cert) @@ -833,6 +932,7 @@ def test_verify_hostname_on_connect ["cx.example.com", true], ["d.x.example.com", false], ].each do |name, expected_ok| + next if name.start_with?('cx') if libressl?(3, 2, 2) begin sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) @@ -851,18 +951,58 @@ def test_verify_hostname_on_connect end end + def test_verify_hostname_failure_error_code + ctx_proc = proc { |ctx| + exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ["subjectAltName", "DNS:a.example.com"], + ] + ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) + ctx.key = @svr_key + } + + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| + verify_callback_ok = verify_callback_err = nil + + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_hostname = true + ctx.cert_store = OpenSSL::X509::Store.new + ctx.cert_store.add_cert(@ca_cert) + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.verify_callback = -> (preverify_ok, store_ctx) { + verify_callback_ok = preverify_ok + verify_callback_err = store_ctx.error + preverify_ok + } + + begin + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.hostname = "b.example.com" + assert_handshake_error { ssl.connect } + assert_equal false, verify_callback_ok + assert_equal OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH, verify_callback_err + ensure + sock&.close + end + end + end + def test_connect_certificate_verify_failed_exception_message start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.set_params - assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) { + # OpenSSL <= 1.1.0: "self signed certificate in certificate chain" + # OpenSSL >= 3.0.0: "self-signed certificate in certificate chain" + assert_raise_with_message(OpenSSL::SSL::SSLError, /self.signed/) { server_connect(port, ctx) } } ctx_proc = proc { |ctx| + now = Time.now ctx.cert = issue_cert(@svr, @svr_key, 30, [], @ca_cert, @ca_key, - not_before: Time.now-100, not_after: Time.now-10) + not_before: now - 7200, not_after: now - 3600) } start_server(ignore_listener_error: true, ctx_proc: ctx_proc) { |port| store = OpenSSL::X509::Store.new @@ -1069,46 +1209,51 @@ def test_minmax_version end def test_options_disable_versions - # Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0. + # It's recommended to use SSLContext#{min,max}_version= instead in real + # applications. The purpose of this test case is to check that SSL options + # are properly propagated to OpenSSL library. supported = check_supported_protocol_versions + if !defined?(OpenSSL::SSL::TLS1_3_VERSION) || + !supported.include?(OpenSSL::SSL::TLS1_2_VERSION) || + !supported.include?(OpenSSL::SSL::TLS1_3_VERSION) || + !defined?(OpenSSL::SSL::OP_NO_TLSv1_3) # LibreSSL < 3.4 + pend "this test case requires both TLS 1.2 and TLS 1.3 to be supported " \ + "and enabled by default" + end - if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) && - supported.include?(OpenSSL::SSL::TLS1_2_VERSION) - # Server disables ~ TLS 1.1 - ctx_proc = proc { |ctx| - ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 | - OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 - } - start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| - # Client only supports TLS 1.1 - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION - assert_handshake_error { server_connect(port, ctx1) { } } + # Server disables TLS 1.2 and earlier + ctx_proc = proc { |ctx| + ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 | + OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 | + OpenSSL::SSL::OP_NO_TLSv1_2 + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| + # Client only supports TLS 1.2 + ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION + assert_handshake_error { server_connect(port, ctx1) { } } - # Client only supports TLS 1.2 - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION - assert_nothing_raised { server_connect(port, ctx2) { } } - } + # Client only supports TLS 1.3 + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_3_VERSION + assert_nothing_raised { server_connect(port, ctx2) { } } + } - # Server only supports TLS 1.1 - ctx_proc = proc { |ctx| - ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION - } - start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| - # Client disables TLS 1.1 - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1 - assert_handshake_error { server_connect(port, ctx1) { } } + # Server only supports TLS 1.2 + ctx_proc = proc { |ctx| + ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port| + # Client doesn't support TLS 1.2 + ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_2 + assert_handshake_error { server_connect(port, ctx1) { } } - # Client disables TLS 1.2 - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2 - assert_nothing_raised { server_connect(port, ctx2) { } } - } - else - pend "TLS 1.1 and TLS 1.2 must be supported; skipping" - end + # Client supports TLS 1.2 by default + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_3 + assert_nothing_raised { server_connect(port, ctx2) { } } + } end def test_ssl_methods_constant @@ -1134,7 +1279,6 @@ def test_renegotiation_cb } end -if openssl?(1, 0, 2) || libressl? def test_alpn_protocol_selection_ary advertised = ["http/1.1", "spdy/2"] ctx_proc = Proc.new { |ctx| @@ -1159,7 +1303,6 @@ def test_alpn_protocol_selection_cancel ctx1 = OpenSSL::SSL::SSLContext.new ctx1.cert = @svr_cert ctx1.key = @svr_key - ctx1.tmp_dh_callback = proc { Fixtures.pkey("dh-1") } ctx1.alpn_select_cb = -> (protocols) { nil } ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) @@ -1180,10 +1323,8 @@ def test_alpn_protocol_selection_cancel t&.kill t&.join end -end def test_npn_protocol_selection_ary - pend "TLS 1.2 is not supported" unless tls12_supported? pend "NPN is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) @@ -1204,7 +1345,6 @@ def test_npn_protocol_selection_ary end def test_npn_protocol_selection_enum - pend "TLS 1.2 is not supported" unless tls12_supported? pend "NPN is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) @@ -1229,7 +1369,6 @@ def advertised.each end def test_npn_protocol_selection_cancel - pend "TLS 1.2 is not supported" unless tls12_supported? pend "NPN is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) @@ -1243,7 +1382,6 @@ def test_npn_protocol_selection_cancel end def test_npn_advertised_protocol_too_long - pend "TLS 1.2 is not supported" unless tls12_supported? pend "NPN is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) @@ -1257,7 +1395,6 @@ def test_npn_advertised_protocol_too_long end def test_npn_selected_protocol_too_long - pend "TLS 1.2 is not supported" unless tls12_supported? pend "NPN is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) @@ -1298,60 +1435,59 @@ def test_sync_close_without_connect end def test_get_ephemeral_key - # OpenSSL >= 1.0.2 - unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) - pend "SSL_get_server_tmp_key() is not supported" - end - - if tls12_supported? - # kRSA - ctx_proc1 = proc { |ctx| - ctx.ssl_version = :TLSv1_2 - ctx.ciphers = "kRSA" - } - start_server(ctx_proc: ctx_proc1) do |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.ssl_version = :TLSv1_2 - ctx.ciphers = "kRSA" + # kRSA + ctx_proc1 = proc { |ctx| + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "kRSA" + } + start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "kRSA" + begin server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key } + rescue OpenSSL::SSL::SSLError + # kRSA seems disabled + raise unless $!.message =~ /no cipher/ end end - if defined?(OpenSSL::PKey::DH) && tls12_supported? - # DHE - # TODO: How to test this with TLS 1.3? - ctx_proc2 = proc { |ctx| - ctx.ssl_version = :TLSv1_2 - ctx.ciphers = "EDH" + # DHE + # TODO: How to test this with TLS 1.3? + ctx_proc2 = proc { |ctx| + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "EDH" + ctx.tmp_dh = Fixtures.pkey("dh-1") + } + start_server(ctx_proc: ctx_proc2) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ssl_version = :TLSv1_2 + ctx.ciphers = "EDH" + server_connect(port, ctx) { |ssl| + assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key } - start_server(ctx_proc: ctx_proc2) do |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.ssl_version = :TLSv1_2 - ctx.ciphers = "EDH" - server_connect(port, ctx) { |ssl| - assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key - } - end end - if defined?(OpenSSL::PKey::EC) - # ECDHE - ctx_proc3 = proc { |ctx| - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" - ctx.ecdh_curves = "P-256" + # ECDHE + ctx_proc3 = proc { |ctx| + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + ctx.ecdh_curves = "P-256" + } + start_server(ctx_proc: ctx_proc3) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + server_connect(port, ctx) { |ssl| + assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key + ssl.puts "abc"; assert_equal "abc\n", ssl.gets } - start_server(ctx_proc: ctx_proc3) do |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" - server_connect(port, ctx) { |ssl| - assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key - ssl.puts "abc"; assert_equal "abc\n", ssl.gets - } - end end end def test_fallback_scsv + supported = check_supported_protocol_versions + return unless supported.include?(OpenSSL::SSL::TLS1_1_VERSION) && + supported.include?(OpenSSL::SSL::TLS1_2_VERSION) + pend "Fallback SCSV is not supported" unless \ OpenSSL::SSL::SSLContext.method_defined?(:enable_fallback_scsv) @@ -1408,13 +1544,11 @@ def test_fallback_scsv end end - def test_dh_callback - pend "TLS 1.2 is not supported" unless tls12_supported? - + def test_tmp_dh_callback dh = Fixtures.pkey("dh-1") called = false ctx_proc = -> ctx { - ctx.ssl_version = :TLSv1_2 + ctx.max_version = :TLS1_2 ctx.ciphers = "DH:!NULL" ctx.tmp_dh_callback = ->(*args) { called = true @@ -1424,18 +1558,14 @@ def test_dh_callback start_server(ctx_proc: ctx_proc) do |port| server_connect(port) { |ssl| assert called, "dh callback should be called" - if ssl.respond_to?(:tmp_key) - assert_equal dh.to_der, ssl.tmp_key.to_der - end + assert_equal dh.to_der, ssl.tmp_key.to_der } end end def test_connect_works_when_setting_dh_callback_to_nil - pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = -> ctx { - ctx.ssl_version = :TLSv1_2 + ctx.max_version = :TLS1_2 ctx.ciphers = "DH:!NULL" # use DH ctx.tmp_dh_callback = nil } @@ -1448,71 +1578,71 @@ def test_connect_works_when_setting_dh_callback_to_nil end end - def test_tmp_ecdh_callback - pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) - pend "tmp_ecdh_callback is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:tmp_ecdh_callback) - pend "LibreSSL 2.6 has broken SSL_CTX_set_tmp_ecdh_callback()" \ - if libressl?(2, 6, 1) - - EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05) - called = false - ctx_proc = -> ctx { - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" - ctx.tmp_ecdh_callback = -> (*args) { - called = true - OpenSSL::PKey::EC.new "prime256v1" - } + def test_tmp_dh + dh = Fixtures.pkey("dh-1") + ctx_proc = -> ctx { + ctx.max_version = :TLS1_2 + ctx.ciphers = "DH:!NULL" # use DH + ctx.tmp_dh = dh + } + start_server(ctx_proc: ctx_proc) do |port| + server_connect(port) { |ssl| + assert_equal dh.to_der, ssl.tmp_key.to_der } - start_server(ctx_proc: ctx_proc) do |port| - server_connect(port) { |s| - assert called, "tmp_ecdh_callback should be called" - } - end end end - def test_ecdh_curves - pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) - + def test_ecdh_curves_tls12 ctx_proc = -> ctx { # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + ctx.ciphers = "kEECDH" ctx.ecdh_curves = "P-384:P-521" } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| + # Test 1: Client=P-256:P-384, Server=P-384:P-521 --> P-384 ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-256:P-384" # disable P-521 for OpenSSL >= 1.0.2 - + ctx.ecdh_curves = "P-256:P-384" server_connect(port, ctx) { |ssl| cs = ssl.cipher[0] - if /\ATLS/ =~ cs # Is TLS 1.3 is used? - assert_equal "secp384r1", ssl.tmp_key.group.curve_name - else - assert_match (/\AECDH/), cs - if ssl.respond_to?(:tmp_key) - assert_equal "secp384r1", ssl.tmp_key.group.curve_name - end - end + assert_match (/\AECDH/), cs + assert_equal "secp384r1", ssl.tmp_key.group.curve_name ssl.puts "abc"; assert_equal "abc\n", ssl.gets } - if openssl?(1, 0, 2) || libressl?(2, 5, 1) - ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-256" + # Test 2: Client=P-256, Server=P-521:P-384 --> Fail + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-256" + assert_raise(OpenSSL::SSL::SSLError) { + server_connect(port, ctx) { } + } - assert_raise(OpenSSL::SSL::SSLError) { - server_connect(port, ctx) { } - } + # Test 3: Client=P-521:P-384, Server=P-521:P-384 --> P-521 + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-521:P-384" + server_connect(port, ctx) { |ssl| + assert_equal "secp521r1", ssl.tmp_key.group.curve_name + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + } + end + end - ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-521:P-384" + def test_ecdh_curves_tls13 + pend "TLS 1.3 not supported" unless tls13_supported? - server_connect(port, ctx) { |ssl| - assert_equal "secp521r1", ssl.tmp_key.group.curve_name - ssl.puts "abc"; assert_equal "abc\n", ssl.gets - } - end + ctx_proc = -> ctx { + # Assume TLS 1.3 is enabled and chosen by default + ctx.ecdh_curves = "P-384:P-521" + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-256:P-384" # disable P-521 + + server_connect(port, ctx) { |ssl| + assert_equal "TLSv1.3", ssl.ssl_version + assert_equal "secp384r1", ssl.tmp_key.group.curve_name + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + } end end @@ -1570,6 +1700,20 @@ def test_freeze_calls_setup } end + def test_fileno + ctx = OpenSSL::SSL::SSLContext.new + sock1, sock2 = socketpair + + socket = OpenSSL::SSL::SSLSocket.new(sock1) + server = OpenSSL::SSL::SSLServer.new(sock2, ctx) + + assert_equal socket.fileno, socket.to_io.fileno + assert_equal server.fileno, server.to_io.fileno + ensure + sock1.close + sock2.close + end + private def start_server_version(version, ctx_proc = nil, @@ -1602,8 +1746,8 @@ def server_connect(port, ctx = nil) def assert_handshake_error # different OpenSSL versions react differently when facing a SSL/TLS version - # that has been marked as forbidden, therefore either of these may be raised - assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) { + # that has been marked as forbidden, therefore any of these may be raised + assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE) { yield } end diff --git a/ruby/test/openssl/test_ssl_session.rb b/ruby/test/openssl/test_ssl_session.rb index e199f86d2..b72b10d3b 100644 --- a/ruby/test/openssl/test_ssl_session.rb +++ b/ruby/test/openssl/test_ssl_session.rb @@ -1,12 +1,10 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase def test_session - pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 } start_server(ctx_proc: ctx_proc) do |port| server_connect_with_session(port, nil, nil) { |ssl| @@ -122,6 +120,7 @@ def test_resumption ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET # Disable server-side session cache which is enabled by default ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0) } start_server(ctx_proc: ctx_proc) do |port| sess1 = server_connect_with_session(port, nil, nil) { |ssl| @@ -143,8 +142,6 @@ def test_resumption end def test_server_session_cache - pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = Proc.new do |ctx| ctx.ssl_version = :TLSv1_2 ctx.options |= OpenSSL::SSL::OP_NO_TICKET @@ -223,8 +220,6 @@ def test_server_session_cache TEST_SESSION_REMOVE_CB = ENV["OSSL_TEST_ALL"] == "1" def test_ctx_client_session_cb - pend "TLS 1.2 is not supported" unless tls12_supported? - ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 } start_server(ctx_proc: ctx_proc) do |port| called = {} @@ -256,8 +251,6 @@ def test_ctx_client_session_cb end def test_ctx_server_session_cb - pend "TLS 1.2 is not supported" unless tls12_supported? - connections = nil called = {} cctx = OpenSSL::SSL::SSLContext.new diff --git a/ruby/test/openssl/test_ts.rb b/ruby/test/openssl/test_ts.rb new file mode 100644 index 000000000..7cb1a1fe8 --- /dev/null +++ b/ruby/test/openssl/test_ts.rb @@ -0,0 +1,680 @@ +require_relative "utils" + +if defined?(OpenSSL) && defined?(OpenSSL::Timestamp) + +class OpenSSL::TestTimestamp < OpenSSL::TestCase + def intermediate_key + @intermediate_key ||= OpenSSL::PKey::RSA.new <<-_end_of_pem_ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCcyODxH+oTrr7l7MITWcGaYnnBma6vidCCJjuSzZpaRmXZHAyH +0YcY4ttC0BdJ4uV+cE05IySVC7tyvVfFb8gFQ6XJV+AEktP+XkLbcxZgj9d2NVu1 +ziXdI+ldXkPnMhyWpMS5E7SD6gflv9NhUYEsmAGsUgdK6LDmm2W2/4TlewIDAQAB +AoGAYgx6KDFWONLqjW3f/Sv/mGYHUNykUyDzpcD1Npyf797gqMMSzwlo3FZa2tC6 +D7n23XirwpTItvEsW9gvgMikJDPlThAeGLZ+L0UbVNNBHVxGP998Nda1kxqKvhRE +pfZCKc7PLM9ZXc6jBTmgxdcAYfVCCVUoa2mEf9Ktr3BlI4kCQQDQAM09+wHDXGKP +o2UnCwCazGtyGU2r0QCzHlh9BVY+KD2KjjhuWh86rEbdWN7hEW23Je1vXIhuM6Pa +/Ccd+XYnAkEAwPZ91PK6idEONeGQ4I3dyMKV2SbaUjfq3MDL4iIQPQPuj7QsBO/5 +3Nf9ReSUUTRFCUVwoC8k4Z1KAJhR/K/ejQJANE7PTnPuGJQGETs09+GTcFpR9uqY +FspDk8fg1ufdrVnvSAXF+TJewiGK3KU5v33jinhWQngRsyz3Wt2odKhEZwJACbjh +oicQqvzzgFd7GzVKpWDYd/ZzLY1PsgusuhoJQ2m9TVRAm4cTycLAKhNYPbcqe0sa +X5fAffWU0u7ZwqeByQJAOUAbYET4RU3iymAvAIDFj8LiQnizG9t5Ty3HXlijKQYv +y8gsvWd4CdxwOPatWpBUX9L7IXcMJmD44xXTUvpbfQ== +-----END RSA PRIVATE KEY----- +_end_of_pem_ + end + + def ee_key + @ee_key ||= OpenSSL::PKey::RSA.new <<-_end_of_pem_ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDA6eB5r2O5KOKNbKMBhzadl43lgpwqq28m+G0gH38kKCL1f3o9 +P8xUZm7sZqcWEervZMSSXMGBV9DgeoSR+U6FMJywgQGx/JNRx7wZTMNym3PvgLkl +xCXh6ZA0/xbtJtcNI+UUv0ENBkTIuUWBhkAf3jQclAr9aQ0ktYBuHAcRcQIDAQAB +AoGAKNhcAuezwZx6e18pFEXAtpVEIfgJgK9TlXi8AjUpAkrNPBWFmDpN1QDrM3p4 +nh+lEpLPW/3vqqchPqYyM4YJraMLpS3KUG+s7+m9QIia0ri2WV5Cig7WL+Tl9p7K +b3oi2Aj/wti8GfOLFQXOQQ4Ea4GoCv2Sxe0GZR39UBxzTsECQQD1zuVIwBvqU2YR +8innsoa+j4u2hulRmQO6Zgpzj5vyRYfA9uZxQ9nKbfJvzuWwUv+UzyS9RqxarqrP +5nQw5EmVAkEAyOmJg6+AfGrgvSWfSpXEds/WA/sHziCO3rE4/sd6cnDc6XcTgeMs +mT8Z3kAYGpqFDew5orUylPfJJa+PUueJbQJAY+gkvw3+Cp69FLw1lgu0wo07fwOU +n2qu3jsNMm0DOFRUWfTAMvcd9S385L7WEnWZldUfnKK1+OGXYYrMXPbchQJAChU2 +UoaHQzc16iguM1cK0g+iJPb/MEgQA3sPajHmokGpxIm2T+lvvo0dJjs/Om6QyN8X +EWRYkoNQ8/Q4lCeMjQJAfvDIGtyqF4PieFHYgluQAv5pGgYpakdc8SYyeRH9NKey +GaL27FRs4fRWf9OmxPhUVgIyGzLGXrueemvQUDHObA== +-----END RSA PRIVATE KEY----- +_end_of_pem_ + end + + def ca_cert + @ca_cert ||= OpenSSL::Certs.ca_cert + end + + def ca_store + @ca_store ||= OpenSSL::X509::Store.new.tap { |s| s.add_cert(ca_cert) } + end + + def ts_cert_direct + @ts_cert_direct ||= OpenSSL::Certs.ts_cert_direct(ee_key, ca_cert) + end + + def intermediate_cert + @intermediate_cert ||= OpenSSL::Certs.intermediate_cert(intermediate_key, ca_cert) + end + + def intermediate_store + @intermediate_store ||= OpenSSL::X509::Store.new.tap { |s| s.add_cert(intermediate_cert) } + end + + def ts_cert_ee + @ts_cert_ee ||= OpenSSL::Certs.ts_cert_ee(ee_key, intermediate_cert, intermediate_key) + end + + def test_request_mandatory_fields + req = OpenSSL::Timestamp::Request.new + assert_raise(OpenSSL::Timestamp::TimestampError) do + tmp = req.to_der + pp OpenSSL::ASN1.decode(tmp) + end + req.algorithm = "sha1" + assert_raise(OpenSSL::Timestamp::TimestampError) do + req.to_der + end + req.message_imprint = OpenSSL::Digest.digest('SHA1', "data") + req.to_der + end + + def test_request_assignment + req = OpenSSL::Timestamp::Request.new + + req.version = 2 + assert_equal(2, req.version) + assert_raise(TypeError) { req.version = nil } + assert_raise(TypeError) { req.version = "foo" } + + req.algorithm = "SHA1" + assert_equal("SHA1", req.algorithm) + assert_raise(TypeError) { req.algorithm = nil } + assert_raise(OpenSSL::ASN1::ASN1Error) { req.algorithm = "xxx" } + + req.message_imprint = "test" + assert_equal("test", req.message_imprint) + assert_raise(TypeError) { req.message_imprint = nil } + + req.policy_id = "1.2.3.4.5" + assert_equal("1.2.3.4.5", req.policy_id) + assert_raise(TypeError) { req.policy_id = 123 } + assert_raise(TypeError) { req.policy_id = nil } + + req.nonce = 42 + assert_equal(42, req.nonce) + assert_raise(TypeError) { req.nonce = "foo" } + assert_raise(TypeError) { req.nonce = nil } + + req.cert_requested = false + assert_equal(false, req.cert_requested?) + req.cert_requested = nil + assert_equal(false, req.cert_requested?) + req.cert_requested = 123 + assert_equal(true, req.cert_requested?) + req.cert_requested = "asdf" + assert_equal(true, req.cert_requested?) + end + + def test_request_serialization + req = OpenSSL::Timestamp::Request.new + + req.version = 2 + req.algorithm = "SHA1" + req.message_imprint = "test" + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + req.cert_requested = true + + req = OpenSSL::Timestamp::Request.new(req.to_der) + + assert_equal(2, req.version) + assert_equal("SHA1", req.algorithm) + assert_equal("test", req.message_imprint) + assert_equal("1.2.3.4.5", req.policy_id) + assert_equal(42, req.nonce) + assert_equal(true, req.cert_requested?) + + end + + def test_request_re_assignment + #tests whether the potential 'freeing' of previous values in C works properly + req = OpenSSL::Timestamp::Request.new + req.version = 2 + req.version = 3 + req.algorithm = "SHA1" + req.algorithm = "SHA256" + req.message_imprint = "test" + req.message_imprint = "test2" + req.policy_id = "1.2.3.4.5" + req.policy_id = "1.2.3.4.6" + req.nonce = 42 + req.nonce = 24 + req.cert_requested = false + req.cert_requested = true + req.to_der + end + + def test_request_encode_decode + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + + qer = OpenSSL::Timestamp::Request.new(req.to_der) + assert_equal(1, qer.version) + assert_equal("SHA1", qer.algorithm) + assert_equal(digest, qer.message_imprint) + assert_equal("1.2.3.4.5", qer.policy_id) + assert_equal(42, qer.nonce) + + #put OpenSSL::ASN1.decode inbetween + qer2 = OpenSSL::Timestamp::Request.new(OpenSSL::ASN1.decode(req.to_der)) + assert_equal(1, qer2.version) + assert_equal("SHA1", qer2.algorithm) + assert_equal(digest, qer2.message_imprint) + assert_equal("1.2.3.4.5", qer2.policy_id) + assert_equal(42, qer2.nonce) + end + + def test_request_invalid_asn1 + assert_raise(OpenSSL::Timestamp::TimestampError) do + OpenSSL::Timestamp::Request.new("*" * 44) + end + end + + def test_response_constants + assert_equal(0, OpenSSL::Timestamp::Response::GRANTED) + assert_equal(1, OpenSSL::Timestamp::Response::GRANTED_WITH_MODS) + assert_equal(2, OpenSSL::Timestamp::Response::REJECTION) + assert_equal(3, OpenSSL::Timestamp::Response::WAITING) + assert_equal(4, OpenSSL::Timestamp::Response::REVOCATION_WARNING) + assert_equal(5, OpenSSL::Timestamp::Response::REVOCATION_NOTIFICATION) + end + + def test_response_creation + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + + fac = OpenSSL::Timestamp::Factory.new + time = Time.now + fac.gen_time = time + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + resp = OpenSSL::Timestamp::Response.new(resp) + assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status) + assert_nil(resp.failure_info) + assert_equal([], resp.status_text) + assert_equal(1, resp.token_info.version) + assert_equal("1.2.3.4.5", resp.token_info.policy_id) + assert_equal("SHA1", resp.token_info.algorithm) + assert_equal(digest, resp.token_info.message_imprint) + assert_equal(1, resp.token_info.serial_number) + assert_equal(time.to_i, resp.token_info.gen_time.to_i) + assert_equal(false, resp.token_info.ordering) + assert_nil(resp.token_info.nonce) + assert_cert(ts_cert_ee, resp.tsa_certificate) + #compare PKCS7 + token = OpenSSL::ASN1.decode(resp.to_der).value[1] + assert_equal(token.to_der, resp.token.to_der) + end + + def test_response_failure_info + resp = OpenSSL::Timestamp::Response.new("0\"0 \x02\x01\x020\x17\f\x15Invalid TimeStampReq.\x03\x02\x06\x80") + assert_equal(:BAD_ALG, resp.failure_info) + end + + def test_response_mandatory_fields + fac = OpenSSL::Timestamp::Factory.new + req = OpenSSL::Timestamp::Request.new + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + req.algorithm = "sha1" + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + req.message_imprint = OpenSSL::Digest.digest('SHA1', "data") + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + fac.gen_time = Time.now + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + fac.default_policy_id = "1.2.3.4.5" + assert_equal OpenSSL::Timestamp::Response::GRANTED, fac.create_timestamp(ee_key, ts_cert_ee, req).status + fac.default_policy_id = nil + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + req.policy_id = "1.2.3.4.5" + assert_equal OpenSSL::Timestamp::Response::GRANTED, fac.create_timestamp(ee_key, ts_cert_ee, req).status + end + + def test_response_allowed_digests + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + req.message_imprint = OpenSSL::Digest.digest('SHA1', "test") + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.default_policy_id = "1.2.3.4.6" + + # None allowed by default + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status + + # Explicitly allow SHA1 (string) + fac.allowed_digests = ["sha1"] + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal OpenSSL::Timestamp::Response::GRANTED, resp.status + + # Explicitly allow SHA1 (object) + fac.allowed_digests = [OpenSSL::Digest.new('SHA1')] + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal OpenSSL::Timestamp::Response::GRANTED, resp.status + + # Others not allowed + req.algorithm = "SHA256" + req.message_imprint = OpenSSL::Digest.digest('SHA256', "test") + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status + + # Non-Array + fac.allowed_digests = 123 + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status + + # Non-String, non-Digest Array element + fac.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA1'), 123] + assert_raise(TypeError) do + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + end + + def test_response_default_policy + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.default_policy_id = "1.2.3.4.6" + + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status) + assert_equal("1.2.3.4.6", resp.token_info.policy_id) + end + + def test_response_bad_purpose + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + + + assert_raise(OpenSSL::Timestamp::TimestampError) do + fac.create_timestamp(ee_key, intermediate_cert, req) + end + end + + def test_response_invalid_asn1 + assert_raise(OpenSSL::Timestamp::TimestampError) do + OpenSSL::Timestamp::Response.new("*" * 44) + end + end + + def test_no_cert_requested + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.cert_requested = false + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.default_policy_id = "1.2.3.4.5" + + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status) + assert_nil(resp.tsa_certificate) + end + + def test_response_no_policy_defined + assert_raise(OpenSSL::Timestamp::TimestampError) do + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + + fac.create_timestamp(ee_key, ts_cert_ee, req) + end + end + + def test_verify_ee_no_req + assert_raise(TypeError) do + ts, _ = timestamp_ee + ts.verify(nil, ca_cert) + end + end + + def test_verify_ee_no_store + assert_raise(TypeError) do + ts, req = timestamp_ee + ts.verify(req, nil) + end + end + + def test_verify_ee_wrong_root_no_intermediate + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_ee + ts.verify(req, intermediate_store) + end + end + + def test_verify_ee_wrong_root_wrong_intermediate + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_ee + ts.verify(req, intermediate_store, [ca_cert]) + end + end + + def test_verify_ee_nonce_mismatch + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_ee + req.nonce = 1 + ts.verify(req, ca_store, [intermediate_cert]) + end + end + + def test_verify_ee_intermediate_missing + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_ee + ts.verify(req, ca_store) + end + end + + def test_verify_ee_intermediate + ts, req = timestamp_ee + ts.verify(req, ca_store, [intermediate_cert]) + end + + def test_verify_ee_intermediate_type_error + ts, req = timestamp_ee + assert_raise(TypeError) { ts.verify(req, [ca_cert], 123) } + end + + def test_verify_ee_def_policy + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.nonce = 42 + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.default_policy_id = "1.2.3.4.5" + + ts = fac.create_timestamp(ee_key, ts_cert_ee, req) + ts.verify(req, ca_store, [intermediate_cert]) + end + + def test_verify_direct + ts, req = timestamp_direct + ts.verify(req, ca_store) + end + + def test_verify_direct_redundant_untrusted + ts, req = timestamp_direct + ts.verify(req, ca_store, [ts.tsa_certificate, ts.tsa_certificate]) + end + + def test_verify_direct_unrelated_untrusted + ts, req = timestamp_direct + ts.verify(req, ca_store, [intermediate_cert]) + end + + def test_verify_direct_wrong_root + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_direct + ts.verify(req, intermediate_store) + end + end + + def test_verify_direct_no_cert_no_intermediate + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_direct_no_cert + ts.verify(req, ca_store) + end + end + + def test_verify_ee_no_cert + ts, req = timestamp_ee_no_cert + ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert]) + end + + def test_verify_ee_no_cert_no_intermediate + assert_raise(OpenSSL::Timestamp::TimestampError) do + ts, req = timestamp_ee_no_cert + ts.verify(req, ca_store, [ts_cert_ee]) + end + end + + def test_verify_ee_additional_certs_array + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.additional_certs = [intermediate_cert] + ts = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal(2, ts.token.certificates.size) + fac.additional_certs = nil + ts.verify(req, ca_store) + ts = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal(1, ts.token.certificates.size) + end + + def test_verify_ee_additional_certs_with_root + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.additional_certs = [intermediate_cert, ca_cert] + ts = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_equal(3, ts.token.certificates.size) + ts.verify(req, ca_store) + end + + def test_verify_ee_cert_inclusion_not_requested + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.nonce = 42 + req.cert_requested = false + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + #needed because the Request contained no policy identifier + fac.default_policy_id = '1.2.3.4.5' + fac.additional_certs = [ ts_cert_ee, intermediate_cert ] + ts = fac.create_timestamp(ee_key, ts_cert_ee, req) + assert_nil(ts.token.certificates) #since cert_requested? == false + ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert]) + end + + def test_reusable + #test if req and faq are reusable, i.e. the internal + #CTX_free methods don't mess up e.g. the certificates + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + fac.additional_certs = [ intermediate_cert ] + ts1 = fac.create_timestamp(ee_key, ts_cert_ee, req) + ts1.verify(req, ca_store) + ts2 = fac.create_timestamp(ee_key, ts_cert_ee, req) + ts2.verify(req, ca_store) + refute_nil(ts1.tsa_certificate) + refute_nil(ts2.tsa_certificate) + end + + def test_token_info_creation + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = OpenSSL::BN.new(123) + + fac = OpenSSL::Timestamp::Factory.new + time = Time.now + fac.gen_time = time + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + + resp = fac.create_timestamp(ee_key, ts_cert_ee, req) + info = resp.token_info + info = OpenSSL::Timestamp::TokenInfo.new(info.to_der) + + assert_equal(1, info.version) + assert_equal("1.2.3.4.5", info.policy_id) + assert_equal("SHA1", info.algorithm) + assert_equal(digest, info.message_imprint) + assert_equal(1, info.serial_number) + assert_equal(time.to_i, info.gen_time.to_i) + assert_equal(false, info.ordering) + assert_equal(123, info.nonce) + end + + def test_token_info_invalid_asn1 + assert_raise(OpenSSL::Timestamp::TimestampError) do + OpenSSL::Timestamp::TokenInfo.new("*" * 44) + end + end + + private + + def assert_cert expected, actual + assert_equal expected.to_der, actual.to_der + end + + def timestamp_ee + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + return fac.create_timestamp(ee_key, ts_cert_ee, req), req + end + + def timestamp_ee_no_cert + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + req.cert_requested = false + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + return fac.create_timestamp(ee_key, ts_cert_ee, req), req + end + + def timestamp_direct + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + return fac.create_timestamp(ee_key, ts_cert_direct, req), req + end + + def timestamp_direct_no_cert + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest + req.policy_id = "1.2.3.4.5" + req.nonce = 42 + req.cert_requested = false + + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + return fac.create_timestamp(ee_key, ts_cert_direct, req), req + end +end + +end diff --git a/ruby/test/openssl/test_x509attr.rb b/ruby/test/openssl/test_x509attr.rb index c6c48e86a..2919d23d2 100644 --- a/ruby/test/openssl/test_x509attr.rb +++ b/ruby/test/openssl/test_x509attr.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) @@ -79,6 +79,16 @@ def test_eq assert_equal true, attr1 == attr2 assert_equal false, attr1 == attr3 end + + def test_marshal + val = OpenSSL::ASN1::Set([ + OpenSSL::ASN1::UTF8String("abc123") + ]) + attr = OpenSSL::X509::Attribute.new("challengePassword", val) + deserialized = Marshal.load(Marshal.dump(attr)) + + assert_equal attr.to_der, deserialized.to_der + end end end diff --git a/ruby/test/openssl/test_x509cert.rb b/ruby/test/openssl/test_x509cert.rb index 40a5b0ad7..d696b98c0 100644 --- a/ruby/test/openssl/test_x509cert.rb +++ b/ruby/test/openssl/test_x509cert.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) @@ -73,9 +73,12 @@ def test_extension ["basicConstraints","CA:TRUE",true], ["keyUsage","keyCertSign, cRLSign",true], ["subjectKeyIdentifier","hash",false], - ["authorityKeyIdentifier","keyid:always",false], + ["authorityKeyIdentifier","issuer:always,keyid:always",false], ] ca_cert = issue_cert(@ca, @rsa2048, 1, ca_exts, nil, nil) + keyid = get_subject_key_id(ca_cert.to_der, hex: false) + assert_equal keyid, ca_cert.authority_key_identifier + assert_equal keyid, ca_cert.subject_key_identifier ca_cert.extensions.each_with_index{|ext, i| assert_equal(ca_exts[i].first, ext.oid) assert_equal(ca_exts[i].last, ext.critical?) @@ -84,9 +87,10 @@ def test_extension ee1_exts = [ ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true], ["subjectKeyIdentifier","hash",false], - ["authorityKeyIdentifier","keyid:always",false], + ["authorityKeyIdentifier","issuer:always,keyid:always",false], ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false], ["subjectAltName","email:ee1@ruby-lang.org",false], + ["authorityInfoAccess","caIssuers;URI:http://www.example.com/caIssuers,OCSP;URI:http://www.example.com/ocsp",false], ] ee1_cert = issue_cert(@ee1, @rsa1024, 2, ee1_exts, ca_cert, @rsa2048) assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der) @@ -94,6 +98,78 @@ def test_extension assert_equal(ee1_exts[i].first, ext.oid) assert_equal(ee1_exts[i].last, ext.critical?) } + assert_nil(ee1_cert.crl_uris) + + ef = OpenSSL::X509::ExtensionFactory.new + ef.config = OpenSSL::Config.parse(<<~_cnf_) + [crlDistPts] + URI.1 = http://www.example.com/crl + URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary + _cnf_ + cdp_cert = generate_cert(@ee1, @rsa1024, 3, ca_cert) + ef.subject_certificate = cdp_cert + cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "@crlDistPts")) + cdp_cert.sign(@rsa2048, "sha256") + assert_equal( + ["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"], + cdp_cert.crl_uris + ) + + ef = OpenSSL::X509::ExtensionFactory.new + aia_cert = generate_cert(@ee1, @rsa1024, 4, ca_cert) + ef.subject_certificate = aia_cert + aia_cert.add_extension( + ef.create_extension( + "authorityInfoAccess", + "caIssuers;URI:http://www.example.com/caIssuers," \ + "caIssuers;URI:ldap://ldap.example.com/cn=ca?authorityInfoAccessCaIssuers;binary," \ + "OCSP;URI:http://www.example.com/ocsp," \ + "OCSP;URI:ldap://ldap.example.com/cn=ca?authorityInfoAccessOcsp;binary", + false + ) + ) + aia_cert.sign(@rsa2048, "sha256") + assert_equal( + ["http://www.example.com/caIssuers", "ldap://ldap.example.com/cn=ca?authorityInfoAccessCaIssuers;binary"], + aia_cert.ca_issuer_uris + ) + assert_equal( + ["http://www.example.com/ocsp", "ldap://ldap.example.com/cn=ca?authorityInfoAccessOcsp;binary"], + aia_cert.ocsp_uris + ) + + no_exts_cert = issue_cert(@ca, @rsa2048, 5, [], nil, nil) + assert_equal nil, no_exts_cert.authority_key_identifier + assert_equal nil, no_exts_cert.subject_key_identifier + assert_equal nil, no_exts_cert.crl_uris + assert_equal nil, no_exts_cert.ca_issuer_uris + assert_equal nil, no_exts_cert.ocsp_uris + end + + def test_invalid_extension + integer = OpenSSL::ASN1::Integer.new(0) + invalid_exts_cert = generate_cert(@ee1, @rsa1024, 1, nil) + ["subjectKeyIdentifier", "authorityKeyIdentifier", "crlDistributionPoints", "authorityInfoAccess"].each do |ext| + invalid_exts_cert.add_extension( + OpenSSL::X509::Extension.new(ext, integer.to_der) + ) + end + + assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") { + invalid_exts_cert.authority_key_identifier + } + assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") { + invalid_exts_cert.subject_key_identifier + } + assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") { + invalid_exts_cert.crl_uris + } + assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") { + invalid_exts_cert.ca_issuer_uris + } + assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") { + invalid_exts_cert.ocsp_uris + } end def test_sign_and_verify_rsa_sha1 @@ -129,7 +205,7 @@ def test_sign_and_verify_dsa end def test_sign_and_verify_rsa_dss1 - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest::DSS1.new) + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest.new('DSS1')) assert_equal(false, cert.verify(@rsa1024)) assert_equal(true, cert.verify(@rsa2048)) assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) }) @@ -169,6 +245,18 @@ def test_read_from_file } end + def test_read_der_then_pem + cert1 = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + exts = [ + # A new line before PEM block + ["nsComment", "Another certificate:\n" + cert1.to_pem], + ] + cert2 = issue_cert(@ca, @rsa2048, 2, exts, nil, nil) + + assert_equal cert2, OpenSSL::X509::Certificate.new(cert2.to_der) + assert_equal cert2, OpenSSL::X509::Certificate.new(cert2.to_pem) + end + def test_eq now = Time.now cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil, @@ -189,6 +277,49 @@ def test_eq assert_equal false, cert3 == cert4 end + def test_marshal + now = Time.now + cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil, + not_before: now, not_after: now + 3600) + cert = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, + not_before: now, not_after: now + 3600) + deserialized = Marshal.load(Marshal.dump(cert)) + + assert_equal cert.to_der, deserialized.to_der + end + + def test_load_file_empty_pem + empty_path = Fixtures.file_path("pkey", "empty.pem") + assert_raise(OpenSSL::X509::CertificateError) do + OpenSSL::X509::Certificate.load_file(empty_path) + end + end + + def test_load_file_fullchain_pem + fullchain_path = Fixtures.file_path("pkey", "fullchain.pem") + certificates = OpenSSL::X509::Certificate.load_file(fullchain_path) + assert_equal 2, certificates.size + assert_equal "/CN=www.codeotaku.com", certificates[0].subject.to_s + assert_equal "/C=US/O=Let's Encrypt/CN=R3", certificates[1].subject.to_s + end + + def test_load_file_certificate_der + fullchain_path = Fixtures.file_path("pkey", "certificate.der") + certificates = OpenSSL::X509::Certificate.load_file(fullchain_path) + + # DER encoding can only contain one certificate: + assert_equal 1, certificates.size + assert_equal "/CN=www.codeotaku.com", certificates[0].subject.to_s + end + + def test_load_file_fullchain_garbage + fullchain_path = Fixtures.file_path("pkey", "garbage.txt") + + assert_raise(OpenSSL::X509::CertificateError) do + OpenSSL::X509::Certificate.load_file(fullchain_path) + end + end + private def certificate_error_returns_false diff --git a/ruby/test/openssl/test_x509crl.rb b/ruby/test/openssl/test_x509crl.rb index 03fdf64dd..bcdb0a697 100644 --- a/ruby/test/openssl/test_x509crl.rb +++ b/ruby/test/openssl/test_x509crl.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) @@ -20,7 +20,7 @@ def test_basic cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, now, now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) assert_equal(1, crl.version) assert_equal(cert.issuer.to_der, crl.issuer.to_der) assert_equal(now, crl.last_update) @@ -57,7 +57,7 @@ def test_revoked ] cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) revoked = crl.revoked assert_equal(5, revoked.size) assert_equal(1, revoked[0].serial) @@ -98,7 +98,7 @@ def test_revoked revoke_info = (1..1000).collect{|i| [i, now, 0] } crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) revoked = crl.revoked assert_equal(1000, revoked.size) assert_equal(1, revoked[0].serial) @@ -118,19 +118,22 @@ def test_extension ["keyUsage", "cRLSign, keyCertSign", true], ] crl_exts = [ - ["authorityKeyIdentifier", "keyid:always", false], + ["authorityKeyIdentifier", "issuer:always,keyid:always", false], ["issuerAltName", "issuer:copy", false], ] cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts, - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) exts = crl.extensions assert_equal(3, exts.size) assert_equal("1", exts[0].value) assert_equal("crlNumber", exts[0].oid) assert_equal(false, exts[0].critical?) + expected_keyid = OpenSSL::TestUtils.get_subject_key_id(cert, hex: false) + assert_equal expected_keyid, crl.authority_key_identifier + assert_equal("authorityKeyIdentifier", exts[1].oid) keyid = OpenSSL::TestUtils.get_subject_key_id(cert) assert_match(/^keyid:#{keyid}/, exts[1].value) @@ -155,22 +158,26 @@ def test_extension assert_equal("issuerAltName", exts[2].oid) assert_equal("email:xyzzy@ruby-lang.org", exts[2].value) assert_equal(false, exts[2].critical?) + + no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [], + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + assert_equal nil, no_ext_crl.authority_key_identifier end def test_crlnumber cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) assert_match(1.to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text) crl = issue_crl([], 2**32, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) assert_match((2**32).to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text) crl = issue_crl([], 2**100, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text) assert_match((2**100).to_s, crl.extensions[0].value) end @@ -178,7 +185,7 @@ def test_crlnumber def test_sign_and_verify cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest::SHA1.new) + cert, @rsa2048, OpenSSL::Digest.new('SHA1')) assert_equal(false, crl.verify(@rsa1024)) assert_equal(true, crl.verify(@rsa2048)) assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) }) @@ -188,7 +195,7 @@ def test_sign_and_verify cert = issue_cert(@ca, @dsa512, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @dsa512, OpenSSL::Digest::SHA1.new) + cert, @dsa512, OpenSSL::Digest.new('SHA1')) assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) }) assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) }) assert_equal(false, crl.verify(@dsa256)) @@ -249,6 +256,22 @@ def test_eq assert_equal true, rev2 == crl2.revoked[1] end + def test_marshal + now = Time.now + + cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil) + crl = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256") + rev = OpenSSL::X509::Revoked.new.tap { |rev| + rev.serial = 1 + rev.time = now + } + crl.add_revoked(rev) + deserialized = Marshal.load(Marshal.dump(crl)) + + assert_equal crl.to_der, deserialized.to_der + assert_equal crl.revoked[0].to_der, deserialized.revoked[0].to_der + end + private def crl_error_returns_false diff --git a/ruby/test/openssl/test_x509ext.rb b/ruby/test/openssl/test_x509ext.rb index 91ce202fe..7ad010d1e 100644 --- a/ruby/test/openssl/test_x509ext.rb +++ b/ruby/test/openssl/test_x509ext.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -86,6 +86,19 @@ def test_eq assert_equal true, ext1 == ext2 assert_equal false, ext1 == ext3 end + + def test_marshal + ef = OpenSSL::X509::ExtensionFactory.new + ext = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2") + deserialized = Marshal.load(Marshal.dump(ext)) + + assert_equal ext.to_der, deserialized.to_der + end + + def test_value_der + ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der) + assert_equal @basic_constraints_value.to_der, ext.value_der + end end end diff --git a/ruby/test/openssl/test_x509name.rb b/ruby/test/openssl/test_x509name.rb index 8a4596ea6..c6d15219f 100644 --- a/ruby/test/openssl/test_x509name.rb +++ b/ruby/test/openssl/test_x509name.rb @@ -1,5 +1,5 @@ # coding: ASCII-8BIT -# frozen_string_literal: false +# frozen_string_literal: true require_relative 'utils' if defined?(OpenSSL) @@ -242,16 +242,15 @@ def test_s_parse_rfc2253 assert_match(/^multi-valued RDN is not supported: #{dn_r}/, ex.message) } - bad_dc = "exa#{"pm"}le" # <- typo of "example" [ - ["DC=org,DC=#{bad_dc},CN", "CN"], + ["DC=org,DC=exapmle,CN", "CN"], ["DC=org,DC=example,", ""], - ["DC=org,DC=#{bad_dc},CN=www.example.org;", "CN=www.example.org;"], - ["DC=org,DC=#{bad_dc},CN=#www.example.org", "CN=#www.example.org"], - ["DC=org,DC=#{bad_dc},CN=#777777.example.org", "CN=#777777.example.org"], - ["DC=org,DC=#{bad_dc},CN=\"www.example\".org", "CN=\"www.example\".org"], - ["DC=org,DC=#{bad_dc},CN=www.\"example.org\"", "CN=www.\"example.org\""], - ["DC=org,DC=#{bad_dc},CN=www.\"example\".org", "CN=www.\"example\".org"], + ["DC=org,DC=exapmle,CN=www.example.org;", "CN=www.example.org;"], + ["DC=org,DC=exapmle,CN=#www.example.org", "CN=#www.example.org"], + ["DC=org,DC=exapmle,CN=#777777.example.org", "CN=#777777.example.org"], + ["DC=org,DC=exapmle,CN=\"www.example\".org", "CN=\"www.example\".org"], + ["DC=org,DC=exapmle,CN=www.\"example.org\"", "CN=www.\"example.org\""], + ["DC=org,DC=exapmle,CN=www.\"example\".org", "CN=www.\"example\".org"], ].each{|dn, msg| ex = scanner.call(dn) rescue $! assert_match(/^malformed RDN: .*=>#{Regexp.escape(msg)}/, ex.message) @@ -390,7 +389,7 @@ def test_to_utf8 dn.each { |x| name.add_entry(*x) } str = name.to_utf8 - expected = "CN=フー\\, ãƒãƒ¼,DC=ruby-lang,DC=org".force_encoding("UTF-8") + expected = String.new("CN=フー\\, ãƒãƒ¼,DC=ruby-lang,DC=org").force_encoding("UTF-8") assert_equal expected, str assert_equal Encoding.find("UTF-8"), str.encoding @@ -403,6 +402,9 @@ def test_equals2 n2 = OpenSSL::X509::Name.parse_rfc2253 'CN=a' assert_equal n1, n2 + + assert_equal(false, n1 == 'abc') + assert_equal(false, n2 == nil) end def test_spaceship @@ -416,6 +418,9 @@ def test_spaceship assert_equal(-1, n2 <=> n3) assert_equal(1, n3 <=> n1) assert_equal(1, n3 <=> n2) + assert_equal(nil, n1 <=> 'abc') + assert_equal(nil, n2 <=> 123) + assert_equal(nil, n3 <=> nil) end def name_hash(name) @@ -427,13 +432,13 @@ def name_hash(name) def test_hash dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org" name = OpenSSL::X509::Name.parse(dn) - d = OpenSSL::Digest::MD5.digest(name.to_der) + d = OpenSSL::Digest.digest('MD5', name.to_der) expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24 assert_equal(expected, name_hash(name)) # dn = "/DC=org/DC=ruby-lang/CN=baz.ruby-lang.org" name = OpenSSL::X509::Name.parse(dn) - d = OpenSSL::Digest::MD5.digest(name.to_der) + d = OpenSSL::Digest.digest('MD5', name.to_der) expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24 assert_equal(expected, name_hash(name)) end @@ -448,6 +453,13 @@ def test_equality assert_equal false, name0.eql?(name2) end + def test_marshal + name = OpenSSL::X509::Name.new([["DC", "org"], ["DC", "ruby-lang"], ["CN", "bar.ruby-lang.org"]]) + deserialized = Marshal.load(Marshal.dump(name)) + + assert_equal name.to_der, deserialized.to_der + end + def test_dup name = OpenSSL::X509::Name.parse("/CN=ruby-lang.org") assert_equal(name.to_der, name.dup.to_der) diff --git a/ruby/test/openssl/test_x509req.rb b/ruby/test/openssl/test_x509req.rb index 2c447ccdd..ee9c678fb 100644 --- a/ruby/test/openssl/test_x509req.rb +++ b/ruby/test/openssl/test_x509req.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) @@ -23,31 +23,31 @@ def issue_csr(ver, dn, key, digest) end def test_public_key - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) end def test_version - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(0, req.version) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(0, req.version) - req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(1, req.version) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(1, req.version) end def test_subject - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(@dn.to_der, req.subject.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@dn.to_der, req.subject.to_der) @@ -78,9 +78,9 @@ def test_attr OpenSSL::X509::Attribute.new("msExtReq", attrval), ] - req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) attrs.each{|attr| req0.add_attribute(attr) } - req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) req1.attributes = attrs assert_equal(req0.to_der, req1.to_der) @@ -101,7 +101,7 @@ def test_attr end def test_sign_and_verify_rsa_sha1 - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(true, req.verify(@rsa1024)) assert_equal(false, req.verify(@rsa2048)) assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) @@ -111,7 +111,7 @@ def test_sign_and_verify_rsa_sha1 end def test_sign_and_verify_rsa_md5 - req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest::MD5.new) + req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest.new('MD5')) assert_equal(false, req.verify(@rsa1024)) assert_equal(true, req.verify(@rsa2048)) assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) @@ -122,7 +122,7 @@ def test_sign_and_verify_rsa_md5 end def test_sign_and_verify_dsa - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) assert_equal(false, request_error_returns_false { req.verify(@rsa1024) }) assert_equal(false, request_error_returns_false { req.verify(@rsa2048) }) assert_equal(false, req.verify(@dsa256)) @@ -133,11 +133,11 @@ def test_sign_and_verify_dsa def test_sign_and_verify_dsa_md5 assert_raise(OpenSSL::X509::RequestError){ - issue_csr(0, @dn, @dsa512, OpenSSL::Digest::MD5.new) } + issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('MD5')) } end def test_dup - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) assert_equal(req.to_der, req.dup.to_der) end @@ -151,6 +151,13 @@ def test_eq assert_equal false, req1 == req3 end + def test_marshal + req = issue_csr(0, @dn, @rsa1024, "sha256") + deserialized = Marshal.load(Marshal.dump(req)) + + assert_equal req.to_der, deserialized.to_der + end + private def request_error_returns_false diff --git a/ruby/test/openssl/test_x509store.rb b/ruby/test/openssl/test_x509store.rb index 6412249b9..d6c0e707a 100644 --- a/ruby/test/openssl/test_x509store.rb +++ b/ruby/test/openssl/test_x509store.rb @@ -1,40 +1,30 @@ -# frozen_string_literal: false +# frozen_string_literal: true require_relative "utils" if defined?(OpenSSL) class OpenSSL::TestX509Store < OpenSSL::TestCase - def setup - super - @rsa1024 = Fixtures.pkey("rsa1024") - @rsa2048 = Fixtures.pkey("rsa2048") - @dsa256 = Fixtures.pkey("dsa256") - @dsa512 = Fixtures.pkey("dsa512") - @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1") - @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2") - @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") - @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") - end - - def test_nosegv_on_cleanup - cert = OpenSSL::X509::Certificate.new - store = OpenSSL::X509::Store.new - ctx = OpenSSL::X509::StoreContext.new(store, cert, []) - EnvUtil.suppress_warning do - ctx.cleanup - end - ctx.verify + def test_store_new + # v2.3.0 emits explicit warning + assert_warning(/new does not take any arguments/) { + OpenSSL::X509::Store.new(123) + } end - def test_add_file + def test_add_file_path ca_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign,keyCertSign", true], ] - cert1 = issue_cert(@ca1, @rsa1024, 1, ca_exts, nil, nil) - cert2 = issue_cert(@ca2, @rsa2048, 1, ca_exts, nil, nil) - tmpfile = Tempfile.open { |f| f << cert1.to_pem << cert2.to_pem; f } + cert1_subj = OpenSSL::X509::Name.parse_rfc2253("CN=Cert 1") + cert1_key = Fixtures.pkey("rsa-1") + cert1 = issue_cert(cert1_subj, cert1_key, 1, ca_exts, nil, nil) + cert2_subj = OpenSSL::X509::Name.parse_rfc2253("CN=Cert 2") + cert2_key = Fixtures.pkey("rsa-2") + cert2 = issue_cert(cert2_subj, cert2_key, 1, ca_exts, nil, nil) + # X509::Store#add_file reads concatenated PEM file + tmpfile = Tempfile.open { |f| f << cert1.to_pem << cert2.to_pem; f } store = OpenSSL::X509::Store.new assert_equal false, store.verify(cert1) assert_equal false, store.verify(cert2) @@ -42,188 +32,322 @@ def test_add_file assert_equal true, store.verify(cert1) assert_equal true, store.verify(cert2) + # X509::Store#add_path + Dir.mktmpdir do |dir| + hash1 = "%08x.%d" % [cert1_subj.hash, 0] + File.write(File.join(dir, hash1), cert1.to_pem) + store = OpenSSL::X509::Store.new + store.add_path(dir) + + assert_equal true, store.verify(cert1) + assert_equal false, store.verify(cert2) + end + # OpenSSL < 1.1.1 leaks an error on a duplicate certificate assert_nothing_raised { store.add_file(tmpfile.path) } assert_equal [], OpenSSL.errors + + # Non-String is given + assert_raise(TypeError) { store.add_file(nil) } ensure tmpfile and tmpfile.close! end - def test_verify - # OpenSSL uses time(2) while Time.now uses clock_gettime(CLOCK_REALTIME), - # and there may be difference. - now = Time.now - 3 + def test_verify_simple ca_exts = [ - ["basicConstraints","CA:TRUE",true], - ["keyUsage","cRLSign,keyCertSign",true], + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign,keyCertSign", true], ] + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil) + ca2 = OpenSSL::X509::Name.parse_rfc2253("CN=Intermediate CA") + ca2_key = Fixtures.pkey("rsa-2") + ca2_cert = issue_cert(ca2, ca2_key, 2, ca_exts, ca1_cert, ca1_key) + ee_exts = [ - ["keyUsage","keyEncipherment,digitalSignature",true], + ["keyUsage", "keyEncipherment,digitalSignature", true], ] - ca1_cert = issue_cert(@ca1, @rsa2048, 1, ca_exts, nil, nil) - ca2_cert = issue_cert(@ca2, @rsa1024, 2, ca_exts, ca1_cert, @rsa2048, - not_after: now+1800) - ee1_cert = issue_cert(@ee1, @dsa256, 10, ee_exts, ca2_cert, @rsa1024) - ee2_cert = issue_cert(@ee2, @dsa512, 20, ee_exts, ca2_cert, @rsa1024) - ee3_cert = issue_cert(@ee2, @dsa512, 30, ee_exts, ca2_cert, @rsa1024, - not_before: now-100, not_after: now-1) - ee4_cert = issue_cert(@ee2, @dsa512, 40, ee_exts, ca2_cert, @rsa1024, - not_before: now+1000, not_after: now+2000,) + ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1") + ee1_key = Fixtures.pkey("rsa-3") + ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca2_cert, ca2_key) - revoke_info = [] - crl1 = issue_crl(revoke_info, 1, now, now+1800, [], - ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) - revoke_info = [ [2, now, 1], ] - crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [], - ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) - revoke_info = [ [20, now, 1], ] - crl2 = issue_crl(revoke_info, 1, now, now+1800, [], - ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) - revoke_info = [] - crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [], - ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new) + # Nothing trusted + store = OpenSSL::X509::Store.new + assert_equal(false, store.verify(ee1_cert, [ca2_cert, ca1_cert])) + assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, store.error) + assert_match(/self.signed/i, store.error_string) - assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed - assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1 - assert_equal(true, ee1_cert.verify(ca2_cert.public_key)) # issued by ca2 - assert_equal(true, ee2_cert.verify(ca2_cert.public_key)) # issued by ca2 - assert_equal(true, ee3_cert.verify(ca2_cert.public_key)) # issued by ca2 - assert_equal(true, crl1.verify(ca1_cert.public_key)) # issued by ca1 - assert_equal(true, crl1_2.verify(ca1_cert.public_key)) # issued by ca1 - assert_equal(true, crl2.verify(ca2_cert.public_key)) # issued by ca2 - assert_equal(true, crl2_2.verify(ca2_cert.public_key)) # issued by ca2 + # CA1 trusted, CA2 missing + store = OpenSSL::X509::Store.new + store.add_cert(ca1_cert) + assert_equal(false, store.verify(ee1_cert)) + assert_equal(OpenSSL::X509::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, store.error) + # CA1 trusted, CA2 supplied store = OpenSSL::X509::Store.new - assert_equal(false, store.verify(ca1_cert)) - assert_not_equal(OpenSSL::X509::V_OK, store.error) + store.add_cert(ca1_cert) + assert_equal(true, store.verify(ee1_cert, [ca2_cert])) + assert_match(/ok/i, store.error_string) + assert_equal(OpenSSL::X509::V_OK, store.error) + assert_equal([ee1_cert, ca2_cert, ca1_cert], store.chain) + end - assert_equal(false, store.verify(ca2_cert)) - assert_not_equal(OpenSSL::X509::V_OK, store.error) + def test_verify_callback + ca_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign,keyCertSign", true], + ] + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil) + ca2 = OpenSSL::X509::Name.parse_rfc2253("CN=Intermediate CA") + ca2_key = Fixtures.pkey("rsa-2") + ca2_cert = issue_cert(ca2, ca2_key, 2, ca_exts, ca1_cert, ca1_key) + ee_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ] + ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1") + ee1_key = Fixtures.pkey("rsa-3") + ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca2_cert, ca2_key) + + # verify_callback on X509::Store is called with proper arguments + cb_calls = [] + store = OpenSSL::X509::Store.new + store.verify_callback = -> (preverify_ok, sctx) { + cb_calls << [preverify_ok, sctx.current_cert] + preverify_ok + } store.add_cert(ca1_cert) - assert_equal(true, store.verify(ca2_cert)) - assert_equal(OpenSSL::X509::V_OK, store.error) - assert_equal("ok", store.error_string) - chain = store.chain - assert_equal(2, chain.size) - assert_equal(@ca2.to_der, chain[0].subject.to_der) - assert_equal(@ca1.to_der, chain[1].subject.to_der) + assert_equal(true, store.verify(ee1_cert, [ca2_cert])) + assert_include([2, 3, 4, 5], cb_calls.size) + cb_calls.each do |pre_ok, cert| + assert_equal(true, pre_ok) + assert_include([ca1_cert, ca2_cert, ee1_cert], cert) + end - store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT - assert_equal(false, store.verify(ca2_cert)) - assert_not_equal(OpenSSL::X509::V_OK, store.error) + # verify_callback can change verification result + store = OpenSSL::X509::Store.new + store.verify_callback = -> (preverify_ok, sctx) { + next preverify_ok if sctx.current_cert != ee1_cert + sctx.error = OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION + false + } + store.add_cert(ca1_cert) + assert_equal(false, store.verify(ee1_cert, [ca2_cert])) + assert_equal(OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION, store.error) - store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN - assert_equal(true, store.verify(ca2_cert)) - assert_equal(OpenSSL::X509::V_OK, store.error) + # Exception raised by verify_callback is currently suppressed, and is + # treated as a non-truthy return (with warning) + store = OpenSSL::X509::Store.new + store.verify_callback = -> (preverify_ok, sctx) { + raise "suppressed" + } + store.add_cert(ca1_cert) + assert_warning(/exception in verify_callback/) { + assert_equal(false, store.verify(ee1_cert, [ca2_cert])) + } - store.add_cert(ca2_cert) - store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT - assert_equal(true, store.verify(ee1_cert)) - assert_equal(true, store.verify(ee2_cert)) - assert_equal(OpenSSL::X509::V_OK, store.error) - assert_equal("ok", store.error_string) - chain = store.chain - assert_equal(3, chain.size) - assert_equal(@ee2.to_der, chain[0].subject.to_der) - assert_equal(@ca2.to_der, chain[1].subject.to_der) - assert_equal(@ca1.to_der, chain[2].subject.to_der) - assert_equal(false, store.verify(ee3_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) - assert_match(/expire/i, store.error_string) - assert_equal(false, store.verify(ee4_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) - assert_match(/not yet valid/i, store.error_string) + # The block given to X509::Store#verify replaces it + called = nil + store = OpenSSL::X509::Store.new + store.verify_callback = -> (preverify_ok, sctx) { called = :store; preverify_ok } + store.add_cert(ca1_cert) + blk = proc { |preverify_ok, sctx| called = :block; preverify_ok } + assert_equal(true, store.verify(ee1_cert, [ca2_cert], &blk)) + assert_equal(:block, called) + end + + def test_verify_purpose + ca_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign,keyCertSign", true], + ] + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil) + + ee_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ] + ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1") + ee1_key = Fixtures.pkey("rsa-3") + ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca1_cert, ca1_key) + # Purpose not set store = OpenSSL::X509::Store.new store.add_cert(ca1_cert) - store.add_cert(ca2_cert) - store.time = now + 1500 assert_equal(true, store.verify(ca1_cert)) - assert_equal(true, store.verify(ca2_cert)) - assert_equal(true, store.verify(ee4_cert)) - store.time = now + 1900 + assert_equal(true, store.verify(ee1_cert)) + + # Purpose set to X509::PURPOSE_SSL_CLIENT; keyUsage is checked + store = OpenSSL::X509::Store.new + store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN + store.add_cert(ca1_cert) assert_equal(true, store.verify(ca1_cert)) - assert_equal(false, store.verify(ca2_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) - assert_equal(false, store.verify(ee4_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) - store.time = now + 4000 assert_equal(false, store.verify(ee1_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) - assert_equal(false, store.verify(ee4_cert)) - assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) + end - # the underlying X509 struct caches the result of the last - # verification for signature and not-before. so the following code - # rebuilds new objects to avoid site effect. - store.time = Time.now - 4000 - assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ca2_cert))) + def test_verify_validity_period + # Creating test certificates with validity periods: + # + # now-5000 now-1000 now+1000 now+5000 + # CA1:|---------------------------------------------------------------| + # EE1:|---------------------------------------------------------------| + # EE2:|-------------------------| + # EE3: |-------------------------| + now = Time.now + ca_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign,keyCertSign", true], + ] + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil, + not_before: now - 5000, not_after: now + 5000) + + ee_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ] + ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1") + ee1_key = Fixtures.pkey("rsa-1") + ee1_cert = issue_cert(ee1, ee1_key, 11, ee_exts, ca1_cert, ca1_key, + not_before: now - 5000, not_after: now + 5000) + ee2 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 2") + ee2_key = Fixtures.pkey("rsa-2") + ee2_cert = issue_cert(ee2, ee2_key, 12, ee_exts, ca1_cert, ca1_key, + not_before: now - 5000, not_after: now - 1000) + ee3 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 3") + ee3_key = Fixtures.pkey("rsa-3") + ee3_cert = issue_cert(ee3, ee3_key, 13, ee_exts, ca1_cert, ca1_key, + not_before: now + 1000, not_after: now + 5000) + + # Using system time + store = OpenSSL::X509::Store.new + store.add_cert(ca1_cert) + assert_equal(true, store.verify(ee1_cert)) + assert_equal(false, store.verify(ee2_cert)) + assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) + assert_equal(false, store.verify(ee3_cert)) assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) - assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert))) + + # Time set to now-2000; EE2 is still valid + store = OpenSSL::X509::Store.new + store.time = now - 2000 + store.add_cert(ca1_cert) + assert_equal(true, store.verify(ee1_cert)) + assert_equal(true, store.verify(ee2_cert)) + assert_equal(false, store.verify(ee3_cert)) assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) + end + + def test_verify_with_crl + ca_exts = [ + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "cRLSign,keyCertSign", true], + ] + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, ca_exts, nil, nil) + ca2 = OpenSSL::X509::Name.parse_rfc2253("CN=Intermediate CA") + ca2_key = Fixtures.pkey("rsa-2") + ca2_cert = issue_cert(ca2, ca2_key, 2, ca_exts, ca1_cert, ca1_key) + + ee_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ] + ee1 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 1") + ee1_key = Fixtures.pkey("rsa-3") + ee1_cert = issue_cert(ee1, ee1_key, 10, ee_exts, ca2_cert, ca2_key) + ee2 = OpenSSL::X509::Name.parse_rfc2253("CN=EE 2") + ee2_key = Fixtures.pkey("rsa-3") + ee2_cert = issue_cert(ee2, ee2_key, 20, ee_exts, ca2_cert, ca2_key) + + # OpenSSL uses time(2) while Time.now uses clock_gettime(CLOCK_REALTIME), + # and there may be difference, so giving 50 seconds margin. + now = Time.now - 50 + revoke_info = [] + ca1_crl1 = issue_crl(revoke_info, 1, now, now+1800, [], ca1_cert, ca1_key, "sha256") + revoke_info = [ [2, now, 1], ] + ca1_crl2 = issue_crl(revoke_info, 2, now, now+1800, [], ca1_cert, ca1_key, "sha256") + + revoke_info = [ [20, now, 1], ] + ca2_crl1 = issue_crl(revoke_info, 1, now, now+1800, [], ca2_cert, ca2_key, "sha256") + revoke_info = [] + ca2_crl2 = issue_crl(revoke_info, 2, now-100, now-1, [], ca2_cert, ca2_key, "sha256") + # CRL check required, but no CRL supplied store = OpenSSL::X509::Store.new - store.purpose = OpenSSL::X509::PURPOSE_ANY store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK store.add_cert(ca1_cert) - store.add_crl(crl1) # revoke no cert - store.add_crl(crl2) # revoke ee2_cert - assert_equal(true, store.verify(ca1_cert)) - assert_equal(true, store.verify(ca2_cert)) - assert_equal(true, store.verify(ee1_cert, [ca2_cert])) + assert_equal(false, store.verify(ca2_cert)) + assert_equal(OpenSSL::X509::V_ERR_UNABLE_TO_GET_CRL, store.error) + + # Intermediate CA revoked EE2 + store = OpenSSL::X509::Store.new + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK + store.add_cert(ca1_cert) + store.add_crl(ca1_crl1) # revoke no cert + store.add_crl(ca2_crl1) # revoke ee2_cert + assert_equal(true, store.verify(ca2_cert)) + assert_equal(true, store.verify(ee1_cert, [ca2_cert])) assert_equal(false, store.verify(ee2_cert, [ca2_cert])) + # Root CA revoked Intermediate CA; Intermediate CA revoked EE2 store = OpenSSL::X509::Store.new - store.purpose = OpenSSL::X509::PURPOSE_ANY store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK store.add_cert(ca1_cert) - store.add_crl(crl1_2) # revoke ca2_cert - store.add_crl(crl2) # revoke ee2_cert - assert_equal(true, store.verify(ca1_cert)) + store.add_crl(ca1_crl2) # revoke ca2_cert + store.add_crl(ca2_crl1) # revoke ee2_cert assert_equal(false, store.verify(ca2_cert)) - assert_equal(true, store.verify(ee1_cert, [ca2_cert]), - "This test is expected to be success with OpenSSL 0.9.7c or later.") + # Validity of intermediate CAs is not checked by default + assert_equal(true, store.verify(ee1_cert, [ca2_cert])) assert_equal(false, store.verify(ee2_cert, [ca2_cert])) - store.flags = - OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL - assert_equal(true, store.verify(ca1_cert)) + # Same as above, but with OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + store = OpenSSL::X509::Store.new + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + store.add_cert(ca1_cert) + store.add_crl(ca1_crl2) # revoke ca2_cert + store.add_crl(ca2_crl1) # revoke ee2_cert assert_equal(false, store.verify(ca2_cert)) assert_equal(false, store.verify(ee1_cert, [ca2_cert])) assert_equal(false, store.verify(ee2_cert, [ca2_cert])) + # Expired CRL supplied store = OpenSSL::X509::Store.new - store.purpose = OpenSSL::X509::PURPOSE_ANY - store.flags = - OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL store.add_cert(ca1_cert) store.add_cert(ca2_cert) - store.add_crl(crl1) - store.add_crl(crl2_2) # issued by ca2 but expired. - assert_equal(true, store.verify(ca1_cert)) + store.add_crl(ca1_crl1) + store.add_crl(ca2_crl2) # issued by ca2 but expired assert_equal(true, store.verify(ca2_cert)) assert_equal(false, store.verify(ee1_cert)) assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error) assert_equal(false, store.verify(ee2_cert)) end - def test_set_errors + def test_add_cert_duplicate + # Up until OpenSSL 1.1.0, X509_STORE_add_{cert,crl}() returned an error + # if the given certificate is already in the X509_STORE return if openssl?(1, 1, 0) || libressl? - now = Time.now - ca1_cert = issue_cert(@ca1, @rsa2048, 1, [], nil, nil) + ca1 = OpenSSL::X509::Name.parse_rfc2253("CN=Root CA") + ca1_key = Fixtures.pkey("rsa-1") + ca1_cert = issue_cert(ca1, ca1_key, 1, [], nil, nil) store = OpenSSL::X509::Store.new store.add_cert(ca1_cert) assert_raise(OpenSSL::X509::StoreError){ store.add_cert(ca1_cert) # add same certificate twice } + now = Time.now revoke_info = [] crl1 = issue_crl(revoke_info, 1, now, now+1800, [], - ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) + ca1_cert, ca1_key, "sha256") revoke_info = [ [2, now, 1], ] crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [], - ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) + ca1_cert, ca1_key, "sha256") store.add_crl(crl1) assert_raise(OpenSSL::X509::StoreError){ store.add_crl(crl2) # add CRL issued by same CA twice. @@ -236,6 +360,14 @@ def test_dup ctx = OpenSSL::X509::StoreContext.new(store) assert_raise(NoMethodError) { ctx.dup } end + + def test_ctx_cleanup + # Deprecated in Ruby 1.9.3 + cert = OpenSSL::X509::Certificate.new + store = OpenSSL::X509::Store.new + ctx = OpenSSL::X509::StoreContext.new(store, cert, []) + assert_warning(/cleanup/) { ctx.cleanup } + end end end diff --git a/ruby/test/openssl/ut_eof.rb b/ruby/test/openssl/ut_eof.rb index bd62fd50f..7b18f43a7 100644 --- a/ruby/test/openssl/ut_eof.rb +++ b/ruby/test/openssl/ut_eof.rb @@ -1,9 +1,13 @@ -# frozen_string_literal: false +# frozen_string_literal: true require 'test/unit' if defined?(OpenSSL) module OpenSSL::TestEOF + def test_getbyte_eof + open_file("") {|f| assert_nil f.getbyte } + end + def test_eof_0 open_file("") {|f| assert_equal("", f.read(0)) @@ -18,12 +22,12 @@ def test_eof_0 assert_nil(f.read(1)) } open_file("") {|f| - s = "x" + s = +"x" assert_equal("", f.read(nil, s)) assert_equal("", s) } open_file("") {|f| - s = "x" + s = +"x" assert_nil(f.read(10, s)) assert_equal("", s) } @@ -75,12 +79,12 @@ def test_eof_1 assert_equal("", f.read(0)) } open_file("a") {|f| - s = "x" + s = +"x" assert_equal("a", f.read(nil, s)) assert_equal("a", s) } open_file("a") {|f| - s = "x" + s = +"x" assert_equal("a", f.read(10, s)) assert_equal("a", s) } diff --git a/ruby/test/openssl/utils.rb b/ruby/test/openssl/utils.rb index bf1916305..4ebcb9837 100644 --- a/ruby/test/openssl/utils.rb +++ b/ruby/test/openssl/utils.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true begin require "openssl" @@ -42,9 +42,6 @@ module Fixtures def pkey(name) OpenSSL::PKey.read(read_file("pkey", name)) - rescue OpenSSL::PKey::PKeyError - # TODO: DH parameters can be read by OpenSSL::PKey.read atm - OpenSSL::PKey::DH.new(read_file("pkey", name)) end def read_file(category, name) @@ -52,15 +49,18 @@ def read_file(category, name) @file_cache[[category, name]] ||= File.read(File.join(__dir__, "fixtures", category, name + ".pem")) end + + def file_path(category, name) + File.join(__dir__, "fixtures", category, name) + end end module_function - def issue_cert(dn, key, serial, extensions, issuer, issuer_key, - not_before: nil, not_after: nil, digest: "sha256") + def generate_cert(dn, key, serial, issuer, + not_before: nil, not_after: nil) cert = OpenSSL::X509::Certificate.new issuer = cert unless issuer - issuer_key = key unless issuer_key cert.version = 2 cert.serial = serial cert.subject = dn @@ -69,6 +69,16 @@ def issue_cert(dn, key, serial, extensions, issuer, issuer_key, now = Time.now cert.not_before = not_before || now - 3600 cert.not_after = not_after || now + 3600 + cert + end + + + def issue_cert(dn, key, serial, extensions, issuer, issuer_key, + not_before: nil, not_after: nil, digest: "sha256") + cert = generate_cert(dn, key, serial, issuer, + not_before: not_before, not_after: not_after) + issuer = cert unless issuer + issuer_key = key unless issuer_key ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = issuer @@ -107,13 +117,18 @@ def issue_crl(revoke_info, serial, lastup, nextup, extensions, crl end - def get_subject_key_id(cert) + def get_subject_key_id(cert, hex: true) asn1_cert = OpenSSL::ASN1.decode(cert) tbscert = asn1_cert.value[0] pkinfo = tbscert.value[6] publickey = pkinfo.value[1] pkvalue = publickey.value - OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase + digest = OpenSSL::Digest.digest('SHA1', pkvalue) + if hex + digest.unpack("H2"*20).join(":").upcase + else + digest + end end def openssl?(major = nil, minor = nil, fix = nil, patch = 0) @@ -174,9 +189,10 @@ def setup @server = nil end - def tls12_supported? + def tls13_supported? + return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION) ctx = OpenSSL::SSL::SSLContext.new - ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION true rescue end @@ -189,6 +205,7 @@ def readwrite_loop(ctx, ssl) def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true, ctx_proc: nil, server_proc: method(:readwrite_loop), + accept_proc: proc{}, ignore_listener_error: false, &block) IO.pipe {|stop_pipe_r, stop_pipe_w| store = OpenSSL::X509::Store.new @@ -198,7 +215,6 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true ctx.cert_store = store ctx.cert = @svr_cert ctx.key = @svr_key - ctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") } ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc @@ -212,9 +228,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true threads = [] begin server_thread = Thread.new do - if Thread.method_defined?(:report_on_exception=) # Ruby >= 2.4 - Thread.current.report_on_exception = false - end + Thread.current.report_on_exception = false begin loop do @@ -222,6 +236,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true readable, = IO.select([ssls, stop_pipe_r]) break if readable.include? stop_pipe_r ssl = ssls.accept + accept_proc.call(ssl) rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET retry if ignore_listener_error @@ -229,9 +244,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true end th = Thread.new do - if Thread.method_defined?(:report_on_exception=) - Thread.current.report_on_exception = false - end + Thread.current.report_on_exception = false begin server_proc.call(ctx, ssl) @@ -248,9 +261,7 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true end client_thread = Thread.new do - if Thread.method_defined?(:report_on_exception=) - Thread.current.report_on_exception = false - end + Thread.current.report_on_exception = false begin block.call(port) @@ -268,9 +279,8 @@ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true begin timeout = EnvUtil.apply_timeout_scale(30) th.join(timeout) or - th.raise(RuntimeError, "[start_server] thread did not exit in #{ timeout } secs") - rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError) - # MiniTest::Skip is for the Ruby tree + th.raise(RuntimeError, "[start_server] thread did not exit in #{timeout} secs") + rescue Test::Unit::PendedError pend = $! rescue Exception end @@ -288,31 +298,63 @@ def check_component(base, test, keys) assert_equal base.send(comp), test.send(comp) } end +end - def dup_public(key) - case key - when OpenSSL::PKey::RSA - rsa = OpenSSL::PKey::RSA.new - rsa.set_key(key.n, key.e, nil) - rsa - when OpenSSL::PKey::DSA - dsa = OpenSSL::PKey::DSA.new - dsa.set_pqg(key.p, key.q, key.g) - dsa.set_key(key.pub_key, nil) - dsa - when OpenSSL::PKey::DH - dh = OpenSSL::PKey::DH.new - dh.set_pqg(key.p, nil, key.g) - dh - else - if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key - ec = OpenSSL::PKey::EC.new(key.group) - ec.public_key = key.public_key - ec - else - raise "unknown key type" - end - end +module OpenSSL::Certs + include OpenSSL::TestUtils + + module_function + + def ca_cert + ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Timestamp Root CA") + + ca_exts = [ + ["basicConstraints","CA:TRUE,pathlen:1",true], + ["keyUsage","keyCertSign, cRLSign",true], + ["subjectKeyIdentifier","hash",false], + ["authorityKeyIdentifier","keyid:always",false], + ] + OpenSSL::TestUtils.issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil) + end + + def ts_cert_direct(key, ca_cert) + dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Server Direct") + + exts = [ + ["basicConstraints","CA:FALSE",true], + ["keyUsage","digitalSignature, nonRepudiation", true], + ["subjectKeyIdentifier", "hash",false], + ["authorityKeyIdentifier","keyid,issuer", false], + ["extendedKeyUsage", "timeStamping", true] + ] + + OpenSSL::TestUtils.issue_cert(dn, key, 2, exts, ca_cert, Fixtures.pkey("rsa2048")) + end + + def intermediate_cert(key, ca_cert) + dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Timestamp Intermediate CA") + + exts = [ + ["basicConstraints","CA:TRUE,pathlen:0",true], + ["keyUsage","keyCertSign, cRLSign",true], + ["subjectKeyIdentifier","hash",false], + ["authorityKeyIdentifier","keyid:always",false], + ] + + OpenSSL::TestUtils.issue_cert(dn, key, 3, exts, ca_cert, Fixtures.pkey("rsa2048")) + end + + def ts_cert_ee(key, intermediate, im_key) + dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Server End Entity") + + exts = [ + ["keyUsage","digitalSignature, nonRepudiation", true], + ["subjectKeyIdentifier", "hash",false], + ["authorityKeyIdentifier","keyid,issuer", false], + ["extendedKeyUsage", "timeStamping", true] + ] + + OpenSSL::TestUtils.issue_cert(dn, key, 4, exts, intermediate, im_key) end end diff --git a/ruby/test/optparse/test_acceptable.rb b/ruby/test/optparse/test_acceptable.rb index 5c3fbdb10..12f788653 100644 --- a/ruby/test/optparse/test_acceptable.rb +++ b/ruby/test/optparse/test_acceptable.rb @@ -196,4 +196,3 @@ def test_decimal_numeric end end - diff --git a/ruby/test/optparse/test_did_you_mean.rb b/ruby/test/optparse/test_did_you_mean.rb index 763062586..a9ad051f0 100644 --- a/ruby/test/optparse/test_did_you_mean.rb +++ b/ruby/test/optparse/test_did_you_mean.rb @@ -13,11 +13,7 @@ def setup @opt.def_option("--bar", Integer) { |v| @bar = v } @opt.def_option("--baz", Integer) { |v| @baz = v } @formatter = ::DidYouMean.formatter - case @formatter - when ::DidYouMean::PlainFormatter - else - ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new - end + ::DidYouMean.formatter = ::DidYouMean::Formatter end def teardown @@ -36,15 +32,7 @@ def test_plain end end - def test_verbose - require 'did_you_mean/formatters/verbose_formatter' - ::DidYouMean.formatter = ::DidYouMean::VerboseFormatter.new - assert_raise_with_message(OptionParser::InvalidOption, /invalid option: --baa\n\s+Did you mean\?\s+bar\s+baz\s*\Z/) do - @opt.permute!(%w"--baa") - end - end - - def test_ambiguos + def test_ambiguous assert_raise_with_message(OptionParser::AmbiguousOption, /ambiguous option: --ba\nDid you mean\?\s+bar\s+baz\Z/) do @opt.permute!(%w"--ba") end diff --git a/ruby/test/optparse/test_optparse.rb b/ruby/test/optparse/test_optparse.rb index e4aeb07aa..5f5ea183b 100644 --- a/ruby/test/optparse/test_optparse.rb +++ b/ruby/test/optparse/test_optparse.rb @@ -75,4 +75,34 @@ def test_into assert_equal({host: "localhost", port: 8000, verbose: true}, result) assert_equal(true, @verbose) end + + def test_require_exact + @opt.def_option('-F', '--zrs=IRS', 'zrs') + %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg| + result = {} + @opt.parse([arg, 'foo'], into: result) + assert_equal({zrs: 'foo'}, result) + end + + @opt.require_exact = true + %w(--zrs -F -Ffoo).each do |arg| + result = {} + @opt.parse([arg, 'foo'], into: result) + assert_equal({zrs: 'foo'}, result) + end + + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo))} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo))} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo))} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo))} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo))} + end + + def test_nonopt_pattern + @opt.def_option(/^[^-]/) do |arg| + assert(false, "Never gets called") + end + e = assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-t))} + assert_equal(["-t"], e.args) + end end diff --git a/ruby/test/ostruct/test_ostruct.rb b/ruby/test/ostruct/test_ostruct.rb index 61a482281..6487cc831 100644 --- a/ruby/test/ostruct/test_ostruct.rb +++ b/ruby/test/ostruct/test_ostruct.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'test/unit' require 'ostruct' +require 'yaml' class TC_OpenStruct < Test::Unit::TestCase def test_initialize @@ -66,16 +67,15 @@ def test_frozen o = OpenStruct.new(foo: 42) o.a = 'a' o.freeze - expected_error = defined?(FrozenError) ? FrozenError : RuntimeError - assert_raise(expected_error) {o.b = 'b'} + assert_raise(FrozenError) {o.b = 'b'} assert_not_respond_to(o, :b) - assert_raise(expected_error) {o.a = 'z'} + assert_raise(FrozenError) {o.a = 'z'} assert_equal('a', o.a) assert_equal(42, o.foo) o = OpenStruct.new :a => 42 def o.frozen?; nil end o.freeze - assert_raise(expected_error, '[ruby-core:22559]') {o.a = 1764} + assert_raise(FrozenError, '[ruby-core:22559]') {o.a = 1764} end def test_delete_field @@ -89,7 +89,7 @@ def test_delete_field a = o.delete_field :a assert_not_respond_to(o, :a, bug) assert_not_respond_to(o, :a=, bug) - assert_equal(a, 'a') + assert_equal('a', a) s = Object.new def s.to_sym :foo @@ -100,6 +100,19 @@ def s.to_sym o.delete_field s assert_not_respond_to(o, :foo) assert_not_respond_to(o, :foo=) + + assert_raise(NameError) { o.delete_field(s) } + assert_equal(:bar, o.delete_field(s) { :bar }) + + o[s] = :foobar + assert_respond_to(o, :foo) + assert_respond_to(o, :foo=) + assert_equal(:foobar, o.delete_field(s) { :baz }) + + assert_equal(42, OpenStruct.new(foo: 42).delete_field(:foo) { :bug }) + + o = OpenStruct.new(block_given?: 42) + assert_raise(NameError) { o.delete_field(:foo) } end def test_setter @@ -179,19 +192,21 @@ def test_method_missing def test_accessor_defines_method os = OpenStruct.new(foo: 42) - assert os.respond_to? :foo - assert_equal([], os.singleton_methods) + assert_respond_to(os, :foo) assert_equal(42, os.foo) assert_equal([:foo, :foo=], os.singleton_methods.sort) end def test_does_not_redefine + $VERBOSE, verbose_bak = nil, $VERBOSE os = OpenStruct.new(foo: 42) def os.foo 43 end os.foo = 44 assert_equal(43, os.foo) + ensure + $VERBOSE = verbose_bak end def test_allocate_subclass @@ -203,6 +218,15 @@ def initialize(x,y={})super(y);end assert_instance_of(c, os) end + def test_initialize_subclass + c = Class.new(OpenStruct) { + def initialize(x,y={})super(y);end + } + o = c.new(1, {a: 42}) + assert_equal(42, o.dup.a) + assert_equal(42, o.clone.a) + end + def test_private_method os = OpenStruct.new class << os @@ -226,4 +250,160 @@ def foo os.foo true, true end end + + def test_access_undefined + os = OpenStruct.new + assert_nil os.foo + end + + def test_overridden_private_methods + os = OpenStruct.new(puts: :foo, format: :bar) + assert_equal(:foo, os.puts) + assert_equal(:bar, os.format) + end + + def test_super + c = Class.new(OpenStruct) { + def foo; super; end + } + os = c.new(foo: :bar) + assert_equal(:bar, os.foo) + end + + def test_overridden_public_methods + os = OpenStruct.new(method: :foo, class: :bar) + assert_equal(:foo, os.method) + assert_equal(:bar, os.class) + end + + def test_access_original_methods + os = OpenStruct.new(method: :foo, hash: 42) + assert_equal(os.object_id, os.method!(:object_id).call) + assert_not_equal(42, os.hash!) + refute os.methods.include?(:"!~!") + end + + def test_override_subclass + c = Class.new(OpenStruct) { + def foo; :protect_me; end + private def bar; :protect_me; end + def inspect; 'protect me'; end + } + o = c.new( + foo: 1, bar: 2, inspect: '3', # in subclass: protected + table!: 4, # bang method: protected + each_pair: 5, to_s: 'hello', # others: not protected + ) + # protected: + assert_equal(:protect_me, o.foo) + assert_equal(:protect_me, o.send(:bar)) + assert_equal('protect me', o.inspect) + assert_not_equal(4, o.send(:table!)) + # not protected: + assert_equal(5, o.each_pair) + assert_equal('hello', o.to_s) + end + + def test_override_submodule + m = Module.new { + def foo; :protect_me; end + private def bar; :protect_me; end + def inspect; 'protect me'; end + } + m2 = Module.new { + def added_to_all_open_struct; :override_me; end + } + OpenStruct.class_eval do + include m2 + # prepend case tbd + def added_to_all_open_struct_2; :override_me; end + end + c = Class.new(OpenStruct) { include m } + o = c.new( + foo: 1, bar: 2, inspect: '3', # in subclass: protected + table!: 4, # bang method: protected + each_pair: 5, to_s: 'hello', # others: not protected + # including those added by the user: + added_to_all_open_struct: 6, added_to_all_open_struct_2: 7, + ) + # protected: + assert_equal(:protect_me, o.foo) + assert_equal(:protect_me, o.send(:bar)) + assert_equal('protect me', o.inspect) + assert_not_equal(4, o.send(:table!)) + # not protected: + assert_equal(5, o.each_pair) + assert_equal('hello', o.to_s) + assert_equal(6, o.added_to_all_open_struct) + assert_equal(7, o.added_to_all_open_struct_2) + end + + def test_mistaken_subclass + sub = Class.new(OpenStruct) do + def [](k) + __send__(k) + super + end + + def []=(k, v) + @item_set = true + __send__("#{k}=", v) + super + end + end + o = sub.new + o.foo = 42 + assert_equal 42, o.foo + end + + def test_ractor + assert_ractor(<<~RUBY, require: 'ostruct') + obj1 = OpenStruct.new(a: 42, b: 42) + obj1.c = 42 + obj1.freeze + + obj2 = Ractor.new obj1 do |obj| + obj + end.take + assert obj1.object_id == obj2.object_id + RUBY + end if defined?(Ractor) + + def test_access_methods_from_different_ractor + assert_ractor(<<~RUBY, require: 'ostruct') + os = OpenStruct.new + os.value = 100 + r = Ractor.new(os) do |x| + v = x.value + Ractor.yield v + end + assert 100 == r.take + RUBY + end if defined?(Ractor) + + def test_legacy_yaml + s = "--- !ruby/object:OpenStruct\ntable:\n :foo: 42\n" + o = YAML.safe_load(s, permitted_classes: [Symbol, OpenStruct]) + assert_equal(42, o.foo) + + o = OpenStruct.new(table: {foo: 42}) + assert_equal({foo: 42}, YAML.safe_load(YAML.dump(o), permitted_classes: [Symbol, OpenStruct]).table) + end if RUBY_VERSION >= '2.6' + + def test_yaml + h = {name: "John Smith", age: 70, pension: 300.42} + yaml = "--- !ruby/object:OpenStruct\nname: John Smith\nage: 70\npension: 300.42\n" + os1 = OpenStruct.new(h) + os2 = YAML.safe_load(os1.to_yaml, permitted_classes: [Symbol, OpenStruct]) + assert_equal yaml, os1.to_yaml + assert_equal os1, os2 + assert_equal true, os1.eql?(os2) + assert_equal 300.42, os2.pension + end if RUBY_VERSION >= '2.6' + + def test_marshal + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300.42) + o2 = Marshal.load(Marshal.dump(o)) + assert_equal o, o2 + end end diff --git a/ruby/test/pathname/test_pathname.rb b/ruby/test/pathname/test_pathname.rb index 792510bdf..9e14668c9 100644 --- a/ruby/test/pathname/test_pathname.rb +++ b/ruby/test/pathname/test_pathname.rb @@ -269,17 +269,17 @@ def relative?(path) Pathname.new(path).relative? end + defassert(:relative?, true, '') defassert(:relative?, false, '/') defassert(:relative?, false, '/a') defassert(:relative?, false, '/..') defassert(:relative?, true, 'a') defassert(:relative?, true, 'a/b') - if DOSISH_DRIVE_LETTER - defassert(:relative?, false, 'A:') - defassert(:relative?, false, 'A:/') - defassert(:relative?, false, 'A:/a') - end + defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:.') + defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:') + defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:/') + defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:/a') if File.dirname('//') == '//' defassert(:relative?, false, '//') @@ -345,9 +345,26 @@ def with_tmpchdir(base=nil) def has_symlink? begin File.symlink("", "") - rescue NotImplementedError, Errno::EACCES + rescue NotImplementedError return false rescue Errno::ENOENT + return false + rescue Errno::EACCES + return false + end + return true + end + + def has_hardlink? + begin + with_tmpchdir("rubytest-pathname") {|dir| + File.write("dummy", "dummy") + File.link("dummy", "hardlink") + } + rescue NotImplementedError + return false + rescue Errno::EACCES + return false end return true end @@ -616,7 +633,7 @@ def test_to_s def test_kernel_open count = 0 result = Kernel.open(Pathname.new(__FILE__)) {|f| - assert(File.identical?(__FILE__, f)) + assert_file.identical?(__FILE__, f) count += 1 2 } @@ -690,6 +707,32 @@ def test_each_line } end + def test_each_line_opts + with_tmpchdir('rubytest-pathname') {|dir| + open("a", "w") {|f| f.puts 1, 2 } + a = [] + Pathname("a").each_line(chomp: true) {|line| a << line } + assert_equal(["1", "2"], a) + + a = [] + Pathname("a").each_line("2", chomp: true) {|line| a << line } + assert_equal(["1\n", "\n"], a) + + a = [] + Pathname("a").each_line(1, chomp: true) {|line| a << line } + assert_equal(["1", "", "2", ""], a) + + a = [] + Pathname("a").each_line("2", 1, chomp: true) {|line| a << line } + assert_equal(["1", "\n", "", "\n"], a) + + a = [] + enum = Pathname("a").each_line(chomp: true) + enum.each {|line| a << line } + assert_equal(["1", "2"], a) + } + end + def test_readlines with_tmpchdir('rubytest-pathname') {|dir| open("a", "w") {|f| f.puts 1, 2 } @@ -772,7 +815,7 @@ def test_atime end def test_birthtime - skip if RUBY_PLATFORM =~ /android/ + omit if RUBY_PLATFORM =~ /android/ # Check under a (probably) local filesystem. # Remote filesystems often may not support birthtime. with_tmpchdir('rubytest-pathname') do |dir| @@ -780,9 +823,9 @@ def test_birthtime assert_kind_of(Time, Pathname("a").birthtime) rescue Errno::EPERM # Docker prohibits statx syscall by the default. - skip("statx(2) is prohibited by seccomp") + omit("statx(2) is prohibited by seccomp") rescue Errno::ENOSYS - skip("statx(2) is not supported on this filesystem") + omit("statx(2) is not supported on this filesystem") rescue NotImplementedError # assert_raise(NotImplementedError) do # File.birthtime("a") @@ -818,7 +861,7 @@ def test_lchmod old = path.lstat.mode begin path.lchmod(0444) - rescue NotImplementedError + rescue NotImplementedError, Errno::EOPNOTSUPP next end assert_equal(0444, path.lstat.mode & 0777) @@ -886,6 +929,7 @@ def test_ftype end def test_make_link + return if !has_hardlink? with_tmpchdir('rubytest-pathname') {|dir| open("a", "w") {|f| f.write "abc" } Pathname("l").make_link(Pathname("a")) @@ -1023,6 +1067,21 @@ def test_expand_path def test_split assert_equal([Pathname("dirname"), Pathname("basename")], Pathname("dirname/basename").split) + + assert_separately([], <<-'end;') + require 'pathname' + + mod = Module.new do + def split(_arg) + end + end + + File.singleton_class.prepend(mod) + + assert_raise(TypeError) do + Pathname('/').split + end + end; end def test_blockdev? @@ -1061,7 +1120,7 @@ def test_exist? end def test_grpowned? - skip "Unix file owner test" if DOSISH + omit "Unix file owner test" if DOSISH with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } File.chown(-1, Process.gid, "f") @@ -1116,7 +1175,7 @@ def test_readable? end def test_world_readable? - skip "Unix file mode bit test" if DOSISH + omit "Unix file mode bit test" if DOSISH with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } File.chmod(0400, "f") @@ -1168,7 +1227,7 @@ def test_size? end def test_sticky? - skip "Unix file mode bit test" if DOSISH + omit "Unix file mode bit test" if DOSISH with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } assert_equal(false, Pathname("f").sticky?) @@ -1190,7 +1249,7 @@ def test_writable? end def test_world_writable? - skip "Unix file mode bit test" if DOSISH + omit "Unix file mode bit test" if DOSISH with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } File.chmod(0600, "f") @@ -1244,11 +1303,12 @@ def test_s_glob end def test_s_glob_3args + expect = RUBY_VERSION >= "3.1" ? [Pathname("."), Pathname("f")] : [Pathname("."), Pathname(".."), Pathname("f")] with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } Dir.chdir("/") { assert_equal( - [Pathname("."), Pathname(".."), Pathname("f")], + expect, Pathname.glob("*", File::FNM_DOTMATCH, base: dir).sort) } } @@ -1298,18 +1358,18 @@ def test_each_entry def test_mkdir with_tmpchdir('rubytest-pathname') {|dir| Pathname("d").mkdir - assert(File.directory?("d")) + assert_file.directory?("d") Pathname("e").mkdir(0770) - assert(File.directory?("e")) + assert_file.directory?("e") } end def test_rmdir with_tmpchdir('rubytest-pathname') {|dir| Pathname("d").mkdir - assert(File.directory?("d")) + assert_file.directory?("d") Pathname("d").rmdir - assert(!File.exist?("d")) + assert_file.not_exist?("d") } end @@ -1349,8 +1409,8 @@ def test_find a = []; Pathname("d").find(ignore_error: true) {|v| a << v }; a.sort! assert_equal([Pathname("d"), Pathname("d/x")], a) - skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM - skip 'skipped in root privilege' if Process.uid == 0 + omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM + omit 'skipped in root privilege' if Process.uid == 0 a = []; assert_raise_with_message(Errno::EACCES, %r{d/x}) do Pathname(".").find(ignore_error: false) {|v| a << v } @@ -1369,19 +1429,31 @@ def test_find } end + def assert_mode(val, mask, path, mesg = nil) + st = File.stat(path) + assert_equal(val.to_s(8), (st.mode & mask).to_s(8), st.inspect) + end + def test_mkpath with_tmpchdir('rubytest-pathname') {|dir| Pathname("a/b/c/d").mkpath - assert(File.directory?("a/b/c/d")) + assert_file.directory?("a/b/c/d") + unless File.stat(dir).world_readable? + # mktmpdir should make unreadable + Pathname("x/y/z").mkpath(mode: 0775) + assert_mode(0775, 0777, "x") + assert_mode(0775, 0777, "x/y") + assert_mode(0775, 0777, "x/y/z") + end } end def test_rmtree with_tmpchdir('rubytest-pathname') {|dir| Pathname("a/b/c/d").mkpath - assert(File.exist?("a/b/c/d")) + assert_file.exist?("a/b/c/d") Pathname("a").rmtree - assert(!File.exist?("a")) + assert_file.not_exist?("a") } end @@ -1389,10 +1461,10 @@ def test_unlink with_tmpchdir('rubytest-pathname') {|dir| open("f", "w") {|f| f.write "abc" } Pathname("f").unlink - assert(!File.exist?("f")) + assert_file.not_exist?("f") Dir.mkdir("d") Pathname("d").unlink - assert(!File.exist?("d")) + assert_file.not_exist?("d") } end @@ -1417,7 +1489,7 @@ def test_file_extname end def test_file_fnmatch - assert(File.fnmatch("*.*", Pathname.new("bar.baz"))) + assert_file.fnmatch("*.*", Pathname.new("bar.baz")) end def test_relative_path_from_casefold diff --git a/ruby/test/pathname/test_ractor.rb b/ruby/test/pathname/test_ractor.rb new file mode 100644 index 000000000..3d7b63dee --- /dev/null +++ b/ruby/test/pathname/test_ractor.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +require "test/unit" +require "pathname" + +class TestPathnameRactor < Test::Unit::TestCase + def setup + omit unless defined? Ractor + end + + def test_ractor_shareable + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + $VERBOSE = nil + require "pathname" + r = Ractor.new Pathname("a") do |x| + x.join(Pathname("b"), Pathname("c")) + end + assert_equal(Pathname("a/b/c"), r.take) + end; + end +end + diff --git a/ruby/test/psych/helper.rb b/ruby/test/psych/helper.rb index 934845795..0643139d8 100644 --- a/ruby/test/psych/helper.rb +++ b/ruby/test/psych/helper.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'minitest/autorun' +require 'test/unit' require 'stringio' require 'tempfile' require 'date' @@ -7,13 +7,7 @@ require 'psych' module Psych - superclass = if defined?(Minitest::Test) - Minitest::Test - else - MiniTest::Unit::TestCase - end - - class TestCase < superclass + class TestCase < Test::Unit::TestCase def self.suppress_warning verbose, $VERBOSE = $VERBOSE, nil yield @@ -47,24 +41,30 @@ def with_default_internal(enc) # Convert between Psych and the object to verify correct parsing and # emitting # - def assert_to_yaml( obj, yaml ) - assert_equal( obj, Psych::load( yaml ) ) + def assert_to_yaml( obj, yaml, loader = :load ) + assert_equal( obj, Psych.send(loader, yaml) ) assert_equal( obj, Psych::parse( yaml ).transform ) - assert_equal( obj, Psych::load( obj.to_yaml ) ) + assert_equal( obj, Psych.send(loader, obj.to_yaml) ) assert_equal( obj, Psych::parse( obj.to_yaml ).transform ) - assert_equal( obj, Psych::load( + assert_equal( obj, Psych.send(loader, obj.to_yaml( :UseVersion => true, :UseHeader => true, :SortKeys => true ) )) + rescue Psych::DisallowedClass, Psych::BadAlias + assert_to_yaml obj, yaml, :unsafe_load end # # Test parser only # def assert_parse_only( obj, yaml ) - assert_equal( obj, Psych::load( yaml ) ) - assert_equal( obj, Psych::parse( yaml ).transform ) + begin + assert_equal obj, Psych::load( yaml ) + rescue Psych::DisallowedClass, Psych::BadAlias + assert_equal obj, Psych::unsafe_load( yaml ) + end + assert_equal obj, Psych::parse( yaml ).transform end def assert_cycle( obj ) @@ -75,9 +75,15 @@ def assert_cycle( obj ) assert_nil Psych::load(Psych.dump(obj)) assert_nil Psych::load(obj.to_yaml) else - assert_equal(obj, Psych.load(v.tree.yaml)) - assert_equal(obj, Psych::load(Psych.dump(obj))) - assert_equal(obj, Psych::load(obj.to_yaml)) + begin + assert_equal(obj, Psych.load(v.tree.yaml)) + assert_equal(obj, Psych::load(Psych.dump(obj))) + assert_equal(obj, Psych::load(obj.to_yaml)) + rescue Psych::DisallowedClass, Psych::BadAlias + assert_equal(obj, Psych.unsafe_load(v.tree.yaml)) + assert_equal(obj, Psych::unsafe_load(Psych.dump(obj))) + assert_equal(obj, Psych::unsafe_load(obj.to_yaml)) + end end end diff --git a/ruby/test/psych/test_alias_and_anchor.rb b/ruby/test/psych/test_alias_and_anchor.rb index 91c09dfdf..81ebd66be 100644 --- a/ruby/test/psych/test_alias_and_anchor.rb +++ b/ruby/test/psych/test_alias_and_anchor.rb @@ -19,7 +19,7 @@ def test_mri_compatibility - *id001 - *id001 EOYAML - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each {|el| assert_same(result[0], el) } end @@ -33,7 +33,7 @@ def test_mri_compatibility_object_with_ivars - *id001 EOYAML - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each do |el| assert_same(result[0], el) assert_equal('test1', el.var1) @@ -50,7 +50,7 @@ def test_mri_compatibility_substring_with_ivars - *id001 - *id001 EOYAML - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each do |el| assert_same(result[0], el) assert_equal('test', el.var1) @@ -62,7 +62,7 @@ def test_anchor_alias_round_trip original = [o,o,o] yaml = Psych.dump original - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each {|el| assert_same(result[0], el) } end @@ -73,7 +73,7 @@ def test_anchor_alias_round_trip_object_with_ivars original = [o,o,o] yaml = Psych.dump original - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each do |el| assert_same(result[0], el) assert_equal('test1', el.var1) @@ -87,7 +87,7 @@ def test_anchor_alias_round_trip_substring_with_ivars original = [o,o,o] yaml = Psych.dump original - result = Psych.load yaml + result = Psych.unsafe_load yaml result.each do |el| assert_same(result[0], el) assert_equal('test', el.var1) diff --git a/ruby/test/psych/test_array.rb b/ruby/test/psych/test_array.rb index f2bbdcab8..28b76da78 100644 --- a/ruby/test/psych/test_array.rb +++ b/ruby/test/psych/test_array.rb @@ -24,7 +24,7 @@ def test_enumerator def test_another_subclass_with_attributes y = Y.new.tap {|o| o.val = 1} y << "foo" << "bar" - y = Psych.load Psych.dump y + y = Psych.unsafe_load Psych.dump y assert_equal %w{foo bar}, y assert_equal Y, y.class @@ -42,13 +42,13 @@ def test_subclass end def test_subclass_with_attributes - y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1} + y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1} assert_equal Y, y.class assert_equal 1, y.val end def test_backwards_with_syck - x = Psych.load "--- !seq:#{X.name} []\n\n" + x = Psych.unsafe_load "--- !seq:#{X.name} []\n\n" assert_equal X, x.class end diff --git a/ruby/test/psych/test_class.rb b/ruby/test/psych/test_class.rb index 71f7ec31f..faa504c7e 100644 --- a/ruby/test/psych/test_class.rb +++ b/ruby/test/psych/test_class.rb @@ -7,13 +7,13 @@ module Foo end def test_cycle_anonymous_class - assert_raises(::TypeError) do + assert_raise(::TypeError) do assert_cycle(Class.new) end end def test_cycle_anonymous_module - assert_raises(::TypeError) do + assert_raise(::TypeError) do assert_cycle(Module.new) end end diff --git a/ruby/test/psych/test_coder.rb b/ruby/test/psych/test_coder.rb index 5ea8cab96..b2be0a410 100644 --- a/ruby/test/psych/test_coder.rb +++ b/ruby/test/psych/test_coder.rb @@ -112,9 +112,19 @@ def init_with(c) end end + class CustomEncode + def initialize(**opts) + @opts = opts + end + + def encode_with(coder) + @opts.each { |k,v| coder.public_send :"#{k}=", v } + end + end + def test_self_referential x = Referential.new - copy = Psych.load Psych.dump x + copy = Psych.unsafe_load Psych.dump x assert_equal copy, copy.a end @@ -153,23 +163,23 @@ def test_map_with_tag_and_style end def test_represent_map - thing = Psych.load(Psych.dump(RepresentWithMap.new)) + thing = Psych.unsafe_load(Psych.dump(RepresentWithMap.new)) assert_equal({ "string" => 'a', :symbol => 'b' }, thing.map) end def test_represent_sequence - thing = Psych.load(Psych.dump(RepresentWithSeq.new)) + thing = Psych.unsafe_load(Psych.dump(RepresentWithSeq.new)) assert_equal %w{ foo bar }, thing.seq end def test_represent_with_init - thing = Psych.load(Psych.dump(RepresentWithInit.new)) + thing = Psych.unsafe_load(Psych.dump(RepresentWithInit.new)) assert_equal 'bar', thing.str end def test_represent! assert_match(/foo/, Psych.dump(Represent.new)) - assert_instance_of(Represent, Psych.load(Psych.dump(Represent.new))) + assert_instance_of(Represent, Psych.unsafe_load(Psych.dump(Represent.new))) end def test_scalar_coder @@ -179,7 +189,7 @@ def test_scalar_coder def test_load_dumped_tagging foo = InitApi.new - bar = Psych.load(Psych.dump(foo)) + bar = Psych.unsafe_load(Psych.dump(foo)) assert_equal false, bar.implicit assert_equal "!ruby/object:Psych::TestCoder::InitApi", bar.tag assert_equal Psych::Nodes::Mapping::BLOCK, bar.style @@ -198,10 +208,121 @@ def test_dump_encode_with def test_dump_init_with foo = InitApi.new - bar = Psych.load(Psych.dump(foo)) + bar = Psych.unsafe_load(Psych.dump(foo)) assert_equal foo.a, bar.a assert_equal foo.b, bar.b assert_nil bar.c end + + def test_coder_style_map_default + foo = Psych.dump a: 1, b: 2 + assert_equal "---\n:a: 1\n:b: 2\n", foo + end + + def test_coder_style_map_any + foo = Psych.dump CustomEncode.new \ + map: {a: 1, b: 2}, + style: Psych::Nodes::Mapping::ANY, + tag: nil + assert_equal "---\n:a: 1\n:b: 2\n", foo + end + + def test_coder_style_map_block + foo = Psych.dump CustomEncode.new \ + map: {a: 1, b: 2}, + style: Psych::Nodes::Mapping::BLOCK, + tag: nil + assert_equal "---\n:a: 1\n:b: 2\n", foo + end + + def test_coder_style_map_flow + foo = Psych.dump CustomEncode.new \ + map: { a: 1, b: 2 }, + style: Psych::Nodes::Mapping::FLOW, + tag: nil + assert_equal "--- {! ':a': 1, ! ':b': 2}\n", foo + end + + def test_coder_style_seq_default + foo = Psych.dump [ 1, 2, 3 ] + assert_equal "---\n- 1\n- 2\n- 3\n", foo + end + + def test_coder_style_seq_any + foo = Psych.dump CustomEncode.new \ + seq: [ 1, 2, 3 ], + style: Psych::Nodes::Sequence::ANY, + tag: nil + assert_equal "---\n- 1\n- 2\n- 3\n", foo + end + + def test_coder_style_seq_block + foo = Psych.dump CustomEncode.new \ + seq: [ 1, 2, 3 ], + style: Psych::Nodes::Sequence::BLOCK, + tag: nil + assert_equal "---\n- 1\n- 2\n- 3\n", foo + end + + def test_coder_style_seq_flow + foo = Psych.dump CustomEncode.new \ + seq: [ 1, 2, 3 ], + style: Psych::Nodes::Sequence::FLOW, + tag: nil + assert_equal "--- [1, 2, 3]\n", foo + end + + def test_coder_style_scalar_default + foo = Psych.dump 'some scalar' + assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo) + end + + def test_coder_style_scalar_any + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::ANY, + tag: nil + assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo) + end + + def test_coder_style_scalar_plain + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::PLAIN, + tag: nil + assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo) + end + + def test_coder_style_scalar_single_quoted + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::SINGLE_QUOTED, + tag: nil + assert_equal "--- ! 'some scalar'\n", foo + end + + def test_coder_style_scalar_double_quoted + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::DOUBLE_QUOTED, + tag: nil + assert_equal %Q'--- ! "some scalar"\n', foo + end + + def test_coder_style_scalar_literal + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::LITERAL, + tag: nil + assert_equal "--- ! |-\n some scalar\n", foo + end + + def test_coder_style_scalar_folded + foo = Psych.dump CustomEncode.new \ + scalar: 'some scalar', + style: Psych::Nodes::Scalar::FOLDED, + tag: nil + assert_equal "--- ! >-\n some scalar\n", foo + end end end diff --git a/ruby/test/psych/test_date_time.rb b/ruby/test/psych/test_date_time.rb index f73f34628..6f1e8b509 100644 --- a/ruby/test/psych/test_date_time.rb +++ b/ruby/test/psych/test_date_time.rb @@ -22,7 +22,7 @@ def test_non_utc def test_timezone_offset times = [Time.new(2017, 4, 13, 12, 0, 0, "+09:00"), Time.new(2017, 4, 13, 12, 0, 0, "-05:00")] - cycled = Psych::load(Psych.dump times) + cycled = Psych::unsafe_load(Psych.dump times) assert_match(/12:00:00 \+0900/, cycled.first.to_s) assert_match(/12:00:00 -0500/, cycled.last.to_s) end @@ -39,7 +39,7 @@ def test_datetime_non_utc def test_datetime_timezone_offset times = [DateTime.new(2017, 4, 13, 12, 0, 0, "+09:00"), DateTime.new(2017, 4, 13, 12, 0, 0, "-05:00")] - cycled = Psych::load(Psych.dump times) + cycled = Psych::unsafe_load(Psych.dump times) assert_match(/12:00:00\+09:00/, cycled.first.to_s) assert_match(/12:00:00-05:00/, cycled.last.to_s) end diff --git a/ruby/test/psych/test_deprecated.rb b/ruby/test/psych/test_deprecated.rb index 624f4379a..af3379909 100644 --- a/ruby/test/psych/test_deprecated.rb +++ b/ruby/test/psych/test_deprecated.rb @@ -41,7 +41,7 @@ def to_yaml opts = {} def test_recursive_quick_emit_encode_with qeew = QuickEmitterEncodeWith.new hash = { :qe => qeew } - hash2 = Psych.load Psych.dump hash + hash2 = Psych.unsafe_load Psych.dump hash qe = hash2[:qe] assert_equal qeew.name, qe.name @@ -72,7 +72,7 @@ def yaml_initialize tag, vals # receive the yaml_initialize call. def test_yaml_initialize_and_init_with hash = { :yi => YamlInitAndInitWith.new } - hash2 = Psych.load Psych.dump hash + hash2 = Psych.unsafe_load Psych.dump hash yi = hash2[:yi] assert_equal 'TGIF!', yi.name diff --git a/ruby/test/psych/test_document.rb b/ruby/test/psych/test_document.rb index a88dd32f0..cf3b7001f 100644 --- a/ruby/test/psych/test_document.rb +++ b/ruby/test/psych/test_document.rb @@ -30,7 +30,7 @@ def test_emit_multitag end def test_emit_bad_tag - assert_raises(RuntimeError) do + assert_raise(RuntimeError) do @doc.tag_directives = [['!']] @stream.yaml end diff --git a/ruby/test/psych/test_emitter.rb b/ruby/test/psych/test_emitter.rb index 52d5e9d1c..506d72241 100644 --- a/ruby/test/psych/test_emitter.rb +++ b/ruby/test/psych/test_emitter.rb @@ -40,7 +40,7 @@ def test_emit_utf_8 end def test_start_stream_arg_error - assert_raises(TypeError) do + assert_raise(TypeError) do @emitter.start_stream 'asdfasdf' end end @@ -56,7 +56,7 @@ def test_start_doc_arg_error [[], [nil,nil], false], [[1,1], [[nil, "tag:TALOS"]], 0], ].each do |args| - assert_raises(TypeError) do + assert_raise(TypeError) do @emitter.start_document(*args) end end @@ -73,7 +73,7 @@ def test_scalar_arg_error ['foo', nil, nil, false, true, :foo], [nil, nil, nil, false, true, 1], ].each do |args| - assert_raises(TypeError) do + assert_raise(TypeError) do @emitter.scalar(*args) end end @@ -83,11 +83,11 @@ def test_start_sequence_arg_error @emitter.start_stream Psych::Nodes::Stream::UTF8 @emitter.start_document [], [], false - assert_raises(TypeError) do + assert_raise(TypeError) do @emitter.start_sequence(nil, Object.new, true, 1) end - assert_raises(TypeError) do + assert_raise(TypeError) do @emitter.start_sequence(nil, nil, true, :foo) end end diff --git a/ruby/test/psych/test_encoding.rb b/ruby/test/psych/test_encoding.rb index ef6653142..e5831c904 100644 --- a/ruby/test/psych/test_encoding.rb +++ b/ruby/test/psych/test_encoding.rb @@ -63,7 +63,7 @@ def test_io_shiftjis # If the external encoding isn't utf8, utf16le, or utf16be, we cannot # process the file. File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f| - assert_raises Psych::SyntaxError do + assert_raise Psych::SyntaxError do Psych.load(f) end end @@ -121,7 +121,7 @@ def test_io_utf8_read_as_binary def test_emit_alias @emitter.start_stream Psych::Parser::UTF8 @emitter.start_document [], [], true - e = assert_raises(RuntimeError) do + e = assert_raise(RuntimeError) do @emitter.alias 'ドラãˆã‚‚ã‚“'.encode('EUC-JP') end assert_match(/alias value/, e.message) diff --git a/ruby/test/psych/test_exception.rb b/ruby/test/psych/test_exception.rb index e7fc88c70..c1e69ab18 100644 --- a/ruby/test/psych/test_exception.rb +++ b/ruby/test/psych/test_exception.rb @@ -33,42 +33,36 @@ def make_ex msg = 'oh no!' def test_backtrace err = make_ex - new_err = Psych.load(Psych.dump(err)) + new_err = Psych.unsafe_load(Psych.dump(err)) assert_equal err.backtrace, new_err.backtrace end def test_naming_exception err = String.xxx rescue $! - new_err = Psych.load(Psych.dump(err)) + new_err = Psych.unsafe_load(Psych.dump(err)) assert_equal err.message, new_err.message end def test_load_takes_file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.load '--- `' end assert_nil ex.file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.load '--- `', filename: 'meow' end assert_equal 'meow', ex.file - - # deprecated interface - ex = assert_raises(Psych::SyntaxError) do - Psych.load '--- `', 'deprecated' - end - assert_equal 'deprecated', ex.file end def test_psych_parse_stream_takes_file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.parse_stream '--- `' end assert_nil ex.file assert_match '()', ex.message - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.parse_stream '--- `', filename: 'omg!' end assert_equal 'omg!', ex.file @@ -76,22 +70,16 @@ def test_psych_parse_stream_takes_file end def test_load_stream_takes_file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.load_stream '--- `' end assert_nil ex.file assert_match '()', ex.message - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.load_stream '--- `', filename: 'omg!' end assert_equal 'omg!', ex.file - - # deprecated interface - ex = assert_raises(Psych::SyntaxError) do - Psych.load_stream '--- `', 'deprecated' - end - assert_equal 'deprecated', ex.file end def test_parse_file_exception @@ -99,7 +87,7 @@ def test_parse_file_exception t.binmode t.write '--- `' t.close - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.parse_file t.path end assert_equal t.path, ex.file @@ -111,34 +99,40 @@ def test_load_file_exception t.binmode t.write '--- `' t.close - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.load_file t.path end assert_equal t.path, ex.file } end + def test_safe_load_file_exception + Tempfile.create(['loadfile', 'yml']) {|t| + t.binmode + t.write '--- `' + t.close + ex = assert_raise(Psych::SyntaxError) do + Psych.safe_load_file t.path + end + assert_equal t.path, ex.file + } + end + def test_psych_parse_takes_file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.parse '--- `' end assert_match '()', ex.message assert_nil ex.file - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do Psych.parse '--- `', filename: 'omg!' end assert_match 'omg!', ex.message - - # deprecated interface - ex = assert_raises(Psych::SyntaxError) do - Psych.parse '--- `', 'deprecated' - end - assert_match 'deprecated', ex.message end def test_attributes - e = assert_raises(Psych::SyntaxError) { + e = assert_raise(Psych::SyntaxError) { Psych.load '--- `foo' } @@ -153,8 +147,9 @@ def test_attributes end def test_convert - w = Psych.load(Psych.dump(@wups)) - assert_equal @wups, w + w = Psych.unsafe_load(Psych.dump(@wups)) + assert_equal @wups.message, w.message + assert_equal @wups.backtrace, w.backtrace assert_equal 1, w.foo assert_equal 2, w.bar end diff --git a/ruby/test/psych/test_hash.rb b/ruby/test/psych/test_hash.rb index ba11b827d..537478133 100644 --- a/ruby/test/psych/test_hash.rb +++ b/ruby/test/psych/test_hash.rb @@ -39,7 +39,7 @@ def setup def test_hash_with_ivar t1 = HashWithIvar.new t1[:foo] = :bar - t2 = Psych.load(Psych.dump(t1)) + t2 = Psych.unsafe_load(Psych.dump(t1)) assert_equal t1, t2 assert_cycle t1 end @@ -54,14 +54,14 @@ def test_referenced_hash_with_ivar def test_custom_initialized a = [1,2,3,4,5] t1 = HashWithCustomInit.new(a) - t2 = Psych.load(Psych.dump(t1)) + t2 = Psych.unsafe_load(Psych.dump(t1)) assert_equal t1, t2 assert_cycle t1 end def test_custom_initialize_no_ivar t1 = HashWithCustomInitNoIvar.new(nil) - t2 = Psych.load(Psych.dump(t1)) + t2 = Psych.unsafe_load(Psych.dump(t1)) assert_equal t1, t2 assert_cycle t1 end @@ -70,25 +70,25 @@ def test_hash_subclass_with_ivars x = X.new x[:a] = 'b' x.instance_variable_set :@foo, 'bar' - dup = Psych.load Psych.dump x + dup = Psych.unsafe_load Psych.dump x assert_cycle x assert_equal 'bar', dup.instance_variable_get(:@foo) assert_equal X, dup.class end def test_load_with_class_syck_compatibility - hash = Psych.load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n" + hash = Psych.unsafe_load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n" assert_equal({ user_id: 7, username: 'Lucas'}, hash) end def test_empty_subclass assert_match "!ruby/hash:#{X}", Psych.dump(X.new) - x = Psych.load Psych.dump X.new + x = Psych.unsafe_load Psych.dump X.new assert_equal X, x.class end def test_map - x = Psych.load "--- !map:#{X} { }\n" + x = Psych.unsafe_load "--- !map:#{X} { }\n" assert_equal X, x.class end @@ -102,7 +102,7 @@ def test_cycles end def test_ref_append - hash = Psych.load(<<-eoyml) + hash = Psych.unsafe_load(<<-eoyml) --- foo: &foo hello: world @@ -114,7 +114,7 @@ def test_ref_append def test_key_deduplication unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20))) - skip "This Ruby implementation doesn't support string deduplication" + pend "This Ruby implementation doesn't support string deduplication" end hashes = Psych.load(<<-eoyml) diff --git a/ruby/test/psych/test_marshalable.rb b/ruby/test/psych/test_marshalable.rb index b1f4a837f..74ee90288 100644 --- a/ruby/test/psych/test_marshalable.rb +++ b/ruby/test/psych/test_marshalable.rb @@ -6,7 +6,7 @@ module Psych class TestMarshalable < TestCase def test_objects_defining_marshal_dump_and_marshal_load_can_be_dumped sd = SimpleDelegator.new(1) - loaded = Psych.load(Psych.dump(sd)) + loaded = Psych.unsafe_load(Psych.dump(sd)) assert_instance_of(SimpleDelegator, loaded) assert_equal(sd, loaded) @@ -46,7 +46,15 @@ def class def test_init_with_takes_priority_over_marshal_methods obj = PsychCustomMarshalable.new(1) - loaded = Psych.load(Psych.dump(obj)) + loaded = Psych.unsafe_load(Psych.dump(obj)) + + assert(PsychCustomMarshalable === loaded) + assert_equal(2, loaded.foo) + end + + def test_init_symbolize_names + obj = PsychCustomMarshalable.new(1) + loaded = Psych.unsafe_load(Psych.dump(obj), symbolize_names: true) assert(PsychCustomMarshalable === loaded) assert_equal(2, loaded.foo) diff --git a/ruby/test/psych/test_merge_keys.rb b/ruby/test/psych/test_merge_keys.rb index 1bc3dd1cb..dcf4f1fce 100644 --- a/ruby/test/psych/test_merge_keys.rb +++ b/ruby/test/psych/test_merge_keys.rb @@ -17,6 +17,16 @@ def test_merge_key_with_bare_hash assert_equal hash, doc end + def test_merge_key_with_bare_hash_symbolized_names + doc = Psych.load <<-eodoc, symbolize_names: true +map: + <<: + hello: world + eodoc + hash = { map: { hello: "world" } } + assert_equal hash, doc + end + def test_roundtrip_with_chevron_key h = {} v = { 'a' => h, '<<' => h } @@ -24,7 +34,7 @@ def test_roundtrip_with_chevron_key end def test_explicit_string - doc = Psych.load <<-eoyml + doc = Psych.unsafe_load <<-eoyml a: &me { hello: world } b: { !!str '<<': *me } eoyml @@ -45,7 +55,7 @@ def test_mergekey_with_object !ruby/object:#{Product.name} <<: *foo eoyml - hash = Psych.load s + hash = Psych.unsafe_load s assert_equal({"bar" => 10}, hash["foo"]) product = hash["product"] assert_equal 10, product.bar @@ -57,7 +67,7 @@ def test_merge_nil development: <<: *defaults eoyml - assert_equal({'<<' => nil }, Psych.load(yaml)['development']) + assert_equal({'<<' => nil }, Psych.unsafe_load(yaml)['development']) end def test_merge_array @@ -67,7 +77,7 @@ def test_merge_array baz: <<: *hello eoyml - assert_equal({'<<' => [1]}, Psych.load(yaml)['baz']) + assert_equal({'<<' => [1]}, Psych.unsafe_load(yaml)['baz']) end def test_merge_is_not_partial @@ -79,9 +89,9 @@ def test_merge_is_not_partial baz: <<: [*hello, *default] eoyml - doc = Psych.load yaml + doc = Psych.unsafe_load yaml refute doc['baz'].key? 'hello' - assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.load(yaml)['baz']) + assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.unsafe_load(yaml)['baz']) end def test_merge_seq_nil @@ -90,7 +100,7 @@ def test_merge_seq_nil baz: <<: [*hello] eoyml - assert_equal({'<<' => [nil]}, Psych.load(yaml)['baz']) + assert_equal({'<<' => [nil]}, Psych.unsafe_load(yaml)['baz']) end def test_bad_seq_merge @@ -99,7 +109,7 @@ def test_bad_seq_merge development: <<: *defaults eoyml - assert_equal({'<<' => [1,2,3]}, Psych.load(yaml)['development']) + assert_equal({'<<' => [1,2,3]}, Psych.unsafe_load(yaml)['development']) end def test_missing_merge_key @@ -107,7 +117,7 @@ def test_missing_merge_key bar: << : *foo eoyml - exp = assert_raises(Psych::BadAlias) { Psych.load yaml } + exp = assert_raise(Psych::BadAlias) { Psych.load yaml } assert_match 'foo', exp.message end @@ -124,7 +134,7 @@ def test_merge_key hash = { "foo" => { "hello" => "world"}, "bar" => { "hello" => "world", "baz" => "boo" } } - assert_equal hash, Psych.load(yaml) + assert_equal hash, Psych.unsafe_load(yaml) end def test_multiple_maps @@ -149,7 +159,7 @@ def test_multiple_maps 'label' => 'center/big' } - assert_equal hash, Psych.load(yaml)[4] + assert_equal hash, Psych.unsafe_load(yaml)[4] end def test_override @@ -175,7 +185,7 @@ def test_override 'label' => 'center/big' } - assert_equal hash, Psych.load(yaml)[4] + assert_equal hash, Psych.unsafe_load(yaml)[4] end end end diff --git a/ruby/test/psych/test_nil.rb b/ruby/test/psych/test_nil.rb index 910a2e697..bcbbcb9c9 100644 --- a/ruby/test/psych/test_nil.rb +++ b/ruby/test/psych/test_nil.rb @@ -5,13 +5,13 @@ module Psych class TestNil < TestCase def test_nil yml = Psych.dump nil - assert_match(/--- \n(?:\.\.\.\n)?/, yml) + assert_match(/---[ ]?\n(?:\.\.\.\n)?/, yml) assert_nil Psych.load(yml) end def test_array_nil yml = Psych.dump [nil] - assert_equal "---\n- \n", yml + assert_match(/---\n-[ ]?\n/, yml) assert_equal [nil], Psych.load(yml) end diff --git a/ruby/test/psych/test_numeric.rb b/ruby/test/psych/test_numeric.rb index db99a2a0d..8c3dcd173 100644 --- a/ruby/test/psych/test_numeric.rb +++ b/ruby/test/psych/test_numeric.rb @@ -33,6 +33,7 @@ def test_big_decimal_tag def test_big_decimal_round_trip decimal = BigDecimal("12.34") + $DEBUG = false assert_cycle decimal end diff --git a/ruby/test/psych/test_object.rb b/ruby/test/psych/test_object.rb index f1c61451d..0faf6b244 100644 --- a/ruby/test/psych/test_object.rb +++ b/ruby/test/psych/test_object.rb @@ -28,7 +28,7 @@ def test_dump_with_tag def test_tag_round_trip tag = Tagged.new - tag2 = Psych.load(Psych.dump(tag)) + tag2 = Psych.unsafe_load(Psych.dump(tag)) assert_equal tag.baz, tag2.baz assert_instance_of(Tagged, tag2) end @@ -36,7 +36,7 @@ def test_tag_round_trip def test_cyclic_references foo = Foo.new(nil) foo.parent = foo - loaded = Psych.load Psych.dump foo + loaded = Psych.unsafe_load Psych.dump foo assert_instance_of(Foo, loaded) assert_equal loaded, loaded.parent diff --git a/ruby/test/psych/test_object_references.rb b/ruby/test/psych/test_object_references.rb index ca69c7d28..269d72242 100644 --- a/ruby/test/psych/test_object_references.rb +++ b/ruby/test/psych/test_object_references.rb @@ -34,12 +34,16 @@ def test_struct_has_references def assert_reference_trip obj yml = Psych.dump([obj, obj]) assert_match(/\*-?\d+/, yml) - data = Psych.load yml + begin + data = Psych.load yml + rescue Psych::DisallowedClass + data = Psych.unsafe_load yml + end assert_equal data.first.object_id, data.last.object_id end def test_float_references - data = Psych.load <<-eoyml + data = Psych.unsafe_load <<-eoyml ---\s - &name 1.2 - *name @@ -49,7 +53,7 @@ def test_float_references end def test_binary_references - data = Psych.load <<-eoyml + data = Psych.unsafe_load <<-eoyml --- - &name !binary |- aGVsbG8gd29ybGQh @@ -60,7 +64,7 @@ def test_binary_references end def test_regexp_references - data = Psych.load <<-eoyml + data = Psych.unsafe_load <<-eoyml ---\s - &name !ruby/regexp /pattern/i - *name diff --git a/ruby/test/psych/test_omap.rb b/ruby/test/psych/test_omap.rb index 98636ded9..6de028640 100644 --- a/ruby/test/psych/test_omap.rb +++ b/ruby/test/psych/test_omap.rb @@ -4,7 +4,7 @@ module Psych class TestOmap < TestCase def test_parse_as_map - o = Psych.load "--- !!omap\na: 1\nb: 2" + o = Psych.unsafe_load "--- !!omap\na: 1\nb: 2" assert_kind_of Psych::Omap, o assert_equal 1, o['a'] assert_equal 2, o['b'] @@ -14,7 +14,7 @@ def test_self_referential map = Psych::Omap.new map['foo'] = 'bar' map['self'] = map - assert_equal(map, Psych.load(Psych.dump(map))) + assert_equal(map, Psych.unsafe_load(Psych.dump(map))) end def test_keys diff --git a/ruby/test/psych/test_parser.rb b/ruby/test/psych/test_parser.rb index e8225dabb..3604e7c98 100644 --- a/ruby/test/psych/test_parser.rb +++ b/ruby/test/psych/test_parser.rb @@ -63,7 +63,7 @@ def test_exception_memory_leak parser = Psych::Parser.new klass.new 2.times { - assert_raises(RuntimeError, method.to_s) do + assert_raise(RuntimeError, method.to_s) do parser.parse yaml end } @@ -77,7 +77,7 @@ def test_multiparse end def test_filename - ex = assert_raises(Psych::SyntaxError) do + ex = assert_raise(Psych::SyntaxError) do @parser.parse '--- `', 'omg!' end assert_match 'omg!', ex.message @@ -180,7 +180,7 @@ def test_bogus_io def o.external_encoding; nil end def o.read len; self end - assert_raises(TypeError) do + assert_raise(TypeError) do @parser.parse o end end @@ -193,23 +193,23 @@ def test_parse_io end def test_syntax_error - assert_raises(Psych::SyntaxError) do + assert_raise(Psych::SyntaxError) do @parser.parse("---\n\"foo\"\n\"bar\"\n") end end def test_syntax_error_twice - assert_raises(Psych::SyntaxError) do + assert_raise(Psych::SyntaxError) do @parser.parse("---\n\"foo\"\n\"bar\"\n") end - assert_raises(Psych::SyntaxError) do + assert_raise(Psych::SyntaxError) do @parser.parse("---\n\"foo\"\n\"bar\"\n") end end def test_syntax_error_has_path_for_string - e = assert_raises(Psych::SyntaxError) do + e = assert_raise(Psych::SyntaxError) do @parser.parse("---\n\"foo\"\n\"bar\"\n") end assert_match '():', e.message @@ -219,7 +219,7 @@ def test_syntax_error_has_path_for_io io = StringIO.new "---\n\"foo\"\n\"bar\"\n" def io.path; "hello!"; end - e = assert_raises(Psych::SyntaxError) do + e = assert_raise(Psych::SyntaxError) do @parser.parse(io) end assert_match "(#{io.path}):", e.message diff --git a/ruby/test/psych/test_psych.rb b/ruby/test/psych/test_psych.rb index eeadc864e..1abd69cec 100644 --- a/ruby/test/psych/test_psych.rb +++ b/ruby/test/psych/test_psych.rb @@ -16,7 +16,7 @@ def teardown end def test_line_width_invalid - assert_raises(ArgumentError) { Psych.dump('x', { :line_width => -2 }) } + assert_raise(ArgumentError) { Psych.dump('x', { :line_width => -2 }) } end def test_line_width_no_limit @@ -61,7 +61,7 @@ def test_version_bool end def test_load_argument_error - assert_raises(TypeError) do + assert_raise(TypeError) do Psych.load nil end end @@ -75,16 +75,12 @@ def test_parse_default_fallback end def test_parse_raises_on_bad_input - assert_raises(Psych::SyntaxError) { Psych.parse("--- `") } - end - - def test_parse_with_fallback - assert_equal 42, Psych.parse("", fallback: 42) + assert_raise(Psych::SyntaxError) { Psych.parse("--- `") } end def test_non_existing_class_on_deserialize - e = assert_raises(ArgumentError) do - Psych.load("--- !ruby/object:NonExistent\nfoo: 1") + e = assert_raise(ArgumentError) do + Psych.unsafe_load("--- !ruby/object:NonExistent\nfoo: 1") end assert_equal 'undefined class/module NonExistent', e.message end @@ -125,12 +121,25 @@ def test_load_stream assert_equal %w{ foo bar }, docs end + def test_load_stream_freeze + docs = Psych.load_stream("--- foo\n...\n--- bar\n...", freeze: true) + assert_equal %w{ foo bar }, docs + docs.each do |string| + assert_predicate string, :frozen? + end + end + + def test_load_stream_symbolize_names + docs = Psych.load_stream("---\nfoo: bar", symbolize_names: true) + assert_equal [{foo: 'bar'}], docs + end + def test_load_stream_default_fallback assert_equal [], Psych.load_stream("") end def test_load_stream_raises_on_bad_input - assert_raises(Psych::SyntaxError) { Psych.load_stream("--- `") } + assert_raise(Psych::SyntaxError) { Psych.load_stream("--- `") } end def test_parse_stream @@ -162,7 +171,7 @@ def test_parse_stream_with_block_default_fallback end def test_parse_stream_raises_on_bad_input - assert_raises(Psych::SyntaxError) { Psych.parse_stream("--- `") } + assert_raise(Psych::SyntaxError) { Psych.parse_stream("--- `") } end def test_add_builtin_type @@ -178,43 +187,59 @@ def test_add_builtin_type def test_domain_types got = nil - Psych.add_domain_type 'foo.bar,2002', 'foo' do |type, val| + Psych.add_domain_type 'foo.bar/2002', 'foo' do |type, val| got = val end - Psych.load('--- !foo.bar,2002/foo hello') + Psych.load('--- !foo.bar/2002:foo hello') assert_equal 'hello', got - Psych.load("--- !foo.bar,2002/foo\n- hello\n- world") + Psych.load("--- !foo.bar/2002:foo\n- hello\n- world") assert_equal %w{ hello world }, got - Psych.load("--- !foo.bar,2002/foo\nhello: world") + Psych.load("--- !foo.bar/2002:foo\nhello: world") assert_equal({ 'hello' => 'world' }, got) end + def test_load_freeze + data = Psych.load("--- {foo: ['a']}", freeze: true) + assert_predicate data, :frozen? + assert_predicate data['foo'], :frozen? + assert_predicate data['foo'].first, :frozen? + end + + def test_load_freeze_deduplication + unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20))) + pend "This Ruby implementation doesn't support string deduplication" + end + + data = Psych.load("--- ['a']", freeze: true) + assert_same 'a', data.first + end + def test_load_default_fallback - assert_equal false, Psych.load("") + assert_equal false, Psych.unsafe_load("") end def test_load_with_fallback - assert_equal 42, Psych.load("", "file", fallback: 42) + assert_equal 42, Psych.load("", filename: "file", fallback: 42) end def test_load_with_fallback_nil_or_false - assert_nil Psych.load("", "file", fallback: nil) - assert_equal false, Psych.load("", "file", fallback: false) + assert_nil Psych.load("", filename: "file", fallback: nil) + assert_equal false, Psych.load("", filename: "file", fallback: false) end def test_load_with_fallback_hash - assert_equal Hash.new, Psych.load("", "file", fallback: Hash.new) + assert_equal Hash.new, Psych.load("", filename: "file", fallback: Hash.new) end def test_load_with_fallback_for_nil - assert_nil Psych.load("--- null", "file", fallback: 42) + assert_nil Psych.unsafe_load("--- null", filename: "file", fallback: 42) end def test_load_with_fallback_for_false - assert_equal false, Psych.load("--- false", "file", fallback: 42) + assert_equal false, Psych.unsafe_load("--- false", filename: "file", fallback: 42) end def test_load_file @@ -226,9 +251,30 @@ def test_load_file } end + def test_load_file_freeze + Tempfile.create(['yikes', 'yml']) {|t| + t.binmode + t.write('--- hello world') + t.close + + object = Psych.load_file(t.path, freeze: true) + assert_predicate object, :frozen? + } + end + + def test_load_file_symbolize_names + Tempfile.create(['yikes', 'yml']) {|t| + t.binmode + t.write("---\nfoo: bar") + t.close + + assert_equal({foo: 'bar'}, Psych.load_file(t.path, symbolize_names: true)) + } + end + def test_load_file_default_fallback Tempfile.create(['empty', 'yml']) {|t| - assert_equal false, Psych.load_file(t.path) + assert_equal false, Psych.unsafe_load_file(t.path) } end @@ -269,6 +315,18 @@ def test_load_file_with_fallback_for_false } end + def test_safe_load_file_with_permitted_classe + Tempfile.create(['false', 'yml']) {|t| + t.binmode + t.write("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") + t.close + assert_equal 0..42, Psych.safe_load_file(t.path, permitted_classes: [Range]) + assert_raise(Psych::DisallowedClass) { + Psych.safe_load_file(t.path) + } + } + end + def test_parse_file Tempfile.create(['yikes', 'yml']) {|t| t.binmode @@ -285,9 +343,9 @@ def test_parse_file_default_fallback end def test_degenerate_strings - assert_equal false, Psych.load(' ') + assert_equal false, Psych.unsafe_load(' ') assert_equal false, Psych.parse(' ') - assert_equal false, Psych.load('') + assert_equal false, Psych.unsafe_load('') assert_equal false, Psych.parse('') end @@ -295,16 +353,13 @@ def test_callbacks types = [] appender = lambda { |*args| types << args } - Psych.add_builtin_type('foo', &appender) - Psych.add_domain_type('example.com,2002', 'foo', &appender) + Psych.add_domain_type('example.com:2002', 'foo', &appender) Psych.load <<-eoyml -- !tag:yaml.org,2002:foo bar -- !tag:example.com,2002:foo bar +- !tag:example.com:2002:foo bar eoyml assert_equal [ - ["tag:yaml.org,2002:foo", "bar"], - ["tag:example.com,2002:foo", "bar"] + ["tag:example.com:2002:foo", "bar"] ], types end @@ -312,17 +367,75 @@ def test_symbolize_names yaml = <<-eoyml foo: bar: baz + 1: 2 hoge: - fuga: piyo eoyml result = Psych.load(yaml) - assert_equal result, { "foo" => { "bar" => "baz"}, "hoge" => [{ "fuga" => "piyo" }] } + assert_equal result, { "foo" => { "bar" => "baz", 1 => 2 }, "hoge" => [{ "fuga" => "piyo" }] } result = Psych.load(yaml, symbolize_names: true) - assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] } + assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] } result = Psych.safe_load(yaml, symbolize_names: true) - assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] } + assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] } + end + + def test_safe_dump_defaults + yaml = <<-eoyml +--- +array: +- 1 +float: 13.12 +booleans: +- true +- false +eoyml + + payload = Psych.safe_dump({ + "array" => [1], + "float" => 13.12, + "booleans" => [true, false], + }) + assert_equal yaml, payload + end + + def test_safe_dump_unpermitted_class + error = assert_raise Psych::DisallowedClass do + Psych.safe_dump(Object.new) + end + assert_equal "Tried to dump unspecified class: Object", error.message + + hash_subclass = Class.new(Hash) + error = assert_raise Psych::DisallowedClass do + Psych.safe_dump(hash_subclass.new) + end + assert_equal "Tried to dump unspecified class: #{hash_subclass.inspect}", error.message + end + + def test_safe_dump_extra_permitted_classes + assert_equal "--- !ruby/object {}\n", Psych.safe_dump(Object.new, permitted_classes: [Object]) end + + def test_safe_dump_symbols + error = assert_raise Psych::DisallowedClass do + Psych.safe_dump(:foo, permitted_classes: [Symbol]) + end + assert_equal "Tried to dump unspecified class: Symbol(:foo)", error.message + + assert_match(/\A--- :foo\n(?:\.\.\.\n)?\z/, Psych.safe_dump(:foo, permitted_classes: [Symbol], permitted_symbols: [:foo])) + end + + def test_safe_dump_aliases + x = [] + x << x + error = assert_raise Psych::BadAlias do + Psych.safe_dump(x) + end + assert_equal "Tried to dump an aliased object", error.message + + assert_equal "--- &1\n" + "- *1\n", Psych.safe_dump(x, aliases: true) + end + end diff --git a/ruby/test/psych/test_ractor.rb b/ruby/test/psych/test_ractor.rb new file mode 100644 index 000000000..1b0d81060 --- /dev/null +++ b/ruby/test/psych/test_ractor.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true +require_relative 'helper' + +class TestPsychRactor < Test::Unit::TestCase + def test_ractor_round_trip + assert_ractor(<<~RUBY, require_relative: 'helper') + obj = {foo: [42]} + obj2 = Ractor.new(obj) do |obj| + Psych.unsafe_load(Psych.dump(obj)) + end.take + assert_equal obj, obj2 + RUBY + end + + def test_not_shareable + # There's no point in making these frozen / shareable + # and the C-ext disregards begin frozen + assert_ractor(<<~RUBY, require_relative: 'helper') + parser = Psych::Parser.new + emitter = Psych::Emitter.new(nil) + assert_raise(Ractor::Error) { Ractor.make_shareable(parser) } + assert_raise(Ractor::Error) { Ractor.make_shareable(emitter) } + RUBY + end + + def test_ractor_config + # Config is ractor-local + # Test is to make sure it works, even though usage is probably very low. + # The methods are not documented and might be deprecated one day + assert_ractor(<<~RUBY, require_relative: 'helper') + r = Ractor.new do + Psych.add_builtin_type 'omap' do |type, val| + val * 2 + end + Psych.load('--- !!omap hello') + end.take + assert_equal 'hellohello', r + assert_equal 'hello', Psych.load('--- !!omap hello') + RUBY + end + + def test_ractor_constants + assert_ractor(<<~RUBY, require_relative: 'helper') + r = Ractor.new do + Psych.libyaml_version.join('.') == Psych::LIBYAML_VERSION + end.take + assert_equal true, r + RUBY + end +end if defined?(Ractor) diff --git a/ruby/test/psych/test_safe_load.rb b/ruby/test/psych/test_safe_load.rb index e3972712f..b52d6048b 100644 --- a/ruby/test/psych/test_safe_load.rb +++ b/ruby/test/psych/test_safe_load.rb @@ -22,7 +22,7 @@ class Foo; end def test_no_recursion x = [] x << x - assert_raises(Psych::BadAlias) do + assert_raise(Psych::BadAlias) do Psych.safe_load Psych.dump(x) end end @@ -31,13 +31,11 @@ def test_explicit_recursion x = [] x << x assert_equal(x, Psych.safe_load(Psych.dump(x), permitted_classes: [], permitted_symbols: [], aliases: true)) - # deprecated interface - assert_equal(x, Psych.safe_load(Psych.dump(x), [], [], true)) end def test_permitted_symbol yml = Psych.dump :foo - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do Psych.safe_load yml end assert_equal( @@ -48,55 +46,36 @@ def test_permitted_symbol permitted_symbols: [:foo] ) ) - - # deprecated interface - assert_equal(:foo, Psych.safe_load(yml, [Symbol], [:foo])) end def test_symbol - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do assert_safe_cycle :foo end - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do Psych.safe_load '--- !ruby/symbol foo', permitted_classes: [] end - # deprecated interface - assert_raises(Psych::DisallowedClass) do - Psych.safe_load '--- !ruby/symbol foo', [] - end - assert_safe_cycle :foo, permitted_classes: [Symbol] assert_safe_cycle :foo, permitted_classes: %w{ Symbol } assert_equal :foo, Psych.safe_load('--- !ruby/symbol foo', permitted_classes: [Symbol]) - - # deprecated interface - assert_equal :foo, Psych.safe_load('--- !ruby/symbol foo', [Symbol]) end def test_foo - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do Psych.safe_load '--- !ruby/object:Foo {}', permitted_classes: [Foo] end - # deprecated interface - assert_raises(Psych::DisallowedClass) do - Psych.safe_load '--- !ruby/object:Foo {}', [Foo] - end - - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do assert_safe_cycle Foo.new end assert_kind_of(Foo, Psych.safe_load(Psych.dump(Foo.new), permitted_classes: [Foo])) - - # deprecated interface - assert_kind_of(Foo, Psych.safe_load(Psych.dump(Foo.new), [Foo])) end X = Struct.new(:x) def test_struct_depends_on_sym assert_safe_cycle(X.new, permitted_classes: [X, Symbol]) - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do cycle X.new, permitted_classes: [X] end end @@ -107,14 +86,14 @@ def test_anon_struct foo: bar eoyml - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do Psych.safe_load(<<-eoyml, permitted_classes: [Struct]) --- !ruby/struct foo: bar eoyml end - assert_raises(Psych::DisallowedClass) do + assert_raise(Psych::DisallowedClass) do Psych.safe_load(<<-eoyml, permitted_classes: [Symbol]) --- !ruby/struct foo: bar @@ -122,27 +101,6 @@ def test_anon_struct end end - def test_deprecated_anon_struct - assert Psych.safe_load(<<-eoyml, [Struct, Symbol]) ---- !ruby/struct - foo: bar - eoyml - - assert_raises(Psych::DisallowedClass) do - Psych.safe_load(<<-eoyml, [Struct]) ---- !ruby/struct - foo: bar - eoyml - end - - assert_raises(Psych::DisallowedClass) do - Psych.safe_load(<<-eoyml, [Symbol]) ---- !ruby/struct - foo: bar - eoyml - end - end - def test_safe_load_default_fallback assert_nil Psych.safe_load("") end @@ -152,15 +110,13 @@ def test_safe_load end def test_safe_load_raises_on_bad_input - assert_raises(Psych::SyntaxError) { Psych.safe_load("--- `") } + assert_raise(Psych::SyntaxError) { Psych.safe_load("--- `") } end private def cycle object, permitted_classes: [] Psych.safe_load(Psych.dump(object), permitted_classes: permitted_classes) - # deprecated interface test - Psych.safe_load(Psych.dump(object), permitted_classes) end def assert_safe_cycle object, permitted_classes: [] diff --git a/ruby/test/psych/test_scalar_scanner.rb b/ruby/test/psych/test_scalar_scanner.rb index d12a90533..ebc9fbdcd 100644 --- a/ruby/test/psych/test_scalar_scanner.rb +++ b/ruby/test/psych/test_scalar_scanner.rb @@ -66,6 +66,10 @@ def test_scan_inf assert_equal(1 / 0.0, ss.tokenize('.inf')) end + def test_scan_plus_inf + assert_equal(1 / 0.0, ss.tokenize('+.inf')) + end + def test_scan_minus_inf assert_equal(-1 / 0.0, ss.tokenize('-.inf')) end @@ -111,7 +115,15 @@ def test_scan_true end def test_scan_strings_starting_with_underscores - assert_equal "_100", ss.tokenize('_100') + assert_equal '_100', ss.tokenize('_100') + end + + def test_scan_strings_starting_with_number + assert_equal '450D', ss.tokenize('450D') + end + + def test_scan_strings_ending_with_underscores + assert_equal '100_', ss.tokenize('100_') end def test_scan_int_commas_and_underscores @@ -121,6 +133,10 @@ def test_scan_int_commas_and_underscores assert_equal 123_456_789, ss.tokenize('123,456,789') assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789') + assert_equal 1, ss.tokenize('1') + assert_equal 1, ss.tokenize('+1') + assert_equal(-1, ss.tokenize('-1')) + assert_equal 0b010101010, ss.tokenize('0b010101010') assert_equal 0b010101010, ss.tokenize('0b0,1_0,1_,0,1_01,0') @@ -129,6 +145,38 @@ def test_scan_int_commas_and_underscores assert_equal 0x123456789abcdef, ss.tokenize('0x123456789abcdef') assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef') + assert_equal 0x123456789abcdef, ss.tokenize('0x_12_,34,_56,_789abcdef') + assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef__') + end + + def test_scan_dot + assert_equal '.', ss.tokenize('.') + end + + def test_scan_plus_dot + assert_equal '+.', ss.tokenize('+.') + end + + class MatchCallCounter < String + attr_reader :match_call_count + + def match?(pat) + @match_call_count ||= 0 + @match_call_count += 1 + super + end + end + + def test_scan_ascii_matches_quickly + ascii = MatchCallCounter.new('abcdefghijklmnopqrstuvwxyz') + ss.tokenize(ascii) + assert_equal 1, ascii.match_call_count + end + + def test_scan_unicode_matches_quickly + unicode = MatchCallCounter.new('é³¥ã‹ã”関連用å“') + ss.tokenize(unicode) + assert_equal 1, unicode.match_call_count end end end diff --git a/ruby/test/psych/test_serialize_subclasses.rb b/ruby/test/psych/test_serialize_subclasses.rb index 8e1d0d354..344c79b3e 100644 --- a/ruby/test/psych/test_serialize_subclasses.rb +++ b/ruby/test/psych/test_serialize_subclasses.rb @@ -17,7 +17,7 @@ def == other def test_some_object so = SomeObject.new('foo', [1,2,3]) - assert_equal so, Psych.load(Psych.dump(so)) + assert_equal so, Psych.unsafe_load(Psych.dump(so)) end class StructSubclass < Struct.new(:foo) @@ -33,7 +33,7 @@ def == other def test_struct_subclass so = StructSubclass.new('foo', [1,2,3]) - assert_equal so, Psych.load(Psych.dump(so)) + assert_equal so, Psych.unsafe_load(Psych.dump(so)) end end end diff --git a/ruby/test/psych/test_set.rb b/ruby/test/psych/test_set.rb index 5690957ef..87944d839 100644 --- a/ruby/test/psych/test_set.rb +++ b/ruby/test/psych/test_set.rb @@ -21,7 +21,7 @@ def test_roundtrip ### # FIXME: Syck should also support !!set as shorthand def test_load_from_yaml - loaded = Psych.load(<<-eoyml) + loaded = Psych.unsafe_load(<<-eoyml) --- !set foo: bar bar: baz @@ -30,11 +30,11 @@ def test_load_from_yaml end def test_loaded_class - assert_instance_of(Psych::Set, Psych.load(Psych.dump(@set))) + assert_instance_of(Psych::Set, Psych.unsafe_load(Psych.dump(@set))) end def test_set_shorthand - loaded = Psych.load(<<-eoyml) + loaded = Psych.unsafe_load(<<-eoyml) --- !!set foo: bar bar: baz diff --git a/ruby/test/psych/test_string.rb b/ruby/test/psych/test_string.rb index 973f38b9c..0dc34b308 100644 --- a/ruby/test/psych/test_string.rb +++ b/ruby/test/psych/test_string.rb @@ -17,6 +17,19 @@ def initialize end end + # 'y' and 'n' are kind of ambiguous. Syck treated y and n literals in + # YAML documents as strings. But this is not what the YAML 1.1 spec says. + # YAML 1.1 says they should be treated as booleans. When we're dumping + # documents, we know it's a string, so adding quotes will eliminate the + # "ambiguity" in the emitted document + def test_y_is_quoted + assert_match(/"y"/, Psych.dump("y")) + end + + def test_n_is_quoted + assert_match(/"n"/, Psych.dump("n")) + end + def test_string_with_newline assert_equal "1\n2", Psych.load("--- ! '1\n\n 2'\n") end @@ -104,7 +117,7 @@ def test_float_with_no_fractional_before_exponent end def test_string_subclass_with_anchor - y = Psych.load <<-eoyml + y = Psych.unsafe_load <<-eoyml --- body: string: &70121654388580 !ruby/string @@ -116,7 +129,7 @@ def test_string_subclass_with_anchor end def test_self_referential_string - y = Psych.load <<-eoyml + y = Psych.unsafe_load <<-eoyml --- string: &70121654388580 !ruby/string str: ! 'foo' @@ -129,32 +142,32 @@ def test_self_referential_string end def test_another_subclass_with_attributes - y = Psych.load Psych.dump Y.new("foo").tap {|o| o.val = 1} + y = Psych.unsafe_load Psych.dump Y.new("foo").tap {|o| o.val = 1} assert_equal "foo", y assert_equal Y, y.class assert_equal 1, y.val end def test_backwards_with_syck - x = Psych.load "--- !str:#{X.name} foo\n\n" + x = Psych.unsafe_load "--- !str:#{X.name} foo\n\n" assert_equal X, x.class assert_equal 'foo', x end def test_empty_subclass assert_match "!ruby/string:#{X}", Psych.dump(X.new) - x = Psych.load Psych.dump X.new + x = Psych.unsafe_load Psych.dump X.new assert_equal X, x.class end def test_empty_character_subclass assert_match "!ruby/string:#{Z}", Psych.dump(Z.new) - x = Psych.load Psych.dump Z.new + x = Psych.unsafe_load Psych.dump Z.new assert_equal Z, x.class end def test_subclass_with_attributes - y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1} + y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1} assert_equal Y, y.class assert_equal 1, y.val end diff --git a/ruby/test/psych/test_struct.rb b/ruby/test/psych/test_struct.rb index 721df4421..1479798b1 100644 --- a/ruby/test/psych/test_struct.rb +++ b/ruby/test/psych/test_struct.rb @@ -22,7 +22,7 @@ def test_self_referential_struct ss = StructSubclass.new(nil, 'foo') ss.foo = ss - loaded = Psych.load(Psych.dump(ss)) + loaded = Psych.unsafe_load(Psych.dump(ss)) assert_instance_of(StructSubclass, loaded.foo) assert_equal(ss, loaded) @@ -30,14 +30,14 @@ def test_self_referential_struct def test_roundtrip thing = PsychStructWithIvar.new('bar') - struct = Psych.load(Psych.dump(thing)) + struct = Psych.unsafe_load(Psych.dump(thing)) assert_equal 'hello', struct.bar assert_equal 'bar', struct.foo end def test_load - obj = Psych.load(<<-eoyml) + obj = Psych.unsafe_load(<<-eoyml) --- !ruby/struct:PsychStructWithIvar :foo: bar :@bar: hello diff --git a/ruby/test/psych/test_yaml.rb b/ruby/test/psych/test_yaml.rb index 5fa759c98..e12b9769f 100644 --- a/ruby/test/psych/test_yaml.rb +++ b/ruby/test/psych/test_yaml.rb @@ -17,7 +17,7 @@ def teardown end def test_y_method - assert_raises(NoMethodError) do + assert_raise(NoMethodError) do OpenStruct.new.y 1 end end @@ -573,7 +573,7 @@ def test_spec_root_fold end def test_spec_root_mapping - y = Psych::load( < { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <7, "center"=>{"x"=>73, "y"=>129}, "TYPE"=>"Shape: graph/circle"}, {"finish"=>{"x"=>89, "y"=>102}, "TYPE"=>"Shape: graph/line", "start"=>{"x"=>73, "y"=>129}}, {"TYPE"=>"Shape: graph/text", "value"=>"Pretty vector drawing.", "start"=>{"x"=>73, "y"=>129}, "color"=>16772795}, "Shape Container"]], <(s) { stderr = s } + stderr = stderr.lines[1..-1].join if RUBY_PLATFORM.match?(/java/) + assert_equal(<<~STDERR, stderr) + 1 useless nonterminals: + dummy + 2 useless rules: + #4 (dummy) + #5 (dummy) + 1 shift/reduce conflicts + Turn on logging with "-v" and check ".output" file for details + STDERR + end end end diff --git a/ruby/test/racc/test_scan_y.rb b/ruby/test/racc/test_scan_y.rb index 4c6011911..fcd7e53c9 100644 --- a/ruby/test/racc/test_scan_y.rb +++ b/ruby/test/racc/test_scan_y.rb @@ -1,4 +1,4 @@ -require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) +require File.expand_path(File.join(__dir__, 'case')) module Racc class TestScanY < TestCase diff --git a/ruby/test/rdoc/support/test_case.rb b/ruby/test/rdoc/support/test_case.rb index 9a4f04b76..7617fc847 100644 --- a/ruby/test/rdoc/support/test_case.rb +++ b/ruby/test/rdoc/support/test_case.rb @@ -1,16 +1,3 @@ -## -# RDoc::TestCase is an abstract TestCase to provide common setup and teardown -# across all RDoc tests. The test case uses minitest, so all the assertions -# of minitest may be used. -# -# The testcase provides the following: -# -# * A reset code-object tree -# * A reset markup preprocessor (RDoc::Markup::PreProcess) -# * The @RM alias of RDoc::Markup (for less typing) -# * @pwd containing the current working directory -# * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO - require 'bundler/errors' begin gem 'test-unit' @@ -30,8 +17,8 @@ ## # RDoc::TestCase is an abstract TestCase to provide common setup and teardown -# across all RDoc tests. The test case uses minitest, so all the assertions -# of minitest may be used. +# across all RDoc tests. The test case uses test-unit, so all the assertions +# of test-unit may be used. # # The testcase provides the following: # @@ -49,6 +36,9 @@ class RDoc::TestCase < Test::Unit::TestCase def setup super + @orig_home = ENV["HOME"] + ENV["HOME"] = Dir.tmpdir + @top_level = nil @RM = RDoc::Markup @@ -69,6 +59,15 @@ def g.file_dir() end RDoc::Markup::PreProcess.reset end + ## + # Abstract test-case teardown + + def teardown + ENV["HOME"] = @orig_home if defined?(@orig_home) + + super + end + ## # Asserts +path+ is a file diff --git a/ruby/test/rdoc/test_rdoc_any_method.rb b/ruby/test/rdoc/test_rdoc_any_method.rb index 615789dfb..caff86b05 100644 --- a/ruby/test/rdoc/test_rdoc_any_method.rb +++ b/ruby/test/rdoc/test_rdoc_any_method.rb @@ -72,6 +72,54 @@ def test_is_alias_for assert_nil m1.is_alias_for, 'missing alias' end + def test_call_seq_handles_aliases + # see 0ead786 + @store.path = Dir.tmpdir + top_level = @store.add_file 'file.rb' + cm = top_level.add_class RDoc::ClassModule, 'Klass' + + method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq") + method_with_call_seq.call_seq = <<~SEQ + method_with_call_seq(a) + method_with_call_seq(a, b) + alias_to_method(a) + alias_to_method(a, b) + SEQ + cm.add_method(method_with_call_seq) + + alias_to_method = method_with_call_seq.add_alias( + RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"), + cm + ) + + assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)", + method_with_call_seq.call_seq) + assert_equal("alias_to_method(a)\nalias_to_method(a, b)", + alias_to_method.call_seq) + end + + def test_call_seq_returns_nil_if_alias_is_missing_from_call_seq + @store.path = Dir.tmpdir + top_level = @store.add_file 'file.rb' + cm = top_level.add_class RDoc::ClassModule, 'Klass' + + method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq") + method_with_call_seq.call_seq = <<~SEQ + method_with_call_seq(a) + method_with_call_seq(a, b) + SEQ + cm.add_method(method_with_call_seq) + + alias_to_method = method_with_call_seq.add_alias( + RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"), + cm + ) + + assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)", + method_with_call_seq.call_seq) + assert_nil(alias_to_method.call_seq) + end + def test_markup_code tokens = [ { :line_no => 0, :char_no => 0, :kind => :on_const, :text => 'CONSTANT' }, diff --git a/ruby/test/rdoc/test_rdoc_class_module.rb b/ruby/test/rdoc/test_rdoc_class_module.rb index 4dcc5d15a..13021b9cc 100644 --- a/ruby/test/rdoc/test_rdoc_class_module.rb +++ b/ruby/test/rdoc/test_rdoc_class_module.rb @@ -63,7 +63,7 @@ def test_add_comment_stopdoc end def test_ancestors - assert_equal [@parent, "Object"], @child.ancestors + assert_equal [@parent, @object, "BasicObject"], @child.ancestors end def test_comment_equals @@ -89,7 +89,7 @@ def test_comment_equals_comment assert_equal 'comment', cm.comment.text end - def test_docuent_self_or_methods + def test_document_self_or_methods assert @c1.document_self_or_methods @c1.document_self = false @@ -129,7 +129,7 @@ def test_documented_eh end def test_each_ancestor - assert_equal [@parent], @child.each_ancestor.to_a + assert_equal [@parent, @object], @child.each_ancestor.to_a end def test_each_ancestor_cycle @@ -238,7 +238,7 @@ def test_marshal_dump assert_equal tl, loaded.method_list.first.file end - def test_marshal_dump_visibilty + def test_marshal_dump_visibility @store.path = Dir.tmpdir tl = @store.add_file 'file.rb' diff --git a/ruby/test/rdoc/test_rdoc_context.rb b/ruby/test/rdoc/test_rdoc_context.rb index ecdb3cbd6..f77fb3138 100644 --- a/ruby/test/rdoc/test_rdoc_context.rb +++ b/ruby/test/rdoc/test_rdoc_context.rb @@ -125,7 +125,7 @@ def test_add_class_basic_object basic = @c1.find_module_named 'BasicObject' - assert_equal 'Object', basic.superclass + assert_equal @object, basic.superclass end def test_add_class_object diff --git a/ruby/test/rdoc/test_rdoc_context_section.rb b/ruby/test/rdoc/test_rdoc_context_section.rb index c520ad05a..24c68c49d 100644 --- a/ruby/test/rdoc/test_rdoc_context_section.rb +++ b/ruby/test/rdoc/test_rdoc_context_section.rb @@ -143,13 +143,5 @@ def test_remove_comment_document assert_equal doc(other_comment.parse), loaded.comments end - def test_sequence - _, err = verbose_capture_output do - assert_match(/\ASEC\d{5}\Z/, @s.sequence) - end - - assert_equal "#{@S}#sequence is deprecated, use #aref\n", err - end - end diff --git a/ruby/test/rdoc/test_rdoc_cross_reference.rb b/ruby/test/rdoc/test_rdoc_cross_reference.rb index 183de0930..f73681ebc 100644 --- a/ruby/test/rdoc/test_rdoc_cross_reference.rb +++ b/ruby/test/rdoc/test_rdoc_cross_reference.rb @@ -20,7 +20,7 @@ def refute_ref name def test_METHOD_REGEXP_STR re = /#{RDoc::CrossReference::METHOD_REGEXP_STR}/ - %w'=== [] []= << >>'.each do |x| + %w'== === [] []= << >>'.each do |x| re =~ x assert_equal x, $& end @@ -88,6 +88,15 @@ def test_resolve_C4_C4 assert_ref @c4_c4, 'C4' end + def test_resolve_class_and_method_of_the_same_name + assert_ref @c10_class, 'C10' + assert_ref @c10_method, '#C10' + assert_ref @c11_class, 'C11' + assert_ref @c11_method, '#C11' + assert_ref @c10_c11_class, 'C10::C11' + assert_ref @c10_c11_method, 'C10#C11' + end + def test_resolve_class assert_ref @c1, 'C1' refute_ref 'H1' diff --git a/ruby/test/rdoc/test_rdoc_extend.rb b/ruby/test/rdoc/test_rdoc_extend.rb index f4c842586..e78f287b8 100644 --- a/ruby/test/rdoc/test_rdoc_extend.rb +++ b/ruby/test/rdoc/test_rdoc_extend.rb @@ -43,7 +43,7 @@ def test_module_extended m1_m2_k0.add_extend e0_m3 assert_equal [e0_m4, e0_m5, e0_m6, e0_m1, e0_m2, e0_m3], m1_m2_k0.extends - assert_equal ['Object'], m1_m2_k0.ancestors + assert_equal [@object, 'BasicObject'], m1_m2_k0.ancestors m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1' @@ -60,7 +60,7 @@ def test_module_extended m1_k1.add_extend e1_k0_m4 assert_equal [e1_m1, e1_m2, e1_m3, e1_m4, e1_k0_m4], m1_k1.extends - assert_equal ['Object'], m1_k1.ancestors + assert_equal [@object, 'BasicObject'], m1_k1.ancestors m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2' @@ -75,7 +75,7 @@ def test_module_extended m1_k2.add_extend e2_k0_m4 assert_equal [e2_m1, e2_m3, e2_m2, e2_k0_m4], m1_k2.extends - assert_equal ['Object'], m1_k2.ancestors + assert_equal [@object, 'BasicObject'], m1_k2.ancestors m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3' @@ -88,7 +88,7 @@ def test_module_extended m1_k3.add_extend e3_m4 assert_equal [e3_m1, e3_m2, e3_m4], m1_k3.extends - assert_equal ['Object'], m1_k3.ancestors + assert_equal [@object, 'BasicObject'], m1_k3.ancestors end end diff --git a/ruby/test/rdoc/test_rdoc_generator_darkfish.rb b/ruby/test/rdoc/test_rdoc_generator_darkfish.rb index f5858bce6..b78a3fb45 100644 --- a/ruby/test/rdoc/test_rdoc_generator_darkfish.rb +++ b/ruby/test/rdoc/test_rdoc_generator_darkfish.rb @@ -142,15 +142,6 @@ def test_install_rdoc_static_file @g.install_rdoc_static_file src, dst, options assert_file dst - - begin - assert_hard_link dst - rescue MiniTest::Assertion - return # hard links are not supported, no further tests needed - end - - @g.install_rdoc_static_file src, dst, options - assert_hard_link dst end @@ -220,6 +211,21 @@ def test_generated_method_with_html_tag_yield assert_includes method_name, '{ |%<<script>alert("atui")</script>>, yield_arg| ... }' end + def test_template_stylesheets + css = Tempfile.create(%W'hoge .css', Dir.mktmpdir('tmp', '.')) + File.write(css, '') + css.close + base = File.basename(css) + refute_file(base) + + @options.template_stylesheets << css + + @g.generate + + assert_file base + assert_include File.read('index.html'), %Q[href="./#{base}"] + end + ## # Asserts that +filename+ has a link count greater than 1 if hard links to # @tmpdir are supported. diff --git a/ruby/test/rdoc/test_rdoc_generator_json_index.rb b/ruby/test/rdoc/test_rdoc_generator_json_index.rb index 66d15d184..6b69337b4 100644 --- a/ruby/test/rdoc/test_rdoc_generator_json_index.rb +++ b/ruby/test/rdoc/test_rdoc_generator_json_index.rb @@ -104,7 +104,7 @@ def test_generate orig_file = Pathname(File.join srcdir, 'generator/template/json_index/js/navigation.js') generated_file = Pathname(File.join @tmpdir, 'js/navigation.js') - # This is dirty hack on JRuby for MiniTest 4 + # This is dirty hack on JRuby assert orig_file.mtime.inspect == generated_file.mtime.inspect, '.js files should be the same timestamp of original' diff --git a/ruby/test/rdoc/test_rdoc_include.rb b/ruby/test/rdoc/test_rdoc_include.rb index 67d3dfd88..b8e8f2603 100644 --- a/ruby/test/rdoc/test_rdoc_include.rb +++ b/ruby/test/rdoc/test_rdoc_include.rb @@ -46,7 +46,7 @@ def test_module_extended assert_equal [i0_m4, i0_m5, i0_m6, i0_m1, i0_m2, i0_m3], m1_m2_k0.includes assert_equal [m1_m2_m3, m1_m2, m1, m1_m2_k0_m4_m6, m1_m2_k0_m5, - m1_m2_k0_m4, 'Object'], m1_m2_k0.ancestors + m1_m2_k0_m4, @object, 'BasicObject'], m1_m2_k0.ancestors m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1' @@ -63,8 +63,8 @@ def test_module_extended m1_k1.add_include i1_k0_m4 assert_equal [i1_m1, i1_m2, i1_m3, i1_m4, i1_k0_m4], m1_k1.includes - assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, 'Object'], - m1_k1.ancestors + assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, @object, + 'BasicObject'], m1_k1.ancestors m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2' @@ -79,7 +79,8 @@ def test_module_extended m1_k2.add_include i2_k0_m4 assert_equal [i2_m1, i2_m3, i2_m2, i2_k0_m4], m1_k2.includes - assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, 'Object'], m1_k2.ancestors + assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, @object, 'BasicObject'], + m1_k2.ancestors m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3' @@ -92,7 +93,7 @@ def test_module_extended m1_k3.add_include i3_m4 assert_equal [i3_m1, i3_m2, i3_m4], m1_k3.includes - assert_equal [m1_m2_m4, m1_m2, m1, 'Object'], m1_k3.ancestors + assert_equal [m1_m2_m4, m1_m2, m1, @object, 'BasicObject'], m1_k3.ancestors end def test_store_equals diff --git a/ruby/test/rdoc/test_rdoc_markdown.rb b/ruby/test/rdoc/test_rdoc_markdown.rb index 021d94297..ad53e9473 100644 --- a/ruby/test/rdoc/test_rdoc_markdown.rb +++ b/ruby/test/rdoc/test_rdoc_markdown.rb @@ -8,6 +8,8 @@ class TestRDocMarkdown < RDoc::TestCase def setup + super + @RM = RDoc::Markup @parser = RDoc::Markdown.new @@ -141,7 +143,7 @@ def test_parse_code end def test_parse_code_github - doc = parse <<-MD + doc = <<-MD Example: ``` @@ -154,11 +156,25 @@ def test_parse_code_github para("Example:"), verb("code goes here\n")) - assert_equal expected, doc + assert_equal expected, parse(doc) + assert_equal expected, parse(doc.sub(/^\n/, '')) + + @parser.github = false + + expected = + doc(para("Example:"), + para("\n""code goes here\n")) + + assert_equal expected, parse(doc) + + expected = + doc(para("Example:\n\n""code goes here\n")) + + assert_equal expected, parse(doc.sub(/^\n/, '')) end def test_parse_code_github_format - doc = parse <<-MD + doc = <<-MD Example: ``` ruby @@ -174,7 +190,21 @@ def test_parse_code_github_format para("Example:"), code) - assert_equal expected, doc + assert_equal expected, parse(doc) + assert_equal expected, parse(doc.sub(/^\n/, '')) + + @parser.github = false + + expected = + doc(para("Example:"), + para("ruby\n""code goes here\n")) + + assert_equal expected, parse(doc) + + expected = + doc(para("Example:\nruby\n""code goes here\n")) + + assert_equal expected, parse(doc.sub(/^\n/, '')) end def test_parse_definition_list @@ -1010,6 +1040,29 @@ def test_code_fence_with_unintended_array assert_equal expected, doc end + def test_gfm_table + doc = parse <<~MD + | | |compare-ruby|built-ruby| + |------|:----------------|-----------:|---------:| + |test | 1 | 11.618M| 10.757M| + | | | 1.08x| -| + |test | 10 | 1.849M| 1.723M| + | | | 1.07x| -| + MD + + head = ["", "", "compare-ruby", "built-ruby"] + align = [nil, :left, :right, :right] + body = [ + ["test", "1", "11.618M", "10.757M"], + ["", "", "1.08x", "-"], + ["test", "10", "1.849M", "1.723M"], + ["", "", "1.07x", "-"], + ] + expected = doc(@RM::Table.new(head, align, body)) + + assert_equal expected, doc + end + def parse text @parser.parse text end diff --git a/ruby/test/rdoc/test_rdoc_markup_attribute_manager.rb b/ruby/test/rdoc/test_rdoc_markup_attribute_manager.rb index a18066686..944364ba8 100644 --- a/ruby/test/rdoc/test_rdoc_markup_attribute_manager.rb +++ b/ruby/test/rdoc/test_rdoc_markup_attribute_manager.rb @@ -172,22 +172,25 @@ def test_combined def test_convert_attrs str = '+foo+'.dup - attrs = RDoc::Markup::AttrSpan.new str.length + attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap + @am.convert_attrs str, attrs, true @am.convert_attrs str, attrs assert_equal "\000foo\000", str str = '+:foo:+'.dup - attrs = RDoc::Markup::AttrSpan.new str.length + attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap + @am.convert_attrs str, attrs, true @am.convert_attrs str, attrs assert_equal "\000:foo:\000", str str = '+x-y+'.dup - attrs = RDoc::Markup::AttrSpan.new str.length + attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap + @am.convert_attrs str, attrs, true @am.convert_attrs str, attrs assert_equal "\000x-y\000", str @@ -243,6 +246,22 @@ def test_escapes output('unhandled

      tag

      unchanged') end + def test_exclude_tag + assert_equal 'aaa[:symbol]', output('+aaa+[:symbol]') + assert_equal 'aaa[:symbol]', output('+aaa[:symbol]+') + assert_equal 'aaa[:symbol]', output('aaa[:symbol]') + assert_equal 'index', output('index') + end + + def test_exclude_tag_flow + assert_equal [@tt_on, "aaa", @tt_off, "[:symbol]"], + @am.flow("+aaa+[:symbol]") + assert_equal [@tt_on, "aaa[:symbol]", @tt_off], + @am.flow("+aaa[:symbol]+") + assert_equal ["aaa[:symbol]"], + @am.flow("aaa[:symbol]") + end + def test_html_like_em_bold assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off], @am.flow("cat and dog") diff --git a/ruby/test/rdoc/test_rdoc_markup_to_html.rb b/ruby/test/rdoc/test_rdoc_markup_to_html.rb index fb9426906..b2b21de80 100644 --- a/ruby/test/rdoc/test_rdoc_markup_to_html.rb +++ b/ruby/test/rdoc/test_rdoc_markup_to_html.rb @@ -704,6 +704,17 @@ def test_convert_TIDYLINK_irc assert_equal "\n

      ruby-lang

      \n", result end + def test_convert_with_exclude_tag + assert_equal "\n

      aaa[:symbol]

      \n", @to.convert('+aaa+[:symbol]') + assert_equal "\n

      aaa[:symbol]

      \n", @to.convert('+aaa[:symbol]+') + assert_equal "\n

      aaa

      \n", @to.convert('aaa[:symbol]') + end + + def test_convert_underscore_adjacent_to_code + assert_equal "\n

      aaa_

      \n", @to.convert(%q{+aaa+_}) + assert_equal "\n

      \u{2018}i386-mswin32_MSRTVERSION\u{2019}

      \n", @to.convert(%q{`+i386-mswin32_+_MSRTVERSION_'}) + end + def test_gen_url assert_equal 'example', @to.gen_url('link:example', 'example') @@ -727,6 +738,45 @@ def test_gen_url_ssl_image_url assert_equal '', @to.gen_url('https://example.com/image.png', 'ignored') end + def test_gen_url_rdoc_file + assert_equal 'example', + @to.gen_url('example.rdoc', 'example') + assert_equal 'example', + @to.gen_url('doc/example.rdoc', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.rdoc', 'example') + assert_equal 'example', + @to.gen_url('doc/example.rdoc#label-one', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.rdoc#label-two', 'example') + end + + def test_gen_url_md_file + assert_equal 'example', + @to.gen_url('example.md', 'example') + assert_equal 'example', + @to.gen_url('doc/example.md', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.md', 'example') + assert_equal 'example', + @to.gen_url('doc/example.md#label-one', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.md#label-two', 'example') + end + + def test_gen_url_rb_file + assert_equal 'example', + @to.gen_url('example.rb', 'example') + assert_equal 'example', + @to.gen_url('doc/example.rb', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.rb', 'example') + assert_equal 'example', + @to.gen_url('doc/example.rb#label-one', 'example') + assert_equal 'example', + @to.gen_url('../ex.doc/example.rb#label-two', 'example') + end + def test_handle_regexp_HYPERLINK_link target = RDoc::Markup::RegexpHandling.new 0, 'link:README.txt' diff --git a/ruby/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/ruby/test/rdoc/test_rdoc_markup_to_html_crossref.rb index bac2569f8..f6fabfb7d 100644 --- a/ruby/test/rdoc/test_rdoc_markup_to_html_crossref.rb +++ b/ruby/test/rdoc/test_rdoc_markup_to_html_crossref.rb @@ -89,6 +89,20 @@ def test_convert_RDOCLINK_rdoc_ref_method_percent assert_equal para("C1::%"), result end + def test_convert_RDOCLINK_rdoc_ref_method_escape_html + m = @c1.add_method RDoc::AnyMethod.new nil, '<<' + m.singleton = false + + result = @to.convert 'rdoc-ref:C1#<<' + + assert_equal para("C1#<<"), result + m.singleton = true + + result = @to.convert 'rdoc-ref:C1::<<' + + assert_equal para("C1::<<"), result + end + def test_convert_RDOCLINK_rdoc_ref_method_percent_label m = @c1.add_method RDoc::AnyMethod.new nil, '%' m.singleton = false @@ -137,6 +151,13 @@ def test_handle_regexp_CROSSREF_show_hash_false REGEXP_HANDLING('#m') end + def test_handle_regexp_CROSSREF_with_arg_looks_like_TIDYLINK + result = @to.convert 'C1.m[:sym]' + + assert_equal para("C1.m[:sym]"), result, + 'C1.m[:sym]' + end + def test_handle_regexp_HYPERLINK_rdoc readme = @store.add_file 'README.txt' readme.parser = RDoc::Parser::Simple diff --git a/ruby/test/rdoc/test_rdoc_markup_to_markdown.rb b/ruby/test/rdoc/test_rdoc_markup_to_markdown.rb index 4d3a00538..c8c5fd4d5 100644 --- a/ruby/test/rdoc/test_rdoc_markup_to_markdown.rb +++ b/ruby/test/rdoc/test_rdoc_markup_to_markdown.rb @@ -363,9 +363,9 @@ def test_convert_RDOCLINK_image def test_convert_TIDYLINK result = @to.convert \ - '{DSL}[http://en.wikipedia.org/wiki/Domain-specific_language]' + '{DSL}[https://en.wikipedia.org/wiki/Domain-specific_language]' - expected = "[DSL](http://en.wikipedia.org/wiki/Domain-specific_language)\n" + expected = "[DSL](https://en.wikipedia.org/wiki/Domain-specific_language)\n" assert_equal expected, result end diff --git a/ruby/test/rdoc/test_rdoc_normal_class.rb b/ruby/test/rdoc/test_rdoc_normal_class.rb index 874eaaa88..7cb5e4bfc 100644 --- a/ruby/test/rdoc/test_rdoc_normal_class.rb +++ b/ruby/test/rdoc/test_rdoc_normal_class.rb @@ -11,7 +11,7 @@ def test_ancestors sub_klass.superclass = klass sub_klass.add_include incl - assert_equal [incl.name, klass, 'Object'], sub_klass.ancestors + assert_equal [incl.name, klass, @object, 'BasicObject'], sub_klass.ancestors end def test_ancestors_multilevel @@ -19,7 +19,7 @@ def test_ancestors_multilevel c2 = @top_level.add_class RDoc::NormalClass, 'Middle', c1.full_name c3 = @top_level.add_class RDoc::NormalClass, 'Inner', c2.full_name - assert_equal [c2, c1, 'Object'], c3.ancestors + assert_equal [c2, c1, @object, 'BasicObject'], c3.ancestors end def test_aref diff --git a/ruby/test/rdoc/test_rdoc_options.rb b/ruby/test/rdoc/test_rdoc_options.rb index 140c4afc9..7c264c5e8 100644 --- a/ruby/test/rdoc/test_rdoc_options.rb +++ b/ruby/test/rdoc/test_rdoc_options.rb @@ -145,7 +145,7 @@ def test_init_with_encoding @options.encoding = Encoding::IBM437 - options = YAML.load YAML.dump @options + options = YAML.safe_load(YAML.dump(@options), permitted_classes: [RDoc::Options, Symbol]) assert_equal Encoding::IBM437, options.encoding end @@ -161,7 +161,7 @@ def test_init_with_trim_paths - /etc YAML - options = YAML.load yaml + options = YAML.safe_load(yaml, permitted_classes: [RDoc::Options, Symbol]) assert_empty options.rdoc_include assert_empty options.static_path @@ -632,6 +632,21 @@ def test_parse_template_load_path $LOAD_PATH.replace orig_LOAD_PATH end + def test_parse_template_stylesheets + css = nil + Dir.mktmpdir do |dir| + css = File.join(dir, "hoge.css") + File.write(css, "") + out, err = capture_output do + @options.parse %W[--template-stylesheets #{css}] + end + + assert_empty out + assert_empty err + end + assert_include @options.template_stylesheets, css + end + def test_parse_visibility @options.parse %w[--visibility=public] assert_equal :public, @options.visibility @@ -749,7 +764,7 @@ def test_write_options assert File.exist? '.rdoc_options' - assert_equal @options, YAML.load(File.read('.rdoc_options')) + assert_equal @options, YAML.safe_load(File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol]) end end @@ -777,4 +792,62 @@ def test_visibility @options.visibility = :all assert_equal :private, @options.visibility end + + def test_load_options + temp_dir do + options = RDoc::Options.new + options.markup = 'tomdoc' + options.write_options + + options = RDoc::Options.load_options + + assert_equal 'tomdoc', options.markup + end + end + + def test_load_options_invalid + temp_dir do + File.open '.rdoc_options', 'w' do |io| + io.write "a: !ruby.yaml.org,2002:str |\nfoo" + end + + e = assert_raise RDoc::Error do + RDoc::Options.load_options + end + + options_file = File.expand_path '.rdoc_options' + assert_equal "#{options_file} is not a valid rdoc options file", e.message + end + end + + def test_load_options_empty_file + temp_dir do + File.open '.rdoc_options', 'w' do |io| + end + + options = RDoc::Options.load_options + + assert_equal 'rdoc', options.markup + end + end + + def test_load_options_partial_override + temp_dir do + File.open '.rdoc_options', 'w' do |io| + io.write "markup: Markdown" + end + + options = RDoc::Options.load_options + + assert_equal 'Markdown', options.markup + end + end + + def load_options_no_file + temp_dir do + options = RDoc::Options.load_options + + assert_kind_of RDoc::Options, options + end + end end diff --git a/ruby/test/rdoc/test_rdoc_parser_c.rb b/ruby/test/rdoc/test_rdoc_parser_c.rb index 6601d28f6..8f51f32f2 100644 --- a/ruby/test/rdoc/test_rdoc_parser_c.rb +++ b/ruby/test/rdoc/test_rdoc_parser_c.rb @@ -1600,6 +1600,39 @@ def test_define_method assert_equal "Method Comment! ", read_method.comment.text assert_equal "rb_io_s_read", read_method.c_function assert read_method.singleton + assert_nil read_method.section.title + end + + def test_define_method_with_category + content = <<-EOF +/* :category: Awesome Methods + Method Comment! + */ +static VALUE +rb_io_s_read(argc, argv, io) + int argc; + VALUE *argv; + VALUE io; +{ +} + +void +Init_IO(void) { + /* + * a comment for class Foo on rb_define_class + */ + VALUE rb_cIO = rb_define_class("IO", rb_cObject); + rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1); +} + EOF + + klass = util_get_class content, 'rb_cIO' + read_method = klass.method_list.first + assert_equal "read", read_method.name + assert_equal "Method Comment!", read_method.comment.text.strip + assert_equal "rb_io_s_read", read_method.c_function + assert read_method.singleton + assert_equal "Awesome Methods", read_method.section.title end def test_define_method_dynamically @@ -1930,6 +1963,39 @@ def test_scan_order_dependent @store.all_classes_and_modules.map { |m| m.full_name }.sort end + def test_markup_format_default + content = <<-EOF +void Init_Blah(void) { + cBlah = rb_define_class("Blah", rb_cObject); + + /* + * This should be interpreted in the default format. + */ + rb_attr(cBlah, rb_intern("default_format"), 1, 1, Qfalse); +} + EOF + + klass = util_get_class content, 'cBlah' + assert_equal("rdoc", klass.attributes.find {|a| a.name == "default_format"}.comment.format) + end + + def test_markup_format_override + content = <<-EOF +void Init_Blah(void) { + cBlah = rb_define_class("Blah", rb_cObject); + + /* + * This should be interpreted in the default format. + */ + rb_attr(cBlah, rb_intern("default_format"), 1, 1, Qfalse); +} + EOF + + @options.markup = "markdown" + klass = util_get_class content, 'cBlah' + assert_equal("markdown", klass.attributes.find {|a| a.name == "default_format"}.comment.format) + end + def util_get_class content, name = nil @parser = util_parser content @parser.scan diff --git a/ruby/test/rdoc/test_rdoc_parser_changelog.rb b/ruby/test/rdoc/test_rdoc_parser_changelog.rb index cb6406259..658484057 100644 --- a/ruby/test/rdoc/test_rdoc_parser_changelog.rb +++ b/ruby/test/rdoc/test_rdoc_parser_changelog.rb @@ -14,6 +14,8 @@ def setup def teardown @tempfile.close! + + super end def test_class_can_parse @@ -210,6 +212,8 @@ def test_parse_entries change condition of using `opt_send_simple'. More method invocations can be simple. +commit\ 8187228de0142d3ac7950b7d977c2849e934c637 + Other note that will be ignored ChangeLog @@ -268,6 +272,24 @@ def test_parse_entries_gnu assert_equal expected, parser.parse_entries end + def test_parse_entries_git + parser = util_parser <<-ChangeLog +commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3 + Author: git + Date: 2021-01-21 01:03:52 +0900 + + * 2021-01-21 [ci skip] +ChangeLog + + expected = [ + [ "709bed2afaee50e2ce80", + [ "git", "svn-admin@ruby-lang.org", + "2021-01-21 01:03:52 +0900", + "* 2021-01-21 [ci skip]\n"]]] + + assert_equal expected, parser.parse_entries + end + def test_scan parser = util_parser <<-ChangeLog Tue Dec 4 08:32:10 2012 Eric Hodel @@ -307,10 +329,157 @@ def test_scan assert_equal expected, @top_level.comment end + def test_scan_git + parser = util_parser <<-ChangeLog +commit\ 38816887962ec167ee46acf500f68df5c3013163 +Author: git +Date: Sun Jan 24 14:35:51 2021 +0900 + + * 2021-01-24 [ci skip] + +commit\ db7d0b89f6eca66cc7eb155c95f9123133da1ffc +Author: git +Date: Sat, 23 Jan 2021 06:01:39 +0900 + + * 2021-01-23 [ci skip] + +commit\ a3efbda7128ef20b55505b32d1608ea48f80af4a +Author: git +Date: 2021-01-22T02:49:39+09:00 + + * 2021-01-22 [ci skip] + +commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3 + Author: git + Date: 2021-01-21 01:03:52 +0900 + + * 2021-01-21 [ci skip] + +commit\ a8dc5156e183489c5121fb1759bda5d9406d9175 + Author: git + Date: 2021-01-20 01:58:26 +0900 + + * 2021-01-20 [ci skip] + +commit\ de5f8a92d5001799bedb3b1a271a2d9b23c6c8fb + Author: Masataka Pocke Kuwabara + Date: 2021-01-01 14:25:08 +0900 + + Make args info for RubyVM::AST to available on endless method without parens + + Problem + === + + Arguments information is missing for endless method without parens. + For example: + + ```ruby + # ok + ``` + + It causes an error if a program expects `args` node exists. + + Solution + === + + Call `new_args` on this case. +ChangeLog + + parser.scan + + expected = doc( + head(1, File.basename(@tempfile.path)), + blank_line, + head(2, '2021-01-24'), + blank_line, + log_entry(nil, '38816887962ec167ee46', + 'git', 'svn-admin@ruby-lang.org', 'Sun Jan 24 14:35:51 2021 +0900', + [list(:BULLET, item(nil, para('2021-01-24 [ci skip]')))]), + head(2, '2021-01-23'), + blank_line, + log_entry(nil, 'db7d0b89f6eca66cc7eb', + 'git', 'svn-admin@ruby-lang.org', 'Sat, 23 Jan 2021 06:01:39 +0900', + [list(:BULLET, item(nil, para('2021-01-23 [ci skip]')))]), + head(2, '2021-01-22'), + blank_line, + log_entry(nil, 'a3efbda7128ef20b5550', + 'git', 'svn-admin@ruby-lang.org', '2021-01-22T02:49:39+09:00', + [list(:BULLET, item(nil, para('2021-01-22 [ci skip]')))]), + head(2, '2021-01-21'), + blank_line, + log_entry(nil, '709bed2afaee50e2ce80', + 'git', 'svn-admin@ruby-lang.org', '2021-01-21 01:03:52 +0900', + [list(:BULLET, item(nil, para('2021-01-21 [ci skip]')))]), + head(2, '2021-01-20'), + blank_line, + log_entry(nil, 'a8dc5156e183489c5121', + 'git', 'svn-admin@ruby-lang.org', '2021-01-20 01:58:26 +0900', + [list(:BULLET, item(nil, para('2021-01-20 [ci skip]')))]), + head(2, '2021-01-01'), + blank_line, + log_entry(nil, 'de5f8a92d5001799bedb', + 'Masataka Pocke Kuwabara', 'kuwabara@pocke.me', '2021-01-01 14:25:08 +0900', + [head(4, 'Make args info for RubyVM::AST to available on endless method without parens'), + head(5, 'Problem'), + para("Arguments information is missing for endless method without parens.\n" + + "For example:"), + verb("# ok\n").tap {|v| v.format = :ruby}, + para('It causes an error if a program expects args node exists.'), + head(5, 'Solution'), + para('Call new_args on this case.')])) + + expected.file = @top_level + + assert_equal expected, @top_level.comment + end + + def test_scan_git_commit_date + parser = util_parser <<-ChangeLog +commit\ ee1e690a2df901adb279d7a63fbd92c64e0a5ae6 + Author: Igor Zubkov + AuthorDate: 2016-10-25 03:56:11 +0900 + Commit: Nobuyoshi Nakada + CommitDate: 2021-01-07 13:40:42 +0900 + + We don't need "require 'uri'" after "require 'net/http'". + +commit\ 4d0985a7bd8f591dff4b430e288bfd83af782e51 + Author: git + AuthorDate: 2021-01-07 10:21:34 +0900 + Commit: git + CommitDate: 2021-01-07 10:21:34 +0900 + + * 2021-01-07 [ci skip] +ChangeLog + + parser.scan + + expected = doc( + head(1, File.basename(@tempfile.path)), + blank_line, + head(2, "2021-01-07"), + blank_line, + log_entry(nil, 'ee1e690a2df901adb279', + 'Igor Zubkov', 'igor.zubkov@gmail.com', + '2016-10-25 03:56:11 +0900', + [head(4, %[We don't need "require 'uri'" after "require 'net/http'".])]), + log_entry(nil, '4d0985a7bd8f591dff4b', + 'git', 'svn-admin@ruby-lang.org', + '2021-01-07 10:21:34 +0900', + [list(:BULLET, item(nil, para("2021-01-07 [ci skip]")))])) + + expected.file = @top_level + + assert_equal expected, @top_level.comment + end + def util_parser content = '' RDoc::Parser::ChangeLog.new \ @top_level, @tempfile.path, content, @options, @stats end + def log_entry(*a) + RDoc::Parser::ChangeLog::Git::LogEntry.new(*a) + end end diff --git a/ruby/test/rdoc/test_rdoc_parser_ruby.rb b/ruby/test/rdoc/test_rdoc_parser_ruby.rb index 0c8190609..337cf9ea1 100644 --- a/ruby/test/rdoc/test_rdoc_parser_ruby.rb +++ b/ruby/test/rdoc/test_rdoc_parser_ruby.rb @@ -4297,4 +4297,52 @@ class D assert_equal 'A::D', a_d.full_name end + def test_parse_included + util_parser <<-CLASS +module A + module B + extend ActiveSupport::Concern + included do + ## + # :singleton-method: + # Hello + mattr_accessor :foo + end + end +end + CLASS + + @parser.scan + + a = @store.find_module_named 'A' + assert_equal 'A', a.full_name + a_b = a.find_module_named 'B' + assert_equal 'A::B', a_b.full_name + meth = a_b.method_list.first + assert_equal 'foo', meth.name + assert_equal 'Hello', meth.comment.text + end + + def test_end_that_doesnt_belong_to_class_doesnt_change_visibility + util_parser <<-CLASS +class A + private + + begin + end + + # Hello + def foo() end +end + CLASS + + @parser.scan + + a = @store.find_class_named 'A' + assert_equal 'A', a.full_name + assert_equal 'foo', a.find_method_named('foo').name + meth = a.method_list.first + assert_equal 'Hello', meth.comment.text + end + end diff --git a/ruby/test/rdoc/test_rdoc_rdoc.rb b/ruby/test/rdoc/test_rdoc_rdoc.rb index f2cc90128..eaf92c8a9 100644 --- a/ruby/test/rdoc/test_rdoc_rdoc.rb +++ b/ruby/test/rdoc/test_rdoc_rdoc.rb @@ -73,6 +73,11 @@ def test_gather_files b = File.expand_path '../test_rdoc_text.rb', __FILE__ assert_equal [a, b], @rdoc.gather_files([b, a, b]) + + assert_empty @rdoc.gather_files([b, a, b]) + + @rdoc.last_modified[a] -= 10 + assert_equal [a, b], @rdoc.gather_files([b, a, b]) end def test_handle_pipe @@ -101,41 +106,6 @@ def test_handle_pipe_rd $stdin = STDIN end - def test_load_options - temp_dir do - options = RDoc::Options.new - options.markup = 'tomdoc' - options.write_options - - options = @rdoc.load_options - - assert_equal 'tomdoc', options.markup - end - end - - def test_load_options_invalid - temp_dir do - File.open '.rdoc_options', 'w' do |io| - io.write "a: !ruby.yaml.org,2002:str |\nfoo" - end - - e = assert_raise RDoc::Error do - @rdoc.load_options - end - - options_file = File.expand_path '.rdoc_options' - assert_equal "#{options_file} is not a valid rdoc options file", e.message - end - end - - def load_options_no_file - temp_dir do - options = @rdoc.load_options - - assert_kind_of RDoc::Options, options - end - end - def test_normalized_file_list test_path = File.expand_path(__FILE__) files = temp_dir do |dir| @@ -146,7 +116,7 @@ def test_normalized_file_list @rdoc.normalized_file_list [test_path, flag_file] end - files = files.map { |file| File.expand_path file } + files = files.map { |file, *| File.expand_path file } assert_equal [test_path], files end @@ -156,7 +126,9 @@ def test_normalized_file_list_not_modified files = @rdoc.normalized_file_list [__FILE__] - assert_empty files + files = files.collect {|file, mtime| file if mtime}.compact + + assert_empty(files) end def test_normalized_file_list_non_file_directory @@ -205,7 +177,7 @@ def test_normalized_file_list_with_dot_doc @rdoc.normalized_file_list [File.realpath(dir)] end - files = files.map { |file| File.expand_path file } + files = files.map { |file, *| File.expand_path file } assert_equal expected_files, files end @@ -236,7 +208,7 @@ def test_normalized_file_list_with_dot_doc_overridden_by_exclude_option @rdoc.normalized_file_list [File.realpath(dir)] end - files = files.map { |file| File.expand_path file } + files = files.map { |file, *| File.expand_path file } assert_equal expected_files, files end @@ -426,6 +398,19 @@ def test_remove_unparseable_tags_vim end end + def test_remove_unparseable_CVE_2021_31799 + omit 'for Un*x platforms' if Gem.win_platform? + temp_dir do + file_list = ['| touch evil.txt && echo tags'] + file_list.each do |f| + FileUtils.touch f rescue omit + end + + assert_equal file_list, @rdoc.remove_unparseable(file_list) + assert_equal file_list, Dir.children('.') + end + end + def test_setup_output_dir Dir.mktmpdir {|d| path = File.join d, 'testdir' diff --git a/ruby/test/rdoc/test_rdoc_ri_driver.rb b/ruby/test/rdoc/test_rdoc_ri_driver.rb index 6f17fecec..87e4ebd2b 100644 --- a/ruby/test/rdoc/test_rdoc_ri_driver.rb +++ b/ruby/test/rdoc/test_rdoc_ri_driver.rb @@ -13,8 +13,9 @@ def setup FileUtils.mkdir_p @home_ri @orig_ri = ENV['RI'] - @orig_home = ENV['HOME'] ENV['HOME'] = @tmpdir + @rdoc_home = File.join ENV["HOME"], ".rdoc" + FileUtils.mkdir_p @rdoc_home ENV.delete 'RI' @options = RDoc::RI::Driver.default_options @@ -31,11 +32,10 @@ def setup end def teardown - super - - ENV['HOME'] = @orig_home ENV['RI'] = @orig_ri FileUtils.rm_rf @tmpdir + + super end DUMMY_PAGER = ":;\n" @@ -81,7 +81,7 @@ def test_add_also_in @RM::Rule.new(1), @RM::Paragraph.new('Also found in:'), @RM::Verbatim.new("ruby core", "\n", - "~/.rdoc", "\n")) + @rdoc_home, "\n")) assert_equal expected, out end @@ -231,7 +231,7 @@ def test_add_method doc( head(1, 'Foo::Bar#blah'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), head(3, 'Implementation from Bar'), rule(1), verb("blah(5) => 5\n", @@ -254,7 +254,7 @@ def test_add_method_that_is_alias_for_original doc( head(1, 'Qux#aliased'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), rule(1), blank_line, para('alias comment'), @@ -280,7 +280,7 @@ def test_add_method_attribute doc( head(1, 'Foo::Bar#attr'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), rule(1), blank_line, blank_line) @@ -299,7 +299,7 @@ def test_add_method_inherited doc( head(1, 'Bar#inherit'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), head(3, 'Implementation from Foo'), rule(1), blank_line, @@ -343,13 +343,13 @@ def test_add_method_documentation doc( head(1, 'Foo#inherit'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), rule(1), blank_line, blank_line, head(1, 'Foo#override'), blank_line, - para('(from ~/.rdoc)'), + para("(from #{@rdoc_home})"), rule(1), blank_line, para('must not be displayed in Bar#override'), @@ -421,6 +421,30 @@ def test_ancestors_of assert_equal %w[X Mixin Object Foo], @driver.ancestors_of('Foo::Bar') end + def test_ancestors_of_chained_inclusion + # Store represents something like: + # + # module X + # end + # + # module Y + # include X + # end + # + # class Z + # include Y + # end + # + # Y is not chosen randomly, it has to be after Object in the alphabet + # to reproduce https://github.com/ruby/rdoc/issues/814. + store = RDoc::RI::Store.new @home_ri + store.cache[:ancestors] = { "Z" => ["Object", "Y"], "Y" => ["X"] } + store.cache[:modules] = %W[X Y Z] + @driver.stores = [store] + + assert_equal %w[X Y Object], @driver.ancestors_of('Z') + end + def test_classes util_multi_store @@ -802,7 +826,7 @@ def test_display_page_ambiguous @driver.display_page 'home:README' end - assert_match %r%= README pages in ~/\.rdoc%, out + assert_match %r%= README pages in #{@rdoc_home}%, out assert_match %r%README\.rdoc%, out assert_match %r%README\.md%, out end @@ -856,7 +880,7 @@ def test_display_page_missing @driver.display_page_list @store1 end - assert_match %r%= Pages in ~/\.rdoc%, out + assert_match %r%= Pages in #{@rdoc_home}%, out assert_match %r%README\.rdoc%, out end @@ -876,7 +900,7 @@ def test_display_page_list @driver.display_page_list @store1 end - assert_match %r%= Pages in ~/\.rdoc%, out + assert_match %r%= Pages in #{@rdoc_home}%, out assert_match %r%README\.rdoc%, out assert_match %r%OTHER\.rdoc%, out end diff --git a/ruby/test/rdoc/test_rdoc_ri_paths.rb b/ruby/test/rdoc/test_rdoc_ri_paths.rb index 726922daf..c01a4711e 100644 --- a/ruby/test/rdoc/test_rdoc_ri_paths.rb +++ b/ruby/test/rdoc/test_rdoc_ri_paths.rb @@ -36,12 +36,12 @@ def setup end def teardown - super - Gem.use_paths(*@orig_gem_path) Gem::Specification.reset FileUtils.rm_rf @tempdir ENV.replace(@orig_env) + + super end def test_class_each @@ -51,7 +51,7 @@ def test_class_each assert_equal RDoc::RI::Paths.system_dir, path.shift assert_equal RDoc::RI::Paths.site_dir, path.shift - assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir assert_equal File.join(@nodoc.doc_dir, 'ri'), path.shift assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift assert_equal File.join(@rdoc_4_0.doc_dir, 'ri'), path.shift @@ -128,7 +128,7 @@ def test_class_raw_path assert_equal RDoc::RI::Paths.system_dir, path.shift assert_equal RDoc::RI::Paths.site_dir, path.shift - assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift end @@ -138,7 +138,7 @@ def test_class_raw_path_extra_dirs assert_equal '/nonexistent', path.shift assert_equal RDoc::RI::Paths.system_dir, path.shift assert_equal RDoc::RI::Paths.site_dir, path.shift - assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift end diff --git a/ruby/test/rdoc/test_rdoc_rubygems_hook.rb b/ruby/test/rdoc/test_rdoc_rubygems_hook.rb index 7d59577d9..04f84d4bc 100644 --- a/ruby/test/rdoc/test_rdoc_rubygems_hook.rb +++ b/ruby/test/rdoc/test_rdoc_rubygems_hook.rb @@ -1,31 +1,62 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require "rubygems" +require "fileutils" +require "tmpdir" require 'rdoc/rubygems_hook' +require "test/unit" -class TestRDocRubygemsHook < Gem::TestCase - +class TestRDocRubygemsHook < Test::Unit::TestCase def setup - super - - @a = util_spec 'a', 2 do |s| + @a = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = "a" + s.version = 2 s.rdoc_options = %w[--main MyTitle] s.extra_rdoc_files = %w[README] end - - write_file File.join(@tempdir, 'lib', 'a.rb') - write_file File.join(@tempdir, 'README') - - install_gem @a + @tempdir = File.realpath(Dir.mktmpdir("test_rubygems_hook_")) + + @orig_envs = %w[ + GEM_VENDOR + GEMRC + XDG_CACHE_HOME + XDG_CONFIG_HOME + XDG_DATA_HOME + SOURCE_DATE_EPOCH + BUNDLER_VERSION + HOME + RDOCOPT + ].map {|e| [e, ENV.delete(e)]}.to_h + ENV["HOME"] = @tempdir + + Gem.configuration = nil + + @a.instance_variable_set(:@doc_dir, File.join(@tempdir, "doc")) + @a.instance_variable_set(:@gem_dir, File.join(@tempdir, "a-2")) + @a.instance_variable_set(:@full_gem_path, File.join(@tempdir, "a-2")) + @a.loaded_from = File.join(@tempdir, 'a-2', 'a-2.gemspec') + + FileUtils.mkdir_p File.join(@tempdir, 'a-2', 'lib') + FileUtils.touch File.join(@tempdir, 'a-2', 'lib', 'a.rb') + FileUtils.touch File.join(@tempdir, 'a-2', 'README') @hook = RDoc::RubygemsHook.new @a begin RDoc::RubygemsHook.load_rdoc rescue Gem::DocumentError => e - skip e.message + omit e.message end + @old_ui = Gem::DefaultUserInteraction.ui + Gem::DefaultUserInteraction.ui = Gem::SilentUI.new + end - Gem.configuration[:rdoc] = nil + def teardown + ui = Gem::DefaultUserInteraction.ui + Gem::DefaultUserInteraction.ui = @old_ui + FileUtils.rm_rf @tempdir + ui.close + ENV.update(@orig_envs) end def test_initialize @@ -165,8 +196,8 @@ def test_generate_force @hook.generate - refute_path_exists File.join(@a.doc_dir('rdoc'), 'index.html') - assert_path_exists File.join(@a.doc_dir('ri'), 'cache.ri') + assert_path_not_exist File.join(@a.doc_dir('rdoc'), 'index.html') + assert_path_exist File.join(@a.doc_dir('ri'), 'cache.ri') end def test_generate_no_overwrite @@ -176,8 +207,8 @@ def test_generate_no_overwrite @hook.generate - refute_path_exists File.join(@a.doc_dir('rdoc'), 'index.html') - refute_path_exists File.join(@a.doc_dir('ri'), 'cache.ri') + assert_path_not_exist File.join(@a.doc_dir('rdoc'), 'index.html') + assert_path_not_exist File.join(@a.doc_dir('ri'), 'cache.ri') end def test_new_rdoc @@ -201,17 +232,17 @@ def test_remove refute @hook.rdoc_installed? refute @hook.ri_installed? - assert_path_exists @a.doc_dir + assert_path_exist @a.doc_dir end def test_remove_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip "assumes that euid is not root" if Process.euid == 0 + omit 'chmod not supported' if Gem.win_platform? + omit "assumes that euid is not root" if Process.euid == 0 FileUtils.mkdir_p @a.base_dir FileUtils.chmod 0, @a.base_dir - e = assert_raises Gem::FilePermissionError do + e = assert_raise Gem::FilePermissionError do @hook.remove end @@ -231,17 +262,17 @@ def test_ri_installed? def test_setup @hook.setup - assert_path_exists @a.doc_dir + assert_path_exist @a.doc_dir end def test_setup_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip "assumes that euid is not root" if Process.euid == 0 + omit 'chmod not supported' if Gem.win_platform? + omit "assumes that euid is not root" if Process.euid == 0 FileUtils.mkdir_p @a.doc_dir FileUtils.chmod 0, @a.doc_dir - e = assert_raises Gem::FilePermissionError do + e = assert_raise Gem::FilePermissionError do @hook.setup end diff --git a/ruby/test/rdoc/test_rdoc_servlet.rb b/ruby/test/rdoc/test_rdoc_servlet.rb index 112740819..7a5b15a6e 100644 --- a/ruby/test/rdoc/test_rdoc_servlet.rb +++ b/ruby/test/rdoc/test_rdoc_servlet.rb @@ -1,5 +1,9 @@ # frozen_string_literal: true require_relative 'helper' +begin + require 'webrick' +rescue LoadError +end class TestRDocServlet < RDoc::TestCase @@ -45,7 +49,8 @@ def @req.path= path @orig_base = RDoc::RI::Paths::BASE RDoc::RI::Paths::BASE.replace @base @orig_ri_path_homedir = RDoc::RI::Paths::HOMEDIR - RDoc::RI::Paths::HOMEDIR.replace @home_dir + RDoc::RI::Paths.send :remove_const, :HOMEDIR + RDoc::RI::Paths.const_set :HOMEDIR, @home_dir RDoc::RI::Paths.instance_variable_set \ :@gemdirs, %w[/nonexistent/gems/example-1.0/ri] @@ -60,7 +65,8 @@ def teardown FileUtils.rm_rf @tempdir RDoc::RI::Paths::BASE.replace @orig_base - RDoc::RI::Paths::HOMEDIR.replace @orig_ri_path_homedir + RDoc::RI::Paths.send :remove_const, :HOMEDIR + RDoc::RI::Paths.const_set :HOMEDIR, @orig_ri_path_homedir RDoc::RI::Paths.instance_variable_set :@gemdirs, nil end @@ -546,4 +552,4 @@ def touch_extra_cache_path store.save end -end +end if defined?(WEBrick) diff --git a/ruby/test/rdoc/test_rdoc_store.rb b/ruby/test/rdoc/test_rdoc_store.rb index 8332d9233..0abad4232 100644 --- a/ruby/test/rdoc/test_rdoc_store.rb +++ b/ruby/test/rdoc/test_rdoc_store.rb @@ -161,9 +161,10 @@ def test_add_file_relative def test_all_classes_and_modules expected = %w[ - C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B + C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B Child M1 M1::M2 + Object Parent ] @@ -212,8 +213,9 @@ def test_class_path def test_classes expected = %w[ - C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B + C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B Child + Object Parent ] @@ -317,6 +319,9 @@ def test_find_text_page end def test_friendly_path + @orig_xdg_data_home = ENV['XDG_DATA_HOME'] + ENV.delete('XDG_DATA_HOME') + @s.path = @tmpdir @s.type = nil assert_equal @s.path, @s.friendly_path @@ -331,11 +336,13 @@ def test_friendly_path assert_equal "ruby site", @s.friendly_path @s.type = :home - assert_equal "~/.rdoc", @s.friendly_path + assert_equal File.expand_path("~/.local/share/rdoc"), @s.friendly_path @s.type = :gem @s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri" assert_equal "gem gem_name-1.0", @s.friendly_path + ensure + ENV['XDG_DATA_HOME'] = @orig_xdg_data_home end def test_dry_run @@ -606,6 +613,14 @@ def test_page assert_equal page, @store.page('PAGE') end + def test_page_with_extension + page = @store.add_file 'PAGE.txt', parser: RDoc::Parser::Simple + + assert_nil @store.page 'no such page' + + assert_equal page, @store.page('PAGE.txt') + end + def test_save FileUtils.mkdir_p @tmpdir diff --git a/ruby/test/rdoc/test_rdoc_task.rb b/ruby/test/rdoc/test_rdoc_task.rb index d9fc6664f..77f2af33a 100644 --- a/ruby/test/rdoc/test_rdoc_task.rb +++ b/ruby/test/rdoc/test_rdoc_task.rb @@ -69,8 +69,8 @@ def test_tasks_option_parser rd.options << "--all" end - assert rdoc_task.title, "Test Tasks Option Parser" - assert rdoc_task.main, "README.md" + assert_equal "Test Tasks Option Parser", rdoc_task.title + assert_equal "README.md", rdoc_task.main assert rdoc_task.rdoc_files.include?("README.md") assert rdoc_task.options.include?("--all") diff --git a/ruby/test/rdoc/test_rdoc_text.rb b/ruby/test/rdoc/test_rdoc_text.rb index 59d63b29b..a6b1597bb 100644 --- a/ruby/test/rdoc/test_rdoc_text.rb +++ b/ruby/test/rdoc/test_rdoc_text.rb @@ -485,6 +485,13 @@ def test_to_html_apostrophe assert_equal '‘a’ ‘', to_html("'a' '") end + def test_to_html_apostrophe_entity + assert_equal '‘a', to_html("'a") + assert_equal 'a’', to_html("a'") + + assert_equal '‘a’ ‘', to_html("'a' '") + end + def test_to_html_backslash assert_equal 'S', to_html('\\S') end @@ -495,6 +502,7 @@ def test_to_html_br def test_to_html_copyright assert_equal '©', to_html('(c)') + assert_equal '©', to_html('(C)') end def test_to_html_dash @@ -507,6 +515,7 @@ def test_to_html_dash def test_to_html_double_backtick assert_equal '“a', to_html('``a') assert_equal '“a“', to_html('``a``') + assert_equal '“aâ€', to_html("``a''") end def test_to_html_double_quote @@ -549,6 +558,7 @@ def test_to_html_html_tag def test_to_html_registered_trademark assert_equal '®', to_html('(r)') + assert_equal '®', to_html('(R)') end def test_to_html_tt_tag diff --git a/ruby/test/rdoc/test_rdoc_top_level.rb b/ruby/test/rdoc/test_rdoc_top_level.rb index e396791ab..3f6d153b6 100644 --- a/ruby/test/rdoc/test_rdoc_top_level.rb +++ b/ruby/test/rdoc/test_rdoc_top_level.rb @@ -90,7 +90,7 @@ def test_add_method @top_level.add_method method object = @store.find_class_named 'Object' - assert_equal [method], object.method_list + assert_equal [@c10_method, @c11_method, method], object.method_list assert_includes object.in_files, @top_level end @@ -101,7 +101,7 @@ def test_add_method_stopdoc @top_level.add_method method object = @store.find_class_named('Object') - assert_empty object.method_list + assert_equal [@c10_method, @c11_method], object.method_list assert_includes object.in_files, @top_level end @@ -157,6 +157,9 @@ def test_hash def test_http_url assert_equal 'prefix/path/top_level_rb.html', @top_level.http_url('prefix') + + other_level = @store.add_file 'path.other/level.rb' + assert_equal 'prefix/path_other/level_rb.html', other_level.http_url('prefix') end def test_last_modified diff --git a/ruby/test/rdoc/xref_data.rb b/ruby/test/rdoc/xref_data.rb index aa9faaecd..de76a9060 100644 --- a/ruby/test/rdoc/xref_data.rb +++ b/ruby/test/rdoc/xref_data.rb @@ -115,6 +115,23 @@ def bar() end end end +class C10 + class C11 + end + + def C11 + end +end + +def C10 +end + +class C11 +end + +def C11 +end + module M1 def m end diff --git a/ruby/test/rdoc/xref_test_case.rb b/ruby/test/rdoc/xref_test_case.rb index 729e4a70b..22b00d04b 100644 --- a/ruby/test/rdoc/xref_test_case.rb +++ b/ruby/test/rdoc/xref_test_case.rb @@ -70,6 +70,14 @@ def generator.file_dir() nil end @c9_b_c_foo = @c9_b.method_list.first @c9_b_i_bar = @c9_b.method_list.last + @object = @xref_data.find_module_named 'Object' + @c10_class = @xref_data.find_module_named 'C10' + @c10_method = @object.find_method_named 'C10' + @c11_class = @xref_data.find_module_named 'C11' + @c10_c11_class = @c10_class.find_module_named 'C11' + @c10_c11_method = @c10_class.find_method_named 'C11' + @c11_method = @object.find_method_named 'C11' + @m1 = @xref_data.find_module_named 'M1' @m1_m = @m1.method_list.first diff --git a/ruby/test/readline/helper.rb b/ruby/test/readline/helper.rb index 1b80327b5..2d28d18a7 100644 --- a/ruby/test/readline/helper.rb +++ b/ruby/test/readline/helper.rb @@ -12,6 +12,7 @@ def use_ext_readline # Use ext/readline as Readline begin require "reline" rescue LoadError + Object.class_eval {remove_const :Reline} if defined?(Reline) else def use_lib_reline # Use lib/reline as Readline Reline.send(:remove_const, 'IOGate') if Reline.const_defined?('IOGate') @@ -21,4 +22,8 @@ def use_lib_reline # Use lib/reline as Readline Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline) Object.const_set(:Readline, Reline) end + + def finish_using_lib_reline + Reline.instance_variable_set(:@core, nil) + end end diff --git a/ruby/test/readline/test_readline.rb b/ruby/test/readline/test_readline.rb index 7ac221271..be338c6c0 100644 --- a/ruby/test/readline/test_readline.rb +++ b/ruby/test/readline/test_readline.rb @@ -3,18 +3,24 @@ require "test/unit" require "tempfile" require "timeout" +require "open3" module BasetestReadline INPUTRC = "INPUTRC" + TERM = "TERM" SAVED_ENV = %w[COLUMNS LINES] + TIMEOUT = 8 + def setup @saved_env = ENV.values_at(*SAVED_ENV) @inputrc, ENV[INPUTRC] = ENV[INPUTRC], IO::NULL + @term, ENV[TERM] = ENV[TERM], "vt100" end def teardown ENV[INPUTRC] = @inputrc + ENV[TERM] = @term Readline.instance_variable_set("@completion_proc", nil) begin Readline.delete_text @@ -150,10 +156,13 @@ def test_completion_proc def test_completion_case_fold expected = [true, false, "string", {"a" => "b"}] + completion_case_fold = Readline.completion_case_fold expected.each do |e| Readline.completion_case_fold = e assert_equal(e, Readline.completion_case_fold) end + ensure + Readline.completion_case_fold = completion_case_fold end def test_completion_proc_empty_result @@ -173,7 +182,7 @@ def test_completion_proc_empty_result assert_equal("", line2) begin assert_equal("", Readline.line_buffer) - rescue NotimplementedError + rescue NotImplementedError end end end @@ -446,7 +455,7 @@ def test_input_metachar_multibyte w << "\cr\u3042\u3093" w.reopen(IO::NULL) assert_equal("\u3046\u3093", Readline.readline("", true), bug6602) - Timeout.timeout(2) do + Timeout.timeout(TIMEOUT) do assert_equal("\u3042\u3093", Readline.readline("", true), bug6602) end assert_equal(nil, Readline.readline("", true), bug6602) @@ -472,6 +481,115 @@ def test_refresh_line end end + # TODO Green CI for arm32-linux (Travis CI), and Readline 7.0. + def test_interrupt_in_other_thread + # Editline and Readline 7.0 can't treat I/O that is not tty. + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + omit "Skip Readline 7.0" if Readline::VERSION == "7.0" + omit unless respond_to?(:assert_ruby_status) + omit if /mswin|mingw/ =~ RUBY_PLATFORM + + # On 32-bit machine, readline library (or libtinfo) seems to cause SEGV internally even with Readline 8.0 + # GDB Backtrace: https://gist.github.com/mame/d12b9de3bbc3f16d440c1927398d176a + # Maybe the same issue: https://github.com/facebookresearch/nle/issues/120 + omit if /i[3-6]86-linux/ =~ RUBY_PLATFORM + + if defined?(TestReadline) && self.class == TestReadline + use = "use_ext_readline" + elsif defined?(TestRelineAsReadline) && self.class == TestRelineAsReadline + use = "use_lib_reline" + end + code = <<-"end;" + $stdout.sync = true + require 'readline' + require 'helper' + #{use} + puts "Readline::VERSION is \#{Readline::VERSION}." + Readline.input = STDIN + # 0. Send SIGINT to this script. + begin + Thread.new{ + trap(:INT) { + puts 'TRAP' # 2. Show 'TRAP' message. + } + Readline.readline('input> ') # 1. Should keep working and call old trap. + # 4. Receive "\\n" and return because still working. + }.value + rescue Interrupt + puts 'FAILED' # 3. "Interrupt" shouldn't be raised because trapped. + raise + end + puts 'SUCCEEDED' # 5. Finish correctly. + end; + + script = Tempfile.new("interrupt_in_other_thread") + script.write code + script.close + + log = String.new + + EnvUtil.invoke_ruby(["-I#{__dir__}", script.path], "", true, :merge_to_stdout) do |_in, _out, _, pid| + Timeout.timeout(TIMEOUT) do + log << "** START **" + loop do + c = _out.read(1) + log << c if c + break if log.include?('input> ') + end + log << "** SIGINT **" + sleep 0.5 + Process.kill(:INT, pid) + sleep 0.5 + loop do + c = _out.read(1) + log << c if c + break if log.include?('TRAP') + end + begin + log << "** NEWLINE **" + _in.write "\n" + rescue Errno::EPIPE + log << "** Errno::EPIPE **" + # The "write" will fail if Reline crashed by SIGINT. + end + interrupt_suppressed = nil + loop do + c = _out.read(1) + log << c if c + if log.include?('FAILED') + interrupt_suppressed = false + break + end + if log.include?('SUCCEEDED') + interrupt_suppressed = true + break + end + end + assert interrupt_suppressed, "Should handle SIGINT correctly but raised interrupt.\nLog: #{log}\n----" + end + rescue Timeout::Error => e + Process.kill(:KILL, pid) + log << "\nKilled by timeout" + assert false, "Timed out to handle SIGINT!\nLog: #{log}\nBacktrace:\n#{e.full_message(highlight: false)}\n----" + ensure + status = nil + begin + Timeout.timeout(TIMEOUT) do + status = Process.wait2(pid).last + end + rescue Timeout::Error => e + log << "\nKilled by timeout to wait2" + Process.kill(:KILL, pid) + assert false, "Timed out to wait for terminating a process in a test of SIGINT!\nLog: #{log}\nBacktrace:\n#{e.full_message(highlight: false)}\n----" + end + assert status&.success?, "Unknown failure with exit status #{status.inspect}\nLog: #{log}\n----" + end + + assert log.include?('INT'), "Interrupt was handled correctly." + ensure + script&.close! + end + def test_setting_quoting_detection_proc return unless Readline.respond_to?(:quoting_detection_proc=) @@ -489,8 +607,8 @@ def test_using_quoting_detection_proc saved_completer_word_break_characters = Readline.completer_word_break_characters # skip if previous value is nil because Readline... = nil is not allowed. - skip unless saved_completer_quote_characters - skip unless saved_completer_word_break_characters + omit "No completer_quote_characters" unless saved_completer_quote_characters + omit "No completer_word_break_characters" unless saved_completer_word_break_characters return unless Readline.respond_to?(:quoting_detection_proc=) @@ -532,8 +650,8 @@ def test_using_quoting_detection_proc_with_multibyte_input saved_completer_word_break_characters = Readline.completer_word_break_characters # skip if previous value is nil because Readline... = nil is not allowed. - skip unless saved_completer_quote_characters - skip unless saved_completer_word_break_characters + omit "No completer_quote_characters" unless saved_completer_quote_characters + omit "No completer_word_break_characters" unless saved_completer_word_break_characters return unless Readline.respond_to?(:quoting_detection_proc=) unless get_default_internal_encoding == Encoding::UTF_8 @@ -593,7 +711,14 @@ def test_simple_completion end w.write("a\t\n") w.flush - line = Readline.readline('> ', false) + begin + stderr = $stderr.dup + $stderr.reopen(null) + line = Readline.readline('> ', false) + ensure + $stderr.reopen(stderr) + stderr.close + end end end @@ -632,6 +757,8 @@ def test_completion_with_completion_append_character def test_completion_quote_character_completing_unquoted_argument return unless Readline.respond_to?(:completion_quote_character) + saved_completer_quote_characters = Readline.completer_quote_characters + quote_character = "original value" Readline.completion_proc = -> (_) do quote_character = Readline.completion_quote_character @@ -648,11 +775,15 @@ def test_completion_quote_character_completing_unquoted_argument end assert_nil(quote_character) + ensure + Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters end def test_completion_quote_character_completing_quoted_argument return unless Readline.respond_to?(:completion_quote_character) + saved_completer_quote_characters = Readline.completer_quote_characters + quote_character = "original value" Readline.completion_proc = -> (_) do quote_character = Readline.completion_quote_character @@ -669,6 +800,8 @@ def test_completion_quote_character_completing_quoted_argument end assert_equal("'", quote_character) + ensure + Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters end def test_completion_quote_character_after_completion @@ -679,6 +812,8 @@ def test_completion_quote_character_after_completion end omit 'Needs GNU Readline 6 or later' if /mswin|mingw/ =~ RUBY_PLATFORM and defined?(TestReadline) and kind_of?(TestReadline) and Readline::VERSION < '6.0' + saved_completer_quote_characters = Readline.completer_quote_characters + Readline.completion_proc = -> (_) { [] } Readline.completer_quote_characters = "'\"" @@ -691,6 +826,22 @@ def test_completion_quote_character_after_completion end assert_nil(Readline.completion_quote_character) + ensure + Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters + end + + def test_without_tty + omit "Skip Editline" if /EditLine/n.match(Readline::VERSION) + loader = nil + if defined?(TestReadline) && self.class == TestReadline + loader = "use_ext_readline" + elsif defined?(TestRelineAsReadline) && self.class == TestRelineAsReadline + loader = "use_lib_reline" + end + if loader + res, exit_status = Open3.capture2e("ruby -I#{__dir__} -Ilib -rhelper -e '#{loader}; Readline.readline(%{y or n?})'", stdin_data: "y\n") + assert exit_status.success?, "It should work fine without tty, but it failed.\nError output:\n#{res}" + end end private @@ -784,11 +935,16 @@ def setup super end + def teardown + finish_using_lib_reline + super + end + def get_default_internal_encoding if RUBY_PLATFORM =~ /mswin|mingw/ Encoding.default_internal || Encoding::UTF_8 else - super + Reline::IOGate.encoding end end end if defined?(Reline) && ENV["TEST_READLINE_OR_RELINE"] != "Readline" diff --git a/ruby/test/readline/test_readline_history.rb b/ruby/test/readline/test_readline_history.rb index f4e93fa1b..39ad4fe85 100644 --- a/ruby/test/readline/test_readline_history.rb +++ b/ruby/test/readline/test_readline_history.rb @@ -277,11 +277,16 @@ def setup super end + def teardown + finish_using_lib_reline + super + end + def get_default_internal_encoding if RUBY_PLATFORM =~ /mswin|mingw/ Encoding.default_internal || Encoding::UTF_8 else - super + Reline::IOGate.encoding end end end if defined?(Reline) && ENV["TEST_READLINE_OR_RELINE"] != "Readline" diff --git a/ruby/test/reline/helper.rb b/ruby/test/reline/helper.rb index 0b5b8af31..e8b8e3a6e 100644 --- a/ruby/test/reline/helper.rb +++ b/ruby/test/reline/helper.rb @@ -1,4 +1,7 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) + +ENV['TERM'] = 'xterm' # for some CI environments + require 'reline' require 'test/unit' @@ -7,6 +10,12 @@ class < expected but was\n<#{@line_editor.line.byteslice(0, byte_pointer).inspect}>") + <<~EOM) + <#{expected.inspect} (#{expected.encoding.inspect})> expected but was + <#{chunk.inspect} (#{chunk.encoding.inspect})> in + EOM end def assert_cursor(expected) @@ -87,4 +108,18 @@ def assert_cursor(expected) def assert_cursor_max(expected) assert_equal(expected, @line_editor.instance_variable_get(:@cursor_max)) end + + def assert_line_index(expected) + assert_equal(expected, @line_editor.instance_variable_get(:@line_index)) + end + + def assert_whole_lines(expected) + previous_line_index = @line_editor.instance_variable_get(:@previous_line_index) + if previous_line_index + lines = @line_editor.whole_lines(index: previous_line_index) + else + lines = @line_editor.whole_lines + end + assert_equal(expected, lines) + end end diff --git a/ruby/test/reline/test_config.rb b/ruby/test/reline/test_config.rb index cecb364f8..e00a47c70 100644 --- a/ruby/test/reline/test_config.rb +++ b/ruby/test/reline/test_config.rb @@ -11,12 +11,14 @@ def setup Dir.mkdir(@tmpdir) end Dir.chdir(@tmpdir) + Reline.test_mode @config = Reline::Config.new end def teardown Dir.chdir(@pwd) FileUtils.rm_rf(@tmpdir) + Reline.test_reset @config.reset end @@ -36,6 +38,67 @@ def test_read_lines_with_variable assert_equal true, @config.instance_variable_get(:@disable_completion) end + def test_string_value + @config.read_lines(<<~LINES.lines) + set show-mode-in-prompt on + set emacs-mode-string Emacs + LINES + + assert_equal 'Emacs', @config.instance_variable_get(:@emacs_mode_string) + end + + def test_string_value_with_brackets + @config.read_lines(<<~LINES.lines) + set show-mode-in-prompt on + set emacs-mode-string [Emacs] + LINES + + assert_equal '[Emacs]', @config.instance_variable_get(:@emacs_mode_string) + end + + def test_string_value_with_brackets_and_quotes + @config.read_lines(<<~LINES.lines) + set show-mode-in-prompt on + set emacs-mode-string "[Emacs]" + LINES + + assert_equal '[Emacs]', @config.instance_variable_get(:@emacs_mode_string) + end + + def test_string_value_with_parens + @config.read_lines(<<~LINES.lines) + set show-mode-in-prompt on + set emacs-mode-string (Emacs) + LINES + + assert_equal '(Emacs)', @config.instance_variable_get(:@emacs_mode_string) + end + + def test_string_value_with_parens_and_quotes + @config.read_lines(<<~LINES.lines) + set show-mode-in-prompt on + set emacs-mode-string "(Emacs)" + LINES + + assert_equal '(Emacs)', @config.instance_variable_get(:@emacs_mode_string) + end + + def test_encoding_is_ascii + @config.reset + Reline::IOGate.reset(encoding: Encoding::US_ASCII) + @config = Reline::Config.new + + assert_equal true, @config.convert_meta + end + + def test_encoding_is_not_ascii + @config.reset + Reline::IOGate.reset(encoding: Encoding::UTF_8) + @config = Reline::Config.new + + assert_equal nil, @config.convert_meta + end + def test_comment_line @config.read_lines([" #a: error\n"]) assert_not_include @config.key_bindings, nil @@ -196,6 +259,21 @@ def test_additional_key_bindings_with_nesting_and_comment_out assert_equal expected, @config.key_bindings end + def test_additional_key_bindings_for_other_keymap + @config.read_lines(<<~'LINES'.lines) + set keymap vi-command + "ab": "AB" + set keymap vi-insert + "cd": "CD" + set keymap emacs + "ef": "EF" + set editing-mode vi # keymap changes to be vi-insert + LINES + + expected = { 'cd'.bytes => 'CD'.bytes } + assert_equal expected, @config.key_bindings + end + def test_history_size @config.read_lines(<<~LINES.lines) set history-size 5000 @@ -213,6 +291,99 @@ def test_empty_inputrc_env assert_nothing_raised do @config.read end + ensure + ENV['INPUTRC'] = inputrc_backup + end + + def test_inputrc + inputrc_backup = ENV['INPUTRC'] + expected = "#{@tmpdir}/abcde" + ENV['INPUTRC'] = expected + assert_equal expected, @config.inputrc_path + ensure ENV['INPUTRC'] = inputrc_backup end + + def test_inputrc_with_utf8 + # This file is encoded by UTF-8 so this heredoc string is also UTF-8. + @config.read_lines(<<~'LINES'.lines) + set editing-mode vi + set vi-cmd-mode-string 🸠+ set vi-ins-mode-string 🶠+ LINES + assert_equal 'ðŸ¸', @config.vi_cmd_mode_string + assert_equal 'ðŸ¶', @config.vi_ins_mode_string + rescue Reline::ConfigEncodingConversionError + # do nothing + end + + def test_inputrc_with_eucjp + @config.read_lines(<<~"LINES".encode(Encoding::EUC_JP).lines) + set editing-mode vi + set vi-cmd-mode-string ォャッ + set vi-ins-mode-string 能 + LINES + assert_equal 'ォャッ'.encode(Reline.encoding_system_needs), @config.vi_cmd_mode_string + assert_equal '能'.encode(Reline.encoding_system_needs), @config.vi_ins_mode_string + rescue Reline::ConfigEncodingConversionError + # do nothing + end + + def test_empty_inputrc + assert_nothing_raised do + @config.read_lines([]) + end + end + + def test_xdg_config_home + home_backup = ENV['HOME'] + xdg_config_home_backup = ENV['XDG_CONFIG_HOME'] + xdg_config_home = File.expand_path("#{@tmpdir}/.config/example_dir") + expected = File.expand_path("#{xdg_config_home}/readline/inputrc") + FileUtils.mkdir_p(File.dirname(expected)) + FileUtils.touch(expected) + ENV['HOME'] = @tmpdir + ENV['XDG_CONFIG_HOME'] = xdg_config_home + assert_equal expected, @config.inputrc_path + ensure + FileUtils.rm(expected) + ENV['XDG_CONFIG_HOME'] = xdg_config_home_backup + ENV['HOME'] = home_backup + end + + def test_empty_xdg_config_home + home_backup = ENV['HOME'] + xdg_config_home_backup = ENV['XDG_CONFIG_HOME'] + ENV['HOME'] = @tmpdir + ENV['XDG_CONFIG_HOME'] = '' + expected = File.expand_path('~/.config/readline/inputrc') + FileUtils.mkdir_p(File.dirname(expected)) + FileUtils.touch(expected) + assert_equal expected, @config.inputrc_path + ensure + FileUtils.rm(expected) + ENV['XDG_CONFIG_HOME'] = xdg_config_home_backup + ENV['HOME'] = home_backup + end + + def test_relative_xdg_config_home + home_backup = ENV['HOME'] + xdg_config_home_backup = ENV['XDG_CONFIG_HOME'] + ENV['HOME'] = @tmpdir + expected = File.expand_path('~/.config/readline/inputrc') + FileUtils.mkdir_p(File.dirname(expected)) + FileUtils.touch(expected) + result = Dir.chdir(@tmpdir) do + xdg_config_home = ".config/example_dir" + ENV['XDG_CONFIG_HOME'] = xdg_config_home + inputrc = "#{xdg_config_home}/readline/inputrc" + FileUtils.mkdir_p(File.dirname(inputrc)) + FileUtils.touch(inputrc) + @config.inputrc_path + end + assert_equal expected, result + FileUtils.rm(expected) + ENV['XDG_CONFIG_HOME'] = xdg_config_home_backup + ENV['HOME'] = home_backup + end end diff --git a/ruby/test/reline/test_history.rb b/ruby/test/reline/test_history.rb index 189f2db86..53360409b 100644 --- a/ruby/test/reline/test_history.rb +++ b/ruby/test/reline/test_history.rb @@ -6,6 +6,10 @@ def setup Reline.send(:test_mode) end + def teardown + Reline.test_reset + end + def test_ancestors assert_equal(Reline::History.ancestors.include?(Array), true) end @@ -242,6 +246,26 @@ def test_delete_at__out_of_range end end + def test_history_size_zero + history = history_new(history_size: 0) + assert_equal 0, history.size + history << 'aa' + history << 'bb' + assert_equal 0, history.size + history.push(*%w{aa bb cc}) + assert_equal 0, history.size + end + + def test_history_size_negative_unlimited + history = history_new(history_size: -1) + assert_equal 0, history.size + history << 'aa' + history << 'bb' + assert_equal 2, history.size + history.push(*%w{aa bb cc}) + assert_equal 5, history.size + end + private def history_new(history_size: 10) @@ -268,11 +292,14 @@ def history_new_and_push_history(num) def assert_external_string_equal(expected, actual) assert_equal(expected, actual) - assert_equal(get_default_internal_encoding, actual.encoding) + mes = "Encoding of #{actual.inspect} is expected #{get_default_internal_encoding.inspect} but #{actual.encoding}" + assert_equal(get_default_internal_encoding, actual.encoding, mes) end def get_default_internal_encoding - if RUBY_PLATFORM =~ /mswin|mingw/ + if encoding = Reline::IOGate.encoding + encoding + elsif RUBY_PLATFORM =~ /mswin|mingw/ Encoding.default_internal || Encoding::UTF_8 else Encoding.default_internal || Encoding.find("locale") diff --git a/ruby/test/reline/test_key_actor_emacs.rb b/ruby/test/reline/test_key_actor_emacs.rb index c16212c62..a5fdf247c 100644 --- a/ruby/test/reline/test_key_actor_emacs.rb +++ b/ruby/test/reline/test_key_actor_emacs.rb @@ -5,13 +5,18 @@ def setup Reline.send(:test_mode) @prompt = '> ' @config = Reline::Config.new # Emacs mode is default + @config.autocompletion = false Reline::HISTORY.instance_variable_set(:@config, @config) Reline::HISTORY.clear - @encoding = (RELINE_TEST_ENCODING rescue Encoding.default_external) + @encoding = Reline::IOGate.encoding @line_editor = Reline::LineEditor.new(@config, @encoding) @line_editor.reset(@prompt, encoding: @encoding) end + def teardown + Reline.test_reset + end + def test_ed_insert_one input_keys('a') assert_line('a') @@ -250,31 +255,31 @@ def test_ed_kill_line end def test_em_kill_line - input_keys("\C-u", false) + @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false)) assert_byte_pointer_size('') assert_cursor(0) assert_cursor_max(0) assert_line('') input_keys('abc') - assert_byte_pointer_size('abc') - assert_cursor(3) - assert_cursor_max(3) - input_keys("\C-u", false) + @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false)) assert_byte_pointer_size('') assert_cursor(0) assert_cursor_max(0) assert_line('') input_keys('abc') - input_keys("\C-b\C-u", false) + input_keys("\C-b", false) + @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false)) assert_byte_pointer_size('') assert_cursor(0) - assert_cursor_max(1) - assert_line('c') - input_keys("\C-u", false) + assert_cursor_max(0) + assert_line('') + input_keys('abc') + input_keys("\C-a", false) + @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false)) assert_byte_pointer_size('') assert_cursor(0) - assert_cursor_max(1) - assert_line('c') + assert_cursor_max(0) + assert_line('') end def test_ed_move_to_beg @@ -1281,6 +1286,36 @@ def test_em_delete_or_list assert_equal(%w{foo_foo foo_bar foo_baz}, @line_editor.instance_variable_get(:@menu_info).list) end + def test_completion_duplicated_list + @line_editor.completion_proc = proc { |word| + %w{ + foo_foo + foo_foo + foo_bar + }.map { |i| + i.encode(@encoding) + } + } + input_keys('foo_') + assert_byte_pointer_size('foo_') + assert_cursor(4) + assert_cursor_max(4) + assert_line('foo_') + assert_equal(nil, @line_editor.instance_variable_get(:@menu_info)) + input_keys("\C-i", false) + assert_byte_pointer_size('foo_') + assert_cursor(4) + assert_cursor_max(4) + assert_line('foo_') + assert_equal(nil, @line_editor.instance_variable_get(:@menu_info)) + input_keys("\C-i", false) + assert_byte_pointer_size('foo_') + assert_cursor(4) + assert_cursor_max(4) + assert_line('foo_') + assert_equal(%w{foo_foo foo_bar}, @line_editor.instance_variable_get(:@menu_info).list) + end + def test_completion @line_editor.completion_proc = proc { |word| %w{ @@ -1625,7 +1660,7 @@ def test_em_kill_region_mbchar assert_line('') end - def test_ed_search_prev_history + def test_vi_search_prev Reline::HISTORY.concat(%w{abc 123 AAA}) assert_line('') assert_byte_pointer_size('') @@ -1864,6 +1899,36 @@ def test_search_history_by_last_determined assert_cursor_max(0) end + def test_search_history_with_isearch_terminator + @config.read_lines(<<~LINES.split(/(?<=\n)/)) + set isearch-terminators "XYZ" + LINES + Reline::HISTORY.concat([ + '1235', # old + '12aa', + '1234' # new + ]) + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + input_keys("\C-r12a") + assert_line('12aa') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) # doesn't determine yet + input_keys('Y') + assert_line('12aa') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(4) + input_keys('x') + assert_line('x12aa') + assert_byte_pointer_size('x') + assert_cursor(1) + assert_cursor_max(5) + end + def test_em_set_mark_and_em_exchange_mark input_keys('aaa bbb ccc ddd') assert_byte_pointer_size('aaa bbb ccc ddd') @@ -1896,37 +1961,372 @@ def test_em_set_mark_and_em_exchange_mark assert_equal([0, 0], @line_editor.instance_variable_get(:@mark_pointer)) end + def test_em_exchange_mark_without_mark + input_keys('aaa bbb ccc ddd') + assert_byte_pointer_size('aaa bbb ccc ddd') + assert_cursor(15) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + input_keys("\C-a\M-f", false) + assert_byte_pointer_size('aaa') + assert_cursor(3) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer)) + input_key_by_symbol(:em_exchange_mark) + assert_byte_pointer_size('aaa') + assert_cursor(3) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer)) + end + def test_modify_lines_with_wrong_rs + verbose, $VERBOSE = $VERBOSE, nil original_global_slash = $/ $/ = 'b' + $VERBOSE = verbose @line_editor.output_modifier_proc = proc { |output| Reline::Unicode.escape_for_print(output) } input_keys("abcdef\n") - assert_equal(['abcdef'], @line_editor.__send__(:modify_lines, @line_editor.whole_lines)) + result = @line_editor.__send__(:modify_lines, @line_editor.whole_lines) + $/ = nil + assert_equal(['abcdef'], result) + ensure + $VERBOSE = nil $/ = original_global_slash + $VERBOSE = verbose end -=begin # TODO: move KeyStroke instance from Reline to LineEditor - def test_key_delete - input_keys('ab') - assert_byte_pointer_size('ab') + def test_ed_search_prev_history + Reline::HISTORY.concat([ + '12356', # old + '12aaa', + '12345' # new + ]) + input_keys('123') + # The ed_search_prev_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12356') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12356') + end + + def test_ed_search_prev_history_with_empty + Reline::HISTORY.concat([ + '12356', # old + '12aaa', + '12345' # new + ]) + # The ed_search_prev_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12aaa') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12356') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12356') + end + + def test_ed_search_prev_history_without_match + Reline::HISTORY.concat([ + '12356', # old + '12aaa', + '12345' # new + ]) + input_keys('ABC') + # The ed_search_prev_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('ABC') + assert_cursor(3) + assert_cursor_max(3) + assert_line('ABC') + end + + def test_ed_search_next_history + Reline::HISTORY.concat([ + '12356', # old + '12aaa', + '12345' # new + ]) + input_keys('123') + # The ed_search_prev_history and ed_search_next_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12356') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12356') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_byte_pointer_size('123') + assert_cursor(3) + assert_cursor_max(5) + assert_line('12345') + end + + def test_ed_search_next_history_with_empty + Reline::HISTORY.concat([ + '12356', # old + '12aaa', + '12345' # new + ]) + # The ed_search_prev_history and ed_search_next_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12aaa') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12356') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12aaa') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(5) + assert_line('12345') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + end + + # Unicode emoji test + def test_ed_insert_for_include_zwj_emoji + omit "This test is for UTF-8 but the locale is #{Reline::IOGate.encoding}" if Reline::IOGate.encoding != Encoding::UTF_8 + # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦" + input_keys("\u{1F468}") # U+1F468 is man "👨" + assert_line("\u{1F468}") + assert_byte_pointer_size("\u{1F468}") assert_cursor(2) assert_cursor_max(2) - assert_line('ab') - [27, 91, 51, 126].each do |key| - @line_editor.input_key(key) - end - assert_byte_pointer_size('ab') + input_keys("\u200D") # U+200D is ZERO WIDTH JOINER + assert_line("\u{1F468 200D}") + assert_byte_pointer_size("\u{1F468 200D}") assert_cursor(2) assert_cursor_max(2) - assert_line('ab') - input_keys("\C-b") - [27, 91, 51, 126].each do |key| - @line_editor.input_key(key) - end - assert_byte_pointer_size('a') + input_keys("\u{1F469}") # U+1F469 is woman "👩" + assert_line("\u{1F468 200D 1F469}") + assert_byte_pointer_size("\u{1F468 200D 1F469}") + assert_cursor(2) + assert_cursor_max(2) + input_keys("\u200D") # U+200D is ZERO WIDTH JOINER + assert_line("\u{1F468 200D 1F469 200D}") + assert_byte_pointer_size("\u{1F468 200D 1F469 200D}") + assert_cursor(2) + assert_cursor_max(2) + input_keys("\u{1F467}") # U+1F467 is girl "👧" + assert_line("\u{1F468 200D 1F469 200D 1F467}") + assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467}") + assert_cursor(2) + assert_cursor_max(2) + input_keys("\u200D") # U+200D is ZERO WIDTH JOINER + assert_line("\u{1F468 200D 1F469 200D 1F467 200D}") + assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D}") + assert_cursor(2) + assert_cursor_max(2) + input_keys("\u{1F466}") # U+1F466 is boy "👦" + assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466}") + assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466}") + assert_cursor(2) + assert_cursor_max(2) + # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦" + input_keys("\u{1F468 200D 1F469 200D 1F467 200D 1F466}") + assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}") + assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}") + assert_cursor(4) + assert_cursor_max(4) + end + + def test_ed_insert_for_include_valiation_selector + omit "This test is for UTF-8 but the locale is #{Reline::IOGate.encoding}" if Reline::IOGate.encoding != Encoding::UTF_8 + # U+0030 U+FE00 is DIGIT ZERO + VARIATION SELECTOR-1 "0︀" + input_keys("\u0030") # U+0030 is DIGIT ZERO + assert_line("\u0030") + assert_byte_pointer_size("\u0030") + assert_cursor(1) + assert_cursor_max(1) + input_keys("\uFE00") # U+FE00 is VARIATION SELECTOR-1 + assert_line("\u{0030 FE00}") + assert_byte_pointer_size("\u{0030 FE00}") + assert_cursor(1) + assert_cursor_max(1) + end + + def test_em_yank_pop + input_keys("def hoge\C-w\C-b\C-f\C-w", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + input_keys("\C-y", false) + assert_byte_pointer_size('def ') + assert_cursor(4) + assert_cursor_max(4) + assert_line('def ') + input_keys("\M-\C-y", false) + assert_byte_pointer_size('hoge') + assert_cursor(4) + assert_cursor_max(4) + assert_line('hoge') + end + + def test_em_kill_region_with_kill_ring + input_keys("def hoge\C-b\C-b\C-b\C-b", false) + assert_byte_pointer_size('def ') + assert_cursor(4) + assert_cursor_max(8) + assert_line('def hoge') + input_keys("\C-k\C-w", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + input_keys("\C-y", false) + assert_byte_pointer_size('def hoge') + assert_cursor(8) + assert_cursor_max(8) + assert_line('def hoge') + end + + def test_ed_search_prev_next_history_in_multibyte + Reline::HISTORY.concat([ + "def hoge\n 67890\n 12345\nend", # old + "def aiu\n 0xDEADBEEF\nend", + "def foo\n 12345\nend" # new + ]) + @line_editor.multiline_on + input_keys(' 123') + # The ed_search_prev_history doesn't have default binding + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_whole_lines(['def foo', ' 12345', 'end']) + assert_line_index(1) + assert_whole_lines(['def foo', ' 12345', 'end']) + assert_byte_pointer_size(' 123') + assert_cursor(5) + assert_cursor_max(7) + assert_line(' 12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_line_index(2) + assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end']) + assert_byte_pointer_size(' 123') + assert_cursor(5) + assert_cursor_max(7) + assert_line(' 12345') + @line_editor.__send__(:ed_search_prev_history, "\C-p".ord) + assert_line_index(2) + assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end']) + assert_byte_pointer_size(' 123') + assert_cursor(5) + assert_cursor_max(7) + assert_line(' 12345') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_line_index(1) + assert_whole_lines(['def foo', ' 12345', 'end']) + assert_byte_pointer_size(' 123') + assert_cursor(5) + assert_cursor_max(7) + assert_line(' 12345') + @line_editor.__send__(:ed_search_next_history, "\C-n".ord) + assert_line_index(1) + assert_whole_lines(['def foo', ' 12345', 'end']) + assert_byte_pointer_size(' 123') + assert_cursor(5) + assert_cursor_max(7) + assert_line(' 12345') + end + + def test_ignore_NUL_by_ed_quoted_insert + input_keys(%Q{"\C-v\C-@"}, false) + assert_byte_pointer_size('""') + assert_cursor(2) + assert_cursor_max(2) + end + + def test_ed_argument_digit_by_meta_num + input_keys('abcdef') + assert_byte_pointer_size('abcdef') + assert_cursor(6) + assert_cursor_max(6) + assert_line('abcdef') + input_keys("\M-2", false) + input_keys("\C-h", false) + assert_byte_pointer_size('abcd') + assert_cursor(4) + assert_cursor_max(4) + assert_line('abcd') + end + + def test_halfwidth_kana_width_dakuten + input_raw_keys('ガギゲゴ') + assert_byte_pointer_size('ガギゲゴ') + assert_cursor(8) + assert_cursor_max(8) + input_keys("\C-b\C-b", false) + assert_byte_pointer_size('ガギ') + assert_cursor(4) + assert_cursor_max(8) + input_raw_keys('グ', false) + assert_byte_pointer_size('ガギグ') + assert_cursor(6) + assert_cursor_max(10) + assert_line('ガギグゲゴ') + end + + def test_input_unknown_char + input_keys('͸') # U+0378 (unassigned) + assert_line('͸') + assert_byte_pointer_size('͸') assert_cursor(1) assert_cursor_max(1) - assert_line('a') end -=end end diff --git a/ruby/test/reline/test_key_actor_vi.rb b/ruby/test/reline/test_key_actor_vi.rb index c6337baea..b3d49c9bb 100644 --- a/ruby/test/reline/test_key_actor_vi.rb +++ b/ruby/test/reline/test_key_actor_vi.rb @@ -8,11 +8,15 @@ def setup @config.read_lines(<<~LINES.split(/(?<=\n)/)) set editing-mode vi LINES - @encoding = (RELINE_TEST_ENCODING rescue Encoding.default_external) + @encoding = Reline::IOGate.encoding @line_editor = Reline::LineEditor.new(@config, @encoding) @line_editor.reset(@prompt, encoding: @encoding) end + def teardown + Reline.test_reset + end + def test_vi_command_mode input_keys("\C-[") assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode) @@ -615,6 +619,24 @@ def test_vi_replace_char assert_cursor_max(6) end + def test_vi_replace_char_with_mbchar + input_keys("ã‚ã„ã†ãˆãŠ\C-[0l") + assert_line('ã‚ã„ã†ãˆãŠ') + assert_byte_pointer_size('ã‚') + assert_cursor(2) + assert_cursor_max(10) + input_keys('rx') + assert_line('ã‚xã†ãˆãŠ') + assert_byte_pointer_size('ã‚') + assert_cursor(2) + assert_cursor_max(9) + input_keys('l2ry') + assert_line('ã‚xyyãŠ') + assert_byte_pointer_size('ã‚xyy') + assert_cursor(5) + assert_cursor_max(7) + end + def test_vi_next_char input_keys("abcdef\C-[0") assert_line('abcdef') @@ -965,11 +987,6 @@ def test_completion_journey assert_cursor_max(3) assert_line('foo') input_keys("\C-n") - assert_byte_pointer_size('foo') - assert_cursor(3) - assert_cursor_max(3) - assert_line('foo') - input_keys("\C-n") assert_byte_pointer_size('foo_bar') assert_cursor(7) assert_cursor_max(7) @@ -990,11 +1007,6 @@ def test_completion_journey assert_cursor_max(7) assert_line('foo_bar') input_keys("_\C-n") - assert_byte_pointer_size('foo_bar_') - assert_cursor(8) - assert_cursor_max(8) - assert_line('foo_bar_') - input_keys("\C-n") assert_byte_pointer_size('foo_bar_baz') assert_cursor(11) assert_cursor_max(11) @@ -1021,11 +1033,6 @@ def test_completion_journey_reverse assert_cursor_max(3) assert_line('foo') input_keys("\C-p") - assert_byte_pointer_size('foo') - assert_cursor(3) - assert_cursor_max(3) - assert_line('foo') - input_keys("\C-p") assert_byte_pointer_size('foo_bar_baz') assert_cursor(11) assert_cursor_max(11) @@ -1046,11 +1053,6 @@ def test_completion_journey_reverse assert_cursor_max(11) assert_line('foo_bar_baz') input_keys("\C-h\C-p") - assert_byte_pointer_size('foo_bar_ba') - assert_cursor(10) - assert_cursor_max(10) - assert_line('foo_bar_ba') - input_keys("\C-p") assert_byte_pointer_size('foo_bar_baz') assert_cursor(11) assert_cursor_max(11) @@ -1074,11 +1076,6 @@ def test_completion_journey_in_middle_of_line input_keys('abcde fo ABCDE') assert_line('abcde fo ABCDE') input_keys("\C-[" + 'h' * 5 + "i\C-n") - assert_byte_pointer_size('abcde fo') - assert_cursor(8) - assert_cursor_max(14) - assert_line('abcde fo ABCDE') - input_keys("\C-n") assert_byte_pointer_size('abcde foo_bar') assert_cursor(13) assert_cursor_max(19) @@ -1099,11 +1096,6 @@ def test_completion_journey_in_middle_of_line assert_cursor_max(19) assert_line('abcde foo_bar ABCDE') input_keys("_\C-n") - assert_byte_pointer_size('abcde foo_bar_') - assert_cursor(14) - assert_cursor_max(20) - assert_line('abcde foo_bar_ ABCDE') - input_keys("\C-n") assert_byte_pointer_size('abcde foo_bar_baz') assert_cursor(17) assert_cursor_max(23) @@ -1215,26 +1207,251 @@ def test_vi_delete_meta assert_line('aaa ddd eee') end + def test_vi_delete_meta_with_vi_next_word_at_eol + input_keys("foo bar\C-[0w") + assert_byte_pointer_size('foo ') + assert_cursor(4) + assert_cursor_max(7) + assert_line('foo bar') + input_keys('w') + assert_byte_pointer_size('foo ba') + assert_cursor(6) + assert_cursor_max(7) + assert_line('foo bar') + input_keys('0dw') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(3) + assert_line('bar') + input_keys('dw') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + end + + def test_vi_delete_meta_with_vi_next_char + input_keys("aaa bbb ccc ___ ddd\C-[02w") + assert_byte_pointer_size('aaa bbb ') + assert_cursor(8) + assert_cursor_max(19) + assert_line('aaa bbb ccc ___ ddd') + input_keys('df_') + assert_byte_pointer_size('aaa bbb ') + assert_cursor(8) + assert_cursor_max(14) + assert_line('aaa bbb __ ddd') + end + + def test_vi_delete_meta_with_arg + input_keys("aaa bbb ccc\C-[02w") + assert_byte_pointer_size('aaa bbb ') + assert_cursor(8) + assert_cursor_max(11) + assert_line('aaa bbb ccc') + input_keys('2dl') + assert_byte_pointer_size('aaa bbb ') + assert_cursor(8) + assert_cursor_max(9) + assert_line('aaa bbb c') + end + def test_vi_change_meta input_keys("aaa bbb ccc ddd eee\C-[02w") assert_byte_pointer_size('aaa bbb ') assert_cursor(8) assert_cursor_max(19) assert_line('aaa bbb ccc ddd eee') - input_keys('cwaiueo ') - assert_byte_pointer_size('aaa bbb aiueo ') - assert_cursor(14) + input_keys('cwaiueo') + assert_byte_pointer_size('aaa bbb aiueo') + assert_cursor(13) assert_cursor_max(21) assert_line('aaa bbb aiueo ddd eee') input_keys("\C-[") - assert_byte_pointer_size('aaa bbb aiueo') - assert_cursor(13) + assert_byte_pointer_size('aaa bbb aiue') + assert_cursor(12) assert_cursor_max(21) assert_line('aaa bbb aiueo ddd eee') input_keys('cb') assert_byte_pointer_size('aaa bbb ') assert_cursor(8) - assert_cursor_max(16) - assert_line('aaa bbb ddd eee') + assert_cursor_max(17) + assert_line('aaa bbb o ddd eee') + end + + def test_vi_change_meta_with_vi_next_word + input_keys("foo bar baz\C-[0w") + assert_byte_pointer_size('foo ') + assert_cursor(5) + assert_cursor_max(13) + assert_line('foo bar baz') + input_keys('cwhoge') + assert_byte_pointer_size('foo hoge') + assert_cursor(9) + assert_cursor_max(14) + assert_line('foo hoge baz') + input_keys("\C-[") + assert_byte_pointer_size('foo hog') + assert_cursor(8) + assert_cursor_max(14) + assert_line('foo hoge baz') + end + + def test_unimplemented_vi_command_should_be_no_op + input_keys("abc\C-[h") + assert_byte_pointer_size('a') + assert_cursor(1) + assert_cursor_max(3) + assert_line('abc') + input_keys('@') + assert_byte_pointer_size('a') + assert_cursor(1) + assert_cursor_max(3) + assert_line('abc') + end + + def test_vi_yank + input_keys("foo bar\C-[0") + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('y3l') + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('P') + assert_line('foofoo bar') + assert_byte_pointer_size('fo') + assert_cursor(2) + assert_cursor_max(10) + end + + def test_vi_end_word_with_operator + input_keys("foo bar\C-[0") + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('de') + assert_line(' bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(4) + input_keys('de') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + input_keys('de') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + end + + def test_vi_end_big_word_with_operator + input_keys("aaa b{b}}}b\C-[0") + assert_line('aaa b{b}}}b') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(13) + input_keys('dE') + assert_line(' b{b}}}b') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(10) + input_keys('dE') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + input_keys('dE') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + end + + def test_vi_next_char_with_operator + input_keys("foo bar\C-[0") + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('df ') + assert_line('bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(3) + end + + def test_pasting + start_pasting + input_keys('ab') + finish_pasting + input_keys('c') + assert_line('abc') + assert_byte_pointer_size('abc') + assert_cursor(3) + assert_cursor_max(3) + end + + def test_pasting_fullwidth + start_pasting + input_keys('ã‚') + finish_pasting + input_keys('ã„') + assert_line('ã‚ã„') + assert_byte_pointer_size('ã‚ã„') + assert_cursor(4) + assert_cursor_max(4) + end + + def test_ed_delete_next_char_at_eol + input_keys('"ã‚"') + assert_line('"ã‚"') + assert_byte_pointer_size('"ã‚"') + assert_cursor(4) + assert_cursor_max(4) + input_keys("\C-[") + assert_line('"ã‚"') + assert_byte_pointer_size('"ã‚') + assert_cursor(3) + assert_cursor_max(4) + input_keys('xa"') + assert_line('"ã‚"') + assert_byte_pointer_size('"ã‚"') + assert_cursor(4) + assert_cursor_max(4) + end + + def test_vi_kill_line_prev + input_keys("\C-u", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + input_keys('abc') + assert_byte_pointer_size('abc') + assert_cursor(3) + assert_cursor_max(3) + input_keys("\C-u", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + assert_line('') + input_keys('abc') + input_keys("\C-[\C-u", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(1) + assert_line('c') + input_keys("\C-u", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(1) + assert_line('c') end end diff --git a/ruby/test/reline/test_key_stroke.rb b/ruby/test/reline/test_key_stroke.rb index 224e93d9a..d377a1e97 100644 --- a/ruby/test/reline/test_key_stroke.rb +++ b/ruby/test/reline/test_key_stroke.rb @@ -16,10 +16,10 @@ def to_keys def test_match_status config = Reline::Config.new { - "a" => "xx", - "ab" => "y", - "abc" => "z", - "x" => "rr" + 'a' => 'xx', + 'ab' => 'y', + 'abc' => 'z', + 'x' => 'rr' }.each_pair do |key, func| config.add_default_key_binding(key.bytes, func.bytes) end @@ -35,4 +35,45 @@ def test_match_status assert_equal(:unmatched, stroke.match_status("m".bytes)) assert_equal(:matched, stroke.match_status("abzwabk".bytes)) end + + def test_expand + config = Reline::Config.new + { + 'abc' => '123', + }.each_pair do |key, func| + config.add_default_key_binding(key.bytes, func.bytes) + end + stroke = Reline::KeyStroke.new(config) + assert_equal('123'.bytes, stroke.expand('abc'.bytes)) + end + + def test_oneshot_key_bindings + config = Reline::Config.new + { + 'abc' => '123', + }.each_pair do |key, func| + config.add_default_key_binding(key.bytes, func.bytes) + end + stroke = Reline::KeyStroke.new(config) + assert_equal(:unmatched, stroke.match_status('zzz'.bytes)) + assert_equal(:matched, stroke.match_status('abc'.bytes)) + end + + def test_with_reline_key + config = Reline::Config.new + { + [ + Reline::Key.new(100, 228, true), # Alt+d + Reline::Key.new(97, 97, false) # a + ] => 'abc', + [195, 164] => 'def' + }.each_pair do |key, func| + config.add_oneshot_key_binding(key, func.bytes) + end + stroke = Reline::KeyStroke.new(config) + assert_equal(:unmatched, stroke.match_status('da'.bytes)) + assert_equal(:matched, stroke.match_status("\M-da".bytes)) + assert_equal(:unmatched, stroke.match_status([32, 195, 164])) + assert_equal(:matched, stroke.match_status([195, 164])) + end end diff --git a/ruby/test/reline/test_kill_ring.rb b/ruby/test/reline/test_kill_ring.rb index 8bebfe217..9f6e0c3e7 100644 --- a/ruby/test/reline/test_kill_ring.rb +++ b/ruby/test/reline/test_kill_ring.rb @@ -253,4 +253,16 @@ def test_append_complex_chain assert_equal(['AB', 'abcde'], @kill_ring.yank_pop) assert_equal(Reline::KillRing::State::YANK, @kill_ring.instance_variable_get(:@state)) end + + def test_enumerable + @kill_ring.append('a') + @kill_ring.process + @kill_ring.process + @kill_ring.append('b') + @kill_ring.process + @kill_ring.process + @kill_ring.append('c') + @kill_ring.process + assert_equal(%w{c b a}, @kill_ring.to_a) + end end diff --git a/ruby/test/reline/test_macro.rb b/ruby/test/reline/test_macro.rb index b97de88a9..76a677c83 100644 --- a/ruby/test/reline/test_macro.rb +++ b/ruby/test/reline/test_macro.rb @@ -2,8 +2,9 @@ class Reline::MacroTest < Reline::TestCase def setup + Reline.send(:test_mode) @config = Reline::Config.new - @encoding = (RELINE_TEST_ENCODING rescue Encoding.default_external) + @encoding = Reline::IOGate.encoding @line_editor = Reline::LineEditor.new(@config, @encoding) @line_editor.instance_variable_set(:@screen_size, [24, 80]) @output = @line_editor.output = File.open(IO::NULL, "w") @@ -11,6 +12,7 @@ def setup def teardown @output.close + Reline.test_reset end def input_key(char, combined_char = char, with_meta = false) diff --git a/ruby/test/reline/test_reline.rb b/ruby/test/reline/test_reline.rb index 0de2462a0..03e663bcd 100644 --- a/ruby/test/reline/test_reline.rb +++ b/ruby/test/reline/test_reline.rb @@ -1,5 +1,6 @@ require_relative 'helper' -require "reline" +require 'reline' +require 'stringio' class Reline::Test < Reline::TestCase class DummyCallbackObject @@ -7,6 +8,12 @@ def call; end end def setup + Reline.output_modifier_proc = nil + Reline.completion_proc = nil + Reline.prompt_proc = nil + Reline.auto_indent_proc = nil + Reline.pre_input_hook = nil + Reline.dig_perfect_match_proc = nil end def teardown @@ -14,6 +21,8 @@ def teardown end def test_completion_append_character + completion_append_character = Reline.completion_append_character + assert_equal(nil, Reline.completion_append_character) Reline.completion_append_character = "" @@ -33,57 +42,89 @@ def test_completion_append_character Reline.completion_append_character = nil assert_equal(nil, Reline.completion_append_character) + ensure + Reline.completion_append_character = completion_append_character end def test_basic_word_break_characters + basic_word_break_characters = Reline.basic_word_break_characters + assert_equal(" \t\n`><=;|&{(", Reline.basic_word_break_characters) Reline.basic_word_break_characters = "[".encode(Encoding::ASCII) assert_equal("[", Reline.basic_word_break_characters) assert_equal(get_reline_encoding, Reline.basic_word_break_characters.encoding) + ensure + Reline.basic_word_break_characters = basic_word_break_characters end def test_completer_word_break_characters + completer_word_break_characters = Reline.completer_word_break_characters + assert_equal(" \t\n`><=;|&{(", Reline.completer_word_break_characters) Reline.completer_word_break_characters = "[".encode(Encoding::ASCII) assert_equal("[", Reline.completer_word_break_characters) assert_equal(get_reline_encoding, Reline.completer_word_break_characters.encoding) + + assert_nothing_raised { Reline.completer_word_break_characters = '' } + ensure + Reline.completer_word_break_characters = completer_word_break_characters end def test_basic_quote_characters + basic_quote_characters = Reline.basic_quote_characters + assert_equal('"\'', Reline.basic_quote_characters) Reline.basic_quote_characters = "`".encode(Encoding::ASCII) assert_equal("`", Reline.basic_quote_characters) assert_equal(get_reline_encoding, Reline.basic_quote_characters.encoding) + ensure + Reline.basic_quote_characters = basic_quote_characters end def test_completer_quote_characters + completer_quote_characters = Reline.completer_quote_characters + assert_equal('"\'', Reline.completer_quote_characters) Reline.completer_quote_characters = "`".encode(Encoding::ASCII) assert_equal("`", Reline.completer_quote_characters) assert_equal(get_reline_encoding, Reline.completer_quote_characters.encoding) + + assert_nothing_raised { Reline.completer_quote_characters = '' } + ensure + Reline.completer_quote_characters = completer_quote_characters end def test_filename_quote_characters + filename_quote_characters = Reline.filename_quote_characters + assert_equal('', Reline.filename_quote_characters) Reline.filename_quote_characters = "\'".encode(Encoding::ASCII) assert_equal("\'", Reline.filename_quote_characters) assert_equal(get_reline_encoding, Reline.filename_quote_characters.encoding) + ensure + Reline.filename_quote_characters = filename_quote_characters end def test_special_prefixes + special_prefixes = Reline.special_prefixes + assert_equal('', Reline.special_prefixes) Reline.special_prefixes = "\'".encode(Encoding::ASCII) assert_equal("\'", Reline.special_prefixes) assert_equal(get_reline_encoding, Reline.special_prefixes.encoding) + ensure + Reline.special_prefixes = special_prefixes end def test_completion_case_fold + completion_case_fold = Reline.completion_case_fold + assert_equal(nil, Reline.completion_case_fold) Reline.completion_case_fold = true @@ -91,6 +132,8 @@ def test_completion_case_fold Reline.completion_case_fold = "hoge".encode(Encoding::ASCII) assert_equal("hoge", Reline.completion_case_fold) + ensure + Reline.completion_case_fold = completion_case_fold end def test_completion_proc @@ -99,9 +142,9 @@ def test_completion_proc # assert_equal(nil, Reline.completion_proc) - p = proc {} - Reline.completion_proc = p - assert_equal(p, Reline.completion_proc) + dummy_proc = proc {} + Reline.completion_proc = dummy_proc + assert_equal(dummy_proc, Reline.completion_proc) l = lambda {} Reline.completion_proc = l @@ -118,9 +161,9 @@ def test_completion_proc def test_output_modifier_proc assert_equal(nil, Reline.output_modifier_proc) - p = proc {} - Reline.output_modifier_proc = p - assert_equal(p, Reline.output_modifier_proc) + dummy_proc = proc {} + Reline.output_modifier_proc = dummy_proc + assert_equal(dummy_proc, Reline.output_modifier_proc) l = lambda {} Reline.output_modifier_proc = l @@ -137,9 +180,9 @@ def test_output_modifier_proc def test_prompt_proc assert_equal(nil, Reline.prompt_proc) - p = proc {} - Reline.prompt_proc = p - assert_equal(p, Reline.prompt_proc) + dummy_proc = proc {} + Reline.prompt_proc = dummy_proc + assert_equal(dummy_proc, Reline.prompt_proc) l = lambda {} Reline.prompt_proc = l @@ -156,9 +199,9 @@ def test_prompt_proc def test_auto_indent_proc assert_equal(nil, Reline.auto_indent_proc) - p = proc {} - Reline.auto_indent_proc = p - assert_equal(p, Reline.auto_indent_proc) + dummy_proc = proc {} + Reline.auto_indent_proc = dummy_proc + assert_equal(dummy_proc, Reline.auto_indent_proc) l = lambda {} Reline.auto_indent_proc = l @@ -175,9 +218,9 @@ def test_auto_indent_proc def test_pre_input_hook assert_equal(nil, Reline.pre_input_hook) - p = proc {} - Reline.pre_input_hook = p - assert_equal(p, Reline.pre_input_hook) + dummy_proc = proc {} + Reline.pre_input_hook = dummy_proc + assert_equal(dummy_proc, Reline.pre_input_hook) l = lambda {} Reline.pre_input_hook = l @@ -187,9 +230,9 @@ def test_pre_input_hook def test_dig_perfect_match_proc assert_equal(nil, Reline.dig_perfect_match_proc) - p = proc {} - Reline.dig_perfect_match_proc = p - assert_equal(p, Reline.dig_perfect_match_proc) + dummy_proc = proc {} + Reline.dig_perfect_match_proc = dummy_proc + assert_equal(dummy_proc, Reline.dig_perfect_match_proc) l = lambda {} Reline.dig_perfect_match_proc = l @@ -204,29 +247,57 @@ def test_dig_perfect_match_proc end def test_insert_text - # TODO - end - - def test_line_buffer - # TODO - end - - def test_point - # TODO - end - - def test_input= - # TODO + assert_equal('', Reline.line_buffer) + assert_equal(0, Reline.point) + Reline.insert_text('abc') + assert_equal('abc', Reline.line_buffer) + assert_equal(3, Reline.point) + end + + def test_delete_text + assert_equal('', Reline.line_buffer) + assert_equal(0, Reline.point) + Reline.insert_text('abc') + assert_equal('abc', Reline.line_buffer) + assert_equal(3, Reline.point) + Reline.delete_text() + assert_equal('', Reline.line_buffer) + assert_equal(0, Reline.point) + Reline.insert_text('abc') + Reline.delete_text(1) + assert_equal('a', Reline.line_buffer) + assert_equal(1, Reline.point) + Reline.insert_text('defghi') + Reline.delete_text(2, 2) + assert_equal('adghi', Reline.line_buffer) + assert_equal(5, Reline.point) + end + + def test_set_input_and_output assert_raise(TypeError) do Reline.input = "This is not a file." end - end - - def test_output= - # TODO assert_raise(TypeError) do Reline.output = "This is not a file." end + + input, to_write = IO.pipe + to_read, output = IO.pipe + unless Reline.__send__(:input=, input) + omit "Setting to input is not effective on #{Reline::IOGate}" + end + Reline.output = output + + to_write.write "a\n" + result = Reline.readline + to_write.close + read_text = to_read.read_nonblock(100) + assert_equal('a', result) + refute(read_text.empty?) + ensure + input&.close + output&.close + to_read&.close end def test_vi_editing_mode @@ -239,8 +310,46 @@ def test_emacs_editing_mode assert_equal(Reline::KeyActor::Emacs, Reline.send(:core).config.editing_mode.class) end - def test_editing_mode - # TODO + def test_add_dialog_proc + dummy_proc = proc {} + Reline.add_dialog_proc(:test_proc, dummy_proc) + d = Reline.dialog_proc(:test_proc) + assert_equal(dummy_proc, d.dialog_proc) + + dummy_proc_2 = proc {} + Reline.add_dialog_proc(:test_proc, dummy_proc_2) + d = Reline.dialog_proc(:test_proc) + assert_equal(dummy_proc_2, d.dialog_proc) + + l = lambda {} + Reline.add_dialog_proc(:test_lambda, l) + d = Reline.dialog_proc(:test_lambda) + assert_equal(l, d.dialog_proc) + + assert_equal(nil, Reline.dialog_proc(:test_nothing)) + + assert_raise(ArgumentError) { Reline.add_dialog_proc(:error, 42) } + assert_raise(ArgumentError) { Reline.add_dialog_proc(:error, 'hoge') } + assert_raise(ArgumentError) { Reline.add_dialog_proc('error', proc {} ) } + + dummy = DummyCallbackObject.new + Reline.add_dialog_proc(:dummy, dummy) + d = Reline.dialog_proc(:dummy) + assert_equal(dummy, d.dialog_proc) + end + + def test_add_dialog_proc_with_context + dummy_proc = proc {} + array = Array.new + Reline.add_dialog_proc(:test_proc, dummy_proc, array) + d = Reline.dialog_proc(:test_proc) + assert_equal(dummy_proc, d.dialog_proc) + assert_equal(array, d.context) + + Reline.add_dialog_proc(:test_proc, dummy_proc, nil) + d = Reline.dialog_proc(:test_proc) + assert_equal(dummy_proc, d.dialog_proc) + assert_equal(nil, d.context) end def test_readmultiline @@ -272,6 +381,12 @@ def test_may_req_ambiguous_char_width end def get_reline_encoding - RUBY_PLATFORM =~ /mswin|mingw/ ? Encoding::UTF_8 : Encoding::default_external + if encoding = Reline::IOGate.encoding + encoding + elsif RUBY_PLATFORM =~ /mswin|mingw/ + Encoding::UTF_8 + else + Encoding::default_external + end end end diff --git a/ruby/test/reline/test_reline_key.rb b/ruby/test/reline/test_reline_key.rb new file mode 100644 index 000000000..fb700a6f2 --- /dev/null +++ b/ruby/test/reline/test_reline_key.rb @@ -0,0 +1,53 @@ +require_relative 'helper' +require "reline" + +class Reline::TestKey < Reline::TestCase + def setup + end + + def teardown + Reline.test_reset + end + + def test_match_key + assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, false))) + assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(nil, 2, false))) + assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, nil))) + + assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false))) + assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false))) + assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil))) + + assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false))) + assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false))) + assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil))) + + assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(3, 1, false))) + assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, false))) + assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, true))) + end + + def test_match_integer + assert(Reline::Key.new(1, 2, false).match?(2)) + assert(Reline::Key.new(nil, 2, false).match?(2)) + assert(Reline::Key.new(1, nil, false).match?(1)) + + assert(!Reline::Key.new(1, 2, false).match?(1)) + assert(!Reline::Key.new(1, nil, false).match?(2)) + assert(!Reline::Key.new(nil, nil, false).match?(1)) + end + + def test_match_symbol + assert(Reline::Key.new(:key1, :key2, false).match?(:key2)) + assert(Reline::Key.new(:key1, nil, false).match?(:key1)) + + assert(!Reline::Key.new(:key1, :key2, false).match?(:key1)) + assert(!Reline::Key.new(:key1, nil, false).match?(:key2)) + assert(!Reline::Key.new(nil, nil, false).match?(:key1)) + end + + def test_match_other + assert(!Reline::Key.new(:key1, 2, false).match?("key1")) + assert(!Reline::Key.new(nil, nil, false).match?(nil)) + end +end diff --git a/ruby/test/reline/test_string_processing.rb b/ruby/test/reline/test_string_processing.rb index e76fa384f..5db97545d 100644 --- a/ruby/test/reline/test_string_processing.rb +++ b/ruby/test/reline/test_string_processing.rb @@ -6,11 +6,15 @@ def setup @prompt = '> ' @config = Reline::Config.new Reline::HISTORY.instance_variable_set(:@config, @config) - @encoding = (RELINE_TEST_ENCODING rescue Encoding.default_external) + @encoding = Reline::IOGate.encoding @line_editor = Reline::LineEditor.new(@config, @encoding) @line_editor.reset(@prompt, encoding: @encoding) end + def teardown + Reline.test_reset + end + def test_calculate_width width = @line_editor.send(:calculate_width, 'Ruby string') assert_equal('Ruby string'.size, width) @@ -20,4 +24,58 @@ def test_calculate_width_with_escape_sequence width = @line_editor.send(:calculate_width, "\1\e[31m\2RubyColor\1\e[34m\2 default string \1\e[m\2>", true) assert_equal('RubyColor default string >'.size, width) end + + def test_completion_proc_with_preposing_and_postposing + buf = ['def hoge', ' puts :aaa', 'end'] + + @line_editor.instance_variable_set(:@is_multiline, true) + @line_editor.instance_variable_set(:@buffer_of_lines, buf) + @line_editor.instance_variable_set(:@line, buf[1]) + @line_editor.instance_variable_set(:@byte_pointer, 3) + @line_editor.instance_variable_set(:@cursor, 3) + @line_editor.instance_variable_set(:@cursor_max, 11) + @line_editor.instance_variable_set(:@line_index, 1) + @line_editor.instance_variable_set(:@completion_proc, proc { |target| + assert_equal('p', target) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@is_multiline, true) + @line_editor.instance_variable_set(:@buffer_of_lines, buf) + @line_editor.instance_variable_set(:@line, buf[1]) + @line_editor.instance_variable_set(:@byte_pointer, 6) + @line_editor.instance_variable_set(:@cursor, 6) + @line_editor.instance_variable_set(:@cursor_max, 11) + @line_editor.instance_variable_set(:@line_index, 1) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('puts', target) + assert_equal("def hoge\n ", pre) + assert_equal(" :aaa\nend", post) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@line, buf[0]) + @line_editor.instance_variable_set(:@byte_pointer, 6) + @line_editor.instance_variable_set(:@cursor, 6) + @line_editor.instance_variable_set(:@cursor_max, 8) + @line_editor.instance_variable_set(:@line_index, 0) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('ho', target) + assert_equal('def ', pre) + assert_equal("ge\n puts :aaa\nend", post) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@line, buf[2]) + @line_editor.instance_variable_set(:@byte_pointer, 1) + @line_editor.instance_variable_set(:@cursor, 1) + @line_editor.instance_variable_set(:@cursor_max, 3) + @line_editor.instance_variable_set(:@line_index, 2) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('e', target) + assert_equal("def hoge\n puts :aaa\n", pre) + assert_equal('nd', post) + }) + @line_editor.__send__(:call_completion_proc) + end end diff --git a/ruby/test/reline/test_terminfo.rb b/ruby/test/reline/test_terminfo.rb new file mode 100644 index 000000000..f1bf19793 --- /dev/null +++ b/ruby/test/reline/test_terminfo.rb @@ -0,0 +1,32 @@ +require_relative 'helper' +require "reline" + +class Reline::Terminfo::Test < Reline::TestCase + def setup + Reline::Terminfo.setupterm(0, 2) + end + + def test_tigetstr + assert Reline::Terminfo.tigetstr('khome') + rescue Reline::Terminfo::TerminfoError => e + skip e.message + end + + def test_tiparm + assert Reline::Terminfo.tigetstr('khome').tiparm + rescue Reline::Terminfo::TerminfoError => e + skip e.message + end + + def test_tigetstr_with_param + assert Reline::Terminfo.tigetstr('cuu').include?('%p1%d') + rescue Reline::Terminfo::TerminfoError => e + skip e.message + end + + def test_tiparm_with_param + assert Reline::Terminfo.tigetstr('cuu').tiparm(4649).include?('4649') + rescue Reline::Terminfo::TerminfoError => e + skip e.message + end +end if Reline::Terminfo.enabled? diff --git a/ruby/test/reline/test_unicode.rb b/ruby/test/reline/test_unicode.rb new file mode 100644 index 000000000..1233e034e --- /dev/null +++ b/ruby/test/reline/test_unicode.rb @@ -0,0 +1,25 @@ +require_relative 'helper' +require "reline/unicode" + +class Reline::Unicode::Test < Reline::TestCase + def setup + Reline.send(:test_mode) + end + + def teardown + Reline.test_reset + end + + def test_get_mbchar_width + assert_equal Reline.ambiguous_width, Reline::Unicode.get_mbchar_width('é') + end + + def test_ambiguous_width + assert_equal 2, Reline::Unicode.calculate_width('√', true) + end + + def test_take_range + assert_equal 'cdef', Reline::Unicode.take_range('abcdefghi', 2, 4) + assert_equal 'ã„ã†', Reline::Unicode.take_range('ã‚ã„ã†ãˆãŠ', 2, 4) + end +end diff --git a/ruby/test/reline/test_within_pipe.rb b/ruby/test/reline/test_within_pipe.rb index 46b4465f3..43a66f45f 100644 --- a/ruby/test/reline/test_within_pipe.rb +++ b/ruby/test/reline/test_within_pipe.rb @@ -3,10 +3,13 @@ class Reline::WithinPipeTest < Reline::TestCase def setup Reline.send(:test_mode) - @reader, @writer = IO.pipe((RELINE_TEST_ENCODING rescue Encoding.default_external)) - Reline.input = @reader - @output = Reline.output = File.open(IO::NULL, 'w') + @encoding = Reline::IOGate.encoding + @input_reader, @writer = IO.pipe(@encoding) + Reline.input = @input_reader + @reader, @output_writer = IO.pipe(@encoding) + @output = Reline.output = @output_writer @config = Reline.send(:core).config + @config.keyseq_timeout *= 600 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait CI @line_editor = Reline.send(:core).line_editor end @@ -14,10 +17,14 @@ def teardown Reline.input = STDIN Reline.output = STDOUT Reline.point = 0 - @reader.close + Reline.delete_text + @input_reader.close @writer.close - @output.close + @reader.close + @output_writer.close @config.reset + @config.reset_default_key_bindings + Reline.test_reset end def test_simple_input @@ -55,4 +62,17 @@ def test_macro_commands_for_editing @writer.write("abcde\C-b\C-b\C-b\C-x\C-d\C-x\C-h\C-x\C-v\C-a\C-f\C-f EF\C-x\C-t gh\C-x\M-t\C-b\C-b\C-b\C-b\C-b\C-b\C-b\C-b\C-x\M-u\C-x\M-l\C-x\M-c\n") assert_equal "a\C-aDE gh Fe", Reline.readmultiline(&proc{ true }) end + + def test_delete_text_in_multiline + @writer.write("abc\ndef\nxyz\n") + result = Reline.readmultiline(&proc{ |str| + if str.include?('xyz') + Reline.delete_text + true + else + false + end + }) + assert_equal "abc\ndef", result + end end diff --git a/ruby/test/reline/windows/test_key_event_record.rb b/ruby/test/reline/windows/test_key_event_record.rb new file mode 100644 index 000000000..a034d20fe --- /dev/null +++ b/ruby/test/reline/windows/test_key_event_record.rb @@ -0,0 +1,41 @@ +require_relative '../helper' +return unless Reline.const_defined?(:Windows) + +class Reline::Windows + class KeyEventRecord::Test < Reline::TestCase + + def setup + # Ctrl+A + @key = Reline::Windows::KeyEventRecord.new(0x41, 1, Reline::Windows::LEFT_CTRL_PRESSED) + end + + def test_matches__with_no_arguments_raises_error + assert_raise(ArgumentError) { @key.matches? } + end + + def test_matches_char_code + assert @key.matches?(char_code: 0x1) + end + + def test_matches_virtual_key_code + assert @key.matches?(virtual_key_code: 0x41) + end + + def test_matches_control_keys + assert @key.matches?(control_keys: :CTRL) + end + + def test_doesnt_match_alt + refute @key.matches?(control_keys: :ALT) + end + + def test_doesnt_match_empty_control_key + refute @key.matches?(control_keys: []) + end + + def test_matches_control_keys_and_virtual_key_code + assert @key.matches?(control_keys: :CTRL, virtual_key_code: 0x41) + end + + end +end diff --git a/ruby/test/reline/yamatanooroti/multiline_repl b/ruby/test/reline/yamatanooroti/multiline_repl new file mode 100755 index 000000000..3c47184b8 --- /dev/null +++ b/ruby/test/reline/yamatanooroti/multiline_repl @@ -0,0 +1,211 @@ +#!/usr/bin/env ruby + +require 'reline' +require 'optparse' +require_relative 'termination_checker' + +opt = OptionParser.new +opt.on('--prompt-list-cache-timeout VAL') { |v| + Reline::LineEditor.__send__(:remove_const, :PROMPT_LIST_CACHE_TIMEOUT) + Reline::LineEditor::PROMPT_LIST_CACHE_TIMEOUT = v.to_f +} +opt.on('--dynamic-prompt') { + Reline.prompt_proc = proc { |lines| + lines.each_with_index.map { |l, i| + '[%04d]> ' % i + } + } +} +opt.on('--broken-dynamic-prompt') { + Reline.prompt_proc = proc { |lines| + range = lines.size > 1 ? (0..(lines.size - 2)) : (0..0) + lines[range].each_with_index.map { |l, i| + '[%04d]> ' % i + } + } +} +opt.on('--dynamic-prompt-returns-empty') { + Reline.prompt_proc = proc { |l| [] } +} +opt.on('--dynamic-prompt-with-newline') { + Reline.prompt_proc = proc { |lines| + range = lines.size > 1 ? (0..(lines.size - 2)) : (0..0) + lines[range].each_with_index.map { |l, i| + '[%04d\n]> ' % i + } + } +} +opt.on('--auto-indent') { + AutoIndent.new +} +opt.on('--dialog VAL') { |v| + Reline.add_dialog_proc(:simple_dialog, lambda { + return nil if v.include?('nil') + if v.include?('simple') + contents = <<~RUBY.split("\n") + Ruby is... + A dynamic, open source programming + language with a focus on simplicity + and productivity. It has an elegant + syntax that is natural to read and + easy to write. + RUBY + elsif v.include?('long') + contents = <<~RUBY.split("\n") + Ruby is... + A dynamic, open + source programming + language with a + focus on simplicity + and productivity. + It has an elegant + syntax that is + natural to read + and easy to write. + RUBY + elsif v.include?('fullwidth') + contents = <<~RUBY.split("\n") + Rubyã¨ã¯... + + オープンソースã®å‹•çš„ãªãƒ—ログラミン + グ言語ã§ã€ã‚·ãƒ³ãƒ—ルã•ã¨é«˜ã„生産性を + å‚™ãˆã¦ã„ã¾ã™ã€‚ã‚¨ãƒ¬ã‚¬ãƒ³ãƒˆãªæ–‡æ³•ã‚’æŒ + ã¡ã€è‡ªç„¶ã«èª­ã¿æ›¸ããŒã§ãã¾ã™ã€‚ + RUBY + end + if v.include?('scrollkey') + dialog.trap_key = nil + if key and key.match?(dialog.name) + if dialog.pointer.nil? + dialog.pointer = 0 + elsif dialog.pointer >= (contents.size - 1) + dialog.pointer = 0 + else + dialog.pointer += 1 + end + end + dialog.trap_key = [?j.ord] + height = 4 + end + scrollbar = false + if v.include?('scrollbar') + scrollbar = true + end + if v.include?('alt-scrollbar') + scrollbar = true + end + Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, scrollbar: scrollbar) + }) + if v.include?('alt-scrollbar') + ENV['RELINE_ALT_SCROLLBAR'] = '1' + end +} +opt.on('--complete') { + Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| + %w{String ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) } + } +} +opt.on('--autocomplete') { + Reline.autocompletion = true + Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| + %w{String Struct Symbol ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) } + } +} +opt.on('--autocomplete-long') { + Reline.autocompletion = true + Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| + %w{ + String + Struct + Symbol + StopIteration + SystemCallError + SystemExit + SystemStackError + ScriptError + SyntaxError + Signal + SizedQueue + Set + SecureRandom + Socket + StringIO + StringScanner + Shellwords + Syslog + Singleton + SDBM + }.select{ |c| c.start_with?(target) } + } +} +opt.on('--autocomplete-super-long') { + Reline.autocompletion = true + Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| + c = 'A' + 2000.times.map{ s = "Str_#{c}"; c.succ!; s }.select{ |c| c.start_with?(target) } + } +} + +opt.on('--autocomplete-width-long') { + Reline.autocompletion = true + Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| + %w{ + remove_instance_variable + respond_to? + ruby2_keywords + rand + readline + readlines + require + require_relative + raise + respond_to_missing? + redo + rescue + retry + return + }.select{ |c| c.start_with?(target) } + } +} +opt.parse!(ARGV) + +begin + stty_save = `stty -g`.chomp +rescue +end + +begin + prompt = ENV['RELINE_TEST_PROMPT'] || 'prompt> ' + puts 'Multiline REPL.' + checker = TerminationChecker.new + while code = Reline.readmultiline(prompt, true) { |code| checker.terminated?(code) } + case code.chomp + when 'exit', 'quit', 'q' + exit 0 + when '' + # NOOP + else + begin + result = eval(code) + puts "=> #{result.inspect}" + rescue ScriptError, StandardError => e + puts "Traceback (most recent call last):" + e.backtrace.reverse_each do |f| + puts " #{f}" + end + puts e.message + end + end + end +rescue Interrupt + puts '^C' + `stty #{stty_save}` if stty_save + exit 0 +ensure + `stty #{stty_save}` if stty_save +end +begin + puts +rescue Errno::EIO + # Maybe the I/O has been closed. +end diff --git a/ruby/test/reline/yamatanooroti/termination_checker.rb b/ruby/test/reline/yamatanooroti/termination_checker.rb new file mode 100644 index 000000000..9c2c3ae74 --- /dev/null +++ b/ruby/test/reline/yamatanooroti/termination_checker.rb @@ -0,0 +1,30 @@ +require 'ripper' +require 'irb/ruby-lex' + +class TerminationChecker < RubyLex + def terminated?(code) + code.gsub!(/\n*$/, '').concat("\n") + @tokens = Ripper.lex(code) + continue = process_continue + code_block_open = check_code_block(code) + indent = process_nesting_level + ltype = process_literal_type + if code_block_open or ltype or continue or indent > 0 + false + else + true + end + end +end + +class AutoIndent < RubyLex + def initialize + set_input(self) + context = Struct.new(:auto_indent_mode, :workspace).new(true, nil) + set_auto_indent(context) + end + + def auto_indent(&block) + Reline.auto_indent_proc = block + end +end diff --git a/ruby/test/reline/yamatanooroti/test_rendering.rb b/ruby/test/reline/yamatanooroti/test_rendering.rb index 4eab6661d..43c24f641 100644 --- a/ruby/test/reline/yamatanooroti/test_rendering.rb +++ b/ruby/test/reline/yamatanooroti/test_rendering.rb @@ -5,14 +5,28 @@ class Reline::TestRendering < Yamatanooroti::TestCase def setup - inputrc_backup = ENV['INPUTRC'] - ENV['INPUTRC'] = 'nonexistent_file' - start_terminal(5, 30, %w{ruby -Ilib bin/multiline_repl}) - sleep 0.5 - ENV['INPUTRC'] = inputrc_backup + @pwd = Dir.pwd + suffix = '%010d' % Random.rand(0..65535) + @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_reline_config_#{$$}_#{suffix}") + begin + Dir.mkdir(@tmpdir) + rescue Errno::EEXIST + FileUtils.rm_rf(@tmpdir) + Dir.mkdir(@tmpdir) + end + @inputrc_backup = ENV['INPUTRC'] + @inputrc_file = ENV['INPUTRC'] = File.join(@tmpdir, 'temporaty_inputrc') + File.unlink(@inputrc_file) if File.exist?(@inputrc_file) + end + + def teardown + FileUtils.rm_rf(@tmpdir) + ENV['INPUTRC'] = @inputrc_backup + ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT'] end def test_history_back + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') write(":a\n") write("\C-p") close @@ -25,6 +39,7 @@ def test_history_back end def test_backspace + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') write(":abc\C-h\n") close assert_screen(<<~EOC) @@ -34,6 +49,1215 @@ def test_backspace prompt> EOC end + + def test_autowrap + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write('01234567890123456789012') + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> 0123456789012345678901 + 2 + EOC + end + + def test_fullwidth + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":ã‚\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> :ã‚ + => :ã‚ + prompt> + EOC + end + + def test_two_fullwidth + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":ã‚ã„\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> :ã‚ã„ + => :ã‚ã„ + prompt> + EOC + end + + def test_finish_autowrapped_line + start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("[{'user'=>{'email'=>'a@a', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> [{'user'=>{'email'=>'a@a', 'id'= + >'ABC'}, 'version'=>4, 'status'=>'succee + ded'}] + => [{"user"=>{"email"=>"a@a", "id"=>"ABC + "}, "version"=>4, "status"=>"succeeded"} + ] + prompt> + EOC + end + + def test_finish_autowrapped_line_in_the_middle_of_lines + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("[{'user'=>{'email'=>'abcdef@abcdef', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]#{"\C-b"*7}") + write("\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> [{'user'=>{'email'=>'a + bcdef@abcdef', 'id'=>'ABC'}, ' + version'=>4, 'status'=>'succee + ded'}] + => [{"user"=>{"email"=>"abcdef + @abcdef", "id"=>"ABC"}, "versi + on"=>4, "status"=>"succeeded"} + ] + prompt> + EOC + end + + def test_finish_autowrapped_line_in_the_middle_of_multilines + start_terminal(30, 16, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("<<~EOM\n ABCDEFG\nEOM\n") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> <<~EOM + prompt> ABCDEF + G + prompt> EOM + => "ABCDEFG\n" + prompt> + EOC + end + + def test_prompt + write_inputrc <<~'LINES' + "abc": "123" + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("abc\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> 123 + => 123 + prompt> + EOC + end + + def test_mode_string_emacs + write_inputrc <<~LINES + set show-mode-in-prompt on + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + close + assert_screen(<<~EOC) + Multiline REPL. + @prompt> + EOC + end + + def test_mode_string_vi + write_inputrc <<~LINES + set editing-mode vi + set show-mode-in-prompt on + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":a\n\C-[k") + close + assert_screen(<<~EOC) + Multiline REPL. + (ins)prompt> :a + => :a + (cmd)prompt> :a + EOC + end + + def test_original_mode_string_emacs + write_inputrc <<~LINES + set show-mode-in-prompt on + set emacs-mode-string [emacs] + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + close + assert_screen(<<~EOC) + Multiline REPL. + [emacs]prompt> + EOC + end + + def test_original_mode_string_with_quote + write_inputrc <<~LINES + set show-mode-in-prompt on + set emacs-mode-string "[emacs]" + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + close + assert_screen(<<~EOC) + Multiline REPL. + [emacs]prompt> + EOC + end + + def test_original_mode_string_vi + write_inputrc <<~LINES + set editing-mode vi + set show-mode-in-prompt on + set vi-ins-mode-string "{InS}" + set vi-cmd-mode-string "{CmD}" + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":a\n\C-[k") + close + assert_screen(<<~EOC) + Multiline REPL. + {InS}prompt> :a + => :a + {CmD}prompt> :a + EOC + end + + def test_mode_string_vi_changing + write_inputrc <<~LINES + set editing-mode vi + set show-mode-in-prompt on + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":a\C-[ab\C-[ac\C-h\C-h\C-h\C-h:a") + close + assert_screen(<<~EOC) + Multiline REPL. + (ins)prompt> :a + EOC + end + + def test_prompt_with_escape_sequence + ENV['RELINE_TEST_PROMPT'] = "\1\e[30m\2prompt> \1\e[m\2" + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("123\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> 123 + => 123 + prompt> + EOC + end + + def test_prompt_with_escape_sequence_and_autowrap + ENV['RELINE_TEST_PROMPT'] = "\1\e[30m\2prompt> \1\e[m\2" + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("1234567890123\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> 123456789012 + 3 + => 1234567890123 + prompt> + EOC + end + + def test_multiline_and_autowrap + start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def aaaaaaaaaa\n 33333333\n end\C-a\C-pputs\C-e\e\C-m888888888888888") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def aaaaaaaa + aa + prompt> puts 333333 + 33 + prompt> 888888888888 + 888 + prompt> e + nd + EOC + end + + def test_clear + start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("3\C-l") + close + assert_screen(<<~EOC) + prompt> 3 + EOC + end + + def test_clear_multiline_and_autowrap + start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def aaaaaa\n 3\n\C-lend") + close + assert_screen(<<~EOC) + prompt> def aaa + aaa + prompt> 3 + prompt> end + EOC + end + + def test_nearest_cursor + start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def ã‚ã‚\n :ã„ã„\nend\C-pbb\C-pcc") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def ccã‚ã‚ + prompt> :bbã„ã„ + prompt> end + EOC + end + + def test_delete_line + start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def a\n\nend\C-p\C-h") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def a + prompt> end + EOC + end + + def test_last_line_of_screen + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("\n\n\n\n\ndef a\nend") + close + assert_screen(<<~EOC) + prompt> + prompt> + prompt> + prompt> def a + prompt> end + EOC + end + + # c17a09b7454352e2aff5a7d8722e80afb73e454b + def test_autowrap_at_last_line_of_screen + start_terminal(5, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def a\nend\n\C-p") + close + assert_screen(<<~EOC) + prompt> def a + prompt> end + => :a + prompt> def a + prompt> end + EOC + end + + # f002483b27cdb325c5edf9e0fe4fa4e1c71c4b0e + def test_insert_line_in_the_middle_of_line + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("333\C-b\C-b\e\C-m8") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> 3 + prompt> 833 + EOC + end + + # 9d8978961c5de5064f949d56d7e0286df9e18f43 + def test_insert_line_in_the_middle_of_line_at_last_line_of_screen + start_terminal(3, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("333333333333333\C-a\C-f\e\C-m") + close + assert_screen(<<~EOC) + prompt> 3 + prompt> 333333333333 + 33 + EOC + end + + def test_insert_after_clear + start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def a\n 01234\nend\C-l\C-p5678") + close + assert_screen(<<~EOC) + prompt> def a + prompt> 056781234 + prompt> end + EOC + end + + def test_foced_newline_insertion + start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + #write("def a\nend\C-p\C-e\e\C-m 3") + write("def a\nend\C-p\C-e\e\x0D") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def a + prompt> + prompt> end + EOC + end + + def test_multiline_incremental_search + start_terminal(6, 25, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def a\n 8\nend\ndef b\n 3\nend\C-s8") + close + assert_screen(<<~EOC) + (i-search)`8'def a + (i-search)`8' 8 + (i-search)`8'end + EOC + end + + def test_multiline_incremental_search_finish + start_terminal(6, 25, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def a\n 8\nend\ndef b\n 3\nend\C-r8\C-j") + close + assert_screen(<<~EOC) + prompt> def a + prompt> 8 + prompt> end + EOC + end + + def test_binding_for_vi_movement_mode + write_inputrc <<~LINES + set editing-mode vi + "\\C-a": vi-movement-mode + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(":1234\C-ahhhi0") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> :01234 + EOC + end + + def test_prompt_list_caching + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --prompt-list-cache-timeout 10 --dynamic-prompt}, startup_message: 'Multiline REPL.') + write("def hoge\n 3\nend") + close + assert_screen(<<~EOC) + Multiline REPL. + [0000]> def hoge + [0001]> 3 + [0002]> end + EOC + end + + def test_broken_prompt_list + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --broken-dynamic-prompt}, startup_message: 'Multiline REPL.') + write("def hoge\n 3\nend") + close + assert_screen(<<~EOC) + Multiline REPL. + [0000]> def hoge + [0001]> 3 + [0001]> end + EOC + end + + def test_enable_bracketed_paste + omit if Reline::IOGate.win? + write_inputrc <<~LINES + set enable-bracketed-paste on + LINES + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("\e[200~,") + write("def hoge\n 3\nend") + write("\e[200~.") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + prompt> 3 + prompt> end + EOC + end + + def test_backspace_until_returns_to_initial + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("ABC") + write("\C-h\C-h\C-h") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> + EOC + end + + def test_longer_than_screen_height + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(<<~EOC.chomp) + def each_top_level_statement + initialize_input + catch(:TERM_INPUT) do + loop do + begin + prompt + unless l = lex + throw :TERM_INPUT if @line == '' + else + @line_no += l.count("\n") + next if l == "\n" + @line.concat l + if @code_block_open or @ltype or @continue or @indent > 0 + next + end + end + if @line != "\n" + @line.force_encoding(@io.encoding) + yield @line, @exp_line_no + end + break if @io.eof? + @line = '' + @exp_line_no = @line_no + # + @indent = 0 + rescue TerminateLineInput + initialize_input + prompt + end + end + end + end + EOC + sleep 1 + close + assert_screen(<<~EOC) + prompt> prompt + prompt> end + prompt> end + prompt> end + prompt> end + EOC + end + + def test_longer_than_screen_height_with_scroll_back + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(<<~EOC.chomp) + def each_top_level_statement + initialize_input + catch(:TERM_INPUT) do + loop do + begin + prompt + unless l = lex + throw :TERM_INPUT if @line == '' + else + @line_no += l.count("\n") + next if l == "\n" + @line.concat l + if @code_block_open or @ltype or @continue or @indent > 0 + next + end + end + if @line != "\n" + @line.force_encoding(@io.encoding) + yield @line, @exp_line_no + end + break if @io.eof? + @line = '' + @exp_line_no = @line_no + # + @indent = 0 + rescue TerminateLineInput + initialize_input + prompt + end + end + end + end + EOC + sleep 1 + write("\C-p" * 6) + close + assert_screen(<<~EOC) + prompt> rescue Terminate + LineInput + prompt> initialize_inp + ut + prompt> prompt + EOC + end + + def test_longer_than_screen_height_with_complex_scroll_back + start_terminal(4, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write(<<~EOC.chomp) + def each_top_level_statement + initialize_input + catch(:TERM_INPUT) do + loop do + begin + prompt + unless l = lex + throw :TERM_INPUT if @line == '' + else + @line_no += l.count("\n") + next if l == "\n" + @line.concat l + if @code_block_open or @ltype or @continue or @indent > 0 + next + end + end + if @line != "\n" + @line.force_encoding(@io.encoding) + yield @line, @exp_line_no + end + break if @io.eof? + @line = '' + @exp_line_no = @line_no + # + @indent = 0 + rescue TerminateLineInput + initialize_input + prompt + end + end + end + end + EOC + sleep 1 + write("\C-p" * 5) + write("\C-n" * 3) + close + assert_screen(<<~EOC) + ut + prompt> prompt + prompt> end + prompt> end + EOC + end + + def test_update_cursor_correctly_when_just_cursor_moving + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def hoge\n 01234678") + write("\C-p") + write("\C-b") + write("\C-n") + write('5') + write("\C-e") + write('9') + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + prompt> 0123456789 + EOC + end + + def test_suppress_auto_indent_just_after_pasted + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.') + write("def hoge\n [[\n 3]]\ned") + write("\C-bn") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + prompt> [[ + prompt> 3]] + prompt> end + EOC + end + + def test_suppress_auto_indent_for_adding_newlines_in_pasting + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.') + write("<<~Q\n") + write("{\n #\n}") + write("#") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> <<~Q + prompt> { + prompt> # + prompt> }# + EOC + end + + def test_autowrap_in_the_middle_of_a_line + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def abcdefg; end\C-b\C-b\C-b\C-b\C-b") + %w{h i}.each do |c| + write(c) + end + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def abcdefgh + i; end + EOC + end + + def test_terminate_in_the_middle_of_lines + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def hoge\n 1\n 2\n 3\n 4\nend\n") + write("\C-p\C-p\C-p\C-e\n") + close + assert_screen(<<~EOC) + prompt> 3 + prompt> 4 + prompt> end + => :hoge + prompt> + EOC + end + + def test_dynamic_prompt_returns_empty + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt-returns-empty}, startup_message: 'Multiline REPL.') + write("def hoge\nend\n") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + prompt> end + => :hoge + prompt> + EOC + end + + def test_reset_rest_height_when_clear_screen + start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("\n\n\n\C-l3\n") + close + assert_screen(<<~EOC) + prompt> 3 + => 3 + prompt> + EOC + end + + def test_meta_key + start_terminal(30, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def ge\M-bho") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + EOC + end + + def test_not_meta_key + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("ãŠã ã‚“ã”") # "ã " in UTF-8 contains "\xA0" + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> ãŠã ã‚“ã” + EOC + end + + def test_force_enter + start_terminal(30, 120, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def hoge\nend\C-p\C-e") + write("\M-\x0D") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> def hoge + prompt> + prompt> end + EOC + end + + def test_with_newline + omit if Reline::IOGate.win? + cmd = %Q{ruby -e 'print(%Q{abc def \\e\\r})' | ruby -I#{@pwd}/lib -rreline -e 'p Reline.readline(%{> })'} + start_terminal(40, 50, ['bash', '-c', cmd]) + close + assert_screen(<<~'EOC') + > abc def + "abc def " + EOC + end + + def test_em_set_mark_and_em_exchange_mark + start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("aaa bbb ccc ddd\M-b\M-b\M-\x20\M-b\C-x\C-xX\C-x\C-xY") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> aaa Ybbb Xccc ddd + EOC + end + + def test_completion_journey_2nd_line + write_inputrc <<~LINES + set editing-mode vi + LINES + start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.') + write("def hoge\n S\C-n") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> def hoge + prompt> String + EOC + end + + def test_completion_journey_with_empty_line + write_inputrc <<~LINES + set editing-mode vi + LINES + start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.') + write("\C-n\C-p") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> + EOC + end + + def test_simple_dialog + start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.') + write('a') + write('b') + write('c') + write("\C-h") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> ab + Ruby is... + A dynamic, open source programming + language with a focus on simplicity + and productivity. It has an elegant + syntax that is natural to read and + easy to write. + EOC + end + + def test_simple_dialog_at_right_edge + start_terminal(20, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.') + write('a') + write('b') + write('c') + write("\C-h") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> ab + Ruby is... + A dynamic, open source programming + language with a focus on simplicity + and productivity. It has an elegant + syntax that is natural to read and + easy to write. + EOC + end + + def test_autocomplete_at_bottom + start_terminal(15, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write('def hoge' + "\C-m" * 10 + "end\C-p ") + write('S') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> def hoge + prompt> + prompt> + prompt> String + prompt> Struct + prompt> Symbol + prompt> ScriptError + prompt> SyntaxError + prompt> Signal + prompt> S + prompt> end + EOC + end + + def test_autocomplete_return_to_original + start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write('S') + write('t') + write('r') + 3.times{ write("\C-i") } + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> Str + String + Struct + EOC + end + + def test_autocomplete_target_is_wrapped + start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write(' ') + write('S') + write('t') + write('r') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> St + r String + Struct + EOC + end + + def test_simple_dialog_with_scroll_key + start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey}, startup_message: 'Multiline REPL.') + write('a') + 5.times{ write('j') } + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> a + A dynamic, open + source programming + language with a + focus on simplicity + EOC + end + + def test_simple_dialog_scrollbar_with_moving_to_right + start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey,scrollbar}, startup_message: 'Multiline REPL.') + 6.times{ write('j') } + write('a') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> a + source programming â–„ + language with a â–ˆ + focus on simplicity + and productivity. + EOC + end + + def test_simple_dialog_scrollbar_with_moving_to_left + start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey,scrollbar}, startup_message: 'Multiline REPL.') + write('a') + 6.times{ write('j') } + write("\C-h") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> + source programming â–„ + language with a â–ˆ + focus on simplicity + and productivity. + EOC + end + + def test_dialog_with_fullwidth_chars + ENV['RELINE_TEST_PROMPT'] = '> ' + start_terminal(30, 5, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog fullwidth,scrollkey,scrollbar}, startup_message: 'Multiline REPL.') + 6.times{ write('j') } + close + assert_screen(<<~'EOC') + Multi + line + REPL. + > + オー + グ言▄ + å‚™ãˆâ–ˆ + ã¡ã€â–ˆ + EOC + end + + def test_dialog_with_fullwidth_chars_split + ENV['RELINE_TEST_PROMPT'] = '> ' + start_terminal(30, 6, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog fullwidth,scrollkey,scrollbar}, startup_message: 'Multiline REPL.') + 6.times{ write('j') } + close + assert_screen(<<~'EOC') + Multil + ine RE + PL. + > + オー + グ言 â–„ + 備㈠█ + ã¡ã€ â–ˆ + EOC + end + + def test_autocomplete_empty + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write('Street') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> Street + EOC + end + + def test_autocomplete + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write('Str') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> Str + String + Struct + EOC + end + + def test_autocomplete_after_2nd_line + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write("def hoge\n Str") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> def hoge + prompt> Str + String + Struct + EOC + end + + def test_autocomplete_rerender_under_dialog + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write("def hoge\n\n 123456\n 456789\nend\C-p\C-p\C-p a = Str") + write('i') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> def hoge + prompt> a = Stri + prompt> 1234String + prompt> 456789 + prompt> end + EOC + end + + def test_autocomplete_long_with_scrollbar + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.') + write('S') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> S + String â–ˆ + Struct â–ˆ + Symbol â–ˆ + StopIteration â–ˆ + SystemCallError â–ˆ + SystemExit â–ˆ + SystemStackErrorâ–ˆ + ScriptError â–ˆ + SyntaxError â–ˆ + Signal â–ˆ + SizedQueue â–ˆ + Set + SecureRandom + Socket + StringIO + EOC + end + + def test_autocomplete_long_with_scrollbar_scroll + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.') + write('S' + "\C-i" * 16) + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> StringScanner + Struct â–„ + Symbol â–ˆ + StopIteration â–ˆ + SystemCallError â–ˆ + SystemExit â–ˆ + SystemStackErrorâ–ˆ + ScriptError â–ˆ + SyntaxError â–ˆ + Signal â–ˆ + SizedQueue â–ˆ + Set â–ˆ + SecureRandom â–€ + Socket + StringIO + StringScanner + EOC + end + + def test_autocomplete_super_long_and_backspace + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-super-long}, startup_message: 'Multiline REPL.') + shift_tab = [27, 91, 90] + write('S' + shift_tab.map(&:chr).join) + write("\C-h") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> Str_BX + Str_BX + Str_BXA + Str_BXB + Str_BXC + Str_BXD + Str_BXE + Str_BXF + Str_BXG + Str_BXH + Str_BXI + Str_BXJ + Str_BXK + Str_BXL + Str_BXM + Str_BXN + EOC + end + + def test_dialog_callback_returns_nil + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog nil}, startup_message: 'Multiline REPL.') + write('a') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> a + EOC + end + + def test_dialog_narrower_than_screen + start_terminal(20, 11, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.') + close + assert_screen(<<~'EOC') + Multiline R + EPL. + prompt> + Ruby is... + A dynamic, + language wi + and product + syntax that + easy to wri + EOC + end + + def test_dialog_narrower_than_screen_with_scrollbar + start_terminal(20, 11, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.') + write('S' + "\C-i" * 3) + close + assert_screen(<<~'EOC') + Multiline R + EPL. + prompt> Sym + String + Struct â–ˆ + Symbol â–ˆ + StopIteratâ–ˆ + SystemCallâ–ˆ + SystemExitâ–ˆ + SystemStacâ–ˆ + ScriptErroâ–ˆ + SyntaxErroâ–ˆ + Signal â–ˆ + SizedQueueâ–ˆ + Set + SecureRand + Socket + StringIO + EOC + end + + def test_dialog_with_fullwidth_scrollbar + start_terminal(20, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple,scrollkey,alt-scrollbar}, startup_message: 'Multiline REPL.') + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> + Ruby is... :: + A dynamic, open source programming :: + language with a focus on simplicity'' + and productivity. It has an elegant + EOC + end + + def test_rerender_argument_prompt_after_pasting + start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write('abcdef') + write("\M-3\C-h") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> abc + EOC + end + + def test_autocomplete_old_dialog_width_greater_than_dialog_width + start_terminal(40, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-width-long}, startup_message: 'Multiline REPL.') + write("0+ \n12345678901234") + write("\C-p") + write("r") + write("a") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> 0+ ra + prompt> 123rand 901234 + raise + EOC + end + + def test_scroll_at_bottom_for_dialog + start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write("\n\n\n\n\n\n") + write("def hoge\n\n\n\n\n\n\nend\C-p\C-p\C-p\C-e") + write(" S") + close + assert_screen(<<~'EOC') + prompt> def hoge + prompt> + prompt> + prompt> + prompt> S + prompt> String + prompt> Struct + prompt> enSymbol + ScriptError + Signal + EOC + end + + def test_clear_dialog_in_pasting + start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write("S") + write("tring ") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> String + EOC + end + + def test_prompt_with_newline + ENV['RELINE_TEST_PROMPT'] = "::\n> " + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("def hoge\n 3\nend") + close + assert_screen(<<~'EOC') + Multiline REPL. + ::\n> def hoge + ::\n> 3 + ::\n> end + EOC + end + + def test_dynamic_prompt_with_newline + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt-with-newline}, startup_message: 'Multiline REPL.') + write("def hoge\n 3\nend") + close + assert_screen(<<~'EOC') + Multiline REPL. + [0000\n]> def hoge + [0001\n]> 3 + [0001\n]> end + EOC + end + + def write_inputrc(content) + File.open(@inputrc_file, 'w') do |f| + f.write content + end + end end rescue LoadError, NameError # On Ruby repository, this test suit doesn't run because Ruby repo doesn't diff --git a/ruby/test/resolv/test_addr.rb b/ruby/test/resolv/test_addr.rb index 14ec2651a..62092676b 100644 --- a/ruby/test/resolv/test_addr.rb +++ b/ruby/test/resolv/test_addr.rb @@ -16,6 +16,28 @@ def test_invalid_ipv4_address } end + def test_valid_ipv6_link_local_address + bug17112 = "[ruby-core:99539]" + assert_not_match(Resolv::IPv6::Regex, "fe80::1%", bug17112) + assert_not_match(Resolv::IPv6::Regex, "fe80:2:3:4:5:6:7:8%", bug17112) + assert_not_match(Resolv::IPv6::Regex, "fe90::1%em1", bug17112) + assert_not_match(Resolv::IPv6::Regex, "1:2:3:4:5:6:7:8%em1", bug17112) + assert_match(Resolv::IPv6::Regex, "fe80:2:3:4:5:6:7:8%em1", bug17112) + assert_match(Resolv::IPv6::Regex, "fe80::20d:3aff:fe7d:9760%eth0", bug17112) + assert_match(Resolv::IPv6::Regex, "fe80::1%em1", bug17112) + assert_match(Resolv::IPv6::Regex, "FE80:2:3:4:5:6:7:8%EM1", bug17112) + assert_match(Resolv::IPv6::Regex, "FE80::20D:3AFF:FE7D:9760%ETH0", bug17112) + assert_match(Resolv::IPv6::Regex, "FE80::1%EM1", bug17112) + end + + def test_valid_socket_ip_address_list + Socket.ip_address_list.each do |addr| + ip = addr.ip_address + assert_match(Resolv::AddressRegex, ip) + assert_equal(ip, Resolv.getaddress(ip)) + end + end + def test_invalid_byte_comment bug9273 = '[ruby-core:59239] [Bug #9273]' Tempfile.create('resolv_test_addr_') do |tmpfile| diff --git a/ruby/test/resolv/test_dns.rb b/ruby/test/resolv/test_dns.rb index 70d506775..5171604a8 100644 --- a/ruby/test/resolv/test_dns.rb +++ b/ruby/test/resolv/test_dns.rb @@ -3,7 +3,36 @@ require 'resolv' require 'socket' require 'tempfile' -require 'minitest/mock' + +class Object # :nodoc: + def stub name, val_or_callable, &block + new_name = "__minitest_stub__#{name}" + + metaclass = class << self; self; end + + if respond_to? name and not methods.map(&:to_s).include? name.to_s then + metaclass.send :define_method, name do |*args| + super(*args) + end + end + + metaclass.send :alias_method, new_name, name + + metaclass.send :define_method, name do |*args| + if val_or_callable.respond_to? :call then + val_or_callable.call(*args) + else + val_or_callable + end + end + + yield self + ensure + metaclass.send :undef_method, name + metaclass.send :alias_method, name, new_name + metaclass.send :undef_method, new_name + end unless method_defined?(:stub) # lib/rubygems/test_case.rb also has the same method definition +end class TestResolvDNS < Test::Unit::TestCase def setup @@ -128,6 +157,119 @@ def test_query_ipv4_address } end + def test_query_ipv4_duplicate_responses + begin + OpenSSL + rescue LoadError + skip 'autoload problem. see [ruby-dev:45021][Bug #5786]' + end if defined?(OpenSSL) + + with_udp('127.0.0.1', 0) {|u| + _, server_port, _, server_address = u.addr + begin + client_thread = Thread.new { + Resolv::DNS.open(:nameserver_port => [[server_address, server_port]], :search => ['bad1.com', 'bad2.com', 'good.com'], ndots: 5) {|dns| + dns.getaddress("example") + } + } + server_thread = Thread.new { + 3.times do + msg, (_, client_port, _, client_address) = Timeout.timeout(5) {u.recvfrom(4096)} + id, flags, qdcount, ancount, nscount, arcount = msg.unpack("nnnnnn") + + qr = (flags & 0x8000) >> 15 + opcode = (flags & 0x7800) >> 11 + aa = (flags & 0x0400) >> 10 + tc = (flags & 0x0200) >> 9 + rd = (flags & 0x0100) >> 8 + ra = (flags & 0x0080) >> 7 + z = (flags & 0x0070) >> 4 + rcode = flags & 0x000f + _rest = msg[12..-1] + + questions = msg.bytes[12..-1] + labels = [] + idx = 0 + while idx < questions.length-5 + size = questions[idx] + labels << questions[idx+1..idx+size].pack('c*') + idx += size+1 + end + hostname = labels.join('.') + + if hostname == "example.good.com" + id = id + qr = 1 + opcode = opcode + aa = 0 + tc = 0 + rd = rd + ra = 1 + z = 0 + rcode = 0 + qdcount = 1 + ancount = 1 + nscount = 0 + arcount = 0 + word2 = (qr << 15) | + (opcode << 11) | + (aa << 10) | + (tc << 9) | + (rd << 8) | + (ra << 7) | + (z << 4) | + rcode + msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn") + msg << questions.pack('c*') + type = 1 + klass = 1 + ttl = 3600 + rdlength = 4 + rdata = [52,0,2,1].pack("CCCC") + rr = [0xc00c, type, klass, ttl, rdlength, rdata].pack("nnnNna*") + msg << rr + rdata = [52,0,2,2].pack("CCCC") + rr = [0xc00c, type, klass, ttl, rdlength, rdata].pack("nnnNna*") + msg << rr + + u.send(msg, 0, client_address, client_port) + else + id = id + qr = 1 + opcode = opcode + aa = 0 + tc = 0 + rd = rd + ra = 1 + z = 0 + rcode = 3 + qdcount = 1 + ancount = 0 + nscount = 0 + arcount = 0 + word2 = (qr << 15) | + (opcode << 11) | + (aa << 10) | + (tc << 9) | + (rd << 8) | + (ra << 7) | + (z << 4) | + rcode + msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn") + msg << questions.pack('c*') + + u.send(msg, 0, client_address, client_port) + u.send(msg, 0, client_address, client_port) + end + end + } + result, _ = assert_join_threads([client_thread, server_thread]) + assert_instance_of(Resolv::IPv4, result) + assert_equal("52.0.2.1", result.to_s) + end + } + end + def test_query_ipv4_address_timeout with_udp('127.0.0.1', 0) {|u| _, port , _, host = u.addr @@ -155,6 +297,7 @@ def test_query_ipv4_address_timeout end def test_no_server + skip if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning u = UDPSocket.new u.bind("127.0.0.1", 0) _, port, _, host = u.addr diff --git a/ruby/test/rexml/data/LostineRiver.kml.gz b/ruby/test/rexml/data/LostineRiver.kml.gz deleted file mode 100644 index 68a00c51d..000000000 Binary files a/ruby/test/rexml/data/LostineRiver.kml.gz and /dev/null differ diff --git a/ruby/test/rexml/data/ProductionSupport.xml b/ruby/test/rexml/data/ProductionSupport.xml deleted file mode 100644 index 083cf64a6..000000000 --- a/ruby/test/rexml/data/ProductionSupport.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - >#error:]]> - - - - - Update Policy request 9997: Please check CICS log - - - - - MotorInsuranceContract(Object)>>#error: - - Have not got a complete - - - Have not got a complete and consistent set of price matrices for policy period - ask back-end prod supp to sort out - - - - - - diff --git a/ruby/test/rexml/data/axis.xml b/ruby/test/rexml/data/axis.xml deleted file mode 100644 index bc996c571..000000000 --- a/ruby/test/rexml/data/axis.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ruby/test/rexml/data/bad.xml b/ruby/test/rexml/data/bad.xml deleted file mode 100644 index 18786f2b4..000000000 --- a/ruby/test/rexml/data/bad.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Here is an XML document. - - It has some elements, but it also has a hidden < error! (or two) - diff --git a/ruby/test/rexml/data/basic.xml b/ruby/test/rexml/data/basic.xml deleted file mode 100644 index 88385fb6e..000000000 --- a/ruby/test/rexml/data/basic.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/ruby/test/rexml/data/basicupdate.xml b/ruby/test/rexml/data/basicupdate.xml deleted file mode 100644 index 57d458cf2..000000000 --- a/ruby/test/rexml/data/basicupdate.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Goudse kaas - Rond - - - - - - - More cheese! - - - - - Even more cheese! - - - - - No sausages today - - - - - - - - - - - - - - - - - - diff --git a/ruby/test/rexml/data/broken.rss b/ruby/test/rexml/data/broken.rss deleted file mode 100644 index d5f29e5d1..000000000 --- a/ruby/test/rexml/data/broken.rss +++ /dev/null @@ -1,20 +0,0 @@ - - - %HTMLlat1; -]> - - - - - O'Reilly Network Articles - http://www.oreillynet.com/ - - diff --git a/ruby/test/rexml/data/contents.xml b/ruby/test/rexml/data/contents.xml deleted file mode 100644 index 35e3ac704..000000000 --- a/ruby/test/rexml/data/contents.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - Java and XML - - - Introduction - - What Is It? - - - How Do I Use It? - - - Why Should I Use It? - - - What's Next? - - - - - Creating XML - An XML Document - The Header - The Content - What's Next? - - - - Parsing XML - Getting Prepared - SAX Readers - Content Handlers - Error Handlers - - A Better Way to Load a Parser - - "Gotcha!" - What's Next? - - - - - - Web Publishing Frameworks - Selecting a Framework - Installation - - Using a Publishing Framework - - XSP - Cocoon 2.0 and Beyond - What's Next? - - - diff --git a/ruby/test/rexml/data/dash.xml b/ruby/test/rexml/data/dash.xml deleted file mode 100644 index e1be65575..000000000 --- a/ruby/test/rexml/data/dash.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - content-1-text - - - content-2-text - - - content-3-text - - diff --git a/ruby/test/rexml/data/defaultNamespace.xml b/ruby/test/rexml/data/defaultNamespace.xml deleted file mode 100644 index 1e3298150..000000000 --- a/ruby/test/rexml/data/defaultNamespace.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - Hello - - diff --git a/ruby/test/rexml/data/doctype_test.xml b/ruby/test/rexml/data/doctype_test.xml deleted file mode 100644 index a690cab99..000000000 --- a/ruby/test/rexml/data/doctype_test.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]> - diff --git a/ruby/test/rexml/data/documentation.xml b/ruby/test/rexml/data/documentation.xml deleted file mode 100644 index a1ad6e878..000000000 --- a/ruby/test/rexml/data/documentation.xml +++ /dev/null @@ -1,542 +0,0 @@ - - - - - - - - REXML - - - - @ANT_VERSION@ - - @ANT_DATE@ - - http://www.germane-software.com/software/rexml - - rexml - - ruby - - Sean - Russell - - - - -

      REXML is a conformant XML processor for the Ruby programming - language. REXML passes 100% of the Oasis non-validating tests and - includes full XPath support. It is reasonably fast, and is implemented - in pure Ruby. Best of all, it has a clean, intuitive API. REXML is - included in the standard library of Ruby

      - -

      This software is distribute under the Ruby - license.

      -
      - - -

      REXML arose out of a desire for a straightforward XML API, and is an - attempt at an API that doesn't require constant referencing of - documentation to do common tasks. "Keep the common case simple, and the - uncommon, possible."

      - -

      REXML avoids The DOM API, which violates the maxim of simplicity. It - does provide a DOM model, but one that is Ruby-ized. It is an - XML API oriented for Ruby programmers, not for XML programmers coming - from Java.

      - -

      Some of the common differences are that the Ruby API relies on block - enumerations, rather than iterators. For example, the Java code:

      - - for (Enumeration e=parent.getChildren(); e.hasMoreElements(); ) { - Element child = (Element)e.nextElement(); // Do something with child -} - -

      in Ruby becomes:

      - - parent.each_child{ |child| # Do something with child } - -

      Can't you feel the peace and contentment in this block of code? Ruby - is the language Buddha would have programmed in.

      - -

      One last thing. If you use and like this software, and you're in a - position of power in a company in Western Europe and are looking for a - software architect or developer, drop me a line. I took a lot of French - classes in college (all of which I've forgotten), and I lived in Munich - long enough that I was pretty fluent by the time I left, and I'd love to - get back over there.

      -
      - - - Four intuitive parsing APIs. - - Intuitive, powerful, and reasonably fast tree parsing API (a-la - DOM - - Fast stream parsing API (a-la SAX)This is not a SAX - API. - - SAX2-based APIIn addition to the native REXML streaming - API. This is slower than the native REXML API, but does a lot more work - for you. - - Pull parsing API. - - Small - - Reasonably fast (for interpreted code) - - Native Ruby - - Full XPath supportCurrently only available for the tree - API - - XML 1.0 conformantREXML passes all of the non-validating - OASIS tests. There are probably places where REXML isn't conformant, but - I try to fix them as they're reported. - - ISO-8859-1, UNILE, UTF-16 and UTF-8 input and output; also, - support for any encoding the iconv supports. - - Documentation - -
      - - - -

      You don't have to install anything; if you're running a - version of Ruby greater than 1.8, REXML is included. However, if you - choose to upgrade from the REXML distribution, run the command: - ruby bin/install.rb. By the way, you really should look at - these sorts of files before you run them as root. They could contain - anything, and since (in Ruby, at least) they tend to be mercifully - short, it doesn't hurt to glance over them. If you want to uninstall - REXML, run ruby bin/install.rb -u.

      -
      - - -

      If you have Test::Unit installed, you can run the unit test cases. - Run the command: ruby bin/suite.rb; it runs against the - distribution, not against the installed version.

      -
      - - -

      There is a benchmark suite in benchmarks/. To run the - benchmarks, change into that directory and run ruby - comparison.rb. If you have nothing else installed, only the - benchmarks for REXML will be run. However, if you have any of the - following installed, benchmarks for those tools will also be run:

      - - - NQXML - - XMLParser - - Electric XML (you must copy EXML.jar into the - benchmarks directory and compile - flatbench.java before running the test) - - -

      The results will be written to index.html.

      -
      - - -

      Please see the Tutorial.

      - -

      The API documentation is available on-line, - or it can be downloaded as an archive in - tgz format (~70Kb) or (if you're a masochist) in - zip format (~280Kb). The best solution is to download and install - Dave Thomas' most excellent rdoc and generate the API docs - yourself; then you'll be sure to have the latest API docs and won't have - to keep downloading the doc archive.

      - -

      The unit tests in test/ and the benchmarking code in - benchmark/ provide additional examples of using REXML. The - Tutorial provides examples with commentary. The documentation unpacks - into rexml/doc.

      - -

      Kouhei Sutou maintains a Japanese - version of the REXML API docs. Kou's - documentation page contains links to binary archives for various - versions of the documentation.

      -
      -
      - - - -

      Unfortunately, NQXML is the only package REXML can be compared - against; XMLParser uses expat, which is a native library, and really is - a different beast altogether. So in comparing NQXML and REXML you can - look at four things: speed, size, completeness, and API.

      - -

      Benchmarks

      - -

      REXML is faster than NQXML in some things, and slower than NQXML in a - couple of things. You can see this for yourself by running the supplied - benchmarks. Most of the places where REXML are slower are because of the - convenience methodsFor example, - element.elements[index] isn't really an array operation; - index can be an Integer or an XPath, and this feature is relatively time - expensive.. On the positive side, most of the convenience - methods can be bypassed if you know what you are doing. Check the benchmark comparison page for a - general comparison. You can look at the benchmark code yourself - to decide how much salt to take with them.

      - -

      The sizes of the XML parsers are closeAs measured with - ruby -nle 'print unless /^\s*(#.*|)$/' *.rb | wc -l - . NQXML 1.1.3 has 1580 non-blank, non-comment lines of code; - REXML 2.0 has 2340REXML started out with about 1200, but that - number has been steadily increasing as features are added. XPath - accounts for 541 lines of that code, so the core REXML has about 1800 - LOC..

      - -

      REXML is a conformant XML 1.0 parser. It supports multiple language - encodings, and internal processing uses the required UTF-8 and UTF-16 - encodings. It passes 100% of the Oasis non-validating tests. - Furthermore, it provides a full implementation of XPath, a SAX2 and a - PullParser API.

      -
      - - -

      As of release 2.0, XPath 1.0 is fully implemented.

      - -

      I fully expect bugs to crop up from time to time, so if you see any - bogus XPath results, please let me know. That said, since I'm now - following the XPath grammar and spec fairly closely, I suspect that you - won't be surprised by REXML's XPath very often, and it should become - rock solid fairly quickly.

      - -

      Check the "bugs" section for known problems; there are little bits of - XPath here and there that are not yet implemented, but I'll get to them - soon.

      - -

      Namespace support is rather odd, but it isn't my fault. I can only do - so much and still conform to the specs. In particular, XPath attempts to - help as much as possible. Therefore, in the trivial cases, you can pass - namespace prefixes to Element.elements[...] and so on -- in these cases, - XPath will use the namespace environment of the base element you're - starting your XPath search from. However, if you want to do something - more complex, like pass in your own namespace environment, you have to - use the XPath first(), each(), and match() methods. Also, default - namespaces force you to use the XPath methods, rather than the - convenience methods, because there is no way for XPath to know what the - mappings for the default namespaces should be. This is exactly why I - loath namespaces -- a pox on the person(s) who thought them up!

      -
      - - -

      Namespace support is now fairly stable. One thing to be aware of is - that REXML is not (yet) a validating parser. This means that some - invalid namespace declarations are not caught.

      -
      - - -

      There is a low-volume mailing list dedicated to REXML. To subscribe, - send an empty email to ser-rexml-subscribe@germane-software.com. - This list is more or less spam proof. To unsubscribe, similarly send a - message to ser-rexml-unsubscribe@germane-software.com.

      -
      - - -

      An RSS - file for REXML is now being generated from the change log. This - allows you to be alerted of bug fixes and feature additions via "pull". - Another - RSS is available which contains a single item: the release notice - for the most recent release. This is an abuse of the RSS - mechanism, which was intended to be a distribution system for headlines - linked back to full articles, but it works. The headline for REXML is - the version number, and the description is the change log. The links all - link back to the REXML home page. The URL for the RSS itself is - http://www.germane-software.com/software/rexml/rss.xml.

      - -

      The changelog itself is here.

      - -

      For those who are interested, there's a SLOCCount (by David A. Wheeler) file - with stats on the REXML sourcecode. Note that the SLOCCount output - includes the files in the test/, benchmarks/, and bin/ directories, as - well as the main sourcecode for REXML itself.

      -
      - - - - Raggle is a - console-based RSS aggregator. - - getrss - is an RSS aggregator - - Ned Konz's ruby-htmltools - uses REXML - - Hiroshi NAKAMURA's SOAP4R - package can use REXML as the XML processor. - - Chris Morris' XML - Serializer. XML Serializer provides a serialization mechanism - for Ruby that provides a bidirectional mapping between Ruby classes - and XML documents. - - Much of the RubyXML - site is generated with scripts that use REXML. RubyXML is a great - place to find information about th intersection between Ruby and - XML. - - - - -

      You can submit bug reports and feature requests, and view the list of - known bugs, at the REXML bug report - page. Please do submit bug reports. If you really want your bug - fixed fast, include an runit or Test::Unit method (or methods) that - illustrates the problem. At the very least, send me some XML that REXML - doesn't process properly.

      - -

      You don't have to send an entire test suite -- just the unit test - methods. If you don't send me a unit test, I'll have to write one - myself, which will mean that your bug will take longer to fix.

      - -

      When submitting bug reports, please include the version of Ruby and - of REXML that you're using, and the operating system you're running on. - Just run: ruby -vrrexml/rexml -e 'p - REXML::VERSION,PLATFORM' and paste the results in your bug - report. Include your email if you want a response about the bug.

      - - Attributes are not handled internally as nodes, so you can't - perform node functions on them. This will have to change. It'll also - probably mean that, rather than returning attribute values, XPath will - return the Attribute nodes. - - Some of the XPath functions are untestedMike - Stok has been testing, debugging, and implementing some of these - Functions (and he's been doing a good job) so there's steady improvement - in this area.. Any XPath functions that don't work are also - bugs... please report them. If you send a unit test that illustrates the - problem, I'll try to fix the problem within a couple of days (if I can) - and send you a patch, personally. - - Accessing prefixes for which there is no defined namespace in an - XPath should throw an exception. It currently doesn't -- it just fails - to match. -
      - - - Reparsing a tree with a pull/SAX parser - - Better namespace support in SAX - - Lazy tree parsing - - Segregate parsers, for optimized minimal distributions - - XML <-> Ruby - - Validation support - - True XML character support - - Add XPath support for streaming APIs - - XQuery support - - XUpdate support - - Make sure namespaces are supported in pull parser - - Add document start and entity replacement events - in pull parser - - Better stream parsing exception handling - - I'd like to hack XMLRPC4R to use REXML, for my own - purposes. - -
      - - - REXML is hanging while parsing one of my XML files. - - Your XML is probably malformed. Some malformed XML, especially XML that - contains literal '<' embedded in the document, causes REXML to hang. - REXML should be throwing an exception, but it doesn't; this is a bug. I'm - aware that it is an extremely annoying bug, and it is one I'm trying to - solve in a way that doesn't significantly reduce REXML's parsing - speed. - - I'm using the XPath '//foo' on an XML branch node X, and keep getting - all of the 'foo' elements in the entire document. Why? Shouldn't it return - only the 'foo' element descendants of X? - - No. XPath specifies that '/' returns the document root, regardless of - the context node. '//' also starts at the document root. If you want to - limit your search to a branch, you need to use the self:: axe. EG, - 'self::node()//foo', or the shorthand './/foo'. - - I want to parse a document both as a tree, and as a stream. Can I do - this? - - Yes, and no. There is no mechanism that directly supports this in - REXML. However, aside from writing your own traversal layer, there is a - way of doing this. To turn a tree into a stream, just turn the branch you - want to process as a stream back into a string, and re-parse it with your - preferred API. EG: pp = PullParser.new( some_element.to_s ). The other - direction is more difficult; you basically have to build a tree from the - events. REXML will have one of these builders, eventually, but it doesn't - currently exist. - - Why is Element.elements indexed off of '1' instead of '0'? - - Because of XPath. The XPath specification states that the index of the - first child node is '1'. Although it may be counter-intuitive to base - elements on 1, it is more undesireable to have element.elements[0] == - element.elements[ 'node()[1]' ]. Since I can't change the XPath - specification, the result is that Element.elements[1] is the first child - element. - - Why isn't REXML a validating parser? - - Because validating parsers must include code that parses and interprets - DTDs. I hate DTDs. REXML supports the barest minimum of DTD parsing, and - even that isn't complete. There is DTD parsing code in the works, but I - only work on it when I'm really, really bored. Rumor has it that a - contributor is working on a DTD parser for REXML; rest assured that any - such contribution will be included with REXML as soon as it is - available. - - I'm trying to create an ISO-8859-1 document, but when I add text to the - document it isn't being properly encoded. - - Regardless of what the encoding of your document is, when you add text - programmatically to a REXML document you must ensure that you are - only adding UTF-8 to the tree. In particular, you can't add ISO-8859-1 - encoded text that contains characters above 0x80 to REXML trees -- you - must convert it to UTF-8 before doing so. Luckily, this is easy: - text.unpack('C*').pack('U*') will do the trick. 7-bit ASCII - is identical to UTF-8, so you probably won't need to worry about this. - - How do I get the tag name of an Element? - - You take a look at the APIs, and notice that Element - includes Namespace. Then you click on the - Namespace link and look at the methods that - Element includes from Namespace. One of these is - name(). Another is expanded_name(). Yet another - is prefix(). Then, you email the author of rdoc and ask him - to extend rdoc so that it lists methods in the API that are included from - other files, so that you don't have to do all of that looking around for - your method. - - - -

      I've had help from a number of resources; if I haven't listed you here, - it means that I just haven't gotten around to adding you, or that I'm a - dork and have forgotten. In either case, feel free to write me and - complain.

      - - - Mike Stok has been very active, sending not only fixes for bugs - (especially in Functions), but also by providing unit tests and making - sure REXML runs under Ruby 1.7. He also sent the most awesome hand - knitted tea cozy, with "REXML" and the Ruby knitted into it. - - Kouhei Sutou translated the REXML API documentation to Japanese! - Links are in the API docs section of the main documentation. He has also - contributed a large number of bug reports and patches to fix bugs in - REXML. - - Erik Terpstra heard my pleas and submitted several logos for - REXML. After sagely procrastinating for several weeks, I finally forced - my poor slave of a wife to pick one (this is what we call "delegation"). - She did, with caveats; Erik quickly made the changes, and the result is - what you now see at the top of this page. He also supplied a smaller version that you can include - with your projects that use REXML, if you'd like. - - Ernest Ellingson contributed the sourcecode for turning UTF16 and - UNILE encodings into UTF8, which allowed REXML to get the 100% OASIS - valid tests rating. - - Ian Macdonald provided me with a comprehensive, well written RPM - spec file. - - Oliver M . Bolzer is maintaining a Debian package distribution of - REXML. He also has provided good feedback and bug reports about - namespace support. - - Michael Granger supplied a patch for REXML that make the unit - tests pass under Ruby 1.7. - - James Britt contributed code that makes using - Document.parse_stream easier to use by allowing it to be passed either a - Source, File, or String. - - Tobias Reif: Numerous bug reports, and suggestions for - improvement. - - Stefan Scholl, who provided a lot of feedback and bug reports - while I was trying to get ISO-8859-1 support working. - - Steven E Lumos for volunteering information about XPath - particulars. - - Fumitoshi UKAI provided some bug fixes for CData metacharacter - quoting. - - TAKAHASHI Masayoshi, for information on UTF - - Robert Feldt: Bug reports and suggestions/recommendations about - improving REXML. Testing is one of the most important aspects of - software development. - - Electric - XML: This was, after all, the inspiration for REXML. Originally, - I was just going to do a straight port, and although REXML doesn't in - any way, shape or form resemble Electric XML, still the basic framework - and philosophy was inspired by E-XML. And I still use E-XML in my Java - projects. - - NQXML: - While I may complain about the NQXML API, I wrote a few applications - using it that wouldn't have been written otherwise, and it was very - useful to me. It also encouraged me to write REXML. Never complain about - free software *slap*. - - See my technologies - page for a more comprehensive list of computer technologies that - I depend on for my day-to-day work. - - rdoc, an excellent JavaDoc analogWhen I was first - working on REXML, rdoc wasn't, IMO, very good, so I wrote API2XML. - API2XML was good enough for a while, and then there was a flurry of work - on rdoc, and it quickly surpassed API2XML in features. Since I was never - really interested in maintaining a JavaDoc analog, I stopped support of - API2XML, and am now recommending that people use - rdoc.. - - Many, many other people who've submitted bug reports, suggestions, - and positive feedback. You're all co-developers! - -
      -
      diff --git a/ruby/test/rexml/data/euc.xml b/ruby/test/rexml/data/euc.xml deleted file mode 100644 index a3c341949..000000000 --- a/ruby/test/rexml/data/euc.xml +++ /dev/null @@ -1,296 +0,0 @@ - - - - - - - - - -Ruby-mswin32 - - - -

      Ruby-mswin32

      -

      ¤¢¤ë¤¤¤Ï¡¢Windows¤È¤Î½ª¤ï¤ê¤Ê¤­À襤 ;-(

      -

      [ÆüËܸì / English]

      - - - -

      ¢§ Ìܼ¡

      - - - - -

      ¢§ Ãí°Õ»ö¹à

      -

      ¤³¤Î¥Ú¡¼¥¸¤Ç¤Ï¡¢mswin32ÈÇruby¤ÎÇÛÉÛ¤ÈÊѹ¹¾õ¶·¤Î¤ªÃΤ餻¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£

      -

      ¤³¤³¤ÏÊ̤˸ø¼°¥Ú¡¼¥¸¤Ç¤â¤Ê¤ó¤Ç¤â¤Ê¤¯¤Æ¡¢»ä¤¬¾¡¼ê¤Ë½ñ¤¤¤Æ¤ë¥Ú¡¼¥¸¤Ç¤¹¡£¤³¤³¤ÇÆþ¼ê¤Ç¤­¤ë¥×¥í¥°¥é¥à¡¦¾ðÊó(̵¤¤¤ËÅù¤·¤¤¤±¤É)¤Ë¤Ä¤¤¤Æ¤Ï¡¢³Æ¼«¤ÎȽÃǤǤ´ÍøÍѤ¯¤À¤µ¤¤¡£
      -Ì䤤¹ç¤ï¤»¤Ï»ä¤Ø¡£´Ö°ã¤Ã¤Æ¤â¾¤Î¿Í¤ËÌÂÏǤò¤«¤±¤ë¤è¤¦¤Ê¤³¤È¤Ï¤·¤Ê¤¤¤Ç¤Í¡£

      - - - -

      ¢§ Ruby¤È¤Ï?

      -

      Ruby¤Î¥µ¥¤¥È¤ò¤´Í÷²¼¤µ¤¤¡£

      - - - -

      ¢§ mswin32ÈÇruby¤È¤Ï?

      -

      mswin32ÈÇruby¤È¤Ï¡¢32bitÈÇWindows(Windows95¡¦Windows98¡¦WindowsMe¡¦Windows NT¡¦Windows 2000¡¦WindowsXP¡¦Windows 2003 Server¡¢°Ê²¼Windows¤Èɽµ­)¾å¤Çưºî¤¹¤ëRuby¤Î¥Ð¥¤¥Ê¥ê¤Î°ì¤Ä¤Ç¤¹¡£
      -Windows¾å¤Çưºî¤¹¤ëRuby¤È¤·¤Æ¤Ï¡¢¸½ºß¡¢5¼ïÎà¤Î¥Ð¥¤¥Ê¥ê¤¬Â¸ºß¤·¤Þ¤¹¡£¤³¤ì¤é¤Ï¤½¤ì¤¾¤ìmswin32ÈÇ¡¦cygwinÈÇ¡¦mingw32ÈÇ¡¦bccwin32ÈÇ¡¦djgppÈÇ¤È¸Æ¤Ð¤ì¤Æ¤¤¤Þ¤¹¡£
      -¤½¤ì¤¾¤ì¤Î°ã¤¤¤ò¤Þ¤È¤á¤ë¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹(»ö¼Â¸íǧ¤¬¤¢¤ì¤Ð¤ªÃΤ餻¤¯¤À¤µ¤¤)¡£

      -
      -
      mswin32ÈÇ
      -

      VC++¤Ç¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤ë¡£Windows¤«¤é¸«¤ì¤Ð¤â¤Ã¤È¤â¡ÖÉáÄ̡פΥХ¤¥Ê¥ê¤È¸À¤¨¤ë¤¬¡¢È¿ÌÌ¡¢Ruby¤¬»ý¤ÄUNIX¤ÇÆÃħŪ¤Êµ¡Ç½¤Î°ìÉô¤¬»ÈÍѤǤ­¤Ê¤¤¡£1.7.3°Ê¹ß¤Ïmingw32ÈǤȳÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï¥Ð¥¤¥Ê¥ê¸ß´¹À­¤¬¤¢¤ë¡£
      -RUBY_PLATFORM¤Ï*-mswin32¡£

      -
      -
      cygwinÈÇ
      -

      gcc¤Ç¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¡¢cygwin´Ä¶­¤Çưºî¤¹¤ë¡£cygwin´Ä¶­¤¬UNIX¥é¥¤¥¯¤Ê´Ä¶­¤òWindows¾å¤Ç¹½ÃÛ¤¹¤ë¤â¤Î¤Ç¤¢¤ë¤Î¤Ç¡¢ÅöÁ³¡¢cygwinÈÇruby¤Ï°ìÈ̤ÎUNIXÍѤΤâ¤Î¤È¤À¤¤¤¿¤¤Æ±¤¸¤è¤¦¤Ëưºî¤¹¤ë(¤³¤È¤¬´üÂԤǤ­¤ë)¡£
      -RUBY_PLATFORM¤Ï*-cygwin¡£

      -
      -
      mingw32ÈÇ
      -

      gcc¤Ç¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤ë¡£¥½¡¼¥¹¤Ï¤Û¤È¤ó¤Émswin32ÈǤȶ¦Ä̤Ǥ¢¤ê¡¢¥é¥ó¥¿¥¤¥à¥é¥¤¥Ö¥é¥ê¤â¶¦ÄÌ(MSVCRT.dll)¤Ê¤Î¤Ç¡¢Æ°ºî¤â(¤ª¤½¤é¤¯)mswin32ÈÇ¤È¤Û¤ÜÆ±¤¸¡£1.7.3°Ê¹ß¤Ïmswin32ÈǤȳÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï¥Ð¥¤¥Ê¥ê¸ß´¹À­¤¬¤¢¤ë¡£
      -RUBY_PLATFORM¤Ï*-mingw32¡£

      -
      -
      bccwin32ÈÇ
      -

      BC++¤Ç¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤ë¡£¥½¡¼¥¹¤Ï¤«¤Ê¤ê¤ÎÉôʬ¤¬mswin32ÈǤȶ¦Ä̤ǤϤ¢¤ë¤¬¡¢¥é¥ó¥¿¥¤¥à¥é¥¤¥Ö¥é¥ê¤¬°Û¤Ê¤ë¤Î¤Ç¡¢ºÙ¤«¤¤¤È¤³¤í¤Çµóư¤¬mswin32ÈǤȤϰۤʤë(¤Ï¤º)¡£1.7°Ê¹ß¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤ë¡£
      -RUBY_PLATFORM¤Ï*-bccwin32¡£

      -
      -
      djgppÈÇ
      -

      DJGPP¤Ç¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤ë¡£DOSÍѤΥХ¤¥Ê¥ê¤Ê¤Î¤Ç¡¢¤â¤Á¤í¤óDOS¤Ç¤âưºî¤¹¤ë¡£È¿ÌÌ¡¢Windows¤Ë¤¢¤Ã¤ÆDOS¤Ë¤Ê¤¤µ¡Ç½¤Î¿¤¯¤¬»È¤¨¤Ê¤¤(¥Í¥Ã¥È¥ï¡¼¥¯´ØÏ¢¤Ê¤É)¡£
      -RUBY_PLATFORM¤Ï*-msdosdjgpp¡£

      -
      -
      -

      ¤³¤Î¥Ú¡¼¥¸¤Ç¤Ï¡¢¾åµ­¤Î¤¦¤Ámswin32ÈǤΤߤò°·¤Ã¤Æ¤¤¤Þ¤¹¡£
      -¤Ê¤ª¡¢cygwinÈÇ¡¦mingw32ÈÇ¡¦djgppÈǤˤĤ¤¤Æ¤Ï¤ï¤¿¤Ê¤Ù¤µ¤ó¤ÎRuby binaries¤«¤éÆþ¼ê²Äǽ¤Ç¤¹¡£¤Þ¤¿¡¢bccwin32ÈǤˤĤ¤¤Æ¤Ï¾®À¾¤µ¤ó¤ÎRuby¤«¤éÆþ¼ê²Äǽ¤Ç¤¹¡£

      - - - -

      ¢§ ¥Ð¥¤¥Ê¥ê ¥À¥¦¥ó¥í¡¼¥É

      -

      ¸½ºßÇÛÉÛÃæ¤ÎÁ´¤Æ¤Î¥Ð¥¤¥Ê¥ê¤ÏVC++ 5.0(Version 11.00.7022 for 80x86)¤Çmake¤·¤¿¤â¤Î¤Ç¤¹¡£ruby¼«ÂΤ˴ؤ·¤Æ¤Ï¡¢É¸½àÇÛÉۤΥ½¡¼¥¹(¤Þ¤¿¤ÏCVS¤Î¥½¡¼¥¹)¤«¤é¤½¤Î¤Þ¤ÞºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï³Æ¡¹¤Î¥ê¥ó¥¯Àè¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£
      -¤¤¤º¤ì¤Î¥Ð¥¤¥Ê¥ê¤âzip·Á¼°¤Ç¥¢¡¼¥«¥¤¥Ö¤µ¤ì¤Æ¤¤¤Þ¤¹¡£

      -

      md5sum¤Î¥Á¥§¥Ã¥¯ÊýË¡¤Ç¤¹¤¬¡¢Î㤨¤Ðruby¤¬¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤Ê¤é²¼µ­¤Î¤è¤¦¤ÊÊýË¡¤¬¤¢¤ê¤Þ¤¹¡£
      -ruby -r md5 -e "puts MD5.new(File.open('filename', 'rb').read).hexdigest"

      - - - -

      Release

      - - - - - - - - -

      Developing versions snapshots

      - - - - -

      Stable versions snapshots

      -

      1.8.0

      - -

      1.6.8

      - - - - -

      Extension libraries

      -

      1.8.0

      - -

      1.6.8

      - - - - -

      ¢§ ¥¤¥ó¥¹¥È¡¼¥ë

      -

      ¾åµ­¤Î¥Ð¥¤¥Ê¥ê¤ò¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¾ì¹ç¤Ï¡¢¤ª¹¥¤ß¤Î¥Ç¥£¥ì¥¯¥È¥ê(°Ê²¼$TOPDIR¤Èµ­½Ò)¤ËŸ³«¤·¤Æ¤¯¤À¤µ¤¤¡£¥Ç¥£¥ì¥¯¥È¥êÉÕ¤­¤Ç°µ½Ì¤µ¤ì¤Æ¤Þ¤¹¤Î¤Ç¡¢Å¸³«»þ¤Ë¤Ï¥Ç¥£¥ì¥¯¥È¥êÉÕ¤­¤ÇŸ³«¤¹¤ë¤Î¤ò˺¤ì¤º¤Ë(°ÕÌ£¤¬¤ï¤«¤é¤Ê¤¤¿Í¤Ïµ¤¤Ë¤·¤Ê¤¯¤Æ¤¤¤¤¤Ç¤¹)¡£
      -Ÿ³«¸å¤Ï¡¢$TOPDIR\bin¤ËPATH¤òÄ̤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡£

      -

      ¤Ê¤ª¡¢°Ê²¼¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ï¡¢¤³¤ÎÇÛÉÛʪ¤Ë´Þ¤Þ¤ì¤Ê¤¤³°Éô¤Î¥é¥¤¥Ö¥é¥ê¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£

      -
        -
      • curses.so : PDCurses¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • dbm.so : GDBM¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • gdbm.so : GDBM¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • iconv.so : Iconv¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • openssl.so : OpenSSL¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • readline.so : readline¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • tcltklib.so : Tcl/Tk¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      • zlib.so : Zlib¤Ë°Í¸¤·¤Æ¤¤¤Þ¤¹¡£
      • -
      -

      ¾åµ­¤Î¤¦¤Á¡¢PDCurses¡¦GDBM¡¦OpenSSL¡¦readline¡¦Zlib¤Ë¤Ä¤¤¤Æ¤Ï¡¢Porting Libraries to Win32¤Ë¥Ð¥¤¥Ê¥ê¤¬Â¸ºß¤·¤Þ¤¹¡£
      -Iconv¤Ë¤Ä¤¤¤Æ¤Ï¡¢Meadowy.org¤ÇÇÛÉÛ¤µ¤ì¤Æ¤¤¤ëiconv-1.8.win32.zip¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹¡£
      -Tcl/Tk¤Ë¤Ä¤¤¤Æ¤Ï¡¢ActiveState¤ÇÇÛÉÛ¤µ¤ì¤Æ¤¤¤ëActiveTcl¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹¡£

      - - - -

      ¢§ ºÇ¶á¤Î½ÐÍè»ö

      - - - -

      2004-01-27

      -

      ¤¢¤±¤Þ¤·¤Æ¤ª¤á¤Ç¤È¤¦¤´¤¶¤¤¤Þ¤¹¡£¤Ã¤ÆÃÙ¤¤¤è!

      -

      ruby-1.8.1-20040127¤Èruby-1.9.0-20040126¤òÃÖ¤­¤Þ¤·¤¿¡£
      -Á°¼Ô¤Ï¼ç¤Ë1.8.1¥ê¥ê¡¼¥¹ÈǤÇȯ¸«¤µ¤ì¤¿ÉÔ¶ñ¹ç¤Î½¤Àµ¤Ç¤¹¡£¸å¼Ô¤Ï³«È¯ÈÇ¡£

      - -

      2003-12-25

      -

      ¥á¥ê¡¼¥¯¥ê¥¹¥Þ¥¹! ruby-1.8.1¤¬¥ê¥ê¡¼¥¹¤µ¤ì¤Þ¤·¤¿!
      -(preview¤ò°ì¤ÄÈô¤Ð¤·¤Á¤ã¤¤¤Þ¤·¤¿¡¢¤´¤á¤ó¤Ê¤µ¤¤...)

      - -

      2003-12-06

      -

      ruby-1.8.1-preview3¤òÃÖ¤­¤Þ¤·¤¿¡£»×¤¤¤Î¤Û¤«´Ö¤¬¶õ¤¤¤Á¤ã¤¤¤Þ¤·¤¿¤Í¡£

      - -

      2003-11-01

      -

      ruby-1.8.1-preview2¤òÃÖ¤­¤Þ¤·¤¿¡£

      - -

      2003-10-28

      -

      ruby-1.8.1-20031027¤òÃÖ¤­¤Þ¤·¤¿¡£
      -racc-1.4.4-all¤òÃÖ¤­¤Þ¤·¤¿¡£

      - -

      2003-09-07

      -

      eruby-1.0.4¡¦vrswin-030906¡¦vruby-030906¤òÃÖ¤­¤Þ¤·¤¿¡£

      - -

      2003-08-12

      -

      ruby-1.8.0-20030812¤òÃÖ¤­¤Þ¤·¤¿¡£

      -

      vrswin-030811¡¦vruby-030811¤òÃÖ¤­¤Þ¤·¤¿¡£º£²ó¤«¤éÃÖ¤¯³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÏÁ´¤Æ1.8ÍѤˤʤê¤Þ¤¹¡£

      - -

      2003-08-04

      -

      ruby-1.8.0¤òÃÖ¤­¤Þ¤·¤¿¡£Ruby 1.8·ÏºÇ½é¤Î¥ê¥ê¡¼¥¹¤È¤Ê¤ê¤Þ¤¹¡£
      -1.6·Ï¤«¤é¤ÎÊѹ¹ÅÀ¤Ë¤Ä¤¤¤Æ¤Ï¡¢changes.1.8.0¤Ê¤É¤ò¤´Í÷¤¯¤À¤µ¤¤¡£

      - -

      2003-07-31

      -

      ruby-1.8.0-preview6¤òÃÖ¤­¤Þ¤·¤¿¡£¤¨¡¼¤È¡¢¤³¤ì¤ò´Þ¤á¤Æ¤¢¤È2²ópreview¤¬½Ð¤ëÌÏÍͤǤ¹ :)

      - -

      2003-07-28

      -

      ruby-1.8.0-preview5¤òÃÖ¤­¤Þ¤·¤¿¡£¤ª¤½¤é¤¯¤³¤ì¤¬1.8.0¤ÎºÇ¸å¤Îpreview¤Ë¤Ê¤ë¤Ç¤·¤ç¤¦¡£
      -ruby-1.6.8-20030727¤òÃÖ¤­¤Þ¤·¤¿¡£

      - - - -

      ¤«¤Ä¤Æ¤Î½ÐÍè»ö

      -

      ¤³¤Á¤é¤ò¤É¤¦¤¾¡£

      - - - -

      ¢§ ¥ê¥ó¥¯

      -

      mswin32ÈǤ˴ؤ¹¤ë(¤È»×¤ï¤ì¤ë)¥ê¥ó¥¯¤Ç¤¹¡£¾¡¼ê¤ËÄ¥¤Ã¤Æ¤Þ¤¹¤Î¤Ç¡¢ÉÔÅԹ礬¤¢¤ì¤Ð»ä¤Þ¤Ç¤´Ï¢Íí¤¯¤À¤µ¤¤¡£

      -
        -
      • Ruby Home Page (ÆüËܸì / English)
        - ¸À¤ï¤º¤È¤·¤ì¤¿¡¢Ëܲȥµ¥¤¥È¡£
      • -
      • »¨µ­Ä¢ (ÆüËܸì / English)
        - ½õÅĤµ¤ó¤Î¥Ú¡¼¥¸¡£RubWin¡¦Win32OLE¤Ê¤É¤¬¤¢¤ê¤Þ¤¹¡£
      • -
      • Script/Ruby (ÆüËܸì)
        - MoonWolf¤µ¤ó¤Î¥Ú¡¼¥¸¡£Win32Module¤Ê¤É¤¬¤¢¤ê¤Þ¤¹¡£
      • -
      • ActiveScriptRuby (ÆüËܸì / English)
        - arton¤µ¤ó¤Î¥Ú¡¼¥¸¡£WindowsÈÇRuby¤Î̤Íè¤Ï¤³¤³¤Ë¤¢¤ë¤Î¤«¤â¡£
      • -
      • VisualuRuby·×²è(²¾¾Î) (ÆüËܸì / English)
        - nyasu¤µ¤ó¤Î¥Ú¡¼¥¸¡£VisualuRuby¤Ê¤É¤¬¤¢¤ê¤Þ¤¹(¤Ã¤Æ¤³¤ì¤â¤½¤Î¤Þ¤ó¤Þ)¡£Windows¤ÇRuby¤ò»È¤¦¤¿¤á¤Î¥ê¥ó¥¯½¸¤¬½¼¼Â¤·¤Æ¤Þ¤¹¡£¤Á¤Ê¤ß¤Ë¡¢Åö¥µ¥¤¥È¤Î¥Ç¥¶¥¤¥ó¤Ï¤³¤Á¤é¤Î¥Ñ¥¯¥ê¤Ç¤¹¡£Â¿¼Õ!
      • -
      • Ruby (ÆüËܸì / English)
        - ¤è¤·¤À¤à¤µ¤ó¤Î¥Ú¡¼¥¸¡£Susie¥×¥é¥°¥¤¥ó¥é¥¤¥Ö¥é¥ê¤äDirectDraw for Ruby¤Ê¤É¤¬¤¢¤ê¤Þ¤¹¡£
      • -
      • RDE(Ruby Development Environment) (ÆüËܸì)
        - sakazuki¤µ¤ó¤Î¥Ú¡¼¥¸¡£mswin32Èǥ桼¥¶¤Ê¤éɬ¸«¤Ç¤¹¡£¿ä¾©´Ä¶­¤Ïarton¤µ¤ó¤È¤³¤ÎActiveScriptRuby¤Ç¤¹¤¬ (^^; ¤³¤³¤ÎÇÛÉÛʪ¤ò»È¤Ã¤Æ¤âÌäÂê¤Ê¤¯Æ°ºî¤·¤Þ¤¹¡£
      • -
      - - - - -
      written by U.Nakamura
      -

      -ruby 1.9.0 (2004-01-13)
      -ERb 2.0.4
      -RDtool 0.6.11
      -rublog 0.0.2 -

      - - - diff --git a/ruby/test/rexml/data/evaluate.xml b/ruby/test/rexml/data/evaluate.xml deleted file mode 100644 index 90d06bd65..000000000 --- a/ruby/test/rexml/data/evaluate.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - brown - - - moderate - - diff --git a/ruby/test/rexml/data/fibo.xml b/ruby/test/rexml/data/fibo.xml deleted file mode 100644 index 9b5d0ecd8..000000000 --- a/ruby/test/rexml/data/fibo.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 0 - 1 - 1 - 2 - 3 - 5 - 8 - 13 - 21 - 34 - 55 - 89 - 144 - 233 - 377 - 610 - 987 - 1597 - 2584 - 4181 - 6765 - 10946 - 17711 - 28657 - 46368 - 75025 - diff --git a/ruby/test/rexml/data/foo.xml b/ruby/test/rexml/data/foo.xml deleted file mode 100644 index 53b9a4e00..000000000 --- a/ruby/test/rexml/data/foo.xml +++ /dev/null @@ -1,10 +0,0 @@ - - -]> - - human leg - table leg - diff --git a/ruby/test/rexml/data/google.2.xml b/ruby/test/rexml/data/google.2.xml deleted file mode 100644 index a1df93b10..000000000 --- a/ruby/test/rexml/data/google.2.xml +++ /dev/null @@ -1,156 +0,0 @@ -
      - - - - - - - - Campaign Name - - - - Current Status - - - Current Budget - - [?] - - - - Clicks - - - - - - Impr. - - - CTR - - - Avg. CPC - - - Cost - - - Conv. Rate - - - Cost/Conv. - - - - - - - - Test - - - - Paused - - - - Test - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - - - - - Test - - - - Paused - - - - Test - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - - - - - Test - - - - Test - - - - Test - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - -
      diff --git a/ruby/test/rexml/data/id.xml b/ruby/test/rexml/data/id.xml deleted file mode 100644 index 749ab207c..000000000 --- a/ruby/test/rexml/data/id.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -]> - - - - baz - gouda - baz - cheddar - baz - - diff --git a/ruby/test/rexml/data/iso8859-1.xml b/ruby/test/rexml/data/iso8859-1.xml deleted file mode 100644 index 5fb04ec9b..000000000 --- a/ruby/test/rexml/data/iso8859-1.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/ruby/test/rexml/data/jaxen24.xml b/ruby/test/rexml/data/jaxen24.xml deleted file mode 100644 index 9b819967e..000000000 --- a/ruby/test/rexml/data/jaxen24.xml +++ /dev/null @@ -1,2 +0,0 @@ - -

      diff --git a/ruby/test/rexml/data/jaxen3.xml b/ruby/test/rexml/data/jaxen3.xml deleted file mode 100644 index a87723a3b..000000000 --- a/ruby/test/rexml/data/jaxen3.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2 - - CE-A - - - - 1 - - CE-B - - - diff --git a/ruby/test/rexml/data/lang.xml b/ruby/test/rexml/data/lang.xml deleted file mode 100644 index 49b45db29..000000000 --- a/ruby/test/rexml/data/lang.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/ruby/test/rexml/data/lang0.xml b/ruby/test/rexml/data/lang0.xml deleted file mode 100644 index 283b4e0f0..000000000 --- a/ruby/test/rexml/data/lang0.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - Ruby - - - Yukihiro Matsumoto - - - - - Python - - - Guido van Rossum - - - diff --git a/ruby/test/rexml/data/message.xml b/ruby/test/rexml/data/message.xml deleted file mode 100644 index 3b81df2a8..000000000 --- a/ruby/test/rexml/data/message.xml +++ /dev/null @@ -1,27 +0,0 @@ - - -
      - lookupformservice - 9 - stammdaten - new -
      - - - - - iteminfo - ELE - - - parentinfo - Pruefgebiete - - - id - 1 - - - - -
      diff --git a/ruby/test/rexml/data/moreover.xml b/ruby/test/rexml/data/moreover.xml deleted file mode 100644 index 38d4c4f81..000000000 --- a/ruby/test/rexml/data/moreover.xml +++ /dev/null @@ -1,244 +0,0 @@ - - -
      - http://c.moreover.com/click/here.pl?x13563273 - e-Commerce Operators Present Version 1.0 of the XML Standard - StockAccess - text - moreover... - - http://www.stockaccess.com/index.html - Dec 24 2000 6:28AM - - -
      -
      - http://c.moreover.com/click/here.pl?x13560995 - W3C Publishes XML Protocol Requirements Document - Xml - text - moreover... - - http://www.xml.com/ - Dec 24 2000 12:22AM - - -
      -
      - http://c.moreover.com/click/here.pl?x13553521 - Prowler: Open Source XML-Based Content Management Framework - Xml - text - moreover... - - http://www.xml.com/ - Dec 23 2000 2:05PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13549013 - The Middleware Company Debuts Public Training Courses in Ejb, J2ee And Xml - Java Industry Connection - text - moreover... - - http://industry.java.sun.com/javanews/more/hotnews/ - Dec 23 2000 12:15PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13544467 - Revised Working Draft for the W3C XML Information Set - Xml - text - moreover... - - http://www.xml.com/ - Dec 23 2000 5:50AM - - -
      -
      - http://c.moreover.com/click/here.pl?x13534836 - XML: Its The Great Peacemaker - ZDNet - text - moreover... - - http://www.zdnet.com/intweek/ - Dec 22 2000 9:05PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13533485 - Project eL - The XML Leningrad Codex Markup Project - Xml - text - moreover... - - http://www.xml.com/ - Dec 22 2000 8:34PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13533488 - XML Linking Language (XLink) and XML Base Specifications Issued as W3C Proposed Recommenda - Xml - text - moreover... - - http://www.xml.com/ - Dec 22 2000 8:34PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13533492 - W3C Releases XHTML Basic Specification as a W3C Recommendation - Xml - text - moreover... - - http://www.xml.com/ - Dec 22 2000 8:34PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13521827 - Java, Xml And Oracle9i(TM) Make A Great Team - Java Industry Connection - text - moreover... - - http://industry.java.sun.com/javanews/more/hotnews/ - Dec 22 2000 3:21PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13511233 - Competing initiatives to vie for security standard - ZDNet - text - moreover... - - http://www.zdnet.com/eweek/filters/news/ - Dec 22 2000 10:54AM - - -
      -
      - http://c.moreover.com/click/here.pl?x13492397 - Oracle Provides Developers with Great Xml Reading This Holiday Season - Java Industry Connection - text - moreover... - - http://industry.java.sun.com/javanews/more/hotnews/ - Dec 21 2000 8:08PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13491292 - XML as the great peacemaker - Extensible Markup Language Accomplished The Seemingly Impossible This Year: It B - Hospitality Net - text - moreover... - - http://www.hospitalitynet.org/news/list.htm?c=2000 - Dec 21 2000 7:45PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13484758 - XML as the great peacemaker - CNET - text - moreover... - - http://news.cnet.com/news/0-1003.html?tag=st.ne.1002.dir.1003 - Dec 21 2000 4:41PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13480896 - COOP Switzerland Selects Mercator as Integration Platform - Stockhouse Canada - text - moreover... - - http://www.stockhouse.ca/news/ - Dec 21 2000 1:55PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13471023 - Competing XML Specs Move Toward a Union - Internet World - text - moreover... - - http://www.internetworld.com/ - Dec 21 2000 11:14AM - - -
      -
      - http://c.moreover.com/click/here.pl?x13452280 - Next-generation XHTML stripped down for handhelds - CNET - text - moreover... - - http://news.cnet.com/news/0-1005.html?tag=st.ne.1002.dir.1005 - Dec 20 2000 9:11PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13451789 - Xml Powers Oracle9i(TM) Dynamic Services - Java Industry Connection - text - moreover... - - http://industry.java.sun.com/javanews/more/hotnews/ - Dec 20 2000 9:05PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13442097 - XML DOM reference guide - ASPWire - text - moreover... - - http://aspwire.com/ - Dec 20 2000 6:26PM - - -
      -
      - http://c.moreover.com/click/here.pl?x13424117 - Repeat/Xqsite And Bowstreet Team to Deliver Integrated Xml Solutions - Java Industry Connection - text - moreover... - - http://industry.java.sun.com/javanews/more/hotnews/ - Dec 20 2000 9:04AM - - -
      -
      - diff --git a/ruby/test/rexml/data/much_ado.xml b/ruby/test/rexml/data/much_ado.xml deleted file mode 100644 index f008fadbb..000000000 --- a/ruby/test/rexml/data/much_ado.xml +++ /dev/null @@ -1,6850 +0,0 @@ - - -Much Ado about Nothing - - -

      Text placed in the public domain by Moby Lexical Tools, 1992.

      -

      SGML markup by Jon Bosak, 1992-1994.

      -

      XML version by Jon Bosak, 1996-1998.

      -

      This work may be freely copied and distributed worldwide.

      -
      - - - -Dramatis Personae - -DON PEDRO, prince of Arragon. -DON JOHN, his bastard brother. -CLAUDIO, a young lord of Florence. -BENEDICK, a young lord of Padua. -LEONATO, governor of Messina. -ANTONIO, his brother. -BALTHASAR, attendant on Don Pedro. - - -CONRADE -BORACHIO -followers of Don John. - - -FRIAR FRANCIS -DOGBERRY, a constable. -VERGES, a headborough. -A Sexton. -A Boy. -HERO, daughter to Leonato. -BEATRICE, niece to Leonato. - - -MARGARET -URSULA -gentlewomen attending on Hero. - - -Messengers, Watch, Attendants, &c. - - -SCENE Messina. - -MUCH ADO ABOUT NOTHING - -ACT I - -SCENE I. Before LEONATO'S house. -Enter LEONATO, HERO, and BEATRICE, with a -Messenger - - -LEONATO -I learn in this letter that Don Peter of Arragon -comes this night to Messina. - - - -Messenger -He is very near by this: he was not three leagues off -when I left him. - - - -LEONATO -How many gentlemen have you lost in this action? - - - -Messenger -But few of any sort, and none of name. - - - -LEONATO -A victory is twice itself when the achiever brings -home full numbers. I find here that Don Peter hath -bestowed much honour on a young Florentine called Claudio. - - - -Messenger -Much deserved on his part and equally remembered by -Don Pedro: he hath borne himself beyond the -promise of his age, doing, in the figure of a lamb, -the feats of a lion: he hath indeed better -bettered expectation than you must expect of me to -tell you how. - - - -LEONATO -He hath an uncle here in Messina will be very much -glad of it. - - - -Messenger -I have already delivered him letters, and there -appears much joy in him; even so much that joy could -not show itself modest enough without a badge of -bitterness. - - - -LEONATO -Did he break out into tears? - - - -Messenger -In great measure. - - - -LEONATO -A kind overflow of kindness: there are no faces -truer than those that are so washed. How much -better is it to weep at joy than to joy at weeping! - - - -BEATRICE -I pray you, is Signior Mountanto returned from the -wars or no? - - - -Messenger -I know none of that name, lady: there was none such -in the army of any sort. - - - -LEONATO -What is he that you ask for, niece? - - - -HERO -My cousin means Signior Benedick of Padua. - - - -Messenger -O, he's returned; and as pleasant as ever he was. - - - -BEATRICE -He set up his bills here in Messina and challenged -Cupid at the flight; and my uncle's fool, reading -the challenge, subscribed for Cupid, and challenged -him at the bird-bolt. I pray you, how many hath he -killed and eaten in these wars? But how many hath -he killed? for indeed I promised to eat all of his killing. - - - -LEONATO -Faith, niece, you tax Signior Benedick too much; -but he'll be meet with you, I doubt it not. - - - -Messenger -He hath done good service, lady, in these wars. - - - -BEATRICE -You had musty victual, and he hath holp to eat it: -he is a very valiant trencherman; he hath an -excellent stomach. - - - -Messenger -And a good soldier too, lady. - - - -BEATRICE -And a good soldier to a lady: but what is he to a lord? - - - -Messenger -A lord to a lord, a man to a man; stuffed with all -honourable virtues. - - - -BEATRICE -It is so, indeed; he is no less than a stuffed man: -but for the stuffing,--well, we are all mortal. - - - -LEONATO -You must not, sir, mistake my niece. There is a -kind of merry war betwixt Signior Benedick and her: -they never meet but there's a skirmish of wit -between them. - - - -BEATRICE -Alas! he gets nothing by that. In our last -conflict four of his five wits went halting off, and -now is the whole man governed with one: so that if -he have wit enough to keep himself warm, let him -bear it for a difference between himself and his -horse; for it is all the wealth that he hath left, -to be known a reasonable creature. Who is his -companion now? He hath every month a new sworn brother. - - - -Messenger -Is't possible? - - - -BEATRICE -Very easily possible: he wears his faith but as -the fashion of his hat; it ever changes with the -next block. - - - -Messenger -I see, lady, the gentleman is not in your books. - - - -BEATRICE -No; an he were, I would burn my study. But, I pray -you, who is his companion? Is there no young -squarer now that will make a voyage with him to the devil? - - - -Messenger -He is most in the company of the right noble Claudio. - - - -BEATRICE -O Lord, he will hang upon him like a disease: he -is sooner caught than the pestilence, and the taker -runs presently mad. God help the noble Claudio! if -he have caught the Benedick, it will cost him a -thousand pound ere a' be cured. - - - -Messenger -I will hold friends with you, lady. - - - -BEATRICE -Do, good friend. - - - -LEONATO -You will never run mad, niece. - - - -BEATRICE -No, not till a hot January. - - - -Messenger -Don Pedro is approached. - - - -Enter DON PEDRO, DON JOHN, CLAUDIO, BENEDICK, -and BALTHASAR - - -DON PEDRO -Good Signior Leonato, you are come to meet your -trouble: the fashion of the world is to avoid -cost, and you encounter it. - - - -LEONATO -Never came trouble to my house in the likeness of -your grace: for trouble being gone, comfort should -remain; but when you depart from me, sorrow abides -and happiness takes his leave. - - - -DON PEDRO -You embrace your charge too willingly. I think this -is your daughter. - - - -LEONATO -Her mother hath many times told me so. - - - -BENEDICK -Were you in doubt, sir, that you asked her? - - - -LEONATO -Signior Benedick, no; for then were you a child. - - - -DON PEDRO -You have it full, Benedick: we may guess by this -what you are, being a man. Truly, the lady fathers -herself. Be happy, lady; for you are like an -honourable father. - - - -BENEDICK -If Signior Leonato be her father, she would not -have his head on her shoulders for all Messina, as -like him as she is. - - - -BEATRICE -I wonder that you will still be talking, Signior -Benedick: nobody marks you. - - - -BENEDICK -What, my dear Lady Disdain! are you yet living? - - - -BEATRICE -Is it possible disdain should die while she hath -such meet food to feed it as Signior Benedick? -Courtesy itself must convert to disdain, if you come -in her presence. - - - -BENEDICK -Then is courtesy a turncoat. But it is certain I -am loved of all ladies, only you excepted: and I -would I could find in my heart that I had not a hard -heart; for, truly, I love none. - - - -BEATRICE -A dear happiness to women: they would else have -been troubled with a pernicious suitor. I thank God -and my cold blood, I am of your humour for that: I -had rather hear my dog bark at a crow than a man -swear he loves me. - - - -BENEDICK -God keep your ladyship still in that mind! so some -gentleman or other shall 'scape a predestinate -scratched face. - - - -BEATRICE -Scratching could not make it worse, an 'twere such -a face as yours were. - - - -BENEDICK -Well, you are a rare parrot-teacher. - - - -BEATRICE -A bird of my tongue is better than a beast of yours. - - - -BENEDICK -I would my horse had the speed of your tongue, and -so good a continuer. But keep your way, i' God's -name; I have done. - - - -BEATRICE -You always end with a jade's trick: I know you of old. - - - -DON PEDRO -That is the sum of all, Leonato. Signior Claudio -and Signior Benedick, my dear friend Leonato hath -invited you all. I tell him we shall stay here at -the least a month; and he heartily prays some -occasion may detain us longer. I dare swear he is no -hypocrite, but prays from his heart. - - - -LEONATO -If you swear, my lord, you shall not be forsworn. -To DON JOHN -Let me bid you welcome, my lord: being reconciled to -the prince your brother, I owe you all duty. - - - -DON JOHN -I thank you: I am not of many words, but I thank -you. - - - -LEONATO -Please it your grace lead on? - - - -DON PEDRO -Your hand, Leonato; we will go together. - - - -Exeunt all except BENEDICK and CLAUDIO - - -CLAUDIO -Benedick, didst thou note the daughter of Signior Leonato? - - - -BENEDICK -I noted her not; but I looked on her. - - - -CLAUDIO -Is she not a modest young lady? - - - -BENEDICK -Do you question me, as an honest man should do, for -my simple true judgment; or would you have me speak -after my custom, as being a professed tyrant to their sex? - - - -CLAUDIO -No; I pray thee speak in sober judgment. - - - -BENEDICK -Why, i' faith, methinks she's too low for a high -praise, too brown for a fair praise and too little -for a great praise: only this commendation I can -afford her, that were she other than she is, she -were unhandsome; and being no other but as she is, I -do not like her. - - - -CLAUDIO -Thou thinkest I am in sport: I pray thee tell me -truly how thou likest her. - - - -BENEDICK -Would you buy her, that you inquire after her? - - - -CLAUDIO -Can the world buy such a jewel? - - - -BENEDICK -Yea, and a case to put it into. But speak you this -with a sad brow? or do you play the flouting Jack, -to tell us Cupid is a good hare-finder and Vulcan a -rare carpenter? Come, in what key shall a man take -you, to go in the song? - - - -CLAUDIO -In mine eye she is the sweetest lady that ever I -looked on. - - - -BENEDICK -I can see yet without spectacles and I see no such -matter: there's her cousin, an she were not -possessed with a fury, exceeds her as much in beauty -as the first of May doth the last of December. But I -hope you have no intent to turn husband, have you? - - - -CLAUDIO -I would scarce trust myself, though I had sworn the -contrary, if Hero would be my wife. - - - -BENEDICK -Is't come to this? In faith, hath not the world -one man but he will wear his cap with suspicion? -Shall I never see a bachelor of three-score again? -Go to, i' faith; an thou wilt needs thrust thy neck -into a yoke, wear the print of it and sigh away -Sundays. Look Don Pedro is returned to seek you. - - - -Re-enter DON PEDRO - - -DON PEDRO -What secret hath held you here, that you followed -not to Leonato's? - - - -BENEDICK -I would your grace would constrain me to tell. - - - -DON PEDRO -I charge thee on thy allegiance. - - - -BENEDICK -You hear, Count Claudio: I can be secret as a dumb -man; I would have you think so; but, on my -allegiance, mark you this, on my allegiance. He is -in love. With who? now that is your grace's part. -Mark how short his answer is;--With Hero, Leonato's -short daughter. - - - -CLAUDIO -If this were so, so were it uttered. - - - -BENEDICK -Like the old tale, my lord: 'it is not so, nor -'twas not so, but, indeed, God forbid it should be -so.' - - - -CLAUDIO -If my passion change not shortly, God forbid it -should be otherwise. - - - -DON PEDRO -Amen, if you love her; for the lady is very well worthy. - - - -CLAUDIO -You speak this to fetch me in, my lord. - - - -DON PEDRO -By my troth, I speak my thought. - - - -CLAUDIO -And, in faith, my lord, I spoke mine. - - - -BENEDICK -And, by my two faiths and troths, my lord, I spoke mine. - - - -CLAUDIO -That I love her, I feel. - - - -DON PEDRO -That she is worthy, I know. - - - -BENEDICK -That I neither feel how she should be loved nor -know how she should be worthy, is the opinion that -fire cannot melt out of me: I will die in it at the stake. - - - -DON PEDRO -Thou wast ever an obstinate heretic in the despite -of beauty. - - - -CLAUDIO -And never could maintain his part but in the force -of his will. - - - -BENEDICK -That a woman conceived me, I thank her; that she -brought me up, I likewise give her most humble -thanks: but that I will have a recheat winded in my -forehead, or hang my bugle in an invisible baldrick, -all women shall pardon me. Because I will not do -them the wrong to mistrust any, I will do myself the -right to trust none; and the fine is, for the which -I may go the finer, I will live a bachelor. - - - -DON PEDRO -I shall see thee, ere I die, look pale with love. - - - -BENEDICK -With anger, with sickness, or with hunger, my lord, -not with love: prove that ever I lose more blood -with love than I will get again with drinking, pick -out mine eyes with a ballad-maker's pen and hang me -up at the door of a brothel-house for the sign of -blind Cupid. - - - -DON PEDRO -Well, if ever thou dost fall from this faith, thou -wilt prove a notable argument. - - - -BENEDICK -If I do, hang me in a bottle like a cat and shoot -at me; and he that hits me, let him be clapped on -the shoulder, and called Adam. - - - -DON PEDRO -Well, as time shall try: 'In time the savage bull -doth bear the yoke.' - - - -BENEDICK -The savage bull may; but if ever the sensible -Benedick bear it, pluck off the bull's horns and set -them in my forehead: and let me be vilely painted, -and in such great letters as they write 'Here is -good horse to hire,' let them signify under my sign -'Here you may see Benedick the married man.' - - - -CLAUDIO -If this should ever happen, thou wouldst be horn-mad. - - - -DON PEDRO -Nay, if Cupid have not spent all his quiver in -Venice, thou wilt quake for this shortly. - - - -BENEDICK -I look for an earthquake too, then. - - - -DON PEDRO -Well, you temporize with the hours. In the -meantime, good Signior Benedick, repair to -Leonato's: commend me to him and tell him I will -not fail him at supper; for indeed he hath made -great preparation. - - - -BENEDICK -I have almost matter enough in me for such an -embassage; and so I commit you-- - - - -CLAUDIO -To the tuition of God: From my house, if I had it,-- - - - -DON PEDRO -The sixth of July: Your loving friend, Benedick. - - - -BENEDICK -Nay, mock not, mock not. The body of your -discourse is sometime guarded with fragments, and -the guards are but slightly basted on neither: ere -you flout old ends any further, examine your -conscience: and so I leave you. - - - -Exit - - -CLAUDIO -My liege, your highness now may do me good. - - - -DON PEDRO -My love is thine to teach: teach it but how, -And thou shalt see how apt it is to learn -Any hard lesson that may do thee good. - - - -CLAUDIO -Hath Leonato any son, my lord? - - - -DON PEDRO -No child but Hero; she's his only heir. -Dost thou affect her, Claudio? - - - -CLAUDIO -O, my lord, -When you went onward on this ended action, -I look'd upon her with a soldier's eye, -That liked, but had a rougher task in hand -Than to drive liking to the name of love: -But now I am return'd and that war-thoughts -Have left their places vacant, in their rooms -Come thronging soft and delicate desires, -All prompting me how fair young Hero is, -Saying, I liked her ere I went to wars. - - - -DON PEDRO -Thou wilt be like a lover presently -And tire the hearer with a book of words. -If thou dost love fair Hero, cherish it, -And I will break with her and with her father, -And thou shalt have her. Was't not to this end -That thou began'st to twist so fine a story? - - - -CLAUDIO -How sweetly you do minister to love, -That know love's grief by his complexion! -But lest my liking might too sudden seem, -I would have salved it with a longer treatise. - - - -DON PEDRO -What need the bridge much broader than the flood? -The fairest grant is the necessity. -Look, what will serve is fit: 'tis once, thou lovest, -And I will fit thee with the remedy. -I know we shall have revelling to-night: -I will assume thy part in some disguise -And tell fair Hero I am Claudio, -And in her bosom I'll unclasp my heart -And take her hearing prisoner with the force -And strong encounter of my amorous tale: -Then after to her father will I break; -And the conclusion is, she shall be thine. -In practise let us put it presently. - - - -Exeunt - - -SCENE II. A room in LEONATO's house. -Enter LEONATO and ANTONIO, meeting - - -LEONATO -How now, brother! Where is my cousin, your son? -hath he provided this music? - - - -ANTONIO -He is very busy about it. But, brother, I can tell -you strange news that you yet dreamt not of. - - - -LEONATO -Are they good? - - - -ANTONIO -As the event stamps them: but they have a good -cover; they show well outward. The prince and Count -Claudio, walking in a thick-pleached alley in mine -orchard, were thus much overheard by a man of mine: -the prince discovered to Claudio that he loved my -niece your daughter and meant to acknowledge it -this night in a dance: and if he found her -accordant, he meant to take the present time by the -top and instantly break with you of it. - - - -LEONATO -Hath the fellow any wit that told you this? - - - -ANTONIO -A good sharp fellow: I will send for him; and -question him yourself. - - - -LEONATO -No, no; we will hold it as a dream till it appear -itself: but I will acquaint my daughter withal, -that she may be the better prepared for an answer, -if peradventure this be true. Go you and tell her of it. -Enter Attendants -Cousins, you know what you have to do. O, I cry you -mercy, friend; go you with me, and I will use your -skill. Good cousin, have a care this busy time. - - - -Exeunt - - -SCENE III. The same. -Enter DON JOHN and CONRADE - - -CONRADE -What the good-year, my lord! why are you thus out -of measure sad? - - - -DON JOHN -There is no measure in the occasion that breeds; -therefore the sadness is without limit. - - - -CONRADE -You should hear reason. - - - -DON JOHN -And when I have heard it, what blessing brings it? - - - -CONRADE -If not a present remedy, at least a patient -sufferance. - - - -DON JOHN -I wonder that thou, being, as thou sayest thou art, -born under Saturn, goest about to apply a moral -medicine to a mortifying mischief. I cannot hide -what I am: I must be sad when I have cause and smile -at no man's jests, eat when I have stomach and wait -for no man's leisure, sleep when I am drowsy and -tend on no man's business, laugh when I am merry and -claw no man in his humour. - - - -CONRADE -Yea, but you must not make the full show of this -till you may do it without controlment. You have of -late stood out against your brother, and he hath -ta'en you newly into his grace; where it is -impossible you should take true root but by the -fair weather that you make yourself: it is needful -that you frame the season for your own harvest. - - - -DON JOHN -I had rather be a canker in a hedge than a rose in -his grace, and it better fits my blood to be -disdained of all than to fashion a carriage to rob -love from any: in this, though I cannot be said to -be a flattering honest man, it must not be denied -but I am a plain-dealing villain. I am trusted with -a muzzle and enfranchised with a clog; therefore I -have decreed not to sing in my cage. If I had my -mouth, I would bite; if I had my liberty, I would do -my liking: in the meantime let me be that I am and -seek not to alter me. - - - -CONRADE -Can you make no use of your discontent? - - - -DON JOHN -I make all use of it, for I use it only. -Who comes here? -Enter BORACHIO -What news, Borachio? - - - -BORACHIO -I came yonder from a great supper: the prince your -brother is royally entertained by Leonato: and I -can give you intelligence of an intended marriage. - - - -DON JOHN -Will it serve for any model to build mischief on? -What is he for a fool that betroths himself to -unquietness? - - - -BORACHIO -Marry, it is your brother's right hand. - - - -DON JOHN -Who? the most exquisite Claudio? - - - -BORACHIO -Even he. - - - -DON JOHN -A proper squire! And who, and who? which way looks -he? - - - -BORACHIO -Marry, on Hero, the daughter and heir of Leonato. - - - -DON JOHN -A very forward March-chick! How came you to this? - - - -BORACHIO -Being entertained for a perfumer, as I was smoking a -musty room, comes me the prince and Claudio, hand -in hand in sad conference: I whipt me behind the -arras; and there heard it agreed upon that the -prince should woo Hero for himself, and having -obtained her, give her to Count Claudio. - - - -DON JOHN -Come, come, let us thither: this may prove food to -my displeasure. That young start-up hath all the -glory of my overthrow: if I can cross him any way, I -bless myself every way. You are both sure, and will assist me? - - - -CONRADE -To the death, my lord. - - - -DON JOHN -Let us to the great supper: their cheer is the -greater that I am subdued. Would the cook were of -my mind! Shall we go prove what's to be done? - - - -BORACHIO -We'll wait upon your lordship. - - - -Exeunt - - - - -ACT II - -SCENE I. A hall in LEONATO'S house. -Enter LEONATO, ANTONIO, HERO, BEATRICE, and others - - -LEONATO -Was not Count John here at supper? - - - -ANTONIO -I saw him not. - - - -BEATRICE -How tartly that gentleman looks! I never can see -him but I am heart-burned an hour after. - - - -HERO -He is of a very melancholy disposition. - - - -BEATRICE -He were an excellent man that were made just in the -midway between him and Benedick: the one is too -like an image and says nothing, and the other too -like my lady's eldest son, evermore tattling. - - - -LEONATO -Then half Signior Benedick's tongue in Count John's -mouth, and half Count John's melancholy in Signior -Benedick's face,-- - - - -BEATRICE -With a good leg and a good foot, uncle, and money -enough in his purse, such a man would win any woman -in the world, if a' could get her good-will. - - - -LEONATO -By my troth, niece, thou wilt never get thee a -husband, if thou be so shrewd of thy tongue. - - - -ANTONIO -In faith, she's too curst. - - - -BEATRICE -Too curst is more than curst: I shall lessen God's -sending that way; for it is said, 'God sends a curst -cow short horns;' but to a cow too curst he sends none. - - - -LEONATO -So, by being too curst, God will send you no horns. - - - -BEATRICE -Just, if he send me no husband; for the which -blessing I am at him upon my knees every morning and -evening. Lord, I could not endure a husband with a -beard on his face: I had rather lie in the woollen. - - - -LEONATO -You may light on a husband that hath no beard. - - - -BEATRICE -What should I do with him? dress him in my apparel -and make him my waiting-gentlewoman? He that hath a -beard is more than a youth, and he that hath no -beard is less than a man: and he that is more than -a youth is not for me, and he that is less than a -man, I am not for him: therefore, I will even take -sixpence in earnest of the bear-ward, and lead his -apes into hell. - - - -LEONATO -Well, then, go you into hell? - - - -BEATRICE -No, but to the gate; and there will the devil meet -me, like an old cuckold, with horns on his head, and -say 'Get you to heaven, Beatrice, get you to -heaven; here's no place for you maids:' so deliver -I up my apes, and away to Saint Peter for the -heavens; he shows me where the bachelors sit, and -there live we as merry as the day is long. - - - -ANTONIO -To HERO Well, niece, I trust you will be ruled -by your father. - - - -BEATRICE -Yes, faith; it is my cousin's duty to make curtsy -and say 'Father, as it please you.' But yet for all -that, cousin, let him be a handsome fellow, or else -make another curtsy and say 'Father, as it please -me.' - - - -LEONATO -Well, niece, I hope to see you one day fitted with a husband. - - - -BEATRICE -Not till God make men of some other metal than -earth. Would it not grieve a woman to be -overmastered with a pierce of valiant dust? to make -an account of her life to a clod of wayward marl? -No, uncle, I'll none: Adam's sons are my brethren; -and, truly, I hold it a sin to match in my kindred. - - - -LEONATO -Daughter, remember what I told you: if the prince -do solicit you in that kind, you know your answer. - - - -BEATRICE -The fault will be in the music, cousin, if you be -not wooed in good time: if the prince be too -important, tell him there is measure in every thing -and so dance out the answer. For, hear me, Hero: -wooing, wedding, and repenting, is as a Scotch jig, -a measure, and a cinque pace: the first suit is hot -and hasty, like a Scotch jig, and full as -fantastical; the wedding, mannerly-modest, as a -measure, full of state and ancientry; and then comes -repentance and, with his bad legs, falls into the -cinque pace faster and faster, till he sink into his grave. - - - -LEONATO -Cousin, you apprehend passing shrewdly. - - - -BEATRICE -I have a good eye, uncle; I can see a church by daylight. - - - -LEONATO -The revellers are entering, brother: make good room. - - -All put on their masks -Enter DON PEDRO, CLAUDIO, BENEDICK, BALTHASAR, -DON JOHN, BORACHIO, MARGARET, URSULA and others, masked - - -DON PEDRO -Lady, will you walk about with your friend? - - - -HERO -So you walk softly and look sweetly and say nothing, -I am yours for the walk; and especially when I walk away. - - - -DON PEDRO -With me in your company? - - - -HERO -I may say so, when I please. - - - -DON PEDRO -And when please you to say so? - - - -HERO -When I like your favour; for God defend the lute -should be like the case! - - - -DON PEDRO -My visor is Philemon's roof; within the house is Jove. - - - -HERO -Why, then, your visor should be thatched. - - - -DON PEDRO -Speak low, if you speak love. - - - -Drawing her aside - - -BALTHASAR -Well, I would you did like me. - - - -MARGARET -So would not I, for your own sake; for I have many -ill-qualities. - - - -BALTHASAR -Which is one? - - - -MARGARET -I say my prayers aloud. - - - -BALTHASAR -I love you the better: the hearers may cry, Amen. - - - -MARGARET -God match me with a good dancer! - - - -BALTHASAR -Amen. - - - -MARGARET -And God keep him out of my sight when the dance is -done! Answer, clerk. - - - -BALTHASAR -No more words: the clerk is answered. - - - -URSULA -I know you well enough; you are Signior Antonio. - - - -ANTONIO -At a word, I am not. - - - -URSULA -I know you by the waggling of your head. - - - -ANTONIO -To tell you true, I counterfeit him. - - - -URSULA -You could never do him so ill-well, unless you were -the very man. Here's his dry hand up and down: you -are he, you are he. - - - -ANTONIO -At a word, I am not. - - - -URSULA -Come, come, do you think I do not know you by your -excellent wit? can virtue hide itself? Go to, -mum, you are he: graces will appear, and there's an -end. - - - -BEATRICE -Will you not tell me who told you so? - - - -BENEDICK -No, you shall pardon me. - - - -BEATRICE -Nor will you not tell me who you are? - - - -BENEDICK -Not now. - - - -BEATRICE -That I was disdainful, and that I had my good wit -out of the 'Hundred Merry Tales:'--well this was -Signior Benedick that said so. - - - -BENEDICK -What's he? - - - -BEATRICE -I am sure you know him well enough. - - - -BENEDICK -Not I, believe me. - - - -BEATRICE -Did he never make you laugh? - - - -BENEDICK -I pray you, what is he? - - - -BEATRICE -Why, he is the prince's jester: a very dull fool; -only his gift is in devising impossible slanders: -none but libertines delight in him; and the -commendation is not in his wit, but in his villany; -for he both pleases men and angers them, and then -they laugh at him and beat him. I am sure he is in -the fleet: I would he had boarded me. - - - -BENEDICK -When I know the gentleman, I'll tell him what you say. - - - -BEATRICE -Do, do: he'll but break a comparison or two on me; -which, peradventure not marked or not laughed at, -strikes him into melancholy; and then there's a -partridge wing saved, for the fool will eat no -supper that night. -Music -We must follow the leaders. - - - -BENEDICK -In every good thing. - - - -BEATRICE -Nay, if they lead to any ill, I will leave them at -the next turning. - - - -Dance. Then exeunt all except DON JOHN, BORACHIO, -and CLAUDIO - - -DON JOHN -Sure my brother is amorous on Hero and hath -withdrawn her father to break with him about it. -The ladies follow her and but one visor remains. - - - -BORACHIO -And that is Claudio: I know him by his bearing. - - - -DON JOHN -Are not you Signior Benedick? - - - -CLAUDIO -You know me well; I am he. - - - -DON JOHN -Signior, you are very near my brother in his love: -he is enamoured on Hero; I pray you, dissuade him -from her: she is no equal for his birth: you may -do the part of an honest man in it. - - - -CLAUDIO -How know you he loves her? - - - -DON JOHN -I heard him swear his affection. - - - -BORACHIO -So did I too; and he swore he would marry her to-night. - - - -DON JOHN -Come, let us to the banquet. - - - -Exeunt DON JOHN and BORACHIO - - -CLAUDIO -Thus answer I in the name of Benedick, -But hear these ill news with the ears of Claudio. -'Tis certain so; the prince wooes for himself. -Friendship is constant in all other things -Save in the office and affairs of love: -Therefore, all hearts in love use their own tongues; -Let every eye negotiate for itself -And trust no agent; for beauty is a witch -Against whose charms faith melteth into blood. -This is an accident of hourly proof, -Which I mistrusted not. Farewell, therefore, Hero! - - - -Re-enter BENEDICK - - -BENEDICK -Count Claudio? - - - -CLAUDIO -Yea, the same. - - - -BENEDICK -Come, will you go with me? - - - -CLAUDIO -Whither? - - - -BENEDICK -Even to the next willow, about your own business, -county. What fashion will you wear the garland of? -about your neck, like an usurer's chain? or under -your arm, like a lieutenant's scarf? You must wear -it one way, for the prince hath got your Hero. - - - -CLAUDIO -I wish him joy of her. - - - -BENEDICK -Why, that's spoken like an honest drovier: so they -sell bullocks. But did you think the prince would -have served you thus? - - - -CLAUDIO -I pray you, leave me. - - - -BENEDICK -Ho! now you strike like the blind man: 'twas the -boy that stole your meat, and you'll beat the post. - - - -CLAUDIO -If it will not be, I'll leave you. - - - -Exit - - -BENEDICK -Alas, poor hurt fowl! now will he creep into sedges. -But that my Lady Beatrice should know me, and not -know me! The prince's fool! Ha? It may be I go -under that title because I am merry. Yea, but so I -am apt to do myself wrong; I am not so reputed: it -is the base, though bitter, disposition of Beatrice -that puts the world into her person and so gives me -out. Well, I'll be revenged as I may. - - - -Re-enter DON PEDRO - - -DON PEDRO -Now, signior, where's the count? did you see him? - - - -BENEDICK -Troth, my lord, I have played the part of Lady Fame. -I found him here as melancholy as a lodge in a -warren: I told him, and I think I told him true, -that your grace had got the good will of this young -lady; and I offered him my company to a willow-tree, -either to make him a garland, as being forsaken, or -to bind him up a rod, as being worthy to be whipped. - - - -DON PEDRO -To be whipped! What's his fault? - - - -BENEDICK -The flat transgression of a schoolboy, who, being -overjoyed with finding a birds' nest, shows it his -companion, and he steals it. - - - -DON PEDRO -Wilt thou make a trust a transgression? The -transgression is in the stealer. - - - -BENEDICK -Yet it had not been amiss the rod had been made, -and the garland too; for the garland he might have -worn himself, and the rod he might have bestowed on -you, who, as I take it, have stolen his birds' nest. - - - -DON PEDRO -I will but teach them to sing, and restore them to -the owner. - - - -BENEDICK -If their singing answer your saying, by my faith, -you say honestly. - - - -DON PEDRO -The Lady Beatrice hath a quarrel to you: the -gentleman that danced with her told her she is much -wronged by you. - - - -BENEDICK -O, she misused me past the endurance of a block! -an oak but with one green leaf on it would have -answered her; my very visor began to assume life and -scold with her. She told me, not thinking I had been -myself, that I was the prince's jester, that I was -duller than a great thaw; huddling jest upon jest -with such impossible conveyance upon me that I stood -like a man at a mark, with a whole army shooting at -me. She speaks poniards, and every word stabs: -if her breath were as terrible as her terminations, -there were no living near her; she would infect to -the north star. I would not marry her, though she -were endowed with all that Adam bad left him before -he transgressed: she would have made Hercules have -turned spit, yea, and have cleft his club to make -the fire too. Come, talk not of her: you shall find -her the infernal Ate in good apparel. I would to God -some scholar would conjure her; for certainly, while -she is here, a man may live as quiet in hell as in a -sanctuary; and people sin upon purpose, because they -would go thither; so, indeed, all disquiet, horror -and perturbation follows her. - - - -DON PEDRO -Look, here she comes. - - - -Enter CLAUDIO, BEATRICE, HERO, and LEONATO - - -BENEDICK -Will your grace command me any service to the -world's end? I will go on the slightest errand now -to the Antipodes that you can devise to send me on; -I will fetch you a tooth-picker now from the -furthest inch of Asia, bring you the length of -Prester John's foot, fetch you a hair off the great -Cham's beard, do you any embassage to the Pigmies, -rather than hold three words' conference with this -harpy. You have no employment for me? - - - -DON PEDRO -None, but to desire your good company. - - - -BENEDICK -O God, sir, here's a dish I love not: I cannot -endure my Lady Tongue. - - - -Exit - - -DON PEDRO -Come, lady, come; you have lost the heart of -Signior Benedick. - - - -BEATRICE -Indeed, my lord, he lent it me awhile; and I gave -him use for it, a double heart for his single one: -marry, once before he won it of me with false dice, -therefore your grace may well say I have lost it. - - - -DON PEDRO -You have put him down, lady, you have put him down. - - - -BEATRICE -So I would not he should do me, my lord, lest I -should prove the mother of fools. I have brought -Count Claudio, whom you sent me to seek. - - - -DON PEDRO -Why, how now, count! wherefore are you sad? - - - -CLAUDIO -Not sad, my lord. - - - -DON PEDRO -How then? sick? - - - -CLAUDIO -Neither, my lord. - - - -BEATRICE -The count is neither sad, nor sick, nor merry, nor -well; but civil count, civil as an orange, and -something of that jealous complexion. - - - -DON PEDRO -I' faith, lady, I think your blazon to be true; -though, I'll be sworn, if he be so, his conceit is -false. Here, Claudio, I have wooed in thy name, and -fair Hero is won: I have broke with her father, -and his good will obtained: name the day of -marriage, and God give thee joy! - - - -LEONATO -Count, take of me my daughter, and with her my -fortunes: his grace hath made the match, and an -grace say Amen to it. - - - -BEATRICE -Speak, count, 'tis your cue. - - - -CLAUDIO -Silence is the perfectest herald of joy: I were -but little happy, if I could say how much. Lady, as -you are mine, I am yours: I give away myself for -you and dote upon the exchange. - - - -BEATRICE -Speak, cousin; or, if you cannot, stop his mouth -with a kiss, and let not him speak neither. - - - -DON PEDRO -In faith, lady, you have a merry heart. - - - -BEATRICE -Yea, my lord; I thank it, poor fool, it keeps on -the windy side of care. My cousin tells him in his -ear that he is in her heart. - - - -CLAUDIO -And so she doth, cousin. - - - -BEATRICE -Good Lord, for alliance! Thus goes every one to the -world but I, and I am sunburnt; I may sit in a -corner and cry heigh-ho for a husband! - - - -DON PEDRO -Lady Beatrice, I will get you one. - - - -BEATRICE -I would rather have one of your father's getting. -Hath your grace ne'er a brother like you? Your -father got excellent husbands, if a maid could come by them. - - - -DON PEDRO -Will you have me, lady? - - - -BEATRICE -No, my lord, unless I might have another for -working-days: your grace is too costly to wear -every day. But, I beseech your grace, pardon me: I -was born to speak all mirth and no matter. - - - -DON PEDRO -Your silence most offends me, and to be merry best -becomes you; for, out of question, you were born in -a merry hour. - - - -BEATRICE -No, sure, my lord, my mother cried; but then there -was a star danced, and under that was I born. -Cousins, God give you joy! - - - -LEONATO -Niece, will you look to those things I told you of? - - - -BEATRICE -I cry you mercy, uncle. By your grace's pardon. - - - -Exit - - -DON PEDRO -By my troth, a pleasant-spirited lady. - - - -LEONATO -There's little of the melancholy element in her, my -lord: she is never sad but when she sleeps, and -not ever sad then; for I have heard my daughter say, -she hath often dreamed of unhappiness and waked -herself with laughing. - - - -DON PEDRO -She cannot endure to hear tell of a husband. - - - -LEONATO -O, by no means: she mocks all her wooers out of suit. - - - -DON PEDRO -She were an excellent wife for Benedict. - - - -LEONATO -O Lord, my lord, if they were but a week married, -they would talk themselves mad. - - - -DON PEDRO -County Claudio, when mean you to go to church? - - - -CLAUDIO -To-morrow, my lord: time goes on crutches till love -have all his rites. - - - -LEONATO -Not till Monday, my dear son, which is hence a just -seven-night; and a time too brief, too, to have all -things answer my mind. - - - -DON PEDRO -Come, you shake the head at so long a breathing: -but, I warrant thee, Claudio, the time shall not go -dully by us. I will in the interim undertake one of -Hercules' labours; which is, to bring Signior -Benedick and the Lady Beatrice into a mountain of -affection the one with the other. I would fain have -it a match, and I doubt not but to fashion it, if -you three will but minister such assistance as I -shall give you direction. - - - -LEONATO -My lord, I am for you, though it cost me ten -nights' watchings. - - - -CLAUDIO -And I, my lord. - - - -DON PEDRO -And you too, gentle Hero? - - - -HERO -I will do any modest office, my lord, to help my -cousin to a good husband. - - - -DON PEDRO -And Benedick is not the unhopefullest husband that -I know. Thus far can I praise him; he is of a noble -strain, of approved valour and confirmed honesty. I -will teach you how to humour your cousin, that she -shall fall in love with Benedick; and I, with your -two helps, will so practise on Benedick that, in -despite of his quick wit and his queasy stomach, he -shall fall in love with Beatrice. If we can do this, -Cupid is no longer an archer: his glory shall be -ours, for we are the only love-gods. Go in with me, -and I will tell you my drift. - - - -Exeunt - - -SCENE II. The same. -Enter DON JOHN and BORACHIO - - -DON JOHN -It is so; the Count Claudio shall marry the -daughter of Leonato. - - - -BORACHIO -Yea, my lord; but I can cross it. - - - -DON JOHN -Any bar, any cross, any impediment will be -medicinable to me: I am sick in displeasure to him, -and whatsoever comes athwart his affection ranges -evenly with mine. How canst thou cross this marriage? - - - -BORACHIO -Not honestly, my lord; but so covertly that no -dishonesty shall appear in me. - - - -DON JOHN -Show me briefly how. - - - -BORACHIO -I think I told your lordship a year since, how much -I am in the favour of Margaret, the waiting -gentlewoman to Hero. - - - -DON JOHN -I remember. - - - -BORACHIO -I can, at any unseasonable instant of the night, -appoint her to look out at her lady's chamber window. - - - -DON JOHN -What life is in that, to be the death of this marriage? - - - -BORACHIO -The poison of that lies in you to temper. Go you to -the prince your brother; spare not to tell him that -he hath wronged his honour in marrying the renowned -Claudio--whose estimation do you mightily hold -up--to a contaminated stale, such a one as Hero. - - - -DON JOHN -What proof shall I make of that? - - - -BORACHIO -Proof enough to misuse the prince, to vex Claudio, -to undo Hero and kill Leonato. Look you for any -other issue? - - - -DON JOHN -Only to despite them, I will endeavour any thing. - - - -BORACHIO -Go, then; find me a meet hour to draw Don Pedro and -the Count Claudio alone: tell them that you know -that Hero loves me; intend a kind of zeal both to the -prince and Claudio, as,--in love of your brother's -honour, who hath made this match, and his friend's -reputation, who is thus like to be cozened with the -semblance of a maid,--that you have discovered -thus. They will scarcely believe this without trial: -offer them instances; which shall bear no less -likelihood than to see me at her chamber-window, -hear me call Margaret Hero, hear Margaret term me -Claudio; and bring them to see this the very night -before the intended wedding,--for in the meantime I -will so fashion the matter that Hero shall be -absent,--and there shall appear such seeming truth -of Hero's disloyalty that jealousy shall be called -assurance and all the preparation overthrown. - - - -DON JOHN -Grow this to what adverse issue it can, I will put -it in practise. Be cunning in the working this, and -thy fee is a thousand ducats. - - - -BORACHIO -Be you constant in the accusation, and my cunning -shall not shame me. - - - -DON JOHN -I will presently go learn their day of marriage. - - - -Exeunt - - -SCENE III. LEONATO'S orchard. -Enter BENEDICK - - -BENEDICK -Boy! - - - -Enter Boy - - -Boy -Signior? - - - -BENEDICK -In my chamber-window lies a book: bring it hither -to me in the orchard. - - - -Boy -I am here already, sir. - - - -BENEDICK -I know that; but I would have thee hence, and here again. -Exit Boy -I do much wonder that one man, seeing how much -another man is a fool when he dedicates his -behaviors to love, will, after he hath laughed at -such shallow follies in others, become the argument -of his own scorn by failing in love: and such a man -is Claudio. I have known when there was no music -with him but the drum and the fife; and now had he -rather hear the tabour and the pipe: I have known -when he would have walked ten mile a-foot to see a -good armour; and now will he lie ten nights awake, -carving the fashion of a new doublet. He was wont to -speak plain and to the purpose, like an honest man -and a soldier; and now is he turned orthography; his -words are a very fantastical banquet, just so many -strange dishes. May I be so converted and see with -these eyes? I cannot tell; I think not: I will not -be sworn, but love may transform me to an oyster; but -I'll take my oath on it, till he have made an oyster -of me, he shall never make me such a fool. One woman -is fair, yet I am well; another is wise, yet I am -well; another virtuous, yet I am well; but till all -graces be in one woman, one woman shall not come in -my grace. Rich she shall be, that's certain; wise, -or I'll none; virtuous, or I'll never cheapen her; -fair, or I'll never look on her; mild, or come not -near me; noble, or not I for an angel; of good -discourse, an excellent musician, and her hair shall -be of what colour it please God. Ha! the prince and -Monsieur Love! I will hide me in the arbour. - - -Withdraws -Enter DON PEDRO, CLAUDIO, and LEONATO - - -DON PEDRO -Come, shall we hear this music? - - - -CLAUDIO -Yea, my good lord. How still the evening is, -As hush'd on purpose to grace harmony! - - - -DON PEDRO -See you where Benedick hath hid himself? - - - -CLAUDIO -O, very well, my lord: the music ended, -We'll fit the kid-fox with a pennyworth. - - - -Enter BALTHASAR with Music - - -DON PEDRO -Come, Balthasar, we'll hear that song again. - - - -BALTHASAR -O, good my lord, tax not so bad a voice -To slander music any more than once. - - - -DON PEDRO -It is the witness still of excellency -To put a strange face on his own perfection. -I pray thee, sing, and let me woo no more. - - - -BALTHASAR -Because you talk of wooing, I will sing; -Since many a wooer doth commence his suit -To her he thinks not worthy, yet he wooes, -Yet will he swear he loves. - - - -DON PEDRO -Now, pray thee, come; -Or, if thou wilt hold longer argument, -Do it in notes. - - - -BALTHASAR -Note this before my notes; -There's not a note of mine that's worth the noting. - - - -DON PEDRO -Why, these are very crotchets that he speaks; -Note, notes, forsooth, and nothing. - - - -Air - - -BENEDICK -Now, divine air! now is his soul ravished! Is it -not strange that sheeps' guts should hale souls out -of men's bodies? Well, a horn for my money, when -all's done. - - - -The Song - - -BALTHASAR -Sigh no more, ladies, sigh no more, -Men were deceivers ever, -One foot in sea and one on shore, -To one thing constant never: -Then sigh not so, but let them go, -And be you blithe and bonny, -Converting all your sounds of woe -Into Hey nonny, nonny. -Sing no more ditties, sing no moe, -Of dumps so dull and heavy; -The fraud of men was ever so, -Since summer first was leafy: -Then sigh not so, &c. - - - -DON PEDRO -By my troth, a good song. - - - -BALTHASAR -And an ill singer, my lord. - - - -DON PEDRO -Ha, no, no, faith; thou singest well enough for a shift. - - - -BENEDICK -An he had been a dog that should have howled thus, -they would have hanged him: and I pray God his bad -voice bode no mischief. I had as lief have heard the -night-raven, come what plague could have come after -it. - - - -DON PEDRO -Yea, marry, dost thou hear, Balthasar? I pray thee, -get us some excellent music; for to-morrow night we -would have it at the Lady Hero's chamber-window. - - - -BALTHASAR -The best I can, my lord. - - - -DON PEDRO -Do so: farewell. -Exit BALTHASAR -Come hither, Leonato. What was it you told me of -to-day, that your niece Beatrice was in love with -Signior Benedick? - - - -CLAUDIO -O, ay: stalk on. stalk on; the fowl sits. I did -never think that lady would have loved any man. - - - -LEONATO -No, nor I neither; but most wonderful that she -should so dote on Signior Benedick, whom she hath in -all outward behaviors seemed ever to abhor. - - - -BENEDICK -Is't possible? Sits the wind in that corner? - - - -LEONATO -By my troth, my lord, I cannot tell what to think -of it but that she loves him with an enraged -affection: it is past the infinite of thought. - - - -DON PEDRO -May be she doth but counterfeit. - - - -CLAUDIO -Faith, like enough. - - - -LEONATO -O God, counterfeit! There was never counterfeit of -passion came so near the life of passion as she -discovers it. - - - -DON PEDRO -Why, what effects of passion shows she? - - - -CLAUDIO -Bait the hook well; this fish will bite. - - - -LEONATO -What effects, my lord? She will sit you, you heard -my daughter tell you how. - - - -CLAUDIO -She did, indeed. - - - -DON PEDRO -How, how, pray you? You amaze me: I would have I -thought her spirit had been invincible against all -assaults of affection. - - - -LEONATO -I would have sworn it had, my lord; especially -against Benedick. - - - -BENEDICK -I should think this a gull, but that the -white-bearded fellow speaks it: knavery cannot, -sure, hide himself in such reverence. - - - -CLAUDIO -He hath ta'en the infection: hold it up. - - - -DON PEDRO -Hath she made her affection known to Benedick? - - - -LEONATO -No; and swears she never will: that's her torment. - - - -CLAUDIO -'Tis true, indeed; so your daughter says: 'Shall -I,' says she, 'that have so oft encountered him -with scorn, write to him that I love him?' - - - -LEONATO -This says she now when she is beginning to write to -him; for she'll be up twenty times a night, and -there will she sit in her smock till she have writ a -sheet of paper: my daughter tells us all. - - - -CLAUDIO -Now you talk of a sheet of paper, I remember a -pretty jest your daughter told us of. - - - -LEONATO -O, when she had writ it and was reading it over, she -found Benedick and Beatrice between the sheet? - - - -CLAUDIO -That. - - - -LEONATO -O, she tore the letter into a thousand halfpence; -railed at herself, that she should be so immodest -to write to one that she knew would flout her; 'I -measure him,' says she, 'by my own spirit; for I -should flout him, if he writ to me; yea, though I -love him, I should.' - - - -CLAUDIO -Then down upon her knees she falls, weeps, sobs, -beats her heart, tears her hair, prays, curses; 'O -sweet Benedick! God give me patience!' - - - -LEONATO -She doth indeed; my daughter says so: and the -ecstasy hath so much overborne her that my daughter -is sometime afeared she will do a desperate outrage -to herself: it is very true. - - - -DON PEDRO -It were good that Benedick knew of it by some -other, if she will not discover it. - - - -CLAUDIO -To what end? He would make but a sport of it and -torment the poor lady worse. - - - -DON PEDRO -An he should, it were an alms to hang him. She's an -excellent sweet lady; and, out of all suspicion, -she is virtuous. - - - -CLAUDIO -And she is exceeding wise. - - - -DON PEDRO -In every thing but in loving Benedick. - - - -LEONATO -O, my lord, wisdom and blood combating in so tender -a body, we have ten proofs to one that blood hath -the victory. I am sorry for her, as I have just -cause, being her uncle and her guardian. - - - -DON PEDRO -I would she had bestowed this dotage on me: I would -have daffed all other respects and made her half -myself. I pray you, tell Benedick of it, and hear -what a' will say. - - - -LEONATO -Were it good, think you? - - - -CLAUDIO -Hero thinks surely she will die; for she says she -will die, if he love her not, and she will die, ere -she make her love known, and she will die, if he woo -her, rather than she will bate one breath of her -accustomed crossness. - - - -DON PEDRO -She doth well: if she should make tender of her -love, 'tis very possible he'll scorn it; for the -man, as you know all, hath a contemptible spirit. - - - -CLAUDIO -He is a very proper man. - - - -DON PEDRO -He hath indeed a good outward happiness. - - - -CLAUDIO -Before God! and, in my mind, very wise. - - - -DON PEDRO -He doth indeed show some sparks that are like wit. - - - -CLAUDIO -And I take him to be valiant. - - - -DON PEDRO -As Hector, I assure you: and in the managing of -quarrels you may say he is wise; for either he -avoids them with great discretion, or undertakes -them with a most Christian-like fear. - - - -LEONATO -If he do fear God, a' must necessarily keep peace: -if he break the peace, he ought to enter into a -quarrel with fear and trembling. - - - -DON PEDRO -And so will he do; for the man doth fear God, -howsoever it seems not in him by some large jests -he will make. Well I am sorry for your niece. Shall -we go seek Benedick, and tell him of her love? - - - -CLAUDIO -Never tell him, my lord: let her wear it out with -good counsel. - - - -LEONATO -Nay, that's impossible: she may wear her heart out first. - - - -DON PEDRO -Well, we will hear further of it by your daughter: -let it cool the while. I love Benedick well; and I -could wish he would modestly examine himself, to see -how much he is unworthy so good a lady. - - - -LEONATO -My lord, will you walk? dinner is ready. - - - -CLAUDIO -If he do not dote on her upon this, I will never -trust my expectation. - - - -DON PEDRO -Let there be the same net spread for her; and that -must your daughter and her gentlewomen carry. The -sport will be, when they hold one an opinion of -another's dotage, and no such matter: that's the -scene that I would see, which will be merely a -dumb-show. Let us send her to call him in to dinner. - - - -Exeunt DON PEDRO, CLAUDIO, and LEONATO - - -BENEDICK -Coming forward This can be no trick: the -conference was sadly borne. They have the truth of -this from Hero. They seem to pity the lady: it -seems her affections have their full bent. Love me! -why, it must be requited. I hear how I am censured: -they say I will bear myself proudly, if I perceive -the love come from her; they say too that she will -rather die than give any sign of affection. I did -never think to marry: I must not seem proud: happy -are they that hear their detractions and can put -them to mending. They say the lady is fair; 'tis a -truth, I can bear them witness; and virtuous; 'tis -so, I cannot reprove it; and wise, but for loving -me; by my troth, it is no addition to her wit, nor -no great argument of her folly, for I will be -horribly in love with her. I may chance have some -odd quirks and remnants of wit broken on me, -because I have railed so long against marriage: but -doth not the appetite alter? a man loves the meat -in his youth that he cannot endure in his age. -Shall quips and sentences and these paper bullets of -the brain awe a man from the career of his humour? -No, the world must be peopled. When I said I would -die a bachelor, I did not think I should live till I -were married. Here comes Beatrice. By this day! -she's a fair lady: I do spy some marks of love in -her. - - - -Enter BEATRICE - - -BEATRICE -Against my will I am sent to bid you come in to dinner. - - - -BENEDICK -Fair Beatrice, I thank you for your pains. - - - -BEATRICE -I took no more pains for those thanks than you take -pains to thank me: if it had been painful, I would -not have come. - - - -BENEDICK -You take pleasure then in the message? - - - -BEATRICE -Yea, just so much as you may take upon a knife's -point and choke a daw withal. You have no stomach, -signior: fare you well. - - - -Exit - - -BENEDICK -Ha! 'Against my will I am sent to bid you come in -to dinner;' there's a double meaning in that 'I took -no more pains for those thanks than you took pains -to thank me.' that's as much as to say, Any pains -that I take for you is as easy as thanks. If I do -not take pity of her, I am a villain; if I do not -love her, I am a Jew. I will go get her picture. - - - -Exit - - - - -ACT III - -SCENE I. LEONATO'S garden. -Enter HERO, MARGARET, and URSULA - - -HERO -Good Margaret, run thee to the parlor; -There shalt thou find my cousin Beatrice -Proposing with the prince and Claudio: -Whisper her ear and tell her, I and Ursula -Walk in the orchard and our whole discourse -Is all of her; say that thou overheard'st us; -And bid her steal into the pleached bower, -Where honeysuckles, ripen'd by the sun, -Forbid the sun to enter, like favourites, -Made proud by princes, that advance their pride -Against that power that bred it: there will she hide her, -To listen our purpose. This is thy office; -Bear thee well in it and leave us alone. - - - -MARGARET -I'll make her come, I warrant you, presently. - - - -Exit - - -HERO -Now, Ursula, when Beatrice doth come, -As we do trace this alley up and down, -Our talk must only be of Benedick. -When I do name him, let it be thy part -To praise him more than ever man did merit: -My talk to thee must be how Benedick -Is sick in love with Beatrice. Of this matter -Is little Cupid's crafty arrow made, -That only wounds by hearsay. -Enter BEATRICE, behind -Now begin; -For look where Beatrice, like a lapwing, runs -Close by the ground, to hear our conference. - - - -URSULA -The pleasant'st angling is to see the fish -Cut with her golden oars the silver stream, -And greedily devour the treacherous bait: -So angle we for Beatrice; who even now -Is couched in the woodbine coverture. -Fear you not my part of the dialogue. - - - -HERO -Then go we near her, that her ear lose nothing -Of the false sweet bait that we lay for it. -Approaching the bower -No, truly, Ursula, she is too disdainful; -I know her spirits are as coy and wild -As haggerds of the rock. - - - -URSULA -But are you sure -That Benedick loves Beatrice so entirely? - - - -HERO -So says the prince and my new-trothed lord. - - - -URSULA -And did they bid you tell her of it, madam? - - - -HERO -They did entreat me to acquaint her of it; -But I persuaded them, if they loved Benedick, -To wish him wrestle with affection, -And never to let Beatrice know of it. - - - -URSULA -Why did you so? Doth not the gentleman -Deserve as full as fortunate a bed -As ever Beatrice shall couch upon? - - - -HERO -O god of love! I know he doth deserve -As much as may be yielded to a man: -But Nature never framed a woman's heart -Of prouder stuff than that of Beatrice; -Disdain and scorn ride sparkling in her eyes, -Misprising what they look on, and her wit -Values itself so highly that to her -All matter else seems weak: she cannot love, -Nor take no shape nor project of affection, -She is so self-endeared. - - - -URSULA -Sure, I think so; -And therefore certainly it were not good -She knew his love, lest she make sport at it. - - - -HERO -Why, you speak truth. I never yet saw man, -How wise, how noble, young, how rarely featured, -But she would spell him backward: if fair-faced, -She would swear the gentleman should be her sister; -If black, why, Nature, drawing of an antique, -Made a foul blot; if tall, a lance ill-headed; -If low, an agate very vilely cut; -If speaking, why, a vane blown with all winds; -If silent, why, a block moved with none. -So turns she every man the wrong side out -And never gives to truth and virtue that -Which simpleness and merit purchaseth. - - - -URSULA -Sure, sure, such carping is not commendable. - - - -HERO -No, not to be so odd and from all fashions -As Beatrice is, cannot be commendable: -But who dare tell her so? If I should speak, -She would mock me into air; O, she would laugh me -Out of myself, press me to death with wit. -Therefore let Benedick, like cover'd fire, -Consume away in sighs, waste inwardly: -It were a better death than die with mocks, -Which is as bad as die with tickling. - - - -URSULA -Yet tell her of it: hear what she will say. - - - -HERO -No; rather I will go to Benedick -And counsel him to fight against his passion. -And, truly, I'll devise some honest slanders -To stain my cousin with: one doth not know -How much an ill word may empoison liking. - - - -URSULA -O, do not do your cousin such a wrong. -She cannot be so much without true judgment-- -Having so swift and excellent a wit -As she is prized to have--as to refuse -So rare a gentleman as Signior Benedick. - - - -HERO -He is the only man of Italy. -Always excepted my dear Claudio. - - - -URSULA -I pray you, be not angry with me, madam, -Speaking my fancy: Signior Benedick, -For shape, for bearing, argument and valour, -Goes foremost in report through Italy. - - - -HERO -Indeed, he hath an excellent good name. - - - -URSULA -His excellence did earn it, ere he had it. -When are you married, madam? - - - -HERO -Why, every day, to-morrow. Come, go in: -I'll show thee some attires, and have thy counsel -Which is the best to furnish me to-morrow. - - - -URSULA -She's limed, I warrant you: we have caught her, madam. - - - -HERO -If it proves so, then loving goes by haps: -Some Cupid kills with arrows, some with traps. - - - -Exeunt HERO and URSULA - - -BEATRICE -Coming forward -What fire is in mine ears? Can this be true? -Stand I condemn'd for pride and scorn so much? -Contempt, farewell! and maiden pride, adieu! -No glory lives behind the back of such. -And, Benedick, love on; I will requite thee, -Taming my wild heart to thy loving hand: -If thou dost love, my kindness shall incite thee -To bind our loves up in a holy band; -For others say thou dost deserve, and I -Believe it better than reportingly. - - - -Exit - - -SCENE II. A room in LEONATO'S house -Enter DON PEDRO, CLAUDIO, BENEDICK, and LEONATO - - -DON PEDRO -I do but stay till your marriage be consummate, and -then go I toward Arragon. - - - -CLAUDIO -I'll bring you thither, my lord, if you'll -vouchsafe me. - - - -DON PEDRO -Nay, that would be as great a soil in the new gloss -of your marriage as to show a child his new coat -and forbid him to wear it. I will only be bold -with Benedick for his company; for, from the crown -of his head to the sole of his foot, he is all -mirth: he hath twice or thrice cut Cupid's -bow-string and the little hangman dare not shoot at -him; he hath a heart as sound as a bell and his -tongue is the clapper, for what his heart thinks his -tongue speaks. - - - -BENEDICK -Gallants, I am not as I have been. - - - -LEONATO -So say I methinks you are sadder. - - - -CLAUDIO -I hope he be in love. - - - -DON PEDRO -Hang him, truant! there's no true drop of blood in -him, to be truly touched with love: if he be sad, -he wants money. - - - -BENEDICK -I have the toothache. - - - -DON PEDRO -Draw it. - - - -BENEDICK -Hang it! - - - -CLAUDIO -You must hang it first, and draw it afterwards. - - - -DON PEDRO -What! sigh for the toothache? - - - -LEONATO -Where is but a humour or a worm. - - - -BENEDICK -Well, every one can master a grief but he that has -it. - - - -CLAUDIO -Yet say I, he is in love. - - - -DON PEDRO -There is no appearance of fancy in him, unless it be -a fancy that he hath to strange disguises; as, to be -a Dutchman today, a Frenchman to-morrow, or in the -shape of two countries at once, as, a German from -the waist downward, all slops, and a Spaniard from -the hip upward, no doublet. Unless he have a fancy -to this foolery, as it appears he hath, he is no -fool for fancy, as you would have it appear he is. - - - -CLAUDIO -If he be not in love with some woman, there is no -believing old signs: a' brushes his hat o' -mornings; what should that bode? - - - -DON PEDRO -Hath any man seen him at the barber's? - - - -CLAUDIO -No, but the barber's man hath been seen with him, -and the old ornament of his cheek hath already -stuffed tennis-balls. - - - -LEONATO -Indeed, he looks younger than he did, by the loss of a beard. - - - -DON PEDRO -Nay, a' rubs himself with civet: can you smell him -out by that? - - - -CLAUDIO -That's as much as to say, the sweet youth's in love. - - - -DON PEDRO -The greatest note of it is his melancholy. - - - -CLAUDIO -And when was he wont to wash his face? - - - -DON PEDRO -Yea, or to paint himself? for the which, I hear -what they say of him. - - - -CLAUDIO -Nay, but his jesting spirit; which is now crept into -a lute-string and now governed by stops. - - - -DON PEDRO -Indeed, that tells a heavy tale for him: conclude, -conclude he is in love. - - - -CLAUDIO -Nay, but I know who loves him. - - - -DON PEDRO -That would I know too: I warrant, one that knows him not. - - - -CLAUDIO -Yes, and his ill conditions; and, in despite of -all, dies for him. - - - -DON PEDRO -She shall be buried with her face upwards. - - - -BENEDICK -Yet is this no charm for the toothache. Old -signior, walk aside with me: I have studied eight -or nine wise words to speak to you, which these -hobby-horses must not hear. - - - -Exeunt BENEDICK and LEONATO - - -DON PEDRO -For my life, to break with him about Beatrice. - - - -CLAUDIO -'Tis even so. Hero and Margaret have by this -played their parts with Beatrice; and then the two -bears will not bite one another when they meet. - - - -Enter DON JOHN - - -DON JOHN -My lord and brother, God save you! - - - -DON PEDRO -Good den, brother. - - - -DON JOHN -If your leisure served, I would speak with you. - - - -DON PEDRO -In private? - - - -DON JOHN -If it please you: yet Count Claudio may hear; for -what I would speak of concerns him. - - - -DON PEDRO -What's the matter? - - - -DON JOHN -To CLAUDIO Means your lordship to be married -to-morrow? - - - -DON PEDRO -You know he does. - - - -DON JOHN -I know not that, when he knows what I know. - - - -CLAUDIO -If there be any impediment, I pray you discover it. - - - -DON JOHN -You may think I love you not: let that appear -hereafter, and aim better at me by that I now will -manifest. For my brother, I think he holds you -well, and in dearness of heart hath holp to effect -your ensuing marriage;--surely suit ill spent and -labour ill bestowed. - - - -DON PEDRO -Why, what's the matter? - - - -DON JOHN -I came hither to tell you; and, circumstances -shortened, for she has been too long a talking of, -the lady is disloyal. - - - -CLAUDIO -Who, Hero? - - - -DON PEDRO -Even she; Leonato's Hero, your Hero, every man's Hero: - - - -CLAUDIO -Disloyal? - - - -DON JOHN -The word is too good to paint out her wickedness; I -could say she were worse: think you of a worse -title, and I will fit her to it. Wonder not till -further warrant: go but with me to-night, you shall -see her chamber-window entered, even the night -before her wedding-day: if you love her then, -to-morrow wed her; but it would better fit your honour -to change your mind. - - - -CLAUDIO -May this be so? - - - -DON PEDRO -I will not think it. - - - -DON JOHN -If you dare not trust that you see, confess not -that you know: if you will follow me, I will show -you enough; and when you have seen more and heard -more, proceed accordingly. - - - -CLAUDIO -If I see any thing to-night why I should not marry -her to-morrow in the congregation, where I should -wed, there will I shame her. - - - -DON PEDRO -And, as I wooed for thee to obtain her, I will join -with thee to disgrace her. - - - -DON JOHN -I will disparage her no farther till you are my -witnesses: bear it coldly but till midnight, and -let the issue show itself. - - - -DON PEDRO -O day untowardly turned! - - - -CLAUDIO -O mischief strangely thwarting! - - - -DON JOHN -O plague right well prevented! so will you say when -you have seen the sequel. - - - -Exeunt - - -SCENE III. A street. -Enter DOGBERRY and VERGES with the Watch - - -DOGBERRY -Are you good men and true? - - - -VERGES -Yea, or else it were pity but they should suffer -salvation, body and soul. - - - -DOGBERRY -Nay, that were a punishment too good for them, if -they should have any allegiance in them, being -chosen for the prince's watch. - - - -VERGES -Well, give them their charge, neighbour Dogberry. - - - -DOGBERRY -First, who think you the most desertless man to be -constable? - - - -First Watchman -Hugh Otecake, sir, or George Seacole; for they can -write and read. - - - -DOGBERRY -Come hither, neighbour Seacole. God hath blessed -you with a good name: to be a well-favoured man is -the gift of fortune; but to write and read comes by nature. - - - -Second Watchman -Both which, master constable,-- - - - -DOGBERRY -You have: I knew it would be your answer. Well, -for your favour, sir, why, give God thanks, and make -no boast of it; and for your writing and reading, -let that appear when there is no need of such -vanity. You are thought here to be the most -senseless and fit man for the constable of the -watch; therefore bear you the lantern. This is your -charge: you shall comprehend all vagrom men; you are -to bid any man stand, in the prince's name. - - - -Second Watchman -How if a' will not stand? - - - -DOGBERRY -Why, then, take no note of him, but let him go; and -presently call the rest of the watch together and -thank God you are rid of a knave. - - - -VERGES -If he will not stand when he is bidden, he is none -of the prince's subjects. - - - -DOGBERRY -True, and they are to meddle with none but the -prince's subjects. You shall also make no noise in -the streets; for, for the watch to babble and to -talk is most tolerable and not to be endured. - - - -Watchman -We will rather sleep than talk: we know what -belongs to a watch. - - - -DOGBERRY -Why, you speak like an ancient and most quiet -watchman; for I cannot see how sleeping should -offend: only, have a care that your bills be not -stolen. Well, you are to call at all the -ale-houses, and bid those that are drunk get them to bed. - - - -Watchman -How if they will not? - - - -DOGBERRY -Why, then, let them alone till they are sober: if -they make you not then the better answer, you may -say they are not the men you took them for. - - - -Watchman -Well, sir. - - - -DOGBERRY -If you meet a thief, you may suspect him, by virtue -of your office, to be no true man; and, for such -kind of men, the less you meddle or make with them, -why the more is for your honesty. - - - -Watchman -If we know him to be a thief, shall we not lay -hands on him? - - - -DOGBERRY -Truly, by your office, you may; but I think they -that touch pitch will be defiled: the most peaceable -way for you, if you do take a thief, is to let him -show himself what he is and steal out of your company. - - - -VERGES -You have been always called a merciful man, partner. - - - -DOGBERRY -Truly, I would not hang a dog by my will, much more -a man who hath any honesty in him. - - - -VERGES -If you hear a child cry in the night, you must call -to the nurse and bid her still it. - - - -Watchman -How if the nurse be asleep and will not hear us? - - - -DOGBERRY -Why, then, depart in peace, and let the child wake -her with crying; for the ewe that will not hear her -lamb when it baes will never answer a calf when he bleats. - - - -VERGES -'Tis very true. - - - -DOGBERRY -This is the end of the charge:--you, constable, are -to present the prince's own person: if you meet the -prince in the night, you may stay him. - - - -VERGES -Nay, by'r our lady, that I think a' cannot. - - - -DOGBERRY -Five shillings to one on't, with any man that knows -the statutes, he may stay him: marry, not without -the prince be willing; for, indeed, the watch ought -to offend no man; and it is an offence to stay a -man against his will. - - - -VERGES -By'r lady, I think it be so. - - - -DOGBERRY -Ha, ha, ha! Well, masters, good night: an there be -any matter of weight chances, call up me: keep your -fellows' counsels and your own; and good night. -Come, neighbour. - - - -Watchman -Well, masters, we hear our charge: let us go sit here -upon the church-bench till two, and then all to bed. - - - -DOGBERRY -One word more, honest neighbours. I pray you watch -about Signior Leonato's door; for the wedding being -there to-morrow, there is a great coil to-night. -Adieu: be vigitant, I beseech you. - - -Exeunt DOGBERRY and VERGES -Enter BORACHIO and CONRADE - - -BORACHIO -What Conrade! - - - -Watchman -Aside Peace! stir not. - - - -BORACHIO -Conrade, I say! - - - -CONRADE -Here, man; I am at thy elbow. - - - -BORACHIO -Mass, and my elbow itched; I thought there would a -scab follow. - - - -CONRADE -I will owe thee an answer for that: and now forward -with thy tale. - - - -BORACHIO -Stand thee close, then, under this pent-house, for -it drizzles rain; and I will, like a true drunkard, -utter all to thee. - - - -Watchman -Aside Some treason, masters: yet stand close. - - - -BORACHIO -Therefore know I have earned of Don John a thousand ducats. - - - -CONRADE -Is it possible that any villany should be so dear? - - - -BORACHIO -Thou shouldst rather ask if it were possible any -villany should be so rich; for when rich villains -have need of poor ones, poor ones may make what -price they will. - - - -CONRADE -I wonder at it. - - - -BORACHIO -That shows thou art unconfirmed. Thou knowest that -the fashion of a doublet, or a hat, or a cloak, is -nothing to a man. - - - -CONRADE -Yes, it is apparel. - - - -BORACHIO -I mean, the fashion. - - - -CONRADE -Yes, the fashion is the fashion. - - - -BORACHIO -Tush! I may as well say the fool's the fool. But -seest thou not what a deformed thief this fashion -is? - - - -Watchman -Aside I know that Deformed; a' has been a vile -thief this seven year; a' goes up and down like a -gentleman: I remember his name. - - - -BORACHIO -Didst thou not hear somebody? - - - -CONRADE -No; 'twas the vane on the house. - - - -BORACHIO -Seest thou not, I say, what a deformed thief this -fashion is? how giddily a' turns about all the hot -bloods between fourteen and five-and-thirty? -sometimes fashioning them like Pharaoh's soldiers -in the reeky painting, sometime like god Bel's -priests in the old church-window, sometime like the -shaven Hercules in the smirched worm-eaten tapestry, -where his codpiece seems as massy as his club? - - - -CONRADE -All this I see; and I see that the fashion wears -out more apparel than the man. But art not thou -thyself giddy with the fashion too, that thou hast -shifted out of thy tale into telling me of the fashion? - - - -BORACHIO -Not so, neither: but know that I have to-night -wooed Margaret, the Lady Hero's gentlewoman, by the -name of Hero: she leans me out at her mistress' -chamber-window, bids me a thousand times good -night,--I tell this tale vilely:--I should first -tell thee how the prince, Claudio and my master, -planted and placed and possessed by my master Don -John, saw afar off in the orchard this amiable encounter. - - - -CONRADE -And thought they Margaret was Hero? - - - -BORACHIO -Two of them did, the prince and Claudio; but the -devil my master knew she was Margaret; and partly -by his oaths, which first possessed them, partly by -the dark night, which did deceive them, but chiefly -by my villany, which did confirm any slander that -Don John had made, away went Claudio enraged; swore -he would meet her, as he was appointed, next morning -at the temple, and there, before the whole -congregation, shame her with what he saw o'er night -and send her home again without a husband. - - - -First Watchman -We charge you, in the prince's name, stand! - - - -Second Watchman -Call up the right master constable. We have here -recovered the most dangerous piece of lechery that -ever was known in the commonwealth. - - - -First Watchman -And one Deformed is one of them: I know him; a' -wears a lock. - - - -CONRADE -Masters, masters,-- - - - -Second Watchman -You'll be made bring Deformed forth, I warrant you. - - - -CONRADE -Masters,-- - - - -First Watchman -Never speak: we charge you let us obey you to go with us. - - - -BORACHIO -We are like to prove a goodly commodity, being taken -up of these men's bills. - - - -CONRADE -A commodity in question, I warrant you. Come, we'll obey you. - - - -Exeunt - - -SCENE IV. HERO's apartment. -Enter HERO, MARGARET, and URSULA - - -HERO -Good Ursula, wake my cousin Beatrice, and desire -her to rise. - - - -URSULA -I will, lady. - - - -HERO -And bid her come hither. - - - -URSULA -Well. - - - -Exit - - -MARGARET -Troth, I think your other rabato were better. - - - -HERO -No, pray thee, good Meg, I'll wear this. - - - -MARGARET -By my troth, 's not so good; and I warrant your -cousin will say so. - - - -HERO -My cousin's a fool, and thou art another: I'll wear -none but this. - - - -MARGARET -I like the new tire within excellently, if the hair -were a thought browner; and your gown's a most rare -fashion, i' faith. I saw the Duchess of Milan's -gown that they praise so. - - - -HERO -O, that exceeds, they say. - - - -MARGARET -By my troth, 's but a night-gown in respect of -yours: cloth o' gold, and cuts, and laced with -silver, set with pearls, down sleeves, side sleeves, -and skirts, round underborne with a bluish tinsel: -but for a fine, quaint, graceful and excellent -fashion, yours is worth ten on 't. - - - -HERO -God give me joy to wear it! for my heart is -exceeding heavy. - - - -MARGARET -'Twill be heavier soon by the weight of a man. - - - -HERO -Fie upon thee! art not ashamed? - - - -MARGARET -Of what, lady? of speaking honourably? Is not -marriage honourable in a beggar? Is not your lord -honourable without marriage? I think you would have -me say, 'saving your reverence, a husband:' and bad -thinking do not wrest true speaking, I'll offend -nobody: is there any harm in 'the heavier for a -husband'? None, I think, and it be the right husband -and the right wife; otherwise 'tis light, and not -heavy: ask my Lady Beatrice else; here she comes. - - - -Enter BEATRICE - - -HERO -Good morrow, coz. - - - -BEATRICE -Good morrow, sweet Hero. - - - -HERO -Why how now? do you speak in the sick tune? - - - -BEATRICE -I am out of all other tune, methinks. - - - -MARGARET -Clap's into 'Light o' love;' that goes without a -burden: do you sing it, and I'll dance it. - - - -BEATRICE -Ye light o' love, with your heels! then, if your -husband have stables enough, you'll see he shall -lack no barns. - - - -MARGARET -O illegitimate construction! I scorn that with my heels. - - - -BEATRICE -'Tis almost five o'clock, cousin; tis time you were -ready. By my troth, I am exceeding ill: heigh-ho! - - - -MARGARET -For a hawk, a horse, or a husband? - - - -BEATRICE -For the letter that begins them all, H. - - - -MARGARET -Well, and you be not turned Turk, there's no more -sailing by the star. - - - -BEATRICE -What means the fool, trow? - - - -MARGARET -Nothing I; but God send every one their heart's desire! - - - -HERO -These gloves the count sent me; they are an -excellent perfume. - - - -BEATRICE -I am stuffed, cousin; I cannot smell. - - - -MARGARET -A maid, and stuffed! there's goodly catching of cold. - - - -BEATRICE -O, God help me! God help me! how long have you -professed apprehension? - - - -MARGARET -Even since you left it. Doth not my wit become me rarely? - - - -BEATRICE -It is not seen enough, you should wear it in your -cap. By my troth, I am sick. - - - -MARGARET -Get you some of this distilled Carduus Benedictus, -and lay it to your heart: it is the only thing for a qualm. - - - -HERO -There thou prickest her with a thistle. - - - -BEATRICE -Benedictus! why Benedictus? you have some moral in -this Benedictus. - - - -MARGARET -Moral! no, by my troth, I have no moral meaning; I -meant, plain holy-thistle. You may think perchance -that I think you are in love: nay, by'r lady, I am -not such a fool to think what I list, nor I list -not to think what I can, nor indeed I cannot think, -if I would think my heart out of thinking, that you -are in love or that you will be in love or that you -can be in love. Yet Benedick was such another, and -now is he become a man: he swore he would never -marry, and yet now, in despite of his heart, he eats -his meat without grudging: and how you may be -converted I know not, but methinks you look with -your eyes as other women do. - - - -BEATRICE -What pace is this that thy tongue keeps? - - - -MARGARET -Not a false gallop. - - - -Re-enter URSULA - - -URSULA -Madam, withdraw: the prince, the count, Signior -Benedick, Don John, and all the gallants of the -town, are come to fetch you to church. - - - -HERO -Help to dress me, good coz, good Meg, good Ursula. - - - -Exeunt - - -SCENE V. Another room in LEONATO'S house. -Enter LEONATO, with DOGBERRY and VERGES - - -LEONATO -What would you with me, honest neighbour? - - - -DOGBERRY -Marry, sir, I would have some confidence with you -that decerns you nearly. - - - -LEONATO -Brief, I pray you; for you see it is a busy time with me. - - - -DOGBERRY -Marry, this it is, sir. - - - -VERGES -Yes, in truth it is, sir. - - - -LEONATO -What is it, my good friends? - - - -DOGBERRY -Goodman Verges, sir, speaks a little off the -matter: an old man, sir, and his wits are not so -blunt as, God help, I would desire they were; but, -in faith, honest as the skin between his brows. - - - -VERGES -Yes, I thank God I am as honest as any man living -that is an old man and no honester than I. - - - -DOGBERRY -Comparisons are odorous: palabras, neighbour Verges. - - - -LEONATO -Neighbours, you are tedious. - - - -DOGBERRY -It pleases your worship to say so, but we are the -poor duke's officers; but truly, for mine own part, -if I were as tedious as a king, I could find it in -my heart to bestow it all of your worship. - - - -LEONATO -All thy tediousness on me, ah? - - - -DOGBERRY -Yea, an 'twere a thousand pound more than 'tis; for -I hear as good exclamation on your worship as of any -man in the city; and though I be but a poor man, I -am glad to hear it. - - - -VERGES -And so am I. - - - -LEONATO -I would fain know what you have to say. - - - -VERGES -Marry, sir, our watch to-night, excepting your -worship's presence, ha' ta'en a couple of as arrant -knaves as any in Messina. - - - -DOGBERRY -A good old man, sir; he will be talking: as they -say, when the age is in, the wit is out: God help -us! it is a world to see. Well said, i' faith, -neighbour Verges: well, God's a good man; an two men -ride of a horse, one must ride behind. An honest -soul, i' faith, sir; by my troth he is, as ever -broke bread; but God is to be worshipped; all men -are not alike; alas, good neighbour! - - - -LEONATO -Indeed, neighbour, he comes too short of you. - - - -DOGBERRY -Gifts that God gives. - - - -LEONATO -I must leave you. - - - -DOGBERRY -One word, sir: our watch, sir, have indeed -comprehended two aspicious persons, and we would -have them this morning examined before your worship. - - - -LEONATO -Take their examination yourself and bring it me: I -am now in great haste, as it may appear unto you. - - - -DOGBERRY -It shall be suffigance. - - - -LEONATO -Drink some wine ere you go: fare you well. - - - -Enter a Messenger - - -Messenger -My lord, they stay for you to give your daughter to -her husband. - - - -LEONATO -I'll wait upon them: I am ready. - - - -Exeunt LEONATO and Messenger - - -DOGBERRY -Go, good partner, go, get you to Francis Seacole; -bid him bring his pen and inkhorn to the gaol: we -are now to examination these men. - - - -VERGES -And we must do it wisely. - - - -DOGBERRY -We will spare for no wit, I warrant you; here's -that shall drive some of them to a non-come: only -get the learned writer to set down our -excommunication and meet me at the gaol. - - - -Exeunt - - - - -ACT IV - -SCENE I. A church. -Enter DON PEDRO, DON JOHN, LEONATO, FRIAR FRANCIS, -CLAUDIO, BENEDICK, HERO, BEATRICE, and Attendants - - -LEONATO -Come, Friar Francis, be brief; only to the plain -form of marriage, and you shall recount their -particular duties afterwards. - - - -FRIAR FRANCIS -You come hither, my lord, to marry this lady. - - - -CLAUDIO -No. - - - -LEONATO -To be married to her: friar, you come to marry her. - - - -FRIAR FRANCIS -Lady, you come hither to be married to this count. - - - -HERO -I do. - - - -FRIAR FRANCIS -If either of you know any inward impediment why you -should not be conjoined, charge you, on your souls, -to utter it. - - - -CLAUDIO -Know you any, Hero? - - - -HERO -None, my lord. - - - -FRIAR FRANCIS -Know you any, count? - - - -LEONATO -I dare make his answer, none. - - - -CLAUDIO -O, what men dare do! what men may do! what men daily -do, not knowing what they do! - - - -BENEDICK -How now! interjections? Why, then, some be of -laughing, as, ah, ha, he! - - - -CLAUDIO -Stand thee by, friar. Father, by your leave: -Will you with free and unconstrained soul -Give me this maid, your daughter? - - - -LEONATO -As freely, son, as God did give her me. - - - -CLAUDIO -And what have I to give you back, whose worth -May counterpoise this rich and precious gift? - - - -DON PEDRO -Nothing, unless you render her again. - - - -CLAUDIO -Sweet prince, you learn me noble thankfulness. -There, Leonato, take her back again: -Give not this rotten orange to your friend; -She's but the sign and semblance of her honour. -Behold how like a maid she blushes here! -O, what authority and show of truth -Can cunning sin cover itself withal! -Comes not that blood as modest evidence -To witness simple virtue? Would you not swear, -All you that see her, that she were a maid, -By these exterior shows? But she is none: -She knows the heat of a luxurious bed; -Her blush is guiltiness, not modesty. - - - -LEONATO -What do you mean, my lord? - - - -CLAUDIO -Not to be married, -Not to knit my soul to an approved wanton. - - - -LEONATO -Dear my lord, if you, in your own proof, -Have vanquish'd the resistance of her youth, -And made defeat of her virginity,-- - - - -CLAUDIO -I know what you would say: if I have known her, -You will say she did embrace me as a husband, -And so extenuate the 'forehand sin: -No, Leonato, -I never tempted her with word too large; -But, as a brother to his sister, show'd -Bashful sincerity and comely love. - - - -HERO -And seem'd I ever otherwise to you? - - - -CLAUDIO -Out on thee! Seeming! I will write against it: -You seem to me as Dian in her orb, -As chaste as is the bud ere it be blown; -But you are more intemperate in your blood -Than Venus, or those pamper'd animals -That rage in savage sensuality. - - - -HERO -Is my lord well, that he doth speak so wide? - - - -LEONATO -Sweet prince, why speak not you? - - - -DON PEDRO -What should I speak? -I stand dishonour'd, that have gone about -To link my dear friend to a common stale. - - - -LEONATO -Are these things spoken, or do I but dream? - - - -DON JOHN -Sir, they are spoken, and these things are true. - - - -BENEDICK -This looks not like a nuptial. - - - -HERO -True! O God! - - - -CLAUDIO -Leonato, stand I here? -Is this the prince? is this the prince's brother? -Is this face Hero's? are our eyes our own? - - - -LEONATO -All this is so: but what of this, my lord? - - - -CLAUDIO -Let me but move one question to your daughter; -And, by that fatherly and kindly power -That you have in her, bid her answer truly. - - - -LEONATO -I charge thee do so, as thou art my child. - - - -HERO -O, God defend me! how am I beset! -What kind of catechising call you this? - - - -CLAUDIO -To make you answer truly to your name. - - - -HERO -Is it not Hero? Who can blot that name -With any just reproach? - - - -CLAUDIO -Marry, that can Hero; -Hero itself can blot out Hero's virtue. -What man was he talk'd with you yesternight -Out at your window betwixt twelve and one? -Now, if you are a maid, answer to this. - - - -HERO -I talk'd with no man at that hour, my lord. - - - -DON PEDRO -Why, then are you no maiden. Leonato, -I am sorry you must hear: upon mine honour, -Myself, my brother and this grieved count -Did see her, hear her, at that hour last night -Talk with a ruffian at her chamber-window -Who hath indeed, most like a liberal villain, -Confess'd the vile encounters they have had -A thousand times in secret. - - - -DON JOHN -Fie, fie! they are not to be named, my lord, -Not to be spoke of; -There is not chastity enough in language -Without offence to utter them. Thus, pretty lady, -I am sorry for thy much misgovernment. - - - -CLAUDIO -O Hero, what a Hero hadst thou been, -If half thy outward graces had been placed -About thy thoughts and counsels of thy heart! -But fare thee well, most foul, most fair! farewell, -Thou pure impiety and impious purity! -For thee I'll lock up all the gates of love, -And on my eyelids shall conjecture hang, -To turn all beauty into thoughts of harm, -And never shall it more be gracious. - - - -LEONATO -Hath no man's dagger here a point for me? - - - -HERO swoons - - -BEATRICE -Why, how now, cousin! wherefore sink you down? - - - -DON JOHN -Come, let us go. These things, come thus to light, -Smother her spirits up. - - - -Exeunt DON PEDRO, DON JOHN, and CLAUDIO - - -BENEDICK -How doth the lady? - - - -BEATRICE -Dead, I think. Help, uncle! -Hero! why, Hero! Uncle! Signior Benedick! Friar! - - - -LEONATO -O Fate! take not away thy heavy hand. -Death is the fairest cover for her shame -That may be wish'd for. - - - -BEATRICE -How now, cousin Hero! - - - -FRIAR FRANCIS -Have comfort, lady. - - - -LEONATO -Dost thou look up? - - - -FRIAR FRANCIS -Yea, wherefore should she not? - - - -LEONATO -Wherefore! Why, doth not every earthly thing -Cry shame upon her? Could she here deny -The story that is printed in her blood? -Do not live, Hero; do not ope thine eyes: -For, did I think thou wouldst not quickly die, -Thought I thy spirits were stronger than thy shames, -Myself would, on the rearward of reproaches, -Strike at thy life. Grieved I, I had but one? -Chid I for that at frugal nature's frame? -O, one too much by thee! Why had I one? -Why ever wast thou lovely in my eyes? -Why had I not with charitable hand -Took up a beggar's issue at my gates, -Who smirch'd thus and mired with infamy, -I might have said 'No part of it is mine; -This shame derives itself from unknown loins'? -But mine and mine I loved and mine I praised -And mine that I was proud on, mine so much -That I myself was to myself not mine, -Valuing of her,--why, she, O, she is fallen -Into a pit of ink, that the wide sea -Hath drops too few to wash her clean again -And salt too little which may season give -To her foul-tainted flesh! - - - -BENEDICK -Sir, sir, be patient. -For my part, I am so attired in wonder, -I know not what to say. - - - -BEATRICE -O, on my soul, my cousin is belied! - - - -BENEDICK -Lady, were you her bedfellow last night? - - - -BEATRICE -No, truly not; although, until last night, -I have this twelvemonth been her bedfellow. - - - -LEONATO -Confirm'd, confirm'd! O, that is stronger made -Which was before barr'd up with ribs of iron! -Would the two princes lie, and Claudio lie, -Who loved her so, that, speaking of her foulness, -Wash'd it with tears? Hence from her! let her die. - - - -FRIAR FRANCIS -Hear me a little; for I have only been -Silent so long and given way unto -This course of fortune -By noting of the lady. I have mark'd -A thousand blushing apparitions -To start into her face, a thousand innocent shames -In angel whiteness beat away those blushes; -And in her eye there hath appear'd a fire, -To burn the errors that these princes hold -Against her maiden truth. Call me a fool; -Trust not my reading nor my observations, -Which with experimental seal doth warrant -The tenor of my book; trust not my age, -My reverence, calling, nor divinity, -If this sweet lady lie not guiltless here -Under some biting error. - - - -LEONATO -Friar, it cannot be. -Thou seest that all the grace that she hath left -Is that she will not add to her damnation -A sin of perjury; she not denies it: -Why seek'st thou then to cover with excuse -That which appears in proper nakedness? - - - -FRIAR FRANCIS -Lady, what man is he you are accused of? - - - -HERO -They know that do accuse me; I know none: -If I know more of any man alive -Than that which maiden modesty doth warrant, -Let all my sins lack mercy! O my father, -Prove you that any man with me conversed -At hours unmeet, or that I yesternight -Maintain'd the change of words with any creature, -Refuse me, hate me, torture me to death! - - - -FRIAR FRANCIS -There is some strange misprision in the princes. - - - -BENEDICK -Two of them have the very bent of honour; -And if their wisdoms be misled in this, -The practise of it lives in John the bastard, -Whose spirits toil in frame of villanies. - - - -LEONATO -I know not. If they speak but truth of her, -These hands shall tear her; if they wrong her honour, -The proudest of them shall well hear of it. -Time hath not yet so dried this blood of mine, -Nor age so eat up my invention, -Nor fortune made such havoc of my means, -Nor my bad life reft me so much of friends, -But they shall find, awaked in such a kind, -Both strength of limb and policy of mind, -Ability in means and choice of friends, -To quit me of them throughly. - - - -FRIAR FRANCIS -Pause awhile, -And let my counsel sway you in this case. -Your daughter here the princes left for dead: -Let her awhile be secretly kept in, -And publish it that she is dead indeed; -Maintain a mourning ostentation -And on your family's old monument -Hang mournful epitaphs and do all rites -That appertain unto a burial. - - - -LEONATO -What shall become of this? what will this do? - - - -FRIAR FRANCIS -Marry, this well carried shall on her behalf -Change slander to remorse; that is some good: -But not for that dream I on this strange course, -But on this travail look for greater birth. -She dying, as it must so be maintain'd, -Upon the instant that she was accused, -Shall be lamented, pitied and excused -Of every hearer: for it so falls out -That what we have we prize not to the worth -Whiles we enjoy it, but being lack'd and lost, -Why, then we rack the value, then we find -The virtue that possession would not show us -Whiles it was ours. So will it fare with Claudio: -When he shall hear she died upon his words, -The idea of her life shall sweetly creep -Into his study of imagination, -And every lovely organ of her life -Shall come apparell'd in more precious habit, -More moving-delicate and full of life, -Into the eye and prospect of his soul, -Than when she lived indeed; then shall he mourn, -If ever love had interest in his liver, -And wish he had not so accused her, -No, though he thought his accusation true. -Let this be so, and doubt not but success -Will fashion the event in better shape -Than I can lay it down in likelihood. -But if all aim but this be levell'd false, -The supposition of the lady's death -Will quench the wonder of her infamy: -And if it sort not well, you may conceal her, -As best befits her wounded reputation, -In some reclusive and religious life, -Out of all eyes, tongues, minds and injuries. - - - -BENEDICK -Signior Leonato, let the friar advise you: -And though you know my inwardness and love -Is very much unto the prince and Claudio, -Yet, by mine honour, I will deal in this -As secretly and justly as your soul -Should with your body. - - - -LEONATO -Being that I flow in grief, -The smallest twine may lead me. - - - -FRIAR FRANCIS -'Tis well consented: presently away; -For to strange sores strangely they strain the cure. -Come, lady, die to live: this wedding-day -Perhaps is but prolong'd: have patience and endure. - - - -Exeunt all but BENEDICK and BEATRICE - - -BENEDICK -Lady Beatrice, have you wept all this while? - - - -BEATRICE -Yea, and I will weep a while longer. - - - -BENEDICK -I will not desire that. - - - -BEATRICE -You have no reason; I do it freely. - - - -BENEDICK -Surely I do believe your fair cousin is wronged. - - - -BEATRICE -Ah, how much might the man deserve of me that would right her! - - - -BENEDICK -Is there any way to show such friendship? - - - -BEATRICE -A very even way, but no such friend. - - - -BENEDICK -May a man do it? - - - -BEATRICE -It is a man's office, but not yours. - - - -BENEDICK -I do love nothing in the world so well as you: is -not that strange? - - - -BEATRICE -As strange as the thing I know not. It were as -possible for me to say I loved nothing so well as -you: but believe me not; and yet I lie not; I -confess nothing, nor I deny nothing. I am sorry for my cousin. - - - -BENEDICK -By my sword, Beatrice, thou lovest me. - - - -BEATRICE -Do not swear, and eat it. - - - -BENEDICK -I will swear by it that you love me; and I will make -him eat it that says I love not you. - - - -BEATRICE -Will you not eat your word? - - - -BENEDICK -With no sauce that can be devised to it. I protest -I love thee. - - - -BEATRICE -Why, then, God forgive me! - - - -BENEDICK -What offence, sweet Beatrice? - - - -BEATRICE -You have stayed me in a happy hour: I was about to -protest I loved you. - - - -BENEDICK -And do it with all thy heart. - - - -BEATRICE -I love you with so much of my heart that none is -left to protest. - - - -BENEDICK -Come, bid me do any thing for thee. - - - -BEATRICE -Kill Claudio. - - - -BENEDICK -Ha! not for the wide world. - - - -BEATRICE -You kill me to deny it. Farewell. - - - -BENEDICK -Tarry, sweet Beatrice. - - - -BEATRICE -I am gone, though I am here: there is no love in -you: nay, I pray you, let me go. - - - -BENEDICK -Beatrice,-- - - - -BEATRICE -In faith, I will go. - - - -BENEDICK -We'll be friends first. - - - -BEATRICE -You dare easier be friends with me than fight with mine enemy. - - - -BENEDICK -Is Claudio thine enemy? - - - -BEATRICE -Is he not approved in the height a villain, that -hath slandered, scorned, dishonoured my kinswoman? O -that I were a man! What, bear her in hand until they -come to take hands; and then, with public -accusation, uncovered slander, unmitigated rancour, ---O God, that I were a man! I would eat his heart -in the market-place. - - - -BENEDICK -Hear me, Beatrice,-- - - - -BEATRICE -Talk with a man out at a window! A proper saying! - - - -BENEDICK -Nay, but, Beatrice,-- - - - -BEATRICE -Sweet Hero! She is wronged, she is slandered, she is undone. - - - -BENEDICK -Beat-- - - - -BEATRICE -Princes and counties! Surely, a princely testimony, -a goodly count, Count Comfect; a sweet gallant, -surely! O that I were a man for his sake! or that I -had any friend would be a man for my sake! But -manhood is melted into courtesies, valour into -compliment, and men are only turned into tongue, and -trim ones too: he is now as valiant as Hercules -that only tells a lie and swears it. I cannot be a -man with wishing, therefore I will die a woman with grieving. - - - -BENEDICK -Tarry, good Beatrice. By this hand, I love thee. - - - -BEATRICE -Use it for my love some other way than swearing by it. - - - -BENEDICK -Think you in your soul the Count Claudio hath wronged Hero? - - - -BEATRICE -Yea, as sure as I have a thought or a soul. - - - -BENEDICK -Enough, I am engaged; I will challenge him. I will -kiss your hand, and so I leave you. By this hand, -Claudio shall render me a dear account. As you -hear of me, so think of me. Go, comfort your -cousin: I must say she is dead: and so, farewell. - - - -Exeunt - - -SCENE II. A prison. -Enter DOGBERRY, VERGES, and Sexton, in gowns; and -the Watch, with CONRADE and BORACHIO - - -DOGBERRY -Is our whole dissembly appeared? - - - -VERGES -O, a stool and a cushion for the sexton. - - - -Sexton -Which be the malefactors? - - - -DOGBERRY -Marry, that am I and my partner. - - - -VERGES -Nay, that's certain; we have the exhibition to examine. - - - -Sexton -But which are the offenders that are to be -examined? let them come before master constable. - - - -DOGBERRY -Yea, marry, let them come before me. What is your -name, friend? - - - -BORACHIO -Borachio. - - - -DOGBERRY -Pray, write down, Borachio. Yours, sirrah? - - - -CONRADE -I am a gentleman, sir, and my name is Conrade. - - - -DOGBERRY -Write down, master gentleman Conrade. Masters, do -you serve God? - - - -CONRADE -BORACHIO -Yea, sir, we hope. - - - -DOGBERRY -Write down, that they hope they serve God: and -write God first; for God defend but God should go -before such villains! Masters, it is proved already -that you are little better than false knaves; and it -will go near to be thought so shortly. How answer -you for yourselves? - - - -CONRADE -Marry, sir, we say we are none. - - - -DOGBERRY -A marvellous witty fellow, I assure you: but I -will go about with him. Come you hither, sirrah; a -word in your ear: sir, I say to you, it is thought -you are false knaves. - - - -BORACHIO -Sir, I say to you we are none. - - - -DOGBERRY -Well, stand aside. 'Fore God, they are both in a -tale. Have you writ down, that they are none? - - - -Sexton -Master constable, you go not the way to examine: -you must call forth the watch that are their accusers. - - - -DOGBERRY -Yea, marry, that's the eftest way. Let the watch -come forth. Masters, I charge you, in the prince's -name, accuse these men. - - - -First Watchman -This man said, sir, that Don John, the prince's -brother, was a villain. - - - -DOGBERRY -Write down Prince John a villain. Why, this is flat -perjury, to call a prince's brother villain. - - - -BORACHIO -Master constable,-- - - - -DOGBERRY -Pray thee, fellow, peace: I do not like thy look, -I promise thee. - - - -Sexton -What heard you him say else? - - - -Second Watchman -Marry, that he had received a thousand ducats of -Don John for accusing the Lady Hero wrongfully. - - - -DOGBERRY -Flat burglary as ever was committed. - - - -VERGES -Yea, by mass, that it is. - - - -Sexton -What else, fellow? - - - -First Watchman -And that Count Claudio did mean, upon his words, to -disgrace Hero before the whole assembly. and not marry her. - - - -DOGBERRY -O villain! thou wilt be condemned into everlasting -redemption for this. - - - -Sexton -What else? - - - -Watchman -This is all. - - - -Sexton -And this is more, masters, than you can deny. -Prince John is this morning secretly stolen away; -Hero was in this manner accused, in this very manner -refused, and upon the grief of this suddenly died. -Master constable, let these men be bound, and -brought to Leonato's: I will go before and show -him their examination. - - - -Exit - - -DOGBERRY -Come, let them be opinioned. - - - -VERGES -Let them be in the hands-- - - - -CONRADE -Off, coxcomb! - - - -DOGBERRY -God's my life, where's the sexton? let him write -down the prince's officer coxcomb. Come, bind them. -Thou naughty varlet! - - - -CONRADE -Away! you are an ass, you are an ass. - - - -DOGBERRY -Dost thou not suspect my place? dost thou not -suspect my years? O that he were here to write me -down an ass! But, masters, remember that I am an -ass; though it be not written down, yet forget not -that I am an ass. No, thou villain, thou art full of -piety, as shall be proved upon thee by good witness. -I am a wise fellow, and, which is more, an officer, -and, which is more, a householder, and, which is -more, as pretty a piece of flesh as any is in -Messina, and one that knows the law, go to; and a -rich fellow enough, go to; and a fellow that hath -had losses, and one that hath two gowns and every -thing handsome about him. Bring him away. O that -I had been writ down an ass! - - - -Exeunt - - - - -ACT V - -SCENE I. Before LEONATO'S house. -Enter LEONATO and ANTONIO - - -ANTONIO -If you go on thus, you will kill yourself: -And 'tis not wisdom thus to second grief -Against yourself. - - - -LEONATO -I pray thee, cease thy counsel, -Which falls into mine ears as profitless -As water in a sieve: give not me counsel; -Nor let no comforter delight mine ear -But such a one whose wrongs do suit with mine. -Bring me a father that so loved his child, -Whose joy of her is overwhelm'd like mine, -And bid him speak of patience; -Measure his woe the length and breadth of mine -And let it answer every strain for strain, -As thus for thus and such a grief for such, -In every lineament, branch, shape, and form: -If such a one will smile and stroke his beard, -Bid sorrow wag, cry 'hem!' when he should groan, -Patch grief with proverbs, make misfortune drunk -With candle-wasters; bring him yet to me, -And I of him will gather patience. -But there is no such man: for, brother, men -Can counsel and speak comfort to that grief -Which they themselves not feel; but, tasting it, -Their counsel turns to passion, which before -Would give preceptial medicine to rage, -Fetter strong madness in a silken thread, -Charm ache with air and agony with words: -No, no; 'tis all men's office to speak patience -To those that wring under the load of sorrow, -But no man's virtue nor sufficiency -To be so moral when he shall endure -The like himself. Therefore give me no counsel: -My griefs cry louder than advertisement. - - - -ANTONIO -Therein do men from children nothing differ. - - - -LEONATO -I pray thee, peace. I will be flesh and blood; -For there was never yet philosopher -That could endure the toothache patiently, -However they have writ the style of gods -And made a push at chance and sufferance. - - - -ANTONIO -Yet bend not all the harm upon yourself; -Make those that do offend you suffer too. - - - -LEONATO -There thou speak'st reason: nay, I will do so. -My soul doth tell me Hero is belied; -And that shall Claudio know; so shall the prince -And all of them that thus dishonour her. - - - -ANTONIO -Here comes the prince and Claudio hastily. - - - -Enter DON PEDRO and CLAUDIO - - -DON PEDRO -Good den, good den. - - - -CLAUDIO -Good day to both of you. - - - -LEONATO -Hear you. my lords,-- - - - -DON PEDRO -We have some haste, Leonato. - - - -LEONATO -Some haste, my lord! well, fare you well, my lord: -Are you so hasty now? well, all is one. - - - -DON PEDRO -Nay, do not quarrel with us, good old man. - - - -ANTONIO -If he could right himself with quarreling, -Some of us would lie low. - - - -CLAUDIO -Who wrongs him? - - - -LEONATO -Marry, thou dost wrong me; thou dissembler, thou:-- -Nay, never lay thy hand upon thy sword; -I fear thee not. - - - -CLAUDIO -Marry, beshrew my hand, -If it should give your age such cause of fear: -In faith, my hand meant nothing to my sword. - - - -LEONATO -Tush, tush, man; never fleer and jest at me: -I speak not like a dotard nor a fool, -As under privilege of age to brag -What I have done being young, or what would do -Were I not old. Know, Claudio, to thy head, -Thou hast so wrong'd mine innocent child and me -That I am forced to lay my reverence by -And, with grey hairs and bruise of many days, -Do challenge thee to trial of a man. -I say thou hast belied mine innocent child; -Thy slander hath gone through and through her heart, -And she lies buried with her ancestors; -O, in a tomb where never scandal slept, -Save this of hers, framed by thy villany! - - - -CLAUDIO -My villany? - - - -LEONATO -Thine, Claudio; thine, I say. - - - -DON PEDRO -You say not right, old man. - - - -LEONATO -My lord, my lord, -I'll prove it on his body, if he dare, -Despite his nice fence and his active practise, -His May of youth and bloom of lustihood. - - - -CLAUDIO -Away! I will not have to do with you. - - - -LEONATO -Canst thou so daff me? Thou hast kill'd my child: -If thou kill'st me, boy, thou shalt kill a man. - - - -ANTONIO -He shall kill two of us, and men indeed: -But that's no matter; let him kill one first; -Win me and wear me; let him answer me. -Come, follow me, boy; come, sir boy, come, follow me: -Sir boy, I'll whip you from your foining fence; -Nay, as I am a gentleman, I will. - - - -LEONATO -Brother,-- - - - -ANTONIO -Content yourself. God knows I loved my niece; -And she is dead, slander'd to death by villains, -That dare as well answer a man indeed -As I dare take a serpent by the tongue: -Boys, apes, braggarts, Jacks, milksops! - - - -LEONATO -Brother Antony,-- - - - -ANTONIO -Hold you content. What, man! I know them, yea, -And what they weigh, even to the utmost scruple,-- -Scrambling, out-facing, fashion-monging boys, -That lie and cog and flout, deprave and slander, -Go anticly, show outward hideousness, -And speak off half a dozen dangerous words, -How they might hurt their enemies, if they durst; -And this is all. - - - -LEONATO -But, brother Antony,-- - - - -ANTONIO -Come, 'tis no matter: -Do not you meddle; let me deal in this. - - - -DON PEDRO -Gentlemen both, we will not wake your patience. -My heart is sorry for your daughter's death: -But, on my honour, she was charged with nothing -But what was true and very full of proof. - - - -LEONATO -My lord, my lord,-- - - - -DON PEDRO -I will not hear you. - - - -LEONATO -No? Come, brother; away! I will be heard. - - - -ANTONIO -And shall, or some of us will smart for it. - - - -Exeunt LEONATO and ANTONIO - - -DON PEDRO -See, see; here comes the man we went to seek. - - - -Enter BENEDICK - - -CLAUDIO -Now, signior, what news? - - - -BENEDICK -Good day, my lord. - - - -DON PEDRO -Welcome, signior: you are almost come to part -almost a fray. - - - -CLAUDIO -We had like to have had our two noses snapped off -with two old men without teeth. - - - -DON PEDRO -Leonato and his brother. What thinkest thou? Had -we fought, I doubt we should have been too young for them. - - - -BENEDICK -In a false quarrel there is no true valour. I came -to seek you both. - - - -CLAUDIO -We have been up and down to seek thee; for we are -high-proof melancholy and would fain have it beaten -away. Wilt thou use thy wit? - - - -BENEDICK -It is in my scabbard: shall I draw it? - - - -DON PEDRO -Dost thou wear thy wit by thy side? - - - -CLAUDIO -Never any did so, though very many have been beside -their wit. I will bid thee draw, as we do the -minstrels; draw, to pleasure us. - - - -DON PEDRO -As I am an honest man, he looks pale. Art thou -sick, or angry? - - - -CLAUDIO -What, courage, man! What though care killed a cat, -thou hast mettle enough in thee to kill care. - - - -BENEDICK -Sir, I shall meet your wit in the career, and you -charge it against me. I pray you choose another subject. - - - -CLAUDIO -Nay, then, give him another staff: this last was -broke cross. - - - -DON PEDRO -By this light, he changes more and more: I think -he be angry indeed. - - - -CLAUDIO -If he be, he knows how to turn his girdle. - - - -BENEDICK -Shall I speak a word in your ear? - - - -CLAUDIO -God bless me from a challenge! - - - -BENEDICK -Aside to CLAUDIO You are a villain; I jest not: -I will make it good how you dare, with what you -dare, and when you dare. Do me right, or I will -protest your cowardice. You have killed a sweet -lady, and her death shall fall heavy on you. Let me -hear from you. - - - -CLAUDIO -Well, I will meet you, so I may have good cheer. - - - -DON PEDRO -What, a feast, a feast? - - - -CLAUDIO -I' faith, I thank him; he hath bid me to a calf's -head and a capon; the which if I do not carve most -curiously, say my knife's naught. Shall I not find -a woodcock too? - - - -BENEDICK -Sir, your wit ambles well; it goes easily. - - - -DON PEDRO -I'll tell thee how Beatrice praised thy wit the -other day. I said, thou hadst a fine wit: 'True,' -said she, 'a fine little one.' 'No,' said I, 'a -great wit:' 'Right,' says she, 'a great gross one.' -'Nay,' said I, 'a good wit:' 'Just,' said she, 'it -hurts nobody.' 'Nay,' said I, 'the gentleman -is wise:' 'Certain,' said she, 'a wise gentleman.' -'Nay,' said I, 'he hath the tongues:' 'That I -believe,' said she, 'for he swore a thing to me on -Monday night, which he forswore on Tuesday morning; -there's a double tongue; there's two tongues.' Thus -did she, an hour together, transshape thy particular -virtues: yet at last she concluded with a sigh, thou -wast the properest man in Italy. - - - -CLAUDIO -For the which she wept heartily and said she cared -not. - - - -DON PEDRO -Yea, that she did: but yet, for all that, an if she -did not hate him deadly, she would love him dearly: -the old man's daughter told us all. - - - -CLAUDIO -All, all; and, moreover, God saw him when he was -hid in the garden. - - - -DON PEDRO -But when shall we set the savage bull's horns on -the sensible Benedick's head? - - - -CLAUDIO -Yea, and text underneath, 'Here dwells Benedick the -married man'? - - - -BENEDICK -Fare you well, boy: you know my mind. I will leave -you now to your gossip-like humour: you break jests -as braggarts do their blades, which God be thanked, -hurt not. My lord, for your many courtesies I thank -you: I must discontinue your company: your brother -the bastard is fled from Messina: you have among -you killed a sweet and innocent lady. For my Lord -Lackbeard there, he and I shall meet: and, till -then, peace be with him. - - - -Exit - - -DON PEDRO -He is in earnest. - - - -CLAUDIO -In most profound earnest; and, I'll warrant you, for -the love of Beatrice. - - - -DON PEDRO -And hath challenged thee. - - - -CLAUDIO -Most sincerely. - - - -DON PEDRO -What a pretty thing man is when he goes in his -doublet and hose and leaves off his wit! - - - -CLAUDIO -He is then a giant to an ape; but then is an ape a -doctor to such a man. - - - -DON PEDRO -But, soft you, let me be: pluck up, my heart, and -be sad. Did he not say, my brother was fled? - - - -Enter DOGBERRY, VERGES, and the Watch, with CONRADE -and BORACHIO - - -DOGBERRY -Come you, sir: if justice cannot tame you, she -shall ne'er weigh more reasons in her balance: nay, -an you be a cursing hypocrite once, you must be looked to. - - - -DON PEDRO -How now? two of my brother's men bound! Borachio -one! - - - -CLAUDIO -Hearken after their offence, my lord. - - - -DON PEDRO -Officers, what offence have these men done? - - - -DOGBERRY -Marry, sir, they have committed false report; -moreover, they have spoken untruths; secondarily, -they are slanders; sixth and lastly, they have -belied a lady; thirdly, they have verified unjust -things; and, to conclude, they are lying knaves. - - - -DON PEDRO -First, I ask thee what they have done; thirdly, I -ask thee what's their offence; sixth and lastly, why -they are committed; and, to conclude, what you lay -to their charge. - - - -CLAUDIO -Rightly reasoned, and in his own division: and, by -my troth, there's one meaning well suited. - - - -DON PEDRO -Who have you offended, masters, that you are thus -bound to your answer? this learned constable is -too cunning to be understood: what's your offence? - - - -BORACHIO -Sweet prince, let me go no farther to mine answer: -do you hear me, and let this count kill me. I have -deceived even your very eyes: what your wisdoms -could not discover, these shallow fools have brought -to light: who in the night overheard me confessing -to this man how Don John your brother incensed me -to slander the Lady Hero, how you were brought into -the orchard and saw me court Margaret in Hero's -garments, how you disgraced her, when you should -marry her: my villany they have upon record; which -I had rather seal with my death than repeat over -to my shame. The lady is dead upon mine and my -master's false accusation; and, briefly, I desire -nothing but the reward of a villain. - - - -DON PEDRO -Runs not this speech like iron through your blood? - - - -CLAUDIO -I have drunk poison whiles he utter'd it. - - - -DON PEDRO -But did my brother set thee on to this? - - - -BORACHIO -Yea, and paid me richly for the practise of it. - - - -DON PEDRO -He is composed and framed of treachery: -And fled he is upon this villany. - - - -CLAUDIO -Sweet Hero! now thy image doth appear -In the rare semblance that I loved it first. - - - -DOGBERRY -Come, bring away the plaintiffs: by this time our -sexton hath reformed Signior Leonato of the matter: -and, masters, do not forget to specify, when time -and place shall serve, that I am an ass. - - - -VERGES -Here, here comes master Signior Leonato, and the -Sexton too. - - - -Re-enter LEONATO and ANTONIO, with the Sexton - - -LEONATO -Which is the villain? let me see his eyes, -That, when I note another man like him, -I may avoid him: which of these is he? - - - -BORACHIO -If you would know your wronger, look on me. - - - -LEONATO -Art thou the slave that with thy breath hast kill'd -Mine innocent child? - - - -BORACHIO -Yea, even I alone. - - - -LEONATO -No, not so, villain; thou beliest thyself: -Here stand a pair of honourable men; -A third is fled, that had a hand in it. -I thank you, princes, for my daughter's death: -Record it with your high and worthy deeds: -'Twas bravely done, if you bethink you of it. - - - -CLAUDIO -I know not how to pray your patience; -Yet I must speak. Choose your revenge yourself; -Impose me to what penance your invention -Can lay upon my sin: yet sinn'd I not -But in mistaking. - - - -DON PEDRO -By my soul, nor I: -And yet, to satisfy this good old man, -I would bend under any heavy weight -That he'll enjoin me to. - - - -LEONATO -I cannot bid you bid my daughter live; -That were impossible: but, I pray you both, -Possess the people in Messina here -How innocent she died; and if your love -Can labour ought in sad invention, -Hang her an epitaph upon her tomb -And sing it to her bones, sing it to-night: -To-morrow morning come you to my house, -And since you could not be my son-in-law, -Be yet my nephew: my brother hath a daughter, -Almost the copy of my child that's dead, -And she alone is heir to both of us: -Give her the right you should have given her cousin, -And so dies my revenge. - - - -CLAUDIO -O noble sir, -Your over-kindness doth wring tears from me! -I do embrace your offer; and dispose -For henceforth of poor Claudio. - - - -LEONATO -To-morrow then I will expect your coming; -To-night I take my leave. This naughty man -Shall face to face be brought to Margaret, -Who I believe was pack'd in all this wrong, -Hired to it by your brother. - - - -BORACHIO -No, by my soul, she was not, -Nor knew not what she did when she spoke to me, -But always hath been just and virtuous -In any thing that I do know by her. - - - -DOGBERRY -Moreover, sir, which indeed is not under white and -black, this plaintiff here, the offender, did call -me ass: I beseech you, let it be remembered in his -punishment. And also, the watch heard them talk of -one Deformed: they say be wears a key in his ear and -a lock hanging by it, and borrows money in God's -name, the which he hath used so long and never paid -that now men grow hard-hearted and will lend nothing -for God's sake: pray you, examine him upon that point. - - - -LEONATO -I thank thee for thy care and honest pains. - - - -DOGBERRY -Your worship speaks like a most thankful and -reverend youth; and I praise God for you. - - - -LEONATO -There's for thy pains. - - - -DOGBERRY -God save the foundation! - - - -LEONATO -Go, I discharge thee of thy prisoner, and I thank thee. - - - -DOGBERRY -I leave an arrant knave with your worship; which I -beseech your worship to correct yourself, for the -example of others. God keep your worship! I wish -your worship well; God restore you to health! I -humbly give you leave to depart; and if a merry -meeting may be wished, God prohibit it! Come, neighbour. - - - -Exeunt DOGBERRY and VERGES - - -LEONATO -Until to-morrow morning, lords, farewell. - - - -ANTONIO -Farewell, my lords: we look for you to-morrow. - - - -DON PEDRO -We will not fail. - - - -CLAUDIO -To-night I'll mourn with Hero. - - - -LEONATO -To the Watch Bring you these fellows on. We'll -talk with Margaret, -How her acquaintance grew with this lewd fellow. - - - -Exeunt, severally - - -SCENE II. LEONATO'S garden. -Enter BENEDICK and MARGARET, meeting - - -BENEDICK -Pray thee, sweet Mistress Margaret, deserve well at -my hands by helping me to the speech of Beatrice. - - - -MARGARET -Will you then write me a sonnet in praise of my beauty? - - - -BENEDICK -In so high a style, Margaret, that no man living -shall come over it; for, in most comely truth, thou -deservest it. - - - -MARGARET -To have no man come over me! why, shall I always -keep below stairs? - - - -BENEDICK -Thy wit is as quick as the greyhound's mouth; it catches. - - - -MARGARET -And yours as blunt as the fencer's foils, which hit, -but hurt not. - - - -BENEDICK -A most manly wit, Margaret; it will not hurt a -woman: and so, I pray thee, call Beatrice: I give -thee the bucklers. - - - -MARGARET -Give us the swords; we have bucklers of our own. - - - -BENEDICK -If you use them, Margaret, you must put in the -pikes with a vice; and they are dangerous weapons for maids. - - - -MARGARET -Well, I will call Beatrice to you, who I think hath legs. - - - -BENEDICK -And therefore will come. -Exit MARGARET -Sings -The god of love, -That sits above, -And knows me, and knows me, -How pitiful I deserve,-- -I mean in singing; but in loving, Leander the good -swimmer, Troilus the first employer of panders, and -a whole bookful of these quondam carpet-mangers, -whose names yet run smoothly in the even road of a -blank verse, why, they were never so truly turned -over and over as my poor self in love. Marry, I -cannot show it in rhyme; I have tried: I can find -out no rhyme to 'lady' but 'baby,' an innocent -rhyme; for 'scorn,' 'horn,' a hard rhyme; for, -'school,' 'fool,' a babbling rhyme; very ominous -endings: no, I was not born under a rhyming planet, -nor I cannot woo in festival terms. -Enter BEATRICE -Sweet Beatrice, wouldst thou come when I called thee? - - - -BEATRICE -Yea, signior, and depart when you bid me. - - - -BENEDICK -O, stay but till then! - - - -BEATRICE -'Then' is spoken; fare you well now: and yet, ere -I go, let me go with that I came; which is, with -knowing what hath passed between you and Claudio. - - - -BENEDICK -Only foul words; and thereupon I will kiss thee. - - - -BEATRICE -Foul words is but foul wind, and foul wind is but -foul breath, and foul breath is noisome; therefore I -will depart unkissed. - - - -BENEDICK -Thou hast frighted the word out of his right sense, -so forcible is thy wit. But I must tell thee -plainly, Claudio undergoes my challenge; and either -I must shortly hear from him, or I will subscribe -him a coward. And, I pray thee now, tell me for -which of my bad parts didst thou first fall in love with me? - - - -BEATRICE -For them all together; which maintained so politic -a state of evil that they will not admit any good -part to intermingle with them. But for which of my -good parts did you first suffer love for me? - - - -BENEDICK -Suffer love! a good epithet! I do suffer love -indeed, for I love thee against my will. - - - -BEATRICE -In spite of your heart, I think; alas, poor heart! -If you spite it for my sake, I will spite it for -yours; for I will never love that which my friend hates. - - - -BENEDICK -Thou and I are too wise to woo peaceably. - - - -BEATRICE -It appears not in this confession: there's not one -wise man among twenty that will praise himself. - - - -BENEDICK -An old, an old instance, Beatrice, that lived in -the lime of good neighbours. If a man do not erect -in this age his own tomb ere he dies, he shall live -no longer in monument than the bell rings and the -widow weeps. - - - -BEATRICE -And how long is that, think you? - - - -BENEDICK -Question: why, an hour in clamour and a quarter in -rheum: therefore is it most expedient for the -wise, if Don Worm, his conscience, find no -impediment to the contrary, to be the trumpet of his -own virtues, as I am to myself. So much for -praising myself, who, I myself will bear witness, is -praiseworthy: and now tell me, how doth your cousin? - - - -BEATRICE -Very ill. - - - -BENEDICK -And how do you? - - - -BEATRICE -Very ill too. - - - -BENEDICK -Serve God, love me and mend. There will I leave -you too, for here comes one in haste. - - - -Enter URSULA - - -URSULA -Madam, you must come to your uncle. Yonder's old -coil at home: it is proved my Lady Hero hath been -falsely accused, the prince and Claudio mightily -abused; and Don John is the author of all, who is -fed and gone. Will you come presently? - - - -BEATRICE -Will you go hear this news, signior? - - - -BENEDICK -I will live in thy heart, die in thy lap, and be -buried in thy eyes; and moreover I will go with -thee to thy uncle's. - - - -Exeunt - - -SCENE III. A church. -Enter DON PEDRO, CLAUDIO, and three or four -with tapers - - -CLAUDIO -Is this the monument of Leonato? - - - -Lord -It is, my lord. - - - -CLAUDIO -Reading out of a scroll -Done to death by slanderous tongues -Was the Hero that here lies: -Death, in guerdon of her wrongs, -Gives her fame which never dies. -So the life that died with shame -Lives in death with glorious fame. -Hang thou there upon the tomb, -Praising her when I am dumb. -Now, music, sound, and sing your solemn hymn. -SONG. -Pardon, goddess of the night, -Those that slew thy virgin knight; -For the which, with songs of woe, -Round about her tomb they go. -Midnight, assist our moan; -Help us to sigh and groan, -Heavily, heavily: -Graves, yawn and yield your dead, -Till death be uttered, -Heavily, heavily. - - - -CLAUDIO -Now, unto thy bones good night! -Yearly will I do this rite. - - - -DON PEDRO -Good morrow, masters; put your torches out: -The wolves have prey'd; and look, the gentle day, -Before the wheels of Phoebus, round about -Dapples the drowsy east with spots of grey. -Thanks to you all, and leave us: fare you well. - - - -CLAUDIO -Good morrow, masters: each his several way. - - - -DON PEDRO -Come, let us hence, and put on other weeds; -And then to Leonato's we will go. - - - -CLAUDIO -And Hymen now with luckier issue speed's -Than this for whom we render'd up this woe. - - - -Exeunt - - -SCENE IV. A room in LEONATO'S house. -Enter LEONATO, ANTONIO, BENEDICK, BEATRICE, -MARGARET, URSULA, FRIAR FRANCIS, and HERO - - -FRIAR FRANCIS -Did I not tell you she was innocent? - - - -LEONATO -So are the prince and Claudio, who accused her -Upon the error that you heard debated: -But Margaret was in some fault for this, -Although against her will, as it appears -In the true course of all the question. - - - -ANTONIO -Well, I am glad that all things sort so well. - - - -BENEDICK -And so am I, being else by faith enforced -To call young Claudio to a reckoning for it. - - - -LEONATO -Well, daughter, and you gentle-women all, -Withdraw into a chamber by yourselves, -And when I send for you, come hither mask'd. -Exeunt Ladies -The prince and Claudio promised by this hour -To visit me. You know your office, brother: -You must be father to your brother's daughter -And give her to young Claudio. - - - -ANTONIO -Which I will do with confirm'd countenance. - - - -BENEDICK -Friar, I must entreat your pains, I think. - - - -FRIAR FRANCIS -To do what, signior? - - - -BENEDICK -To bind me, or undo me; one of them. -Signior Leonato, truth it is, good signior, -Your niece regards me with an eye of favour. - - - -LEONATO -That eye my daughter lent her: 'tis most true. - - - -BENEDICK -And I do with an eye of love requite her. - - - -LEONATO -The sight whereof I think you had from me, -From Claudio and the prince: but what's your will? - - - -BENEDICK -Your answer, sir, is enigmatical: -But, for my will, my will is your good will -May stand with ours, this day to be conjoin'd -In the state of honourable marriage: -In which, good friar, I shall desire your help. - - - -LEONATO -My heart is with your liking. - - - -FRIAR FRANCIS -And my help. -Here comes the prince and Claudio. - - - -Enter DON PEDRO and CLAUDIO, and two or -three others - - -DON PEDRO -Good morrow to this fair assembly. - - - -LEONATO -Good morrow, prince; good morrow, Claudio: -We here attend you. Are you yet determined -To-day to marry with my brother's daughter? - - - -CLAUDIO -I'll hold my mind, were she an Ethiope. - - - -LEONATO -Call her forth, brother; here's the friar ready. - - - -Exit ANTONIO - - -DON PEDRO -Good morrow, Benedick. Why, what's the matter, -That you have such a February face, -So full of frost, of storm and cloudiness? - - - -CLAUDIO -I think he thinks upon the savage bull. -Tush, fear not, man; we'll tip thy horns with gold -And all Europa shall rejoice at thee, -As once Europa did at lusty Jove, -When he would play the noble beast in love. - - - -BENEDICK -Bull Jove, sir, had an amiable low; -And some such strange bull leap'd your father's cow, -And got a calf in that same noble feat -Much like to you, for you have just his bleat. - - - -CLAUDIO -For this I owe you: here comes other reckonings. -Re-enter ANTONIO, with the Ladies masked -Which is the lady I must seize upon? - - - -ANTONIO -This same is she, and I do give you her. - - - -CLAUDIO -Why, then she's mine. Sweet, let me see your face. - - - -LEONATO -No, that you shall not, till you take her hand -Before this friar and swear to marry her. - - - -CLAUDIO -Give me your hand: before this holy friar, -I am your husband, if you like of me. - - - -HERO -And when I lived, I was your other wife: -Unmasking -And when you loved, you were my other husband. - - - -CLAUDIO -Another Hero! - - - -HERO -Nothing certainer: -One Hero died defiled, but I do live, -And surely as I live, I am a maid. - - - -DON PEDRO -The former Hero! Hero that is dead! - - - -LEONATO -She died, my lord, but whiles her slander lived. - - - -FRIAR FRANCIS -All this amazement can I qualify: -When after that the holy rites are ended, -I'll tell you largely of fair Hero's death: -Meantime let wonder seem familiar, -And to the chapel let us presently. - - - -BENEDICK -Soft and fair, friar. Which is Beatrice? - - - -BEATRICE -Unmasking I answer to that name. What is your will? - - - -BENEDICK -Do not you love me? - - - -BEATRICE -Why, no; no more than reason. - - - -BENEDICK -Why, then your uncle and the prince and Claudio -Have been deceived; they swore you did. - - - -BEATRICE -Do not you love me? - - - -BENEDICK -Troth, no; no more than reason. - - - -BEATRICE -Why, then my cousin Margaret and Ursula -Are much deceived; for they did swear you did. - - - -BENEDICK -They swore that you were almost sick for me. - - - -BEATRICE -They swore that you were well-nigh dead for me. - - - -BENEDICK -'Tis no such matter. Then you do not love me? - - - -BEATRICE -No, truly, but in friendly recompense. - - - -LEONATO -Come, cousin, I am sure you love the gentleman. - - - -CLAUDIO -And I'll be sworn upon't that he loves her; -For here's a paper written in his hand, -A halting sonnet of his own pure brain, -Fashion'd to Beatrice. - - - -HERO -And here's another -Writ in my cousin's hand, stolen from her pocket, -Containing her affection unto Benedick. - - - -BENEDICK -A miracle! here's our own hands against our hearts. -Come, I will have thee; but, by this light, I take -thee for pity. - - - -BEATRICE -I would not deny you; but, by this good day, I yield -upon great persuasion; and partly to save your life, -for I was told you were in a consumption. - - - -BENEDICK -Peace! I will stop your mouth. - - - -Kissing her - - -DON PEDRO -How dost thou, Benedick, the married man? - - - -BENEDICK -I'll tell thee what, prince; a college of -wit-crackers cannot flout me out of my humour. Dost -thou think I care for a satire or an epigram? No: -if a man will be beaten with brains, a' shall wear -nothing handsome about him. In brief, since I do -purpose to marry, I will think nothing to any -purpose that the world can say against it; and -therefore never flout at me for what I have said -against it; for man is a giddy thing, and this is my -conclusion. For thy part, Claudio, I did think to -have beaten thee, but in that thou art like to be my -kinsman, live unbruised and love my cousin. - - - -CLAUDIO -I had well hoped thou wouldst have denied Beatrice, -that I might have cudgelled thee out of thy single -life, to make thee a double-dealer; which, out of -question, thou wilt be, if my cousin do not look -exceedingly narrowly to thee. - - - -BENEDICK -Come, come, we are friends: let's have a dance ere -we are married, that we may lighten our own hearts -and our wives' heels. - - - -LEONATO -We'll have dancing afterward. - - - -BENEDICK -First, of my word; therefore play, music. Prince, -thou art sad; get thee a wife, get thee a wife: -there is no staff more reverend than one tipped with horn. - - - -Enter a Messenger - - -Messenger -My lord, your brother John is ta'en in flight, -And brought with armed men back to Messina. - - - -BENEDICK -Think not on him till to-morrow: -I'll devise thee brave punishments for him. -Strike up, pipers. - - -Dance -Exeunt - - -
      diff --git a/ruby/test/rexml/data/namespaces.xml b/ruby/test/rexml/data/namespaces.xml deleted file mode 100644 index e8e4df836..000000000 --- a/ruby/test/rexml/data/namespaces.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - Hello - - - - Hey - - - - Hey2 - - - - Hey3 - - diff --git a/ruby/test/rexml/data/nitf.xml b/ruby/test/rexml/data/nitf.xml deleted file mode 100644 index 269d99e21..000000000 --- a/ruby/test/rexml/data/nitf.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Use of Napster Quadruples - - By PETER SVENSSON - AP Business Writer - - The Associated Press - - NEW YORK - - - - -

      Despite the uncertain legality of the Napster online music-sharing service, the number of people -using it more than quadrupled in just five months, Media Metrix said Monday.

      -

      That made Napster the fastest-growing software application ever recorded by the Internet research -company.

      -

      From 1.1 million home users in the United States in February, the first month Media Metrix -tracked the application, Napster use rocketed to 4.9 million users in July.

      -

      That represents 6 percent of U.S. home PC users who have modems, said Media Metrix, which pays -people to install monitoring software on their computers.

      -

      It estimates total usage from a panel of about 50,000 people in the United States.

      -

      Napster was also used at work by 887,000 people in July, Media Metrix said.

      -

      Napster Inc. has been sued by the recording industry for allegedly enabling copyright -infringement. The federal government weighed in on the case Friday, saying the service is not protected -under a key copyright law, as the San Mateo, Calif., company claims.

      -

      Bruce Ryon, head of Media Metrix's New Media Group, said Napster was used by "the full spectrum of PC users, not just the youth with time on their hands and a passion for music."

      -

      The Napster program allows users to copy digital music files from the hard drives of other -users over the Internet.

      -

      Napster Inc. said last week that 28 million people had downloaded its program. It does not reveal -its own figures for how many people actually use the software.

      -

      Because the program connects to the company's computers over the Internet every time -it is run, Napster Inc. can track usage exactly.

      -

      __

      -

      On the Net:

      -

      -http://www.napster.com

      -

      -http://www.mediametrix.com

      -
      -
      - -
      diff --git a/ruby/test/rexml/data/numbers.xml b/ruby/test/rexml/data/numbers.xml deleted file mode 100644 index a1791cd63..000000000 --- a/ruby/test/rexml/data/numbers.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - 3 - 24 - 55 - 11 - 2 - -3 - - - - - - - - diff --git a/ruby/test/rexml/data/ofbiz-issues-full-177.xml b/ruby/test/rexml/data/ofbiz-issues-full-177.xml deleted file mode 100644 index bfff771d1..000000000 --- a/ruby/test/rexml/data/ofbiz-issues-full-177.xml +++ /dev/null @@ -1,13971 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]> - - - 1 - RESOLVED - P3 - FIXED - Documentation - CVS - All - issues@ofbiz - 20030820210924 - website - ajzeneski - not determined - DEFECT - 2003-08-13 22:35:10 - issues@ofbiz - - - - All - Website missing - - - ajzeneski - 2003-08-13 22:35:10 - Website is missing from CVS. - - - ajzeneski - 2003-08-19 12:09:17 - Website starting to move - - - ajzeneski - 2003-08-19 12:11:57 - Changed milestone - - - ajzeneski - 2003-08-20 21:09:24 - Website has been imported into CVS - - - ajzeneski - 2003-08-19 12:09:17 - issue_status - Status - NEW - STARTED - - - ajzeneski - 2003-08-19 12:09:17 - version - Version - unspecified - CVS - - - ajzeneski - 2003-08-19 12:11:57 - target_milestone - Target Milestone - milestone 1 - not determined - - - ajzeneski - 2003-08-20 21:09:24 - issue_status - Status - STARTED - RESOLVED - - - ajzeneski - 2003-08-20 21:09:24 - resolution - Resolution - - FIXED - - - - 2 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20030824004146 - Product - ajzeneski - not determined - DEFECT - 2003-08-23 14:25:20 - issues@ofbiz - - - - All - Missing FTL - - - ajzeneski - 2003-08-23 14:25:20 - Missing FTL file: - -Error: File not found: /feature/EditFeatureCategoryFeatures.ftl - - - jonesde - 2003-08-24 00:41:46 - Converted JSP to FTL, made some small corrections. - - - jonesde - 2003-08-24 00:41:46 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-08-24 00:41:46 - resolution - Resolution - - FIXED - - - - 3 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20030828103031 - Product - ajzeneski - not determined - DEFECT - 2003-08-23 14:27:14 - issues@ofbiz - - - - All - Edit Promo Bug - - - ajzeneski - 2003-08-23 14:27:14 - When editing a promo rule; the drop down for the current condition contains only -the existing condition (many times). - - - jonesde - 2003-08-28 10:30:31 - #list directive had a type. Fix in CVS. - - - jonesde - 2003-08-28 10:30:31 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-08-28 10:30:31 - resolution - Resolution - - FIXED - - - - 4 - VERIFIED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20030828103057 - Product - ajzeneski - not determined - DEFECT - 2003-08-23 14:30:52 - issues@ofbiz - - - - All - Price Rule Bug - - - ajzeneski - 2003-08-23 14:30:52 - When editing a price rule; changing the is "sale price" flag sets properly, -however always displays "no" as the selected choice. - - - jonesde - 2003-08-28 10:20:59 - Fixed conditional on the no button, now appears correctly. - - - jonesde - 2003-08-28 10:30:57 - Done - - - jonesde - 2003-08-28 10:20:59 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-08-28 10:20:59 - resolution - Resolution - - FIXED - - - jonesde - 2003-08-28 10:30:57 - issue_status - Status - RESOLVED - VERIFIED - - - - 5 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20030823144138 - Party - ajzeneski - not determined - DEFECT - 2003-08-23 14:41:38 - issues@ofbiz - - - - All - Relationship missing button - - - ajzeneski - 2003-08-23 14:41:38 - View/Edit party relationships page first is still JSP and second is missing the -links to communication event(s). - - - - 6 - CLOSED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20030918144334 - Entity - robdawson - not determined - DEFECT - 2003-09-04 02:09:57 - jonesde - - - - All - Entity Engine ConnectionFactory and DBCPConnectionFactory issues with Oracle - - - robdawson - 2003-09-04 02:09:57 - When using the Inline JDBC Functionality of the Entity Engine to access an Oracle -database the Entity Engine gives SQL no suitable driver exceptions. - -The fix for this involves changing: - loader.loadClass(driverClassName); -to - Class clazz = loader.loadClass(driverClassName); - clazz.newInstance(); -in both the ConnectionFactory and DBCPConnectionFactory classes. - -There will also need to be the appropriate exception handling. - -Please contact me if this requires any clarification. - - - ajzeneski - 2003-09-04 22:15:06 - The message you are getting means that the JDBC drivers for Oracle cannot be -found on the classpath. Contact the users mailing list if you need further help -with this issue. - - - ajzeneski - 2003-09-04 22:17:28 - Sorry; DBCP support is currently outdated and not used due to the fact that -there is no transaction support. It is recommended you use the JOTM/XAPool -connections. This issue will be addressed during a refactor of this class in the -coming months. - - - jonesde - 2003-09-18 14:43:34 - -This issue has been resolved with code changes similar to those recommended. - -HOWEVER: There is one caveat with this: I would NOT recommend running using -either of these blocks of code. Without a transaction aware connection pool -performance will be severely affected or operations may be performed outside of -transactions. So, I wouldn't use straight JDBC or DBCP right now. Hopefully in -the future DBCP will support XADataSources, then it may be an option. - -Later, --David Jones - - - - ajzeneski - 2003-09-04 22:15:06 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2003-09-04 22:15:06 - resolution - Resolution - - INVALID - - - jonesde - 2003-09-18 14:43:34 - issue_status - Status - RESOLVED - CLOSED - - - jonesde - 2003-09-18 14:43:34 - qa_contact - QA Contact - issues@ofbiz - jonesde - - - - 7 - NEW - P4 - - Components - CVS - All - issues@ofbiz - 20040304194045 - WebTools - fzhu_genshare - not determined - DEFECT - 2003-09-21 07:35:08 - issues@ofbiz - - http://localhost:8080/webtools/control/view/ModelGroupWriter?savetofile=true - - All - "Save Entity Group XML to File" error - - - 8 - jonesde - 2003-11-04 01:04:02 - - - fzhu_genshare - 2003-09-21 07:35:08 - If click "Save Entity Group XML to File" on the webtools, the new page opens and -the following error message appears: - -org.apache.jasper.JasperException: Unable to compile class for JSP - -An error occurred at line: -1 in the jsp file: null - -Generated servlet error: -[javac] Since fork is true, ignoring compiler setting. -[javac] Compiling 1 source file -[javac] Since fork is true, ignoring compiler setting. -[javac] C:\DOCUME~1\ADMINI~1\LOCALS~1 -\Temp\Jetty_0_0_0_0_8080__webtools\entity\ModelGroupWriter_jsp.java:72: -cannot resolve symbol -[javac] symbol : variable entityGroupResourceHandler -[javac] location: class org.ofbiz.entity.model.ModelGroupReader -[javac] ResourceHandler resourceHandler = -modelGroupReader.entityGroupResourceHandler; -[javac] ^ -[javac] 1 error - - - jonesde - 2003-11-04 01:04:02 - *** Issue 8 has been marked as a duplicate of this issue. *** - - - jonesde - 2004-03-04 19:40:45 - lower priority - - - jonesde - 2004-03-04 19:40:45 - priority - Priority - P3 - P4 - - - - 8 - RESOLVED - P3 - DUPLICATE - Components - CVS - All - issues@ofbiz - 20031104010402 - WebTools - fzhu_genshare - not determined - DEFECT - 2003-09-21 07:40:53 - issues@ofbiz - - http://localhost:8080/webtools/control/view/ModelGroupWriter - - All - "Generate Entity Group XML" error - - - 7 - jonesde - 2003-11-04 01:04:02 - - - fzhu_genshare - 2003-09-21 07:40:53 - If clicked "Generate Entity Group XML" on webtools, an error message occurs: - -org.apache.jasper.JasperException: Unable to compile class for JSP - -An error occurred at line: -1 in the jsp file: null - -Generated servlet error: -[javac] Since fork is true, ignoring compiler setting. -[javac] Compiling 1 source file -[javac] Since fork is true, ignoring compiler setting. -[javac] C:\DOCUME~1\ADMINI~1\LOCALS~1 -\Temp\Jetty_0_0_0_0_8080__webtools\entity\ModelGroupWriter_jsp.java:72: -cannot resolve symbol -[javac] symbol : variable entityGroupResourceHandler -[javac] location: class org.ofbiz.entity.model.ModelGroupReader -[javac] ResourceHandler resourceHandler = -modelGroupReader.entityGroupResourceHandler; -[javac] ^ -[javac] 1 error - -It seems the class ResourceHandler is missing. The same error result in several -links of webtools concerning entity engine xml export broken. - - - jonesde - 2003-11-04 01:04:02 - This issue is a duplicate of #7, they may be different links but they hit the same -request and code. - -*** This issue has been marked as a duplicate of 7 *** - - - jonesde - 2003-11-04 01:04:02 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-11-04 01:04:02 - resolution - Resolution - - DUPLICATE - - - - 9 - RESOLVED - P3 - WONTFIX - Components - CVS - All - issues@ofbiz - 20040223211140 - Entity - byersa - not determined - DEFECT - 2003-10-28 09:27:31 - issues@ofbiz - - - - All - GenericEntity.getBytes fails with HSQLDB - - - byersa - 2003-10-28 09:27:31 - getBytes internally casts to ByteWrapper which causes a ClassCastException. -Casting directly to byte[] seems to work. - -Don't know if it fails with other dbs. - - - jonesde - 2004-02-23 21:11:40 - This does not appear to be something that can be fixed in OFBiz, it appears to be a bug in HSQLDB, and -only in certain versions. Trying it with an earlier version it worked, but various other things didn't. We -may just have to be patient until HSQLDB has another stable release. - - - jonesde - 2004-02-23 21:11:40 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-02-23 21:11:40 - resolution - Resolution - - WONTFIX - - - - 10 - RESOLVED - P5 - FIXED - Components - CVS - All - ajzeneski - 20040630193003 - Service - byersa - not determined - ENHANCEMENT - 2003-10-31 08:53:59 - issues@ofbiz - - - - All - missing or incorrect service parameter message - - - byersa - 2003-10-31 08:53:59 - If possible, I think it would be very helpful to developers if the message that -informs on invalid service parameter conditions would clearly indicate whether -it is in the IN or OUT mode that the problem is occurring. - - - ajzeneski - 2004-03-08 12:17:42 - changed to enhancement - - - ajzeneski - 2004-03-08 17:49:18 - reassigned - - - ajzeneski - 2004-06-30 19:30:03 - The ServiceValidationException has been updated to support missing and extra fields as well as -knowing which "mode" (IN/OUT) the error occured in. - - - ajzeneski - 2004-03-08 12:17:42 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - ajzeneski - 2004-03-08 12:17:42 - priority - Priority - P3 - P5 - - - ajzeneski - 2004-03-08 17:49:17 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-06-30 19:30:03 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:30:03 - resolution - Resolution - - FIXED - - - - 11 - RESOLVED - P2 - INVALID - Components - CVS - PC - jonesde - 20031104002629 - Content - cyf - not determined - DEFECT - 2003-11-03 22:26:18 - issues@ofbiz - - - - Windows 2000 - "response.sendRedirect" in jsp could not take effect - - - cyf - 2003-11-03 22:26:18 - I have write a test.jsp code(like): -..... -hello world! -<%response.sendRedirect("control/main");%> -.... - -define : -in controller.xml: -<request-map uri="test" edit="true"> - <response name="success" type="view" value="test"/> - <response name="error" type="view" value="error"/> -</request-map> -..... -<view-map name="test" type="region"/> - -in region also configued - -when I test the page : -it's appear "hello world!",but didn't redirect. - -When I use this code as jsp page in normal web app,redirect can take effect. - -I think this is a bug of in region process. - - - jonesde - 2003-11-04 00:26:29 - -If I understand your complaint correctly it is because the way you organized -things the response output stream is committed before the sendRedirect is -called. There is absolutely nothing that can be done about this. - -If you want to send a redirect you should do so in an event or a non-region view -(and non-jpublish for that matter). Those composite view tools are meant for -generating views and involve templates that may cause the response to be -committed before you wrapped view is even called. - -BTW, this may be more appropriate as a question on the users list, not as a defect -bug report. - -Later, --David Jones - - - jonesde - 2003-11-04 00:26:29 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-11-04 00:26:29 - resolution - Resolution - - INVALID - - - - 12 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040223213513 - Entity - quake_wang - not determined - DEFECT - 2003-11-04 01:39:16 - issues@ofbiz - - - - All - entity cache is not synchronized with DB - - - quake_wang - 2003-11-04 01:39:16 - Quake, - -It might make sense to have an issue created on the ofbiz.dev.java.net -site that covers this problem, since it may take some time to resolve. -Could you create one there? It could just include text from messages -send back and forth in this email thread. - -Thanks, --David - -On Nov 3, 2003, at 6:57 PM, Quake_Wang wrote: - -> The immutable flag can solve some cache synchronize issues, it will -> help for debugging. But, please consider this scenario: -> -> Service A: -> OK, now base on policy: "NEVER read from the cache if you are planning -> on updating", we directly read from DB, -> order = findByPK ("Order", 10000); -> order.set("status", "DEF"); -> order.store(); -> -> -> Service B: -> order = findByPKCache("Order", 10000); -> just query, do not change any fields, entity engine will put the order -> 10000 with "DEF" status in cache, after some other operations (not on -> the order generic value) throw exception, rolled back service A and B, -> then PKCache is not synchronized with DB too, the immutable flag can -> not help any...... -> -> You wrote a service using cache for better performance, and someone -> may assembly your service in same transaction (group service, ECA -> service), the synchronizing may broken, it's really hard to find such -> problem. -> -> Any ideas? -> -> Quake -> -> -----Original Message----- -> From: David Jones [mailto:jonesde@ofbiz.org] -> Sent: Monday, November 03, 2003 11:05 PM -> To: dev@ofbiz.dev.java.net -> Subject: Re: [OFBiz] Dev - Important - [Bug] PKCache is not -> synchronized -> with DB -> -> -> -> Because of the possibility that this is happening and causing -> previously unexplained problems, I decided to go ahead and implement -> the immutable feature on the GenericEntity. This is now in CVS, but may -> cause problems with current code (and will most likely in many cases). -> Do disable this just comment out the line near the beginning of the set -> method in GenericEntity.java. It is around line 248 in the current -> revision of the file. -> -> I fixed a few places that had this problem, including createCustomer in -> ecommerce and the userLogin service. Creating a new customer and going -> through the checkout process works fine now, but variations on the way -> I did it may break. -> -> If we have too many problems with this, I'm okay with disabling it -> temporarily, but it would be nice to go this direction in the future. -> It will help resolve the possibility that strange things happen because -> things are being changed in the cache when they shouldn't be and the -> cache is out of sync with the database, ie is dirty. -> -> Feel free to report bugs along these lines, or better yet send -> patches... -> -> Later, -> -David -> -> -> On Nov 3, 2003, at 5:24 AM, David Jones wrote: -> ->> ->> Quake, ->> ->> Yes, I know this is a problem, although I had forgotten about it since ->> it hasn't come up for a long time. ->> ->> Our official answer on this, related to the use of the cache in ->> general is: NEVER read from the cache if you are planning on updating ->> something. It's tempting to change the GenericValue object to have an ->> unchangeable flag that is set for all versions that go into the ->> cache.... ->> ->> I agree with you, there doesn't seem to be an easy way to ->> automatically clear the cache on a rollback. In most cases the ->> rollback doesn't even go through the Entity Engine, it is done in ->> external code. So, the Entity Engine never gets a notification of the ->> rollback, and if it did it would have to remember every operation that ->> happened during that transaction so it could clear those dirty cache ->> entries. ->> ->> Thus the policy: never use the cache to read when you are planning on ->> writing to the database. And yeah, maybe I should throw some code in ->> there to enforce this... Any thoughts from anyone on that? ->> ->> Later, ->> -David ->> ->> ->> ->> On Nov 3, 2003, at 4:45 AM, Quake_Wang wrote: ->> ->>> Found a bug in the PKCache, below is the scenario ->>> ->>> Service A: ->>> 1. find an order with the order No. 10000, dummy code: ->>> order = findByPKCache("Order", 10000); ->>> assume we get an order with the status "ABC"; ->>> ->>> 2. set the order status to "DEF" and store, dummy code: ->>> order.set("status", "DEF"); ->>> order.store(); ->>> ->>> Service B: ->>> 1. find order 10000 again, dummy code: ->>> order = findByPKCache("Order", 10000); ->>> If the service A and B are in the same transaction (ex, group service ->>> or ECA service), entity engine will get the order with "DEF" status ->>> and put it in the PK cache. ->>> ->>> 2. some other operations, throw exception ->>> Service A and B are rolled back, as the result, the PKCache is not ->>> synchronized with DB: ->>> DB: order 10000, status "ABC" ->>> PKCache: order 10000, status "DEF" ->>> ->>> I spent some time to trace this bug, but can not find an easy way to ->>> fix it, just simply change the findByPKCache to findByPK in service ->>> B. ->>> I'm sending out this email in hopes of helping who may encounter the ->>> same problem and receiving a better fix method. ->>> ->>> Regards ->>> Quake ->>> ->>> --------------------------------------------------------------------- ->>> To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net ->>> For additional commands, e-mail: dev-help@ofbiz.dev.java.net ->> ->> ->> --------------------------------------------------------------------- ->> To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net ->> For additional commands, e-mail: dev-help@ofbiz.dev.java.net -> -> -> --------------------------------------------------------------------- -> To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net -> For additional commands, e-mail: dev-help@ofbiz.dev.java.net -> -> -> --------------------------------------------------------------------- -> To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net -> For additional commands, e-mail: dev-help@ofbiz.dev.java.net - - ---------------------------------------------------------------------- -To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net -For additional commands, e-mail: dev-help@ofbiz.dev.java.net - - - jonesde - 2004-02-23 21:35:13 - -Just a note on this. To fix it there need to be ThreadLocal caches that are maintained by a class that -implements the Synchronization interface for transactions. The idea would be that cache reads look in -the ThreadLocal cache first, then in the global cache, cache writes put everything in the ThreadLocal -cache and when the transaction is committed all ThreadLocal cache entries go into the global cache. --David - - - - 13 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20031112065558 - Entity - byersa - not determined - DEFECT - 2003-11-12 06:15:27 - issues@ofbiz - - - - All - setNonPKFields - - - byersa - 2003-11-12 06:15:27 - I had a situation in which I used setNonPKFields to populate an entity that had -createdData and lastModifiedDate from parameters thinking that it would be a -sort of parameter map. My intention was to then add the individual fields to a -service input, but it turns out that instead of converting the date string to -DateTime format, it kept them as strings and the service complained. I guess the -GenericValue only converts datatypes during the persistence phase? If that is -the case, it would be useful if it converted up loading. - - - jonesde - 2003-11-12 06:55:58 - This is really not the responsibility of the GenericValue object (or really the -GenericEntity object). This is difficult to handle as a defect report and should -be sent to the dev mailing for discussion of the best way to go about what you -are trying to do. The email message should perhaps include more detail about the -overall goal you are trying to accomplish. Note that the GenericEntity, at the -moment, does not enforce types going in, but may be changed to do that and throw -an exception if the type is wrong. -David - - - jonesde - 2003-11-12 06:55:58 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2003-11-12 06:55:58 - resolution - Resolution - - INVALID - - - - 14 - NEW - P3 - - Components - CVS - Macintosh - issues@ofbiz - 20040107162053 - Order - jonesde - not determined - DEFECT - 2004-01-07 16:20:53 - issues@ofbiz - - - - All - Order Summary pages don't show free shipping promo - - - jonesde - 2004-01-07 16:20:53 - Here is a description from Si Chen who reported the problem: - -One thing that I noticed that is anomalous, though, is that the order review -pages still show an estimate for shipping charges, even though the customer -should get free shipping. It seems that the checkout review pages are using -org.ofbiz.order.shoppingcart.shipping.ShippingEvents.getShipEstimate, while on -actual checkout it is using -org.ofbiz.order.order.OrderReadHelper.getShippingTotal. - -The former is not taking into account shipping adjustments. - - - - 15 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040210064750 - Order - nowpulse - not determined - PATCH - 2004-02-10 01:36:16 - issues@ofbiz - - - - All - Order Stats showing incorrect YTD info - - - nowpulse - 2004-02-10 01:36:16 - The YTD info is incorrect since the Java month starts at 0 instead of 1. - -ofbiz/components/order/webapp/ordermgr/WEB-INF/actions/order/orderstats.bsh -On Line 71 the 1 should be replaced with a 0 - -cal.set(Calendar.MONTH, 0); - -thank you, -sterling - - - jonesde - 2004-02-10 06:47:50 - Fixed as recommended. - - - jonesde - 2004-02-10 06:47:50 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-02-10 06:47:50 - resolution - Resolution - - FIXED - - - - 16 - NEW - P4 - - Components - CVS - All - jonesde - 20040527233859 - Product - jonesde - not determined - FEATURE - 2004-02-24 02:56:29 - issues@ofbiz - - - - All - Limit Categories Shown in Drop Downs - - - jonesde - 2004-02-24 02:56:29 - Add "show in drop-down" option ProductCategory, filter by it in all combo style category drop downs, -and change existing category drop-downs to be combo-boxes, include those on the EditProduct, -EditProductCategories, EditCategory, EditCategoryProducts, EditPromoRules pages. - - - jonesde - 2004-05-27 23:38:59 - Some progress has been made on this, but something still needs to be done with the form tool, etc to -limit the drop downs. - - - ajzeneski - 2004-03-18 11:59:21 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-05-27 23:38:59 - priority - Priority - P1 - P4 - - - - 17 - RESOLVED - P1 - FIXED - Components - CVS - All - jonesde - 20040318120731 - Product - jonesde - not determined - FEATURE - 2004-02-24 02:58:45 - issues@ofbiz - - - - All - Filter Promotion Products to exclude discontinued - - - jonesde - 2004-02-24 02:58:45 - Add code to the ProductPromoWorker to (perhaps optionally) filter products included by the -salesDiscontinuationDate, and of course make sure the category member from/thru dates are being -honored. - - - jonesde - 2004-02-25 21:00:44 - Now implemented. - - - jonesde - 2004-02-25 21:00:44 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-02-25 21:00:44 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:07:31 - version - Version - Pre3.0.0 - CVS - - - - 18 - RESOLVED - P1 - FIXED - Components - CVS - All - jonesde - 20040318120740 - Product - jonesde - not determined - DEFECT - 2004-02-24 03:01:49 - issues@ofbiz - - - - All - Back ordered, or insufficient quantities not handled right - - - jonesde - 2004-02-24 03:01:49 - It appears that when a product is back-ordered, or reserved in excess of the AvailableToPromise the -calculations and setting of values are messed up. - -Here is a report on this from Bryce Ewing on Feb 5th, 2004: - -================================================= -I have found something that appears to be a bug (but I am not totally sure), I will explain this in two -cases below: - -case 1: buy 1 item of product1 with no inventory - - inventory item created with 0 on hand, and -1 available to promise - - order item inventory res created with quantity of 1 and quantity not available of 1 - -case 2: buy 2 items of product2 with 1 item in inventory - - inventory item updated with 1 on hand, and -1 available to promise - - order item inventory res created with quantity of 2 and quantity not available of 0 - -For case 1 the system is doing exactly what I would expect, but in case 2 I would have expected that -the order item inventory res record would have had a quantity not available of 1 rather than 0. - -Am I mistaken in this expectation, or is this infact a bug? -================================================= - -Here is a comment on some apparently related findings by Jacopo Cappellato: - -================================================= -I'm studying the simple method InventoryServices.reserveProductInventory -that implements the inventory reservation of on order/order item, and I've -got a question about this issue. -What is the meaning of the quantityNotAvailable field in -OrderItemInventoryRes entity? Where and how is it used (or intended to be -used for)? I've noticed that this quantity is considered in the pick list -reports... - -Probably the quantityNotAvailable field should contain the quantity reserved -that caused inventory item's atp to be less than zero: if so, why in the -reserveProductInventory method the quantityNotAvailable is set only in line -498 and not also after line 458? And in which way, once set, could this -quantity return to zero? -================================================= - - - jonesde - 2004-02-24 18:35:45 - After a patch from Bryce Ewing it appears to be fixed. - - - jonesde - 2004-02-24 18:35:45 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-02-24 18:35:45 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:07:40 - version - Version - Pre3.0.0 - CVS - - - - 19 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120748 - Product - jacopo - not determined - PATCH - 2004-02-24 06:44:51 - issues@ofbiz - - - - All - Patch for bug in the Inventory Receive function - - - jacopo - 2004-02-24 06:44:51 - In Facility manager, when you receive a purchase order delivered with more than -one shipments and you select to receive only one shipment the proposed -quantities are the quantities of the original purchase order and not the -quantities of the shipment. -In my patches I tried to change the minimum amount of code and the -result is that the code is not well written... obviously feel free to change -my code. -PS: I submitted this patches to the dev list in january 2004. -PPS: the two patches are in Unified Output Format - - -Index: ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl -=================================================================== -RCS -file: /cvs/ofbiz/components/product/webapp/facility/inventory/receiveInventory.f -tl,v -retrieving revision 1.5 -diff -u -r1.5 receiveInventory.ftl ---- ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl - 17 Dec 2003 22:46:36 -0000 1.5 -+++ ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl - 14 Jan 2004 11:05:06 -0000 -@@ -312,6 +312,9 @@ - </tr> - <#list purchaseOrderItems as orderItem> - <#assign defaultQuantity = orderItem.quantity - receivedQuantities -[orderItem.orderItemSeqId]?double> -+ <#if shipment?has_content> -+ <#assign defaultQuantity = shippedQuantities -[orderItem.orderItemSeqId]?double - receivedQuantities -[orderItem.orderItemSeqId]?double> -+ </#if> - <#if 0 < defaultQuantity> - <#assign orderItemType = orderItem.getRelatedOne("OrderItemType")> - <input type="hidden" name="orderId_o_${rowCount}" -value="${orderItem.orderId}"> - - - - - - - -Index: ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh -=================================================================== -RCS file: /cvs/ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh,v -retrieving revision 1.4 -diff -u -r1.4 receiveInventory.bsh ---- ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh 25 Aug 2003 15:28:00 -0000 - 1.4 -+++ ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh 14 Jan 2004 11:08:14 -0000 -@@ -69,6 +69,7 @@ - shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap -("shipmentId", shipmentId)); - } - -+shippedQuantities = new HashMap(); - purchaseOrderItems = null; - if (purchaseOrder != null) { - if (product != null) { -@@ -80,14 +81,18 @@ - exprs = new ArrayList(); - while (issueIter.hasNext()) { - issuance = issueIter.next(); -- exprs.add(new EntityExpr("orderItemSeqId", EntityOperator.EQUALS, -issuance.getString("orderItemSeqId"))); -+ exprs.add(new EntityExpr("orderItemSeqId", EntityOperator.EQUALS, -issuance.getString("orderItemSeqId"))); -+ double issuanceQty = issuance.getDouble("quantity").doubleValue(); -+ if (shippedQuantities.containsKey(issuance.getString -("orderItemSeqId"))) { -+ issuanceQty += ((Double)shippedQuantities.get -(issuance.getString("orderItemSeqId"))).doubleValue(); -+ } -+ shippedQuantities.put(issuance.getString("orderItemSeqId"), -issuanceQty); - } - purchaseOrderItems = EntityUtil.filterByOr(orderItems, exprs); - } else { - purchaseOrderItems = purchaseOrder.getRelated("OrderItem"); - } - } -- - receivedQuantities = new HashMap(); - if (purchaseOrderItems != null && purchaseOrderItems.size() > 0) { - context.put("firstOrderItem", EntityUtil.getFirst(purchaseOrderItems)); -@@ -100,7 +105,13 @@ - if (receipts != null && receipts.size() > 0) { - recIter = receipts.iterator(); - while (recIter.hasNext()) { -- rec = recIter.next(); -+ rec = recIter.next(); -+ if (shipment != null) { -+ if (rec.getString("shipmentId") == null || -+ !rec.getString("shipmentId").equals(shipment.getString -("shipmentId"))) { -+ continue; -+ } -+ } - accepted = rec.getDouble("quantityAccepted"); - rejected = rec.getDouble("quantityRejected"); - if (accepted != null) -@@ -140,6 +151,7 @@ - context.put("product", product); - context.put("shipments", shipments); - context.put("shipment", shipment); -+context.put("shippedQuantities", shippedQuantities); - context.put("purchaseOrderItems", purchaseOrderItems); - context.put("receivedQuantities", receivedQuantities); - context.put("rejectReasons", rejectReasons); - - - jacopo - 2004-02-24 06:55:45 - Created an attachment (id=1) -Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl - - - - jonesde - 2004-03-01 06:35:22 - The changes are in CVS. Thanks Jacopo! - - - text/plain - 1 - 2004-02-24 06:55:45 - Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl - 1 - receiveInventory.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/1/receiveInventory.patch - - - jacopo - 2004-02-24 06:55:45 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=1) -Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl - - - - jonesde - 2004-03-01 06:35:22 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 06:35:22 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:07:48 - version - Version - Pre3.0.0 - CVS - - - - 20 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120758 - Party - jacopo - not determined - PATCH - 2004-02-24 07:36:49 - issues@ofbiz - - - - All - List All Visits link in the Party Profile page returns an error with 0 visits - - - jacopo - 2004-02-24 07:36:50 - List All Visits link in the Party Profile page returns an error with 0 visits -(see attached patch file) due to wrong bsh code. - - - jacopo - 2004-02-24 07:38:20 - Created an attachment (id=2) -Patch for bug in uof - - - - jonesde - 2004-03-01 06:39:57 - The changes are in CVS. Thanks Jacopo! - - - text/plain - 2 - 2004-02-24 07:38:20 - Patch for bug in uof - 1 - showvisits.bsh.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/2/showvisits.bsh.patch - - - jacopo - 2004-02-24 07:38:20 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=2) -Patch for bug in uof - - - - jonesde - 2004-03-01 06:39:57 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 06:39:57 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:07:58 - version - Version - Pre3.0.0 - CVS - - - - 21 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120807 - Party - jacopo - not determined - PATCH - 2004-02-24 07:40:56 - issues@ofbiz - - - - All - findparty page returns JavaScript errors when clicking on the LookupParty link and when the lookup fields are hidden - - - jacopo - 2004-02-24 07:40:56 - findparty page returns JavaScript errors when clicking on the LookupParty link -and when the lookup fields are hidden. The attached patch should fix the -problem. - - - jacopo - 2004-02-24 07:41:29 - Created an attachment (id=3) -Patch for bug in uof - - - - jonesde - 2004-03-01 06:44:01 - Your changes are in CVS. Thanks Jacopo! - - - text/plain - 3 - 2004-02-24 07:41:29 - Patch for bug in uof - 1 - findparty.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/3/findparty.ftl.patch - - - jacopo - 2004-02-24 07:41:29 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=3) -Patch for bug in uof - - - - jonesde - 2004-03-01 06:44:01 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 06:44:01 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:07 - version - Version - Pre3.0.0 - CVS - - - - 22 - NEW - P3 - - Components - CVS - All - ajzeneski - 20040318115951 - Order - jacopo - not determined - DEFECT - 2004-02-24 08:52:07 - issues@ofbiz - - - - All - Errors in order entry when "Payment Already Received" type is selected. - - - jacopo - 2004-02-24 08:52:08 - In Order Entry: -when you finalize an order and, in the "Order Entry Payment -Settings" page, you select the "Payment Already Received" type, in the -following page you get JavaScript errors when you click over -the links (stating that the object "document.billsetupform" doesn't exist); -and so you cannot submit the order. - - - jonesde - 2004-02-26 07:08:20 - -This has been an issue for a while now. It's good to have it in the tracking system since it may not get -fixed right away. Andy is more aware of what is happening there than I am, so he may have more -feedback on it. -David - - - jonesde - 2004-02-26 07:08:20 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - jonesde - 2004-02-26 07:08:20 - priority - Priority - P2 - P3 - - - ajzeneski - 2004-03-18 11:59:51 - version - Version - Pre3.0.0 - CVS - - - - 23 - NEW - P4 - - Components - CVS - All - ajzeneski - 20040318120006 - Product - jacopo - not determined - DEFECT - 2004-02-24 08:56:40 - issues@ofbiz - - - - All - Inventory receive ignores the inventory item id field. - - - jacopo - 2004-02-24 08:56:40 - In Facility Manager -> Inventory receive: -it always creates a new inventory item even if the "inventory item id" optional -field is filled with an existing inventory item id. - - - ajzeneski - 2004-03-08 17:38:11 - reassigned - - - ajzeneski - 2004-03-08 17:38:11 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-03-18 12:00:06 - version - Version - Pre3.0.0 - CVS - - - - 24 - NEW - P4 - - Components - CVS - All - ajzeneski - 20040318120024 - Product - jacopo - not determined - DEFECT - 2004-02-24 09:01:59 - issues@ofbiz - - - - All - Receive return: it always creates serialized inventory items. - - - jacopo - 2004-02-24 09:01:59 - In Facility Manager -->Receive return - -it always creates a serialized inventory item (even if 'non-serialized' is -selected) and so the received quantities are lost (if more than one). - - - ajzeneski - 2004-03-08 17:38:55 - reassigned - - - ajzeneski - 2004-03-08 17:38:55 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-03-18 12:00:24 - version - Version - Pre3.0.0 - CVS - - - - 25 - RESOLVED - P2 - INVALID - Components - CVS - All - ajzeneski - 20040318120814 - Accounting - jonesde - not determined - DEFECT - 2004-02-25 14:58:53 - issues@ofbiz - - - - All - Permission Checks missing in various part of Accounting Manager - - - jonesde - 2004-02-25 14:58:53 - Various pages in the Accounting Manager have no view permission checking, including the billing -account, invoice, etc pages. - - - jaz - 2004-02-25 15:36:03 - I'm not involved in this project. - - - jonesde - 2004-02-25 16:13:54 - -Fixed assigned to mistake. - - - ajzeneski - 2004-03-08 10:48:28 - All components have a default VIEW permission based on the component configuration. Each page no -longer needs to have the added code as long as require auth is set in the controller.xml file. The -checkLogin event will make sure the user has the default permission for the specific component. -Additional permissions are only necessary when not using the default permission. - - - jaz - 2004-02-25 15:36:03 - assigned_to - Assigned To - jaz - jonesde - - - jonesde - 2004-02-25 16:13:54 - assigned_to - Assigned To - jonesde - ajzeneski - - - ajzeneski - 2004-03-08 10:48:28 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-03-08 10:48:28 - resolution - Resolution - - INVALID - - - ajzeneski - 2004-03-18 12:08:14 - version - Version - Pre3.0.0 - CVS - - - - 26 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040308115822 - Order - jonesde - not determined - DEFECT - 2004-02-25 21:11:36 - issues@ofbiz - - - - All - Billing Account Errors - - - jonesde - 2004-02-25 21:11:36 - This issue was reported by Si Chen, Olivier Heintz, and some others. - -The following is some text from an email fro Si Chen on Jan 26, 2004; the attached patch is also from -this email. - -======================================= -Hello. After some work we have tracked down the problem with using -billingAccount in the order manager and were able to fix it. The -problem is stated in the order manager's billsettings.ftl, it was -passing in "EXT_BILLACT|10000" for the checkoutPaymentId instead of -separate checkoutPaymentId and billingAccountId. Olivier had suggested -a good patch earlier which parses this form of checkoutPaymentId in the -CheckOutEvents.java. We took a different approach and used code from -ecommerce to pass both checkoutPaymentId and billingAccountId. We also -fixed CheckOutEvents.java to get the billingAccountId from the request -and associate it with the cart. Both are shown in the attached patch. - -One last problem: in ecommerce, in checkoutpayment.ftl, gift cards, -credit cards, and billing accounts are all using "amount_<account_id>" -as the name of the input fields. As a result, when the -toggleBillingAccount javascript function tries to toggle the billing -account selected for entering the amount to pay, it gets confused and -cannot do this. As a result, when you use the multi-page rather than -express checkout in ecommerce, it does not work properly. I'll be happy -to elaborate on this if you need me to. -======================================= - - - jonesde - 2004-02-25 21:14:01 - Created an attachment (id=4) -Patch to fix BillingAccount issues - - - - ajzeneski - 2004-03-08 11:58:22 - Applied patch; fixed JS in ecommerce - - - text/plain - 4 - 2004-02-25 21:14:01 - Patch to fix BillingAccount issues - 1 - BillingAccountError.patch - 3 - jonesde - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/4/BillingAccountError.patch - - - jonesde - 2004-02-25 21:14:01 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=4) -Patch to fix BillingAccount issues - - - - ajzeneski - 2004-03-08 11:58:22 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-03-08 11:58:22 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-08 11:58:22 - version - Version - Pre3.0.0 - CVS - - - - 27 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120822 - WorkEffort - jacopo - not determined - PATCH - 2004-02-26 03:20:00 - issues@ofbiz - - - - All - Patch for missing pagedef file for popup template that causes lookup error (due to i18n changes) - - - jacopo - 2004-02-26 03:20:00 - The lookup link in New Event -> Parties page is broken. -The popup template doesn't run the envsetup script that loads the localized -labels. - -PATCH: add a file named "popup.xml" to the template folder containing the -following lines: - -<?xml version="1.0" encoding="UTF-8"?> -<page> - <template-action name="/includes/envsetup.bsh"/> -</page> - - - jonesde - 2004-03-01 07:16:55 - -I have added the popup.xml file to CVS. Thanks for sending it over Jacopo. - - - jonesde - 2004-03-01 07:16:55 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 07:16:55 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:22 - version - Version - Pre3.0.0 - CVS - - - - 28 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040806161040 - WorkEffort - jacopo - not determined - PATCH - 2004-02-26 03:32:11 - issues@ofbiz - - - - All - Added lookup link for parties in month view - - - jacopo - 2004-02-26 03:32:11 - Added lookup link for parties in month view. -All the stuff was already in place... I just added the link. -However I think this is a very useful enhancement. - - - jacopo - 2004-02-26 03:32:44 - Created an attachment (id=5) -Patch in UOF - - - - jonesde - 2004-03-03 08:10:20 - Changed issue type as per email from Jacopo. - - - jonesde - 2004-08-06 16:10:40 - Thanks Jacopo, this is now in CVS. - - - text/plain - 5 - 2004-02-26 03:32:44 - Patch in UOF - 1 - month.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/5/month.ftl.patch - - - jacopo - 2004-02-26 03:32:44 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=5) -Patch in UOF - - - - jonesde - 2004-03-03 08:10:20 - issue_type - Issue Type - ENHANCEMENT - PATCH - - - ajzeneski - 2004-03-18 12:00:44 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-08-06 16:10:40 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-06 16:10:40 - resolution - Resolution - - FIXED - - - - 29 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120831 - WorkEffort - jacopo - not determined - PATCH - 2004-02-26 03:56:48 - issues@ofbiz - - - - All - When creating a new event from calendar, start and end date were not filled properly in the form - - - jacopo - 2004-02-26 03:56:48 - When creating a new event from calendar, start and end date were not filled -properly in the event form. -The two patches (one for the event.ftl file and one for the event.bsh file) -will solve this problem. - - - jacopo - 2004-02-26 03:59:24 - Created an attachment (id=6) -Patch for event.bsh in UOF - - - - jacopo - 2004-02-26 03:59:58 - Created an attachment (id=7) -Patch for event.ftl file in UOF - - - - jonesde - 2004-03-01 07:28:02 - Your changes are in CVS, thanks Jacopo! - - - text/plain - 6 - 2004-02-26 03:59:24 - Patch for event.bsh in UOF - 1 - event.bsh.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/6/event.bsh.patch - - - text/plain - 7 - 2004-02-26 03:59:58 - Patch for event.ftl file in UOF - 1 - event.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/7/event.ftl.patch - - - jacopo - 2004-02-26 03:59:24 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=6) -Patch for event.bsh in UOF - - - - jacopo - 2004-02-26 03:59:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=7) -Patch for event.ftl file in UOF - - - - jonesde - 2004-03-01 07:28:02 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 07:28:02 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:31 - version - Version - Pre3.0.0 - CVS - - - - 30 - NEW - P5 - - Components - CVS - All - ajzeneski - 20040308175050 - Order - jackhung - not determined - DEFECT - 2004-02-26 04:17:49 - issues@ofbiz - - - - All - Fail to approval order - - - jackhung - 2004-02-26 04:17:49 - 19285437[ ControlServlet.java:133:DEBUG] [[[updateactivityassign] Servlet -Starting, doing setup- total:0.0,since last(Begin):0.0]] -19285438[ ControlServlet.java:182:DEBUG] [[[updateactivityassign] Setup -done, doing Event(s) and View(s)- total:0.0,since last([updateactivityas...):0.0]] -19285440[ RequestHandler.java:200:INFO ] [Processing Request]: -updateactivityassign -19285744[ WfProcessMgrImpl.java:106:INFO ] [WfProcessMgr.init] : Create -process manager (org.ofbiz.order[20030730144901] / ProcessOrder[20030730144901]) -19285890[ BshUtil.java:75 :ERROR] BSH Evaluation error. -Sourced file: <Inline eval of: approvalCode.equals("0"); > : Attempt to resolve -method: equals() on undefined variable or class name: approvalCode : at Line: 1 -: in file: <Inline eval of: approvalCode.equals("0"); > : approvalCode .equals ( -"0" ) - - at bsh.UtilEvalError.toEvalError(UtilEvalError.java:82) - at bsh.UtilEvalError.toEvalError(UtilEvalError.java:87) - at bsh.BSHMethodInvocation.eval(BSHMethodInvocation.java:79) - at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:69) - at bsh.Interpreter.evalParsedScript(Interpreter.java:1104) - at bsh.Interpreter.eval(Interpreter.java:590) - at bsh.Interpreter.eval(Interpreter.java:616) - at bsh.Interpreter.eval(Interpreter.java:606) - at org.ofbiz.base.util.BshUtil.eval(BshUtil.java:64) - at -org.ofbiz.workflow.impl.WfExecutionObjectImpl.evalBshCondition(WfExecutionObjectImpl.java:718) - at -org.ofbiz.workflow.impl.WfProcessImpl.getTransFrom(WfProcessImpl.java:477) - at org.ofbiz.workflow.impl.WfProcessImpl.queueNext(WfProcessImpl.java:298) - at -org.ofbiz.workflow.impl.WfProcessImpl.activityComplete(WfProcessImpl.java:286) - at org.ofbiz.workflow.impl.WfActivityImpl.complete(WfActivityImpl.java:408) - at -org.ofbiz.workflow.impl.WfAssignmentImpl.complete(WfAssignmentImpl.java:175) - at -org.ofbiz.workflow.client.WorkflowClient.complete(WorkflowClient.java:266) - at -org.ofbiz.workflow.client.WorkflowServices.completeAssignment(WorkflowServices.java:418) - - - ajzeneski - 2004-03-08 12:08:46 - I cannot duplicate this problem; please provide more information or we will have to close this has no -longer an issue. - - - ajzeneski - 2004-03-08 17:50:50 - reassigned - - - ajzeneski - 2004-03-08 12:08:46 - issue_status - Status - NEW - STARTED - - - ajzeneski - 2004-03-08 12:08:46 - op_sys - OS/Version - Linux - All - - - ajzeneski - 2004-03-08 12:08:46 - rep_platform - Platform - PC - All - - - ajzeneski - 2004-03-08 12:08:46 - short_desc - Summary - Fail to approval order - Fail to approval order - - - ajzeneski - 2004-03-08 17:50:50 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-03-08 17:50:50 - issue_status - Status - STARTED - NEW - - - ajzeneski - 2004-03-08 17:50:50 - priority - Priority - P2 - P5 - - - - 31 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040318120101 - WorkEffort - jacopo - not determined - DEFECT - 2004-02-26 05:39:36 - issues@ofbiz - - - - All - Error message when you try to create new contact information under an event - - - jacopo - 2004-02-26 05:39:36 - An error message is returned when you try to create new contact information -under an event: Cannot locate service by name (createWorkEffortContactMech) - -This is the complete message: - -ERROR: Could not complete the Create an email address for WorkEffort process -[problem invoking the [createWorkEffortContactMech] service with the map named -[context] containing [{locale=en_US, infoString=foo@bar.com, userLogin= -[GenericEntity:UserLogin][partyId,admin(java.lang.String)][disabledDateTime,null -()][passwordHint,null()][createdTxStamp,null()][successiveFailedLogins,null()] -[enabled,Y(java.lang.String)][userLoginId,admin(java.lang.String)] -[currentPassword,ofbiz(java.lang.String)][lastUpdatedTxStamp,null()] -[lastUpdatedStamp,null()][createdStamp,null()], workEffortId=10030, -contactMechTypeId=EMAIL_ADDRESS}]: Cannot locate service by name -(createWorkEffortContactMech)] - - - ajzeneski - 2004-03-18 12:01:01 - version - Version - Pre3.0.0 - CVS - - - - 32 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040409054533 - WorkEffort - jacopo - not determined - DEFECT - 2004-02-26 05:50:01 - issues@ofbiz - - - - All - Errors that prevent adding a new phase to a project. - - - jacopo - 2004-02-26 05:50:01 - It's impossible to add a new phase to a project. Even if you fill all the -fields of the new phase form when you press the 'create' button you get an -error in the system log (however no error messages are shown in the html page). - -This is the complete error message: - -1160388[ ServiceDispatcher.java:309:ERROR] Service Error [createPhase]: ERROR: -Could not complete the Create Project Phase process [problem creating the newEnt -ity value: while inserting: [GenericEntity:WorkEffortAssoc][createdTxStamp,2004- -02-26 14:44:26.096(java.sql.Timestamp)][workEffortIdTo,10034(java.lang.String)][ -workEffortIdFrom,10031(java.lang.String)][workEffortAssocTypeId,WORK_EFF_BREAKDO -WN(java.lang.String)][lastUpdatedTxStamp,2004-02-26 14:44:26.096(java.sql.Timest -amp)][createdStamp,2004-02-26 14:44:26.106(java.sql.Timestamp)][lastUpdatedStamp -,2004-02-26 14:44:26.106(java.sql.Timestamp)] (SQL Exception while executing the - following:INSERT INTO WORK_EFFORT_ASSOC (WORK_EFFORT_ID_FROM, WORK_EFFORT_ID_TO -, WORK_EFFORT_ASSOC_TYPE_ID, SEQUENCE_NUM, FROM_DATE, THRU_DATE, LAST_UPDATED_ST -AMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, CREATED_TX_STAMP) VALUES (?, ?, ?, ?, - ?, ?, ?, ?, ?, ?) ([-5005] (at 124): Missing non-NULL value))] - - - jacopo - 2004-04-09 05:45:33 - David Jones has fixed this problem in date 2004-04-08 (see the -thread "createphase ERROR in OFBiz 3.0 and OFBiz CVS versions" in the dev-list). - - - - ajzeneski - 2004-03-18 12:01:18 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2004-04-09 05:45:33 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-04-09 05:45:33 - resolution - Resolution - - FIXED - - - - 33 - RESOLVED - P4 - FIXED - Components - CVS - All - issues@ofbiz - 20050209023142 - WorkEffort - jacopo - not determined - DEFECT - 2004-02-26 06:00:26 - issues@ofbiz - - - - All - When you create a new request and you don't fill correctly all the fields no error messages are shown - - - jacopo - 2004-02-26 06:00:26 - When you create a new request and you don't fill correctly all the fields no -error messages are shown. - - - jacopo - 2005-02-09 02:31:42 - Fixed after the refactoring to screen widget. - - - ajzeneski - 2004-03-18 12:01:30 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2005-02-09 02:31:42 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2005-02-09 02:31:42 - resolution - Resolution - - FIXED - - - - 34 - RESOLVED - P5 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120838 - Order - jacopo - not determined - PATCH - 2004-02-26 06:11:14 - issues@ofbiz - - - - All - Little JavaScript in "find returns" when lookup fields are hidden - - - jacopo - 2004-02-26 06:11:14 - Little JavaScript in "find returns" when lookup fields are hidden - -Patch for findReturns.ftl is attached. - - - jacopo - 2004-02-26 06:11:49 - Created an attachment (id=8) -Patch for findReturn.ftl in UOF - - - - jonesde - 2004-03-01 11:18:49 - Your changes are in CVS. Thanks for sending that over. - - - text/plain - 8 - 2004-02-26 06:11:49 - Patch for findReturn.ftl in UOF - 1 - findReturn.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/8/findReturn.ftl.patch - - - jacopo - 2004-02-26 06:11:49 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=8) -Patch for findReturn.ftl in UOF - - - - jonesde - 2004-03-01 11:18:49 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 11:18:49 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:38 - version - Version - Pre3.0.0 - CVS - - - - 35 - RESOLVED - P1 - FIXED - Components - CVS - All - ajzeneski - 20040308103928 - E-Commerce - razorb - not determined - DEFECT - 2004-02-26 06:18:48 - issues@ofbiz - - http://localhost:8080/ecommerce/control/product/~category_id=100/~product_id=GZ-1006 - - All - Single variant combo doesn't select properly - - - razorb - 2004-02-26 06:18:48 - Using the drop down menu to select a variantion i.e. LGPL does not set the -selection on the menu. Using the swatch/images does correctly set the menu -selection and allows adding to the basket. - -I suspect a little JS error somewhere for single variant items. - - - jonesde - 2004-02-26 06:52:49 - -I just reproduced this against the latest code base, appears to still be an issue with single feature type -virtual products. - - - ajzeneski - 2004-03-08 09:54:51 - Updated since this is a CVS bug and updated status - - - ajzeneski - 2004-03-08 10:39:28 - fixed JS bugs in productdetail - - - jonesde - 2004-02-26 06:52:48 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - jonesde - 2004-02-26 06:52:48 - priority - Priority - P3 - P1 - - - ajzeneski - 2004-03-08 09:54:51 - issue_status - Status - NEW - STARTED - - - ajzeneski - 2004-03-08 09:54:51 - version - Version - Pre3.0.0 - CVS - - - ajzeneski - 2004-03-08 10:39:28 - issue_status - Status - STARTED - RESOLVED - - - ajzeneski - 2004-03-08 10:39:28 - resolution - Resolution - - FIXED - - - - 36 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120846 - Product - jacopo - not determined - PATCH - 2004-02-26 23:17:51 - issues@ofbiz - - - - All - Facility Manager: in 'inventory receive' the type of order is not checked and it's possible to receive a sales order if you enter its id in the 'purchase order id' field - - - jacopo - 2004-02-26 23:17:51 - Facility Manager: in 'inventory receive' the type of order is not checked and -it's possible to receive a sales order if you enter its id in the 'purchase -order id' field. - -This is the patch in UOF for the receiveInventory.bsh file (pay attention that -some days ago I've submitted a patch for the same file against the same CVS -release): - -Index: ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh -=================================================================== -RCS file: /cvs/ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh,v -retrieving revision 1.4 -diff -u -r1.4 receiveInventory.bsh ---- ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh 25 Aug 2003 15:28:00 -0000 - 1.4 -+++ ofbiz/components/product/webapp/facility/WEB- -INF/actions/inventory/receiveInventory.bsh 27 Feb 2004 07:17:08 -0000 -@@ -43,6 +43,9 @@ - purchaseOrder = null; - if (purchaseOrderId != null && purchaseOrderId.length() > 0) { - purchaseOrder = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap -("orderId", purchaseOrderId)); -+ if (purchaseOrder != null && !"PURCHASE_ORDER".equals -(purchaseOrder.getString("orderTypeId"))) { -+ purchaseOrder = null; -+ } - } - - product = null; - - - jonesde - 2004-02-28 11:58:13 - The patch is in CVS. - - - jonesde - 2004-02-28 11:58:13 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-02-28 11:58:13 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:46 - version - Version - Pre3.0.0 - CVS - - - - 37 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120856 - Product - jacopo - not determined - DEFECT - 2004-02-27 02:05:25 - issues@ofbiz - - - - All - Facility Manager: error message when trying to confirm stock moves needed. - - - jacopo - 2004-02-27 02:05:25 - In the Facility Manager, int the PickList -> Stock Moves page, if I try to -confirm the "stock moves needed" proposed by the system I get the following -error: - -Error calling event: org.ofbiz.content.webapp.event.EventHandlerException: No -rows to process - -And the movements are not performed. - - - jonesde - 2004-03-01 17:22:23 - This is caused by some code that was added to display warning messages that wiped out the rowCount -variable. The warning message loop now uses a variable names messageCount. - - - jonesde - 2004-03-01 17:22:23 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 17:22:23 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:08:56 - version - Version - Pre3.0.0 - CVS - - - - 38 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120905 - Product - jacopo - not determined - PATCH - 2004-02-27 02:23:36 - issues@ofbiz - - - - All - Facility Manager: in Edit shipment -> items tab, a wrong link to EditProduct page caused a controller error. - - - jacopo - 2004-02-27 02:23:36 - Facility Manager: in Edit shipment -> items tab, a wrong link to EditProduct -page caused a controller error. - -Patch for EditShipmentItems.ftl file is attached. - - - jacopo - 2004-02-27 02:24:16 - Created an attachment (id=9) -Patch for EditShipmentItems.ftl in UOF - - - - jonesde - 2004-03-01 07:38:50 - Your changes are in CVS. Thanks for the patch Jacopo. - - - text/plain - 9 - 2004-02-27 02:24:16 - Patch for EditShipmentItems.ftl in UOF - 1 - EditShipmentItems.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/9/EditShipmentItems.ftl.patch - - - jacopo - 2004-02-27 02:24:16 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=9) -Patch for EditShipmentItems.ftl in UOF - - - - jonesde - 2004-03-01 07:38:50 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 07:38:50 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:09:05 - version - Version - Pre3.0.0 - CVS - - - - 39 - NEW - P2 - - Components - CVS - All - issues@ofbiz - 20040318120141 - Order - jacopo - not determined - DEFECT - 2004-02-27 04:05:34 - issues@ofbiz - - - - All - SapDB problem when displaying order task list assigned to user role - - - jacopo - 2004-02-27 04:05:34 - SapDB problem when displaying order task list assigned to user role: -if more than one order is assigned to user role, in "Order List" page the -orders are shown 5 times! -If only one order is assigned to the user role, the order is shown well (1 -time). - -See picture attached. - - - jacopo - 2004-02-27 04:07:00 - Created an attachment (id=10) -Bug example showing two orders waiting approval duplicated 5 times. - - - - image/gif - 10 - 2004-02-27 04:07:00 - Bug example showing two orders waiting approval duplicated 5 times. - - order_list_bug.GIF - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/10/order_list_bug.GIF - - - jacopo - 2004-02-27 04:07:00 - attachments.thedata - Attachment Data - - Created an attachment (id=10) -Bug example showing two orders waiting approval duplicated 5 times. - - - - ajzeneski - 2004-03-18 12:01:41 - version - Version - Pre3.0.0 - CVS - - - - 40 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20050209023003 - WorkEffort - jacopo - not determined - DEFECT - 2004-02-27 07:27:15 - issues@ofbiz - - - - All - Party lookup with empty fields returns only one person repeated many times (= number of persons). - - - jacopo - 2004-02-27 07:27:15 - If, in Party lookup, you perform a lookup with empty fields (all records), -returns only one person repeated many times (= number of persons). -I suspect that the problem is in the "lookupParty" simple method in common -component. - - - jacopo - 2005-02-09 02:30:03 - Fixed changing the way the lookup is implemented (see Jira issue OFBIZ-114). - - - ajzeneski - 2004-03-18 12:01:50 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2005-02-09 02:30:03 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2005-02-09 02:30:03 - resolution - Resolution - - FIXED - - - - 41 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120912 - Product - jacopo - not determined - PATCH - 2004-02-27 08:53:04 - issues@ofbiz - - - - All - Facility Manager: in Edit shipment -> items tab, a wrong link to EditProduct caused a controller error (same as issue #38) - - - jacopo - 2004-02-27 08:53:04 - Facility Manager: in View shipment tab, a wrong link to EditProduct -page caused a controller error (same as issue #38). - -Patch for ViewShipmentItemInfo.ftl file is attached. - - - jacopo - 2004-02-27 08:53:50 - Created an attachment (id=11) -Patch for file ViewShipmentItemInfo.ftl in UOF - - - - jonesde - 2004-03-01 07:41:15 - Your changes are now in CVS. Thanks for sending those over Jacopo. - - - text/plain - 11 - 2004-02-27 08:53:50 - Patch for file ViewShipmentItemInfo.ftl in UOF - 1 - ViewShipmentItemInfo.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/11/ViewShipmentItemInfo.ftl.patch - - - jacopo - 2004-02-27 08:53:50 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=11) -Patch for file ViewShipmentItemInfo.ftl in UOF - - - - jonesde - 2004-03-01 07:41:15 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 07:41:15 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:09:12 - version - Version - Pre3.0.0 - CVS - - - - 42 - RESOLVED - P4 - WONTFIX - Components - CVS - All - ajzeneski - 20040630193328 - Product - jacopo - not determined - DEFECT - 2004-02-28 22:34:42 - issues@ofbiz - - - - All - In shipment, the following error message appears: "Applet Package Weight Reader notinited" - - - jacopo - 2004-02-28 22:34:42 - In shipment, the following error message appears: "Applet Package Weight Reader -notinited". -I think the problem is caused by the fact that the class ShipmentScaleApplet is -not built in the ant task. -Was this done intentionally? (I think this applet tries to connect to a scale -device connected to a serial port and so probably this could cause some -problems...). - - - ajzeneski - 2004-03-08 17:39:52 - reassigned; I will comment out the applet code until this is finished - - - ajzeneski - 2004-06-30 19:33:28 - The applet is going to be replaced with a think client shipment station UI - - - ajzeneski - 2004-03-08 17:39:52 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-03-18 12:01:59 - version - Version - Pre3.0.0 - CVS - - - ajzeneski - 2004-06-30 19:33:28 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:33:28 - resolution - Resolution - - WONTFIX - - - - 43 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040318120921 - E-Commerce - jacopo - not determined - PATCH - 2004-02-28 22:46:49 - issues@ofbiz - - - - All - In "Create Return", select-all checkbox doesn't work due to wrong form name. - - - jacopo - 2004-02-28 22:46:49 - In "Create Return", select-all checkbox doesn't work due to wrong form name. - -Patch attached for requestreturn.ftl in Unified Output Format. - - - jacopo - 2004-02-28 22:47:40 - Created an attachment (id=12) -Patch attached for requestreturn.ftl in UOF. - - - - jonesde - 2004-03-01 07:48:30 - Your changes are in CVS. Thanks for fixing that. - - - text/plain - 12 - 2004-02-28 22:47:39 - Patch attached for requestreturn.ftl in UOF. - 1 - requestreturn.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/12/requestreturn.ftl.patch - - - jacopo - 2004-02-28 22:47:40 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=12) -Patch attached for requestreturn.ftl in UOF. - - - - jonesde - 2004-03-01 07:48:30 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-01 07:48:30 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-18 12:09:21 - version - Version - Pre3.0.0 - CVS - - - - 44 - NEW - P4 - - Components - CVS - All - issues@ofbiz - 20040229030013 - Product - jacopo - not determined - ENHANCEMENT - 2004-02-29 03:00:13 - issues@ofbiz - - - - All - Packages: ShipmentPackage's weight automatically updated when ShipmentPackageContent entries are added/deleted (weight taken from the Product entity). - - - jacopo - 2004-02-29 03:00:13 - Packages: ShipmentPackage's weight automatically updated when -ShipmentPackageContent entries are added/deleted (weight taken from the Product -entity). - - - - 45 - RESOLVED - P1 - FIXED - Components - CVS - All - issues@ofbiz - 20040301155709 - Order - jacopo - not determined - DEFECT - 2004-02-29 06:17:33 - issues@ofbiz - - - - All - In orderview page, if you select the "QuickShip order link" you get a controller error. - - - jacopo - 2004-02-29 06:17:33 - In orderview page (/ordermgr/control/orderview), if you select the "QuickShip -order link" you get a controller error: - -org.ofbiz.content.webapp.control.RequestHandlerException: Unknown request -[quickShipOrderMultiFacility]; this request does not exist or cannot be called -directly. - - - jonesde - 2004-03-01 12:11:07 - I'll get on this... - - - jonesde - 2004-03-01 15:57:09 - Changed the default behavior for this; also added request-map and service defs for the quick ship from -multi facilites. - - - jonesde - 2004-03-01 12:11:07 - issue_status - Status - NEW - STARTED - - - jonesde - 2004-03-01 15:57:09 - issue_status - Status - STARTED - RESOLVED - - - jonesde - 2004-03-01 15:57:09 - resolution - Resolution - - FIXED - - - - 46 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040806152631 - Product - jacopo - not determined - PATCH - 2004-03-02 05:13:01 - issues@ofbiz - - - - All - Patch for multiple inventory facility reservation - - - jacopo - 2004-03-02 05:13:01 - Patch for multiple inventory facility reservation: -the intent of this is to perform reservation only if all items are available in -one facility: that, I think, is the declared behaviour, and what is checked -with the isInventoryAvailable method. - - - jacopo - 2004-03-02 05:13:49 - Created an attachment (id=13) -Patch for ProductStoreWorker.java in UOF - - - - jonesde - 2004-08-06 15:26:31 - Thanks Jacopo, your patch is now in CVS. - - - text/plain - 13 - 2004-03-02 05:13:49 - Patch for ProductStoreWorker.java in UOF - 1 - ProductStoreWorker.java.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/13/ProductStoreWorker.java.patch - - - jacopo - 2004-03-02 05:13:49 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=13) -Patch for ProductStoreWorker.java in UOF - - - - ajzeneski - 2004-03-18 12:02:10 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-08-06 15:26:31 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-06 15:26:31 - resolution - Resolution - - FIXED - - - - 47 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040323221326 - Product - jacopo - not determined - PATCH - 2004-03-02 06:06:51 - issues@ofbiz - - - - All - Facility -> Shipment: patch for JavaScript error introduced during i18n process. - - - jacopo - 2004-03-02 06:06:51 - Facility -> Shipment: patch for JavaScript error introduced during i18n process. - - - jacopo - 2004-03-02 06:07:51 - Created an attachment (id=14) -Patch for AddItemsFromOrder.ftl file in UOF - - - - ajzeneski - 2004-03-08 17:42:45 - reassigned - - - jacopo - 2004-03-23 22:13:26 - This bug has been fixed by the code for the new feature regarding shipment -plans. - - - text/plain - 14 - 2004-03-02 06:07:51 - Patch for AddItemsFromOrder.ftl file in UOF - 1 - AddItemsFromOrder.ftl.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/14/AddItemsFromOrder.ftl.patch - - - jacopo - 2004-03-02 06:07:51 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=14) -Patch for AddItemsFromOrder.ftl file in UOF - - - - ajzeneski - 2004-03-08 17:42:45 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-03-18 12:02:18 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2004-03-23 22:13:26 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-03-23 22:13:26 - resolution - Resolution - - FIXED - - - - 48 - NEW - P2 - - Components - CVS - All - issues@ofbiz - 20040318120228 - Product - jacopo - not determined - DEFECT - 2004-03-02 06:28:37 - issues@ofbiz - - - - All - Facility -> Shipment -> Items: delete shipment item link returns a constraint violation error. - - - jacopo - 2004-03-02 06:28:37 - Facility -> Shipment -> Items: delete shipment item link returns a constraint -violation error: - -The following errors occurred: -ERROR: Could not complete the Delete ShipmentItem process [problem removing the -lookedUpValue value: Exception while deleting the following entity: -[GenericEntity:ShipmentItem][shipmentId,10010(java.lang.String)] -[shipmentItemSeqId,00001(java.lang.String)] (SQL Exception while executing the -following:DELETE FROM SHIPMENT_ITEM WHERE SHIPMENT_ID=? AND -SHIPMENT_ITEM_SEQ_ID=? (Integrity constraint violation ITEM_ISS_SHITM table: -ITEM_ISSUANCE in statement [DELETE FROM SHIPMENT_ITEM WHERE SHIPMENT_ID=? AND -SHIPMENT_ITEM_SEQ_ID=?]))] - -In my opinion, the delete shipment item link should perform something like this -(instead of barely trying to remove the ShipmentItem entry): it should remove -the item issuances, recreate the reservations and then remove the shipment item. - - - ajzeneski - 2004-03-18 12:02:28 - version - Version - Pre3.0.0 - CVS - - - - 49 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040528001027 - Product - jacopo - not determined - PATCH - 2004-03-03 03:11:18 - issues@ofbiz - - - - All - Facility -> Receive PO: at now it's possible to receive multiple times the same shipment items. This is a partial patch for this problem. - - - jacopo - 2004-03-03 03:11:18 - Facility -> Receive PO: at now it's possible to receive multiple times the same -shipment items. This is a partial patch for this problem. With the attached -patch the shipment already delivered (or cancelled) are not shown (and so the -user cannot receive them again). -In order to completely fix this issue the best solution is, in my opinion, to -automatically update the shipment status to "delivered" when the user receives -an item: this could be done modifying the service -group "receiveInventoryProduct" by adding to it the "updateShipment" service -(to update the shipment status). However I'm going to add this comments to a -new "DEFECT" issue. - - - jacopo - 2004-03-03 03:12:11 - Created an attachment (id=15) -Patch for file receiveInventory.bsh in UOF. - - - - jonesde - 2004-05-28 00:10:27 - This is now in CVS, thanks for sending it over Jacopo. - - - text/plain - 15 - 2004-03-03 03:12:11 - Patch for file receiveInventory.bsh in UOF. - 1 - receiveInventory.bsh.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/15/receiveInventory.bsh.patch - - - jacopo - 2004-03-03 03:12:11 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=15) -Patch for file receiveInventory.bsh in UOF. - - - - ajzeneski - 2004-03-18 12:02:37 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-05-28 00:10:27 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-28 00:10:27 - resolution - Resolution - - FIXED - - - - 50 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040528000924 - Product - jacopo - not determined - DEFECT - 2004-03-03 03:15:23 - issues@ofbiz - - - - All - Facility -> Receive PO: at now it's possible to receive multiple times the same shipment items. - - - jacopo - 2004-03-03 03:15:24 - Facility -> Receive PO: at now it's possible to receive multiple times the same -shipment items. -This problem was partially fixed by the patch attached to issue #49. -With that patch the shipment already delivered (or cancelled) are not shown -(and so the user cannot receive them again). -In order to completely fix this issue the best solution is, in my opinion, to -automatically update the shipment status to "delivered" when the user receives -an item: this could be done modifying the service -group "receiveInventoryProduct" by adding to it the "updateShipment" service -(to update the shipment status). However I'm going to add this comments to a -new "DEFECT" issue. - - - jonesde - 2004-05-28 00:09:24 - The patch is in, now just need to update the shipment status as mentioned in the description. - - - ajzeneski - 2004-03-18 12:02:49 - version - Version - Pre3.0.0 - CVS - - - - 51 - RESOLVED - P3 - REMIND - Base - CVS - All - issues@ofbiz - 20040811004716 - Startup - jacopo - not determined - DEFECT - 2004-03-03 06:37:30 - issues@ofbiz - - - - All - Several SapDB error messages are generated at startup when entities are created. - - - jacopo - 2004-03-03 06:37:30 - Several SapDB error messages are generated at startup when entities are created. -The messages appear during the indices' generation phase, not for all entities -(maybe 5-10%); here is an example: - -147042[ DatabaseUtil.java:319:ERROR] Could not create foreign key indices -for entity "EftAccount": SQL Exception while executing the following: -CREATE INDEX EFTACCT_PMETH ON EFT_ACCOUNT (PAYMENT_METHOD_ID) -Error was: com.sap.dbtech.jdbc.exceptions.DatabaseException: [-7055] (at 44): -Column(s) already indexed:EFTACCT_PMETH -SQL Exception while executing the following: -CREATE INDEX EFTACCT_PADDR ON EFT_ACCOUNT (CONTACT_MECH_ID) -Error was: com.sap.dbtech.jdbc.exceptions.DatabaseException: [-7055] (at 44): -Column(s) already indexed:EFTACCT_PADDR - - - jacopo - 2004-08-11 00:47:16 - I've created a new issue (OFBIZ-1) for this in Jira; in it you will find a lot -of details. - - - - ajzeneski - 2004-03-18 12:03:00 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2004-08-11 00:47:16 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-08-11 00:47:16 - resolution - Resolution - - REMIND - - - - 52 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040308121509 - Order - jacopo - not determined - DEFECT - 2004-03-04 03:14:08 - issues@ofbiz - - - - All - Billing accounts selectable by users during order entry are not correctly filtered out. - - - jacopo - 2004-03-04 03:14:08 - Billing accounts selectable by users as payment methods during order entry are -not correctly filtered out: removed billing accounts are also shown (i.e. -billing accounts with thru date < now). - - - ajzeneski - 2004-03-08 12:15:09 - Billing accounts are now filtered by date so expired accounts no longer show on order manager order -entry and the ecommerce checkout pages - - - ajzeneski - 2004-03-08 12:15:09 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-03-08 12:15:09 - resolution - Resolution - - FIXED - - - ajzeneski - 2004-03-08 12:15:09 - version - Version - Pre3.0.0 - CVS - - - - 53 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040528010450 - Product - jacopo - not determined - DEFECT - 2004-03-05 06:01:05 - issues@ofbiz - - - - All - In Shipment: it's possible to issue 0 quantities from AddItemsFormOrder page. - - - jacopo - 2004-03-05 06:01:05 - In Shipment: it's possible to issue 0 quantities from AddItemsFormOrder page -(an ItemIssuance record is created with 0 quantity). -I think this should be avoided by submitting only quantities > 0. - - - jonesde - 2004-05-28 01:04:50 - Now checks to see if quantity is empty or 0 when issuing OIIRs to the shipment. - - - ajzeneski - 2004-03-18 12:03:13 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-05-28 01:04:50 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-28 01:04:50 - resolution - Resolution - - FIXED - - - - 54 - RESOLVED - P1 - FIXED - Components - CVS - All - issues@ofbiz - 20040630124239 - Product - jacopo - not determined - DEFECT - 2004-03-05 06:20:02 - issues@ofbiz - - - - All - In Shipment: if you enter a non numeric value (such as null quantity) in the issue field the program returns a bad error. - - - jacopo - 2004-03-05 06:20:02 - In Shipment: if you enter a non numeric value (such as null quantity) in the -issue field the program returns a bad error. -See also issue#53. -I'm running SapDB and after this error I need to restart OFBiz because in every -page I receive SQL errors like the following: - -Target exception: org.ofbiz.entity.GenericDataSourceException: SQL Exception -occurred on commit (Cannot commit a transactional connection: See JDBC 2.0 -Optional Package Specification section 7.1 (p25)) -BSF info: ..\ofbiz\components\content\webapp\content\WEB- -INF\actions\includes\envsetup.bsh at line: 0 column: 0) - - - ajzeneski - 2004-06-30 12:42:39 - Applied patch which fixes a bug in the service multi event handler - - - ajzeneski - 2004-03-18 12:03:23 - version - Version - Pre3.0.0 - CVS - - - ajzeneski - 2004-06-30 12:42:39 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 12:42:39 - resolution - Resolution - - FIXED - - - - 55 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040323221851 - Product - jacopo - not determined - DEFECT - 2004-03-05 06:25:34 - issues@ofbiz - - - - All - In shipment, it's possible to issue to shipment items with negative reservations (atp < 0); as a consequence of this, also the inventory items' quantity on hand can be negative. - - - jacopo - 2004-03-05 06:25:34 - I've noticed that, in shipment, it's possible to issue to shipment items with -negative reservations (atp < 0); as a consequence of this, also the inventory -items' quantity on hand can be negative. -In my opinion, in this situation at least a warning message should be -provided. - - - jacopo - 2004-03-23 22:18:51 - In "Order Items" page a new column has been added that tells users if they are -issuing negative reservations and the default issuance value is also -decremented by this quantity. -However is still possible to override this value and force an issuance for a -negative reservation. - - - - - ajzeneski - 2004-03-18 12:03:32 - version - Version - Pre3.0.0 - CVS - - - jacopo - 2004-03-23 22:18:51 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-03-23 22:18:51 - resolution - Resolution - - FIXED - - - - 56 - RESOLVED - P3 - WONTFIX - Components - CVS - PC - issues@ofbiz - 20040308173638 - Party - vivalinux - not determined - PATCH - 2004-03-08 14:07:32 - issues@ofbiz - - http://<ofbiz_root_url>/partymgr/control/findparty - - All - Selecting "Show All Records" displays all names as "(Not selected)" - - - vivalinux - 2004-03-08 14:07:32 - The findparty.bsh constructs a dynamic view tailored to the search fields -submited by the lookupparty form. Since selecting all does not give a hint about -which fields the client is interested in, the findparty.bsh fails to include any -of the name (firstName, lastName, groupName) fields. - -The can be corrected with the patch that follows or handling the select all -records as yet another case. I think, I'll side with simplicity, and sacrify -efficiency .... - -Hope this helps. - - -Index: components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh -=================================================================== -RCS file: -/cvs/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh,v -retrieving revision 1.13 -diff -u -r1.13 findparty.bsh ---- components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh 27 Jan -2004 19:44:36 -0000 1.13 -+++ components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh 8 Mar -2004 22:06:24 -0000 -@@ -100,8 +100,15 @@ - - // default view settings - dynamicView.addMemberEntity("PT", "Party"); -+ dynamicView.addMemberEntity("PG", "PartyGroup"); -+ dynamicView.addMemberEntity("PP", "Person"); - dynamicView.addAlias("PT", "partyId"); - dynamicView.addAlias("PT", "partyTypeId"); -+ dynamicView.addAlias("PG", "groupName"); -+ dynamicView.addAlias("PP", "firstName"); -+ dynamicView.addAlias("PP", "lastName"); -+ dynamicView.addViewLink("PT","PG",true,UtilMisc.toList(new -ModelKeyMap("partyId", "partyId"))); -+ dynamicView.addViewLink("PT","PP",true,UtilMisc.toList(new -ModelKeyMap("partyId", "partyId"))); - dynamicView.addRelation("one-nofk", "", "PartyType", -ModelKeyMap.makeKeyMapList("partyTypeId")); - dynamicView.addRelation("many", "", "UserLogin", -ModelKeyMap.makeKeyMapList("partyId")); - -@@ -143,11 +150,6 @@ - if (groupName != null && groupName.length() > 0) { - paramList = paramList + "&groupName=" + groupName; - -- // modify the dynamic view -- dynamicView.addMemberEntity("PG", "PartyGroup"); -- dynamicView.addAlias("PG", "groupName"); -- dynamicView.addViewLink("PT", "PG", Boolean.FALSE, -ModelKeyMap.makeKeyMapList("partyId")); -- - // add the expr - andExprs.add(new EntityExpr("groupName", true, EntityOperator.LIKE, -"%"+groupName+"%", true)); - } -@@ -160,14 +162,6 @@ - firstName = request.getParameter("firstName"); - lastName = request.getParameter("lastName"); - -- // modify the dynamic view -- if ((firstName != null && firstName.length() > 0) || (lastName != null && -lastName.length() > 0)) { -- dynamicView.addMemberEntity("PE", "Person"); -- dynamicView.addAlias("PE", "firstName"); -- dynamicView.addAlias("PE", "lastName"); -- dynamicView.addViewLink("PT", "PE", Boolean.FALSE, -ModelKeyMap.makeKeyMapList("partyId")); -- } -- - // filter on firstName - if (firstName != null && firstName.length() > 0) { - paramList = paramList + "&firstName=" + firstName; -@@ -319,6 +313,12 @@ - List orderBy = new ArrayList(); - fieldsToSelect.add("partyId"); - fieldsToSelect.add("partyTypeId"); -+ fieldsToSelect.add("firstName"); -+ fieldsToSelect.add("lastName"); -+ fieldsToSelect.add("groupName"); -+ orderBy.add("-partyTypeId"); -+ orderBy.add("lastName"); -+ orderBy.add("groupName"); - - // UserLogin - if (userLoginId != null && userLoginId.length() > 0) { -@@ -327,14 +327,11 @@ - - // Person - if ((firstName != null && firstName.length() > 0) || (lastName != null -&& lastName.length() > 0)) { -- fieldsToSelect.add("firstName"); -- fieldsToSelect.add("lastName"); - orderBy.add("lastName"); - orderBy.add("firstName"); - } - // PartyGroup - if (groupName != null && groupName.length() > 0) { -- fieldsToSelect.add("groupName"); - orderBy.add("groupName"); - } - // RoleType -Index: components/party/webapp/partymgr/party/findparty.ftl -=================================================================== -RCS file: /cvs/ofbiz/components/party/webapp/partymgr/party/findparty.ftl,v -retrieving revision 1.10 -diff -u -r1.10 findparty.ftl ---- components/party/webapp/partymgr/party/findparty.ftl 1 Mar 2004 14:43:27 --0000 1.10 -+++ components/party/webapp/partymgr/party/findparty.ftl 8 Mar 2004 22:06:24 -0000 -@@ -212,13 +212,12 @@ - </table> - <input type="image" src="/images/spacer.gif" -onClick="javascript:document.lookupparty.submit();"> - </form> --<#if requestParameters.hideFields?default("N") != "Y"> - <script language="JavaScript"> - <!--// - document.lookupparty.partyId.focus(); - //--> - </script> --</#if> -+ - <#if partyList?exists> - <br> - <table border=0 width='100%' cellspacing='0' cellpadding='0' -class='boxoutside'> -@@ -292,21 +291,13 @@ - </td> - <td> - <div class="tabletext"> -- <#if partyRow.containsKey("lastName")> - <#if partyRow.lastName?has_content> - ${partyRow.lastName}<#if -partyRow.firstName?has_content>, ${partyRow.firstName}</#if> -- <#else> -- (No Name Found) -- </#if> -- <#elseif partyRow.containsKey("groupName")> -- <#if partyRow.groupName?has_content> -+ <#elseif partyRow.groupName?has_content> - ${partyRow.groupName} - <#else> -- (No Name Found) -+ (Not Selected) - </#if> -- <#else> -- (Not Selected) -- </#if> - </td> - <#if extInfo?default("") == "P"> - <td><div -class="tabletext">${partyRow.postalCode?if_exists}</div></td> - - - ajzeneski - 2004-03-08 17:36:38 - This page has been changed from using the left joins in the dynamic view. Using left joins performs too -poorly for actual use. This patch has been rejected; a new task will be opened for fixing the problem of -the name not being displayed. - - - ajzeneski - 2004-03-08 17:36:38 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-03-08 17:36:38 - resolution - Resolution - - WONTFIX - - - - 57 - NEW - P4 - - Components - CVS - All - ajzeneski - 20040308174641 - Party - ajzeneski - not determined - DEFECT - 2004-03-08 17:36:18 - issues@ofbiz - - - - All - Find Party - Show all does not show name - - - ajzeneski - 2004-03-08 17:36:18 - The name is not displayed when selecting show all in the party manager. - - - ajzeneski - 2004-03-08 17:46:41 - reassigned - - - ajzeneski - 2004-03-08 17:46:41 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - - 58 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040308185722 - Content - vivalinux - not determined - ENHANCEMENT - 2004-03-08 18:57:22 - issues@ofbiz - - - - All - Inherited hidden fields overide child fields when they have use-when - - - vivalinux - 2004-03-08 18:57:22 - In working with inherited forms I noticed that hidden fields are hard -to override if the overriding field has a use-when attribute: - - Since the HtmlFormRenderer gives precedence to hidden fields, and new -fields with "use-when" are only placed in front of existing fields -but not merged with, the resulting behavior is that hidden fields of -parent forms always get rendered even when the use-when condition is -true. This causes the hidden field to take precedence over the user -input when the form is submitted. - - Here is a posible solution: - -Index: components/content/src/org/ofbiz/content/widget/form/ModelForm.java -=================================================================== -RCS file: -/usr/local/cvsrepos/newriverbiz/components/content/src/org/ofbiz/content/widget/form/ModelForm.java,v -retrieving revision 1.1.1.4 -diff -u -r1.1.1.4 ModelForm.java ---- components/content/src/org/ofbiz/content/widget/form/ModelForm.java -2004/01/08 14:19:55 1.1.1.4 -+++ components/content/src/org/ofbiz/content/widget/form/ModelForm.java -2004/01/29 20:23:20 -@@ -277,15 +277,25 @@ - public ModelFormField addUpdateField(ModelFormField modelFormField) { - if (!modelFormField.isUseWhenEmpty()) { - // is a conditional field, add to the List but don't worry about -the Map -- //for adding to list, see if there is another field with that name -in the list and if so, put it before that one -+ //for adding to list, see if there is another field with that name -+ //in the list and if so, put it before that one - boolean inserted = false; - for (int i = 0; i < this.fieldList.size(); i++) { - ModelFormField curField = (ModelFormField) this.fieldList.get(i); -+ // BUG FIX: parent hidden fields are left and rendered even when they -+ // are overriden with fields that have a use-when - if (curField.getName() != null && -curField.getName().equals(modelFormField.getName())) { -- this.fieldList.add(i, modelFormField); -- inserted = true; -- break; -+ if ((curField.getFieldInfo().getFieldType() != -ModelFormField.FieldInfo.HIDDEN) && -+ (curField.getFieldInfo().getFieldType() != ModelFormField.FieldInfo.IGNORED)) { -+ this.fieldList.add(i, modelFormField); -+ inserted = true; -+ break; -+ } else { -+ curField.mergeOverrideModelFormField(modelFormField); -+ break; -+ } - } -+ //End of BUG fix - } - if (!inserted) { - this.fieldList.add(modelFormField); - - - - 59 - NEW - P1 - - Components - CVS - All - issues@ofbiz - 20040318120354 - Workflow - mbennani - not determined - DEFECT - 2004-03-09 06:47:17 - issues@ofbiz - - - - All - Serious Problem in Sub-flow Implementation: in-Memory Requester Used!! - - - mbennani - 2004-03-09 06:47:17 - I am running ofbiz almost v.3 :-) (image from late 2003 from cvs). -(subflow implementation did not change since 1.2 anyways, I believe) - -Quick Description: ------------------- -Subflows are using the in-memory requester object which -does not persist over server re-starts. This is serious one guys. - -More Description (Scenario): ---------------------------- -I have a main process with 3 steps(step1,step2-subflow,step3). A subflow -process being the second step. This second step calls another process that I -call sub. sub has 2 simple steps (substep1,substep2). - -Now, in normal time (i.e no server restart), it all works fine and my main -process runs fine, calls the subflow, subflow runs, the call returns and my -step3 of the main process runs successfully and main completes fine. - -The problem arises when say I run step 1 of main process, subflow gets -initiated, substep1 is executed, and before substep2 is executed, I stop the -server (faking a server problem..., connection lost...whatever). -When I restart the server, the subflow resumes at substep2 which executes fine, -and eventually completes the subflow process. But, step-subflow activity in the -workeffort table still shows WF_RUNNING. Therefore, my main process is hanging -there and will never move along. The waitForResult() is not executed anymore -after server restart. -This is happening in WfActivitySubFlowImplementation on runService. - -Even More Details, code wise, if you want to look at it: -------------------------------------------------------- -In a normal scenario (no server stopped), the runService of -WfActivitySubFlowImplementation eventually calls the runSync in WorkflowEngine -and then waitForResult. I put a system out message in the waiter class and I -can see my message being displayed in the console forever ("waiting..."), until -the subflow process finishes. And that's ok, that's what we want. When the -subflow process finishes, the call is returned back to the runService in -WfActivitySubFlowImplementation() and the setComplete is called, which changes -the status of my step2-subflow activity in the main process to WF_COMPLETED to -advance the main process. It also calls setResults() to propagate the results -from the subflow up to the main process. - -BUT, now if I stop my server during that wait, and restart it the call never -reachs the setComplete nor the setResults, making therefore my main process -unusable anymore. - - - ajzeneski - 2004-03-18 12:03:54 - op_sys - OS/Version - Windows 2000 - All - - - ajzeneski - 2004-03-18 12:03:54 - version - Version - Pre3.0.0 - CVS - - - - 60 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040707152609 - Entity - doogie - not determined - ENHANCEMENT - 2004-03-09 07:09:04 - issues@ofbiz - - - - All - Replace simplistic caching with complex reverse dependency resolver - - - doogie - 2004-03-09 07:09:04 - This patch removes all simple caching from GenericDelegator, and replaces -it with a stand-alone class, that handles all entity cache management. It -uses new features in the entity model, that keeps track of view entities -that are referenced by regular entities. As entities are updated, all -cached lists of views or condition caches are cleared. - -With this patch applied, view entities can be cached, without worry that -they will become stale. Which then allows very complex views to be -created, that emulate complex code patterns, while still allowing for -caching. This can speed up code tremendously. - -Additionally, since cache clearing now works, it almost always makes more -sense to use the cache variation of the methods. - - - doogie - 2004-03-09 07:14:24 - Created an attachment (id=16) -The patch - - - - doogie - 2004-04-29 15:44:46 - This patch is on hold, until some other patches are committed. Some of them -need to have bugs filed, which I am working on. Plus, this patch needs to be -updated to the latest code base(not a big task, done locally). - - - doogie - 2004-07-07 15:26:09 - This is now in cvs. - - - text/plain - 16 - 2004-03-09 07:14:24 - The patch - 1 - EntityCache.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/16/EntityCache.patch - - - doogie - 2004-03-09 07:14:24 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=16) -The patch - - - - doogie - 2004-04-29 15:44:46 - issue_status - Status - NEW - STARTED - - - doogie - 2004-04-29 16:16:01 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-07-07 15:26:09 - issue_status - Status - STARTED - RESOLVED - - - doogie - 2004-07-07 15:26:09 - resolution - Resolution - - FIXED - - - - 61 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422222023 - Product - doogie - not determined - FEATURE - 2004-03-09 07:18:26 - issues@ofbiz - - - - All - Allow for easier extension of this class. - - - doogie - 2004-03-09 07:18:26 - This patch makes a protected writeValues() method, which allows sub-classes -to redirect the output to other places, as needed. - - - doogie - 2004-03-09 07:18:49 - Created an attachment (id=17) -The patch - - - - doogie - 2004-04-22 22:20:23 - Applied the patch. - - - text/plain - 17 - 2004-03-09 07:18:49 - The patch - 1 - EntitySaxReader-extension.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/17/EntitySaxReader-extension.patch - - - doogie - 2004-03-09 07:18:49 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=17) -The patch - - - - doogie - 2004-04-22 22:20:23 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:20:23 - resolution - Resolution - - FIXED - - - - 62 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422223418 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:34:07 - issues@ofbiz - - - - All - Allow for UPPER() and LOWER() sorting - - - doogie - 2004-03-09 07:34:07 - See $summary. - - - doogie - 2004-03-09 07:34:26 - Created an attachment (id=18) -The patch. - - - - doogie - 2004-04-22 22:34:18 - Applied patch. - - - text/plain - 18 - 2004-03-09 07:34:26 - The patch. - 1 - EntityUtil-UPPER_LOWER.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/18/EntityUtil-UPPER_LOWER.patch - - - doogie - 2004-03-09 07:34:26 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=18) -The patch. - - - - doogie - 2004-04-22 22:34:18 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:34:18 - resolution - Resolution - - FIXED - - - - 63 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040429160209 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:36:19 - issues@ofbiz - - - - All - Add support for turning off schemas completely - - - doogie - 2004-03-09 07:36:19 - See $summary. - - - doogie - 2004-03-09 07:36:42 - Created an attachment (id=19) -The patch - - - - doogie - 2004-04-29 16:02:09 - Applied this patch. - - - text/plain - 19 - 2004-03-09 07:36:42 - The patch - 1 - use-schemas.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/19/use-schemas.patch - - - doogie - 2004-03-09 07:36:42 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=19) -The patch - - - - doogie - 2004-04-29 16:02:09 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-29 16:02:09 - resolution - Resolution - - FIXED - - - - 64 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422222810 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:43:55 - issues@ofbiz - - - - All - Make the code look like the rest of the file. - - - doogie - 2004-03-09 07:43:55 - See $summary. - - - doogie - 2004-03-09 07:44:21 - Created an attachment (id=20) -The patch - - - - doogie - 2004-04-22 22:28:10 - Applied patch. - - - text/plain - 20 - 2004-03-09 07:44:21 - The patch - 1 - SqlJdbcUtil-Cast.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/20/SqlJdbcUtil-Cast.patch - - - doogie - 2004-03-09 07:44:21 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=20) -The patch - - - - doogie - 2004-04-22 22:28:10 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:28:10 - resolution - Resolution - - FIXED - - - - 65 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040429163146 - Entity - doogie - not determined - ENHANCEMENT - 2004-03-09 07:46:14 - issues@ofbiz - - - - All - Add java.util.Date support. - - - doogie - 2004-03-09 07:46:14 - See $summary. - - - doogie - 2004-03-09 07:46:39 - Created an attachment (id=21) -The patch - - - - doogie - 2004-04-29 16:31:46 - Applied the patch. - - - text/plain - 21 - 2004-03-09 07:46:39 - The patch - 1 - SqlJdbcUtil-Java_Util_Date.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/21/SqlJdbcUtil-Java_Util_Date.patch - - - doogie - 2004-03-09 07:46:39 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=21) -The patch - - - - doogie - 2004-04-29 16:16:03 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 16:31:45 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-29 16:31:45 - resolution - Resolution - - FIXED - - - - 66 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422221943 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:47:46 - issues@ofbiz - - - - All - Use UtilValidate.isNotEmpty. - - - doogie - 2004-03-09 07:47:46 - See $summary. - - - doogie - 2004-03-09 07:48:06 - Created an attachment (id=22) -The patch - - - - doogie - 2004-04-22 22:19:43 - Applied patch, which uses UtilValidate.isNotEmpty in SqlJdbcUtil. - - - text/plain - 22 - 2004-03-09 07:48:06 - The patch - 1 - SqlJdbcUtil-UtilValidate.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/22/SqlJdbcUtil-UtilValidate.patch - - - doogie - 2004-03-09 07:48:06 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=22) -The patch - - - - doogie - 2004-04-22 22:19:43 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:19:43 - resolution - Resolution - - FIXED - - - - 67 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040429161604 - Entity - doogie - not determined - ENHANCEMENT - 2004-03-09 07:49:20 - issues@ofbiz - - - - All - Add support for <constraint> on relations and views. - - - doogie - 2004-03-09 07:49:20 - When defining a view or relation, you can now constrain the returned -values to those that match an EntityCondition. This is really helpful -for complex views. - - - doogie - 2004-03-09 07:49:42 - Created an attachment (id=23) -The patch - - - - text/plain - 23 - 2004-03-09 07:49:42 - The patch - 1 - model-constraint.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/23/model-constraint.patch - - - doogie - 2004-03-09 07:49:42 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=23) -The patch - - - - doogie - 2004-04-29 16:16:04 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - - 68 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040423074926 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:51:20 - issues@ofbiz - - - - All - Use a NumberFormat for casting number objects to strings. - - - doogie - 2004-03-09 07:51:20 - See $summary. - - - doogie - 2004-03-09 07:51:40 - Created an attachment (id=24) -The patch - - - - doogie - 2004-04-23 07:49:26 - Applied patch. - - - text/plain - 24 - 2004-03-09 07:51:40 - The patch - 1 - GenericEntity-NumberFormat.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/24/GenericEntity-NumberFormat.patch - - - doogie - 2004-03-09 07:51:40 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=24) -The patch - - - - doogie - 2004-04-23 07:49:26 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-23 07:49:26 - resolution - Resolution - - FIXED - - - - 69 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040423075223 - Entity - doogie - not determined - FEATURE - 2004-03-09 07:52:20 - issues@ofbiz - - - - All - Add addToXmlElement method - - - doogie - 2004-03-09 07:52:20 - See $summary. - - - doogie - 2004-03-09 07:52:42 - Created an attachment (id=25) -The patch - - - - doogie - 2004-04-23 07:52:23 - Applied patch. - - - text/plain - 25 - 2004-03-09 07:52:42 - The patch - 1 - GenericEntity-addToXmlElement.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/25/GenericEntity-addToXmlElement.patch - - - doogie - 2004-03-09 07:52:42 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=25) -The patch - - - - doogie - 2004-04-23 07:52:23 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-23 07:52:23 - resolution - Resolution - - FIXED - - - - 70 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422221512 - Entity - doogie - not determined - DEFECT - 2004-03-09 07:54:40 - issues@ofbiz - - - - All - Fix modelEntity dereferencing - - - doogie - 2004-03-09 07:54:40 - When GenericEntities have been deserialized, modelEntity will be null. -getModelEntity() should be called, to repopulate it. - - - doogie - 2004-03-09 07:54:57 - Created an attachment (id=26) -The patch - - - - doogie - 2004-04-22 22:15:12 - Applied patch, plus fixed it in a few other areas. - - - text/plain - 26 - 2004-03-09 07:54:57 - The patch - 1 - GenericEntity-getModelEntity.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/26/GenericEntity-getModelEntity.patch - - - doogie - 2004-03-09 07:54:57 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=26) -The patch - - - - doogie - 2004-04-22 22:15:12 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:15:12 - resolution - Resolution - - FIXED - - - - 71 - NEW - P4 - - Components - CVS - All - issues@ofbiz - 20040501214447 - Content - doogie - not determined - ENHANCEMENT - 2004-03-09 07:56:46 - issues@ofbiz - - - - All - Factor out the code - - - doogie - 2004-03-09 07:56:46 - See $summary. - - - doogie - 2004-03-09 07:57:40 - Created an attachment (id=27) -The patch. - - - - doogie - 2004-04-29 19:57:51 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:06:43 - Not adding this patch, breaks the Server Stats Since Start page in WebTools, and not totally sure the -cleanup is worth it yet. - - - doogie - 2004-05-01 21:44:47 - I'll fix that page then, and submit a revised patch. - - - text/plain - 27 - 2004-03-09 07:57:40 - The patch. - 1 - ServerHitBin-factor.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/27/ServerHitBin-factor.patch - - - doogie - 2004-03-09 07:57:40 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=27) -The patch. - - - - doogie - 2004-04-29 16:16:02 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 19:57:51 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:07:05 - priority - Priority - P2 - P4 - - - - 72 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422223139 - Entity - doogie - not determined - FEATURE - 2004-03-09 08:04:05 - issues@ofbiz - - - - All - Add a matches(condition) helper method. - - - doogie - 2004-03-09 08:04:05 - See $summary. - - - doogie - 2004-03-09 08:04:31 - Created an attachment (id=28) -The patch - - - - doogie - 2004-04-22 22:31:39 - Applied patch. - - - text/plain - 28 - 2004-03-09 08:04:31 - The patch - 1 - GenericEntity-matches-condition.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/28/GenericEntity-matches-condition.patch - - - doogie - 2004-03-09 08:04:31 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=28) -The patch - - - - doogie - 2004-04-22 22:31:39 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:31:39 - resolution - Resolution - - FIXED - - - - 73 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422221835 - Entity - doogie - not determined - DEFECT - 2004-03-09 08:05:30 - issues@ofbiz - - - - All - Fix deserializing of these objects. - - - doogie - 2004-03-09 08:05:30 - See $summary. - - - doogie - 2004-03-09 08:05:51 - Created an attachment (id=29) -The patch. - - - - doogie - 2004-04-22 22:18:35 - Applied patch, which set delegatorName to "default" when it is null. - - - text/plain - 29 - 2004-03-09 08:05:50 - The patch. - 1 - GenericDelegator-fix-serialization.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/29/GenericDelegator-fix-serialization.patch - - - doogie - 2004-03-09 08:05:51 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=29) -The patch. - - - - doogie - 2004-04-22 22:18:35 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:18:35 - resolution - Resolution - - FIXED - - - - 74 - NEW - P2 - - Components - CVS - All - issues@ofbiz - 20040429200642 - Order - doogie - not determined - ENHANCEMENT - 2004-03-09 08:08:00 - issues@ofbiz - - - - All - Fix all fetchers of shopping cart to use a static method - - - doogie - 2004-03-09 08:08:00 - This patch fixes all code that fetches the ShoppingCart from the session, -to use a static method instead. It also adds the beginning of named -ShoppingCart support. - - - doogie - 2004-03-09 08:08:22 - Created an attachment (id=30) -The patch. - - - - doogie - 2004-04-29 19:57:51 - Changing priority, so that someone else can see the ones I want applied next. - - - doogie - 2004-04-29 20:05:04 - This patch depends on EntityCache, which isn't ready for inclussion yet, -reducing priority. - - - doogie - 2004-04-29 20:06:42 - Oops, modified wrong issue. - - - text/plain - 30 - 2004-03-09 08:08:22 - The patch. - 1 - ShoppingCart-getShoppingCart.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/30/ShoppingCart-getShoppingCart.patch - - - doogie - 2004-03-09 08:08:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=30) -The patch. - - - - doogie - 2004-04-29 16:16:03 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 19:57:51 - priority - Priority - P3 - P2 - - - doogie - 2004-04-29 20:05:04 - priority - Priority - P2 - P3 - - - doogie - 2004-04-29 20:06:41 - priority - Priority - P3 - P2 - - - - 75 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429171641 - Base - doogie - not determined - ENHANCEMENT - 2004-03-09 08:09:21 - issues@ofbiz - - - - All - Allow code to detect whether a cacheline has expired. - - - doogie - 2004-03-09 08:09:21 - See $summary. - - - doogie - 2004-03-09 08:09:41 - Created an attachment (id=31) -The patch - - - - doogie - 2004-04-29 16:57:47 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:16:41 - Now in CVS, thanks Adam. - - - text/plain - 31 - 2004-03-09 08:09:41 - The patch - 1 - UtilCache-hasExpired.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/31/UtilCache-hasExpired.patch - - - doogie - 2004-03-09 08:09:41 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=31) -The patch - - - - doogie - 2004-04-29 16:16:04 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 16:57:47 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:16:41 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:16:41 - resolution - Resolution - - FIXED - - - - 76 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429171643 - Base - doogie - not determined - ENHANCEMENT - 2004-03-09 08:10:31 - issues@ofbiz - - - - All - Allow code to get the values stored in the cache. - - - doogie - 2004-03-09 08:10:31 - See $summary. - - - doogie - 2004-03-09 08:10:58 - Created an attachment (id=32) -The patch - - - - doogie - 2004-04-29 16:57:47 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:16:43 - Now in CVS, thanks Adam. - - - text/plain - 32 - 2004-03-09 08:10:58 - The patch - 1 - UtilCache-getCacheLineValues.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/32/UtilCache-getCacheLineValues.patch - - - doogie - 2004-03-09 08:10:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=32) -The patch - - - - doogie - 2004-04-29 16:16:05 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 16:57:47 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:16:43 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:16:43 - resolution - Resolution - - FIXED - - - - 77 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429171648 - Base - doogie - not determined - ENHANCEMENT - 2004-03-09 08:11:52 - issues@ofbiz - - - - All - Allow registering of listeners for the various events on caches. - - - doogie - 2004-03-09 08:11:52 - See $summary. - - - doogie - 2004-03-09 08:12:13 - Created an attachment (id=33) -The patch - - - - doogie - 2004-04-29 16:57:48 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:16:48 - Now in CVS, thanks Adam. - - - text/plain - 33 - 2004-03-09 08:12:12 - The patch - 1 - UtilCache-listeners.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/33/UtilCache-listeners.patch - - - doogie - 2004-03-09 08:12:13 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=33) -The patch - - - - doogie - 2004-04-29 16:16:05 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 16:57:48 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:16:48 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:16:48 - resolution - Resolution - - FIXED - - - - 78 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040423080723 - Entity - doogie - not determined - FEATURE - 2004-03-09 08:19:59 - issues@ofbiz - - - - All - Some additional methods to manipulate the embedded cache. - - - doogie - 2004-03-09 08:19:59 - See $summary. - - - doogie - 2004-03-09 08:20:20 - Created an attachment (id=34) -The patch - - - - doogie - 2004-04-23 08:07:23 - Add some more methods to GenericValue to manipulate the cache. - - - text/plain - 34 - 2004-03-09 08:20:20 - The patch - 1 - GenericValue-EmbeddedCache.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/34/GenericValue-EmbeddedCache.patch - - - doogie - 2004-03-09 08:20:20 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=34) -The patch - - - - doogie - 2004-04-23 08:07:23 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-23 08:07:23 - resolution - Resolution - - FIXED - - - - 79 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040429200727 - Product - doogie - not determined - ENHANCEMENT - 2004-03-09 08:21:27 - issues@ofbiz - - - - All - methods to fetch the list of available catalogs. - - - doogie - 2004-03-09 08:21:27 - See $summary. - - - doogie - 2004-03-09 08:21:46 - Created an attachment (id=35) -The patch - - - - doogie - 2004-04-29 19:57:52 - Changing priority, so that someone else can see the ones I want applied next. - - - doogie - 2004-04-29 20:07:27 - This patch depends on EntityCache, which isn't ready for inclussion yet, -reducing priority. - - - text/plain - 35 - 2004-03-09 08:21:46 - The patch - 1 - CatalogWorker-getCatalogsAvailable.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/35/CatalogWorker-getCatalogsAvailable.patch - - - doogie - 2004-03-09 08:21:46 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=35) -The patch - - - - doogie - 2004-04-29 16:16:05 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 19:57:52 - priority - Priority - P3 - P2 - - - doogie - 2004-04-29 20:07:27 - priority - Priority - P2 - P3 - - - - 80 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040422222535 - Entity - doogie - not determined - DEFECT - 2004-03-09 08:22:53 - issues@ofbiz - - - - All - Create a separate makeIndexName helper method. - - - doogie - 2004-03-09 08:22:53 - This patch also truncates the index name, based on the clipping value. - - - doogie - 2004-03-09 08:23:14 - Created an attachment (id=36) -The patch - - - - doogie - 2004-04-22 22:25:35 - Applied patch. - - - text/plain - 36 - 2004-03-09 08:23:14 - The patch - 1 - DatabaseUtil-makeIndexName.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/36/DatabaseUtil-makeIndexName.patch - - - doogie - 2004-03-09 08:23:14 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=36) -The patch - - - - doogie - 2004-04-22 22:25:35 - issue_status - Status - NEW - RESOLVED - - - doogie - 2004-04-22 22:25:35 - resolution - Resolution - - FIXED - - - - 81 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429172408 - Base - doogie - not determined - ENHANCEMENT - 2004-03-09 08:23:52 - issues@ofbiz - - - - All - Add support for writing elements. - - - doogie - 2004-03-09 08:23:52 - See $summary. - - - doogie - 2004-03-09 08:24:13 - Created an attachment (id=37) -The patch - - - - doogie - 2004-04-29 16:57:47 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:24:08 - Now in CVS, thanks Adam. - - - text/plain - 37 - 2004-03-09 08:24:12 - The patch - 1 - UtilXml-writeElement.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/37/UtilXml-writeElement.patch - - - doogie - 2004-03-09 08:24:13 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=37) -The patch - - - - doogie - 2004-04-29 16:16:03 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 16:57:47 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:24:08 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:24:08 - resolution - Resolution - - FIXED - - - - 82 - NEW - P2 - - Components - CVS - All - issues@ofbiz - 20040429195752 - Party - doogie - not determined - ENHANCEMENT - 2004-03-09 08:25:06 - issues@ofbiz - - - - All - Services/etc for manipulating PartyAttributes. - - - doogie - 2004-03-09 08:25:06 - See $summary. - - - doogie - 2004-03-09 08:25:27 - Created an attachment (id=38) -The patch - - - - doogie - 2004-04-29 19:57:52 - Changing priority, so that someone else can see the ones I want applied next. - - - text/plain - 38 - 2004-03-09 08:25:27 - The patch - 1 - PartyAttributes.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/38/PartyAttributes.patch - - - doogie - 2004-03-09 08:25:27 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=38) -The patch - - - - doogie - 2004-04-29 16:16:04 - issue_type - Issue Type - FEATURE - ENHANCEMENT - - - doogie - 2004-04-29 19:57:52 - priority - Priority - P3 - P2 - - - - 83 - NEW - P5 - - Components - CVS - All - issues@ofbiz - 20040309095844 - Content - jacopo - not determined - DEFECT - 2004-03-09 09:58:44 - issues@ofbiz - - - - All - Problems displaying the Euro symbol in order confirmation by email with MS Outlook - - - jacopo - 2004-03-09 09:58:44 - Problems displaying the Euro symbol in order confirmation by email with MS -Outlook: instead of the beautyful Euro symbol you see a '?'. -Ok, maybe I should create an issue to the Microsoft issue tracker... however -I've reported this for two reasons: -1) other users reported this some time ago in the mailing lists -2) maybe, in general, for the currency symbols in ftl templates we should use -the html entity references (i.e. &euro; for the Euro symbol): this will solve -all the display problems with virtually any client software. - - - - 84 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040309101202 - Product - jacopo - not determined - ENHANCEMENT - 2004-03-09 10:12:02 - issues@ofbiz - - - - All - In shipment, it's possible to issue to shipment items with negative reservations (atp < 0); as a consequence of this, also the inventory items' quantity on hand can be negative. - - - jacopo - 2004-03-09 10:12:02 - In shipment, it's possible to issue to shipment items with negative -reservations (atp < 0); as a consequence of this, also the inventory items' -quantity on hand can be negative. -In fact, when the issuance is performed, the (negative) reservation is deleted -and a new issuance is created and the inventory's qoh is decremented. -In my opinion, in this situation a warning message should be provided. -Also, David Jones has suggested to create a report of all negative QOH -InventoryItems and add a link for each one to get a physical inventory variance -started. - - - - 85 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040730212116 - Party - jonesde - not determined - ENHANCEMENT - 2004-03-11 08:14:35 - issues@ofbiz - - - - All - The showvisits page in the Party Manager is very slow when there are many visits - - - jonesde - 2004-03-11 08:14:35 - The showvisits page is not coded to efficiently display a subset of the visits when there are many active. -When there are tens of thousands the current code doesn't work very efficiently. - - - ajzeneski - 2004-07-30 21:21:16 - The code for visit display utilized the entity list iterator and pulls a subset for each page. The query -fields are indexed (as of now) so depending on the JDBC driver being used this should be quite efficient. -If you experience further problems, send more information to the DEV list. - - - ajzeneski - 2004-03-18 12:04:04 - version - Version - Pre3.0.0 - CVS - - - ajzeneski - 2004-07-30 21:21:16 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 21:21:16 - resolution - Resolution - - INVALID - - - - 86 - NEW - P4 - - Components - CVS - All - issues@ofbiz - 20040312164734 - Content - jonesde - not determined - PATCH - 2004-03-12 16:45:26 - issues@ofbiz - - - - All - Error Message (esp Map) Improvements from Quake Wang - - - jonesde - 2004-03-12 16:45:26 - A description from an email from Quake: - -================================ -David, - The attachment is my patch. The main changes are: - -1. Now the event and the service invoke will use the same message fields in SimpleMethod. -2. Add the errorMessageMap and successMessageMap for the message handling - - I only change the envsetup.bsh and errormsg.ftl in the ecommerce component, please use the -ecommerce to review the backward compatiblity. - -Regards -Quake -============================= - - - jonesde - 2004-03-12 16:47:34 - Created an attachment (id=39) -Error Message patch from Quake Wang - - - - text/plain - 39 - 2004-03-12 16:47:34 - Error Message patch from Quake Wang - 1 - quake.errormessages.patch - 3 - jonesde - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/39/quake.errormessages.patch - - - jonesde - 2004-03-12 16:47:34 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=39) -Error Message patch from Quake Wang - - - - - 87 - NEW - P3 - - Base - CVS - All - issues@ofbiz - 20040312165745 - Base - doogie - not determined - DEFECT - 2004-03-12 16:56:52 - issues@ofbiz - - - - All - bsf.jar in base is old - - - doogie - 2004-03-12 16:56:52 - bsf is no longer part of IBM. Instead, it has moved to jakarta. - -Attached patch changes imports, etc. It can't change the bsf.jar in -base/lib/scripting/, however. - - - doogie - 2004-03-12 16:57:45 - Created an attachment (id=40) -The patch. - - - - text/plain - 40 - 2004-03-12 16:57:45 - The patch. - 1 - IBM-Jakarta-BSF.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/40/IBM-Jakarta-BSF.patch - - - doogie - 2004-03-12 16:57:45 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=40) -The patch. - - - - - 88 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040312165737 - Order - jonesde - not determined - DEFECT - 2004-03-12 16:57:37 - issues@ofbiz - - - - All - Promotion/other adjustments not as expected when cancelling order items - - - jonesde - 2004-03-12 16:57:37 - When order items are cancelled some order level adjustments are not changed, like order level -promotion adjustments. Because of this order totals can easily become negative. The question is what -to do about it? - -Andy wrote this at one point in an email: - -============================ -I was aware of this; the only order level adjustments which are currently re-calculated are shipping and -tax, order level promotions are not done at this time so we will need to add this in. In order to do this -promotion evaluation will need to be able to be done without a shopping cart. -============================ - -I'm not sure I totally agree with this, I think short of that it would still be good to at least pro-rate these -order adjustments like we do with tax and shipping. - -Or would it be better on any order change to just cancel the order and create a new one with full re- -calculations, including promotions, tax, shipping, etc, etc? If that is done should we apply promotions, -etc as if it was the original order date, or using today's date? (could be a big difference based on -promotions that come and go over time) - - - - 89 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040312171315 - Product - jonesde - not determined - PATCH - 2004-03-12 17:10:18 - issues@ofbiz - - - - All - In product detail show variant prices (from Brian Johnson) - - - jonesde - 2004-03-12 17:10:18 - Here is a description from an email from Brian Johnson: - -=================================== -I've changed productdetail to better handle variants with different prices. When you first bring-up the -page it says "make selections", then when you select the features from the drop-downs it'll show the -price for the product with those features. --- -Brian Johnson -=================================== - - - jonesde - 2004-03-12 17:13:15 - Created an attachment (id=41) -Show prices for variants along with drop down, patch from Brian Johnson - - - - text/plain - 41 - 2004-03-12 17:13:15 - Show prices for variants along with drop down, patch from Brian Johnson - 1 - productdetail-variantprices.patch - 3 - jonesde - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/41/productdetail-variantprices.patch - - - jonesde - 2004-03-12 17:11:11 - issue_type - Issue Type - DEFECT - PATCH - - - jonesde - 2004-03-12 17:13:15 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=41) -Show prices for variants along with drop down, patch from Brian Johnson - - - - - 90 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040312172159 - E-Commerce - jonesde - not determined - FEATURE - 2004-03-12 17:21:59 - issues@ofbiz - - - - All - Web/order/etc marketing reports like Core Metrics - - - jonesde - 2004-03-12 17:21:59 - The feature here is to create a standard set of reports commonly used to keep tabs on a web content -and/or ecommerce site. These reports would be similar to what a company like Core Metrics offers. - -Would include reports for a given time period such as for things like hits, visits/sessions, orders, -tracking codes, percent of customers that order, orders per customer, pages/products/etc viewed, -searches done, referring sites & search strings, etc, etc, etc. - - - - 91 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040315011245 - Product - jacopo - not determined - DEFECT - 2004-03-15 01:12:45 - issues@ofbiz - - - - All - Shipment: potential problem when issuing negative reservations (quantityNotAvailable could be lost) - - - jacopo - 2004-03-15 01:12:45 - This is a potential problem when you issue negative reservation to a shipment. -Here is the scenario: - -1) inventory item 9000 for product WG-1111 with atp/qoh = 10/10 -2) two orders are received for WG-1111: the first for 8 items, the second -for 5 items -3) two reservations are made: the first for 8 items and the second for 5 -items but with quantityNotAvailable = 3 -4) the inventory item 9000 is now: atp/qoh = -3/10 -5) only the second order is issued to shipment: the reservation record is -deleted and the qoh is decremented -6) the inventory item 9000 is now: atp/qoh = -3/5 but the reservation for -the first order (for quantity = 8) has quantityNotAvailable = 0 (ERROR: it -should be 3) - -A possible patch: if we issue a negative reservation we should try to assign -the quantityNotAvailable to another reservation in the same inventory item. - -In order to do this, David Jones has proposed to do a re-reservation whenever a -reservation is issued to a shipment, considering that (like in this scenario) -shipments may occur in a different order than reservations. - -In fact, when new inventory is received a re-reservation is already done for -all OIIR that are associated to inventory items (of the same product) that have -negative ATP. -In a similar way, when we issue a OIIR, we could do a re-reservation for all -the OIIR associated to the inventory item. - - - - 92 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20040416115022 - E-Commerce - holivier - not determined - PATCH - 2004-03-16 06:35:41 - issues@ofbiz - - - - All - Simple Update for localization - - - holivier - 2004-03-16 06:35:41 - In the ecommerce component -2 UiLabels change (the # is now in the label) -and some french UiLabel correction - - - holivier - 2004-03-16 06:38:00 - Created an attachment (id=42) -the Ecommerce UiLabel patch - - - - jonesde - 2004-04-16 11:50:22 - Patch is in CVS. Thanks for doing these Olivier. - - - text/plain - 42 - 2004-03-16 06:38:00 - the Ecommerce UiLabel patch - 1 - EcommerceUiLabel.update.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/42/EcommerceUiLabel.update.patch - - - holivier - 2004-03-16 06:38:00 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=42) -the Ecommerce UiLabel patch - - - - ajzeneski - 2004-03-18 12:04:15 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-04-16 11:50:22 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-16 11:50:22 - resolution - Resolution - - FIXED - - - - 93 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20040416115029 - Order - holivier - not determined - PATCH - 2004-03-16 08:00:55 - issues@ofbiz - - - - All - Simple Update for localization - - - holivier - 2004-03-16 08:00:55 - Order component, some french UiLabels correction - - - holivier - 2004-03-16 08:02:07 - Created an attachment (id=43) -The OrderUilabel properties patch file - - - - jonesde - 2004-04-16 11:50:29 - Patch is in CVS. Thanks for doing these Olivier. - - - text/plain - 43 - 2004-03-16 08:02:07 - The OrderUilabel properties patch file - 1 - OrderUilabelCorrection.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/43/OrderUilabelCorrection.patch - - - holivier - 2004-03-16 08:02:07 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=43) -The OrderUilabel properties patch file - - - - ajzeneski - 2004-03-18 12:04:26 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-04-16 11:50:29 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-16 11:50:29 - resolution - Resolution - - FIXED - - - - 94 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20040416115037 - Party - holivier - not determined - PATCH - 2004-03-16 09:28:27 - issues@ofbiz - - - - All - Simple Update for localization - - - holivier - 2004-03-16 09:28:27 - simple french correction & translation in the Party and workeffort components - - - holivier - 2004-03-16 09:29:26 - Created an attachment (id=44) -the PartyUiLabel correction patch file - - - - holivier - 2004-03-16 09:30:03 - Created an attachment (id=45) -the workeffortUilabel correction patch file - - - - jonesde - 2004-04-16 11:50:37 - Patch is in CVS. Thanks for doing these Olivier. - - - text/plain - 44 - 2004-03-16 09:29:26 - the PartyUiLabel correction patch file - 1 - PartyUiLabelCorrection040316.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/44/PartyUiLabelCorrection040316.patch - - - text/plain - 45 - 2004-03-16 09:30:03 - the workeffortUilabel correction patch file - 1 - WorkeffortUiLabelCorrection040316.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/45/WorkeffortUiLabelCorrection040316.patch - - - holivier - 2004-03-16 09:29:26 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=44) -the PartyUiLabel correction patch file - - - - holivier - 2004-03-16 09:30:03 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=45) -the workeffortUilabel correction patch file - - - - ajzeneski - 2004-03-18 12:04:35 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-04-16 11:50:37 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-16 11:50:37 - resolution - Resolution - - FIXED - - - - 95 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20040416115047 - Product - holivier - not determined - PATCH - 2004-03-16 09:32:59 - issues@ofbiz - - - - All - Simple Update for localization - - - holivier - 2004-03-16 09:32:59 - Product components internationalization and the UiLabel files associated - - - holivier - 2004-03-16 09:36:08 - Created an attachment (id=46) -the patch file for produt bsh, xml, ftl and properties - - - - jonesde - 2004-04-16 11:50:47 - Patch is in CVS. Thanks for doing these Olivier. - - - text/plain - 46 - 2004-03-16 09:36:08 - the patch file for produt bsh, xml, ftl and properties - 1 - ProductUiLabelMigration040316.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/46/ProductUiLabelMigration040316.patch - - - holivier - 2004-03-16 09:36:08 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=46) -the patch file for produt bsh, xml, ftl and properties - - - - ajzeneski - 2004-03-18 12:04:46 - version - Version - Pre3.0.0 - CVS - - - jonesde - 2004-04-16 11:50:47 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-16 11:50:47 - resolution - Resolution - - FIXED - - - - 96 - RESOLVED - P3 - FIXED - Components - CVS - All - jonesde - 20040730204543 - Security Extensions - holivier - not determined - PATCH - 2004-03-16 13:30:49 - issues@ofbiz - - - - All - Typo error correction in emailPassword (bcc in place of cc) - - - holivier - 2004-03-16 13:30:49 - just a simple typo correction.In the emailPassword method when reading and -populated the service fields they was an error. - serviceContext.put("sendBcc", productStoreEmail.get("ccAddress")); -I have change cc to bcc - - - holivier - 2004-03-16 13:31:26 - Created an attachment (id=47) -the patch file - - - - ajzeneski - 2004-07-30 20:45:43 - this has already been fixed in cvs. - - - text/plain - 47 - 2004-03-16 13:31:26 - the patch file - 1 - EmailPassword040316.patch - 165 - holivier - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/47/EmailPassword040316.patch - - - holivier - 2004-03-16 13:31:26 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=47) -the patch file - - - - ajzeneski - 2004-03-18 12:04:54 - version - Version - Pre3.0.0 - CVS - - - ajzeneski - 2004-07-30 20:45:43 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 20:45:43 - resolution - Resolution - - FIXED - - - - 97 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040527234819 - Accounting - jacopo - not determined - DEFECT - 2004-03-18 06:59:56 - issues@ofbiz - - - - All - Error when creating an invoice with billing account payment type. - - - jacopo - 2004-03-18 06:59:56 - The following error is generated when you try to create an invoice for an order -with payment type == billing account: - ----------------------------------------- -803495[ InvoiceServices.java:583:ERROR] Problems storing invoice items -org.ofbiz.entity.GenericEntityException: Exception occurred in storeAll (while i -nserting: [GenericEntity:InvoiceContactMech][createdTxStamp,2004-03-18 15:29:46. -156(java.sql.Timestamp)][invoiceId,10010(java.lang.String)][contactMechPurposeTy -peId,BILLING_LOCATION(java.lang.String)][lastUpdatedTxStamp,2004-03-18 15:29:46. -156(java.sql.Timestamp)][contactMechId,null()][createdStamp,2004-03-18 15:29:46. -977(java.sql.Timestamp)][lastUpdatedStamp,2004-03-18 15:29:46.977(java.sql.Times -tamp)] (SQL Exception while executing the following:INSERT INTO INVOICE_CONTACT_ -MECH (INVOICE_ID, CONTACT_MECH_PURPOSE_TYPE_ID, CONTACT_MECH_ID, LAST_UPDATED_ST -AMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, CREATED_TX_STAMP) VALUES (?, ?, ?, ?, - ?, ?, ?) ([-5005] (at 83): Missing non-NULL value))) ----------------------------------------- - -I think I've tracked down the source of this problem: -the field contactMechId for the billing account entry in BillingAccount entity -is empty. - - - jacopo - 2004-05-26 10:12:53 - The error happens when no Billing Contact Mechanism is specified in the billing -account. -In order to fix this issue the input field "Billing Contact Mech" in the -EditBillingAccount page should be marked as mandatory. - - - - jonesde - 2004-05-27 23:48:19 - Fixed by changing the code to not try to create that record when the BillingAccount.contactMechId is -empty. - - - jonesde - 2004-05-27 23:48:18 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-27 23:48:18 - resolution - Resolution - - FIXED - - - - 98 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040322173551 - Product - jacopo - not determined - FEATURE - 2004-03-19 07:41:21 - issues@ofbiz - - - - All - New Shipment Plan feature for the shipment process. - - - jacopo - 2004-03-19 07:41:21 - New Shipment Plan feature for the shipment process. - -In order to support some of the tasks in the manufacturing industry there was -the need of some simple shipment planning functionality: we need to assign a -group of customer order items to a scheduled shipment (but without actually -picking and issuing the items from warehouse). - -The patches in the attached zip file add this functionality to the shipment ui. -This is the list of changes: - -NEW FILES (new page, within the shipment ui, for ShipmentPlan management) - -product/webapp/facility/shipment/EditShipmentPlan.ftl -product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.bsh -product/webapp/facility/WEB-INF/pagedefs/shipment/EditShipmentPlan.xml - -PATCHES -product/webapp/facility/shipment/ShipmentTabBar.ftl (added new link to -EditShipmentPlan page) - -product/webapp/facility/shipment/ShipmentForms.xml (some new forms for the -EditShipmentPlan page) - -product/webapp/facility/WEB-INF/controller.xml (controller definitions for the -EditShipmentPlan page) - -product/webapp/facility/shipment/AddItemsFromOrder.ftl (added some info, also -fixed issues #47 and #55) -product/webapp/facility/WEB-INF/actions/shipment/AddItemsFromOrder.bsh (added -code to get reservations also from shipment plan) - -product/servicedef/services_shipment.xml (definitions for two new services to -add/delete entries in the Shipment Plan) -product/scripts/org/ofbiz/shipment/shipment/ShipmentSerices.xml (implementation -of the two new services) - -product/entitydef/entitygroup.xml (declaration of the new entity ShipmentPlan) -product/entitydef/entitymodel_shipment.xml (definition of the new entity -ShipmentPlan) - -product/config/ProductUiLabels.properties (some new labels) -product/config/ProductUiLabels_fr.properties (some new labels in ENGLISH) - - - jacopo - 2004-03-19 07:42:41 - Created an attachment (id=48) -The patches and new files - - - - jonesde - 2004-03-22 17:35:51 - This patch is now in place. Thanks for sending it in Jacopo. BTW, for future patches a consolidated -patch file is nice. - - - application/x-compressed - 48 - 2004-03-19 07:42:41 - The patches and new files - - ShipmentPlan.zip - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/48/ShipmentPlan.zip - - - jacopo - 2004-03-19 07:42:41 - attachments.thedata - Attachment Data - - Created an attachment (id=48) -The patches and new files - - - - jonesde - 2004-03-22 17:35:51 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-03-22 17:35:51 - resolution - Resolution - - FIXED - - - - 99 - RESOLVED - P4 - FIXED - Components - CVS - All - issues@ofbiz - 20040806160304 - Product - jacopo - not determined - PATCH - 2004-03-28 01:13:10 - issues@ofbiz - - - - All - New html report that shows inventory availability by product - - - jacopo - 2004-03-28 01:13:10 - This is a new html report (patches are in the attached zip file) for the -Facility Manager Application that shows info about stock levels and -reservations from a product point of view (instead of inventory item). -The action code is very simple (the bsh action calls a service to -compute atp and qoh per product); the report is formatted by the form widget -stuff. -It is not internationalized. -In my local setup I've added a link to it from the Inventory Item page but fell -free to modify it and put it where you want. - - - jacopo - 2004-03-28 01:14:46 - Created an attachment (id=49) -Files and patches for the new report. - - - - jonesde - 2004-08-06 16:03:04 - Okay, this is in CVS, and I added a link to it from the facility inventory items page. Thanks for sending -this over. - - - application/x-compressed - 49 - 2004-03-28 01:14:46 - Files and patches for the new report. - - inventory_report.zip - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/49/inventory_report.zip - - - jacopo - 2004-03-28 01:14:46 - attachments.thedata - Attachment Data - - Created an attachment (id=49) -Files and patches for the new report. - - - - jonesde - 2004-08-06 16:03:04 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-06 16:03:04 - resolution - Resolution - - FIXED - - - - 100 - RESOLVED - P3 - FIXED - Components - REL 3.0.0 - All - issues@ofbiz - 20040403232241 - E-Commerce - dlouzado - not determined - DEFECT - 2004-03-28 13:50:10 - issues@ofbiz - - - - All - crash on Shipping Information page - - - dlouzado - 2004-03-28 13:50:10 - I was logged as "admin" user and buying something on the test store on ofbiz -instance running on a standalone machine (no connection with the internet). - -I was filling the shipping information and when I clicked 'continue' the -following exception was thrown: - - -"org.ofbiz.base.util.GeneralException: JPublish execution error (BeanShell -script error: Sourced file: -C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh -: Error in method invocation: Attempt to pass void argument (position 0) to -method: getContactMechByType : at Line: 65 : in file: -C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh -: ContactHelper .getContactMechByType ( party , "EMAIL_ADDRESS" , false ) -BSF info: -C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh -at line: 0 column: 0)" - - - jonesde - 2004-04-03 23:22:41 - Fixed so that "party" would exist where it is referenced there. - - - jonesde - 2004-04-03 23:22:41 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-03 23:22:41 - resolution - Resolution - - FIXED - - - - 101 - RESOLVED - P5 - FIXED - Components - CVS - All - ajzeneski - 20040730152858 - Content - eckardjf - not determined - DEFECT - 2004-04-02 09:44:46 - issues@ofbiz - - - - All - https Website Settings Ignored - - - eckardjf - 2004-04-02 09:44:46 - org.ofbiz.content.webapp.control.RequestHandler.doRequest() checks to see if a request should be -secure, but is not - and will redirect to a secure url if necessary. However, when rewriting the url to -make it secure, it does not check the website settings for the enableHttps, httpsHost and httpsPort. It -uses the global defaults from url.properties instead, which means the website settings have no effect. - - - ajzeneski - 2004-07-30 15:28:58 - this has now been corrected in CVS. - - - ajzeneski - 2004-06-30 19:43:50 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-07-30 15:28:58 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 15:28:58 - resolution - Resolution - - FIXED - - - - 102 - NEW - P4 - - Components - REL 3.0.0 - All - issues@ofbiz - 20040403233556 - Entity Extensions - jonesde - not determined - ENHANCEMENT - 2004-04-03 23:35:56 - issues@ofbiz - - - - All - Easy way to disabling Entity Sync oriented information - - - jonesde - 2004-04-03 23:35:56 - Need an easy way to disable the saving of Entity Sync oriented information such as the entity remove -information. May not want to disable the auto tx and individual timestamps because they are used in -other code that takes advantage of the fact that they are always present (though we still need to get rid -of the last updated and created timestamps that were added to various entities). - - - - 103 - RESOLVED - P1 - FIXED - Components - CVS - All - ajzeneski - 20040405070601 - Accounting - bryce_nz - not determined - DEFECT - 2004-04-05 00:05:28 - issues@ofbiz - - - - All - Nasty little error in PaymentGatewayServices - - - bryce_nz - 2004-04-05 00:05:28 - In PaymentGatewayServices.refundPayment there is a section of code for creating -the payment for the refund, then at line 1255 there is the following: - - Map result = ServiceUtil.returnSuccess(); - result.put("paymentId", "10000"); - return result; - -Obviously the payment id being returned shouldn't be hardcoded in, should read: - - Map result = ServiceUtil.returnSuccess(); - result.put("paymentId", paymentId); - return result; - - - ajzeneski - 2004-04-05 07:06:01 - This has been corrected in CVS, thank you. - - - ajzeneski - 2004-04-05 07:05:36 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-04-05 07:06:01 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 07:06:01 - resolution - Resolution - - FIXED - - - - 104 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405134511 - Workflow - elfring - not determined - FEATURE - 2004-04-05 13:22:20 - issues@ofbiz - - - - All - Job Definition - - - elfring - 2004-04-05 13:22:20 - This request might fit to the section "Service Engine Tools" on the page -"http://ofbiz.org/feature-list.html". - -Would you like to support the JDF -standard? -http://en.wikipedia.org/wiki/Job_Definition_Format - - - ajzeneski - 2004-04-05 13:45:11 - Not sure what this is supposed to be requesting. This issue contains no specific feature request. - - - ajzeneski - 2004-04-05 13:45:11 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 13:45:11 - resolution - Resolution - - INVALID - - - - 105 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405134741 - Service - elfring - not determined - FEATURE - 2004-04-05 13:28:41 - issues@ofbiz - - - - All - Support for dynamic Service Configuration - - - elfring - 2004-04-05 13:28:41 - Would you like to use a service configurator for your server? -- -http://www.cs.wustl.edu/~schmidt/ACE-papers.html -- -http://java.sun.com/j2se/1.5.0/docs/guide/jmx/tutorial/tutorialTOC.html - -Can this -request solved with JMX? -http://en.wikipedia.org/wiki/Java_Management_eXtensions - - - ajzeneski - 2004-04-05 13:47:41 - This issue contains no specific feature request. Not sure what you are requesting, so there is no way to -determine if JMX will solve the problem. - - - ajzeneski - 2004-04-05 13:47:41 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 13:47:41 - resolution - Resolution - - INVALID - - - - 106 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405134845 - WebTools - elfring - not determined - FEATURE - 2004-04-05 13:42:12 - issues@ofbiz - - - - All - Portlet Interface - - - elfring - 2004-04-05 13:42:12 - Would you like to integrate components with web portals? - -- -http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-portlet2.html -- -http://www.javaworld.net/javaworld/jw-11-2003/jw-1114-jsfredux.html -- -http://en.wikipedia.org/wiki/Portlet - - - ajzeneski - 2004-04-05 13:48:45 - Sure we would love to integrate with web portals, however this issue contains no specific feature -request. - - - ajzeneski - 2004-04-05 13:48:45 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 13:48:45 - resolution - Resolution - - INVALID - - - - 107 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405135106 - WebTools - elfring - not determined - FEATURE - 2004-04-05 13:47:12 - issues@ofbiz - - - - All - Vector graphics and XForms - - - elfring - 2004-04-05 13:47:12 - Will the application support .svgz or .x3dz files that contain XForms? - -- -http://en.wikipedia.org/wiki/Scalable_Vector_Graphics -- -http://en.wikipedia.org/wiki/X3D -- http://en.wikipedia.org/wiki/XForms -- -http://xml.apache.org/batik/ - -See also the request "XForms" in the discussion forum by -Britton LaRoche from "August 28, 2003 12:38:36 AM -GMT". -https://ofbiz.dev.java.net/servlets/ProjectForumMessageView?forumID=282&messageID=1065 - - - ajzeneski - 2004-04-05 13:51:06 - This issue contains no specific feature request. No information was provided regarding how support for -these file types is desired and where the desired functionality is needed. - - - ajzeneski - 2004-04-05 13:51:06 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 13:51:06 - resolution - Resolution - - INVALID - - - - 108 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405140048 - Rules - elfring - not determined - FEATURE - 2004-04-05 13:51:31 - issues@ofbiz - - - - All - Integration with Knowledge Representation - - - elfring - 2004-04-05 13:51:31 - What is the current state of your support for this technology? -- -http://en.wikipedia.org/wiki/Knowledge_representation -- -http://en.wikipedia.org/wiki/Expert_system - - - ajzeneski - 2004-04-05 14:00:48 - This issue is not a valid feature request, questions of this sort should be discussed on the mailing lists. -In addition, do expect readers to follow links and read articles to get your point across it is highly -unlikely that people will spent the time to research something for you. Your best bet is to read the -articles and post a question asking something specific, then your chances of getting an intelligent -response is greater. - - - ajzeneski - 2004-04-05 14:00:48 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 14:00:48 - resolution - Resolution - - INVALID - - - - 109 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405140138 - Service - elfring - not determined - FEATURE - 2004-04-05 13:52:57 - issues@ofbiz - - - - All - Open Services Gateway - - - elfring - 2004-04-05 13:52:57 - Would you like to cooperate with these service APIs so that your software can be used over these -interfaces? -http://www.osgi.org/about/faqs.asp -http://en.wikipedia.org/wiki/OSGi - - - ajzeneski - 2004-04-05 14:01:37 - This issue contains no specific feature request. - - - ajzeneski - 2004-04-05 14:01:37 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 14:01:37 - resolution - Resolution - - INVALID - - - - 110 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405140228 - Entity - elfring - not determined - FEATURE - 2004-04-05 13:56:20 - issues@ofbiz - - - - All - Content Storage API - - - elfring - 2004-04-05 13:56:20 - Would you like to support the programming interface "Content -Repository"? -http://jcp.org/en/jsr/detail?id=170 - -This topic can be perhaps combined -with requests for CVS and Subversion integration. - - - ajzeneski - 2004-04-05 14:02:28 - This issue contains no specific feature request; please see issue #108 for more suggestions. - - - ajzeneski - 2004-04-05 14:02:28 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 14:02:28 - resolution - Resolution - - INVALID - - - - 111 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405140305 - Workflow - elfring - not determined - ENHANCEMENT - 2004-04-05 14:02:16 - issues@ofbiz - - - - All - Workflow Management - - - elfring - 2004-04-05 14:02:17 - How do you think about workflow modelling patterns? -Which of them are supported by your -software? (Is cooperation with other standards like BPML besides WfMC XPDL -possible?) -http://tmitwww.tm.tue.nl/research/patterns/ - - - ajzeneski - 2004-04-05 14:03:05 - see issue #108 - - - ajzeneski - 2004-04-05 14:03:05 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 14:03:05 - resolution - Resolution - - INVALID - - - - 112 - RESOLVED - P3 - INVALID - Components - CVS - All - issues@ofbiz - 20040405141257 - Entity Extensions - elfring - not determined - ENHANCEMENT - 2004-04-05 14:07:40 - issues@ofbiz - - - - All - relationships and object mapping - - - elfring - 2004-04-05 14:07:40 - I've got the impression from the discussion about the topic "entity-engine: thoughts on extends -(IS A) pattern and relationships" that there might be something useful from other information -sources. - -1. CORBA: Relationship Service -Specification -http://www.omg.org/technology/documents/formal/relationship_service.htm - -2. -ObJectRelationalBridge -http://db.apache.org/ojb/ - -3. alternative open source -implementation for JDO -http://speedo.objectweb.org/ - -4. Citations from -CiteSeer -http://citeseer.ist.psu.edu/cis?q=object+and+relational+and+mapping+and+database - -5. -a detailed Wiki -http://en.wikipedia.org/wiki/Object_database - -Would you like to reuse -anything from those implementations and experiences? - -How does your use of the Java Open -Transaction Manager (http://jotm.objectweb.org/) fit into this picture? - - - ajzeneski - 2004-04-05 14:12:57 - No specific enhancement requested. - - - ajzeneski - 2004-04-05 14:12:57 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-04-05 14:12:57 - resolution - Resolution - - INVALID - - - - 113 - RESOLVED - P3 - WORKSFORME - Components - CVS - All - issues@ofbiz - 20040406101817 - WebTools - ajzeneski - not determined - DEFECT - 2004-04-06 07:00:29 - issues@ofbiz - - - - All - EditEntity.jsp displays wrong field length - - - ajzeneski - 2004-04-06 07:00:29 - Reported by prozelit@yahoo.com: - -On EditEntity.jsp, there is a fields table. It is -supposed to display the length of each field, but it -looks like it displays the length of the field name -instead. It seems to me there is a bug at line 347. - - - jonesde - 2004-04-06 10:18:17 - -This is the expected behavior. The length in parenthesis there is meant to show you the length of the -column name so that you can tell if it is within the required length of the database, we generally -recommend (and always use) equal or less than 30 characters. - - - jonesde - 2004-04-06 10:18:17 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-06 10:18:17 - resolution - Resolution - - WORKSFORME - - - - 114 - NEW - P3 - - Components - CVS - PC - issues@ofbiz - 20040406100126 - WorkEffort - vivalinux - not determined - PATCH - 2004-04-06 10:01:26 - issues@ofbiz - - http://<ofbiz_URL>/workeffort/control/month?start=1083297600000 - - All - Daylight savings and the calendar - - - vivalinux - 2004-04-06 10:01:26 - On the months when daylight savings takes place, or stops taking place -(April/September in the US), the way the start of the period is computed in the -WorkEffortServices.getWorkEffortsByPeriod yields one extra hour after dayligh -savings kicks in. -The reason for this is that the absolute time is interpreted differently once -daylight savings is in place. -So I suggest using the attached patch which relies on UtilDateTime.getDayStart -to get the period start/end. - - - - 115 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040730150719 - Product - lykins - not determined - FEATURE - 2004-04-06 13:56:51 - issues@ofbiz - - - - All - Product to Order Lookup Link - - - lykins - 2004-04-06 13:56:51 - Something that should bring great benefit is the ability to link the product to -the orders from the product maintenance screen. It would be very beneficial to -know what purchase order the product came from. I noticed that there are links -to almost all other relations besides this. - -Thanks, -Patrick - - - ajzeneski - 2004-07-30 15:07:19 - good idea; now in CVS - - - ajzeneski - 2004-07-30 15:07:19 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 15:07:19 - resolution - Resolution - - FIXED - - - - 116 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040417174533 - Product - jacopo - not determined - PATCH - 2004-04-17 00:19:59 - issues@ofbiz - - - - All - Implementation of getProductVariant service. - - - jacopo - 2004-04-17 00:19:59 - Implementation of getProductVariant service. - - - jacopo - 2004-04-17 00:20:48 - Created an attachment (id=50) -Patch for the java implementation - - - - jacopo - 2004-04-17 00:21:21 - Created an attachment (id=51) -Patch for the service definition. - - - - jonesde - 2004-04-17 17:45:33 - It's in. Thanks Jacopo. - - - text/plain - 50 - 2004-04-17 00:20:48 - Patch for the java implementation - 1 - ProductServices.java.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/50/ProductServices.java.patch - - - text/plain - 51 - 2004-04-17 00:21:21 - Patch for the service definition. - 1 - services.xml.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/51/services.xml.patch - - - jacopo - 2004-04-17 00:20:48 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=50) -Patch for the java implementation - - - - jacopo - 2004-04-17 00:21:21 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=51) -Patch for the service definition. - - - - jonesde - 2004-04-17 17:45:33 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-17 17:45:33 - resolution - Resolution - - FIXED - - - - 117 - RESOLVED - P1 - FIXED - Components - CVS - All - issues@ofbiz - 20040422201817 - Accounting - colt_nz - not determined - DEFECT - 2004-04-20 14:45:56 - issues@ofbiz - - - - All - editPayment has wrongly named fields - - - colt_nz - 2004-04-20 14:45:56 - /accounting/webapp/accounting/payment/editPayment.ftl - -Input fields partyIdTo and partyIdFrom are round the wrong way. ie switch 'em. - - - jonesde - 2004-04-22 20:18:17 - -Thanks for reporting this, the fix is in CVS. Looks like it was perhaps an issue with the i18n... - - - jonesde - 2004-04-22 20:18:17 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-22 20:18:17 - resolution - Resolution - - FIXED - - - - 118 - RESOLVED - P4 - FIXED - Components - CVS - All - issues@ofbiz - 20040819001212 - Product - jonesde - not determined - FEATURE - 2004-04-23 21:32:35 - issues@ofbiz - - - - All - Make QuickAddVariants Easier to Use - - - jonesde - 2004-04-23 21:32:35 - Make QuickAddVariants Easier to Use: - -1. Change to multi-form -2. Allow enter pattern to use to pre-populate the various IDs - - - jacopo - 2004-08-19 00:12:11 - Some time ago I did this and you put all the stuff in CVS, so now it's done. - - - jacopo - 2004-08-19 00:12:10 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-08-19 00:12:10 - resolution - Resolution - - FIXED - - - - 119 - RESOLVED - P2 - FIXED - Components - CVS - All - jacopo - 20040717041328 - Manufacturing - jacopo - not determined - ENHANCEMENT - 2004-04-24 00:15:36 - issues@ofbiz - - - - All - Refactoring of the BOMEvent class that manages all the related to bill of materials editing. - - - jacopo - 2004-04-24 00:15:36 - Refactoring of the BOMEvent class that manages all the related to bill of -materials editing. - -Three new (simple) services should be created (create, update, delete). -An sECA rule should be added to the create and update services to update the -low level code. - - - jacopo - 2004-07-17 04:13:28 - Ok, the BOMEvent class has gone away; I have implemented some simple services -to add/update/remove/copy boms (performing all the needed checks for loops and -updating the product's llc). - - - - jacopo - 2004-07-17 04:13:28 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-17 04:13:28 - resolution - Resolution - - FIXED - - - - 120 - NEW - P3 - - Components - CVS - All - jacopo - 20040424001903 - Manufacturing - jacopo - not determined - ENHANCEMENT - 2004-04-24 00:19:03 - issues@ofbiz - - - - All - searchDuplicateAncenstor service should resolve also virtual to variant products to search for loops. - - - jacopo - 2004-04-24 00:19:03 - searchDuplicateAncenstor service should resolve also virtual to variant -products to search for loops. - - - - 121 - RESOLVED - P3 - FIXED - Components - CVS - All - jacopo - 20040717041557 - Manufacturing - jacopo - not determined - ENHANCEMENT - 2004-04-24 00:24:11 - issues@ofbiz - - - - All - Refactoring of the Bill of Material editor's ui: migration to the forms widget. - - - jacopo - 2004-04-24 00:24:11 - Refactoring of the Bill of Material editor's ui: migration to the forms widget. - -This will also include: -- i18n and l10n issues -- management of all the relavant fields that are missing -- lookup fields -- fields validation - - - jacopo - 2004-07-17 04:15:57 - I have not used the form widget (maybe in the future, together with some more -clean ups) here, but most of these points has been fixed. - - - jacopo - 2004-07-17 04:15:57 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-17 04:15:57 - resolution - Resolution - - FIXED - - - - 122 - NEW - P3 - - Components - CVS - All - jacopo - 20040424002537 - Manufacturing - jacopo - not determined - ENHANCEMENT - 2004-04-24 00:25:37 - issues@ofbiz - - - - All - updateLowLevelCode service - it should also update the low level code for variant products - - - jacopo - 2004-04-24 00:25:37 - updateLowLevelCode service - it should also update the low level code for -variant products - - - - 123 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501062848 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:05:20 - issues@ofbiz - - - - All - Add methods to check against classes, instead of only objects. - - - doogie - 2004-04-29 16:05:20 - This patch adds new versions of interfaceOf, isOrSubOf, and instanceOf, that -check against a class, instead of an Object. - - - doogie - 2004-04-29 16:06:57 - Created an attachment (id=52) -The patch. - - - - doogie - 2004-04-29 19:57:52 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:28:48 - This is now in CVS, thanks Adam! - - - text/plain - 52 - 2004-04-29 16:06:57 - The patch. - 1 - ObjectType-check-against-class.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/52/ObjectType-check-against-class.patch - - - doogie - 2004-04-29 16:06:57 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=52) -The patch. - - - - doogie - 2004-04-29 16:15:14 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - doogie - 2004-04-29 19:57:52 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:28:48 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:28:48 - resolution - Resolution - - FIXED - - - - 124 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501062855 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:08:48 - issues@ofbiz - - - - All - Handle is-* operators when value1 is null - - - doogie - 2004-04-29 16:08:48 - See $summary. - - - doogie - 2004-04-29 16:09:11 - Created an attachment (id=53) -The patch - - - - doogie - 2004-04-29 19:57:53 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:28:55 - This is now in CVS, thanks Adam! - - - text/plain - 53 - 2004-04-29 16:09:11 - The patch - 1 - ObjectType-is-compare-value1-null.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/53/ObjectType-is-compare-value1-null.patch - - - doogie - 2004-04-29 16:09:11 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=53) -The patch - - - - doogie - 2004-04-29 16:15:14 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - doogie - 2004-04-29 19:57:53 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:28:55 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:28:55 - resolution - Resolution - - FIXED - - - - 125 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501062903 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:10:04 - issues@ofbiz - - - - All - Convert classnames to full names. - - - doogie - 2004-04-29 16:10:04 - See $summary. - - - doogie - 2004-04-29 16:10:21 - Created an attachment (id=54) -The patch. - - - - doogie - 2004-04-29 19:57:48 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:29:03 - This is now in CVS, thanks Adam! - - - text/plain - 54 - 2004-04-29 16:10:21 - The patch. - 1 - ObjectType-convert-classname-to-full.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/54/ObjectType-convert-classname-to-full.patch - - - doogie - 2004-04-29 16:10:21 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=54) -The patch. - - - - doogie - 2004-04-29 16:15:13 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - doogie - 2004-04-29 19:57:48 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:29:03 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:29:03 - resolution - Resolution - - FIXED - - - - 126 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501062243 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:13:25 - issues@ofbiz - - - - All - Add some helper methods for objects implementing their own equals, compareTo, and hashCode - - - doogie - 2004-04-29 16:13:25 - Name: UtilObject.patch -Prune: 1 -Description: Add some helper methods for objects implementing their own equals, -compareTo, and hashCode. -DiffStat: - base/src/base/org/ofbiz/base/util/UtilObject.java | 35 ++++++++++++++++++++++ - 1 files changed, 35 insertions(+) - - - doogie - 2004-04-29 16:13:45 - Created an attachment (id=55) -The patch. - - - - doogie - 2004-04-29 19:57:49 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:22:43 - This is now in CVS, thanks Adam! - - - text/plain - 55 - 2004-04-29 16:13:45 - The patch. - 1 - UtilObject.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/55/UtilObject.patch - - - doogie - 2004-04-29 16:13:45 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=55) -The patch. - - - - doogie - 2004-04-29 16:15:13 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - doogie - 2004-04-29 19:57:49 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:22:43 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:22:43 - resolution - Resolution - - FIXED - - - - 127 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501055554 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:18:14 - issues@ofbiz - - - - All - Simplify the top-level build.xml - - - doogie - 2004-04-29 16:18:14 - Name: simpler-build.xml.patch -Prune: 1 -Description: Simplifies the top-level build.xml - This patch makes use of ant 1.6 features, to automate calling of sub - build.xmls. It also adds a 'test' target; note, however, that the - listed sub build.xmls don't actually have that test target yet. -DiffStat: - build.xml | 494 ++++---------------------------------------------------------- - 1 files changed, 32 insertions(+), 462 deletions(-) - - - doogie - 2004-04-29 16:18:43 - Created an attachment (id=56) -The patch. - - - - doogie - 2004-04-29 19:57:50 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 05:55:54 - This is now in, thanks Adam! - - - text/plain - 56 - 2004-04-29 16:18:43 - The patch. - 1 - simpler-build.xml.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/56/simpler-build.xml.patch - - - doogie - 2004-04-29 16:18:43 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=56) -The patch. - - - - doogie - 2004-04-29 16:19:44 - issue_type - Issue Type - DEFECT - ENHANCEMENT - - - doogie - 2004-04-29 19:57:50 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 05:55:54 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 05:55:54 - resolution - Resolution - - FIXED - - - - 128 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501051820 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:20:39 - issues@ofbiz - - - - All - Add support for formatting time intervals with human words - - - doogie - 2004-04-29 16:20:39 - Name: UtilDateTime-time-interval.patch -Prune: 1 -Description: Add support for formatting time intervals with human words -DiffStat: - base/config/DateTimeLabels.properties | 10 ++ - base/src/base/org/ofbiz/base/util/UtilDateTime.java | 90 ++++++++++++++++++++ - 2 files changed, 100 insertions(+) - - - doogie - 2004-04-29 16:20:57 - Created an attachment (id=57) -The patch. - - - - doogie - 2004-04-29 19:57:51 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 05:18:20 - These are now in CVS, thanks Adam! - - - text/plain - 57 - 2004-04-29 16:20:57 - The patch. - 1 - UtilDateTime-time-interval.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/57/UtilDateTime-time-interval.patch - - - doogie - 2004-04-29 16:20:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=57) -The patch. - - - - doogie - 2004-04-29 19:57:51 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 05:18:20 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 05:18:20 - resolution - Resolution - - FIXED - - - - 129 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429172414 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:22:10 - issues@ofbiz - - - - All - Add more childElementList and firstChildElement variants. - - - doogie - 2004-04-29 16:22:10 - Name: UtilXml-childElementList-firstChildElement.patch -Prune: 1 -Depends: UtilXml-writeElement.patch -Description: Add more childElementList and firstChildElement variants. -DiffStat: - base/src/base/org/ofbiz/base/component/ComponentLoaderConfig.java - | 2 - base/src/base/org/ofbiz/base/util/UtilXml.java - | 80 ++++++++++ - components/content/src/org/ofbiz/content/widget/form/ModelFormField.java - | 4 - components/entity/src/org/ofbiz/entity/model/ModelViewEntity.java - | 2 - components/minilang/src/org/ofbiz/minilang/SimpleMethod.java - | 2 - components/minilang/src/org/ofbiz/minilang/method/callops/CallClassMethod.java - | 2 - components/minilang/src/org/ofbiz/minilang/method/callops/CallObjectMethod.java - | 2 - components/minilang/src/org/ofbiz/minilang/method/callops/CreateObject.java - | 2 - components/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java -| 2 - components/minilang/src/org/ofbiz/minilang/method/conditional/MasterIf.java - | 2 - components/minilang/src/org/ofbiz/minilang/method/otherops/Calculate.java - | 4 - components/minilang/src/org/ofbiz/minilang/method/otherops/Log.java - | 2 - components/minilang/src/org/ofbiz/minilang/operation/MakeInString.java - | 2 - components/minilang/src/org/ofbiz/minilang/operation/SimpleMapProcess.java - | 2 - 14 files changed, 95 insertions(+), 15 deletions(-) - - - doogie - 2004-04-29 16:22:50 - Created an attachment (id=58) -The patch. - - - - doogie - 2004-04-29 16:57:47 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:24:14 - Now in CVS, thanks Adam. - - - text/plain - 58 - 2004-04-29 16:22:50 - The patch. - 1 - UtilXml-childElementList-firstChildElement.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/58/UtilXml-childElementList-firstChildElement.patch - - - doogie - 2004-04-29 16:22:50 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=58) -The patch. - - - - doogie - 2004-04-29 16:57:47 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:24:14 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:24:14 - resolution - Resolution - - FIXED - - - - 130 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429174623 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:24:36 - issues@ofbiz - - - - All - put now returns the previous value of the object, if it exists - - - doogie - 2004-04-29 16:24:36 - Name: UtilCache-put-returns-object.patch -Prune: 1 -Depends: UtilCache-listeners.patch -Description: put now returns the previous value of the object, if it exists -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 16 ++++++++++------ - 1 files changed, 10 insertions(+), 6 deletions(-) - - - doogie - 2004-04-29 16:24:58 - Created an attachment (id=59) -The patch. - - - - doogie - 2004-04-29 16:57:48 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:46:23 - Now in CVS, thanks Adam. - - - text/plain - 59 - 2004-04-29 16:24:58 - The patch. - 1 - UtilCache-put-returns-object.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/59/UtilCache-put-returns-object.patch - - - doogie - 2004-04-29 16:24:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=59) -The patch. - - - - doogie - 2004-04-29 16:57:48 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:46:23 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:46:23 - resolution - Resolution - - FIXED - - - - 131 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040429174619 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 16:55:31 - issues@ofbiz - - - - All - Add getCacheLineKeys method. - - - doogie - 2004-04-29 16:55:31 - Name: UtilCache-getCacheLineKeys.patch -Prune: 1 -Depends: UtilCache-put-returns-object.patch -Description: Add getCacheLineKeys method. -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 4 ++++ - 1 files changed, 4 insertions(+) - - - doogie - 2004-04-29 16:55:56 - Created an attachment (id=60) -The patch. - - - - doogie - 2004-04-29 16:57:48 - Changing priority to P2, as I need these applied before I can commit my entity -cache work. - - - jonesde - 2004-04-29 17:46:19 - Now in CVS, thanks Adam. - - - text/plain - 60 - 2004-04-29 16:55:56 - The patch. - 1 - UtilCache-getCacheLineKeys.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/60/UtilCache-getCacheLineKeys.patch - - - doogie - 2004-04-29 16:55:56 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=60) -The patch. - - - - doogie - 2004-04-29 16:57:48 - priority - Priority - P3 - P2 - - - jonesde - 2004-04-29 17:46:19 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-04-29 17:46:19 - resolution - Resolution - - FIXED - - - - 132 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501051751 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 19:39:13 - issues@ofbiz - - - - All - Add entrySet(), which functions like Map.entrySet(). - - - doogie - 2004-04-29 19:39:13 - Name: UtilCache-entrySet.patch -Prune: 1 -Description: Add entrySet(), which functions like Map.entrySet(). -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 4 ++++ - 1 files changed, 4 insertions(+) - - - doogie - 2004-04-29 19:41:28 - Created an attachment (id=61) -The patch. - - - - doogie - 2004-04-29 19:57:53 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 05:17:51 - These are now in CVS, thanks Adam! - - - text/plain - 61 - 2004-04-29 19:41:27 - The patch. - 1 - UtilCache-entrySet.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/61/UtilCache-entrySet.patch - - - doogie - 2004-04-29 19:41:28 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=61) -The patch. - - - - doogie - 2004-04-29 19:57:53 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 05:17:51 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 05:17:51 - resolution - Resolution - - FIXED - - - - 133 - RESOLVED - P1 - FIXED - Base - CVS - All - issues@ofbiz - 20040501042628 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 19:42:19 - issues@ofbiz - - - - All - Add a new constructor. - - - doogie - 2004-04-29 19:42:19 - Name: UtilCache-new-constructor.patch -Prune: 1 -Depends: UtilCache-entrySet.patch -Description: Add a new constructor. -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 13 +++++++++++++ - 1 files changed, 13 insertions(+) - - - doogie - 2004-04-29 19:42:45 - Created an attachment (id=62) -The patch. - - - - doogie - 2004-04-29 19:57:48 - Changing priority, so that someone else can see the ones I want applied next. - - - doogie - 2004-04-30 10:42:15 - Changing these issuses, as they are needed by EntityCache.patch. - - - jonesde - 2004-05-01 04:26:28 - These are now in CVS, thanks Adam! - - - text/plain - 62 - 2004-04-29 19:42:45 - The patch. - 1 - UtilCache-new-constructor.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/62/UtilCache-new-constructor.patch - - - doogie - 2004-04-29 19:42:45 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=62) -The patch. - - - - doogie - 2004-04-29 19:57:48 - priority - Priority - P3 - P2 - - - doogie - 2004-04-30 10:42:15 - priority - Priority - P2 - P1 - - - jonesde - 2004-05-01 04:26:28 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 04:26:28 - resolution - Resolution - - FIXED - - - - 134 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501062248 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 19:43:49 - issues@ofbiz - - - - All - Change utilCacheTable to a WeakHashMap. - - - doogie - 2004-04-29 19:43:49 - Name: UtilCache-WeakHashMap.patch -Prune: 1 -Depends: UtilCache-new-constructor.patch -Description: Change utilCacheTable to a WeakHashMap. -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 3 ++- - 1 files changed, 2 insertions(+), 1 deletion(-) - - - doogie - 2004-04-29 19:44:39 - Created an attachment (id=63) -The patch. - - - - doogie - 2004-04-29 19:57:49 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:22:48 - This is now in CVS, thanks Adam! - - - text/plain - 63 - 2004-04-29 19:44:39 - The patch. - 1 - UtilCache-WeakHashMap.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/63/UtilCache-WeakHashMap.patch - - - doogie - 2004-04-29 19:44:39 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=63) -The patch. - - - - doogie - 2004-04-29 19:57:49 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:22:48 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:22:48 - resolution - Resolution - - FIXED - - - - 135 - RESOLVED - P1 - FIXED - Base - CVS - All - issues@ofbiz - 20040501042633 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 19:45:22 - issues@ofbiz - - - - All - Methods that clear a cache by name or pattern. - - - doogie - 2004-04-29 19:45:22 - Name: UtilCache-clearCache-helpers.patch -Prune: 1 -Depends: UtilCache-WeakHashMap.patch -Description: Methods that clear a cache by name or pattern. -DiffStat: - base/src/base/org/ofbiz/base/util/UtilCache.java | 22 ++++++++++++++++++++++ - 1 files changed, 22 insertions(+) - - - doogie - 2004-04-29 19:45:43 - Created an attachment (id=64) -The patch. - - - - doogie - 2004-04-29 19:57:49 - Changing priority, so that someone else can see the ones I want applied next. - - - doogie - 2004-04-30 10:42:16 - Changing these issuses, as they are needed by EntityCache.patch. - - - jonesde - 2004-05-01 04:26:33 - These are now in CVS, thanks Adam! - - - text/plain - 64 - 2004-04-29 19:45:43 - The patch. - 1 - UtilCache-clearCache-helpers.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/64/UtilCache-clearCache-helpers.patch - - - doogie - 2004-04-29 19:45:43 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=64) -The patch. - - - - doogie - 2004-04-29 19:57:49 - priority - Priority - P3 - P2 - - - doogie - 2004-04-30 10:42:16 - priority - Priority - P2 - P1 - - - jonesde - 2004-05-01 04:26:33 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 04:26:33 - resolution - Resolution - - FIXED - - - - 136 - RESOLVED - P2 - FIXED - Base - CVS - All - issues@ofbiz - 20040501064335 - Base - doogie - not determined - ENHANCEMENT - 2004-04-29 19:46:54 - issues@ofbiz - - - - All - Place the loaded document object in a UtilCache instance. - - - doogie - 2004-04-29 19:46:54 - Name: ResourceLoader-document-in-cache.patch -Prune: 1 -Depends: UtilCache-clearCache-helpers.patch -Description: Place the loaded document object in a UtilCache instance. -DiffStat: - base/src/base/org/ofbiz/base/config/ResourceLoader.java | 11 ++++------- - 1 files changed, 4 insertions(+), 7 deletions(-) - - - doogie - 2004-04-29 19:47:17 - Created an attachment (id=65) -The patch. - - - - doogie - 2004-04-29 19:57:50 - Changing priority, so that someone else can see the ones I want applied next. - - - jonesde - 2004-05-01 06:43:35 - This is now in CVS, thanks Adam! - - - text/plain - 65 - 2004-04-29 19:47:17 - The patch. - 1 - ResourceLoader-document-in-cache.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/65/ResourceLoader-document-in-cache.patch - - - doogie - 2004-04-29 19:47:17 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=65) -The patch. - - - - doogie - 2004-04-29 19:57:50 - priority - Priority - P3 - P2 - - - jonesde - 2004-05-01 06:43:35 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-01 06:43:35 - resolution - Resolution - - FIXED - - - - 137 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040527233355 - Accounting - sichen - not determined - DEFECT - 2004-05-03 14:48:41 - issues@ofbiz - - - - All - createInvoiceForOrder not get correct fields for terms - - - 141 - jacopo - 2004-05-26 10:48:21 - - - sichen - 2004-05-03 14:48:41 - InvoiceServices.createInvoiceForOrder is not getting correct fields for terms. -It is not automatically generating a key for InvoiceTerm entity and is also -looking for "termType" from BillingAccount when the field is actually "termTypeId." - - - sichen - 2004-05-03 14:50:09 - Created an attachment (id=66) -Patch fixes defect and allows invoices to be created correctly - - - - jacopo - 2004-05-04 00:50:17 - See also issue #97 - - - jacopo - 2004-05-26 10:48:20 - *** Issue 141 has been marked as a duplicate of this issue. *** - - - jonesde - 2004-05-27 23:33:55 - It's now in CVS, thanks to both Si Chen and Jacopo Cappellato for reporting/fixing this. - - - text/plain - 66 - 2004-05-03 14:50:09 - Patch fixes defect and allows invoices to be created correctly - 1 - InvoiceServices.java.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/66/InvoiceServices.java.patch - - - sichen - 2004-05-03 14:50:09 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=66) -Patch fixes defect and allows invoices to be created correctly - - - - jonesde - 2004-05-03 23:03:12 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - jonesde - 2004-05-27 23:33:55 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-05-27 23:33:55 - resolution - Resolution - - FIXED - - - - 138 - RESOLVED - P3 - WORKSFORME - Components - CVS - All - issues@ofbiz - 20040713022331 - Manufacturing - sichen - not determined - DEFECT - 2004-05-04 17:45:50 - issues@ofbiz - - - - Windows XP - Null delegator in FindProductRun - - - sichen - 2004-05-04 17:45:50 - I am getting a -4269781[ VisitHandler.java:130:ERROR] Could not find delegator with -delegatorName [null] in session, not creating Visit entity - -Is this a Windows problem or a bug? - -Thanks, - -Si Chen - - - sichen - 2004-05-04 17:46:33 - Created an attachment (id=67) -error log from running FindProductRun in Manufacturing - - - - jacopo - 2004-07-13 02:23:31 - I couldn't recreate this error. -However, from the log it seems something related to the Visit stuff. - - - text/plain - 67 - 2004-05-04 17:46:33 - error log from running FindProductRun in Manufacturing - - findproductrun.log - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/67/findproductrun.log - - - sichen - 2004-05-04 17:46:33 - attachments.thedata - Attachment Data - - Created an attachment (id=67) -error log from running FindProductRun in Manufacturing - - - - jacopo - 2004-07-13 02:23:31 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-13 02:23:31 - resolution - Resolution - - WORKSFORME - - - - 139 - NEW - P3 - - Components - CVS - All - david - 20040509064322 - E-Commerce - arukala - not determined - FEATURE - 2004-05-09 06:43:22 - issues@ofbiz - - - - All - Reading UiLable Properties in Email templates - - - arukala - 2004-05-09 06:43:22 - Hallo David, - -We are looking for your suggestions. on how should i call the UiLabel -Properties in eCommerce Email Templates. we are eager to see this feature in -email Confirmation after placing an order for customers?. suggest us how to? - - - - 140 - RESOLVED - P3 - FIXED - Components - CVS - All - jacopo - 20040518040000 - Manufacturing - jacopo - not determined - ENHANCEMENT - 2004-05-11 08:26:52 - issues@ofbiz - - - - All - Remove all the checks against the isVariant field. - - - jacopo - 2004-05-11 08:26:52 - Remove all the checks against the isVariant field: the best way to see if a -product is variant is to check the ProductAssoc entity. - - - jacopo - 2004-05-18 04:00:00 - Committed with the last changes a few days ago. - - - jacopo - 2004-05-18 04:00:00 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-05-18 04:00:00 - resolution - Resolution - - FIXED - - - - 141 - RESOLVED - P3 - DUPLICATE - Components - CVS - All - issues@ofbiz - 20040526104821 - Accounting - jacopo - not determined - PATCH - 2004-05-26 09:01:42 - issues@ofbiz - - - - All - Patch for bug in invoice creation when terms are specified for a billing account. - - - 137 - jacopo - 2004-05-26 10:48:21 - - - jacopo - 2004-05-26 09:01:42 - Patch for bug in invoice creation when terms are specified for billing account: -A wrong field name was used. -Also a non-null field was not set. - - - jacopo - 2004-05-26 09:02:49 - Created an attachment (id=68) -The patch file in UOF - - - - jacopo - 2004-05-26 10:48:21 - Ok, Si Chen had already fixed this!!! - -*** This issue has been marked as a duplicate of 137 *** - - - text/plain - 68 - 2004-05-26 09:02:49 - The patch file in UOF - 1 - InvoiceServices.java.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/68/InvoiceServices.java.patch - - - jacopo - 2004-05-26 09:02:49 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=68) -The patch file in UOF - - - - jacopo - 2004-05-26 10:48:21 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-05-26 10:48:21 - resolution - Resolution - - DUPLICATE - - - - 142 - RESOLVED - P3 - FIXED - Components - CVS - PC - ajzeneski - 20040630194530 - Party - jackhung - not determined - DEFECT - 2004-06-15 03:33:20 - issues@ofbiz - - - - Linux - Party Profile [New Communication] throws exception - - - jackhung - 2004-06-15 03:33:20 - Error: The application script threw an exception: Sourced file: -/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh -: null : at Line: 47 : in file: -/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh -: party .getRelatedOne ( "Person" ) Target exception: -java.lang.NullPointerException: Null Pointer in Method Invocation BSF info: -/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh -at line: 0 column: 0 - - -URL: https://jhpc:18443/partymgr/control/viewCommunicationEvent?partyIdFrom=ltdadmin - -partyId = request.getParameter("party_id"); -... -party = delegator.findByPrimaryKey("Party", UtilMisc.toMap("partyId", partyId)); -context.put("party", party); -context.put("lookupPerson", party.getRelatedOne("Person")); <--- - - - ajzeneski - 2004-06-30 19:45:30 - This has been fixed in CVS - - - jonesde - 2004-06-15 03:39:27 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-06-30 19:45:30 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:45:30 - resolution - Resolution - - FIXED - - - - 143 - NEW - P3 - - Components - CVS - All - ajzeneski - 20040630194322 - Order - sichen - not determined - FEATURE - 2004-06-17 10:51:48 - issues@ofbiz - - - - All - Allows orders to have shipBeforeDate and shipAfterDate - - - sichen - 2004-06-17 10:51:48 - Changed ShoppingCart.java and CheckoutHelper.java to allow ship before and -after dates to be set using the OrderShipmentPreference entity. -OrderServices.java is modified as well to allow these dates to go on the order -confirmation email. - - - sichen - 2004-06-17 10:53:16 - Created an attachment (id=69) -Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java, - - - - text/plain - 69 - 2004-06-17 10:53:16 - Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java, - 1 - order_dating_patch.txt - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/69/order_dating_patch.txt - - - sichen - 2004-06-17 10:53:16 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=69) -Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java, - - - - ajzeneski - 2004-06-30 19:43:22 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - ajzeneski - 2004-06-30 19:43:22 - short_desc - Summary - Allows orders to have shipBeforeDate and shipAfterDate - Allows orders to have shipBeforeDate and shipAfterDate - - - - 144 - RESOLVED - P3 - WORKSFORME - Base - CVS - PC - issues@ofbiz - 20040630194017 - Base - jackhung - not determined - DEFECT - 2004-06-18 02:57:10 - issues@ofbiz - - - - Linux - https connection broke Mozilla 1.3 and 1.4 - - - jackhung - 2004-06-18 02:57:10 - I'm getting a strange problem lately (2 days). I'm at the ecommerce's main page -and try to [Login] (url -https://www.myhost.net:8443/ecommerce/control/checkLogin/main). The -certification stuff comes up and I accepted it. On one of my system using -Mozilla 1.3, the browser popup a dialog saying: - "www.myhost.net has received an incorrect or unexpected message. Error Code: --12229" -For all subsequent attempt, the browser popup a dialog saying: - "The Document contains no data" -It appears that the browser is not sending any request to the server on -subsequent attempt. - -On another system using Mozilla 1.4, i did not get the "unexpected message", but -still got the "no data" one. - -I have an Crozilla 1.3a browser around (from the Mozilla SVG project). I tried -it and it works!! - -As a matter of fact, i'm having the same problem with any of the secure -components (webtools, partymgr, ...) - - - ajzeneski - 2004-06-30 19:40:17 - I cannot duplicate this issue with FireFox. It could be a bug in that version of mozilla. Is this still an -issue w/ the 1.5-1.7? - - - ajzeneski - 2004-06-30 19:40:17 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:40:17 - resolution - Resolution - - WORKSFORME - - - - 145 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040619093839 - Party - sichen - not determined - PATCH - 2004-06-18 09:57:41 - issues@ofbiz - - - - All - Fixes duplicated PartyContactMechPurposes when using updatePartyContactMech - - - sichen - 2004-06-18 09:57:41 - Fixes duplicated PartyContactMechPurposes when using updatePartyContactMech to -move a party's contact information from an old contactMechId to a -newContactMechId by checking to make sure the PartyContactMechPurpose does not -already exist. - - - sichen - 2004-06-18 09:58:34 - Created an attachment (id=70) -Patches PartyContactMechServices.xml - - - - jonesde - 2004-06-19 09:38:39 - It's in CVS now. Thanks Si. - - - text/plain - 70 - 2004-06-18 09:58:34 - Patches PartyContactMechServices.xml - 1 - PartyContactMechServices.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/70/PartyContactMechServices.patch - - - sichen - 2004-06-18 09:58:34 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=70) -Patches PartyContactMechServices.xml - - - - jonesde - 2004-06-19 09:38:39 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-06-19 09:38:39 - resolution - Resolution - - FIXED - - - - 146 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040622094557 - Party - sichen - not determined - PATCH - 2004-06-21 17:56:29 - issues@ofbiz - - - - All - Passes partyId into updatePostalAddress from updatepartyPostalAddress - - - sichen - 2004-06-21 17:56:29 - Passes partyId into updatePostalAddress from updatePartyPostalAddress, to -preserve it for updateCreditCard later. - - - sichen - 2004-06-21 17:57:02 - Created an attachment (id=71) -Passes partyId from updatePartyPostalAddress to updatePostalAddress - - - - jonesde - 2004-06-22 09:45:57 - It's in. Thanks Si Chen. - - - text/plain - 71 - 2004-06-21 17:57:02 - Passes partyId from updatePartyPostalAddress to updatePostalAddress - 1 - PartyContactMechServices.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/71/PartyContactMechServices.patch - - - sichen - 2004-06-21 17:57:02 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=71) -Passes partyId from updatePartyPostalAddress to updatePostalAddress - - - - jonesde - 2004-06-22 09:45:57 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-06-22 09:45:57 - resolution - Resolution - - FIXED - - - - 147 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040623161518 - Product - sichen - not determined - ENHANCEMENT - 2004-06-22 15:58:48 - issues@ofbiz - - - - All - Minor additions to calculateProductPrice - - - sichen - 2004-06-22 15:58:48 - Implements a "Percent of Default Price" price action for price rules and checks -both default and list prices when there is a "Promotional Price Override" price -action. - - - sichen - 2004-06-22 15:59:22 - Created an attachment (id=72) -minor additions to calculateProductPrice - - - - jonesde - 2004-06-23 16:15:18 - Okay, this patch is in. Thanks for working on this and sending it over Si. - - - text/plain - 72 - 2004-06-22 15:59:22 - minor additions to calculateProductPrice - 1 - calculateProductPrice.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/72/calculateProductPrice.patch - - - sichen - 2004-06-22 15:59:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=72) -minor additions to calculateProductPrice - - - - jonesde - 2004-06-23 16:15:18 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-06-23 16:15:18 - resolution - Resolution - - FIXED - - - - 148 - RESOLVED - P2 - WORKSFORME - Components - CVS - All - ajzeneski - 20040730233418 - Accounting - jacopo - not determined - DEFECT - 2004-06-23 05:42:27 - issues@ofbiz - - - - All - Duplicate invoices for the same order under some cicumstances. - - - jacopo - 2004-06-23 05:42:27 - With "Offline Payments", from the order detail page it is possible to -receive payments: when the payments cover the order's grand total an invoice -is generated; also when the shipment to which the order is issued changes -its status to PACKED an invoice is created: this can cause the creation -of two different invoices for the same order. - - - ajzeneski - 2004-07-30 21:11:52 - I cannot duplicate this problem; I attempted an offline order, received the payment - no invoice was -created; issued a quick ship a single invoice was created. Please provide more details. - - - jacopo - 2004-07-30 23:34:18 - I cannot believe... I have tried again and the problem is gone away. -However I'm totally sure (99%) that this was an issue... - - - - jonesde - 2004-06-23 16:16:30 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - jacopo - 2004-07-30 23:34:18 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-30 23:34:18 - resolution - Resolution - - WORKSFORME - - - - 149 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040818085225 - Order - jacopo - not determined - PATCH - 2004-06-26 01:51:16 - issues@ofbiz - - - - All - Patch for bug that happens when you try to cancel an order item. - - - jacopo - 2004-06-26 01:51:16 - In revision 1.30 of the services.xml file for the order component, the require- -new-transaction="true" was added to the resetGrandTotal service: this causes -problems when you cancel an order item because the resetGrandTotal is one of -the services that are triggered and it seems to hang up the process waiting for -a transaction (at least this happens with SAP-DB). - -The attached patch removes the require-new-transaction="true" parameter and -this solves the problem; however I don't know if this could cause other -problems in different parts of the system. - - - jacopo - 2004-06-26 01:51:58 - Created an attachment (id=73) -Patch in UOF - - - - jacopo - 2004-08-18 08:52:25 - The patch has been applied. - - - text/plain - 73 - 2004-06-26 01:51:58 - Patch in UOF - 1 - services.xml.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/73/services.xml.patch - - - jacopo - 2004-06-26 01:51:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=73) -Patch in UOF - - - - jacopo - 2004-08-18 08:52:25 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-08-18 08:52:25 - resolution - Resolution - - FIXED - - - - 150 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040630190556 - Order - jacopo - not determined - PATCH - 2004-06-26 01:56:29 - issues@ofbiz - - - - All - When you receive a purchase order the order lines are declared completed (also multiple times) even if it's not true. - - - jacopo - 2004-06-26 01:56:29 - The attached patch fixes two bugs that caused the problem. - - - jacopo - 2004-06-26 01:56:53 - Created an attachment (id=74) -Tha patch in UOF - - - - ajzeneski - 2004-06-30 19:05:56 - patch applied to CVS - - - text/plain - 74 - 2004-06-26 01:56:53 - Tha patch in UOF - 1 - OrderSimpleMethods.xml.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/74/OrderSimpleMethods.xml.patch - - - jacopo - 2004-06-26 01:56:53 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=74) -Tha patch in UOF - - - - ajzeneski - 2004-06-30 19:05:56 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:05:56 - resolution - Resolution - - FIXED - - - - 151 - RESOLVED - P3 - FIXED - Components - CVS - All - ajzeneski - 20040630224402 - Order - jacopo - not determined - PATCH - 2004-06-26 02:01:14 - issues@ofbiz - - - - All - In order entry, if no party is selected, during the checkout process some errors are generated: this patch fix the problem by disabling the checkout link if the party is missing. - - - jacopo - 2004-06-26 02:01:14 - In order entry, if no party is selected, during the checkout process some -errors are generated: this patch fix the problem by disabling the checkout link -if the party is missing. - - - jacopo - 2004-06-26 02:01:41 - Created an attachment (id=75) -Patch in UOF - - - - ajzeneski - 2004-06-30 19:19:39 - I cannot duplicate this issue; is it still a problem? - - - jacopo - 2004-06-30 22:44:02 - Hmmm, now it seems to work for me, too. -I'm wondering if something is changed during the last 10 days... I was quite -sure about this problem. -By the way, I'm going to declare resolved this issue, thanks. - - - - text/plain - 75 - 2004-06-26 02:01:41 - Patch in UOF - 1 - noparty.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/75/noparty.patch - - - jacopo - 2004-06-26 02:01:41 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=75) -Patch in UOF - - - - jacopo - 2004-06-30 22:44:02 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-06-30 22:44:02 - resolution - Resolution - - FIXED - - - - 152 - RESOLVED - P4 - LATER - Components - CVS - All - ajzeneski - 20040630192805 - Order - jacopo - not determined - PATCH - 2004-06-26 02:13:57 - issues@ofbiz - - - - All - Shipping location is missing in purchase orders: this causes problems when you try to cancel an order item. - - - jacopo - 2004-06-26 02:13:57 - In purchase order the shipping location address is not set and this causes -problems when you try to cancel order items (the shipping location is used is -some service that are triggered in this situation, such as the calcTax service -etc...). -In my opinion the best solution is to add a shipping location address to the -purchase order. -The address could be that of the facility that will receive the po. - -I have also attached a patch (not a good one, so probably you shouldn't apply -it) that fix this problem by allowing, during order entry, to select one of the -addresses of the facility that is linked to the productStore for which the -purchase order is taken: so in the checkinits page the store selection should -be enabled for purchase orders too. - - - jacopo - 2004-06-26 02:14:21 - Created an attachment (id=76) -Patch in UOF - - - - ajzeneski - 2004-06-30 19:28:05 - Sounds like there are more issues here. First off most likely tax should not be calculated for purchase -orders; nor should the same shipping charges which apply to sales orders should not apply to purchase -orders. - -I will see what I can do when working on some additional PO enhancements. - - - text/plain - 76 - 2004-06-26 02:14:20 - Patch in UOF - 1 - shipping_address.patch - 194 - jacopo - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/76/shipping_address.patch - - - jacopo - 2004-06-26 02:14:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=76) -Patch in UOF - - - - ajzeneski - 2004-06-30 19:28:05 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-06-30 19:28:05 - resolution - Resolution - - LATER - - - - 153 - NEW - P5 - - Components - CVS - All - ajzeneski - 20040707011403 - Service - eckardjf - not determined - DEFECT - 2004-07-05 12:19:00 - issues@ofbiz - - - - All - purgeOldJobs service leaves artifacts - - - eckardjf - 2004-07-05 12:19:00 - The purgeOldJobs service will remove qualifying JobSandbox entities, but will not remove the related -RuntimeData, RecurrenceInfo and RecurrenceRule entities (even if they are not referenced by an -existing WorkEffort). - - - jonesde - 2004-07-07 01:14:03 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - - 154 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040707150844 - Content - doogie - not determined - DEFECT - 2004-07-06 12:49:26 - issues@ofbiz - - - - All - Unknown import - - - doogie - 2004-07-06 12:49:26 - Region.java imports com.sun.rsasign.r. When compiling with jikes, this class is -not available. Removing the import, and the class compiles fine, so it's -obviously not needed. - - - doogie - 2004-07-06 12:49:58 - Created an attachment (id=77) -Remove the bad import - - - - jonesde - 2004-07-07 15:08:44 - This import has now been removed, not even sure why it was there in the first place... Thanks Adam. - - - text/plain - 77 - 2004-07-06 12:49:58 - Remove the bad import - 1 - Region.java.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/77/Region.java.patch - - - doogie - 2004-07-06 12:49:58 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=77) -Remove the bad import - - - - jonesde - 2004-07-07 15:08:44 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 15:08:44 - resolution - Resolution - - FIXED - - - - 155 - RESOLVED - P3 - FIXED - Base - CVS - All - issues@ofbiz - 20040707011249 - Base - doogie - not determined - DEFECT - 2004-07-06 14:27:26 - issues@ofbiz - - - - All - UtilCache does not allow for null keys - - - doogie - 2004-07-06 14:27:26 - UtilCache doesn't allow null keys to be stored. This is sub-optimal, and -actually causes problems with my enhanced entity cache code. Attached patch fixes. - - - doogie - 2004-07-06 14:28:17 - Created an attachment (id=78) -Allow for null keys - - - - jonesde - 2004-07-07 01:12:49 - This is now in CVS, thanks Adam! - - - text/plain - 78 - 2004-07-06 14:28:17 - Allow for null keys - 1 - UtilCache-null-key.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/78/UtilCache-null-key.patch - - - doogie - 2004-07-06 14:28:17 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=78) -Allow for null keys - - - - jonesde - 2004-07-07 01:12:49 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 01:12:49 - resolution - Resolution - - FIXED - - - - 156 - RESOLVED - P3 - FIXED - Base - CVS - All - issues@ofbiz - 20040707011312 - Base - doogie - not determined - ENHANCEMENT - 2004-07-06 14:30:09 - issues@ofbiz - - - - All - Allow specifying the expire time on put in UtilCache - - - doogie - 2004-07-06 14:30:09 - Add a new put method, that takes an expireTime parameter. - - - doogie - 2004-07-06 14:30:31 - Created an attachment (id=79) -The patch. - - - - jonesde - 2004-07-07 01:13:12 - This is now in CVS, thanks Adam! - - - text/plain - 79 - 2004-07-06 14:30:31 - The patch. - 1 - UtilCache-put-takes-expireTime.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/79/UtilCache-put-takes-expireTime.patch - - - doogie - 2004-07-06 14:30:31 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=79) -The patch. - - - - jonesde - 2004-07-07 01:13:12 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 01:13:12 - resolution - Resolution - - FIXED - - - - 157 - RESOLVED - P3 - FIXED - Base - CVS - All - issues@ofbiz - 20040707011225 - Base - doogie - not determined - ENHANCEMENT - 2004-07-06 14:35:33 - issues@ofbiz - - - - All - In UtilCache, allow for a list of property bases to be specified - - - doogie - 2004-07-06 14:35:33 - When a UtilCache instance is created, it currently will only look for a single -matching property value, by name. This patch allows for a list of base property -names to be specified, and the first one found will be used. - -I make use of this in my entity cache code. For instance: -== -Cache.entity-list.${delegator-name}.${entity-name}.expireTime=1800000 -Cache.entity-list.${delegator-name}.${entity-name}.maxSize=500 - -# high count, low access -# 5 minute cache time -Cache.entity-list.${delegator-name}.PartyAttribute=300000 -== - - - doogie - 2004-07-06 14:35:48 - Created an attachment (id=80) -The patch - - - - jonesde - 2004-07-07 01:12:25 - This is now in CVS, thanks Adam! - - - text/plain - 80 - 2004-07-06 14:35:48 - The patch - 1 - UtilCache-wildcard-config.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/80/UtilCache-wildcard-config.patch - - - doogie - 2004-07-06 14:35:48 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=80) -The patch - - - - jonesde - 2004-07-07 01:12:25 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 01:12:25 - resolution - Resolution - - FIXED - - - - 158 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040707011838 - Product - sichen - not determined - DEFECT - 2004-07-06 17:08:44 - issues@ofbiz - - - - All - distinct attribute for getProductFeatures is not working - - - sichen - 2004-07-06 17:08:44 - distinct attribute for getProductFeatures service does not work because it is -trying to use ProductFeatureType rather than ProductFeatureTypeId in -ProductServices.prodGetFeatures - - - sichen - 2004-07-06 17:16:51 - Created an attachment (id=81) -Corrects productFeatureType to productFeatureTypeId - - - - jonesde - 2004-07-07 01:18:38 - It's in CVS now, thanks Si! - - - text/plain - 81 - 2004-07-06 17:16:51 - Corrects productFeatureType to productFeatureTypeId - 1 - ProductServices_1.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/81/ProductServices_1.patch - - - sichen - 2004-07-06 17:16:51 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=81) -Corrects productFeatureType to productFeatureTypeId - - - - jonesde - 2004-07-07 01:18:38 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 01:18:38 - resolution - Resolution - - FIXED - - - - 159 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040707012137 - Product - sichen - not determined - ENHANCEMENT - 2004-07-06 17:26:05 - issues@ofbiz - - - - All - Adds productFeatureApplTypeId field to getProductFeatureSet service - - - sichen - 2004-07-06 17:26:05 - Adds productFeatureApplTypeId as optional field to getProductFeatureSet service. - If none is specified, it will still search for "SELECTABLE_FEATURE"s (to be -compatible with existing code), but if one is specified, it will use that -productFeatureApplTypeId, so the same service can now be used to search for -STANDARD, DISTINGUISHING, OPTIONAL features. - - - sichen - 2004-07-06 17:27:49 - Created an attachment (id=82) -Extends getProductFeatures with optional productFeatureApplTypeId field - - - - jonesde - 2004-07-07 01:21:37 - It's in CVS now, thanks Si! - - - text/plain - 82 - 2004-07-06 17:27:49 - Extends getProductFeatures with optional productFeatureApplTypeId field - 1 - ProductServices_2.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/82/ProductServices_2.patch - - - sichen - 2004-07-06 17:27:49 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=82) -Extends getProductFeatures with optional productFeatureApplTypeId field - - - - jonesde - 2004-07-07 01:21:37 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 01:21:37 - resolution - Resolution - - FIXED - - - - 160 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040707144701 - Entity Extensions - doogie - not determined - ENHANCEMENT - 2004-07-07 07:27:45 - issues@ofbiz - - - - All - implement condition versions of functions in entityext - - - doogie - 2004-07-07 07:27:45 - I had sent an earlier version of this patch to the mailing list. I'm now adding -it as an issue, as I have for all the other patches. - - - doogie - 2004-07-07 07:28:22 - Created an attachment (id=83) -The patch - - - - jonesde - 2004-07-07 14:47:01 - This is now in CVS. Thanks Adam! - - - text/plain - 83 - 2004-07-07 07:28:22 - The patch - 1 - cache-entityext.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/83/cache-entityext.patch - - - doogie - 2004-07-07 07:28:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=83) -The patch - - - - jonesde - 2004-07-07 14:47:01 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-07 14:47:01 - resolution - Resolution - - FIXED - - - - 161 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040708153407 - WebTools - doogie - not determined - DEFECT - 2004-07-08 11:51:01 - issues@ofbiz - - - - All - NPE in FindUtilCacheElements.jsp - - - doogie - 2004-07-08 11:51:01 - Missed one NPE when key is null(calls key.toString()). - - - doogie - 2004-07-08 11:51:22 - Created an attachment (id=84) -The patch - - - - jonesde - 2004-07-08 15:34:07 - Thanks Adam, it is now in CVS. - - - text/plain - 84 - 2004-07-08 11:51:22 - The patch - 1 - FindUtilCacheElements.jsp.patch - 270 - doogie - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/84/FindUtilCacheElements.jsp.patch - - - doogie - 2004-07-08 11:51:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=84) -The patch - - - - jonesde - 2004-07-08 15:34:07 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-08 15:34:07 - resolution - Resolution - - FIXED - - - - 162 - RESOLVED - P3 - WORKSFORME - Components - CVS - All - issues@ofbiz - 20040713170819 - Workflow - ktippetts - not determined - DEFECT - 2004-07-12 09:32:42 - issues@ofbiz - - - - Linux - NoSuchMethodError in Entity Data Maintenance - - - ktippetts - 2004-07-12 09:32:42 - Getting this error when trying to view entity data in Webtools | Entity Data -Maintenance: - -<snip> -Exception: java.lang.NoSuchMethodError -Message: -org.ofbiz.entity.condition.EntityFieldMap.<init>(Ljava/util/Map;Lorg/ofbiz/entity/condition/EntityOperator;)V ------ stack trace ---------------------------------------- -java.lang.NoSuchMethodError: -org.ofbiz.entity.condition.EntityFieldMap.<init>(Ljava/util/Map;Lorg/ofbiz/entity/condition/EntityOperator;)V -org.apache.jsp.entity.FindGeneric_jsp._jspService(FindGeneric_jsp.java:159) -<snip> - -To duplicate Using CVS code as of 09Jul2004: -* Webtools > Entity Data Maintenance -* Click 'All' on any entity. - -Possible Solution: -* in FindGeneric.jsp (line 94) change 2nd parameter to EntityJoinOperator.AND - - - jonesde - 2004-07-12 20:41:10 - This works fine from a clean compile, but if have partial old code and partial new code in a build it may -have problems. Try an "ant clean" and then an "ant". - - - doogie - 2004-07-13 17:08:19 - The signature of the constructor changed. It used to take an EntityOperator. -However, the code only accepted an EntityJoinOperator. Passing in an -EntityComparisonOperator would have caused it to fail. - -Also, running ant clean will *not* fix the problem. The parsed/compiled jsp -pages need to be cleaned out. - - - jonesde - 2004-07-12 20:41:10 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-07-12 20:41:10 - resolution - Resolution - - WORKSFORME - - - - 163 - RESOLVED - P3 - INVALID - Documentation - CVS - All - issues@ofbiz - 20040730150851 - website - michaelrempel - not determined - TASK - 2004-07-13 11:11:43 - issues@ofbiz - - - - All - cant get csv instructions - - - michaelrempel - 2004-07-13 11:11:43 - When I pull up csv instructions for either the wincsv or command line, I get a -logon request screen, even though I am logged on. - -Thx - -Michael Rempel - - - ajzeneski - 2004-07-30 15:08:51 - This is a java.net related issue not OFBiz; please contact the Java.Net team for help. - - - ajzeneski - 2004-07-30 15:08:51 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 15:08:51 - resolution - Resolution - - INVALID - - - - 164 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040730204811 - Security - adrianc - not determined - DEFECT - 2004-07-14 12:24:23 - issues@ofbiz - - - - All - SecurityData.xml File - - - adrianc - 2004-07-14 12:24:23 - From mailing list: - -On Jul 14, 2004, at 12:03 PM, Adrian Crum wrote: - -> I was just wondering... -> -> Why is the security data for ALL components in the SecurityData.xml file? This -file looks monolithic. Shouldn't each component load its own security data? -> -> -Adrian - - -Adrian, - -Yes, good point, monolithic is a good word for this. Ideally it should be split -up, I think that's a good idea. - -If anyone wants to work on this please do... In the mean time it might be a good -idea to create an issue for it. - --David - - - ajzeneski - 2004-07-30 20:48:11 - applied patch file(s); now in CVS - - - ajzeneski - 2004-07-30 20:48:11 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 20:48:11 - resolution - Resolution - - FIXED - - - - 165 - RESOLVED - P4 - FIXED - Components - CVS - All - ajzeneski - 20040730065021 - Order - pgoron - not determined - PATCH - 2004-07-15 06:34:37 - issues@ofbiz - - - - All - Allow user to specify default value for desired delivery date and comment fields in order entry GUI - - - pgoron - 2004-07-15 06:34:37 - This patch allows user to define default desired delivery date and default -comment during quickaddform filling in OrderEntry page. Thus, users are not -obliged any more to reinput these informations for each order item. - - - pgoron - 2004-07-15 06:35:35 - Created an attachment (id=85) -The patch - - - - jacopo - 2004-07-30 06:50:21 - The patch is in CVS. - - - text/plain - 85 - 2004-07-15 06:35:35 - The patch - 1 - order20040707.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/85/order20040707.patch - - - pgoron - 2004-07-15 06:35:35 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=85) -The patch - - - - jonesde - 2004-07-15 16:16:54 - assigned_to - Assigned To - issues@ofbiz - ajzeneski - - - jonesde - 2004-07-15 16:16:54 - issue_type - Issue Type - ENHANCEMENT - PATCH - - - jacopo - 2004-07-30 06:50:21 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-30 06:50:21 - resolution - Resolution - - FIXED - - - - 166 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040730115233 - Order - pgoron - not determined - PATCH - 2004-07-21 02:46:56 - issues@ofbiz - - - - All - Allow user to associate parties to an order in OrderEntry website - - - pgoron - 2004-07-21 02:46:56 - Hi, - -Currently, I did not found any way to associate additional parties to an order. -That's why I've written this enhancement patch. - - -This patch adds a new step during order entry in which user can associate -additional party&role to order. Then, these informations are stored in OrderRole -entity. - - -List of modifications : -- I've written a new view in which user can select a party and party's role to -associate to order -+ webapp/ordermgr/entry/SetAdditionalParty.ftl -+ webapp/ordermgr/WEB-INF/actions/entry/SetAdditionalParty.bsh -+ webapp/ordermgr/WEB-INF/pagedefs/entry/SetAdditionalParty.xml -+ webapp/ordermgr/entry/AdditionalPartyListing.ftl -+ webapp/ordermgr/WEB-INF/actions/entry/AdditionalPartyListing.bsh -+ webapp/ordermgr/entry/PartySettingsForm.xml -M webapp/ordermgr/WEB-INF/controller.xml - -- I've included list of additional parties associated to order in confimorder view -M webapp/ordermgr/entry/confirmorder.ftl -M webapp/ordermgr/WEB-INF/pagedefs/entry/confirmorder.xml - -- I've modified these files so that my view is shown before order confirmation -M src/org/ofbiz/order/shoppingcart/CheckOutEvents.java -M webapp/ordermgr/entry/showcart.ftl - -- I've modified storeOrder service and ShoppingCart to take in account -additional parties. -M servicedef/services.xml -M src/org/ofbiz/order/order/OrderServices.java -M src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java -M src/org/ofbiz/order/shoppingcart/ShoppingCart.java - -- I've copied some files from content module to be able to use GenericLookup. -+ src/org/ofbiz/order/lookupParams.java -+ webapp/ordermgr/lookup/FieldLookupForms.xml -+ webapp/ordermgr/lookup/GenericLookup.ftl -+ webapp/ordermgr/templates/lookup.ftl -+ webapp/ordermgr/templates/lookup.xml -+ webapp/ordermgr/WEB-INF/actions/includes/findprepLk.bsh -+ webapp/ordermgr/WEB-INF/actions/includes/formprep.bsh -+ webapp/ordermgr/WEB-INF/actions/includes/pagelistprepLk.bsh -+ webapp/ordermgr/WEB-INF/pagedefs/lookup/GenericLookup.xml - - - pgoron - 2004-07-21 02:47:42 - Created an attachment (id=86) -The patch - - - - pgoron - 2004-07-22 00:38:39 - I've found some minor mistakes. I am correcting them and I will send a new patch -as soon as possible. - - - pgoron - 2004-07-22 01:29:07 - Created an attachment (id=87) -The corrected patch - - - - jacopo - 2004-07-30 11:52:33 - The patches are in CVS. - - - text/plain - 86 - 2004-07-21 02:47:42 - The patch - 1 - order20040721.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/86/order20040721.patch - - - text/plain - 87 - 2004-07-22 01:29:07 - The corrected patch - 1 - order20040722.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/87/order20040722.patch - - - pgoron - 2004-07-21 02:47:42 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=86) -The patch - - - - pgoron - 2004-07-22 01:29:07 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=87) -The corrected patch - - - - jacopo - 2004-07-30 11:52:33 - issue_status - Status - NEW - RESOLVED - - - jacopo - 2004-07-30 11:52:33 - resolution - Resolution - - FIXED - - - - 167 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040730145814 - Accounting - sichen - not determined - PATCH - 2004-07-28 17:15:09 - issues@ofbiz - - - - All - Fixes a couple of other getNextSeqId methods - - - sichen - 2004-07-28 17:15:09 - getNextSeqId now returns a string(), so .toString() is no longer needed and will -cause runtime exceptions. - - - sichen - 2004-07-28 17:19:29 - Created an attachment (id=88) -Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine - - - - ajzeneski - 2004-07-30 14:58:14 - patch applied - - - text/plain - 88 - 2004-07-28 17:19:29 - Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine - 1 - changes.txt - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/88/changes.txt - - - sichen - 2004-07-28 17:19:29 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=88) -Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine - - - - ajzeneski - 2004-07-30 14:58:14 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 14:58:14 - resolution - Resolution - - FIXED - - - - 168 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040730144804 - Content - pgoron - not determined - PATCH - 2004-07-29 02:43:55 - issues@ofbiz - - - - All - FreeMarker localization issues - - - pgoron - 2004-07-29 02:43:55 - Hi, - -This patch resolves some localization issues. Currently, FreeMarker formats -number according to the machine's locale. My patch forces FreeMarker to use the -user session's locale. - -It must be applied in ofbiz/components/content/src/org/ofbiz/content/webapp/ftl -folder. - - - pgoron - 2004-07-29 02:45:19 - Created an attachment (id=89) -The patch - - - - ajzeneski - 2004-07-30 14:48:04 - This has been fixed in CVS - - - text/plain - 89 - 2004-07-29 02:45:19 - The patch - 1 - locale-freemaker-200040727.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/89/locale-freemaker-200040727.patch - - - pgoron - 2004-07-29 02:45:19 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=89) -The patch - - - - ajzeneski - 2004-07-30 14:48:04 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 14:48:04 - resolution - Resolution - - FIXED - - - - 169 - RESOLVED - P3 - FIXED - Components - CVS - PC - issues@ofbiz - 20040730220642 - E-Commerce - amheiss - not determined - DEFECT - 2004-07-30 09:53:11 - issues@ofbiz - - https://localhost:8443/ecommerce/control/finalizeOrder - - Linux - Party/Userlogin issues - - - amheiss - 2004-07-30 09:53:11 - Application will not allow run of createPartyPostalAddress (due to null user -login?). Sequence of events from july 30th, 11am build: goto ecommerce, -login, then logout. attempt to use anonymous checkout after this, and shipping -address feilds prepopulated with previous logins settings. After adjusting and -trying to save, get error 'User authorization is required for this service: -createPartyPostalAddress ' . - -Debug output from shipsettings.bsh: -Debug.log("party ID : " + partyId); ---> output admin ( i logged in as admin, -then logged out) -Debug.log("ul: " + session.getAttribute("userLogin")); ---> (null) - - - ajzeneski - 2004-07-30 22:06:42 - Yes, if there is an autoUserLogin attribute available that will break anonymous checkout. In theory, the -anonymous checkout links should not be displayed if there is an auto-userlogin. However, I have added -some code to clear this when entering the anonymous checkout process. - - - ajzeneski - 2004-07-30 22:06:42 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-07-30 22:06:42 - resolution - Resolution - - FIXED - - - - 170 - RESOLVED - P3 - FIXED - Components - CVS - All - issues@ofbiz - 20040804093020 - Product - sichen - not determined - ENHANCEMENT - 2004-08-03 17:02:41 - issues@ofbiz - - - - All - Optionally duplicates ProductContent when duplicating a Product - - - sichen - 2004-08-03 17:02:41 - Will now optionally duplicate ProductContent entries when duplicating a Product - - - sichen - 2004-08-03 17:03:19 - Created an attachment (id=90) -Patches services.xml, EditProduct.ftl, and ProductServices.xml - - - - jonesde - 2004-08-04 09:30:20 - Thanks Si. This is now in CVS. I also did a content remove option, and fixed an issue I noticed with the -product IDs (GoodIdentification). BTW, this is from a slightly earlier version of OFBiz than the current -CVS as this form has been moved to the file EditProductDupForm.ftl. - - - text/plain - 90 - 2004-08-03 17:03:19 - Patches services.xml, EditProduct.ftl, and ProductServices.xml - 1 - duplicateProduct.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/90/duplicateProduct.patch - - - sichen - 2004-08-03 17:03:19 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=90) -Patches services.xml, EditProduct.ftl, and ProductServices.xml - - - - jonesde - 2004-08-04 09:30:20 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-04 09:30:20 - resolution - Resolution - - FIXED - - - - 171 - RESOLVED - P2 - FIXED - Components - CVS - All - issues@ofbiz - 20040804091929 - Product - pgoron - not determined - PATCH - 2004-08-04 00:59:53 - issues@ofbiz - - - - All - Comparaison bug in InventoryServices.xml minilang script - - - pgoron - 2004-08-04 00:59:53 - Some if-compare element forget to declare type used to compare fields. By -default, string comparison is used whereas Double is required. - - -Applying patch : -cd /ofbiz/components/product/script/org/ofbiz/product/inventory -patch -p0 < InventoryServices.xml.patch - - - pgoron - 2004-08-04 01:01:13 - Created an attachment (id=91) -The patch - - - - jonesde - 2004-08-04 09:19:29 - Thanks, it's now in CVS. - - - text/plain - 91 - 2004-08-04 01:01:13 - The patch - 1 - InventoryServices.xml.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/91/InventoryServices.xml.patch - - - pgoron - 2004-08-04 01:01:13 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=91) -The patch - - - - jonesde - 2004-08-04 09:19:29 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-04 09:19:29 - resolution - Resolution - - FIXED - - - - 172 - NEW - P2 - - Components - CVS - All - issues@ofbiz - 20040819033400 - Order - pgoron - not determined - PATCH - 2004-08-05 07:09:49 - issues@ofbiz - - - - All - Bug in shippableWeight calculation from OrderReadHelper.getShippableWeight method - - - pgoron - 2004-08-05 07:09:49 - Hi, - -The purpose of this patch is to solve a bug in -OrderReadHelper.getShippableWeight method. The algorithm of shippable weight -calculation don't care of order item's quantity. So there is an inconsistency -with ShoppingCart.getShippableWeight method when order is modified after his -creation (for example, by RecalcShippingTotal service). - -Applying patch: -cd ofbiz/components/order/src/org/ofbiz/order/order -patch -p0 < OrderReadHelper-20040805.patch - -Peter Goron - - - pgoron - 2004-08-05 07:10:36 - Created an attachment (id=92) -The patch - - - - pgoron - 2004-08-19 03:34:00 - Created an attachment (id=96) -An up to date patch - - - - text/plain - 92 - 2004-08-05 07:10:36 - The patch - 1 - OrderReadHelper-20040805.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/92/OrderReadHelper-20040805.patch - - - text/plain - 96 - 2004-08-19 03:34:00 - An up to date patch - 1 - OrderReadHelper-200408019.patch - 392 - pgoron - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/96/OrderReadHelper-200408019.patch - - - pgoron - 2004-08-05 07:10:36 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=92) -The patch - - - - pgoron - 2004-08-19 03:34:00 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=96) -An up to date patch - - - - - 173 - RESOLVED - P3 - INVALID - Base - CVS - PC - issues@ofbiz - 20040809165336 - Startup - mn - not determined - PATCH - 2004-08-09 13:38:08 - issues@ofbiz - - - - Linux - typo in base/config/debug.properties - - - mn - 2004-08-09 13:38:08 - Index: base/config/debug.properties -=================================================================== -RCS file: /cvs/ofbiz/base/config/debug.properties,v -retrieving revision 1.10 -diff -u -r1.10 debug.properties ---- base/config/debug.properties 9 Jun 2004 18:12:59 -0000 1.10 -+++ base/config/debug.properties 9 Aug 2004 19:32:33 -0000 -@@ -7,7 +7,7 @@ - pack.exception=true - - # These top level switches are used before calling Log4J, or if Log4J is not used --print.verbose=ftrue -+print.verbose=true - print.timing=true - print.info=true - print.important=true - - - mn - 2004-08-09 13:40:09 - Created an attachment (id=93) -corerct typo for print.verbose property - - - - jonesde - 2004-08-09 16:25:29 - In this case "ftrue" is not a misspelling of "true", we add the "f" before "true" so that it is easier to switch -between true and false than it would be to type out "true" and "false". In other words, anything but -"true" is false. - - - mn - 2004-08-09 16:53:36 - What about placing comment into debug.properties about this decision? - - - text/plain - 93 - 2004-08-09 13:40:09 - corerct typo for print.verbose property - 1 - debug.properties.patch - 377 - mn - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/93/debug.properties.patch - - - mn - 2004-08-09 13:40:09 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=93) -corerct typo for print.verbose property - - - - jonesde - 2004-08-09 16:25:29 - issue_status - Status - NEW - RESOLVED - - - jonesde - 2004-08-09 16:25:29 - resolution - Resolution - - INVALID - - - - 174 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040810161004 - Accounting - amheiss - not determined - PATCH - 2004-08-10 16:08:36 - issues@ofbiz - - - - All - retry failed auths fix - - - amheiss - 2004-08-10 16:08:36 - retryFailedAuths service was creating superfluous retryFailedOrderAuth -services. I'll see if i can attach the patch to check on order status before -dispatching retryFailedOrderAuth service. If not, patch will be to dev list -soon enough. - - - amheiss - 2004-08-10 16:10:04 - Created an attachment (id=94) -Patch for retryFailedAuth fix - - - - text/plain - 94 - 2004-08-10 16:10:04 - Patch for retryFailedAuth fix - 1 - retryAuth.patch - 336 - amheiss - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/94/retryAuth.patch - - - amheiss - 2004-08-10 16:10:04 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=94) -Patch for retryFailedAuth fix - - - - - 175 - RESOLVED - P3 - FIXED - foo - unspecified - All - ajzeneski - 20040817213241 - bar - ajzeneski - milestone 1 - DEFECT - 2004-08-17 21:31:38 - ajzeneski - - - - All - bar - - - ajzeneski - 2004-08-17 21:31:38 - foo - - - ajzeneski - 2004-08-17 21:32:41 - . - - - ajzeneski - 2004-08-17 21:32:41 - issue_status - Status - NEW - RESOLVED - - - ajzeneski - 2004-08-17 21:32:41 - resolution - Resolution - - FIXED - - - - 176 - NEW - P3 - - Components - CVS - All - issues@ofbiz - 20040818174622 - Content - sichen - not determined - DEFECT - 2004-08-18 17:45:44 - issues@ofbiz - - - - All - Possible bug in renderContentAsText - - - sichen - 2004-08-18 17:45:44 - It seems that renderContentAsText is still trying to do a findByAnd on -SubContentDataResourceView with a fromDate as the orderBy, whereas -renderContentAsTextCache no longer does (it passes a null.) We got an -exception from this in ProductContentWrapper and made this change to fix it. -Is this a defect? - - - sichen - 2004-08-18 17:46:22 - Created an attachment (id=95) -Changes findByAnd of SubContentDataResourceView - - - - text/plain - 95 - 2004-08-18 17:46:22 - Changes findByAnd of SubContentDataResourceView - 1 - ContentWorker.patch - 178 - sichen - - https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/95/ContentWorker.patch - - - sichen - 2004-08-18 17:46:22 - attachments.ispatch - Attachment is Patch - - Created an attachment (id=95) -Changes findByAnd of SubContentDataResourceView - - - - - 177 - NEW - P3 - - Base - CVS - Other - issues@ofbiz - 20040910075014 - Base - lrawley - not determined - TASK - 2004-09-10 07:50:14 - issues@ofbiz - - - - Windows XP - HTTP Header needs Expires - - - lrawley - 2004-09-10 07:50:14 - Using Internet Explorer 6.0 with settings for automatically obtaining newer -versions of page. - -Images are cached and if changed are not refreshed on visits to the same page. -Pages get cached with login page because the first time a user requested they -were prompted to login first and then redirected to the page. - -This behavior is resolved if set to obtain newer versions on every visit, -however, this causes performance issues. So, automatically is the desired -browser setting. - -I would like to be able to set the EXPIRE in the HTTP header. I'm not sure -where this change needs to occur. Can you assist? Is this available in 3.0? -I am using 2.1.1. - -Please contact me at lrawley@tla.com. - -Lisa Rawley - - - diff --git a/ruby/test/rexml/data/pi.xml b/ruby/test/rexml/data/pi.xml deleted file mode 100644 index 980bbf98e..000000000 --- a/ruby/test/rexml/data/pi.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/ruby/test/rexml/data/pi2.xml b/ruby/test/rexml/data/pi2.xml deleted file mode 100644 index 46bce4505..000000000 --- a/ruby/test/rexml/data/pi2.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - foo - - bar - diff --git a/ruby/test/rexml/data/project.xml b/ruby/test/rexml/data/project.xml deleted file mode 100644 index a02582fde..000000000 --- a/ruby/test/rexml/data/project.xml +++ /dev/null @@ -1 +0,0 @@ -tool testing diff --git a/ruby/test/rexml/data/simple.xml b/ruby/test/rexml/data/simple.xml deleted file mode 100644 index 3cff71a02..000000000 --- a/ruby/test/rexml/data/simple.xml +++ /dev/null @@ -1,2 +0,0 @@ - -abd diff --git a/ruby/test/rexml/data/stream_accents.xml b/ruby/test/rexml/data/stream_accents.xml deleted file mode 100644 index 6def54ee5..000000000 --- a/ruby/test/rexml/data/stream_accents.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/ruby/test/rexml/data/t63-1.xml b/ruby/test/rexml/data/t63-1.xml deleted file mode 100644 index f8d0c543e..000000000 Binary files a/ruby/test/rexml/data/t63-1.xml and /dev/null differ diff --git a/ruby/test/rexml/data/t63-2.svg b/ruby/test/rexml/data/t63-2.svg deleted file mode 100644 index 706c0e96b..000000000 --- a/ruby/test/rexml/data/t63-2.svg +++ /dev/null @@ -1,2828 +0,0 @@ -ÿþ - - - - - - - - - - - - - - - - - - - - - - - - SYMBOL 640 - - OFF - - - - SYMBOL 642 - - NORMAL - - - - SYMBOL 643 - - ARMED - - - - SYMBOL 644 - - ALARM - - - - SYMBOL 646 - - FAILED - - - - SYMBOL 652 - - ON - - - - SYMBOL 660 - - AUTO - - - - SYMBOL 675 - - MARGINAL - - - - SYMBOL 835 - - TRIPPED - - - - SYMBOL 922 - - MANUAL - - - - Select - - S - - - - Unack - - U - - - - Alarm - - A - - - - Deact - - D - - - - Alinh - - I - - - - Telem - - E - - - - Manual - - M - - - - TagInfo - - I - - - - - - - - TagCtl - - - - - - N - - - - TagCls - - - - - - H - - - - TagOpn - - O - - - - - - - - RDV - - R - - - - Gmerr - - G - - - - Limovr - - O - - - - Limit1 - - 1 - - - - Kimit2 - - 2 - - - - Limit3 - - 3 - - - - - - - - - - - - - 03/16/06 ADDED DFK 6 -- K. POPE - - - - - 01/05/05 FIXED DFK'S -- K. POPE - - - - - 10/14/04 CHANGED ACRONYM FOR REG CONTROL TO MANUAL / AUTO -- O. WAHLSTROM - - - - - 12/24/03 DISPLAY BUILT AND DATA ADDED -- K. POPE - - - - - 01/06/04 DISPLAY CORRECTED PER R. MCCORMICK -- N. FISHER - - - - - 03/18/04 DISPLAY UPDATED/DFK'S FIXED/APPENDED SYMBOLS MOVED -- T. TURNER - - - - - 03/29/04 REVIEWED -- O. WAHLSTROM - - - - - 05/11/04 RTU BOX FIXED AND DISPLAY UPDATED -- K. POPE - - - - - 10/18/05 REMOVED BUS VOLT MAXIMUM ALARM -- K. POPE - - - - - - - 118TH SOUTH (118TH-SO) - - - - - - - - - - - Salt Lake County, Utah - - - - - - - - - - - REG 1 AUTOMATIC (C) - - - - - To control regulator, right click on the tap position - - - - - indication and select the regulation option. - - - - - XFMR 1 TEMPERATURE - - - - - XFMR 1 NITROGEN CYL LOW - - - - - XFMR 1 LOW OIL LEVEL - - - - - XFMR 1 NITROGEN PRESSURE - - - - - XFMR 1 PRESSURE FAULT - - - - - XFMR 1 LTC CONTROL LOSS - - - - - RELAY LOSS OF AC - - - - - STATION SERVICE - - - - - XFMR 1 LTC FAIL - - - - - XFMR 1 WINDING TEMP TRIP - - - - - XFMR 1 LOCKOUT - - - - - CONTROL SYSTEM FAIL - - - - - UNDER FREQ TRIP RELAY - - - - - CB LOW SPRING CHARGE - - - - - RELAY FAILURE - - - - - CAP 1 VOLT CONTROL (C) - - - - - HMI PLC STALLED - - - - - XFMR 1 LTC FILTER - - - - - CONTROL SYSTEM NON CRITICAL - - - - - Station Alarms - - - - - Regulator 1 Control and Tap Position - - - - - REG 1 TAP POSITION - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1234.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1234.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1234.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 - - - 12 - - - 8 - - - 4 - - - 0 - - - -4 - - - -8 - - - -12 - - - -16 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REG 1 12KV BUS VOLTS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RTU STATUS: - - - - - - - - - - - - - - - RTU COMMUNICATIONS: - - - - - ENTRY - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RTU - 481 - - - - diff --git a/ruby/test/rexml/data/t75.xml b/ruby/test/rexml/data/t75.xml deleted file mode 100644 index eb3cccee4..000000000 --- a/ruby/test/rexml/data/t75.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - ]> - - -Next_Actions - @class - @agenda - this is something I'd like to do - - @dorm - clean room - - @computer - Write general makefile for cs projects - Set up bash podder - - @errands - Purchase geo lab book - - @dublin - -projects - diff --git a/ruby/test/rexml/data/test/tests.xml b/ruby/test/rexml/data/test/tests.xml deleted file mode 100644 index cf03b42b0..000000000 --- a/ruby/test/rexml/data/test/tests.xml +++ /dev/null @@ -1,683 +0,0 @@ - - - - - - - span - - - - - - - - - - - - - - abd - - - abd - - - a - - - d - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 2 - 1 - 2 - - - - - - - true - true - - - - - - true - true - true - true - true - true - - - - - - - true - true - true - true - - - 0 - - 1 - - 3 - - false - - false - - false - - false - - true - - true - - - - - - - - - - - - order-by="x" - foo - order-by="x" - - - - - - foobar - - - - - - - - - - - - - - - - - - - - - - - - is tasty - - - - - - - - - - - - - - - - - - - - - true - true - false - true - true - false - - - - - - - - - - - - - - - - - - - - - - a.2 - a.1 - - - - a.4 - a.5 - - - - - - - - - snoop - snoop - file - file - - - - snoop - snoop - - - - - - - - - - - - - - - - - - - - web-app - - - - - - web-app - - - web-app - - - web-app - - - web-app - - - web-app - - - - - - - - - - - - - web-app - web-app - web-app - web-app - web-app - web-app - web-app - web-app - web-app - - - - - - - - - - - web-app - web-app - web-app - web-app - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://c.moreover.com/click/here.pl?x13563273 - - - http://c.moreover.com/click/here.pl?x13563273 - - - http://c.moreover.com/click/here.pl?x13563273 - - - http://c.moreover.com/click/here.pl?x13563273 - - - http://c.moreover.com/click/here.pl?x13563273 - - - http://c.moreover.com/click/here.pl?x13563273 - - - - - - - - - - - - - - - - - - - - - - - - - - - - 196417 - 325 - 1 - 75025 - 46368 - - - - - - - - - - - - - - - - - - - - 2 - - 2 - - - - - - - - - - - - - - Much Ado about Nothing - 4 - 21 - 5 - 35 - 75 - - - - - - - 646 - 142 - 2 - 1 - 3 - 1 - 6 - - - - 5 - - - - - - - - - - - - - - - - - - snoop - snoop - - snoop - - - - 3foo3 - 3snoop3 - - - - - - Pruefgebiete - Pruefgebiete - - - - - - - - ab - ba - ba - db - - - - - - abcd - abcd - abcd - dcba - ab - cd - xy - abcd - abcd - - - - 234 - 12 - - - 12345 - - 345 - 12345 - - - - - - abc - a b c - a b c - - - - - - - - - - - - - SNOOPSERVLET - snoopservlet - SNOOPSERVLET - SNOOPSERVLET - SNOOPSERVLET - true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Hello - Hey - Hey3 - Hey3 - Hey3 - - - - - - - - - - - - - - - - - - baz - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ruby/test/rexml/data/test/tests.xsl b/ruby/test/rexml/data/test/tests.xsl deleted file mode 100644 index 3ecd648b3..000000000 --- a/ruby/test/rexml/data/test/tests.xsl +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/ruby/test/rexml/data/testNamespaces.xml b/ruby/test/rexml/data/testNamespaces.xml deleted file mode 100644 index 50f7c9306..000000000 --- a/ruby/test/rexml/data/testNamespaces.xml +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/ruby/test/rexml/data/testsrc.xml b/ruby/test/rexml/data/testsrc.xml deleted file mode 100644 index 9c7a78212..000000000 --- a/ruby/test/rexml/data/testsrc.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - xmlhack - http://www.xmlhack.com - Developer news from the XML community - en-us - Copyright 1999-2001, xmlhack team. - editor@xmlhack.com - webmaster@xmlhack.com - - xmlhack - http://www.xmlhack.com/images/mynetscape88.gif - http://www.xmlhack.com - 88 - 31 - News, opinions, tips and issues concerning XML development - - -Experimental non-XML syntax for RELAX NG -http://www.xmlhack.com/read.php?item=1343 - - James Clark has announced the release of an experimental non-XML syntax for RELAX - NG and a Java translator implementation that converts - instances of the syntax into RELAX NG's XML syntax. - -Schemas - - -Long-awaited entity-resolver Java classes finally released -http://www.xmlhack.com/read.php?item=1342 -Norman Walsh has - announced the release of SAX entityResolver() and JAXP - URIResolver() Java - classes he wrote to implement the OASIS XML Catalogs - Committee Specification (in addition to the TR9401 and - Apache XCatalogs specifications). - -SGML/XML -Java - - - -Beepcore-C framework released -http://www.xmlhack.com/read.php?item=1341 -Invisible Worlds have announced the publication of Beepcore-C, an implementation of the BEEP framework written in C. -Protocols -C++ - - -SVG and XSL-FO by example -http://www.xmlhack.com/read.php?item=1340 -Jirka Jirat has announced the -addition of an XSL-FO and SVG examples repository to the Zvon developer -reference site. -SVG -XSL-FO - - - - - diff --git a/ruby/test/rexml/data/text.xml b/ruby/test/rexml/data/text.xml deleted file mode 100644 index e1865c797..000000000 --- a/ruby/test/rexml/data/text.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - baz - - baz - - baz - - diff --git a/ruby/test/rexml/data/ticket_61.xml b/ruby/test/rexml/data/ticket_61.xml deleted file mode 100644 index 4df1cc9b8..000000000 --- a/ruby/test/rexml/data/ticket_61.xml +++ /dev/null @@ -1,4 +0,0 @@ - - -



      List Matters

      Open  | Closed  | All
      Open Matters











      - diff --git a/ruby/test/rexml/data/ticket_68.xml b/ruby/test/rexml/data/ticket_68.xml deleted file mode 100644 index 7ab34b08c..000000000 --- a/ruby/test/rexml/data/ticket_68.xml +++ /dev/null @@ -1,590 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]> - - - - - - -1000000 - -ヽ - - -ãりã‹ãˆã— - - -&n; -repetition mark in katakana -Wiederholungszeichen für Katakana -normalerweise nur in vertikaler Schreibweise verwendet -marque de la répétition dans katakana -(JF2) - - - -1000010 - -ヾ - - -ãりã‹ãˆã— - - -&n; -voiced repetition mark in katakana -stimmhaftes Wiederholungszeichen für Katakana -normalerweise nur in vertikaler Schreibweise verwendet -marque de la répétition sonore dans katakana -(JF2) - - - -1000020 - -ã‚ - - -ãりã‹ãˆã— - - -&n; -repetition mark in hiragana -Wiederholungszeichen für Hiragana -normalerweise nur in vertikaler Schreibweise verwendet -marque de la répétition dans hiragana -(JF2) - - - -1000030 - -ゞ - - -ãりã‹ãˆã— - - -&n; -voiced repetition mark in hiragana -stimmhaftes Wiederholungszeichen für Hiragana -normalerweise nur in vertikaler Schreibweise verwendet -marque de la répétition sonore dans hiragana -(JF2) - - - -1000040 - -〃 - - -ãŠãªã˜ã - - -&n; -ditto mark -знак "то же Ñамое" -Wiederholungszeichen in Tabellen -idem marque -(JF2) - - - -1000050 - -ä» - - -ã©ã†ã˜ã‚‡ã† - - -&n; -"as above" mark -Abkürzung für "siehe oben" -comme au-dessus -(JF2) - - - -1000060 - -々 - - -ãりã‹ãˆã— - - -&n; -repetition of kanji (sometimes voiced) -Wiederholungszeichen für Kanji -(Laut wird durch Wiederholung manchmal stimmhaft) -répétition de kanji(quelquefois a exprimé) -(JF2) - - - -1000070 - -〆 - - -ã—ã‚ - - -&n; -end or closure mark -Zeichen als eine Art Versiegelung über der zugeklebten Lasche auf der Rückseite eines Briefumschlages -fin ou marque de la fermeture -(JF2) - - - -1000080 - -〇 - - -â—‹ -&iK; - - -ã‹ã‚“ã™ã†ã˜ã‚¼ãƒ­ - - -&n; -漢数字 -ゼロ -"kanji" zero -Kanji-Ziffer für Null -kanji -(JF2) - - - -1000090 - -â—‹ - - -〇 -&iK; - - -ã¾ã‚‹ - - -&n; -circle (sometimes used for zero) -круг -ноÌль -Kreis -Markierung für "richtig" -Maru -(ein japan. Schriftfont hat mindestens drei verschiedene Codierungen und Darstellungen für "maru") -entourez -mettez à zéro -(JF2) - - - -1000100 - -ABC順 - - -エービーシーã˜ã‚…ã‚“ - - -ãˆãˆã³ã„ã—ã„ã˜ã‚…ã‚“ - - -&n; -alphabetical order -alphabetische Ordnung -alphabetische Reihenfolge -ordre alphabétique -(JF2) - - - -1000110 - -CDプレーヤー - - -シーディープレーヤー - - -&n; -CD player -CD плеер -проигрыватель компакт-диÑков - - - -1000120 - -ï¼¨ãªæ˜ ç”» - - -エッãƒãªæ˜ ç”» - - -エッãƒãªãˆã„㌠- - -&n; -pornographic film -salacious film - - - -1000130 - -N響 - - -エヌãょㆠ- - -&n; -&abbr; -NHK Symphony Orchestra -NHK Symphonie Orchestre(abbr) -(JF2) - - - -1000140 - -Oãƒãƒƒã‚¯ - - -&n; -O-back -skirt with peek-a-boo hole in rump -O En arrière -contournez avec coucou trou dans croupe -(JF2) - - - -1000150 - -RS232ケーブル - - -&n; -rs232 cable -les rs232 câblent -(JF2) - - - diff --git a/ruby/test/rexml/data/tutorial.xml b/ruby/test/rexml/data/tutorial.xml deleted file mode 100644 index bf5783d09..000000000 --- a/ruby/test/rexml/data/tutorial.xml +++ /dev/null @@ -1,678 +0,0 @@ - - - - - - - REXML Tutorial - - $Revision: 1.1.2.1 $ - - *2001-296+594 - - http://www.germane-software.com/~ser/software/rexml - - - - ruby - - Sean Russell - - - - -

      This is a tutorial for using REXML, - a pure Ruby XML processor.

      -
      - - -

      REXML was inspired by the Electric XML library for Java, which - features an easy-to-use API, small size, and speed. Hopefully, REXML, - designed with the same philosophy, has these same features. I've tried - to keep the API as intuitive as possible, and have followed the Ruby - methodology for method naming and code flow, rather than mirroring the - Java API.

      - -

      REXML supports both tree and stream document parsing. Stream parsing - is faster (about 1.5 times as fast). However, with stream parsing, you - don't get access to features such as XPath.

      - -

      The API documentation also - contains code snippits to help you learn how to use various methods. - This tutorial serves as a starting point and quick guide to using - REXML.

      - - -

      We'll start with parsing an XML document

      - - require "rexml/document" -file = File.new( "mydoc.xml" ) -doc = REXML::Document.new file - -

      Line 3 creates a new document and parses the supplied file. You can - also do the following

      - - require "rexml/document" -include REXML # so that we don't have to prefix everything with REXML::... -string = <<EOF - <mydoc> - <someelement attribute="nanoo">Text, text, text</someelement> - </mydoc> -EOF -doc = Document.new string - -

      So parsing a string is just as easy as parsing a file. For future - examples, I'm going to omit both the require and - include lines.

      - -

      Once you have a document, you can access elements in that document - in a number of ways:

      - - - The Element class itself has - each_element_with_attribute, a common way of accessing - elements. - - The attribute Element.elements is an - Elements class instance which has the each - and [] methods for accessing elements. Both methods can - be supplied with an XPath for filtering, which makes them very - powerful. - - Since Element is a subclass of Parent, you can - also access the element's children directly through the Array-like - methods Element[], Element.each, Element.find, - Element.delete. This is the fastest way of accessing - children, but note that, being a true array, XPath searches are not - supported, and that all of the element children are contained in - this array, not just the Element children. - - -

      Here are a few examples using these methods. First is the source - document used in the examples. Save this as mydoc.xml before running - any of the examples that require it:

      - - <inventory title="OmniCorp Store #45x10^3"> - <section name="health"> - <item upc="123456789" stock="12"> - <name>Invisibility Cream</name> - <price>14.50</price> - <description>Makes you invisible</description> - </item> - <item upc="445322344" stock="18"> - <name>Levitation Salve</name> - <price>23.99</price> - <description>Levitate yourself for up to 3 hours per application</description> - </item> - </section> - <section name="food"> - <item upc="485672034" stock="653"> - <name>Blork and Freen Instameal</name> - <price>4.95</price> - <description>A tasty meal in a tablet; just add water</description> - </item> - <item upc="132957764" stock="44"> - <name>Grob winglets</name> - <price>3.56</price> - <description>Tender winglets of Grob. Just add water</description> - </item> - </section> -</inventory> - - doc = Document.new File.new("mydoc.xml") -doc.elements.each("inventory/section") { |element| puts element.attributes["name"] } -# -> health -# -> food -doc.elements.each("*/section/item") { |element| puts element.attributes["upc"] } -# -> 123456789 -# -> 445322344 -# -> 485672034 -# -> 132957764 -root = doc.root -puts root.attributes["title"] -# -> OmniCorp Store #45x10^3 -puts root.elements["section/item[@stock='44']"].attributes["upc"] -# -> 132957764 -puts root.elements["section"].attributes["name"] -# -> health (returns the first encountered matching element) -puts root.elements[1].attributes["name"] -# -> health (returns the FIRST child element) -root.detect {|node| node.kind_of? Element and node.attributes["name"] == "food" } - -

      Notice the second-to-last line of code. Element children in REXML - are indexed starting at 1, not 0. This is because XPath itself counts - elements from 1, and REXML maintains this relationship; IE, - root.elements['*[1]'] == root.elements[1]. The last line - finds the first child element with the name of "food". As you can see - in this example, accessing attributes is also straightforward.

      - -

      You can also access xpaths directly via the XPath class.

      - - # The invisibility cream is the first <item> -invisibility = XPath.first( doc, "//item" ) -# Prints out all of the prices -XPath.each( doc, "//price") { |element| puts element.text } -# Gets an array of all of the "name" elements in the document. -names = XPath.match( doc, "//name" ) - -

      Another way of getting an array of matching nodes is through - Element.elements.to_a(). Although this is a method on elements, if - passed an XPath it can return an array of arbitrary objects. This is - due to the fact that XPath itself can return arbitrary nodes - (Attribute nodes, Text nodes, and Element nodes).

      - - all_elements = doc.elements.to_a -all_children = doc.to_a -all_upc_strings = doc.elements.to_a( "//item/attribute::upc" ) -all_name_elements = doc.elements.to_a( "//name" ) -
      - - -

      REXML attempts to make the common case simple, but this means that - the uncommon case can be complicated. This is especially true with - Text nodes.

      - -

      Text nodes have a lot of behavior, and in the case of internal - entities, what you get may be different from what you expect. When - REXML reads an XML document, in parses the DTD and creates an internal - table of entities. If it finds any of these entities in the document, - it replaces them with their values:

      - - doc = Document.new '<!DOCTYPE foo [ -<!ENTITY ent "replace"> -]><a>&ent;</a>' -doc.root.text #-> "replace" - - -

      When you write the document back out, REXML replaces the values - with the entity reference:

      - - doc.to_s -# Generates: -# <!DOCTYPE foo [ -# <!ENTITY ent "replace"> -# ]><a>&ent;</a> - -

      But there's a problem. What happens if only some of the words are - also entity reference values?

      - - doc = Document.new '<!DOCTYPE foo [ -<!ENTITY ent "replace"> -]><a>replace &ent;</a>' -doc.root.text #-> "replace replace" - - -

      Well, REXML does the only thing it can:

      - - doc.to_s -# Generates: -# <!DOCTYPE foo [ -# <!ENTITY ent "replace"> -# ]><a>&ent; &ent;</a> - -

      This is probably not what you expect. However, when designing - REXML, I had a choice between this behavior, and using immutable text - nodes. The problem is that, if you can change the text in a node, - REXML can never tell which tokens you want to have replaced with - entities. There is a wrinkle: REXML will write what it gets in as long - as you don't access the text. This is because REXML does lazy - evaluation of entities. Therefore,

      - - doc = Document.new( '<!DOCTYPE foo - [ <!ENTITY ent "replace"> ]><a>replace - &ent;</a>' ) doc.to_s # Generates: # <!DOCTYPE foo [ # - <!ENTITY ent "replace"> # ]><a>replace - &ent;</a> doc.root.text #-> Now accessed, - entities have been resolved doc.to_s # Generates: # <!DOCTYPE foo [ - # <!ENTITY ent "replace"> # ]><a>&ent; - &ent;</a> - -

      There is a programmatic solution: :raw. If you set the - :raw flag on any Text or Element node, the entities - within that node will not be processed. This means that you'll have to - deal with entities yourself:

      - - doc = Document.new('<!DOCTYPE - foo [ <!ENTITY ent "replace"> ]><a>replace - &ent;</a>',{:raw=>:all}) - doc.root.text #-> "replace &ent;" doc.to_s # Generates: # - <!DOCTYPE foo [ # <!ENTITY ent "replace"> # - ]><a>replace &ent;</a> -
      - - -

      Again, there are a couple of mechanisms for creating XML documents - in REXML. Adding elements by hand is faster than the convenience - method, but which you use will probably be a matter of aesthetics.

      - - el = someelement.add_element "myel" -# creates an element named "myel", adds it to "someelement", and returns it -el2 = el.add_element "another", {"id"=>"10"} -# does the same, but also sets attribute "id" of el2 to "10" -el3 = Element.new "blah" -el1.elements << el3 -el3.attributes["myid"] = "sean" -# creates el3 "blah", adds it to el1, then sets attribute "myid" to "sean" - -

      If you want to add text to an element, you can do it by either - creating Text objects and adding them to the element, or by using the - convenience method text=

      - - el1 = Element.new "myelement" -el1.text = "Hello world!" -# -> <myelement>Hello world!</myelement> -el1.add_text "Hello dolly" -# -> <myelement>Hello world!Hello dolly</element> -el1.add Text.new("Goodbye") -# -> <myelement>Hello world!Hello dollyGoodbye</element> -el1 << Text.new(" cruel world") -# -> <myelement>Hello world!Hello dollyGoodbye cruel world</element> - -

      But note that each of these text objects are still stored as - separate objects; el1.text will return "Hello world!"; - el1[2] will return a Text object with the contents - "Goodbye".

      - -

      Please be aware that all text nodes in REXML are UTF-8 encoded, and - all of your code must reflect this. You may input and output other - encodings (UTF-8, UTF-16, ISO-8859-1, and UNILE are all supported, - input and output), but within your program, you must pass REXML UTF-8 - strings.

      - -

      I can't emphasize this enough, because people do have problems with - this. REXML can't possibly alway guess correctly how your text is - encoded, so it always assumes the text is UTF-8. It also does not warn - you when you try to add text which isn't properly encoded, for the - same reason. You must make sure that you are adding UTF-8 text. -  If you're adding standard 7-bit ASCII, which is most common, you - don't have to worry.  If you're using ISO-8859-1 text (characters - above 0x80), you must convert it to UTF-8 before adding it to an - element.  You can do this with the shard: - text.unpack("C*").pack("U*"). If you ignore this warning - and add 8-bit ASCII characters to your documents, your code may - work... or it may not.  In either case, REXML is not at fault. - You have been warned.

      - -

      One last thing: alternate encoding output support only works from - Document.write() and Document.to_s(). If you want to write out other - nodes with a particular encoding, you must wrap your output object - with Output:

      - - e = Element.new "<a/>" -e.text = "f\xfcr" # ISO-8859-1 'ü' -o = '' -e.write( Output.new( o, "ISO-8859-1" ) ) - - -

      You can pass Output any of the supported encodings.

      - -

      If you want to insert an element between two elements, you can use - either the standard Ruby array notation, or - Parent.insert_before and - Parent.insert_after.

      - - doc = Document.new "<a><one/><three/></a>" -doc.root[1,0] = Element.new "two" -# -> <a><one/><two/><three/></a> -three = doc.elements["a/three"] -doc.root.insert_after three, Element.new "four" -# -> <a><one/><two/><three/><four/></a> -# A convenience method allows you to insert before/after an XPath: -doc.root.insert_after( "//one", Element.new("one-five") ) -# -> <a><one/><one-five/><two/><three/><four/></a> -# Another convenience method allows you to insert after/before an element: -four = doc.elements["//four"] -four.previous_sibling = Element.new("three-five") -# -> <a><one/><one-five/><two/><three/><three-five/><four/></a> - -

      The raw flag in the Text constructor can - be used to tell REXML to leave strings which have entities defined for - them alone.

      - - doc = Document.new( "<?xml version='1.0?> -<!DOCTYPE foo SYSTEM 'foo.dtd' [ -<!ENTITY % s "Sean"> -]> -<a/>" -t = Text.new( "Sean", false, nil, false ) -doc.root.text = t -t.to_s # -> &s; -t = Text.new( "Sean", false, nil, true ) -doc.root.text = t -t.to_s # -> Sean - -

      Note that, in all cases, the value() method returns - the text with entities expanded, so the raw flag only - affects the to_s() method. If the raw is set - for a text node, then to_s() will not entities will not - normalize (turn into entities) entity values. You can not create raw - text nodes that contain illegal XML, so the following will generate a - parse error:

      - - t = Text.new( "&", false, nil, true ) - -

      You can also tell REXML to set the Text children of given elements - to raw automatically, on parsing or creating:

      - - doc = REXML::Document.new( source, { :raw => %w{ tag1 tag2 tag3 } } - -

      In this example, all tags named "tag1", "tag2", or "tag3" will have - any Text children set to raw text. If you want to have all of the text - processed as raw text, pass in the :all tag:

      - - doc = REXML::Document.new( source, { :raw => :all }) -
      - - -

      There aren't many things that are more simple than writing a REXML - tree. Simply pass an object that supports <<( String - ) to the write method of any object. In Ruby, both - IO instances (File) and String instances support <<.

      - - doc.write $stdout -output = "" -doc.write output - -

      If you want REXML to pretty-print output, pass write() - an indent value greater than -1:

      - - doc.write( $stdout, 0 ) - -

      REXML will not, by default, write out the XML declaration unless - you specifically ask for them. If a document is read that contains an - XML declaration, that declaration will be written - faithfully. The other way you can tell REXML to write the declaration - is to specifically add the declaration:

      - - doc = Document.new -doc.add_element 'foo' -doc.to_s #-> <foo/> -doc << XMLDecl.new -doc.to_s #-> <?xml version='1.0'?><foo/> -
      - - -

      There are four main methods of iterating over children. - Element.each, which iterates over all the children; - Element.elements.each, which iterates over just the child - Elements; Element.next_element and - Element.previous_element, which can be used to fetch the - next Element siblings; and Element.next_sibling and - Eleemnt.previous_sibling, which fetches the next and - previous siblings, regardless of type.

      -
      - - -

      REXML stream parsing requires you to supply a Listener class. When - REXML encounters events in a document (tag start, text, etc.) it - notifies your listener class of the event. You can supply any subset - of the methods, but make sure you implement method_missing if you - don't implement them all. A StreamListener module has been supplied as - a template for you to use.

      - - list = MyListener.new -source = File.new "mydoc.xml" -REXML::Document.parse_stream(source, list) - -

      Stream parsing in REXML is much like SAX, where events are - generated when the parser encounters them in the process of parsing - the document. When a tag is encountered, the stream listener's - tag_start() method is called. When the tag end is - encountered, tag_end() is called. When text is - encountered, text() is called, and so on, until the end - of the stream is reached. One other note: the method - entity() is called when an &entity; is - encountered in text, and only then.

      - -

      Please look at the StreamListener - API for more information.You must generate the API - documentation with rdoc or download the API documentation from the - REXML website for this documentation.

      -
      - - -

      By default, REXML respects whitespace in your document. In many - applications, you want the parser to compress whitespace in your - document. In these cases, you have to tell the parser which elements - you want to respect whitespace in by passing a context to the - parser:

      - - doc = REXML::Document.new( source, { :compress_whitespace => %w{ tag1 tag2 tag3 } } - -

      Whitespace for tags "tag1", "tag2", and "tag3" will be compressed; - all other tags will have their whitespace respected. Like :raw, you - can set :compress_whitespace to :all, and have all elements have their - whitespace compressed.

      - -

      You may also use the tag :respect_whitespace, which - flip-flops the behavior. If you use :respect_whitespace - for one or more tags, only those elements will have their whitespace - respected; all other tags will have their whitespace compressed.

      -
      - - -

      REXML does some automatic processing of entities for your - convenience. The processed entities are &, <, >, ", and '. - If REXML finds any of these characters in Text or Attribute values, it - automatically turns them into entity references when it writes them - out. Additionally, when REXML finds any of these entity references in - a document source, it converts them to their character equivalents. - All other entity references are left unprocessed. If REXML finds an - &, <, or > in the document source, it will generate a - parsing error.

      - - bad_source = "<a>Cats & dogs</a>" -good_source = "<a>Cats &amp; &#100;ogs</a>" -doc = REXML::Document.new bad_source -# Generates a parse error -doc = REXML::Document.new good_source -puts doc.root.text -# -> "Cats & &#100;ogs" -doc.root.write $stdout -# -> "<a>Cats &amp; &#100;ogs</a>" -doc.root.attributes["m"] = "x'y\"z" -puts doc.root.attributes["m"] -# -> "x'y\"z" -doc.root.write $stdout -# -> "<a m='x&apos;y&quot;z'>Cats &amp; &#100;ogs</a>" -
      - - -

      Namespaces are fully supported in REXML and within the XPath - parser. There are a few caveats when using XPath, however:

      - - - If you don't supply a namespace mapping, the default namespace - mapping of the context element is used. This has its limitations, - but is convenient for most purposes. - - If you need to supply a namespace mapping, you must use the - XPath methods each, first, and - match and pass them the mapping. - - - source = "<a xmlns:x='foo' xmlns:y='bar'><x:b id='1'/><y:b id='2'/></a>" -doc = Document.new source -doc.elements["/a/x:b"].attributes["id"] # -> '1' -XPath.first(doc, "/a/m:b", {"m"=>"bar"}).attributes["id"] # -> '2' -doc.elements["//x:b"].prefix # -> 'x' -doc.elements["//x:b"].namespace # -> 'foo' -XPath.first(doc, "//m:b", {"m"=>"bar"}).prefix # -> 'y' -
      - - -

      The pull parser API is not yet stable. When it settles down, I'll - fill in this section. For now, you'll have to bite the bullet and read - the PullParser - API docs. Ignore the PullListener class; it is a private helper - class.

      -
      - - -

      The original REXML stream parsing API is very minimal. This also - means that it is fairly fast. For a more complex, more "standard" API, - REXML also includes a streaming parser with a SAX2+ API. This API - differs from SAX2 in a couple of ways, such as having more filters and - multiple notification mechanisms, but the core API is SAX2.

      - -

      The two classes in the SAX2 API are SAX2Parser - and SAX2Listener. - You can use the parser in one of five ways, depending on your needs. - Three of the ways are useful if you are filtering for a small number - of events in the document, such as just printing out the names of all - of the elements in a document, or getting all of the text in a - document. The other two ways are for more complex processing, where - you want to be notified of multiple events. The first three involve - Procs, and the last two involve listeners. The listener mechanisms are - very similar to the original REXML streaming API, with the addition of - filtering options, and are faster than the proc mechanisms.

      - -

      An example is worth a thousand words, so we'll just take a look at - a small example of each of the mechanisms. The first example involves - printing out only the text content of a document.

      - - require 'rexml/sax2parser' -parser = REXML::SAX2Parser.new( File.new( 'documentation.xml' ) ) -parser.listen( :characters ) {|text| puts text } -parser.parse - -

      In this example, we tell the parser to call our block for every - characters event. "characters" is what SAX2 calls Text - nodes. The event is identified by the symbol :characters. - There are a number of these events, including - :element_start, :end_prefix_mapping, and so - on; the events are named after the methods in the - SAX2Listener API, so refer to that document for a - complete list.

      - -

      You can additionally filter for particular elements by passing an - array of tag names to the listen method. In further - examples, we will not include the require or parser - construction lines, as they are the same for all of these - examples.

      - - parser.listen( :characters, %w{ changelog todo } ) {|text| puts text } -parser.parse - -

      In this example, only the text content of changelog and todo - elements will be printed. The array of tag names can also contain - regular expressions which the element names will be matched - against.

      - -

      Finally, as a shortcut, if you do not pass a symbol to the listen - method, it will default to :element_start

      - - parser.listen( %w{ item }) do |uri,localname,qname,attributes| - puts attributes['version'] -end -parser.parse - -

      This example prints the "version" attribute of all "item" elements - in the document. Notice that the number of arguments passed to the - block is larger than for :text; again, check the - SAX2Listener API for a list of what arguments are passed the blocks - for a given event.

      - -

      The last two mechanisms for parsing use the SAX2Listener API. Like - StreamListener, SAX2Listener is a module, so you can - include it in your class to give you an adapter. To use - the listener model, create a class that implements some of the - SAX2Listener methods, or all of them if you don't include the - SAX2Listener model. Add them to a parser as you would blocks, and when - the parser is run, the methods will be called when events occur. - Listeners do not use event symbols, but they can filter on element - names.

      - - listener1 = MySAX2Listener.new -listener2 = MySAX2Listener.new -parser.listen( listener1 ) -parser.listen( %{ changelog, todo, credits }, listener2 ) -parser.parse - -

      In the previous example, listener1 will be notified of - all events that occur, and listener2 will only be - notified of events that occur in changelog, - todo, and credits elements. We also see that - multiple listeners can be added to the same parser; multiple blocks - can also be added, and listeners and blocks can be mixed together.

      - -

      There is, as yet, no mechanism for recursion. Two upcoming features - of the SAX2 API will be the ability to filter based on an XPath, and - the ability to specify filtering on an elemnt and all of its - descendants.

      - -

      WARNING: The SAX2 API for dealing with doctype (DTD) - events almost certainly will change.

      -
      - - -

      Michael Neumann contributed some convenience functions for nodes, - and they are general enough that I've included. Michael's use-case - examples follow: # - Starting with +root_node+, we recursively look for a node with the - given # +tag+, the given +attributes+ (a Hash) and whoose text equals - or matches the # +text+ string or regular expression. # # To find the - following node: # # <td class='abc'>text</td> # # We use: - # # find_node(root, 'td', {'class' => 'abc'}, "text") # # Returns - +nil+ if no matching node was found. def find_node(root_node, tag, - attributes, text) root_node.find_first_recursive {|node| node.name == - tag and attributes.all? {|attr, val| node.attributes[attr] == val} and - text === node.text } end # # Extract specific columns (specified by - the position of it's corresponding # header column) from a table. # # - Given the following table: # # <table> # <tr> # - <td>A</td> # <td>B</td> # - <td>C</td> # </tr> # <tr> # - <td>A.1</td> # <td>B.1</td> # - <td>C.1</td> # </tr> # <tr> # - <td>A.2</td> # <td>B.2</td> # - <td>C.2</td> # </tr> # </table> # # To extract - the first (A) and last (C) column: # # extract_from_table(root_node, - ["A", "C"]) # # And you get this as result: # # [ # ["A.1", "C.1"], # - ["A.2", "C.2"] # ] # def extract_from_table(root_node, headers) # - extract and collect all header nodes header_nodes = headers.collect { - |header| find_node(root_node, 'td', {}, header) } raise "some headers - not found" if header_nodes.compact.size < headers.size # assert - that all headers have the same parent 'header_row', which is the row # - in which the header_nodes are contained. 'table' is the surrounding - table tag. header_row = header_nodes.first.parent table = - header_row.parent raise "different parents" unless header_nodes.all? - {|n| n.parent == header_row} # we now iterate over all rows in the - table that follows the header_row. # for each row we collect the - elements at the same positions as the header_nodes. # this is what we - finally return from the method. (header_row.index_in_parent+1 .. - table.elements.size).collect do |inx| row = table.elements[inx] - header_nodes.collect { |n| row.elements[ n.index_in_parent ].text } - end end

      -
      - - -

      This isn't everything there is to REXML, but it should be enough to - get started. Check the API - documentationYou must generate the API documentation - with rdoc or download the API documentation from the REXML website for - this documentation. for particulars and more examples. - There are plenty of unit tests in the test/ directory, - and these are great sources of working examples.

      -
      -
      -
      - - -

      Among the people who've contributed to this document are:

      - - - Eichert, Diana (bug - fix) - -
      -
      \ No newline at end of file diff --git a/ruby/test/rexml/data/underscore.xml b/ruby/test/rexml/data/underscore.xml deleted file mode 100644 index 111446f4b..000000000 --- a/ruby/test/rexml/data/underscore.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 1 - <_b>2 - - diff --git a/ruby/test/rexml/data/utf16.xml b/ruby/test/rexml/data/utf16.xml deleted file mode 100644 index f7e5e90d0..000000000 Binary files a/ruby/test/rexml/data/utf16.xml and /dev/null differ diff --git a/ruby/test/rexml/data/web.xml b/ruby/test/rexml/data/web.xml deleted file mode 100644 index 972cf5d27..000000000 --- a/ruby/test/rexml/data/web.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - snoop - SnoopServlet - - - file - ViewFile - - initial - - 1000 - - - The initial value for the counter - - - - - - mv - - - *.wm - - - - - - - - manager - - - director - - - president - - - diff --git a/ruby/test/rexml/data/web2.xml b/ruby/test/rexml/data/web2.xml deleted file mode 100644 index 7d479d37e..000000000 --- a/ruby/test/rexml/data/web2.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/ruby/test/rexml/data/working.rss b/ruby/test/rexml/data/working.rss deleted file mode 100644 index b38c45f5d..000000000 --- a/ruby/test/rexml/data/working.rss +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Paul Duncan - http://www.paulduncan.org/ - Paul Duncan's personal blog. - - - - Fun With Tense - - Wed Sep 3 19:37:18 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=23 - -<pre> -&lt;richlowe&gt; blah. -&lt;richlowe&gt; that's what I say. -&lt;pabs&gt; if i say it too then what happens? -&lt;richlowe&gt; then "that's what we say" -&lt;richlowe&gt; duh. -&lt;pabs&gt; what if i say it, then retract it? -&lt;richlowe&gt; Did they teach you nothing in school! -&lt;richlowe&gt; "that's what I say, and he said" -&lt;pabs&gt; :( -&lt;pabs&gt; okay what if i say it, retract it, but then plan on saying it - again at some point in the indeterminite future? -&lt;richlowe&gt; "that's what I say, and he has said, and will possibly say - again"? -&lt;pabs&gt; see now that's not concise at all -</pre> - - - - - - We'll Miss You, Michael - - Mon Aug 25 09:52:41 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=22 - -<p> -Perhaps <a href='http://www.dash-dash.org/pix/death.jpg'>the image</a> -on <a href='http://www.dash-dash.org/'>his site</a> was a bit more -fitting than we realized. I'm frustrated that nothing and noone around -him could help ease the pain that he was going through. We can take -comfort in knowing that he felt the decision he made was best for him. -We'll miss you, Michael. -</p> - - - - - - Horis, Isis, Osiris, Oh My! - - Fri Aug 22 22:39:23 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=21 - -<p> -I started reading one of the several mythology books I checked out -earlier this week (as part of a personal research project, the results -of which will be available here eventually). I've only made it through -about 60 pages of Egyptian mythology so far, but it's interesting stuff. -One thing that's impressive to me is how the sexes appear to be on much -more equal footing (as compared to the Judeo/Christian mythology we've -been innundated with for most of our lives). For example, Isis revives -her husband Osiris by collecting his body parts, which are scattered -throughout Egypt. She also saves her son Horus from death and nurtures -him until he can fend for himself. Really interesting stuff. Anyway, -I'll have more about the project as I get farther along. -</p> - - - - - - Nature Sucks - - Fri Aug 22 08:33:41 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=20 - -<p> -<a href='http://www.linuxbrit.co.uk/'>Tom</a> has been having a rough -couple of weeks. Apparently he's got <a -href='http://www.ninds.nih.gov/health_and_medical/disorders/bells_doc.htm'>Bell's -Palsy</a> (link from ljlane), which, while treatable and rarely -permanent, still leaves his face partially paralyzed. If you have a few -minutes, you might consider sending him an <abbr title='Electronic -Card'>E-Card</abbr> or an <a -href='mailto:dr_spock@linuxbrit.co.uk'>email</a>. -</p> - - - - - - Or Maybe He Does - - Thu Aug 21 23:45:40 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=19 - -<p> -Okay, apparently Ed <em>does</em> read this page. :-D -</p> - - - - - - Ed Got Married!! - - Thu Aug 21 15:52:34 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=18 - -<p> -Ed got married in the Bahamas! Here's a picture from the honeymoon: -</p> - -<img src='/files/ed_dolphin.jpg' width='252' height='288' - title='Ed on his honeymoon!' alt='Ed on his honeymoon!' /> - -<p> -(Fortunately he doesn't read this site). -</p> - -<p> -One other thing. I weigh 186<abbr title='Pounds'>lbs</abbr> now. -The <a href='http://www.pablotron.org/weight/'>weight page</a> has been -updated. -</p> - - - - - - Gratuitous Douglas Adams Reference, #32427! - - Tue Aug 19 08:25:42 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=17 - -<p> -Just saw this <acronym title='Uniform Resource Locator'>URL</acronym> -on <a href='http://www.diveintomark.org/'>Dive Into -Mark</a>: -</p> - -<p> -<a -href='http://www.google.com/search?q=answer+to+life+the+universe+and+everything'>http://www.google.com/search?q=answer+to+life+the+universe+and+everything</a> -</p> - -<p> -<a href='http://www.bbc.co.uk/h2g2/guide/'><acronym title='Hitchhikers -Guide to the Galaxy'>H2G2</acronym></a> references never get old for me. -</p> - - - - - - Weekend Update, sans Norm McDonald - - Tue Aug 19 08:18:32 2003 - paul@paulduncan.org - http://www.paulduncan.org/?id=16 - -<p> -What a nutty weekend. A friend of mine went to the <acronym -title='Emergency Room'>ER</acronym> on Friday night, so I spent 4 hours -down there. It's really frustrating to see that many sick and injured -people in once place, and not really be able to do anything about it. -Also, for that much chaos, both the atmosphere and the staff are -disturbingly calm. -</p> - -<p> -I finally got <a href='http://www.raggle.org/'>Raggle</a> to a point -worthy of a new release. I'm not going to blather on about the new -stuff; if you're interested you can <a -href='http://www.raggle.org/'>check it out</a> on your own. -</p> - -<p> -<a href='http://www.pablotron.org/weight/'>The war against obesity</a> -continues! I'm down to 188 pounds now, a total of 75 pounds lost since -the beginning of March. I've been having trouble losing these last 10 -pounds, so this week is officially "Go to the Gym Every Night or Else" -week. 2 days down, 5 to go. -</p> - - - - - diff --git a/ruby/test/rexml/data/xmlfile-bug.xml b/ruby/test/rexml/data/xmlfile-bug.xml deleted file mode 100644 index d4396682f..000000000 --- a/ruby/test/rexml/data/xmlfile-bug.xml +++ /dev/null @@ -1,15 +0,0 @@ - - -Technik - -Technik -Die Technik ist das Rückgrat der meisten Geschäftsprozesse bei Home of the Brave. Deshalb sollen hier alle relevanten technischen Abläufe, Daten und Einrichtungen beschrieben werden, damit jeder im Bedarfsfall die nötigen Informationen, Anweisungen und Verhaltensempfehlungen nachlesen und/oder abrufen kann. - - - Flash - Nützliches von Flashern für Flasher. - CVS-FAQ - FAQ zur Benutzung von CVS bei HOB - - - diff --git a/ruby/test/rexml/data/xp.tst b/ruby/test/rexml/data/xp.tst deleted file mode 100644 index 655137257..000000000 --- a/ruby/test/rexml/data/xp.tst +++ /dev/null @@ -1,27 +0,0 @@ -/ -/rss -//rss -/rss/channel -//link -//image/* -//link[2] -//link[last()] -rss/channel/link[last()] -rss/channel/item/link[last()] -rss/channel/item/link[1] -rss/channel/item[@x='1'] -rss/channel/item[@x] -//item[@x] -//item[normalize-space(@name)='x'] -//*[count(title)=1] -//*[name()='link'] -//*[starts-with(name(),'li')] -//*[contains(name(),'y')] -//*[string-length(name()) = 4] -//copyright | //title -/child::rss -/descendant::* -//language/parent::* -/rss/channel/ancestor::* -//item[position() mod 2 = 0 ] -//item/ancestor::* \ No newline at end of file diff --git a/ruby/test/rexml/data/yahoo.xml b/ruby/test/rexml/data/yahoo.xml deleted file mode 100644 index b63a9440b..000000000 --- a/ruby/test/rexml/data/yahoo.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - -<![CDATA[Yahoo! News Search Results for market]]> -http://news.search.yahoo.com/search/news?p=market&ei=UTF-8 - -en-us -Copyright (c) 2004 Yahoo! Inc. All rights reserved. -Sun, 03 Sep 2006 16:34:54 GMT -5 - -Yahoo! News -142 -18 -http://news.search.yahoo.com/news -http://us.i1.yimg.com/us.yimg.com/i/us/nws/th/main_142.gif - -false -<![CDATA[Toyota increases share in US auto market (Manila Bulletin)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13ck33lrk/*http%3A//www.mb.com.ph/archive_pages.php?url=http://www.mb.com.ph/issues/2006/09/04/BSNS2006090473427.html -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13ck33lrk/*http%3A//www.mb.com.ph/archive_pages.php?url=http://www.mb.com.ph/issues/2006/09/04/BSNS2006090473427.html -Sun, 03 Sep 2006 16:21:30 GMT - - -<![CDATA[ANALYSIS - North Korea finds market for missiles shrinking (Reuters via Yahoo! Asia News)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11ibfq78e/*http%3A//asia.news.yahoo.com/060903/3/2pd1j.html -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11ibfq78e/*http%3A//asia.news.yahoo.com/060903/3/2pd1j.html -Sun, 03 Sep 2006 08:37:33 GMT - - -<![CDATA[Broward labor market's a solid performer (Miami Herald)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13671c2t8/*http%3A//www.miami.com/mld/miamiherald/business/15427113.htm?source=rss&channel=miamiherald_business -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13671c2t8/*http%3A//www.miami.com/mld/miamiherald/business/15427113.htm?source=rss&channel=miamiherald_business -Sun, 03 Sep 2006 07:39:53 GMT - - -<![CDATA[NID to help Jharkhand e-market crafts (Yahoo! India News)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11hg1j19f/*http%3A//in.news.yahoo.com/060903/43/6780a.html -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11hg1j19f/*http%3A//in.news.yahoo.com/060903/43/6780a.html -Sun, 03 Sep 2006 10:02:54 GMT - - -<![CDATA[Reinsurance market goes high-tech to predict disasters (The Herald-Tribune)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12j43rdgp/*http%3A//www.heraldtribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS/609030458 -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12j43rdgp/*http%3A//www.heraldtribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS/609030458 -Sun, 03 Sep 2006 10:34:36 GMT - - -<![CDATA[Government warned against going into property market (Sunday Business Post)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pru5k6v/*http%3A//www.sbpost.ie/breakingnews/breaking_story.asp?j=4126020&p=4yz6x35&n=4126112&x= -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pru5k6v/*http%3A//www.sbpost.ie/breakingnews/breaking_story.asp?j=4126020&p=4yz6x35&n=4126112&x= -Sun, 03 Sep 2006 09:31:34 GMT - - -<![CDATA[Farmers Market gets shoulder-to-shoulder crowds on Saturdays (Great Falls Tribune)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pfls0n1/*http%3A//www.greatfallstribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS01/609030306 -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pfls0n1/*http%3A//www.greatfallstribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS01/609030306 -Sun, 03 Sep 2006 11:12:36 GMT - - -<![CDATA[City Hall takes Plan B for SF market rehab (Sun Star)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=138rfnhvi/*http%3A//www.sunstar.com.ph/static/pam/2006/09/03/news/city.hall.takes.plan.b.for.sf.market.rehab.html -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=138rfnhvi/*http%3A//www.sunstar.com.ph/static/pam/2006/09/03/news/city.hall.takes.plan.b.for.sf.market.rehab.html -Sun, 03 Sep 2006 08:18:46 GMT - - -<![CDATA[Market watch (AG Weekly)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12ahobgi6/*http%3A//www.agweekly.com/articles/2006/09/02/news/markets/markets01.txt -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12ahobgi6/*http%3A//www.agweekly.com/articles/2006/09/02/news/markets/markets01.txt -Sun, 03 Sep 2006 04:20:37 GMT - - -<![CDATA[Catholic War Vets Ladies Club sets flea market (Times Leader)]]> -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=1383flil1/*http%3A//www.timesleader.com/mld/timesleader/living/15431391.htm?source=rss&channel=timesleader_living -http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=1383flil1/*http%3A//www.timesleader.com/mld/timesleader/living/15431391.htm?source=rss&channel=timesleader_living -Sun, 03 Sep 2006 07:07:50 GMT - - - - diff --git a/ruby/test/rexml/formatter/test_default.rb b/ruby/test/rexml/formatter/test_default.rb deleted file mode 100644 index b5b131724..000000000 --- a/ruby/test/rexml/formatter/test_default.rb +++ /dev/null @@ -1,19 +0,0 @@ -require_relative "../rexml_test_utils" - -module REXMLTests - class DefaultFormatterTest < Test::Unit::TestCase - def format(node) - formatter = REXML::Formatters::Default.new - output = "" - formatter.write(node, output) - output - end - - class InstructionTest < self - def test_content_nil - instruction = REXML::Instruction.new("target") - assert_equal("", format(instruction)) - end - end - end -end diff --git a/ruby/test/rexml/functions/test_base.rb b/ruby/test/rexml/functions/test_base.rb deleted file mode 100644 index 74dc1a31d..000000000 --- a/ruby/test/rexml/functions/test_base.rb +++ /dev/null @@ -1,261 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" - -require "rexml/document" - -# TODO: Split me -module REXMLTests - class FunctionsTester < Test::Unit::TestCase - include REXML - - def setup - super - REXML::Functions.context = nil - end - - def test_functions - # trivial text() test - # confuse-a-function - source = "more dumb text" - doc = Document.new source - res = "" - XPath::each(doc.root, "text()") {|val| res << val.to_s} - assert_equal "more text", res - - res = XPath::first(doc.root, "b[last()]") - assert_equal '3', res.attributes['id'] - res = XPath::first(doc.root, "b[position()=2]") - assert_equal '2', res.attributes['id'] - res = XPath::first(doc.root, "*[name()='c']") - assert_equal "c", res.name - end - - # Contributed by Mike Stok - def test_starts_with - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]") - assert_equal 1, mailtos.size - assert_equal "mailto:a@b.c", mailtos[0].attributes['href'] - - ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]") - assert_equal 0, ailtos.size - end - - def test_string_length - doc = Document.new <<-EOF - - - - - - - - - EOF - assert doc, "create doc" - - set = doc.elements.to_a("//*[string-length(name()) = 3]") - assert_equal 2, set.size, "nodes with names length = 3" - - set = doc.elements.to_a("//*[string-length(name()) < 3]") - assert_equal 2, set.size, "nodes with names length < 3" - - set = doc.elements.to_a("//*[string-length(name()) > 3]") - assert_equal 3, set.size, "nodes with names length > 3" - end - - # Test provided by Mike Stok - def test_contains - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - - [['o', 2], ['foo', 1], ['bar', 0]].each { |test| - search, expected = test - set = doc.elements.to_a("//a[contains(@href, '#{search}')]") - assert_equal expected, set.size - } - end - - # Mike Stok and Sean Russell - def test_substring - # examples from http://www.w3.org/TR/xpath#function-substring - doc = Document.new('') - - #puts XPath.first(d, 'node()[0 + 1]') - #d = Document.new("") - #puts XPath.first(d, 'a[0 mod 0]') - [ [1.5, 2.6, '234'], - [0, 3, '12'], - [0, '0 div 0', ''], - [1, '0 div 0', ''], - ['-42', '1 div 0', '12345'], - ['-1 div 0', '1 div 0', ''] - ].each { |start, length, expected| - set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']") - assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'" - } - end - - def test_substring_angrez - testString = REXML::Functions::substring_after("helloworld","hello") - assert_equal( 'world', testString ) - end - - def test_translate - source = <<-EOF - - - - - - - - EOF - - doc = Document.new(source) - - [ ['bar', 'abc', 'ABC', 'w3c one'], - ['--aaa--','abc-','ABC', 'w3c two'], - ['lead', 'dear language', 'doll groover', 'alchemy'], - ['A Space Odissei', 'i', 'y', 'vbxml one'], - ['abcdefg', 'aceg', 'ACE', 'vbxml two'], - ].each { |arg1, arg2, arg3, name| - translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')" - set = doc.elements.to_a("//case[@result = #{translate}]") - assert_equal 1, set.size, translate - assert_equal name, set[0].attributes['name'] - } - end - - def test_name - d = REXML::Document.new("") - assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size - assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size - end - - def test_local_name - d = REXML::Document.new("") - assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size - assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size - end - - def test_substring2 - doc = Document.new('') - assert_equal(1,doc.elements.to_a("//test[substring(@string,2)='2345']").size) - end - - # Submitted by Kouhei - def test_floor_ceiling_round - source = "" - doc = REXML::Document.new(source) - - id_1 = doc.elements["/a/b[@id='1']"] - id_2 = doc.elements["/a/b[@id='2']"] - id_3 = doc.elements["/a/b[@id='3']"] - - good = { - "floor" => [[], [id_1], [id_2], [id_3]], - "ceiling" => [[id_1], [id_2], [id_3], []], - "round" => [[id_1], [id_2], [id_3], []] - } - good.each do |key, value| - (0..3).each do |i| - xpath = "//b[number(@id) = #{key}(#{i+0.5})]" - assert_equal(value[i], REXML::XPath.match(doc, xpath)) - end - end - - good["round"] = [[], [id_1], [id_2], [id_3]] - good.each do |key, value| - (0..3).each do |i| - xpath = "//b[number(@id) = #{key}(#{i+0.4})]" - assert_equal(value[i], REXML::XPath.match(doc, xpath)) - end - end - end - - # Submitted by Kou - def test_lang - d = Document.new(<<-XML) - - - - - - - - - XML - - assert_equal(1, d.elements.to_a("//*[lang('fr')]").size) - assert_equal(3, d.elements.to_a("//*[lang('ja')]").size) - assert_equal(2, d.elements.to_a("//*[lang('en')]").size) - assert_equal(1, d.elements.to_a("//*[lang('en-us')]").size) - - d = Document.new(<<-XML) - - -
      - - -
      - XML - - assert_equal(5, d.elements.to_a("//*[lang('en')]").size) - end - - def test_ticket_60 - document = REXML::Document.new("A1") - assert_equal( "A", REXML::XPath.first(document, '//b[.="A"]').text ) - assert_equal( "1", REXML::XPath.first(document, '//b[.="1"]').text ) - end - - def test_normalize_space - source = "" - doc = REXML::Document.new(source) - predicate = "string(.)=normalize_space('\nCOMMENT \n A \n\n ')" - m = REXML::XPath.match(doc, "//comment()[#{predicate}]") - assert_equal( [REXML::Comment.new("COMMENT A")], m ) - end - - def test_string_nil_without_context - doc = REXML::Document.new(<<-XML) - - - - - - XML - - assert_equal([doc.root.elements[2]], - REXML::XPath.match(doc, - "//foo[@bar=$n]", - nil, - {"n" => nil})) - end - - def test_unregistered_method - doc = Document.new("") - assert_nil(XPath::first(doc.root, "to_s()")) - end - - def test_nonexistent_function - doc = Document.new("") - # TODO: Maybe, this is not XPath spec behavior. - # This behavior must be reconsidered. - assert_equal(doc.root.elements[1], - XPath::first(doc.root, "nonexistent()")) - end - end -end diff --git a/ruby/test/rexml/functions/test_boolean.rb b/ruby/test/rexml/functions/test_boolean.rb deleted file mode 100644 index b3e2117c1..000000000 --- a/ruby/test/rexml/functions/test_boolean.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: false - -require "test/unit" -require "rexml/document" -require "rexml/functions" - -module REXMLTests - class TestFunctionsBoolean < Test::Unit::TestCase - def setup - REXML::Functions.context = nil - end - - def test_true - assert_equal(true, REXML::Functions.boolean(true)) - end - - def test_false - assert_equal(false, REXML::Functions.boolean(false)) - end - - def test_integer_true - assert_equal(true, REXML::Functions.boolean(1)) - end - - def test_integer_positive_zero - assert_equal(false, REXML::Functions.boolean(0)) - end - - def test_integer_negative_zero - assert_equal(false, REXML::Functions.boolean(-0)) - end - - def test_float_true - assert_equal(true, REXML::Functions.boolean(1.1)) - end - - def test_float_positive_zero - assert_equal(false, REXML::Functions.boolean(-0.0)) - end - - def test_float_negative_zero - assert_equal(false, REXML::Functions.boolean(-0.0)) - end - - def test_float_nan - assert_equal(false, REXML::Functions.boolean(Float::NAN)) - end - - def test_string_true - assert_equal(true, REXML::Functions.boolean("content")) - end - - def test_string_empty - assert_equal(false, REXML::Functions.boolean("")) - end - - def test_node_set_true - root = REXML::Document.new("").root - assert_equal(true, REXML::Functions.boolean([root])) - end - - def test_node_set_empty - assert_equal(false, REXML::Functions.boolean([])) - end - - def test_nil - assert_equal(false, REXML::Functions.boolean(nil)) - end - - def test_context - REXML::Functions.context = {node: true} - assert_equal(true, REXML::Functions.boolean()) - end - end -end diff --git a/ruby/test/rexml/functions/test_local_name.rb b/ruby/test/rexml/functions/test_local_name.rb deleted file mode 100644 index 97c9e7485..000000000 --- a/ruby/test/rexml/functions/test_local_name.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: false - -require "test/unit" -require "rexml/document" -require "rexml/functions" - -module REXMLTests - class TestFunctionsLocalName < Test::Unit::TestCase - def setup - REXML::Functions.context = nil - end - - def test_one - document = REXML::Document.new(<<-XML) - - - - XML - node_set = document.root.children - assert_equal("child", REXML::Functions.local_name(node_set)) - end - - def test_multiple - document = REXML::Document.new(<<-XML) - - - - - XML - node_set = document.root.children - assert_equal("child1", REXML::Functions.local_name(node_set)) - end - - def test_nonexistent - assert_equal("", REXML::Functions.local_name([])) - end - - def test_context - document = REXML::Document.new("") - REXML::Functions.context = {node: document.root} - assert_equal("root", REXML::Functions.local_name()) - end - end -end diff --git a/ruby/test/rexml/functions/test_number.rb b/ruby/test/rexml/functions/test_number.rb deleted file mode 100644 index 16e635701..000000000 --- a/ruby/test/rexml/functions/test_number.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: false - -require "test/unit" -require "rexml/document" -require "rexml/functions" - -module REXMLTests - class TestFunctionsNumber < Test::Unit::TestCase - def setup - REXML::Functions.context = nil - end - - def test_true - assert_equal(1, REXML::Functions.number(true)) - end - - def test_false - assert_equal(0, REXML::Functions.number(false)) - end - - def test_numeric - assert_equal(29, REXML::Functions.number(29)) - end - - def test_string_integer - assert_equal(100, REXML::Functions.number("100")) - end - - def test_string_float - assert_equal(-9.13, REXML::Functions.number("-9.13")) - end - - def test_node_set - root = REXML::Document.new("100").root - assert_equal(100, REXML::Functions.number([root])) - end - end -end diff --git a/ruby/test/rexml/listener.rb b/ruby/test/rexml/listener.rb deleted file mode 100644 index 6bede03c5..000000000 --- a/ruby/test/rexml/listener.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: false -class Listener - attr_reader :ts, :te - attr_reader :normalize - def initialize - @ts = false - @te = false - end - def tag_start name, attrs - @ts = true if name=="subsection" and attrs["title"]=="Namespaces" - end - def tag_end name - @te = true if name=="documentation" - end - def text text - @normalize = text - #text.tr! "\n", ' ' - #puts "text #{text[0..10]}..." - end - def instruction name, instruction - #puts "instruction" - end - def comment comment - #puts "comment #{comment[0..10]}..." - end - def doctype name, pub_sys, long_name, uri - #puts "doctype #{name}" - end - def attlistdecl content - #puts "attlistdecl" - end - def elementdecl content - #puts "elementdecl" - end - def entitydecl content - #puts "entitydecl" - end - def notationdecl content - #puts "notationdecl" - end - def entity content - #puts "entity" - end - def cdata content - #puts "cdata" - end - def xmldecl version, encoding, standalone - #puts "xmldecl #{version}" - end -end - diff --git a/ruby/test/rexml/parse/test_document_type_declaration.rb b/ruby/test/rexml/parse/test_document_type_declaration.rb deleted file mode 100644 index 80f70888f..000000000 --- a/ruby/test/rexml/parse/test_document_type_declaration.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require "rexml/document" - -module REXMLTests - class TestParseDocumentTypeDeclaration < Test::Unit::TestCase - private - def xml(internal_subset) - <<-XML - - - XML - end - - def parse(internal_subset) - REXML::Document.new(xml(internal_subset)).doctype - end - - class TestMixed < self - def test_entity_element - doctype = parse(<<-INTERNAL_SUBSET) - - - INTERNAL_SUBSET - assert_equal([REXML::Entity, REXML::ElementDecl], - doctype.children.collect(&:class)) - end - - def test_attlist_entity - doctype = parse(<<-INTERNAL_SUBSET) - - - INTERNAL_SUBSET - assert_equal([REXML::AttlistDecl, REXML::Entity], - doctype.children.collect(&:class)) - end - - def test_notation_attlist - doctype = parse(<<-INTERNAL_SUBSET) - - - INTERNAL_SUBSET - assert_equal([REXML::NotationDecl, REXML::AttlistDecl], - doctype.children.collect(&:class)) - end - end - end -end diff --git a/ruby/test/rexml/parse/test_element.rb b/ruby/test/rexml/parse/test_element.rb deleted file mode 100644 index 7322e0eb4..000000000 --- a/ruby/test/rexml/parse/test_element.rb +++ /dev/null @@ -1,51 +0,0 @@ -require "test/unit" -require "rexml/document" - -module REXMLTests - class TestParseElement < Test::Unit::TestCase - def parse(xml) - REXML::Document.new(xml) - end - - class TestInvalid < self - def test_top_level_end_tag - exception = assert_raise(REXML::ParseException) do - parse("") - end - assert_equal(<<-DETAIL.chomp, exception.to_s) -Unexpected top-level end tag (got 'a') -Line: 1 -Position: 4 -Last 80 unconsumed characters: - - DETAIL - end - - def test_no_end_tag - exception = assert_raise(REXML::ParseException) do - parse("
      ") - end - assert_equal(<<-DETAIL.chomp, exception.to_s) -Invalid attribute name: <:a=""> -Line: 1 -Position: 9 -Last 80 unconsumed characters: - - DETAIL - end - end - end -end diff --git a/ruby/test/rexml/parse/test_notation_declaration.rb b/ruby/test/rexml/parse/test_notation_declaration.rb deleted file mode 100644 index 0d29f0d81..000000000 --- a/ruby/test/rexml/parse/test_notation_declaration.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rexml/document' - -module REXMLTests - class TestParseNotationDeclaration < Test::Unit::TestCase - private - def xml(internal_subset) - <<-XML - - - XML - end - - def parse(internal_subset) - REXML::Document.new(xml(internal_subset)).doctype - end - - class TestCommon < self - def test_name - doctype = parse("") - assert_equal("name", doctype.notation("name").name) - end - end - - class TestExternalID < self - class TestSystem < self - def test_single_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("system-literal", doctype.notation("name").system) - end - - def test_double_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("system-literal", doctype.notation("name").system) - end - end - - class TestPublic < self - class TestPublicIDLiteral < self - def test_single_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("public-id-literal", doctype.notation("name").public) - end - - def test_double_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("public-id-literal", doctype.notation("name").public) - end - end - - class TestSystemLiteral < self - def test_single_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("system-literal", doctype.notation("name").system) - end - - def test_double_quote - doctype = parse(<<-INTERNAL_SUBSET) - - INTERNAL_SUBSET - assert_equal("system-literal", doctype.notation("name").system) - end - end - end - - class TestMixed < self - def test_system_public - doctype = parse(<<-INTERNAL_SUBSET) - - - INTERNAL_SUBSET - assert_equal(["system-name", "public-name"], - doctype.notations.collect(&:name)) - end - - def test_public_system - doctype = parse(<<-INTERNAL_SUBSET) - - - INTERNAL_SUBSET - assert_equal(["public-name", "system-name"], - doctype.notations.collect(&:name)) - end - end - end - end -end diff --git a/ruby/test/rexml/parse/test_processing_instruction.rb b/ruby/test/rexml/parse/test_processing_instruction.rb deleted file mode 100644 index a23513fc6..000000000 --- a/ruby/test/rexml/parse/test_processing_instruction.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "test/unit" -require "rexml/document" - -module REXMLTests - class TestParseProcessinInstruction < Test::Unit::TestCase - def parse(xml) - REXML::Document.new(xml) - end - - class TestInvalid < self - def test_no_name - exception = assert_raise(REXML::ParseException) do - parse("") - end - assert_equal(<<-DETAIL.chomp, exception.to_s) -Invalid processing instruction node -Line: 1 -Position: 4 -Last 80 unconsumed characters: - - DETAIL - end - end - end -end diff --git a/ruby/test/rexml/parser/test_sax2.rb b/ruby/test/rexml/parser/test_sax2.rb deleted file mode 100644 index 91d135f5f..000000000 --- a/ruby/test/rexml/parser/test_sax2.rb +++ /dev/null @@ -1,203 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require "rexml/parsers/sax2parser" -require "rexml/sax2listener" - -module REXMLTests -class TestSAX2Parser < Test::Unit::TestCase - class TestDocumentTypeDeclaration < self - private - def xml(internal_subset) - <<-XML - - - XML - end - - class TestEntityDeclaration < self - class Listener - include REXML::SAX2Listener - attr_reader :entity_declarations - def initialize - @entity_declarations = [] - end - - def entitydecl(declaration) - super - @entity_declarations << declaration - end - end - - private - def parse(internal_subset) - listener = Listener.new - parser = REXML::Parsers::SAX2Parser.new(xml(internal_subset)) - parser.listen(listener) - parser.parse - listener.entity_declarations - end - - class TestGeneralEntity < self - class TestValue < self - def test_double_quote - assert_equal([["name", "value"]], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_single_quote - assert_equal([["name", "value"]], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - - class TestExternlID < self - class TestSystem < self - def test_with_ndata - declaration = [ - "name", - "SYSTEM", "system-literal", - "NDATA", "ndata-name", - ] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_without_ndata - declaration = [ - "name", - "SYSTEM", "system-literal", - ] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - - class TestPublic < self - def test_with_ndata - declaration = [ - "name", - "PUBLIC", "public-literal", "system-literal", - "NDATA", "ndata-name", - ] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_without_ndata - declaration = [ - "name", - "PUBLIC", "public-literal", "system-literal", - ] - assert_equal([declaration], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - end - end - - class TestParameterEntity < self - class TestValue < self - def test_double_quote - assert_equal([["%", "name", "value"]], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_single_quote - assert_equal([["%", "name", "value"]], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - - class TestExternlID < self - def test_system - declaration = [ - "%", - "name", - "SYSTEM", "system-literal", - ] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_public - declaration = [ - "%", - "name", - "PUBLIC", "public-literal", "system-literal", - ] - assert_equal([declaration], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - end - end - - class TestNotationDeclaration < self - class Listener - include REXML::SAX2Listener - attr_reader :notation_declarations - def initialize - @notation_declarations = [] - end - - def notationdecl(*declaration) - super - @notation_declarations << declaration - end - end - - private - def parse(internal_subset) - listener = Listener.new - parser = REXML::Parsers::SAX2Parser.new(xml(internal_subset)) - parser.listen(listener) - parser.parse - listener.notation_declarations - end - - class TestExternlID < self - def test_system - declaration = ["name", "SYSTEM", nil, "system-literal"] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - def test_public - declaration = ["name", "PUBLIC", "public-literal", "system-literal"] - assert_equal([declaration], parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - - class TestPublicID < self - def test_literal - declaration = ["name", "PUBLIC", "public-literal", nil] - assert_equal([declaration], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - end - end - end -end -end diff --git a/ruby/test/rexml/parser/test_stream.rb b/ruby/test/rexml/parser/test_stream.rb deleted file mode 100644 index c315833e4..000000000 --- a/ruby/test/rexml/parser/test_stream.rb +++ /dev/null @@ -1,32 +0,0 @@ -require "test/unit" -require "rexml/document" -require "rexml/streamlistener" - -module REXMLTests - class TestStreamParser < Test::Unit::TestCase - class NullListener - include REXML::StreamListener - end - - class TestInvalid < self - def test_no_end_tag - xml = "" - exception = assert_raise(REXML::ParseException) do - parse(xml) - end - assert_equal(<<-MESSAGE, exception.to_s) -Missing end tag for '/root/sub' -Line: 1 -Position: #{xml.bytesize} -Last 80 unconsumed characters: - MESSAGE - end - - private - def parse(xml, listener=nil) - listener ||= NullListener.new - REXML::Document.parse_stream(xml, listener) - end - end - end -end diff --git a/ruby/test/rexml/parser/test_tree.rb b/ruby/test/rexml/parser/test_tree.rb deleted file mode 100644 index 8a5d9d122..000000000 --- a/ruby/test/rexml/parser/test_tree.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require "rexml/document" -require "rexml/parsers/treeparser" - -module REXMLTests -class TestTreeParser < Test::Unit::TestCase - class TestInvalid < self - def test_unmatched_close_tag - xml = "" - exception = assert_raise(REXML::ParseException) do - parse(xml) - end - assert_equal(<<-MESSAGE, exception.to_s) -Missing end tag for 'root' (got 'not-root') -Line: 1 -Position: #{xml.bytesize} -Last 80 unconsumed characters: - MESSAGE - end - - def test_no_close_tag - xml = "" - exception = assert_raise(REXML::ParseException) do - parse(xml) - end - assert_equal(<<-MESSAGE, exception.to_s) -No close tag for /root -Line: 1 -Position: #{xml.bytesize} -Last 80 unconsumed characters: - MESSAGE - end - - private - def parse(xml) - document = REXML::Document.new - parser = REXML::Parsers::TreeParser.new(xml, document) - parser.parse - end - end -end -end diff --git a/ruby/test/rexml/parser/test_ultra_light.rb b/ruby/test/rexml/parser/test_ultra_light.rb deleted file mode 100644 index 8f4a3980d..000000000 --- a/ruby/test/rexml/parser/test_ultra_light.rb +++ /dev/null @@ -1,70 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require "rexml/parsers/ultralightparser" - -module REXMLTests -class TestUltraLightParser < Test::Unit::TestCase - class TestDocumentTypeDeclaration < self - def test_entity_declaration - assert_equal([ - [ - :start_doctype, - :parent, - "root", - "SYSTEM", - "urn:x-test", - nil, - [:entitydecl, "name", "value"] - ], - [:text, "\n"], - [:start_element, :parent, "root", {}], - [:text, "\n"], - ], - parse(<<-INTERNAL_SUBSET)) - - INTERNAL_SUBSET - end - - private - def xml(internal_subset) - <<-XML - - - XML - end - - def parse(internal_subset) - parser = REXML::Parsers::UltraLightParser.new(xml(internal_subset)) - normalize(parser.parse) - end - - def normalize(root) - root.collect do |child| - normalize_child(child) - end - end - - def normalize_child(child) - tag = child.first - case tag - when :start_doctype - normalized_parent = :parent - normalized_doctype = child.dup - normalized_doctype[1] = normalized_parent - normalized_doctype - when :start_element - tag, _parent, name, attributes, *children = child - normalized_parent = :parent - normalized_children = children.collect do |sub_child| - normalize_child(sub_child) - end - [tag, normalized_parent, name, attributes, *normalized_children] - else - child - end - end - end -end -end diff --git a/ruby/test/rexml/rexml_test_utils.rb b/ruby/test/rexml/rexml_test_utils.rb deleted file mode 100644 index 8bb002cee..000000000 --- a/ruby/test/rexml/rexml_test_utils.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: false - -require "test/unit" -require "rexml/document" - -module REXMLTestUtils - def fixture_path(*components) - File.join(File.dirname(__FILE__), "data", *components) - end -end diff --git a/ruby/test/rexml/test_attribute.rb b/ruby/test/rexml/test_attribute.rb deleted file mode 100644 index 5175bd445..000000000 --- a/ruby/test/rexml/test_attribute.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "rexml_test_utils" - -module REXMLTests - class AttributeTest < Test::Unit::TestCase - def test_empty_prefix - error = assert_raise(ArgumentError) do - REXML::Attribute.new(":x") - end - assert_equal("name must be " + - "\#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: <\":x\">", - error.message) - end - end -end diff --git a/ruby/test/rexml/test_attributes.rb b/ruby/test/rexml/test_attributes.rb deleted file mode 100644 index d6f566bdf..000000000 --- a/ruby/test/rexml/test_attributes.rb +++ /dev/null @@ -1,223 +0,0 @@ -# frozen_string_literal: false -require 'test/unit/testcase' -require 'rexml/document' - -module REXMLTests - class AttributesTester < Test::Unit::TestCase - include REXML - def test_accessor - doc = Document.new("") - assert_equal '3', doc.root.attributes['att'] - assert_equal '2', doc.root.attributes['bar:att'] - doc.root.attributes['att'] = 5 - assert_equal '5', doc.root.attributes['att'] - end - - def test_each_attribute - doc = Document.new('') - doc.root.attributes.each_attribute {|attr| - if attr.expanded_name == 'x' - assert_equal '1', attr.value - elsif attr.expanded_name == 'y' - assert_equal '2', attr.value - else - assert_fail "No such attribute!!" - end - } - end - - def test_each - doc = Document.new('') - doc.root.attributes.each {|name, value| - if name == 'x' - assert_equal '1', value - elsif name == 'y' - assert_equal '2', value - else - assert_fail "No such attribute!!" - end - } - end - - def test_get_attribute - doc = Document.new('') - assert_equal '2', doc.root.attributes.get_attribute("foo").value - assert_equal '1', doc.root.attributes.get_attribute("x:foo").value - end - - def test_size - doc = Document.new("") - assert_equal 4, doc.root.attributes.length - end - - def test_setter - doc = Document.new("") - doc.root.attributes['y:foo'] = '2' - assert_equal '2', doc.root.attributes['y:foo'] - doc.root.attributes['foo'] = '4' - assert_equal '4', doc.root.attributes['foo'] - doc.root.attributes['x:foo'] = nil - assert_equal 3, doc.root.attributes.size - end - - def test_delete - doc = Document.new("") - doc.root.attributes.delete 'foo' - assert_equal 6, doc.root.attributes.size - assert_equal '1', doc.root.attributes['x:foo'] - - doc.root.attributes.delete 'x:foo' - assert_equal 5, doc.root.attributes.size - - attr = doc.root.attributes.get_attribute('y:foo') - doc.root.attributes.delete attr - assert_equal 4, doc.root.attributes.size - - assert_equal '4', doc.root.attributes['z:foo'] - end - - def test_prefixes - doc = Document.new("") - prefixes = doc.root.attributes.prefixes - assert_equal 2, prefixes.size - assert_equal 0, (prefixes - ['x', 'y']).size - end - - # Contributed by Mike Stok - def test_values_with_apostrophes - doc = Document.new(%q##) - s = doc.to_s - assert(s =~ /h1='1'2''/) - assert(s =~ /h2='1"2'/) - end - - # Submitted by Kou - def test_namespace_conflict - assert_raise( ParseException, - "Declaring two attributes with the same namespace should be an error" ) do - REXML::Document.new <<-XML - - - - XML - end - - REXML::Document.new("") - end - - # Submitted by Kou - def test_attribute_deletion - e = REXML::Element.new - e.add_namespace("a", "http://a/") - e.add_namespace("b", "http://b/") - e.add_attributes({"c" => "cc", "a:c" => "cC", "b:c" => "CC"}) - - e.attributes.delete("c") - assert_nil(e.attributes.get_attribute("c")) - - before_size = e.attributes.size - e.attributes.delete("c") - assert_nil(e.attributes.get_attribute("c")) - assert_equal(before_size, e.attributes.size) - - e.attributes.delete(e.attributes.get_attribute("a:c")) - assert_nil(e.attributes.get_attribute("a:c")) - - e.attributes.delete("b:c") - assert_nil(e.attributes.get_attribute("b:c")) - - before_size = e.attributes.size - e.attributes.delete(e.attributes.get_attribute("b:c")) - assert_nil(e.attributes.get_attribute("b:c")) - assert_equal(before_size, e.attributes.size) - - before_size = e.attributes.size - e.attributes.delete("c") - assert_nil(e.attributes.get_attribute("c")) - assert_equal(before_size, e.attributes.size) - - e.add_attribute("c", "cc") - - e.attributes.delete(e.attributes.get_attribute("c")) - assert_nil(e.attributes.get_attribute("c")) - end - - # Submitted by Kou - def test_element_usage - attr = Attribute.new("name", "value") - elem = Element.new("elem") - a = Attribute.new(attr, elem) - assert_equal(elem, a.element) - end - - def attr_test(attr_name,attr_value) - a1 = REXML::Attribute.new(attr_name,attr_value) - - s1 = a1.value - s2 = a1.value - - #p s1 - #p s2 - assert_equal(s1,s2) - - a2 = REXML::Attribute.new(attr_name,attr_value) - - a2.to_s # NB invocation of to_s - s1 = a2.value - s2 = a2.value - - #p s1 - #p s2 - assert_equal(s1,s2) - end - - def test_amp_attributes - attr_test('name','value with & ampersand only') - end - - def test_amp_and_lf_attributes - attr_test('name','value with LF & ampersand') - end - - def test_quoting - d = Document.new(%q{}) - assert_equal( %q{}, d.to_s ) - d.root.context[:attribute_quote] = :quote - assert_equal( %q{}, d.to_s ) - - d = Document.new(%q{}) - assert_equal( %q{}, d.to_s ) - d.root.context[:attribute_quote] = :quote - assert_equal( %q{}, d.to_s ) - end - - def test_ticket_127 - doc = Document.new - doc.add_element 'a', { 'v' => 'x & y' } - assert doc.to_s.index(';') - end - - def test_to_a_with_namespaces - document = Document.new(<<-XML) - - - -XML - child = document.root.elements["child"] - assert_equal([ - "attribute='no-ns'", - "ns1:attribute='ns1'", - "ns2:attribute='ns2'", - "other-attribute='other-value'", - ], - child.attributes.to_a.collect(&:to_string).sort) - end - end -end diff --git a/ruby/test/rexml/test_attributes_mixin.rb b/ruby/test/rexml/test_attributes_mixin.rb deleted file mode 100644 index 3a9f54eef..000000000 --- a/ruby/test/rexml/test_attributes_mixin.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rexml/document' - -module REXMLTests - class TestAttributes < Test::Unit::TestCase - def setup - @ns_a = "urn:x-test:a" - @ns_b = "urn:x-test:b" - element_string = <<-"XMLEND" - - XMLEND - @attributes = REXML::Document.new(element_string).root.attributes - end - - def test_get_attribute_ns - assert_equal("1", @attributes.get_attribute_ns("", "a").value) - assert_equal("2", @attributes.get_attribute_ns("", "b").value) - assert_equal("3", @attributes.get_attribute_ns(@ns_a, "c").value) - assert_equal("4", @attributes.get_attribute_ns(@ns_a, "d").value) - assert_equal("5", @attributes.get_attribute_ns(@ns_a, "e").value) - assert_equal("6", @attributes.get_attribute_ns(@ns_b, "f").value) - end - end -end diff --git a/ruby/test/rexml/test_changing_encoding.rb b/ruby/test/rexml/test_changing_encoding.rb deleted file mode 100644 index a2dc07254..000000000 --- a/ruby/test/rexml/test_changing_encoding.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require 'rexml/encoding' - -module REXMLTests - class ChangingEncodings < Test::Unit::TestCase - def initialize a - @u = 'テスト ã»ã’ ãµãŒ 美ã—ã„' - @e = @u.encode("EUC-JP") - @f = Foo.new - super - end - - class Foo - include REXML::Encoding - end - - # Note that these tests must be executed in order for the third one to - # actually test anything. - def test_0_euc - @f.encoding = 'EUC-JP' - assert_equal( @u, @f.decode(@e) ) - # This doesn't happen anymore, for some reason - #assert_raise( Iconv::IllegalSequence, "Decoding unicode should fail" ) { - # @f.decode(@u) == @u - #} - end - - def test_1_utf - @f.encoding = 'UTF-8' - assert_not_equal( @u, @f.decode( @e ) ) - assert_equal( @u, @f.decode( @u ) ) - end - - def test_2_euc - @f.encoding = 'EUC-JP' - assert_equal( @u, @f.decode(@e) ) - # This doesn't happen anymore, for some reason - #assert_raise( Iconv::IllegalSequence, "Decoding unicode should fail" ) { - # @f.decode(@u) == @u - #} - end - end -end diff --git a/ruby/test/rexml/test_comment.rb b/ruby/test/rexml/test_comment.rb deleted file mode 100644 index 0af2f5ca7..000000000 --- a/ruby/test/rexml/test_comment.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" - -require 'rexml/document' - -module REXMLTests - class CommentTester < Test::Unit::TestCase - # Bug #5278 - def test_hyphen_end_line_in_doctype - xml = <<-XML - - -]> - - XML - document = REXML::Document.new(xml) - comments = document.doctype.children.find_all do |child| - child.is_a?(REXML::Comment) - end - assert_equal([" comment end with hyphen -\n here "], - comments.collect(&:to_s)) - end - end -end diff --git a/ruby/test/rexml/test_contrib.rb b/ruby/test/rexml/test_contrib.rb deleted file mode 100644 index 8462b3c23..000000000 --- a/ruby/test/rexml/test_contrib.rb +++ /dev/null @@ -1,585 +0,0 @@ -# coding: binary -# frozen_string_literal: false - -require_relative "rexml_test_utils" - -require "rexml/document" -require "rexml/parseexception" -require "rexml/formatters/default" - -module REXMLTests - class ContribTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - - XML_STRING_01 = < - - - Thomas, David; Hunt, Andrew - english - Addison-Wesley - Programming Ruby. The Pragmatic Programmer's Guide - 2000 - - - Blammo, Blah - english - Hubbabubba - Foozboozer's Life - Book - 2002 - - -DELIMITER - - XML_STRING_02 = < - - english - Addison-Wesley - Programming Ruby. The Pragmatic Programmer's Guide - Book - 2000 - - - Blammo, Blah - english - Hubbabubba - Foozboozer's Life - Book - 2002 - - -DELIMITER - - # Tobias Reif - def test_bad_doctype_Tobias - source = <<-EOF - --> - - - ' - > - ] - > - EOF - doc = REXML::Document.new source - doc.write(out="") - assert(out[/>\'>/] != nil, "Couldn't find >'>") - assert(out[/\]>/] != nil, "Couldn't find ]>") - end - - # Peter Verhage - def test_namespace_Peter - source = <<-EOF - - - - - - - - EOF - doc = REXML::Document.new source - assert_equal "myprog-config", doc.root.name - count = 0 - REXML::XPath.each(doc, "x:myprog-config/x:main/x:parameter", - {"x"=>"http://someurl/program/version"}) { |element| - assert_equal "name", element.attributes["name"] - count += 1; - } - assert_equal 1, count - assert_equal "myprog-config", doc.elements["config:myprog-config"].name - end - - # Tobias Reif - def test_complex_xpath_Tobias - source = <<-EOF - - - - - - - - - - - - - EOF - # elements that have child elements - # but not grandchildren - # and not children that don't have a style attribute - # and not children that have a unique style attribute - complex_path = "*[* "+ - "and not(*/node()) "+ - "and not(*[not(@style)]) "+ - "and not(*/@style != */@style)]" - doc = REXML::Document.new source - results = REXML::XPath.match( doc.root, complex_path ) - assert(results) - assert_equal 1, results.size - assert_equal "foo", results[0].name - end - - # "Chris Morris" - def test_extra_newline_on_read_Chris - text = 'test text' - e = REXML::Element.new('Test') - e.add_text(text) - REXML::Formatters::Default.new.write(e,out="") - - doc = REXML::Document.new(out) - outtext = doc.root.text - - assert_equal(text, outtext) - end - - # Tobias Reif - def test_other_xpath_Tobias - schema = <<-DELIM - - - - - - - - - - - - - - - - DELIM - - doc = REXML::Document.new schema - - result = REXML::XPath.first(doc.root, 'xs:element[descendant::xs:element[@ref]]') - assert result - assert_equal "svg", result.attributes['name'] - result = REXML::XPath.first(doc, 'element[descendant::element[@ref]]') - assert_nil result - end - - #this first test succeeds, to check if stuff is set up correctly - def test_xpath_01_TobiasReif - doc = Document.new XML_STRING_01.dup - desired_result = Document.new 'Thomas, David; Hunt, Andrew' - xpath = '//author' - result = XPath.first(doc, xpath) - assert_equal desired_result.to_s, result.to_s - end - - def test_xpath_whitespace_TobiasReif - # same as above, with whitespace in XPath - doc = Document.new(XML_STRING_01.dup) - desired_result = Document.new('Thomas, David; Hunt, Andrew') - xpath = "\/\/author\n \n" - result = XPath.first(doc, xpath) - failure_message = "\n[[[TR: AFAIK, whitespace should be allowed]]]\n" - assert_equal(desired_result.to_s, result.to_s, failure_message) - end - - def test_xpath_02_TobiasReif - doc = Document.new XML_STRING_01.dup - desired_result = Document.new 'Thomas, David; Hunt, Andrew' - # Could that quirky - # Programmer',"'",'s - # be handled automatically, somehow? - # Or is there a simpler way? (the below XPath should match the author element above, - # AFAIK; I tested it inside an XSLT) - xpath = %q{/biblio/entry[ - title/text()=concat('Programming Ruby. The Pragmatic Programmer',"'",'s Guide') - and - year='2000' - ]/author} - result = XPath.first(doc, xpath) - failure_message = "\nHow to handle the apos inside the string inside the XPath?\nXPath = #{xpath}\n" - assert_equal desired_result.to_s, result.to_s, failure_message - end - - def test_xpath_03_TobiasReif - doc = Document.new XML_STRING_02.dup - desired_result_string = " - english - Addison-Wesley - Programming Ruby. The Pragmatic Programmer's Guide - Book - 2000 - " - Document.new desired_result_string - xpath = "/biblio/entry[not(author)]" - result = XPath.first(doc, xpath) - assert_equal desired_result_string, result.to_s - end - - def test_umlaut - koln_iso = "K\xf6ln" - koln_utf = "K\xc3\xb6ln" - source_iso = "#{koln_iso}" - source_utf = "#{koln_utf}" - - if String.method_defined? :encode - koln_iso.force_encoding('iso-8859-1') - koln_utf.force_encoding('utf-8') - source_iso.force_encoding('iso-8859-1') - source_utf.force_encoding('utf-8') - end - - doc = REXML::Document.new(source_iso) - assert_equal('ISO-8859-1', doc.xml_decl.encoding) - assert_equal(koln_utf, doc.root.text) - doc.write(out="") - assert_equal(source_iso, out ) - doc.xml_decl.encoding = 'UTF-8' - doc.write(out="") - assert_equal(source_utf, out) - - doc = Document.new <<-EOF - - -Technik - -Technik -Die Technik ist das R\xFCckgrat der meisten Gesch\xFCftsprozesse bei Home of the Brave. Deshalb sollen hier alle relevanten technischen Abl\xFCufe, Daten und Einrichtungen beschrieben werden, damit jeder im Bedarfsfall die n\xFCtigen Informationen, Anweisungen und Verhaltensempfehlungen nachlesen und/oder abrufen kann. - - - Flash - N\xFCtzliches von Flashern f\xFCr Flasher. - CVS-FAQ - FAQ zur Benutzung von CVS bei HOB - - -EOF - tn = XPath.first(doc, "//nebenspalte/text()[2]") - expected_iso = "N\xFCtzliches von Flashern f\xFCr Flasher." - expected_utf = expected_iso.unpack('C*').pack('U*') - expected_iso.force_encoding(::Encoding::ISO_8859_1) - expected_utf.force_encoding(::Encoding::UTF_8) - assert_equal(expected_utf, tn.to_s.strip) - f = REXML::Formatters::Default.new - f.write( tn, Output.new(o = "", "ISO-8859-1") ) - assert_equal(expected_iso, o.strip) - - doc = File.open(fixture_path('xmlfile-bug.xml')) {|file| Document.new file } - tn = XPath.first(doc, "//nebenspalte/text()[2]") - assert_equal(expected_utf, tn.to_s.strip) - f.write( tn, Output.new(o = "", "ISO-8859-1") ) - assert_equal(expected_iso, o.strip) - end - - def test_element_cloning_namespace_Chris - aDoc = REXML::Document.new '

      Dummy title

      ' - - anElement = anElement = aDoc.elements[1] - elementAttrPrefix = anElement.attributes.get_attribute('content').prefix - - aClone = anElement.clone - cloneAttrPrefix = aClone.attributes.get_attribute('content').prefix - - assert_equal( elementAttrPrefix , cloneAttrPrefix ) - end - - def test_namespaces_in_attlist_tobias - in_string = File.open(fixture_path('foo.xml'), 'r') do |file| - file.read - end - - doc = Document.new in_string - - assert_nil XPath.first(doc,'//leg') - assert_equal 'http://www.foo.com/human', doc.root.elements[1].namespace - assert_equal 'human leg', - XPath.first(doc, '//x:leg/text()', {'x'=>'http://www.foo.com/human'}).to_s - end - - # Alun ap Rhisiart - def test_less_than_in_element_content - doc = File.open(fixture_path('ProductionSupport.xml')) do |source| - REXML::Document.new source - end - h = Hash.new - doc.elements.each("//CommonError") { |el| - h[el.elements['Key'].text] = 'okay' - } - assert(h.include?('MotorInsuranceContract(Object)>>#error:')) - end - - # XPaths provided by Thomas Sawyer - def test_various_xpath - #@doc = REXML::Document.new('

      ') - doc = REXML::Document.new('

      3

      ') - - [['/r', REXML::Element], - ['/r/p/c', REXML::Element], - ['/r/attribute::a', Attribute], - ['/r/@a', Attribute], - ['/r/attribute::*', Attribute], - ['/r/@*', Attribute], - ['/r/p/c/attribute::b', Attribute], - ['/r/p/c/@b', Attribute], - ['/r/p/c/attribute::*', Attribute], - ['/r/p/c/@*', Attribute], - ['//c/attribute::b', Attribute], - ['//c/@b', Attribute], - ['//c/attribute::*', Attribute], - ['//c/@*', Attribute], - ['.//node()', REXML::Node ], - ['.//node()[@a]', REXML::Element ], - ['.//node()[@a="1"]', REXML::Element ], - ['.//node()[@b]', REXML::Element ], # no show, why? - ['.//node()[@b="2"]', REXML::Element ] - ].each do |xpath,kind| - begin - REXML::XPath.each( doc, xpath ) do |what| - assert_kind_of( kind, what, "\n\nWrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n\n" ) - end - rescue Exception - puts "PATH WAS: #{xpath}" - raise - end - end - - [ - ['/r', 'attribute::a', Attribute ], - ['/r', '@a', Attribute ], - ['/r', 'attribute::*', Attribute ], - ['/r', '@*', Attribute ], - ['/r/p/c', 'attribute::b', Attribute ], - ['/r/p/c', '@b', Attribute ], - ['/r/p/c', 'attribute::*', Attribute ], - ['/r/p/c', '@*', Attribute ] - ].each do |nodepath, xpath, kind| - begin - context = REXML::XPath.first(doc, nodepath) - REXML::XPath.each( context, xpath ) do |what| - assert_kind_of kind, what, "Wrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n" - end - rescue Exception - puts "PATH WAS: #{xpath}" - raise - end - end - end - - def test_entities_Holden_Glova - document = <<-EOL - - - - - - - - - - - - - ]> - - - - - uga.rb - 0444 - &rbconfig.libdir;/rexml - ... the file here - - - booga.h - 0444 - &rbconfig.includedir; - ... the file here - - - foo.so - 0555 - &rbconfig.sitearchdir;/rexml - Li4uIHRoZSBmaWxlIGhlcmU=\n - - - - - EOL - - file_xpath = '/rubynet/pkg/files/file' - - root = REXML::Document.new(document) - - root.elements.each(file_xpath) do |metadata| - text = metadata.elements['path'].get_text.value - assert text !~ /&rbconfig/, "'#{text}' failed" - end - - #Error occurred in test_package_file_opens(TC_PackageInstall): - # ArgumentError: - #illegal access mode &rbconfig.prefix;/lib/rexml - # - #[synack@Evergreen] src $ ruby --version - #ruby 1.6.7 (2002-03-01) [i686-linux-gnu] - # - #It looks like it expanded the first entity, but didn't reparse it for more - #entities. possible bug - or have I mucked this up? - end - - def test_whitespace_after_xml_decl - Document.new < - - - - -EOL - end - - def test_external_entity - xp = '//channel/title' - - %w{working.rss broken.rss}.each do |path| - File.open(File.join(fixture_path(path))) do |file| - doc = REXML::Document.new file.readlines.join('') - - # check to make sure everything is kosher - assert_equal( doc.root.class, REXML::Element ) - assert_equal( doc.root.elements.class, REXML::Elements ) - - # get the title of the feed - assert( doc.root.elements[xp].kind_of?( REXML::Element ) ) - end - end - end - - def test_maintain_dtd - src = %q{ - - -%extern-packages; -%extern-common; -]>} - doc = Document.new( src ) - doc.write( out="" ) - src = src.tr('"', "'") - out = out.tr('"', "'") - assert_equal( src, out ) - end - - def test_text_nodes_nomatch - source = "test" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/root/child[text()="no-test"]} ) - assert_equal( 0, r.size ) - end - - def test_raw_Terje_Elde - f = REXML::Formatters::Default.new - txt = 'abcødef' - a = Text.new( txt,false,nil,true ) - f.write(a,out="") - assert_equal( txt, out ) - - txt = 'abcødef' - a = Document.new( txt, { :raw => ["russell"] } ) - f.write(a,out="") - assert_equal( txt, out ) - end - - def test_indenting_error - a=Element.new("test1") - b=Element.new("test2") - c=Element.new("test3") - b << c - a << b - - REXML::Formatters::Pretty.new.write(a,"") - end - - def test_pos - require 'tempfile' - Tempfile.create("tidal") {|testfile| - testdata = %Q{ -
      -760 -50 -
      -
      -} - - testfile.puts testdata - testfile.rewind - assert_nothing_raised do - REXML::Document.new(testfile) - end - } - end - - def test_deep_clone - a = Document.new( '' ) - b = a.deep_clone - assert_equal a.to_s, b.to_s - end - - def test_double_escaping - data = 'AT&T' - xml = "" - - doc = REXML::Document.new(xml) - description = doc.find {|e| e.name=="description"} - assert_equal data, description.text - end - - def test_ticket_12 - cfg = "ab" - - config = REXML::Document.new( cfg ) - - assert_equal( "a", config.elements[ "//child1" ].text ) - end - -=begin - # This is a silly test, and is low priority - def test_namespace_serialization_tobi_reif - doc = Document.new ' - - ' - ns = 'http://www.foo.foo' - ns_declaration={'f'=>ns} - returned = XPath.match(doc,'//f:p',ns_declaration) - # passes: - assert( (returned[0].namespace==ns), 'namespace should be '+ns) - serialized = returned.to_s - serialized_and_parsed = Document.new(serialized) - puts 'serialized: '+serialized - # ... currently brings - # prefix b is undeclared (!) - assert( (serialized_and_parsed.namespace==ns), - 'namespace should still be '+ns.inspect+ - ' and not '+serialized_and_parsed.namespace.inspect) - # ... currently results in a failure: - # 'namespace should still be "http://www.foo.foo" and not ""' - end -=end - end -end diff --git a/ruby/test/rexml/test_core.rb b/ruby/test/rexml/test_core.rb deleted file mode 100644 index 41e6e4354..000000000 --- a/ruby/test/rexml/test_core.rb +++ /dev/null @@ -1,1517 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "rexml_test_utils" - -require "rexml/document" -require "rexml/parseexception" -require "rexml/output" -require "rexml/source" -require "rexml/formatters/pretty" -require "rexml/undefinednamespaceexception" - -require_relative "listener" - -module REXMLTests - class Tester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - def setup - @xsa_source = <<-EOL - - - - - - - - Lars Marius Garshol - larsga@garshol.priv.no - http://www.stud.ifi.uio.no/~lmariusg/ - - - EOL - end - - def test_bad_markup - [ - " foo ", - '<0/>', - '&', - '&a', -# '&a;', # FIXME - '', - '', - '', - '', - '', - '', - '', - "", - "\f", - "", - "\000", -# FIXME '', - '', - '￿', -# FIXME '', -# FIXME '', - ].each do |src| - assert_raise( ParseException, %Q{Parse #{src.inspect} should have failed!} ) do - Document.new(src) - end - end - end - - def test_attribute - # Testing constructors - #a = Attribute.new "hello", "dolly" - #b = Attribute.new a - #d = Document.new( "" ) - #c = d[0].attributes.get_attribute( "hello" ) - - #assert_equal a, b - #for attr in [ a, b, c] - # assert_equal "hello", attr.name - # assert_equal "dolly", attr.value - #end - - # This because of a reported bug in attribute handling in 1.0a8 - source = 'blah' - doc = Document.new source - doc.elements.each do |a| - a.attributes['att'] << 'B' - assert_equal "AB", a.attributes['att'] - a.attributes['att'] = 'C' - assert_equal "C", a.attributes['att'] - end - - # Bryan Murphy - text = "this is a {target[@name='test']/@value} test" - source = <<-EOL - - - EOL - - xml = Document.new source - value = xml.root.attributes["search"] - assert_equal text, value.to_s - - e = Element.new "test" - e.add_attributes({ "name1" => "test1", "name4" => "test4" }) - e.add_attributes([["name3","test3"], ["name2","test2"]]) - assert_equal "test1", e.attributes["name1"] - assert_equal "test2", e.attributes["name2"] - assert_equal "test3", e.attributes["name3"] - assert_equal "test4", e.attributes["name4"] - - # ensure that the attributes come out in sorted order - assert_equal %w().join(' '), e.to_s - end - - def test_attribute_namespace_conflict - # https://www.w3.org/TR/xml-names/#uniqAttrs - message = <<-MESSAGE -Duplicate attribute "a" -Line: 4 -Position: 140 -Last 80 unconsumed characters: - MESSAGE - assert_raise_with_message(REXML::ParseException, message) do - Document.new(<<-XML) - - - - - - XML - end - end - - def test_attribute_default_namespace - # https://www.w3.org/TR/xml-names/#uniqAttrs - document = Document.new(<<-XML) - - - - - - XML - attributes = document.root.elements.collect do |element| - element.attributes.each_attribute.collect do |attribute| - [attribute.prefix, attribute.namespace, attribute.name] - end - end - assert_equal([ - [ - ["", "", "a"], - ["", "", "b"], - ], - [ - ["", "", "a"], - ["n1", "http://www.w3.org", "a"], - ], - ], - attributes) - end - - def test_cdata - test = "The quick brown fox jumped - & < & < \" ' - over the lazy dog." - - source = "" - d = REXML::Document.new( source ) - - # Test constructors - cdata = d[0][0] - assert_equal test, cdata.value - end - - def test_comment - string = "This is a new comment!" - source = "" - comment = Comment.new string - REXML::Formatters::Default.new.write( comment, out = "" ) - assert_equal(source, out) - - comment2 = Comment.new comment - assert_equal(comment, comment2) - - assert_raise(ParseException) { - REXML::Document.new("") - } - assert_raise(ParseException) { - REXML::Document.new(" - - - - - - - - - - - - - - - - - - EOF - doc = Document.new source - assert_equal "someuri", doc.root.namespace - assert_equal "default", doc.root.elements[1].namespace - assert_equal "someuri", doc.root.elements[2].namespace - assert_equal "notdefault", doc.root.elements[ 3 ].namespace - - # Testing namespaces in attributes - source = <<-EOF - - - - - - EOF - doc = Document.new source - b = doc.root.elements["b"] - assert_equal "x", b.attributes["b:a"] - assert_equal "y", b.attributes["a"] - - doc = Document.new - doc.add_element "sean:blah" - doc.root.text = "Some text" - out = "" - doc.write(out) - assert_equal "Some text", out - end - - - def test_add_namespace - e = Element.new 'a' - e.add_namespace 'someuri' - e.add_namespace 'foo', 'otheruri' - e.add_namespace 'xmlns:bar', 'thirduri' - assert_equal 'someuri', e.attributes['xmlns'] - assert_equal 'otheruri', e.attributes['xmlns:foo'] - assert_equal 'thirduri', e.attributes['xmlns:bar'] - end - - - def test_big_documentation - d = File.open(fixture_path("documentation.xml")) {|f| Document.new f } - assert_equal "Sean Russell", d.elements["documentation/head/author"].text.tr("\n\t", " ").squeeze(" ") - out = "" - d.write out - end - - def test_tutorial - doc = File.open(fixture_path("tutorial.xml")) {|f| Document.new f } - out = "" - doc.write out - end - - def test_stream - c = Listener.new - File.open(fixture_path("documentation.xml")) do |f| - Document.parse_stream( f, c ) - end - assert(c.ts, "Stream parsing apparently didn't parse the whole file") - assert(c.te, "Stream parsing dropped end tag for documentation") - - Document.parse_stream(" ", c) - - Document.parse_stream("<>&", c) - assert_equal('<>&', c.normalize) - end - - def test_line - f = File.new(fixture_path("bad.xml")) - Document.new f - assert_fail "There should have been an error" - rescue Exception - # We should get here - assert($!.line == 5, "Should have been an error on line 5, "+ - "but was reported as being on line #{$!.line}" ) - ensure - f.close if f - end - - def test_substitution - val = "a'b\"c" - el = Element.new("a") - el.attributes["x"] = val - REXML::Formatters::Default.new.write(el, out="") - - nel = Document.new( out) - assert_equal( val, nel.root.attributes["x"] ) - end - - def test_exception - source = SourceFactory.create_from "" - p = ParseException.new( "dummy message", source ) - begin - raise "dummy" - rescue Exception - p.continued_exception = $! - end - end - - def test_bad_content - in_gt = 'content>content' - in_lt = 'content' - - # This is OK - tree_gt = Document.new in_gt - assert_equal "content>content", tree_gt.elements[1].text - # This isn't - begin - Document.new in_lt - assert_fail "Should have gotten a parse error" - rescue ParseException - end - end - - def test_iso_8859_1_output_function - out = "" - output = Output.new( out ) - koln_iso_8859_1 = "K\xF6ln" - koln_utf8 = "K\xc3\xb6ln" - source = Source.new( koln_iso_8859_1, 'iso-8859-1' ) - results = source.scan(/.*/)[0] - koln_utf8.force_encoding('UTF-8') if koln_utf8.respond_to?(:force_encoding) - assert_equal koln_utf8, results - output << results - if koln_iso_8859_1.respond_to?(:force_encoding) - koln_iso_8859_1.force_encoding('ISO-8859-1') - end - assert_equal koln_iso_8859_1, out - end - - def test_attributes_each - doc = Document.new("") - count = 0 - doc.root.elements[1].attributes.each {|k,v| count += 1 } - assert_equal 4, count - end - - def test_delete_namespace - doc = Document.new "" - doc.root.delete_namespace - doc.root.delete_namespace 'x' - assert_equal "", doc.to_s - end - - def test_each_element_with_attribute - doc = Document.new "" - arry = [] - block = proc { |e| - assert arry.include?(e.name) - arry.delete e.name - } - # Yields b, c, d - arry = %w{b c d} - doc.root.each_element_with_attribute( 'id', &block ) - assert_equal 0, arry.size - # Yields b, d - arry = %w{b d} - doc.root.each_element_with_attribute( 'id', '1', &block ) - assert_equal 0, arry.size - # Yields b - arry = ['b'] - doc.root.each_element_with_attribute( 'id', '1', 1, &block ) - assert_equal 0, arry.size - # Yields d - arry = ['d'] - doc.root.each_element_with_attribute( 'id', '1', 0, 'd', &block ) - assert_equal 0, arry.size - end - def test_each_element_with_text - doc = Document.new 'bbd' - arry = [] - block = proc { |e| - assert arry.include?(e.name) - arry.delete e.name - } - # Yields b, c, d - arry = %w{b c d} - doc.root.each_element_with_text(&block) - assert_equal 0, arry.size - # Yields b, d - arry = %w{b c} - doc.root.each_element_with_text( 'b', &block ) - assert_equal 0, arry.size - # Yields b - arry = ['b'] - doc.root.each_element_with_text( 'b', 1, &block ) - assert_equal 0, arry.size - # Yields d - arry = ['d'] - doc.root.each_element_with_text( nil, 0, 'd', &block ) - assert_equal 0, arry.size - end - - def test_element_parse_stream - s = Source.new( "some text" ) - l = Listener.new - class << l - def tag_start name, attributes - raise "Didn't find proper tag name" unless 'a'==name - end - end - - Document::parse_stream(s, l) - end - - def test_deep_clone - a = Document.new( 'texttexttext' ) - b = a.deep_clone - assert_equal a.to_s, b.to_s - - a = Document.new( 'some < text more > text > ' ) - b = a.deep_clone - assert_equal a.to_s, b.to_s - c = Document.new( b.to_s ) - assert_equal a.to_s, c.to_s - end - - def test_whitespace_before_root - a = < - - - - -EOL - d = Document.new(a) - b = "" - d.write( b ) - assert_equal a,b - end - - def test_entities - a = Document.new( 'eeü' ) - assert_equal('eeü'.force_encoding("UTF-8"), a.root.text) - end - - def test_element_decl - element_decl = Source.new(" -]>") - doc = Document.new( element_decl ) - d = doc[0] - assert_equal("", d.to_s.split(/\n/)[1].strip) - end - - def test_attlist_decl - doc = Document.new <<-EOL - - - ]> - - EOL - assert_equal 'gobble', doc.root.attributes['bar'] - assert_equal 'xxx', doc.root.elements[2].namespace - assert_equal 'two', doc.root.elements[1].namespace - assert_equal 'foo', doc.root.namespace - - doc = Document.new <<-EOL - - - - ]> - - EOL - prefixes = doc.root.prefixes.sort - correct = ['svg', 'xlink', 'xml'] - assert_equal correct, prefixes - end - - def test_attlist_write - doc = File.open(fixture_path("foo.xml")) {|file| Document.new file } - out = '' - doc.write(out) - end - - def test_more_namespaces - assert_raise( REXML::UndefinedNamespaceException, - %Q{Should have gotten an Undefined Namespace error} ) { - Document.new("

      ") - } - doc2 = Document.new("

      ") - es = XPath.match(doc2, '//c') - assert_equal 0, es.size - es = XPath.match(doc2, '//n:c') - assert_equal 1, es.size - doc2.root.add_namespace('m', '2') - doc2.root.add_element("m:o") - es = XPath.match(doc2, './/o') - assert_equal 0, es.size - es = XPath.match(doc2, '//n:c') - assert_equal 1, es.size - end - - def test_ticket_51 - doc = REXML::Document.new <<-EOL - - X - Y - - - Z - - - EOL - - # The most common case. People not caring about the namespaces much. - assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()" ).join ) - assert_equal( "XY", XPath.match( doc, "/*:test/x:a/text()" ).join ) - # Surprising? I don't think so, if you believe my definition of the "common case" - assert_equal( "XYZ", XPath.match( doc, "//*:a/text()" ).join ) - - # These are the uncommon cases. Namespaces are actually important, so we define our own - # mappings, and pass them in. - assert_equal( "XY", XPath.match( doc, "/f:test/f:a/text()", { "f" => "1" } ).join ) - # The namespaces are defined, and override the original mappings - assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()", { "f" => "1" } ).join ) - assert_equal( "", XPath.match( doc, "/x:test/x:a/text()", { "f" => "1" } ).join ) - assert_equal( "XYZ", XPath.match( doc, "//*:a/text()", { "f" => "1" } ).join ) - end - - def test_processing_instruction - d = Document.new("") - assert_equal 4, XPath.match(d, '//processing-instruction()' ).size - match = XPath.match(d, "//processing-instruction('foo3')" ) - assert_equal 1, match.size - assert_equal 'bar3', match[0].content - end - - def test_oses_with_bad_EOLs - Document.new("\n\n\n\n\n\n\n\n") - end - - # Contributed (with patch to fix bug) by Kouhei - def test_ignore_whitespace - source = " abc " - - context_all = {:ignore_whitespace_nodes => :all} - context_a = {:ignore_whitespace_nodes => %(a)} - context_b = {:ignore_whitespace_nodes => %(b)} - - tests = [[[" abc ", "def"], context_all], - [[" abc ", "def"], context_a], - [[" ", " abc ", "def", " "], context_b]] - - tests.each do |test| - assert_equal(test[0], Document.new(source, test[1]).root.texts.collect{|x| - x.to_s}) - end - end - - def test_0xD_in_preface - doc = "\x0D\x0D" - doc = Document.new doc - end - - def test_hyphens_in_doctype - doc = REXML::Document.new <<-EOQ - - - - - - EOQ - - assert_equal('a-b-c', doc.doctype.name) - end - - def test_accents - docs = [ - %Q{ - - - - -}, - ' - - - - -', - %Q{ - - - - -}, - %Q{ - - - - -} ] - docs.each_with_index { |d,i| - begin - REXML::Document.new(d) - rescue - puts "#{i} => #{docs[i]}" - raise - end - } - end - - def test_replace_text - e = REXML::Element.new( "a" ) - e.add_text( "foo" ) - assert_equal( "foo", e.to_s ) - e[0].value = "bar" - assert_equal( "bar", e.to_s ) - e[0].value = "<" - assert_equal( "<", e.to_s ) - assert_equal( "<", e[0].value ) - end - - - def test_write_doctype - ## XML Document and Declaration - document = REXML::Document.new - xmldecl = REXML::XMLDecl.new("1.0", "UTF-8") - document.add(xmldecl) - s = "" - document.write(s) - - ## XML Doctype - str = '' - source = REXML::Source.new(str) - doctype = REXML::DocType.new(source) - document.add(doctype) - document.write(s) - - ## Element - element = REXML::Element.new("hoge") - document.add(element) - - document.write(s) - end - - def test_write_cdata - src = "A" - doc = REXML::Document.new( src ) - out = "" - doc.write( out ) - assert_equal( src, out ) - - src = "" - doc = REXML::Document.new( src ) - out = "" - doc.write( out ) - assert_equal( src, out ) - end - - def test_namespace_attributes - source = <<-EOL - - - - EOL - d = Document.new( source ) - assert_equal( 'foo', REXML::XPath.first(d.root, "//x:b/@x:n").value ) - assert_equal( nil, REXML::XPath.first(d.root, "//x:b/@x:n", {})) - end - - def test_null_element_name - a = REXML::Document.new - assert_raise( RuntimeError ) { - a.add_element( nil ) - } - end - - def test_text_raw - # From the REXML tutorial - # (http://www.germane-software.com/software/rexml/test/data/tutorial.html) - doc = Document.new <<-EOL - - - ]> - - EOL - a = doc.root - - # This makes sure that RAW text nodes don't have their entity strings - # replaced - t = Text.new "Sean", false, nil, true - a.text = t - assert_equal( "Sean", t.to_s ) - assert_equal( "Sean", t.value ) - - # This makes sure that they do - t = Text.new "Sean", false, nil, false - a.text = t - assert_equal( "&s;", t.to_s ) - assert_equal( "Sean", t.value ) - - t = Text.new "&s;", false, nil, true - a.text = t - assert_equal( "&s;", t.to_s ) - assert_equal( "Sean", t.value ) - - t = Text.new "&s;", false, nil, true - a.text = t - assert_equal( "&s;", t.to_s ) - assert_equal( "Sean", t.value ) - - # Ticket #44 - t = REXML::Text.new( "&", false, nil, true ) - assert_equal( "&", t.to_s ) - - t = REXML::Text.new("&", false, false) - assert_equal( "&amp;", t.to_s ) - end - - def test_to_xpath - doc = REXML::Document.new( %q{ - - - }) - names = %w{ /tag1/tag2[1] /tag1/tag2[2] } - doc.root.elements.each_with_index {|el, i| - assert_equal( names[i], el.xpath ) - } - end - - def test_transitive - doc = REXML::Document.new( "") - s = "" - doc.write( s, 0, true ) - end - - # This is issue #40 - def test_replace_with - old = 'oldold' - d = REXML::Document.new(old).root - new = REXML::Text.new('new',true,nil,true) - child = d.children[2] - child.replace_with(new) - assert_equal( new, d.children[2] ) - end - - def test_repeated_writes - a = IO.read(fixture_path("iso8859-1.xml")) - f = REXML::Formatters::Pretty.new - - xmldoc = REXML::Document.new( a ) - a_andre = xmldoc.elements['//image'].attributes['caption'] - - f.write(xmldoc,b="") - - xmldoc = REXML::Document.new(b) - b_andre = xmldoc.elements['//image'].attributes['caption'] - assert_equal( a_andre, b_andre ) - - f.write(xmldoc,c="") - - xmldoc = REXML::Document.new(c) - c_andre = xmldoc.elements['//image'].attributes['caption'] - assert_equal( b_andre, c_andre ) - - o = Output.new(d="","UTF-8") - f.write(xmldoc,o) - assert_not_equal( c, d ) - end - - def test_pretty_format_long_text_finite - n = 1_000_000 - long_text = 'aaaa ' * n - xml = "#{long_text}" - formatter = REXML::Formatters::Pretty.new - document = nil - begin - document = REXML::Document.new(xml) - rescue REXML::ParseException - skip_message = "skip this test because we can't check Pretty#wrap " + - "works without # on " + - "small memory system. # " + - "will be raised on the system. See also [ruby-dev:42599]." - return skip_message - end - output = "" - formatter.write(document, output) - assert_equal("\n" + - ((" " + (" aaaa" * 15) + "\n") * (n / 15)) + - " " + ("aaaa " * (n % 15)) + "\n" + - "", - output) - end - - def test_pretty_format_deep_indent - n = 6 - elements = "" - n.times do |i| - elements << "" - elements << "element#{i} " * 5 - end - (n - 1).downto(0) do |i| - elements << "" - end - xml = "#{elements}" - document = REXML::Document.new(xml) - formatter = REXML::Formatters::Pretty.new - formatter.width = 20 - output = "" - formatter.write(document, output) - assert_equal(<<-XML.strip, output) - - - element0 - element0 - element0 - element0 - element0\s - - element1 - element1 - element1 - element1 - element1\s - - element2 - element2 - element2 - element2 - element2\s - - element3 - element3 - element3 - element3 - element3\s - - element4 - element4 - element4 - element4 - element4 - \s - - element5 element5 element5 element5 element5\s - - - - - - - - XML - end - - def test_ticket_58 - doc = REXML::Document.new - doc << REXML::XMLDecl.default - doc << REXML::Element.new("a") - - str = "" - doc.write(str) - - assert_equal("", str) - - doc = REXML::Document.new - doc << REXML::XMLDecl.new("1.0", "UTF-8") - doc << REXML::Element.new("a") - - str = "" - doc.write(str) - - assert_equal("", str) - end - - # Incomplete tags should generate an error - def test_ticket_53 - assert_raise( REXML::ParseException ) { - REXML::Document.new( "" ) - } - assert_raise( REXML::ParseException ) { - REXML::Document.new( "" ) - } - assert_raise( REXML::ParseException ) { - REXML::Document.new( "" ) - } - end - - def test_ticket_52 - source = "" - d = REXML::Document.new(source) - d.write(k="") - assert_equal( source, k ) - - source = "" - target = "\n \n" - d = REXML::Document.new(source) - REXML::Formatters::Pretty.new(4).write(d,k="") - assert_equal( target, k ) - end - - def test_ticket_76 - src = "
      at&t" - assert_raise( ParseException, %Q{"#{src}" is invalid XML} ) { - REXML::Document.new(src) - } - end - - def test_ticket_21 - src = "" - exception = assert_raise(ParseException) do - Document.new(src) - end - assert_equal(<<-DETAIL, exception.to_s) -Missing attribute value start quote: -Line: 1 -Position: 16 -Last 80 unconsumed characters: - DETAIL - end - - def test_ticket_63 - File.open(fixture_path("t63-1.xml")) {|f| Document.new(f) } - end - - def test_ticket_75 - d = File.open(fixture_path("t75.xml")) {|f| REXML::Document.new(f) } - assert_equal("tree", d.root.name) - end - - def test_ticket_48_part_II - f = REXML::Formatters::Pretty.new - #- rexml sanity check (bugs in ruby 1.8.4, ruby 1.8.6) - xmldoc = Document.new("") - xmldoc << XMLDecl.new(XMLDecl::DEFAULT_VERSION, "UTF-8") - content = ['61c3a927223c3e26'].pack("H*") - content.force_encoding('UTF-8') if content.respond_to?(:force_encoding) - #- is some UTF-8 text but just to make sure my editor won't magically convert.. - xmldoc.root.add_attribute('attr', content) - f.write(xmldoc,out=[]) - - xmldoc = REXML::Document.new(out.join) - sanity1 = xmldoc.root.attributes['attr'] - f.write(xmldoc,out=[]) - - xmldoc = REXML::Document.new(out.join) - sanity2 = xmldoc.root.attributes['attr'] - f.write(xmldoc,out=[]) - - assert_equal( sanity1, sanity2 ) - end - - def test_ticket_88 - doc = REXML::Document.new("") - assert_equal("", doc.to_s) - doc = REXML::Document.new("") - assert_equal("", doc.to_s) - end - - def test_ticket_85 - xml = < - - - - -ENDXML - - yml = " - - - -" - - # The pretty printer ignores all whitespace, anyway so output1 == output2 - f = REXML::Formatters::Pretty.new( 2 ) - d = Document.new( xml, :ignore_whitespace_nodes=>:all ) - f.write( d, output1="" ) - - d = Document.new( xml ) - f.write( d, output2="" ) - - # Output directives should override whitespace directives. - assert_equal( output1, output2 ) - - # The base case. - d = Document.new(yml) - f.write( d, output3="" ) - - assert_equal( output3.strip, output2.strip ) - - d = Document.new(yml) - f.write( d, output4="" ) - - assert_equal( output3.strip, output4.strip ) - end - - def test_ticket_91 - source=" - - great - - " - expected=" - - great - - -" - d = Document.new( source ) - d.root.add_element( "bah" ) - p=REXML::Formatters::Pretty.new(2) - p.compact = true # Don't add whitespace to text nodes unless necessary - p.write(d,out="") - assert_equal( expected, out ) - end - - def test_ticket_95 - testd = REXML::Document.new "" - testd.write(out1="") - testd.elements["//c[2]"].xpath - testd.write(out2="") - assert_equal(out1,out2) - end - - def test_ticket_102 - doc = REXML::Document.new '' - assert_equal( "foo", doc.root.elements["*:item"].attribute("name","ns").to_s ) - assert_equal( "item", doc.root.elements["*:item[@name='foo']"].name ) - end - - def test_ticket_14 - # Per .2.5 Node Tests of XPath spec - assert_raise( REXML::UndefinedNamespaceException, - %Q{Should have gotten an Undefined Namespace error} ) { - Document.new("") - } - end - - # 5.7 Text Nodes - # Character data is grouped into text nodes. As much character data as - # possible is grouped into each text node: a text node never has an - # immediately following or preceding sibling that is a text node. The - # string-value of a text node is the character data. A text node always has - # at least one character of data. - def test_ticket_105 - d = Document.new("") - d.root.add_text( "a" ) - d.root.add_text( "b" ) - assert_equal( 1, d.root.children.size ) - end - - # phantom namespace same as default namespace - def test_ticket_121 - doc = REXML::Document.new( - 'text' - ) - assert_equal 'text', doc.text( "/*:doc/*:item[@name='foo']" ) - assert_equal "name='foo'", - doc.root.elements["*:item"].attribute("name", "ns").inspect - assert_equal "text", - doc.root.elements["*:item[@name='foo']"].to_s - end - - def test_ticket_135 - bean_element = REXML::Element.new("bean") - textToAdd = "(&(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))" - bean_element.add_element("prop", {"key"=> "filter"}).add_text(textToAdd) - doc = REXML::Document.new - doc.add_element(bean_element) - - REXML::Formatters::Pretty.new(3).write( doc, out = "" ) - - assert_equal "\n \n (&#38;(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))\n \n", out - end - - def test_ticket_138 - doc = REXML::Document.new( - '' - ) - expected = { - "inkscape" => attribute("xmlns:inkscape", - "http://www.inkscape.org/namespaces/inkscape"), - "version" => { - "inkscape" => attribute("inkscape:version", "0.44"), - "" => attribute("version", "1.0"), - }, - } - assert_equal(expected, doc.root.attributes) - assert_equal(expected, REXML::Document.new(doc.root.to_s).root.attributes) - end - - def test_empty_doc - assert(REXML::Document.new('').children.empty?) - end - - private - def attribute(name, value) - REXML::Attribute.new(name, value) - end - end -end diff --git a/ruby/test/rexml/test_doctype.rb b/ruby/test/rexml/test_doctype.rb deleted file mode 100644 index 7f4266917..000000000 --- a/ruby/test/rexml/test_doctype.rb +++ /dev/null @@ -1,157 +0,0 @@ -# frozen_string_literal: false - -require_relative "rexml_test_utils" - -module REXMLTests - class TestDocTypeAccessor < Test::Unit::TestCase - def setup - @sysid = "urn:x-test:sysid1" - @notation_id1 = "urn:x-test:notation1" - @notation_id2 = "urn:x-test:notation2" - xml_system = <<-XML - - - ]> - - XML - @doc_type_system = REXML::Document.new(xml_system).doctype - - @pubid = "TEST_ID" - xml_public = <<-XML - - - XML - @doc_type_public = REXML::Document.new(xml_public).doctype - - xml_public_system = <<-XML - - - XML - @doc_type_public_system = REXML::Document.new(xml_public_system).doctype - end - - def test_public - assert_equal([ - nil, - @pubid, - @pubid, - ], - [ - @doc_type_system.public, - @doc_type_public.public, - @doc_type_public_system.public, - ]) - end - - def test_to_s - assert_equal("", - @doc_type_public_system.to_s) - end - - def test_to_s_apostrophe - @doc_type_public_system.parent.context[:prologue_quote] = :apostrophe - assert_equal("", - @doc_type_public_system.to_s) - end - - def test_system - assert_equal([ - @sysid, - nil, - @sysid, - ], - [ - @doc_type_system.system, - @doc_type_public.system, - @doc_type_public_system.system, - ]) - end - - def test_notation - assert_equal([ - @notation_id1, - @notation_id2, - ], - [ - @doc_type_system.notation("n1").system, - @doc_type_system.notation("n2").system, - ]) - end - - def test_notations - notations = @doc_type_system.notations - assert_equal([ - @notation_id1, - @notation_id2, - ], - notations.collect(&:system)) - end - end - - class TestNotationDeclPublic < Test::Unit::TestCase - def setup - @name = "vrml" - @id = "VRML 1.0" - @uri = "http://www.web3d.org/" - end - - def test_to_s - assert_equal("", - decl(@id, nil).to_s) - end - - def test_to_s_with_uri - assert_equal("", - decl(@id, @uri).to_s) - end - - def test_to_s_apostrophe - document = REXML::Document.new(<<-XML) - - - XML - document.context[:prologue_quote] = :apostrophe - notation = document.doctype.notations[0] - assert_equal("", - notation.to_s) - end - - private - def decl(id, uri) - REXML::NotationDecl.new(@name, "PUBLIC", id, uri) - end - end - - class TestNotationDeclSystem < Test::Unit::TestCase - def setup - @name = "gif" - @id = "gif viewer" - end - - def test_to_s - assert_equal("", - decl(@id).to_s) - end - - def test_to_s_apostrophe - document = REXML::Document.new(<<-XML) - - - XML - document.context[:prologue_quote] = :apostrophe - notation = document.doctype.notations[0] - assert_equal("", - notation.to_s) - end - - private - def decl(id) - REXML::NotationDecl.new(@name, "SYSTEM", id, nil) - end - end -end diff --git a/ruby/test/rexml/test_document.rb b/ruby/test/rexml/test_document.rb deleted file mode 100644 index c0faae4ae..000000000 --- a/ruby/test/rexml/test_document.rb +++ /dev/null @@ -1,416 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require "rexml/document" -require "test/unit" - -module REXMLTests - class TestDocument < Test::Unit::TestCase - def test_version_attributes_to_s - doc = REXML::Document.new(<<-eoxml) - - - - eoxml - - string = doc.to_s - assert_match('xmlns:sodipodi', string) - assert_match('xmlns:inkscape', string) - assert_match('sodipodi:version', string) - assert_match('inkscape:version', string) - end - - def test_new - doc = REXML::Document.new(< -Hello world! -EOF - assert_equal("Hello world!", doc.root.children.first.value) - end - - class EntityExpansionLimitTest < Test::Unit::TestCase - def setup - @default_entity_expansion_limit = REXML::Security.entity_expansion_limit - end - - def teardown - REXML::Security.entity_expansion_limit = @default_entity_expansion_limit - end - - class GeneralEntityTest < self - def test_have_value - xml = < - - - - - - - -]> - -&a; - -EOF - - doc = REXML::Document.new(xml) - assert_raise(RuntimeError) do - doc.root.children.first.value - end - REXML::Security.entity_expansion_limit = 100 - assert_equal(100, REXML::Security.entity_expansion_limit) - doc = REXML::Document.new(xml) - assert_raise(RuntimeError) do - doc.root.children.first.value - end - assert_equal(101, doc.entity_expansion_count) - end - - def test_empty_value - xml = < - - - - - - - -]> - -&a; - -EOF - - doc = REXML::Document.new(xml) - assert_raise(RuntimeError) do - doc.root.children.first.value - end - REXML::Security.entity_expansion_limit = 100 - assert_equal(100, REXML::Security.entity_expansion_limit) - doc = REXML::Document.new(xml) - assert_raise(RuntimeError) do - doc.root.children.first.value - end - assert_equal(101, doc.entity_expansion_count) - end - - def test_with_default_entity - xml = < - - -]> - -&a; -&a2; -< - -EOF - - REXML::Security.entity_expansion_limit = 4 - doc = REXML::Document.new(xml) - assert_equal("\na\na a\n<\n", doc.root.children.first.value) - REXML::Security.entity_expansion_limit = 3 - doc = REXML::Document.new(xml) - assert_raise(RuntimeError) do - doc.root.children.first.value - end - end - end - - class ParameterEntityTest < self - def test_have_value - xml = < - - - - - - - -]> - -EOF - - assert_raise(REXML::ParseException) do - REXML::Document.new(xml) - end - REXML::Security.entity_expansion_limit = 100 - assert_equal(100, REXML::Security.entity_expansion_limit) - assert_raise(REXML::ParseException) do - REXML::Document.new(xml) - end - end - - def test_empty_value - xml = < - - - - - - - -]> - -EOF - - assert_raise(REXML::ParseException) do - REXML::Document.new(xml) - end - REXML::Security.entity_expansion_limit = 100 - assert_equal(100, REXML::Security.entity_expansion_limit) - assert_raise(REXML::ParseException) do - REXML::Document.new(xml) - end - end - end - end - - def test_tag_in_cdata_with_not_ascii_only_but_ascii8bit_encoding_source - tag = "..." - message = "ã“ã‚“ã«ã¡ã¯ã€ä¸–界ï¼" # Hello world! in Japanese - xml = < - -EOX - xml.force_encoding(Encoding::ASCII_8BIT) - doc = REXML::Document.new(xml) - assert_equal("#{tag}#{message}", doc.root.children.first.value) - end - - def test_xml_declaration_standalone - bug2539 = '[ruby-core:27345]' - doc = REXML::Document.new('') - assert_equal('no', doc.stand_alone?, bug2539) - doc = REXML::Document.new('') - assert_equal('no', doc.stand_alone?, bug2539) - doc = REXML::Document.new('') - assert_equal('no', doc.stand_alone?, bug2539) - end - - class WriteTest < Test::Unit::TestCase - def setup - @document = REXML::Document.new(<<-EOX) - -Hello world! -EOX - end - - class ArgumentsTest < self - def test_output - output = "" - @document.write(output) - assert_equal(<<-EOX, output) - -Hello world! -EOX - end - - def test_indent - output = "" - indent = 2 - @document.write(output, indent) - assert_equal(<<-EOX.chomp, output) - - - Hello world! - -EOX - end - - def test_transitive - output = "" - indent = 2 - transitive = true - @document.write(output, indent, transitive) - assert_equal(<<-EOX, output) - -Hello world! -EOX - end - - def test_ie_hack - output = "" - indent = -1 - transitive = false - ie_hack = true - document = REXML::Document.new("") - document.write(output, indent, transitive, ie_hack) - assert_equal("", output) - end - - def test_encoding - output = "" - indent = -1 - transitive = false - ie_hack = false - encoding = "Windows-31J" - - @document.xml_decl.encoding = "Shift_JIS" - japanese_text = "ã“ã‚“ã«ã¡ã¯" - @document.root.text = japanese_text - @document.write(output, indent, transitive, ie_hack, encoding) - assert_equal(<<-EOX.encode(encoding), output) - -#{japanese_text} -EOX - end - end - - class OptionsTest < self - def test_output - output = "" - @document.write(:output => output) - assert_equal(<<-EOX, output) - -Hello world! -EOX - end - - def test_indent - output = "" - @document.write(:output => output, :indent => 2) - assert_equal(<<-EOX.chomp, output) - - - Hello world! - -EOX - end - - def test_transitive - output = "" - @document.write(:output => output, :indent => 2, :transitive => true) - assert_equal(<<-EOX, output) - -Hello world! -EOX - end - - def test_ie_hack - output = "" - document = REXML::Document.new("") - document.write(:output => output, :ie_hack => true) - assert_equal("", output) - end - - def test_encoding - output = "" - encoding = "Windows-31J" - @document.xml_decl.encoding = "Shift_JIS" - japanese_text = "ã“ã‚“ã«ã¡ã¯" - @document.root.text = japanese_text - @document.write(:output => output, :encoding => encoding) - assert_equal(<<-EOX.encode(encoding), output) - -#{japanese_text} -EOX - end - end - end - - class BomTest < Test::Unit::TestCase - class HaveEncodingTest < self - def test_utf_8 - xml = <<-EOX.force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-8", document.encoding) - end - - def test_utf_16le - xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-16", document.encoding) - end - - def test_utf_16be - xml = <<-EOX.encode("UTF-16BE").force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".encode("UTF-16BE").force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-16", document.encoding) - end - end - - class NoEncodingTest < self - def test_utf_8 - xml = <<-EOX.force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-8", document.encoding) - end - - def test_utf_16le - xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-16", document.encoding) - end - - def test_utf_16be - xml = <<-EOX.encode("UTF-16BE").force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".encode("UTF-16BE").force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - assert_equal("UTF-16", document.encoding) - end - end - - class WriteTest < self - def test_utf_16 - xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT") - -Hello world! -EOX - bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT") - document = REXML::Document.new(bom + xml) - - actual_xml = "" - document.write(actual_xml) - expected_xml = <<-EOX.encode("UTF-16BE") -\ufeff -Hello world! -EOX - assert_equal(expected_xml, actual_xml) - end - end - end - end -end diff --git a/ruby/test/rexml/test_element.rb b/ruby/test/rexml/test_element.rb deleted file mode 100644 index 82830b44e..000000000 --- a/ruby/test/rexml/test_element.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: false - -require "test/unit/testcase" -require "rexml/document" - -module REXMLTests - class ElementTester < Test::Unit::TestCase - def test_array_reference_string - doc = REXML::Document.new("") - assert_equal("Ruby", doc.root["name"]) - end - - def test_array_reference_symbol - doc = REXML::Document.new("") - assert_equal("Ruby", doc.root[:name]) - end - end -end diff --git a/ruby/test/rexml/test_elements.rb b/ruby/test/rexml/test_elements.rb deleted file mode 100644 index a850e6220..000000000 --- a/ruby/test/rexml/test_elements.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: false -require 'test/unit/testcase' -require 'rexml/document' - -module REXMLTests - class ElementsTester < Test::Unit::TestCase - include REXML - def test_accessor - doc = Document.new '' - assert_equal 'b', doc.root.elements[1].name - assert_equal '1', doc.root.elements['c'].attributes['id'] - assert_equal '2', doc.root.elements[2,'c'].attributes['id'] - end - - def test_indexing - doc = Document.new '' - doc.root.elements[10] = Element.new('b') - assert_equal 'b', doc.root.elements[1].name - doc.root.elements[1] = Element.new('c') - assert_equal 'c', doc.root.elements[1].name - doc.root.elements['c'] = Element.new('d') - assert_equal 'd', doc.root.elements[1].name - end - - def test_delete - doc = Document.new '' - block = proc { |str| - out = '' - doc.write out - assert_equal str, out - } - b = doc.root.elements[1] - doc.root.elements.delete b - block.call( "" ) - doc.elements.delete("a/c[@id='1']") - block.call( '' ) - doc.root.elements.delete 1 - block.call( '' ) - end - - def test_delete_all - doc = Document.new '' - deleted = doc.elements.delete_all 'a/c' - assert_equal 4, deleted.size - end - - def test_ticket_36 - doc = Document.new( "" ) - - deleted = doc.root.elements.delete_all( "xi:c" ) - assert_equal( 1, deleted.size ) - - doc = Document.new( "" ) - deleted = doc.root.elements.delete_all( "//xi:c" ) - assert_equal( 2, deleted.size ) - end - - def test_add - a = Element.new 'a' - a.elements.add Element.new('b') - assert_equal 'b', a.elements[1].name - a.elements.add 'c' - assert_equal 'c', a.elements[2].name - end - - def test_size - doc = Document.new 'seanelliottrussell' - assert_equal 6, doc.root.size - assert_equal 3, doc.root.elements.size - end - - def test_each - doc = Document.new 'sean' - count = 0 - block = proc {|e| count += 1} - doc.root.elements.each(&block) - assert_equal 6, count - count = 0 - doc.root.elements.each('b', &block) - assert_equal 2, count - count = 0 - doc.root.elements.each('child::node()', &block) - assert_equal 6, count - count = 0 - XPath.each(doc.root, 'child::node()', &block) - assert_equal 7, count - end - - def test_each_with_frozen_condition - doc = Document.new('') - names = [] - doc.root.elements.each('book'.freeze) do |element| - names << element.attributes["name"] - end - assert_equal(["Ruby", "XML"], names) - end - - def test_to_a - doc = Document.new 'seanelliott' - assert_equal 2, doc.root.elements.to_a.size - assert_equal 2, doc.root.elements.to_a("child::node()").size - assert_equal 4, XPath.match(doc.root, "child::node()").size - end - - def test_collect - doc = Document.new( "" ) - r = doc.elements.collect( "/a/b" ) { |e| e.attributes["id"].to_i } - assert_equal( [1,2], r ) - end - - def test_inject - doc = Document.new( "" ) - r = doc.elements.inject( "/a/b", 3 ) { |s, e| - s + e.attributes["id"].to_i - } - assert_equal 6, r - end - end -end diff --git a/ruby/test/rexml/test_encoding.rb b/ruby/test/rexml/test_encoding.rb deleted file mode 100644 index 919db131f..000000000 --- a/ruby/test/rexml/test_encoding.rb +++ /dev/null @@ -1,108 +0,0 @@ -# coding: binary -# frozen_string_literal: false - -require_relative "rexml_test_utils" - -require 'rexml/source' -require 'rexml/document' - -module REXMLTests - class EncodingTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - - def setup - @encoded_root = "\346" - @encoded = ""+ - @encoded_root - @not_encoded = "ĉ" - end - - # Given an encoded document, try to write out to that encoding - def test_encoded_in_encoded_out - doc = Document.new( @encoded ) - doc.write( out="" ) - out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @encoded, out ) - end - - # Given an encoded document, try to change the encoding and write it out - def test_encoded_in_change_out - doc = Document.new( @encoded ) - doc.xml_decl.encoding = "UTF-8" - assert_equal("UTF-8", doc.encoding) - REXML::Formatters::Default.new.write( doc.root, out="" ) - out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @not_encoded, out ) - char = XPath.first( doc, "/a/b/text()" ).to_s - char.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( "ĉ", char ) - end - - # * Given an encoded document, try to write it to a different encoding - def test_encoded_in_different_out - doc = Document.new( @encoded ) - REXML::Formatters::Default.new.write( doc.root, Output.new( out="", "UTF-8" ) ) - out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @not_encoded, out ) - end - - # * Given a non-encoded document, change the encoding - def test_in_change_out - doc = Document.new( @not_encoded ) - doc.xml_decl.encoding = "ISO-8859-3" - assert_equal("ISO-8859-3", doc.encoding) - doc.write( out="" ) - out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @encoded, out ) - end - - # * Given a non-encoded document, write to a different encoding - def test_in_different_out - doc = Document.new( @not_encoded ) - doc.write( Output.new( out="", "ISO-8859-3" ) ) - out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( "#{@encoded_root}", out ) - end - - # * Given an encoded document, accessing text and attribute nodes - # should provide UTF-8 text. - def test_in_different_access - doc = Document.new <<-EOL - - \xFF - EOL - expect = "\303\277" - expect.force_encoding(::Encoding::UTF_8) - assert_equal( expect, doc.elements['a'].attributes['a'] ) - assert_equal( expect, doc.elements['a'].text ) - end - - - def test_ticket_89 - doc = Document.new <<-EOL - - - EOL - - REXML::Document.new doc - end - - def test_parse_utf16 - utf16 = File.open(fixture_path("utf16.xml")) do |f| - REXML::Document.new(f) - end - assert_equal("UTF-16", utf16.encoding) - assert( utf16[0].kind_of?(REXML::XMLDecl)) - end - - def test_parse_utf16_with_utf8_default_internal - EnvUtil.with_default_internal("UTF-8") do - utf16 = File.open(fixture_path("utf16.xml")) do |f| - REXML::Document.new(f) - end - assert_equal("UTF-16", utf16.encoding) - end - end - end -end diff --git a/ruby/test/rexml/test_entity.rb b/ruby/test/rexml/test_entity.rb deleted file mode 100644 index 6dc663707..000000000 --- a/ruby/test/rexml/test_entity.rb +++ /dev/null @@ -1,206 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" - -require 'rexml/document' -require 'rexml/entity' -require 'rexml/source' - -module REXMLTests - class EntityTester < Test::Unit::TestCase - def test_parse_general_decl - simple = "" - simple =~ /#{REXML::Entity::GEDECL}/ - assert $& - assert_equal simple, $& - - REXML::Entity::ENTITYDECL =~ simple - assert REXML::Entity::matches?(simple) - match = REXML::Entity::ENTITYDECL.match(simple) - assert_equal 'foo', match[1] - assert_equal "'bar'", match[2] - - simple = '' - assert REXML::Entity::matches?(simple) - match = REXML::Entity::ENTITYDECL.match(simple) - assert_equal 'Pub-Status', match[1] - assert_equal '"This is a pre-release of the specification."', match[2] - - txt = '"This is a - pre-release of specification."' - simple = "" - assert REXML::Entity::matches?(simple) - match = REXML::Entity::ENTITYDECL.match(simple) - assert_equal 'Pub-Status', match[1] - assert_equal txt, match[2] - end - - def test_parse_external_decl - zero = '' - one = '' - two = '' - three = '' - assert REXML::Entity::matches?(zero) - assert REXML::Entity::matches?(one) - assert REXML::Entity::matches?(two) - assert REXML::Entity::matches?(three) - end - - def test_parse_entity - one = %q{} - two = %q{} - assert REXML::Entity::matches?(one) - assert REXML::Entity::matches?(two) - end - - def test_constructor - one = [ %q{}, - %q{}, - %q{}, - '', - '', - '' ] - source = %q{ - - - - - - ]>} - - d = REXML::Document.new( source ) - dt = d.doctype - c = 0 - dt.each do |child| - if child.kind_of? REXML::Entity - str = one[c].tr("\r\n\t", ' ').squeeze(" ") - assert_equal str, child.to_s - c+=1 - end - end - end - - def test_replace_entities - source = "\n]>&foo;" - doc = REXML::Document.new(source) - assert_equal 'bar', doc.root.text - out = '' - doc.write out - assert_equal source, out - end - - def test_entity_string_limit - template = ' ]> $' - len = 5120 # 5k per entity - template.sub!(/\^/, "B" * len) - - # 10k is OK - entities = '&a;' * 2 # 5k entity * 2 = 10k - xmldoc = REXML::Document.new(template.sub(/\$/, entities)) - assert_equal(len * 2, xmldoc.root.text.bytesize) - - # above 10k explodes - entities = '&a;' * 3 # 5k entity * 2 = 15k - xmldoc = REXML::Document.new(template.sub(/\$/, entities)) - assert_raise(RuntimeError) do - xmldoc.root.text - end - end - - def test_entity_string_limit_for_parameter_entity - template = ' ]>' - len = 5120 # 5k per entity - template.sub!(/\^/, "B" * len) - - # 10k is OK - entities = '%a;' * 2 # 5k entity * 2 = 10k - REXML::Document.new(template.sub(/\$/, entities)) - - # above 10k explodes - entities = '%a;' * 3 # 5k entity * 2 = 15k - assert_raise(REXML::ParseException) do - REXML::Document.new(template.sub(/\$/, entities)) - end - end - - def test_raw - source = ' -]>replace &ent;' - doc = REXML::Document.new( source, {:raw=>:all}) - assert_equal('replace &ent;', doc.root.get_text.to_s) - assert_equal(source, doc.to_s) - end - - def test_lazy_evaluation - source = ' -]>replace &ent;' - doc = REXML::Document.new( source ) - assert_equal(source, doc.to_s) - assert_equal("replace replace", doc.root.text) - assert_equal(source, doc.to_s) - end - - # Contributed (not only test, but bug fix!!) by Kouhei Sutou - def test_entity_replacement - source = %q{ - ]> - &WhatHeSaid;} - - d = REXML::Document.new( source ) - dt = d.doctype - assert_equal( '"Yes"', dt.entities[ "YN" ].value ) - assert_equal( 'He said "Yes"', dt.entities[ "WhatHeSaid" ].value ) - assert_equal( 'He said "Yes"', d.elements[1].text ) - end - - # More unit tests from Kouhei. I looove users who give me unit tests. - def test_entity_insertions - assert_equal("&", REXML::Text.new("&", false, nil, true).to_s) - #assert_equal("&", REXML::Text.new("&", false, false).to_s) - end - - def test_single_pass_unnormalization # ticket 123 - assert_equal '&&', REXML::Text::unnormalize('&amp;&') - end - - def test_entity_filter - document = REXML::Document.new(<<-XML) - - -]> - -XML - respect_whitespace = false - parent = document.root - raw = false - entity_filter = ["copy"] - assert_equal("(c) &release-year;", - REXML::Text.new("(c) 2013", - respect_whitespace, - parent, - raw, - entity_filter).to_s) - end - end -end diff --git a/ruby/test/rexml/test_instruction.rb b/ruby/test/rexml/test_instruction.rb deleted file mode 100644 index 96fa909e1..000000000 --- a/ruby/test/rexml/test_instruction.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "rexml_test_utils" - -module REXMLTests - class InstructionTest < Test::Unit::TestCase - def test_target_nil - error = assert_raise(ArgumentError) do - REXML::Instruction.new(nil) - end - assert_equal("processing instruction target must be String or " + - "REXML::Instruction: ", - error.message) - end - end -end diff --git a/ruby/test/rexml/test_jaxen.rb b/ruby/test/rexml/test_jaxen.rb deleted file mode 100644 index 9640b8290..000000000 --- a/ruby/test/rexml/test_jaxen.rb +++ /dev/null @@ -1,131 +0,0 @@ -# frozen_string_literal: false -require_relative 'rexml_test_utils' - -require "rexml/document" -require "rexml/xpath" - -# Harness to test REXML's capabilities against the test suite from Jaxen -# ryan.a.cox@gmail.com - -module REXMLTests - class JaxenTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - - def test_axis ; process_test_case("axis") ; end - def test_basic ; process_test_case("basic") ; end - def test_basicupdate ; process_test_case("basicupdate") ; end - def test_contents ; process_test_case("contents") ; end - def test_defaultNamespace ; process_test_case("defaultNamespace") ; end - def test_fibo ; process_test_case("fibo") ; end - def test_id ; process_test_case("id") ; end - def test_jaxen24 ; process_test_case("jaxen24") ; end - def test_lang ; process_test_case("lang") ; end - # document() function for XSLT isn't supported - def _test_message ; process_test_case("message") ; end - def test_moreover ; process_test_case("moreover") ; end - def test_much_ado ; process_test_case("much_ado") ; end - def test_namespaces ; process_test_case("namespaces") ; end - def test_nitf ; process_test_case("nitf") ; end - # Exception should be considered - def _test_numbers ; process_test_case("numbers") ; end - def test_pi ; process_test_case("pi") ; end - def test_pi2 ; process_test_case("pi2") ; end - def test_simple ; process_test_case("simple") ; end - # TODO: namespace node is needed - def _test_testNamespaces ; process_test_case("testNamespaces") ; end - # document() function for XSLT isn't supported - def _test_text ; process_test_case("text") ; end - def test_underscore ; process_test_case("underscore") ; end - def _test_web ; process_test_case("web") ; end - def test_web2 ; process_test_case("web2") ; end - - private - def process_test_case(name) - xml_path = "#{name}.xml" - doc = File.open(fixture_path(xml_path)) do |file| - Document.new(file) - end - test_doc = File.open(fixture_path("test/tests.xml")) do |file| - Document.new(file) - end - XPath.each(test_doc, - "/tests/document[@url='xml/#{xml_path}']/context") do |context| - process_context(doc, context) - end - end - - # processes a tests/document/context node - def process_context(doc, context) - test_context = XPath.match(doc, context.attributes["select"]) - namespaces = context.namespaces - namespaces.delete("var") - namespaces = nil if namespaces.empty? - variables = {} - var_namespace = "http://jaxen.org/test-harness/var" - XPath.each(context, - "@*[namespace-uri() = '#{var_namespace}']") do |attribute| - variables[attribute.name] = attribute.value - end - XPath.each(context, "valueOf") do |value| - process_value_of(test_context, variables, namespaces, value) - end - XPath.each(context, - "test[not(@exception) or (@exception != 'true')]") do |test| - process_nominal_test(test_context, variables, namespaces, test) - end - XPath.each(context, - "test[@exception = 'true']") do |test| - process_exceptional_test(test_context, variables, namespaces, test) - end - end - - # processes a tests/document/context/valueOf or tests/document/context/test/valueOf node - def process_value_of(context, variables, namespaces, value_of) - expected = value_of.text - xpath = value_of.attributes["select"] - matched = XPath.match(context, xpath, namespaces, variables, strict: true) - - message = user_message(context, xpath, matched) - assert_equal(expected || "", - REXML::Functions.string(matched), - message) - end - - # processes a tests/document/context/test node ( where @exception is false or doesn't exist ) - def process_nominal_test(context, variables, namespaces, test) - xpath = test.attributes["select"] - matched = XPath.match(context, xpath, namespaces, variables, strict: true) - # might be a test with no count attribute, but nested valueOf elements - expected = test.attributes["count"] - if expected - assert_equal(Integer(expected, 10), - matched.size, - user_message(context, xpath, matched)) - end - - XPath.each(test, "valueOf") do |value_of| - process_value_of(matched, variables, namespaces, value_of) - end - end - - # processes a tests/document/context/test node ( where @exception is true ) - def process_exceptional_test(context, variables, namespaces, test) - xpath = test.attributes["select"] - assert_raise(REXML::ParseException) do - XPath.match(context, xpath, namespaces, variables, strict: true) - end - end - - def user_message(context, xpath, matched) - message = "" - context.each_with_index do |node, i| - message << "Node#{i}:\n" - message << "#{node}\n" - end - message << "XPath: <#{xpath}>\n" - message << "Matched <#{matched}>" - message - end - end -end diff --git a/ruby/test/rexml/test_light.rb b/ruby/test/rexml/test_light.rb deleted file mode 100644 index 99bd9cac3..000000000 --- a/ruby/test/rexml/test_light.rb +++ /dev/null @@ -1,107 +0,0 @@ -# frozen_string_literal: false -require_relative "rexml_test_utils" -require "rexml/light/node" -require "rexml/parsers/lightparser" - -module REXMLTests - class LightTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML::Light - - def test_parse_large - xml_string = fixture_path("documentation.xml") - parser = REXML::Parsers::LightParser.new(xml_string) - tag, content = parser.parse - assert_equal([:document, :text], [tag, content.first]) - end - - # FIXME INCOMPLETE - # This is because the light API is not yet ready to be used to produce - # trees. -=begin - def test_add_element - doc = Node.new - foo = doc.add_element( 'foo' ) - assert_equal( "foo", foo.name ) - end - - def test_add_attribute - foo = Node.new( "a" ) - foo["attr"] = "bar" - assert_equal( "bar", foo["attr"] ) - end - - def test_write_document - r = make_small_document - assert_equal( "", r.to_s ) - end - - def test_add_attribute_under_namespace - foo = Node.new("a") - foo["attr", "a"] = "1" - foo["attr", "b"] = "2" - foo["attr"] = "3" - assert_equal( '1', foo['attr', 'a'] ) - assert_equal( '2', foo['attr', 'b'] ) - assert_equal( '3', foo['attr'] ) - end - - def test_change_namespace_of_element - foo = Node.new - assert_equal( '', foo.namespace ) - foo.namespace = 'a' - assert_equal( 'a', foo.namespace ) - end - - def test_access_child_elements - foo = make_small_document - assert_equal( 1, foo.size ) - a = foo[0] - assert_equal( 2, a.size ) - assert_equal( 'b', a[0].name ) - assert_equal( 'c', a[1].name ) - end - - def test_itterate_over_children - foo = make_small_document - ctr = 0 - foo[0].each { ctr += 1 } - assert_equal( 2, ctr ) - end - - def test_add_text - foo = Node.new( "a" ) - foo.add_text( "Sean" ) - sean = foo[0] - assert( sean.node_type == :text ) - end - - def test_add_instruction - foo = Node.new( "a" ) - foo.add_instruction( "target", "value" ) - assert( foo[0].node_type == :processing_instruction ) - end - - def test_add_comment - foo = Node.new( "a" ) - foo.add_comment( "target", "value" ) - assert( foo[0].node_type == :comment ) - end - - def test_get_root - foo = Node.new( 'a' ) - 10.times { foo = foo.add_element('b') } - assert_equals( 'b', foo.name ) - assert_equals( 'a', foo.root.name ) - end - - def make_small_document - r = Node.new - a = r.add_element( "a" ) - a.add_element( 'b' ) - a.add_element( 'c' ) - r - end -=end - end -end diff --git a/ruby/test/rexml/test_lightparser.rb b/ruby/test/rexml/test_lightparser.rb deleted file mode 100644 index 1aeac072d..000000000 --- a/ruby/test/rexml/test_lightparser.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: false -require_relative 'rexml_test_utils' -require 'rexml/parsers/lightparser' - -module REXMLTests - class LightParserTester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - def test_parsing - File.open(fixture_path("documentation.xml")) do |f| - parser = REXML::Parsers::LightParser.new( f ) - parser.parse - end - end - end -end diff --git a/ruby/test/rexml/test_listener.rb b/ruby/test/rexml/test_listener.rb deleted file mode 100644 index 322d368be..000000000 --- a/ruby/test/rexml/test_listener.rb +++ /dev/null @@ -1,131 +0,0 @@ -# coding: binary -# frozen_string_literal: false - -require_relative 'rexml_test_utils' - -require 'rexml/document' -require 'rexml/streamlistener' - -module REXMLTests - class BaseTester < Test::Unit::TestCase - include REXMLTestUtils - def test_empty - return unless defined? @listener - # Empty. - t1 = %Q{} - assert_equal( "", @listener.parse( t1 ), - "Empty" ) - end - - def test_space - return unless defined? @listener - # Space. - t2 = %Q{ } - assert_equal( " ", @listener.parse( t2 ), - "Space" ) - end - - def test_whitespace - return unless defined? @listener - # Whitespaces. - t3 = %Q{RE\n \t \n \t XML} - assert_equal( "RE\n \t \n \t XML", @listener.parse( t3 ), - "Whitespaces" ) - end - - def test_leading_trailing_whitespace - return unless defined? @listener - # Leading and trailing whitespaces. - t4 = %Q{ REXML } - assert_equal( " REXML ", @listener.parse( t4 ), - "Leading and trailing whitespaces" ) - end - - def test_entity_reference - return unless defined? @listener - # Entity reference. - t5 = %Q{<>&lt;&gt;} - assert_equal( "<><>", @listener.parse( t5 ), - "Entity reference" ) - end - - def test_character_reference - return unless defined? @listener - # Character reference. - t6 = %Q{ } - assert_equal( "\r", @listener.parse( t6 ), - "Character reference." ) - end - - def test_cr - return unless defined? @listener - # CR. - t7 = %Q{ \r\n \r \n } - assert_equal( " \n \n \n ".unpack("C*").inspect, - @listener.parse( t7 ).unpack("C*").inspect, "CR" ) - end - - # The accent bug, and the code that exhibits the bug, was contributed by - # Guilhem Vellut - class AccentListener - def tag_start(name,attributes) - #p name - #p attributes - end - def tag_end(name) - #p "/"+name - end - def xmldecl(a,b,c) - #puts "#{a} #{b} #{c}" - end - def text(tx) - #p tx - end - end - - def test_accents - source = %[ - - -] - doc = REXML::Document.new( source ) - a = doc.elements['/g/f'].attribute('a') - if a.value.respond_to? :force_encoding - a.value.force_encoding('binary') - end - assert_equal( "\xC3\xA9", a.value) - doc = File::open(fixture_path("stream_accents.xml")) do |f| - REXML::Document.parse_stream(f, AccentListener::new) - end - end - end - - class MyREXMLListener - include REXML::StreamListener - - def initialize - @text = nil - end - - def parse( stringOrReadable ) - @text = "" - REXML::Document.parse_stream( stringOrReadable, self ) - @text - end - - def text( text ) - @text << text - end - end - - class REXMLTester < BaseTester - def setup - @listener = MyREXMLListener.new - end - - def test_character_reference_2 - t6 = %Q{ } - assert_equal( t6.strip, REXML::Document.new(t6).to_s ) - end - end -end diff --git a/ruby/test/rexml/test_martin_fowler.rb b/ruby/test/rexml/test_martin_fowler.rb deleted file mode 100644 index add3c8272..000000000 --- a/ruby/test/rexml/test_martin_fowler.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rexml/document' - -module REXMLTests - class OrderTesterMF < Test::Unit::TestCase - DOC = < -Remove this element and figs order differently -
      -
      -

      Para of text

      -

      Remove this and figs order differently

      -
      -
      -
      -
      - -END - - def initialize n - @doc = REXML::Document.new(DOC) - @figs = REXML::XPath.match(@doc,'//figure') - @names = @figs.collect {|f| f.attributes['src']} - super - end - def test_fig1 - assert_equal 'fig1', @figs[0].attributes['src'] - end - def test_fig2 - assert_equal 'fig2', @figs[1].attributes['src'] - end - def test_fig3 - assert_equal 'fig3', @figs[2].attributes['src'] - end - def test_fig4 - assert_equal 'fig4', @figs[3].attributes['src'] - end - end -end diff --git a/ruby/test/rexml/test_namespace.rb b/ruby/test/rexml/test_namespace.rb deleted file mode 100644 index 90e1d3694..000000000 --- a/ruby/test/rexml/test_namespace.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: false -require_relative "rexml_test_utils" - -require "rexml/document" - -module REXMLTests - class TestNamespace < Test::Unit::TestCase - include REXMLTestUtils - include REXML - - def setup - @xsa_source = <<-EOL - - - - - - - - Lars Marius Garshol - larsga@garshol.priv.no - http://www.stud.ifi.uio.no/~lmariusg/ - - - EOL - end - - def test_xml_namespace - xml = <<-XML - - -XML - document = Document.new(xml) - assert_equal("http://www.w3.org/XML/1998/namespace", - document.root.namespace("xml")) - end - end -end diff --git a/ruby/test/rexml/test_order.rb b/ruby/test/rexml/test_order.rb deleted file mode 100644 index 807d9faa9..000000000 --- a/ruby/test/rexml/test_order.rb +++ /dev/null @@ -1,110 +0,0 @@ -# frozen_string_literal: false -require_relative 'rexml_test_utils' -require 'rexml/document' -begin - require 'zlib' -rescue LoadError -end - -module REXMLTests - class OrderTester < Test::Unit::TestCase - include REXMLTestUtils - - TESTDOC = < - - - - - - - - -END - - def setup - @doc = REXML::Document.new(TESTDOC) - @items = REXML::XPath.match(@doc,'//x') - end - def test_first_element - assert_equal '1', @items[0].attributes['id'] - end - def test_second_element - assert_equal '2', @items[1].attributes['id'] - end - def test_third_element - assert_equal '3', @items[2].attributes['id'] - end - def test_order - d = REXML::Document.new( " - " ) - items = REXML::XPath.match( d, '//x' ) - assert_equal( %w{1 2 3 4 5}, items.collect{|e| e.attributes['id']} ) - d = REXML::Document.new( " - - " ) - items = REXML::XPath.match( d, '//y' ) - assert_equal( %w{1 2 3 4}, items.collect{|e| e.attributes['id']} ) - end - # Provided by Tom Talbott - def test_more_ordering - doc = Zlib::GzipReader.open(fixture_path('LostineRiver.kml.gz'), encoding: 'utf-8') do |f| - REXML::Document.new(f) - end - actual = [ - "Head south from Phinney Ave N", - "Turn left at N 36th St", - "Turn right at Fremont Ave N", - "Continue on 4th Ave N", - "Turn left at Westlake Ave N", - "Bear right at 9th Ave N", - "Turn left at Mercer St", - "Take the I-5 ramp", - "Take the I-5 S ramp", - "Take the I-90 E exit #164 to Bellevue/Spokane/4th Ave S.", - "Take the I-90 E ramp to Bellevue/Spokane", - "Take exit #137 to Wanapum Dam/Richland", - "Bear right at WA-26", - "Bear right and head toward WA-243", - "Continue on WA-243", - "Bear right at WA-24", - "Continue on WA-240", - "Turn right at WA-240 E", - "Take the I-182 W ramp to Yakima (I-82)/Pendleton", - "Take the I-82 E ramp to Umatilla/Pendleton", - "Take the I-84 E ramp to Pendleton", - "Take the OR-82 exit #261 to La Grande/Elgin", - "Turn right at Island Ave", - "Continue on W 1st St", - "Turn left at N McAlister Rd", - "Bear right at OR-82", - "Continue on Wallowa Lake Hwy", - "Continue on OR-82", - "Continue on Ruckman Ave", - "Continue on OR-82", - "Continue on S 8th Ave", - "Turn right at Albany St", - "Continue on OR-82", - "Continue on Wallowa Lake Hwy", - "Continue on N Madison St", - "Bear left at W 1st St", - "Continue on Wallowa Lake Hwy", - "Continue on Water St", - "Bear right at Lostine River Rd", - "Bear right and head toward Lostine River Rd", - "Turn right at Lostine River Rd", - "Continue on NF-8210", - "Turn right and head toward NF-8210", - "Turn right at NF-8210", - "", - "Route" - ] - count = 0 - REXML::XPath.each( doc, "//Placemark") { |element| - n = element.elements["name"].text.squeeze(" ") - assert_equal( actual[count], n ) unless n =~ /Arrive at/ - count += 1 - } - end if defined?(Zlib::GzipReader) - end -end diff --git a/ruby/test/rexml/test_preceding_sibling.rb b/ruby/test/rexml/test_preceding_sibling.rb deleted file mode 100644 index d89a1e1c9..000000000 --- a/ruby/test/rexml/test_preceding_sibling.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: false -# ISSUE 32 -require 'test/unit' -require 'rexml/document' - -module REXMLTests - # daz - for report by Dan Kohn in: - # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/156328 - class XPathTesterDd < Test::Unit::TestCase - include REXML - - def setup - @@docDd = Document.new(<<-EOS, :ignore_whitespace_nodes => :all) - - - Success - - - abc02C - - - EOS - end - - def test_Dd_preceding_sibling_children - arr = [] - XPath.each(@@docDd, "//b[@x='ab02A']/preceding-sibling::b/child::*") do |cell| - arr << cell.texts.join - end - assert_equal( 'Success', arr.join ) - end - - def test_Dd_preceding_sibling_all - arr = [] - XPath.each(@@docDd, "//b[@x='ab02A']/preceding-sibling::*") do |cell| - arr << cell.to_s - end - assert_equal( "Success", arr.join ) - end - end -end diff --git a/ruby/test/rexml/test_pullparser.rb b/ruby/test/rexml/test_pullparser.rb deleted file mode 100644 index 31b5b74bd..000000000 --- a/ruby/test/rexml/test_pullparser.rb +++ /dev/null @@ -1,103 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" - -require 'rexml/parsers/pullparser' - -module REXMLTests - class PullParserTester < Test::Unit::TestCase - include REXML - def test_basics - source = ' - - foo <bar nooo' - parser = REXML::Parsers::PullParser.new(source) - res = { :text=>0 } - until parser.empty? - results = parser.pull - res[ :xmldecl ] = true if results.xmldecl? - res[ :doctype ] = true if results.doctype? - res[ :a ] = true if results.start_element? and results[0] == 'a' - if results.start_element? and results[0] == 'b' - res[ :b ] = true - assert_equal 'value', results[1]['attribute'] - end - res[ :text ] += 1 if results.text? - end - [ :xmldecl, :doctype, :a, :b ].each { |tag| - assert res[tag] , "#{tag} wasn't processed" - } - assert_equal 4, res[ :text ] - rescue ParseException - puts $! - end - - def test_bad_document - source = "" - parser = REXML::Parsers::PullParser.new(source) - assert_raise(ParseException, "Parsing should have failed") { - parser.pull while parser.has_next? - } - end - - def test_entity_replacement - source = ' - - - ]>&la;&lala;' - pp = REXML::Parsers::PullParser.new( source ) - el_name = '' - while pp.has_next? - event = pp.pull - case event.event_type - when :start_element - el_name = event[0] - when :text - case el_name - when 'la' - assert_equal('1234', event[1]) - when 'lala' - assert_equal('--1234--', event[1]) - end - end - end - end - - def test_peek_unshift - source = "" - REXML::Parsers::PullParser.new(source) - # FINISH ME! - end - - def test_inspect - xml = 'Hey' - parser = Parsers::PullParser.new( xml ) - while parser.has_next? - pull_event = parser.pull - if pull_event.start_element? - peek = parser.peek() - peek.inspect - end - end - end - - def test_peek - xml = 'Hey' - parser = Parsers::PullParser.new( xml ) - names = %w{ a b } - while parser.has_next? - pull_event = parser.pull - if pull_event.start_element? - assert_equal( :start_element, pull_event.event_type ) - assert_equal( names.shift, pull_event[0] ) - if names[0] == 'b' - peek = parser.peek() - assert_equal( :start_element, peek.event_type ) - assert_equal( names[0], peek[0] ) - end - end - end - assert_equal( 0, names.length ) - end - end -end diff --git a/ruby/test/rexml/test_rexml_issuezilla.rb b/ruby/test/rexml/test_rexml_issuezilla.rb deleted file mode 100644 index 1c54c9d53..000000000 --- a/ruby/test/rexml/test_rexml_issuezilla.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: false -require_relative 'rexml_test_utils' -require 'rexml/document' - -module REXMLTests - class TestIssuezillaParsing < Test::Unit::TestCase - include REXMLTestUtils - def test_rexml - doc = File.open(fixture_path("ofbiz-issues-full-177.xml")) do |f| - REXML::Document.new(f) - end - ctr = 1 - doc.root.each_element('//issue') do |issue| - assert_equal( ctr, issue.elements['issue_id'].text.to_i ) - ctr += 1 - end - end - end -end diff --git a/ruby/test/rexml/test_sax.rb b/ruby/test/rexml/test_sax.rb deleted file mode 100644 index 00539f0d4..000000000 --- a/ruby/test/rexml/test_sax.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: false -require_relative "rexml_test_utils" -require 'rexml/sax2listener' -require 'rexml/parsers/sax2parser' -require 'rexml/document' - -module REXMLTests - class SAX2Tester < Test::Unit::TestCase - include REXMLTestUtils - include REXML - def test_characters - d = Document.new( "@blah@" ) - txt = d.root.text - p = Parsers::SAX2Parser.new "@blah@" - p.listen(:characters) {|x| assert_equal txt, x} - p.listen(:characters, ["A"]) {|x| assert_equal txt,x} - p.parse - end - - def test_entity_replacement - source = ' - - - ]>&la;&lala;' - sax = Parsers::SAX2Parser.new( source ) - results = [] - sax.listen(:characters) {|x| results << x } - sax.parse - assert_equal 2, results.size - assert_equal '1234', results[0] - assert_equal '--1234--', results[1] - end - - def test_sax2 - File.open(fixture_path("documentation.xml")) do |f| - parser = Parsers::SAX2Parser.new( f ) - # Listen to all events on the following elements - count = 0 - blok = proc { |uri,localname,qname,attributes| - assert %w{ bugs todo }.include?(localname), - "Mismatched name; we got '#{qname}'\nArgs were:\n\tURI: #{uri}\n\tLOCALNAME: #{localname}\n\tQNAME: #{qname}\n\tATTRIBUTES: #{attributes.inspect}\n\tSELF=#{blok}" - count += 1 - } - - start_document = 0 - end_document = 0 - parser.listen( :start_document ) { start_document += 1 } - parser.listen( :end_document ) { end_document += 1 } - parser.listen( :start_element, %w{ changelog bugs todo }, &blok ) - # Listen to all events on the following elements. Synonymous with - # listen( :start_element, %w{ ... } ) - parser.listen( %w{ changelog bugs todo }, &blok ) - # Listen for all start element events - parser.listen( :start_element ) { |uri,localname,qname,attributes| - } - listener = MySAX2Listener.new - # Listen for all events - parser.listen( listener ) - # Listen for all events on the given elements. Does not include children - # events. Regular expressions work as well! - parser.listen( %w{ /change/ bugs todo }, listener ) - # Test the deafening method - blok = proc { |uri,localname,qname,attributes| - assert_fail "This listener should have been deafened!" - } - parser.listen( %w{ changelog }, &blok ) - parser.deafen( &blok ) - - tc = 0 - parser.listen( :characters, %w{version} ) {|text| - assert(text=~/@ANT_VERSION@/, "version was '#{text}'") - tc += 1 - } - - begin - parser.parse - rescue => exception - if exception.kind_of? Test::Unit::AssertionFailedError - raise exception - end - puts $! - puts exception.backtrace - end - assert_equal 2, count - assert_equal 1, tc - assert_equal 1, start_document - assert_equal 1, end_document - end - end - - # used by test_simple_doctype_listener - # submitted by Jeff Barczewski - class SimpleDoctypeListener - include REXML::SAX2Listener - attr_reader :name, :pub_sys, :long_name, :uri - - def initialize - @name = @pub_sys = @long_name = @uri = nil - end - - def doctype(name, pub_sys, long_name, uri) - @name = name - @pub_sys = pub_sys - @long_name = long_name - @uri = uri - end - end - - # test simple non-entity doctype in sax listener - # submitted by Jeff Barczewski - def test_simple_doctype_listener - xml = <<-END - - - Hello, world! - END - parser = Parsers::SAX2Parser.new(xml) - dtl = SimpleDoctypeListener.new - parser.listen(dtl) - tname = nil - tpub_sys = nil - tlong_name = nil - turi = nil - parser.listen(:doctype) do |name, pub_sys, long_name, uri| - tname = name - tpub_sys = pub_sys - tlong_name = long_name - turi = uri - end - parser.parse - assert_equal 'greeting', tname, 'simple doctype block listener failed - incorrect name' - assert_equal 'PUBLIC', tpub_sys, 'simple doctype block listener failed - incorrect pub_sys' - assert_equal 'Hello Greeting DTD', tlong_name, 'simple doctype block listener failed - incorrect long_name' - assert_equal 'http://foo/hello.dtd', turi, 'simple doctype block listener failed - incorrect uri' - assert_equal 'greeting', dtl.name, 'simple doctype listener failed - incorrect name' - assert_equal 'PUBLIC', dtl.pub_sys, 'simple doctype listener failed - incorrect pub_sys' - assert_equal 'Hello Greeting DTD', dtl.long_name, 'simple doctype listener failed - incorrect long_name' - assert_equal 'http://foo/hello.dtd', dtl.uri, 'simple doctype listener failed - incorrect uri' - end - - # test doctype with missing name, should throw ParseException - # submitted by Jeff Barczewseki - def test_doctype_with_mising_name_throws_exception - xml = <<-END - - - Hello, world! - END - parser = Parsers::SAX2Parser.new(xml) - assert_raise(REXML::ParseException, 'doctype missing name did not throw ParseException') do - parser.parse - end - end - - - class KouListener - include REXML::SAX2Listener - attr_accessor :sdoc, :edoc - attr_reader :selem, :decl, :pi - def initialize - @sdoc = @edoc = @selem = false - @decl = 0 - @pi = 0 - end - def start_document - @sdoc = true - end - def end_document - @edoc = true - end - def xmldecl( *arg ) - @decl += 1 - end - def processing_instruction( *arg ) - @pi += 1 - end - def start_element( *arg ) - @selem = true - end - end - - # Submitted by Kou - def test_begin_end_document - parser = Parsers::SAX2Parser.new("") - - kl = KouListener.new - parser.listen(kl) - sd = false - ed = false - parser.listen(:start_document) { sd = true } - parser.listen(:end_document) { ed = true } - - parser.parse - assert( sd, ':start_document block failed' ) - assert( ed, ':end_document block failed' ) - assert( kl.sdoc, ':start_document listener failed' ) - assert( kl.edoc, ':end_document listener failed' ) - end - - # Submitted by Kou - def test_listen_before_start - # FIXME: the following comment should be a test for validity. (The xml declaration - # is invalid). - #parser = Parsers::SAX2Parser.new( "") - parser = Parsers::SAX2Parser.new( "") - k1 = KouListener.new - parser.listen( k1 ) - xmldecl = false - pi = 0 - parser.listen( :xmldecl ) { xmldecl = true } - parser.listen( :processing_instruction ) { pi += 1 } - - parser.parse - - assert( xmldecl, ':xmldecl failed' ) - assert_equal( 2, pi, ':processing_instruction failed' ) - assert( k1.decl, 'Listener for xmldecl failed' ) - assert_equal( 2, k1.pi, 'Listener for processing instruction failed' ) - end - - - def test_socket - require 'socket' - - TCPServer.open('127.0.0.1', 0) do |server| - TCPSocket.open('127.0.0.1', server.addr[1]) do |socket| - ok = false - session = server.accept - begin - session << '' - parser = REXML::Parsers::SAX2Parser.new(socket) - Fiber.new do - parser.listen(:start_element) do - ok = true - Fiber.yield - end - parser.parse - end.resume - assert(ok) - ensure - session.close - end - end - end - end - - def test_char_ref_sax2() - parser = REXML::Parsers::SAX2Parser.new('ü') - result = nil - parser.listen(:characters) {|text| result = text.unpack('U*')} - parser.parse() - assert_equal(1, result.size) - assert_equal(252, result[0]) - end - - - def test_char_ref_dom() - doc = REXML::Document.new('ü') - result = doc.root.text.unpack('U*') - assert_equal(1, result.size) - assert_equal(252, result[0]) - end - - class Ticket68 - include REXML::SAX2Listener - end - def test_ticket_68 - File.open(fixture_path('ticket_68.xml')) do |f| - parser = REXML::Parsers::SAX2Parser.new(f) - parser.listen( Ticket68.new ) - begin - parser.parse - rescue - p parser.source.position - p parser.source.current_line - puts $!.backtrace.join("\n") - flunk $!.message - end - end - end - end - - class MySAX2Listener - include REXML::SAX2Listener - end -end diff --git a/ruby/test/rexml/test_stream.rb b/ruby/test/rexml/test_stream.rb deleted file mode 100644 index 08d4462ef..000000000 --- a/ruby/test/rexml/test_stream.rb +++ /dev/null @@ -1,130 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" -require 'rexml/streamlistener' -require 'stringio' - -module REXMLTests - class MyListener - include REXML::StreamListener - end - - - class StreamTester < Test::Unit::TestCase - # Submitted by Han Holl - def test_listener - data = %Q{\n} - - RequestReader.new( data ) - RequestReader.new( data ) - end - - def test_ticket_49 - source = StringIO.new( <<-EOL ) - - ]> - &ent; - EOL - REXML::Document.parse_stream(source, MyListener.new) - end - - def test_ticket_10 - source = StringIO.new( <<-EOL ) - - - - - ]> - - EOL - listener = MyListener.new - class << listener - attr_accessor :events - def entitydecl( content ) - @events[ :entitydecl ] = true - end - def attlistdecl( element_name, attributes, raw_content ) - @events[ :attlistdecl ] = true - end - def elementdecl( content ) - @events[ :elementdecl ] = true - end - def notationdecl( content ) - @events[ :notationdecl ] = true - end - end - listener.events = {} - - REXML::Document.parse_stream( source, listener ) - - assert( listener.events[:entitydecl] ) - assert( listener.events[:attlistdecl] ) - assert( listener.events[:elementdecl] ) - assert( listener.events[:notationdecl] ) - end - - def test_entity - listener = MyListener.new - class << listener - attr_accessor :entities - def entity(content) - @entities << content - end - end - listener.entities = [] - - source = StringIO.new(<<-XML) - -%ISOLat2; -]> - - XML - REXML::Document.parse_stream(source, listener) - - assert_equal(["ISOLat2"], listener.entities) - end - end - - - # For test_listener - class RequestReader - attr_reader :doc - def initialize(io) - @stack = [] - @doc = nil - catch(:fini) do - REXML::Document.parse_stream(io, self) - raise IOError - end - end - def tag_start(name, args) - if @doc - @stack.push(REXML::Element.new(name, @stack.last)) - else - @doc = REXML::Document.new("<#{name}/>") - @stack.push(@doc.root) - end - args.each do |attr,val| - @stack.last.add_attribute(attr, val) - end - end - def tag_end(name, *args) - @stack.pop - throw(:fini) if @stack.empty? - end - def text(str) - @stack.last.text = str - end - def comment(str) - end - def doctype( name, pub_sys, long_name, uri ) - end - def doctype_end - end - end -end diff --git a/ruby/test/rexml/test_text.rb b/ruby/test/rexml/test_text.rb deleted file mode 100644 index e9a246e27..000000000 --- a/ruby/test/rexml/test_text.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: false - -require_relative "rexml_test_utils" - -module REXMLTests - class TextTester < Test::Unit::TestCase - include REXML - - def test_new_text_response_whitespace_default - text = Text.new("a b\t\tc", true) - assert_equal("a b\tc", Text.new(text).to_s) - end - - def test_new_text_response_whitespace_true - text = Text.new("a b\t\tc", true) - assert_equal("a b\t\tc", Text.new(text, true).to_s) - end - - def test_new_text_raw_default - text = Text.new("&lt;", false, nil, true) - assert_equal("&lt;", Text.new(text).to_s) - end - - def test_new_text_raw_false - text = Text.new("&lt;", false, nil, true) - assert_equal("&amp;lt;", Text.new(text, false, nil, false).to_s) - end - - def test_new_text_entity_filter_default - document = REXML::Document.new(<<-XML) - - -]> - - XML - text = Text.new("aaa bbb", false, document.root, nil, ["a"]) - assert_equal("aaa &b;", - Text.new(text, false, document.root).to_s) - end - - def test_new_text_entity_filter_custom - document = REXML::Document.new(<<-XML) - - -]> - - XML - text = Text.new("aaa bbb", false, document.root, nil, ["a"]) - assert_equal("&a; bbb", - Text.new(text, false, document.root, nil, ["b"]).to_s) - end - - def test_shift_operator_chain - text = Text.new("original\r\n") - text << "append1\r\n" << "append2\r\n" - assert_equal("original\nappend1\nappend2\n", text.to_s) - end - - def test_shift_operator_cache - text = Text.new("original\r\n") - text << "append1\r\n" << "append2\r\n" - assert_equal("original\nappend1\nappend2\n", text.to_s) - text << "append3\r\n" << "append4\r\n" - assert_equal("original\nappend1\nappend2\nappend3\nappend4\n", text.to_s) - end - - def test_clone - text = Text.new("&lt; <") - assert_equal(text.to_s, - text.clone.to_s) - end - end -end diff --git a/ruby/test/rexml/test_ticket_80.rb b/ruby/test/rexml/test_ticket_80.rb deleted file mode 100644 index ab6a57efa..000000000 --- a/ruby/test/rexml/test_ticket_80.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: false -#------------------------------------------------------------------------------ -# file: rexml_test.rb -# desc: test's REXML's XML/XPath implementation -# auth: Philip J Grabner atdot -# date: 2006/08/17 -# copy: (C) CopyLoose 2006 Bib Development Team atdot -#------------------------------------------------------------------------------ - -require 'test/unit' -require 'rexml/document' - -module REXMLTests - class Ticket80 < Test::Unit::TestCase - - @@xmlstr = ' - - - - - - - - - - - - - -' - - #---------------------------------------------------------------------------- - def test_xpathNamespacedChildWildcard - # tests the "prefix:*" node test syntax - out = Array.new - REXML::XPath.each( REXML::Document.new(@@xmlstr), - '/ns:root/ns:*/ns:l2/@value', - { 'ns' => 'urn:some-xml-ns' } ) do |node| out.push node.value ; end - chk = [ 'foo-01', 'foo-02', 'foo-03', 'bar-01', 'bar-02' ] - assert_equal chk, out - end - - #---------------------------------------------------------------------------- - def test_xpathNamespacedChildWildcardWorkaround - # tests a workaround for the "prefix:*" node test syntax - out = Array.new - REXML::XPath.each( REXML::Document.new(@@xmlstr), - '/ns:root/*[namespace-uri()="urn:some-xml-ns"]/ns:l2/@value', - { 'ns' => 'urn:some-xml-ns' } ) do |node| out.push node.value ; end - chk = [ 'foo-01', 'foo-02', 'foo-03', 'bar-01', 'bar-02' ] - assert_equal chk, out - end - - end -end - -#------------------------------------------------------------------------------ -# end of rexml_test.rb -#------------------------------------------------------------------------------ diff --git a/ruby/test/rexml/test_validation_rng.rb b/ruby/test/rexml/test_validation_rng.rb deleted file mode 100644 index b5b50450e..000000000 --- a/ruby/test/rexml/test_validation_rng.rb +++ /dev/null @@ -1,793 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" - -require "rexml/document" -require "rexml/validation/relaxng" - -module REXMLTests - class RNGValidation < Test::Unit::TestCase - include REXML - - def test_validate - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - error( validator, %q{} ) - end - - - def test_sequence - rng = %q{ - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - end - - - def test_choice - rng = %q{ - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_optional - rng = %q{ - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - end - - def test_zero_or_more - rng = %q{ - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - end - - def test_one_or_more - rng = %q{ - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - end - - def test_attribute - rng = %q{ - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_choice_attributes - rng = %q{ - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{}) - no_error( validator, %q{} ) - end - - def test_choice_attribute_element - rng = %q{ - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{}) - no_error( validator, %q{} ) - end - - def test_empty - rng = %q{ - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{Text} ) - no_error( validator, %q{}) - end - - def test_text_val - rng = %q{ - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{Text} ) - error( validator, %q{}) - end - - def test_choice_text - rng = %q{ - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{Text} ) - error( validator, %q{Text} ) - no_error( validator, %q{Text} ) - no_error( validator, %q{} ) - end - - def test_group - rng = %q{ - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_value - # Values as text nodes - rng = %q{ - - - - VaLuE - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{X} ) - error( validator, %q{} ) - no_error( validator, %q{VaLuE} ) - - # Values as text nodes, via choice - rng = %q{ - - - - - Option 1 - Option 2 - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{XYZ} ) - no_error( validator, %q{Option 1} ) - no_error( validator, %q{Option 2} ) - - # Attribute values - rng = %q{ - - - - VaLuE - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - - # Attribute values via choice - rng = %q{ - - - - - Option 1 - Option 2 - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_interleave - rng = %q{ - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - end - - def test_mixed - rng = %q{ - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{Text} ) - no_error( validator, %q{Text} ) - end - - def test_ref_sequence - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - error( validator, %q{} ) - end - - def test_ref_choice - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - - def test_ref_zero_plus - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - - def test_ref_one_plus - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_ref_interleave - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_ref_recurse - rng = %q{ - - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - error( validator, %q{} ) - no_error( validator, %q{} ) - no_error( validator, %q{} ) - end - - def test_ref_optional - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - - rng = %q{ - - - - - - - - - - - - - - - - } - validator = REXML::Validation::RelaxNG.new( rng ) - - no_error( validator, %q{} ) - no_error( validator, %q{} ) - error( validator, %q{} ) - error( validator, %q{} ) - end - - - - def error( validator, source ) - parser = REXML::Parsers::TreeParser.new( source ) - parser.add_listener( validator.reset ) - assert_raise( REXML::Validation::ValidationException, - "Expected a validation error" ) { parser.parse } - end - - def no_error( validator, source ) - parser = REXML::Parsers::TreeParser.new( source ) - parser.add_listener( validator.reset ) - assert_nothing_raised { parser.parse } - end - end -end diff --git a/ruby/test/rexml/test_xml_declaration.rb b/ruby/test/rexml/test_xml_declaration.rb deleted file mode 100644 index da7076126..000000000 --- a/ruby/test/rexml/test_xml_declaration.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: false -# -# Created by Henrik MÃ¥rtensson on 2007-02-18. -# Copyright (c) 2007. All rights reserved. - -require "rexml/document" -require "test/unit" - -module REXMLTests - class TestXmlDeclaration < Test::Unit::TestCase - def setup - xml = <<-XML - - - - XML - @doc = REXML::Document.new xml - @root = @doc.root - @xml_declaration = @doc.children[0] - end - - def test_is_first_child - assert_kind_of(REXML::XMLDecl, @xml_declaration) - end - - def test_has_document_as_parent - assert_kind_of(REXML::Document, @xml_declaration.parent) - end - - def test_has_sibling - assert_kind_of(REXML::XMLDecl, @root.previous_sibling.previous_sibling) - assert_kind_of(REXML::Element, @xml_declaration.next_sibling.next_sibling) - end - - def test_write_prologue_quote - @doc.context[:prologue_quote] = :quote - assert_equal("", - @xml_declaration.to_s) - end - - def test_is_writethis_attribute_copied_by_clone - assert_equal(true, @xml_declaration.clone.writethis) - @xml_declaration.nowrite - assert_equal(false, @xml_declaration.clone.writethis) - end - end -end diff --git a/ruby/test/rexml/xpath/test_attribute.rb b/ruby/test/rexml/xpath/test_attribute.rb deleted file mode 100644 index 713d77b22..000000000 --- a/ruby/test/rexml/xpath/test_attribute.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rexml/document' - -module REXMLTests - class TestXPathAttribute < Test::Unit::TestCase - def setup - @xml = <<-XML - - - child1 - child2 - child3 - - XML - @document = REXML::Document.new(@xml) - end - - def test_elements - root = @document.elements["root"] - second_child = root.elements["child[@name='two']"] - assert_equal("child2", second_child.text) - end - - def test_xpath_each - children = REXML::XPath.each(@document, "/root/child[@name='two']") - assert_equal(["child2"], children.collect(&:text)) - end - - def test_no_namespace - children = REXML::XPath.match(@document, - "/root/child[@nothing:name='two']", - "" => "http://example.com/", - "nothing" => "") - assert_equal(["child2"], children.collect(&:text)) - end - end -end diff --git a/ruby/test/rexml/xpath/test_axis_preceding_sibling.rb b/ruby/test/rexml/xpath/test_axis_preceding_sibling.rb deleted file mode 100644 index 5842c6bc5..000000000 --- a/ruby/test/rexml/xpath/test_axis_preceding_sibling.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" - -module REXMLTests - class TestXPathAxisPredcedingSibling < Test::Unit::TestCase - include REXML - SOURCE = <<-EOF - - - - - - - - - EOF - - def setup - @@doc = Document.new(SOURCE) unless defined? @@doc - end - - def test_preceding_sibling_axis - context = XPath.first(@@doc,"/a/e/f[last()]") - assert_equal "6", context.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f") - assert_equal "5", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[1]") - assert_equal "5", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[2]") - assert_equal "4", prev.attributes["id"] - - prev = XPath.first(context, "preceding-sibling::f[3]") - assert_equal "3", prev.attributes["id"] - end - end -end diff --git a/ruby/test/rexml/xpath/test_base.rb b/ruby/test/rexml/xpath/test_base.rb deleted file mode 100644 index 210d6c7c8..000000000 --- a/ruby/test/rexml/xpath/test_base.rb +++ /dev/null @@ -1,1125 +0,0 @@ -# frozen_string_literal: false -require_relative "../rexml_test_utils" - -require "rexml/document" - -module REXMLTests - class TestXPathBase < Test::Unit::TestCase - include REXMLTestUtils - include REXML - SOURCE = <<-EOF - - - - - - - - - - - - - - - - - - - - - - -

      - - - - - EOF - JENI_TENNISON = <<-EOJT - - - - - - - - - - - - - - - - - - - - - - - - EOJT - - def setup - @@doc = Document.new(SOURCE) unless defined? @@doc - @@jeni = Document.new( JENI_TENNISON ) unless defined? @@jeni - end - - def each_test( element, xpath ) - count = 0 - XPath::each( element, xpath ) { |child| - count += 1 - yield child if block_given? - } - count - end - - def test_descendant - doc = Document.new("") - p = XPath.match( doc, "//c" ) - assert_equal( 2, p.size ) - p = XPath.first( @@doc, "//p" ) - assert_equal "p", p.name - c = each_test( @@doc, "//c" ) { |child| assert_equal "c", child.name } - assert_equal 5, c - c = each_test( @@doc.root, "b//c" ) { |child| - assert_equal "c", child.name - } - assert_equal 2, c - - doc = Document.new( "" ) - # //para[1] : all descendants which are the first para child of their parent - assert_equal( 4, XPath.match( doc, "//z[1]" ).size ) - # /descendant::para[1] : the first descendant para element - assert_equal( 1, XPath.match( doc, "/descendant::z[1]" ).size ) - end - - def test_root - source = "" - doc = Document.new( source ) - assert_equal doc, doc.root_node - assert_equal "a", XPath::first( doc, "/" ).elements[1].name - end - - def test_abbreviated_simple_child - assert_equal "a", XPath::first(@@doc, "a").name - end - - def test_child - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "c", c.name - assert_equal "3", XPath::first(@@doc, "a/b/c").attributes["id"] - end - - def test_root_child - assert_equal "a", XPath::first(@@doc, "/a").name - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "a", XPath::first(c, "/a").name - end - - def test_root_children - c = XPath::first( @@doc, "a/b/c" ) - assert_equal "2", XPath::first(c, "/a/b").attributes["id"] - end - - def test_abbreviated_step - c = XPath::first( @@doc, "a/b/c" ) - assert_equal("c", c.name) - assert_equal("a", XPath::first(@@doc.root, ".").name) - assert_equal("b", XPath::first(c, "..").name) - assert_equal("a", XPath::first(@@doc, "a/b/..").name) - - doc = File.open(fixture_path("project.xml")) do |f| - REXML::Document.new(f) - end - c = each_test(doc.root, "./Description" ) { |child| - assert_equal("Description",child.name) - } - assert_equal 1, c - end - - # Things that aren't tested elsewhere - def test_predicates - assert_equal "12", XPath::first(@@doc, "a/e/f[3]").attributes["id"] - assert_equal "13", XPath::first(@@doc, "a/e/f[3]/g").attributes["id"] - assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][2]").attributes["id"] - assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][@id='14']").attributes["id"] - assert_equal "a", XPath::first( @@doc, "*[name()='a' and @id='1']" ).name - c=each_test( @@doc, "//*[name()='f' and @a='d']") { |i| - assert_equal "f", i.name - } - assert_equal 2, c - c=each_test( @@doc, "//*[name()='m' or @a='d']") { |i| - assert ["m","f"].include?(i.name) - } - assert_equal 3, c - - assert_equal "b", XPath::first( @@doc, "//b[@x]" ).name - end - - def test_node_type - doc = Document.new "text" - #res = XPath::first(doc.root, "text()") - #assert_equal "text", res.to_s - - #res = XPath::first(doc, "*") - #assert_equal "a", res.name - - assert_equal( :processing_instruction, - XPath::first(doc.root, "processing-instruction()").node_type) - assert_equal( :comment, XPath::first(doc.root, "comment()").node_type) - end - - def test_functions - # trivial text() test - # confuse-a-function - source = "more dumb text" - doc = Document.new source - res = "" - #XPath::each(doc.root, "text()") {|val| res << val.to_s} - #assert_equal "more text", res - - #res = XPath::first(doc.root, "b[last()]") - #assert_equal '3', res.attributes['id'] - res = XPath::first(doc.root, "b[position()=2]") - assert_equal '2', res.attributes['id'] - res = XPath::first(doc.root, "*[name()='c']") - assert_equal "c", res.name - end - - def no_test_ancestor - doc = REXML::Document.new(File.new(fixture_path("testsrc.xml"))) - doc.elements.each("//item") { |el| print el.name - if el.attributes['x'] - puts " -- "+el.attributes['x'] - else - puts - end - } - doc.elements.each("//item/ancestor::") { |el| print el.name - if el.attributes['x'] - puts " -- "+el.attributes['x'] - else - puts - end - } - end - - # Here are some XPath tests that were originally submitted by ... - # The code has changed some, but the logic and the source documents are the - # same. - # This method reads a document from a file, and then a series of xpaths, - # also from a file. It then checks each xpath against the source file. - def test_more - xmlsource = fixture_path("testsrc.xml") - xpathtests = fixture_path("xp.tst") - - doc = File.open(xmlsource) {|f| REXML::Document.new(f) } - #results = "" - results = REXML::Document.new - results.add_element "test-results" - File.foreach(xpathtests) do |line| - line.strip! - begin - doc.root - #puts "#"*80 - #print "\nDoing #{line} " ; $stdout.flush - doc.elements.each(line) do |el| - #print "." ; $stdout.flush - results.root << el.clone - #results << el.to_s - end - #ObjectSpace.garbage_collect - GC::start - rescue Exception => z - #puts "\n'#{line}' failed" - fail("Error on line #{line}:\n#{z.message}\n"+z.backtrace[0,10].join("\n")) - #results.root.add_element( "error", {"path"=>line}).text = z.message+"\n"+z.backtrace[0,10].join("\n") - #results << ""+z.message+"" - end - end - end - - def test_axe_descendant - assert_equal "f", XPath::first( @@doc, "descendant::f").name - end - - def test_axe_parent - q = XPath.first( @@doc, "a/d/c/parent::*/q" ) - assert_equal 19, q.attributes["id"].to_i - end - - def test_abbreviated_attribute - assert_equal 'a', XPath::first( @@doc, "a[@id='1']" ).name - c = XPath::first( @@doc, "a/b/c[@id='4']" ) - assert_equal 'c', c.name - assert_equal '4', c.attributes['id'] - - result = XPath::first( @@doc, "descendant::f[@a='c']") - assert_equal "11", result.attributes['id'] - - assert_equal "11", XPath::first(@@doc, "a/e/f[@a='c']").attributes["id"] - assert_equal "11", XPath::first(@@doc, "a/e/*[@a='c']").attributes["id"] - end - - def test_axe_self - c = XPath::first( @@doc, "a/b/c" ) - assert c - assert_equal "c", c.name - assert_equal "c", XPath::first( c, "self::node()" ).name - end - - def test_axe_ancestor - doc = REXML::Document.new " - - - - - - - - - " - - d = XPath.first( doc, "//d" ) - assert_equal "d", d.name - b = each_test( d, "ancestor::b" ) { |el| - assert((1..2) === el.attributes['id'].to_i, - "Expected #{el.attributes['id']} to be either 1 or 2" - ) - } - assert_equal 2, b - end - - def test_axe_child - m = XPath.first( @@doc, "a/child::m" ) - assert_equal 15, m.attributes['id'].to_i - end - - def test_axe_attribute - a = XPath.first( @@doc, "a/attribute::id" ) - assert_equal "1", a.value - a = XPath.first( @@doc, "a/e/f[@id='14']/attribute::a" ) - assert_equal "d", a.value - end - - def test_axe_sibling - doc = Document.new "" - first_f = XPath.first( doc, "a/e/f" ) - assert first_f - assert_equal '10', first_f.attributes['id'] - next_f = XPath.first( doc, "a/e/f/following-sibling::node()" ) - assert_equal '11', next_f.attributes['id'] - - b = XPath.first( doc, "a/e/preceding-sibling::node()" ) - assert_equal 'b', b.name - end - - def test_lang - doc = File.open(fixture_path("lang0.xml")) {|f| Document.new(f) } - #puts IO.read( "test/lang.xml" ) - - #puts XPath.match( doc, "//language/*" ).size - c = each_test( doc, "//language/*" ) { |element| - #puts "#{element.name}: #{element.text}" - } - assert_equal 4, c - end - - def test_namespaces_1 - source = <<-EOF - - this bar - that bar - - EOF - doc = Document.new source - XPath.each( doc, "//bar" ) { - fail "'bar' should match nothing in this case" - } - - namespace = {"t"=>"this"} - results = XPath.first( doc, "//t:bar", namespace ) - assert_equal "this bar", results.text - end - - def test_namespaces_2 - source = <<-EOF - - this bar - that bar - - EOF - doc = Document.new source - res = XPath::first(doc, "//*[local_name()='bar']") - assert res, "looking for //*[name()='bar']" - assert_equal 'this', res.namespace - res = XPath::first(doc.root, "*[namespace_uri()='that']") - assert_equal 'that bar', res.text - end - - def test_complex - next_f = XPath.first( @@doc, "a/e/f[@id='11']/following-sibling::*" ) - assert_equal 12, next_f.attributes['id'].to_i - prev_f = XPath.first( @@doc, "a/e/f[@id='11']/preceding-sibling::*" ) - assert_equal 10, prev_f.attributes['id'].to_i - c = each_test( @@doc, "descendant-or-self::*[@x='y']" ) - assert_equal 2, c - end - - def match(xpath) - XPath.match(@@doc, xpath).collect(&:to_s) - end - - def test_grouping - assert_equal([], - match("a/d/*[name()='d' and (name()='f' or name()='q')]")) - assert_equal([""], - match("a/d/*[(name()='d' and name()='f') or name()='q']")) - end - - def test_preceding - d = Document.new "" - start = XPath.first( d, "/a/b[@id='1']" ) - assert_equal 'b', start.name - c = XPath.first( start, "preceding::c" ) - assert_equal '2', c.attributes['id'] - - c1, c0 = XPath.match( d, "/a/b/c[@id='2']/preceding::node()" ) - assert_equal '1', c1.attributes['id'] - assert_equal '0', c0.attributes['id'] - - c2, c1, c0, b, b2, b0 = XPath.match( start, "preceding::node()" ) - - assert_equal 'c', c2.name - assert_equal 'c', c1.name - assert_equal 'c', c0.name - assert_equal 'b', b.name - assert_equal 'b', b2.name - assert_equal 'b', b0.name - - assert_equal '2', c2.attributes['id'] - assert_equal '1', c1.attributes['id'] - assert_equal '0', c0.attributes['id'] - assert b.attributes.empty? - assert_equal '2', b2.attributes['id'] - assert_equal '0', b0.attributes['id'] - - d = REXML::Document.new("") - matches = REXML::XPath.match(d, "/a/d/preceding::node()") - assert_equal("c", matches[0].name) - assert_equal("b", matches[1].name) - - s = "" - d = REXML::Document.new(s) - c = REXML::XPath.match( d, "//c[@id = '5']") - cs = REXML::XPath.match( c, "preceding::c" ) - assert_equal( 4, cs.length ) - end - - def test_following - d = Document.new "" - start = XPath.first( d, "/a/b[@id='0']" ) - assert_equal 'b', start.name - c = XPath.first( start, "following::c" ) - assert_equal '1', c.attributes['id'] - - s = "" - d = Document.new(s) - c = XPath.first(d, '/a/b/c') - assert_equal 'c', c.name - res = XPath.match( c, 'following::*' ) - assert_equal 6, res.size - res = XPath.match( c, 'following::i' ) - assert_equal 2, res.size - end - - # The following three paths were provided by - # Jeni Tennison - # a consultant who is also an XSL and XPath expert - #def test_child_cubed - # els = @@jeni.elements.to_a("*****") - # assert_equal 3, els.size - #end - - #def test_div_2 - # results = doc.elements.to_a("/ div 2") - #end - - #def test_nested_predicates - # puts @@jeni.root.elements[1].elements[1].name - # results = @@jeni.root.elements[1].elements[1].elements.to_a("../following-sibling::*[*[name() = name(current())]]") - # puts results - #end - - # Contributed by Mike Stok - def test_starts_with - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]") - assert_equal 1, mailtos.size - assert_equal "mailto:a@b.c", mailtos[0].attributes['href'] - - ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]") - assert_equal 0, ailtos.size - end - - def test_toms_text_node - file = "ABCDEF" - doc = Document.new(file) - assert_equal 'A', XPath.first(doc[0], 'text()').to_s - assert_equal 'AF', XPath.match(doc[0], 'text()').collect { |n| - n.to_s - }.join('') - assert_equal 'B', XPath.first(doc[0], 'b/text()').to_s - assert_equal 'D', XPath.first(doc[0], '//d/text()').to_s - assert_equal 'ABCDEF', XPath.match(doc[0], '//text()').collect {|n| - n.to_s - }.join('') - end - - def test_string_length - doc = Document.new <<-EOF - - - - - - - - - EOF - assert doc, "create doc" - - set = doc.elements.to_a("//*[string-length(name()) = 3]") - assert_equal 2, set.size, "nodes with names length = 3" - - set = doc.elements.to_a("//*[string-length(name()) < 3]") - assert_equal 2, set.size, "nodes with names length < 3" - - set = doc.elements.to_a("//*[string-length(name()) > 3]") - assert_equal 3, set.size, "nodes with names length > 3" - end - - # Test provided by Mike Stok - def test_contains - source = <<-EOF - - a@b.c - http://www.foo.com - - EOF - doc = Document.new source - - [ - #['o', 2], - ['foo', 1], ['bar', 0]].each { |search, expected| - set = doc.elements.to_a("//a[contains(@href, '#{search}')]") - assert_equal expected, set.size - } - end - - # Mike Stok and Sean Russell - def test_substring - # examples from http://www.w3.org/TR/xpath#function-substring - doc = Document.new('') - - Document.new("") - #puts XPath.first(d, 'node()[0 + 1]') - #d = Document.new("") - #puts XPath.first(d, 'a[0 mod 0]') - [ [1.5, 2.6, '234'], - [0, 3, '12'], - [0, '0 div 0', ''], - [1, '0 div 0', ''], - ['-42', '1 div 0', '12345'], - ['-1 div 0', '1 div 0', ''] - ].each { |start, length, expected| - set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']") - assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'" - } - end - - def test_translate - source = <<-EOF - - - - - - - - EOF - - doc = Document.new(source) - - [ ['bar', 'abc', 'ABC', 'w3c one'], - ['--aaa--','abc-','ABC', 'w3c two'], - ['lead', 'dear language', 'doll groover', 'alchemy'], - ['A Space Odissei', 'i', 'y', 'vbxml one'], - ['abcdefg', 'aceg', 'ACE', 'vbxml two'], - ].each { |arg1, arg2, arg3, name| - translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')" - set = doc.elements.to_a("//case[@result = #{translate}]") - assert_equal 1, set.size, translate - assert_equal name, set[0].attributes['name'] - } - end - - def test_math - d = Document.new( '' ) - assert XPath.first( d.root, 'node()[1]' ) - assert_equal 'b', XPath.first( d.root, 'node()[1]' ).name - assert XPath.first( d.root, 'node()[0 + 1]' ) - assert_equal 'b', XPath.first( d.root, './node()[0 + 1]' ).name - assert XPath.first( d.root, 'node()[1 + 1]' ) - assert_equal 'c', XPath.first( d.root, './node()[1 + 1]' ).name - assert XPath.first( d.root, 'node()[4 div 2]' ) - assert_equal 'c', XPath.first( d.root, './node()[4 div 2]' ).name - assert XPath.first( d.root, 'node()[2 - 1]' ) - assert_equal 'b', XPath.first( d.root, './node()[2 - 1]' ).name - assert XPath.first( d.root, 'node()[5 mod 2]' ) - assert_equal 'b', XPath.first( d.root, './node()[5 mod 2]' ).name - assert XPath.first( d.root, 'node()[8 mod 3]' ) - assert_equal 'c', XPath.first( d.root, './node()[8 mod 3]' ).name - assert XPath.first( d.root, 'node()[1 * 2]' ) - assert_equal 'c', XPath.first( d.root, './node()[1 * 2]' ).name - assert XPath.first( d.root, 'node()[2 + -1]' ) - assert_equal 'b', XPath.first( d.root, './node()[2 + -1]' ).name - end - - def test_name - assert_raise( UndefinedNamespaceException, "x should be undefined" ) { - REXML::Document.new("") - } - d = REXML::Document.new("") - assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size - assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size - end - - def test_local_name - d = REXML::Document.new("") - assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size - assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size - end - - def test_comparisons - source = "" - doc = REXML::Document.new(source) - - # NOTE TO SER: check that number() is required - assert_equal 2, REXML::XPath.match(doc, "//b[number(@id) > 1]").size - assert_equal 3, REXML::XPath.match(doc, "//b[number(@id) >= 1]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) <= 1]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 * 1)]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 mod 2)]").size - assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (4 div 2)]").size - end - - # Contributed by Kouhei - def test_substring_before - doc = Document.new("") - assert_equal("a", doc.root.elements.to_a("*[name()=substring-before('abc', 'b')]")[0].name) - assert_equal("c", doc.root.elements.to_a("*[name()=substring-after('abc', 'b')]")[0].name) - end - - def test_spaces - doc = Document.new(" - - - - - - - ") - match = lambda do |xpath| - REXML::XPath.match(doc, xpath).collect(&:to_s) - end - assert_equal([""], - match.call("//*[local-name()='c' and @id='b']")) - assert_equal([""], - match.call("//*[ local-name()='c' and @id='b' ]")) - assert_equal([""], - match.call("//*[ local-name() = 'c' and @id = 'b' ]")) - assert_equal(["", ""], - match.call('/a/c[@id]')) - assert_equal(["", ""], - match.call('/a/c[(@id)]')) - assert_equal(["", ""], - match.call('/a/c[ @id ]')) - assert_equal(["", ""], - match.call('/a/c[ (@id) ]')) - assert_equal(["", ""], - match.call('/a/c[( @id )]')) - assert_equal(["", ""], - match.call('/a/c[ ( @id ) ]')) - assert_equal(["", ""], - match.call('/a/c [ ( @id ) ] ')) - assert_equal(["", ""], - match.call(' / a / c [ ( @id ) ] ')) - assert_equal(["", ""], - match.call('/ a / child:: c [( @id )] /')) - end - - def test_text_nodes - # source = " - # - #test - #" - source = "test" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/root/child[text()="test"]} ) - assert_equal( 1, r.size ) - assert_equal( "child", r[0].name ) - assert_equal( "test", r[0].text ) - end - - def test_auto_string_value - source = "Introduction" - d = REXML::Document.new( source ) - #r = REXML::XPath.match( d, %q{/root[title="Introduction"]} ) - #assert_equal( 1, r.size ) - source = "test" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a[c='test']} ) - assert_equal( 1, r.size ) - r = REXML::XPath.match( d, %q{a[c='test']} ) - assert_equal( 1, r.size ) - r = d.elements["/a[c='test']"] - assert_not_nil( r ) - r = d.elements["a[c='test']"] - assert_not_nil( r ) - r = d.elements["a[c='xtest']"] - assert_nil( r ) - r = REXML::XPath.match( d, %q{a[c='xtest']} ) - assert_equal( 0, r.size ) - end - - def test_ordering - source = <<-XML - - - - - - - - - - - XML - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a/*/*[1]} ) - assert_equal(["1", "3"], - r.collect {|element| element.attribute("id").value}) - end - - def test_descendant_or_self_ordering - source = " - - - - - - - - - - - - - - - " - d = REXML::Document.new( source ) - cs = XPath.match( d, "/descendant-or-self::c" ) - assert_equal( 4, cs.length ) - 1.upto(4) {|x| assert_equal( x.to_s, cs[x-1].attributes['id'] ) } - end - - def test_and - d = Document.new %q{} - assert_equal( nil, d.root.elements["route[@run='0']"] ) - assert_equal( nil, d.root.elements["route[@run='0' and @title='HNO']"] ) - end - - - def test_numbers - d = Document.new %q{} - - xp1 = "/a[ @x = 0 ]" - xp2 = "/a[ @x = '0' ]" - xp3 = "/a[ (@x + 1) = 1 ]" - xp4 = "/a[ @y = 0 ]" - xp5 = "/a[ (@z + 1) = 5 ]" - xp6 = "/a[ (@w + 1) = 5 ]" - xp7 = "/a[ (@v + 1) = 1 ]" - xp8 = "/a[ @n = 0 ]" - - assert_equal( 1, XPath.match( d, xp1 ).length ) - assert_equal( 1, XPath.match( d, xp2 ).length ) - assert_equal( 1, XPath.match( d, xp3 ).length ) - assert_equal( 0, XPath.match( d, xp4 ).length ) - assert_equal( 0, XPath.match( d, xp5 ).length ) - assert_equal( 0, XPath.match( d, xp6 ).length ) - assert_equal( 0, XPath.match( d, xp7 ).length ) - assert_equal( 0, XPath.match( d, xp8 ).length ) - end - - def test_tobis_preceding - doc_string = ' - - - - - -' - - doc = Document.new(doc_string) - - # e = REXML::XPath.first(doc,'/a/c/e') - e = doc.root.get_elements('/a/c/e')[0] - assert_equal( 1, e.get_elements('preceding-sibling::*').length ) - assert_equal( 2, XPath.match(e, 'preceding::*').length ) - end - - - def test_filtering - #doc=Document.new("") - #assert_equal( 3, XPath.match( doc, '/a/b/*[1]' ).length ) - #assert_equal( 2, XPath.match( doc, '/a/b/following-sibling::*[1]' ).length ) - end - - # Submitted by Alex - def test_union - data = %Q{

      - - a - - b -
      } - rd = REXML::Document.new( data ) - #union = rd.get_elements("/div/span | /div/em") - #assert_equal(2, union.length, "/div/span | /div/em" ) - union = rd.get_elements('//*[name()="em" or name()="strong"]') - assert_equal(2, union.length, 'name() and "or" failed') - union = rd.get_elements('//em|//strong') - assert_equal(2, union.length, - 'Both tag types are returned by XPath union operator') - end - - - def test_union2 - src = <<-EOL -
      - -a - -b -
      - EOL - rd = REXML::Document.new( src ) - union = rd.get_elements('//em|//strong') - assert_equal(2, union.length, - 'Both tag types are returned by XPath union operator') - end - - - def test_a_star_star_one - string = <<-EOL - - - - - - - - - - - - - - - EOL - d = REXML::Document.new( string ) - cs = XPath.match( d, '/a/*/*[1]' ) - assert_equal(["c1", "c2"], cs.collect(&:name)) - end - - def test_sum - d = Document.new(<<-XML) - - 1 - 2 - 3 - - 1 - 2 - - - - - XML - - assert_equal([6], XPath::match(d, "sum(/a/b)")) - assert_equal([9], XPath::match(d, "sum(//b | //d)")) - assert_equal([3], XPath::match(d, "sum(/a/e/@*)")) - end - - def test_xpath_namespace - d = REXML::Document.new(<<-XML) - - - xa - xb - - XML - actual = [] - d.root.each_element('tada') do |element| - actual << element.to_s - end - assert_equal(["xa", "xb"], - actual) - end - - def test_ticket_39 - doc = REXML::Document.new( <<-EOL ) - - - - true - - Item 1 - - - Item 2 - Thu, 13 Oct 2005 19:59:00 +0000 - - - Item 3 - - - - EOL - root_node = XPath.first(doc, "rss") - assert_not_nil root_node - channel_node = XPath.first(root_node, "channel") - assert_not_nil channel_node - items = XPath.match(channel_node, "*") - assert_equal 4, items.size - items = XPath.match(channel_node, "item") - assert_equal 3, items.size # fails - end - - - def test_ticket_42 - source = "" - doc = Document.new(source) - bElem = Element.new('b') - doc.root.add_element(bElem) - doc.elements.each('//b[name(..) = "a"]') { |x| - assert_equal x,bElem - } - end - - def test_ticket_56 - namespaces = {'h' => 'http://www.w3.org/1999/xhtml'} - - finaldoc = REXML::Document.new(File.read(fixture_path('google.2.xml'))) - - column_headers = [] - - REXML::XPath.each(finaldoc, '//h:form[@action="ModifyCampaign"]//h:th', - namespaces) do |el| - node = REXML::XPath.first(el, 'h:a/text()', namespaces) - column_headers << (node ? node.value : nil) - end - column_headers.map! { |h| h.to_s.strip.chomp } - expected = ["", "", "Current Status", "Current Budget", - "Clicks", "Impr.", "CTR", "Avg. CPC", "Cost", "Conv. Rate", - "Cost/Conv."] - assert_equal( expected, column_headers ) - end - - - def test_ticket_70 - string = < - - Text1, text, -text - - Text2, text, -text - - - - -EOF - doc = Document.new string - assert_equal( 1, XPath.match( doc, "//someelement[contains(@attribute,'1.10')]" ).length ) - end - - def test_ticket_43 - #url = http://news.search.yahoo.com/news/rss?p=market&ei=UTF-8&fl=0&x=wrt - - sum = File.open(fixture_path("yahoo.xml")) do |f| - Document.new(f).elements.to_a("//item").size - end - assert_equal( 10, sum ) - - text = File.open(fixture_path("yahoo.xml")) do |f| - Document.new(f).elements.to_a(%Q{//title[contains(text(), "'")]}).collect{|e| e.text}.join - end - assert_equal( "Broward labor market's a solid performer (Miami Herald)", text ) - end - - def test_ticket_57 - data = "zzz" - - r = Document.new(data) - - assert_equal(Text, REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").class) - assert_equal("zzz", REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").to_s) - end - - def test_ticket_59 - data = " - - - - - - - - - - - - - - - - - - - - - - - - - - - " - d = Document.new(data) - res = d.elements.to_a( "//c" ).collect {|e| e.attributes['id'].to_i} - assert_equal((1..12).to_a, res) - end - - def ticket_61_fixture(doc, xpath) - matches = [] - doc.elements.each(xpath) do |element| - matches << element - assert_equal('Add', element.text) - assert_equal('ButtonText', element.attributes['class']) - end - assert_equal(1, matches.length) - end - - def test_ticket_61_text - doc = File.open(fixture_path("ticket_61.xml")) do |file| - REXML::Document.new file - end - ticket_61_fixture( doc, "//div[text()='Add' and @class='ButtonText']" ) - end - - def test_ticket_61_contains - doc = File.open(fixture_path("ticket_61.xml")) do |file| - REXML::Document.new file - end - ticket_61_fixture( doc, "//div[contains(.,'Add') and @class='ButtonText']" ) - end - - def test_namespaces_0 - d = Document.new(%q{}) - assert_equal( 1, XPath.match( d, "//x:a" ).size ) - assert_equal( 1, XPath.match( d, "//x:*" ).size ) - end - - def test_ticket_71 - doc = Document.new(%Q{}) - el = doc.root.elements[1] - assert_equal( "element", el.name ) - el2 = XPath.first( doc.root, "element[@ns:attrname='foo']", { 'ns' => "xyz" } ) - assert_equal( el, el2 ) - end - - def test_ticket_78 - doc = <<-EOT - - - 123 - - - 123a - - - EOT - seq = %w{BEGIN 123 END BEGIN 123a END} - - xmlDoc = Document.new(doc) - - ["//element[tag='123']/tag", "//element[tag='123a']/tag"].each do |query| - assert_equal( "BEGIN", seq.shift ) - XPath.each(xmlDoc, query) { |element| - assert_equal( seq.shift, element.text ) - } - assert_equal( "END", seq.shift ) - end - end - - def test_ticket_79 - source = "test3" - d = REXML::Document.new( source ) - r = REXML::XPath.match( d, %q{/a/b[c='test']} ) - assert_equal(1, r.size()) - r = REXML::XPath.match( d, %q{/a/b[c='3']} ) - assert_equal(1, r.size()) - end - - def test_or_and - doc = " - - - test - - -

      - A link. -

      - - -" - - xmldoc = REXML::Document.new(doc) - xpath = "descendant::node()[(local-name()='link' or local-name()='a') and @rel='sub']" - hrefs = [] - xmldoc.elements.each(xpath) do |element| - hrefs << element.attributes["href"] - end - assert_equal(["/"], hrefs, "Bug #3842 [ruby-core:32447]") - end - end -end diff --git a/ruby/test/rexml/xpath/test_compare.rb b/ruby/test/rexml/xpath/test_compare.rb deleted file mode 100644 index bb666c9b1..000000000 --- a/ruby/test/rexml/xpath/test_compare.rb +++ /dev/null @@ -1,256 +0,0 @@ -# frozen_string_literal: false - -require_relative "../rexml_test_utils" - -require "rexml/document" - -module REXMLTests - class TestXPathCompare < Test::Unit::TestCase - def match(xml, xpath) - document = REXML::Document.new(xml) - REXML::XPath.match(document, xpath) - end - - class TestEqual < self - class TestNodeSet < self - def test_boolean_true - xml = <<-XML - - - - - - XML - assert_equal([true], - match(xml, "/root/child=true()")) - end - - def test_boolean_false - xml = <<-XML - - - - XML - assert_equal([false], - match(xml, "/root/child=true()")) - end - - def test_number_true - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([true], - match(xml, "/root/child=100")) - end - - def test_number_false - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([false], - match(xml, "/root/child=300")) - end - - def test_string_true - xml = <<-XML - - - text - string - - XML - assert_equal([true], - match(xml, "/root/child='string'")) - end - - def test_string_false - xml = <<-XML - - - text - string - - XML - assert_equal([false], - match(xml, "/root/child='nonexistent'")) - end - end - - class TestBoolean < self - def test_number_true - xml = "" - assert_equal([true], - match(xml, "true()=1")) - end - - def test_number_false - xml = "" - assert_equal([false], - match(xml, "true()=0")) - end - - def test_string_true - xml = "" - assert_equal([true], - match(xml, "true()='string'")) - end - - def test_string_false - xml = "" - assert_equal([false], - match(xml, "true()=''")) - end - end - - class TestNumber < self - def test_string_true - xml = "" - assert_equal([true], - match(xml, "1='1'")) - end - - def test_string_false - xml = "" - assert_equal([false], - match(xml, "1='2'")) - end - end - end - - class TestGreaterThan < self - class TestNodeSet < self - def test_boolean_truex - xml = <<-XML - - - - - XML - assert_equal([true], - match(xml, "/root/child>false()")) - end - - def test_boolean_false - xml = <<-XML - - - - - XML - assert_equal([false], - match(xml, "/root/child>true()")) - end - - def test_number_true - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([true], - match(xml, "/root/child>199")) - end - - def test_number_false - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([false], - match(xml, "/root/child>200")) - end - - def test_string_true - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([true], - match(xml, "/root/child>'199'")) - end - - def test_string_false - xml = <<-XML - - - 100 - 200 - - XML - assert_equal([false], - match(xml, "/root/child>'200'")) - end - end - - class TestBoolean < self - def test_string_true - xml = "" - assert_equal([true], - match(xml, "true()>'0'")) - end - - def test_string_false - xml = "" - assert_equal([false], - match(xml, "true()>'1'")) - end - end - - class TestNumber < self - def test_boolean_true - xml = "" - assert_equal([true], - match(xml, "true()>0")) - end - - def test_number_false - xml = "" - assert_equal([false], - match(xml, "true()>1")) - end - - def test_string_true - xml = "" - assert_equal([true], - match(xml, "1>'0'")) - end - - def test_string_false - xml = "" - assert_equal([false], - match(xml, "1>'1'")) - end - end - - class TestString < self - def test_string_true - xml = "" - assert_equal([true], - match(xml, "'1'>'0'")) - end - - def test_string_false - xml = "" - assert_equal([false], - match(xml, "'1'>'1'")) - end - end - end - end -end diff --git a/ruby/test/rexml/xpath/test_node.rb b/ruby/test/rexml/xpath/test_node.rb deleted file mode 100644 index e0e958e70..000000000 --- a/ruby/test/rexml/xpath/test_node.rb +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../rexml_test_utils" - -require "rexml/document" - -module REXMLTests - class TestXPathNode < Test::Unit::TestCase - def matches(xml, xpath) - document = REXML::Document.new(xml) - REXML::XPath.each(document, xpath).collect(&:to_s) - end - - class TestQName < self - def test_ascii - xml = <<-XML - - - - child - - - XML - assert_equal(["child"], - matches(xml, "/root/ascii/child")) - end - - def test_non_ascii - xml = <<-XML - - - - child - - - XML - assert_equal(["child"], - matches(xml, "/root/non-àscii/child")) - end - end - end -end diff --git a/ruby/test/rexml/xpath/test_predicate.rb b/ruby/test/rexml/xpath/test_predicate.rb deleted file mode 100644 index ce1aaa324..000000000 --- a/ruby/test/rexml/xpath/test_predicate.rb +++ /dev/null @@ -1,83 +0,0 @@ -# frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" -require "rexml/xpath" -require "rexml/parsers/xpathparser" - -module REXMLTests - class TestXPathPredicate < Test::Unit::TestCase - include REXML - SRC=<<-EOL -
      -
      - free flowing text. -
      -
      -
      - free flowing text. -
      -
      - free flowing text. -
      -
      -
      - EOL - - def setup - @doc = REXML::Document.new( SRC ) - @parser = REXML::Parsers::XPathParser.new - - end - - def test_predicates_parent - path = '//section[../self::section[@role="division"]]' - m = do_path( path ) - assert_equal( 2, m.size ) - assert_equal( "2", m[0].attributes["id"] ) - assert_nil( m[1].attributes["id"] ) - end - - def test_predicates_single - path = '//section[@role="subdivision" and not(../self::section[@role="division"])]' - m = do_path( path ) - assert_equal( 1, m.size ) - assert_equal( "1", m[0].attributes["id"] ) - end - - def test_predicates_multi - path = '//section[@role="subdivision"][not(../self::section[@role="division"])]' - m = do_path( path ) - assert_equal( 1, m.size ) - assert_equal( "1", m[0].attributes["id"] ) - end - - def do_path( path ) - m = REXML::XPath.match( @doc, path ) - #puts path, @parser.parse( path ).inspect - return m - end - - def test_get_no_siblings_terminal_nodes - source = <<-XML - - TEXT1 - - - - TEXT2 - - - -XML - doc = REXML::Document.new(source) - predicate = "count(child::node()|" + - "following-sibling::node()|" + - "preceding-sibling::node())=0" - m = REXML::XPath.match(doc, "/descendant-or-self::node()[#{predicate}]") - assert_equal( [REXML::Text.new("TEXT1"), - REXML::Text.new("TEXT2"), - REXML::Comment.new("COMMENT")], - m ) - end - end -end diff --git a/ruby/test/rexml/xpath/test_text.rb b/ruby/test/rexml/xpath/test_text.rb deleted file mode 100644 index 7222388e1..000000000 --- a/ruby/test/rexml/xpath/test_text.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rexml/document' -require 'rexml/element' -require 'rexml/xpath' - -module REXMLTests - class TestXPathText < Test::Unit::TestCase - def setup - @doc = REXML::Document.new - end - - def tear_down - end - - def test_text_as_element - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - REXML::Text.new('test', false, node2) - assert_equal(1, @doc.elements.size, "doc owns 1 element node1") - assert_same(node1, @doc.elements[1], "doc owns 1 element node1") - assert_equal(1, node1.elements.size, "node1 owns 1 element node2") - assert_same(node2, node1.elements[1], "node1 owns 1 element node2") - assert_equal(1, node2.size, "node2 owns 1 text element") - end - - def test_text_in_xpath_query - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - textnode = REXML::Text.new('test', false, node2) - textnode.parent = node2 # should be unnecessary - nodes = @doc.get_elements('//b') - assert_equal(1, nodes.size, "document has one element") - # why doesn't this query work right? - nodes = REXML::XPath.match(@doc, '//text()') - assert_equal(1, nodes.size, "//text() should yield one Text element") - assert_equal(REXML::Text, nodes[0].class) - end - - def test_comment_in_xpath_query - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - commentnode = REXML::Comment.new('test', node2) - nodes = REXML::XPath.match(@doc, '//comment()') - assert_equal(1, nodes.size, "//comment() should yield one Comment element") - assert_same commentnode, nodes[0] - end - - def test_parentage - node1 = REXML::Element.new('a', @doc) - assert_same(@doc, node1.parent, "node1 parent is document") - node2 = REXML::Element.new('b', node1) - assert_same(node1, node2.parent, "node2 parent is node1") - textnode = REXML::Text.new('test', false, node2) - # why isn't the text's parent node2? - # Also look at Comment, etc. - assert_same(node2, textnode.parent) - comment = REXML::Comment.new('Test comment', node2) - assert_same(node2, comment.parent) - end - - def test_ancestors - node1 = REXML::Element.new('a', @doc) - node2 = REXML::Element.new('b', node1) - textnode = REXML::Text.new('test', false, node2) - #textnode.parent = node2 # should be unnecessary - assert_same node2, textnode.parent - nodes = @doc.get_elements('//b/ancestor::*') - assert_equal(1, nodes.size, " has one element ancestor") - nodes = @doc.get_elements('//b/ancestor::node()') - assert_equal(2, nodes.size, " has two node ancestors") - nodes.sort_by!(&:name) - assert_kind_of REXML::Document, nodes[0] - assert_kind_of REXML::Element, nodes[1] - end - end -end diff --git a/ruby/test/rinda/test_rinda.rb b/ruby/test/rinda/test_rinda.rb index 22966532b..00e1ba787 100644 --- a/ruby/test/rinda/test_rinda.rb +++ b/ruby/test/rinda/test_rinda.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require 'test/unit' +require 'envutil' require 'drb/drb' require 'drb/eq' @@ -401,6 +402,7 @@ def test_cancel_01 end def test_cancel_02 + skip 'this test is unstable with --jit-wait' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? entry = @ts.write([:removeme, 1]) assert_equal([[:removeme, 1]], @ts.read_all([nil, nil])) entry.cancel @@ -638,30 +640,30 @@ def teardown end def test_do_reply - with_timeout(10) {_test_do_reply} + with_timeout(30) {_test_do_reply} end def _test_do_reply called = nil - callback = proc { |ts| + callback_orig = proc { |ts| called = ts } - callback = DRb::DRbObject.new callback + callback = DRb::DRbObject.new callback_orig @ts.write [:lookup_ring, callback] @rs.do_reply - wait_for(10) {called} + wait_for(30) {called} assert_same @ts, called end def test_do_reply_local - skip 'timeout-based test becomes unstable with --jit-wait' if RubyVM::MJIT.enabled? - with_timeout(10) {_test_do_reply_local} + skip 'timeout-based test becomes unstable with --jit-wait' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + with_timeout(30) {_test_do_reply_local} end def _test_do_reply_local @@ -675,7 +677,7 @@ def _test_do_reply_local @rs.do_reply - wait_for(10) {called} + wait_for(30) {called} assert_same @ts, called end diff --git a/ruby/test/ripper/dummyparser.rb b/ruby/test/ripper/dummyparser.rb index ca3698589..fa834bd0f 100644 --- a/ruby/test/ripper/dummyparser.rb +++ b/ruby/test/ripper/dummyparser.rb @@ -101,7 +101,11 @@ def on_var_alias(a, b) Node.new('valias', a, b) end - def on_alias_error(a) + def on_assign_error(mesg = nil, a) + Node.new('assign_error', a) + end + + def on_alias_error(mesg = nil, a) Node.new('aliaserr', a) end diff --git a/ruby/test/ripper/test_lexer.rb b/ruby/test/ripper/test_lexer.rb index 1794773d8..83130668b 100644 --- a/ruby/test/ripper/test_lexer.rb +++ b/ruby/test/ripper/test_lexer.rb @@ -90,6 +90,16 @@ def test_expr_at_beginning_in_heredoc assert_equal expect, Ripper.lex(src).map {|e| e[1]} end + def test_stack_at_on_heredoc_beg + src = "a <(name, *) {thru[name] = true} + + thru = {} + tree = parse('def foo() = 42', events, &hook) + assert_equal({on_def: true}, thru) + assert_equal '[def(foo,[],bodystmt(42))]', tree + + thru = {} + tree = parse('def foo() = 42 rescue 0', events, &hook) + assert_equal({on_def: true}, thru) + assert_equal '[def(foo,[],bodystmt(rescue_mod(42,0)))]', tree + + thru = {} + tree = parse('def foo=() = 42', events, &hook) + assert_equal({on_def: true, on_parse_error: true}, thru) + + thru = {} + tree = parse('def foo=() = 42 rescue 0', events, &hook) + assert_equal({on_def: true, on_parse_error: true}, thru) + + thru = {} + tree = parse('def foo() = p 42', events, &hook) + assert_equal({on_def: true}, thru) + assert_equal '[def(foo,[],bodystmt(command(p,[42])))]', tree + + thru = {} + tree = parse('def foo() = p 42 rescue 0', events, &hook) + assert_equal({on_def: true}, thru) + assert_equal '[def(foo,[],bodystmt(rescue_mod(command(p,[42]),0)))]', tree end def test_defined @@ -661,6 +715,40 @@ def test_defs assert_equal(true, thru_parse_error) end + def test_endless_defs + events = %i[on_defs on_parse_error] + thru = nil + hook = ->(name, *) {thru[name] = true} + + thru = {} + tree = parse('def foo.bar() = 42', events, &hook) + assert_equal({on_defs: true}, thru) + assert_equal '[defs(vcall(foo),.,bar,[],bodystmt(42))]', tree + + thru = {} + tree = parse('def foo.bar() = 42 rescue 0', events, &hook) + assert_equal({on_defs: true}, thru) + assert_equal '[defs(vcall(foo),.,bar,[],bodystmt(rescue_mod(42,0)))]', tree + + thru = {} + tree = parse('def foo.bar=() = 42', events, &hook) + assert_equal({on_defs: true, on_parse_error: true}, thru) + + thru = {} + tree = parse('def foo.bar=() = 42 rescue 0', events, &hook) + assert_equal({on_defs: true, on_parse_error: true}, thru) + + thru = {} + tree = parse('def foo.bar() = p 42', events, &hook) + assert_equal({on_defs: true}, thru) + assert_equal '[defs(vcall(foo),.,bar,[],bodystmt(command(p,[42])))]', tree + + thru = {} + tree = parse('def foo.bar() = p 42 rescue 0', events, &hook) + assert_equal({on_defs: true}, thru) + assert_equal '[defs(vcall(foo),.,bar,[],bodystmt(rescue_mod(command(p,[42]),0)))]', tree + end + def test_do_block thru_do_block = false parse('proc do end', :on_do_block) {thru_do_block = true} @@ -1490,16 +1578,9 @@ def test_local_variables end def test_block_variables - assert_equal("[fcall(proc,[],&block([],[void()]))]", parse("proc{|;y|}")) - if defined?(Process::RLIMIT_AS) - dir = File.dirname(__FILE__) - as = 100 * 1024 * 1024 # 100MB - as *= 2 if RubyVM::MJIT.enabled? # space for compiler - assert_in_out_err(%W(-I#{dir} -rdummyparser), - "Process.setrlimit(Process::RLIMIT_AS,#{as}); "\ - "puts DummyParser.new('proc{|;y|!y}').parse", - ["[fcall(proc,[],&block([],[unary(!,ref(y))]))]"], [], '[ruby-dev:39423]') - end + bug4159 = '[ruby-dev:39423]' + assert_equal("[fcall(proc,[],&block([],[void()]))]", parse("proc{|;y|}"), bug4159) + assert_equal("[fcall(proc,[],&block([],[unary(!,ref(y))]))]", parse("proc{|;y|!y}"), bug4159) end def test_unterminated_regexp @@ -1529,12 +1610,28 @@ def test_warning_ignored_magic_comment assert_equal("frozen_string_literal", args[0]) end + def test_warning_invalid_magic_comment + fmt, *args = warning("#-*- frozen-string-literal: nottrue -*-") + assert_match(/invalid value/, fmt) + assert_equal(%w"frozen_string_literal nottrue", args) + end + def test_warn_cr_in_middle fmt = nil assert_warn("") {fmt, = warn("\r;")} assert_match(/encountered/, fmt) end + def test_warn_mismatched_indentations + fmt, tokend, tokbeg, line = assert_warning("") {break warn("if true\n end\n")} + assert_match(/mismatched indentations/, fmt) + assert_equal(["if", "end", 1], [tokbeg, tokend, line]) + result = assert_warning("") { + warn("begin\n" " def f() = nil\n" "end\n") {break :ok} + } + assert_equal(:ok, result) + end + def test_in thru_in = false parse('case 0; in 0; end', :on_in) {thru_in = true} @@ -1547,6 +1644,12 @@ def test_aryptn assert_equal true, thru_aryptn end + def test_fndptn + thru_fndptn = false + parse('case 0; in [*,0,*]; end', :on_fndptn) {thru_fndptn = true} + assert_equal true, thru_fndptn + end + def test_hshptn thru_hshptn = false parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true} diff --git a/ruby/test/ripper/test_ripper.rb b/ruby/test/ripper/test_ripper.rb index ab841b761..76276c54e 100644 --- a/ruby/test/ripper/test_ripper.rb +++ b/ruby/test/ripper/test_ripper.rb @@ -75,6 +75,15 @@ def test_yydebug_ident assert_include out.string[/.*"local variable or method".*/], 'test_xxxx' end + def test_yydebug_string + out = StringIO.new + ripper = Ripper.new '"woot"' + ripper.yydebug = true + ripper.debug_output = out + ripper.parse + assert_include out.string[/.*"literal content".*/], 'woot' + end + def test_regexp_with_option bug11932 = '[ruby-core:72638] [Bug #11932]' src = '/[\xC0-\xF0]/u'.dup.force_encoding(Encoding::UTF_8) diff --git a/ruby/test/ripper/test_scanner_events.rb b/ruby/test/ripper/test_scanner_events.rb index cef584c15..13bd44e83 100644 --- a/ruby/test/ripper/test_scanner_events.rb +++ b/ruby/test/ripper/test_scanner_events.rb @@ -56,13 +56,13 @@ def test_tokenize end def test_lex - assert_equal [], + assert_lex [], Ripper.lex('') - assert_equal [[[1,0], :on_ident, "a", Ripper::EXPR_CMDARG]], + assert_lex [[[1,0], :on_ident, "a", Ripper::EXPR_CMDARG]], Ripper.lex('a') - assert_equal [[[1, 0], :on_kw, "nil", Ripper::EXPR_END]], + assert_lex [[[1, 0], :on_kw, "nil", Ripper::EXPR_END]], Ripper.lex("nil") - assert_equal [[[1, 0], :on_kw, "def", Ripper::EXPR_FNAME], + assert_lex [[[1, 0], :on_kw, "def", Ripper::EXPR_FNAME], [[1, 3], :on_sp, " ", Ripper::EXPR_FNAME], [[1, 4], :on_ident, "m", Ripper::EXPR_ENDFN], [[1, 5], :on_lparen, "(", Ripper::EXPR_BEG | Ripper::EXPR_LABEL], @@ -70,39 +70,39 @@ def test_lex [[1, 7], :on_rparen, ")", Ripper::EXPR_ENDFN], [[1, 8], :on_kw, "end", Ripper::EXPR_END]], Ripper.lex("def m(a)end") - assert_equal [[[1, 0], :on_int, "1", Ripper::EXPR_END], + assert_lex [[[1, 0], :on_int, "1", Ripper::EXPR_END], [[1, 1], :on_nl, "\n", Ripper::EXPR_BEG], [[2, 0], :on_int, "2", Ripper::EXPR_END], [[2, 1], :on_nl, "\n", Ripper::EXPR_BEG], [[3, 0], :on_int, "3", Ripper::EXPR_END]], Ripper.lex("1\n2\n3") - assert_equal [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG], [[1, 5], :on_nl, "\n", Ripper::EXPR_BEG], [[2, 0], :on_tstring_content, "heredoc\n", Ripper::EXPR_BEG], [[3, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]], Ripper.lex("<<""EOS\nheredoc\nEOS") - assert_equal [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG], [[1, 5], :on_nl, "\n", Ripper::EXPR_BEG], [[2, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]], Ripper.lex("<<""EOS\nEOS"), "bug#4543" - assert_equal [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG], [[1, 1], :on_tstring_content, "foo\nbar", Ripper::EXPR_BEG], [[2, 3], :on_regexp_end, "/", Ripper::EXPR_BEG]], Ripper.lex("/foo\nbar/") - assert_equal [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG], [[1, 1], :on_tstring_content, "foo\n\u3020", Ripper::EXPR_BEG], [[2, 3], :on_regexp_end, "/", Ripper::EXPR_BEG]], Ripper.lex("/foo\n\u3020/") - assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], [[1, 1], :on_tstring_content, "foo\n\xe3\x80\xa0", Ripper::EXPR_BEG], [[2, 3], :on_tstring_end, "'", Ripper::EXPR_END]], Ripper.lex("'foo\n\xe3\x80\xa0'") - assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], [[1, 1], :on_tstring_content, "\u3042\n\u3044", Ripper::EXPR_BEG], [[2, 3], :on_tstring_end, "'", Ripper::EXPR_END]], Ripper.lex("'\u3042\n\u3044'") - assert_equal [[[1, 0], :on_rational, "1r", Ripper::EXPR_END], + assert_lex [[[1, 0], :on_rational, "1r", Ripper::EXPR_END], [[1, 2], :on_nl, "\n", Ripper::EXPR_BEG], [[2, 0], :on_imaginary, "2i", Ripper::EXPR_END], [[2, 2], :on_nl, "\n", Ripper::EXPR_BEG], @@ -113,18 +113,25 @@ def test_lex [[5, 0], :on_imaginary, "5.6ri", Ripper::EXPR_END], ], Ripper.lex("1r\n2i\n3ri\n4.2r\n5.6ri") - assert_equal [[[1, 0], :on_heredoc_beg, "<<~EOS", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_heredoc_beg, "<<~EOS", Ripper::EXPR_BEG], [[1, 6], :on_nl, "\n", Ripper::EXPR_BEG], [[2, 0], :on_ignored_sp, " ", Ripper::EXPR_BEG], [[2, 2], :on_tstring_content, "heredoc\n", Ripper::EXPR_BEG], [[3, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG] ], Ripper.lex("<<~EOS\n heredoc\nEOS") - assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], + assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG], [[1, 1], :on_tstring_content, "foo", Ripper::EXPR_BEG]], Ripper.lex("'foo") end + def assert_lex(expected, *rest) + expected = expected.map do |pos, type, tok, state, *rest| + [pos, type, tok, Ripper::Lexer::State.new(state), *rest] + end + assert_equal(expected, *rest) + end + def test_location assert_location "" assert_location " " diff --git a/ruby/test/ripper/test_sexp.rb b/ruby/test/ripper/test_sexp.rb index 89b45941a..9faeaba78 100644 --- a/ruby/test/ripper/test_sexp.rb +++ b/ruby/test/ripper/test_sexp.rb @@ -412,6 +412,43 @@ def test_dsym [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, nil, nil], [[:void_stmt]], nil]], + [__LINE__, %q{ 0 => [*, a, *] }] => + [:case, + [:@int, "0", [1, 0]], + [:in, + [:fndptn, + nil, + [:var_field, nil], + [[:var_field, [:@ident, "a", [1, 9]]]], + [:var_field, nil]], + nil, + nil]], + + [__LINE__, %q{ 0 => [*a, b, *c] }] => + [:case, + [:@int, "0", [1, 0]], + [:in, + [:fndptn, + nil, + [:var_field, [:@ident, "a", [1, 7]]], + [[:var_field, [:@ident, "b", [1, 10]]]], + [:var_field, [:@ident, "c", [1, 14]]]], + nil, + nil]], + + [__LINE__, %q{ 0 => A(*a, b, c, *d) }] => + [:case, + [:@int, "0", [1, 0]], + [:in, + [:fndptn, + [:var_ref, [:@const, "A", [1, 5]]], + [:var_field, [:@ident, "a", [1, 8]]], + [[:var_field, [:@ident, "b", [1, 11]]], + [:var_field, [:@ident, "c", [1, 14]]]], + [:var_field, [:@ident, "d", [1, 18]]]], + nil, + nil]], + [__LINE__, %q{ case 0; in {a: 0}; end }] => [:case, [:@int, "0", [1, 5]], @@ -441,6 +478,14 @@ def test_dsym [__LINE__, %q{ case 0; in "a\x0":a1, "a\0":a2; end }] => nil, # duplicated key name + + [__LINE__, %q{ case 0; in ^(0+0); end } ] => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:begin, [:binary, [:@int, "0", [1, 13]], :+, [:@int, "0", [1, 15]]]], + [[:void_stmt]], + nil]], } pattern_matching_data.each do |(i, src), expected| define_method(:"test_pattern_matching_#{i}") do @@ -470,4 +515,23 @@ def on_label(token) assert_equal(:hshptn, hshptn[0]) assert_equal([:@label, "a:"], hshptn.dig(2, 0, 0)) end + + def test_raise_errors_keyword + assert_raise(SyntaxError) { Ripper.sexp('def req(true) end', raise_errors: true) } + assert_raise(SyntaxError) { Ripper.sexp_raw('def req(true) end', raise_errors: true) } + end + + def test_hash_value_omission + sexp = Ripper.sexp("{x: 1, y:}") + assoclist = search_sexp(:assoclist_from_args, sexp) + x = assoclist[1][0] + assert_equal(:@label, x[1][0]) + assert_equal("x:", x[1][1]) + assert_equal(:@int, x[2][0]) + assert_equal("1", x[2][1]) + y = assoclist[1][1] + assert_equal(:@label, y[1][0]) + assert_equal("y:", y[1][1]) + assert_equal(nil, y[2]) + end end if ripper_test diff --git a/ruby/test/rss/dot.png b/ruby/test/rss/dot.png deleted file mode 100644 index 9c6960fa2..000000000 Binary files a/ruby/test/rss/dot.png and /dev/null differ diff --git a/ruby/test/rss/rss-assertions.rb b/ruby/test/rss/rss-assertions.rb deleted file mode 100644 index 86fb91aa1..000000000 --- a/ruby/test/rss/rss-assertions.rb +++ /dev/null @@ -1,2120 +0,0 @@ -# frozen_string_literal: false -require 'erb' - -module RSS - module Assertions - def _wrap_assertion - yield - end - - def assert_parse(rss, assert_method, *args) - __send__("assert_#{assert_method}", *args) do - ::RSS::Parser.parse(rss) - end - __send__("assert_#{assert_method}", *args) do - ::RSS::Parser.parse(rss, false).validate - end - end - - def assert_ns(prefix, uri) - _wrap_assertion do - begin - yield - flunk("Not raise NSError") - rescue ::RSS::NSError => e - assert_equal(prefix, e.prefix) - assert_equal(uri, e.uri) - end - end - end - - def assert_missing_tag(tag, parent) - _wrap_assertion do - begin - yield - flunk("Not raise MissingTagError") - rescue ::RSS::MissingTagError => e - assert_equal(tag, e.tag) - assert_equal(parent, e.parent) - end - end - end - - def assert_too_much_tag(tag, parent) - _wrap_assertion do - begin - yield - flunk("Not raise TooMuchTagError") - rescue ::RSS::TooMuchTagError => e - assert_equal(tag, e.tag) - assert_equal(parent, e.parent) - end - end - end - - def assert_missing_attribute(tag, attrname) - _wrap_assertion do - begin - yield - flunk("Not raise MissingAttributeError") - rescue ::RSS::MissingAttributeError => e - assert_equal(tag, e.tag) - assert_equal(attrname, e.attribute) - end - end - end - - def assert_not_expected_tag(tag, uri, parent) - _wrap_assertion do - begin - yield - flunk("Not raise NotExpectedTagError") - rescue ::RSS::NotExpectedTagError => e - assert_equal(tag, e.tag) - assert_equal(uri, e.uri) - assert_equal(parent, e.parent) - end - end - end - - def assert_not_available_value(tag, value, attribute=nil) - _wrap_assertion do - begin - yield - flunk("Not raise NotAvailableValueError") - rescue ::RSS::NotAvailableValueError => e - assert_equal(tag, e.tag) - assert_equal(value, e.value) - assert_equal(attribute, e.attribute) - end - end - end - - def assert_not_set_error(name, variables) - _wrap_assertion do - begin - yield - flunk("Not raise NotSetError") - rescue ::RSS::NotSetError => e - assert_equal(name, e.name) - assert_kind_of(Array, variables) - assert_equal(variables.sort, e.variables.sort) - end - end - end - - def assert_xml_declaration(version, encoding, standalone, rss) - _wrap_assertion do - assert_equal(version, rss.version) - assert_equal(encoding, rss.encoding) - assert_equal(standalone, rss.standalone) - end - end - - def assert_xml_stylesheet_attrs(attrs, xsl) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - ::RSS::XMLStyleSheet::ATTRIBUTES.each do |name| - assert_equal(n_attrs[name], xsl.__send__(name)) - end - end - end - - def assert_xml_stylesheet(target, attrs, xsl) - _wrap_assertion do - if attrs.has_key?(:href) - if !attrs.has_key?(:type) and attrs.has_key?(:guess_type) - attrs[:type] = attrs[:guess_type] - end - assert_equal("xml-stylesheet", target) - assert_xml_stylesheet_attrs(attrs, xsl) - else - assert_nil(target) - assert_equal("", xsl.to_s) - end - end - end - - def assert_xml_stylesheet_pis(attrs_ary, rss=nil) - _wrap_assertion do - if rss.nil? - rss = ::RSS::RDF.new - setup_rss10(rss) - end - xss_strs = [] - attrs_ary.each do |attrs| - xss = ::RSS::XMLStyleSheet.new(attrs) - xss_strs.push(xss.to_s) - rss.xml_stylesheets.push(xss) - end - pi_str = rss.to_s.gsub(/<\?xml .*\n/, "").gsub(/\s*<[^\?].*\z/m, "") - assert_equal(xss_strs.join("\n"), pi_str) - end - end - - def assert_xml_stylesheets(attrs, xss) - _wrap_assertion do - xss.each_with_index do |xs, i| - assert_xml_stylesheet_attrs(attrs[i], xs) - end - end - end - - - def assert_atom_person(tag_name, generator) - _wrap_assertion do - name = "Mark Pilgrim" - uri = "http://example.org/" - email = "f8dy@example.com" - - assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name) - <#{tag_name}/> -EOA - - assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name) - <#{tag_name}> - #{uri} - #{email} - -EOA - - assert_parse(generator.call(<<-EOA), :nothing_raised) - <#{tag_name}> - #{name} - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - <#{tag_name}> - #{name} - #{uri} - #{email} - -EOA - - person = yield(feed) - assert_not_nil(person) - assert_equal(name, person.name.content) - assert_equal(uri, person.uri.content) - assert_equal(email, person.email.content) - end - end - - def assert_atom_category(generator) - _wrap_assertion do - term = "Music" - scheme = "http://xmlns.com/wordnet/1.6/" - label = "music" - - missing_args = [:missing_attribute, "category", "term"] - assert_parse(generator.call(<<-EOA), *missing_args) - -EOA - - assert_parse(generator.call(<<-EOA), *missing_args) - -EOA - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - -EOA - - category = yield(feed) - assert_not_nil(category) - assert_equal(term, category.term) - assert_equal(scheme, category.scheme) - assert_equal(label, category.label) - end - end - - def assert_atom_link(generator) - _wrap_assertion do - href = "http://example.org/feed.atom" - rel = "self" - type = "application/atom+xml" - hreflang = "en" - title = "Atom" - length = "1024" - - assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href") - -EOA - - assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href") - -EOA - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - -EOA - - link = yield(feed) - assert_not_nil(link) - assert_equal(href, link.href) - assert_equal(rel, link.rel) - assert_equal(type, link.type) - assert_equal(hreflang, link.hreflang) - assert_equal(title, link.title) - assert_equal(length, link.length) - - - href = "http://example.org/index.html.ja" - parent = link.parent.tag_name - return if parent == "source" - - optional_attributes = %w(hreflang="ja" type="text/html") - 0.upto(optional_attributes.size) do |i| - combination(optional_attributes, i).each do |attributes| - attrs = attributes.join(" ") - assert_parse(generator.call(<<-EOA), :too_much_tag, "link", parent) - - -EOA - end - end - end - end - - def assert_atom_generator(generator) - _wrap_assertion do - uri = "http://www.example.com/" - version = "1.0" - content = "Example Toolkit" - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{content} -EOA - - gen = yield(feed) - assert_not_nil(gen) - assert_equal(uri, gen.uri) - assert_equal(version, gen.version) - assert_equal(content, gen.content) - end - end - - def assert_atom_icon(generator) - _wrap_assertion do - content = "http://www.example.com/example.png" - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{content} -EOA - - icon = yield(feed) - assert_not_nil(icon) - assert_equal(content, icon.content) - end - end - - def assert_atom_text_construct(tag_name, generator) - _wrap_assertion do - [nil, "text", "html"].each do |type| - attr = "" - attr = " type=\"#{type}\"" if type - assert_parse(generator.call(<<-EOA), :nothing_raised) - <#{tag_name}#{attr}/> -EOA - end - - assert_parse(generator.call(<<-EOA), :missing_tag, "div", tag_name) - <#{tag_name} type="xhtml"/> -EOA - - args = ["x", Atom::URI, tag_name] - assert_parse(generator.call(<<-EOA), :not_expected_tag, *args) - <#{tag_name} type="xhtml"> -EOA - - invalid_value = "invalid" - args = ["type", invalid_value] - assert_parse(generator.call(<<-EOA), :not_available_value, *args) - <#{tag_name} type="#{invalid_value}"/> -EOA - - [ - [nil, "A lot of effort went into making this effortless"], - ["text", "A lot of effort went into making this effortless"], - ["html", "A lot of effort went into making this effortless"], - ].each do |type, content| - attr = "" - attr = " type=\"#{type}\"" if type - feed = RSS::Parser.parse(generator.call(<<-EOA)) - <#{tag_name}#{attr}>#{h content} -EOA - - element = yield(feed) - assert_not_nil(element) - assert_equal(type, element.type) - assert_equal(content, element.content) - end - - [false, true].each do |with_space| - xhtml_uri = "http://www.w3.org/1999/xhtml" - xhtml_content = "
      abc
      " - xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - ["abc"]) - content = xhtml_content - content = " #{content} " if with_space - feed = RSS::Parser.parse(generator.call(<<-EOA)) - <#{tag_name} type="xhtml">#{content} -EOA - - element = yield(feed) - assert_not_nil(element) - assert_equal("xhtml", element.type) - assert_equal(xhtml_content, element.content) - assert_equal(xhtml_element, element.xhtml) - end - end - end - - def assert_atom_date_construct(tag_name, generator) - _wrap_assertion do - args = [tag_name, ""] - assert_parse(generator.call(<<-EOR), :not_available_value, *args) - <#{tag_name}/> -EOR - - [ - ["xxx", false], - ["2007", false], - ["2007/02/09", true], - ].each do |invalid_value, can_parse| - assert_not_available_value(tag_name, invalid_value) do - RSS::Parser.parse(generator.call(<<-EOR)) - <#{tag_name}>#{invalid_value} -EOR - end - - feed = RSS::Parser.parse(generator.call(<<-EOR), false) - <#{tag_name}>#{invalid_value} -EOR - value = yield(feed).content - if can_parse - assert_equal(Time.parse(invalid_value), value) - else - assert_nil(value) - end - end - - [ - "2003-12-13T18:30:02Z", - "2003-12-13T18:30:02.25Z", - "2003-12-13T18:30:02+01:00", - "2003-12-13T18:30:02.25+01:00", - ].each do |valid_value| - assert_parse(generator.call(<<-EOR), :nothing_raised) - <#{tag_name}>#{valid_value} -EOR - - feed = RSS::Parser.parse(generator.call(<<-EOR)) - <#{tag_name}>#{valid_value} -EOR - assert_equal(Time.parse(valid_value), yield(feed).content) - end - end - end - - def assert_atom_logo(generator) - _wrap_assertion do - content = "http://www.example.com/example.png" - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{content} -EOA - - logo = yield(feed) - assert_not_nil(logo) - assert_equal(content, logo.content) - end - end - - def assert_atom_content(generator, &getter) - _wrap_assertion do - assert_atom_content_inline_text(generator, &getter) - assert_atom_content_inline_xhtml(generator, &getter) - assert_atom_content_inline_other(generator, &getter) - assert_atom_content_out_of_line(generator, &getter) - end - end - - def assert_atom_content_inline_text(generator) - _wrap_assertion do - [nil, "text", "html"].each do |type| - content = "sample content"] - ].each do |type, content_content| - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{h content_content} -EOA - content = yield(feed) - assert_equal(type, content.type) - if %w(text html).include?(type) - assert(content.inline_text?) - else - assert(!content.inline_text?) - end - if type == "html" - assert(content.inline_html?) - else - assert(!content.inline_html?) - end - assert(!content.inline_xhtml?) - if type == "text/plain" - assert(content.inline_other?) - assert(content.inline_other_text?) - else - assert(!content.inline_other?) - assert(!content.inline_other_text?) - end - assert(!content.inline_other_xml?) - assert(!content.inline_other_base64?) - assert(!content.out_of_line?) - assert(!content.have_xml_content?) - assert_equal(content_content, content.content) - end - end - end - - def assert_atom_content_inline_xhtml(generator) - _wrap_assertion do - args = ["div", "content"] - assert_parse(generator.call(<<-EOA), :missing_tag, *args) - -EOA - - args = ["x", Atom::URI, "content"] - assert_parse(generator.call(<<-EOA), :not_expected_tag, *args) - -EOA - - xhtml_uri = "http://www.w3.org/1999/xhtml" - xhtml_content = "
      abc
      " - xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - ["abc"]) - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{xhtml_content} -EOA - - content = yield(feed) - assert_not_nil(content) - assert_equal("xhtml", content.type) - assert(!content.inline_text?) - assert(!content.inline_html?) - assert(content.inline_xhtml?) - assert(!content.inline_other?) - assert(!content.inline_other_text?) - assert(!content.inline_other_xml?) - assert(!content.inline_other_base64?) - assert(!content.out_of_line?) - assert(content.have_xml_content?) - assert_equal(xhtml_content, content.content) - assert_equal(xhtml_element, content.xhtml) - end - end - - def assert_atom_content_inline_other(generator, &getter) - _wrap_assertion do - assert_atom_content_inline_other_text(generator, &getter) - assert_atom_content_inline_other_xml(generator, &getter) - end - end - - def assert_atom_content_inline_other_text(generator) - _wrap_assertion do - type = "image/png" - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - png_file = File.join(File.dirname(__FILE__), "dot.png") - png = File.open(png_file, "rb") do |file| - file.read.force_encoding("binary") - end - base64_content = [png].pack("m").delete("\n") - - [false, true].each do |with_space| - xml_content = base64_content - xml_content = " #{base64_content}" if with_space - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{xml_content} -EOA - - content = yield(feed) - assert_not_nil(content) - assert_equal(type, content.type) - assert(!content.inline_text?) - assert(!content.inline_html?) - assert(!content.inline_xhtml?) - assert(content.inline_other?) - assert(!content.inline_other_text?) - assert(!content.inline_other_xml?) - assert(content.inline_other_base64?) - assert(!content.out_of_line?) - assert(!content.have_xml_content?) - assert_equal(png, content.content) - - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([], {"type" => type}, base64_content, xml) - end - end - end - - def assert_atom_content_inline_other_xml(generator) - _wrap_assertion do - type = "image/svg+xml" - - assert_parse(generator.call(<<-EOA), :nothing_raised) - -EOA - - svg_uri = "http://www.w3.org/2000/svg" - svg_width = "50pt" - svg_height = "20pt" - svg_version = "1.0" - text_x = "15" - text_y = "15" - text = "text" - svg_content = <<-EOS -#{text} -EOS - - text_element = RSS::XML::Element.new("text", nil, svg_uri, - { - "x" => text_x, - "y" => text_y, - }, - [text]) - svg_element = RSS::XML::Element.new("svg", nil, svg_uri, - { - "xmlns" => svg_uri, - "width" => svg_width, - "height" => svg_height, - "version" => svg_version, - }, - [text_element]) - feed = RSS::Parser.parse(generator.call(<<-EOA)) - #{svg_content} -EOA - - content = yield(feed) - assert_not_nil(content) - assert_equal(type, content.type) - assert(!content.inline_text?) - assert(!content.inline_html?) - assert(!content.inline_xhtml?) - assert(content.inline_other?) - assert(!content.inline_other_text?) - assert(content.inline_other_xml?) - assert(!content.inline_other_base64?) - assert(!content.out_of_line?) - assert(content.have_xml_content?) - assert_equal(REXML::Document.new(svg_content).to_s.chomp, - REXML::Document.new(content.content).to_s.chomp) - assert_equal(svg_element, content.xml) - assert_nil(content.xhtml) - end - end - - def assert_atom_content_out_of_line(generator) - _wrap_assertion do - text_type = "text/plain" - text_src = "http://example.com/README.txt" - - missing_args = [:missing_attribute, "content", "type"] - # RSS Parser raises error even if this is "should" not "must". - assert_parse(generator.call(<<-EOA), *missing_args) - -EOA - - content_content = "xxx" - not_available_value_args = [:not_available_value, - "content", content_content] - assert_parse(generator.call(<<-EOA), *not_available_value_args) - #{content_content} -EOA - - feed = RSS::Parser.parse(generator.call(<<-EOA)) - -EOA - content = yield(feed) - assert_not_nil(content) - assert_equal(text_type, content.type) - assert_equal(text_src, content.src) - assert(!content.inline_text?) - assert(!content.inline_html?) - assert(!content.inline_xhtml?) - assert(!content.inline_other?) - assert(!content.inline_other_text?) - assert(!content.inline_other_xml?) - assert(!content.inline_other_base64?) - assert(content.out_of_line?) - assert(!content.have_xml_content?) - assert_nil(content.xml) - assert_nil(content.xhtml) - assert_equal("", content.content) - end - end - - def assert_atom_source(generator, &getter) - _wrap_assertion do - assert_atom_source_author(generator, &getter) - assert_atom_source_category(generator, &getter) - assert_atom_source_contributor(generator, &getter) - assert_atom_source_generator(generator, &getter) - assert_atom_source_icon(generator, &getter) - assert_atom_source_id(generator, &getter) - assert_atom_source_link(generator, &getter) - assert_atom_source_logo(generator, &getter) - assert_atom_source_rights(generator, &getter) - assert_atom_source_subtitle(generator, &getter) - assert_atom_source_title(generator, &getter) - assert_atom_source_updated(generator, &getter) - end - end - - def assert_atom_source_author(generator) - assert_atom_person("author", generator) do |feed| - source = yield(feed) - assert_equal(1, source.authors.size) - source.author - end - end - - def assert_atom_source_category(generator) - assert_atom_category(generator) do |feed| - source = yield(feed) - assert_equal(1, source.categories.size) - source.category - end - end - - def assert_atom_source_contributor(generator) - assert_atom_person("contributor", generator) do |feed| - source = yield(feed) - assert_equal(1, source.contributors.size) - source.contributor - end - end - - def assert_atom_source_generator(generator) - assert_atom_generator(generator) do |feed| - yield(feed).generator - end - end - - def assert_atom_source_icon(generator) - assert_atom_icon(generator) do |feed| - yield(feed).icon - end - end - - def assert_atom_source_id(generator) - id_content = "urn:uuid:a2fb588b-5674-4898-b420-265a734fea69" - id = "#{id_content}" - feed = RSS::Parser.parse(generator.call(id)) - assert_equal(id_content, yield(feed).id.content) - end - - def assert_atom_source_link(generator) - assert_atom_link(generator) do |feed| - source = yield(feed) - assert_equal(1, source.links.size) - source.link - end - end - - def assert_atom_source_logo(generator) - assert_atom_logo(generator) do |feed| - yield(feed).logo - end - end - - def assert_atom_source_rights(generator) - assert_atom_text_construct("rights", generator) do |feed| - yield(feed).rights - end - end - - def assert_atom_source_subtitle(generator) - assert_atom_text_construct("subtitle", generator) do |feed| - yield(feed).subtitle - end - end - - def assert_atom_source_title(generator) - assert_atom_text_construct("title", generator) do |feed| - yield(feed).title - end - end - - def assert_atom_source_updated(generator) - assert_atom_date_construct("updated", generator) do |feed| - yield(feed).updated - end - end - - def assert_dublin_core(elems, target) - _wrap_assertion do - elems.each do |name, value| - assert_equal(value, target.__send__("dc_#{name}")) - end - end - end - - def assert_multiple_dublin_core(elems, target) - _wrap_assertion do - elems.each do |name, values, plural| - plural ||= "#{name}s" - actual = target.__send__("dc_#{plural}").collect{|x| x.value} - assert_equal(values, actual) - end - end - end - - def assert_syndication(elems, target) - _wrap_assertion do - elems.each do |name, value| - meth = "sy_#{name}" - value = value.to_i if meth == "sy_updateFrequency" - assert_equal(value, target.__send__(meth )) - end - end - end - - def assert_content(elems, target) - _wrap_assertion do - elems.each do |name, value| - assert_equal(value, target.__send__("content_#{name}")) - end - end - end - - def assert_trackback(attrs, target) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - if n_attrs["ping"] - assert_equal(n_attrs["ping"], target.trackback_ping) - end - if n_attrs["abouts"] - n_attrs["abouts"].each_with_index do |about, i| - assert_equal(about, target.trackback_abouts[i].value) - end - end - end - end - - def assert_taxo_topic(topics, target) - _wrap_assertion do - topics.each_with_index do |topic, i| - taxo_topic = target.taxo_topics[i] - topic.each do |name, value| - case name - when :link - assert_equal(value, taxo_topic.about) - assert_equal(value, taxo_topic.taxo_link) - when :topics - assert_equal(value, taxo_topic.taxo_topics.resources) - else - assert_equal(value, taxo_topic.__send__("dc_#{name}")) - end - end - end - end - end - - - def assert_attributes(attrs, names, target) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - names.each do |info| - if info.is_a?(String) - name = info - type = nil - else - name, type = info - end - value = n_attrs[name] - if value.is_a?(Time) - actual = target.__send__(name) - assert_instance_of(Time, actual) - assert_equal(value.to_i, actual.to_i) - elsif value - case type - when :integer - value = value.to_i - when :boolean - value = value == "true" if value.is_a?(String) - end - assert_equal(value, target.__send__(name)) - end - end - end - end - - def assert_rexml_element(children, attrs, text, element, text_type=nil) - _wrap_assertion do - if children - children_info = element.elements.collect {|e| [e.namespace, e.name]} - assert_equal(children.collect {|uri, name| [uri, name]}.sort, - children_info.sort) - end - if attrs - assert_equal(attrs.collect {|k, v| [k, v]}.sort, - element.attributes.collect {|k, v| [k, v]}.sort) - end - case text_type - when :time - assert_not_nil(element.text) - assert_equal(Time.parse(text).to_s, Time.parse(element.text).to_s) - else - assert_equal(text, element.text) - end - end - end - - def _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) - _wrap_assertion do - persons = [] - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - targets.each do |target| - person = { - :name => target.name, - :uri => target.uri, - :email => target.email, - } - persons << person if person[:name] - end - end - - actual_persons = chain_reader(feed, feed_readers) || [] - actual_persons = actual_persons.collect do |person| - { - :name => person.name ? person.name.content : nil, - :uri => person.uri ? person.uri.content : nil, - :email => person.email ? person.email.content : nil, - } - end - assert_equal(persons, actual_persons) - end - end - - def assert_maker_atom_persons(feed_type, maker_readers, feed_readers, - not_set_error_name=nil, - parent_not_set_error_name=nil, - parent_not_set_variable=nil) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - args = [feed_type, maker_readers, feed_readers] - if parent_not_set_error_name or parent_not_set_variable - assert_not_set_error(parent_not_set_error_name, - parent_not_set_variable) do - _assert_maker_atom_persons(*args) do |maker| - yield maker - end - end - else - _assert_maker_atom_persons(*args) do |maker| - yield maker - end - end - - assert_not_set_error(not_set_error_name, %w(name)) do - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - targets.new_child - end - end - - assert_not_set_error(not_set_error_name, %w(name)) do - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.uri = "http://example.com/~me/" - end - end - - assert_not_set_error(not_set_error_name, %w(name)) do - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.email = "me@example.com" - end - end - - assert_not_set_error(not_set_error_name, %w(name)) do - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.uri = "http://example.com/~me/" - target.email = "me@example.com" - end - end - - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.name = "me" - end - - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.name = "me" - target.uri = "http://example.com/~me/" - end - - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.name = "me" - target.email = "me@example.com" - end - - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - target = targets.new_child - target.name = "me" - target.uri = "http://example.com/~me/" - target.email = "me@example.com" - end - - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - - target = targets.new_child - target.name = "me" - target.uri = "http://example.com/~me/" - target.email = "me@example.com" - - target = targets.new_child - target.name = "you" - target.uri = "http://example.com/~you/" - target.email = "you@example.com" - end - - assert_not_set_error(not_set_error_name, %w(name)) do - _assert_maker_atom_persons(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - - target = targets.new_child - target.name = "me" - target.uri = "http://example.com/~me/" - target.email = "me@example.com" - - targets.new_child - end - end - end - end - - def _assert_maker_atom_text_construct(feed_type, maker_readers, - feed_readers, &block) - maker_extractor = Proc.new do |target| - text = { - :type => target.type, - :content => target.content, - :xml_content => target.xml_content, - } - if text[:type] == "xhtml" - if text[:xml_content] - xml_content = text[:xml_content] - xhtml_uri = "http://www.w3.org/1999/xhtml" - unless xml_content.is_a?(RSS::XML::Element) and - ["div", xhtml_uri] == [xml_content.name, xml_content.uri] - children = xml_content - children = [children] unless children.is_a?(Array) - xml_content = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - children) - text[:xml_content] = xml_content - end - text - else - nil - end - else - text[:content] ? text : nil - end - end - feed_extractor = Proc.new do |target| - { - :type => target.type, - :content => target.content, - :xml_content => target.xhtml, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_text_construct(feed_type, maker_readers, feed_readers, - parent_not_set_error_name=nil, - parent_not_set_variable=nil, - not_set_error_name=nil) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - args = [feed_type, maker_readers, feed_readers] - if parent_not_set_error_name or parent_not_set_variable - assert_not_set_error(parent_not_set_error_name, - parent_not_set_variable) do - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - end - end - else - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - end - end - - assert_not_set_error(not_set_error_name, %w(content)) do - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "text" - end - end - - assert_not_set_error(not_set_error_name, %w(content)) do - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "html" - end - end - - assert_not_set_error(not_set_error_name, %w(xml_content)) do - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "xhtml" - end - end - - assert_not_set_error(not_set_error_name, %w(xml_content)) do - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "xhtml" - target.content = "Content" - end - end - - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "text" - target.content = "Content" - end - - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "html" - target.content = "Content" - end - - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "xhtml" - target.xml_content = "text only" - end - - _assert_maker_atom_text_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - target.type = "xhtml" - target.xml_content = RSS::XML::Element.new("unknown") - end - end - end - - def _assert_maker_atom_date_construct(feed_type, maker_readers, - feed_readers, &block) - maker_extractor = Proc.new do |target| - date = { - :content => target, - } - date[:content] ? date : nil - end - feed_extractor = Proc.new do |target| - { - :content => target.content, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, false, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_date_construct(feed_type, maker_readers, feed_readers, - parent_not_set_error_name=nil, - parent_not_set_variable=nil) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - if parent_not_set_error_name or parent_not_set_variable - assert_not_set_error(parent_not_set_error_name, - parent_not_set_variable) do - _assert_maker_atom_date_construct(*args) do |maker| - yield maker - end - end - else - _assert_maker_atom_date_construct(*args) do |maker| - yield maker - end - end - - maker_readers = maker_readers.dup - writer = "#{maker_readers.pop}=" - _assert_maker_atom_date_construct(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.__send__(writer, Time.now) - end - end - end - - def _assert_maker_atom_element(feed_type, - maker_readers, - maker_readers_need_block, - feed_readers, - maker_extractor, - feed_extractor) - _wrap_assertion do - element = nil - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - if maker_readers_need_block - target = chain_reader(maker, maker_readers) {|x| x} - else - target = chain_reader(maker, maker_readers) - end - element = maker_extractor.call(target) - end - - target = chain_reader(feed, feed_readers) - if target - actual_element = feed_extractor.call(target) - else - actual_element = nil - end - assert_equal(element, actual_element) - end - end - - def _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - maker_extractor, feed_extractor, - invalid_feed_checker=nil) - _wrap_assertion do - elements = [] - invalid_feed_exception = nil - feed = nil - begin - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - targets.each do |target| - element = maker_extractor.call(target) - elements << element if element - end - if invalid_feed_checker - invalid_feed_exception = invalid_feed_checker.call(targets) - end - end - rescue RSS::Error - if invalid_feed_exception.is_a?(RSS::TooMuchTagError) - assert_too_much_tag(invalid_feed_exception.tag, - invalid_feed_exception.parent) do - raise - end - else - raise - end - end - - if invalid_feed_exception.nil? - actual_elements = chain_reader(feed, feed_readers) || [] - actual_elements = actual_elements.collect do |target| - feed_extractor.call(target) - end - assert_equal(elements, actual_elements) - end - end - end - - def assert_maker_atom_element(feed_type, maker_readers, feed_readers, - setup_target, optional_variables, - required_variable, assert_method_name, - not_set_error_name=nil, - *additional_args) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - 0.upto(optional_variables.size) do |i| - combination(optional_variables, i).each do |names| - have = {} - names.each do |name| - have[name.intern] = true - end - have_required_variable_too = - have.merge({required_variable.intern => true}) - - assert_not_set_error(not_set_error_name, [required_variable]) do - __send__(assert_method_name, feed_type, maker_readers, - feed_readers, *additional_args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - setup_target.call(target, have) - end - end - - __send__(assert_method_name, feed_type, maker_readers, feed_readers, - *additional_args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) {|x| x} - setup_target.call(target, have_required_variable_too) - end - end - end - end - end - - def assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - setup_target, optional_variables, - required_variable, assert_method_name, - not_set_error_name=nil, - *additional_args) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - 0.upto(optional_variables.size) do |i| - combination(optional_variables, i).each do |names| - have = {} - names.each do |name| - have[name.intern] = true - end - have_required_variable_too = - have.merge({required_variable.intern => true}) - - assert_not_set_error(not_set_error_name, [required_variable]) do - __send__(assert_method_name, feed_type, maker_readers, - feed_readers, *additional_args) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - setup_target.call(targets, have) - end - end - - __send__(assert_method_name, feed_type, maker_readers, feed_readers, - *additional_args) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - setup_target.call(targets, have_required_variable_too) - end - - __send__(assert_method_name, feed_type, maker_readers, feed_readers, - *additional_args) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - setup_target.call(targets, have_required_variable_too) - setup_target.call(targets, have_required_variable_too) - end - - assert_not_set_error(not_set_error_name, [required_variable]) do - __send__(assert_method_name, feed_type, maker_readers, feed_readers, - *additional_args) do |maker| - yield maker - targets = chain_reader(maker, maker_readers) - setup_target.call(targets, have_required_variable_too) - setup_target.call(targets, have) - end - end - end - end - end - end - - def _assert_maker_atom_categories(feed_type, maker_readers, - feed_readers, &block) - maker_extractor = Proc.new do |target| - category = { - :term => target.term, - :scheme => target.scheme, - :label => target.label, - } - category[:term] ? category : nil - end - feed_extractor = Proc.new do |target| - { - :term => target.term, - :scheme => target.scheme, - :label => target.label, - } - end - _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - maker_extractor, feed_extractor, &block) - end - - def assert_maker_atom_categories(feed_type, maker_readers, feed_readers, - not_set_error_name=nil, &block) - _wrap_assertion do - _assert_maker_atom_categories(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - end - - setup_target = Proc.new do |targets, have| - target = targets.new_child - target.term = "music" if have[:term] - target.scheme = "http://example.com/category/music" if have[:scheme] - target.label = "Music" if have[:label] - end - - optional_variables = %w(scheme label) - - assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - setup_target, optional_variables, - "term", :_assert_maker_atom_categories, - not_set_error_name, &block) - end - end - - def _assert_maker_atom_generator(feed_type, maker_readers, - feed_readers, &block) - maker_extractor = Proc.new do |target| - generator = { - :uri => target.uri, - :version => target.version, - :content => target.content, - } - generator[:content] ? generator : nil - end - feed_extractor = Proc.new do |target| - { - :uri => target.uri, - :version => target.version, - :content => target.content, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_generator(feed_type, maker_readers, feed_readers, - not_set_error_name=nil, &block) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - _assert_maker_atom_generator(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - end - - setup_target = Proc.new do |target, have| - target.content = "RSS Maker" if have[:content] - target.uri = "http://example.com/rss/maker" if have[:uri] - target.version = "0.0.1" if have[:version] - end - - optional_variables = %w(uri version) - - assert_maker_atom_element(feed_type, maker_readers, feed_readers, - setup_target, optional_variables, - "content", :_assert_maker_atom_generator, - not_set_error_name, &block) - end - end - - def _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, - accessor_base, &block) - maker_extractor = Proc.new do |target| - icon = { - :content => target.__send__(accessor_base), - } - icon[:content] ? icon : nil - end - feed_extractor = Proc.new do |target| - { - :content => target.content, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_icon(feed_type, maker_readers, feed_readers, - accessor_base=nil, not_set_error_name=nil) - _wrap_assertion do - accessor_base ||= "url" - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, - accessor_base) do |maker| - yield maker - end - - _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, - accessor_base) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.__send__("#{accessor_base}=", "http://example.com/icon.png") - end - end - end - - def _assert_maker_atom_links(feed_type, maker_readers, feed_readers, - allow_duplication=false, &block) - maker_extractor = Proc.new do |target| - link = { - :href => target.href, - :rel => target.rel, - :type => target.type, - :hreflang => target.hreflang, - :title => target.title, - :length => target.length, - } - link[:href] ? link : nil - end - feed_extractor = Proc.new do |target| - { - :href => target.href, - :rel => target.rel, - :type => target.type, - :hreflang => target.hreflang, - :title => target.title, - :length => target.length, - } - end - - if feed_readers.first == "entries" - parent = "entry" - else - parent = feed_type - end - invalid_feed_checker = Proc.new do |targets| - infos = {} - invalid_exception = nil - targets.each do |target| - key = [target.hreflang, target.type] - if infos.has_key?(key) - invalid_exception = RSS::TooMuchTagError.new("link", parent) - break - end - infos[key] = true if target.rel.nil? or target.rel == "alternate" - end - invalid_exception - end - invalid_feed_checker = nil if allow_duplication - _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - maker_extractor, feed_extractor, - invalid_feed_checker, - &block) - end - - def assert_maker_atom_links(feed_type, maker_readers, feed_readers, - not_set_error_name=nil, allow_duplication=false, - &block) - _wrap_assertion do - _assert_maker_atom_links(feed_type, maker_readers, - feed_readers) do |maker| - yield maker - end - - langs = %(ja en fr zh po) - setup_target = Proc.new do |targets, have| - target = targets.new_child - lang = langs[targets.size % langs.size] - target.href = "http://example.com/index.html.#{lang}" if have[:href] - target.rel = "alternate" if have[:rel] - target.type = "text/xhtml" if have[:type] - target.hreflang = lang if have[:hreflang] - target.title = "FrontPage(#{lang})" if have[:title] - target.length = 1024 if have[:length] - end - - optional_variables = %w(rel type hreflang title length) - - assert_maker_atom_elements(feed_type, maker_readers, feed_readers, - setup_target, optional_variables, - "href", :_assert_maker_atom_links, - not_set_error_name, allow_duplication, - &block) - end - end - - def _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, - accessor_base, &block) - maker_extractor = Proc.new do |target| - logo = { - :uri => target.__send__(accessor_base), - } - logo[:uri] ? logo : nil - end - feed_extractor = Proc.new do |target| - { - :uri => target.content, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_logo(feed_type, maker_readers, feed_readers, - accessor_base=nil, not_set_error_name=nil) - _wrap_assertion do - accessor_base ||= "uri" - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, - accessor_base) do |maker| - yield maker - end - - _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, - accessor_base) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.__send__("#{accessor_base}=", "http://example.com/logo.png") - end - end - end - - def _assert_maker_atom_id(feed_type, maker_readers, feed_readers, &block) - maker_extractor = Proc.new do |target| - id = { - :uri => target.id, - } - id[:uri] ? id : nil - end - feed_extractor = Proc.new do |target| - if target.id - { - :uri => target.id.content, - } - else - nil - end - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_id(feed_type, maker_readers, feed_readers, - not_set_error_name=nil) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - - args = [feed_type, maker_readers, feed_readers] - _assert_maker_atom_id(*args) do |maker| - yield maker - end - - _assert_maker_atom_id(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.id = "http://example.com/id/1" - end - end - end - - def _assert_maker_atom_content(feed_type, maker_readers, - feed_readers, &block) - maker_extractor = Proc.new do |target| - content = { - :type => target.type, - :src => target.src, - :content => target.content, - :xml => target.xml, - :inline_text => target.inline_text?, - :inline_html => target.inline_html?, - :inline_xhtml => target.inline_xhtml?, - :inline_other => target.inline_other?, - :inline_other_text => target.inline_other_text?, - :inline_other_xml => target.inline_other_xml?, - :inline_other_base64 => target.inline_other_base64?, - :out_of_line => target.out_of_line?, - } - content[:src] = nil if content[:src] and content[:content] - if content[:type] or content[:content] - content - else - nil - end - end - feed_extractor = Proc.new do |target| - { - :type => target.type, - :src => target.src, - :content => target.content, - :xml => target.xml, - :inline_text => target.inline_text?, - :inline_html => target.inline_html?, - :inline_xhtml => target.inline_xhtml?, - :inline_other => target.inline_other?, - :inline_other_text => target.inline_other_text?, - :inline_other_xml => target.inline_other_xml?, - :inline_other_base64 => target.inline_other_base64?, - :out_of_line => target.out_of_line?, - } - end - _assert_maker_atom_element(feed_type, - maker_readers, true, - feed_readers, - maker_extractor, - feed_extractor, - &block) - end - - def assert_maker_atom_content(feed_type, maker_readers, feed_readers, - not_set_error_name=nil, &block) - _wrap_assertion do - not_set_error_name ||= "maker.#{maker_readers.join('.')}" - args = [feed_type, maker_readers, feed_readers, not_set_error_name] - assert_maker_atom_content_inline_text(*args, &block) - assert_maker_atom_content_inline_xhtml(*args, &block) - assert_maker_atom_content_inline_other(*args, &block) - assert_maker_atom_content_out_of_line(*args, &block) - end - end - - def assert_maker_atom_content_inline_text(feed_type, maker_readers, - feed_readers, not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - _assert_maker_atom_content(*args) do |maker| - yield maker - end - - assert_not_set_error(not_set_error_name, %w(content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "text" - end - end - - assert_not_set_error(not_set_error_name, %w(content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "html" - end - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.content = "" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "text" - target.content = "example content" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "html" - target.content = "text" - end - end - end - - def assert_maker_atom_content_inline_xhtml(feed_type, maker_readers, - feed_readers, not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - assert_not_set_error(not_set_error_name, %w(xml_content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - end - end - - assert_not_set_error(not_set_error_name, %w(xml_content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.content = "dummy" - end - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml_content = "text" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml = "text" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml_content = - RSS::XML::Element.new("em", nil, nil, {}, ["text"]) - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml = RSS::XML::Element.new("em", nil, nil, {}, ["text"]) - end - - - xhtml_uri = "http://www.w3.org/1999/xhtml" - em = RSS::XML::Element.new("em", nil, nil, {}, ["text"]) - em_with_xhtml_uri = - RSS::XML::Element.new("em", nil, xhtml_uri, {}, ["text"]) - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml = em - end - assert_equal(RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - [em_with_xhtml_uri]), - chain_reader(feed, feed_readers).xml) - - div = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri, - "class" => "sample"}, - ["text"]) - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "xhtml" - target.xml = div - end - assert_equal(div, chain_reader(feed, feed_readers).xml) - end - end - - def assert_maker_atom_content_inline_other(*args, &block) - _wrap_assertion do - assert_maker_atom_content_inline_other_xml(*args, &block) - assert_maker_atom_content_inline_other_text(*args, &block) - assert_maker_atom_content_inline_other_base64(*args, &block) - end - end - - def assert_maker_atom_content_inline_other_xml(feed_type, maker_readers, - feed_readers, - not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - assert_not_set_error(not_set_error_name, %w(xml_content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "application/xml" - end - end - - assert_not_set_error(not_set_error_name, %w(xml_content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "svg/image+xml" - end - end - - svg_uri = "http://www.w3.org/2000/svg" - rect = RSS::XML::Element.new("rect", nil, svg_uri, - {"x" => "0.5cm", - "y" => "0.5cm", - "width" => "2cm", - "height" => "1cm"}) - svg = RSS::XML::Element.new("svg", nil, svg_uri, - {"xmlns" => svg_uri, - "version" => "1.1", - "width" => "5cm", - "height" => "4cm"}, - [rect]) - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/svg+xml" - target.xml = svg - end - - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/svg+xml" - target.xml = svg - end - assert_equal(svg, chain_reader(feed, feed_readers).xml) - end - end - - def assert_maker_atom_content_inline_other_text(feed_type, maker_readers, - feed_readers, - not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - assert_not_set_error(not_set_error_name, %w(content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "text/plain" - end - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "text/plain" - target.content = "text" - end - end - end - - def assert_maker_atom_content_inline_other_base64(feed_type, maker_readers, - feed_readers, - not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - content = "\211PNG\r\n\032\n" - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - target.content = content - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - target.src = "http://example.com/logo.png" - target.content = content - end - - feed = RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - target.src = "http://example.com/logo.png" - target.content = content - end - target = chain_reader(feed, feed_readers) - assert_nil(target.src) - assert_equal(content, target.content) - end - end - - def assert_maker_atom_content_out_of_line(feed_type, maker_readers, - feed_readers, not_set_error_name) - _wrap_assertion do - args = [feed_type, maker_readers, feed_readers] - assert_not_set_error(not_set_error_name, %w(content)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - end - end - - assert_not_set_error(not_set_error_name, %w(type)) do - RSS::Maker.make("atom:#{feed_type}") do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.src = "http://example.com/logo.png" - end - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - target.src = "http://example.com/logo.png" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "image/png" - target.content = "\211PNG\r\n\032\n" - end - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "application/xml" - target.src = "http://example.com/sample.xml" - end - - - _assert_maker_atom_content(*args) do |maker| - yield maker - target = chain_reader(maker, maker_readers) - target.type = "text/plain" - target.src = "http://example.com/README.txt" - end - end - end - - def assert_slash_elements(expected, target) - assert_equal(expected, - { - "section" => target.slash_section, - "department" => target.slash_department, - "comments" => target.slash_comments, - "hit_parades" => target.slash_hit_parades, - }) - assert_equal(expected["hit_parades"].join(","), - target.slash_hit_parade) - end - - def chain_reader(target, readers, &block) - readers.inject(target) do |result, reader| - return nil if result.nil? - result.__send__(reader, &block) - end - end - - def normalized_attrs(attrs) - n_attrs = {} - attrs.each do |name, value| - n_attrs[name.to_s] = value - end - n_attrs - end - - def combination(elements, n) - if n <= 0 or elements.size < n - [] - elsif n == 1 - elements.collect {|element| [element]} - else - first, *rest = elements - combination(rest, n - 1).collect do |sub_elements| - [first, *sub_elements] - end + combination(rest, n) - end - end - - def tag(name, content=nil, attributes={}) - attributes = attributes.collect do |key, value| - "#{ERB::Util.h(key)}=\"#{ERB::Util.h(value)}\"" - end.join(" ") - begin_tag = "<#{name}" - begin_tag << " #{attributes}" unless attributes.empty? - if content - "#{begin_tag}>#{content}\n" - else - "#{begin_tag}/>\n" - end - end - end -end diff --git a/ruby/test/rss/rss-testcase.rb b/ruby/test/rss/rss-testcase.rb deleted file mode 100644 index 30067d43b..000000000 --- a/ruby/test/rss/rss-testcase.rb +++ /dev/null @@ -1,479 +0,0 @@ -# frozen_string_literal: false -require "erb" - -require "test/unit" -require_relative 'rss-assertions' - -require "rss" - -module RSS - class TestCase < Test::Unit::TestCase - include ERB::Util - - include RSS - include Assertions - - XMLDECL_VERSION = "1.0" - XMLDECL_ENCODING = "UTF-8" - XMLDECL_STANDALONE = "no" - - RDF_ABOUT = "http://www.xml.com/xml/news.rss" - RDF_RESOURCE = "http://xml.com/universal/images/xml_tiny.gif" - TITLE_VALUE = "XML.com" - LINK_VALUE = "http://xml.com/pub" - URL_VALUE = "http://xml.com/universal/images/xml_tiny.gif" - NAME_VALUE = "hogehoge" - LANGUAGE_VALUE = "ja" - DESCRIPTION_VALUE = " - XML.com features a rich mix of information and services - for the XML community. - " - RESOURCES = [ - "http://xml.com/pub/2000/08/09/xslt/xslt.html", - "http://xml.com/pub/2000/08/09/rdfdb/index.html", - ] - - CLOUD_DOMAIN = "data.ourfavoritesongs.com" - CLOUD_PORT = "80" - CLOUD_PATH = "/RPC2" - CLOUD_REGISTER_PROCEDURE = "ourFavoriteSongs.rssPleaseNotify" - CLOUD_PROTOCOL = "xml-rpc" - - ENCLOSURE_URL = "http://www.scripting.com/mp3s/weatherReportSuite.mp3" - ENCLOSURE_LENGTH = "12216320" - ENCLOSURE_TYPE = "audio/mpeg" - - CATEGORY_DOMAIN = "http://www.superopendirectory.com/" - - FEED_TITLE = "dive into mark" - FEED_UPDATED = "2003-12-13T18:30:02Z" - FEED_AUTHOR_NAME = "John Doe" - FEED_ID = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6" - - ENTRY_TITLE = "Atom-Powered Robots Run Amok" - ENTRY_LINK = "http://example.org/2003/12/13/atom03" - ENTRY_ID = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a" - ENTRY_UPDATED = "2003-12-13T18:30:02Z" - ENTRY_SUMMARY = "Some text." - - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - DC_ELEMENTS = { - :title => "hoge", - :description => - " XML is placing increasingly heavy loads on - the existing technical infrastructure of the Internet.", - :creator => "Rael Dornfest (mailto:rael@oreilly.com)", - :subject => "XML", - :publisher => "The O'Reilly Network", - :contributor => "hogehoge", - :type => "fugafuga", - :format => "hohoho", - :identifier => "fufufu", - :source => "barbar", - :language => "ja", - :relation => "cococo", - :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", - :date => t, - } - - DC_NODES = DC_ELEMENTS.collect do |name, value| - "<#{DC_PREFIX}:#{name}>#{value}" - end.join("\n") - - def default_test - # This class isn't tested - end - - private - def make_xmldecl(v=XMLDECL_VERSION, e=XMLDECL_ENCODING, s=XMLDECL_STANDALONE) - rv = "" - rv - end - - def make_RDF(content=nil, xmlns=[]) - <<-EORSS -#{make_xmldecl} - -#{block_given? ? yield : content} - -EORSS - end - - def make_channel(content=nil) - <<-EOC - - #{TITLE_VALUE} - #{LINK_VALUE} - #{DESCRIPTION_VALUE} - - - - - -#{RESOURCES.collect do |res| '' end.join("\n")} - - - - - -#{block_given? ? yield : content} - -EOC - end - - def make_image(content=nil) - <<-EOI - - #{TITLE_VALUE} - #{URL_VALUE} - #{LINK_VALUE} -#{block_given? ? yield : content} - -EOI - end - - def make_item(content=nil) - <<-EOI - - #{TITLE_VALUE} - #{LINK_VALUE} - #{DESCRIPTION_VALUE} -#{block_given? ? yield : content} - -EOI - end - - def make_textinput(content=nil) - <<-EOT - - #{TITLE_VALUE} - #{DESCRIPTION_VALUE} - #{NAME_VALUE} - #{LINK_VALUE} -#{block_given? ? yield : content} - -EOT - end - - def make_sample_RDF - make_RDF(<<-EOR) -#{make_channel} -#{make_image} -#{make_item} -#{make_textinput} -EOR - end - - def make_rss20(content=nil, xmlns=[]) - <<-EORSS -#{make_xmldecl} - -#{block_given? ? yield : content} - -EORSS - end - - def make_sample_items20 - RESOURCES.collect do |res| - elems = ["#{res}"] - elems << "title of #{res}" - elems = elems.join("\n") - "\n#{elems}\n" - end.join("\n") - end - - def make_channel20(content=nil) - <<-EOC - - #{TITLE_VALUE} - #{LINK_VALUE} - #{DESCRIPTION_VALUE} - #{LANGUAGE_VALUE} - - - #{RDF_RESOURCE} - #{TITLE_VALUE} - #{LINK_VALUE} - - -#{make_sample_items20} - - - #{TITLE_VALUE} - #{DESCRIPTION_VALUE} - #{NAME_VALUE} - #{RDF_RESOURCE} - - -#{block_given? ? yield : content} - -EOC - end - - def make_item20(content=nil) - <<-EOI - - #{TITLE_VALUE} - #{LINK_VALUE} - #{DESCRIPTION_VALUE} -#{block_given? ? yield : content} - -EOI - end - - def make_cloud20 - <<-EOC - -EOC - end - - def make_sample_rss20 - make_rss20(<<-EOR) -#{make_channel20} -EOR - end - - def make_feed_without_entry(content=nil, xmlns=[]) - <<-EOA - - #{FEED_ID} - #{FEED_TITLE} - #{FEED_UPDATED} - - #{FEED_AUTHOR_NAME} - -#{block_given? ? yield : content} - -EOA - end - - def make_entry(content=nil) - <<-EOA - - #{ENTRY_TITLE} - #{ENTRY_ID} - #{ENTRY_UPDATED} -#{block_given? ? yield : content} - -EOA - end - - def make_feed_with_open_entry(content=nil, xmlns=[], &block) - make_feed_without_entry(<<-EOA, xmlns) -#{make_entry(content, &block)} -EOA - end - - def make_feed_with_open_entry_source(content=nil, xmlns=[]) - make_feed_with_open_entry(<<-EOA, xmlns) - -#{block_given? ? yield : content} - -EOA - end - - def make_feed(content=nil, xmlns=[]) - make_feed_without_entry(<<-EOA, xmlns) - - #{ENTRY_TITLE} - - #{ENTRY_ID} - #{ENTRY_UPDATED} - #{ENTRY_SUMMARY} - -#{block_given? ? yield : content} -EOA - end - - def make_entry_document(content=nil, xmlns=[]) - <<-EOA - - #{ENTRY_ID} - #{ENTRY_TITLE} - #{ENTRY_UPDATED} - - #{FEED_AUTHOR_NAME} - -#{block_given? ? yield : content} - -EOA - end - - def make_entry_document_with_open_source(content=nil, xmlns=[]) - make_entry_document(<<-EOA, xmlns) - -#{block_given? ? yield : content} - -EOA - end - - def make_element(elem_name, attrs, contents) - attrs_str = attrs.collect do |name, value| - "#{h name}='#{h value}'" - end.join(" ") - attrs_str = " #{attrs_str}" unless attrs_str.empty? - - if contents.is_a?(String) - contents_str = h(contents) - else - contents_str = contents.collect do |name, value| - "#{Element::INDENT}<#{h name}>#{h value}" - end.join("\n") - contents_str = "\n#{contents_str}\n" - end - - "<#{h elem_name}#{attrs_str}>#{contents_str}" - end - - def xmlns_container(xmlns_decls, content) - attributes = xmlns_decls.collect do |prefix, uri| - "xmlns:#{h prefix}=\"#{h uri}\"" - end.join(" ") - "#{content}" - end - - private - def setup_rss10(rdf) - assert_equal("", rdf.to_s) - - channel = RDF::Channel.new - assert_equal("", channel.to_s) - channel.about = "http://example.com/index.rdf" - channel.title = "title" - channel.link = "http://example.com/" - channel.description = "description" - assert_equal("", channel.to_s) - - item_title = "item title" - item_link = "http://example.com/item" - channel.items = RDF::Channel::Items.new - channel.items.Seq.lis << RDF::Channel::Items::Seq::Li.new(item_link) - assert_not_equal("", channel.to_s) - - rdf.channel = channel - assert_equal("", rdf.to_s) - - item = RDF::Item.new - item.title = item_title - item.link = item_link - item.about = item_link - rdf.items << item - assert_not_equal("", rdf.to_s) - end - - def setup_rss20(rss) - assert_equal("", rss.to_s) - - channel = Rss::Channel.new - assert_equal("", channel.to_s) - channel.title = "title" - channel.link = "http://example.com/" - channel.description = "description" - assert_not_equal("", channel.to_s) - - rss.channel = channel - assert_not_equal("", rss.to_s) - end - - def setup_dummy_channel(maker) - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com/feed.xml" - description = "fugafugafugafuga" - language = "ja" - - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - end - - def setup_dummy_channel_atom(maker) - updated = Time.now - author = "Foo" - - setup_dummy_channel(maker) - maker.channel.links.first.rel = "self" - maker.channel.links.first.type = "application/atom+xml" - maker.channel.updated = updated - maker.channel.author = author - end - - def setup_dummy_image(maker) - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - - maker.channel.link = link if maker.channel.link.nil? - - maker.image.title = title - maker.image.url = url - end - - def setup_dummy_textinput(maker) - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com/search.cgi" - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - - def setup_dummy_item(maker) - title = "TITLE" - link = "http://hoge.com/" - - item = maker.items.new_item - item.title = title - item.link = link - end - - def setup_dummy_item_atom(maker) - setup_dummy_item(maker) - - item = maker.items.first - item.id = "http://example.net/xxx" - item.updated = Time.now - end - - def setup_taxo_topic(target, topics) - topics.each do |topic| - taxo_topic = target.taxo_topics.new_taxo_topic - topic.each do |name, value| - case name - when :link - taxo_topic.taxo_link = value - when :topics - value.each do |t| - taxo_topic.taxo_topics << t - end - else - dc_elems = taxo_topic.__send__("dc_#{name}s") - dc_elem = dc_elems.__send__("new_#{name}") - dc_elem.value = value - end - end - end - end - end -end diff --git a/ruby/test/rss/test_1.0.rb b/ruby/test/rss/test_1.0.rb deleted file mode 100644 index 33ae29141..000000000 --- a/ruby/test/rss/test_1.0.rb +++ /dev/null @@ -1,308 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" - -module RSS - class TestRSS10Core < TestCase - - def setup - @rdf_prefix = "rdf" - @rdf_uri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" - @uri = "http://purl.org/rss/1.0/" - end - - def test_RDF - version = "1.0" - encoding = "UTF-8" - standalone = false - - rdf = RDF.new(version, encoding, standalone) - setup_rss10(rdf) - doc = REXML::Document.new(rdf.to_s) - - xmldecl = doc.xml_decl - - assert_equal(version, xmldecl.version) - assert_equal(encoding, xmldecl.encoding.to_s) - assert_equal(standalone, !xmldecl.standalone.nil?) - - assert_equal(@rdf_uri, doc.root.namespace) - end - - def test_not_displayed_xml_stylesheets - rdf = RDF.new() - plain_rdf = rdf.to_s - 3.times do - rdf.xml_stylesheets.push(XMLStyleSheet.new) - assert_equal(plain_rdf, rdf.to_s) - end - end - - def test_xml_stylesheets - [ - [{:href => "a.xsl", :type => "text/xsl"}], - [ - {:href => "a.xsl", :type => "text/xsl"}, - {:href => "a.css", :type => "text/css"}, - ], - ].each do |attrs_ary| - assert_xml_stylesheet_pis(attrs_ary) - end - end - - def test_channel - about = "http://hoge.com" - resource = "http://hoge.com/hoge.png" - - item_title = "item title" - item_link = "http://hoge.com/item" - - image = RDF::Channel::Image.new(resource) - items = RDF::Channel::Items.new - items.Seq.lis << items.class::Seq::Li.new(item_link) - textinput = RDF::Channel::Textinput.new(resource) - - rss_item = RDF::Item.new - rss_item.title = item_title - rss_item.link = item_link - rss_item.about = item_link - - h = { - 'title' => "fugafuga", - 'link' => "http://hoge.com", - 'description' => "fugafugafugafuga", - 'image' => image, - 'items' => items, - 'textinput' => textinput, - } - - channel = RDF::Channel.new(about) - %w(title link description image items textinput).each do |x| - channel.__send__("#{x}=", h[x]) - end - - doc = REXML::Document.new(make_RDF(<<-EOR)) -#{channel} - -#{rss_item} - -EOR - c = doc.root.elements[1] - - assert_equal(about, c.attributes["about"]) - %w(title link description image textinput).each do |x| - elem = c.elements[x] - assert_equal(x, elem.name) - assert_equal(@uri, elem.namespace) - if x == "image" or x == "textinput" - excepted = resource - res = elem.attributes.get_attribute("resource") - assert_equal(@rdf_uri, res.namespace) - value = res.value - else - excepted = h[x] - value = elem.text - end - assert_equal(excepted, value) - end - assert_equal(@uri, c.elements["items"].namespace) - assert_equal("items", c.elements["items"].name) - end - - def test_channel_image - resource = "http://hoge.com/hoge.png" - image = RDF::Channel::Image.new(resource) - - doc = REXML::Document.new(make_RDF(image.to_s)) - i = doc.root.elements[1] - - assert_equal("image", i.name) - assert_equal(@uri, i.namespace) - - res = i.attributes.get_attribute("resource") - - assert_equal(@rdf_uri, res.namespace) - assert_equal(resource, res.value) - end - - def test_channel_textinput - resource = "http://hoge.com/hoge.png" - textinput = RDF::Channel::Textinput.new(resource) - - doc = REXML::Document.new(make_RDF(textinput.to_s)) - t = doc.root.elements[1] - - assert_equal("textinput", t.name) - assert_equal(@uri, t.namespace) - - res = t.attributes.get_attribute("resource") - - assert_equal(@rdf_uri, res.namespace) - assert_equal(resource, res.value) - end - - def test_channel_items - item_link = "http://example.com/item" - - items = RDF::Channel::Items.new - li = items.Seq.class::Li.new(item_link) - items.Seq.lis << li - - doc = REXML::Document.new(make_RDF(items.to_s)) - i = doc.root.elements[1] - - assert_equal("items", i.name) - assert_equal(@uri, i.namespace) - - assert_equal(1, i.elements.size) - seq = i.elements[1] - assert_equal("Seq", seq.name) - assert_equal(@rdf_uri, seq.namespace) - - assert_equal(1, seq.elements.size) - l = seq.elements[1] - assert_equal("li", l.name) - assert_equal(@rdf_uri, l.namespace) - assert_equal(item_link, l.attributes["resource"]) - end - - def test_seq - item_link = "http://example.com/item" - seq = RDF::Seq.new - li = seq.class::Li.new(item_link) - seq.lis << li - - doc = REXML::Document.new(make_RDF(seq.to_s)) - s = doc.root.elements[1] - - assert_equal("Seq", s.name) - assert_equal(@rdf_uri, s.namespace) - - assert_equal(1, s.elements.size) - l = s.elements[1] - assert_equal("li", l.name) - assert_equal(@rdf_uri, l.namespace) - assert_equal(item_link, l.attributes["resource"]) - end - - def test_li - resource = "http://hoge.com/" - li = RDF::Li.new(resource) - - doc = REXML::Document.new(make_RDF(li.to_s)) - l = doc.root.elements[1] - - assert_equal("li", l.name) - assert_equal(@rdf_uri, l.namespace(l.prefix)) - - res = l.attributes.get_attribute("resource") - - assert_equal('', res.instance_eval("@prefix")) - assert_equal(resource, res.value) - end - - def test_image - about = "http://hoge.com" - h = { - 'title' => "fugafuga", - 'url' => "http://hoge.com/hoge", - 'link' => "http://hoge.com/fuga", - } - - image = RDF::Image.new(about) - %w(title url link).each do |x| - image.__send__("#{x}=", h[x]) - end - - doc = REXML::Document.new(make_RDF(image.to_s)) - i = doc.root.elements[1] - - assert_equal(about, i.attributes["about"]) - %w(title url link).each do |x| - elem = i.elements[x] - assert_equal(x, elem.name) - assert_equal(@uri, elem.namespace) - assert_equal(h[x], elem.text) - end - end - - def test_item - about = "http://hoge.com" - h = { - 'title' => "fugafuga", - 'link' => "http://hoge.com/fuga", - 'description' => "hogehogehoge", - } - - item = RDF::Item.new(about) - %w(title link description).each do |x| - item.__send__("#{x}=", h[x]) - end - - doc = REXML::Document.new(make_RDF(item.to_s)) - i = doc.root.elements[1] - - assert_equal(about, i.attributes["about"]) - %w(title link description).each do |x| - elem = i.elements[x] - assert_equal(x, elem.name) - assert_equal(@uri, elem.namespace) - assert_equal(h[x], elem.text) - end - end - - def test_textinput - about = "http://hoge.com" - h = { - 'title' => "fugafuga", - 'link' => "http://hoge.com/fuga", - 'name' => "foo", - 'description' => "hogehogehoge", - } - - textinput = RDF::Textinput.new(about) - %w(title link name description).each do |x| - textinput.__send__("#{x}=", h[x]) - end - - doc = REXML::Document.new(make_RDF(textinput.to_s)) - t = doc.root.elements[1] - - assert_equal(about, t.attributes["about"]) - %w(title link name description).each do |x| - elem = t.elements[x] - assert_equal(x, elem.name) - assert_equal(@uri, elem.namespace) - assert_equal(h[x], elem.text) - end - end - - def test_to_xml - rss = RSS::Parser.parse(make_sample_RDF) - assert_equal(rss.to_s, rss.to_xml) - assert_equal(rss.to_s, rss.to_xml("1.0")) - rss09 = rss.to_xml("0.91") do |maker| - maker.channel.language = "en-us" - end - rss09 = RSS::Parser.parse(rss09) - assert_equal("0.91", rss09.rss_version) - assert_equal(["rss", "0.91", nil], rss09.feed_info) - rss20 = RSS::Parser.parse(rss.to_xml("2.0")) - assert_equal("2.0", rss20.rss_version) - assert_equal(["rss", "2.0", nil], rss20.feed_info) - - atom_xml = rss.to_xml("atom") do |maker| - maker.channel.author = "Alice" - maker.channel.updated ||= Time.now - maker.items.each do |item| - item.updated ||= Time.now - end - end - atom = RSS::Parser.parse(atom_xml) - assert_equal(["atom", "1.0", "feed"], atom.feed_info) - end - end -end diff --git a/ruby/test/rss/test_2.0.rb b/ruby/test/rss/test_2.0.rb deleted file mode 100644 index 650f83501..000000000 --- a/ruby/test/rss/test_2.0.rb +++ /dev/null @@ -1,412 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" - -require_relative "rss-testcase" - -module RSS - class TestRSS20Core < TestCase - - def setup - @rss_version = "2.0" - end - - def test_Rss - version = "1.0" - encoding = "UTF-8" - standalone = false - - rss = Rss.new(@rss_version, version, encoding, standalone) - setup_rss20(rss) - - doc = REXML::Document.new(rss.to_s(false)) - - xmldecl = doc.xml_decl - - assert_equal(version, xmldecl.version) - assert_equal(encoding, xmldecl.encoding.to_s) - assert_equal(standalone, !xmldecl.standalone.nil?) - - assert_equal("", doc.root.namespace) - assert_equal(@rss_version, doc.root.attributes["version"]) - end - - def test_not_displayed_xml_stylesheets - rss = Rss.new(@rss_version) - plain_rss = rss.to_s - 3.times do - rss.xml_stylesheets.push(XMLStyleSheet.new) - assert_equal(plain_rss, rss.to_s) - end - end - - def test_xml_stylesheets - [ - [{:href => "a.xsl", :type => "text/xsl"}], - [ - {:href => "a.xsl", :type => "text/xsl"}, - {:href => "a.css", :type => "text/css"}, - ], - ].each do |attrs_ary| - rss = Rss.new(@rss_version) - setup_rss20(rss) - assert_xml_stylesheet_pis(attrs_ary, rss) - end - end - - def test_channel - h = { - 'title' => "fugafuga", - 'link' => "http://hoge.com", - 'description' => "fugafugafugafuga", - - 'language' => "en-us", - 'copyright' => "Copyright 2002, Spartanburg Herald-Journal", - 'managingEditor' => "geo@herald.com (George Matesky)", - 'webMaster' => "betty@herald.com (Betty Guernsey)", - 'pubDate' => Time.parse("Sat, 07 Sep 2002 00:00:01 GMT"), - 'lastBuildDate' => Time.parse("Sat, 07 Sep 2002 09:42:31 GMT"), - 'generator' => "MightyInHouse Content System v2.3", - 'docs' => "http://blogs.law.harvard.edu/tech/rss", - 'ttl' => "60", - 'rating' => '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))', - } - categories = [ - { - :content => "Newspapers", - }, - { - :domain => "Syndic8", - :content => "1765", - } - ] - - channel = Rss::Channel.new - - elems = %w(title link description language copyright - managingEditor webMaster pubDate lastBuildDate - generator docs ttl rating) - elems.each do |x| - value = h[x] - value = value.rfc822 if %w(pubDate lastBuildDate).include?(x) - channel.__send__("#{x}=", value) - end - categories.each do |cat| - channel.categories << Rss::Channel::Category.new(cat[:domain], - cat[:content]) - end - - doc = REXML::Document.new(make_rss20(channel.to_s)) - c = doc.root.elements[1] - - elems.each do |x| - elem = c.elements[x] - assert_equal(x, elem.name) - assert_equal("", elem.namespace) - expected = h[x] - case x - when "pubDate", "lastBuildDate" - assert_equal(expected, Time.parse(elem.text)) - when "ttl" - expected = channel.__send__(x) - assert_equal(expected, elem.text.to_i) - else - assert_equal(expected, elem.text) - end - end - categories.each_with_index do |cat, i| - cat = cat.dup - cat[:domain] ||= nil - category = c.elements["category[#{i+1}]"] - actual = { - :domain => category.attributes["domain"], - :content => category.text, - } - assert_equal(cat, actual) - end - end - - def test_channel_cloud - cloud_params = { - :domain => "rpc.sys.com", - :port => "80", - :path => "/RPC2", - :registerProcedure => "myCloud.rssPleaseNotify", - :protocol => "xml-rpc", - } - cloud = Rss::Channel::Cloud.new(cloud_params[:domain], - cloud_params[:port], - cloud_params[:path], - cloud_params[:registerProcedure], - cloud_params[:protocol]) - cloud_params[:port] = cloud.port - - doc = REXML::Document.new(cloud.to_s) - cloud_elem = doc.root - - actual = {} - cloud_elem.attributes.each do |name, value| - value = value.to_i if name == "port" - actual[name.intern] = value - end - assert_equal(cloud_params, actual) - end - - def test_channel_image - image_params = { - :url => "http://hoge.com/hoge.png", - :title => "fugafuga", - :link => "http://hoge.com", - :width => "144", - :height => "400", - :description => "an image", - } - image = Rss::Channel::Image.new(image_params[:url], - image_params[:title], - image_params[:link], - image_params[:width], - image_params[:height], - image_params[:description]) - - doc = REXML::Document.new(image.to_s) - image_elem = doc.root - - image_params.each do |name, value| - value = image.__send__(name) - actual = image_elem.elements[name.to_s].text - actual = actual.to_i if [:width, :height].include?(name) - assert_equal(value, actual) - end - end - - def test_channel_textInput - textInput_params = { - :title => "fugafuga", - :description => "text hoge fuga", - :name => "hoge", - :link => "http://hoge.com", - } - textInput = Rss::Channel::TextInput.new(textInput_params[:title], - textInput_params[:description], - textInput_params[:name], - textInput_params[:link]) - - doc = REXML::Document.new(textInput.to_s) - input_elem = doc.root - - textInput_params.each do |name, value| - actual = input_elem.elements[name.to_s].text - assert_equal(value, actual) - end - end - - def test_channel_skip_days - skipDays_values = [ - "Sunday", - "Monday", - ] - skipDays = Rss::Channel::SkipDays.new - skipDays_values.each do |value| - skipDays.days << Rss::Channel::SkipDays::Day.new(value) - end - - doc = REXML::Document.new(skipDays.to_s) - days_elem = doc.root - - skipDays_values.each_with_index do |value, i| - assert_equal(value, days_elem.elements[i + 1].text) - end - end - - def test_channel_skip_hours - skipHours_values = [ - "0", - "13", - ] - skipHours = Rss::Channel::SkipHours.new - skipHours_values.each do |value| - skipHours.hours << Rss::Channel::SkipHours::Hour.new(value) - end - - doc = REXML::Document.new(skipHours.to_s) - hours_elem = doc.root - - skipHours_values.each_with_index do |value, i| - expected = skipHours.hours[i].content - assert_equal(expected, hours_elem.elements[i + 1].text.to_i) - end - end - - def test_item - h = { - 'title' => "fugafuga", - 'link' => "http://hoge.com/", - 'description' => "text hoge fuga", - 'author' => "oprah@oxygen.net", - 'comments' => "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290", - 'pubDate' => Time.parse("Sat, 07 Sep 2002 00:00:01 GMT"), - } - categories = [ - { - :content => "Newspapers", - }, - { - :domain => "Syndic8", - :content => "1765", - } - ] - - channel = Rss::Channel.new - channel.title = "title" - channel.link = "http://example.com/" - channel.description = "description" - - item = Rss::Channel::Item.new - channel.items << item - - elems = %w(title link description author comments pubDate) - elems.each do |x| - value = h[x] - value = value.rfc822 if x == "pubDate" - item.__send__("#{x}=", value) - end - categories.each do |cat| - item.categories << Rss::Channel::Category.new(cat[:domain], - cat[:content]) - end - - doc = REXML::Document.new(channel.to_s) - channel_elem = doc.root - - item_elem = channel_elem.elements["item[1]"] - elems.each do |x| - elem = item_elem.elements[x] - assert_equal(x, elem.name) - assert_equal("", elem.namespace) - expected = h[x] - case x - when "pubDate" - assert_equal(expected, Time.parse(elem.text)) - else - assert_equal(expected, elem.text) - end - end - categories.each_with_index do |cat, i| - cat = cat.dup - cat[:domain] ||= nil - category = item_elem.elements["category[#{i+1}]"] - actual = { - :domain => category.attributes["domain"], - :content => category.text, - } - assert_equal(cat, actual) - end - end - - def test_item_enclosure - enclosure_params = { - :url => "http://www.scripting.com/mp3s/weatherReportSuite.mp3", - :length => "12216320", - :type => "audio/mpeg", - } - - enclosure = Rss::Channel::Item::Enclosure.new(enclosure_params[:url], - enclosure_params[:length], - enclosure_params[:type]) - enclosure_params[:length] = enclosure.length - - doc = REXML::Document.new(enclosure.to_s) - enclosure_elem = doc.root - - actual = {} - enclosure_elem.attributes.each do |name, value| - value = value.to_i if name == "length" - actual[name.intern] = value - end - assert_equal(enclosure_params, actual) - end - - def test_item_guid - test_params = [ - { - :content => "http://some.server.com/weblogItem3207", - }, - { - :isPermaLink => "true", - :content => "http://inessential.com/2002/09/01.php#a2", - }, - ] - - test_params.each do |guid_params| - guid = Rss::Channel::Item::Guid.new(guid_params[:isPermaLink], - guid_params[:content]) - if guid_params.has_key?(:isPermaLink) - guid_params[:isPermaLink] = guid.isPermaLink - end - if guid.isPermaLink.nil? - assert_equal(true, guid.PermaLink?) - else - assert_equal(guid.isPermaLink, guid.PermaLink?) - end - - doc = REXML::Document.new(guid.to_s) - guid_elem = doc.root - - actual = {} - actual[:content] = guid_elem.text if guid_elem.text - guid_elem.attributes.each do |name, value| - value = value == "true" if name == "isPermaLink" - actual[name.intern] = value - end - assert_equal(guid_params, actual) - end - end - - def test_item_source - source_params = { - :url => "http://www.tomalak.org/links2.xml", - :content => "Tomalak's Realm", - } - - source = Rss::Channel::Item::Source.new(source_params[:url], - source_params[:content]) - - doc = REXML::Document.new(source.to_s) - source_elem = doc.root - - actual = {} - actual[:content] = source_elem.text - source_elem.attributes.each do |name, value| - actual[name.intern] = value - end - assert_equal(source_params, actual) - end - - def test_to_xml - rss = RSS::Parser.parse(make_sample_rss20) - assert_equal(rss.to_s, rss.to_xml) - assert_equal(rss.to_s, rss.to_xml("2.0")) - rss09_xml = rss.to_xml("0.91") do |maker| - setup_dummy_image(maker) - end - rss09 = RSS::Parser.parse(rss09_xml) - assert_equal("0.91", rss09.rss_version) - rss10 = rss.to_xml("1.0") do |maker| - maker.channel.about = "http://www.example.com/index.rdf" - end - rss10 = RSS::Parser.parse(rss10) - assert_equal("1.0", rss10.rss_version) - - atom_xml = rss.to_xml("atom1.0") do |maker| - maker.channel.id = "http://www.example.com/atom.xml" - maker.channel.author = "Alice" - maker.channel.updated = Time.now - maker.items.each do |item| - item.author = "Bob" - item.updated = Time.now - end - end - atom = RSS::Parser.parse(atom_xml) - assert_equal(["atom", "1.0", "feed"], atom.feed_info) - end - end -end diff --git a/ruby/test/rss/test_accessor.rb b/ruby/test/rss/test_accessor.rb deleted file mode 100644 index 7d4424dbb..000000000 --- a/ruby/test/rss/test_accessor.rb +++ /dev/null @@ -1,104 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/2.0" -require "rss/syndication" -require "rss/image" - -module RSS - class TestAccessor < TestCase - def test_date - channel = Rss::Channel.new - channel.pubDate = nil - assert_nil(channel.pubDate) - - time = Time.now - channel.pubDate = time - assert_equal(time, channel.pubDate) - - time = Time.parse(Time.now.rfc822) - channel.pubDate = time.rfc822 - assert_equal(time, channel.pubDate) - - time = Time.parse(Time.now.iso8601) - value = time.iso8601 - assert_not_available_value("pubDate", value) do - channel.pubDate = value - end - - channel.do_validate = false - time = Time.parse(Time.now.iso8601) - value = time.iso8601 - channel.pubDate = value - assert_equal(time, channel.pubDate) - - channel.pubDate = nil - assert_nil(channel.pubDate) - end - - def test_integer - image_item = RDF::Item::ImageItem.new - - image_item.width = nil - assert_nil(image_item.width) - - width = 10 - image_item.width = width - assert_equal(width, image_item.width) - - width = 10.0 - image_item.width = width - assert_equal(width, image_item.width) - - width = "10" - image_item.width = width - assert_equal(width.to_i, image_item.width) - - width = "10.0" - assert_not_available_value("image:width", width) do - image_item.width = width - end - - image_item.do_validate = false - width = "10.0" - image_item.width = width - assert_equal(width.to_i, image_item.width) - - image_item.width = nil - assert_nil(image_item.width) - end - - def test_positive_integer - channel = RDF::Channel.new - - channel.sy_updateFrequency = nil - assert_nil(channel.sy_updateFrequency) - - freq = 10 - channel.sy_updateFrequency = freq - assert_equal(freq, channel.sy_updateFrequency) - - freq = 10.0 - channel.sy_updateFrequency = freq - assert_equal(freq, channel.sy_updateFrequency) - - freq = "10" - channel.sy_updateFrequency = freq - assert_equal(freq.to_i, channel.sy_updateFrequency) - - freq = "10.0" - assert_not_available_value("sy:updateFrequency", freq) do - channel.sy_updateFrequency = freq - end - - channel.do_validate = false - freq = "10.0" - channel.sy_updateFrequency = freq - assert_equal(freq.to_i, channel.sy_updateFrequency) - - channel.sy_updateFrequency = nil - assert_nil(channel.sy_updateFrequency) - end - end -end diff --git a/ruby/test/rss/test_atom.rb b/ruby/test/rss/test_atom.rb deleted file mode 100644 index 774064eff..000000000 --- a/ruby/test/rss/test_atom.rb +++ /dev/null @@ -1,684 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/atom" - -module RSS - class TestAtomCore < TestCase - def setup - @uri = "http://www.w3.org/2005/Atom" - @xhtml_uri = "http://www.w3.org/1999/xhtml" - end - - def test_feed - version = "1.0" - encoding = "UTF-8" - standalone = false - - feed = Atom::Feed.new(version, encoding, standalone) - assert_equal("", feed.to_s) - - author = feed.class::Author.new - name = feed.class::Author::Name.new - name.content = "an author" - author.name = name - assert_not_equal("", author.to_s) - feed.authors << author - assert_equal("", feed.to_s) - - id = feed.class::Id.new - id.content = "http://example.com/atom.xml" - assert_not_equal("", id.to_s) - feed.id = id - assert_equal("", feed.to_s) - - title = feed.class::Title.new - title.content = "a title" - assert_not_equal("", title.to_s) - feed.title = title - assert_equal("", feed.to_s) - - updated = feed.class::Updated.new - updated.content = Time.now - assert_not_equal("", updated.to_s) - feed.updated = updated - assert_not_equal("", feed.to_s) - - - feed.authors.clear - assert_equal("", feed.to_s) - entry = Atom::Feed::Entry.new - setup_entry(entry) - assert_not_equal("", entry.to_s) - - author = entry.authors.first - entry.authors.clear - assert_equal("", entry.to_s) - entry.parent = feed - assert_equal("", entry.to_s) - feed.authors << author - assert_not_equal("", entry.to_s) - feed.authors.clear - feed.entries << entry - assert_equal("", feed.to_s) - entry.authors << author - assert_not_equal("", entry.to_s) - assert_not_equal("", feed.to_s) - - doc = REXML::Document.new(feed.to_s) - xmldecl = doc.xml_decl - - assert_equal(version, xmldecl.version) - assert_equal(encoding, xmldecl.encoding.to_s) - assert_equal(standalone, !xmldecl.standalone.nil?) - - assert_equal(@uri, doc.root.namespace) - end - - def test_entry - version = "1.0" - encoding = "UTF-8" - standalone = false - - entry = Atom::Entry.new(version, encoding, standalone) - setup_entry(entry) - - author = entry.authors.first - entry.authors.clear - assert_equal("", entry.to_s) - source = Atom::Entry::Source.new - source.authors << author - entry.source = source - assert_not_equal("", entry.to_s) - - doc = REXML::Document.new(entry.to_s) - xmldecl = doc.xml_decl - - assert_equal(version, xmldecl.version) - assert_equal(encoding, xmldecl.encoding.to_s) - assert_equal(standalone, !xmldecl.standalone.nil?) - - assert_equal(@uri, doc.root.namespace) - end - - def test_not_displayed_xml_stylesheets - feed = Atom::Feed.new - plain_feed = feed.to_s - 3.times do - feed.xml_stylesheets.push(XMLStyleSheet.new) - assert_equal(plain_feed, feed.to_s) - end - end - - def test_atom_author - assert_atom_person_to_s(Atom::Feed::Author) - assert_atom_person_to_s(Atom::Feed::Entry::Author) - assert_atom_person_to_s(Atom::Entry::Author) - assert_atom_person_to_s(Atom::Feed::Entry::Source::Author) - assert_atom_person_to_s(Atom::Entry::Source::Author) - end - - def test_atom_category - assert_atom_category_to_s(Atom::Feed::Category) - assert_atom_category_to_s(Atom::Feed::Entry::Category) - assert_atom_category_to_s(Atom::Entry::Category) - assert_atom_category_to_s(Atom::Feed::Entry::Source::Category) - assert_atom_category_to_s(Atom::Entry::Source::Category) - end - - def test_atom_contributor - assert_atom_person_to_s(Atom::Feed::Contributor) - assert_atom_person_to_s(Atom::Feed::Entry::Contributor) - assert_atom_person_to_s(Atom::Entry::Contributor) - assert_atom_person_to_s(Atom::Feed::Entry::Source::Contributor) - assert_atom_person_to_s(Atom::Entry::Source::Contributor) - end - - def test_atom_generator - assert_atom_generator_to_s(Atom::Feed::Generator) - assert_atom_generator_to_s(Atom::Feed::Entry::Source::Generator) - assert_atom_generator_to_s(Atom::Entry::Source::Generator) - end - - def test_atom_icon - assert_atom_icon_to_s(Atom::Feed::Icon) - assert_atom_icon_to_s(Atom::Feed::Entry::Source::Icon) - assert_atom_icon_to_s(Atom::Entry::Source::Icon) - end - - def test_atom_id - assert_atom_id_to_s(Atom::Feed::Id) - assert_atom_id_to_s(Atom::Feed::Entry::Id) - assert_atom_id_to_s(Atom::Entry::Id) - assert_atom_id_to_s(Atom::Feed::Entry::Source::Id) - assert_atom_id_to_s(Atom::Entry::Source::Id) - end - - def test_atom_link - assert_atom_link_to_s(Atom::Feed::Link) - assert_atom_link_to_s(Atom::Feed::Entry::Link) - assert_atom_link_to_s(Atom::Entry::Link) - assert_atom_link_to_s(Atom::Feed::Entry::Source::Link) - assert_atom_link_to_s(Atom::Entry::Source::Link) - end - - def test_atom_logo - assert_atom_logo_to_s(Atom::Feed::Logo) - assert_atom_logo_to_s(Atom::Feed::Entry::Source::Logo) - assert_atom_logo_to_s(Atom::Entry::Source::Logo) - end - - def test_atom_rights - assert_atom_text_construct_to_s(Atom::Feed::Rights) - assert_atom_text_construct_to_s(Atom::Feed::Entry::Rights) - assert_atom_text_construct_to_s(Atom::Entry::Rights) - assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Rights) - assert_atom_text_construct_to_s(Atom::Entry::Source::Rights) - end - - def test_atom_subtitle - assert_atom_text_construct_to_s(Atom::Feed::Subtitle) - assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Subtitle) - assert_atom_text_construct_to_s(Atom::Entry::Source::Subtitle) - end - - def test_atom_title - assert_atom_text_construct_to_s(Atom::Feed::Title) - assert_atom_text_construct_to_s(Atom::Feed::Entry::Title) - assert_atom_text_construct_to_s(Atom::Entry::Title) - assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Title) - assert_atom_text_construct_to_s(Atom::Entry::Source::Title) - end - - def test_atom_updated - assert_atom_date_construct_to_s(Atom::Feed::Updated) - assert_atom_date_construct_to_s(Atom::Feed::Entry::Updated) - assert_atom_date_construct_to_s(Atom::Entry::Updated) - assert_atom_date_construct_to_s(Atom::Feed::Entry::Source::Updated) - assert_atom_date_construct_to_s(Atom::Entry::Source::Updated) - end - - def test_atom_content - assert_atom_content_to_s(Atom::Feed::Entry::Content) - assert_atom_content_to_s(Atom::Entry::Content) - end - - def test_atom_published - assert_atom_date_construct_to_s(Atom::Feed::Entry::Published) - assert_atom_date_construct_to_s(Atom::Entry::Published) - end - - def test_atom_summary - assert_atom_text_construct_to_s(Atom::Feed::Entry::Summary) - assert_atom_text_construct_to_s(Atom::Entry::Summary) - end - - - def test_to_xml(with_convenience_way=true) - atom = RSS::Parser.parse(make_feed) - assert_equal(atom.to_s, atom.to_xml) - assert_equal(atom.to_s, atom.to_xml("atom")) - assert_equal(atom.to_s, atom.to_xml("atom1.0")) - assert_equal(atom.to_s, atom.to_xml("atom1.0:feed")) - assert_equal(atom.to_s, atom.to_xml("atom:feed")) - - rss09_xml = atom.to_xml("0.91") do |maker| - maker.channel.language = "en-us" - maker.channel.link = "http://example.com/" - if with_convenience_way - maker.channel.description = atom.title.content - else - maker.channel.description {|d| d.content = atom.title.content} - end - - maker.image.url = "http://example.com/logo.png" - maker.image.title = "Logo" - end - rss09 = RSS::Parser.parse(rss09_xml) - assert_equal(["rss", "0.91", nil], rss09.feed_info) - - rss20_xml = atom.to_xml("2.0") do |maker| - maker.channel.link = "http://example.com/" - if with_convenience_way - maker.channel.description = atom.title.content - else - maker.channel.description {|d| d.content = atom.title.content} - end - end - rss20 = RSS::Parser.parse(rss20_xml) - assert_equal("2.0", rss20.rss_version) - assert_equal(["rss", "2.0", nil], rss20.feed_info) - end - - def test_to_xml_with_new_api_since_018 - test_to_xml(false) - end - - private - def setup_entry(entry) - _wrap_assertion do - assert_equal("", entry.to_s) - - author = entry.class::Author.new - name = entry.class::Author::Name.new - name.content = "an author" - author.name = name - assert_not_equal("", author.to_s) - entry.authors << author - assert_equal("", entry.to_s) - - id = entry.class::Id.new - id.content = "http://example.com/atom.xml" - assert_not_equal("", id.to_s) - entry.id = id - assert_equal("", entry.to_s) - - title = entry.class::Title.new - title.content = "a title" - assert_not_equal("", title.to_s) - entry.title = title - assert_equal("", entry.to_s) - - updated = entry.class::Updated.new - updated.content = Time.now - assert_not_equal("", updated.to_s) - entry.updated = updated - assert_not_equal("", entry.to_s) - end - end - - - def assert_atom_person_to_s(target_class) - _wrap_assertion do - name = "A person" - uri = "http://example.com/person/" - email = "person@example.com" - - target = target_class.new - assert_equal("", target.to_s) - - target = target_class.new - person_name = target_class::Name.new - person_name.content = name - target.name = person_name - xml_target = REXML::Document.new(target.to_s).root - assert_equal(["name"], xml_target.elements.collect {|e| e.name}) - assert_equal([name], xml_target.elements.collect {|e| e.text}) - - person_uri = target_class::Uri.new - person_uri.content = uri - target.uri = person_uri - xml_target = REXML::Document.new(target.to_s).root - assert_equal(["name", "uri"], xml_target.elements.collect {|e| e.name}) - assert_equal([name, uri], xml_target.elements.collect {|e| e.text}) - - person_email = target_class::Email.new - person_email.content = email - target.email = person_email - xml_target = REXML::Document.new(target.to_s).root - assert_equal(["name", "uri", "email"], - xml_target.elements.collect {|e| e.name}) - assert_equal([name, uri, email], - xml_target.elements.collect {|e| e.text}) - end - end - - def assert_atom_category_to_s(target_class) - _wrap_assertion do - term = "music" - scheme = "http://example.com/music" - label = "Music" - - category = target_class.new - assert_equal("", category.to_s) - - category = target_class.new - category.scheme = scheme - assert_equal("", category.to_s) - - category = target_class.new - category.label = label - assert_equal("", category.to_s) - - category = target_class.new - category.scheme = scheme - category.label = label - assert_equal("", category.to_s) - - category = target_class.new - category.term = term - xml = REXML::Document.new(category.to_s).root - assert_rexml_element([], {"term" => term}, nil, xml) - - category = target_class.new - category.term = term - category.scheme = scheme - xml = REXML::Document.new(category.to_s).root - assert_rexml_element([], {"term" => term, "scheme" => scheme}, nil, xml) - - category = target_class.new - category.term = term - category.label = label - xml = REXML::Document.new(category.to_s).root - assert_rexml_element([], {"term" => term, "label" => label}, nil, xml) - - category = target_class.new - category.term = term - category.scheme = scheme - category.label = label - xml = REXML::Document.new(category.to_s).root - attrs = {"term" => term, "scheme" => scheme, "label" => label} - assert_rexml_element([], attrs, nil, xml) - end - end - - def assert_atom_generator_to_s(target_class) - _wrap_assertion do - content = "Feed generator" - uri = "http://example.com/generator" - version = "0.0.1" - - generator = target_class.new - assert_equal("", generator.to_s) - - generator = target_class.new - generator.uri = uri - assert_equal("", generator.to_s) - - generator = target_class.new - generator.version = version - assert_equal("", generator.to_s) - - generator = target_class.new - generator.uri = uri - generator.version = version - assert_equal("", generator.to_s) - - generator = target_class.new - generator.content = content - xml = REXML::Document.new(generator.to_s).root - assert_rexml_element([], {}, content, xml) - - generator = target_class.new - generator.content = content - generator.uri = uri - xml = REXML::Document.new(generator.to_s).root - assert_rexml_element([], {"uri" => uri}, content, xml) - - generator = target_class.new - generator.content = content - generator.version = version - xml = REXML::Document.new(generator.to_s).root - assert_rexml_element([], {"version" => version}, content, xml) - - generator = target_class.new - generator.content = content - generator.uri = uri - generator.version = version - xml = REXML::Document.new(generator.to_s).root - assert_rexml_element([], {"uri" => uri, "version" => version}, - content, xml) - end - end - - def assert_atom_icon_to_s(target_class) - _wrap_assertion do - content = "http://example.com/icon.png" - - icon = target_class.new - assert_equal("", icon.to_s) - - icon = target_class.new - icon.content = content - xml = REXML::Document.new(icon.to_s).root - assert_rexml_element([], {}, content, xml) - end - end - - def assert_atom_id_to_s(target_class) - _wrap_assertion do - content = "http://example.com/1" - - id = target_class.new - assert_equal("", id.to_s) - - id = target_class.new - id.content = content - xml = REXML::Document.new(id.to_s).root - assert_rexml_element([], {}, content, xml) - end - end - - def assert_atom_link_to_s(target_class) - _wrap_assertion do - href = "http://example.com/atom.xml" - optvs = { - 'rel' => "self", - 'type' => "application/atom+xml", - 'hreflang' => "ja", - 'title' => "Atom Feed", - 'length' => "801", - } - - link = target_class.new - assert_equal("", link.to_s) - - link = target_class.new - link.href = href - xml = REXML::Document.new(link.to_s).root - assert_rexml_element([], {"href" => href}, nil, xml) - - optional_arguments = %w(rel type hreflang title length) - optional_arguments.each do |name| - rest = optional_arguments.reject {|x| x == name} - - link = target_class.new - link.__send__("#{name}=", optvs[name]) - assert_equal("", link.to_s) - - rest.each do |n| - link.__send__("#{n}=", optvs[n]) - assert_equal("", link.to_s) - end - - link = target_class.new - link.href = href - link.__send__("#{name}=", optvs[name]) - attrs = [["href", href], [name, optvs[name]]] - xml = REXML::Document.new(link.to_s).root - assert_rexml_element([], attrs, nil, xml) - - rest.each do |n| - link.__send__("#{n}=", optvs[n]) - attrs << [n, optvs[n]] - xml = REXML::Document.new(link.to_s).root - assert_rexml_element([], attrs, nil, xml) - end - end - end - end - - def assert_atom_logo_to_s(target_class) - _wrap_assertion do - content = "http://example.com/logo.png" - - logo = target_class.new - assert_equal("", logo.to_s) - - logo = target_class.new - logo.content = content - xml = REXML::Document.new(logo.to_s).root - assert_rexml_element([], {}, content, xml) - end - end - - def assert_atom_text_construct_to_s(target_class) - _wrap_assertion do - text_content = "plain text" - html_content = "#{text_content}" - xhtml_uri = "http://www.w3.org/1999/xhtml" - xhtml_em = RSS::XML::Element.new("em", nil, xhtml_uri, {}, text_content) - xhtml_content = RSS::XML::Element.new("div", nil, xhtml_uri, - {"xmlns" => xhtml_uri}, - [xhtml_em]) - - text = target_class.new - assert_equal("", text.to_s) - - text = target_class.new - text.type = "text" - assert_equal("", text.to_s) - - text = target_class.new - text.content = text_content - xml = REXML::Document.new(text.to_s).root - assert_rexml_element([], {}, text_content, xml) - - text = target_class.new - text.type = "text" - text.content = text_content - xml = REXML::Document.new(text.to_s).root - assert_rexml_element([], {"type" => "text"}, text_content, xml) - - text = target_class.new - text.type = "html" - text.content = html_content - xml = REXML::Document.new(text.to_s).root - assert_rexml_element([], {"type" => "html"}, html_content, xml) - - text = target_class.new - text.type = "xhtml" - text.content = xhtml_content - assert_equal("", text.to_s) - - text = target_class.new - text.type = "xhtml" - text.__send__(target_class.xml_setter, xhtml_content) - xml = REXML::Document.new(text.to_s).root - assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"}, - nil, xml) - assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1]) - assert_rexml_element([], {}, text_content, xml.elements[1].elements[1]) - - text = target_class.new - text.type = "xhtml" - text.__send__(target_class.xml_setter, xhtml_em) - xml = REXML::Document.new(text.to_s).root - assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"}, - nil, xml) - assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1]) - assert_rexml_element([], {}, text_content, xml.elements[1].elements[1]) - end - end - - def assert_atom_date_construct_to_s(target_class) - _wrap_assertion do - date = target_class.new - assert_equal("", date.to_s) - - [ - "2003-12-13T18:30:02Z", - "2003-12-13T18:30:02.25Z", - "2003-12-13T18:30:02+01:00", - "2003-12-13T18:30:02.25+01:00", - ].each do |content| - date = target_class.new - date.content = content - xml = REXML::Document.new(date.to_s).root - assert_rexml_element([], {}, content, xml, :time) - - date = target_class.new - date.content = Time.parse(content) - xml = REXML::Document.new(date.to_s).root - assert_rexml_element([], {}, content, xml, :time) - end - end - end - - def assert_atom_content_to_s(target_class) - _wrap_assertion do - assert_atom_text_construct_to_s(target_class) - assert_atom_content_inline_other_xml_to_s(target_class) - assert_atom_content_inline_other_text_to_s(target_class) - assert_atom_content_inline_other_base64_to_s(target_class) - assert_atom_content_out_of_line_to_s(target_class) - end - end - - def assert_atom_content_inline_other_xml_to_s(target_class) - _wrap_assertion do - content = target_class.new - content.type = "text/xml" - assert_equal("", content.to_s) - - content = target_class.new - content.type = "text/xml" - content.xml = RSS::XML::Element.new("em") - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([["", "em"]], {"type" => "text/xml"}, nil, xml) - end - end - - def assert_atom_content_inline_other_text_to_s(target_class) - _wrap_assertion do - content = target_class.new - content.type = "text/plain" - assert_equal("", content.to_s) - - content = target_class.new - content.type = "text/plain" - content.xml = RSS::XML::Element.new("em") - assert_equal("", content.to_s) - - content = target_class.new - content.type = "text/plain" - content.content = "content" - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([], {"type" => "text/plain"}, "content", xml) - end - end - - def assert_atom_content_inline_other_base64_to_s(target_class) - _wrap_assertion do - type = "image/png" - png_file = File.join(File.dirname(__FILE__), "dot.png") - original_content = File.open(png_file, "rb") do |file| - file.read.force_encoding("binary") - end - - content = target_class.new - content.type = type - content.content = original_content - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([], {"type" => type}, - [original_content].pack("m").delete("\n"), - xml) - end - end - - def assert_atom_content_out_of_line_to_s(target_class) - _wrap_assertion do - type = "application/zip" - src = "http://example.com/xxx.zip" - - content = target_class.new - assert(!content.out_of_line?) - content.src = src - assert(content.out_of_line?) - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([], {"src" => src}, nil, xml) - - content = target_class.new - assert(!content.out_of_line?) - content.type = type - assert(!content.out_of_line?) - content.src = src - assert(content.out_of_line?) - xml = REXML::Document.new(content.to_s).root - assert_rexml_element([], {"type" => type, "src" => src}, nil, xml) - end - end - end -end diff --git a/ruby/test/rss/test_content.rb b/ruby/test/rss/test_content.rb deleted file mode 100644 index fc8269df1..000000000 --- a/ruby/test/rss/test_content.rb +++ /dev/null @@ -1,105 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/content" - -module RSS - class TestContent < TestCase - def setup - @prefix = "content" - @uri = "http://purl.org/rss/1.0/modules/content/" - - @elems = { - :encoded => "ATTENTION", - } - - @content_nodes = @elems.collect do |name, value| - "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}" - end.join("\n") - - @rss10_source = make_RDF(<<-EOR, {@prefix => @uri}) -#{make_channel()} -#{make_image()} -#{make_item(@content_nodes)} -#{make_textinput()} -EOR - - @rss10 = Parser.parse(@rss10_source) - - - @rss20_source = make_rss20(<<-EOR, {@prefix => @uri}) -#{make_channel20(make_item20(@content_nodes))} -EOR - - @rss20 = Parser.parse(@rss20_source) - end - - def test_parser - assert_nothing_raised do - Parser.parse(@rss10_source) - end - - assert_nothing_raised do - Parser.parse(@rss20_source) - end - - @elems.each do |tag, value| - tag_name = "#{@prefix}:#{tag}" - content_encodes = make_element(tag_name, {}, value) * 2 - - assert_too_much_tag(tag.to_s, "item") do - Parser.parse(make_RDF(<<-EOR, {@prefix => @uri})) -#{make_channel} -#{make_item(content_encodes)} -EOR - end - - assert_too_much_tag(tag.to_s, "item") do - Parser.parse(make_rss20(<<-EOR, {@prefix => @uri})) -#{make_channel20(make_item20(content_encodes))} -EOR - end - end - end - - def test_accessor - new_value = { - :encoded => "hoge]]>", - } - - @elems.each do |name, value| - [@rss10, @rss20].each do |rss| - meth = "#{RSS::CONTENT_PREFIX}_#{name}" - parent = rss.items.last - assert_equal(value, parent.__send__(meth)) - parent.__send__("#{meth}=", new_value[name].to_s) - assert_equal(new_value[name], parent.__send__(meth)) - end - end - end - - def test_to_s - @elems.each do |name, value| - excepted = make_element("#{@prefix}:#{name}", {}, value) - meth = "#{RSS::CONTENT_PREFIX}_#{name}_element" - [@rss10, @rss20].each do |rss| - assert_equal(excepted, rss.items.last.__send__(meth)) - end - end - - [@rss10_source, @rss20_source].each do |source| - REXML::Document.new(source).root.each_element do |parent| - next unless parent.name != "item" - parent.each_element do |elem| - if elem.namespace == @uri - assert_equal(elem.text, @elems[elem.name.intern].to_s) - end - end - end - end - end - end -end diff --git a/ruby/test/rss/test_dublincore.rb b/ruby/test/rss/test_dublincore.rb deleted file mode 100644 index 37ef17719..000000000 --- a/ruby/test/rss/test_dublincore.rb +++ /dev/null @@ -1,270 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/dublincore" - -module RSS - class TestDublinCore < TestCase - def setup - @rss10_parents = [%w(channel), %w(image), %w(item), %w(textinput)] - - @rss10_source = make_RDF(<<-EOR, {DC_PREFIX => DC_URI}) -#{make_channel(DC_NODES)} -#{make_image(DC_NODES)} -#{make_item(DC_NODES)} -#{make_textinput(DC_NODES)} -EOR - - @rss20_parents = [%w(channel), %w(items last)] - - @rss20_source = make_rss20(<<-EOR, {DC_PREFIX => DC_URI}) -#{make_channel20(DC_NODES + make_item20(DC_NODES))} -EOR - - @atom_feed_parents = [[], %w(entries last)] - - @atom_feed_source = make_feed(<<-EOR, {DC_PREFIX => DC_URI}) -#{DC_NODES} -#{make_entry(DC_NODES)} -EOR - - @atom_entry_parents = [[]] - - @atom_entry_source = make_entry_document(<<-EOR, {DC_PREFIX => DC_URI}) -#{DC_NODES} -EOR - end - - def test_parser - rss10_maker = Proc.new do |content, xmlns| - make_RDF(<<-EOR, xmlns) -#{make_channel(content)} -#{make_image(content)} -#{make_item(content)} -#{make_textinput(content)} -EOR - end - assert_dc_parse(@rss10_source, @rss10_parents, false, &rss10_maker) - assert_dc_parse(@rss10_source, @rss10_parents, true, &rss10_maker) - - rss20_maker = Proc.new do |content, xmlns| - make_rss20(<<-EOR, xmlns) -#{make_channel20(content + make_item20(content))} -EOR - end - assert_dc_parse(@rss20_source, @rss20_parents, false, &rss20_maker) - assert_dc_parse(@rss20_source, @rss20_parents, true, &rss20_maker) - - atom_feed_maker = Proc.new do |content, xmlns| - make_feed(<<-EOR, xmlns) -#{content} -#{make_entry(content)} -EOR - end - assert_dc_parse(@atom_feed_source, @atom_feed_parents, false, - &atom_feed_maker) - assert_dc_parse(@atom_feed_source, @atom_feed_parents, true, - &atom_feed_maker) - - atom_entry_maker = Proc.new do |content, xmlns| - make_entry_document(<<-EOR, xmlns) -#{content} -EOR - end - assert_dc_parse(@atom_entry_source, @atom_entry_parents, false, - &atom_entry_maker) - assert_dc_parse(@atom_entry_source, @atom_entry_parents, true, - &atom_entry_maker) - end - - def test_singular_accessor - assert_dc_singular_accessor(@rss10_source, @rss10_parents) - assert_dc_singular_accessor(@rss20_source, @rss20_parents) - assert_dc_singular_accessor(@atom_feed_source, @atom_feed_parents) - assert_dc_singular_accessor(@atom_entry_source, @atom_entry_parents) - end - - def test_plural_accessor - assert_dc_plural_accessor(@rss10_source, @rss10_parents, false) - assert_dc_plural_accessor(@rss10_source, @rss10_parents, true) - - assert_dc_plural_accessor(@rss20_source, @rss20_parents, false) - assert_dc_plural_accessor(@rss20_source, @rss20_parents, true) - - assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, false) - assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, true) - - assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, false) - assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, true) - end - - def test_to_s - assert_dc_to_s(@rss10_source, @rss10_parents, false) - assert_dc_to_s(@rss10_source, @rss10_parents, true) - - targets = ["channel", "channel/item[3]"] - assert_dc_to_s(@rss20_source, @rss20_parents, false, targets) - assert_dc_to_s(@rss20_source, @rss20_parents, true, targets) - - targets = [".", "entry"] - assert_dc_to_s(@atom_feed_source, @atom_feed_parents, false, targets) - assert_dc_to_s(@atom_feed_source, @atom_feed_parents, true, targets) - - targets = ["."] - assert_dc_to_s(@atom_entry_source, @atom_entry_parents, false, targets) - assert_dc_to_s(@atom_entry_source, @atom_entry_parents, true, targets) - end - - private - def dc_plural_suffix(name, check_backward_compatibility) - if name == :rights - if check_backward_compatibility - "es" - else - "_list" - end - else - "s" - end - end - - def assert_dc_parse(source, parents, check_backward_compatibility, &maker) - assert_nothing_raised do - Parser.parse(source) - end - - DC_ELEMENTS.each do |name, value| - parents.each do |parent_readers| - feed = nil - assert_nothing_raised do - tag = "#{DC_PREFIX}:#{name}" - dc_content = "<#{tag}>#{value}\n" - dc_content *= 2 - feed = Parser.parse(maker.call(dc_content, {DC_PREFIX => DC_URI})) - end - parent = chain_reader(feed, parent_readers) - - plural_suffix = dc_plural_suffix(name, check_backward_compatibility) - plural_reader = "dc_#{name}#{plural_suffix}" - values = parent.__send__(plural_reader).collect(&:value) - value = CGI.unescapeHTML(value) if value.kind_of?(String) - assert_equal([value, value], values) - end - end - end - - def assert_dc_singular_accessor(source, parents) - feed = Parser.parse(source) - new_value = "hoge" - - parents.each do |parent_readers| - parent = chain_reader(feed, parent_readers) - DC_ELEMENTS.each do |name, value| - parsed_value = parent.__send__("dc_#{name}") - value = CGI.unescapeHTML(value) if value.kind_of?(String) - assert_equal(value, parsed_value) - if name == :date - t = Time.iso8601("2003-01-01T02:30:23+09:00") - class << t - alias_method(:to_s, :iso8601) - end - parent.__send__("dc_#{name}=", t.iso8601) - assert_equal(t, parent.__send__("dc_#{name}")) - if parent.class.method_defined?(:date_without_dc_date=) - assert_nil(parent.date) - else - assert_equal(t, parent.date) - end - - parent.date = value - assert_equal(value, parent.date) - assert_equal(value, parent.__send__("dc_#{name}")) - else - parent.__send__("dc_#{name}=", new_value) - assert_equal(new_value, parent.__send__("dc_#{name}")) - end - end - end - end - - def assert_dc_plural_accessor(source, parents, check_backward_compatibility) - feed = Parser.parse(source) - new_value = "hoge" - - DC_ELEMENTS.each do |name, value| - parents.each do |parent_readers| - parent = chain_reader(feed, parent_readers) - parsed_value = parent.__send__("dc_#{name}") - value = CGI.unescapeHTML(value) if value.kind_of?(String) - assert_equal(value, parsed_value) - - plural_suffix = dc_plural_suffix(name, check_backward_compatibility) - plural_reader = "dc_#{name}#{plural_suffix}" - klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}" - klass = DublinCoreModel.const_get(klass_name) - if name == :date - t = Time.iso8601("2003-01-01T02:30:23+09:00") - class << t - alias_method(:to_s, :iso8601) - end - elems = parent.__send__(plural_reader) - elems << klass.new(t.iso8601) - new_elems = parent.__send__(plural_reader) - values = new_elems.collect{|x| x.value} - assert_equal([parent.__send__("dc_#{name}"), t], values) - else - elems = parent.__send__(plural_reader) - elems << klass.new(new_value) - new_elems = parent.__send__(plural_reader) - values = new_elems.collect{|x| x.value} - assert_equal([parent.__send__("dc_#{name}"), new_value], - values) - end - end - end - end - - def assert_dc_to_s(source, parents, check_backward_compatibility, - targets=nil) - feed = Parser.parse(source) - - DC_ELEMENTS.each do |name, value| - excepted = "<#{DC_PREFIX}:#{name}>#{value}" - parents.each do |parent_readers| - parent = chain_reader(feed, parent_readers) - assert_equal(excepted, parent.__send__("dc_#{name}_elements")) - end - - plural_suffix = dc_plural_suffix(name, check_backward_compatibility) - reader = "dc_#{name}#{plural_suffix}" - excepted = Array.new(2, excepted).join("\n") - parents.each do |parent_readers| - parent = chain_reader(feed, parent_readers) - elems = parent.__send__(reader) - klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}" - klass = DublinCoreModel.const_get(klass_name) - elems << klass.new(parent.__send__("dc_#{name}")) - assert_equal(excepted, parent.__send__("dc_#{name}_elements")) - end - end - - targets ||= parents.collect do |parent_readers| - parent_readers.first - end - feed_root = REXML::Document.new(source).root - targets.each do |target_xpath| - parent = feed_root.elements[target_xpath] - parent.each_element do |elem| - if elem.namespace == DC_URI - assert_equal(elem.text, - CGI.unescapeHTML(DC_ELEMENTS[elem.name.intern].to_s)) - end - end - end - end - end -end diff --git a/ruby/test/rss/test_image.rb b/ruby/test/rss/test_image.rb deleted file mode 100644 index 0f1cd8c9e..000000000 --- a/ruby/test/rss/test_image.rb +++ /dev/null @@ -1,215 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/image" - -module RSS - class TestImage < TestCase - - def setup - @prefix = "image" - @uri = "http://purl.org/rss/1.0/modules/image/" - - @favicon_attrs = { - "rdf:about" => "http://www.kuro5hin.org/favicon.ico", - "#{@prefix}:size" => "small", - } - @favicon_contents = {"dc:title" => "Kuro5hin",} - @items = [ - [ - { - "rdf:about" => "http://www.example.org/item.png", - "rdf:resource" => "http://www.example.org/item", - }, - { - "dc:title" => "Example Image", - "#{@prefix}:width" => "100", - "#{@prefix}:height" => "65", - }, - ], - [ - { - "rdf:about" => "http://www.kuro5hin.org/images/topics/culture.jpg", - }, - { - "dc:title" => "Culture", - "#{@prefix}:width" => "80", - "#{@prefix}:height" => "50", - }, - ] - ] - - - @channel_nodes = make_element("#{@prefix}:favicon", - @favicon_attrs, - @favicon_contents) - items = "" - @items.each do |attrs, contents| - image_item = make_element("#{@prefix}:item", attrs, contents) - items << make_item(image_item) - end - - @ns = { - @prefix => @uri, - DC_PREFIX => DC_URI, - } - @rss_source = make_RDF(<<-EOR, @ns) -#{make_channel(@channel_nodes)} -#{make_image} -#{items} -#{make_textinput} -EOR - - @rss = Parser.parse(@rss_source) - end - - def test_parser - assert_nothing_raised do - Parser.parse(@rss_source) - end - - assert_too_much_tag("favicon", "channel") do - Parser.parse(make_RDF(<<-EOR, @ns)) -#{make_channel(@channel_nodes * 2)} -#{make_item} -EOR - end - - attrs = {"rdf:about" => "http://www.example.org/item.png"} - contents = [["#{@prefix}:width", "80"]] * 5 - image_item = make_element("#{@prefix}:item", attrs, contents) - assert_too_much_tag("width", "item") do - Parser.parse(make_RDF(<<-EOR, @ns)) -#{make_channel} -#{make_item(image_item)} -EOR - end - end - - def test_favicon_accessor - favicon = @rss.channel.image_favicon - [ - %w(about rdf:about http://example.com/favicon.ico), - %w(size image:size large), - %w(image_size image:size medium), - ].each do |name, full_name, new_value| - assert_equal(@favicon_attrs[full_name], favicon.__send__(name)) - favicon.__send__("#{name}=", new_value) - assert_equal(new_value, favicon.__send__(name)) - favicon.__send__("#{name}=", @favicon_attrs[full_name]) - assert_equal(@favicon_attrs[full_name], favicon.__send__(name)) - end - - %w(small medium large).each do |value| - assert_nothing_raised do - favicon.size = value - favicon.image_size = value - end - end - - %w(aaa AAA SMALL MEDIUM LARGE).each do |value| - args = ["#{@prefix}:favicon", value, "#{@prefix}:size"] - assert_not_available_value(*args) do - favicon.size = value - end - assert_not_available_value(*args) do - favicon.image_size = value - end - end - - [ - %w(dc_title dc:title sample-favicon), - ].each do |name, full_name, new_value| - assert_equal(@favicon_contents[full_name], favicon.__send__(name)) - favicon.__send__("#{name}=", new_value) - assert_equal(new_value, favicon.__send__(name)) - favicon.__send__("#{name}=", @favicon_contents[full_name]) - assert_equal(@favicon_contents[full_name], favicon.__send__(name)) - end - end - - def test_item_accessor - @rss.items.each_with_index do |item, i| - image_item = item.image_item - attrs, contents = @items[i] - [ - %w(about rdf:about http://example.com/image.png), - %w(resource rdf:resource http://example.com/), - ].each do |name, full_name, new_value| - assert_equal(attrs[full_name], image_item.__send__(name)) - image_item.__send__("#{name}=", new_value) - assert_equal(new_value, image_item.__send__(name)) - image_item.__send__("#{name}=", attrs[full_name]) - assert_equal(attrs[full_name], image_item.__send__(name)) - end - - [ - ["width", "image:width", "111"], - ["image_width", "image:width", "44"], - ["height", "image:height", "222"], - ["image_height", "image:height", "88"], - ].each do |name, full_name, new_value| - assert_equal(contents[full_name].to_i, image_item.__send__(name)) - image_item.__send__("#{name}=", new_value) - assert_equal(new_value.to_i, image_item.__send__(name)) - image_item.__send__("#{name}=", contents[full_name]) - assert_equal(contents[full_name].to_i, image_item.__send__(name)) - end - - [ - ["dc_title", "dc:title", "sample-image"], - ].each do |name, full_name, new_value| - assert_equal(contents[full_name], image_item.__send__(name)) - image_item.__send__("#{name}=", new_value) - assert_equal(new_value, image_item.__send__(name)) - image_item.__send__("#{name}=", contents[full_name]) - assert_equal(contents[full_name], image_item.__send__(name)) - end - end - end - - def test_favicon_to_s - favicon = @rss.channel.image_favicon - expected_xml = image_xmlns_container(make_element("#{@prefix}:favicon", - @favicon_attrs, - @favicon_contents)) - expected = REXML::Document.new(expected_xml) - actual_xml = image_xmlns_container(favicon.to_s(false, "")) - actual = REXML::Document.new(actual_xml) - assert_equal(expected.to_s, actual.to_s) - end - - def test_item_to_s - @rss.items.each_with_index do |item, i| - attrs, contents = @items[i] - expected_xml = make_element("#{@prefix}:item", attrs, contents) - expected_xml = image_xmlns_container(expected_xml) - expected = REXML::Document.new(expected_xml) - actual_xml = image_xmlns_container(item.image_item.to_s(false, "")) - actual = REXML::Document.new(actual_xml) - - assert_equal(expected[0].attributes, actual[0].attributes) - - %w(image:height image:width dc:title).each do |name| - actual_target = actual.elements["//#{name}"] - expected_target = expected.elements["//#{name}"] - assert_equal(expected_target.to_s, actual_target.to_s) - end - end - end - - private - def image_xmlns_container(content) - xmlns_container({ - @prefix => @uri, - "dc" => "http://purl.org/dc/elements/1.1/", - "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - }, - content) - end - end -end diff --git a/ruby/test/rss/test_inherit.rb b/ruby/test/rss/test_inherit.rb deleted file mode 100644 index 020f066c5..000000000 --- a/ruby/test/rss/test_inherit.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/1.0" - -module RSS - class TestInherit < TestCase - - class InheritedImage < RSS::RDF::Image - def self.indent_size; 1; end - def self.tag_name; 'image'; end - end - - def setup - @rss = make_RDF(<<-EOR) -#{make_channel} -#{make_image} -#{make_item} -#{make_textinput} -EOR - end - - def test_inherit - rss = RSS::Parser.parse(@rss) - orig_image = rss.image - prefix = "[INHERIT]" - image = InheritedImage.new("#{prefix} #{orig_image.about}") - image.title = "#{prefix} #{orig_image.title}" - image.url = "#{prefix} #{orig_image.url}" - image.link = "#{prefix} #{orig_image.link}" - rss.image = image - - new_rss = RSS::Parser.parse(rss.to_s) - new_image = new_rss.image - assert_equal("#{prefix} #{orig_image.about}", new_image.about) - assert_equal("#{prefix} #{orig_image.title}", new_image.title) - assert_equal("#{prefix} #{orig_image.url}", new_image.url) - assert_equal("#{prefix} #{orig_image.link}", new_image.link) - end - end -end diff --git a/ruby/test/rss/test_itunes.rb b/ruby/test/rss/test_itunes.rb deleted file mode 100644 index 4459d8bfc..000000000 --- a/ruby/test/rss/test_itunes.rb +++ /dev/null @@ -1,356 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/2.0" -require "rss/itunes" - -module RSS - class TestITunes < TestCase - def test_author - assert_itunes_author(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - - assert_itunes_author(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_block - assert_itunes_block(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_category - assert_itunes_category(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - end - - def test_image - assert_itunes_image(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - end - - def test_duration - assert_itunes_duration(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_explicit - assert_itunes_explicit(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - - assert_itunes_explicit(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_keywords - assert_itunes_keywords(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - - assert_itunes_keywords(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_new_feed_url - assert_itunes_new_feed_url(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - end - - def test_owner - assert_itunes_owner(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - end - - def test_subtitle - assert_itunes_subtitle(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - - assert_itunes_subtitle(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - def test_summary - assert_itunes_summary(%w(channel)) do |content, xmlns| - make_rss20(make_channel20(content), xmlns) - end - - assert_itunes_summary(%w(items last)) do |content, xmlns| - make_rss20(make_channel20(make_item20(content)), xmlns) - end - end - - private - def itunes_rss20_parse(content, &maker) - xmlns = {"itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd"} - rss20_xml = maker.call(content, xmlns) - ::RSS::Parser.parse(rss20_xml) - end - - def assert_itunes_author(readers, &rss20_maker) - _wrap_assertion do - author = "John Lennon" - rss20 = itunes_rss20_parse(tag("itunes:author", author), &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(author, target.itunes_author) - end - end - - def _assert_itunes_block(value, boolean_value, readers, &rss20_maker) - rss20 = itunes_rss20_parse(tag("itunes:block", value), &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(value, target.itunes_block) - assert_equal(boolean_value, target.itunes_block?) - end - - def assert_itunes_block(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_block("yes", true, readers, &rss20_maker) - _assert_itunes_block("Yes", true, readers, &rss20_maker) - _assert_itunes_block("no", false, readers, &rss20_maker) - _assert_itunes_block("", false, readers, &rss20_maker) - end - end - - def _assert_itunes_category(categories, readers, &rss20_maker) - cats = categories.collect do |category| - if category.is_a?(Array) - category, sub_category = category - tag("itunes:category", - tag("itunes:category", nil, {"text" => sub_category}), - {"text" => category}) - else - tag("itunes:category", nil, {"text" => category}) - end - end.join - rss20 = itunes_rss20_parse(cats, &rss20_maker) - target = chain_reader(rss20, readers) - actual_categories = target.itunes_categories.collect do |category| - cat = category.text - if category.itunes_categories.empty? - cat - else - [cat, *category.itunes_categories.collect {|c| c.text}] - end - end - assert_equal(categories, actual_categories) - end - - def assert_itunes_category(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_category(["Audio Blogs"], readers, &rss20_maker) - _assert_itunes_category([["Arts & Entertainment", "Games"]], - readers, &rss20_maker) - _assert_itunes_category([["Arts & Entertainment", "Games"], - ["Technology", "Computers"], - "Audio Blogs"], - readers, &rss20_maker) - end - end - - def assert_itunes_image(readers, &rss20_maker) - _wrap_assertion do - url = "http://example.com/podcasts/everything/AllAboutEverything.jpg" - content = tag("itunes:image", nil, {"href" => url}) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_not_nil(target.itunes_image) - assert_equal(url, target.itunes_image.href) - - assert_missing_attribute("image", "href") do - content = tag("itunes:image") - itunes_rss20_parse(content, &rss20_maker) - end - end - end - - def _assert_itunes_duration(hour, minute, second, value, - readers, &rss20_maker) - content = tag("itunes:duration", value) - rss20 = itunes_rss20_parse(content, &rss20_maker) - duration = chain_reader(rss20, readers).itunes_duration - assert_equal(value, duration.content) - assert_equal(hour, duration.hour) - assert_equal(minute, duration.minute) - assert_equal(second, duration.second) - end - - def _assert_itunes_duration_not_available_value(value, &rss20_maker) - assert_not_available_value("duration", value) do - content = tag("itunes:duration", value) - itunes_rss20_parse(content, &rss20_maker) - end - end - - def assert_itunes_duration(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_duration(7, 14, 5, "07:14:05", readers, &rss20_maker) - _assert_itunes_duration(7, 14, 5, "7:14:05", readers, &rss20_maker) - _assert_itunes_duration(0, 4, 55, "04:55", readers, &rss20_maker) - _assert_itunes_duration(0, 4, 5, "4:05", readers, &rss20_maker) - _assert_itunes_duration(0, 0, 5, "5", readers, &rss20_maker) - _assert_itunes_duration(0, 3, 15, "195", readers, &rss20_maker) - _assert_itunes_duration(1, 0, 1, "3601", readers, &rss20_maker) - - _assert_itunes_duration_not_available_value("09:07:14:05", &rss20_maker) - _assert_itunes_duration_not_available_value("10:5", &rss20_maker) - _assert_itunes_duration_not_available_value("10:03:5", &rss20_maker) - _assert_itunes_duration_not_available_value("10:3:05", &rss20_maker) - - _assert_itunes_duration_not_available_value("xx:xx:xx", &rss20_maker) - - _assert_itunes_duration_not_available_value("", &rss20_maker) - end - end - - def _assert_itunes_explicit(explicit, value, readers, &rss20_maker) - content = tag("itunes:explicit", value) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(value, target.itunes_explicit) - assert_equal(explicit, target.itunes_explicit?) - end - - def assert_itunes_explicit(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_explicit(true, "explicit", readers, &rss20_maker) - _assert_itunes_explicit(true, "yes", readers, &rss20_maker) - _assert_itunes_explicit(true, "true", readers, &rss20_maker) - _assert_itunes_explicit(false, "clean", readers, &rss20_maker) - _assert_itunes_explicit(false, "no", readers, &rss20_maker) - _assert_itunes_explicit(false, "false", readers, &rss20_maker) - _assert_itunes_explicit(nil, "invalid", readers, &rss20_maker) - end - end - - def _assert_itunes_keywords(keywords, value, readers, &rss20_maker) - content = tag("itunes:keywords", value) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(keywords, target.itunes_keywords) - end - - def assert_itunes_keywords(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_keywords(["salt"], "salt", readers, &rss20_maker) - _assert_itunes_keywords(["salt"], " salt ", readers, &rss20_maker) - _assert_itunes_keywords(["salt", "pepper", "shaker", "exciting"], - "salt, pepper, shaker, exciting", - readers, &rss20_maker) - _assert_itunes_keywords(["metric", "socket", "wrenches", "toolsalt"], - "metric, socket, wrenches, toolsalt", - readers, &rss20_maker) - _assert_itunes_keywords(["olitics", "red", "blue", "state"], - "olitics, red, blue, state", - readers, &rss20_maker) - end - end - - def assert_itunes_new_feed_url(readers, &rss20_maker) - _wrap_assertion do - url = "http://newlocation.com/example.rss" - content = tag("itunes:new-feed-url", url) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(url, target.itunes_new_feed_url) - end - end - - def _assert_itunes_owner(name, email, readers, &rss20_maker) - content = tag("itunes:owner", - tag("itunes:name", name) + tag("itunes:email", email)) - rss20 = itunes_rss20_parse(content, &rss20_maker) - owner = chain_reader(rss20, readers).itunes_owner - assert_equal(name, owner.itunes_name) - assert_equal(email, owner.itunes_email) - end - - def assert_itunes_owner(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_owner("John Doe", "john.doe@example.com", - readers, &rss20_maker) - - assert_missing_tag("name", "owner") do - content = tag("itunes:owner") - itunes_rss20_parse(content, &rss20_maker) - end - - assert_missing_tag("name", "owner") do - content = tag("itunes:owner", - tag("itunes:email", "john.doe@example.com")) - itunes_rss20_parse(content, &rss20_maker) - end - - assert_missing_tag("email", "owner") do - content = tag("itunes:owner", tag("itunes:name", "John Doe")) - itunes_rss20_parse(content, &rss20_maker) - end - end - end - - def _assert_itunes_subtitle(value, readers, &rss20_maker) - content = tag("itunes:subtitle", value) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(value, target.itunes_subtitle) - end - - def assert_itunes_subtitle(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_subtitle("A show about everything", readers, &rss20_maker) - _assert_itunes_subtitle("A short primer on table spices", - readers, &rss20_maker) - _assert_itunes_subtitle("Comparing socket wrenches is fun!", - readers, &rss20_maker) - _assert_itunes_subtitle("Red + Blue != Purple", readers, &rss20_maker) - end - end - - def _assert_itunes_summary(value, readers, &rss20_maker) - content = tag("itunes:summary", value) - rss20 = itunes_rss20_parse(content, &rss20_maker) - target = chain_reader(rss20, readers) - assert_equal(value, target.itunes_summary) - end - - def assert_itunes_summary(readers, &rss20_maker) - _wrap_assertion do - _assert_itunes_summary("All About Everything is a show about " + - "everything. Each week we dive into any " + - "subject known to man and talk about it as " + - "much as we can. Look for our Podcast in " + - "the iTunes Music Store", - readers, &rss20_maker) - _assert_itunes_summary("This week we talk about salt and pepper " + - "shakers, comparing and contrasting pour " + - "rates, construction materials, and overall " + - "aesthetics. Come and join the party!", - readers, &rss20_maker) - _assert_itunes_summary("This week we talk about metric vs. old " + - "english socket wrenches. Which one is " + - "better? Do you really need both? Get all " + - "of your answers here.", - readers, &rss20_maker) - _assert_itunes_summary("This week we talk about surviving in a " + - "Red state if you're a Blue person. Or " + - "vice versa.", - readers, &rss20_maker) - end - end - end -end diff --git a/ruby/test/rss/test_maker_0.9.rb b/ruby/test/rss/test_maker_0.9.rb deleted file mode 100644 index d07a724ab..000000000 --- a/ruby/test/rss/test_maker_0.9.rb +++ /dev/null @@ -1,477 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMaker09 < TestCase - def test_supported? - assert(RSS::Maker.supported?("0.9")) - assert(RSS::Maker.supported?("rss0.9")) - assert(RSS::Maker.supported?("0.91")) - assert(RSS::Maker.supported?("rss0.91")) - assert(RSS::Maker.supported?("0.92")) - assert(RSS::Maker.supported?("rss0.92")) - assert(!RSS::Maker.supported?("0.93")) - assert(!RSS::Maker.supported?("rss0.93")) - end - - def test_find_class - assert_equal(RSS::Maker::RSS091, RSS::Maker["0.91"]) - assert_equal(RSS::Maker::RSS091, RSS::Maker["rss0.91"]) - assert_equal(RSS::Maker::RSS092, RSS::Maker["0.9"]) - assert_equal(RSS::Maker::RSS092, RSS::Maker["0.92"]) - assert_equal(RSS::Maker::RSS092, RSS::Maker["rss0.92"]) - end - - def test_rss - assert_raise(LocalJumpError) do - RSS::Maker.make("0.91") - end - - rss = RSS::Maker.make("0.9") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - end - assert_equal("0.92", rss.rss_version) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - end - assert_equal("0.91", rss.rss_version) - - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.encoding = "EUC-JP" - end - assert_equal("0.91", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.standalone = "yes" - end - assert_equal("0.91", rss.rss_version) - assert_equal("yes", rss.standalone) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.encoding = "EUC-JP" - maker.standalone = "yes" - end - assert_equal("0.91", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - assert_equal("yes", rss.standalone) - end - - def test_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - copyright = "foo" - managingEditor = "bar" - webMaster = "web master" - rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))' - docs = "http://foo.com/doc" - skipDays = [ - "Sunday", - "Monday", - ] - skipHours = [ - "0", - "13", - ] - pubDate = Time.now - lastBuildDate = Time.now - - image_url = "http://example.com/logo.png" - image_title = "Logo" - - rss = RSS::Maker.make("0.91") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - maker.channel.copyright = copyright - maker.channel.managingEditor = managingEditor - maker.channel.webMaster = webMaster - maker.channel.rating = rating - maker.channel.docs = docs - maker.channel.pubDate = pubDate - maker.channel.lastBuildDate = lastBuildDate - - skipDays.each do |day| - maker.channel.skipDays.new_day do |new_day| - new_day.content = day - end - end - skipHours.each do |hour| - maker.channel.skipHours.new_hour do |new_hour| - new_hour.content = hour - end - end - - maker.image.url = image_url - maker.image.title = image_title - end - channel = rss.channel - - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(language, channel.language) - assert_equal(copyright, channel.copyright) - assert_equal(managingEditor, channel.managingEditor) - assert_equal(webMaster, channel.webMaster) - assert_equal(rating, channel.rating) - assert_equal(docs, channel.docs) - assert_equal(pubDate, channel.pubDate) - assert_equal(pubDate, channel.date) - assert_equal(lastBuildDate, channel.lastBuildDate) - - skipDays.each_with_index do |day, i| - assert_equal(day, channel.skipDays.days[i].content) - end - skipHours.each_with_index do |hour, i| - assert_equal(hour.to_i, channel.skipHours.hours[i].content) - end - - assert(channel.items.empty?) - - assert_equal(image_url, channel.image.url) - assert_equal(image_title, channel.image.title) - assert_equal(link, channel.image.link) - - assert_nil(channel.textInput) - end - - def test_not_valid_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - - assert_not_set_error("maker.channel", %w(title)) do - RSS::Maker.make("0.91") do |maker| - # maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - end - end - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("0.91") do |maker| - maker.channel.title = title - # maker.channel.link = link - maker.channel.link = nil - maker.channel.description = description - maker.channel.language = language - end - end - - assert_not_set_error("maker.channel", %w(description)) do - RSS::Maker.make("0.91") do |maker| - maker.channel.title = title - maker.channel.link = link - # maker.channel.description = description - maker.channel.language = language - end - end - - assert_not_set_error("maker.channel", %w(language)) do - RSS::Maker.make("0.91") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - # maker.channel.language = language - end - end - end - - def test_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - image = rss.image - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - assert_equal(width.to_i, image.width) - assert_equal(height.to_i, image.height) - assert_equal(description, image.description) - - assert_not_set_error("maker.channel", %w(description title language)) do - RSS::Maker.make("0.91") do |maker| - # setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - end - - def test_not_valid_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - assert_not_set_error("maker.image", %w(title)) do - RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - # maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - # maker.channel.link = link - maker.channel.link = nil - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - - assert_not_set_error("maker.image", %w(url)) do - RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - # maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - end - - def test_items(with_convenience_way=true) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - end - assert(rss.channel.items.empty?) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - item.title = title - item.link = link - # item.description = description - end - - setup_dummy_image(maker) - end - assert_equal(1, rss.channel.items.size) - item = rss.channel.items.first - assert_equal(title, item.title) - assert_equal(link, item.link) - assert_nil(item.description) - - pubDate = Time.now - - item_size = 5 - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - _item.date = pubDate - i - end - end - maker.items.do_sort = true - - setup_dummy_image(maker) - end - assert_equal(item_size, rss.items.size) - rss.channel.items.each_with_index do |_item, i| - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - end - end - maker.items.do_sort = Proc.new do |x, y| - if with_convenience_way - y.title[-1] <=> x.title[-1] - else - y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]} - end - end - - setup_dummy_image(maker) - end - assert_equal(item_size, rss.items.size) - rss.channel.items.reverse.each_with_index do |_item, i| - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - end - - def test_items_with_new_api_since_018 - test_items(false) - end - - def test_textInput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - textInput = rss.channel.textInput - assert_equal(title, textInput.title) - assert_equal(description, textInput.description) - assert_equal(name, textInput.name) - assert_equal(link, textInput.link) - - assert_not_set_error("maker.channel", - %w(link language description title)) do - RSS::Maker.make("0.91") do |maker| - # setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - end - end - - def test_not_valid_textInput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - # maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.textinput.title = title - # maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.textinput.title = title - maker.textinput.description = description - # maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - # maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - end - - def test_date_in_string - date = Time.now - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.items.new_item do |item| - item.title = "The first item" - item.link = "http://example.com/blog/1.html" - item.date = date.rfc822 - end - end - - assert_equal(date.iso8601, rss.items[0].date.iso8601) - end - end -end diff --git a/ruby/test/rss/test_maker_1.0.rb b/ruby/test/rss/test_maker_1.0.rb deleted file mode 100644 index f3c0e50ce..000000000 --- a/ruby/test/rss/test_maker_1.0.rb +++ /dev/null @@ -1,519 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMaker10 < TestCase - def test_supported? - assert(RSS::Maker.supported?("1.0")) - assert(RSS::Maker.supported?("rss1.0")) - assert(!RSS::Maker.supported?("1.1")) - assert(!RSS::Maker.supported?("rss1.1")) - end - - def test_find_class - assert_equal(RSS::Maker::RSS10, RSS::Maker["1.0"]) - assert_equal(RSS::Maker::RSS10, RSS::Maker["rss1.0"]) - end - - def test_rdf - assert_raise(LocalJumpError) do - RSS::Maker.make("1.0") - end - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - assert_equal("1.0", rss.rss_version) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.encoding = "EUC-JP" - - setup_dummy_item(maker) - end - assert_equal("1.0", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.standalone = "yes" - - setup_dummy_item(maker) - end - assert_equal("1.0", rss.rss_version) - assert_equal("yes", rss.standalone) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.encoding = "EUC-JP" - maker.standalone = "yes" - - setup_dummy_item(maker) - end - assert_equal("1.0", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - assert_equal("yes", rss.standalone) - end - - def test_channel - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - - rss = RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - - setup_dummy_item(maker) - end - channel = rss.channel - assert_equal(about, channel.about) - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(1, channel.items.Seq.lis.size) - assert_nil(channel.image) - assert_nil(channel.textinput) - - rss = RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - - setup_dummy_image(maker) - - setup_dummy_textinput(maker) - - setup_dummy_item(maker) - end - channel = rss.channel - assert_equal(about, channel.about) - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(1, channel.items.Seq.lis.size) - assert_equal(rss.image.about, channel.image.resource) - assert_equal(rss.textinput.about, channel.textinput.resource) - end - - def test_channel_language - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - - rss = RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - - setup_dummy_item(maker) - end - channel = rss.channel - assert_equal(language, channel.dc_language) - end - - def test_not_valid_channel - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - - assert_not_set_error("maker.channel", %w(about)) do - RSS::Maker.make("1.0") do |maker| - # maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - end - end - - assert_not_set_error("maker.channel", %w(title)) do - RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - # maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - end - end - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - # maker.channel.link = link - maker.channel.description = description - end - end - - assert_not_set_error("maker.channel", %w(description)) do - RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - # maker.channel.description = description - end - end - end - - - def test_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - - setup_dummy_item(maker) - end - image = rss.image - assert_equal(url, image.about) - assert_equal(url, rss.channel.image.resource) - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - - assert_not_set_error("maker.channel", %w(about title description)) do - RSS::Maker.make("1.0") do |maker| - # setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - end - end - end - - def test_not_valid_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - # maker.image.url = url - maker.image.title = title - - setup_dummy_item(maker) - end - assert_nil(rss.channel.image) - assert_nil(rss.image) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.url = url - # maker.image.title = title - - setup_dummy_item(maker) - end - assert_nil(rss.channel.image) - assert_nil(rss.image) - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - # maker.channel.link = link - maker.channel.link = nil - - maker.image.url = url - maker.image.title = title - - setup_dummy_item(maker) - end - end - end - - def test_items(with_convenience_way=true) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - - assert_not_set_error("maker", %w(items)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - end - end - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - item.title = title - item.link = link - # item.description = description - end - end - assert_equal(1, rss.items.size) - item = rss.items.first - assert_equal(link, item.about) - assert_equal(title, item.title) - assert_equal(link, item.link) - assert_nil(item.description) - - pubDate = Time.now - - item_size = 5 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - _item.date = pubDate - i - end - end - maker.items.do_sort = true - end - assert_equal(item_size, rss.items.size) - rss.items.each_with_index do |_item, i| - assert_equal("#{link}#{i}", _item.about) - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - end - end - maker.items.do_sort = Proc.new do |x, y| - if with_convenience_way - y.title[-1] <=> x.title[-1] - else - y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]} - end - end - end - assert_equal(item_size, rss.items.size) - rss.items.reverse.each_with_index do |_item, i| - assert_equal("#{link}#{i}", _item.about) - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - - max_size = item_size / 2 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - end - end - maker.items.max_size = max_size - end - assert_equal(max_size, rss.items.size) - rss.items.each_with_index do |_item, i| - assert_equal("#{link}#{i}", _item.about) - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - - max_size = 0 - assert_not_set_error("maker", %w(items)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - end - end - maker.items.max_size = max_size - end - end - - max_size = -2 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |_item| - _item.title = "#{title}#{i}" - _item.link = "#{link}#{i}" - _item.description = "#{description}#{i}" - end - end - maker.items.max_size = max_size - end - assert_equal(item_size + max_size + 1, rss.items.size) - rss.items.each_with_index do |_item, i| - assert_equal("#{link}#{i}", _item.about) - assert_equal("#{title}#{i}", _item.title) - assert_equal("#{link}#{i}", _item.link) - assert_equal("#{description}#{i}", _item.description) - end - end - - def test_items_with_new_api_since_018 - test_items(false) - end - - def test_not_valid_items - title = "TITLE" - link = "http://hoge.com/" - - assert_not_set_error("maker.item", %w(title)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - # item.title = title - item.link = link - end - end - end - - assert_not_set_error("maker.item", %w(link)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - item.title = title - # item.link = link - end - end - end - - assert_not_set_error("maker.item", %w(title link)) do - RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - # item.title = title - # item.link = link - end - end - end - end - - def test_textinput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.link = link - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - - setup_dummy_item(maker) - end - textinput = rss.textinput - assert_equal(link, textinput.about) - assert_equal(link, rss.channel.textinput.resource) - assert_equal(title, textinput.title) - assert_equal(name, textinput.name) - assert_equal(description, textinput.description) - assert_equal(link, textinput.link) - - assert_not_set_error("maker.channel", %w(about link description title)) do - RSS::Maker.make("1.0") do |maker| - # setup_dummy_channel(maker) - - maker.textinput.link = link - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - end - end - end - - def test_not_valid_textinput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - # maker.textinput.link = link - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - - setup_dummy_item(maker) - end - assert_nil(rss.channel.textinput) - assert_nil(rss.textinput) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.link = link - # maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - - setup_dummy_item(maker) - end - assert_nil(rss.channel.textinput) - assert_nil(rss.textinput) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.link = link - maker.textinput.title = title - # maker.textinput.description = description - maker.textinput.name = name - - setup_dummy_item(maker) - end - assert_nil(rss.channel.textinput) - assert_nil(rss.textinput) - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.link = link - maker.textinput.title = title - maker.textinput.description = description - # maker.textinput.name = name - - setup_dummy_item(maker) - end - assert_nil(rss.channel.textinput) - assert_nil(rss.textinput) - end - - end -end diff --git a/ruby/test/rss/test_maker_2.0.rb b/ruby/test/rss/test_maker_2.0.rb deleted file mode 100644 index f6d83f0c3..000000000 --- a/ruby/test/rss/test_maker_2.0.rb +++ /dev/null @@ -1,758 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMaker20 < TestCase - def test_supported? - assert(RSS::Maker.supported?("2.0")) - assert(RSS::Maker.supported?("rss2.0")) - assert(!RSS::Maker.supported?("2.2")) - assert(!RSS::Maker.supported?("rss2.2")) - end - - def test_find_class - assert_equal(RSS::Maker::RSS20, RSS::Maker["2.0"]) - assert_equal(RSS::Maker::RSS20, RSS::Maker["rss2.0"]) - end - - def test_rss - assert_raise(LocalJumpError) do - RSS::Maker.make("2.0") - end - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - end - assert_equal("2.0", rss.rss_version) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.encoding = "EUC-JP" - end - assert_equal("2.0", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.standalone = "yes" - end - assert_equal("2.0", rss.rss_version) - assert_equal("yes", rss.standalone) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.encoding = "EUC-JP" - maker.standalone = "yes" - end - assert_equal("2.0", rss.rss_version) - assert_equal("EUC-JP", rss.encoding) - assert_equal("yes", rss.standalone) - end - - def test_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - copyright = "foo" - managingEditor = "bar" - webMaster = "web master" - rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))' - docs = "http://foo.com/doc" - skipDays = [ - "Sunday", - "Monday", - ] - skipHours = [ - "0", - "13", - ] - pubDate = Time.now - lastBuildDate = Time.now - categories = [ - "Nespapers", - "misc", - ] - generator = "RSS Maker" - ttl = "60" - - rss = RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - maker.channel.copyright = copyright - maker.channel.managingEditor = managingEditor - maker.channel.webMaster = webMaster - maker.channel.rating = rating - maker.channel.docs = docs - maker.channel.pubDate = pubDate - maker.channel.lastBuildDate = lastBuildDate - - skipDays.each do |day| - maker.channel.skipDays.new_day do |new_day| - new_day.content = day - end - end - skipHours.each do |hour| - maker.channel.skipHours.new_hour do |new_hour| - new_hour.content = hour - end - end - - categories.each do |category| - maker.channel.categories.new_category do |new_category| - new_category.content = category - end - end - - maker.channel.generator = generator - maker.channel.ttl = ttl - end - channel = rss.channel - - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(language, channel.language) - assert_equal(copyright, channel.copyright) - assert_equal(managingEditor, channel.managingEditor) - assert_equal(webMaster, channel.webMaster) - assert_equal(rating, channel.rating) - assert_equal(docs, channel.docs) - assert_equal(pubDate, channel.pubDate) - assert_equal(pubDate, channel.date) - assert_equal(lastBuildDate, channel.lastBuildDate) - - skipDays.each_with_index do |day, i| - assert_equal(day, channel.skipDays.days[i].content) - end - skipHours.each_with_index do |hour, i| - assert_equal(hour.to_i, channel.skipHours.hours[i].content) - end - - channel.categories.each_with_index do |category, i| - assert_equal(categories[i], category.content) - end - - assert_equal(generator, channel.generator) - assert_equal(ttl.to_i, channel.ttl) - - assert(channel.items.empty?) - assert_nil(channel.image) - assert_nil(channel.textInput) - end - - def test_not_valid_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - - assert_not_set_error("maker.channel", %w(title)) do - RSS::Maker.make("2.0") do |maker| - # maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - end - end - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - # maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - end - end - - assert_not_set_error("maker.channel", %w(description)) do - RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - maker.channel.link = link - # maker.channel.description = description - maker.channel.language = language - end - end - - rss = RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - # maker.channel.language = language - end - assert_not_nil(rss) - end - - - def test_cloud - domain = "rpc.sys.com" - port = "80" - path = "/RPC2" - registerProcedure = "myCloud.rssPleaseNotify" - protocol = "xml-rpc" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.channel.cloud.domain = domain - maker.channel.cloud.port = port - maker.channel.cloud.path = path - maker.channel.cloud.registerProcedure = registerProcedure - maker.channel.cloud.protocol = protocol - end - cloud = rss.channel.cloud - assert_equal(domain, cloud.domain) - assert_equal(port.to_i, cloud.port) - assert_equal(path, cloud.path) - assert_equal(registerProcedure, cloud.registerProcedure) - assert_equal(protocol, cloud.protocol) - end - - def test_not_valid_cloud - domain = "rpc.sys.com" - port = "80" - path = "/RPC2" - registerProcedure = "myCloud.rssPleaseNotify" - protocol = "xml-rpc" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - # maker.channel.cloud.domain = domain - maker.channel.cloud.port = port - maker.channel.cloud.path = path - maker.channel.cloud.registerProcedure = registerProcedure - maker.channel.cloud.protocol = protocol - end - assert_nil(rss.channel.cloud) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.channel.cloud.domain = domain - # maker.channel.cloud.port = port - maker.channel.cloud.path = path - maker.channel.cloud.registerProcedure = registerProcedure - maker.channel.cloud.protocol = protocol - end - assert_nil(rss.channel.cloud) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.channel.cloud.domain = domain - maker.channel.cloud.port = port - # maker.channel.cloud.path = path - maker.channel.cloud.registerProcedure = registerProcedure - maker.channel.cloud.protocol = protocol - end - assert_nil(rss.channel.cloud) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.channel.cloud.domain = domain - maker.channel.cloud.port = port - maker.channel.cloud.path = path - # maker.channel.cloud.registerProcedure = registerProcedure - maker.channel.cloud.protocol = protocol - end - assert_nil(rss.channel.cloud) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.channel.cloud.domain = domain - maker.channel.cloud.port = port - maker.channel.cloud.path = path - maker.channel.cloud.registerProcedure = registerProcedure - # maker.channel.cloud.protocol = protocol - end - assert_nil(rss.channel.cloud) - end - - - def test_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - image = rss.image - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - assert_equal(width.to_i, image.width) - assert_equal(height.to_i, image.height) - assert_equal(description, image.description) - - assert_not_set_error("maker.channel", %w(title description)) do - RSS::Maker.make("2.0") do |maker| - # setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - end - - def test_not_valid_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - # maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - assert_nil(rss.image) - - assert_not_set_error("maker.channel", %w(link)) do - RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - # maker.channel.link = link - maker.channel.link = nil - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - end - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - # maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - assert_nil(rss.image) - end - - def test_items(with_convenience_way=true) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - author = "oprah@oxygen.net" - comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290" - pubDate = Time.now - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - end - assert(rss.channel.items.empty?) - - item_size = 5 - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.author = "#{author}#{i}" - item.comments = "#{comments}#{i}" - item.date = pubDate - i - end - end - maker.items.do_sort = true - end - assert_equal(item_size, rss.items.size) - rss.channel.items.each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - assert_equal("#{author}#{i}", item.author) - assert_equal("#{comments}#{i}", item.comments) - assert_equal(pubDate - i, item.pubDate) - assert_equal(pubDate - i, item.date) - end - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.author = "#{author}#{i}" - item.comments = "#{comments}#{i}" - item.date = pubDate - end - end - maker.items.do_sort = Proc.new do |x, y| - if with_convenience_way - y.title[-1] <=> x.title[-1] - else - y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]} - end - end - end - assert_equal(item_size, rss.items.size) - rss.channel.items.reverse.each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - assert_equal("#{author}#{i}", item.author) - assert_equal("#{comments}#{i}", item.comments) - assert_equal(pubDate, item.pubDate) - assert_equal(pubDate, item.date) - end - end - - def test_items_with_new_api_since_018 - test_items(false) - end - - def test_pubDate_without_description - title = "TITLE" - link = "http://hoge.com/" - # description = "text hoge fuga" - author = "oprah@oxygen.net" - pubDate = Time.now - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.items.new_item do |item| - item.title = title - item.link = link - # item.description = description - item.author = author - item.pubDate = pubDate - end - end - assert_equal(1, rss.items.size) - rss.channel.items.each_with_index do |item, i| - assert_equal(title, item.title) - assert_equal(link, item.link) - # assert_equal(description, item.description) - assert_equal(author, item.author) - assert_equal(pubDate, item.pubDate) - assert_equal(pubDate, item.date) - end - end - - def test_guid - isPermaLink = "true" - content = "http://inessential.com/2002/09/01.php#a2" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - guid = maker.items.last.guid - guid.isPermaLink = isPermaLink - guid.content = content - end - guid = rss.channel.items.last.guid - assert_equal(isPermaLink == "true", guid.isPermaLink) - assert_equal(content, guid.content) - end - - def test_guid_permanent_link - content = "http://inessential.com/2002/09/01.php#a2" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - guid = maker.items.last.guid - assert_equal(nil, guid.permanent_link?) - assert_equal(guid.isPermaLink, guid.permanent_link?) - guid.permanent_link = true - assert_equal(true, guid.permanent_link?) - assert_equal(guid.isPermaLink, guid.permanent_link?) - guid.content = content - end - guid = rss.channel.items.last.guid - assert_equal(true, guid.isPermaLink) - assert_equal(content, guid.content) - end - - def test_guid_permanent_link_false - content = "http://inessential.com/2002/09/01.php#a2" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - guid = maker.items.last.guid - assert_equal(nil, guid.permanent_link?) - assert_equal(guid.isPermaLink, guid.permanent_link?) - guid.permanent_link = false - assert_equal(false, guid.permanent_link?) - assert_equal(guid.isPermaLink, guid.permanent_link?) - guid.content = content - end - guid = rss.channel.items.last.guid - assert_equal(false, guid.isPermaLink) - assert_equal(content, guid.content) - end - - def test_not_valid_guid - # content = "http://inessential.com/2002/09/01.php#a2" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - # guid = maker.items.last.guid - # guid.content = content - end - assert_nil(rss.channel.items.last.guid) - end - - def test_enclosure - url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3" - length = "12216320" - type = "audio/mpeg" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - enclosure = maker.items.last.enclosure - enclosure.url = url - enclosure.length = length - enclosure.type = type - end - enclosure = rss.channel.items.last.enclosure - assert_equal(url, enclosure.url) - assert_equal(length.to_i, enclosure.length) - assert_equal(type, enclosure.type) - end - - def test_not_valid_enclosure - url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3" - length = "12216320" - type = "audio/mpeg" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - enclosure = maker.items.last.enclosure - # enclosure.url = url - enclosure.length = length - enclosure.type = type - end - assert_nil(rss.channel.items.last.enclosure) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - enclosure = maker.items.last.enclosure - enclosure.url = url - # enclosure.length = length - enclosure.type = type - end - assert_nil(rss.channel.items.last.enclosure) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - enclosure = maker.items.last.enclosure - enclosure.url = url - enclosure.length = length - # enclosure.type = type - end - assert_nil(rss.channel.items.last.enclosure) - end - - - def test_source - url = "http://static.userland.com/tomalak/links2.xml" - content = "Tomalak's Realm" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - source = maker.items.last.source - source.url = url - source.content = content - end - source = rss.channel.items.last.source - assert_equal(url, source.url) - assert_equal(content, source.content) - end - - def test_not_valid_source - url = "http://static.userland.com/tomalak/links2.xml" - content = "Tomalak's Realm" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - source = maker.items.last.source - # source.url = url - source.content = content - end - assert_nil(rss.channel.items.last.source) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - source = maker.items.last.source - source.url = url - # source.content = content - end - assert_nil(rss.channel.items.last.source) - end - - def test_category - domain = "http://www.fool.com/cusips" - content = "MSFT" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - maker.items.last.categories.new_category do |category| - category.domain = domain - category.content = content - end - end - category = rss.channel.items.last.categories.last - assert_equal(domain, category.domain) - assert_equal(content, category.content) - end - - def test_not_valid_category - # content = "Grateful Dead" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - maker.items.last.categories.new_category do |category| - # category.content = content - end - end - assert(rss.channel.items.last.categories.empty?) - end - - def test_textInput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - textInput = rss.channel.textInput - assert_equal(title, textInput.title) - assert_equal(description, textInput.description) - assert_equal(name, textInput.name) - assert_equal(link, textInput.link) - - assert_not_set_error("maker.channel", %w(link description title)) do - RSS::Maker.make("2.0") do |maker| - # setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - end - end - - def test_not_valid_textInput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - # maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.title = title - # maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - # maker.textinput.name = name - maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - # maker.textinput.link = link - end - assert_nil(rss.channel.textInput) - end - end -end diff --git a/ruby/test/rss/test_maker_atom_entry.rb b/ruby/test/rss/test_maker_atom_entry.rb deleted file mode 100644 index 8e41c7c50..000000000 --- a/ruby/test/rss/test_maker_atom_entry.rb +++ /dev/null @@ -1,394 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerAtomEntry < TestCase - def test_supported? - assert(RSS::Maker.supported?("atom:entry")) - assert(RSS::Maker.supported?("atom1.0:entry")) - assert(!RSS::Maker.supported?("atom2.0:entry")) - end - - def test_find_class - assert_equal(RSS::Maker::Atom::Entry, RSS::Maker["atom:entry"]) - assert_equal(RSS::Maker::Atom::Entry, RSS::Maker["atom1.0:entry"]) - end - - def test_root_element - entry = Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - assert_equal(["atom", "1.0", "entry"], entry.feed_info) - - entry = Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.encoding = "EUC-JP" - end - assert_equal(["atom", "1.0", "entry"], entry.feed_info) - assert_equal("EUC-JP", entry.encoding) - - entry = Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.standalone = "yes" - end - assert_equal(["atom", "1.0", "entry"], entry.feed_info) - assert_equal("yes", entry.standalone) - - entry = Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.encoding = "EUC-JP" - maker.standalone = "yes" - end - assert_equal(["atom", "1.0", "entry"], entry.feed_info) - assert_equal("EUC-JP", entry.encoding) - assert_equal("yes", entry.standalone) - end - - def test_invalid_feed - assert_not_set_error("maker.item", %w(id title author updated)) do - Maker.make("atom:entry") do |maker| - end - end - - assert_not_set_error("maker.item", %w(id title updated)) do - Maker.make("atom:entry") do |maker| - maker.channel.author = "foo" - end - end - - assert_not_set_error("maker.item", %w(title updated)) do - Maker.make("atom:entry") do |maker| - maker.channel.author = "foo" - maker.channel.id = "http://example.com" - end - end - - assert_not_set_error("maker.item", %w(updated)) do - Maker.make("atom:entry") do |maker| - maker.channel.author = "foo" - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - end - end - - assert_not_set_error("maker.item", %w(author)) do - Maker.make("atom:entry") do |maker| - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - maker.channel.updated = Time.now - end - end - - entry = Maker.make("atom:entry") do |maker| - maker.channel.author = "Foo" - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - maker.channel.updated = Time.now - end - assert_not_nil(entry) - end - - def test_author - assert_maker_atom_persons("entry", - ["channel", "authors"], - ["authors"], - "maker.channel.author") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_persons("entry", - ["items", "first", "authors"], - ["authors"], - "maker.item.author", - "maker.item", ["author"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.authors.clear - maker.items.first.authors.clear - end - - assert_maker_atom_persons("entry", - ["items", "first", "source", "authors"], - ["source", "authors"], - "maker.item.source.author") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_category - assert_maker_atom_categories("entry", - ["channel", "categories"], - ["categories"], - "maker.channel.category") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_categories("entry", - ["items", "first", "categories"], - ["categories"], - "maker.item.category") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_categories("entry", - ["items", "first", "source", "categories"], - ["source", "categories"], - "maker.item.source.category") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_content - assert_maker_atom_content("entry", - ["items", "first", "content"], - ["content"], - "maker.item.content") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_contributor - assert_maker_atom_persons("entry", - ["channel", "contributors"], - ["contributors"], - "maker.channel.contributor") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_persons("entry", - ["items", "first", "contributors"], - ["contributors"], - "maker.item.contributor") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_persons("entry", - ["items", "first", "source", "contributors"], - ["source", "contributors"], - "maker.item.source.contributor") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_link - assert_maker_atom_links("entry", - ["channel", "links"], - ["links"], - "maker.channel.link") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.links.clear - maker.items.first.links.clear - end - - assert_maker_atom_links("entry", - ["items", "first", "links"], - ["links"], - "maker.item.link") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.links.clear - maker.items.first.links.clear - end - - assert_maker_atom_links("entry", - ["items", "first", "source", "links"], - ["source", "links"], - "maker.item.source.link", true) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_published - assert_maker_atom_date_construct("entry", - ["items", "first", "published"], - ["published"] - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_rights - assert_maker_atom_text_construct("entry", - ["channel", "copyright"], - ["rights"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_text_construct("entry", - ["items", "first", "rights"], - ["rights"], - nil, nil, "maker.item.rights" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_text_construct("entry", - ["items", "first", "source", "rights"], - ["source", "rights"], - nil, nil, "maker.item.source.rights" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - - def test_source_generator - assert_maker_atom_generator("entry", - ["items", "first", "source", "generator"], - ["source", "generator"], - "maker.item.source.generator") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_source_icon - assert_maker_atom_icon("entry", - ["items", "first", "source", "icon"], - ["source", "icon"], - nil, "maker.item.source.icon") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_source_id - assert_maker_atom_id("entry", - ["items", "first", "source"], - ["source"], - "maker.item.source") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_source_logo - assert_maker_atom_logo("entry", - ["items", "first", "source", "logo"], - ["source", "logo"], - nil, - "maker.item.source.logo") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_source_subtitle - assert_maker_atom_text_construct("entry", - ["items", "first", "source", "subtitle"], - ["source", "subtitle"], - nil, nil, - "maker.item.source.subtitle") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_summary - assert_maker_atom_text_construct("entry", - ["items", "first", "description"], - ["summary"], - nil, nil, "maker.item.description" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_title - assert_maker_atom_text_construct("entry", - ["channel", "title"], ["title"], - "maker.item", ["title"], - "maker.channel.title") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.title = nil - maker.items.first.title = nil - end - - assert_maker_atom_text_construct("entry", - ["items", "first", "title"], - ["title"], - "maker.item", ["title"], - "maker.item.title") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.title = nil - maker.items.first.title = nil - end - - assert_maker_atom_text_construct("entry", - ["items", "first", "source", "title"], - ["source", "title"], - nil, nil, "maker.item.source.title" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_updated - assert_maker_atom_date_construct("entry", - ["channel", "updated"], ["updated"], - "maker.item", ["updated"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.updated = nil - maker.items.first.updated = nil - end - - assert_maker_atom_date_construct("entry", - ["items", "first", "updated"], - ["updated"], - "maker.item", ["updated"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.updated = nil - maker.items.first.updated = nil - end - - assert_maker_atom_date_construct("entry", - ["items", "first", "source", "updated"], - ["source", "updated"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_date - date = Time.parse("2004/11/1 10:10") - feed = Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - maker.channel.date = nil - maker.items.new_item do |item| - item.link = "http://example.com/article.html" - item.title = "Sample Article" - item.date = date - end - end - assert_equal(date, feed.items[0].updated.content) - assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value}) - end - end -end diff --git a/ruby/test/rss/test_maker_atom_feed.rb b/ruby/test/rss/test_maker_atom_feed.rb deleted file mode 100644 index d4eacd36a..000000000 --- a/ruby/test/rss/test_maker_atom_feed.rb +++ /dev/null @@ -1,455 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerAtomFeed < TestCase - def test_supported? - assert(RSS::Maker.supported?("atom")) - assert(RSS::Maker.supported?("atom:feed")) - assert(RSS::Maker.supported?("atom1.0")) - assert(RSS::Maker.supported?("atom1.0:feed")) - assert(!RSS::Maker.supported?("atom2.0")) - assert(!RSS::Maker.supported?("atom2.0:feed")) - end - - def test_find_class - assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom"]) - assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom:feed"]) - assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom1.0"]) - assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom1.0:feed"]) - end - - def test_root_element - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - end - assert_equal(["atom", "1.0", "feed"], feed.feed_info) - - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.encoding = "EUC-JP" - end - assert_equal(["atom", "1.0", "feed"], feed.feed_info) - assert_equal("EUC-JP", feed.encoding) - - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.standalone = "yes" - end - assert_equal(["atom", "1.0", "feed"], feed.feed_info) - assert_equal("yes", feed.standalone) - - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.encoding = "EUC-JP" - maker.standalone = "yes" - end - assert_equal(["atom", "1.0", "feed"], feed.feed_info) - assert_equal("EUC-JP", feed.encoding) - assert_equal("yes", feed.standalone) - end - - def test_invalid_feed - assert_not_set_error("maker.channel", %w(id title author updated)) do - Maker.make("atom") do |maker| - end - end - - assert_not_set_error("maker.channel", %w(id title updated)) do - Maker.make("atom") do |maker| - maker.channel.author = "foo" - end - end - - assert_not_set_error("maker.channel", %w(title updated)) do - Maker.make("atom") do |maker| - maker.channel.author = "foo" - maker.channel.id = "http://example.com" - end - end - - assert_not_set_error("maker.channel", %w(updated)) do - Maker.make("atom") do |maker| - maker.channel.author = "foo" - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - end - end - - assert_not_set_error("maker.channel", %w(author)) do - Maker.make("atom") do |maker| - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - maker.channel.updated = Time.now - end - end - - feed = Maker.make("atom") do |maker| - maker.channel.author = "Foo" - maker.channel.id = "http://example.com" - maker.channel.title = "Atom Feed" - maker.channel.updated = Time.now - end - assert_not_nil(feed) - end - - def test_author - assert_maker_atom_persons("feed", - ["channel", "authors"], - ["authors"], - "maker.channel.author") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_not_set_error("maker.channel", %w(author)) do - RSS::Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.channel.authors.clear - end - end - - assert_maker_atom_persons("feed", - ["items", "first", "authors"], - ["entries", "first", "authors"], - "maker.item.author") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_persons("feed", - ["items", "first", "source", "authors"], - ["entries", "first", "source", "authors"], - "maker.item.source.author") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_category - assert_maker_atom_categories("feed", - ["channel", "categories"], - ["categories"], - "maker.channel.category") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_categories("feed", - ["items", "first", "categories"], - ["entries", "first", "categories"], - "maker.item.category") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_categories("feed", - ["items", "first", "source", "categories"], - ["entries", "first", "source", "categories"], - "maker.item.source.category") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_contributor - assert_maker_atom_persons("feed", - ["channel", "contributors"], - ["contributors"], - "maker.channel.contributor") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_persons("feed", - ["items", "first", "contributors"], - ["entries", "first", "contributors"], - "maker.item.contributor") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_persons("feed", - ["items", "first", "source", "contributors"], - ["entries", "first", "source", "contributors"], - "maker.item.source.contributor") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_generator - assert_maker_atom_generator("feed", - ["channel", "generator"], - ["generator"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_generator("feed", - ["items", "first", "source", "generator"], - ["entries", "first", "source", "generator"], - "maker.item.source.generator") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_icon - assert_maker_atom_icon("feed", ["channel"], ["icon"], "icon") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_icon("feed", - ["items", "first", "source", "icon"], - ["entries", "first", "source", "icon"], - nil, "maker.item.source.icon") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_link - assert_maker_atom_links("feed", - ["channel", "links"], - ["links"], - "maker.channel.link") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_links("feed", - ["items", "first", "links"], - ["entries", "first", "links"], - "maker.item.link") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_links("feed", - ["items", "first", "source", "links"], - ["entries", "first", "source", "links"], - "maker.item.source.link", true) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_logo - assert_maker_atom_logo("feed", ["channel"], ["logo"], "logo") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_logo("feed", ["image"], ["logo"], "url") do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_logo("feed", - ["items", "first", "source", "logo"], - ["entries", "first", "source", "logo"], - nil, "maker.item.source.logo") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_rights - assert_maker_atom_text_construct("feed", - ["channel", "copyright"], - ["rights"]) do |maker| - setup_dummy_channel_atom(maker) - end - - assert_maker_atom_text_construct("feed", - ["items", "first", "rights"], - ["entries", "first", "rights"], - nil, nil, "maker.item.rights" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - - assert_maker_atom_text_construct("feed", - ["items", "first", "source", "rights"], - ["entries", "first", "source", "rights"], - nil, nil, "maker.item.source.rights" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_subtitle - assert_maker_atom_text_construct("feed", - ["channel", "subtitle"], - ["subtitle"], - nil, nil, - "maker.channel.description") do |maker| - setup_dummy_channel_atom(maker) - maker.channel.description = nil - end - - assert_maker_atom_text_construct("feed", - ["channel", "subtitle"], - ["subtitle"], - nil, nil, - "maker.channel.description") do |maker| - setup_dummy_channel_atom(maker) - maker.channel.description {|d| d.content = nil} - end - - assert_maker_atom_text_construct("feed", - ["items", "first", "source", "subtitle"], - ["entries", "first", - "source", "subtitle"], - nil, nil, - "maker.item.source.subtitle") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_title - assert_maker_atom_text_construct("feed", - ["channel", "title"], ["title"], - "maker.channel", ["title"]) do |maker| - setup_dummy_channel_atom(maker) - maker.channel.title = nil - end - - assert_maker_atom_text_construct("feed", - ["items", "first", "title"], - ["entries", "first", "title"], - "maker.item", ["title"], - "maker.item.title") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.items.first.title = nil - end - - assert_maker_atom_text_construct("feed", - ["items", "first", "source", "title"], - ["entries", "first", "source", "title"], - nil, nil, "maker.item.source.title" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_updated - assert_maker_atom_date_construct("feed", - ["channel", "updated"], ["updated"], - "maker.channel", ["updated"]) do |maker| - setup_dummy_channel_atom(maker) - maker.channel.updated = nil - end - - assert_maker_atom_date_construct("feed", - ["items", "first", "updated"], - ["entries", "first", "updated"], - "maker.item", ["updated"]) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - maker.items.first.updated = nil - end - - assert_maker_atom_date_construct("feed", - ["items", "first", "source", "updated"], - ["entries", "first", "source", "updated"] - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_published - assert_maker_atom_date_construct("feed", - ["items", "first", "published"], - ["entries", "first", "published"] - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_summary - assert_maker_atom_text_construct("feed", - ["items", "first", "description"], - ["entries", "first", "summary"], - nil, nil, "maker.item.description" - ) do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_content - assert_maker_atom_content("feed", - ["items", "first", "content"], - ["entries", "first", "content"], - "maker.item.content") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_id - assert_maker_atom_id("feed", - ["items", "first", "source"], - ["entries", "first", "source"], - "maker.item.source") do |maker| - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - end - - def test_language - language = "ja" - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.channel.language = "ja" - end - assert_equal(language, feed.dc_language) - end - - def test_date - date = Time.parse("2004/11/1 10:10") - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.items.new_item do |item| - item.link = "http://example.com/article.html" - item.title = "sample article" - item.date = date - end - end - assert_equal(date, feed.items[0].updated.content) - assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value}) - end - - def test_channel_dc_date - date = Time.parse("2004/11/1 10:10") - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.channel.updated = nil - maker.channel.dc_date = date - setup_dummy_item_atom(maker) - end - assert_equal(date, feed.updated.content) - assert_equal([date], feed.dc_dates.collect {|_date| _date.value}) - end - - def test_item_dc_date - date = Time.parse("2004/11/1 10:10") - feed = Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - maker.items.new_item do |item| - item.link = "http://example.com/article.html" - item.title = "sample article" - item.dc_date = date - end - end - assert_equal(date, feed.items[0].updated.content) - assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value}) - end - end -end diff --git a/ruby/test/rss/test_maker_content.rb b/ruby/test/rss/test_maker_content.rb deleted file mode 100644 index e3b84c53a..000000000 --- a/ruby/test/rss/test_maker_content.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerContent < TestCase - - def setup - @uri = "http://purl.org/rss/1.0/modules/content/" - - @elements = { - :encoded => "ATTENTION", - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - setup_dummy_item(maker) - item = maker.items.last - @elements.each do |name, value| - item.__send__("#{accessor_name(name)}=", value) - end - end - assert_content(@elements, rss.items.last) - end - - def test_rss20 - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - setup_dummy_item(maker) - item = maker.items.last - @elements.each do |name, value| - item.__send__("#{accessor_name(name)}=", value) - end - end - assert_content(@elements, rss.items.last) - end - - private - def accessor_name(name) - "content_#{name}" - end - end -end diff --git a/ruby/test/rss/test_maker_dc.rb b/ruby/test/rss/test_maker_dc.rb deleted file mode 100644 index f5c8bad2b..000000000 --- a/ruby/test/rss/test_maker_dc.rb +++ /dev/null @@ -1,150 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerDublinCore < TestCase - - def setup - @uri = "http://purl.org/dc/elements/1.1/" - - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @elements = { - :title => "hoge", - :description => - " XML is placing increasingly heavy loads on - the existing technical infrastructure of the Internet.", - :creator => "Rael Dornfest (mailto:rael@oreilly.com)", - :subject => "XML", - :publisher => "The O'Reilly Network", - :contributor => "hogehoge", - :type => "fugafuga", - :format => "hohoho", - :identifier => "fufufu", - :source => "barbar", - :language => "ja", - :relation => "cococo", - :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", - :date => t, - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - set_elements(maker.channel) - - setup_dummy_image(maker) - set_elements(maker.image) - - setup_dummy_item(maker) - item = maker.items.last - @elements.each do |name, value| - item.__send__("#{accessor_name(name)}=", value) - end - - setup_dummy_textinput(maker) - set_elements(maker.textinput) - end - assert_dublin_core(@elements, rss.channel) - assert_dublin_core(@elements, rss.image) - assert_dublin_core(@elements, rss.items.last) - assert_dublin_core(@elements, rss.textinput) - end - - def test_rss10_multiple - assert_multiple_dublin_core_rss10("_list") - assert_multiple_dublin_core_rss10("es") - end - - def assert_multiple_dublin_core_rss10(multiple_rights_suffix) - elems = [] - @elements.each do |name, value| - plural = name.to_s + (name == :rights ? multiple_rights_suffix : "s") - values = [value] - if name == :date - values << value + 60 - else - values << value * 2 - end - elems << [name, values, plural] - end - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - set_multiple_elements(maker.channel, elems) - - setup_dummy_image(maker) - set_multiple_elements(maker.image, elems) - - setup_dummy_item(maker) - item = maker.items.last - elems.each do |name, values, plural| - dc_elems = item.__send__("dc_#{plural}") - values.each do |value| - elem = dc_elems.__send__("new_#{name}") - elem.value = value - end - end - - setup_dummy_textinput(maker) - set_multiple_elements(maker.textinput, elems) - end - assert_multiple_dublin_core(elems, rss.channel) - assert_multiple_dublin_core(elems, rss.image) - assert_multiple_dublin_core(elems, rss.items.last) - assert_multiple_dublin_core(elems, rss.textinput) - end - - def test_date - t1 = Time.iso8601("2000-01-01T12:00:05+00:00") - t2 = Time.iso8601("2005-01-01T12:00:05+00:00") - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.date = t1 - maker.channel.dc_dates.new_date do |date| - date.value = t2 - end - - setup_dummy_item(maker) - item = maker.items.last - item.date = t2 - item.dc_dates.new_date do |date| - date.value = t1 - end - end - assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value}) - assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value}) - end - - private - def accessor_name(name) - "dc_#{name}" - end - - def set_elements(target, elems=@elements) - elems.each do |name, value| - target.__send__("#{accessor_name(name)}=", value) - end - end - - def set_multiple_elements(target, elems) - elems.each do |name, values, plural| - plural ||= "#{name}s" - dc_elems = target.__send__("dc_#{plural}") - values.each do |value| - dc_elems.__send__("new_#{name}") do |new_dc_elem| - new_dc_elem.value = value - end - end - end - end - - end -end diff --git a/ruby/test/rss/test_maker_image.rb b/ruby/test/rss/test_maker_image.rb deleted file mode 100644 index cc663c6a5..000000000 --- a/ruby/test/rss/test_maker_image.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerImage < TestCase - - def setup - @uri = "http://web.resource.org/rss/1.0/modules/image/" - - @favicon_infos = { - "about" => "http://www.kuro5hin.org/favicon.ico", - "image_size" => "small", - "dc_title" => "example", - } - @item_infos = { - "about" => "http://www.example.org/item.png", - "resource" => "http://www.example.org/item", - "dc_title" => "Example Image", - "image_width" => "100", - "image_height" => "65", - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - @favicon_infos.each do |name, value| - maker.channel.image_favicon.__send__("#{name}=", value) - end - - setup_dummy_image(maker) - - setup_dummy_item(maker) - item = maker.items.last - @item_infos.each do |name, value| - item.image_item.__send__("#{name}=", value) - end - - setup_dummy_textinput(maker) - end - - setup_rss = RSS::Maker.make("1.0") do |maker| - rss.setup_maker(maker) - end - - [rss, setup_rss].each_with_index do |target, i| - favicon = target.channel.image_favicon - assert_equal(@favicon_infos["about"], favicon.about) - assert_equal(@favicon_infos["image_size"], favicon.image_size) - assert_equal(@favicon_infos["dc_title"], favicon.dc_title) - - item = target.items.last.image_item - assert_equal(@item_infos["about"], item.about) - assert_equal(@item_infos["resource"], item.resource) - assert_equal(@item_infos["image_width"].to_i, item.image_width) - assert_equal(@item_infos["image_height"].to_i, item.image_height) - assert_equal(@item_infos["dc_title"], item.dc_title) - end - end - end -end diff --git a/ruby/test/rss/test_maker_itunes.rb b/ruby/test/rss/test_maker_itunes.rb deleted file mode 100644 index cba612c09..000000000 --- a/ruby/test/rss/test_maker_itunes.rb +++ /dev/null @@ -1,487 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerITunes < TestCase - def test_author - assert_maker_itunes_author(%w(channel)) - assert_maker_itunes_author(%w(items last)) - end - - def test_block - assert_maker_itunes_block(%w(channel)) - assert_maker_itunes_block(%w(items last)) - end - - def test_category - assert_maker_itunes_category(%w(channel)) - end - - def test_image - assert_maker_itunes_image(%w(channel)) - end - - def test_duration - assert_maker_itunes_duration(%w(items last)) - end - - def test_explicit - assert_maker_itunes_explicit(%w(channel)) - assert_maker_itunes_explicit(%w(items last)) - end - - def test_keywords - assert_maker_itunes_keywords(%w(channel)) - assert_maker_itunes_keywords(%w(items last)) - end - - def test_new_feed_url - assert_maker_itunes_new_feed_url(%w(channel)) - end - - def test_owner - assert_maker_itunes_owner(%w(channel)) - end - - def test_subtitle - assert_maker_itunes_subtitle(%w(channel)) - assert_maker_itunes_subtitle(%w(items last)) - end - - def test_summary - assert_maker_itunes_summary(%w(channel)) - assert_maker_itunes_summary(%w(items last)) - end - - private - - def assert_maker_itunes_author(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - author = "John Doe" - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_author = author - end - target = chain_reader(rss20, feed_readers) - assert_equal(author, target.itunes_author) - end - end - - def _assert_maker_itunes_block(value, boolean_value, maker_readers, - feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_block = value - assert_equal(value, target.itunes_block) - assert_equal(boolean_value, target.itunes_block?) - end - target = chain_reader(rss20, feed_readers) - if [true, false].include?(value) - value = value ? "yes" : "no" - end - assert_equal(value, target.itunes_block) - assert_equal(boolean_value, target.itunes_block?) - end - - def assert_maker_itunes_block(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_block("yes", true, maker_readers, feed_readers) - _assert_maker_itunes_block("Yes", true, maker_readers, feed_readers) - _assert_maker_itunes_block("no", false, maker_readers, feed_readers) - _assert_maker_itunes_block("", false, maker_readers, feed_readers) - _assert_maker_itunes_block(true, true, maker_readers, feed_readers) - _assert_maker_itunes_block(false, false, maker_readers, feed_readers) - _assert_maker_itunes_block(nil, false, maker_readers, feed_readers) - end - end - - def _assert_maker_itunes_category(categories, maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - categories.each do |category| - sub_target = target.itunes_categories - if category.is_a?(Array) - category.each do |sub_category| - sub_target = sub_target.new_category - sub_target.text = sub_category - end - else - sub_target.new_category.text = category - end - end - end - - target = chain_reader(rss20, feed_readers) - actual_categories = target.itunes_categories.collect do |category| - cat = category.text - if category.itunes_categories.empty? - cat - else - [cat, *category.itunes_categories.collect {|c| c.text}] - end - end - assert_equal(categories, actual_categories) - end - - def assert_maker_itunes_category(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_category(["Audio Blogs"], - maker_readers, feed_readers) - _assert_maker_itunes_category([["Arts & Entertainment", "Games"]], - maker_readers, feed_readers) - _assert_maker_itunes_category([["Arts & Entertainment", "Games"], - ["Technology", "Computers"], - "Audio Blogs"], - maker_readers, feed_readers) - end - end - - def assert_maker_itunes_image(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - url = "http://example.com/podcasts/everything/AllAboutEverything.jpg" - - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_image = url - end - - target = chain_reader(rss20, feed_readers) - assert_not_nil(target.itunes_image) - assert_equal(url, target.itunes_image.href) - end - end - - def _assert_maker_itunes_duration(hour, minute, second, value, - maker_readers, feed_readers) - _assert_maker_itunes_duration_by_value(hour, minute, second, value, - maker_readers, feed_readers) - _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second, - value, - maker_readers, - feed_readers) - end - - def _assert_maker_itunes_duration_by(hour, minute, second, value, - maker_readers, feed_readers) - expected_value = nil - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - expected_value = yield(target) - assert_equal(expected_value, target.itunes_duration) - target.itunes_duration do |duration| - assert_equal([hour, minute, second, expected_value], - [duration.hour, duration.minute, - duration.second, duration.content]) - end - end - target = chain_reader(rss20, feed_readers) - duration = target.itunes_duration - assert_not_nil(duration) - assert_equal([hour, minute, second, expected_value], - [duration.hour, duration.minute, - duration.second, duration.content]) - end - - def _assert_maker_itunes_duration_by_value(hour, minute, second, value, - maker_readers, feed_readers) - _assert_maker_itunes_duration_by(hour, minute, second, value, - maker_readers, feed_readers) do |target| - target.itunes_duration = value - value - end - end - - def _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second, - value, - maker_readers, - feed_readers) - _assert_maker_itunes_duration_by(hour, minute, second, value, - maker_readers, feed_readers) do |target| - target.itunes_duration do |duration| - duration.hour = hour - duration.minute = minute - duration.second = second - end - value.split(":").collect {|v| "%02d" % v.to_i}.join(":") - end - end - - def _assert_maker_itunes_duration_invalid_value(value, maker_readers) - assert_raise(ArgumentError) do - ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_duration = value - end - end - end - - def assert_maker_itunes_duration(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_duration(7, 14, 5, "07:14:05", maker_readers, - feed_readers) - _assert_maker_itunes_duration(7, 14, 5, "7:14:05", maker_readers, - feed_readers) - _assert_maker_itunes_duration(0, 4, 55, "04:55", maker_readers, - feed_readers) - _assert_maker_itunes_duration(0, 4, 5, "4:05", maker_readers, - feed_readers) - _assert_maker_itunes_duration(0, 0, 5, "0:05", maker_readers, - feed_readers) - _assert_maker_itunes_duration_by_value(0, 5, 15, "315", maker_readers, - feed_readers) - _assert_maker_itunes_duration_by_value(1, 0, 1, "3601", maker_readers, - feed_readers) - - _assert_maker_itunes_duration_invalid_value("09:07:14:05", maker_readers) - _assert_maker_itunes_duration_invalid_value("10:5", maker_readers) - _assert_maker_itunes_duration_invalid_value("10:03:5", maker_readers) - _assert_maker_itunes_duration_invalid_value("10:3:05", maker_readers) - - _assert_maker_itunes_duration_invalid_value("xx:xx:xx", maker_readers) - - _assert_maker_itunes_duration_invalid_value("", maker_readers) - end - end - - def _assert_maker_itunes_explicit(explicit, value, - maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_explicit = value - assert_equal(explicit, target.itunes_explicit?) - end - target = chain_reader(rss20, feed_readers) - assert_equal(value, target.itunes_explicit) - assert_equal(explicit, target.itunes_explicit?) - end - - def assert_maker_itunes_explicit(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_explicit(true, "explicit", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(true, "yes", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(true, "true", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(false, "clean", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(false, "no", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(false, "false", - maker_readers, feed_readers) - _assert_maker_itunes_explicit(nil, "invalid", - maker_readers, feed_readers) - end - end - - def _assert_maker_itunes_keywords(keywords, value, - maker_readers, feed_readers) - _assert_maker_itunes_keywords_by_value(keywords, value, - maker_readers, feed_readers) - _assert_maker_itunes_keywords_by_keywords(keywords, maker_readers, - feed_readers) - end - - def _assert_maker_itunes_keywords_by(keywords, maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - yield(target) - end - assert_nothing_raised do - rss20 = ::RSS::Parser.parse(rss20.to_s) - end - target = chain_reader(rss20, feed_readers) - assert_equal(keywords, target.itunes_keywords) - end - - def _assert_maker_itunes_keywords_by_value(keywords, value, - maker_readers, feed_readers) - _assert_maker_itunes_keywords_by(keywords, maker_readers, - feed_readers) do |target| - target.itunes_keywords = value - end - end - - def _assert_maker_itunes_keywords_by_keywords(keywords, - maker_readers, feed_readers) - _assert_maker_itunes_keywords_by(keywords, maker_readers, - feed_readers) do |target| - target.itunes_keywords = keywords - end - end - - def assert_maker_itunes_keywords(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_keywords(["salt"], "salt", - maker_readers, feed_readers) - _assert_maker_itunes_keywords(["salt"], " salt ", - maker_readers, feed_readers) - _assert_maker_itunes_keywords(["salt", "pepper", "shaker", "exciting"], - "salt, pepper, shaker, exciting", - maker_readers, feed_readers) - _assert_maker_itunes_keywords(["metric", "socket", "wrenches", - "toolsalt"], - "metric, socket, wrenches, toolsalt", - maker_readers, feed_readers) - _assert_maker_itunes_keywords(["olitics", "red", "blue", "state"], - "olitics, red, blue, state", - maker_readers, feed_readers) - end - end - - def assert_maker_itunes_new_feed_url(maker_readers, feed_readers=nil) - feed_readers ||= maker_readers - url = "http://newlocation.com/example.rss" - - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_new_feed_url = url - end - target = chain_reader(rss20, feed_readers) - assert_equal(url, target.itunes_new_feed_url) - end - - def _assert_maker_itunes_owner(name, email, maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - owner = target.itunes_owner - owner.itunes_name = name - owner.itunes_email = email - end - owner = chain_reader(rss20, feed_readers).itunes_owner - if name.nil? and email.nil? - assert_nil(owner) - else - assert_not_nil(owner) - assert_equal(name, owner.itunes_name) - assert_equal(email, owner.itunes_email) - end - end - - def assert_maker_itunes_owner(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_owner("John Doe", "john.doe@example.com", - maker_readers, feed_readers) - - not_set_name = (["maker"] + maker_readers + ["itunes_owner"]).join(".") - assert_not_set_error(not_set_name, ["itunes_name"]) do - _assert_maker_itunes_owner(nil, "john.doe@example.com", - maker_readers, feed_readers) - end - assert_not_set_error(not_set_name, ["itunes_email"]) do - _assert_maker_itunes_owner("John Doe", nil, - maker_readers, feed_readers) - end - - _assert_maker_itunes_owner(nil, nil, maker_readers, feed_readers) - end - end - - def _assert_maker_itunes_subtitle(subtitle, maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_subtitle = subtitle - end - - target = chain_reader(rss20, feed_readers) - assert_equal(subtitle, target.itunes_subtitle) - end - - def assert_maker_itunes_subtitle(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_subtitle("A show about everything", - maker_readers, feed_readers) - _assert_maker_itunes_subtitle("A short primer on table spices", - maker_readers, feed_readers) - _assert_maker_itunes_subtitle("Comparing socket wrenches is fun!", - maker_readers, feed_readers) - _assert_maker_itunes_subtitle("Red + Blue != Purple", - maker_readers, feed_readers) - end - end - - def _assert_maker_itunes_summary(summary, maker_readers, feed_readers) - rss20 = ::RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - target = chain_reader(maker, maker_readers) - target.itunes_summary = summary - end - - target = chain_reader(rss20, feed_readers) - assert_equal(summary, target.itunes_summary) - end - - def assert_maker_itunes_summary(maker_readers, feed_readers=nil) - _wrap_assertion do - feed_readers ||= maker_readers - _assert_maker_itunes_summary("All About Everything is a show about " + - "everything. Each week we dive into any " + - "subject known to man and talk about it " + - "as much as we can. Look for our Podcast " + - "in the iTunes Music Store", - maker_readers, feed_readers) - _assert_maker_itunes_summary("This week we talk about salt and pepper " + - "shakers, comparing and contrasting pour " + - "rates, construction materials, and " + - "overall aesthetics. Come and join the " + - "party!", - maker_readers, feed_readers) - _assert_maker_itunes_summary("This week we talk about metric vs. old " + - "english socket wrenches. Which one is " + - "better? Do you really need both? Get " + - "all of your answers here.", - maker_readers, feed_readers) - _assert_maker_itunes_summary("This week we talk about surviving in a " + - "Red state if you're a Blue person. Or " + - "vice versa.", - maker_readers, feed_readers) - end - end - end -end diff --git a/ruby/test/rss/test_maker_slash.rb b/ruby/test/rss/test_maker_slash.rb deleted file mode 100644 index 5e5761ab0..000000000 --- a/ruby/test/rss/test_maker_slash.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerSlash < TestCase - def setup - @elements = { - "section" => "articles", - "department" => "not-an-ocean-unless-there-are-lobsters", - "comments" => 177, - "hit_parades" => [177, 155, 105, 33, 6, 3, 0], - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - setup_dummy_item(maker) - item = maker.items.last - @elements.each do |name, value| - item.send("slash_#{name}=", value) - end - end - - item = rss.items.last - assert_not_nil(item) - assert_slash_elements(item) - end - - private - def assert_slash_elements(target) - super(@elements, target) - end - end -end diff --git a/ruby/test/rss/test_maker_sy.rb b/ruby/test/rss/test_maker_sy.rb deleted file mode 100644 index 6f4d6f839..000000000 --- a/ruby/test/rss/test_maker_sy.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerSyndication < TestCase - - def setup - @uri = "http://purl.org/rss/1.0/modules/syndication/" - - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @elements = { - :updatePeriod => "hourly", - :updateFrequency => "2", - :updateBase => t, - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - set_elements(maker.channel) - setup_dummy_item(maker) - end - assert_syndication(@elements, rss.channel) - end - - private - def accessor_name(name) - "sy_#{name}" - end - - def set_elements(target) - @elements.each do |name, value| - target.__send__("#{accessor_name(name)}=", value) - end - end - - end -end diff --git a/ruby/test/rss/test_maker_taxo.rb b/ruby/test/rss/test_maker_taxo.rb deleted file mode 100644 index 9a19a52dc..000000000 --- a/ruby/test/rss/test_maker_taxo.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerTaxonomy < TestCase - - def setup - @uri = "http://purl.org/rss/1.0/modules/taxonomy/" - - @resources = [ - "http://meerkat.oreillynet.com/?c=cat23", - "http://meerkat.oreillynet.com/?c=47", - "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/", - ] - - @topics = [ - { - :link => "http://meerkat.oreillynet.com/?c=cat23", - :title => "Data: XML", - :description => "A Meerkat channel", - }, - { - :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/", - :title => "XML", - :subject => "XML", - :description => "DMOZ category", - :topics => [ - "http://meerkat.oreillynet.com/?c=cat23", - "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/", - "http://dmoz.org/Computers/Programming/Internet/", - ] - }, - ] - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - set_topics(maker.channel) - - setup_dummy_item(maker) - set_topics(maker.items.last) - - setup_taxo_topic(maker, @topics) - end - assert_equal(@resources, rss.channel.taxo_topics.resources) - assert_equal(@resources, rss.items.last.taxo_topics.resources) - assert_taxo_topic(@topics, rss) - end - - def _test_date - t1 = Time.iso8601("2000-01-01T12:00:05+00:00") - t2 = Time.iso8601("2005-01-01T12:00:05+00:00") - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.date = t1 - maker.channel.dc_dates.new_date do |date| - date.value = t2 - end - - setup_dummy_item(maker) - item = maker.items.last - item.date = t2 - item.dc_dates.new_date do |date| - date.value = t1 - end - end - assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value}) - assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value}) - end - - private - def set_topics(target, resources=@resources) - resources.each do |value| - target.taxo_topics << value - end - end - end -end diff --git a/ruby/test/rss/test_maker_trackback.rb b/ruby/test/rss/test_maker_trackback.rb deleted file mode 100644 index b49e5c3f5..000000000 --- a/ruby/test/rss/test_maker_trackback.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerTrackBack < TestCase - - def setup - @uri = "http://madskills.com/public/xml/rss/module/trackback/" - - @elements = { - :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback", - :abouts => [ - "http://foo.com/trackback/tb.cgi?tb_id=20020923", - "http://bar.com/trackback/tb.cgi?tb_id=20041114", - ], - } - end - - def test_rss10 - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - setup_dummy_item(maker) - item = maker.items.last - item.trackback_ping = @elements[:ping] - @elements[:abouts].each do |about| - item.trackback_abouts.new_about do |new_about| - new_about.value = about - end - end - end - assert_trackback(@elements, rss.items.last) - end - - private - def accessor_name(name) - "trackback_#{name}" - end - end -end diff --git a/ruby/test/rss/test_maker_xml-stylesheet.rb b/ruby/test/rss/test_maker_xml-stylesheet.rb deleted file mode 100644 index 4563de990..000000000 --- a/ruby/test/rss/test_maker_xml-stylesheet.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestMakerXMLStyleSheet < TestCase - - def test_xml_stylesheet - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - rss = RSS::Maker.make("1.0") do |maker| - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - - xss = rss.xml_stylesheets.first - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - - - href = 'http://example.com/index.xsl' - type = 'text/xsl' - rss = RSS::Maker.make("1.0") do |maker| - maker.xml_stylesheets.new_xml_stylesheet do |_xss| - _xss.href = href - end - - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - - xss = rss.xml_stylesheets.first - assert_equal(href, xss.href) - assert_equal(type, xss.type) - end - - def test_not_valid_xml_stylesheet - href = 'xss.XXX' - type = "text/xsl" - - rss = RSS::Maker.make("1.0") do |maker| - maker.xml_stylesheets.new_xml_stylesheet do |xss| - # xss.href = href - xss.type = type - end - - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - assert(rss.xml_stylesheets.empty?) - - rss = RSS::Maker.make("1.0") do |maker| - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - # xss.type = type - end - - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - assert(rss.xml_stylesheets.empty?) - end - - end -end diff --git a/ruby/test/rss/test_parser.rb b/ruby/test/rss/test_parser.rb deleted file mode 100644 index 19344a064..000000000 --- a/ruby/test/rss/test_parser.rb +++ /dev/null @@ -1,121 +0,0 @@ -# frozen_string_literal: false -require "tempfile" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/dublincore" - -module RSS - class TestParser < TestCase - def setup - @_default_parser = Parser.default_parser - @rss10 = make_RDF(<<-EOR) -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} -EOR - @rss_tmp = Tempfile.new(%w"rss10- .rdf") - @rss_tmp.print(@rss10) - @rss_tmp.close - @rss_file = @rss_tmp.path - end - - def teardown - Parser.default_parser = @_default_parser - @rss_tmp.close(true) - end - - def test_default_parser - assert_nothing_raised do - Parser.default_parser = RSS::AVAILABLE_PARSERS.first - end - - assert_raise(RSS::NotValidXMLParser) do - Parser.default_parser = RSS::Parser - end - end - - def test_parse - assert_not_nil(RSS::Parser.parse(@rss_file)) - - garbage_rss_file = @rss_file + "-garbage" - if RSS::Parser.default_parser.name == "RSS::XMLParserParser" - assert_raise(RSS::NotWellFormedError) do - RSS::Parser.parse(garbage_rss_file) - end - else - assert_nil(RSS::Parser.parse(garbage_rss_file)) - end - end - - def test_parse_tag_includes_hyphen - assert_nothing_raised do - RSS::Parser.parse(make_RDF(<<-EOR)) - -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} -EOR - end - end - - def test_parse_option_validate_nil - assert_raise(RSS::MissingTagError) do - RSS::Parser.parse(make_RDF(<<-RDF), :validate => nil) - RDF - end - end - - def test_parse_option_validate_true - assert_raise(RSS::MissingTagError) do - RSS::Parser.parse(make_RDF(<<-RDF), :validate => true) - RDF - end - end - - def test_parse_option_validate_false - rdf = RSS::Parser.parse(make_RDF(<<-RDF), :validate => false) - RDF - assert_nil(rdf.channel) - end - - def test_parse_option_ignore_unknown_element_nil - assert_nothing_raised do - RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => nil) - -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} - RDF - end - end - - def test_parse_option_ignore_unknown_element_true - assert_nothing_raised do - RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => true) - -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} - RDF - end - end - - def test_parse_option_ignore_unknown_element_false - assert_raise(RSS::NotExpectedTagError) do - RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => false) - -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} - RDF - end - end - end -end diff --git a/ruby/test/rss/test_parser_1.0.rb b/ruby/test/rss/test_parser_1.0.rb deleted file mode 100644 index f7be5153a..000000000 --- a/ruby/test/rss/test_parser_1.0.rb +++ /dev/null @@ -1,529 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/dublincore" - -module RSS - class TestParser10 < TestCase - def test_RDF - assert_ns("", RDF::URI) do - Parser.parse(<<-EOR) -#{make_xmldecl} - -EOR - end - - assert_ns("", RDF::URI) do - Parser.parse(<<-EOR) -#{make_xmldecl} - -EOR - end - - assert_ns("rdf", RDF::URI) do - Parser.parse(<<-EOR) -#{make_xmldecl} - -EOR - end - - assert_parse(<<-EOR, :missing_tag, "channel", "RDF") -#{make_xmldecl} - -EOR - - assert_parse(<<-EOR, :missing_tag, "channel", "RDF") -#{make_xmldecl} - -EOR - - assert_parse(<<-EOR, :missing_tag, "channel", "RDF") -#{make_xmldecl} - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") -#{make_channel} -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") -#{make_channel} -#{make_image} -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") -#{make_channel} -#{make_textinput} -EOR - - assert_too_much_tag("image", "RDF") do - Parser.parse(make_RDF(<<-EOR)) -#{make_channel} -#{make_image} -#{make_image} -#{make_item} -#{make_textinput} -EOR - end - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_item} -#{make_image} -#{make_textinput} -EOR - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_item} -#{make_textinput} -#{make_image} -EOR - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_image} -#{make_item} -EOR - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_image} -#{make_item} -#{make_textinput} -EOR - - 1.step(15, 3) do |i| - rss = make_RDF() do - res = make_channel - i.times { res << make_item } - res - end - assert_parse(rss, :nothing_raised) - end - end - - def test_undefined_entity - return unless RSS::Parser.default_parser.raise_for_undefined_entity? - assert_parse(make_RDF(<<-EOR), :raises, RSS::NotWellFormedError) -#{make_channel} -#{make_image} - - #{TITLE_VALUE} &UNKNOWN_ENTITY; - #{LINK_VALUE} - #{DESCRIPTION_VALUE} - -#{make_textinput} -EOR - end - - def test_channel - assert_parse(make_RDF(<<-EOR), :missing_attribute, "channel", "rdf:about") - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "channel") - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "channel") - - hoge - -EOR - - assert_parse(make_RDF(< - hoge - http://example.com/ - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel") - - hoge - http://example.com/ - hogehoge - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:resource") - - hoge - http://example.com/ - hogehoge - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel") - - hoge - http://example.com/ - hogehoge - - -EOR - - rss = make_RDF(<<-EOR) - - hoge - http://example.com/ - hogehoge - - - -EOR - - assert_missing_tag("Seq", "items") do - Parser.parse(rss) - end - - assert_missing_tag("item", "RDF") do - Parser.parse(rss, false).validate - end - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") - - hoge - http://example.com/ - hogehoge - - - - - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:resource") - - hoge - http://example.com/ - hogehoge - - - - - - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") - - hoge - http://example.com/ - hogehoge - - - - - - - -EOR - end - - def test_rdf_li - rss = make_RDF(<<-EOR) - - hoge - http://example.com/ - hogehoge - - - - - - - - -#{make_item} -EOR - - source = Proc.new do |rdf_li_attr| - eval(%Q[%Q[#{rss}]], binding) - end - - attr = %q[resource="http://example.com/hoge"] - assert_parse(source.call(attr), :nothing_raised) - - attr = %q[rdf:resource="http://example.com/hoge"] - assert_parse(source.call(attr), :nothing_raised) - - assert_parse(source.call(""), :missing_attribute, "li", "resource") - end - - def test_image - assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:about") -#{make_channel} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "image") -#{make_channel} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "url", "image") -#{make_channel} - - hoge - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "image") -#{make_channel} - - hoge - http://example.com/hoge.png - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF") -#{make_channel} - - hoge - http://example.com/hoge.png - http://example.com/ - -EOR - - rss = make_RDF(<<-EOR) -#{make_channel} - - http://example.com/ - http://example.com/hoge.png - hoge - -EOR - - assert_missing_tag("item", "RDF") do - Parser.parse(rss) - end - - assert_missing_tag("item", "RDF") do - Parser.parse(rss, false).validate - end - end - - def test_item - assert_parse(make_RDF(<<-EOR), :missing_attribute, "item", "rdf:about") -#{make_channel} -#{make_image} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "item") -#{make_channel} -#{make_image} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "item") -#{make_channel} -#{make_image} - - hoge - -EOR - - assert_too_much_tag("title", "item") do - Parser.parse(make_RDF(<<-EOR)) -#{make_channel} -#{make_image} - - hoge - hoge - http://example.com/hoge.html - -EOR - end - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_image} - - hoge - http://example.com/hoge.html - -EOR - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_image} - - hoge - http://example.com/hoge.html - hogehoge - -EOR - end - - def test_textinput - assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:about") -#{make_channel} -#{make_image} -#{make_item} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "textinput") -#{make_channel} -#{make_image} -#{make_item} - - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "description", "textinput") -#{make_channel} -#{make_image} -#{make_item} - - hoge - -EOR - - assert_too_much_tag("title", "textinput") do - Parser.parse(make_RDF(<<-EOR)) -#{make_channel} -#{make_image} -#{make_item} - - hoge - hoge - hogehoge - -EOR - end - - assert_parse(make_RDF(<<-EOR), :missing_tag, "name", "textinput") -#{make_channel} -#{make_image} -#{make_item} - - hoge - hogehoge - -EOR - - assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "textinput") -#{make_channel} -#{make_image} -#{make_item} - - hoge - hogehoge - key - -EOR - - assert_parse(make_RDF(<<-EOR), :nothing_raised) -#{make_channel} -#{make_image} -#{make_item} - - hoge - hogehoge - key - http://example.com/search.html - -EOR - end - - def test_ignore - name = "a" - rss = make_RDF(<<-EOR) -#{make_channel} -#{make_item} -<#{name}/> -EOR - assert_not_expected_tag(name, ::RSS::URI, "RDF") do - Parser.parse(rss, true, false) - end - - uri = "" - name = "a" - rss = make_RDF(<<-EOR) -#{make_channel} -#{make_item} -<#{name} xmlns=""/> -EOR - assert_parse(rss, :nothing_raised) - assert_not_expected_tag(name, uri, "RDF") do - Parser.parse(rss, true, false) - end - - uri = "http://example.com/" - name = "a" - rss = make_RDF(<<-EOR) -#{make_channel} -#{make_item} - -EOR - assert_parse(rss, :nothing_raised) - assert_not_expected_tag(name, uri, "RDF") do - Parser.parse(rss, true, false) - end - - uri = ::RSS::URI - name = "a" - rss = make_RDF(<<-EOR) -#{make_channel} -#{make_item} -#{make_image("<#{name}/>")} -EOR - assert_parse(rss, :nothing_raised) - assert_not_expected_tag(name, uri, "image") do - Parser.parse(rss, true, false) - end - - uri = CONTENT_URI - name = "encoded" - elem = "<#{name} xmlns='#{uri}'/>" - rss = make_RDF(<<-EOR) -#{make_channel} -#{make_item} -#{make_image(elem)} -EOR - assert_parse(rss, :nothing_raised) - assert_not_expected_tag(name, uri, "image") do - Parser.parse(rss, true, false) - end - end - - def test_unknown_duplicated_element - xmlns = {"test" => "http://localhost/test"} - assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised) - #{make_channel("")} - #{make_item} - #{make_image} - EOR - end - - def test_unknown_case_insensitive_duplicated_element - xmlns = { - "foaf" => "http://xmlns.com/foaf/0.1/", - "dc" => "http://purl.org/dc/elements/1.1/", - } - assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised) - #{make_channel} - #{make_item} - #{make_image} - - Myself - http://example.com/ - - EOR - end - end -end - diff --git a/ruby/test/rss/test_parser_2.0.rb b/ruby/test/rss/test_parser_2.0.rb deleted file mode 100644 index ac7a67b8b..000000000 --- a/ruby/test/rss/test_parser_2.0.rb +++ /dev/null @@ -1,123 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/2.0" - -module RSS - class TestParser20 < TestCase - def test_rss20 - assert_parse(make_rss20(<<-EOR), :missing_tag, "channel", "rss") -EOR - - assert_parse(make_rss20(<<-EOR), :nothing_raised) -#{make_channel20("")} -EOR - end - - def test_cloud20 - attrs = [ - ["domain", CLOUD_DOMAIN], - ["port", CLOUD_PORT], - ["path", CLOUD_PATH], - ["registerProcedure", CLOUD_REGISTER_PROCEDURE], - ["protocol", CLOUD_PROTOCOL], - ] - - (attrs.size + 1).times do |i| - missing_attr = attrs[i] - if missing_attr - meth = :missing_attribute - args = ["cloud", missing_attr[0]] - else - meth = :nothing_raised - args = [] - end - - cloud_attrs = [] - attrs.each_with_index do |attr, j| - unless i == j - cloud_attrs << %Q[#{attr[0]}="#{attr[1]}"] - end - end - - assert_parse(make_rss20(<<-EOR), meth, *args) -#{make_channel20(%Q[])} -EOR - end - end - - def test_source20 - assert_parse(make_rss20(<<-EOR), :missing_attribute, "source", "url") -#{make_channel20(make_item20(%Q[Example]))} -EOR - - assert_parse(make_rss20(<<-EOR), :nothing_raised) -#{make_channel20(make_item20(%Q[]))} -EOR - - assert_parse(make_rss20(<<-EOR), :nothing_raised) -#{make_channel20(make_item20(%Q[Example]))} -EOR - end - - def test_enclosure20 - attrs = [ - ["url", ENCLOSURE_URL], - ["length", ENCLOSURE_LENGTH], - ["type", ENCLOSURE_TYPE], - ] - - (attrs.size + 1).times do |i| - missing_attr = attrs[i] - if missing_attr - meth = :missing_attribute - args = ["enclosure", missing_attr[0]] - else - meth = :nothing_raised - args = [] - end - - enclosure_attrs = [] - attrs.each_with_index do |attr, j| - unless i == j - enclosure_attrs << %Q[#{attr[0]}="#{attr[1]}"] - end - end - - assert_parse(make_rss20(<<-EOR), meth, *args) -#{make_channel20(%Q[ -#{make_item20(%Q[ - - ])} - ])} -EOR - end - end - - def test_category20 - values = [nil, CATEGORY_DOMAIN] - values.each do |value| - domain = "" - domain << %Q[domain="#{value}"] if value - - ["", "Example Text"].each do |text| - rss_src = make_rss20(<<-EOR) -#{make_channel20(%Q[ -#{make_item20(%Q[ -#{text} - ])} - ])} -EOR - assert_parse(rss_src, :nothing_raised) - - rss = RSS::Parser.parse(rss_src) - category = rss.items.last.categories.first - assert_equal(value, category.domain) - assert_equal(text, category.content) - end - end - end - end -end - diff --git a/ruby/test/rss/test_parser_atom_entry.rb b/ruby/test/rss/test_parser_atom_entry.rb deleted file mode 100644 index 4f54ba3ca..000000000 --- a/ruby/test/rss/test_parser_atom_entry.rb +++ /dev/null @@ -1,164 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/atom" - -module RSS - class TestParserAtom < TestCase - def test_entry_validation - assert_ns("", Atom::URI) do - Parser.parse(<<-EOA) - -EOA - end - - assert_ns("", Atom::URI) do - Parser.parse(<<-EOA) - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "id", "entry") do - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "title", "entry") do - - urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746 - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "updated", "entry") do - - urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746 - Example Entry - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "author", "entry") do - - urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746 - Example Entry - 2003-10-10T18:30:02Z - -EOA - end - - assert_parse(<<-EOA, :nothing_raised) do - - urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746 - Example Entry - 2003-10-10T18:30:02Z - - A person - - -EOA - end - end - - def test_entry - entry = RSS::Parser.parse(<<-EOA) - - - - A person - - Atom-Powered Robots Run Amok - - urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a - 2003-12-13T18:30:02Z - Some text. - -EOA - assert_not_nil(entry) - assert_equal("Atom-Powered Robots Run Amok", entry.title.content) - assert_equal("http://example.org/2003/12/13/atom03", entry.link.href) - assert_equal("urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a", - entry.id.content) - assert_equal(Time.parse("2003-12-13T18:30:02Z"), entry.updated.content) - assert_equal("Some text.", entry.summary.content) - end - - def test_entry_author - assert_atom_person("author", method(:make_entry_document)) do |entry| - assert_equal(2, entry.authors.size) - entry.authors.last - end - end - - def test_entry_category - assert_atom_category(method(:make_entry_document)) do |entry| - assert_equal(1, entry.categories.size) - entry.category - end - end - - def test_entry_content_text - assert_atom_content(method(:make_entry_document)) do |entry| - entry.content - end - end - - def test_entry_contributor - assert_atom_person("contributor", method(:make_entry_document)) do |entry| - assert_equal(1, entry.contributors.size) - entry.contributor - end - end - - def test_entry_id - entry = RSS::Parser.parse(make_entry_document) - assert_equal(ENTRY_ID, entry.id.content) - end - - def test_entry_link - assert_atom_link(method(:make_entry_document)) do |entry| - assert_equal(1, entry.links.size) - entry.link - end - end - - def test_published - generator = method(:make_entry_document) - assert_atom_date_construct("published", generator) do |entry| - entry.published - end - end - - def test_entry_rights - generator = method(:make_entry_document) - assert_atom_text_construct("rights", generator) do |entry| - entry.rights - end - end - - def test_entry_source - generator = method(:make_entry_document_with_open_source) - assert_atom_source(generator) do |entry| - assert_not_nil(entry.source) - entry.source - end - end - - def test_entry_summary - generator = method(:make_entry_document) - assert_atom_text_construct("summary", generator) do |entry| - entry.summary - end - end - - def test_entry_title - entry = RSS::Parser.parse(make_entry_document) - assert_equal(ENTRY_TITLE, entry.title.content) - end - - def test_entry_updated - entry = RSS::Parser.parse(make_entry_document) - assert_equal(Time.parse(ENTRY_UPDATED), entry.updated.content) - end - end -end diff --git a/ruby/test/rss/test_parser_atom_feed.rb b/ruby/test/rss/test_parser_atom_feed.rb deleted file mode 100644 index 626062d23..000000000 --- a/ruby/test/rss/test_parser_atom_feed.rb +++ /dev/null @@ -1,277 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/atom" - -module RSS - class TestParserAtomFeed < TestCase - def test_feed_validation - assert_ns("", Atom::URI) do - Parser.parse(<<-EOA) - -EOA - end - - assert_ns("", Atom::URI) do - Parser.parse(<<-EOA) - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "id", "feed") do - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "title", "feed") do - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "updated", "feed") do - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - Example Feed - -EOA - end - - assert_parse(<<-EOA, :missing_tag, "author", "feed") do - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - Example Feed - 2003-12-13T18:30:02Z - -EOA - end - - assert_parse(<<-EOA, :nothing_raised) do - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - Example Feed - 2003-12-13T18:30:02Z - - A person - - -EOA - end - end - - def test_lang - feed = RSS::Parser.parse(<<-EOA) - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - Example Feed - 2003-12-13T18:30:02Z - - A person - - -EOA - - assert_equal("ja", feed.lang) - assert_equal("ja", feed.id.lang) - assert_equal("en", feed.title.lang) - assert_equal("ja", feed.updated.lang) - assert_equal("en", feed.author.lang) - assert_equal("en", feed.author.name.lang) - end - - def test_base - feed = RSS::Parser.parse(<<-EOA) - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - Example Feed - 2003-12-13T18:30:02Z - Generator - - - - - A person - person - - -EOA - - assert_equal("http://example.com/", feed.base) - assert_equal("http://example.com/", feed.id.base) - assert_equal("http://example.com/", feed.title.base) - assert_equal("http://example.com/", feed.updated.base) - assert_equal("http://example.com/", feed.generator.base) - assert_equal("http://example.com/generator", feed.generator.uri) - - assert_equal("http://example.com/", feed.links[0].base) - assert_equal("http://example.org/link1", feed.links[0].href) - assert_equal("http://example.com/", feed.links[1].base) - assert_equal("http://example.com/link2", feed.links[1].href) - assert_equal("http://example.net/", feed.links[2].base) - assert_equal("http://example.net/link3", feed.links[2].href) - assert_equal("http://example.com/person", feed.author.uri.content) - end - - def test_feed_author - assert_atom_person("author", method(:make_feed)) do |feed| - assert_equal(2, feed.authors.size) - feed.authors[1] - end - end - - def test_entry_author - generator = method(:make_feed_with_open_entry) - assert_atom_person("author", generator) do |feed| - assert_equal(1, feed.entries.size) - assert_equal(1, feed.entry.authors.size) - feed.entry.author - end - end - - def test_feed_category - assert_atom_category(method(:make_feed)) do |feed| - assert_equal(1, feed.categories.size) - feed.category - end - end - - def test_entry_category - assert_atom_category(method(:make_feed_with_open_entry)) do |feed| - assert_equal(1, feed.entries.size) - assert_equal(1, feed.entry.categories.size) - feed.entry.category - end - end - - def test_entry_content - assert_atom_content(method(:make_feed_with_open_entry)) do |feed| - assert_equal(1, feed.entries.size) - feed.entry.content - end - end - - def test_feed_contributor - assert_atom_person("contributor", method(:make_feed)) do |feed| - assert_equal(1, feed.contributors.size) - feed.contributor - end - end - - def test_entry_contributor - generator = method(:make_feed_with_open_entry) - assert_atom_person("contributor", generator) do |feed| - assert_equal(1, feed.entries.size) - assert_equal(1, feed.entry.contributors.size) - feed.entry.contributor - end - end - - def test_feed_generator - assert_atom_generator(method(:make_feed)) do |feed| - feed.generator - end - end - - def test_feed_icon - assert_atom_icon(method(:make_feed)) do |feed| - feed.icon - end - end - - def test_feed_id - feed = RSS::Parser.parse(make_feed('')) - assert_equal(FEED_ID, feed.id.content) - end - - def test_entry_id - feed = RSS::Parser.parse(make_feed('')) - assert_equal(ENTRY_ID, feed.entry.id.content) - end - - def test_feed_link - assert_atom_link(method(:make_feed)) do |feed| - assert_equal(1, feed.links.size) - feed.link - end - end - - def test_entry_link - assert_atom_link(method(:make_feed_with_open_entry)) do |feed| - assert_equal(1, feed.entries.size) - assert_equal(1, feed.entry.links.size) - feed.entry.link - end - end - - def test_feed_logo - assert_atom_logo(method(:make_feed)) do |feed| - feed.logo - end - end - - def test_feed_rights - assert_atom_text_construct("rights", method(:make_feed)) do |feed| - feed.rights - end - end - - def test_entry_rights - generator = method(:make_feed_with_open_entry) - assert_atom_text_construct("rights", generator) do |feed| - assert_equal(1, feed.entries.size) - feed.entry.rights - end - end - - def test_entry_source - assert_atom_source(method(:make_feed_with_open_entry_source)) do |feed| - assert_equal(1, feed.entries.size) - assert_not_nil(feed.entry.source) - feed.entry.source - end - end - - def test_feed_subtitle - assert_atom_text_construct("subtitle", method(:make_feed)) do |feed| - feed.subtitle - end - end - - def test_feed_title - feed = RSS::Parser.parse(make_feed('')) - assert_equal(FEED_TITLE, feed.title.content) - end - - def test_entry_title - feed = RSS::Parser.parse(make_feed('')) - assert_equal(ENTRY_TITLE, feed.entry.title.content) - end - - def test_feed_updated - feed = RSS::Parser.parse(make_feed('')) - assert_equal(Time.parse(FEED_UPDATED), feed.updated.content) - end - - def test_entry_updated - feed = RSS::Parser.parse(make_feed('')) - assert_equal(Time.parse(ENTRY_UPDATED), feed.entry.updated.content) - end - - def test_entry_published - generator = method(:make_feed_with_open_entry) - assert_atom_date_construct("published", generator) do |feed| - assert_equal(1, feed.entries.size) - feed.entry.published - end - end - - def test_entry_summary - generator = method(:make_feed_with_open_entry) - assert_atom_text_construct("summary", generator) do |feed| - assert_equal(1, feed.entries.size) - feed.entry.summary - end - end - end -end diff --git a/ruby/test/rss/test_setup_maker_0.9.rb b/ruby/test/rss/test_setup_maker_0.9.rb deleted file mode 100644 index 4eae62417..000000000 --- a/ruby/test/rss/test_setup_maker_0.9.rb +++ /dev/null @@ -1,247 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMaker09 < TestCase - - def test_setup_maker_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - copyright = "foo" - managingEditor = "bar" - webMaster = "web master" - rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))' - docs = "http://foo.com/doc" - skipDays = [ - "Sunday", - "Monday", - ] - skipHours = [ - "0", - "13", - ] - pubDate = Time.now - lastBuildDate = Time.now - - rss = RSS::Maker.make("0.91") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - maker.channel.copyright = copyright - maker.channel.managingEditor = managingEditor - maker.channel.webMaster = webMaster - maker.channel.rating = rating - maker.channel.docs = docs - maker.channel.pubDate = pubDate - maker.channel.lastBuildDate = lastBuildDate - - skipDays.each do |day| - maker.channel.skipDays.new_day do |new_day| - new_day.content = day - end - end - skipHours.each do |hour| - maker.channel.skipHours.new_hour do |new_hour| - new_hour.content = hour - end - end - - setup_dummy_image(maker) - end - - assert_not_set_error("maker.image", %w(title url)) do - RSS::Maker.make("0.91") do |maker| - rss.channel.setup_maker(maker) - end - end - - new_rss = RSS::Maker.make("0.91") do |maker| - rss.channel.setup_maker(maker) - setup_dummy_image(maker) - end - channel = new_rss.channel - - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(language, channel.language) - assert_equal(copyright, channel.copyright) - assert_equal(managingEditor, channel.managingEditor) - assert_equal(webMaster, channel.webMaster) - assert_equal(rating, channel.rating) - assert_equal(docs, channel.docs) - assert_equal(pubDate, channel.pubDate) - assert_equal(lastBuildDate, channel.lastBuildDate) - - skipDays.each_with_index do |day, i| - assert_equal(day, channel.skipDays.days[i].content) - end - skipHours.each_with_index do |hour, i| - assert_equal(hour.to_i, channel.skipHours.hours[i].content) - end - - assert(channel.items.empty?) - assert_nil(channel.textInput) - end - - def test_setup_maker_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - - new_rss = RSS::Maker.make("0.91") do |maker| - rss.channel.setup_maker(maker) - rss.image.setup_maker(maker) - end - - image = new_rss.image - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - assert_equal(width.to_i, image.width) - assert_equal(height.to_i, image.height) - assert_equal(description, image.description) - end - - def test_setup_maker_textinput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - setup_dummy_image(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - - new_rss = RSS::Maker.make("0.91") do |maker| - rss.channel.setup_maker(maker) - rss.image.setup_maker(maker) - rss.textinput.setup_maker(maker) - end - - textInput = new_rss.channel.textInput - assert_equal(title, textInput.title) - assert_equal(description, textInput.description) - assert_equal(name, textInput.name) - assert_equal(link, textInput.link) - end - - def test_setup_maker_items(for_backward_compatibility=false) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - - item_size = 5 - - rss = RSS::Maker.make("0.91") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - end - end - - setup_dummy_image(maker) - end - - new_rss = RSS::Maker.make("0.91") do |maker| - rss.channel.setup_maker(maker) - - rss.items.each do |item| - if for_backward_compatibility - item.setup_maker(maker) - else - item.setup_maker(maker.items) - end - end - - rss.image.setup_maker(maker) - end - - assert_equal(item_size, new_rss.items.size) - new_rss.items.each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - end - end - - def test_setup_maker_items_backward_compatibility - test_setup_maker_items(true) - end - - def test_setup_maker - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - rss = RSS::Maker.make("0.91") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel(maker) - setup_dummy_image(maker) - end - - new_rss = RSS::Maker.make("0.91") do |maker| - rss.setup_maker(maker) - end - - assert_equal("0.91", new_rss.rss_version) - assert_equal(encoding, new_rss.encoding) - assert_equal(standalone, new_rss.standalone) - - xss = rss.xml_stylesheets.first - assert_equal(1, rss.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - end - end -end diff --git a/ruby/test/rss/test_setup_maker_1.0.rb b/ruby/test/rss/test_setup_maker_1.0.rb deleted file mode 100644 index a9d60ddb9..000000000 --- a/ruby/test/rss/test_setup_maker_1.0.rb +++ /dev/null @@ -1,551 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMaker10 < TestCase - - def setup - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @dc_elems = { - :title => "hoge", - :description => - " XML is placing increasingly heavy loads on - the existing technical infrastructure of the Internet.", - :creator => "Rael Dornfest (mailto:rael@oreilly.com)", - :subject => "XML", - :publisher => "The O'Reilly Network", - :contributor => "hogehoge", - :type => "fugafuga", - :format => "hohoho", - :identifier => "fufufu", - :source => "barbar", - :language => "ja", - :relation => "cococo", - :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", - :date => t, - } - - @sy_elems = { - :updatePeriod => "hourly", - :updateFrequency => "2", - :updateBase => t, - } - - @content_elems = { - :encoded => "ATTENTION", - } - - @trackback_elems = { - :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback", - :about => [ - "http://foo.com/trackback/tb.cgi?tb_id=20020923", - "http://foo.com/trackback/tb.cgi?tb_id=20021010", - ], - } - - @taxo_topic_elems = [ - { - :link => "http://meerkat.oreillynet.com/?c=cat23", - :title => "Data: XML", - :description => "A Meerkat channel", - }, - { - :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/", - :title => "XML", - :subject => "XML", - :description => "DMOZ category", - :topics => [ - "http://meerkat.oreillynet.com/?c=cat23", - "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/", - "http://dmoz.org/Computers/Programming/Internet/", - ] - }, - ] - end - - def test_setup_maker_channel - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - - rss = RSS::Maker.make("1.0") do |maker| - maker.channel.about = about - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - - @dc_elems.each do |var, value| - maker.channel.__send__("dc_#{var}=", value) - end - - @sy_elems.each do |var, value| - maker.channel.__send__("sy_#{var}=", value) - end - - setup_dummy_item(maker) - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.channel.setup_maker(maker) - rss.items.each do |item| - item.setup_maker(maker) - end - end - channel = new_rss.channel - - assert_equal(about, channel.about) - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(1, channel.items.Seq.lis.size) - assert_nil(channel.image) - assert_nil(channel.textinput) - - @dc_elems.each do |var, value| - assert_equal(value, channel.__send__("dc_#{var}")) - end - - @sy_elems.each do |var, value| - value = value.to_i if var == :updateFrequency - assert_equal(value, channel.__send__("sy_#{var}")) - end - - end - - def test_setup_maker_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - - @dc_elems.each do |var, value| - maker.image.__send__("dc_#{var}=", value) - end - - setup_dummy_item(maker) - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.channel.setup_maker(maker) - rss.image.setup_maker(maker) - rss.items.each do |item| - item.setup_maker(maker) - end - end - - image = new_rss.image - assert_equal(url, image.about) - assert_equal(url, new_rss.channel.image.resource) - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - - @dc_elems.each do |var, value| - assert_equal(image.__send__("dc_#{var}"), value) - end - end - - def test_setup_maker_textinput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.link = link - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - - @dc_elems.each do |var, value| - maker.textinput.__send__("dc_#{var}=", value) - end - - setup_dummy_item(maker) - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.channel.setup_maker(maker) - rss.textinput.setup_maker(maker) - rss.items.each do |item| - item.setup_maker(maker) - end - end - - textinput = new_rss.textinput - assert_equal(link, textinput.about) - assert_equal(link, new_rss.channel.textinput.resource) - assert_equal(title, textinput.title) - assert_equal(name, textinput.name) - assert_equal(description, textinput.description) - assert_equal(link, textinput.link) - - @dc_elems.each do |var, value| - assert_equal(textinput.__send__("dc_#{var}"), value) - end - end - - def test_setup_maker_items(for_backward_compatibility=false) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - - item_size = 5 - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - - @dc_elems.each do |var, value| - item.__send__("dc_#{var}=", value) - end - - @content_elems.each do |var, value| - item.__send__("content_#{var}=", value) - end - - item.trackback_ping = @trackback_elems[:ping] - @trackback_elems[:about].each do |value| - item.trackback_abouts.new_about do |new_about| - new_about.value = value - end - end - end - end - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.channel.setup_maker(maker) - - rss.items.each do |item| - if for_backward_compatibility - item.setup_maker(maker) - else - item.setup_maker(maker.items) - end - end - end - - assert_equal(item_size, new_rss.items.size) - new_rss.items.each_with_index do |item, i| - assert_equal("#{link}#{i}", item.about) - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - - @dc_elems.each do |var, value| - assert_equal(item.__send__("dc_#{var}"), value) - end - - @content_elems.each do |var, value| - assert_equal(item.__send__("content_#{var}"), value) - end - - assert_equal(@trackback_elems[:ping], item.trackback_ping) - assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size) - item.trackback_abouts.each_with_index do |about, j| - assert_equal(@trackback_elems[:about][j], about.value) - end - end - end - - def test_setup_maker_items_sort - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - - item_size = 5 - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - item = RSS::RDF::Item.new("#{link}#{i}") - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.dc_date = Time.now + i * 60 - item.setup_maker(maker.items) - end - maker.items.do_sort = false - end - assert_equal(item_size, rss.items.size) - rss.items.each_with_index do |item, i| - assert_equal("#{link}#{i}", item.about) - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - end - - - rss = RSS::Maker.make("1.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - item = RSS::RDF::Item.new("#{link}#{i}") - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.dc_date = Time.now + i * 60 - item.setup_maker(maker.items) - end - maker.items.do_sort = true - end - assert_equal(item_size, rss.items.size) - rss.items.reverse.each_with_index do |item, i| - assert_equal("#{link}#{i}", item.about) - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - end - end - - def test_setup_maker_items_backward_compatibility - test_setup_maker_items(true) - end - - def test_setup_maker - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - rss = RSS::Maker.make("1.0") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel(maker) - setup_dummy_item(maker) - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.setup_maker(maker) - end - - assert_equal("1.0", new_rss.rss_version) - assert_equal(encoding, new_rss.encoding) - assert_equal(standalone, new_rss.standalone) - - xss = new_rss.xml_stylesheets.first - assert_equal(1, new_rss.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - end - - def test_setup_maker_full - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - channel_about = "http://hoge.com" - channel_title = "fugafuga" - channel_link = "http://hoge.com" - channel_description = "fugafugafugafuga" - - image_title = "fugafuga" - image_url = "http://hoge.com/hoge.png" - - textinput_title = "fugafuga" - textinput_description = "text hoge fuga" - textinput_name = "hoge" - textinput_link = "http://hoge.com" - - item_title = "TITLE" - item_link = "http://hoge.com/" - item_description = "text hoge fuga" - - item_size = 5 - - rss = RSS::Maker.make("1.0") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - maker.channel.about = channel_about - maker.channel.title = channel_title - maker.channel.link = channel_link - maker.channel.description = channel_description - @dc_elems.each do |var, value| - maker.channel.__send__("dc_#{var}=", value) - end - @sy_elems.each do |var, value| - maker.channel.__send__("sy_#{var}=", value) - end - - maker.image.title = image_title - maker.image.url = image_url - @dc_elems.each do |var, value| - maker.image.__send__("dc_#{var}=", value) - end - - maker.textinput.link = textinput_link - maker.textinput.title = textinput_title - maker.textinput.description = textinput_description - maker.textinput.name = textinput_name - @dc_elems.each do |var, value| - maker.textinput.__send__("dc_#{var}=", value) - end - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{item_title}#{i}" - item.link = "#{item_link}#{i}" - item.description = "#{item_description}#{i}" - - @dc_elems.each do |var, value| - item.__send__("dc_#{var}=", value) - end - - @content_elems.each do |var, value| - item.__send__("content_#{var}=", value) - end - - item.trackback_ping = @trackback_elems[:ping] - @trackback_elems[:about].each do |value| - item.trackback_abouts.new_about do |new_about| - new_about.value = value - end - end - end - end - - setup_taxo_topic(maker, @taxo_topic_elems) - end - - new_rss = RSS::Maker.make("1.0") do |maker| - rss.setup_maker(maker) - end - - assert_equal("1.0", new_rss.rss_version) - assert_equal(encoding, new_rss.encoding) - assert_equal(standalone, new_rss.standalone) - - xss = new_rss.xml_stylesheets.first - assert_equal(1, new_rss.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - - channel = new_rss.channel - assert_equal(channel_about, channel.about) - assert_equal(channel_title, channel.title) - assert_equal(channel_link, channel.link) - assert_equal(channel_description, channel.description) - item_resources = [] - item_size.times do |i| - item_resources << "#{item_link}#{i}" - end - assert_equal(item_resources, channel.items.resources) - assert_equal(image_url, channel.image.resource) - assert_equal(textinput_link, channel.textinput.resource) - @dc_elems.each do |var, value| - assert_equal(value, channel.__send__("dc_#{var}")) - end - @sy_elems.each do |var, value| - value = value.to_i if var == :updateFrequency - assert_equal(value, channel.__send__("sy_#{var}")) - end - - image = new_rss.image - assert_equal(image_url, image.about) - assert_equal(image_url, new_rss.channel.image.resource) - assert_equal(image_title, image.title) - assert_equal(channel_link, image.link) - assert_equal(image_url, image.url) - @dc_elems.each do |var, value| - assert_equal(image.__send__("dc_#{var}"), value) - end - - textinput = new_rss.textinput - assert_equal(textinput_link, textinput.about) - assert_equal(textinput_link, new_rss.channel.textinput.resource) - assert_equal(textinput_title, textinput.title) - assert_equal(textinput_name, textinput.name) - assert_equal(textinput_description, textinput.description) - assert_equal(textinput_link, textinput.link) - @dc_elems.each do |var, value| - assert_equal(textinput.__send__("dc_#{var}"), value) - end - - assert_equal(item_size, new_rss.items.size) - new_rss.items.each_with_index do |item, i| - assert_equal("#{item_link}#{i}", item.about) - assert_equal("#{item_title}#{i}", item.title) - assert_equal("#{item_link}#{i}", item.link) - assert_equal("#{item_description}#{i}", item.description) - - @dc_elems.each do |var, value| - assert_equal(item.__send__("dc_#{var}"), value) - end - - @content_elems.each do |var, value| - assert_equal(item.__send__("content_#{var}"), value) - end - - assert_equal(@trackback_elems[:ping], item.trackback_ping) - assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size) - item.trackback_abouts.each_with_index do |about, j| - assert_equal(@trackback_elems[:about][j], about.value) - end - end - - assert_taxo_topic(@taxo_topic_elems, new_rss) - end - - end -end diff --git a/ruby/test/rss/test_setup_maker_2.0.rb b/ruby/test/rss/test_setup_maker_2.0.rb deleted file mode 100644 index dffffe6da..000000000 --- a/ruby/test/rss/test_setup_maker_2.0.rb +++ /dev/null @@ -1,309 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMaker20 < TestCase - - def test_setup_maker_channel - title = "fugafuga" - link = "http://hoge.com" - description = "fugafugafugafuga" - language = "ja" - copyright = "foo" - managingEditor = "bar" - webMaster = "web master" - rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))' - docs = "http://foo.com/doc" - skipDays = [ - "Sunday", - "Monday", - ] - skipHours = [ - "0", - "13", - ] - pubDate = Time.now - lastBuildDate = Time.now - categories = [ - "Nespapers", - "misc", - ] - generator = "RSS Maker" - ttl = "60" - - rss = RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - maker.channel.language = language - maker.channel.copyright = copyright - maker.channel.managingEditor = managingEditor - maker.channel.webMaster = webMaster - maker.channel.rating = rating - maker.channel.docs = docs - maker.channel.pubDate = pubDate - maker.channel.lastBuildDate = lastBuildDate - - skipDays.each do |day| - maker.channel.skipDays.new_day do |new_day| - new_day.content = day - end - end - skipHours.each do |hour| - maker.channel.skipHours.new_hour do |new_hour| - new_hour.content = hour - end - end - - - categories.each do |category| - maker.channel.categories.new_category do |new_category| - new_category.content = category - end - end - - maker.channel.generator = generator - maker.channel.ttl = ttl - end - - new_rss = RSS::Maker.make("2.0") do |maker| - rss.channel.setup_maker(maker) - end - channel = new_rss.channel - - assert_equal(title, channel.title) - assert_equal(link, channel.link) - assert_equal(description, channel.description) - assert_equal(language, channel.language) - assert_equal(copyright, channel.copyright) - assert_equal(managingEditor, channel.managingEditor) - assert_equal(webMaster, channel.webMaster) - assert_equal(rating, channel.rating) - assert_equal(docs, channel.docs) - assert_equal(pubDate, channel.pubDate) - assert_equal(lastBuildDate, channel.lastBuildDate) - - skipDays.each_with_index do |day, i| - assert_equal(day, channel.skipDays.days[i].content) - end - skipHours.each_with_index do |hour, i| - assert_equal(hour.to_i, channel.skipHours.hours[i].content) - end - - - channel.categories.each_with_index do |category, i| - assert_equal(categories[i], category.content) - end - - assert_equal(generator, channel.generator) - assert_equal(ttl.to_i, channel.ttl) - - - assert(channel.items.empty?) - assert_nil(channel.image) - assert_nil(channel.textInput) - end - - def test_setup_maker_image - title = "fugafuga" - link = "http://hoge.com" - url = "http://hoge.com/hoge.png" - width = "144" - height = "400" - description = "an image" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - maker.channel.link = link - - maker.image.title = title - maker.image.url = url - maker.image.width = width - maker.image.height = height - maker.image.description = description - end - - new_rss = RSS::Maker.make("2.0") do |maker| - rss.channel.setup_maker(maker) - rss.image.setup_maker(maker) - end - - image = new_rss.image - assert_equal(title, image.title) - assert_equal(link, image.link) - assert_equal(url, image.url) - assert_equal(width.to_i, image.width) - assert_equal(height.to_i, image.height) - assert_equal(description, image.description) - end - - def test_setup_maker_textinput - title = "fugafuga" - description = "text hoge fuga" - name = "hoge" - link = "http://hoge.com" - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - maker.textinput.title = title - maker.textinput.description = description - maker.textinput.name = name - maker.textinput.link = link - end - - new_rss = RSS::Maker.make("2.0") do |maker| - rss.channel.setup_maker(maker) - rss.textinput.setup_maker(maker) - end - - textInput = new_rss.channel.textInput - assert_equal(title, textInput.title) - assert_equal(description, textInput.description) - assert_equal(name, textInput.name) - assert_equal(link, textInput.link) - end - - def test_setup_maker_items(for_backward_compatibility=false) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - author = "oprah@oxygen.net" - comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290" - pubDate = Time.now - - guid_isPermaLink = "true" - guid_content = "http://inessential.com/2002/09/01.php#a2" - - enclosure_url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3" - enclosure_length = "12216320" - enclosure_type = "audio/mpeg" - - source_url = "http://static.userland.com/tomalak/links2.xml" - source_content = "Tomalak's Realm" - - category_domain = "http://www.fool.com/cusips" - category_content = "MSFT" - - item_size = 5 - - rss = RSS::Maker.make("2.0") do |maker| - setup_dummy_channel(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.author = "#{author}#{i}" - item.comments = "#{comments}#{i}" - item.date = pubDate - - item.guid.isPermaLink = guid_isPermaLink - item.guid.content = guid_content - - item.enclosure.url = enclosure_url - item.enclosure.length = enclosure_length - item.enclosure.type = enclosure_type - - item.source.url = source_url - item.source.content = source_content - - category = item.categories.new_category - category.domain = category_domain - category.content = category_content - end - end - end - - new_rss = RSS::Maker.make("2.0") do |maker| - rss.channel.setup_maker(maker) - - rss.items.each do |item| - if for_backward_compatibility - item.setup_maker(maker) - else - item.setup_maker(maker.items) - end - end - end - - assert_equal(item_size, new_rss.items.size) - new_rss.items.each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title) - assert_equal("#{link}#{i}", item.link) - assert_equal("#{description}#{i}", item.description) - assert_equal("#{author}#{i}", item.author) - assert_equal("#{comments}#{i}", item.comments) - assert_equal(pubDate, item.pubDate) - - assert_equal(guid_isPermaLink == "true", item.guid.isPermaLink) - assert_equal(guid_content, item.guid.content) - - assert_equal(enclosure_url, item.enclosure.url) - assert_equal(enclosure_length.to_i, item.enclosure.length) - assert_equal(enclosure_type, item.enclosure.type) - - assert_equal(source_url, item.source.url) - assert_equal(source_content, item.source.content) - - assert_equal(1, item.categories.size) - assert_equal(category_domain, item.category.domain) - assert_equal(category_content, item.category.content) - end - - end - - def test_setup_maker_items_backward_compatibility - test_setup_maker_items(true) - end - - def test_setup_maker - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - rss = RSS::Maker.make("2.0") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel(maker) - end - - new_rss = RSS::Maker.make("2.0") do |maker| - rss.setup_maker(maker) - end - - assert_equal("2.0", new_rss.rss_version) - assert_equal(encoding, new_rss.encoding) - assert_equal(standalone, new_rss.standalone) - - xss = rss.xml_stylesheets.first - assert_equal(1, rss.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - end - - end -end diff --git a/ruby/test/rss/test_setup_maker_atom_entry.rb b/ruby/test/rss/test_setup_maker_atom_entry.rb deleted file mode 100644 index f8649ea18..000000000 --- a/ruby/test/rss/test_setup_maker_atom_entry.rb +++ /dev/null @@ -1,410 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMakerAtomEntry < TestCase - def setup - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @dc_elems = { - :title => "hoge", - :description => - " XML is placing increasingly heavy loads on - the existing technical infrastructure of the Internet.", - :creator => "Rael Dornfest (mailto:rael@oreilly.com)", - :subject => "XML", - :publisher => "The O'Reilly Network", - :contributor => "hogehoge", - :type => "fugafuga", - :format => "hohoho", - :identifier => "fufufu", - :source => "barbar", - :language => "ja", - :relation => "cococo", - :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", - :date => t, - } - end - - def test_setup_maker_entry(with_dc=true) - authors = [ - { - :name => "Bob", - :uri => "http://example.com/~bob/", - :email => "bob@example.com", - }, - { - :name => "Alice", - :uri => "http://example.com/~alice/", - :email => "alice@example.com", - }, - ] - categories = [ - { - :term => "music", - :label => "Music", - }, - { - :term => "book", - :scheme => "http://example.com/category/book/", - :label => "Book", - }, - ] - contributors = [ - { - :name => "Chris", - :email => "chris@example.com", - }, - { - :name => "Eva", - :uri => "http://example.com/~eva/", - }, - ] - id = "urn:uuid:8b105336-7e20-45fc-bb78-37fb3e1db25a" - link = "http://hoge.com" - published = Time.now - 60 * 3600 - rights = "Copyrights (c) 2007 Alice and Bob" - description = "fugafugafugafuga" - title = "fugafuga" - updated = Time.now - - feed = RSS::Maker.make("atom:entry") do |maker| - maker.items.new_item do |item| - authors.each do |author_info| - item.authors.new_author do |author| - author_info.each do |key, value| - author.__send__("#{key}=", value) - end - end - end - - categories.each do |category_info| - item.categories.new_category do |category| - category_info.each do |key, value| - category.__send__("#{key}=", value) - end - end - end - - contributors.each do |contributor_info| - item.contributors.new_contributor do |contributor| - contributor_info.each do |key, value| - contributor.__send__("#{key}=", value) - end - end - end - - item.id = id - item.link = link - item.published = published - item.rights = rights - item.description = description - item.title = title - item.updated = updated - - if with_dc - @dc_elems.each do |var, value| - if var == :date - item.new_dc_date(value) - else - item.__send__("dc_#{var}=", value) - end - end - end - end - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("atom:entry") do |maker| - feed.setup_maker(maker) - end - assert_not_nil(new_feed) - - new_authors = new_feed.authors.collect do |author| - { - :name => author.name.content, - :uri => author.uri.content, - :email => author.email.content, - } - end - assert_equal(authors, new_authors) - - new_categories = new_feed.categories.collect do |category| - { - :term => category.term, - :scheme => category.scheme, - :label => category.label, - }.reject {|key, value| value.nil?} - end - assert_equal(categories, new_categories) - - new_contributors = new_feed.contributors.collect do |contributor| - info = {} - info[:name] = contributor.name.content - info[:uri] = contributor.uri.content if contributor.uri - info[:email] = contributor.email.content if contributor.email - info - end - assert_equal(contributors, new_contributors) - - assert_equal(id, new_feed.id.content) - assert_equal(link, new_feed.link.href) - assert_equal(published, new_feed.published.content) - assert_equal(rights, new_feed.rights.content) - assert_equal(description, new_feed.summary.content) - assert_equal(title, new_feed.title.content) - assert_equal(updated, new_feed.updated.content) - - if with_dc - @dc_elems.each do |var, value| - if var == :date - assert_equal([updated, value], - new_feed.dc_dates.collect {|date| date.value}) - else - assert_equal(value, new_feed.__send__("dc_#{var}")) - end - end - end - - assert_equal(1, new_feed.items.size) - end - - def test_setup_maker_entry_without_dc - test_setup_maker_entry(false) - end - - def test_setup_maker_items(for_backward_compatibility=false) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - updated = Time.now - - item_size = 5 - feed = RSS::Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.updated = updated + i * 60 - end - end - end - - new_feed = RSS::Maker.make("atom:entry") do |maker| - feed.items.each do |item| - if for_backward_compatibility - item.setup_maker(maker) - else - item.setup_maker(maker.items) - end - end - - feed.items.clear - feed.setup_maker(maker) - end - - assert_equal(1, new_feed.items.size) - new_feed.items[0..1].each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title.content) - assert_equal("#{link}#{i}", item.link.href) - assert_equal("#{description}#{i}", item.summary.content) - assert_equal(updated + i * 60, item.updated.content) - end - end - - def test_setup_maker_items_sort - title = "TITLE" - link = "http://hoge.com/" - summary = "text hoge fuga" - updated = Time.now - - feed_size = 5 - feed = RSS::Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - - feed_size.times do |i| - entry_class = RSS::Atom::Entry - entry = entry_class.new - entry.title = entry_class::Title.new(:content => "#{title}#{i}") - entry.links << entry_class::Link.new(:href => "#{link}#{i}") - entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}") - entry.updated = entry_class::Updated.new(:content => updated + i * 60) - entry.setup_maker(maker.items) - end - maker.items.do_sort = false - end - assert_equal(1, feed.items.size) - - assert_equal("#{title}0", feed.title.content) - assert_equal("#{link}0", feed.link.href) - assert_equal("#{summary}0", feed.summary.content) - - - feed = RSS::Maker.make("atom:entry") do |maker| - setup_dummy_channel_atom(maker) - - feed_size.times do |i| - entry_class = RSS::Atom::Entry - entry = entry_class.new - entry.title = entry_class::Title.new(:content => "#{title}#{i}") - entry.links << entry_class::Link.new(:href => "#{link}#{i}") - entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}") - entry.updated = entry_class::Updated.new(:content => updated + i * 60) - entry.setup_maker(maker.items) - end - maker.items.do_sort = true - end - assert_equal(1, feed.items.size) - - assert_equal("#{title}#{feed_size - 1}", feed.title.content) - assert_equal("#{link}#{feed_size - 1}", feed.link.href) - assert_equal("#{summary}#{feed_size - 1}", feed.summary.content) - end - - def test_setup_maker_items_backward_compatibility - test_setup_maker_items(true) - end - - def test_setup_maker - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - feed = RSS::Maker.make("atom:entry") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("atom:entry") do |maker| - feed.setup_maker(maker) - end - - assert_equal(["atom", "1.0", "entry"], new_feed.feed_info) - assert_equal(encoding, new_feed.encoding) - assert_equal(standalone, new_feed.standalone) - - xss = new_feed.xml_stylesheets.first - assert_equal(1, new_feed.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - end - - def test_setup_maker_full - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - channel_about = "http://hoge.com" - channel_title = "fugafuga" - channel_link = "http://hoge.com" - channel_description = "fugafugafugafuga" - channel_author = "Bob" - - image_url = "http://hoge.com/hoge.png" - - item_title = "TITLE" - item_link = "http://hoge.com/" - item_description = "text hoge fuga" - - entry_size = 5 - feed = RSS::Maker.make("atom:entry") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - maker.channel.about = channel_about - maker.channel.title = channel_title - maker.channel.link = channel_link - maker.channel.description = channel_description - maker.channel.author = channel_author - @dc_elems.each do |var, value| - maker.channel.__send__("dc_#{var}=", value) - end - - maker.image.url = image_url - - entry_size.times do |i| - maker.items.new_item do |item| - item.title = "#{item_title}#{i}" - item.link = "#{item_link}#{i}" - item.description = "#{item_description}#{i}" - - @dc_elems.each do |var, value| - item.__send__("dc_#{var}=", value) - end - end - end - end - - new_feed = RSS::Maker.make("atom:entry") do |maker| - feed.setup_maker(maker) - end - - assert_equal(["atom", "1.0", "entry"], new_feed.feed_info) - assert_equal(encoding, new_feed.encoding) - assert_equal(standalone, new_feed.standalone) - - xss = new_feed.xml_stylesheets.first - assert_equal(1, new_feed.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - - assert_equal("#{item_title}0", new_feed.title.content) - assert_equal("#{item_link}0", new_feed.link.href) - assert_equal("#{item_description}0", new_feed.summary.content) - @dc_elems.each do |var, value| - assert_equal(value, new_feed.__send__("dc_#{var}")) - end - assert_equal(1, new_feed.items.size) - end - end -end diff --git a/ruby/test/rss/test_setup_maker_atom_feed.rb b/ruby/test/rss/test_setup_maker_atom_feed.rb deleted file mode 100644 index 2196f1a46..000000000 --- a/ruby/test/rss/test_setup_maker_atom_feed.rb +++ /dev/null @@ -1,446 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMakerAtomFeed < TestCase - def setup - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @dc_elems = { - :title => "hoge", - :description => - " XML is placing increasingly heavy loads on - the existing technical infrastructure of the Internet.", - :creator => "Rael Dornfest (mailto:rael@oreilly.com)", - :subject => "XML", - :publisher => "The O'Reilly Network", - :contributor => "hogehoge", - :type => "fugafuga", - :format => "hohoho", - :identifier => "fufufu", - :source => "barbar", - :language => "ja", - :relation => "cococo", - :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", - :date => t, - } - end - - def test_setup_maker_feed(with_dc=true) - authors = [ - { - :name => "Bob", - :uri => "http://example.com/~bob/", - :email => "bob@example.com", - }, - { - :name => "Alice", - :uri => "http://example.com/~alice/", - :email => "alice@example.com", - }, - ] - categories = [ - { - :term => "music", - :label => "Music", - }, - { - :term => "book", - :scheme => "http://example.com/category/book/", - :label => "Book", - }, - ] - contributors = [ - { - :name => "Chris", - :email => "chris@example.com", - }, - { - :name => "Eva", - :uri => "http://example.com/~eva/", - }, - ] - generator = { - :uri => "http://example.com/generator/", - :version => "0.0.1", - :content => "Feed Generator", - } - icon = "http://example.com/icon.png" - about = "http://hoge.com" - title = "fugafuga" - link = "http://hoge.com" - logo = "http://example.com/logo.png" - rights = "Copyrights (c) 2007 Alice and Bob" - description = "fugafugafugafuga" - updated = Time.now - - feed = RSS::Maker.make("atom") do |maker| - authors.each do |author_info| - maker.channel.authors.new_author do |author| - author_info.each do |key, value| - author.__send__("#{key}=", value) - end - end - end - - categories.each do |category_info| - maker.channel.categories.new_category do |category| - category_info.each do |key, value| - category.__send__("#{key}=", value) - end - end - end - - contributors.each do |contributor_info| - maker.channel.contributors.new_contributor do |contributor| - contributor_info.each do |key, value| - contributor.__send__("#{key}=", value) - end - end - end - - generator.each do |key, value| - maker.channel.generator do |g| - g.__send__("#{key}=", value) - end - end - - maker.channel.icon = icon - - maker.channel.about = about - maker.channel.link = link - maker.channel.logo = logo - maker.channel.rights = rights - maker.channel.title = title - maker.channel.description = description - maker.channel.updated = updated - - if with_dc - @dc_elems.each do |var, value| - if var == :date - maker.channel.new_dc_date(value) - else - maker.channel.__send__("dc_#{var}=", value) - end - end - end - - setup_dummy_item_atom(maker) - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("atom") do |maker| - feed.setup_maker(maker) - end - assert_not_nil(new_feed) - - new_authors = new_feed.authors.collect do |author| - { - :name => author.name.content, - :uri => author.uri.content, - :email => author.email.content, - } - end - assert_equal(authors, new_authors) - - new_categories = new_feed.categories.collect do |category| - { - :term => category.term, - :scheme => category.scheme, - :label => category.label, - }.reject {|key, value| value.nil?} - end - assert_equal(categories, new_categories) - - new_contributors = new_feed.contributors.collect do |contributor| - info = {} - info[:name] = contributor.name.content - info[:uri] = contributor.uri.content if contributor.uri - info[:email] = contributor.email.content if contributor.email - info - end - assert_equal(contributors, new_contributors) - - new_generator = { - :uri => new_feed.generator.uri, - :version => new_feed.generator.version, - :content => new_feed.generator.content, - } - assert_equal(generator, new_generator) - - assert_equal(icon, new_feed.icon.content) - assert_equal(about, new_feed.id.content) - assert_equal(link, new_feed.link.href) - assert_equal(logo, new_feed.logo.content) - assert_equal(rights, new_feed.rights.content) - assert_equal(description, new_feed.subtitle.content) - assert_equal(title, new_feed.title.content) - assert_equal(updated, new_feed.updated.content) - - if with_dc - @dc_elems.each do |var, value| - if var == :date - assert_equal([updated, value], - new_feed.dc_dates.collect {|date| date.value}) - else - assert_equal(value, new_feed.__send__("dc_#{var}")) - end - end - end - - assert_equal(1, new_feed.items.size) - end - - def test_setup_maker_feed_without_dc - test_setup_maker_feed(false) - end - - def test_setup_maker_items(for_backward_compatibility=false) - title = "TITLE" - link = "http://hoge.com/" - description = "text hoge fuga" - updated = Time.now - - item_size = 5 - feed = RSS::Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - - item_size.times do |i| - maker.items.new_item do |item| - item.title = "#{title}#{i}" - item.link = "#{link}#{i}" - item.description = "#{description}#{i}" - item.updated = updated + i * 60 - end - end - end - - new_feed = RSS::Maker.make("atom") do |maker| - feed.items.each do |item| - if for_backward_compatibility - item.setup_maker(maker) - else - item.setup_maker(maker.items) - end - end - - feed.items.clear - feed.setup_maker(maker) - end - - assert_equal(item_size, new_feed.items.size) - new_feed.items.each_with_index do |item, i| - assert_equal("#{title}#{i}", item.title.content) - assert_equal("#{link}#{i}", item.link.href) - assert_equal("#{description}#{i}", item.summary.content) - assert_equal(updated + i * 60, item.updated.content) - end - end - - def test_setup_maker_items_sort - title = "TITLE" - link = "http://hoge.com/" - summary = "text hoge fuga" - updated = Time.now - - feed_size = 5 - feed = RSS::Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - - feed_size.times do |i| - entry_class = RSS::Atom::Feed::Entry - entry = entry_class.new - entry.title = entry_class::Title.new(:content => "#{title}#{i}") - entry.links << entry_class::Link.new(:href => "#{link}#{i}") - entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}") - entry.updated = entry_class::Updated.new(:content => updated + i * 60) - entry.setup_maker(maker.items) - end - maker.items.do_sort = false - end - assert_equal(feed_size, feed.entries.size) - feed.entries.each_with_index do |entry, i| - assert_equal("#{title}#{i}", entry.title.content) - assert_equal("#{link}#{i}", entry.link.href) - assert_equal("#{summary}#{i}", entry.summary.content) - end - - - feed = RSS::Maker.make("atom") do |maker| - setup_dummy_channel_atom(maker) - - feed_size.times do |i| - entry_class = RSS::Atom::Feed::Entry - entry = entry_class.new - entry.title = entry_class::Title.new(:content => "#{title}#{i}") - entry.links << entry_class::Link.new(:href => "#{link}#{i}") - entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}") - entry.updated = entry_class::Updated.new(:content => updated + i * 60) - entry.setup_maker(maker.items) - end - maker.items.do_sort = true - end - assert_equal(feed_size, feed.entries.size) - feed.entries.reverse.each_with_index do |entry, i| - assert_equal("#{title}#{i}", entry.title.content) - assert_equal("#{link}#{i}", entry.link.href) - assert_equal("#{summary}#{i}", entry.summary.content) - end - end - - def test_setup_maker_items_backward_compatibility - test_setup_maker_items(true) - end - - def test_setup_maker - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - feed = RSS::Maker.make("atom") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - setup_dummy_channel_atom(maker) - setup_dummy_item_atom(maker) - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("atom") do |maker| - feed.setup_maker(maker) - end - - assert_equal(["atom", "1.0", "feed"], new_feed.feed_info) - assert_equal(encoding, new_feed.encoding) - assert_equal(standalone, new_feed.standalone) - - xss = new_feed.xml_stylesheets.first - assert_equal(1, new_feed.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - end - - def test_setup_maker_full - encoding = "EUC-JP" - standalone = true - - href = 'a.xsl' - type = 'text/xsl' - title = 'sample' - media = 'printer' - charset = 'UTF-8' - alternate = 'yes' - - channel_about = "http://hoge.com" - channel_title = "fugafuga" - channel_link = "http://hoge.com" - channel_description = "fugafugafugafuga" - channel_author = "Bob" - - image_url = "http://hoge.com/hoge.png" - - item_title = "TITLE" - item_link = "http://hoge.com/" - item_description = "text hoge fuga" - - entry_size = 5 - feed = RSS::Maker.make("atom") do |maker| - maker.encoding = encoding - maker.standalone = standalone - - maker.xml_stylesheets.new_xml_stylesheet do |xss| - xss.href = href - xss.type = type - xss.title = title - xss.media = media - xss.charset = charset - xss.alternate = alternate - end - - maker.channel.about = channel_about - maker.channel.title = channel_title - maker.channel.link = channel_link - maker.channel.description = channel_description - maker.channel.author = channel_author - @dc_elems.each do |var, value| - maker.channel.__send__("dc_#{var}=", value) - end - - maker.image.url = image_url - - entry_size.times do |i| - maker.items.new_item do |item| - item.title = "#{item_title}#{i}" - item.link = "#{item_link}#{i}" - item.description = "#{item_description}#{i}" - - @dc_elems.each do |var, value| - item.__send__("dc_#{var}=", value) - end - end - end - end - - new_feed = RSS::Maker.make("atom") do |maker| - feed.setup_maker(maker) - end - - assert_equal(["atom", "1.0", "feed"], new_feed.feed_info) - assert_equal(encoding, new_feed.encoding) - assert_equal(standalone, new_feed.standalone) - - xss = new_feed.xml_stylesheets.first - assert_equal(1, new_feed.xml_stylesheets.size) - assert_equal(href, xss.href) - assert_equal(type, xss.type) - assert_equal(title, xss.title) - assert_equal(media, xss.media) - assert_equal(charset, xss.charset) - assert_equal(alternate, xss.alternate) - - assert_equal(channel_title, new_feed.title.content) - assert_equal(channel_link, new_feed.link.href) - assert_equal(channel_description, new_feed.subtitle.content) - assert_equal(channel_author, new_feed.author.name.content) - assert_equal(image_url, new_feed.logo.content) - @dc_elems.each do |var, value| - assert_equal(value, new_feed.__send__("dc_#{var}")) - end - - assert_equal(entry_size, new_feed.entries.size) - new_feed.entries.each_with_index do |entry, i| - assert_equal("#{item_title}#{i}", entry.title.content) - assert_equal("#{item_link}#{i}", entry.link.href) - assert_equal("#{item_description}#{i}", entry.summary.content) - - @dc_elems.each do |var, value| - assert_equal(value, entry.__send__("dc_#{var}")) - end - end - end - end -end diff --git a/ruby/test/rss/test_setup_maker_itunes.rb b/ruby/test/rss/test_setup_maker_itunes.rb deleted file mode 100644 index 35ecfb482..000000000 --- a/ruby/test/rss/test_setup_maker_itunes.rb +++ /dev/null @@ -1,144 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMakerITunes < TestCase - def test_setup_maker_simple - author = "John Doe" - block = true - categories = ["Audio Blogs"] - image = "http://example.com/podcasts/everything/AllAboutEverything.jpg" - duration = "4:05" - duration_components = [0, 4, 5] - explicit = true - keywords = ["salt", "pepper", "shaker", "exciting"] - owner = {:name => "John Doe", :email => "john.doe@example.com"} - subtitle = "A show about everything" - summary = "All About Everything is a show about " + - "everything. Each week we dive into any " + - "subject known to man and talk about it " + - "as much as we can. Look for our Podcast " + - "in the iTunes Music Store" - - feed = RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - channel = maker.channel - channel.itunes_author = author - channel.itunes_block = block - categories.each do |category| - channel.itunes_categories.new_category.text = category - end - channel.itunes_image = image - channel.itunes_explicit = explicit - channel.itunes_keywords = keywords - channel.itunes_owner.itunes_name = owner[:name] - channel.itunes_owner.itunes_email = owner[:email] - channel.itunes_subtitle = subtitle - channel.itunes_summary = summary - - item = maker.items.last - item.itunes_author = author - item.itunes_block = block - item.itunes_duration = duration - item.itunes_explicit = explicit - item.itunes_keywords = keywords - item.itunes_subtitle = subtitle - item.itunes_summary = summary - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("rss2.0") do |maker| - feed.setup_maker(maker) - end - assert_not_nil(new_feed) - - channel = new_feed.channel - item = new_feed.items.last - - assert_equal(author, channel.itunes_author) - assert_equal(author, item.itunes_author) - - assert_equal(block, channel.itunes_block?) - assert_equal(block, item.itunes_block?) - - assert_equal(categories, - collect_itunes_categories(channel.itunes_categories)) - - assert_equal(image, channel.itunes_image.href) - - assert_equal(duration_components, - [item.itunes_duration.hour, - item.itunes_duration.minute, - item.itunes_duration.second]) - - assert_equal(explicit, channel.itunes_explicit?) - assert_equal(explicit, item.itunes_explicit?) - - assert_equal(keywords, channel.itunes_keywords) - assert_equal(keywords, item.itunes_keywords) - - assert_equal(owner, - { - :name => channel.itunes_owner.itunes_name, - :email => channel.itunes_owner.itunes_email - }) - - assert_equal(subtitle, channel.itunes_subtitle) - assert_equal(subtitle, item.itunes_subtitle) - - assert_equal(summary, channel.itunes_summary) - assert_equal(summary, item.itunes_summary) - end - - def test_setup_maker_with_nested_categories - categories = [["Arts & Entertainment", "Games"], - ["Technology", "Computers"], - "Audio Blogs"] - - feed = RSS::Maker.make("rss2.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - channel = maker.channel - categories.each do |category| - target = channel.itunes_categories - if category.is_a?(Array) - category.each do |sub_category| - target = target.new_category - target.text = sub_category - end - else - target.new_category.text = category - end - end - end - assert_not_nil(feed) - - new_feed = RSS::Maker.make("rss2.0") do |maker| - feed.setup_maker(maker) - end - assert_not_nil(new_feed) - - channel = new_feed.channel - - assert_equal(categories, - collect_itunes_categories(channel.itunes_categories)) - end - - private - def collect_itunes_categories(categories) - categories.collect do |c| - rest = collect_itunes_categories(c.itunes_categories) - if rest.empty? - c.text - else - [c.text, *rest] - end - end - end - end -end diff --git a/ruby/test/rss/test_setup_maker_slash.rb b/ruby/test/rss/test_setup_maker_slash.rb deleted file mode 100644 index d6973bed4..000000000 --- a/ruby/test/rss/test_setup_maker_slash.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: false -require_relative "rss-testcase" - -require "rss/maker" - -module RSS - class TestSetupMakerSlash < TestCase - def test_setup_maker - elements = { - "section" => "articles", - "department" => "not-an-ocean-unless-there-are-lobsters", - "comments" => 177, - "hit_parades" => [177, 155, 105, 33, 6, 3, 0], - } - - rss = RSS::Maker.make("rss1.0") do |maker| - setup_dummy_channel(maker) - setup_dummy_item(maker) - - item = maker.items.last - item.slash_section = elements["section"] - item.slash_department = elements["department"] - item.slash_comments = elements["comments"] - item.slash_hit_parade = elements["hit_parades"].join(",") - end - assert_not_nil(rss) - - new_rss = RSS::Maker.make("rss1.0") do |maker| - rss.setup_maker(maker) - end - assert_not_nil(new_rss) - - item = new_rss.items.last - assert_not_nil(item) - - assert_slash_elements(elements, item) - end - end -end diff --git a/ruby/test/rss/test_slash.rb b/ruby/test/rss/test_slash.rb deleted file mode 100644 index 6746e4488..000000000 --- a/ruby/test/rss/test_slash.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/slash" - -module RSS - class TestSlash < TestCase - def setup - @elements = { - "section" => "articles", - "department" => "not-an-ocean-unless-there-are-lobsters", - "comments" => 177, - "hit_parades" => [177, 155, 105, 33, 6, 3, 0], - } - - slash_nodes = @elements.collect do |name, value| - if name == "hit_parades" - name = "hit_parade" - value = value.join(",") - end - "#{value}" - end.join("\n") - - slash_ns = {"slash" => "http://purl.org/rss/1.0/modules/slash/"} - @source = make_RDF(<<-EOR, slash_ns) -#{make_channel} -#{make_image} -#{make_item(slash_nodes)} -#{make_textinput} -EOR - end - - def test_parser - rss = RSS::Parser.parse(@source) - - assert_not_nil(rss) - - item = rss.items[0] - assert_not_nil(item) - - assert_slash_elements(item) - end - - def test_to_s - rss = RSS::Parser.parse(@source) - rss = RSS::Parser.parse(rss.to_s) - - assert_not_nil(rss) - - item = rss.items[0] - assert_not_nil(item) - - assert_slash_elements(item) - end - - private - def assert_slash_elements(target) - super(@elements, target) - end - end -end diff --git a/ruby/test/rss/test_syndication.rb b/ruby/test/rss/test_syndication.rb deleted file mode 100644 index ec3895eaf..000000000 --- a/ruby/test/rss/test_syndication.rb +++ /dev/null @@ -1,126 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/syndication" - -module RSS - class TestSyndication < TestCase - - def setup - @prefix = "sy" - @uri = "http://purl.org/rss/1.0/modules/syndication/" - - @parents = %w(channel) - - t = Time.iso8601("2000-01-01T12:00:05+00:00") - class << t - alias_method(:to_s, :iso8601) - end - - @elems = { - :updatePeriod => "hourly", - :updateFrequency => "2", - :updateBase => t, - } - - @sy_nodes = @elems.collect do |name, value| - "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}" - end.join("\n") - - @rss_source = make_RDF(<<-EOR, {@prefix => @uri}) -#{make_channel(@sy_nodes)} -#{make_image()} -#{make_item()} -#{make_textinput()} -EOR - - @rss = Parser.parse(@rss_source) - end - - def test_parser - - assert_nothing_raised do - Parser.parse(@rss_source) - end - - @elems.each do |tag, value| - assert_too_much_tag(tag.to_s, "channel") do - Parser.parse(make_RDF(<<-EOR, {@prefix => @uri})) -#{make_channel(("<" + @prefix + ":" + tag.to_s + ">" + - CGI.escapeHTML(value.to_s) + - "") * 2)} -#{make_item} -EOR - end - end - - end - - def test_accessor - - t = Time.iso8601("2003-01-01T12:00:23+09:00") - class << t - alias_method(:to_s, :iso8601) - end - - new_value = { - :updatePeriod => "daily", - :updateFrequency => "11", - :updateBase => t, - } - - @elems.each do |name, value| - value = value.to_i if name == :updateFrequency - @parents.each do |parent| - assert_equal(value, @rss.__send__(parent).__send__("sy_#{name}")) - @rss.__send__(parent).__send__("sy_#{name}=", new_value[name]) - new_val = new_value[name] - new_val = new_val.to_i if name == :updateFrequency - assert_equal(new_val, @rss.__send__(parent).__send__("sy_#{name}")) - end - end - - %w(hourly daily weekly monthly yearly).each do |x| - @parents.each do |parent| - assert_nothing_raised do - @rss.__send__(parent).sy_updatePeriod = x - end - end - end - - %w(-2 0.3 -0.4).each do |x| - @parents.each do |parent| - assert_not_available_value("sy:updateBase", x) do - @rss.__send__(parent).sy_updateBase = x - end - end - end - - end - - def test_to_s - - @elems.each do |name, value| - excepted = "<#{@prefix}:#{name}>#{value}" - @parents.each do |parent| - assert_equal(excepted, - @rss.__send__(parent).__send__("sy_#{name}_element")) - end - end - - REXML::Document.new(@rss_source).root.each_element do |parent| - if @parents.include?(parent.name) - parent.each_element do |elem| - if elem.namespace == @uri - assert_equal(elem.text, @elems[elem.name.intern].to_s) - end - end - end - end - end - end -end diff --git a/ruby/test/rss/test_taxonomy.rb b/ruby/test/rss/test_taxonomy.rb deleted file mode 100644 index 89f49a94c..000000000 --- a/ruby/test/rss/test_taxonomy.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: false -require "cgi" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/2.0" -require "rss/taxonomy" - -module RSS - class TestTaxonomy < TestCase - - def setup - @prefix = "taxo" - @uri = "http://purl.org/rss/1.0/modules/taxonomy/" - @dc_prefix = "dc" - @dc_uri = "http://purl.org/dc/elements/1.1/" - - @ns = { - @prefix => @uri, - @dc_prefix => @dc_uri, - } - - @topics_parents = %w(channel item) - - @topics_lis = [ - "http://meerkat.oreillynet.com/?c=cat23", - "http://meerkat.oreillynet.com/?c=47", - "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/", - ] - - @topics_node = "<#{@prefix}:topics>\n" - @topics_node << " \n" - @topics_lis.each do |value| - resource = CGI.escapeHTML(value) - @topics_node << " \n" - end - @topics_node << " \n" - @topics_node << "" - - @topic_topics_lis = \ - [ - "http://meerkat.oreillynet.com/?c=cat23", - "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/", - "http://dmoz.org/Computers/Programming/Internet/", - ] - - @topic_contents = \ - [ - { - :link => "http://meerkat.oreillynet.com/?c=cat23", - :title => "Data: XML", - :description => "A Meerkat channel", - }, - { - :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/", - :title => "XML", - :subject => "XML", - :description => "DMOZ category", - :topics => @topic_topics_lis, - } - ] - - @topic_nodes = @topic_contents.collect do |info| - link = info[:link] - rv = "<#{@prefix}:topic rdf:about=\"#{link}\">\n" - info.each do |name, value| - case name - when :topics - rv << " <#{@prefix}:topics>\n" - rv << " \n" - value.each do |li| - resource = CGI.escapeHTML(li) - rv << " \n" - end - rv << " \n" - rv << " \n" - else - prefix = (name == :link ? @prefix : @dc_prefix) - rv << " <#{prefix}:#{name}>#{value}\n" - end - end - rv << "" - end - - @rss_source = make_RDF(<<-EOR, @ns) -#{make_channel(@topics_node)} -#{make_image()} -#{make_item(@topics_node)} -#{make_textinput()} -#{@topic_nodes.join("\n")} -EOR - - @rss = Parser.parse(@rss_source) - end - - def test_parser - assert_nothing_raised do - Parser.parse(@rss_source) - end - - assert_too_much_tag("topics", "channel") do - Parser.parse(make_RDF(<<-EOR, @ns)) -#{make_channel(@topics_node * 2)} -#{make_item()} -EOR - end - - assert_too_much_tag("topics", "item") do - Parser.parse(make_RDF(<<-EOR, @ns)) -#{make_channel()} -#{make_item(@topics_node * 2)} -EOR - end - end - - def test_accessor - topics = @rss.channel.taxo_topics - assert_equal(@topics_lis.sort, - topics.Bag.lis.collect {|li| li.resource}.sort) - assert_equal(@topics_lis.sort, topics.resources.sort) - - assert_equal(@rss.taxo_topics.first, @rss.taxo_topic) - - @topic_contents.each_with_index do |info, i| - topic = @rss.taxo_topics[i] - info.each do |name, value| - case name - when :link - assert_equal(value, topic.about) - assert_equal(value, topic.taxo_link) - when :topics - assert_equal(value.sort, topic.taxo_topics.resources.sort) - else - assert_equal(value, topic.__send__("dc_#{name}")) - end - end - end - end - - def test_to_s - @topics_parents.each do |parent| - meth = "taxo_topics_element" - assert_equal(@topics_node, @rss.__send__(parent).__send__(meth)) - end - - @topic_nodes.each_with_index do |node, i| - expected_xml = taxo_xmlns_container(node) - expected = REXML::Document.new(expected_xml).root.elements[1] - actual_xml = taxo_xmlns_container(@rss.taxo_topics[i].to_s(true, "")) - actual = REXML::Document.new(actual_xml).root.elements[1] - expected_elems = expected.reject {|x| x.is_a?(REXML::Text)} - actual_elems = actual.reject {|x| x.is_a?(REXML::Text)} - expected_elems.sort! {|x, y| x.name <=> y.name} - actual_elems.sort! {|x, y| x.name <=> y.name} - assert_equal(expected_elems.collect {|x| x.to_s}, - actual_elems.collect {|x| x.to_s}) - assert_equal(expected.attributes.sort, actual.attributes.sort) - end - end - - private - def taxo_xmlns_container(content) - xmlns_container({ - @prefix => @uri, - "dc" => "http://purl.org/dc/elements/1.1/", - "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - }, - content) - end - end -end - diff --git a/ruby/test/rss/test_to_s.rb b/ruby/test/rss/test_to_s.rb deleted file mode 100644 index bbdd74ef0..000000000 --- a/ruby/test/rss/test_to_s.rb +++ /dev/null @@ -1,701 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/maker" -require "rss/1.0" -require "rss/2.0" -require "rss/content" -require "rss/dublincore" -require "rss/syndication" -require "rss/trackback" - -module RSS - class TestToS < TestCase - def setup - @image_url = "http://example.com/foo.png" - @textinput_link = "http://example.com/search.cgi" - @item_links = [ - "http://example.com/1", - "http://example.com/2", - ] - - setup_xml_declaration_info - setup_xml_stylesheet_infos - setup_channel_info - setup_item_infos - setup_image_info - setup_textinput_info - - setup_dublin_core_info - setup_syndication_info - setup_content_info - setup_trackback_info - end - - def test_to_s_10 - rss = RSS::Maker.make("1.0") do |maker| - setup_full(maker) - end - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel10(@channel_info, rss.channel) - assert_items10(@item_infos, rss.items) - rss.items.each do |item| - assert_trackback(@trackback_info, item) - end - assert_image10(@image_info, rss.image) - assert_textinput10(@textinput_info, rss.textinput) - - rss = RSS::Parser.parse(rss.to_s) - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel10(@channel_info, rss.channel) - assert_items10(@item_infos, rss.items) - assert_image10(@image_info, rss.image) - assert_textinput10(@textinput_info, rss.textinput) - end - - def test_to_s_09 - rss = RSS::Maker.make("0.91") do |maker| - setup_full(maker) - end - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel09(@channel_info, rss.channel) - assert_items09(@item_infos, rss.items) - assert_image09(@image_info, rss.image) - assert_textinput09(@textinput_info, rss.textinput) - - rss = RSS::Parser.parse(rss.to_s) - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel09(@channel_info, rss.channel) - assert_items09(@item_infos, rss.items) - assert_image09(@image_info, rss.image) - assert_textinput09(@textinput_info, rss.textinput) - end - - def test_to_s_20 - rss = RSS::Maker.make("2.0") do |maker| - setup_full(maker) - end - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel20(@channel_info, rss.channel) - assert_items20(@item_infos, rss.items) - assert_image20(@image_info, rss.image) - assert_textinput20(@textinput_info, rss.textinput) - - rss = RSS::Parser.parse(rss.to_s) - - assert_xml_declaration(@version, @encoding, @standalone, rss) - assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets) - assert_channel20(@channel_info, rss.channel) - assert_items20(@item_infos, rss.items) - assert_image20(@image_info, rss.image) - assert_textinput20(@textinput_info, rss.textinput) - end - - def test_time_w3cdtf - assert_equal("2015-09-05T01:25:48.0001Z", - Time.utc(2015, 9, 5, 1, 25, 48, 100).w3cdtf, - '[ruby-core:70667] [Bug #11509]') - end - - def test_20_empty_text - title = "Blog entries" - link = "http://blog.example.com/" - description = "" - rss = RSS::Maker.make("2.0") do |maker| - maker.channel.title = title - maker.channel.link = link - maker.channel.description = description - end - - parsed_rss = RSS::Parser.parse(rss.to_s) - assert_equal({ - title: title, - link: link, - description: description, - }, - { - title: parsed_rss.channel.title, - link: parsed_rss.channel.link, - description: parsed_rss.channel.description, - }, - "[ruby-core:80965] [Bug #13531]") - end - - private - def setup_xml_declaration_info - @version = "1.0" - @encoding = "UTF-8" - @standalone = false - end - - def setup_xml_stylesheet_infos - @xs_infos = [ - { - "href" => "XXX.xsl", - "type" => "text/xsl", - "title" => "XXX", - "media" => "print", - "alternate" => "no", - }, - { - "href" => "YYY.css", - "type" => "text/css", - "title" => "YYY", - "media" => "all", - "alternate" => "no", - }, - ] - end - - def setup_channel_info - @channel_info = { - "about" => "http://example.com/index.rdf", - "title" => "Sample RSS", - "link" => "http://example.com/", - "description" => "Sample\n\n\n\n\nSite", - "language" => "en", - "copyright" => "FDL", - "managingEditor" => "foo@example.com", - "webMaster" => "webmaster@example.com", - "rating" => '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))', - "docs" => "http://backend.userland.com/rss091", - "skipDays" => [ - "Monday", - "Friday", - ], - "skipHours" => [ - "12", - "23", - ], - "date" => Time.now, - "lastBuildDate" => Time.now - 3600, - "generator" => "RSS Maker", - "ttl" => "60", - "cloud" => { - "domain" => "rpc.sys.com", - "port" => "80", - "path" => "/RPC2", - "registerProcedure" => "myCloud.rssPleaseNotify", - "protocol" => "xml-rpc", - }, - "category" => { - "domain" => "http://example.com/misc/", - "content" => "misc", - }, - - "image" => { - "resource" => @image_url, - }, - - "textinput" => { - "resource" => @textinput_link, - }, - - "items" => @item_links.collect{|link| {"resource" => link}}, - } - end - - def setup_item_infos - @item_infos = [ - { - "title" => "Sample item1", - "link" => @item_links[0], - "description" => "Sample description1", - "date" => Time.now - 3600, - "author" => "foo@example.com", - "comments" => "http://example.com/1/comments", - "guid" => { - "isPermaLink" => "true", - "content" => "http://example.com/1", - }, - "enclosure" => { - "url" => "http://example.com/1.mp3", - "length" => "100", - "type" => "audio/mpeg", - }, - "source" => { - "url" => "http:/example.com/", - "content" => "Sample site", - }, - "category" => { - "domain" => "http://example.com/misc/", - "content" => "misc", - }, - }, - - { - "title" => "Sample item2", - "link" => @item_links[1], - "description" => "Sample description2", - "date" => Time.now - 7200, - "author" => "foo@example.com", - "comments" => "http://example.com/2/comments", - "guid" => { - "isPermaLink" => "false", - "content" => "http://example.com/2", - }, - "enclosure" => { - "url" => "http://example.com/2.mp3", - "length" => "200", - "type" => "audio/mpeg", - }, - "source" => { - "url" => "http:/example.com/", - "content" => "Sample site", - }, - "category" => { - "domain" => "http://example.com/misc/", - "content" => "misc", - }, - }, - ] - end - - def setup_image_info - @image_info = { - "title" => "Sample image", - "url" => @image_url, - "width" => "88", - "height" => "31", - "description" => "Sample", - } - end - - def setup_textinput_info - @textinput_info = { - "title" => "Sample textinput", - "description" => "Search", - "name" => "key", - "link" => @textinput_link, - } - end - - def setup_dublin_core_info - @dc_info = { - "title" => "DC title", - "description" => "DC desc", - "creator" => "DC creator", - "subject" => "DC subject", - "publisher" => "DC publisher", - "contributor" => "DC contributor", - "type" => "DC type", - "format" => "DC format", - "identifier" => "DC identifier", - "source" => "DC source", - "language" => "ja", - "relation" => "DC relation", - "coverage" => "DC coverage", - "rights" => "DC rights", - "date" => Time.now - 60, - } - end - - def setup_syndication_info - @sy_info = { - "updatePeriod" => "hourly", - "updateFrequency" => "2", - "updateBase" => Time.now - 3600, - } - end - - def setup_content_info - @content_info = { - "encoded" => "

      p

      ", - } - end - - def setup_trackback_info - @trackback_info = { - "ping" => "http://example.com/tb.cgi?tb_id=XXX", - "abouts" => [ - "http://example.net/tb.cgi?tb_id=YYY", - "http://example.org/tb.cgi?tb_id=ZZZ", - ] - } - end - - - def setup_full(maker) - setup_xml_declaration(maker) - setup_xml_stylesheets(maker) - setup_channel(maker) - setup_image(maker) - setup_items(maker) - setup_textinput(maker) - end - - def setup_xml_declaration(maker) - %w(version encoding standalone).each do |name| - maker.__send__("#{name}=", instance_eval("@#{name}")) - end - end - - def setup_xml_stylesheets(maker) - @xs_infos.each do |info| - xs = maker.xml_stylesheets.new_xml_stylesheet - info.each do |name, value| - xs.__send__("#{name}=", value) - end - end - end - - def setup_channel(maker) - channel = maker.channel - info = @channel_info - - %w(about title link description language copyright - managingEditor webMaster rating docs date - lastBuildDate generator ttl).each do |name| - channel.__send__("#{name}=", info[name]) - end - - skipDays = channel.skipDays - info["skipDays"].each do |day| - new_day = skipDays.new_day - new_day.content = day - end - - skipHours = channel.skipHours - info["skipHours"].each do |hour| - new_hour = skipHours.new_hour - new_hour.content = hour - end - - cloud = channel.cloud - %w(domain port path registerProcedure protocol).each do |name| - cloud.__send__("#{name}=", info["cloud"][name]) - end - - category = channel.categories.new_category - %w(domain content).each do |name| - category.__send__("#{name}=", info["category"][name]) - end - end - - def setup_image(maker) - image = maker.image - info = @image_info - - %w(title url width height description).each do |name| - image.__send__("#{name}=", info[name]) - end - end - - def setup_items(maker) - items = maker.items - - @item_infos.each do |info| - item = items.new_item - %w(title link description date author comments).each do |name| - item.__send__("#{name}=", info[name]) - end - - guid = item.guid - %w(isPermaLink content).each do |name| - guid.__send__("#{name}=", info["guid"][name]) - end - - enclosure = item.enclosure - %w(url length type).each do |name| - enclosure.__send__("#{name}=", info["enclosure"][name]) - end - - source = item.source - %w(url content).each do |name| - source.__send__("#{name}=", info["source"][name]) - end - - category = item.categories.new_category - %w(domain content).each do |name| - category.__send__("#{name}=", info["category"][name]) - end - - setup_trackback(item) - end - end - - def setup_textinput(maker) - textinput = maker.textinput - info = @textinput_info - - %w(title description name link).each do |name| - textinput.__send__("#{name}=", info[name]) - end - end - - def setup_content(target) - prefix = "content" - %w(encoded).each do |name| - target.__send__("#{prefix}_#{name}=", @content_info[name]) - end - end - - def setup_dublin_core(target) - prefix = "dc" - %w(title description creator subject publisher - contributor type format identifier source language - relation coverage rights).each do |name| - target.__send__("#{prefix}_#{name}=", @dc_info[name]) - end - end - - def setup_syndicate(target) - prefix = "sy" - %w(updatePeriod updateFrequency updateBase).each do |name| - target.__send__("#{prefix}_#{name}=", @sy_info[name]) - end - end - - def setup_trackback(target) - target.trackback_ping = @trackback_info["ping"] - @trackback_info["abouts"].each do |about| - new_about = target.trackback_abouts.new_about - new_about.value = about - end - end - - - def assert_channel10(attrs, channel) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - - names = %w(about title link description) - assert_attributes(attrs, names, channel) - - %w(image items textinput).each do |name| - value = n_attrs[name] - if value - target = channel.__send__(name) - __send__("assert_channel10_#{name}", value, target) - end - end - end - end - - def assert_channel10_image(attrs, image) - _wrap_assertion do - assert_attributes(attrs, %w(resource), image) - end - end - - def assert_channel10_textinput(attrs, textinput) - _wrap_assertion do - assert_attributes(attrs, %w(resource), textinput) - end - end - - def assert_channel10_items(attrs, items) - _wrap_assertion do - assert_equal(items.resources, items.Seq.lis.collect {|x| x.resource}) - items.Seq.lis.each_with_index do |li, i| - assert_attributes(attrs[i], %w(resource), li) - end - end - end - - def assert_image10(attrs, image) - _wrap_assertion do - names = %w(about title url link) - assert_attributes(attrs, names, image) - end - end - - def assert_items10(attrs, items) - _wrap_assertion do - names = %w(about title link description) - items.each_with_index do |item, i| - assert_attributes(attrs[i], names, item) - end - end - end - - def assert_textinput10(attrs, textinput) - _wrap_assertion do - names = %w(about title description name link) - assert_attributes(attrs, names, textinput) - end - end - - - def assert_channel09(attrs, channel) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - - names = %w(title description link language rating - copyright pubDate lastBuildDate docs - managingEditor webMaster) - assert_attributes(attrs, names, channel) - - %w(skipHours skipDays).each do |name| - value = n_attrs[name] - if value - target = channel.__send__(name) - __send__("assert_channel09_#{name}", value, target) - end - end - end - end - - def assert_channel09_skipDays(contents, skipDays) - _wrap_assertion do - days = skipDays.days - contents.each_with_index do |content, i| - assert_equal(content, days[i].content) - end - end - end - - def assert_channel09_skipHours(contents, skipHours) - _wrap_assertion do - hours = skipHours.hours - contents.each_with_index do |content, i| - assert_equal(content.to_i, hours[i].content) - end - end - end - - def assert_image09(attrs, image) - _wrap_assertion do - names = %w(url link title description) - names << ["width", :integer] - names << ["height", :integer] - assert_attributes(attrs, names, image) - end - end - - def assert_items09(attrs, items) - _wrap_assertion do - names = %w(title link description) - items.each_with_index do |item, i| - assert_attributes(attrs[i], names, item) - end - end - end - - def assert_textinput09(attrs, textinput) - _wrap_assertion do - names = %w(title description name link) - assert_attributes(attrs, names, textinput) - end - end - - - def assert_channel20(attrs, channel) - _wrap_assertion do - n_attrs = normalized_attrs(attrs) - - names = %w(title link description language copyright - managingEditor webMaster pubDate - lastBuildDate generator docs rating) - names << ["ttl", :integer] - assert_attributes(attrs, names, channel) - - %w(cloud categories skipHours skipDays).each do |name| - value = n_attrs[name] - if value - target = channel.__send__(name) - __send__("assert_channel20_#{name}", value, target) - end - end - end - end - - def assert_channel20_skipDays(contents, skipDays) - assert_channel09_skipDays(contents, skipDays) - end - - def assert_channel20_skipHours(contents, skipHours) - assert_channel09_skipHours(contents, skipHours) - end - - def assert_channel20_cloud(attrs, cloud) - _wrap_assertion do - names = %w(domain path registerProcedure protocol) - names << ["port", :integer] - assert_attributes(attrs, names, cloud) - end - end - - def assert_channel20_categories(attrs, categories) - _wrap_assertion do - names = %w(domain content) - categories.each_with_index do |category, i| - assert_attributes(attrs[i], names, category) - end - end - end - - def assert_image20(attrs, image) - _wrap_assertion do - names = %w(url link title description) - names << ["width", :integer] - names << ["height", :integer] - assert_attributes(attrs, names, image) - end - end - - def assert_items20(attrs, items) - _wrap_assertion do - names = %w(about title link description) - items.each_with_index do |item, i| - assert_attributes(attrs[i], names, item) - - n_attrs = normalized_attrs(attrs[i]) - - %w(source enclosure categories guid).each do |name| - value = n_attrs[name] - if value - target = item.__send__(name) - __send__("assert_items20_#{name}", value, target) - end - end - end - end - end - - def assert_items20_source(attrs, source) - _wrap_assertion do - assert_attributes(attrs, %w(url content), source) - end - end - - def assert_items20_enclosure(attrs, enclosure) - _wrap_assertion do - names = ["url", ["length", :integer], "type"] - assert_attributes(attrs, names, enclosure) - end - end - - def assert_items20_categories(attrs, categories) - _wrap_assertion do - assert_channel20_categories(attrs, categories) - end - end - - def assert_items20_guid(attrs, guid) - _wrap_assertion do - names = [["isPermaLink", :boolean], ["content"]] - assert_attributes(attrs, names, guid) - end - end - - def assert_textinput20(attrs, textinput) - _wrap_assertion do - names = %w(title description name link) - assert_attributes(attrs, names, textinput) - end - end - end -end diff --git a/ruby/test/rss/test_trackback.rb b/ruby/test/rss/test_trackback.rb deleted file mode 100644 index 2910b4b34..000000000 --- a/ruby/test/rss/test_trackback.rb +++ /dev/null @@ -1,136 +0,0 @@ -# frozen_string_literal: false -require "cgi" -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/2.0" -require "rss/trackback" - -module RSS - class TestTrackBack < TestCase - - def setup - @prefix = "trackback" - @uri = "http://madskills.com/public/xml/rss/module/trackback/" - - @parents = %w(item) - - @elems = { - :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback", - :about => "http://foo.com/trackback/tb.cgi?tb_id=20020923", - } - - @content_nodes = @elems.collect do |name, value| - "<#{@prefix}:#{name} rdf:resource=\"#{CGI.escapeHTML(value.to_s)}\"/>" - end.join("\n") - - @content_nodes2 = @elems.collect do |name, value| - "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}" - end.join("\n") - - @rss_source = make_RDF(<<-EOR, {@prefix => @uri}) -#{make_channel()} -#{make_image()} -#{make_item(@content_nodes)} -#{make_textinput()} -EOR - - @rss = Parser.parse(@rss_source) - - @rss20_source = make_rss20(nil, {@prefix => @uri}) do - make_channel20(nil) do - make_item20(@content_nodes2) - end - end - - @rss20 = Parser.parse(@rss20_source, false) - end - - def test_parser - - assert_nothing_raised do - Parser.parse(@rss_source) - end - - @elems.find_all{|k, v| k == :ping}.each do |tag, value| - assert_too_much_tag(tag.to_s, "item") do - Parser.parse(make_RDF(<<-EOR, {@prefix => @uri})) -#{make_channel()} -#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" + - CGI.escapeHTML(value.to_s) + - "\"/>") * 2)} -EOR - end - end - - @elems.find_all{|k, v| k == :about}.each do |tag, value| - assert_missing_tag("trackback:ping", "item") do - Parser.parse(make_RDF(<<-EOR, {@prefix => @uri})) -#{make_channel()} -#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" + - CGI.escapeHTML(value.to_s) + - "\"/>") * 2)} -EOR - end - - end - - end - - def test_accessor - - new_value = { - :ping => "http://baz.com/trackback/tb.cgi?tb_id=20030808", - :about => "http://hoge.com/trackback/tb.cgi?tb_id=90030808", - } - - @elems.each do |name, value| - @parents.each do |parent| - accessor = "#{RSS::TRACKBACK_PREFIX}_#{name}" - target = @rss.__send__(parent) - target20 = @rss20.channel.__send__(parent, -1) - assert_equal(value, target.__send__(accessor)) - assert_equal(value, target20.__send__(accessor)) - if name == :about - # abount is zero or more - target.__send__("#{accessor}=", 0, new_value[name].to_s) - target20.__send__("#{accessor}=", 0, new_value[name].to_s) - else - target.__send__("#{accessor}=", new_value[name].to_s) - target20.__send__("#{accessor}=", new_value[name].to_s) - end - assert_equal(new_value[name], target.__send__(accessor)) - assert_equal(new_value[name], target20.__send__(accessor)) - end - end - - end - - def test_to_s - - @elems.each do |name, value| - excepted = %Q!<#{@prefix}:#{name} rdf:resource="#{CGI.escapeHTML(value)}"/>! - @parents.each do |parent| - meth = "#{RSS::TRACKBACK_PREFIX}_#{name}_element" - meth << "s" if name == :about - assert_equal(excepted, @rss.__send__(parent).__send__(meth)) - end - end - - REXML::Document.new(@rss_source).root.each_element do |parent| - if @parents.include?(parent.name) - parent.each_element do |elem| - if elem.namespace == @uri - assert_equal(elem.attributes["resource"], @elems[elem.name.intern]) - end - end - end - end - - end - - end -end - diff --git a/ruby/test/rss/test_xml-stylesheet.rb b/ruby/test/rss/test_xml-stylesheet.rb deleted file mode 100644 index 71be1d8fe..000000000 --- a/ruby/test/rss/test_xml-stylesheet.rb +++ /dev/null @@ -1,109 +0,0 @@ -# frozen_string_literal: false -require "rexml/document" - -require_relative "rss-testcase" - -require "rss/1.0" -require "rss/xml-stylesheet" - -module RSS - class TestXMLStyleSheet < TestCase - - def test_accessor - [ - {:href => "a.xsl", :type => "text/xsl"}, - {:media => "print", :title => "FOO"}, - {:charset => "UTF-8", :alternate => "yes"}, - ].each do |attrs| - assert_xml_stylesheet_attrs(attrs, XMLStyleSheet.new(attrs)) - end - end - - def test_to_s - [ - {:href => "a.xsl", :type => "text/xsl"}, - {:type => "text/xsl"}, - {:href => "a.xsl", :guess_type => "text/xsl"}, - {:href => "a.css", :type => "text/css"}, - {:href => "a.css", :type => "text/xsl", - :guess_type => "text/css"}, - {:href => "a.xsl", :type => "text/xsl", - :title => "sample", :media => "printer", - :charset => "UTF-8", :alternate => "yes"}, - {:href => "a.css", :guess_type => "text/css", - :alternate => "no"}, - {:type => "text/xsl", :title => "sample", - :media => "printer", :charset => "UTF-8", - :alternate => "yes"}, - ].each do |attrs| - target, contents = parse_pi(XMLStyleSheet.new(attrs).to_s) - assert_xml_stylesheet(target, attrs, XMLStyleSheet.new(contents)) - end - end - - def test_bad_alternate - %w(a ___ ??? BAD_ALTERNATE).each do |value| - xss = XMLStyleSheet.new - assert_raise(NotAvailableValueError) do - xss.alternate = value - end - xss.do_validate = false - assert_nothing_raised do - xss.alternate = value - end - assert_nil(xss.alternate) - end - end - - def test_parse - [ - [{:href => "a.xsl", :type => "text/xsl"},], - [{:media => "print", :title => "FOO"},], - [{:charset => "UTF-8", :alternate => "yes"},], - [{:href => "a.xsl", :type => "text/xsl"}, - {:type => "text/xsl"}, - {:href => "a.xsl", :guess_type => "text/xsl"}, - {:href => "a.css", :type => "text/css"}, - {:href => "a.css", :type => "text/xsl", - :guess_type => "text/css"}, - {:href => "a.xsl", :type => "text/xsl", - :title => "sample", :media => "printer", - :charset => "UTF-8", :alternate => "yes"}, - {:href => "a.css", :guess_type => "text/css", - :alternate => "no"}, - {:type => "text/xsl", :title => "sample", - :media => "printer", :charset => "UTF-8", - :alternate => "yes"},], - ].each do |xsss| - doc = REXML::Document.new(make_sample_RDF) - root = doc.root - xsss.each do |xss| - content = xss.collect do |key, name| - %Q[#{key}="#{name}"] - end.join(" ") - pi = REXML::Instruction.new("xml-stylesheet", content) - root.previous_sibling = pi - end - rss = Parser.parse(doc.to_s) - have_href_xsss = xsss.find_all {|xss| xss.has_key?(:href)} - assert_equal(have_href_xsss.size, rss.xml_stylesheets.size) - rss.xml_stylesheets.each_with_index do |stylesheet, i| - target, = parse_pi(stylesheet.to_s) - assert_xml_stylesheet(target, have_href_xsss[i], stylesheet) - end - end - end - - def parse_pi(pi) - /\A\s*<\?(\S+)([^?]*\?+(?:[^?>][^?]*\?+)*)>\s*\z/ =~ pi - target = $1 - dummy = REXML::Document.new("").root - contents = {} - dummy.attributes.each do |name, value| - contents[name] = value - end - [target, contents] - end - - end -end diff --git a/ruby/test/ruby/enc/test_emoji_breaks.rb b/ruby/test/ruby/enc/test_emoji_breaks.rb index 7048d8d59..cdde4da9b 100644 --- a/ruby/test/ruby/enc/test_emoji_breaks.rb +++ b/ruby/test/ruby/enc/test_emoji_breaks.rb @@ -13,7 +13,7 @@ def initialize(filename, line_number, data, comment='') @filename = filename @line_number = line_number @comment = comment.gsub(/\s+/, ' ').strip - if filename=='emoji-test' + if filename=='emoji-test' or filename=='emoji-variation-sequences' codes, @type = data.split(/\s*;\s*/) @shortname = '' else @@ -31,22 +31,42 @@ def initialize(filename, line_number, data, comment='') end end +class TestEmojiBreaks::BreakFile + attr_reader :basename, :fullname, :version + FILES = [] + + def initialize(basename, path, version) + @basename = basename + @fullname = "#{path}/#{basename}.txt" # File.expand_path(path + version, __dir__) + @version = version + FILES << self + end + + def self.files + FILES + end +end + class TestEmojiBreaks < Test::Unit::TestCase - EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-variation-sequences emoji-zwj-sequences] - EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION'] - EMOJI_DATA_PATH = File.expand_path("../../../enc/unicode/data/emoji/#{EMOJI_VERSION}", __dir__) + UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION'] + UNICODE_DATA_PATH = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}/ucd/emoji", __dir__) + EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION'] + EMOJI_DATA_PATH = File.expand_path("../../../enc/unicode/data/emoji/#{EMOJI_VERSION}", __dir__) - def self.expand_filename(basename) - File.expand_path("#{EMOJI_DATA_PATH}/#{basename}.txt", __dir__) + EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-zwj-sequences].map do |basename| + BreakFile.new(basename, EMOJI_DATA_PATH, EMOJI_VERSION) end + UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION[0..-3]) # [0..-3] deals with a versioning mismatch problem in Unicode + EMOJI_DATA_FILES << UNICODE_DATA_FILE def self.data_files_available? EMOJI_DATA_FILES.all? do |f| - File.exist?(expand_filename(f)) + File.exist?(f.fullname) end end def test_data_files_available + assert_equal 4, EMOJI_DATA_FILES.size # debugging test unless TestEmojiBreaks.data_files_available? skip "Emoji data files not available in #{EMOJI_DATA_PATH}." end @@ -56,17 +76,26 @@ def test_data_files_available TestEmojiBreaks.data_files_available? and class TestEmojiBreaks def read_data tests = [] - EMOJI_DATA_FILES.each do |filename| + EMOJI_DATA_FILES.each do |file| version_mismatch = true file_tests = [] - IO.foreach(TestEmojiBreaks.expand_filename(filename), encoding: Encoding::UTF_8) do |line| + IO.foreach(file.fullname, encoding: Encoding::UTF_8) do |line| line.chomp! - raise "File Name Mismatch" if $.==1 and not line=="# #{filename}.txt" - version_mismatch = false if line=="# Version: #{EMOJI_VERSION}" - next if /\A(#|\z)/.match? line - file_tests << BreakTest.new(filename, $., *line.split('#')) rescue 'whatever' + raise "File Name Mismatch: line: #{line}, expected filename: #{file.basename}.txt" if $.==1 and not line=="# #{file.basename}.txt" + version_mismatch = false if line =~ /^# Version: #{file.version}/ + next if line.match?(/\A(#|\z)/) + if line =~ /^(\h{4,6})\.\.(\h{4,6}) *(;.+)/ # deal with Unicode ranges in emoji-sequences.txt (Bug #18028) + range_start = $1.to_i(16) + range_end = $2.to_i(16) + rest = $3 + (range_start..range_end).each do |code_point| + file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2)) + end + else + file_tests << BreakTest.new(file.basename, $., *line.split('#', 2)) + end end - raise "File Version Mismatch" if version_mismatch + raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch tests += file_tests end tests diff --git a/ruby/test/ruby/enc/test_regex_casefold.rb b/ruby/test/ruby/enc/test_regex_casefold.rb index 2b252bd44..ec5dc7f22 100644 --- a/ruby/test/ruby/enc/test_regex_casefold.rb +++ b/ruby/test/ruby/enc/test_regex_casefold.rb @@ -11,7 +11,7 @@ class TestCaseFold < Test::Unit::TestCase def check_downcase_properties(expected, start, *flags) assert_equal expected, start.downcase(*flags) - temp = start + temp = start.dup assert_equal expected, temp.downcase!(*flags) assert_equal expected, expected.downcase(*flags) temp = expected diff --git a/ruby/test/ruby/marshaltestlib.rb b/ruby/test/ruby/marshaltestlib.rb index 5c48a8d85..7f100b787 100644 --- a/ruby/test/ruby/marshaltestlib.rb +++ b/ruby/test/ruby/marshaltestlib.rb @@ -112,7 +112,7 @@ def test_exception marshal_equal(Exception.new('foo')) {|o| o.message} obj = Object.new e = assert_raise(NoMethodError) {obj.no_such_method()} - marshal_equal(e) {|o| o.message} + marshal_equal(e) {|o| o.message.lines.first.chomp} end def test_exception_subclass diff --git a/ruby/test/ruby/test_alias.rb b/ruby/test/ruby/test_alias.rb index 33fb82e1d..99f2223b4 100644 --- a/ruby/test/ruby/test_alias.rb +++ b/ruby/test/ruby/test_alias.rb @@ -35,6 +35,18 @@ def quux end end + class Alias4 < Alias0 + alias foo1 foo + alias foo2 foo1 + alias foo3 foo2 + end + + class Alias5 < Alias4 + alias foo1 foo + alias foo3 foo2 + alias foo2 foo1 + end + def test_alias x = Alias2.new assert_equal "foo", x.bar @@ -47,6 +59,20 @@ def test_alias assert_raise(NoMethodError) { x.quux } end + def test_alias_inspect + o = Alias4.new + assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1]) + assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1]) + assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1]) + assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1]) + + o = Alias5.new + assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1]) + assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1]) + assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1]) + assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1]) + end + def test_nonexistmethod assert_raise(NameError){ Class.new{ @@ -227,4 +253,33 @@ def self.method_added(mid) assert_equal(:foo, k.instance_method(:bar).original_name) assert_equal(:foo, name) end + + def test_alias_suppressing_redefinition + assert_in_out_err(%w[-w], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + class A + def foo; end + alias foo foo + def foo; end + end + end; + end + + def test_alias_memory_leak + assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true) + begin; + class A + 500.times do + 1000.times do |i| + define_method(:"foo_#{i}") {} + + alias :"foo_#{i}" :"foo_#{i}" + + remove_method :"foo_#{i}" + end + GC.start + end + end + end; + end end diff --git a/ruby/test/ruby/test_argf.rb b/ruby/test/ruby/test_argf.rb index 277fa368f..e3bd1cd07 100644 --- a/ruby/test/ruby/test_argf.rb +++ b/ruby/test/ruby/test_argf.rb @@ -387,6 +387,21 @@ def test_inplace_suffix_encoding assert_equal("foo", File.read(name+suffix)) end + def test_inplace_bug_17117 + assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}") + {# + #!/usr/bin/ruby -pi.bak + BEGIN { + GC.start + arr = [] + 1000000.times { |x| arr << "fooo#{x}" } + } + puts "hello" + }; + assert_equal("hello\n1\nhello\n2\n", File.read(@t1.path)) + assert_equal("1\n2\n", File.read("#{@t1.path}.bak")) + end + def test_encoding ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| {# @@ -730,6 +745,18 @@ def test_each_line_chomp ["\"a\\n\"", "\"b\\n\""], []) assert_in_out_err(['-e', 'ARGF.each_line(chomp: true) {|para| p para}'], "a\nb\n", ["\"a\"", "\"b\""], []) + + t = make_tempfile + argf = ARGF.class.new(t.path) + lines = [] + begin + argf.each_line(chomp: true) do |line| + lines << line + end + ensure + argf.close + end + assert_equal(%w[foo bar baz], lines) end def test_each_byte @@ -978,53 +1005,55 @@ def test_unreadable assert_nil(argf.gets, bug4274) end - def test_readlines_twice - bug5952 = '[ruby-dev:45160]' - assert_ruby_status(["-e", "2.times {STDIN.tty?; readlines}"], "", bug5952) + def test_readlines_chomp + t = make_tempfile + argf = ARGF.class.new(t.path) + begin + assert_equal(%w[foo bar baz], argf.readlines(chomp: true)) + ensure + argf.close + end + + assert_in_out_err(['-e', 'p readlines(chomp: true)'], "a\nb\n", + ["[\"a\", \"b\"]"], []) end - def test_lines - ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| - {# - $stderr = $stdout - s = [] - ARGF.lines {|l| s << l } - p s - }; - assert_match(/deprecated/, f.gets) - assert_equal("[\"1\\n\", \"2\\n\", \"3\\n\", \"4\\n\", \"5\\n\", \"6\\n\"]\n", f.read) + def test_readline_chomp + t = make_tempfile + argf = ARGF.class.new(t.path) + begin + assert_equal("foo", argf.readline(chomp: true)) + ensure + argf.close end + + assert_in_out_err(['-e', 'p readline(chomp: true)'], "a\nb\n", + ["\"a\""], []) end - def test_bytes - ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| - {# - $stderr = $stdout - print Marshal.dump(ARGF.bytes.to_a) - }; - assert_match(/deprecated/, f.gets) - assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read)) + def test_gets_chomp + t = make_tempfile + argf = ARGF.class.new(t.path) + begin + assert_equal("foo", argf.gets(chomp: true)) + ensure + argf.close end + + assert_in_out_err(['-e', 'p gets(chomp: true)'], "a\nb\n", + ["\"a\""], []) end - def test_chars - ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| - {# - $stderr = $stdout - print [Marshal.dump(ARGF.chars.to_a)].pack('m') - }; - assert_match(/deprecated/, f.gets) - assert_equal(["1", "\n", "2", "\n", "3", "\n", "4", "\n", "5", "\n", "6", "\n"], Marshal.load(f.read.unpack('m').first)) - end + def test_readlines_twice + bug5952 = '[ruby-dev:45160]' + assert_ruby_status(["-e", "2.times {STDIN.tty?; readlines}"], "", bug5952) end - def test_codepoints + def test_each_codepoint ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| {# - $stderr = $stdout - print Marshal.dump(ARGF.codepoints.to_a) + print Marshal.dump(ARGF.each_codepoint.to_a) }; - assert_match(/deprecated/, f.gets) assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read)) end end @@ -1081,4 +1110,23 @@ def test_wrong_type assert_raise(TypeError, bug11610) {gets} }; end + + def test_sized_read + s = "a" + [@t1, @t2, @t3].each { |t| + File.binwrite(t.path, s) + s = s.succ + } + + ruby('-e', "print ARGF.read(3)", @t1.path, @t2.path, @t3.path) do |f| + assert_equal("abc", f.read) + end + + argf = ARGF.class.new(@t1.path, @t2.path, @t3.path) + begin + assert_equal("abc", argf.read(3)) + ensure + argf.close + end + end end diff --git a/ruby/test/ruby/test_arithmetic_sequence.rb b/ruby/test/ruby/test_arithmetic_sequence.rb index 45a0ab922..5e2a82526 100644 --- a/ruby/test/ruby/test_arithmetic_sequence.rb +++ b/ruby/test/ruby/test_arithmetic_sequence.rb @@ -162,11 +162,6 @@ def test_first assert_equal([], seq.first(1)) assert_equal([], seq.first(3)) - seq = 1.step(10, by: 0) - assert_equal(1, seq.first) - assert_equal([1], seq.first(1)) - assert_equal([1, 1, 1], seq.first(3)) - seq = 10.0.step(-1.0, by: -2.0) assert_equal(10.0, seq.first) assert_equal([10.0], seq.first(1)) @@ -269,6 +264,11 @@ def test_last_with_rational assert_instance_of Integer, res[1] end + def test_last_bug17218 + seq = (1.0997r .. 1.1r).step(0.0001r) + assert_equal(1.1r, seq.last, '[ruby-core:100312] [Bug #17218]') + end + def test_to_a assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1.step(10).to_a) assert_equal([1, 3, 5, 7, 9], 1.step(10, 2).to_a) @@ -284,6 +284,11 @@ def test_to_a_bug15444 '[ruby-core:90648] [Bug #15444]') end + def test_to_a_bug17218 + seq = (1.0997r .. 1.1r).step(0.0001r) + assert_equal([1.0997r, 1.0998r, 1.0999r, 1.1r], seq.to_a, '[ruby-core:100312] [Bug #17218]') + end + def test_slice seq = 1.step(10, 2) assert_equal([[1, 3, 5], [7, 9]], seq.each_slice(3).to_a) @@ -340,9 +345,6 @@ def test_next [10, 8, 6, 4, 2].each do |i| assert_equal(i, seq.next) end - - seq = ((1/10r)..(1/2r)).step(0) - assert_equal(1/10r, seq.next) end def test_next_bug15444 diff --git a/ruby/test/ruby/test_array.rb b/ruby/test/ruby/test_array.rb index 476cf795f..a97a9c255 100644 --- a/ruby/test/ruby/test_array.rb +++ b/ruby/test/ruby/test_array.rb @@ -7,7 +7,6 @@ class TestArray < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil @cls = Array end @@ -15,6 +14,11 @@ def teardown $VERBOSE = @verbose end + def assert_equal_instance(x, y, *msg) + assert_equal(x, y, *msg) + assert_instance_of(x.class, y) + end + def test_percent_i assert_equal([:foo, :bar], %i[foo bar]) assert_equal([:"\"foo"], %i["foo]) @@ -114,6 +118,9 @@ def test_misc_0 assert_equal('1', (x * 1).join(":")) assert_equal('', (x * 0).join(":")) + assert_instance_of(Array, (@cls[] * 5)) + assert_instance_of(Array, (@cls[1] * 5)) + *x = *(1..7).to_a assert_equal(7, x.size) assert_equal([1, 2, 3, 4, 5, 6, 7], x) @@ -645,8 +652,17 @@ def test_concat b.concat(b, b) assert_equal([4, 5, 4, 5, 4, 5], b) - assert_raise(TypeError) { [0].concat(:foo) } - assert_raise(FrozenError) { [0].freeze.concat(:foo) } + assert_raise(TypeError) { @cls[0].concat(:foo) } + assert_raise(FrozenError) { @cls[0].freeze.concat(:foo) } + + a = @cls[nil] + def (x = Object.new).to_ary + ary = Array.new(2) + ary << [] << [] << :ok + end + EnvUtil.under_gc_stress {a.concat(x)} + GC.start + assert_equal(:ok, a.last) end def test_count @@ -654,7 +670,7 @@ def test_count assert_equal(5, a.count) assert_equal(2, a.count(1)) assert_equal(3, a.count {|x| x % 2 == 1 }) - assert_equal(2, a.count(1) {|x| x % 2 == 1 }) + assert_equal(2, assert_warning(/given block not used/) {a.count(1) {|x| x % 2 == 1 }}) assert_raise(ArgumentError) { a.count(0, 1) } bug8654 = '[ruby-core:56072]' @@ -747,6 +763,15 @@ def test_delete_if a = @cls[ 5, 6, 7, 8, 9, 10 ] assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7}) assert_equal(@cls[7, 8, 9, 10], a, bug2545) + + assert_raise(FrozenError) do + a = @cls[1, 2, 3, 42] + a.delete_if do + a.freeze + true + end + end + assert_equal(@cls[1, 2, 3, 42], a) end def test_dup @@ -842,14 +867,14 @@ def test_flatten a2 = @cls[ 5, 6 ] a3 = @cls[ 4, a2 ] a4 = @cls[ a1, a3 ] - assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten) - assert_equal(@cls[ a1, a3], a4) + assert_equal_instance([1, 2, 3, 4, 5, 6], a4.flatten) + assert_equal_instance(@cls[ a1, a3], a4) a5 = @cls[ a1, @cls[], a3 ] - assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten) - assert_equal(@cls[1, 2, 3, 4, [5, 6]], a5.flatten(1)) - assert_equal(@cls[], @cls[].flatten) - assert_equal(@cls[], + assert_equal_instance([1, 2, 3, 4, 5, 6], a5.flatten) + assert_equal_instance([1, 2, 3, 4, [5, 6]], a5.flatten(1)) + assert_equal_instance([], @cls[].flatten) + assert_equal_instance([], @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten) end @@ -886,6 +911,17 @@ def m; end assert_raise(NoMethodError, bug12738) { a.flatten.m } end + def test_flatten_recursive + a = [] + a << a + assert_raise(ArgumentError) { a.flatten } + b = [1]; c = [2, b]; b << c + assert_raise(ArgumentError) { b.flatten } + + assert_equal([1, 2, b], b.flatten(1)) + assert_equal([1, 2, 1, 2, 1, c], b.flatten(4)) + end + def test_flatten! a1 = @cls[ 1, 2, 3] a2 = @cls[ 5, 6 ] @@ -1073,6 +1109,19 @@ def test_include? assert_not_include(a, [1,2]) end + def test_intersect? + a = @cls[ 1, 2, 3] + assert_send([a, :intersect?, [3]]) + assert_not_send([a, :intersect?, [4]]) + assert_not_send([a, :intersect?, []]) + end + + def test_intersect_big_array + assert_send([@cls[ 1, 4, 5 ]*64, :intersect?, @cls[ 1, 2, 3 ]*64]) + assert_not_send([@cls[ 1, 2, 3 ]*64, :intersect?, @cls[ 4, 5, 6 ]*64]) + assert_not_send([@cls[], :intersect?, @cls[ 1, 2, 3 ]*64]) + end + def test_index a = @cls[ 'cat', 99, /a/, 99, @cls[ 1, 2, 3] ] assert_equal(0, a.index('cat')) @@ -1081,7 +1130,7 @@ def test_index assert_nil(a.index('ca')) assert_nil(a.index([1,2])) - assert_equal(1, a.index(99) {|x| x == 'cat' }) + assert_equal(1, assert_warn(/given block not used/) {a.index(99) {|x| x == 'cat' }}) end def test_values_at @@ -1092,42 +1141,42 @@ def test_values_at end def test_join - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[] - assert_equal("", a.join) + assert_equal("", assert_deprecated_warn(/non-nil value/) {a.join}) assert_equal("", a.join(',')) - assert_equal(Encoding::US_ASCII, a.join.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {a.join}.encoding) - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[1, 2] - assert_equal("12", a.join) - assert_equal("12", a.join(nil)) + assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join}) + assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) assert_equal("1,2", a.join(',')) - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[1, 2, 3] - assert_equal("123", a.join) - assert_equal("123", a.join(nil)) + assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join}) + assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) assert_equal("1,2,3", a.join(',')) - $, = ":" + assert_deprecated_warning {$, = ":"} a = @cls[1, 2, 3] - assert_equal("1:2:3", a.join) - assert_equal("1:2:3", a.join(nil)) + assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join}) + assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) assert_equal("1,2,3", a.join(',')) - $, = "" + assert_deprecated_warning {$, = ""} e = ''.force_encoding('EUC-JP') u = ''.force_encoding('UTF-8') - assert_equal(Encoding::US_ASCII, [[]].join.encoding) - assert_equal(Encoding::US_ASCII, [1, [u]].join.encoding) - assert_equal(Encoding::UTF_8, [u, [e]].join.encoding) - assert_equal(Encoding::UTF_8, [u, [1]].join.encoding) - assert_equal(Encoding::UTF_8, [Struct.new(:to_str).new(u)].join.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[]].join}.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[1, [u]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [e]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [1]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[Struct.new(:to_str).new(u)].join}.encoding) bug5379 = '[ruby-core:39776]' - assert_equal(Encoding::US_ASCII, [[], u, nil].join.encoding, bug5379) - assert_equal(Encoding::UTF_8, [[], "\u3042", nil].join.encoding, bug5379) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[], u, nil].join}.encoding, bug5379) + assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[[], "\u3042", nil].join}.encoding, bug5379) ensure $, = nil end @@ -1304,6 +1353,15 @@ def test_reject! a = @cls[ 5, 6, 7, 8, 9, 10 ] assert_equal(9, a.reject! {|i| break i if i > 8; i < 7}) assert_equal(@cls[7, 8, 9, 10], a, bug2545) + + assert_raise(FrozenError) do + a = @cls[1, 2, 3, 42] + a.reject! do + a.freeze + true + end + end + assert_equal(@cls[1, 2, 3, 42], a) end def test_shared_array_reject! @@ -1421,7 +1479,7 @@ def test_rindex assert_nil(a.rindex('ca')) assert_nil(a.rindex([1,2])) - assert_equal(3, a.rindex(99) {|x| x == [1,2,3] }) + assert_equal(3, assert_warning(/given block not used/) {a.rindex(99) {|x| x == [1,2,3] }}) bug15951 = "[Bug #15951]" o2 = Object.new @@ -1461,35 +1519,74 @@ def test_slice assert_equal(1, a.slice(-100)) assert_nil(a.slice(-101)) - assert_equal(@cls[1], a.slice(0,1)) - assert_equal(@cls[100], a.slice(99,1)) - assert_equal(@cls[], a.slice(100,1)) - assert_equal(@cls[100], a.slice(99,100)) - assert_equal(@cls[100], a.slice(-1,1)) - assert_equal(@cls[99], a.slice(-2,1)) + assert_equal_instance([1], a.slice(0,1)) + assert_equal_instance([100], a.slice(99,1)) + assert_equal_instance([], a.slice(100,1)) + assert_equal_instance([100], a.slice(99,100)) + assert_equal_instance([100], a.slice(-1,1)) + assert_equal_instance([99], a.slice(-2,1)) - assert_equal(@cls[10, 11, 12], a.slice(9, 3)) - assert_equal(@cls[10, 11, 12], a.slice(-91, 3)) + assert_equal_instance([10, 11, 12], a.slice(9, 3)) + assert_equal_instance([10, 11, 12], a.slice(-91, 3)) assert_nil(a.slice(-101, 2)) - assert_equal(@cls[1], a.slice(0..0)) - assert_equal(@cls[100], a.slice(99..99)) - assert_equal(@cls[], a.slice(100..100)) - assert_equal(@cls[100], a.slice(99..200)) - assert_equal(@cls[100], a.slice(-1..-1)) - assert_equal(@cls[99], a.slice(-2..-2)) - - assert_equal(@cls[10, 11, 12], a.slice(9..11)) - assert_equal(@cls[98, 99, 100], a.slice(97..)) - assert_equal(@cls[10, 11, 12], a.slice(-91..-89)) - assert_equal(@cls[10, 11, 12], a.slice(-91..-89)) + assert_equal_instance([1], a.slice(0..0)) + assert_equal_instance([100], a.slice(99..99)) + assert_equal_instance([], a.slice(100..100)) + assert_equal_instance([100], a.slice(99..200)) + assert_equal_instance([100], a.slice(-1..-1)) + assert_equal_instance([99], a.slice(-2..-2)) + + assert_equal_instance([10, 11, 12], a.slice(9..11)) + assert_equal_instance([98, 99, 100], a.slice(97..)) + assert_equal_instance([10, 11, 12], a.slice(-91..-89)) + assert_equal_instance([10, 11, 12], a.slice(-91..-89)) + + assert_equal_instance([5, 8, 11], a.slice((4..12)%3)) + assert_equal_instance([95, 97, 99], a.slice((94..)%2)) + + # [0] [1] [2] [3] [4] [5] [6] [7] + # ary = [ 1 2 3 4 5 6 7 8 ... ] + # (0) (1) (2) <- (..7) % 3 + # (2) (1) (0) <- (7..) % -3 + assert_equal_instance([1, 4, 7], a.slice((..7)%3)) + assert_equal_instance([8, 5, 2], a.slice((7..)% -3)) + + # [-98] [-97] [-96] [-95] [-94] [-93] [-92] [-91] [-90] + # ary = [ ... 3 4 5 6 7 8 9 10 11 ... ] + # (0) (1) (2) <- (-98..-90) % 3 + # (2) (1) (0) <- (-90..-98) % -3 + assert_equal_instance([3, 6, 9], a.slice((-98..-90)%3)) + assert_equal_instance([11, 8, 5], a.slice((-90..-98)% -3)) + + # [ 48] [ 49] [ 50] [ 51] [ 52] [ 53] + # [-52] [-51] [-50] [-49] [-48] [-47] + # ary = [ ... 49 50 51 52 53 54 ... ] + # (0) (1) (2) <- (48..-47) % 2 + # (2) (1) (0) <- (-47..48) % -2 + assert_equal_instance([49, 51, 53], a.slice((48..-47)%2)) + assert_equal_instance([54, 52, 50], a.slice((-47..48)% -2)) + + idx = ((3..90) % 2).to_a + assert_equal_instance(a.values_at(*idx), a.slice((3..90)%2)) + idx = 90.step(3, -2).to_a + assert_equal_instance(a.values_at(*idx), a.slice((90 .. 3)% -2)) + end + + def test_slice_out_of_range + a = @cls[*(1..100).to_a] assert_nil(a.slice(-101..-1)) assert_nil(a.slice(-101..)) + assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.slice((-101..-1)%2) } + assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.slice((-101..)%2) } + assert_nil(a.slice(10, -3)) assert_equal @cls[], a.slice(10..7) + + assert_equal([100], a.slice(-1, 1_000_000_000)) end def test_slice! @@ -1502,15 +1599,18 @@ def test_slice! assert_equal(@cls[1, 2, 3, 5], a) a = @cls[1, 2, 3, 4, 5] - assert_equal(@cls[3,4], a.slice!(2,2)) + s = a.slice!(2,2) + assert_equal_instance([3,4], s) assert_equal(@cls[1, 2, 5], a) a = @cls[1, 2, 3, 4, 5] - assert_equal(@cls[4,5], a.slice!(-2,2)) + s = a.slice!(-2,2) + assert_equal_instance([4,5], s) assert_equal(@cls[1, 2, 3], a) a = @cls[1, 2, 3, 4, 5] - assert_equal(@cls[3,4], a.slice!(2..3)) + s = a.slice!(2..3) + assert_equal_instance([3,4], s) assert_equal(@cls[1, 2, 5], a) a = @cls[1, 2, 3, 4, 5] @@ -1535,6 +1635,21 @@ def test_slice! assert_raise(ArgumentError) { @cls[1].slice!(0, 0, 0) } end + def test_slice_out_of_range! + a = @cls[*(1..100).to_a] + + assert_nil(a.clone.slice!(-101..-1)) + assert_nil(a.clone.slice!(-101..)) + + # assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.clone.slice!((-101..-1)%2) } + # assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.clone.slice!((-101..)%2) } + + assert_nil(a.clone.slice!(10, -3)) + assert_equal @cls[], a.clone.slice!(10..7) + + assert_equal([100], a.clone.slice!(-1, 1_000_000_000)) + end + def test_sort a = @cls[ 4, 1, 2, 3 ] assert_equal(@cls[1, 2, 3, 4], a.sort) @@ -1574,6 +1689,37 @@ def test_sort! assert_equal([1, 2, 3, 4], a) end + def test_freeze_inside_sort! + array = [1, 2, 3, 4, 5] + frozen_array = nil + assert_raise(FrozenError) do + count = 0 + array.sort! do |a, b| + array.freeze if (count += 1) == 6 + frozen_array ||= array.map.to_a if array.frozen? + b <=> a + end + end + assert_equal(frozen_array, array) + + object = Object.new + array = [1, 2, 3, 4, 5] + object.define_singleton_method(:>){|_| array.freeze; true} + assert_raise(FrozenError) do + array.sort! do |a, b| + object + end + end + + object = Object.new + array = [object, object] + object.define_singleton_method(:>){|_| array.freeze; true} + object.define_singleton_method(:<=>){|o| object} + assert_raise(FrozenError) do + array.sort! + end + end + def test_sort_with_callcc need_continuation n = 1000 @@ -1637,6 +1783,13 @@ def t; ary = [*1..5]; ary.pop(2); ary.sort!; end TEST end + def test_sort_uncomparable + assert_raise(ArgumentError) {[1, Float::NAN].sort} + assert_raise(ArgumentError) {[1.0, Float::NAN].sort} + assert_raise(ArgumentError) {[Float::NAN, 1].sort} + assert_raise(ArgumentError) {[Float::NAN, 1.0].sort} + end + def test_to_a a = @cls[ 1, 2, 3 ] a_id = a.__id__ @@ -1668,19 +1821,19 @@ def o.to_ary end def test_to_s - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[] assert_equal("[]", a.to_s) - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[1, 2] assert_equal("[1, 2]", a.to_s) - $, = "" + assert_deprecated_warning {$, = ""} a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) - $, = ":" + assert_deprecated_warning {$, = ""} a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) ensure @@ -1734,10 +1887,12 @@ def test_to_h_block end def test_min + assert_equal(3, [3].min) assert_equal(1, [1, 2, 3, 1, 2].min) assert_equal(3, [1, 2, 3, 1, 2].min {|a,b| b <=> a }) cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } assert_equal([3, 2], [1, 2, 3, 1, 2].each_with_index.min(&cond)) + assert_equal(1.0, [3.0, 1.0, 2.0].min) ary = %w(albatross dog horse) assert_equal("albatross", ary.min) assert_equal("dog", ary.min {|a,b| a.length <=> b.length }) @@ -1755,11 +1910,20 @@ def coerce(x) [x, 1] end assert_same(obj, [obj, 1.0].min) end + def test_min_uncomparable + assert_raise(ArgumentError) {[1, Float::NAN].min} + assert_raise(ArgumentError) {[1.0, Float::NAN].min} + assert_raise(ArgumentError) {[Float::NAN, 1].min} + assert_raise(ArgumentError) {[Float::NAN, 1.0].min} + end + def test_max + assert_equal(1, [1].max) assert_equal(3, [1, 2, 3, 1, 2].max) assert_equal(1, [1, 2, 3, 1, 2].max {|a,b| b <=> a }) cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } assert_equal([1, 3], [1, 2, 3, 1, 2].each_with_index.max(&cond)) + assert_equal(3.0, [1.0, 3.0, 2.0].max) ary = %w(albatross dog horse) assert_equal("horse", ary.max) assert_equal("albatross", ary.max {|a,b| a.length <=> b.length }) @@ -1776,7 +1940,15 @@ def coerce(x) [x, 1] end assert_same(obj, [obj, 1.0].max) end + def test_max_uncomparable + assert_raise(ArgumentError) {[1, Float::NAN].max} + assert_raise(ArgumentError) {[1.0, Float::NAN].max} + assert_raise(ArgumentError) {[Float::NAN, 1].max} + assert_raise(ArgumentError) {[Float::NAN, 1.0].max} + end + def test_minmax + assert_equal([3, 3], [3].minmax) assert_equal([1, 3], [1, 2, 3, 1, 2].minmax) assert_equal([3, 1], [1, 2, 3, 1, 2].minmax {|a,b| b <=> a }) cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } @@ -1847,26 +2019,22 @@ def test_uniq sc = Class.new(@cls) a = sc[] b = a.dup - assert_instance_of(sc, a.uniq) - assert_equal(sc[], a.uniq) + assert_equal_instance([], a.uniq) assert_equal(b, a) a = sc[1] b = a.dup - assert_instance_of(sc, a.uniq) - assert_equal(sc[1], a.uniq) + assert_equal_instance([1], a.uniq) assert_equal(b, a) a = sc[1, 1] b = a.dup - assert_instance_of(sc, a.uniq) - assert_equal(sc[1], a.uniq) + assert_equal_instance([1], a.uniq) assert_equal(b, a) a = sc[1, 1] b = a.dup - assert_instance_of(sc, a.uniq{|x| x}) - assert_equal(sc[1], a.uniq{|x| x}) + assert_equal_instance([1], a.uniq{|x| x}) assert_equal(b, a) end @@ -2281,23 +2449,23 @@ def test_repeated_combination_stack_error end def test_take - assert_equal([1,2,3], [1,2,3,4,5,0].take(3)) + assert_equal_instance([1,2,3], @cls[1,2,3,4,5,0].take(3)) assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) } - assert_equal([1,2], [1,2].take(1000000000), '[ruby-dev:34123]') + assert_equal_instance([1,2], @cls[1,2].take(1000000000), '[ruby-dev:34123]') end def test_take_while - assert_equal([1,2], [1,2,3,4,5,0].take_while {|i| i < 3 }) + assert_equal_instance([1,2], @cls[1,2,3,4,5,0].take_while {|i| i < 3 }) end def test_drop - assert_equal([4,5,0], [1,2,3,4,5,0].drop(3)) + assert_equal_instance([4,5,0], @cls[1,2,3,4,5,0].drop(3)) assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].drop(-1) } - assert_equal([], [1,2].drop(1000000000), '[ruby-dev:34123]') + assert_equal_instance([], @cls[1,2].drop(1000000000), '[ruby-dev:34123]') end def test_drop_while - assert_equal([3,4,5,0], [1,2,3,4,5,0].drop_while {|i| i < 3 }) + assert_equal_instance([3,4,5,0], @cls[1,2,3,4,5,0].drop_while {|i| i < 3 }) end LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x| @@ -2322,13 +2490,13 @@ def test_try_convert def test_initialize assert_nothing_raised { [].instance_eval { initialize } } - assert_nothing_raised { Array.new { } } + assert_warning(/given block not used/) { Array.new { } } assert_equal([1, 2, 3], Array.new([1, 2, 3])) assert_raise(ArgumentError) { Array.new(-1, 1) } assert_raise(ArgumentError) { Array.new(LONGP, 1) } assert_equal([1, 1, 1], Array.new(3, 1)) assert_equal([1, 1, 1], Array.new(3) { 1 }) - assert_equal([1, 1, 1], Array.new(3, 1) { 1 }) + assert_equal([1, 1, 1], assert_warning(/block supersedes default value argument/) {Array.new(3, 1) { 1 }}) end def test_aset_error @@ -2344,6 +2512,9 @@ def test_aset_error assert_raise(ArgumentError) { [0].freeze[0, 0, 0] = 0 } assert_raise(TypeError) { [0][:foo] = 0 } assert_raise(FrozenError) { [0].freeze[:foo] = 0 } + + # [Bug #17271] + assert_raise_with_message(RangeError, "-7.. out of range") { [*0..5][-7..] = 1 } end def test_first2 @@ -2374,11 +2545,11 @@ def test_unshift_error def test_aref assert_raise(ArgumentError) { [][0, 0, 0] } - assert_raise(TypeError) { [][(1..10).step(2)] } + assert_raise(ArgumentError) { @cls[][0, 0, 0] } end def test_fetch - assert_equal(1, [].fetch(0, 0) { 1 }) + assert_equal(1, assert_warning(/block supersedes default value argument/) {[].fetch(0, 0) { 1 }}) assert_equal(1, [0, 1].fetch(-1)) assert_raise(IndexError) { [0, 1].fetch(2) } assert_raise(IndexError) { [0, 1].fetch(-3) } @@ -2447,6 +2618,27 @@ def (a = Object.new).to_ary assert_equal("12345", [1,[2,[3,4],5]].join) end + def test_join_recheck_elements_type + x = Struct.new(:ary).new + def x.to_str + ary[2] = [0, 1, 2] + "z" + end + (x.ary = ["a", "b", "c", x]) + assert_equal("ab012z", x.ary.join("")) + end + + def test_join_recheck_array_length + x = Struct.new(:ary).new + def x.to_str + ary.clear + ary[0] = "b" + "z" + end + x.ary = Array.new(1023) {"a"*1} << x + assert_equal("b", x.ary.join("")) + end + def test_to_a2 klass = Class.new(Array) a = klass.new.to_a @@ -2495,6 +2687,15 @@ def test_select! a = @cls[ 1, 2, 3, 4, 5 ] a.select! {|i| a.clear if i == 5; false } assert_equal(0, a.size, bug13053) + + assert_raise(FrozenError) do + a = @cls[1, 2, 3, 42] + a.select! do + a.freeze + false + end + end + assert_equal(@cls[1, 2, 3, 42], a) end # also select! @@ -2510,6 +2711,15 @@ def test_keep_if a = @cls[ 1, 2, 3, 4, 5 ] assert_equal(a, a.keep_if { |i| i > 3 }) assert_equal(@cls[4, 5], a) + + assert_raise(FrozenError) do + a = @cls[1, 2, 3, 42] + a.keep_if do + a.freeze + false + end + end + assert_equal(@cls[1, 2, 3, 42], a) end def test_filter @@ -2575,13 +2785,24 @@ def ary.to_ary; [5, 6]; end def test_zip_bug bug8153 = "ruby-core:53650" - r = 1..1 + r = [1] def r.respond_to?(*) super end assert_equal [[42, 1]], [42].zip(r), bug8153 end + def test_zip_with_enumerator + bug17814 = "ruby-core:103513" + + step = 0.step + e = Enumerator.produce { step.next } + a = %w(a b c) + assert_equal([["a", 0], ["b", 1], ["c", 2]], a.zip(e), bug17814) + assert_equal([["a", 3], ["b", 4], ["c", 5]], a.zip(e), bug17814) + assert_equal([["a", 6], ["b", 7], ["c", 8]], a.zip(e), bug17814) + end + def test_transpose assert_equal([[1, :a], [2, :b], [3, :c]], [[1, 2, 3], [:a, :b, :c]].transpose) @@ -2608,25 +2829,21 @@ def o.==(x); :foo; end assert_not_equal([0, 1, 2], [0, 1, 3]) end - A = Array.new(3, &:to_s) - B = A.dup - def test_equal_resize + $test_equal_resize_a = Array.new(3, &:to_s) + $test_equal_resize_b = $test_equal_resize_a.dup o = Object.new def o.==(o) - A.clear - B.clear + $test_equal_resize_a.clear + $test_equal_resize_b.clear true end - A[1] = o - assert_equal(A, B) + $test_equal_resize_a[1] = o + assert_equal($test_equal_resize_a, $test_equal_resize_b) end def test_flatten_error a = [] - a << a - assert_raise(ArgumentError) { a.flatten } - f = [].freeze assert_raise(ArgumentError) { a.flatten!(1, 2) } assert_raise(TypeError) { a.flatten!(:foo) } @@ -2861,15 +3078,6 @@ def test_product2 end end - class Array2 < Array - end - - def test_array_subclass - assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]") - assert_equal(Array2, Array2[1,2][0,1].class) # embedded - assert_equal(Array2, Array2[*(1..100)][1..99].class) #not embedded - end - def test_initialize2 a = [1] * 1000 a.instance_eval { initialize } @@ -3209,3 +3417,23 @@ def need_continuation end end end + +class TestArraySubclass < TestArray + def setup + @verbose = $VERBOSE + @cls = Class.new(Array) + end + + def test_to_a + a = @cls[ 1, 2, 3 ] + a_id = a.__id__ + assert_equal_instance([1, 2, 3], a.to_a) + assert_not_equal(a_id, a.to_a.__id__) + end + + def test_array_subclass + assert_equal(Array, @cls[1,2,3].uniq.class, "[ruby-dev:34581]") + assert_equal(Array, @cls[1,2][0,1].class) # embedded + assert_equal(Array, @cls[*(1..100)][1..99].class) #not embedded + end +end diff --git a/ruby/test/ruby/test_assignment.rb b/ruby/test/ruby/test_assignment.rb index 5a6ec97e6..41e8bffe8 100644 --- a/ruby/test/ruby/test_assignment.rb +++ b/ruby/test/ruby/test_assignment.rb @@ -81,6 +81,64 @@ def test_massign_simple a,b,*c = [*[1,2]]; assert_equal([1,2,[]], [a,b,c]) end + def test_massign_order + order = [] + define_singleton_method(:x1){order << :x1; self} + define_singleton_method(:y1){order << :y1; self} + define_singleton_method(:z=){|x| order << [:z=, x]} + define_singleton_method(:x2){order << :x2; self} + define_singleton_method(:x3){order << :x3; self} + define_singleton_method(:x4){order << :x4; self} + define_singleton_method(:x5=){|x| order << [:x5=, x]; self} + define_singleton_method(:[]=){|*args| order << [:[]=, *args]} + define_singleton_method(:r1){order << :r1; :r1} + define_singleton_method(:r2){order << :r2; :r2} + + x1.y1.z, x2[1, 2, 3], self[4] = r1, 6, r2 + assert_equal([:x1, :y1, :x2, :r1, :r2, [:z=, :r1], [:[]=, 1, 2, 3, 6], [:[]=, 4, :r2]], order) + order.clear + + x1.y1.z, *x2[1, 2, 3], self[4] = r1, 6, 7, r2 + assert_equal([:x1, :y1, :x2, :r1, :r2, [:z=, :r1], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2]], order) + order.clear + + x1.y1.z, *x2[1, 2, 3], x3[4] = r1, 6, 7, r2 + assert_equal([:x1, :y1, :x2, :x3, :r1, :r2, [:z=, :r1], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2]], order) + order.clear + + x1.y1.z, *x2[1, 2, 3], x3[4], x4.x5 = r1, 6, 7, r2, 8 + assert_equal([:x1, :y1, :x2, :x3, :x4, :r1, :r2, [:z=, :r1], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2], [:x5=, 8]], order) + order.clear + + (x1.y1.z, x2.x5), _a = [r1, r2], 7 + assert_equal([:x1, :y1, :x2, :r1, :r2, [:z=, :r1], [:x5=, :r2]], order) + order.clear + + (x1.y1.z, x1.x5), *x2[1, 2, 3] = [r1, 5], 6, 7, r2, 8 + assert_equal([:x1, :y1, :x1, :x2, :r1, :r2, [:z=, :r1], [:x5=, 5], [:[]=, 1, 2, 3, [6, 7, :r2, 8]]], order) + order.clear + + *x2[1, 2, 3], (x3[4], x4.x5) = 6, 7, [r2, 8] + assert_equal([:x2, :x3, :x4, :r2, [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2], [:x5=, 8]], order) + order.clear + + (x1.y1.z, x1.x5), *x2[1, 2, 3], x3[4], x4.x5 = [r1, 5], 6, 7, r2, 8 + assert_equal([:x1, :y1, :x1, :x2, :x3, :x4, :r1, :r2, [:z=, :r1], [:x5=, 5], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2], [:x5=, 8]], order) + order.clear + + (x1.y1.z, x1.x5), *x2[1, 2, 3], (x3[4], x4.x5) = [r1, 5], 6, 7, [r2, 8] + assert_equal([:x1, :y1, :x1, :x2, :x3, :x4, :r1, :r2, [:z=, :r1], [:x5=, 5], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2], [:x5=, 8]], order) + order.clear + + ((x1.y1.z, x1.x5), _a), *x2[1, 2, 3], ((x3[4], x4.x5), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11] + assert_equal([:x1, :y1, :x1, :x2, :x3, :x4, :r1, :r2, [:z=, :r1], [:x5=, 5], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, :r2], [:x5=, 8]], order) + order.clear + + ((x1.y1.z, *x1.x5), _a), *x2[1, 2, 3], ((*x3[4], x4.x5), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11] + assert_equal([:x1, :y1, :x1, :x2, :x3, :x4, :r1, :r2, [:z=, :r1], [:x5=, [5]], [:[]=, 1, 2, 3, [6, 7]], [:[]=, 4, [:r2]], [:x5=, 8]], order) + order.clear + end + def test_massign_splat a,b,*c = *[]; assert_equal([nil,nil,[]], [a,b,c]) a,b,*c = *[1]; assert_equal([1,nil,[]], [a,b,c]) diff --git a/ruby/test/ruby/test_ast.rb b/ruby/test/ruby/test_ast.rb index 147d05ead..a4edfd3cb 100644 --- a/ruby/test/ruby/test_ast.rb +++ b/ruby/test/ruby/test_ast.rb @@ -185,7 +185,7 @@ def test_parse_file_raises_syntax_error end end - def test_of + def test_of_proc_and_method proc = Proc.new { 1 + 2 } method = self.method(__method__) @@ -194,7 +194,6 @@ def test_of assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_proc) assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_method) - assert_raise(TypeError) { RubyVM::AbstractSyntaxTree.of("1 + 2") } Tempfile.create(%w"test_of .rb") do |tmp| tmp.print "#{<<-"begin;"}\n#{<<-'end;'}" @@ -211,6 +210,122 @@ def test_of end end + def sample_backtrace_location + [caller_locations(0).first, __LINE__] + end + + def test_of_backtrace_location + backtrace_location, lineno = sample_backtrace_location + node = RubyVM::AbstractSyntaxTree.of(backtrace_location) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node) + assert_equal(lineno, node.first_lineno) + end + + def test_of_error + assert_raise(TypeError) { RubyVM::AbstractSyntaxTree.of("1 + 2") } + end + + def test_of_proc_and_method_under_eval + keep_script_lines_back = RubyVM.keep_script_lines + RubyVM.keep_script_lines = false + + method = self.method(eval("def example_method_#{$$}; end")) + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = self.method(eval("def self.example_singleton_method_#{$$}; end")) + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = eval("proc{}") + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = self.method(eval("singleton_class.define_method(:example_define_method_#{$$}){}")) + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = self.method(eval("define_singleton_method(:example_dsm_#{$$}){}")) + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = eval("Class.new{def example_method; end}.instance_method(:example_method)") + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + method = eval("Class.new{def example_method; end}.instance_method(:example_method)") + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) } + + ensure + RubyVM.keep_script_lines = keep_script_lines_back + end + + def test_of_proc_and_method_under_eval_with_keep_script_lines + keep_script_lines_back = RubyVM.keep_script_lines + RubyVM.keep_script_lines = true + + method = self.method(eval("def example_method_#{$$}_with_keep_script_lines; end")) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = self.method(eval("def self.example_singleton_method_#{$$}_with_keep_script_lines; end")) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = eval("proc{}") + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = self.method(eval("singleton_class.define_method(:example_define_method_#{$$}_with_keep_script_lines){}")) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = self.method(eval("define_singleton_method(:example_dsm_#{$$}_with_keep_script_lines){}")) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = eval("Class.new{def example_method_with_keep_script_lines; end}.instance_method(:example_method_with_keep_script_lines)") + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + method = eval("Class.new{def example_method_with_keep_script_lines; end}.instance_method(:example_method_with_keep_script_lines)") + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method)) + + ensure + RubyVM.keep_script_lines = keep_script_lines_back + end + + def test_of_backtrace_location_under_eval + keep_script_lines_back = RubyVM.keep_script_lines + RubyVM.keep_script_lines = false + + m = Module.new do + eval(<<-END, nil, __FILE__, __LINE__) + def self.sample_backtrace_location + caller_locations(0).first + end + END + end + backtrace_location = m.sample_backtrace_location + assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(backtrace_location) } + + ensure + RubyVM.keep_script_lines = keep_script_lines_back + end + + def test_of_backtrace_location_under_eval_with_keep_script_lines + keep_script_lines_back = RubyVM.keep_script_lines + RubyVM.keep_script_lines = true + + m = Module.new do + eval(<<-END, nil, __FILE__, __LINE__) + def self.sample_backtrace_location + caller_locations(0).first + end + END + end + backtrace_location = m.sample_backtrace_location + node = RubyVM::AbstractSyntaxTree.of(backtrace_location) + assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node) + assert_equal(2, node.first_lineno) + + ensure + RubyVM.keep_script_lines = keep_script_lines_back + end + + def test_of_c_method + c = Class.new { attr_reader :foo } + assert_nil(RubyVM::AbstractSyntaxTree.of(c.instance_method(:foo))) + end + def test_scope_local_variables node = RubyVM::AbstractSyntaxTree.parse("_x = 0") lv, _, body = *node.children @@ -253,6 +368,19 @@ def test_defn mid, defn = body.children assert_equal(:a, mid) assert_equal(:SCOPE, defn.type) + _, args, = defn.children + assert_equal(:ARGS, args.type) + end + + def test_defn_endless + node = RubyVM::AbstractSyntaxTree.parse("def a = nil") + _, _, body = *node.children + assert_equal(:DEFN, body.type) + mid, defn = body.children + assert_equal(:a, mid) + assert_equal(:SCOPE, defn.type) + _, args, = defn.children + assert_equal(:ARGS, args.type) end def test_defs @@ -263,6 +391,20 @@ def test_defs assert_equal(:VCALL, recv.type) assert_equal(:b, mid) assert_equal(:SCOPE, defn.type) + _, args, = defn.children + assert_equal(:ARGS, args.type) + end + + def test_defs_endless + node = RubyVM::AbstractSyntaxTree.parse("def a.b = nil") + _, _, body = *node.children + assert_equal(:DEFS, body.type) + recv, mid, defn = body.children + assert_equal(:VCALL, recv.type) + assert_equal(:b, mid) + assert_equal(:SCOPE, defn.type) + _, args, = defn.children + assert_equal(:ARGS, args.type) end def test_dstr @@ -319,4 +461,85 @@ def test_ranges_numbered_parameter helper.validate_range assert_equal([], helper.errors) end + + def test_op_asgn2 + node = RubyVM::AbstractSyntaxTree.parse("struct.field += foo") + _, _, body = *node.children + assert_equal(:OP_ASGN2, body.type) + recv, _, mid, op, value = body.children + assert_equal(:VCALL, recv.type) + assert_equal(:field, mid) + assert_equal(:+, op) + assert_equal(:VCALL, value.type) + end + + def test_args + rest = 6 + node = RubyVM::AbstractSyntaxTree.parse("proc { |a| }") + _, args = *node.children.last.children[1].children + assert_equal(nil, args.children[rest]) + + node = RubyVM::AbstractSyntaxTree.parse("proc { |a,| }") + _, args = *node.children.last.children[1].children + assert_equal(:NODE_SPECIAL_EXCESSIVE_COMMA, args.children[rest]) + + node = RubyVM::AbstractSyntaxTree.parse("proc { |*a| }") + _, args = *node.children.last.children[1].children + assert_equal(:a, args.children[rest]) + end + + def test_keep_script_lines_for_parse + node = RubyVM::AbstractSyntaxTree.parse(<<~END, keep_script_lines: true) +1.times do + 2.times do + end +end +__END__ +dummy + END + + expected = [ + "1.times do\n", + " 2.times do\n", + " end\n", + "end\n", + "__END__\n", + ] + assert_equal(expected, node.script_lines) + + expected = + "1.times do\n" + + " 2.times do\n" + + " end\n" + + "end" + assert_equal(expected, node.source) + + expected = + "do\n" + + " 2.times do\n" + + " end\n" + + "end" + assert_equal(expected, node.children.last.children.last.source) + + expected = + "2.times do\n" + + " end" + assert_equal(expected, node.children.last.children.last.children.last.source) + end + + def test_keep_script_lines_for_of + proc = Proc.new { 1 + 2 } + method = self.method(__method__) + + node_proc = RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: true) + node_method = RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: true) + + assert_equal("{ 1 + 2 }", node_proc.source) + assert_equal("def test_keep_script_lines_for_of\n", node_method.source.lines.first) + end + + def test_e_option + assert_in_out_err(["-e", "def foo; end; pp RubyVM::AbstractSyntaxTree.of(method(:foo)).type"], + "", [":SCOPE"], []) + end end diff --git a/ruby/test/ruby/test_autoload.rb b/ruby/test/ruby/test_autoload.rb index 2e53c9203..7709760d1 100644 --- a/ruby/test/ruby/test_autoload.rb +++ b/ruby/test/ruby/test_autoload.rb @@ -66,6 +66,8 @@ def test_autoload_p end def test_autoload_with_unqualified_file_name # [ruby-core:69206] + Object.send(:remove_const, :A) if Object.const_defined?(:A) + lp = $LOAD_PATH.dup lf = $LOADED_FEATURES.dup @@ -425,8 +427,25 @@ def test_autoload_same_file_with_raise end end - def test_no_leak - assert_no_memory_leak([], '', <<~'end;', 'many autoloads', timeout: 60) + def test_source_location + bug = "Bug16764" + Dir.mktmpdir('autoload') do |tmpdir| + path = "#{tmpdir}/test-#{bug}.rb" + File.write(path, "C::#{bug} = __FILE__\n") + assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + class C; end + C.autoload(:Bug16764, #{path.dump}) + assert_equal [__FILE__, __LINE__-1], C.const_source_location(#{bug.dump}) + assert_equal #{path.dump}, C.const_get(#{bug.dump}) + assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump}) + end; + end + end + + def test_no_memory_leak + assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", 'many autoloads', timeout: 60) + begin; 200000.times do |i| m = Module.new m.instance_eval do @@ -437,6 +456,31 @@ def test_no_leak end; end + def test_autoload_after_failed_and_removed_from_loaded_features + Dir.mktmpdir('autoload') do |tmpdir| + autoload_path = File.join(tmpdir, "test-bug-15790.rb") + File.write(autoload_path, '') + + assert_separately(%W[-I #{tmpdir}], <<-RUBY) + path = #{File.realpath(autoload_path).inspect} + autoload :X, path + assert_equal(path, Object.autoload?(:X)) + + assert_raise(NameError){X} + assert_nil(Object.autoload?(:X)) + assert_equal(false, Object.const_defined?(:X)) + + $LOADED_FEATURES.delete(path) + assert_equal(false, Object.const_defined?(:X)) + assert_nil(Object.autoload?(:X)) + + assert_raise(NameError){X} + assert_equal(false, Object.const_defined?(:X)) + assert_nil(Object.autoload?(:X)) + RUBY + end + end + def add_autoload(path) (@autoload_paths ||= []) << path ::Object.class_eval {autoload(:AutoloadTest, path)} @@ -444,6 +488,7 @@ def add_autoload(path) def remove_autoload_constant $".replace($" - @autoload_paths) - ::Object.class_eval {remove_const(:AutoloadTest)} + ::Object.class_eval {remove_const(:AutoloadTest)} if defined? Object::AutoloadTest + TestAutoload.class_eval {remove_const(:AutoloadTest)} if defined? TestAutoload::AutoloadTest end end diff --git a/ruby/test/ruby/test_backtrace.rb b/ruby/test/ruby/test_backtrace.rb index 00c96b3b9..aa79db24c 100644 --- a/ruby/test/ruby/test_backtrace.rb +++ b/ruby/test/ruby/test_backtrace.rb @@ -138,10 +138,66 @@ def test_caller_lev_and_n rec[m] end + def test_caller_with_limit + x = nil + c = Class.new do + define_method(:bar) do + x = caller(1, 1) + end + end + [c.new].group_by(&:bar) + assert_equal 1, x.length + assert_equal caller(0), caller(0, nil) + end + def test_caller_with_nil_length assert_equal caller(0), caller(0, nil) end + def test_caller_locations_first_label + def self.label + caller_locations.first.label + end + + def self.label_caller + label + end + + assert_equal 'label_caller', label_caller + + [1].group_by do + assert_equal 'label_caller', label_caller + end + end + + def test_caller_limit_cfunc_iseq_no_pc + def self.a; [1].group_by { b } end + def self.b + [ + caller_locations(2, 1).first.base_label, + caller_locations(3, 1).first.base_label + ] + end + assert_equal({["each", "group_by"]=>[1]}, a) + end + + def test_caller_location_inspect_cfunc_iseq_no_pc + def self.foo + @res = caller_locations(2, 1).inspect + end + @line = __LINE__ + 1 + 1.times.map { 1.times.map { foo } } + assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @res) + end + + def test_caller_location_path_cfunc_iseq_no_pc + def self.foo + @res = caller_locations(2, 1)[0].path + end + 1.times.map { 1.times.map { foo } } + assert_equal(__FILE__, @res) + end + def test_caller_locations cs = caller(0); locs = caller_locations(0).map{|loc| loc.to_s diff --git a/ruby/test/ruby/test_basicinstructions.rb b/ruby/test/ruby/test_basicinstructions.rb index ab32ee54e..f6b69cc1e 100644 --- a/ruby/test/ruby/test_basicinstructions.rb +++ b/ruby/test/ruby/test_basicinstructions.rb @@ -428,7 +428,9 @@ def set_gvar_in_another_method end class CVarA - @@cv = 'CVarA@@cv' + def self.setup + @@cv = 'CVarA@@cv' + end def self.cv() @@cv end def self.cv=(v) @@cv = v end class << self @@ -449,6 +451,7 @@ def cvB=(v) @@cv = v end end def test_class_variable + CVarA.setup assert_equal 'CVarA@@cv', CVarA.cv assert_equal 'CVarA@@cv', CVarA.cv2 assert_equal 'CVarA@@cv', CVarA.new.cv diff --git a/ruby/test/ruby/test_bignum.rb b/ruby/test/ruby/test_bignum.rb index 434c5befd..3ffe7114b 100644 --- a/ruby/test/ruby/test_bignum.rb +++ b/ruby/test/ruby/test_bignum.rb @@ -19,23 +19,22 @@ class TestBignum < Test::Unit::TestCase end BIGNUM_MIN_BITS = n - T_ZERO = 0.to_bignum - T_ONE = 1.to_bignum - T_MONE = (-1).to_bignum - T31 = (2**31).to_bignum # 2147483648 - T31P = (T31 - 1).to_bignum # 2147483647 - T32 = (2**32).to_bignum # 4294967296 - T32P = (T32 - 1).to_bignum # 4294967295 - T64 = (2**64).to_bignum # 18446744073709551616 - T64P = (T64 - 1).to_bignum # 18446744073709551615 - T128 = (2**128).to_bignum - T128P = (T128 - 1).to_bignum - T1024 = (2**1024).to_bignum - T1024P = (T1024 - 1).to_bignum + T_ZERO = Bug::Integer.to_bignum(0) + T_ONE = Bug::Integer.to_bignum(1) + T_MONE = Bug::Integer.to_bignum(-1) + T31 = Bug::Integer.to_bignum(2**31) # 2147483648 + T31P = Bug::Integer.to_bignum(T31 - 1) # 2147483647 + T32 = Bug::Integer.to_bignum(2**32) # 4294967296 + T32P = Bug::Integer.to_bignum(T32 - 1) # 4294967295 + T64 = Bug::Integer.to_bignum(2**64) # 18446744073709551616 + T64P = Bug::Integer.to_bignum(T64 - 1) # 18446744073709551615 + T128 = Bug::Integer.to_bignum(2**128) + T128P = Bug::Integer.to_bignum(T128 - 1) + T1024 = Bug::Integer.to_bignum(2**1024) + T1024P = Bug::Integer.to_bignum(T1024 - 1) def setup @verbose = $VERBOSE - $VERBOSE = nil @fmax = Float::MAX.to_i @fmax2 = @fmax * 2 @big = (1 << BIGNUM_MIN_BITS) - 1 @@ -214,9 +213,11 @@ def test_to_s2 def test_to_f assert_nothing_raised { T31P.to_f.to_i } - assert_raise(FloatDomainError) { (1024**1024).to_f.to_i } - assert_equal(1, (2**50000).to_f.infinite?) - assert_equal(-1, (-(2**50000)).to_f.infinite?) + assert_raise(FloatDomainError) { + assert_warning(/out of Float range/) {(1024**1024).to_f}.to_i + } + assert_equal(1, assert_warning(/out of Float range/) {(2**50000).to_f}.infinite?) + assert_equal(-1, assert_warning(/out of Float range/) {(-(2**50000)).to_f}.infinite?) end def test_cmp @@ -415,7 +416,7 @@ def test_divrem def test_divide bug5490 = '[ruby-core:40429]' assert_raise(ZeroDivisionError, bug5490) {T1024./(0)} - assert_equal(Float::INFINITY, T1024./(0.0), bug5490) + assert_equal(Float::INFINITY, assert_warning(/out of Float range/) {T1024./(0.0)}, bug5490) end def test_div @@ -466,8 +467,8 @@ def test_quo def test_pow assert_equal(1.0, T32 ** 0.0) assert_equal(1.0 / T32, T32 ** -1) - assert_equal(1, (T32 ** T32).infinite?) - assert_equal(1, (T32 ** (2**30-1)).infinite?) + assert_equal(1, assert_warning(/may be too big/) {T32 ** T32}.infinite?) + assert_equal(1, assert_warning(/may be too big/) {T32 ** (2**30-1)}.infinite?) ### rational changes the behavior of Bignum#** #assert_raise(TypeError) { T32**"foo" } @@ -505,39 +506,57 @@ def to_int end def test_and_with_float - assert_raise(TypeError) { T1024 & 1.5 } + assert_raise(TypeError) { + assert_warning(/out of Float range/) {T1024 & 1.5} + } end def test_and_with_rational - assert_raise(TypeError, "#1792") { T1024 & Rational(3, 2) } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 & Rational(3, 2)} + } end def test_and_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { T1024 & DummyNumeric.new } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 & DummyNumeric.new} + } end def test_or_with_float - assert_raise(TypeError) { T1024 | 1.5 } + assert_raise(TypeError) { + assert_warn(/out of Float range/) {T1024 | 1.5} + } end def test_or_with_rational - assert_raise(TypeError, "#1792") { T1024 | Rational(3, 2) } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 | Rational(3, 2)} + } end def test_or_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { T1024 | DummyNumeric.new } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 | DummyNumeric.new} + } end def test_xor_with_float - assert_raise(TypeError) { T1024 ^ 1.5 } + assert_raise(TypeError) { + assert_warn(/out of Float range/) {T1024 ^ 1.5} + } end def test_xor_with_rational - assert_raise(TypeError, "#1792") { T1024 ^ Rational(3, 2) } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 ^ Rational(3, 2)} + } end def test_xor_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { T1024 ^ DummyNumeric.new } + assert_raise(TypeError, "#1792") { + assert_warn(/out of Float range/) {T1024 ^ DummyNumeric.new} + } end def test_shift2 @@ -613,7 +632,7 @@ def test_interrupt_during_to_s time = Time.now end_flag = false num = (65536 ** 65536) - q = Queue.new + q = Thread::Queue.new thread = Thread.new do assert_raise(RuntimeError) { q << true @@ -663,7 +682,7 @@ def test_interrupt_during_bigdivrem end def test_too_big_to_s - if (big = 2**31-1).fixnum? + if Bug::Integer.fixnum?(big = 2**31-1) return end assert_raise_with_message(RangeError, /too big to convert/) {(1 << big).to_s} @@ -746,7 +765,7 @@ def obj.coerce(other) end def test_digits - assert_equal([90, 78, 56, 34, 12], 1234567890.to_bignum.digits(100)) + assert_equal([90, 78, 56, 34, 12], Bug::Integer.to_bignum(1234567890).digits(100)) assert_equal([7215, 2413, 6242], T1024P.digits(10_000).first(3)) assert_equal([11], 11.digits(T1024P)) assert_equal([T1024P - 1, 1], (T1024P + T1024P - 1).digits(T1024P)) @@ -759,13 +778,13 @@ def test_digits_for_negative_numbers end def test_digits_for_invalid_base_numbers - assert_raise(ArgumentError) { T1024P.to_bignum.digits(0) } - assert_raise(ArgumentError) { T1024P.to_bignum.digits(-1) } - assert_raise(ArgumentError) { T1024P.to_bignum.digits(0.to_bignum) } - assert_raise(ArgumentError) { T1024P.to_bignum.digits(1.to_bignum) } - assert_raise(ArgumentError) { T1024P.to_bignum.digits(-T1024P) } - assert_raise(ArgumentError) { 10.digits(0.to_bignum) } - assert_raise(ArgumentError) { 10.digits(1.to_bignum) } + assert_raise(ArgumentError) { Bug::Integer.to_bignum(T1024P).digits(0) } + assert_raise(ArgumentError) { Bug::Integer.to_bignum(T1024P).digits(-1) } + assert_raise(ArgumentError) { Bug::Integer.to_bignum(T1024P).digits(Bug::Integer.to_bignum(0)) } + assert_raise(ArgumentError) { Bug::Integer.to_bignum(T1024P).digits(Bug::Integer.to_bignum(1)) } + assert_raise(ArgumentError) { Bug::Integer.to_bignum(T1024P).digits(-T1024P) } + assert_raise(ArgumentError) { 10.digits(Bug::Integer.to_bignum(0)) } + assert_raise(ArgumentError) { 10.digits(Bug::Integer.to_bignum(1)) } end def test_digits_for_non_integral_base_numbers diff --git a/ruby/test/ruby/test_call.rb b/ruby/test/ruby/test_call.rb index 2a1b671ca..67b3a936d 100644 --- a/ruby/test/ruby/test_call.rb +++ b/ruby/test/ruby/test_call.rb @@ -99,4 +99,13 @@ def test_call_splat_order ary = [1, 2] assert_equal([0, 1, 2, 1], aaa(0, *ary, ary.shift), bug12860) end + + def test_call_block_order + bug16504 = '[ruby-core:96769] [Bug# 16504]' + b = proc{} + ary = [1, 2, b] + assert_equal([1, 2, b], aaa(*ary, &ary.pop), bug16504) + ary = [1, 2, b] + assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504) + end end diff --git a/ruby/test/ruby/test_case.rb b/ruby/test/ruby/test_case.rb index 77612a894..4a0f1bf78 100644 --- a/ruby/test/ruby/test_case.rb +++ b/ruby/test/ruby/test_case.rb @@ -102,6 +102,18 @@ def test_optimization else assert(false) end + case 0 + when 0r + assert(true) + else + assert(false) + end + case 0 + when 0i + assert(true) + else + assert(false) + end end def test_method_missing diff --git a/ruby/test/ruby/test_class.rb b/ruby/test/ruby/test_class.rb index ca7847302..07c34ce9d 100644 --- a/ruby/test/ruby/test_class.rb +++ b/ruby/test/ruby/test_class.rb @@ -312,7 +312,7 @@ def test_invalid_return_from_class_definition end def test_invalid_yield_from_class_definition - assert_raise(LocalJumpError) { + assert_raise(SyntaxError) { EnvUtil.suppress_warning {eval("class C; yield; end")} } end @@ -483,6 +483,53 @@ def foo; :foo; end assert_equal(:foo, d.foo) end + def test_clone_singleton_class_exists + klass = Class.new do + def self.bar; :bar; end + end + + o = klass.new + o.singleton_class + clone = o.clone + + assert_empty(o.singleton_class.instance_methods(false)) + assert_empty(clone.singleton_class.instance_methods(false)) + assert_empty(o.singleton_class.singleton_class.instance_methods(false)) + assert_empty(clone.singleton_class.singleton_class.instance_methods(false)) + end + + def test_clone_when_singleton_class_of_singleton_class_exists + klass = Class.new do + def self.bar; :bar; end + end + + o = klass.new + o.singleton_class.singleton_class + clone = o.clone + + assert_empty(o.singleton_class.instance_methods(false)) + assert_empty(clone.singleton_class.instance_methods(false)) + assert_empty(o.singleton_class.singleton_class.instance_methods(false)) + assert_empty(clone.singleton_class.singleton_class.instance_methods(false)) + end + + def test_clone_when_method_exists_on_singleton_class_of_singleton_class + klass = Class.new do + def self.bar; :bar; end + end + + o = klass.new + o.singleton_class.singleton_class.define_method(:s2_method) { :s2 } + clone = o.clone + + assert_empty(o.singleton_class.instance_methods(false)) + assert_empty(clone.singleton_class.instance_methods(false)) + assert_equal(:s2, o.singleton_class.s2_method) + assert_equal(:s2, clone.singleton_class.s2_method) + assert_equal([:s2_method], o.singleton_class.singleton_class.instance_methods(false)) + assert_equal([:s2_method], clone.singleton_class.singleton_class.instance_methods(false)) + end + def test_singleton_class_p feature7609 = '[ruby-core:51087] [Feature #7609]' assert_predicate(self.singleton_class, :singleton_class?, feature7609) @@ -683,4 +730,58 @@ def (Array.singleton_class).bla; :bla; end end; end + + def test_assign_frozen_class_to_const + c = Class.new.freeze + assert_same(c, Module.new.module_eval("self::Foo = c")) + c = Class.new.freeze + assert_same(c, Module.new.const_set(:Foo, c)) + end + + def test_subclasses + c = Class.new + sc = Class.new(c) + ssc = Class.new(sc) + [c, sc, ssc].each do |k| + k.include Module.new + k.new.define_singleton_method(:force_singleton_class){} + end + assert_equal([sc], c.subclasses) + assert_equal([ssc], sc.subclasses) + assert_equal([], ssc.subclasses) + + object_subclasses = Object.subclasses + assert_include(object_subclasses, c) + assert_not_include(object_subclasses, sc) + assert_not_include(object_subclasses, ssc) + object_subclasses.each do |subclass| + assert_equal Object, subclass.superclass, "Expected #{subclass}.superclass to be Object" + end + end + + def test_subclass_gc + c = Class.new + 10_000.times do + cc = Class.new(c) + 100.times { Class.new(cc) } + end + assert(c.subclasses.size <= 10_000) + end + + def test_subclass_gc_stress + 10000.times do + c = Class.new + 100.times { Class.new(c) } + assert(c.subclasses.size <= 100) + end + end + + def test_classext_memory_leak + assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true) +code = proc { Class.new } +1_000.times(&code) +PREP +3_000_000.times(&code) +CODE + end end diff --git a/ruby/test/ruby/test_complex.rb b/ruby/test/ruby/test_complex.rb index a4fe9d423..a3a754657 100644 --- a/ruby/test/ruby/test_complex.rb +++ b/ruby/test/ruby/test_complex.rb @@ -220,6 +220,11 @@ def test_rect def test_polar assert_equal([1,2], Complex.polar(1,2).polar) assert_equal(Complex.polar(1.0, Math::PI * 2 / 3), Complex.polar(1, Math::PI * 2 / 3)) + + assert_in_out_err([], <<-'end;', ['OK'], []) + Complex.polar(1, Complex(1, 0)) + puts :OK + end; end def test_uplus diff --git a/ruby/test/ruby/test_const.rb b/ruby/test/ruby/test_const.rb index 1c73b6664..f6b9ea83d 100644 --- a/ruby/test/ruby/test_const.rb +++ b/ruby/test/ruby/test_const.rb @@ -3,20 +3,30 @@ require 'test/unit' class TestConst < Test::Unit::TestCase - TEST1 = 1 - TEST2 = 2 - module Const - TEST3 = 3 - TEST4 = 4 - end + Constants_Setup = -> do + remove_const :TEST1 if defined? ::TestConst::TEST1 + remove_const :TEST2 if defined? ::TestConst::TEST2 + remove_const :Const if defined? ::TestConst::Const + remove_const :Const2 if defined? ::TestConst::Const2 + + TEST1 = 1 + TEST2 = 2 - module Const2 - TEST3 = 6 - TEST4 = 8 + module Const + TEST3 = 3 + TEST4 = 4 + end + + module Const2 + TEST3 = 6 + TEST4 = 8 + end end def test_const + Constants_Setup.call + assert defined?(TEST1) assert_equal 1, TEST1 assert defined?(TEST2) diff --git a/ruby/test/ruby/test_defined.rb b/ruby/test/ruby/test_defined.rb index 9976db3b6..3324a09af 100644 --- a/ruby/test/ruby/test_defined.rb +++ b/ruby/test/ruby/test_defined.rb @@ -23,40 +23,80 @@ def defined_test return !defined?(yield) end - def test_defined + def test_defined_global_variable $x = nil assert(defined?($x)) # global variable assert_equal('global-variable', defined?($x))# returns description + end + def test_defined_local_variable assert_nil(defined?(foo)) # undefined foo=5 assert(defined?(foo)) # local variable + end + def test_defined_constant assert(defined?(Array)) # constant assert(defined?(::Array)) # toplevel constant assert(defined?(File::Constants)) # nested constant + end + + def test_defined_public_method assert(defined?(Object.new)) # method assert(defined?(Object::new)) # method + end + + def test_defined_private_method assert(!defined?(Object.print)) # private method + end + + def test_defined_operator assert(defined?(1 == 2)) # operator expression + end + def test_defined_protected_method f = Foo.new assert_nil(defined?(f.foo)) # protected method f.bar(f) { |v| assert(v) } + f.bar(Class.new(Foo).new) { |v| assert(v, "inherited protected method") } + end + + def test_defined_undefined_method + f = Foo.new assert_nil(defined?(f.quux)) # undefined method + end + + def test_defined_undefined_argument + f = Foo.new assert_nil(defined?(f.baz(x))) # undefined argument x = 0 assert(defined?(f.baz(x))) assert_nil(defined?(f.quux(x))) assert(defined?(print(x))) assert_nil(defined?(quux(x))) + end + + def test_defined_attrasgn + f = Foo.new assert(defined?(f.attr = 1)) f.attrasgn_test { |v| assert(v) } + end + + def test_defined_undef + x = Object.new + def x.foo; end + assert(defined?(x.foo)) + x.instance_eval {undef :foo} + assert(!defined?(x.foo), "undefed method should not be defined?") + end + def test_defined_yield assert(defined_test) # not iterator assert(!defined_test{}) # called as iterator + end + def test_defined_matchdata /a/ =~ '' assert_equal nil, defined?($&) assert_equal nil, defined?($`) @@ -85,12 +125,65 @@ def test_defined assert_equal 'global-variable', defined?($+) assert_equal 'global-variable', defined?($1) assert_equal nil, defined?($2) + end + def test_defined_literal assert_equal("nil", defined?(nil)) assert_equal("true", defined?(true)) assert_equal("false", defined?(false)) assert_equal("expression", defined?(1)) + end + + def test_defined_method + self_ = self + assert_equal("method", defined?(test_defined_method)) + assert_equal("method", defined?(self.test_defined_method)) + assert_equal("method", defined?(self_.test_defined_method)) + + assert_equal(nil, defined?(1.test_defined_method)) + assert_equal("method", defined?(1.to_i)) + assert_equal(nil, defined?(1.to_i.test_defined_method)) + assert_equal(nil, defined?(1.test_defined_method.to_i)) + + assert_equal("method", defined?("x".reverse)) + assert_equal("method", defined?("x".reverse(1))) + assert_equal("method", defined?("x".reverse.reverse)) + assert_equal(nil, defined?("x".reverse(1).reverse)) + + assert_equal("method", defined?(1.to_i(10))) + assert_equal("method", defined?(1.to_i("x"))) + assert_equal(nil, defined?(1.to_i("x").undefined)) + assert_equal(nil, defined?(1.to_i(undefined).to_i)) + assert_equal(nil, defined?(1.to_i("x").undefined.to_i)) + assert_equal(nil, defined?(1.to_i(undefined).to_i.to_i)) + end + + def test_defined_method_single_call + times_called = 0 + define_singleton_method(:t) do + times_called += 1 + self + end + assert_equal("method", defined?(t)) + assert_equal(0, times_called) + + assert_equal("method", defined?(t.t)) + assert_equal(1, times_called) + + times_called = 0 + assert_equal("method", defined?(t.t.t)) + assert_equal(2, times_called) + + times_called = 0 + assert_equal("method", defined?(t.t.t.t)) + assert_equal(3, times_called) + + times_called = 0 + assert_equal("method", defined?(t.t.t.t.t)) + assert_equal(4, times_called) + end + def test_defined_empty_paren_expr bug8224 = '[ruby-core:54024] [Bug #8224]' (1..3).each do |level| expr = "("*level+")"*level @@ -214,6 +307,23 @@ def test_super_toplevel assert_separately([], "assert_nil(defined?(super))") end + def test_respond_to + obj = "#{self.class.name}##{__method__}" + class << obj + def respond_to?(mid) + true + end + end + assert_warn(/deprecated method signature.*\n.*respond_to\? is defined here/) do + Warning[:deprecated] = true + defined?(obj.foo) + end + assert_warn('') do + Warning[:deprecated] = false + defined?(obj.foo) + end + end + class ExampleRespondToMissing attr_reader :called @@ -257,4 +367,53 @@ def test_method_by_respond_to_missing def test_top_level_constant_not_defined assert_nil(defined?(TestDefined::Object)) end + + class RefinedClass + end + + module RefiningModule + refine RefinedClass do + def pub + end + + private + + def priv + end + end + + def self.call_without_using(x = RefinedClass.new) + defined?(x.pub) + end + + def self.vcall_without_using(x = RefinedClass.new) + x.instance_eval {defined?(priv)} + end + + using self + + def self.call_with_using(x = RefinedClass.new) + defined?(x.pub) + end + + def self.vcall_with_using(x = RefinedClass.new) + x.instance_eval {defined?(priv)} + end + end + + def test_defined_refined_call_without_using + assert(!RefiningModule.call_without_using, "refined public method without using") + end + + def test_defined_refined_vcall_without_using + assert(!RefiningModule.vcall_without_using, "refined private method without using") + end + + def test_defined_refined_call_with_using + assert(RefiningModule.call_with_using, "refined public method with using") + end + + def test_defined_refined_vcall_with_using + assert(RefiningModule.vcall_with_using, "refined private method with using") + end end diff --git a/ruby/test/ruby/test_dir.rb b/ruby/test/ruby/test_dir.rb index 1bb228fd4..9474c6e92 100644 --- a/ruby/test/ruby/test_dir.rb +++ b/ruby/test/ruby/test_dir.rb @@ -8,7 +8,6 @@ class TestDir < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil @root = File.realpath(Dir.mktmpdir('__test_dir__')) @nodir = File.join(@root, "dummy") @dirs = [] @@ -88,36 +87,67 @@ def test_rewind end def test_chdir - @pwd = Dir.pwd - @env_home = ENV["HOME"] - @env_logdir = ENV["LOGDIR"] + pwd = Dir.pwd + env_home = ENV["HOME"] + env_logdir = ENV["LOGDIR"] ENV.delete("HOME") ENV.delete("LOGDIR") assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) } assert_raise(ArgumentError) { Dir.chdir } - ENV["HOME"] = @pwd + ENV["HOME"] = pwd Dir.chdir do - assert_equal(@pwd, Dir.pwd) - Dir.chdir(@root) + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } + + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) } assert_equal(@root, Dir.pwd) + + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } + + assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join } + assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join } + + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } + + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) } + assert_equal(@root, Dir.pwd) + + assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } + Dir.chdir(@root) do + assert_equal(@root, Dir.pwd) + end + assert_equal(pwd, Dir.pwd) end ensure begin - Dir.chdir(@pwd) + Dir.chdir(pwd) rescue - abort("cannot return the original directory: #{ @pwd }") + abort("cannot return the original directory: #{ pwd }") + end + ENV["HOME"] = env_home + ENV["LOGDIR"] = env_logdir + end + + def test_chdir_conflict + pwd = Dir.pwd + q = Thread::Queue.new + t = Thread.new do + q.pop + Dir.chdir(pwd) rescue $! end - if @env_home - ENV["HOME"] = @env_home - else - ENV.delete("HOME") + Dir.chdir(pwd) do + q.push nil + assert_instance_of(RuntimeError, t.value) + end + + t = Thread.new do + q.pop + Dir.chdir(pwd){} rescue $! end - if @env_logdir - ENV["LOGDIR"] = @env_logdir - else - ENV.delete("LOGDIR") + Dir.chdir(pwd) do + q.push nil + assert_instance_of(RuntimeError, t.value) end end @@ -135,16 +165,26 @@ def test_close end def test_glob - assert_equal((%w(. ..) + ("a".."z").to_a).map{|f| File.join(@root, f) }, - Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH).sort) - assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort, - Dir.glob([@root, File.join(@root, "*")]).sort) + assert_equal((%w(.) + ("a".."z").to_a).map{|f| File.join(@root, f) }, + Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH)) + assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }, + Dir.glob([@root, File.join(@root, "*")])) + assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }, + Dir.glob([@root, File.join(@root, "*")], sort: false).sort) + assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }, + Dir.glob([@root, File.join(@root, "*")], sort: true)) assert_raise_with_message(ArgumentError, /nul-separated/) do Dir.glob(@root + "\0\0\0" + File.join(@root, "*")) end + assert_raise_with_message(ArgumentError, /expected true or false/) do + Dir.glob(@root, sort: 1) + end + assert_raise_with_message(ArgumentError, /expected true or false/) do + Dir.glob(@root, sort: nil) + end - assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }.sort, - Dir.glob(File.join(@root, "*/")).sort) + assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }, + Dir.glob(File.join(@root, "*/"))) assert_equal([File.join(@root, '//a')], Dir.glob(@root + '//a')) FileUtils.touch(File.join(@root, "{}")) @@ -154,7 +194,7 @@ def test_glob assert_equal([], Dir.glob(File.join(@root, '[a-\\'))) assert_equal([File.join(@root, "a")], Dir.glob(File.join(@root, 'a\\'))) - assert_equal(("a".."f").map {|f| File.join(@root, f) }.sort, Dir.glob(File.join(@root, '[abc/def]')).sort) + assert_equal(("a".."f").map {|f| File.join(@root, f) }, Dir.glob(File.join(@root, '[abc/def]'))) open(File.join(@root, "}}{}"), "wb") {} open(File.join(@root, "}}a"), "wb") {} @@ -171,6 +211,9 @@ def test_glob_recursive Dir.chdir(@root) do assert_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/.", bug8006) + Dir.mkdir("a/b") + assert_not_include(Dir.glob("a/**/*", File::FNM_DOTMATCH), "a/b/.") + FileUtils.mkdir_p("a/b/c/d/e/f") assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/e/f"), bug6977) assert_equal(["a/b/c/d/e/f"], Dir.glob("a/**/d/e/f"), bug6977) @@ -184,7 +227,7 @@ def test_glob_recursive dirs = ["a/.x", "a/b/.y"] FileUtils.mkdir_p(dirs) dirs.map {|dir| open("#{dir}/z", "w") {}} - assert_equal([], Dir.glob("a/**/z").sort, bug8283) + assert_equal([], Dir.glob("a/**/z"), bug8283) assert_equal(["a/.x/z"], Dir.glob("a/**/.x/z"), bug8283) assert_equal(["a/.x/z"], Dir.glob("a/.x/**/z"), bug8283) assert_equal(["a/b/.y/z"], Dir.glob("a/**/.y/z"), bug8283) @@ -202,6 +245,9 @@ def test_glob_recursive_directory bug15540 = '[ruby-core:91110] [Bug #15540]' assert_equal(["c/d/a/", "c/d/a/b/", "c/d/a/b/c/", "c/e/a/", "c/e/a/b/", "c/e/a/b/c/"], Dir.glob('c/{d,e}/a/**/'), bug15540) + + assert_equal(["c/e/a/", "c/e/a/b/", "c/e/a/b/c/", "c/d/a/", "c/d/a/b/", "c/d/a/b/c/"], + Dir.glob('c/{e,d}/a/**/')) end end @@ -213,6 +259,17 @@ def test_glob_starts_with_brace end end + def test_glob_order + Dir.chdir(@root) do + assert_equal(["#{@root}/a", "#{@root}/b"], Dir.glob("#{@root}/[ba]")) + assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob(%W"#{@root}/b #{@root}/a")) + assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob("#{@root}/{b,a}")) + end + assert_equal(["a", "b"], Dir.glob("[ba]", base: @root)) + assert_equal(["b", "a"], Dir.glob(%W"b a", base: @root)) + assert_equal(["b", "a"], Dir.glob("{b,a}", base: @root)) + end + if Process.const_defined?(:RLIMIT_NOFILE) def test_glob_too_may_open_files assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", chdir: @root) @@ -237,21 +294,38 @@ def test_glob_base Dir.mkdir(File.join(@root, "a/dir")) dirs = @dirs + %w[a/dir/] dirs.sort! - assert_equal(files, Dir.glob("*/*.c", base: @root).sort) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".").sort}) - assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a").sort}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "").sort}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil).sort}) - assert_equal(@dirs, Dir.glob("*/", base: @root).sort) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".").sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a").sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "").sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil).sort}) - assert_equal(dirs, Dir.glob("**/*/", base: @root).sort) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".").sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a").sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "").sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil).sort}) + + assert_equal(files, Dir.glob("*/*.c", base: @root)) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".")}) + assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a")}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "")}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil)}) + assert_equal(@dirs, Dir.glob("*/", base: @root)) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".")}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a")}) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "")}) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil)}) + assert_equal(dirs, Dir.glob("**/*/", base: @root)) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".")}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a")}) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "")}) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil)}) + + assert_equal(files, Dir.glob("*/*.c", base: @root, sort: false).sort) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".", sort: false).sort}) + assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a", sort: false).sort}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "", sort: false).sort}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil, sort: false).sort}) + assert_equal(@dirs, Dir.glob("*/", base: @root)) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".", sort: false).sort}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a", sort: false).sort}) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "", sort: false).sort}) + assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil, sort: false).sort}) + assert_equal(dirs, Dir.glob("**/*/", base: @root)) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".", sort: false).sort}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a", sort: false).sort}) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "", sort: false).sort}) + assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil, sort: false).sort}) end def test_glob_base_dir @@ -260,12 +334,31 @@ def test_glob_base_dir Dir.mkdir(File.join(@root, "a/dir")) dirs = @dirs + %w[a/dir/] dirs.sort! - assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}.sort) + + assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}) assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d)}}) - assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d).sort}}) - assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d).sort}}) + assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d)}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d)}}) + assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d)}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d)}}) + + assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d, sort: false).sort}) + assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d, sort: false).sort}}) + assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d, sort: false).sort}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d, sort: false).sort}}) + assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d, sort: false).sort}) + assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d, sort: false).sort}}) + end + + def test_glob_ignore_casefold_invalid_encoding + bug14456 = "[ruby-core:85448]" + filename = "\u00AAa123".encode('ISO-8859-1') + File.write(File.join(@root, filename), "") + matches = Dir.chdir(@root) {|d| Dir.glob("*a123".encode('UTF-8'), File::FNM_CASEFOLD)} + assert_equal(1, matches.size, bug14456) + matches.each{|f| f.force_encoding('ISO-8859-1')} + # Handle MacOS/Windows, which saves under a different filename + assert_include([filename, "\u00C2\u00AAa123".encode('ISO-8859-1')], matches.first, bug14456) end def assert_entries(entries, children_only = false) @@ -277,26 +370,52 @@ def assert_entries(entries, children_only = false) def test_entries assert_entries(Dir.open(@root) {|dir| dir.entries}) - assert_entries(Dir.entries(@root).to_a) + assert_entries(Dir.entries(@root)) assert_raise(ArgumentError) {Dir.entries(@root+"\0")} + [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| + assert_equal(enc, Dir.entries(@root, encoding: enc).first.encoding) + end end def test_foreach assert_entries(Dir.open(@root) {|dir| dir.each.to_a}) assert_entries(Dir.foreach(@root).to_a) assert_raise(ArgumentError) {Dir.foreach(@root+"\0").to_a} + newdir = @root+"/new" + e = Dir.foreach(newdir) + assert_raise(Errno::ENOENT) {e.to_a} + Dir.mkdir(newdir) + File.write(newdir+"/a", "") + assert_equal(%w[. .. a], e.to_a.sort) + [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| + e = Dir.foreach(newdir, encoding: enc) + assert_equal(enc, e.to_a.first.encoding) + end end def test_children assert_entries(Dir.open(@root) {|dir| dir.children}, true) assert_entries(Dir.children(@root), true) assert_raise(ArgumentError) {Dir.children(@root+"\0")} + [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| + assert_equal(enc, Dir.children(@root, encoding: enc).first.encoding) + end end def test_each_child assert_entries(Dir.open(@root) {|dir| dir.each_child.to_a}, true) assert_entries(Dir.each_child(@root).to_a, true) assert_raise(ArgumentError) {Dir.each_child(@root+"\0").to_a} + newdir = @root+"/new" + e = Dir.each_child(newdir) + assert_raise(Errno::ENOENT) {e.to_a} + Dir.mkdir(newdir) + File.write(newdir+"/a", "") + assert_equal(%w[a], e.to_a) + [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| + e = Dir.each_child(newdir, encoding: enc) + assert_equal(enc, e.to_a.first.encoding) + end end def test_dir_enc @@ -337,10 +456,10 @@ def test_symlink end assert_equal([*"a".."z", *"symlink-a".."symlink-z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort, - Dir.glob(File.join(@root, "*/")).sort) + Dir.glob(File.join(@root, "*/"))) - assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort], - Dir.glob(File.join(@root, "**/")).sort) + assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }], + Dir.glob(File.join(@root, "**/"))) end def test_glob_metachar @@ -424,8 +543,8 @@ def test_symlinks_not_resolved Dir.mkdir('some-dir') File.write('some-dir/foo', 'some content') - assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*'].sort - assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*'].sort + assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*'] + assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*'] end end end @@ -471,9 +590,21 @@ def test_glob_gc_for_fd ensure fs.clear end - list = Dir.glob("*").sort + list = Dir.glob("*") assert_not_empty(list) assert_equal([*"a".."z"], list) end; end if defined?(Process::RLIMIT_NOFILE) + + def test_glob_array_with_destructive_element + args = Array.new(100, "") + pat = Struct.new(:ary).new(args) + args.push(pat, *Array.new(100) {"."*40}) + def pat.to_path + ary.clear + GC.start + "" + end + assert_empty(Dir.glob(args)) + end end diff --git a/ruby/test/ruby/test_dir_m17n.rb b/ruby/test/ruby/test_dir_m17n.rb index c2c0c4999..67bad8a51 100644 --- a/ruby/test/ruby/test_dir_m17n.rb +++ b/ruby/test/ruby/test_dir_m17n.rb @@ -17,27 +17,19 @@ def assert_raw_file_name(code, encoding) assert_separately(["-E#{encoding}"], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("#{encoding}") File.open(filename, "w") {} - opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".") + if /mswin|mingw/ =~ RUBY_PLATFORM + filename = filename.encode("UTF-8") + end assert_include(ents, filename) EOS return if /cygwin/ =~ RUBY_PLATFORM assert_separately(%w[-EASCII-8BIT], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("ASCII-8BIT") - opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) - expected_filename = #{code}.chr('UTF-8').encode(Encoding.find("filesystem")) rescue expected_filename = "?" - expected_filename = expected_filename.force_encoding("ASCII-8BIT") + ents = Dir.entries(".") if /mswin|mingw/ =~ RUBY_PLATFORM - case - when ents.include?(filename) - when ents.include?(expected_filename) - filename = expected_filename - else - ents = Dir.entries(".", :encoding => Encoding.find("filesystem")) - filename = expected_filename - end + filename.force_encoding("UTF-8") end assert_include(ents, filename) EOS @@ -199,27 +191,23 @@ def test_filename_euc_jp assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} - opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".") if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8").force_encoding("euc-jp") + elsif /mswin|mingw/ =~ RUBY_PLATFORM + filename = filename.encode("utf-8") end assert_include(ents, filename) EOS assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding('ASCII-8BIT') - win_expected_filename = filename.encode(Encoding.find("filesystem"), "euc-jp") rescue "?" - opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".") unless ents.include?(filename) case RUBY_PLATFORM when /darwin/ filename = filename.encode("utf-8", "euc-jp").b when /mswin|mingw/ - if ents.include?(win_expected_filename.b) - ents = Dir.entries(".", :encoding => Encoding.find("filesystem")) - filename = win_expected_filename - end + filename = filename.encode("utf-8", "euc-jp") end end assert_include(ents, filename) @@ -414,13 +402,8 @@ def test_entries_compose orig.each {|n| open(n, "w") {}} enc = Encoding.find("filesystem") enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII - if /mswin|mingw/ =~ RUBY_PLATFORM - opts = {:encoding => enc} - orig.map! {|o| o.encode("filesystem") rescue o.tr("^a-z", "?")} - else - orig.each {|o| o.force_encoding(enc) } - end - ents = Dir.entries(".", **(opts||{})).reject {|n| /\A\./ =~ n} + orig.each {|o| o.force_encoding(enc) } + ents = Dir.entries(".").reject {|n| /\A\./ =~ n} ents.sort! PP.assert_equal(orig, ents, bug7267) } @@ -431,13 +414,9 @@ def test_pwd expected = [] results = [] orig.each {|o| - if /mswin|mingw/ =~ RUBY_PLATFORM - n = (o.encode("filesystem") rescue next) - else - enc = Encoding.find("filesystem") - enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII - n = o.dup.force_encoding(enc) - end + enc = Encoding.find("filesystem") + enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII + n = o.dup.force_encoding(enc) expected << n with_tmpdir { Dir.mkdir(o) diff --git a/ruby/test/ruby/test_econv.rb b/ruby/test/ruby/test_econv.rb index a469614d8..1aad0de34 100644 --- a/ruby/test/ruby/test_econv.rb +++ b/ruby/test/ruby/test_econv.rb @@ -803,7 +803,7 @@ def test_xml_escape_attr_content assert_equal('', ec.finish) ec = Encoding::Converter.new("", "xml_attr_content_escape") - assert_equal('&<>"', ec.convert("&<>\"")) + assert_equal('&<>"'', ec.convert("&<>\"'")) assert_equal('', ec.finish) end @@ -844,7 +844,7 @@ def test_xml_escape_with_charref def test_xml_hasharg assert_equal("&\e$B$&\e(B♥&\"'".force_encoding("iso-2022-jp"), "&\u3046\u2665&\"'".encode("iso-2022-jp", xml: :text)) - assert_equal("\"&\e$B$&\e(B♡&"'\"".force_encoding("iso-2022-jp"), + assert_equal("\"&\e$B$&\e(B♡&"'\"".force_encoding("iso-2022-jp"), "&\u3046\u2661&\"'".encode("iso-2022-jp", xml: :attr)) assert_equal("&\u3046\u2661&\"'".force_encoding("utf-8"), @@ -912,6 +912,21 @@ def test_newline_option assert_raise_with_message(ArgumentError, /\u{3042}/) { Encoding::Converter.new("", "", newline: "\u{3042}".to_sym) } + newlines = %i[universal_newline crlf_newline cr_newline] + (2..newlines.size).each do |i| + newlines.combination(i) do |opts| + assert_raise(Encoding::ConverterNotFoundError, "#{opts} are mutually exclusive") do + Encoding::Converter.new("", "", **opts.inject({}) {|o,nl|o[nl]=true;o}) + end + end + end + newlines.each do |nl| + opts = {newline: :universal, nl => true} + ec2 = assert_warning(/:newline option precedes/, opts.inspect) do + Encoding::Converter.new("", "", **opts) + end + assert_equal(ec1, ec2) + end end def test_default_external diff --git a/ruby/test/ruby/test_encoding.rb b/ruby/test/ruby/test_encoding.rb index 019cb2417..4a6dd932e 100644 --- a/ruby/test/ruby/test_encoding.rb +++ b/ruby/test/ruby/test_encoding.rb @@ -56,11 +56,36 @@ def test_find end def test_replicate - assert_instance_of(Encoding, Encoding::UTF_8.replicate('UTF-8-ANOTHER')) - assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate('ISO-2022-JP-ANOTHER')) + assert_separately([], "#{<<~'END;'}") + assert_instance_of(Encoding, Encoding::UTF_8.replicate("UTF-8-ANOTHER#{Time.now.to_f}")) + assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate("ISO-2022-JP-ANOTHER#{Time.now.to_f}")) bug3127 = '[ruby-dev:40954]' assert_raise(TypeError, bug3127) {Encoding::UTF_8.replicate(0)} - assert_raise(ArgumentError, bug3127) {Encoding::UTF_8.replicate("\0")} + assert_raise_with_message(ArgumentError, /\bNUL\b/, bug3127) {Encoding::UTF_8.replicate("\0")} + END; + end + + def test_extra_encoding + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + 200.times {|i| + Encoding::UTF_8.replicate("dummy#{i}") + } + e = Encoding.list.last + format = "%d".force_encoding(e) + assert_equal("0", format % 0) + assert_equal(e, format.dup.encoding) + assert_equal(e, (format*1).encoding) + + assert_equal(e, (("x"*30).force_encoding(e)*1).encoding) + GC.start + + name = "A" * 64 + Encoding.list.each do |enc| + assert_raise(ArgumentError) {enc.replicate(name)} + name.succ! + end + end; end def test_dummy_p @@ -130,7 +155,7 @@ def test_nonascii_library_path assert_equal(Encoding::US_ASCII, __ENCODING__) $:.unshift("/\x80") assert_raise_with_message(LoadError, /\[Bug #16382\]/) do - $:.resolve_feature_path "[Bug #16382]" + require "[Bug #16382]" end end; end diff --git a/ruby/test/ruby/test_enum.rb b/ruby/test/ruby/test_enum.rb index 7b647231c..b0c43b9a7 100644 --- a/ruby/test/ruby/test_enum.rb +++ b/ruby/test/ruby/test_enum.rb @@ -27,7 +27,6 @@ def each(&block) end end @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -63,11 +62,32 @@ def test_grep assert_equal([[2, 1], [2, 4]], a) end + def test_grep_optimization + bug17030 = '[ruby-core:99156]' + 'set last match' =~ /set last (.*)/ + assert_equal([:a, 'b', :c], [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/), bug17030) + assert_equal(['z', 42, nil], [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/), bug17030) + assert_equal('match', $1, bug17030) + + regexp = Regexp.new('x') + assert_equal([], @obj.grep(regexp), bug17030) # sanity check + def regexp.===(other) + true + end + assert_equal([1, 2, 3, 1, 2], @obj.grep(regexp), bug17030) + + o = Object.new + def o.to_str + 'hello' + end + assert_same(o, [o].grep(/ll/).first, bug17030) + end + def test_count assert_equal(5, @obj.count) assert_equal(2, @obj.count(1)) assert_equal(3, @obj.count {|x| x % 2 == 1 }) - assert_equal(2, @obj.count(1) {|x| x % 2 == 1 }) + assert_equal(2, assert_warning(/given block not used/) {@obj.count(1) {|x| x % 2 == 1 }}) assert_raise(ArgumentError) { @obj.count(0, 1) } if RUBY_ENGINE == "ruby" @@ -95,7 +115,7 @@ def test_find_index assert_equal(1, @obj.find_index {|x| x % 2 == 0 }) assert_equal(nil, @obj.find_index {|x| false }) assert_raise(ArgumentError) { @obj.find_index(0, 1) } - assert_equal(1, @obj.find_index(2) {|x| x == 1 }) + assert_equal(1, assert_warning(/given block not used/) {@obj.find_index(2) {|x| x == 1 }}) end def test_find_all @@ -114,6 +134,12 @@ def test_to_a assert_equal([1, 2, 3, 1, 2], @obj.to_a) end + def test_to_a_keywords + @obj.singleton_class.remove_method(:each) + def @obj.each(foo:) yield foo end + assert_equal([1], @obj.to_a(foo: 1)) + end + def test_to_a_size_symbol sym = Object.new class << sym @@ -206,7 +232,7 @@ def test_inject assert_equal(48, @obj.inject {|z, x| z * 2 + x }) assert_equal(12, @obj.inject(:*)) assert_equal(24, @obj.inject(2) {|z, x| z * x }) - assert_equal(24, @obj.inject(2, :*) {|z, x| z * x }) + assert_equal(24, assert_warning(/given block not used/) {@obj.inject(2, :*) {|z, x| z * x }}) assert_equal(nil, @empty.inject() {9}) end @@ -228,17 +254,75 @@ def test_inject_array_plus assert_equal(15, [3, 5, 7].inject(:+)) assert_float_equal(15.0, [3, 5, 7.0].inject(:+)) assert_equal(2*FIXNUM_MAX, Array.new(2, FIXNUM_MAX).inject(:+)) + assert_equal(3*FIXNUM_MAX, Array.new(3, FIXNUM_MAX).inject(:+)) assert_equal(2*(FIXNUM_MAX+1), Array.new(2, FIXNUM_MAX+1).inject(:+)) assert_equal(10*FIXNUM_MAX, Array.new(10, FIXNUM_MAX).inject(:+)) assert_equal(0, ([FIXNUM_MAX, 1, -FIXNUM_MAX, -1]*10).inject(:+)) assert_equal(FIXNUM_MAX*10, ([FIXNUM_MAX+1, -1]*10).inject(:+)) assert_equal(2*FIXNUM_MIN, Array.new(2, FIXNUM_MIN).inject(:+)) + assert_equal(3*FIXNUM_MIN, Array.new(3, FIXNUM_MIN).inject(:+)) assert_equal((FIXNUM_MAX+1).to_f, [FIXNUM_MAX, 1, 0.0].inject(:+)) assert_float_equal(10.0, [3.0, 5].inject(2.0, :+)) assert_float_equal((FIXNUM_MAX+1).to_f, [0.0, FIXNUM_MAX+1].inject(:+)) assert_equal(2.0+3.0i, [2.0, 3.0i].inject(:+)) end + def test_inject_op_redefined + assert_separately([], "#{<<~"end;"}\n""end") + k = Class.new do + include Enumerable + def each + yield 1 + yield 2 + yield 3 + end + end + all_assertions_foreach("", *%i[+ * / - %]) do |op| + bug = '[ruby-dev:49510] [Bug#12178] should respect redefinition' + begin + Integer.class_eval do + alias_method :orig, op + define_method(op) do |x| + 0 + end + end + assert_equal(0, k.new.inject(op), bug) + ensure + Integer.class_eval do + undef_method op + alias_method op, :orig + end + end + end; + end + + def test_inject_op_private + assert_separately([], "#{<<~"end;"}\n""end") + k = Class.new do + include Enumerable + def each + yield 1 + yield 2 + yield 3 + end + end + all_assertions_foreach("", *%i[+ * / - %]) do |op| + bug = '[ruby-core:81349] [Bug #13592] should respect visibility' + assert_raise_with_message(NoMethodError, /private method/, bug) do + begin + Integer.class_eval do + private op + end + k.new.inject(op) + ensure + Integer.class_eval do + public op + end + end + end + end; + end + def test_inject_array_op_redefined assert_separately([], "#{<<~"end;"}\n""end") all_assertions_foreach("", *%i[+ * / - %]) do |op| @@ -279,6 +363,25 @@ def test_inject_array_op_private end; end + def test_refine_Enumerable_then_include + assert_separately([], "#{<<~"end;"}\n") + module RefinementBug + refine Enumerable do + def refined_method + :rm + end + end + end + using RefinementBug + + class A + include Enumerable + end + + assert_equal(:rm, [].refined_method) + end; + end + def test_partition assert_equal([[1, 3, 1], [2, 2]], @obj.partition {|x| x % 2 == 1 }) cond = ->(x, i) { x % 2 == 1 } @@ -297,6 +400,45 @@ def test_group_by def test_tally h = {1 => 2, 2 => 2, 3 => 1} assert_equal(h, @obj.tally) + + h = {1 => 5, 2 => 2, 3 => 1, 4 => "x"} + assert_equal(h, @obj.tally({1 => 3, 4 => "x"})) + + assert_raise(TypeError) do + @obj.tally({1 => ""}) + end + + h = {1 => 2, 2 => 2, 3 => 1} + assert_same(h, @obj.tally(h)) + + h = {1 => 2, 2 => 2, 3 => 1}.freeze + assert_raise(FrozenError) do + @obj.tally(h) + end + assert_equal({1 => 2, 2 => 2, 3 => 1}, h) + + hash_convertible = Object.new + def hash_convertible.to_hash + {1 => 3, 4 => "x"} + end + assert_equal({1 => 5, 2 => 2, 3 => 1, 4 => "x"}, @obj.tally(hash_convertible)) + + hash_convertible = Object.new + def hash_convertible.to_hash + {1 => 3, 4 => "x"}.freeze + end + assert_raise(FrozenError) do + @obj.tally(hash_convertible) + end + assert_equal({1 => 3, 4 => "x"}, hash_convertible.to_hash) + + assert_raise(TypeError) do + @obj.tally(BasicObject.new) + end + + h = {1 => 2, 2 => 2, 3 => 1} + assert_equal(h, @obj.tally(Hash.new(100))) + assert_equal(h, @obj.tally(Hash.new {100})) end def test_first @@ -319,6 +461,17 @@ def each(&block) empty.first empty.block.call end; + + bug18475 = '[ruby-dev:107059]' + assert_in_out_err([], <<-'end;', [], /unexpected break/, bug18475) + e = Enumerator.new do |g| + Thread.new do + g << 1 + end.join + end + + e.first + end; end def test_sort @@ -341,7 +494,7 @@ def test_all assert_equal(false, [true, true, false].all?) assert_equal(true, [].all?) assert_equal(true, @empty.all?) - assert_equal(true, @obj.all?(Fixnum)) + assert_equal(true, @obj.all?(Integer)) assert_equal(false, @obj.all?(1..2)) end @@ -595,6 +748,9 @@ def test_each_slice ary.clear (1..10).each_slice(11) {|a| ary << a} assert_equal([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]], ary) + + assert_equal(1..10, (1..10).each_slice(3) { }) + assert_equal([], [].each_slice(3) { }) end def test_each_cons @@ -614,6 +770,9 @@ def test_each_cons ary.clear (1..5).each_cons(6) {|a| ary << a} assert_empty(ary) + + assert_equal(1..5, (1..5).each_cons(3) { }) + assert_equal([], [].each_cons(3) { }) end def test_zip @@ -1134,6 +1293,21 @@ def test_uniq assert_equal([1, [1, 2]], Foo.new.to_enum.uniq) end + def test_compact + class << (enum = Object.new) + include Enumerable + def each + yield 3 + yield nil + yield 7 + yield 9 + yield nil + end + end + + assert_equal([3, 7, 9], enum.compact) + end + def test_transient_heap_sort_by klass = Class.new do include Comparable diff --git a/ruby/test/ruby/test_enumerator.rb b/ruby/test/ruby/test_enumerator.rb index 75cf1aeec..c823b79c6 100644 --- a/ruby/test/ruby/test_enumerator.rb +++ b/ruby/test/ruby/test_enumerator.rb @@ -69,18 +69,17 @@ def (o = Object.new).each def test_initialize assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a) - _, err = capture_io do - assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a) - end - assert_match 'Enumerator.new without a block is deprecated', err + assert_raise(ArgumentError) { + Enumerator.new(@obj, :foo, 1, 2, 3) + } assert_equal([1, 2, 3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)) assert_raise(ArgumentError) { Enumerator.new } enum = @obj.to_enum assert_raise(NoMethodError) { enum.each {} } enum.freeze - assert_raise(FrozenError) { - capture_io do + assert_raise(ArgumentError) { + capture_output do # warning: Enumerator.new without a block is deprecated; use Object#to_enum enum.__send__(:initialize, @obj, :foo) end @@ -697,6 +696,11 @@ def test_uniq assert_equal([0, 1], u.force) end + def test_compact + u = [0, 1, nil, 2, 3, nil].to_enum.lazy.compact + assert_equal([0, 1, 2, 3], u.force) + end + def test_enum_chain_and_plus r = 1..5 @@ -812,6 +816,28 @@ def test_chained_enums ) end + def test_chain_with_index + assert_equal([[3, 0], [4, 1]], [3].chain([4]).with_index.to_a) + end + + def test_lazy_chain + ea = (10..).lazy.select(&:even?).take(10) + ed = (20..).lazy.select(&:odd?) + chain = (ea + ed).select{|x| x % 3 == 0} + assert_equal(12, chain.next) + assert_equal(18, chain.next) + assert_equal(24, chain.next) + assert_equal(21, chain.next) + assert_equal(27, chain.next) + assert_equal(33, chain.next) + end + + def test_chain_undef_methods + chain = [1].to_enum + [2].to_enum + meths = (chain.methods & [:feed, :next, :next_values, :peek, :peek_values]) + assert_equal(0, meths.size) + end + def test_produce assert_raise(ArgumentError) { Enumerator.produce } diff --git a/ruby/test/ruby/test_env.rb b/ruby/test/ruby/test_env.rb index f93cd503d..87ccd5102 100644 --- a/ruby/test/ruby/test_env.rb +++ b/ruby/test/ruby/test_env.rb @@ -22,7 +22,6 @@ def assert_invalid_env(msg = nil) def setup @verbose = $VERBOSE - $VERBOSE = nil @backup = ENV.to_hash ENV.delete('test') ENV.delete('TEST') @@ -63,6 +62,46 @@ def test_bracket } end + def test_dup + assert_raise(TypeError) { + ENV.dup + } + end + + def test_clone + warning = /ENV\.clone is deprecated; use ENV\.to_h instead/ + clone = assert_deprecated_warning(warning) { + ENV.clone + } + assert_same(ENV, clone) + + clone = assert_deprecated_warning(warning) { + ENV.clone(freeze: false) + } + assert_same(ENV, clone) + + clone = assert_deprecated_warning(warning) { + ENV.clone(freeze: nil) + } + assert_same(ENV, clone) + + assert_raise(TypeError) { + ENV.clone(freeze: true) + } + assert_raise(ArgumentError) { + ENV.clone(freeze: 1) + } + assert_raise(ArgumentError) { + ENV.clone(foo: false) + } + assert_raise(ArgumentError) { + ENV.clone(1) + } + assert_raise(ArgumentError) { + ENV.clone(1, foo: false) + } + end + def test_has_value val = 'a' val.succ! while ENV.has_value?(val) || ENV.has_value?(val.upcase) @@ -84,7 +123,6 @@ def test_key ENV['test'] = val[0...-1] assert_nil(ENV.key(val)) - assert_nil(ENV.index(val)) assert_nil(ENV.key(val.upcase)) ENV['test'] = val if IGNORE_CASE @@ -106,6 +144,7 @@ def test_delete assert_invalid_env {|v| ENV.delete(v)} assert_nil(ENV.delete("TEST")) assert_nothing_raised { ENV.delete(PATH_ENV) } + assert_equal("NO TEST", ENV.delete("TEST") {|name| "NO "+name}) end def test_getenv @@ -286,6 +325,17 @@ def test_slice assert_equal({"foo"=>"bar", "baz"=>"qux"}, ENV.slice("foo", "baz")) end + def test_except + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + ENV["bar"] = "rab" + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except()) + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except("")) + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except("unknown")) + assert_equal({"bar"=>"rab"}, ENV.except("foo", "baz")) + end + def test_clear ENV.clear assert_equal(0, ENV.size) @@ -358,7 +408,8 @@ def test_assoc assert_equal("foo", v) end assert_invalid_env {|var| ENV.assoc(var)} - assert_equal(Encoding.find("locale"), v.encoding) + encoding = /mswin|mingw/ =~ RUBY_PLATFORM ? Encoding::UTF_8 : Encoding.find("locale") + assert_equal(encoding, v.encoding) end def test_has_value2 @@ -406,8 +457,8 @@ def test_reject def check(as, bs) if IGNORE_CASE - as = as.map {|xs| xs.map {|x| x.upcase } } - bs = bs.map {|xs| xs.map {|x| x.upcase } } + as = as.map {|k, v| [k.upcase, v] } + bs = bs.map {|k, v| [k.upcase, v] } end assert_equal(as.sort, bs.sort) end @@ -433,6 +484,8 @@ def test_replace ENV["foo"] = "xxx" ENV.replace({"foo"=>"bar", "baz"=>"qux"}) check(ENV.to_hash.to_a, [%w(foo bar), %w(baz qux)]) + ENV.replace({"Foo"=>"Bar", "Baz"=>"Qux"}) + check(ENV.to_hash.to_a, [%w(Foo Bar), %w(Baz Qux)]) end def test_update @@ -450,15 +503,15 @@ def test_update end def test_huge_value - huge_value = "bar" * 40960 - ENV["foo"] = "bar" - if /mswin/ =~ RUBY_PLATFORM - assert_raise(Errno::EINVAL) { ENV["foo"] = huge_value } - assert_equal("bar", ENV["foo"]) + if /mswin|ucrt/ =~ RUBY_PLATFORM + # On Windows >= Vista each environment variable can be max 32768 characters + huge_value = "bar" * 10900 else - assert_nothing_raised { ENV["foo"] = huge_value } - assert_equal(huge_value, ENV["foo"]) + huge_value = "bar" * 40960 end + ENV["foo"] = "overwritten" + assert_nothing_raised { ENV["foo"] = huge_value } + assert_equal(huge_value, ENV["foo"]) end if /mswin|mingw/ =~ RUBY_PLATFORM @@ -525,6 +578,892 @@ def test_shared_substring assert_nil(e1, bug12475) end + def ignore_case_str + IGNORE_CASE ? "true" : "false" + end + + def str_for_yielding_exception_class(code_str, exception_var: "raised_exception") + <<-"end;" + #{exception_var} = nil + begin + #{code_str} + rescue Exception => e + #{exception_var} = e + end + Ractor.yield #{exception_var}.class + end; + end + + def str_for_assert_raise_on_yielded_exception_class(expected_error_class, ractor_var) + <<-"end;" + error_class = #{ractor_var}.take + assert_raise(#{expected_error_class}) do + if error_class < Exception + raise error_class + end + end + end; + end + + def str_to_yield_invalid_envvar_errors(var_name, code_str) + <<-"end;" + envvars_to_check = [ + "foo\0bar", + "#{'\xa1\xa1'}".force_encoding(Encoding::UTF_16LE), + "foo".force_encoding(Encoding::ISO_2022_JP), + ] + envvars_to_check.each do |#{var_name}| + #{str_for_yielding_exception_class(code_str)} + end + end; + end + + def str_to_receive_invalid_envvar_errors(ractor_var) + <<-"end;" + 3.times do + #{str_for_assert_raise_on_yielded_exception_class(ArgumentError, ractor_var)} + end + end; + end + + STR_DEFINITION_FOR_CHECK = %Q{ + def check(as, bs) + if #{IGNORE_CASE ? "true" : "false"} + as = as.map {|k, v| [k.upcase, v] } + bs = bs.map {|k, v| [k.upcase, v] } + end + assert_equal(as.sort, bs.sort) + end + } + + def test_bracket_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + Ractor.yield ENV['test'] + Ractor.yield ENV['TEST'] + ENV['test'] = 'foo' + Ractor.yield ENV['test'] + Ractor.yield ENV['TEST'] + ENV['TEST'] = 'bar' + Ractor.yield ENV['TEST'] + Ractor.yield ENV['test'] + #{str_for_yielding_exception_class("ENV[1]")} + #{str_for_yielding_exception_class("ENV[1] = 'foo'")} + #{str_for_yielding_exception_class("ENV['test'] = 0")} + end + assert_nil(r.take) + assert_nil(r.take) + assert_equal('foo', r.take) + if #{ignore_case_str} + assert_equal('foo', r.take) + else + assert_nil(r.take) + end + assert_equal('bar', r.take) + if #{ignore_case_str} + assert_equal('bar', r.take) + else + assert_equal('foo', r.take) + end + 3.times do + #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")} + end + end; + end + + def test_dup_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + #{str_for_yielding_exception_class("ENV.dup")} + end + #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")} + end; + end + + def test_clone_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + original_warning_state = Warning[:deprecated] + Warning[:deprecated] = false + + begin + Ractor.yield ENV.clone.object_id + Ractor.yield ENV.clone(freeze: false).object_id + Ractor.yield ENV.clone(freeze: nil).object_id + + #{str_for_yielding_exception_class("ENV.clone(freeze: true)")} + #{str_for_yielding_exception_class("ENV.clone(freeze: 1)")} + #{str_for_yielding_exception_class("ENV.clone(foo: false)")} + #{str_for_yielding_exception_class("ENV.clone(1)")} + #{str_for_yielding_exception_class("ENV.clone(1, foo: false)")} + + ensure + Warning[:deprecated] = original_warning_state + end + end + assert_equal(ENV.object_id, r.take) + assert_equal(ENV.object_id, r.take) + assert_equal(ENV.object_id, r.take) + #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")} + 4.times do + #{str_for_assert_raise_on_yielded_exception_class(ArgumentError, "r")} + end + end; + end + + def test_has_value_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + val = 'a' + val.succ! while ENV.has_value?(val) || ENV.has_value?(val.upcase) + ENV['test'] = val[0...-1] + Ractor.yield(ENV.has_value?(val)) + Ractor.yield(ENV.has_value?(val.upcase)) + ENV['test'] = val + Ractor.yield(ENV.has_value?(val)) + Ractor.yield(ENV.has_value?(val.upcase)) + ENV['test'] = val.upcase + Ractor.yield ENV.has_value?(val) + Ractor.yield ENV.has_value?(val.upcase) + end + assert_equal(false, r.take) + assert_equal(false, r.take) + assert_equal(true, r.take) + assert_equal(false, r.take) + assert_equal(false, r.take) + assert_equal(true, r.take) + end; + end + + def test_key_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + val = 'a' + val.succ! while ENV.has_value?(val) || ENV.has_value?(val.upcase) + ENV['test'] = val[0...-1] + Ractor.yield ENV.key(val) + Ractor.yield ENV.key(val.upcase) + ENV['test'] = val + Ractor.yield ENV.key(val) + Ractor.yield ENV.key(val.upcase) + ENV['test'] = val.upcase + Ractor.yield ENV.key(val) + Ractor.yield ENV.key(val.upcase) + end + assert_nil(r.take) + assert_nil(r.take) + if #{ignore_case_str} + assert_equal('TEST', r.take.upcase) + else + assert_equal('test', r.take) + end + assert_nil(r.take) + assert_nil(r.take) + if #{ignore_case_str} + assert_equal('TEST', r.take.upcase) + else + assert_equal('test', r.take) + end + end; + + end + + def test_delete_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + #{str_to_yield_invalid_envvar_errors("v", "ENV.delete(v)")} + Ractor.yield ENV.delete("TEST") + #{str_for_yielding_exception_class("ENV.delete('#{PATH_ENV}')")} + Ractor.yield(ENV.delete("TEST"){|name| "NO "+name}) + end + #{str_to_receive_invalid_envvar_errors("r")} + assert_nil(r.take) + exception_class = r.take + assert_equal(NilClass, exception_class) + assert_equal("NO TEST", r.take) + end; + end + + def test_getenv_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + #{str_to_yield_invalid_envvar_errors("v", "ENV[v]")} + ENV["#{PATH_ENV}"] = "" + Ractor.yield ENV["#{PATH_ENV}"] + Ractor.yield ENV[""] + end + #{str_to_receive_invalid_envvar_errors("r")} + assert_equal("", r.take) + assert_nil(r.take) + end; + end + + def test_fetch_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV["test"] = "foo" + Ractor.yield ENV.fetch("test") + ENV.delete("test") + #{str_for_yielding_exception_class("ENV.fetch('test')", exception_var: "ex")} + Ractor.yield ex.receiver.object_id + Ractor.yield ex.key + Ractor.yield ENV.fetch("test", "foo") + Ractor.yield(ENV.fetch("test"){"bar"}) + #{str_to_yield_invalid_envvar_errors("v", "ENV.fetch(v)")} + #{str_for_yielding_exception_class("ENV.fetch('#{PATH_ENV}', 'foo')")} + ENV['#{PATH_ENV}'] = "" + Ractor.yield ENV.fetch('#{PATH_ENV}') + end + assert_equal("foo", r.take) + #{str_for_assert_raise_on_yielded_exception_class(KeyError, "r")} + assert_equal(ENV.object_id, r.take) + assert_equal("test", r.take) + assert_equal("foo", r.take) + assert_equal("bar", r.take) + #{str_to_receive_invalid_envvar_errors("r")} + exception_class = r.take + assert_equal(NilClass, exception_class) + assert_equal("", r.take) + end; + end + + def test_aset_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + #{str_for_yielding_exception_class("ENV['test'] = nil")} + ENV["test"] = nil + Ractor.yield ENV["test"] + #{str_to_yield_invalid_envvar_errors("v", "ENV[v] = 'test'")} + #{str_to_yield_invalid_envvar_errors("v", "ENV['test'] = v")} + end + exception_class = r.take + assert_equal(NilClass, exception_class) + assert_nil(r.take) + #{str_to_receive_invalid_envvar_errors("r")} + #{str_to_receive_invalid_envvar_errors("r")} + end; + end + + def test_keys_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + a = ENV.keys + Ractor.yield a + end + a = r.take + assert_kind_of(Array, a) + a.each {|k| assert_kind_of(String, k) } + end; + + end + + def test_each_key_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.each_key {|k| Ractor.yield(k)} + Ractor.yield "finished" + end + while((x=r.take) != "finished") + assert_kind_of(String, x) + end + end; + end + + def test_values_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + a = ENV.values + Ractor.yield a + end + a = r.take + assert_kind_of(Array, a) + a.each {|k| assert_kind_of(String, k) } + end; + end + + def test_each_value_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.each_value {|k| Ractor.yield(k)} + Ractor.yield "finished" + end + while((x=r.take) != "finished") + assert_kind_of(String, x) + end + end; + end + + def test_each_pair_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.each_pair {|k, v| Ractor.yield([k,v])} + Ractor.yield "finished" + end + while((k,v=r.take) != "finished") + assert_kind_of(String, k) + assert_kind_of(String, v) + end + end; + end + + def test_reject_bang_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + ENV.reject! {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" } + h2 = {} + ENV.each_pair {|k, v| h2[k] = v } + Ractor.yield [h1, h2] + Ractor.yield(ENV.reject! {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }) + end + h1, h2 = r.take + assert_equal(h1, h2) + assert_nil(r.take) + end; + end + + def test_delete_if_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + ENV.delete_if {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" } + h2 = {} + ENV.each_pair {|k, v| h2[k] = v } + Ractor.yield [h1, h2] + Ractor.yield (ENV.delete_if {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }).object_id + end + h1, h2 = r.take + assert_equal(h1, h2) + assert_equal(ENV.object_id, r.take) + end; + end + + def test_select_bang_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + ENV.select! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" } + h2 = {} + ENV.each_pair {|k, v| h2[k] = v } + Ractor.yield [h1, h2] + Ractor.yield(ENV.select! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }) + end + h1, h2 = r.take + assert_equal(h1, h2) + assert_nil(r.take) + end; + end + + def test_filter_bang_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + ENV.filter! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" } + h2 = {} + ENV.each_pair {|k, v| h2[k] = v } + Ractor.yield [h1, h2] + Ractor.yield(ENV.filter! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }) + end + h1, h2 = r.take + assert_equal(h1, h2) + assert_nil(r.take) + end; + end + + def test_keep_if_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + ENV.keep_if {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" } + h2 = {} + ENV.each_pair {|k, v| h2[k] = v } + Ractor.yield [h1, h2] + Ractor.yield (ENV.keep_if {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }).object_id + end + h1, h2 = r.take + assert_equal(h1, h2) + assert_equal(ENV.object_id, r.take) + end; + end + + def test_values_at_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV["test"] = "foo" + Ractor.yield ENV.values_at("test", "test") + end + assert_equal(["foo", "foo"], r.take) + end; + end + + def test_select_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV["test"] = "foo" + h = ENV.select {|k| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" } + Ractor.yield h.size + k = h.keys.first + v = h.values.first + Ractor.yield [k, v] + end + assert_equal(1, r.take) + k, v = r.take + if #{ignore_case_str} + assert_equal("TEST", k.upcase) + assert_equal("FOO", v.upcase) + else + assert_equal("test", k) + assert_equal("foo", v) + end + end; + end + + def test_filter_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV["test"] = "foo" + h = ENV.filter {|k| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" } + Ractor.yield(h.size) + k = h.keys.first + v = h.values.first + Ractor.yield [k, v] + end + assert_equal(1, r.take) + k, v = r.take + if #{ignore_case_str} + assert_equal("TEST", k.upcase) + assert_equal("FOO", v.upcase) + else + assert_equal("test", k) + assert_equal("foo", v) + end + end; + end + + def test_slice_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + ENV["bar"] = "rab" + Ractor.yield(ENV.slice()) + Ractor.yield(ENV.slice("")) + Ractor.yield(ENV.slice("unknown")) + Ractor.yield(ENV.slice("foo", "baz")) + end + assert_equal({}, r.take) + assert_equal({}, r.take) + assert_equal({}, r.take) + assert_equal({"foo"=>"bar", "baz"=>"qux"}, r.take) + end; + end + + def test_except_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + ENV["bar"] = "rab" + Ractor.yield ENV.except() + Ractor.yield ENV.except("") + Ractor.yield ENV.except("unknown") + Ractor.yield ENV.except("foo", "baz") + end + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take) + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take) + assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take) + assert_equal({"bar"=>"rab"}, r.take) + end; + end + + def test_clear_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + Ractor.yield ENV.size + end + assert_equal(0, r.take) + end; + end + + def test_to_s_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.to_s + end + assert_equal("ENV", r.take) + end; + end + + def test_inspect_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + s = ENV.inspect + Ractor.yield s + end + s = r.take + if #{ignore_case_str} + s = s.upcase + assert(s == '{"FOO"=>"BAR", "BAZ"=>"QUX"}' || s == '{"BAZ"=>"QUX", "FOO"=>"BAR"}') + else + assert(s == '{"foo"=>"bar", "baz"=>"qux"}' || s == '{"baz"=>"qux", "foo"=>"bar"}') + end + end; + end + + def test_to_a_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + a = ENV.to_a + Ractor.yield a + end + a = r.take + assert_equal(2, a.size) + if #{ignore_case_str} + a = a.map {|x| x.map {|y| y.upcase } } + assert(a == [%w(FOO BAR), %w(BAZ QUX)] || a == [%w(BAZ QUX), %w(FOO BAR)]) + else + assert(a == [%w(foo bar), %w(baz qux)] || a == [%w(baz qux), %w(foo bar)]) + end + end; + end + + def test_rehash_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.rehash + end + assert_nil(r.take) + end; + end + + def test_size_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + s = ENV.size + ENV["test"] = "foo" + Ractor.yield [s, ENV.size] + end + s, s2 = r.take + assert_equal(s + 1, s2) + end; + end + + def test_empty_p_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + Ractor.yield ENV.empty? + ENV["test"] = "foo" + Ractor.yield ENV.empty? + end + assert r.take + assert !r.take + end; + end + + def test_has_key_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + Ractor.yield ENV.has_key?("test") + ENV["test"] = "foo" + Ractor.yield ENV.has_key?("test") + #{str_to_yield_invalid_envvar_errors("v", "ENV.has_key?(v)")} + end + assert !r.take + assert r.take + #{str_to_receive_invalid_envvar_errors("r")} + end; + end + + def test_assoc_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + Ractor.yield ENV.assoc("test") + ENV["test"] = "foo" + Ractor.yield ENV.assoc("test") + #{str_to_yield_invalid_envvar_errors("v", "ENV.assoc(v)")} + end + assert_nil(r.take) + k, v = r.take + if #{ignore_case_str} + assert_equal("TEST", k.upcase) + assert_equal("FOO", v.upcase) + else + assert_equal("test", k) + assert_equal("foo", v) + end + #{str_to_receive_invalid_envvar_errors("r")} + encoding = /mswin|mingw/ =~ RUBY_PLATFORM ? Encoding::UTF_8 : Encoding.find("locale") + assert_equal(encoding, v.encoding) + end; + end + + def test_has_value2_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + Ractor.yield ENV.has_value?("foo") + ENV["test"] = "foo" + Ractor.yield ENV.has_value?("foo") + end + assert !r.take + assert r.take + end; + end + + def test_rassoc_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV.clear + Ractor.yield ENV.rassoc("foo") + ENV["foo"] = "bar" + ENV["test"] = "foo" + ENV["baz"] = "qux" + Ractor.yield ENV.rassoc("foo") + end + assert_nil(r.take) + k, v = r.take + if #{ignore_case_str} + assert_equal("TEST", k.upcase) + assert_equal("FOO", v.upcase) + else + assert_equal("test", k) + assert_equal("foo", v) + end + end; + end + + def test_to_hash_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h = {} + ENV.each {|k, v| h[k] = v } + Ractor.yield [h, ENV.to_hash] + end + h, h2 = r.take + assert_equal(h, h2) + end; + end + + def test_to_h_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + Ractor.yield [ENV.to_hash, ENV.to_h] + Ractor.yield [ENV.map {|k, v| ["$\#{k}", v.size]}.to_h, ENV.to_h {|k, v| ["$\#{k}", v.size]}] + end + a, b = r.take + assert_equal(a,b) + c, d = r.take + assert_equal(c,d) + end; + end + + def test_reject_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + h1 = {} + ENV.each_pair {|k, v| h1[k] = v } + ENV["test"] = "foo" + h2 = ENV.reject {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" } + Ractor.yield [h1, h2] + end + h1, h2 = r.take + assert_equal(h1, h2) + end; + end + + def test_shift_in_ractor + assert_ractor(<<-"end;") + #{STR_DEFINITION_FOR_CHECK} + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + a = ENV.shift + b = ENV.shift + Ractor.yield [a,b] + Ractor.yield ENV.shift + end + a,b = r.take + check([a, b], [%w(foo bar), %w(baz qux)]) + assert_nil(r.take) + end; + end + + def test_invert_in_ractor + assert_ractor(<<-"end;") + #{STR_DEFINITION_FOR_CHECK} + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + Ractor.yield(ENV.invert) + end + check(r.take.to_a, [%w(bar foo), %w(qux baz)]) + end; + end + + def test_replace_in_ractor + assert_ractor(<<-"end;") + #{STR_DEFINITION_FOR_CHECK} + r = Ractor.new do + ENV["foo"] = "xxx" + ENV.replace({"foo"=>"bar", "baz"=>"qux"}) + Ractor.yield ENV.to_hash + ENV.replace({"Foo"=>"Bar", "Baz"=>"Qux"}) + Ractor.yield ENV.to_hash + end + check(r.take.to_a, [%w(foo bar), %w(baz qux)]) + check(r.take.to_a, [%w(Foo Bar), %w(Baz Qux)]) + end; + end + + def test_update_in_ractor + assert_ractor(<<-"end;") + #{STR_DEFINITION_FOR_CHECK} + r = Ractor.new do + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + ENV.update({"baz"=>"quux","a"=>"b"}) + Ractor.yield ENV.to_hash + ENV.clear + ENV["foo"] = "bar" + ENV["baz"] = "qux" + ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 } + Ractor.yield ENV.to_hash + end + check(r.take.to_a, [%w(foo bar), %w(baz quux), %w(a b)]) + check(r.take.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)]) + end; + end + + def test_huge_value_in_ractor + assert_ractor(<<-"end;") + huge_value = "bar" * 40960 + r = Ractor.new huge_value do |v| + ENV["foo"] = "bar" + #{str_for_yielding_exception_class("ENV['foo'] = v ")} + Ractor.yield ENV["foo"] + end + + if /mswin|ucrt/ =~ RUBY_PLATFORM + #{str_for_assert_raise_on_yielded_exception_class(Errno::EINVAL, "r")} + result = r.take + assert_equal("bar", result) + else + exception_class = r.take + assert_equal(NilClass, exception_class) + result = r.take + assert_equal(huge_value, result) + end + end; + end + + def test_frozen_env_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + #{str_for_yielding_exception_class("ENV.freeze")} + end + #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")} + end; + end + + def test_frozen_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + ENV["#{PATH_ENV}"] = "/" + ENV.each do |k, v| + Ractor.yield [k.frozen?] + Ractor.yield [v.frozen?] + end + ENV.each_key do |k| + Ractor.yield [k.frozen?] + end + ENV.each_value do |v| + Ractor.yield [v.frozen?] + end + ENV.each_key do |k| + Ractor.yield [ENV[k].frozen?, "[\#{k.dump}]"] + Ractor.yield [ENV.fetch(k).frozen?, "fetch(\#{k.dump})"] + end + Ractor.yield "finished" + end + while((params=r.take) != "finished") + assert(*params) + end + end; + end + + def test_shared_substring_in_ractor + assert_ractor(<<-"end;") + r = Ractor.new do + bug12475 = '[ruby-dev:49655] [Bug #12475]' + n = [*"0".."9"].join("")*3 + e0 = ENV[n0 = "E\#{n}"] + e1 = ENV[n1 = "E\#{n}."] + ENV[n0] = nil + ENV[n1] = nil + ENV[n1.chop] = "T\#{n}.".chop + ENV[n0], e0 = e0, ENV[n0] + ENV[n1], e1 = e1, ENV[n1] + Ractor.yield [n, e0, e1, bug12475] + end + n, e0, e1, bug12475 = r.take + assert_equal("T\#{n}", e0, bug12475) + assert_nil(e1, bug12475) + end; + end + + def test_ivar_in_env_should_not_be_access_from_non_main_ractors + assert_ractor <<~RUBY + ENV.instance_eval{ @a = "hello" } + assert_equal "hello", ENV.instance_variable_get(:@a) + + r_get = Ractor.new do + ENV.instance_variable_get(:@a) + rescue Ractor::IsolationError => e + e + end + assert_equal Ractor::IsolationError, r_get.take.class + + r_get = Ractor.new do + ENV.instance_eval{ @a } + rescue Ractor::IsolationError => e + e + end + + assert_equal Ractor::IsolationError, r_get.take.class + + r_set = Ractor.new do + ENV.instance_eval{ @b = "hello" } + rescue Ractor::IsolationError => e + e + end + + assert_equal Ractor::IsolationError, r_set.take.class + RUBY + end + if RUBY_PLATFORM =~ /bccwin|mswin|mingw/ def test_memory_leak_aset bug9977 = '[ruby-dev:48323] [Bug #9977]' @@ -566,15 +1505,13 @@ def test_memory_leak_shift end; end - if Encoding.find("locale") == Encoding::UTF_8 - def test_utf8 - text = "testing \u{e5 e1 e2 e4 e3 101 3042}" - test = ENV["test"] - ENV["test"] = text - assert_equal text, ENV["test"] - ensure - ENV["test"] = test - end + def test_utf8 + text = "testing \u{e5 e1 e2 e4 e3 101 3042}" + test = ENV["test"] + ENV["test"] = text + assert_equal text, ENV["test"] + ensure + ENV["test"] = test end end end diff --git a/ruby/test/ruby/test_eval.rb b/ruby/test/ruby/test_eval.rb index 3d6116edb..d55977c98 100644 --- a/ruby/test/ruby/test_eval.rb +++ b/ruby/test/ruby/test_eval.rb @@ -219,6 +219,12 @@ def test_instance_eval_cvar end end + def test_instance_exec_cvar + [Object.new, [], 7, :sym, true, false, nil].each do |obj| + assert_equal(13, obj.instance_exec{@@cvar}) + end + end + def test_instance_eval_method bug2788 = '[ruby-core:28324]' [Object.new, [], nil, true, false].each do |o| @@ -253,6 +259,70 @@ def test_instance_eval_const assert_equal(2, bar) end + def test_instance_exec_block_basic + forall_TYPE do |o| + assert_equal nil, o.instance_exec { nil } + assert_equal true, o.instance_exec { true } + assert_equal false, o.instance_exec { false } + assert_equal o, o.instance_exec { self } + assert_equal 1, o.instance_exec { 1 } + assert_equal :sym, o.instance_exec { :sym } + + assert_equal 11, o.instance_exec { 11 } + assert_equal 12, o.instance_exec { @ivar } unless o.frozen? + assert_equal 13, o.instance_exec { @@cvar } + assert_equal 14, o.instance_exec { $gvar__eval } + assert_equal 15, o.instance_exec { Const } + assert_equal 16, o.instance_exec { 7 + 9 } + assert_equal 17, o.instance_exec { 17.to_i } + assert_equal "18", o.instance_exec { "18" } + assert_equal "19", o.instance_exec { "1#{9}" } + + 1.times { + assert_equal 12, o.instance_exec { @ivar } unless o.frozen? + assert_equal 13, o.instance_exec { @@cvar } + assert_equal 14, o.instance_exec { $gvar__eval } + assert_equal 15, o.instance_exec { Const } + } + end + end + + def test_instance_exec_method_definition + klass = Class.new + o = klass.new + + o.instance_exec do + def foo + :foo_result + end + end + + assert_respond_to o, :foo + refute_respond_to klass, :foo + refute_respond_to klass.new, :foo + + assert_equal :foo_result, o.foo + end + + def test_instance_exec_eval_method_definition + klass = Class.new + o = klass.new + + o.instance_exec do + eval %{ + def foo + :foo_result + end + } + end + + assert_respond_to o, :foo + refute_respond_to klass, :foo + refute_respond_to klass.new, :foo + + assert_equal :foo_result, o.foo + end + # # From ruby/test/ruby/test_eval.rb # @@ -347,6 +417,10 @@ module EvTest assert_equal(55, eval("foo22")) assert_equal(55, foo22) }.call + + self.class.class_eval do + remove_const :EvTest + end end def test_nil_instance_eval_cvar @@ -470,9 +544,12 @@ def test_eval_location_fstring end def test_eval_location_binding - assert_warning(/__FILE__ in eval/) do - assert_equal(__FILE__, eval("__FILE__", binding)) - end + assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", nil)) + assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", binding)) + assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", nil, 'foo')) + assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", binding, 'foo')) + assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", nil, 'foo', 2)) + assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", binding, 'foo', 2)) end def test_fstring_instance_eval diff --git a/ruby/test/ruby/test_exception.rb b/ruby/test/ruby/test_exception.rb index 79ac11ab2..f99bb230a 100644 --- a/ruby/test/ruby/test_exception.rb +++ b/ruby/test/ruby/test_exception.rb @@ -78,6 +78,77 @@ def test_exception_ensure_2 # just duplication? assert(!bad) end + def test_exception_in_ensure_with_next + string = "[ruby-core:82936] [Bug #13930]" + assert_raise_with_message(RuntimeError, string) do + lambda do + next + rescue + assert(false) + ensure + raise string + end.call + assert(false) + end + + assert_raise_with_message(RuntimeError, string) do + flag = true + while flag + flag = false + begin + next + rescue + assert(false) + ensure + raise string + end + end + end + + iseq = RubyVM::InstructionSequence.compile(<<-RUBY) + begin + while true + break + end + rescue + end + RUBY + + assert_equal false, iseq.to_a[13].any?{|(e,_)| e == :throw} + end + + def test_exception_in_ensure_with_redo + string = "[ruby-core:82936] [Bug #13930]" + + assert_raise_with_message(RuntimeError, string) do + i = 0 + lambda do + i += 1 + redo if i < 2 + rescue + assert(false) + ensure + raise string + end.call + assert(false) + end + end + + def test_exception_in_ensure_with_return + @string = "[ruby-core:97104] [Bug #16618]" + def self.meow + return if true # This if modifier suppresses "warning: statement not reached" + assert(false) + rescue + assert(false) + ensure + raise @string + end + assert_raise_with_message(RuntimeError, @string) do + meow + end + end + def test_errinfo_in_debug bug9568 = EnvUtil.labeled_class("[ruby-core:61091] [Bug #9568]", RuntimeError) do def to_s @@ -181,6 +252,27 @@ def test_catch_throw_in_require } end + def test_catch_throw_in_require_cant_be_rescued + bug18562 = '[ruby-core:107403]' + Tempfile.create(["dep", ".rb"]) {|t| + t.puts("throw :extdep, 42") + t.close + + rescue_all = Class.new(Exception) + def rescue_all.===(_) + raise "should not reach here" + end + + v = assert_throw(:extdep, bug18562) do + require t.path + rescue rescue_all => e + assert(false, "should not reach here") + end + + assert_equal(42, v, bug18562) + } + end + def test_throw_false bug12743 = '[ruby-core:77229] [Bug #12743]' Thread.start { @@ -438,16 +530,6 @@ def test_exit_success_p assert_not_send([e, :success?], "abort means failure") end - def test_nomethoderror - bug3237 = '[ruby-core:29948]' - str = "\u2600" - id = :"\u2604" - msg = "undefined method `#{id}' for \"#{str}\":String" - assert_raise_with_message(NoMethodError, msg, bug3237) do - str.__send__(id) - end - end - def test_errno assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding) end @@ -499,6 +581,35 @@ def test_exception_in_name_error_to_str end; end + def test_ensure_after_nomemoryerror + skip "Forcing NoMemoryError causes problems in some environments" + assert_separately([], "$_ = 'a' * 1_000_000_000_000_000_000") + rescue NoMemoryError + assert_raise(NoMemoryError) do + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + bug15779 = bug15779 = '[ruby-core:92342]' + begin; + require 'open-uri' + + begin + 'a' * 1_000_000_000_000_000_000 + ensure + URI.open('http://www.ruby-lang.org/') + end + end; + end + rescue Test::Unit::AssertionFailedError + # Possibly compiled with -DRUBY_DEBUG, in which + # case rb_bug is used instead of NoMemoryError, + # and we cannot test ensure after NoMemoryError. + rescue RangeError + # MingW can raise RangeError instead of NoMemoryError, + # so we cannot test this case. + rescue Timeout::Error + # Solaris 11 CI times out instead of raising NoMemoryError, + # so we cannot test this case. + end + def test_equal bug5865 = '[ruby-core:41979]' assert_equal(RuntimeError.new("a"), RuntimeError.new("a"), bug5865) @@ -753,7 +864,7 @@ def test_cause_thread_with_cause bug12741 = '[ruby-core:77222] [Bug #12741]' x = Thread.current - q = Queue.new + q = Thread::Queue.new y = Thread.start do q.pop begin @@ -824,261 +935,28 @@ def test_cause_with_frozen_exception } end - def test_anonymous_message - assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/) - end - - PrettyObject = - Class.new(BasicObject) do - alias object_id __id__ - def pretty_inspect; "`obj'"; end - alias inspect pretty_inspect - end - - def test_frozen_error_receiver - obj = Object.new.freeze - (obj.foo = 1) rescue (e = $!) - assert_same(obj, e.receiver) - obj.singleton_class.const_set(:A, 2) rescue (e = $!) - assert_same(obj.singleton_class, e.receiver) - end - - def test_frozen_error_initialize - obj = Object.new - exc = FrozenError.new("bar", receiver: obj) - assert_equal("bar", exc.message) - assert_same(obj, exc.receiver) - - exc = FrozenError.new("bar") - assert_equal("bar", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - - exc = FrozenError.new - assert_equal("FrozenError", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - end - - def test_frozen_error_message - obj = Object.new.freeze - e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { - obj.instance_variable_set(:@test, true) - } - assert_include(e.message, obj.inspect) - - klass = Class.new do - def init - @x = true - end - def inspect - init - super - end - end - obj = klass.new.freeze - e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { - obj.init - } - assert_include(e.message, klass.inspect) - end - - def test_name_error_new_default - error = NameError.new - assert_equal("NameError", error.message) - end - - def test_name_error_new_message - error = NameError.new("Message") - assert_equal("Message", error.message) - end - - def test_name_error_new_name - error = NameError.new("Message") - assert_nil(error.name) - - error = NameError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_name_error_new_receiver - receiver = Object.new - - error = NameError.new - assert_raise(ArgumentError) {error.receiver} - assert_equal("NameError", error.message) - - error = NameError.new(receiver: receiver) - assert_equal(["NameError", receiver], - [error.message, error.receiver]) - - error = NameError.new("Message", :foo, receiver: receiver) - assert_equal(["Message", receiver, :foo], - [error.message, error.receiver, error.name]) - end - - def test_nomethod_error_new_default - error = NoMethodError.new - assert_equal("NoMethodError", error.message) - end - - def test_nomethod_error_new_message - error = NoMethodError.new("Message") - assert_equal("Message", error.message) - end - - def test_nomethod_error_new_name - error = NoMethodError.new("Message") - assert_nil(error.name) - - error = NoMethodError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_nomethod_error_new_name_args - error = NoMethodError.new("Message", :foo) - assert_nil(error.args) - - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_equal([:foo, [1, 2]], [error.name, error.args]) - end - - def test_nomethod_error_new_name_args_priv - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_not_predicate(error, :private_call?) - - error = NoMethodError.new("Message", :foo, [1, 2], true) - assert_equal([:foo, [1, 2], true], - [error.name, error.args, error.private_call?]) - end - - def test_nomethod_error_new_receiver - receiver = Object.new - - error = NoMethodError.new - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new(receiver: receiver) - assert_equal(receiver, error.receiver) - - error = NoMethodError.new("Message") - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", receiver: receiver) - assert_equal(["Message", receiver], - [error.message, error.receiver]) - - error = NoMethodError.new("Message", :foo) - assert_raise(ArgumentError) {error.receiver} - - msg = defined?(DidYouMean.formatter) ? - "Message\nDid you mean? for" : "Message" - - error = NoMethodError.new("Message", :foo, receiver: receiver) - assert_equal([msg, :foo, receiver], - [error.message, error.name, error.receiver]) - - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver) - assert_equal([msg, :foo, [1, 2], receiver], - [error.message, error.name, error.args, error.receiver]) - - error = NoMethodError.new("Message", :foo, [1, 2], true) - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", :foo, [1, 2], true, receiver: receiver) - assert_equal([:foo, [1, 2], true, receiver], - [error.name, error.args, error.private_call?, error.receiver]) - end - - def test_name_error_info_const - obj = PrettyObject.new - - e = assert_raise(NameError) { - obj.instance_eval("Object") - } - assert_equal(:Object, e.name) - - e = assert_raise(NameError) { - BasicObject::X - } - assert_same(BasicObject, e.receiver) - assert_equal(:X, e.name) - end - - def test_name_error_info_method - obj = PrettyObject.new - - e = assert_raise(NameError) { - obj.instance_eval {foo} - } - assert_equal(:foo, e.name) - assert_same(obj, e.receiver) - - e = assert_raise(NoMethodError) { - obj.foo(1, 2) - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_not_predicate(e, :private_call?) - - e = assert_raise(NoMethodError) { - obj.instance_eval {foo(1, 2)} - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_predicate(e, :private_call?) - end - - def test_name_error_info_local_variables - obj = PrettyObject.new - def obj.test(a, b=nil, *c, &d) - e = a - 1.times {|f| g = foo; g} - e - end - - e = assert_raise(NameError) { - obj.test(3) - } - assert_equal(:foo, e.name) - assert_same(obj, e.receiver) - assert_equal(%i[a b c d e f g], e.local_variables.sort) - end - - def test_name_error_info_method_missing - obj = PrettyObject.new - def obj.method_missing(*) - super + def test_cause_exception_in_cause_message + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}") do |outs, errs, status| + begin; + exc = Class.new(StandardError) do + def initialize(obj, cnt) + super(obj) + @errcnt = cnt + end + def to_s + return super if @errcnt <= 0 + @errcnt -= 1 + raise "xxx" + end + end.new("ok", 10) + raise "[Bug #17033]", cause: exc + end; + assert_equal(1, errs.count {|m| m.include?("[Bug #17033]")}, proc {errs.pretty_inspect}) end - - e = assert_raise(NoMethodError) { - obj.foo(1, 2) - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_not_predicate(e, :private_call?) - - e = assert_raise(NoMethodError) { - obj.instance_eval {foo(1, 2)} - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_predicate(e, :private_call?) end - def test_name_error_info_parent_iseq_mark - assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;') - -> {require ARGV[0]}.call - end; + def test_anonymous_message + assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/) end def test_output_string_encoding @@ -1158,28 +1036,37 @@ def test_message_of_name_error end end - def capture_warning_warn + def capture_warning_warn(category: false) verbose = $VERBOSE deprecated = Warning[:deprecated] + experimental = Warning[:experimental] warning = [] ::Warning.class_eval do alias_method :warn2, :warn remove_method :warn - define_method(:warn) do |str| - warning << str + if category + define_method(:warn) do |str, category: nil| + warning << [str, category] + end + else + define_method(:warn) do |str| + warning << str + end end end $VERBOSE = true Warning[:deprecated] = true + Warning[:experimental] = true yield return warning ensure $VERBOSE = verbose Warning[:deprecated] = deprecated + Warning[:experimental] = experimental ::Warning.class_eval do remove_method :warn @@ -1189,14 +1076,38 @@ def capture_warning_warn end def test_warning_warn - warning = capture_warning_warn {@a} - assert_match(/instance variable @a not initialized/, warning[0]) + warning = capture_warning_warn {$asdfasdsda_test_warning_warn} + assert_match(/global variable `\$asdfasdsda_test_warning_warn' not initialized/, warning[0]) assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"}) assert_equal([], capture_warning_warn {warn}) assert_equal(["\n"], capture_warning_warn {warn ""}) end + def test_warn_deprecated_backwards_compatibility_category + warning = capture_warning_warn { Dir.exists?("non-existent") } + + assert_match(/deprecated/, warning[0]) + end + + def test_warn_deprecated_category + warning = capture_warning_warn(category: true) { Dir.exists?("non-existent") } + + assert_equal :deprecated, warning[0][1] + end + + def test_warn_deprecated_to_remove_backwards_compatibility_category + warning = capture_warning_warn { Object.new.tainted? } + + assert_match(/deprecated/, warning[0]) + end + + def test_warn_deprecated_to_remove_category + warning = capture_warning_warn(category: true) { Object.new.tainted? } + + assert_equal :deprecated, warning[0][1] + end + def test_kernel_warn_uplevel warning = capture_warning_warn {warn("test warning", uplevel: 0)} assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0]) @@ -1208,8 +1119,7 @@ def (obj = Object.new).w(n) warn("test warning", uplevel: n) end assert_raise(ArgumentError) {warn("test warning", uplevel: -1)} assert_in_out_err(["-e", "warn 'ok', uplevel: 1"], '', [], /warning:/) warning = capture_warning_warn {warn("test warning", {uplevel: 0})} - assert_equal("#{__FILE__}:#{__LINE__-1}: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call\n", warning[0]) - assert_match(/warning: The called method (?:`.*' )?is defined here|warning: test warning/, warning[1]) + assert_match(/test warning.*{:uplevel=>0}/m, warning[0]) warning = capture_warning_warn {warn("test warning", **{uplevel: 0})} assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0]) warning = capture_warning_warn {warn("test warning", {uplevel: 0}, **{})} @@ -1238,10 +1148,12 @@ def test_warning_warn_circular_require_backtrace t.puts "require '#{basename}'" t.close $LOAD_PATH.push(File.dirname(t)) - warning = capture_warning_warn {require basename} + warning = capture_warning_warn { + assert require(basename) + } ensure $LOAD_PATH.pop - $LOADED_FEATURES.delete(t) + $LOADED_FEATURES.delete(t.path) end assert_equal(1, warning.size) assert_match(/circular require/, warning.first) @@ -1249,7 +1161,7 @@ def test_warning_warn_circular_require_backtrace end def test_warning_warn_super - assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /instance variable @a not initialized/) + assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /global variable `\$asdfiasdofa_test_warning_warn_super' not initialized/) {# module Warning def warn(message) @@ -1258,7 +1170,7 @@ def warn(message) end $VERBOSE = true - @a + $asdfiasdofa_test_warning_warn_super }; end @@ -1269,6 +1181,54 @@ def test_warning_category assert_include([true, false], Warning[:experimental]) end + def test_warning_category_deprecated + warning = EnvUtil.verbose_warning do + deprecated = Warning[:deprecated] + Warning[:deprecated] = true + Warning.warn "deprecated feature", category: :deprecated + ensure + Warning[:deprecated] = deprecated + end + assert_equal "deprecated feature", warning + + warning = EnvUtil.verbose_warning do + deprecated = Warning[:deprecated] + Warning[:deprecated] = false + Warning.warn "deprecated feature", category: :deprecated + ensure + Warning[:deprecated] = deprecated + end + assert_empty warning + end + + def test_warning_category_experimental + warning = EnvUtil.verbose_warning do + experimental = Warning[:experimental] + Warning[:experimental] = true + Warning.warn "experimental feature", category: :experimental + ensure + Warning[:experimental] = experimental + end + assert_equal "experimental feature", warning + + warning = EnvUtil.verbose_warning do + experimental = Warning[:experimental] + Warning[:experimental] = false + Warning.warn "experimental feature", category: :experimental + ensure + Warning[:experimental] = experimental + end + assert_empty warning + end + + def test_undef_Warning_warn + assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + Warning.undef_method(:warn) + assert_raise(NoMethodError) { warn "" } + end; + end + def test_undefined_backtrace assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") begin; @@ -1418,13 +1378,11 @@ def test_full_message if Exception.to_tty? assert_match(/\e/, message) message = message.gsub(/\e\[[\d;]*m/, '') - assert_operator(message, :start_with?, remark) - assert_operator(message, :end_with?, bottom) else assert_not_match(/\e/, message) - assert_operator(message, :start_with?, bottom) - assert_operator(message, :end_with?, top) end + assert_operator(message, :start_with?, bottom) + assert_operator(message, :end_with?, top) end def test_exception_in_message diff --git a/ruby/test/ruby/test_fiber.rb b/ruby/test/ruby/test_fiber.rb index a7ed9ac7e..e4b7322bd 100644 --- a/ruby/test/ruby/test_fiber.rb +++ b/ruby/test/ruby/test_fiber.rb @@ -34,8 +34,8 @@ def test_term end def test_many_fibers - skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if RubyVM::MJIT.enabled? - max = 10_000 + skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + max = 1000 assert_equal(max, max.times{ Fiber.new{} }) @@ -50,7 +50,7 @@ def test_many_fibers end def test_many_fibers_with_threads - assert_normal_exit <<-SRC, timeout: 60 + assert_normal_exit <<-SRC, timeout: (/solaris/i =~ RUBY_PLATFORM ? 1000 : 60) max = 1000 @cnt = 0 (1..100).map{|ti| @@ -169,6 +169,16 @@ def test_raise assert_equal(:ok, fib.raise) end + def test_raise_transferring_fiber + root = Fiber.current + fib = Fiber.new { root.transfer } + fib.transfer + assert_raise(RuntimeError){ + fib.raise "can raise with transfer: true" + } + assert_not_predicate(fib, :alive?) + end + def test_transfer ary = [] f2 = nil @@ -184,6 +194,33 @@ def test_transfer assert_equal([:baz], ary) end + def test_terminate_transferred_fiber + log = [] + fa1 = fa2 = fb1 = r1 = nil + + fa1 = Fiber.new{ + fa2 = Fiber.new{ + log << :fa2_terminate + } + fa2.resume + log << :fa1_terminate + } + fb1 = Fiber.new{ + fa1.transfer + log << :fb1_terminate + } + + r1 = Fiber.new{ + fb1.transfer + log << :r1_terminate + } + + r1.resume + log << :root_terminate + + assert_equal [:fa2_terminate, :fa1_terminate, :r1_terminate, :root_terminate], log + end + def test_tls # def tvar(var, val) @@ -278,29 +315,71 @@ def test_no_valid_cfp assert_instance_of(Class, Fiber.new(&Class.new.method(:undef_method)).resume(:to_s), bug5083) end - def test_prohibit_resume_transferred_fiber + def test_prohibit_transfer_to_resuming_fiber + root_fiber = Fiber.current + assert_raise(FiberError){ - root_fiber = Fiber.current - f = Fiber.new{ - root_fiber.transfer - } - f.transfer - f.resume + fiber = Fiber.new{ root_fiber.transfer } + fiber.resume + } + + fa1 = Fiber.new{ + _fa2 = Fiber.new{ root_fiber.transfer } + } + fb1 = Fiber.new{ + _fb2 = Fiber.new{ root_fiber.transfer } } + fa1.transfer + fb1.transfer + assert_raise(FiberError){ - g=nil - f=Fiber.new{ - g.resume - g.resume - } - g=Fiber.new{ - f.resume - f.resume + fa1.transfer + } + assert_raise(FiberError){ + fb1.transfer + } + end + + def test_prohibit_transfer_to_yielding_fiber + f1 = f2 = f3 = nil + + f1 = Fiber.new{ + f2 = Fiber.new{ + f3 = Fiber.new{ + p f3: Fiber.yield + } + f3.resume } - f.transfer + f2.resume + } + f1.resume + + assert_raise(FiberError){ f3.transfer 10 } + end + + def test_prohibit_resume_to_transferring_fiber + root_fiber = Fiber.current + + assert_raise(FiberError){ + Fiber.new{ + root_fiber.resume + }.transfer + } + + f1 = f2 = nil + f1 = Fiber.new do + f2.transfer + end + f2 = Fiber.new do + f1.resume # attempt to resume transferring fiber + end + + assert_raise(FiberError){ + f1.transfer } end + def test_fork_from_fiber skip 'fork not supported' unless Process.respond_to?(:fork) pid = nil @@ -312,13 +391,12 @@ def test_fork_from_fiber Fiber.new { xpid = fork do # enough to trigger GC on old root fiber - count = 10000 - count = 1000 if /openbsd/i =~ RUBY_PLATFORM + count = 1000 count.times do Fiber.new {}.transfer Fiber.new { Fiber.yield } end - exit!(0) + exit!(true) end }.transfer _, status = Process.waitpid2(xpid) @@ -327,8 +405,13 @@ def test_fork_from_fiber end.resume end pid, status = Process.waitpid2(pid) - assert_equal(0, status.exitstatus, bug5700) - assert_equal(false, status.signaled?, bug5700) + assert_not_predicate(status, :signaled?, bug5700) + assert_predicate(status, :success?, bug5700) + + pid = Fiber.new {fork}.resume + pid, status = Process.waitpid2(pid) + assert_not_predicate(status, :signaled?) + assert_predicate(status, :success?) end def test_exit_in_fiber @@ -341,56 +424,12 @@ def test_exit_in_fiber def test_fatal_in_fiber assert_in_out_err(["-r-test-/fatal/rb_fatal", "-e", <<-EOS], "", [], /ok/) Fiber.new{ - rb_fatal "ok" + Bug.rb_fatal "ok" }.resume puts :ng # unreachable. EOS end - def invoke_rec script, vm_stack_size, machine_stack_size, use_length = true - env = {} - env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size - env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size - out = Dir.mktmpdir("test_fiber") {|tmpdir| - out, err, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, chdir: tmpdir, timeout: 30) - assert(!status.signaled?, FailDesc[status, nil, err]) - out - } - use_length ? out.length : out - end - - def test_stack_size - h_default = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', nil, nil, false)) - h_0 = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 0, 0, false)) - h_large = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 1024 * 1024 * 5, 1024 * 1024 * 10, false)) - - assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size]) - assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size]) - assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size]) - assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size]) - - # check VM machine stack size - script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume' - size_default = invoke_rec script, nil, nil - assert_operator(size_default, :>, 0) - size_0 = invoke_rec script, 0, nil - assert_operator(size_default, :>, size_0) - size_large = invoke_rec script, 1024 * 1024 * 5, nil - assert_operator(size_default, :<, size_large) - - return if /mswin|mingw/ =~ RUBY_PLATFORM - - # check machine stack size - # Note that machine stack size may not change size (depend on OSs) - script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume' - vm_stack_size = 1024 * 1024 - size_default = invoke_rec script, vm_stack_size, nil - size_0 = invoke_rec script, vm_stack_size, 0 - assert_operator(size_default, :>=, size_0) - size_large = invoke_rec script, vm_stack_size, 1024 * 1024 * 10 - assert_operator(size_default, :<=, size_large) - end - def test_separate_lastmatch bug7678 = '[ruby-core:51331]' /a/ =~ "a" diff --git a/ruby/test/ruby/test_file_exhaustive.rb b/ruby/test/ruby/test_file_exhaustive.rb index 975bcb6bc..03675eaeb 100644 --- a/ruby/test/ruby/test_file_exhaustive.rb +++ b/ruby/test/ruby/test_file_exhaustive.rb @@ -78,6 +78,19 @@ def notownedfile @notownedfile end + def grpownedfile + return nil unless POSIX + return @grpownedfile if defined? @grpownedfile + if group = (Process.groups - [Process.egid]).last + grpownedfile = make_tmp_filename("grpownedfile") + make_file("grpowned", grpownedfile) + File.chown(nil, group, grpownedfile) + return @grpownedfile = grpownedfile + end + rescue + @grpownedfile = nil + end + def suidfile return @suidfile if defined? @suidfile if POSIX @@ -130,7 +143,7 @@ def hardlinkfile @hardlinkfile = make_tmp_filename("hardlinkfile") begin File.link(regular_file, @hardlinkfile) - rescue NotImplementedError, Errno::EINVAL # EINVAL for Windows Vista + rescue NotImplementedError, Errno::EINVAL, Errno::EACCES # EINVAL for Windows Vista, EACCES for Android Termux @hardlinkfile = nil end @hardlinkfile @@ -493,6 +506,9 @@ def test_owned_p def test_grpowned_p ## xxx assert_file.grpowned?(regular_file) assert_file.grpowned?(utf8_file) + if file = grpownedfile + assert_file.grpowned?(file) + end end if POSIX def io_open(file_name) @@ -679,6 +695,13 @@ def test_utime File.utime(t + 1, t + 2, zerofile) assert_equal(t + 1, File.atime(zerofile)) assert_equal(t + 2, File.mtime(zerofile)) + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + path = "foo\u{30b3 30d4 30fc}" + File.write(path, "") rescue next + assert_equal(1, File.utime(nil, nil, path)) + end + end end def test_utime_symlinkfile @@ -880,6 +903,8 @@ def test_expand_path_encoding assert_equal("#{Dir.pwd}/#{path}", File.expand_path(path)) assert_incompatible_encoding {|d| File.expand_path(d)} + + assert_equal(Encoding::UTF_8, File.expand_path("foo", "#{drive}/").encoding) end def test_expand_path_encoding_filesystem @@ -1245,6 +1270,12 @@ def test_dirname assert_equal(@dir, File.dirname(regular_file)) assert_equal(@dir, File.dirname(utf8_file)) assert_equal(".", File.dirname("")) + assert_equal(regular_file, File.dirname(regular_file, 0)) + assert_equal(@dir, File.dirname(regular_file, 1)) + assert_equal(File.dirname(@dir), File.dirname(regular_file, 2)) + return if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # rootdir and tmpdir are in different drives + assert_equal(rootdir, File.dirname(regular_file, regular_file.count('/'))) + assert_raise(ArgumentError) {File.dirname(regular_file, -1)} end def test_dirname_encoding @@ -1377,21 +1408,24 @@ def test_truncate end def test_flock_exclusive + timeout = EnvUtil.apply_timeout_scale(0.1).to_s File.open(regular_file, "r+") do |f| f.flock(File::LOCK_EX) - assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}") - begin + assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}") + begin; + timeout = ARGV[1].to_f open(ARGV[0], "r") do |f| - Timeout.timeout(0.1) do + Timeout.timeout(timeout) do assert(!f.flock(File::LOCK_SH|File::LOCK_NB)) end end end; - assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}") - begin + assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}") + begin; + timeout = ARGV[1].to_f open(ARGV[0], "r") do |f| assert_raise(Timeout::Error) do - Timeout.timeout(0.1) do + Timeout.timeout(timeout) do f.flock(File::LOCK_SH) end end @@ -1403,21 +1437,24 @@ def test_flock_exclusive end def test_flock_shared + timeout = EnvUtil.apply_timeout_scale(0.1).to_s File.open(regular_file, "r+") do |f| f.flock(File::LOCK_SH) - assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}") - begin + assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}") + begin; + timeout = ARGV[1].to_f open(ARGV[0], "r") do |f| - Timeout.timeout(0.1) do + Timeout.timeout(timeout) do assert(f.flock(File::LOCK_SH)) end end end; - assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}") - begin + assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}") + begin; + timeout = ARGV[1].to_f open(ARGV[0], "r+") do |f| assert_raise(Timeout::Error) do - Timeout.timeout(0.1) do + Timeout.timeout(timeout) do f.flock(File::LOCK_EX) end end @@ -1439,6 +1476,7 @@ def test_test fn1, zerofile, notownedfile, + grpownedfile, suidfile, sgidfile, stickyfile, @@ -1449,31 +1487,31 @@ def test_test fifo, socket ].compact.each do |f| - assert_equal(File.atime(f), test(?A, f)) - assert_equal(File.ctime(f), test(?C, f)) - assert_equal(File.mtime(f), test(?M, f)) - assert_equal(File.blockdev?(f), test(?b, f)) - assert_equal(File.chardev?(f), test(?c, f)) - assert_equal(File.directory?(f), test(?d, f)) - assert_equal(File.exist?(f), test(?e, f)) - assert_equal(File.file?(f), test(?f, f)) - assert_equal(File.setgid?(f), test(?g, f)) - assert_equal(File.grpowned?(f), test(?G, f)) - assert_equal(File.sticky?(f), test(?k, f)) - assert_equal(File.symlink?(f), test(?l, f)) - assert_equal(File.owned?(f), test(?o, f)) - assert_nothing_raised { test(?O, f) } - assert_equal(File.pipe?(f), test(?p, f)) - assert_equal(File.readable?(f), test(?r, f)) - assert_equal(File.readable_real?(f), test(?R, f)) - assert_equal(File.size?(f), test(?s, f)) - assert_equal(File.socket?(f), test(?S, f)) - assert_equal(File.setuid?(f), test(?u, f)) - assert_equal(File.writable?(f), test(?w, f)) - assert_equal(File.writable_real?(f), test(?W, f)) - assert_equal(File.executable?(f), test(?x, f)) - assert_equal(File.executable_real?(f), test(?X, f)) - assert_equal(File.zero?(f), test(?z, f)) + assert_equal(File.atime(f), test(?A, f), f) + assert_equal(File.ctime(f), test(?C, f), f) + assert_equal(File.mtime(f), test(?M, f), f) + assert_equal(File.blockdev?(f), test(?b, f), f) + assert_equal(File.chardev?(f), test(?c, f), f) + assert_equal(File.directory?(f), test(?d, f), f) + assert_equal(File.exist?(f), test(?e, f), f) + assert_equal(File.file?(f), test(?f, f), f) + assert_equal(File.setgid?(f), test(?g, f), f) + assert_equal(File.grpowned?(f), test(?G, f), f) + assert_equal(File.sticky?(f), test(?k, f), f) + assert_equal(File.symlink?(f), test(?l, f), f) + assert_equal(File.owned?(f), test(?o, f), f) + assert_nothing_raised(f) { test(?O, f) } + assert_equal(File.pipe?(f), test(?p, f), f) + assert_equal(File.readable?(f), test(?r, f), f) + assert_equal(File.readable_real?(f), test(?R, f), f) + assert_equal(File.size?(f), test(?s, f), f) + assert_equal(File.socket?(f), test(?S, f), f) + assert_equal(File.setuid?(f), test(?u, f), f) + assert_equal(File.writable?(f), test(?w, f), f) + assert_equal(File.writable_real?(f), test(?W, f), f) + assert_equal(File.executable?(f), test(?x, f), f) + assert_equal(File.executable_real?(f), test(?X, f), f) + assert_equal(File.zero?(f), test(?z, f), f) end assert_equal(false, test(?-, @dir, fn1)) assert_equal(true, test(?-, fn1, fn1)) @@ -1674,6 +1712,9 @@ def test_stat_owned_p def test_stat_grpowned_p ## xxx assert_predicate(File::Stat.new(regular_file), :grpowned?) + if file = grpownedfile + assert_predicate(File::Stat.new(file), :grpowned?) + end end if POSIX def test_stat_suid diff --git a/ruby/test/ruby/test_fixnum.rb b/ruby/test/ruby/test_fixnum.rb index bd18067dd..287825892 100644 --- a/ruby/test/ruby/test_fixnum.rb +++ b/ruby/test/ruby/test_fixnum.rb @@ -4,7 +4,6 @@ class TestFixnum < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown diff --git a/ruby/test/ruby/test_float.rb b/ruby/test/ruby/test_float.rb index 7cbf3b5a8..57a46fce9 100644 --- a/ruby/test/ruby/test_float.rb +++ b/ruby/test/ruby/test_float.rb @@ -171,6 +171,24 @@ def test_strtod assert_raise(ArgumentError, n += z + "A") {Float(n)} assert_raise(ArgumentError, n += z + ".0") {Float(n)} end + + x = nil + 2000.times do + x = Float("0x"+"0"*30) + break unless x == 0.0 + end + assert_equal(0.0, x, ->{"%a" % x}) + x = nil + 2000.times do + begin + x = Float("0x1."+"0"*270) + rescue ArgumentError => e + raise unless /"0x1\.0{270}"/ =~ e.message + else + break + end + end + assert_nil(x, ->{"%a" % x}) end def test_divmod @@ -305,6 +323,7 @@ def test_pow assert_equal(1.0, 1.0 ** (2**32)) assert_equal(1.0, 1.0 ** 1.0) assert_raise(TypeError) { 1.0 ** nil } + assert_equal(9.0, 3.0 ** 2) end def test_eql @@ -764,6 +783,9 @@ def test_round_half_invalid assert_raise_with_message(ArgumentError, /xxx/) { 1.0.round(half: "\0xxx") } + assert_raise_with_message(Encoding::CompatibilityError, /ASCII incompatible/) { + 1.0.round(half: "up".force_encoding("utf-16be")) + } end def test_Float @@ -878,6 +900,11 @@ def test_step end assert_equal([5.0, 4.0, 3.0, 2.0], 5.0.step(1.5, -1).to_a) + + assert_equal(11, ((0.24901079128550474)..(340.2500808898068)).step(34.00010700985213).to_a.size) + assert_equal(11, ((0.24901079128550474)..(340.25008088980684)).step(34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)..(-340.2500808898068)).step(-34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)..(-340.25008088980684)).step(-34.00010700985213).to_a.size) end def test_step2 @@ -889,7 +916,9 @@ def test_step_excl a = rand b = a+rand*1000 s = (b - a) / 10 - assert_equal(10, (a...b).step(s).to_a.length) + b = a + s*9.999999 + seq = (a...b).step(s) + assert_equal(10, seq.to_a.length, seq.inspect) end assert_equal([1.0, 2.9, 4.8, 6.699999999999999], (1.0...6.8).step(1.9).to_a) @@ -898,6 +927,11 @@ def test_step_excl (1.0 ... e).step(1E-16) do |n| assert_operator(n, :<=, e) end + + assert_equal(10, ((0.24901079128550474)...(340.2500808898068)).step(34.00010700985213).to_a.size) + assert_equal(11, ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).to_a.size) + assert_equal(10, ((-0.24901079128550474)...(-340.2500808898068)).step(-34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)...(-340.25008088980684)).step(-34.00010700985213).to_a.size) end def test_singleton_method diff --git a/ruby/test/ruby/test_frozen_error.rb b/ruby/test/ruby/test_frozen_error.rb new file mode 100644 index 000000000..ace1e4c77 --- /dev/null +++ b/ruby/test/ruby/test_frozen_error.rb @@ -0,0 +1,57 @@ +require 'test/unit' + +class TestFrozenError < Test::Unit::TestCase + def test_new_default + exc = FrozenError.new + assert_equal("FrozenError", exc.message) + assert_raise_with_message(ArgumentError, "no receiver is available") { + exc.receiver + } + end + + def test_new_message + exc = FrozenError.new("bar") + assert_equal("bar", exc.message) + assert_raise_with_message(ArgumentError, "no receiver is available") { + exc.receiver + } + end + + def test_new_receiver + obj = Object.new + exc = FrozenError.new("bar", receiver: obj) + assert_equal("bar", exc.message) + assert_same(obj, exc.receiver) + end + + def test_message + obj = Object.new.freeze + e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { + obj.instance_variable_set(:@test, true) + } + assert_include(e.message, obj.inspect) + + klass = Class.new do + def init + @x = true + end + def inspect + init + super + end + end + obj = klass.new.freeze + e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { + obj.init + } + assert_include(e.message, klass.inspect) + end + + def test_receiver + obj = Object.new.freeze + e = assert_raise(FrozenError) {def obj.foo; end} + assert_same(obj, e.receiver) + e = assert_raise(FrozenError) {obj.singleton_class.const_set(:A, 2)} + assert_same(obj.singleton_class, e.receiver) + end +end diff --git a/ruby/test/ruby/test_gc.rb b/ruby/test/ruby/test_gc.rb index ef99f69f5..baf9971c4 100644 --- a/ruby/test/ruby/test_gc.rb +++ b/ruby/test/ruby/test_gc.rb @@ -56,6 +56,7 @@ def test_start_full_mark return unless use_rgengc? skip 'stress' if GC.stress + 3.times { GC.start } # full mark and next time it should be minor mark GC.start(full_mark: false) assert_nil GC.latest_gc_info(:major_by) @@ -91,16 +92,23 @@ def test_stat assert_kind_of(Integer, res[:count]) stat, count = {}, {} - GC.start - GC.stat(stat) - ObjectSpace.count_objects(count) + 2.times{ # to ignore const cache imemo creation + GC.start + GC.stat(stat) + ObjectSpace.count_objects(count) + # repeat same methods invocation for cache object creation. + GC.stat(stat) + ObjectSpace.count_objects(count) + } assert_equal(count[:TOTAL]-count[:FREE], stat[:heap_live_slots]) assert_equal(count[:FREE], stat[:heap_free_slots]) # measure again without GC.start - 1000.times{ "a" + "b" } - GC.stat(stat) - ObjectSpace.count_objects(count) + 2.times{ # to ignore const cache imemo creation + 1000.times{ "a" + "b" } + GC.stat(stat) + ObjectSpace.count_objects(count) + } assert_equal(count[:FREE], stat[:heap_free_slots]) end @@ -141,10 +149,15 @@ def test_latest_gc_info assert_equal :newobj, GC.latest_gc_info[:gc_by] eom + GC.latest_gc_info(h = {}) # allocate hash and rehearsal GC.start - assert_equal :force, GC.latest_gc_info[:major_by] if use_rgengc? - assert_equal :method, GC.latest_gc_info[:gc_by] - assert_equal true, GC.latest_gc_info[:immediate_sweep] + GC.start + GC.start + GC.latest_gc_info(h) + + assert_equal :force, h[:major_by] if use_rgengc? + assert_equal :method, h[:gc_by] + assert_equal true, h[:immediate_sweep] GC.stress = true assert_equal :force, GC.latest_gc_info[:major_by] @@ -162,6 +175,16 @@ def test_latest_gc_info_argument assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")} end + def test_stress_compile_send + assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "") + GC.stress = true + begin + eval("A::B.c(1, 1, d: 234)") + rescue + end + EOS + end + def test_singleton_method assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]") GC.stress = true @@ -224,12 +247,6 @@ def test_gc_parameter # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0 assert_in_out_err([env, "-e", "1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "") if use_rgengc? - # check obsolete - assert_in_out_err([{'RUBY_FREE_MIN' => '100'}, '-w', '-eexit'], '', [], - /RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead/) - assert_in_out_err([{'RUBY_HEAP_MIN_SLOTS' => '100'}, '-w', '-eexit'], '', [], - /RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead/) - env = { "RUBY_GC_MALLOC_LIMIT" => "60000000", "RUBY_GC_MALLOC_LIMIT_MAX" => "160000000", @@ -425,49 +442,43 @@ def test_vm_object end def test_exception_in_finalizer_procs - result = [] + assert_in_out_err(["-W0"], "#{<<~"begin;"}\n#{<<~'end;'}", %w[c1 c2]) c1 = proc do - result << :c1 + puts "c1" raise end c2 = proc do - result << :c2 + puts "c2" raise end - tap { - tap { + begin; + tap do obj = Object.new ObjectSpace.define_finalizer(obj, c1) ObjectSpace.define_finalizer(obj, c2) obj = nil - } - } - GC.start - skip "finalizers did not get run" if result.empty? - assert_equal([:c1, :c2], result) + end + end; end def test_exception_in_finalizer_method - @result = [] + assert_in_out_err(["-W0"], "#{<<~"begin;"}\n#{<<~'end;'}", %w[c1 c2]) def self.c1(x) - @result << :c1 + puts "c1" raise end def self.c2(x) - @result << :c2 + puts "c2" raise end - tap { - tap { + begin; + tap do obj = Object.new ObjectSpace.define_finalizer(obj, method(:c1)) ObjectSpace.define_finalizer(obj, method(:c2)) obj = nil - } - } - GC.start - skip "finalizers did not get run" if @result.empty? - assert_equal([:c1, :c2], @result) + end + end; end def test_object_ids_never_repeat @@ -477,4 +488,10 @@ def test_object_ids_never_repeat b = 1000.times.map { Object.new.object_id } assert_empty(a & b) end + + def test_ast_node_buffer + # https://github.com/ruby/ruby/pull/4416 + Module.new.class_eval( (["# shareable_constant_value: literal"] + + (0..100000).map {|i| "M#{ i } = {}" }).join("\n")) + end end diff --git a/ruby/test/ruby/test_gc_compact.rb b/ruby/test/ruby/test_gc_compact.rb index 75d9b01f2..42ad02853 100644 --- a/ruby/test/ruby/test_gc_compact.rb +++ b/ruby/test/ruby/test_gc_compact.rb @@ -1,8 +1,115 @@ # frozen_string_literal: true require 'test/unit' require 'fiddle' +require 'etc' + +if RUBY_PLATFORM =~ /s390x/ + warn "Currently, it is known that the compaction does not work well on s390x; contribution is welcome https://github.com/ruby/ruby/pull/5077" + return +end class TestGCCompact < Test::Unit::TestCase + module SupportsCompact + def setup + skip "autocompact not supported on this platform" unless supports_auto_compact? + super + end + + private + + def supports_auto_compact? + return true unless defined?(Etc::SC_PAGE_SIZE) + + begin + return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0 + rescue NotImplementedError + rescue ArgumentError + end + + true + end + end + + include SupportsCompact + + class AutoCompact < Test::Unit::TestCase + include SupportsCompact + + def test_enable_autocompact + before = GC.auto_compact + GC.auto_compact = true + assert GC.auto_compact + ensure + GC.auto_compact = before + end + + def test_disable_autocompact + before = GC.auto_compact + GC.auto_compact = false + refute GC.auto_compact + ensure + GC.auto_compact = before + end + + def test_major_compacts + before = GC.auto_compact + GC.auto_compact = true + compact = GC.stat :compact_count + GC.start + assert_operator GC.stat(:compact_count), :>, compact + ensure + GC.auto_compact = before + end + + def test_implicit_compaction_does_something + before = GC.auto_compact + list = [] + list2 = [] + + # Try to make some fragmentation + 500.times { + list << Object.new + Object.new + Object.new + } + count = GC.stat :compact_count + GC.auto_compact = true + n = 1_000_000 + n.times do + break if count < GC.stat(:compact_count) + list2 << Object.new + end and skip "implicit compaction didn't happen within #{n} objects" + compact_stats = GC.latest_compact_info + refute_predicate compact_stats[:considered], :empty? + refute_predicate compact_stats[:moved], :empty? + ensure + GC.auto_compact = before + end + end + + def os_page_size + return true unless defined?(Etc::SC_PAGE_SIZE) + end + + def setup + skip "autocompact not supported on this platform" unless supports_auto_compact? + super + end + + def test_gc_compact_stats + list = [] + + # Try to make some fragmentation + 500.times { + list << Object.new + Object.new + Object.new + } + compact_stats = GC.compact + refute_predicate compact_stats[:considered], :empty? + refute_predicate compact_stats[:moved], :empty? + end + def memory_location(obj) (Fiddle.dlwrap(obj) >> 1) end @@ -43,18 +150,20 @@ def test_complex_hash_keys assert_equal hash, list_of_objects.hash end - def walk_ast ast - children = ast.children.grep(RubyVM::AbstractSyntaxTree::Node) - children.each do |child| - assert child.type - walk_ast child - end - end - def test_ast_compacts - ast = RubyVM::AbstractSyntaxTree.parse_file __FILE__ - assert GC.compact - walk_ast ast + assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV) + begin; + def walk_ast ast + children = ast.children.grep(RubyVM::AbstractSyntaxTree::Node) + children.each do |child| + assert child.type + walk_ast child + end + end + ast = RubyVM::AbstractSyntaxTree.parse_file #{__FILE__.dump} + assert GC.compact + walk_ast ast + end; end def test_compact_count diff --git a/ruby/test/ruby/test_hash.rb b/ruby/test/ruby/test_hash.rb index 7832466ff..eaff09d43 100644 --- a/ruby/test/ruby/test_hash.rb +++ b/ruby/test/ruby/test_hash.rb @@ -86,7 +86,6 @@ def setup 'nil' => nil ] @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -114,16 +113,36 @@ def test_self_initialize_copy assert_equal(2, h[1]) end - def test_dup_will_rehash - set1 = @cls[] - set2 = @cls[set1 => true] + def test_dup_will_not_rehash + assert_hash_does_not_rehash(&:dup) + end - set1[set1] = true + def assert_hash_does_not_rehash + obj = Object.new + class << obj + attr_accessor :hash_calls + def hash + @hash_calls += 1 + super + end + end + obj.hash_calls = 0 + hash = {obj => 42} + assert_equal(1, obj.hash_calls) + yield hash + assert_equal(1, obj.hash_calls) + end - assert_equal set2, set2.dup + def test_select_reject_will_not_rehash + assert_hash_does_not_rehash do |hash| + hash.select { true } + end + assert_hash_does_not_rehash do |hash| + hash.reject { false } + end end - def test_s_AREF + def test_s_AREF_from_hash h = @cls["a" => 100, "b" => 200] assert_equal(100, h['a']) assert_equal(200, h['b']) @@ -134,11 +153,21 @@ def test_s_AREF assert_equal(200, h['b']) assert_nil(h['c']) + h = @cls[Hash.new(42)] + assert_nil(h['a']) + + h = @cls[Hash.new {42}] + assert_nil(h['a']) + end + + def test_s_AREF_from_list h = @cls["a", 100, "b", 200] assert_equal(100, h['a']) assert_equal(200, h['b']) assert_nil(h['c']) + end + def test_s_AREF_from_pairs h = @cls[[["a", 100], ["b", 200]]] assert_equal(100, h['a']) assert_equal(200, h['b']) @@ -266,10 +295,13 @@ def test_ASET # '[]=' end def test_AREF_fstring_key + # warmup ObjectSpace.count_objects + ObjectSpace.count_objects + h = {"abc" => 1} - before = GC.stat(:total_allocated_objects) + before = ObjectSpace.count_objects[:T_STRING] 5.times{ h["abc"] } - assert_equal before, GC.stat(:total_allocated_objects) + assert_equal before, ObjectSpace.count_objects[:T_STRING] end def test_ASET_fstring_key @@ -417,6 +449,15 @@ def test_delete_if true } assert_equal(base.size, n) + + h = base.dup + assert_raise(FrozenError) do + h.delete_if do + h.freeze + true + end + end + assert_equal(base.dup, h) end def test_keep_if @@ -424,6 +465,14 @@ def test_keep_if assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 }) h = @cls[1=>2,3=>4,5=>6] assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.keep_if do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_compact @@ -453,6 +502,7 @@ def test_dup_equality h1 = @cls[h => 1] assert_equal(h1, h1.dup) h[1] = 2 + h1.rehash assert_equal(h1, h1.dup) end @@ -699,6 +749,33 @@ def test_reject assert_not_send([h, :instance_variable_defined?, :@foo]) end + def test_reject_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + expected = {}.compare_by_identity + expected[str1] = 1 + expected[str2] = 2 + h2 = h.reject{|k,| k != 'str'} + assert_equal(expected, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.reject{true} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + h2 = h.reject{true} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.reject{|k,| k != 'str'} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + end + def test_reject! base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ] h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ] @@ -720,6 +797,15 @@ def test_reject! h = base.dup assert_equal(h3, h.reject! {|k,v| v }) assert_equal(h3, h) + + h = base.dup + assert_raise(FrozenError) do + h.reject! do + h.freeze + true + end + end + assert_equal(base.dup, h) end def test_replace @@ -875,7 +961,7 @@ def test_nil_to_h def test_to_s h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ] assert_equal(h.inspect, h.to_s) - $, = ":" + assert_deprecated_warning { $, = ":" } assert_equal(h.inspect, h.to_s) h = @cls[] assert_equal(h.inspect, h.to_s) @@ -944,7 +1030,7 @@ def test_rehash2 end def test_fetch2 - assert_equal(:bar, @h.fetch(0, :foo) { :bar }) + assert_equal(:bar, assert_warning(/block supersedes default value argument/) {@h.fetch(0, :foo) { :bar }}) end def test_default_proc @@ -983,6 +1069,19 @@ def h.default(k = nil) assert_equal("FOO", h.shift) end + def test_shift_for_empty_hash + # [ruby-dev:51159] + h = @cls[] + 100.times{|n| + while h.size < n + k = Random.rand 0..1<<30 + h[k] = 1 + end + 0 while h.shift + assert_equal({}, h) + } + end + def test_reject_bang2 assert_equal({1=>2}, @cls[1=>2,3=>4].reject! {|k, v| k + v == 7 }) assert_nil(@cls[1=>2,3=>4].reject! {|k, v| k == 5 }) @@ -1017,12 +1116,47 @@ def test_select assert_not_send([h, :instance_variable_defined?, :@foo]) end + def test_select_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + expected = {}.compare_by_identity + expected[str1] = 1 + expected[str2] = 2 + h2 = h.select{|k,| k == 'str'} + assert_equal(expected, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.select{false} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + h2 = h.select{false} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.select{|k,| k == 'str'} + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + end + def test_select! h = @cls[1=>2,3=>4,5=>6] assert_equal(h, h.select! {|k, v| k + v >= 7 }) assert_equal({3=>4,5=>6}, h) h = @cls[1=>2,3=>4,5=>6] assert_equal(nil, h.select!{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.select! do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_slice @@ -1033,6 +1167,65 @@ def test_slice assert_equal({}, {}.slice) end + def test_slice_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + sliced = h.slice(str1, str2) + expected = {}.compare_by_identity + expected[str1] = 1 + expected[str2] = 2 + assert_equal(expected, sliced) + assert_equal(true, sliced.compare_by_identity?) + sliced = h.slice + assert_equal({}.compare_by_identity, sliced) + assert_equal(true, sliced.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + sliced= h.slice + assert_equal({}.compare_by_identity, sliced) + assert_equal(true, sliced.compare_by_identity?) + sliced = h.slice(str1, str2) + assert_equal({}.compare_by_identity, sliced) + assert_equal(true, sliced.compare_by_identity?) + end + + def test_except + h = @cls[1=>2,3=>4,5=>6] + assert_equal({5=>6}, h.except(1, 3)) + assert_equal({1=>2,3=>4,5=>6}, h.except(7)) + assert_equal({1=>2,3=>4,5=>6}, h.except) + assert_equal({}, {}.except) + end + + def test_except_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + excepted = h.except(str1, str2) + assert_equal({1=>2,3=>4,5=>6}.compare_by_identity, excepted) + assert_equal(true, excepted.compare_by_identity?) + excepted = h.except + assert_equal(h, excepted) + assert_equal(true, excepted.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + excepted = h.except + assert_equal({}.compare_by_identity, excepted) + assert_equal(true, excepted.compare_by_identity?) + excepted = h.except(str1, str2) + assert_equal({}.compare_by_identity, excepted) + assert_equal(true, excepted.compare_by_identity?) + end + def test_filter assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].filter {|k, v| k + v >= 7 }) @@ -1067,6 +1260,14 @@ def test_filter! assert_equal({3=>4,5=>6}, h) h = @cls[1=>2,3=>4,5=>6] assert_equal(nil, h.filter!{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.filter! do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_clear2 @@ -1090,6 +1291,15 @@ def test_replace2 assert_raise(FrozenError) { h2.replace(42) } end + def test_replace_memory_leak + assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}") + h = ("aa".."zz").each_with_index.to_h + 10_000.times {h.dup} + begin; + 500_000.times {h.dup.replace(h)} + end; + end + def test_size2 assert_equal(0, @cls[].size) end @@ -1101,6 +1311,7 @@ def test_equal2 def o.to_hash; @cls[]; end def o.==(x); true; end assert_equal({}, o) + o.singleton_class.remove_method(:==) def o.==(x); false; end assert_not_equal({}, o) @@ -1117,6 +1328,7 @@ def test_eql def o.to_hash; @cls[]; end def o.eql?(x); true; end assert_send([@cls[], :eql?, o]) + o.singleton_class.remove_method(:eql?) def o.eql?(x); false; end assert_not_send([@cls[], :eql?, o]) end @@ -1157,6 +1369,20 @@ def test_update4 assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1) end + def test_update5 + h = @cls[a: 1, b: 2, c: 3] + assert_raise(FrozenError) do + h.update({a: 10, b: 20}){ |key, v1, v2| key == :b && h.freeze; v2 } + end + assert_equal(@cls[a: 10, b: 2, c: 3], h) + + h = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10] + assert_raise(FrozenError) do + h.update({a: 10, b: 20}){ |key, v1, v2| key == :b && h.freeze; v2 } + end + assert_equal(@cls[a: 10, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], h) + end + def test_merge h1 = @cls[1=>2, 3=>4] h2 = {1=>3, 5=>7} @@ -1168,6 +1394,48 @@ def test_merge assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3) {|k, v1, v2| k + v1 + v2 }) end + def test_merge_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + expected = h.dup + expected[7] = 8 + h2 = h.merge(7=>8) + assert_equal(expected, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.merge({}) + assert_equal(h, h2) + assert_equal(true, h2.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + h1 = @cls[7=>8] + h1.compare_by_identity + h2 = h.merge(7=>8) + assert_equal(h1, h2) + assert_equal(true, h2.compare_by_identity?) + h2 = h.merge({}) + assert_equal(h, h2) + assert_equal(true, h2.compare_by_identity?) + end + + def test_merge! + h = @cls[a: 1, b: 2, c: 3] + assert_raise(FrozenError) do + h.merge!({a: 10, b: 20}){ |key, v1, v2| key == :b && h.freeze; v2 } + end + assert_equal(@cls[a: 10, b: 2, c: 3], h) + + h = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10] + assert_raise(FrozenError) do + h.merge!({a: 10, b: 20}){ |key, v1, v2| key == :b && h.freeze; v2 } + end + assert_equal(@cls[a: 10, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], h) + end + def test_assoc assert_equal([3,4], @cls[1=>2, 3=>4, 5=>6].assoc(3)) assert_nil(@cls[1=>2, 3=>4, 5=>6].assoc(4)) @@ -1624,6 +1892,8 @@ def test_to_proc } assert_equal([10, 20, 30], [1, 2, 3].map(&h)) + + assert_equal(true, h.to_proc.lambda?) end def test_transform_keys @@ -1638,6 +1908,27 @@ def test_transform_keys y = x.transform_keys.with_index {|k, i| "#{k}.#{i}" } assert_equal(%w(a.0 b.1 c.2), y.keys) + + assert_equal({A: 1, B: 2, c: 3}, x.transform_keys({a: :A, b: :B, d: :D})) + assert_equal({A: 1, B: 2, "c" => 3}, x.transform_keys({a: :A, b: :B, d: :D}, &:to_s)) + end + + def test_transform_keys_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + h2 = h.transform_keys(&:itself) + assert_equal(Hash[h.to_a], h2) + assert_equal(false, h2.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + h2 = h.transform_keys(&:itself) + assert_equal({}, h2) + assert_equal(false, h2.compare_by_identity?) end def test_transform_keys_bang @@ -1657,30 +1948,79 @@ def test_transform_keys_bang x.transform_keys! {|k| -k } assert_equal([-1, :a, 1, :b], x.flatten) + x = @cls[a: 1, b: 2, c: 3] + x.transform_keys! { |k| k == :b && break } + assert_equal({false => 1, b: 2, c: 3}, x) + x = @cls[true => :a, false => :b] x.transform_keys! {|k| !k } assert_equal([false, :a, true, :b], x.flatten) + + x = @cls[a: 1, b: 2, c: 3] + x.transform_keys!({a: :A, b: :B, d: :D}) + assert_equal({A: 1, B: 2, c: 3}, x) + x = @cls[a: 1, b: 2, c: 3] + x.transform_keys!({a: :A, b: :B, d: :D}, &:to_s) + assert_equal({A: 1, B: 2, "c" => 3}, x) end def test_transform_values x = @cls[a: 1, b: 2, c: 3] + x.default = 42 y = x.transform_values {|v| v ** 2 } assert_equal([1, 4, 9], y.values_at(:a, :b, :c)) assert_not_same(x, y) + assert_nil(y.default) + + x.default_proc = proc {|h, k| k} + y = x.transform_values {|v| v ** 2 } + assert_nil(y.default_proc) + assert_nil(y.default) y = x.transform_values.with_index {|v, i| "#{v}.#{i}" } assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c)) end + def test_transform_values_on_identhash + h = @cls[1=>2,3=>4,5=>6] + h.compare_by_identity + str1 = +'str' + str2 = +'str' + h[str1] = 1 + h[str2] = 2 + h2 = h.transform_values(&:itself) + assert_equal(h, h2) + assert_equal(true, h2.compare_by_identity?) + + h = @cls[] + h.compare_by_identity + h2 = h.transform_values(&:itself) + assert_equal({}.compare_by_identity, h2) + assert_equal(true, h2.compare_by_identity?) + end + def test_transform_values_bang x = @cls[a: 1, b: 2, c: 3] y = x.transform_values! {|v| v ** 2 } assert_equal([1, 4, 9], y.values_at(:a, :b, :c)) assert_same(x, y) + x = @cls[a: 1, b: 2, c: 3] + x.transform_values! { |v| v == 2 && break } + assert_equal({a: false, b: 2, c: 3}, x) + x = @cls[a: 1, b: 2, c: 3] y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" } assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c)) + + x = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10] + assert_raise(FrozenError) do + x.transform_values!() do |v| + x.freeze if v == 2 + v.succ + end + end + assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x) end def test_broken_hash_value @@ -1730,9 +2070,6 @@ def test_huge_iter_level class TestSubHash < TestHash class SubHash < Hash - def reject(*) - super - end end def setup @@ -1822,4 +2159,36 @@ def obj2.hash h[obj2] = true assert_equal true, h[obj] end + + def test_bug_12706 + assert_raise(ArgumentError) do + {a: 1}.each(&->(k, v) {}) + end + end + + def test_any_hash_fixable + 20.times do + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + require "delegate" + typename = DelegateClass(String) + + hash = { + "Int" => true, + "Float" => true, + "String" => true, + "Boolean" => true, + "WidgetFilter" => true, + "WidgetAggregation" => true, + "WidgetEdge" => true, + "WidgetSortOrder" => true, + "WidgetGrouping" => true, + } + + hash.each_key do |key| + assert_send([hash, :key?, typename.new(key)]) + end + end; + end + end end diff --git a/ruby/test/ruby/test_inlinecache.rb b/ruby/test/ruby/test_inlinecache.rb new file mode 100644 index 000000000..6c2d86aef --- /dev/null +++ b/ruby/test/ruby/test_inlinecache.rb @@ -0,0 +1,110 @@ +# -*- coding: us-ascii -*- +# frozen_string_literal: true + +require 'test/unit' + +class TestMethod < Test::Unit::TestCase + def test_alias + m0 = Module.new do + def foo; :M0 end + end + m1 = Module.new do + include m0 + end + c = Class.new do + include m1 + alias bar foo + end + d = Class.new(c) do + end + + test = -> do + d.new.bar + end + + assert_equal :M0, test[] + + c.class_eval do + def bar + :C + end + end + + assert_equal :C, test[] + end + + def test_zsuper + assert_separately [], <<-EOS + class C + private def foo + :C + end + end + + class D < C + public :foo + end + + class E < D; end + class F < E; end + + test = -> do + F.new().foo + end + + assert_equal :C, test[] + + class E + def foo; :E; end + end + + assert_equal :E, test[] + EOS + end + + def test_module_methods_redefiniton + m0 = Module.new do + def foo + super + end + end + + c1 = Class.new do + def foo + :C1 + end + end + + c2 = Class.new do + def foo + :C2 + end + end + + d1 = Class.new(c1) do + include m0 + end + + d2 = Class.new(c2) do + include m0 + end + + assert_equal :C1, d1.new.foo + + m = Module.new do + def foo + super + end + end + + d1.class_eval do + include m + end + + d2.class_eval do + include m + end + + assert_equal :C2, d2.new.foo + end +end diff --git a/ruby/test/ruby/test_insns_leaf.rb b/ruby/test/ruby/test_insns_leaf.rb new file mode 100644 index 000000000..9c9a4324c --- /dev/null +++ b/ruby/test/ruby/test_insns_leaf.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: false +require 'test/unit' + +class TestInsnsLeaf < Test::Unit::TestCase + require "set" + + class Id + attr_reader :db_id + def initialize(db_id) + @db_id = db_id + end + + def ==(other) + other.class == self.class && other.db_id == db_id + end + alias_method :eql?, :== + + def hash + 10 + end + + def <=>(other) + db_id <=> other.db_id if other.is_a?(self.class) + end + end + + class Namespace + IDS = Set[ + Id.new(1).freeze, + Id.new(2).freeze, + Id.new(3).freeze, + Id.new(4).freeze, + ].freeze + + class << self + def test?(id) + IDS.include?(id) + end + end + end + + def test_insns_leaf + assert Namespace.test?(Id.new(1)), "IDS should include 1" + assert !Namespace.test?(Id.new(5)), "IDS should not include 5" + end +end diff --git a/ruby/test/ruby/test_integer.rb b/ruby/test/ruby/test_integer.rb index a11169877..a2b181c64 100644 --- a/ruby/test/ruby/test_integer.rb +++ b/ruby/test/ruby/test_integer.rb @@ -260,6 +260,7 @@ def test_chr assert_equal("a", "a".ord.chr) assert_raise(RangeError) { (-1).chr } assert_raise(RangeError) { 0x100.chr } + assert_raise_with_message(RangeError, "3000000000 out of char range") { 3_000_000_000.chr } end def test_upto @@ -298,6 +299,31 @@ def test_times end end + def test_times_bignum_redefine_plus_lt + assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}") + begin; + called = false + Integer.class_eval do + alias old_plus + + undef + + define_method(:+){|x| called = true; 1} + alias old_lt < + undef < + define_method(:<){|x| called = true} + end + big = 2**65 + big.times{break 0} + Integer.class_eval do + undef + + alias + old_plus + undef < + alias < old_lt + end + bug18377 = "[ruby-core:106361]" + assert_equal(false, called, bug18377) + end; + end + def assert_int_equal(expected, result, mesg = nil) assert_kind_of(Integer, result, mesg) assert_equal(expected, result, mesg) @@ -575,6 +601,8 @@ def test_digits assert_equal([0, 9, 8, 7, 6, 5, 4, 3, 2, 1], 1234567890.digits) assert_equal([90, 78, 56, 34, 12], 1234567890.digits(100)) assert_equal([10, 5, 6, 8, 0, 10, 8, 6, 1], 1234567890.digits(13)) + assert_equal((2 ** 1024).to_s(7).chars.map(&:to_i).reverse, (2 ** 1024).digits(7)) + assert_equal([0] * 100 + [1], (2 ** (128 * 100)).digits(2 ** 128)) end def test_digits_for_negative_numbers @@ -659,4 +687,21 @@ def o.coerce(x); [self, x]; end def o.fdiv(x); 1; end assert_equal(1.0, 1.fdiv(o)) end + + def test_try_convert + assert_equal(1, Integer.try_convert(1)) + assert_equal(1, Integer.try_convert(1.0)) + assert_nil Integer.try_convert("1") + o = Object.new + assert_nil Integer.try_convert(o) + def o.to_i; 1; end + assert_nil Integer.try_convert(o) + o = Object.new + def o.to_int; 1; end + assert_equal(1, Integer.try_convert(o)) + + o = Object.new + def o.to_int; Object.new; end + assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)} + end end diff --git a/ruby/test/ruby/test_io.rb b/ruby/test/ruby/test_io.rb index c66446d2e..4f54052d3 100644 --- a/ruby/test/ruby/test_io.rb +++ b/ruby/test/ruby/test_io.rb @@ -394,6 +394,24 @@ def test_each_byte_with_seek } end + def test_each_byte_closed + pipe(proc do |w| + w << "abc def" + w.close + end, proc do |r| + assert_raise(IOError) do + r.each_byte {|byte| r.close if byte == 32 } + end + end) + make_tempfile {|t| + File.open(t, 'rt') {|f| + assert_raise(IOError) do + f.each_byte {|c| f.close if c == 10} + end + } + } + end + def test_each_codepoint make_tempfile {|t| bug2959 = '[ruby-core:28650]' @@ -405,16 +423,21 @@ def test_each_codepoint } end - def test_codepoints + def test_each_codepoint_closed + pipe(proc do |w| + w.print("abc def") + w.close + end, proc do |r| + assert_raise(IOError) do + r.each_codepoint {|c| r.close if c == 32} + end + end) make_tempfile {|t| - bug2959 = '[ruby-core:28650]' - a = "" File.open(t, 'rt') {|f| - assert_warn(/deprecated/) { - f.codepoints {|c| a << c} - } + assert_raise(IOError) do + f.each_codepoint {|c| f.close if c == 10} + end } - assert_equal("foo\nbar\nbaz\n", a, bug2959) } end @@ -453,6 +476,18 @@ def test_copy_stream_append } end + def test_copy_stream_append_to_nonempty + with_srccontent("foobar") {|src, content| + preface = 'preface' + File.write('dst', preface) + File.open('dst', 'ab') do |dst| + ret = IO.copy_stream(src, dst) + assert_equal(content.bytesize, ret) + assert_equal(preface + content, File.read("dst")) + end + } + end + def test_copy_stream_smaller with_srccontent {|src, content| @@ -620,7 +655,7 @@ def test_copy_stream_file_to_pipe if have_nonblock? def test_copy_stream_no_busy_wait - skip "MJIT has busy wait on GC. This sometimes fails with --jit." if RubyVM::MJIT.enabled? + skip "MJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? skip "multiple threads already active" if Thread.list.size > 1 msg = 'r58534 [ruby-core:80969] [Backport #13533]' @@ -1459,6 +1494,13 @@ def test_readpartial_with_not_empty_buffer end) end + def test_readpartial_zero_size + File.open(IO::NULL) do |r| + assert_empty(r.readpartial(0, s = "01234567")) + assert_empty(s) + end + end + def test_readpartial_buffer_error with_pipe do |r, w| s = "" @@ -1504,6 +1546,13 @@ def test_read_with_not_empty_buffer end) end + def test_read_zero_size + File.open(IO::NULL) do |r| + assert_empty(r.read(0, s = "01234567")) + assert_empty(s) + end + end + def test_read_buffer_error with_pipe do |r, w| s = "" @@ -1541,6 +1590,13 @@ def test_read_nonblock_with_not_empty_buffer } end + def test_read_nonblock_zero_size + File.open(IO::NULL) do |r| + assert_empty(r.read_nonblock(0, s = "01234567")) + assert_empty(s) + end + end + def test_write_nonblock_simple_no_exceptions pipe(proc do |w| w.write_nonblock('1', exception: false) @@ -1575,7 +1631,7 @@ def test_read_nonblock_invalid_exception end if have_nonblock? def test_read_nonblock_no_exceptions - skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker. + skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker. with_pipe {|r, w| assert_equal :wait_readable, r.read_nonblock(4096, exception: false) w.puts "HI!" @@ -1822,8 +1878,7 @@ def test_each_char end) end - def test_lines - verbose, $VERBOSE = $VERBOSE, nil + def test_each_line pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1831,20 +1886,17 @@ def test_lines w.close end, proc do |r| e = nil - assert_warn(/deprecated/) { - e = r.lines + assert_warn('') { + e = r.each_line } assert_equal("foo\n", e.next) assert_equal("bar\n", e.next) assert_equal("baz\n", e.next) assert_raise(StopIteration) { e.next } end) - ensure - $VERBOSE = verbose end - def test_bytes - verbose, $VERBOSE = $VERBOSE, nil + def test_each_byte2 pipe(proc do |w| w.binmode w.puts "foo" @@ -1853,20 +1905,17 @@ def test_bytes w.close end, proc do |r| e = nil - assert_warn(/deprecated/) { - e = r.bytes + assert_warn('') { + e = r.each_byte } (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c| assert_equal(c.ord, e.next) end assert_raise(StopIteration) { e.next } end) - ensure - $VERBOSE = verbose end - def test_chars - verbose, $VERBOSE = $VERBOSE, nil + def test_each_char2 pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1874,16 +1923,14 @@ def test_chars w.close end, proc do |r| e = nil - assert_warn(/deprecated/) { - e = r.chars + assert_warn('') { + e = r.each_char } (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c| assert_equal(c, e.next) end assert_raise(StopIteration) { e.next } end) - ensure - $VERBOSE = verbose end def test_readbyte @@ -2232,7 +2279,7 @@ def test_autoclose def test_autoclose_true_closed_by_finalizer # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1465760 # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1469765 - skip 'this randomly fails with MJIT' if RubyVM::MJIT.enabled? + skip 'this randomly fails with MJIT' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? feature2250 = '[ruby-core:26222]' pre = 'ft2250' @@ -2284,26 +2331,14 @@ def test_open_redirect_keyword def o.to_open(**kw); kw; end assert_equal({:a=>1}, open(o, a: 1)) - w = /Using the last argument as keyword parameters is deprecated.*The called method `(to_)?open'/m - redefined = nil - w.singleton_class.define_method(:===) do |s| - match = super(s) - redefined = !$1 - match - end - - assert_warn(w) do - assert_equal({:a=>1}, open(o, {a: 1})) - end + assert_raise(ArgumentError) { open(o, {a: 1}) } class << o remove_method(:to_open) end def o.to_open(kw); kw; end assert_equal({:a=>1}, open(o, a: 1)) - unless redefined - assert_equal({:a=>1}, open(o, {a: 1})) - end + assert_equal({:a=>1}, open(o, {a: 1})) end def test_open_pipe @@ -2501,6 +2536,17 @@ def test_reopen_opt_encoding end end + def test_reopen_ivar + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + f = File.open(IO::NULL) + f.instance_variable_set(:@foo, 42) + f.reopen(STDIN) + f.instance_variable_defined?(:@foo) + f.instance_variable_get(:@foo) + end; + end + def test_foreach a = [] IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x } @@ -2580,11 +2626,13 @@ def test_print end def test_print_separators - EnvUtil.suppress_warning {$, = ':'} - $\ = "\n" + EnvUtil.suppress_warning { + $, = ':' + $\ = "\n" + } pipe(proc do |w| w.print('a') - w.print('a','b','c') + EnvUtil.suppress_warning {w.print('a','b','c')} w.close end, proc do |r| assert_equal("a\n", r.gets) @@ -2642,7 +2690,7 @@ def capture.write(str) end capture.clear - assert_warning(/[.#]write is outdated/) do + assert_deprecated_warning(/[.#]write is outdated/) do stdout, $stdout = $stdout, capture puts "hey" ensure @@ -2825,7 +2873,7 @@ def test_flush_in_finalizer1 def test_flush_in_finalizer2 bug3910 = '[ruby-dev:42341]' - Tempfile.open("bug3910") {|t| + Tempfile.create("bug3910") {|t| path = t.path t.close begin @@ -2844,7 +2892,6 @@ def test_flush_in_finalizer2 end } end - t.close! } end @@ -3138,11 +3185,8 @@ def test_s_write assert_equal("\00f", File.read(path)) assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8")) assert_equal("ff", File.read(path)) - assert_raise(TypeError) { - assert_warn(/The last argument is split into positional and keyword parameters/) do - File.write(path, "foo", Object.new => Object.new) - end - } + File.write(path, "foo", Object.new => Object.new) + assert_equal("foo", File.read(path)) end end @@ -3341,11 +3385,17 @@ def test_sysread_locktmp data = "a" * 100 with_pipe do |r,w| th = Thread.new {r.sysread(100, buf)} + Thread.pass until th.stop? - buf.replace("") - assert_empty(buf, bug6099) + + assert_equal 100, buf.bytesize + + msg = /can't modify string; temporarily locked/ + assert_raise_with_message(RuntimeError, msg) do + buf.replace("") + end + assert_predicate(th, :alive?) w.write(data) - Thread.pass while th.alive? th.join end assert_equal(data, buf, bug6099) @@ -3466,10 +3516,17 @@ def test_io_select_with_many_files tempfiles = [] (0..fd_setsize+1).map {|i| - tempfiles << Tempfile.open("test_io_select_with_many_files") + tempfiles << Tempfile.create("test_io_select_with_many_files") } - IO.select(tempfiles) + begin + IO.select(tempfiles) + ensure + tempfiles.each { |t| + t.close + File.unlink(t.path) + } + end }, bug8080, timeout: 100 end if defined?(Process::RLIMIT_NOFILE) @@ -3643,15 +3700,27 @@ def test_open_flag end def test_open_flag_binary + binary_enc = Encoding.find("BINARY") make_tempfile do |t| open(t.path, File::RDONLY, flags: File::BINARY) do |f| assert_equal true, f.binmode? + assert_equal binary_enc, f.external_encoding end open(t.path, 'r', flags: File::BINARY) do |f| assert_equal true, f.binmode? + assert_equal binary_enc, f.external_encoding end open(t.path, mode: 'r', flags: File::BINARY) do |f| assert_equal true, f.binmode? + assert_equal binary_enc, f.external_encoding + end + open(t.path, File::RDONLY|File::BINARY) do |f| + assert_equal true, f.binmode? + assert_equal binary_enc, f.external_encoding + end + open(t.path, File::RDONLY|File::BINARY, autoclose: true) do |f| + assert_equal true, f.binmode? + assert_equal binary_enc, f.external_encoding end end end if File::BINARY != 0 @@ -3700,7 +3769,7 @@ def test_race_closed_stream begin; bug13158 = '[ruby-core:79262] [Bug #13158]' closed = nil - q = Queue.new + q = Thread::Queue.new IO.pipe do |r, w| thread = Thread.new do begin @@ -3811,30 +3880,6 @@ def test_closed_stream_in_rescue end end; end - - def test_write_no_garbage - skip "multiple threads already active" if Thread.list.size > 1 - res = {} - ObjectSpace.count_objects(res) # creates strings on first call - [ 'foo'.b, '*' * 24 ].each do |buf| - with_pipe do |r, w| - GC.disable - begin - before = ObjectSpace.count_objects(res)[:T_STRING] - n = w.write(buf) - s = w.syswrite(buf) - after = ObjectSpace.count_objects(res)[:T_STRING] - ensure - GC.enable - end - assert_equal before, after, - "no strings left over after write [ruby-core:78898] [Bug #13085]: #{ before } strings before write -> #{ after } strings after write" - assert_not_predicate buf, :frozen?, 'no inadvertent freeze' - assert_equal buf.bytesize, n, 'IO#write wrote expected size' - assert_equal s, n, 'IO#syswrite wrote expected size' - end - end - end end def test_pread @@ -3914,21 +3959,22 @@ def test_recycled_fd_close end end - def test_select_leak + def test_select_memory_leak # avoid malloc arena explosion from glibc and jemalloc: env = { 'MALLOC_ARENA_MAX' => '1', 'MALLOC_ARENA_TEST' => '1', 'MALLOC_CONF' => 'narenas:1', } - assert_no_memory_leak([env], <<-"end;", <<-"end;", rss: true, timeout: 60) + assert_no_memory_leak([env], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", rss: true, timeout: 60) + begin; r, w = IO.pipe rset = [r] wset = [w] exc = StandardError.new(-"select used to leak on exception") exc.set_backtrace([]) Thread.new { IO.select(rset, wset, nil, 0) }.join - end; + else; th = Thread.new do Thread.handle_interrupt(StandardError => :on_blocking) do begin @@ -3953,4 +3999,34 @@ def test_external_encoding_index assert_raise(TypeError) {Marshal.dump(w)} } end + + def test_marshal_closed_io + bug18077 = '[ruby-core:104927] [Bug #18077]' + r, w = IO.pipe + r.close; w.close + assert_raise(TypeError, bug18077) {Marshal.dump(r)} + + class << r + undef_method :closed? + end + assert_raise(TypeError, bug18077) {Marshal.dump(r)} + end + + def test_stdout_to_closed_pipe + EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do + |in_p, out_p, err_p, pid| + out = out_p.gets + out_p.close + err = err_p.read + ensure + status = Process.wait2(pid)[1] + assert_equal("ok\n", out) + assert_empty(err) + assert_not_predicate(status, :success?) + if Signal.list["PIPE"] + assert_predicate(status, :signaled?) + assert_equal("PIPE", Signal.signame(status.termsig) || status.termsig) + end + end + end end diff --git a/ruby/test/ruby/test_io_buffer.rb b/ruby/test/ruby/test_io_buffer.rb new file mode 100644 index 000000000..7e3b467ed --- /dev/null +++ b/ruby/test/ruby/test_io_buffer.rb @@ -0,0 +1,330 @@ +# frozen_string_literal: false + +require 'tempfile' + +class TestIOBuffer < Test::Unit::TestCase + experimental = Warning[:experimental] + begin + Warning[:experimental] = false + IO::Buffer.new(0) + ensure + Warning[:experimental] = experimental + end + + def assert_negative(value) + assert(value < 0, "Expected #{value} to be negative!") + end + + def assert_positive(value) + assert(value > 0, "Expected #{value} to be positive!") + end + + def test_flags + assert_equal 1, IO::Buffer::EXTERNAL + assert_equal 2, IO::Buffer::INTERNAL + assert_equal 4, IO::Buffer::MAPPED + + assert_equal 32, IO::Buffer::LOCKED + assert_equal 64, IO::Buffer::PRIVATE + + assert_equal 128, IO::Buffer::READONLY + end + + def test_endian + assert_equal 4, IO::Buffer::LITTLE_ENDIAN + assert_equal 8, IO::Buffer::BIG_ENDIAN + assert_equal 8, IO::Buffer::NETWORK_ENDIAN + + assert_include [IO::Buffer::LITTLE_ENDIAN, IO::Buffer::BIG_ENDIAN], IO::Buffer::HOST_ENDIAN + end + + def test_default_size + assert_equal IO::Buffer::DEFAULT_SIZE, IO::Buffer.new.size + end + + def test_new_internal + buffer = IO::Buffer.new(1024, IO::Buffer::INTERNAL) + assert_equal 1024, buffer.size + refute buffer.external? + assert buffer.internal? + refute buffer.mapped? + end + + def test_new_mapped + buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED) + assert_equal 1024, buffer.size + refute buffer.external? + refute buffer.internal? + assert buffer.mapped? + end + + def test_new_readonly + buffer = IO::Buffer.new(128, IO::Buffer::INTERNAL|IO::Buffer::READONLY) + assert buffer.readonly? + + assert_raise IO::Buffer::AccessError do + buffer.set_string("") + end + + assert_raise IO::Buffer::AccessError do + buffer.set_string("!", 1) + end + end + + def test_file_mapped + buffer = File.open(__FILE__) {|file| IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)} + contents = buffer.get_string + + assert_include contents, "Hello World" + assert_equal Encoding::BINARY, contents.encoding + end + + def test_file_mapped_invalid + assert_raise NoMethodError do + IO::Buffer.map("foobar") + end + end + + def test_string_mapped + string = "Hello World" + buffer = IO::Buffer.for(string) + refute buffer.readonly? + + # Cannot modify string as it's locked by the buffer: + assert_raise RuntimeError do + string[0] = "h" + end + + buffer.set_value(:U8, 0, "h".ord) + + # Buffer releases it's ownership of the string: + buffer.free + + assert_equal "hello World", string + string[0] = "H" + assert_equal "Hello World", string + end + + def test_string_mapped_frozen + string = "Hello World".freeze + buffer = IO::Buffer.for(string) + + assert buffer.readonly? + end + + def test_non_string + not_string = Object.new + + assert_raise TypeError do + IO::Buffer.for(not_string) + end + end + + def test_resize_mapped + buffer = IO::Buffer.new + + buffer.resize(2048) + assert_equal 2048, buffer.size + + buffer.resize(4096) + assert_equal 4096, buffer.size + end + + def test_resize_preserve + message = "Hello World" + buffer = IO::Buffer.new(1024) + buffer.set_string(message) + buffer.resize(2048) + assert_equal message, buffer.get_string(0, message.bytesize) + end + + def test_compare_same_size + buffer1 = IO::Buffer.new(1) + assert_equal buffer1, buffer1 + + buffer2 = IO::Buffer.new(1) + buffer1.set_value(:U8, 0, 0x10) + buffer2.set_value(:U8, 0, 0x20) + + assert_negative buffer1 <=> buffer2 + assert_positive buffer2 <=> buffer1 + end + + def test_compare_different_size + buffer1 = IO::Buffer.new(3) + buffer2 = IO::Buffer.new(5) + + assert_negative buffer1 <=> buffer2 + assert_positive buffer2 <=> buffer1 + end + + def test_slice + buffer = IO::Buffer.new(128) + slice = buffer.slice(8, 32) + slice.set_string("Hello World") + assert_equal("Hello World", buffer.get_string(8, 11)) + end + + def test_slice_bounds + buffer = IO::Buffer.new(128) + + assert_raise ArgumentError do + buffer.slice(128, 10) + end + + # assert_raise RuntimeError do + # pp buffer.slice(-10, 10) + # end + end + + def test_locked + buffer = IO::Buffer.new(128, IO::Buffer::INTERNAL|IO::Buffer::LOCKED) + + assert_raise IO::Buffer::LockedError do + buffer.resize(256) + end + + assert_equal 128, buffer.size + + assert_raise IO::Buffer::LockedError do + buffer.free + end + + assert_equal 128, buffer.size + end + + def test_get_string + message = "Hello World 🤓" + + buffer = IO::Buffer.new(128) + buffer.set_string(message) + + chunk = buffer.get_string(0, message.bytesize, Encoding::UTF_8) + assert_equal message, chunk + assert_equal Encoding::UTF_8, chunk.encoding + + chunk = buffer.get_string(0, message.bytesize, Encoding::BINARY) + assert_equal Encoding::BINARY, chunk.encoding + end + + # We check that values are correctly round tripped. + RANGES = { + :U8 => [0, 2**8-1], + :S8 => [-2**7, 0, 2**7-1], + + :U16 => [0, 2**16-1], + :S16 => [-2**15, 0, 2**15-1], + :u16 => [0, 2**16-1], + :s16 => [-2**15, 0, 2**15-1], + + :U32 => [0, 2**32-1], + :S32 => [-2**31, 0, 2**31-1], + :u32 => [0, 2**32-1], + :s32 => [-2**31, 0, 2**31-1], + + :U64 => [0, 2**64-1], + :S64 => [-2**63, 0, 2**63-1], + :u64 => [0, 2**64-1], + :s64 => [-2**63, 0, 2**63-1], + + :F32 => [-1.0, 0.0, 0.5, 1.0, 128.0], + :F64 => [-1.0, 0.0, 0.5, 1.0, 128.0], + } + + def test_get_set_primitives + buffer = IO::Buffer.new(128) + + RANGES.each do |type, values| + values.each do |value| + buffer.set_value(type, 0, value) + assert_equal value, buffer.get_value(type, 0), "Converting #{value} as #{type}." + end + end + end + + def test_clear + buffer = IO::Buffer.new(16) + buffer.set_string("Hello World!") + end + + def test_invalidation + input, output = IO.pipe + + # (1) rb_write_internal creates IO::Buffer object, + buffer = IO::Buffer.new(128) + + # (2) it is passed to (malicious) scheduler + # (3) scheduler starts a thread which call system call with the buffer object + thread = Thread.new{buffer.locked{input.read}} + + Thread.pass until thread.stop? + + # (4) scheduler returns + # (5) rb_write_internal invalidate the buffer object + assert_raise IO::Buffer::LockedError do + buffer.free + end + + # (6) the system call access the memory area after invalidation + output.write("Hello World") + output.close + thread.join + + input.close + end + + def test_read + io = Tempfile.new + io.write("Hello World") + io.seek(0) + + buffer = IO::Buffer.new(128) + buffer.read(io, 5) + + assert_equal "Hello", buffer.get_string(0, 5) + ensure + io.close! + end + + def test_write + io = Tempfile.new + + buffer = IO::Buffer.new(128) + buffer.set_string("Hello") + buffer.write(io, 5) + + io.seek(0) + assert_equal "Hello", io.read(5) + ensure + io.close! + end + + def test_pread + io = Tempfile.new + io.write("Hello World") + io.seek(0) + + buffer = IO::Buffer.new(128) + buffer.pread(io, 5, 6) + + assert_equal "World", buffer.get_string(0, 5) + assert_equal 0, io.tell + ensure + io.close! + end + + def test_pwrite + io = Tempfile.new + + buffer = IO::Buffer.new(128) + buffer.set_string("World") + buffer.pwrite(io, 5, 6) + + assert_equal 0, io.tell + + io.seek(6) + assert_equal "World", io.read(5) + ensure + io.close! + end +end diff --git a/ruby/test/ruby/test_io_m17n.rb b/ruby/test/ruby/test_io_m17n.rb index e5b0ef058..27b16a2a3 100644 --- a/ruby/test/ruby/test_io_m17n.rb +++ b/ruby/test/ruby/test_io_m17n.rb @@ -776,10 +776,10 @@ def test_pipe assert_equal(eucjp, r.read) end) - assert_raise_with_message(ArgumentError, /invalid name encoding/) do + assert_raise_with_message(ArgumentError, /invalid encoding name/) do with_pipe("UTF-8", "UTF-8".encode("UTF-32BE")) {} end - assert_raise_with_message(ArgumentError, /invalid name encoding/) do + assert_raise_with_message(ArgumentError, /invalid encoding name/) do with_pipe("UTF-8".encode("UTF-32BE")) {} end @@ -2047,19 +2047,19 @@ def test_w_xml_attr with_tmpdir { open("raw.txt", "wb", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("raw.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content) open("ascii.txt", "wb:us-ascii", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("ascii.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'丂あ\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'丂あ\n\"".force_encoding("ascii-8bit"), content) open("iso-2022-jp.txt", "wb:iso-2022-jp", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("iso-2022-jp.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'丂\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'丂\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content) open("utf-16be.txt", "wb:utf-16be", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("utf-16be.txt", :mode=>"rb:ascii-8bit") - assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0'\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content) + assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0&\0a\0p\0o\0s\0;\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content) open("eucjp.txt", "w:euc-jp:utf-8", xml: :attr) {|f| f.print "\u4E02" # U+4E02 is 0x3021 in JIS X 0212 diff --git a/ruby/test/ruby/test_iseq.rb b/ruby/test/ruby/test_iseq.rb index 7c384c19b..f01d36cc5 100644 --- a/ruby/test/ruby/test_iseq.rb +++ b/ruby/test/ruby/test_iseq.rb @@ -10,13 +10,16 @@ def test_no_linenum end def compile(src, line = nil, opt = nil) + unless line + line = caller_locations(1).first.lineno + end EnvUtil.suppress_warning do ISeq.new(src, __FILE__, __FILE__, line, opt) end end - def lines src - body = compile(src).to_a[13] + def lines src, lines = nil + body = compile(src, lines).to_a[13] body.find_all{|e| e.kind_of? Integer} end @@ -25,24 +28,22 @@ def test_allocate end def test_to_a_lines - src = <<-EOS + assert_equal [__LINE__+1, __LINE__+2, __LINE__+4], lines(<<-EOS, __LINE__+1) p __LINE__ # 1 p __LINE__ # 2 # 3 p __LINE__ # 4 EOS - assert_equal [1, 2, 4], lines(src) - src = <<-EOS + assert_equal [__LINE__+2, __LINE__+4], lines(<<-EOS, __LINE__+1) # 1 p __LINE__ # 2 # 3 p __LINE__ # 4 # 5 EOS - assert_equal [2, 4], lines(src) - src = <<-EOS + assert_equal [__LINE__+3, __LINE__+4, __LINE__+7, __LINE__+9], lines(<<~EOS, __LINE__+1) 1 # should be optimized out 2 # should be optimized out p __LINE__ # 3 @@ -53,10 +54,9 @@ def test_to_a_lines 8 # should be optimized out 9 EOS - assert_equal [3, 4, 7, 9], lines(src) end - def test_unsupport_type + def test_unsupported_type ary = compile("p").to_a ary[9] = :foobar assert_raise_with_message(TypeError, /:foobar/) {ISeq.load(ary)} @@ -82,6 +82,91 @@ def bug(kw) end; end if defined?(RubyVM::InstructionSequence.load) + def test_cdhash_after_roundtrip + # CDHASH was not built properly when loading from binary and + # was causing opt_case_dispatch to clobber its stack canary + # for its "leaf" instruction attribute. + iseq = compile(<<~EOF, __LINE__+1) + case Class.new(String).new("foo") + when "foo" + 42 + end + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_super_with_block + iseq = compile(<<~EOF, __LINE__+1) + def (Object.new).touch(*) # :nodoc: + foo { super } + end + 42 + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_super_with_block_hash_0 + iseq = compile(<<~EOF, __LINE__+1) + # [Bug #18250] `req` specifically cause `Assertion failed: (key != 0), function hash_table_raw_insert` + def (Object.new).touch(req, *) + foo { super } + end + 42 + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_super_with_block_and_kwrest + iseq = compile(<<~EOF, __LINE__+1) + def (Object.new).touch(**) # :nodoc: + foo { super } + end + 42 + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_lambda_with_ractor_roundtrip + iseq = compile(<<~EOF, __LINE__+1) + x = 42 + y = nil.instance_eval{ lambda { x } } + Ractor.make_shareable(y) + y.call + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_super_with_anonymous_block + iseq = compile(<<~EOF, __LINE__+1) + def (Object.new).touch(&) # :nodoc: + foo { super } + end + 42 + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + + def test_ractor_unshareable_outer_variable + name = "\u{2603 26a1}" + y = nil.instance_eval do + eval("proc {#{name} = nil; proc {|x| #{name} = x}}").call + end + assert_raise_with_message(ArgumentError, /\(#{name}\)/) do + Ractor.make_shareable(y) + end + y = nil.instance_eval do + eval("proc {#{name} = []; proc {|x| #{name}}}").call + end + assert_raise_with_message(Ractor::IsolationError, /`#{name}'/) do + Ractor.make_shareable(y) + end + obj = Object.new + def obj.foo(*) nil.instance_eval{ ->{super} } end + assert_raise_with_message(Ractor::IsolationError, /hidden variable/) do + Ractor.make_shareable(obj.foo) + end + end + def test_disasm_encoding src = "\u{3042} = 1; \u{3042}; \u{3043}" asm = compile(src).disasm @@ -98,6 +183,22 @@ def test_disasm_encoding assert_include(RubyVM::InstructionSequence.of(obj.method(name)).disasm, name) end + def test_compile_file_encoding + Tempfile.create(%w"test_iseq .rb") do |f| + f.puts "{ '\u00de' => 'Th', '\u00df' => 'ss', '\u00e0' => 'a' }" + f.close + + EnvUtil.with_default_external(Encoding::US_ASCII) do + assert_warn('') { + load f.path + } + assert_nothing_raised(SyntaxError) { + RubyVM::InstructionSequence.compile_file(f.path) + } + end + end + end + LINE_BEFORE_METHOD = __LINE__ def method_test_line_trace @@ -108,16 +209,16 @@ def method_test_line_trace end def test_line_trace - iseq = compile \ - %q{ a = 1 + iseq = compile(<<~EOF, __LINE__+1) + a = 1 b = 2 c = 3 # d = 4 e = 5 # f = 6 g = 7 + EOF - } assert_equal([1, 2, 3, 5, 7], iseq.line_trace_all) iseq.line_trace_specify(1, true) # line 2 iseq.line_trace_specify(3, true) # line 5 @@ -187,8 +288,8 @@ def test_frozen_string_literal_compile_option s1, s2, s3, s4 = compile(code, line, {frozen_string_literal: true}).eval assert_predicate(s1, :frozen?) assert_predicate(s2, :frozen?) - assert_predicate(s3, :frozen?) - assert_predicate(s4, :frozen?) + assert_not_predicate(s3, :frozen?) + assert_not_predicate(s4, :frozen?) end # Safe call chain is not optimized when Coverage is running. @@ -289,6 +390,22 @@ def test_inspect end end + def anon_star(*); end + + def test_anon_param_in_disasm + iseq = RubyVM::InstructionSequence.of(method(:anon_star)) + param_names = iseq.to_a[iseq.to_a.index(:method) + 1] + assert_equal [2], param_names + end + + def anon_block(&); end + + def test_anon_block_param_in_disasm + iseq = RubyVM::InstructionSequence.of(method(:anon_block)) + param_names = iseq.to_a[iseq.to_a.index(:method) + 1] + assert_equal [:&], param_names + end + def strip_lineno(source) source.gsub(/^.*?: /, "") end @@ -425,6 +542,11 @@ def assert_iseq_to_binary(code, mesg = nil) a1 = iseq.to_a a2 = iseq2.to_a assert_equal(a1, a2, message(mesg) {diff iseq.disassemble, iseq2.disassemble}) + if iseq2.script_lines + assert_kind_of(Array, iseq2.script_lines) + else + assert_nil(iseq2.script_lines) + end iseq2 end @@ -465,6 +587,11 @@ def q; end attr_reader :i end end; + + # cleanup + ::Object.class_eval do + remove_const :P + end end def collect_from_binary_tracepoint_lines(tracepoint_type, filename) @@ -561,9 +688,58 @@ def test_iseq_of_twice_for_same_code end def test_iseq_builtin_to_a - insns = RubyVM::InstructionSequence.of([].method(:pack)).to_a.last - invokebuiltin = insns.find { |insn| insn.is_a?(Array) && insn[0] == :opt_invokebuiltin_delegate_leave } + invokebuiltin = eval(EnvUtil.invoke_ruby(['-e', <<~EOS], '', true).first) + insns = RubyVM::InstructionSequence.of([].method(:pack)).to_a.last + p insns.find { |insn| insn.is_a?(Array) && insn[0] == :opt_invokebuiltin_delegate_leave } + EOS assert_not_nil(invokebuiltin) assert_equal([:func_ptr, :argc, :index, :name], invokebuiltin[1].keys) end + + def test_iseq_builtin_load + Tempfile.create(["builtin", ".iseq"]) do |f| + f.binmode + f.write(RubyVM::InstructionSequence.of(1.method(:abs)).to_binary) + f.close + assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + bin = File.binread(ARGV[0]) + assert_raise(ArgumentError) do + RubyVM::InstructionSequence.load_from_binary(bin) + end + end; + end + end + + def test_iseq_option_debug_level + assert_raise(TypeError) {ISeq.compile("", debug_level: "")} + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + RubyVM::InstructionSequence.compile("", debug_level: 5) + end; + end + + def test_mandatory_only + assert_separately [], <<~RUBY + at0 = Time.at(0) + assert_equal at0, Time.public_send(:at, 0, 0) + RUBY + end + + def test_mandatory_only_redef + assert_separately ['-W0'], <<~RUBY + r = Ractor.new{ + Float(10) + module Kernel + undef Float + def Float(n) + :new + end + end + GC.start + Float(30) + } + assert_equal :new, r.take + RUBY + end end diff --git a/ruby/test/ruby/test_iterator.rb b/ruby/test/ruby/test_iterator.rb index 54c095338..820d5591c 100644 --- a/ruby/test/ruby/test_iterator.rb +++ b/ruby/test/ruby/test_iterator.rb @@ -339,8 +339,7 @@ def test_marity marity_test(:marity_test) marity_test(:p) - lambda(&method(:assert)).call(true) - lambda(&get_block{|a,n| assert(a,n)}).call(true, "marity") + get_block{|a,n| assert(a,n)}.call(true, "marity") end def foo diff --git a/ruby/test/ruby/test_jit.rb b/ruby/test/ruby/test_jit.rb index e3d8f9cee..07ac76210 100644 --- a/ruby/test/ruby/test_jit.rb +++ b/ruby/test/ruby/test_jit.rb @@ -10,10 +10,12 @@ class TestJIT < Test::Unit::TestCase IGNORABLE_PATTERNS = [ /\AJIT recompile: .+\n\z/, /\AJIT inline: .+\n\z/, + /\AJIT cancel: .+\n\z/, /\ASuccessful MJIT finish\n\z/, ] MAX_CACHE_PATTERNS = [ /\AJIT compaction \([^)]+\): .+\n\z/, + /\AToo many JIT code, but skipped unloading units for JIT compaction\n\z/, /\ANo units can be unloaded -- .+\n\z/, ] @@ -21,7 +23,6 @@ class TestJIT < Test::Unit::TestCase TEST_PENDING_INSNS = RubyVM::INSTRUCTION_NAMES.select { |n| n.start_with?('trace_') }.map(&:to_sym) + [ # not supported yet :defineclass, - :opt_call_c_function, # to be tested :invokebuiltin, @@ -38,22 +39,36 @@ def self.untested_insns @untested_insns ||= (RubyVM::INSTRUCTION_NAMES.map(&:to_sym) - TEST_PENDING_INSNS) end - def setup - unless JITSupport.supported? - skip 'JIT seems not supported on this platform' + def self.setup + return if defined?(@setup_hooked) + @setup_hooked = true + + # ci.rvm.jp caches its build environment. Clean up temporary files left by SEGV. + if ENV['RUBY_DEBUG']&.include?('ci') + Dir.glob("#{ENV.fetch('TMPDIR', '/tmp')}/_ruby_mjit_p*u*.*").each do |file| + puts "test/ruby/test_jit.rb: removing #{file}" + File.unlink(file) + end end # ruby -w -Itest/lib test/ruby/test_jit.rb - if $VERBOSE && !defined?(@@at_exit_hooked) + if $VERBOSE + pid = $$ at_exit do - unless TestJIT.untested_insns.empty? + if pid == $$ && !TestJIT.untested_insns.empty? warn "you may want to add tests for following insns, when you have a chance: #{TestJIT.untested_insns.join(' ')}" end end - @@at_exit_hooked = true end end + def setup + unless JITSupport.supported? + skip 'JIT seems not supported on this platform' + end + self.class.setup + end + def test_compile_insn_nop assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop]) end @@ -228,16 +243,8 @@ def a end; end - def test_compile_insn_putstring_concatstrings_tostring - assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring]) - end - - def test_compile_insn_freezestring - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring]) - begin; - # frozen_string_literal: true - print proc { "#{true}".frozen? }.call - end; + def test_compile_insn_putstring_concatstrings_objtostring + assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings objtostring]) end def test_compile_insn_toregexp @@ -313,10 +320,6 @@ def test_compile_insn_swap_topn assert_compile_once('{}["true"] = true', result_inspect: 'true', insns: %i[swap topn]) end - def test_compile_insn_reverse - assert_compile_once('q, (w, e), r = 1, [2, 3], 4; [q, w, e, r]', result_inspect: '[1, 2, 3, 4]', insns: %i[reverse]) - end - def test_compile_insn_reput skip "write test" end @@ -357,7 +360,7 @@ def test_compile_insn_defineclass end def test_compile_insn_send - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send]) + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send]) begin; print proc { yield_self { 1 } }.call end; @@ -479,8 +482,8 @@ def test_compile_insn_branchnil end; end - def test_compile_insn_checktype - assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype]) + def test_compile_insn_objtostring + assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[objtostring]) begin; a = '2' "4#{a}" @@ -496,7 +499,7 @@ def test_compile_insn_once end def test_compile_insn_checkmatch_opt_case_dispatch - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch opt_case_dispatch]) + assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch]) begin; case 'hello' when 'hello' @@ -597,16 +600,26 @@ def test_compile_insn_opt_regexpmatch2 assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2]) end - def test_compile_insn_opt_call_c_function - skip "support this in opt_call_c_function (low priority)" - end - def test_compile_insn_opt_invokebuiltin_delegate_leave - insns = collect_insns(RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a) + iseq = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first) + p RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a + EOS + insns = collect_insns(iseq) mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns) assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1) end + def test_compile_insn_checkmatch + assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch]) + begin; + ary = %w(hello good-bye) + case 'hello' + when *ary + 'world' + end + end; + end + def test_jit_output out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5) assert_equal("MJIT\n" * 5, out) @@ -680,30 +693,40 @@ def mjit#{i} debug_info = %Q[stdout:\n"""\n#{out}\n"""\n\nstderr:\n"""\n#{err}"""\n] assert_equal('012345678910', out, debug_info) compactions, errs = err.lines.partition do |l| - l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods ->/) + l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods /) end 10.times do |i| assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit#{i}@\(eval\):/, errs[i], debug_info) end - assert_equal("Too many JIT code -- 1 units unloaded\n", errs[10], debug_info) - assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info) + assert_equal("No units can be unloaded -- incremented max-cache-size to 11 for --jit-wait\n", errs[10], debug_info) + assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info) # On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache, # it should trigger compaction. unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet - assert_equal(3, compactions.size, debug_info) + assert_equal(1, compactions.size, debug_info) end if RUBY_PLATFORM.match?(/mswin/) # "Permission Denied" error is preventing to remove so file on AppVeyor/RubyCI. skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.' else - # verify .o files are deleted on unload_units + # verify .c files are deleted on unload_units assert_send([Dir, :empty?, dir], debug_info) end end end + def test_newarraykwsplat_on_stack + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "[nil, [{:type=>:development}]]\n", success_count: 1, insns: %i[newarraykwsplat]) + begin; + def arr + [nil, [:type => :development]] + end + p arr + end; + end + def test_local_stack_on_exception assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2) begin; @@ -763,6 +786,57 @@ def wrapper(paths, prefixes) end; end + def test_inlined_builtin_methods + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 1, min_calls: 2) + begin; + def test + float = 0.0 + float.abs + float.-@ + float.zero? + end + test + test + end; + end + + def test_inlined_c_method + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2) + begin; + def test(obj, recursive: nil) + if recursive + test(recursive) + end + obj.to_s + end + + print(test('a')) # set #to_s cc to String#to_s (expecting C method) + print(test('a')) # JIT with #to_s cc: String#to_s + # update #to_s cd->cc to Symbol#to_s, then go through the Symbol#to_s cd->cc + # after checking receiver class using inlined #to_s cc with String#to_s. + print(test('a', recursive: :foo)) + end; + end + + def test_inlined_exivar + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2) + begin; + class Foo < Hash + def initialize + @a = :a + end + + def bar + @a + end + end + + print(Foo.new.bar) + print(Foo.new.bar) # compile #initialize, #bar -> recompile #bar + print(Foo.new.bar) # compile #bar with exivar + end; + end + def test_inlined_undefined_ivar assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3) begin; @@ -778,11 +852,9 @@ def bar end end - verbose, $VERBOSE = $VERBOSE, false # suppress "instance variable @b not initialized" print(Foo.new.bar) print(Foo.new.bar) print(Foo.new.bar) - $VERBOSE = verbose end; end @@ -808,6 +880,18 @@ def a end; end + def test_inlined_getconstant + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, min_calls: 2) + begin; + FOO = 1 + def const + FOO + end + print const + print const + end; + end + def test_attr_reader assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2) begin; @@ -872,6 +956,34 @@ def test(recv) end; end + def test_heap_promotion_of_ivar_in_the_middle_of_jit + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2) + begin; + class A + def initialize + @iv0 = nil + @iv1 = [] + @iv2 = nil + end + + def test(add) + @iv0.nil? + @iv2.nil? + add_ivar if add + @iv1.empty? + end + + def add_ivar + @iv3 = nil + end + end + + a = A.new + p a.test(false) + p a.test(true) + end; + end + def test_jump_to_precompiled_branch assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1) begin; @@ -935,7 +1047,7 @@ def test_stack_pointer_with_assignment def test_frame_omitted_inlining assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2) begin; - class Numeric + class Integer remove_method :zero? def zero? self == 0 @@ -961,6 +1073,10 @@ def multiply(a, b) end; end + def test_builtin_frame_omitted_inlining + assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2) + end + def test_program_counter_with_regexpmatch assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1) begin; @@ -989,6 +1105,30 @@ def test_pushed_values_with_opt_aref_with end; end + def test_mjit_pause_wait + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, min_calls: 1) + begin; + RubyVM::MJIT.pause + proc {}.call + end; + end + + def test_not_cancel_by_tracepoint_class + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, min_calls: 2) + begin; + TracePoint.new(:class) {}.enable + 2.times {} + end; + end + + def test_cancel_by_tracepoint + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, min_calls: 2) + begin; + TracePoint.new(:line) {}.enable + 2.times {} + end; + end + def test_caller_locations_without_catch_table out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1) begin; @@ -1050,12 +1190,13 @@ def assert_compile_once(script, result_inspect:, insns: [], uplevel: 1) end # Shorthand for normal test cases - def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: []) + def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: []) out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache) - actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size - # Add --jit-verbose=2 logs for cl.exe because compiler's error message is suppressed - # for cl.exe with --jit-verbose=1. See `start_process` in mjit_worker.c. - if RUBY_PLATFORM.match?(/mswin/) && success_count != actual + success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size + recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size + # Add --mjit-verbose=2 logs for cl.exe because compiler's error message is suppressed + # for cl.exe with --mjit-verbose=1. See `start_process` in mjit_worker.c. + if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache) end @@ -1065,13 +1206,19 @@ def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 1, max_ mark_tested_insn(insn, used_insns: used_insns, uplevel: uplevel + 3) end + suffix = "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{( + "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2 + )}" assert_equal( - success_count, actual, - "Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\ - "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{( - "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2 - )}", + success_count, success_actual, + "Expected #{success_count} times of JIT success, but succeeded #{success_actual} times.\n\n#{suffix}", ) + if recompile_count + assert_equal( + recompile_count, recompile_actual, + "Expected #{success_count} times of JIT recompile, but recompiled #{success_actual} times.\n\n#{suffix}", + ) + end if stdout assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}") end @@ -1084,7 +1231,9 @@ def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 1, max_ end def mark_tested_insn(insn, used_insns:, uplevel: 1) - unless used_insns.include?(insn) + # Currently, this check emits a false-positive warning against opt_regexpmatch2, + # so the insn is excluded explicitly. See https://bugs.ruby-lang.org/issues/18269 + if !used_insns.include?(insn) && insn != :opt_regexpmatch2 $stderr.puts warn "'#{insn}' insn is not included in the script. Actual insns are: #{used_insns.join(' ')}\n", uplevel: uplevel end diff --git a/ruby/test/ruby/test_jit_debug.rb b/ruby/test/ruby/test_jit_debug.rb new file mode 100644 index 000000000..b8dc9416e --- /dev/null +++ b/ruby/test/ruby/test_jit_debug.rb @@ -0,0 +1,17 @@ +require_relative 'test_jit' + +return unless defined?(TestJIT) +return if ENV.key?('APPVEYOR') +return if ENV.key?('RUBYCI_NICKNAME') +return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp +return if /mswin/ =~ RUBY_PLATFORM + +class TestJITDebug < TestJIT + @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker? + + def setup + super + # let `#eval_with_jit` use --mjit-debug + @mjit_debug = true + end +end diff --git a/ruby/test/ruby/test_keyword.rb b/ruby/test/ruby/test_keyword.rb index a0459553a..9094259bc 100644 --- a/ruby/test/ruby/test_keyword.rb +++ b/ruby/test/ruby/test_keyword.rb @@ -24,9 +24,7 @@ def f2(x, str: "foo", num: 424242) def test_f2 assert_equal([:xyz, "foo", 424242], f2(:xyz)) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `f2'/m) do - assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42)) - end + assert_raise(ArgumentError) { f2("bar"=>42) } end @@ -192,6 +190,218 @@ def test_lambda assert_equal(["bar", 111111], f[str: "bar", num: 111111]) end + def test_keyword_splat_new + kw = {} + h = {a: 1} + + def self.assert_equal_not_same(kw, res) + assert_instance_of(Hash, res) + assert_equal(kw, res) + assert_not_same(kw, res) + end + + def self.y(**kw) kw end + m = method(:y) + assert_equal(false, y(**{}).frozen?) + assert_equal_not_same(kw, y(**kw)) + assert_equal_not_same(h, y(**h)) + assert_equal(false, send(:y, **{}).frozen?) + assert_equal_not_same(kw, send(:y, **kw)) + assert_equal_not_same(h, send(:y, **h)) + assert_equal(false, public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, public_send(:y, **kw)) + assert_equal_not_same(h, public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + m = method(:send) + assert_equal(false, m.(:y, **{}).frozen?) + assert_equal_not_same(kw, m.(:y, **kw)) + assert_equal_not_same(h, m.(:y, **h)) + assert_equal(false, m.send(:call, :y, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, :y, **kw)) + assert_equal_not_same(h, m.send(:call, :y, **h)) + + singleton_class.send(:remove_method, :y) + define_singleton_method(:y) { |**kw| kw } + m = method(:y) + assert_equal(false, y(**{}).frozen?) + assert_equal_not_same(kw, y(**kw)) + assert_equal_not_same(h, y(**h)) + assert_equal(false, send(:y, **{}).frozen?) + assert_equal_not_same(kw, send(:y, **kw)) + assert_equal_not_same(h, send(:y, **h)) + assert_equal(false, public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, public_send(:y, **kw)) + assert_equal_not_same(h, public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + y = lambda { |**kw| kw } + m = y.method(:call) + assert_equal(false, y.(**{}).frozen?) + assert_equal_not_same(kw, y.(**kw)) + assert_equal_not_same(h, y.(**h)) + assert_equal(false, y.send(:call, **{}).frozen?) + assert_equal_not_same(kw, y.send(:call, **kw)) + assert_equal_not_same(h, y.send(:call, **h)) + assert_equal(false, y.public_send(:call, **{}).frozen?) + assert_equal_not_same(kw, y.public_send(:call, **kw)) + assert_equal_not_same(h, y.public_send(:call, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + y = :y.to_proc + m = y.method(:call) + assert_equal(false, y.(self, **{}).frozen?) + assert_equal_not_same(kw, y.(self, **kw)) + assert_equal_not_same(h, y.(self, **h)) + assert_equal(false, y.send(:call, self, **{}).frozen?) + assert_equal_not_same(kw, y.send(:call, self, **kw)) + assert_equal_not_same(h, y.send(:call, self, **h)) + assert_equal(false, y.public_send(:call, self, **{}).frozen?) + assert_equal_not_same(kw, y.public_send(:call, self, **kw)) + assert_equal_not_same(h, y.public_send(:call, self, **h)) + assert_equal(false, m.(self, **{}).frozen?) + assert_equal_not_same(kw, m.(self, **kw)) + assert_equal_not_same(h, m.(self, **h)) + assert_equal(false, m.send(:call, self, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, self, **kw)) + assert_equal_not_same(h, m.send(:call, self, **h)) + + c = Class.new do + def y(**kw) kw end + end + o = c.new + def o.y(**kw) super end + m = o.method(:y) + assert_equal(false, o.y(**{}).frozen?) + assert_equal_not_same(kw, o.y(**kw)) + assert_equal_not_same(h, o.y(**h)) + assert_equal(false, o.send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.send(:y, **kw)) + assert_equal_not_same(h, o.send(:y, **h)) + assert_equal(false, o.public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.public_send(:y, **kw)) + assert_equal_not_same(h, o.public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + o.singleton_class.send(:remove_method, :y) + def o.y(**kw) super(**kw) end + assert_equal(false, o.y(**{}).frozen?) + assert_equal_not_same(kw, o.y(**kw)) + assert_equal_not_same(h, o.y(**h)) + assert_equal(false, o.send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.send(:y, **kw)) + assert_equal_not_same(h, o.send(:y, **h)) + assert_equal(false, o.public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.public_send(:y, **kw)) + assert_equal_not_same(h, o.public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + c = Class.new do + def method_missing(_, **kw) kw end + end + o = c.new + def o.y(**kw) super end + m = o.method(:y) + assert_equal(false, o.y(**{}).frozen?) + assert_equal_not_same(kw, o.y(**kw)) + assert_equal_not_same(h, o.y(**h)) + assert_equal(false, o.send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.send(:y, **kw)) + assert_equal_not_same(h, o.send(:y, **h)) + assert_equal(false, o.public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.public_send(:y, **kw)) + assert_equal_not_same(h, o.public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + o.singleton_class.send(:remove_method, :y) + def o.y(**kw) super(**kw) end + assert_equal(false, o.y(**{}).frozen?) + assert_equal_not_same(kw, o.y(**kw)) + assert_equal_not_same(h, o.y(**h)) + assert_equal(false, o.send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.send(:y, **kw)) + assert_equal_not_same(h, o.send(:y, **h)) + assert_equal(false, o.public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, o.public_send(:y, **kw)) + assert_equal_not_same(h, o.public_send(:y, **h)) + assert_equal(false, m.(**{}).frozen?) + assert_equal_not_same(kw, m.(**kw)) + assert_equal_not_same(h, m.(**h)) + assert_equal(false, m.send(:call, **{}).frozen?) + assert_equal_not_same(kw, m.send(:call, **kw)) + assert_equal_not_same(h, m.send(:call, **h)) + + c = Class.new do + attr_reader :kw + def initialize(**kw) @kw = kw end + end + m = c.method(:new) + assert_equal(false, c.new(**{}).kw.frozen?) + assert_equal_not_same(kw, c.new(**kw).kw) + assert_equal_not_same(h, c.new(**h).kw) + assert_equal(false, c.send(:new, **{}).kw.frozen?) + assert_equal_not_same(kw, c.send(:new, **kw).kw) + assert_equal_not_same(h, c.send(:new, **h).kw) + assert_equal(false, c.public_send(:new, **{}).kw.frozen?) + assert_equal_not_same(kw, c.public_send(:new, **kw).kw) + assert_equal_not_same(h, c.public_send(:new, **h).kw) + assert_equal(false, m.(**{}).kw.frozen?) + assert_equal_not_same(kw, m.(**kw).kw) + assert_equal_not_same(h, m.(**h).kw) + assert_equal(false, m.send(:call, **{}).kw.frozen?) + assert_equal_not_same(kw, m.send(:call, **kw).kw) + assert_equal_not_same(h, m.send(:call, **h).kw) + + singleton_class.send(:attr_writer, :y) + m = method(:y=) + assert_equal_not_same(h, send(:y=, **h)) + assert_equal_not_same(h, public_send(:y=, **h)) + assert_equal_not_same(h, m.(**h)) + assert_equal_not_same(h, m.send(:call, **h)) + + singleton_class.send(:remove_method, :y) + def self.method_missing(_, **kw) kw end + assert_equal(false, y(**{}).frozen?) + assert_equal_not_same(kw, y(**kw)) + assert_equal_not_same(h, y(**h)) + assert_equal(false, send(:y, **{}).frozen?) + assert_equal_not_same(kw, send(:y, **kw)) + assert_equal_not_same(h, send(:y, **h)) + assert_equal(false, public_send(:y, **{}).frozen?) + assert_equal_not_same(kw, public_send(:y, **kw)) + assert_equal_not_same(h, public_send(:y, **h)) + end + def test_regular_kwsplat kw = {} h = {:a=>1} @@ -224,12 +434,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(kw, c.m(kw, **kw)) assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) @@ -248,39 +454,21 @@ def c.m(**args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } assert_equal([h, kw], c.m(h)) assert_equal([h2, kw], c.m(h2)) assert_equal([h3, kw], c.m(h3)) @@ -296,13 +484,9 @@ def c.m(arg=1, **args) assert_equal([1, h2], c.m(**h2)) assert_equal([1, h3], c.m(**h3)) assert_equal([1, h3], c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal([1, h], c.m(h)) - end + assert_equal([h, kw], c.m(h)) assert_equal([h2, kw], c.m(h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_equal([h2, h], c.m(h3)) - end + assert_equal([h3, kw], c.m(h3)) end def test_implicit_super_kwsplat @@ -313,19 +497,9 @@ def test_implicit_super_kwsplat sc = Class.new c = sc.new - redef = -> do - if defined?(c.m) - class << c - remove_method(:m) - end - end - eval <<-END - def c.m(*args, **kw) - super(*args, **kw) - end - END + def c.m(*args, **kw) + super(*args, **kw) end - redef[] sc.class_eval do def m(*args) args @@ -357,13 +531,8 @@ def m(args) args end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -383,13 +552,9 @@ def m(**args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } sc.class_eval do remove_method(:m) @@ -397,34 +562,13 @@ def m(arg, **args) [arg, args] end end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } sc.class_eval do remove_method(:m) @@ -449,19 +593,9 @@ def test_explicit_super_kwsplat sc = Class.new c = sc.new - redef = -> do - if defined?(c.m) - class << c - remove_method(:m) - end - end - eval <<-END - def c.m(*args, **kw) - super(*args, **kw) - end - END + def c.m(*args, **kw) + super(*args, **kw) end - redef[] sc.class_eval do def m(*args) args @@ -493,13 +627,8 @@ def m(args) args end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -519,13 +648,9 @@ def m(**args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } sc.class_eval do remove_method(:m) @@ -533,34 +658,13 @@ def m(arg, **args) [arg, args] end end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } sc.class_eval do remove_method(:m) @@ -592,12 +696,8 @@ def test_lambda_kwsplat_call assert_raise(ArgumentError) { f[**h3] } f = ->(a) { a } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**kw]) - end + assert_raise(ArgumentError) { f[**{}] } + assert_raise(ArgumentError) { f[**kw] } assert_equal(h, f[**h]) assert_equal(h, f[a: 1]) assert_equal(h2, f[**h2]) @@ -612,36 +712,18 @@ def test_lambda_kwsplat_call assert_equal(h2, f[**h2]) assert_equal(h3, f[**h3]) assert_equal(h3, f[a: 1, **h2]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `\[\]'/m) do - assert_equal(h, f[h]) - end + assert_raise(ArgumentError) { f[h] } assert_raise(ArgumentError) { f[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `\[\]'/m) do - assert_raise(ArgumentError) { f[h3] } - end + assert_raise(ArgumentError) { f[h3] } f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([{}, {}], f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([{}, {}], f[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h, {}], f[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h, {}], f[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h2, {}], f[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h3, {}], f[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h3, {}], f[a: 1, **h2]) - end + assert_raise(ArgumentError) { f[**{}] } + assert_raise(ArgumentError) { f[**kw] } + assert_raise(ArgumentError) { f[**h] } + assert_raise(ArgumentError) { f[a: 1] } + assert_raise(ArgumentError) { f[**h2] } + assert_raise(ArgumentError) { f[**h3] } + assert_raise(ArgumentError) { f[a: 1, **h2] } f = ->(a=1, **x) { [a, x] } assert_equal([1, kw], f[**{}]) @@ -670,12 +752,8 @@ def test_lambda_method_kwsplat_call f = ->(a) { a } f = f.method(:call) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**kw]) - end + assert_raise(ArgumentError) { f[**{}] } + assert_raise(ArgumentError) { f[**kw] } assert_equal(h, f[**h]) assert_equal(h, f[a: 1]) assert_equal(h2, f[**h2]) @@ -691,37 +769,19 @@ def test_lambda_method_kwsplat_call assert_equal(h2, f[**h2]) assert_equal(h3, f[**h3]) assert_equal(h3, f[a: 1, **h2]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, f[h]) - end + assert_raise(ArgumentError) { f[h] } assert_raise(ArgumentError) { f[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { f[h3] } - end + assert_raise(ArgumentError) { f[h3] } f = ->(a, **x) { [a,x] } f = f.method(:call) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], f[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], f[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], f[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], f[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], f[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], f[a: 1, **h2]) - end + assert_raise(ArgumentError) { f[**{}] } + assert_raise(ArgumentError) { f[**kw] } + assert_raise(ArgumentError) { f[**h] } + assert_raise(ArgumentError) { f[a: 1] } + assert_raise(ArgumentError) { f[**h2] } + assert_raise(ArgumentError) { f[**h3] } + assert_raise(ArgumentError) { f[a: 1, **h2] } f = ->(a=1, **x) { [a, x] } f = f.method(:call) @@ -751,12 +811,8 @@ def test_Thread_new_kwsplat assert_raise(ArgumentError) { t.new(**h3, &f).value } f = ->(a) { a } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(**{}, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(**kw, &f).value) - end + assert_raise(ArgumentError) { t.new(**{}, &f).value } + assert_raise(ArgumentError) { t.new(**kw, &f).value } assert_equal(h, t.new(**h, &f).value) assert_equal(h, t.new(a: 1, &f).value) assert_equal(h2, t.new(**h2, &f).value) @@ -771,36 +827,18 @@ def test_Thread_new_kwsplat assert_equal(h2, t.new(**h2, &f).value) assert_equal(h3, t.new(**h3, &f).value) assert_equal(h3, t.new(a: 1, **h2, &f).value) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, t.new(h, &f).value) - end + assert_raise(ArgumentError) { t.new(h, &f).value } assert_raise(ArgumentError) { t.new(h2, &f).value } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { t.new(h3, &f).value } - end + assert_raise(ArgumentError) { t.new(h3, &f).value } f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(**{}, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(**kw, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(**h, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(a: 1, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], t.new(**h2, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(**h3, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(a: 1, **h2, &f).value) - end + assert_raise(ArgumentError) { t.new(**{}, &f).value } + assert_raise(ArgumentError) { t.new(**kw, &f).value } + assert_raise(ArgumentError) { t.new(**h, &f).value } + assert_raise(ArgumentError) { t.new(a: 1, &f).value } + assert_raise(ArgumentError) { t.new(**h2, &f).value } + assert_raise(ArgumentError) { t.new(**h3, &f).value } + assert_raise(ArgumentError) { t.new(a: 1, **h2, &f).value } f = ->(a=1, **x) { [a, x] } assert_equal([1, kw], t.new(**{}, &f).value) @@ -830,12 +868,8 @@ def test_Fiber_resume_kwsplat assert_raise(ArgumentError) { t.new(&f).resume(**h3) } f = ->(a) { a } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(&f).resume(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(&f).resume(**kw)) - end + assert_raise(ArgumentError) { t.new(&f).resume(**{}) } + assert_raise(ArgumentError) { t.new(&f).resume(**kw) } assert_equal(h, t.new(&f).resume(**h)) assert_equal(h, t.new(&f).resume(a: 1)) assert_equal(h2, t.new(&f).resume(**h2)) @@ -850,36 +884,18 @@ def test_Fiber_resume_kwsplat assert_equal(h2, t.new(&f).resume(**h2)) assert_equal(h3, t.new(&f).resume(**h3)) assert_equal(h3, t.new(&f).resume(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, t.new(&f).resume(h)) - end + assert_raise(ArgumentError) { t.new(&f).resume(h) } assert_raise(ArgumentError) { t.new(&f).resume(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { t.new(&f).resume(h3) } - end + assert_raise(ArgumentError) { t.new(&f).resume(h3) } f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(&f).resume(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(&f).resume(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(&f).resume(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(&f).resume(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], t.new(&f).resume(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(&f).resume(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(&f).resume(a: 1, **h2)) - end + assert_raise(ArgumentError) { t.new(&f).resume(**{}) } + assert_raise(ArgumentError) { t.new(&f).resume(**kw) } + assert_raise(ArgumentError) { t.new(&f).resume(**h) } + assert_raise(ArgumentError) { t.new(&f).resume(a: 1) } + assert_raise(ArgumentError) { t.new(&f).resume(**h2) } + assert_raise(ArgumentError) { t.new(&f).resume(**h3) } + assert_raise(ArgumentError) { t.new(&f).resume(a: 1, **h2) } f = ->(a=1, **x) { [a, x] } assert_equal([1, kw], t.new(&f).resume(**{})) @@ -907,12 +923,8 @@ def test_Enumerator_Generator_each_kwsplat assert_raise(ArgumentError) { g.new(&f).each(**h3) } f = ->(_, a) { a } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new(&f).each(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new(&f).each(**kw)) - end + assert_raise(ArgumentError) { g.new(&f).each(**{}) } + assert_raise(ArgumentError) { g.new(&f).each(**kw) } assert_equal(h, g.new(&f).each(**h)) assert_equal(h, g.new(&f).each(a: 1)) assert_equal(h2, g.new(&f).each(**h2)) @@ -927,36 +939,18 @@ def test_Enumerator_Generator_each_kwsplat assert_equal(h2, g.new(&f).each(**h2)) assert_equal(h3, g.new(&f).each(**h3)) assert_equal(h3, g.new(&f).each(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, g.new(&f).each(h)) - end + assert_raise(ArgumentError) { g.new(&f).each(h) } assert_raise(ArgumentError) { g.new(&f).each(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { g.new(&f).each(h3) } - end + assert_raise(ArgumentError) { g.new(&f).each(h3) } f = ->(_, a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new(&f).each(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new(&f).each(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new(&f).each(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new(&f).each(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], g.new(&f).each(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new(&f).each(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new(&f).each(a: 1, **h2)) - end + assert_raise(ArgumentError) { g.new(&f).each(**{}) } + assert_raise(ArgumentError) { g.new(&f).each(**kw) } + assert_raise(ArgumentError) { g.new(&f).each(**h) } + assert_raise(ArgumentError) { g.new(&f).each(a: 1) } + assert_raise(ArgumentError) { g.new(&f).each(**h2) } + assert_raise(ArgumentError) { g.new(&f).each(**h3) } + assert_raise(ArgumentError) { g.new(&f).each(a: 1, **h2) } f = ->(_, a=1, **x) { [a, x] } assert_equal([1, kw], g.new(&f).each(**{})) @@ -984,12 +978,8 @@ def test_Enumerator_Yielder_yield_kwsplat assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) } f = ->(a) { a } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new{|y| y.yield(**{})}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new{|y| y.yield(**kw)}.each(&f)) - end + assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) } assert_equal(h, g.new{|y| y.yield(**h)}.each(&f)) assert_equal(h, g.new{|y| y.yield(a: 1)}.each(&f)) assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f)) @@ -1004,36 +994,18 @@ def test_Enumerator_Yielder_yield_kwsplat assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f)) assert_equal(h3, g.new{|y| y.yield(**h3)}.each(&f)) assert_equal(h3, g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, g.new{|y| y.yield(h)}.each(&f)) - end + assert_raise(ArgumentError) { g.new{|y| y.yield(h)}.each(&f) } assert_raise(ArgumentError) { g.new{|y| y.yield(h2)}.each(&f) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) } - end + assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) } f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new{|y| y.yield(**{})}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new{|y| y.yield(**kw)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new{|y| y.yield(**h)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new{|y| y.yield(a: 1)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], g.new{|y| y.yield(**h2)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new{|y| y.yield(**h3)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - end + assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(**h)}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1)}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(**h2)}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) } + assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1, **h2)}.each(&f) } f = ->(a=1, **x) { [a, x] } assert_equal([1, kw], g.new{|y| y.yield(**{})}.each(&f)) @@ -1087,12 +1059,8 @@ def initialize(args) @args = args end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**kw].args) - end + assert_raise(ArgumentError) { c[**{}] } + assert_raise(ArgumentError) { c[**kw] } assert_equal(h, c[**h].args) assert_equal(h, c[a: 1].args) assert_equal(h2, c[**h2].args) @@ -1111,40 +1079,22 @@ def initialize(**args) assert_equal(h2, c[**h2].args) assert_equal(h3, c[**h3].args) assert_equal(h3, c[a: 1, **h2].args) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal(h, c[h].args) - end + assert_raise(ArgumentError) { c[h].args } assert_raise(ArgumentError) { c[h2].args } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do - assert_raise(ArgumentError) { c[h3].args } - end + assert_raise(ArgumentError) { c[h3].args } c = Class.new(sc) do def initialize(arg, **args) @args = [arg, args] end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**kw].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[**h].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[a: 1].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h2, kw], c[**h2].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[**h3].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[a: 1, **h2].args) - end + assert_raise(ArgumentError) { c[**{}].args } + assert_raise(ArgumentError) { c[**kw].args } + assert_raise(ArgumentError) { c[**h].args } + assert_raise(ArgumentError) { c[a: 1].args } + assert_raise(ArgumentError) { c[**h2].args } + assert_raise(ArgumentError) { c[**h3].args } + assert_raise(ArgumentError) { c[a: 1, **h2].args } c = Class.new(sc) do def initialize(arg=1, **args) @@ -1199,12 +1149,8 @@ def initialize(args) @args = args end end.method(:new) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**kw].args) - end + assert_raise(ArgumentError) { c[**{}] } + assert_raise(ArgumentError) { c[**kw] } assert_equal(h, c[**h].args) assert_equal(h, c[a: 1].args) assert_equal(h2, c[**h2].args) @@ -1223,40 +1169,22 @@ def initialize(**args) assert_equal(h2, c[**h2].args) assert_equal(h3, c[**h3].args) assert_equal(h3, c[a: 1, **h2].args) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal(h, c[h].args) - end + assert_raise(ArgumentError) { c[h].args } assert_raise(ArgumentError) { c[h2].args } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do - assert_raise(ArgumentError) { c[h3].args } - end + assert_raise(ArgumentError) { c[h3].args } c = Class.new(sc) do def initialize(arg, **args) @args = [arg, args] end end.method(:new) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**kw].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[**h].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[a: 1].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h2, kw], c[**h2].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[**h3].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[a: 1, **h2].args) - end + assert_raise(ArgumentError) { c[**{}].args } + assert_raise(ArgumentError) { c[**kw].args } + assert_raise(ArgumentError) { c[**h].args } + assert_raise(ArgumentError) { c[a: 1].args } + assert_raise(ArgumentError) { c[**h2].args } + assert_raise(ArgumentError) { c[**h3].args } + assert_raise(ArgumentError) { c[a: 1, **h2].args } c = Class.new(sc) do def initialize(arg=1, **args) @@ -1304,12 +1232,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.method(:m)[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.method(:m)[**kw]) - end + assert_raise(ArgumentError) { c.method(:m)[**{}] } + assert_raise(ArgumentError) { c.method(:m)[**kw] } assert_equal(h, c.method(:m)[**h]) assert_equal(h, c.method(:m)[a: 1]) assert_equal(h2, c.method(:m)[**h2]) @@ -1327,39 +1251,21 @@ def c.m(**args) assert_equal(h2, c.method(:m)[**h2]) assert_equal(h3, c.method(:m)[**h3]) assert_equal(h3, c.method(:m)[a: 1, **h2]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.method(:m)[h]) - end + assert_raise(ArgumentError) { c.method(:m)[h] } assert_raise(ArgumentError) { c.method(:m)[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.method(:m)[h3] } - end + assert_raise(ArgumentError) { c.method(:m)[h3] } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.method(:m)[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.method(:m)[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.method(:m)[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.method(:m)[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.method(:m)[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.method(:m)[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.method(:m)[a: 1, **h2]) - end + assert_raise(ArgumentError) { c.method(:m)[**{}] } + assert_raise(ArgumentError) { c.method(:m)[**kw] } + assert_raise(ArgumentError) { c.method(:m)[**h] } + assert_raise(ArgumentError) { c.method(:m)[a: 1] } + assert_raise(ArgumentError) { c.method(:m)[**h2] } + assert_raise(ArgumentError) { c.method(:m)[**h3] } + assert_raise(ArgumentError) { c.method(:m)[a: 1, **h2] } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -1407,12 +1313,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, sc.instance_method(:m).bind_call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, sc.instance_method(:m).bind_call(c, **kw)) - end + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) } assert_equal(h, sc.instance_method(:m).bind_call(c, **h)) assert_equal(h, sc.instance_method(:m).bind_call(c, a: 1)) assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2)) @@ -1430,39 +1332,21 @@ def c.m(**args) assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2)) assert_equal(h3, sc.instance_method(:m).bind_call(c, **h3)) assert_equal(h3, sc.instance_method(:m).bind_call(c, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, sc.instance_method(:m).bind_call(c, h)) - end + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h) } assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) } - end + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) } sc.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], sc.instance_method(:m).bind_call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], sc.instance_method(:m).bind_call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], sc.instance_method(:m).bind_call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, a: 1, **h2)) - end + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h2) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h3) } + assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1, **h2) } sc.remove_method(:m) def c.m(arg=1, **args) @@ -1509,12 +1393,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.send(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.send(:m, **kw)) - end + assert_raise(ArgumentError) { c.send(:m, **{}) } + assert_raise(ArgumentError) { c.send(:m, **kw) } assert_equal(h, c.send(:m, **h)) assert_equal(h, c.send(:m, a: 1)) assert_equal(h2, c.send(:m, **h2)) @@ -1532,39 +1412,21 @@ def c.m(**args) assert_equal(h2, c.send(:m, **h2)) assert_equal(h3, c.send(:m, **h3)) assert_equal(h3, c.send(:m, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.send(:m, h)) - end + assert_raise(ArgumentError) { c.send(:m, h) } assert_raise(ArgumentError) { c.send(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.send(:m, h3) } - end + assert_raise(ArgumentError) { c.send(:m, h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.send(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.send(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.send(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.send(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.send(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.send(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.send(:m, a: 1, **h2)) - end + assert_raise(ArgumentError) { c.send(:m, **{}) } + assert_raise(ArgumentError) { c.send(:m, **kw) } + assert_raise(ArgumentError) { c.send(:m, **h) } + assert_raise(ArgumentError) { c.send(:m, a: 1) } + assert_raise(ArgumentError) { c.send(:m, **h2) } + assert_raise(ArgumentError) { c.send(:m, **h3) } + assert_raise(ArgumentError) { c.send(:m, a: 1, **h2) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -1611,12 +1473,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.public_send(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.public_send(:m, **kw)) - end + assert_raise(ArgumentError) { c.public_send(:m, **{}) } + assert_raise(ArgumentError) { c.public_send(:m, **kw) } assert_equal(h, c.public_send(:m, **h)) assert_equal(h, c.public_send(:m, a: 1)) assert_equal(h2, c.public_send(:m, **h2)) @@ -1634,39 +1492,21 @@ def c.m(**args) assert_equal(h2, c.public_send(:m, **h2)) assert_equal(h3, c.public_send(:m, **h3)) assert_equal(h3, c.public_send(:m, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.public_send(:m, h)) - end + assert_raise(ArgumentError) { c.public_send(:m, h) } assert_raise(ArgumentError) { c.public_send(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.public_send(:m, h3) } - end + assert_raise(ArgumentError) { c.public_send(:m, h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.public_send(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.public_send(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.public_send(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.public_send(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.public_send(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.public_send(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.public_send(:m, a: 1, **h2)) - end + assert_raise(ArgumentError) { c.public_send(:m, **{}) } + assert_raise(ArgumentError) { c.public_send(:m, **kw) } + assert_raise(ArgumentError) { c.public_send(:m, **h) } + assert_raise(ArgumentError) { c.public_send(:m, a: 1) } + assert_raise(ArgumentError) { c.public_send(:m, **h2) } + assert_raise(ArgumentError) { c.public_send(:m, **h3) } + assert_raise(ArgumentError) { c.public_send(:m, a: 1, **h2) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -1716,12 +1556,8 @@ def c.m(args) args end m = c.method(:send) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(:m, **kw)) - end + assert_raise(ArgumentError) { m.call(:m, **{}) } + assert_raise(ArgumentError) { m.call(:m, **kw) } assert_equal(h, m.call(:m, **h)) assert_equal(h, m.call(:m, a: 1)) assert_equal(h2, m.call(:m, **h2)) @@ -1740,40 +1576,22 @@ def c.m(**args) assert_equal(h2, m.call(:m, **h2)) assert_equal(h3, m.call(:m, **h3)) assert_equal(h3, m.call(:m, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, m.call(:m, h)) - end + assert_raise(ArgumentError) { m.call(:m, h) } assert_raise(ArgumentError) { m.call(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { m.call(:m, h3) } - end + assert_raise(ArgumentError) { m.call(:m, h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end m = c.method(:send) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - m.call(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - m.call(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], m.call(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(:m, a: 1, **h2)) - end + assert_raise(ArgumentError) { m.call(:m, **{}) } + assert_raise(ArgumentError) { m.call(:m, **kw) } + assert_raise(ArgumentError) { m.call(:m, **h) } + assert_raise(ArgumentError) { m.call(:m, a: 1) } + assert_raise(ArgumentError) { m.call(:m, **h2) } + assert_raise(ArgumentError) { m.call(:m, **h3) } + assert_raise(ArgumentError) { m.call(:m, a: 1, **h2) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -1821,12 +1639,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, :m.to_proc.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, :m.to_proc.call(c, **kw)) - end + assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) } + assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) } assert_equal(h, :m.to_proc.call(c, **h)) assert_equal(h, :m.to_proc.call(c, a: 1)) assert_equal(h2, :m.to_proc.call(c, **h2)) @@ -1844,39 +1658,21 @@ def c.m(**args) assert_equal(h2, :m.to_proc.call(c, **h2)) assert_equal(h3, :m.to_proc.call(c, **h3)) assert_equal(h3, :m.to_proc.call(c, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, :m.to_proc.call(c, h)) - end + assert_raise(ArgumentError) { :m.to_proc.call(c, h) } assert_raise(ArgumentError) { :m.to_proc.call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { :m.to_proc.call(c, h3) } - end + assert_raise(ArgumentError) { :m.to_proc.call(c, h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], :m.to_proc.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], :m.to_proc.call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], :m.to_proc.call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], :m.to_proc.call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], :m.to_proc.call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], :m.to_proc.call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], :m.to_proc.call(c, a: 1, **h2)) - end + assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) } + assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) } + assert_raise(ArgumentError) { :m.to_proc.call(c, **h) } + assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1) } + assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) } + assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) } + assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1, **h2) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -1924,12 +1720,8 @@ def c.m; end def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(c, **kw)) - end + assert_raise(ArgumentError) { m.call(c, **{}) } + assert_raise(ArgumentError) { m.call(c, **kw) } assert_equal(h, m.call(c, **h)) assert_equal(h, m.call(c, a: 1)) assert_equal(h2, m.call(c, **h2)) @@ -1947,39 +1739,21 @@ def c.m(**args) assert_equal(h2, m.call(c, **h2)) assert_equal(h3, m.call(c, **h3)) assert_equal(h3, m.call(c, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, m.call(c, h)) - end + assert_raise(ArgumentError) { m.call(c, h) } assert_raise(ArgumentError) { m.call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { m.call(c, h3) } - end + assert_raise(ArgumentError) { m.call(c, h3) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], m.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], m.call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], m.call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(c, a: 1, **h2)) - end + assert_raise(ArgumentError) { m.call(c, **{}) } + assert_raise(ArgumentError) { m.call(c, **kw) } + assert_raise(ArgumentError) { m.call(c, **h) } + assert_raise(ArgumentError) { m.call(c, a: 1) } + assert_raise(ArgumentError) { m.call(c, **h2) } + assert_raise(ArgumentError) { m.call(c, **h3) } + assert_raise(ArgumentError) { m.call(c, a: 1, **h2) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -2026,12 +1800,8 @@ def c.method_missing(_); end def c.method_missing(_, args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -2049,39 +1819,21 @@ def c.method_missing(_, **args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg=1, **args) @@ -2128,22 +1880,12 @@ def c.method_missing(_); end assert_raise(ArgumentError) { c.m(**h3) } assert_raise(ArgumentError) { c.m(a: 1, **h2) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, args) + args end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -2161,50 +1903,21 @@ def c.method_missing(_, **args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, arg, **args) + [arg, args] end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg=1, **args) @@ -2252,12 +1965,8 @@ def c.method_missing(_); end def c.method_missing(_, args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -2275,39 +1984,21 @@ def c.method_missing(_, **args) assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg=1, **args) @@ -2344,12 +2035,8 @@ class << c class << c define_method(:m) {|arg| arg } end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.m(**kw)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } assert_equal(h, c.m(**h)) assert_equal(h, c.m(a: 1)) assert_equal(h2, c.m(**h2)) @@ -2379,39 +2066,21 @@ class << c assert_equal(h2, c.m(**h2)) assert_equal(h3, c.m(**h3)) assert_equal(h3, c.m(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, c.m(h)) - end + assert_raise(ArgumentError) { c.m(h) } assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { c.m(h3) } - end + assert_raise(ArgumentError) { c.m(h3) } c = Object.new class << c define_method(:m) {|arg, **opt| [arg, opt] } end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(**{}) } + assert_raise(ArgumentError) { c.m(**kw) } + assert_raise(ArgumentError) { c.m(**h) } + assert_raise(ArgumentError) { c.m(a: 1) } + assert_raise(ArgumentError) { c.m(**h2) } + assert_raise(ArgumentError) { c.m(**h3) } + assert_raise(ArgumentError) { c.m(a: 1, **h2) } c = Object.new class << c @@ -2429,23 +2098,15 @@ class << c class << c define_method(:m) {|*args, **opt| [args, opt] } end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[], h], c.m(h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[h], h], c.m(h, h)) - end + assert_equal([[h], kw], c.m(h)) + assert_equal([[h, h], kw], c.m(h, h)) c = Object.new class << c define_method(:m) {|arg=nil, a: nil| [arg, a] } end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], c.m(h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], c.m(**h3)) - end + assert_equal([h3, nil], c.m(h3)) + assert_raise(ArgumentError) { c.m(**h3) } end def test_define_method_method_kwsplat @@ -2472,12 +2133,8 @@ class << c define_method(:m) {|arg| arg } end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, m.call(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, m.call(**kw)) - end + assert_raise(ArgumentError) { m.call(**{}) } + assert_raise(ArgumentError) { m.call(**kw) } assert_equal(h, m.call(**h)) assert_equal(h, m.call(a: 1)) assert_equal(h2, m.call(**h2)) @@ -2509,40 +2166,22 @@ class << c assert_equal(h2, m.call(**h2)) assert_equal(h3, m.call(**h3)) assert_equal(h3, m.call(a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, m.call(h)) - end + assert_raise(ArgumentError) { m.call(h) } assert_raise(ArgumentError) { m.call(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { m.call(h3) } - end + assert_raise(ArgumentError) { m.call(h3) } c = Object.new class << c define_method(:m) {|arg, **opt| [arg, opt] } end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], m.call(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], m.call(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], m.call(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], m.call(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], m.call(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], m.call(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], m.call(a: 1, **h2)) - end + assert_raise(ArgumentError) { m.call(**{}) } + assert_raise(ArgumentError) { m.call(**kw) } + assert_raise(ArgumentError) { m.call(**h) } + assert_raise(ArgumentError) { m.call(a: 1) } + assert_raise(ArgumentError) { m.call(**h2) } + assert_raise(ArgumentError) { m.call(**h3) } + assert_raise(ArgumentError) { m.call(a: 1, **h2) } c = Object.new class << c @@ -2562,24 +2201,16 @@ class << c define_method(:m) {|*args, **opt| [args, opt] } end m = c.method(:m) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[], h], m.call(h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[h], h], m.call(h, h)) - end + assert_equal([[h], kw], m.call(h)) + assert_equal([[h, h], kw], m.call(h, h)) c = Object.new class << c define_method(:m) {|arg=nil, a: nil| [arg, a] } end m = c.method(:m) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], m.call(h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], m.call(**h3)) - end + assert_equal([h3, nil], m.call(h3)) + assert_raise(ArgumentError) { m.call(**h3) } end def test_attr_reader_kwsplat @@ -2631,12 +2262,8 @@ def test_attr_writer_kwsplat class << c attr_writer :m end - assert_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do - c.send(:m=, **{}) - end - assert_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do - c.send(:m=, **kw) - end + assert_raise(ArgumentError) { c.send(:m=, **{}) } + assert_raise(ArgumentError) { c.send(:m=, **kw) } assert_equal(h, c.send(:m=, **h)) assert_equal(h, c.send(:m=, a: 1)) assert_equal(h2, c.send(:m=, **h2)) @@ -2663,12 +2290,8 @@ class << c attr_writer :m end m = c.method(:m=) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - m.call(**{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - m.call(**kw) - end + assert_raise(ArgumentError) { m.call(**{}) } + assert_raise(ArgumentError) { m.call(**kw) } assert_equal(h, m.call(**h)) assert_equal(h, m.call(a: 1)) assert_equal(h2, m.call(**h2)) @@ -2691,13 +2314,9 @@ def test_proc_ruby2_keywords assert_equal([[1], h1], foo.call(1, :a=>1, &->(*args, **kw){[args, kw]})) assert_equal([1, h1], foo.call(1, :a=>1, &->(*args){args})) - assert_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal([[1], h1], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]})) - end + assert_equal([[1, h1], {}], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]})) assert_equal([1, h1], foo.call(1, {:a=>1}, &->(*args){args})) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h1, {}], foo.call(:a=>1, &->(arg, **kw){[arg, kw]})) - end + assert_raise(ArgumentError) { foo.call(:a=>1, &->(arg, **kw){[arg, kw]}) } assert_equal(h1, foo.call(:a=>1, &->(arg){arg})) [->(){}, ->(arg){}, ->(*args, **kw){}, ->(*args, k: 1){}, ->(*args, k: ){}].each do |pr| @@ -2724,6 +2343,12 @@ def o.foo(*args) end def test_ruby2_keywords + assert_raise(ArgumentError) do + Class.new do + ruby2_keywords + end + end + c = Class.new do ruby2_keywords def foo(meth, *args) send(meth, *args) @@ -2741,6 +2366,11 @@ def test_ruby2_keywords baz(*args) end + define_method(:block_splat) {|*args| } + ruby2_keywords :block_splat, def foo_bar_after_bmethod(*args) + bar(*args) + end + ruby2_keywords def foo_baz2(*args) baz(*args) baz(*args) @@ -2781,6 +2411,13 @@ def baz(*args) args end + def empty_method + end + + def opt(arg = :opt) + arg + end + ruby2_keywords def foo_dbar(*args) dbar(*args) end @@ -2789,6 +2426,16 @@ def baz(*args) dbaz(*args) end + ruby2_keywords def clear_last_empty_method(*args) + args.last.clear + empty_method(*args) + end + + ruby2_keywords def clear_last_opt(*args) + args.last.clear + opt(*args) + end + define_method(:dbar) do |*args, **kw| [args, kw] end @@ -2876,6 +2523,7 @@ def method_missing(*args) assert_equal([1, h1], o.foo(:foo_baz, 1, :a=>1)) assert_equal([[1], h1], o.foo_foo_bar(1, :a=>1)) assert_equal([1, h1], o.foo_foo_baz(1, :a=>1)) + assert_equal([[1], h1], o.foo_bar_after_bmethod(1, :a=>1)) assert_equal([[1], h1], o.foo(:bar, 1, **h1)) assert_equal([1, h1], o.foo(:baz, 1, **h1)) @@ -2891,6 +2539,7 @@ def method_missing(*args) assert_equal([1, h1], o.foo(:foo_baz, 1, **h1)) assert_equal([[1], h1], o.foo_foo_bar(1, **h1)) assert_equal([1, h1], o.foo_foo_baz(1, **h1)) + assert_equal([[1], h1], o.foo_bar_after_bmethod(1, **h1)) assert_equal([[h1], {}], o.foo(:bar, h1, **{})) assert_equal([h1], o.foo(:baz, h1, **{})) @@ -2906,23 +2555,17 @@ def method_missing(*args) assert_equal([h1], o.foo(:foo_baz, h1, **{})) assert_equal([[h1], {}], o.foo_foo_bar(h1, **{})) assert_equal([h1], o.foo_foo_baz(h1, **{})) + assert_equal([[h1], {}], o.foo_bar_after_bmethod(h1, **{})) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo(:bar, 1, h1)) - end + assert_equal([[1, h1], {}], o.foo(:bar, 1, h1)) assert_equal([1, h1], o.foo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bfoo(:bar, 1, h1)) - end + assert_equal([[1, h1], {}], o.bfoo(:bar, 1, h1)) assert_equal([1, h1], o.bfoo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.store_foo(:bar, 1, h1)) - end + assert_equal([[1, h1], {}], o.store_foo(:bar, 1, h1)) assert_equal([1, h1], o.store_foo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo_bar(1, h1)) - end + assert_equal([[1, h1], {}], o.foo_bar(1, h1)) assert_equal([1, h1], o.foo_baz(1, h1)) + assert_equal([[1, h1], {}], o.foo_bar_after_bmethod(1, h1)) assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, :a=>1)) assert_equal([1, h1, 1], o.foo_mod(:baz, 1, :a=>1)) @@ -2934,10 +2577,10 @@ def method_missing(*args) assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, **h1)) assert_equal([1, h1, 1], o.foo_baz_mod(1, **h1)) - assert_equal([[h1, {}, 1], {}], o.foo_mod(:bar, h1, **{})) - assert_equal([h1, {}, 1], o.foo_mod(:baz, h1, **{})) - assert_equal([[h1, {}, 1], {}], o.foo_bar_mod(h1, **{})) - assert_equal([h1, {}, 1], o.foo_baz_mod(h1, **{})) + assert_equal([[h1, 1], {}], o.foo_mod(:bar, h1, **{})) + assert_equal([h1, 1], o.foo_mod(:baz, h1, **{})) + assert_equal([[h1, 1], {}], o.foo_bar_mod(h1, **{})) + assert_equal([h1, 1], o.foo_baz_mod(h1, **{})) assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, h1)) assert_equal([1, h1, 1], o.foo_mod(:baz, 1, h1)) @@ -2971,43 +2614,29 @@ def method_missing(*args) assert_equal([[h1], {}], o.foo_dbar(h1, **{})) assert_equal([h1], o.foo_dbaz(h1, **{})) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.foo(:dbar, 1, h1)) - end + assert_equal([[1, h1], {}], o.foo(:dbar, 1, h1)) assert_equal([1, h1], o.foo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.bfoo(:dbar, 1, h1)) - end + assert_equal([[1, h1], {}], o.bfoo(:dbar, 1, h1)) assert_equal([1, h1], o.bfoo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.store_foo(:dbar, 1, h1)) - end + assert_equal([[1, h1], {}], o.store_foo(:dbar, 1, h1)) assert_equal([1, h1], o.store_foo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.foo_dbar(1, h1)) - end + assert_equal([[1, h1], {}], o.foo_dbar(1, h1)) assert_equal([1, h1], o.foo_dbaz(1, h1)) assert_equal([[1], h1], o.block(1, :a=>1)) assert_equal([[1], h1], o.block(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal([[1], h1], o.block(1, h1)) - end + assert_equal([[1, h1], {}], o.block(1, h1)) assert_equal([[h1], {}], o.block(h1, **{})) assert_equal([[1], h1], o.cfunc(1, :a=>1)) assert_equal([[1], h1], o.cfunc(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal([[1], h1], o.cfunc(1, h1)) - end + assert_equal([[1, h1], {}], o.cfunc(1, h1)) assert_equal([[h1], {}], o.cfunc(h1, **{})) o = mmkw.new assert_equal([[:b, 1], h1], o.b(1, :a=>1)) assert_equal([[:b, 1], h1], o.b(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([[:b, 1], h1], o.b(1, h1)) - end + assert_equal([[:b, 1, h1], {}], o.b(1, h1)) assert_equal([[:b, h1], {}], o.b(h1, **{})) o = mmnokw.new @@ -3019,9 +2648,7 @@ def method_missing(*args) o = implicit_super.new assert_equal([[1], h1], o.bar(1, :a=>1)) assert_equal([[1], h1], o.bar(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bar(1, h1)) - end + assert_equal([[1, h1], {}], o.bar(1, h1)) assert_equal([[h1], {}], o.bar(h1, **{})) assert_equal([1, h1], o.baz(1, :a=>1)) @@ -3032,9 +2659,7 @@ def method_missing(*args) o = explicit_super.new assert_equal([[1], h1], o.bar(1, :a=>1)) assert_equal([[1], h1], o.bar(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bar(1, h1)) - end + assert_equal([[1, h1], {}], o.bar(1, h1)) assert_equal([[h1], {}], o.bar(h1, **{})) assert_equal([1, h1], o.baz(1, :a=>1)) @@ -3042,19 +2667,11 @@ def method_missing(*args) assert_equal([1, h1], o.baz(1, h1)) assert_equal([h1], o.baz(h1, **{})) - c.class_eval do - remove_method(:bar) - def bar(*args, **kw) - [args, kw] - end - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1)) - end + assert_equal([[1, h1], {}], o.foo(:pass_bar, 1, :a=>1)) + assert_equal([[1, h1], {}], o.foo(:pass_cfunc, 1, :a=>1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal([[1], h1], o.foo(:pass_cfunc, 1, :a=>1)) - end + assert_equal(:opt, o.clear_last_opt(a: 1)) + assert_nothing_raised(ArgumentError) { o.clear_last_empty_method(a: 1) } assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do assert_nil(c.send(:ruby2_keywords, :bar)) @@ -3142,25 +2759,14 @@ def c.dig(**args) end assert_equal(c, [c].dig(0, **{})) assert_equal(c, [c].dig(0, **kw)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, a: 1)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, **h3) } - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, h)) - end + assert_raise(ArgumentError) { [c].dig(0, **h) } + assert_raise(ArgumentError) { [c].dig(0, a: 1) } + assert_raise(ArgumentError) { [c].dig(0, **h2) } + assert_raise(ArgumentError) { [c].dig(0, **h3) } + assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } + assert_raise(ArgumentError) { [c].dig(0, h) } assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, h3) } - end + assert_raise(ArgumentError) { [c].dig(0, h3) } c.singleton_class.remove_method(:dig) def c.dig(arg, **args) @@ -3180,26 +2786,14 @@ def c.dig(arg=1, **args) end assert_equal(c, [c].dig(0, **{})) assert_equal(c, [c].dig(0, **kw)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, a: 1)) - end + assert_equal([h, kw], [c].dig(0, **h)) + assert_equal([h, kw], [c].dig(0, a: 1)) assert_equal([h2, kw], [c].dig(0, **h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, **h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, a: 1, **h2)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, h)) - end + assert_equal([h3, kw], [c].dig(0, **h3)) + assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) + assert_equal([h, {}], [c].dig(0, h)) assert_equal([h2, kw], [c].dig(0, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, h3)) - end + assert_equal([h3, kw], [c].dig(0, h3)) assert_equal([h, kw], [c].dig(0, h, **{})) assert_equal([h2, kw], [c].dig(0, h2, **{})) assert_equal([h3, kw], [c].dig(0, h3, **{})) @@ -3252,25 +2846,14 @@ def c.method_missing(_, **args) end assert_equal(c, [c].dig(0, **{})) assert_equal(c, [c].dig(0, **kw)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, a: 1)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, **h3) } - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, h)) - end + assert_raise(ArgumentError) { [c].dig(0, **h) } + assert_raise(ArgumentError) { [c].dig(0, a: 1) } + assert_raise(ArgumentError) { [c].dig(0, **h2) } + assert_raise(ArgumentError) { [c].dig(0, **h3) } + assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } + assert_raise(ArgumentError) { [c].dig(0, h) } assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, h3) } - end + assert_raise(ArgumentError) { [c].dig(0, h3) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg, **args) @@ -3290,26 +2873,14 @@ def c.method_missing(_, arg=1, **args) end assert_equal(c, [c].dig(0, **{})) assert_equal(c, [c].dig(0, **kw)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, a: 1)) - end + assert_equal([h, kw], [c].dig(0, **h)) + assert_equal([h, kw], [c].dig(0, a: 1)) assert_equal([h2, kw], [c].dig(0, **h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, **h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, a: 1, **h2)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, h)) - end + assert_equal([h3, kw], [c].dig(0, **h3)) + assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) + assert_equal([h, kw], [c].dig(0, h)) assert_equal([h2, kw], [c].dig(0, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, h3)) - end + assert_equal([h3, kw], [c].dig(0, h3)) assert_equal([h, kw], [c].dig(0, h, **{})) assert_equal([h2, kw], [c].dig(0, h2, **{})) assert_equal([h3, kw], [c].dig(0, h3, **{})) @@ -3342,12 +2913,8 @@ def test_enumerator_size_kwsplat assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size } m = ->(args){ args } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.to_enum(:each, **{}, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.to_enum(:each, **kw, &m).size) - end + assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size } assert_equal(kw, c.to_enum(:each, kw, **kw, &m).size) assert_equal(h, c.to_enum(:each, **h, &m).size) assert_equal(h, c.to_enum(:each, a: 1, &m).size) @@ -3363,36 +2930,18 @@ def test_enumerator_size_kwsplat assert_equal(h2, c.to_enum(:each, **h2, &m).size) assert_equal(h3, c.to_enum(:each, **h3, &m).size) assert_equal(h3, c.to_enum(:each, a: 1, **h2, &m).size) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, c.to_enum(:each, h, &m).size) - end + assert_raise(ArgumentError) { c.to_enum(:each, h, &m).size } assert_raise(ArgumentError) { c.to_enum(:each, h2, &m).size } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size } - end + assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size } m = ->(arg, **args){ [arg, args] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - c.to_enum(:each, **{}, &m).size - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - c.to_enum(:each, **kw, &m).size - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.to_enum(:each, **h, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.to_enum(:each, a: 1, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], c.to_enum(:each, **h2, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.to_enum(:each, **h3, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.to_enum(:each, a: 1, **h2, &m).size) - end + assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, **h, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, a: 1, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, **h2, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, **h3, &m).size } + assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size } assert_equal([h, kw], c.to_enum(:each, h, &m).size) assert_equal([h2, kw], c.to_enum(:each, h2, &m).size) assert_equal([h3, kw], c.to_enum(:each, h3, &m).size) @@ -3405,13 +2954,9 @@ def test_enumerator_size_kwsplat assert_equal([1, h2], c.to_enum(:each, **h2, &m).size) assert_equal([1, h3], c.to_enum(:each, **h3, &m).size) assert_equal([1, h3], c.to_enum(:each, a: 1, **h2, &m).size) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.to_enum(:each, h, &m).size) - end + assert_equal([h, kw], c.to_enum(:each, h, &m).size) assert_equal([h2, kw], c.to_enum(:each, h2, &m).size) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_equal([h2, h], c.to_enum(:each, h3, &m).size) - end + assert_equal([h3, kw], c.to_enum(:each, h3, &m).size) end def test_instance_exec_kwsplat @@ -3440,12 +2985,8 @@ def test_instance_exec_kwsplat assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } m = ->(args) { args } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } assert_equal(kw, c.instance_exec(kw, **kw, &m)) assert_equal(h, c.instance_exec(**h, &m)) assert_equal(h, c.instance_exec(a: 1, &m)) @@ -3461,36 +3002,18 @@ def test_instance_exec_kwsplat assert_equal(h2, c.instance_exec(**h2, &m)) assert_equal(h3, c.instance_exec(**h3, &m)) assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(h, &m) } assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end + assert_raise(ArgumentError) { c.instance_exec(h3, &m) } m = ->(arg, **args) { [arg, args] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) assert_equal([h3, kw], c.instance_exec(h3, &m)) @@ -3503,13 +3026,9 @@ def test_instance_exec_kwsplat assert_equal([1, h2], c.instance_exec(**h2, &m)) assert_equal([1, h3], c.instance_exec(**h3, &m)) assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end + assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end + assert_equal([h3, kw], c.instance_exec(h3, &m)) end def test_instance_exec_method_kwsplat @@ -3548,12 +3067,8 @@ def c.m(args) args end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } assert_equal(kw, c.instance_exec(kw, **kw, &m)) assert_equal(h, c.instance_exec(**h, &m)) assert_equal(h, c.instance_exec(a: 1, &m)) @@ -3573,40 +3088,22 @@ def c.m(**args) assert_equal(h2, c.instance_exec(**h2, &m)) assert_equal(h3, c.instance_exec(**h3, &m)) assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(h, &m) } assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end + assert_raise(ArgumentError) { c.instance_exec(h3, &m) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) assert_equal([h3, kw], c.instance_exec(h3, &m)) @@ -3623,13 +3120,9 @@ def c.m(arg=1, **args) assert_equal([1, h2], c.instance_exec(**h2, &m)) assert_equal([1, h3], c.instance_exec(**h3, &m)) assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end + assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end + assert_equal([h3, kw], c.instance_exec(h3, &m)) end def test_instance_exec_define_method_kwsplat @@ -3668,12 +3161,8 @@ def test_instance_exec_define_method_kwsplat args end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } assert_equal(kw, c.instance_exec(kw, **kw, &m)) assert_equal(h, c.instance_exec(**h, &m)) assert_equal(h, c.instance_exec(a: 1, &m)) @@ -3693,40 +3182,22 @@ def test_instance_exec_define_method_kwsplat assert_equal(h2, c.instance_exec(**h2, &m)) assert_equal(h3, c.instance_exec(**h3, &m)) assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(h, &m) } assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end + assert_raise(ArgumentError) { c.instance_exec(h3, &m) } c.singleton_class.remove_method(:m) c.define_singleton_method(:m) do |arg, **args| [arg, args] end m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end + assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } + assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } + assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } + assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) assert_equal([h3, kw], c.instance_exec(h3, &m)) @@ -3743,13 +3214,9 @@ def test_instance_exec_define_method_kwsplat assert_equal([1, h2], c.instance_exec(**h2, &m)) assert_equal([1, h3], c.instance_exec(**h3, &m)) assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end + assert_equal([h, kw], c.instance_exec(h, &m)) assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end + assert_equal([h3, kw], c.instance_exec(h3, &m)) end def test_instance_exec_sym_proc_kwsplat @@ -3785,12 +3252,8 @@ def c.m def c.m(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(c, **{}, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(c, **kw, &:m)) - end + assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) } assert_equal(kw, c.instance_exec(c, kw, **kw, &:m)) assert_equal(h, c.instance_exec(c, **h, &:m)) assert_equal(h, c.instance_exec(c, a: 1, &:m)) @@ -3809,39 +3272,21 @@ def c.m(**args) assert_equal(h2, c.instance_exec(c, **h2, &:m)) assert_equal(h3, c.instance_exec(c, **h3, &:m)) assert_equal(h3, c.instance_exec(c, a: 1, **h2, &:m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(c, h, &:m)) - end + assert_raise(ArgumentError) { c.instance_exec(c, h, &:m) } assert_raise(ArgumentError) { c.instance_exec(c, h2, &:m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) } - end + assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) } c.singleton_class.remove_method(:m) def c.m(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(c, **{}, &:m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(c, **kw, &:m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(c, **h, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(c, a: 1, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(c, **h2, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(c, **h3, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(c, a: 1, **h2, &:m)) - end + assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, **h, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, a: 1, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, **h2, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, **h3, &:m) } + assert_raise(ArgumentError) { c.instance_exec(c, a: 1, **h2, &:m) } assert_equal([h, kw], c.instance_exec(c, h, &:m)) assert_equal([h2, kw], c.instance_exec(c, h2, &:m)) assert_equal([h3, kw], c.instance_exec(c, h3, &:m)) @@ -3857,13 +3302,9 @@ def c.m(arg=1, **args) assert_equal([1, h2], c.instance_exec(c, **h2, &:m)) assert_equal([1, h3], c.instance_exec(c, **h3, &:m)) assert_equal([1, h3], c.instance_exec(c, a: 1, **h2, &:m)) - assert_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(c, h, &:m)) - end + assert_equal([h, kw], c.instance_exec(c, h, &:m)) assert_equal([h2, kw], c.instance_exec(c, h2, &:m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(c, h3, &:m)) - end + assert_equal([h3, kw], c.instance_exec(c, h3, &:m)) end def test_rb_yield_block_kwsplat @@ -3902,12 +3343,8 @@ def c.c; end def c.c(args) args end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal(kw, c.m(:c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal(kw, c.m(:c, **kw)) - end + assert_raise(ArgumentError) { c.m(:c, **{}) } + assert_raise(ArgumentError) { c.m(:c, **kw) } assert_equal(kw, c.m(:c, kw, **kw)) assert_equal(h, c.m(:c, **h)) assert_equal(h, c.m(:c, a: 1)) @@ -3927,39 +3364,21 @@ def c.c(**args) assert_equal([h2, h2], c.m(:c, **h2, &m)) assert_equal([h3, h3], c.m(:c, **h3, &m)) assert_equal([h3, h3], c.m(:c, a: 1, **h2, &m)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([h, h], c.m(:c, h, &m)) - end + assert_raise(ArgumentError) { c.m(:c, h, &m) } assert_raise(ArgumentError) { c.m(:c, h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do - assert_raise(ArgumentError) { c.m(:c, h3, &m) } - end + assert_raise(ArgumentError) { c.m(:c, h3, &m) } c.singleton_class.remove_method(:c) def c.c(arg, **args) [arg, args] end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([kw, kw], c.m(:c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([kw, kw], c.m(:c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h, kw], c.m(:c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h, kw], c.m(:c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h2, kw], c.m(:c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h3, kw], c.m(:c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h3, kw], c.m(:c, a: 1, **h2)) - end + assert_raise(ArgumentError) { c.m(:c, **{}, &m) } + assert_raise(ArgumentError) { c.m(:c, **kw, &m) } + assert_raise(ArgumentError) { c.m(:c, **h, &m) } + assert_raise(ArgumentError) { c.m(:c, a: 1, &m) } + assert_raise(ArgumentError) { c.m(:c, **h2, &m) } + assert_raise(ArgumentError) { c.m(:c, **h3, &m) } + assert_raise(ArgumentError) { c.m(:c, a: 1, **h2, &m) } assert_equal([h, kw], c.m(:c, h)) assert_equal([h2, kw], c.m(:c, h2)) assert_equal([h3, kw], c.m(:c, h3)) @@ -3975,13 +3394,9 @@ def c.c(arg=1, **args) assert_equal([1, h2], c.m(:c, **h2)) assert_equal([1, h3], c.m(:c, **h3)) assert_equal([1, h3], c.m(:c, a: 1, **h2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([1, h], c.m(:c, h)) - end + assert_equal([h, kw], c.m(:c, h)) assert_equal([h2, kw], c.m(:c, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([h2, h], c.m(:c, h3)) - end + assert_equal([h3, kw], c.m(:c, h3)) end def p1 @@ -4109,25 +3524,21 @@ def rest_keyrest(*args, **opt) def test_rest_keyrest bug7665 = '[ruby-core:51278]' bug8463 = '[ruby-core:55203] [Bug #8463]' - expect = [*%w[foo bar], {zzz: 42}] - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `rest_keyrest'/m) do - assert_equal(expect, rest_keyrest(*expect), bug7665) - end + a = [*%w[foo bar], {zzz: 42}] + splat_expect = a + [{}] + nonsplat_expect = [a, {}] + assert_equal(splat_expect, rest_keyrest(*a), bug7665) + assert_equal(nonsplat_expect, rest_keyrest(a), bug7665) + pr = proc {|*args, **opt| next *args, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(*expect), bug7665) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(expect), bug8463) - end + assert_equal(splat_expect, pr.call(*a), bug7665) + assert_equal(nonsplat_expect, pr.call(a), bug8463) + pr = proc {|a, *b, **opt| next a, *b, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(expect), bug8463) - end + assert_equal(splat_expect, pr.call(a), bug8463) + pr = proc {|a, **opt| next a, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) - end + assert_equal(splat_expect.values_at(0, -1), pr.call(splat_expect), bug8463) end def req_plus_keyword(x, **h) @@ -4142,16 +3553,10 @@ def splat_plus_keyword(*a, **h) [a, h] end - def test_keyword_split - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{:a=>1}, {}], req_plus_keyword(:a=>1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{"a"=>1}, {}], req_plus_keyword("a"=>1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword("a"=>1, :a=>1)) - end + def test_keyword_no_split + assert_raise(ArgumentError) { req_plus_keyword(:a=>1) } + assert_raise(ArgumentError) { req_plus_keyword("a"=>1) } + assert_raise(ArgumentError) { req_plus_keyword("a"=>1, :a=>1) } assert_equal([{:a=>1}, {}], req_plus_keyword({:a=>1})) assert_equal([{"a"=>1}, {}], req_plus_keyword({"a"=>1})) assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword({"a"=>1, :a=>1})) @@ -4159,24 +3564,16 @@ def test_keyword_split assert_equal([1, {:a=>1}], opt_plus_keyword(:a=>1)) assert_equal([1, {"a"=>1}], opt_plus_keyword("a"=>1)) assert_equal([1, {"a"=>1, :a=>1}], opt_plus_keyword("a"=>1, :a=>1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do - assert_equal([1, {:a=>1}], opt_plus_keyword({:a=>1})) - end + assert_equal([{:a=>1}, {}], opt_plus_keyword({:a=>1})) assert_equal([{"a"=>1}, {}], opt_plus_keyword({"a"=>1})) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do - assert_equal([{"a"=>1}, {:a=>1}], opt_plus_keyword({"a"=>1, :a=>1})) - end + assert_equal([{"a"=>1, :a=>1}, {}], opt_plus_keyword({"a"=>1, :a=>1})) assert_equal([[], {:a=>1}], splat_plus_keyword(:a=>1)) assert_equal([[], {"a"=>1}], splat_plus_keyword("a"=>1)) assert_equal([[], {"a"=>1, :a=>1}], splat_plus_keyword("a"=>1, :a=>1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do - assert_equal([[], {:a=>1}], splat_plus_keyword({:a=>1})) - end + assert_equal([[{:a=>1}], {}], splat_plus_keyword({:a=>1})) assert_equal([[{"a"=>1}], {}], splat_plus_keyword({"a"=>1})) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do - assert_equal([[{"a"=>1}], {:a=>1}], splat_plus_keyword({"a"=>1, :a=>1})) - end + assert_equal([[{"a"=>1, :a=>1}], {}], splat_plus_keyword({"a"=>1, :a=>1})) end def test_bare_kwrest @@ -4313,6 +3710,25 @@ def foo(*args, bar: 'x') assert_equal([42, {:bar=>"x"}], b.new.foo(42), bug8236) end + def test_super_with_keyword_kwrest + base = Class.new do + def foo(**h) + h + end + end + a = Class.new(base) do + attr_reader :h + def foo(a:, b:, **h) + @h = h + super + end + end + + o = a.new + assert_equal({a: 1, b: 2, c: 3}, o.foo(a: 1, b: 2, c: 3)) + assert_equal({c: 3}, o.h) + end + def test_zsuper_only_named_kwrest bug8416 = '[ruby-core:55033] [Bug #8416]' base = Class.new do @@ -4321,11 +3737,15 @@ def foo(**h) end end a = Class.new(base) do + attr_reader :h def foo(**h) + @h = h super end end - assert_equal({:bar=>"x"}, a.new.foo(bar: "x"), bug8416) + o = a.new + assert_equal({:bar=>"x"}, o.foo(bar: "x"), bug8416) + assert_equal({:bar=>"x"}, o.h) end def test_zsuper_only_anonymous_kwrest @@ -4355,15 +3775,12 @@ def foo(x, **h) end def test_precedence_of_keyword_arguments_with_post_argument - bug8993 = '[ruby-core:57706] [Bug #8993]' a = Class.new do def foo(a, b, c=1, *d, e, f:2, **g) [a, b, c, d, e, f, g] end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `foo'/m) do - assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993) - end + assert_raise(ArgumentError) { a.new.foo(1, 2, f:5) } end def test_splat_keyword_nondestructive @@ -4390,18 +3807,12 @@ def o2.to_hash() { b: 2 } end assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898) end - def test_implicit_hash_conversion - bug10016 = '[ruby-core:63593] [Bug #10016]' - + def test_no_implicit_hash_conversion o = Object.new def o.to_hash() { k: 9 } end assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do - assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do - assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016) - end + assert_equal([1, 0], m1(1, o) {|a, k: 0| break [a, k]}) + assert_raise(ArgumentError) { m1(1, o, &->(a, k: 0) {break [a, k]}) } end def test_splat_hash @@ -4412,7 +3823,7 @@ def m.f2(a = nil) a; end def m.f3(**a) a; end def m.f4(*a) a; end o = {a: 1} - assert_raise_with_message(ArgumentError, /unknown keyword: :a/) { + assert_raise_with_message(ArgumentError, /wrong number of arguments \(given 1, expected 0\)/) { m.f(**o) } o = {} @@ -4520,7 +3931,7 @@ def m(a) yield a end def test_nonsymbol_key result = m(["a" => 10]) { |a = nil, **b| [a, b] } - assert_equal([{"a" => 10}, {}], result) + assert_equal([[{"a" => 10}], {}], result) end def method_for_test_to_hash_call_during_setup_complex_parameters k1:, k2:, **rest_kw @@ -4705,22 +4116,12 @@ def c.m; end assert_raise(ArgumentError) { c.call(**h3, &:m) } assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - redef = -> do - c.singleton_class.remove_method(:m) - eval <<-END - def c.m(args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.call(**kw, &:m)) + c.singleton_class.remove_method(:m) + def c.m(args) + args end + assert_raise(ArgumentError) { c.call(**{}, &:m) } + assert_raise(ArgumentError) { c.call(**kw, &:m) } assert_equal(h, c.call(**h, &:m)) assert_equal(h, c.call(a: 1, &:m)) assert_equal(h2, c.call(**h2, &:m)) @@ -4738,50 +4139,21 @@ def c.m(**args) assert_equal(h2, c.call(**h2, &:m)) assert_equal(h3, c.call(**h3, &:m)) assert_equal(h3, c.call(a: 1, **h2, &:m)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m)) - end + assert_raise(ArgumentError) { c.call(h, &:m) } assert_raise(ArgumentError) { c.call(h2, &:m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m) } - end + assert_raise(ArgumentError) { c.call(h3, &:m) } - redef = -> do - c.singleton_class.remove_method(:m) - eval <<-END - def c.m(arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.call(**kw, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.call(**h, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.call(a: 1, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.call(**h2, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.call(**h3, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m)) + c.singleton_class.remove_method(:m) + def c.m(arg, **args) + [arg, args] end + assert_raise(ArgumentError) { c.call(**{}, &:m) } + assert_raise(ArgumentError) { c.call(**kw, &:m) } + assert_raise(ArgumentError) { c.call(**h, &:m) } + assert_raise(ArgumentError) { c.call(a: 1, &:m) } + assert_raise(ArgumentError) { c.call(**h2, &:m) } + assert_raise(ArgumentError) { c.call(**h3, &:m) } + assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } c.singleton_class.remove_method(:m) def c.m(arg=1, **args) @@ -4825,22 +4197,12 @@ def c.method_missing(_) end assert_raise(ArgumentError) { c.call(**h3, &:m) } assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**kw, &:m)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, args) + args end + assert_raise(ArgumentError) { c.call(**{}, &:m) } + assert_raise(ArgumentError) { c.call(**kw, &:m) } assert_equal(h, c.call(**h, &:m)) assert_equal(h, c.call(a: 1, &:m)) assert_equal(h2, c.call(**h2, &:m)) @@ -4858,50 +4220,21 @@ def c.method_missing(_, **args) assert_equal(h2, c.call(**h2, &:m)) assert_equal(h3, c.call(**h3, &:m)) assert_equal(h3, c.call(a: 1, **h2, &:m)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m2)) - end + assert_raise(ArgumentError) { c.call(h, &:m2) } assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m2) } - end + assert_raise(ArgumentError) { c.call(h3, &:m2) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**kw, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(**h, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(a: 1, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.call(**h2, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(**h3, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, arg, **args) + [arg, args] end + assert_raise(ArgumentError) { c.call(**{}, &:m2) } + assert_raise(ArgumentError) { c.call(**kw, &:m2) } + assert_raise(ArgumentError) { c.call(**h, &:m2) } + assert_raise(ArgumentError) { c.call(a: 1, &:m2) } + assert_raise(ArgumentError) { c.call(**h2, &:m2) } + assert_raise(ArgumentError) { c.call(**h3, &:m2) } + assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg=1, **args) @@ -4945,22 +4278,12 @@ def c.method_missing(_) end assert_raise(ArgumentError) { c.call(**h3, &:m2) } assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**{}, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**kw, &:m2)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, args) + args end + assert_raise(ArgumentError) { c.call(**{}, &:m2) } + assert_raise(ArgumentError) { c.call(**kw, &:m2) } assert_equal(h, c.call(**h, &:m2)) assert_equal(h, c.call(a: 1, &:m2)) assert_equal(h2, c.call(**h2, &:m2)) @@ -4978,50 +4301,21 @@ def c.method_missing(_, **args) assert_equal(h2, c.call(**h2, &:m2)) assert_equal(h3, c.call(**h3, &:m2)) assert_equal(h3, c.call(a: 1, **h2, &:m2)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m2)) - end + assert_raise(ArgumentError) { c.call(h, &:m2) } assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m2) } - end + assert_raise(ArgumentError) { c.call(h3, &:m2) } - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**{}, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**kw, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(**h, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(a: 1, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.call(**h2, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(**h3, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m2)) + c.singleton_class.remove_method(:method_missing) + def c.method_missing(_, arg, **args) + [arg, args] end + assert_raise(ArgumentError) { c.call(**{}, &:m2) } + assert_raise(ArgumentError) { c.call(**kw, &:m2) } + assert_raise(ArgumentError) { c.call(**h, &:m2) } + assert_raise(ArgumentError) { c.call(a: 1, &:m2) } + assert_raise(ArgumentError) { c.call(**h2, &:m2) } + assert_raise(ArgumentError) { c.call(**h3, &:m2) } + assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } c.singleton_class.remove_method(:method_missing) def c.method_missing(_, arg=1, **args) @@ -5052,17 +4346,26 @@ def bar(x, y) end end - def test_ruby2_keywords_hash_empty_kw_splat - def self.foo(*a) a.last end - singleton_class.send(:ruby2_keywords, :foo) - bug16642 = '[ruby-core:97203] [Bug #16642]' + def test_splat_fixnum + bug16603 = '[ruby-core:97047] [Bug #16603]' + assert_raise(TypeError, bug16603) { p(**42) } + assert_raise(TypeError, bug16603) { p(k:1, **42) } + end + + def test_value_omission + f = ->(**kwargs) { kwargs } + x = 1 + y = 2 + assert_equal({x: 1, y: 2}, f.call(x:, y:)) + assert_equal({x: 1, y: 2, z: 3}, f.call(x:, y:, z: 3)) + assert_equal({one: 1, two: 2}, f.call(one:, two:)) + end - res = foo(**{}) - assert_equal({}, res, bug16642) - assert_equal(false, res.frozen?, bug16642) + private def one + 1 + end - res = foo(*[], **{}) - assert_equal({}, res, bug16642) - assert_equal(false, res.frozen?, bug16642) + private def two + 2 end end diff --git a/ruby/test/ruby/test_lambda.rb b/ruby/test/ruby/test_lambda.rb index 03b501a6c..9949fab8c 100644 --- a/ruby/test/ruby/test_lambda.rb +++ b/ruby/test/ruby/test_lambda.rb @@ -74,6 +74,109 @@ def test_call_block_from_lambda assert_raise(ArgumentError, bug9605) {proc(&plus).call [1,2]} end + def test_proc_inside_lambda_inside_method_return_inside_lambda_inside_method + def self.a + -> do + p = Proc.new{return :a} + p.call + end.call + end + assert_equal(:a, a) + + def self.b + lambda do + p = Proc.new{return :b} + p.call + end.call + end + assert_equal(:b, b) + end + + def test_proc_inside_lambda_inside_method_return_inside_lambda_outside_method + def self.a + -> do + p = Proc.new{return :a} + p.call + end + end + assert_equal(:a, a.call) + + def self.b + lambda do + p = Proc.new{return :b} + p.call + end + end + assert_equal(:b, b.call) + end + + def test_proc_inside_lambda_inside_method_return_outside_lambda_inside_method + def self.a + -> do + Proc.new{return :a} + end.call.call + end + assert_raise(LocalJumpError) {a} + + def self.b + lambda do + Proc.new{return :b} + end.call.call + end + assert_raise(LocalJumpError) {b} + end + + def test_proc_inside_lambda_inside_method_return_outside_lambda_outside_method + def self.a + -> do + Proc.new{return :a} + end + end + assert_raise(LocalJumpError) {a.call.call} + + def self.b + lambda do + Proc.new{return :b} + end + end + assert_raise(LocalJumpError) {b.call.call} + end + + def test_proc_inside_lambda2_inside_method_return_outside_lambda1_inside_method + def self.a + -> do + -> do + Proc.new{return :a} + end.call.call + end.call + end + assert_raise(LocalJumpError) {a} + + def self.b + lambda do + lambda do + Proc.new{return :a} + end.call.call + end.call + end + assert_raise(LocalJumpError) {b} + end + + def test_proc_inside_lambda_toplevel + assert_separately [], <<~RUBY + lambda{ + $g = proc{ return :pr } + }.call + begin + $g.call + rescue LocalJumpError + # OK! + else + raise + end + RUBY + end + def pass_along(&block) lambda(&block) end @@ -83,15 +186,21 @@ def pass_along2(&block) end def test_create_non_lambda_for_proc_one_level + prev_warning, Warning[:deprecated] = Warning[:deprecated], false f = pass_along {} refute_predicate(f, :lambda?, '[Bug #15620]') assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } + ensure + Warning[:deprecated] = prev_warning end def test_create_non_lambda_for_proc_two_levels + prev_warning, Warning[:deprecated] = Warning[:deprecated], false f = pass_along2 {} refute_predicate(f, :lambda?, '[Bug #15620]') assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } + ensure + Warning[:deprecated] = prev_warning end def test_instance_exec diff --git a/ruby/test/ruby/test_lazy_enumerator.rb b/ruby/test/ruby/test_lazy_enumerator.rb index 6e5c1714a..2116d0ee3 100644 --- a/ruby/test/ruby/test_lazy_enumerator.rb +++ b/ruby/test/ruby/test_lazy_enumerator.rb @@ -160,6 +160,10 @@ def test_flat_map_hash assert_equal([{?a=>97}, {?b=>98}, {?c=>99}], [?a, ?b, ?c].lazy.flat_map {|x| {x=>x.ord}}.force) end + def test_flat_map_take + assert_equal([1,2]*3, [[1,2]].cycle.lazy.take(3).flat_map {|x| x}.to_a) + end + def test_reject a = Step.new(1..6) assert_equal(4, a.reject {|x| x < 4}.first) @@ -678,4 +682,8 @@ def test_with_index ary = (0..Float::INFINITY).lazy.with_index.take(2).to_a assert_equal([[0, 0], [1, 1]], ary) end + + def test_with_index_size + assert_equal(3, Enumerator::Lazy.new([1, 2, 3], 3){|y, v| y << v}.with_index.size) + end end diff --git a/ruby/test/ruby/test_literal.rb b/ruby/test/ruby/test_literal.rb index 7f4a329c4..99dd3a0c5 100644 --- a/ruby/test/ruby/test_literal.rb +++ b/ruby/test/ruby/test_literal.rb @@ -26,7 +26,7 @@ def test_special_const assert_equal '5', 0b101.inspect assert_instance_of Integer, 0b101 assert_raise(SyntaxError) { eval("0b") } - assert_equal '123456789012345678901234567890', 123456789012345678901234567890.inspect + assert_equal '123456789012345678901234567890', 123456789012345678901234567890.to_s assert_instance_of Integer, 123456789012345678901234567890 assert_instance_of Float, 1.3 assert_equal '2', eval("0x00+2").inspect @@ -187,14 +187,14 @@ def test_frozen_string_in_array_literal if defined?(RubyVM::InstructionSequence.compile_option) and RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal) def test_debug_frozen_string - src = 'n = 1; _="foo#{n ? "-#{n}" : ""}"'; f = "test.rb"; n = 1 + src = '_="foo-1"'; f = "test.rb"; n = 1 opt = {frozen_string_literal: true, debug_frozen_string_literal: true} str = RubyVM::InstructionSequence.compile(src, f, f, n, **opt).eval assert_equal("foo-1", str) assert_predicate(str, :frozen?) assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) { str << "x" - } + } unless ENV['RUBY_ISEQ_DUMP_DEBUG'] end def test_debug_frozen_string_in_array_literal @@ -461,17 +461,46 @@ def test_big_hash_literal def test_hash_duplicated_key h = EnvUtil.suppress_warning do - eval <<~end + eval "#{<<-"begin;"}\n#{<<-'end;'}" + begin; # This is a syntax that renders warning at very early stage. # eval used to delay warning, to be suppressible by EnvUtil. {"a" => 100, "b" => 200, "a" => 300, "a" => 400} - end + end; end assert_equal(2, h.size) assert_equal(400, h['a']) assert_equal(200, h['b']) assert_nil(h['c']) assert_equal(nil, h.key('300')) + + a = [] + h = EnvUtil.suppress_warning do + eval <<~end + # This is a syntax that renders warning at very early stage. + # eval used to delay warning, to be suppressible by EnvUtil. + {"a" => a.push(100).last, "b" => a.push(200).last, "a" => a.push(300).last, "a" => a.push(400).last} + end + end + assert_equal({'a' => 400, 'b' => 200}, h) + assert_equal([100, 200, 300, 400], a) + + assert_all_assertions_foreach( + "duplicated literal key", + ':foo', + '"a"', + '1000', + '1.0', + '1_000_000_000_000_000_000_000', + '1.0r', + '1.0i', + '1.72723e-77', + '//', + ) do |key| + assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) do + eval("{#{key} => :bar, #{key} => :foo}") + end + end end def test_hash_frozen_key_id @@ -488,6 +517,30 @@ def test_hash_key_tampering assert_equal(100, h['a']) end + FOO = "foo" + + def test_hash_value_omission + x = 1 + y = 2 + assert_equal({x: 1, y: 2}, {x:, y:}) + assert_equal({x: 1, y: 2, z: 3}, {x:, y:, z: 3}) + assert_equal({one: 1, two: 2}, {one:, two:}) + b = binding + b.local_variable_set(:if, "if") + b.local_variable_set(:self, "self") + assert_equal({FOO: "foo", if: "if", self: "self"}, + eval('{FOO:, if:, self:}', b)) + assert_syntax_error('{"#{x}":}', /'\}'/) + end + + private def one + 1 + end + + private def two + 2 + end + def test_range assert_instance_of Range, (1..2) assert_equal(1..2, 1..2) diff --git a/ruby/test/ruby/test_m17n.rb b/ruby/test/ruby/test_m17n.rb index 6c7d0e6ba..c793520ac 100644 --- a/ruby/test/ruby/test_m17n.rb +++ b/ruby/test/ruby/test_m17n.rb @@ -299,6 +299,9 @@ def test_object_inspect_external orig_v, $VERBOSE = $VERBOSE, false orig_int, Encoding.default_internal = Encoding.default_internal, nil orig_ext = Encoding.default_external + + skip "https://bugs.ruby-lang.org/issues/18338" + o = Object.new Encoding.default_external = Encoding::UTF_16BE @@ -310,6 +313,7 @@ def o.inspect def o.inspect "abc".encode(Encoding.default_external) end + assert_equal '[abc]', [o].inspect Encoding.default_external = Encoding::US_ASCII @@ -1324,10 +1328,14 @@ def test_marshal end def test_env - locale_encoding = Encoding.find("locale") + if RUBY_PLATFORM =~ /bccwin|mswin|mingw/ + env_encoding = Encoding::UTF_8 + else + env_encoding = Encoding.find("locale") + end ENV.each {|k, v| - assert_equal(locale_encoding, k.encoding, k) - assert_equal(locale_encoding, v.encoding, v) + assert_equal(env_encoding, k.encoding, proc {"key(#{k.encoding})=#{k.dump}"}) + assert_equal(env_encoding, v.encoding, proc {"key(#{k.encoding})=#{k.dump}\n" "value(#{v.encoding})=#{v.dump}"}) } end diff --git a/ruby/test/ruby/test_m17n_comb.rb b/ruby/test/ruby/test_m17n_comb.rb index cfb8bff88..e48a1948b 100644 --- a/ruby/test/ruby/test_m17n_comb.rb +++ b/ruby/test/ruby/test_m17n_comb.rb @@ -593,6 +593,21 @@ def test_str_casecmp } end + def test_str_casecmp? + strings = STRINGS.dup + strings.push( + # prevent wrong single byte optimization + "\xC0".force_encoding("ISO-8859-1"), + "\xE0".force_encoding("ISO-8859-1"), + ) + combination(strings, strings) {|s1, s2| + #puts "#{encdump(s1)}.casecmp(#{encdump(s2)})" + next unless s1.valid_encoding? && s2.valid_encoding? && Encoding.compatible?(s1, s2) + r = s1.casecmp?(s2) + assert_equal(s1.downcase(:fold) == s2.downcase(:fold), r) + } + end + def test_str_center combination(STRINGS, [0,1,2,3,10]) {|s1, width| t = s1.center(width) @@ -751,8 +766,14 @@ def crypt_supports_des_crypt? # glibc 2.16 or later denies salt contained other than [0-9A-Za-z./] #7312 # we use this check to test strict and non-strict behavior separately #11045 strict_crypt = if defined? Etc::CS_GNU_LIBC_VERSION - glibcver = Etc.confstr(Etc::CS_GNU_LIBC_VERSION).scan(/\d+/).map(&:to_i) - (glibcver <=> [2, 16]) >= 0 + begin + confstr = Etc.confstr(Etc::CS_GNU_LIBC_VERSION) + rescue Errno::EINVAL + false + else + glibcver = confstr.scan(/\d+/).map(&:to_i) + (glibcver <=> [2, 16]) >= 0 + end end def test_str_crypt diff --git a/ruby/test/ruby/test_marshal.rb b/ruby/test/ruby/test_marshal.rb index f300710d2..361d18dd4 100644 --- a/ruby/test/ruby/test_marshal.rb +++ b/ruby/test/ruby/test_marshal.rb @@ -8,7 +8,6 @@ class TestMarshal < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -59,6 +58,8 @@ def test_inconsistent_struct TestMarshal.instance_eval { remove_const :StructOrNot } TestMarshal.const_set :StructOrNot, Class.new assert_raise(TypeError, "[ruby-dev:31709]") { Marshal.load(s) } + ensure + TestMarshal.instance_eval { remove_const :StructOrNot } end def test_struct_invalid_members @@ -67,6 +68,8 @@ def test_struct_invalid_members Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo") TestMarshal::StructInvalidMembers.members } + ensure + TestMarshal.instance_eval { remove_const :StructInvalidMembers } end class C @@ -157,20 +160,29 @@ def test_modify_array_during_dump end def test_change_class_name + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) eval("class C3; def _dump(s); 'foo'; end; end") m = Marshal.dump(C3.new) assert_raise(TypeError) { Marshal.load(m) } + self.class.__send__(:remove_const, :C3) eval("C3 = nil") assert_raise(TypeError) { Marshal.load(m) } + ensure + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) end def test_change_struct + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) eval("C3 = Struct.new(:foo, :bar)") m = Marshal.dump(C3.new("FOO", "BAR")) + self.class.__send__(:remove_const, :C3) eval("C3 = Struct.new(:foo)") assert_raise(TypeError) { Marshal.load(m) } + self.class.__send__(:remove_const, :C3) eval("C3 = Struct.new(:foo, :baz)") assert_raise(TypeError) { Marshal.load(m) } + ensure + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) end class C4 @@ -542,7 +554,7 @@ def test_module_ivar end class TestForRespondToFalse - def respond_to?(a) + def respond_to?(a, priv = false) false end end @@ -570,7 +582,7 @@ def marshal_load(v) end def test_continuation - require "continuation" + EnvUtil.suppress_warning {require "continuation"} c = Bug9523.new assert_raise_with_message(RuntimeError, /Marshal\.dump reentered at marshal_dump/) do Marshal.dump(c) @@ -596,7 +608,8 @@ def test_undumpable_data end def test_unloadable_data - c = eval("class Unloadable\u{23F0 23F3}(v) { v == str ? v.upcase : v })) end + def test_marshal_proc_string_encoding + string = "foo" + payload = Marshal.dump(string) + Marshal.load(payload, ->(v) { + if v.is_a?(String) + assert_equal(string, v) + assert_equal(string.encoding, v.encoding) + end + v + }) + end + + def test_marshal_proc_freeze + object = { foo: [42, "bar"] } + assert_equal object, Marshal.load(Marshal.dump(object), :freeze.to_proc) + end + def test_marshal_load_extended_class_crash assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") begin; @@ -753,4 +795,136 @@ def test_marshal_dump_removing_instance_variable Marshal.dump(obj) end end + + ruby2_keywords def ruby2_keywords_hash(*a) + a.last + end + + def ruby2_keywords_test(key: 1) + key + end + + def test_marshal_with_ruby2_keywords_hash + flagged_hash = ruby2_keywords_hash(key: 42) + data = Marshal.dump(flagged_hash) + hash = Marshal.load(data) + assert_equal(42, ruby2_keywords_test(*[hash])) + + hash2 = Marshal.load(data.sub(/\x06K(?=T\z)/, "\x08KEY")) + assert_raise(ArgumentError, /\(given 1, expected 0\)/) { + ruby2_keywords_test(*[hash2]) + } + hash2 = Marshal.load(data.sub(/:\x06K(?=T\z)/, "I\\&\x06:\x0dencoding\"\x0aUTF-7")) + assert_raise(ArgumentError, /\(given 1, expected 0\)/) { + ruby2_keywords_test(*[hash2]) + } + end + + def test_invalid_byte_sequence_symbol + data = Marshal.dump(:K) + data = data.sub(/:\x06K/, "I\\&\x06:\x0dencoding\"\x0dUTF-16LE") + assert_raise(ArgumentError, /UTF-16LE: "\\x4B"/) { + Marshal.load(data) + } + end + + def exception_test + raise + end + + def test_marshal_exception + begin + exception_test + rescue => e + e2 = Marshal.load(Marshal.dump(e)) + assert_equal(e.message, e2.message) + assert_equal(e.backtrace, e2.backtrace) + assert_nil(e2.backtrace_locations) # temporal + end + end + + def nameerror_test + unknown_method + end + + def test_marshal_nameerror + begin + nameerror_test + rescue NameError => e + e2 = Marshal.load(Marshal.dump(e)) + assert_equal(e.message.lines.first.chomp, e2.message.lines.first) + assert_equal(e.name, e2.name) + assert_equal(e.backtrace, e2.backtrace) + assert_nil(e2.backtrace_locations) # temporal + end + end + + class TestMarshalFreezeProc < Test::Unit::TestCase + include MarshalTestLib + + def encode(o) + Marshal.dump(o) + end + + def decode(s) + Marshal.load(s, :freeze.to_proc) + end + end + + def _test_hash_compared_by_identity(h) + h.compare_by_identity + h["a" + "0"] = 1 + h["a" + "0"] = 2 + h = Marshal.load(Marshal.dump(h)) + assert_predicate(h, :compare_by_identity?) + a = h.to_a + assert_equal([["a0", 1], ["a0", 2]], a.sort) + assert_not_same(a[1][0], a[0][0]) + end + + def test_hash_compared_by_identity + _test_hash_compared_by_identity(Hash.new) + end + + def test_hash_default_compared_by_identity + _test_hash_compared_by_identity(Hash.new(true)) + end + + class TestMarshalFreeze < Test::Unit::TestCase + include MarshalTestLib + + def encode(o) + Marshal.dump(o) + end + + def decode(s) + Marshal.load(s, freeze: true) + end + + def test_return_objects_are_frozen + source = ["foo", {}, /foo/, 1..2] + objects = decode(encode(source)) + assert_equal source, objects + assert_predicate objects, :frozen? + objects.each do |obj| + assert_predicate obj, :frozen? + end + end + + def test_proc_returned_object_are_not_frozen + source = ["foo", {}, /foo/, 1..2] + objects = Marshal.load(encode(source), ->(o) { o.dup }, freeze: true) + assert_equal source, objects + refute_predicate objects, :frozen? + objects.each do |obj| + refute_predicate obj, :frozen? + end + end + + def test_modules_and_classes_are_not_frozen + _objects = Marshal.load(encode([Object, Kernel]), freeze: true) + refute_predicate Object, :frozen? + refute_predicate Kernel, :frozen? + end + end end diff --git a/ruby/test/ruby/test_math.rb b/ruby/test/ruby/test_math.rb index 5cc12bcfe..73f44c6ae 100644 --- a/ruby/test/ruby/test_math.rb +++ b/ruby/test/ruby/test_math.rb @@ -73,9 +73,9 @@ def test_acos check(1 * Math::PI / 4, Math.acos( 1.0 / Math.sqrt(2))) check(2 * Math::PI / 4, Math.acos( 0.0)) check(4 * Math::PI / 4, Math.acos(-1.0)) - assert_raise(Math::DomainError) { Math.acos(+1.0 + Float::EPSILON) } - assert_raise(Math::DomainError) { Math.acos(-1.0 - Float::EPSILON) } - assert_raise(Math::DomainError) { Math.acos(2.0) } + assert_raise_with_message(Math::DomainError, /\bacos\b/) { Math.acos(+1.0 + Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\bacos\b/) { Math.acos(-1.0 - Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\bacos\b/) { Math.acos(2.0) } end def test_asin @@ -83,9 +83,9 @@ def test_asin check( 1 * Math::PI / 4, Math.asin( 1.0 / Math.sqrt(2))) check( 2 * Math::PI / 4, Math.asin( 1.0)) check(-2 * Math::PI / 4, Math.asin(-1.0)) - assert_raise(Math::DomainError) { Math.asin(+1.0 + Float::EPSILON) } - assert_raise(Math::DomainError) { Math.asin(-1.0 - Float::EPSILON) } - assert_raise(Math::DomainError) { Math.asin(2.0) } + assert_raise_with_message(Math::DomainError, /\basin\b/) { Math.asin(+1.0 + Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\basin\b/) { Math.asin(-1.0 - Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\basin\b/) { Math.asin(2.0) } end def test_atan @@ -119,8 +119,8 @@ def test_acosh check(0, Math.acosh(1)) check(1, Math.acosh((Math::E ** 1 + Math::E ** -1) / 2)) check(2, Math.acosh((Math::E ** 2 + Math::E ** -2) / 2)) - assert_raise(Math::DomainError) { Math.acosh(1.0 - Float::EPSILON) } - assert_raise(Math::DomainError) { Math.acosh(0) } + assert_raise_with_message(Math::DomainError, /\bacosh\b/) { Math.acosh(1.0 - Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\bacosh\b/) { Math.acosh(0) } end def test_asinh @@ -135,8 +135,8 @@ def test_atanh check(2, Math.atanh(Math.sinh(2) / Math.cosh(2))) assert_nothing_raised { assert_infinity(Math.atanh(1)) } assert_nothing_raised { assert_infinity(-Math.atanh(-1)) } - assert_raise(Math::DomainError) { Math.atanh(+1.0 + Float::EPSILON) } - assert_raise(Math::DomainError) { Math.atanh(-1.0 - Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\batanh\b/) { Math.atanh(+1.0 + Float::EPSILON) } + assert_raise_with_message(Math::DomainError, /\batanh\b/) { Math.atanh(-1.0 - Float::EPSILON) } end def test_exp @@ -157,10 +157,14 @@ def test_log assert_nothing_raised { assert_infinity(Math.log(1.0/0)) } assert_nothing_raised { assert_infinity(-Math.log(+0.0)) } assert_nothing_raised { assert_infinity(-Math.log(-0.0)) } - assert_raise(Math::DomainError) { Math.log(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(-Float::EPSILON) } assert_raise(TypeError) { Math.log(1,nil) } - assert_raise(Math::DomainError, '[ruby-core:62309] [ruby-Bug #9797]') { Math.log(1.0, -1.0) } + assert_raise_with_message(Math::DomainError, /\blog\b/, '[ruby-core:62309] [ruby-Bug #9797]') { Math.log(1.0, -1.0) } + assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(1.0, -Float::EPSILON) } assert_nothing_raised { assert_nan(Math.log(0.0, 0.0)) } + assert_nothing_raised { assert_nan(Math.log(Float::NAN)) } + assert_nothing_raised { assert_nan(Math.log(1.0, Float::NAN)) } end def test_log2 @@ -172,7 +176,9 @@ def test_log2 assert_nothing_raised { assert_infinity(Math.log2(1.0/0)) } assert_nothing_raised { assert_infinity(-Math.log2(+0.0)) } assert_nothing_raised { assert_infinity(-Math.log2(-0.0)) } - assert_raise(Math::DomainError) { Math.log2(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-Float::EPSILON) } + assert_nothing_raised { assert_nan(Math.log2(Float::NAN)) } end def test_log10 @@ -184,7 +190,9 @@ def test_log10 assert_nothing_raised { assert_infinity(Math.log10(1.0/0)) } assert_nothing_raised { assert_infinity(-Math.log10(+0.0)) } assert_nothing_raised { assert_infinity(-Math.log10(-0.0)) } - assert_raise(Math::DomainError) { Math.log10(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-1.0) } + assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-Float::EPSILON) } + assert_nothing_raised { assert_nan(Math.log10(Float::NAN)) } end def test_sqrt @@ -193,7 +201,9 @@ def test_sqrt check(2, Math.sqrt(4)) assert_nothing_raised { assert_infinity(Math.sqrt(1.0/0)) } assert_equal("0.0", Math.sqrt(-0.0).to_s) # insure it is +0.0, not -0.0 - assert_raise(Math::DomainError) { Math.sqrt(-1.0) } + assert_raise_with_message(Math::DomainError, /\bsqrt\b/) { Math.sqrt(-1.0) } + assert_raise_with_message(Math::DomainError, /\bsqrt\b/) { Math.sqrt(-Float::EPSILON) } + assert_nothing_raised { assert_nan(Math.sqrt(Float::NAN)) } end def test_cbrt @@ -201,8 +211,11 @@ def test_cbrt check(-2, Math.cbrt(-8)) check(3, Math.cbrt(27)) check(-0.1, Math.cbrt(-0.001)) + check(0.0, Math.cbrt(0.0)) assert_nothing_raised { assert_infinity(Math.cbrt(1.0/0)) } assert_operator(Math.cbrt(1.0 - Float::EPSILON), :<=, 1.0) + assert_nothing_raised { assert_nan(Math.sqrt(Float::NAN)) } + assert_nothing_raised { assert_nan(Math.cbrt(Float::NAN)) } end def test_frexp @@ -211,6 +224,7 @@ def test_frexp assert_float_and_int([0.5, 1], Math.frexp(1.0)) assert_float_and_int([0.5, 2], Math.frexp(2.0)) assert_float_and_int([0.75, 2], Math.frexp(3.0)) + assert_nan(Math.frexp(Float::NAN)[0]) end def test_ldexp @@ -228,11 +242,13 @@ def test_hypot def test_erf check(0, Math.erf(0)) check(1, Math.erf(1.0 / 0.0)) + assert_nan(Math.erf(Float::NAN)) end def test_erfc check(1, Math.erfc(0)) check(0, Math.erfc(1.0 / 0.0)) + assert_nan(Math.erfc(Float::NAN)) end def test_gamma @@ -257,11 +273,13 @@ def test_gamma assert_infinity(Math.gamma(i-1), "Math.gamma(#{i-1}) should be INF") end - assert_raise(Math::DomainError) { Math.gamma(-Float::INFINITY) } + assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-Float::INFINITY) } + assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-1.0) } x = Math.gamma(-0.0) mesg = "Math.gamma(-0.0) should be -INF" assert_infinity(x, mesg) assert_predicate(x, :negative?, mesg) + assert_nan(Math.gamma(Float::NAN)) end def test_lgamma @@ -277,12 +295,14 @@ def test_lgamma assert_float_and_int([Math.log(15 * sqrt_pi / 8), 1], Math.lgamma(3.5)) assert_float_and_int([Math.log(6), 1], Math.lgamma(4)) - assert_raise(Math::DomainError) { Math.lgamma(-Float::INFINITY) } + assert_raise_with_message(Math::DomainError, /\blgamma\b/) { Math.lgamma(-Float::INFINITY) } x, sign = Math.lgamma(-0.0) mesg = "Math.lgamma(-0.0) should be [INF, -1]" assert_infinity(x, mesg) assert_predicate(x, :positive?, mesg) assert_equal(-1, sign, mesg) + x, sign = Math.lgamma(Float::NAN) + assert_nan(x) end def test_fixnum_to_f diff --git a/ruby/test/ruby/test_memory_view.rb b/ruby/test/ruby/test_memory_view.rb new file mode 100644 index 000000000..5a39084d1 --- /dev/null +++ b/ruby/test/ruby/test_memory_view.rb @@ -0,0 +1,341 @@ +require "-test-/memory_view" +require "rbconfig/sizeof" + +class TestMemoryView < Test::Unit::TestCase + NATIVE_ENDIAN = MemoryViewTestUtils::NATIVE_ENDIAN + LITTLE_ENDIAN = :little_endian + BIG_ENDIAN = :big_endian + + %I(SHORT INT INT16 INT32 INT64 INTPTR LONG LONG_LONG FLOAT DOUBLE).each do |type| + name = :"#{type}_ALIGNMENT" + const_set(name, MemoryViewTestUtils.const_get(name)) + end + + def test_rb_memory_view_register_duplicated + assert_warning(/Duplicated registration of memory view to/) do + MemoryViewTestUtils.register(MemoryViewTestUtils::ExportableString) + end + end + + def test_rb_memory_view_register_nonclass + assert_raise(TypeError) do + MemoryViewTestUtils.register(Object.new) + end + end + + def sizeof(type) + RbConfig::SIZEOF[type.to_s] + end + + def test_rb_memory_view_item_size_from_format + [ + [nil, 1], ['c', 1], ['C', 1], + ['n', 2], ['v', 2], + ['l', 4], ['L', 4], ['N', 4], ['V', 4], ['f', 4], ['e', 4], ['g', 4], + ['q', 8], ['Q', 8], ['d', 8], ['E', 8], ['G', 8], + ['s', sizeof(:short)], ['S', sizeof(:short)], ['s!', sizeof(:short)], ['S!', sizeof(:short)], + ['i', sizeof(:int)], ['I', sizeof(:int)], ['i!', sizeof(:int)], ['I!', sizeof(:int)], + ['l!', sizeof(:long)], ['L!', sizeof(:long)], + ['q!', sizeof('long long')], ['Q!', sizeof('long long')], + ['j', sizeof(:intptr_t)], ['J', sizeof(:intptr_t)], + ].each do |format, expected| + actual, err = MemoryViewTestUtils.item_size_from_format(format) + assert_nil(err) + assert_equal(expected, actual, "rb_memory_view_item_size_from_format(#{format || 'NULL'}) == #{expected}") + end + end + + def test_rb_memory_view_item_size_from_format_composed + actual, = MemoryViewTestUtils.item_size_from_format("ccc") + assert_equal(3, actual) + + actual, = MemoryViewTestUtils.item_size_from_format("c3") + assert_equal(3, actual) + + actual, = MemoryViewTestUtils.item_size_from_format("fd") + assert_equal(12, actual) + + actual, = MemoryViewTestUtils.item_size_from_format("fx2d") + assert_equal(14, actual) + end + + def test_rb_memory_view_item_size_from_format_with_spaces + # spaces should be ignored + actual, = MemoryViewTestUtils.item_size_from_format("f x2 d") + assert_equal(14, actual) + end + + def test_rb_memory_view_item_size_from_format_error + assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccca")) + assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccc4a")) + end + + def test_rb_memory_view_parse_item_format + total_size, members, err = MemoryViewTestUtils.parse_item_format("ccc2f3x2d4q!<") + assert_equal(58, total_size) + assert_nil(err) + assert_equal([ + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1}, + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2}, + {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 4, size: 4, repeat: 3}, + {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 18, size: 8, repeat: 4}, + {format: 'q', native_size_p: true, endianness: :little_endian, offset: 50, size: sizeof('long long'), repeat: 1} + ], + members) + end + + def test_rb_memory_view_parse_item_format_with_alignment_signle + [ + ["c", false, NATIVE_ENDIAN, 1, 1, 1], + ["C", false, NATIVE_ENDIAN, 1, 1, 1], + ["s", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], + ["S", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], + ["s!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], + ["S!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], + ["n", false, :big_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1], + ["v", false, :little_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1], + ["i", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], + ["I", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], + ["i!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], + ["I!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], + ["l", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1], + ["L", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1], + ["l!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1], + ["L!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1], + ["N", false, :big_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1], + ["V", false, :little_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1], + ["f", false, NATIVE_ENDIAN, FLOAT_ALIGNMENT, sizeof(:float), 1], + ["e", false, :little_endian, FLOAT_ALIGNMENT, sizeof(:float), 1], + ["g", false, :big_endian, FLOAT_ALIGNMENT, sizeof(:float), 1], + ["q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1], + ["Q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1], + ["q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1], + ["Q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1], + ["d", false, NATIVE_ENDIAN, DOUBLE_ALIGNMENT, sizeof(:double), 1], + ["E", false, :little_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1], + ["G", false, :big_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1], + ["j", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1], + ["J", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1], + ].each do |type, native_size_p, endianness, alignment, size, repeat, total_size| + total_size, members, err = MemoryViewTestUtils.parse_item_format("|c#{type}") + assert_nil(err) + + padding_size = alignment - 1 + expected_total_size = 1 + padding_size + size + assert_equal(expected_total_size, total_size) + + expected_result = [ + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, + {format: type[0], native_size_p: native_size_p, endianness: endianness, offset: alignment, size: size, repeat: repeat}, + ] + assert_equal(expected_result, members) + end + end + + def alignment_padding(total_size, alignment) + res = total_size % alignment + if res > 0 + alignment - res + else + 0 + end + end + + def test_rb_memory_view_parse_item_format_with_alignment_total_size_with_tail_padding + total_size, _members, err = MemoryViewTestUtils.parse_item_format("|lqc") + assert_nil(err) + + expected_total_size = sizeof(:int32_t) + expected_total_size += alignment_padding(expected_total_size, INT32_ALIGNMENT) + expected_total_size += sizeof(:int64_t) + expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT) + expected_total_size += 1 + expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT) + assert_equal(expected_total_size, total_size) + end + + def test_rb_memory_view_parse_item_format_with_alignment_compound + total_size, members, err = MemoryViewTestUtils.parse_item_format("|ccc2f3x2d4cq!<") + assert_nil(err) + + expected_total_size = 1 + 1 + 1*2 + expected_total_size += alignment_padding(expected_total_size, FLOAT_ALIGNMENT) + expected_total_size += sizeof(:float)*3 + 1*2 + expected_total_size += alignment_padding(expected_total_size, DOUBLE_ALIGNMENT) + expected_total_size += sizeof(:double)*4 + 1 + expected_total_size += alignment_padding(expected_total_size, LONG_LONG_ALIGNMENT) + expected_total_size += sizeof("long long") + assert_equal(expected_total_size, total_size) + + expected_result = [ + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1}, + {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2}, + ] + offset = 4 + + res = offset % FLOAT_ALIGNMENT + offset += FLOAT_ALIGNMENT - res if res > 0 + expected_result << {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 4, repeat: 3} + offset += 12 + + offset += 2 # 2x + + res = offset % DOUBLE_ALIGNMENT + offset += DOUBLE_ALIGNMENT - res if res > 0 + expected_result << {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 8, repeat: 4} + offset += 32 + + expected_result << {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 1, repeat: 1} + offset += 1 + + res = offset % LONG_LONG_ALIGNMENT + offset += LONG_LONG_ALIGNMENT - res if res > 0 + expected_result << {format: 'q', native_size_p: true, endianness: :little_endian, offset: offset, size: 8, repeat: 1} + + assert_equal(expected_result, members) + end + + def test_rb_memory_view_extract_item_members + m = MemoryViewTestUtils + assert_equal(1, m.extract_item_members([1].pack("c"), "c")) + assert_equal([1, 2], m.extract_item_members([1, 2].pack("ii"), "ii")) + assert_equal([1, 2, 3], m.extract_item_members([1, 2, 3].pack("cls"), "cls")) + end + + def test_rb_memory_view_extract_item_members_endianness + m = MemoryViewTestUtils + assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S>2")) + assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "n2")) + assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S<2")) + assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "v2")) + assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L>")) + assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "N")) + assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L<")) + assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "V")) + assert_equal(0x0102030405060708, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q>")) + assert_equal(0x0807060504030201, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q<")) + end + + def test_rb_memory_view_extract_item_members_float + m = MemoryViewTestUtils + packed = [1.23].pack("f") + assert_equal(packed.unpack("f")[0], m.extract_item_members(packed, "f")) + end + + def test_rb_memory_view_extract_item_members_float_endianness + m = MemoryViewTestUtils + hi, lo = [1.23].pack("f").unpack("L")[0].divmod(0x10000) + packed = [lo, hi].pack("S*") + assert_equal(packed.unpack("e")[0], m.extract_item_members(packed, "e")) + packed = [hi, lo].pack("S*") + assert_equal(packed.unpack("g")[0], m.extract_item_members(packed, "g")) + end + + def test_rb_memory_view_extract_item_members_doble + m = MemoryViewTestUtils + packed = [1.23].pack("d") + assert_equal(1.23, m.extract_item_members(packed, "d")) + end + + def test_rb_memory_view_extract_item_members_doble_endianness + m = MemoryViewTestUtils + hi, lo = [1.23].pack("d").unpack("Q")[0].divmod(0x10000) + packed = [lo, hi].pack("L*") + assert_equal(packed.unpack("E")[0], m.extract_item_members(packed, "E")) + packed = [hi, lo].pack("L*") + assert_equal(packed.unpack("G")[0], m.extract_item_members(packed, "G")) + end + + def test_rb_memory_view_available_p + es = MemoryViewTestUtils::ExportableString.new("ruby") + assert_equal(true, MemoryViewTestUtils.available?(es)) + es = MemoryViewTestUtils::ExportableString.new(nil) + assert_equal(false, MemoryViewTestUtils.available?(es)) + end + + def test_ref_count_with_exported_object + es = MemoryViewTestUtils::ExportableString.new("ruby") + assert_equal(1, MemoryViewTestUtils.ref_count_while_exporting(es, 1)) + assert_equal(2, MemoryViewTestUtils.ref_count_while_exporting(es, 2)) + assert_equal(10, MemoryViewTestUtils.ref_count_while_exporting(es, 10)) + assert_nil(MemoryViewTestUtils.ref_count_while_exporting(es, 0)) + end + + def test_rb_memory_view_init_as_byte_array + # ExportableString's memory view is initialized by rb_memory_view_init_as_byte_array + es = MemoryViewTestUtils::ExportableString.new("ruby") + memory_view_info = MemoryViewTestUtils.get_memory_view_info(es) + assert_equal({ + obj: es, + byte_size: 4, + readonly: true, + format: nil, + item_size: 1, + ndim: 1, + shape: nil, + strides: nil, + sub_offsets: nil + }, + memory_view_info) + end + + def test_rb_memory_view_get_with_memory_view_unavailable_object + es = MemoryViewTestUtils::ExportableString.new(nil) + memory_view_info = MemoryViewTestUtils.get_memory_view_info(es) + assert_nil(memory_view_info) + end + + def test_rb_memory_view_fill_contiguous_strides + row_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], true) + assert_equal([96, 32, 8], + row_major_strides) + + column_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], false) + assert_equal([8, 16, 48], + column_major_strides) + end + + def test_rb_memory_view_get_item_pointer_single_member + buf = [ 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12 ].pack("l!*") + shape = [3, 4] + mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil) + assert_equal(1, mv[[0, 0]]) + assert_equal(4, mv[[0, 3]]) + assert_equal(6, mv[[1, 1]]) + assert_equal(10, mv[[2, 1]]) + end + + def test_rb_memory_view_get_item_pointer_multiple_members + buf = [ 1, 2, 3, 4, 5, 6, 7, 8, + -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") + shape = [2, 4] + strides = [4*sizeof(:short)*2, sizeof(:short)*2] + mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) + assert_equal([1, 2], mv[[0, 0]]) + assert_equal([5, 6], mv[[0, 2]]) + assert_equal([-1, -2], mv[[1, 0]]) + assert_equal([-7, -8], mv[[1, 3]]) + end + + def test_ractor + assert_in_out_err([], <<-"end;", ["[5, 6]", "[-7, -8]"], []) + require "-test-/memory_view" + require "rbconfig/sizeof" + $VERBOSE = nil + r = Ractor.new RbConfig::SIZEOF["short"] do |sizeof_short| + buf = [ 1, 2, 3, 4, 5, 6, 7, 8, + -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") + shape = [2, 4] + strides = [4*sizeof_short*2, sizeof_short*2] + mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) + p mv[[0, 2]] + mv[[1, 3]] + end + p r.take + end; + end +end diff --git a/ruby/test/ruby/test_method.rb b/ruby/test/ruby/test_method.rb index 6ad9620a0..da6878793 100644 --- a/ruby/test/ruby/test_method.rb +++ b/ruby/test/ruby/test_method.rb @@ -5,7 +5,6 @@ class TestMethod < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -104,6 +103,12 @@ def foo() :changed end assert_raise(TypeError) do um.bind(Base.new) end + + # cleanup + Derived.class_eval do + remove_method :foo + def foo() :derived; end + end end def test_callee @@ -467,6 +472,15 @@ def o.foo; end; line_no = __LINE__ o.singleton_class m4 = o.method(:bar) assert_equal("#", m4.inspect, bug15608) + + bug17428 = '[ruby-core:101635] [Bug #17428]' + assert_equal("#(Module)#prepend(*)>", String.method(:prepend).inspect, bug17428) + + c5 = Class.new(String) + m = Module.new{def prepend; end; alias prep prepend}; line_no = __LINE__ + c5.extend(m) + c6 = Class.new(c5) + assert_equal("#(#{m.inspect})#prep(prepend)() #{__FILE__}:#{line_no}>", c6.method(:prep).inspect, bug17428) end def test_callee_top_level @@ -564,7 +578,7 @@ def test_bound_parameters assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:mk8).parameters) assert_equal([[:nokey]], method(:mnk).parameters) # pending - assert_equal([[:rest, :*], [:block, :&]], method(:mf).parameters) + assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], method(:mf).parameters) end def test_unbound_parameters @@ -590,7 +604,7 @@ def test_unbound_parameters assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:mk8).parameters) assert_equal([[:nokey]], self.class.instance_method(:mnk).parameters) # pending - assert_equal([[:rest, :*], [:block, :&]], self.class.instance_method(:mf).parameters) + assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], self.class.instance_method(:mf).parameters) end def test_bmethod_bound_parameters @@ -798,7 +812,9 @@ def test___dir__ assert_instance_of String, __dir__ assert_equal(File.dirname(File.realpath(__FILE__)), __dir__) bug8436 = '[ruby-core:55123] [Bug #8436]' - assert_equal(__dir__, eval("__dir__", binding), bug8436) + file, line = *binding.source_location + file = File.realpath(file) + assert_equal(__dir__, eval("__dir__", binding, file, line), bug8436) bug8662 = '[ruby-core:56099] [Bug #8662]' assert_equal("arbitrary", eval("__dir__", binding, "arbitrary/file.rb"), bug8662) assert_equal("arbitrary", Object.new.instance_eval("__dir__", "arbitrary/file.rb"), bug8662) @@ -820,7 +836,7 @@ class << x assert_equal(c, c.instance_method(:foo).owner) assert_equal(c, x.method(:foo).owner) assert_equal(x.singleton_class, x.method(:bar).owner) - assert_not_equal(x.method(:foo), x.method(:bar), bug7613) + assert_equal(x.method(:foo), x.method(:bar), bug7613) assert_equal(c, x.method(:zot).owner, bug7993) assert_equal(c, c.instance_method(:zot).owner, bug7993) end @@ -1072,6 +1088,118 @@ def test_super_method_after_bind '[ruby-core:85231] [Bug #14421]' end + def test_super_method_alias + c0 = Class.new do + def m1 + [:C0_m1] + end + def m2 + [:C0_m2] + end + end + + c1 = Class.new(c0) do + def m1 + [:C1_m1] + super + end + alias m2 m1 + end + + c2 = Class.new(c1) do + def m2 + [:C2_m2] + super + end + end + o1 = c2.new + assert_equal([:C2_m2, :C1_m1, :C0_m1], o1.m2) + + m = o1.method(:m2) + assert_equal([:C2_m2, :C1_m1, :C0_m1], m.call) + + m = m.super_method + assert_equal([:C1_m1, :C0_m1], m.call) + + m = m.super_method + assert_equal([:C0_m1], m.call) + + assert_nil(m.super_method) + end + + def test_super_method_alias_to_prepended_module + m = Module.new do + def m1 + [:P_m1] + super + end + + def m2 + [:P_m2] + super + end + end + + c0 = Class.new do + def m1 + [:C0_m1] + end + end + + c1 = Class.new(c0) do + def m1 + [:C1_m1] + super + end + prepend m + alias m2 m1 + end + + o1 = c1.new + assert_equal([:P_m2, :P_m1, :C1_m1, :C0_m1], o1.m2) + + m = o1.method(:m2) + assert_equal([:P_m2, :P_m1, :C1_m1, :C0_m1], m.call) + + m = m.super_method + assert_equal([:P_m1, :C1_m1, :C0_m1], m.call) + + m = m.super_method + assert_equal([:C1_m1, :C0_m1], m.call) + + m = m.super_method + assert_equal([:C0_m1], m.call) + + assert_nil(m.super_method) + end + + # Bug 17780 + def test_super_method_module_alias + m = Module.new do + def foo + end + alias :f :foo + end + + method = m.instance_method(:f) + super_method = method.super_method + assert_nil(super_method) + end + + def test_method_visibility_predicates + v = Visibility.new + assert_equal(true, v.method(:mv1).public?) + assert_equal(true, v.method(:mv2).private?) + assert_equal(true, v.method(:mv3).protected?) + assert_equal(false, v.method(:mv2).public?) + assert_equal(false, v.method(:mv3).private?) + assert_equal(false, v.method(:mv1).protected?) + end + + def test_unbound_method_visibility_predicates + assert_equal(true, Visibility.instance_method(:mv1).public?) + assert_equal(true, Visibility.instance_method(:mv2).private?) + assert_equal(true, Visibility.instance_method(:mv3).protected?) + assert_equal(false, Visibility.instance_method(:mv2).public?) + assert_equal(false, Visibility.instance_method(:mv3).private?) + assert_equal(false, Visibility.instance_method(:mv1).protected?) + end + def rest_parameter(*rest) rest end @@ -1108,17 +1236,22 @@ def test_to_proc_binding assert_equal([:bar, :foo], b.local_variables.sort, bug11012) end - class MethodInMethodClass - def m1 - def m2 - end + MethodInMethodClass_Setup = -> do + remove_const :MethodInMethodClass if defined? MethodInMethodClass - self.class.send(:define_method, :m3){} # [Bug #11754] + class MethodInMethodClass + def m1 + def m2 + end + self.class.send(:define_method, :m3){} # [Bug #11754] + end + private end - private end def test_method_in_method_visibility_should_be_public + MethodInMethodClass_Setup.call + assert_equal([:m1].sort, MethodInMethodClass.public_instance_methods(false).sort) assert_equal([].sort, MethodInMethodClass.private_instance_methods(false).sort) @@ -1168,6 +1301,42 @@ def test_argument_error_location assert_separately [], "RubyVM::InstructionSequence.compile_option = {trace_instruction: false}\n" + body end + def test_zsuper_private_override_instance_method + assert_separately(%w(--disable-gems), <<-'end;', timeout: 30) + # Bug #16942 [ruby-core:98691] + module M + def x + end + end + + module M2 + prepend Module.new + include M + private :x + end + + ::Object.prepend(M2) + + m = Object.instance_method(:x) + assert_equal M, m.owner + end; + end + + def test_override_optimized_method_on_class_using_prepend + assert_separately(%w(--disable-gems), <<-'end;', timeout: 30) + # Bug #17725 [ruby-core:102884] + $VERBOSE = nil + String.prepend(Module.new) + class String + def + other + 'blah blah' + end + end + + assert_equal('blah blah', 'a' + 'b') + end; + end + def test_eqq assert_operator(0.method(:<), :===, 5) assert_not_operator(0.method(:<), :===, -5) @@ -1274,4 +1443,8 @@ def test_method_list assert_operator nummodule, :>, 0 assert_operator nummethod, :>, 0 end + + def test_invalidating_CC_ASAN + assert_ruby_status(['-e', 'using Module.new']) + end end diff --git a/ruby/test/ruby/test_method_cache.rb b/ruby/test/ruby/test_method_cache.rb new file mode 100644 index 000000000..2ed89e47b --- /dev/null +++ b/ruby/test/ruby/test_method_cache.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +require 'test/unit' + +class TestMethodCache < Test::Unit::TestCase + def test_undef + # clear same + c0 = Class.new do + def foo; end + undef foo + end + + assert_raise(NoMethodError) do + c0.new.foo + end + + c0.class_eval do + def foo; :ok; end + end + + assert_equal :ok, c0.new.foo + end + + def test_undef_with_subclasses + # with subclasses + c0 = Class.new do + def foo; end + undef foo + end + + _c1 = Class.new(c0) + + assert_raise(NoMethodError) do + c0.new.foo + end + + c0.class_eval do + def foo; :ok; end + end + + assert_equal :ok, c0.new.foo + end + + def test_undef_with_subclasses_complicated + c0 = Class.new{ def foo; end } + c1 = Class.new(c0){ undef foo } + c2 = Class.new(c1) + c3 = Class.new(c2) + _c4 = Class.new(c3) + + assert_raise(NoMethodError) do + c3.new.foo + end + + c2.class_eval do + def foo; :c2; end + end + + assert_raise(NoMethodError) do + c1.new.foo + end + + assert_equal :c2, c3.new.foo + end + + def test_negative_cache_with_and_without_subclasses + c0 = Class.new{} + c1 = Class.new(c0){} + c0.new.foo rescue nil + c1.new.foo rescue nil + c1.module_eval{ def foo = :c1 } + c0.module_eval{ def foo = :c0 } + + assert_equal :c0, c0.new.foo + end +end + diff --git a/ruby/test/ruby/test_module.rb b/ruby/test/ruby/test_module.rb index 2e7e5804d..fa890c0e4 100644 --- a/ruby/test/ruby/test_module.rb +++ b/ruby/test/ruby/test_module.rb @@ -27,7 +27,6 @@ def assert_method_not_defined?(klass, mid, message="") def setup @verbose = $VERBOSE - $VERBOSE = nil @deprecated = Warning[:deprecated] Warning[:deprecated] = true end @@ -88,8 +87,11 @@ def user3 private :user3 end - module Other - def other + OtherSetup = -> do + remove_const :Other if defined? ::TestModule::Other + module Other + def other + end end end @@ -223,6 +225,8 @@ def test_ancestors @@class_eval = 'b' def test_class_eval + OtherSetup.call + Other.class_eval("CLASS_EVAL = 1") assert_equal(1, Other::CLASS_EVAL) assert_include(Other.constants, :CLASS_EVAL) @@ -263,7 +267,7 @@ def each_bad_constants(m, &b) ].each do |name, msg| expected = "wrong constant name %s" % name msg = "#{msg}#{': ' if msg}wrong constant name #{name.dump}" - assert_raise_with_message(NameError, expected, "#{msg} to #{m}") do + assert_raise_with_message(NameError, Regexp.compile(Regexp.quote(expected)), "#{msg} to #{m}") do yield name end end @@ -297,6 +301,8 @@ def n.count; @count; end end def test_nested_get + OtherSetup.call + assert_equal Other, Object.const_get([self.class, 'Other'].join('::')) assert_equal User::USER, self.class.const_get([User, 'USER'].join('::')) assert_raise(NameError) { @@ -305,6 +311,8 @@ def test_nested_get end def test_nested_get_symbol + OtherSetup.call + const = [self.class, Other].join('::').to_sym assert_raise(NameError) {Object.const_get(const)} @@ -331,6 +339,8 @@ def test_nested_get_bad_class end def test_nested_defined + OtherSetup.call + assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')]) assert_send([self.class, :const_defined?, 'User::USER']) assert_not_send([self.class, :const_defined?, 'User::Foo']) @@ -338,6 +348,8 @@ def test_nested_defined end def test_nested_defined_symbol + OtherSetup.call + const = [self.class, Other].join('::').to_sym assert_raise(NameError) {Object.const_defined?(const)} @@ -363,6 +375,8 @@ def test_nested_defined_bad_class end def test_const_set + OtherSetup.call + assert_not_operator(Other, :const_defined?, :KOALA) Other.const_set(:KOALA, 99) assert_operator(Other, :const_defined?, :KOALA) @@ -390,19 +404,20 @@ def test_constants assert_equal([:MIXIN, :USER], User.constants.sort) end - def test_self_initialize_copy - bug9535 = '[ruby-dev:47989] [Bug #9535]' - m = Module.new do - def foo - :ok - end - initialize_copy(self) + def test_initialize_copy + mod = Module.new { define_method(:foo) {:first} } + klass = Class.new { include mod } + instance = klass.new + assert_equal(:first, instance.foo) + new_mod = Module.new { define_method(:foo) { :second } } + assert_raise(TypeError) do + mod.send(:initialize_copy, new_mod) end - assert_equal(:ok, Object.new.extend(m).foo, bug9535) + 4.times { GC.start } + assert_equal(:first, instance.foo) # [BUG] unreachable end def test_initialize_copy_empty - bug9813 = '[ruby-dev:48182] [Bug #9813]' m = Module.new do def x end @@ -412,15 +427,66 @@ def x assert_equal([:x], m.instance_methods) assert_equal([:@x], m.instance_variables) assert_equal([:X], m.constants) - m.module_eval do - initialize_copy(Module.new) + assert_raise(TypeError) do + m.module_eval do + initialize_copy(Module.new) + end end - assert_empty(m.instance_methods, bug9813) - assert_empty(m.instance_variables, bug9813) - assert_empty(m.constants, bug9813) + + m = Class.new(Module) do + def initialize_copy(other) + # leave uninitialized + end + end.new.dup + c = Class.new + assert_operator(c.include(m), :<, m) + cp = Module.instance_method(:initialize_copy) + assert_raise(TypeError) do + cp.bind_call(m, Module.new) + end + end + + class Bug18185 < Module + module InstanceMethods + end + attr_reader :ancestor_list + def initialize + @ancestor_list = ancestors + include InstanceMethods + end + class Foo + attr_reader :key + def initialize(key:) + @key = key + end + end + end + + def test_module_subclass_initialize + mod = Bug18185.new + c = Class.new(Bug18185::Foo) do + include mod + end + anc = c.ancestors + assert_include(anc, mod) + assert_equal(1, anc.count(BasicObject), ->{anc.inspect}) + b = c.new(key: 1) + assert_equal(1, b.key) + assert_not_include(mod.ancestor_list, BasicObject) + end + + def test_module_collected_extended_object + m1 = labeled_module("m1") + m2 = labeled_module("m2") + Object.new.extend(m1) + GC.start + m1.include(m2) + assert_equal([m1, m2], m1.ancestors) end def test_dup + OtherSetup.call + bug6454 = '[ruby-core:45132]' a = Module.new @@ -462,6 +528,169 @@ def test_include_with_no_args assert_raise(ArgumentError) { Module.new { include } } end + def test_include_before_initialize + m = Class.new(Module) do + def initialize(...) + include Enumerable + super + end + end.new + assert_equal(true, m < Enumerable) + end + + def test_prepend_self + m = Module.new + assert_equal([m], m.ancestors) + m.prepend(m) rescue nil + assert_equal([m], m.ancestors) + end + + def test_bug17590 + m = Module.new + c = Class.new + c.prepend(m) + c.include(m) + m.prepend(m) rescue nil + m2 = Module.new + m2.prepend(m) + c.include(m2) + + assert_equal([m, c, m2] + Object.ancestors, c.ancestors) + end + + def test_prepend_works_with_duped_classes + m = Module.new + a = Class.new do + def b; 2 end + prepend m + end + a2 = a.dup.new + a.class_eval do + alias _b b + def b; 1 end + end + assert_equal(2, a2.b) + end + + def test_gc_prepend_chain + assert_separately([], <<-EOS) + 10000.times { |i| + m1 = Module.new do + def foo; end + end + m2 = Module.new do + prepend m1 + def bar; end + end + m3 = Module.new do + def baz; end + prepend m2 + end + Class.new do + prepend m3 + end + } + GC.start + EOS + end + + def test_refine_module_then_include + assert_separately([], "#{<<~"end;"}\n") + module M + end + class C + include M + end + module RefinementBug + refine M do + def refined_method + :rm + end + end + end + using RefinementBug + + class A + include M + end + + assert_equal(:rm, C.new.refined_method) + end; + end + + def test_include_into_module_already_included + c = Class.new{def foo; [:c] end} + modules = lambda do || + sub = Class.new(c){def foo; [:sc] + super end} + [ + Module.new{def foo; [:m1] + super end}, + Module.new{def foo; [:m2] + super end}, + Module.new{def foo; [:m3] + super end}, + sub, + sub.new + ] + end + + m1, m2, m3, sc, o = modules.call + assert_equal([:sc, :c], o.foo) + sc.include m1 + assert_equal([:sc, :m1, :c], o.foo) + m1.include m2 + assert_equal([:sc, :m1, :m2, :c], o.foo) + m2.include m3 + assert_equal([:sc, :m1, :m2, :m3, :c], o.foo) + + m1, m2, m3, sc, o = modules.call + sc.prepend m1 + assert_equal([:m1, :sc, :c], o.foo) + m1.include m2 + assert_equal([:m1, :m2, :sc, :c], o.foo) + m2.include m3 + assert_equal([:m1, :m2, :m3, :sc, :c], o.foo) + + m1, m2, m3, sc, o = modules.call + sc.include m2 + assert_equal([:sc, :m2, :c], o.foo) + sc.prepend m1 + assert_equal([:m1, :sc, :m2, :c], o.foo) + m1.include m2 + assert_equal([:m1, :sc, :m2, :c], o.foo) + m1.include m3 + assert_equal([:m1, :m3, :sc, :m2, :c], o.foo) + + m1, m2, m3, sc, o = modules.call + sc.include m3 + sc.include m2 + assert_equal([:sc, :m2, :m3, :c], o.foo) + sc.prepend m1 + assert_equal([:m1, :sc, :m2, :m3, :c], o.foo) + m1.include m2 + m1.include m3 + assert_equal([:m1, :sc, :m2, :m3, :c], o.foo) + + m1, m2, m3, sc, o = modules.call + assert_equal([:sc, :c], o.foo) + sc.prepend m1 + assert_equal([:m1, :sc, :c], o.foo) + m1.prepend m2 + assert_equal([:m2, :m1, :sc, :c], o.foo) + m2.prepend m3 + assert_equal([:m3, :m2, :m1, :sc, :c], o.foo) + m1, m2, m3, sc, o = modules.call + sc.include m1 + assert_equal([:sc, :m1, :c], o.foo) + sc.prepend m2 + assert_equal([:m2, :sc, :m1, :c], o.foo) + sc.prepend m3 + assert_equal([:m3, :m2, :sc, :m1, :c], o.foo) + m1, m2, m3, sc, o = modules.call + sc.include m1 + assert_equal([:sc, :m1, :c], o.foo) + m2.prepend m3 + m1.include m2 + assert_equal([:sc, :m1, :m3, :m2, :c], o.foo) + end + def test_included_modules assert_equal([], Mixin.included_modules) assert_equal([Mixin], User.included_modules) @@ -472,6 +701,61 @@ def test_included_modules assert_equal([Comparable, Kernel], String.included_modules - mixins) end + def test_included_modules_with_prepend + m1 = Module.new + m2 = Module.new + m3 = Module.new + + m2.prepend m1 + m3.include m2 + assert_equal([m1, m2], m3.included_modules) + end + + def test_include_with_prepend + c = Class.new{def m; [:c] end} + p = Module.new{def m; [:p] + super end} + q = Module.new{def m; [:q] + super end; include p} + r = Module.new{def m; [:r] + super end; prepend q} + s = Module.new{def m; [:s] + super end; include r} + a = Class.new(c){def m; [:a] + super end; prepend p; include s} + assert_equal([:p, :a, :s, :q, :r, :c], a.new.m) + end + + def test_prepend_after_include + c = Class.new{def m; [:c] end} + sc = Class.new(c){def m; [:sc] + super end} + m = Module.new{def m; [:m] + super end} + sc.include m + sc.prepend m + sc.prepend m + assert_equal([:m, :sc, :m, :c], sc.new.m) + + c = Class.new{def m; [:c] end} + sc = Class.new(c){def m; [:sc] + super end} + m0 = Module.new{def m; [:m0] + super end} + m1 = Module.new{def m; [:m1] + super end} + m1.prepend m0 + sc.include m1 + sc.prepend m1 + assert_equal([:m0, :m1, :sc, :m0, :m1, :c], sc.new.m) + sc.prepend m + assert_equal([:m, :m0, :m1, :sc, :m0, :m1, :c], sc.new.m) + sc.prepend m1 + assert_equal([:m, :m0, :m1, :sc, :m0, :m1, :c], sc.new.m) + + + c = Class.new{def m; [:c] end} + sc = Class.new(c){def m; [:sc] + super end} + m0 = Module.new{def m; [:m0] + super end} + m1 = Module.new{def m; [:m1] + super end} + m1.include m0 + sc.include m1 + sc.prepend m + sc.prepend m1 + sc.prepend m1 + assert_equal([:m1, :m0, :m, :sc, :m1, :m0, :c], sc.new.m) + end + def test_instance_methods assert_equal([:user, :user2], User.instance_methods(false).sort) assert_equal([:user, :user2, :mixin].sort, User.instance_methods(true).sort) @@ -522,6 +806,11 @@ def test_method_defined_without_include_super assert !c.method_defined?(:userx, false) c.define_method(:userx){} assert c.method_defined?(:userx, false) + + # cleanup + User.class_eval do + remove_const :FOO + end end def module_exec_aux @@ -552,6 +841,14 @@ def dynamically_added_method_2; end def dynamically_added_method_4; end end assert_method_defined?(User, :dynamically_added_method_4) + + # cleanup + User.class_eval do + remove_method :dynamically_added_method_1 + remove_method :dynamically_added_method_2 + remove_method :dynamically_added_method_3 + remove_method :dynamically_added_method_4 + end end def test_module_eval @@ -595,13 +892,13 @@ def test_classpath n = Module.new m.const_set(:N, n) assert_nil(m.name) - assert_nil(n.name) + assert_match(/::N$/, n.name) assert_equal([:N], m.constants) m.module_eval("module O end") assert_equal([:N, :O], m.constants.sort) m.module_eval("class C; end") assert_equal([:C, :N, :O], m.constants.sort) - assert_nil(m::N.name) + assert_match(/::N$/, m::N.name) assert_match(/\A#::O\z/, m::O.name) assert_match(/\A#::C\z/, m::C.name) self.class.const_set(:M, m) @@ -611,12 +908,19 @@ def test_classpath assert_equal(prefix+"C", m.const_get(:C).name) c = m.class_eval("Bug15891 = Class.new.freeze") assert_equal(prefix+"Bug15891", c.name) + ensure + self.class.class_eval {remove_const(:M)} end def test_private_class_method assert_raise(ExpectedException) { AClass.cm1 } assert_raise(ExpectedException) { AClass.cm3 } assert_equal("cm1cm2cm3", AClass.cm2) + + c = Class.new(AClass) + c.class_eval {private_class_method [:cm1, :cm2]} + assert_raise(NoMethodError, /private method/) {c.cm1} + assert_raise(NoMethodError, /private method/) {c.cm2} end def test_private_instance_methods @@ -639,6 +943,11 @@ def test_public_class_method assert_equal("cm1", MyClass.cm1) assert_equal("cm1cm2cm3", MyClass.cm2) assert_raise(ExpectedException) { eval "MyClass.cm3" } + + c = Class.new(AClass) + c.class_eval {public_class_method [:cm1, :cm2]} + assert_equal("cm1", c.cm1) + assert_equal("cm1cm2cm3", c.cm2) end def test_public_instance_methods @@ -646,12 +955,116 @@ def test_public_instance_methods assert_equal([:bClass1], BClass.public_instance_methods(false)) end + def test_s_public + o = (c = Class.new(AClass)).new + assert_raise(NoMethodError, /private method/) {o.aClass1} + assert_raise(NoMethodError, /protected method/) {o.aClass2} + c.class_eval {public :aClass1} + assert_equal(:aClass1, o.aClass1) + + o = (c = Class.new(AClass)).new + c.class_eval {public :aClass1, :aClass2} + assert_equal(:aClass1, o.aClass1) + assert_equal(:aClass2, o.aClass2) + + o = (c = Class.new(AClass)).new + c.class_eval {public [:aClass1, :aClass2]} + assert_equal(:aClass1, o.aClass1) + assert_equal(:aClass2, o.aClass2) + + o = AClass.new + assert_equal(:aClass, o.aClass) + assert_raise(NoMethodError, /private method/) {o.aClass1} + assert_raise(NoMethodError, /protected method/) {o.aClass2} + end + + def test_s_private + o = (c = Class.new(AClass)).new + assert_equal(:aClass, o.aClass) + c.class_eval {private :aClass} + assert_raise(NoMethodError, /private method/) {o.aClass} + + o = (c = Class.new(AClass)).new + c.class_eval {private :aClass, :aClass2} + assert_raise(NoMethodError, /private method/) {o.aClass} + assert_raise(NoMethodError, /private method/) {o.aClass2} + + o = (c = Class.new(AClass)).new + c.class_eval {private [:aClass, :aClass2]} + assert_raise(NoMethodError, /private method/) {o.aClass} + assert_raise(NoMethodError, /private method/) {o.aClass2} + + o = AClass.new + assert_equal(:aClass, o.aClass) + assert_raise(NoMethodError, /private method/) {o.aClass1} + assert_raise(NoMethodError, /protected method/) {o.aClass2} + end + + def test_s_protected + aclass = Class.new(AClass) do + def _aClass(o) o.aClass; end + def _aClass1(o) o.aClass1; end + def _aClass2(o) o.aClass2; end + end + + o = (c = Class.new(aclass)).new + assert_equal(:aClass, o.aClass) + c.class_eval {protected :aClass} + assert_raise(NoMethodError, /protected method/) {o.aClass} + assert_equal(:aClass, c.new._aClass(o)) + + o = (c = Class.new(aclass)).new + c.class_eval {protected :aClass, :aClass1} + assert_raise(NoMethodError, /protected method/) {o.aClass} + assert_raise(NoMethodError, /protected method/) {o.aClass1} + assert_equal(:aClass, c.new._aClass(o)) + assert_equal(:aClass1, c.new._aClass1(o)) + + o = (c = Class.new(aclass)).new + c.class_eval {protected [:aClass, :aClass1]} + assert_raise(NoMethodError, /protected method/) {o.aClass} + assert_raise(NoMethodError, /protected method/) {o.aClass1} + assert_equal(:aClass, c.new._aClass(o)) + assert_equal(:aClass1, c.new._aClass1(o)) + + o = AClass.new + assert_equal(:aClass, o.aClass) + assert_raise(NoMethodError, /private method/) {o.aClass1} + assert_raise(NoMethodError, /protected method/) {o.aClass2} + end + + def test_visibility_method_return_value + no_arg_results = nil + c = Module.new do + singleton_class.send(:public, :public, :private, :protected, :module_function) + def foo; end + def bar; end + no_arg_results = [public, private, protected, module_function] + end + + assert_equal([nil]*4, no_arg_results) + + assert_equal(:foo, c.private(:foo)) + assert_equal(:foo, c.public(:foo)) + assert_equal(:foo, c.protected(:foo)) + assert_equal(:foo, c.module_function(:foo)) + + assert_equal([:foo, :bar], c.private(:foo, :bar)) + assert_equal([:foo, :bar], c.public(:foo, :bar)) + assert_equal([:foo, :bar], c.protected(:foo, :bar)) + assert_equal([:foo, :bar], c.module_function(:foo, :bar)) + end + def test_s_constants c1 = Module.constants Object.module_eval "WALTER = 99" c2 = Module.constants assert_equal([:WALTER], c2 - c1) + Object.class_eval do + remove_const :WALTER + end + assert_equal([], Module.constants(true)) assert_equal([], Module.constants(false)) @@ -714,14 +1127,19 @@ def foo; end end def test_attr_obsoleted_flag - c = Class.new - c.class_eval do + c = Class.new do + extend Test::Unit::Assertions + extend Test::Unit::CoreAssertions def initialize @foo = :foo @bar = :bar end - attr :foo, true - attr :bar, false + assert_deprecated_warning(/optional boolean argument/) do + attr :foo, true + end + assert_deprecated_warning(/optional boolean argument/) do + attr :bar, false + end end o = c.new assert_equal(true, o.respond_to?(:foo)) @@ -766,6 +1184,7 @@ def test_const_get_evaled assert_equal(:foo, c2.const_get(:Foo)) assert_raise(NameError) { c2.const_get(:Foo, false) } + c1.__send__(:remove_const, :Foo) eval("c1::Foo = :foo") assert_raise(NameError) { c1::Bar } assert_raise(NameError) { c2::Bar } @@ -963,6 +1382,28 @@ def test_attr assert_raise(NameError) do c.instance_eval { attr_reader :"." } end + + assert_equal([:a], c.class_eval { attr :a }) + assert_equal([:b, :c], c.class_eval { attr :b, :c }) + assert_equal([:d], c.class_eval { attr_reader :d }) + assert_equal([:e, :f], c.class_eval { attr_reader :e, :f }) + assert_equal([:g=], c.class_eval { attr_writer :g }) + assert_equal([:h=, :i=], c.class_eval { attr_writer :h, :i }) + assert_equal([:j, :j=], c.class_eval { attr_accessor :j }) + assert_equal([:k, :k=, :l, :l=], c.class_eval { attr_accessor :k, :l }) + end + + def test_alias_method + c = Class.new do + def foo; :foo end + end + o = c.new + assert_respond_to(o, :foo) + assert_not_respond_to(o, :bar) + r = c.class_eval {alias_method :bar, :foo} + assert_respond_to(o, :bar) + assert_equal(:foo, o.bar) + assert_equal(:bar, r) end def test_undef @@ -1112,13 +1553,25 @@ def baz; end end def test_top_public_private - assert_in_out_err([], <<-INPUT, %w([:foo] [:bar]), []) + assert_in_out_err([], <<-INPUT, %w([:foo] [:bar] [:bar,\ :foo] [] [:bar,\ :foo] []), []) private def foo; :foo; end public def bar; :bar; end p self.private_methods.grep(/^foo$|^bar$/) p self.methods.grep(/^foo$|^bar$/) + + private :foo, :bar + p self.private_methods.grep(/^foo$|^bar$/).sort + + public :foo, :bar + p self.private_methods.grep(/^foo$|^bar$/).sort + + private [:foo, :bar] + p self.private_methods.grep(/^foo$|^bar$/).sort + + public [:foo, :bar] + p self.private_methods.grep(/^foo$|^bar$/).sort INPUT end @@ -1579,23 +2032,31 @@ def test_deprecate_constant c = Class.new c.const_set(:FOO, "foo") c.deprecate_constant(:FOO) - assert_warn(/deprecated/) {c::FOO} - assert_warn(/#{c}::FOO is deprecated/) {Class.new(c)::FOO} + assert_warn(/deprecated/) do + Warning[:deprecated] = true + c::FOO + end + assert_warn(/#{c}::FOO is deprecated/) do + Warning[:deprecated] = true + Class.new(c)::FOO + end bug12382 = '[ruby-core:75505] [Bug #12382]' - assert_warn(/deprecated/, bug12382) {c.class_eval "FOO"} - Warning[:deprecated] = false - assert_warn('') {c::FOO} - end - - NIL = nil - FALSE = false - deprecate_constant(:NIL, :FALSE) - - def test_deprecate_nil_constant - w = EnvUtil.verbose_warning {2.times {FALSE}} - assert_equal(1, w.scan("::FALSE").size, w) - w = EnvUtil.verbose_warning {2.times {NIL}} - assert_equal(1, w.scan("::NIL").size, w) + assert_warn(/deprecated/, bug12382) do + Warning[:deprecated] = true + c.class_eval "FOO" + end + assert_warn('') do + Warning[:deprecated] = false + c::FOO + end + assert_warn('') do + Warning[:deprecated] = false + Class.new(c)::FOO + end + assert_warn('') do + Warning[:deprecated] = false + c.class_eval "FOO" + end end def test_constants_with_private_constant @@ -1835,7 +2296,7 @@ def test_prepend_module_ancestors assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x) m3 = labeled_module("m3") {include m1; prepend m1} - assert_equal([m3, m0, m1], m3.ancestors) + assert_equal([m0, m1, m3, m0, m1], m3.ancestors) m3 = labeled_module("m3") {prepend m1; include m1} assert_equal([m0, m1, m3], m3.ancestors) m3 = labeled_module("m3") {prepend m1; prepend m1} @@ -1916,6 +2377,137 @@ def /(other) assert_equal(0, 1 / 2) end + def test_visibility_after_refine_and_visibility_change_with_origin_class + m = Module.new + c = Class.new do + def x; :x end + end + c.prepend(m) + Module.new do + refine c do + def x; :y end + end + end + + o1 = c.new + o2 = c.new + assert_equal(:x, o1.public_send(:x)) + assert_equal(:x, o2.public_send(:x)) + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + + def test_visibility_after_multiple_refine_and_visibility_change_with_origin_class + m = Module.new + c = Class.new do + def x; :x end + end + c.prepend(m) + Module.new do + refine c do + def x; :y end + end + end + Module.new do + refine c do + def x; :z end + end + end + + o1 = c.new + o2 = c.new + assert_equal(:x, o1.public_send(:x)) + assert_equal(:x, o2.public_send(:x)) + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + + def test_visibility_after_refine_and_visibility_change_without_origin_class + c = Class.new do + def x; :x end + end + Module.new do + refine c do + def x; :y end + end + end + o1 = c.new + o2 = c.new + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + + def test_visibility_after_multiple_refine_and_visibility_change_without_origin_class + c = Class.new do + def x; :x end + end + Module.new do + refine c do + def x; :y end + end + end + Module.new do + refine c do + def x; :z end + end + end + o1 = c.new + o2 = c.new + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + + def test_visibility_after_refine_and_visibility_change_with_superclass + c = Class.new do + def x; :x end + end + sc = Class.new(c) + Module.new do + refine sc do + def x; :y end + end + end + o1 = sc.new + o2 = sc.new + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + + def test_visibility_after_multiple_refine_and_visibility_change_with_superclass + c = Class.new do + def x; :x end + end + sc = Class.new(c) + Module.new do + refine sc do + def x; :y end + end + end + Module.new do + refine sc do + def x; :z end + end + end + o1 = sc.new + o2 = sc.new + o1.singleton_class.send(:private, :x) + o2.singleton_class.send(:public, :x) + assert_raise(NoMethodError) { o1.public_send(:x) } + assert_equal(:x, o2.public_send(:x)) + end + def test_prepend_visibility bug8005 = '[ruby-core:53106] [Bug #8005]' c = Class.new do @@ -1958,6 +2550,33 @@ def test_prepend_included_modules assert_include(im, mixin, bug8025) end + def test_prepended_module_with_super_and_alias + bug16736 = '[Bug #16736]' + + a = labeled_class("A") do + def m; "A"; end + end + m = labeled_module("M") do + prepend Module.new + + def self.included(base) + base.alias_method :base_m, :m + end + + def m + super + "M" + end + + def m2 + base_m + end + end + b = labeled_class("B", a) do + include m + end + assert_equal("AM", b.new.m2, bug16736) + end + def test_prepend_super_in_alias bug7842 = '[Bug #7842]' @@ -2076,6 +2695,22 @@ def test_class_variables assert_equal([:@@bar], m2.class_variables(false)) end + def test_class_variable_in_dup_class + a = Class.new do + @@a = 'A' + def a=(x) + @@a = x + end + def a + @@a + end + end + + b = a.dup + b.new.a = 'B' + assert_equal 'A', a.new.a, '[ruby-core:17019]' + end + Bug6891 = '[ruby-core:47241]' def test_extend_module_with_protected_method @@ -2152,6 +2787,9 @@ def test_invalid_attr class AttrTest class << self attr_accessor :cattr + def reset + self.cattr = nil + end end attr_accessor :iattr def ivar @@ -2161,7 +2799,7 @@ def ivar def test_uninitialized_instance_variable a = AttrTest.new - assert_warning(/instance variable @ivar not initialized/) do + assert_warning('') do assert_nil(a.ivar) end a.instance_variable_set(:@ivar, 42) @@ -2170,7 +2808,7 @@ def test_uninitialized_instance_variable end name = "@\u{5909 6570}" - assert_warning(/instance variable #{name} not initialized/) do + assert_warning('') do assert_nil(a.instance_eval(name)) end end @@ -2194,6 +2832,8 @@ def test_uninitialized_attr_class assert_warning '' do assert_equal(42, AttrTest.cattr) end + + AttrTest.reset end def test_uninitialized_attr_non_object @@ -2297,31 +2937,6 @@ def test_visibility_by_public_class_method assert_raise(NoMethodError, bug8284) {Object.remove_const} end - def test_include_module_with_constants_does_not_invalidate_method_cache - assert_in_out_err([], <<-RUBY, %w(123 456 true), []) - A = 123 - - class Foo - def self.a - A - end - end - - module M - A = 456 - end - - puts Foo.a - starting = RubyVM.stat[:global_method_state] - - Foo.send(:include, M) - - ending = RubyVM.stat[:global_method_state] - puts Foo.a - puts starting == ending - RUBY - end - def test_return_value_of_define_method retvals = [] Class.new.class_eval do @@ -2358,9 +2973,67 @@ def foo; end } end + def test_prepend_constant_lookup + m = Module.new do + const_set(:C, :m) + end + c = Class.new do + const_set(:C, :c) + prepend m + end + sc = Class.new(c) + # Situation from [Bug #17887] + assert_equal(sc.ancestors.take(3), [sc, m, c]) + assert_equal(:m, sc.const_get(:C)) + assert_equal(:m, sc::C) + + assert_equal(:c, c::C) + + m.send(:remove_const, :C) + assert_equal(:c, sc.const_get(:C)) + assert_equal(:c, sc::C) + + # Same ancestors, built with include instead of prepend + m = Module.new do + const_set(:C, :m) + end + c = Class.new do + const_set(:C, :c) + end + sc = Class.new(c) do + include m + end + + assert_equal(sc.ancestors.take(3), [sc, m, c]) + assert_equal(:m, sc.const_get(:C)) + assert_equal(:m, sc::C) + + m.send(:remove_const, :C) + assert_equal(:c, sc.const_get(:C)) + assert_equal(:c, sc::C) + + # Situation from [Bug #17887], but with modules + m = Module.new do + const_set(:C, :m) + end + m2 = Module.new do + const_set(:C, :m2) + prepend m + end + c = Class.new do + include m2 + end + assert_equal(c.ancestors.take(3), [c, m, m2]) + assert_equal(:m, c.const_get(:C)) + assert_equal(:m, c::C) + end + def test_inspect_segfault bug_10282 = '[ruby-core:65214] [Bug #10282]' - assert_separately [], <<-RUBY + assert_separately [], "#{<<~"begin;"}\n#{<<~'end;'}" + bug_10282 = "#{bug_10282}" + begin; + line = __LINE__ + 2 module ShallowInspect def shallow_inspect "foo" @@ -2377,9 +3050,9 @@ class A A.prepend InspectIsShallow - expect = "#" - assert_equal expect, A.new.method(:inspect).inspect, "#{bug_10282}" - RUBY + expect = "#" + assert_equal expect, A.new.method(:inspect).inspect, bug_10282 + end; end def test_define_method_with_unbound_method @@ -2491,6 +3164,18 @@ def test_constant_access_from_method_in_cloned_module assert_equal :M2, CloneTestC2.new.foo, '[Bug #15877]' end + def test_clone_freeze + m = Module.new.freeze + assert_predicate m.clone, :frozen? + assert_not_predicate m.clone(freeze: false), :frozen? + end + + def test_module_name_in_singleton_method + s = Object.new.singleton_class + mod = s.const_set(:Foo, Module.new) + assert_match(/::Foo$/, mod.name, '[Bug #14895]') + end + private def assert_top_method_is_private(method) diff --git a/ruby/test/ruby/test_name_error.rb b/ruby/test/ruby/test_name_error.rb new file mode 100644 index 000000000..f0402de4b --- /dev/null +++ b/ruby/test/ruby/test_name_error.rb @@ -0,0 +1,156 @@ +require 'test/unit' + +class TestNameError < Test::Unit::TestCase + def test_new_default + error = NameError.new + assert_equal("NameError", error.message) + end + + def test_new_message + error = NameError.new("Message") + assert_equal("Message", error.message) + end + + def test_new_name + error = NameError.new("Message") + assert_nil(error.name) + + error = NameError.new("Message", :foo) + assert_equal(:foo, error.name) + end + + def test_new_receiver + receiver = Object.new + + error = NameError.new + assert_raise(ArgumentError) {error.receiver} + assert_equal("NameError", error.message) + + error = NameError.new(receiver: receiver) + assert_equal(["NameError", receiver], + [error.message, error.receiver]) + + error = NameError.new("Message", :foo, receiver: receiver) + assert_equal(["Message", receiver, :foo], + [error.message, error.receiver, error.name]) + end + + PrettyObject = + Class.new(BasicObject) do + alias object_id __id__ + def pretty_inspect; "`obj'"; end + alias inspect pretty_inspect + end + + def test_info_const + obj = PrettyObject.new + + e = assert_raise(NameError) { + obj.instance_eval("Object") + } + assert_equal(:Object, e.name) + + e = assert_raise(NameError) { + BasicObject::X + } + assert_same(BasicObject, e.receiver) + assert_equal(:X, e.name) + end + + def test_info_const_name + mod = Module.new do + def self.name + "ModuleName" + end + + def self.inspect + raise "" + end + end + assert_raise_with_message(NameError, /ModuleName/) {mod::DOES_NOT_EXIST} + end + + def test_info_method + obj = PrettyObject.new + + e = assert_raise(NameError) { + obj.instance_eval {foo} + } + assert_equal(:foo, e.name) + assert_same(obj, e.receiver) + + e = assert_raise(NoMethodError) { + obj.foo(1, 2) + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_not_predicate(e, :private_call?) + + e = assert_raise(NoMethodError) { + obj.instance_eval {foo(1, 2)} + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_predicate(e, :private_call?) + end + + def test_info_local_variables + obj = PrettyObject.new + def obj.test(a, b=nil, *c, &d) + e = a + 1.times {|f| g = foo; g} + e + end + + e = assert_raise(NameError) { + obj.test(3) + } + assert_equal(:foo, e.name) + assert_same(obj, e.receiver) + assert_equal(%i[a b c d e f g], e.local_variables.sort) + end + + def test_info_method_missing + obj = PrettyObject.new + def obj.method_missing(*) + super + end + + e = assert_raise(NoMethodError) { + obj.foo(1, 2) + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_not_predicate(e, :private_call?) + + e = assert_raise(NoMethodError) { + obj.instance_eval {foo(1, 2)} + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_predicate(e, :private_call?) + end + + def test_info_parent_iseq_mark + assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;') + -> {require ARGV[0]}.call + end; + end + + def test_large_receiver_inspect + receiver = Class.new do + def self.inspect + 'A' * 120 + end + end + + error = assert_raise(NameError) do + receiver::FOO + end + assert_match(/\Auninitialized constant #{'A' * 120}::FOO$/, error.message) + end +end diff --git a/ruby/test/ruby/test_nomethod_error.rb b/ruby/test/ruby/test_nomethod_error.rb new file mode 100644 index 000000000..321b7ccab --- /dev/null +++ b/ruby/test/ruby/test_nomethod_error.rb @@ -0,0 +1,109 @@ +require 'test/unit' + +class TestNoMethodError < Test::Unit::TestCase + def test_new_default + error = NoMethodError.new + assert_equal("NoMethodError", error.message) + end + + def test_new_message + error = NoMethodError.new("Message") + assert_equal("Message", error.message) + end + + def test_new_name + error = NoMethodError.new("Message") + assert_nil(error.name) + + error = NoMethodError.new("Message", :foo) + assert_equal(:foo, error.name) + end + + def test_new_name_args + error = NoMethodError.new("Message", :foo) + assert_nil(error.args) + + error = NoMethodError.new("Message", :foo, [1, 2]) + assert_equal([:foo, [1, 2]], [error.name, error.args]) + end + + def test_new_name_args_priv + error = NoMethodError.new("Message", :foo, [1, 2]) + assert_not_predicate(error, :private_call?) + + error = NoMethodError.new("Message", :foo, [1, 2], true) + assert_equal([:foo, [1, 2], true], + [error.name, error.args, error.private_call?]) + end + + def test_new_receiver + receiver = Object.new + + error = NoMethodError.new + assert_raise(ArgumentError) {error.receiver} + + error = NoMethodError.new(receiver: receiver) + assert_equal(receiver, error.receiver) + + error = NoMethodError.new("Message") + assert_raise(ArgumentError) {error.receiver} + + error = NoMethodError.new("Message", receiver: receiver) + assert_equal(["Message", receiver], + [error.message, error.receiver]) + + error = NoMethodError.new("Message", :foo) + assert_raise(ArgumentError) {error.receiver} + + msg = "Message" + + error = NoMethodError.new("Message", :foo, receiver: receiver) + assert_match msg, error.message + assert_equal :foo, error.name + assert_equal receiver, error.receiver + + error = NoMethodError.new("Message", :foo, [1, 2]) + assert_raise(ArgumentError) {error.receiver} + + error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver) + assert_match msg, error.message + assert_equal :foo, error.name + assert_equal [1, 2], error.args + assert_equal receiver, error.receiver + + error = NoMethodError.new("Message", :foo, [1, 2], true) + assert_raise(ArgumentError) {error.receiver} + + error = NoMethodError.new("Message", :foo, [1, 2], true, receiver: receiver) + assert_equal :foo, error.name + assert_equal [1, 2], error.args + assert_equal receiver, error.receiver + assert error.private_call?, "private_call? was false." + end + + def test_message_encoding + bug3237 = '[ruby-core:29948]' + str = "\u2600" + id = :"\u2604" + msg = "undefined method `#{id}' for \"#{str}\":String" + assert_raise_with_message(NoMethodError, Regexp.compile(Regexp.quote(msg)), bug3237) do + str.__send__(id) + end + end + + def test_to_s + pre = Module.new do + def name + BasicObject.new + end + end + mod = Module.new + mod.singleton_class.prepend(pre) + + err = assert_raise(NoMethodError) do + mod.this_method_does_not_exist + end + + assert_match(/undefined method.+this_method_does_not_exist.+for.+Module/, err.to_s) + end +end diff --git a/ruby/test/ruby/test_notimp.rb b/ruby/test/ruby/test_notimp.rb deleted file mode 100644 index b069154cf..000000000 --- a/ruby/test/ruby/test_notimp.rb +++ /dev/null @@ -1,85 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'timeout' -require 'tmpdir' - -class TestNotImplement < Test::Unit::TestCase - def test_respond_to_fork - assert_include(Process.methods, :fork) - if /linux/ =~ RUBY_PLATFORM - assert_equal(true, Process.respond_to?(:fork)) - end - end - - def test_respond_to_lchmod - assert_include(File.methods, :lchmod) - if /linux/ =~ RUBY_PLATFORM - assert_equal(false, File.respond_to?(:lchmod)) - end - if /freebsd/ =~ RUBY_PLATFORM - assert_equal(true, File.respond_to?(:lchmod)) - end - end - - def test_call_fork - GC.start - pid = nil - ps = - case RUBY_PLATFORM - when /linux/ # assume Linux Distribution uses procps - proc {`ps -eLf #{pid}`} - when /freebsd/ - proc {`ps -lH #{pid}`} - when /darwin/ - proc {`ps -lM #{pid}`} - else - proc {`ps -l #{pid}`} - end - assert_nothing_raised(Timeout::Error, ps) do - EnvUtil.timeout(20) { - pid = fork {} - Process.wait pid - pid = nil - } - end - ensure - if pid - Process.kill(:KILL, pid) - Process.wait pid - end - end if Process.respond_to?(:fork) - - def test_call_lchmod - if File.respond_to?(:lchmod) - Dir.mktmpdir {|d| - f = "#{d}/f" - g = "#{d}/g" - File.open(f, "w") {} - File.symlink f, g - newmode = 0444 - File.lchmod newmode, "#{d}/g" - snew = File.lstat(g) - assert_equal(newmode, snew.mode & 0777) - } - end - end - - def test_method_inspect_fork - m = Process.method(:fork) - if Process.respond_to?(:fork) - assert_not_match(/not-implemented/, m.inspect) - else - assert_match(/not-implemented/, m.inspect) - end - end - - def test_method_inspect_lchmod - m = File.method(:lchmod) - if File.respond_to?(:lchmod) - assert_not_match(/not-implemented/, m.inspect) - else - assert_match(/not-implemented/, m.inspect) - end - end - -end diff --git a/ruby/test/ruby/test_numeric.rb b/ruby/test/ruby/test_numeric.rb index 636f827fe..0593cb535 100644 --- a/ruby/test/ruby/test_numeric.rb +++ b/ruby/test/ruby/test_numeric.rb @@ -200,6 +200,14 @@ def test_cmp assert_nil(a <=> :foo) end + def test_float_round_ndigits + bug14635 = "[ruby-core:86323]" + f = 0.5 + 31.times do |i| + assert_equal(0.5, f.round(i+1), bug14635 + " (argument: #{i+1})") + end + end + def test_floor_ceil_round_truncate a = Class.new(Numeric) do def to_f; 1.5; end @@ -229,6 +237,15 @@ def to_f; -1.5; end assert_equal(-1, a.truncate) end + def test_floor_ceil_ndigits + bug17183 = "[ruby-core:100090]" + f = 291.4 + 31.times do |i| + assert_equal(291.4, f.floor(i+1), bug17183) + assert_equal(291.4, f.ceil(i+1), bug17183) + end + end + def assert_step(expected, (from, *args), inf: false) kw = args.last.is_a?(Hash) ? args.pop : {} enum = from.step(*args, **kw) @@ -267,12 +284,7 @@ def test_step assert_raise(ArgumentError) { 1.step(10, "1") { } } assert_raise(ArgumentError) { 1.step(10, "1").size } assert_raise(TypeError) { 1.step(10, nil) { } } - assert_nothing_raised { 1.step(10, 0).size } assert_nothing_raised { 1.step(10, nil).size } - assert_nothing_raised { 1.step(by: 0, to: nil) } - assert_nothing_raised { 1.step(by: 0, to: nil).size } - assert_nothing_raised { 1.step(by: 0) } - assert_nothing_raised { 1.step(by: 0).size } assert_nothing_raised { 1.step(by: nil) } assert_nothing_raised { 1.step(by: nil).size } @@ -292,13 +304,26 @@ def test_step assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11) {} } assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11).size } - - e = assert_warn(/Using the last argument as keyword parameters is deprecated/) { - 1.step(10, {by: "1"}) - } - assert_warn('') { - assert_raise(ArgumentError) {e.size} - } + feature15573 = "[ruby-core:91324] [Feature #15573]" + assert_raise(ArgumentError, feature15573) { 1.step(10, 0) } + assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) } + assert_raise(ArgumentError, feature15573) { 1.step(10, 0) { break } } + assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) { break } } + assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: -Float::INFINITY) } + assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: 42.5) } + assert_raise(ArgumentError, feature15573) { 4.2.step(by: 0.0) } + assert_raise(ArgumentError, feature15573) { 4.2.step(by: -0.0) } + assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 44) } + assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 0) } + assert_raise(ArgumentError, feature15573) { 42.step(by: -0.0, to: 44) } + assert_raise(ArgumentError, feature15573) { bignum.step(by: 0) } + assert_raise(ArgumentError, feature15573) { bignum.step(by: 0.0) } + assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: bignum+1) } + assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: 0) } + + e = 1.step(10, {by: "1"}) + assert_raise(TypeError) {e.next} + assert_raise(TypeError) {e.size} assert_equal(bignum*2+1, (-bignum).step(bignum, 1).size) assert_equal(bignum*2, (-bignum).step(bignum-1, 1).size) @@ -325,8 +350,6 @@ def test_step assert_step [], [2, 1, 3] assert_step [], [-2, -1, -3] - assert_step [3, 3, 3, 3], [3, by: 0], inf: true - assert_step [3, 3, 3, 3], [3, by: 0, to: 42], inf: true assert_step [10], [10, 1, -bignum] assert_step [], [1, 0, Float::INFINITY] @@ -336,19 +359,6 @@ def test_step assert_step [10, 11, 12, 13], [10], inf: true assert_step [10, 9, 8, 7], [10, by: -1], inf: true assert_step [10, 9, 8, 7], [10, by: -1, to: nil], inf: true - - assert_step [42, 42, 42, 42], [42, by: 0, to: -Float::INFINITY], inf: true - assert_step [42, 42, 42, 42], [42, by: 0, to: 42.5], inf: true - assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: 0.0], inf: true - assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: -0.0], inf: true - assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 44], inf: true - assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 0], inf: true - assert_step [42.0, 42.0, 42.0, 42.0], [42, by: -0.0, to: 44], inf: true - - assert_step [bignum]*4, [bignum, by: 0], inf: true - assert_step [bignum]*4, [bignum, by: 0.0], inf: true - assert_step [bignum]*4, [bignum, by: 0, to: bignum+1], inf: true - assert_step [bignum]*4, [bignum, by: 0, to: 0], inf: true end def test_step_bug15537 @@ -391,6 +401,18 @@ def %(a) self; end end; end + def test_remainder_infinity + assert_equal(4, 4.remainder(Float::INFINITY)) + assert_equal(4, 4.remainder(-Float::INFINITY)) + assert_equal(-4, -4.remainder(Float::INFINITY)) + assert_equal(-4, -4.remainder(-Float::INFINITY)) + + assert_equal(4.2, 4.2.remainder(Float::INFINITY)) + assert_equal(4.2, 4.2.remainder(-Float::INFINITY)) + assert_equal(-4.2, -4.2.remainder(Float::INFINITY)) + assert_equal(-4.2, -4.2.remainder(-Float::INFINITY)) + end + def test_comparison_comparable bug12864 = '[ruby-core:77713] [Bug #12864]' @@ -438,6 +460,26 @@ def test_pow assert_equal(12, 12.pow(1, 10000000001), '[Bug #14259]') assert_equal(12, 12.pow(1, 10000000002), '[Bug #14259]') assert_equal(17298641040, 12.pow(72387894339363242, 243682743764), '[Bug #14259]') + + integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789] + integers.each do |i| + assert_equal(0, i.pow(0, 1), '[Bug #17257]') + assert_equal(1, i.pow(0, 2)) + assert_equal(1, i.pow(0, 3)) + assert_equal(1, i.pow(0, 6)) + assert_equal(1, i.pow(0, 1234567890123456789)) + + assert_equal(0, i.pow(0, -1)) + assert_equal(-1, i.pow(0, -2)) + assert_equal(-2, i.pow(0, -3)) + assert_equal(-5, i.pow(0, -6)) + assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789)) + end + + assert_equal(0, 0.pow(2, 1)) + assert_equal(0, 0.pow(3, 1)) + assert_equal(0, 2.pow(3, 1)) + assert_equal(0, -2.pow(3, 1)) end end diff --git a/ruby/test/ruby/test_object.rb b/ruby/test/ruby/test_object.rb index add5b9fb1..83208bbcd 100644 --- a/ruby/test/ruby/test_object.rb +++ b/ruby/test/ruby/test_object.rb @@ -5,7 +5,6 @@ class TestObject < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -47,15 +46,27 @@ def test_clone a = Object.new def a.b; 2 end + c = a.clone + assert_equal(false, c.frozen?) + assert_equal(false, a.frozen?) + assert_equal(2, c.b) + + c = a.clone(freeze: true) + assert_equal(true, c.frozen?) + assert_equal(false, a.frozen?) + assert_equal(2, c.b) + a.freeze c = a.clone assert_equal(true, c.frozen?) + assert_equal(true, a.frozen?) assert_equal(2, c.b) assert_raise(ArgumentError) {a.clone(freeze: [])} d = a.clone(freeze: false) def d.e; 3; end assert_equal(false, d.frozen?) + assert_equal(true, a.frozen?) assert_equal(2, d.b) assert_equal(3, d.e) @@ -75,6 +86,30 @@ def d.e; 3; end assert_raise_with_message(ArgumentError, /\u{1f4a9}/) do Object.new.clone(freeze: x) end + + c = Class.new do + attr_reader :f + end + o = c.new + def o.initialize_clone(_, freeze: true) + @f = freeze + super + end + clone = o.clone + assert_kind_of c, clone + assert_equal true, clone.f + clone = o.clone(freeze: false) + assert_kind_of c, clone + assert_equal false, clone.f + + class << o + remove_method(:initialize_clone) + end + def o.initialize_clone(_) + super + end + assert_kind_of c, o.clone + assert_raise(ArgumentError) { o.clone(freeze: false) } end def test_init_dupclone @@ -324,6 +359,7 @@ def test_convert_string o = Object.new def o.to_s; 1; end assert_raise(TypeError) { String(o) } + o.singleton_class.remove_method(:to_s) def o.to_s; "o"; end assert_equal("o", String(o)) def o.to_str; "O"; end @@ -336,6 +372,7 @@ def test_convert_array o = Object.new def o.to_a; 1; end assert_raise(TypeError) { Array(o) } + o.singleton_class.remove_method(:to_a) def o.to_a; [1]; end assert_equal([1], Array(o)) def o.to_ary; [2]; end @@ -353,6 +390,7 @@ def test_convert_hash o = Object.new def o.to_hash; {a: 1, b: 2}; end assert_equal({a: 1, b: 2}, Hash(o)) + o.singleton_class.remove_method(:to_hash) def o.to_hash; 9; end assert_raise(TypeError) { Hash(o) } end @@ -361,6 +399,7 @@ def test_to_integer o = Object.new def o.to_i; nil; end assert_raise(TypeError) { Integer(o) } + o.singleton_class.remove_method(:to_i) def o.to_i; 42; end assert_equal(42, Integer(o)) def o.respond_to?(*) false; end @@ -595,7 +634,7 @@ def test_implicit_respond_to_arity_1 called = [] p.singleton_class.class_eval do - define_method(:respond_to?) do |a| + define_method(:respond_to?) do |a, priv = false| called << [:respond_to?, a] false end @@ -738,7 +777,7 @@ def test_no_superclass_method e = assert_raise(NoMethodError) { o.never_defined_test_no_superclass_method } - assert_equal(m1, e.message, bug2312) + assert_equal(m1.lines.first, e.message.lines.first, bug2312) end def test_superclass_method @@ -954,13 +993,4 @@ def test_clone_object_should_not_be_old end EOS end - - def test_matcher - assert_warning(/deprecated Object#=~ is called on Object/) do - assert_equal(Object.new =~ 42, nil) - end - assert_warning(/deprecated Object#=~ is called on Array/) do - assert_equal([] =~ 42, nil) - end - end end diff --git a/ruby/test/ruby/test_objectspace.rb b/ruby/test/ruby/test_objectspace.rb index 243e9f681..e0f9eecd1 100644 --- a/ruby/test/ruby/test_objectspace.rb +++ b/ruby/test/ruby/test_objectspace.rb @@ -55,6 +55,16 @@ def test_id2ref_liveness EOS end + def test_id2ref_invalid_argument + msg = /no implicit conversion/ + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(nil)} + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(false)} + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(true)} + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(:a)} + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref("0")} + assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(Object.new)} + end + def test_count_objects h = {} ObjectSpace.count_objects(h) @@ -151,6 +161,40 @@ def foo END end + def test_exception_in_finalizer + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], /finalizing \(RuntimeError\)/) + begin; + ObjectSpace.define_finalizer(Object.new) {raise "finalizing"} + end; + end + + def test_finalizer_thread_raise + GC.disable + fzer = proc do |id| + sleep 0.2 + end + 2.times do + o = Object.new + ObjectSpace.define_finalizer(o, fzer) + end + + my_error = Class.new(RuntimeError) + begin + main_th = Thread.current + Thread.new do + sleep 0.1 + main_th.raise(my_error) + end + GC.start + puts "After GC" + sleep(10) + assert(false) + rescue my_error + end + ensure + GC.enable + end + def test_each_object klass = Class.new new_obj = klass.new @@ -175,7 +219,7 @@ def test_each_object_enumerator assert_same(new_obj, found[0]) end - def test_each_object_no_gabage + def test_each_object_no_garbage assert_separately([], <<-End) GC.disable eval('begin; 1.times{}; rescue; ensure; end') @@ -223,4 +267,11 @@ class << self assert_kind_of(meta, sclass) assert_include(ObjectSpace.each_object(meta).to_a, sclass) end + + def test_each_object_with_allocation + assert_normal_exit(<<-End) + list = [] + ObjectSpace.each_object { |o| list << Object.new } + End + end end diff --git a/ruby/test/ruby/test_optimization.rb b/ruby/test/ruby/test_optimization.rb index b42314b76..43795d150 100644 --- a/ruby/test/ruby/test_optimization.rb +++ b/ruby/test/ruby/test_optimization.rb @@ -150,6 +150,64 @@ def test_string_uminus assert_redefine_method('String', '-@', 'assert_nil(-"foo")') end + def test_array_min + assert_equal 1, [1, 2, 4].min + assert_redefine_method('Array', 'min', 'assert_nil([1, 2, 4].min)') + assert_redefine_method('Array', 'min', 'assert_nil([1 + 0, 2, 4].min)') + end + + def test_array_max + assert_equal 4, [1, 2, 4].max + assert_redefine_method('Array', 'max', 'assert_nil([1, 2, 4].max)') + assert_redefine_method('Array', 'max', 'assert_nil([1 + 0, 2, 4].max)') + end + + def test_trace_optimized_methods + bug14870 = "[ruby-core:87638]" + expected = [:-@, :max, :min, :+, :-, :*, :/, :%, :==, :<, :<=, :>, :>=, :<<, + :&, :|, :[], :[]=, :length, :empty?, :nil?, :succ, :!, :=~] + [:c_call, :c_return].each do |type| + methods = [] + tp = TracePoint.new(type) { |tp| methods << tp.method_id } + tp.enable do + x = "a"; x = -x + [1].max + [1].min + x = 42 + 2 + x = 42 - 2 + x = 42 * 2 + x = 42 / 2 + x = 42 % 2 + y = x == 42 + y = x < 42 + y = x <= 42 + y = x > 42 + y = x >= 42 + x = x << 1 + x = x & 1 + x = x | 1 + x = []; x[1] + x[1] = 2 + x.length + x.empty? + x.nil? + x = 1; x.succ + !x + x = 'a'; x =~ /a/ + x = y + end + assert_equal(expected, methods, bug14870) + end + + methods = [] + tp = TracePoint.new(:c_call, :c_return) { |tp| methods << tp.method_id } + tp.enable do + x = 1 + x != 42 + end + assert_equal([:!=, :==, :==, :!=], methods, bug14870) + end + def test_string_freeze_saves_memory n = 16384 data = '.'.freeze @@ -452,7 +510,7 @@ def run(current, final) end def test_tailcall_not_to_grow_stack - skip 'currently JIT-ed code always creates a new stack frame' if RubyVM::MJIT.enabled? + skip 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? bug16161 = '[ruby-core:94881]' tailcall("#{<<-"begin;"}\n#{<<~"end;"}") @@ -701,16 +759,16 @@ def test_block_parameter def test_block_parameter_should_not_create_objects assert_separately [], <<-END - # def foo &b end h1 = {}; h2 = {} - ObjectSpace.count_objects(h1) # reharsal + ObjectSpace.count_objects(h1) # rehearsal + GC.start; GC.disable # to disable GC while foo{} ObjectSpace.count_objects(h1) foo{} ObjectSpace.count_objects(h2) - assert_equal 0, h2[:TOTAL] - h1[:TOTAL] + assert_equal 0, h2[:T_DATA] - h1[:T_DATA] # Proc is T_DATA END end @@ -845,4 +903,34 @@ def test_optimized_rescue raise "END" end; end + + class Objtostring + end + + def test_objtostring + assert_raise(NoMethodError){"#{BasicObject.new}"} + assert_redefine_method('Symbol', 'to_s', <<-'end') + assert_match %r{\A#\z}, "#{:foo}" + end + assert_redefine_method('NilClass', 'to_s', <<-'end') + assert_match %r{\A#\z}, "#{nil}" + end + assert_redefine_method('TrueClass', 'to_s', <<-'end') + assert_match %r{\A#\z}, "#{true}" + end + assert_redefine_method('FalseClass', 'to_s', <<-'end') + assert_match %r{\A#\z}, "#{false}" + end + assert_redefine_method('Integer', 'to_s', <<-'end') + (-1..10).each { |i| + assert_match %r{\A#\z}, "#{i}" + } + end + assert_equal "TestRubyOptimization::Objtostring", "#{Objtostring}" + assert_match %r{\A#\z}, "#{Class.new}" + assert_match %r{\A#\z}, "#{Module.new}" + o = Object.new + def o.to_s; 1; end + assert_match %r{\A#\z}, "#{o}" + end end diff --git a/ruby/test/ruby/test_pack.rb b/ruby/test/ruby/test_pack.rb index 60edd0018..9738f82b7 100644 --- a/ruby/test/ruby/test_pack.rb +++ b/ruby/test/ruby/test_pack.rb @@ -638,6 +638,14 @@ def test_pack_unpack_m end; end + def test_bug_18343 + bug18343 = '[ruby-core:106096] [Bug #18343]' + assert_separately(%W[- #{bug18343}], <<-'end;') + bug = ARGV.shift + assert_raise(ArgumentError, bug){[0].pack('c', {})} + end; + end + def test_pack_unpack_m0 assert_equal("", [""].pack("m0")) assert_equal("AA==", ["\0"].pack("m0")) @@ -764,7 +772,7 @@ def test_pack_garbage $VERBOSE = true - _, err = capture_io do + _, err = capture_output do assert_equal "\000", [0].pack("*U") end @@ -783,7 +791,7 @@ def test_unpack_garbage $VERBOSE = true - _, err = capture_io do + _, err = capture_output do assert_equal [0], "\000".unpack("*U") end @@ -869,4 +877,30 @@ def test_unpack1 assert_equal "hogefuga", "aG9nZWZ1Z2E=".unpack1("m") assert_equal "01000001", "A".unpack1("B*") end + + def test_unpack1_offset + assert_equal 65, "ZA".unpack1("C", offset: 1) + assert_equal "01000001", "YZA".unpack1("B*", offset: 2) + assert_nil "abc".unpack1("C", offset: 3) + assert_raise_with_message(ArgumentError, /offset can't be negative/) { + "a".unpack1("C", offset: -1) + } + assert_raise_with_message(ArgumentError, /offset outside of string/) { + "a".unpack1("C", offset: 2) + } + assert_nil "a".unpack1("C", offset: 1) + end + + def test_unpack_offset + assert_equal [65], "ZA".unpack("C", offset: 1) + assert_equal ["01000001"], "YZA".unpack("B*", offset: 2) + assert_equal [nil, nil, nil], "abc".unpack("CCC", offset: 3) + assert_raise_with_message(ArgumentError, /offset can't be negative/) { + "a".unpack("C", offset: -1) + } + assert_raise_with_message(ArgumentError, /offset outside of string/) { + "a".unpack("C", offset: 2) + } + assert_equal [nil], "a".unpack("C", offset: 1) + end end diff --git a/ruby/test/ruby/test_parse.rb b/ruby/test/ruby/test_parse.rb index 1e909bce1..d697a29c1 100644 --- a/ruby/test/ruby/test_parse.rb +++ b/ruby/test/ruby/test_parse.rb @@ -6,7 +6,6 @@ class TestParse < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -399,7 +398,6 @@ def test_disallowed_gloal_variable def test_arg2 o = Object.new - assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end @@ -411,6 +409,7 @@ def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end assert_equal(-42100, o.foo(1) {|x| -x }) assert_raise(ArgumentError) { o.foo() } + o = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,z,&b); b.call(a*1000+z*100); end @@ -420,6 +419,7 @@ def o.foo(a=42,z,&b); b.call(a*1000+z*100); end assert_equal(-42100, o.foo(1) {|x| -x } ) assert_raise(ArgumentError) { o.foo() } + o = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end @@ -562,6 +562,21 @@ def test_string assert_syntax_error("\"\\M-\x01\"", 'Invalid escape character syntax') assert_syntax_error("\"\\M-\\C-\x01\"", 'Invalid escape character syntax') assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax') + + e = assert_syntax_error('"\c\u0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~'"\n", e.message.lines.last) + e = assert_syntax_error('"\c\U0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~'"\n", e.message.lines.last) + + e = assert_syntax_error('"\C-\u0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~~'"\n", e.message.lines.last) + e = assert_syntax_error('"\C-\U0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~~'"\n", e.message.lines.last) + + e = assert_syntax_error('"\M-\u0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~~'"\n", e.message.lines.last) + e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax') + assert_equal(' ^~~~~'"\n", e.message.lines.last) end def test_question @@ -599,6 +614,9 @@ def test_percent assert_syntax_error('%s', /unterminated quoted string/) assert_syntax_error('%ss', /unknown type/) assert_syntax_error('%z()', /unknown type/) + assert_syntax_error("%\u3042", /unknown type/) + assert_syntax_error("%q\u3042", /unknown type/) + assert_syntax_error("%", /unterminated quoted string/) end def test_symbol @@ -666,6 +684,15 @@ def test_here_document def test_magic_comment x = nil + + assert_nothing_raised do + eval <<-END, nil, __FILE__, __LINE__+1 +# coding: utf-8 +x = __ENCODING__ + END + end + assert_equal(Encoding.find("UTF-8"), x) + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 # coding = utf-8 @@ -680,6 +707,14 @@ def test_magic_comment x = __ENCODING__ END end + + assert_nothing_raised do + eval <<-END, nil, __FILE__, __LINE__+1 +# xxxx : coding sjis +x = __ENCODING__ + END + end + assert_equal(__ENCODING__, x) end def test_utf8_bom @@ -722,13 +757,13 @@ def test_embedded_rd_error end def test_float - assert_equal(1.0/0, eval("1e10000")) + assert_predicate(assert_warning(/out of range/) {eval("1e10000")}, :infinite?) assert_syntax_error('1_E', /trailing `_'/) assert_syntax_error('1E1E1', /unexpected constant/) end def test_global_variable - assert_equal(nil, eval('$-x')) + assert_equal(nil, assert_warning(/not initialized/) {eval('$-x')}) assert_equal(nil, eval('alias $preserve_last_match $&')) assert_equal(nil, eval('alias $& $test_parse_foobarbazqux')) $test_parse_foobarbazqux = nil @@ -821,13 +856,13 @@ def test_void_expr_stmts_value end def test_assign_in_conditional - assert_nothing_raised do + assert_warning(/`= literal' in conditional/) do eval <<-END, nil, __FILE__, __LINE__+1 (x, y = 1, 2) ? 1 : 2 END end - assert_nothing_raised do + assert_warning(/`= literal' in conditional/) do eval <<-END, nil, __FILE__, __LINE__+1 if @x = true 1 @@ -839,13 +874,13 @@ def test_assign_in_conditional end def test_literal_in_conditional - assert_nothing_raised do + assert_warning(/string literal in condition/) do eval <<-END, nil, __FILE__, __LINE__+1 "foo" ? 1 : 2 END end - assert_nothing_raised do + assert_warning(/regex literal in condition/) do x = "bar" eval <<-END, nil, __FILE__, __LINE__+1 /foo#{x}baz/ ? 1 : 2 @@ -858,13 +893,13 @@ def test_literal_in_conditional END end - assert_nothing_raised do + assert_warning(/string literal in flip-flop/) do eval <<-END, nil, __FILE__, __LINE__+1 ("foo".."bar") ? 1 : 2 END end - assert_nothing_raised do + assert_warning(/literal in condition/) do x = "bar" eval <<-END, nil, __FILE__, __LINE__+1 :"foo#{"x"}baz" ? 1 : 2 @@ -1009,7 +1044,7 @@ def test_error_def_in_argument end; assert_syntax_error("def\nf(000)end", /^ \^~~/) - assert_syntax_error("def\nf(&)end", /^ \^/) + assert_syntax_error("def\nf(&0)end", /^ \^/) end def test_method_location_in_rescue @@ -1045,6 +1080,32 @@ def test_file_in_indented_heredoc end; end + def test_heredoc_interpolation + var = 1 + + v1 = <<~HEREDOC + something + #{"/#{var}"} + HEREDOC + + v2 = <<~HEREDOC + something + #{_other = "/#{var}"} + HEREDOC + + v3 = <<~HEREDOC + something + #{("/#{var}")} + HEREDOC + + assert_equal "something\n/1\n", v1 + assert_equal "something\n/1\n", v2 + assert_equal "something\n/1\n", v3 + assert_equal v1, v2 + assert_equal v2, v3 + assert_equal v1, v3 + end + def test_unexpected_token_error assert_syntax_error('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', /unexpected/) end @@ -1101,6 +1162,10 @@ def test_eof_in_def assert_syntax_error("def m\n\C-z""end", /unexpected/) end + def test_unexpected_eof + assert_syntax_error('unless', /^ \^\Z/) + end + def test_location_of_invalid_token assert_syntax_error('class xxx end', /^ \^~~\Z/) end @@ -1166,10 +1231,128 @@ def test_cdmarg_after_command_args_and_tlbrace_arg assert_valid_syntax('let () { m(a) do; end }') end - def test_void_value_in_command_rhs + def test_void_value_in_rhs w = "void value expression" - ex = assert_syntax_error("x = return 1", w) - assert_equal(1, ex.message.scan(w).size, "same #{w.inspect} warning should be just once") + ["x = return 1", "x = return, 1", "x = 1, return", "x, y = return"].each do |code| + ex = assert_syntax_error(code, w) + assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"}) + end + end + + def eval_separately(code) + Class.new.class_eval(code) + end + + def assert_raise_separately(error, message, code) + assert_raise_with_message(error, message) do + eval_separately(code) + end + end + + def assert_ractor_shareable(obj) + assert Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} to be ractor shareable"} + end + + def assert_not_ractor_shareable(obj) + assert !Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} not to be ractor shareable"} + end + + def test_shareable_constant_value_invalid + assert_warning(/invalid value/) do + assert_valid_syntax("# shareable_constant_value: invalid-option", verbose: true) + end + end + + def test_shareable_constant_value_ignored + assert_warning(/ignored/) do + assert_valid_syntax("nil # shareable_constant_value: true", verbose: true) + end + end + + def test_shareable_constant_value_simple + obj = [['unsharable_value']] + a, b, c = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: experimental_everything + A = [[1]] + # shareable_constant_value: none + B = [[2]] + # shareable_constant_value: literal + C = [["shareable", "constant#{nil}"]] + D = A + + [A, B, C] + end; + assert_ractor_shareable(a) + assert_not_ractor_shareable(b) + assert_ractor_shareable(c) + assert_equal([1], a[0]) + assert_ractor_shareable(a[0]) + + a, obj = eval_separately(<<~'end;') + # shareable_constant_value: experimental_copy + obj = [["unshareable"]] + A = obj + [A, obj] + end; + + assert_ractor_shareable(a) + assert_not_ractor_shareable(obj) + assert_equal obj, a + assert !obj.equal?(a) + end + + def test_shareable_constant_value_nested + a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: none + class X + # shareable_constant_value: experimental_everything + var = [[1]] + A = var + end + B = [] + [X::A, B] + end; + assert_ractor_shareable(a) + assert_not_ractor_shareable(b) + assert_equal([1], a[0]) + assert_ractor_shareable(a[0]) + end + + def test_shareable_constant_value_unshareable_literal + assert_raise_separately(Ractor::IsolationError, /unshareable/, + "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: literal + C = ["Not " + "shareable"] + end; + end + + def test_shareable_constant_value_nonliteral + assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: literal + var = [:not_frozen] + C = var + end; + + assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: literal + D = begin [] end + end; + end + + def test_shareable_constant_value_unfrozen + assert_raise_separately(Ractor::Error, /does not freeze object correctly/, + "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + # shareable_constant_value: experimental_everything + o = Object.new + def o.freeze; self; end + C = [o] + end; end =begin diff --git a/ruby/test/ruby/test_pattern_matching.rb b/ruby/test/ruby/test_pattern_matching.rb index 2afa823d5..35c41eb8b 100644 --- a/ruby/test/ruby/test_pattern_matching.rb +++ b/ruby/test/ruby/test_pattern_matching.rb @@ -4,6 +4,25 @@ experimental, Warning[:experimental] = Warning[:experimental], false # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!" eval "\n#{<<~'END_of_GUARD'}", binding, __FILE__, __LINE__ class TestPatternMatching < Test::Unit::TestCase + class NullFormatter + def message_for(corrections) + "" + end + end + + def setup + if defined?(DidYouMean) + @original_formatter = DidYouMean.formatter + DidYouMean.formatter = NullFormatter.new + end + end + + def teardown + if defined?(DidYouMean) + DidYouMean.formatter = @original_formatter + end + end + class C class << self attr_accessor :keys @@ -272,7 +291,7 @@ def test_var_pattern end assert_syntax_error(%q{ - 0 in [a, a] + 0 => [a, a] }, /duplicated variable name/) end @@ -400,6 +419,53 @@ def test_pin_operator_value_pattern a == 0 end end + + assert_block do + @a = /a/ + case 'abc' + in ^@a + true + end + end + + assert_block do + @@TestPatternMatching = /a/ + case 'abc' + in ^@@TestPatternMatching + true + end + end + + assert_block do + $TestPatternMatching = /a/ + case 'abc' + in ^$TestPatternMatching + true + end + end + end + + def test_pin_operator_expr_pattern + assert_block do + case 'abc' + in ^(/a/) + true + end + end + + assert_block do + case {name: '2.6', released_at: Time.new(2018, 12, 25)} + in {released_at: ^(Time.new(2010)..Time.new(2020))} + true + end + end + + assert_block do + case 0 + in ^(0+0) + true + end + end end def test_array_pattern @@ -736,6 +802,74 @@ def test_array_pattern end end + def test_find_pattern + [0, 1, 2] => [*, 1 => a, *] + assert_equal(1, a) + + [0, 1, 2] => [*a, 1 => b, *c] + assert_equal([0], a) + assert_equal(1, b) + assert_equal([2], c) + + assert_block do + case [0, 1, 2] + in [*, 9, *] + false + else + true + end + end + + assert_block do + case [0, 1, 2] + in [*, Integer, String, *] + false + else + true + end + end + + [0, 1, 2] => [*a, 1 => b, 2 => c, *d] + assert_equal([0], a) + assert_equal(1, b) + assert_equal(2, c) + assert_equal([], d) + + case [0, 1, 2] + in *, 1 => a, *; + assert_equal(1, a) + end + + assert_block do + case [0, 1, 2] + in String(*, 1, *) + false + in Array(*, 1, *) + true + end + end + + assert_block do + case [0, 1, 2] + in String[*, 1, *] + false + in Array[*, 1, *] + true + end + end + + # https://bugs.ruby-lang.org/issues/17534 + assert_block do + case [0, 1, 2] + in x + x = x # avoid a warning "assigned but unused variable - x" + true + in [*, 2, *] + false + end + end + end + def test_hash_pattern assert_block do [{}, C.new({})].all? do |i| @@ -1105,6 +1239,10 @@ def test_paren end end + def test_nomatchingpatternerror + assert_equal(StandardError, NoMatchingPatternError.superclass) + end + def test_invalid_syntax assert_syntax_error(%q{ case 0 @@ -1208,6 +1346,94 @@ def test_deconstruct_keys ################################################################ + class CDeconstructCache + def initialize(v) + @v = v + end + + def deconstruct + @v.shift + end + end + + def test_deconstruct_cache + assert_block do + case CDeconstructCache.new([[0]]) + in [1] + in [0] + true + end + end + + assert_block do + case CDeconstructCache.new([[0, 1]]) + in [1,] + in [0,] + true + end + end + + assert_block do + case CDeconstructCache.new([[[0]]]) + in [[1]] + in [[*a]] + a == [0] + end + end + + assert_block do + case CDeconstructCache.new([[0]]) + in [x] if x > 0 + in [0] + true + end + end + + assert_block do + case CDeconstructCache.new([[0]]) + in [] + in [1] | [0] + true + end + end + + assert_block do + case CDeconstructCache.new([[0]]) + in [1] => _ + in [0] => _ + true + end + end + + assert_block do + case CDeconstructCache.new([[0]]) + in C[0] + in CDeconstructCache[0] + true + end + end + + assert_block do + case [CDeconstructCache.new([[0], [1]])] + in [[1]] + false + in [[1]] + true + end + end + + assert_block do + case CDeconstructCache.new([[0, :a, 1]]) + in [*, String => x, *] + false + in [*, Symbol => x, *] + x == :a + end + end + end + + ################################################################ + class TestPatternMatchingRefinements < Test::Unit::TestCase class C1 def deconstruct @@ -1306,19 +1532,22 @@ def test_struct ################################################################ - def test_modifier_in - 1 in a + def test_one_line + 1 => a assert_equal 1, a assert_raise(NoMatchingPatternError) do - {a: 1} in {a: 0} + {a: 1} => {a: 0} end - assert_syntax_error("if {} in {a:}; end", /void value expression/) - assert_syntax_error(%q{ - 1 in a, b - }, /unexpected/, '[ruby-core:95098]') - assert_syntax_error(%q{ - 1 in a: - }, /unexpected/, '[ruby-core:95098]') + + [1, 2] => a, b + assert_equal 1, a + assert_equal 2, b + + {a: 1} => a: + assert_equal 1, a + + assert_equal true, (1 in 1) + assert_equal false, (1 in 2) end def assert_experimental_warning(code) @@ -1328,14 +1557,140 @@ def assert_experimental_warning(code) assert_warn('') {eval(code)} Warning[:experimental] = true - assert_warn(/Pattern matching is experimental/) {eval(code)} + assert_warn(/is experimental/) {eval(code)} ensure Warning[:experimental] = w end def test_experimental_warning - assert_experimental_warning("case 0; in 0; end") - assert_experimental_warning("0 in 0") + assert_experimental_warning("case [0]; in [*, 0, *]; end") + end + + ################################################################ + + def test_single_pattern_error_value_pattern + assert_raise_with_message(NoMatchingPatternError, "0: 1 === 0 does not return true") do + 0 => 1 + end + end + + def test_single_pattern_error_array_pattern + assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do + [] => Hash[] + end + + assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do + 0 => [] + end + + assert_raise_with_message(NoMatchingPatternError, "[0]: [0] length mismatch (given 1, expected 0)") do + [0] => [] + end + + assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do + [] => [_, *] + end + + assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do + [0, 0] => [0, 1] + end + + assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do + [0, 0] => [*, 0, 1] + end + end + + def test_single_pattern_error_find_pattern + assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do + [] => Hash[*, _, *] + end + + assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do + 0 => [*, _, *] + end + + assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do + [] => [*, _, *] + end + + assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do + [0] => [*, 1, *] + end + + assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do + [0] => [*, {a:}, *] + raise a # suppress "unused variable: a" warning + end + end + + def test_single_pattern_error_hash_pattern + assert_raise_with_message(NoMatchingPatternError, "{}: Array === {} does not return true") do + {} => Array[a:] + raise a # suppress "unused variable: a" warning + end + + assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct_keys") do + 0 => {a:} + raise a # suppress "unused variable: a" warning + end + + assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>0}: key not found: :aa") do + {a: 0} => {aa:} + raise aa # suppress "unused variable: aa" warning + rescue NoMatchingPatternKeyError => e + assert_equal({a: 0}, e.matchee) + assert_equal(:aa, e.key) + raise e + end + + assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>{:b=>0}}: key not found: :bb") do + {a: {b: 0}} => {a: {bb:}} + raise bb # suppress "unused variable: bb" warning + rescue NoMatchingPatternKeyError => e + assert_equal({b: 0}, e.matchee) + assert_equal(:bb, e.key) + raise e + end + + assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: 1 === 0 does not return true") do + {a: 0} => {a: 1} + end + + assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: {:a=>0} is not empty") do + {a: 0} => {} + end + + assert_raise_with_message(NoMatchingPatternError, "[{:a=>0}]: rest of {:a=>0} is not empty") do + [{a: 0}] => [{**nil}] + end + end + + def test_single_pattern_error_as_pattern + assert_raise_with_message(NoMatchingPatternError, "[0]: 1 === 0 does not return true") do + case [0] + in [1] => _ + end + end + end + + def test_single_pattern_error_alternative_pattern + assert_raise_with_message(NoMatchingPatternError, "0: 2 === 0 does not return true") do + 0 => 1 | 2 + end + end + + def test_single_pattern_error_guard_clause + assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do + case 0 + in _ if false + end + end + + assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do + case 0 + in _ unless true + end + end end end END_of_GUARD diff --git a/ruby/test/ruby/test_primitive.rb b/ruby/test/ruby/test_primitive.rb index 19af44ad3..f1db93400 100644 --- a/ruby/test/ruby/test_primitive.rb +++ b/ruby/test/ruby/test_primitive.rb @@ -26,24 +26,31 @@ def test_lvar assert_equal 4, c end - C = 1 - class A - Const = 1 - class B - Const = 2 - class C - Const = 3 - def const - Const + C_Setup = -> do + remove_const :C if defined? ::TestRubyPrimitive::C + remove_const :A if defined? ::TestRubyPrimitive::A + + C = 1 + class A + Const = 1 + class B + Const = 2 + class C + Const = 3 + def const + Const + end end end end + (1..2).map { + A::B::C::Const + } end - (1..2).map { - A::B::C::Const - } def test_constant + C_Setup.call + assert_equal 1, C assert_equal 1, C assert_equal 1, A::Const @@ -145,42 +152,60 @@ def test_gvar assert_equal 7, ($test_ruby_primitive_gvar = 7) end - class A7 - @@c = 1 - def m - @@c += 1 + A7_Setup = -> do + remove_const :A7 if defined? TestRubyPrimitive::A7 + + class A7 + @@c = 1 + def m + @@c += 1 + end end end def test_cvar_from_instance_method + A7_Setup.call + assert_equal 2, A7.new.m assert_equal 3, A7.new.m assert_equal 4, A7.new.m end - class A8 - @@c = 1 - class << self - def m - @@c += 1 + A8_Setup = -> do + remove_const :A8 if defined? TestRubyPrimitive::A8 + + class A8 + @@c = 1 + class << self + def m + @@c += 1 + end end end end def test_cvar_from_singleton_method + A8_Setup.call + assert_equal 2, A8.m assert_equal 3, A8.m assert_equal 4, A8.m end - class A9 - @@c = 1 - def self.m - @@c += 1 + A9_Setup = -> do + remove_const :A8 if defined? TestRubyPrimitive::A8 + + class A9 + @@c = 1 + def self.m + @@c += 1 + end end end def test_cvar_from_singleton_method2 + A9_Setup.call + assert_equal 2, A9.m assert_equal 3, A9.m assert_equal 4, A9.m @@ -199,6 +224,9 @@ def test_opassign @iv += 2 assert_equal 4, @iv + # init @@cv + @@cv = nil + @@cv ||= 1 assert_equal 1, @@cv @@cv &&= 2 diff --git a/ruby/test/ruby/test_proc.rb b/ruby/test/ruby/test_proc.rb index 3f0d599a0..51872e49b 100644 --- a/ruby/test/ruby/test_proc.rb +++ b/ruby/test/ruby/test_proc.rb @@ -4,7 +4,6 @@ class TestProc < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -53,16 +52,14 @@ def self.dyna_var_check assert_equal(5, x) end - def assert_arity(n) + def assert_arity(n, &block) meta = class << self; self; end - b = assert_warn(/Capturing the given block using Proc\.new is deprecated/) do - Proc.new - end + b = Proc.new(&block) meta.class_eval { - remove_method(:foo) if method_defined?(:foo) - define_method(:foo, b) + remove_method(:foo_arity) if method_defined?(:foo_arity) + define_method(:foo_arity, b) } - assert_equal(n, method(:foo).arity) + assert_equal(n, method(:foo_arity).arity) end def test_arity @@ -139,6 +136,14 @@ def m(x) lambda { x } end + def m_nest0(&block) + block + end + + def m_nest(&block) + [m_nest0(&block), m_nest0(&block)] + end + def test_eq a = m(1) b = m(2) @@ -150,6 +155,17 @@ def test_eq a = lambda {|x| lambda {} }.call(1) b = lambda {} assert_not_equal(a, b, "[ruby-dev:22601]") + + assert_equal(*m_nest{}, "[ruby-core:84583] Feature #14627") + end + + def test_hash + def self.capture(&block) + block + end + + procs = Array.new(1000){capture{:foo }} + assert_operator(procs.map(&:hash).uniq.size, :>=, 500) end def test_block_par @@ -263,7 +279,7 @@ def test_curry_no_arguments def test_curry_given_blocks b = lambda {|x, y, &blk| blk.call(x + y) }.curry - b = b.call(2) { raise } + b = assert_warning(/given block not used/) {b.call(2) { raise }} b = b.call(3) {|x| x + 4 } assert_equal(9, b) end @@ -273,7 +289,7 @@ def test_lambda? assert_equal(false, l.lambda?) assert_equal(false, l.curry.lambda?, '[ruby-core:24127]') assert_equal(false, proc(&l).lambda?) - assert_equal(false, lambda(&l).lambda?) + assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?) assert_equal(false, Proc.new(&l).lambda?) l = lambda {} assert_equal(true, l.lambda?) @@ -283,6 +299,49 @@ def test_lambda? assert_equal(true, Proc.new(&l).lambda?) end + def self.helper_test_warn_lamda_with_passed_block &b + lambda(&b) + end + + def self.def_lambda_warning name, warn + define_method(name, proc do + prev = Warning[:deprecated] + assert_warn warn do + Warning[:deprecated] = true + yield + end + ensure + Warning[:deprecated] = prev + end) + end + + def_lambda_warning 'test_lambda_warning_normal', '' do + lambda{} + end + + def_lambda_warning 'test_lambda_warning_pass_lambda', '' do + b = lambda{} + lambda(&b) + end + + def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do + lambda(&:to_s) + end + + def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do + b = proc{} + lambda(&b) + end + + def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do + helper_test_warn_lamda_with_passed_block{} + end + + def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do + # Symbol#to_proc returns lambda + helper_test_warn_lamda_with_passed_block(&:to_s) + end + def test_curry_ski_fib s = proc {|f, g, x| f[x][g[x]] }.curry k = proc {|x, y| x }.curry @@ -383,7 +442,7 @@ def test_binding_source_location def test_proc_lambda assert_raise(ArgumentError) { proc } - assert_raise(ArgumentError) { lambda } + assert_raise(ArgumentError) { assert_warn(/deprecated/) {lambda} } o = Object.new def o.foo @@ -391,14 +450,18 @@ def o.foo 1.times { b = lambda } b end - assert_raise(ArgumentError) {o.foo { :foo }.call} + assert_raise(ArgumentError) do + assert_deprecated_warning {o.foo { :foo }}.call + end - def o.foo(&b) + def o.bar(&b) b = nil 1.times { b = lambda } b end - assert_raise(ArgumentError) {o.foo { :foo }.call} + assert_raise(ArgumentError) do + assert_deprecated_warning {o.bar { :foo }}.call + end end def test_arity2 @@ -784,6 +847,33 @@ def test_proc_args_rest_block assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x}) end + def test_proc_args_only_rest + pr = proc {|*c| c } + assert_equal [], pr.call() + assert_equal [1], pr.call(1) + assert_equal [[1]], pr.call([1]) + assert_equal [1, 2], pr.call(1,2) + assert_equal [[1, 2]], pr.call([1,2]) + end + + def test_proc_args_rest_kw + pr = proc {|*c, a: 1| [c, a] } + assert_equal [[], 1], pr.call() + assert_equal [[1], 1], pr.call(1) + assert_equal [[[1]], 1], pr.call([1]) + assert_equal [[1, 2], 1], pr.call(1,2) + assert_equal [[[1, 2]], 1], pr.call([1,2]) + end + + def test_proc_args_rest_kwsplat + pr = proc {|*c, **kw| [c, kw] } + assert_equal [[], {}], pr.call() + assert_equal [[1], {}], pr.call(1) + assert_equal [[[1]], {}], pr.call([1]) + assert_equal [[1, 2], {}], pr.call(1,2) + assert_equal [[[1, 2]], {}], pr.call([1,2]) + end + def test_proc_args_pos_rest_post_block pr = proc {|a,b,*c,d,e,&f| [a, b, c, d, e, f.class, f&&f.call(:x)] @@ -1107,6 +1197,16 @@ def self.a(arg, kw) assert_equal([[1, 2], [[1, 2, 3], {a: 1}], [[1, 2, 3], {a: 1}]], arr) end + def test_proc_single_arg_with_keywords_accepted_and_yielded + def self.a + yield [], **{a: 1} + end + res = a do |arg, **opts| + [arg, opts] + end + assert_equal([[], {a: 1}], res) + end + def test_parameters assert_equal([], proc {}.parameters) assert_equal([], proc {||}.parameters) @@ -1396,16 +1496,6 @@ def m(&blk) blk.call; end end; end - def method_for_test_proc_without_block_for_symbol - assert_warn(/Capturing the given block using Kernel#proc is deprecated/) do - binding.eval('proc') - end - end - - def test_proc_without_block_for_symbol - assert_equal('1', method_for_test_proc_without_block_for_symbol(&:to_s).call(1), '[Bug #14782]') - end - def test_compose f = proc {|x| x * 2} g = proc {|x| x + 1} @@ -1433,9 +1523,13 @@ def test_compose_with_block def test_compose_with_lambda f = lambda {|x| x * 2} g = lambda {|x| x} + not_lambda = proc {|x| x} assert_predicate((f << g), :lambda?) assert_predicate((g >> f), :lambda?) + assert_predicate((not_lambda << f), :lambda?) + assert_not_predicate((f << not_lambda), :lambda?) + assert_not_predicate((not_lambda >> f), :lambda?) end def test_compose_with_method @@ -1447,6 +1541,7 @@ def g(x) x + 1 end assert_equal(6, (f << g).call(2)) assert_equal(5, (f >> g).call(2)) + assert_predicate((f << g), :lambda?) end def test_compose_with_callable @@ -1458,6 +1553,7 @@ def call(x) x + 1 end assert_equal(6, (f << g).call(2)) assert_equal(5, (f >> g).call(2)) + assert_predicate((f << g), :lambda?) end def test_compose_with_noncallable @@ -1497,6 +1593,63 @@ def m1(&b) b end; def m2(); m1 { next 42 }.call end }.m2) assert_equal(42, Module.new { extend self def m1(&b) b end; def m2(); m1 { next 42 } end }.m2.call) end + + def test_isolate + assert_raise_with_message ArgumentError, /\(a\)/ do + a = :a + Proc.new{p a}.isolate + end + + assert_raise_with_message ArgumentError, /\(a\)/ do + a = :a + 1.times{ + Proc.new{p a}.isolate + } + end + + assert_raise_with_message ArgumentError, /yield/ do + Proc.new{yield}.isolate + end + + + name = "\u{2603 26a1}" + assert_raise_with_message(ArgumentError, /\(#{name}\)/) do + eval("#{name} = :#{name}; Proc.new {p #{name}}").isolate + end + + # binding + + :a.tap{|a| + :b.tap{|b| + Proc.new{ + :c.tap{|c| + assert_equal :c, eval('c') + + assert_raise_with_message SyntaxError, /\`a\'/ do + eval('p a') + end + + assert_raise_with_message SyntaxError, /\`b\'/ do + eval('p b') + end + + assert_raise_with_message SyntaxError, /can not yield from isolated Proc/ do + eval('p yield') + end + + assert_equal :c, binding.local_variable_get(:c) + + assert_raise_with_message NameError, /local variable \`a\' is not defined/ do + binding.local_variable_get(:a) + end + + assert_equal [:c], local_variables + assert_equal [:c], binding.local_variables + } + }.isolate.call + } + } + end if proc{}.respond_to? :isolate end class TestProcKeywords < Test::Unit::TestCase @@ -1505,29 +1658,15 @@ def test_compose_keywords g = ->(kw) { kw.merge(:a=>2) } assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end + assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end + assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end + assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } + assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f << g).call(**{})[:a] } assert_equal(2, (f >> g).call(**{})[:a]) end @@ -1535,29 +1674,15 @@ def test_compose_keywords_method f = ->(**kw) { kw.merge(:a=>1) }.method(:call) g = ->(kw) { kw.merge(:a=>2) }.method(:call) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end + assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end + assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end + assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } + assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f << g).call(**{})[:a] } assert_equal(2, (f >> g).call(**{})[:a]) end @@ -1569,29 +1694,15 @@ def g.to_proc; method(:call).to_proc; end def g.<<(f) to_proc << f end def g.>>(f) to_proc >> f end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end + assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end + assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `call'/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end + assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } + assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f << g).call(**{})[:a] } assert_equal(2, (f >> g).call(**{})[:a]) f = ->(kw) { kw.merge(:a=>1) } @@ -1602,29 +1713,15 @@ def g.<<(f) to_proc << f end def g.>>(f) to_proc >> f end assert_equal(1, (f << g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (g << f).call(a: 3)[:a]) - end + assert_raise(ArgumentError) { (f >> g).call(a: 3)[:a] } + assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } + assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } + assert_raise(ArgumentError) { (g << f).call(a: 3)[:a] } assert_equal(1, (g >> f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end + assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } + assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } assert_equal(1, (f << g).call(**{})[:a]) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call(**{})[:a]) - end + assert_raise(ArgumentError) { (f >> g).call(**{})[:a] } end end diff --git a/ruby/test/ruby/test_process.rb b/ruby/test/ruby/test_process.rb index ab723c6f6..91d554ea3 100644 --- a/ruby/test/ruby/test_process.rb +++ b/ruby/test/ruby/test_process.rb @@ -208,39 +208,39 @@ def test_execopts_rlimit n = max IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io| - assert_equal("[#{n}, #{n}]\n", io.read) + "puts Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io| + assert_equal("#{n}\n#{n}\n", io.read) } n = 0 IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io| - assert_equal("[#{n}, #{n}]\n", io.read) + "puts Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io| + assert_equal("#{n}\n#{n}\n", io.read) } n = max IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE)", :rlimit_core=>[n]]) {|io| - assert_equal("[#{n}, #{n}]", io.read.chomp) + "puts Process.getrlimit(:CORE)", :rlimit_core=>[n]]) {|io| + assert_equal("#{n}\n#{n}\n", io.read) } m, n = 0, max IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io| - assert_equal("[#{m}, #{n}]", io.read.chomp) + "puts Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io| + assert_equal("#{m}\n#{n}\n", io.read) } m, n = 0, 0 IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io| - assert_equal("[#{m}, #{n}]", io.read.chomp) + "puts Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io| + assert_equal("#{m}\n#{n}\n", io.read) } n = max IO.popen([RUBY, "-e", - "p Process.getrlimit(:CORE), Process.getrlimit(:CPU)", + "puts Process.getrlimit(:CORE), Process.getrlimit(:CPU)", :rlimit_core=>n, :rlimit_cpu=>3600]) {|io| - assert_equal("[#{n}, #{n}]\n[3600, 3600]", io.read.chomp) + assert_equal("#{n}\n#{n}\n""3600\n3600\n", io.read) } assert_raise(ArgumentError) do @@ -261,6 +261,18 @@ def test_execopts_rlimit } end + def test_overwrite_ENV + assert_separately([],"#{<<~"begin;"}\n#{<<~"end;"}") + BUG = "[ruby-core:105223] [Bug #18164]" + begin; + $VERBOSE = nil + ENV = {} + pid = spawn({}, *#{TRUECOMMAND.inspect}) + ENV.replace({}) + assert_kind_of(Integer, pid, BUG) + end; + end + MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR] case RbConfig::CONFIG['target_os'] when /linux/ @@ -338,6 +350,13 @@ def test_execopts_env ensure ENV["hmm"] = old end + + assert_raise_with_message(ArgumentError, /fo=fo/) { + system({"fo=fo"=>"ha"}, *ENVCOMMAND) + } + assert_raise_with_message(ArgumentError, /\u{30c0}=\u{30e1}/) { + system({"\u{30c0}=\u{30e1}"=>"ha"}, *ENVCOMMAND) + } end def test_execopt_env_path @@ -1418,6 +1437,8 @@ def test_status assert_equal(s.to_i >> 1, s >> 1) assert_equal(false, s.stopped?) assert_equal(nil, s.stopsig) + + assert_equal(s, Marshal.load(Marshal.dump(s))) end end @@ -1435,6 +1456,8 @@ def test_status_kill assert_equal(expected, [s.exited?, s.signaled?, s.stopped?, s.success?], "[s.exited?, s.signaled?, s.stopped?, s.success?]") + + assert_equal(s, Marshal.load(Marshal.dump(s))) end end @@ -1449,6 +1472,27 @@ def test_status_quit "[s.exited?, s.signaled?, s.stopped?, s.success?]") assert_equal("#", s.inspect.sub(/ \(core dumped\)(?=>\z)/, '')) + + assert_equal(s, Marshal.load(Marshal.dump(s))) + end + end + + def test_status_fail + ret = Process::Status.wait($$) + assert_instance_of(Process::Status, ret) + assert_equal(-1, ret.pid) + end + + + def test_status_wait + IO.popen([RUBY, "-e", "gets"], "w") do |io| + pid = io.pid + assert_nil(Process::Status.wait(pid, Process::WNOHANG)) + io.puts + ret = Process::Status.wait(pid) + assert_instance_of(Process::Status, ret) + assert_equal(pid, ret.pid) + assert_predicate(ret, :exited?) end end @@ -1598,6 +1642,34 @@ def test_setegid rescue NotImplementedError end + if Process::UID.respond_to?(:from_name) + def test_uid_from_name + if u = Etc.getpwuid(Process.uid) + assert_equal(Process.uid, Process::UID.from_name(u.name), u.name) + end + assert_raise_with_message(ArgumentError, /\u{4e0d 5b58 5728}/) { + Process::UID.from_name("\u{4e0d 5b58 5728}") + } + end + end + + if Process::GID.respond_to?(:from_name) && !RUBY_PLATFORM.include?("android") + def test_gid_from_name + if g = Etc.getgrgid(Process.gid) + assert_equal(Process.gid, Process::GID.from_name(g.name), g.name) + end + expected_excs = [ArgumentError] + expected_excs << Errno::ENOENT if defined?(Errno::ENOENT) + expected_excs << Errno::ESRCH if defined?(Errno::ESRCH) # WSL 2 actually raises Errno::ESRCH + expected_excs << Errno::EBADF if defined?(Errno::EBADF) + expected_excs << Errno::EPERM if defined?(Errno::EPERM) + exc = assert_raise(*expected_excs) do + Process::GID.from_name("\u{4e0d 5b58 5728}") # fu son zai ("absent" in Kanji) + end + assert_match(/\u{4e0d 5b58 5728}/, exc.message) if exc.is_a?(ArgumentError) + end + end + def test_uid_re_exchangeable_p r = Process::UID.re_exchangeable? assert_include([true, false], r) @@ -1646,7 +1718,7 @@ def test_wait_and_sigchild Process.wait pid assert_send [sig_r, :wait_readable, 5], 'self-pipe not readable' end - if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD. + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD. assert_equal [true], signal_received.uniq, "[ruby-core:19744]" else assert_equal [true], signal_received, "[ruby-core:19744]" @@ -1660,6 +1732,9 @@ def test_wait_and_sigchild end def test_no_curdir + if /solaris/i =~ RUBY_PLATFORM + skip "Temporary skip to avoid CI failures after commit to use realpath on required files" + end with_tmpchdir {|d| Dir.mkdir("vd") status = nil @@ -1711,6 +1786,7 @@ def assert_fail_too_long_path((cmd, sep), mesg) min = 1_000 / (cmd.size + sep.size) cmds = Array.new(min, cmd) exs = [Errno::ENOENT] + exs << Errno::EINVAL if windows? exs << Errno::E2BIG if defined?(Errno::E2BIG) opts = {[STDOUT, STDERR]=>File::NULL} opts[:rlimit_nproc] = 128 if defined?(Process::RLIMIT_NPROC) @@ -2260,8 +2336,6 @@ def test_deadlock_by_signal_at_forking pid = fork {Process.kill(:QUIT, parent)} IO.popen([ruby, -'--disable=gems'], -'r+'){} Process.wait(pid) - $stdout.puts - $stdout.flush end INPUT end if defined?(fork) @@ -2374,7 +2448,7 @@ def test_threading_works_after_exec_fail rescue SystemCallError w.syswrite("exec failed\n") end - q = Queue.new + q = Thread::Queue.new th1 = Thread.new { i = 0; i += 1 while q.empty?; i } th2 = Thread.new { j = 0; j += 1 while q.empty? && Thread.pass.nil?; j } sleep 0.5 @@ -2383,7 +2457,7 @@ def test_threading_works_after_exec_fail end w.close assert_equal "exec failed\n", r.gets - vals = r.gets.chomp.split.map!(&:to_i) + vals = r.gets.split.map!(&:to_i) assert_operator vals[0], :>, vals[1], vals.inspect _, status = Process.waitpid2(pid) end @@ -2458,4 +2532,109 @@ def test_last_status Process.wait spawn(RUBY, "-e", "exit 13") assert_same(Process.last_status, $?) end + + def test_last_status_failure + assert_nil system("sad") + assert_not_predicate $?, :success? + assert_equal $?.exitstatus, 127 + end + + def test_exec_failure_leaves_no_child + assert_raise(Errno::ENOENT) do + spawn('inexistent_command') + end + assert_empty(Process.waitall) + end + + def test__fork + r, w = IO.pipe + pid = Process._fork + if pid == 0 + begin + r.close + w << "ok: #$$" + w.close + ensure + exit! + end + else + w.close + assert_equal("ok: #{pid}", r.read) + r.close + Process.waitpid(pid) + end + end if Process.respond_to?(:_fork) + + def test__fork_hook + %w(fork Process.fork).each do |method| + feature17795 = '[ruby-core:103400] [Feature #17795]' + assert_in_out_err([], <<-"end;", [], [], feature17795, timeout: 60) do |r, e| + module ForkHook + def _fork + p :before + ret = super + p :after + ret + end + end + + Process.singleton_class.prepend(ForkHook) + + pid = #{ method } + p pid + Process.waitpid(pid) if pid + end; + assert_equal([], e) + assert_equal(":before", r.shift) + assert_equal(":after", r.shift) + s = r.map {|s| s.chomp }.sort #=> [pid, ":after", "nil"] + assert_match(/^\d+$/, s[0]) # pid + assert_equal(":after", s[1]) + assert_equal("nil", s[2]) + end + end + end if Process.respond_to?(:_fork) + + def test__fork_hook_popen + feature17795 = '[ruby-core:103400] [Feature #17795]' + assert_in_out_err([], <<-"end;", %w(:before :after :after foo bar), [], feature17795, timeout: 60) + module ForkHook + def _fork + p :before + ret = super + p :after + ret + end + end + + Process.singleton_class.prepend(ForkHook) + + IO.popen("-") {|io| + if !io + puts "foo" + else + puts io.read + "bar" + end + } + end; + end if Process.respond_to?(:_fork) + + def test__fork_wrong_type_hook + feature17795 = '[ruby-core:103400] [Feature #17795]' + assert_in_out_err([], <<-"end;", ["OK"], [], feature17795, timeout: 60) + module ForkHook + def _fork + "BOO" + end + end + + Process.singleton_class.prepend(ForkHook) + + begin + fork + rescue TypeError + puts "OK" + end + end; + end if Process.respond_to?(:_fork) end diff --git a/ruby/test/ruby/test_rand.rb b/ruby/test/ruby/test_rand.rb index 939d17bdf..13b732926 100644 --- a/ruby/test/ruby/test_rand.rb +++ b/ruby/test/ruby/test_rand.rb @@ -2,14 +2,13 @@ require 'test/unit' class TestRand < Test::Unit::TestCase - def assert_random_int(ws, m, init = 0) + def assert_random_int(m, init = 0, iterate: 5) srand(init) rnds = [Random.new(init)] rnds2 = [rnds[0].dup] rnds3 = [rnds[0].dup] - ws.each_with_index do |w, i| - w = w.to_i - assert_equal(w, rand(m)) + iterate.times do |i| + w = rand(m) rnds.each do |rnd| assert_equal(w, rnd.rand(m)) end @@ -27,133 +26,97 @@ def assert_random_int(ws, m, init = 0) end def test_mt - assert_random_int(%w(1067595299 955945823 477289528 4107218783 4228976476), - 0x100000000, 0x00000456_00000345_00000234_00000123) + assert_random_int(0x100000000, 0x00000456_00000345_00000234_00000123) end def test_0x3fffffff - assert_random_int(%w(209652396 398764591 924231285 404868288 441365315), - 0x3fffffff) + assert_random_int(0x3fffffff) end def test_0x40000000 - assert_random_int(%w(209652396 398764591 924231285 404868288 441365315), - 0x40000000) + assert_random_int(0x40000000) end def test_0x40000001 - assert_random_int(%w(209652396 398764591 924231285 441365315 192771779), - 0x40000001) + assert_random_int(0x40000001) end def test_0xffffffff - assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963), - 0xffffffff) + assert_random_int(0xffffffff) end def test_0x100000000 - assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963), - 0x100000000) + assert_random_int(0x100000000) end def test_0x100000001 - assert_random_int(%w(2546248239 1277901399 243580376 1171049868 2051556033), - 0x100000001) + assert_random_int(0x100000001) end def test_rand_0x100000000 - assert_random_int(%w(4119812344 3870378946 80324654 4294967296 410016213), - 0x100000001, 311702798) + assert_random_int(0x100000001, 311702798) end def test_0x1000000000000 - assert_random_int(%w(11736396900911 - 183025067478208 - 197104029029115 - 130583529618791 - 180361239846611), - 0x1000000000000) + assert_random_int(0x1000000000000) end def test_0x1000000000001 - assert_random_int(%w(187121911899765 - 197104029029115 - 180361239846611 - 236336749852452 - 208739549485656), - 0x1000000000001) + assert_random_int(0x1000000000001) end def test_0x3fffffffffffffff - assert_random_int(%w(900450186894289455 - 3969543146641149120 - 1895649597198586619 - 827948490035658087 - 3203365596207111891), - 0x3fffffffffffffff) + assert_random_int(0x3fffffffffffffff) end def test_0x4000000000000000 - assert_random_int(%w(900450186894289455 - 3969543146641149120 - 1895649597198586619 - 827948490035658087 - 3203365596207111891), - 0x4000000000000000) + assert_random_int(0x4000000000000000) end def test_0x4000000000000001 - assert_random_int(%w(900450186894289455 - 3969543146641149120 - 1895649597198586619 - 827948490035658087 - 2279347887019741461), - 0x4000000000000001) + assert_random_int(0x4000000000000001) end def test_0x10000000000 - ws = %w(455570294424 1073054410371 790795084744 2445173525 1088503892627) - assert_random_int(ws, 0x10000000000, 3) + assert_random_int(0x10000000000, 3) end def test_0x10000 - ws = %w(2732 43567 42613 52416 45891) - assert_random_int(ws, 0x10000) + assert_random_int(0x10000) + end + + def assert_same_numbers(type, *nums) + nums.each do |n| + assert_instance_of(type, n) + end + x = nums.shift + nums.each do |n| + assert_equal(x, n) + end + x end def test_types - srand(0) - rnd = Random.new(0) - assert_equal(44, rand(100.0)) - assert_equal(44, rnd.rand(100)) - assert_equal(1245085576965981900420779258691, rand((2**100).to_f)) - assert_equal(1245085576965981900420779258691, rnd.rand(2**100)) - assert_equal(914679880601515615685077935113, rand(-(2**100).to_f)) + o = Object.new + class << o + def to_int; 100; end + def class; Integer; end + end srand(0) - rnd = Random.new(0) - assert_equal(997707939797331598305742933184, rand(2**100)) - assert_equal(997707939797331598305742933184, rnd.rand(2**100)) - assert_in_delta(0.602763376071644, rand((2**100).coerce(0).first), - 0.000000000000001) - assert_raise(ArgumentError) {rnd.rand((2**100).coerce(0).first)} + nums = [100.0, (2**100).to_f, (2**100), o, o, o].map do |m| + k = Integer + assert_kind_of(k, x = rand(m), m.inspect) + [m, k, x] + end + assert_kind_of(Integer, rand(-(2**100).to_f)) srand(0) rnd = Random.new(0) - assert_in_delta(0.548813503927325, rand(nil), - 0.000000000000001) - assert_in_delta(0.548813503927325, rnd.rand(), - 0.000000000000001) - srand(0) - rnd = Random.new(0) - o = Object.new - def o.to_int; 100; end - assert_equal(44, rand(o)) - assert_equal(44, rnd.rand(o)) - assert_equal(47, rand(o)) - assert_equal(47, rnd.rand(o)) - assert_equal(64, rand(o)) - assert_equal(64, rnd.rand(o)) + rnd2 = Random.new(0) + nums.each do |m, k, x| + assert_same_numbers(m.class, Random.rand(m), rnd.rand(m), rnd2.rand(m)) + end end def test_srand @@ -163,10 +126,13 @@ def test_srand srand(2**100) rnd = Random.new(2**100) - %w(3258412053).each {|w| - assert_equal(w.to_i, rand(0x100000000)) - assert_equal(w.to_i, rnd.rand(0x100000000)) - } + r = 3.times.map do + assert_same_numbers(Integer, rand(0x100000000), rnd.rand(0x100000000)) + end + srand(2**100) + r.each do |n| + assert_same_numbers(Integer, n, rand(0x100000000)) + end end def test_shuffle @@ -177,17 +143,17 @@ def test_shuffle end def test_big_seed - assert_random_int(%w(2757555016), 0x100000000, 2**1000000-1) + assert_random_int(0x100000000, 2**1000000-1) end def test_random_gc r = Random.new(0) - %w(2357136044 2546248239 3071714933).each do |w| - assert_equal(w.to_i, r.rand(0x100000000)) + 3.times do + assert_kind_of(Integer, r.rand(0x100000000)) end GC.start - %w(3626093760 2588848963 3684848379).each do |w| - assert_equal(w.to_i, r.rand(0x100000000)) + 3.times do + assert_kind_of(Integer, r.rand(0x100000000)) end end @@ -223,179 +189,56 @@ def test_random_seed def test_random_dup r1 = Random.new(0) r2 = r1.dup - %w(2357136044 2546248239 3071714933).each do |w| - assert_equal(w.to_i, r1.rand(0x100000000)) - end - %w(2357136044 2546248239 3071714933).each do |w| - assert_equal(w.to_i, r2.rand(0x100000000)) + 3.times do + assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000)) end r2 = r1.dup - %w(3626093760 2588848963 3684848379).each do |w| - assert_equal(w.to_i, r1.rand(0x100000000)) - end - %w(3626093760 2588848963 3684848379).each do |w| - assert_equal(w.to_i, r2.rand(0x100000000)) + 3.times do + assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000)) end end - def test_random_state - state = < b } } + + assert_equal(2, (..2).max) + assert_raise(TypeError) { (...2).max } + assert_raise(TypeError) { (...2.0).max } + + assert_equal(Float::INFINITY, (1..Float::INFINITY).max) + assert_nil((1..-Float::INFINITY).max) end def test_minmax @@ -146,12 +153,18 @@ def test_minmax assert_equal([nil, nil], (0...0).minmax) assert_equal([2, 1], (1..2).minmax{|a, b| b <=> a}) + + assert_equal(['a', 'c'], ('a'..'c').minmax) + assert_equal(['a', 'b'], ('a'...'c').minmax) + + assert_equal([1, Float::INFINITY], (1..Float::INFINITY).minmax) + assert_equal([nil, nil], (1..-Float::INFINITY).minmax) end def test_initialize_twice r = eval("1..2") - assert_raise(NameError) { r.instance_eval { initialize 3, 4 } } - assert_raise(NameError) { r.instance_eval { initialize_copy 3..4 } } + assert_raise(FrozenError) { r.instance_eval { initialize 3, 4 } } + assert_raise(FrozenError) { r.instance_eval { initialize_copy 3..4 } } end def test_uninitialized_range @@ -258,8 +271,10 @@ def test_step assert_kind_of(Enumerator::ArithmeticSequence, (1..).step(2)) assert_raise(ArgumentError) { (0..10).step(-1) { } } + assert_raise(ArgumentError) { (0..10).step(0) } assert_raise(ArgumentError) { (0..10).step(0) { } } assert_raise(ArgumentError) { (0..).step(-1) { } } + assert_raise(ArgumentError) { (0..).step(0) } assert_raise(ArgumentError) { (0..).step(0) { } } a = [] @@ -290,6 +305,7 @@ def test_step (2**32-1 .. 2**32+1).step(2) {|x| a << x } assert_equal([4294967295, 4294967297], a) zero = (2**32).coerce(0).first + assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) } assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } } a = [] (2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 } diff --git a/ruby/test/ruby/test_rational.rb b/ruby/test/ruby/test_rational.rb index 301890b62..fe9de64c4 100644 --- a/ruby/test/ruby/test_rational.rb +++ b/ruby/test/ruby/test_rational.rb @@ -128,6 +128,13 @@ def test_conv assert_raise(TypeError){Rational(Object.new, Object.new)} assert_raise(TypeError){Rational(1, Object.new)} + bug12485 = '[ruby-core:75995] [Bug #12485]' + o = Object.new + def o.to_int; 1; end + assert_equal(1, Rational(o, 1), bug12485) + assert_equal(1, Rational(1, o), bug12485) + assert_equal(1, Rational(o, o), bug12485) + o = Object.new def o.to_r; 1/42r; end assert_equal(1/42r, Rational(o)) @@ -158,6 +165,14 @@ def o.to_r; raise; end if (1.0/0).infinite? assert_raise(FloatDomainError){Rational(1.0/0)} end + + bug16518 = "[ruby-core:96942] [Bug #16518]" + cls = Class.new(Numeric) do + def /(y); 42; end + def to_r; 1r; end + def to_int; 1; end + end + assert_equal(1/2r, Rational(cls.new, 2), bug16518) end def test_attr @@ -598,6 +613,13 @@ def test_coerce assert_nothing_raised(TypeError, '[Bug #5020] [ruby-dev:44088]') do Rational(1,2).coerce(Complex(1,1)) end + + assert_raise(ZeroDivisionError) do + 1 / 0r.coerce(0+0i)[0] + end + assert_raise(ZeroDivisionError) do + 1 / 0r.coerce(0.0+0i)[0] + end end class ObjectX @@ -834,6 +856,18 @@ def test_Rational_without_exception assert_equal(nil, Rational(1, Object.new, exception: false)) } + bug12485 = '[ruby-core:75995] [Bug #12485]' + assert_nothing_raised(RuntimeError, bug12485) { + o = Object.new + def o.to_int; raise; end + assert_equal(nil, Rational(o, exception: false)) + } + assert_nothing_raised(RuntimeError, bug12485) { + o = Object.new + def o.to_int; raise; end + assert_equal(nil, Rational(1, o, exception: false)) + } + o = Object.new; def o.to_r; raise; end assert_nothing_raised(RuntimeError) { diff --git a/ruby/test/ruby/test_refinement.rb b/ruby/test/ruby/test_refinement.rb index 6fb04de5d..19857b035 100644 --- a/ruby/test/ruby/test_refinement.rb +++ b/ruby/test/ruby/test_refinement.rb @@ -225,6 +225,8 @@ def pow(*) end end def test_method_should_use_refinements + skip if Test::Unit::Runner.current_repeat_count > 0 + foo = Foo.new assert_raise(NameError) { foo.method(:z) } assert_equal("FooExt#z", FooExtClient.method_z(foo).call) @@ -246,6 +248,8 @@ def abs end end def test_instance_method_should_use_refinements + skip if Test::Unit::Runner.current_repeat_count > 0 + foo = Foo.new assert_raise(NameError) { Foo.instance_method(:z) } assert_equal("FooExt#z", FooExtClient.instance_method_z(foo).bind(foo).call) @@ -743,6 +747,13 @@ def call_using_in_method end end + def self.suppress_verbose + verbose, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = verbose + end + module IncludeIntoRefinement class C def bar @@ -770,7 +781,9 @@ def baz module M refine C do - include Mixin + TestRefinement.suppress_verbose do + include Mixin + end def baz return super << " M#baz" @@ -833,7 +846,9 @@ def baz module M refine C do - prepend Mixin + TestRefinement.suppress_verbose do + prepend Mixin + end def baz return super << " M#baz" @@ -916,7 +931,7 @@ def test_prepend_after_refine_wb_miss #{PrependAfterRefine_CODE} undef PrependAfterRefine } - }, timeout: 30 + }, timeout: 60 end def test_prepend_after_refine @@ -1648,7 +1663,6 @@ class D < C def test_reopen_refinement_module assert_separately([], <<-"end;") - $VERBOSE = nil class C end @@ -1665,6 +1679,7 @@ def m module R refine C do + alias m m def m :bar end @@ -2382,6 +2397,281 @@ def test_prepend_refined_module assert_equal(0, Bug13446::GenericEnumerable.new.sum) end + def test_unbound_refine_method + a = EnvUtil.labeled_class("A") do + def foo + self.class + end + end + b = EnvUtil.labeled_class("B") + bar = EnvUtil.labeled_module("R") do + break refine a do + def foo + super + end + end + end + assert_raise(TypeError) do + bar.instance_method(:foo).bind(b.new) + end + end + + def test_refine_frozen_class + verbose_bak, $VERBOSE = $VERBOSE, nil + singleton_class.instance_variable_set(:@x, self) + class << self + c = Class.new do + def foo + :cfoo + end + end + foo = Module.new do + refine c do + def foo + :rfoo + end + end + end + using foo + @x.assert_equal(:rfoo, c.new.foo) + c.freeze + foo.module_eval do + refine c do + def foo + :rfoo2 + end + def bar + :rbar + end + end + end + @x.assert_equal(:rfoo2, c.new.foo) + @x.assert_equal(:rbar, c.new.bar, '[ruby-core:71391] [Bug #11669]') + end + ensure + $VERBOSE = verbose_bak + end + + # [Bug #17386] + def test_prepended_with_method_cache + foo = Class.new do + def foo + :Foo + end + end + + code = Module.new do + def foo + :Code + end + end + + _ext = Module.new do + refine foo do + def foo; end + end + end + + obj = foo.new + + assert_equal :Foo, obj.foo + foo.prepend code + assert_equal :Code, obj.foo + end + + # [Bug #17417] + def test_prepended_with_method_cache_17417 + assert_normal_exit %q{ + module M + def hoge; end + end + + module R + refine Hash do + def except *args; end + end + end + + h = {} + h.method(:except) # put it on pCMC + Hash.prepend(M) + h.method(:except) + } + end + + def test_defining_after_cached + klass = Class.new + _refinement = Module.new { refine(klass) { def foo; end } } + klass.new.foo rescue nil # cache the refinement method entry + klass.define_method(:foo) { 42 } + assert_equal(42, klass.new.foo) + end + + # [Bug #17806] + def test_two_refinements_for_prepended_class + assert_normal_exit %q{ + module R1 + refine Hash do + def foo; :r1; end + end + end + + class Hash + prepend(Module.new) + end + + class Hash + def foo; end + end + + {}.method(:foo) # put it on pCMC + + module R2 + refine Hash do + def foo; :r2; end + end + end + + {}.foo + } + end + + # [Bug #17806] + def test_redefining_refined_for_prepended_class + klass = Class.new { def foo; end } + _refinement = Module.new do + refine(klass) { def foo; :refined; end } + end + klass.prepend(Module.new) + klass.new.foo # cache foo + klass.define_method(:foo) { :second } + assert_equal(:second, klass.new.foo) + end + + class Bug18180 + module M + refine Array do + def min; :min; end + def max; :max; end + end + end + + using M + + def t + [[1+0, 2, 4].min, [1, 2, 4].min, [1+0, 2, 4].max, [1, 2, 4].max] + end + end + + def test_refine_array_min_max + assert_equal([:min, :min, :max, :max], Bug18180.new.t) + end + + class Bug17822 + module Ext + refine(Bug17822) do + def foo = :refined + end + end + + private(def foo = :not_refined) + + module Client + using Ext + def self.call_foo + Bug17822.new.foo + end + end + end + + # [Bug #17822] + def test_privatizing_refined_method + assert_equal(:refined, Bug17822::Client.call_foo) + end + + def test_ancestors + refinement = nil + as = nil + Module.new do + refine Array do + refinement = self + as = ancestors + end + end + assert_equal([refinement], as, "[ruby-core:86949] [Bug #14744]") + end + + module TestImport + class A + def foo + "original" + end + end + + module B + BAR = "bar" + + def bar + "#{foo}:#{BAR}" + end + end + + module C + refine A do + import_methods B + + def foo + "refined" + end + end + end + + module D + refine A do + TestRefinement.suppress_verbose do + include B + end + + def foo + "refined" + end + end + end + + module UsingC + using C + + def self.call_bar + A.new.bar + end + end + + module UsingD + using D + + def self.call_bar + A.new.bar + end + end + end + + def test_import_methods + assert_equal("refined:bar", TestImport::UsingC.call_bar) + assert_equal("original:bar", TestImport::UsingD.call_bar) + + assert_raise(ArgumentError) do + Module.new do + refine Integer do + import_methods Enumerable + end + end + end + end + + def test_inherit_singleton_methods_of_module + assert_equal([], Refinement.used_modules) + end + private def eval_using(mod, s) diff --git a/ruby/test/ruby/test_regexp.rb b/ruby/test/ruby/test_regexp.rb index b469d643f..2bf4649f1 100644 --- a/ruby/test/ruby/test_regexp.rb +++ b/ruby/test/ruby/test_regexp.rb @@ -5,7 +5,6 @@ class TestRegexp < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -43,13 +42,14 @@ def test_ruby_dev_24887 def test_yoshidam_net_20041111_1 s = "[\xC2\xA0-\xC3\xBE]" - assert_match(Regexp.new(s, nil, "u"), "\xC3\xBE") + r = assert_deprecated_warning(/ignored/) {Regexp.new(s, nil, "u")} + assert_match(r, "\xC3\xBE") end def test_yoshidam_net_20041111_2 assert_raise(RegexpError) do s = "[\xFF-\xFF]".force_encoding("utf-8") - Regexp.new(s, nil, "u") + assert_warning(/ignored/) {Regexp.new(s, nil, "u")} end end @@ -57,6 +57,17 @@ def test_ruby_dev_31309 assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-')) end + def test_premature_end_char_property + ["\\p{", + "\\p{".dup.force_encoding("UTF-8"), + "\\p{".dup.force_encoding("US-ASCII") + ].each do |string| + assert_raise(RegexpError) do + Regexp.new(string) + end + end + end + def test_assert_normal_exit # moved from knownbug. It caused core. Regexp.union("a", "a") @@ -218,6 +229,17 @@ def test_assign_named_capture def test_assign_named_capture_to_reserved_word /(?.)/ =~ "a" assert_not_include(local_variables, :nil, "[ruby-dev:32675]") + + def (obj = Object.new).test(s, nil: :ng) + /(?.)/ =~ s + binding.local_variable_get(:nil) + end + assert_equal("b", obj.test("b")) + + tap do |nil: :ng| + /(?.)/ =~ "c" + assert_equal("c", binding.local_variable_get(:nil)) + end end def test_assign_named_capture_to_const @@ -243,6 +265,27 @@ def test_match_regexp assert_equal(re, re.match("foo").regexp) end + def test_match_lambda_multithread + bug17507 = "[ruby-core:101901]" + str = "a-x-foo-bar-baz-z-b" + + worker = lambda do + m = /foo-([A-Za-z0-9_\.]+)-baz/.match(str) + assert_equal("bar", m[1], bug17507) + + # These two lines are needed to trigger the bug + File.exist? "/tmp" + str.gsub(/foo-bar-baz/, "foo-abc-baz") + end + + def self. threaded_test(worker) + 6.times.map {Thread.new {10_000.times {worker.call}}}.each(&:join) + end + + # The bug only occurs in a method calling a block/proc/lambda + threaded_test(worker) + end + def test_source bug5484 = '[ruby-core:40364]' assert_equal('', //.source) @@ -451,6 +494,40 @@ def test_match_string assert_equal("foobarbaz", m.string) end + def test_match_matchsubstring + m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + assert_equal("HX1138", m.match(0)) + assert_equal("8", m.match(4)) + assert_nil(m.match(5)) + + m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044") + assert_equal("\u3043", m.match(1)) + assert_nil(m.match(2)) + assert_equal("\u3044", m.match(3)) + + m = /(?.)(?[^aeiou])?(?.+)/.match("hoge\u3042") + assert_equal("h", m.match(:foo)) + assert_nil(m.match(:n)) + assert_equal("oge\u3042", m.match(:bar)) + end + + def test_match_match_length + m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + assert_equal(6, m.match_length(0)) + assert_equal(1, m.match_length(4)) + assert_nil(m.match_length(5)) + + m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044") + assert_equal(1, m.match_length(1)) + assert_nil(m.match_length(2)) + assert_equal(1, m.match_length(3)) + + m = /(?.)(?[^aeiou])?(?.+)/.match("hoge\u3042") + assert_equal(1, m.match_length(:foo)) + assert_nil(m.match_length(:n)) + assert_equal(4, m.match_length(:bar)) + end + def test_match_inspect m = /(...)(...)(...)(...)?/.match("foobarbaz") assert_equal('#', m.inspect) @@ -458,7 +535,7 @@ def test_match_inspect def test_initialize assert_raise(ArgumentError) { Regexp.new } - assert_equal(/foo/, Regexp.new(/foo/, Regexp::IGNORECASE)) + assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)}) assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding) assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")]) @@ -474,6 +551,24 @@ def test_initialize assert_raise(RegexpError) { Regexp.new("((?))\\g<0>") } end + def test_match_control_meta_escape + assert_equal(0, /\c\xFF/ =~ "\c\xFF") + assert_equal(0, /\c\M-\xFF/ =~ "\c\M-\xFF") + assert_equal(0, /\C-\xFF/ =~ "\C-\xFF") + assert_equal(0, /\C-\M-\xFF/ =~ "\C-\M-\xFF") + assert_equal(0, /\M-\xFF/ =~ "\M-\xFF") + assert_equal(0, /\M-\C-\xFF/ =~ "\M-\C-\xFF") + assert_equal(0, /\M-\c\xFF/ =~ "\M-\c\xFF") + + assert_nil(/\c\xFE/ =~ "\c\xFF") + assert_nil(/\c\M-\xFE/ =~ "\c\M-\xFF") + assert_nil(/\C-\xFE/ =~ "\C-\xFF") + assert_nil(/\C-\M-\xFE/ =~ "\C-\M-\xFF") + assert_nil(/\M-\xFE/ =~ "\M-\xFF") + assert_nil(/\M-\C-\xFE/ =~ "\M-\C-\xFF") + assert_nil(/\M-\c\xFE/ =~ "\M-\c\xFF") + end + def test_unescape assert_raise(ArgumentError) { s = '\\'; /#{ s }/ } assert_equal(/\xFF/n, /#{ s="\\xFF" }/n) @@ -550,7 +645,10 @@ def test_match assert_equal("bc", /../.match('abc', -2)[0]) assert_nil(/../.match("abc", -4)) assert_nil(/../.match("abc", 4)) - assert_equal('\x', /../n.match("\u3042" + '\x', 1)[0]) + + # use eval because only one warning is shown for the same regexp literal + pat = eval('/../n') + assert_equal('\x', assert_warning(/binary regexp/) {pat.match("\u3042" + '\x', 1)}[0]) r = nil /.../.match("abc") {|m| r = m[0] } @@ -626,7 +724,7 @@ def test_union2 def test_dup assert_equal(//, //.dup) - assert_raise(TypeError) { //.instance_eval { initialize_copy(nil) } } + assert_raise(TypeError) { //.dup.instance_eval { initialize_copy(nil) } } end def test_regsub @@ -650,21 +748,10 @@ def test_regsub_K assert_equal('foobazquux/foobazquux', result, bug8856) end - def test_KCODE - assert_nil($KCODE) - assert_nothing_raised { $KCODE = nil } - assert_equal(false, $=) - assert_nothing_raised { $= = nil } - end - - def test_KCODE_warning - assert_warning(/variable \$KCODE is no longer effective; ignored/) { $KCODE = nil } - assert_warning(/variable \$KCODE is no longer effective/) { $KCODE = nil } - end - - def test_ignorecase_warning - assert_warning(/variable \$= is no longer effective; ignored/) { $= = nil } - assert_warning(/variable \$= is no longer effective/) { $= } + def test_ignorecase + v = assert_deprecated_warning(/variable \$= is no longer effective/) { $= } + assert_equal(false, v) + assert_deprecated_warning(/variable \$= is no longer effective; ignored/) { $= = nil } end def test_match_setter @@ -680,11 +767,16 @@ def test_match_without_regexp test = proc {|&blk| "abc".sub("a", ""); blk.call($~) } bug10877 = '[ruby-core:68209] [Bug #10877]' + bug18160 = '[Bug #18160]' test.call {|m| assert_raise_with_message(IndexError, /foo/, bug10877) {m["foo"]} } key = "\u{3042}" [Encoding::UTF_8, Encoding::Shift_JIS, Encoding::EUC_JP].each do |enc| idx = key.encode(enc) - test.call {|m| assert_raise_with_message(IndexError, /#{idx}/, bug10877) {m[idx]} } + pat = /#{idx}/ + test.call {|m| assert_raise_with_message(IndexError, pat, bug10877) {m[idx]} } + test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.offset(idx)} } + test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.begin(idx)} } + test.call {|m| assert_raise_with_message(IndexError, pat, bug18160) {m.end(idx)} } end test.call {|m| assert_equal(/a/, m.regexp) } test.call {|m| assert_equal("abc", m.string) } @@ -726,11 +818,13 @@ def test_getter end def test_rindex_regexp - assert_equal(3, "foobarbaz\u3042".rindex(/b../n, 5)) + # use eval because only one warning is shown for the same regexp literal + pat = eval('/b../n') + assert_equal(3, assert_warning(/binary regexp/) {"foobarbaz\u3042".rindex(pat, 5)}) end def assert_regexp(re, ss, fs = [], msg = nil) - re = Regexp.new(re) unless re.is_a?(Regexp) + re = EnvUtil.suppress_warning {Regexp.new(re)} unless re.is_a?(Regexp) ss = [ss] unless ss.is_a?(Array) ss.each do |e, s| s ||= e @@ -763,7 +857,7 @@ def test_parse check(/\A\80\z/, "80", ["\100", ""]) check(/\A\77\z/, "?") check(/\A\78\z/, "\7" + '8', ["\100", ""]) - check(eval('/\A\Qfoo\E\z/'), "QfooE") + check(assert_warning(/Unknown escape/) {eval('/\A\Qfoo\E\z/')}, "QfooE") check(/\Aa++\z/, "aaa") check('\Ax]\z', "x]") check(/x#foo/x, "x", "#foo") @@ -807,8 +901,8 @@ def test_exec check(/^(A+|B(?>\g<1>)*)[AC]$/, %w(AAAC BBBAAAAC), %w(BBBAAA)) check(/^()(?>\g<1>)*$/, "", "a") check(/^(?>(?=a)(#{ "a" * 1000 }|))++$/, ["a" * 1000, "a" * 2000, "a" * 3000], ["", "a" * 500, "b" * 1000]) - check(eval('/^(?:a?)?$/'), ["", "a"], ["aa"]) - check(eval('/^(?:a+)?$/'), ["", "a", "aa"], ["ab"]) + check(assert_warning(/nested repeat operator/) {eval('/^(?:a?)?$/')}, ["", "a"], ["aa"]) + check(assert_warning(/nested repeat operator/) {eval('/^(?:a+)?$/')}, ["", "a", "aa"], ["ab"]) check(/^(?:a?)+?$/, ["", "a", "aa"], ["ab"]) check(/^a??[ab]/, [["a", "a"], ["a", "aa"], ["b", "b"], ["a", "ab"]], ["c"]) check(/^(?:a*){3,5}$/, ["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], ["b"]) @@ -937,13 +1031,13 @@ def test_char_class def test_posix_bracket check(/\A[[:alpha:]0]\z/, %w(0 a), %w(1 .)) - check(eval('/\A[[:^alpha:]0]\z/'), %w(0 1 .), "a") - check(eval('/\A[[:alpha\:]]\z/'), %w(a l p h a :), %w(b 0 1 .)) - check(eval('/\A[[:alpha:foo]0]\z/'), %w(0 a), %w(1 .)) + check(assert_warning(/duplicated range/) {eval('/\A[[:^alpha:]0]\z/')}, %w(0 1 .), "a") + check(assert_warning(/duplicated range/) {eval('/\A[[:alpha\:]]\z/')}, %w(a l p h a :), %w(b 0 1 .)) + check(assert_warning(/duplicated range/) {eval('/\A[[:alpha:foo]0]\z/')}, %w(0 a), %w(1 .)) check(/\A[[:xdigit:]&&[:alpha:]]\z/, "a", %w(g 0)) check('\A[[:abcdefghijklmnopqrstu:]]+\z', "[]") failcheck('[[:alpha') - failcheck('[[:alpha:') + assert_warning(/duplicated range/) {failcheck('[[:alpha:')} failcheck('[[:alp:]]') assert_match(/\A[[:digit:]]+\z/, "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19") @@ -1110,13 +1204,17 @@ def test_matchdata end def test_regexp_popped - assert_nothing_raised { eval("a = 1; /\#{ a }/; a") } - assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") } + EnvUtil.suppress_warning do + assert_nothing_raised { eval("a = 1; /\#{ a }/; a") } + assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") } + end end def test_invalid_fragment bug2547 = '[ruby-core:27374]' - assert_raise(SyntaxError, bug2547) {eval('/#{"\\\\"}y/')} + assert_raise(SyntaxError, bug2547) do + assert_warning(/ignored/) {eval('/#{"\\\\"}y/')} + end end def test_dup_warn @@ -1156,7 +1254,8 @@ def test_invalid_escape_error def test_raw_hyphen_and_tk_char_type_after_range bug6853 = '[ruby-core:47115]' # use Regexp.new instead of literal to ignore a parser warning. - check(Regexp.new('[0-1-\\s]'), [' ', '-'], ['2', 'a'], bug6853) + re = assert_warning(/without escape/) {Regexp.new('[0-1-\\s]')} + check(re, [' ', '-'], ['2', 'a'], bug6853) end def test_error_message_on_failed_conversion @@ -1192,6 +1291,20 @@ def test_options_in_look_behind } end + def test_quantifier_reduction + assert_equal('aa', eval('/(a+?)*/').match('aa')[0]) + assert_equal('aa', eval('/(?:a+?)*/').match('aa')[0]) + + quantifiers = %w'? * + ?? *? +?' + quantifiers.product(quantifiers) do |q1, q2| + EnvUtil.suppress_warning do + r1 = eval("/(a#{q1})#{q2}/").match('aa')[0] + r2 = eval("/(?:a#{q1})#{q2}/").match('aa')[0] + assert_equal(r1, r2) + end + end + end + def test_once pr1 = proc{|i| /#{i}/o} assert_equal(/0/, pr1.call(0)) @@ -1277,6 +1390,12 @@ def test_absent assert_nil($1) end + def test_backref_overrun + assert_raise_with_message(SyntaxError, /invalid backref number/) do + eval(%["".match(/(())(?)((?(90000)))/)]) + end + end + # This assertion is for porting x2() tests in testpy.py of Onigmo. def assert_match_at(re, str, positions, msg = nil) re = Regexp.new(re) unless re.is_a?(Regexp) diff --git a/ruby/test/ruby/test_require.rb b/ruby/test/ruby/test_require.rb index a86ea356c..77cdae64d 100644 --- a/ruby/test/ruby/test_require.rb +++ b/ruby/test/ruby/test_require.rb @@ -88,6 +88,7 @@ def self.ospath_encoding(path) end def prepare_require_path(dir, encoding) + require 'enc/trans/single_byte' Dir.mktmpdir {|tmp| begin require_path = File.join(tmp, dir, 'foo.rb').encode(encoding) @@ -199,6 +200,7 @@ def test_require_twice end def assert_syntax_error_backtrace + loaded_features = $LOADED_FEATURES.dup Dir.mktmpdir do |tmp| req = File.join(tmp, "test.rb") File.write(req, ",\n") @@ -208,6 +210,7 @@ def assert_syntax_error_backtrace assert_not_nil(bt = e.backtrace, "no backtrace") assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect}) end + $LOADED_FEATURES.replace loaded_features end def test_require_syntax_error @@ -364,19 +367,51 @@ def test_load_scope } end + def test_load_into_module + Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| + t.puts "def b; 1 end" + t.puts "class Foo" + t.puts " def c; 2 end" + t.puts "end" + t.close + + m = Module.new + load(t.path, m) + assert_equal([:b], m.private_instance_methods(false)) + c = Class.new do + include m + public :b + end + assert_equal(1, c.new.b) + assert_equal(2, m::Foo.new.c) + } + end + + def test_load_wrap_nil + Dir.mktmpdir do |tmp| + File.write("#{tmp}/1.rb", "class LoadWrapNil; end\n") + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + path = ""#{tmp.dump}"/1.rb" + begin; + load path, nil + assert_instance_of(Class, LoadWrapNil) + end; + end + end + def test_load_ospath bug = '[ruby-list:49994] path in ospath' base = "test_load\u{3042 3044 3046 3048 304a}".encode(Encoding::Windows_31J) path = nil - Tempfile.create([base, ".rb"]) do |t| - path = t.path - + Dir.mktmpdir do |dir| + path = File.join(dir, base+".rb") assert_raise_with_message(LoadError, /#{base}/) { - load(File.join(File.dirname(path), base)) + load(File.join(dir, base)) } - t.puts "warn 'ok'" - t.close + File.open(path, "w+b") do |t| + t.puts "warn 'ok'" + end assert_include(path, base) assert_warn("ok\n", bug) { assert_nothing_raised(LoadError, bug) { @@ -388,6 +423,8 @@ def test_load_ospath def test_relative load_path = $:.dup + loaded_featrures = $LOADED_FEATURES.dup + $:.delete(".") Dir.mktmpdir do |tmp| Dir.chdir(tmp) do @@ -407,6 +444,7 @@ def test_relative end ensure $:.replace(load_path) if load_path + $LOADED_FEATURES.replace loaded_featrures end def test_relative_symlink @@ -428,6 +466,32 @@ def test_relative_symlink } end + def test_relative_symlink_realpath + Dir.mktmpdir {|tmp| + Dir.chdir(tmp) { + Dir.mkdir "a" + File.open("a/a.rb", "w") {|f| f.puts 'require_relative "b"' } + File.open("a/b.rb", "w") {|f| f.puts '$t += 1' } + Dir.mkdir "b" + File.binwrite("c.rb", <<~RUBY) + $t = 0 + $:.unshift(File.expand_path('../b', __FILE__)) + require "b" + require "a" + print $t + RUBY + begin + File.symlink("../a/a.rb", "b/a.rb") + File.symlink("../a/b.rb", "b/b.rb") + result = IO.popen([EnvUtil.rubybin, "c.rb"], &:read) + assert_equal("1", result, "bug17885 [ruby-core:104010]") + rescue NotImplementedError, Errno::EACCES + skip "File.symlink is not implemented" + end + } + } + end + def test_frozen_loaded_features bug3756 = '[ruby-core:31913]' assert_in_out_err(['-e', '$LOADED_FEATURES.freeze; require "ostruct"'], "", @@ -525,6 +589,28 @@ def test_loaded_features_encoding $".replace(features) end + def test_default_loaded_features_encoding + Dir.mktmpdir {|tmp| + Dir.mkdir("#{tmp}/1") + Dir.mkdir("#{tmp}/2") + File.write("#{tmp}/1/bug18191-1.rb", "") + File.write("#{tmp}/2/bug18191-2.rb", "") + assert_separately(%W[-Eutf-8 -I#{tmp}/1 -], "#{<<~"begin;"}\n#{<<~'end;'}") + tmp = #{tmp.dump}"/2" + begin; + $:.unshift(tmp) + require "bug18191-1" + require "bug18191-2" + encs = [Encoding::US_ASCII, Encoding.find("filesystem")] + message = -> { + require "pp" + {filesystem: encs[1], **$".group_by(&:encoding)}.pretty_inspect + } + assert($".all? {|n| encs.include?(n.encoding)}, message) + end; + } + end + def test_require_changed_current_dir bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| @@ -705,8 +791,8 @@ def test_require_with_loaded_features_pop assert_in_out_err([{"RUBYOPT" => nil}, "-", script.path], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7530, timeout: 60) begin; PATH = ARGV.shift - THREADS = 4 - ITERATIONS_PER_THREAD = 1000 + THREADS = 30 + ITERATIONS_PER_THREAD = 300 THREADS.times.map { Thread.new do @@ -764,6 +850,8 @@ def test_loading_fifo_threading_success end if File.respond_to?(:mkfifo) def test_loading_fifo_fd_leak + skip if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz + Tempfile.create(%w'fifo .rb') {|f| f.close File.unlink(f.path) @@ -831,6 +919,23 @@ def test_symlink_load_path } end + def test_provide_in_required_file + paths, loaded = $:.dup, $".dup + Dir.mktmpdir do |tmp| + provide = File.realdirpath("provide.rb", tmp) + File.write(File.join(tmp, "target.rb"), "raise __FILE__\n") + File.write(provide, '$" << '"'target.rb'\n") + $:.replace([tmp]) + assert(require("provide")) + assert(!require("target")) + assert_equal($".pop, provide) + assert_equal($".pop, "target.rb") + end + ensure + $:.replace(paths) + $".replace(loaded) + end + if defined?($LOAD_PATH.resolve_feature_path) def test_resolve_feature_path paths, loaded = $:.dup, $".dup @@ -849,5 +954,9 @@ def test_resolve_feature_path $:.replace(paths) $".replace(loaded) end + + def test_resolve_feature_path_with_missing_feature + assert_nil($LOAD_PATH.resolve_feature_path("superkalifragilisticoespialidoso")) + end end end diff --git a/ruby/test/ruby/test_require_lib.rb b/ruby/test/ruby/test_require_lib.rb index 4af57173b..6b2846c8f 100644 --- a/ruby/test/ruby/test_require_lib.rb +++ b/ruby/test/ruby/test_require_lib.rb @@ -8,8 +8,7 @@ class TestRequireLib < Test::Unit::TestCase # skip some problems next if %r!/lib/(?:bundler|rubygems)\b! =~ lib next if %r!/lib/(?:debug|mkmf)\.rb\z! =~ lib - # skip because "in `': undefined method `add_maker' for RSS::Maker:Module (NoMethodError)" - next if %r!/lib/rss\b! =~ lib + next if %r!/lib/irb/ext/tracer\.rb\z! =~ lib # skip many files that almost use no threads next if TEST_RATIO < rand(0.0..1.0) define_method "test_thread_size:#{lib}" do diff --git a/ruby/test/ruby/test_rubyoptions.rb b/ruby/test/ruby/test_rubyoptions.rb index 093720b1f..5018a3815 100644 --- a/ruby/test/ruby/test_rubyoptions.rb +++ b/ruby/test/ruby/test_rubyoptions.rb @@ -7,9 +7,13 @@ require_relative '../lib/jit_support' class TestRubyOptions < Test::Unit::TestCase + def self.yjit_enabled? = defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled? + NO_JIT_DESCRIPTION = - if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE - RUBY_DESCRIPTION.sub(/\+JIT /, '') + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE + RUBY_DESCRIPTION.sub(/\+MJIT /, '') + elsif yjit_enabled? # checking -DYJIT_FORCE_ENABLE + RUBY_DESCRIPTION.sub(/\+YJIT /, '') else RUBY_DESCRIPTION end @@ -66,20 +70,48 @@ def test_option_variables end end + def test_backtrace_limit + assert_in_out_err(%w(--backtrace-limit), "", [], /missing argument for --backtrace-limit/) + assert_in_out_err(%w(--backtrace-limit= 1), "", [], /missing argument for --backtrace-limit/) + assert_in_out_err(%w(--backtrace-limit=-1), "", [], /wrong limit for backtrace length/) + code = 'def f(n);n > 0 ? f(n-1) : raise;end;f(5)' + assert_in_out_err(%w(--backtrace-limit=1), code, [], + [/.*unhandled exception\n/, /^\tfrom .*\n/, + /^\t \.{3} \d+ levels\.{3}\n/]) + assert_in_out_err(%w(--backtrace-limit=3), code, [], + [/.*unhandled exception\n/, *[/^\tfrom .*\n/]*3, + /^\t \.{3} \d+ levels\.{3}\n/]) + assert_kind_of(Integer, Thread::Backtrace.limit) + assert_in_out_err(%w(--backtrace-limit=1), "p Thread::Backtrace.limit", ['1'], []) + end def test_warning save_rubyopt = ENV['RUBYOPT'] ENV['RUBYOPT'] = nil assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), []) assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), []) - assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(1), []) + assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(2), []) assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), []) + assert_in_out_err(%w(-We) + ['p $-W'], "", %w(2), []) assert_in_out_err(%w(-w -W0 -e) + ['p $-W'], "", %w(0), []) assert_in_out_err(%w(-W:deprecated -e) + ['p Warning[:deprecated]'], "", %w(true), []) assert_in_out_err(%w(-W:no-deprecated -e) + ['p Warning[:deprecated]'], "", %w(false), []) assert_in_out_err(%w(-W:experimental -e) + ['p Warning[:experimental]'], "", %w(true), []) assert_in_out_err(%w(-W:no-experimental -e) + ['p Warning[:experimental]'], "", %w(false), []) assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/) + assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), []) + assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), []) + assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), []) + assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), []) + code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}"' + Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t| + t.puts code + t.close + assert_in_out_err(["-r#{t.path}", '-e', code], "", %w(false:false:true false:false:true), []) + assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", %w(true:true:true true:true:true), []) + assert_in_out_err(["-r#{t.path}", '-W:deprecated', '-e', code], "", %w(false:true:true false:true:true), []) + assert_in_out_err(["-r#{t.path}", '-W:no-experimental', '-e', code], "", %w(false:false:false false:false:false), []) + end ensure ENV['RUBYOPT'] = save_rubyopt end @@ -105,16 +137,18 @@ def test_debug VERSION_PATTERN_WITH_JIT = case RUBY_ENGINE when 'ruby' - /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+JIT \[#{q[RUBY_PLATFORM]}\]$/ + /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+MJIT \[#{q[RUBY_PLATFORM]}\]$/ else VERSION_PATTERN end private_constant :VERSION_PATTERN_WITH_JIT def test_verbose - assert_in_out_err(["-vve", ""]) do |r, e| + assert_in_out_err([{'RUBY_YJIT_ENABLE' => nil}, "-vve", ""]) do |r, e| assert_match(VERSION_PATTERN, r[0]) - if RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE + assert_equal(NO_JIT_DESCRIPTION, r[0]) + elsif self.class.yjit_enabled? && !yjit_force_enabled? # checking -DYJIT_FORCE_ENABLE assert_equal(NO_JIT_DESCRIPTION, r[0]) else assert_equal(RUBY_DESCRIPTION, r[0]) @@ -175,9 +209,12 @@ def test_kanji end def test_version - assert_in_out_err(%w(--version)) do |r, e| + env = {'RUBY_YJIT_ENABLE' => nil} # unset in children + assert_in_out_err([env, '--version']) do |r, e| assert_match(VERSION_PATTERN, r[0]) - if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE + if ENV['RUBY_YJIT_ENABLE'] == '1' + assert_equal(NO_JIT_DESCRIPTION, r[0]) + elsif defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? || self.class.yjit_enabled? # checking -D(M|Y)JIT_FORCE_ENABLE assert_equal(EnvUtil.invoke_ruby(['-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0]) else assert_equal(RUBY_DESCRIPTION, r[0]) @@ -186,13 +223,19 @@ def test_version end return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no' + return if yjit_force_enabled? [ - %w(--version --jit --disable=jit), - %w(--version --enable=jit --disable=jit), - %w(--version --enable-jit --disable-jit), + %w(--version --mjit --disable=mjit), + %w(--version --enable=mjit --disable=mjit), + %w(--version --enable-mjit --disable-mjit), + *([ + %w(--version --jit --disable=jit), + %w(--version --enable=jit --disable=jit), + %w(--version --enable-jit --disable-jit), + ] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/), ].each do |args| - assert_in_out_err(args) do |r, e| + assert_in_out_err([env] + args) do |r, e| assert_match(VERSION_PATTERN, r[0]) assert_match(NO_JIT_DESCRIPTION, r[0]) assert_equal([], e) @@ -201,16 +244,21 @@ def test_version if JITSupport.supported? [ - %w(--version --jit), - %w(--version --enable=jit), - %w(--version --enable-jit), + %w(--version --mjit), + %w(--version --enable=mjit), + %w(--version --enable-mjit), + *([ + %w(--version --jit), + %w(--version --enable=jit), + %w(--version --enable-jit), + ] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/), ].each do |args| - assert_in_out_err(args) do |r, e| + assert_in_out_err([env] + args) do |r, e| assert_match(VERSION_PATTERN_WITH_JIT, r[0]) - if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE + if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE assert_equal(RUBY_DESCRIPTION, r[0]) else - assert_equal(EnvUtil.invoke_ruby(['--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0]) + assert_equal(EnvUtil.invoke_ruby([env, '--mjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0]) end assert_equal([], e) end @@ -333,6 +381,10 @@ def test_rubyopt assert_in_out_err(%w(), "p $VERBOSE", ["true"]) assert_in_out_err(%w(-W1), "p $VERBOSE", ["false"]) assert_in_out_err(%w(-W0), "p $VERBOSE", ["nil"]) + assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"]) + assert_in_out_err(%w(-W0), "p Warning[:deprecated]", ["false"]) + assert_in_out_err(%w(-W1), "p Warning[:deprecated]", ["false"]) + assert_in_out_err(%w(-W2), "p Warning[:deprecated]", ["true"]) ENV['RUBYOPT'] = '-W:deprecated' assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"]) ENV['RUBYOPT'] = '-W:no-deprecated' @@ -494,16 +546,18 @@ def test_indentation_check ["case nil; when true", "end"], ["if false;", "end", "if true\nelse ", "end"], ["else", " end", "_ = if true\n"], + ["begin\n def f() = nil", "end"], + ["begin\n def self.f() = nil", "end"], ].each do |b, e = 'end', pre = nil, post = nil| src = ["#{pre}#{b}\n", " #{e}\n#{post}"] k = b[/\A\s*(\S+)/, 1] e = e[/\A\s*(\S+)/, 1] - n = 2 - n += pre.count("\n") if pre + n = 1 + src[0].count("\n") + n1 = 1 + (pre ? pre.count("\n") : 0) a.for("no directives with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"] + err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] t.rewind t.truncate(0) t.puts src @@ -522,7 +576,7 @@ def test_indentation_check end a.for("false and true directives with #{src}") do - err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n+1}"] + err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1+2}"] t.rewind t.truncate(0) t.puts "# -*- warn-indent: false -*-" @@ -544,7 +598,7 @@ def test_indentation_check end a.for("BOM with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"] + err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] t.rewind t.truncate(0) t.print "\u{feff}" @@ -718,6 +772,8 @@ module SEGVTest end def assert_segv(args, message=nil) + skip if ENV['RUBY_ON_BUG'] + test_stdin = "" opt = SEGVTest::ExecOptions.dup list = SEGVTest::ExpectedStderrList @@ -1011,11 +1067,11 @@ def test_frozen_string_literal_debug err = !freeze ? [] : debug ? with_debug_pat : wo_debug_pat [ ['"foo" << "bar"', err], - ['"foo#{123}bar" << "bar"', err], + ['"foo#{123}bar" << "bar"', []], ['+"foo#{123}bar" << "bar"', []], - ['-"foo#{123}bar" << "bar"', freeze && debug ? with_debug_pat : wo_debug_pat], + ['-"foo#{123}bar" << "bar"', wo_debug_pat], ].each do |code, expected| - assert_in_out_err(opt, code, [], expected, [opt, code]) + assert_in_out_err(opt, code, [], expected, "#{opt} #{code}") end end end @@ -1053,6 +1109,11 @@ def test_cwd_encoding end end + def test_rubylib_invalid_encoding + env = {"RUBYLIB"=>"\xFF", "LOCALE"=>"en_US.UTF-8", "LC_ALL"=>"en_US.UTF-8"} + assert_ruby_status([env, "-e;"]) + end + def test_null_script skip "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL) assert_in_out_err([IO::NULL], success: true) @@ -1062,7 +1123,7 @@ def test_jit_debug # mswin uses prebuilt precompiled header. Thus it does not show a pch compilation log to check "-O0 -O1". if JITSupport.supported? && !RUBY_PLATFORM.match?(/mswin/) env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } - assert_in_out_err([env, "--jit-debug=-O0 -O1", "--jit-verbose=2", "" ], "", [], /-O0 -O1/) + assert_in_out_err([env, "--disable-yjit", "--mjit-debug=-O0 -O1", "--mjit-verbose=2", "" ], "", [], /-O0 -O1/) end end @@ -1071,4 +1132,8 @@ def test_jit_debug def mjit_force_enabled? "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/) end + + def yjit_force_enabled? + "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?YJIT_FORCE_ENABLE\b/) + end end diff --git a/ruby/test/ruby/test_rubyvm.rb b/ruby/test/ruby/test_rubyvm.rb index 7673d8dfb..7d4588a16 100644 --- a/ruby/test/ruby/test_rubyvm.rb +++ b/ruby/test/ruby/test_rubyvm.rb @@ -4,15 +4,68 @@ class TestRubyVM < Test::Unit::TestCase def test_stat assert_kind_of Hash, RubyVM.stat - assert_kind_of Integer, RubyVM.stat[:global_method_state] + assert_kind_of Integer, RubyVM.stat[:global_constant_state] RubyVM.stat(stat = {}) assert_not_empty stat - assert_equal stat[:global_method_state], RubyVM.stat(:global_method_state) + assert_equal stat[:global_constant_state], RubyVM.stat(:global_constant_state) end def test_stat_unknown assert_raise(ArgumentError){ RubyVM.stat(:unknown) } assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {RubyVM.stat(:"\u{30eb 30d3 30fc}")} end + + def parse_and_compile + script = <<~RUBY + _a = 1 + def foo + _b = 2 + end + 1.times{ + _c = 3 + } + RUBY + + ast = RubyVM::AbstractSyntaxTree.parse(script) + iseq = RubyVM::InstructionSequence.compile(script) + + [ast, iseq] + end + + def test_keep_script_lines + prev_conf = RubyVM.keep_script_lines + + # keep + RubyVM.keep_script_lines = true + + ast, iseq = *parse_and_compile + + lines = ast.script_lines + assert_equal Array, lines.class + + lines = iseq.script_lines + assert_equal Array, lines.class + iseq.each_child{|child| + assert_equal lines, child.script_lines + } + assert lines.frozen? + + # don't keep + RubyVM.keep_script_lines = false + + ast, iseq = *parse_and_compile + + lines = ast.script_lines + assert_equal nil, lines + + lines = iseq.script_lines + assert_equal nil, lines + iseq.each_child{|child| + assert_equal lines, child.script_lines + } + + ensure + RubyVM.keep_script_lines = prev_conf + end end diff --git a/ruby/test/ruby/test_rubyvm_jit.rb b/ruby/test/ruby/test_rubyvm_jit.rb new file mode 100644 index 000000000..a3558d791 --- /dev/null +++ b/ruby/test/ruby/test_rubyvm_jit.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true +require 'test/unit' +require_relative '../lib/jit_support' + +return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no' + +class TestRubyVMJIT < Test::Unit::TestCase + include JITSupport + + def setup + unless JITSupport.supported? + skip 'JIT seems not supported on this platform' + end + end + + def test_pause + out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) + i = 0 + while i < 5 + eval("def mjit#{i}; end; mjit#{i}") + i += 1 + end + print RubyVM::MJIT.pause + print RubyVM::MJIT.pause + while i < 10 + eval("def mjit#{i}; end; mjit#{i}") + i += 1 + end + print RubyVM::MJIT.pause # no JIT here + EOS + assert_equal('truefalsefalse', out) + assert_equal( + 5, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, + "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", + ) + end + + def test_pause_waits_until_compaction + out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) + def a() end; a + def b() end; b + RubyVM::MJIT.pause + EOS + assert_equal( + 2, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, + "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", + ) + assert_equal( + 1, err.scan(/#{JITSupport::JIT_COMPACTION_PREFIX}/).size, + "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", + ) unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet + end + + def test_pause_does_not_hang_on_full_units + out, _ = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, max_cache: 10, wait: false) + i = 0 + while i < 11 + eval("def mjit#{i}; end; mjit#{i}") + i += 1 + end + print RubyVM::MJIT.pause + EOS + assert_equal('true', out) + end + + def test_pause_wait_false + out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) + i = 0 + while i < 10 + eval("def mjit#{i}; end; mjit#{i}") + i += 1 + end + print RubyVM::MJIT.pause(wait: false) + print RubyVM::MJIT.pause(wait: false) + EOS + assert_equal('truefalse', out) + assert_equal(true, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size < 10) + end + + def test_resume + out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) + print RubyVM::MJIT.resume + print RubyVM::MJIT.pause + print RubyVM::MJIT.resume + print RubyVM::MJIT.resume + print RubyVM::MJIT.pause + EOS + assert_equal('falsetruetruefalsetrue', out) + assert_equal(0, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size) + end +end diff --git a/ruby/test/ruby/test_rubyvm_mjit.rb b/ruby/test/ruby/test_rubyvm_mjit.rb deleted file mode 100644 index ef7475670..000000000 --- a/ruby/test/ruby/test_rubyvm_mjit.rb +++ /dev/null @@ -1,91 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require_relative '../lib/jit_support' - -return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no' - -class TestRubyVMMJIT < Test::Unit::TestCase - include JITSupport - - def setup - unless JITSupport.supported? - skip 'JIT seems not supported on this platform' - end - end - - def test_pause - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - i = 0 - while i < 5 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause - print RubyVM::MJIT.pause - while i < 10 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause # no JIT here - EOS - assert_equal('truefalsefalse', out) - assert_equal( - 5, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) - end - - def test_pause_waits_until_compaction - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - def a() end; a - def b() end; b - RubyVM::MJIT.pause - EOS - assert_equal( - 2, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) - assert_equal( - 1, err.scan(/#{JITSupport::JIT_COMPACTION_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet - end - - def test_pause_does_not_hang_on_full_units - out, _ = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, max_cache: 10, wait: false) - i = 0 - while i < 11 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause - EOS - assert_equal('true', out) - end - - def test_pause_wait_false - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - i = 0 - while i < 10 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause(wait: false) - print RubyVM::MJIT.pause(wait: false) - EOS - assert_equal('truefalse', out) - assert_equal(true, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size < 10) - end - - def test_resume - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - print RubyVM::MJIT.resume - print RubyVM::MJIT.pause - print RubyVM::MJIT.resume - print RubyVM::MJIT.resume - print RubyVM::MJIT.pause - EOS - assert_equal('falsetruetruefalsetrue', out) - assert_equal(0, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size) - end -end diff --git a/ruby/test/ruby/test_settracefunc.rb b/ruby/test/ruby/test_settracefunc.rb index ada7b7596..c25debb38 100644 --- a/ruby/test/ruby/test_settracefunc.rb +++ b/ruby/test/ruby/test_settracefunc.rb @@ -3,17 +3,21 @@ class TestSetTraceFunc < Test::Unit::TestCase def setup - @original_compile_option = RubyVM::InstructionSequence.compile_option - RubyVM::InstructionSequence.compile_option = { - :trace_instruction => true, - :specialized_instruction => false - } + if defined?(RubyVM) + @original_compile_option = RubyVM::InstructionSequence.compile_option + RubyVM::InstructionSequence.compile_option = { + :trace_instruction => true, + :specialized_instruction => false + } + end @target_thread = Thread.current end def teardown set_trace_func(nil) - RubyVM::InstructionSequence.compile_option = @original_compile_option + if defined?(RubyVM) + RubyVM::InstructionSequence.compile_option = @original_compile_option + end @target_thread = nil end @@ -137,6 +141,10 @@ def test_class assert_equal(["c-call", 9, :set_trace_func, Kernel], events.shift) assert_equal([], events) + + self.class.class_eval do + remove_const :Foo + end end def test_return # [ruby-dev:38701] @@ -362,6 +370,11 @@ def test_thread_trace end assert_equal([], events[:set]) assert_equal([], events[:add]) + + # cleanup + self.class.class_eval do + remove_const :ThreadTraceInnerClass + end end def test_trace_defined_method @@ -380,7 +393,7 @@ def test_trace_defined_method [["c-return", 3, :set_trace_func, Kernel], ["line", 6, __method__, self.class], ["call", 1, :foobar, FooBar], - ["return", 6, :foobar, FooBar], + ["return", 1, :foobar, FooBar], ["line", 7, __method__, self.class], ["c-call", 7, :set_trace_func, Kernel]].each{|e| assert_equal(e, events.shift) @@ -472,8 +485,6 @@ def trace_by_tracepoint *trace_events [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing], - [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self], [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], @@ -499,8 +510,6 @@ def trace_by_tracepoint *trace_events [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], - [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing], - [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy], [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], @@ -555,6 +564,16 @@ def test_tracepoint } end + # Bug #18264 + def test_tracepoint_memory_leak + assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true) +code = proc { TracePoint.new(:line) { } } +1_000.times(&code) +PREP +1_000_000.times(&code) +CODE + end + def trace_by_set_trace_func events = [] trace = nil @@ -597,8 +616,6 @@ def trace_by_set_trace_func [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing], - [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self], [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], @@ -624,8 +641,6 @@ def trace_by_set_trace_func [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], - [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing], - [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy], [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], @@ -826,6 +841,56 @@ def test_tracepoint_return_value } end + def test_tracepoint_attr + c = Class.new do + attr_accessor :x + alias y x + alias y= x= + end + obj = c.new + + ar_meth = obj.method(:x) + aw_meth = obj.method(:x=) + aar_meth = obj.method(:y) + aaw_meth = obj.method(:y=) + events = [] + trace = TracePoint.new(:c_call, :c_return){|tp| + next if !target_thread? + next if tp.path != __FILE__ + next if tp.method_id == :call + case tp.event + when :c_call + assert_raise(RuntimeError) {tp.return_value} + events << [tp.event, tp.method_id, tp.callee_id] + when :c_return + events << [tp.event, tp.method_id, tp.callee_id, tp.return_value] + end + } + test_proc = proc do + obj.x = 1 + obj.x + obj.y = 2 + obj.y + aw_meth.call(1) + ar_meth.call + aaw_meth.call(2) + aar_meth.call + end + test_proc.call # populate call caches + trace.enable(&test_proc) + expected = [ + [:c_call, :x=, :x=], + [:c_return, :x=, :x=, 1], + [:c_call, :x, :x], + [:c_return, :x, :x, 1], + [:c_call, :x=, :y=], + [:c_return, :x=, :y=, 2], + [:c_call, :x, :y], + [:c_return, :x, :y, 2], + ] + assert_equal(expected*2, events) + end + class XYZZYException < Exception; end def method_test_tracepoint_raised_exception err raise err @@ -932,9 +997,9 @@ def test_tracepoint_inspect when :line assert_match(/ in /, str) when :call, :c_call - assert_match(/call \`/, str) # # + assert_match(/call \`/, str) # # when :return, :c_return - assert_match(/return \`/, str) # # + assert_match(/return \`/, str) # # when /thread/ assert_match(/\#> else @@ -977,20 +1042,24 @@ def test_tracepoint_exception_at_c_return def test_tracepoint_with_multithreads assert_nothing_raised do - TracePoint.new{ + TracePoint.new(:line){ 10.times{ Thread.pass } }.enable do (1..10).map{ Thread.new{ - 1000.times{ + 1_000.times{|i| + _a = i } } }.each{|th| th.join } end + _a = 1 + _b = 2 + _c = 3 # to make sure the deletion of unused TracePoints end end @@ -1588,6 +1657,33 @@ def test_fiber_switch assert_equal ev, :fiber_switch } + # test for raise into resumable fiber + evs = [] + f = nil + TracePoint.new(:raise, :fiber_switch){|tp| + next unless target_thread? + evs << [tp.event, Fiber.current] + }.enable{ + f = Fiber.new{ + Fiber.yield # will raise + Fiber.yield # unreachable + } + begin + f.resume + f.raise StopIteration + rescue StopIteration + evs << :rescued + end + } + assert_equal [:fiber_switch, f], evs[0], "initial resume" + assert_equal [:fiber_switch, Fiber.current], evs[1], "Fiber.yield" + assert_equal [:fiber_switch, f], evs[2], "fiber.raise" + assert_equal [:raise, f], evs[3], "fiber.raise" + assert_equal [:fiber_switch, Fiber.current], evs[4], "terminated with raise" + assert_equal [:raise, Fiber.current], evs[5], "terminated with raise" + assert_equal :rescued, evs[6] + assert_equal 7, evs.size + # test for transfer evs = [] TracePoint.new(:fiber_switch){|tp| @@ -1610,6 +1706,41 @@ def test_fiber_switch evs.each{|ev| assert_equal ev, :fiber_switch } + + # test for raise and from transferring fibers + evs = [] + f1 = f2 = nil + TracePoint.new(:raise, :fiber_switch){|tp| + next unless target_thread? + evs << [tp.event, Fiber.current] + }.enable{ + f1 = Fiber.new{ + f2.transfer + f2.raise ScriptError + Fiber.yield :ok + } + f2 = Fiber.new{ + f1.transfer + f1.transfer + } + begin + f1.resume + rescue ScriptError + evs << :rescued + end + } + assert_equal [:fiber_switch, f1], evs[0], "initial resume" + assert_equal [:fiber_switch, f2], evs[1], "f2.transfer" + assert_equal [:fiber_switch, f1], evs[2], "f1.transfer" + assert_equal [:fiber_switch, f2], evs[3], "f2.raise ScriptError" + assert_equal [:raise, f2], evs[4], "f2.raise ScriptError" + assert_equal [:fiber_switch, f1], evs[5], "f2 unhandled exception" + assert_equal [:raise, f1], evs[6], "f2 unhandled exception" + assert_equal [:fiber_switch, Fiber.current], evs[7], "f1 unhandled exception" + assert_equal [:raise, Fiber.current], evs[8], "f1 unhandled exception" + assert_equal :rescued, evs[9], "rescued everything" + assert_equal 10, evs.size + end def test_tracepoint_callee_id @@ -1672,7 +1803,7 @@ def m TracePoint.new(:return, &capture_events).enable{ o.alias_m } - assert_equal [[:return, :m, :alias_m]], events + assert_equal [[:return, :tap, :tap], [:return, :m, :alias_m]], events events.clear o = Class.new{ @@ -1696,13 +1827,13 @@ def m events.clear o = Class.new{ - alias alias_tap tap - define_method(:m){alias_tap{return}} + alias alias_singleton_class singleton_class + define_method(:m){alias_singleton_class} }.new TracePoint.new(:c_return, &capture_events).enable{ o.m } - assert_equal [[:c_return, :tap, :alias_tap]], events + assert_equal [[:c_return, :singleton_class, :alias_singleton_class]], events events.clear c = Class.new{ @@ -1820,7 +1951,7 @@ def test_return_value_with_rescue end define_method(:f_break_defined) do - return :f_break_defined + break :f_break_defined end define_method(:f_raise_defined) do @@ -1841,27 +1972,44 @@ def test_return_value_with_rescue_and_defined_methods tp_return_value(:f_last_defined), '[Bug #13369]' - assert_equal [[:b_return, :f_return_defined, nil], # current limitation + assert_equal [[:b_return, :f_return_defined, :f_return_defined], [:return, :f_return_defined, :f_return_defined]], tp_return_value(:f_return_defined), '[Bug #13369]' - assert_equal [[:b_return, :f_break_defined, nil], + assert_equal [[:b_return, :f_break_defined, :f_break_defined], [:return, :f_break_defined, :f_break_defined]], tp_return_value(:f_break_defined), '[Bug #13369]' - assert_equal [[:b_return, :f_raise_defined, nil], + assert_equal [[:b_return, :f_raise_defined, f_raise_defined], [:return, :f_raise_defined, f_raise_defined]], tp_return_value(:f_raise_defined), '[Bug #13369]' - assert_equal [[:b_return, :f_break_in_rescue_defined, nil], + assert_equal [[:b_return, :f_break_in_rescue_defined, f_break_in_rescue_defined], [:return, :f_break_in_rescue_defined, f_break_in_rescue_defined]], tp_return_value(:f_break_in_rescue_defined), '[Bug #13369]' end + define_method(:just_yield) do |&block| + block.call + end + + define_method(:unwind_multiple_bmethods) do + just_yield { return :unwind_multiple_bmethods } + end + + def test_non_local_return_across_multiple_define_methods + assert_equal [[:b_return, :unwind_multiple_bmethods, nil], + [:b_return, :just_yield, nil], + [:return, :just_yield, nil], + [:b_return, :unwind_multiple_bmethods, :unwind_multiple_bmethods], + [:return, :unwind_multiple_bmethods, :unwind_multiple_bmethods]], + tp_return_value(:unwind_multiple_bmethods) + end + def f_iter yield end @@ -1917,7 +2065,7 @@ def method_for_test_thread_add_trace_func def test_thread_add_trace_func events = [] base_line = __LINE__ - q = Queue.new + q = Thread::Queue.new t = Thread.new{ Thread.current.add_trace_func proc{|ev, file, line, *args| events << [ev, line] @@ -1943,7 +2091,7 @@ def test_thread_add_trace_func # other thread events = [] - m2t_q = Queue.new + m2t_q = Thread::Queue.new t = Thread.new{ Thread.current.abort_on_exception = true @@ -1958,7 +2106,7 @@ def test_thread_add_trace_func Thread.pass until t.status == 'sleep' # When MJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop. # This sleep forces it to reach m2t_q.pop for --jit-wait. - sleep 1 if RubyVM::MJIT.enabled? + sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? t.add_trace_func proc{|ev, file, line, *args| if file == __FILE__ @@ -2170,6 +2318,31 @@ def test_tracepoint_enable_with_target_line assert_equal 'target_line is specified, but line event is not specified', e.message end + def test_tracepoint_enable_with_target_line_two_times + events = [] + line_0 = __LINE__ + code1 = proc{ + events << 1 # tp1 + events << 2 + events << 3 # tp2 + } + + tp1 = TracePoint.new(:line) do |tp| + events << :tp1 + end + tp2 = TracePoint.new(:line) do |tp| + events << :tp2 + end + + tp1.enable(target: code1, target_line: line_0 + 2) do + tp2.enable(target: code1, target_line: line_0 + 4) do + # two hooks + code1.call + end + end + assert_equal [:tp1, 1, 2, :tp2, 3], events + end + def test_script_compiled events = [] tp = TracePoint.new(:script_compiled){|tp| @@ -2228,8 +2401,8 @@ def test_enable_target_thread events << Thread.current end - q1 = Queue.new - q2 = Queue.new + q1 = Thread::Queue.new + q2 = Thread::Queue.new th = Thread.new{ q1 << :ok; q2.pop @@ -2247,6 +2420,99 @@ def test_enable_target_thread assert_equal Array.new(2){th}, events end + def test_return_bmethod_location + bug13392 = "[ruby-core:80515] incorrect bmethod return location" + actual = nil + obj = Object.new + expected = __LINE__ + 1 + obj.define_singleton_method(:t){} + tp = TracePoint.new(:return) do + next unless target_thread? + actual = tp.lineno + end + tp.enable {obj.t} + assert_equal(expected, actual, bug13392) + end + + def test_b_tracepoints_going_away + # test that call and return TracePoints continue to work + # when b_call and b_return TracePoints stop + events = [] + record_events = ->(tp) do + next unless target_thread? + events << [tp.event, tp.method_id] + end + + call_ret_tp = TracePoint.new(:call, :return, &record_events) + block_call_ret_tp = TracePoint.new(:b_call, :b_return, &record_events) + + obj = Object.new + obj.define_singleton_method(:foo) {} # a bmethod + + foo = obj.method(:foo) + call_ret_tp.enable(target: foo) do + block_call_ret_tp.enable(target: foo) do + obj.foo + end + obj.foo + end + + assert_equal( + [ + [:call, :foo], + [:b_call, :foo], + [:b_return, :foo], + [:return, :foo], + [:call, :foo], + [:return, :foo], + ], + events, + ) + end + + def test_target_different_bmethod_same_iseq + # make two bmethods that share the same block iseq + block = Proc.new {} + obj = Object.new + obj.define_singleton_method(:one, &block) + obj.define_singleton_method(:two, &block) + + events = [] + record_events = ->(tp) do + next unless target_thread? + events << [tp.event, tp.method_id] + end + tp_one = TracePoint.new(:call, :return, &record_events) + tp_two = TracePoint.new(:call, :return, &record_events) + + tp_one.enable(target: obj.method(:one)) do + obj.one + obj.two # not targeted + end + assert_equal([[:call, :one], [:return, :one]], events) + events.clear + + tp_one.enable(target: obj.method(:one)) do + obj.one + tp_two.enable(target: obj.method(:two)) do + obj.two + end + obj.two + obj.one + end + assert_equal( + [ + [:call, :one], + [:return, :one], + [:call, :two], + [:return, :two], + [:call, :one], + [:return, :one], + ], + events + ) + end + def test_return_event_with_rescue obj = Object.new def obj.example @@ -2279,4 +2545,58 @@ def bar def test_stat_exists assert_instance_of Hash, TracePoint.stat end + + def test_tracepoint_opt_invokebuiltin_delegate_leave + code = 'puts RubyVM::InstructionSequence.of("\x00".method(:unpack)).disasm' + out = EnvUtil.invoke_ruby(['-e', code], '', true).first + assert_match(/^0000 opt_invokebuiltin_delegate_leave /, out) + + event = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first) + TracePoint.new(:return) do |tp| + p [tp.event, tp.method_id] + end.enable do + "\x00".unpack("c") + end + EOS + assert_equal [:return, :unpack], event + end + + def test_while_in_while + lines = [] + + TracePoint.new(:line){|tp| + next unless target_thread? + lines << tp.lineno + }.enable{ + n = 3 + while n > 0 + n -= 1 while n > 0 + end + } + assert_equal [__LINE__ - 5, __LINE__ - 4, __LINE__ - 3], lines, 'Bug #17868' + end + + def test_allow_reentry + event_lines = [] + _l1 = _l2 = _l3 = _l4 = nil + TracePoint.new(:line) do |tp| + next unless target_thread? + + event_lines << tp.lineno + next if (__LINE__ + 2 .. __LINE__ + 4).cover?(tp.lineno) + TracePoint.allow_reentry do + _a = 1; _l3 = __LINE__ + _b = 2; _l4 = __LINE__ + end + end.enable do + _c = 3; _l1 = __LINE__ + _d = 4; _l2 = __LINE__ + end + + assert_equal [_l1, _l3, _l4, _l2, _l3, _l4], event_lines + + assert_raise RuntimeError do + TracePoint.allow_reentry{} + end + end end diff --git a/ruby/test/ruby/test_sprintf.rb b/ruby/test/ruby/test_sprintf.rb index 7986e9d14..f2e73eb58 100644 --- a/ruby/test/ruby/test_sprintf.rb +++ b/ruby/test/ruby/test_sprintf.rb @@ -528,19 +528,4 @@ def test_negative_width_overflow sprintf("%*s", RbConfig::LIMITS["INT_MIN"], "") end end - - def test_no_hidden_garbage - skip unless Thread.list.size == 1 - - fmt = [4, 2, 2].map { |x| "%0#{x}d" }.join('-') # defeats optimization - ObjectSpace.count_objects(res = {}) # creates strings on first call - GC.disable - before = ObjectSpace.count_objects(res)[:T_STRING] - val = sprintf(fmt, 1970, 1, 1) - after = ObjectSpace.count_objects(res)[:T_STRING] - assert_equal before + 1, after, 'only new string is the created one' - assert_equal '1970-01-01', val - ensure - GC.enable - end end diff --git a/ruby/test/ruby/test_stack.rb b/ruby/test/ruby/test_stack.rb new file mode 100644 index 000000000..763aeb6bc --- /dev/null +++ b/ruby/test/ruby/test_stack.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: false +require 'test/unit' +require 'tmpdir' + +class TestStack < Test::Unit::TestCase + LARGE_VM_STACK_SIZE = 1024*1024*5 + LARGE_MACHINE_STACK_SIZE = 1024*1024*10 + + def initialize(*) + super + + @h_default = nil + @h_0 = nil + @h_large = nil + end + + def invoke_ruby script, vm_stack_size: nil, machine_stack_size: nil + env = {} + env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size + env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size + env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS'] + + stdout, stderr, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, timeout: 30) + assert(!status.signaled?, FailDesc[status, nil, stderr]) + + return stdout + end + + def h_default + @h_default ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS')) + end + + def h_0 + @h_0 ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS', + vm_stack_size: 0, + machine_stack_size: 0 + )) + end + + def h_large + @h_large ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS', + vm_stack_size: LARGE_VM_STACK_SIZE, + machine_stack_size: LARGE_MACHINE_STACK_SIZE + )) + end + + def test_relative_stack_sizes + assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size]) + assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size]) + assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size]) + assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size]) + end + + def test_vm_stack_size + script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume' + + size_default = invoke_ruby(script).bytesize + assert_operator(size_default, :>, 0) + + size_0 = invoke_ruby(script, vm_stack_size: 0).bytesize + assert_operator(size_default, :>, size_0) + + size_large = invoke_ruby(script, vm_stack_size: LARGE_VM_STACK_SIZE).bytesize + assert_operator(size_default, :<, size_large) + end + + # Depending on OS, machine stack size may not change size. + def test_machine_stack_size + return if /mswin|mingw/ =~ RUBY_PLATFORM + + script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume' + + vm_stack_size = 1024 * 1024 + size_default = invoke_ruby(script, vm_stack_size: vm_stack_size).bytesize + + size_0 = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: 0).bytesize + assert_operator(size_default, :>=, size_0) + + size_large = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: LARGE_MACHINE_STACK_SIZE).bytesize + assert_operator(size_default, :<=, size_large) + end +end diff --git a/ruby/test/ruby/test_string.rb b/ruby/test/ruby/test_string.rb index 09d099bb4..3f7c06e07 100644 --- a/ruby/test/ruby/test_string.rb +++ b/ruby/test/ruby/test_string.rb @@ -2,8 +2,6 @@ require 'test/unit' class TestString < Test::Unit::TestCase - ENUMERATOR_WANTARRAY = RUBY_VERSION >= "3.0.0" - WIDE_ENCODINGS = [ Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE, @@ -107,6 +105,16 @@ def test_initialize_memory_leak CODE end + # Bug #18154 + def test_initialize_nofree_memory_leak + assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true) +code = proc {0.to_s.__send__(:initialize, capacity: 10000)} +1_000.times(&code) +PREP +100_000.times(&code) +CODE + end + def test_AREF # '[]' assert_equal("A", S("AooBar")[0]) assert_equal("B", S("FooBaB")[-1]) @@ -257,6 +265,7 @@ def test_EQUAL # '==' assert_not_equal(S("CAT"), S('cat')) assert_not_equal(S("CaT"), S('cAt')) + assert_not_equal(S("cat\0""dog"), S("cat\0")) o = Object.new def o.to_str; end @@ -387,6 +396,8 @@ def test_center end def test_chomp + verbose, $VERBOSE = $VERBOSE, nil + assert_equal(S("hello"), S("hello").chomp("\n")) assert_equal(S("hello"), S("hello\n").chomp("\n")) save = $/ @@ -452,9 +463,12 @@ def test_chomp assert_equal("foo", s.chomp("\n")) ensure $/ = save + $VERBOSE = verbose end def test_chomp! + verbose, $VERBOSE = $VERBOSE, nil + a = S("hello") a.chomp!(S("\n")) @@ -511,6 +525,7 @@ def test_chomp! s = S("").freeze assert_raise_with_message(FrozenError, /frozen/) {s.chomp!} + $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state s = S("ax") o = Struct.new(:s).new(s) @@ -519,6 +534,7 @@ def o.to_str "x" end assert_raise_with_message(FrozenError, /frozen/) {s.chomp!(o)} + $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state s = S("hello") assert_equal("hel", s.chomp!('lo')) @@ -569,6 +585,7 @@ def o.to_str assert_equal("foo", s.chomp!("\n")) ensure $/ = save + $VERBOSE = verbose end def test_chop @@ -688,6 +705,7 @@ def test_crypt @cls == String and assert_no_memory_leak([], "s = ''; salt_proc = proc{#{(crypt_supports_des_crypt? ? '..' : good_salt).inspect}}", "#{<<~"begin;"}\n#{<<~'end;'}") + begin; 1000.times { s.crypt(-salt_proc.call).clear } end; @@ -751,6 +769,7 @@ def test_downcase assert_equal(S("hello"), S("hello").downcase) assert_equal(S("hello"), S("HELLO").downcase) assert_equal(S("abc hello 123"), S("abc HELLO 123").downcase) + assert_equal(S("h\0""ello"), S("h\0""ELLO").downcase) end def test_downcase! @@ -763,6 +782,12 @@ def test_downcase! a=S("hello") assert_nil(a.downcase!) assert_equal(S("hello"), a) + + a = S("h\0""ELLO") + b = a.dup + assert_equal(S("h\0""ello"), a.downcase!) + assert_equal(S("h\0""ello"), a) + assert_equal(S("h\0""ELLO"), b) end def test_dump @@ -859,6 +884,8 @@ def test_dup end def test_each + verbose, $VERBOSE = $VERBOSE, nil + save = $/ $/ = "\n" res=[] @@ -878,6 +905,7 @@ def test_each assert_equal(S("world"), res[1]) ensure $/ = save + $VERBOSE = verbose end def test_each_byte @@ -896,21 +924,15 @@ def test_bytes s = S("ABC") assert_equal [65, 66, 67], s.bytes - if ENUMERATOR_WANTARRAY - assert_warn(/block not used/) { - assert_equal [65, 66, 67], s.bytes {} - } - else - res = [] - assert_equal s.object_id, s.bytes {|x| res << x }.object_id - assert_equal(65, res[0]) - assert_equal(66, res[1]) - assert_equal(67, res[2]) - s = S("ABC") - res = [] - assert_same s, s.bytes {|x| res << x } - assert_equal [65, 66, 67], res - end + res = [] + assert_equal s.object_id, s.bytes {|x| res << x }.object_id + assert_equal(65, res[0]) + assert_equal(66, res[1]) + assert_equal(67, res[2]) + s = S("ABC") + res = [] + assert_same s, s.bytes {|x| res << x } + assert_equal [65, 66, 67], res end def test_each_codepoint @@ -935,21 +957,15 @@ def test_codepoints s = S("\u3042\u3044\u3046") assert_equal [0x3042, 0x3044, 0x3046], s.codepoints - if ENUMERATOR_WANTARRAY - assert_warn(/block not used/) { - assert_equal [0x3042, 0x3044, 0x3046], s.codepoints {} - } - else - res = [] - assert_equal s.object_id, s.codepoints {|x| res << x }.object_id - assert_equal(0x3042, res[0]) - assert_equal(0x3044, res[1]) - assert_equal(0x3046, res[2]) - s = S("ABC") - res = [] - assert_same s, s.codepoints {|x| res << x } - assert_equal [65, 66, 67], res - end + res = [] + assert_equal s.object_id, s.codepoints {|x| res << x }.object_id + assert_equal(0x3042, res[0]) + assert_equal(0x3044, res[1]) + assert_equal(0x3046, res[2]) + s = S("ABC") + res = [] + assert_same s, s.codepoints {|x| res << x } + assert_equal [65, 66, 67], res end def test_each_char @@ -968,17 +984,11 @@ def test_chars s = S("ABC") assert_equal ["A", "B", "C"], s.chars - if ENUMERATOR_WANTARRAY - assert_warn(/block not used/) { - assert_equal ["A", "B", "C"], s.chars {} - } - else - res = [] - assert_equal s.object_id, s.chars {|x| res << x }.object_id - assert_equal("A", res[0]) - assert_equal("B", res[1]) - assert_equal("C", res[2]) - end + res = [] + assert_equal s.object_id, s.chars {|x| res << x }.object_id + assert_equal("A", res[0]) + assert_equal("B", res[1]) + assert_equal("C", res[2]) end def test_each_grapheme_cluster @@ -1039,22 +1049,18 @@ def test_grapheme_clusters end assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters - if ENUMERATOR_WANTARRAY - assert_warn(/block not used/) { - assert_equal ["A", "B", "C"], "ABC".grapheme_clusters {} - } - else - s = "ABC".b - res = [] - assert_same s, s.grapheme_clusters {|x| res << x } - assert_equal(3, res.size) - assert_equal("A", res[0]) - assert_equal("B", res[1]) - assert_equal("C", res[2]) - end + s = "ABC".b + res = [] + assert_same s, s.grapheme_clusters {|x| res << x } + assert_equal(3, res.size) + assert_equal("A", res[0]) + assert_equal("B", res[1]) + assert_equal("C", res[2]) end def test_each_line + verbose, $VERBOSE = $VERBOSE, nil + save = $/ $/ = "\n" res=[] @@ -1101,6 +1107,7 @@ def test_each_line end ensure $/ = save + $VERBOSE = verbose end def test_each_line_chomp @@ -1158,16 +1165,10 @@ def test_lines assert_equal ["hello\n", "world"], s.lines assert_equal ["hello\nworld"], s.lines(nil) - if ENUMERATOR_WANTARRAY - assert_warn(/block not used/) { - assert_equal ["hello\n", "world"], s.lines {} - } - else - res = [] - assert_equal s.object_id, s.lines {|x| res << x }.object_id - assert_equal(S("hello\n"), res[0]) - assert_equal(S("world"), res[1]) - end + res = [] + assert_equal s.object_id, s.lines {|x| res << x }.object_id + assert_equal(S("hello\n"), res[0]) + assert_equal(S("world"), res[1]) end def test_empty? @@ -1179,6 +1180,8 @@ def test_end_with? assert_send([S("hello"), :end_with?, S("llo")]) assert_not_send([S("hello"), :end_with?, S("ll")]) assert_send([S("hello"), :end_with?, S("el"), S("lo")]) + assert_send([S("hello"), :end_with?, S("")]) + assert_not_send([S("hello"), :end_with?]) bug5536 = '[ruby-core:40623]' assert_raise(TypeError, bug5536) {S("str").end_with? :not_convertible_to_string} @@ -1331,6 +1334,8 @@ def o.to_str; "bar"; end assert_nil("foo".index(//, -100)) assert_nil($~) + + assert_equal(2, S("abcdbce").index(/b\Kc/)) end def test_insert @@ -1503,6 +1508,8 @@ def o.to_str; "bar"; end assert_equal(3, "foo".rindex(//)) assert_equal([3, 3], $~.offset(0)) + + assert_equal(5, S("abcdbce").rindex(/b\Kc/)) end def test_rjust @@ -1594,8 +1601,10 @@ def test_slice! a = S("FooBar") if @aref_slicebang_silent assert_nil( a.slice!(6) ) + assert_nil( a.slice!(6r) ) else assert_raise(IndexError) { a.slice!(6) } + assert_raise(IndexError) { a.slice!(6r) } end assert_equal(S("FooBar"), a) @@ -1768,13 +1777,6 @@ def test_fs GC.start assert_equal([], "".split, bug) end; - - begin - fs = $; - assert_warn(/`\$;' is deprecated/) {$; = " "} - ensure - EnvUtil.suppress_warning {$; = fs} - end end def test_split_encoding @@ -1816,6 +1818,11 @@ def test_split_dupped assert_equal("abc", s) end + def test_split_lookbehind + assert_equal([S("ab"), S("d")], S("abcd").split(/(?<=b)c/)) + assert_equal([S("ab"), S("d")], S("abcd").split(/b\Kc/)) + end + def test_squeeze assert_equal(S("abc"), S("aaabbbbccc").squeeze) assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" "))) @@ -1858,6 +1865,7 @@ def test_start_with? def test_strip assert_equal(S("x"), S(" x ").strip) assert_equal(S("x"), S(" \n\r\t x \t\r\n\n ").strip) + assert_equal(S("x"), S("\x00x\x00").strip) assert_equal("0b0 ".force_encoding("UTF-16BE"), "\x00 0b0 ".force_encoding("UTF-16BE").strip) @@ -1876,6 +1884,10 @@ def test_strip! assert_equal(S("x"), a.strip!) assert_equal(S("x"), a) + a = S("\x00x\x00") + assert_equal(S("x"), a.strip!) + assert_equal(S("x"), a) + a = S("x") assert_nil(a.strip!) assert_equal(S("x") ,a) @@ -2095,6 +2107,8 @@ def test_sum_long def test_swapcase assert_equal(S("hi&LOW"), S("HI&low").swapcase) + s = S("") + assert_not_same(s, s.swapcase) end def test_swapcase! @@ -2330,6 +2344,7 @@ def test_upcase assert_equal(S("HELLO"), S("hello").upcase) assert_equal(S("HELLO"), S("HELLO").upcase) assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase) + assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase) end def test_upcase! @@ -2342,6 +2357,12 @@ def test_upcase! a = S("HELLO") assert_nil(a.upcase!) assert_equal(S("HELLO"), a) + + a = S("H\0""ello") + b = a.dup + assert_equal(S("H\0""ELLO"), a.upcase!) + assert_equal(S("H\0""ELLO"), a) + assert_equal(S("H\0""ello"), b) end def test_upto @@ -2567,6 +2588,10 @@ def (hyphen = Object.new).to_str; "-"; end hello = "hello" hello.partition("hi").map(&:upcase!) assert_equal("hello", hello, bug) + + assert_equal(["", "", "foo"], "foo".partition(/^=*/)) + + assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/)) end def test_rpartition @@ -2591,6 +2616,8 @@ def (hyphen = Object.new).to_str; "-"; end hello = "hello" hello.rpartition("hi").map(&:upcase!) assert_equal("hello", hello, bug) + + assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/)) end def test_setter @@ -2658,6 +2685,7 @@ def test_casecmp assert_equal(1, "FoO".casecmp("BaR")) assert_equal(-1, "baR".casecmp("FoO")) assert_equal(1, "\u3042B".casecmp("\u3042a")) + assert_equal(-1, "foo".casecmp("foo\0")) assert_nil("foo".casecmp(:foo)) assert_nil("foo".casecmp(Object.new)) @@ -2672,6 +2700,7 @@ def test_casecmp? assert_equal(false, 'FoO'.casecmp?('BaR')) assert_equal(false, 'baR'.casecmp?('FoO')) assert_equal(true, 'äöü'.casecmp?('ÄÖÜ')) + assert_equal(false, "foo".casecmp?("foo\0")) assert_nil("foo".casecmp?(:foo)) assert_nil("foo".casecmp?(Object.new)) @@ -2692,6 +2721,7 @@ def test_downcase2 def test_rstrip assert_equal(" hello", " hello ".rstrip) assert_equal("\u3042", "\u3042 ".rstrip) + assert_equal("\u3042", "\u3042\u0000".rstrip) assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip } end @@ -2712,12 +2742,17 @@ def test_rstrip_bang assert_equal(nil, s4.rstrip!) assert_equal("\u3042", s4) + s5 = S("\u3042\u0000") + assert_equal("\u3042", s5.rstrip!) + assert_equal("\u3042", s5) + assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! } end def test_lstrip assert_equal("hello ", " hello ".lstrip) assert_equal("\u3042", " \u3042".lstrip) + assert_equal("hello ", "\x00hello ".lstrip) end def test_lstrip_bang @@ -2736,6 +2771,11 @@ def test_lstrip_bang s4 = S("\u3042") assert_equal(nil, s4.lstrip!) assert_equal("\u3042", s4) + + s5 = S("\u0000\u3042") + assert_equal("\u3042", s5.lstrip!) + assert_equal("\u3042", s5) + end def test_delete_prefix @@ -3141,6 +3181,22 @@ def test_uplus_minus assert_same(str, -bar, "uminus deduplicates [Feature #13077]") end + def test_uminus_frozen + # embedded + str1 = ("foobar" * 3).freeze + str2 = ("foobar" * 3).freeze + assert_not_same str1, str2 + assert_same str1, -str1 + assert_same str1, -str2 + + # regular + str1 = ("foobar" * 4).freeze + str2 = ("foobar" * 4).freeze + assert_not_same str1, str2 + assert_same str1, -str1 + assert_same str1, -str2 + end + def test_uminus_no_freeze_not_bare str = @cls.new("foo") assert_instance_of(@cls, -str) diff --git a/ruby/test/ruby/test_struct.rb b/ruby/test/ruby/test_struct.rb index f13afbbdd..176e2ac5d 100644 --- a/ruby/test/ruby/test_struct.rb +++ b/ruby/test/ruby/test_struct.rb @@ -23,6 +23,10 @@ def test_struct test.bar = 47 assert_equal(47, test.bar) + + @Struct.class_eval do + remove_const :Test + end end # [ruby-dev:26247] more than 10 struct members causes segmentation fault @@ -114,10 +118,9 @@ def test_struct_new_with_keyword_init assert_equal "#{@Struct}::KeywordInitFalse", @Struct::KeywordInitFalse.inspect assert_equal "#{@Struct}::KeywordInitTrue(keyword_init: true)", @Struct::KeywordInitTrue.inspect # eval is needed to prevent the warning duplication filter - k = eval("Class.new(@Struct::KeywordInitFalse) {def initialize(**) end}") - assert_warn(/Using the last argument as keyword parameters is deprecated/) {k.new(a: 1, b: 2)} - k = Class.new(@Struct::KeywordInitTrue) {def initialize(**) end} - assert_warn('') {k.new(a: 1, b: 2)} + k = Class.new(@Struct::KeywordInitTrue) {def initialize(b, options); super(a: options, b: b); end} + o = assert_warn('') { k.new(42, {foo: 1, bar: 2}) } + assert_equal(1, o.a[:foo]) @Struct.instance_eval do remove_const(:KeywordInitTrue) @@ -135,6 +138,17 @@ def c assert_equal(3, struct.new(a: 1, b: 2).c) end + def test_struct_keyword_init_p + struct = @Struct.new(:a, :b, keyword_init: true) + assert_equal(true, struct.keyword_init?) + + struct = @Struct.new(:a, :b, keyword_init: false) + assert_equal(false, struct.keyword_init?) + + struct = @Struct.new(:a, :b) + assert_nil(struct.keyword_init?) + end + def test_initialize klass = @Struct.new(:a) assert_raise(ArgumentError) { klass.new(1, 2) } @@ -146,6 +160,17 @@ def initialize(a, b) assert_equal 3, klass.new(1,2).total end + def test_initialize_with_kw + klass = @Struct.new(:foo, :options) do + def initialize(foo, **options) + super(foo, options) + end + end + assert_equal({}, klass.new(42, **Hash.new).options) + x = assert_warn('') { klass.new(1, bar: 2) } + assert_equal 2, x.options[:bar] + end + def test_each klass = @Struct.new(:a, :b) o = klass.new(1, 2) @@ -325,15 +350,31 @@ def test_error end def test_redefinition_warning - @Struct.new("RedefinitionWarning") + @Struct.new(name = "RedefinitionWarning") e = EnvUtil.verbose_warning do @Struct.new("RedefinitionWarning") end assert_match(/redefining constant #@Struct::RedefinitionWarning/, e) + + @Struct.class_eval do + remove_const name + end + end + + def test_keyword_args_warning + warning = /warning: Passing only keyword arguments to Struct#initialize will behave differently from Ruby 3\.2\./ + assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a).new(a: 1).a) } + assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a, keyword_init: nil).new(a: 1).a) } + assert_warn('') { assert_equal({a: 1}, @Struct.new(:a).new({a: 1}).a) } + assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, :b).new(1, a: 1).b) } + assert_warn('') { assert_equal(1, @Struct.new(:a, keyword_init: true).new(a: 1).a) } + assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, keyword_init: nil).new({a: 1}).a) } + assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, keyword_init: false).new(a: 1).a) } + assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, keyword_init: false).new({a: 1}).a) } end def test_nonascii - struct_test = @Struct.new("R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}") + struct_test = @Struct.new(name = "R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}") assert_equal(@Struct.const_get("R\u{e9}sum\u{e9}"), struct_test, '[ruby-core:24849]') a = struct_test.new(42) assert_equal("#", a.inspect, '[ruby-core:24849]') @@ -343,6 +384,10 @@ def test_nonascii assert_nothing_raised(Encoding::CompatibilityError) do assert_match(/redefining constant #@Struct::R\u{e9}sum\u{e9}/, e) end + + @Struct.class_eval do + remove_const name + end end def test_junk @@ -444,6 +489,43 @@ def test_deconstruct_keys } end + def test_public_send + klass = @Struct.new(:a) + x = klass.new(1) + assert_equal(1, x.public_send("a")) + assert_equal(42, x.public_send("a=", 42)) + assert_equal(42, x.public_send("a")) + end + + def test_arity + klass = @Struct.new(:a) + assert_equal 0, klass.instance_method(:a).arity + assert_equal 1, klass.instance_method(:a=).arity + + klass.module_eval do + define_method(:b=, instance_method(:a=)) + alias c= a= + end + + assert_equal 1, klass.instance_method(:b=).arity + assert_equal 1, klass.instance_method(:c=).arity + end + + def test_parameters + klass = @Struct.new(:a) + assert_equal [], klass.instance_method(:a).parameters + # NOTE: :_ may not be a spec. + assert_equal [[:req, :_]], klass.instance_method(:a=).parameters + + klass.module_eval do + define_method(:b=, instance_method(:a=)) + alias c= a= + end + + assert_equal [[:req, :_]], klass.instance_method(:b=).parameters + assert_equal [[:req, :_]], klass.instance_method(:c=).parameters + end + class TopStruct < Test::Unit::TestCase include TestStruct diff --git a/ruby/test/ruby/test_super.rb b/ruby/test/ruby/test_super.rb index bbfc58150..6a575b88c 100644 --- a/ruby/test/ruby/test_super.rb +++ b/ruby/test/ruby/test_super.rb @@ -521,6 +521,43 @@ def foo(result) assert_equal(%w[B A], result, bug9721) end + # [Bug #18329] + def test_super_missing_prepended_module + a = Module.new do + def probe(*methods) + prepend(probing_module(methods)) + end + + def probing_module(methods) + Module.new do + methods.each do |method| + define_method(method) do |*args, **kwargs, &block| + super(*args, **kwargs, &block) + end + end + end + end + end + + b = Class.new do + extend a + + probe :danger!, :missing + + def danger!; end + end + + o = b.new + o.danger! + begin + original_gc_stress = GC.stress + GC.stress = true + 2.times { o.missing rescue NoMethodError } + ensure + GC.stress = original_gc_stress + end + end + def test_from_eval bug10263 = '[ruby-core:65122] [Bug #10263a]' a = Class.new do @@ -583,4 +620,81 @@ def foo *args def test_super_with_modified_rest_parameter assert_equal [13], TestFor_super_with_modified_rest_parameter.new.foo end + + def test_super_with_define_method + superklass1 = Class.new do + def foo; :foo; end + def bar; :bar; end + def boo; :boo; end + end + superklass2 = Class.new(superklass1) do + alias baz boo + def boo; :boo2; end + end + subklass = Class.new(superklass2) + [:foo, :bar, :baz, :boo].each do |sym| + subklass.define_method(sym){ super() } + end + assert_equal :foo, subklass.new.foo + assert_equal :bar, subklass.new.bar + assert_equal :boo, subklass.new.baz + assert_equal :boo2, subklass.new.boo + end + + def test_super_attr_writer # [Bug #16785] + writer_class = Class.new do + attr_writer :test + end + superwriter_class = Class.new(writer_class) do + def initialize + @test = 1 # index: 1 + end + + def test=(test) + super(test) + end + end + inherited_class = Class.new(superwriter_class) do + def initialize + @a = nil + @test = 2 # index: 2 + end + end + + superwriter = superwriter_class.new + superwriter.test = 3 # set ic->index of superwriter_class#test= to 1 + + inherited = inherited_class.new + inherited.test = 4 # it may set 4 to index=1 while it should be index=2 + + assert_equal 3, superwriter.instance_variable_get(:@test) + assert_equal 4, inherited.instance_variable_get(:@test) + end + + def test_super_attr_reader + reader_class = Class.new do + attr_reader :test + end + superreader_class = Class.new(reader_class) do + def initialize + @test = 1 # index: 1 + end + + def test + super + end + end + inherited_class = Class.new(superreader_class) do + def initialize + @a = nil + @test = 2 # index: 2 + end + end + + superreader = superreader_class.new + assert_equal 1, superreader.test # set ic->index of superreader_class#test to 1 + + inherited = inherited_class.new + assert_equal 2, inherited.test # it may read index=1 while it should be index=2 + end end diff --git a/ruby/test/ruby/test_symbol.rb b/ruby/test/ruby/test_symbol.rb index 660f2e157..f7f17b8d6 100644 --- a/ruby/test/ruby/test_symbol.rb +++ b/ruby/test/ruby/test_symbol.rb @@ -105,6 +105,12 @@ def test_inspect end end + def test_name + assert_equal("foo", :foo.name) + assert_same(:foo.name, :foo.name) + assert_predicate(:foo.name, :frozen?) + end + def test_to_proc assert_equal %w(1 2 3), (1..3).map(&:to_s) [ @@ -153,6 +159,14 @@ def (obj = Object.new).proc(&b) b; end end; end + def test_to_proc_lambda? + assert_predicate(:itself.to_proc, :lambda?) + end + + def test_to_proc_arity + assert_equal(-2, :itself.to_proc.arity) + end + def test_to_proc_call_with_symbol_proc first = 1 bug11594 = "[ruby-core:71088] [Bug #11594] corrupted the first local variable" @@ -165,6 +179,9 @@ class TestToPRocArgWithRefinements; end def _test_to_proc_arg_with_refinements_call(&block) block.call TestToPRocArgWithRefinements.new end + def _test_to_proc_with_refinements_call(&block) + block + end using Module.new { refine TestToPRocArgWithRefinements do def hoge @@ -176,6 +193,14 @@ def test_to_proc_arg_with_refinements assert_equal(:hoge, _test_to_proc_arg_with_refinements_call(&:hoge)) end + def test_to_proc_lambda_with_refinements + assert_predicate(_test_to_proc_with_refinements_call(&:hoge), :lambda?) + end + + def test_to_proc_arity_with_refinements + assert_equal(-2, _test_to_proc_with_refinements_call(&:hoge).arity) + end + def self._test_to_proc_arg_with_refinements_call(&block) block.call TestToPRocArgWithRefinements.new end @@ -219,11 +244,11 @@ def test_to_proc_iseq begin; bug11845 = '[ruby-core:72381] [Bug #11845]' assert_nil(:class.to_proc.source_location, bug11845) - assert_equal([[:rest]], :class.to_proc.parameters, bug11845) + assert_equal([[:req], [:rest]], :class.to_proc.parameters, bug11845) c = Class.new {define_method(:klass, :class.to_proc)} m = c.instance_method(:klass) assert_nil(m.source_location, bug11845) - assert_equal([[:rest]], m.parameters, bug11845) + assert_equal([[:req], [:rest]], m.parameters, bug11845) end; end @@ -504,12 +529,14 @@ class << (obj = Object.new) assert_nothing_raised(NoMethodError, bug10259) {obj.send("unagi=".intern, 1)} end - def test_symbol_fstr_leak + def test_symbol_fstr_memory_leak bug10686 = '[ruby-core:67268] [Bug #10686]' - x = x = 0 - assert_no_memory_leak([], '200_000.times { |i| i.to_s.to_sym }; GC.start', "#{<<-"begin;"}\n#{<<-"end;"}", bug10686, limit: 1.71, rss: true, timeout: 20) + assert_no_memory_leak([], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", bug10686, limit: 1.71, rss: true, timeout: 20) begin; - 200_000.times { |i| (i + 200_000).to_s.to_sym } + n = 100_000 + n.times { |i| i.to_s.to_sym } + else; + (2 * n).times { |i| (i + n).to_s.to_sym } end; end diff --git a/ruby/test/ruby/test_syntax.rb b/ruby/test/ruby/test_syntax.rb index 21b0bc7ce..b71f492f9 100644 --- a/ruby/test/ruby/test_syntax.rb +++ b/ruby/test/ruby/test_syntax.rb @@ -66,6 +66,18 @@ def test_script_lines f&.close! end + def test_anonymous_block_forwarding + assert_syntax_error("def b; c(&); end", /no anonymous block parameter/) + assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}") + begin; + def b(&); c(&) end + def c(&); yield 1 end + a = nil + b{|c| a = c} + assert_equal(1, a) + end; + end + def test_newline_in_block_parameters bug = '[ruby-dev:45292]' ["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params| @@ -93,6 +105,17 @@ def test_do_block_in_cmdarg assert_valid_syntax("tap (proc do end)", __FILE__, bug9726) end + def test_hash_kwsplat_hash + kw = {} + h = {a: 1} + assert_equal({}, {**{}}) + assert_equal({}, {**kw}) + assert_equal(h, {**h}) + assert_equal(false, {**{}}.frozen?) + assert_equal(false, {**kw}.equal?(kw)) + assert_equal(false, {**h}.equal?(h)) + end + def test_array_kwsplat_hash kw = {} h = {a: 1} @@ -182,26 +205,36 @@ def test_keyword_duplicated_splat h = {k3: 31} assert_raise(ArgumentError) {o.kw(**h)} h = {"k1"=>11, k2: 12} - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `kw'/m) do - assert_raise(ArgumentError) {o.kw(**h)} - end + assert_raise(ArgumentError) {o.kw(**h)} end def test_keyword_duplicated bug10315 = '[ruby-core:65625] [Bug #10315]' a = [] def a.add(x) push(x); x; end - def a.f(k:) k; end + b = a.clone + def a.f(k:, **) k; end + def b.f(k:) k; end a.clear r = nil - assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), k: a.add(2))")} + assert_warn(/duplicated/) {r = eval("b.f(k: b.add(1), k: b.add(2))")} assert_equal(2, r) - assert_equal([1, 2], a, bug10315) + assert_equal([1, 2], b, bug10315) + b.clear + r = nil + assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4))")} + assert_equal(4, r) + assert_equal([1, 2, 3, 4], a) a.clear r = nil - assert_warn(/duplicated/) {r = eval("a.f({k: a.add(1), k: a.add(2)})")} + assert_warn(/duplicated/) {r = eval("b.f(**{k: b.add(1), k: b.add(2)})")} assert_equal(2, r) - assert_equal([1, 2], a, bug10315) + assert_equal([1, 2], b, bug10315) + b.clear + r = nil + assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4)})")} + assert_equal(4, r) + assert_equal([1, 2, 3, 4], a) end def test_keyword_empty_splat @@ -610,6 +643,11 @@ def test_do_block_in_lambda def test_do_block_after_lambda bug11380 = '[ruby-core:70067] [Bug #11380]' assert_valid_syntax('p -> { :hello }, a: 1 do end', bug11380) + + assert_valid_syntax('->(opt = (foo.[] bar)) {}') + assert_valid_syntax('->(opt = (foo.[]= bar)) {}') + assert_valid_syntax('->(opt = (foo.[] bar)) do end') + assert_valid_syntax('->(opt = (foo.[]= bar)) do end') end def test_reserved_method_no_args @@ -951,9 +989,14 @@ def test__END___cr def test_warning_for_cr feature8699 = '[ruby-core:56240] [Feature #8699]' - assert_warning(/encountered \\r/, feature8699) do - eval("\r""__id__\r") + s = assert_warning(/encountered \\r/, feature8699) do + eval("'\r'\r") end + assert_equal("\r", s) + s = assert_warning('') do + eval("'\r'\r\n") + end + assert_equal("\r", s) end def test_unexpected_fraction @@ -984,6 +1027,19 @@ def test_range_at_eol assert_warn('') {eval("(1...)")} assert_warn('') {eval("(1...\n2)")} assert_warn('') {eval("{a: 1...\n2}")} + + assert_warn(/\.\.\. at EOL/) do + assert_valid_syntax('foo.[]= ...', verbose: true) + end + assert_warn(/\.\.\. at EOL/) do + assert_valid_syntax('foo.[] ...', verbose: true) + end + assert_warn(/\.\.\. at EOL/) do + assert_syntax_error('foo.[]= bar, ...', /unexpected/, verbose: true) + end + assert_warn(/\.\.\. at EOL/) do + assert_syntax_error('foo.[] bar, ...', /unexpected/, verbose: true) + end end def test_too_big_nth_ref @@ -1029,19 +1085,19 @@ def test_no_warning_logop_literal end def test_warning_literal_in_condition - assert_warn(/literal in condition/) do + assert_warn(/string literal in condition/) do eval('1 if ""') end - assert_warn(/literal in condition/) do + assert_warn(/regex literal in condition/) do eval('1 if //') end assert_warning(/literal in condition/) do eval('1 if 1') end - assert_warning(/literal in condition/) do + assert_warning(/symbol literal in condition/) do eval('1 if :foo') end - assert_warning(/literal in condition/) do + assert_warning(/symbol literal in condition/) do eval('1 if :"#{"foo".upcase}"') end @@ -1374,6 +1430,15 @@ def obj.test assert_nil obj.test end + def test_assignment_return_in_loop + obj = Object.new + def obj.test + x = nil + _y = (return until x unless x) + end + assert_nil obj.test, "[Bug #16695]" + end + def test_method_call_location line = __LINE__+5 e = assert_raise(NoMethodError) do @@ -1400,6 +1465,52 @@ def test_method_call_location assert_equal(line, e.backtrace_locations[0].lineno) end + def test_methoddef_endless + assert_valid_syntax('private def foo = 42') + assert_valid_syntax('private def foo() = 42') + assert_valid_syntax('private def inc(x) = x + 1') + assert_valid_syntax('private def obj.foo = 42') + assert_valid_syntax('private def obj.foo() = 42') + assert_valid_syntax('private def obj.inc(x) = x + 1') + k = Class.new do + class_eval('def rescued(x) = raise("to be caught") rescue "instance #{x}"') + class_eval('def self.rescued(x) = raise("to be caught") rescue "class #{x}"') + end + assert_equal("class ok", k.rescued("ok")) + assert_equal("instance ok", k.new.rescued("ok")) + + error = /setter method cannot be defined in an endless method definition/ + assert_syntax_error('def foo=() = 42', error) + assert_syntax_error('def obj.foo=() = 42', error) + assert_syntax_error('def foo=() = 42 rescue nil', error) + assert_syntax_error('def obj.foo=() = 42 rescue nil', error) + end + + def test_methoddef_endless_command + assert_valid_syntax('def foo = puts "Hello"') + assert_valid_syntax('def foo() = puts "Hello"') + assert_valid_syntax('def foo(x) = puts x') + assert_valid_syntax('def obj.foo = puts "Hello"') + assert_valid_syntax('def obj.foo() = puts "Hello"') + assert_valid_syntax('def obj.foo(x) = puts x') + k = Class.new do + class_eval('def rescued(x) = raise "to be caught" rescue "instance #{x}"') + class_eval('def self.rescued(x) = raise "to be caught" rescue "class #{x}"') + end + assert_equal("class ok", k.rescued("ok")) + assert_equal("instance ok", k.new.rescued("ok")) + + # Current technical limitation: cannot prepend "private" or something for command endless def + error = /syntax error, unexpected string literal/ + error2 = /syntax error, unexpected local variable or method/ + assert_syntax_error('private def foo = puts "Hello"', error) + assert_syntax_error('private def foo() = puts "Hello"', error) + assert_syntax_error('private def foo(x) = puts x', error2) + assert_syntax_error('private def obj.foo = puts "Hello"', error) + assert_syntax_error('private def obj.foo() = puts "Hello"', error) + assert_syntax_error('private def obj.foo(x) = puts x', error2) + end + def test_methoddef_in_cond assert_valid_syntax('while def foo; tap do end; end; break; end') assert_valid_syntax('while def foo a = tap do end; end; break; end') @@ -1437,13 +1548,12 @@ def test_numbered_parameter assert_syntax_error('-> {_1; -> {_2}}', /numbered parameter is already used/) assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/) assert_syntax_error('proc {_1; _1 = nil}', /Can't assign to numbered parameter _1/) - mesg = proc {|n| /`_#{n}' is reserved for numbered parameter/} - assert_warn(mesg[1]) {eval('proc {_1 = nil}')} - assert_warn(mesg[2]) {eval('_2=1')} - assert_warn(mesg[3]) {eval('proc {|_3|}')} - assert_warn(mesg[4]) {instance_eval('def x(_4) end')} - assert_warn(mesg[5]) {instance_eval('def _5; end')} - assert_warn(mesg[6]) {instance_eval('def self._6; end')} + assert_syntax_error('proc {_1 = nil}', /_1 is reserved for numbered parameter/) + assert_syntax_error('_2=1', /_2 is reserved for numbered parameter/) + assert_syntax_error('proc {|_3|}', /_3 is reserved for numbered parameter/) + assert_syntax_error('def x(_4) end', /_4 is reserved for numbered parameter/) + assert_syntax_error('def _5; end', /_5 is reserved for numbered parameter/) + assert_syntax_error('def self._6; end', /_6 is reserved for numbered parameter/) assert_raise_with_message(NameError, /undefined local variable or method `_1'/) { eval('_1') } @@ -1452,7 +1562,13 @@ def test_numbered_parameter assert_valid_syntax("->{_1;#{c};->{_1};end}\n") end - 1.times {_1} + 1.times { + [ + _1, + assert_equal([:a], eval("[:a].map{_1}")), + assert_raise(NameError) {eval("_1")}, + ] + } end def test_value_expr_in_condition @@ -1463,13 +1579,33 @@ def test_value_expr_in_condition assert_valid_syntax("tap {a = (break unless true)}") end + def test_tautological_condition + assert_valid_syntax("def f() return if false and invalid; nil end") + assert_valid_syntax("def f() return unless true or invalid; nil end") + end + def test_argument_forwarding assert_valid_syntax('def foo(...) bar(...) end') assert_valid_syntax('def foo(...) end') + assert_valid_syntax('def foo(a, ...) bar(...) end') + assert_valid_syntax("def foo ...\n bar(...)\nend") + assert_valid_syntax("def foo a, ...\n bar(...)\nend") + assert_valid_syntax("def foo b = 1, ...\n bar(...)\nend") + assert_valid_syntax("def foo ...; bar(...); end") + assert_valid_syntax("def foo a, ...; bar(...); end") + assert_valid_syntax("def foo b = 1, ...; bar(...); end") + assert_valid_syntax("(def foo ...\n bar(...)\nend)") + assert_valid_syntax("(def foo ...; bar(...); end)") + assert_valid_syntax('def ==(...) end') + assert_valid_syntax('def [](...) end') + assert_valid_syntax('def nil(...) end') + assert_valid_syntax('def true(...) end') + assert_valid_syntax('def false(...) end') + unexpected = /unexpected \.{3}/ assert_syntax_error('iter do |...| end', /unexpected/) assert_syntax_error('iter {|...|}', /unexpected/) - assert_syntax_error('->... {}', /unexpected/) - assert_syntax_error('->(...) {}', /unexpected/) + assert_syntax_error('->... {}', unexpected) + assert_syntax_error('->(...) {}', unexpected) assert_syntax_error('def foo(x, y, z) bar(...); end', /unexpected/) assert_syntax_error('def foo(x, y, z) super(...); end', /unexpected/) assert_syntax_error('def foo(...) yield(...); end', /unexpected/) @@ -1489,7 +1625,11 @@ def obj1.bar(*args, **kws, &block) [args, kws] end end + obj4 = obj1.clone + obj5 = obj1.clone obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) + obj4.instance_eval("def foo ...\n bar(...)\n""end", __FILE__, __LINE__) + obj5.instance_eval("def foo ...; bar(...); end", __FILE__, __LINE__) klass = Class.new { def foo(*args, **kws, &block) @@ -1518,25 +1658,177 @@ def obj3.bar(*args, &block) end obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) - [obj1, obj2, obj3].each do |obj| + [obj1, obj2, obj3, obj4, obj5].each do |obj| assert_warning('') { assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x}) } assert_warning('') { assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5)) } - warning = "warning: Using the last argument as keyword parameters is deprecated" - assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) { - assert_equal([[], {}], obj.foo({}) {|*x| x}) + array = obj == obj3 ? [] : [{}] + assert_warning('') { + assert_equal([array, {}], obj.foo({}) {|*x| x}) } - assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) { - assert_equal([[], {}], obj.foo({})) + assert_warning('') { + assert_equal([array, {}], obj.foo({})) } assert_equal(-1, obj.method(:foo).arity) parameters = obj.method(:foo).parameters assert_equal(:rest, parameters.dig(0, 0)) - assert_equal(:block, parameters.dig(1, 0)) + assert_equal(:keyrest, parameters.dig(1, 0)) + assert_equal(:block, parameters.dig(2, 0)) + end + end + + def test_argument_forwarding_with_leading_arguments + obj = Object.new + def obj.bar(*args, **kws, &block) + if block + block.call(args, kws) + else + [args, kws] + end end + obj.instance_eval('def foo(_a, ...) bar(...) end', __FILE__, __LINE__) + assert_equal [[], {}], obj.foo(1) + assert_equal [[2], {}], obj.foo(1, 2) + assert_equal [[2, 3], {}], obj.foo(1, 2, 3) + assert_equal [[], {a: 1}], obj.foo(1, a: 1) + assert_equal [[2], {a: 1}], obj.foo(1, 2, a: 1) + assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1) + assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(...) bar(1, ...) end', __FILE__, __LINE__) + assert_equal [[1], {}], obj.foo + assert_equal [[1, 1], {}], obj.foo(1) + assert_equal [[1, 1, 2], {}], obj.foo(1, 2) + assert_equal [[1, 1, 2, 3], {}], obj.foo(1, 2, 3) + assert_equal [[1], {a: 1}], obj.foo(a: 1) + assert_equal [[1, 1], {a: 1}], obj.foo(1, a: 1) + assert_equal [[1, 1, 2], {a: 1}], obj.foo(1, 2, a: 1) + assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1) + assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(a, ...) bar(a, ...) end', __FILE__, __LINE__) + assert_equal [[4], {}], obj.foo(4) + assert_equal [[4, 2], {}], obj.foo(4, 2) + assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3) + assert_equal [[4], {a: 1}], obj.foo(4, a: 1) + assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(_a, ...) bar(1, ...) end', __FILE__, __LINE__) + assert_equal [[1], {}], obj.foo(4) + assert_equal [[1, 2], {}], obj.foo(4, 2) + assert_equal [[1, 2, 3], {}], obj.foo(4, 2, 3) + assert_equal [[1], {a: 1}], obj.foo(4, a: 1) + assert_equal [[1, 2], {a: 1}], obj.foo(4, 2, a: 1) + assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) + assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(_a, _b, ...) bar(...) end', __FILE__, __LINE__) + assert_equal [[], {}], obj.foo(4, 5) + assert_equal [[2], {}], obj.foo(4, 5, 2) + assert_equal [[2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(_a, _b, ...) bar(1, ...) end', __FILE__, __LINE__) + assert_equal [[1], {}], obj.foo(4, 5) + assert_equal [[1, 2], {}], obj.foo(4, 5, 2) + assert_equal [[1, 2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[1], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[1, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(_a, ...) bar(1, 2, ...) end', __FILE__, __LINE__) + assert_equal [[1, 2], {}], obj.foo(5) + assert_equal [[1, 2, 5], {}], obj.foo(4, 5) + assert_equal [[1, 2, 5, 2], {}], obj.foo(4, 5, 2) + assert_equal [[1, 2, 5, 2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[1, 2, 5], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[1, 2, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(a, b, ...) bar(b, a, ...) end', __FILE__, __LINE__) + assert_equal [[5, 4], {}], obj.foo(4, 5) + assert_equal [[5, 4, 2], {}], obj.foo(4, 5, 2) + assert_equal [[5, 4, 2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[5, 4], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[5, 4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(a, _b, ...) bar(a, ...) end', __FILE__, __LINE__) + assert_equal [[4], {}], obj.foo(4, 5) + assert_equal [[4, 2], {}], obj.foo(4, 5, 2) + assert_equal [[4, 2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[4], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval('def foo(a, ...) bar(a, 1, ...) end', __FILE__, __LINE__) + assert_equal [[4, 1], {}], obj.foo(4) + assert_equal [[4, 1, 5], {}], obj.foo(4, 5) + assert_equal [[4, 1, 5, 2], {}], obj.foo(4, 5, 2) + assert_equal [[4, 1, 5, 2, 3], {}], obj.foo(4, 5, 2, 3) + assert_equal [[4, 1, 5], {a: 1}], obj.foo(4, 5, a: 1) + assert_equal [[4, 1, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) + assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) + assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval("def foo a, ...\n bar(a, ...)\n"" end", __FILE__, __LINE__) + assert_equal [[4], {}], obj.foo(4) + assert_equal [[4, 2], {}], obj.foo(4, 2) + assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3) + assert_equal [[4], {a: 1}], obj.foo(4, a: 1) + assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval("def foo a, ...; bar(a, ...); end", __FILE__, __LINE__) + assert_equal [[4], {}], obj.foo(4) + assert_equal [[4, 2], {}], obj.foo(4, 2) + assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3) + assert_equal [[4], {a: 1}], obj.foo(4, a: 1) + assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} + + exp = eval("-> (a: nil) {a...1}") + assert_equal 0...1, exp.call(a: 0) + end + + def test_cdhash + assert_separately([], <<-RUBY) + n = case 1 when 2r then false else true end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY + assert_separately([], <<-RUBY) + n = case 3/2r when 1.5r then true else false end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY + assert_separately([], <<-RUBY) + n = case 1i when 1i then true else false end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY end private diff --git a/ruby/test/ruby/test_thread.rb b/ruby/test/ruby/test_thread.rb index 30a3cc784..ddfeb8b7a 100644 --- a/ruby/test/ruby/test_thread.rb +++ b/ruby/test/ruby/test_thread.rb @@ -230,9 +230,17 @@ def test_join2 assert_equal(t1, t3.value) ensure - t1&.kill - t2&.kill - t3&.kill + t1&.kill&.join + t2&.kill&.join + t3&.kill&.join + end + + def test_join_argument_conversion + t = Thread.new {} + assert_raise(TypeError) {t.join(:foo)} + + limit = Struct.new(:to_f, :count).new(0.05) + assert_same(t, t.join(limit)) end { 'FIXNUM_MAX' => RbConfig::LIMITS['FIXNUM_MAX'], @@ -309,7 +317,7 @@ def test_wakeup s += 1 end Thread.pass until t.stop? - sleep 1 if RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait + sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait assert_equal(1, s) t.wakeup Thread.pass while t.alive? @@ -490,6 +498,19 @@ def test_report_on_exception end; end + def test_ignore_deadlock + if /mswin|mingw/ =~ RUBY_PLATFORM + skip "can't trap a signal from another process on Windows" + end + assert_in_out_err([], <<-INPUT, %w(false :sig), [], :signal=>:INT, timeout: 1, timeout_error: nil) + p Thread.ignore_deadlock + q = Thread::Queue.new + trap(:INT){q.push :sig} + Thread.ignore_deadlock = true + p q.pop + INPUT + end + def test_status_and_stop_p a = ::Thread.new { Thread.current.report_on_exception = false @@ -617,7 +638,7 @@ def test_select_wait Thread.pass until t.stop? assert_predicate(t, :alive?) ensure - t&.kill + t&.kill&.join end def test_mutex_deadlock @@ -718,8 +739,8 @@ def test_no_valid_cfp def make_handle_interrupt_test_thread1 flag r = [] - ready_q = Queue.new - done_q = Queue.new + ready_q = Thread::Queue.new + done_q = Thread::Queue.new th = Thread.new{ begin Thread.handle_interrupt(RuntimeError => flag){ @@ -796,7 +817,7 @@ def test_handle_interrupt_with_break def test_handle_interrupt_blocking r = nil - q = Queue.new + q = Thread::Queue.new e = Class.new(Exception) th_s = Thread.current th = Thread.start { @@ -820,7 +841,7 @@ def test_handle_interrupt_blocking def test_handle_interrupt_and_io assert_in_out_err([], <<-INPUT, %w(ok), []) th_waiting = true - q = Queue.new + q = Thread::Queue.new t = Thread.new { Thread.current.report_on_exception = false @@ -1106,7 +1127,7 @@ def test_mutex_owned2 Thread.pass until mutex.locked? assert_equal(mutex.owned?, false) ensure - th&.kill + th&.kill&.join end end @@ -1133,7 +1154,9 @@ def invoke_rec script, vm_stack_size, machine_stack_size, use_length = true env = {} env['RUBY_THREAD_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size env['RUBY_THREAD_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size - out, = EnvUtil.invoke_ruby([env, '-e', script], '', true, true) + out, err, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true) + assert_not_predicate(status, :signaled?, err) + use_length ? out.length : out end @@ -1222,7 +1245,7 @@ def test_fork_in_thread end if Process.respond_to?(:fork) def test_fork_while_locked - m = Mutex.new + m = Thread::Mutex.new thrs = [] 3.times do |i| thrs << Thread.new { m.synchronize { Process.waitpid2(fork{})[1] } } @@ -1255,7 +1278,7 @@ def test_fork_while_parent_locked def test_fork_while_mutex_locked_by_forker skip 'needs fork' unless Process.respond_to?(:fork) - m = Mutex.new + m = Thread::Mutex.new m.synchronize do pid = fork do exit!(2) unless m.locked? @@ -1321,11 +1344,32 @@ def test_thread_setname_in_initialize assert_equal("foo", c.new {Thread.current.name}.value, bug12290) end + def test_thread_native_thread_id + skip "don't support native_thread_id" unless Thread.method_defined?(:native_thread_id) + assert_instance_of Integer, Thread.main.native_thread_id + + th1 = Thread.start{sleep} + + # newly created thread which doesn't run yet returns nil or integer + assert_include [NilClass, Integer], th1.native_thread_id.class + + Thread.pass until th1.stop? + + # After a thread starts (and execute `sleep`), it returns native_thread_id + assert_instance_of Integer, th1.native_thread_id + + th1.wakeup + Thread.pass while th1.alive? + + # dead thread returns nil + assert_nil th1.native_thread_id + end + def test_thread_interrupt_for_killed_thread opts = { timeout: 5, timeout_error: nil } # prevent SIGABRT from slow shutdown with MJIT - opts[:reprieve] = 3 if RubyVM::MJIT.enabled? + opts[:reprieve] = 3 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? assert_normal_exit(<<-_end, '[Bug #8996]', **opts) Thread.report_on_exception = false diff --git a/ruby/test/ruby/test_thread_cv.rb b/ruby/test/ruby/test_thread_cv.rb index 38bcc3b8f..88733419d 100644 --- a/ruby/test/ruby/test_thread_cv.rb +++ b/ruby/test/ruby/test_thread_cv.rb @@ -13,9 +13,10 @@ def test_initialized end def test_condvar_signal_and_wait - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new result = [] + woken = nil mutex.synchronize do t = Thread.new do mutex.synchronize do @@ -25,18 +26,19 @@ def test_condvar_signal_and_wait end result << 0 - condvar.wait(mutex) + woken = condvar.wait(mutex) result << 2 t.join end assert_equal([0, 1, 2], result) + assert(woken) end def test_condvar_wait_exception_handling # Calling wait in the only thread running should raise a ThreadError of # 'stopping only thread' - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new locked = false thread = Thread.new do @@ -61,8 +63,8 @@ def test_condvar_wait_exception_handling def test_condvar_wait_and_broadcast nr_threads = 3 threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new result = [] nr_threads.times do |i| @@ -87,12 +89,15 @@ def test_condvar_wait_and_broadcast end assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result + ensure + threads.each(&:kill) + threads.each(&:join) end def test_condvar_wait_deadlock assert_in_out_err([], <<-INPUT, /\Afatal\nNo live threads left\. Deadlock/, []) - mutex = Mutex.new - cv = ConditionVariable.new + mutex = Thread::Mutex.new + cv = Thread::ConditionVariable.new klass = nil mesg = nil @@ -112,8 +117,8 @@ def test_condvar_wait_deadlock def test_condvar_wait_deadlock_2 nr_threads = 3 threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new nr_threads.times do |i| if (i != 0) @@ -136,15 +141,16 @@ def test_condvar_wait_deadlock_2 end def test_condvar_timed_wait - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new timeout = 0.3 locked = false + woken = true t0 = Time.now mutex.synchronize do begin - condvar.wait(mutex, timeout) + woken = condvar.wait(mutex, timeout) ensure locked = mutex.locked? end @@ -154,18 +160,19 @@ def test_condvar_timed_wait assert_operator(timeout*0.9, :<, t) assert(locked) + assert_nil(woken) end def test_condvar_nolock - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new assert_raise(ThreadError) {condvar.wait(mutex)} end def test_condvar_nolock_2 - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new Thread.new do assert_raise(ThreadError) {condvar.wait(mutex)} @@ -173,8 +180,8 @@ def test_condvar_nolock_2 end def test_condvar_nolock_3 - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new Thread.new do assert_raise(ThreadError) {condvar.wait(mutex, 0.1)} @@ -182,22 +189,22 @@ def test_condvar_nolock_3 end def test_condvar_empty_signal - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new assert_nothing_raised(Exception) { mutex.synchronize {condvar.signal} } end def test_condvar_empty_broadcast - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new assert_nothing_raised(Exception) { mutex.synchronize {condvar.broadcast} } end def test_dup bug9440 = '[ruby-core:59961] [Bug #9440]' - condvar = ConditionVariable.new + condvar = Thread::ConditionVariable.new assert_raise(NoMethodError, bug9440) do condvar.dup end @@ -207,7 +214,7 @@ def test_dup def test_dump bug9674 = '[ruby-core:61677] [Bug #9674]' - condvar = ConditionVariable.new + condvar = Thread::ConditionVariable.new assert_raise_with_message(TypeError, /#{ConditionVariable}/, bug9674) do Marshal.dump(condvar) end @@ -219,8 +226,8 @@ def test_dump end def test_condvar_fork - mutex = Mutex.new - condvar = ConditionVariable.new + mutex = Thread::Mutex.new + condvar = Thread::ConditionVariable.new thrs = (1..10).map do Thread.new { mutex.synchronize { condvar.wait(mutex) } } end diff --git a/ruby/test/ruby/test_thread_queue.rb b/ruby/test/ruby/test_thread_queue.rb index 41e6865ed..3fa0eae2c 100644 --- a/ruby/test/ruby/test_thread_queue.rb +++ b/ruby/test/ruby/test_thread_queue.rb @@ -54,15 +54,37 @@ def grind(num_threads, num_objects, num_iterations, klass, *args) assert_equal 0, to_workers.size end + def test_queue_initialize + e = Class.new do + include Enumerable + def initialize(list) @list = list end + def each(&block) @list.each(&block) end + end + + all_assertions_foreach(nil, + [Array, "Array"], + [e, "Enumerable"], + [Struct.new(:to_a), "Array-like"], + ) do |a, type| + q = Thread::Queue.new(a.new([1,2,3])) + assert_equal(3, q.size, type) + assert_not_predicate(q, :empty?, type) + assert_equal(1, q.pop, type) + assert_equal(2, q.pop, type) + assert_equal(3, q.pop, type) + assert_predicate(q, :empty?, type) + end + end + def test_sized_queue_initialize - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) assert_equal 1, q.max - assert_raise(ArgumentError) { SizedQueue.new(0) } - assert_raise(ArgumentError) { SizedQueue.new(-1) } + assert_raise(ArgumentError) { Thread::SizedQueue.new(0) } + assert_raise(ArgumentError) { Thread::SizedQueue.new(-1) } end def test_sized_queue_assign_max - q = SizedQueue.new(2) + q = Thread::SizedQueue.new(2) assert_equal(2, q.max) q.max = 1 assert_equal(1, q.max) @@ -82,7 +104,7 @@ def test_sized_queue_assign_max end def test_queue_pop_interrupt - q = Queue.new + q = Thread::Queue.new t1 = Thread.new { q.pop } sleep 0.01 until t1.stop? t1.kill.join @@ -90,14 +112,14 @@ def test_queue_pop_interrupt end def test_queue_pop_non_block - q = Queue.new + q = Thread::Queue.new assert_raise_with_message(ThreadError, /empty/) do q.pop(true) end end def test_sized_queue_pop_interrupt - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) t1 = Thread.new { q.pop } sleep 0.01 until t1.stop? t1.kill.join @@ -105,14 +127,14 @@ def test_sized_queue_pop_interrupt end def test_sized_queue_pop_non_block - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) assert_raise_with_message(ThreadError, /empty/) do q.pop(true) end end def test_sized_queue_push_interrupt - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) q.push(1) assert_raise_with_message(ThreadError, /full/) do q.push(2, true) @@ -120,7 +142,7 @@ def test_sized_queue_push_interrupt end def test_sized_queue_push_non_block - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) q.push(1) t1 = Thread.new { q.push(2) } sleep 0.01 until t1.stop? @@ -131,13 +153,13 @@ def test_sized_queue_push_non_block def test_thr_kill bug5343 = '[ruby-core:39634]' Dir.mktmpdir {|d| - timeout = 60 + timeout = EnvUtil.apply_timeout_scale(60) total_count = 250 begin assert_normal_exit(<<-"_eom", bug5343, **{:timeout => timeout, :chdir=>d}) #{total_count}.times do |i| open("test_thr_kill_count", "w") {|f| f.puts i } - queue = Queue.new + queue = Thread::Queue.new r, w = IO.pipe th = Thread.start { queue.push(nil) @@ -156,20 +178,20 @@ def test_thr_kill end def test_queue_push_return_value - q = Queue.new + q = Thread::Queue.new retval = q.push(1) assert_same q, retval end def test_queue_clear_return_value - q = Queue.new + q = Thread::Queue.new retval = q.clear assert_same q, retval end def test_sized_queue_clear - # Fill queue, then test that SizedQueue#clear wakes up all waiting threads - sq = SizedQueue.new(2) + # Fill queue, then test that Thread::SizedQueue#clear wakes up all waiting threads + sq = Thread::SizedQueue.new(2) 2.times { sq << 1 } t1 = Thread.new do @@ -190,19 +212,19 @@ def test_sized_queue_clear end def test_sized_queue_push_return_value - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) retval = q.push(1) assert_same q, retval end def test_sized_queue_clear_return_value - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) retval = q.clear assert_same q, retval end def test_sized_queue_throttle - q = SizedQueue.new(1) + q = Thread::SizedQueue.new(1) i = 0 consumer = Thread.new do while q.pop @@ -225,7 +247,7 @@ def test_sized_queue_throttle end def test_queue_thread_raise - q = Queue.new + q = Thread::Queue.new th1 = Thread.new do begin q.pop @@ -255,7 +277,7 @@ def test_queue_thread_raise def test_dup bug9440 = '[ruby-core:59961] [Bug #9440]' - q = Queue.new + q = Thread::Queue.new assert_raise(NoMethodError, bug9440) do q.dup end @@ -265,12 +287,12 @@ def test_dup def test_dump bug9674 = '[ruby-core:61677] [Bug #9674]' - q = Queue.new + q = Thread::Queue.new assert_raise_with_message(TypeError, /#{Queue}/, bug9674) do Marshal.dump(q) end - sq = SizedQueue.new(1) + sq = Thread::SizedQueue.new(1) assert_raise_with_message(TypeError, /#{SizedQueue}/, bug9674) do Marshal.dump(sq) end @@ -282,7 +304,7 @@ def test_dump end def test_close - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| + [->{Thread::Queue.new}, ->{Thread::SizedQueue.new 3}].each do |qcreate| q = qcreate.call assert_equal false, q.closed? q << :something @@ -321,15 +343,15 @@ def close_wakeup( num_items, num_threads, &qcreate ) end def test_queue_close_wakeup - close_wakeup(15, 18){Queue.new} + close_wakeup(15, 18){Thread::Queue.new} end def test_size_queue_close_wakeup - close_wakeup(5, 8){SizedQueue.new 9} + close_wakeup(5, 8){Thread::SizedQueue.new 9} end def test_sized_queue_one_closed_interrupt - q = SizedQueue.new 1 + q = Thread::SizedQueue.new 1 q << :one t1 = Thread.new { Thread.current.report_on_exception = false @@ -346,7 +368,7 @@ def test_sized_queue_one_closed_interrupt # make sure that shutdown state is handled properly by empty? for the non-blocking case def test_empty_non_blocking - q = SizedQueue.new 3 + q = Thread::SizedQueue.new 3 3.times{|i| q << i} # these all block cos the queue is full @@ -372,13 +394,13 @@ def test_empty_non_blocking end def test_sized_queue_closed_push_non_blocking - q = SizedQueue.new 7 + q = Thread::SizedQueue.new 7 q.close assert_raise_with_message(ClosedQueueError, /queue closed/){q.push(non_block=true)} end def test_blocked_pushers - q = SizedQueue.new 3 + q = Thread::SizedQueue.new 3 prod_threads = 6.times.map do |i| thr = Thread.new{ Thread.current.report_on_exception = false @@ -424,9 +446,9 @@ def test_blocked_pushers end def test_deny_pushers - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| + [->{Thread::Queue.new}, ->{Thread::SizedQueue.new 3}].each do |qcreate| q = qcreate[] - synq = Queue.new + synq = Thread::Queue.new prod_threads = 20.times.map do |i| Thread.new { synq.pop @@ -444,7 +466,7 @@ def test_deny_pushers # size should account for waiting pushers during shutdown def sized_queue_size_close - q = SizedQueue.new 4 + q = Thread::SizedQueue.new 4 4.times{|i| q << i} Thread.new{ q << 5 } Thread.new{ q << 6 } @@ -456,7 +478,7 @@ def sized_queue_size_close end def test_blocked_pushers_empty - q = SizedQueue.new 3 + q = Thread::SizedQueue.new 3 prod_threads = 6.times.map do |i| Thread.new{ Thread.current.report_on_exception = false @@ -488,14 +510,14 @@ def test_blocked_pushers_empty # test thread wakeup on one-element SizedQueue with close def test_one_element_sized_queue - q = SizedQueue.new 1 + q = Thread::SizedQueue.new 1 t = Thread.new{ q.pop } q.close assert_nil t.value end def test_close_twice - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| + [->{Thread::Queue.new}, ->{Thread::SizedQueue.new 3}].each do |qcreate| q = qcreate[] q.close assert_nothing_raised(ClosedQueueError){q.close} @@ -503,7 +525,7 @@ def test_close_twice end def test_queue_close_multi_multi - q = SizedQueue.new rand(800..1200) + q = Thread::SizedQueue.new rand(800..1200) count_items = rand(3000..5000) count_producers = rand(10..20) @@ -565,13 +587,14 @@ def test_queue_with_trap end assert_in_out_err([], <<-INPUT, %w(INT INT exit), []) - q = Queue.new + q = Thread::Queue.new trap(:INT){ q.push 'INT' } Thread.new{ loop{ Process.kill :INT, $$ + sleep 0.1 } } puts q.pop @@ -581,8 +604,8 @@ def test_queue_with_trap end def test_fork_while_queue_waiting - q = Queue.new - sq = SizedQueue.new(1) + q = Thread::Queue.new + sq = Thread::SizedQueue.new(1) thq = Thread.new { q.pop } thsq = Thread.new { sq.pop } Thread.pass until thq.stop? && thsq.stop? diff --git a/ruby/test/ruby/test_time.rb b/ruby/test/ruby/test_time.rb index 35e3172fb..2fdf0c201 100644 --- a/ruby/test/ruby/test_time.rb +++ b/ruby/test/ruby/test_time.rb @@ -7,7 +7,6 @@ class TestTime < Test::Unit::TestCase def setup @verbose = $VERBOSE - $VERBOSE = nil end def teardown @@ -38,8 +37,11 @@ def get_t2000 end def test_new + assert_equal(Time.new(2000,1,1,0,0,0), Time.new(2000)) + assert_equal(Time.new(2000,2,1,0,0,0), Time.new("2000", "Feb")) assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, 3600*11)) assert_equal(Time.utc(2000,2,10), Time.new(2000,2,9, 13,0,0, -3600*11)) + assert_equal(Time.utc(2000,2,29,23,0,0), Time.new(2000, 3, 1, 0, 0, 0, 3600)) assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, "+11:00")) assert_equal(Rational(1,2), Time.new(2000,2,10, 11,0,5.5, "+11:00").subsec) bug4090 = '[ruby-dev:42631]' @@ -47,6 +49,10 @@ def test_new t = Time.new(*tm, "-12:00") assert_equal([2001,2,28,23,59,30,-43200], [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.gmt_offset], bug4090) assert_raise(ArgumentError) { Time.new(2000,1,1, 0,0,0, "+01:60") } + msg = /invalid value for Integer/ + assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, 1, "+09:99") } + assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, "+09:99") } + assert_raise_with_message(ArgumentError, msg) { Time.new(2021, "+09:99") } end def test_time_add() @@ -108,6 +114,10 @@ def test_timegm assert_equal(78796800, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec) assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec) assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec) + + # Giveup to try 2nd test because some state is changed. + skip if Test::Unit::Runner.current_repeat_count > 0 + assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec) assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec) else @@ -236,6 +246,10 @@ def test_at2 assert_equal(1, Time.at(0, 0.001).nsec) end + def test_at_splat + assert_equal(Time.at(1, 2), Time.at(*[1, 2])) + end + def test_at_with_unit assert_equal(123456789, Time.at(0, 123456789, :nanosecond).nsec) assert_equal(123456789, Time.at(0, 123456789, :nsec).nsec) @@ -375,6 +389,11 @@ def test_marshal_broken_zone end end + def test_marshal_broken_month + data = "\x04\x08u:\tTime\r\x20\x7c\x1e\xc0\x00\x00\x00\x00" + assert_equal(Time.utc(2022, 4, 1), Marshal.load(data)) + end + def test_marshal_distant_past assert_marshal_roundtrip(Time.utc(1890, 1, 1)) assert_marshal_roundtrip(Time.utc(-4.5e9, 1, 1)) @@ -417,8 +436,10 @@ def test_utc_or_local def o.to_int; 0; end def o.to_r; nil; end assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } + class << o; remove_method(:to_r); end def o.to_r; ""; end assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } + class << o; remove_method(:to_r); end def o.to_r; Rational(11); end assert_equal(11, Time.gm(2000, 1, 1, 0, 0, o).sec) o = Object.new @@ -431,6 +452,10 @@ def o.to_int; 10; end assert_equal(-4427700000, Time.utc(-4427700000,12,1).year) assert_equal(-2**30+10, Time.utc(-2**30+10,1,1).year) + + assert_raise(ArgumentError) { Time.gm(2000, 1, -1) } + assert_raise(ArgumentError) { Time.gm(2000, 1, 2**30 + 1) } + assert_raise(ArgumentError) { Time.gm(2000, 1, -2**30 + 1) } end def test_time_interval @@ -575,6 +600,10 @@ def test_inspect t2000 = get_t2000.localtime(9*3600) + 1/10r assert_equal("2000-01-01 09:00:00.1 +0900", t2000.inspect) + + t2000 = get_t2000 + assert_equal("2000-01-01 09:12:00 +0912", t2000.localtime(9*3600+12*60).inspect) + assert_equal("2000-01-01 09:12:34 +091234", t2000.localtime(9*3600+12*60+34).inspect) end def assert_zone_encoding(time) @@ -596,13 +625,12 @@ def test_zone assert_nil(t.getlocal("+02:00").zone) end - def test_plus_minus_succ + def test_plus_minus t2000 = get_t2000 # assert_raise(RangeError) { t2000 + 10000000000 } # assert_raise(RangeError) t2000 - 3094168449 } # assert_raise(RangeError) { t2000 + 1200798848 } assert_raise(TypeError) { t2000 + Time.now } - assert_equal(t2000 + 1, t2000.succ) end def test_plus_type @@ -705,7 +733,9 @@ def test_strftime assert_equal("12:00:00 AM", t2000.strftime("%r")) assert_equal("Sat 2000-01-01T00:00:00", t2000.strftime("%3a %FT%T")) - assert_equal("", t2000.strftime("")) + assert_warning(/strftime called with empty format string/) do + assert_equal("", t2000.strftime("")) + end assert_equal("foo\0bar\x0000\x0000\x0000", t2000.strftime("foo\0bar\0%H\0%M\0%S")) assert_equal("foo" * 1000, t2000.strftime("foo" * 1000)) @@ -885,6 +915,13 @@ def test_strftime_too_wide assert_equal(8192, Time.now.strftime('%8192z').size) end + def test_strftime_wide_precision + t2000 = get_t2000 + s = t2000.strftime("%28c") + assert_equal(28, s.size) + assert_equal(t2000.strftime("%c"), s.strip) + end + def test_strfimte_zoneoffset t2000 = get_t2000 t = t2000.getlocal("+09:00:00") @@ -898,6 +935,17 @@ def test_strfimte_zoneoffset assert_equal("+09:00", t.strftime("%:z")) assert_equal("+09:00:01", t.strftime("%::z")) assert_equal("+09:00:01", t.strftime("%:::z")) + + assert_equal("+0000", t2000.strftime("%z")) + assert_equal("-0000", t2000.strftime("%-z")) + assert_equal("-00:00", t2000.strftime("%-:z")) + assert_equal("-00:00:00", t2000.strftime("%-::z")) + + t = t2000.getlocal("+00:00") + assert_equal("+0000", t.strftime("%z")) + assert_equal("+0000", t.strftime("%-z")) + assert_equal("+00:00", t.strftime("%-:z")) + assert_equal("+00:00:00", t.strftime("%-::z")) end def test_strftime_padding @@ -1054,6 +1102,11 @@ def test_ceil t2 = (t+0.123456789).ceil(4) assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) assert_equal(Rational(1235,10000), t2.subsec) + + time = Time.utc(2016, 4, 23, 0, 0, 0.123456789r) + assert_equal(time, time.ceil(9)) + assert_equal(time, time.ceil(10)) + assert_equal(time, time.ceil(11)) end def test_getlocal_dont_share_eigenclass @@ -1129,6 +1182,9 @@ def test_1970 end def test_2038 + # Giveup to try 2nd test because some state is changed. + skip if Test::Unit::Runner.current_repeat_count > 0 + if no_leap_seconds? assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec) end @@ -1187,6 +1243,30 @@ def test_future } end + def test_getlocal_utc + t = Time.gm(2000) + assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("UTC")).to_a[0, 6] + assert_predicate t1, :utc? + assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("-0000")).to_a[0, 6] + assert_predicate t1, :utc? + assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("+0000")).to_a[0, 6] + assert_not_predicate t1, :utc? + end + + def test_getlocal_utc_offset + t = Time.gm(2000) + assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-02:30").to_a[0, 6] + assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+09:00").to_a[0, 6] + assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-02:30:40").to_a[0, 6] + assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+09:10:35").to_a[0, 6] + assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-0230").to_a[0, 6] + assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+0900").to_a[0, 6] + assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-023040").to_a[0, 6] + assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+091035").to_a[0, 6] + assert_raise(ArgumentError) {t.getlocal("-02:3040")} + assert_raise(ArgumentError) {t.getlocal("+0910:35")} + end + def test_getlocal_nil now = Time.now now2 = nil @@ -1216,22 +1296,6 @@ def test_strftime_yearday_on_last_day_of_year assert_equal("366", t.strftime("%j")) end - def test_strftime_no_hidden_garbage - skip unless Thread.list.size == 1 - - fmt = %w(Y m d).map { |x| "%#{x}" }.join('-') # defeats optimization - t = Time.at(0).getutc - ObjectSpace.count_objects(res = {}) # creates strings on first call - GC.disable - before = ObjectSpace.count_objects(res)[:T_STRING] - val = t.strftime(fmt) - after = ObjectSpace.count_objects(res)[:T_STRING] - assert_equal before + 1, after, 'only new string is the created one' - assert_equal '1970-01-01', val - ensure - GC.enable - end - def test_num_exact_error bad = EnvUtil.labeled_class("BadValue").new x = EnvUtil.labeled_class("Inexact") do @@ -1245,6 +1309,7 @@ def to_s; "Inexact"; end def test_memsize # Time objects are common in some code, try to keep them small skip "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM + skip "GC is in debug" if GC::INTERNAL_CONSTANTS[:DEBUG] require 'objspace' t = Time.at(0) size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] diff --git a/ruby/test/ruby/test_time_tz.rb b/ruby/test/ruby/test_time_tz.rb index 83482eac6..fdc9e114b 100644 --- a/ruby/test/ruby/test_time_tz.rb +++ b/ruby/test/ruby/test_time_tz.rb @@ -219,7 +219,6 @@ def test_pacific_kiritimati def test_right_utc with_tz(tz="right/UTC") { - ::Bug::Time.reset_leap_second_info assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59]) assert_time_constructor(tz, "2008-12-31 23:59:60 UTC", :utc, [2008,12,31,23,59,60]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0]) @@ -229,25 +228,23 @@ def test_right_utc def test_right_utc_switching with_tz("UTC") { # ensure no leap second timezone - ::Bug::Time.reset_leap_second_info assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) with_tz(tz="right/UTC") { assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,23,59,60]) + assert_time_constructor(tz, "2008-12-31 23:59:60 UTC", :utc, [2008,12,31,23,59,60]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0]) - assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) + assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) } } with_tz("right/UTC") { - ::Bug::Time.reset_leap_second_info assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) with_tz(tz="UTC") { assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,23,59,60]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0]) assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0]) - assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) + assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) } } end if has_right_tz @@ -264,6 +261,8 @@ def test_utc_names assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "UTC"), :utc?) assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "utc"), :utc?) assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "Z"), :utc?) + assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "-00:00"), :utc?) + assert_not_predicate(Time.new(2019, 1, 1, 0, 0, 0, "+00:00"), :utc?) end def test_military_names @@ -376,7 +375,6 @@ def self.gen_zdump_test(data) mesg = "#{mesg_utc}.localtime" define_method(gen_test_name(tz)) { with_tz(tz) { - ::Bug::Time.reset_leap_second_info t = nil assert_nothing_raised(mesg) { t = Time.utc(*u) } assert_equal(expected_utc, time_to_s(t), mesg_utc) @@ -608,6 +606,10 @@ def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset) assert_equal([2018, 9, 1, 12, 0, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) h, m = (-utc_offset / 60).divmod(60) assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i) + assert_equal(6, t.wday) + assert_equal(244, t.yday) + assert_equal(t, time_class.new(2018, 9, 1, 12, in: tzarg)) + assert_raise(ArgumentError) {time_class.new(2018, 9, 1, 12, 0, 0, tzarg, in: tzarg)} end def subtest_now(time_class, tz, tzarg, tzname, abbr, utc_offset) @@ -634,6 +636,7 @@ def subtest_strftime(time_class, tz, tzarg, tzname, abbr, utc_offset) h, m = (utc_offset.abs / 60).divmod(60) h = -h if utc_offset < 0 assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z")) + assert_equal("34 35 35", t.strftime("%U %V %W")) end def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset) @@ -662,6 +665,12 @@ def subtest_at(time_class, tz, tzarg, tzname, abbr, utc_offset) assert_equal(utc, t.to_i) end + def subtest_to_a(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) + ary = t.to_a + assert_equal(ary, [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst, t.zone]) + end + def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset) t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) t2 = Marshal.load(Marshal.dump(t)) @@ -747,6 +756,16 @@ def self.find_timezone(tzname) def self.make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil) TestTimeTZ::TZ.new(tzname, abbr, utc_offset, abbr2, utc_offset2) end + + def test_fractional_second + x = Object.new + def x.local_to_utc(t); t + 8*3600; end + def x.utc_to_local(t); t - 8*3600; end + + t1 = Time.new(2020,11,11,12,13,14.124r, '-08:00') + t2 = Time.new(2020,11,11,12,13,14.124r, x) + assert_equal(t1, t2) + end end begin diff --git a/ruby/test/ruby/test_transcode.rb b/ruby/test/ruby/test_transcode.rb index 1f4c623ac..c8b0034e0 100644 --- a/ruby/test/ruby/test_transcode.rb +++ b/ruby/test/ruby/test_transcode.rb @@ -126,6 +126,28 @@ def test_twostep assert_equal("D\xFCrst".force_encoding('iso-8859-2'), "D\xFCrst".encode('iso-8859-2', 'iso-8859-1')) end + def test_encode_xml_multibyte + encodings = %w'UTF-8 UTF-16LE UTF-16BE UTF-32LE UTF-32BE' + encodings.each do |src_enc| + encodings.each do |dst_enc| + escaped = "<>".encode(src_enc).encode(dst_enc, :xml=>:text) + assert_equal("<>", escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :text") + + escaped = '<">'.encode(src_enc).encode(dst_enc, :xml=>:attr) + assert_equal('"<">"', escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :attr") + + escaped = "<>".encode(src_enc).force_encoding("UTF-8").encode(dst_enc, src_enc, :xml=>:text) + assert_equal("<>", escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :text") + + escaped = '<">'.encode(src_enc).force_encoding("UTF-8").encode(dst_enc, src_enc, :xml=>:attr) + assert_equal('"<">"', escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :attr") + end + end + # regression test; U+6E7F (湿) uses the same bytes in ISO-2022-JP as "<>" + assert_equal( "<>\u6E7F", "<>\u6E7F".encode("ISO-2022-JP").encode("ISO-2022-JP", :xml=>:text).encode("UTF-8")) + assert_equal("\"<>\u6E7F\"", "<>\u6E7F".encode("ISO-2022-JP").encode("ISO-2022-JP", :xml=>:attr).encode("UTF-8")) + end + def test_ascii_range encodings = [ 'US-ASCII', 'ASCII-8BIT', @@ -469,6 +491,25 @@ def test_IBM437 check_both_ways("\u00A0", "\xFF", 'IBM437') # non-breaking space end + def test_IBM720 + assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM720') } + assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'IBM720') } + assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'IBM720') } + check_both_ways("\u0627", "\x9F", 'IBM720') # ا + check_both_ways("\u0628", "\xA0", 'IBM720') # ب + check_both_ways("\u00BB", "\xAF", 'IBM720') # » + check_both_ways("\u2591", "\xB0", 'IBM720') # â–‘ + check_both_ways("\u2510", "\xBF", 'IBM720') # â” + check_both_ways("\u2514", "\xC0", 'IBM720') # â”” + check_both_ways("\u2567", "\xCF", 'IBM720') # â•§ + check_both_ways("\u2568", "\xD0", 'IBM720') # ╨ + check_both_ways("\u2580", "\xDF", 'IBM720') # â–€ + check_both_ways("\u0636", "\xE0", 'IBM720') # ض + check_both_ways("\u064A", "\xEF", 'IBM720') # ÙŠ + check_both_ways("\u2261", "\xF0", 'IBM720') # ≡ + check_both_ways("\u00A0", "\xFF", 'IBM720') # non-breaking space + end + def test_IBM775 check_both_ways("\u0106", "\x80", 'IBM775') # Ć check_both_ways("\u00C5", "\x8F", 'IBM775') # Ã… @@ -2250,12 +2291,19 @@ def test_scrub_encode_with_coderange "#{bug} coderange should not have side effects") end - def test_universal_newline + def test_newline_options bug11324 = '[ruby-core:69841] [Bug #11324]' usascii = Encoding::US_ASCII s = "A\nB\r\nC".force_encoding(usascii) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true), bug11324) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace), bug11324) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace, replace: ''), bug11324) + assert_equal("A\nB\nC", s.encode(usascii, newline: :universal)) + assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace)) + assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace, replace: '')) + assert_equal("A\rB\r\rC", s.encode(usascii, cr_newline: true)) + assert_equal("A\rB\r\rC", s.encode(usascii, newline: :cr)) + assert_equal("A\r\nB\r\r\nC", s.encode(usascii, crlf_newline: true)) + assert_equal("A\r\nB\r\r\nC", s.encode(usascii, newline: :crlf)) end end diff --git a/ruby/test/ruby/test_undef.rb b/ruby/test/ruby/test_undef.rb index e0add7c3a..074b92be5 100644 --- a/ruby/test/ruby/test_undef.rb +++ b/ruby/test/ruby/test_undef.rb @@ -35,4 +35,20 @@ def test_special_const_undef end end end + + def test_singleton_undef + klass = Class.new do + def foo + :ok + end + end + + klass.new.foo + + klass.new.instance_eval do + undef foo + end + + klass.new.foo + end end diff --git a/ruby/test/ruby/test_variable.rb b/ruby/test/ruby/test_variable.rb index b053e1160..f8a7c68fd 100644 --- a/ruby/test/ruby/test_variable.rb +++ b/ruby/test/ruby/test_variable.rb @@ -29,12 +29,20 @@ class Titans < Gods @@rule = "Cronus" # modifies @@rule in Gods include Olympians def ruler4 - EnvUtil.suppress_warning { - @@rule - } + @@rule end end + def test_setting_class_variable_on_module_through_inheritance + mod = Module.new + mod.class_variable_set(:@@foo, 1) + mod.freeze + c = Class.new { include(mod) } + assert_raise(FrozenError) { c.class_variable_set(:@@foo, 2) } + assert_raise(FrozenError) { c.class_eval("@@foo = 2") } + assert_equal(1, c.class_variable_get(:@@foo)) + end + def test_singleton_class_included_class_variable c = Class.new c.extend(Olympians) @@ -63,6 +71,67 @@ def test_singleton_class_included_class_variable assert_equal(1, o.singleton_class.class_variable_get(:@@foo)) end + def test_cvar_overtaken_by_parent_class + error = eval <<~EORB + class Parent + end + + class Child < Parent + @@cvar = 1 + + def self.cvar + @@cvar + end + end + + assert_equal 1, Child.cvar + + class Parent + @@cvar = 2 + end + + assert_raise RuntimeError do + Child.cvar + end + EORB + + assert_equal "class variable @@cvar of TestVariable::Child is overtaken by TestVariable::Parent", error.message + ensure + TestVariable.send(:remove_const, :Child) rescue nil + TestVariable.send(:remove_const, :Parent) rescue nil + end + + def test_cvar_overtaken_by_module + error = eval <<~EORB + class ParentForModule + @@cvar = 1 + + def self.cvar + @@cvar + end + end + + assert_equal 1, ParentForModule.cvar + + module Mixin + @@cvar = 2 + end + + class ParentForModule + include Mixin + end + + assert_raise RuntimeError do + ParentForModule.cvar + end + EORB + + assert_equal "class variable @@cvar of TestVariable::ParentForModule is overtaken by TestVariable::Mixin", error.message + ensure + TestVariable.send(:remove_const, :Mixin) rescue nil + TestVariable.send(:remove_const, :ParentForModule) rescue nil + end + class IncludeRefinedModuleClassVariableNoWarning module Mod @@_test_include_refined_module_class_variable = true @@ -107,7 +176,7 @@ def test_variable atlas = Titans.new assert_equal("Cronus", atlas.ruler0) assert_equal("Zeus", atlas.ruler3) - assert_equal("Cronus", atlas.ruler4) + assert_raise(RuntimeError) { atlas.ruler4 } assert_nothing_raised do class << Gods defined?(@@rule) && @@rule diff --git a/ruby/test/ruby/test_vm_dump.rb b/ruby/test/ruby/test_vm_dump.rb index 68f0fa7f2..679ce94b9 100644 --- a/ruby/test/ruby/test_vm_dump.rb +++ b/ruby/test/ruby/test_vm_dump.rb @@ -16,6 +16,6 @@ def test_darwin_segv_in_syscall end def test_darwin_invalid_access - assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).class']) + assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).inspect']) end end diff --git a/ruby/test/ruby/test_weakmap.rb b/ruby/test/ruby/test_weakmap.rb index 3b9eef770..46d8b50c0 100644 --- a/ruby/test/ruby/test_weakmap.rb +++ b/ruby/test/ruby/test_weakmap.rb @@ -73,6 +73,15 @@ def test_inspect @wm.inspect) end + def test_inspect_garbage + 1000.times do |i| + @wm[i] = Object.new + @wm.inspect + end + assert_match(/\A\#<#{@wm.class.name}:[^:]++:(?:\s\d+\s=>\s\#<(?:Object|collected):[^:<>]*+>(?:,|>\z))+/, + @wm.inspect) + end + def test_each m = __callee__[/test_(.*)/, 1] x1 = Object.new diff --git a/ruby/test/ruby/test_yjit.rb b/ruby/test/ruby/test_yjit.rb new file mode 100644 index 000000000..6390ab4c0 --- /dev/null +++ b/ruby/test/ruby/test_yjit.rb @@ -0,0 +1,687 @@ +# frozen_string_literal: true +require 'test/unit' +require 'envutil' +require 'tmpdir' + +return unless defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled? + +# Tests for YJIT with assertions on compilation and side exits +# insipired by the MJIT tests in test/ruby/test_jit.rb +class TestYJIT < Test::Unit::TestCase + def test_yjit_in_ruby_description + assert_includes(RUBY_DESCRIPTION, '+YJIT') + end + + def test_yjit_in_version + [ + %w(--version --yjit), + %w(--version --disable-yjit --yjit), + %w(--version --disable-yjit --enable-yjit), + %w(--version --disable-yjit --enable=yjit), + %w(--version --disable=yjit --yjit), + %w(--version --disable=yjit --enable-yjit), + %w(--version --disable=yjit --enable=yjit), + *([ + %w(--version --jit), + %w(--version --disable-jit --jit), + %w(--version --disable-jit --enable-jit), + %w(--version --disable-jit --enable=jit), + %w(--version --disable=jit --yjit), + %w(--version --disable=jit --enable-jit), + %w(--version --disable=jit --enable=jit), + ] if RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/), + ].each do |version_args| + assert_in_out_err(version_args) do |stdout, stderr| + assert_equal(RUBY_DESCRIPTION, stdout.first) + assert_equal([], stderr) + end + end + end + + def test_command_line_switches + assert_in_out_err('--yjit-', '', [], /invalid option --yjit-/) + assert_in_out_err('--yjithello', '', [], /invalid option --yjithello/) + assert_in_out_err('--yjit-call-threshold', '', [], /--yjit-call-threshold needs an argument/) + assert_in_out_err('--yjit-call-threshold=', '', [], /--yjit-call-threshold needs an argument/) + assert_in_out_err('--yjit-greedy-versioning=1', '', [], /warning: argument to --yjit-greedy-versioning is ignored/) + end + + def test_yjit_stats_and_v_no_error + _stdout, stderr, _status = EnvUtil.invoke_ruby(%w(-v --yjit-stats), '', true, true) + refute_includes(stderr, "NoMethodError") + end + + def test_enable_from_env_var + yjit_child_env = {'RUBY_YJIT_ENABLE' => '1'} + assert_in_out_err([yjit_child_env, '--version'], '') do |stdout, stderr| + assert_equal(RUBY_DESCRIPTION, stdout.first) + assert_equal([], stderr) + end + assert_in_out_err([yjit_child_env, '-e puts RUBY_DESCRIPTION'], '', [RUBY_DESCRIPTION]) + assert_in_out_err([yjit_child_env, '-e p RubyVM::YJIT.enabled?'], '', ['true']) + end + + def test_compile_setclassvariable + script = 'class Foo; def self.foo; @@foo = 1; end; end; Foo.foo' + assert_compiles(script, insns: %i[setclassvariable], result: 1) + end + + def test_compile_getclassvariable + script = 'class Foo; @@foo = 1; def self.foo; @@foo; end; end; Foo.foo' + assert_compiles(script, insns: %i[getclassvariable], result: 1) + end + + def test_compile_putnil + assert_compiles('nil', insns: %i[putnil], result: nil) + end + + def test_compile_putobject + assert_compiles('true', insns: %i[putobject], result: true) + assert_compiles('123', insns: %i[putobject], result: 123) + assert_compiles(':foo', insns: %i[putobject], result: :foo) + end + + def test_compile_opt_not + assert_compiles('!false', insns: %i[opt_not], result: true) + assert_compiles('!nil', insns: %i[opt_not], result: true) + assert_compiles('!true', insns: %i[opt_not], result: false) + assert_compiles('![]', insns: %i[opt_not], result: false) + end + + def test_compile_opt_newarray + assert_compiles('[]', insns: %i[newarray], result: []) + assert_compiles('[1+1]', insns: %i[newarray opt_plus], result: [2]) + assert_compiles('[1,1+1,3,4,5,6]', insns: %i[newarray opt_plus], result: [1, 2, 3, 4, 5, 6]) + end + + def test_compile_opt_duparray + assert_compiles('[1]', insns: %i[duparray], result: [1]) + assert_compiles('[1, 2, 3]', insns: %i[duparray], result: [1, 2, 3]) + end + + def test_compile_newrange + assert_compiles('s = 1; (s..5)', insns: %i[newrange], result: 1..5) + assert_compiles('s = 1; e = 5; (s..e)', insns: %i[newrange], result: 1..5) + assert_compiles('s = 1; (s...5)', insns: %i[newrange], result: 1...5) + assert_compiles('s = 1; (s..)', insns: %i[newrange], result: 1..) + assert_compiles('e = 5; (..e)', insns: %i[newrange], result: ..5) + end + + def test_compile_duphash + assert_compiles('{ two: 2 }', insns: %i[duphash], result: { two: 2 }) + end + + def test_compile_newhash + assert_compiles('{}', insns: %i[newhash], result: {}) + assert_compiles('{ two: 1 + 1 }', insns: %i[newhash], result: { two: 2 }) + assert_compiles('{ 1 + 1 => :two }', insns: %i[newhash], result: { 2 => :two }) + end + + def test_compile_opt_nil_p + assert_compiles('nil.nil?', insns: %i[opt_nil_p], result: true) + assert_compiles('false.nil?', insns: %i[opt_nil_p], result: false) + assert_compiles('true.nil?', insns: %i[opt_nil_p], result: false) + assert_compiles('(-"").nil?', insns: %i[opt_nil_p], result: false) + assert_compiles('123.nil?', insns: %i[opt_nil_p], result: false) + end + + def test_compile_eq_fixnum + assert_compiles('123 == 123', insns: %i[opt_eq], result: true) + assert_compiles('123 == 456', insns: %i[opt_eq], result: false) + end + + def test_compile_eq_string + assert_compiles('-"" == -""', insns: %i[opt_eq], result: true) + assert_compiles('-"foo" == -"foo"', insns: %i[opt_eq], result: true) + assert_compiles('-"foo" == -"bar"', insns: %i[opt_eq], result: false) + end + + def test_compile_eq_symbol + assert_compiles(':foo == :foo', insns: %i[opt_eq], result: true) + assert_compiles(':foo == :bar', insns: %i[opt_eq], result: false) + assert_compiles(':foo == "foo".to_sym', insns: %i[opt_eq], result: true) + end + + def test_compile_eq_object + assert_compiles(<<~RUBY, insns: %i[opt_eq], result: false) + def eq(a, b) + a == b + end + + eq(Object.new, Object.new) + RUBY + + assert_compiles(<<~RUBY, insns: %i[opt_eq], result: true) + def eq(a, b) + a == b + end + + obj = Object.new + eq(obj, obj) + RUBY + end + + def test_compile_eq_arbitrary_class + assert_compiles(<<~RUBY, insns: %i[opt_eq], result: "yes") + def eq(a, b) + a == b + end + + class Foo + def ==(other) + "yes" + end + end + + eq(Foo.new, Foo.new) + eq(Foo.new, Foo.new) + RUBY + end + + def test_compile_opt_lt + assert_compiles('1 < 2', insns: %i[opt_lt]) + assert_compiles('"a" < "b"', insns: %i[opt_lt]) + end + + def test_compile_opt_le + assert_compiles('1 <= 2', insns: %i[opt_le]) + assert_compiles('"a" <= "b"', insns: %i[opt_le]) + end + + def test_compile_opt_gt + assert_compiles('1 > 2', insns: %i[opt_gt]) + assert_compiles('"a" > "b"', insns: %i[opt_gt]) + end + + def test_compile_opt_ge + assert_compiles('1 >= 2', insns: %i[opt_ge]) + assert_compiles('"a" >= "b"', insns: %i[opt_ge]) + end + + def test_compile_opt_plus + assert_compiles('1 + 2', insns: %i[opt_plus]) + assert_compiles('"a" + "b"', insns: %i[opt_plus]) + assert_compiles('[:foo] + [:bar]', insns: %i[opt_plus]) + end + + def test_compile_opt_minus + assert_compiles('1 - 2', insns: %i[opt_minus]) + assert_compiles('[:foo, :bar] - [:bar]', insns: %i[opt_minus]) + end + + def test_compile_opt_or + assert_compiles('1 | 2', insns: %i[opt_or]) + assert_compiles('[:foo] | [:bar]', insns: %i[opt_or]) + end + + def test_compile_opt_and + assert_compiles('1 & 2', insns: %i[opt_and]) + assert_compiles('[:foo, :bar] & [:bar]', insns: %i[opt_and]) + end + + def test_compile_set_and_get_global + assert_compiles('$foo = 123; $foo', insns: %i[setglobal], result: 123) + end + + def test_compile_putspecialobject + assert_compiles('-> {}', insns: %i[putspecialobject]) + end + + def test_compile_tostring + assert_no_exits('"i am a string #{true}"') + end + + def test_compile_opt_aset + assert_compiles('[1,2,3][2] = 4', insns: %i[opt_aset]) + assert_compiles('{}[:foo] = :bar', insns: %i[opt_aset]) + assert_compiles('[1,2,3][0..-1] = []', insns: %i[opt_aset]) + assert_compiles('"foo"[3] = "d"', insns: %i[opt_aset]) + end + + def test_compile_attr_set + assert_no_exits(<<~EORB) + class Foo + attr_accessor :bar + end + + foo = Foo.new + foo.bar = 3 + foo.bar = 3 + foo.bar = 3 + foo.bar = 3 + EORB + end + + def test_compile_regexp + assert_no_exits('/#{true}/') + end + + def test_compile_dynamic_symbol + assert_compiles(':"#{"foo"}"', insns: %i[intern]) + assert_compiles('s = "bar"; :"foo#{s}"', insns: %i[intern]) + end + + def test_getlocal_with_level + assert_compiles(<<~RUBY, insns: %i[getlocal opt_plus], result: [[7]]) + def foo(foo, bar) + [1].map do |x| + [1].map do |y| + foo + bar + end + end + end + + foo(5, 2) + RUBY + end + + def test_setlocal_with_level + assert_no_exits(<<~RUBY) + def sum(arr) + sum = 0 + arr.each do |x| + sum += x + end + sum + end + + sum([1,2,3]) + RUBY + end + + def test_string_then_nil + assert_compiles(<<~RUBY, insns: %i[opt_nil_p], result: true) + def foo(val) + val.nil? + end + + foo("foo") + foo(nil) + RUBY + end + + def test_nil_then_string + assert_compiles(<<~RUBY, insns: %i[opt_nil_p], result: false) + def foo(val) + val.nil? + end + + foo(nil) + foo("foo") + RUBY + end + + def test_opt_length_in_method + assert_compiles(<<~RUBY, insns: %i[opt_length], result: 5) + def foo(str) + str.length + end + + foo("hello, ") + foo("world") + RUBY + end + + def test_opt_regexpmatch2 + assert_compiles(<<~RUBY, insns: %i[opt_regexpmatch2], result: 0) + def foo(str) + str =~ /foo/ + end + + foo("foobar") + RUBY + end + + def test_expandarray + assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [1, 2]) + a, b = [1, 2] + RUBY + end + + def test_expandarray_nil + assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [nil, nil]) + a, b = nil + [a, b] + RUBY + end + + def test_getspecial_backref + assert_compiles("'foo' =~ /(o)./; $&", insns: %i[getspecial], result: "oo") + assert_compiles("'foo' =~ /(o)./; $`", insns: %i[getspecial], result: "f") + assert_compiles("'foo' =~ /(o)./; $'", insns: %i[getspecial], result: "") + assert_compiles("'foo' =~ /(o)./; $+", insns: %i[getspecial], result: "o") + assert_compiles("'foo' =~ /(o)./; $1", insns: %i[getspecial], result: "o") + assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil) + end + + def test_compile_opt_getinlinecache + assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2) + def get_foo + FOO + end + + FOO = 123 + + get_foo # warm inline cache + get_foo + RUBY + end + + def test_opt_getinlinecache_slowpath + assert_compiles(<<~RUBY, exits: { opt_getinlinecache: 1 }, result: [42, 42, 1, 1], min_calls: 2) + class A + FOO = 42 + class << self + def foo + _foo = nil + FOO + end + end + end + + result = [] + + result << A.foo + result << A.foo + + class << A + FOO = 1 + end + + result << A.foo + result << A.foo + + result + RUBY + end + + def test_string_interpolation + assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "foobar", min_calls: 2) + def make_str(foo, bar) + "#{foo}#{bar}" + end + + make_str("foo", "bar") + make_str("foo", "bar") + RUBY + end + + def test_string_interpolation_cast + assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "123") + def make_str(foo, bar) + "#{foo}#{bar}" + end + + make_str(1, 23) + RUBY + end + + def test_checkkeyword + assert_compiles(<<~'RUBY', insns: %i[checkkeyword], result: [2, 5]) + def foo(foo: 1+1) + foo + end + + [foo, foo(foo: 5)] + RUBY + end + + def test_struct_aref + assert_compiles(<<~RUBY) + def foo(obj) + obj.foo + obj.bar + end + + Foo = Struct.new(:foo, :bar) + foo(Foo.new(123)) + foo(Foo.new(123)) + RUBY + end + + def test_struct_aset + assert_compiles(<<~RUBY) + def foo(obj) + obj.foo = 123 + obj.bar = 123 + end + + Foo = Struct.new(:foo, :bar) + foo(Foo.new(123)) + foo(Foo.new(123)) + RUBY + end + + def test_super_iseq + assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15) + class A + def foo + 1 + 2 + end + end + + class B < A + def foo + super * 5 + end + end + + B.new.foo + RUBY + end + + def test_super_cfunc + assert_compiles(<<~'RUBY', insns: %i[invokesuper], result: "Hello") + class Gnirts < String + def initialize + super(-"olleH") + end + + def to_s + super().reverse + end + end + + Gnirts.new.to_s + RUBY + end + + # Tests calling a variadic cfunc with many args + def test_build_large_struct + assert_compiles(<<~RUBY, insns: %i[opt_send_without_block], min_calls: 2) + ::Foo = Struct.new(:a, :b, :c, :d, :e, :f, :g, :h) + + def build_foo + ::Foo.new(:a, :b, :c, :d, :e, :f, :g, :h) + end + + build_foo + build_foo + RUBY + end + + def test_fib_recursion + assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34) + def fib(n) + return n if n <= 1 + fib(n-1) + fib(n-2) + end + + fib(9) + RUBY + end + + def test_optarg_and_kwarg + assert_no_exits(<<~'RUBY') + def opt_and_kwarg(a, b=nil, c: nil) + end + + 2.times do + opt_and_kwarg(1, 2, c: 3) + end + RUBY + end + + def test_ctx_different_mappings + # regression test simplified from URI::Generic#hostname= + assert_compiles(<<~'RUBY', frozen_string_literal: true) + def foo(v) + !(v&.start_with?('[')) && v&.index(':') + end + + foo(nil) + foo("example.com") + RUBY + end + + def test_no_excessive_opt_getinlinecache_invalidation + assert_compiles(<<~'RUBY', exits: :any, result: :ok) + objects = [Object.new, Object.new] + + objects.each do |o| + class << o + def foo + Object + end + end + end + + 9000.times { + objects[0].foo + objects[1].foo + } + + stats = RubyVM::YJIT.runtime_stats + return :ok unless stats[:all_stats] + return :ok if stats[:invalidation_count] < 10 + + :fail + RUBY + end + + def assert_no_exits(script) + assert_compiles(script) + end + + ANY = Object.new + def assert_compiles(test_script, insns: [], min_calls: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil) + reset_stats = <<~RUBY + RubyVM::YJIT.runtime_stats + RubyVM::YJIT.reset_stats! + RUBY + + write_results = <<~RUBY + stats = RubyVM::YJIT.runtime_stats + + def collect_blocks(blocks) + blocks.sort_by(&:address).map { |b| [b.iseq_start_index, b.iseq_end_index] } + end + + def collect_iseqs(iseq) + iseq_array = iseq.to_a + insns = iseq_array.last.grep(Array) + blocks = RubyVM::YJIT.blocks_for(iseq) + h = { + name: iseq_array[5], + insns: insns, + blocks: collect_blocks(blocks), + } + arr = [h] + iseq.each_child { |c| arr.concat collect_iseqs(c) } + arr + end + + iseq = RubyVM::InstructionSequence.of(_test_proc) + IO.open(3).write Marshal.dump({ + result: #{result == ANY ? "nil" : "result"}, + stats: stats, + iseqs: collect_iseqs(iseq), + disasm: iseq.disasm + }) + RUBY + + script = <<~RUBY + #{"# frozen_string_literal: true" if frozen_string_literal} + _test_proc = -> { + #{test_script} + } + #{reset_stats} + result = _test_proc.call + #{write_results} + RUBY + + status, out, err, stats = eval_with_jit(script, min_calls: min_calls) + + assert status.success?, "exited with status #{status.to_i}, stderr:\n#{err}" + + assert_equal stdout.chomp, out.chomp if stdout + + unless ANY.equal?(result) + assert_equal result, stats[:result] + end + + runtime_stats = stats[:stats] + iseqs = stats[:iseqs] + disasm = stats[:disasm] + + # Only available when RUBY_DEBUG enabled + if runtime_stats[:all_stats] + recorded_exits = runtime_stats.select { |k, v| k.to_s.start_with?("exit_") } + recorded_exits = recorded_exits.reject { |k, v| v == 0 } + + recorded_exits.transform_keys! { |k| k.to_s.gsub("exit_", "").to_sym } + if exits != :any && exits != recorded_exits + flunk "Expected #{exits.empty? ? "no" : exits.inspect} exits" \ + ", but got\n#{recorded_exits.inspect}" + end + end + + # Only available when RUBY_DEBUG enabled + if runtime_stats[:all_stats] + missed_insns = insns.dup + all_compiled_blocks = {} + iseqs.each do |iseq| + compiled_blocks = iseq[:blocks].map { |from, to| (from...to) } + all_compiled_blocks[iseq[:name]] = compiled_blocks + compiled_insns = iseq[:insns] + next_idx = 0 + compiled_insns.map! do |insn| + # TODO: not sure this is accurate for determining insn size + idx = next_idx + next_idx += insn.length + [idx, *insn] + end + + compiled_insns.each do |idx, op, *arguments| + next unless missed_insns.include?(op) + next unless compiled_blocks.any? { |block| block === idx } + + # This instruction was compiled + missed_insns.delete(op) + end + end + + unless missed_insns.empty? + flunk "Expected to compile instructions #{missed_insns.join(", ")} but didn't.\nCompiled ranges: #{all_compiled_blocks.inspect}\niseq:\n#{disasm}" + end + end + end + + def eval_with_jit(script, min_calls: 1, timeout: 1000) + args = [ + "--disable-gems", + "--yjit-call-threshold=#{min_calls}", + "--yjit-stats" + ] + args << "-e" << script + stats_r, stats_w = IO.pipe + out, err, status = EnvUtil.invoke_ruby(args, + '', true, true, timeout: timeout, ios: {3 => stats_w} + ) + stats_w.close + stats = stats_r.read + stats = Marshal.load(stats) if !stats.empty? + stats_r.close + [status, out, err, stats] + end +end diff --git a/ruby/test/rubygems/bogussources.rb b/ruby/test/rubygems/bogussources.rb deleted file mode 100644 index 4f783c3bd..000000000 --- a/ruby/test/rubygems/bogussources.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -#-- -# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. -# All rights reserved. -# See LICENSE.txt for permissions. -#++ - -require 'rubygems' -Gem.use_paths("test/mock/gems") diff --git a/ruby/test/rubygems/data/null-required-ruby-version.gemspec.rz b/ruby/test/rubygems/data/null-required-ruby-version.gemspec.rz new file mode 100644 index 000000000..f4ec1a962 Binary files /dev/null and b/ruby/test/rubygems/data/null-required-ruby-version.gemspec.rz differ diff --git a/ruby/test/rubygems/data/null-required-rubygems-version.gemspec.rz b/ruby/test/rubygems/data/null-required-rubygems-version.gemspec.rz new file mode 100644 index 000000000..db3d0af08 Binary files /dev/null and b/ruby/test/rubygems/data/null-required-rubygems-version.gemspec.rz differ diff --git a/ruby/test/rubygems/data/null-type.gemspec.rz b/ruby/test/rubygems/data/null-type.gemspec.rz index bad99289d..2134fcde2 100644 Binary files a/ruby/test/rubygems/data/null-type.gemspec.rz and b/ruby/test/rubygems/data/null-type.gemspec.rz differ diff --git a/ruby/test/rubygems/encrypted_private_key.pem b/ruby/test/rubygems/encrypted_private_key.pem index 868f332b7..d9667689a 100644 --- a/ruby/test/rubygems/encrypted_private_key.pem +++ b/ruby/test/rubygems/encrypted_private_key.pem @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: DES-CBC,4E38D58B5A059DB6 +DEK-Info: AES-256-CBC,CB6FD0B173EF450C6EE21A01DD785C1D -IgWLfnHVnkErKkhysrUMoE0ubkRDtJXZv9KR02jGGFk/kGqWyTqPk08uzhwVNM+l -eOk0qfPykkJM3KZgqTsD6xfA1D5WqFp5mLoFXVVTn9I3acSZsqOY0FweCipwdVpI -x+9Fl+v62kIW06dOjyWLE1abed9hHiXesGGsD87/RJSywy4OBxOcrhR1fJLK4ElR -ya0UzI7rWnmZMChjaZBssfzT1DR79/dARXhon2m5EiIJDjMpc8BKGYlQy5RHCHwA -cnrhUTTvsggZbQtmLZ/yVx8FSJ273XpYR0pmwbw4j1R+zeXQRK5MroBnCfOGcYa7 -rmpERmDW3VAuxXR20SUAGdo1XOMTDe1uLbaotn6e56pXghIaYROTPS+HsuOkAZGY -OYWEkUoyog4l4n+h/C1umFfTFGvKNATLgDugONFvTw/PLbjvl+sWMy2QfqH0MlNB -DIUPxhEVCFD9oB4nfB86WDAmPp1DH9/IBet/21kbQ2eTIzakTdG3XiC+xzAQRu68 -EOCTbasFWGxlCix66gt4xWMLksEg8UhWSpjS3/HsifrKyNMB8sfUFYmZmOYMW4mf -NuEtpBL3AdHNObN8nQ75HfehukzNpbYVRsLzWrVgtxvXHVpnvoCCpCvQBMHeRZxK -6m028mhH1m6yYE/uGFiRKLrN7BKAttbUiqnGgVIg/lQQilFWwylxQ6aXqJGmNgxa -oihzWZRlXivIhhrM7VMnLoKAF/YfmWpP3zahGpBQGfObtPtm44R0ezXPdtsivnyu -CmFOPGzRNMKZtH/lwVhuIIK3AFIGDsRRP9ySN4YfjQZnTdu2sRlxBnANP9m8W9T2 -p+C4zVkDYAbsuWq2HpHwsdL8gqIiXeptsHLqkNw+ulSSLyeBCgM9fpV3RsNGjwqu -k8QLb1CYp2VX46CE8UKvOd/nyFnEsD+EAc3WangEwA41m2IaXcbs9Au7xsG9oacZ -DrxlJVNxlxO9YyP9dNOTfP0fHIiygKQQY2aU3y3oRneu7ogYES5V2mUNH7cYUWVL -CHPXAoUXJErvDQ/opW2DroA9Eqv9sST6WqBf6LXRcWU0ntfzcFUbEqgmCmB7Cbu2 -8udEn6iWilQahLyDoAShLkU7+Tk78Z1c6RuqjyY4VboZPzxrTYK8YIXzwX+jj9bG -KIIGS5eghK185+AjlwtzJ7MBdoL323YIik6uOZluhnJHLaxjxUXGa1VqDgsyqGi7 -ISRMTpVTrbR+UtoEi4ZhMjobtFUr7lGkt24VkXwBKdoyryj4RPHGdp7Tf6XDJufQ -+KKhqt8QrpOTPiMskFN2disOSF5/YZCmtT84nkhU7Hf1lkQ2kfx1zfNk0GqYYXOW -zHOAczy8gWBRetDMnhRYohDzQGWn//b+2Wr2n1RD8D9kyjMRhpFMYfQGfRcuPGjW -91k/T0XFcjcjeZPL9s+HITmrh7zg5WxbCfTEp91j3Oy1bns196SY77TE0BzUsqR2 -geJggcUMEfyvHiiCMtijmSSD9nf8tNIxLVL8Jaf1coA6e1CrlHnYAu2f/Q3GIcvU -EEEmw+cZRwsk4fffYzh5psxxGdXKBv1KcQ/CeBhZL0WJsCp2y5oxwg== +KqHn2Df8hSuwNE+W+60MnGtc6xpoXmF3iN25iVwcN67krYn+N6cBhjFeXwXccYwJ +2gHSu4iEK9Qe32vK0yuv8N9h/fmsabZl0TotnEem/pqO5T8W4LxyK+Rw0s6RB30S +C+mUisRADTanAxyBxsNU8xR8OAUNMAAxV1me6It0W2lfNE3t5jg/Kr0NWMoRUNRx +dkE6WlD5D8jBeC3QdZ6OuE7QXOCEAWAjcFMc0d1WJq2t2r3TrLVfTH7EOoRyvL1H +rrFRx/dEW1UJfM6P11wB5R0nhg3rDXF7oDFszjwO/3tzARke0NZuN37l301lYRl1 +aolO6sShJLa0Ml/TgNcJw0S6rc6a1Z52gTfQKztKcL1UX4HLZg75zKmn6qfatMBC +iXn+pQRYNsOPQ5h4r7lBBqvuV+gBw+rN768tYpZ2/YVDaygxETHcZAFCdAw/JNbP +d0XPIbP79NRrCgzSo58LKQGuOQf3Hh0vp1YS+MilMtm/eogoj1enSPM+ymStHRwG +i+D00xCQ6blSOZ2eUUBJXt11YzP22GYnv+XTR/5kGKkTIvoRMfd+39bQyR32IEv2 +Z+yweAGQInD94eifT9ObbIayJ47y01KP0+Vj6hz4RCFsmJKsYiai5JiKlmf7lV9w +7zH3TtCOx/xSyomesXVRkqvFkdyeguU72kXc5tiMPaDXGCOeV0GWyR1GU1DUX9/K +60E7ym0Wx77WGMKk2fkirZzBdOeliyCRUXd7ccN2rBCjTwtjAUIk27lwzdUaTUv7 +EmjauDvSMFtir58c+zjlLmBaSQOzKcj0KXMp0Oucls9bD85WGGbGyzGhTa0AZ+/+ +cCEJt7RAwW0kTEO/uO+BAZe/zBoi9ek+QBn54FK3E7CXfS4Oi9Qbc3fwlVyTlVmz +ZGrCncO0TIVGErFWK24Z7lX8rBnk8enfnamrPfKtwn4LG9aDfhSj8DtisjlRUVT5 +chDQ+CCi9rh3wXh28lyS+nXJ3yFidCzRgcsc3PpN/c4DNRggZc+C/KDw+J2FW+8Y +p65OliBQHQcG0PnCa2xRyCGevytPG0rfNDgyaY33dPEo90mBLVcwLbzGiSGBHgFl +pr8A/rqbnFpRO39NYbACeRFCqPpzyzfARCCcjcDoFrENdIaJui0fjlBkoV3B/KiK +EVjDcgwt1HAtz8bV2YJ+OpQbhD7E90e2vTRMuXAH21Ygo32VOS0LRlCRc9ZyZW4z +PTyO/6a+FbXZ1zhVJxu/0bmBERZ14WVmWq56oxQav8knpxYeYPgpEmIZnrHnJ1Ko +UoXcc8Hy4NKtaBmDcaF8TCobNsRZTxO/htqpdyNsOrBSsnX2kP5D/O1l1vuVYi1/ +RYfUqL9dvGzvfsFuuDDjDlQ/fIA6pFzJV3fy4KJHlF1r33qaE/lNMdpKljBwvUII +Vog4cGmzxssqK5q9kuogcuyeOuFODjBNW4qt0WylSi9bwwy3ZwaZLRqhngz6+tCV +Jp45Gk881XiVe3aVU0l+4DmJJ9/5vwqjH5Vo/GJqFU6gzB+Zv/0plYeNkuE0Xo2z +ecdxnGKVPl42q44lvczjDw2KX0ahxQrfrbcl48//zR295u9POzCL97d6zpioI2NR -----END RSA PRIVATE KEY----- diff --git a/ruby/test/rubygems/helper.rb b/ruby/test/rubygems/helper.rb new file mode 100644 index 000000000..d97d93047 --- /dev/null +++ b/ruby/test/rubygems/helper.rb @@ -0,0 +1,1609 @@ +# frozen_string_literal: true + +require 'rubygems' + +# If bundler gemspec exists, add to stubs +bundler_gemspec = File.expand_path("../../../bundler/bundler.gemspec", __FILE__) +if File.exist?(bundler_gemspec) + Gem::Specification.dirs.unshift File.dirname(bundler_gemspec) + Gem::Specification.class_variable_set :@@stubs, nil + Gem::Specification.stubs + Gem::Specification.dirs.shift +end + +begin + gem 'test-unit', '~> 3.0' +rescue Gem::LoadError +end + +if File.exist?(bundler_gemspec) + require_relative '../../bundler/lib/bundler' +else + require 'bundler' +end + +require 'test/unit' + +ENV["JARS_SKIP"] = "true" if Gem.java_platform? # avoid unnecessary and noisy `jar-dependencies` post install hook + +require 'rubygems/deprecate' + +require 'fileutils' +require 'pathname' +require 'pp' +require 'rubygems/package' +require 'shellwords' +require 'tmpdir' +require 'uri' +require 'zlib' +require 'benchmark' # stdlib +require 'rubygems/mock_gem_ui' + +module Gem + + ## + # Allows setting the gem path searcher. + + def self.searcher=(searcher) + @searcher = searcher + end + + ## + # Allows toggling Windows behavior. + + def self.win_platform=(val) + @@win_platform = val + end + + ## + # Allows setting path to Ruby. + + def self.ruby=(ruby) + @ruby = ruby + end + + ## + # Sets the default user interaction to a MockGemUi. + + module DefaultUserInteraction + @ui = Gem::MockGemUi.new + end +end + +require "rubygems/command" + +class Gem::Command + ## + # Allows resetting the hash of specific args per command. + + def self.specific_extra_args_hash=(value) + @specific_extra_args_hash = value + end +end + +## +# RubyGemTestCase provides a variety of methods for testing rubygems and +# gem-related behavior in a sandbox. Through RubyGemTestCase you can install +# and uninstall gems, fetch remote gems through a stub fetcher and be assured +# your normal set of gems is not affected. + +class Gem::TestCase < Test::Unit::TestCase + extend Gem::Deprecate + + attr_accessor :fetcher # :nodoc: + + attr_accessor :gem_repo # :nodoc: + + attr_accessor :uri # :nodoc: + + def assert_activate(expected, *specs) + specs.each do |spec| + case spec + when String then + Gem::Specification.find_by_name(spec).activate + when Gem::Specification then + spec.activate + else + flunk spec.inspect + end + end + + loaded = Gem.loaded_specs.values.map(&:full_name) + + assert_equal expected.sort, loaded.sort if expected + end + + def assert_directory_exists(path, msg = nil) + msg = build_message(msg, "Expected path '#{path}' to be a directory") + assert_path_exist path + assert File.directory?(path), msg + end + + # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188 + def _synchronize + yield + end + + # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546 + def capture_subprocess_io + _synchronize do + begin + require "tempfile" + + captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") + + orig_stdout, orig_stderr = $stdout.dup, $stderr.dup + $stdout.reopen captured_stdout + $stderr.reopen captured_stderr + + yield + + $stdout.rewind + $stderr.rewind + + return captured_stdout.read, captured_stderr.read + ensure + $stdout.reopen orig_stdout + $stderr.reopen orig_stderr + + orig_stdout.close + orig_stderr.close + captured_stdout.close! + captured_stderr.close! + end + end + end + + ## + # Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores + # the original value when the block ends + + def enable_shared(value) + enable_shared = RbConfig::CONFIG['ENABLE_SHARED'] + RbConfig::CONFIG['ENABLE_SHARED'] = value + + yield + ensure + if enable_shared + RbConfig::CONFIG['enable_shared'] = enable_shared + else + RbConfig::CONFIG.delete 'enable_shared' + end + end + + ## + # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the + # original value when the block ends + # + def vendordir(value) + vendordir = RbConfig::CONFIG['vendordir'] + + if value + RbConfig::CONFIG['vendordir'] = value + else + RbConfig::CONFIG.delete 'vendordir' + end + + yield + ensure + if vendordir + RbConfig::CONFIG['vendordir'] = vendordir + else + RbConfig::CONFIG.delete 'vendordir' + end + end + + ## + # Sets the bindir entry in RbConfig::CONFIG to +value+ and restores the + # original value when the block ends + # + def bindir(value) + with_clean_path_to_ruby do + bindir = RbConfig::CONFIG['bindir'] + + if value + RbConfig::CONFIG['bindir'] = value + else + RbConfig::CONFIG.delete 'bindir' + end + + begin + yield + ensure + if bindir + RbConfig::CONFIG['bindir'] = bindir + else + RbConfig::CONFIG.delete 'bindir' + end + end + end + end + + ## + # Sets the EXEEXT entry in RbConfig::CONFIG to +value+ and restores the + # original value when the block ends + # + def exeext(value) + exeext = RbConfig::CONFIG['EXEEXT'] + + if value + RbConfig::CONFIG['EXEEXT'] = value + else + RbConfig::CONFIG.delete 'EXEEXT' + end + + yield + ensure + if exeext + RbConfig::CONFIG['EXEEXT'] = exeext + else + RbConfig::CONFIG.delete 'EXEEXT' + end + end + + def scan_make_command_lines(output) + output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/) + end + + def parse_make_command_line_targets(line) + args = line.sub(/^#{Regexp.escape make_command}/, "").shellsplit + + targets = [] + + args.each do |arg| + case arg + when /\A(\w+)=/ + else + targets << arg + end + end + + targets << '' if targets.empty? + + targets + end + + def assert_contains_make_command(target, output, msg = nil) + if output.match(/\n/) + msg = build_message(msg, + "Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT" % [ + ('%s %s' % [make_command, target]).rstrip, + output, + ] + ) + else + msg = build_message(msg, + 'Expected make command "%s", but was "%s"' % [ + ('%s %s' % [make_command, target]).rstrip, + output, + ] + ) + end + + assert scan_make_command_lines(output).any? {|line| + targets = parse_make_command_line_targets(line) + + if targets.include?(target) + true + else + false + end + }, msg + end + + include Gem::DefaultUserInteraction + + ## + # #setup prepares a sandboxed location to install gems. All installs are + # directed to a temporary directory. All install plugins are removed. + # + # If the +RUBY+ environment variable is set the given path is used for + # Gem::ruby. The local platform is set to i386-mswin32 for Windows + # or i686-darwin8.10.1 otherwise. + + def setup + @orig_env = ENV.to_hash + @tmp = File.expand_path("tmp") + + FileUtils.mkdir_p @tmp + + ENV['GEM_VENDOR'] = nil + ENV['GEMRC'] = nil + ENV['XDG_CACHE_HOME'] = nil + ENV['XDG_CONFIG_HOME'] = nil + ENV['XDG_DATA_HOME'] = nil + ENV['SOURCE_DATE_EPOCH'] = nil + ENV['BUNDLER_VERSION'] = nil + + @current_dir = Dir.pwd + @fetcher = nil + + @back_ui = Gem::DefaultUserInteraction.ui + @ui = Gem::MockGemUi.new + # This needs to be a new instance since we call use_ui(@ui) when we want to + # capture output + Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new + + @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) + @tempdir.tap(&Gem::UNTAINT) + + ENV["TMPDIR"] = @tempdir + + @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE + Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE + Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, + File.join(@tempdir, 'system-gemrc') + + @gemhome = File.join @tempdir, 'gemhome' + @userhome = File.join @tempdir, 'userhome' + ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache' + + @orig_ruby = if ENV['RUBY'] + ruby = Gem.ruby + Gem.ruby = ENV['RUBY'] + ruby + end + + @git = ENV['GIT'] || (win_platform? ? 'git.exe' : 'git') + + Gem.ensure_gem_subdirectories @gemhome + Gem.ensure_default_gem_subdirectories @gemhome + + @orig_LOAD_PATH = $LOAD_PATH.dup + $LOAD_PATH.map! do |s| + expand_path = File.realpath(s) rescue File.expand_path(s) + if expand_path != s + expand_path.tap(&Gem::UNTAINT) + if s.instance_variable_defined?(:@gem_prelude_index) + expand_path.instance_variable_set(:@gem_prelude_index, expand_path) + end + expand_path.freeze if s.frozen? + s = expand_path + end + s + end + + Dir.chdir @tempdir + + ENV['HOME'] = @userhome + Gem.instance_variable_set :@config_file, nil + Gem.instance_variable_set :@user_home, nil + Gem.instance_variable_set :@config_home, nil + Gem.instance_variable_set :@data_home, nil + Gem.instance_variable_set :@gemdeps, nil + Gem.instance_variable_set :@env_requirements_by_name, nil + Gem.send :remove_instance_variable, :@ruby_version if + Gem.instance_variables.include? :@ruby_version + + FileUtils.mkdir_p @userhome + + ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE + + Gem.instance_variable_set(:@default_specifications_dir, nil) + if Gem.java_platform? + @orig_default_gem_home = RbConfig::CONFIG['default_gem_home'] + RbConfig::CONFIG['default_gem_home'] = @gemhome + else + Gem.instance_variable_set(:@default_dir, @gemhome) + end + + @orig_bindir = RbConfig::CONFIG["bindir"] + RbConfig::CONFIG["bindir"] = File.join @gemhome, "bin" + + @orig_sitelibdir = RbConfig::CONFIG["sitelibdir"] + new_sitelibdir = @orig_sitelibdir.sub(RbConfig::CONFIG["prefix"], @gemhome) + $LOAD_PATH.insert(Gem.load_path_insert_index, new_sitelibdir) + RbConfig::CONFIG["sitelibdir"] = new_sitelibdir + + @orig_mandir = RbConfig::CONFIG["mandir"] + RbConfig::CONFIG["mandir"] = File.join @gemhome, "share", "man" + + Gem::Specification.unresolved_deps.clear + Gem.use_paths(@gemhome) + + Gem.loaded_specs.clear + Gem.instance_variable_set(:@activated_gem_paths, 0) + Gem.clear_default_specs + Bundler.reset! + + Gem.configuration.verbose = true + Gem.configuration.update_sources = true + + Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new + + @gem_repo = "http://gems.example.com/" + @uri = URI.parse @gem_repo + Gem.sources.replace [@gem_repo] + + Gem.searcher = nil + Gem::SpecFetcher.fetcher = nil + + @orig_arch = RbConfig::CONFIG['arch'] + + if win_platform? + util_set_arch 'i386-mswin32' + else + util_set_arch 'i686-darwin8.10.1' + end + + @orig_hooks = {} + %w[post_install_hooks done_installing_hooks post_uninstall_hooks pre_uninstall_hooks pre_install_hooks pre_reset_hooks post_reset_hooks post_build_hooks].each do |name| + @orig_hooks[name] = Gem.send(name).dup + end + + @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" + @orig_LOADED_FEATURES = $LOADED_FEATURES.dup + end + + ## + # #teardown restores the process to its original state and removes the + # tempdir + + def teardown + $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH + if @orig_LOADED_FEATURES + if @orig_LOAD_PATH + ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat| + $LOADED_FEATURES.delete(feat) if feat.start_with?(@tmp) + end + else + $LOADED_FEATURES.replace @orig_LOADED_FEATURES + end + end + + RbConfig::CONFIG['arch'] = @orig_arch + + if defined? Gem::RemoteFetcher + Gem::RemoteFetcher.fetcher = nil + end + + Dir.chdir @current_dir + + FileUtils.rm_rf @tempdir + + ENV.replace(@orig_env) + + Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE + Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, + @orig_SYSTEM_WIDE_CONFIG_FILE + + Gem.ruby = @orig_ruby if @orig_ruby + + RbConfig::CONFIG['mandir'] = @orig_mandir + RbConfig::CONFIG['sitelibdir'] = @orig_sitelibdir + RbConfig::CONFIG['bindir'] = @orig_bindir + + Gem.instance_variable_set :@default_specifications_dir, nil + if Gem.java_platform? + RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home + else + Gem.instance_variable_set :@default_dir, nil + end + + Gem::Specification.unresolved_deps.clear + Gem::refresh + + @orig_hooks.each do |name, hooks| + Gem.send(name).replace hooks + end + + @back_ui.close + end + + def credential_setup + @temp_cred = File.join(@userhome, '.gem', 'credentials') + FileUtils.mkdir_p File.dirname(@temp_cred) + File.write @temp_cred, ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97' + File.chmod 0600, @temp_cred + end + + def credential_teardown + FileUtils.rm_rf @temp_cred + end + + def common_installer_setup + common_installer_teardown + + Gem.post_build do |installer| + @post_build_hook_arg = installer + true + end + + Gem.post_install do |installer| + @post_install_hook_arg = installer + end + + Gem.post_uninstall do |uninstaller| + @post_uninstall_hook_arg = uninstaller + end + + Gem.pre_install do |installer| + @pre_install_hook_arg = installer + true + end + + Gem.pre_uninstall do |uninstaller| + @pre_uninstall_hook_arg = uninstaller + end + end + + def common_installer_teardown + Gem.post_build_hooks.clear + Gem.post_install_hooks.clear + Gem.done_installing_hooks.clear + Gem.post_reset_hooks.clear + Gem.post_uninstall_hooks.clear + Gem.pre_install_hooks.clear + Gem.pre_reset_hooks.clear + Gem.pre_uninstall_hooks.clear + end + + def without_any_upwards_gemfiles + ENV["BUNDLE_GEMFILE"] = File.join(@tempdir, "Gemfile") + end + + ## + # A git_gem is used with a gem dependencies file. The gem created here + # has no files, just a gem specification for the given +name+ and +version+. + # + # Yields the +specification+ to the block, if given + + def git_gem(name = 'a', version = 1) + have_git? + + directory = File.join 'git', name + directory = File.expand_path directory + + git_spec = Gem::Specification.new name, version do |specification| + yield specification if block_given? + end + + FileUtils.mkdir_p directory + + gemspec = "#{name}.gemspec" + + File.open File.join(directory, gemspec), 'w' do |io| + io.write git_spec.to_ruby + end + + head = nil + + Dir.chdir directory do + unless File.exist? '.git' + system @git, 'init', '--quiet' + system @git, 'config', 'user.name', 'RubyGems Tests' + system @git, 'config', 'user.email', 'rubygems@example' + end + + system @git, 'add', gemspec + system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet' + head = Gem::Util.popen(@git, 'rev-parse', 'master').strip + end + + return name, git_spec.version, directory, head + end + + ## + # Skips this test unless you have a git executable + + def have_git? + return if in_path? @git + + pend 'cannot find git executable, use GIT environment variable to set' + end + + def in_path?(executable) # :nodoc: + return true if %r{\A([A-Z]:|/)} =~ executable and File.exist? executable + + ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| + File.exist? File.join directory, executable + end + end + + ## + # Builds and installs the Gem::Specification +spec+ + + def install_gem(spec, options = {}) + require 'rubygems/installer' + + gem = spec.cache_file + + unless File.exist? gem + use_ui Gem::MockGemUi.new do + Dir.chdir @tempdir do + Gem::Package.build spec + end + end + + gem = File.join(@tempdir, File.basename(gem)).tap(&Gem::UNTAINT) + end + + Gem::Installer.at(gem, options.merge({:wrappers => true})).install + end + + ## + # Builds and installs the Gem::Specification +spec+ into the user dir + + def install_gem_user(spec) + install_gem spec, :user_install => true + end + + ## + # Uninstalls the Gem::Specification +spec+ + def uninstall_gem(spec) + require 'rubygems/uninstaller' + + Class.new(Gem::Uninstaller) do + def ask_if_ok(spec) + true + end + end.new(spec.name, :executables => true, :user_install => true).uninstall + end + + ## + # Enables pretty-print for all tests + + def mu_pp(obj) + s = String.new + s = PP.pp obj, s + s = s.force_encoding(Encoding.default_external) + s.chomp + end + + ## + # Reads a Marshal file at +path+ + + def read_cache(path) + File.open path.dup.tap(&Gem::UNTAINT), 'rb' do |io| + Marshal.load io.read + end + end + + ## + # Reads a binary file at +path+ + + def read_binary(path) + Gem.read_binary path + end + + ## + # Writes a binary file to +path+ which is relative to +@gemhome+ + + def write_file(path) + path = File.join @gemhome, path unless Pathname.new(path).absolute? + dir = File.dirname path + FileUtils.mkdir_p dir unless File.directory? dir + + File.open path, 'wb' do |io| + yield io if block_given? + end + + path + end + + ## + # Load a YAML string, the psych 3 way + + def load_yaml(yaml) + if Psych.respond_to?(:unsafe_load) + Psych.unsafe_load(yaml) + else + Psych.load(yaml) + end + end + + ## + # Load a YAML file, the psych 3 way + + def load_yaml_file(file) + if Psych.respond_to?(:unsafe_load_file) + Psych.unsafe_load_file(file) + else + Psych.load_file(file) + end + end + + def all_spec_names + Gem::Specification.map(&:full_name) + end + + ## + # Creates a Gem::Specification with a minimum of extra work. +name+ and + # +version+ are the gem's name and version, platform, author, email, + # homepage, summary and description are defaulted. The specification is + # yielded for customization. + # + # The gem is added to the installed gems in +@gemhome+ and the runtime. + # + # Use this with #write_file to build an installed gem. + + def quick_gem(name, version='2') + require 'rubygems/specification' + + spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = name + s.version = version + s.author = 'A User' + s.email = 'example@example.com' + s.homepage = 'http://example.com' + s.summary = "this is a summary" + s.description = "This is a test description" + + yield(s) if block_given? + end + + written_path = write_file spec.spec_file do |io| + io.write spec.to_ruby_for_cache + end + + spec.loaded_from = written_path + + Gem::Specification.reset + + return spec + end + + ## + # Builds a gem from +spec+ and places it in File.join @gemhome, + # 'cache'. Automatically creates files based on +spec.files+ + + def util_build_gem(spec) + dir = spec.gem_dir + FileUtils.mkdir_p dir + + Dir.chdir dir do + spec.files.each do |file| + next if File.exist? file + FileUtils.mkdir_p File.dirname(file) + + File.open file, 'w' do |fp| + fp.puts "# #{file}" + end + end + + use_ui Gem::MockGemUi.new do + Gem::Package.build spec + end + + cache = spec.cache_file + FileUtils.mv File.basename(cache), cache + end + end + + def util_remove_gem(spec) + FileUtils.rm_rf spec.cache_file + FileUtils.rm_rf spec.spec_file + end + + ## + # Removes all installed gems from +@gemhome+. + + def util_clear_gems + FileUtils.rm_rf File.join(@gemhome, "gems") + FileUtils.mkdir File.join(@gemhome, "gems") + FileUtils.rm_rf File.join(@gemhome, "specifications") + FileUtils.mkdir File.join(@gemhome, "specifications") + Gem::Specification.reset + end + + ## + # Install the provided specs + + def install_specs(*specs) + specs.each do |spec| + Gem::Installer.for_spec(spec, :force => true).install + end + + Gem.searcher = nil + end + + ## + # Installs the provided default specs including writing the spec file + + def install_default_gems(*specs) + specs.each do |spec| + installer = Gem::Installer.for_spec(spec, :install_as_default => true) + installer.install + Gem.register_default_spec(spec) + end + end + + def loaded_spec_names + Gem.loaded_specs.values.map(&:full_name).sort + end + + def unresolved_names + Gem::Specification.unresolved_deps.values.map(&:to_s).sort + end + + def new_default_spec(name, version, deps = nil, *files) + spec = util_spec name, version, deps + + spec.loaded_from = File.join(@gemhome, "specifications", "default", spec.spec_name) + spec.files = files + + lib_dir = File.join(@tempdir, "default_gems", "lib") + lib_dir.instance_variable_set(:@gem_prelude_index, lib_dir) + Gem.instance_variable_set(:@default_gem_load_paths, [*Gem.send(:default_gem_load_paths), lib_dir]) + $LOAD_PATH.unshift(lib_dir) + files.each do |file| + rb_path = File.join(lib_dir, file) + FileUtils.mkdir_p(File.dirname(rb_path)) + File.open(rb_path, "w") do |rb| + rb << "# #{file}" + end + end + + spec + end + + ## + # Creates a spec with +name+, +version+. +deps+ can specify the dependency + # or a +block+ can be given for full customization of the specification. + + def util_spec(name, version = 2, deps = nil, *files) # :yields: specification + raise "deps or block, not both" if deps and block_given? + + spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = name + s.version = version + s.author = 'A User' + s.email = 'example@example.com' + s.homepage = 'http://example.com' + s.summary = "this is a summary" + s.description = "This is a test description" + + s.files.push(*files) unless files.empty? + + yield s if block_given? + end + + if deps + deps.keys.each do |n| + spec.add_dependency n, (deps[n] || '>= 0') + end + end + + unless files.empty? + write_file spec.spec_file do |io| + io.write spec.to_ruby_for_cache + end + + util_build_gem spec + + FileUtils.rm spec.spec_file + end + + return spec + end + + ## + # Creates a gem with +name+, +version+ and +deps+. The specification will + # be yielded before gem creation for customization. The gem will be placed + # in File.join @tempdir, 'gems'. The specification and .gem file + # location are returned. + + def util_gem(name, version, deps = nil, &block) + if deps + block = proc do |s| + deps.keys.each do |n| + s.add_dependency n, (deps[n] || '>= 0') + end + end + end + + spec = quick_gem(name, version, &block) + + util_build_gem spec + + cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" + FileUtils.mkdir_p File.dirname cache_file + FileUtils.mv spec.cache_file, cache_file + FileUtils.rm spec.spec_file + + spec.loaded_from = nil + + [spec, cache_file] + end + + ## + # Gzips +data+. + + def util_gzip(data) + out = StringIO.new + + Zlib::GzipWriter.wrap out do |io| + io.write data + end + + out.string + end + + ## + # Creates several default gems which all have a lib/code.rb file. The gems + # are not installed but are available in the cache dir. + # + # +@a1+:: gem a version 1, this is the best-described gem. + # +@a2+:: gem a version 2 + # +@a3a:: gem a version 3.a + # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems + # don't collide with a. + # +@b2+:: gem b version 2 + # +@c1_2+:: gem c version 1.2 + # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux. + # + # Additional +prerelease+ gems may also be created: + # + # +@a2_pre+:: gem a version 2.a + # TODO: nuke this and fix tests. this should speed up a lot + + def util_make_gems(prerelease = false) + @a1 = quick_gem 'a', '1' do |s| + s.files = %w[lib/code.rb] + s.require_paths = %w[lib] + s.date = Gem::Specification::TODAY - 86400 + s.homepage = 'http://a.example.com' + s.email = %w[example@example.com example2@example.com] + s.authors = %w[Example Example2] + s.description = <<-DESC +This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed. + +Also, a list: + * An entry that\'s actually kind of sort + * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters. + DESC + end + + init = proc do |s| + s.files = %w[lib/code.rb] + s.require_paths = %w[lib] + end + + @a2 = quick_gem('a', '2', &init) + @a3a = quick_gem('a', '3.a', &init) + @a_evil9 = quick_gem('a_evil', '9', &init) + @b2 = quick_gem('b', '2', &init) + @c1_2 = quick_gem('c', '1.2', &init) + @x = quick_gem('x', '1', &init) + @dep_x = quick_gem('dep_x', '1') do |s| + s.files = %w[lib/code.rb] + s.require_paths = %w[lib] + s.add_dependency 'x', '>= 1' + end + + @pl1 = quick_gem 'pl', '1' do |s| # l for legacy + s.files = %w[lib/code.rb] + s.require_paths = %w[lib] + s.platform = Gem::Platform.new 'i386-linux' + s.instance_variable_set :@original_platform, 'i386-linux' + end + + if prerelease + @a2_pre = quick_gem('a', '2.a', &init) + write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) + util_build_gem @a2_pre + end + + write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) + + [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec| + util_build_gem spec + end + + FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name) + end + + ## + # Set the platform to +arch+ + + def util_set_arch(arch) + RbConfig::CONFIG['arch'] = arch + platform = Gem::Platform.new arch + + Gem.instance_variable_set :@platforms, nil + Gem::Platform.instance_variable_set :@local, nil + + yield if block_given? + + platform + end + + ## + # Add +spec+ to +@fetcher+ serving the data in the file +path+. + # +repo+ indicates which repo to make +spec+ appear to be in. + + def add_to_fetcher(spec, path=nil, repo=@gem_repo) + path ||= spec.cache_file + @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) + end + + ## + # Sets up Gem::SpecFetcher to return information from the gems in +specs+. + + def util_setup_spec_fetcher(*specs) + all_specs = Gem::Specification.to_a + specs + Gem::Specification._resort! all_specs + + spec_fetcher = Gem::SpecFetcher.fetcher + + prerelease, all = all_specs.partition {|spec| spec.version.prerelease? } + latest = Gem::Specification._latest_specs all_specs + + spec_fetcher.specs[@uri] = [] + all.each do |spec| + spec_fetcher.specs[@uri] << spec.name_tuple + end + + spec_fetcher.latest_specs[@uri] = [] + latest.each do |spec| + spec_fetcher.latest_specs[@uri] << spec.name_tuple + end + + spec_fetcher.prerelease_specs[@uri] = [] + prerelease.each do |spec| + spec_fetcher.prerelease_specs[@uri] << spec.name_tuple + end + + # HACK for test_download_to_cache + unless Gem::RemoteFetcher === @fetcher + v = Gem.marshal_version + + specs = all.map {|spec| spec.name_tuple } + s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs + + latest_specs = latest.map do |spec| + spec.name_tuple + end + + l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs + + prerelease_specs = prerelease.map {|spec| spec.name_tuple } + p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs + + @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip + @fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip + @fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip + + write_marshalled_gemspecs(*all_specs) + end + + nil # force errors + end + + def write_marshalled_gemspecs(*all_specs) + v = Gem.marshal_version + + all_specs.each do |spec| + path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz" + data = Marshal.dump spec + data_deflate = Zlib::Deflate.deflate data + @fetcher.data[path] = data_deflate + end + end + + ## + # Deflates +data+ + + def util_zip(data) + Zlib::Deflate.deflate data + end + + def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil) + if Gem.instance_variables.include? :@ruby_version + Gem.send :remove_instance_variable, :@ruby_version + end + + @RUBY_VERSION = RUBY_VERSION + @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) + @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) + @RUBY_DESCRIPTION = RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) + @RUBY_ENGINE = RUBY_ENGINE + @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) + + util_clear_RUBY_VERSION + + Object.const_set :RUBY_VERSION, version + Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel + Object.const_set :RUBY_REVISION, revision if revision + Object.const_set :RUBY_DESCRIPTION, description if description + Object.const_set :RUBY_ENGINE, engine + Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version + end + + def util_restore_RUBY_VERSION + util_clear_RUBY_VERSION + + Object.const_set :RUBY_VERSION, @RUBY_VERSION + Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if + defined?(@RUBY_PATCHLEVEL) + Object.const_set :RUBY_REVISION, @RUBY_REVISION if + defined?(@RUBY_REVISION) + Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION if + defined?(@RUBY_DESCRIPTION) + Object.const_set :RUBY_ENGINE, @RUBY_ENGINE + Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if + defined?(@RUBY_ENGINE_VERSION) + end + + def util_clear_RUBY_VERSION + Object.send :remove_const, :RUBY_VERSION + Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) + Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) + Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) + Object.send :remove_const, :RUBY_ENGINE + Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) + end + + ## + # Is this test being run on a Windows platform? + + def self.win_platform? + Gem.win_platform? + end + + ## + # Is this test being run on a Windows platform? + + def win_platform? + Gem.win_platform? + end + + ## + # Is this test being run on a Java platform? + + def self.java_platform? + Gem.java_platform? + end + + ## + # Is this test being run on a Java platform? + + def java_platform? + Gem.java_platform? + end + + ## + # Returns whether or not we're on a version of Ruby built with VC++ (or + # Borland) versus Cygwin, Mingw, etc. + + def self.vc_windows? + RUBY_PLATFORM.match('mswin') + end + + ## + # Returns whether or not we're on a version of Ruby built with VC++ (or + # Borland) versus Cygwin, Mingw, etc. + + def vc_windows? + RUBY_PLATFORM.match('mswin') + end + + ## + # Returns the make command for the current platform. For versions of Ruby + # built on MS Windows with VC++ or Borland it will return 'nmake'. On all + # other platforms, including Cygwin, it will return 'make'. + + def self.make_command + ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make') + end + + ## + # Returns the make command for the current platform. For versions of Ruby + # built on MS Windows with VC++ or Borland it will return 'nmake'. On all + # other platforms, including Cygwin, it will return 'make'. + + def make_command + ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make') + end + + ## + # Returns whether or not the nmake command could be found. + + def nmake_found? + system('nmake /? 1>NUL 2>&1') + end + + # In case we're building docs in a background process, this method waits for + # that process to exit (or if it's already been reaped, or never happened, + # swallows the Errno::ECHILD error). + def wait_for_child_process_to_exit + Process.wait if Process.respond_to?(:fork) + rescue Errno::ECHILD + end + + ## + # Allows tests to use a random (but controlled) port number instead of + # a hardcoded one. This helps CI tools when running parallels builds on + # the same builder slave. + + def self.process_based_port + @@process_based_port ||= 8000 + $$ % 1000 + end + + ## + # See ::process_based_port + + def process_based_port + self.class.process_based_port + end + + ## + # Allows the proper version of +rake+ to be used for the test. + + def build_rake_in(good=true) + gem_ruby = Gem.ruby + Gem.ruby = self.class.rubybin + env_rake = ENV["rake"] + rake = (good ? @@good_rake : @@bad_rake) + ENV["rake"] = rake + yield rake + ensure + Gem.ruby = gem_ruby + if env_rake + ENV["rake"] = env_rake + else + ENV.delete("rake") + end + end + + ## + # Finds the path to the Ruby executable + + def self.rubybin + ruby = ENV["RUBY"] + return ruby if ruby + ruby = "ruby" + rubyexe = "#{ruby}.exe" + + 3.times do + if File.exist? ruby and File.executable? ruby and !File.directory? ruby + return File.expand_path(ruby) + end + if File.exist? rubyexe and File.executable? rubyexe + return File.expand_path(rubyexe) + end + ruby = File.join("..", ruby) + end + + begin + Gem.ruby + rescue LoadError + "ruby" + end + end + + def ruby_with_rubygems_in_load_path + [Gem.ruby, "-I", rubygems_path] + end + + def rubygems_path + $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) } + end + + def with_clean_path_to_ruby + orig_ruby = Gem.ruby + + Gem.instance_variable_set :@ruby, nil + + yield + ensure + Gem.instance_variable_set :@ruby, orig_ruby + end + + def with_internal_encoding(encoding) + int_enc = Encoding.default_internal + silence_warnings { Encoding.default_internal = encoding } + + yield + ensure + silence_warnings { Encoding.default_internal = int_enc } + end + + def silence_warnings + old_verbose, $VERBOSE = $VERBOSE, false + yield + ensure + $VERBOSE = old_verbose + end + + class << self + # :nodoc: + ## + # Return the join path, with escaping backticks, dollars, and + # double-quotes. Unlike `shellescape`, equal-sign is not escaped. + + private + + def escape_path(*path) + path = File.join(*path) + if %r{\A[-+:/=@,.\w]+\z} =~ path + path + else + "\"#{path.gsub(/[`$"]/, '\\&')}\"" + end + end + end + + @@good_rake = "#{rubybin} #{escape_path(__dir__, 'good_rake.rb')}" + @@bad_rake = "#{rubybin} #{escape_path(__dir__, 'bad_rake.rb')}" + + ## + # Construct a new Gem::Dependency. + + def dep(name, *requirements) + Gem::Dependency.new name, *requirements + end + + ## + # Constructs a Gem::Resolver::DependencyRequest from a + # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the + # dependency and a +parent+ DependencyRequest + + def dependency_request(dep, from_name, from_version, parent = nil) + remote = Gem::Source.new @uri + + unless parent + parent_dep = dep from_name, from_version + parent = Gem::Resolver::DependencyRequest.new parent_dep, nil + end + + spec = Gem::Resolver::IndexSpecification.new \ + nil, from_name, from_version, remote, Gem::Platform::RUBY + activation = Gem::Resolver::ActivationRequest.new spec, parent + + Gem::Resolver::DependencyRequest.new dep, activation + end + + ## + # Constructs a new Gem::Requirement. + + def req(*requirements) + return requirements.first if Gem::Requirement === requirements.first + Gem::Requirement.create requirements + end + + ## + # Constructs a new Gem::Specification. + + def spec(name, version, &block) + Gem::Specification.new name, v(version), &block + end + + ## + # Creates a SpecFetcher pre-filled with the gems or specs defined in the + # block. + # + # Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds + # a specification to the SpecFetcher while +gem+ adds both a specification + # and the gem data to the RemoteFetcher so the built gem can be downloaded. + # + # If only the a-3 gem is supposed to be downloaded you can save setup + # time by creating only specs for the other versions: + # + # spec_fetcher do |fetcher| + # fetcher.spec 'a', 1 + # fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3 + # fetcher.gem 'a', 3 do |spec| + # # spec is a Gem::Specification + # # ... + # end + # end + + def spec_fetcher(repository = @gem_repo) + Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup| + yield spec_fetcher_setup if block_given? + end + end + + ## + # Construct a new Gem::Version. + + def v(string) + Gem::Version.create string + end + + ## + # A vendor_gem is used with a gem dependencies file. The gem created here + # has no files, just a gem specification for the given +name+ and +version+. + # + # Yields the +specification+ to the block, if given + + def vendor_gem(name = 'a', version = 1) + directory = File.join 'vendor', name + + FileUtils.mkdir_p directory + + save_gemspec name, version, directory + end + + ## + # create_gemspec creates gem specification in given +directory+ or '.' + # for the given +name+ and +version+. + # + # Yields the +specification+ to the block, if given + + def save_gemspec(name = 'a', version = 1, directory = '.') + vendor_spec = Gem::Specification.new name, version do |specification| + yield specification if block_given? + end + + File.open File.join(directory, "#{name}.gemspec"), 'w' do |io| + io.write vendor_spec.to_ruby + end + + return name, vendor_spec.version, directory + end + + ## + # The StaticSet is a static set of gem specifications used for testing only. + # It is available by requiring Gem::TestCase. + + class StaticSet < Gem::Resolver::Set + ## + # A StaticSet ignores remote because it has a fixed set of gems. + + attr_accessor :remote + + ## + # Creates a new StaticSet for the given +specs+ + + def initialize(specs) + super() + + @specs = specs + + @remote = true + end + + ## + # Adds +spec+ to this set. + + def add(spec) + @specs << spec + end + + ## + # Finds +dep+ in this set. + + def find_spec(dep) + @specs.reverse_each do |s| + return s if dep.matches_spec? s + end + end + + ## + # Finds all gems matching +dep+ in this set. + + def find_all(dep) + @specs.find_all {|s| dep.match? s, @prerelease } + end + + ## + # Loads a Gem::Specification from this set which has the given +name+, + # version +ver+, +platform+. The +source+ is ignored. + + def load_spec(name, ver, platform, source) + dep = Gem::Dependency.new name, ver + spec = find_spec dep + + Gem::Specification.new spec.name, spec.version do |s| + s.platform = spec.platform + end + end + + def prefetch(reqs) # :nodoc: + end + end + + ## + # Loads certificate named +cert_name+ from test/rubygems/. + + def self.load_cert(cert_name) + cert_file = cert_path cert_name + + cert = File.read cert_file + + OpenSSL::X509::Certificate.new cert + end + + ## + # Returns the path to the certificate named +cert_name+ from + # test/rubygems/. + + def self.cert_path(cert_name) + if 32 == (Time.at(2**32) rescue 32) + cert_file = "#{__dir__}/#{cert_name}_cert_32.pem" + + return cert_file if File.exist? cert_file + end + + "#{__dir__}/#{cert_name}_cert.pem" + end + + ## + # Loads a private key named +key_name+ with +passphrase+ in test/rubygems/ + + def self.load_key(key_name, passphrase = nil) + key_file = key_path key_name + + key = File.read key_file + + OpenSSL::PKey.read key, passphrase + end + + ## + # Returns the path to the key named +key_name+ from test/rubygems + + def self.key_path(key_name) + "#{__dir__}/#{key_name}_key.pem" + end + + # :stopdoc: + # only available in RubyGems tests + + PRIVATE_KEY_PASSPHRASE = 'Foo bar'.freeze + + begin + PRIVATE_KEY = load_key 'private' + PRIVATE_KEY_PATH = key_path 'private' + + # ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE + ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE + ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private' + + PUBLIC_KEY = PRIVATE_KEY.public_key + + PUBLIC_CERT = load_cert 'public' + PUBLIC_CERT_PATH = cert_path 'public' + rescue Errno::ENOENT + PRIVATE_KEY = nil + PUBLIC_KEY = nil + PUBLIC_CERT = nil + end if Gem::HAVE_OPENSSL +end + +# https://github.com/seattlerb/minitest/blob/13c48a03d84a2a87855a4de0c959f96800100357/lib/minitest/mock.rb#L192 +class Object + def stub(name, val_or_callable, *block_args) + new_name = "__minitest_stub__#{name}" + + metaclass = class << self; self; end + + if respond_to? name and not methods.map(&:to_s).include? name.to_s + metaclass.send :define_method, name do |*args| + super(*args) + end + end + + metaclass.send :alias_method, new_name, name + + metaclass.send :define_method, name do |*args, &blk| + if val_or_callable.respond_to? :call + val_or_callable.call(*args, &blk) + else + blk.call(*block_args) if blk + val_or_callable + end + end + + metaclass.send(:ruby2_keywords, name) if metaclass.respond_to?(:ruby2_keywords, true) + + yield self + ensure + metaclass.send :undef_method, name + metaclass.send :alias_method, name, new_name + metaclass.send :undef_method, new_name + end unless method_defined?(:stub) # lib/resolv/test_dns.rb also has the same method definition +end + +require_relative 'utilities' diff --git a/ruby/lib/rubygems/installer_test_case.rb b/ruby/test/rubygems/installer_test_case.rb similarity index 83% rename from ruby/lib/rubygems/installer_test_case.rb rename to ruby/test/rubygems/installer_test_case.rb index f48466d3e..824ac53a8 100644 --- a/ruby/lib/rubygems/installer_test_case.rb +++ b/ruby/test/rubygems/installer_test_case.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/installer' class Gem::Installer - ## # Available through requiring rubygems/installer_test_case @@ -58,14 +57,12 @@ class Gem::Installer # Available through requiring rubygems/installer_test_case attr_writer :wrappers - end ## # A test case for Gem::Installer. class Gem::InstallerTestCase < Gem::TestCase - def setup super @@ -111,9 +108,9 @@ def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby", bindir = "bin") # # And returns a Gem::Installer for the @spec that installs into @gemhome - def setup_base_installer + def setup_base_installer(force = true) @gem = setup_base_gem - util_installer @spec, @gemhome + util_installer @spec, @gemhome, false, force end ## @@ -171,10 +168,10 @@ def setup_base_user_installer ## # Sets up the base @gem, builds it and returns an installer for it. # - def util_setup_installer + def util_setup_installer(&block) @gem = setup_base_gem - util_setup_gem + util_setup_gem(&block) end ## @@ -185,7 +182,7 @@ def util_setup_installer # lib/code.rb # ext/a/mkrf_conf.rb - def util_setup_gem(ui = @ui) + def util_setup_gem(ui = @ui, force = true) @spec.files << File.join('lib', 'code.rb') @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb') @@ -217,17 +214,34 @@ def util_setup_gem(ui = @ui) end end - Gem::Installer.at @gem + Gem::Installer.at @gem, :force => force end ## # Creates an installer for +spec+ that will install into +gem_home+. If # +user+ is true a user-install will be performed. - def util_installer(spec, gem_home, user=false) + def util_installer(spec, gem_home, user=false, force=true) Gem::Installer.at(spec.cache_file, :install_dir => gem_home, - :user_install => user) + :user_install => user, + :force => force) end + @@symlink_supported = nil + + # This is needed for Windows environment without symlink support enabled (the default + # for non admin) to be able to skip test for features using symlinks. + def symlink_supported? + if @@symlink_supported.nil? + begin + File.symlink("", "") + rescue Errno::ENOENT, Errno::EEXIST + @@symlink_supported = true + rescue NotImplementedError, SystemCallError + @@symlink_supported = false + end + end + @@symlink_supported + end end diff --git a/ruby/lib/rubygems/package/tar_test_case.rb b/ruby/test/rubygems/package/tar_test_case.rb similarity index 95% rename from ruby/lib/rubygems/package/tar_test_case.rb rename to ruby/test/rubygems/package/tar_test_case.rb index 75978c8ed..99f503a23 100644 --- a/ruby/lib/rubygems/package/tar_test_case.rb +++ b/ruby/test/rubygems/package/tar_test_case.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative '../helper' require 'rubygems/package' ## # A test case for Gem::Package::Tar* classes class Gem::Package::TarTestCase < Gem::TestCase - def ASCIIZ(str, length) str + "\0" * (length - str.length) end @@ -68,7 +67,7 @@ def assert_headers_equal(expected, actual) end def calc_checksum(header) - sum = header.unpack("C*").inject{|s,a| s + a} + sum = header.unpack("C*").inject{|s,a| s + a } SP(Z(to_oct(sum, 6))) end @@ -91,7 +90,7 @@ def header(type, fname, dname, length, mode, mtime, checksum = nil, linkname = " ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null - ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled) + ASCIIZ(dname, 155), # char prefix[155]; ASCII + (Z unless filled) ] h = arr.join @@ -137,5 +136,4 @@ def util_dir_entry def util_symlink_entry util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link") end - end diff --git a/ruby/test/rubygems/packages/ascii_binder-0.1.10.1.gem b/ruby/test/rubygems/packages/ascii_binder-0.1.10.1.gem new file mode 100644 index 000000000..19c505395 Binary files /dev/null and b/ruby/test/rubygems/packages/ascii_binder-0.1.10.1.gem differ diff --git a/ruby/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem b/ruby/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem new file mode 100644 index 000000000..58a13535c Binary files /dev/null and b/ruby/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem differ diff --git a/ruby/test/rubygems/plugin/load/rubygems_plugin.rb b/ruby/test/rubygems/plugin/load/rubygems_plugin.rb index 85a6851ac..7cc6bef90 100644 --- a/ruby/test/rubygems/plugin/load/rubygems_plugin.rb +++ b/ruby/test/rubygems/plugin/load/rubygems_plugin.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true class TestGem - TEST_PLUGIN_LOAD = :loaded - end diff --git a/ruby/test/rubygems/private_ec_key.pem b/ruby/test/rubygems/private_ec_key.pem new file mode 100644 index 000000000..5d855d0df --- /dev/null +++ b/ruby/test/rubygems/private_ec_key.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,4107F98A374CB8EC18F1AA4EA4B6A0DB + +BRklFxJGcz7gqQYxek8TZkt8qbPhB0FSR6nyw3SYuio/2tlT9ohs74mlK3EbG9Lt +Y4OquJbksBFmoB7fIoM4vnuIZ0Eoz2ooxn9tjhBtqJ3mVscYXwZmA3UDUWDMlviQ +Fu37OpikQv4TFA1jlmUK0LM8xmUCfUeLl0kHD17lFsz2gkO2kwg8mn/YUMOIaDOu +EnnmxbAwnZBpemQkQfpTt2mYL9gu3CcMt5gokBuGDxY= +-----END EC PRIVATE KEY----- diff --git a/ruby/test/rubygems/rubygems/commands/crash_command.rb b/ruby/test/rubygems/rubygems/commands/crash_command.rb index a27a79f8d..9155360e7 100644 --- a/ruby/test/rubygems/rubygems/commands/crash_command.rb +++ b/ruby/test/rubygems/rubygems/commands/crash_command.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true class Gem::Commands::CrashCommand < Gem::Command - raise "crash" - end diff --git a/ruby/test/rubygems/rubygems_plugin.rb b/ruby/test/rubygems/rubygems_plugin.rb index 7fac2ebec..2dc783690 100644 --- a/ruby/test/rubygems/rubygems_plugin.rb +++ b/ruby/test/rubygems/rubygems_plugin.rb @@ -11,7 +11,6 @@ module Gem::Commands end class Gem::Commands::InterruptCommand < Gem::Command - def initialize super('interrupt', 'Raises an Interrupt Exception', {}) end @@ -19,7 +18,6 @@ def initialize def execute raise Interrupt, "Interrupt exception" end - end Gem::CommandManager.instance.register_command :interrupt diff --git a/ruby/test/rubygems/specifications/bar-0.0.2.gemspec b/ruby/test/rubygems/specifications/bar-0.0.2.gemspec index ceefa4ed1..37b6ea45d 100644 --- a/ruby/test/rubygems/specifications/bar-0.0.2.gemspec +++ b/ruby/test/rubygems/specifications/bar-0.0.2.gemspec @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - Gem::Specification.new do |s| s.name = "bar" s.version = "0.0.2" diff --git a/ruby/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/ruby/test/rubygems/specifications/rubyforge-0.0.1.gemspec new file mode 100644 index 000000000..c760a4207 --- /dev/null +++ b/ruby/test/rubygems/specifications/rubyforge-0.0.1.gemspec @@ -0,0 +1,12 @@ +Gem::Specification.new do |s| + s.name = "rubyforge" + s.version = "0.0.1" + s.platform = "ruby" + s.require_paths = ["lib"] + s.summary = "A very bar gem" + s.authors = ["unknown"] + s.license = 'MIT' + s.homepage = 'http://example.com' + s.files = ['README.md'] + s.rubyforge_project = 'abc' +end diff --git a/ruby/test/rubygems/test_bundled_ca.rb b/ruby/test/rubygems/test_bundled_ca.rb index ad66f3e61..fff5904ab 100644 --- a/ruby/test/rubygems/test_bundled_ca.rb +++ b/ruby/test/rubygems/test_bundled_ca.rb @@ -1,6 +1,12 @@ # frozen_string_literal: true -require 'rubygems/test_case' -require 'net/https' +require_relative 'helper' +require 'net/http' +require 'rubygems/openssl' + +unless Gem::HAVE_OPENSSL + warn 'Skipping bundled certificates tests. openssl not found.' +end + require 'rubygems/request' # = Testing Bundled CA @@ -8,56 +14,47 @@ # The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9 # -if ENV["CI"] || ENV["TEST_SSL"] - class TestBundledCA < Gem::TestCase - - THIS_FILE = File.expand_path __FILE__ - - def bundled_certificate_store - store = OpenSSL::X509::Store.new +class TestBundledCA < Gem::TestCase + def bundled_certificate_store + store = OpenSSL::X509::Store.new - ssl_cert_glob = - File.expand_path '../../../lib/rubygems/ssl_certs/*/*.pem', THIS_FILE - - Dir[ssl_cert_glob].each do |ssl_cert| - store.add_file ssl_cert - end - - store + Gem::Request.get_cert_files.each do |ssl_cert| + store.add_file ssl_cert end - def assert_https(host) - if self.respond_to? :_assertions # minitest <= 4 - self._assertions += 1 - else # minitest >= 5 - self.assertions += 1 - end - http = Net::HTTP.new(host, 443) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_PEER - http.cert_store = bundled_certificate_store - http.get('/') - rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError - skip "#{host} seems offline, I can't tell whether ssl would work." - rescue OpenSSL::SSL::SSLError => e - # Only fail for certificate verification errors - if e.message =~ /certificate verify failed/ - flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}" - end - raise - end + store + end - def test_accessing_rubygems - assert_https('rubygems.org') + def assert_https(host) + assert true + http = Net::HTTP.new(host, 443) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + http.cert_store = bundled_certificate_store + http.get('/') + rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError + pend "#{host} seems offline, I can't tell whether ssl would work." + rescue OpenSSL::SSL::SSLError => e + # Only fail for certificate verification errors + if e.message =~ /certificate verify failed/ + flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}" end + raise + end - def test_accessing_fastly - assert_https('rubygems.global.ssl.fastly.net') - end + def test_accessing_rubygems + assert_https('rubygems.org') + end - def test_accessing_new_index - assert_https('fastly.rubygems.org') - end + def test_accessing_www_rubygems + assert_https('www.rubygems.org') + end + def test_accessing_staging + assert_https('staging.rubygems.org') end -end + + def test_accessing_new_index + assert_https('index.rubygems.org') + end +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_config.rb b/ruby/test/rubygems/test_config.rb index 70fc4e23f..fff539c81 100644 --- a/ruby/test/rubygems/test_config.rb +++ b/ruby/test/rubygems/test_config.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' require 'shellwords' class TestConfig < Gem::TestCase - def test_datadir util_make_gems spec = Gem::Specification.find_by_name("a") @@ -13,17 +12,16 @@ def test_datadir end def test_good_rake_path_is_escaped - path = Gem::TestCase.class_eval('@@good_rake') + path = Gem::TestCase.class_variable_get(:@@good_rake) ruby, rake = path.shellsplit assert_equal(Gem.ruby, ruby) assert_match(/\/good_rake.rb\z/, rake) end def test_bad_rake_path_is_escaped - path = Gem::TestCase.class_eval('@@bad_rake') + path = Gem::TestCase.class_variable_get(:@@bad_rake) ruby, rake = path.shellsplit assert_equal(Gem.ruby, ruby) assert_match(/\/bad_rake.rb\z/, rake) end - end diff --git a/ruby/test/rubygems/test_deprecate.rb b/ruby/test/rubygems/test_deprecate.rb index b92bd1c3d..a619eccb3 100644 --- a/ruby/test/rubygems/test_deprecate.rb +++ b/ruby/test/rubygems/test_deprecate.rb @@ -1,15 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' -# require 'rubygems/builder' -# require 'rubygems/package' +require_relative 'helper' require 'rubygems/deprecate' class TestDeprecate < Gem::TestCase - def setup super - # Gem::Deprecate.saved_warnings.clear @original_skip = Gem::Deprecate.skip Gem::Deprecate.skip = false end @@ -17,7 +13,6 @@ def setup def teardown super - # Gem::Deprecate.saved_warnings.clear Gem::Deprecate.skip = @original_skip end @@ -45,7 +40,34 @@ def test_skip end class Thing + extend Gem::Deprecate + attr_accessor :message + def foo + @message = "foo" + end + def bar + @message = "bar" + end + rubygems_deprecate :foo, :bar + + def foo_arg(msg) + @message = "foo" + msg + end + def bar_arg(msg) + @message = "bar" + msg + end + rubygems_deprecate :foo_arg, :bar_arg + + def foo_kwarg(message:) + @message = "foo" + message + end + def bar_kwarg(message:) + @message = "bar" + message + end + rubygems_deprecate :foo_kwarg, :bar_kwarg + end + class OtherThing extend Gem::Deprecate attr_accessor :message def foo @@ -56,25 +78,80 @@ def bar end deprecate :foo, :bar, 2099, 3 + def foo_arg(msg) + @message = "foo" + msg + end + def bar_arg(msg) + @message = "bar" + msg + end + deprecate :foo_arg, :bar_arg, 2099, 3 + + def foo_kwarg(message:) + @message = "foo" + message + end + def bar_kwarg(message:) + @message = "bar" + message + end + deprecate :foo_kwarg, :bar_kwarg, 2099, 3 end def test_deprecated_method_calls_the_old_method - capture_io do + capture_output do thing = Thing.new thing.foo assert_equal "foo", thing.message + thing.foo_arg("msg") + assert_equal "foomsg", thing.message + thing.foo_kwarg(message: "msg") + assert_equal "foomsg", thing.message end end def test_deprecated_method_outputs_a_warning - out, err = capture_io do + out, err = capture_output do thing = Thing.new thing.foo + thing.foo_arg("msg") + thing.foo_kwarg(message: "msg") end assert_equal "", out assert_match(/Thing#foo is deprecated; use bar instead\./, err) - assert_match(/on or after 2099-03-01/, err) + assert_match(/Thing#foo_arg is deprecated; use bar_arg instead\./, err) + assert_match(/Thing#foo_kwarg is deprecated; use bar_kwarg instead\./, err) + assert_match(/in Rubygems [0-9]+/, err) + end + + def test_rubygems_deprecate_command + require 'rubygems/command' + foo_command = Class.new(Gem::Command) do + extend Gem::Deprecate + + rubygems_deprecate_command + + def execute + puts "pew pew!" + end + end + + Gem::Commands.send(:const_set, :FooCommand, foo_command) + assert Gem::Commands::FooCommand.new("foo").deprecated? + ensure + Gem::Commands.send(:remove_const, :FooCommand) end + def test_deprecated_method_outputs_a_warning_old_way + out, err = capture_output do + thing = OtherThing.new + thing.foo + thing.foo_arg("msg") + thing.foo_kwarg(message: "msg") + end + + assert_equal "", out + assert_match(/OtherThing#foo is deprecated; use bar instead\./, err) + assert_match(/OtherThing#foo_arg is deprecated; use bar_arg instead\./, err) + assert_match(/OtherThing#foo_kwarg is deprecated; use bar_kwarg instead\./, err) + assert_match(/on or after 2099-03/, err) + end end diff --git a/ruby/test/rubygems/test_exit.rb b/ruby/test/rubygems/test_exit.rb new file mode 100644 index 000000000..9557fe5d0 --- /dev/null +++ b/ruby/test/rubygems/test_exit.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'helper' +require 'rubygems' + +class TestExit < Gem::TestCase + def test_exit + system(*ruby_with_rubygems_in_load_path, "-e", "raise Gem::SystemExitException.new(2)") + assert_equal 2, $?.exitstatus + end +end diff --git a/ruby/test/rubygems/test_gem.rb b/ruby/test/rubygems/test_gem.rb index 6d223b7d6..cc4772a0c 100644 --- a/ruby/test/rubygems/test_gem.rb +++ b/ruby/test/rubygems/test_gem.rb @@ -1,5 +1,5 @@ # coding: US-ASCII -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' require 'rubygems/command' require 'rubygems/installer' @@ -7,18 +7,7 @@ require 'tmpdir' require 'rbconfig' -if File.exist?(File.join(Dir.tmpdir, "Gemfile")) - raise "rubygems/bundler tests do not work correctly if there is #{ File.join(Dir.tmpdir, "Gemfile") }" -end - -# TODO: push this up to test_case.rb once battle tested - -$LOAD_PATH.map! do |path| - path.dup.tap(&Gem::UNTAINT) -end - class TestGem < Gem::TestCase - PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT) @@ -30,79 +19,72 @@ def setup common_installer_setup - ENV.delete 'RUBYGEMS_GEMDEPS' - @additional = %w[a b].map { |d| File.join @tempdir, d } + @additional = %w[a b].map {|d| File.join @tempdir, d } util_remove_interrupt_command end def test_self_finish_resolve - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate + a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + assert_equal [], unresolved_names end def test_self_finish_resolve_wtf - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this - b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = util_spec "c", "1" # this - c2 = util_spec "c", "2" - d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = util_spec "c", "1" # this + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this - install_specs c1, c2, b1, b2, d1, d2, a1 + install_specs c1, c2, b1, b2, d1, d2, a1 - a1.activate + a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)", "d (> 0)"], unresolved_names + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)", "d (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w(a-1 b-1 c-1 d-2), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names + assert_equal [], unresolved_names end def test_self_finish_resolve_respects_loaded_specs - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate - c1.activate + a1.activate + c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + assert_equal %w[a-1 c-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w(a-1 b-1 c-1), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-1 c-1], loaded_spec_names + assert_equal [], unresolved_names end def test_self_install @@ -115,9 +97,9 @@ def test_self_install installed = Gem.install 'a', '= 1', :install_dir => gemhome2 - assert_equal %w[a-1], installed.map { |spec| spec.full_name } + assert_equal %w[a-1], installed.map {|spec| spec.full_name } - assert_path_exists File.join(gemhome2, 'gems', 'a-1') + assert_path_exist File.join(gemhome2, 'gems', 'a-1') end def test_self_install_in_rescue @@ -134,7 +116,7 @@ def test_self_install_in_rescue rescue StandardError Gem.install 'a', '= 1', :install_dir => gemhome2 end - assert_equal %w[a-1], installed.map { |spec| spec.full_name } + assert_equal %w[a-1], installed.map {|spec| spec.full_name } end def test_self_install_permissions @@ -161,10 +143,8 @@ def test_self_install_permissions_with_format_executable def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name Gem::Installer.exec_format = nil - with_clean_path_to_ruby do - ruby_install_name 'ruby27' do - assert_self_install_permissions(format_executable: true) - end + ruby_install_name 'ruby27' do + assert_self_install_permissions(format_executable: true) end ensure Gem::Installer.exec_format = nil @@ -177,7 +157,7 @@ def assert_self_install_permissions(format_executable: false) :prog_mode => win_platform? ? 0410 : 0510, :data_mode => 0640, :wrappers => true, - :format_executable => format_executable + :format_executable => format_executable, } Dir.chdir @tempdir do Dir.mkdir 'bin' @@ -220,29 +200,25 @@ def assert_self_install_permissions(format_executable: false) end assert_equal(expected, result) ensure - File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT)}) + File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT) }) end def test_require_missing - save_loaded_features do - assert_raises ::LoadError do - require "test_require_missing" - end + assert_raise ::LoadError do + require "test_require_missing" end end def test_require_does_not_glob - save_loaded_features do - a1 = util_spec "a", "1", nil, "lib/a1.rb" + a1 = util_spec "a", "1", nil, "lib/a1.rb" - install_specs a1 + install_specs a1 - assert_raises ::LoadError do - require "a*" - end - - assert_equal [], loaded_spec_names + assert_raise ::LoadError do + require "a*" end + + assert_equal [], loaded_spec_names end def test_self_bin_path_active @@ -274,7 +250,7 @@ def test_self_bin_path_picking_newest end def test_self_activate_bin_path_no_exec_name - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.activate_bin_path 'a' end @@ -307,42 +283,75 @@ def test_activate_bin_path_resolves_eagerly gem 'c' Gem.finish_resolve - assert_equal %w(a-1 b-2 c-1), loaded_spec_names + assert_equal %w[a-1 b-2 c-1], loaded_spec_names end - def test_activate_bin_path_gives_proper_error_for_bundler - bundler = util_spec 'bundler', '2' do |s| - s.executables = ['bundle'] + def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + s.add_dependency 'b' end - install_specs bundler + b1 = util_spec 'b', '1' do |s| + s.add_dependency 'c', '1' + end - File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") - GEM - remote: https://rubygems.org/ - specs: + b2 = util_spec 'b', '2' do |s| + s.add_dependency 'c', '2' + end - PLATFORMS - ruby + c2 = util_spec 'c', '2' - DEPENDENCIES + install_specs c2, b1, b2, a1 - BUNDLED WITH - 9999 - L + # c1 is missing, but not needed for activation, so we should not get any errors here + + Gem.activate_bin_path("a", "exec", ">= 0") + + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + end + + def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + s.add_dependency 'b' end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + b1 = util_spec 'b', '1' do |s| + s.add_dependency 'c', '1' + end - e = assert_raises Gem::GemNotFoundException do - load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") + b2 = util_spec 'b', '2' do |s| + s.add_dependency 'c', '2' end - assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." - assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." - assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" - refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" + c1 = util_spec 'c', '1' + + install_specs c1, b1, b2, a1 + + # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency + + e = assert_raise Gem::UnsatisfiableDependencyError do + load Gem.activate_bin_path("a", "exec", ">= 0") + end + + assert_equal "Unable to resolve dependency: 'b (>= 0)' requires 'c (= 2)'", e.message + end + + def test_activate_bin_path_in_debug_mode + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + end + + install_specs a1 + + require "open3" + output, status = Open3.capture2e( + { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, + *ruby_with_rubygems_in_load_path, "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" + ) + + assert status.success?, output end def test_activate_bin_path_selects_exact_bundler_version_if_present @@ -372,11 +381,11 @@ def test_activate_bin_path_selects_exact_bundler_version_if_present L end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") - assert_equal %w(bundler-2.0.0), loaded_spec_names + assert_equal %w[bundler-2.0.0], loaded_spec_names end def test_activate_bin_path_respects_underscore_selection_if_given @@ -406,15 +415,41 @@ def test_activate_bin_path_respects_underscore_selection_if_given L end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3") - assert_equal %w(bundler-1.17.3), loaded_spec_names + assert_equal %w[bundler-1.17.3], loaded_spec_names + end + + def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 2.1.4 + L + end + + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } + + e = assert_raise Gem::GemNotFoundException do + load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8") + end + + assert_equal "can't find gem bundler (= 2.2.8) with executable bundle", e.message end def test_self_bin_path_no_exec_name - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.bin_path 'a' end @@ -435,20 +470,20 @@ def test_self_bin_path_nonexistent_binfile util_spec 'a', '2' do |s| s.executables = ['exec'] end - assert_raises(Gem::GemNotFoundException) do + assert_raise(Gem::GemNotFoundException) do Gem.bin_path('a', 'other', '2') end end def test_self_bin_path_no_bin_file util_spec 'a', '1' - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do Gem.bin_path('a', nil, '1') end end def test_self_bin_path_not_found - assert_raises(Gem::GemNotFoundException) do + assert_raise(Gem::GemNotFoundException) do Gem.bin_path('non-existent', 'blah') end end @@ -459,7 +494,6 @@ def test_self_bin_path_bin_file_gone_in_latest s.executables = [] end install_specs spec - # Should not find a-10's non-abin (bug) assert_equal @abin_path, Gem.bin_path('a', 'abin') end @@ -515,7 +549,7 @@ def test_self_datadir end def test_self_datadir_nonexistent_package - assert_raises(Gem::MissingSpecError) do + assert_raise(Gem::MissingSpecError) do Gem::Specification.find_by_name("xyzzy").datadir end end @@ -583,22 +617,22 @@ def test_self_default_sources end def test_self_use_gemdeps - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + with_rubygems_gemdeps('-') do + FileUtils.mkdir_p 'detect/a/b' + FileUtils.mkdir_p 'detect/a/Isolate' - FileUtils.mkdir_p 'detect/a/b' - FileUtils.mkdir_p 'detect/a/Isolate' + FileUtils.touch 'detect/Isolate' - FileUtils.touch 'detect/Isolate' + begin + Dir.chdir 'detect/a/b' - begin - Dir.chdir 'detect/a/b' + Gem.use_gemdeps - assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name) - ensure - Dir.chdir @tempdir + assert_equal add_bundler_full_name([]), loaded_spec_names + ensure + Dir.chdir @tempdir + end end - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_self_dir @@ -611,12 +645,12 @@ def test_self_ensure_gem_directories Gem.ensure_gem_subdirectories @gemhome - assert_path_exists File.join @gemhome, 'build_info' - assert_path_exists File.join @gemhome, 'cache' - assert_path_exists File.join @gemhome, 'doc' - assert_path_exists File.join @gemhome, 'extensions' - assert_path_exists File.join @gemhome, 'gems' - assert_path_exists File.join @gemhome, 'specifications' + assert_path_exist File.join @gemhome, 'build_info' + assert_path_exist File.join @gemhome, 'cache' + assert_path_exist File.join @gemhome, 'doc' + assert_path_exist File.join @gemhome, 'extensions' + assert_path_exist File.join @gemhome, 'gems' + assert_path_exist File.join @gemhome, 'specifications' end def test_self_ensure_gem_directories_permissions @@ -657,7 +691,7 @@ def test_self_ensure_gem_directories_missing_parents assert_directory_exists util_cache_dir end - unless win_platform? || Process.uid.zero? # only for FS that support write protection + unless win_platform? || Process.uid.zero? # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil @@ -689,6 +723,11 @@ def test_self_ensure_gem_directories_write_protected_parents ensure FileUtils.chmod 0600, parent end + + def test_self_ensure_gem_directories_non_existent_paths + Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise + Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario + end end def test_self_extension_dir_shared @@ -709,7 +748,7 @@ def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, foo2 = %w(1 2).map do |version| + foo1, foo2 = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -741,7 +780,7 @@ def test_self_find_files_with_gemfile discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, _ = %w(1 2).map do |version| + foo1, _ = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -762,7 +801,7 @@ def test_self_find_files_with_gemfile expected = [ File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), - File.join(foo1.full_gem_path, discover_path) + File.join(foo1.full_gem_path, discover_path), ].sort assert_equal expected, Gem.find_files('sff/discover').sort @@ -777,7 +816,7 @@ def test_self_find_latest_files discover_path = File.join 'lib', 'sff', 'discover.rb' - _, foo2 = %w(1 2).map do |version| + _, foo2 = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -814,6 +853,27 @@ def test_self_latest_spec_for assert_equal gems['a-2'], spec end + def test_self_latest_spec_for_multiple_sources + uri = 'https://example.sample.com/' + source = Gem::Source.new(uri) + source_list = Gem::SourceList.new + source_list << Gem::Source.new(@uri) + source_list << source + Gem.sources.replace source_list + + spec_fetcher(uri) do |fetcher| + fetcher.spec 'a', 1.1 + end + + gems = spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + fetcher.spec 'a', '3.a' + fetcher.spec 'a', 2 + end + spec = Gem.latest_spec_for 'a' + assert_equal gems['a-2'], spec + end + def test_self_latest_rubygems_version spec_fetcher do |fetcher| fetcher.spec 'rubygems-update', '1.8.23' @@ -838,6 +898,29 @@ def test_self_latest_version_for assert_equal Gem::Version.new(2), version end + def test_self_latest_version_for_multiple_sources + uri = 'https://example.sample.com/' + source = Gem::Source.new(uri) + source_list = Gem::SourceList.new + source_list << Gem::Source.new(@uri) + source_list << source + Gem.sources.replace source_list + + spec_fetcher(uri) do |fetcher| + fetcher.spec 'a', 1.1 + end + + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + fetcher.spec 'a', 2 + fetcher.spec 'a', '3.a' + end + + version = Gem.latest_version_for 'a' + + assert_equal Gem::Version.new(2), version + end + def test_self_loaded_specs foo = util_spec 'foo' install_gem foo @@ -847,56 +930,17 @@ def test_self_loaded_specs assert_equal true, Gem.loaded_specs.keys.include?('foo') end - def util_path - ENV.delete "GEM_HOME" - ENV.delete "GEM_PATH" - end - def test_self_path assert_equal [Gem.dir], Gem.path end def test_self_path_default - util_path - - if defined?(APPLE_GEM_HOME) - orig_APPLE_GEM_HOME = APPLE_GEM_HOME - Object.send :remove_const, :APPLE_GEM_HOME - end + ENV.delete "GEM_HOME" + ENV.delete "GEM_PATH" Gem.instance_variable_set :@paths, nil assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path - ensure - Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME if orig_APPLE_GEM_HOME - end - - unless win_platform? - def test_self_path_APPLE_GEM_HOME - util_path - - Gem.clear_paths - apple_gem_home = File.join @tempdir, 'apple_gem_home' - - old, $-w = $-w, nil - Object.const_set :APPLE_GEM_HOME, apple_gem_home - $-w = old - - assert_includes Gem.path, apple_gem_home - ensure - Object.send :remove_const, :APPLE_GEM_HOME - end - - def test_self_path_APPLE_GEM_HOME_GEM_PATH - Gem.clear_paths - ENV['GEM_PATH'] = @gemhome - apple_gem_home = File.join @tempdir, 'apple_gem_home' - Gem.const_set :APPLE_GEM_HOME, apple_gem_home - - refute Gem.path.include?(apple_gem_home) - ensure - Gem.send :remove_const, :APPLE_GEM_HOME - end end def test_self_path_ENV_PATH @@ -972,7 +1016,7 @@ def test_self_read_binary assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a - skip 'chmod not supported' if Gem.win_platform? + pend 'chmod not supported' if Gem.win_platform? begin File.chmod 0444, 'test' @@ -1017,7 +1061,7 @@ def test_self_refresh_keeps_loaded_specs_activated Gem.refresh - Gem::Specification.each{|spec| assert spec.activated? if spec == s} + Gem::Specification.each{|spec| assert spec.activated? if spec == s } Gem.loaded_specs.delete(s) Gem.refresh @@ -1025,20 +1069,16 @@ def test_self_refresh_keeps_loaded_specs_activated def test_self_ruby_escaping_spaces_in_path with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby - end + with_rb_config_ruby("C:/Ruby 1.8/bin/ruby.exe") do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby end end end def test_self_ruby_path_without_spaces with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby - end + with_rb_config_ruby("C:/Ruby18/bin/ruby.exe") do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby end end end @@ -1062,7 +1102,7 @@ def test_self_env_requirement assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo') assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr') - assert_raises(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } + assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } assert_equal Gem::Requirement.default, Gem.env_requirement('qux') end @@ -1090,7 +1130,7 @@ def test_self_ruby_version_with_non_mri_implementations util_restore_RUBY_VERSION end - def test_self_ruby_version_with_prerelease + def test_self_ruby_version_with_svn_prerelease util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version @@ -1098,6 +1138,14 @@ def test_self_ruby_version_with_prerelease util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_prerelease + util_set_RUBY_VERSION '2.7.0', -1, 'b563439274a402e33541f5695b1bfd4ac1085638', 'ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.preview3'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0' @@ -1106,7 +1154,7 @@ def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compa util_restore_RUBY_VERSION end - def test_self_ruby_version_with_trunk + def test_self_ruby_version_with_svn_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version @@ -1114,6 +1162,14 @@ def test_self_ruby_version_with_trunk util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_master + util_set_RUBY_VERSION '2.7.0', -1, '5de284ec78220e75643f89b454ce999da0c1c195', 'ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.dev'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_rubygems_version assert_equal Gem::Version.new(Gem::VERSION), Gem.rubygems_version end @@ -1147,7 +1203,7 @@ def test_self_paths_eq_nonexistent_home def test_self_post_build assert_equal 1, Gem.post_build_hooks.length - Gem.post_build { |installer| } + Gem.post_build {|installer| } assert_equal 2, Gem.post_build_hooks.length end @@ -1155,7 +1211,7 @@ def test_self_post_build def test_self_post_install assert_equal 1, Gem.post_install_hooks.length - Gem.post_install { |installer| } + Gem.post_install {|installer| } assert_equal 2, Gem.post_install_hooks.length end @@ -1163,7 +1219,7 @@ def test_self_post_install def test_self_done_installing assert_empty Gem.done_installing_hooks - Gem.done_installing { |gems| } + Gem.done_installing {|gems| } assert_equal 1, Gem.done_installing_hooks.length end @@ -1171,7 +1227,7 @@ def test_self_done_installing def test_self_post_reset assert_empty Gem.post_reset_hooks - Gem.post_reset { } + Gem.post_reset {} assert_equal 1, Gem.post_reset_hooks.length end @@ -1179,7 +1235,7 @@ def test_self_post_reset def test_self_post_uninstall assert_equal 1, Gem.post_uninstall_hooks.length - Gem.post_uninstall { |installer| } + Gem.post_uninstall {|installer| } assert_equal 2, Gem.post_uninstall_hooks.length end @@ -1187,7 +1243,7 @@ def test_self_post_uninstall def test_self_pre_install assert_equal 1, Gem.pre_install_hooks.length - Gem.pre_install { |installer| } + Gem.pre_install {|installer| } assert_equal 2, Gem.pre_install_hooks.length end @@ -1195,7 +1251,7 @@ def test_self_pre_install def test_self_pre_reset assert_empty Gem.pre_reset_hooks - Gem.pre_reset { } + Gem.pre_reset {} assert_equal 1, Gem.pre_reset_hooks.length end @@ -1203,7 +1259,7 @@ def test_self_pre_reset def test_self_pre_uninstall assert_equal 1, Gem.pre_uninstall_hooks.length - Gem.pre_uninstall { |installer| } + Gem.pre_uninstall {|installer| } assert_equal 2, Gem.pre_uninstall_hooks.length end @@ -1232,7 +1288,7 @@ def test_spec_order_is_consistent install_specs b1, b2, b3 - specs1 = Gem::Specification.stubs.find_all { |s| s.name == 'b' } + specs1 = Gem::Specification.stubs.find_all {|s| s.name == 'b' } Gem::Specification.reset specs2 = Gem::Specification.stubs_for('b') assert_equal specs1.map(&:version), specs2.map(&:version) @@ -1251,11 +1307,12 @@ def test_self_try_activate_missing_dep io.puts '# a_file.rb' end - e = assert_raises Gem::MissingSpecError do + e = assert_raise Gem::MissingSpecError do Gem.try_activate 'a_file' end - assert_match %r%Could not find 'b' %, e.message + assert_match %r{Could not find 'b' }, e.message + assert_match %r{at: #{a.spec_file}}, e.message end def test_self_try_activate_missing_prerelease @@ -1271,11 +1328,11 @@ def test_self_try_activate_missing_prerelease io.puts '# a_file.rb' end - e = assert_raises Gem::MissingSpecError do + e = assert_raise Gem::MissingSpecError do Gem.try_activate 'a_file' end - assert_match %r%Could not find 'b' \(= 1.0rc1\)%, e.message + assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message end def test_self_try_activate_missing_extensions @@ -1290,7 +1347,7 @@ def test_self_try_activate_missing_extensions io.write spec.to_ruby_for_cache end - _, err = capture_io do + _, err = capture_output do refute Gem.try_activate 'nonexistent' end @@ -1315,7 +1372,7 @@ def test_self_use_paths_with_nils end def test_setting_paths_does_not_warn_about_unknown_keys - stdout, stderr = capture_io do + stdout, stderr = capture_output do Gem.paths = { 'foo' => [], 'bar' => Object.new, 'GEM_HOME' => Gem.paths.home, @@ -1333,7 +1390,7 @@ def test_setting_paths_does_not_mutate_parameter_object end def test_deprecated_paths= - stdout, stderr = capture_io do + stdout, stderr = capture_output do Gem.paths = { 'GEM_HOME' => Gem.paths.home, 'GEM_PATH' => [Gem.paths.home, 'foo'] } end @@ -1355,6 +1412,8 @@ def test_self_user_dir parts = [@userhome, '.gem', Gem.ruby_engine] parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? + FileUtils.mkdir_p File.join(parts) + assert_equal File.join(parts), Gem.user_dir end @@ -1378,30 +1437,28 @@ def test_self_needs r.gem "b", "= 1" end - activated = Gem::Specification.map { |x| x.full_name } + activated = Gem::Specification.map {|x| x.full_name } - assert_equal %w!a-1 b-1 c-2!, activated.sort + assert_equal %w[a-1 b-1 c-2], activated.sort end def test_self_needs_picks_up_unresolved_deps - save_loaded_features do - a = util_spec "a", "1" - b = util_spec "b", "1", "c" => nil - c = util_spec "c", "2" - d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" - e = util_spec "e", "1" - - install_specs a, c, b, e, d + a = util_spec "a", "1" + b = util_spec "b", "1", "c" => nil + c = util_spec "c", "2" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" + e = util_spec "e", "1" - Gem.needs do |r| - r.gem "a" - r.gem "b", "= 1" + install_specs a, c, b, e, d - require "d#{$$}" - end + Gem.needs do |r| + r.gem "a" + r.gem "b", "= 1" - assert_equal %w!a-1 b-1 c-2 d-1 e-1!, loaded_spec_names + require "d#{$$}" end + + assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names end def test_self_gunzip @@ -1470,7 +1527,6 @@ def test_load_plugins install_gem foo2 end - Gem.searcher = nil Gem::Specification.reset gem 'foo' @@ -1480,6 +1536,31 @@ def test_load_plugins assert_equal %w[plugin], PLUGINS_LOADED end + def test_load_user_installed_plugins + plugin_path = File.join "lib", "rubygems_plugin.rb" + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'lib' + File.open plugin_path, "w" do |fp| + fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" + end + + foo = util_spec 'foo', '1' do |s| + s.files << plugin_path + end + + install_gem_user foo + end + + Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) } + + gem 'foo' + + Gem.load_plugins + + assert_equal %w[plugin], PLUGINS_LOADED + end + def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil @@ -1500,8 +1581,8 @@ def test_load_env_plugins def test_gem_path_ordering refute_equal Gem.dir, Gem.user_dir - write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } g = util_spec 'g', '1', nil, "lib/g.rb" m = util_spec 'm', '1', nil, "lib/m.rb" @@ -1515,7 +1596,7 @@ def test_gem_path_ordering tests = [ [:dir0, [ Gem.dir, Gem.user_dir], m0], - [:dir1, [ Gem.user_dir, Gem.dir], m1] + [:dir1, [ Gem.user_dir, Gem.dir], m1], ] tests.each do |_name, _paths, expected| @@ -1556,8 +1637,8 @@ def test_gem_path_ordering end def test_gem_path_ordering_short - write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } g = util_spec 'g', '1', nil, "lib/g.rb" m = util_spec 'm', '1', nil, "lib/m.rb" @@ -1589,11 +1670,11 @@ def test_auto_activation_of_specific_gemdeps_file f.puts "gem 'c'" end - ENV['RUBYGEMS_GEMDEPS'] = path + with_rubygems_gemdeps(path) do + Gem.use_gemdeps - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + end end def test_auto_activation_of_used_gemdeps_file @@ -1611,14 +1692,16 @@ def test_auto_activation_of_used_gemdeps_file f.puts "gem 'c'" end - ENV['RUBYGEMS_GEMDEPS'] = "-" + with_rubygems_gemdeps("-") do + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) + + Gem.use_gemdeps - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact - assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } + assert_equal expected_specs, loaded_spec_names + end end - LIB_PATH = File.expand_path "../../../lib".dup.tap(&Gem::UNTAINT), __FILE__.dup.tap(&Gem::UNTAINT) - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.tap(&Gem::UNTAINT) + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze def add_bundler_full_name(names) @@ -1627,10 +1710,18 @@ def add_bundler_full_name(names) names end - def test_looks_for_gemdeps_files_automatically_on_start - skip "Requiring bundler messes things up" if Gem.java_platform? + def test_looks_for_gemdeps_files_automatically_from_binstubs + pend "Requiring bundler messes things up" if Gem.java_platform? + + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, 'exe', 'foo') do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end - a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1642,31 +1733,44 @@ def test_looks_for_gemdeps_files_automatically_on_start install_gem c, :install_dir => path ENV['GEM_PATH'] = path - ENV['RUBYGEMS_GEMDEPS'] = "-" - path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", - "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + with_rubygems_gemdeps("-") do + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = IO.popen(cmd, &:read).split(/\n/) + path = File.join @tempdir, "gem.deps.rb" - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = IO.popen(cmd, &:read).split(/\n/) + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end - assert_equal ["b-1", "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 + end end - def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir - skip "Requiring bundler messes things up" if Gem.java_platform? + def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir + pend "Requiring bundler messes things up" if Gem.java_platform? + + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, 'exe', 'foo') do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end - a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1678,29 +1782,34 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir install_gem c, :install_dir => path ENV['GEM_PATH'] = path - ENV['RUBYGEMS_GEMDEPS'] = "-" - Dir.mkdir "sub1" + with_rubygems_gemdeps("-") do + Dir.mkdir "sub1" - path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-Csub1", "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", - "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = IO.popen(cmd, &:read).split(/\n/) + path = File.join @tempdir, "gem.deps.rb" - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = IO.popen(cmd, &:read).split(/\n/) + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end - Dir.rmdir "sub1" + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end + + Dir.rmdir "sub1" - assert_equal ["b-1", "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 + end end def test_register_default_spec @@ -1731,12 +1840,24 @@ def test_register_default_spec assert_nil Gem.find_unresolved_default_spec("README") end + def test_register_default_spec_old_style_with_folder_starting_with_lib + Gem.clear_default_specs + + old_style = Gem::Specification.new do |spec| + spec.files = ["libexec/bundle", "foo.rb", "bar.rb"] + end + + Gem.register_default_spec old_style + + assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") + end + def test_use_gemdeps gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT) spec = util_spec 'a', 1 install_specs spec - spec = Gem::Specification.find { |s| s == spec } + spec = Gem::Specification.find {|s| s == spec } refute spec.activated? File.open gem_deps_file, 'w' do |io| @@ -1747,30 +1868,28 @@ def test_use_gemdeps Gem.use_gemdeps gem_deps_file - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names refute_nil Gem.gemdeps end def test_use_gemdeps_ENV - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil - - spec = util_spec 'a', 1 + with_rubygems_gemdeps(nil) do + spec = util_spec 'a', 1 - refute spec.activated? + refute spec.activated? - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end + File.open 'gem.deps.rb', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - refute spec.activated? - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + refute spec.activated? + end end def test_use_gemdeps_argument_missing - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.use_gemdeps 'gem.deps.rb' end @@ -1779,114 +1898,96 @@ def test_use_gemdeps_argument_missing end def test_use_gemdeps_argument_missing_match_ENV - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = - ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb' + with_rubygems_gemdeps('gem.deps.rb') do + e = assert_raise ArgumentError do + Gem.use_gemdeps 'gem.deps.rb' + end - e = assert_raises ArgumentError do - Gem.use_gemdeps 'gem.deps.rb' + assert_equal 'Unable to find gem dependencies file at gem.deps.rb', + e.message end - - assert_equal 'Unable to find gem dependencies file at gem.deps.rb', - e.message - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_use_gemdeps_automatic - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + with_rubygems_gemdeps('-') do + spec = util_spec 'a', 1 + install_specs spec + spec = Gem::Specification.find {|s| s == spec } - spec = util_spec 'a', 1 - install_specs spec - spec = Gem::Specification.find { |s| s == spec } + refute spec.activated? - refute spec.activated? - - File.open 'Gemfile', 'w' do |io| - io.write 'gem "a"' - end + File.open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end end def test_use_gemdeps_automatic_missing - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + with_rubygems_gemdeps('-') do + Gem.use_gemdeps - Gem.use_gemdeps - - assert true # count - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert true # count + end end def test_use_gemdeps_disabled - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '' - - spec = util_spec 'a', 1 + with_rubygems_gemdeps('') do + spec = util_spec 'a', 1 - refute spec.activated? + refute spec.activated? - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end + File.open 'gem.deps.rb', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - refute spec.activated? - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + refute spec.activated? + end end def test_use_gemdeps_missing_gem - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' - - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end - - platform = Bundler::GemHelpers.generic_local_platform - if platform == Gem::Platform::RUBY - platform = '' - else - platform = " #{platform}" - end + with_rubygems_gemdeps('x') do + File.open 'x', 'w' do |io| + io.write 'gem "a"' + end - expected = <<-EXPECTED -Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. -You may need to `gem install -g` to install missing gems + expected = <<-EXPECTED +Could not find gem 'a' in locally installed gems. +You may need to `bundle install` to install missing gems - EXPECTED + EXPECTED - Gem::Deprecate.skip_during do - assert_output nil, expected do - Gem.use_gemdeps + Gem::Deprecate.skip_during do + actual_stdout, actual_stderr = capture_output do + Gem.use_gemdeps + end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end end - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_use_gemdeps_specific - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' + with_rubygems_gemdeps('x') do + spec = util_spec 'a', 1 + install_specs spec - spec = util_spec 'a', 1 - install_specs spec + spec = Gem::Specification.find {|s| s == spec } + refute spec.activated? - spec = Gem::Specification.find { |s| s == spec } - refute spec.activated? - - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end + File.open 'x', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end end def test_operating_system_defaults @@ -1903,35 +2004,62 @@ def test_platform_defaults assert platform_defaults.is_a? Hash end - def ruby_install_name(name) - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = name + # Ensure that `Gem.source_date_epoch` is consistent even if + # $SOURCE_DATE_EPOCH has not been set. + def test_default_source_date_epoch_doesnt_change + old_epoch = ENV['SOURCE_DATE_EPOCH'] + ENV['SOURCE_DATE_EPOCH'] = nil - yield + # Unfortunately, there is no real way to test this aside from waiting + # enough for `Time.now.to_i` to change -- which is a whole second. + # + # Fortunately, we only need to do this once. + a = Gem.source_date_epoch + sleep 1 + b = Gem.source_date_epoch + assert_equal a, b ensure - if orig_RUBY_INSTALL_NAME - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME - else - RbConfig::CONFIG.delete 'ruby_install_name' - end + ENV['SOURCE_DATE_EPOCH'] = old_epoch end - def with_bindir_and_exeext(bindir, exeext) - bindir(bindir) do - exeext(exeext) do + private + + def ruby_install_name(name) + with_clean_path_to_ruby do + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = name + + begin yield + ensure + if orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + else + RbConfig::CONFIG.delete 'ruby_install_name' + end end end end - def with_clean_path_to_ruby - orig_ruby = Gem.ruby + def with_rb_config_ruby(path) + rb_config_singleton_class = class << RbConfig; self; end + orig_path = RbConfig.ruby - Gem.instance_variable_set :@ruby, nil + redefine_method(rb_config_singleton_class, :ruby, path) yield ensure - Gem.instance_variable_set :@ruby, orig_ruby + redefine_method(rb_config_singleton_class, :ruby, orig_path) + end + + def redefine_method(base, method, new_result) + if RUBY_VERSION >= "2.5" + base.alias_method(method, method) + base.define_method(method) { new_result } + else + base.send(:alias_method, method, method) + base.send(:define_method, method) { new_result } + end end def with_plugin(path) @@ -1943,7 +2071,7 @@ def with_plugin(path) refute_includes $LOAD_PATH, test_plugin_path $LOAD_PATH.unshift test_plugin_path - capture_io do + capture_output do yield end ensure @@ -1980,4 +2108,21 @@ def util_cache_dir File.join Gem.dir, "cache" end + def with_path_and_rubyopt(path_value, rubyopt_value) + path, ENV['PATH'] = ENV['PATH'], path_value + rubyopt, ENV['RUBYOPT'] = ENV['RUBYOPT'], rubyopt_value + + yield + ensure + ENV['PATH'] = path + ENV['RUBYOPT'] = rubyopt + end + + def with_rubygems_gemdeps(value) + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], value + + yield + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end end diff --git a/ruby/test/rubygems/test_gem_available_set.rb b/ruby/test/rubygems/test_gem_available_set.rb index 64ee9a36a..c4164d77f 100644 --- a/ruby/test/rubygems/test_gem_available_set.rb +++ b/ruby/test/rubygems/test_gem_available_set.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/available_set' require 'rubygems/security' class TestGemAvailableSet < Gem::TestCase - def setup super @@ -37,12 +36,12 @@ def test_find_all dep = Gem::Resolver::DependencyRequest.new dep('a'), nil - assert_equal %w[a-1], set.find_all(dep).map { |spec| spec.full_name } + assert_equal %w[a-1], set.find_all(dep).map {|spec| spec.full_name } dep = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil assert_equal %w[a-1 a-1.a], - set.find_all(dep).map { |spec| spec.full_name }.sort + set.find_all(dep).map {|spec| spec.full_name }.sort end def test_match_platform @@ -123,9 +122,8 @@ def test_sorted_respect_pre set.add a2a, @source set.add a2, @source - g = set.sorted.map { |t| t.spec } + g = set.sorted.map {|t| t.spec } assert_equal [a3a, a2, a2a, a1, a1a], g end - end diff --git a/ruby/test/rubygems/test_gem_bundler_version_finder.rb b/ruby/test/rubygems/test_gem_bundler_version_finder.rb index 34a451b64..7494a94d6 100644 --- a/ruby/test/rubygems/test_gem_bundler_version_finder.rb +++ b/ruby/test/rubygems/test_gem_bundler_version_finder.rb @@ -1,20 +1,17 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemBundlerVersionFinder < Gem::TestCase - def setup super @argv = ARGV.dup - @env = ENV.to_hash.clone - ENV.delete("BUNDLER_VERSION") @dollar_0 = $0 + without_any_upwards_gemfiles end def teardown ARGV.replace @argv - ENV.replace @env $0 = @dollar_0 super @@ -51,82 +48,78 @@ def test_bundler_version_with_bundle_update_bundler end def test_bundler_version_with_lockfile - bvf.stub(:lockfile_contents, [nil, ""]) do + bvf.stub(:lockfile_contents, "") do assert_nil bvf.bundler_version end - bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do + bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n 1.1.1.1\n") do assert_equal v("1.1.1.1"), bvf.bundler_version end - bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n fjdkslfjdkslfjsldk\n"]) do + bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n fjdkslfjdkslfjsldk\n") do assert_nil bvf.bundler_version end end - def test_bundler_version_with_reason - assert_nil bvf.bundler_version_with_reason - bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do - assert_equal ["1.1.1.1", "your lockfile"], bvf.bundler_version_with_reason + def test_bundler_version + assert_nil bvf.bundler_version + bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n 1.1.1.1\n") do + assert_equal "1.1.1.1", bvf.bundler_version.to_s $0 = "bundle" ARGV.replace %w[update --bundler] - assert_nil bvf.bundler_version_with_reason + assert_nil bvf.bundler_version + ARGV.replace %w[update --bundler=1.1.1.2] - assert_equal ["1.1.1.2", "`bundle update --bundler`"], bvf.bundler_version_with_reason + assert_equal "1.1.1.2", bvf.bundler_version.to_s ENV["BUNDLER_VERSION"] = "1.1.1.3" - assert_equal ["1.1.1.3", "`$BUNDLER_VERSION`"], bvf.bundler_version_with_reason + assert_equal "1.1.1.3", bvf.bundler_version.to_s end end - def test_compatible - assert bvf.compatible?(util_spec("foo")) - assert bvf.compatible?(util_spec("bundler", 1.1)) + def test_deleted_directory + pend "Cannot perform this test on windows" if win_platform? + pend "Cannot perform this test on Solaris" if /solaris/ =~ RUBY_PLATFORM + require "tmpdir" - bvf.stub(:bundler_version, v("1.1.1.1")) do - assert bvf.compatible?(util_spec("foo")) - assert bvf.compatible?(util_spec("bundler", "1.1.1.1")) - assert bvf.compatible?(util_spec("bundler", "1.1.1.a")) - assert bvf.compatible?(util_spec("bundler", "1.999")) - refute bvf.compatible?(util_spec("bundler", "2.999")) - end + orig_dir = Dir.pwd - bvf.stub(:bundler_version, v("2.1.1.1")) do - assert bvf.compatible?(util_spec("foo")) - assert bvf.compatible?(util_spec("bundler", "2.1.1.1")) - assert bvf.compatible?(util_spec("bundler", "2.1.1.a")) - assert bvf.compatible?(util_spec("bundler", "2.999")) - refute bvf.compatible?(util_spec("bundler", "1.999")) - refute bvf.compatible?(util_spec("bundler", "3.0.0")) + begin + Dir.mktmpdir("some_dir") do |dir| + Dir.chdir(dir) + end + ensure + Dir.chdir(orig_dir) end + + assert_nil bvf.bundler_version end - def test_filter + def test_prioritize versions = %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1] - specs = versions.map { |v| util_spec("bundler", v) } + specs = versions.map {|v| util_spec("bundler", v) } - assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs) bvf.stub(:bundler_version, v("2.1.1.1")) do - assert_equal %w[2 2.a 2.0 2.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs) end bvf.stub(:bundler_version, v("1.1.1.1")) do - assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs) end bvf.stub(:bundler_version, v("1")) do - assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs) end bvf.stub(:bundler_version, v("2.a")) do - assert_equal %w[2.a 2 2.0 2.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[2.a 1 1.0 1.0.1.1 2 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs) end bvf.stub(:bundler_version, v("3")) do - assert_equal %w[3 3.a 3.0 3.1.1], util_filter_specs(specs).map(&:version).map(&:to_s) + assert_equal %w[3 1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3.a 3.0 3.1.1], util_prioritize_specs(specs) end end - def util_filter_specs(specs) + def util_prioritize_specs(specs) specs = specs.dup - bvf.filter!(specs) - specs + bvf.prioritize!(specs) + specs.map(&:version).map(&:to_s) end - end diff --git a/ruby/test/rubygems/test_gem_command.rb b/ruby/test/rubygems/test_gem_command.rb index 230baa535..65b9b040b 100644 --- a/ruby/test/rubygems/test_gem_command.rb +++ b/ruby/test/rubygems/test_gem_command.rb @@ -1,15 +1,12 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/command' class Gem::Command - public :parser - end class TestGemCommand < Gem::TestCase - def setup super @@ -34,7 +31,7 @@ def teardown def test_self_add_specific_extra_args added_args = %w[--all] - @cmd.add_option('--all') { |v,o| } + @cmd.add_option('--all') {|v,o| } Gem::Command.add_specific_extra_args @cmd_name, added_args @@ -57,6 +54,27 @@ def test_self_add_specific_extra_args_unknown assert_equal [], h end + def test_self_extra_args + verbose, $VERBOSE, separator = $VERBOSE, nil, $; + extra_args = Gem::Command.extra_args + + Gem::Command.extra_args = %w[--all] + assert_equal %w[--all], Gem::Command.extra_args + + Gem::Command.extra_args = "--file --help" + assert_equal %w[--file --help], Gem::Command.extra_args + + $; = "=" + + Gem::Command.extra_args = "--awesome=true --verbose" + assert_equal %w[--awesome=true --verbose], Gem::Command.extra_args + + ensure + Gem::Command.extra_args = extra_args + $; = separator + $VERBOSE = verbose + end + def test_basic_accessors assert_equal "doit", @cmd.command assert_equal "gem doit", @cmd.program_name @@ -82,7 +100,7 @@ def test_defaults @cmd.invoke end - assert_match %r|Usage: gem doit|, @ui.output + assert_match %r{Usage: gem doit}, @ui.output end def test_invoke @@ -100,7 +118,7 @@ def test_invoke_with_bad_options use_ui @ui do @cmd.when_invoked { true } - ex = assert_raises OptionParser::InvalidOption do + ex = assert_raise Gem::OptionParser::InvalidOption do @cmd.invoke('-zzz') end @@ -168,7 +186,19 @@ def test_invoke_with_options @cmd.invoke '-h' end - assert_match %r|Usage: gem doit|, @ui.output + assert_match %r{Usage: gem doit}, @ui.output + end + + def test_add_option + assert_nothing_raised RuntimeError do + @cmd.add_option('--force', 'skip validation of the spec') {|v,o| } + end + end + + def test_add_option_with_empty + assert_raise RuntimeError, "Do not pass an empty string in opts" do + @cmd.add_option('', 'skip validation of the spec') {|v,o| } + end end def test_option_recognition @@ -367,5 +397,4 @@ def test_show_lookup_failure_suggestions_remote assert_equal expected, @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_command_manager.rb b/ruby/test/rubygems/test_gem_command_manager.rb index 45be9f01b..ff1f955c6 100644 --- a/ruby/test/rubygems/test_gem_command_manager.rb +++ b/ruby/test/rubygems/test_gem_command_manager.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/command_manager' class TestGemCommandManager < Gem::TestCase - PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT) def setup @@ -23,7 +22,7 @@ def test_find_command end def test_find_command_ambiguous - e = assert_raises Gem::CommandLineError do + e = assert_raise Gem::CommandLineError do @command_manager.find_command 'u' end @@ -37,6 +36,18 @@ def test_find_alias_command assert_kind_of Gem::Commands::InstallCommand, command end + def test_find_login_alias_command + command = @command_manager.find_command 'login' + + assert_kind_of Gem::Commands::SigninCommand, command + end + + def test_find_logout_alias_comamnd + command = @command_manager.find_command 'logout' + + assert_kind_of Gem::Commands::SignoutCommand, command + end + def test_find_command_ambiguous_exact ins_command = Class.new Gem::Commands.send :const_set, :InsCommand, ins_command @@ -51,13 +62,27 @@ def test_find_command_ambiguous_exact end def test_find_command_unknown - e = assert_raises Gem::CommandLineError do + e = assert_raise Gem::UnknownCommandError do @command_manager.find_command 'xyz' end assert_equal 'Unknown command xyz', e.message end + def test_find_command_unknown_suggestions + e = assert_raise Gem::UnknownCommandError do + @command_manager.find_command 'pish' + end + + message = 'Unknown command pish'.dup + + if RUBY_VERSION >= "2.4" && defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable) + message << "\nDid you mean? \"push\"" + end + + assert_equal message, e.message + end + def test_run_interrupt old_load_path = $:.dup $: << File.expand_path("test/rubygems", PROJECT_DIR) @@ -66,7 +91,7 @@ def test_run_interrupt @command_manager.register_command :interrupt use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @command_manager.run %w[interrupt] end assert_equal '', ui.output @@ -83,7 +108,7 @@ def test_run_crash_command @command_manager.register_command :crash use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @command_manager.run %w[crash] end assert_equal '', ui.output @@ -97,7 +122,7 @@ def test_run_crash_command def test_process_args_bad_arg use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @command_manager.process_args %w[--bad-arg] end end @@ -224,26 +249,34 @@ def test_process_args_query end #check defaults - @command_manager.process_args %w[query] - assert_equal(//, check_options[:name]) + Gem::Deprecate.skip_during do + @command_manager.process_args %w[query] + end + assert_nil(check_options[:name]) assert_equal :local, check_options[:domain] assert_equal false, check_options[:details] #check settings check_options = nil - @command_manager.process_args %w[query --name foobar --local --details] + Gem::Deprecate.skip_during do + @command_manager.process_args %w[query --name foobar --local --details] + end assert_equal(/foobar/i, check_options[:name]) assert_equal :local, check_options[:domain] assert_equal true, check_options[:details] #remote domain check_options = nil - @command_manager.process_args %w[query --remote] + Gem::Deprecate.skip_during do + @command_manager.process_args %w[query --remote] + end assert_equal :remote, check_options[:domain] #both (local/remote) domains check_options = nil - @command_manager.process_args %w[query --both] + Gem::Deprecate.skip_during do + @command_manager.process_args %w[query --both] + end assert_equal :both, check_options[:domain] end @@ -258,7 +291,7 @@ def test_process_args_update #check defaults @command_manager.process_args %w[update] - assert_includes check_options[:document], 'rdoc' + assert_includes check_options[:document], 'ri' #check settings check_options = nil @@ -268,4 +301,28 @@ def test_process_args_update assert_equal Dir.pwd, check_options[:install_dir] end + def test_deprecated_command + require 'rubygems/command' + foo_command = Class.new(Gem::Command) do + extend Gem::Deprecate + + rubygems_deprecate_command + + def execute + say "pew pew!" + end + end + + Gem::Commands.send(:const_set, :FooCommand, foo_command) + @command_manager.register_command(:foo, foo_command.new("foo")) + + use_ui @ui do + @command_manager.process_args(%w[foo]) + end + + assert_equal "pew pew!\n", @ui.output + assert_match(/WARNING: foo command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error) + ensure + Gem::Commands.send(:remove_const, :FooCommand) + end end diff --git a/ruby/test/rubygems/test_gem_commands_build_command.rb b/ruby/test/rubygems/test_gem_commands_build_command.rb index 50c447e2e..1304beb58 100644 --- a/ruby/test/rubygems/test_gem_commands_build_command.rb +++ b/ruby/test/rubygems/test_gem_commands_build_command.rb @@ -1,11 +1,9 @@ - # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/build_command' require 'rubygems/package' class TestGemCommandsBuildCommand < Gem::TestCase - CERT_FILE = cert_path 'public3072' SIGNING_KEY = key_path 'private3072' @@ -17,8 +15,13 @@ def setup readme_file = File.join(@tempdir, 'README.md') - File.open readme_file, 'w' do |f| - f.write 'My awesome gem' + begin + umask_orig = File.umask(2) + File.open readme_file, 'w' do |f| + f.write 'My awesome gem' + end + ensure + File.umask(umask_orig) end @gem = util_spec 'some_gem' do |s| @@ -34,6 +37,8 @@ def test_handle_options assert @cmd.options[:force] assert @cmd.options[:strict] + assert @cmd.handles?(%W[--platform #{Gem::Platform.local}]) + assert_includes Gem.platforms, Gem::Platform.local end def test_options_filename @@ -83,6 +88,26 @@ def test_execute util_test_build_gem @gem end + def test_execute_platform + gemspec_file = File.join(@tempdir, @gem.spec_name) + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:args] = [gemspec_file] + + platforms = Gem.platforms.dup + begin + Gem.platforms << Gem::Platform.new("java") + + spec = util_test_build_gem @gem, suffix: "java" + ensure + Gem.platforms.replace(platforms) + end + assert_match spec.platform, "java" + end + def test_execute_bad_name [".", "-", "_"].each do |special_char| gem = util_spec 'some_gem_with_bad_name' do |s| @@ -101,7 +126,7 @@ def test_execute_bad_name use_ui @ui do Dir.chdir @tempdir do - assert_raises Gem::InvalidSpecificationException do + assert_raise Gem::InvalidSpecificationException do @cmd.execute end end @@ -122,6 +147,23 @@ def test_execute_strict_without_warnings util_test_build_gem @gem end + def test_execute_rubyforge_project_warning + rubyforge_gemspec = File.expand_path File.join("specifications", "rubyforge-0.0.1.gemspec"), __dir__ + + @cmd.options[:args] = [rubyforge_gemspec] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + error = @ui.error.split("\n") + assert_equal "WARNING: rubyforge_project= is deprecated and ignored. Please remove this from your gemspec to ensure that your gem continues to build in the future.", error.shift + assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift + assert_equal [], error + end + def test_execute_strict_with_warnings bad_gem = util_spec 'some_bad_gem' do |s| s.files = ['README.md'] @@ -138,7 +180,7 @@ def test_execute_strict_with_warnings use_ui @ui do Dir.chdir @tempdir do - assert_raises Gem::InvalidSpecificationException do + assert_raise Gem::InvalidSpecificationException do @cmd.execute end end @@ -147,7 +189,7 @@ def test_execute_strict_with_warnings error = @ui.error.split "\n" assert_equal "WARNING: licenses is empty, but is recommended. Use a license identifier from", error.shift assert_equal "http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.", error.shift - assert_equal "WARNING: See http://guides.rubygems.org/specification-reference/ for help", error.shift + assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift assert_equal [], error gem_file = File.join @tempdir, File.basename(@gem.cache_file) @@ -166,8 +208,8 @@ def test_execute_bad_spec @cmd.options[:args] = [gemspec_file] out, err = use_ui @ui do - capture_io do - assert_raises Gem::MockGemUi::TermError do + capture_output do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -183,13 +225,13 @@ def test_execute_bad_spec def test_execute_missing_file @cmd.options[:args] = %w[some_gem] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end assert_equal '', @ui.output - assert_equal "ERROR: Gemspec file not found: some_gem.gemspec\n", @ui.error + assert_equal "ERROR: Couldn't find a gemspec file matching 'some_gem' in #{@tempdir}\n", @ui.error end def test_execute_outside_dir @@ -230,8 +272,200 @@ def test_execute_outside_dir assert_equal "this is a summary", spec.summary end + def test_execute_outside_dir_with_glob_argument + gemspec_dir = File.join @tempdir, 'build_command_gem' + gemspec_file = File.join gemspec_dir, @gem.spec_name + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = ["*.gemspec"] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_no_gemspec_present + gemspec_dir = File.join @tempdir, 'build_command_gem' + gemspec_file = File.join @tempdir, @gem.spec_name + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = ["*.gemspec"] + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + @cmd.execute + end + end + + assert_equal "", @ui.output + assert_equal "ERROR: Couldn't find a gemspec file matching '*.gemspec' in #{gemspec_dir}\n", @ui.error + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + refute File.exist?(gem_file) + end + + def test_execute_outside_dir_without_gem_name + gemspec_dir = File.join(@tempdir, 'build_command_gem') + gemspec_file = File.join(gemspec_dir, @gem.spec_name) + + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p(gemspec_dir) + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open(gemspec_file, "w") do |gs| + gs.write(@gem.to_ruby) + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = [] + + use_ui @ui do + Dir.chdir(gemspec_dir) do + @cmd.execute + end + end + + output = @ui.output.split("\n") + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_with_external_gemspec + gemspec_dir = File.join @tempdir, 'gemspec_dir' + gemspec_file = File.join gemspec_dir, @gem.spec_name + + gemcode_dir = File.join @tempdir, 'build_command_gem' + readme_file = File.join gemcode_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + FileUtils.mkdir_p gemcode_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem in nested directory" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemcode_dir + @cmd.options[:args] = [gemspec_file] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemcode_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_with_external_relative_gemspec + gemspec_dir = File.join @tempdir, 'gemspec_dir' + gemspec_file = File.join gemspec_dir, @gem.spec_name + + gemcode_dir = File.join @tempdir, 'build_command_gem' + readme_file = File.join gemcode_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + FileUtils.mkdir_p gemcode_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem in nested directory" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemcode_dir + @cmd.options[:args] = [File.join("..", "gemspec_dir", @gem.spec_name)] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemcode_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + def test_can_find_gemspecs_without_dot_gemspec - gemspec_file = File.join(@tempdir, @gem.spec_name) + gemspec_file = File.join(@tempdir, @gem.name) File.open gemspec_file + ".gemspec", 'w' do |gs| gs.write @gem.to_ruby @@ -293,7 +527,7 @@ def test_execute_multiple_gemspec_without_gem_name use_ui @ui do Dir.chdir(gemspec_dir) do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -307,27 +541,29 @@ def test_execute_multiple_gemspec_without_gem_name refute File.exist?(expected_gem) end - def util_test_build_gem(gem) + def util_test_build_gem(gem, suffix: nil) use_ui @ui do Dir.chdir @tempdir do @cmd.execute end end - + suffix &&= "-#{suffix}" + gem_file = "some_gem-2#{suffix}.gem" output = @ui.output.split "\n" assert_equal " Successfully built RubyGem", output.shift assert_equal " Name: some_gem", output.shift assert_equal " Version: 2", output.shift - assert_equal " File: some_gem-2.gem", output.shift + assert_equal " File: #{gem_file}", output.shift assert_equal [], output - gem_file = File.join(@tempdir, File.basename(gem.cache_file)) + gem_file = File.join(@tempdir, gem_file) assert File.exist?(gem_file) spec = Gem::Package.new(gem_file).spec assert_equal "some_gem", spec.name assert_equal "this is a summary", spec.summary + spec end def test_execute_force @@ -346,7 +582,7 @@ def test_execute_force end def test_build_signed_gem - skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform? + pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform? trust_dir = Gem::Security.trust_dir @@ -373,7 +609,7 @@ def test_build_signed_gem end def test_build_signed_gem_with_cert_expiration_length_days - skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform? + pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform? gem_path = File.join Gem.user_home, ".gem" Dir.mkdir gem_path @@ -417,7 +653,7 @@ def test_build_signed_gem_with_cert_expiration_length_days end def test_build_auto_resign_cert - skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform? + pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform? gem_path = File.join Gem.user_home, ".gem" Dir.mkdir gem_path @@ -488,5 +724,4 @@ def test_build_is_reproducible ensure ENV["SOURCE_DATE_EPOCH"] = epoch end - end diff --git a/ruby/test/rubygems/test_gem_commands_cert_command.rb b/ruby/test/rubygems/test_gem_commands_cert_command.rb index fd1e66b91..901bf5aed 100644 --- a/ruby/test/rubygems/test_gem_commands_cert_command.rb +++ b/ruby/test/rubygems/test_gem_commands_cert_command.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/cert_command' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping `gem cert` tests. openssl not found.' end @@ -11,13 +11,13 @@ end class TestGemCommandsCertCommand < Gem::TestCase - ALTERNATE_CERT = load_cert 'alternate' EXPIRED_PUBLIC_CERT = load_cert 'expired' - ALTERNATE_KEY_FILE = key_path 'alternate' - PRIVATE_KEY_FILE = key_path 'private' - PUBLIC_KEY_FILE = key_path 'public' + ALTERNATE_KEY_FILE = key_path 'alternate' + PRIVATE_KEY_FILE = key_path 'private' + PRIVATE_EC_KEY_FILE = key_path 'private_ec' + PUBLIC_KEY_FILE = key_path 'public' ALTERNATE_CERT_FILE = cert_path 'alternate' CHILD_CERT_FILE = cert_path 'child' @@ -55,7 +55,7 @@ def test_certificates_matching assert_equal PUBLIC_CERT.to_pem, match.first.to_pem assert_equal @trust_dir.cert_path(PUBLIC_CERT), match.last - assert_raises StopIteration do + assert_raise StopIteration do matches.next end end @@ -70,7 +70,7 @@ def test_certificates_matching_filter assert_equal ALTERNATE_CERT.to_pem, match.first.to_pem assert_equal @trust_dir.cert_path(ALTERNATE_CERT), match.last - assert_raises StopIteration do + assert_raise StopIteration do matches.next end end @@ -84,7 +84,7 @@ def test_execute_add cert_path = @trust_dir.cert_path PUBLIC_CERT - assert_path_exists cert_path + assert_path_exist cert_path assert_equal "Added '/CN=nobody/DC=example'\n", @ui.output assert_empty @ui.error @@ -139,8 +139,44 @@ def test_execute_build assert_empty output assert_empty @build_ui.error - assert_path_exists File.join(@tempdir, 'gem-private_key.pem') - assert_path_exists File.join(@tempdir, 'gem-public_cert.pem') + assert_path_exist File.join(@tempdir, 'gem-private_key.pem') + assert_path_exist File.join(@tempdir, 'gem-public_cert.pem') + end + + def test_execute_build_key_algorithm_ec_key + passphrase = 'Foo bar' + + @cmd.handle_options %W[--build nobody@example.com --key-algorithm ec] + + @build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}" + + use_ui @build_ui do + @cmd.execute + end + + output = @build_ui.output.squeeze("\n").split "\n" + + assert_equal "Passphrase for your Private Key: ", + output.shift + assert_equal "Please repeat the passphrase for your Private Key: ", + output.shift + assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + output.shift + assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}", + output.shift + + assert_equal "Don't forget to move the key file to somewhere private!", + output.shift + + assert_empty output + assert_empty @build_ui.error + + assert_path_exist File.join(@tempdir, 'gem-private_key.pem') + + cert_path = File.join(@tempdir, 'gem-public_cert.pem') + assert_path_exist cert_path + cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) + assert cert.public_key.is_a? OpenSSL::PKey::EC end def test_execute_build_bad_email_address @@ -153,15 +189,15 @@ def test_execute_build_bad_email_address use_ui @build_ui do - e = assert_raises Gem::CommandLineError do + e = assert_raise Gem::CommandLineError do @cmd.execute end assert_equal "Invalid email address #{email}", e.message - refute_path_exists File.join(@tempdir, 'gem-private_key.pem') - refute_path_exists File.join(@tempdir, 'gem-public_cert.pem') + assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem') + assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem') end end @@ -196,8 +232,8 @@ def test_execute_build_expiration_days assert_empty output assert_empty @build_ui.error - assert_path_exists File.join(@tempdir, 'gem-private_key.pem') - assert_path_exists File.join(@tempdir, 'gem-public_cert.pem') + assert_path_exist File.join(@tempdir, 'gem-private_key.pem') + assert_path_exist File.join(@tempdir, 'gem-public_cert.pem') pem = File.read("#{@tempdir}/gem-public_cert.pem") cert = OpenSSL::X509::Certificate.new(pem) @@ -215,7 +251,7 @@ def test_execute_build_bad_passphrase_confirmation @build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase_confirmation}" use_ui @build_ui do - e = assert_raises Gem::CommandLineError do + e = assert_raise Gem::CommandLineError do @cmd.execute end @@ -233,8 +269,8 @@ def test_execute_build_bad_passphrase_confirmation end - refute_path_exists File.join(@tempdir, 'gem-private_key.pem') - refute_path_exists File.join(@tempdir, 'gem-public_cert.pem') + assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem') + assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem') end def test_execute_build_key @@ -255,8 +291,8 @@ def test_execute_build_key assert_empty output assert_empty @ui.error - assert_path_exists File.join(@tempdir, 'gem-public_cert.pem') - refute_path_exists File.join(@tempdir, 'gem-private_key.pem') + assert_path_exist File.join(@tempdir, 'gem-public_cert.pem') + assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem') end def test_execute_build_encrypted_key @@ -277,7 +313,29 @@ def test_execute_build_encrypted_key assert_empty output assert_empty @ui.error - assert_path_exists File.join(@tempdir, 'gem-public_cert.pem') + assert_path_exist File.join(@tempdir, 'gem-public_cert.pem') + end + + def test_execute_build_ec_key + @cmd.handle_options %W[ + --build nobody@example.com + --private-key #{PRIVATE_EC_KEY_FILE} + ] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + + assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + output.shift + + assert_empty output + assert_empty @ui.error + + assert_path_exist File.join(@tempdir, 'gem-public_cert.pem') + assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem') end def test_execute_certificate @@ -347,7 +405,7 @@ def test_execute_remove cert_path = @trust_dir.cert_path PUBLIC_CERT - assert_path_exists cert_path + assert_path_exist cert_path @cmd.handle_options %W[--remove nobody] @@ -358,7 +416,7 @@ def test_execute_remove assert_equal "Removed '/CN=nobody/DC=example'\n", @ui.output assert_equal '', @ui.error - refute_path_exists cert_path + assert_path_not_exist cert_path end def test_execute_remove_multiple @@ -368,8 +426,8 @@ def test_execute_remove_multiple public_path = @trust_dir.cert_path PUBLIC_CERT alternate_path = @trust_dir.cert_path ALTERNATE_CERT - assert_path_exists public_path - assert_path_exists alternate_path + assert_path_exist public_path + assert_path_exist alternate_path @cmd.handle_options %W[--remove example] @@ -385,8 +443,8 @@ def test_execute_remove_multiple assert_equal expected, @ui.output assert_equal '', @ui.error - refute_path_exists public_path - refute_path_exists alternate_path + assert_path_not_exist public_path + assert_path_not_exist alternate_path end def test_execute_remove_twice @@ -396,8 +454,8 @@ def test_execute_remove_twice public_path = @trust_dir.cert_path PUBLIC_CERT alternate_path = @trust_dir.cert_path ALTERNATE_CERT - assert_path_exists public_path - assert_path_exists alternate_path + assert_path_exist public_path + assert_path_exist alternate_path @cmd.handle_options %W[--remove nobody --remove alternate] @@ -413,8 +471,8 @@ def test_execute_remove_twice assert_equal expected, @ui.output assert_equal '', @ui.error - refute_path_exists public_path - refute_path_exists alternate_path + assert_path_not_exist public_path + assert_path_not_exist alternate_path end def test_execute_sign @@ -553,7 +611,7 @@ def test_execute_sign_no_cert @cmd.handle_options %W[--sign #{path}] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -581,7 +639,7 @@ def test_execute_sign_no_key @cmd.handle_options %W[--sign #{path}] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -675,19 +733,19 @@ def test_handle_options ] assert_equal [PUBLIC_CERT.to_pem, ALTERNATE_CERT.to_pem], - @cmd.options[:add].map { |cert| cert.to_pem } + @cmd.options[:add].map {|cert| cert.to_pem } assert_equal %w[nobody example], @cmd.options[:remove] assert_equal %w[nobody@example other@example], - @cmd.options[:build].map { |name| name.to_s } + @cmd.options[:build].map {|name| name.to_s } assert_equal ['', 'example'], @cmd.options[:list] end def test_handle_options_add_bad nonexistent = File.join @tempdir, 'nonexistent' - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--add #{nonexistent}] end @@ -697,7 +755,7 @@ def test_handle_options_add_bad bad = File.join @tempdir, 'bad' FileUtils.touch bad - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--add #{bad}] end @@ -707,7 +765,7 @@ def test_handle_options_add_bad def test_handle_options_certificate nonexistent = File.join @tempdir, 'nonexistent' - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--certificate #{nonexistent}] end @@ -717,7 +775,7 @@ def test_handle_options_certificate bad = File.join @tempdir, 'bad' FileUtils.touch bad - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--certificate #{bad}] end @@ -728,7 +786,7 @@ def test_handle_options_certificate def test_handle_options_key_bad nonexistent = File.join @tempdir, 'nonexistent' - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--private-key #{nonexistent}] end @@ -739,14 +797,14 @@ def test_handle_options_key_bad bad = File.join @tempdir, 'bad' FileUtils.touch bad - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--private-key #{bad}] end - assert_equal "invalid argument: --private-key #{bad}: invalid RSA key", + assert_equal "invalid argument: --private-key #{bad}: invalid RSA, DSA, or EC key", e.message - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[--private-key #{PUBLIC_KEY_FILE}] end @@ -793,7 +851,7 @@ def test_handle_options_sign_encrypted_key def test_handle_options_sign_nonexistent nonexistent = File.join @tempdir, 'nonexistent' - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %W[ --private-key #{ALTERNATE_KEY_FILE} @@ -806,5 +864,4 @@ def test_handle_options_sign_nonexistent assert_equal "invalid argument: --sign #{nonexistent}: does not exist", e.message end - -end if defined?(OpenSSL::SSL) && !Gem.java_platform? +end if Gem::HAVE_OPENSSL && !Gem.java_platform? diff --git a/ruby/test/rubygems/test_gem_commands_check_command.rb b/ruby/test/rubygems/test_gem_commands_check_command.rb index 6a6033d35..f280b060c 100644 --- a/ruby/test/rubygems/test_gem_commands_check_command.rb +++ b/ruby/test/rubygems/test_gem_commands_check_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/check_command' class TestGemCommandsCheckCommand < Gem::TestCase - def setup super @@ -51,19 +50,18 @@ def test_doctor FileUtils.rm b.spec_file - assert_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_exist b.gem_dir + assert_path_not_exist b.spec_file Gem.use_paths @gemhome - capture_io do + capture_output do use_ui @ui do @cmd.doctor end end - refute_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_not_exist b.gem_dir + assert_path_not_exist b.spec_file end - end diff --git a/ruby/test/rubygems/test_gem_commands_cleanup_command.rb b/ruby/test/rubygems/test_gem_commands_cleanup_command.rb index 3494085a6..fc9899801 100644 --- a/ruby/test/rubygems/test_gem_commands_cleanup_command.rb +++ b/ruby/test/rubygems/test_gem_commands_cleanup_command.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/cleanup_command' require 'rubygems/installer' class TestGemCommandsCleanupCommand < Gem::TestCase - def setup super @@ -23,10 +22,21 @@ def test_handle_options_d end def test_handle_options_dry_run - @cmd.handle_options %w[--dryrun] + @cmd.handle_options %w[--dry-run] assert @cmd.options[:dryrun] end + def test_handle_options_deprecated_dry_run + use_ui @ui do + @cmd.handle_options %w[--dryrun] + assert @cmd.options[:dryrun] + end + + assert_equal \ + "WARNING: The \"--dryrun\" option has been deprecated and will be removed in future versions of Rubygems. Use --dry-run instead\n", + @ui.error + end + def test_handle_options_n @cmd.handle_options %w[-n] assert @cmd.options[:dryrun] @@ -52,7 +62,7 @@ def test_execute @cmd.execute - refute_path_exists @a_1.gem_dir + assert_path_not_exist @a_1.gem_dir end def test_execute_all_dependencies @@ -71,8 +81,8 @@ def test_execute_all_dependencies @cmd.execute - refute_path_exists @a_1.gem_dir - refute_path_exists @b_1.gem_dir + assert_path_not_exist @a_1.gem_dir + assert_path_not_exist @b_1.gem_dir end def test_execute_dev_dependencies @@ -91,7 +101,7 @@ def test_execute_dev_dependencies @cmd.execute - assert_path_exists @a_1.gem_dir + assert_path_exist @a_1.gem_dir end def test_execute_without_dev_dependencies @@ -110,7 +120,7 @@ def test_execute_without_dev_dependencies @cmd.execute - refute_path_exists @a_1.gem_dir + assert_path_not_exist @a_1.gem_dir end def test_execute_all @@ -133,8 +143,8 @@ def test_execute_all assert_equal @gemhome, Gem.dir, 'GEM_HOME' assert_equal [@gemhome, gemhome2], Gem.path.sort, 'GEM_PATH' - refute_path_exists @a_1.gem_dir - refute_path_exists @b_1.gem_dir + assert_path_not_exist @a_1.gem_dir + assert_path_not_exist @b_1.gem_dir end def test_execute_all_user @@ -143,15 +153,15 @@ def test_execute_all_user Gem::Specification.dirs = [Gem.dir, Gem.user_dir] - assert_path_exists @a_1.gem_dir - assert_path_exists @a_1_1.gem_dir + assert_path_exist @a_1.gem_dir + assert_path_exist @a_1_1.gem_dir @cmd.options[:args] = %w[a] @cmd.execute - refute_path_exists @a_1.gem_dir - refute_path_exists @a_1_1.gem_dir + assert_path_not_exist @a_1.gem_dir + assert_path_not_exist @a_1_1.gem_dir end def test_execute_all_user_no_sudo @@ -162,15 +172,15 @@ def test_execute_all_user_no_sudo Gem::Specification.dirs = [Gem.dir, Gem.user_dir] - assert_path_exists @a_1.gem_dir - assert_path_exists @a_1_1.gem_dir + assert_path_exist @a_1.gem_dir + assert_path_exist @a_1_1.gem_dir @cmd.options[:args] = %w[a] @cmd.execute - assert_path_exists @a_1.gem_dir - assert_path_exists @a_1_1.gem_dir + assert_path_exist @a_1.gem_dir + assert_path_exist @a_1_1.gem_dir ensure FileUtils.chmod 0755, @gemhome end unless win_platform? || Process.uid.zero? @@ -181,7 +191,7 @@ def test_execute_dry_run @cmd.execute - assert_path_exists @a_1.gem_dir + assert_path_exist @a_1.gem_dir end def test_execute_keeps_older_versions_with_deps @@ -200,7 +210,7 @@ def test_execute_keeps_older_versions_with_deps @cmd.execute - assert_path_exists @b_1.gem_dir + assert_path_exist @b_1.gem_dir end def test_execute_ignore_default_gem_verbose @@ -211,7 +221,7 @@ def test_execute_ignore_default_gem_verbose @b_2 = util_spec 'b', 3 install_gem @b_1 - install_default_specs @b_default + install_default_gems @b_default install_gem @b_2 @cmd.options[:args] = [] @@ -220,7 +230,7 @@ def test_execute_ignore_default_gem_verbose @cmd.execute end - assert_match %r%^Skipped default gems: b-2%, @ui.output + assert_match %r{^Skipped default gems: b-2}, @ui.output assert_empty @ui.error end @@ -247,9 +257,9 @@ def test_execute_remove_gem_home_only @cmd.execute - assert_path_exists c_1.gem_dir - refute_path_exists d_1.gem_dir - refute_path_exists e_1.gem_dir + assert_path_exist c_1.gem_dir + assert_path_not_exist d_1.gem_dir + assert_path_not_exist e_1.gem_dir end def test_execute_user_install @@ -272,11 +282,10 @@ def test_execute_user_install @cmd.execute - refute_path_exists c_1.gem_dir - assert_path_exists c_2.gem_dir + assert_path_not_exist c_1.gem_dir + assert_path_exist c_2.gem_dir - assert_path_exists d_1.gem_dir - assert_path_exists d_2.gem_dir + assert_path_exist d_1.gem_dir + assert_path_exist d_2.gem_dir end - end diff --git a/ruby/test/rubygems/test_gem_commands_contents_command.rb b/ruby/test/rubygems/test_gem_commands_contents_command.rb index a8d6efe79..d79174717 100644 --- a/ruby/test/rubygems/test_gem_commands_contents_command.rb +++ b/ruby/test/rubygems/test_gem_commands_contents_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/contents_command' class TestGemCommandsContentsCommand < Gem::TestCase - def setup super @@ -27,8 +26,8 @@ def test_execute @cmd.execute end - assert_match %r|lib/foo\.rb|, @ui.output - assert_match %r|Rakefile|, @ui.output + assert_match %r{lib/foo\.rb}, @ui.output + assert_match %r{Rakefile}, @ui.output assert_equal "", @ui.error end @@ -42,23 +41,23 @@ def test_execute_all @cmd.execute end - assert_match %r|lib/foo\.rb|, @ui.output - assert_match %r|lib/bar\.rb|, @ui.output - assert_match %r|Rakefile|, @ui.output + assert_match %r{lib/foo\.rb}, @ui.output + assert_match %r{lib/bar\.rb}, @ui.output + assert_match %r{Rakefile}, @ui.output assert_equal "", @ui.error end def test_execute_bad_gem @cmd.options[:args] = %w[foo] - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end end - assert_match %r|Unable to find gem 'foo' in default gem paths|, @ui.output - assert_match %r|Directories searched:|, @ui.output + assert_match %r{Unable to find gem 'foo' in default gem paths}, @ui.output + assert_match %r{Directories searched:}, @ui.output assert_equal "", @ui.error end @@ -71,8 +70,8 @@ def test_execute_exact_match @cmd.execute end - assert_match %r|lib/foo\.rb|, @ui.output - assert_match %r|Rakefile|, @ui.output + assert_match %r{lib/foo\.rb}, @ui.output + assert_match %r{Rakefile}, @ui.output assert_equal "", @ui.error end @@ -86,8 +85,8 @@ def test_execute_lib_only @cmd.execute end - assert_match %r|lib/foo\.rb|, @ui.output - refute_match %r|Rakefile|, @ui.output + assert_match %r{lib/foo\.rb}, @ui.output + refute_match %r{Rakefile}, @ui.output assert_equal "", @ui.error end @@ -95,7 +94,23 @@ def test_execute_lib_only def test_execute_missing_single @cmd.options[:args] = %w[foo] - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_match "Unable to find gem 'foo'", @ui.output + assert_empty @ui.error + end + + def test_execute_missing_version + @cmd.options[:args] = %w[foo] + @cmd.options[:version] = Gem::Requirement.new '= 2' + + gem 'foo', 1 + + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end @@ -130,9 +145,9 @@ def test_execute_multiple @cmd.execute end - assert_match %r|lib/foo\.rb|, @ui.output - assert_match %r|lib/bar\.rb|, @ui.output - assert_match %r|Rakefile|, @ui.output + assert_match %r{lib/foo\.rb}, @ui.output + assert_match %r{lib/bar\.rb}, @ui.output + assert_match %r{Rakefile}, @ui.output assert_equal "", @ui.error end @@ -152,6 +167,23 @@ def test_execute_show_install_dir assert_equal "", @ui.error end + def test_execute_show_install_dir_latest_version + @cmd.options[:args] = %w[foo] + @cmd.options[:show_install_dir] = true + + gem 'foo', 1 + gem 'foo', 2 + + use_ui @ui do + @cmd.execute + end + + expected = File.join @gemhome, 'gems', 'foo-2' + + assert_equal "#{expected}\n", @ui.output + assert_equal "", @ui.error + end + def test_execute_show_install_dir_version @cmd.options[:args] = %w[foo] @cmd.options[:show_install_dir] = true @@ -195,7 +227,7 @@ def test_execute_default_gem nil, "default/gem.rb") default_gem_spec.executables = ["default_command"] default_gem_spec.files += ["default_gem.so"] - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) @cmd.options[:args] = %w[default] @@ -206,8 +238,8 @@ def test_execute_default_gem expected = [ [RbConfig::CONFIG['bindir'], 'default_command'], [RbConfig::CONFIG['rubylibdir'], 'default/gem.rb'], - [RbConfig::CONFIG['archdir'], 'default_gem.so'] - ].sort.map{|a|File.join a}.join "\n" + [RbConfig::CONFIG['archdir'], 'default_gem.so'], + ].sort.map{|a|File.join a }.join "\n" assert_equal expected, @ui.output.chomp assert_equal "", @ui.error @@ -235,5 +267,4 @@ def test_handle_options assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version] assert @cmd.options[:show_install_dir] end - end diff --git a/ruby/test/rubygems/test_gem_commands_dependency_command.rb b/ruby/test/rubygems/test_gem_commands_dependency_command.rb index eaa959416..13c7c065b 100644 --- a/ruby/test/rubygems/test_gem_commands_dependency_command.rb +++ b/ruby/test/rubygems/test_gem_commands_dependency_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/dependency_command' class TestGemCommandsDependencyCommand < Gem::TestCase - def setup super @stub_ui = Gem::MockGemUi.new @@ -65,7 +64,7 @@ def test_execute_no_args def test_execute_no_match @cmd.options[:args] = %w[foo] - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -156,7 +155,7 @@ def test_execute_reverse_remote @cmd.options[:reverse_dependencies] = true @cmd.options[:domain] = :remote - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -225,5 +224,4 @@ def test_execute_prerelease assert_equal "Gem a-2.a\n\n", @stub_ui.output assert_equal '', @stub_ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_environment_command.rb b/ruby/test/rubygems/test_gem_commands_environment_command.rb index 5dd0fc752..2bf80d8d8 100644 --- a/ruby/test/rubygems/test_gem_commands_environment_command.rb +++ b/ruby/test/rubygems/test_gem_commands_environment_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/environment_command' class TestGemCommandsEnvironmentCommand < Gem::TestCase - def setup super @@ -22,29 +21,29 @@ def test_execute @cmd.execute end - assert_match %r|RUBYGEMS VERSION: (\d\.)+\d|, @ui.output - assert_match %r|RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]|, @ui.output - assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|, + assert_match %r{RUBYGEMS VERSION: (\d\.)+\d}, @ui.output + assert_match %r{RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]}, @ui.output + assert_match %r{INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}}, @ui.output - assert_match %r|RUBYGEMS PREFIX: |, @ui.output - assert_match %r|RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}|, + assert_match %r{RUBYGEMS PREFIX: }, @ui.output + assert_match %r{RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}}, @ui.output - assert_match %r|GIT EXECUTABLE: #{@cmd.send(:git_path)}|, @ui.output - assert_match %r|SYSTEM CONFIGURATION DIRECTORY:|, @ui.output - assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output - assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output - assert_match %r|- #{Gem::Platform.local}|, @ui.output - assert_match %r|GEM PATHS:|, @ui.output - assert_match %r|- #{Regexp.escape @gemhome}|, @ui.output - assert_match %r|GEM CONFIGURATION:|, @ui.output - assert_match %r|"gemcutter_key" => "\*\*\*\*"|, @ui.output - assert_match %r|:verbose => |, @ui.output - assert_match %r|REMOTE SOURCES:|, @ui.output - - assert_match %r|- SHELL PATH:|, @ui.output - assert_match %r|- /usr/local/bin$|, @ui.output - assert_match %r|- /usr/bin$|, @ui.output - assert_match %r|- /bin$|, @ui.output + assert_match %r{GIT EXECUTABLE: #{@cmd.send(:git_path)}}, @ui.output + assert_match %r{SYSTEM CONFIGURATION DIRECTORY:}, @ui.output + assert_match %r{EXECUTABLE DIRECTORY:}, @ui.output + assert_match %r{RUBYGEMS PLATFORMS:}, @ui.output + assert_match %r{- #{Gem::Platform.local}}, @ui.output + assert_match %r{GEM PATHS:}, @ui.output + assert_match %r{- #{Regexp.escape @gemhome}}, @ui.output + assert_match %r{GEM CONFIGURATION:}, @ui.output + assert_match %r{"gemcutter_key" => "\*\*\*\*"}, @ui.output + assert_match %r{:verbose => }, @ui.output + assert_match %r{REMOTE SOURCES:}, @ui.output + + assert_match %r{- SHELL PATH:}, @ui.output + assert_match %r{- /usr/local/bin$}, @ui.output + assert_match %r{- /usr/bin$}, @ui.output + assert_match %r{- /bin$}, @ui.output assert_empty @ui.error @@ -110,7 +109,7 @@ def test_execute_remotesources def test_execute_unknown @cmd.send :handle_options, %w[unknown] - assert_raises Gem::CommandLineError do + assert_raise Gem::CommandLineError do use_ui @ui do @cmd.execute end @@ -141,5 +140,4 @@ def test_execute_platform assert_equal "#{Gem.platforms.join File::PATH_SEPARATOR}\n", @ui.output assert_equal '', @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_fetch_command.rb b/ruby/test/rubygems/test_gem_commands_fetch_command.rb index 9989f57bd..7d4c77afa 100644 --- a/ruby/test/rubygems/test_gem_commands_fetch_command.rb +++ b/ruby/test/rubygems/test_gem_commands_fetch_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/package' require 'rubygems/security' require 'rubygems/commands/fetch_command' class TestGemCommandsFetchCommand < Gem::TestCase - def setup super @@ -17,7 +16,7 @@ def test_execute fetcher.gem 'a', 2 end - refute_path_exists File.join(@tempdir, 'cache'), 'sanity check' + assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check' @cmd.options[:args] = %w[a] @@ -29,9 +28,9 @@ def test_execute a2 = specs['a-2'] - assert_path_exists(File.join(@tempdir, a2.file_name), + assert_path_exist(File.join(@tempdir, a2.file_name), "#{a2.full_name} not fetched") - refute_path_exists File.join(@tempdir, 'cache'), + assert_path_not_exist File.join(@tempdir, 'cache'), 'gem repository directories must not be created' end @@ -41,7 +40,7 @@ def test_execute_latest fetcher.gem 'a', 2 end - refute_path_exists File.join(@tempdir, 'cache'), 'sanity check' + assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check' @cmd.options[:args] = %w[a] @cmd.options[:version] = req('>= 0.1') @@ -53,9 +52,9 @@ def test_execute_latest end a2 = specs['a-2'] - assert_path_exists(File.join(@tempdir, a2.file_name), + assert_path_exist(File.join(@tempdir, a2.file_name), "#{a2.full_name} not fetched") - refute_path_exists File.join(@tempdir, 'cache'), + assert_path_not_exist File.join(@tempdir, 'cache'), 'gem repository directories must not be created' end @@ -76,10 +75,46 @@ def test_execute_prerelease a2 = specs['a-2'] - assert_path_exists(File.join(@tempdir, a2.file_name), + assert_path_exist(File.join(@tempdir, a2.file_name), "#{a2.full_name} not fetched") end + def test_execute_platform + a2_spec, a2 = util_gem("a", "2") + + a2_universal_darwin_spec, a2_universal_darwin = util_gem("a", "2") do |s| + s.platform = 'universal-darwin' + end + + Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new + + write_marshalled_gemspecs(a2_spec, a2_universal_darwin_spec) + + @cmd.options[:args] = %w[a] + + @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([ + Gem::NameTuple.new(a2_spec.name, a2_spec.version, a2_spec.platform), + Gem::NameTuple.new(a2_universal_darwin_spec.name, a2_universal_darwin_spec.version, a2_universal_darwin_spec.platform), + ])) + + @fetcher.data["#{@gem_repo}gems/#{a2_spec.file_name}"] = Gem.read_binary(a2) + FileUtils.cp a2, a2_spec.cache_file + + @fetcher.data["#{@gem_repo}gems/#{a2_universal_darwin_spec.file_name}"] = Gem.read_binary(a2_universal_darwin) + FileUtils.cp a2_universal_darwin, a2_universal_darwin_spec.cache_file + + util_set_arch 'arm64-darwin20' do + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + end + + assert_path_exist(File.join(@tempdir, a2_universal_darwin_spec.file_name), + "#{a2_universal_darwin_spec.full_name} not fetched") + end + def test_execute_specific_prerelease specs = spec_fetcher do |fetcher| fetcher.gem 'a', 2 @@ -98,7 +133,7 @@ def test_execute_specific_prerelease a2_pre = specs['a-2.a'] - assert_path_exists(File.join(@tempdir, a2_pre.file_name), + assert_path_exist(File.join(@tempdir, a2_pre.file_name), "#{a2_pre.full_name} not fetched") end @@ -119,8 +154,104 @@ def test_execute_version a1 = specs['a-1'] - assert_path_exists(File.join(@tempdir, a1.file_name), + assert_path_exist(File.join(@tempdir, a1.file_name), + "#{a1.full_name} not fetched") + end + + def test_execute_version_specified_by_colon + specs = spec_fetcher do |fetcher| + fetcher.gem 'a', 1 + end + + @cmd.options[:args] = %w[a:1] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + a1 = specs['a-1'] + + assert_path_exist(File.join(@tempdir, a1.file_name), "#{a1.full_name} not fetched") end + def test_execute_two_version + @cmd.options[:args] = %w[a b] + @cmd.options[:version] = Gem::Requirement.new '1' + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError, @ui.error do + @cmd.execute + end + end + + msg = "ERROR: Can't use --version with multiple gems. You can specify multiple gems with" \ + " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`" + + assert_empty @ui.output + assert_equal msg, @ui.error.chomp + end + + def test_execute_two_version_specified_by_colon + specs = spec_fetcher do |fetcher| + fetcher.gem 'a', 1 + fetcher.gem 'b', 1 + end + + @cmd.options[:args] = %w[a:1 b:1] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + a1 = specs['a-1'] + b1 = specs['b-1'] + + assert_path_exist(File.join(@tempdir, a1.file_name), + "#{a1.full_name} not fetched") + assert_path_exist(File.join(@tempdir, b1.file_name), + "#{b1.full_name} not fetched") + end + + def test_execute_version_nonexistent + spec_fetcher do |fetcher| + fetcher.spec 'foo', 1 + end + + @cmd.options[:args] = %w[foo:2] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EXPECTED +ERROR: Could not find a valid gem 'foo' (2) in any repository +ERROR: Possible alternatives: foo + EXPECTED + + assert_equal expected, @ui.error + end + + def test_execute_nonexistent_hint_disabled + spec_fetcher do |fetcher| + fetcher.spec 'foo', 1 + end + + @cmd.options[:args] = %w[foo:2] + @cmd.options[:suggest_alternate] = false + + use_ui @ui do + @cmd.execute + end + + expected = <<-EXPECTED +ERROR: Could not find a valid gem 'foo' (2) in any repository + EXPECTED + + assert_equal expected, @ui.error + end end diff --git a/ruby/test/rubygems/test_gem_commands_generate_index_command.rb b/ruby/test/rubygems/test_gem_commands_generate_index_command.rb index d8fda32fc..5b7b37a44 100644 --- a/ruby/test/rubygems/test_gem_commands_generate_index_command.rb +++ b/ruby/test/rubygems/test_gem_commands_generate_index_command.rb @@ -1,14 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/indexer' require 'rubygems/commands/generate_index_command' -unless defined?(Builder::XChar) - warn "generate_index tests are being skipped. Install builder gem." -end - class TestGemCommandsGenerateIndexCommand < Gem::TestCase - def setup super @@ -82,5 +77,4 @@ def test_handle_options_no_modern "WARNING: The \"--no-modern\" option has been deprecated and will be removed in Rubygems 4.0. The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.\n", @ui.error end - -end if defined?(Builder::XChar) +end diff --git a/ruby/test/rubygems/test_gem_commands_help_command.rb b/ruby/test/rubygems/test_gem_commands_help_command.rb index f2a519775..a70dd770e 100644 --- a/ruby/test/rubygems/test_gem_commands_help_command.rb +++ b/ruby/test/rubygems/test_gem_commands_help_command.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true require "rubygems" -require "rubygems/test_case" +require_relative "helper" require "rubygems/commands/help_command" require "rubygems/package" require "rubygems/command_manager" class TestGemCommandsHelpCommand < Gem::TestCase - def setup super @@ -36,18 +35,38 @@ def test_gem_help_platforms end end + def test_gem_help_build + util_gem 'build' do |out, err| + assert_match(/-C PATH *Run as if gem build was started in /, out) + assert_equal '', err + end + end + def test_gem_help_commands mgr = Gem::CommandManager.new util_gem 'commands' do |out, err| mgr.command_names.each do |cmd| - assert_match(/\s+#{cmd}\s+\S+/, out) + unless mgr[cmd].deprecated? + assert_match(/\s+#{cmd}\s+\S+/, out) + end end - if defined?(OpenSSL::SSL) + if Gem::HAVE_OPENSSL assert_empty err - refute_match 'No command found for ', out + refute_match %r{No command found for }, out + end + end + end + + def test_gem_help_commands_omits_deprecated_commands + mgr = Gem::CommandManager.new + + util_gem 'commands' do |out, err| + deprecated_commands = mgr.command_names.select {|cmd| mgr[cmd].deprecated? } + deprecated_commands.each do |cmd| + refute_match(/\A\s+#{cmd}\s+\S+\z/, out) end end end @@ -71,5 +90,4 @@ def util_gem(*args) yield @ui.output, @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_info_command.rb b/ruby/test/rubygems/test_gem_commands_info_command.rb index 373fcccee..462075f98 100644 --- a/ruby/test/rubygems/test_gem_commands_info_command.rb +++ b/ruby/test/rubygems/test_gem_commands_info_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/info_command' class TestGemCommandsInfoCommand < Gem::TestCase - def setup super @@ -33,13 +32,12 @@ def test_execute @cmd.execute end - assert_match %r%#{@gem.name} \(#{@gem.version}\)\n%, @ui.output - assert_match %r%Authors: #{@gem.authors.join(', ')}\n%, @ui.output - assert_match %r%Homepage: #{@gem.homepage}\n%, @ui.output - assert_match %r%License: #{@gem.license}\n%, @ui.output - assert_match %r%Installed at: #{@gem.base_dir}\n%, @ui.output - assert_match %r%#{@gem.summary}\n%, @ui.output + assert_match %r{#{@gem.name} \(#{@gem.version}\)\n}, @ui.output + assert_match %r{Authors: #{@gem.authors.join(', ')}\n}, @ui.output + assert_match %r{Homepage: #{@gem.homepage}\n}, @ui.output + assert_match %r{License: #{@gem.license}\n}, @ui.output + assert_match %r{Installed at: #{@gem.base_dir}\n}, @ui.output + assert_match %r{#{@gem.summary}\n}, @ui.output assert_match "", @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_install_command.rb b/ruby/test/rubygems/test_gem_commands_install_command.rb index a233377c4..47a97dae4 100644 --- a/ruby/test/rubygems/test_gem_commands_install_command.rb +++ b/ruby/test/rubygems/test_gem_commands_install_command.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/install_command' require 'rubygems/request_set' require 'rubygems/rdoc' class TestGemCommandsInstallCommand < Gem::TestCase - def setup super common_installer_setup @@ -38,12 +37,12 @@ def test_execute_exclude_prerelease @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_explicit_version_includes_prerelease @@ -60,12 +59,12 @@ def test_execute_explicit_version_includes_prerelease assert @cmd.options[:version].satisfied_by?(a2_pre.version) use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2.a], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_local @@ -83,7 +82,7 @@ def test_execute_local orig_dir = Dir.pwd begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -91,7 +90,7 @@ def test_execute_local end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "1 gem installed", @ui.output end @@ -111,7 +110,7 @@ def test_execute_local_dependency_nonexistent orig_dir = Dir.pwd begin Dir.chdir @tempdir - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end assert_equal 2, e.exit_code @@ -143,7 +142,7 @@ def test_execute_local_dependency_nonexistent_ignore_dependencies orig_dir = Dir.pwd begin Dir.chdir orig_dir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -174,7 +173,7 @@ def test_execute_local_transitive_prerelease begin Dir.chdir @tempdir FileUtils.rm_r [@gemhome, "gems"] - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -182,14 +181,14 @@ def test_execute_local_transitive_prerelease end end - assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map { |spec| spec.full_name }.sort + assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map {|spec| spec.full_name }.sort assert_match "3 gems installed", @ui.output end def test_execute_no_user_install - skip 'skipped on MS Windows (chmod has no effect)' if win_platform? - skip 'skipped in root privilege' if Process.uid.zero? + pend 'skipped on MS Windows (chmod has no effect)' if win_platform? + pend 'skipped in root privilege' if Process.uid.zero? specs = spec_fetcher do |fetcher| fetcher.gem 'a', 2 @@ -208,7 +207,7 @@ def test_execute_no_user_install FileUtils.chmod 0555, @gemhome Dir.chdir @tempdir - assert_raises Gem::FilePermissionError do + assert_raise Gem::FilePermissionError do @cmd.execute end ensure @@ -226,7 +225,7 @@ def test_execute_local_missing @cmd.options[:args] = %w[no_such_gem] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end assert_equal 2, e.exit_code @@ -245,7 +244,7 @@ def test_execute_local_missing_ignore_dependencies @cmd.options[:args] = %w[no_such_gem] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end assert_equal 2, e.exit_code @@ -258,7 +257,7 @@ def test_execute_local_missing_ignore_dependencies def test_execute_no_gem @cmd.options[:args] = %w[] - assert_raises Gem::CommandLineError do + assert_raise Gem::CommandLineError do @cmd.execute end end @@ -269,7 +268,23 @@ def test_execute_nonexistent @cmd.options[:args] = %w[nonexistent] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do + @cmd.execute + end + assert_equal 2, e.exit_code + end + + assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error) + end + + def test_execute_nonexistent_force + spec_fetcher + + @cmd.options[:args] = %w[nonexistent] + @cmd.options[:force] = true + + use_ui @ui do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end assert_equal 2, e.exit_code @@ -286,7 +301,7 @@ def test_execute_dependency_nonexistent @cmd.options[:args] = ['foo'] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -302,7 +317,7 @@ def test_execute_dependency_nonexistent def test_execute_http_proxy use_ui @ui do - e = assert_raises ArgumentError, @ui.error do + e = assert_raise ArgumentError, @ui.error do @cmd.handle_options %w[-p=foo.bar.com] end @@ -328,7 +343,7 @@ def test_execute_bad_source @cmd.options[:args] = %w[nonexistent] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end assert_equal 2, e.exit_code @@ -337,7 +352,7 @@ def test_execute_bad_source errs = @ui.error.split("\n") assert_match(/ould not find a valid gem 'nonexistent'/, errs.shift) - assert_match(%r!Unable to download data from http://not-there.nothing!, errs.shift) + assert_match(%r{Unable to download data from http://not-there.nothing}, errs.shift) end def test_execute_nonexistent_hint_disabled @@ -352,7 +367,7 @@ def test_execute_nonexistent_hint_disabled @cmd.options[:suggest_alternate] = false use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -377,7 +392,7 @@ def test_execute_nonexistent_with_hint @cmd.options[:args] = [misspelled] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -402,7 +417,7 @@ def test_execute_nonexistent_with_dashes @cmd.options[:args] = [misspelled] use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -411,7 +426,7 @@ def test_execute_nonexistent_with_dashes expected = [ "ERROR: Could not find a valid gem 'non-existent_with-hint' (>= 0) in any repository", - "ERROR: Possible alternatives: nonexistent-with_hint" + "ERROR: Possible alternatives: nonexistent-with_hint", ] output = @ui.error.split "\n" @@ -424,7 +439,7 @@ def test_execute_conflicting_install_options @cmd.options[:install_dir] = "whatever" use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -444,12 +459,12 @@ def test_execute_prerelease_skipped_when_no_flag_set @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_prerelease_wins_over_previous_ver @@ -462,12 +477,12 @@ def test_execute_prerelease_wins_over_previous_ver @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2.a], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_with_version_specified_by_colon @@ -479,12 +494,12 @@ def test_execute_with_version_specified_by_colon @cmd.options[:args] = %w[a:1] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_prerelease_skipped_when_non_pre_available @@ -497,12 +512,143 @@ def test_execute_prerelease_skipped_when_non_pre_available @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + end + + def test_execute_required_ruby_version + next_ruby = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".") + + local = Gem::Platform.local + spec_fetcher do |fetcher| + fetcher.download 'a', 2 + fetcher.download 'a', 2 do |s| + s.required_ruby_version = "< #{RUBY_VERSION}.a" + s.platform = local + end + fetcher.download 'a', 3 do |s| + s.required_ruby_version = ">= #{next_ruby}" + end + fetcher.download 'a', 3 do |s| + s.required_ruby_version = ">= #{next_ruby}" + s.platform = local + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + end + + def test_execute_required_ruby_version_upper_bound + local = Gem::Platform.local + spec_fetcher do |fetcher| + fetcher.gem 'a', 2.0 + fetcher.gem 'a', 2.0 do |s| + s.required_ruby_version = "< #{RUBY_VERSION}.a" + s.platform = local + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-2.0], @cmd.installed_specs.map {|spec| spec.full_name } + end + + def test_execute_required_ruby_version_specific_not_met + spec_fetcher do |fetcher| + fetcher.gem 'a', '1.0' do |s| + s.required_ruby_version = '= 1.4.6' + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + @cmd.execute + end + end + + errs = @ui.error.split("\n") + assert_equal "ERROR: Error installing a:", errs.shift + assert_equal "\ta-1.0 requires Ruby version = 1.4.6. The current ruby version is #{Gem.ruby_version}.", errs.shift + end + + def test_execute_required_ruby_version_specific_prerelease_met + spec_fetcher do |fetcher| + fetcher.gem 'a', '1.0' do |s| + s.required_ruby_version = '>= 1.4.6.preview2' + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-1.0], @cmd.installed_specs.map {|spec| spec.full_name } + end + + def test_execute_required_ruby_version_specific_prerelease_not_met + next_ruby_pre = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".") + ".a" + + spec_fetcher do |fetcher| + fetcher.gem 'a', '1.0' do |s| + s.required_ruby_version = "> #{next_ruby_pre}" + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + @cmd.execute + end + end + + errs = @ui.error.split("\n") + assert_equal "ERROR: Error installing a:", errs.shift + assert_equal "\ta-1.0 requires Ruby version > #{next_ruby_pre}. The current ruby version is #{Gem.ruby_version}.", errs.shift + end + + def test_execute_required_rubygems_version_wrong + spec_fetcher do |fetcher| + fetcher.gem 'a', '1.0' do |s| + s.required_rubygems_version = '< 0' + end + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + errs = @ui.error.split("\n") + assert_equal "ERROR: Error installing a:", errs.shift + assert_equal "\ta-1.0 requires RubyGems version < 0. The current RubyGems version is #{Gem.rubygems_version}. Try 'gem update --system' to update RubyGems itself.", errs.shift end def test_execute_rdoc @@ -527,7 +673,7 @@ def test_execute_rdoc begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -537,8 +683,8 @@ def test_execute_rdoc wait_for_child_process_to_exit - assert_path_exists File.join(a2.doc_dir, 'ri') - assert_path_exists File.join(a2.doc_dir, 'rdoc') + assert_path_exist File.join(a2.doc_dir, 'ri') + assert_path_exist File.join(a2.doc_dir, 'rdoc') end def test_execute_rdoc_with_path @@ -564,7 +710,7 @@ def test_execute_rdoc_with_path begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -574,7 +720,7 @@ def test_execute_rdoc_with_path wait_for_child_process_to_exit - assert_path_exists 'whatever/doc/a-2', 'documentation not installed' + assert_path_exist 'whatever/doc/a-2', 'documentation not installed' end def test_execute_saves_build_args @@ -582,7 +728,7 @@ def test_execute_saves_build_args fetcher.gem 'a', 2 end - args = %w!--with-awesome=true --more-awesome=yes! + args = %w[--with-awesome=true --more-awesome=yes] Gem::Command.build_args = args @@ -600,7 +746,7 @@ def test_execute_saves_build_args begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -609,7 +755,7 @@ def test_execute_saves_build_args end path = a2.build_info_file - assert_path_exists path + assert_path_exist path assert_equal args, a2.build_args end @@ -622,12 +768,12 @@ def test_execute_remote @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "1 gem installed", @ui.output end @@ -642,16 +788,49 @@ def test_execute_with_invalid_gem_file @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "1 gem installed", @ui.output end + def test_execute_remote_truncates_existing_gemspecs + spec_fetcher do |fetcher| + fetcher.gem 'a', 1 + end + + @cmd.options[:domain] = :remote + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_match "1 gem installed", @ui.output + + a1_gemspec = File.join(@gemhome, 'specifications', "a-1.gemspec") + + initial_a1_gemspec_content = File.read(a1_gemspec) + modified_a1_gemspec_content = initial_a1_gemspec_content + "\n # AAAAAAA\n" + File.write(a1_gemspec, modified_a1_gemspec_content) + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal initial_a1_gemspec_content, File.read(a1_gemspec) + end + def test_execute_remote_ignores_files specs = spec_fetcher do |fetcher| fetcher.gem 'a', 1 @@ -682,13 +861,13 @@ def test_execute_remote_ignores_files use_ui @ui do Dir.chdir @tempdir do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end end - assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "1 gem installed", @ui.output @@ -714,7 +893,7 @@ def test_execute_two orig_dir = Dir.pwd begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end ensure @@ -722,7 +901,7 @@ def test_execute_two end end - assert_equal %w[a-2 b-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2 b-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "2 gems installed", @ui.output end @@ -732,7 +911,7 @@ def test_execute_two_version @cmd.options[:version] = Gem::Requirement.new("> 1") use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -759,12 +938,12 @@ def test_execute_two_version_specified_by_colon @cmd.options[:args] = %w[a:1 b:1] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-1 b-1], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-1 b-1], @cmd.installed_specs.map {|spec| spec.full_name } end def test_execute_conservative @@ -782,7 +961,7 @@ def test_execute_conservative orig_dir = Dir.pwd begin Dir.chdir @tempdir - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do @cmd.execute end ensure @@ -790,7 +969,7 @@ def test_execute_conservative end end - assert_equal %w[b-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[b-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_equal "", @ui.error assert_match "1 gem installed", @ui.output @@ -812,7 +991,7 @@ def test_install_gem_ignore_dependencies_both @cmd.install_gem 'a', '>= 0' - assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name } assert done_installing, 'documentation was not generated' end @@ -826,7 +1005,7 @@ def test_install_gem_ignore_dependencies_remote @cmd.install_gem 'a', '>= 0' - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } end def test_install_gem_ignore_dependencies_remote_platform_local @@ -843,7 +1022,7 @@ def test_install_gem_ignore_dependencies_remote_platform_local @cmd.install_gem 'a', '>= 0' - assert_equal %W[a-3-#{local}], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %W[a-3-#{local}], @cmd.installed_specs.map {|spec| spec.full_name } end def test_install_gem_ignore_dependencies_specific_file @@ -857,7 +1036,7 @@ def test_install_gem_ignore_dependencies_specific_file @cmd.install_gem File.join(@tempdir, spec.file_name), nil - assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name } end def test_parses_requirement_from_gemname @@ -877,7 +1056,7 @@ def test_parses_requirement_from_gemname orig_dir = Dir.pwd begin Dir.chdir @tempdir - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end ensure @@ -886,7 +1065,7 @@ def test_parses_requirement_from_gemname end assert_equal 2, e.exit_code - assert_match %r!Could not find a valid gem 'a' \(= 10.0\)!, @ui.error + assert_match %r{Could not find a valid gem 'a' \(= 10.0\)}, @ui.error end def test_show_errors_on_failure @@ -899,7 +1078,7 @@ def test_show_errors_on_failure orig_dir = Dir.pwd begin Dir.chdir @tempdir - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end ensure @@ -922,12 +1101,12 @@ def test_show_source_problems_even_on_success @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "1 gem installed", @ui.output @@ -937,6 +1116,31 @@ def test_show_source_problems_even_on_success assert_equal x, e end + def test_redact_credentials_from_uri_on_warning + spec_fetcher do |fetcher| + fetcher.download 'a', 2 + end + + Gem.sources << "http://username:SECURE_TOKEN@nonexistent.example" + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + + assert_match "1 gem installed", @ui.output + + e = @ui.error + + x = "WARNING: Unable to pull data from 'http://username:REDACTED@nonexistent.example': no data for http://username:REDACTED@nonexistent.example/specs.4.8.gz (http://username:REDACTED@nonexistent.example/specs.4.8.gz)\n" + assert_equal x, e + end + def test_execute_uses_from_a_gemdeps spec_fetcher do |fetcher| fetcher.gem 'a', 2 @@ -949,12 +1153,12 @@ def test_execute_uses_from_a_gemdeps @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "Using a (2)", @ui.output assert File.exist?("#{@gemdeps}.lock") @@ -973,12 +1177,12 @@ def test_execute_uses_from_a_gemdeps_with_no_lock @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "Using a (2)", @ui.output assert !File.exist?("#{@gemdeps}.lock") @@ -998,12 +1202,12 @@ def test_execute_installs_from_a_gemdeps_with_conservative @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "Using a (1)", @ui.output end @@ -1020,12 +1224,12 @@ def test_execute_installs_from_a_gemdeps @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } assert_match "Installing a (2)", @ui.output end @@ -1043,12 +1247,12 @@ def test_execute_installs_deps_a_gemdeps @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - names = @cmd.installed_specs.map { |spec| spec.full_name } + names = @cmd.installed_specs.map {|spec| spec.full_name } assert_equal %w[q-1.0 r-2.0], names @@ -1070,12 +1274,12 @@ def test_execute_uses_deps_a_gemdeps @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - names = @cmd.installed_specs.map { |spec| spec.full_name } + names = @cmd.installed_specs.map {|spec| spec.full_name } assert_equal %w[r-2.0], names @@ -1097,12 +1301,12 @@ def test_execute_installs_deps_a_gemdeps_into_a_path @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - names = @cmd.installed_specs.map { |spec| spec.full_name } + names = @cmd.installed_specs.map {|spec| spec.full_name } assert_equal %w[q-1.0 r-2.0], names @@ -1129,12 +1333,12 @@ def test_execute_with_gemdeps_path_ignores_system @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - names = @cmd.installed_specs.map { |spec| spec.full_name } + names = @cmd.installed_specs.map {|spec| spec.full_name } assert_equal %w[q-1.0 r-2.0], names @@ -1164,12 +1368,12 @@ def test_execute_uses_deps_a_gemdeps_with_a_path @cmd.options[:gemdeps] = @gemdeps use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end - names = @cmd.installed_specs.map { |spec| spec.full_name } + names = @cmd.installed_specs.map {|spec| spec.full_name } assert_equal %w[r-2.0], names @@ -1249,7 +1453,7 @@ def test_explain_platform_local @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end @@ -1276,7 +1480,7 @@ def test_explain_platform_local_ignore_dependencies @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end @@ -1305,7 +1509,7 @@ def test_explain_platform_ruby @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end @@ -1335,7 +1539,7 @@ def test_explain_platform_ruby_ignore_dependencies @cmd.options[:args] = %w[a] use_ui @ui do - assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do @cmd.execute end end @@ -1346,5 +1550,4 @@ def test_explain_platform_ruby_ignore_dependencies assert_equal " a-3", out.shift assert_empty out end - end diff --git a/ruby/test/rubygems/test_gem_commands_list_command.rb b/ruby/test/rubygems/test_gem_commands_list_command.rb index a44ccb417..d8cffce7a 100644 --- a/ruby/test/rubygems/test_gem_commands_list_command.rb +++ b/ruby/test/rubygems/test_gem_commands_list_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/list_command' class TestGemCommandsListCommand < Gem::TestCase - def setup super @@ -21,7 +20,7 @@ def setup def test_execute_installed @cmd.handle_options %w[c --installed] - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do use_ui @ui do @cmd.execute end @@ -30,5 +29,4 @@ def test_execute_installed assert_equal "true\n", @ui.output assert_equal '', @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_lock_command.rb b/ruby/test/rubygems/test_gem_commands_lock_command.rb index a35ed081c..f8afca1e2 100644 --- a/ruby/test/rubygems/test_gem_commands_lock_command.rb +++ b/ruby/test/rubygems/test_gem_commands_lock_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/lock_command' class TestGemCommandsLockCommand < Gem::TestCase - def setup super @@ -56,7 +55,7 @@ def test_execute_missing_dependency def test_execute_strict @cmd.handle_options %w[c-1 --strict] - e = assert_raises Gem::Exception do + e = assert_raise Gem::Exception do use_ui @ui do @cmd.execute end @@ -64,5 +63,4 @@ def test_execute_strict assert_equal 'Could not find gem c-1, try using the full name', e.message end - end diff --git a/ruby/test/rubygems/test_gem_commands_mirror.rb b/ruby/test/rubygems/test_gem_commands_mirror.rb index 07ec9f3d0..470f1c30f 100644 --- a/ruby/test/rubygems/test_gem_commands_mirror.rb +++ b/ruby/test/rubygems/test_gem_commands_mirror.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/mirror_command' class TestGemCommandsMirrorCommand < Gem::TestCase - def setup super @@ -15,7 +14,6 @@ def test_execute @cmd.execute end - assert_match %r%Install the rubygems-mirror%i, @ui.error + assert_match %r{Install the rubygems-mirror}i, @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_open_command.rb b/ruby/test/rubygems/test_gem_commands_open_command.rb index e73a13820..29cff1ed9 100644 --- a/ruby/test/rubygems/test_gem_commands_open_command.rb +++ b/ruby/test/rubygems/test_gem_commands_open_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/open_command' class TestGemCommandsOpenCommand < Gem::TestCase - def setup super @@ -22,20 +21,19 @@ def gem(name, version = "1.0") def test_execute @cmd.options[:args] = %w[foo] - @cmd.options[:editor] = "#{Gem.ruby} -e0 --" + @cmd.options[:editor] = "#{ruby_with_rubygems_in_load_path} -eexit --" gem 'foo', '1.0.0' spec = gem 'foo', '1.0.1' - mock = MiniTest::Mock.new - mock.expect(:call, true, [spec.full_gem_path]) - Dir.stub(:chdir, mock) do - use_ui @ui do - @cmd.execute + assert_nothing_raised Gem::MockGemUi::TermError do + Dir.stub(:chdir, spec.full_gem_path) do + use_ui @ui do + @cmd.execute + end end end - assert mock.verify assert_equal "", @ui.error end @@ -45,26 +43,26 @@ def test_wrong_version gem "foo", "5.0" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end end - assert_match %r|Unable to find gem 'foo'|, @ui.output + assert_match %r{Unable to find gem 'foo'}, @ui.output assert_equal "", @ui.error end def test_execute_bad_gem @cmd.options[:args] = %w[foo] - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end end - assert_match %r|Unable to find gem 'foo'|, @ui.output + assert_match %r{Unable to find gem 'foo'}, @ui.output assert_equal "", @ui.error end @@ -87,14 +85,13 @@ def test_default_gem gem("foo", "1.0") - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end end - assert_match %r|'foo' is a default gem and can't be opened\.| , @ui.output + assert_match %r{'foo' is a default gem and can't be opened\.} , @ui.output assert_equal "", @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_outdated_command.rb b/ruby/test/rubygems/test_gem_commands_outdated_command.rb index 3c37e22a0..dc5c40a78 100644 --- a/ruby/test/rubygems/test_gem_commands_outdated_command.rb +++ b/ruby/test/rubygems/test_gem_commands_outdated_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/outdated_command' class TestGemCommandsOutdatedCommand < Gem::TestCase - def setup super @@ -30,4 +29,21 @@ def test_execute assert_equal "", @ui.error end + def test_execute_with_up_to_date_platform_specific_gem + spec_fetcher do |fetcher| + fetcher.download 'foo', '2.0' + + fetcher.gem 'foo', '1.0' + fetcher.gem 'foo', '2.0' do |s| + s.platform = Gem::Platform.local + end + end + + use_ui @ui do + @cmd.execute + end + + assert_equal "", @ui.output + assert_equal "", @ui.error + end end diff --git a/ruby/test/rubygems/test_gem_commands_owner_command.rb b/ruby/test/rubygems/test_gem_commands_owner_command.rb index 799d631f8..5b06b628c 100644 --- a/ruby/test/rubygems/test_gem_commands_owner_command.rb +++ b/ruby/test/rubygems/test_gem_commands_owner_command.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/owner_command' class TestGemCommandsOwnerCommand < Gem::TestCase - def setup super + credential_setup + ENV["RUBYGEMS_HOST"] = nil @stub_ui = Gem::MockGemUi.new @stub_fetcher = Gem::FakeFetcher.new @@ -17,6 +18,12 @@ def setup @cmd = Gem::Commands::OwnerCommand.new end + def teardown + credential_teardown + + super + end + def test_show_owners response = < build_args @@ -360,10 +356,10 @@ def test_execute_many_multi_repo assert_equal "Restored #{b.full_name}", out.shift assert_empty out, out.inspect - assert_path_exists File.join(@gemhome, "gems", 'a-2') - refute_path_exists File.join(gemhome2, "gems", 'a-2') - assert_path_exists File.join(gemhome2, "gems", 'b-2') - refute_path_exists File.join(@gemhome, "gems", 'b-2') + assert_path_exist File.join(@gemhome, "gems", 'a-2') + assert_path_not_exist File.join(gemhome2, "gems", 'a-2') + assert_path_exist File.join(gemhome2, "gems", 'b-2') + assert_path_not_exist File.join(@gemhome, "gems", 'b-2') end def test_execute_missing_cache_gem @@ -438,27 +434,27 @@ def test_execute_missing_cache_gem_when_multi_repo assert_empty out, out.inspect assert_empty @ui.error - assert_path_exists File.join(@gemhome, "cache", 'a-1.gem') - refute_path_exists File.join(gemhome2, "cache", 'a-2.gem') - assert_path_exists File.join(@gemhome, "gems", 'a-1') - refute_path_exists File.join(gemhome2, "gems", 'a-1') + assert_path_exist File.join(@gemhome, "cache", 'a-1.gem') + assert_path_not_exist File.join(gemhome2, "cache", 'a-2.gem') + assert_path_exist File.join(@gemhome, "gems", 'a-1') + assert_path_not_exist File.join(gemhome2, "gems", 'a-1') - assert_path_exists File.join(gemhome2, "cache", 'b-1.gem') - refute_path_exists File.join(@gemhome, "cache", 'b-2.gem') - assert_path_exists File.join(gemhome2, "gems", 'b-1') - refute_path_exists File.join(@gemhome, "gems", 'b-1') + assert_path_exist File.join(gemhome2, "cache", 'b-1.gem') + assert_path_not_exist File.join(@gemhome, "cache", 'b-2.gem') + assert_path_exist File.join(gemhome2, "gems", 'b-1') + assert_path_not_exist File.join(@gemhome, "gems", 'b-1') end def test_execute_no_gem @cmd.options[:args] = %w[] - e = assert_raises Gem::CommandLineError do + e = assert_raise Gem::CommandLineError do use_ui @ui do @cmd.execute end end - assert_match %r|at least one gem name|, e.message + assert_match %r{at least one gem name}, e.message end def test_execute_only_executables @@ -491,6 +487,42 @@ def test_execute_only_executables refute File.exist? gem_lib end + def test_execute_only_plugins + a = util_spec 'a' do |s| + s.executables = %w[foo] + s.files = %w[bin/foo lib/a.rb lib/rubygems_plugin.rb] + end + write_file File.join(@tempdir, 'lib', 'a.rb') do |fp| + fp.puts "puts __FILE__" + end + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |fp| + fp.puts "puts __FILE__" + end + write_file File.join(@tempdir, 'bin', 'foo') do |fp| + fp.puts "#!/usr/bin/ruby" + end + + install_gem a + + gem_lib = File.join @gemhome, 'gems', a.full_name, 'lib', 'a.rb' + gem_plugin = File.join @gemhome, 'plugins', 'a_plugin.rb' + gem_exec = File.join @gemhome, 'bin', 'foo' + + FileUtils.rm gem_exec + FileUtils.rm gem_plugin + FileUtils.rm gem_lib + + @cmd.handle_options %w[--all --only-plugins] + + use_ui @ui do + @cmd.execute + end + + refute File.exist? gem_exec + assert File.exist? gem_plugin + refute File.exist? gem_lib + end + def test_execute_bindir a = util_spec 'a' do |s| s.name = "test_gem" @@ -536,7 +568,7 @@ def test_execute_unknown_gem_at_remote_source assert_equal([ "Restoring gems to pristine condition...", "Cached gem for a-2 not found, attempting to fetch...", - "Skipped a-2, it was not found from cache and remote sources" + "Skipped a-2, it was not found from cache and remote sources", ], @ui.output.split("\n")) assert_empty @ui.error @@ -545,7 +577,7 @@ def test_execute_unknown_gem_at_remote_source def test_execute_default_gem default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) @cmd.options[:args] = %w[default] @@ -623,5 +655,4 @@ def test_handle_options_extensions assert @cmd.options[:extensions] assert @cmd.options[:extensions_set] end - end diff --git a/ruby/test/rubygems/test_gem_commands_push_command.rb b/ruby/test/rubygems/test_gem_commands_push_command.rb index f666c6d43..fa3968ffc 100644 --- a/ruby/test/rubygems/test_gem_commands_push_command.rb +++ b/ruby/test/rubygems/test_gem_commands_push_command.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/push_command' class TestGemCommandsPushCommand < Gem::TestCase - def setup super + + credential_setup + ENV["RUBYGEMS_HOST"] = nil Gem.host = Gem::DEFAULT_HOST Gem.configuration.disable_default_gem_server = false @@ -37,6 +39,8 @@ def latest_rubygems_version end def teardown + credential_teardown + super singleton_gem_class.class_eval do @@ -119,7 +123,7 @@ def test_sending_when_default_host_disabled Gem.configuration.disable_default_gem_server = true response = "You must specify a gem server" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.send_gem(@path) end @@ -148,10 +152,9 @@ def test_sending_gem_to_metadata_host keys = { :rubygems_api_key => 'KEY', - @host => @api_key + @host => @api_key, } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -183,10 +186,9 @@ def test_sending_gem_to_allowed_push_host keys = { :rubygems_api_key => 'KEY', - @host => @api_key + @host => @api_key, } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -228,7 +230,6 @@ def test_sending_gem_to_allowed_push_host_with_basic_credentials :rubygems_api_key => @api_key, } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -246,9 +247,9 @@ def test_sending_gem_to_disallowed_default_host spec.metadata['allowed_push_host'] = "https://privategemserver.example" end - response = %{ERROR: "#{@host}" is not allowed by the gemspec, which only allows "https://privategemserver.example"} + response = %(ERROR: "#{@host}" is not allowed by the gemspec, which only allows "https://privategemserver.example") - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do send_battery end @@ -267,10 +268,9 @@ def test_sending_gem_to_disallowed_push_host keys = { :rubygems_api_key => 'KEY', - @host => @api_key + @host => @api_key, } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -280,7 +280,7 @@ def test_sending_gem_to_disallowed_push_host response = "ERROR: \"#{@host}\" is not allowed by the gemspec, which only allows \"#{push_host}\"" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do send_battery end @@ -298,10 +298,9 @@ def test_sending_gem_defaulting_to_allowed_push_host api_key = "PRIVKEY" keys = { - host => api_key + host => api_key, } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -328,7 +327,7 @@ def test_sending_gem_defaulting_to_allowed_push_host def test_raises_error_with_no_arguments def @cmd.sign_in(*); end - assert_raises Gem::CommandLineError do + assert_raise Gem::CommandLineError do @cmd.execute end end @@ -338,7 +337,7 @@ def test_sending_gem_denied @fetcher.data["#{@host}/api/v1/gems"] = [response, 403, 'Forbidden'] @cmd.instance_variable_set :@host, @host - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.send_gem(@path) end @@ -355,7 +354,7 @@ def test_sending_gem_key end Gem.configuration.load_api_keys - @cmd.handle_options %w(-k other) + @cmd.handle_options %w[-k other] @cmd.instance_variable_set :@host, @host @cmd.send_gem(@path) @@ -369,7 +368,7 @@ def test_otp_verified_success @fetcher.data["#{Gem.host}/api/v1/gems"] = [ [response_fail, 401, 'Unauthorized'], - [response_success, 200, 'OK'] + [response_success, 200, 'OK'], ] @otp_ui = Gem::MockGemUi.new "111111\n" @@ -388,7 +387,7 @@ def test_otp_verified_failure @fetcher.data["#{Gem.host}/api/v1/gems"] = [response, 401, 'Unauthorized'] @otp_ui = Gem::MockGemUi.new "111111\n" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @otp_ui do @cmd.send_gem(@path) end @@ -400,10 +399,74 @@ def test_otp_verified_failure assert_equal '111111', @fetcher.last_request['OTP'] end + def test_sending_gem_unathorized_api_key_with_mfa_enabled + response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + response_forbidden = "The API key doesn't have access" + response_success = 'Successfully registered gem: freewill (1.0.0)' + + @fetcher.data["#{@host}/api/v1/gems"] = [ + [response_mfa_enabled, 401, 'Unauthorized'], + [response_forbidden, 403, 'Forbidden'], + [response_success, 200, "OK"], + ] + + @fetcher.data["#{@host}/api/v1/api_key"] = ["", 200, "OK"] + @cmd.instance_variable_set :@host, @host + @cmd.instance_variable_set :@scope, :push_rubygem + + @ui = Gem::MockGemUi.new "11111\nsome@mail.com\npass\n" + use_ui @ui do + @cmd.send_gem(@path) + end + + mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code." + access_notice = "The existing key doesn't have access of push_rubygem on https://rubygems.example. Please sign in to update access." + assert_match mfa_notice, @ui.output + assert_match access_notice, @ui.output + assert_match "Email:", @ui.output + assert_match "Password:", @ui.output + assert_match "Added push_rubygem scope to the existing API key", @ui.output + assert_match response_success, @ui.output + assert_equal '11111', @fetcher.last_request['OTP'] + end + + def test_sending_gem_with_no_local_creds + Gem.configuration.rubygems_api_key = nil + + response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + response_success = 'Successfully registered gem: freewill (1.0.0)' + + @fetcher.data["#{@host}/api/v1/gems"] = [ + [response_success, 200, "OK"], + ] + + @fetcher.data["#{@host}/api/v1/api_key"] = [ + [response_mfa_enabled, 401, 'Unauthorized'], + ["", 200, "OK"], + ] + + @cmd.instance_variable_set :@scope, :push_rubygem + @cmd.options[:args] = [@path] + @cmd.options[:host] = @host + + @ui = Gem::MockGemUi.new "some@mail.com\npass\n11111\n" + use_ui @ui do + @cmd.execute + end + + mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code." + assert_match mfa_notice, @ui.output + assert_match "Enter your https://rubygems.example credentials.", @ui.output + assert_match "Email:", @ui.output + assert_match "Password:", @ui.output + assert_match "Signed in with API key:", @ui.output + assert_match response_success, @ui.output + assert_equal '11111', @fetcher.last_request['OTP'] + end + private def singleton_gem_class class << Gem; self; end end - end diff --git a/ruby/test/rubygems/test_gem_commands_query_command.rb b/ruby/test/rubygems/test_gem_commands_query_command.rb index 6183e592e..0cc88b168 100644 --- a/ruby/test/rubygems/test_gem_commands_query_command.rb +++ b/ruby/test/rubygems/test_gem_commands_query_command.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/query_command' module TestGemCommandsQueryCommandSetup @@ -19,7 +19,6 @@ def setup end class TestGemCommandsQueryCommandWithInstalledGems < Gem::TestCase - include TestGemCommandsQueryCommandSetup def test_execute @@ -214,7 +213,7 @@ def test_execute_details_truncates_summary def test_execute_installed @cmd.handle_options %w[-n a --installed] - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do use_ui @stub_ui do @cmd.execute end @@ -227,7 +226,7 @@ def test_execute_installed def test_execute_installed_inverse @cmd.handle_options %w[-n a --no-installed] - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -242,7 +241,7 @@ def test_execute_installed_inverse def test_execute_installed_inverse_not_installed @cmd.handle_options %w[-n not_installed --no-installed] - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do use_ui @stub_ui do @cmd.execute end @@ -255,7 +254,7 @@ def test_execute_installed_inverse_not_installed def test_execute_installed_no_name @cmd.handle_options %w[--installed] - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -270,7 +269,7 @@ def test_execute_installed_no_name def test_execute_installed_not_installed @cmd.handle_options %w[-n not_installed --installed] - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -285,7 +284,7 @@ def test_execute_installed_not_installed def test_execute_installed_version @cmd.handle_options %w[-n a --installed --version 2] - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do use_ui @stub_ui do @cmd.execute end @@ -298,7 +297,7 @@ def test_execute_installed_version def test_execute_installed_version_not_installed @cmd.handle_options %w[-n c --installed --version 2] - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @cmd.execute end @@ -580,8 +579,8 @@ def test_execute_multiple_args @cmd.execute end - assert_match %r%^a %, @stub_ui.output - assert_match %r%^pl %, @stub_ui.output + assert_match %r{^a }, @stub_ui.output + assert_match %r{^pl }, @stub_ui.output assert_equal '', @stub_ui.error end @@ -593,8 +592,8 @@ def test_show_gems @cmd.send :show_gems, /a/i end - assert_match %r%^a %, @stub_ui.output - refute_match %r%^pl %, @stub_ui.output + assert_match %r{^a }, @stub_ui.output + refute_match %r{^pl }, @stub_ui.output assert_empty @stub_ui.error end @@ -607,11 +606,9 @@ def add_gems_to_fetcher fetcher.spec 'a', '3.a' end end - end class TestGemCommandsQueryCommandWithoutInstalledGems < Gem::TestCase - include TestGemCommandsQueryCommandSetup def test_execute_platform @@ -644,10 +641,10 @@ def test_execute_platform end def test_execute_show_default_gems - spec_fetcher { |fetcher| fetcher.spec 'a', 2 } + spec_fetcher {|fetcher| fetcher.spec 'a', 2 } a1 = new_default_spec 'a', 1 - install_default_specs a1 + install_default_gems a1 use_ui @stub_ui do @cmd.execute @@ -666,7 +663,7 @@ def test_execute_show_default_gems def test_execute_show_default_gems_with_platform a1 = new_default_spec 'a', 1 a1.platform = 'java' - install_default_specs a1 + install_default_gems a1 use_ui @stub_ui do @cmd.execute @@ -688,7 +685,7 @@ def test_execute_default_details end a1 = new_default_spec 'a', 1 - install_default_specs a1 + install_default_gems a1 @cmd.handle_options %w[-l -d] @@ -844,6 +841,10 @@ def test_execute_exact_multiple assert_equal expected, @stub_ui.output end + def test_depprecated + assert @cmd.deprecated? + end + private def add_gems_to_fetcher @@ -853,5 +854,4 @@ def add_gems_to_fetcher fetcher.download 'a', '3.a' end end - end diff --git a/ruby/test/rubygems/test_gem_commands_search_command.rb b/ruby/test/rubygems/test_gem_commands_search_command.rb index 9187050c3..6397dbd4d 100644 --- a/ruby/test/rubygems/test_gem_commands_search_command.rb +++ b/ruby/test/rubygems/test_gem_commands_search_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/search_command' class TestGemCommandsSearchCommand < Gem::TestCase - def setup super @@ -13,5 +12,4 @@ def setup def test_initialize assert_equal :remote, @cmd.defaults[:domain] end - end diff --git a/ruby/test/rubygems/test_gem_commands_server_command.rb b/ruby/test/rubygems/test_gem_commands_server_command.rb index af15aadfd..96c328f93 100644 --- a/ruby/test/rubygems/test_gem_commands_server_command.rb +++ b/ruby/test/rubygems/test_gem_commands_server_command.rb @@ -1,63 +1,19 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/server_command' class TestGemCommandsServerCommand < Gem::TestCase - def setup super @cmd = Gem::Commands::ServerCommand.new end - def test_handle_options - @cmd.send :handle_options, %w[-p 8808 --no-daemon] - - assert_equal false, @cmd.options[:daemon] - assert_equal [], @cmd.options[:gemdir] - assert_equal 8808, @cmd.options[:port] - - @cmd.send :handle_options, %w[-p 9999 -d /nonexistent --daemon] - - assert_equal true, @cmd.options[:daemon] - assert_equal [File.expand_path('/nonexistent')], @cmd.options[:gemdir] - assert_equal 9999, @cmd.options[:port] - end - - def test_handle_options_gemdir - @cmd.send :handle_options, %w[--dir a --dir b] - - assert_equal [File.expand_path('a'), File.expand_path('b')], - @cmd.options[:gemdir] - end - - def test_handle_options_port - @cmd.send :handle_options, %w[-p 0] - assert_equal 0, @cmd.options[:port] - - @cmd.send :handle_options, %w[-p 65535] - assert_equal 65535, @cmd.options[:port] - - begin - @cmd.send :handle_options, %w[-p discard] - assert_equal 9, @cmd.options[:port] - rescue OptionParser::InvalidArgument - # for container environment on GitHub Actions - end - - e = assert_raises OptionParser::InvalidArgument do - @cmd.send :handle_options, %w[-p nonexistent] + def test_execute + use_ui @ui do + @cmd.execute end - assert_equal 'invalid argument: -p nonexistent: no such named service', - e.message - - e = assert_raises OptionParser::InvalidArgument do - @cmd.send :handle_options, %w[-p 65536] - end - - assert_equal 'invalid argument: -p 65536: not a port number', - e.message + assert_match %r{Install the rubygems-server}i, @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_setup_command.rb b/ruby/test/rubygems/test_gem_commands_setup_command.rb index c63f7177c..5cf94a1dc 100644 --- a/ruby/test/rubygems/test_gem_commands_setup_command.rb +++ b/ruby/test/rubygems/test_gem_commands_setup_command.rb @@ -1,11 +1,9 @@ -# coding: UTF-8 # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/setup_command' class TestGemCommandsSetupCommand < Gem::TestCase - bundler_gemspec = File.expand_path("../../../bundler/lib/bundler/version.rb", __FILE__) if File.exist?(bundler_gemspec) BUNDLER_VERS = File.read(bundler_gemspec).match(/VERSION = "(#{Gem::Version::VERSION_PATTERN})"/)[1] @@ -16,86 +14,50 @@ class TestGemCommandsSetupCommand < Gem::TestCase def setup super - @install_dir = File.join @tempdir, 'install' @cmd = Gem::Commands::SetupCommand.new - @cmd.options[:prefix] = @install_dir - - FileUtils.mkdir_p 'bin' - FileUtils.mkdir_p 'lib/rubygems/ssl_certs/rubygems.org' - - File.open 'bin/gem', 'w' do - |io| io.puts '# gem' - end - - File.open 'lib/rubygems.rb', 'w' do |io| - io.puts '# rubygems.rb' - end - - File.open 'lib/rubygems/test_case.rb', 'w' do |io| - io.puts '# test_case.rb' - end - - File.open 'lib/rubygems/ssl_certs/rubygems.org/foo.pem', 'w' do |io| - io.puts 'PEM' - end - - FileUtils.mkdir_p 'bundler/exe' - FileUtils.mkdir_p 'bundler/lib/bundler' - File.open 'bundler/exe/bundle', 'w' do |io| - io.puts '# bundle' - end - - File.open 'bundler/lib/bundler.rb', 'w' do |io| - io.puts '# bundler.rb' - end - - File.open 'bundler/lib/bundler/b.rb', 'w' do |io| - io.puts '# b.rb' - end - - FileUtils.mkdir_p 'default/gems' + filelist = %w[ + bin/gem + lib/rubygems.rb + lib/rubygems/requirement.rb + lib/rubygems/ssl_certs/rubygems.org/foo.pem + bundler/exe/bundle + bundler/exe/bundler + bundler/lib/bundler.rb + bundler/lib/bundler/b.rb + bundler/bin/bundler/man/bundle-b.1 + bundler/lib/bundler/man/bundle-b.1.ronn + bundler/lib/bundler/man/gemfile.5 + bundler/lib/bundler/man/gemfile.5.ronn + bundler/lib/bundler/templates/.circleci/config.yml + bundler/lib/bundler/templates/.travis.yml + ] + + create_dummy_files(filelist) gemspec = Gem::Specification.new gemspec.author = "Us" gemspec.name = "bundler" gemspec.version = BUNDLER_VERS gemspec.bindir = "exe" - gemspec.executables = ["bundle"] + gemspec.executables = ["bundle", "bundler"] - File.open 'bundler/bundler.gemspec', 'w' do |io| + File.open 'bundler/bundler.gemspec', 'w' do |io| io.puts gemspec.to_ruby end - open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), 'w') do |io| + File.open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), 'w') do |io| gemspec.version = "1.15.4" io.puts gemspec.to_ruby end - FileUtils.mkdir_p File.join(Gem.default_dir, "specifications") + spec_fetcher do |fetcher| + fetcher.download "bundler", "1.15.4" - open(File.join(Gem.default_dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec"), 'w') do |io| - io.puts "# bundler-#{BUNDLER_VERS}" - end + fetcher.gem "bundler", BUNDLER_VERS - open(File.join(Gem.default_dir, "specifications", "bundler-audit-1.0.0.gemspec"), 'w') do |io| - io.puts '# bundler-audit' + fetcher.gem "bundler-audit", "1.0.0" end - - FileUtils.mkdir_p 'default/gems/bundler-1.15.4' - FileUtils.mkdir_p 'default/gems/bundler-audit-1.0.0' - end - - def gem_install(name) - gem = util_spec name do |s| - s.executables = [name] - s.files = %W[bin/#{name}] - end - write_file File.join @tempdir, 'bin', name do |f| - f.puts '#!/usr/bin/ruby' - end - install_gem gem - File.join @gemhome, 'bin', name end def test_execute_regenerate_binstubs @@ -123,7 +85,46 @@ def test_execute_no_regenerate_binstubs assert_equal "I changed it!\n", File.read(gem_bin_path) end + def test_execute_regenerate_plugins + gem_plugin_path = gem_install_with_plugin 'a' + write_file gem_plugin_path do |io| + io.puts 'I changed it!' + end + + @cmd.options[:document] = [] + @cmd.execute + + assert_match %r{\Arequire}, File.read(gem_plugin_path) + end + + def test_execute_no_regenerate_plugins + gem_plugin_path = gem_install_with_plugin 'a' + write_file gem_plugin_path do |io| + io.puts 'I changed it!' + end + + @cmd.options[:document] = [] + @cmd.options[:regenerate_plugins] = false + @cmd.execute + + assert_equal "I changed it!\n", File.read(gem_plugin_path) + end + + def test_execute_regenerate_plugins_creates_plugins_dir_if_not_there + gem_plugin_path = gem_install_with_plugin 'a' + + # Simulate gem installed with an older rubygems without a plugins layout + FileUtils.rm_rf Gem.plugindir + + @cmd.options[:document] = [] + @cmd.execute + + assert_match %r{\Arequire}, File.read(gem_plugin_path) + end + def test_execute_informs_about_installed_executables + @cmd.options[:document] = [] + use_ui @ui do @cmd.execute end @@ -133,6 +134,7 @@ def test_execute_informs_about_installed_executables exec_line = out.shift until exec_line == "RubyGems installed the following executables:" assert_equal "\t#{default_gem_bin_path}", out.shift assert_equal "\t#{default_bundle_bin_path}", out.shift + assert_equal "\t#{default_bundler_bin_path}", out.shift end def test_env_shebang_flag @@ -147,25 +149,31 @@ def test_env_shebang_flag ruby_exec = sprintf Gem.default_exec_format, 'ruby' - if Gem.win_platform? - assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_gem_bin_path) - assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_bundle_bin_path) - assert_match %r%\A#!\s*#{ruby_exec}%, File.read(gem_bin_path) - else - assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_gem_bin_path) - assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_bundle_bin_path) - assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(gem_bin_path) - end + bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " " + assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_gem_bin_path) + assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundle_bin_path) + assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundler_bin_path) + assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_bin_path) end - def test_pem_files_in - assert_equal %w[rubygems/ssl_certs/rubygems.org/foo.pem], - @cmd.pem_files_in('lib').sort + def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home + FileUtils.chmod "-w", File.join(@gemhome, "plugins") + + destdir = File.join(@tempdir, 'foo') + + @cmd.options[:destdir] = destdir + @cmd.execute + + spec = Gem::Specification.load("bundler/bundler.gemspec") + + spec.executables.each do |e| + assert_path_exist File.join destdir, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'gems', spec.full_name, spec.bindir, e + end end - def test_rb_files_in - assert_equal %w[rubygems.rb rubygems/test_case.rb], - @cmd.rb_files_in('lib').sort + def test_files_in + assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem], + @cmd.files_in('lib').sort end def test_install_lib @@ -174,11 +182,14 @@ def test_install_lib Dir.mktmpdir 'lib' do |dir| @cmd.install_lib dir - assert_path_exists File.join(dir, 'rubygems.rb') - assert_path_exists File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem') + assert_path_exist File.join(dir, 'rubygems.rb') + assert_path_exist File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem') + + assert_path_exist File.join(dir, 'bundler.rb') + assert_path_exist File.join(dir, 'bundler/b.rb') - assert_path_exists File.join(dir, 'bundler.rb') - assert_path_exists File.join(dir, 'bundler/b.rb') + assert_path_exist File.join(dir, 'bundler/templates/.circleci/config.yml') + assert_path_exist File.join(dir, 'bundler/templates/.travis.yml') end end @@ -194,34 +205,27 @@ def test_install_default_bundler_gem spec.executables.each do |e| if Gem.win_platform? - assert_path_exists File.join(bin_dir, "#{e}.bat") + assert_path_exist File.join(bin_dir, "#{e}.bat") end - assert_path_exists File.join bin_dir, Gem.default_exec_format % e + assert_path_exist File.join bin_dir, e end default_dir = Gem.default_specifications_dir # expect to remove other versions of bundler gemspecs on default specification directory. - refute_path_exists File.join(default_dir, "bundler-1.15.4.gemspec") - assert_path_exists File.join(default_dir, "bundler-#{BUNDLER_VERS}.gemspec") + assert_path_not_exist File.join(default_dir, "bundler-1.15.4.gemspec") + assert_path_exist File.join(default_dir, "bundler-#{BUNDLER_VERS}.gemspec") # expect to not remove bundler-* gemspecs. - assert_path_exists File.join(Gem.default_dir, "specifications", "bundler-audit-1.0.0.gemspec") + assert_path_exist File.join(Gem.dir, "specifications", "bundler-audit-1.0.0.gemspec") # expect to remove normal gem that was same version. because it's promoted default gems. - refute_path_exists File.join(Gem.default_dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec") + assert_path_not_exist File.join(Gem.dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec") - # expect to install default gems. It location was `site_ruby` directory on real world. - assert_path_exists "default/gems/bundler-#{BUNDLER_VERS}" - - # expect to not remove other versions of bundler on `site_ruby` - assert_path_exists 'default/gems/bundler-1.15.4' - - # TODO: We need to assert to remove same version of bundler on gem_dir directory(It's not site_ruby dir) - - # expect to not remove bundler-* directory. - assert_path_exists 'default/gems/bundler-audit-1.0.0' + assert_path_exist "#{Gem.dir}/gems/bundler-#{BUNDLER_VERS}" + assert_path_exist "#{Gem.dir}/gems/bundler-1.15.4" + assert_path_exist "#{Gem.dir}/gems/bundler-audit-1.0.0" end def test_install_default_bundler_gem_with_force_flag @@ -236,76 +240,112 @@ def test_install_default_bundler_gem_with_force_flag f.puts 'echo "hello"' end - bindir(bin_dir) do - @cmd.options[:force] = true - - @cmd.install_default_bundler_gem bin_dir + @cmd.options[:force] = true - bundler_spec = Gem::Specification.load("bundler/bundler.gemspec") - default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec") - spec = Gem::Specification.load(default_spec_path) + @cmd.install_default_bundler_gem bin_dir - spec.executables.each do |e| - if Gem.win_platform? - assert_path_exists File.join(bin_dir, "#{e}.bat") - end + bundler_spec = Gem::Specification.load("bundler/bundler.gemspec") + default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec") + spec = Gem::Specification.load(default_spec_path) - assert_path_exists File.join bin_dir, Gem.default_exec_format % e + spec.executables.each do |e| + if Gem.win_platform? + assert_path_exist File.join(bin_dir, "#{e}.bat") end + + assert_path_exist File.join bin_dir, e + end + end + + def test_install_default_bundler_gem_with_destdir_flag + @cmd.extend FileUtils + + FileUtils.chmod "-w", @gemhome + + destdir = File.join(@tempdir, 'foo') + bin_dir = File.join(destdir, 'bin') + + @cmd.options[:destdir] = destdir + + @cmd.install_default_bundler_gem bin_dir + + spec = Gem::Specification.load("bundler/bundler.gemspec") + + spec.executables.each do |e| + assert_path_exist File.join destdir, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'gems', spec.full_name, spec.bindir, e + end + end + + def test_install_default_bundler_gem_with_destdir_and_prefix_flags + @cmd.extend FileUtils + + destdir = File.join(@tempdir, 'foo') + bin_dir = File.join(destdir, 'bin') + + @cmd.options[:destdir] = destdir + @cmd.options[:prefix] = "/" + + @cmd.install_default_bundler_gem bin_dir + + spec = Gem::Specification.load("bundler/bundler.gemspec") + + spec.executables.each do |e| + assert_path_exist File.join destdir, 'gems', spec.full_name, spec.bindir, e end end def test_remove_old_lib_files - lib = File.join @install_dir, 'lib' + lib = RbConfig::CONFIG["sitelibdir"] lib_rubygems = File.join lib, 'rubygems' lib_bundler = File.join lib, 'bundler' lib_rubygems_defaults = File.join lib_rubygems, 'defaults' + lib_bundler_templates = File.join lib_bundler, 'templates' securerandom_rb = File.join lib, 'securerandom.rb' engine_defaults_rb = File.join lib_rubygems_defaults, 'jruby.rb' os_defaults_rb = File.join lib_rubygems_defaults, 'operating_system.rb' + old_gauntlet_rubygems_rb = File.join lib, 'gauntlet_rubygems.rb' + old_builder_rb = File.join lib_rubygems, 'builder.rb' old_format_rb = File.join lib_rubygems, 'format.rb' old_bundler_c_rb = File.join lib_bundler, 'c.rb' + old_bundler_ci = File.join lib_bundler_templates, '.lecacy_ci', 'config.yml' - FileUtils.mkdir_p lib_rubygems_defaults - FileUtils.mkdir_p lib_bundler + files_that_go = [old_gauntlet_rubygems_rb, old_builder_rb, old_format_rb, old_bundler_c_rb, old_bundler_ci] + files_that_stay = [securerandom_rb, engine_defaults_rb, os_defaults_rb] - File.open securerandom_rb, 'w' do |io| - io.puts '# securerandom.rb' - end + create_dummy_files(files_that_go + files_that_stay) - File.open old_builder_rb, 'w' do |io| - io.puts '# builder.rb' - end + @cmd.remove_old_lib_files lib - File.open old_format_rb, 'w' do |io| - io.puts '# format.rb' - end + files_that_go.each {|file| assert_path_not_exist(file) unless file == old_bundler_ci } - File.open old_bundler_c_rb, 'w' do |io| - io.puts '# c.rb' - end + files_that_stay.each {|file| assert_path_exist file } + end - File.open engine_defaults_rb, 'w' do |io| - io.puts '# jruby.rb' - end + def test_remove_old_man_files + man = File.join RbConfig::CONFIG['mandir'], 'man' - File.open os_defaults_rb, 'w' do |io| - io.puts '# operating_system.rb' - end + ruby_1 = File.join man, 'man1', 'ruby.1' + bundle_b_1 = File.join man, 'man1', 'bundle-b.1' + bundle_b_1_ronn = File.join man, 'man1', 'bundle-b.1.ronn' + bundle_b_1_txt = File.join man, 'man1', 'bundle-b.1.txt' + gemfile_5 = File.join man, 'man5', 'gemfile.5' + gemfile_5_ronn = File.join man, 'man5', 'gemfile.5.ronn' + gemfile_5_txt = File.join man, 'man5', 'gemfile.5.txt' - @cmd.remove_old_lib_files lib + files_that_go = [bundle_b_1, bundle_b_1_txt, bundle_b_1_ronn, gemfile_5, gemfile_5_txt, gemfile_5_ronn] + files_that_stay = [ruby_1] + + create_dummy_files(files_that_go + files_that_stay) - refute_path_exists old_builder_rb - refute_path_exists old_format_rb - refute_path_exists old_bundler_c_rb + @cmd.remove_old_man_files man - assert_path_exists securerandom_rb - assert_path_exists engine_defaults_rb - assert_path_exists os_defaults_rb + files_that_go.each {|file| assert_path_not_exist file } + + files_that_stay.each {|file| assert_path_exist file } end def test_show_release_notes @@ -314,26 +354,24 @@ def test_show_release_notes @cmd.options[:previous_version] = Gem::Version.new '2.0.2' - File.open 'History.txt', 'w' do |io| - io.puts <<-History_txt -# coding: UTF-8 - -=== #{Gem::VERSION} / 2013-03-26 + File.open 'CHANGELOG.md', 'w' do |io| + io.puts <<-HISTORY_TXT +# #{Gem::VERSION} / 2013-03-26 -* Bug fixes: +## Bug fixes: * Fixed release note display for LANG=C when installing rubygems * Ï€ is tasty -=== 2.0.2 / 2013-03-06 +# 2.0.2 / 2013-03-06 -* Bug fixes: +## Bug fixes: * Other bugs fixed -=== 2.0.1 / 2013-03-05 +# 2.0.1 / 2013-03-05 -* Bug fixes: +## Bug fixes: * Yet more bugs fixed - History_txt + HISTORY_TXT end use_ui @ui do @@ -341,9 +379,9 @@ def test_show_release_notes end expected = <<-EXPECTED -=== #{Gem::VERSION} / 2013-03-26 +# #{Gem::VERSION} / 2013-03-26 -* Bug fixes: +## Bug fixes: * Fixed release note display for LANG=C when installing rubygems * Ï€ is tasty @@ -359,14 +397,49 @@ def test_show_release_notes private + def create_dummy_files(list) + list.each do |file| + FileUtils.mkdir_p File.dirname(file) + + File.open file, 'w' do |io| + io.puts "# #{File.basename(file)}" + end + end + end + + def gem_install(name) + gem = util_spec name do |s| + s.executables = [name] + s.files = %W[bin/#{name}] + end + write_file File.join @tempdir, 'bin', name do |f| + f.puts '#!/usr/bin/ruby' + end + install_gem gem + File.join @gemhome, 'bin', name + end + + def gem_install_with_plugin(name) + gem = util_spec name do |s| + s.files = %W[lib/rubygems_plugin.rb] + end + write_file File.join @tempdir, 'lib', 'rubygems_plugin.rb' do |f| + f.puts "require '#{gem.plugins.first}'" + end + install_gem gem + + File.join Gem.plugindir, "#{name}_plugin.rb" + end + def default_gem_bin_path - gem_exec = sprintf Gem.default_exec_format, 'gem' - File.join @install_dir, 'bin', gem_exec + File.join RbConfig::CONFIG['bindir'], 'gem' end def default_bundle_bin_path - bundle_exec = sprintf Gem.default_exec_format, 'bundle' - File.join @install_dir, 'bin', bundle_exec + File.join RbConfig::CONFIG['bindir'], 'bundle' end + def default_bundler_bin_path + File.join RbConfig::CONFIG['bindir'], 'bundler' + end end unless Gem.java_platform? diff --git a/ruby/test/rubygems/test_gem_commands_signin_command.rb b/ruby/test/rubygems/test_gem_commands_signin_command.rb index c000c7a77..0f856a53b 100644 --- a/ruby/test/rubygems/test_gem_commands_signin_command.rb +++ b/ruby/test/rubygems/test_gem_commands_signin_command.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/signin_command' require 'rubygems/installer' class TestGemCommandsSigninCommand < Gem::TestCase - def setup super + credential_setup + Gem.configuration.rubygems_api_key = nil Gem.configuration.api_keys.clear @@ -15,13 +16,20 @@ def setup end def teardown - credentials_path = Gem.configuration.credentials_path - File.delete(credentials_path) if File.exist?(credentials_path) + credential_teardown + super end def test_execute_when_not_already_signed_in - sign_in_ui = util_capture() { @cmd.execute } + sign_in_ui = util_capture { @cmd.execute } + assert_match %r{Signed in.}, sign_in_ui.output + end + + def test_execute_when_not_already_signed_in_and_not_preexisting_credentials_folder + FileUtils.rm Gem.configuration.credentials_path + + sign_in_ui = util_capture { @cmd.execute } assert_match %r{Signed in.}, sign_in_ui.output end @@ -29,10 +37,10 @@ def test_execute_when_already_signed_in_with_same_host host = 'http://some-gemcutter-compatible-host.org' util_capture(nil, host) { @cmd.execute } - old_credentials = YAML.load_file Gem.configuration.credentials_path + old_credentials = load_yaml_file Gem.configuration.credentials_path util_capture(nil, host) { @cmd.execute } - new_credentials = YAML.load_file Gem.configuration.credentials_path + new_credentials = load_yaml_file Gem.configuration.credentials_path assert_equal old_credentials[host], new_credentials[host] end @@ -44,7 +52,7 @@ def test_execute_when_already_signed_in_with_different_host host = 'http://some-gemcutter-compatible-host.org' util_capture(nil, host, api_key) { @cmd.execute } - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal credentials[:rubygems_api_key], api_key @@ -59,27 +67,51 @@ def test_execute_with_host_supplied assert_match %r{Signed in.}, sign_in_ui.output api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[host] end def test_execute_with_valid_creds_set_for_default_host - util_capture {@cmd.execute} + util_capture { @cmd.execute } api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] end + def test_execute_with_key_name_and_scope + email = 'you@example.com' + password = 'secret' + api_key = '1234' + fetcher = Gem::RemoteFetcher.fetcher + + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\n" + util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } + + user = ENV["USER"] || ENV["USERNAME"] + + assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "index_rubygems [y/N]", key_name_ui.output + assert_match "push_rubygem [y/N]", key_name_ui.output + assert_match "yank_rubygem [y/N]", key_name_ui.output + assert_match "add_owner [y/N]", key_name_ui.output + assert_match "remove_owner [y/N]", key_name_ui.output + assert_match "access_webhooks [y/N]", key_name_ui.output + assert_match "show_dashboard [y/N]", key_name_ui.output + assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body + + credentials = load_yaml_file Gem.configuration.credentials_path + assert_equal api_key, credentials[:rubygems_api_key] + end + # Utility method to capture IO/UI within the block passed - def util_capture(ui_stub = nil, host = nil, api_key = nil) + def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new) api_key ||= 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' response = [api_key, 200, 'OK'] email = 'you@example.com' password = 'secret' - fetcher = Gem::FakeFetcher.new # Set the expected response for the Web-API supplied ENV['RUBYGEMS_HOST'] = host || Gem::DEFAULT_HOST @@ -87,7 +119,7 @@ def util_capture(ui_stub = nil, host = nil, api_key = nil) fetcher.data[data_key] = response Gem::RemoteFetcher.fetcher = fetcher - sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n") + sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n") use_ui sign_in_ui do yield @@ -95,5 +127,4 @@ def util_capture(ui_stub = nil, host = nil, api_key = nil) sign_in_ui end - end diff --git a/ruby/test/rubygems/test_gem_commands_signout_command.rb b/ruby/test/rubygems/test_gem_commands_signout_command.rb index 814b55cf4..aa6300b6a 100644 --- a/ruby/test/rubygems/test_gem_commands_signout_command.rb +++ b/ruby/test/rubygems/test_gem_commands_signout_command.rb @@ -1,21 +1,15 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/signout_command' require 'rubygems/installer' class TestGemCommandsSignoutCommand < Gem::TestCase - def setup super @cmd = Gem::Commands::SignoutCommand.new end - def teardown - super - File.delete Gem.configuration.credentials_path if File.exist?(Gem.configuration.credentials_path) - end - def test_execute_when_user_is_signed_in FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path) FileUtils::touch Gem.configuration.credentials_path @@ -33,5 +27,4 @@ def test_execute_when_not_signed_in # i.e. no credential file created assert_match %r{You are not currently signed in}, @sign_out_ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_sources_command.rb b/ruby/test/rubygems/test_gem_commands_sources_command.rb index b63fbce81..7bca0f380 100644 --- a/ruby/test/rubygems/test_gem_commands_sources_command.rb +++ b/ruby/test/rubygems/test_gem_commands_sources_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/sources_command' class TestGemCommandsSourcesCommand < Gem::TestCase - def setup super @@ -108,6 +107,36 @@ def test_execute_add_allow_typo_squatting_source assert_empty ui.error end + def test_execute_add_allow_typo_squatting_source_forced + rubygems_org = "https://rubyems.org" + + spec_fetcher do |fetcher| + fetcher.spec("a", 1) + end + + specs = Gem::Specification.map do |spec| + [spec.name, spec.version, spec.original_platform] + end + + specs_dump_gz = StringIO.new + Zlib::GzipWriter.wrap(specs_dump_gz) do |io| + Marshal.dump(specs, io) + end + + @fetcher.data["#{rubygems_org}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string + @cmd.handle_options %W[--force --add #{rubygems_org}] + + @cmd.execute + + expected = "https://rubyems.org added to sources\n" + assert_equal expected, ui.output + + source = Gem::Source.new(rubygems_org) + assert Gem.sources.include?(source) + + assert_empty ui.error + end + def test_execute_add_deny_typo_squatting_source rubygems_org = "https://rubyems.org" @@ -133,7 +162,7 @@ def test_execute_add_deny_typo_squatting_source use_ui ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -159,7 +188,7 @@ def test_execute_add_nonexistent_source @cmd.handle_options %w[--add http://beta-gems.example.com] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -247,7 +276,7 @@ def test_execute_add_redundant_source_trailing_slash end def test_execute_add_http_rubygems_org - http_rubygems_org = 'http://rubygems.org' + http_rubygems_org = 'http://rubygems.org/' spec_fetcher do |fetcher| fetcher.spec 'a', 1 @@ -270,7 +299,75 @@ def test_execute_add_http_rubygems_org ui = Gem::MockGemUi.new "n" use_ui ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do + @cmd.execute + end + end + + assert_equal [@gem_repo], Gem.sources + + expected = <<-EXPECTED + EXPECTED + + assert_equal expected, @ui.output + assert_empty @ui.error + end + + def test_execute_add_http_rubygems_org_forced + rubygems_org = "http://rubygems.org" + + spec_fetcher do |fetcher| + fetcher.spec("a", 1) + end + + specs = Gem::Specification.map do |spec| + [spec.name, spec.version, spec.original_platform] + end + + specs_dump_gz = StringIO.new + Zlib::GzipWriter.wrap(specs_dump_gz) do |io| + Marshal.dump(specs, io) + end + + @fetcher.data["#{rubygems_org}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string + @cmd.handle_options %W[--force --add #{rubygems_org}] + + @cmd.execute + + expected = "http://rubygems.org added to sources\n" + assert_equal expected, ui.output + + source = Gem::Source.new(rubygems_org) + assert Gem.sources.include?(source) + + assert_empty ui.error + end + + def test_execute_add_https_rubygems_org + https_rubygems_org = 'https://rubygems.org/' + + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + end + + specs = Gem::Specification.map do |spec| + [spec.name, spec.version, spec.original_platform] + end + + specs_dump_gz = StringIO.new + Zlib::GzipWriter.wrap specs_dump_gz do |io| + Marshal.dump specs, io + end + + @fetcher.data["#{https_rubygems_org}/specs.#{@marshal_version}.gz"] = + specs_dump_gz.string + + @cmd.handle_options %W[--add #{https_rubygems_org}] + + ui = Gem::MockGemUi.new "n" + + use_ui ui do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -288,7 +385,7 @@ def test_execute_add_bad_uri @cmd.handle_options %w[--add beta-gems.example.com] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -384,5 +481,4 @@ def test_execute_update assert_equal "source cache successfully updated\n", @ui.output assert_equal '', @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_specification_command.rb b/ruby/test/rubygems/test_gem_commands_specification_command.rb index f56aa9777..c8cb7df32 100644 --- a/ruby/test/rubygems/test_gem_commands_specification_command.rb +++ b/ruby/test/rubygems/test_gem_commands_specification_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/specification_command' class TestGemCommandsSpecificationCommand < Gem::TestCase - def setup super @@ -21,8 +20,8 @@ def test_execute @cmd.execute end - assert_match %r|Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output assert_equal '', @ui.error end @@ -37,10 +36,10 @@ def test_execute_all @cmd.execute end - assert_match %r|Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output - assert_match %r|version: 0.0.1|, @ui.output - assert_match %r|version: 0.0.2|, @ui.output + assert_match %r{Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output + assert_match %r{version: 0.0.1}, @ui.output + assert_match %r{version: 0.0.2}, @ui.output assert_equal '', @ui.error end @@ -52,7 +51,7 @@ def test_execute_all_conflicts_with_version @cmd.options[:all] = true @cmd.options[:version] = "1" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end @@ -65,7 +64,7 @@ def test_execute_all_conflicts_with_version def test_execute_bad_name @cmd.options[:args] = %w[foo] - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end @@ -79,7 +78,7 @@ def test_execute_bad_name_with_version @cmd.options[:args] = %w[foo] @cmd.options[:version] = "1.3.2" - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end @@ -99,8 +98,8 @@ def test_execute_exact_match @cmd.execute end - assert_match %r|Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output assert_equal '', @ui.error end @@ -115,7 +114,7 @@ def test_execute_field @cmd.execute end - assert_equal "foo", YAML.load(@ui.output) + assert_equal "foo", load_yaml(@ui.output) end def test_execute_file @@ -131,8 +130,8 @@ def test_execute_file @cmd.execute end - assert_match %r|Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output assert_equal '', @ui.error end @@ -164,8 +163,8 @@ def test_execute_remote @cmd.execute end - assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output end def test_execute_remote_with_version @@ -187,6 +186,34 @@ def test_execute_remote_with_version assert_equal Gem::Version.new("1"), spec.version end + def test_execute_remote_with_version_and_platform + original_platforms = Gem.platforms.dup + + spec_fetcher do |fetcher| + fetcher.spec 'foo', "1" + fetcher.spec 'foo', "1" do |s| + s.platform = 'x86_64-linux' + end + end + + @cmd.options[:args] = %w[foo] + @cmd.options[:version] = "1" + @cmd.options[:domain] = :remote + @cmd.options[:added_platform] = true + Gem.platforms = [Gem::Platform::RUBY, Gem::Platform.new("x86_64-linux")] + + use_ui @ui do + @cmd.execute + end + + spec = Gem::Specification.from_yaml @ui.output + + assert_equal Gem::Version.new("1"), spec.version + assert_equal Gem::Platform.new("x86_64-linux"), spec.platform + ensure + Gem.platforms = original_platforms + end + def test_execute_remote_without_prerelease spec_fetcher do |fetcher| fetcher.spec 'foo', '2.0.0' @@ -200,10 +227,10 @@ def test_execute_remote_without_prerelease @cmd.execute end - assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output - spec = YAML.load @ui.output + spec = load_yaml @ui.output assert_equal Gem::Version.new("2.0.0"), spec.version end @@ -222,10 +249,10 @@ def test_execute_remote_with_prerelease @cmd.execute end - assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output - assert_match %r|name: foo|, @ui.output + assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output + assert_match %r{name: foo}, @ui.output - spec = YAML.load @ui.output + spec = load_yaml @ui.output assert_equal Gem::Version.new("2.0.1.pre"), spec.version end @@ -242,9 +269,8 @@ def test_execute_ruby @cmd.execute end - assert_match %r|Gem::Specification.new|, @ui.output - assert_match %r|s.name = "foo"|, @ui.output + assert_match %r{Gem::Specification.new}, @ui.output + assert_match %r{s.name = "foo"}, @ui.output assert_equal '', @ui.error end - end diff --git a/ruby/test/rubygems/test_gem_commands_stale_command.rb b/ruby/test/rubygems/test_gem_commands_stale_command.rb index a8909c6d1..83bd3e5de 100644 --- a/ruby/test/rubygems/test_gem_commands_stale_command.rb +++ b/ruby/test/rubygems/test_gem_commands_stale_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/stale_command' class TestGemCommandsStaleCommand < Gem::TestCase - def setup super @stub_ui = Gem::MockGemUi.new @@ -40,5 +39,4 @@ def test_execute_sorts assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first) assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first) end - end diff --git a/ruby/test/rubygems/test_gem_commands_uninstall_command.rb b/ruby/test/rubygems/test_gem_commands_uninstall_command.rb index 927a24120..5bd2c40d5 100644 --- a/ruby/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/ruby/test/rubygems/test_gem_commands_uninstall_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/installer_test_case' +require_relative 'installer_test_case' require 'rubygems/commands/uninstall_command' class TestGemCommandsUninstallCommand < Gem::InstallerTestCase - def setup super @cmd = Gem::Commands::UninstallCommand.new @@ -361,6 +360,7 @@ def test_execute_all end assert_equal %w[default-1], Gem::Specification.all_names.sort + assert_equal "INFO: Uninstalled all gems in #{@gemhome}", @ui.output.split("\n").last end def test_execute_outside_gem_home @@ -377,7 +377,7 @@ def test_execute_outside_gem_home @cmd.options[:args] = ['a:4'] - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do use_ui ui do @cmd.execute end @@ -420,7 +420,7 @@ def test_execute_two_version @cmd.options[:version] = Gem::Requirement.new("> 1") use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end @@ -436,7 +436,7 @@ def test_execute_two_version def test_handle_options_vendor_missing vendordir(nil) do - e = assert_raises OptionParser::InvalidOption do + e = assert_raise Gem::OptionParser::InvalidOption do @cmd.handle_options %w[--vendor] end @@ -477,7 +477,7 @@ def test_execute_with_gem_uninstall_error e = nil @cmd.stub :uninstall, uninstall_exception do use_ui @ui do - e = assert_raises Gem::MockGemUi::TermError do + e = assert_raise Gem::MockGemUi::TermError do @cmd.execute end end @@ -486,7 +486,7 @@ def test_execute_with_gem_uninstall_error end assert_empty @ui.output - assert_match %r!Error: unable to successfully uninstall '#{@spec.name}'!, @ui.error + assert_match %r{Error: unable to successfully uninstall '#{@spec.name}'}, @ui.error end private @@ -501,5 +501,4 @@ def initial_install end end end - end diff --git a/ruby/test/rubygems/test_gem_commands_unpack_command.rb b/ruby/test/rubygems/test_gem_commands_unpack_command.rb index 7d96caaf5..55369f1ee 100644 --- a/ruby/test/rubygems/test_gem_commands_unpack_command.rb +++ b/ruby/test/rubygems/test_gem_commands_unpack_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/unpack_command' class TestGemCommandsUnpackCommand < Gem::TestCase - def setup super @@ -152,7 +151,7 @@ def test_execute_spec_target end def test_execute_sudo - skip 'Cannot perform this test on windows (chmod)' if win_platform? + pend 'Cannot perform this test on windows (chmod)' if win_platform? util_make_gems @@ -211,7 +210,7 @@ def test_execute_exact_match end end - assert_path_exists File.join(@tempdir, foo_spec.full_name) + assert_path_exist File.join(@tempdir, foo_spec.full_name) end def test_handle_options_metadata @@ -221,5 +220,4 @@ def test_handle_options_metadata assert @cmd.options[:spec] end - end diff --git a/ruby/test/rubygems/test_gem_commands_update_command.rb b/ruby/test/rubygems/test_gem_commands_update_command.rb index 37f990ea1..c765e9a8d 100644 --- a/ruby/test/rubygems/test_gem_commands_update_command.rb +++ b/ruby/test/rubygems/test_gem_commands_update_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/update_command' class TestGemCommandsUpdateCommand < Gem::TestCase - def setup super common_installer_setup @@ -96,7 +95,7 @@ def test_execute_system_at_latest @cmd.options[:args] = [] @cmd.options[:system] = true - assert_raises Gem::MockGemUi::SystemExitException do + assert_raise Gem::MockGemUi::SystemExitException do use_ui @ui do @cmd.execute end @@ -107,6 +106,31 @@ def test_execute_system_at_latest assert_empty out end + def test_execute_system_when_latest_does_not_support_your_ruby + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', 9 do |s| + s.files = %w[setup.rb] + s.required_ruby_version = '> 9' + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = true + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_equal "Updating rubygems-update", out.shift + assert_empty out + + err = @ui.error.split "\n" + assert_equal "ERROR: Error installing rubygems-update:", err.shift + assert_equal "\trubygems-update-9 requires Ruby version > 9. The current ruby version is #{Gem.ruby_version}.", err.shift + assert_empty err + end + def test_execute_system_multiple spec_fetcher do |fetcher| fetcher.download 'rubygems-update', 8 do |s| @@ -133,6 +157,40 @@ def test_execute_system_multiple assert_empty out end + def test_execute_system_update_installed + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', 8 do |s| + s.files = %w[setup.rb] + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = true + + @cmd.execute + + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', 9 do |s| + s.files = %w[setup.rb] + end + end + + @cmd = Gem::Commands::UpdateCommand.new + @cmd.options[:args] = [] + @cmd.options[:system] = true + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_equal "Updating rubygems-update", out.shift + assert_equal "Installing RubyGems 9", out.shift + assert_equal "RubyGems system software updated", out.shift + + assert_empty out + end + def test_execute_system_specific spec_fetcher do |fetcher| fetcher.download 'rubygems-update', 8 do |s| @@ -159,6 +217,91 @@ def test_execute_system_specific assert_empty out end + def test_execute_system_specific_older_than_minimum_supported_rubygems + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', "2.5.1" do |s| + s.files = %w[setup.rb] + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = "2.5.1" + + oldest_version_mod = Module.new do + def oldest_supported_version + Gem::Version.new("2.5.2") + end + private :oldest_supported_version + end + + @cmd.extend(oldest_version_mod) + + assert_raise Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_empty @ui.output + assert_equal "ERROR: rubygems 2.5.1 is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is 2.5.2\n", @ui.error + end + + def test_execute_system_specific_older_than_3_2_removes_plugins_dir + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', 3.1 do |s| + s.files = %w[setup.rb] + end + end + + oldest_version_mod = Module.new do + def oldest_supported_version + Gem::Version.new("2.5.2") + end + private :oldest_supported_version + end + + @cmd.extend(oldest_version_mod) + + @cmd.options[:args] = [] + @cmd.options[:system] = "3.1" + + FileUtils.mkdir_p Gem.plugindir + write_file File.join(Gem.plugindir, 'a_plugin.rb') + + @cmd.execute + + assert_path_not_exist Gem.plugindir, "Plugins folder not removed when updating rubygems to pre-3.2" + end + + def test_execute_system_specific_newer_than_or_equal_to_3_2_leaves_plugins_dir_alone + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', "3.2.a" do |s| + s.files = %w[setup.rb] + end + end + + oldest_version_mod = Module.new do + def oldest_supported_version + Gem::Version.new("2.5.2") + end + private :oldest_supported_version + end + + @cmd.extend(oldest_version_mod) + + @cmd.options[:args] = [] + @cmd.options[:system] = "3.2.a" + + FileUtils.mkdir_p Gem.plugindir + plugin_file = File.join(Gem.plugindir, 'a_plugin.rb') + write_file plugin_file + + @cmd.execute + + assert_path_exist Gem.plugindir, "Plugin folder removed when updating rubygems to post-3.2" + assert_path_exist plugin_file, "Plugin removed when updating rubygems to post-3.2" + end + def test_execute_system_specifically_to_latest_version spec_fetcher do |fetcher| fetcher.download 'rubygems-update', 8 do |s| @@ -189,7 +332,7 @@ def test_execute_system_with_gems @cmd.options[:args] = %w[gem] @cmd.options[:system] = true - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do use_ui @ui do @cmd.execute end @@ -200,6 +343,53 @@ def test_execute_system_with_gems @ui.error end + def test_execute_system_with_disabled_update + old_disable_system_update_message = Gem.disable_system_update_message + Gem.disable_system_update_message = "Please use package manager instead." + + @cmd.options[:args] = [] + @cmd.options[:system] = true + + assert_raise Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_empty @ui.output + assert_equal "ERROR: Please use package manager instead.\n", @ui.error + ensure + Gem.disable_system_update_message = old_disable_system_update_message + end + + # The other style of `gem update --system` tests don't actually run + # setup.rb, so we just check that setup.rb gets the `--silent` flag. + def test_execute_system_silent_passed_to_setuprb + @cmd.options[:args] = [] + @cmd.options[:system] = true + @cmd.options[:silent] = true + + assert_equal true, @cmd.update_rubygems_arguments.include?('--silent') + end + + def test_execute_system_silent + spec_fetcher do |fetcher| + fetcher.download 'rubygems-update', 9 do |s| + s.files = %w[setup.rb] + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = true + @cmd.options[:silent] = true + + use_ui @ui do + @cmd.execute + end + + assert_empty @ui.output + end + # before: # a1 -> c1.2 # after: @@ -253,7 +443,7 @@ def test_execute_rdoc a2 = @specs['a-2'] - assert_path_exists File.join(a2.doc_dir, 'rdoc') + assert_path_exist File.join(a2.doc_dir, 'rdoc') end def test_execute_named @@ -359,10 +549,10 @@ def test_execute_up_to_date end def test_execute_user_install - spec_fetcher do |fetcher| - fetcher.download 'a', 2 - fetcher.spec 'a', 1 - end + a = util_spec "a", 1 + b = util_spec "b", 1 + install_gem_user(a) + install_gem(b) @cmd.handle_options %w[--user-install] @@ -373,7 +563,13 @@ def test_execute_user_install installer = @cmd.installer user_install = installer.instance_variable_get :@user_install - assert user_install, 'user_install must be set on the installer' + assert user_install, "user_install must be set on the installer" + + out = @ui.output.split "\n" + assert_equal "Updating installed gems", out.shift + assert_equal "Updating a", out.shift + assert_equal "Gems updated: a", out.shift + assert_empty out end def test_fetch_remote_gems @@ -393,7 +589,7 @@ def test_fetch_remote_gems def test_fetch_remote_gems_error Gem.sources.replace %w[http://nonexistent.example] - assert_raises Gem::RemoteFetcher::FetchError do + assert_raise Gem::RemoteFetcher::FetchError do @cmd.fetch_remote_gems @specs['a-1'] end end @@ -442,7 +638,7 @@ def test_handle_options_system expected = { :args => [], - :document => %w[rdoc ri], + :document => %w[ri], :force => false, :system => true, } @@ -451,7 +647,7 @@ def test_handle_options_system end def test_handle_options_system_non_version - assert_raises ArgumentError do + assert_raise ArgumentError do @cmd.handle_options %w[--system non-version] end end @@ -461,7 +657,7 @@ def test_handle_options_system_specific expected = { :args => [], - :document => %w[rdoc ri], + :document => %w[ri], :force => false, :system => "1.3.7", } @@ -584,5 +780,4 @@ def test_explain_platform_ruby assert_equal " a-2", out.shift assert_empty out end - end diff --git a/ruby/test/rubygems/test_gem_commands_which_command.rb b/ruby/test/rubygems/test_gem_commands_which_command.rb index 0d63bb9b3..a398dc570 100644 --- a/ruby/test/rubygems/test_gem_commands_which_command.rb +++ b/ruby/test/rubygems/test_gem_commands_which_command.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/which_command' class TestGemCommandsWhichCommand < Gem::TestCase - def setup super Gem::Specification.reset @@ -27,13 +26,13 @@ def test_execute_directory @cmd.handle_options %w[directory] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end assert_equal '', @ui.output - assert_match %r%Can.t find Ruby library file or shared library directory\n%, + assert_match %r{Can.t find Ruby library file or shared library directory\n}, @ui.error end @@ -45,13 +44,13 @@ def test_execute_one_missing @cmd.handle_options %w[foo_bar missinglib] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output - assert_match %r%Can.t find Ruby library file or shared library missinglib\n%, + assert_match %r{Can.t find Ruby library file or shared library missinglib\n}, @ui.error end @@ -59,13 +58,13 @@ def test_execute_missing @cmd.handle_options %w[missinglib] use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.execute end end assert_equal '', @ui.output - assert_match %r%Can.t find Ruby library file or shared library missinglib\n%, + assert_match %r{Can.t find Ruby library file or shared library missinglib\n}, @ui.error end @@ -82,5 +81,4 @@ def util_foo_bar FileUtils.touch filename end end - end diff --git a/ruby/test/rubygems/test_gem_commands_yank_command.rb b/ruby/test/rubygems/test_gem_commands_yank_command.rb index 1aafc92bf..b798eb368 100644 --- a/ruby/test/rubygems/test_gem_commands_yank_command.rb +++ b/ruby/test/rubygems/test_gem_commands_yank_command.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/commands/yank_command' class TestGemCommandsYankCommand < Gem::TestCase - def setup super + credential_setup + @cmd = Gem::Commands::YankCommand.new @cmd.options[:host] = 'http://example' @@ -16,6 +17,12 @@ def setup Gem.configuration.api_keys[:KEY] = 'other' end + def teardown + credential_teardown + + super + end + def test_handle_options @cmd.handle_options %w[a --version 1.0 --platform x86-darwin -k KEY --host HOST] @@ -28,7 +35,7 @@ def test_handle_options def test_handle_options_missing_argument %w[-v --version -p --platform].each do |option| - assert_raises OptionParser::MissingArgument do + assert_raise Gem::OptionParser::MissingArgument do @cmd.handle_options %W[a #{option}] end end @@ -46,8 +53,8 @@ def test_execute @cmd.execute end - assert_match %r%Yanking gem from http://example%, @ui.output - assert_match %r%Successfully yanked%, @ui.output + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match %r{Successfully yanked}, @ui.output platform = Gem.platforms[1] body = @fetcher.last_request.body.split('&').sort @@ -63,7 +70,7 @@ def test_execute_with_otp_success yank_uri = 'http://example/api/v1/gems/yank' @fetcher.data[yank_uri] = [ [response_fail, 401, 'Unauthorized'], - ['Successfully yanked', 200, 'OK'] + ['Successfully yanked', 200, 'OK'], ] @cmd.options[:args] = %w[a] @@ -77,8 +84,8 @@ def test_execute_with_otp_success assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output assert_match 'Code: ', @otp_ui.output - assert_match %r%Yanking gem from http://example%, @otp_ui.output - assert_match %r%Successfully yanked%, @otp_ui.output + assert_match %r{Yanking gem from http://example}, @otp_ui.output + assert_match %r{Successfully yanked}, @otp_ui.output assert_equal '111111', @fetcher.last_request['OTP'] end @@ -132,8 +139,8 @@ def test_execute_host @cmd.execute end - assert_match %r%Yanking gem from https://other.example%, @ui.output - assert_match %r%Successfully yanked%, @ui.output + assert_match %r{Yanking gem from https://other.example}, @ui.output + assert_match %r{Successfully yanked}, @ui.output body = @fetcher.last_request.body.split('&').sort assert_equal %w[gem_name=a version=1.0], body @@ -141,4 +148,33 @@ def test_execute_host assert_equal [yank_uri], @fetcher.paths end + def test_yank_gem_unathorized_api_key + response_forbidden = "The API key doesn't have access" + response_success = 'Successfully yanked' + host = 'http://example' + + @fetcher.data["#{host}/api/v1/gems/yank"] = [ + [response_forbidden, 403, 'Forbidden'], + [response_success, 200, "OK"], + ] + + @fetcher.data["#{host}/api/v1/api_key"] = ["", 200, "OK"] + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req('= 1.0') + @cmd.instance_variable_set :@host, host + @cmd.instance_variable_set :@scope, :yank_rubygem + + @ui = Gem::MockGemUi.new "some@mail.com\npass\n" + use_ui @ui do + @cmd.execute + end + + access_notice = "The existing key doesn't have access of yank_rubygem on http://example. Please sign in to update access." + assert_match access_notice, @ui.output + assert_match "Email:", @ui.output + assert_match "Password:", @ui.output + assert_match "Added yank_rubygem scope to the existing API key", @ui.output + assert_match response_success, @ui.output + end end diff --git a/ruby/test/rubygems/test_gem_config_file.rb b/ruby/test/rubygems/test_gem_config_file.rb index 492a0c5a0..32375e693 100644 --- a/ruby/test/rubygems/test_gem_config_file.rb +++ b/ruby/test/rubygems/test_gem_config_file.rb @@ -1,20 +1,17 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/config_file' class TestGemConfigFile < Gem::TestCase - def setup super + credential_setup + @temp_conf = File.join @tempdir, '.gemrc' @cfg_args = %W[--config-file #{@temp_conf}] - @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE - Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE - Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, - File.join(@tempdir, 'system-gemrc') Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear Gem::ConfigFile::PLATFORM_DEFAULTS.clear @@ -27,12 +24,11 @@ def setup def teardown Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear Gem::ConfigFile::PLATFORM_DEFAULTS.clear - Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE - Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, - @orig_SYSTEM_WIDE_CONFIG_FILE ENV['GEMRC'] = @env_gemrc + credential_teardown + super end @@ -45,6 +41,7 @@ def test_initialize assert_equal true, @cfg.verbose assert_equal [@gem_repo], Gem.sources assert_equal 365, @cfg.cert_expiration_length_days + assert_equal false, @cfg.ipv4_fallback_enabled File.open @temp_conf, 'w' do |fp| fp.puts ":backtrace: true" @@ -60,6 +57,7 @@ def test_initialize fp.puts ":ssl_verify_mode: 0" fp.puts ":ssl_ca_cert: /etc/ssl/certs" fp.puts ":cert_expiration_length_days: 28" + fp.puts ":ipv4_fallback_enabled: true" end util_config_file @@ -74,6 +72,14 @@ def test_initialize assert_equal 0, @cfg.ssl_verify_mode assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert assert_equal 28, @cfg.cert_expiration_length_days + assert_equal true, @cfg.ipv4_fallback_enabled + end + + def test_initialize_ipv4_fallback_enabled_env + ENV['IPV4_FALLBACK_ENABLED'] = 'true' + util_config_file %W[--config-file #{@temp_conf}] + + assert_equal true, @cfg.ipv4_fallback_enabled end def test_initialize_handle_arguments_config_file @@ -177,7 +183,7 @@ def test_api_keys assert_nil @cfg.instance_variable_get :@api_keys temp_cred = File.join Gem.user_home, '.gem', 'credentials' - FileUtils.mkdir File.dirname(temp_cred) + FileUtils.mkdir_p File.dirname(temp_cred) File.open temp_cred, 'w', 0600 do |fp| fp.puts ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97' end @@ -189,14 +195,14 @@ def test_api_keys end def test_check_credentials_permissions - skip 'chmod not supported' if win_platform? + pend 'chmod not supported' if win_platform? @cfg.rubygems_api_key = 'x' File.chmod 0644, @cfg.credentials_path use_ui @ui do - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cfg.load_api_keys end end @@ -247,7 +253,7 @@ def test_handle_arguments_debug args = %w[--debug] - _, err = capture_io do + _, err = capture_output do @cfg.handle_arguments args end @@ -303,7 +309,7 @@ def test_handle_arguments_norc def test_load_api_keys temp_cred = File.join Gem.user_home, '.gem', 'credentials' - FileUtils.mkdir File.dirname(temp_cred) + FileUtils.mkdir_p File.dirname(temp_cred) File.open temp_cred, 'w', 0600 do |fp| fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97" fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c" @@ -316,13 +322,13 @@ def test_load_api_keys end def test_load_api_keys_bad_permission - skip 'chmod not supported' if win_platform? + pend 'chmod not supported' if win_platform? @cfg.rubygems_api_key = 'x' File.chmod 0644, @cfg.credentials_path - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cfg.load_api_keys end end @@ -348,7 +354,7 @@ def test_rubygems_api_key_equals :rubygems_api_key => 'x', } - assert_equal expected, YAML.load_file(@cfg.credentials_path) + assert_equal expected, load_yaml_file(@cfg.credentials_path) unless win_platform? stat = File.stat @cfg.credentials_path @@ -358,13 +364,13 @@ def test_rubygems_api_key_equals end def test_rubygems_api_key_equals_bad_permission - skip 'chmod not supported' if win_platform? + pend 'chmod not supported' if win_platform? @cfg.rubygems_api_key = 'x' File.chmod 0644, @cfg.credentials_path - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cfg.rubygems_api_key = 'y' end @@ -372,7 +378,7 @@ def test_rubygems_api_key_equals_bad_permission :rubygems_api_key => 'x', } - assert_equal expected, YAML.load_file(@cfg.credentials_path) + assert_equal expected, load_yaml_file(@cfg.credentials_path) stat = File.stat @cfg.credentials_path @@ -392,7 +398,7 @@ def test_write util_config_file # These should not be written out to the config file. - assert_equal false, @cfg.backtrace, 'backtrace' + assert_equal false, @cfg.backtrace, 'backtrace' assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold, 'bulk_threshold' assert_equal true, @cfg.update_sources, 'update_sources' @@ -495,5 +501,4 @@ def test_disable_default_gem_server util_config_file assert_equal(true, @cfg.disable_default_gem_server) end - end diff --git a/ruby/test/rubygems/test_gem_dependency.rb b/ruby/test/rubygems/test_gem_dependency.rb index 0caab10d3..5551966da 100644 --- a/ruby/test/rubygems/test_gem_dependency.rb +++ b/ruby/test/rubygems/test_gem_dependency.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/dependency' class TestGemDependency < Gem::TestCase + def setup + super + + without_any_upwards_gemfiles + end def test_initialize d = dep "pkg", "> 1.0" @@ -12,7 +17,7 @@ def test_initialize end def test_initialize_type_bad - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem::Dependency.new 'monkey' => '1.0' end @@ -44,7 +49,7 @@ def test_initialize_type assert_equal :runtime, dep("pkg").type assert_equal :development, dep("pkg", [], :development).type - assert_raises ArgumentError do + assert_raise ArgumentError do dep "pkg", :sometimes end end @@ -249,7 +254,7 @@ def test_merge_name_mismatch a = dep 'a' b = dep 'b' - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do a.merge b end @@ -331,7 +336,7 @@ def test_to_specs_suggests_other_versions dep = Gem::Dependency.new "a", "= 2.0" - e = assert_raises Gem::MissingSpecVersionError do + e = assert_raise Gem::MissingSpecVersionError do dep.to_specs end @@ -353,16 +358,12 @@ def test_to_specs_respects_bundler_version assert_equal [b, b_1], dep.to_specs - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["3.5", "reason"]) do - e = assert_raises Gem::MissingSpecVersionError do - dep.to_specs - end - - assert_match "Could not find 'bundler' (3.5) required by reason.\nTo update to the latest version installed on your system, run `bundle update --bundler`.\nTo install the missing version, run `gem install bundler:3.5`\n", e.message + Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do + assert_equal [b_1, b], dep.to_specs end - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["2.0.0.pre.1", "reason"]) do - assert_equal [b], dep.to_specs + Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("2.0.0.pre.1")) do + assert_equal [b, b_1], dep.to_specs end end @@ -378,7 +379,7 @@ def test_to_specs_indicates_total_gem_set_size dep = Gem::Dependency.new "b", "= 2.0" - e = assert_raises Gem::MissingSpecError do + e = assert_raise Gem::MissingSpecError do dep.to_specs end @@ -391,5 +392,4 @@ def test_identity assert_equal dep("a", " >= 1.a").identity, :abs_latest assert_equal dep("a").identity, :latest end - end diff --git a/ruby/test/rubygems/test_gem_dependency_installer.rb b/ruby/test/rubygems/test_gem_dependency_installer.rb index 22f3a9158..9cbdcefea 100644 --- a/ruby/test/rubygems/test_gem_dependency_installer.rb +++ b/ruby/test/rubygems/test_gem_dependency_installer.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/dependency_installer' require 'rubygems/security' class TestGemDependencyInstaller < Gem::TestCase - def setup super common_installer_setup @@ -45,70 +44,7 @@ def util_setup_gems s.add_development_dependency 'c' end - util_reset_gems - end - - def test_available_set_for_name - util_setup_gems - p1a, = util_gem 'a', '10.a' - util_setup_spec_fetcher p1a, @a1, @a1_pre - - inst = Gem::DependencyInstaller.new - - available = Gem::Deprecate.skip_during do - inst.available_set_for 'a', Gem::Requirement.default - end - - assert_equal %w[a-1], available.set.map { |s| s.spec.full_name } - end - - def test_available_set_for_name_prerelease - util_setup_gems - p1a, = util_gem 'a', '10.a' - util_setup_spec_fetcher p1a, @a1, @a1_pre - - inst = Gem::DependencyInstaller.new :prerelease => true - - available = Gem::Deprecate.skip_during do - inst.available_set_for 'a', Gem::Requirement.default - end - - assert_equal %w[a-10.a], - available.sorted.map { |s| s.spec.full_name } - end - - def test_available_set_for_dep - util_setup_gems - p1a, = util_gem 'a', '10.a' - util_setup_spec_fetcher p1a, @a1, @a1_pre - - inst = Gem::DependencyInstaller.new - - dep = Gem::Dependency.new 'a', Gem::Requirement.default - - available = Gem::Deprecate.skip_during do - inst.available_set_for dep, Gem::Requirement.default - end - - assert_equal %w[a-1], available.set.map { |s| s.spec.full_name } - end - - def test_available_set_for_dep_prerelease - util_setup_gems - p1a, = util_gem 'a', '10.a' - util_setup_spec_fetcher p1a, @a1, @a1_pre - - inst = Gem::DependencyInstaller.new :prerelease => true - - dep = Gem::Dependency.new 'a', Gem::Requirement.default - dep.prerelease = true - - available = Gem::Deprecate.skip_during do - inst.available_set_for dep, Gem::Requirement.default - end - - assert_equal %w[a-10.a], - available.sorted.map { |s| s.spec.full_name } + util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1) end def test_install @@ -177,7 +113,7 @@ def test_install_when_only_prerelease dep = Gem::Dependency.new "p" inst = Gem::DependencyInstaller.new - assert_raises Gem::UnsatisfiableDependencyError do + assert_raise Gem::UnsatisfiableDependencyError do inst.install dep end @@ -211,7 +147,7 @@ def test_install_all_dependencies FileUtils.mv @a1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir - FileUtils.mv e1_gem, @tempdir + FileUtils.mv e1_gem, @tempdir inst = nil @@ -220,7 +156,7 @@ def test_install_all_dependencies inst.install 'b' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }, + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, 'sanity check' Dir.chdir @tempdir do @@ -228,7 +164,7 @@ def test_install_all_dependencies inst.install 'e' end - assert_equal %w[a-1 e-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name } end def test_install_cache_dir @@ -245,7 +181,7 @@ def test_install_cache_dir inst.install 'b' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } assert File.exist? File.join(@gemhome, "cache", @a1.file_name) assert File.exist? File.join(@gemhome, "cache", @b1.file_name) @@ -270,7 +206,7 @@ def test_install_dependencies_satisfied inst.install 'a', req("= 2") end - assert_equal %w[a-2], inst.installed_gems.map { |s| s.full_name }, + assert_equal %w[a-2], inst.installed_gems.map {|s| s.full_name }, 'sanity check' FileUtils.rm File.join(@tempdir, a2.file_name) @@ -281,7 +217,7 @@ def test_install_dependencies_satisfied end assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name) - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end # This asserts that if a gem's dependency is satisfied by an @@ -302,7 +238,7 @@ def test_install_doesnt_upgrade_installed_dependencies FileUtils.mv @a1_gem, @tempdir FileUtils.mv a2_gem, @tempdir # not in index FileUtils.mv @b1_gem, @tempdir - FileUtils.mv a3_gem, @tempdir + FileUtils.mv a3_gem, @tempdir Dir.chdir @tempdir do Gem::DependencyInstaller.new.install 'a', req("= 2") @@ -318,7 +254,7 @@ def test_install_doesnt_upgrade_installed_dependencies end assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name) - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dependency @@ -341,7 +277,7 @@ def test_install_dependency inst.install 'b' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } assert done_installing_ran, 'post installs hook was not run' end @@ -351,8 +287,6 @@ def test_install_dependency_development @aa1, @aa1_gem = util_gem 'aa', '1' - util_reset_gems - FileUtils.mv @a1_gem, @tempdir FileUtils.mv @aa1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir @@ -363,7 +297,7 @@ def test_install_dependency_development inst.install 'b' end - assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dependency_development_deep @@ -371,8 +305,6 @@ def test_install_dependency_development_deep @aa1, @aa1_gem = util_gem 'aa', '1' - util_reset_gems - FileUtils.mv @a1_gem, @tempdir FileUtils.mv @aa1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir @@ -385,7 +317,7 @@ def test_install_dependency_development_deep inst.install 'd' end - assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dependency_development_shallow @@ -393,8 +325,6 @@ def test_install_dependency_development_shallow @aa1, @aa1_gem = util_gem 'aa', '1' - util_reset_gems - FileUtils.mv @a1_gem, @tempdir FileUtils.mv @aa1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir @@ -407,7 +337,7 @@ def test_install_dependency_development_shallow inst.install 'd' end - assert_equal %w[c-1 d-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[c-1 d-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dependency_existing @@ -423,7 +353,7 @@ def test_install_dependency_existing inst.install 'b' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dependency_existing_extension @@ -440,7 +370,7 @@ def test_install_dependency_existing_extension e1 = util_spec 'e', '1', nil, 'extconf.rb' do |s| s.extensions << 'extconf.rb' end - e1_gem = File.join @tempdir, 'gems', "#{e1.full_name}.gem" + e1_gem = e1.cache_file _, f1_gem = util_gem 'f', '1', 'e' => nil @@ -460,9 +390,9 @@ def test_install_dependency_existing_extension Dir.chdir pwd end - assert_equal %w[f-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[f-1], inst.installed_gems.map {|s| s.full_name } - assert_path_exists e1.extension_dir + assert_path_exist e1.extension_dir end def test_install_dependency_old @@ -480,7 +410,7 @@ def test_install_dependency_old inst.install 'f' end - assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[f-2], inst.installed_gems.map {|s| s.full_name } end def test_install_local @@ -494,7 +424,7 @@ def test_install_local inst.install 'a-1.gem' end - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_local_prerelease @@ -508,7 +438,7 @@ def test_install_local_prerelease inst.install 'a-1.a.gem' end - assert_equal %w[a-1.a], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1.a], inst.installed_gems.map {|s| s.full_name } end def test_install_local_dependency @@ -524,7 +454,7 @@ def test_install_local_dependency inst.install 'b-1.gem' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_local_dependency_installed @@ -542,7 +472,7 @@ def test_install_local_dependency_installed inst.install 'b-1.gem' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_local_subdir @@ -555,7 +485,7 @@ def test_install_local_subdir inst.install 'gems/a-1.gem' end - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_minimal_deps @@ -581,7 +511,7 @@ def test_install_minimal_deps inst.install 'b', req('= 1') end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }, + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, 'sanity check' Dir.chdir @tempdir do @@ -589,7 +519,41 @@ def test_install_minimal_deps inst.install 'e' end - assert_equal %w[a-1 e-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name } + end + + def test_install_no_minimal_deps + util_setup_gems + + _, e1_gem = util_gem 'e', '1' do |s| + s.add_dependency 'b' + end + + _, b2_gem = util_gem 'b', '2' do |s| + s.add_dependency 'a' + end + + FileUtils.mv @a1_gem, @tempdir + FileUtils.mv @b1_gem, @tempdir + FileUtils.mv b2_gem, @tempdir + FileUtils.mv e1_gem, @tempdir + + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst.install 'b', req('= 1') + end + + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, + 'sanity check' + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new :minimal_deps => false + inst.install 'e' + end + + assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map {|s| s.full_name } end def test_install_no_document @@ -622,7 +586,7 @@ def test_install_env_shebang env = "/\\S+/env" unless Gem.win_platform? - assert_match %r|\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n|, + assert_match %r{\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n}, File.read(File.join(@gemhome, 'bin', 'a_bin')) end @@ -639,7 +603,7 @@ def test_install_force inst.install 'b' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_build_args @@ -669,7 +633,7 @@ def test_install_ignore_dependencies inst.install 'b' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_install_dir @@ -690,7 +654,7 @@ def test_install_install_dir inst.install 'b' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name)) assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name)) @@ -714,7 +678,7 @@ def test_install_domain_both inst.install 'b' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } a1, b1 = inst.installed_gems assert_equal a1.spec_file, a1.loaded_from @@ -738,7 +702,7 @@ def test_install_domain_both_no_network inst.install 'b' end - assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_domain_local @@ -748,7 +712,7 @@ def test_install_domain_local inst = nil Dir.chdir @tempdir do - e = assert_raises Gem::UnsatisfiableDependencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do inst = Gem::DependencyInstaller.new :domain => :local inst.install 'b' end @@ -757,7 +721,7 @@ def test_install_domain_local assert_equal expected, e.message end - assert_equal [], inst.installed_gems.map { |s| s.full_name } + assert_equal [], inst.installed_gems.map {|s| s.full_name } end def test_install_domain_remote @@ -773,7 +737,7 @@ def test_install_domain_remote inst = Gem::DependencyInstaller.new :domain => :remote inst.install 'a' - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_dual_repository @@ -790,7 +754,7 @@ def test_install_dual_repository inst.install 'a' end - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }, + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }, 'sanity check' ENV['GEM_HOME'] = @gemhome @@ -802,7 +766,7 @@ def test_install_dual_repository inst.install 'b' end - assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } end def test_install_reinstall @@ -813,7 +777,7 @@ def test_install_reinstall inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new + inst = Gem::DependencyInstaller.new :force => true inst.install 'a' end @@ -837,7 +801,7 @@ def test_install_remote inst.install 'a' end - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_remote_dep @@ -857,7 +821,7 @@ def test_install_remote_dep inst.install dep end - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_remote_platform_newer @@ -890,7 +854,7 @@ def test_install_remote_platform_newer inst = Gem::DependencyInstaller.new :domain => :remote inst.install 'a' - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } end def test_install_platform_is_ignored_when_a_file_is_specified @@ -901,30 +865,32 @@ def test_install_platform_is_ignored_when_a_file_is_specified inst = Gem::DependencyInstaller.new :domain => :local inst.install a_gem - assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map {|s| s.full_name } end - if defined? OpenSSL + require 'rubygems/openssl' + + if Gem::HAVE_OPENSSL def test_install_security_policy util_setup_gems - data = File.open(@a1_gem, 'rb') { |f| f.read } + data = File.open(@a1_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data - data = File.open(@b1_gem, 'rb') { |f| f.read } + data = File.open(@b1_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data policy = Gem::Security::HighSecurity inst = Gem::DependencyInstaller.new :security_policy => policy - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do inst.install 'b' end assert_equal 'unsigned gems are not allowed by the High Security policy', e.message - assert_equal %w[], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[], inst.installed_gems.map {|s| s.full_name } end end @@ -938,7 +904,7 @@ def test_install_no_wrappers inst = Gem::DependencyInstaller.new :wrappers => false, :format_executable => false inst.install 'a' - refute_match(%r|This file was generated by RubyGems.|, + refute_match(%r{This file was generated by RubyGems.}, File.read(File.join(@gemhome, 'bin', 'a_bin'))) end end @@ -946,126 +912,102 @@ def test_install_no_wrappers def test_install_version util_setup_d - data = File.open(@d2_gem, 'rb') { |f| f.read } + data = File.open(@d2_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data - data = File.open(@d1_gem, 'rb') { |f| f.read } + data = File.open(@d1_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data inst = Gem::DependencyInstaller.new inst.install 'd', '= 1' - assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[d-1], inst.installed_gems.map {|s| s.full_name } end def test_install_version_default util_setup_d - data = File.open(@d2_gem, 'rb') { |f| f.read } + data = File.open(@d2_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data - data = File.open(@d1_gem, 'rb') { |f| f.read } + data = File.open(@d1_gem, 'rb') {|f| f.read } @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data inst = Gem::DependencyInstaller.new inst.install 'd' - assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name } + assert_equal %w[d-2], inst.installed_gems.map {|s| s.full_name } end - def test_find_gems_gems_with_sources - util_setup_gems - - inst = Gem::DependencyInstaller.new - dep = Gem::Dependency.new 'b', '>= 0' - - Gem::Specification.reset + def test_install_legacy_spec_with_nil_required_ruby_version + path = File.expand_path "../data/null-required-ruby-version.gemspec.rz", __FILE__ + spec = Marshal.load Gem.read_binary(path) + def spec.validate(*args); end - set = Gem::Deprecate.skip_during do - inst.find_gems_with_sources(dep) - end + util_build_gem spec - assert_kind_of Gem::AvailableSet, set + cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" + FileUtils.mkdir_p File.dirname cache_file + FileUtils.mv spec.cache_file, cache_file - s = set.set.first + util_setup_spec_fetcher spec - assert_equal @b1, s.spec - assert_equal Gem::Source.new(@gem_repo), s.source - end + data = Gem.read_binary(cache_file) - def test_find_spec_by_name_and_version_wildcard - util_gem 'a', 1 - FileUtils.mv 'gems/a-1.gem', @tempdir + @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data - FileUtils.touch 'rdoc.gem' + dep = Gem::Dependency.new 'activesupport' inst = Gem::DependencyInstaller.new + inst.install dep - available = Gem::Deprecate.skip_during do - inst.find_spec_by_name_and_version('*.gem') - end - - assert_equal %w[a-1], available.each_spec.map { |spec| spec.full_name } + assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name) end - def test_find_spec_by_name_and_version_wildcard_bad_gem - FileUtils.touch 'rdoc.gem' + def test_install_legacy_spec_with_nil_required_rubygems_version + path = File.expand_path "../data/null-required-rubygems-version.gemspec.rz", __FILE__ + spec = Marshal.load Gem.read_binary(path) + def spec.validate(*args); end - inst = Gem::DependencyInstaller.new + util_build_gem spec - assert_raises Gem::Package::FormatError do - Gem::Deprecate.skip_during do - inst.find_spec_by_name_and_version '*.gem' - end - end - end + cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" + FileUtils.mkdir_p File.dirname cache_file + FileUtils.mv spec.cache_file, cache_file - def test_find_spec_by_name_and_version_bad_gem - FileUtils.touch 'rdoc.gem' + util_setup_spec_fetcher spec - inst = Gem::DependencyInstaller.new + data = Gem.read_binary(cache_file) - e = assert_raises Gem::Package::FormatError do - Gem::Deprecate.skip_during do - inst.find_spec_by_name_and_version 'rdoc.gem' - end - end - - full_path = File.join @tempdir, 'rdoc.gem' - assert_equal "package metadata is missing in #{full_path}", e.message - end + @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data - def test_find_spec_by_name_and_version_directory - Dir.mkdir 'rdoc' + dep = Gem::Dependency.new 'activesupport' inst = Gem::DependencyInstaller.new + inst.install dep - e = assert_raises Gem::SpecificGemNotFoundException do - Gem::Deprecate.skip_during do - inst.find_spec_by_name_and_version 'rdoc' - end - end - - assert_equal "Could not find a valid gem 'rdoc' (>= 0) " + - "locally or in a repository", - e.message + assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name) end - def test_find_spec_by_name_and_version_file - FileUtils.touch 'rdoc' + def test_find_gems_gems_with_sources + util_setup_gems inst = Gem::DependencyInstaller.new + dep = Gem::Dependency.new 'b', '>= 0' - e = assert_raises Gem::SpecificGemNotFoundException do - Gem::Deprecate.skip_during do - inst.find_spec_by_name_and_version 'rdoc' - end + Gem::Specification.reset + + set = Gem::Deprecate.skip_during do + inst.find_gems_with_sources(dep) end - assert_equal "Could not find a valid gem 'rdoc' (>= 0) " + - "locally or in a repository", - e.message + assert_kind_of Gem::AvailableSet, set + + s = set.set.first + + assert_equal @b1, s.spec + assert_equal Gem::Source.new(@gem_repo), s.source end def test_find_gems_with_sources_local @@ -1109,8 +1051,8 @@ def test_find_gems_with_sources_prerelease releases = set.all_specs - assert releases.any? { |s| s.name == 'a' and s.version.to_s == '1' } - refute releases.any? { |s| s.name == 'a' and s.version.to_s == '1.a' } + assert releases.any? {|s| s.name == 'a' and s.version.to_s == '1' } + refute releases.any? {|s| s.name == 'a' and s.version.to_s == '1.a' } dependency.prerelease = true @@ -1168,7 +1110,7 @@ def test_resolve_dependencies inst = Gem::DependencyInstaller.new request_set = inst.resolve_dependencies 'b', req('>= 0') - requests = request_set.sorted_requests.map { |req| req.full_name } + requests = request_set.sorted_requests.map {|req| req.full_name } assert_equal %w[a-1 b-1], requests end @@ -1182,7 +1124,7 @@ def test_resolve_dependencies_ignore_dependencies inst = Gem::DependencyInstaller.new :ignore_dependencies => true request_set = inst.resolve_dependencies 'b', req('>= 0') - requests = request_set.sorted_requests.map { |req| req.full_name } + requests = request_set.sorted_requests.map {|req| req.full_name } assert request_set.ignore_dependencies @@ -1199,71 +1141,15 @@ def test_resolve_dependencies_local inst = Gem::DependencyInstaller.new request_set = inst.resolve_dependencies 'a-1.gem', req('>= 0') - requests = request_set.sorted_requests.map { |req| req.full_name } + requests = request_set.sorted_requests.map {|req| req.full_name } assert_equal %w[a-1], requests end - def util_write_a1_bin - write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp| - fp.puts "#!/usr/bin/ruby" - end - end - - def util_setup_c1_pre - @c1_pre, @c1_pre_gem = util_spec 'c', '1.a' do |s| - s.add_dependency 'a', '1.a' - s.add_dependency 'b', '1' - end - - util_reset_gems - end - def util_setup_d @d1, @d1_gem = util_gem 'd', '1' @d2, @d2_gem = util_gem 'd', '2' - util_reset_gems + util_setup_spec_fetcher(@d1, @d2) end - - def util_setup_wxyz - @x1_m, @x1_m_gem = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @x1_o, @x1_o_gem = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu other_platform 1] - end - - @w1, @w1_gem = util_spec 'w', '1', 'x' => nil - - @y1, @y1_gem = util_spec 'y', '1' - @y1_1_p, @y1_1_p_gem = util_spec 'y', '1.1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @z1, @z1_gem = util_spec 'z', '1', 'y' => nil - - util_reset_gems - end - - def util_reset_gems - @a1 ||= nil - @b1 ||= nil - @a1_pre ||= nil - @c1_pre ||= nil - @d1 ||= nil - @d2 ||= nil - @w1 ||= nil - @x1_m ||= nil - @x1_o ||= nil - @y1 ||= nil - @y1_1_p ||= nil - @z1 ||= nil - - util_setup_spec_fetcher(*[@a1, @a1_pre, @b1, @c1_pre, - @d1, @d2, @x1_m, @x1_o, @w1, @y1, - @y1_1_p, @z1].compact) - end - end diff --git a/ruby/test/rubygems/test_gem_dependency_list.rb b/ruby/test/rubygems/test_gem_dependency_list.rb index 6bf803fe5..15c50de19 100644 --- a/ruby/test/rubygems/test_gem_dependency_list.rb +++ b/ruby/test/rubygems/test_gem_dependency_list.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/dependency_list' class TestGemDependencyList < Gem::TestCase - def setup super @@ -53,7 +52,7 @@ def test_dependency_order order = @deplist.dependency_order - assert_equal %w[d-1 c-1 b-1 a-1], order.map { |s| s.full_name } + assert_equal %w[d-1 c-1 b-1 a-1], order.map {|s| s.full_name } end def test_dependency_order_circle @@ -62,7 +61,7 @@ def test_dependency_order_circle order = @deplist.dependency_order - assert_equal %w[b-1 c-1 a-1], order.map { |s| s.full_name } + assert_equal %w[b-1 c-1 a-1], order.map {|s| s.full_name } end def test_dependency_order_development @@ -80,7 +79,7 @@ def test_dependency_order_development order = deplist.dependency_order - assert_equal %w[g-1 a-1 f-1 e-1], order.map { |s| s.full_name }, + assert_equal %w[g-1 a-1 f-1 e-1], order.map {|s| s.full_name }, 'development on' deplist2 = Gem::DependencyList.new @@ -88,7 +87,7 @@ def test_dependency_order_development order = deplist2.dependency_order - assert_equal %w[a-1 g-1 f-1 e-1], order.map { |s| s.full_name }, + assert_equal %w[a-1 g-1 f-1 e-1], order.map {|s| s.full_name }, 'development off' end @@ -100,7 +99,7 @@ def test_dependency_order_diamond order = @deplist.dependency_order - assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map { |s| s.full_name }, + assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map {|s| s.full_name }, 'deps of trimmed specs not included' end @@ -109,7 +108,7 @@ def test_dependency_order_no_dependencies order = @deplist.dependency_order - assert_equal %w[c-2 a-1], order.map { |s| s.full_name } + assert_equal %w[c-2 a-1], order.map {|s| s.full_name } end def test_find_name @@ -134,14 +133,14 @@ def test_ok_eh end def test_why_not_ok_eh - assert_equal({}, @deplist.why_not_ok?) + assert_equal({}, @deplist.why_not_ok?) @deplist.add @b2 exp = { "b" => [ - Gem::Dependency.new("a", ">= 1") - ] + Gem::Dependency.new("a", ">= 1"), + ], } assert_equal exp, @deplist.why_not_ok? @@ -162,7 +161,7 @@ def test_why_not_ok_eh_old_dependency @deplist.add a, b0, b1 - assert_equal({}, @deplist.why_not_ok?) + assert_equal({}, @deplist.why_not_ok?) end def test_ok_eh_mismatch @@ -262,5 +261,4 @@ def util_diamond @deplist.add @a1, @a2, @b1, @c2, @d1 end - end diff --git a/ruby/test/rubygems/test_gem_dependency_resolution_error.rb b/ruby/test/rubygems/test_gem_dependency_resolution_error.rb index cf4663650..0e4a2fe31 100644 --- a/ruby/test/rubygems/test_gem_dependency_resolution_error.rb +++ b/ruby/test/rubygems/test_gem_dependency_resolution_error.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemDependencyResolutionError < Gem::TestCase - def setup super @@ -21,8 +20,7 @@ def setup end def test_message - assert_match %r%^conflicting dependencies a \(= 1\) and a \(= 2\)$%, + assert_match %r{^conflicting dependencies a \(= 1\) and a \(= 2\)$}, @error.message end - end diff --git a/ruby/test/rubygems/test_gem_doctor.rb b/ruby/test/rubygems/test_gem_doctor.rb index a0e3a18d7..583c735dd 100644 --- a/ruby/test/rubygems/test_gem_doctor.rb +++ b/ruby/test/rubygems/test_gem_doctor.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/doctor' class TestGemDoctor < Gem::TestCase - def gem(name) spec = quick_gem name do |gem| gem.files = %W[lib/#{name}.rb Rakefile] @@ -28,31 +27,31 @@ def test_doctor io.write 'this will raise an exception when evaluated.' end - assert_path_exists File.join(a.gem_dir, 'Rakefile') - assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb') + assert_path_exist File.join(a.gem_dir, 'Rakefile') + assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb') - assert_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_exist b.gem_dir + assert_path_not_exist b.spec_file - assert_path_exists c.gem_dir - assert_path_exists c.spec_file + assert_path_exist c.gem_dir + assert_path_exist c.spec_file doctor = Gem::Doctor.new @gemhome - capture_io do + capture_output do use_ui @ui do doctor.doctor end end - assert_path_exists File.join(a.gem_dir, 'Rakefile') - assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb') + assert_path_exist File.join(a.gem_dir, 'Rakefile') + assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb') - refute_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_not_exist b.gem_dir + assert_path_not_exist b.spec_file - refute_path_exists c.gem_dir - refute_path_exists c.spec_file + assert_path_not_exist c.gem_dir + assert_path_not_exist c.spec_file expected = <<-OUTPUT Checking #{@gemhome} @@ -81,31 +80,31 @@ def test_doctor_dry_run io.write 'this will raise an exception when evaluated.' end - assert_path_exists File.join(a.gem_dir, 'Rakefile') - assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb') + assert_path_exist File.join(a.gem_dir, 'Rakefile') + assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb') - assert_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_exist b.gem_dir + assert_path_not_exist b.spec_file - assert_path_exists c.gem_dir - assert_path_exists c.spec_file + assert_path_exist c.gem_dir + assert_path_exist c.spec_file doctor = Gem::Doctor.new @gemhome, true - capture_io do + capture_output do use_ui @ui do doctor.doctor end end - assert_path_exists File.join(a.gem_dir, 'Rakefile') - assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb') + assert_path_exist File.join(a.gem_dir, 'Rakefile') + assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb') - assert_path_exists b.gem_dir - refute_path_exists b.spec_file + assert_path_exist b.gem_dir + assert_path_not_exist b.spec_file - assert_path_exists c.gem_dir - assert_path_exists c.spec_file + assert_path_exist c.gem_dir + assert_path_exist c.spec_file expected = <<-OUTPUT Checking #{@gemhome} @@ -128,13 +127,13 @@ def test_doctor_non_gem_home doctor = Gem::Doctor.new @tempdir - capture_io do + capture_output do use_ui @ui do doctor.doctor end end - assert_path_exists other_dir + assert_path_exist other_dir expected = <<-OUTPUT Checking #{@tempdir} @@ -153,6 +152,34 @@ def test_doctor_child_missing assert true # count end + def test_doctor_badly_named_plugins + gem 'a' + + Gem.use_paths @gemhome.to_s + + FileUtils.mkdir_p Gem.plugindir + bad_plugin = File.join(Gem.plugindir, "a_badly_named_file.rb") + write_file bad_plugin + + doctor = Gem::Doctor.new @gemhome + + capture_output do + use_ui @ui do + doctor.doctor + end + end + + # assert_path_not_exist bad_plugin + + expected = <<-OUTPUT +Checking #{@gemhome} +Removed file plugins/a_badly_named_file.rb + + OUTPUT + + assert_equal expected, @ui.output + end + def test_gem_repository_eh doctor = Gem::Doctor.new @gemhome @@ -164,5 +191,4 @@ def test_gem_repository_eh assert doctor.gem_repository?, 'gems installed' end - end diff --git a/ruby/test/rubygems/test_gem_ext_builder.rb b/ruby/test/rubygems/test_gem_ext_builder.rb index 7091acdca..165194510 100644 --- a/ruby/test/rubygems/test_gem_ext_builder.rb +++ b/ruby/test/rubygems/test_gem_ext_builder.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/ext' require 'rubygems/installer' class TestGemExtBuilder < Gem::TestCase - def setup super @@ -15,6 +14,7 @@ def setup FileUtils.mkdir_p @dest_path @orig_DESTDIR = ENV['DESTDIR'] + @orig_make = ENV['make'] @spec = util_spec 'a' @@ -23,6 +23,7 @@ def setup def teardown ENV['DESTDIR'] = @orig_DESTDIR + ENV['make'] = @orig_make super end @@ -31,9 +32,8 @@ def test_class_make ENV['DESTDIR'] = 'destination' results = [] - Dir.chdir @ext do - File.open 'Makefile', 'w' do |io| - io.puts <<-MAKEFILE + File.open File.join(@ext, 'Makefile'), 'w' do |io| + io.puts <<-MAKEFILE all: \t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}" @@ -42,22 +42,21 @@ def test_class_make install: \t@#{Gem.ruby} -e "puts %Q{install: \#{ENV['DESTDIR']}}" - MAKEFILE - end - - Gem::Ext::Builder.make @dest_path, results + MAKEFILE end - results = results.join "\n" + Gem::Ext::Builder.make @dest_path, results, @ext + + results = results.join("\n").b - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results if /nmake/ !~ results - assert_match %r%^clean: destination$%, results - assert_match %r%^all: destination$%, results - assert_match %r%^install: destination$%, results + assert_match %r{^clean: destination$}, results + assert_match %r{^all: destination$}, results + assert_match %r{^install: destination$}, results end end @@ -65,28 +64,49 @@ def test_class_make_no_clean ENV['DESTDIR'] = 'destination' results = [] - Dir.chdir @ext do - File.open 'Makefile', 'w' do |io| - io.puts <<-MAKEFILE + File.open File.join(@ext, 'Makefile'), 'w' do |io| + io.puts <<-MAKEFILE all: \t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}" install: \t@#{Gem.ruby} -e "puts %Q{install: \#{ENV['DESTDIR']}}" - MAKEFILE - end - - Gem::Ext::Builder.make @dest_path, results + MAKEFILE end - results = results.join "\n" + Gem::Ext::Builder.make @dest_path, results, @ext + + results = results.join("\n").b - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results + assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results + end + + def test_custom_make_with_options + ENV['make'] = 'make V=1' + results = [] + File.open File.join(@ext, 'Makefile'), 'w' do |io| + io.puts <<-MAKEFILE +all: +\t@#{Gem.ruby} -e "puts 'all: OK'" + +clean: +\t@#{Gem.ruby} -e "puts 'clean: OK'" + +install: +\t@#{Gem.ruby} -e "puts 'install: OK'" + MAKEFILE + end + Gem::Ext::Builder.make @dest_path, results, @ext + results = results.join("\n").b + assert_match %r{clean: OK}, results + assert_match %r{all: OK}, results + assert_match %r{install: OK}, results end def test_build_extensions + pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning @spec.extensions << 'ext/extconf.rb' ext_dir = File.join @spec.gem_dir, 'ext' @@ -113,15 +133,16 @@ def test_build_extensions @builder.build_extensions end - assert_path_exists @spec.extension_dir - assert_path_exists @spec.gem_build_complete_path - assert_path_exists File.join @spec.extension_dir, 'gem_make.out' - assert_path_exists File.join @spec.extension_dir, 'a.rb' - assert_path_exists File.join @spec.gem_dir, 'lib', 'a.rb' - assert_path_exists File.join @spec.gem_dir, 'lib', 'a', 'b.rb' + assert_path_exist @spec.extension_dir + assert_path_exist @spec.gem_build_complete_path + assert_path_exist File.join @spec.extension_dir, 'gem_make.out' + assert_path_exist File.join @spec.extension_dir, 'a.rb' + assert_path_exist File.join @spec.gem_dir, 'lib', 'a.rb' + assert_path_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb' end def test_build_extensions_with_gemhome_with_space + pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning new_gemhome = File.join @tempdir, 'gem home' File.rename(@gemhome, new_gemhome) @gemhome = new_gemhome @@ -134,7 +155,6 @@ def test_build_extensions_with_gemhome_with_space def test_build_extensions_install_ext_only class << Gem - alias orig_install_extension_in_lib install_extension_in_lib remove_method :install_extension_in_lib @@ -142,8 +162,8 @@ class << Gem def Gem.install_extension_in_lib false end - end + pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning @spec.extensions << 'ext/extconf.rb' @@ -171,19 +191,17 @@ def Gem.install_extension_in_lib @builder.build_extensions end - assert_path_exists @spec.extension_dir - assert_path_exists @spec.gem_build_complete_path - assert_path_exists File.join @spec.extension_dir, 'gem_make.out' - assert_path_exists File.join @spec.extension_dir, 'a.rb' - refute_path_exists File.join @spec.gem_dir, 'lib', 'a.rb' - refute_path_exists File.join @spec.gem_dir, 'lib', 'a', 'b.rb' + assert_path_exist @spec.extension_dir + assert_path_exist @spec.gem_build_complete_path + assert_path_exist File.join @spec.extension_dir, 'gem_make.out' + assert_path_exist File.join @spec.extension_dir, 'a.rb' + assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a.rb' + assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb' ensure class << Gem - remove_method :install_extension_in_lib alias install_extension_in_lib orig_install_extension_in_lib - end end @@ -195,7 +213,7 @@ def test_build_extensions_none assert_equal '', @ui.output assert_equal '', @ui.error - refute_path_exists File.join @spec.extension_dir, 'gem_make.out' + assert_path_not_exist File.join @spec.extension_dir, 'gem_make.out' end def test_build_extensions_rebuild_failure @@ -204,13 +222,13 @@ def test_build_extensions_rebuild_failure @spec.extensions << nil - assert_raises Gem::Ext::BuildError do + assert_raise Gem::Ext::BuildError do use_ui @ui do @builder.build_extensions end end - refute_path_exists @spec.gem_build_complete_path + assert_path_not_exist @spec.gem_build_complete_path end def test_build_extensions_extconf_bad @@ -220,32 +238,23 @@ def test_build_extensions_extconf_bad FileUtils.mkdir_p @spec.gem_dir - e = assert_raises Gem::Ext::BuildError do + e = assert_raise Gem::Ext::BuildError do use_ui @ui do @builder.build_extensions end end assert_match(/\AERROR: Failed to build gem native extension.$/, e.message) - - assert_equal "Building native extensions. This could take a while...\n", - @ui.output + assert_equal "Building native extensions. This could take a while...\n", @ui.output assert_equal '', @ui.error gem_make_out = File.join @spec.extension_dir, 'gem_make.out' + cmd_make_out = File.read(gem_make_out) - assert_match %r%#{Regexp.escape Gem.ruby}.* extconf\.rb%, - File.read(gem_make_out) - assert_match %r%: No such file%, - File.read(gem_make_out) - - refute_path_exists @spec.gem_build_complete_path + assert_match %r{#{Regexp.escape Gem.ruby} .* extconf\.rb}, cmd_make_out + assert_match %r{: No such file}, cmd_make_out - skip "Gem.ruby is not the name of the binary being run in the end" \ - unless File.read(gem_make_out).include? "#{Gem.ruby}:" - - assert_match %r%#{Regexp.escape Gem.ruby}: No such file%, - File.read(gem_make_out) + assert_path_not_exist @spec.gem_build_complete_path assert_equal cwd, Dir.pwd end @@ -255,21 +264,19 @@ def test_build_extensions_unsupported gem_make_out = File.join @spec.extension_dir, 'gem_make.out' @spec.extensions << nil - e = assert_raises Gem::Ext::BuildError do + e = assert_raise Gem::Ext::BuildError do use_ui @ui do @builder.build_extensions end end assert_match(/^\s*No builder for extension ''$/, e.message) - - assert_equal "Building native extensions. This could take a while...\n", - @ui.output + assert_equal "Building native extensions. This could take a while...\n", @ui.output assert_equal '', @ui.error assert_equal "No builder for extension ''\n", File.read(gem_make_out) - refute_path_exists @spec.gem_build_complete_path + assert_path_not_exist @spec.gem_build_complete_path ensure FileUtils.rm_f gem_make_out end @@ -304,7 +311,7 @@ def test_build_extensions_with_build_args path = File.join @spec.gem_dir, "extconf_args" assert_equal args.inspect, File.read(path).strip - assert_path_exists @spec.extension_dir + assert_path_exist @spec.extension_dir end def test_initialize @@ -328,5 +335,4 @@ def test_initialize_build_args assert_equal %w[--with-foo-dir=/nonexistent], builder.build_args end - end unless Gem.java_platform? diff --git a/ruby/test/rubygems/test_gem_ext_cmake_builder.rb b/ruby/test/rubygems/test_gem_ext_cmake_builder.rb index f7dc383fe..5ab82c545 100644 --- a/ruby/test/rubygems/test_gem_ext_cmake_builder.rb +++ b/ruby/test/rubygems/test_gem_ext_cmake_builder.rb @@ -1,20 +1,20 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/ext' class TestGemExtCmakeBuilder < Gem::TestCase - def setup super # Details: https://github.com/rubygems/rubygems/issues/1270#issuecomment-177368340 - skip "CmakeBuilder doesn't work on Windows." if Gem.win_platform? - - skip "CmakeBuilder doesn't work on JRuby." if Gem.java_platform? && ENV["CI"] + pend "CmakeBuilder doesn't work on Windows." if Gem.win_platform? - system('cmake', out: IO::NULL, err: [:child, :out]) - - skip 'cmake not present' unless $?.success? + begin + _, status = Open3.capture2e('cmake') + pend 'cmake not present' unless status.success? + rescue Errno::ENOENT + pend 'cmake not present' + end @ext = File.join @tempdir, 'ext' @dest_path = File.join @tempdir, 'prefix' @@ -25,49 +25,43 @@ def setup def test_self_build File.open File.join(@ext, 'CMakeLists.txt'), 'w' do |cmakelists| - cmakelists.write <<-eo_cmake + cmakelists.write <<-EO_CMAKE cmake_minimum_required(VERSION 2.6) project(self_build NONE) install (FILES test.txt DESTINATION bin) - eo_cmake + EO_CMAKE end FileUtils.touch File.join(@ext, 'test.txt') output = [] - Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, @dest_path, output - end + Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext output = output.join "\n" - assert_match \ - %r%^cmake \. -DCMAKE_INSTALL_PREFIX=#{Regexp.escape @dest_path}%, output - assert_match %r%#{Regexp.escape @ext}%, output + assert_match %r{^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output + assert_match %r{#{Regexp.escape @ext}}, output assert_contains_make_command '', output assert_contains_make_command 'install', output - assert_match %r%test\.txt%, output + assert_match %r{test\.txt}, output end def test_self_build_fail output = [] - error = assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, @dest_path, output - end + error = assert_raise Gem::InstallError do + Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext end output = output.join "\n" shell_error_msg = %r{(CMake Error: .*)} - sh_prefix_cmake = "cmake . -DCMAKE_INSTALL_PREFIX=" assert_match 'cmake failed', error.message - assert_match %r%^#{sh_prefix_cmake}#{Regexp.escape @dest_path}%, output - assert_match %r%#{shell_error_msg}%, output + assert_match %r{^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output + assert_match %r{#{shell_error_msg}}, output end def test_self_build_has_makefile @@ -77,14 +71,11 @@ def test_self_build_has_makefile output = [] - Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, @dest_path, output - end + Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext output = output.join "\n" assert_contains_make_command '', output assert_contains_make_command 'install', output end - end diff --git a/ruby/test/rubygems/test_gem_ext_configure_builder.rb b/ruby/test/rubygems/test_gem_ext_configure_builder.rb index eeeb654ae..76ccfe2dc 100644 --- a/ruby/test/rubygems/test_gem_ext_configure_builder.rb +++ b/ruby/test/rubygems/test_gem_ext_configure_builder.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/ext' class TestGemExtConfigureBuilder < Gem::TestCase - def setup super @@ -18,11 +17,7 @@ def setup end def test_self_build - if java_platform? && ENV["CI"] - skip("failing on jruby") - end - - skip("test_self_build skipped on MS Windows (VC++)") if vc_windows? + pend("test_self_build skipped on MS Windows (VC++)") if vc_windows? File.open File.join(@ext, './configure'), 'w' do |configure| configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile" @@ -30,12 +25,10 @@ def test_self_build output = [] - Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, @dest_path, output - end + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext assert_match(/^current directory:/, output.shift) - assert_equal "sh ./configure --prefix=#{@dest_path}", output.shift + assert_equal "sh ./configure --prefix\\=#{@dest_path}", output.shift assert_equal "", output.shift assert_match(/^current directory:/, output.shift) assert_contains_make_command 'clean', output.shift @@ -49,33 +42,27 @@ def test_self_build end def test_self_build_fail - if java_platform? && ENV["CI"] - skip("failing on jruby") - end - - skip("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows? + pend("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows? output = [] - error = assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, @dest_path, output - end + error = assert_raise Gem::InstallError do + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext end shell_error_msg = %r{(\./configure: .*)|((?:[Cc]an't|cannot) open '?\./configure'?(?:: No such file or directory)?)} - sh_prefix_configure = "sh ./configure --prefix=" + sh_prefix_configure = "sh ./configure --prefix\\=" assert_match 'configure failed', error.message assert_match(/^current directory:/, output.shift) assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift - assert_match %r(#{shell_error_msg}), output.shift + assert_match %r{#{shell_error_msg}}, output.shift assert_equal true, output.empty? end def test_self_build_has_makefile if vc_windows? && !nmake_found? - skip("test_self_build_has_makefile skipped - nmake not found") + pend("test_self_build_has_makefile skipped - nmake not found") end File.open File.join(@ext, 'Makefile'), 'w' do |makefile| @@ -83,13 +70,10 @@ def test_self_build_has_makefile end output = [] - Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, @dest_path, output - end + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext assert_contains_make_command 'clean', output[1] assert_contains_make_command '', output[4] assert_contains_make_command 'install', output[7] end - end diff --git a/ruby/test/rubygems/test_gem_ext_ext_conf_builder.rb b/ruby/test/rubygems/test_gem_ext_ext_conf_builder.rb index 556761c97..10a544cbb 100644 --- a/ruby/test/rubygems/test_gem_ext_ext_conf_builder.rb +++ b/ruby/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -1,11 +1,9 @@ -# coding: UTF-8 # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/ext' class TestGemExtExtConfBuilder < Gem::TestCase - def setup super @@ -18,11 +16,11 @@ def setup def test_class_build if java_platform? - skip("failing on jruby") + pend("failing on jruby") end if vc_windows? && !nmake_found? - skip("test_class_build skipped - nmake not found") + pend("test_class_build skipped - nmake not found") end File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| @@ -31,12 +29,9 @@ def test_class_build output = [] - Dir.chdir @ext do - result = - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output + result = Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext - assert_same result, output - end + assert_same result, output assert_match(/^current directory:/, output[0]) assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1]) @@ -46,11 +41,12 @@ def test_class_build assert_contains_make_command '', output[7] assert_contains_make_command 'install', output[10] assert_empty Dir.glob(File.join(@ext, 'siteconf*.rb')) + assert_empty Dir.glob(File.join(@ext, '.gem.*')) end def test_class_build_rbconfig_make_prog if java_platform? - skip("failing on jruby") + pend("failing on jruby") end configure_args do @@ -61,9 +57,7 @@ def test_class_build_rbconfig_make_prog output = [] - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output - end + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext assert_equal "creating Makefile\n", output[2] assert_contains_make_command 'clean', output[4] @@ -72,12 +66,15 @@ def test_class_build_rbconfig_make_prog end end - def test_class_build_env_make - env_make = ENV.delete 'MAKE' + def test_class_build_env_MAKE + env_make = ENV.delete 'make' + ENV['make'] = nil + + env_MAKE = ENV.delete 'MAKE' ENV['MAKE'] = 'anothermake' if java_platform? - skip("failing on jruby") + pend("failing on jruby") end configure_args '' do @@ -87,22 +84,21 @@ def test_class_build_env_make output = [] - assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output - end + assert_raise Gem::InstallError do + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext end assert_equal "creating Makefile\n", output[2] assert_contains_make_command 'clean', output[4] end ensure - ENV['MAKE'] = env_make + ENV['MAKE'] = env_MAKE + ENV['make'] = env_make end def test_class_build_extconf_fail if vc_windows? && !nmake_found? - skip("test_class_build_extconf_fail skipped - nmake not found") + pend("test_class_build_extconf_fail skipped - nmake not found") end File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| @@ -113,10 +109,8 @@ def test_class_build_extconf_fail output = [] - error = assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output - end + error = assert_raise Gem::InstallError do + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext end assert_equal 'extconf failed, exit code 1', error.message @@ -125,12 +119,12 @@ def test_class_build_extconf_fail assert_match(File.join(@dest_path, 'mkmf.log'), output[4]) assert_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n") - assert_path_exists File.join @dest_path, 'mkmf.log' + assert_path_exist File.join @dest_path, 'mkmf.log' end def test_class_build_extconf_success_without_warning if vc_windows? && !nmake_found? - skip("test_class_build_extconf_fail skipped - nmake not found") + pend("test_class_build_extconf_fail skipped - nmake not found") end File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| @@ -141,18 +135,16 @@ def test_class_build_extconf_success_without_warning output = [] - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output - end + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext refute_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n") - assert_path_exists File.join @dest_path, 'mkmf.log' + assert_path_exist File.join @dest_path, 'mkmf.log' end def test_class_build_unconventional if vc_windows? && !nmake_found? - skip("test_class_build skipped - nmake not found") + pend("test_class_build skipped - nmake not found") end File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| @@ -183,9 +175,7 @@ def test_class_build_unconventional output = [] - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output - end + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext assert_contains_make_command 'clean', output[4] assert_contains_make_command '', output[7] @@ -195,7 +185,7 @@ def test_class_build_unconventional def test_class_make if vc_windows? && !nmake_found? - skip("test_class_make skipped - nmake not found") + pend("test_class_make skipped - nmake not found") end output = [] @@ -209,9 +199,7 @@ def test_class_make makefile.puts "install:" end - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.make @ext, output - end + Gem::Ext::ExtConfBuilder.make @ext, output, @ext assert_contains_make_command 'clean', output[1] assert_contains_make_command '', output[4] @@ -219,10 +207,8 @@ def test_class_make end def test_class_make_no_Makefile - error = assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.make @ext, ['output'] - end + error = assert_raise Gem::InstallError do + Gem::Ext::ExtConfBuilder.make @ext, ['output'], @ext end assert_equal 'Makefile not found', error.message @@ -241,5 +227,4 @@ def configure_args(args = nil) RbConfig::CONFIG.delete 'configure_args' end end - end diff --git a/ruby/test/rubygems/test_gem_ext_rake_builder.rb b/ruby/test/rubygems/test_gem_ext_rake_builder.rb index c86ff0764..3d8922eed 100644 --- a/ruby/test/rubygems/test_gem_ext_rake_builder.rb +++ b/ruby/test/rubygems/test_gem_ext_rake_builder.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/ext' class TestGemExtRakeBuilder < Gem::TestCase - def setup super @@ -19,15 +18,13 @@ def test_class_build output = [] build_rake_in do |rake| - Dir.chdir @ext do - Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output - end + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [], nil, @ext output = output.join "\n" - refute_match %r%^rake failed:%, output - assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output - assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}%, output + refute_match %r{^rake failed:}, output + assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output + assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output end end @@ -39,31 +36,54 @@ def test_class_build_with_args output = [] build_rake_in do |rake| - Dir.chdir @ext do - non_empty_args_list = [''] - Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list - end + non_empty_args_list = [''] + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list, nil, @ext output = output.join "\n" - refute_match %r%^rake failed:%, output - assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output - assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}%, output + refute_match %r{^rake failed:}, output + assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output + assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output + end + end + + def test_class_no_openssl_override + pend 'openssl is missing' unless Gem::HAVE_OPENSSL + + create_temp_mkrf_file('task :default') + + rake = util_spec 'rake' do |s| + s.executables = %w[rake] + s.files = %w[bin/rake] + end + + output = [] + + write_file File.join(@tempdir, 'bin', 'rake') do |fp| + fp.puts "#!/usr/bin/ruby" + fp.puts "require 'openssl'; puts OpenSSL" end + + install_gem rake + + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [''], nil, @ext + + output = output.join "\n" + + assert_match "OpenSSL", output + assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output end def test_class_build_no_mkrf_passes_args output = [] build_rake_in do |rake| - Dir.chdir @ext do - Gem::Ext::RakeBuilder.build "ext/Rakefile", @dest_path, output, ["test1", "test2"] - end + Gem::Ext::RakeBuilder.build "ext/Rakefile", @dest_path, output, ["test1", "test2"], nil, @ext output = output.join "\n" - refute_match %r%^rake failed:%, output - assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2%, output + refute_match %r{^rake failed:}, output + assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2}, output end end @@ -72,13 +92,11 @@ def test_class_build_fail output = [] build_rake_in(false) do |rake| - error = assert_raises Gem::InstallError do - Dir.chdir @ext do - Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output - end + error = assert_raise Gem::InstallError do + Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [], nil, @ext end - assert_match %r%^rake failed%, error.message + assert_match %r{^rake failed}, error.message end end @@ -91,5 +109,4 @@ def create_temp_mkrf_file(rakefile_content) EO_MKRF end end - end diff --git a/ruby/test/rubygems/test_gem_gem_runner.rb b/ruby/test/rubygems/test_gem_gem_runner.rb index efde71dce..6f5361cf2 100644 --- a/ruby/test/rubygems/test_gem_gem_runner.rb +++ b/ruby/test/rubygems/test_gem_gem_runner.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemGemRunner < Gem::TestCase - def setup super require 'rubygems/command' @orig_args = Gem::Command.build_args + @orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup + @orig_extra_args = Gem::Command.extra_args.dup require 'rubygems/gem_runner' @runner = Gem::GemRunner.new @@ -17,6 +18,8 @@ def teardown super Gem::Command.build_args = @orig_args + Gem::Command.specific_extra_args_hash = @orig_specific_extra_args + Gem::Command.extra_args = @orig_extra_args end def test_do_configuration @@ -67,4 +70,44 @@ def test_extract_build_args assert_equal %w[--foo], args end + def test_query_is_deprecated + args = %w[query] + + use_ui @ui do + @runner.run(args) + end + + assert_match(/WARNING: query command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error) + assert_match(/WARNING: It is recommended that you use `gem search` or `gem list` instead/, @ui.error) + end + + def test_info_succeeds + args = %w[info] + + use_ui @ui do + @runner.run(args) + end + + assert_empty @ui.error + end + + def test_list_succeeds + args = %w[list] + + use_ui @ui do + @runner.run(args) + end + + assert_empty @ui.error + end + + def test_search_succeeds + args = %w[search] + + use_ui @ui do + @runner.run(args) + end + + assert_empty @ui.error + end end diff --git a/ruby/test/rubygems/test_gem_gemcutter_utilities.rb b/ruby/test/rubygems/test_gem_gemcutter_utilities.rb index 03bb78271..0bcd1504e 100644 --- a/ruby/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/ruby/test/rubygems/test_gem_gemcutter_utilities.rb @@ -1,17 +1,20 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' require 'rubygems/command' require 'rubygems/gemcutter_utilities' class TestGemGemcutterUtilities < Gem::TestCase - def setup super + + credential_setup + # below needed for random testing, class property Gem.configuration.disable_default_gem_server = nil ENV['RUBYGEMS_HOST'] = nil + ENV['GEM_HOST_OTP_CODE'] = nil Gem.configuration.rubygems_api_key = nil @cmd = Gem::Command.new '', 'summary' @@ -20,19 +23,20 @@ def setup def teardown ENV['RUBYGEMS_HOST'] = nil + ENV['GEM_HOST_OTP_CODE'] = nil Gem.configuration.rubygems_api_key = nil + credential_teardown + super end def test_alternate_key_alternate_host keys = { :rubygems_api_key => 'KEY', - "http://rubygems.engineyard.com" => "EYKEY" + "http://rubygems.engineyard.com" => "EYKEY", } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path - File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -46,7 +50,6 @@ def test_alternate_key_alternate_host def test_api_key keys = { :rubygems_api_key => 'KEY' } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml @@ -59,7 +62,6 @@ def test_api_key def test_api_key_override keys = { :rubygems_api_key => 'KEY', :other => 'OTHER' } - FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml @@ -97,7 +99,7 @@ def test_sign_in assert @fetcher.last_request["authorization"] assert_match %r{Signed in.}, @sign_in_ui.output - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] end @@ -111,7 +113,7 @@ def test_sign_in_with_host assert @fetcher.last_request["authorization"] assert_match %r{Signed in.}, @sign_in_ui.output - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials['http://example.com'] end @@ -125,7 +127,7 @@ def test_sign_in_with_host_nil assert @fetcher.last_request["authorization"] assert_match %r{Signed in.}, @sign_in_ui.output - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] end @@ -138,7 +140,7 @@ def test_sign_in_with_host_ENV assert @fetcher.last_request["authorization"] assert_match %r{Signed in.}, @sign_in_ui.output - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials['http://example.com'] end @@ -164,7 +166,6 @@ def test_sign_in_with_other_credentials_doesnt_overwrite_other_keys api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' other_api_key = 'f46dbb18bb6a9c97cdc61b5b85c186a17403cdcbf' - FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path) File.open Gem.configuration.credentials_path, 'w' do |f| f.write Hash[:other_api_key, other_api_key].to_yaml end @@ -173,13 +174,13 @@ def test_sign_in_with_other_credentials_doesnt_overwrite_other_keys assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output assert_match %r{Signed in.}, @sign_in_ui.output - credentials = YAML.load_file Gem.configuration.credentials_path + credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] assert_equal other_api_key, credentials[:other_api_key] end def test_sign_in_with_bad_credentials - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do util_sign_in ['Access Denied.', 403, 'Forbidden'] end @@ -187,6 +188,16 @@ def test_sign_in_with_bad_credentials assert_match %r{Access Denied.}, @sign_in_ui.output end + def test_signin_with_env_otp_code + ENV['GEM_HOST_OTP_CODE'] = '111111' + api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' + + util_sign_in [api_key, 200, 'OK'] + + assert_match 'Signed in with API key:', @sign_in_ui.output + assert_equal '111111', @fetcher.last_request['OTP'] + end + def test_sign_in_with_correct_otp_code api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." @@ -198,14 +209,14 @@ def test_sign_in_with_correct_otp_code assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @sign_in_ui.output assert_match 'Code: ', @sign_in_ui.output - assert_match 'Signed in.', @sign_in_ui.output + assert_match 'Signed in with API key:', @sign_in_ui.output assert_equal '111111', @fetcher.last_request['OTP'] end def test_sign_in_with_incorrect_otp_code response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do util_sign_in [response, 401, 'Unauthorized'], nil, [], "111111\n" end @@ -229,7 +240,7 @@ def util_sign_in(response, host = nil, args = [], extra_input = '') @fetcher.data["#{host}/api/v1/api_key"] = response Gem::RemoteFetcher.fetcher = @fetcher - @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n" + extra_input) + @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n" + extra_input) use_ui @sign_in_ui do if args.length > 0 @@ -242,7 +253,6 @@ def util_sign_in(response, host = nil, args = [], extra_input = '') def test_verify_api_key keys = {:other => 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'} - FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path) File.open Gem.configuration.credentials_path, 'w' do |f| f.write keys.to_yaml end @@ -253,9 +263,8 @@ def test_verify_api_key end def test_verify_missing_api_key - assert_raises Gem::MockGemUi::TermError do + assert_raise Gem::MockGemUi::TermError do @cmd.verify_api_key :missing end end - end diff --git a/ruby/test/rubygems/test_gem_impossible_dependencies_error.rb b/ruby/test/rubygems/test_gem_impossible_dependencies_error.rb index 8a0f8d619..971be151d 100644 --- a/ruby/test/rubygems/test_gem_impossible_dependencies_error.rb +++ b/ruby/test/rubygems/test_gem_impossible_dependencies_error.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemImpossibleDependenciesError < Gem::TestCase - def test_message_conflict request = dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8' @@ -57,5 +56,4 @@ def test_message_conflict assert_equal expected, error.message end - end diff --git a/ruby/test/rubygems/test_gem_indexer.rb b/ruby/test/rubygems/test_gem_indexer.rb index fdef33e46..6653f29ad 100644 --- a/ruby/test/rubygems/test_gem_indexer.rb +++ b/ruby/test/rubygems/test_gem_indexer.rb @@ -1,13 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/indexer' -unless defined?(Builder::XChar) - warn "Gem::Indexer tests are being skipped. Install builder gem." -end - class TestGemIndexer < Gem::TestCase - def setup super @@ -189,15 +184,15 @@ def test_generate_index_ui @indexer.generate_index end - assert_match %r%^\.\.\.\.\.\.\.\.\.\.\.\.$%, @ui.output - assert_match %r%^Generating Marshal quick index gemspecs for 12 gems$%, + assert_match %r{^\.\.\.\.\.\.\.\.\.\.\.\.$}, @ui.output + assert_match %r{^Generating Marshal quick index gemspecs for 12 gems$}, @ui.output - assert_match %r%^Complete$%, @ui.output - assert_match %r%^Generating specs index$%, @ui.output - assert_match %r%^Generating latest specs index$%, @ui.output - assert_match %r%^Generating prerelease specs index$%, @ui.output - assert_match %r%^Complete$%, @ui.output - assert_match %r%^Compressing indices$%, @ui.output + assert_match %r{^Complete$}, @ui.output + assert_match %r{^Generating specs index$}, @ui.output + assert_match %r{^Generating latest specs index$}, @ui.output + assert_match %r{^Generating prerelease specs index$}, @ui.output + assert_match %r{^Complete$}, @ui.output + assert_match %r{^Compressing indices$}, @ui.output assert_equal '', @ui.error end @@ -359,5 +354,4 @@ def refute_indexed(dir, name) file = File.join dir, name refute File.exist?(file), "#{file} exists" end - -end if defined?(Builder::XChar) +end diff --git a/ruby/test/rubygems/test_gem_install_update_options.rb b/ruby/test/rubygems/test_gem_install_update_options.rb index c6b477833..a499c2be3 100644 --- a/ruby/test/rubygems/test_gem_install_update_options.rb +++ b/ruby/test/rubygems/test_gem_install_update_options.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/installer_test_case' +require_relative 'installer_test_case' require 'rubygems/install_update_options' require 'rubygems/command' require 'rubygems/dependency_installer' class TestGemInstallUpdateOptions < Gem::InstallerTestCase - def setup super @@ -31,7 +30,7 @@ def test_add_install_update_options args.concat %w[--vendor] unless Gem.java_platform? - args.concat %w[-P HighSecurity] if defined?(OpenSSL::SSL) + args.concat %w[-P HighSecurity] if Gem::HAVE_OPENSSL assert @cmd.handles?(args) end @@ -93,7 +92,7 @@ def test_document_rdoc end def test_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @cmd.handle_options %w[-P HighSecurity] @@ -101,11 +100,11 @@ def test_security_policy end def test_security_policy_unknown - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @cmd.add_install_update_options - e = assert_raises OptionParser::InvalidArgument do + e = assert_raise Gem::OptionParser::InvalidArgument do @cmd.handle_options %w[-P UnknownSecurity] end assert_includes e.message, "UnknownSecurity" @@ -125,8 +124,8 @@ def test_user_install_enabled @installer = Gem::Installer.at @gem, @cmd.options @installer.install - assert_path_exists File.join(Gem.user_dir, 'gems') - assert_path_exists File.join(Gem.user_dir, 'gems', @spec.full_name) + assert_path_exist File.join(Gem.user_dir, 'gems') + assert_path_exist File.join(Gem.user_dir, 'gems', @spec.full_name) end def test_user_install_disabled_read_only @@ -138,9 +137,9 @@ def test_user_install_disabled_read_only @gem = @spec.cache_file if win_platform? - skip('test_user_install_disabled_read_only test skipped on MS Windows') + pend('test_user_install_disabled_read_only test skipped on MS Windows') elsif Process.uid.zero? - skip('test_user_install_disabled_read_only test skipped in root privilege') + pend('test_user_install_disabled_read_only test skipped in root privilege') else @cmd.handle_options %w[--no-user-install] @@ -151,7 +150,7 @@ def test_user_install_disabled_read_only Gem.use_paths @gemhome, @userhome - assert_raises(Gem::FilePermissionError) do + assert_raise(Gem::FilePermissionError) do Gem::Installer.at(@gem, @cmd.options).install end end @@ -170,7 +169,7 @@ def test_vendor def test_vendor_missing vendordir(nil) do - e = assert_raises OptionParser::InvalidOption do + e = assert_raise Gem::OptionParser::InvalidOption do @cmd.handle_options %w[--vendor] end @@ -194,4 +193,15 @@ def test_post_install_message assert_equal true, @cmd.options[:post_install_message] end + def test_minimal_deps_no + @cmd.handle_options %w[--no-minimal-deps] + + assert_equal false, @cmd.options[:minimal_deps] + end + + def test_minimal_deps + @cmd.handle_options %w[--minimal-deps] + + assert_equal true, @cmd.options[:minimal_deps] + end end diff --git a/ruby/test/rubygems/test_gem_installer.rb b/ruby/test/rubygems/test_gem_installer.rb index 731a1ac01..c90fdab28 100644 --- a/ruby/test/rubygems/test_gem_installer.rb +++ b/ruby/test/rubygems/test_gem_installer.rb @@ -1,26 +1,7 @@ # frozen_string_literal: true -require 'rubygems/installer_test_case' +require_relative 'installer_test_case' class TestGemInstaller < Gem::InstallerTestCase - - @@symlink_supported = nil - - # Our CI does not currently hit the "symlink not supported" case, but this is - # needed for Windows developers without symlink support enabled (the default - # for non admin) to be able to run the tests successfully - def symlink_supported? - if @@symlink_supported.nil? - begin - File.symlink("", "") - rescue Errno::ENOENT, Errno::EEXIST - @@symlink_supported = true - rescue NotImplementedError, SystemCallError - @@symlink_supported = false - end - end - @@symlink_supported - end - def setup super common_installer_setup @@ -37,11 +18,12 @@ def teardown end def test_app_script_text - installer = setup_base_installer + load_relative "no" do + installer = setup_base_installer - util_make_exec @spec, '' + util_make_exec @spec, '' - expected = <<-EOF + expected = <<-EOF #!#{Gem.ruby} # # This file was generated by RubyGems. @@ -52,6 +34,8 @@ def test_app_script_text require 'rubygems' +Gem.use_gemdeps + version = \">= 0.a\" str = ARGV.first @@ -69,10 +53,11 @@ def test_app_script_text gem "a", version load Gem.bin_path("a", "executable", version) end - EOF + EOF - wrapper = installer.app_script_text 'executable' - assert_equal expected, wrapper + wrapper = installer.app_script_text 'executable' + assert_equal expected, wrapper + end end def test_check_executable_overwrite @@ -95,26 +80,26 @@ def test_check_executable_overwrite installer.generate_bin installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_check_executable_overwrite_default_bin_dir - installer = setup_base_installer + installer = setup_base_installer(false) bindir(Gem.bindir) do util_conflict_executable false ui = Gem::MockGemUi.new "n\n" use_ui ui do - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.generate_bin end conflicted = File.join @gemhome, 'bin', 'executable' - assert_match %r%\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z%, + assert_match %r{\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z}, e.message end end @@ -153,23 +138,23 @@ def test_check_executable_overwrite_format_executable installer.generate_bin # should not raise installed_exec = File.join util_inst_bindir, 'foo-executable-bar' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper ensure Gem::Installer.exec_format = nil end def test_check_executable_overwrite_other_gem - installer = setup_base_installer + installer = setup_base_installer(false) util_conflict_executable true ui = Gem::MockGemUi.new "n\n" use_ui ui do - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.generate_bin end @@ -188,10 +173,10 @@ def test_check_executable_overwrite_other_gem_force installer.generate_bin installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_check_executable_overwrite_other_non_gem @@ -203,10 +188,10 @@ def test_check_executable_overwrite_other_non_gem installer.generate_bin installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end unless Gem.win_platform? def test_check_that_user_bin_dir_is_in_path @@ -215,7 +200,7 @@ def test_check_that_user_bin_dir_is_in_path bin_dir = installer.bin_dir if Gem.win_platform? - bin_dir = bin_dir.downcase.gsub(File::SEPARATOR, File::ALT_SEPARATOR) + bin_dir = bin_dir.downcase end orig_PATH, ENV['PATH'] = @@ -226,12 +211,22 @@ def test_check_that_user_bin_dir_is_in_path end assert_empty @ui.error + + return unless win_platform? + + ENV['PATH'] = [orig_PATH, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR) + + use_ui @ui do + installer.check_that_user_bin_dir_is_in_path + end + + assert_empty @ui.error ensure ENV['PATH'] = orig_PATH end def test_check_that_user_bin_dir_is_in_path_tilde - skip "Tilde is PATH is not supported under MS Windows" if win_platform? + pend "Tilde is PATH is not supported under MS Windows" if win_platform? orig_PATH, ENV['PATH'] = ENV['PATH'], [ENV['PATH'], '~/bin'].join(File::PATH_SEPARATOR) @@ -258,7 +253,7 @@ def test_check_that_user_bin_dir_is_in_path_not_in_path expected = installer.bin_dir if Gem.win_platform? - expected = expected.downcase.gsub(File::SEPARATOR, File::ALT_SEPARATOR) + expected = expected.downcase end assert_match expected, @ui.error @@ -273,7 +268,7 @@ def test_ensure_dependency assert installer.ensure_dependency(@spec, dep) dep = Gem::Dependency.new 'b', '> 2' - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.ensure_dependency @spec, dep end @@ -287,7 +282,7 @@ def test_ensure_loadable_spec installer = Gem::Installer.at a_gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.ensure_loadable_spec end @@ -296,7 +291,7 @@ def test_ensure_loadable_spec end def test_ensure_loadable_spec_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL _, a_gem = util_gem 'a', 2 do |s| s.add_dependency 'garbage ~> 5' @@ -305,7 +300,7 @@ def test_ensure_loadable_spec_security_policy policy = Gem::Security::HighSecurity installer = Gem::Installer.at a_gem, :security_policy => policy - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do installer.ensure_loadable_spec end end @@ -315,7 +310,7 @@ def test_extract_files installer.extract_files - assert_path_exists File.join @spec.gem_dir, 'bin/executable' + assert_path_exist File.join @spec.gem_dir, 'bin/executable' end def test_generate_bin_bindir @@ -338,11 +333,11 @@ def test_generate_bin_bindir assert_directory_exists util_inst_bindir installed_exec = File.join(util_inst_bindir, 'executable') - assert_path_exists installed_exec + assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless win_platform? wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_generate_bin_bindir_with_user_install_warning @@ -354,7 +349,7 @@ def test_generate_bin_bindir_with_user_install_warning options = { :bin_dir => bin_dir, - :install_dir => "/non/existent" + :install_dir => "/non/existent", } inst = Gem::Installer.at '', options @@ -381,11 +376,11 @@ def test_generate_bin_script installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless win_platform? wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_generate_bin_script_format @@ -400,7 +395,7 @@ def test_generate_bin_script_format installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, 'foo-executable-bar' - assert_path_exists installed_exec + assert_path_exist installed_exec ensure Gem::Installer.exec_format = nil end @@ -416,7 +411,7 @@ def test_generate_bin_script_format_disabled installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec ensure Gem::Installer.exec_format = nil end @@ -440,11 +435,11 @@ def test_generate_bin_script_install_dir installer.generate_bin installed_exec = File.join("#{@gemhome}2", "bin", 'executable') - assert_path_exists installed_exec + assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless win_platform? wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_generate_bin_script_no_execs @@ -455,7 +450,7 @@ def test_generate_bin_script_no_execs installer.wrappers = true installer.generate_bin - refute_path_exists util_inst_bindir, 'bin dir was created when not needed' + assert_path_not_exist util_inst_bindir, 'bin dir was created when not needed' end def test_generate_bin_script_no_perms @@ -467,13 +462,13 @@ def test_generate_bin_script_no_perms Dir.mkdir util_inst_bindir if win_platform? - skip('test_generate_bin_script_no_perms skipped on MS Windows') + pend('test_generate_bin_script_no_perms skipped on MS Windows') elsif Process.uid.zero? - skip('test_generate_bin_script_no_perms skipped in root privilege') + pend('test_generate_bin_script_no_perms skipped in root privilege') else FileUtils.chmod 0000, util_inst_bindir - assert_raises Gem::FilePermissionError do + assert_raise Gem::FilePermissionError do installer.generate_bin end end @@ -497,11 +492,11 @@ def test_generate_bin_script_no_shebang installer.generate_bin installed_exec = File.join @gemhome, 'bin', 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless win_platform? wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper # HACK some gems don't have #! in their executables, restore 2008/06 #assert_no_match %r|generated by RubyGems|, wrapper end @@ -524,17 +519,17 @@ def test_generate_bin_script_wrappers installer.generate_bin assert_directory_exists util_inst_bindir - assert_path_exists installed_exec + assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless win_platform? - assert_match %r|generated by RubyGems|, File.read(installed_exec) + assert_match %r{generated by RubyGems}, File.read(installed_exec) - refute_match %r|generated by RubyGems|, File.read(real_exec), + refute_match %r{generated by RubyGems}, File.read(real_exec), 'real executable overwritten' end def test_generate_bin_symlink - skip "Symlinks not supported or not enabled" unless symlink_supported? + pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer @@ -558,7 +553,7 @@ def test_generate_bin_symlink_no_execs installer.wrappers = false installer.generate_bin - refute_path_exists util_inst_bindir + assert_path_not_exist util_inst_bindir end def test_generate_bin_symlink_no_perms @@ -571,13 +566,13 @@ def test_generate_bin_symlink_no_perms Dir.mkdir util_inst_bindir if win_platform? - skip('test_generate_bin_symlink_no_perms skipped on MS Windows') + pend('test_generate_bin_symlink_no_perms skipped on MS Windows') elsif Process.uid.zero? - skip('test_user_install_disabled_read_only test skipped in root privilege') + pend('test_user_install_disabled_read_only test skipped in root privilege') else FileUtils.chmod 0000, util_inst_bindir - assert_raises Gem::FilePermissionError do + assert_raise Gem::FilePermissionError do installer.generate_bin end end @@ -586,7 +581,7 @@ def test_generate_bin_symlink_no_perms end def test_generate_bin_symlink_update_newer - skip "Symlinks not supported or not enabled" unless symlink_supported? + pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer @@ -618,7 +613,7 @@ def test_generate_bin_symlink_update_newer end def test_generate_bin_symlink_update_older - skip "Symlinks not supported or not enabled" unless symlink_supported? + pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer @@ -656,7 +651,7 @@ def test_generate_bin_symlink_update_older end def test_generate_bin_symlink_update_remove_wrapper - skip "Symlinks not supported or not enabled" unless symlink_supported? + pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer @@ -667,7 +662,7 @@ def test_generate_bin_symlink_update_remove_wrapper installer.generate_bin installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec @spec = Gem::Specification.new do |s| s.files = ['lib/code.rb'] @@ -710,7 +705,7 @@ def test_generate_bin_symlink_win32 assert_directory_exists util_inst_bindir installed_exec = File.join(util_inst_bindir, 'executable') - assert_path_exists installed_exec + assert_path_exist installed_exec if symlink_supported? assert File.symlink?(installed_exec) @@ -729,19 +724,183 @@ def test_generate_bin_symlink_win32 end def test_generate_bin_uses_default_shebang - skip "Symlinks not supported or not enabled" unless symlink_supported? + pend "Symlinks not supported or not enabled" unless symlink_supported? - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - installer.wrappers = true - util_make_exec + installer.wrappers = true + util_make_exec - installer.generate_bin + installer.generate_bin + + default_shebang = Gem.ruby + shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first } + assert_match(/\A#!/, shebang_line) + assert_match(/#{default_shebang}/, shebang_line) + end + end + + def test_generate_bin_with_dangling_symlink + gem_with_dangling_symlink = File.expand_path("packages/ascii_binder-0.1.10.1.gem", __dir__) + + installer = Gem::Installer.at( + gem_with_dangling_symlink, + :user_install => false, + :force => true + ) + + build_rake_in do + use_ui @ui do + installer.install + end + end + + assert_match %r{bin/ascii_binder` is dangling symlink pointing to `bin/asciibinder`}, @ui.error + assert_empty @ui.output + end - default_shebang = Gem.ruby - shebang_line = open("#{@gemhome}/bin/executable") { |f| f.readlines.first } - assert_match(/\A#!/, shebang_line) - assert_match(/#{default_shebang}/, shebang_line) + def test_generate_plugins + installer = util_setup_installer do |spec| + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + spec.files += %w[lib/rubygems_plugin.rb] + end + + build_rake_in do + installer.install + end + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + + FileUtils.rm plugin_path + + installer.generate_plugins + + assert File.exist?(plugin_path), 'plugin not written' + end + + def test_generate_plugins_with_install_dir + spec = quick_gem 'a' do |s| + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + s.files += %w[lib/rubygems_plugin.rb] + end + + util_build_gem spec + + plugin_path = File.join "#{@gemhome}2", 'plugins', 'a_plugin.rb' + installer = util_installer spec, "#{@gemhome}2" + + assert_equal spec, installer.install + + assert File.exist?(plugin_path), 'plugin not written to install_dir' + end + + def test_generate_plugins_with_user_install + spec = quick_gem 'a' do |s| + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + s.files += %w[lib/rubygems_plugin.rb] + end + + util_build_gem spec + + File.chmod(0555, Gem.plugindir) + system_path = File.join(Gem.plugindir, 'a_plugin.rb') + user_path = File.join(Gem.plugindir(Gem.user_dir), 'a_plugin.rb') + installer = util_installer spec, Gem.dir, :user + + assert_equal spec, installer.install + + assert !File.exist?(system_path), 'plugin incorrectly written to system plugins_dir' + assert File.exist?(user_path), 'plugin not written to user plugins_dir' + end + + def test_generate_plugins_with_build_root + spec = quick_gem 'a' do |s| + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + s.files += %w[lib/rubygems_plugin.rb] + end + + util_build_gem spec + + File.chmod(0555, Gem.plugindir) + system_path = File.join(Gem.plugindir, 'a_plugin.rb') + + build_root = File.join(@tempdir, 'build_root') + build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ''), 'a_plugin.rb') + + installer = Gem::Installer.at spec.cache_file, :build_root => build_root + + assert_equal spec, installer.install + + assert !File.exist?(system_path), 'plugin written incorrect written to system plugins_dir' + assert File.exist?(build_root_path), 'plugin not written to build_root' + + refute_includes File.read(build_root_path), build_root + end + + def test_keeps_plugins_up_to_date + # NOTE: version a-2 is already installed by setup hooks + + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + build_rake_in do + util_setup_installer do |spec| + spec.version = '1' + spec.files += %w[lib/rubygems_plugin.rb] + end.install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + refute File.exist?(plugin_path), 'old version installed while newer version without plugin also installed, but plugin written' + + util_setup_installer do |spec| + spec.version = '2' + spec.files += %w[lib/rubygems_plugin.rb] + end.install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + assert File.exist?(plugin_path), 'latest version reinstalled, but plugin not written' + assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content' + + util_setup_installer do |spec| + spec.version = '3' + spec.files += %w[lib/rubygems_plugin.rb] + end.install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + assert File.exist?(plugin_path), 'latest version installed, but plugin removed' + assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content' + + util_setup_installer do |spec| + spec.version = '4' + end.install + + refute File.exist?(plugin_path), 'new version installed without a plugin while older version with a plugin installed, but plugin not removed' + end + end + + def test_generates_plugins_dir_under_install_dir_if_not_there + Gem.use_paths "#{@gemhome}2" # Set GEM_HOME to an uninitialized repo + + @spec = util_spec 'a' + + path = Gem::Package.build @spec + + installer = Gem::Installer.at path, :install_dir => "#{@gemhome}3" + assert_equal @spec, installer.install end def test_initialize @@ -792,22 +951,19 @@ def test_install spec_file = File.join @gemhome, 'specifications', @spec.spec_name Gem.pre_install do - refute_path_exists cache_file, 'cache file must not exist yet' - refute_path_exists spec_file, 'spec file must not exist yet' + assert_path_not_exist cache_file, 'cache file must not exist yet' true end Gem.post_build do - assert_path_exists gemdir, 'gem install dir must exist' - assert_path_exists rakefile, 'gem executable must exist' - refute_path_exists stub_exe, 'gem executable must not exist' - refute_path_exists spec_file, 'spec file must not exist yet' + assert_path_exist gemdir, 'gem install dir must exist' + assert_path_exist rakefile, 'gem executable must exist' + assert_path_not_exist stub_exe, 'gem executable must not exist' true end Gem.post_install do - assert_path_exists cache_file, 'cache file must exist' - assert_path_exists spec_file, 'spec file must exist' + assert_path_exist cache_file, 'cache file must exist' end @newspec = nil @@ -818,21 +974,21 @@ def test_install end assert_equal @spec, @newspec - assert_path_exists gemdir - assert_path_exists stub_exe, 'gem executable must exist' + assert_path_exist gemdir + assert_path_exist stub_exe, 'gem executable must exist' exe = File.join gemdir, 'bin', 'executable' - assert_path_exists exe + assert_path_exist exe exe_mode = File.stat(exe).mode & 0111 assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform? - assert_path_exists File.join gemdir, 'lib', 'code.rb' + assert_path_exist File.join gemdir, 'lib', 'code.rb' - assert_path_exists rakefile + assert_path_exist rakefile assert_equal spec_file, @newspec.loaded_from - assert_path_exists spec_file + assert_path_exist spec_file assert_same installer, @post_build_hook_arg assert_same installer, @post_install_hook_arg @@ -855,7 +1011,7 @@ def test_install_creates_working_binstub exe = File.join gemdir, 'bin', 'executable' - e = assert_raises RuntimeError do + e = assert_raise RuntimeError do instance_eval File.read(exe) end @@ -901,7 +1057,7 @@ def test_conflicting_binstubs end end - e = assert_raises RuntimeError do + e = assert_raise RuntimeError do instance_eval File.read(old_bin_file) end @@ -929,7 +1085,7 @@ def test_install_creates_binstub_that_understand_version begin Gem::Specification.reset - e = assert_raises Gem::GemNotFoundException do + e = assert_raise Gem::GemNotFoundException do instance_eval File.read(exe) end ensure @@ -940,7 +1096,13 @@ def test_install_creates_binstub_that_understand_version end def test_install_creates_binstub_that_prefers_user_installed_gem_to_default - install_default_gems new_default_spec('default', '2') + default_spec = new_default_spec('default', '2', nil, 'exe/executable') + default_spec.executables = 'executable' + install_default_gems default_spec + + exe = File.join @gemhome, 'bin', 'executable' + + assert_path_exist exe, "default gem's executable not installed" installer = util_setup_installer do |spec| spec.name = 'default' @@ -958,9 +1120,7 @@ def test_install_creates_binstub_that_prefers_user_installed_gem_to_default end end - exe = File.join @gemhome, 'bin', 'executable' - - e = assert_raises RuntimeError do + e = assert_raise RuntimeError do instance_eval File.read(exe) end @@ -987,7 +1147,7 @@ def test_install_creates_binstub_that_dont_trust_encoding begin Gem::Specification.reset - e = assert_raises RuntimeError do + e = assert_raise RuntimeError do instance_eval File.read(exe) end ensure @@ -1007,7 +1167,7 @@ def test_install_with_no_prior_files end gemdir = File.join(@gemhome, 'gems', @spec.full_name) - assert_path_exists File.join gemdir, 'lib', 'code.rb' + assert_path_exist File.join gemdir, 'lib', 'code.rb' installer = util_setup_installer @@ -1023,26 +1183,39 @@ def test_install_with_no_prior_files Gem::Package.build @spec end end - installer = Gem::Installer.at @gem + installer = Gem::Installer.at @gem, :force => true build_rake_in do use_ui @ui do assert_equal @spec, installer.install end end - assert_path_exists File.join gemdir, 'lib', 'other.rb' - refute_path_exists File.join gemdir, 'lib', 'code.rb', + assert_path_exist File.join gemdir, 'lib', 'other.rb' + assert_path_not_exist File.join gemdir, 'lib', 'code.rb', "code.rb from prior install of same gem shouldn't remain here" end def test_install_force + _, missing_dep_gem = util_gem 'missing_dep', '1' do |s| + s.add_dependency 'doesnt_exist', '1' + end + use_ui @ui do - installer = Gem::Installer.at old_ruby_required('= 1.4.6'), :force => true + installer = Gem::Installer.at missing_dep_gem, :force => true installer.install end - gem_dir = File.join(@gemhome, 'gems', 'old_ruby_required-1') - assert_path_exists gem_dir + gem_dir = File.join(@gemhome, 'gems', 'missing_dep-1') + assert_path_exist gem_dir + end + + def test_install_build_root + build_root = File.join(@tempdir, 'build_root') + + @gem = setup_base_gem + installer = Gem::Installer.at @gem, :build_root => build_root + + assert_equal @spec, installer.install end def test_install_missing_dirs @@ -1060,19 +1233,23 @@ def test_install_missing_dirs assert_directory_exists File.join(Gem.dir, 'doc') assert_directory_exists File.join(Gem.dir, 'specifications') - assert_path_exists File.join @gemhome, 'cache', @spec.file_name - assert_path_exists File.join @gemhome, 'specifications', @spec.spec_name + assert_path_exist File.join @gemhome, 'cache', @spec.file_name + assert_path_exist File.join @gemhome, 'specifications', @spec.spec_name end def test_install_post_build_false - installer = setup_base_installer + @spec = util_spec 'a' + + util_build_gem @spec + + installer = util_installer @spec, @gemhome Gem.post_build do false end use_ui @ui do - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.install end @@ -1082,10 +1259,10 @@ def test_install_post_build_false end spec_file = File.join @gemhome, 'specifications', @spec.spec_name - refute_path_exists spec_file + assert_path_not_exist spec_file gem_dir = File.join @gemhome, 'gems', @spec.full_name - refute_path_exists gem_dir + assert_path_not_exist gem_dir end def test_install_post_build_nil @@ -1100,21 +1277,25 @@ def test_install_post_build_nil end spec_file = File.join @gemhome, 'specifications', @spec.spec_name - assert_path_exists spec_file + assert_path_exist spec_file gem_dir = File.join @gemhome, 'gems', @spec.full_name - assert_path_exists gem_dir + assert_path_exist gem_dir end def test_install_pre_install_false - installer = setup_base_installer + @spec = util_spec 'a' + + util_build_gem @spec + + installer = util_installer @spec, @gemhome Gem.pre_install do false end use_ui @ui do - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.install end @@ -1124,7 +1305,7 @@ def test_install_pre_install_false end spec_file = File.join @gemhome, 'specifications', @spec.spec_name - refute_path_exists spec_file + assert_path_not_exist spec_file end def test_install_pre_install_nil @@ -1139,7 +1320,7 @@ def test_install_pre_install_nil end spec_file = File.join @gemhome, 'specifications', @spec.spec_name - assert_path_exists spec_file + assert_path_exist spec_file end def test_install_with_message @@ -1153,7 +1334,7 @@ def test_install_with_message installer.install end - assert_match %r|I am a shiny gem!|, @ui.output + assert_match %r{I am a shiny gem!}, @ui.output end def test_install_with_skipped_message @@ -1167,7 +1348,7 @@ def test_install_with_skipped_message installer.install end - refute_match %r|I am a shiny gem!|, @ui.output + refute_match %r{I am a shiny gem!}, @ui.output end def test_install_extension_dir @@ -1193,7 +1374,7 @@ def test_install_extension_dir expected_makefile = File.join gemhome2, 'gems', @spec.full_name, 'Makefile' - assert_path_exists expected_makefile + assert_path_exist expected_makefile end def test_install_extension_dir_is_removed_on_reinstall @@ -1222,15 +1403,15 @@ def test_install_extension_dir_is_removed_on_reinstall write_file should_be_removed do |io| io.write "DELETE ME ON REINSTALL" end - assert_path_exists should_be_removed + assert_path_exist should_be_removed # reinstall the gem, this is also the same as pristine use_ui @ui do - installer = Gem::Installer.at path + installer = Gem::Installer.at path, :force => true installer.install end - refute_path_exists should_be_removed + assert_path_not_exist should_be_removed end def test_install_user_extension_dir @@ -1258,13 +1439,13 @@ def test_install_user_extension_dir expected_makefile = File.join Gem.user_dir, 'gems', @spec.full_name, 'Makefile' - assert_path_exists expected_makefile - assert_path_exists expected_extension_dir - refute_path_exists File.join expected_extension_dir, 'gem_make.out' + assert_path_exist expected_makefile + assert_path_exist expected_extension_dir + assert_path_not_exist File.join expected_extension_dir, 'gem_make.out' end def test_find_lib_file_after_install - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? @spec = setup_base_spec @spec.extensions << "extconf.rb" @@ -1303,14 +1484,15 @@ def test_find_lib_file_after_install installer.install end - expected = File.join @spec.full_require_paths.find { |path| + expected = File.join @spec.full_require_paths.find {|path| File.exist? File.join path, 'b.rb' }, 'b.rb' assert_equal expected, @spec.matches_for_glob('b.rb').first end def test_install_extension_and_script - skip "Makefile creation crashes on jruby" if Gem.java_platform? + pend "Makefile creation crashes on jruby" if Gem.java_platform? + pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning @spec = setup_base_spec @spec.extensions << "extconf.rb" @@ -1338,65 +1520,67 @@ def test_install_extension_and_script RUBY end - refute_path_exists File.join @spec.gem_dir, rb - refute_path_exists File.join @spec.gem_dir, rb2 + assert_path_not_exist File.join @spec.gem_dir, rb + assert_path_not_exist File.join @spec.gem_dir, rb2 use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end - assert_path_exists File.join @spec.gem_dir, rb - assert_path_exists File.join @spec.gem_dir, rb2 + assert_path_exist File.join @spec.gem_dir, rb + assert_path_exist File.join @spec.gem_dir, rb2 end def test_install_extension_flat - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? - @spec = setup_base_spec - @spec.require_paths = ["."] + begin + @spec = setup_base_spec + @spec.require_paths = ["."] - @spec.extensions << "extconf.rb" + @spec.extensions << "extconf.rb" - write_file File.join(@tempdir, "extconf.rb") do |io| - io.write <<-RUBY - require "mkmf" + write_file File.join(@tempdir, "extconf.rb") do |io| + io.write <<-RUBY + require "mkmf" - CONFIG['CC'] = '$(TOUCH) $@ ||' - CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' - $ruby = '#{Gem.ruby}' + CONFIG['CC'] = '$(TOUCH) $@ ||' + CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' + $ruby = '#{Gem.ruby}' - create_makefile("#{@spec.name}") - RUBY - end + create_makefile("#{@spec.name}") + RUBY + end - # empty depend file for no auto dependencies - @spec.files += %W"depend #{@spec.name}.c".each do |file| - write_file File.join(@tempdir, file) - end + # empty depend file for no auto dependencies + @spec.files += %W[depend #{@spec.name}.c].each do |file| + write_file File.join(@tempdir, file) + end - so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}") - refute_path_exists so - use_ui @ui do - path = Gem::Package.build @spec + so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}") + assert_path_not_exist so + use_ui @ui do + path = Gem::Package.build @spec - installer = Gem::Installer.at path - installer.install - end - assert_path_exists so - rescue - puts '-' * 78 - puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile') - puts '-' * 78 + installer = Gem::Installer.at path + installer.install + end + assert_path_exist so + rescue + puts '-' * 78 + puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile') + puts '-' * 78 - path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out') + path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out') - if File.exist?(path) - puts File.read(path) - puts '-' * 78 - end + if File.exist?(path) + puts File.read(path) + puts '-' * 78 + end - raise + raise + end end def test_installation_satisfies_dependency_eh @@ -1426,9 +1610,10 @@ def test_pre_install_checks_dependencies installer = setup_base_installer @spec.add_dependency 'b', '> 5' installer = util_setup_gem + installer.force = false use_ui @ui do - assert_raises Gem::InstallError do + assert_raise Gem::InstallError do installer.install end end @@ -1474,54 +1659,6 @@ def test_pre_install_checks_dependencies_install_dir end end - def test_pre_install_checks_ruby_version - use_ui @ui do - installer = Gem::Installer.at old_ruby_required('= 1.4.6') - e = assert_raises Gem::RuntimeRequirementNotMetError do - installer.pre_install_checks - end - rv = Gem.ruby_version - assert_equal "old_ruby_required requires Ruby version = 1.4.6. The current ruby version is #{rv}.", - e.message - end - end - - def test_pre_install_checks_ruby_version_with_prereleases - util_set_RUBY_VERSION '2.6.0', -1, '63539', 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' - - installer = Gem::Installer.at old_ruby_required('>= 2.6.0.preview2') - assert installer.pre_install_checks - - installer = Gem::Installer.at old_ruby_required('> 2.6.0.preview2') - e = assert_raises Gem::RuntimeRequirementNotMetError do - assert installer.pre_install_checks - end - assert_equal "old_ruby_required requires Ruby version > 2.6.0.preview2. The current ruby version is 2.6.0.preview2.", - e.message - ensure - util_restore_RUBY_VERSION - end - - def test_pre_install_checks_wrong_rubygems_version - spec = util_spec 'old_rubygems_required', '1' do |s| - s.required_rubygems_version = '< 0' - end - - util_build_gem spec - - gem = File.join(@gemhome, 'cache', spec.file_name) - - use_ui @ui do - installer = Gem::Installer.at gem - e = assert_raises Gem::RuntimeRequirementNotMetError do - installer.pre_install_checks - end - rgv = Gem::VERSION - assert_equal "old_rubygems_required requires RubyGems version < 0. The current RubyGems version is #{rgv}. " + - "Try 'gem update --system' to update RubyGems itself.", e.message - end - end - def test_pre_install_checks_malicious_name spec = util_spec '../malicious', '1' def spec.full_name # so the spec is buildable @@ -1535,7 +1672,7 @@ def spec.validate(packaging, strict); end use_ui @ui do installer = Gem::Installer.at gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal '# has an invalid name', e.message @@ -1555,7 +1692,7 @@ def spec.validate(*args); end use_ui @ui do installer = Gem::Installer.at gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid name", e.message @@ -1577,7 +1714,7 @@ def spec.validate(*args); end use_ui @ui do installer = Gem::Installer.at gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid require_paths", e.message @@ -1585,7 +1722,7 @@ def spec.validate(*args); end end def test_pre_install_checks_malicious_extensions_before_eval - skip "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform? + pend "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform? spec = util_spec "malicious", '1' def spec.full_name # so the spec is buildable @@ -1600,7 +1737,7 @@ def spec.validate(*args); end use_ui @ui do installer = Gem::Installer.at gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid extensions", e.message @@ -1621,7 +1758,7 @@ def spec.validate(*args); end use_ui @ui do installer = Gem::Installer.at gem - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid specification_version", e.message @@ -1643,21 +1780,43 @@ def spec.validate(*args); end use_ui @ui do installer = Gem::Installer.at gem installer.ignore_dependencies = true - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid dependencies", e.message end end + def test_pre_install_checks_malicious_platform_before_eval + gem_with_ill_formated_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__) + + installer = Gem::Installer.at( + gem_with_ill_formated_platform, + :install_dir => @gem_home, + :user_install => false, + :force => true + ) + + use_ui @ui do + e = assert_raise Gem::InstallError do + installer.pre_install_checks + end + + assert_equal "x86-mswin32\n system('id > /tmp/nyangawa')# is an invalid platform", e.message + assert_empty @ui.output + end + end + def test_shebang - installer = setup_base_installer + load_relative "no" do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/ruby" + util_make_exec @spec, "#!/usr/bin/ruby" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + assert_equal "#!#{Gem.ruby}", shebang + end end def test_process_options @@ -1670,52 +1829,101 @@ def test_process_options def test_process_options_build_root build_root = File.join @tempdir, 'build_root' + bin_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'bin') + gem_home = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, '')) + plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'plugins') @gem = setup_base_gem - installer = Gem::Installer.at @gem, :build_root => build_root + installer = use_ui(@ui) { Gem::Installer.at @gem, :build_root => build_root } + + assert_equal build_root, installer.build_root + assert_equal bin_dir, installer.bin_dir + assert_equal gem_home, installer.gem_home - assert_equal Pathname(build_root), installer.build_root - assert_equal File.join(build_root, @gemhome, 'bin'), installer.bin_dir - assert_equal File.join(build_root, @gemhome), installer.gem_home + errors = @ui.error.split("\n") + + assert_equal "WARNING: You build with buildroot.", errors.shift + assert_equal " Build root: #{build_root}", errors.shift + assert_equal " Bin dir: #{bin_dir}", errors.shift + assert_equal " Gem home: #{gem_home}", errors.shift + assert_equal " Plugins dir: #{plugins_dir}", errors.shift end def test_shebang_arguments - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/ruby -ws" + util_make_exec @spec, "#!/usr/bin/ruby -ws" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + end + + def test_shebang_arguments_with_load_relative + load_relative 'yes' do + installer = setup_base_installer + + util_make_exec @spec, "#!/usr/bin/ruby -ws" + + shebang = installer.shebang 'executable' + + shebang_lines = shebang.split "\n" - assert_equal "#!#{Gem.ruby} -ws", shebang + assert_equal "#!/bin/sh", shebang_lines.shift + assert_includes shebang_lines, "#!#{Gem.ruby} -ws" + end end def test_shebang_empty - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, '' + util_make_exec @spec, '' - shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + shebang = installer.shebang 'executable' + assert_equal "#!#{Gem.ruby}", shebang + end end def test_shebang_env - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/env ruby" + util_make_exec @spec, "#!/usr/bin/env ruby" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + assert_equal "#!#{Gem.ruby}", shebang + end end def test_shebang_env_arguments - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/env ruby -ws" + util_make_exec @spec, "#!/usr/bin/env ruby -ws" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + end - assert_equal "#!#{Gem.ruby} -ws", shebang + def test_shebang_env_arguments_with_load_relative + load_relative 'yes' do + installer = setup_base_installer + + util_make_exec @spec, "#!/usr/bin/env ruby -ws" + + shebang = installer.shebang 'executable' + + shebang_lines = shebang.split "\n" + + assert_equal "#!/bin/sh", shebang_lines.shift + assert_includes shebang_lines, "#!#{Gem.ruby} -ws" + end end def test_shebang_env_shebang @@ -1726,70 +1934,127 @@ def test_shebang_env_shebang shebang = installer.shebang 'executable' - env_shebang = "/usr/bin/env" unless Gem.win_platform? + bin_env = get_bin_env - assert_equal("#!#{env_shebang} #{RbConfig::CONFIG['ruby_install_name']}", + assert_equal("#!#{bin_env} #{RbConfig::CONFIG['ruby_install_name']}", shebang) end def test_shebang_nested - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/opt/local/ruby/bin/ruby" + util_make_exec @spec, "#!/opt/local/ruby/bin/ruby" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + assert_equal "#!#{Gem.ruby}", shebang + end end def test_shebang_nested_arguments - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws" + util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby} -ws", shebang + assert_equal "#!#{Gem.ruby} -ws", shebang + end + end + + def test_shebang_nested_arguments_with_load_relative + load_relative 'yes' do + installer = setup_base_installer + + util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws" + + shebang = installer.shebang 'executable' + + shebang_lines = shebang.split "\n" + + assert_equal "#!/bin/sh", shebang_lines.shift + assert_includes shebang_lines, "#!#{Gem.ruby} -ws" + end end def test_shebang_version - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/ruby18" + util_make_exec @spec, "#!/usr/bin/ruby18" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + assert_equal "#!#{Gem.ruby}", shebang + end end def test_shebang_version_arguments - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/ruby18 -ws" + util_make_exec @spec, "#!/usr/bin/ruby18 -ws" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + end + + def test_shebang_version_arguments_with_load_relative + load_relative 'yes' do + installer = setup_base_installer + + util_make_exec @spec, "#!/usr/bin/ruby18 -ws" - assert_equal "#!#{Gem.ruby} -ws", shebang + shebang = installer.shebang 'executable' + + shebang_lines = shebang.split "\n" + + assert_equal "#!/bin/sh", shebang_lines.shift + assert_includes shebang_lines, "#!#{Gem.ruby} -ws" + end end def test_shebang_version_env - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/env ruby18" + util_make_exec @spec, "#!/usr/bin/env ruby18" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby}", shebang + assert_equal "#!#{Gem.ruby}", shebang + end end def test_shebang_version_env_arguments - installer = setup_base_installer + load_relative 'no' do + installer = setup_base_installer - util_make_exec @spec, "#!/usr/bin/env ruby18 -ws" + util_make_exec @spec, "#!/usr/bin/env ruby18 -ws" - shebang = installer.shebang 'executable' + shebang = installer.shebang 'executable' - assert_equal "#!#{Gem.ruby} -ws", shebang + assert_equal "#!#{Gem.ruby} -ws", shebang + end + end + + def test_shebang_version_env_arguments_with_load_relative + load_relative 'yes' do + installer = setup_base_installer + + util_make_exec @spec, "#!/usr/bin/env ruby18 -ws" + + shebang = installer.shebang 'executable' + + shebang_lines = shebang.split "\n" + + assert_equal "#!/bin/sh", shebang_lines.shift + assert_includes shebang_lines, "#!#{Gem.ruby} -ws" + end end def test_shebang_custom @@ -1807,10 +2072,18 @@ def test_shebang_custom assert_equal "#!test", shebang end + def get_bin_env + if win_platform? + "" + else + %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + end + end + def test_shebang_custom_with_expands installer = setup_base_installer - bin_env = win_platform? ? '' : '/usr/bin/env' + bin_env = get_bin_env conf = Gem::ConfigFile.new [] conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec 4 $name' @@ -1826,7 +2099,7 @@ def test_shebang_custom_with_expands def test_shebang_custom_with_expands_and_arguments installer = setup_base_installer - bin_env = win_platform? ? '' : '/usr/bin/env' + bin_env = get_bin_env conf = Gem::ConfigFile.new [] conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec' @@ -1848,14 +2121,14 @@ def test_unpack installer.unpack dest end - assert_path_exists File.join dest, 'lib', 'code.rb' - assert_path_exists File.join dest, 'bin', 'executable' + assert_path_exist File.join dest, 'lib', 'code.rb' + assert_path_exist File.join dest, 'bin', 'executable' end def test_write_build_info_file installer = setup_base_installer - refute_path_exists @spec.build_info_file + assert_path_not_exist @spec.build_info_file installer.build_args = %w[ --with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4 @@ -1863,7 +2136,7 @@ def test_write_build_info_file installer.write_build_info_file - assert_path_exists @spec.build_info_file + assert_path_exist @spec.build_info_file expected = "--with-libyaml-dir\n/usr/local/Cellar/libyaml/0.1.4\n" @@ -1873,11 +2146,11 @@ def test_write_build_info_file def test_write_build_info_file_empty installer = setup_base_installer - refute_path_exists @spec.build_info_file + assert_path_not_exist @spec.build_info_file installer.write_build_info_file - refute_path_exists @spec.build_info_file + assert_path_not_exist @spec.build_info_file end def test_write_build_info_file_install_dir @@ -1890,8 +2163,8 @@ def test_write_build_info_file_install_dir installer.write_build_info_file - refute_path_exists @spec.build_info_file - assert_path_exists \ + assert_path_not_exist @spec.build_info_file + assert_path_exist \ File.join("#{@gemhome}2", 'build_info', "#{@spec.full_name}.info") end @@ -1901,27 +2174,27 @@ def test_write_cache_file gem = File.join @gemhome, @spec.file_name FileUtils.mv cache_file, gem - refute_path_exists cache_file + assert_path_not_exist cache_file installer = Gem::Installer.at gem installer.gem_home = @gemhome installer.write_cache_file - assert_path_exists cache_file + assert_path_exist cache_file end def test_write_spec @spec = setup_base_spec FileUtils.rm @spec.spec_file - refute_path_exists @spec.spec_file + assert_path_not_exist @spec.spec_file installer = Gem::Installer.for_spec @spec installer.gem_home = @gemhome installer.write_spec - assert_path_exists @spec.spec_file + assert_path_exist @spec.spec_file loaded = Gem::Specification.load @spec.spec_file @@ -1933,7 +2206,7 @@ def test_write_spec def test_write_spec_writes_cached_spec @spec = setup_base_spec FileUtils.rm @spec.spec_file - refute_path_exists @spec.spec_file + assert_path_not_exist @spec.spec_file @spec.files = %w[a.rb b.rb c.rb] @@ -1951,7 +2224,7 @@ def test_write_spec_writes_cached_spec def test_dir installer = setup_base_installer - assert_match %r!/gemhome/gems/a-2$!, installer.dir + assert_match %r{/gemhome/gems/a-2$}, installer.dir end def test_default_gem_loaded_from @@ -1976,7 +2249,7 @@ def test_default_gem_without_wrappers assert_directory_exists File.join(@spec.gem_dir, 'bin') installed_exec = File.join @spec.gem_dir, 'bin', 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec assert_directory_exists File.join(Gem.default_dir, 'specifications') assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default') @@ -1988,10 +2261,16 @@ def test_default_gem_without_wrappers assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - refute_match %r|generated by RubyGems|, wrapper + + if symlink_supported? + refute_match %r{generated by RubyGems}, wrapper + else # when symlink not supported, it warns and fallbacks back to installing wrapper + assert_match %r{Unable to use symlinks, installing wrapper}, @ui.error + assert_match %r{generated by RubyGems}, wrapper + end end def test_default_gem_with_wrappers @@ -2008,10 +2287,10 @@ def test_default_gem_with_wrappers assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r|generated by RubyGems|, wrapper + assert_match %r{generated by RubyGems}, wrapper end def test_default_gem_with_exe_as_bindir @@ -2034,7 +2313,7 @@ def test_default_gem_with_exe_as_bindir assert_directory_exists File.join(@spec.gem_dir, 'exe') installed_exec = File.join @spec.gem_dir, 'exe', 'executable' - assert_path_exists installed_exec + assert_path_exist installed_exec assert_directory_exists File.join(Gem.default_dir, 'specifications') assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default') @@ -2044,6 +2323,23 @@ def test_default_gem_with_exe_as_bindir assert_equal ['exe/executable'], default_spec.files end + def test_default_gem_to_specific_install_dir + @gem = setup_base_gem + installer = util_installer @spec, "#{@gemhome}2" + installer.options[:install_as_default] = true + + use_ui @ui do + installer.install + end + + assert_directory_exists File.join("#{@gemhome}2", 'specifications') + assert_directory_exists File.join("#{@gemhome}2", 'specifications', 'default') + + default_spec = eval File.read File.join("#{@gemhome}2", 'specifications', 'default', 'a-2.gemspec') + assert_equal Gem::Version.new("2"), default_spec.version + assert_equal ['bin/executable'], default_spec.files + end + def test_package_attribute gem = quick_gem 'c' do |spec| util_make_exec spec, '#!/usr/bin/ruby', 'exe' @@ -2054,16 +2350,18 @@ def test_package_attribute assert_kind_of(Gem::Package, installer.package) end - def old_ruby_required(requirement) - spec = util_spec 'old_ruby_required', '1' do |s| - s.required_ruby_version = requirement + def test_gem_attribute + gem = quick_gem 'c' do |spec| + util_make_exec spec, '#!/usr/bin/ruby', 'exe' end - util_build_gem spec - - spec.cache_file + installer = util_installer(gem, @gemhome) + assert_respond_to(installer, :gem) + assert_kind_of(String, installer.gem) end + private + def util_execless @spec = util_spec 'z' util_build_gem @spec @@ -2084,7 +2382,15 @@ def util_conflict_executable(wrappers) end def mask - 0100755 & (~File.umask) + 0100755 end + def load_relative(value) + orig_LIBRUBY_RELATIVE = RbConfig::CONFIG['LIBRUBY_RELATIVE'] + RbConfig::CONFIG['LIBRUBY_RELATIVE'] = value + + yield + ensure + RbConfig::CONFIG['LIBRUBY_RELATIVE'] = orig_LIBRUBY_RELATIVE + end end diff --git a/ruby/test/rubygems/test_gem_local_remote_options.rb b/ruby/test/rubygems/test_gem_local_remote_options.rb index 6c21300c2..948d1e398 100644 --- a/ruby/test/rubygems/test_gem_local_remote_options.rb +++ b/ruby/test/rubygems/test_gem_local_remote_options.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/local_remote_options' require 'rubygems/command' class TestGemLocalRemoteOptions < Gem::TestCase - def setup super @@ -124,11 +123,10 @@ def test_source_option_bad s1 = 'htp://more-gems.example.com' - assert_raises ArgumentError do + assert_raise ArgumentError do @cmd.handle_options %W[--source #{s1}] end assert_equal [@gem_repo], Gem.sources end - end diff --git a/ruby/test/rubygems/test_gem_name_tuple.rb b/ruby/test/rubygems/test_gem_name_tuple.rb index 5331e1cdb..d87db9bc4 100644 --- a/ruby/test/rubygems/test_gem_name_tuple.rb +++ b/ruby/test/rubygems/test_gem_name_tuple.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/name_tuple' class TestGemNameTuple < Gem::TestCase - def test_full_name n = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby" assert_equal "a-0", n.full_name @@ -40,5 +39,4 @@ def test_spaceship assert_equal 1, a_p.<=>(a) end - end diff --git a/ruby/test/rubygems/test_gem_package.rb b/ruby/test/rubygems/test_gem_package.rb index 5da247e14..9172b7eef 100644 --- a/ruby/test/rubygems/test_gem_package.rb +++ b/ruby/test/rubygems/test_gem_package.rb @@ -1,11 +1,9 @@ -# coding: utf-8 # frozen_string_literal: true -require 'rubygems/package/tar_test_case' -require 'digest' +require_relative 'package/tar_test_case' +require 'rubygems/openssl' class TestGemPackage < Gem::Package::TarTestCase - def setup super @@ -24,7 +22,7 @@ def setup end def test_class_new_old_format - skip "jruby can't require the simple_gem file" if Gem.java_platform? + pend "jruby can't require the simple_gem file" if Gem.java_platform? require_relative "simple_gem" File.open 'old_format.gem', 'wb' do |io| io.write SIMPLE_GEM @@ -86,27 +84,24 @@ def test_add_checksums io.write spec.to_yaml end - metadata_sha256 = Digest::SHA256.hexdigest s.string - metadata_sha512 = Digest::SHA512.hexdigest s.string + metadata_sha256 = OpenSSL::Digest::SHA256.hexdigest s.string + metadata_sha512 = OpenSSL::Digest::SHA512.hexdigest s.string expected = { 'SHA512' => { 'metadata.gz' => metadata_sha512, - 'data.tar.gz' => Digest::SHA512.hexdigest(tar), - } - } - - if defined?(OpenSSL::Digest) - expected['SHA256'] = { + 'data.tar.gz' => OpenSSL::Digest::SHA512.hexdigest(tar), + }, + 'SHA256' => { 'metadata.gz' => metadata_sha256, - 'data.tar.gz' => Digest::SHA256.hexdigest(tar), - } - end + 'data.tar.gz' => OpenSSL::Digest::SHA256.hexdigest(tar), + }, + } - assert_equal expected, YAML.load(checksums) + assert_equal expected, load_yaml(checksums) end - def test_build_time_source_date_epoch + def test_build_time_uses_source_date_epoch epoch = ENV["SOURCE_DATE_EPOCH"] ENV["SOURCE_DATE_EPOCH"] = "123456789" @@ -124,12 +119,10 @@ def test_build_time_source_date_epoch ENV["SOURCE_DATE_EPOCH"] = epoch end - def test_build_time_source_date_epoch_automatically_set + def test_build_time_without_source_date_epoch epoch = ENV["SOURCE_DATE_EPOCH"] ENV["SOURCE_DATE_EPOCH"] = nil - start_time = Time.now.utc.to_i - spec = Gem::Specification.new 'build', '1' spec.summary = 'build' spec.authors = 'build' @@ -138,14 +131,11 @@ def test_build_time_source_date_epoch_automatically_set package = Gem::Package.new spec.file_name - end_time = Time.now.utc.to_i - assert_kind_of Time, package.build_time build_time = package.build_time.to_i - assert_operator(start_time, :<=, build_time) - assert_operator(build_time, :<=, end_time) + assert_equal Gem.source_date_epoch.to_i, build_time ensure ENV["SOURCE_DATE_EPOCH"] = epoch end @@ -156,7 +146,7 @@ def test_add_files FileUtils.mkdir_p 'lib/empty' - File.open 'lib/code.rb', 'w' do |io| + File.open 'lib/code.rb', 'w' do |io| io.write '# lib/code.rb' end @@ -190,7 +180,7 @@ def test_add_files_symlink FileUtils.mkdir_p 'lib' - File.open 'lib/code.rb', 'w' do |io| + File.open 'lib/code.rb', 'w' do |io| io.write '# lib/code.rb' end @@ -200,7 +190,7 @@ def test_add_files_symlink File.symlink('../lib/code.rb', 'lib/code_sym2.rb') rescue Errno::EACCES => e if win_platform? - skip "symlink - must be admin with no UAC on Windows" + pend "symlink - must be admin with no UAC on Windows" else raise e end @@ -228,7 +218,7 @@ def test_add_files_symlink end assert_equal %w[lib/code.rb], files - assert_equal [{'lib/code_sym.rb' => 'lib/code.rb'}, {'lib/code_sym2.rb' => '../lib/code.rb'}], symlinks + assert_equal [{'lib/code_sym.rb' => 'code.rb'}, {'lib/code_sym2.rb' => '../lib/code.rb'}], symlinks end def test_build @@ -250,7 +240,7 @@ def test_build package.build assert_equal Gem::VERSION, spec.rubygems_version - assert_path_exists spec.file_name + assert_path_exist spec.file_name reader = Gem::Package.new spec.file_name assert_equal spec, reader.spec @@ -262,7 +252,7 @@ def test_build end def test_build_auto_signed - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL FileUtils.mkdir_p File.join(Gem.user_home, '.gem') @@ -289,7 +279,7 @@ def test_build_auto_signed package.build assert_equal Gem::VERSION, spec.rubygems_version - assert_path_exists spec.file_name + assert_path_exist spec.file_name reader = Gem::Package.new spec.file_name assert reader.verify @@ -305,7 +295,7 @@ def test_build_auto_signed end def test_build_auto_signed_encrypted_key - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL FileUtils.mkdir_p File.join(Gem.user_home, '.gem') @@ -332,7 +322,7 @@ def test_build_auto_signed_encrypted_key package.build assert_equal Gem::VERSION, spec.rubygems_version - assert_path_exists spec.file_name + assert_path_exist spec.file_name reader = Gem::Package.new spec.file_name assert reader.verify @@ -353,7 +343,7 @@ def test_build_invalid package = Gem::Package.new spec.file_name package.spec = spec - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do package.build end @@ -366,7 +356,7 @@ def test_build_invalid_arguments package = Gem::Package.new spec.file_name package.spec = spec - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do package.build true, true end @@ -374,7 +364,7 @@ def test_build_invalid_arguments end def test_build_signed - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL spec = Gem::Specification.new 'build', '1' spec.summary = 'build' @@ -395,7 +385,7 @@ def test_build_signed package.build assert_equal Gem::VERSION, spec.rubygems_version - assert_path_exists spec.file_name + assert_path_exist spec.file_name reader = Gem::Package.new spec.file_name assert reader.verify @@ -411,7 +401,7 @@ def test_build_signed end def test_build_signed_encrypted_key - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL spec = Gem::Specification.new 'build', '1' spec.summary = 'build' @@ -432,7 +422,7 @@ def test_build_signed_encrypted_key package.build assert_equal Gem::VERSION, spec.rubygems_version - assert_path_exists spec.file_name + assert_path_exist spec.file_name reader = Gem::Package.new spec.file_name assert reader.verify @@ -448,7 +438,7 @@ def test_build_signed_encrypted_key end def test_raw_spec - data_tgz = util_tar_gz { } + data_tgz = util_tar_gz {} gem = util_tar do |tar| tar.add_file 'data.tar.gz', 0644 do |io| @@ -486,7 +476,7 @@ def test_extract_files package.extract_files @destination extracted = File.join @destination, 'lib/code.rb' - assert_path_exists extracted + assert_path_exist extracted mask = 0100666 & (~File.umask) @@ -495,7 +485,7 @@ def test_extract_files end def test_extract_files_empty - data_tgz = util_tar_gz { } + data_tgz = util_tar_gz {} gem = util_tar do |tar| tar.add_file 'data.tar.gz', 0644 do |io| @@ -517,7 +507,7 @@ def test_extract_files_empty package.extract_files @destination - assert_path_exists @destination + assert_path_exist @destination end def test_extract_tar_gz_absolute @@ -529,7 +519,7 @@ def test_extract_tar_gz_absolute end end - e = assert_raises Gem::Package::PathError do + e = assert_raise Gem::Package::PathError do package.extract_tar_gz tgz_io, @destination end @@ -541,11 +531,11 @@ def test_extract_tar_gz_symlink_relative_path package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file 'relative.rb', 0644 do |io| + tar.add_file 'relative.rb', 0644 do |io| io.write 'hi' end - tar.mkdir 'lib', 0755 + tar.mkdir 'lib', 0755 tar.add_symlink 'lib/foo.rb', '../relative.rb', 0644 end @@ -553,14 +543,14 @@ def test_extract_tar_gz_symlink_relative_path package.extract_tar_gz tgz_io, @destination rescue Errno::EACCES => e if win_platform? - skip "symlink - must be admin with no UAC on Windows" + pend "symlink - must be admin with no UAC on Windows" else raise e end end extracted = File.join @destination, 'lib/foo.rb' - assert_path_exists extracted + assert_path_exist extracted assert_equal '../relative.rb', File.readlink(extracted) assert_equal 'hi', @@ -584,18 +574,19 @@ def test_extract_symlink_parent destination_subdir = File.join @destination, 'subdir' FileUtils.mkdir_p destination_subdir - e = assert_raises(Gem::Package::PathError, Errno::EACCES) do + expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + + e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir end - if Gem::Package::PathError === e - assert_equal("installing into parent path lib/link/outside.txt of " + - "#{destination_subdir} is not allowed", e.message) - elsif win_platform? - skip "symlink - must be admin with no UAC on Windows" - else - raise e - end + pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e + + assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " + + "#{destination_subdir} is not allowed", e.message) + + assert_path_not_exist File.join(@destination, "outside.txt") + assert_path_not_exist File.join(destination_subdir, "lib/link") end def test_extract_symlink_parent_doesnt_delete_user_dir @@ -611,25 +602,27 @@ def test_extract_symlink_parent_doesnt_delete_user_dir destination_user_subdir = File.join destination_user_dir, 'dir' FileUtils.mkdir_p destination_user_subdir + pend "TMPDIR seems too long to add it as symlink into tar" if destination_user_dir.size > 90 + tgz_io = util_tar_gz do |tar| tar.add_symlink 'link', destination_user_dir, 16877 tar.add_symlink 'link/dir', '.', 16877 end - e = assert_raises(Gem::Package::PathError, Errno::EACCES) do + expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + + e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir end - assert_path_exists destination_user_subdir + pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e - if Gem::Package::PathError === e - assert_equal("installing into parent path #{destination_user_subdir} of " + - "#{destination_subdir} is not allowed", e.message) - elsif win_platform? - skip "symlink - must be admin with no UAC on Windows" - else - raise e - end + assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " + + "#{destination_subdir} is not allowed", e.message) + + assert_path_exist destination_user_subdir + assert_path_not_exist File.join(destination_subdir, "link/dir") + assert_path_not_exist File.join(destination_subdir, "link") end def test_extract_tar_gz_directory @@ -640,16 +633,16 @@ def test_extract_tar_gz_directory tar.add_file 'lib/foo.rb', 0644 do |io| io.write 'hi' end - tar.mkdir 'lib/foo', 0755 + tar.mkdir 'lib/foo', 0755 end package.extract_tar_gz tgz_io, @destination extracted = File.join @destination, 'lib/foo.rb' - assert_path_exists extracted + assert_path_exist extracted extracted = File.join @destination, 'lib/foo' - assert_path_exists extracted + assert_path_exist extracted end def test_extract_tar_gz_dot_slash @@ -664,7 +657,7 @@ def test_extract_tar_gz_dot_slash package.extract_tar_gz tgz_io, @destination extracted = File.join @destination, 'dot_slash.rb' - assert_path_exists extracted + assert_path_exist extracted end def test_extract_tar_gz_dot_file @@ -679,7 +672,7 @@ def test_extract_tar_gz_dot_file package.extract_tar_gz tgz_io, @destination extracted = File.join @destination, '.dot_file.rb' - assert_path_exists extracted + assert_path_exist extracted end if Gem.win_platform? @@ -695,7 +688,7 @@ def test_extract_tar_gz_case_insensitive package.extract_tar_gz tgz_io, @destination.upcase extracted = File.join @destination, 'foo/file.rb' - assert_path_exists extracted + assert_path_exist extracted end end @@ -714,7 +707,7 @@ def test_install_location def test_install_location_absolute package = Gem::Package.new @gem - e = assert_raises Gem::Package::PathError do + e = assert_raise Gem::Package::PathError do package.install_location '/absolute.rb', @destination end @@ -755,7 +748,7 @@ def test_install_location_extra_slash def test_install_location_relative package = Gem::Package.new @gem - e = assert_raises Gem::Package::PathError do + e = assert_raise Gem::Package::PathError do package.install_location '../relative.rb', @destination end @@ -770,7 +763,7 @@ def test_install_location_suffix filename = "../#{File.basename(@destination)}suffix.rb" - e = assert_raises Gem::Package::PathError do + e = assert_raise Gem::Package::PathError do package.install_location filename, @destination end @@ -829,7 +822,7 @@ def test_verify_checksum_bad } tar.add_file 'checksums.yaml.gz', 0444 do |io| Zlib::GzipWriter.wrap io do |gz_io| - gz_io.write YAML.dump bogus_checksums + gz_io.write Psych.dump bogus_checksums end end end @@ -840,7 +833,7 @@ def test_verify_checksum_bad package = Gem::Package.new 'mismatch.gem' - e = assert_raises Gem::Package::FormatError do + e = assert_raise Gem::Package::FormatError do package.verify end @@ -864,7 +857,7 @@ def test_verify_checksum_missing io.write metadata_gz end - digest = Digest::SHA1.new + digest = OpenSSL::Digest::SHA1.new digest << metadata_gz checksums = { @@ -875,7 +868,7 @@ def test_verify_checksum_missing tar.add_file 'checksums.yaml.gz', 0444 do |io| Zlib::GzipWriter.wrap io do |gz_io| - gz_io.write YAML.dump checksums + gz_io.write Psych.dump checksums end end @@ -894,7 +887,7 @@ def test_verify_checksum_missing end def test_verify_corrupt - skip "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform? + pend "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform? tf = Tempfile.open 'corrupt' do |io| data = Gem::Util.gzip 'a' * 10 io.write \ @@ -904,7 +897,7 @@ def test_verify_corrupt package = Gem::Package.new io.path - e = assert_raises Gem::Package::FormatError do + e = assert_raise Gem::Package::FormatError do package.verify end @@ -920,7 +913,7 @@ def test_verify_empty package = Gem::Package.new 'empty.gem' - e = assert_raises Gem::Package::FormatError do + e = assert_raise Gem::Package::FormatError do package.verify end @@ -930,12 +923,12 @@ def test_verify_empty def test_verify_nonexistent package = Gem::Package.new 'nonexistent.gem' - e = assert_raises Gem::Package::FormatError do + e = assert_raise Gem::Package::FormatError do package.verify end - assert_match %r%^No such file or directory%, e.message - assert_match %r%nonexistent.gem$%, e.message + assert_match %r{^No such file or directory}, e.message + assert_match %r{nonexistent.gem$}, e.message end def test_verify_duplicate_file @@ -945,7 +938,7 @@ def test_verify_duplicate_file build = Gem::Package.new @gem build.spec = @spec build.setup_signer - open @gem, 'wb' do |gem_io| + File.open @gem, 'wb' do |gem_io| Gem::Package::TarWriter.new gem_io do |gem| build.add_metadata gem build.add_contents gem @@ -957,7 +950,7 @@ def test_verify_duplicate_file package = Gem::Package.new @gem - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do package.verify end @@ -965,12 +958,12 @@ def test_verify_duplicate_file end def test_verify_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL package = Gem::Package.new @gem package.security_policy = Gem::Security::HighSecurity - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do package.verify end @@ -982,7 +975,7 @@ def test_verify_security_policy end def test_verify_security_policy_low_security - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @spec.cert_chain = [PUBLIC_CERT.to_pem] @spec.signing_key = PRIVATE_KEY @@ -1002,7 +995,7 @@ def test_verify_security_policy_low_security end def test_verify_security_policy_checksum_missing - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @spec.cert_chain = [PUBLIC_CERT.to_pem] @spec.signing_key = PRIVATE_KEY @@ -1023,7 +1016,7 @@ def test_verify_security_policy_checksum_missing bogus_data = Gem::Util.gzip 'hello' fake_signer = Class.new do def digest_name; 'SHA512'; end - def digest_algorithm; Digest(:SHA512); end + def digest_algorithm; OpenSSL::Digest(:SHA512).new; end def key; 'key'; end def sign(*); 'fake_sig'; end end @@ -1040,7 +1033,7 @@ def sign(*); 'fake_sig'; end package = Gem::Package.new @gem package.security_policy = Gem::Security::HighSecurity - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do package.verify end @@ -1057,7 +1050,7 @@ def test_verify_truncate package = Gem::Package.new 'bad.gem' - e = assert_raises Gem::Package::FormatError do + e = assert_raise Gem::Package::FormatError do package.verify end @@ -1073,11 +1066,22 @@ def entry.full_name() raise ArgumentError, 'whatever' end package = Gem::Package.new @gem - e = assert_raises Gem::Package::FormatError do - package.verify_entry entry + _, err = use_ui @ui do + e = nil + + out_err = capture_output do + e = assert_raise ArgumentError do + package.verify_entry entry + end + end + + assert_equal "whatever", e.message + assert_equal "full_name", e.backtrace_locations.first.label + + out_err end - assert_equal "package is corrupt, exception while verifying: whatever (ArgumentError) in #{@gem}", e.message + assert_equal "Exception while verifying #{@gem}\n", err valid_metadata = ["metadata", "metadata.gz"] valid_metadata.each do |vm| @@ -1102,7 +1106,7 @@ def package.load_spec(entry) $spec_loaded = true end $bad_name = vm entry = Object.new - def entry.full_name() $bad_name end + def entry.full_name() $bad_name end package = Gem::Package.new(@gem) package.instance_variable_set(:@files, []) @@ -1137,11 +1141,18 @@ def test_spec_from_io def test_spec_from_io_raises_gem_error_for_io_not_at_start io = StringIO.new Gem.read_binary @gem io.read(1) - assert_raises(Gem::Package::Error) do + assert_raise(Gem::Package::Error) do Gem::Package.new io end end + def test_contents_from_io + io = StringIO.new Gem.read_binary @gem + package = Gem::Package.new io + + assert_equal %w[lib/code.rb], package.contents + end + def util_tar tar_io = StringIO.new @@ -1166,5 +1177,4 @@ def util_tar_gz(&block) StringIO.new tgz_io.string end - end diff --git a/ruby/test/rubygems/test_gem_package_old.rb b/ruby/test/rubygems/test_gem_package_old.rb index d2ce59cfd..945340a96 100644 --- a/ruby/test/rubygems/test_gem_package_old.rb +++ b/ruby/test/rubygems/test_gem_package_old.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' unless Gem.java_platform? # jruby can't require the simple_gem file require 'rubygems/simple_gem' class TestGemPackageOld < Gem::TestCase - def setup super @@ -24,11 +23,11 @@ def test_contents end def test_contents_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @package.security_policy = Gem::Security::AlmostNoSecurity - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @package.contents end end @@ -37,7 +36,7 @@ def test_extract_files @package.extract_files @destination extracted = File.join @destination, 'lib/foo.rb' - assert_path_exists extracted + assert_path_exist extracted mask = 0100644 & (~File.umask) @@ -45,11 +44,11 @@ def test_extract_files end def test_extract_files_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @package.security_policy = Gem::Security::AlmostNoSecurity - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @package.extract_files @destination end end @@ -59,17 +58,17 @@ def test_spec end def test_spec_security_policy - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL @package.security_policy = Gem::Security::AlmostNoSecurity - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @package.spec end end def test_verify - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL assert @package.verify @@ -79,7 +78,7 @@ def test_verify @package.security_policy = Gem::Security::AlmostNoSecurity - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @package.verify end @@ -87,6 +86,5 @@ def test_verify 'and cannot be verified', e.message end - end end diff --git a/ruby/test/rubygems/test_gem_package_tar_header.rb b/ruby/test/rubygems/test_gem_package_tar_header.rb index 7e5907340..0e72a72d6 100644 --- a/ruby/test/rubygems/test_gem_package_tar_header.rb +++ b/ruby/test/rubygems/test_gem_package_tar_header.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/package/tar_test_case' +require_relative 'package/tar_test_case' require 'rubygems/package' class TestGemPackageTarHeader < Gem::Package::TarTestCase - def setup super @@ -58,19 +57,19 @@ def test_initialize end def test_initialize_bad - assert_raises ArgumentError do + assert_raise ArgumentError do Gem::Package::TarHeader.new :name => '', :size => '', :mode => '' end - assert_raises ArgumentError do + assert_raise ArgumentError do Gem::Package::TarHeader.new :name => '', :size => '', :prefix => '' end - assert_raises ArgumentError do + assert_raise ArgumentError do Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => '' end - assert_raises ArgumentError do + assert_raise ArgumentError do Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => '' end end @@ -157,7 +156,7 @@ def test_from_bad_octal # overwrite the size field header_s[124, 12] = val io = TempIO.new header_s - assert_raises ArgumentError do + assert_raise ArgumentError do Gem::Package::TarHeader.from io end io.close! @@ -205,4 +204,22 @@ def test_big_uid_gid assert_equal 6932, tar_header.checksum end + def test_spaces_in_headers + stream = StringIO.new( + <<-EOF.dup.force_encoding('binary').split("\n").join +Access_Points_09202018.csv +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 +\x00\x00100777 \x00 0 \x00 0 \x00 4357 13545040367 104501 +\x000 + EOF + ) + + tar_header = Gem::Package::TarHeader.from stream + + assert_equal 0, tar_header.uid + assert_equal 0, tar_header.gid + end end diff --git a/ruby/test/rubygems/test_gem_package_tar_reader.rb b/ruby/test/rubygems/test_gem_package_tar_reader.rb index 489685d09..277b552f1 100644 --- a/ruby/test/rubygems/test_gem_package_tar_reader.rb +++ b/ruby/test/rubygems/test_gem_package_tar_reader.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/package/tar_test_case' +require_relative 'package/tar_test_case' require 'rubygems/package' class TestGemPackageTarReader < Gem::Package::TarTestCase - def test_each_entry tar = tar_dir_header "foo", "bar", 0, Time.now tar << tar_file_header("bar", "baz", 0, 0, Time.now) @@ -85,5 +84,4 @@ def test_seek_missing ensure io.close! end - end diff --git a/ruby/test/rubygems/test_gem_package_tar_reader_entry.rb b/ruby/test/rubygems/test_gem_package_tar_reader_entry.rb index 87f347167..1be587014 100644 --- a/ruby/test/rubygems/test_gem_package_tar_reader_entry.rb +++ b/ruby/test/rubygems/test_gem_package_tar_reader_entry.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/package/tar_test_case' +require_relative 'package/tar_test_case' require 'rubygems/package' class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase - def setup super @@ -43,19 +42,19 @@ def test_close assert @entry.bytes_read - e = assert_raises(IOError) { @entry.eof? } + e = assert_raise(IOError) { @entry.eof? } assert_equal 'closed Gem::Package::TarReader::Entry', e.message - e = assert_raises(IOError) { @entry.getc } + e = assert_raise(IOError) { @entry.getc } assert_equal 'closed Gem::Package::TarReader::Entry', e.message - e = assert_raises(IOError) { @entry.pos } + e = assert_raise(IOError) { @entry.pos } assert_equal 'closed Gem::Package::TarReader::Entry', e.message - e = assert_raises(IOError) { @entry.read } + e = assert_raise(IOError) { @entry.read } assert_equal 'closed Gem::Package::TarReader::Entry', e.message - e = assert_raises(IOError) { @entry.rewind } + e = assert_raise(IOError) { @entry.rewind } assert_equal 'closed Gem::Package::TarReader::Entry', e.message end @@ -76,10 +75,10 @@ def test_full_name end def test_full_name_null - skip "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform? + pend "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform? @entry.header.prefix << "\000" - e = assert_raises Gem::Package::TarInvalidError do + e = assert_raise Gem::Package::TarInvalidError do @entry.full_name end @@ -135,7 +134,7 @@ def test_read_small end def test_readpartial - assert_raises(EOFError) do + assert_raise(EOFError) do @entry.read(@contents.size) @entry.readpartial(1) end @@ -150,5 +149,4 @@ def test_rewind assert_equal char, @entry.getc end - end diff --git a/ruby/test/rubygems/test_gem_package_tar_writer.rb b/ruby/test/rubygems/test_gem_package_tar_writer.rb index 81661da45..31a91fa21 100644 --- a/ruby/test/rubygems/test_gem_package_tar_writer.rb +++ b/ruby/test/rubygems/test_gem_package_tar_writer.rb @@ -1,13 +1,16 @@ # frozen_string_literal: true -require 'rubygems/package/tar_test_case' +require_relative 'package/tar_test_case' require 'rubygems/package/tar_writer' -require 'minitest/mock' class TestGemPackageTarWriter < Gem::Package::TarTestCase - def setup super + # Setting `@default_source_date_epoch` to `nil` effectively resets the + # value used for `Gem.source_date_epoch` whenever `$SOURCE_DATE_EPOCH` + # is not set. + Gem.instance_variable_set(:'@default_source_date_epoch', nil) + @data = 'abcde12345' @io = TempIO.new @tar_writer = Gem::Package::TarWriter.new @io @@ -67,7 +70,7 @@ def test_add_symlink_source_date_epoch end def test_add_file_digest - digest_algorithms = Digest::SHA1, Digest::SHA512 + digest_algorithms = Digest::SHA1.new, Digest::SHA512.new Time.stub :now, Time.at(1458518157) do digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io| @@ -90,7 +93,7 @@ def test_add_file_digest end def test_add_file_digest_multiple - digest_algorithms = [Digest::SHA1, Digest::SHA512] + digest_algorithms = [Digest::SHA1.new, Digest::SHA512.new] Time.stub :now, Time.at(1458518157) do digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io| @@ -113,7 +116,7 @@ def test_add_file_digest_multiple end def test_add_file_signer - skip 'openssl is missing' unless defined?(OpenSSL::SSL) + pend 'openssl is missing' unless Gem::HAVE_OPENSSL signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT] @@ -146,13 +149,12 @@ def test_add_file_signer_empty signer = Gem::Security::Signer.new nil, nil Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file_signed 'x', 0644, signer do |io| io.write 'a' * 10 end assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now), - @io.string[0, 512]) + @io.string[0, 512]) end assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -166,11 +168,11 @@ def test_add_file_simple end assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now), - @io.string[0, 512]) - end + @io.string[0, 512]) - assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] - assert_equal 1024, @io.pos + assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] + assert_equal 1024, @io.pos + end end def test_add_file_simple_source_date_epoch @@ -181,7 +183,7 @@ def test_add_file_simple_source_date_epoch end assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), - @io.string[0, 512]) + @io.string[0, 512]) end end @@ -190,14 +192,14 @@ def test_add_file_simple_padding @tar_writer.add_file_simple 'x', 0, 100 assert_headers_equal tar_file_header('x', '', 0, 100, Time.now), - @io.string[0, 512] + @io.string[0, 512] end assert_equal "\0" * 512, @io.string[512, 512] end def test_add_file_simple_data - @tar_writer.add_file_simple("lib/foo/bar", 0, 10) { |f| f.write @data } + @tar_writer.add_file_simple("lib/foo/bar", 0, 10) {|f| f.write @data } @tar_writer.flush assert_equal @data + ("\0" * (512 - @data.size)), @@ -205,7 +207,7 @@ def test_add_file_simple_data end def test_add_file_simple_size - assert_raises Gem::Package::TarWriter::FileOverflow do + assert_raise Gem::Package::TarWriter::FileOverflow do @tar_writer.add_file_simple("lib/foo/bar", 0, 10) do |io| io.write "1" * 11 end @@ -217,27 +219,27 @@ def test_close assert_equal "\0" * 1024, @io.string - e = assert_raises IOError do + e = assert_raise IOError do @tar_writer.close end assert_equal 'closed Gem::Package::TarWriter', e.message - e = assert_raises IOError do + e = assert_raise IOError do @tar_writer.flush end assert_equal 'closed Gem::Package::TarWriter', e.message - e = assert_raises IOError do + e = assert_raise IOError do @tar_writer.add_file 'x', 0 end assert_equal 'closed Gem::Package::TarWriter', e.message - e = assert_raises IOError do + e = assert_raise IOError do @tar_writer.add_file_simple 'x', 0, 0 end assert_equal 'closed Gem::Package::TarWriter', e.message - e = assert_raises IOError do + e = assert_raise IOError do @tar_writer.mkdir 'x', 0 end assert_equal 'closed Gem::Package::TarWriter', e.message @@ -293,7 +295,7 @@ def test_split_name_too_long_name assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name) name = File.join 'a', 'b' * 101 - exception = assert_raises Gem::Package::TooLongFileName do + exception = assert_raise Gem::Package::TooLongFileName do @tar_writer.split_name name end assert_includes exception.message, name @@ -301,7 +303,7 @@ def test_split_name_too_long_name # note, GNU tar 1.28 is unable to handle this case too, # tested with "tar --format=ustar -cPf /tmp/foo.tartar -- /aaaaaa....a" name = '/' + 'a' * 100 - exception = assert_raises Gem::Package::TooLongFileName do + exception = assert_raise Gem::Package::TooLongFileName do @tar_writer.split_name name end assert_includes exception.message, name @@ -312,7 +314,7 @@ def test_split_name_too_long_prefix assert_equal ['b', 'a' * 155], @tar_writer.split_name(name) name = File.join 'a' * 156, 'b' - exception = assert_raises Gem::Package::TooLongFileName do + exception = assert_raise Gem::Package::TooLongFileName do @tar_writer.split_name name end assert_includes exception.message, name @@ -320,10 +322,9 @@ def test_split_name_too_long_prefix def test_split_name_too_long_total name = 'a' * 257 - exception = assert_raises Gem::Package::TooLongFileName do + exception = assert_raise Gem::Package::TooLongFileName do @tar_writer.split_name name end assert_includes exception.message, name end - end diff --git a/ruby/test/rubygems/test_gem_package_task.rb b/ruby/test/rubygems/test_gem_package_task.rb index e01f4a404..0cedfe56e 100644 --- a/ruby/test/rubygems/test_gem_package_task.rb +++ b/ruby/test/rubygems/test_gem_package_task.rb @@ -1,22 +1,22 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' -require 'bundler/errors' + begin require 'rubygems/package_task' -rescue LoadError, Bundler::GemfileNotFound +rescue LoadError => e + raise unless e.path == 'rake/packagetask' end -class TestGemPackageTask < Gem::TestCase - - def setup - super +unless defined?(Rake::PackageTask) + warn 'Skipping Gem::PackageTask tests. rake not found.' +end - Rake.application = Rake::Application.new +class TestGemPackageTask < Gem::TestCase + def test_gem_package + original_rake_fileutils_verbosity = RakeFileUtils.verbose_flag RakeFileUtils.verbose_flag = false - end - def test_gem_package gem = Gem::Specification.new do |g| g.name = "pkgr" g.version = "1.2.3" @@ -26,7 +26,9 @@ def test_gem_package g.summary = 'summary' end - pkg = Gem::PackageTask.new(gem) do |p| + Rake.application = Rake::Application.new + + pkg = Gem::PackageTask.new(gem) do |p| p.package_files << "y" end @@ -38,8 +40,40 @@ def test_gem_package Rake.application['package'].invoke - assert_path_exists 'pkg/pkgr-1.2.3.gem' + assert_path_exist 'pkg/pkgr-1.2.3.gem' end + ensure + RakeFileUtils.verbose_flag = original_rake_fileutils_verbosity + end + + def test_gem_package_prints_to_stdout_by_default + gem = Gem::Specification.new do |g| + g.name = "pkgr" + g.version = "1.2.3" + + g.authors = %w[author] + g.files = %w[x] + g.summary = 'summary' + end + + _, err = capture_output do + Rake.application = Rake::Application.new + + pkg = Gem::PackageTask.new(gem) do |p| + p.package_files << "y" + end + + assert_equal %w[x y], pkg.package_files + + Dir.chdir @tempdir do + FileUtils.touch 'x' + FileUtils.touch 'y' + + Rake.application['package'].invoke + end + end + + assert_empty err end def test_gem_package_with_current_platform @@ -49,7 +83,7 @@ def test_gem_package_with_current_platform g.files = Rake::FileList["x"].resolve g.platform = Gem::Platform::CURRENT end - pkg = Gem::PackageTask.new(gem) do |p| + pkg = Gem::PackageTask.new(gem) do |p| p.package_files << "y" end assert_equal ["x", "y"], pkg.package_files @@ -62,7 +96,7 @@ def test_gem_package_with_ruby_platform g.files = Rake::FileList["x"].resolve g.platform = Gem::Platform::RUBY end - pkg = Gem::PackageTask.new(gem) do |p| + pkg = Gem::PackageTask.new(gem) do |p| p.package_files << "y" end assert_equal ["x", "y"], pkg.package_files @@ -80,5 +114,4 @@ def test_package_dir_path assert_equal 'pkg/nokogiri-1.5.0-java', pkg.package_dir_path end - end if defined?(Rake::PackageTask) diff --git a/ruby/test/rubygems/test_gem_path_support.rb b/ruby/test/rubygems/test_gem_path_support.rb index 8715bb62d..394cba2b7 100644 --- a/ruby/test/rubygems/test_gem_path_support.rb +++ b/ruby/test/rubygems/test_gem_path_support.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' require 'fileutils' class TestGemPathSupport < Gem::TestCase - def setup super @@ -17,7 +16,7 @@ def test_initialize assert_equal ENV["GEM_HOME"], ps.home - expected = util_path + expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR) assert_equal expected, ps.path, "defaults to GEM_PATH" end @@ -26,7 +25,7 @@ def test_initialize_home assert_equal File.join(@tempdir, "foo"), ps.home - expected = util_path + [File.join(@tempdir, 'foo')] + expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR) + [File.join(@tempdir, 'foo')] assert_equal expected, ps.path end @@ -103,10 +102,6 @@ def test_initialize_home_path end end - def util_path - ENV["GEM_PATH"].split(File::PATH_SEPARATOR) - end - def test_initialize_spec ENV["GEM_SPEC_CACHE"] = nil @@ -131,7 +126,7 @@ def test_gem_paths_do_not_contain_symlinks begin File.symlink(dir, symlink) rescue NotImplementedError, SystemCallError - skip 'symlinks not supported' + pend 'symlinks not supported' end not_existing = "#{@tempdir}/does_not_exist" path = "#{symlink}#{File::PATH_SEPARATOR}#{not_existing}" @@ -140,5 +135,4 @@ def test_gem_paths_do_not_contain_symlinks assert_equal dir, ps.home assert_equal [dir, not_existing], ps.path end - end diff --git a/ruby/test/rubygems/test_gem_platform.rb b/ruby/test/rubygems/test_gem_platform.rb index 289f07886..8029035db 100644 --- a/ruby/test/rubygems/test_gem_platform.rb +++ b/ruby/test/rubygems/test_gem_platform.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/platform' require 'rbconfig' class TestGemPlatform < Gem::TestCase - def test_self_local util_set_arch 'i686-darwin8.10.1' @@ -12,10 +11,69 @@ def test_self_local end def test_self_match - assert Gem::Platform.match(nil), 'nil == ruby' - assert Gem::Platform.match(Gem::Platform.local), 'exact match' - assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match' - assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby' + Gem::Deprecate.skip_during do + assert Gem::Platform.match(nil), 'nil == ruby' + assert Gem::Platform.match(Gem::Platform.local), 'exact match' + assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match' + assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby' + end + end + + def test_self_match_gem? + assert Gem::Platform.match_gem?(nil, 'json'), 'nil == ruby' + assert Gem::Platform.match_gem?(Gem::Platform.local, 'json'), 'exact match' + assert Gem::Platform.match_gem?(Gem::Platform.local.to_s, 'json'), '=~ match' + assert Gem::Platform.match_gem?(Gem::Platform::RUBY, 'json'), 'ruby' + end + + def test_self_match_spec? + make_spec = -> platform do + util_spec 'mygem-for-platform-match_spec', '1' do |s| + s.platform = platform + end + end + + assert Gem::Platform.match_spec?(make_spec.call(nil)), 'nil == ruby' + assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local)), 'exact match' + assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local.to_s)), '=~ match' + assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform::RUBY)), 'ruby' + end + + def test_self_match_spec_with_match_gem_override + make_spec = -> name, platform do + util_spec name, '1' do |s| + s.platform = platform + end + end + + class << Gem::Platform + alias_method :original_match_gem?, :match_gem? + def match_gem?(platform, gem_name) + # e.g., sassc and libv8 are such gems, their native extensions do not use the Ruby C API + if gem_name == 'gem-with-ruby-impl-independent-precompiled-ext' + match_platforms?(platform, [Gem::Platform::RUBY, Gem::Platform.local]) + else + match_platforms?(platform, Gem.platforms) + end + end + end + + platforms = Gem.platforms + Gem.platforms = [Gem::Platform::RUBY] + begin + assert_equal true, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform::RUBY)) + assert_equal false, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform.local)) + + name = 'gem-with-ruby-impl-independent-precompiled-ext' + assert_equal true, Gem::Platform.match_spec?(make_spec.call(name, Gem::Platform.local)) + ensure + Gem.platforms = platforms + class << Gem::Platform + remove_method :match_gem? + alias_method :match_gem?, :original_match_gem? # rubocop:disable Lint/DuplicateMethods + remove_method :original_match_gem? + end + end end def test_self_new @@ -64,6 +122,7 @@ def test_initialize 'i586-linux-gnu' => ['x86', 'linux', nil], 'i386-linux-gnu' => ['x86', 'linux', nil], 'i386-mingw32' => ['x86', 'mingw32', nil], + 'x64-mingw-ucrt' => ['x64', 'mingw', 'ucrt'], 'i386-mswin32' => ['x86', 'mswin32', nil], 'i386-mswin32_80' => ['x86', 'mswin32', '80'], 'i386-mswin32-80' => ['x86', 'mswin32', '80'], @@ -298,6 +357,14 @@ def test_equals_tilde assert_local_match 'sparc-solaris2.8-mq5.3' end + def test_inspect + result = Gem::Platform.new("universal-java11").inspect + + assert_equal 1, result.scan(/@cpu=/).size + assert_equal 1, result.scan(/@os=/).size + assert_equal 1, result.scan(/@version=/).size + end + def assert_local_match(name) assert_match Gem::Platform.local, name end @@ -305,5 +372,4 @@ def assert_local_match(name) def refute_local_match(name) refute_match Gem::Platform.local, name end - end diff --git a/ruby/test/rubygems/test_gem_rdoc.rb b/ruby/test/rubygems/test_gem_rdoc.rb index 6184d4b45..7b8ad07b2 100644 --- a/ruby/test/rubygems/test_gem_rdoc.rb +++ b/ruby/test/rubygems/test_gem_rdoc.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true require 'rubygems' -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/rdoc' class TestGemRDoc < Gem::TestCase - Gem::RDoc.load_rdoc def setup @@ -25,7 +24,7 @@ def setup begin Gem::RDoc.load_rdoc rescue Gem::DocumentError => e - skip e.message + pend e.message end Gem.configuration[:rdoc] = nil @@ -85,16 +84,16 @@ def test_remove refute @hook.rdoc_installed? refute @hook.ri_installed? - assert_path_exists @a.doc_dir + assert_path_exist @a.doc_dir end def test_remove_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip 'skipped in root privilege' if Process.uid.zero? + pend 'chmod not supported' if Gem.win_platform? + pend 'skipped in root privilege' if Process.uid.zero? FileUtils.mkdir_p @a.base_dir FileUtils.chmod 0, @a.base_dir - e = assert_raises Gem::FilePermissionError do + e = assert_raise Gem::FilePermissionError do @hook.remove end @@ -114,16 +113,16 @@ def test_ri_installed? def test_setup @hook.setup - assert_path_exists @a.doc_dir + assert_path_exist @a.doc_dir end def test_setup_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip 'skipped in root privilege' if Process.uid.zero? + pend 'chmod not supported' if Gem.win_platform? + pend 'skipped in root privilege' if Process.uid.zero? FileUtils.mkdir_p @a.doc_dir FileUtils.chmod 0, @a.doc_dir - e = assert_raises Gem::FilePermissionError do + e = assert_raise Gem::FilePermissionError do @hook.setup end @@ -134,5 +133,4 @@ def test_setup_unwritable FileUtils.rm_r @a.doc_dir end end - end diff --git a/ruby/test/rubygems/test_gem_remote_fetcher.rb b/ruby/test/rubygems/test_gem_remote_fetcher.rb index 76a66af86..3ce9be7c9 100644 --- a/ruby/test/rubygems/test_gem_remote_fetcher.rb +++ b/ruby/test/rubygems/test_gem_remote_fetcher.rb @@ -1,21 +1,15 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'webrick' -begin - require 'webrick/https' -rescue LoadError => e - raise unless (e.respond_to?(:path) && e.path == 'openssl') || - e.message =~ / -- openssl$/ -end +require 'webrick/https' if Gem::HAVE_OPENSSL -unless defined?(OpenSSL::SSL) - warn 'Skipping Gem::Request tests. openssl not found.' +unless Gem::HAVE_OPENSSL + warn 'Skipping Gem::RemoteFetcher tests. openssl not found.' end require 'rubygems/remote_fetcher' require 'rubygems/package' -require 'minitest/mock' # = Testing Proxy Settings # @@ -32,7 +26,6 @@ # proxy is configured. class TestGemRemoteFetcher < Gem::TestCase - include Gem::DefaultUserInteraction SERVER_DATA = <<-EOY.freeze @@ -78,12 +71,10 @@ class TestGemRemoteFetcher < Gem::TestCase PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2') - DIR = File.expand_path(File.dirname(__FILE__)) - # Generated via: # x = OpenSSL::PKey::DH.new(2048) # wait a while... # x.to_s => pem - TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_ + TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_ -----BEGIN DH PARAMETERS----- MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM @@ -92,7 +83,7 @@ class TestGemRemoteFetcher < Gem::TestCase NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== -----END DH PARAMETERS----- - _end_of_pem_ + _END_OF_PEM_ def setup @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY] @@ -100,20 +91,17 @@ def setup @proxies.each {|k| ENV[k] = nil } super - self.class.start_servers - self.class.enable_yaml = true - self.class.enable_zip = false + start_servers + self.enable_yaml = true + self.enable_zip = false - base_server_uri = "http://localhost:#{self.class.normal_server_port}" - @proxy_uri = "http://localhost:#{self.class.proxy_server_port}" + base_server_uri = "http://localhost:#{normal_server_port}" + @proxy_uri = "http://localhost:#{proxy_server_port}" @server_uri = base_server_uri + "/yaml" @server_z_uri = base_server_uri + "/yaml.Z" - # REFACTOR: copied from test_gem_dependency_installer.rb - @gems_dir = File.join @tempdir, 'gems' @cache_dir = File.join @gemhome, "cache" - FileUtils.mkdir @gems_dir # TODO: why does the remote fetcher need it written to disk? @a1, @a1_gem = util_gem 'a', '1' do |s| @@ -129,7 +117,7 @@ def setup def teardown @fetcher.close_all - self.class.stop_servers + stop_servers super Gem.configuration[:http_proxy] = nil @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] } @@ -153,42 +141,22 @@ def test_self_fetcher_with_proxy assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy).to_s end - def test_fetch_size_bad_uri + def test_fetch_path_bad_uri fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher - e = assert_raises ArgumentError do - Gem::Deprecate.skip_during do - fetcher.fetch_size 'gems.example.com/yaml' - end + e = assert_raise ArgumentError do + @fetcher.fetch_path("gems.example.com/yaml", nil, true) end assert_equal 'uri scheme is invalid: nil', e.message end - def test_fetch_size_socket_error - fetcher = Gem::RemoteFetcher.new nil - @fetcher = fetcher - def fetcher.request(uri, request_class, last_modified = nil) - raise SocketError, "oops" - end - - uri = 'http://gems.example.com/yaml' - e = assert_raises Gem::RemoteFetcher::FetchError do - Gem::Deprecate.skip_during do - fetcher.fetch_size uri - end - end - - assert_equal "SocketError: oops (#{uri})", e.message - end - def test_no_proxy use_ui @stub_ui do assert_data_from_server @fetcher.fetch_path(@server_uri) - Gem::Deprecate.skip_during do - assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri) - end + response = @fetcher.fetch_path(@server_uri, nil, true) + assert_equal SERVER_DATA.size, response['content-length'].to_i end end @@ -205,6 +173,21 @@ def test_cache_update_path assert_equal 'hello', File.read(path) end + def test_cache_update_path_with_utf8_internal_encoding + with_internal_encoding('UTF-8') do + uri = URI 'http://example/file' + path = File.join @tempdir, 'file' + data = String.new("\xC8").force_encoding(Encoding::BINARY) + + fetcher = util_fuck_with_fetcher data + + written_data = fetcher.cache_update_path uri, path + + assert_equal data, written_data + assert_equal data, File.binread(path) + end + end + def test_cache_update_path_no_update uri = URI 'http://example/file' path = File.join @tempdir, 'file' @@ -215,7 +198,7 @@ def test_cache_update_path_no_update assert_equal 'hello', data - refute_path_exists path + assert_path_not_exist path end def util_fuck_with_fetcher(data, blow = false) @@ -236,7 +219,7 @@ def self.fetch_path(arg, *rest) @test_data end - raise Gem::RemoteFetcher::FetchError.new("haha!", nil) + raise Gem::RemoteFetcher::FetchError.new("haha!", '') end end @@ -273,6 +256,36 @@ def test_download_with_auth assert File.exist?(a1_cache_gem) end + def test_download_with_token + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + fetcher = util_fuck_with_fetcher a1_data + + a1_cache_gem = @a1.cache_file + assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token@gems.example.com') + assert_equal("http://token@gems.example.com/gems/a-1.gem", + fetcher.instance_variable_get(:@test_arg).to_s) + assert File.exist?(a1_cache_gem) + end + + def test_download_with_x_oauth_basic + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + fetcher = util_fuck_with_fetcher a1_data + + a1_cache_gem = @a1.cache_file + assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token:x-oauth-basic@gems.example.com') + assert_equal("http://token:x-oauth-basic@gems.example.com/gems/a-1.gem", + fetcher.instance_variable_get(:@test_arg).to_s) + assert File.exist?(a1_cache_gem) + end + def test_download_with_encoded_auth a1_data = nil File.open @a1_gem, 'rb' do |fp| @@ -348,6 +361,8 @@ def test_download_local_read_only local_path = File.join @tempdir, @a1.file_name inst = nil FileUtils.chmod 0555, @a1.cache_dir + FileUtils.mkdir_p File.join(Gem.user_dir, "cache") rescue nil + FileUtils.chmod 0555, File.join(Gem.user_dir, "cache") Dir.chdir @tempdir do inst = Gem::RemoteFetcher.fetcher @@ -356,6 +371,7 @@ def test_download_local_read_only assert_equal(File.join(@tempdir, @a1.file_name), inst.download(@a1, local_path)) ensure + FileUtils.chmod 0755, File.join(Gem.user_dir, "cache") FileUtils.chmod 0755, @a1.cache_dir end @@ -418,7 +434,7 @@ def test_download_same_file def test_download_unsupported inst = Gem::RemoteFetcher.fetcher - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do inst.download @a1, 'ftp://gems.rubyforge.org' end @@ -479,7 +495,7 @@ def fetcher.fetch_http(*) url = 'http://example.com/uri' - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path url end @@ -497,7 +513,7 @@ def fetcher.fetch_http(uri, mtime, head = nil) url = 'http://example.com/uri' - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path url end @@ -515,11 +531,49 @@ def fetcher.fetch_http(uri, mtime = nil, head = nil) url = 'http://example.com/uri' - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path url end - assert_match %r|ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z|, + assert_match %r{ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z}, + e.message + assert_equal url, e.uri + end + + def test_fetch_path_timeout_error + fetcher = Gem::RemoteFetcher.new nil + @fetcher = fetcher + + def fetcher.fetch_http(uri, mtime = nil, head = nil) + raise Timeout::Error, 'timed out' + end + + url = 'http://example.com/uri' + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_path url + end + + assert_match %r{Timeout::Error: timed out \(#{Regexp.escape url}\)\z}, + e.message + assert_equal url, e.uri + end + + def test_fetch_path_getaddrinfo_error + fetcher = Gem::RemoteFetcher.new nil + @fetcher = fetcher + + def fetcher.fetch_http(uri, mtime = nil, head = nil) + raise SocketError, 'getaddrinfo: nodename nor servname provided' + end + + url = 'http://example.com/uri' + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_path url + end + + assert_match %r{SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z}, e.message assert_equal url, e.uri end @@ -534,7 +588,7 @@ def fetcher.fetch_http(uri, mtime = nil, head = nil) url = 'http://example.com/uri' - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path url end @@ -624,7 +678,7 @@ def fetcher.request(uri, request_class, last_modified = nil) res end - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_http URI.parse(url) end @@ -641,7 +695,7 @@ def fetcher.request(uri, request_class, last_modified = nil) res end - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_http URI.parse(url) end @@ -691,7 +745,7 @@ def s3_uri_signer.ec2_metadata_credentials_json def test_fetch_s3_config_creds Gem.configuration[:s3_source] = { - 'my-bucket' => {:id => 'testuser', :secret => 'testpass'} + 'my-bucket' => {:id => 'testuser', :secret => 'testpass'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do @@ -703,7 +757,7 @@ def test_fetch_s3_config_creds def test_fetch_s3_config_creds_with_region Gem.configuration[:s3_source] = { - 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :region => 'us-west-2'} + 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :region => 'us-west-2'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do @@ -715,7 +769,7 @@ def test_fetch_s3_config_creds_with_region def test_fetch_s3_config_creds_with_token Gem.configuration[:s3_source] = { - 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :security_token => 'testtoken'} + 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :security_token => 'testtoken'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do @@ -730,14 +784,14 @@ def test_fetch_s3_env_creds ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass' ENV['AWS_SESSION_TOKEN'] = nil Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'env'} + 'my-bucket' => {:provider => 'env'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b' end ensure - ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')} + ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') } Gem.configuration[:s3_source] = nil end @@ -746,14 +800,14 @@ def test_fetch_s3_env_creds_with_region ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass' ENV['AWS_SESSION_TOKEN'] = nil Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'env', :region => 'us-west-2'} + 'my-bucket' => {:provider => 'env', :region => 'us-west-2'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do assert_fetch_s3 url, '4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9', nil, 'us-west-2' end ensure - ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')} + ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') } Gem.configuration[:s3_source] = nil end @@ -762,14 +816,14 @@ def test_fetch_s3_env_creds_with_token ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass' ENV['AWS_SESSION_TOKEN'] = 'testtoken' Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'env'} + 'my-bucket' => {:provider => 'env'}, } url = 's3://my-bucket/gems/specs.4.8.gz' Time.stub :now, Time.at(1561353581) do assert_fetch_s3 url, '935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c', 'testtoken' end ensure - ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')} + ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') } Gem.configuration[:s3_source] = nil end @@ -782,7 +836,7 @@ def test_fetch_s3_url_creds def test_fetch_s3_instance_profile_creds Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'instance_profile'} + 'my-bucket' => {:provider => 'instance_profile'}, } url = 's3://my-bucket/gems/specs.4.8.gz' @@ -796,7 +850,7 @@ def test_fetch_s3_instance_profile_creds def test_fetch_s3_instance_profile_creds_with_region Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'instance_profile', :region => 'us-west-2'} + 'my-bucket' => {:provider => 'instance_profile', :region => 'us-west-2'}, } url = 's3://my-bucket/gems/specs.4.8.gz' @@ -810,7 +864,7 @@ def test_fetch_s3_instance_profile_creds_with_region def test_fetch_s3_instance_profile_creds_with_token Gem.configuration[:s3_source] = { - 'my-bucket' => {:provider => 'instance_profile'} + 'my-bucket' => {:provider => 'instance_profile'}, } url = 's3://my-bucket/gems/specs.4.8.gz' @@ -826,7 +880,7 @@ def refute_fetch_s3(url, expected_message) fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_s3 URI.parse(url) end @@ -840,7 +894,7 @@ def test_fetch_s3_no_source_key def test_fetch_s3_no_host Gem.configuration[:s3_source] = { - 'my-bucket' => {:id => 'testuser', :secret => 'testpass'} + 'my-bucket' => {:id => 'testuser', :secret => 'testpass'}, } url = 's3://other-bucket/gems/specs.4.8.gz' @@ -901,7 +955,7 @@ def test_request_block def test_yaml_error_on_size use_ui @stub_ui do - self.class.enable_yaml = false + self.enable_yaml = false fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_error { fetcher.size } @@ -909,23 +963,20 @@ def test_yaml_error_on_size end def test_ssl_connection - ssl_server = self.class.start_ssl_server - temp_ca_cert = File.join(DIR, 'ca_cert.pem') + ssl_server = start_ssl_server + temp_ca_cert = File.join(__dir__, 'ca_cert.pem') with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher| fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end end def test_ssl_client_cert_auth_connection - skip 'openssl is missing' unless defined?(OpenSSL::SSL) - skip 'openssl in jruby fails' if java_platform? - - ssl_server = self.class.start_ssl_server({ + ssl_server = start_ssl_server({ :SSLVerifyClient => OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT}) - temp_ca_cert = File.join(DIR, 'ca_cert.pem') - temp_client_cert = File.join(DIR, 'client.pem') + temp_ca_cert = File.join(__dir__, 'ca_cert.pem') + temp_client_cert = File.join(__dir__, 'client.pem') with_configured_fetcher( ":ssl_ca_cert: #{temp_ca_cert}\n" + @@ -935,48 +986,46 @@ def test_ssl_client_cert_auth_connection end def test_do_not_allow_invalid_client_cert_auth_connection - skip 'openssl is missing' unless defined?(OpenSSL::SSL) - - ssl_server = self.class.start_ssl_server({ + ssl_server = start_ssl_server({ :SSLVerifyClient => OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT}) - temp_ca_cert = File.join(DIR, 'ca_cert.pem') - temp_client_cert = File.join(DIR, 'invalid_client.pem') + temp_ca_cert = File.join(__dir__, 'ca_cert.pem') + temp_client_cert = File.join(__dir__, 'invalid_client.pem') with_configured_fetcher( ":ssl_ca_cert: #{temp_ca_cert}\n" + ":ssl_client_cert: #{temp_client_cert}\n") do |fetcher| - assert_raises Gem::RemoteFetcher::FetchError do + assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end end end def test_do_not_allow_insecure_ssl_connection_by_default - ssl_server = self.class.start_ssl_server + ssl_server = start_ssl_server with_configured_fetcher do |fetcher| - assert_raises Gem::RemoteFetcher::FetchError do + assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end end end def test_ssl_connection_allow_verify_none - ssl_server = self.class.start_ssl_server + ssl_server = start_ssl_server with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher| fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end end def test_do_not_follow_insecure_redirect - ssl_server = self.class.start_ssl_server - temp_ca_cert = File.join(DIR, 'ca_cert.pem') + ssl_server = start_ssl_server + temp_ca_cert = File.join(__dir__, 'ca_cert.pem') expected_error_message = "redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri})" with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher| - err = assert_raises Gem::RemoteFetcher::FetchError do + err = assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri}") end @@ -985,11 +1034,11 @@ def test_do_not_follow_insecure_redirect end def test_nil_ca_cert - ssl_server = self.class.start_ssl_server + ssl_server = start_ssl_server temp_ca_cert = nil with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher| - assert_raises Gem::RemoteFetcher::FetchError do + assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}") end end @@ -1031,157 +1080,147 @@ def assert_data_from_proxy(data) end class NilLog < WEBrick::Log - def log(level, data) #Do nothing end - end - class << self + private - attr_reader :normal_server, :proxy_server - attr_accessor :enable_zip, :enable_yaml + attr_reader :normal_server, :proxy_server + attr_accessor :enable_zip, :enable_yaml - def start_servers - @normal_server ||= start_server(SERVER_DATA) - @proxy_server ||= start_server(PROXY_DATA) - @enable_yaml = true - @enable_zip = false - @ssl_server = nil - @ssl_server_thread = nil - end + def start_servers + @normal_server ||= start_server(SERVER_DATA) + @proxy_server ||= start_server(PROXY_DATA) + @enable_yaml = true + @enable_zip = false + @ssl_server = nil + @ssl_server_thread = nil + end - def stop_servers - if @normal_server - @normal_server.kill.join - @normal_server = nil - end - if @proxy_server - @proxy_server.kill.join - @proxy_server = nil - end - if @ssl_server - @ssl_server.stop - @ssl_server = nil - end - if @ssl_server_thread - @ssl_server_thread.kill.join - @ssl_server_thread = nil - end - utils = WEBrick::Utils # TimeoutHandler is since 1.9 - utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate) + def stop_servers + if @normal_server + @normal_server.kill.join + @normal_server = nil end - - def normal_server_port - @normal_server[:server].config[:Port] + if @proxy_server + @proxy_server.kill.join + @proxy_server = nil end - - def proxy_server_port - @proxy_server[:server].config[:Port] + if @ssl_server + @ssl_server.stop + @ssl_server = nil + end + if @ssl_server_thread + @ssl_server_thread.kill.join + @ssl_server_thread = nil end + utils = WEBrick::Utils # TimeoutHandler is since 1.9 + utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate) + end - DIR = File.expand_path(File.dirname(__FILE__)) + def normal_server_port + @normal_server[:server].config[:Port] + end - def start_ssl_server(config = {}) - raise MiniTest::Skip, 'openssl not installed' unless - defined?(OpenSSL::SSL) + def proxy_server_port + @proxy_server[:server].config[:Port] + end - null_logger = NilLog.new - server = WEBrick::HTTPServer.new({ - :Port => 0, - :Logger => null_logger, - :AccessLog => [], - :SSLEnable => true, - :SSLCACertificateFile => File.join(DIR, 'ca_cert.pem'), - :SSLCertificate => cert('ssl_cert.pem'), - :SSLPrivateKey => key('ssl_key.pem'), - :SSLVerifyClient => nil, - :SSLCertName => nil - }.merge(config)) - server.mount_proc("/yaml") do |req, res| - res.body = "--- true\n" - end - server.mount_proc("/insecure_redirect") do |req, res| - res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query['to']) - end - server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 } - t = Thread.new do - begin - server.start - rescue Exception => ex - abort ex.message - puts "ERROR during server thread: #{ex.message}" - ensure - server.shutdown - end - end - while server.status != :Running - sleep 0.1 - unless t.alive? - t.join - raise - end - end - @ssl_server = server - @ssl_server_thread = t - server - end - - private - - def start_server(data) - null_logger = NilLog.new - s = WEBrick::HTTPServer.new( - :Port => 0, - :DocumentRoot => nil, - :Logger => null_logger, - :AccessLog => null_logger - ) - s.mount_proc("/kill") { |req, res| s.shutdown } - s.mount_proc("/yaml") do |req, res| - if req["X-Captain"] - res.body = req["X-Captain"] - elsif @enable_yaml - res.body = data - res['Content-Type'] = 'text/plain' - res['content-length'] = data.size - else - res.status = "404" - res.body = "

      NOT FOUND

      " - res['Content-Type'] = 'text/html' - end + def start_ssl_server(config = {}) + pend "starting this test server fails randomly on jruby" if Gem.java_platform? + + null_logger = NilLog.new + server = WEBrick::HTTPServer.new({ + :Port => 0, + :Logger => null_logger, + :AccessLog => [], + :SSLEnable => true, + :SSLCACertificateFile => File.join(__dir__, 'ca_cert.pem'), + :SSLCertificate => cert('ssl_cert.pem'), + :SSLPrivateKey => key('ssl_key.pem'), + :SSLVerifyClient => nil, + :SSLCertName => nil, + }.merge(config)) + server.mount_proc("/yaml") do |req, res| + res.body = "--- true\n" + end + server.mount_proc("/insecure_redirect") do |req, res| + res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query['to']) + end + server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 } + t = Thread.new do + begin + server.start + rescue Exception => ex + puts "ERROR during server thread: #{ex.message}" + raise + ensure + server.shutdown end - s.mount_proc("/yaml.Z") do |req, res| - if @enable_zip - res.body = Zlib::Deflate.deflate(data) - res['Content-Type'] = 'text/plain' - else - res.status = "404" - res.body = "

      NOT FOUND

      " - res['Content-Type'] = 'text/html' - end + end + while server.status != :Running + sleep 0.1 + unless t.alive? + t.join + raise end - th = Thread.new do - begin - s.start - rescue Exception => ex - abort "ERROR during server thread: #{ex.message}" - ensure - s.shutdown - end + end + @ssl_server = server + @ssl_server_thread = t + server + end + + def start_server(data) + null_logger = NilLog.new + s = WEBrick::HTTPServer.new( + :Port => 0, + :DocumentRoot => nil, + :Logger => null_logger, + :AccessLog => null_logger + ) + s.mount_proc("/kill") {|req, res| s.shutdown } + s.mount_proc("/yaml") do |req, res| + if req["X-Captain"] + res.body = req["X-Captain"] + elsif @enable_yaml + res.body = data + res['Content-Type'] = 'text/plain' + res['content-length'] = data.size + else + res.status = "404" + res.body = "

      NOT FOUND

      " + res['Content-Type'] = 'text/html' end - th[:server] = s - th end - - def cert(filename) - OpenSSL::X509::Certificate.new(File.read(File.join(DIR, filename))) + s.mount_proc("/yaml.Z") do |req, res| + if @enable_zip + res.body = Zlib::Deflate.deflate(data) + res['Content-Type'] = 'text/plain' + else + res.status = "404" + res.body = "

      NOT FOUND

      " + res['Content-Type'] = 'text/html' + end end - - def key(filename) - OpenSSL::PKey::RSA.new(File.read(File.join(DIR, filename))) + th = Thread.new do + begin + s.start + rescue Exception => ex + abort "ERROR during server thread: #{ex.message}" + ensure + s.shutdown + end end + th[:server] = s + th + end + def cert(filename) + OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename))) end -end if defined?(OpenSSL::SSL) + def key(filename) + OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename))) + end +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_gem_request.rb b/ruby/test/rubygems/test_gem_request.rb index 2a756eaad..47654f6fa 100644 --- a/ruby/test/rubygems/test_gem_request.rb +++ b/ruby/test/rubygems/test_gem_request.rb @@ -1,15 +1,14 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request' require 'ostruct' require 'base64' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping Gem::Request tests. openssl not found.' end class TestGemRequest < Gem::TestCase - CA_CERT_FILE = cert_path 'ca' CHILD_CERT = load_cert 'child' EXPIRED_CERT = load_cert 'expired' @@ -186,7 +185,7 @@ def test_get_proxy_from_env_empty end def test_fetch - uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}" + uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") response = util_stub_net_http(:body => :junk, :code => 200) do @request = make_request(uri, Net::HTTP::Get, nil, nil) @@ -198,31 +197,57 @@ def test_fetch end def test_fetch_basic_auth - uri = URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}" + Gem.configuration.verbose = :really + uri = Gem::Uri.new(URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}") conn = util_stub_net_http(:body => :junk, :code => 200) do |c| - @request = make_request(uri, Net::HTTP::Get, nil, nil) - @request.fetch + use_ui @ui do + @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request.fetch + end c end auth_header = conn.payload['Authorization'] assert_equal "Basic #{Base64.encode64('user:pass')}".strip, auth_header + assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}" end def test_fetch_basic_auth_encoded - uri = URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}" + Gem.configuration.verbose = :really + uri = Gem::Uri.new(URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}") + conn = util_stub_net_http(:body => :junk, :code => 200) do |c| - @request = make_request(uri, Net::HTTP::Get, nil, nil) - @request.fetch + use_ui @ui do + @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request.fetch + end c end auth_header = conn.payload['Authorization'] assert_equal "Basic #{Base64.encode64('user:{DEScede}pass')}".strip, auth_header + assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}" + end + + def test_fetch_basic_oauth_encoded + Gem.configuration.verbose = :really + uri = Gem::Uri.new(URI.parse "https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}") + + conn = util_stub_net_http(:body => :junk, :code => 200) do |c| + use_ui @ui do + @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request.fetch + end + c + end + + auth_header = conn.payload['Authorization'] + assert_equal "Basic #{Base64.encode64('{DEScede}pass:x-oauth-basic')}".strip, auth_header + assert_includes @ui.output, "GET https://REDACTED:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}" end def test_fetch_head - uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}" + uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") response = util_stub_net_http(:body => '', :code => 200) do |conn| @request = make_request(uri, Net::HTTP::Get, nil, nil) @request.fetch @@ -233,7 +258,7 @@ def test_fetch_head end def test_fetch_unmodified - uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}" + uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") t = Time.utc(2013, 1, 2, 3, 4, 5) conn, response = util_stub_net_http(:body => '', :code => 304) do |c| @request = make_request(uri, Net::HTTP::Get, t, nil) @@ -251,11 +276,11 @@ def test_fetch_unmodified def test_user_agent ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r%^RubyGems/\S+ \S+ Ruby/\S+ \(.*?\)%, ua - assert_match %r%RubyGems/#{Regexp.escape Gem::VERSION}%, ua - assert_match %r% #{Regexp.escape Gem::Platform.local.to_s} %, ua - assert_match %r%Ruby/#{Regexp.escape RUBY_VERSION}%, ua - assert_match %r%\(#{Regexp.escape RUBY_RELEASE_DATE} %, ua + assert_match %r{^RubyGems/\S+ \S+ Ruby/\S+ \(.*?\)}, ua + assert_match %r{RubyGems/#{Regexp.escape Gem::VERSION}}, ua + assert_match %r{ #{Regexp.escape Gem::Platform.local.to_s} }, ua + assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}}, ua + assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE} }, ua end def test_user_agent_engine @@ -266,7 +291,7 @@ def test_user_agent_engine ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r%\) vroom%, ua + assert_match %r{\) vroom}, ua ensure util_restore_version end @@ -279,7 +304,7 @@ def test_user_agent_engine_ruby ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r%\)%, ua + assert_match %r{\)}, ua ensure util_restore_version end @@ -292,7 +317,7 @@ def test_user_agent_patchlevel ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r% patchlevel 5\)%, ua + assert_match %r{ patchlevel 5\)}, ua ensure util_restore_version end @@ -307,8 +332,8 @@ def test_user_agent_revision ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r% revision 6\)%, ua - assert_match %r%Ruby/#{Regexp.escape RUBY_VERSION}dev%, ua + assert_match %r{ revision 6\)}, ua + assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}dev}, ua ensure util_restore_version end @@ -322,37 +347,43 @@ def test_user_agent_revision_missing ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r%\(#{Regexp.escape RUBY_RELEASE_DATE}\)%, ua + assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE}\)}, ua ensure util_restore_version end def test_verify_certificate - skip if Gem.java_platform? + pend if Gem.java_platform? + + error_number = OpenSSL::X509::V_ERR_OUT_OF_MEM + store = OpenSSL::X509::Store.new context = OpenSSL::X509::StoreContext.new store - context.error = OpenSSL::X509::V_ERR_OUT_OF_MEM + context.error = error_number use_ui @ui do Gem::Request.verify_certificate context end - assert_equal "ERROR: SSL verification error at depth 0: out of memory (17)\n", + assert_equal "ERROR: SSL verification error at depth 0: out of memory (#{error_number})\n", @ui.error end def test_verify_certificate_extra_message - skip if Gem.java_platform? + pend if Gem.java_platform? + + error_number = OpenSSL::X509::V_ERR_INVALID_CA + store = OpenSSL::X509::Store.new context = OpenSSL::X509::StoreContext.new store - context.error = OpenSSL::X509::V_ERR_INVALID_CA + context.error = error_number use_ui @ui do Gem::Request.verify_certificate context end expected = <<-ERROR -ERROR: SSL verification error at depth 0: invalid CA certificate (24) +ERROR: SSL verification error at depth 0: invalid CA certificate (#{error_number}) ERROR: Certificate is an invalid CA certificate ERROR @@ -488,7 +519,6 @@ def util_stub_net_http(hash) end class Conn - attr_accessor :payload def new(*args); self; end @@ -507,7 +537,5 @@ def request(req) self.payload = req @response end - end - -end if defined?(OpenSSL::SSL) +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_gem_request_connection_pools.rb b/ruby/test/rubygems/test_gem_request_connection_pools.rb index f8d209516..c5e7cf2ed 100644 --- a/ruby/test/rubygems/test_gem_request_connection_pools.rb +++ b/ruby/test/rubygems/test_gem_request_connection_pools.rb @@ -1,18 +1,15 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request' require 'timeout' class TestGemRequestConnectionPool < Gem::TestCase - class FakeHttp - def initialize(*args) end def start end - end def setup @@ -143,12 +140,11 @@ def test_thread_waits_for_connection pool.checkout Thread.new do - assert_raises(Timeout::Error) do + assert_raise(Timeout::Error) do Timeout.timeout(1) do pool.checkout end end end.join end - end diff --git a/ruby/test/rubygems/test_gem_request_set.rb b/ruby/test/rubygems/test_gem_request_set.rb index ac344015e..e2fe98b9b 100644 --- a/ruby/test/rubygems/test_gem_request_set.rb +++ b/ruby/test/rubygems/test_gem_request_set.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request_set' class TestGemRequestSet < Gem::TestCase - def setup super @@ -65,8 +64,8 @@ def test_install_from_gemdeps end assert_includes installed, 'a-2' - assert_path_exists File.join @gemhome, 'gems', 'a-2' - assert_path_exists 'gem.deps.rb.lock' + assert_path_exist File.join @gemhome, 'gems', 'a-2' + assert_path_exist 'gem.deps.rb.lock' assert rs.remote refute done_installing_ran @@ -88,9 +87,10 @@ def test_install_from_gemdeps_explain a-2 EXPECTED - assert_output expected do + actual, _ = capture_output do rs.install_from_gemdeps :gemdeps => io.path, :explain => true end + assert_equal(expected, actual) end end @@ -100,7 +100,7 @@ def test_install_from_gemdeps_install_dir end util_clear_gems - refute_path_exists File.join Gem.dir, 'gems', 'a-2' + assert_path_not_exist File.join Gem.dir, 'gems', 'a-2' rs = Gem::RequestSet.new installed = [] @@ -119,7 +119,7 @@ def test_install_from_gemdeps_install_dir end assert_includes installed, 'a-2' - refute_path_exists File.join Gem.dir, 'gems', 'a-2' + assert_path_not_exist File.join Gem.dir, 'gems', 'a-2' end def test_install_from_gemdeps_local @@ -133,7 +133,7 @@ def test_install_from_gemdeps_local io.puts 'gem "a"' io.flush - assert_raises Gem::UnsatisfiableDependencyError do + assert_raise Gem::UnsatisfiableDependencyError do rs.install_from_gemdeps :gemdeps => io.path, :domain => :local end end @@ -179,8 +179,60 @@ def test_install_from_gemdeps_lockfile assert_includes installed, 'b-1' assert_includes installed, 'a-1' - assert_path_exists File.join @gemhome, 'specifications', 'a-1.gemspec' - assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec' + end + + def test_install_from_gemdeps_complex_dependencies + quick_gem("z", 1) + quick_gem("z", "1.0.1") + quick_gem("z", "1.0.2") + quick_gem("z", "1.0.3") + quick_gem("z", 2) + + spec_fetcher do |fetcher| + fetcher.download "z", 1 + end + + rs = Gem::RequestSet.new + installed = [] + + File.open 'Gemfile.lock', 'w' do |io| + io.puts <<-LOCKFILE +GEM + remote: #{@gem_repo} + specs: + z (1) + +PLATFORMS + #{Gem::Platform::RUBY} + +DEPENDENCIES + z (~> 1.0, >= 1.0.1) + LOCKFILE + end + + File.open 'testo.gemspec', 'w' do |io| + io.puts <<-LOCKFILE +Gem::Specification.new do |spec| + spec.name = 'testo' + spec.version = '1.0.0' + spec.add_dependency('z', '~> 1.0', '>= 1.0.1') +end + LOCKFILE + end + + File.open 'Gemfile', 'w' do |io| + io.puts("gemspec") + end + + rs.install_from_gemdeps :gemdeps => 'Gemfile' do |req, installer| + installed << req.full_name + end + + assert_includes installed, 'z-1.0.3' + + assert_path_exist File.join @gemhome, 'specifications', 'z-1.0.3.gemspec' end def test_install_from_gemdeps_version_mismatch @@ -272,7 +324,7 @@ def test_resolve res = rs.resolve StaticSet.new([a, b]) assert_equal 2, res.size - names = res.map { |s| s.full_name }.sort + names = res.map {|s| s.full_name }.sort assert_equal ["a-2", "b-2"], names @@ -291,7 +343,7 @@ def test_bug_bug_990 res = rs.resolve StaticSet.new([a, b, c]) assert_equal 3, res.size - names = res.map { |s| s.full_name }.sort + names = res.map {|s| s.full_name }.sort assert_equal %w[a-1.b b-1.b c-1.1.b], names end @@ -344,9 +396,9 @@ def test_resolve_git rs = Gem::RequestSet.new tf = Tempfile.open 'gem.deps.rb' do |io| - io.puts <<-gems_deps_rb + io.puts <<-GEMS_DEPS_RB gem "#{name}", :git => "#{repository}" - gems_deps_rb + GEMS_DEPS_RB io.flush @@ -358,12 +410,12 @@ def test_resolve_git res = rs.resolve assert_equal 1, res.size - names = res.map { |s| s.full_name }.sort + names = res.map {|s| s.full_name }.sort assert_equal %w[a-1], names assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet], - rs.sets.map { |set| set.class } + rs.sets.map {|set| set.class } end def test_resolve_ignore_dependencies @@ -377,7 +429,7 @@ def test_resolve_ignore_dependencies res = rs.resolve StaticSet.new([a, b]) assert_equal 1, res.size - names = res.map { |s| s.full_name }.sort + names = res.map {|s| s.full_name }.sort assert_equal %w[a-2], names end @@ -392,7 +444,7 @@ def test_resolve_incompatible set = StaticSet.new [a1, a2] - assert_raises Gem::UnsatisfiableDependencyError do + assert_raise Gem::UnsatisfiableDependencyError do rs.resolve set end end @@ -407,10 +459,10 @@ def test_resolve_vendor rs = Gem::RequestSet.new tf = Tempfile.open 'gem.deps.rb' do |io| - io.puts <<-gems_deps_rb + io.puts <<-GEMS_DEPS_RB gem "#{a_name}", :path => "#{a_directory}" gem "#{b_name}", :path => "#{b_directory}" - gems_deps_rb + GEMS_DEPS_RB io.flush @@ -422,12 +474,12 @@ def test_resolve_vendor res = rs.resolve assert_equal 2, res.size - names = res.map { |s| s.full_name }.sort + names = res.map {|s| s.full_name }.sort assert_equal ["a-1", "b-2"], names assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet], - rs.sets.map { |set| set.class } + rs.sets.map {|set| set.class } end def test_sorted_requests @@ -440,8 +492,8 @@ def test_sorted_requests rs.resolve StaticSet.new([a, b, c]) - names = rs.sorted_requests.map { |s| s.full_name } - assert_equal %w!c-2 b-2 a-2!, names + names = rs.sorted_requests.map {|s| s.full_name } + assert_equal %w[c-2 b-2 a-2], names end def test_install @@ -469,14 +521,14 @@ def test_install installers << installer end - assert_equal %w[b-1 a-1], reqs.map { |req| req.full_name } + assert_equal %w[b-1 a-1], reqs.map {|req| req.full_name } assert_equal %w[b-1 a-1], - installers.map { |installer| installer.spec.full_name } + installers.map {|installer| installer.spec.full_name } - assert_path_exists File.join @gemhome, 'specifications', 'a-1.gemspec' - assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec' - assert_equal %w[b-1 a-1], installed.map { |s| s.full_name } + assert_equal %w[b-1 a-1], installed.map {|s| s.full_name } assert done_installing_ran end @@ -496,10 +548,10 @@ def test_install_into assert_equal @tempdir, ENV['GEM_HOME'] end - assert_path_exists File.join @tempdir, 'specifications', 'a-1.gemspec' - assert_path_exists File.join @tempdir, 'specifications', 'b-1.gemspec' + assert_path_exist File.join @tempdir, 'specifications', 'a-1.gemspec' + assert_path_exist File.join @tempdir, 'specifications', 'b-1.gemspec' - assert_equal %w!b-1 a-1!, installed.map { |s| s.full_name } + assert_equal %w[b-1 a-1], installed.map {|s| s.full_name } end def test_install_into_development_shallow @@ -531,7 +583,7 @@ def test_install_into_development_shallow assert_equal @tempdir, ENV['GEM_HOME'] end - assert_equal %w[a-1 b-1], installed.map { |s| s.full_name }.sort + assert_equal %w[a-1 b-1], installed.map {|s| s.full_name }.sort end def test_sorted_requests_development_shallow @@ -556,7 +608,7 @@ def test_sorted_requests_development_shallow rs.resolve StaticSet.new [a_spec, b_spec, c_spec] - assert_equal %w[b-1 a-1], rs.sorted_requests.map { |req| req.full_name } + assert_equal %w[b-1 a-1], rs.sorted_requests.map {|req| req.full_name } end def test_tsort_each_child_development @@ -585,7 +637,7 @@ def test_tsort_each_child_development deps = rs.enum_for(:tsort_each_child, a_req).to_a - assert_equal %w[b], deps.map { |dep| dep.name } + assert_equal %w[b], deps.map {|dep| dep.name } end def test_tsort_each_child_development_shallow @@ -616,5 +668,4 @@ def test_tsort_each_child_development_shallow assert_empty deps end - end diff --git a/ruby/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/ruby/test/rubygems/test_gem_request_set_gem_dependency_api.rb index f3d4c6fc7..cc4f99df9 100644 --- a/ruby/test/rubygems/test_gem_request_set_gem_dependency_api.rb +++ b/ruby/test/rubygems/test_gem_request_set_gem_dependency_api.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request_set' class TestGemRequestSetGemDependencyAPI < Gem::TestCase - def setup super @@ -49,8 +48,8 @@ def test_gempspec_with_multiple_runtime_deps s.add_runtime_dependency 'bar', '>= 1.6.0', '< 1.6.4' end @gda.gemspec - assert_equal %w{ foo bar }.sort, @set.dependencies.map(&:name).sort - bar = @set.dependencies.find { |d| d.name == 'bar' } + assert_equal %w[ foo bar ].sort, @set.dependencies.map(&:name).sort + bar = @set.dependencies.find {|d| d.name == 'bar' } assert_equal [["<", Gem::Version.create('1.6.4')], [">=", Gem::Version.create('1.6.0')]], bar.requirement.requirements.sort end @@ -82,7 +81,7 @@ def test_gem def test_gem_duplicate @gda.gem 'a' - _, err = capture_io do + _, err = capture_output do @gda.gem 'a' end @@ -130,7 +129,7 @@ def test_gem_bitbucket_expand_path end def test_gem_git_branch - _, err = capture_io do + _, err = capture_output do @gda.gem 'a', :git => 'git/a', :branch => 'other', :tag => 'v1' end expected = "Gem dependencies file gem.deps.rb includes git reference for both ref/branch and tag but only ref/branch is used." @@ -151,7 +150,7 @@ def test_gem_git_gist end def test_gem_git_ref - _, err = capture_io do + _, err = capture_output do @gda.gem 'a', :git => 'git/a', :ref => 'abcd123', :branch => 'other' end expected = "Gem dependencies file gem.deps.rb includes git reference for both ref and branch but only ref is used." @@ -389,7 +388,7 @@ def test_gem_platforms_version end def test_gem_platforms_unknown - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do @gda.gem 'a', :platforms => :unknown end @@ -456,7 +455,7 @@ def test_gem_source_mismatch gda = @GDA.new @set, nil gda.gem name - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do gda.gem name, :path => directory end @@ -467,7 +466,7 @@ def test_gem_source_mismatch gda.instance_variable_set :@vendor_set, @vendor_set gda.gem name, :path => directory - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do gda.gem name end @@ -490,7 +489,7 @@ def test_gem_group_method groups = @gda.send :gem_group, 'a', :group => :b, :groups => [:c, :d] end - assert_equal [:a, :b, :c, :d], groups.sort_by { |group| group.to_s } + assert_equal [:a, :b, :c, :d], groups.sort_by {|group| group.to_s } end def test_gemspec @@ -518,8 +517,8 @@ def test_gemspec def test_gemspec_bad FileUtils.touch 'a.gemspec' - e = assert_raises ArgumentError do - capture_io do + e = assert_raise ArgumentError do + capture_output do @gda.gemspec end end @@ -551,7 +550,7 @@ def test_gemspec_multiple s.add_dependency 'c', 3 end - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do @gda.gemspec end @@ -583,7 +582,7 @@ def test_gemspec_named end def test_gemspec_none - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do @gda.gemspec end @@ -659,14 +658,14 @@ def test_pin_gem_source gda.send :pin_gem_source, 'a' gda.send :pin_gem_source, 'a' - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do gda.send :pin_gem_source, 'a', :path, 'vendor/a' end assert_equal "duplicate source path: vendor/a for gem a", e.message - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do gda.send :pin_gem_source, 'a', :git, 'git://example/repo.git' end @@ -771,7 +770,7 @@ def test_ruby_engine def test_ruby_engine_mismatch_engine with_engine_version 'ruby', '2.0.0' do - e = assert_raises Gem::RubyVersionMismatch do + e = assert_raise Gem::RubyVersionMismatch do @gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4' end @@ -782,7 +781,7 @@ def test_ruby_engine_mismatch_engine def test_ruby_engine_mismatch_version with_engine_version 'jruby', '1.7.6' do - e = assert_raises Gem::RubyVersionMismatch do + e = assert_raise Gem::RubyVersionMismatch do @gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4' end @@ -792,7 +791,7 @@ def test_ruby_engine_mismatch_version end def test_ruby_engine_no_engine_version - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do @gda.ruby RUBY_VERSION, :engine => 'jruby' end @@ -801,7 +800,7 @@ def test_ruby_engine_no_engine_version end def test_ruby_mismatch - e = assert_raises Gem::RubyVersionMismatch do + e = assert_raise Gem::RubyVersionMismatch do @gda.ruby '1.8.0' end @@ -845,5 +844,4 @@ def test_with_engine_version assert_equal engine_version, RUBY_ENGINE_VERSION if engine end - end unless Gem.java_platform? diff --git a/ruby/test/rubygems/test_gem_request_set_lockfile.rb b/ruby/test/rubygems/test_gem_request_set_lockfile.rb index 7c5e256a2..690b632d9 100644 --- a/ruby/test/rubygems/test_gem_request_set_lockfile.rb +++ b/ruby/test/rubygems/test_gem_request_set_lockfile.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request_set' require 'rubygems/request_set/lockfile' class TestGemRequestSetLockfile < Gem::TestCase - def setup super @@ -52,7 +51,7 @@ def test_add_DEPENDENCIES expected = [ 'DEPENDENCIES', ' a', - nil + nil, ] assert_equal expected, out @@ -79,7 +78,7 @@ def test_add_DEPENDENCIES_from_gem_deps expected = [ 'DEPENDENCIES', ' a (~> 2.0)', - nil + nil, ] assert_equal expected, out @@ -112,7 +111,7 @@ def test_add_GEM ' a (2)', ' b', ' b (2)', - nil + nil, ] assert_equal expected, out @@ -140,7 +139,7 @@ def test_add_PLATFORMS 'PLATFORMS', ' ruby', ' x86-darwin-8', - nil + nil, ] assert_equal expected, out @@ -444,7 +443,7 @@ def test_write gem_deps_lock_file = "#{@gem_deps_file}.lock" - assert_path_exists gem_deps_lock_file + assert_path_exist gem_deps_lock_file refute_empty File.read gem_deps_lock_file end @@ -458,13 +457,12 @@ def test_write_error io.write 'hello' end - assert_raises Gem::UnsatisfiableDependencyError do + assert_raise Gem::UnsatisfiableDependencyError do lockfile.write end - assert_path_exists gem_deps_lock_file + assert_path_exist gem_deps_lock_file assert_equal 'hello', File.read(gem_deps_lock_file) end - end diff --git a/ruby/test/rubygems/test_gem_request_set_lockfile_parser.rb b/ruby/test/rubygems/test_gem_request_set_lockfile_parser.rb index 7fc93c36e..4007c3a69 100644 --- a/ruby/test/rubygems/test_gem_request_set_lockfile_parser.rb +++ b/ruby/test/rubygems/test_gem_request_set_lockfile_parser.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request_set' require 'rubygems/request_set/lockfile' require 'rubygems/request_set/lockfile/tokenizer' require 'rubygems/request_set/lockfile/parser' class TestGemRequestSetLockfileParser < Gem::TestCase - def setup super @gem_deps_file = 'gem.deps.rb' @@ -26,7 +25,7 @@ def test_get_type_mismatch tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "foo", filename, 1, 0 parser = tokenizer.make_parser nil, nil - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do parser.get :section end @@ -53,7 +52,7 @@ def test_get_type_value_mismatch tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1 parser = tokenizer.make_parser nil, nil - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do parser.get :text, 'y' end @@ -94,7 +93,7 @@ def test_parse assert lockfile_set, 'could not find a LockSet' - assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name } + assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name } end def test_parse_dependencies @@ -124,7 +123,7 @@ def test_parse_dependencies assert lockfile_set, 'could not find a LockSet' - assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name } + assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name } end def test_parse_DEPENDENCIES_git @@ -218,7 +217,7 @@ def test_parse_GEM assert lockfile_set, 'found a LockSet' - assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name } + assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name } end def test_parse_GEM_remote_multiple @@ -246,10 +245,10 @@ def test_parse_GEM_remote_multiple assert lockfile_set, 'found a LockSet' - assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name } + assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name } assert_equal %w[https://gems.example/ https://other.example/], - lockfile_set.specs.flat_map { |s| s.sources.map{ |src| src.uri.to_s } } + lockfile_set.specs.flat_map {|s| s.sources.map{|src| src.uri.to_s } } end def test_parse_GIT @@ -284,7 +283,7 @@ def test_parse_GIT assert git_set, 'could not find a GitSet' - assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name } + assert_equal %w[a-2], git_set.specs.values.map {|s| s.full_name } assert_equal [dep('b', '>= 3'), dep('c')], git_set.specs.values.first.dependencies @@ -438,7 +437,7 @@ def test_parse_PATH assert vendor_set, 'could not find a VendorSet' - assert_equal %w[a-1], vendor_set.specs.values.map { |s| s.full_name } + assert_equal %w[a-1], vendor_set.specs.values.map {|s| s.full_name } spec = vendor_set.load_spec 'a', nil, nil, nil @@ -497,14 +496,14 @@ def test_parse_gem_specs_dependency assert lockfile_set, 'could not find a LockSet' - assert_equal %w[a-2 b-3], lockfile_set.specs.map { |tuple| tuple.full_name } + assert_equal %w[a-2 b-3], lockfile_set.specs.map {|tuple| tuple.full_name } expected = [ Gem::Platform::RUBY, Gem::Platform.new('x86_64-linux'), ] - assert_equal expected, lockfile_set.specs.map { |tuple| tuple.platform } + assert_equal expected, lockfile_set.specs.map {|tuple| tuple.platform } spec = lockfile_set.specs.first @@ -519,7 +518,7 @@ def test_parse_gem_specs_dependency end def test_parse_missing - assert_raises(Errno::ENOENT) do + assert_raise(Errno::ENOENT) do parse_lockfile @set, [] end @@ -541,5 +540,4 @@ def parse_lockfile(set, platforms) parser = tokenizer.make_parser set, platforms parser.parse end - end diff --git a/ruby/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/ruby/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb index aa91fc446..f779c3301 100644 --- a/ruby/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +++ b/ruby/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/request_set' require 'rubygems/request_set/lockfile' require 'rubygems/request_set/lockfile/tokenizer' require 'rubygems/request_set/lockfile/parser' class TestGemRequestSetLockfileTokenizer < Gem::TestCase - def setup super @@ -64,86 +63,86 @@ def test_tokenize LOCKFILE expected = [ - [:section, 'GEM', 0, 0], - [:newline, nil, 3, 0], - - [:entry, 'remote', 2, 1], - [:text, @gem_repo, 10, 1], - [:newline, nil, 34, 1], - - [:entry, 'specs', 2, 2], - [:newline, nil, 8, 2], - - [:text, 'a', 4, 3], - [:l_paren, nil, 6, 3], - [:text, '2', 7, 3], - [:r_paren, nil, 8, 3], - [:newline, nil, 9, 3], - - [:text, 'b', 6, 4], - [:l_paren, nil, 8, 4], - [:requirement, '=', 9, 4], - [:text, '2', 11, 4], - [:r_paren, nil, 12, 4], - [:newline, nil, 13, 4], - - [:text, 'c', 6, 5], - [:l_paren, nil, 8, 5], - [:requirement, '!=', 9, 5], - [:text, '3', 12, 5], - [:r_paren, nil, 13, 5], - [:newline, nil, 14, 5], - - [:text, 'd', 6, 6], - [:l_paren, nil, 8, 6], - [:requirement, '>', 9, 6], - [:text, '4', 11, 6], - [:r_paren, nil, 12, 6], - [:newline, nil, 13, 6], - - [:text, 'e', 6, 7], - [:l_paren, nil, 8, 7], - [:requirement, '<', 9, 7], - [:text, '5', 11, 7], - [:r_paren, nil, 12, 7], - [:newline, nil, 13, 7], - - [:text, 'f', 6, 8], - [:l_paren, nil, 8, 8], - [:requirement, '>=', 9, 8], - [:text, '6', 12, 8], - [:r_paren, nil, 13, 8], - [:newline, nil, 14, 8], - - [:text, 'g', 6, 9], - [:l_paren, nil, 8, 9], - [:requirement, '<=', 9, 9], - [:text, '7', 12, 9], - [:r_paren, nil, 13, 9], - [:newline, nil, 14, 9], - - [:text, 'h', 6, 10], - [:l_paren, nil, 8, 10], - [:requirement, '~>', 9, 10], + [:section, 'GEM', 0, 0], + [:newline, nil, 3, 0], + + [:entry, 'remote', 2, 1], + [:text, @gem_repo, 10, 1], + [:newline, nil, 34, 1], + + [:entry, 'specs', 2, 2], + [:newline, nil, 8, 2], + + [:text, 'a', 4, 3], + [:l_paren, nil, 6, 3], + [:text, '2', 7, 3], + [:r_paren, nil, 8, 3], + [:newline, nil, 9, 3], + + [:text, 'b', 6, 4], + [:l_paren, nil, 8, 4], + [:requirement, '=', 9, 4], + [:text, '2', 11, 4], + [:r_paren, nil, 12, 4], + [:newline, nil, 13, 4], + + [:text, 'c', 6, 5], + [:l_paren, nil, 8, 5], + [:requirement, '!=', 9, 5], + [:text, '3', 12, 5], + [:r_paren, nil, 13, 5], + [:newline, nil, 14, 5], + + [:text, 'd', 6, 6], + [:l_paren, nil, 8, 6], + [:requirement, '>', 9, 6], + [:text, '4', 11, 6], + [:r_paren, nil, 12, 6], + [:newline, nil, 13, 6], + + [:text, 'e', 6, 7], + [:l_paren, nil, 8, 7], + [:requirement, '<', 9, 7], + [:text, '5', 11, 7], + [:r_paren, nil, 12, 7], + [:newline, nil, 13, 7], + + [:text, 'f', 6, 8], + [:l_paren, nil, 8, 8], + [:requirement, '>=', 9, 8], + [:text, '6', 12, 8], + [:r_paren, nil, 13, 8], + [:newline, nil, 14, 8], + + [:text, 'g', 6, 9], + [:l_paren, nil, 8, 9], + [:requirement, '<=', 9, 9], + [:text, '7', 12, 9], + [:r_paren, nil, 13, 9], + [:newline, nil, 14, 9], + + [:text, 'h', 6, 10], + [:l_paren, nil, 8, 10], + [:requirement, '~>', 9, 10], [:text, '8', 12, 10], [:r_paren, nil, 13, 10], [:newline, nil, 14, 10], - [:newline, nil, 0, 11], + [:newline, nil, 0, 11], - [:section, 'PLATFORMS', 0, 12], - [:newline, nil, 9, 12], + [:section, 'PLATFORMS', 0, 12], + [:newline, nil, 9, 12], - [:text, Gem::Platform::RUBY, 2, 13], - [:newline, nil, 6, 13], + [:text, Gem::Platform::RUBY, 2, 13], + [:newline, nil, 6, 13], - [:newline, nil, 0, 14], + [:newline, nil, 0, 14], - [:section, 'DEPENDENCIES', 0, 15], + [:section, 'DEPENDENCIES', 0, 15], [:newline, nil, 12, 15], - [:text, 'a', 2, 16], - [:newline, nil, 3, 16], + [:text, 'a', 2, 16], + [:newline, nil, 3, 16], ] assert_equal expected, tokenize_lockfile @@ -164,28 +163,28 @@ def test_tokenize_capitals LOCKFILE expected = [ - [:section, 'GEM', 0, 0], - [:newline, nil, 3, 0], - [:entry, 'remote', 2, 1], + [:section, 'GEM', 0, 0], + [:newline, nil, 3, 0], + [:entry, 'remote', 2, 1], [:text, @gem_repo, 10, 1], [:newline, nil, 34, 1], - [:entry, 'specs', 2, 2], - [:newline, nil, 8, 2], - [:text, 'Ab', 4, 3], - [:l_paren, nil, 7, 3], - [:text, '2', 8, 3], - [:r_paren, nil, 9, 3], + [:entry, 'specs', 2, 2], + [:newline, nil, 8, 2], + [:text, 'Ab', 4, 3], + [:l_paren, nil, 7, 3], + [:text, '2', 8, 3], + [:r_paren, nil, 9, 3], [:newline, nil, 10, 3], - [:newline, nil, 0, 4], - [:section, 'PLATFORMS', 0, 5], - [:newline, nil, 9, 5], - [:text, Gem::Platform::RUBY, 2, 6], - [:newline, nil, 6, 6], - [:newline, nil, 0, 7], - [:section, 'DEPENDENCIES', 0, 8], + [:newline, nil, 0, 4], + [:section, 'PLATFORMS', 0, 5], + [:newline, nil, 9, 5], + [:text, Gem::Platform::RUBY, 2, 6], + [:newline, nil, 6, 6], + [:newline, nil, 0, 7], + [:section, 'DEPENDENCIES', 0, 8], [:newline, nil, 12, 8], - [:text, 'Ab', 2, 9], - [:newline, nil, 4, 9], + [:text, 'Ab', 2, 9], + [:newline, nil, 4, 9], ] assert_equal expected, tokenize_lockfile @@ -194,7 +193,7 @@ def test_tokenize_capitals def test_tokenize_conflict_markers write_lockfile '<<<<<<<' - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do tokenize_lockfile end @@ -203,7 +202,7 @@ def test_tokenize_conflict_markers write_lockfile '|||||||' - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do tokenize_lockfile end @@ -212,7 +211,7 @@ def test_tokenize_conflict_markers write_lockfile '=======' - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do tokenize_lockfile end @@ -221,7 +220,7 @@ def test_tokenize_conflict_markers write_lockfile '>>>>>>>' - e = assert_raises Gem::RequestSet::Lockfile::ParseError do + e = assert_raise Gem::RequestSet::Lockfile::ParseError do tokenize_lockfile end @@ -236,12 +235,12 @@ def test_tokenize_git LOCKFILE expected = [ - [:section, 'DEPENDENCIES', 0, 0], - [:newline, nil, 12, 0], + [:section, 'DEPENDENCIES', 0, 0], + [:newline, nil, 12, 0], - [:text, 'a', 2, 1], - [:bang, nil, 3, 1], - [:newline, nil, 4, 1], + [:text, 'a', 2, 1], + [:bang, nil, 3, 1], + [:newline, nil, 4, 1], ] assert_equal expected, tokenize_lockfile @@ -257,31 +256,31 @@ def test_tokenize_multiple LOCKFILE expected = [ - [:section, 'GEM', 0, 0], - [:newline, nil, 3, 0], - - [:entry, 'remote', 2, 1], - [:text, @gem_repo, 10, 1], - [:newline, nil, 34, 1], - - [:entry, 'specs', 2, 2], - [:newline, nil, 8, 2], - - [:text, 'a', 4, 3], - [:l_paren, nil, 6, 3], - [:text, '2', 7, 3], - [:r_paren, nil, 8, 3], - [:newline, nil, 9, 3], - - [:text, 'b', 6, 4], - [:l_paren, nil, 8, 4], - [:requirement, '~>', 9, 4], - [:text, '3.0', 12, 4], - [:comma, nil, 15, 4], - [:requirement, '>=', 17, 4], - [:text, '3.0.1', 20, 4], - [:r_paren, nil, 25, 4], - [:newline, nil, 26, 4], + [:section, 'GEM', 0, 0], + [:newline, nil, 3, 0], + + [:entry, 'remote', 2, 1], + [:text, @gem_repo, 10, 1], + [:newline, nil, 34, 1], + + [:entry, 'specs', 2, 2], + [:newline, nil, 8, 2], + + [:text, 'a', 4, 3], + [:l_paren, nil, 6, 3], + [:text, '2', 7, 3], + [:r_paren, nil, 8, 3], + [:newline, nil, 9, 3], + + [:text, 'b', 6, 4], + [:l_paren, nil, 8, 4], + [:requirement, '~>', 9, 4], + [:text, '3.0', 12, 4], + [:comma, nil, 15, 4], + [:requirement, '>=', 17, 4], + [:text, '3.0.1', 20, 4], + [:r_paren, nil, 25, 4], + [:newline, nil, 26, 4], ] assert_equal expected, tokenize_lockfile @@ -304,5 +303,4 @@ def write_lockfile(lockfile) def tokenize_lockfile Gem::RequestSet::Lockfile::Tokenizer.from_file(@lock_file).to_a end - end diff --git a/ruby/test/rubygems/test_gem_requirement.rb b/ruby/test/rubygems/test_gem_requirement.rb index 3db393e97..b4367681d 100644 --- a/ruby/test/rubygems/test_gem_requirement.rb +++ b/ruby/test/rubygems/test_gem_requirement.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require "rubygems/requirement" class TestGemRequirement < Gem::TestCase - def test_concat r = req '>= 1' @@ -23,6 +22,8 @@ def test_equals2 refute_requirement_equal "~> 1.3", "~> 1.3.0" refute_requirement_equal "~> 1.3.0", "~> 1.3" + assert_requirement_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] + assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] @@ -82,6 +83,12 @@ def test_parse Gem::Requirement.parse(Gem::Version.new('2')) end + if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/) + def test_parse_deduplication + assert_same '~>', Gem::Requirement.parse('~> 1').first + end + end + def test_parse_bad [ nil, @@ -90,7 +97,7 @@ def test_parse_bad '= junk', '1..2', ].each do |bad| - e = assert_raises Gem::Requirement::BadRequirementError do + e = assert_raise Gem::Requirement::BadRequirementError do Gem::Requirement.parse bad end @@ -121,7 +128,7 @@ def test_satisfied_by_eh_bang_equal refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -133,7 +140,7 @@ def test_satisfied_by_eh_blank assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -145,7 +152,7 @@ def test_satisfied_by_eh_equal assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -157,7 +164,7 @@ def test_satisfied_by_eh_gt refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -169,7 +176,7 @@ def test_satisfied_by_eh_gte assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -181,7 +188,7 @@ def test_satisfied_by_eh_list assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -193,7 +200,7 @@ def test_satisfied_by_eh_lt refute_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -205,7 +212,7 @@ def test_satisfied_by_eh_lte assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -217,7 +224,7 @@ def test_satisfied_by_eh_tilde_gt assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -246,7 +253,6 @@ def test_satisfied_by_eh_good assert_satisfied_by "1.0.0.0", "= 1.0" assert_satisfied_by "10.3.2", "!= 9.3.4" assert_satisfied_by "10.3.2", "> 9.3.2" - assert_satisfied_by "10.3.2", "> 9.3.2" assert_satisfied_by " 9.3.2", ">= 9.3.2" assert_satisfied_by "9.3.2 ", ">= 9.3.2" assert_satisfied_by "", "= 0" @@ -275,18 +281,18 @@ def test_satisfied_by_eh_good def test_illformed_requirements [ ">>> 1.3.5", "> blah" ].each do |rq| - assert_raises Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do + assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do Gem::Requirement.new rq end end end def test_satisfied_by_eh_non_versions - assert_raises ArgumentError do + assert_raise ArgumentError do req(">= 0").satisfied_by? Object.new end - assert_raises ArgumentError do + assert_raise ArgumentError do req(">= 0").satisfied_by? Gem::Requirement.default end end @@ -390,11 +396,66 @@ def test_hash_with_multiple_versions r2 = req('2.0', '1.0') assert_equal r1.hash, r2.hash - r1 = req('1.0', '2.0').tap { |r| r.concat(['3.0']) } - r2 = req('3.0', '1.0').tap { |r| r.concat(['2.0']) } + r1 = req('1.0', '2.0').tap {|r| r.concat(['3.0']) } + r2 = req('3.0', '1.0').tap {|r| r.concat(['2.0']) } assert_equal r1.hash, r2.hash end + def test_hash_returns_equal_hashes_for_equivalent_requirements + refute_requirement_hash_equal "= 1.2", "= 1.3" + refute_requirement_hash_equal "= 1.3", "= 1.2" + + refute_requirement_hash_equal "~> 1.3", "~> 1.3.0" + refute_requirement_hash_equal "~> 1.3.0", "~> 1.3" + + assert_requirement_hash_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] + + assert_requirement_hash_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] + assert_requirement_hash_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] + + assert_requirement_hash_equal "= 1.0", "= 1.0.0" + assert_requirement_hash_equal "= 1.1", "= 1.1.0" + assert_requirement_hash_equal "= 1", "= 1.0.0" + + assert_requirement_hash_equal "1.0", "1.0.0" + assert_requirement_hash_equal "1.1", "1.1.0" + assert_requirement_hash_equal "1", "1.0.0" + end + + class Exploit < RuntimeError + end + + def self.exploit(arg) + raise Exploit, "arg = #{arg}" + end + + def test_marshal_load_attack + wa = Net::WriteAdapter.allocate + wa.instance_variable_set(:@socket, self.class) + wa.instance_variable_set(:@method_id, :exploit) + request_set = Gem::RequestSet.allocate + request_set.instance_variable_set(:@git_set, "id") + request_set.instance_variable_set(:@sets, wa) + wa = Net::WriteAdapter.allocate + wa.instance_variable_set(:@socket, request_set) + wa.instance_variable_set(:@method_id, :resolve) + ent = Gem::Package::TarReader::Entry.allocate + ent.instance_variable_set(:@read, 0) + ent.instance_variable_set(:@header, "aaa") + io = Net::BufferedIO.allocate + io.instance_variable_set(:@io, ent) + io.instance_variable_set(:@debug_output, wa) + reader = Gem::Package::TarReader.allocate + reader.instance_variable_set(:@io, io) + requirement = Gem::Requirement.allocate + requirement.instance_variable_set(:@requirements, reader) + m = [Gem::SpecFetcher, Gem::Installer, requirement] + e = assert_raise(TypeError) do + Marshal.load(Marshal.dump(m)) + end + assert_equal(e.message, "wrong @requirements") + end + # Assert that two requirements are equal. Handles Gem::Requirements, # strings, arrays, numbers, and versions. @@ -409,6 +470,13 @@ def assert_satisfied_by(version, requirement) "#{requirement} is satisfied by #{version}" end + # Assert that two requirement hashes are equal. Handles Gem::Requirements, + # strings, arrays, numbers, and versions. + + def assert_requirement_hash_equal(expected, actual) + assert_equal req(expected).hash, req(actual).hash + end + # Refute the assumption that two requirements are equal. def refute_requirement_equal(unexpected, actual) @@ -422,4 +490,9 @@ def refute_satisfied_by(version, requirement) "#{requirement} is not satisfied by #{version}" end + # Refute the assumption that two requirements hashes are equal. + + def refute_requirement_hash_equal(unexpected, actual) + refute_equal req(unexpected).hash, req(actual).hash + end end diff --git a/ruby/test/rubygems/test_gem_resolver.rb b/ruby/test/rubygems/test_gem_resolver.rb index c35a26474..ea9f9049c 100644 --- a/ruby/test/rubygems/test_gem_resolver.rb +++ b/ruby/test/rubygems/test_gem_resolver.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolver < Gem::TestCase - def setup super @@ -26,10 +25,10 @@ def set(*specs) def assert_resolves_to(expected, resolver) actual = resolver.resolve - exp = expected.sort_by { |s| s.full_name } - act = actual.map { |a| a.spec.spec }.sort_by { |s| s.full_name } + exp = expected.sort_by {|s| s.full_name } + act = actual.map {|a| a.spec.spec }.sort_by {|s| s.full_name } - msg = "Set of gems was not the same: #{exp.map { |x| x.full_name}.inspect} != #{act.map { |x| x.full_name}.inspect}" + msg = "Set of gems was not the same: #{exp.map {|x| x.full_name }.inspect} != #{act.map {|x| x.full_name }.inspect}" assert_equal exp, act, msg rescue Gem::DependencyResolutionError => e @@ -77,7 +76,7 @@ def test_self_compose_sets_nil assert_same index_set, composed - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do @DR.compose_sets nil end @@ -105,7 +104,7 @@ def test_requests res.requests a1, act, reqs - assert_equal ['b (= 2)'], reqs.map { |req| req.to_s } + assert_equal ['b (= 2)'], reqs.map {|req| req.to_s } end def test_requests_development @@ -127,7 +126,7 @@ def spec.fetch_development_dependencies res.requests spec, act, reqs - assert_equal ['b (= 2)'], reqs.map { |req| req.to_s } + assert_equal ['b (= 2)'], reqs.map {|req| req.to_s } assert spec.instance_variable_defined? :@called end @@ -267,14 +266,14 @@ def test_resolve_remote_missing_dependency res = Gem::Resolver.new [a_dep], Gem::Resolver::IndexSet.new - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do res.resolve end refute_empty e.errors end - def test_no_overlap_specificly + def test_no_overlap_specifically a = util_spec "a", '1' b = util_spec "b", "1" @@ -446,7 +445,7 @@ def test_raises_dependency_error r = Gem::Resolver.new([ad, bd], s) - e = assert_raises Gem::DependencyResolutionError do + e = assert_raise Gem::DependencyResolutionError do r.resolve end @@ -470,7 +469,7 @@ def test_raises_when_a_gem_is_missing r = Gem::Resolver.new([ad], set) - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do r.resolve end @@ -487,7 +486,7 @@ def test_raises_when_a_gem_version_is_missing r = Gem::Resolver.new([ad], set(a1)) - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do r.resolve end @@ -500,7 +499,7 @@ def test_raises_and_reports_a_toplevel_request_properly r = Gem::Resolver.new([ad], set(a1)) - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do r.resolve end @@ -517,7 +516,7 @@ def test_raises_and_reports_an_implicit_request_properly r = Gem::Resolver.new([ad], set(a1)) - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do r.resolve end @@ -540,13 +539,13 @@ def test_raises_when_possibles_are_exhausted r = Gem::Resolver.new([ad, bd], s) - e = assert_raises Gem::DependencyResolutionError do + e = assert_raise Gem::DependencyResolutionError do r.resolve end dependency = e.conflict.dependency - assert_includes %w(a b), dependency.name + assert_includes %w[a b], dependency.name assert_equal req('>= 0'), dependency.requirement activated = e.conflict.activated @@ -612,7 +611,7 @@ def test_backtracks_to_the_first_conflict r = Gem::Resolver.new([d1, d2, d3], s) - assert_raises Gem::DependencyResolutionError do + assert_raise Gem::DependencyResolutionError do r.resolve end end @@ -630,7 +629,7 @@ def test_resolve_conflict r = Gem::Resolver.new [a_dep, b_dep], s - assert_raises Gem::DependencyResolutionError do + assert_raise Gem::DependencyResolutionError do r.resolve end end @@ -782,12 +781,11 @@ def test_raises_and_explains_when_platform_prevents_install r = Gem::Resolver.new([ad], set(a1)) - e = assert_raises Gem::UnsatisfiableDepedencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do r.resolve end assert_match "No match for 'a (= 1)' on this platform. Found: c-p-1", e.message end - end diff --git a/ruby/test/rubygems/test_gem_resolver_activation_request.rb b/ruby/test/rubygems/test_gem_resolver_activation_request.rb index dc11ad47c..c7b726a23 100644 --- a/ruby/test/rubygems/test_gem_resolver_activation_request.rb +++ b/ruby/test/rubygems/test_gem_resolver_activation_request.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverActivationRequest < Gem::TestCase - def setup super @@ -40,5 +39,4 @@ def test_installed_eh assert @req.installed? end - end diff --git a/ruby/test/rubygems/test_gem_resolver_api_set.rb b/ruby/test/rubygems/test_gem_resolver_api_set.rb index f6b3e49c7..c3db25d7a 100644 --- a/ruby/test/rubygems/test_gem_resolver_api_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_api_set.rb @@ -1,36 +1,35 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverAPISet < Gem::TestCase - def setup super @DR = Gem::Resolver - @dep_uri = URI "#{@gem_repo}api/v1/dependencies" + @dep_uri = URI "#{@gem_repo}info/" end def test_initialize set = @DR::APISet.new - assert_equal URI('https://rubygems.org/api/v1/dependencies'), set.dep_uri - assert_equal URI('https://rubygems.org'), set.uri - assert_equal Gem::Source.new(URI('https://rubygems.org')), set.source + assert_equal URI('https://index.rubygems.org/info/'), set.dep_uri + assert_equal URI('https://index.rubygems.org/'), set.uri + assert_equal Gem::Source.new(URI('https://index.rubygems.org')), set.source end def test_initialize_deeper_uri - set = @DR::APISet.new 'https://rubygemsserver.com/mygems/api/v1/dependencies' + set = @DR::APISet.new 'https://rubygemsserver.com/mygems/info' - assert_equal URI('https://rubygemsserver.com/mygems/api/v1/dependencies'), set.dep_uri - assert_equal URI('https://rubygemsserver.com/mygems/'), set.uri - assert_equal Gem::Source.new(URI('https://rubygemsserver.com/mygems/')), set.source + assert_equal URI('https://rubygemsserver.com/mygems/info'), set.dep_uri + assert_equal URI('https://rubygemsserver.com/'), set.uri + assert_equal Gem::Source.new(URI('https://rubygemsserver.com/')), set.source end def test_initialize_uri set = @DR::APISet.new @dep_uri - assert_equal URI("#{@gem_repo}api/v1/dependencies"), set.dep_uri - assert_equal URI("#{@gem_repo}"), set.uri + assert_equal URI("#{@gem_repo}info/"), set.dep_uri + assert_equal URI("#{@gem_repo}"), set.uri end def test_find_all @@ -40,17 +39,46 @@ def test_find_all { :name => 'a', :number => '1', :platform => 'ruby', - :dependencies => [], }, + :dependencies => [] }, + ] + + @fetcher.data["#{@dep_uri}a"] = "---\n1 " + + set = @DR::APISet.new @dep_uri + + a_dep = @DR::DependencyRequest.new dep('a'), nil + + expected = [ + @DR::APISpecification.new(set, data.first), + ] + + assert_equal expected, set.find_all(a_dep) + end + + def test_find_all_prereleases + spec_fetcher + + data = [ + { :name => 'a', + :number => '1', + :platform => 'ruby', + :dependencies => [] }, + { :name => 'a', + :number => '2.a', + :platform => 'ruby', + :dependencies => [] }, ] - @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data + @fetcher.data["#{@dep_uri}a"] = "---\n1\n2.a" set = @DR::APISet.new @dep_uri + set.prerelease = true a_dep = @DR::DependencyRequest.new dep('a'), nil expected = [ - @DR::APISpecification.new(set, data.first) + @DR::APISpecification.new(set, data.first), + @DR::APISpecification.new(set, data.last), ] assert_equal expected, set.find_all(a_dep) @@ -63,10 +91,10 @@ def test_find_all_cache { :name => 'a', :number => '1', :platform => 'ruby', - :dependencies => [], }, + :dependencies => [] }, ] - @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data + @fetcher.data["#{@dep_uri}a"] = "---\n1 " set = @DR::APISet.new @dep_uri @@ -75,12 +103,12 @@ def test_find_all_cache set.prefetch [a_dep] expected = [ - @DR::APISpecification.new(set, data.first) + @DR::APISpecification.new(set, data.first), ] assert_equal expected, set.find_all(a_dep) - @fetcher.data.delete "#{@dep_uri}?gems=a" + @fetcher.data.delete "#{@dep_uri}a" end def test_find_all_local @@ -95,7 +123,7 @@ def test_find_all_local def test_find_all_missing spec_fetcher - @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump [] + @fetcher.data["#{@dep_uri}a"] = "---" set = @DR::APISet.new @dep_uri @@ -103,7 +131,7 @@ def test_find_all_missing assert_empty set.find_all(a_dep) - @fetcher.data.delete "#{@dep_uri}?gems=a" + @fetcher.data.delete "#{@dep_uri}a" assert_empty set.find_all(a_dep) end @@ -111,15 +139,8 @@ def test_find_all_missing def test_prefetch spec_fetcher - data = [ - { :name => 'a', - :number => '1', - :platform => 'ruby', - :dependencies => [], }, - ] - - @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data - @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump [] + @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" + @fetcher.data["#{@dep_uri}b"] = "---" set = @DR::APISet.new @dep_uri @@ -128,21 +149,14 @@ def test_prefetch set.prefetch [a_dep, b_dep] - assert_equal %w[a-1], set.find_all(a_dep).map { |s| s.full_name } + assert_equal %w[a-1], set.find_all(a_dep).map {|s| s.full_name } assert_empty set.find_all(b_dep) end def test_prefetch_cache spec_fetcher - data = [ - { :name => 'a', - :number => '1', - :platform => 'ruby', - :dependencies => [], }, - ] - - @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data + @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" set = @DR::APISet.new @dep_uri @@ -151,8 +165,8 @@ def test_prefetch_cache set.prefetch [a_dep] - @fetcher.data.delete "#{@dep_uri}?gems=a" - @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump [] + @fetcher.data.delete "#{@dep_uri}a" + @fetcher.data["#{@dep_uri}?b"] = "---" set.prefetch [a_dep, b_dep] end @@ -160,14 +174,8 @@ def test_prefetch_cache def test_prefetch_cache_missing spec_fetcher - data = [ - { :name => 'a', - :number => '1', - :platform => 'ruby', - :dependencies => [], }, - ] - - @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data + @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" + @fetcher.data["#{@dep_uri}b"] = "---" set = @DR::APISet.new @dep_uri @@ -176,7 +184,8 @@ def test_prefetch_cache_missing set.prefetch [a_dep, b_dep] - @fetcher.data.delete "#{@dep_uri}?gems=a,b" + @fetcher.data.delete "#{@dep_uri}a" + @fetcher.data.delete "#{@dep_uri}b" set.prefetch [a_dep, b_dep] end @@ -184,15 +193,8 @@ def test_prefetch_cache_missing def test_prefetch_local spec_fetcher - data = [ - { :name => 'a', - :number => '1', - :platform => 'ruby', - :dependencies => [], }, - ] - - @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data - @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump [] + @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" + @fetcher.data["#{@dep_uri}b"] = "---" set = @DR::APISet.new @dep_uri set.remote = false @@ -204,5 +206,4 @@ def test_prefetch_local assert_empty set.instance_variable_get :@data end - end diff --git a/ruby/test/rubygems/test_gem_resolver_api_specification.rb b/ruby/test/rubygems/test_gem_resolver_api_specification.rb index 87ff90132..3f9b81868 100644 --- a/ruby/test/rubygems/test_gem_resolver_api_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_api_specification.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverAPISpecification < Gem::TestCase - def test_initialize set = Gem::Resolver::APISet.new data = { @@ -40,7 +39,7 @@ def test_fetch_development_dependencies rails = specs['rails-3.0.3'] - repo = @gem_repo + 'api/v1/dependencies' + repo = @gem_repo + 'info' set = Gem::Resolver::APISet.new repo @@ -124,7 +123,7 @@ def test_spec fetcher.spec 'a', 1 end - dep_uri = URI(@gem_repo) + 'api/v1/dependencies' + dep_uri = URI(@gem_repo) + 'info' set = Gem::Resolver::APISet.new dep_uri data = { :name => 'a', @@ -148,7 +147,7 @@ def test_spec_jruby_platform end end - dep_uri = URI(@gem_repo) + 'api/v1/dependencies' + dep_uri = URI(@gem_repo) + 'info' set = Gem::Resolver::APISet.new dep_uri data = { :name => 'j', @@ -164,5 +163,4 @@ def test_spec_jruby_platform assert_kind_of Gem::Specification, spec assert_equal 'j-1-java', spec.full_name end - end diff --git a/ruby/test/rubygems/test_gem_resolver_best_set.rb b/ruby/test/rubygems/test_gem_resolver_best_set.rb index dc6c9b4c4..0e279d16a 100644 --- a/ruby/test/rubygems/test_gem_resolver_best_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_best_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverBestSet < Gem::TestCase - def setup super @@ -30,7 +29,7 @@ def test_find_all_index found = set.find_all req - assert_equal %w[a-1], found.map { |s| s.full_name } + assert_equal %w[a-1], found.map {|s| s.full_name } end def test_find_all_fallback @@ -40,7 +39,7 @@ def test_find_all_fallback set = @DR::BestSet.new - api_uri = URI(@gem_repo) + './api/v1/dependencies' + api_uri = URI(@gem_repo) set.sets << Gem::Resolver::APISet.new(api_uri) @@ -50,7 +49,7 @@ def test_find_all_fallback found = set.find_all req - assert_equal %w[a-1], found.map { |s| s.full_name } + assert_equal %w[a-1], found.map {|s| s.full_name } end def test_find_all_local @@ -100,12 +99,12 @@ def test_prefetch_local def test_replace_failed_api_set set = @DR::BestSet.new - api_uri = URI(@gem_repo) + './api/v1/dependencies' + api_uri = URI(@gem_repo) + './info/' api_set = Gem::Resolver::APISet.new api_uri set.sets << api_set - error_uri = api_uri + '?gems=a' + error_uri = api_uri + 'a' error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri @@ -127,11 +126,33 @@ def test_replace_failed_api_set_no_api_set error = Gem::RemoteFetcher::FetchError.new 'bogus', @gem_repo - e = assert_raises Gem::RemoteFetcher::FetchError do + e = assert_raise Gem::RemoteFetcher::FetchError do set.replace_failed_api_set error end assert_equal error, e end + def test_replace_failed_api_set_uri_with_credentials + set = @DR::BestSet.new + + api_uri = URI(@gem_repo) + './info/' + api_uri.user = 'user' + api_uri.password = 'pass' + api_set = Gem::Resolver::APISet.new api_uri + + set.sets << api_set + + error_uri = api_uri + 'a' + + error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri + + set.replace_failed_api_set error + + assert_equal 1, set.sets.size + + refute_includes set.sets, api_set + + assert_kind_of Gem::Resolver::IndexSet, set.sets.first + end end diff --git a/ruby/test/rubygems/test_gem_resolver_composed_set.rb b/ruby/test/rubygems/test_gem_resolver_composed_set.rb index 0e745433a..405753a37 100644 --- a/ruby/test/rubygems/test_gem_resolver_composed_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_composed_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverComposedSet < Gem::TestCase - def test_errors index_set = Gem::Resolver::IndexSet.new current_set = Gem::Resolver::CurrentSet.new @@ -41,5 +40,4 @@ def test_remote_equals refute best_set.remote? refute current_set.remote? end - end diff --git a/ruby/test/rubygems/test_gem_resolver_conflict.rb b/ruby/test/rubygems/test_gem_resolver_conflict.rb index 2385c3eee..1d46e69c3 100644 --- a/ruby/test/rubygems/test_gem_resolver_conflict.rb +++ b/ruby/test/rubygems/test_gem_resolver_conflict.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverConflict < Gem::TestCase - def test_explanation root = dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8' @@ -74,10 +73,9 @@ def test_request_path expected = [ 'net-ssh (>= 2.0.13), 2.2.2 activated', - 'rye (= 0.9.8), 0.9.8 activated' + 'rye (= 0.9.8), 0.9.8 activated', ] assert_equal expected, conflict.request_path(child.requester) end - end diff --git a/ruby/test/rubygems/test_gem_resolver_dependency_request.rb b/ruby/test/rubygems/test_gem_resolver_dependency_request.rb index 51f0be9dc..cea0a7952 100644 --- a/ruby/test/rubygems/test_gem_resolver_dependency_request.rb +++ b/ruby/test/rubygems/test_gem_resolver_dependency_request.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverDependencyRequest < Gem::TestCase - def setup super @@ -80,5 +79,4 @@ def test_requirement assert_equal dependency, dr.dependency end - end diff --git a/ruby/test/rubygems/test_gem_resolver_git_set.rb b/ruby/test/rubygems/test_gem_resolver_git_set.rb index f38859c8b..145cd6c7d 100644 --- a/ruby/test/rubygems/test_gem_resolver_git_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_git_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverGitSet < Gem::TestCase - def setup super @@ -52,7 +51,7 @@ def test_add_git_spec assert @set.need_submodules[repository] - refute_path_exists spec.source.repo_cache_dir + assert_path_not_exist spec.source.repo_cache_dir end def test_find_all @@ -185,5 +184,4 @@ def test_prefetch_root_dir assert_equal "#{@gemhome}2", spec.source.root_dir end - end diff --git a/ruby/test/rubygems/test_gem_resolver_git_specification.rb b/ruby/test/rubygems/test_gem_resolver_git_specification.rb index 339150555..857452c15 100644 --- a/ruby/test/rubygems/test_gem_resolver_git_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_git_specification.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/installer' class TestGemResolverGitSpecification < Gem::TestCase - def setup super @@ -63,7 +62,8 @@ def test_install # functional test for Gem::Ext::Builder def test_install_extension - skip if Gem.java_platform? + pend if Gem.java_platform? + pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning name, _, repository, = git_gem 'a', 1 do |s| s.extensions << 'ext/extconf.rb' end @@ -92,7 +92,7 @@ def test_install_extension git_spec.install({}) - assert_path_exists File.join git_spec.spec.extension_dir, 'b.rb' + assert_path_exist File.join git_spec.spec.extension_dir, 'b.rb' end def test_install_installed @@ -110,5 +110,4 @@ def test_install_installed assert called end - end diff --git a/ruby/test/rubygems/test_gem_resolver_index_set.rb b/ruby/test/rubygems/test_gem_resolver_index_set.rb index d9a30d0f5..ddae0c2b8 100644 --- a/ruby/test/rubygems/test_gem_resolver_index_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_index_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverIndexSet < Gem::TestCase - def setup super @@ -42,7 +41,7 @@ def test_find_all found = set.find_all req - assert_equal %w[a-1], found.map { |s| s.full_name } + assert_equal %w[a-1], found.map {|s| s.full_name } end def test_find_all_local @@ -83,7 +82,6 @@ def test_find_all_prerelease found = set.find_all req - assert_equal %w[a-1.a], found.map { |s| s.full_name } + assert_equal %w[a-1.a], found.map {|s| s.full_name } end - end diff --git a/ruby/test/rubygems/test_gem_resolver_index_specification.rb b/ruby/test/rubygems/test_gem_resolver_index_specification.rb index 43e8efd8b..ef9c17034 100644 --- a/ruby/test/rubygems/test_gem_resolver_index_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_index_specification.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/available_set' class TestGemResolverIndexSpecification < Gem::TestCase - def test_initialize set = Gem::Resolver::IndexSet.new source = Gem::Source.new @gem_repo @@ -47,7 +46,7 @@ def test_install called = installer end - assert_path_exists File.join @gemhome, 'specifications', 'a-2.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec' assert_kind_of Gem::Installer, called end @@ -90,5 +89,4 @@ def test_spec_local assert_equal a_2_p.full_name, spec.full_name end - end diff --git a/ruby/test/rubygems/test_gem_resolver_installed_specification.rb b/ruby/test/rubygems/test_gem_resolver_installed_specification.rb index e9422b75f..0e5ea02fb 100644 --- a/ruby/test/rubygems/test_gem_resolver_installed_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_installed_specification.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverInstalledSpecification < Gem::TestCase - def setup super @@ -44,5 +43,4 @@ def test_installable_platform_eh assert b_spec.installable_platform? end - end diff --git a/ruby/test/rubygems/test_gem_resolver_installer_set.rb b/ruby/test/rubygems/test_gem_resolver_installer_set.rb index 5138743cd..928a16b9d 100644 --- a/ruby/test/rubygems/test_gem_resolver_installer_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_installer_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverInstallerSet < Gem::TestCase - def test_add_always_install spec_fetcher do |fetcher| fetcher.download 'a', 1 @@ -15,9 +14,9 @@ def test_add_always_install set.add_always_install dep('a') - assert_equal %w[a-2], set.always_install.map { |s| s.full_name } + assert_equal %w[a-2], set.always_install.map {|s| s.full_name } - e = assert_raises Gem::UnsatisfiableDependencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do set.add_always_install dep('b') end @@ -30,7 +29,7 @@ def test_add_always_install_errors set = Gem::Resolver::InstallerSet.new :both - e = assert_raises Gem::UnsatisfiableDependencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do set.add_always_install dep 'a' end @@ -49,7 +48,7 @@ def test_add_always_install_platform set.add_always_install dep('a') - assert_equal %w[a-1], set.always_install.map { |s| s.full_name } + assert_equal %w[a-1], set.always_install.map {|s| s.full_name } end def test_add_always_install_prerelease @@ -62,7 +61,25 @@ def test_add_always_install_prerelease set.add_always_install dep('a') - assert_equal %w[a-1], set.always_install.map { |s| s.full_name } + assert_equal %w[a-1], set.always_install.map {|s| s.full_name } + end + + def test_add_always_install_prerelease_github_problem + spec_fetcher do |fetcher| + fetcher.gem 'a', 1 + end + + # Github has an issue in which it will generate a misleading prerelease output in its RubyGems server API and + # returns a 0 version for the gem while it doesn't exist. + @fetcher.data["#{@gem_repo}prerelease_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([ + Gem::NameTuple.new('a', Gem::Version.new(0), 'ruby'), + ])) + + set = Gem::Resolver::InstallerSet.new :both + + set.add_always_install dep('a') + + assert_equal %w[a-1], set.always_install.map {|s| s.full_name } end def test_add_always_install_prerelease_only @@ -72,7 +89,7 @@ def test_add_always_install_prerelease_only set = Gem::Resolver::InstallerSet.new :both - assert_raises Gem::UnsatisfiableDependencyError do + assert_raise Gem::UnsatisfiableDependencyError do set.add_always_install dep('a') end end @@ -93,7 +110,7 @@ def test_add_local req = Gem::Resolver::DependencyRequest.new dep('a'), nil - assert_equal %w[a-1], set.find_all(req).map { |spec| spec.full_name } + assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name } end def test_consider_local_eh @@ -149,7 +166,7 @@ def test_find_all_always_install req = Gem::Resolver::DependencyRequest.new dep('a'), nil - assert_equal %w[a-2], set.find_all(req).map { |spec| spec.full_name } + assert_equal %w[a-2], set.find_all(req).map {|spec| spec.full_name } end def test_find_all_prerelease @@ -162,12 +179,12 @@ def test_find_all_prerelease req = Gem::Resolver::DependencyRequest.new dep('a'), nil - assert_equal %w[a-1], set.find_all(req).map { |spec| spec.full_name } + assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name } req = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil assert_equal %w[a-1 a-1.a], - set.find_all(req).map { |spec| spec.full_name }.sort + set.find_all(req).map {|spec| spec.full_name }.sort end def test_load_spec @@ -193,7 +210,7 @@ def test_prefetch def (set.remote_set).prefetch(_) raise "called" end - assert_raises(RuntimeError){ set.prefetch(nil) } + assert_raise(RuntimeError){ set.prefetch(nil) } set = Gem::Resolver::InstallerSet.new :local def (set.remote_set).prefetch(_) @@ -255,5 +272,4 @@ def test_remote_equals_remote refute set.consider_local? refute set.consider_remote? end - end diff --git a/ruby/test/rubygems/test_gem_resolver_local_specification.rb b/ruby/test/rubygems/test_gem_resolver_local_specification.rb index 82598f518..c11f73612 100644 --- a/ruby/test/rubygems/test_gem_resolver_local_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_local_specification.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/available_set' class TestGemResolverLocalSpecification < Gem::TestCase - def setup super @@ -25,7 +24,7 @@ def test_install called = installer end - assert_path_exists File.join @gemhome, 'specifications', 'a-2.gemspec' + assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec' assert_kind_of Gem::Installer, called end @@ -41,5 +40,4 @@ def test_installable_platform_eh assert b_spec.installable_platform? end - end diff --git a/ruby/test/rubygems/test_gem_resolver_lock_set.rb b/ruby/test/rubygems/test_gem_resolver_lock_set.rb index d5258477d..dc7767a3f 100644 --- a/ruby/test/rubygems/test_gem_resolver_lock_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_lock_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverLockSet < Gem::TestCase - def setup super @@ -16,7 +15,7 @@ def test_add specs = @set.add 'a', '2', Gem::Platform::RUBY spec = specs.first - assert_equal %w[a-2], @set.specs.map { |t| t.full_name } + assert_equal %w[a-2], @set.specs.map {|t| t.full_name } assert_kind_of Gem::Resolver::LockSpecification, spec @@ -34,11 +33,11 @@ def test_find_all found = @set.find_all dep 'a' - assert_equal %w[a-2], found.map { |s| s.full_name } + assert_equal %w[a-2], found.map {|s| s.full_name } found = @set.find_all dep 'a', '>= 0.a' - assert_equal %w[a-1.a a-2], found.map { |s| s.full_name } + assert_equal %w[a-1.a a-2], found.map {|s| s.full_name } end def test_load_spec @@ -59,5 +58,4 @@ def test_load_spec def test_prefetch assert_respond_to @set, :prefetch end - end diff --git a/ruby/test/rubygems/test_gem_resolver_lock_specification.rb b/ruby/test/rubygems/test_gem_resolver_lock_specification.rb index 7b9b0ac8f..46c8e5edd 100644 --- a/ruby/test/rubygems/test_gem_resolver_lock_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_lock_specification.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/installer' require 'rubygems/resolver' class TestGemResolverLockSpecification < Gem::TestCase - def setup super @@ -95,5 +94,4 @@ def test_spec_loaded assert_same real_spec, l_spec.spec end - end diff --git a/ruby/test/rubygems/test_gem_resolver_requirement_list.rb b/ruby/test/rubygems/test_gem_resolver_requirement_list.rb index 4cbb93919..806c38766 100644 --- a/ruby/test/rubygems/test_gem_resolver_requirement_list.rb +++ b/ruby/test/rubygems/test_gem_resolver_requirement_list.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverRequirementList < Gem::TestCase - def setup super @@ -16,5 +15,4 @@ def test_each assert_equal [req], @list.each.to_a end - end diff --git a/ruby/test/rubygems/test_gem_resolver_specification.rb b/ruby/test/rubygems/test_gem_resolver_specification.rb index e663ff183..9f28c1c0c 100644 --- a/ruby/test/rubygems/test_gem_resolver_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_specification.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverSpecification < Gem::TestCase - class TestSpec < Gem::Resolver::Specification - attr_writer :source attr_reader :spec @@ -13,7 +11,6 @@ def initialize(spec) @spec = spec end - end def test_install @@ -29,7 +26,7 @@ def test_install a_spec.install :install_dir => gemhome - assert_path_exists File.join gemhome, 'gems', a.full_name + assert_path_exist File.join gemhome, 'gems', a.full_name expected = File.join gemhome, 'specifications', a.spec_name @@ -62,5 +59,4 @@ def test_source assert_equal source, a_spec.source end - end diff --git a/ruby/test/rubygems/test_gem_resolver_vendor_set.rb b/ruby/test/rubygems/test_gem_resolver_vendor_set.rb index 3fc79fec1..e16d43ac1 100644 --- a/ruby/test/rubygems/test_gem_resolver_vendor_set.rb +++ b/ruby/test/rubygems/test_gem_resolver_vendor_set.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverVendorSet < Gem::TestCase - def setup super @@ -28,7 +27,7 @@ def test_add_vendor_gem_missing FileUtils.rm_r directory - e = assert_raises Gem::GemNotFoundException do + e = assert_raise Gem::GemNotFoundException do @set.add_vendor_gem name, directory end @@ -52,7 +51,7 @@ def test_find_all source = Gem::Source::Vendor.new directory expected = [ - Gem::Resolver::VendorSpecification.new(@set, spec, source) + Gem::Resolver::VendorSpecification.new(@set, spec, source), ] assert_equal expected, found @@ -75,9 +74,8 @@ def test_find_all_prerelease def test_load_spec error = Object.const_defined?(:KeyError) ? KeyError : IndexError - assert_raises error do + assert_raise error do @set.load_spec 'b', v(1), Gem::Platform::RUBY, nil end end - end diff --git a/ruby/test/rubygems/test_gem_resolver_vendor_specification.rb b/ruby/test/rubygems/test_gem_resolver_vendor_specification.rb index 315ce0553..93382ccd8 100644 --- a/ruby/test/rubygems/test_gem_resolver_vendor_specification.rb +++ b/ruby/test/rubygems/test_gem_resolver_vendor_specification.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemResolverVendorSpecification < Gem::TestCase - def setup super @@ -79,5 +78,4 @@ def test_version assert_equal v(1), v_spec.version end - end diff --git a/ruby/test/rubygems/test_gem_security.rb b/ruby/test/rubygems/test_gem_security.rb index 71185dc86..415ec2b5f 100644 --- a/ruby/test/rubygems/test_gem_security.rb +++ b/ruby/test/rubygems/test_gem_security.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/security' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping Gem::Security tests. openssl not found.' end @@ -11,8 +11,8 @@ end class TestGemSecurity < Gem::TestCase - CHILD_KEY = load_key 'child' + EC_KEY = load_key 'private_ec', 'Foo bar' ALTERNATE_CERT = load_cert 'child' CHILD_CERT = load_cert 'child' @@ -40,16 +40,16 @@ def test_class_create_cert assert_equal name.to_s, cert.subject.to_s assert_equal 3, cert.extensions.length, - cert.extensions.map { |e| e.to_a.first } + cert.extensions.map {|e| e.to_a.first } - constraints = cert.extensions.find { |ext| ext.oid == 'basicConstraints' } + constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' } assert_equal 'CA:FALSE', constraints.value - key_usage = cert.extensions.find { |ext| ext.oid == 'keyUsage' } + key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' } assert_equal 'Digital Signature, Key Encipherment, Data Encipherment', key_usage.value - key_ident = cert.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' } + key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' } assert_equal 59, key_ident.value.length assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B', key_ident.value @@ -85,30 +85,57 @@ def test_class_create_cert_email assert_equal name.to_s, cert.issuer.to_s assert_equal 5, cert.extensions.length, - cert.extensions.map { |e| e.to_a.first } + cert.extensions.map {|e| e.to_a.first } - constraints = cert.extensions.find { |ext| ext.oid == 'subjectAltName' } + constraints = cert.extensions.find {|ext| ext.oid == 'subjectAltName' } assert_equal 'email:nobody@example', constraints.value - constraints = cert.extensions.find { |ext| ext.oid == 'basicConstraints' } + constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' } assert_equal 'CA:FALSE', constraints.value - key_usage = cert.extensions.find { |ext| ext.oid == 'keyUsage' } + key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' } assert_equal 'Digital Signature, Key Encipherment, Data Encipherment', key_usage.value - key_ident = cert.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' } + key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' } assert_equal 59, key_ident.value.length assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B', key_ident.value end def test_class_create_key - key = @SEC.create_key 1024 + key = @SEC.create_key 'rsa' assert_kind_of OpenSSL::PKey::RSA, key end + def test_class_create_key_downcases + key = @SEC.create_key 'DSA' + + assert_kind_of OpenSSL::PKey::DSA, key + end + + def test_class_create_key_raises_unknown_algorithm + e = assert_raise Gem::Security::Exception do + @SEC.create_key 'NOT_RSA' + end + + assert_equal "NOT_RSA algorithm not found. RSA, DSA, and EC algorithms are supported.", + e.message + end + + def test_class_get_public_key_rsa + pkey_pem = PRIVATE_KEY.public_key.to_pem + + assert_equal pkey_pem, @SEC.get_public_key(PRIVATE_KEY).to_pem + end + + def test_class_get_public_key_ec + pkey = @SEC.get_public_key(EC_KEY) + + assert_respond_to pkey, :to_pem + end + def test_class_email_to_name assert_equal '/CN=nobody/DC=example', @SEC.email_to_name('nobody@example').to_s @@ -136,7 +163,7 @@ def test_class_re_sign end def test_class_re_sign_not_self_signed - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do Gem::Security.re_sign CHILD_CERT, CHILD_KEY end @@ -150,7 +177,7 @@ def test_class_re_sign_not_self_signed end def test_class_re_sign_wrong_key - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do Gem::Security.re_sign ALTERNATE_CERT, PRIVATE_KEY end @@ -169,7 +196,7 @@ def test_class_reset def test_class_sign issuer = PUBLIC_CERT.subject - signee = OpenSSL::X509::Name.parse "/CN=signee/DC=example" + signee = OpenSSL::X509::Name.new([["CN", "signee"], ["DC", "example"]]) key = PRIVATE_KEY cert = OpenSSL::X509::Certificate.new @@ -188,20 +215,20 @@ def test_class_sign assert_in_delta Time.now + 60, signed.not_after, 10 assert_equal 4, signed.extensions.length, - signed.extensions.map { |e| e.to_a.first } + signed.extensions.map {|e| e.to_a.first } - constraints = signed.extensions.find { |ext| ext.oid == 'issuerAltName' } + constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' } assert_equal 'email:nobody@example', constraints.value, 'issuerAltName' - constraints = signed.extensions.find { |ext| ext.oid == 'basicConstraints' } + constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' } assert_equal 'CA:FALSE', constraints.value - key_usage = signed.extensions.find { |ext| ext.oid == 'keyUsage' } + key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' } assert_equal 'Digital Signature, Key Encipherment, Data Encipherment', key_usage.value key_ident = - signed.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' } + signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' } assert_equal 59, key_ident.value.length assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B', key_ident.value @@ -227,23 +254,23 @@ def test_class_sign_AltName assert_equal "sha256WithRSAEncryption", signed.signature_algorithm assert_equal 5, signed.extensions.length, - signed.extensions.map { |e| e.to_a.first } + signed.extensions.map {|e| e.to_a.first } - constraints = signed.extensions.find { |ext| ext.oid == 'issuerAltName' } + constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' } assert_equal 'email:nobody@example', constraints.value, 'issuerAltName' - constraints = signed.extensions.find { |ext| ext.oid == 'subjectAltName' } + constraints = signed.extensions.find {|ext| ext.oid == 'subjectAltName' } assert_equal 'email:signee@example', constraints.value, 'subjectAltName' - constraints = signed.extensions.find { |ext| ext.oid == 'basicConstraints' } + constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' } assert_equal 'CA:FALSE', constraints.value - key_usage = signed.extensions.find { |ext| ext.oid == 'keyUsage' } + key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' } assert_equal 'Digital Signature, Key Encipherment, Data Encipherment', key_usage.value key_ident = - signed.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' } + signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' } assert_equal 59, key_ident.value.length assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B', key_ident.value @@ -260,13 +287,13 @@ def test_class_trust_dir end def test_class_write - key = @SEC.create_key 1024 + key = @SEC.create_key 'rsa' path = File.join @tempdir, 'test-private_key.pem' @SEC.write key, path - assert_path_exists path + assert_path_exist path key_from_file = File.read path @@ -274,7 +301,7 @@ def test_class_write end def test_class_write_encrypted - key = @SEC.create_key 1024 + key = @SEC.create_key 'rsa' path = File.join @tempdir, 'test-private_encrypted_key.pem' @@ -282,7 +309,7 @@ def test_class_write_encrypted @SEC.write key, path, 0600, passphrase - assert_path_exists path + assert_path_exist path key_from_file = OpenSSL::PKey::RSA.new File.read(path), passphrase @@ -290,7 +317,7 @@ def test_class_write_encrypted end def test_class_write_encrypted_cipher - key = @SEC.create_key 1024 + key = @SEC.create_key 'rsa' path = File.join @tempdir, 'test-private_encrypted__with_non_default_cipher_key.pem' @@ -300,7 +327,7 @@ def test_class_write_encrypted_cipher @SEC.write key, path, 0600, passphrase, cipher - assert_path_exists path + assert_path_exist path key_file_contents = File.read(path) @@ -310,5 +337,4 @@ def test_class_write_encrypted_cipher assert_equal key.to_pem, key_from_file.to_pem end - -end if defined?(OpenSSL::SSL) && !Gem.java_platform? +end if Gem::HAVE_OPENSSL && !Gem.java_platform? diff --git a/ruby/test/rubygems/test_gem_security_policy.rb b/ruby/test/rubygems/test_gem_security_policy.rb index 8a1676cd3..515b8ea00 100644 --- a/ruby/test/rubygems/test_gem_security_policy.rb +++ b/ruby/test/rubygems/test_gem_security_policy.rb @@ -1,14 +1,12 @@ -# coding: utf-8 # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping Gem::Security::Policy tests. openssl not found.' end class TestGemSecurityPolicy < Gem::TestCase - ALTERNATE_KEY = load_key 'alternate' INVALID_KEY = load_key 'invalid' CHILD_KEY = load_key 'child' @@ -34,7 +32,7 @@ def setup s.files = %w[lib/code.rb] end - @digest = Gem::Security::DIGEST_ALGORITHM + @digest = OpenSSL::Digest.new Gem::Security::DIGEST_NAME @trust_dir = Gem::Security.trust_dir.dir # HACK use the object @no = Gem::Security::NoSecurity @@ -79,7 +77,7 @@ def test_check_data_invalid invalid = digest 'hello!' - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @almost_no.check_data PUBLIC_KEY, @digest, signature, invalid end @@ -93,7 +91,7 @@ def test_check_chain end def test_check_chain_empty_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_chain [], Time.now end @@ -103,7 +101,7 @@ def test_check_chain_empty_chain def test_check_chain_invalid chain = [PUBLIC_CERT, CHILD_CERT, INVALIDCHILD_CERT] - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_chain chain, Time.now end @@ -113,7 +111,7 @@ def test_check_chain_invalid end def test_check_chain_no_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_chain nil, Time.now end @@ -125,7 +123,7 @@ def test_check_cert end def test_check_cert_expired - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @low.check_cert EXPIRED_CERT, nil, Time.now end @@ -135,7 +133,7 @@ def test_check_cert_expired end def test_check_cert_future - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @low.check_cert FUTURE_CERT, nil, Time.now end @@ -145,7 +143,7 @@ def test_check_cert_future end def test_check_cert_invalid_issuer - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @low.check_cert INVALID_ISSUER_CERT, PUBLIC_CERT, Time.now end @@ -159,7 +157,7 @@ def test_check_cert_issuer end def test_check_cert_no_signer - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.check_cert(nil, nil, Time.now) end @@ -173,7 +171,7 @@ def test_check_key def test_check_key_no_signer assert @almost_no.check_key(nil, nil) - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.check_key(nil, nil) end @@ -181,7 +179,7 @@ def test_check_key_no_signer end def test_check_key_wrong_key - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @almost_no.check_key(PUBLIC_CERT, ALTERNATE_KEY) end @@ -196,7 +194,7 @@ def test_check_root end def test_check_root_empty_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_root [], Time.now end @@ -206,7 +204,7 @@ def test_check_root_empty_chain def test_check_root_invalid_signer chain = [INVALID_SIGNER_CERT] - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_root chain, Time.now end @@ -218,7 +216,7 @@ def test_check_root_invalid_signer def test_check_root_not_self_signed chain = [INVALID_ISSUER_CERT] - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_root chain, Time.now end @@ -228,7 +226,7 @@ def test_check_root_not_self_signed end def test_check_root_no_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_root nil, Time.now end @@ -248,7 +246,7 @@ def test_check_trust_child end def test_check_trust_empty_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_trust [], @digest, @trust_dir end @@ -258,7 +256,7 @@ def test_check_trust_empty_chain def test_check_trust_mismatch Gem::Security.trust_dir.trust_cert PUBLIC_CERT - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.check_trust [WRONG_KEY_CERT], @digest, @trust_dir end @@ -267,7 +265,7 @@ def test_check_trust_mismatch end def test_check_trust_no_chain - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @chain.check_trust nil, @digest, @trust_dir end @@ -275,7 +273,7 @@ def test_check_trust_no_chain end def test_check_trust_no_trust - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.check_trust [PUBLIC_CERT], @digest, @trust_dir end @@ -283,7 +281,7 @@ def test_check_trust_no_trust end def test_check_trust_no_trust_child - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir end @@ -317,7 +315,7 @@ def test_verify_no_digests _, signatures = dummy_signatures - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @almost_no.verify [PUBLIC_CERT], nil, {}, signatures end @@ -329,7 +327,7 @@ def test_verify_no_digests_no_security _, signatures = dummy_signatures - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @no.verify [PUBLIC_CERT], nil, {}, signatures end @@ -347,7 +345,7 @@ def test_verify_no_signatures assert_match "WARNING: some_gem is not signed\n", @ui.error - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @high.verify [PUBLIC_CERT], nil, digests, {} end end @@ -372,7 +370,7 @@ def test_verify_not_enough_signatures signatures[1] = PRIVATE_KEY.sign @digest.new, data.digest - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @almost_no.verify [PUBLIC_CERT], nil, digests, signatures end @@ -389,7 +387,7 @@ def test_verify_no_trust assert_equal "WARNING: email:nobody@example is not trusted for some_gem\n", @ui.error - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @medium.verify [PUBLIC_CERT], nil, digests, signatures end end @@ -397,16 +395,14 @@ def test_verify_no_trust def test_verify_wrong_digest_type Gem::Security.trust_dir.trust_cert PUBLIC_CERT - sha512 = OpenSSL::Digest::SHA512 - - data = sha512.new + data = OpenSSL::Digest.new('SHA512') data << 'hello' digests = { 'SHA512' => { 0 => data } } - signature = PRIVATE_KEY.sign sha512.new, data.digest + signature = PRIVATE_KEY.sign 'sha512', data.digest signatures = { 0 => signature } - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @almost_no.verify [PUBLIC_CERT], nil, digests, signatures end @@ -482,7 +478,7 @@ def test_verify_signatures_missing def s.full_name() 'metadata.gz' end digests = package.digest s - digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello' + digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello' metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz'] @@ -490,7 +486,7 @@ def s.full_name() 'metadata.gz' end signatures['metadata.gz'] = PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @high.verify_signatures @spec, digests, signatures end @@ -511,9 +507,9 @@ def test_verify_signatures_none def s.full_name() 'metadata.gz' end digests = package.digest s - digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello' + digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello' - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do @high.verify_signatures @spec, digests, {} end end @@ -536,5 +532,4 @@ def dummy_signatures(key = PRIVATE_KEY) return digests, signatures end - -end if defined?(OpenSSL::SSL) +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_gem_security_signer.rb b/ruby/test/rubygems/test_gem_security_signer.rb index 08e74e627..7bd6510b5 100644 --- a/ruby/test/rubygems/test_gem_security_signer.rb +++ b/ruby/test/rubygems/test_gem_security_signer.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping Gem::Security::Signer tests. openssl not found.' end class TestGemSecuritySigner < Gem::TestCase - ALTERNATE_KEY = load_key 'alternate' CHILD_KEY = load_key 'child' GRANDCHILD_KEY = load_key 'grandchild' @@ -37,12 +36,12 @@ def test_initialize_cert_chain_empty def test_initialize_cert_chain_mixed signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT] - assert_equal [PUBLIC_CERT, CHILD_CERT].map { |c| c.to_pem }, - signer.cert_chain.map { |c| c.to_pem } + assert_equal [PUBLIC_CERT, CHILD_CERT].map {|c| c.to_pem }, + signer.cert_chain.map {|c| c.to_pem } end def test_initialize_cert_chain_invalid - assert_raises OpenSSL::X509::CertificateError do + assert_raise OpenSSL::X509::CertificateError do Gem::Security::Signer.new nil, ['garbage'] end end @@ -50,8 +49,8 @@ def test_initialize_cert_chain_invalid def test_initialize_cert_chain_path signer = Gem::Security::Signer.new nil, [@cert_file] - assert_equal [PUBLIC_CERT].map { |c| c.to_pem }, - signer.cert_chain.map { |c| c.to_pem } + assert_equal [PUBLIC_CERT].map {|c| c.to_pem }, + signer.cert_chain.map {|c| c.to_pem } end def test_initialize_default @@ -66,7 +65,7 @@ def test_initialize_default signer = Gem::Security::Signer.new nil, nil assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem - assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map { |c| c.to_pem } + assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map {|c| c.to_pem } end def test_initialize_key_path @@ -100,7 +99,7 @@ def test_load_cert_chain signer.load_cert_chain assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem], - signer.cert_chain.map { |c| c.to_pem } + signer.cert_chain.map {|c| c.to_pem } end def test_load_cert_chain_broken @@ -112,7 +111,7 @@ def test_load_cert_chain_broken signer.load_cert_chain assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem], - signer.cert_chain.map { |c| c.to_pem } + signer.cert_chain.map {|c| c.to_pem } end def test_sign @@ -135,7 +134,7 @@ def test_sign def test_sign_expired signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT] - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do signer.sign 'hello' end @@ -143,7 +142,7 @@ def test_sign_expired end def test_sign_expired_auto_update - skip if Gem.java_platform? + pend if Gem.java_platform? FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700 private_key_path = File.join(Gem.user_home, '.gem', 'gem-private_key.pem') @@ -166,7 +165,7 @@ def test_sign_expired_auto_update expired_path = File.join Gem.user_home, '.gem', "gem-public_cert.pem.expired.#{expiry}" - assert_path_exists expired_path + assert_path_exist expired_path assert_equal EXPIRED_CERT.to_pem, File.read(expired_path) end @@ -187,11 +186,11 @@ def test_sign_expired_auto_update_exists signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT] - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do signer.sign 'hello' end - assert_match %r%certificate /CN=nobody/DC=example not valid%, e.message + assert_match %r{certificate /CN=nobody/DC=example not valid}, e.message end def test_sign_no_key @@ -203,7 +202,7 @@ def test_sign_no_key def test_sign_wrong_key signer = Gem::Security::Signer.new ALTERNATE_KEY, [PUBLIC_CERT] - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do signer.sign 'hello' end end @@ -211,9 +210,8 @@ def test_sign_wrong_key def test_sign_no_certs signer = Gem::Security::Signer.new ALTERNATE_KEY, [] - assert_raises Gem::Security::Exception do + assert_raise Gem::Security::Exception do signer.sign 'hello' end end - -end if defined?(OpenSSL::SSL) +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_gem_security_trust_dir.rb b/ruby/test/rubygems/test_gem_security_trust_dir.rb index f2b7b006d..fc88c8486 100644 --- a/ruby/test/rubygems/test_gem_security_trust_dir.rb +++ b/ruby/test/rubygems/test_gem_security_trust_dir.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' -unless defined?(OpenSSL::SSL) +unless Gem::HAVE_OPENSSL warn 'Skipping Gem::Security::TrustDir tests. openssl not found.' end class TestGemSecurityTrustDir < Gem::TestCase - CHILD_CERT = load_cert 'child' def setup @@ -18,7 +17,7 @@ def setup end def test_cert_path - digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s + digest = OpenSSL::Digest.hexdigest Gem::Security::DIGEST_NAME, PUBLIC_CERT.subject.to_s expected = File.join @dest_dir, "cert-#{digest}.pem" @@ -42,7 +41,7 @@ def test_load_certificate end def test_name_path - digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s + digest = OpenSSL::Digest.hexdigest Gem::Security::DIGEST_NAME, PUBLIC_CERT.subject.to_s expected = File.join @dest_dir, "cert-#{digest}.pem" @@ -54,7 +53,7 @@ def test_trust_cert trusted = @trust_dir.cert_path PUBLIC_CERT - assert_path_exists trusted + assert_path_exist trusted mask = 0100600 & (~File.umask) @@ -64,11 +63,11 @@ def test_trust_cert end def test_verify - refute_path_exists @dest_dir + assert_path_not_exist @dest_dir @trust_dir.verify - assert_path_exists @dest_dir + assert_path_exist @dest_dir mask = 040700 & (~File.umask) mask |= 0200000 if /aix/ =~ RUBY_PLATFORM @@ -79,7 +78,7 @@ def test_verify def test_verify_file FileUtils.touch @dest_dir - e = assert_raises Gem::Security::Exception do + e = assert_raise Gem::Security::Exception do @trust_dir.verify end @@ -96,5 +95,4 @@ def test_verify_wrong_permissions assert_equal mask, File.stat(@dest_dir).mode unless win_platform? end - -end if defined?(OpenSSL::SSL) +end if Gem::HAVE_OPENSSL diff --git a/ruby/test/rubygems/test_gem_server.rb b/ruby/test/rubygems/test_gem_server.rb deleted file mode 100644 index ca9ba4bf9..000000000 --- a/ruby/test/rubygems/test_gem_server.rb +++ /dev/null @@ -1,612 +0,0 @@ -# frozen_string_literal: true -require 'rubygems/test_case' -require 'rubygems/server' -require 'stringio' - -class Gem::Server - - attr_reader :server - -end - -class TestGemServer < Gem::TestCase - - def process_based_port - 0 - end - - def setup - super - - @a1 = quick_gem 'a', '1' - @a2 = quick_gem 'a', '2' - @a3_p = quick_gem 'a', '3.a' - - @server = Gem::Server.new Gem.dir, process_based_port, false - @req = WEBrick::HTTPRequest.new :Logger => nil - @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0' - end - - def test_doc_root_3 - orig_rdoc_version = Gem::RDoc.rdoc_version - Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('3.12') - - assert_equal '/doc_root/X-1/rdoc/index.html', @server.doc_root('X-1') - - ensure - Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version - end - - def test_doc_root_4 - orig_rdoc_version = Gem::RDoc.rdoc_version - Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('4.0') - - assert_equal '/doc_root/X-1/', @server.doc_root('X-1') - - ensure - Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version - end - - def test_have_rdoc_4_plus_eh - orig_rdoc_version = Gem::RDoc.rdoc_version - Gem::RDoc.instance_variable_set(:@rdoc_version, Gem::Version.new('4.0')) - - server = Gem::Server.new Gem.dir, 0, false - assert server.have_rdoc_4_plus? - - Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('3.12') - - server = Gem::Server.new Gem.dir, 0, false - refute server.have_rdoc_4_plus? - - Gem::RDoc.instance_variable_set(:@rdoc_version, - Gem::Version.new('4.0.0.preview2')) - - server = Gem::Server.new Gem.dir, 0, false - assert server.have_rdoc_4_plus? - ensure - Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version - end - - def test_spec_dirs - s = Gem::Server.new Gem.dir, process_based_port, false - - assert_equal [File.join(Gem.dir, 'specifications')], s.spec_dirs - - s = Gem::Server.new [Gem.dir, Gem.dir], process_based_port, false - - assert_equal [File.join(Gem.dir, 'specifications'), - File.join(Gem.dir, 'specifications')], s.spec_dirs - end - - def test_latest_specs - data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n" - @req.parse data - - Gem::Deprecate.skip_during do - @server.latest_specs @req, @res - end - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/octet-stream', @res['content-type'] - assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]], - Marshal.load(@res.body) - end - - def test_latest_specs_gemdirs - data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'z', 9 - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - File.open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.latest_specs @req, @res - - assert_equal 200, @res.status - - assert_equal [['z', v(9), Gem::Platform::RUBY]], Marshal.load(@res.body) - end - - def test_latest_specs_gz - data = StringIO.new "GET /latest_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n" - @req.parse data - - Gem::Deprecate.skip_during do - @server.latest_specs @req, @res - end - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/x-gzip', @res['content-type'] - assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]], - Marshal.load(Gem::Util.gunzip(@res.body)) - end - - def test_listen - util_listen - - capture_io do - @server.listen - end - - assert_equal 1, @server.server.listeners.length - end - - def test_listen_addresses - util_listen - - capture_io do - @server.listen %w[a b] - end - - assert_equal 2, @server.server.listeners.length - end - - def test_prerelease_specs - data = StringIO.new "GET /prerelease_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n" - @req.parse data - - Gem::Deprecate.skip_during do - @server.prerelease_specs @req, @res - end - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/octet-stream', @res['content-type'] - assert_equal [['a', v('3.a'), Gem::Platform::RUBY]], - Marshal.load(@res.body) - end - - def test_prerelease_specs_gz - data = StringIO.new "GET /prerelease_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n" - @req.parse data - - Gem::Deprecate.skip_during do - @server.prerelease_specs @req, @res - end - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/x-gzip', @res['content-type'] - assert_equal [['a', v('3.a'), Gem::Platform::RUBY]], - Marshal.load(Gem::Util.gunzip(@res.body)) - end - - def test_quick_gemdirs - data = StringIO.new "GET /quick/Marshal.4.8/z-9.gemspec.rz HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.quick @req, @res - - assert_equal 404, @res.status - - spec = util_spec 'z', 9 - - specs_dir = File.join dir, 'specifications' - - FileUtils.mkdir_p specs_dir - - File.open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - data.rewind - - req = WEBrick::HTTPRequest.new :Logger => nil - res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0' - req.parse data - - server.quick req, res - - assert_equal 200, res.status - end - - def test_quick_missing - data = StringIO.new "GET /quick/Marshal.4.8/z-9.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 404, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'text/plain', @res['content-type'] - assert_equal 'No gems found matching "z-9"', @res.body - assert_equal 404, @res.status - end - - def test_quick_marshal_a_1_gemspec_rz - data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 200, @res.status, @res.body - assert @res['date'] - assert_equal 'application/x-deflate', @res['content-type'] - - spec = Marshal.load Gem::Util.inflate(@res.body) - assert_equal 'a', spec.name - assert_equal Gem::Version.new(1), spec.version - end - - def test_quick_marshal_a_1_mswin32_gemspec_rz - quick_gem 'a', '1' do |s| - s.platform = Gem::Platform.local - end - - data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 200, @res.status, @res.body - assert @res['date'] - assert_equal 'application/x-deflate', @res['content-type'] - - spec = Marshal.load Gem::Util.inflate(@res.body) - assert_equal 'a', spec.name - assert_equal Gem::Version.new(1), spec.version - assert_equal Gem::Platform.local, spec.platform - end - - def test_quick_marshal_a_3_a_gemspec_rz - data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-3.a.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 200, @res.status, @res.body - assert @res['date'] - assert_equal 'application/x-deflate', @res['content-type'] - - spec = Marshal.load Gem::Util.inflate(@res.body) - assert_equal 'a', spec.name - assert_equal v('3.a'), spec.version - end - - def test_quick_marshal_a_b_3_a_gemspec_rz - quick_gem 'a-b', '3.a' - - data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-b-3.a.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 200, @res.status, @res.body - assert @res['date'] - assert_equal 'application/x-deflate', @res['content-type'] - - spec = Marshal.load Gem::Util.inflate(@res.body) - assert_equal 'a-b', spec.name - assert_equal v('3.a'), spec.version - end - - def test_quick_marshal_a_b_1_3_a_gemspec_rz - quick_gem 'a-b-1', '3.a' - - data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-b-1-3.a.gemspec.rz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.quick @req, @res - - assert_equal 200, @res.status, @res.body - assert @res['date'] - assert_equal 'application/x-deflate', @res['content-type'] - - spec = Marshal.load Gem::Util.inflate(@res.body) - assert_equal 'a-b-1', spec.name - assert_equal v('3.a'), spec.version - end - - def test_rdoc - data = StringIO.new "GET /rdoc?q=a HTTP/1.0\r\n\r\n" - @req.parse data - - @server.rdoc @req, @res - - assert_equal 200, @res.status, @res.body - assert_match %r|No documentation found|, @res.body - assert_equal 'text/html', @res['content-type'] - end - - def test_root - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - @req.parse data - - @server.root @req, @res - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'text/html', @res['content-type'] - end - - def test_root_gemdirs - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'z', 9 - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - File.open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.root @req, @res - - assert_equal 200, @res.status - assert_match 'z 9', @res.body - end - - def test_xss_homepage_fix_289313 - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'xsshomepagegem', 1 - spec.homepage = "javascript:confirm(document.domain)" - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.root @req, @res - - assert_equal 200, @res.status - assert_match 'xsshomepagegem 1', @res.body - - # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a - # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here, - # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be - # validated in future versions of Gem::Specification. - # - # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex: - # - # Variant #1 - rdoc not installed - # - # xsshomepagegem 1 - # - # - # [rdoc] - # - # - # - # [www] - # - # Variant #2 - rdoc installed - # - # xsshomepagegem 1 - # - # - # \[rdoc\]<\/a> - # - # - # - # [www] - regex_match = /xsshomepagegem 1<\/b>\s+(\[rdoc\]<\/span>|\[rdoc\]<\/a>)\s+\[www\]<\/a>/ - assert_match regex_match, @res.body - end - - def test_invalid_homepage - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'invalidhomepagegem', 1 - spec.homepage = "notavalidhomepageurl" - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.root @req, @res - - assert_equal 200, @res.status - assert_match 'invalidhomepagegem 1', @res.body - - # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a - # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here, - # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be - # validated in future versions of Gem::Specification. - # - # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex: - # - # Variant #1 - rdoc not installed - # - # invalidhomepagegem 1 - # - # - # [rdoc] - # - # - # - # [www] - # - # Variant #2 - rdoc installed - # - # invalidhomepagegem 1 - # - # - # \[rdoc\]<\/a> - # - # - # - # [www] - regex_match = /invalidhomepagegem 1<\/b>\s+(\[rdoc\]<\/span>|\[rdoc\]<\/a>)\s+\[www\]<\/a>/ - assert_match regex_match, @res.body - end - - def test_valid_homepage_http - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'validhomepagegemhttp', 1 - spec.homepage = "http://rubygems.org" - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.root @req, @res - - assert_equal 200, @res.status - assert_match 'validhomepagegemhttp 1', @res.body - - regex_match = /validhomepagegemhttp 1<\/b>\s+(\[rdoc\]<\/span>|\[rdoc\]<\/a>)\s+\[www\]<\/a>/ - assert_match regex_match, @res.body - end - - def test_valid_homepage_https - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'validhomepagegemhttps', 1 - spec.homepage = "https://rubygems.org" - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.root @req, @res - - assert_equal 200, @res.status - assert_match 'validhomepagegemhttps 1', @res.body - - regex_match = /validhomepagegemhttps 1<\/b>\s+(\[rdoc\]<\/span>|\[rdoc\]<\/a>)\s+\[www\]<\/a>/ - assert_match regex_match, @res.body - end - - def test_specs - data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n" - @req.parse data - - @server.specs @req, @res - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/octet-stream', @res['content-type'] - - assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY], - ['a', Gem::Version.new(2), Gem::Platform::RUBY], - ['a', v('3.a'), Gem::Platform::RUBY]], - Marshal.load(@res.body) - end - - def test_specs_gemdirs - data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n" - dir = "#{@gemhome}2" - - spec = util_spec 'z', 9 - - specs_dir = File.join dir, 'specifications' - FileUtils.mkdir_p specs_dir - - File.open File.join(specs_dir, spec.spec_name), 'w' do |io| - io.write spec.to_ruby - end - - server = Gem::Server.new dir, process_based_port, false - - @req.parse data - - server.specs @req, @res - - assert_equal 200, @res.status - - assert_equal [['z', v(9), Gem::Platform::RUBY]], Marshal.load(@res.body) - end - - def test_specs_gz - data = StringIO.new "GET /specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n" - @req.parse data - - @server.specs @req, @res - - assert_equal 200, @res.status, @res.body - assert_match %r| \d\d:\d\d:\d\d |, @res['date'] - assert_equal 'application/x-gzip', @res['content-type'] - - assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY], - ['a', Gem::Version.new(2), Gem::Platform::RUBY], - ['a', v('3.a'), Gem::Platform::RUBY]], - Marshal.load(Gem::Util.gunzip(@res.body)) - end - - def test_uri_encode - url_safe = @server.uri_encode 'http://rubyonrails.org/">malicious_content' - assert_equal url_safe, 'http://rubyonrails.org/%22%3Emalicious_content%3C/a%3E' - end - - # Regression test for issue #1793: incorrect URL encoding. - # Checking that no URLs have had '://' incorrectly encoded - def test_regression_1793 - data = StringIO.new "GET / HTTP/1.0\r\n\r\n" - @req.parse data - - @server.root @req, @res - - refute_match %r|%3A%2F%2F|, @res.body - end - - def util_listen - webrick = Object.new - webrick.instance_variable_set :@listeners, [] - def webrick.listeners() @listeners end - def webrick.listen(host, port) - socket = Object.new - socket.instance_variable_set :@host, host - socket.instance_variable_set :@port, port - def socket.addr() [nil, @port, @host] end - @listeners << socket - end - - @server.instance_variable_set :@server, webrick - end - -end diff --git a/ruby/test/rubygems/test_gem_silent_ui.rb b/ruby/test/rubygems/test_gem_silent_ui.rb index d49166ff6..355255fb4 100644 --- a/ruby/test/rubygems/test_gem_silent_ui.rb +++ b/ruby/test/rubygems/test_gem_silent_ui.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/user_interaction' require 'timeout' class TestGemSilentUI < Gem::TestCase - def setup super @sui = Gem::SilentUI.new @@ -17,7 +16,7 @@ def teardown def test_ask value = nil - out, err = capture_io do + out, err = capture_output do use_ui @sui do value = @sui.ask 'Problem?' end @@ -31,7 +30,7 @@ def test_ask def test_ask_for_password value = nil - out, err = capture_io do + out, err = capture_output do use_ui @sui do value = @sui.ask_for_password 'Problem?' end @@ -45,9 +44,9 @@ def test_ask_for_password def test_ask_yes_no value = nil - out, err = capture_io do + out, err = capture_output do use_ui @sui do - assert_raises(Gem::OperationNotSupportedError) do + assert_raise(Gem::OperationNotSupportedError) do @sui.ask_yes_no 'Problem?' end end @@ -56,7 +55,7 @@ def test_ask_yes_no assert_empty out, 'No output' assert_empty err, 'No output' - out, err = capture_io do + out, err = capture_output do use_ui @sui do value = @sui.ask_yes_no 'Problem?', true end @@ -67,7 +66,7 @@ def test_ask_yes_no assert value, 'Value is true' - out, err = capture_io do + out, err = capture_output do use_ui @sui do value = @sui.ask_yes_no 'Problem?', false end @@ -81,7 +80,7 @@ def test_ask_yes_no def test_choose_from_list value = nil - out, err = capture_io do + out, err = capture_output do use_ui @sui do value = @sui.choose_from_list 'Problem?', %w[yes no] end @@ -94,7 +93,7 @@ def test_choose_from_list end def test_progress_reporter - out, err = capture_io do + out, err = capture_output do use_ui @sui do @sui.progress_reporter 10, 'hi' end @@ -105,7 +104,7 @@ def test_progress_reporter end def test_download_reporter - out, err = capture_io do + out, err = capture_output do use_ui @sui do @sui.download_reporter.fetch 'a.gem', 1024 end @@ -114,5 +113,4 @@ def test_download_reporter assert_empty out, 'No output' assert_empty err, 'No output' end - end diff --git a/ruby/test/rubygems/test_gem_source.rb b/ruby/test/rubygems/test_gem_source.rb index 30b45ea26..24312626f 100644 --- a/ruby/test/rubygems/test_gem_source.rb +++ b/ruby/test/rubygems/test_gem_source.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' require 'rubygems/indexer' class TestGemSource < Gem::TestCase - def tuple(*args) Gem::NameTuple.new(*args) end @@ -23,7 +22,7 @@ def setup end def test_initialize_invalid_uri - assert_raises URI::InvalidURIError do + assert_raise URI::InvalidURIError do Gem::Source.new 'git@example:a.git' end end @@ -45,9 +44,9 @@ def test_cache_dir_escapes_windows_paths def test_dependency_resolver_set_bundler_api response = Net::HTTPResponse.new '1.1', 200, 'OK' - response.uri = URI('http://example') if response.respond_to? :uri + response.uri = URI('http://example') - @fetcher.data["#{@gem_repo}api/v1/dependencies"] = response + @fetcher.data[@gem_repo] = response set = @source.dependency_resolver_set @@ -55,8 +54,6 @@ def test_dependency_resolver_set_bundler_api end def test_dependency_resolver_set_file_uri - skip 'install builder gem' unless defined? Builder::XChar - Gem::Indexer.new(@tempdir).generate_index source = Gem::Source.new "file://#{@tempdir}/" @@ -125,7 +122,7 @@ def test_fetch_spec_platform_ruby end def test_load_specs - released = @source.load_specs(:released).map { |spec| spec.full_name } + released = @source.load_specs(:released).map {|spec| spec.full_name } assert_equal %W[a-2 a-1 b-2], released cache_dir = File.join Gem.spec_cache_dir, 'gems.example.com%80' @@ -188,7 +185,7 @@ def test_load_specs_cached_empty def test_load_specs_from_unavailable_uri src = Gem::Source.new("http://not-there.nothing") - assert_raises Gem::RemoteFetcher::FetchError do + assert_raise Gem::RemoteFetcher::FetchError do src.load_specs :latest end end @@ -199,30 +196,30 @@ def test_spaceship installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, remote. <=>(remote), 'remote <=> remote') + assert_equal(0, remote.<=>(remote), 'remote <=> remote') - assert_equal(-1, remote. <=>(specific), 'remote <=> specific') - assert_equal(1, specific. <=>(remote), 'specific <=> remote') + assert_equal(-1, remote.<=>(specific), 'remote <=> specific') + assert_equal(1, specific.<=>(remote), 'specific <=> remote') - assert_equal(-1, remote. <=>(local), 'remote <=> local') - assert_equal(1, local. <=>(remote), 'local <=> remote') + assert_equal(-1, remote.<=>(local), 'remote <=> local') + assert_equal(1, local.<=>(remote), 'local <=> remote') - assert_equal(-1, remote. <=>(installed), 'remote <=> installed') - assert_equal(1, installed.<=>(remote), 'installed <=> remote') + assert_equal(-1, remote.<=>(installed), 'remote <=> installed') + assert_equal(1, installed.<=>(remote), 'installed <=> remote') no_uri = @source.dup no_uri.instance_variable_set :@uri, nil - assert_equal(-1, remote. <=>(no_uri), 'remote <=> no_uri') + assert_equal(-1, remote.<=>(no_uri), 'remote <=> no_uri') end def test_spaceship_order_is_preserved_when_uri_differs sourceA = Gem::Source.new "http://example.com/a" sourceB = Gem::Source.new "http://example.com/b" - assert_equal(0, sourceA. <=>(sourceA), 'sourceA <=> sourceA') - assert_equal(1, sourceA. <=>(sourceB), 'sourceA <=> sourceB') - assert_equal(1, sourceB. <=>(sourceA), 'sourceB <=> sourceA') + assert_equal(0, sourceA.<=>(sourceA), 'sourceA <=> sourceA') + assert_equal(1, sourceA.<=>(sourceB), 'sourceA <=> sourceB') + assert_equal(1, sourceB.<=>(sourceA), 'sourceB <=> sourceA') end def test_update_cache_eh @@ -243,10 +240,14 @@ def test_typo_squatting refute rubygems_source.typo_squatting?("rubysertgems.org") end + def test_typo_squatting_false_positive + rubygems_source = Gem::Source.new("https://rubygems.org") + refute rubygems_source.typo_squatting?("rubygems.org") + end + def test_typo_squatting_custom_distance_threshold rubygems_source = Gem::Source.new("https://rubgems.org") distance_threshold = 5 assert rubygems_source.typo_squatting?("rubysertgems.org", distance_threshold) end - end diff --git a/ruby/test/rubygems/test_gem_source_fetch_problem.rb b/ruby/test/rubygems/test_gem_source_fetch_problem.rb index 65b182890..816407781 100644 --- a/ruby/test/rubygems/test_gem_source_fetch_problem.rb +++ b/ruby/test/rubygems/test_gem_source_fetch_problem.rb @@ -1,15 +1,14 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemSourceFetchProblem < Gem::TestCase - def test_exception source = Gem::Source.new @gem_repo error = RuntimeError.new 'test' sf = Gem::SourceFetchProblem.new source, error - e = assert_raises RuntimeError do + e = assert_raise RuntimeError do raise sf end @@ -25,4 +24,13 @@ def test_password_redacted refute_match sf.wordy, 'secret' end + def test_source_password_no_redacted + source = Gem::Source.new 'https://username:secret@gemsource.com' + error = RuntimeError.new 'test' + + sf = Gem::SourceFetchProblem.new source, error + sf.wordy + + assert_match 'secret', source.uri.to_s + end end diff --git a/ruby/test/rubygems/test_gem_source_git.rb b/ruby/test/rubygems/test_gem_source_git.rb index 22fbdee05..73ed8dd2e 100644 --- a/ruby/test/rubygems/test_gem_source_git.rb +++ b/ruby/test/rubygems/test_gem_source_git.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' class TestGemSourceGit < Gem::TestCase - def setup super @@ -25,7 +24,7 @@ def test_base_dir def test_checkout @source.checkout - assert_path_exists File.join @source.install_dir, 'a.gemspec' + assert_path_exist File.join @source.install_dir, 'a.gemspec' end def test_checkout_master @@ -40,7 +39,7 @@ def test_checkout_master @source.checkout - assert_path_exists File.join @source.install_dir, 'b.gemspec' + assert_path_exist File.join @source.install_dir, 'b.gemspec' end def test_checkout_local @@ -50,7 +49,7 @@ def test_checkout_local install_dir = File.join Gem.dir, 'bundler', 'gems', "a-#{@head[0..11]}" - refute_path_exists File.join install_dir, 'a.gemspec' + assert_path_not_exist File.join install_dir, 'a.gemspec' end def test_checkout_local_cached @@ -60,7 +59,7 @@ def test_checkout_local_cached @source.checkout - assert_path_exists File.join @source.install_dir, 'a.gemspec' + assert_path_exist File.join @source.install_dir, 'a.gemspec' end def test_checkout_submodules @@ -69,21 +68,22 @@ def test_checkout_submodules git_gem 'b' Dir.chdir 'git/a' do - Gem::Util.silent_system @git, 'submodule', '--quiet', - 'add', File.expand_path('../b'), 'b' + output, status = Open3.capture2e(@git, 'submodule', '--quiet', 'add', File.expand_path('../b'), 'b') + assert status.success?, output + system @git, 'commit', '--quiet', '-m', 'add submodule b' end source.checkout - assert_path_exists File.join source.install_dir, 'a.gemspec' - assert_path_exists File.join source.install_dir, 'b/b.gemspec' + assert_path_exist File.join source.install_dir, 'a.gemspec' + assert_path_exist File.join source.install_dir, 'b/b.gemspec' end def test_cache assert @source.cache - assert_path_exists @source.repo_cache_dir + assert_path_exist @source.repo_cache_dir Dir.chdir @source.repo_cache_dir do assert_equal @head, Gem::Util.popen(@git, 'rev-parse', 'master').strip @@ -95,7 +95,7 @@ def test_cache_local @source.cache - refute_path_exists @source.repo_cache_dir + assert_path_not_exist @source.repo_cache_dir end def test_dir_shortref @@ -186,8 +186,8 @@ def test_rev_parse source.cache - e = assert_raises Gem::Exception do - capture_subprocess_io {source.rev_parse} + e = assert_raise Gem::Exception do + capture_subprocess_io { source.rev_parse } end assert_equal "unable to find reference nonexistent in #{@repository}", @@ -208,16 +208,16 @@ def test_spaceship installed = Gem::Source::Installed.new vendor = Gem::Source::Vendor.new 'vendor/foo' - assert_equal(0, git. <=>(git), 'git <=> git') + assert_equal(0, git.<=>(git), 'git <=> git') - assert_equal(1, git. <=>(remote), 'git <=> remote') - assert_equal(-1, remote. <=>(git), 'remote <=> git') + assert_equal(1, git.<=>(remote), 'git <=> remote') + assert_equal(-1, remote.<=>(git), 'remote <=> git') - assert_equal(1, git. <=>(installed), 'git <=> installed') - assert_equal(-1, installed.<=>(git), 'installed <=> git') + assert_equal(1, git.<=>(installed), 'git <=> installed') + assert_equal(-1, installed.<=>(git), 'installed <=> git') - assert_equal(-1, git. <=>(vendor), 'git <=> vendor') - assert_equal(1, vendor. <=>(git), 'vendor <=> git') + assert_equal(-1, git.<=>(vendor), 'git <=> vendor') + assert_equal(1, vendor.<=>(git), 'vendor <=> git') end def test_specs @@ -240,11 +240,11 @@ def test_specs specs = nil - capture_io do + capture_output do specs = source.specs end - assert_equal %w[a-1 b-1], specs.map { |spec| spec.full_name } + assert_equal %w[a-1 b-1], specs.map {|spec| spec.full_name } a_spec = specs.shift @@ -275,7 +275,7 @@ def test_specs_local source = Gem::Source::Git.new @name, @repository, 'master', true source.remote = false - capture_io do + capture_output do assert_empty source.specs end end @@ -299,5 +299,4 @@ def test_uri_hash assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe', source.uri_hash end - end diff --git a/ruby/test/rubygems/test_gem_source_installed.rb b/ruby/test/rubygems/test_gem_source_installed.rb index b4a75d8d4..ef9b63e61 100644 --- a/ruby/test/rubygems/test_gem_source_installed.rb +++ b/ruby/test/rubygems/test_gem_source_installed.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' class TestGemSourceInstalled < Gem::TestCase - def test_spaceship a1 = quick_gem 'a', '1' util_build_gem a1 @@ -17,20 +16,19 @@ def test_spaceship assert_equal(0, installed.<=>(installed), 'installed <=> installed') - assert_equal(-1, remote. <=>(installed), 'remote <=> installed') + assert_equal(-1, remote.<=>(installed), 'remote <=> installed') assert_equal(1, installed.<=>(remote), 'installed <=> remote') assert_equal(1, installed.<=>(local), 'installed <=> local') - assert_equal(-1, local. <=>(installed), 'local <=> installed') + assert_equal(-1, local.<=>(installed), 'local <=> installed') - assert_equal(-1, specific. <=>(installed), 'specific <=> installed') + assert_equal(-1, specific.<=>(installed), 'specific <=> installed') assert_equal(1, installed.<=>(specific), 'installed <=> specific') - assert_equal(1, git. <=>(installed), 'git <=> installed') - assert_equal(-1, installed.<=>(git), 'installed <=> git') + assert_equal(1, git. <=>(installed), 'git <=> installed') + assert_equal(-1, installed.<=>(git), 'installed <=> git') - assert_equal(1, vendor. <=>(installed), 'vendor <=> installed') - assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor') + assert_equal(1, vendor.<=>(installed), 'vendor <=> installed') + assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor') end - end diff --git a/ruby/test/rubygems/test_gem_source_list.rb b/ruby/test/rubygems/test_gem_source_list.rb index b05703f0b..6ac5dbb2a 100644 --- a/ruby/test/rubygems/test_gem_source_list.rb +++ b/ruby/test/rubygems/test_gem_source_list.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true +require 'rubygems' require 'rubygems/source_list' -require 'rubygems/test_case' +require_relative 'helper' class TestGemSourceList < Gem::TestCase - def setup super @@ -115,5 +115,4 @@ def test_delete_a_source @sl.delete Gem::Source.new(@uri) assert_equal @sl.sources, [] end - end diff --git a/ruby/test/rubygems/test_gem_source_local.rb b/ruby/test/rubygems/test_gem_source_local.rb index 2f796f0ed..2d4ddbc3a 100644 --- a/ruby/test/rubygems/test_gem_source_local.rb +++ b/ruby/test/rubygems/test_gem_source_local.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' require 'fileutils' class TestGemSourceLocal < Gem::TestCase - def setup super @@ -73,7 +72,7 @@ def test_inspect @sl.load_specs :released - inner = [@a, @ap, @b].map { |t| t.name_tuple }.inspect + inner = [@a, @ap, @b].map {|t| t.name_tuple }.inspect assert_equal "#", @sl.inspect end @@ -93,16 +92,15 @@ def test_spaceship installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, local. <=>(local), 'local <=> local') + assert_equal(0, local.<=>(local), 'local <=> local') - assert_equal(-1, remote. <=>(local), 'remote <=> local') - assert_equal(1, local. <=>(remote), 'local <=> remote') + assert_equal(-1, remote.<=>(local), 'remote <=> local') + assert_equal(1, local.<=>(remote), 'local <=> remote') - assert_equal(1, installed.<=>(local), 'installed <=> local') - assert_equal(-1, local. <=>(installed), 'local <=> installed') + assert_equal(1, installed.<=>(local), 'installed <=> local') + assert_equal(-1, local.<=>(installed), 'local <=> installed') - assert_equal(-1, specific. <=>(local), 'specific <=> local') - assert_equal(1, local. <=>(specific), 'local <=> specific') + assert_equal(-1, specific.<=>(local), 'specific <=> local') + assert_equal(1, local.<=>(specific), 'local <=> specific') end - end diff --git a/ruby/test/rubygems/test_gem_source_lock.rb b/ruby/test/rubygems/test_gem_source_lock.rb index 953941b01..5f916cdf7 100644 --- a/ruby/test/rubygems/test_gem_source_lock.rb +++ b/ruby/test/rubygems/test_gem_source_lock.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemSourceLock < Gem::TestCase - def test_fetch_spec spec_fetcher do |fetcher| fetcher.spec 'a', 1 @@ -59,31 +58,31 @@ def test_spaceship_git lock = Gem::Source::Lock.new git assert_equal(1, lock.<=>(git), 'lock <=> git') - assert_equal(-1, git .<=>(lock), 'git <=> lock') + assert_equal(-1, git.<=>(lock), 'git <=> lock') end def test_spaceship_installed installed = Gem::Source::Installed.new lock = Gem::Source::Lock.new installed - assert_equal(1, lock. <=>(installed), 'lock <=> installed') - assert_equal(-1, installed.<=>(lock), 'installed <=> lock') + assert_equal(1, lock.<=>(installed), 'lock <=> installed') + assert_equal(-1, installed.<=>(lock), 'installed <=> lock') end def test_spaceship_local local = Gem::Source::Local.new lock = Gem::Source::Lock.new local # nonsense - assert_equal(1, lock. <=>(local), 'lock <=> local') - assert_equal(-1, local.<=>(lock), 'local <=> lock') + assert_equal(1, lock.<=>(local), 'lock <=> local') + assert_equal(-1, local.<=>(lock), 'local <=> lock') end def test_spaceship_remote remote = Gem::Source.new @gem_repo lock = Gem::Source::Lock.new remote - assert_equal(1, lock. <=>(remote), 'lock <=> remote') - assert_equal(-1, remote.<=>(lock), 'remote <=> lock') + assert_equal(1, lock.<=>(remote), 'lock <=> remote') + assert_equal(-1, remote.<=>(lock), 'remote <=> lock') end def test_spaceship_specific_file @@ -92,7 +91,7 @@ def test_spaceship_specific_file specific = Gem::Source::SpecificFile.new gem lock = Gem::Source::Lock.new specific # nonsense - assert_equal(1, lock .<=>(specific), 'lock <=> specific') + assert_equal(1, lock.<=>(specific), 'lock <=> specific') assert_equal(-1, specific.<=>(lock), 'specific <=> lock') end @@ -100,8 +99,8 @@ def test_spaceship_vendor vendor = Gem::Source::Vendor.new 'vendor/a' lock = Gem::Source::Lock.new vendor - assert_equal(1, lock. <=>(vendor), 'lock <=> vendor') - assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock') + assert_equal(1, lock.<=>(vendor), 'lock <=> vendor') + assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock') end def test_uri @@ -110,5 +109,4 @@ def test_uri assert_equal URI(@gem_repo), lock.uri end - end diff --git a/ruby/test/rubygems/test_gem_source_specific_file.rb b/ruby/test/rubygems/test_gem_source_specific_file.rb index 9e4ebaa9c..72ed993a8 100644 --- a/ruby/test/rubygems/test_gem_source_specific_file.rb +++ b/ruby/test/rubygems/test_gem_source_specific_file.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' class TestGemSourceSpecificFile < Gem::TestCase - def setup super @@ -28,7 +27,7 @@ def test_fetch_spec end def test_fetch_spec_fails_on_unknown_name - assert_raises Gem::Exception do + assert_raise Gem::Exception do @sf.fetch_spec(nil) end end @@ -46,16 +45,16 @@ def test_spaceship installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, specific. <=>(specific), 'specific <=> specific') + assert_equal(0, specific.<=>(specific), 'specific <=> specific') - assert_equal(-1, remote. <=>(specific), 'remote <=> specific') - assert_equal(1, specific. <=>(remote), 'specific <=> remote') + assert_equal(-1, remote.<=>(specific), 'remote <=> specific') + assert_equal(1, specific.<=>(remote), 'specific <=> remote') - assert_equal(-1, specific. <=>(local), 'specific <=> local') - assert_equal(1, local. <=>(specific), 'local <=> specific') + assert_equal(-1, specific.<=>(local), 'specific <=> local') + assert_equal(1, local. <=>(specific), 'local <=> specific') - assert_equal(-1, specific. <=>(installed), 'specific <=> installed') - assert_equal(1, installed.<=>(specific), 'installed <=> specific') + assert_equal(-1, specific. <=>(installed), 'specific <=> installed') + assert_equal(1, installed.<=>(specific), 'installed <=> specific') a2 = quick_gem 'a', '2' util_build_gem a2 @@ -73,5 +72,4 @@ def test_spaceship assert_equal(0, a1_source.<=>(a1_source), 'a1_source <=> a1_source') assert_equal(1, a2_source.<=>(a1_source), 'a2_source <=> a1_source') end - end diff --git a/ruby/test/rubygems/test_gem_source_subpath_problem.rb b/ruby/test/rubygems/test_gem_source_subpath_problem.rb new file mode 100644 index 000000000..c37df39f0 --- /dev/null +++ b/ruby/test/rubygems/test_gem_source_subpath_problem.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +require_relative 'helper' +require 'rubygems/source' + +class TestGemSourceSubpathProblem < Gem::TestCase + def tuple(*args) + Gem::NameTuple.new(*args) + end + + def setup + super + + @gem_repo = "http://gems.example.com/private" + + spec_fetcher + + @source = Gem::Source.new(@gem_repo) + + util_make_gems + end + + def test_dependency_resolver_set + response = Net::HTTPResponse.new '1.1', 200, 'OK' + response.uri = URI('http://example') + + @fetcher.data["#{@gem_repo}/"] = response + + set = @source.dependency_resolver_set + + assert_kind_of Gem::Resolver::APISet, set + end + + def test_fetch_spec + @fetcher.data["#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] = Zlib::Deflate.deflate(Marshal.dump(@a1)) + + spec = @source.fetch_spec tuple('a', Gem::Version.new(1), 'ruby') + assert_equal @a1.full_name, spec.full_name + end + + def test_load_specs + @fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([ + Gem::NameTuple.new(@a1.name, @a1.version, 'ruby'), + Gem::NameTuple.new(@b2.name, @b2.version, 'ruby'), + ])) + + released = @source.load_specs(:latest).map {|spec| spec.full_name } + assert_equal %W[a-1 b-2], released + end +end diff --git a/ruby/test/rubygems/test_gem_source_vendor.rb b/ruby/test/rubygems/test_gem_source_vendor.rb index fafe1a190..a5ffb0f22 100644 --- a/ruby/test/rubygems/test_gem_source_vendor.rb +++ b/ruby/test/rubygems/test_gem_source_vendor.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/source' class TestGemSourceVendor < Gem::TestCase - def test_initialize source = Gem::Source::Vendor.new 'vendor/foo' @@ -16,16 +15,15 @@ def test_spaceship git = Gem::Source::Git.new 'a', 'a', 'master' installed = Gem::Source::Installed.new - assert_equal(0, vendor. <=>(vendor), 'vendor <=> vendor') + assert_equal(0, vendor.<=>(vendor), 'vendor <=> vendor') - assert_equal(1, vendor. <=>(remote), 'vendor <=> remote') - assert_equal(-1, remote. <=>(vendor), 'remote <=> vendor') + assert_equal(1, vendor.<=>(remote), 'vendor <=> remote') + assert_equal(-1, remote.<=>(vendor), 'remote <=> vendor') - assert_equal(1, vendor. <=>(git), 'vendor <=> git') - assert_equal(-1, git. <=>(vendor), 'git <=> vendor') + assert_equal(1, vendor.<=>(git), 'vendor <=> git') + assert_equal(-1, git.<=>(vendor), 'git <=> vendor') - assert_equal(1, vendor. <=>(installed), 'vendor <=> installed') - assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor') + assert_equal(1, vendor.<=>(installed), 'vendor <=> installed') + assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor') end - end diff --git a/ruby/test/rubygems/test_gem_spec_fetcher.rb b/ruby/test/rubygems/test_gem_spec_fetcher.rb index 99862ce87..afae46e12 100644 --- a/ruby/test/rubygems/test_gem_spec_fetcher.rb +++ b/ruby/test/rubygems/test_gem_spec_fetcher.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/spec_fetcher' class TestGemSpecFetcher < Gem::TestCase - def tuple(*args) Gem::NameTuple.new(*args) end @@ -39,7 +38,7 @@ def test_initialize_nonexistent_home_dir end def test_initialize_unwritable_home_dir - skip 'chmod not supported' if Gem.win_platform? + pend 'chmod not supported' if Gem.win_platform? FileUtils.chmod 0000, Gem.user_home @@ -173,10 +172,19 @@ def test_suggest_gems_from_name_latest spec_fetcher do|fetcher| fetcher.spec 'example', 1 fetcher.spec 'other-example', 1 + fetcher.spec 'examp', 1 end - suggestions = @sf.suggest_gems_from_name('examplw') + suggestions = @sf.suggest_gems_from_name('examplw', :latest, 1) assert_equal ['example'], suggestions + + suggestions = @sf.suggest_gems_from_name('other') + assert_equal ['other-example'], suggestions + + suggestions = @sf.suggest_gems_from_name('exam') + assert suggestions.any? { ['examp'] } + assert suggestions.any? { ['example'] } + assert suggestions.any? { ['other-example'] } end def test_suggest_gems_from_name_prerelease @@ -313,7 +321,7 @@ def test_available_specs_prerelease specs, _ = @sf.available_specs(:prerelease) expected = Gem::NameTuple.from_list \ - [['a', v('2.a'), Gem::Platform::RUBY]] + [['a', v('2.a'), Gem::Platform::RUBY]] assert_equal expected, specs[@source] end @@ -326,5 +334,4 @@ def test_available_specs_with_bad_source assert_equal({}, specs) assert_kind_of Gem::SourceFetchProblem, errors.first end - end diff --git a/ruby/test/rubygems/test_gem_specification.rb b/ruby/test/rubygems/test_gem_specification.rb index dbd45a31f..8b4a07d23 100644 --- a/ruby/test/rubygems/test_gem_specification.rb +++ b/ruby/test/rubygems/test_gem_specification.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'benchmark' -require 'rubygems/test_case' +require_relative 'helper' +require 'date' require 'pathname' require 'stringio' require 'rubygems/ext' @@ -9,7 +10,6 @@ require 'rubygems/platform' class TestGemSpecification < Gem::TestCase - LEGACY_YAML_SPEC = <<-EOF.freeze --- !ruby/object:Gem::Specification rubygems_version: "1.0" @@ -83,6 +83,11 @@ def assert_date(date) def setup super + # Setting `@default_source_date_epoch` to `nil` effectively resets the + # value used for `Gem.source_date_epoch` whenever `$SOURCE_DATE_EPOCH` + # is not set. + Gem.instance_variable_set(:'@default_source_date_epoch', nil) + @a1 = util_spec 'a', '1' do |s| s.executable = 'exec' s.test_file = 'test/suite.rb' @@ -102,8 +107,6 @@ def setup end @current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - - load 'rubygems/syck_hack.rb' end def test_self_find_active_stub_by_path @@ -124,265 +127,242 @@ def test_self_activate end def test_self_activate_ambiguous_direct - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb") - b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb") - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb") + b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb") + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" - Gem::Specification.reset - install_specs c1, c2, b1, b2, a1 + Gem::Specification.reset + install_specs c1, c2, b1, b2, a1 - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + a1.activate + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + assert_equal [], unresolved_names end def test_find_in_unresolved_tree_is_not_exponentiental - save_loaded_features do - num_of_pkg = 7 - num_of_version_per_pkg = 3 - packages = (0..num_of_pkg).map do |pkgi| - (0..num_of_version_per_pkg).map do |pkg_version| - deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi| - ["pkg#{deppkgi}", ">= 0"] - end] - util_spec "pkg#{pkgi}", pkg_version.to_s, deps - end + pend "currently slower in CI on TruffleRuby" if RUBY_ENGINE == 'truffleruby' + num_of_pkg = 7 + num_of_version_per_pkg = 3 + packages = (0..num_of_pkg).map do |pkgi| + (0..num_of_version_per_pkg).map do |pkg_version| + deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi| + ["pkg#{deppkgi}", ">= 0"] + end] + util_spec "pkg#{pkgi}", pkg_version.to_s, deps end - base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"} + end + base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"} - Gem::Specification.reset - install_specs(*packages.flatten.reverse) - install_specs base - base.activate + Gem::Specification.reset + install_specs(*packages.flatten.reverse) + install_specs base + base.activate - tms = Benchmark.measure do - assert_raises(LoadError) { require 'no_such_file_foo' } - end - assert_operator tms.total, :<=, 10 + tms = Benchmark.measure do + assert_raise(LoadError) { require 'no_such_file_foo' } end + assert_operator tms.total, :<=, 10 end def test_self_activate_ambiguous_indirect - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" - c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" + c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + a1.activate + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + assert_equal [], unresolved_names end def test_self_activate_ambiguous_indirect_conflict - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - a2 = util_spec "a", "2", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" - c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2 + a1 = util_spec "a", "1", "b" => "> 0" + a2 = util_spec "a", "2", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" + c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2 - install_specs c1, b1, a1, a2, c2, b2 + install_specs c1, b1, a1, a2, c2, b2 - a2.activate - assert_equal %w(a-2), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + a2.activate + assert_equal %w[a-2], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-2 b-1 c-1), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-2 b-1 c-1], loaded_spec_names + assert_equal [], unresolved_names end def test_self_activate_ambiguous_unrelated - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" - install_specs d1, c1, c2, b1, b2, a1 + install_specs d1, c1, c2, b1, b2, a1 - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + a1.activate + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 d-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - end + assert_equal %w[a-1 d-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names end def test_require_should_prefer_latest_gem_level1 - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 0" # unresolved - b2 = util_spec "b", "2", "c" => ">= 0" - c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level - c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level + c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate + a1.activate - require "c#{$$}" + require "c#{$$}" - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names end def test_require_should_prefer_latest_gem_level2 - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 0" # unresolved - b2 = util_spec "b", "2", "c" => ">= 0" - c1 = util_spec "c", "1", "d" => ">= 0" # 1st level - c2 = util_spec "c", "2", "d" => ">= 0" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level - d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => ">= 0" # 1st level + c2 = util_spec "c", "2", "d" => ">= 0" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" - install_specs d1, d2, c1, c2, b1, b2, a1 + install_specs d1, d2, c1, c2, b1, b2, a1 - a1.activate + a1.activate - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names - end + assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names end def test_require_finds_in_2nd_level_indirect - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 0" # unresolved - b2 = util_spec "b", "2", "c" => ">= 0" - c1 = util_spec "c", "1", "d" => "<= 2" # 1st level - c2 = util_spec "c", "2", "d" => "<= 2" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level - d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" - d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" + d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" - install_specs d1, d2, d3, c1, c2, b1, b2, a1 + install_specs d1, d2, d3, c1, c2, b1, b2, a1 - a1.activate + a1.activate - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names - end + assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names end def test_require_should_prefer_reachable_gems - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 0" # unresolved - b2 = util_spec "b", "2", "c" => ">= 0" - c1 = util_spec "c", "1", "d" => "<= 2" # 1st level - c2 = util_spec "c", "2", "d" => "<= 2" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level - d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" - d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" - e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" + d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb" + + install_specs d1, d2, d3, e, c1, c2, b1, b2, a1 - install_specs d1, d2, d3, e, c1, c2, b1, b2, a1 - - a1.activate + a1.activate - require "d#{$$}" + require "d#{$$}" - assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names - end + assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names end def test_require_should_not_conflict - save_loaded_features do - base = util_spec "0", "1", "A" => ">= 1" - a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" - a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" - b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d#{$$}.rb" - b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d#{$$}.rb" - c1 = util_spec "c", "1", {}, "lib/c.rb" - c2 = util_spec "c", "2", {}, "lib/c.rb" - c3 = util_spec "c", "3", {}, "lib/c.rb" - - install_specs c1, c2, c3, b1, b2, a1, a2, base - - base.activate - assert_equal %w(0-1), loaded_spec_names - assert_equal ["A (>= 1)"], unresolved_names + base = util_spec "0", "1", "A" => ">= 1" + a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" + a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" + b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d#{$$}.rb" + b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d#{$$}.rb" + c1 = util_spec "c", "1", {}, "lib/c.rb" + c2 = util_spec "c", "2", {}, "lib/c.rb" + c3 = util_spec "c", "3", {}, "lib/c.rb" - require "d#{$$}" + install_specs c1, c2, c3, b1, b2, a1, a2, base - assert_equal %w(0-1 A-2 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end + base.activate + assert_equal %w[0-1], loaded_spec_names + assert_equal ["A (>= 1)"], unresolved_names + + require "d#{$$}" + + assert_equal %w[0-1 A-2 b-2 c-2], loaded_spec_names + assert_equal [], unresolved_names end def test_inner_clonflict_in_indirect_gems - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" # unresolved - b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3" - c1 = util_spec "c", "1", "d" => "<= 2" # 1st level - c2 = util_spec "c", "2", "d" => "<= 2" - c3 = util_spec "c", "3", "d" => "<= 3" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level - d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" - d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" # unresolved + b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + c3 = util_spec "c", "3", "d" => "<= 3" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" + d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + + install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 - install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 - - a1.activate + a1.activate - require "d#{$$}" + require "d#{$$}" - assert_includes [%w(a-1 b-2 c-3 d-2),%w(a-1 b-2 d-2)], loaded_spec_names - end + assert_includes [%w[a-1 b-2 c-3 d-2],%w[a-1 b-2 d-2]], loaded_spec_names end def test_inner_clonflict_in_indirect_gems_reversed - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved - b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3" - c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level - c2 = util_spec "xc", "2", "d" => "<= 2" - c3 = util_spec "xc", "3", "d" => "<= 3" - d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level - d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" - d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved + b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3" + c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level + c2 = util_spec "xc", "2", "d" => "<= 2" + c3 = util_spec "xc", "3", "d" => "<= 3" + d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb" + d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb" + + install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 - install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 + a1.activate - a1.activate + require "d#{$$}" - require "d#{$$}" - - assert_includes [%w(a-1 b-2 d-2 xc-3), %w(a-1 b-2 d-2)], loaded_spec_names - end + assert_includes [%w[a-1 b-2 d-2 xc-3], %w[a-1 b-2 d-2]], loaded_spec_names end ## @@ -401,7 +381,7 @@ def test_self_activate_checks_dependencies c = util_spec 'c', '1.0', 'b' => '= 2.0' install_specs b1, b2, c, a - e = assert_raises Gem::LoadError do + e = assert_raise Gem::LoadError do assert_activate nil, a, c, "b" end @@ -423,7 +403,7 @@ def test_self_activate_divergent install_specs b1, b2, c, a - e = assert_raises Gem::ConflictError do + e = assert_raise Gem::ConflictError do assert_activate nil, a, c, "b" end @@ -506,41 +486,37 @@ def test_self_activate_via_require install_specs b1, b2, a1 a1.activate - save_loaded_features do - require "b/c" - end + require "b/c" - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names end def test_self_activate_via_require_wtf - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb" - b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" # this - d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb" - d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb" + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" # this + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this - install_specs c1, c2, b1, b2, d1, d2, a1 + install_specs c1, c2, b1, b2, d1, d2, a1 - a1.activate + a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)", "d (> 0)"], unresolved_names + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)", "d (> 0)"], unresolved_names - require "b#{$$}" + require "b#{$$}" - e = assert_raises Gem::LoadError do - require "d#{$$}" - end + e = assert_raise Gem::LoadError do + require "d#{$$}" + end - assert_equal "unable to find a version of 'd' to activate", e.message + assert_equal "unable to find a version of 'd' to activate", e.message - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal ["d (> 0)"], unresolved_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + assert_equal ["d (> 0)"], unresolved_names end def test_self_activate_deep_unambiguous @@ -553,7 +529,7 @@ def test_self_activate_deep_unambiguous install_specs c1, c2, b1, b2, a1 a1.activate - assert_equal %w(a-1 b-1 c-1), loaded_spec_names + assert_equal %w[a-1 b-1 c-1], loaded_spec_names end def test_self_activate_loaded @@ -668,7 +644,7 @@ def test_self_activate_conflict gem "b", "= 1.0" - assert_raises Gem::LoadError do + assert_raise Gem::LoadError do gem "b", "= 2.0" end end @@ -715,7 +691,7 @@ def test_self_attribute_names version ] - actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort + actual_value = Gem::Specification.attribute_names.map {|a| a.to_s }.sort assert_equal expected_value, actual_value end @@ -742,125 +718,6 @@ def test_self_from_yaml spec.specification_version end - def test_self_from_yaml_syck_date_bug - # This is equivalent to (and totally valid) psych 1.0 output and - # causes parse errors on syck. - yaml = @a1.to_yaml - yaml.sub!(/^date:.*/, "date: 2011-04-26 00:00:00.000000000Z") - - spec = with_syck do - Gem::Specification.from_yaml yaml - end - - assert_kind_of Time, @a1.date - assert_kind_of Time, spec.date - end - - def test_self_from_yaml_syck_default_key_bug - # This is equivalent to (and totally valid) psych 1.0 output and - # causes parse errors on syck. - yaml = <<-YAML ---- !ruby/object:Gem::Specification -name: posix-spawn -version: !ruby/object:Gem::Version - version: 0.3.6 - prerelease: -dependencies: -- !ruby/object:Gem::Dependency - name: rake-compiler - requirement: &70243867725240 !ruby/object:Gem::Requirement - none: false - requirements: - - - = - - !ruby/object:Gem::Version - version: 0.7.6 - type: :development - prerelease: false - version_requirements: *70243867725240 -platform: ruby -files: [] -test_files: [] -bindir: - YAML - - spec = with_syck do - Gem::Specification.from_yaml yaml - end - - op = spec.dependencies.first.requirement.requirements.first.first - refute_kind_of YAML::Syck::DefaultKey, op - - refute_match %r%DefaultKey%, spec.to_ruby - end - - def test_self_from_yaml_cleans_up_defaultkey - yaml = <<-YAML ---- !ruby/object:Gem::Specification -name: posix-spawn -version: !ruby/object:Gem::Version - version: 0.3.6 - prerelease: -dependencies: -- !ruby/object:Gem::Dependency - name: rake-compiler - requirement: &70243867725240 !ruby/object:Gem::Requirement - none: false - requirements: - - - !ruby/object:YAML::Syck::DefaultKey {} - - - !ruby/object:Gem::Version - version: 0.7.6 - type: :development - prerelease: false - version_requirements: *70243867725240 -platform: ruby -files: [] -test_files: [] -bindir: - YAML - - spec = Gem::Specification.from_yaml yaml - - op = spec.dependencies.first.requirement.requirements.first.first - refute_kind_of YAML::Syck::DefaultKey, op - - refute_match %r%DefaultKey%, spec.to_ruby - end - - def test_self_from_yaml_cleans_up_defaultkey_from_newer_192 - yaml = <<-YAML ---- !ruby/object:Gem::Specification -name: posix-spawn -version: !ruby/object:Gem::Version - version: 0.3.6 - prerelease: -dependencies: -- !ruby/object:Gem::Dependency - name: rake-compiler - requirement: &70243867725240 !ruby/object:Gem::Requirement - none: false - requirements: - - - !ruby/object:Syck::DefaultKey {} - - - !ruby/object:Gem::Version - version: 0.7.6 - type: :development - prerelease: false - version_requirements: *70243867725240 -platform: ruby -files: [] -test_files: [] -bindir: - YAML - - spec = Gem::Specification.from_yaml yaml - - op = spec.dependencies.first.requirement.requirements.first.first - refute_kind_of YAML::Syck::DefaultKey, op - - refute_match %r%DefaultKey%, spec.to_ruby - end - def test_self_from_yaml_cleans_up_Date_objects yaml = <<-YAML --- !ruby/object:Gem::Specification @@ -939,7 +796,7 @@ def test_self_load_relative assert_equal File.join(@tempdir, 'a-2.gemspec'), spec.loaded_from end - if RUBY_VERSION < '2.7' + if RUBY_ENGINE == 'ruby' and RUBY_VERSION < '2.7' def test_self_load_tainted full_path = @a2.spec_file write_file full_path do |io| @@ -968,7 +825,7 @@ def test_self_load_escape_curly io.write @a2.to_ruby_for_cache end rescue Errno::EINVAL - skip "cannot create '#{full_path}' on this platform" + pend "cannot create '#{full_path}' on this platform" end spec = Gem::Specification.load full_path @@ -987,7 +844,7 @@ def test_self_load_escape_interpolation io.write @a2.to_ruby_for_cache end rescue Errno::EINVAL - skip "cannot create '#{full_path}' on this platform" + pend "cannot create '#{full_path}' on this platform" end spec = Gem::Specification.load full_path @@ -1006,7 +863,7 @@ def test_self_load_escape_quote io.write @a2.to_ruby_for_cache end rescue Errno::EINVAL - skip "cannot create '#{full_path}' on this platform" + pend "cannot create '#{full_path}' on this platform" end spec = Gem::Specification.load full_path @@ -1017,24 +874,21 @@ def test_self_load_escape_quote end def test_self_load_utf8_with_ascii_encoding - int_enc = Encoding.default_internal - silence_warnings { Encoding.default_internal = 'US-ASCII' } - - spec2 = @a2.dup - bin = "\u5678".dup - spec2.authors = [bin] - full_path = spec2.spec_file - write_file full_path do |io| - io.write spec2.to_ruby_for_cache.force_encoding('BINARY').sub("\\u{5678}", bin.force_encoding('BINARY')) - end + with_internal_encoding('US-ASCII') do + spec2 = @a2.dup + bin = "\u5678".dup + spec2.authors = [bin] + full_path = spec2.spec_file + write_file full_path do |io| + io.write spec2.to_ruby_for_cache.force_encoding('BINARY').sub("\\u{5678}", bin.force_encoding('BINARY')) + end - spec = Gem::Specification.load full_path + spec = Gem::Specification.load full_path - spec2.files.clear + spec2.files.clear - assert_equal spec2, spec - ensure - silence_warnings { Encoding.default_internal = int_enc } + assert_equal spec2, spec + end end def test_self_load_legacy_ruby @@ -1088,7 +942,7 @@ def test_self_outdated end def test_self_outdated_and_latest_remotes - specs = spec_fetcher do |fetcher| + spec_fetcher do |fetcher| fetcher.download 'a', 4 fetcher.download 'b', 3 @@ -1097,8 +951,8 @@ def test_self_outdated_and_latest_remotes end expected = [ - [specs['a-3.a'], v(4)], - [specs['b-2'], v(3)], + [Gem::Specification.stubs.find {|s| s.full_name == 'a-3.a' }, v(4)], + [Gem::Specification.stubs.find {|s| s.full_name == 'b-2' }, v(3)], ] assert_equal expected, Gem::Specification.outdated_and_latest_version.to_a @@ -1108,13 +962,13 @@ def test_self_remove_spec install_specs @a1 assert_includes Gem::Specification.all_names, 'a-1' - assert_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1' + assert_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1' uninstall_gem @a1 Gem::Specification.reset refute_includes Gem::Specification.all_names, 'a-1' - refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1' + refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1' end def test_self_remove_spec_removed @@ -1129,49 +983,39 @@ def test_self_remove_spec_removed Gem::Specification.reset refute_includes Gem::Specification.all_names, 'a-1' - refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1' + refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1' end - def test_self_stubs + def test_self_stubs_for_lazy_loading Gem.loaded_specs.clear Gem::Specification.class_variable_set(:@@stubs, nil) dir_standard_specs = File.join Gem.dir, 'specifications' - dir_default_specs = Gem.default_specifications_dir - # Create gemspecs in three locations used in stubs - loaded_spec = Gem::Specification.new 'a', '3' - Gem.loaded_specs['a'] = loaded_spec - save_gemspec 'a', '2', dir_default_specs - save_gemspec 'a', '1', dir_standard_specs + save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' } + save_gemspec('b-1', '1', dir_standard_specs){|s| s.name = 'b' } - full_names = ['a-3', 'a-2', 'a-1'] - assert_equal full_names, Gem::Specification.stubs.map { |s| s.full_name } + assert_equal ['a-1'], Gem::Specification.stubs_for('a').map {|s| s.full_name } + assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length + assert_equal ['b-1'], Gem::Specification.stubs_for('b').map {|s| s.full_name } + assert_equal 2, Gem::Specification.class_variable_get(:@@stubs_by_name).length + + assert_equal( + Gem::Specification.stubs_for('a').map {|s| s.object_id }, + Gem::Specification.stubs_for('a').map {|s| s.object_id } + ) Gem.loaded_specs.delete 'a' + Gem.loaded_specs.delete 'b' Gem::Specification.class_variable_set(:@@stubs, nil) end - def test_self_stubs_for - Gem.loaded_specs.clear - Gem::Specification.class_variable_set(:@@stubs, nil) - - dir_standard_specs = File.join Gem.dir, 'specifications' - dir_default_specs = Gem.default_specifications_dir - - # Create gemspecs in three locations used in stubs - loaded_spec = Gem::Specification.new 'a', '3' - Gem.loaded_specs['a'] = loaded_spec - save_gemspec('a-2', '2', dir_default_specs) { |s| s.name = 'a' } - save_gemspec('a-1', '1', dir_standard_specs) { |s| s.name = 'a' } + def test_self_stubs_for_no_lazy_loading_after_all_specs_setup + Gem::Specification.all = [util_spec('a', '1')] - full_names = ['a-3', 'a-2', 'a-1'] + save_gemspec('b-1', '1', File.join(Gem.dir, 'specifications')){|s| s.name = 'b' } - assert_equal full_names, Gem::Specification.stubs_for('a').map { |s| s.full_name } - assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length - - Gem.loaded_specs.delete 'a' - Gem::Specification.class_variable_set(:@@stubs, nil) + assert_equal [], Gem::Specification.stubs_for('b').map {|s| s.full_name } end def test_self_stubs_for_mult_platforms @@ -1182,7 +1026,7 @@ def test_self_stubs_for_mult_platforms # create user spec user_spec_dir = File.join Gem.user_dir, 'specifications' - FileUtils.mkdir_p(user_spec_dir) unless Dir.exist? user_spec_dir + FileUtils.mkdir_p(user_spec_dir) unless Dir.exist? user_spec_dir # dirs doesn't include user ? Gem::Specification.dirs << user_spec_dir @@ -1192,7 +1036,7 @@ def test_self_stubs_for_mult_platforms #create specs platforms.each do |plat| - spec = Gem::Specification.new(gem, v) { |s| s.platform = plat } + spec = Gem::Specification.new(gem, v) {|s| s.platform = plat } File.open File.join(user_spec_dir, "#{gem}-#{v}-#{plat}.gemspec"), 'w' do |io| io.write spec.to_ruby end @@ -1213,10 +1057,18 @@ def test_self_stubs_for_mult_platforms Gem.platforms = orig_platform end - DATA_PATH = File.expand_path "../data", __FILE__ + def test_self_stubs_returns_only_specified_named_specs + dir_standard_specs = File.join Gem.dir, 'specifications' + + save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' } + save_gemspec('a-2', '2', dir_standard_specs){|s| s.name = 'a' } + save_gemspec('a-a', '3', dir_standard_specs){|s| s.name = 'a-a' } + + assert_equal ['a-1', 'a-2'], Gem::Specification.stubs_for('a').map(&:full_name).sort + end def test_handles_private_null_type - path = File.join DATA_PATH, "null-type.gemspec.rz" + path = File.expand_path "../data/null-type.gemspec.rz", __FILE__ data = Marshal.load Gem::Util.inflate(Gem.read_binary(path)) @@ -1342,7 +1194,7 @@ def test_initialize_copy_broken spec.instance_variable_set :@licenses, (class << (Object.new);self;end) spec.loaded_from = '/path/to/file' - e = assert_raises Gem::FormatException do + e = assert_raise Gem::FormatException do spec.dup end @@ -1383,12 +1235,12 @@ def test_add_dependency_with_type awesome.add_dependency :gem_name end - assert_equal %w[true gem_name], gem.dependencies.map { |dep| dep.name } + assert_equal %w[true gem_name], gem.dependencies.map {|dep| dep.name } end def test_add_dependency_from_existing_dependency dep = Gem::Dependency.new("existing_dep", Gem::Requirement.new('> 1'), :runtime) - spec = Gem::Specification.new { |s| s.add_dependency dep } + spec = Gem::Specification.new {|s| s.add_dependency dep } assert_equal dep, spec.dependencies.first end @@ -1397,7 +1249,7 @@ def test_add_dependency_with_type_explicit awesome.add_development_dependency "monkey" end - monkey = gem.dependencies.detect { |d| d.name == "monkey" } + monkey = gem.dependencies.detect {|d| d.name == "monkey" } assert_equal(:development, monkey.type) end @@ -1448,7 +1300,7 @@ def test_extra_rdoc_files_equals_nil end def test_build_args - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec assert_empty @ext.build_args @@ -1467,10 +1319,10 @@ def test_build_args end def test_build_extensions - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec - refute_path_exists @ext.extension_dir, 'sanity check' + assert_path_not_exist @ext.extension_dir, 'sanity check' refute_empty @ext.extensions, 'sanity check' extconf_rb = File.join @ext.gem_dir, @ext.extensions.first @@ -1488,14 +1340,14 @@ def test_build_extensions @ext.build_extensions - assert_path_exists @ext.extension_dir + assert_path_exist @ext.extension_dir end def test_default_spec_stub_is_marked_default default = new_default_spec 'default', 2 install_default_gems default - stub = Gem::Specification.stubs.find { |s| s.name == 'default' } + stub = Gem::Specification.stubs.find {|s| s.name == 'default' } assert_predicate stub, :default_gem? stub = Gem::Specification.find_all_by_name('default').first @@ -1503,7 +1355,7 @@ def test_default_spec_stub_is_marked_default end def test_build_extensions_built - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec refute_empty @ext.extensions, 'sanity check' @@ -1517,7 +1369,7 @@ def test_build_extensions_built @ext.build_extensions gem_make_out = File.join @ext.extension_dir, 'gem_make.out' - refute_path_exists gem_make_out + assert_path_not_exist gem_make_out end def test_build_extensions_default_gem @@ -1538,25 +1390,25 @@ def test_build_extensions_default_gem spec.build_extensions - refute_path_exists spec.extension_dir + assert_path_not_exist spec.extension_dir end def test_build_extensions_error - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec refute_empty @ext.extensions, 'sanity check' - assert_raises Gem::Ext::BuildError do + assert_raise Gem::Ext::BuildError do @ext.build_extensions end end def test_build_extensions_extensions_dir_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip 'skipped in root privilege' if Process.uid.zero? + pend 'chmod not supported' if Gem.win_platform? + pend 'skipped in root privilege' if Process.uid.zero? - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec refute_empty @ext.extensions, 'sanity check' @@ -1579,7 +1431,7 @@ def test_build_extensions_extensions_dir_unwritable FileUtils.chmod 0555, File.join(@ext.base_dir, 'extensions') @ext.build_extensions - refute_path_exists @ext.extension_dir + assert_path_not_exist @ext.extension_dir ensure unless ($DEBUG or win_platform? or Process.uid.zero? or Gem.java_platform?) FileUtils.chmod 0755, File.join(@ext.base_dir, 'extensions') @@ -1588,8 +1440,8 @@ def test_build_extensions_extensions_dir_unwritable end def test_build_extensions_no_extensions_dir_unwritable - skip 'chmod not supported' if Gem.win_platform? - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend 'chmod not supported' if Gem.win_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec refute_empty @ext.extensions, 'sanity check' @@ -1613,36 +1465,22 @@ def test_build_extensions_no_extensions_dir_unwritable @ext.build_extensions gem_make_out = File.join @ext.extension_dir, 'gem_make.out' - refute_path_exists gem_make_out + assert_path_not_exist gem_make_out ensure FileUtils.chmod 0755, @gemhome end def test_build_extensions_none - refute_path_exists @a1.extension_dir, 'sanity check' + assert_path_not_exist @a1.extension_dir, 'sanity check' assert_empty @a1.extensions, 'sanity check' @a1.build_extensions - refute_path_exists @a1.extension_dir - end - - def test_build_extensions_old - skip "extensions don't quite work on jruby" if Gem.java_platform? - ext_spec - - refute_empty @ext.extensions, 'sanity check' - - @ext.installed_by_version = v(0) - - @ext.build_extensions - - gem_make_out = File.join @ext.extension_dir, 'gem_make.out' - refute_path_exists gem_make_out + assert_path_not_exist @a1.extension_dir end def test_build_extensions_preview - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec extconf_rb = File.join @ext.gem_dir, @ext.extensions.first @@ -1665,7 +1503,7 @@ def test_build_extensions_preview @ext.build_extensions gem_make_out = File.join @ext.extension_dir, 'gem_make.out' - assert_path_exists gem_make_out + assert_path_exist gem_make_out end def test_contains_requirable_file_eh @@ -1677,10 +1515,10 @@ def test_contains_requirable_file_eh end def test_contains_requirable_file_eh_extension - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec - _, err = capture_io do + _, err = capture_output do refute @ext.contains_requirable_file? 'nonexistent' end @@ -1693,7 +1531,7 @@ def test_contains_requirable_file_eh_extension def test_contains_requirable_file_eh_extension_java_platform ext_spec(platform: Gem::Platform.new("java")) - _, err = capture_io do + _, err = capture_output do refute @ext.contains_requirable_file? 'nonexistent' end @@ -1715,7 +1553,7 @@ def test_date_equals_string end def test_date_equals_string_bad - assert_raises Gem::InvalidSpecificationException do + assert_raise Gem::InvalidSpecificationException do @a1.date = '9/11/2003' end end @@ -1850,7 +1688,6 @@ def test_extension_dir_override RbConfig::CONFIG['ENABLE_SHARED'], 'no' class << Gem - alias orig_default_ext_dir_for default_ext_dir_for remove_method :default_ext_dir_for @@ -1858,7 +1695,6 @@ class << Gem def Gem.default_ext_dir_for(base_dir) 'elsewhere' end - end ext_spec @@ -1872,20 +1708,18 @@ def Gem.default_ext_dir_for(base_dir) RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared class << Gem - remove_method :default_ext_dir_for alias default_ext_dir_for orig_default_ext_dir_for - end end def test_files - @a1.files = %w(files bin/common) - @a1.test_files = %w(test_files bin/common) - @a1.executables = %w(executables common) - @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common) - @a1.extensions = %w(extensions bin/common) + @a1.files = %w[files bin/common] + @a1.test_files = %w[test_files bin/common] + @a1.executables = %w[executables common] + @a1.extra_rdoc_files = %w[extra_rdoc_files bin/common] + @a1.extensions = %w[extensions bin/common] expected = %w[ bin/common @@ -1899,11 +1733,11 @@ def test_files end def test_files_append - @a1.files = %w(files bin/common) - @a1.test_files = %w(test_files bin/common) - @a1.executables = %w(executables common) - @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common) - @a1.extensions = %w(extensions bin/common) + @a1.files = %w[files bin/common] + @a1.test_files = %w[test_files bin/common] + @a1.executables = %w[executables common] + @a1.extra_rdoc_files = %w[extra_rdoc_files bin/common] + @a1.extensions = %w[extensions bin/common] expected = %w[ bin/common @@ -2017,7 +1851,7 @@ def test_full_name_windows test_cases = { 'i386-mswin32' => 'a-1-x86-mswin32-60', 'i386-mswin32_80' => 'a-1-x86-mswin32-80', - 'i386-mingw32' => 'a-1-x86-mingw32' + 'i386-mingw32' => 'a-1-x86-mingw32', } test_cases.each do |arch, expected| @@ -2166,11 +2000,9 @@ def test_require_paths def test_require_paths_default_ext_dir_for class << Gem - send :alias_method, :orig_default_ext_dir_for, :default_ext_dir_for remove_method :default_ext_dir_for - end def Gem.default_ext_dir_for(base_dir) @@ -2186,11 +2018,9 @@ def Gem.default_ext_dir_for(base_dir) end ensure class << Gem - send :remove_method, :default_ext_dir_for send :alias_method, :default_ext_dir_for, :orig_default_ext_dir_for send :remove_method, :orig_default_ext_dir_for - end end @@ -2286,43 +2116,39 @@ def test_fullpath_return_rb_extension_file_when_exist_the_same_name_file end def test_require_already_activated - save_loaded_features do - a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb" + a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb" - install_specs a1 # , a2, b1, b2, c1, c2 + install_specs a1 # , a2, b1, b2, c1, c2 - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal [], unresolved_names + a1.activate + assert_equal %w[a-1], loaded_spec_names + assert_equal [], unresolved_names - assert require "d#{$$}" + assert require "d#{$$}" - assert_equal %w(a-1), loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1], loaded_spec_names + assert_equal [], unresolved_names end def test_require_already_activated_indirect_conflict - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - a2 = util_spec "a", "2", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" - c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2 + a1 = util_spec "a", "1", "b" => "> 0" + a2 = util_spec "a", "2", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb" + c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2 - install_specs c1, b1, a1, a2, c2, b2 + install_specs c1, b1, a1, a2, c2, b2 - a1.activate - c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + a1.activate + c1.activate + assert_equal %w[a-1 c-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - assert require "d#{$$}" + assert require "d#{$$}" - assert_equal %w(a-1 c-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - end + assert_equal %w[a-1 c-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names end def test_requirements @@ -2343,7 +2169,7 @@ def test_runtime_dependencies_legacy expected = %w[rake jabber4r pqa] - assert_equal expected, @c1.runtime_dependencies.map { |d| d.name } + assert_equal expected, @c1.runtime_dependencies.map {|d| d.name } end def test_spaceship_name @@ -2453,6 +2279,9 @@ def test_to_ruby end def test_to_ruby_with_rsa_key + require 'rubygems/openssl' + pend 'openssl is missing' unless defined?(OpenSSL::PKey::RSA) + rsa_key = OpenSSL::PKey::RSA.new(2048) @a2.signing_key = rsa_key ruby_code = @a2.to_ruby @@ -2635,7 +2464,7 @@ def test_to_ruby_platform def test_to_yaml yaml_str = @a1.to_yaml - refute_match '!!null', yaml_str + refute_match %r{!!null}, yaml_str same_spec = Gem::Specification.from_yaml(yaml_str) @@ -2656,7 +2485,7 @@ def test_to_yaml_fancy def test_to_yaml_platform_empty_string @a1.instance_variable_set :@original_platform, '' - assert_match %r|^platform: ruby$|, @a1.to_yaml + assert_match %r{^platform: ruby$}, @a1.to_yaml end def test_to_yaml_platform_legacy @@ -2665,7 +2494,7 @@ def test_to_yaml_platform_legacy yaml_str = @a1.to_yaml - same_spec = YAML.load yaml_str + same_spec = load_yaml yaml_str assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform @@ -2674,7 +2503,7 @@ def test_to_yaml_platform_legacy def test_to_yaml_platform_nil @a1.instance_variable_set :@original_platform, nil - assert_match %r|^platform: ruby$|, @a1.to_yaml + assert_match %r{^platform: ruby$}, @a1.to_yaml end def test_validate @@ -2706,7 +2535,7 @@ def test_validate_authors assert_equal [], @a1.authors - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -2714,19 +2543,19 @@ def test_validate_authors @a1.authors = ["#{f} (who is writing this software)"] - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not an author}, e.message + assert_equal %("#{f}" or "#{t}" is not an author), e.message @a1.authors = ["#{t} (who is writing this software)"] - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not an author}, e.message + assert_equal %("#{f}" or "#{t}" is not an author), e.message end end @@ -2784,7 +2613,7 @@ def test_validate_dependencies add_runtime_dependency 'l', '~> 1.2', '> 1.2.3' #{w}: open-ended dependency on o (>= 0) is not recommended use a bounded requirement, such as '~> x.y' -#{w}: See http://guides.rubygems.org/specification-reference/ for help +#{w}: See https://guides.rubygems.org/specification-reference/ for help EXPECTED assert_equal expected, @ui.error, 'warning' @@ -2801,7 +2630,7 @@ def test_validate_dependencies_duplicates @a1.add_development_dependency 'c', '>= 1.2.3' use_ui @ui do - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -2816,7 +2645,7 @@ def test_validate_dependencies_duplicates end assert_equal <<-EXPECTED, @ui.error -#{w}: See http://guides.rubygems.org/specification-reference/ for help +#{w}: See https://guides.rubygems.org/specification-reference/ for help EXPECTED end end @@ -2851,6 +2680,37 @@ def test_validate_prerelease_dependencies_with_prerelease_version end end + def test_validate_rake_extension_have_rake_dependency_warning + util_setup_validate + + Dir.chdir @tempdir do + @a1.extensions = ['Rakefile'] + File.write File.join(@tempdir, 'Rakefile'), '' + + use_ui @ui do + @a1.validate + end + + assert_match(/add rake as a dependency/, @ui.error) + end + end + + def test_validate_rake_extension_have_rake_dependency_no_warning + util_setup_validate + + Dir.chdir @tempdir do + @a1.extensions = ['Rakefile'] + @a1.add_runtime_dependency 'rake' + File.write File.join(@tempdir, 'Rakefile'), '' + + use_ui @ui do + @a1.validate + end + + refute_match(/add rake as a dependency/, @ui.error) + end + end + def test_validate_description util_setup_validate @@ -2874,19 +2734,47 @@ def test_validate_description @a1.description = "#{f} (describe your package)" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not a description}, e.message + assert_equal %("#{f}" or "#{t}" is not a description), e.message @a1.description = "#{t} (describe your package)" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not a description}, e.message + assert_equal %("#{f}" or "#{t}" is not a description), e.message + + # Adding #{f} anywhere after the start of the description should be fine. + @a1.description = "(some description) #{f}" + + assert_nothing_raised do + @a1.validate + end + + # Adding #{t} anywhere after the start of the description should be fine. + @a1.description = "(some description) #{t}" + + assert_nothing_raised do + @a1.validate + end + + # Adding #{f} at the start of the second or later line should be fine. + @a1.description = "(some description)\n#{f}" + + assert_nothing_raised do + @a1.validate + end + + # Adding #{t} at the start of the second or later line should be fine. + @a1.description = "(some description)\n#{t}" + + assert_nothing_raised do + @a1.validate + end end end @@ -2896,24 +2784,24 @@ def test_validate_email Dir.chdir @tempdir do @a1.email = "FIxxxXME (your e-mail)".sub(/xxx/, "") - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not an email}, e.message + assert_equal %("#{f}" or "#{t}" is not an email), e.message @a1.email = "#{t} (your e-mail)" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not an email}, e.message + assert_equal %("#{f}" or "#{t}" is not an email), e.message end end def test_validate_empty - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do Gem::Specification.new.validate end @@ -2921,13 +2809,13 @@ def test_validate_empty end def test_validate_error - assert_raises Gem::InvalidSpecificationException do + assert_raise Gem::InvalidSpecificationException do use_ui @ui do Gem::Specification.new.validate end end - assert_match 'See http://guides.rubygems.org/specification-reference/ for help', @ui.error + assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error end def test_validate_executables @@ -2951,12 +2839,12 @@ def test_validate_executables def test_validate_empty_require_paths if win_platform? - skip 'test_validate_empty_require_paths skipped on MS Windows (symlink)' + pend 'test_validate_empty_require_paths skipped on MS Windows (symlink)' else util_setup_validate @a1.require_paths = [] - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -2966,7 +2854,7 @@ def test_validate_empty_require_paths end def test_validate_files - skip 'test_validate_files skipped on MS Windows (symlink)' if win_platform? + pend 'test_validate_files skipped on MS Windows (symlink)' if win_platform? util_setup_validate @a1.files += ['lib', 'lib2'] @@ -3006,9 +2894,11 @@ def test_unresolved_specs Please report a bug if this causes problems. EXPECTED - assert_output nil, expected do + actual_stdout, actual_stderr = capture_output do specification.reset end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end def test_unresolved_specs_with_versions @@ -3022,8 +2912,8 @@ def test_unresolved_specs_with_versions specification.define_singleton_method(:find_all_by_name) do |dep_name| [ - specification.new { |s| s.name = "z", s.version = Gem::Version.new("1") }, - specification.new { |s| s.name = "z", s.version = Gem::Version.new("2") } + specification.new {|s| s.name = "z", s.version = Gem::Version.new("1") }, + specification.new {|s| s.name = "z", s.version = Gem::Version.new("2") }, ] end @@ -3037,9 +2927,20 @@ def test_unresolved_specs_with_versions Please report a bug if this causes problems. EXPECTED - assert_output nil, expected do + actual_stdout, actual_stderr = capture_output do specification.reset end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) + end + + def test_duplicate_runtime_dependency + expected = "WARNING: duplicated b dependency [\"~> 3.0\", \"~> 3.0\"]\n" + out, err = capture_output do + @a1.add_runtime_dependency "b", "~> 3.0", "~> 3.0" + end + assert_empty out + assert_equal(expected, err) end def set_orig(cls) @@ -3054,7 +2955,7 @@ def test_validate_files_recursive @a1.files = [@a1.file_name] - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -3086,7 +2987,7 @@ def test_validate_homepage @a1.homepage = 'over at my cool site' - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -3094,13 +2995,13 @@ def test_validate_homepage @a1.homepage = 'ftp://rubygems.org' - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal '"ftp://rubygems.org" is not a valid HTTP URI', e.message - @a1.homepage = 'http://rubygems.org' + @a1.homepage = 'https://rubygems.org/' assert_equal true, @a1.validate @a1.homepage = 'https://rubygems.org' @@ -3117,10 +3018,36 @@ def test_validate_license @a1.validate end - assert_match <<-warning, @ui.error + assert_match <<-WARNING, @ui.error WARNING: licenses is empty, but is recommended. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. - warning + WARNING + end + + def test_validate_license_in_a_non_packaging_context + util_setup_validate + + use_ui @ui do + @a1.licenses.clear + @a1.validate(false) + end + + assert_empty @ui.error + end + + def test_removed_methods + assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=] + end + + def test_validate_removed_rubyforge_project + util_setup_validate + + use_ui @ui do + @a1.rubyforge_project = 'invalid-attribute' + @a1.validate + end + + assert_match "rubyforge_project= is deprecated", @ui.error end def test_validate_license_values @@ -3131,10 +3058,21 @@ def test_validate_license_values @a1.validate end - assert_match <<-warning, @ui.error + assert_match <<-WARNING, @ui.error WARNING: license value 'BSD' is invalid. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. - warning + WARNING + end + + def test_validate_license_ref + util_setup_validate + + use_ui @ui do + @a1.licenses = ['LicenseRef-LICENSE.md'] + @a1.validate + end + + assert_empty @ui.error end def test_validate_license_values_plus @@ -3178,14 +3116,14 @@ def test_validate_license_with_nonsense_suffix @a1.validate end - assert_match <<-warning, @ui.error + assert_match <<-WARNING, @ui.error WARNING: license value 'GPL-2.0+ FOO' is invalid. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. - warning - assert_match <<-warning, @ui.error + WARNING + assert_match <<-WARNING, @ui.error WARNING: license value 'GPL-2.0 FOO' is invalid. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. - warning + WARNING end def test_validate_license_with_invalid_exception @@ -3196,10 +3134,10 @@ def test_validate_license_with_invalid_exception @a1.validate end - assert_match <<-warning, @ui.error + assert_match <<-WARNING, @ui.error WARNING: license value 'GPL-2.0+ WITH Autocofn-exception-2.0' is invalid. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. - warning + WARNING end def test_validate_license_gives_suggestions @@ -3210,11 +3148,11 @@ def test_validate_license_gives_suggestions @a1.validate end - assert_match <<-warning, @ui.error + assert_match <<-WARNING, @ui.error WARNING: license value 'ruby' is invalid. Use a license identifier from http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. Did you mean 'Ruby'? - warning + WARNING end def test_validate_empty_files @@ -3257,7 +3195,7 @@ def test_validate_empty_summary def test_validate_name util_setup_validate - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.name = :json @a1.validate end @@ -3265,31 +3203,31 @@ def test_validate_name assert_equal 'invalid value for attribute name: ":json" must be a string', e.message @a1.name = [] - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal "invalid value for attribute name: \"[]\" must be a string", e.message @a1.name = "" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal "invalid value for attribute name: \"\" must include at least one letter", e.message @a1.name = "12345" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal "invalid value for attribute name: \"12345\" must include at least one letter", e.message @a1.name = "../malicious" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal "invalid value for attribute name: \"../malicious\" can only include letters, numbers, dashes, and underscores", e.message @a1.name = "\ba\t" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end assert_equal "invalid value for attribute name: \"\\ba\\t\" can only include letters, numbers, dashes, and underscores", e.message @@ -3306,17 +3244,17 @@ def test_validate_non_nil spec = @a1.dup spec.instance_variable_set "@#{name}", nil - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do spec.validate end - assert_match %r%^#{name}%, e.message + assert_match %r{^#{name}}, e.message end end end def test_validate_permissions - skip 'chmod not supported' if Gem.win_platform? + pend 'chmod not supported' if Gem.win_platform? util_setup_validate @@ -3335,7 +3273,7 @@ def test_validate_permissions end def test_validate_permissions_of_missing_file_non_packaging - skip 'chmod not supported' if Gem.win_platform? + pend 'chmod not supported' if Gem.win_platform? util_setup_validate @@ -3367,7 +3305,7 @@ def test_validate_rubygems_version util_setup_validate @a1.rubygems_version = "3" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end @@ -3381,7 +3319,7 @@ def test_validate_specification_version Dir.chdir @tempdir do @a1.specification_version = '1.0' - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do use_ui @ui do @a1.validate end @@ -3406,19 +3344,19 @@ def test_validate_summary @a1.summary = "#{f} (describe your package)" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message + assert_equal %("#{f}" or "#{t}" is not a summary), e.message @a1.summary = "#{t} (describe your package)" - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @a1.validate end - assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message + assert_equal %("#{f}" or "#{t}" is not a summary), e.message end end @@ -3430,7 +3368,7 @@ def test_validate_warning @a1.validate end - assert_match 'See http://guides.rubygems.org/specification-reference/ for help', @ui.error + assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error end def test_version @@ -3467,7 +3405,7 @@ def test_load_errors_contain_filename specfile.write "raise 'boom'" specfile.close begin - capture_io do + capture_output do Gem::Specification.load(specfile.path) end rescue => e @@ -3478,19 +3416,6 @@ def test_load_errors_contain_filename specfile.delete end - ## - # KEEP p-1-x86-darwin-8 - # KEEP p-1 - # KEEP c-1.2 - # KEEP a_evil-9 - # a-1 - # a-1-x86-my_platform-1 - # KEEP a-2 - # a-2-x86-other_platform-1 - # KEEP a-2-x86-my_platform-1 - # a-3.a - # KEEP a-3-x86-other_platform-1 - def test_latest_specs spec_fetcher do |fetcher| fetcher.spec 'a', 1 do |s| @@ -3513,8 +3438,6 @@ def test_latest_specs end expected = %W[ - a-2 - a-2-x86-my_platform-1 a-3-x86-other_platform-1 ] @@ -3532,7 +3455,8 @@ def test_metadata_validates_ok s.metadata = { "one" => "two", "home" => "three", - "homepage_uri" => "https://example.com/user/repo" + "homepage_uri" => "https://example.com/user/repo", + "funding_uri" => "https://example.com/donate", } end @@ -3551,7 +3475,7 @@ def test_metadata_key_type_validation_fails s.metadata = { 1 => "fail" } end - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @m2.validate end @@ -3568,11 +3492,11 @@ def test_metadata_key_size_validation_fails s.metadata = { ("x" * 129) => "fail" } end - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @m2.validate end - assert_equal "metadata key too large (129 > 128)", e.message + assert_equal "metadata key is too large (129 > 128)", e.message end end @@ -3585,11 +3509,11 @@ def test_metadata_value_type_validation_fails s.metadata = { 'fail' => [] } end - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @m2.validate end - assert_equal "metadata values must be a String", e.message + assert_equal "metadata['fail'] value must be a String", e.message end end @@ -3602,11 +3526,11 @@ def test_metadata_value_size_validation_fails s.metadata = { 'fail' => ("x" * 1025) } end - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @m2.validate end - assert_equal "metadata value too large (1025 > 1024)", e.message + assert_equal "metadata['fail'] value is too large (1025 > 1024)", e.message end end @@ -3619,7 +3543,7 @@ def test_metadata_link_validation_fails s.metadata = { 'homepage_uri' => 'http:/example.com' } end - e = assert_raises Gem::InvalidSpecificationException do + e = assert_raise Gem::InvalidSpecificationException do @m2.validate end @@ -3659,7 +3583,7 @@ def test_metadata_specs end def test_missing_extensions_eh - skip "extensions don't quite work on jruby" if Gem.java_platform? + pend "extensions don't quite work on jruby" if Gem.java_platform? ext_spec assert @ext.missing_extensions? @@ -3689,18 +3613,6 @@ def test_missing_extensions_eh_default_gem refute spec.missing_extensions? end - def test_missing_extensions_eh_legacy - ext_spec - - @ext.installed_by_version = v '2.2.0.preview.2' - - assert @ext.missing_extensions? - - @ext.installed_by_version = v '2.2.0.preview.1' - - refute @ext.missing_extensions? - end - def test_missing_extensions_eh_none refute @a1.missing_extensions? end @@ -3738,7 +3650,7 @@ def test_find_by_name assert Gem::Specification.find_by_name "a", "1" assert Gem::Specification.find_by_name "a", ">1" - assert_raises Gem::MissingSpecError do + assert_raise Gem::MissingSpecError do Gem::Specification.find_by_name "monkeys" end end @@ -3759,7 +3671,7 @@ def test_find_by_name_prerelease assert Gem::Specification.find_by_name "b" - assert_raises Gem::MissingSpecVersionError do + assert_raise Gem::MissingSpecVersionError do Gem::Specification.find_by_name "b", "1" end @@ -3792,7 +3704,7 @@ def test_load_default_gem default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - spec_path = File.join(@default_spec_dir, default_gem_spec.spec_name) + spec_path = File.join(@gemhome, "specifications", "default", default_gem_spec.spec_name) write_file(spec_path) do |file| file.print(default_gem_spec.to_ruby) end @@ -3817,64 +3729,18 @@ def util_setup_validate FileUtils.mkdir_p "test" FileUtils.mkdir_p "bin" - FileUtils.touch File.join("ext", "a", "extconf.rb") - FileUtils.touch File.join("lib", "code.rb") - FileUtils.touch File.join("test", "suite.rb") + begin + umask_orig = File.umask(2) + FileUtils.touch File.join("ext", "a", "extconf.rb") + FileUtils.touch File.join("lib", "code.rb") + FileUtils.touch File.join("test", "suite.rb") - File.open "bin/exec", "w", 0755 do |fp| - fp.puts "#!#{Gem.ruby}" + File.open "bin/exec", "w", 0755 do |fp| + fp.puts "#!#{Gem.ruby}" + end + ensure + File.umask(umask_orig) end end end - - def with_syck - begin - verbose, $VERBOSE = $VERBOSE, nil - require "yaml" - old_engine = YAML::ENGINE.yamler - YAML::ENGINE.yamler = 'syck' - load 'rubygems/syck_hack.rb' - rescue NameError - # probably on 1.8, ignore - ensure - $VERBOSE = verbose - end - - yield - ensure - begin - YAML::ENGINE.yamler = old_engine - load 'rubygems/syck_hack.rb' - rescue NameError - # ignore - end - end - - def with_psych - begin - require "yaml" - old_engine = YAML::ENGINE.yamler - YAML::ENGINE.yamler = 'psych' - load 'rubygems/syck_hack.rb' - rescue NameError - # probably on 1.8, ignore - end - - yield - ensure - begin - YAML::ENGINE.yamler = old_engine - load 'rubygems/syck_hack.rb' - rescue NameError - # ignore - end - end - - def silence_warnings - old_verbose, $VERBOSE = $VERBOSE, false - yield - ensure - $VERBOSE = old_verbose - end - end diff --git a/ruby/test/rubygems/test_gem_stream_ui.rb b/ruby/test/rubygems/test_gem_stream_ui.rb index 33c25308b..04de6dd36 100644 --- a/ruby/test/rubygems/test_gem_stream_ui.rb +++ b/ruby/test/rubygems/test_gem_stream_ui.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/user_interaction' require 'timeout' class TestGemStreamUI < Gem::TestCase - - SHORT_TIMEOUT = (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?) ? 1.0 : 0.1 # increase timeout with MJIT for --jit-wait testing + # increase timeout with MJIT for --jit-wait testing + mjit_enabled = defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + SHORT_TIMEOUT = (RUBY_ENGINE == "ruby" && !mjit_enabled) ? 0.1 : 1.0 module IsTty attr_accessor :tty @@ -89,7 +90,7 @@ def test_ask_yes_no_no_tty_without_default @in.tty = false Timeout.timeout(SHORT_TIMEOUT) do - assert_raises(Gem::OperationNotSupportedError) do + assert_raise(Gem::OperationNotSupportedError) do @sui.ask_yes_no("do coconuts migrate?") end end @@ -220,5 +221,4 @@ def test_verbose_download_reporter_no_tty reporter.fetch 'a.gem', 1024 assert_equal "", @out.string end - end diff --git a/ruby/test/rubygems/test_gem_stub_specification.rb b/ruby/test/rubygems/test_gem_stub_specification.rb index 8553194c4..e01d5cad8 100644 --- a/ruby/test/rubygems/test_gem_stub_specification.rb +++ b/ruby/test/rubygems/test_gem_stub_specification.rb @@ -1,18 +1,16 @@ # frozen_string_literal: true -require "rubygems/test_case" +require_relative "helper" require "rubygems/stub_specification" class TestStubSpecification < Gem::TestCase - - SPECIFICATIONS = File.expand_path(File.join("..", "specifications"), __FILE__) - FOO = File.join SPECIFICATIONS, "foo-0.0.1-x86-mswin32.gemspec" - BAR = File.join SPECIFICATIONS, "bar-0.0.2.gemspec" + FOO = File.expand_path File.join("specifications", "foo-0.0.1-x86-mswin32.gemspec"), __dir__ + BAR = File.expand_path File.join("specifications", "bar-0.0.2.gemspec"), __dir__ def setup super - @base_dir = File.dirname(SPECIFICATIONS) - @gems_dir = File.join File.dirname(SPECIFICATIONS), 'gem' + @base_dir = __dir__ + @gems_dir = File.join __dir__, 'gem' @foo = Gem::StubSpecification.gemspec_stub FOO, @base_dir, @gems_dir end @@ -67,9 +65,9 @@ def test_contains_requirable_file_eh end def test_contains_requirable_file_eh_extension - skip "I guess making the stub match the running platform should work" if Gem.java_platform? + pend "I guess making the stub match the running platform should work" if Gem.java_platform? stub_with_extension do |stub| - _, err = capture_io do + _, err = capture_output do refute stub.contains_requirable_file? 'nonexistent' end @@ -124,7 +122,7 @@ def test_matches_for_glob_with_bundler_inline end def test_missing_extensions_eh - skip "I guess making the stub match the running platform should work" if Gem.java_platform? + pend "I guess making the stub match the running platform should work" if Gem.java_platform? stub = stub_with_extension do |s| extconf_rb = File.join s.gem_dir, s.extensions.first FileUtils.mkdir_p File.dirname extconf_rb @@ -182,22 +180,6 @@ def test_to_spec_with_other_specs_loaded_does_not_warn assert bar.to_spec end - def test_to_spec_activated - assert @foo.to_spec.is_a?(Gem::Specification) - assert_equal "foo", @foo.to_spec.name - refute @foo.to_spec.instance_variable_get :@ignored - end - - def test_to_spec_missing_extensions - stub = stub_with_extension - - capture_io do - stub.contains_requirable_file? 'nonexistent' - end - - assert stub.to_spec.instance_variable_get :@ignored - end - def stub_with_version spec = File.join @gemhome, 'specifications', 'stub_e-2.gemspec' File.open spec, 'w' do |io| @@ -292,5 +274,4 @@ def stub_without_extension return stub end end - end diff --git a/ruby/test/rubygems/test_gem_text.rb b/ruby/test/rubygems/test_gem_text.rb index ccac812c6..f170fbf39 100644 --- a/ruby/test/rubygems/test_gem_text.rb +++ b/ruby/test/rubygems/test_gem_text.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require "rubygems/text" class TestGemText < Gem::TestCase - include Gem::Text def test_format_text @@ -23,7 +22,7 @@ def test_format_text_none_indent end def test_format_text_no_space - assert_equal "texttowr\nap", format_text("texttowrap", 8) + assert_equal "texttowr\nap", format_text("texttowrap", 8) end def test_format_text_trailing # for two spaces after . @@ -84,6 +83,12 @@ def test_levenshtein_distance_replace assert_equal 7, levenshtein_distance("zentest", "xxxxxxx") end + def test_levenshtein_distance_all + assert_equal 6, levenshtein_distance("algorithm", "altruistic") + assert_equal 3, levenshtein_distance("saturday", "sunday") + assert_equal 3, levenshtein_distance("kitten", "sitting") + end + def test_truncate_text assert_equal "abc", truncate_text("abc", "desc") assert_equal "Truncating desc to 2 characters:\nab", truncate_text("abc", "desc", 2) @@ -94,5 +99,4 @@ def test_truncate_text def test_clean_text assert_equal ".]2;nyan.", clean_text("\e]2;nyan\a") end - end diff --git a/ruby/test/rubygems/test_gem_uninstaller.rb b/ruby/test/rubygems/test_gem_uninstaller.rb index bf5ef5b4a..9e1897286 100644 --- a/ruby/test/rubygems/test_gem_uninstaller.rb +++ b/ruby/test/rubygems/test_gem_uninstaller.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/installer_test_case' +require_relative 'installer_test_case' require 'rubygems/uninstaller' class TestGemUninstaller < Gem::InstallerTestCase - def setup super @installer = setup_base_installer @@ -27,7 +26,7 @@ def test_initialize_expand_path FileUtils.mkdir_p 'foo/bar' uninstaller = Gem::Uninstaller.new nil, :install_dir => 'foo//bar' - assert_match %r|foo/bar$|, uninstaller.instance_variable_get(:@gem_home) + assert_match %r{foo/bar$}, uninstaller.instance_variable_get(:@gem_home) end def test_ask_if_ok @@ -55,7 +54,7 @@ def test_remove_all uninstaller.remove_all [@spec] end - refute_path_exists @spec.gem_dir + assert_path_not_exist @spec.gem_dir end def test_remove_executables_force_keep @@ -139,7 +138,7 @@ def test_remove_not_in_home Dir.mkdir "#{@gemhome}2" uninstaller = Gem::Uninstaller.new nil, :install_dir => "#{@gemhome}2" - e = assert_raises Gem::GemNotInHomeException do + e = assert_raise Gem::GemNotInHomeException do use_ui ui do uninstaller.remove @spec end @@ -150,10 +149,12 @@ def test_remove_not_in_home assert_equal expected, e.message - assert_path_exists @spec.gem_dir + assert_path_exist @spec.gem_dir end def test_remove_symlinked_gem_home + pend "Symlinks not supported or not enabled" unless symlink_supported? + Dir.mktmpdir("gem_home") do |dir| symlinked_gem_home = "#{dir}/#{File.basename(@gemhome)}" @@ -165,8 +166,61 @@ def test_remove_symlinked_gem_home uninstaller.remove @spec end - refute_path_exists @spec.gem_dir + assert_path_not_exist @spec.gem_dir + end + end + + def test_remove_plugins + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + assert File.exist?(plugin_path), 'plugin not written' + + Gem::Uninstaller.new(nil).remove_plugins @spec + + refute File.exist?(plugin_path), 'plugin not removed' + end + + def test_remove_plugins_with_install_dir + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + assert File.exist?(plugin_path), 'plugin not written' + + Dir.mkdir "#{@gemhome}2" + Gem::Uninstaller.new(nil, :install_dir => "#{@gemhome}2").remove_plugins @spec + + assert File.exist?(plugin_path), 'plugin unintentionally removed' + end + + def test_regenerate_plugins_for + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" end + + @spec.files += %w[lib/rubygems_plugin.rb] + + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + assert File.exist?(plugin_path), 'plugin not written' + + FileUtils.rm plugin_path + Gem::Uninstaller.new(nil).regenerate_plugins_for @spec, Gem.plugindir + + assert File.exist?(plugin_path), 'plugin not regenerated' end def test_path_ok_eh @@ -241,9 +295,16 @@ def test_uninstall_default_gem_with_same_version uninstaller = Gem::Uninstaller.new spec.name, :executables => true - uninstaller.uninstall - - refute_path_exists spec.gem_dir + ui = Gem::MockGemUi.new "1\ny\n" + use_ui ui do + uninstaller.uninstall + end + expected = "Successfully uninstalled default-2\n" \ + "There was both a regular copy and a default copy of default-2. The " \ + "regular copy was successfully uninstalled, but the default copy " \ + "was left around because default gems can't be removed.\n" + assert_equal expected, ui.output + assert_path_not_exist spec.gem_dir end def test_uninstall_extension @@ -260,22 +321,22 @@ def test_uninstall_extension use_ui @ui do path = Gem::Package.build @spec - installer = Gem::Installer.at path + installer = Gem::Installer.at path, :force => true installer.install end - assert_path_exists @spec.extension_dir, 'sanity check' + assert_path_exist @spec.extension_dir, 'sanity check' uninstaller = Gem::Uninstaller.new @spec.name, :executables => true uninstaller.uninstall - refute_path_exists @spec.extension_dir + assert_path_not_exist @spec.extension_dir end def test_uninstall_nonexistent uninstaller = Gem::Uninstaller.new 'bogus', :executables => true - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do uninstaller.uninstall end @@ -297,7 +358,7 @@ def test_uninstall_not_ok ui = Gem::MockGemUi.new "n\n" - assert_raises Gem::DependencyRemovalException do + assert_raise Gem::DependencyRemovalException do use_ui ui do uninstaller.uninstall end @@ -317,16 +378,16 @@ def test_uninstall_user_install gem_dir = File.join @user_spec.gem_dir Gem.pre_uninstall do - assert_path_exists gem_dir + assert_path_exist gem_dir end Gem.post_uninstall do - refute_path_exists gem_dir + assert_path_not_exist gem_dir end uninstaller.uninstall - refute_path_exists gem_dir + assert_path_not_exist gem_dir assert_same uninstaller, @pre_uninstall_hook_arg assert_same uninstaller, @post_uninstall_hook_arg @@ -338,7 +399,7 @@ def test_uninstall_wrong_repo uninstaller = Gem::Uninstaller.new @spec.name, :executables => true - e = assert_raises Gem::InstallError do + e = assert_raise Gem::InstallError do uninstaller.uninstall end @@ -405,12 +466,12 @@ def test_uninstall_prompts_about_broken_deps lines = ui.output.split("\n") lines.shift - assert_match %r!You have requested to uninstall the gem:!, lines.shift + assert_match %r{You have requested to uninstall the gem:}, lines.shift lines.shift lines.shift - assert_match %r!r-1 depends on q \(= 1\)!, lines.shift - assert_match %r!Successfully uninstalled q-1!, lines.last + assert_match %r{r-1 depends on q \(= 1\)}, lines.shift + assert_match %r{Successfully uninstalled q-1}, lines.last end def test_uninstall_only_lists_unsatisfied_deps @@ -435,12 +496,12 @@ def test_uninstall_only_lists_unsatisfied_deps lines = ui.output.split("\n") lines.shift - assert_match %r!You have requested to uninstall the gem:!, lines.shift + assert_match %r{You have requested to uninstall the gem:}, lines.shift lines.shift lines.shift - assert_match %r!x-1 depends on q \(= 1.0\)!, lines.shift - assert_match %r!Successfully uninstalled q-1.0!, lines.last + assert_match %r{x-1 depends on q \(= 1.0\)}, lines.shift + assert_match %r{Successfully uninstalled q-1.0}, lines.last end def test_uninstall_doesnt_prompt_when_other_gem_satisfies_requirement @@ -492,7 +553,7 @@ def test_uninstall_doesnt_prompt_and_raises_when_abort_on_dependent_set un = Gem::Uninstaller.new('q', :abort_on_dependent => true) ui = Gem::MockGemUi.new("y\n") - assert_raises Gem::DependencyRemovalException do + assert_raise Gem::DependencyRemovalException do use_ui ui do un.uninstall end @@ -516,12 +577,41 @@ def test_uninstall_prompt_includes_dep_type lines = ui.output.split("\n") lines.shift - assert_match %r!You have requested to uninstall the gem:!, lines.shift + assert_match %r{You have requested to uninstall the gem:}, lines.shift lines.shift lines.shift - assert_match %r!r-1 depends on q \(= 1, development\)!, lines.shift - assert_match %r!Successfully uninstalled q-1!, lines.last + assert_match %r{r-1 depends on q \(= 1, development\)}, lines.shift + assert_match %r{Successfully uninstalled q-1}, lines.last + end + + def test_uninstall_prompt_only_lists_the_dependents_that_prevented_uninstallation + quick_gem 'r', '1' do |s| + s.add_development_dependency 'q', '= 1' + end + + quick_gem 's', '1' do |s| + s.add_dependency 'q', '= 1' + end + + quick_gem 'q', '1' + + un = Gem::Uninstaller.new('q', :check_dev => false) + ui = Gem::MockGemUi.new("y\n") + + use_ui ui do + un.uninstall + end + + lines = ui.output.split("\n") + lines.shift + + assert_match %r{You have requested to uninstall the gem:}, lines.shift + lines.shift + lines.shift + + assert_match %r{s-1 depends on q \(= 1\)}, lines.shift + assert_match %r{Successfully uninstalled q-1}, lines.last end def test_uninstall_no_permission @@ -536,10 +626,49 @@ def test_uninstall_no_permission end FileUtils.stub :rm_r, stub_rm_r do - assert_raises Gem::UninstallError do + assert_raise Gem::UninstallError do uninstaller.uninstall end end end + def test_uninstall_keeps_plugins_up_to_date + write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io| + io.write "puts __FILE__" + end + + plugin_path = File.join Gem.plugindir, 'a_plugin.rb' + + @spec.version = '1' + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + refute File.exist?(plugin_path), 'version without plugin installed, but plugin written' + + @spec.files += %w[lib/rubygems_plugin.rb] + @spec.version = '2' + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + assert File.exist?(plugin_path), 'version with plugin installed, but plugin not written' + assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content' + + @spec.version = '3' + Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + + assert File.exist?(plugin_path), 'version with plugin installed, but plugin removed' + assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version installed, but plugin updated' + + Gem::Uninstaller.new('a', :version => '1', :executables => true).uninstall + + assert File.exist?(plugin_path), 'plugin removed when old version uninstalled' + assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version uninstalled, but plugin updated' + + Gem::Uninstaller.new('a', version: '3', :executables => true).uninstall + + assert File.exist?(plugin_path), 'plugin removed when old version uninstalled and another version with plugin still present' + assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'latest version uninstalled, but plugin not updated to previous version' + + Gem::Uninstaller.new('a', version: '2', :executables => true).uninstall + + refute File.exist?(plugin_path), 'last version uninstalled, but plugin still present' + end end diff --git a/ruby/test/rubygems/test_gem_unsatisfiable_dependency_error.rb b/ruby/test/rubygems/test_gem_unsatisfiable_dependency_error.rb index e68185ce2..f9d30123f 100644 --- a/ruby/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +++ b/ruby/test/rubygems/test_gem_unsatisfiable_dependency_error.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestGemUnsatisfiableDependencyError < Gem::TestCase - def setup super @@ -28,5 +27,4 @@ def test_name def test_version assert_equal @a_dep.requirement, @e.version end - end diff --git a/ruby/test/rubygems/test_gem_uri.rb b/ruby/test/rubygems/test_gem_uri.rb new file mode 100644 index 000000000..7fe572518 --- /dev/null +++ b/ruby/test/rubygems/test_gem_uri.rb @@ -0,0 +1,39 @@ +require_relative 'helper' +require 'rubygems/uri' + +class TestUri < Gem::TestCase + def test_to_s_not_string + assert_equal "not_a_uri", Gem::Uri.new(:not_a_uri).to_s + end + + def test_to_s_invalid_uri + assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").to_s + end + + def test_redacted_with_user_pass + assert_equal "https://user:REDACTED@example.com", Gem::Uri.new("https://user:pass@example.com").redacted.to_s + end + + def test_redacted_with_token + assert_equal "https://REDACTED@example.com", Gem::Uri.new("https://token@example.com").redacted.to_s + end + + def test_redacted_with_user_x_oauth_basic + assert_equal "https://REDACTED:x-oauth-basic@example.com", Gem::Uri.new("https://token:x-oauth-basic@example.com").redacted.to_s + end + + def test_redacted_without_credential + assert_equal "https://www.example.com", Gem::Uri.new("https://www.example.com").redacted.to_s + end + + def test_redacted_with_invalid_uri + assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").redacted.to_s + end + + def test_redacted_does_not_modify_uri + url = 'https://user:password@example.com' + uri = Gem::Uri.new(url) + assert_equal 'https://user:REDACTED@example.com', uri.redacted.to_s + assert_equal url, uri.to_s + end +end diff --git a/ruby/test/rubygems/test_gem_uri_formatter.rb b/ruby/test/rubygems/test_gem_uri_formatter.rb index b19bae993..a41c9238a 100644 --- a/ruby/test/rubygems/test_gem_uri_formatter.rb +++ b/ruby/test/rubygems/test_gem_uri_formatter.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/uri_formatter' class TestGemUriFormatter < Gem::TestCase - def test_normalize_uri assert_equal 'FILE://example/', Gem::UriFormatter.new('FILE://example/').normalize @@ -24,5 +23,4 @@ def test_escape def test_unescape assert_equal 'a@b\c', Gem::UriFormatter.new('a%40b%5Cc').unescape end - end diff --git a/ruby/test/rubygems/test_gem_util.rb b/ruby/test/rubygems/test_gem_util.rb index 3f1d069a2..e0db5c283 100644 --- a/ruby/test/rubygems/test_gem_util.rb +++ b/ruby/test/rubygems/test_gem_util.rb @@ -1,22 +1,25 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/util' class TestGemUtil < Gem::TestCase - def test_class_popen - skip "popen with a block does not behave well on jruby" if Gem.java_platform? - assert_equal "0\n", Gem::Util.popen(Gem.ruby, '-I', File.expand_path('../../../lib', __FILE__), '-e', 'p 0') + pend "popen with a block does not behave well on jruby" if Gem.java_platform? + assert_equal "0\n", Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', 'p 0') - assert_raises Errno::ECHILD do + assert_raise Errno::ECHILD do Process.wait(-1) end end def test_silent_system - skip if Gem.java_platform? - assert_silent do - Gem::Util.silent_system Gem.ruby, '-I', File.expand_path('../../../lib', __FILE__), '-e', 'puts "hello"; warn "hello"' + pend if Gem.java_platform? + Gem::Deprecate.skip_during do + out, err = capture_output do + Gem::Util.silent_system(*ruby_with_rubygems_in_load_path, '-e', 'puts "hello"; warn "hello"') + end + assert_empty out + assert_empty err end end @@ -32,21 +35,21 @@ def test_traverse_parents end def test_traverse_parents_does_not_crash_on_permissions_error - skip 'skipped on MS Windows (chmod has no effect)' if win_platform? || java_platform? + pend 'skipped on MS Windows (chmod has no effect)' if win_platform? || java_platform? FileUtils.mkdir_p 'd/e/f' # remove 'execute' permission from "e" directory and make it # impossible to cd into it and its children FileUtils.chmod(0666, 'd/e') - skip 'skipped in root privilege' if Process.uid.zero? + pend 'skipped in root privilege' if Process.uid.zero? paths = Gem::Util.traverse_parents('d/e/f').to_a assert_equal File.join(@tempdir, 'd'), paths[0] assert_equal @tempdir, paths[1] - assert_equal File.realpath(Dir.tmpdir), paths[2] - assert_equal File.realpath("..", Dir.tmpdir), paths[3] + assert_equal File.realpath("..", @tempdir), paths[2] + assert_equal File.realpath("../..", @tempdir), paths[3] ensure # restore default permissions, allow the directory to be removed FileUtils.chmod(0775, 'd/e') unless win_platform? || java_platform? @@ -56,8 +59,8 @@ def test_linked_list_find list = [1,2,3,4,5].inject(Gem::List.new(0)) do |m,o| Gem::List.new o, m end - assert_equal 5, list.find { |x| x == 5 } - assert_equal 4, list.find { |x| x == 4 } + assert_equal 5, list.find {|x| x == 5 } + assert_equal 4, list.find {|x| x == 4 } end def test_glob_files_in_dir @@ -71,10 +74,10 @@ def test_glob_files_in_dir ] files_with_absolute_base = Gem::Util.glob_files_in_dir('*.rb', File.join(@tempdir, 'g')) - assert_equal expected_paths.to_set, files_with_absolute_base.to_set + assert_equal expected_paths.sort, files_with_absolute_base.sort files_with_relative_base = Gem::Util.glob_files_in_dir('*.rb', 'g') - assert_equal expected_paths.to_set, files_with_relative_base.to_set + assert_equal expected_paths.sort, files_with_relative_base.sort end def test_correct_for_windows_path @@ -84,5 +87,4 @@ def test_correct_for_windows_path path = "/home/skillet" assert_equal "/home/skillet", Gem::Util.correct_for_windows_path(path) end - end diff --git a/ruby/test/rubygems/test_gem_validator.rb b/ruby/test/rubygems/test_gem_validator.rb index 34b7e5fb3..8090776b4 100644 --- a/ruby/test/rubygems/test_gem_validator.rb +++ b/ruby/test/rubygems/test_gem_validator.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require "rubygems/test_case" +require_relative "helper" require "rubygems/validator" class TestGemValidator < Gem::TestCase - def setup super @@ -27,7 +26,7 @@ def test_alien @spec.file_name => [ Gem::Validator::ErrorData.new('lib/b.rb', 'Missing file'), Gem::Validator::ErrorData.new('lib/c.rb', 'Extra file'), - ] + ], } assert_equal expected, alien @@ -40,5 +39,4 @@ def test_alien_default assert_empty alien end - end diff --git a/ruby/test/rubygems/test_gem_version.rb b/ruby/test/rubygems/test_gem_version.rb index 1deecc0ee..f8066ecbb 100644 --- a/ruby/test/rubygems/test_gem_version.rb +++ b/ruby/test/rubygems/test_gem_version.rb @@ -1,11 +1,8 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require "rubygems/version" -require "minitest/benchmark" - class TestGemVersion < Gem::TestCase - class V < ::Gem::Version end @@ -48,9 +45,11 @@ def test_class_correct assert_equal false, Gem::Version.correct?("an incorrect version") expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" - assert_output nil, expected do + actual_stdout, actual_stderr = capture_output do Gem::Version.correct?(nil) end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end def test_class_new_subclass @@ -101,7 +100,7 @@ def test_initialize_invalid invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e." invalid_versions.each do |invalid| - e = assert_raises ArgumentError, invalid do + e = assert_raise ArgumentError, invalid do Gem::Version.new invalid end @@ -109,15 +108,6 @@ def test_initialize_invalid end end - def bench_anchored_version_pattern - assert_performance_linear 0.5 do |count| - version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." - version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN - end - rescue RegexpError - skip "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" - end - def test_empty_version ["", " ", " "].each do |empty| assert_equal "0", Gem::Version.new(empty).version @@ -164,6 +154,10 @@ def test_spaceship assert_equal(-1, v("5.a") <=> v("5.0.0.rc2")) assert_equal(1, v("5.x") <=> v("5.0.0.rc2")) + assert_equal(0, v("1.9.3") <=> "1.9.3") + assert_equal(1, v("1.9.3") <=> "1.9.2.99") + assert_equal(-1, v("1.9.3") <=> "1.9.3.1") + assert_nil v("1.0") <=> "whatever" end @@ -236,7 +230,7 @@ def assert_approximate_equal(expected, version) assert_equal expected, v(version).approximate_recommendation end - # Assert that the "approximate" recommendation for +version+ satifies +version+. + # Assert that the "approximate" recommendation for +version+ satisfies +version+. def assert_approximate_satisfies_itself(version) gem_version = v(version) @@ -298,5 +292,4 @@ def refute_version_eql(first, second) def refute_version_equal(unexpected, actual) refute_equal v(unexpected), v(actual) end - end diff --git a/ruby/test/rubygems/test_gem_version_option.rb b/ruby/test/rubygems/test_gem_version_option.rb index a680c5154..74d7979e3 100644 --- a/ruby/test/rubygems/test_gem_version_option.rb +++ b/ruby/test/rubygems/test_gem_version_option.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems/command' require 'rubygems/version_option' class TestGemVersionOption < Gem::TestCase - def setup super @@ -57,7 +56,7 @@ def test_platform_option_ruby @cmd.handle_options %w[--platform ruby] expected = [ - Gem::Platform::RUBY + Gem::Platform::RUBY, ] assert_equal expected, Gem.platforms @@ -162,5 +161,4 @@ def test_version_option_twice assert_equal expected, @cmd.options end - end diff --git a/ruby/test/rubygems/test_kernel.rb b/ruby/test/rubygems/test_kernel.rb index b9f9b5e25..4efa7e075 100644 --- a/ruby/test/rubygems/test_kernel.rb +++ b/ruby/test/rubygems/test_kernel.rb @@ -1,14 +1,15 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestKernel < Gem::TestCase - def setup super @old_path = $:.dup util_make_gems + + without_any_upwards_gemfiles end def teardown @@ -19,7 +20,7 @@ def teardown def test_gem assert gem('a', '= 1'), "Should load" - assert $:.any? { |p| %r{a-1/lib} =~ p } + assert $:.any? {|p| %r{a-1/lib} =~ p } end def test_gem_default @@ -39,7 +40,7 @@ def test_gem_default_re_gem def test_gem_re_gem_mismatch assert gem('a', '=1') - assert_raises Gem::LoadError do + assert_raise Gem::LoadError do gem('a', '= 2') end @@ -49,13 +50,13 @@ def test_gem_re_gem_mismatch def test_gem_redundant assert gem('a', '= 1'), "Should load" refute gem('a', '= 1'), "Should not load" - assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size + assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size end def test_gem_overlapping assert gem('a', '= 1'), "Should load" refute gem('a', '>= 1'), "Should not load" - assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size + assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size end def test_gem_prerelease @@ -66,7 +67,7 @@ def test_gem_prerelease def test_gem_env_req ENV["GEM_REQUIREMENT_A"] = '~> 2.0' - assert_raises(Gem::MissingSpecVersionError) { gem('a', '= 1') } + assert_raise(Gem::MissingSpecVersionError) { gem('a', '= 1') } assert gem('a', '> 1') assert_equal @a2, Gem.loaded_specs['a'] end @@ -74,7 +75,7 @@ def test_gem_env_req def test_gem_conflicting assert gem('a', '= 1'), "Should load" - ex = assert_raises Gem::LoadError do + ex = assert_raise Gem::LoadError do gem 'a', '= 2' end @@ -82,13 +83,30 @@ def test_gem_conflicting assert_match(/activated a-1/, ex.message) assert_equal 'a', ex.name - assert $:.any? { |p| %r{a-1/lib} =~ p } - refute $:.any? { |p| %r{a-2/lib} =~ p } + assert $:.any? {|p| %r{a-1/lib} =~ p } + refute $:.any? {|p| %r{a-2/lib} =~ p } end def test_gem_not_adding_bin assert gem('a', '= 1'), "Should load" - refute $:.any? { |p| %r{a-1/bin} =~ p } + refute $:.any? {|p| %r{a-1/bin} =~ p } + end + + def test_gem_failing_inside_require_doesnt_cause_double_exceptions + File.write("activate.rb", "gem('a', '= 999')\n") + + require "open3" + + output, _ = Open3.capture2e( + { "GEM_HOME" => Gem.paths.home }, + *ruby_with_rubygems_in_load_path, + "-r", + "./activate.rb" + ) + + load_errors = output.split("\n").select {|line| line.include?("Could not find") } + + assert_equal 1, load_errors.size end def test_gem_bundler @@ -96,29 +114,16 @@ def test_gem_bundler quick_gem 'bundler', '2.a' assert gem('bundler') - assert $:.any? { |p| %r{bundler-1/lib} =~ p } - end - - def test_gem_bundler_missing_bundler_version - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do - quick_gem 'bundler', '1' - quick_gem 'bundler', '2.a' - - e = assert_raises Gem::MissingSpecVersionError do - gem('bundler') - end - assert_match "Could not find 'bundler' (55) required by reason.", e.message - end + assert $:.any? {|p| %r{bundler-1/lib} =~ p } end def test_gem_bundler_inferred_bundler_version - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do + Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do quick_gem 'bundler', '1' quick_gem 'bundler', '2.a' assert gem('bundler', '>= 0.a') - assert $:.any? { |p| %r{bundler-1/lib} =~ p } + assert $:.any? {|p| %r{bundler-1/lib} =~ p } end end - end diff --git a/ruby/test/rubygems/test_project_sanity.rb b/ruby/test/rubygems/test_project_sanity.rb index 6a9eb3b83..38c2541df 100644 --- a/ruby/test/rubygems/test_project_sanity.rb +++ b/ruby/test/rubygems/test_project_sanity.rb @@ -1,15 +1,20 @@ # frozen_string_literal: true +require_relative "helper" require "open3" -class TestProjectSanity < Minitest::Test - +class TestProjectSanity < Gem::TestCase def test_manifest_is_up_to_date - skip unless File.exist?(File.expand_path("../../../Rakefile", __FILE__)) + pend unless File.exist?(File.expand_path("../../../Rakefile", __FILE__)) _, status = Open3.capture2e("rake check_manifest") assert status.success?, "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it." end + def test_require_rubygems_package + err, status = Open3.capture2e(*ruby_with_rubygems_in_load_path, "--disable-gems", "-e", "require \"rubygems/package\"") + + assert status.success?, err + end end diff --git a/ruby/test/rubygems/test_remote_fetch_error.rb b/ruby/test/rubygems/test_remote_fetch_error.rb index 766086756..b9e58389d 100644 --- a/ruby/test/rubygems/test_remote_fetch_error.rb +++ b/ruby/test/rubygems/test_remote_fetch_error.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' class TestRemoteFetchError < Gem::TestCase - def test_password_redacted error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://user:secret@gemsource.org') - refute_match 'secret', error.to_s + refute_match %r{secret}, error.to_s end def test_invalid_url @@ -17,5 +16,4 @@ def test_to_s error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://gemsource.org') assert_equal error.to_s, 'There was an error fetching (https://gemsource.org)' end - end diff --git a/ruby/test/rubygems/test_require.rb b/ruby/test/rubygems/test_require.rb index aa2675af5..5b826d052 100644 --- a/ruby/test/rubygems/test_require.rb +++ b/ruby/test/rubygems/test_require.rb @@ -1,11 +1,9 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'helper' require 'rubygems' class TestGemRequire < Gem::TestCase - class Latch - def initialize(count = 1) @count = count @lock = Monitor.new @@ -24,17 +22,6 @@ def await @cv.wait_while { @count > 0 } end end - - end - - def setup - super - - @old_loaded_features = $LOADED_FEATURES.dup - assert_raises LoadError do - require 'test_gem_require_a' - end - $LOADED_FEATURES.replace @old_loaded_features end def assert_require(path) @@ -45,6 +32,35 @@ def refute_require(path) refute require(path), "'#{path}' was not yet required" end + def test_respect_loaded_features_caching_like_standard_require + dir = Dir.mktmpdir("test_require", @tempdir) + + lp1 = File.join dir, 'foo1' + foo1 = File.join lp1, 'foo.rb' + + FileUtils.mkdir_p lp1 + File.open(foo1, 'w') {|f| f.write "class Object; HELLO = 'foo1' end" } + + lp = $LOAD_PATH.dup + + $LOAD_PATH.unshift lp1 + assert_require 'foo' + assert_equal "foo1", ::Object::HELLO + + lp2 = File.join dir, 'foo2' + foo2 = File.join lp2, 'foo.rb' + + FileUtils.mkdir_p lp2 + File.open(foo2, 'w') {|f| f.write "class Object; HELLO = 'foo2' end" } + + $LOAD_PATH.unshift lp2 + refute_require 'foo' + assert_equal "foo1", ::Object::HELLO + ensure + $LOAD_PATH.replace lp + Object.send :remove_const, :HELLO if Object.const_defined? :HELLO + end + # Providing -I on the commandline should always beat gems def test_dash_i_beats_gems a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb" @@ -60,9 +76,7 @@ def test_dash_i_beats_gems c_rb = File.join dash_i_arg, 'b', 'c.rb' FileUtils.mkdir_p File.dirname c_rb - File.open(c_rb, 'w') { |f| f.write "class Object; HELLO = 'world' end" } - - lp = $LOAD_PATH.dup + File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" } # Pretend to provide a commandline argument that overrides a file in gem b $LOAD_PATH.unshift dash_i_arg @@ -70,9 +84,8 @@ def test_dash_i_beats_gems assert_require 'test_gem_require_a' assert_require 'b/c' # this should be required from -I assert_equal "world", ::Object::HELLO - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names ensure - $LOAD_PATH.replace lp Object.send :remove_const, :HELLO if Object.const_defined? :HELLO end @@ -94,7 +107,7 @@ def test_dash_i_beats_default_gems c1 = new_default_spec "c", "1", nil, "c/c.rb" c2 = new_default_spec "c", "2", nil, "c/c.rb" - install_default_specs c1, c2, b1, a1 + install_default_gems c1, c2, b1, a1 dir = Dir.mktmpdir("test_require", @tempdir) dash_i_arg = File.join dir, 'lib' @@ -102,24 +115,34 @@ def test_dash_i_beats_default_gems c_rb = File.join dash_i_arg, 'c', 'c.rb' FileUtils.mkdir_p File.dirname c_rb - File.open(c_rb, 'w') { |f| f.write "class Object; HELLO = 'world' end" } + File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" } assert_require 'test_gem_require_a' - lp = $LOAD_PATH.dup - # Pretend to provide a commandline argument that overrides a file in gem b $LOAD_PATH.unshift dash_i_arg assert_require 'b/c' assert_require 'c/c' # this should be required from -I assert_equal "world", ::Object::HELLO - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names ensure - $LOAD_PATH.replace lp Object.send :remove_const, :HELLO if Object.const_defined? :HELLO end + def test_dash_i_respects_default_library_extension_priority + pend "extensions don't quite work on jruby" if Gem.java_platform? + pend "not installed yet" unless RbConfig::TOPDIR + + dash_i_ext_arg = util_install_extension_file('a') + dash_i_lib_arg = util_install_ruby_file('a') + + $LOAD_PATH.unshift dash_i_lib_arg + $LOAD_PATH.unshift dash_i_ext_arg + assert_require 'a' + assert_match(/a\.rb$/, $LOADED_FEATURES.last) + end + def test_concurrent_require Object.const_set :FILE_ENTERED_LATCH, Latch.new(2) Object.const_set :FILE_EXIT_LATCH, Latch.new(1) @@ -153,11 +176,11 @@ def test_require_is_not_lazy_with_exact_req install_specs b1, b2, a1 assert_require 'test_gem_require_a' - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names assert_equal unresolved_names, [] assert_require "b/c" - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names end def test_require_is_lazy_with_inexact_req @@ -168,11 +191,11 @@ def test_require_is_lazy_with_inexact_req install_specs b1, b2, a1 assert_require 'test_gem_require_a' - assert_equal %w(a-1), loaded_spec_names + assert_equal %w[a-1], loaded_spec_names assert_equal unresolved_names, ["b (>= 1)"] assert_require "b/c" - assert_equal %w(a-1 b-2), loaded_spec_names + assert_equal %w[a-1 b-2], loaded_spec_names end def test_require_is_not_lazy_with_one_possible @@ -182,11 +205,11 @@ def test_require_is_not_lazy_with_one_possible install_specs b1, a1 assert_require 'test_gem_require_a' - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names assert_equal unresolved_names, [] assert_require "b/c" - assert_equal %w(a-1 b-1), loaded_spec_names + assert_equal %w[a-1 b-1], loaded_spec_names end def test_require_can_use_a_pathname_object @@ -195,42 +218,87 @@ def test_require_can_use_a_pathname_object install_specs a1 assert_require Pathname.new 'test_gem_require_a' - assert_equal %w(a-1), loaded_spec_names + assert_equal %w[a-1], loaded_spec_names assert_equal unresolved_names, [] end def test_activate_via_require_respects_loaded_files - skip "Not sure what's going on. If another spec creates a 'a' gem before + pend "Not sure what's going on. If another spec creates a 'a' gem before this test, somehow require will load the benchmark in b, and ignore that the stdlib one is already in $LOADED_FEATURES?. Reproducible by running the spaceship_specific_file test before this one" if java_platform? - lp = $LOAD_PATH.dup - lib_dir = File.expand_path(File.join(File.dirname(__FILE__), "../../lib")) - if File.exist?(lib_dir) + pend "not installed yet" unless RbConfig::TOPDIR + + lib_dir = File.expand_path("../../lib", File.dirname(__FILE__)) + rubylibdir = File.realdirpath(RbConfig::CONFIG["rubylibdir"]) + if rubylibdir == lib_dir + # testing in the ruby repository where RubyGems' lib/ == stdlib lib/ + # In that case we want to move the stdlib lib/ to still be after b-2 in $LOAD_PATH + lp = $LOAD_PATH.dup $LOAD_PATH.delete lib_dir $LOAD_PATH.push lib_dir + load_path_changed = true end + require 'benchmark' # the stdlib + a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" b1 = util_spec "b", "1", nil, "lib/benchmark.rb" b2 = util_spec "b", "2", nil, "lib/benchmark.rb" install_specs b1, b2, a1 + # Activates a-1, but not b-1 and b-2 assert_require 'test_gem_require_a' + assert_equal %w[a-1], loaded_spec_names + assert $LOAD_PATH.include? a1.load_paths[0] + refute $LOAD_PATH.include? b1.load_paths[0] + refute $LOAD_PATH.include? b2.load_paths[0] + assert_equal unresolved_names, ["b (>= 1)"] - refute require('benchmark'), "benchmark should have already been loaded" + # The require('benchmark') below will activate b-2. However, its + # lib/benchmark.rb won't ever be loaded. The reason is MRI sees that even + # though b-2 is earlier in $LOAD_PATH it already loaded a benchmark.rb file + # and that still exists in $LOAD_PATH (further down), + # and as a result #gem_original_require returns false. + refute require('benchmark'), "the benchmark stdlib should be recognized as already loaded" + + assert_includes $LOAD_PATH, b2.load_paths[0] + assert_includes $LOAD_PATH, rubylibdir + message = proc { + "this test relies on the b-2 gem lib/ to be before stdlib to make sense\n" + + $LOAD_PATH.pretty_inspect + } + assert_operator $LOAD_PATH.index(b2.load_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message # We detected that we should activate b-2, so we did so, but - # then original_require decided "I've already got benchmark.rb" loaded. - # This case is fine because our lazy loading is provided exactly + # then #gem_original_require decided "I've already got some benchmark.rb" loaded. + # This case is fine because our lazy loading provided exactly # the same behavior as eager loading would have. - assert_equal %w(a-1 b-2), loaded_spec_names + assert_equal %w[a-1 b-2], loaded_spec_names ensure - $LOAD_PATH.replace lp unless java_platform? + $LOAD_PATH.replace lp if load_path_changed + end + + def test_activate_via_require_respects_loaded_default_from_default_gems + a1 = new_default_spec "a", "1", nil, "a.rb" + + # simulate requiring a default gem before rubygems is loaded + Kernel.send(:gem_original_require, "a") + + # simulate registering default specs on loading rubygems + install_default_gems a1 + + a2 = util_spec "a", "2", nil, "lib/a.rb" + + install_specs a2 + + refute_require 'a' + + assert_equal %w[a-1], loaded_spec_names end def test_already_activated_direct_conflict @@ -244,12 +312,12 @@ def test_already_activated_direct_conflict a1.activate c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal %w[a-1 c-1], loaded_spec_names assert_equal ["b (> 0)"], unresolved_names assert require("ib") - assert_equal %w(a-1 b-1 c-1), loaded_spec_names + assert_equal %w[a-1 b-1 c-1], loaded_spec_names assert_equal [], unresolved_names end @@ -266,10 +334,10 @@ def test_multiple_gems_with_the_same_path a1.activate c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal %w[a-1 c-1], loaded_spec_names assert_equal ["b (> 0)", "x (> 0)"], unresolved_names - e = assert_raises(Gem::LoadError) do + e = assert_raise(Gem::LoadError) do require("ib") end @@ -289,10 +357,10 @@ def test_unable_to_find_good_unresolved_version a1.activate c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal %w[a-1 c-1], loaded_spec_names assert_equal ["b (> 0)"], unresolved_names - e = assert_raises(Gem::LoadError) do + e = assert_raise(Gem::LoadError) do require("ib") end @@ -315,26 +383,26 @@ def test_require_works_after_cleanup # Remove an old default gem version directly from disk as if someone ran # gem cleanup. - FileUtils.rm_rf(File.join @default_dir, "#{b1.full_name}") - FileUtils.rm_rf(File.join @default_spec_dir, "#{b1.full_name}.gemspec") + FileUtils.rm_rf(File.join @gemhome, "#{b1.full_name}") + FileUtils.rm_rf(File.join @gemhome, "specifications", "default", "#{b1.full_name}.gemspec") # Require gems that have not been removed. assert_require 'a/b' - assert_equal %w(a-1.0), loaded_spec_names + assert_equal %w[a-1.0], loaded_spec_names assert_require 'b/d' - assert_equal %w(a-1.0 b-2.0), loaded_spec_names + assert_equal %w[a-1.0 b-2.0], loaded_spec_names end def test_require_doesnt_traverse_development_dependencies a = util_spec("a#{$$}", "1", nil, "lib/a#{$$}.rb") z = util_spec("z", "1", "w" => "> 0") - w1 = util_spec("w", "1") { |s| s.add_development_dependency "non-existent" } - w2 = util_spec("w", "2") { |s| s.add_development_dependency "non-existent" } + w1 = util_spec("w", "1") {|s| s.add_development_dependency "non-existent" } + w2 = util_spec("w", "2") {|s| s.add_development_dependency "non-existent" } install_specs a, w1, w2, z assert gem("z") - assert_equal %w(z-1), loaded_spec_names + assert_equal %w[z-1], loaded_spec_names assert_equal ["w (> 0)"], unresolved_names assert require("a#{$$}") @@ -343,15 +411,15 @@ def test_require_doesnt_traverse_development_dependencies def test_default_gem_only default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) assert_require "default/gem" - assert_equal %w(default-2.0.0.0), loaded_spec_names + assert_equal %w[default-2.0.0.0], loaded_spec_names end def test_default_gem_require_activates_just_once default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) assert_require "default/gem" @@ -364,41 +432,102 @@ def test_default_gem_require_activates_just_once assert_equal 0, times_called end + def test_second_gem_require_does_not_resolve_path_manually_before_going_through_standard_require + a1 = util_spec "a", "1", nil, "lib/test_gem_require_a.rb" + install_gem a1 + + assert_require "test_gem_require_a" + + stub(:gem_original_require, ->(path) { assert_equal "test_gem_require_a", path }) do + require "test_gem_require_a" + end + end + def test_realworld_default_gem - testing_ruby_repo = !ENV["GEM_COMMAND"].nil? - skip "this test can't work under ruby-core setup" if testing_ruby_repo || java_platform? + omit "this test can't work under ruby-core setup" if testing_ruby_repo? cmd = <<-RUBY $stderr = $stdout require "json" puts Gem.loaded_specs["json"] RUBY - output = Gem::Util.popen(Gem.ruby, "-e", cmd).strip + output = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", cmd).strip + assert $?.success? refute_empty output end + def test_realworld_upgraded_default_gem + omit "this test can't work under ruby-core setup" if testing_ruby_repo? + + newer_json = util_spec("json", "999.99.9", nil, ["lib/json.rb"]) + install_gem newer_json + + path = "#{@tempdir}/test_realworld_upgraded_default_gem.rb" + code = <<-RUBY + $stderr = $stdout + require "json" + puts Gem.loaded_specs["json"].version + puts $LOADED_FEATURES + RUBY + File.write(path, code) + + output = Gem::Util.popen({ 'GEM_HOME' => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip + assert $?.success? + refute_empty output + assert_equal "999.99.9", output.lines[0].chomp + # Make sure only files from the newer json gem are loaded, and no files from the default json gem + assert_equal ["#{@gemhome}/gems/json-999.99.9/lib/json.rb"], output.lines.grep(%r{/gems/json-}).map(&:chomp) + end + def test_default_gem_and_normal_gem default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) normal_gem_spec = util_spec("default", "3.0", nil, "lib/default/gem.rb") install_specs(normal_gem_spec) assert_require "default/gem" - assert_equal %w(default-3.0), loaded_spec_names + assert_equal %w[default-3.0], loaded_spec_names + end + + def test_normal_gems_with_overridden_load_error_message + normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb") + + install_specs(normal_gem_spec) + + File.write("require_with_overridden_load_error_message.rb", <<-RUBY) + LoadError.class_eval do + def message + "Overridden message" + end + end + + require 'normal/gem' + RUBY + + require "open3" + + output, exit_status = Open3.capture2e( + { "GEM_HOME" => Gem.paths.home }, + *ruby_with_rubygems_in_load_path, + "-r", + "./require_with_overridden_load_error_message.rb" + ) + + assert exit_status.success?, "Require failed due to #{output}" end def test_default_gem_prerelease default_gem_spec = new_default_spec("default", "2.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) normal_gem_higher_prerelease_spec = util_spec("default", "3.0.0.rc2", nil, "lib/default/gem.rb") - install_default_specs(normal_gem_higher_prerelease_spec) + install_default_gems(normal_gem_higher_prerelease_spec) assert_require "default/gem" - assert_equal %w(default-3.0.0.rc2), loaded_spec_names + assert_equal %w[default-3.0.0.rc2], loaded_spec_names end def loaded_spec_names @@ -412,10 +541,8 @@ def unresolved_names def test_try_activate_error_unlocks_require_monitor silence_warnings do class << ::Gem - alias old_try_activate try_activate def try_activate(*); raise 'raised from try_activate'; end - end end @@ -426,9 +553,7 @@ def try_activate(*); raise 'raised from try_activate'; end ensure silence_warnings do class << ::Gem - alias try_activate old_try_activate - end end Kernel::RUBYGEMS_ACTIVATION_MONITOR.exit @@ -437,14 +562,14 @@ class << ::Gem def test_require_when_gem_defined default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") - install_default_specs(default_gem_spec) + install_default_gems(default_gem_spec) c = Class.new do def self.gem(*args) raise "received #gem with #{args.inspect}" end end assert c.send(:require, "default/gem") - assert_equal %w(default-2.0.0.0), loaded_spec_names + assert_equal %w[default-2.0.0.0], loaded_spec_names end def test_require_default_when_gem_defined @@ -456,7 +581,7 @@ def self.gem(*args) end end assert c.send(:require, "a#{$$}") - assert_equal %W(a#{$$}-1), loaded_spec_names + assert_equal %W[a#{$$}-1], loaded_spec_names end def test_require_bundler @@ -471,72 +596,128 @@ def test_require_bundler assert_empty unresolved_names end - def test_require_bundler_missing_bundler_version - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do - b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") - b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb") - install_specs b1, b2a - - e = assert_raises Gem::MissingSpecVersionError do - gem('bundler') - end - assert_match "Could not find 'bundler' (55) required by reason.", e.message - end - end - - def test_require_bundler_with_bundler_version - Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do - b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") - b2 = util_spec('bundler', '2', nil, "lib/bundler/setup.rb") - install_specs b1, b2 - - $:.clear - assert_require 'bundler/setup' - assert_equal %w[bundler-1.999999999], loaded_spec_names - end - end - # uplevel is 2.5+ only if RUBY_VERSION >= "2.5" ["", "Kernel."].each do |prefix| define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do - lib = File.realpath("../../../lib", __FILE__) Dir.mktmpdir("warn_test") do |dir| File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n") File.write(dir + "/main.rb", "require 'sub'\n") _, err = capture_subprocess_io do - system(@@ruby, "-w", "--disable=gems", "-I", lib, "-C", dir, "-I.", "main.rb") + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") end assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) _, err = capture_subprocess_io do - system(@@ruby, "-w", "--enable=gems", "-I", lib, "-C", dir, "-I.", "main.rb") + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") end assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) end end define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do - lib = File.realpath("../../../lib", __FILE__) Dir.mktmpdir("warn_test") do |dir| File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n") _, err = capture_subprocess_io do - system(@@ruby, "-w", "--disable=gems", "-I", lib, "-C", dir, "main.rb") + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb") end assert_match(/{:x=>1}\n{:y=>2}\n$/, err) _, err = capture_subprocess_io do - system(@@ruby, "-w", "--enable=gems", "-I", lib, "-C", dir, "main.rb") + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb") end assert_match(/{:x=>1}\n{:y=>2}\n$/, err) end end end + + def test_no_crash_when_overriding_warn_with_warning_module + Dir.mktmpdir("warn_test") do |dir| + File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'") + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb") + end + assert_match(/Foo Bar\n$/, err) + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb") + end + assert_match(/Foo Bar\n$/, err) + end + end + + def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel + Dir.mktmpdir("warn_test") do |dir| + File.write(dir + "/main.rb", "\nrequire 'sub'\n") + File.write(dir + "/sub.rb", <<-'RUBY') + require 'rubygems' + class C < BasicObject + include ::Kernel + def deprecated + warn "This is a deprecated method", uplevel: 2 + end + end + C.new.deprecated + RUBY + + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") + end + assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") + end + assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) + end + end end - def silence_warnings - old_verbose, $VERBOSE = $VERBOSE, false - yield - ensure - $VERBOSE = old_verbose + private + + def testing_ruby_repo? + !ENV["GEM_COMMAND"].nil? + end + + def util_install_extension_file(name) + spec = quick_gem name + util_build_gem spec + + spec.extensions << "extconf.rb" + write_file File.join(@tempdir, "extconf.rb") do |io| + io.write <<-RUBY + require "mkmf" + CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' + create_makefile("#{name}") + RUBY + end + + write_file File.join(@tempdir, "#{name}.c") do |io| + io.write <<-C + void Init_#{name}() { } + C + end + + write_file File.join(@tempdir, "depend") + + spec.files += ["extconf.rb", "depend", "#{name}.c"] + + so = File.join(spec.gem_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}") + assert_path_not_exist so + + path = Gem::Package.build spec + installer = Gem::Installer.at path + installer.install + assert_path_exist so + + spec.gem_dir end + def util_install_ruby_file(name) + dir_lib = Dir.mktmpdir("test_require_lib", @tempdir) + dash_i_lib_arg = File.join dir_lib + + a_rb = File.join dash_i_lib_arg, "#{name}.rb" + + FileUtils.mkdir_p File.dirname a_rb + File.open(a_rb, 'w') {|f| f.write "# #{name}.rb" } + + dash_i_lib_arg + end end diff --git a/ruby/test/rubygems/test_rubygems.rb b/ruby/test/rubygems/test_rubygems.rb new file mode 100644 index 000000000..26c5f1e0f --- /dev/null +++ b/ruby/test/rubygems/test_rubygems.rb @@ -0,0 +1,71 @@ +require_relative 'helper' + +class GemTest < Gem::TestCase + def test_rubygems_normal_behaviour + _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip + assert $?.success? + end + + def test_operating_system_other_exceptions + pend "does not apply to truffleruby" if RUBY_ENGINE == 'truffleruby' + + path = util_install_operating_system_rb <<-RUBY + intentionally_not_implemented_method + RUBY + + output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip + assert !$?.success? + assert_includes output, "undefined local variable or method `intentionally_not_implemented_method'" + assert_includes output, "Loading the rubygems/defaults/operating_system.rb file caused an error. " \ + "This file is owned by your OS, not by rubygems upstream. " \ + "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \ + "the problem and ask for help." + end + + def test_operating_system_customizing_default_dir + pend "does not apply to truffleruby" if RUBY_ENGINE == 'truffleruby' + pend "loads a custom defaults/jruby file that gets in the middle" if RUBY_ENGINE == 'jruby' + + # On a non existing default dir, there should be no gems + + path = util_install_operating_system_rb <<-RUBY + module Gem + def self.default_dir + File.expand_path("foo") + end + end + RUBY + + output = Gem::Util.popen( + *ruby_with_rubygems_and_fake_operating_system_in_load_path(path), + '-e', + "require \"rubygems\"; puts Gem::Specification.stubs.map(&:full_name)", + {:err => [:child, :out]} + ).strip + begin + assert_empty output + rescue Test::Unit::AssertionFailedError + pend "Temporary pending custom default_dir test" + end + end + + private + + def util_install_operating_system_rb(content) + dir_lib = Dir.mktmpdir("test_operating_system_lib", @tempdir) + dir_lib_arg = File.join dir_lib + + dir_lib_rubygems_defaults_arg = File.join dir_lib_arg, "lib", "rubygems", "defaults" + FileUtils.mkdir_p dir_lib_rubygems_defaults_arg + + operating_system_rb = File.join dir_lib_rubygems_defaults_arg, "operating_system.rb" + + File.open(operating_system_rb, 'w') {|f| f.write content } + + File.join dir_lib_arg, "lib" + end + + def ruby_with_rubygems_and_fake_operating_system_in_load_path(operating_system_path) + [Gem.ruby, "-I", operating_system_path, "-I" , $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }] + end +end diff --git a/ruby/test/rubygems/utilities.rb b/ruby/test/rubygems/utilities.rb new file mode 100644 index 000000000..613cf6c0e --- /dev/null +++ b/ruby/test/rubygems/utilities.rb @@ -0,0 +1,371 @@ +# frozen_string_literal: true +require 'tempfile' +require 'rubygems' +require 'rubygems/remote_fetcher' + +## +# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP +# requests when testing code that uses RubyGems. +# +# Example: +# +# @fetcher = Gem::FakeFetcher.new +# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml +# Gem::RemoteFetcher.fetcher = @fetcher +# +# use nested array if multiple response is needed +# +# @fetcher.data['http://gems.example.com/sequence'] = [['Success', 200, 'OK'], ['Failed', 401, 'Unauthorized']] +# +# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Success', 200, 'OK'] +# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Failed', 401, 'Unauthorized'] +# +# # invoke RubyGems code +# +# paths = @fetcher.paths +# assert_equal 'http://gems.example.com/yaml', paths.shift +# assert paths.empty?, paths.join(', ') +# +# See RubyGems' tests for more examples of FakeFetcher. + +class Gem::FakeFetcher + attr_reader :data + attr_reader :last_request + attr_accessor :paths + + def initialize + @data = {} + @paths = [] + end + + def find_data(path) + return Gem.read_binary path.path if URI === path and 'file' == path.scheme + + if URI === path and "URI::#{path.scheme.upcase}" != path.class.name + raise ArgumentError, + "mismatch for scheme #{path.scheme} and class #{path.class}" + end + + path = path.to_s + @paths << path + raise ArgumentError, 'need full URI' unless path.start_with?("https://", "http://") + + unless @data.key? path + raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) + end + + if @data[path].kind_of?(Array) && @data[path].first.kind_of?(Array) + @data[path].shift + else + @data[path] + end + end + + def fetch_path(path, mtime = nil, head = false) + data = find_data(path) + + if data.respond_to?(:call) + data.call + else + if path.to_s.end_with?(".gz") and not data.nil? and not data.empty? + data = Gem::Util.gunzip data + end + data + end + end + + def cache_update_path(uri, path = nil, update = true) + if data = fetch_path(uri) + File.open(path, 'wb') {|io| io.write data } if path and update + data + else + Gem.read_binary(path) if path + end + end + + # Thanks, FakeWeb! + def open_uri_or_path(path) + data = find_data(path) + body, code, msg = data + + response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) + response.instance_variable_set(:@body, body) + response.instance_variable_set(:@read, true) + response + end + + def request(uri, request_class, last_modified = nil) + data = find_data(uri) + body, code, msg = (data.respond_to?(:call) ? data.call : data) + + @last_request = request_class.new uri.request_uri + yield @last_request if block_given? + + response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) + response.instance_variable_set(:@body, body) + response.instance_variable_set(:@read, true) + response + end + + def pretty_print(q) # :nodoc: + q.group 2, '[FakeFetcher', ']' do + q.breakable + q.text 'URIs:' + + q.breakable + q.pp @data.keys + end + end + + def fetch_size(path) + path = path.to_s + @paths << path + + raise ArgumentError, 'need full URI' unless path =~ %r{^http://} + + unless @data.key? path + raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) + end + + data = @data[path] + + data.respond_to?(:call) ? data.call : data.length + end + + def download(spec, source_uri, install_dir = Gem.dir) + name = File.basename spec.cache_file + path = if Dir.pwd == install_dir # see fetch_command + install_dir + else + File.join install_dir, "cache" + end + + path = File.join path, name + + if source_uri =~ /^http/ + File.open(path, "wb") do |f| + f.write fetch_path(File.join(source_uri, "gems", name)) + end + else + FileUtils.cp source_uri, path + end + + path + end + + def download_to_cache(dependency) + found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency + + return if found.empty? + + spec, source = found.first + + download spec, source.uri.to_s + end +end + +# :stopdoc: +class Gem::RemoteFetcher + def self.fetcher=(fetcher) + @fetcher = fetcher + end +end +# :startdoc: + +## +# The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests: +# +# spec_fetcher do |f| +# f.gem 'a', 1 +# f.spec 'a', 2 +# f.gem 'b', 1' 'a' => '~> 1.0' +# end +# +# The above declaration creates two gems, a-1 and b-1, with a dependency from +# b to a. The declaration creates an additional spec a-2, but no gem for it +# (so it cannot be installed). +# +# After the gems are created they are removed from Gem.dir. + +class Gem::TestCase::SpecFetcherSetup + ## + # Executes a SpecFetcher setup block. Yields an instance then creates the + # gems and specifications defined in the instance. + + def self.declare(test, repository) + setup = new test, repository + + yield setup + + setup.execute + end + + def initialize(test, repository) # :nodoc: + @test = test + @repository = repository + + @gems = {} + @downloaded = [] + @installed = [] + @operations = [] + end + + ## + # Returns a Hash of created Specification full names and the corresponding + # Specification. + + def created_specs + created = {} + + @gems.keys.each do |spec| + created[spec.full_name] = spec + end + + created + end + + ## + # Creates any defined gems or specifications + + def execute # :nodoc: + execute_operations + + setup_fetcher + + created_specs + end + + def execute_operations # :nodoc: + @operations.each do |operation, *arguments| + block = arguments.pop + case operation + when :gem then + spec, gem = @test.util_gem(*arguments, &block) + + write_spec spec + + @gems[spec] = gem + @installed << spec + when :download then + spec, gem = @test.util_gem(*arguments, &block) + + @gems[spec] = gem + @downloaded << spec + when :spec then + spec = @test.util_spec(*arguments, &block) + + write_spec spec + + @gems[spec] = nil + @installed << spec + end + end + end + + ## + # Creates a gem with +name+, +version+ and +deps+. The created gem can be + # downloaded and installed. + # + # The specification will be yielded before gem creation for customization, + # but only the block or the dependencies may be set, not both. + + def gem(name, version, dependencies = nil, &block) + @operations << [:gem, name, version, dependencies, block] + end + + ## + # Creates a gem with +name+, +version+ and +deps+. The created gem is + # downloaded in to the cache directory but is not installed + # + # The specification will be yielded before gem creation for customization, + # but only the block or the dependencies may be set, not both. + + def download(name, version, dependencies = nil, &block) + @operations << [:download, name, version, dependencies, block] + end + + ## + # Creates a legacy platform spec with the name 'pl' and version 1 + + def legacy_platform + spec 'pl', 1 do |s| + s.platform = Gem::Platform.new 'i386-linux' + s.instance_variable_set :@original_platform, 'i386-linux' + end + end + + def setup_fetcher # :nodoc: + require 'zlib' + require 'socket' + require 'rubygems/remote_fetcher' + + unless @test.fetcher + @test.fetcher = Gem::FakeFetcher.new + Gem::RemoteFetcher.fetcher = @test.fetcher + end + + Gem::Specification.reset + + begin + gem_repo, @test.gem_repo = @test.gem_repo, @repository + @test.uri = URI @repository + + @test.util_setup_spec_fetcher(*@downloaded) + ensure + @test.gem_repo = gem_repo + @test.uri = URI gem_repo + end + + @gems.each do |spec, gem| + next unless gem + + @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] = + Gem.read_binary(gem) + + FileUtils.cp gem, spec.cache_file + end + end + + ## + # Creates a spec with +name+, +version+ and +deps+. The created gem can be + # downloaded and installed. + # + # The specification will be yielded before creation for customization, + # but only the block or the dependencies may be set, not both. + + def spec(name, version, dependencies = nil, &block) + @operations << [:spec, name, version, dependencies, block] + end + + def write_spec(spec) # :nodoc: + File.open spec.spec_file, 'w' do |io| + io.write spec.to_ruby_for_cache + end + end +end + +## +# A StringIO duck-typed class that uses Tempfile instead of String as the +# backing store. +# +# This class was added to flush out problems in Rubinius' IO implementation. + +class TempIO < Tempfile + ## + # Creates a new TempIO that will be initialized to contain +string+. + + def initialize(string = '') + super "TempIO" + binmode + write string + rewind + end + + ## + # The content of the TempIO as a String. + + def string + flush + Gem.read_binary path + end +end diff --git a/ruby/test/runner.rb b/ruby/test/runner.rb index 3e2e1316b..1b1ae0956 100644 --- a/ruby/test/runner.rb +++ b/ruby/test/runner.rb @@ -2,9 +2,12 @@ # Should be done in rubygems test files? ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze +ENV.delete("RUBY_CODESIGN") + +Warning[:experimental] = false # Get bundled gems on load path -Dir.glob("#{__dir__}/../gems/*/*.gemspec") +Dir.glob("#{__dir__}/../.bundle/gems/*/*.gemspec") .reject {|f| f =~ /minitest|test-unit|power_assert/ } .map {|f| $LOAD_PATH.unshift File.join(File.dirname(f), "lib") } diff --git a/ruby/test/sdbm/test_sdbm.rb b/ruby/test/sdbm/test_sdbm.rb deleted file mode 100644 index 6cea36d3a..000000000 --- a/ruby/test/sdbm/test_sdbm.rb +++ /dev/null @@ -1,544 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' - -begin - require 'sdbm' -rescue LoadError -end - -class TestSDBM < Test::Unit::TestCase - def setup - @tmpdir = Dir.mktmpdir("tmptest_sdbm") - @prefix = "tmptest_sdbm_#{$$}" - @path = "#{@tmpdir}/#{@prefix}_" - assert_instance_of(SDBM, @sdbm = SDBM.new(@path)) - end - def teardown - assert_nil(@sdbm.close) - ObjectSpace.each_object(SDBM) do |obj| - obj.close unless obj.closed? - end - FileUtils.remove_entry_secure @tmpdir - end - - def check_size(expect, sdbm=@sdbm) - assert_equal(expect, sdbm.size) - n = 0 - sdbm.each { n+=1 } - assert_equal(expect, n) - if expect == 0 - assert_equal(true, sdbm.empty?) - else - assert_equal(false, sdbm.empty?) - end - end - - def test_version - assert(! SDBM.const_defined?(:VERSION)) - end - - def test_s_new_has_no_block - # SDBM.new ignore the block - foo = true - assert_instance_of(SDBM, sdbm = SDBM.new("#{@tmpdir}/#{@prefix}") { foo = false }) - assert_equal(foo, true) - assert_nil(sdbm.close) - end - def test_s_open_no_create - assert_nil(sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", nil)) - ensure - sdbm.close if sdbm - end - def test_s_open_with_block - assert_equal(SDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo) - end -=begin - # Is it guaranteed on many OS? - def test_s_open_lock_one_process - # locking on one process - assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644)) - assert_raise(Errno::EWOULDBLOCK) { - begin - SDBM.open("#{@tmpdir}/#{@prefix}", 0644) - rescue Errno::EAGAIN - raise Errno::EWOULDBLOCK - end - } - end -=end - - def open_db_child(dbname, *opts) - opts = [0644, *opts].map(&:inspect).join(', ') - args = [EnvUtil.rubybin, "-rsdbm", <<-SRC, dbname] - STDOUT.sync = true - gdbm = SDBM.open(ARGV.shift, #{opts}) - puts sdbm.class - gets - SRC - IO.popen(args, "r+") do |f| - dbclass = f.gets - assert_equal("SDBM", dbclass.chomp) - yield - end - end - - def test_s_open_nolock - dbname = "#{@tmpdir}/#{@prefix}" - - open_db_child(dbname, SDBM::NOLOCK) do - assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) { - SDBM.open(dbname, 0644) {|sdbm| - assert_instance_of(SDBM, sdbm) - } - } - end - - p Dir.glob("#{@tmpdir}/#{@prefix}*") if $DEBUG - - open_db_child(dbname) do - assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) { - # this test is failed on Cygwin98 (???) - SDBM.open(dbname, 0644, SDBM::NOLOCK) {|sdbm| - assert_instance_of(SDBM, sdbm) - } - } - end - end if defined? SDBM::NOLOCK # sdbm 1.8.0 specific - - def test_s_open_error - skip "doesn't support to avoid read access by owner on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM - skip "skipped because root can open anything" if Process.uid == 0 - assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0)) - assert_raise(Errno::EACCES) { - SDBM.open("#{@tmpdir}/#{@prefix}", 0) - } - sdbm.close - end - - def test_close - assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}")) - assert_nil(sdbm.close) - - # closed SDBM file - assert_raise(SDBMError) { sdbm.close } - end - - def test_aref - assert_equal('bar', @sdbm['foo'] = 'bar') - assert_equal('bar', @sdbm['foo']) - - assert_nil(@sdbm['bar']) - end - - def test_fetch - assert_equal('bar', @sdbm['foo']='bar') - assert_equal('bar', @sdbm.fetch('foo')) - - # key not found - assert_raise(IndexError) { - @sdbm.fetch('bar') - } - - # test for `ifnone' arg - assert_equal('baz', @sdbm.fetch('bar', 'baz')) - - # test for `ifnone' block - assert_equal('foobar', @sdbm.fetch('bar') {|key| 'foo' + key }) - end - - def test_aset - num = 0 - 2.times {|i| - assert_equal('foo', @sdbm['foo'] = 'foo') - assert_equal('foo', @sdbm['foo']) - assert_equal('bar', @sdbm['foo'] = 'bar') - assert_equal('bar', @sdbm['foo']) - - num += 1 if i == 0 - assert_equal(num, @sdbm.size) - - # assign nil - assert_equal('', @sdbm['bar'] = '') - assert_equal('', @sdbm['bar']) - - num += 1 if i == 0 - assert_equal(num, @sdbm.size) - - # empty string - assert_equal('', @sdbm[''] = '') - assert_equal('', @sdbm['']) - - num += 1 if i == 0 - assert_equal(num, @sdbm.size) - - # Integer - assert_equal('200', @sdbm['100'] = '200') - assert_equal('200', @sdbm['100']) - - num += 1 if i == 0 - assert_equal(num, @sdbm.size) - - # Big key and value - assert_equal('y' * 100, @sdbm['x' * 100] = 'y' * 100) - assert_equal('y' * 100, @sdbm['x' * 100]) - - num += 1 if i == 0 - assert_equal(num, @sdbm.size) - } - end - - def test_key - assert_equal('bar', @sdbm['foo'] = 'bar') - assert_equal('foo', @sdbm.key('bar')) - assert_nil(@sdbm['bar']) - end - - def test_values_at - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - assert_equal(values.reverse, @sdbm.values_at(*keys.reverse)) - end - - def test_select_with_block - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - ret = @sdbm.select {|k,v| - assert_equal(k.upcase, v) - k != "bar" - } - assert_equal([['baz', 'BAZ'], ['foo', 'FOO']], - ret.sort) - end - - def test_length - num = 10 - assert_equal(0, @sdbm.size) - num.times {|i| - i = i.to_s - @sdbm[i] = i - } - assert_equal(num, @sdbm.size) - - @sdbm.shift - - assert_equal(num - 1, @sdbm.size) - end - - def test_empty? - assert_equal(true, @sdbm.empty?) - @sdbm['foo'] = 'FOO' - assert_equal(false, @sdbm.empty?) - end - - def test_each_pair - n = 0 - @sdbm.each_pair { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - n = 0 - ret = @sdbm.each_pair {|key, val| - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@sdbm, ret) - end - - def test_each_value - n = 0 - @sdbm.each_value { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - n = 0 - ret = @sdbm.each_value {|val| - assert_not_nil(key = @sdbm.key(val)) - assert_not_nil(i = keys.index(key)) - assert_equal(val, values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@sdbm, ret) - end - - def test_each_key - n = 0 - @sdbm.each_key { n += 1 } - assert_equal(0, n) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - n = 0 - ret = @sdbm.each_key {|key| - assert_not_nil(i = keys.index(key)) - assert_equal(@sdbm[key], values[i]) - - n += 1 - } - assert_equal(keys.size, n) - assert_equal(@sdbm, ret) - end - - def test_keys - assert_equal([], @sdbm.keys) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - assert_equal(keys.sort, @sdbm.keys.sort) - assert_equal(values.sort, @sdbm.values.sort) - end - - def test_values - test_keys - end - - def test_shift - assert_nil(@sdbm.shift) - assert_equal(0, @sdbm.size) - - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - ret_keys = [] - ret_values = [] - while ret = @sdbm.shift - ret_keys.push ret[0] - ret_values.push ret[1] - - assert_equal(keys.size - ret_keys.size, @sdbm.size) - end - - assert_equal(keys.sort, ret_keys.sort) - assert_equal(values.sort, ret_values.sort) - end - - def test_delete - keys = %w(foo bar baz) - values = %w(FOO BAR BAZ) - key = keys[1] - - assert_nil(@sdbm.delete(key)) - assert_equal(0, @sdbm.size) - - @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values - - assert_equal('BAR', @sdbm.delete(key)) - assert_nil(@sdbm[key]) - assert_equal(2, @sdbm.size) - - assert_nil(@sdbm.delete(key)) - end - def test_delete_with_block - key = 'no called block' - @sdbm[key] = 'foo' - assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'; :blockval}) - assert_equal(0, @sdbm.size) - - key = 'no called block' - assert_equal(:blockval, @sdbm.delete(key) {|k| k.replace 'called block'; :blockval}) - assert_equal(0, @sdbm.size) - end - - def test_delete_if - v = "0" - 100.times {@sdbm[v] = v; v = v.next} - - ret = @sdbm.delete_if {|key, val| key.to_i < 50} - assert_equal(@sdbm, ret) - check_size(50, @sdbm) - - ret = @sdbm.delete_if {|key, val| key.to_i >= 50} - assert_equal(@sdbm, ret) - check_size(0, @sdbm) - - # break - v = "0" - 100.times {@sdbm[v] = v; v = v.next} - check_size(100, @sdbm) - n = 0; - @sdbm.delete_if {|key, val| - break if n > 50 - n+=1 - true - } - assert_equal(51, n) - check_size(49, @sdbm) - - @sdbm.clear - - # raise - v = "0" - 100.times {@sdbm[v] = v; v = v.next} - check_size(100, @sdbm) - n = 0; - begin - @sdbm.delete_if {|key, val| - raise "runtime error" if n > 50 - n+=1 - true - } - rescue RuntimeError - end - assert_equal(51, n) - check_size(49, @sdbm) - end - - def test_reject - v = "0" - 100.times {@sdbm[v] = v; v = v.next} - - hash = @sdbm.reject {|key, val| key.to_i < 50} - assert_instance_of(Hash, hash) - assert_equal(100, @sdbm.size) - - assert_equal(50, hash.size) - hash.each_pair {|key,val| - assert_equal(false, key.to_i < 50) - assert_equal(key, val) - } - - hash = @sdbm.reject {|key, val| key.to_i < 100} - assert_instance_of(Hash, hash) - assert_equal(true, hash.empty?) - end - - def test_clear - v = "1" - 100.times {v = v.next; @sdbm[v] = v} - - assert_equal(@sdbm, @sdbm.clear) - - # validate SDBM#size - i = 0 - @sdbm.each { i += 1 } - assert_equal(@sdbm.size, i) - assert_equal(0, i) - end - - def test_invert - v = "0" - 100.times {@sdbm[v] = v; v = v.next} - - hash = @sdbm.invert - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_update - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @sdbm["101"] = "101" - @sdbm.update hash - assert_equal(101, @sdbm.size) - @sdbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_replace - hash = {} - v = "0" - 100.times {v = v.next; hash[v] = v} - - @sdbm["101"] = "101" - @sdbm.replace hash - assert_equal(100, @sdbm.size) - @sdbm.each_pair {|key, val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_haskey? - assert_equal('bar', @sdbm['foo']='bar') - assert_equal(true, @sdbm.has_key?('foo')) - assert_equal(false, @sdbm.has_key?('bar')) - end - - def test_has_value? - assert_equal('bar', @sdbm['foo']='bar') - assert_equal(true, @sdbm.has_value?('bar')) - assert_equal(false, @sdbm.has_value?('foo')) - end - - def test_to_a - v = "0" - 100.times {v = v.next; @sdbm[v] = v} - - ary = @sdbm.to_a - assert_instance_of(Array, ary) - assert_equal(100, ary.size) - ary.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_to_hash - v = "0" - 100.times {v = v.next; @sdbm[v] = v} - - hash = @sdbm.to_hash - assert_instance_of(Hash, hash) - assert_equal(100, hash.size) - hash.each {|key,val| - assert_equal(key.to_i, val.to_i) - } - end - - def test_closed - assert_equal(false, @sdbm.closed?) - @sdbm.close - assert_equal(true, @sdbm.closed?) - @sdbm = SDBM.new(@path) - end - - def test_readonly - skip "skipped because root can read anything" if /mswin|mingw/ !~ RUBY_PLATFORM && Process.uid == 0 - @sdbm["bar"] = "baz" - @sdbm.close - File.chmod(0444, @path + ".dir") - File.chmod(0444, @path + ".pag") - @sdbm = SDBM.new(@path) - assert_raise(SDBMError) { @sdbm["bar"] = "foo" } - assert_raise(SDBMError) { @sdbm.delete("bar") } - assert_raise(SDBMError) { @sdbm.delete_if { true } } - assert_raise(SDBMError) { @sdbm.clear } - assert_nil(@sdbm.store("bar", nil)) - end - - def test_update2 - obj = Object.new - def obj.each_pair - yield [] - end - assert_raise(ArgumentError) { @sdbm.update(obj) } - end -end if defined? SDBM - diff --git a/ruby/test/socket/test_addrinfo.rb b/ruby/test/socket/test_addrinfo.rb index 92b61ea99..5bd34cd5e 100644 --- a/ruby/test/socket/test_addrinfo.rb +++ b/ruby/test/socket/test_addrinfo.rb @@ -103,7 +103,7 @@ def test_addrinfo_predicates end def test_error_message - e = assert_raise_with_message(SocketError, /getaddrinfo:/) do + e = assert_raise_with_message(SocketError, /getaddrinfo/) do Addrinfo.ip("...") end m = e.message @@ -363,11 +363,19 @@ def test_family_addrinfo def random_port # IANA suggests dynamic port for 49152 to 65535 # http://www.iana.org/assignments/port-numbers - 49152 + rand(65535-49152+1) + case RUBY_PLATFORM + when /mingw|mswin/ + rand(50000..65535) + else + rand(49152..65535) + end end def errors_addrinuse - [Errno::EADDRINUSE] + errs = [Errno::EADDRINUSE] + # MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721" + errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM + errs end def test_connect_from @@ -578,7 +586,7 @@ def test_ipv6_address_predicates ai = ipv6(addr) begin assert(ai.ipv4? || ai.send(meth), "ai=#{addr_exp}; ai.ipv4? || .#{meth}") - rescue Minitest::Assertion + rescue Test::Unit::AssertionFailedError if /aix/ =~ RUBY_PLATFORM skip "Known bug in IN6_IS_ADDR_V4COMPAT and IN6_IS_ADDR_V4MAPPED on AIX" end diff --git a/ruby/test/socket/test_basicsocket.rb b/ruby/test/socket/test_basicsocket.rb index c8e9b23f8..02e393d4e 100644 --- a/ruby/test/socket/test_basicsocket.rb +++ b/ruby/test/socket/test_basicsocket.rb @@ -32,7 +32,7 @@ def test_getsockopt n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) assert_equal([0].pack("i"), n.data) - rescue Minitest::Assertion + rescue Test::Unit::AssertionFailedError s.close if /aix/ =~ RUBY_PLATFORM skip "Known bug in getsockopt(2) on AIX" @@ -159,8 +159,6 @@ def test_read_write_nonblock set_nb = true buf = String.new if ssock.respond_to?(:nonblock?) - assert_not_predicate(ssock, :nonblock?) - assert_not_predicate(csock, :nonblock?) csock.nonblock = ssock.nonblock = false # Linux may use MSG_DONTWAIT to avoid setting O_NONBLOCK diff --git a/ruby/test/socket/test_socket.rb b/ruby/test/socket/test_socket.rb index f1ec927c4..7e596f029 100644 --- a/ruby/test/socket/test_socket.rb +++ b/ruby/test/socket/test_socket.rb @@ -163,11 +163,19 @@ def test_tcp_cloexec def random_port # IANA suggests dynamic port for 49152 to 65535 # http://www.iana.org/assignments/port-numbers - 49152 + rand(65535-49152+1) + case RUBY_PLATFORM + when /mingw|mswin/ + rand(50000..65535) + else + rand(49152..65535) + end end def errors_addrinuse - [Errno::EADDRINUSE] + errs = [Errno::EADDRINUSE] + # MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721" + errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM + errs end def test_tcp_server_sockets @@ -430,6 +438,9 @@ def test_udp_server rescue NotImplementedError, Errno::ENOSYS skipped = true skip "need sendmsg and recvmsg: #{$!}" + rescue RuntimeError + skipped = true + skip "UDP server is no response: #{$!}" ensure if th if skipped @@ -475,7 +486,7 @@ def timestamp_retry_rw(s1, s2, t1, type) end while IO.select([r], nil, nil, 0.1).nil? n end - timeout = (RubyVM::MJIT.enabled? ? 120 : 30) # for --jit-wait + timeout = (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? ? 120 : 30) # for --jit-wait assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout)) msg, _, _, stamp = s1.recvmsg assert_equal("a", msg) diff --git a/ruby/test/socket/test_tcp.rb b/ruby/test/socket/test_tcp.rb index 11325fded..9aa716f7e 100644 --- a/ruby/test/socket/test_tcp.rb +++ b/ruby/test/socket/test_tcp.rb @@ -55,6 +55,26 @@ def test_initialize_failure t.close if t && !t.closed? end + def test_initialize_resolv_timeout + TCPServer.open("localhost", 0) do |svr| + th = Thread.new { + c = svr.accept + c.close + } + addr = svr.addr + s = TCPSocket.new(addr[3], addr[1], resolv_timeout: 10) + th.join + ensure + s.close() + end + end + + def test_initialize_connect_timeout + assert_raise(Errno::ETIMEDOUT) do + TCPSocket.new("192.0.2.1", 80, connect_timeout: 0) + end + end + def test_recvfrom TCPServer.open("localhost", 0) {|svr| th = Thread.new { @@ -95,4 +115,29 @@ def test_accept_nonblock assert_raise(IO::WaitReadable) { svr.accept_nonblock(exception: true) } } end + + def test_accept_multithread + attempts_count = 5 + server_threads_count = 3 + client_threads_count = 3 + + attempts_count.times do + server_threads = Array.new(server_threads_count) do + Thread.new do + TCPServer.open("localhost", 0) do |server| + accept_threads = Array.new(client_threads_count) do + Thread.new { server.accept.close } + end + client_threads = Array.new(client_threads_count) do + Thread.new { TCPSocket.open(server.addr[3], server.addr[1]) {} } + end + client_threads.each(&:join) + accept_threads.each(&:join) + end + end + end + + server_threads.each(&:join) + end + end end if defined?(TCPSocket) diff --git a/ruby/test/socket/test_unix.rb b/ruby/test/socket/test_unix.rb index 6efb1d60e..8c74d0c93 100644 --- a/ruby/test/socket/test_unix.rb +++ b/ruby/test/socket/test_unix.rb @@ -47,10 +47,16 @@ def test_fd_passing_class_mode r.close s1.send_io(s1) - # klass = UNIXSocket FIXME: [ruby-core:71860] [Bug #11778] + klass = UNIXSocket + r = s2.recv_io(klass) + assert_instance_of klass, r, 'recv_io with proper klass' + assert_not_equal s1.fileno, r.fileno + r.close + + s1.send_io(s1) klass = IO r = s2.recv_io(klass, 'r+') - assert_instance_of klass, r, 'recv_io with proper klass' + assert_instance_of klass, r, 'recv_io with proper klass and mode' assert_not_equal s1.fileno, r.fileno r.close end @@ -542,16 +548,20 @@ def test_getcred_ucred def test_getcred_xucred return if /freebsd|darwin/ !~ RUBY_PLATFORM - Dir.mktmpdir {|d| + Dir.mktmpdir do |d| sockpath = "#{d}/sock" serv = Socket.unix_server_socket(sockpath) - Socket.unix(sockpath) + u = Socket.unix(sockpath) s, = serv.accept cred = s.getsockopt(0, Socket::LOCAL_PEERCRED) inspect = cred.inspect assert_match(/ euid=#{Process.euid} /, inspect) assert_match(/ \(xucred\)/, inspect) - } + ensure + s&.close + u&.close + serv&.close + end end def test_sendcred_ucred diff --git a/ruby/test/stringio/test_ractor.rb b/ruby/test/stringio/test_ractor.rb new file mode 100644 index 000000000..1c334e2c3 --- /dev/null +++ b/ruby/test/stringio/test_ractor.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +require 'test/unit' + +class TestStringIOInRactor < Test::Unit::TestCase + def setup + omit unless defined? Ractor + end + + def test_ractor + assert_in_out_err([], <<-"end;", ["true"], []) + require "stringio" + $VERBOSE = nil + r = Ractor.new do + io = StringIO.new("") + io.puts "abc" + io.truncate(0) + io.puts "def" + "\0\0\0\0def\n" == io.string + end + puts r.take + end; + end +end diff --git a/ruby/test/stringio/test_stringio.rb b/ruby/test/stringio/test_stringio.rb index a99ccf430..e0b4504b5 100644 --- a/ruby/test/stringio/test_stringio.rb +++ b/ruby/test/stringio/test_stringio.rb @@ -187,6 +187,40 @@ def test_write_encoding assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT") end + def test_write_encoding_conversion + convertible = "\u{3042}" + inconvertible = "\u{1f363}" + conversion_encoding = Encoding::Windows_31J + + s = StringIO.new.set_encoding(conversion_encoding) + s.write(convertible) + assert_equal(conversion_encoding, s.string.encoding) + + s = StringIO.new.set_encoding(Encoding::UTF_8) + s.write("foo".force_encoding("ISO-8859-1"), convertible) + assert_equal(Encoding::UTF_8, s.string.encoding) + + s = StringIO.new.set_encoding(Encoding::US_ASCII) + s.write("foo".force_encoding("US-ASCII"), convertible) + assert_equal(Encoding::UTF_8, s.string.encoding) + + all_assertions do |a| + [ + inconvertible, + convertible + inconvertible, + [convertible, inconvertible], + ["a", inconvertible], + ].each do |data| + a.for(data.inspect) do + s = StringIO.new.set_encoding(conversion_encoding) + assert_raise(Encoding::CompatibilityError) do + s.write(*data) + end + end + end + end + end + def test_write_integer_overflow f = StringIO.new f.pos = RbConfig::LIMITS["LONG_MAX"] @@ -412,6 +446,15 @@ def test_each_byte f.close unless f.closed? end + def test_each_byte_closed + f = StringIO.new("1234") + assert_equal("1".ord, f.each_byte {|c| f.close; break c }) + f = StringIO.new("1234") + assert_raise(IOError) do + f.each_byte { f.close } + end + end + def test_getbyte f = StringIO.new("1234") assert_equal("1".ord, f.getbyte) @@ -486,11 +529,39 @@ def test_each_char assert_equal(%w(1 2 3 4), f.each_char.to_a) end + def test_each_char_closed + f = StringIO.new("1234") + assert_equal("1", f.each_char {|c| f.close; break c }) + f = StringIO.new("1234") + assert_raise(IOError) do + f.each_char { f.close } + end + end + def test_each_codepoint f = StringIO.new("1234") assert_equal([49, 50, 51, 52], f.each_codepoint.to_a) end + def test_each_codepoint_closed + f = StringIO.new("1234") + assert_equal("1".ord, f.each_codepoint {|c| f.close; break c }) + f = StringIO.new("1234") + assert_raise(IOError) do + f.each_codepoint { f.close } + end + end + + def test_each_codepoint_enumerator + io = StringIO.new('你好поÑтроить') + + chinese_part = io.each_codepoint.take(2).pack('U*') + russian_part = io.read(40).force_encoding('UTF-8') + + assert_equal("你好", chinese_part) + assert_equal("поÑтроить", russian_part) + end + def test_gets2 f = StringIO.new("foo\nbar\nbaz\n") assert_equal("fo", f.gets(2)) @@ -754,7 +825,7 @@ def test_new_block_warning end def test_overflow - skip if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"] + omit if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"] limit = RbConfig::LIMITS["INTPTR_MAX"] - 0x10 assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}") begin; @@ -764,7 +835,7 @@ def test_overflow x = "a"*0x100000 break if [x].pack("p").unpack("i!")[0] < 0 ary << x - skip if ary.size > 100 + omit if ary.size > 100 end s = StringIO.new(x) s.gets("xxx", limit) diff --git a/ruby/test/strscan/test_ractor.rb b/ruby/test/strscan/test_ractor.rb new file mode 100644 index 000000000..480c1ae8a --- /dev/null +++ b/ruby/test/strscan/test_ractor.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true +require 'test/unit' + +class TestStringScannerRactor < Test::Unit::TestCase + def setup + pend unless defined? Ractor + end + + def test_ractor + assert_in_out_err([], <<-"end;", ["stra", " ", "strb", " ", "strc"], []) + require "strscan" + $VERBOSE = nil + r = Ractor.new do + s = StringScanner.new("stra strb strc", true) + [ + s.scan(/\\w+/), + s.scan(/\\s+/), + s.scan(/\\w+/), + s.scan(/\\s+/), + s.scan(/\\w+/), + s.scan(/\\w+/), + s.scan(/\\w+/) + ] + end + puts r.take.compact + end; + end +end diff --git a/ruby/test/strscan/test_stringscanner.rb b/ruby/test/strscan/test_stringscanner.rb index 4b001b317..6e30be1f7 100644 --- a/ruby/test/strscan/test_stringscanner.rb +++ b/ruby/test/strscan/test_stringscanner.rb @@ -206,6 +206,23 @@ def test_pos_unicode assert_equal 11, s.charpos end + def test_charpos_not_use_string_methods + string = +'abcädeföghi' + scanner = create_string_scanner(string) + + class << string + EnvUtil.suppress_warning do + undef_method(*instance_methods) + end + end + + assert_equal 0, scanner.charpos + assert_equal "abcä", scanner.scan_until(/ä/) + assert_equal 4, scanner.charpos + assert_equal "defö", scanner.scan_until(/ö/) + assert_equal 8, scanner.charpos + end + def test_concat s = create_string_scanner('a'.dup) s.scan(/a/) diff --git a/ruby/test/test_delegate.rb b/ruby/test/test_delegate.rb index 426a64780..57480b18e 100644 --- a/ruby/test/test_delegate.rb +++ b/ruby/test/test_delegate.rb @@ -50,6 +50,21 @@ def test_simpledelegator_class assert_equal(SimpleDelegator,simple.clone.class) end + def test_simpledelegator_clone + simple=SimpleDelegator.new([]) + simple.freeze + + clone = simple.clone + assert_predicate clone, :frozen? + assert_predicate clone.__getobj__, :frozen? + assert_equal true, Kernel.instance_method(:frozen?).bind(clone).call + + clone = simple.clone(freeze: false) + assert_not_predicate clone, :frozen? + assert_not_predicate clone.__getobj__, :frozen? + assert_equal false, Kernel.instance_method(:frozen?).bind(clone).call + end + class Object def m :o @@ -91,6 +106,10 @@ def parent_public; end protected def parent_protected; end + + private + + def parent_private; end end class Child < DelegateClass(Parent) @@ -102,6 +121,10 @@ def parent_public_added; end protected def parent_protected_added; end + + private + + def parent_private_added; end end def test_public_instance_methods @@ -116,6 +139,32 @@ def test_protected_instance_methods assert_equal([:parent_protected, :parent_protected_added], (Child.new(Parent.new).protected_methods - ignores).sort) end + def test_instance_methods + ignores = Object.instance_methods | Delegator.instance_methods + assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.instance_methods - ignores).sort) + assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.new(Parent.new).methods - ignores).sort) + end + + def test_DelegateClass_instance_method + assert_instance_of UnboundMethod, Child.instance_method(:parent_public) + assert_instance_of UnboundMethod, Child.instance_method(:parent_public_added) + assert_instance_of UnboundMethod, Child.instance_method(:parent_protected) + assert_instance_of UnboundMethod, Child.instance_method(:parent_protected_added) + assert_raise(NameError) { Child.instance_method(:parent_private) } + assert_raise(NameError) { Child.instance_method(:parent_private_added) } + assert_instance_of UnboundMethod, Child.instance_method(:to_s) + end + + def test_DelegateClass_public_instance_method + assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public) + assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public_added) + assert_raise(NameError) { Child.public_instance_method(:parent_protected) } + assert_raise(NameError) { Child.public_instance_method(:parent_protected_added) } + assert_raise(NameError) { Child.instance_method(:parent_private) } + assert_raise(NameError) { Child.instance_method(:parent_private_added) } + assert_instance_of UnboundMethod, Child.public_instance_method(:to_s) + end + class IV < DelegateClass(Integer) attr_accessor :var @@ -190,9 +239,7 @@ def foo.foo(*args, **kw) assert_equal([], d.bar) assert_equal([[], {:a=>1}], d.foo(:a=>1)) assert_equal([{:a=>1}], d.bar(:a=>1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `foo'/m) do - assert_equal([[], {:a=>1}], d.foo({:a=>1})) - end + assert_equal([[{:a=>1}], {}], d.foo({:a=>1})) assert_equal([{:a=>1}], d.bar({:a=>1})) end diff --git a/ruby/test/test_extlibs.rb b/ruby/test/test_extlibs.rb index 7dc22ee8a..958c9ff73 100644 --- a/ruby/test/test_extlibs.rb +++ b/ruby/test/test_extlibs.rb @@ -71,13 +71,11 @@ def windows? check_existence "rbconfig/sizeof" #check_existence "readline" # depend on libreadline check_existence "ripper" - check_existence "sdbm" check_existence "socket" check_existence "stringio" check_existence "strscan" check_existence "syslog" check_existence "thread" - check_existence "Win32API" check_existence "win32ole" check_existence "zlib", "this may be false positive, but should assert because rubygems requires this" end diff --git a/ruby/test/test_getoptlong.rb b/ruby/test/test_getoptlong.rb new file mode 100644 index 000000000..0cd370b6c --- /dev/null +++ b/ruby/test/test_getoptlong.rb @@ -0,0 +1,163 @@ +require 'test/unit' +require 'getoptlong' + +class TestGetoptLong < Test::Unit::TestCase + + def verify(test_argv, expected_remaining_argv, expected_options) + # Save ARGV and replace it with a test ARGV. + argv_saved = ARGV.dup + ARGV.replace(test_argv) + # Define options. + opts = GetoptLong.new( + ['--xxx', '-x', '--aaa', '-a', GetoptLong::REQUIRED_ARGUMENT], + ['--yyy', '-y', '--bbb', '-b', GetoptLong::OPTIONAL_ARGUMENT], + ['--zzz', '-z', '--ccc', '-c', GetoptLong::NO_ARGUMENT] + ) + opts.quiet = true + # Gather options. + actual_options = [] + opts.each do |opt, arg| + actual_options << "#{opt}: #{arg}" + end + # Save remaining test ARGV and restore original ARGV. + actual_remaining_argv = ARGV.dup + ARGV.replace(argv_saved) + # Assert. + assert_equal(expected_remaining_argv, actual_remaining_argv, 'ARGV') + assert_equal(expected_options, actual_options, 'Options') + end + + def test_no_options + expected_options = [] + expected_argv = %w[foo bar] + argv = %w[foo bar] + verify(argv, expected_argv, expected_options) + end + + def test_required_argument + expected_options = [ + '--xxx: arg' + ] + expected_argv = %w[foo bar] + options = %w[--xxx --xx --x -x --aaa --aa --a -a] + options.each do |option| + argv = ['foo', option, 'arg', 'bar'] + verify(argv, expected_argv, expected_options) + end + end + + def test_required_argument_missing + options = %w[--xxx --xx --x -x --aaa --aa --a -a] + options.each do |option| + argv = [option] + e = assert_raise(GetoptLong::MissingArgument) do + verify(argv, [], []) + end + assert_match('requires an argument', e.message) + end + end + + def test_optional_argument + expected_options = [ + '--yyy: arg' + ] + expected_argv = %w[foo bar] + options = %w[--yyy --y --y -y --bbb --bb --b -b] + options.each do |option| + argv = ['foo', 'bar', option, 'arg'] + verify(argv, expected_argv, expected_options) + end + end + + def test_optional_argument_missing + expected_options = [ + '--yyy: ' + ] + expected_argv = %w[foo bar] + options = %w[--yyy --y --y -y --bbb --bb --b -b] + options.each do |option| + argv = ['foo', 'bar', option] + verify(argv, expected_argv, expected_options) + end + end + + def test_no_argument + expected_options = [ + '--zzz: ' + ] + expected_argv = %w[foo bar] + options = %w[--zzz --zz --z -z --ccc --cc --c -c] + options.each do |option| + argv = ['foo', option, 'bar'] + verify(argv, expected_argv, expected_options) + end + end + + def test_new_with_empty_array + e = assert_raise(ArgumentError) do + GetoptLong.new([]) + end + assert_match(/no argument-flag/, e.message) + end + + def test_new_with_bad_array + e = assert_raise(ArgumentError) do + GetoptLong.new('foo') + end + assert_match(/option list contains non-Array argument/, e.message) + end + + def test_new_with_empty_subarray + e = assert_raise(ArgumentError) do + GetoptLong.new([[]]) + end + assert_match(/no argument-flag/, e.message) + end + + def test_new_with_bad_subarray + e = assert_raise(ArgumentError) do + GetoptLong.new([1]) + end + assert_match(/no option name/, e.message) + end + + def test_new_with_invalid_option + invalid_options = %w[verbose -verbose -- +] + invalid_options.each do |invalid_option| + e = assert_raise(ArgumentError, invalid_option.to_s) do + arguments = [ + [invalid_option, '-v', GetoptLong::NO_ARGUMENT] + ] + GetoptLong.new(*arguments) + end + assert_match(/invalid option/, e.message) + end + end + + def test_new_with_invalid_alias + invalid_aliases = %w[v - -- +] + invalid_aliases.each do |invalid_alias| + e = assert_raise(ArgumentError, invalid_alias.to_s) do + arguments = [ + ['--verbose', invalid_alias, GetoptLong::NO_ARGUMENT] + ] + GetoptLong.new(*arguments) + end + assert_match(/invalid option/, e.message) + end + end + + def test_new_with_invalid_flag + invalid_flags = ['foo'] + invalid_flags.each do |invalid_flag| + e = assert_raise(ArgumentError, invalid_flag.to_s) do + arguments = [ + ['--verbose', '-v', invalid_flag] + ] + GetoptLong.new(*arguments) + end + assert_match(/no argument-flag/, e.message) + end + end + +end diff --git a/ruby/test/test_ipaddr.rb b/ruby/test/test_ipaddr.rb index 7b3a199bf..c07ee2a8e 100644 --- a/ruby/test/test_ipaddr.rb +++ b/ruby/test/test_ipaddr.rb @@ -43,6 +43,17 @@ def test_s_new assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string) assert_equal(Socket::AF_INET6, a.family) assert_equal(48, a.prefix) + assert_nil(a.zone_id) + + a = IPAddr.new("fe80::1%ab0") + assert_equal("fe80::1%ab0", a.to_s) + assert_equal("fe80:0000:0000:0000:0000:0000:0000:0001%ab0", a.to_string) + assert_equal(Socket::AF_INET6, a.family) + assert_equal(false, a.ipv4?) + assert_equal(true, a.ipv6?) + assert_equal("#", a.inspect) + assert_equal(128, a.prefix) + assert_equal('%ab0', a.zone_id) a = IPAddr.new("0.0.0.0") assert_equal("0.0.0.0", a.to_s) @@ -87,10 +98,14 @@ def test_s_new assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.256") } assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.011") } - assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%fxp0") } + assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%") } + assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%]") } assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[192.168.1.2]/120") } assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[2001:200:300::]\nINVALID") } assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.1/32\nINVALID") } + assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.1/32/20") } + assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("192.168.0.1/032") } + assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/0128") } assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/255.255.255.0") } assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/129") } assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("192.168.0.1/33") } @@ -116,6 +131,23 @@ def test_s_new_ntoh assert_equal("192.168.2.1", IPAddr.new_ntoh(a.hton).to_s) end + def test_ntop + # IPv4 + assert_equal("192.168.1.1", IPAddr.ntop("\xC0\xA8\x01\x01")) + # IPv6 + assert_equal("0000:0000:0000:0000:0000:0000:0000:0001", + IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) + + # Invalid parameters + assert_raise(IPAddr::AddressFamilyError) { + IPAddr.ntop("192.168.1.1") + } + + assert_raise(IPAddr::AddressFamilyError) { + IPAddr.ntop("\xC0\xA8\x01\xFF1") + } + end + def test_ipv4_compat a = IPAddr.new("::192.168.1.2") assert_equal("::192.168.1.2", a.to_s) @@ -200,6 +232,51 @@ def test_to_s assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0001", IPAddr.new("3ffe:505:2::1").to_string) assert_equal("3ffe:505:2::1", IPAddr.new("3ffe:505:2::1").to_s) end + + def test_netmask + a = IPAddr.new("192.168.1.2/8") + assert_equal(a.netmask, "255.0.0.0") + + a = IPAddr.new("192.168.1.2/16") + assert_equal(a.netmask, "255.255.0.0") + + a = IPAddr.new("192.168.1.2/24") + assert_equal(a.netmask, "255.255.255.0") + end + + def test_zone_id + a = IPAddr.new("192.168.1.2") + assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%ab0' } + assert_raise(IPAddr::InvalidAddressError) { a.zone_id } + + a = IPAddr.new("1:2:3:4:5:6:7:8") + a.zone_id = '%ab0' + assert_equal('%ab0', a.zone_id) + assert_equal("1:2:3:4:5:6:7:8%ab0", a.to_s) + assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%' } + end + + def test_to_range + a1 = IPAddr.new("127.0.0.1") + range = a1..a1 + assert_equal(range, a1.to_range) + assert_equal(range, a1.freeze.to_range) + + a2 = IPAddr.new("192.168.0.1/16") + range = IPAddr.new("192.168.0.0")..IPAddr.new("192.168.255.255") + assert_equal(range, a2.to_range) + assert_equal(range, a2.freeze.to_range) + + a3 = IPAddr.new("3ffe:505:2::1") + range = a3..a3 + assert_equal(range, a3.to_range) + assert_equal(range, a3.freeze.to_range) + + a4 = IPAddr.new("::ffff/127") + range = IPAddr.new("::fffe")..IPAddr.new("::ffff") + assert_equal(range, a4.to_range) + assert_equal(range, a4.freeze.to_range) + end end class TC_Operator < Test::Unit::TestCase @@ -295,6 +372,8 @@ def test_include? assert_equal(true, net1.include?(IPAddr.new("192.168.2.0"))) assert_equal(true, net1.include?(IPAddr.new("192.168.2.255"))) assert_equal(false, net1.include?(IPAddr.new("192.168.3.0"))) + assert_equal(true, net1.include?(IPAddr.new("192.168.2.0/28"))) + assert_equal(false, net1.include?(IPAddr.new("192.168.2.0/16"))) # test with integer parameter int = (192 << 24) + (168 << 16) + (2 << 8) + 13 @@ -303,6 +382,11 @@ def test_include? end + def test_native_coerce_mask_addr + assert_equal(IPAddr.new("0.0.0.2/255.255.255.255"), IPAddr.new("::2").native) + assert_equal(IPAddr.new("0.0.0.2/255.255.255.255").to_range, IPAddr.new("::2").native.to_range) + end + def test_loopback? assert_equal(true, IPAddr.new('127.0.0.1').loopback?) assert_equal(true, IPAddr.new('127.127.1.1').loopback?) diff --git a/ruby/test/test_mutex_m.rb b/ruby/test/test_mutex_m.rb index 30971dd35..e5cfbc8b5 100644 --- a/ruby/test/test_mutex_m.rb +++ b/ruby/test/test_mutex_m.rb @@ -23,4 +23,36 @@ def test_cv_wait c.signal assert_equal "abc", t.value end + + class KeywordInitializeParent + def initialize(x:) + end + end + + class KeywordInitializeChild < KeywordInitializeParent + include Mutex_m + def initialize + super(x: 1) + end + end + + def test_initialize_with_keyword_arg + assert KeywordInitializeChild.new + end + + class NoArgInitializeParent + def initialize + end + end + + class NoArgInitializeChild < NoArgInitializeParent + include Mutex_m + def initialize + super() + end + end + + def test_initialize_no_args + assert NoArgInitializeChild.new + end end diff --git a/ruby/test/test_open3.rb b/ruby/test/test_open3.rb index 24bd08e59..36ccd4c9e 100644 --- a/ruby/test/test_open3.rb +++ b/ruby/test/test_open3.rb @@ -2,7 +2,10 @@ require 'test/unit' require 'open3' -require_relative 'lib/jit_support' + +if RUBY_ENGINE == 'ruby' + require_relative 'lib/jit_support' +end class TestOpen3 < Test::Unit::TestCase RUBY = EnvUtil.rubybin @@ -92,7 +95,7 @@ def test_numeric_file_descriptor2 end def test_numeric_file_descriptor3 - skip "passing FDs bigger than 2 is not supported on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM + skip "passing FDs bigger than 2 is not supported on Windows" if /mswin|mingw/ =~ RbConfig::CONFIG['host_os'] with_pipe {|r, w| Open3.popen3(RUBY, '-e', 'IO.open(3).puts "foo"', 3 => w) {|i,o,e,t| assert_equal("foo\n", r.gets, "[GH-808] [ruby-core:67347] [Bug #10699]") @@ -127,7 +130,11 @@ def test_popen2 i.close STDERR.reopen(old) assert_equal("zo", o.read) - assert_equal("ze", JITSupport.remove_mjit_logs(r.read)) + if defined?(JITSupport) + assert_equal("ze", JITSupport.remove_mjit_logs(r.read)) + else + assert_equal("ze", r.read) + end } } } @@ -149,6 +156,17 @@ def test_popen2e } end + def test_popen2e_noblock + i, o, t = Open3.popen2e(RUBY, '-e', 'STDOUT.print STDIN.read') + i.print "baz" + i.close + assert_equal("baz", o.read) + ensure + i.close + o.close + t.join + end + def test_capture3 o, e, s = Open3.capture3(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>"i") assert_equal("io", o) diff --git a/ruby/test/test_pp.rb b/ruby/test/test_pp.rb index cd16af639..9cef555d7 100644 --- a/ruby/test/test_pp.rb +++ b/ruby/test/test_pp.rb @@ -3,6 +3,16 @@ require 'pp' require 'delegate' require 'test/unit' +require 'ruby2_keywords' + +# Define bind_call for Ruby 2.6 and earlier, to allow testing on JRuby 9.3 +class UnboundMethod + unless public_method_defined?(:bind_call) + def bind_call(obj, *args, &block) + bind(obj).call(*args, &block) + end + end +end module PPTestModule @@ -158,7 +168,7 @@ def test_withinspect a << HasInspect.new(a) assert_equal("[]\n", PP.pp(a, ''.dup)) assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) - end + end unless RUBY_VERSION < "2.7" # temporary mask to test on JRuby 9.3 (2.6 equivalent) def test_share_nil begin @@ -178,7 +188,7 @@ def test_hash end def test_hash_in_array - assert_equal("[{}]", PP.singleline_pp([->(*a){a.last}.ruby2_keywords.call(**{})], ''.dup)) + assert_equal("[{}]", PP.singleline_pp([->(*a){a.last.clear}.ruby2_keywords.call(a: 1)], ''.dup)) assert_equal("[{}]", PP.singleline_pp([Hash.ruby2_keywords_hash({})], ''.dup)) end end @@ -211,12 +221,14 @@ def test_nothing_raised end end -class PPAbstractSyntaxTree < Test::Unit::TestCase - AST = RubyVM::AbstractSyntaxTree - def test_lasgn_literal - ast = AST.parse("_=1") - expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))" - assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast) +if defined?(RubyVM) + class PPAbstractSyntaxTree < Test::Unit::TestCase + AST = RubyVM::AbstractSyntaxTree + def test_lasgn_literal + ast = AST.parse("_=1") + expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))" + assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast) + end end end diff --git a/ruby/test/test_prime.rb b/ruby/test/test_prime.rb deleted file mode 100644 index 9db13f08f..000000000 --- a/ruby/test/test_prime.rb +++ /dev/null @@ -1,280 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'prime' -require 'timeout' - -class TestPrime < Test::Unit::TestCase - # The first 100 prime numbers - PRIMES = [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, - 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127, 131, - 137, 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, - 281, 283, 293, 307, 311, 313, 317, 331, 337, - 347, 349, 353, 359, 367, 373, 379, 383, 389, - 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, - 503, 509, 521, 523, 541, - ] - def test_each - primes = [] - Prime.each do |p| - break if p > 541 - primes << p - end - assert_equal PRIMES, primes - end - - def test_integer_each_prime - primes = [] - Integer.each_prime(1000) do |p| - break if p > 541 - primes << p - end - assert_equal PRIMES, primes - end - - def test_each_by_prime_number_theorem - 3.upto(15) do |i| - max = 2**i - primes = [] - Prime.each do |p| - break if p >= max - primes << p - end - - # Prime number theorem - assert_operator primes.length, :>=, max/Math.log(max) - delta = 0.05 - li = (2..max).step(delta).inject(0){|sum,x| sum + delta/Math.log(x)} - assert_operator primes.length, :<=, li - end - end - - def test_each_without_block - enum = Prime.each - assert_respond_to(enum, :each) - assert_kind_of(Enumerable, enum) - assert_respond_to(enum, :with_index) - assert_respond_to(enum, :next) - assert_respond_to(enum, :succ) - assert_respond_to(enum, :rewind) - end - - def test_instance_without_block - enum = Prime.instance.each - assert_respond_to(enum, :each) - assert_kind_of(Enumerable, enum) - assert_respond_to(enum, :with_index) - assert_respond_to(enum, :next) - assert_respond_to(enum, :succ) - assert_respond_to(enum, :rewind) - end - - def test_new - assert_raise(NoMethodError) { Prime.new } - end - - def test_enumerator_succ - enum = Prime.each - assert_equal PRIMES[0, 50], 50.times.map{ enum.succ } - assert_equal PRIMES[50, 50], 50.times.map{ enum.succ } - enum.rewind - assert_equal PRIMES[0, 100], 100.times.map{ enum.succ } - end - - def test_enumerator_with_index - enum = Prime.each - last = -1 - enum.with_index do |p,i| - break if i >= 100 - assert_equal last+1, i - assert_equal PRIMES[i], p - last = i - end - end - - def test_enumerator_with_index_with_offset - enum = Prime.each - last = 5-1 - enum.with_index(5).each do |p,i| - break if i >= 100+5 - assert_equal last+1, i - assert_equal PRIMES[i-5], p - last = i - end - end - - def test_enumerator_with_object - object = Object.new - enum = Prime.each - enum.with_object(object).each do |p, o| - assert_equal object, o - break - end - end - - def test_enumerator_size - enum = Prime.each - assert_equal Float::INFINITY, enum.size - assert_equal Float::INFINITY, enum.with_object(nil).size - assert_equal Float::INFINITY, enum.with_index(42).size - end - - def test_default_instance_does_not_have_compatibility_methods - assert_not_respond_to(Prime.instance, :succ) - assert_not_respond_to(Prime.instance, :next) - end - - def test_prime_each_basic_argument_checking - assert_raise(ArgumentError) { Prime.prime?(1,2) } - assert_raise(ArgumentError) { Prime.prime?(1.2) } - end - - def test_prime? - assert_equal Prime.prime?(1), false - assert_equal Prime.prime?(2), true - assert_equal Prime.prime?(4), false - end - - class TestPseudoPrimeGenerator < Test::Unit::TestCase - def test_upper_bound - pseudo_prime_generator = Prime::PseudoPrimeGenerator.new(42) - assert_equal pseudo_prime_generator.upper_bound, 42 - end - - def test_succ - pseudo_prime_generator = Prime::PseudoPrimeGenerator.new(42) - assert_raise(NotImplementedError) { pseudo_prime_generator.succ } - end - - def test_next - pseudo_prime_generator = Prime::PseudoPrimeGenerator.new(42) - assert_raise(NotImplementedError) { pseudo_prime_generator.next } - end - - def test_rewind - pseudo_prime_generator = Prime::PseudoPrimeGenerator.new(42) - assert_raise(NotImplementedError) { pseudo_prime_generator.rewind } - end - end - - class TestTrialDivisionGenerator < Test::Unit::TestCase - # The first 100 prime numbers - PRIMES = [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, - 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127, 131, - 137, 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, - 281, 283, 293, 307, 311, 313, 317, 331, 337, - 347, 349, 353, 359, 367, 373, 379, 383, 389, - 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, - 503, 509, 521, 523, 541, - ] - - def test_each - primes = [] - Prime.each(nil, Prime::TrialDivisionGenerator.new) do |p| - break if p > 541 - primes << p - end - assert_equal PRIMES, primes - end - - def test_rewind - generator = Prime::TrialDivisionGenerator.new - assert_equal generator.next, 2 - assert_equal generator.next, 3 - generator.rewind - assert_equal generator.next, 2 - end - end - - class TestGenerator23 < Test::Unit::TestCase - def test_rewind - generator = Prime::Generator23.new - assert_equal generator.next, 2 - assert_equal generator.next, 3 - generator.rewind - assert_equal generator.next, 2 - end - end - - class TestInteger < Test::Unit::TestCase - def test_prime_division - pd = PRIMES.inject(&:*).prime_division - assert_equal PRIMES.map{|p| [p, 1]}, pd - - pd = (-PRIMES.inject(&:*)).prime_division - assert_equal [-1, *PRIMES].map{|p| [p, 1]}, pd - end - - def test_from_prime_division - assert_equal PRIMES.inject(&:*), Integer.from_prime_division(PRIMES.map{|p| [p,1]}) - - assert_equal(-PRIMES.inject(&:*), Integer.from_prime_division([[-1, 1]] + PRIMES.map{|p| [p,1]})) - end - - def test_prime? - PRIMES.each do |p| - assert_predicate(p, :prime?) - end - - composites = (0..PRIMES.last).to_a - PRIMES - composites.each do |c| - assert_not_predicate(c, :prime?) - end - - # mersenne numbers - assert_predicate((2**31-1), :prime?) - assert_not_predicate((2**32-1), :prime?) - - # fermat numbers - assert_predicate((2**(2**4)+1), :prime?) - assert_not_predicate((2**(2**5)+1), :prime?) # Euler! - - # large composite - assert_not_predicate(((2**13-1) * (2**17-1)), :prime?) - - # factorial - assert_not_predicate((2...100).inject(&:*), :prime?) - - # negative - assert_not_predicate(-1, :prime?) - assert_not_predicate(-2, :prime?) - assert_not_predicate(-3, :prime?) - assert_not_predicate(-4, :prime?) - end - end - - def test_eratosthenes_works_fine_after_timeout - sieve = Prime::EratosthenesSieve.instance - sieve.send(:initialize) - # simulates that Timeout.timeout interrupts Prime::EratosthenesSieve#compute_primes - class << Integer - alias_method :org_sqrt, :sqrt - end - begin - def Integer.sqrt(n) - sleep 10 if /compute_primes/ =~ caller.first - org_sqrt(n) - end - assert_raise(Timeout::Error) do - Timeout.timeout(0.5) { Prime.each(7*37){} } - end - ensure - class << Integer - remove_method :sqrt - alias_method :sqrt, :org_sqrt - remove_method :org_sqrt - end - end - - assert_not_include Prime.each(7*37).to_a, 7*37, "[ruby-dev:39465]" - end -end diff --git a/ruby/test/test_pstore.rb b/ruby/test/test_pstore.rb index 52b74f377..fe5f8711a 100644 --- a/ruby/test/test_pstore.rb +++ b/ruby/test/test_pstore.rb @@ -75,7 +75,7 @@ def test_writing_inside_readonly_transaction_raises_error end def test_thread_safe - q1 = Queue.new + q1 = Thread::Queue.new assert_raise(PStore::Error) do th = Thread.new do @pstore.transaction do @@ -92,7 +92,7 @@ def test_thread_safe th.join end end - q2 = Queue.new + q2 = Thread::Queue.new begin pstore = PStore.new(second_file, true) cur = Thread.current diff --git a/ruby/test/test_securerandom.rb b/ruby/test/test_securerandom.rb index 7c8640fce..e4a0e1736 100644 --- a/ruby/test/test_securerandom.rb +++ b/ruby/test/test_securerandom.rb @@ -1,22 +1,17 @@ # frozen_string_literal: false require 'test/unit' require 'securerandom' -require 'tempfile' +require_relative 'ruby/test_random_formatter' # This testcase does NOT aim to test cryptographically strongness and randomness. class TestSecureRandom < Test::Unit::TestCase + include Random::Formatter::FormatterTest + include Random::Formatter::NotDefaultTest + def setup @it = SecureRandom end - def test_s_random_bytes - assert_equal(16, @it.random_bytes.size) - assert_equal(Encoding::ASCII_8BIT, @it.random_bytes.encoding) - 65.times do |idx| - assert_equal(idx, @it.random_bytes(idx).size) - end - end - # This test took 2 minutes on my machine. # And 65536 times loop could not be enough for forcing PID recycle. if false @@ -70,114 +65,6 @@ def check_forking_random_bytes(target_pid, target) end end - def test_s_hex - s = @it.hex - assert_equal(16 * 2, s.size) - assert_match(/\A\h+\z/, s) - 33.times do |idx| - s = @it.hex(idx) - assert_equal(idx * 2, s.size) - assert_match(/\A\h*\z/, s) - end - end - - def test_hex_encoding - assert_equal(Encoding::US_ASCII, @it.hex.encoding) - end - - def test_s_base64 - assert_equal(16, @it.base64.unpack('m*')[0].size) - 17.times do |idx| - assert_equal(idx, @it.base64(idx).unpack('m*')[0].size) - end - end - - def test_s_urlsafe_base64 - safe = /[\n+\/]/ - 65.times do |idx| - assert_not_match(safe, @it.urlsafe_base64(idx)) - end - # base64 can include unsafe byte - assert((0..10000).any? {|idx| safe =~ @it.base64(idx)}, "None of base64(0..10000) is url-safe") - end - - def test_s_random_number_float - 101.times do - v = @it.random_number - assert_in_range(0.0...1.0, v) - end - end - - def test_s_random_number_float_by_zero - 101.times do - v = @it.random_number(0) - assert_in_range(0.0...1.0, v) - end - end - - def test_s_random_number_int - 101.times do |idx| - next if idx.zero? - v = @it.random_number(idx) - assert_in_range(0...idx, v) - end - end - - def test_s_random_number_not_default - msg = "SecureRandom#random_number should not be affected by srand" - seed = srand(0) - x = @it.random_number(1000) - 10.times do|i| - srand(0) - return unless @it.random_number(1000) == x - end - srand(0) - assert_not_equal(x, @it.random_number(1000), msg) - ensure - srand(seed) if seed - end - - def test_uuid - uuid = @it.uuid - assert_equal(36, uuid.size) - - # Check time_hi_and_version and clock_seq_hi_res bits (RFC 4122 4.4) - assert_equal('4', uuid[14]) - assert_include(%w'8 9 a b', uuid[19]) - - assert_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/, uuid) - end - - def test_alphanumeric - 65.times do |n| - an = @it.alphanumeric(n) - assert_match(/\A[0-9a-zA-Z]*\z/, an) - assert_equal(n, an.length) - end - end - - def protect - begin - yield - rescue NotImplementedError - # ignore - end - end - - def remove_feature(basename) - $LOADED_FEATURES.delete_if { |path| - if File.basename(path) == basename - $LOAD_PATH.any? { |dir| - File.exist?(File.join(dir, basename)) - } - end - } - end - - def assert_in_range(range, result, mesg = nil) - assert(range.cover?(result), message(mesg) {"Expected #{result} to be in #{range}"}) - end - def test_with_openssl begin require 'openssl' diff --git a/ruby/test/test_set.rb b/ruby/test/test_set.rb index b0f669ce8..b92930a44 100644 --- a/ruby/test/test_set.rb +++ b/ruby/test/test_set.rb @@ -332,17 +332,39 @@ def test_proper_subset? } end + def test_spacecraft_operator + set = Set[1,2,3] + + assert_nil(set <=> 2) + + assert_nil(set <=> set.to_a) + + [Set, Set2].each { |klass| + assert_equal(-1, set <=> klass[1,2,3,4], klass.name) + assert_equal( 0, set <=> klass[3,2,1] , klass.name) + assert_equal(nil, set <=> klass[1,2,4] , klass.name) + assert_equal(+1, set <=> klass[2,3] , klass.name) + assert_equal(+1, set <=> klass[] , klass.name) + + assert_equal(0, Set[] <=> klass[], klass.name) + } + end + def assert_intersect(expected, set, other) case expected when true assert_send([set, :intersect?, other]) + assert_send([set, :intersect?, other.to_a]) assert_send([other, :intersect?, set]) assert_not_send([set, :disjoint?, other]) + assert_not_send([set, :disjoint?, other.to_a]) assert_not_send([other, :disjoint?, set]) when false assert_not_send([set, :intersect?, other]) + assert_not_send([set, :intersect?, other.to_a]) assert_not_send([other, :intersect?, set]) assert_send([set, :disjoint?, other]) + assert_send([set, :disjoint?, other.to_a]) assert_send([other, :disjoint?, set]) when Class assert_raise(expected) { @@ -360,7 +382,7 @@ def test_intersect? set = Set[3,4,5] assert_intersect(ArgumentError, set, 3) - assert_intersect(ArgumentError, set, [2,4,6]) + assert_intersect(true, set, Set[2,4,6]) assert_intersect(true, set, set) assert_intersect(true, set, Set[2,4]) @@ -619,11 +641,10 @@ def test_eq assert_not_equal(Set[1], [1]) set1 = Class.new(Set)["a", "b"] - set2 = Set["a", "b", set1] - set1 = set1.add(set1.clone) + set1.add(set1).reset # Make recursive + set2 = Set["a", "b", Set["a", "b", set1]] - assert_equal(set2, set2.clone) - assert_equal(set1.clone, set1) + assert_equal(set1, set2) assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]") end @@ -730,6 +751,22 @@ def test_freeze_clone } end + def test_freeze_clone_false + set1 = Set[1,2,3] + set1.freeze + set2 = set1.clone(freeze: false) + + assert_not_predicate set2, :frozen? + set2.add 5 + assert_equal Set[1,2,3,5], set2 + assert_equal Set[1,2,3], set1 + end if Kernel.instance_method(:initialize_clone).arity != 1 + + def test_join + assert_equal('123', Set[1, 2, 3].join) + assert_equal('1 & 2 & 3', Set[1, 2, 3].join(' & ')) + end + def test_inspect set1 = Set[1, 2] assert_equal('#', set1.inspect) @@ -785,113 +822,6 @@ def test_reset end end -class TC_SortedSet < Test::Unit::TestCase - def test_sortedset - s = SortedSet[4,5,3,1,2] - - assert_equal([1,2,3,4,5], s.to_a) - - prev = nil - s.each { |o| assert(prev < o) if prev; prev = o } - assert_not_nil(prev) - - s.map! { |o| -2 * o } - - assert_equal([-10,-8,-6,-4,-2], s.to_a) - - prev = nil - ret = s.each { |o| assert(prev < o) if prev; prev = o } - assert_not_nil(prev) - assert_same(s, ret) - - s = SortedSet.new([2,1,3]) { |o| o * -2 } - assert_equal([-6,-4,-2], s.to_a) - - s = SortedSet.new(['one', 'two', 'three', 'four']) - a = [] - ret = s.delete_if { |o| a << o; o.start_with?('t') } - assert_same(s, ret) - assert_equal(['four', 'one'], s.to_a) - assert_equal(['four', 'one', 'three', 'two'], a) - - s = SortedSet.new(['one', 'two', 'three', 'four']) - a = [] - ret = s.reject! { |o| a << o; o.start_with?('t') } - assert_same(s, ret) - assert_equal(['four', 'one'], s.to_a) - assert_equal(['four', 'one', 'three', 'two'], a) - - s = SortedSet.new(['one', 'two', 'three', 'four']) - a = [] - ret = s.reject! { |o| a << o; false } - assert_same(nil, ret) - assert_equal(['four', 'one', 'three', 'two'], s.to_a) - assert_equal(['four', 'one', 'three', 'two'], a) - end - - def test_each - ary = [1,3,5,7,10,20] - set = SortedSet.new(ary) - - ret = set.each { |o| } - assert_same(set, ret) - - e = set.each - assert_instance_of(Enumerator, e) - - assert_nothing_raised { - set.each { |o| - ary.delete(o) or raise "unexpected element: #{o}" - } - - ary.empty? or raise "forgotten elements: #{ary.join(', ')}" - } - - assert_equal(6, e.size) - set << 42 - assert_equal(7, e.size) - end - - def test_freeze - orig = set = SortedSet[3,2,1] - assert_equal false, set.frozen? - set << 4 - assert_same orig, set.freeze - assert_equal true, set.frozen? - assert_raise(FrozenError) { - set << 5 - } - assert_equal 4, set.size - - # https://bugs.ruby-lang.org/issues/12091 - assert_nothing_raised { - assert_equal [1,2,3,4], set.to_a - } - end - - def test_freeze_dup - set1 = SortedSet[1,2,3] - set1.freeze - set2 = set1.dup - - assert_not_predicate set2, :frozen? - assert_nothing_raised { - set2.add 4 - } - end - - def test_freeze_clone - set1 = SortedSet[1,2,3] - set1.freeze - set2 = set1.clone - - assert_predicate set2, :frozen? - assert_raise(FrozenError) { - set2.add 5 - } - end -end - class TC_Enumerable < Test::Unit::TestCase def test_to_set ary = [2,5,4,3,2,1,3] @@ -906,13 +836,5 @@ def test_to_set assert_same set, set.to_set assert_not_same set, set.to_set { |o| o } - - set = ary.to_set(SortedSet) - assert_instance_of(SortedSet, set) - assert_equal([1,2,3,4,5], set.to_a) - - set = ary.to_set(SortedSet) { |o| o * -2 } - assert_instance_of(SortedSet, set) - assert_equal([-10,-8,-6,-4,-2], set.sort) end end diff --git a/ruby/test/test_sorted_set.rb b/ruby/test/test_sorted_set.rb new file mode 100644 index 000000000..f7ad7af29 --- /dev/null +++ b/ruby/test/test_sorted_set.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: false +require 'test/unit' +require 'set' + +class TC_SortedSet < Test::Unit::TestCase + def base_dir + "#{__dir__}/../lib" + end + + def assert_runs(ruby, options: nil) + options = ['-I', base_dir, *options] + r = system(RbConfig.ruby, *options, '-e', ruby) + assert(r) + end + + def test_error + assert_runs <<~RUBY + require "set" + + r = begin + puts SortedSet.new + rescue Exception => e + e.message + end + raise r unless r.match?(/has been extracted/) + RUBY + end + + def test_ok_with_gem + assert_runs <<~RUBY, options: ['-I', "#{__dir__}/fixtures/fake_sorted_set_gem"] + require "set" + + var = SortedSet.new.to_s + RUBY + end + + def test_ok_require + assert_runs <<~RUBY, options: ['-I', "#{__dir__}/fixtures/fake_sorted_set_gem"] + require "set" + require "sorted_set" + + var = SortedSet.new.to_s + RUBY + end +end diff --git a/ruby/test/test_syslog.rb b/ruby/test/test_syslog.rb index 5327814f7..842ae8df4 100644 --- a/ruby/test/test_syslog.rb +++ b/ruby/test/test_syslog.rb @@ -113,7 +113,7 @@ def test_mask end def syslog_line_regex(ident, message) - /(?:^| )#{Regexp.quote(ident)}(?:\[([1-9][0-9]*)\])?(?: |[: ].* )#{Regexp.quote(message)}$/ + /(?:^| )#{Regexp.quote(ident)}(?:\[([1-9][0-9]*)\])?(?: | ([1-9][0-9]*) - - ||[: ].* )#{Regexp.quote(message)}$/ end def test_log @@ -170,8 +170,9 @@ def test_log end m = re.match(line) assert_not_nil(m) - assert_not_nil(m[1]) - assert_equal(pid, m[1].to_i) + output_pid = m[1] || m[2] + assert_not_nil(output_pid) + assert_equal(pid, output_pid.to_i) } } end diff --git a/ruby/test/test_time.rb b/ruby/test/test_time.rb index ca20788aa..b50d8417c 100644 --- a/ruby/test/test_time.rb +++ b/ruby/test/test_time.rb @@ -62,6 +62,15 @@ def test_rfc2822 assert_equal(true, t.utc?) end + if defined?(Ractor) + def test_rfc2822_ractor + assert_ractor(<<~RUBY, require: 'time') + actual = Ractor.new { Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600") }.take + assert_equal(Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600, actual) + RUBY + end + end + def test_encode_rfc2822 t = Time.utc(1) assert_equal("Mon, 01 Jan 0001 00:00:00 -0000", t.rfc2822) diff --git a/ruby/test/test_timeout.rb b/ruby/test/test_timeout.rb index c57d90c06..74b65f119 100644 --- a/ruby/test/test_timeout.rb +++ b/ruby/test/test_timeout.rb @@ -3,6 +3,17 @@ require 'timeout' class TestTimeout < Test::Unit::TestCase + + def test_non_timing_out_code_is_successful + assert_nothing_raised do + assert_equal :ok, Timeout.timeout(1){ :ok } + end + end + + def test_yield_param + assert_equal [5, :ok], Timeout.timeout(5){|s| [s, :ok] } + end + def test_queue q = Thread::Queue.new assert_raise(Timeout::Error, "[ruby-dev:32935]") { @@ -80,6 +91,14 @@ def test_exit_exception end end + def test_raise_with_message + bug17812 = '[ruby-core:103502] [Bug #17812]: Timeout::Error doesn\'t let two-argument raise() set a new message' + exc = Timeout::Error.new('foo') + assert_raise_with_message(Timeout::Error, 'bar', bug17812) do + raise exc, 'bar' + end + end + def test_enumerator_next bug9380 = '[ruby-dev:47872] [Bug #9380]: timeout in Enumerator#next' e = (o=Object.new).to_enum diff --git a/ruby/test/test_tmpdir.rb b/ruby/test/test_tmpdir.rb index c599dcf51..7ef9f59b5 100644 --- a/ruby/test/test_tmpdir.rb +++ b/ruby/test/test_tmpdir.rb @@ -5,7 +5,7 @@ class TestTmpdir < Test::Unit::TestCase def test_tmpdir_modifiable tmpdir = Dir.tmpdir - assert_equal(false, tmpdir.frozen?) + assert_not_predicate(tmpdir, :frozen?) tmpdir_org = tmpdir.dup tmpdir << "foo" assert_equal(tmpdir_org, Dir.tmpdir) @@ -15,21 +15,34 @@ def test_world_writable skip "no meaning on this platform" if /mswin|mingw/ =~ RUBY_PLATFORM Dir.mktmpdir do |tmpdir| # ToDo: fix for parallel test - olddir, ENV["TMPDIR"] = ENV["TMPDIR"], tmpdir + envs = %w[TMPDIR TMP TEMP] + oldenv = envs.each_with_object({}) {|v, h| h[v] = ENV.delete(v)} begin - assert_equal(tmpdir, Dir.tmpdir) - File.chmod(0777, tmpdir) - assert_not_equal(tmpdir, Dir.tmpdir) - newdir = Dir.mktmpdir("d", tmpdir) do |dir| - assert_file.directory? dir - assert_equal(tmpdir, File.dirname(dir)) - dir + envs.each do |e| + tmpdirx = File.join(tmpdir, e) + ENV[e] = tmpdirx + assert_not_equal(tmpdirx, assert_warn('') {Dir.tmpdir}) + File.write(tmpdirx, "") + assert_not_equal(tmpdirx, assert_warn(/not a directory/) {Dir.tmpdir}) + File.unlink(tmpdirx) + ENV[e] = tmpdir + assert_equal(tmpdir, Dir.tmpdir) + File.chmod(0555, tmpdir) + assert_not_equal(tmpdir, assert_warn(/not writable/) {Dir.tmpdir}) + File.chmod(0777, tmpdir) + assert_not_equal(tmpdir, assert_warn(/world-writable/) {Dir.tmpdir}) + newdir = Dir.mktmpdir("d", tmpdir) do |dir| + assert_file.directory? dir + assert_equal(tmpdir, File.dirname(dir)) + dir + end + assert_file.not_exist?(newdir) + File.chmod(01777, tmpdir) + assert_equal(tmpdir, Dir.tmpdir) + ENV[e] = nil end - assert_file.not_exist?(newdir) - File.chmod(01777, tmpdir) - assert_equal(tmpdir, Dir.tmpdir) ensure - ENV["TMPDIR"] = olddir + ENV.update(oldenv) end end end @@ -52,6 +65,17 @@ def test_mktmpdir_nil } end + def test_mktmpdir_mutate + bug16918 = '[ruby-core:98563]' + assert_nothing_raised(bug16918) do + assert_mktmpdir_traversal do |traversal_path| + Dir.mktmpdir(traversal_path + 'foo') do |actual| + actual << "foo" + end + end + end + end + def test_mktmpdir_traversal assert_mktmpdir_traversal do |traversal_path| Dir.mktmpdir(traversal_path + 'foo') do |actual| @@ -73,8 +97,10 @@ def assert_mktmpdir_traversal target = target.chomp('/') + '/' traversal_path = target.sub(/\A\w:/, '') # for DOSISH traversal_path = Array.new(target.count('/')-2, '..').join('/') + traversal_path - actual = yield traversal_path - assert_not_send([File.absolute_path(actual), :start_with?, target]) + [File::SEPARATOR, File::ALT_SEPARATOR].compact.each do |separator| + actual = yield traversal_path.tr('/', separator) + assert_not_send([File.absolute_path(actual), :start_with?, target]) + end end end end diff --git a/ruby/test/test_tracer.rb b/ruby/test/test_tracer.rb deleted file mode 100644 index 0a098332e..000000000 --- a/ruby/test/test_tracer.rb +++ /dev/null @@ -1,234 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' - -class TestTracer < Test::Unit::TestCase - include EnvUtil - - def test_tracer_with_option_r - assert_in_out_err(%w[-rtracer -e 1]) do |(*lines),| - case lines.size - when 1 - # do nothing - else - assert_match(%r{rubygems/core_ext/kernel_require\.rb:\d+:Kernel:<:}, lines[0]) - end - assert_equal "#0:-e:1::-: 1", lines.last - end - end - - def test_tracer_with_option_r_without_gems - assert_in_out_err(%w[--disable-gems -rtracer -e 1]) do |(*lines),| - assert_equal 1, lines.size, "unexpected output from `ruby --disable-gems -rtracer -e 1`" - assert_equal "#0:-e:1::-: 1", lines.last - end - end - - def test_tracer_with_require - Dir.mktmpdir("test_ruby_tracer") do |dir| - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-EOF -require 'tracer' -1 - EOF - end - assert_in_out_err([script]) do |(*lines),| - assert_empty(lines) - end - end - end - - def test_tracer_with_require_without_gems - Dir.mktmpdir("test_ruby_tracer") do |dir| - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-EOF -require 'tracer' -1 - EOF - end - assert_in_out_err(["--disable-gems", script]) do |(*lines),| - assert_empty(lines) - end - end - end - - def test_tracer_by_add_filter_with_block - Dir.mktmpdir("test_ruby_tracer") do |dir| - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-'EOF' -require 'tracer' - -class Hoge - def Hoge.fuga(i) - "fuga #{i}" - end -end - -Tracer.add_filter {|event, file, line, id, binding, klass| - event =~ /line/ and klass.to_s =~ /hoge/i -} -Tracer.on -for i in 0..3 - puts Hoge.fuga(i) if i % 3 == 0 -end -Tracer.off - EOF - end - assert_in_out_err([script]) do |(*lines), err| - expected = [ - "#0:#{script}:5:Hoge:-: \"fuga \#{i}\"", - "fuga 0", - "#0:#{script}:5:Hoge:-: \"fuga \#{i}\"", - "fuga 3" - ] - assert_equal(expected, lines) - assert_empty(err) - end - end - end - - def test_tracer_by_add_filter_with_proc - Dir.mktmpdir("test_ruby_tracer") do |dir| - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-'EOF' -require 'tracer' - -class Hoge - def Hoge.fuga(i) - "fuga #{i}" - end -end - -a_proc_to_add_filter = proc {|event, file, line, id, binding, klass| - event =~ /line/ and klass.to_s =~ /hoge/i -} -Tracer.add_filter(a_proc_to_add_filter) -Tracer.on -for i in 0..3 - puts Hoge.fuga(i) if i % 3 == 0 -end -Tracer.off - EOF - end - assert_in_out_err([script]) do |(*lines), err| - expected = [ - "#0:#{script}:5:Hoge:-: \"fuga \#{i}\"", - "fuga 0", - "#0:#{script}:5:Hoge:-: \"fuga \#{i}\"", - "fuga 3" - ] - assert_equal(expected, lines) - assert_empty(err) - end - end - end - - def test_tracer_by_set_get_line_procs_with_block - Dir.mktmpdir("test_ruby_tracer") do |dir| - dummy_script = File.join(dir, "dummy.rb") - open(dummy_script, "w") do |f| - f.print <<-'EOF' -class Dummy - def initialize - @number = 135 - end - attr :number -end - EOF - end - dummy_script = File.realpath dummy_script - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-EOF -require 'tracer' - -Tracer.set_get_line_procs('#{dummy_script}') { |line| - str = %{\\n} - str = %{!!\\n} if line >= 3 and line <= 6 - str -} -Tracer.on -require_relative 'dummy' - -dm = Dummy.new -puts dm.number - EOF - end - assert_in_out_err([script]) do |(*lines), err| - expected = [ - "#0:#{script}:9::-: require_relative 'dummy'", - "#0:#{dummy_script}:1::-: ", - "#0:#{dummy_script}:1::C: ", - "#0:#{dummy_script}:2::-: ", - "#0:#{dummy_script}:5::-: !!", - "#0:#{dummy_script}:6::E: !!", - "#0:#{script}:11::-: dm = Dummy.new", - "#0:#{dummy_script}:2:Dummy:>: ", - "#0:#{dummy_script}:3:Dummy:-: !!", - "#0:#{dummy_script}:4:Dummy:<: !!", - "#0:#{script}:12::-: puts dm.number", - "135" - ] - assert_equal(expected, lines) - assert_empty(err) - end - end - end - - def test_tracer_by_set_get_line_procs_with_proc - Dir.mktmpdir("test_ruby_tracer") do |dir| - dummy_script = File.join(dir, "dummy.rb") - open(dummy_script, "w") do |f| - f.print <<-'EOF' -class Dummy - def initialize - @number = 135 - end - attr :number -end - EOF - end - dummy_script = File.realpath dummy_script - script = File.join(dir, "require_tracer.rb") - open(script, "w") do |f| - f.print <<-EOF -require 'tracer' - -a_proc_to_set_get_line_procs = proc { |line| - str = %{\\n} - str = %{!!\\n} if line >= 3 and line <= 6 - str -} -Tracer.set_get_line_procs('#{dummy_script}', a_proc_to_set_get_line_procs) -Tracer.on -require_relative 'dummy' - -dm = Dummy.new -puts dm.number - EOF - end - assert_in_out_err([script]) do |(*lines), err| - expected = [ - "#0:#{script}:10::-: require_relative 'dummy'", - "#0:#{dummy_script}:1::-: ", - "#0:#{dummy_script}:1::C: ", - "#0:#{dummy_script}:2::-: ", - "#0:#{dummy_script}:5::-: !!", - "#0:#{dummy_script}:6::E: !!", - "#0:#{script}:12::-: dm = Dummy.new", - "#0:#{dummy_script}:2:Dummy:>: ", - "#0:#{dummy_script}:3:Dummy:-: !!", - "#0:#{dummy_script}:4:Dummy:<: !!", - "#0:#{script}:13::-: puts dm.number", - "135" - ] - assert_equal(expected, lines) - assert_empty(err) - end - end - end -end diff --git a/ruby/test/test_trick.rb b/ruby/test/test_trick.rb new file mode 100644 index 000000000..e37bda2ef --- /dev/null +++ b/ruby/test/test_trick.rb @@ -0,0 +1,191 @@ +require "test/unit" +require "ripper" +require "envutil" + +# This is a test suite for TRICK entries, joke Ruby program contest. +# The programs are very unusual, and not practical. +# Feel free to comment them out if they bother you. +# I'll appreciate it if you could notify mame + +class TestTRICK2013 < Test::Unit::TestCase + def test_kinaba + src = File.join(__dir__, "../sample/trick2013/kinaba/entry.rb") + expected = [*" ".."~"].join("") # all ASCII printables + assert_in_out_err(["-W0", src], "", [expected]) + assert_equal(expected, File.read(src).chomp.chars.sort.join) + end + + def test_mame + src = File.join(__dir__, "../sample/trick2013/mame/entry.rb") + ignore_dsp = "def open(_file, _mode); s = ''; def s.flush; self;end; yield s; end;" + assert_in_out_err(["-W0"], ignore_dsp + File.read(src), File.read(src).lines(chomp: true), timeout: 60) + end + + def test_shinh + src = File.join(__dir__, "../sample/trick2013/shinh/entry.rb") + assert_in_out_err(["-W0", src], "", []) + end + + def test_yhara + src = File.join(__dir__, "../sample/trick2013/yhara/entry.rb") + assert_in_out_err(["-W0", src], "", ["JUST ANOTHER RUBY HACKER"]) + end +end + +class TestTRICK2015 < Test::Unit::TestCase + def test_kinaba + src = File.join(__dir__, "../sample/trick2015/kinaba/entry.rb") + + # calculate the first 10000 digits of Pi + n = 10000 + a = b = 10 ** n + (n * 8 + 1).step(3, -2) do |i| + a = (i / 2) * (a + b * 2) / i + end + pi = "3#{ a - b }" + + assert_in_out_err(["-W0", src], "", [pi], timeout: 60) + assert_equal(pi[0, 242], Ripper.tokenize(File.read(src)).grep(/\S/).map{|t|t.size%10}.join) + end + + def test_ksk_1 + src = File.join(__dir__, "../sample/trick2015/ksk_1/entry.rb") + + # calculate Collatz sequence + s = ["27"] + n = 27 + until n == 1 + n = n.even? ? n / 2 : n * 3 + 1 + s << n.to_s + end + + assert_in_out_err(["-W0", src, "27"], "", s) + end + + def test_monae + src = File.join(__dir__, "../sample/trick2015/monae/entry.rb") + + code = File.read(src) + expected = code.lines(chomp: true) + (0..15).map { "" } + code.lines.each_with_index do |s, y| + y += 16 + s.chomp.chars.each_with_index do |c, x| + x += 16 + expected[y] << " " while expected[y].size < x + expected[y][x] = c if c != " " + end + end + expected = /\A#{ expected.map {|s| "#{ Regexp.quote(s) }\s*\n" }.join }\z/ + + assert_in_out_err(["-W0", src], "", expected) + end + + def test_eregon + src = File.join(__dir__, "../sample/trick2015/eregon/entry.rb") + + assert_in_out_err(["-W0", src], "", <'http://127.0.0.1:8080', 'no_proxy'=>'192.0.2.2') {|env| assert_equal(URI('http://127.0.0.1:8080'), URI("http://192.0.2.1/").find_proxy(env)) assert_nil(URI("http://192.0.2.2/").find_proxy(env)) - getaddress = IPSocket.method(:getaddress) - begin - class << IPSocket - undef getaddress - def getaddress(host) - host == "example.org" or raise - "192.0.2.1" - end - end - assert_equal(URI('http://127.0.0.1:8080'), URI.parse("http://example.org").find_proxy(env)) - class << IPSocket - undef getaddress - def getaddress(host) - host == "example.org" or raise - "192.0.2.2" - end - end - assert_nil(URI.parse("http://example.org").find_proxy(env)) - ensure - IPSocket.singleton_class.class_eval do - undef getaddress - define_method(:getaddress, getaddress) - end - end + example_address = "192.0.2.1" + assert_equal(URI('http://127.0.0.1:8080'), URI.parse("http://example.org").find_proxy(env)) + example_address = "192.0.2.2" + assert_nil(URI.parse("http://example.org").find_proxy(env)) } with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'example.org') {|env| assert_nil(URI("http://example.org/").find_proxy(env)) @@ -902,6 +909,11 @@ def getaddress(host) assert_equal(URI('http://127.0.0.1:8080'), URI("http://example.org/").find_proxy(env)) assert_nil(URI("http://www.example.org/").find_proxy(env)) } + ensure + IPSocket.singleton_class.class_eval do + undef getaddress + define_method(:getaddress, getaddress) + end end def test_find_proxy_no_proxy_cidr diff --git a/ruby/test/uri/test_http.rb b/ruby/test/uri/test_http.rb index cc19046c8..748e90a32 100644 --- a/ruby/test/uri/test_http.rb +++ b/ruby/test/uri/test_http.rb @@ -1,6 +1,7 @@ # frozen_string_literal: false require 'test/unit' require 'uri/http' +require 'uri/https' module URI @@ -24,14 +25,16 @@ def test_build def test_parse u = URI.parse('http://a') assert_kind_of(URI::HTTP, u) - assert_equal(['http', - nil, 'a', URI::HTTP.default_port, - '', nil, nil], uri_to_ary(u)) + assert_equal([ + 'http', + nil, 'a', URI::HTTP.default_port, + '', nil, nil + ], uri_to_ary(u)) end def test_normalize host = 'aBcD' - u1 = URI.parse('http://' + host + '/eFg?HiJ') + u1 = URI.parse('http://' + host + '/eFg?HiJ') u2 = URI.parse('http://' + host.downcase + '/eFg?HiJ') assert(u1.normalize.host == 'abcd') assert(u1.normalize.path == u1.path) @@ -49,11 +52,11 @@ def test_equal end def test_request_uri - assert_equal('/', URI.parse('http://a.b.c/').request_uri) + assert_equal('/', URI.parse('http://a.b.c/').request_uri) assert_equal('/?abc=def', URI.parse('http://a.b.c/?abc=def').request_uri) - assert_equal('/', URI.parse('http://a.b.c').request_uri) + assert_equal('/', URI.parse('http://a.b.c').request_uri) assert_equal('/?abc=def', URI.parse('http://a.b.c?abc=def').request_uri) - assert_equal(nil, URI.parse('http:foo').request_uri) + assert_equal(nil, URI.parse('http:foo').request_uri) end def test_select @@ -64,6 +67,20 @@ def test_select u.select(:scheme, :host, :not_exist, :port) end end + + def test_authority + assert_equal('a.b.c', URI.parse('http://a.b.c/').authority) + assert_equal('a.b.c:8081', URI.parse('http://a.b.c:8081/').authority) + assert_equal('a.b.c', URI.parse('http://a.b.c:80/').authority) + end + + + def test_origin + assert_equal('http://a.b.c', URI.parse('http://a.b.c/').origin) + assert_equal('http://a.b.c:8081', URI.parse('http://a.b.c:8081/').origin) + assert_equal('http://a.b.c', URI.parse('http://a.b.c:80/').origin) + assert_equal('https://a.b.c', URI.parse('https://a.b.c/').origin) + end end diff --git a/ruby/test/uri/test_ldap.rb b/ruby/test/uri/test_ldap.rb index adad4454b..64845e487 100644 --- a/ruby/test/uri/test_ldap.rb +++ b/ruby/test/uri/test_ldap.rb @@ -95,6 +95,10 @@ def test_select u.select(:scheme, :host, :not_exist, :port) end end + + def test_parse_invalid_uri + assert_raise(URI::InvalidURIError) {URI.parse("ldap:https://example.com")} + end end diff --git a/ruby/test/uri/test_parser.rb b/ruby/test/uri/test_parser.rb index b13a26ca8..03de13778 100644 --- a/ruby/test/uri/test_parser.rb +++ b/ruby/test/uri/test_parser.rb @@ -7,6 +7,11 @@ def uri_to_ary(uri) uri.class.component.collect {|c| uri.send(c)} end + def test_inspect + assert_match(/URI::RFC2396_Parser/, URI::Parser.new.inspect) + assert_match(/URI::RFC3986_Parser/, URI::RFC3986_Parser.new.inspect) + end + def test_compare url = 'http://a/b/c/d;p?q' u0 = URI.parse(url) diff --git a/ruby/test/uri/test_ws.rb b/ruby/test/uri/test_ws.rb new file mode 100644 index 000000000..17acb0d9f --- /dev/null +++ b/ruby/test/uri/test_ws.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: false +require 'test/unit' +require 'uri/http' +require 'uri/ws' + +module URI + + +class TestWS < Test::Unit::TestCase + def setup + end + + def teardown + end + + def uri_to_ary(uri) + uri.class.component.collect {|c| uri.send(c)} + end + + def test_build + u = URI::WS.build(host: 'www.example.com', path: '/foo/bar') + assert_kind_of(URI::WS, u) + end + + def test_parse + u = URI.parse('ws://a') + assert_kind_of(URI::WS, u) + assert_equal(['ws', + nil, 'a', URI::HTTP.default_port, + '', nil], uri_to_ary(u)) + end + + def test_normalize + host = 'aBcD' + u1 = URI.parse('ws://' + host + '/eFg?HiJ') + u2 = URI.parse('ws://' + host.downcase + '/eFg?HiJ') + assert(u1.normalize.host == 'abcd') + assert(u1.normalize.path == u1.path) + assert(u1.normalize == u2.normalize) + assert(!u1.normalize.host.equal?(u1.host)) + assert( u2.normalize.host.equal?(u2.host)) + + assert_equal('ws://abc/', URI.parse('ws://abc').normalize.to_s) + end + + def test_equal + assert(URI.parse('ws://abc') == URI.parse('ws://ABC')) + assert(URI.parse('ws://abc/def') == URI.parse('ws://ABC/def')) + assert(URI.parse('ws://abc/def') != URI.parse('ws://ABC/DEF')) + end + + def test_request_uri + assert_equal('/', URI.parse('ws://a.b.c/').request_uri) + assert_equal('/?abc=def', URI.parse('ws://a.b.c/?abc=def').request_uri) + assert_equal('/', URI.parse('ws://a.b.c').request_uri) + assert_equal('/?abc=def', URI.parse('ws://a.b.c?abc=def').request_uri) + assert_equal(nil, URI.parse('ws:foo').request_uri) + end + + def test_select + assert_equal(['ws', 'a.b.c', 80], URI.parse('ws://a.b.c/').select(:scheme, :host, :port)) + u = URI.parse('ws://a.b.c/') + assert_equal(uri_to_ary(u), u.select(*u.component)) + assert_raise(ArgumentError) do + u.select(:scheme, :host, :not_exist, :port) + end + end +end + + +end diff --git a/ruby/test/webrick/test_filehandler.rb b/ruby/test/webrick/test_filehandler.rb deleted file mode 100644 index 33b6d7b6f..000000000 --- a/ruby/test/webrick/test_filehandler.rb +++ /dev/null @@ -1,353 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require_relative "utils.rb" -require "webrick" -require "stringio" - -class WEBrick::TestFileHandler < Test::Unit::TestCase - def teardown - WEBrick::Utils::TimeoutHandler.terminate - super - end - - def default_file_handler(filename) - klass = WEBrick::HTTPServlet::DefaultFileHandler - klass.new(WEBrick::Config::HTTP, filename) - end - - def windows? - File.directory?("\\") - end - - def get_res_body(res) - sio = StringIO.new - sio.binmode - res.send_body(sio) - sio.string - end - - def make_range_request(range_spec) - msg = <<-END_OF_REQUEST - GET / HTTP/1.0 - Range: #{range_spec} - - END_OF_REQUEST - return StringIO.new(msg.gsub(/^ {6}/, "")) - end - - def make_range_response(file, range_spec) - req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) - req.parse(make_range_request(range_spec)) - res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP) - size = File.size(file) - handler = default_file_handler(file) - handler.make_partial_content(req, res, file, size) - return res - end - - def test_make_partial_content - filename = __FILE__ - filesize = File.size(filename) - - res = make_range_response(filename, "bytes=#{filesize-100}-") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(100, get_res_body(res).size) - - res = make_range_response(filename, "bytes=-100") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(100, get_res_body(res).size) - - res = make_range_response(filename, "bytes=0-99") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(100, get_res_body(res).size) - - res = make_range_response(filename, "bytes=100-199") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(100, get_res_body(res).size) - - res = make_range_response(filename, "bytes=0-0") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(1, get_res_body(res).size) - - res = make_range_response(filename, "bytes=-1") - assert_match(%r{^text/plain}, res["content-type"]) - assert_equal(1, get_res_body(res).size) - - res = make_range_response(filename, "bytes=0-0, -2") - assert_match(%r{^multipart/byteranges}, res["content-type"]) - body = get_res_body(res) - boundary = /; boundary=(.+)/.match(res['content-type'])[1] - off = filesize - 2 - last = filesize - 1 - - exp = "--#{boundary}\r\n" \ - "Content-Type: text/plain\r\n" \ - "Content-Range: bytes 0-0/#{filesize}\r\n" \ - "\r\n" \ - "#{IO.read(__FILE__, 1)}\r\n" \ - "--#{boundary}\r\n" \ - "Content-Type: text/plain\r\n" \ - "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \ - "\r\n" \ - "#{IO.read(__FILE__, 2, off)}\r\n" \ - "--#{boundary}--\r\n" - assert_equal exp, body - end - - def test_filehandler - config = { :DocumentRoot => File.dirname(__FILE__), } - this_file = File.basename(__FILE__) - filesize = File.size(__FILE__) - this_data = File.binread(__FILE__) - range = nil - bug2593 = '[ruby-dev:40030]' - - TestWEBrick.start_httpserver(config) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - req = Net::HTTP::Get.new("/") - http.request(req){|res| - assert_equal("200", res.code, log.call) - assert_equal("text/html", res.content_type, log.call) - assert_match(/HREF="#{this_file}"/, res.body, log.call) - } - req = Net::HTTP::Get.new("/#{this_file}") - http.request(req){|res| - assert_equal("200", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_equal(this_data, res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal((filesize-100)..(filesize-1), range, log.call) - assert_equal(this_data[-100..-1], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal((filesize-100)..(filesize-1), range, log.call) - assert_equal(this_data[-100..-1], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal(0..99, range, log.call) - assert_equal(this_data[0..99], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal(100..199, range, log.call) - assert_equal(this_data[100..199], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal(0..0, range, log.call) - assert_equal(this_data[0..0], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("text/plain", res.content_type, log.call) - assert_nothing_raised(bug2593) {range = res.content_range} - assert_equal((filesize-1)..(filesize-1), range, log.call) - assert_equal(this_data[-1, 1], res.body, log.call) - } - - req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2") - http.request(req){|res| - assert_equal("206", res.code, log.call) - assert_equal("multipart/byteranges", res.content_type, log.call) - } - - end - end - - def test_non_disclosure_name - config = { :DocumentRoot => File.dirname(__FILE__), } - log_tester = lambda {|log, access_log| - log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } - log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s } - assert_equal([], log) - } - this_file = File.basename(__FILE__) - TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - doc_root_opts = server[:DocumentRootOptions] - doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*) - req = Net::HTTP::Get.new("/") - http.request(req){|res| - assert_equal("200", res.code, log.call) - assert_equal("text/html", res.content_type, log.call) - assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body) - } - req = Net::HTTP::Get.new("/#{this_file}") - http.request(req){|res| - assert_equal("404", res.code, log.call) - } - doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*) - http.request(req){|res| - assert_equal("404", res.code, log.call) - } - end - end - - def test_directory_traversal - return if File.executable?(__FILE__) # skip on strange file system - - config = { :DocumentRoot => File.dirname(__FILE__), } - log_tester = lambda {|log, access_log| - log = log.reject {|s| /ERROR bad URI/ =~ s } - log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } - assert_equal([], log) - } - TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - req = Net::HTTP::Get.new("/../../") - http.request(req){|res| assert_equal("400", res.code, log.call) } - req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}") - http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) } - req = Net::HTTP::Get.new("/..%5c..%5cruby.c") - http.request(req){|res| assert_equal("404", res.code, log.call) } - end - end - - def test_unwise_in_path - if windows? - config = { :DocumentRoot => File.dirname(__FILE__), } - TestWEBrick.start_httpserver(config) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - req = Net::HTTP::Get.new("/..%5c..") - http.request(req){|res| assert_equal("301", res.code, log.call) } - end - end - end - - def test_short_filename - return if File.executable?(__FILE__) # skip on strange file system - - config = { - :CGIInterpreter => TestWEBrick::RubyBin, - :DocumentRoot => File.dirname(__FILE__), - :CGIPathEnv => ENV['PATH'], - } - log_tester = lambda {|log, access_log| - log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } - log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s } - assert_equal([], log) - } - TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - if windows? - root = config[:DocumentRoot].tr("/", "\\") - fname = IO.popen(%W[dir /x #{root}\\webrick_long_filename.cgi], &:read) - fname.sub!(/\A.*$^$.*$^$/m, '') - if fname - fname = fname[/\s(w.+?cgi)\s/i, 1] - fname.downcase! - end - else - fname = "webric~1.cgi" - end - req = Net::HTTP::Get.new("/#{fname}/test") - http.request(req) do |res| - if windows? - assert_equal("200", res.code, log.call) - assert_equal("/test", res.body, log.call) - else - assert_equal("404", res.code, log.call) - end - end - - req = Net::HTTP::Get.new("/.htaccess") - http.request(req) {|res| assert_equal("404", res.code, log.call) } - req = Net::HTTP::Get.new("/htacce~1") - http.request(req) {|res| assert_equal("404", res.code, log.call) } - req = Net::HTTP::Get.new("/HTACCE~1") - http.request(req) {|res| assert_equal("404", res.code, log.call) } - end - end - - def test_script_disclosure - return if File.executable?(__FILE__) # skip on strange file system - - config = { - :CGIInterpreter => TestWEBrick::RubyBinArray, - :DocumentRoot => File.dirname(__FILE__), - :CGIPathEnv => ENV['PATH'], - :RequestCallback => Proc.new{|req, res| - def req.meta_vars - meta = super - meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR) - meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV'] - return meta - end - }, - } - log_tester = lambda {|log, access_log| - log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } - assert_equal([], log) - } - TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - http.read_timeout = EnvUtil.apply_timeout_scale(60) - http.write_timeout = EnvUtil.apply_timeout_scale(60) if http.respond_to?(:write_timeout=) - - req = Net::HTTP::Get.new("/webrick.cgi/test") - http.request(req) do |res| - assert_equal("200", res.code, log.call) - assert_equal("/test", res.body, log.call) - end - - resok = windows? - response_assertion = Proc.new do |res| - if resok - assert_equal("200", res.code, log.call) - assert_equal("/test", res.body, log.call) - else - assert_equal("404", res.code, log.call) - end - end - req = Net::HTTP::Get.new("/webrick.cgi%20/test") - http.request(req, &response_assertion) - req = Net::HTTP::Get.new("/webrick.cgi./test") - http.request(req, &response_assertion) - resok &&= File.exist?(__FILE__+"::$DATA") - req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test") - http.request(req, &response_assertion) - end - end - - def test_erbhandler - config = { :DocumentRoot => File.dirname(__FILE__) } - log_tester = lambda {|log, access_log| - log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } - assert_equal([], log) - } - TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| - http = Net::HTTP.new(addr, port) - req = Net::HTTP::Get.new("/webrick.rhtml") - http.request(req) do |res| - assert_equal("200", res.code, log.call) - assert_match %r!\Areq to http://[^/]+/webrick\.rhtml {}\n!, res.body - end - end - end -end diff --git a/ruby/test/webrick/utils.rb b/ruby/test/webrick/utils.rb deleted file mode 100644 index 56d3a30ea..000000000 --- a/ruby/test/webrick/utils.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: false -require "webrick" -begin - require "webrick/https" -rescue LoadError -end -require "webrick/httpproxy" - -module TestWEBrick - NullWriter = Object.new - def NullWriter.<<(msg) - puts msg if $DEBUG - return self - end - - class WEBrick::HTTPServlet::CGIHandler - remove_const :Ruby - require "envutil" unless defined?(EnvUtil) - Ruby = EnvUtil.rubybin - remove_const :CGIRunner - CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc: - remove_const :CGIRunnerArray - CGIRunnerArray = [Ruby, "#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb"] # :nodoc: - end - - RubyBin = "\"#{EnvUtil.rubybin}\"" - RubyBin << " --disable-gems" - RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\"" - RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\"" - RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\"" - - RubyBinArray = [EnvUtil.rubybin] - RubyBinArray << "--disable-gems" - RubyBinArray << "-I" << "#{File.expand_path("../..", File.dirname(__FILE__))}/lib" - RubyBinArray << "-I" << "#{File.dirname(EnvUtil.rubybin)}/.ext/common" - RubyBinArray << "-I" << "#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}" - - require "test/unit" unless defined?(Test::Unit) - include Test::Unit::Assertions - extend Test::Unit::Assertions - - module_function - - DefaultLogTester = lambda {|log, access_log| assert_equal([], log) } - - def start_server(klass, config={}, log_tester=DefaultLogTester, &block) - log_ary = [] - access_log_ary = [] - log = proc { "webrick log start:\n" + (log_ary+access_log_ary).join.gsub(/^/, " ").chomp + "\nwebrick log end" } - config = ({ - :BindAddress => "127.0.0.1", :Port => 0, - :ServerType => Thread, - :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN), - :AccessLog => [[access_log_ary, ""]] - }.update(config)) - server = capture_output {break klass.new(config)} - server_thread = server.start - server_thread2 = Thread.new { - server_thread.join - if log_tester - log_tester.call(log_ary, access_log_ary) - end - } - addr = server.listeners[0].addr - client_thread = Thread.new { - begin - block.yield([server, addr[3], addr[1], log]) - ensure - server.shutdown - end - } - assert_join_threads([client_thread, server_thread2]) - end - - def start_httpserver(config={}, log_tester=DefaultLogTester, &block) - start_server(WEBrick::HTTPServer, config, log_tester, &block) - end - - def start_httpproxy(config={}, log_tester=DefaultLogTester, &block) - start_server(WEBrick::HTTPProxyServer, config, log_tester, &block) - end -end diff --git a/ruby/test/win32ole/test_win32ole.rb b/ruby/test/win32ole/test_win32ole.rb index 394178052..e5f9d35e2 100644 --- a/ruby/test/win32ole/test_win32ole.rb +++ b/ruby/test/win32ole/test_win32ole.rb @@ -101,7 +101,7 @@ def test_ole_get_methods assert_include(mnames, 'Count') end - def test_ole_mehtod_help + def test_ole_method_help minfo = @dict1.ole_method_help("Add") assert_equal(2, minfo.size_params) end diff --git a/ruby/test/win32ole/test_win32ole_event.rb b/ruby/test/win32ole/test_win32ole_event.rb index 742bff4f7..fa9e7b5b0 100644 --- a/ruby/test/win32ole/test_win32ole_event.rb +++ b/ruby/test/win32ole/test_win32ole_event.rb @@ -65,12 +65,13 @@ def message_loop(watch_ivar = nil) if watch_ivar # wait until event is proceeded tries = 0 + seconds = EnvUtil.apply_timeout_scale(1) while tries < 5 && instance_variable_get(watch_ivar) == orig_ivar - seconds = 2 ** tries # sleep at most 31s in total $stderr.puts "test_win32ole_event.rb: retrying and sleeping #{seconds}s until #{watch_ivar} is changed from #{orig_ivar.inspect}..." WIN32OLE_EVENT.message_loop sleep(seconds) tries += 1 + seconds *= 2 # sleep at most 31s in total end end end diff --git a/ruby/test/yaml/test_store.rb b/ruby/test/yaml/test_store.rb index 9112c569a..ef8d3229c 100644 --- a/ruby/test/yaml/test_store.rb +++ b/ruby/test/yaml/test_store.rb @@ -75,7 +75,7 @@ def test_writing_inside_readonly_transaction_raises_error end def test_thread_safe - q1 = Queue.new + q1 = Thread::Queue.new assert_raise(PStore::Error) do th = Thread.new do @yaml_store.transaction do @@ -92,7 +92,7 @@ def test_thread_safe th.join end end - q2 = Queue.new + q2 = Thread::Queue.new begin yaml_store = YAML::Store.new(second_file, true) cur = Thread.current diff --git a/ruby/test/zlib/test_zlib.rb b/ruby/test/zlib/test_zlib.rb index 7d703d15e..1e57c5aa8 100644 --- a/ruby/test/zlib/test_zlib.rb +++ b/ruby/test/zlib/test_zlib.rb @@ -3,6 +3,8 @@ require 'test/unit' require 'stringio' require 'tempfile' +require 'tmpdir' +require 'securerandom' begin require 'zlib' @@ -363,6 +365,65 @@ def test_inflate_chunked } end + def test_inflate_buffer + s = Zlib::Deflate.deflate("foo") + z = Zlib::Inflate.new + buf = String.new + s = z.inflate(s, buffer: buf) + assert_same(buf, s) + buf = String.new + s << z.inflate(nil, buffer: buf) + assert_equal("foo", s) + z.inflate("foo", buffer: buf) # ??? + z << "foo" # ??? + end + + def test_inflate_buffer_partial_input + deflated = Zlib::Deflate.deflate "\0" + + z = Zlib::Inflate.new + + inflated = "".dup + + buf = String.new + deflated.each_char do |byte| + inflated << z.inflate(byte, buffer: buf) + end + + inflated << z.finish + + assert_equal "\0", inflated + end + + def test_inflate_buffer_chunked + # s = Zlib::Deflate.deflate("0" * 100_000) + zeros = "x\234\355\3011\001\000\000\000\302\240J\353\237\316\032\036@" \ + "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \ + "\000\000\000\000\000\000\000\257\006\351\247BH" + + chunks = [] + + z = Zlib::Inflate.new + + buf = String.new + z.inflate(zeros, buffer: buf) do |chunk| + assert_same(buf, chunk) + chunks << chunk.dup + end + + assert_equal [16384, 16384, 16384, 16384, 16384, 16384, 1696], + chunks.map { |chunk| chunk.size } + + assert chunks.all? { |chunk| + chunk =~ /\A0+\z/ + } + end + def test_inflate_chunked_break # zeros = Zlib::Deflate.deflate("0" * 100_000) zeros = "x\234\355\3011\001\000\000\000\302\240J\353\237\316\032\036@" \ @@ -443,9 +504,102 @@ def test_set_dictionary assert_raise(Zlib::StreamError) { z.set_dictionary("foo") } z.close end + + def test_multithread_deflate + zd = Zlib::Deflate.new + + s = "x" * 10000 + (0...10).map do |x| + Thread.new do + 1000.times { zd.deflate(s) } + end + end.each do |th| + th.join + end + ensure + zd&.finish + zd&.close + end + + def test_multithread_inflate + zi = Zlib::Inflate.new + + s = Zlib.deflate("x" * 10000) + (0...10).map do |x| + Thread.new do + 1000.times { zi.inflate(s) } + end + end.each do |th| + th.join + end + ensure + zi&.finish + zi&.close + end + + def test_recursive_deflate + original_gc_stress = GC.stress + GC.stress = true + zd = Zlib::Deflate.new + + s = SecureRandom.random_bytes(1024**2) + assert_raise(Zlib::InProgressError) do + zd.deflate(s) do + zd.deflate(s) + end + end + ensure + GC.stress = original_gc_stress + zd&.finish + zd&.close + end + + def test_recursive_inflate + original_gc_stress = GC.stress + GC.stress = true + zi = Zlib::Inflate.new + + s = Zlib.deflate(SecureRandom.random_bytes(1024**2)) + + assert_raise(Zlib::InProgressError) do + zi.inflate(s) do + zi.inflate(s) + end + end + ensure + GC.stress = original_gc_stress + zi&.close + end end class TestZlibGzipFile < Test::Unit::TestCase + def test_gzip_reader_zcat + Tempfile.create("test_zlib_gzip_file_to_io") {|t| + t.binmode + gz = Zlib::GzipWriter.new(t) + gz.print("foo") + gz.close + File.open(t.path, 'ab') do |f| + gz = Zlib::GzipWriter.new(f) + gz.print("bar") + gz.close + end + + results = [] + File.open(t.path, 'rb') do |f| + Zlib::GzipReader.zcat(f) do |str| + results << str + end + end + assert_equal(["foo", "bar"], results) + + results = File.open(t.path, 'rb') do |f| + Zlib::GzipReader.zcat(f) + end + assert_equal("foobar", results) + } + end + def test_to_io Tempfile.create("test_zlib_gzip_file_to_io") {|t| t.close @@ -637,6 +791,34 @@ def test_path gz.close } end + + if defined? File::TMPFILE + def test_path_tmpfile + sio = StringIO.new("".dup, 'w') + gz = Zlib::GzipWriter.new(sio) + gz.write "hi" + gz.close + + File.open(Dir.mktmpdir, File::RDWR | File::TMPFILE) do |io| + io.write sio.string + io.rewind + + gz0 = Zlib::GzipWriter.new(io) + assert_raise(NoMethodError) { gz0.path } + + gz1 = Zlib::GzipReader.new(io) + assert_raise(NoMethodError) { gz1.path } + gz0.close + gz1.close + end + rescue Errno::EINVAL + skip 'O_TMPFILE not supported (EINVAL)' + rescue Errno::EISDIR + skip 'O_TMPFILE not supported (EISDIR)' + rescue Errno::EOPNOTSUPP + skip 'O_TMPFILE not supported (EOPNOTSUPP)' + end + end end class TestZlibGzipReader < Test::Unit::TestCase @@ -1121,6 +1303,19 @@ def test_adler32 assert_equal(0x02820145, Zlib.adler32("foo")) assert_equal(0x02820145, Zlib.adler32("o", Zlib.adler32("fo"))) assert_equal(0x8a62c964, Zlib.adler32("abc\x01\x02\x03" * 10000)) + Tempfile.create("test_zlib_gzip_file_to_io") {|t| + File.binwrite(t.path, "foo") + t.rewind + assert_equal(0x02820145, Zlib.adler32(t)) + + t.rewind + crc = Zlib.adler32(t.read(2)) + assert_equal(0x02820145, Zlib.adler32(t, crc)) + + File.binwrite(t.path, "abc\x01\x02\x03" * 10000) + t.rewind + assert_equal(0x8a62c964, Zlib.adler32(t)) + } end def test_adler32_combine @@ -1130,7 +1325,7 @@ def test_adler32_combine assert_equal(0x02820145, Zlib.adler32_combine(one, two, 1)) rescue NotImplementedError skip "adler32_combine is not implemented" - rescue Minitest::Assertion + rescue Test::Unit::AssertionFailedError if /aix/ =~ RUBY_PLATFORM skip "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed" end @@ -1143,6 +1338,19 @@ def test_crc32 assert_equal(0x8c736521, Zlib.crc32("foo")) assert_equal(0x8c736521, Zlib.crc32("o", Zlib.crc32("fo"))) assert_equal(0x07f0d68f, Zlib.crc32("abc\x01\x02\x03" * 10000)) + Tempfile.create("test_zlib_gzip_file_to_io") {|t| + File.binwrite(t.path, "foo") + t.rewind + assert_equal(0x8c736521, Zlib.crc32(t)) + + t.rewind + crc = Zlib.crc32(t.read(2)) + assert_equal(0x8c736521, Zlib.crc32(t, crc)) + + File.binwrite(t.path, "abc\x01\x02\x03" * 10000) + t.rewind + assert_equal(0x07f0d68f, Zlib.crc32(t)) + } end def test_crc32_combine @@ -1152,7 +1360,7 @@ def test_crc32_combine assert_equal(0x8c736521, Zlib.crc32_combine(one, two, 1)) rescue NotImplementedError skip "crc32_combine is not implemented" - rescue Minitest::Assertion + rescue Test::Unit::AssertionFailedError if /aix/ =~ RUBY_PLATFORM skip "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed" end @@ -1167,11 +1375,20 @@ def test_crc_table end def test_inflate - TestZlibInflate.new(__name__).test_inflate + s = Zlib::Deflate.deflate("foo") + z = Zlib::Inflate.new + s = z.inflate(s) + s << z.inflate(nil) + assert_equal("foo", s) + z.inflate("foo") # ??? + z << "foo" # ??? end def test_deflate - TestZlibDeflate.new(__name__).test_deflate + s = Zlib::Deflate.deflate("foo") + assert_equal("foo", Zlib::Inflate.inflate(s)) + + assert_raise(Zlib::StreamError) { Zlib::Deflate.deflate("foo", 10000) } end def test_deflate_stream diff --git a/ruby/thread.c b/ruby/thread.c index 708aaa471..cf6e89327 100644 --- a/ruby/thread.c +++ b/ruby/thread.c @@ -63,24 +63,40 @@ /* for model 2 */ -#include "ruby/config.h" -#include "ruby/io.h" +#include "ruby/internal/config.h" + +#ifdef __linux__ +// Normally, gcc(1) translates calls to alloca() with inlined code. This is not done when either the -ansi, -std=c89, -std=c99, or the -std=c11 option is given and the header is not included. +# include +#endif + #include "eval_intern.h" -#include "timev.h" -#include "ruby/thread.h" -#include "ruby/thread_native.h" -#include "ruby/debug.h" #include "gc.h" +#include "hrtime.h" #include "internal.h" +#include "internal/class.h" +#include "internal/cont.h" +#include "internal/error.h" +#include "internal/hash.h" +#include "internal/io.h" +#include "internal/object.h" +#include "internal/proc.h" +#include "ruby/fiber/scheduler.h" +#include "internal/signal.h" +#include "internal/thread.h" +#include "internal/time.h" +#include "internal/warnings.h" #include "iseq.h" -#include "vm_core.h" #include "mjit.h" -#include "hrtime.h" - -#ifdef __linux__ -// Normally, gcc(1) translates calls to alloca() with inlined code. This is not done when either the -ansi, -std=c89, -std=c99, or the -std=c11 option is given and the header is not included. -#include -#endif +#include "ruby/debug.h" +#include "ruby/io.h" +#include "ruby/thread.h" +#include "ruby/thread_native.h" +#include "timev.h" +#include "vm_core.h" +#include "ractor_core.h" +#include "vm_debug.h" +#include "vm_sync.h" #ifndef USE_NATIVE_THREAD_PRIORITY #define USE_NATIVE_THREAD_PRIORITY 0 @@ -116,11 +132,11 @@ rb_thread_local_storage(VALUE thread) return rb_ivar_get(thread, idLocals); } -static void sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl); +static int sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl); static void sleep_forever(rb_thread_t *th, unsigned int fl); -static void rb_thread_sleep_deadly_allow_spurious_wakeup(void); +static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker); static int rb_threadptr_dead(rb_thread_t *th); -static void rb_check_deadlock(rb_vm_t *vm); +static void rb_check_deadlock(rb_ractor_t *r); static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th); static const char *thread_status_name(rb_thread_t *th, int detail); static int hrtime_update_expire(rb_hrtime_t *, const rb_hrtime_t); @@ -139,12 +155,6 @@ struct waiting_fd { int fd; }; -inline static void -st_delete_wrap(st_table *table, st_data_t key) -{ - st_delete(table, &key, 0); -} - /********************************************************************************/ #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION @@ -160,20 +170,13 @@ static inline int blocking_region_begin(rb_thread_t *th, struct rb_blocking_regi rb_unblock_function_t *ubf, void *arg, int fail_if_interrupted); static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region); -#define RB_GC_SAVE_MACHINE_CONTEXT(th) \ - do { \ - FLUSH_REGISTER_WINDOWS; \ - setjmp((th)->ec->machine.regs); \ - SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \ - } while (0) - #define GVL_UNLOCK_BEGIN(th) do { \ RB_GC_SAVE_MACHINE_CONTEXT(th); \ - gvl_release(th->vm); + gvl_release(rb_ractor_gvl(th->ractor)); #define GVL_UNLOCK_END(th) \ - gvl_acquire(th->vm, th); \ - rb_thread_set_current(th); \ + gvl_acquire(rb_ractor_gvl(th->ractor), th); \ + rb_ractor_thread_switch(th->ractor, th); \ } while(0) #ifdef __GNUC__ @@ -215,10 +218,10 @@ vm_check_ints_blocking(rb_execution_context_t *ec) return rb_threadptr_execute_interrupts(th, 1); } -static int -vm_living_thread_num(const rb_vm_t *vm) +int +rb_vm_check_ints_blocking(rb_execution_context_t *ec) { - return vm->living_thread_num; + return vm_check_ints_blocking(ec); } /* @@ -304,7 +307,7 @@ static int rb_thread_debug_enabled; */ static VALUE -rb_thread_s_debug(void) +rb_thread_s_debug(VALUE _) { return INT2NUM(rb_thread_debug_enabled); } @@ -338,7 +341,6 @@ rb_thread_s_debug_set(VALUE self, VALUE val) #endif NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start)); -static void timer_thread_function(void); void ruby_sigchld_handler(rb_vm_t *); /* signal.c */ static void @@ -347,8 +349,9 @@ ubf_sigwait(void *ignore) rb_thread_wakeup_timer_thread(0); } +#include THREAD_IMPL_SRC + #if defined(_WIN32) -#include "thread_win32.c" #define DEBUG_OUT() \ WaitForSingleObject(&debug_mutex, INFINITE); \ @@ -357,7 +360,6 @@ ubf_sigwait(void *ignore) ReleaseMutex(&debug_mutex); #elif defined(HAVE_PTHREAD_H) -#include "thread_pthread.c" #define DEBUG_OUT() \ pthread_mutex_lock(&debug_mutex); \ @@ -366,8 +368,6 @@ ubf_sigwait(void *ignore) fflush(stdout); \ pthread_mutex_unlock(&debug_mutex); -#else -#error "unsupported thread type" #endif /* @@ -418,15 +418,10 @@ rb_thread_debug( #include "thread_sync.c" void -rb_vm_gvl_destroy(rb_vm_t *vm) +rb_vm_gvl_destroy(rb_global_vm_lock_t *gvl) { - gvl_release(vm); - gvl_destroy(vm); - if (0) { - /* may be held by running threads */ - rb_native_mutex_destroy(&vm->waitpid_lock); - rb_native_mutex_destroy(&vm->workqueue_lock); - } + gvl_release(gvl); + gvl_destroy(gvl); } void @@ -483,7 +478,7 @@ static void unblock_function_clear(rb_thread_t *th) { rb_native_mutex_lock(&th->interrupt_lock); - th->unblock.func = NULL; + th->unblock.func = 0; rb_native_mutex_unlock(&th->interrupt_lock); } @@ -491,6 +486,7 @@ static void rb_threadptr_interrupt_common(rb_thread_t *th, int trap) { rb_native_mutex_lock(&th->interrupt_lock); + if (trap) { RUBY_VM_SET_TRAP_INTERRUPT(th->ec); } @@ -519,12 +515,12 @@ threadptr_trap_interrupt(rb_thread_t *th) } static void -terminate_all(rb_vm_t *vm, const rb_thread_t *main_thread) +terminate_all(rb_ractor_t *r, const rb_thread_t *main_thread) { rb_thread_t *th = 0; - list_for_each(&vm->living_threads, th, vmlt_node) { - if (th != main_thread) { + list_for_each(&r->threads.set, th, lt_node) { + if (th != main_thread) { thread_debug("terminate_all: begin (thid: %"PRI_THREAD_ID", status: %s)\n", thread_id_str(th), thread_status_name(th, TRUE)); rb_threadptr_pending_interrupt_enque(th, eTerminateSignal); @@ -538,34 +534,58 @@ terminate_all(rb_vm_t *vm, const rb_thread_t *main_thread) } } +static void +rb_threadptr_join_list_wakeup(rb_thread_t *thread) +{ + while (thread->join_list) { + struct rb_waiting_list *join_list = thread->join_list; + + // Consume the entry from the join list: + thread->join_list = join_list->next; + + rb_thread_t *target_thread = join_list->thread; + + if (target_thread->scheduler != Qnil && rb_fiberptr_blocking(join_list->fiber) == 0) { + rb_fiber_scheduler_unblock(target_thread->scheduler, target_thread->self, rb_fiberptr_self(join_list->fiber)); + } + else { + rb_threadptr_interrupt(target_thread); + + switch (target_thread->status) { + case THREAD_STOPPED: + case THREAD_STOPPED_FOREVER: + target_thread->status = THREAD_RUNNABLE; + default: + break; + } + } + } +} + void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th) { - const char *err; - rb_mutex_t *mutex; - rb_mutex_t *mutexes = th->keeping_mutexes; + while (th->keeping_mutexes) { + rb_mutex_t *mutex = th->keeping_mutexes; + th->keeping_mutexes = mutex->next_mutex; - while (mutexes) { - mutex = mutexes; - /* rb_warn("mutex #<%p> remains to be locked by terminated thread", - (void *)mutexes); */ - mutexes = mutex->next_mutex; - err = rb_mutex_unlock_th(mutex, th); - if (err) rb_bug("invalid keeping_mutexes: %s", err); + /* rb_warn("mutex #<%p> remains to be locked by terminated thread", (void *)mutexes); */ + + const char *error_message = rb_mutex_unlock_th(mutex, th, mutex->fiber); + if (error_message) rb_bug("invalid keeping_mutexes: %s", error_message); } } void -rb_thread_terminate_all(void) +rb_thread_terminate_all(rb_thread_t *th) { - rb_thread_t *volatile th = GET_THREAD(); /* main thread */ + rb_ractor_t *cr = th->ractor; rb_execution_context_t * volatile ec = th->ec; - rb_vm_t *volatile vm = th->vm; volatile int sleeping = 0; - if (vm->main_thread != th) { - rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)", - (void *)vm->main_thread, (void *)th); + if (cr->threads.main != th) { + rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)", + (void *)cr->threads.main, (void *)th); } /* unlock all locking mutexes */ @@ -575,11 +595,11 @@ rb_thread_terminate_all(void) if (EC_EXEC_TAG() == TAG_NONE) { retry: thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th); - terminate_all(vm, th); + terminate_all(cr, th); - while (vm_living_thread_num(vm) > 1) { + while (rb_ractor_living_thread_num(cr) > 1) { rb_hrtime_t rel = RB_HRTIME_PER_SEC; - /* + /*q * Thread exiting routine in thread_start_func_2 notify * me when the last sub-thread exit. */ @@ -610,6 +630,7 @@ thread_cleanup_func_before_exec(void *th_ptr) { rb_thread_t *th = th_ptr; th->status = THREAD_KILLED; + // The thread stack doesn't exist in the forked process: th->ec->machine.stack_start = th->ec->machine.stack_end = NULL; @@ -662,27 +683,43 @@ rb_vm_proc_local_ep(VALUE proc) } } -static void -thread_do_start(rb_thread_t *th) -{ - native_set_thread_name(th); +// for ractor, defined in vm.c +VALUE rb_vm_invoke_proc_with_self(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, + int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler); - if (th->invoke_type == thread_invoke_type_proc) { - VALUE args = th->invoke_arg.proc.args; - int args_len = (int)RARRAY_LEN(args); - int kw_splat = th->invoke_arg.proc.kw_splat; - const VALUE *args_ptr; - VALUE procval = th->invoke_arg.proc.proc; - rb_proc_t *proc; - GetProcPtr(procval, proc); - - th->ec->errinfo = Qnil; - th->ec->root_lep = rb_vm_proc_local_ep(procval); - th->ec->root_svar = Qfalse; - - EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef); +static VALUE +thread_do_start_proc(rb_thread_t *th) +{ + VALUE args = th->invoke_arg.proc.args; + const VALUE *args_ptr; + int args_len; + VALUE procval = th->invoke_arg.proc.proc; + rb_proc_t *proc; + GetProcPtr(procval, proc); + + th->ec->errinfo = Qnil; + th->ec->root_lep = rb_vm_proc_local_ep(procval); + th->ec->root_svar = Qfalse; + + vm_check_ints_blocking(th->ec); + + if (th->invoke_type == thread_invoke_type_ractor_proc) { + VALUE self = rb_ractor_self(th->ractor); + VM_ASSERT(FIXNUM_P(args)); + args_len = FIX2INT(args); + args_ptr = ALLOCA_N(VALUE, args_len); + rb_ractor_receive_parameters(th->ec, th->ractor, args_len, (VALUE *)args_ptr); vm_check_ints_blocking(th->ec); + return rb_vm_invoke_proc_with_self( + th->ec, proc, self, + args_len, args_ptr, + th->invoke_arg.proc.kw_splat, + VM_BLOCK_HANDLER_NONE + ); + } + else { + args_len = RARRAY_LENINT(args); if (args_len < 8) { /* free proc.args if the length is enough small */ args_ptr = ALLOCA_N(VALUE, args_len); @@ -693,16 +730,48 @@ thread_do_start(rb_thread_t *th) args_ptr = RARRAY_CONST_PTR(args); } - rb_adjust_argv_kw_splat(&args_len, &args_ptr, &kw_splat); - th->value = rb_vm_invoke_proc(th->ec, proc, - args_len, args_ptr, - kw_splat, VM_BLOCK_HANDLER_NONE); + vm_check_ints_blocking(th->ec); - EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef); + return rb_vm_invoke_proc( + th->ec, proc, + args_len, args_ptr, + th->invoke_arg.proc.kw_splat, + VM_BLOCK_HANDLER_NONE + ); } - else { - th->value = (*th->invoke_arg.func.func)(th->invoke_arg.func.arg); +} + +static void +thread_do_start(rb_thread_t *th) +{ + native_set_thread_name(th); + VALUE result = Qundef; + + EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef); + + switch (th->invoke_type) { + case thread_invoke_type_proc: + result = thread_do_start_proc(th); + break; + + case thread_invoke_type_ractor_proc: + result = thread_do_start_proc(th); + rb_ractor_atexit(th->ec, result); + break; + + case thread_invoke_type_func: + result = (*th->invoke_arg.func.func)(th->invoke_arg.func.arg); + break; + + case thread_invoke_type_none: + rb_bug("unreachable"); } + + rb_fiber_scheduler_set(Qnil); + + th->value = result; + + EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef); } void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec); @@ -712,122 +781,170 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start) { STACK_GROW_DIR_DETECTION; enum ruby_tag_type state; - rb_thread_list_t *join_list; - rb_thread_t *main_th; VALUE errinfo = Qnil; size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE); + rb_thread_t *ractor_main_th = th->ractor->threads.main; VALUE * vm_stack = NULL; - if (th == th->vm->main_thread) { - rb_bug("thread_start_func_2 must not be used for main thread"); + VM_ASSERT(th != th->vm->ractor.main_thread); + thread_debug("thread start: %p\n", (void *)th); + + // setup native thread + gvl_acquire(rb_ractor_gvl(th->ractor), th); + ruby_thread_set_native(th); + + // setup ractor + if (rb_ractor_status_p(th->ractor, ractor_blocking)) { + RB_VM_LOCK(); + { + rb_vm_ractor_blocking_cnt_dec(th->vm, th->ractor, __FILE__, __LINE__); + rb_ractor_t *r = th->ractor; + r->r_stdin = rb_io_prep_stdin(); + r->r_stdout = rb_io_prep_stdout(); + r->r_stderr = rb_io_prep_stderr(); + } + RB_VM_UNLOCK(); } - thread_debug("thread start: %p\n", (void *)th); - VM_ASSERT((size * sizeof(VALUE)) <= th->ec->machine.stack_maxsize); + // This assertion is not passed on win32 env. Check it later. + // VM_ASSERT((size * sizeof(VALUE)) <= th->ec->machine.stack_maxsize); + // setup VM and machine stack vm_stack = alloca(size * sizeof(VALUE)); VM_ASSERT(vm_stack); - gvl_acquire(th->vm, th); - rb_ec_initialize_vm_stack(th->ec, vm_stack, size); th->ec->machine.stack_start = STACK_DIR_UPPER(vm_stack + size, vm_stack); th->ec->machine.stack_maxsize -= size * sizeof(VALUE); - ruby_thread_set_native(th); + thread_debug("thread start (get lock): %p\n", (void *)th); - { - thread_debug("thread start (get lock): %p\n", (void *)th); - rb_thread_set_current(th); + // Ensure that we are not joinable. + VM_ASSERT(th->value == Qundef); - EC_PUSH_TAG(th->ec); - if ((state = EC_EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(th, thread_do_start(th)); - } - else { - errinfo = th->ec->errinfo; - if (state == TAG_FATAL) { - /* fatal error within this thread, need to stop whole script */ - } - else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { - /* exit on main_thread. */ - } - else { - if (th->report_on_exception) { - VALUE mesg = rb_thread_to_s(th->self); - rb_str_cat_cstr(mesg, " terminated with exception (report_on_exception is true):\n"); - rb_write_error_str(mesg); - rb_ec_error_print(th->ec, errinfo); - } - if (th->vm->thread_abort_on_exception || - th->abort_on_exception || RTEST(ruby_debug)) { - /* exit on main_thread */ - } - else { - errinfo = Qnil; - } - } - th->value = Qnil; - } + EC_PUSH_TAG(th->ec); - th->status = THREAD_KILLED; - thread_debug("thread end: %p\n", (void *)th); + if ((state = EC_EXEC_TAG()) == TAG_NONE) { + SAVE_ROOT_JMPBUF(th, thread_do_start(th)); + } + else { + errinfo = th->ec->errinfo; - main_th = th->vm->main_thread; - if (main_th == th) { - ruby_stop(0); - } - if (RB_TYPE_P(errinfo, T_OBJECT)) { - /* treat with normal error object */ - rb_threadptr_raise(main_th, 1, &errinfo); - } - EC_POP_TAG(); + VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef); + if (!NIL_P(exc)) errinfo = exc; - rb_ec_clear_current_thread_trace_func(th->ec); + if (state == TAG_FATAL) { + if (th->invoke_type == thread_invoke_type_ractor_proc) { + rb_ractor_atexit(th->ec, Qnil); + } + /* fatal error within this thread, need to stop whole script */ + } + else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { + /* exit on main_thread. */ + } + else { + if (th->report_on_exception) { + VALUE mesg = rb_thread_to_s(th->self); + rb_str_cat_cstr(mesg, " terminated with exception (report_on_exception is true):\n"); + rb_write_error_str(mesg); + rb_ec_error_print(th->ec, errinfo); + } - /* locking_mutex must be Qfalse */ - if (th->locking_mutex != Qfalse) { - rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")", - (void *)th, th->locking_mutex); - } + if (th->invoke_type == thread_invoke_type_ractor_proc) { + rb_ractor_atexit_exception(th->ec); + } - /* delete self other than main thread from living_threads */ - rb_vm_living_threads_remove(th->vm, th); - if (main_th->status == THREAD_KILLED && rb_thread_alone()) { - /* I'm last thread. wake up main thread from rb_thread_terminate_all */ - rb_threadptr_interrupt(main_th); - } + if (th->vm->thread_abort_on_exception || + th->abort_on_exception || RTEST(ruby_debug)) { + /* exit on main_thread */ + } + else { + errinfo = Qnil; + } + } + th->value = Qnil; + } - /* wake up joining threads */ - join_list = th->join_list; - while (join_list) { - rb_threadptr_interrupt(join_list->th); - switch (join_list->th->status) { - case THREAD_STOPPED: case THREAD_STOPPED_FOREVER: - join_list->th->status = THREAD_RUNNABLE; - default: break; - } - join_list = join_list->next; - } + // The thread is effectively finished and can be joined. + VM_ASSERT(th->value != Qundef); + + rb_threadptr_join_list_wakeup(th); + rb_threadptr_unlock_all_locking_mutexes(th); + + if (th->invoke_type == thread_invoke_type_ractor_proc) { + rb_thread_terminate_all(th); + rb_ractor_teardown(th->ec); + } + + th->status = THREAD_KILLED; + thread_debug("thread end: %p\n", (void *)th); + + if (th->vm->ractor.main_thread == th) { + ruby_stop(0); + } - rb_threadptr_unlock_all_locking_mutexes(th); - rb_check_deadlock(th->vm); + if (RB_TYPE_P(errinfo, T_OBJECT)) { + /* treat with normal error object */ + rb_threadptr_raise(ractor_main_th, 1, &errinfo); + } + + EC_POP_TAG(); + + rb_ec_clear_current_thread_trace_func(th->ec); - rb_fiber_close(th->ec->fiber_ptr); + /* locking_mutex must be Qfalse */ + if (th->locking_mutex != Qfalse) { + rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")", + (void *)th, th->locking_mutex); } + if (ractor_main_th->status == THREAD_KILLED && + th->ractor->threads.cnt <= 2 /* main thread and this thread */) { + /* I'm last thread. wake up main thread from rb_thread_terminate_all */ + rb_threadptr_interrupt(ractor_main_th); + } + + rb_check_deadlock(th->ractor); + + rb_fiber_close(th->ec->fiber_ptr); + thread_cleanup_func(th, FALSE); VM_ASSERT(th->ec->vm_stack == NULL); - gvl_release(th->vm); + if (th->invoke_type == thread_invoke_type_ractor_proc) { + // after rb_ractor_living_threads_remove() + // GC will happen anytime and this ractor can be collected (and destroy GVL). + // So gvl_release() should be before it. + gvl_release(rb_ractor_gvl(th->ractor)); + rb_ractor_living_threads_remove(th->ractor, th); + } + else { + rb_ractor_living_threads_remove(th->ractor, th); + gvl_release(rb_ractor_gvl(th->ractor)); + } return 0; } +struct thread_create_params { + enum thread_invoke_type type; + + // for normal proc thread + VALUE args; + VALUE proc; + + // for ractor + rb_ractor_t *g; + + // for func + VALUE (*fn)(void *); +}; + static VALUE -thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *)) +thread_create_core(VALUE thval, struct thread_create_params *params) { - rb_thread_t *th = rb_thread_ptr(thval), *current_th = GET_THREAD(); + rb_execution_context_t *ec = GET_EC(); + rb_thread_t *th = rb_thread_ptr(thval), *current_th = rb_ec_thread_ptr(ec); int err; if (OBJ_FROZEN(current_th->thgroup)) { @@ -835,19 +952,35 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *)) "can't start a new thread (frozen ThreadGroup)"); } - if (fn) { - th->invoke_type = thread_invoke_type_func; - th->invoke_arg.func.func = fn; - th->invoke_arg.func.arg = (void *)args; - } - else { - (void)RARRAY_LENINT(args); + switch (params->type) { + case thread_invoke_type_proc: th->invoke_type = thread_invoke_type_proc; - th->invoke_arg.proc.proc = rb_block_proc(); - th->invoke_arg.proc.args = args; - th->invoke_arg.proc.kw_splat = rb_empty_keyword_given_p() ? - RB_PASS_EMPTY_KEYWORDS : - rb_keyword_given_p(); + th->invoke_arg.proc.args = params->args; + th->invoke_arg.proc.proc = params->proc; + th->invoke_arg.proc.kw_splat = rb_keyword_given_p(); + break; + + case thread_invoke_type_ractor_proc: +#if RACTOR_CHECK_MODE > 0 + rb_ractor_setup_belonging_to(thval, rb_ractor_id(params->g)); +#endif + th->invoke_type = thread_invoke_type_ractor_proc; + th->ractor = params->g; + th->ractor->threads.main = th; + th->invoke_arg.proc.proc = rb_proc_isolate_bang(params->proc); + th->invoke_arg.proc.args = INT2FIX(RARRAY_LENINT(params->args)); + th->invoke_arg.proc.kw_splat = rb_keyword_given_p(); + rb_ractor_send_parameters(ec, params->g, params->args); + break; + + case thread_invoke_type_func: + th->invoke_type = thread_invoke_type_func; + th->invoke_arg.func.func = params->fn; + th->invoke_arg.func.arg = (void *)params->args; + break; + + default: + rb_bug("unreachable"); } th->priority = current_th->priority; @@ -860,13 +993,17 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *)) rb_native_mutex_initialize(&th->interrupt_lock); + RUBY_DEBUG_LOG("r:%u th:%p", rb_ractor_id(th->ractor), (void *)th); + + rb_ractor_living_threads_insert(th->ractor, th); + /* kick thread */ err = native_thread_create(th); if (err) { th->status = THREAD_KILLED; - rb_raise(rb_eThreadError, "can't create Thread: %s", strerror(err)); + rb_ractor_living_threads_remove(th->ractor, th); + rb_raise(rb_eThreadError, "can't create Thread: %s", strerror(err)); } - rb_vm_living_threads_insert(th->vm, th); return thval; } @@ -898,8 +1035,9 @@ thread_s_new(int argc, VALUE *argv, VALUE klass) rb_thread_t *th; VALUE thread = rb_thread_alloc(klass); - if (GET_VM()->main_thread->status == THREAD_KILLED) - rb_raise(rb_eThreadError, "can't alloc thread"); + if (GET_RACTOR()->threads.main->status == THREAD_KILLED) { + rb_raise(rb_eThreadError, "can't alloc thread"); + } rb_obj_call_init_kw(thread, argc, argv, RB_PASS_CALLED_KEYWORDS); th = rb_thread_ptr(thread); @@ -923,7 +1061,12 @@ thread_s_new(int argc, VALUE *argv, VALUE klass) static VALUE thread_start(VALUE klass, VALUE args) { - return thread_create_core(rb_thread_alloc(klass), args, 0); + struct thread_create_params params = { + .type = thread_invoke_type_proc, + .args = args, + .proc = rb_block_proc(), + }; + return thread_create_core(rb_thread_alloc(klass), ¶ms); } static VALUE @@ -958,19 +1101,43 @@ thread_initialize(VALUE thread, VALUE args) } } else { - return thread_create_core(thread, args, NULL); + struct thread_create_params params = { + .type = thread_invoke_type_proc, + .args = args, + .proc = rb_block_proc(), + }; + return thread_create_core(thread, ¶ms); } } VALUE rb_thread_create(VALUE (*fn)(void *), void *arg) { - return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn); + struct thread_create_params params = { + .type = thread_invoke_type_func, + .fn = fn, + .args = (VALUE)arg, + }; + return thread_create_core(rb_thread_alloc(rb_cThread), ¶ms); +} + +VALUE +rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc) +{ + struct thread_create_params params = { + .type = thread_invoke_type_ractor_proc, + .g = g, + .args = args, + .proc = proc, + }; + return thread_create_core(rb_thread_alloc(rb_cThread), ¶ms); } struct join_arg { - rb_thread_t *target, *waiting; + struct rb_waiting_list *waiter; + rb_thread_t *target; + VALUE timeout; rb_hrtime_t *limit; }; @@ -978,121 +1145,138 @@ static VALUE remove_from_join_list(VALUE arg) { struct join_arg *p = (struct join_arg *)arg; - rb_thread_t *target_th = p->target, *th = p->waiting; + rb_thread_t *target_thread = p->target; - if (target_th->status != THREAD_KILLED) { - rb_thread_list_t **p = &target_th->join_list; + if (target_thread->status != THREAD_KILLED) { + struct rb_waiting_list **join_list = &target_thread->join_list; - while (*p) { - if ((*p)->th == th) { - *p = (*p)->next; - break; - } - p = &(*p)->next; - } + while (*join_list) { + if (*join_list == p->waiter) { + *join_list = (*join_list)->next; + break; + } + + join_list = &(*join_list)->next; + } } return Qnil; } +static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double); + +static int +thread_finished(rb_thread_t *th) +{ + return th->status == THREAD_KILLED || th->value != Qundef; +} + static VALUE thread_join_sleep(VALUE arg) { struct join_arg *p = (struct join_arg *)arg; - rb_thread_t *target_th = p->target, *th = p->waiting; - rb_hrtime_t end = 0; + rb_thread_t *target_th = p->target, *th = p->waiter->thread; + rb_hrtime_t end = 0, *limit = p->limit; - if (p->limit) { - end = rb_hrtime_add(*p->limit, rb_hrtime_now()); + if (limit) { + end = rb_hrtime_add(*limit, rb_hrtime_now()); } - while (target_th->status != THREAD_KILLED) { - if (!p->limit) { - th->status = THREAD_STOPPED_FOREVER; - th->vm->sleeper++; - rb_check_deadlock(th->vm); - native_sleep(th, 0); - th->vm->sleeper--; - } - else { - if (hrtime_update_expire(p->limit, end)) { - thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n", - thread_id_str(target_th)); - return Qfalse; - } - th->status = THREAD_STOPPED; - native_sleep(th, p->limit); - } - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); - th->status = THREAD_RUNNABLE; - thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n", - thread_id_str(target_th), thread_status_name(target_th, TRUE)); + while (!thread_finished(target_th)) { + VALUE scheduler = rb_fiber_scheduler_current(); + + if (scheduler != Qnil) { + rb_fiber_scheduler_block(scheduler, target_th->self, p->timeout); + } + else if (!limit) { + th->status = THREAD_STOPPED_FOREVER; + rb_ractor_sleeper_threads_inc(th->ractor); + rb_check_deadlock(th->ractor); + native_sleep(th, 0); + rb_ractor_sleeper_threads_dec(th->ractor); + } + else { + if (hrtime_update_expire(limit, end)) { + thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n", + thread_id_str(target_th)); + return Qfalse; + } + th->status = THREAD_STOPPED; + native_sleep(th, limit); + } + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + th->status = THREAD_RUNNABLE; + thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n", + thread_id_str(target_th), thread_status_name(target_th, TRUE)); } return Qtrue; } static VALUE -thread_join(rb_thread_t *target_th, rb_hrtime_t *rel) +thread_join(rb_thread_t *target_th, VALUE timeout, rb_hrtime_t *limit) { - rb_thread_t *th = GET_THREAD(); - struct join_arg arg; + rb_execution_context_t *ec = GET_EC(); + rb_thread_t *th = ec->thread_ptr; + rb_fiber_t *fiber = ec->fiber_ptr; if (th == target_th) { - rb_raise(rb_eThreadError, "Target thread must not be current thread"); - } - if (GET_VM()->main_thread == target_th) { - rb_raise(rb_eThreadError, "Target thread must not be main thread"); + rb_raise(rb_eThreadError, "Target thread must not be current thread"); } - arg.target = target_th; - arg.waiting = th; - arg.limit = rel; + if (th->ractor->threads.main == target_th) { + rb_raise(rb_eThreadError, "Target thread must not be main thread"); + } thread_debug("thread_join (thid: %"PRI_THREAD_ID", status: %s)\n", - thread_id_str(target_th), thread_status_name(target_th, TRUE)); + thread_id_str(target_th), thread_status_name(target_th, TRUE)); if (target_th->status != THREAD_KILLED) { - rb_thread_list_t list; - list.next = target_th->join_list; - list.th = th; - target_th->join_list = &list; - if (!rb_ensure(thread_join_sleep, (VALUE)&arg, - remove_from_join_list, (VALUE)&arg)) { - return Qnil; - } + struct rb_waiting_list waiter; + waiter.next = target_th->join_list; + waiter.thread = th; + waiter.fiber = fiber; + target_th->join_list = &waiter; + + struct join_arg arg; + arg.waiter = &waiter; + arg.target = target_th; + arg.timeout = timeout; + arg.limit = limit; + + if (!rb_ensure(thread_join_sleep, (VALUE)&arg, remove_from_join_list, (VALUE)&arg)) { + return Qnil; + } } thread_debug("thread_join: success (thid: %"PRI_THREAD_ID", status: %s)\n", - thread_id_str(target_th), thread_status_name(target_th, TRUE)); + thread_id_str(target_th), thread_status_name(target_th, TRUE)); if (target_th->ec->errinfo != Qnil) { - VALUE err = target_th->ec->errinfo; - - if (FIXNUM_P(err)) { - switch (err) { - case INT2FIX(TAG_FATAL): - thread_debug("thread_join: terminated (thid: %"PRI_THREAD_ID", status: %s)\n", - thread_id_str(target_th), thread_status_name(target_th, TRUE)); - - /* OK. killed. */ - break; - default: - rb_bug("thread_join: Fixnum (%d) should not reach here.", FIX2INT(err)); - } - } - else if (THROW_DATA_P(target_th->ec->errinfo)) { - rb_bug("thread_join: THROW_DATA should not reach here."); - } - else { - /* normal exception */ - rb_exc_raise(err); - } + VALUE err = target_th->ec->errinfo; + + if (FIXNUM_P(err)) { + switch (err) { + case INT2FIX(TAG_FATAL): + thread_debug("thread_join: terminated (thid: %"PRI_THREAD_ID", status: %s)\n", + thread_id_str(target_th), thread_status_name(target_th, TRUE)); + + /* OK. killed. */ + break; + default: + rb_bug("thread_join: Fixnum (%d) should not reach here.", FIX2INT(err)); + } + } + else if (THROW_DATA_P(target_th->ec->errinfo)) { + rb_bug("thread_join: THROW_DATA should not reach here."); + } + else { + /* normal exception */ + rb_exc_raise(err); + } } return target_th->self; } -static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double); - /* * call-seq: * thr.join -> thr @@ -1135,25 +1319,30 @@ static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double); static VALUE thread_join_m(int argc, VALUE *argv, VALUE self) { - VALUE limit; - rb_hrtime_t rel, *to = 0; + VALUE timeout = Qnil; + rb_hrtime_t rel = 0, *limit = 0; + if (rb_check_arity(argc, 0, 1)) { + timeout = argv[0]; + } + + // Convert the timeout eagerly, so it's always converted and deterministic /* * This supports INFINITY and negative values, so we can't use * rb_time_interval right now... */ - if (!rb_check_arity(argc, 0, 1) || NIL_P(argv[0])) { + if (NIL_P(timeout)) { /* unlimited */ } - else if (FIXNUM_P(limit = argv[0])) { - rel = rb_sec2hrtime(NUM2TIMET(limit)); - to = &rel; + else if (FIXNUM_P(timeout)) { + rel = rb_sec2hrtime(NUM2TIMET(timeout)); + limit = &rel; } else { - to = double2hrtime(&rel, rb_num2dbl(limit)); + limit = double2hrtime(&rel, rb_num2dbl(timeout)); } - return thread_join(rb_thread_ptr(self), to); + return thread_join(rb_thread_ptr(self), timeout, limit); } /* @@ -1174,7 +1363,7 @@ static VALUE thread_value(VALUE self) { rb_thread_t *th = rb_thread_ptr(self); - thread_join(th, 0); + thread_join(th, Qnil, 0); return th->value; } @@ -1192,11 +1381,21 @@ thread_value(VALUE self) #define TIMESPEC_SEC_MAX TIMET_MAX #define TIMESPEC_SEC_MIN TIMET_MIN +COMPILER_WARNING_PUSH +#if __has_warning("-Wimplicit-int-float-conversion") +COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion) +#elif defined(_MSC_VER) +/* C4305: 'initializing': truncation from '__int64' to 'const double' */ +COMPILER_WARNING_IGNORED(4305) +#endif +static const double TIMESPEC_SEC_MAX_as_double = TIMESPEC_SEC_MAX; +COMPILER_WARNING_POP + static rb_hrtime_t * double2hrtime(rb_hrtime_t *hrt, double d) { /* assume timespec.tv_sec has same signedness as time_t */ - const double TIMESPEC_SEC_MAX_PLUS_ONE = TIMET_MAX_PLUS_ONE; + const double TIMESPEC_SEC_MAX_PLUS_ONE = 2.0 * (TIMESPEC_SEC_MAX_as_double / 2.0 + 1.0); if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) { return NULL; @@ -1246,12 +1445,12 @@ sleep_forever(rb_thread_t *th, unsigned int fl) RUBY_VM_CHECK_INTS_BLOCKING(th->ec); while (th->status == status) { if (fl & SLEEP_DEADLOCKABLE) { - th->vm->sleeper++; - rb_check_deadlock(th->vm); + rb_ractor_sleeper_threads_inc(th->ractor); + rb_check_deadlock(th->ractor); } native_sleep(th, 0); if (fl & SLEEP_DEADLOCKABLE) { - th->vm->sleeper--; + rb_ractor_sleeper_threads_dec(th->ractor); } woke = vm_check_ints_blocking(th->ec); if (woke && !(fl & SLEEP_SPURIOUS_CHECK)) @@ -1290,7 +1489,7 @@ hrtime_update_expire(rb_hrtime_t *timeout, const rb_hrtime_t end) } COMPILER_WARNING_POP -static void +static int sleep_hrtime(rb_thread_t *th, rb_hrtime_t rel, unsigned int fl) { enum rb_thread_status prev_status = th->status; @@ -1306,8 +1505,10 @@ sleep_hrtime(rb_thread_t *th, rb_hrtime_t rel, unsigned int fl) break; if (hrtime_update_expire(&rel, end)) break; + woke = 1; } th->status = prev_status; + return woke; } void @@ -1337,10 +1538,16 @@ rb_thread_sleep_interruptible(void) } static void -rb_thread_sleep_deadly_allow_spurious_wakeup(void) +rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker) { - thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n"); - sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE); + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + rb_fiber_scheduler_block(scheduler, blocker, Qnil); + } + else { + thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n"); + sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE); + } } void @@ -1397,8 +1604,8 @@ rb_thread_schedule_limits(uint32_t limits_us) if (th->running_time_us >= limits_us) { thread_debug("rb_thread_schedule/switch start\n"); RB_GC_SAVE_MACHINE_CONTEXT(th); - gvl_yield(th->vm, th); - rb_thread_set_current(th); + gvl_yield(rb_ractor_gvl(th->ractor), th); + rb_ractor_thread_switch(th->ractor, th); thread_debug("rb_thread_schedule/switch done\n"); } } @@ -1421,9 +1628,10 @@ blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region, if (unblock_function_set(th, ubf, arg, fail_if_interrupted)) { th->blocking_region_buffer = region; th->status = THREAD_STOPPED; + rb_ractor_blocking_threads_inc(th->ractor, __FILE__, __LINE__); thread_debug("enter blocking region (%p)\n", (void *)th); RB_GC_SAVE_MACHINE_CONTEXT(th); - gvl_release(th->vm); + gvl_release(rb_ractor_gvl(th->ractor)); return TRUE; } else { @@ -1439,10 +1647,12 @@ blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region) /* entry to ubf_list impossible at this point, so unregister is safe: */ unregister_ubf_list(th); - gvl_acquire(th->vm, th); - rb_thread_set_current(th); + gvl_acquire(rb_ractor_gvl(th->ractor), th); + rb_ractor_thread_switch(th->ractor, th); + thread_debug("leave blocking region (%p)\n", (void *)th); th->blocking_region_buffer = 0; + rb_ractor_blocking_threads_dec(th->ractor, __FILE__, __LINE__); if (th->status == THREAD_STOPPED) { th->status = region->prev_status; } @@ -1456,16 +1666,18 @@ rb_nogvl(void *(*func)(void *), void *data1, void *val = 0; rb_execution_context_t *ec = GET_EC(); rb_thread_t *th = rb_ec_thread_ptr(ec); + rb_vm_t *vm = rb_ec_vm_ptr(ec); + bool is_main_thread = vm->ractor.main_thread == th; int saved_errno = 0; VALUE ubf_th = Qfalse; - if (ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) { + if ((ubf == RUBY_UBF_IO) || (ubf == RUBY_UBF_PROCESS)) { ubf = ubf_select; data2 = th; } - else if (ubf && vm_living_thread_num(th->vm) == 1) { + else if (ubf && rb_ractor_living_thread_num(th->ractor) == 1 && is_main_thread) { if (flags & RB_NOGVL_UBF_ASYNC_SAFE) { - th->vm->ubf_async_safe = 1; + vm->ubf_async_safe = 1; } else { ubf_th = rb_thread_start_unblock_thread(); @@ -1477,7 +1689,7 @@ rb_nogvl(void *(*func)(void *), void *data1, saved_errno = errno; }, ubf, data2, flags & RB_NOGVL_INTR_FAIL); - th->vm->ubf_async_safe = 0; + if (is_main_thread) vm->ubf_async_safe = 0; if ((flags & RB_NOGVL_INTR_FAIL) == 0) { RUBY_VM_CHECK_INTS_BLOCKING(ec); @@ -1598,18 +1810,24 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd) rb_execution_context_t * volatile ec = GET_EC(); volatile int saved_errno = 0; enum ruby_tag_type state; - struct waiting_fd wfd; - wfd.fd = fd; - wfd.th = rb_ec_thread_ptr(ec); - list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &wfd.wfd_node); + struct waiting_fd waiting_fd = { + .fd = fd, + .th = rb_ec_thread_ptr(ec) + }; + + RB_VM_LOCK_ENTER(); + { + list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &waiting_fd.wfd_node); + } + RB_VM_LOCK_LEAVE(); EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - BLOCKING_REGION(wfd.th, { - val = func(data1); - saved_errno = errno; - }, ubf_select, wfd.th, FALSE); + BLOCKING_REGION(waiting_fd.th, { + val = func(data1); + saved_errno = errno; + }, ubf_select, waiting_fd.th, FALSE); } EC_POP_TAG(); @@ -1617,10 +1835,14 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd) * must be deleted before jump * this will delete either from waiting_fds or on-stack LIST_HEAD(busy) */ - list_del(&wfd.wfd_node); + RB_VM_LOCK_ENTER(); + { + list_del(&waiting_fd.wfd_node); + } + RB_VM_LOCK_LEAVE(); if (state) { - EC_JUMP_TAG(ec, state); + EC_JUMP_TAG(ec, state); } /* TODO: check func() */ RUBY_VM_CHECK_INTS_BLOCKING(ec); @@ -1671,7 +1893,7 @@ rb_thread_call_with_gvl(void *(*func)(void *), void *data1) * because this thread is not Ruby's thread. * What should we do? */ - + bp(); fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n"); exit(EXIT_FAILURE); } @@ -2015,6 +2237,8 @@ handle_interrupt_arg_check_i(VALUE key, VALUE val, VALUE args) * # all exceptions inherited from Exception are prohibited. * } * + * For handling all interrupts, use +Object+ and not +Exception+ + * as the ExceptionClass, as kill/terminate interrupts are not handled by +Exception+. */ static VALUE rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) @@ -2089,12 +2313,7 @@ rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread) if (!rb_obj_is_kind_of(err, rb_cModule)) { rb_raise(rb_eTypeError, "class or module required for rescue clause"); } - if (rb_threadptr_pending_interrupt_include_p(target_th, err)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_threadptr_pending_interrupt_include_p(target_th, err)); } else { return Qtrue; @@ -2204,18 +2423,25 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) int timer_interrupt; int pending_interrupt; int trap_interrupt; + int terminate_interrupt; timer_interrupt = interrupt & TIMER_INTERRUPT_MASK; pending_interrupt = interrupt & PENDING_INTERRUPT_MASK; postponed_job_interrupt = interrupt & POSTPONED_JOB_INTERRUPT_MASK; trap_interrupt = interrupt & TRAP_INTERRUPT_MASK; + terminate_interrupt = interrupt & TERMINATE_INTERRUPT_MASK; // request from other ractors + + if (interrupt & VM_BARRIER_INTERRUPT_MASK) { + RB_VM_LOCK_ENTER(); + RB_VM_LOCK_LEAVE(); + } if (postponed_job_interrupt) { rb_postponed_job_flush(th->vm); } /* signal handling */ - if (trap_interrupt && (th == th->vm->main_thread)) { + if (trap_interrupt && (th == th->vm->ractor.main_thread)) { enum rb_thread_status prev_status = th->status; int sigwait_fd = rb_sigwait_fd_get(th); @@ -2244,7 +2470,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) else if (err == eKillSignal /* Thread#kill received */ || err == eTerminateSignal /* Terminate thread */ || err == INT2FIX(TAG_FATAL) /* Thread.exit etc. */ ) { - rb_threadptr_to_kill(th); + terminate_interrupt = 1; } else { if (err == th->vm->special_exceptions[ruby_error_stream_closed]) { @@ -2259,7 +2485,11 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) } } - if (timer_interrupt) { + if (terminate_interrupt) { + rb_threadptr_to_kill(th); + } + + if (timer_interrupt) { uint32_t limits_us = TIME_QUANTUM_USEC; if (th->priority > 0) @@ -2327,7 +2557,7 @@ rb_threadptr_signal_raise(rb_thread_t *th, int sig) argv[0] = rb_eSignal; argv[1] = INT2FIX(sig); - rb_threadptr_raise(th->vm->main_thread, 2, argv); + rb_threadptr_raise(th->vm->ractor.main_thread, 2, argv); } void @@ -2337,7 +2567,9 @@ rb_threadptr_signal_exit(rb_thread_t *th) argv[0] = rb_eSystemExit; argv[1] = rb_str_new2("exit"); - rb_threadptr_raise(th->vm->main_thread, 2, argv); + + // TODO: check signal raise deliverly + rb_threadptr_raise(th->vm->ractor.main_thread, 2, argv); } int @@ -2366,19 +2598,24 @@ rb_notify_fd_close(int fd, struct list_head *busy) rb_vm_t *vm = GET_THREAD()->vm; struct waiting_fd *wfd = 0, *next; - list_for_each_safe(&vm->waiting_fds, wfd, next, wfd_node) { - if (wfd->fd == fd) { - rb_thread_t *th = wfd->th; - VALUE err; + RB_VM_LOCK_ENTER(); + { + list_for_each_safe(&vm->waiting_fds, wfd, next, wfd_node) { + if (wfd->fd == fd) { + rb_thread_t *th = wfd->th; + VALUE err; - list_del(&wfd->wfd_node); - list_add(busy, &wfd->wfd_node); + list_del(&wfd->wfd_node); + list_add(busy, &wfd->wfd_node); - err = th->vm->special_exceptions[ruby_error_stream_closed]; - rb_threadptr_pending_interrupt_enque(th, err); - rb_threadptr_interrupt(th); - } + err = th->vm->special_exceptions[ruby_error_stream_closed]; + rb_threadptr_pending_interrupt_enque(th, err); + rb_threadptr_interrupt(th); + } + } } + RB_VM_LOCK_LEAVE(); + return !list_empty(busy); } @@ -2450,7 +2687,7 @@ rb_thread_kill(VALUE thread) if (th->to_kill || th->status == THREAD_KILLED) { return thread; } - if (th == th->vm->main_thread) { + if (th == th->vm->ractor.main_thread) { rb_exit(EXIT_SUCCESS); } @@ -2629,21 +2866,8 @@ thread_stop(VALUE _) VALUE rb_thread_list(void) { - VALUE ary = rb_ary_new(); - rb_vm_t *vm = GET_THREAD()->vm; - rb_thread_t *th = 0; - - list_for_each(&vm->living_threads, th, vmlt_node) { - switch (th->status) { - case THREAD_RUNNABLE: - case THREAD_STOPPED: - case THREAD_STOPPED_FOREVER: - rb_ary_push(ary, th->self); - default: - break; - } - } - return ary; + // TODO + return rb_ractor_thread_list(GET_RACTOR()); } /* @@ -2696,7 +2920,7 @@ thread_s_current(VALUE klass) VALUE rb_thread_main(void) { - return GET_THREAD()->vm->main_thread->self; + return GET_RACTOR()->threads.main->self; } /* @@ -2736,7 +2960,7 @@ rb_thread_s_main(VALUE klass) static VALUE rb_thread_s_abort_exc(VALUE _) { - return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse; + return RBOOL(GET_THREAD()->vm->thread_abort_on_exception); } @@ -2796,7 +3020,7 @@ rb_thread_s_abort_exc_set(VALUE self, VALUE val) static VALUE rb_thread_abort_exc(VALUE thread) { - return rb_thread_ptr(thread)->abort_on_exception ? Qtrue : Qfalse; + return RBOOL(rb_thread_ptr(thread)->abort_on_exception); } @@ -2860,13 +3084,13 @@ rb_thread_abort_exc_set(VALUE thread, VALUE val) * * There is also an instance level method to set this for a specific thread, * see #report_on_exception=. - * + * */ static VALUE rb_thread_s_report_exc(VALUE _) { - return GET_THREAD()->vm->thread_report_on_exception ? Qtrue : Qfalse; + return RBOOL(GET_THREAD()->vm->thread_report_on_exception); } @@ -2908,6 +3132,52 @@ rb_thread_s_report_exc_set(VALUE self, VALUE val) } +/* + * call-seq: + * Thread.ignore_deadlock -> true or false + * + * Returns the status of the global ``ignore deadlock'' condition. + * The default is +false+, so that deadlock conditions are not ignored. + * + * See also ::ignore_deadlock=. + * + */ + +static VALUE +rb_thread_s_ignore_deadlock(VALUE _) +{ + return RBOOL(GET_THREAD()->vm->thread_ignore_deadlock); +} + + +/* + * call-seq: + * Thread.ignore_deadlock = boolean -> true or false + * + * Returns the new state. + * When set to +true+, the VM will not check for deadlock conditions. + * It is only useful to set this if your application can break a + * deadlock condition via some other means, such as a signal. + * + * Thread.ignore_deadlock = true + * queue = Thread::Queue.new + * + * trap(:SIGUSR1){queue.push "Received signal"} + * + * # raises fatal error unless ignoring deadlock + * puts queue.pop + * + * See also ::ignore_deadlock. + */ + +static VALUE +rb_thread_s_ignore_deadlock_set(VALUE self, VALUE val) +{ + GET_THREAD()->vm->thread_ignore_deadlock = RTEST(val); + return val; +} + + /* * call-seq: * thr.report_on_exception -> true or false @@ -2927,7 +3197,7 @@ rb_thread_s_report_exc_set(VALUE self, VALUE val) static VALUE rb_thread_report_exc(VALUE thread) { - return rb_thread_ptr(thread)->report_on_exception ? Qtrue : Qfalse; + return RBOOL(rb_thread_ptr(thread)->report_on_exception); } @@ -2956,8 +3226,7 @@ rb_thread_report_exc_set(VALUE thread, VALUE val) * call-seq: * thr.group -> thgrp or nil * - * Returns the ThreadGroup which contains the given thread, or returns +nil+ - * if +thr+ is not a member of any group. + * Returns the ThreadGroup which contains the given thread. * * Thread.main.group #=> # */ @@ -2965,8 +3234,7 @@ rb_thread_report_exc_set(VALUE thread, VALUE val) VALUE rb_thread_group(VALUE thread) { - VALUE group = rb_thread_ptr(thread)->thgroup; - return group == 0 ? Qnil : group; + return rb_thread_ptr(thread)->thgroup; } static const char * @@ -3061,12 +3329,7 @@ rb_thread_status(VALUE thread) static VALUE rb_thread_alive_p(VALUE thread) { - if (rb_threadptr_dead(rb_thread_ptr(thread))) { - return Qfalse; - } - else { - return Qtrue; - } + return RBOOL(!thread_finished(rb_thread_ptr(thread))); } /* @@ -3091,30 +3354,7 @@ rb_thread_stop_p(VALUE thread) if (rb_threadptr_dead(th)) { return Qtrue; } - else if (th->status == THREAD_STOPPED || - th->status == THREAD_STOPPED_FOREVER) { - return Qtrue; - } - else { - return Qfalse; - } -} - -/* - * call-seq: - * thr.safe_level -> integer - * - * Returns the safe level. - * - * This method is obsolete because $SAFE is a process global state. - * Simply check $SAFE. - */ - -static VALUE -rb_thread_safe_level(VALUE thread) -{ - rb_warn("Thread#safe_level will be removed in Ruby 3.0"); - return UINT2NUM(GET_VM()->safe_level_); + return RBOOL(th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER); } /* @@ -3160,6 +3400,40 @@ rb_thread_setname(VALUE thread, VALUE name) return name; } +#if USE_NATIVE_THREAD_NATIVE_THREAD_ID +/* + * call-seq: + * thr.native_thread_id -> integer + * + * Return the native thread ID which is used by the Ruby thread. + * + * The ID depends on the OS. (not POSIX thread ID returned by pthread_self(3)) + * * On Linux it is TID returned by gettid(2). + * * On macOS it is the system-wide unique integral ID of thread returned + * by pthread_threadid_np(3). + * * On FreeBSD it is the unique integral ID of the thread returned by + * pthread_getthreadid_np(3). + * * On Windows it is the thread identifier returned by GetThreadId(). + * * On other platforms, it raises NotImplementedError. + * + * NOTE: + * If the thread is not associated yet or already deassociated with a native + * thread, it returns _nil_. + * If the Ruby implementation uses M:N thread model, the ID may change + * depending on the timing. + */ + +static VALUE +rb_thread_native_thread_id(VALUE thread) +{ + rb_thread_t *target_th = rb_thread_ptr(thread); + if (rb_threadptr_dead(target_th)) return Qnil; + return native_thread_native_thread_id(target_th); +} +#else +# define rb_thread_native_thread_id rb_f_notimplement +#endif + /* * call-seq: * thr.to_s -> string @@ -3183,7 +3457,6 @@ rb_thread_to_s(VALUE thread) if ((loc = threadptr_invoke_proc_location(target_th)) != Qnil) { rb_str_catf(str, " %"PRIsVALUE":%"PRIsVALUE, RARRAY_AREF(loc, 0), RARRAY_AREF(loc, 1)); - rb_gc_force_recycle(loc); } rb_str_catf(str, " %s>", status); @@ -3191,7 +3464,7 @@ rb_thread_to_s(VALUE thread) } /* variables for recursive traversals */ -static ID recursive_key; +#define recursive_key id__recursive_key__ static VALUE threadptr_local_aref(rb_thread_t *th, ID id) @@ -3200,11 +3473,11 @@ threadptr_local_aref(rb_thread_t *th, ID id) return th->ec->local_storage_recursive_hash; } else { - st_data_t val; - st_table *local_storage = th->ec->local_storage; + VALUE val; + struct rb_id_table *local_storage = th->ec->local_storage; - if (local_storage != NULL && st_lookup(local_storage, id, &val)) { - return (VALUE)val; + if (local_storage != NULL && rb_id_table_lookup(local_storage, id, &val)) { + return val; } else { return Qnil; @@ -3321,7 +3594,7 @@ rb_thread_fetch(int argc, VALUE *argv, VALUE self) return target_th->ec->local_storage_recursive_hash; } else if (id && target_th->ec->local_storage && - st_lookup(target_th->ec->local_storage, id, &val)) { + rb_id_table_lookup(target_th->ec->local_storage, id, &val)) { return val; } else if (block_given) { @@ -3343,18 +3616,18 @@ threadptr_local_aset(rb_thread_t *th, ID id, VALUE val) return val; } else { - st_table *local_storage = th->ec->local_storage; + struct rb_id_table *local_storage = th->ec->local_storage; if (NIL_P(val)) { if (!local_storage) return Qnil; - st_delete_wrap(local_storage, id); + rb_id_table_delete(local_storage, id); return Qnil; } else { if (local_storage == NULL) { - th->ec->local_storage = local_storage = st_init_numtable(); + th->ec->local_storage = local_storage = rb_id_table_create(0); } - st_insert(local_storage, id, val); + rb_id_table_insert(local_storage, id, val); return val; } } @@ -3439,7 +3712,7 @@ rb_thread_variable_get(VALUE thread, VALUE key) */ static VALUE -rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) +rb_thread_variable_set(VALUE thread, VALUE key, VALUE val) { VALUE locals; @@ -3448,7 +3721,7 @@ rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) } locals = rb_thread_local_storage(thread); - return rb_hash_aset(locals, rb_to_symbol(id), val); + return rb_hash_aset(locals, rb_to_symbol(key), val); } /* @@ -3467,31 +3740,28 @@ rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) static VALUE rb_thread_key_p(VALUE self, VALUE key) { + VALUE val; ID id = rb_check_id(&key); - st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; + struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage; if (!id || local_storage == NULL) { return Qfalse; } - else if (st_is_member(local_storage, id)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_id_table_lookup(local_storage, id, &val)); } -static int -thread_keys_i(ID key, VALUE value, VALUE ary) +static enum rb_id_table_iterator_result +thread_keys_i(ID key, VALUE value, void *ary) { - rb_ary_push(ary, ID2SYM(key)); - return ST_CONTINUE; + rb_ary_push((VALUE)ary, ID2SYM(key)); + return ID_TABLE_CONTINUE; } int rb_thread_alone(void) { - return vm_living_thread_num(GET_VM()) == 1; + // TODO + return rb_ractor_living_thread_num(GET_RACTOR()) == 1; } /* @@ -3511,11 +3781,11 @@ rb_thread_alone(void) static VALUE rb_thread_keys(VALUE self) { - st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; + struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage; VALUE ary = rb_ary_new(); if (local_storage) { - st_foreach(local_storage, thread_keys_i, ary); + rb_id_table_foreach(local_storage, thread_keys_i, (void *)ary); } return ary; } @@ -3580,23 +3850,13 @@ static VALUE rb_thread_variable_p(VALUE thread, VALUE key) { VALUE locals; - ID id = rb_check_id(&key); - - if (!id) return Qfalse; if (LIKELY(!THREAD_LOCAL_STORAGE_INITIALISED_P(thread))) { return Qfalse; } locals = rb_thread_local_storage(thread); - if (rb_hash_lookup(locals, ID2SYM(id)) != Qnil) { - return Qtrue; - } - else { - return Qfalse; - } - - return Qfalse; + return RBOOL(rb_hash_lookup(locals, rb_to_symbol(key)) != Qnil); } /* @@ -3965,6 +4225,9 @@ sigwait_timeout(rb_thread_t *th, int sigwait_fd, const rb_hrtime_t *orig, return orig; } +#define sigwait_signals_fd(result, cond, sigwait_fd) \ + (result > 0 && (cond) ? (result--, (sigwait_fd)) : -1) + static VALUE do_select(VALUE p) { @@ -4000,12 +4263,10 @@ do_select(VALUE p) }, set->sigwait_fd >= 0 ? ubf_sigwait : ubf_select, set->th, TRUE); if (set->sigwait_fd >= 0) { - if (result > 0 && rb_fd_isset(set->sigwait_fd, set->rset)) { - result--; - (void)check_signals_nogvl(set->th, set->sigwait_fd); - } else { - (void)check_signals_nogvl(set->th, -1); - } + int fd = sigwait_signals_fd(result, + rb_fd_isset(set->sigwait_fd, set->rset), + set->sigwait_fd); + (void)check_signals_nogvl(set->th, fd); } RUBY_VM_CHECK_INTS_BLOCKING(set->th->ec); /* may raise */ @@ -4018,39 +4279,6 @@ do_select(VALUE p) return (VALUE)result; } -static void -rb_thread_wait_fd_rw(int fd, int read) -{ - int result = 0; - int events = read ? RB_WAITFD_IN : RB_WAITFD_OUT; - - thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write"); - - if (fd < 0) { - rb_raise(rb_eIOError, "closed stream"); - } - - result = rb_wait_for_single_fd(fd, events, NULL); - if (result < 0) { - rb_sys_fail(0); - } - - thread_debug("rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ? "read" : "write"); -} - -void -rb_thread_wait_fd(int fd) -{ - rb_thread_wait_fd_rw(fd, 1); -} - -int -rb_thread_fd_writable(int fd) -{ - rb_thread_wait_fd_rw(fd, 0); - return TRUE; -} - static rb_fdset_t * init_set_fd(int fd, rb_fdset_t *fds) { @@ -4130,22 +4358,29 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * * returns a mask of events */ int -rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) +rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout) { struct pollfd fds[2]; - int result = 0, lerrno; - rb_hrtime_t *to, rel, end = 0; + int result = 0; int drained; nfds_t nfds; rb_unblock_function_t *ubf; struct waiting_fd wfd; int state; + volatile int lerrno; wfd.th = GET_THREAD(); wfd.fd = fd; - list_add(&wfd.th->vm->waiting_fds, &wfd.wfd_node); + + RB_VM_LOCK_ENTER(); + { + list_add(&wfd.th->vm->waiting_fds, &wfd.wfd_node); + } + RB_VM_LOCK_LEAVE(); + EC_PUSH_TAG(wfd.th->ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { + rb_hrtime_t *to, rel, end = 0; RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec); timeout_prepare(&to, &rel, &end, timeout); fds[0].fd = fd; @@ -4178,12 +4413,8 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) }, ubf, wfd.th, TRUE); if (fds[1].fd >= 0) { - if (result > 0 && fds[1].revents) { - result--; - (void)check_signals_nogvl(wfd.th, fds[1].fd); - } else { - (void)check_signals_nogvl(wfd.th, -1); - } + int fd1 = sigwait_signals_fd(result, fds[1].revents, fds[1].fd); + (void)check_signals_nogvl(wfd.th, fd1); rb_sigwait_fd_put(wfd.th, fds[1].fd); rb_sigwait_fd_migrate(wfd.th->vm); } @@ -4191,7 +4422,13 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) } while (wait_retryable(&result, lerrno, to, end)); } EC_POP_TAG(); - list_del(&wfd.wfd_node); + + RB_VM_LOCK_ENTER(); + { + list_del(&wfd.wfd_node); + } + RB_VM_LOCK_LEAVE(); + if (state) { EC_JUMP_TAG(wfd.th->ec, state); } @@ -4273,7 +4510,7 @@ select_single_cleanup(VALUE ptr) } int -rb_wait_for_single_fd(int fd, int events, struct timeval *tv) +rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout) { rb_fdset_t rfds, wfds, efds; struct select_args args; @@ -4284,11 +4521,16 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv) args.read = (events & RB_WAITFD_IN) ? init_set_fd(fd, &rfds) : NULL; args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL; args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL; - args.tv = tv; + args.tv = timeout; args.wfd.fd = fd; args.wfd.th = GET_THREAD(); - list_add(&args.wfd.th->vm->waiting_fds, &args.wfd.wfd_node); + RB_VM_LOCK_ENTER(); + { + list_add(&args.wfd.th->vm->waiting_fds, &args.wfd.wfd_node); + } + RB_VM_LOCK_LEAVE(); + r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr); if (r == -1) errno = args.as.error; @@ -4324,17 +4566,6 @@ rb_threadptr_check_signal(rb_thread_t *mth) } } -static void -timer_thread_function(void) -{ - volatile rb_execution_context_t *ec; - - /* for time slice */ - ec = ACCESS_ONCE(rb_execution_context_t *, - ruby_current_execution_context_ptr); - if (ec) RUBY_VM_SET_TIMER_INTERRUPT(ec); -} - static void async_bug_fd(const char *mesg, int errno_arg, int fd) { @@ -4403,11 +4634,13 @@ check_signals_nogvl(rb_thread_t *th, int sigwait_fd) ubf_wakeup_all_threads(); ruby_sigchld_handler(vm); if (rb_signal_buff_size()) { - if (th == vm->main_thread) + if (th == vm->ractor.main_thread) { /* no need to lock + wakeup if already in main thread */ RUBY_VM_SET_TRAP_INTERRUPT(th->ec); - else - threadptr_trap_interrupt(vm->main_thread); + } + else { + threadptr_trap_interrupt(vm->ractor.main_thread); + } ret = TRUE; /* for SIGCHLD_LOSSY && rb_sigwait_sleep */ } return ret; @@ -4474,21 +4707,30 @@ rb_clear_coverages(void) } #if defined(HAVE_WORKING_FORK) + static void rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const rb_thread_t *)) { rb_thread_t *i = 0; rb_vm_t *vm = th->vm; - vm->main_thread = th; + rb_ractor_t *r = th->ractor; + vm->ractor.main_ractor = r; + vm->ractor.main_thread = th; + r->threads.main = th; + r->status_ = ractor_created; - gvl_atfork(th->vm); + gvl_atfork(rb_ractor_gvl(th->ractor)); ubf_list_atfork(); - list_for_each(&vm->living_threads, i, vmlt_node) { - atfork(i, th); + // OK. Only this thread accesses: + list_for_each(&vm->ractor.set, r, vmlr_node) { + list_for_each(&r->threads.set, i, lt_node) { + atfork(i, th); + } } rb_vm_living_threads_init(vm); - rb_vm_living_threads_insert(vm, th); + + rb_ractor_atfork(vm, th); /* may be held by MJIT threads in parent */ rb_native_mutex_initialize(&vm->waitpid_lock); @@ -4498,9 +4740,11 @@ rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const r rb_native_mutex_initialize(&th->interrupt_lock); vm->fork_gen++; - - vm->sleeper = 0; + rb_ractor_sleeper_threads_clear(th->ractor); rb_clear_coverages(); + + VM_ASSERT(vm->ractor.blocking_cnt == 0); + VM_ASSERT(vm->ractor.cnt == 1); } static void @@ -4568,7 +4812,7 @@ thgroup_memsize(const void *ptr) static const rb_data_type_t thgroup_data_type = { "thgroup", - {NULL, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,}, + {0, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -4617,11 +4861,11 @@ static VALUE thgroup_list(VALUE group) { VALUE ary = rb_ary_new(); - rb_vm_t *vm = GET_THREAD()->vm; rb_thread_t *th = 0; + rb_ractor_t *r = GET_RACTOR(); - list_for_each(&vm->living_threads, th, vmlt_node) { - if (th->thgroup == group) { + list_for_each(&r->threads.set, th, lt_node) { + if (th->thgroup == group) { rb_ary_push(ary, th->self); } } @@ -4670,9 +4914,7 @@ thgroup_enclosed_p(VALUE group) struct thgroup *data; TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data); - if (data->enclosed) - return Qtrue; - return Qfalse; + return RBOOL(data->enclosed); } @@ -4716,10 +4958,6 @@ thgroup_add(VALUE group, VALUE thread) rb_raise(rb_eThreadError, "can't move to the enclosed thread group"); } - if (!target_th->thgroup) { - return Qnil; - } - if (OBJ_FROZEN(target_th->thgroup)) { rb_raise(rb_eThreadError, "can't move from the frozen thread group"); } @@ -4810,7 +5048,7 @@ rb_thread_shield_wait(VALUE self) if (!mutex) return Qfalse; m = mutex_ptr(mutex); - if (m->th == GET_THREAD()) return Qnil; + if (m->fiber == GET_EC()->fiber_ptr) return Qnil; rb_thread_shield_waiting_inc(self); rb_mutex_lock(mutex); rb_thread_shield_waiting_dec(self); @@ -4836,7 +5074,7 @@ rb_thread_shield_release(VALUE self) { VALUE mutex = thread_shield_get_mutex(self); rb_mutex_unlock(mutex); - return rb_thread_shield_waiting(self) > 0 ? Qtrue : Qfalse; + return RBOOL(rb_thread_shield_waiting(self) > 0); } /* @@ -4848,7 +5086,7 @@ rb_thread_shield_destroy(VALUE self) VALUE mutex = thread_shield_get_mutex(self); DATA_PTR(self) = 0; rb_mutex_unlock(mutex); - return rb_thread_shield_waiting(self) > 0 ? Qtrue : Qfalse; + return RBOOL(rb_thread_shield_waiting(self) > 0); } static VALUE @@ -4893,7 +5131,7 @@ recursive_list_access(VALUE sym) } /* - * Returns Qtrue iff obj (or the pair ) is already + * Returns Qtrue if and only if obj (or the pair ) is already * in the recursion list. * Assumes the recursion list is valid. */ @@ -4904,7 +5142,7 @@ recursive_check(VALUE list, VALUE obj, VALUE paired_obj_id) #if SIZEOF_LONG == SIZEOF_VOIDP #define OBJ_ID_EQL(obj_id, other) ((obj_id) == (other)) #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - #define OBJ_ID_EQL(obj_id, other) (RB_TYPE_P((obj_id), T_BIGNUM) ? \ + #define OBJ_ID_EQL(obj_id, other) (RB_BIGNUM_TYPE_P((obj_id)) ? \ rb_big_eql((obj_id), (other)) : ((obj_id) == (other))) #endif @@ -5053,10 +5291,7 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE } EC_POP_TAG(); if (!recursive_pop(p.list, p.obj, p.pairid)) { - invalid: - rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list " - "for %+"PRIsVALUE" in %+"PRIsVALUE, - sym, rb_thread_current()); + goto invalid; } if (state != TAG_NONE) EC_JUMP_TAG(GET_EC(), state); result = ret; @@ -5064,6 +5299,12 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE } *(volatile struct exec_recursive_params *)&p; return result; + + invalid: + rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list " + "for %+"PRIsVALUE" in %+"PRIsVALUE, + sym, rb_thread_current()); + UNREACHABLE_RETURN(Qundef); } /* @@ -5114,7 +5355,7 @@ rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VAL /* * call-seq: - * thread.backtrace -> array + * thread.backtrace -> array or nil * * Returns the current backtrace of the target thread. * @@ -5143,6 +5384,16 @@ rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval) return rb_vm_thread_backtrace_locations(argc, argv, thval); } +void +Init_Thread_Mutex(void) +{ + rb_thread_t *th = GET_THREAD(); + + rb_native_mutex_initialize(&th->vm->waitpid_lock); + rb_native_mutex_initialize(&th->vm->workqueue_lock); + rb_native_mutex_initialize(&th->interrupt_lock); +} + /* * Document-class: ThreadError * @@ -5161,15 +5412,12 @@ rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval) void Init_Thread(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - VALUE cThGroup; rb_thread_t *th = GET_THREAD(); - sym_never = ID2SYM(rb_intern("never")); - sym_immediate = ID2SYM(rb_intern("immediate")); - sym_on_blocking = ID2SYM(rb_intern("on_blocking")); + sym_never = ID2SYM(rb_intern_const("never")); + sym_immediate = ID2SYM(rb_intern_const("immediate")); + sym_on_blocking = ID2SYM(rb_intern_const("on_blocking")); rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1); rb_define_singleton_method(rb_cThread, "start", thread_start, -2); @@ -5185,6 +5433,8 @@ Init_Thread(void) rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1); rb_define_singleton_method(rb_cThread, "report_on_exception", rb_thread_s_report_exc, 0); rb_define_singleton_method(rb_cThread, "report_on_exception=", rb_thread_s_report_exc_set, 1); + rb_define_singleton_method(rb_cThread, "ignore_deadlock", rb_thread_s_ignore_deadlock, 0); + rb_define_singleton_method(rb_cThread, "ignore_deadlock=", rb_thread_s_ignore_deadlock_set, 1); #if THREAD_DEBUG < 0 rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0); rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1); @@ -5220,13 +5470,13 @@ Init_Thread(void) rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1); rb_define_method(rb_cThread, "report_on_exception", rb_thread_report_exc, 0); rb_define_method(rb_cThread, "report_on_exception=", rb_thread_report_exc_set, 1); - rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0); rb_define_method(rb_cThread, "group", rb_thread_group, 0); rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, -1); rb_define_method(rb_cThread, "backtrace_locations", rb_thread_backtrace_locations_m, -1); rb_define_method(rb_cThread, "name", rb_thread_getname, 0); rb_define_method(rb_cThread, "name=", rb_thread_setname, 1); + rb_define_method(rb_cThread, "native_thread_id", rb_thread_native_thread_id, 0); rb_define_method(rb_cThread, "to_s", rb_thread_to_s, 0); rb_define_alias(rb_cThread, "inspect", "to_s"); @@ -5241,11 +5491,10 @@ Init_Thread(void) rb_define_method(cThGroup, "add", thgroup_add, 1); { - th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup); + th->thgroup = th->ractor->thgroup_default = rb_obj_alloc(cThGroup); rb_define_const(cThGroup, "Default", th->thgroup); } - recursive_key = rb_intern("__recursive_key__"); rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError); /* init thread core */ @@ -5253,11 +5502,8 @@ Init_Thread(void) /* main thread setting */ { /* acquire global vm lock */ - gvl_init(th->vm); - gvl_acquire(th->vm, th); - rb_native_mutex_initialize(&th->vm->waitpid_lock); - rb_native_mutex_initialize(&th->vm->workqueue_lock); - rb_native_mutex_initialize(&th->interrupt_lock); + rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor); + gvl_acquire(gvl, th); th->pending_interrupt_queue = rb_ary_tmp_new(0); th->pending_interrupt_queue_checked = 0; @@ -5267,9 +5513,6 @@ Init_Thread(void) rb_thread_create_timer_thread(); - /* suppress warnings on cygwin, mingw and mswin.*/ - (void)native_mutex_trylock; - Init_thread_sync(); } @@ -5282,67 +5525,74 @@ ruby_native_thread_p(void) } static void -debug_deadlock_check(rb_vm_t *vm, VALUE msg) +debug_deadlock_check(rb_ractor_t *r, VALUE msg) { rb_thread_t *th = 0; VALUE sep = rb_str_new_cstr("\n "); rb_str_catf(msg, "\n%d threads, %d sleeps current:%p main thread:%p\n", - vm_living_thread_num(vm), vm->sleeper, (void *)GET_THREAD(), (void *)vm->main_thread); - list_for_each(&vm->living_threads, th, vmlt_node) { - rb_str_catf(msg, "* %+"PRIsVALUE"\n rb_thread_t:%p " - "native:%"PRI_THREAD_ID" int:%u", - th->self, (void *)th, thread_id_str(th), th->ec->interrupt_flag); - if (th->locking_mutex) { - rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); - rb_str_catf(msg, " mutex:%p cond:%"PRIuSIZE, - (void *)mutex->th, rb_mutex_num_waiting(mutex)); - } - { - rb_thread_list_t *list = th->join_list; - while (list) { - rb_str_catf(msg, "\n depended by: tb_thread_id:%p", (void *)list->th); - list = list->next; - } - } - rb_str_catf(msg, "\n "); - rb_str_concat(msg, rb_ary_join(rb_ec_backtrace_str_ary(th->ec, 0, 0), sep)); - rb_str_catf(msg, "\n"); + rb_ractor_living_thread_num(r), rb_ractor_sleeper_thread_num(r), + (void *)GET_THREAD(), (void *)r->threads.main); + + list_for_each(&r->threads.set, th, lt_node) { + rb_str_catf(msg, "* %+"PRIsVALUE"\n rb_thread_t:%p " + "native:%"PRI_THREAD_ID" int:%u", + th->self, (void *)th, thread_id_str(th), th->ec->interrupt_flag); + + if (th->locking_mutex) { + rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); + rb_str_catf(msg, " mutex:%p cond:%"PRIuSIZE, + (void *)mutex->fiber, rb_mutex_num_waiting(mutex)); + } + + { + struct rb_waiting_list *list = th->join_list; + while (list) { + rb_str_catf(msg, "\n depended by: tb_thread_id:%p", (void *)list->thread); + list = list->next; + } + } + rb_str_catf(msg, "\n "); + rb_str_concat(msg, rb_ary_join(rb_ec_backtrace_str_ary(th->ec, 0, 0), sep)); + rb_str_catf(msg, "\n"); } } static void -rb_check_deadlock(rb_vm_t *vm) +rb_check_deadlock(rb_ractor_t *r) { + if (GET_THREAD()->vm->thread_ignore_deadlock) return; + int found = 0; - rb_thread_t *th = 0; + rb_thread_t *th = NULL; + int sleeper_num = rb_ractor_sleeper_thread_num(r); + int ltnum = rb_ractor_living_thread_num(r); - if (vm_living_thread_num(vm) > vm->sleeper) return; - if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)"); + if (ltnum > sleeper_num) return; + if (ltnum < sleeper_num) rb_bug("sleeper must not be more than vm_living_thread_num(vm)"); if (patrol_thread && patrol_thread != GET_THREAD()) return; - list_for_each(&vm->living_threads, th, vmlt_node) { - if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th->ec)) { - found = 1; - } - else if (th->locking_mutex) { - rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); - - if (mutex->th == th || (!mutex->th && !list_empty(&mutex->waitq))) { - found = 1; - } - } - if (found) - break; + list_for_each(&r->threads.set, th, lt_node) { + if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th->ec)) { + found = 1; + } + else if (th->locking_mutex) { + rb_mutex_t *mutex = mutex_ptr(th->locking_mutex); + if (mutex->fiber == th->ec->fiber_ptr || (!mutex->fiber && !list_empty(&mutex->waitq))) { + found = 1; + } + } + if (found) + break; } if (!found) { VALUE argv[2]; argv[0] = rb_eFatal; argv[1] = rb_str_new2("No live threads left. Deadlock?"); - debug_deadlock_check(vm, argv[1]); - vm->sleeper--; - rb_threadptr_raise(vm->main_thread, 2, argv); + debug_deadlock_check(r, argv[1]); + rb_ractor_sleeper_threads_dec(GET_RACTOR()); + rb_threadptr_raise(r->threads.main, 2, argv); } } @@ -5401,6 +5651,8 @@ rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[5]) { VALUE path, beg_pos_lineno, beg_pos_column, end_pos_lineno, end_pos_column; + if (!me->def) return NULL; // negative cme + retry: switch (me->def->type) { case VM_METHOD_TYPE_ISEQ: { @@ -5489,7 +5741,15 @@ void rb_set_coverages(VALUE coverages, int mode, VALUE me2counter) { GET_VM()->coverages = coverages; + GET_VM()->me2counter = me2counter; GET_VM()->coverage_mode = mode; +} + +void +rb_resume_coverages(void) +{ + int mode = GET_VM()->coverage_mode; + VALUE me2counter = GET_VM()->me2counter; rb_add_event_hook2((rb_event_hook_func_t) update_line_coverage, RUBY_EVENT_COVERAGE_LINE, Qnil, RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG); if (mode & COVERAGE_TARGET_BRANCHES) { rb_add_event_hook2((rb_event_hook_func_t) update_branch_coverage, RUBY_EVENT_COVERAGE_BRANCH, Qnil, RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG); @@ -5499,13 +5759,9 @@ rb_set_coverages(VALUE coverages, int mode, VALUE me2counter) } } -/* Make coverage arrays empty so old covered files are no longer tracked. */ void -rb_reset_coverages(void) +rb_suspend_coverages(void) { - rb_clear_coverages(); - rb_iseq_remove_coverage_all(); - GET_VM()->coverages = Qfalse; rb_remove_event_hook((rb_event_hook_func_t) update_line_coverage); if (GET_VM()->coverage_mode & COVERAGE_TARGET_BRANCHES) { rb_remove_event_hook((rb_event_hook_func_t) update_branch_coverage); @@ -5515,6 +5771,15 @@ rb_reset_coverages(void) } } +/* Make coverage arrays empty so old covered files are no longer tracked. */ +void +rb_reset_coverages(void) +{ + rb_clear_coverages(); + rb_iseq_remove_coverage_all(); + GET_VM()->coverages = Qfalse; +} + VALUE rb_default_coverage(int n) { @@ -5528,20 +5793,31 @@ rb_default_coverage(int n) RARRAY_ASET(coverage, COVERAGE_INDEX_LINES, lines); if (mode & COVERAGE_TARGET_BRANCHES) { - branches = rb_ary_tmp_new_fill(2); - /* internal data structures for branch coverage: - * - * [[base_type, base_first_lineno, base_first_column, base_last_lineno, base_last_column, - * target_type_1, target_first_lineno_1, target_first_column_1, target_last_lineno_1, target_last_column_1, target_counter_index_1, - * target_type_2, target_first_lineno_2, target_first_column_2, target_last_lineno_2, target_last_column_2, target_counter_index_2, ...], - * ...] - * - * Example: [[:case, 1, 0, 4, 3, - * :when, 2, 8, 2, 9, 0, - * :when, 3, 8, 3, 9, 1, ...], - * ...] - */ - RARRAY_ASET(branches, 0, rb_ary_tmp_new(0)); + branches = rb_ary_tmp_new_fill(2); + /* internal data structures for branch coverage: + * + * { branch base node => + * [base_type, base_first_lineno, base_first_column, base_last_lineno, base_last_column, { + * branch target id => + * [target_type, target_first_lineno, target_first_column, target_last_lineno, target_last_column, target_counter_index], + * ... + * }], + * ... + * } + * + * Example: + * { NODE_CASE => + * [1, 0, 4, 3, { + * NODE_WHEN => [2, 8, 2, 9, 0], + * NODE_WHEN => [3, 8, 3, 9, 1], + * ... + * }], + * ... + * } + */ + VALUE structure = rb_hash_new(); + rb_obj_hide(structure); + RARRAY_ASET(branches, 0, structure); /* branch execution counters */ RARRAY_ASET(branches, 1, rb_ary_tmp_new(0)); } @@ -5550,6 +5826,19 @@ rb_default_coverage(int n) return coverage; } +static VALUE +uninterruptible_exit(VALUE v) +{ + rb_thread_t *cur_th = GET_THREAD(); + rb_ary_pop(cur_th->pending_interrupt_mask_stack); + + cur_th->pending_interrupt_queue_checked = 0; + if (!rb_threadptr_pending_interrupt_empty_p(cur_th)) { + RUBY_VM_SET_INTERRUPT(cur_th->ec); + } + return Qnil; +} + VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data) { @@ -5560,5 +5849,8 @@ rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data) OBJ_FREEZE_RAW(interrupt_mask); rb_ary_push(cur_th->pending_interrupt_mask_stack, interrupt_mask); - return rb_ensure(b_proc, data, rb_ary_pop, cur_th->pending_interrupt_mask_stack); + VALUE ret = rb_ensure(b_proc, data, uninterruptible_exit, Qnil); + + RUBY_VM_CHECK_INTS(cur_th->ec); + return ret; } diff --git a/ruby/thread_pthread.c b/ruby/thread_pthread.c index cbe6aa028..6f0cc3d54 100644 --- a/ruby/thread_pthread.c +++ b/ruby/thread_pthread.c @@ -20,9 +20,9 @@ #ifdef HAVE_THR_STKSEGMENT #include #endif -#if HAVE_FCNTL_H +#if defined(HAVE_FCNTL_H) #include -#elif HAVE_SYS_FCNTL_H +#elif defined(HAVE_SYS_FCNTL_H) #include #endif #ifdef HAVE_SYS_PRCTL_H @@ -34,6 +34,9 @@ #if defined(__HAIKU__) #include #endif +#ifdef __linux__ +#include /* for SYS_gettid */ +#endif #include #include @@ -44,7 +47,7 @@ # define USE_EVENTFD (0) #endif -#if defined(SIGVTALRM) && !defined(__CYGWIN__) +#if defined(SIGVTALRM) && !defined(__CYGWIN__) && !defined(__EMSCRIPTEN__) # define USE_UBF_LIST 1 #endif @@ -103,13 +106,52 @@ enum rtimer_state { #if UBF_TIMER == UBF_TIMER_POSIX static const struct itimerspec zero; static struct { - rb_atomic_t state; /* rtimer_state */ + rb_atomic_t state_; /* rtimer_state */ rb_pid_t owner; timer_t timerid; } timer_posix = { /* .state = */ RTIMER_DEAD, }; +#define TIMER_STATE_DEBUG 0 + +static const char * +rtimer_state_name(enum rtimer_state state) +{ + switch (state) { + case RTIMER_DISARM: return "disarm"; + case RTIMER_ARMING: return "arming"; + case RTIMER_ARMED: return "armed"; + case RTIMER_DEAD: return "dead"; + default: rb_bug("unreachable"); + } +} + +static enum rtimer_state +timer_state_exchange(enum rtimer_state state) +{ + enum rtimer_state prev = ATOMIC_EXCHANGE(timer_posix.state_, state); + if (TIMER_STATE_DEBUG) fprintf(stderr, "state (exc): %s->%s\n", rtimer_state_name(prev), rtimer_state_name(state)); + return prev; +} + +static enum rtimer_state +timer_state_cas(enum rtimer_state expected_prev, enum rtimer_state state) +{ + enum rtimer_state prev = ATOMIC_CAS(timer_posix.state_, expected_prev, state); + + if (TIMER_STATE_DEBUG) { + if (prev == expected_prev) { + fprintf(stderr, "state (cas): %s->%s\n", rtimer_state_name(prev), rtimer_state_name(state)); + } + else { + fprintf(stderr, "state (cas): %s (expected:%s)\n", rtimer_state_name(prev), rtimer_state_name(expected_prev)); + } + } + + return prev; +} + #elif UBF_TIMER == UBF_TIMER_PTHREAD static void *timer_pthread_fn(void *); static struct { @@ -122,26 +164,14 @@ static struct { }; #endif -void rb_native_mutex_lock(rb_nativethread_lock_t *lock); -void rb_native_mutex_unlock(rb_nativethread_lock_t *lock); -static int native_mutex_trylock(rb_nativethread_lock_t *lock); -void rb_native_mutex_initialize(rb_nativethread_lock_t *lock); -void rb_native_mutex_destroy(rb_nativethread_lock_t *lock); -void rb_native_cond_signal(rb_nativethread_cond_t *cond); -void rb_native_cond_broadcast(rb_nativethread_cond_t *cond); -void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex); -void rb_native_cond_initialize(rb_nativethread_cond_t *cond); -void rb_native_cond_destroy(rb_nativethread_cond_t *cond); -static void clear_thread_cache_altstack(void); -static void ubf_wakeup_all_threads(void); -static int ubf_threads_empty(void); -static int native_cond_timedwait(rb_nativethread_cond_t *, pthread_mutex_t *, - const rb_hrtime_t *abs); static const rb_hrtime_t *sigwait_timeout(rb_thread_t *, int sigwait_fd, const rb_hrtime_t *, int *drained_p); static void ubf_timer_disarm(void); static void threadptr_trap_interrupt(rb_thread_t *); +static void clear_thread_cache_altstack(void); +static void ubf_wakeup_all_threads(void); +static int ubf_threads_empty(void); #define TIMER_THREAD_CREATED_P() (signal_self_pipe.owner_process == getpid()) @@ -180,17 +210,18 @@ static const void *const condattr_monotonic = NULL; #define TIME_QUANTUM_NSEC (TIME_QUANTUM_USEC * 1000) static rb_hrtime_t native_cond_timeout(rb_nativethread_cond_t *, rb_hrtime_t); +static int native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const rb_hrtime_t *abs); /* * Designate the next gvl.timer thread, favor the last thread in * the waitq since it will be in waitq longest */ static int -designate_timer_thread(rb_vm_t *vm) +designate_timer_thread(rb_global_vm_lock_t *gvl) { native_thread_data_t *last; - last = list_tail(&vm->gvl.waitq, native_thread_data_t, node.ubf); + last = list_tail(&gvl->waitq, native_thread_data_t, node.ubf); if (last) { rb_native_cond_signal(&last->cond.gvlq); return TRUE; @@ -203,29 +234,31 @@ designate_timer_thread(rb_vm_t *vm) * periodically. Continue on old timeout if it expired. */ static void -do_gvl_timer(rb_vm_t *vm, rb_thread_t *th) +do_gvl_timer(rb_global_vm_lock_t *gvl, rb_thread_t *th) { + rb_vm_t *vm = GET_VM(); static rb_hrtime_t abs; native_thread_data_t *nd = &th->native_thread_data; - vm->gvl.timer = th; + gvl->timer = th; /* take over wakeups from UBF_TIMER */ ubf_timer_disarm(); - if (vm->gvl.timer_err == ETIMEDOUT) { + if (gvl->timer_err == ETIMEDOUT) { abs = native_cond_timeout(&nd->cond.gvlq, TIME_QUANTUM_NSEC); } - vm->gvl.timer_err = native_cond_timedwait(&nd->cond.gvlq, &vm->gvl.lock, &abs); + gvl->timer_err = native_cond_timedwait(&nd->cond.gvlq, &gvl->lock, &abs); ubf_wakeup_all_threads(); ruby_sigchld_handler(vm); + if (UNLIKELY(rb_signal_buff_size())) { - if (th == vm->main_thread) { + if (th == vm->ractor.main_thread) { RUBY_VM_SET_TRAP_INTERRUPT(th->ec); } else { - threadptr_trap_interrupt(vm->main_thread); + threadptr_trap_interrupt(vm->ractor.main_thread); } } @@ -233,77 +266,80 @@ do_gvl_timer(rb_vm_t *vm, rb_thread_t *th) * Timeslice. Warning: the process may fork while this * thread is contending for GVL: */ - if (vm->gvl.owner) timer_thread_function(); - vm->gvl.timer = 0; + if (gvl->owner) { + // strictly speaking, accessing "gvl->owner" is not thread-safe + RUBY_VM_SET_TIMER_INTERRUPT(gvl->owner->ec); + } + gvl->timer = 0; } static void -gvl_acquire_common(rb_vm_t *vm, rb_thread_t *th) +gvl_acquire_common(rb_global_vm_lock_t *gvl, rb_thread_t *th) { - if (vm->gvl.owner) { + if (gvl->owner) { native_thread_data_t *nd = &th->native_thread_data; VM_ASSERT(th->unblock.func == 0 && "we must not be in ubf_list and GVL waitq at the same time"); - list_add_tail(&vm->gvl.waitq, &nd->node.gvl); + list_add_tail(&gvl->waitq, &nd->node.gvl); do { - if (!vm->gvl.timer) { - do_gvl_timer(vm, th); + if (!gvl->timer) { + do_gvl_timer(gvl, th); } else { - rb_native_cond_wait(&nd->cond.gvlq, &vm->gvl.lock); + rb_native_cond_wait(&nd->cond.gvlq, &gvl->lock); } - } while (vm->gvl.owner); + } while (gvl->owner); list_del_init(&nd->node.gvl); - if (vm->gvl.need_yield) { - vm->gvl.need_yield = 0; - rb_native_cond_signal(&vm->gvl.switch_cond); + if (gvl->need_yield) { + gvl->need_yield = 0; + rb_native_cond_signal(&gvl->switch_cond); } } else { /* reset timer if uncontended */ - vm->gvl.timer_err = ETIMEDOUT; + gvl->timer_err = ETIMEDOUT; } - vm->gvl.owner = th; - if (!vm->gvl.timer) { - if (!designate_timer_thread(vm) && !ubf_threads_empty()) { + gvl->owner = th; + if (!gvl->timer) { + if (!designate_timer_thread(gvl) && !ubf_threads_empty()) { rb_thread_wakeup_timer_thread(-1); } } } static void -gvl_acquire(rb_vm_t *vm, rb_thread_t *th) +gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th) { - rb_native_mutex_lock(&vm->gvl.lock); - gvl_acquire_common(vm, th); - rb_native_mutex_unlock(&vm->gvl.lock); + rb_native_mutex_lock(&gvl->lock); + gvl_acquire_common(gvl, th); + rb_native_mutex_unlock(&gvl->lock); } static const native_thread_data_t * -gvl_release_common(rb_vm_t *vm) +gvl_release_common(rb_global_vm_lock_t *gvl) { native_thread_data_t *next; - vm->gvl.owner = 0; - next = list_top(&vm->gvl.waitq, native_thread_data_t, node.ubf); + gvl->owner = 0; + next = list_top(&gvl->waitq, native_thread_data_t, node.ubf); if (next) rb_native_cond_signal(&next->cond.gvlq); return next; } static void -gvl_release(rb_vm_t *vm) +gvl_release(rb_global_vm_lock_t *gvl) { - rb_native_mutex_lock(&vm->gvl.lock); - gvl_release_common(vm); - rb_native_mutex_unlock(&vm->gvl.lock); + rb_native_mutex_lock(&gvl->lock); + gvl_release_common(gvl); + rb_native_mutex_unlock(&gvl->lock); } static void -gvl_yield(rb_vm_t *vm, rb_thread_t *th) +gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th) { const native_thread_data_t *next; @@ -312,49 +348,49 @@ gvl_yield(rb_vm_t *vm, rb_thread_t *th) * (perhaps looping in io_close_fptr) so we kick them: */ ubf_wakeup_all_threads(); - rb_native_mutex_lock(&vm->gvl.lock); - next = gvl_release_common(vm); + rb_native_mutex_lock(&gvl->lock); + next = gvl_release_common(gvl); /* An another thread is processing GVL yield. */ - if (UNLIKELY(vm->gvl.wait_yield)) { - while (vm->gvl.wait_yield) - rb_native_cond_wait(&vm->gvl.switch_wait_cond, &vm->gvl.lock); + if (UNLIKELY(gvl->wait_yield)) { + while (gvl->wait_yield) + rb_native_cond_wait(&gvl->switch_wait_cond, &gvl->lock); } else if (next) { /* Wait until another thread task takes GVL. */ - vm->gvl.need_yield = 1; - vm->gvl.wait_yield = 1; - while (vm->gvl.need_yield) - rb_native_cond_wait(&vm->gvl.switch_cond, &vm->gvl.lock); - vm->gvl.wait_yield = 0; - rb_native_cond_broadcast(&vm->gvl.switch_wait_cond); + gvl->need_yield = 1; + gvl->wait_yield = 1; + while (gvl->need_yield) + rb_native_cond_wait(&gvl->switch_cond, &gvl->lock); + gvl->wait_yield = 0; + rb_native_cond_broadcast(&gvl->switch_wait_cond); } else { - rb_native_mutex_unlock(&vm->gvl.lock); + rb_native_mutex_unlock(&gvl->lock); native_thread_yield(); - rb_native_mutex_lock(&vm->gvl.lock); - rb_native_cond_broadcast(&vm->gvl.switch_wait_cond); + rb_native_mutex_lock(&gvl->lock); + rb_native_cond_broadcast(&gvl->switch_wait_cond); } - gvl_acquire_common(vm, th); - rb_native_mutex_unlock(&vm->gvl.lock); + gvl_acquire_common(gvl, th); + rb_native_mutex_unlock(&gvl->lock); } -static void -gvl_init(rb_vm_t *vm) +void +rb_gvl_init(rb_global_vm_lock_t *gvl) { - rb_native_mutex_initialize(&vm->gvl.lock); - rb_native_cond_initialize(&vm->gvl.switch_cond); - rb_native_cond_initialize(&vm->gvl.switch_wait_cond); - list_head_init(&vm->gvl.waitq); - vm->gvl.owner = 0; - vm->gvl.timer = 0; - vm->gvl.timer_err = ETIMEDOUT; - vm->gvl.need_yield = 0; - vm->gvl.wait_yield = 0; + rb_native_mutex_initialize(&gvl->lock); + rb_native_cond_initialize(&gvl->switch_cond); + rb_native_cond_initialize(&gvl->switch_wait_cond); + list_head_init(&gvl->waitq); + gvl->owner = 0; + gvl->timer = 0; + gvl->timer_err = ETIMEDOUT; + gvl->need_yield = 0; + gvl->wait_yield = 0; } static void -gvl_destroy(rb_vm_t *vm) +gvl_destroy(rb_global_vm_lock_t *gvl) { /* * only called once at VM shutdown (not atfork), another thread @@ -362,9 +398,9 @@ gvl_destroy(rb_vm_t *vm) * the end of thread_start_func_2 */ if (0) { - rb_native_cond_destroy(&vm->gvl.switch_wait_cond); - rb_native_cond_destroy(&vm->gvl.switch_cond); - rb_native_mutex_destroy(&vm->gvl.lock); + rb_native_cond_destroy(&gvl->switch_wait_cond); + rb_native_cond_destroy(&gvl->switch_cond); + rb_native_mutex_destroy(&gvl->lock); } clear_thread_cache_altstack(); } @@ -372,11 +408,11 @@ gvl_destroy(rb_vm_t *vm) #if defined(HAVE_WORKING_FORK) static void thread_cache_reset(void); static void -gvl_atfork(rb_vm_t *vm) +gvl_atfork(rb_global_vm_lock_t *gvl) { thread_cache_reset(); - gvl_init(vm); - gvl_acquire(vm, GET_THREAD()); + rb_gvl_init(gvl); + gvl_acquire(gvl, GET_THREAD()); } #endif @@ -415,8 +451,8 @@ rb_native_mutex_unlock(pthread_mutex_t *lock) } } -static inline int -native_mutex_trylock(pthread_mutex_t *lock) +int +rb_native_mutex_trylock(pthread_mutex_t *lock) { int r; mutex_debug("trylock", lock); @@ -513,8 +549,7 @@ rb_native_cond_wait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex) } static int -native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, - const rb_hrtime_t *abs) +native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const rb_hrtime_t *abs) { int r; struct timespec ts; @@ -526,16 +561,24 @@ native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, * Let's hide it from arch generic code. */ do { - r = pthread_cond_timedwait(cond, mutex, rb_hrtime2timespec(&ts, abs)); + rb_hrtime2timespec(&ts, abs); + r = pthread_cond_timedwait(cond, mutex, &ts); } while (r == EINTR); if (r != 0 && r != ETIMEDOUT) { - rb_bug_errno("pthread_cond_timedwait", r); + rb_bug_errno("pthread_cond_timedwait", r); } return r; } +void +rb_native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, unsigned long msec) +{ + rb_hrtime_t hrmsec = native_cond_timeout(cond, RB_HRTIME_PER_MSEC * msec); + native_cond_timedwait(cond, mutex, &hrmsec); +} + static rb_hrtime_t native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel) { @@ -553,7 +596,11 @@ native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel) #define native_cleanup_push pthread_cleanup_push #define native_cleanup_pop pthread_cleanup_pop +#ifdef RB_THREAD_LOCAL_SPECIFIER +static RB_THREAD_LOCAL_SPECIFIER rb_thread_t *ruby_native_thread; +#else static pthread_key_t ruby_native_thread_key; +#endif static void null_func(int i) @@ -561,16 +608,28 @@ null_func(int i) /* null */ } -static rb_thread_t * +rb_thread_t * ruby_thread_from_native(void) { +#ifdef RB_THREAD_LOCAL_SPECIFIER + return ruby_native_thread; +#else return pthread_getspecific(ruby_native_thread_key); +#endif } -static int +int ruby_thread_set_native(rb_thread_t *th) { + if (th && th->ec) { + rb_ractor_set_current_ec(th->ractor, th->ec); + } +#ifdef RB_THREAD_LOCAL_SPECIFIER + ruby_native_thread = th; + return 1; +#else return pthread_setspecific(ruby_native_thread_key, th) == 0; +#endif } static void native_thread_init(rb_thread_t *th); @@ -587,25 +646,48 @@ Init_native_thread(rb_thread_t *th) if (r) condattr_monotonic = NULL; } #endif - pthread_key_create(&ruby_native_thread_key, NULL); + +#ifndef RB_THREAD_LOCAL_SPECIFIER + if (pthread_key_create(&ruby_native_thread_key, 0) == EAGAIN) { + rb_bug("pthread_key_create failed (ruby_native_thread_key)"); + } + if (pthread_key_create(&ruby_current_ec_key, 0) == EAGAIN) { + rb_bug("pthread_key_create failed (ruby_current_ec_key)"); + } +#endif th->thread_id = pthread_self(); + ruby_thread_set_native(th); fill_thread_id_str(th); native_thread_init(th); posix_signal(SIGVTALRM, null_func); } +#ifdef RB_THREAD_T_HAS_NATIVE_ID +static int +get_native_thread_id(void) +{ +#ifdef __linux__ + return (int)syscall(SYS_gettid); +#elif defined(__FreeBSD__) + return pthread_getthreadid_np(); +#endif +} +#endif + static void native_thread_init(rb_thread_t *th) { native_thread_data_t *nd = &th->native_thread_data; +#ifdef RB_THREAD_T_HAS_NATIVE_ID + th->tid = get_native_thread_id(); +#endif #ifdef USE_UBF_LIST list_node_init(&nd->node.ubf); #endif rb_native_cond_initialize(&nd->cond.gvlq); if (&nd->cond.gvlq != &nd->cond.intr) rb_native_cond_initialize(&nd->cond.intr); - ruby_thread_set_native(th); } #ifndef USE_THREAD_CACHE @@ -683,10 +765,10 @@ get_stack(void **addr, size_t *size) # endif # ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); - *size -= guard; # else - *size -= getpagesize(); + guard = getpagesize(); # endif + *size -= guard; pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; @@ -826,10 +908,6 @@ reserve_stack(volatile char *limit, size_t size) #endif #undef ruby_init_stack -/* Set stack bottom of Ruby implementation. - * - * You must call this function before any heap allocation by Ruby implementation. - * Or GC will break living objects */ void ruby_init_stack(volatile VALUE *addr) { @@ -950,7 +1028,7 @@ static void * thread_start_func_1(void *th_ptr) { rb_thread_t *th = th_ptr; - RB_ALTSTACK_INIT(void *altstack); + RB_ALTSTACK_INIT(void *altstack, th->altstack); #if USE_THREAD_CACHE thread_start: #endif @@ -1099,6 +1177,9 @@ native_thread_create(rb_thread_t *th) const size_t stack_size = th->vm->default_params.thread_machine_stack_size + th->vm->default_params.thread_vm_stack_size; const size_t space = space_size(stack_size); +#ifdef USE_SIGALTSTACK + th->altstack = rb_allocate_sigaltstack(); +#endif th->ec->machine.stack_maxsize = stack_size - space; CHECK_ERR(pthread_attr_init(&attr)); @@ -1113,7 +1194,7 @@ native_thread_create(rb_thread_t *th) # endif CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); - err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th); + err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th); thread_debug("create: %p (%d)\n", (void *)th, err); /* should be done in the created thread */ fill_thread_id_str(th); @@ -1204,7 +1285,7 @@ native_cond_sleep(rb_thread_t *th, rb_hrtime_t *rel) } end = native_cond_timeout(cond, *rel); - native_cond_timedwait(cond, lock, &end); + native_cond_timedwait(cond, lock, &end); } } th->unblock.func = 0; @@ -1274,7 +1355,7 @@ static void ubf_select(void *ptr) { rb_thread_t *th = (rb_thread_t *)ptr; - rb_vm_t *vm = th->vm; + rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor); const rb_thread_t *cur = ruby_thread_from_native(); /* may be 0 */ register_ubf_list(th); @@ -1289,17 +1370,17 @@ ubf_select(void *ptr) * sigwait_th thread, otherwise we can deadlock with a thread * in unblock_function_clear. */ - if (cur != vm->gvl.timer && cur != sigwait_th) { + if (cur != gvl->timer && cur != sigwait_th) { /* * Double-checked locking above was to prevent nested locking * by the SAME thread. We use trylock here to prevent deadlocks * between DIFFERENT threads */ - if (native_mutex_trylock(&vm->gvl.lock) == 0) { - if (!vm->gvl.timer) { + if (rb_native_mutex_trylock(&gvl->lock) == 0) { + if (!gvl->timer) { rb_thread_wakeup_timer_thread(-1); } - rb_native_mutex_unlock(&vm->gvl.lock); + rb_native_mutex_unlock(&gvl->lock); } } @@ -1395,7 +1476,7 @@ ubf_timer_arm(rb_pid_t current) /* async signal safe */ { #if UBF_TIMER == UBF_TIMER_POSIX if ((!current || timer_posix.owner == current) && - !ATOMIC_CAS(timer_posix.state, RTIMER_DISARM, RTIMER_ARMING)) { + timer_state_cas(RTIMER_DISARM, RTIMER_ARMING) == RTIMER_DISARM) { struct itimerspec it; it.it_interval.tv_sec = it.it_value.tv_sec = 0; @@ -1404,7 +1485,7 @@ ubf_timer_arm(rb_pid_t current) /* async signal safe */ if (timer_settime(timer_posix.timerid, 0, &it, 0)) rb_async_bug_errno("timer_settime (arm)", errno); - switch (ATOMIC_CAS(timer_posix.state, RTIMER_ARMING, RTIMER_ARMED)) { + switch (timer_state_cas(RTIMER_ARMING, RTIMER_ARMED)) { case RTIMER_DISARM: /* somebody requested a disarm while we were arming */ /* may race harmlessly with ubf_timer_destroy */ @@ -1468,7 +1549,7 @@ rb_thread_wakeup_timer_thread(int sig) * on heap for maximum safety (and startup/shutdown speed) */ if (!vm) return; - mth = vm->main_thread; + mth = vm->ractor.main_thread; if (!mth || system_working <= 0) return; /* this relies on GC for grace period before cont_free */ @@ -1569,6 +1650,18 @@ setup_communication_pipe_internal(int pipes[2]) # define SET_CURRENT_THREAD_NAME(name) prctl(PR_SET_NAME, name) #endif +enum { + THREAD_NAME_MAX = +#if defined(__linux__) + 16 +#elif defined(__APPLE__) +/* Undocumented, and main thread seems unlimited */ + 64 +#else + 16 +#endif +}; + static VALUE threadptr_invoke_proc_location(rb_thread_t *th); static void @@ -1581,17 +1674,17 @@ native_set_thread_name(rb_thread_t *th) } else if ((loc = threadptr_invoke_proc_location(th)) != Qnil) { char *name, *p; - char buf[16]; + char buf[THREAD_NAME_MAX]; size_t len; int n; name = RSTRING_PTR(RARRAY_AREF(loc, 0)); p = strrchr(name, '/'); /* show only the basename of the path. */ if (p && p[1]) - name = p + 1; + name = p + 1; n = snprintf(buf, sizeof(buf), "%s:%d", name, NUM2INT(RARRAY_AREF(loc, 1))); - rb_gc_force_recycle(loc); /* acts as a GC guard, too */ + RB_GC_GUARD(loc); len = (size_t)n; if (len >= sizeof(buf)) { @@ -1603,16 +1696,51 @@ native_set_thread_name(rb_thread_t *th) #endif } -static VALUE +static void native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name) { -#ifdef SET_ANOTHER_THREAD_NAME +#if defined SET_ANOTHER_THREAD_NAME || defined SET_CURRENT_THREAD_NAME + char buf[THREAD_NAME_MAX]; const char *s = ""; - if (!NIL_P(name)) s = RSTRING_PTR(name); +# if !defined SET_ANOTHER_THREAD_NAME + if (!pthread_equal(pthread_self(), thread_id)) return; +# endif + if (!NIL_P(name)) { + long n; + RSTRING_GETMEM(name, s, n); + if (n >= (int)sizeof(buf)) { + memcpy(buf, s, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + s = buf; + } + } +# if defined SET_ANOTHER_THREAD_NAME SET_ANOTHER_THREAD_NAME(thread_id, s); +# elif defined SET_CURRENT_THREAD_NAME + SET_CURRENT_THREAD_NAME(s); +# endif +#endif +} + +#if defined(RB_THREAD_T_HAS_NATIVE_ID) || defined(__APPLE__) +static VALUE +native_thread_native_thread_id(rb_thread_t *target_th) +{ +#ifdef RB_THREAD_T_HAS_NATIVE_ID + int tid = target_th->tid; + if (tid == 0) return Qnil; + return INT2FIX(tid); +#elif defined(__APPLE__) + uint64_t tid; + int e = pthread_threadid_np(target_th->thread_id, &tid); + if (e != 0) rb_syserr_fail(e, "pthread_threadid_np"); + return ULL2NUM((unsigned long long)tid); #endif - return name; } +# define USE_NATIVE_THREAD_NATIVE_THREAD_ID 1 +#else +# define USE_NATIVE_THREAD_NATIVE_THREAD_ID 0 +#endif static void ubf_timer_invalidate(void) @@ -1659,7 +1787,7 @@ ubf_timer_create(rb_pid_t current) sev.sigev_value.sival_ptr = &timer_posix; if (!timer_create(UBF_TIMER_CLOCK, &sev, &timer_posix.timerid)) { - rb_atomic_t prev = ATOMIC_EXCHANGE(timer_posix.state, RTIMER_DISARM); + rb_atomic_t prev = timer_state_exchange(RTIMER_DISARM); if (prev != RTIMER_DEAD) { rb_bug("timer_posix was not dead: %u\n", (unsigned)prev); @@ -1704,7 +1832,8 @@ ubf_timer_disarm(void) #if UBF_TIMER == UBF_TIMER_POSIX rb_atomic_t prev; - prev = ATOMIC_CAS(timer_posix.state, RTIMER_ARMED, RTIMER_DISARM); + if (timer_posix.owner && timer_posix.owner != getpid()) return; + prev = timer_state_cas(RTIMER_ARMED, RTIMER_DISARM); switch (prev) { case RTIMER_DISARM: return; /* likely */ case RTIMER_ARMING: return; /* ubf_timer_arm will disarm itself */ @@ -1713,7 +1842,7 @@ ubf_timer_disarm(void) int err = errno; if (err == EINVAL) { - prev = ATOMIC_CAS(timer_posix.state, RTIMER_DISARM, RTIMER_DISARM); + prev = timer_state_cas(RTIMER_DISARM, RTIMER_DISARM); /* main thread may have killed the timer */ if (prev == RTIMER_DEAD) return; @@ -1742,7 +1871,7 @@ ubf_timer_destroy(void) /* prevent signal handler from arming: */ for (i = 0; i < max; i++) { - switch (ATOMIC_CAS(timer_posix.state, expect, RTIMER_DEAD)) { + switch (timer_state_cas(expect, RTIMER_DEAD)) { case RTIMER_DISARM: if (expect == RTIMER_DISARM) goto done; expect = RTIMER_DISARM; @@ -1768,7 +1897,7 @@ ubf_timer_destroy(void) if (timer_delete(timer_posix.timerid) < 0) rb_sys_fail("timer_delete"); - VM_ASSERT(ATOMIC_EXCHANGE(timer_posix.state, RTIMER_DEAD) == RTIMER_DEAD); + VM_ASSERT(timer_state_exchange(RTIMER_DEAD) == RTIMER_DEAD); } #elif UBF_TIMER == UBF_TIMER_PTHREAD int err; @@ -2033,12 +2162,12 @@ ubf_ppoll_sleep(void *ignore) */ #define GVL_UNLOCK_BEGIN_YIELD(th) do { \ const native_thread_data_t *next; \ - rb_vm_t *vm = th->vm; \ + rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor); \ RB_GC_SAVE_MACHINE_CONTEXT(th); \ - rb_native_mutex_lock(&vm->gvl.lock); \ - next = gvl_release_common(vm); \ - rb_native_mutex_unlock(&vm->gvl.lock); \ - if (!next && vm_living_thread_num(vm) > 1) { \ + rb_native_mutex_lock(&gvl->lock); \ + next = gvl_release_common(gvl); \ + rb_native_mutex_unlock(&gvl->lock); \ + if (!next && rb_ractor_living_thread_num(th->ractor) > 1) { \ native_thread_yield(); \ } @@ -2087,6 +2216,7 @@ static void native_sleep(rb_thread_t *th, rb_hrtime_t *rel) { int sigwait_fd = rb_sigwait_fd_get(th); + rb_ractor_blocking_threads_inc(th->ractor, __FILE__, __LINE__); if (sigwait_fd >= 0) { rb_native_mutex_lock(&th->interrupt_lock); @@ -2106,12 +2236,14 @@ native_sleep(rb_thread_t *th, rb_hrtime_t *rel) rb_sigwait_fd_put(th, sigwait_fd); rb_sigwait_fd_migrate(th->vm); } - else if (th == th->vm->main_thread) { /* always able to handle signals */ + else if (th == th->vm->ractor.main_thread) { /* always able to handle signals */ native_ppoll_sleep(th, rel); } else { native_cond_sleep(th, rel); } + + rb_ractor_blocking_threads_dec(th->ractor, __FILE__, __LINE__); } #if UBF_TIMER == UBF_TIMER_PTHREAD @@ -2119,7 +2251,7 @@ static void * timer_pthread_fn(void *p) { rb_vm_t *vm = p; - pthread_t main_thread_id = vm->main_thread->thread_id; + pthread_t main_thread_id = vm->ractor.main_thread->thread_id; struct pollfd pfd; int timeout = -1; int ccp; diff --git a/ruby/thread_pthread.h b/ruby/thread_pthread.h index f2b7e598f..2ac354046 100644 --- a/ruby/thread_pthread.h +++ b/ruby/thread_pthread.h @@ -1,3 +1,5 @@ +#ifndef RUBY_THREAD_PTHREAD_H +#define RUBY_THREAD_PTHREAD_H /********************************************************************** thread_pthread.h - @@ -8,9 +10,6 @@ **********************************************************************/ -#ifndef RUBY_THREAD_PTHREAD_H -#define RUBY_THREAD_PTHREAD_H - #ifdef HAVE_PTHREAD_NP_H #include #endif @@ -18,8 +17,6 @@ #define RB_NATIVETHREAD_LOCK_INIT PTHREAD_MUTEX_INITIALIZER #define RB_NATIVETHREAD_COND_INIT PTHREAD_COND_INITIALIZER -typedef pthread_cond_t rb_nativethread_cond_t; - typedef struct native_thread_data_struct { union { struct list_node ubf; @@ -72,4 +69,47 @@ typedef struct rb_global_vm_lock_struct { int wait_yield; } rb_global_vm_lock_t; + +#if __STDC_VERSION__ >= 201112 + #define RB_THREAD_LOCAL_SPECIFIER _Thread_local +#elif defined(__GNUC__) + /* note that ICC (linux) and Clang are covered by __GNUC__ */ + #define RB_THREAD_LOCAL_SPECIFIER __thread +#else + +typedef pthread_key_t native_tls_key_t; + +static inline void * +native_tls_get(native_tls_key_t key) +{ + void *ptr = pthread_getspecific(key); + if (UNLIKELY(ptr == NULL)) { + rb_bug("pthread_getspecific returns NULL"); + } + return ptr; +} + +static inline void +native_tls_set(native_tls_key_t key, void *ptr) +{ + if (UNLIKELY(pthread_setspecific(key, ptr) != 0)) { + rb_bug("pthread_setspecific error"); + } +} +#endif + +RUBY_SYMBOL_EXPORT_BEGIN +#ifdef RB_THREAD_LOCAL_SPECIFIER + #ifdef __APPLE__ + // on Darwin, TLS can not be accessed across .so + struct rb_execution_context_struct *rb_current_ec(void); + void rb_current_ec_set(struct rb_execution_context_struct *); + #else + RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec; + #endif +#else + RUBY_EXTERN native_tls_key_t ruby_current_ec_key; +#endif +RUBY_SYMBOL_EXPORT_END + #endif /* RUBY_THREAD_PTHREAD_H */ diff --git a/ruby/thread_sync.c b/ruby/thread_sync.c index efe295e64..eaf2c025b 100644 --- a/ruby/thread_sync.c +++ b/ruby/thread_sync.c @@ -4,9 +4,18 @@ static VALUE rb_cMutex, rb_cQueue, rb_cSizedQueue, rb_cConditionVariable; static VALUE rb_eClosedQueueError; +/* Mutex */ +typedef struct rb_mutex_struct { + rb_fiber_t *fiber; + struct rb_mutex_struct *next_mutex; + struct list_head waitq; /* protected by GVL */ +} rb_mutex_t; + /* sync_waiter is always on-stack */ struct sync_waiter { + VALUE self; rb_thread_t *th; + rb_fiber_t *fiber; struct list_node node; }; @@ -18,12 +27,20 @@ sync_wakeup(struct list_head *head, long max) struct sync_waiter *cur = 0, *next; list_for_each_safe(head, cur, next, node) { - list_del_init(&cur->node); - if (cur->th->status != THREAD_KILLED) { - rb_threadptr_interrupt(cur->th); - cur->th->status = THREAD_RUNNABLE; - if (--max == 0) return; - } + list_del_init(&cur->node); + + if (cur->th->status != THREAD_KILLED) { + + if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) { + rb_fiber_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber)); + } + else { + rb_threadptr_interrupt(cur->th); + cur->th->status = THREAD_RUNNABLE; + } + + if (--max == 0) return; + } } } @@ -39,30 +56,22 @@ wakeup_all(struct list_head *head) sync_wakeup(head, LONG_MAX); } -/* Mutex */ - -typedef struct rb_mutex_struct { - rb_thread_t *th; - struct rb_mutex_struct *next_mutex; - struct list_head waitq; /* protected by GVL */ -} rb_mutex_t; - #if defined(HAVE_WORKING_FORK) static void rb_mutex_abandon_all(rb_mutex_t *mutexes); static void rb_mutex_abandon_keeping_mutexes(rb_thread_t *th); static void rb_mutex_abandon_locking_mutex(rb_thread_t *th); #endif -static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th); +static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber); /* - * Document-class: Mutex + * Document-class: Thread::Mutex * - * Mutex implements a simple semaphore that can be used to coordinate access to - * shared data from multiple concurrent threads. + * Thread::Mutex implements a simple semaphore that can be used to + * coordinate access to shared data from multiple concurrent threads. * * Example: * - * semaphore = Mutex.new + * semaphore = Thread::Mutex.new * * a = Thread.new { * semaphore.synchronize { @@ -78,7 +87,7 @@ static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th); * */ -#define mutex_mark NULL +#define mutex_mark ((void(*)(void*))0) static size_t rb_mutex_num_waiting(rb_mutex_t *mutex) @@ -93,13 +102,15 @@ rb_mutex_num_waiting(rb_mutex_t *mutex) return n; } +rb_thread_t* rb_fiber_threadptr(const rb_fiber_t *fiber); + static void mutex_free(void *ptr) { rb_mutex_t *mutex = ptr; - if (mutex->th) { + if (mutex->fiber) { /* rb_warn("free locked mutex"); */ - const char *err = rb_mutex_unlock_th(mutex, mutex->th); + const char *err = rb_mutex_unlock_th(mutex, rb_fiber_threadptr(mutex->fiber), mutex->fiber); if (err) rb_bug("%s", err); } ruby_xfree(ptr); @@ -114,7 +125,7 @@ mutex_memsize(const void *ptr) static const rb_data_type_t mutex_data_type = { "mutex", {mutex_mark, mutex_free, mutex_memsize,}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY }; static rb_mutex_t * @@ -130,12 +141,7 @@ mutex_ptr(VALUE obj) VALUE rb_obj_is_mutex(VALUE obj) { - if (rb_typeddata_is_kind_of(obj, &mutex_data_type)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_typeddata_is_kind_of(obj, &mutex_data_type)); } static VALUE @@ -145,13 +151,14 @@ mutex_alloc(VALUE klass) rb_mutex_t *mutex; obj = TypedData_Make_Struct(klass, rb_mutex_t, &mutex_data_type, mutex); + list_head_init(&mutex->waitq); return obj; } /* * call-seq: - * Mutex.new -> mutex + * Thread::Mutex.new -> mutex * * Creates a new Mutex */ @@ -178,7 +185,33 @@ rb_mutex_locked_p(VALUE self) { rb_mutex_t *mutex = mutex_ptr(self); - return mutex->th ? Qtrue : Qfalse; + return RBOOL(mutex->fiber); +} + +static void +thread_mutex_insert(rb_thread_t *thread, rb_mutex_t *mutex) +{ + if (thread->keeping_mutexes) { + mutex->next_mutex = thread->keeping_mutexes; + } + + thread->keeping_mutexes = mutex; +} + +static void +thread_mutex_remove(rb_thread_t *thread, rb_mutex_t *mutex) +{ + rb_mutex_t **keeping_mutexes = &thread->keeping_mutexes; + + while (*keeping_mutexes && *keeping_mutexes != mutex) { + // Move to the next mutex in the list: + keeping_mutexes = &(*keeping_mutexes)->next_mutex; + } + + if (*keeping_mutexes) { + *keeping_mutexes = mutex->next_mutex; + mutex->next_mutex = NULL; + } } static void @@ -186,10 +219,7 @@ mutex_locked(rb_thread_t *th, VALUE self) { rb_mutex_t *mutex = mutex_ptr(self); - if (th->keeping_mutexes) { - mutex->next_mutex = th->keeping_mutexes; - } - th->keeping_mutexes = mutex; + thread_mutex_insert(th, mutex); } /* @@ -203,17 +233,17 @@ VALUE rb_mutex_trylock(VALUE self) { rb_mutex_t *mutex = mutex_ptr(self); - VALUE locked = Qfalse; - if (mutex->th == 0) { + if (mutex->fiber == 0) { + rb_fiber_t *fiber = GET_EC()->fiber_ptr; rb_thread_t *th = GET_THREAD(); - mutex->th = th; - locked = Qtrue; + mutex->fiber = fiber; mutex_locked(th, self); + return Qtrue; } - return locked; + return Qfalse; } /* @@ -224,20 +254,32 @@ rb_mutex_trylock(VALUE self) static const rb_thread_t *patrol_thread = NULL; static VALUE -mutex_owned_p(rb_thread_t *th, rb_mutex_t *mutex) +mutex_owned_p(rb_fiber_t *fiber, rb_mutex_t *mutex) { - if (mutex->th == th) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(mutex->fiber == fiber); +} + +static VALUE +call_rb_fiber_scheduler_block(VALUE mutex) +{ + return rb_fiber_scheduler_block(rb_fiber_scheduler_current(), mutex, Qnil); +} + +static VALUE +delete_from_waitq(VALUE value) +{ + struct sync_waiter *sync_waiter = (void *)value; + list_del(&sync_waiter->node); + + return Qnil; } static VALUE do_mutex_lock(VALUE self, int interruptible_p) { - rb_thread_t *th = GET_THREAD(); + rb_execution_context_t *ec = GET_EC(); + rb_thread_t *th = ec->thread_ptr; + rb_fiber_t *fiber = ec->fiber_ptr; rb_mutex_t *mutex = mutex_ptr(self); /* When running trap handler */ @@ -247,71 +289,91 @@ do_mutex_lock(VALUE self, int interruptible_p) } if (rb_mutex_trylock(self) == Qfalse) { - struct sync_waiter w; - - if (mutex->th == th) { - rb_raise(rb_eThreadError, "deadlock; recursive locking"); - } - - w.th = th; - - while (mutex->th != th) { - enum rb_thread_status prev_status = th->status; - rb_hrtime_t *timeout = 0; - rb_hrtime_t rel = rb_msec2hrtime(100); - - th->status = THREAD_STOPPED_FOREVER; - th->locking_mutex = self; - th->vm->sleeper++; - /* - * Carefully! while some contended threads are in native_sleep(), - * vm->sleeper is unstable value. we have to avoid both deadlock - * and busy loop. - */ - if ((vm_living_thread_num(th->vm) == th->vm->sleeper) && - !patrol_thread) { - timeout = &rel; - patrol_thread = th; - } - - list_add_tail(&mutex->waitq, &w.node); - native_sleep(th, timeout); /* release GVL */ - list_del(&w.node); - - if (!mutex->th) { - mutex->th = th; - } - - if (patrol_thread == th) - patrol_thread = NULL; - - th->locking_mutex = Qfalse; - if (mutex->th && timeout && !RUBY_VM_INTERRUPTED(th->ec)) { - rb_check_deadlock(th->vm); - } - if (th->status == THREAD_STOPPED_FOREVER) { - th->status = prev_status; - } - th->vm->sleeper--; + if (mutex->fiber == fiber) { + rb_raise(rb_eThreadError, "deadlock; recursive locking"); + } + + while (mutex->fiber != fiber) { + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + struct sync_waiter sync_waiter = { + .self = self, + .th = th, + .fiber = fiber + }; + + list_add_tail(&mutex->waitq, &sync_waiter.node); + + rb_ensure(call_rb_fiber_scheduler_block, self, delete_from_waitq, (VALUE)&sync_waiter); + + if (!mutex->fiber) { + mutex->fiber = fiber; + } + } + else { + enum rb_thread_status prev_status = th->status; + rb_hrtime_t *timeout = 0; + rb_hrtime_t rel = rb_msec2hrtime(100); + + th->status = THREAD_STOPPED_FOREVER; + th->locking_mutex = self; + rb_ractor_sleeper_threads_inc(th->ractor); + /* + * Carefully! while some contended threads are in native_sleep(), + * ractor->sleeper is unstable value. we have to avoid both deadlock + * and busy loop. + */ + if ((rb_ractor_living_thread_num(th->ractor) == rb_ractor_sleeper_thread_num(th->ractor)) && + !patrol_thread) { + timeout = &rel; + patrol_thread = th; + } + + struct sync_waiter sync_waiter = { + .self = self, + .th = th, + .fiber = fiber + }; + + list_add_tail(&mutex->waitq, &sync_waiter.node); + + native_sleep(th, timeout); /* release GVL */ + + list_del(&sync_waiter.node); + + if (!mutex->fiber) { + mutex->fiber = fiber; + } + + if (patrol_thread == th) + patrol_thread = NULL; + + th->locking_mutex = Qfalse; + if (mutex->fiber && timeout && !RUBY_VM_INTERRUPTED(th->ec)) { + rb_check_deadlock(th->ractor); + } + if (th->status == THREAD_STOPPED_FOREVER) { + th->status = prev_status; + } + rb_ractor_sleeper_threads_dec(th->ractor); + } if (interruptible_p) { /* release mutex before checking for interrupts...as interrupt checking * code might call rb_raise() */ - if (mutex->th == th) mutex->th = 0; + if (mutex->fiber == fiber) mutex->fiber = 0; RUBY_VM_CHECK_INTS_BLOCKING(th->ec); /* may release mutex */ - if (!mutex->th) { - mutex->th = th; - mutex_locked(th, self); + if (!mutex->fiber) { + mutex->fiber = fiber; } } - else { - if (mutex->th == th) mutex_locked(th, self); - } - } + } + + if (mutex->fiber == fiber) mutex_locked(th, self); } // assertion - if (mutex_owned_p(th, mutex) == Qfalse) rb_bug("do_mutex_lock: mutex is not owned."); + if (mutex_owned_p(fiber, mutex) == Qfalse) rb_bug("do_mutex_lock: mutex is not owned."); return self; } @@ -344,49 +406,52 @@ rb_mutex_lock(VALUE self) VALUE rb_mutex_owned_p(VALUE self) { - rb_thread_t *th = GET_THREAD(); + rb_fiber_t *fiber = GET_EC()->fiber_ptr; rb_mutex_t *mutex = mutex_ptr(self); - return mutex_owned_p(th, mutex); + return mutex_owned_p(fiber, mutex); } static const char * -rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th) +rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber) { const char *err = NULL; - if (mutex->th == 0) { - err = "Attempt to unlock a mutex which is not locked"; + if (mutex->fiber == 0) { + err = "Attempt to unlock a mutex which is not locked"; } - else if (mutex->th != th) { - err = "Attempt to unlock a mutex which is locked by another thread"; + else if (mutex->fiber != fiber) { + err = "Attempt to unlock a mutex which is locked by another thread/fiber"; } else { - struct sync_waiter *cur = 0, *next; - rb_mutex_t **th_mutex = &th->keeping_mutexes; - - mutex->th = 0; - list_for_each_safe(&mutex->waitq, cur, next, node) { - list_del_init(&cur->node); - switch (cur->th->status) { - case THREAD_RUNNABLE: /* from someone else calling Thread#run */ - case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */ - rb_threadptr_interrupt(cur->th); - goto found; - case THREAD_STOPPED: /* probably impossible */ - rb_bug("unexpected THREAD_STOPPED"); - case THREAD_KILLED: - /* not sure about this, possible in exit GC? */ - rb_bug("unexpected THREAD_KILLED"); - continue; - } - } - found: - while (*th_mutex != mutex) { - th_mutex = &(*th_mutex)->next_mutex; - } - *th_mutex = mutex->next_mutex; - mutex->next_mutex = NULL; + struct sync_waiter *cur = 0, *next; + + mutex->fiber = 0; + list_for_each_safe(&mutex->waitq, cur, next, node) { + list_del_init(&cur->node); + + if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) { + rb_fiber_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber)); + goto found; + } + else { + switch (cur->th->status) { + case THREAD_RUNNABLE: /* from someone else calling Thread#run */ + case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */ + rb_threadptr_interrupt(cur->th); + goto found; + case THREAD_STOPPED: /* probably impossible */ + rb_bug("unexpected THREAD_STOPPED"); + case THREAD_KILLED: + /* not sure about this, possible in exit GC? */ + rb_bug("unexpected THREAD_KILLED"); + continue; + } + } + } + + found: + thread_mutex_remove(th, mutex); } return err; @@ -404,8 +469,9 @@ rb_mutex_unlock(VALUE self) { const char *err; rb_mutex_t *mutex = mutex_ptr(self); + rb_thread_t *th = GET_THREAD(); - err = rb_mutex_unlock_th(mutex, GET_THREAD()); + err = rb_mutex_unlock_th(mutex, th, GET_EC()->fiber_ptr); if (err) rb_raise(rb_eThreadError, "%s", err); return self; @@ -438,7 +504,7 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes) while (mutexes) { mutex = mutexes; mutexes = mutex->next_mutex; - mutex->th = 0; + mutex->fiber = 0; mutex->next_mutex = 0; list_head_init(&mutex->waitq); } @@ -446,9 +512,9 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes) #endif static VALUE -rb_mutex_sleep_forever(VALUE time) +rb_mutex_sleep_forever(VALUE self) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + rb_thread_sleep_deadly_allow_spurious_wakeup(self); return Qnil; } @@ -457,39 +523,46 @@ rb_mutex_wait_for(VALUE time) { rb_hrtime_t *rel = (rb_hrtime_t *)time; /* permit spurious check */ - sleep_hrtime(GET_THREAD(), *rel, 0); - return Qnil; + return RBOOL(sleep_hrtime(GET_THREAD(), *rel, 0)); } VALUE rb_mutex_sleep(VALUE self, VALUE timeout) { - time_t beg, end; struct timeval t; + VALUE woken = Qtrue; if (!NIL_P(timeout)) { t = rb_time_interval(timeout); } rb_mutex_unlock(self); - beg = time(0); - if (NIL_P(timeout)) { - rb_ensure(rb_mutex_sleep_forever, Qnil, mutex_lock_uninterruptible, self); + time_t beg = time(0); + + VALUE scheduler = rb_fiber_scheduler_current(); + if (scheduler != Qnil) { + rb_fiber_scheduler_kernel_sleep(scheduler, timeout); + mutex_lock_uninterruptible(self); } else { - rb_hrtime_t rel = rb_timeval2hrtime(&t); - - rb_ensure(rb_mutex_wait_for, (VALUE)&rel, - mutex_lock_uninterruptible, self); + if (NIL_P(timeout)) { + rb_ensure(rb_mutex_sleep_forever, self, mutex_lock_uninterruptible, self); + } + else { + rb_hrtime_t rel = rb_timeval2hrtime(&t); + woken = rb_ensure(rb_mutex_wait_for, (VALUE)&rel, mutex_lock_uninterruptible, self); + } } + RUBY_VM_CHECK_INTS_BLOCKING(GET_EC()); - end = time(0) - beg; - return INT2FIX(end); + if (!woken) return Qnil; + time_t end = time(0) - beg; + return TIMET2NUM(end); } /* * call-seq: - * mutex.sleep(timeout = nil) -> number + * mutex.sleep(timeout = nil) -> number or nil * * Releases the lock and sleeps +timeout+ seconds if it is given and * non-nil or forever. Raises +ThreadError+ if +mutex+ wasn't locked by @@ -500,6 +573,8 @@ rb_mutex_sleep(VALUE self, VALUE timeout) * * Note that this method can wakeup without explicit Thread#wakeup call. * For example, receiving signal and so on. + * + * Returns the slept time in seconds if woken up, or +nil+ if timed out. */ static VALUE mutex_sleep(int argc, VALUE *argv, VALUE self) @@ -515,7 +590,7 @@ mutex_sleep(int argc, VALUE *argv, VALUE self) * mutex.synchronize { ... } -> result of the block * * Obtains a lock, runs the block, and releases the lock when the block - * completes. See the example under +Mutex+. + * completes. See the example under Thread::Mutex. */ VALUE @@ -530,7 +605,7 @@ rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg) * mutex.synchronize { ... } -> result of the block * * Obtains a lock, runs the block, and releases the lock when the block - * completes. See the example under +Mutex+. + * completes. See the example under Thread::Mutex. */ static VALUE rb_mutex_synchronize_m(VALUE self) @@ -707,7 +782,7 @@ queue_closed_p(VALUE self) * Document-class: ClosedQueueError * * The exception class which will be raised when pushing into a closed - * Queue. See Queue#close and SizedQueue#close. + * Queue. See Thread::Queue#close and Thread::SizedQueue#close. */ NORETURN(static void raise_closed_queue_error(VALUE self)); @@ -726,19 +801,19 @@ queue_closed_result(VALUE self, struct rb_queue *q) } /* - * Document-class: Queue + * Document-class: Thread::Queue * - * The Queue class implements multi-producer, multi-consumer queues. - * It is especially useful in threaded programming when information - * must be exchanged safely between multiple threads. The Queue class - * implements all the required locking semantics. + * The Thread::Queue class implements multi-producer, multi-consumer + * queues. It is especially useful in threaded programming when + * information must be exchanged safely between multiple threads. The + * Thread::Queue class implements all the required locking semantics. * * The class implements FIFO type of queue. In a FIFO queue, the first * tasks added are the first retrieved. * * Example: * - * queue = Queue.new + * queue = Thread::Queue.new * * producer = Thread.new do * 5.times do |i| @@ -763,15 +838,41 @@ queue_closed_result(VALUE self, struct rb_queue *q) /* * Document-method: Queue::new * - * Creates a new queue instance. + * call-seq: + * Thread::Queue.new -> empty_queue + * Thread::Queue.new(enumerable) -> queue + * + * Creates a new queue instance, optionally using the contents of an +enumerable+ + * for its initial state. + * + * Example: + * + * q = Thread::Queue.new + * #=> # + * q.empty? + * #=> true + * + * q = Thread::Queue.new([1, 2, 3]) + * #=> # + * q.empty? + * #=> false + * q.pop + * #=> 1 */ static VALUE -rb_queue_initialize(VALUE self) +rb_queue_initialize(int argc, VALUE *argv, VALUE self) { + VALUE initial; struct rb_queue *q = queue_ptr(self); + if ((argc = rb_scan_args(argc, argv, "01", &initial)) == 1) { + initial = rb_to_array(initial); + } RB_OBJ_WRITE(self, &q->que, ary_buf_new()); list_head_init(queue_waitq(q)); + if (argc == 1) { + rb_ary_concat(q->que, initial); + } return self; } @@ -787,7 +888,7 @@ queue_do_push(VALUE self, struct rb_queue *q, VALUE obj) } /* - * Document-method: Queue#close + * Document-method: Thread::Queue#close * call-seq: * close * @@ -808,9 +909,9 @@ queue_do_push(VALUE self, struct rb_queue *q, VALUE obj) * * ClosedQueueError is inherited from StopIteration, so that you can break loop block. * - * Example: + * Example: * - * q = Queue.new + * q = Thread::Queue.new * Thread.new{ * while e = q.deq # wait for nil to break loop * # ... @@ -834,7 +935,7 @@ rb_queue_close(VALUE self) } /* - * Document-method: Queue#closed? + * Document-method: Thread::Queue#closed? * call-seq: closed? * * Returns +true+ if the queue is closed. @@ -843,11 +944,11 @@ rb_queue_close(VALUE self) static VALUE rb_queue_closed_p(VALUE self) { - return queue_closed_p(self) ? Qtrue : Qfalse; + return RBOOL(queue_closed_p(self)); } /* - * Document-method: Queue#push + * Document-method: Thread::Queue#push * call-seq: * push(object) * enq(object) @@ -863,9 +964,9 @@ rb_queue_push(VALUE self, VALUE obj) } static VALUE -queue_sleep(VALUE arg) +queue_sleep(VALUE self) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + rb_thread_sleep_deadly_allow_spurious_wakeup(self); return Qnil; } @@ -905,25 +1006,30 @@ queue_do_pop(VALUE self, struct rb_queue *q, int should_block) check_array(self, q->que); while (RARRAY_LEN(q->que) == 0) { - if (!should_block) { - rb_raise(rb_eThreadError, "queue empty"); - } - else if (queue_closed_p(self)) { - return queue_closed_result(self, q); - } - else { - struct queue_waiter qw; - - assert(RARRAY_LEN(q->que) == 0); - assert(queue_closed_p(self) == 0); - - qw.w.th = GET_THREAD(); - qw.as.q = q; - list_add_tail(queue_waitq(qw.as.q), &qw.w.node); - qw.as.q->num_waiting++; - - rb_ensure(queue_sleep, self, queue_sleep_done, (VALUE)&qw); - } + if (!should_block) { + rb_raise(rb_eThreadError, "queue empty"); + } + else if (queue_closed_p(self)) { + return queue_closed_result(self, q); + } + else { + rb_execution_context_t *ec = GET_EC(); + + assert(RARRAY_LEN(q->que) == 0); + assert(queue_closed_p(self) == 0); + + struct queue_waiter queue_waiter = { + .w = {.self = self, .th = ec->thread_ptr, .fiber = ec->fiber_ptr}, + .as = {.q = q} + }; + + struct list_head *waitq = queue_waitq(q); + + list_add_tail(waitq, &queue_waiter.w.node); + queue_waiter.as.q->num_waiting++; + + rb_ensure(queue_sleep, self, queue_sleep_done, (VALUE)&queue_waiter); + } } return rb_ary_shift(q->que); @@ -941,7 +1047,7 @@ queue_pop_should_block(int argc, const VALUE *argv) } /* - * Document-method: Queue#pop + * Document-method: Thread::Queue#pop * call-seq: * pop(non_block=false) * deq(non_block=false) @@ -962,7 +1068,7 @@ rb_queue_pop(int argc, VALUE *argv, VALUE self) } /* - * Document-method: Queue#empty? + * Document-method: Thread::Queue#empty? * call-seq: empty? * * Returns +true+ if the queue is empty. @@ -971,11 +1077,11 @@ rb_queue_pop(int argc, VALUE *argv, VALUE self) static VALUE rb_queue_empty_p(VALUE self) { - return queue_length(self, queue_ptr(self)) == 0 ? Qtrue : Qfalse; + return RBOOL(queue_length(self, queue_ptr(self)) == 0); } /* - * Document-method: Queue#clear + * Document-method: Thread::Queue#clear * * Removes all objects from the queue. */ @@ -990,7 +1096,7 @@ rb_queue_clear(VALUE self) } /* - * Document-method: Queue#length + * Document-method: Thread::Queue#length * call-seq: * length * size @@ -1005,7 +1111,7 @@ rb_queue_length(VALUE self) } /* - * Document-method: Queue#num_waiting + * Document-method: Thread::Queue#num_waiting * * Returns the number of threads waiting on the queue. */ @@ -1019,12 +1125,12 @@ rb_queue_num_waiting(VALUE self) } /* - * Document-class: SizedQueue + * Document-class: Thread::SizedQueue * * This class represents queues of specified size capacity. The push operation * may be blocked if the capacity is full. * - * See Queue for an example of how a SizedQueue works. + * See Thread::Queue for an example of how a Thread::SizedQueue works. */ /* @@ -1054,11 +1160,11 @@ rb_szqueue_initialize(VALUE self, VALUE vmax) } /* - * Document-method: SizedQueue#close + * Document-method: Thread::SizedQueue#close * call-seq: * close * - * Similar to Queue#close. + * Similar to Thread::Queue#close. * * The difference is behavior with waiting enqueuing threads. * @@ -1079,7 +1185,7 @@ rb_szqueue_close(VALUE self) } /* - * Document-method: SizedQueue#max + * Document-method: Thread::SizedQueue#max * * Returns the maximum size of the queue. */ @@ -1091,7 +1197,7 @@ rb_szqueue_max_get(VALUE self) } /* - * Document-method: SizedQueue#max= + * Document-method: Thread::SizedQueue#max= * call-seq: max=(number) * * Sets the maximum size of the queue to the given +number+. @@ -1127,7 +1233,7 @@ szqueue_push_should_block(int argc, const VALUE *argv) } /* - * Document-method: SizedQueue#push + * Document-method: Thread::SizedQueue#push * call-seq: * push(object, non_block=false) * enq(object, non_block=false) @@ -1147,28 +1253,30 @@ rb_szqueue_push(int argc, VALUE *argv, VALUE self) int should_block = szqueue_push_should_block(argc, argv); while (queue_length(self, &sq->q) >= sq->max) { - if (!should_block) { - rb_raise(rb_eThreadError, "queue full"); - } - else if (queue_closed_p(self)) { - goto closed; - } - else { - struct queue_waiter qw; - struct list_head *pushq = szqueue_pushq(sq); - - qw.w.th = GET_THREAD(); - qw.as.sq = sq; - list_add_tail(pushq, &qw.w.node); - sq->num_waiting_push++; - - rb_ensure(queue_sleep, self, szqueue_sleep_done, (VALUE)&qw); - } + if (!should_block) { + rb_raise(rb_eThreadError, "queue full"); + } + else if (queue_closed_p(self)) { + break; + } + else { + rb_execution_context_t *ec = GET_EC(); + struct queue_waiter queue_waiter = { + .w = {.self = self, .th = ec->thread_ptr, .fiber = ec->fiber_ptr}, + .as = {.sq = sq} + }; + + struct list_head *pushq = szqueue_pushq(sq); + + list_add_tail(pushq, &queue_waiter.w.node); + sq->num_waiting_push++; + + rb_ensure(queue_sleep, self, szqueue_sleep_done, (VALUE)&queue_waiter); + } } if (queue_closed_p(self)) { - closed: - raise_closed_queue_error(self); + raise_closed_queue_error(self); } return queue_do_push(self, &sq->q, argv[0]); @@ -1188,7 +1296,7 @@ szqueue_do_pop(VALUE self, int should_block) } /* - * Document-method: SizedQueue#pop + * Document-method: Thread::SizedQueue#pop * call-seq: * pop(non_block=false) * deq(non_block=false) @@ -1209,7 +1317,7 @@ rb_szqueue_pop(int argc, VALUE *argv, VALUE self) } /* - * Document-method: SizedQueue#clear + * Document-method: Thread::SizedQueue#clear * * Removes all objects from the queue. */ @@ -1225,7 +1333,7 @@ rb_szqueue_clear(VALUE self) } /* - * Document-method: SizedQueue#length + * Document-method: Thread::SizedQueue#length * call-seq: * length * size @@ -1242,7 +1350,7 @@ rb_szqueue_length(VALUE self) } /* - * Document-method: SizedQueue#num_waiting + * Document-method: Thread::SizedQueue#num_waiting * * Returns the number of threads waiting on the queue. */ @@ -1256,7 +1364,7 @@ rb_szqueue_num_waiting(VALUE self) } /* - * Document-method: SizedQueue#empty? + * Document-method: Thread::SizedQueue#empty? * call-seq: empty? * * Returns +true+ if the queue is empty. @@ -1267,7 +1375,7 @@ rb_szqueue_empty_p(VALUE self) { struct rb_szqueue *sq = szqueue_ptr(self); - return queue_length(self, &sq->q) == 0 ? Qtrue : Qfalse; + return RBOOL(queue_length(self, &sq->q) == 0); } @@ -1278,7 +1386,7 @@ struct rb_condvar { }; /* - * Document-class: ConditionVariable + * Document-class: Thread::ConditionVariable * * ConditionVariable objects augment class Mutex. Using condition variables, * it is possible to suspend while in the middle of a critical section until a @@ -1286,8 +1394,8 @@ struct rb_condvar { * * Example: * - * mutex = Mutex.new - * resource = ConditionVariable.new + * mutex = Thread::Mutex.new + * resource = Thread::ConditionVariable.new * * a = Thread.new { * mutex.synchronize { @@ -1374,43 +1482,40 @@ do_sleep(VALUE args) return rb_funcallv(p->mutex, id_sleep, 1, &p->timeout); } -static VALUE -delete_from_waitq(VALUE v) -{ - struct sync_waiter *w = (void *)v; - list_del(&w->node); - - return Qnil; -} - /* - * Document-method: ConditionVariable#wait + * Document-method: Thread::ConditionVariable#wait * call-seq: wait(mutex, timeout=nil) * * Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup. * * If +timeout+ is given, this method returns after +timeout+ seconds passed, * even if no other thread doesn't signal. + * + * Returns the slept result on +mutex+. */ static VALUE rb_condvar_wait(int argc, VALUE *argv, VALUE self) { + rb_execution_context_t *ec = GET_EC(); + struct rb_condvar *cv = condvar_ptr(self); struct sleep_call args; - struct sync_waiter w; rb_scan_args(argc, argv, "11", &args.mutex, &args.timeout); - w.th = GET_THREAD(); - list_add_tail(&cv->waitq, &w.node); - rb_ensure(do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)&w); + struct sync_waiter sync_waiter = { + .self = args.mutex, + .th = ec->thread_ptr, + .fiber = ec->fiber_ptr + }; - return self; + list_add_tail(&cv->waitq, &sync_waiter.node); + return rb_ensure(do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)&sync_waiter); } /* - * Document-method: ConditionVariable#signal + * Document-method: Thread::ConditionVariable#signal * * Wakes up the first thread in line waiting for this lock. */ @@ -1424,7 +1529,7 @@ rb_condvar_signal(VALUE self) } /* - * Document-method: ConditionVariable#broadcast + * Document-method: Thread::ConditionVariable#broadcast * * Wakes up all threads waiting for this lock. */ @@ -1437,6 +1542,7 @@ rb_condvar_broadcast(VALUE self) return self; } +NORETURN(static VALUE undumpable(VALUE obj)); /* :nodoc: */ static VALUE undumpable(VALUE obj) @@ -1446,10 +1552,10 @@ undumpable(VALUE obj) } static VALUE -define_thread_class(VALUE outer, const char *name, VALUE super) +define_thread_class(VALUE outer, const ID name, VALUE super) { - VALUE klass = rb_define_class_under(outer, name, super); - rb_define_const(rb_cObject, name, klass); + VALUE klass = rb_define_class_id_under(outer, name, super); + rb_const_set(rb_cObject, name, klass); return klass; } @@ -1457,15 +1563,15 @@ static void Init_thread_sync(void) { #undef rb_intern -#if 0 - rb_cMutex = rb_define_class("Mutex", rb_cObject); /* teach rdoc Mutex */ - rb_cConditionVariable = rb_define_class("ConditionVariable", rb_cObject); /* teach rdoc ConditionVariable */ - rb_cQueue = rb_define_class("Queue", rb_cObject); /* teach rdoc Queue */ - rb_cSizedQueue = rb_define_class("SizedQueue", rb_cObject); /* teach rdoc SizedQueue */ +#if defined(TEACH_RDOC) && TEACH_RDOC == 42 + rb_cMutex = rb_define_class_under(rb_cThread, "Mutex", rb_cObject); + rb_cConditionVariable = rb_define_class_under(rb_cThread, "ConditionVariable", rb_cObject); + rb_cQueue = rb_define_class_under(rb_cThread, "Queue", rb_cObject); + rb_cSizedQueue = rb_define_class_under(rb_cThread, "SizedQueue", rb_cObject); #endif #define DEFINE_CLASS(name, super) \ - rb_c##name = define_thread_class(rb_cThread, #name, rb_c##super) + rb_c##name = define_thread_class(rb_cThread, rb_intern(#name), rb_c##super) /* Mutex */ DEFINE_CLASS(Mutex, Object); @@ -1485,7 +1591,7 @@ Init_thread_sync(void) rb_eClosedQueueError = rb_define_class("ClosedQueueError", rb_eStopIteration); - rb_define_method(rb_cQueue, "initialize", rb_queue_initialize, 0); + rb_define_method(rb_cQueue, "initialize", rb_queue_initialize, -1); rb_undef_method(rb_cQueue, "initialize_copy"); rb_define_method(rb_cQueue, "marshal_dump", undumpable, 0); rb_define_method(rb_cQueue, "close", rb_queue_close, 0); diff --git a/ruby/thread_win32.c b/ruby/thread_win32.c index d8eb2b1ee..026ccc4c6 100644 --- a/ruby/thread_win32.c +++ b/ruby/thread_win32.c @@ -28,9 +28,8 @@ static volatile DWORD ruby_native_thread_key = TLS_OUT_OF_INDEXES; static int w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th); -void rb_native_mutex_lock(rb_nativethread_lock_t *lock); -void rb_native_mutex_unlock(rb_nativethread_lock_t *lock); +RBIMPL_ATTR_NORETURN() static void w32_error(const char *func) { @@ -51,15 +50,16 @@ w32_error(const char *func) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); rb_bug("%s: %s", func, (char*)lpMsgBuf); + UNREACHABLE; } static int -w32_mutex_lock(HANDLE lock) +w32_mutex_lock(HANDLE lock, bool try) { DWORD result; while (1) { thread_debug("rb_native_mutex_lock: %p\n", lock); - result = w32_wait_events(&lock, 1, INFINITE, 0); + result = w32_wait_events(&lock, 1, try ? 0 : INFINITE, 0); switch (result) { case WAIT_OBJECT_0: /* get mutex object */ @@ -72,7 +72,7 @@ w32_mutex_lock(HANDLE lock) return 0; case WAIT_TIMEOUT: thread_debug("timeout mutex: %p\n", lock); - break; + return EBUSY; case WAIT_ABANDONED: rb_bug("win32_mutex_lock: WAIT_ABANDONED"); break; @@ -97,56 +97,64 @@ w32_mutex_create(void) #define GVL_DEBUG 0 static void -gvl_acquire(rb_vm_t *vm, rb_thread_t *th) +gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th) { - w32_mutex_lock(vm->gvl.lock); + w32_mutex_lock(gvl->lock, false); if (GVL_DEBUG) fprintf(stderr, "gvl acquire (%p): acquire\n", th); } static void -gvl_release(rb_vm_t *vm) +gvl_release(rb_global_vm_lock_t *gvl) { - ReleaseMutex(vm->gvl.lock); + ReleaseMutex(gvl->lock); } static void -gvl_yield(rb_vm_t *vm, rb_thread_t *th) +gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th) { - gvl_release(th->vm); + gvl_release(gvl); native_thread_yield(); - gvl_acquire(vm, th); + gvl_acquire(gvl, th); } -static void -gvl_init(rb_vm_t *vm) +void +rb_gvl_init(rb_global_vm_lock_t *gvl) { if (GVL_DEBUG) fprintf(stderr, "gvl init\n"); - vm->gvl.lock = w32_mutex_create(); + gvl->lock = w32_mutex_create(); } static void -gvl_destroy(rb_vm_t *vm) +gvl_destroy(rb_global_vm_lock_t *gvl) { if (GVL_DEBUG) fprintf(stderr, "gvl destroy\n"); - CloseHandle(vm->gvl.lock); + CloseHandle(gvl->lock); } -static rb_thread_t * +rb_thread_t * ruby_thread_from_native(void) { return TlsGetValue(ruby_native_thread_key); } -static int +int ruby_thread_set_native(rb_thread_t *th) { + if (th && th->ec) { + rb_ractor_set_current_ec(th->ractor, th->ec); + } return TlsSetValue(ruby_native_thread_key, th); } void Init_native_thread(rb_thread_t *th) { - ruby_native_thread_key = TlsAlloc(); + if ((ruby_current_ec_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { + rb_bug("TlsAlloc() for ruby_current_ec_key fails"); + } + if ((ruby_native_thread_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { + rb_bug("TlsAlloc() for ruby_native_thread_key fails"); + } ruby_thread_set_native(th); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), @@ -316,17 +324,27 @@ native_sleep(rb_thread_t *th, rb_hrtime_t *rel) void rb_native_mutex_lock(rb_nativethread_lock_t *lock) { -#if USE_WIN32_MUTEX - w32_mutex_lock(lock->mutex); +#ifdef USE_WIN32_MUTEX + w32_mutex_lock(lock->mutex, false); #else EnterCriticalSection(&lock->crit); #endif } +int +rb_native_mutex_trylock(rb_nativethread_lock_t *lock) +{ +#ifdef USE_WIN32_MUTEX + return w32_mutex_lock(lock->mutex, true); +#else + return TryEnterCriticalSection(&lock->crit) == 0 ? EBUSY : 0; +#endif +} + void rb_native_mutex_unlock(rb_nativethread_lock_t *lock) { -#if USE_WIN32_MUTEX +#ifdef USE_WIN32_MUTEX thread_debug("release mutex: %p\n", lock->mutex); ReleaseMutex(lock->mutex); #else @@ -334,30 +352,10 @@ rb_native_mutex_unlock(rb_nativethread_lock_t *lock) #endif } -static int -native_mutex_trylock(rb_nativethread_lock_t *lock) -{ -#if USE_WIN32_MUTEX - int result; - thread_debug("native_mutex_trylock: %p\n", lock->mutex); - result = w32_wait_events(&lock->mutex, 1, 1, 0); - thread_debug("native_mutex_trylock result: %d\n", result); - switch (result) { - case WAIT_OBJECT_0: - return 0; - case WAIT_TIMEOUT: - return EBUSY; - } - return EINVAL; -#else - return TryEnterCriticalSection(&lock->crit) == 0; -#endif -} - void rb_native_mutex_initialize(rb_nativethread_lock_t *lock) { -#if USE_WIN32_MUTEX +#ifdef USE_WIN32_MUTEX lock->mutex = w32_mutex_create(); /* thread_debug("initialize mutex: %p\n", lock->mutex); */ #else @@ -368,7 +366,7 @@ rb_native_mutex_initialize(rb_nativethread_lock_t *lock) void rb_native_mutex_destroy(rb_nativethread_lock_t *lock) { -#if USE_WIN32_MUTEX +#ifdef USE_WIN32_MUTEX w32_close_handle(lock->mutex); #else DeleteCriticalSection(&lock->crit); @@ -458,7 +456,6 @@ rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex) native_cond_timedwait_ms(cond, mutex, INFINITE); } -#if 0 static unsigned long abs_timespec_to_timeout_ms(const struct timespec *ts) { @@ -487,6 +484,19 @@ native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mute return native_cond_timedwait_ms(cond, mutex, timeout_ms); } +static struct timespec native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel); + +void +rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec) +{ + struct timespec rel = { + .tv_sec = msec / 1000, + .tv_nsec = (msec % 1000) * 1000 * 1000, + }; + struct timespec ts = native_cond_timeout(cond, rel); + native_cond_timedwait(cond, mutex, &ts); +} + static struct timespec native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel) { @@ -516,7 +526,6 @@ native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel) return timeout; } -#endif void rb_native_cond_initialize(rb_nativethread_cond_t *cond) @@ -539,6 +548,17 @@ ruby_init_stack(volatile VALUE *addr) #define CHECK_ERR(expr) \ {if (!(expr)) {rb_bug("err: %lu - %s", GetLastError(), #expr);}} +COMPILER_WARNING_PUSH +#if defined(__GNUC__) +COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) +#endif +static inline SIZE_T +query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi) +{ + return VirtualQuery(mi, mi, sizeof(*mi)); +} +COMPILER_WARNING_POP + static void native_thread_init_stack(rb_thread_t *th) { @@ -546,7 +566,7 @@ native_thread_init_stack(rb_thread_t *th) char *base, *end; DWORD size, space; - CHECK_ERR(VirtualQuery(&mi, &mi, sizeof(mi))); + CHECK_ERR(query_memory_basic_info(&mi)); base = mi.AllocationBase; end = mi.BaseAddress; end += mi.RegionSize; @@ -692,11 +712,11 @@ timer_thread_func(void *dummy) rb_vm_t *vm = GET_VM(); thread_debug("timer_thread\n"); rb_w32_set_thread_description(GetCurrentThread(), L"ruby-timer-thread"); - while (WaitForSingleObject(timer_thread.lock, TIME_QUANTUM_USEC/1000) == - WAIT_TIMEOUT) { - timer_thread_function(); + while (WaitForSingleObject(timer_thread.lock, + TIME_QUANTUM_USEC/1000) == WAIT_TIMEOUT) { + vm->clock++; ruby_sigchld_handler(vm); /* probably no-op */ - rb_threadptr_check_signal(vm->main_thread); + rb_threadptr_check_signal(vm->ractor.main_thread); } thread_debug("timer killed\n"); return 0; @@ -817,6 +837,15 @@ native_set_thread_name(rb_thread_t *th) { } +static VALUE +native_thread_native_thread_id(rb_thread_t *th) +{ + DWORD tid = GetThreadId(th->thread_id); + if (tid == 0) rb_sys_fail("GetThreadId"); + return ULONG2NUM(tid); +} +#define USE_NATIVE_THREAD_NATIVE_THREAD_ID 1 + #if USE_MJIT static unsigned long __stdcall mjit_worker(void *arg) diff --git a/ruby/thread_win32.h b/ruby/thread_win32.h index 60083da0a..994949d2b 100644 --- a/ruby/thread_win32.h +++ b/ruby/thread_win32.h @@ -1,3 +1,5 @@ +#ifndef RUBY_THREAD_WIN32_H +#define RUBY_THREAD_WIN32_H /********************************************************************** thread_win32.h - @@ -9,20 +11,20 @@ **********************************************************************/ /* interface */ -#ifndef RUBY_THREAD_WIN32_H -#define RUBY_THREAD_WIN32_H # ifdef __CYGWIN__ # undef _WIN32 # endif +#define USE_VM_CLOCK 1 + WINBASEAPI BOOL WINAPI TryEnterCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); -typedef struct rb_thread_cond_struct { +struct rb_thread_cond_struct { struct cond_event_entry *next; struct cond_event_entry *prev; -} rb_nativethread_cond_t; +}; typedef struct native_thread_data_struct { HANDLE interrupt_event; @@ -32,5 +34,28 @@ typedef struct rb_global_vm_lock_struct { HANDLE lock; } rb_global_vm_lock_t; -#endif /* RUBY_THREAD_WIN32_H */ +typedef DWORD native_tls_key_t; // TLS index + +static inline void * +native_tls_get(native_tls_key_t key) +{ + void *ptr = TlsGetValue(key); + if (UNLIKELY(ptr == NULL)) { + rb_bug("TlsGetValue() returns NULL"); + } + return ptr; +} + +static inline void +native_tls_set(native_tls_key_t key, void *ptr) +{ + if (UNLIKELY(TlsSetValue(key, ptr) == 0)) { + rb_bug("TlsSetValue() error"); + } +} + +RUBY_SYMBOL_EXPORT_BEGIN +RUBY_EXTERN native_tls_key_t ruby_current_ec_key; +RUBY_SYMBOL_EXPORT_END +#endif /* RUBY_THREAD_WIN32_H */ diff --git a/ruby/time.c b/ruby/time.c index d71d43e05..77f42fc89 100644 --- a/ruby/time.c +++ b/ruby/time.c @@ -11,34 +11,46 @@ #define _DEFAULT_SOURCE #define _BSD_SOURCE -#include "ruby/encoding.h" -#include "internal.h" -#include -#include +#include "ruby/internal/config.h" + #include +#include +#include +#include +#include #ifdef HAVE_UNISTD_H -#include +# include #endif -#include -#include - #ifdef HAVE_STRINGS_H -#include +# include #endif #if defined(HAVE_SYS_TIME_H) -#include +# include #endif -#include "timev.h" #include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/compar.h" +#include "internal/numeric.h" +#include "internal/rational.h" +#include "internal/string.h" +#include "internal/time.h" +#include "internal/variable.h" +#include "ruby/encoding.h" +#include "timev.h" + +#include "builtin.h" static ID id_submicro, id_nano_num, id_nano_den, id_offset, id_zone; static ID id_nanosecond, id_microsecond, id_millisecond, id_nsec, id_usec; static ID id_local_to_utc, id_utc_to_local, id_find_timezone; static ID id_year, id_mon, id_mday, id_hour, id_min, id_sec, id_isdst; +static VALUE str_utc, str_empty; + #define id_quo idQuo #define id_div idDiv #define id_divmod idDivmod @@ -75,7 +87,7 @@ cmp(VALUE x, VALUE y) return 1; return 0; } - if (RB_TYPE_P(x, T_BIGNUM)) return FIX2INT(rb_big_cmp(x, y)); + if (RB_BIGNUM_TYPE_P(x)) return FIX2INT(rb_big_cmp(x, y)); return rb_cmpint(rb_funcall(x, idCmp, 1, y), x, y); } @@ -91,7 +103,7 @@ addv(VALUE x, VALUE y) if (FIXNUM_P(x) && FIXNUM_P(y)) { return LONG2NUM(FIX2LONG(x) + FIX2LONG(y)); } - if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_plus(x, y); + if (RB_BIGNUM_TYPE_P(x)) return rb_big_plus(x, y); return rb_funcall(x, '+', 1, y); } @@ -101,7 +113,7 @@ subv(VALUE x, VALUE y) if (FIXNUM_P(x) && FIXNUM_P(y)) { return LONG2NUM(FIX2LONG(x) - FIX2LONG(y)); } - if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_minus(x, y); + if (RB_BIGNUM_TYPE_P(x)) return rb_big_minus(x, y); return rb_funcall(x, '-', 1, y); } @@ -111,7 +123,7 @@ mulv(VALUE x, VALUE y) if (FIXNUM_P(x) && FIXNUM_P(y)) { return rb_fix_mul_fix(x, y); } - if (RB_TYPE_P(x, T_BIGNUM)) + if (RB_BIGNUM_TYPE_P(x)) return rb_big_mul(x, y); return rb_funcall(x, '*', 1, y); } @@ -122,7 +134,7 @@ divv(VALUE x, VALUE y) if (FIXNUM_P(x) && FIXNUM_P(y)) { return rb_fix_div_fix(x, y); } - if (RB_TYPE_P(x, T_BIGNUM)) + if (RB_BIGNUM_TYPE_P(x)) return rb_big_div(x, y); return rb_funcall(x, id_div, 1, y); } @@ -134,7 +146,7 @@ modv(VALUE x, VALUE y) if (FIX2LONG(y) == 0) rb_num_zerodiv(); if (FIXNUM_P(x)) return rb_fix_mod_fix(x, y); } - if (RB_TYPE_P(x, T_BIGNUM)) return rb_big_modulo(x, y); + if (RB_BIGNUM_TYPE_P(x)) return rb_big_modulo(x, y); return rb_funcall(x, '%', 1, y); } @@ -310,7 +322,7 @@ v2w(VALUE v) if (FIXNUM_P(v)) { return WIDEVAL_WRAP((WIDEVALUE)(SIGNED_WIDEVALUE)(long)v); } - else if (RB_TYPE_P(v, T_BIGNUM) && + else if (RB_BIGNUM_TYPE_P(v) && rb_absint_size(v, NULL) <= sizeof(WIDEVALUE)) { return v2w_bignum(v); } @@ -502,47 +514,37 @@ num_exact(VALUE v) { VALUE tmp; - if (NIL_P(v)) { - rb_raise(rb_eTypeError, "can't convert nil into an exact number"); - } - else if (RB_INTEGER_TYPE_P(v)) { + switch (TYPE(v)) { + case T_FIXNUM: + case T_BIGNUM: return v; - } - else if (RB_TYPE_P(v, T_RATIONAL)) { - goto rational; - } - else if (RB_TYPE_P(v, T_STRING)) { - goto typeerror; - } - else { + + case T_RATIONAL: + return rb_rational_canonicalize(v); + + default: if ((tmp = rb_check_funcall(v, idTo_r, 0, NULL)) != Qundef) { /* test to_int method availability to reject non-Numeric * objects such as String, Time, etc which have to_r method. */ - if (!rb_respond_to(v, idTo_int)) goto typeerror; + if (!rb_respond_to(v, idTo_int)) { + /* FALLTHROUGH */ + } + else if (RB_INTEGER_TYPE_P(tmp)) { + return tmp; + } + else if (RB_TYPE_P(tmp, T_RATIONAL)) { + return rb_rational_canonicalize(tmp); + } } else if (!NIL_P(tmp = rb_check_to_int(v))) { return tmp; } - else { - goto typeerror; - } - } - if (RB_INTEGER_TYPE_P(tmp)) { - v = tmp; - } - else if (RB_TYPE_P(tmp, T_RATIONAL)) { - v = tmp; - rational: - if (RRATIONAL(v)->den == INT2FIX(1)) - v = RRATIONAL(v)->num; - } - else { - typeerror: + case T_NIL: + case T_STRING: rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into an exact number", rb_obj_class(v)); } - return v; } /* time_t */ @@ -646,7 +648,7 @@ VALUE rb_cTime; static VALUE rb_cTimeTM; static int obj2int(VALUE obj); -static uint32_t obj2ubits(VALUE obj, size_t bits); +static uint32_t obj2ubits(VALUE obj, unsigned int bits); static VALUE obj2vint(VALUE obj); static uint32_t month_arg(VALUE arg); static VALUE validate_utc_offset(VALUE utc_offset); @@ -673,6 +675,13 @@ static VALUE tm_from_time(VALUE klass, VALUE time); bool ruby_tz_uptodate_p; +void +ruby_reset_timezone(void) +{ + ruby_tz_uptodate_p = false; + ruby_reset_leap_second_info(); +} + static void update_tz(void) { @@ -735,7 +744,7 @@ rb_gmtime_r(const time_t *t, struct tm *result) # define GMTIME(tm, result) rb_gmtime_r((tm), &(result)) #endif -static const int common_year_yday_offset[] = { +static const int16_t common_year_yday_offset[] = { -1, -1 + 31, -1 + 31 + 28, @@ -750,7 +759,7 @@ static const int common_year_yday_offset[] = { -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 /* 1 2 3 4 5 6 7 8 9 10 11 */ }; -static const int leap_year_yday_offset[] = { +static const int16_t leap_year_yday_offset[] = { -1, -1 + 31, -1 + 31 + 29, @@ -766,13 +775,17 @@ static const int leap_year_yday_offset[] = { /* 1 2 3 4 5 6 7 8 9 10 11 */ }; -static const int common_year_days_in_month[] = { +static const int8_t common_year_days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const int leap_year_days_in_month[] = { +static const int8_t leap_year_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +#define days_in_month_of(leap) ((leap) ? leap_year_days_in_month : common_year_days_in_month) +#define days_in_month_in(y) days_in_month_of(leap_year_p(y)) +#define days_in_month_in_v(y) days_in_month_of(leap_year_v_p(y)) + #define M28(m) \ (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \ (m),(m),(m),(m),(m),(m),(m),(m),(m),(m), \ @@ -1015,7 +1028,7 @@ gmtimew_noleapsecond(wideval_t timew, struct vtm *vtm) } vtm->utc_offset = INT2FIX(0); - vtm->zone = rb_fstring_lit("UTC"); + vtm->zone = str_utc; } static struct tm * @@ -1097,9 +1110,7 @@ gmtime_with_leapsecond(const time_t *timep, struct tm *result) result->tm_yday = leap_year_p(result->tm_year + 1900) ? 365 : 364; } else if (result->tm_mday == 1) { - const int *days_in_month = leap_year_p(result->tm_year + 1900) ? - leap_year_days_in_month : - common_year_days_in_month; + const int8_t *days_in_month = days_in_month_of(result->tm_year + 1900); result->tm_mon--; result->tm_mday = days_in_month[result->tm_mon]; result->tm_yday--; @@ -1118,8 +1129,7 @@ gmtime_with_leapsecond(const time_t *timep, struct tm *result) result->tm_mday = 1; result->tm_yday = 0; } - else if (result->tm_mday == (leap ? leap_year_days_in_month : - common_year_days_in_month)[result->tm_mon]) { + else if (result->tm_mday == days_in_month_of(leap)[result->tm_mon]) { result->tm_mon++; result->tm_mday = 1; result->tm_yday++; @@ -1160,7 +1170,11 @@ init_leap_second_info(void) struct vtm vtm; wideval_t timew; now = time(NULL); +#ifdef HAVE_GMTIME_R + gmtime_r(&now, &result); +#else gmtime(&now); +#endif tm = gmtime_with_leapsecond(&now, &result); if (!tm) return; this_year = tm->tm_year; @@ -1295,7 +1309,7 @@ gmtimew(wideval_t timew, struct vtm *result) static struct tm *localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VALUE *zone); /* - * The idea is borrowed from Perl: + * The idea, extrapolate localtime() function, is borrowed from Perl: * http://web.archive.org/web/20080211114141/http://use.perl.org/articles/08/02/07/197204.shtml * * compat_common_month_table is generated by the following program. @@ -1447,7 +1461,7 @@ guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, VALUE *zone_ret) timev = w2v(rb_time_unmagnify(timegmw(&vtm2))); t = NUM2TIMET(timev); - zone = rb_fstring_lit("UTC"); + zone = str_utc; if (localtime_with_gmtoff_zone(&t, &tm, &gmtoff, &zone)) { if (isdst_ret) *isdst_ret = tm.tm_isdst; @@ -1613,7 +1627,7 @@ localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VAL #if defined(HAVE_TM_ZONE) *zone = zone_str(tm.tm_zone); #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT) -# if RUBY_MSVCRT_VERSION >= 140 +# if defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 140 # define tzname _tzname # define daylight _daylight # endif @@ -1757,6 +1771,14 @@ static VALUE time_get_tm(VALUE, struct time_object *); time_get_tm((time), (tobj)); \ } \ } while (0) +#define MAKE_TM_ENSURE(time, tobj, cond) \ + do { \ + MAKE_TM(time, tobj); \ + if (!(cond)) { \ + VALUE zone = (tobj)->vtm.zone; \ + if (!NIL_P(zone)) zone_localtime(zone, (time)); \ + } \ + } while (0) static void time_mark(void *ptr) @@ -1779,7 +1801,8 @@ time_memsize(const void *tobj) static const rb_data_type_t time_data_type = { "time", {time_mark, RUBY_TYPED_DEFAULT_FREE, time_memsize,}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, + (RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE), }; static VALUE @@ -1826,13 +1849,13 @@ time_modify(VALUE time) } static wideval_t -timespec2timew(struct timespec *ts) +timenano2timew(time_t sec, long nsec) { wideval_t timew; - timew = rb_time_magnify(TIMET2WV(ts->tv_sec)); - if (ts->tv_nsec) - timew = wadd(timew, wmulquoll(WINT2WV(ts->tv_nsec), TIME_SCALE, 1000000000)); + timew = rb_time_magnify(TIMET2WV(sec)); + if (nsec) + timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000)); return timew; } @@ -1889,7 +1912,7 @@ rb_timespec_now(struct timespec *ts) } static VALUE -time_init_0(VALUE time) +time_init_now(rb_execution_context_t *ec, VALUE time, VALUE zone) { struct time_object *tobj; struct timespec ts; @@ -1900,8 +1923,11 @@ time_init_0(VALUE time) tobj->tm_got=0; tobj->timew = WINT2FIXWV(0); rb_timespec_now(&ts); - tobj->timew = timespec2timew(&ts); + tobj->timew = timenano2timew(ts.tv_sec, ts.tv_nsec); + if (!NIL_P(zone)) { + time_zonelocal(time, zone); + } return time; } @@ -1959,10 +1985,8 @@ vtm_add_offset(struct vtm *vtm, VALUE off, int sign) vtm->subsecx = subv(vtm->subsecx, INT2FIX(TIME_SCALE)); sec += 1; } - goto not_zero_sec; } if (sec) { - not_zero_sec: /* If sec + subsec == 0, don't change vtm->sec. * It may be 60 which is a leap second. */ sec += vtm->sec; @@ -2010,9 +2034,7 @@ vtm_add_offset(struct vtm *vtm, VALUE off, int sign) vtm->yday = leap_year_v_p(vtm->year) ? 366 : 365; } else if (vtm->mday == 1) { - const int *days_in_month = leap_year_v_p(vtm->year) ? - leap_year_days_in_month : - common_year_days_in_month; + const int8_t *days_in_month = days_in_month_in_v(vtm->year); vtm->mon--; vtm->mday = days_in_month[vtm->mon-1]; vtm->yday--; @@ -2031,8 +2053,7 @@ vtm_add_offset(struct vtm *vtm, VALUE off, int sign) vtm->mday = 1; vtm->yday = 1; } - else if (vtm->mday == (leap ? leap_year_days_in_month : - common_year_days_in_month)[vtm->mon-1]) { + else if (vtm->mday == days_in_month_of(leap)[vtm->mon-1]) { vtm->mon++; vtm->mday = 1; vtm->yday++; @@ -2055,14 +2076,13 @@ maybe_tzobj_p(VALUE obj) return TRUE; } -NORETURN(static void invalid_utc_offset(void)); +NORETURN(static void invalid_utc_offset(VALUE)); static void -invalid_utc_offset(void) +invalid_utc_offset(VALUE zone) { - static const char message[] = "\"+HH:MM\", \"-HH:MM\", \"UTC\" " - "or \"A\"..\"I\",\"K\"..\"Z\" expected for utc_offset"; - VALUE str = rb_usascii_str_new_static(message, sizeof(message)-1); - rb_exc_raise(rb_exc_new_str(rb_eArgError, str)); + rb_raise(rb_eArgError, "\"+HH:MM\", \"-HH:MM\", \"UTC\" or " + "\"A\"..\"I\",\"K\"..\"Z\" expected for utc_offset: %"PRIsVALUE, + zone); } static VALUE @@ -2071,10 +2091,9 @@ utc_offset_arg(VALUE arg) VALUE tmp; if (!NIL_P(tmp = rb_check_string_type(arg))) { int n = 0; - char *s = RSTRING_PTR(tmp); + const char *s = RSTRING_PTR(tmp), *min = NULL, *sec = NULL; if (!rb_enc_str_asciicompat_p(tmp)) { - invalid_utc_offset: - return Qnil; + goto invalid_utc_offset; } switch (RSTRING_LEN(tmp)) { case 1: @@ -2100,31 +2119,49 @@ utc_offset_arg(VALUE arg) if (STRNCASECMP("UTC", s, 3) == 0) { return UTC_ZONE; } - goto invalid_utc_offset; - case 9: - if (s[6] != ':') goto invalid_utc_offset; - if (!ISDIGIT(s[7]) || !ISDIGIT(s[8])) goto invalid_utc_offset; - n += (s[7] * 10 + s[8] - '0' * 11); - /* fall through */ - case 6: - if (s[0] != '+' && s[0] != '-') goto invalid_utc_offset; - if (!ISDIGIT(s[1]) || !ISDIGIT(s[2])) goto invalid_utc_offset; - if (s[3] != ':') goto invalid_utc_offset; - if (!ISDIGIT(s[4]) || !ISDIGIT(s[5])) goto invalid_utc_offset; - if (s[4] > '5') goto invalid_utc_offset; - break; + break; /* +HH */ + case 5: /* +HHMM */ + min = s+3; + break; + case 6: /* +HH:MM */ + min = s+4; + break; + case 7: /* +HHMMSS */ + sec = s+5; + min = s+3; + break; + case 9: /* +HH:MM:SS */ + sec = s+7; + min = s+4; + break; default: goto invalid_utc_offset; } + if (sec) { + if (sec == s+7 && *(sec-1) != ':') goto invalid_utc_offset; + if (!ISDIGIT(sec[0]) || !ISDIGIT(sec[1])) goto invalid_utc_offset; + n += (sec[0] * 10 + sec[1] - '0' * 11); + } + if (min) { + if (min == s+4 && *(min-1) != ':') goto invalid_utc_offset; + if (!ISDIGIT(min[0]) || !ISDIGIT(min[1])) goto invalid_utc_offset; + if (min[0] > '5') goto invalid_utc_offset; + n += (min[0] * 10 + min[1] - '0' * 11) * 60; + } + if (s[0] != '+' && s[0] != '-') goto invalid_utc_offset; + if (!ISDIGIT(s[1]) || !ISDIGIT(s[2])) goto invalid_utc_offset; n += (s[1] * 10 + s[2] - '0' * 11) * 3600; - n += (s[4] * 10 + s[5] - '0' * 11) * 60; - if (s[0] == '-') + if (s[0] == '-') { + if (n == 0) return UTC_ZONE; n = -n; + } return INT2FIX(n); } else { return num_exact(arg); } + invalid_utc_offset: + return Qnil; } static void @@ -2281,45 +2318,41 @@ find_timezone(VALUE time, VALUE zone) } static VALUE -time_init_1(int argc, VALUE *argv, VALUE time) +time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VALUE mday, VALUE hour, VALUE min, VALUE sec, VALUE zone) { struct vtm vtm; - VALUE zone = Qnil; VALUE utc = Qnil; - VALUE v[7]; struct time_object *tobj; vtm.wday = VTM_WDAY_INITVAL; vtm.yday = 0; - vtm.zone = rb_fstring_lit(""); - - /* year mon mday hour min sec off */ - rb_scan_args(argc, argv, "16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]); + vtm.zone = str_empty; - vtm.year = obj2vint(v[0]); + vtm.year = obj2vint(year); - vtm.mon = NIL_P(v[1]) ? 1 : month_arg(v[1]); + vtm.mon = NIL_P(mon) ? 1 : month_arg(mon); - vtm.mday = NIL_P(v[2]) ? 1 : obj2ubits(v[2], 5); + vtm.mday = NIL_P(mday) ? 1 : obj2ubits(mday, 5); - vtm.hour = NIL_P(v[3]) ? 0 : obj2ubits(v[3], 5); + vtm.hour = NIL_P(hour) ? 0 : obj2ubits(hour, 5); - vtm.min = NIL_P(v[4]) ? 0 : obj2ubits(v[4], 6); + vtm.min = NIL_P(min) ? 0 : obj2ubits(min, 6); - if (NIL_P(v[5])) { + if (NIL_P(sec)) { vtm.sec = 0; vtm.subsecx = INT2FIX(0); } else { VALUE subsecx; - vtm.sec = obj2subsecx(v[5], &subsecx); + vtm.sec = obj2subsecx(sec, &subsecx); vtm.subsecx = subsecx; } vtm.isdst = VTM_ISDST_INITVAL; vtm.utc_offset = Qnil; - if (!NIL_P(v[6])) { - VALUE arg = v[6]; + const VALUE arg = zone; + if (!NIL_P(arg)) { + zone = Qnil; if (arg == ID2SYM(rb_intern("dst"))) vtm.isdst = 1; else if (arg == ID2SYM(rb_intern("std"))) @@ -2329,7 +2362,7 @@ time_init_1(int argc, VALUE *argv, VALUE time) else if (!NIL_P(utc = utc_offset_arg(arg))) vtm.utc_offset = utc == UTC_ZONE ? INT2FIX(0) : utc; else if (NIL_P(zone = find_timezone(time, arg))) - invalid_utc_offset(); + invalid_utc_offset(arg); } validate_vtm(&vtm); @@ -2347,7 +2380,7 @@ time_init_1(int argc, VALUE *argv, VALUE time) } else if (NIL_P(vtm.utc_offset = utc_offset_arg(zone))) { if (NIL_P(zone = find_timezone(time, zone)) || !zone_timelocal(zone, time)) - invalid_utc_offset(); + invalid_utc_offset(arg); } } @@ -2376,85 +2409,27 @@ time_init_1(int argc, VALUE *argv, VALUE time) } } - -/* - * call-seq: - * Time.new -> time - * Time.new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, tz=nil) -> time - * - * Returns a Time object. - * - * It is initialized to the current system time if no argument is given. - * - * *Note:* The new object will use the resolution available on your - * system clock, and may include fractional seconds. - * - * If one or more arguments are specified, the time is initialized to the - * specified time. - * - * +sec+ may have fraction if it is a rational. - * - * +tz+ specifies the timezone. - * It can be an offset from UTC, given either as a string such as "+09:00" - * or a single letter "A".."Z" excluding "J" (so-called military time zone), - * or as a number of seconds such as 32400. - * Or it can be a timezone object, - * see {Timezone argument}[#class-Time-label-Timezone+argument] for details. - * - * a = Time.new #=> 2007-11-19 07:50:02 -0600 - * b = Time.new #=> 2007-11-19 07:50:02 -0600 - * a == b #=> false - * "%.6f" % a.to_f #=> "1195480202.282373" - * "%.6f" % b.to_f #=> "1195480202.283415" - * - * Time.new(2008,6,21, 13,30,0, "+09:00") #=> 2008-06-21 13:30:00 +0900 - * - * # A trip for RubyConf 2007 - * t1 = Time.new(2007,11,1,15,25,0, "+09:00") # JST (Narita) - * t2 = Time.new(2007,11,1,12, 5,0, "-05:00") # CDT (Minneapolis) - * t3 = Time.new(2007,11,1,13,25,0, "-05:00") # CDT (Minneapolis) - * t4 = Time.new(2007,11,1,16,53,0, "-04:00") # EDT (Charlotte) - * t5 = Time.new(2007,11,5, 9,24,0, "-05:00") # EST (Charlotte) - * t6 = Time.new(2007,11,5,11,21,0, "-05:00") # EST (Detroit) - * t7 = Time.new(2007,11,5,13,45,0, "-05:00") # EST (Detroit) - * t8 = Time.new(2007,11,6,17,10,0, "+09:00") # JST (Narita) - * (t2-t1)/3600.0 #=> 10.666666666666666 - * (t4-t3)/3600.0 #=> 2.466666666666667 - * (t6-t5)/3600.0 #=> 1.95 - * (t8-t7)/3600.0 #=> 13.416666666666666 - * - */ - -static VALUE -time_init(int argc, VALUE *argv, VALUE time) -{ - if (argc == 0) - return time_init_0(time); - else - return time_init_1(argc, argv, time); -} - static void -time_overflow_p(time_t *secp, long *nsecp) +subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec) { time_t sec = *secp; - long nsec = *nsecp; + long subsec = *subsecp; long sec2; - if (nsec >= 1000000000) { /* nsec positive overflow */ - sec2 = nsec / 1000000000; + if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */ + sec2 = subsec / maxsubsec; if (TIMET_MAX - sec2 < sec) { rb_raise(rb_eRangeError, "out of Time range"); } - nsec -= sec2 * 1000000000; + subsec -= sec2 * maxsubsec; sec += sec2; } - else if (nsec < 0) { /* nsec negative overflow */ - sec2 = NDIV(nsec,1000000000); /* negative div */ + else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */ + sec2 = NDIV(subsec, maxsubsec); /* negative div */ if (sec < TIMET_MIN - sec2) { rb_raise(rb_eRangeError, "out of Time range"); } - nsec -= sec2 * 1000000000; + subsec -= sec2 * maxsubsec; sec += sec2; } #ifndef NEGATIVE_TIME_T @@ -2462,17 +2437,17 @@ time_overflow_p(time_t *secp, long *nsecp) rb_raise(rb_eArgError, "time must be positive"); #endif *secp = sec; - *nsecp = nsec; + *subsecp = subsec; } +#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000) +#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000) + static wideval_t nsec2timew(time_t sec, long nsec) { - struct timespec ts; - time_overflow_p(&sec, &nsec); - ts.tv_sec = sec; - ts.tv_nsec = nsec; - return timespec2timew(&ts); + time_nsec_normalize(&sec, &nsec); + return timenano2timew(sec, nsec); } static VALUE @@ -2491,27 +2466,8 @@ time_new_timew(VALUE klass, wideval_t timew) VALUE rb_time_new(time_t sec, long usec) { - wideval_t timew; - - if (usec >= 1000000) { - long sec2 = usec / 1000000; - if (sec > TIMET_MAX - sec2) { - rb_raise(rb_eRangeError, "out of Time range"); - } - usec -= sec2 * 1000000; - sec += sec2; - } - else if (usec < 0) { - long sec2 = NDIV(usec,1000000); /* negative div */ - if (sec < TIMET_MIN - sec2) { - rb_raise(rb_eRangeError, "out of Time range"); - } - usec -= sec2 * 1000000; - sec += sec2; - } - - timew = nsec2timew(sec, usec * 1000); - return time_new_timew(rb_cTime, timew); + time_usec_normalize(&sec, &usec); + return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000)); } /* returns localtime time object */ @@ -2521,11 +2477,6 @@ rb_time_nano_new(time_t sec, long nsec) return time_new_timew(rb_cTime, nsec2timew(sec, nsec)); } -/** - * Returns a time object with UTC/localtime/fixed offset - * - * offset is -86400 < fixoff < 86400 or INT_MAX (localtime) or INT_MAX-1 (utc) - */ VALUE rb_time_timespec_new(const struct timespec *ts, int offset) { @@ -2562,9 +2513,10 @@ rb_time_num_new(VALUE timev, VALUE off) if (zone_timelocal(zone, time)) return time; } if (NIL_P(off = utc_offset_arg(off))) { - if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); + off = zone; + if (NIL_P(zone = find_timezone(time, off))) invalid_utc_offset(off); time_gmtime(time); - if (!zone_timelocal(zone, time)) invalid_utc_offset(); + if (!zone_timelocal(zone, time)) invalid_utc_offset(off); return time; } else if (off == UTC_ZONE) { @@ -2627,7 +2579,7 @@ time_timespec(VALUE num, int interval) } } } - else if (RB_TYPE_P(num, T_BIGNUM)) { + else if (RB_BIGNUM_TYPE_P(num)) { t.tv_sec = NUM2TIMET(num); arg_range_check(t.tv_sec); t.tv_nsec = 0; @@ -2708,45 +2660,6 @@ rb_time_timespec_interval(VALUE num) return time_timespec(num, TRUE); } -enum { - TMOPT_IN, - TMOPT_MAX_ -}; - -static bool -get_tmopt(VALUE opts, VALUE vals[TMOPT_MAX_]) -{ - ID ids[TMOPT_MAX_]; - - if (NIL_P(opts)) return false; - CONST_ID(ids[TMOPT_IN], "in"); - rb_get_kwargs(opts, ids, 0, TMOPT_MAX_, vals); - return true; -} - -/* - * call-seq: - * Time.now -> time - * - * Creates a new Time object for the current time. - * This is same as Time.new without arguments. - * - * Time.now #=> 2009-06-24 12:39:54 +0900 - */ - -static VALUE -time_s_now(int argc, VALUE *argv, VALUE klass) -{ - VALUE vals[TMOPT_MAX_], opts, t, zone = Qundef; - rb_scan_args(argc, argv, ":", &opts); - if (get_tmopt(opts, vals)) zone = vals[TMOPT_IN]; - t = rb_class_new_instance(0, NULL, klass); - if (zone != Qundef) { - time_zonelocal(t, zone); - } - return t; -} - static int get_scale(VALUE unit) { @@ -2764,59 +2677,16 @@ get_scale(VALUE unit) } } -/* - * call-seq: - * Time.at(time) -> time - * Time.at(seconds_with_frac) -> time - * Time.at(seconds, microseconds_with_frac) -> time - * Time.at(seconds, milliseconds, :millisecond) -> time - * Time.at(seconds, microseconds, :usec) -> time - * Time.at(seconds, microseconds, :microsecond) -> time - * Time.at(seconds, nanoseconds, :nsec) -> time - * Time.at(seconds, nanoseconds, :nanosecond) -> time - * Time.at(time, in: tz) -> time - * Time.at(seconds_with_frac, in: tz) -> time - * Time.at(seconds, microseconds_with_frac, in: tz) -> time - * Time.at(seconds, milliseconds, :millisecond, in: tz) -> time - * Time.at(seconds, microseconds, :usec, in: tz) -> time - * Time.at(seconds, microseconds, :microsecond, in: tz) -> time - * Time.at(seconds, nanoseconds, :nsec, in: tz) -> time - * Time.at(seconds, nanoseconds, :nanosecond, in: tz) -> time - * - * Creates a new Time object with the value given by +time+, - * the given number of +seconds_with_frac+, or - * +seconds+ and +microseconds_with_frac+ since the Epoch. - * +seconds_with_frac+ and +microseconds_with_frac+ - * can be an Integer, Float, Rational, or other Numeric. - * non-portable feature allows the offset to be negative on some systems. - * - * If +in+ argument is given, the result is in that timezone or UTC offset, or - * if a numeric argument is given, the result is in local time. - * - * Time.at(0) #=> 1969-12-31 18:00:00 -0600 - * Time.at(Time.at(0)) #=> 1969-12-31 18:00:00 -0600 - * Time.at(946702800) #=> 1999-12-31 23:00:00 -0600 - * Time.at(-284061600) #=> 1960-12-31 00:00:00 -0600 - * Time.at(946684800.2).usec #=> 200000 - * Time.at(946684800, 123456.789).nsec #=> 123456789 - * Time.at(946684800, 123456789, :nsec).nsec #=> 123456789 - */ - static VALUE -time_s_at(int argc, VALUE *argv, VALUE klass) +time_s_at(rb_execution_context_t *ec, VALUE klass, VALUE time, VALUE subsec, VALUE unit, VALUE zone) { - VALUE time, t, unit = Qundef, zone = Qundef, opts; - VALUE vals[TMOPT_MAX_]; + VALUE t; wideval_t timew; - argc = rb_scan_args(argc, argv, "12:", &time, &t, &unit, &opts); - if (get_tmopt(opts, vals)) { - zone = vals[0]; - } - if (argc >= 2) { - int scale = argc == 3 ? get_scale(unit) : 1000000; + if (subsec) { + int scale = get_scale(unit); time = num_exact(time); - t = num_exact(t); + t = num_exact(subsec); timew = wadd(rb_time_magnify(v2w(time)), wmulquoll(v2w(t), TIME_SCALE, scale)); t = time_new_timew(klass, timew); } @@ -2831,13 +2701,19 @@ time_s_at(int argc, VALUE *argv, VALUE klass) timew = rb_time_magnify(v2w(num_exact(time))); t = time_new_timew(klass, timew); } - if (zone != Qundef) { + if (!NIL_P(zone)) { time_zonelocal(t, zone); } return t; } +static VALUE +time_s_at1(rb_execution_context_t *ec, VALUE klass, VALUE time) +{ + return time_s_at(ec, klass, time, Qfalse, ID2SYM(id_microsecond), Qnil); +} + static const char months[][4] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", @@ -2847,33 +2723,29 @@ static int obj2int(VALUE obj) { if (RB_TYPE_P(obj, T_STRING)) { - obj = rb_str_to_inum(obj, 10, FALSE); + obj = rb_str_to_inum(obj, 10, TRUE); } return NUM2INT(obj); } +/* bits should be 0 <= x <= 31 */ static uint32_t -obj2ubits(VALUE obj, size_t bits) +obj2ubits(VALUE obj, unsigned int bits) { - static const uint32_t u32max = (uint32_t)-1; - const uint32_t usable_mask = ~(u32max << bits); - uint32_t rv; - int tmp = obj2int(obj); + const unsigned int usable_mask = (1U << bits) - 1; + unsigned int rv = (unsigned int)obj2int(obj); - if (tmp < 0) - rb_raise(rb_eArgError, "argument out of range"); - rv = tmp; if ((rv & usable_mask) != rv) rb_raise(rb_eArgError, "argument out of range"); - return rv; + return (uint32_t)rv; } static VALUE obj2vint(VALUE obj) { if (RB_TYPE_P(obj, T_STRING)) { - obj = rb_str_to_inum(obj, 10, FALSE); + obj = rb_str_to_inum(obj, 10, TRUE); } else { obj = rb_to_int(obj); @@ -2888,7 +2760,7 @@ obj2subsecx(VALUE obj, VALUE *subsecx) VALUE subsec; if (RB_TYPE_P(obj, T_STRING)) { - obj = rb_str_to_inum(obj, 10, FALSE); + obj = rb_str_to_inum(obj, 10, TRUE); *subsecx = INT2FIX(0); } else { @@ -2902,7 +2774,7 @@ static VALUE usec2subsecx(VALUE obj) { if (RB_TYPE_P(obj, T_STRING)) { - obj = rb_str_to_inum(obj, 10, FALSE); + obj = rb_str_to_inum(obj, 10, TRUE); } return mulquov(num_exact(obj), INT2FIX(TIME_SCALE), INT2FIX(1000000)); @@ -2913,9 +2785,14 @@ month_arg(VALUE arg) { int i, mon; + if (FIXNUM_P(arg)) { + return obj2ubits(arg, 4); + } + + mon = 0; VALUE s = rb_check_string_type(arg); if (!NIL_P(s) && RSTRING_LEN(s) > 0) { - mon = 0; + arg = s; for (i=0; i<12; i++) { if (RSTRING_LEN(s) == 3 && STRNCASECMP(months[i], RSTRING_PTR(s), 3) == 0) { @@ -2923,15 +2800,8 @@ month_arg(VALUE arg) break; } } - if (mon == 0) { - char c = RSTRING_PTR(s)[0]; - - if ('0' <= c && c <= '9') { - mon = obj2ubits(s, 4); - } - } } - else { + if (mon == 0) { mon = obj2ubits(arg, 4); } return mon; @@ -2986,7 +2856,7 @@ time_arg(int argc, const VALUE *argv, struct vtm *vtm) vtm->wday = 0; vtm->yday = 0; vtm->isdst = 0; - vtm->zone = rb_fstring_lit(""); + vtm->zone = str_empty; if (argc == 10) { v[0] = argv[5]; @@ -3108,24 +2978,43 @@ timegm_noleapsecond(struct tm *tm) #define DEBUG_GUESSRANGE #endif +static const bool debug_guessrange = #ifdef DEBUG_GUESSRANGE -#define DEBUG_REPORT_GUESSRANGE fprintf(stderr, "find time guess range: %ld - %ld : %"PRI_TIMET_PREFIX"u\n", guess_lo, guess_hi, (unsigned_time_t)(guess_hi-guess_lo)) + true; #else -#define DEBUG_REPORT_GUESSRANGE + false; #endif -#ifdef DEBUG_FIND_TIME_NUMGUESS -#define DEBUG_FIND_TIME_NUMGUESS_INC find_time_numguess++, -static unsigned long long find_time_numguess; +#define DEBUG_REPORT_GUESSRANGE \ + (debug_guessrange ? debug_report_guessrange(guess_lo, guess_hi) : (void)0) -static VALUE find_time_numguess_getter(void) +static inline void +debug_report_guessrange(time_t guess_lo, time_t guess_hi) { - return ULL2NUM(find_time_numguess); + unsigned_time_t guess_diff = (unsigned_time_t)(guess_hi-guess_lo); + fprintf(stderr, "find time guess range: %"PRI_TIMET_PREFIX"d - " + "%"PRI_TIMET_PREFIX"d : %"PRI_TIMET_PREFIX"u\n", + guess_lo, guess_hi, guess_diff); } + +static const bool debug_find_time_numguess = +#ifdef DEBUG_FIND_TIME_NUMGUESS + true; #else -#define DEBUG_FIND_TIME_NUMGUESS_INC + false; #endif +#define DEBUG_FIND_TIME_NUMGUESS_INC \ + (void)(debug_find_time_numguess && find_time_numguess++), +static unsigned long long find_time_numguess; + +static VALUE +find_time_numguess_getter(ID name, VALUE *data) +{ + unsigned long long *numguess = (void *)data; + return ULL2NUM(*numguess); +} + static const char * find_time_t(struct tm *tptr, int utc_p, time_t *tp) { @@ -3168,9 +3057,7 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) tm0.tm_min = 0; tm0.tm_sec = 0; } - else if ((d = (leap_year_p(1900 + tm0.tm_year) ? - leap_year_days_in_month : - common_year_days_in_month)[tm0.tm_mon]) < tm0.tm_mday) { + else if ((d = days_in_month_in(1900 + tm0.tm_year)[tm0.tm_mon]) < tm0.tm_mday) { tm0.tm_mday = d; tm0.tm_hour = 23; tm0.tm_min = 59; @@ -3246,8 +3133,8 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) status = 1; while (guess_lo + 1 < guess_hi) { + binsearch: if (status == 0) { - binsearch: guess = guess_lo / 2 + guess_hi / 2; if (guess <= guess_lo) guess = guess_lo + 1; @@ -3272,10 +3159,17 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) } if (guess <= guess_lo || guess_hi <= guess) { /* Previous guess is invalid. try binary search. */ -#ifdef DEBUG_GUESSRANGE - if (guess <= guess_lo) fprintf(stderr, "too small guess: %ld <= %ld\n", guess, guess_lo); - if (guess_hi <= guess) fprintf(stderr, "too big guess: %ld <= %ld\n", guess_hi, guess); -#endif + if (debug_guessrange) { + if (guess <= guess_lo) { + fprintf(stderr, "too small guess: %"PRI_TIMET_PREFIX"d"\ + " <= %"PRI_TIMET_PREFIX"d\n", guess, guess_lo); + } + if (guess_hi <= guess) { + fprintf(stderr, "too big guess: %"PRI_TIMET_PREFIX"d"\ + " <= %"PRI_TIMET_PREFIX"d\n", guess_hi, guess); + } + } + status = 0; goto binsearch; } } @@ -3296,64 +3190,8 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) DEBUG_REPORT_GUESSRANGE; } else { - found: - if (!utc_p) { - /* If localtime is nonmonotonic, another result may exist. */ - time_t guess2; - if (find_dst) { - guess2 = guess - 2 * 60 * 60; - tm = LOCALTIME(&guess2, result); - if (tm) { - if (tptr->tm_hour != (tm->tm_hour + 2) % 24 || - tptr->tm_min != tm->tm_min || - tptr->tm_sec != tm->tm_sec) { - guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 + - (tm->tm_min - tptr->tm_min) * 60 + - (tm->tm_sec - tptr->tm_sec); - if (tptr->tm_mday != tm->tm_mday) - guess2 += 24 * 60 * 60; - if (guess != guess2) { - tm = LOCALTIME(&guess2, result); - if (tm && tmcmp(tptr, tm) == 0) { - if (guess < guess2) - *tp = guess; - else - *tp = guess2; - return NULL; - } - } - } - } - } - else { - guess2 = guess + 2 * 60 * 60; - tm = LOCALTIME(&guess2, result); - if (tm) { - if ((tptr->tm_hour + 2) % 24 != tm->tm_hour || - tptr->tm_min != tm->tm_min || - tptr->tm_sec != tm->tm_sec) { - guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 + - (tm->tm_min - tptr->tm_min) * 60 + - (tm->tm_sec - tptr->tm_sec); - if (tptr->tm_mday != tm->tm_mday) - guess2 -= 24 * 60 * 60; - if (guess != guess2) { - tm = LOCALTIME(&guess2, result); - if (tm && tmcmp(tptr, tm) == 0) { - if (guess < guess2) - *tp = guess2; - else - *tp = guess; - return NULL; - } - } - } - } - } - } - *tp = guess; - return NULL; - } + goto found; + } } /* Given argument has no corresponding time_t. Let's extrapolate. */ @@ -3382,6 +3220,64 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) return NULL; + found: + if (!utc_p) { + /* If localtime is nonmonotonic, another result may exist. */ + time_t guess2; + if (find_dst) { + guess2 = guess - 2 * 60 * 60; + tm = LOCALTIME(&guess2, result); + if (tm) { + if (tptr->tm_hour != (tm->tm_hour + 2) % 24 || + tptr->tm_min != tm->tm_min || + tptr->tm_sec != tm->tm_sec) { + guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 + + (tm->tm_min - tptr->tm_min) * 60 + + (tm->tm_sec - tptr->tm_sec); + if (tptr->tm_mday != tm->tm_mday) + guess2 += 24 * 60 * 60; + if (guess != guess2) { + tm = LOCALTIME(&guess2, result); + if (tm && tmcmp(tptr, tm) == 0) { + if (guess < guess2) + *tp = guess; + else + *tp = guess2; + return NULL; + } + } + } + } + } + else { + guess2 = guess + 2 * 60 * 60; + tm = LOCALTIME(&guess2, result); + if (tm) { + if ((tptr->tm_hour + 2) % 24 != tm->tm_hour || + tptr->tm_min != tm->tm_min || + tptr->tm_sec != tm->tm_sec) { + guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 + + (tm->tm_min - tptr->tm_min) * 60 + + (tm->tm_sec - tptr->tm_sec); + if (tptr->tm_mday != tm->tm_mday) + guess2 -= 24 * 60 * 60; + if (guess != guess2) { + tm = LOCALTIME(&guess2, result); + if (tm && tmcmp(tptr, tm) == 0) { + if (guess < guess2) + *tp = guess2; + else + *tp = guess; + return NULL; + } + } + } + } + } + } + *tp = guess; + return NULL; + out_of_range: return "time out of range"; @@ -3430,36 +3326,38 @@ tmcmp(struct tm *a, struct tm *b) } /* - * call-seq: - * Time.utc(year) -> time - * Time.utc(year, month) -> time - * Time.utc(year, month, day) -> time - * Time.utc(year, month, day, hour) -> time - * Time.utc(year, month, day, hour, min) -> time - * Time.utc(year, month, day, hour, min, sec_with_frac) -> time - * Time.utc(year, month, day, hour, min, sec, usec_with_frac) -> time - * Time.utc(sec, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> time - * Time.gm(year) -> time - * Time.gm(year, month) -> time - * Time.gm(year, month, day) -> time - * Time.gm(year, month, day, hour) -> time - * Time.gm(year, month, day, hour, min) -> time - * Time.gm(year, month, day, hour, min, sec_with_frac) -> time - * Time.gm(year, month, day, hour, min, sec, usec_with_frac) -> time - * Time.gm(sec, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> time - * - * Creates a Time object based on given values, interpreted as UTC (GMT). The - * year must be specified. Other values default to the minimum value - * for that field (and may be +nil+ or omitted). Months may - * be specified by numbers from 1 to 12, or by the three-letter English - * month names. Hours are specified on a 24-hour clock (0..23). Raises - * an ArgumentError if any values are out of range. Will - * also accept ten arguments in the order output by Time#to_a. - * - * +sec_with_frac+ and +usec_with_frac+ can have a fractional part. - * - * Time.utc(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 UTC - * Time.gm(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 UTC + * call-seq: + * Time.utc(year, month=1, day=1, hour=0, min=0, sec_i=0, usec=0) -> new_time + * Time.utc(sec_i, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> new_time + * + * Returns a new \Time object based the on given arguments; + * its timezone is UTC. + * + * In the first form (up to seven arguments), argument +year+ is required. + * + * Time.utc(2000) # => 2000-01-01 00:00:00 UTC + * Time.utc(0, 1, 2, 3, 4, 5, 6.5) # => 0000-01-02 03:04:05.0000065 UTC + * + * In the second form, all ten arguments are required, + * though the last four are ignored. + * This form is useful for creating a time from a 10-element array + * such as is returned by #to_a. + * + * array = Time.now.to_a + * p array # => [57, 26, 13, 24, 4, 2021, 6, 114, true, "Central Daylight Time"] + * array[5] = 2000 + * Time.utc(*array) # => 2000-04-24 13:26:57 UTC + * + * Parameters: + * :include: doc/time/year.rdoc + * :include: doc/time/mon-min.rdoc + * :include: doc/time/sec_i.rdoc + * :include: doc/time/usec.rdoc + * + * Alias: Time.gm. + + * Related: Time.local. + * */ static VALUE time_s_mkutc(int argc, VALUE *argv, VALUE klass) @@ -3471,28 +3369,37 @@ time_s_mkutc(int argc, VALUE *argv, VALUE klass) } /* - * call-seq: - * Time.local(year) -> time - * Time.local(year, month) -> time - * Time.local(year, month, day) -> time - * Time.local(year, month, day, hour) -> time - * Time.local(year, month, day, hour, min) -> time - * Time.local(year, month, day, hour, min, sec_with_frac) -> time - * Time.local(year, month, day, hour, min, sec, usec_with_frac) -> time - * Time.local(sec, min, hour, day, month, year, dummy, dummy, isdst, dummy) -> time - * Time.mktime(year) -> time - * Time.mktime(year, month) -> time - * Time.mktime(year, month, day) -> time - * Time.mktime(year, month, day, hour) -> time - * Time.mktime(year, month, day, hour, min) -> time - * Time.mktime(year, month, day, hour, min, sec_with_frac) -> time - * Time.mktime(year, month, day, hour, min, sec, usec_with_frac) -> time - * Time.mktime(sec, min, hour, day, month, year, dummy, dummy, isdst, dummy) -> time - * - * Same as Time::gm, but interprets the values in the - * local time zone. - * - * Time.local(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 -0600 + * call-seq: + * Time.local(year, month=1, day=1, hour=0, min=0, sec_i=0, usec=0) -> new_time + * Time.local(sec, min, hour, day, month, year, dummy, dummy, dummy, dummy) -> new_time + * + * Returns a new \Time object based the on given arguments; + * its timezone is the local timezone. + * + * In the first form (up to seven arguments), argument +year+ is required. + * + * Time.local(2000) # => 2000-01-01 00:00:00 -0600 + * Time.local(0, 1, 2, 3, 4, 5, 6.5) # => 0000-01-02 03:04:05.0000065 -0600 + * + * In the second form, all ten arguments are required, + * though the last four are ignored. + * This form is useful for creating a time from a 10-element array + * such as those returned by #to_a. + * + * array = Time.now.to_a + * p array # => [57, 26, 13, 24, 4, 2021, 6, 114, true, "Central Daylight Time"] + * array[5] = 2000 + * Time.local(*array) # => 2000-04-24 13:26:57 -0500 + * + * Parameters: + * :include: doc/time/year.rdoc + * :include: doc/time/mon-min.rdoc + * :include: doc/time/sec_i.rdoc + * :include: doc/time/usec.rdoc + * + * Alias: Time.mktime. + * + * Related: Time.utc. */ static VALUE @@ -3512,9 +3419,10 @@ time_s_mktime(int argc, VALUE *argv, VALUE klass) * Returns the value of _time_ as an integer number of seconds * since the Epoch. * - * t = Time.now - * "%10.5f" % t.to_f #=> "1270968656.89607" - * t.to_i #=> 1270968656 + * If _time_ contains subsecond, they are truncated. + * + * t = Time.now #=> 2020-07-21 01:41:29.746012609 +0900 + * t.to_i #=> 1595263289 */ static VALUE @@ -3532,13 +3440,22 @@ time_to_i(VALUE time) * * Returns the value of _time_ as a floating point number of * seconds since the Epoch. + * The return value approximate the exact value in the Time object + * because floating point numbers cannot represent all rational numbers + * exactly. * - * t = Time.now - * "%10.5f" % t.to_f #=> "1270968744.77658" - * t.to_i #=> 1270968744 + * t = Time.now #=> 2020-07-20 22:00:29.38740268 +0900 + * t.to_f #=> 1595250029.3874028 + * t.to_i #=> 1595250029 * * Note that IEEE 754 double is not accurate enough to represent * the exact number of nanoseconds since the Epoch. + * (IEEE 754 double has 53bit mantissa. + * So it can represent exact number of nanoseconds only in + * 2 ** 53 / 1_000_000_000 / 60 / 60 / 24 = 104.2 days.) + * When Ruby uses a nanosecond-resolution clock function, + * such as +clock_gettime+ of POSIX, to obtain the current time, + * Time#to_f can lose information of a Time object created with +Time.now+. */ static VALUE @@ -3557,12 +3474,11 @@ time_to_f(VALUE time) * Returns the value of _time_ as a rational number of seconds * since the Epoch. * - * t = Time.now - * t.to_r #=> (1270968792716287611/1000000000) + * t = Time.now #=> 2020-07-20 22:03:45.212167333 +0900 + * t.to_r #=> (1595250225212167333/1000000000) * - * This methods is intended to be used to get an accurate value - * representing the nanoseconds since the Epoch. You can use this method - * to convert _time_ to another Epoch. + * This method is intended to be used to get an accurate value + * representing the seconds (including subsecond) since the Epoch. */ static VALUE @@ -3584,11 +3500,19 @@ time_to_r(VALUE time) * time.usec -> int * time.tv_usec -> int * - * Returns the number of microseconds for _time_. + * Returns the number of microseconds for the subsecond part of _time_. + * The result is a non-negative integer less than 10**6. + * + * t = Time.now #=> 2020-07-20 22:05:58.459785953 +0900 + * t.usec #=> 459785 + * + * If _time_ has fraction of microsecond (such as nanoseconds), + * it is truncated. + * + * t = Time.new(2000,1,1,0,0,0.666_777_888_999r) + * t.usec #=> 666777 * - * t = Time.now #=> 2007-11-19 08:03:26 -0600 - * "%10.6f" % t.to_f #=> "1195481006.775195" - * t.usec #=> 775195 + * Time#subsec can be used to obtain the subsecond part exactly. */ static VALUE @@ -3609,17 +3533,19 @@ time_usec(VALUE time) * time.nsec -> int * time.tv_nsec -> int * - * Returns the number of nanoseconds for _time_. + * Returns the number of nanoseconds for the subsecond part of _time_. + * The result is a non-negative integer less than 10**9. * - * t = Time.now #=> 2007-11-17 15:18:03 +0900 - * "%10.9f" % t.to_f #=> "1195280283.536151409" - * t.nsec #=> 536151406 + * t = Time.now #=> 2020-07-20 22:07:10.963933942 +0900 + * t.nsec #=> 963933942 * - * The lowest digits of #to_f and #nsec are different because - * IEEE 754 double is not accurate enough to represent - * the exact number of nanoseconds since the Epoch. + * If _time_ has fraction of nanosecond (such as picoseconds), + * it is truncated. + * + * t = Time.new(2000,1,1,0,0,0.666_777_888_999r) + * t.nsec #=> 666777888 * - * The more accurate value is returned by #nsec. + * Time#subsec can be used to obtain the subsecond part exactly. */ static VALUE @@ -3635,19 +3561,21 @@ time_nsec(VALUE time) * call-seq: * time.subsec -> number * - * Returns the fraction for _time_. + * Returns the subsecond for _time_. * * The return value can be a rational number. * - * t = Time.now #=> 2009-03-26 22:33:12 +0900 - * "%10.9f" % t.to_f #=> "1238074392.940563917" - * t.subsec #=> (94056401/100000000) + * t = Time.now #=> 2020-07-20 15:40:26.867462289 +0900 + * t.subsec #=> (867462289/1000000000) + * + * t = Time.now #=> 2020-07-20 15:40:50.313828595 +0900 + * t.subsec #=> (62765719/200000000) + * + * t = Time.new(2000,1,1,2,3,4) #=> 2000-01-01 02:03:04 +0900 + * t.subsec #=> 0 * - * The lowest digits of #to_f and #subsec are different because - * IEEE 754 double is not accurate enough to represent - * the rational number. + * Time.new(2000,1,1,0,0,1/3r,"UTC").subsec #=> (1/3) * - * The more accurate value is returned by #subsec. */ static VALUE @@ -3663,9 +3591,9 @@ time_subsec(VALUE time) * call-seq: * time <=> other_time -> -1, 0, +1, or nil * - * Comparison---Compares +time+ with +other_time+. + * Compares +time+ with +other_time+. * - * -1, 0, +1 or nil depending on whether +time+ is less than, equal to, or + * -1, 0, +1 or nil depending on whether +time+ is less than, equal to, or * greater than +other_time+. * * +nil+ is returned if the two values are incomparable. @@ -3708,7 +3636,7 @@ time_cmp(VALUE time1, VALUE time2) * time.eql?(other_time) * * Returns +true+ if _time_ and +other_time+ are - * both Time objects with the same seconds and fractional seconds. + * both Time objects with the same seconds (including subsecond) from the Epoch. */ static VALUE @@ -3748,8 +3676,7 @@ time_utc_p(VALUE time) struct time_object *tobj; GetTimeval(time, tobj); - if (TZMODE_UTC_P(tobj)) return Qtrue; - return Qfalse; + return RBOOL(TZMODE_UTC_P(tobj)); } /* @@ -3829,8 +3756,9 @@ time_zonelocal(VALUE time, VALUE off) if (zone_localtime(zone, time)) return time; if (NIL_P(off = utc_offset_arg(off))) { - if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); - if (!zone_localtime(zone, time)) invalid_utc_offset(); + off = zone; + if (NIL_P(zone = find_timezone(time, off))) invalid_utc_offset(off); + if (!zone_localtime(zone, time)) invalid_utc_offset(off); return time; } else if (off == UTC_ZONE) { @@ -3910,7 +3838,7 @@ time_gmtime(VALUE time) time_modify(time); } - vtm.zone = rb_fstring_lit("UTC"); + vtm.zone = str_utc; GMTIMEW(tobj->timew, &vtm); tobj->vtm = vtm; @@ -3994,9 +3922,10 @@ time_getlocaltime(int argc, VALUE *argv, VALUE time) } if (NIL_P(off = utc_offset_arg(off))) { - if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); + off = zone; + if (NIL_P(zone = find_timezone(time, off))) invalid_utc_offset(off); time = time_dup(time); - if (!zone_localtime(zone, time)) invalid_utc_offset(); + if (!zone_localtime(zone, time)) invalid_utc_offset(off); return time; } else if (off == UTC_ZONE) { @@ -4092,7 +4021,7 @@ time_to_s(VALUE time) * time.inspect -> string * * Returns a detailed string representing _time_. Unlike to_s, - * preserves nanoseconds in the representation for easier debugging. + * preserves subsecond in the representation for easier debugging. * * t = Time.now * t.inspect #=> "2012-11-10 18:16:12.261257655 +0100" @@ -4115,7 +4044,7 @@ time_inspect(VALUE time) } else if (FIXNUM_P(subsec) && FIX2LONG(subsec) < TIME_SCALE) { long len; - str = rb_enc_sprintf(rb_usascii_encoding(), "%"PRIsVALUE".%09ld", str, FIX2LONG(subsec)); + rb_str_catf(str, ".%09ld", FIX2LONG(subsec)); for (len=RSTRING_LEN(str); RSTRING_PTR(str)[len-1] == '0' && len > 0; len--) ; rb_str_resize(str, len); @@ -4129,7 +4058,14 @@ time_inspect(VALUE time) rb_str_cat_cstr(str, " UTC"); } else { - rb_str_concat(str, strftimev(" %z", time, rb_usascii_encoding())); + /* ?TODO: subsecond offset */ + long off = NUM2LONG(rb_funcall(tobj->vtm.utc_offset, rb_intern("round"), 0)); + char sign = (off < 0) ? (off = -off, '-') : '+'; + int sec = off % 60; + int min = (off /= 60) % 60; + off /= 60; + rb_str_catf(str, " %c%.2d%.2d", sign, (int)off, min); + if (sec) rb_str_catf(str, "%.2d", sec); } return str; } @@ -4161,11 +4097,11 @@ time_add(const struct time_object *tobj, VALUE torig, VALUE offset, int sign) * call-seq: * time + numeric -> time * - * Addition --- Adds some number of seconds (possibly fractional) to + * Adds some number of seconds (possibly including subsecond) to * _time_ and returns that value as a new Time object. * - * t = Time.now #=> 2007-11-19 08:22:21 -0600 - * t + (60 * 60 * 24) #=> 2007-11-20 08:22:21 -0600 + * t = Time.now #=> 2020-07-20 22:14:43.170490982 +0900 + * t + (60 * 60 * 24) #=> 2020-07-21 22:14:43.170490982 +0900 */ static VALUE @@ -4185,14 +4121,14 @@ time_plus(VALUE time1, VALUE time2) * time - other_time -> float * time - numeric -> time * - * Difference --- Returns a difference in seconds as a Float + * Returns a difference in seconds as a Float * between _time_ and +other_time+, or subtracts the given number * of seconds in +numeric+ from _time_. * - * t = Time.now #=> 2007-11-19 08:23:10 -0600 - * t2 = t + 2592000 #=> 2007-12-19 08:23:10 -0600 + * t = Time.now #=> 2020-07-20 22:15:49.302766336 +0900 + * t2 = t + 2592000 #=> 2020-08-19 22:15:49.302766336 +0900 * t2 - t #=> 2592000.0 - * t2 - 2592000 #=> 2007-11-19 08:23:10 -0600 + * t2 - 2592000 #=> 2020-07-20 22:15:49.302766336 +0900 */ static VALUE @@ -4210,40 +4146,6 @@ time_minus(VALUE time1, VALUE time2) return time_add(tobj, time1, time2, -1); } -/* - * call-seq: - * time.succ -> new_time - * - * Returns a new Time object, one second later than _time_. - * Time#succ is obsolete since 1.9.2 for time is not a discrete value. - * - * t = Time.now #=> 2007-11-19 08:23:57 -0600 - * t.succ #=> 2007-11-19 08:23:58 -0600 - * - * Use instead time + 1 - * - * t + 1 #=> 2007-11-19 08:23:58 -0600 - */ - -VALUE -rb_time_succ(VALUE time) -{ - struct time_object *tobj; - struct time_object *tobj2; - - rb_warn("Time#succ is obsolete; use time + 1"); - GetTimeval(time, tobj); - time = time_new_timew(rb_cTime, wadd(tobj->timew, WINT2FIXWV(TIME_SCALE))); - GetTimeval(time, tobj2); - TZMODE_COPY(tobj2, tobj); - if (TZMODE_LOCALTIME_P(tobj2) && maybe_tzobj_p(tobj2->vtm.zone)) { - zone_localtime(tobj2->vtm.zone, time); - } - return time; -} - -#define time_succ rb_time_succ - static VALUE ndigits_denominator(VALUE ndigits) { @@ -4263,31 +4165,29 @@ ndigits_denominator(VALUE ndigits) * call-seq: * time.round([ndigits]) -> new_time * - * Rounds sub seconds to a given precision in decimal digits (0 digits by default). + * Rounds subsecond to a given precision in decimal digits (0 digits by default). * It returns a new Time object. * +ndigits+ should be zero or a positive integer. * - * require 'time' - * * t = Time.utc(2010,3,30, 5,43,25.123456789r) - * t.iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z" - * t.round.iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z" - * t.round(0).iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z" - * t.round(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z" - * t.round(2).iso8601(10) #=> "2010-03-30T05:43:25.1200000000Z" - * t.round(3).iso8601(10) #=> "2010-03-30T05:43:25.1230000000Z" - * t.round(4).iso8601(10) #=> "2010-03-30T05:43:25.1235000000Z" + * t #=> 2010-03-30 05:43:25.123456789 UTC + * t.round #=> 2010-03-30 05:43:25 UTC + * t.round(0) #=> 2010-03-30 05:43:25 UTC + * t.round(1) #=> 2010-03-30 05:43:25.1 UTC + * t.round(2) #=> 2010-03-30 05:43:25.12 UTC + * t.round(3) #=> 2010-03-30 05:43:25.123 UTC + * t.round(4) #=> 2010-03-30 05:43:25.1235 UTC * * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.4).round.iso8601(3) #=> "1999-12-31T23:59:59.000Z" - * (t + 0.49).round.iso8601(3) #=> "1999-12-31T23:59:59.000Z" - * (t + 0.5).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 1.4).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 1.49).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 1.5).round.iso8601(3) #=> "2000-01-01T00:00:01.000Z" - * - * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.123456789).round(4).iso8601(6) #=> "1999-12-31T23:59:59.123500Z" + * (t + 0.4).round #=> 1999-12-31 23:59:59 UTC + * (t + 0.49).round #=> 1999-12-31 23:59:59 UTC + * (t + 0.5).round #=> 2000-01-01 00:00:00 UTC + * (t + 1.4).round #=> 2000-01-01 00:00:00 UTC + * (t + 1.49).round #=> 2000-01-01 00:00:00 UTC + * (t + 1.5).round #=> 2000-01-01 00:00:01 UTC + * + * t = Time.utc(1999,12,31, 23,59,59) #=> 1999-12-31 23:59:59 UTC + * (t + 0.123456789).round(4).iso8601(6) #=> 1999-12-31 23:59:59.1235 UTC */ static VALUE @@ -4315,29 +4215,27 @@ time_round(int argc, VALUE *argv, VALUE time) * call-seq: * time.floor([ndigits]) -> new_time * - * Floors sub seconds to a given precision in decimal digits (0 digits by default). + * Floors subsecond to a given precision in decimal digits (0 digits by default). * It returns a new Time object. * +ndigits+ should be zero or a positive integer. * - * require 'time' - * * t = Time.utc(2010,3,30, 5,43,25.123456789r) - * t.iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z" - * t.floor.iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z" - * t.floor(0).iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z" - * t.floor(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z" - * t.floor(2).iso8601(10) #=> "2010-03-30T05:43:25.1200000000Z" - * t.floor(3).iso8601(10) #=> "2010-03-30T05:43:25.1230000000Z" - * t.floor(4).iso8601(10) #=> "2010-03-30T05:43:25.1234000000Z" + * t #=> 2010-03-30 05:43:25.123456789 UTC + * t.floor #=> 2010-03-30 05:43:25 UTC + * t.floor(0) #=> 2010-03-30 05:43:25 UTC + * t.floor(1) #=> 2010-03-30 05:43:25.1 UTC + * t.floor(2) #=> 2010-03-30 05:43:25.12 UTC + * t.floor(3) #=> 2010-03-30 05:43:25.123 UTC + * t.floor(4) #=> 2010-03-30 05:43:25.1234 UTC * * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.4).floor.iso8601(3) #=> "1999-12-31T23:59:59.000Z" - * (t + 0.9).floor.iso8601(3) #=> "1999-12-31T23:59:59.000Z" - * (t + 1.4).floor.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 1.9).floor.iso8601(3) #=> "2000-01-01T00:00:00.000Z" + * (t + 0.4).floor #=> 1999-12-31 23:59:59 UTC + * (t + 0.9).floor #=> 1999-12-31 23:59:59 UTC + * (t + 1.4).floor #=> 2000-01-01 00:00:00 UTC + * (t + 1.9).floor #=> 2000-01-01 00:00:00 UTC * * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.123456789).floor(4).iso8601(6) #=> "1999-12-31T23:59:59.123400Z" + * (t + 0.123456789).floor(4) #=> 1999-12-31 23:59:59.1234 UTC */ static VALUE @@ -4362,29 +4260,27 @@ time_floor(int argc, VALUE *argv, VALUE time) * call-seq: * time.ceil([ndigits]) -> new_time * - * Ceils sub seconds to a given precision in decimal digits (0 digits by default). + * Ceils subsecond to a given precision in decimal digits (0 digits by default). * It returns a new Time object. * +ndigits+ should be zero or a positive integer. * - * require 'time' - * * t = Time.utc(2010,3,30, 5,43,25.0123456789r) - * t.iso8601(10) #=> "2010-03-30T05:43:25.0123456789Z" - * t.ceil.iso8601(10) #=> "2010-03-30T05:43:26.0000000000Z" - * t.ceil(0).iso8601(10) #=> "2010-03-30T05:43:26.0000000000Z" - * t.ceil(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z" - * t.ceil(2).iso8601(10) #=> "2010-03-30T05:43:25.0200000000Z" - * t.ceil(3).iso8601(10) #=> "2010-03-30T05:43:25.0130000000Z" - * t.ceil(4).iso8601(10) #=> "2010-03-30T05:43:25.0124000000Z" + * t #=> 2010-03-30 05:43:25 123456789/10000000000 UTC + * t.ceil #=> 2010-03-30 05:43:26 UTC + * t.ceil(0) #=> 2010-03-30 05:43:26 UTC + * t.ceil(1) #=> 2010-03-30 05:43:25.1 UTC + * t.ceil(2) #=> 2010-03-30 05:43:25.02 UTC + * t.ceil(3) #=> 2010-03-30 05:43:25.013 UTC + * t.ceil(4) #=> 2010-03-30 05:43:25.0124 UTC * * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.4).ceil.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 0.9).ceil.iso8601(3) #=> "2000-01-01T00:00:00.000Z" - * (t + 1.4).ceil.iso8601(3) #=> "2000-01-01T00:00:01.000Z" - * (t + 1.9).ceil.iso8601(3) #=> "2000-01-01T00:00:01.000Z" + * (t + 0.4).ceil #=> 2000-01-01 00:00:00 UTC + * (t + 0.9).ceil #=> 2000-01-01 00:00:00 UTC + * (t + 1.4).ceil #=> 2000-01-01 00:00:01 UTC + * (t + 1.9).ceil #=> 2000-01-01 00:00:01 UTC * * t = Time.utc(1999,12,31, 23,59,59) - * (t + 0.123456789).ceil(4).iso8601(6) #=> "1999-12-31T23:59:59.123500Z" + * (t + 0.123456789).ceil(4) #=> 1999-12-31 23:59:59.1235 UTC */ static VALUE @@ -4402,7 +4298,10 @@ time_ceil(int argc, VALUE *argv, VALUE time) v = w2v(rb_time_unmagnify(tobj->timew)); v = modv(v, den); - return time_add(tobj, time, subv(den, v), 1); + if (!rb_equal(v, INT2FIX(0))) { + v = subv(den, v); + } + return time_add(tobj, time, v, 1); } /* @@ -4412,7 +4311,7 @@ time_ceil(int argc, VALUE *argv, VALUE time) * Returns the second of the minute (0..60) for _time_. * * *Note:* Seconds range from zero to 60 to allow the system to inject - * leap seconds. See http://en.wikipedia.org/wiki/Leap_second for further + * leap seconds. See https://en.wikipedia.org/wiki/Leap_second for further * details. * * t = Time.now #=> 2007-11-19 08:25:02 -0600 @@ -4474,7 +4373,7 @@ time_hour(VALUE time) * time.day -> integer * time.mday -> integer * - * Returns the day of the month (1..n) for _time_. + * Returns the day of the month (1..31) for _time_. * * t = Time.now #=> 2007-11-19 08:27:03 -0600 * t.day #=> 19 @@ -4557,15 +4456,12 @@ time_wday(VALUE time) struct time_object *tobj; GetTimeval(time, tobj); - MAKE_TM(time, tobj); + MAKE_TM_ENSURE(time, tobj, tobj->vtm.wday != VTM_WDAY_INITVAL); return INT2FIX((int)tobj->vtm.wday); } #define wday_p(n) {\ - struct time_object *tobj;\ - GetTimeval(time, tobj);\ - MAKE_TM(time, tobj);\ - return (tobj->vtm.wday == (n)) ? Qtrue : Qfalse;\ + return RBOOL(time_wday(time) == INT2FIX(n)); \ } /* @@ -4696,7 +4592,7 @@ time_yday(VALUE time) struct time_object *tobj; GetTimeval(time, tobj); - MAKE_TM(time, tobj); + MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0); return INT2FIX(tobj->vtm.yday); } @@ -4735,7 +4631,7 @@ time_isdst(VALUE time) if (tobj->vtm.isdst == VTM_ISDST_INITVAL) { rb_raise(rb_eRuntimeError, "isdst is not set yet"); } - return tobj->vtm.isdst ? Qtrue : Qfalse; + return RBOOL(tobj->vtm.isdst); } /* @@ -4813,7 +4709,7 @@ rb_time_utc_offset(VALUE time) * * See the individual methods for an explanation of the * valid ranges of each value. The ten elements can be passed directly - * to Time::utc or Time::local to create a + * to Time.utc or Time.local to create a * new Time object. * * t = Time.now #=> 2007-11-19 08:36:01 -0600 @@ -4826,7 +4722,7 @@ time_to_a(VALUE time) struct time_object *tobj; GetTimeval(time, tobj); - MAKE_TM(time, tobj); + MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0); return rb_ary_new3(10, INT2FIX(tobj->vtm.sec), INT2FIX(tobj->vtm.min), @@ -4836,7 +4732,7 @@ time_to_a(VALUE time) tobj->vtm.year, INT2FIX(tobj->vtm.wday), INT2FIX(tobj->vtm.yday), - tobj->vtm.isdst?Qtrue:Qfalse, + RBOOL(tobj->vtm.isdst), time_zone(time)); } @@ -5068,7 +4964,7 @@ time_strftime(VALUE time, VALUE format) VALUE tmp; GetTimeval(time, tobj); - MAKE_TM(time, tobj); + MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0); StringValue(format); if (!rb_enc_str_asciicompat_p(format)) { rb_raise(rb_eArgError, "format should have ASCII compatible encoding"); @@ -5172,7 +5068,7 @@ time_mdump(VALUE time) * Append extended year distance from 1900..(1900+0xffff). In * each cases, there is no sign as the value is positive. The * format is length (marshaled long) + little endian packed - * binary (like as Fixnum and Bignum). + * binary (like as Integer). */ size_t ysize = rb_absint_size(year_extend, NULL); char *p, *const buf_year_extend = buf + base_dump_size; @@ -5296,8 +5192,8 @@ time_mload(VALUE time, VALUE str) get_attr(nano_num, {}); get_attr(nano_den, {}); get_attr(submicro, {}); - get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, NULL, Qnil))); - get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, NULL, Qnil))); + get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, 0, Qnil))); + get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, 0, Qnil))); get_attr(year, {}); #undef get_attr @@ -5307,8 +5203,7 @@ time_mload(VALUE time, VALUE str) StringValue(str); buf = (unsigned char *)RSTRING_PTR(str); if (RSTRING_LEN(str) < base_dump_size) { - invalid_format: - rb_raise(rb_eTypeError, "marshaled time format differ"); + goto invalid_format; } p = s = 0; @@ -5350,8 +5245,13 @@ time_mload(VALUE time, VALUE str) year = rb_int_plus(year, year_extend); } } + unsigned int mon = ((int)(p >> 10) & 0xf); /* 0...12 */ + if (mon >= 12) { + mon -= 12; + year = addv(year, LONG2FIX(1)); + } vtm.year = year; - vtm.mon = ((int)(p >> 10) & 0xf) + 1; + vtm.mon = mon + 1; vtm.mday = (int)(p >> 5) & 0x1f; vtm.hour = (int) p & 0x1f; vtm.min = (int)(s >> 26) & 0x3f; @@ -5359,7 +5259,7 @@ time_mload(VALUE time, VALUE str) vtm.utc_offset = INT2FIX(0); vtm.yday = vtm.wday = 0; vtm.isdst = 0; - vtm.zone = rb_fstring_lit(""); + vtm.zone = str_empty; usec = (long)(s & 0xfffff); nsec = usec * 1000; @@ -5411,6 +5311,10 @@ end_submicro: ; } return time; + + invalid_format: + rb_raise(rb_eTypeError, "marshaled time format differ"); + UNREACHABLE_RETURN(Qundef); } /* :nodoc: */ @@ -5451,6 +5355,7 @@ tm_from_time(VALUE klass, VALUE time) ttm = DATA_PTR(tm); v = &vtm; GMTIMEW(ttm->timew = tobj->timew, v); + ttm->timew = wsub(ttm->timew, v->subsecx); v->subsecx = INT2FIX(0); v->zone = Qnil; ttm->vtm = *v; @@ -5485,7 +5390,7 @@ tm_from_time(VALUE klass, VALUE time) /* * call-seq: * - * Time::tm.new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, tz=nil) -> tm + * Time::tm.new(year, month=nil, day=nil, hour=nil, min=nil, sec=nil, zone=nil) -> tm * * Creates new Time::tm object. */ @@ -5639,7 +5544,7 @@ Init_tm(VALUE outer, const char *name) #endif rb_define_method(tm, "initialize", tm_initialize, -1); rb_define_method(tm, "utc", tm_to_time, 0); - rb_alias(tm, rb_intern("to_time"), rb_intern("utc")); + rb_alias(tm, rb_intern_const("to_time"), rb_intern_const("utc")); rb_define_singleton_method(tm, "from_time", tm_from_time, 1); /* :startdoc:*/ @@ -5677,172 +5582,54 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time) return rb_obj_as_string(abbr); } -/* - * Time is an abstraction of dates and times. Time is stored internally as - * the number of seconds with fraction since the _Epoch_, January 1, 1970 - * 00:00 UTC. Also see the library module Date. The Time class treats GMT - * (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent. - * GMT is the older way of referring to these baseline times but persists in - * the names of calls on POSIX systems. - * - * All times may have fraction. Be aware of this fact when comparing times - * with each other -- times that are apparently equal when displayed may be - * different when compared. - * - * Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, - * Bignum or Rational. +/* Internal Details: + * + * Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer or + * Integer(T_BIGNUM), Rational. * The integer is a number of nanoseconds since the _Epoch_ which can * represent 1823-11-12 to 2116-02-20. - * When Bignum or Rational is used (before 1823, after 2116, under - * nanosecond), Time works slower as when integer is used. - * - * = Examples - * - * All of these examples were done using the EST timezone which is GMT-5. - * - * == Creating a new Time instance - * - * You can create a new instance of Time with Time::new. This will use the - * current system time. Time::now is an alias for this. You can also - * pass parts of the time to Time::new such as year, month, minute, etc. When - * you want to construct a time this way you must pass at least a year. If you - * pass the year with nothing else time will default to January 1 of that year - * at 00:00:00 with the current system timezone. Here are some examples: - * - * Time.new(2002) #=> 2002-01-01 00:00:00 -0500 - * Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500 - * Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500 - * - * You can pass a UTC offset: - * - * Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200 - * - * Or a timezone object: - * - * tz = timezone("Europe/Athens") # Eastern European Time, UTC+2 - * Time.new(2002, 10, 31, 2, 2, 2, tz) #=> 2002-10-31 02:02:02 +0200 - * - * You can also use Time::gm, Time::local and Time::utc to infer GMT, - * local and UTC timezones instead of using the current system - * setting. - * - * You can also create a new time using Time::at which takes the number of - * seconds (or fraction of seconds) since the {Unix - * Epoch}[http://en.wikipedia.org/wiki/Unix_time]. - * - * Time.at(628232400) #=> 1989-11-28 00:00:00 -0500 - * - * == Working with an instance of Time - * - * Once you have an instance of Time there is a multitude of things you can - * do with it. Below are some examples. For all of the following examples, we - * will work on the assumption that you have done the following: - * - * t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00") - * - * Was that a monday? - * - * t.monday? #=> false - * - * What year was that again? - * - * t.year #=> 1993 - * - * Was it daylight savings at the time? - * - * t.dst? #=> false - * - * What's the day a year later? - * - * t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900 - * - * How many seconds was that since the Unix Epoch? - * - * t.to_i #=> 730522800 - * - * You can also do standard functions like compare two times. - * - * t1 = Time.new(2010) - * t2 = Time.new(2011) - * - * t1 == t2 #=> false - * t1 == t1 #=> true - * t1 < t2 #=> true - * t1 > t2 #=> false - * - * Time.new(2010,10,31).between?(t1, t2) #=> true - * - * == Timezone argument - * - * A timezone argument must have +local_to_utc+ and +utc_to_local+ - * methods, and may have +name+, +abbr+, and +dst?+ methods. - * - * The +local_to_utc+ method should convert a Time-like object from - * the timezone to UTC, and +utc_to_local+ is the opposite. The - * result also should be a Time or Time-like object (not necessary to - * be the same class). The #zone of the result is just ignored. - * Time-like argument to these methods is similar to a Time object in - * UTC without sub-second; it has attribute readers for the parts, - * e.g. #year, #month, and so on, and epoch time readers, #to_i. The - * sub-second attributes are fixed as 0, and #utc_offset, #zone, - * #isdst, and their aliases are same as a Time object in UTC. - * Also #to_time, #+, and #- methods are defined. - * - * The +name+ method is used for marshaling. If this method is not - * defined on a timezone object, Time objects using that timezone - * object can not be dumped by Marshal. - * - * The +abbr+ method is used by '%Z' in #strftime. - * - * The +dst?+ method is called with a +Time+ value and should return whether - * the +Time+ value is in daylight savings time in the zone. - * - * === Auto conversion to Timezone - * - * At loading marshaled data, a timezone name will be converted to a timezone - * object by +find_timezone+ class method, if the method is defined. - * - * Similarly, that class method will be called when a timezone argument does - * not have the necessary methods mentioned above. + * When Integer(T_BIGNUM) or Rational is used (before 1823, after 2116, under + * nanosecond), Time works slower than when integer is used. */ +// void Init_Time(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - id_submicro = rb_intern("submicro"); - id_nano_num = rb_intern("nano_num"); - id_nano_den = rb_intern("nano_den"); - id_offset = rb_intern("offset"); - id_zone = rb_intern("zone"); - id_nanosecond = rb_intern("nanosecond"); - id_microsecond = rb_intern("microsecond"); - id_millisecond = rb_intern("millisecond"); - id_nsec = rb_intern("nsec"); - id_usec = rb_intern("usec"); - id_local_to_utc = rb_intern("local_to_utc"); - id_utc_to_local = rb_intern("utc_to_local"); - id_year = rb_intern("year"); - id_mon = rb_intern("mon"); - id_mday = rb_intern("mday"); - id_hour = rb_intern("hour"); - id_min = rb_intern("min"); - id_sec = rb_intern("sec"); - id_isdst = rb_intern("isdst"); - id_find_timezone = rb_intern("find_timezone"); + id_submicro = rb_intern_const("submicro"); + id_nano_num = rb_intern_const("nano_num"); + id_nano_den = rb_intern_const("nano_den"); + id_offset = rb_intern_const("offset"); + id_zone = rb_intern_const("zone"); + id_nanosecond = rb_intern_const("nanosecond"); + id_microsecond = rb_intern_const("microsecond"); + id_millisecond = rb_intern_const("millisecond"); + id_nsec = rb_intern_const("nsec"); + id_usec = rb_intern_const("usec"); + id_local_to_utc = rb_intern_const("local_to_utc"); + id_utc_to_local = rb_intern_const("utc_to_local"); + id_year = rb_intern_const("year"); + id_mon = rb_intern_const("mon"); + id_mday = rb_intern_const("mday"); + id_hour = rb_intern_const("hour"); + id_min = rb_intern_const("min"); + id_sec = rb_intern_const("sec"); + id_isdst = rb_intern_const("isdst"); + id_find_timezone = rb_intern_const("find_timezone"); + + str_utc = rb_fstring_lit("UTC"); + rb_gc_register_mark_object(str_utc); + str_empty = rb_fstring_lit(""); + rb_gc_register_mark_object(str_empty); rb_cTime = rb_define_class("Time", rb_cObject); rb_include_module(rb_cTime, rb_mComparable); rb_define_alloc_func(rb_cTime, time_s_alloc); - rb_define_singleton_method(rb_cTime, "now", time_s_now, -1); - rb_define_singleton_method(rb_cTime, "at", time_s_at, -1); rb_define_singleton_method(rb_cTime, "utc", time_s_mkutc, -1); - rb_define_singleton_method(rb_cTime, "gm", time_s_mkutc, -1); rb_define_singleton_method(rb_cTime, "local", time_s_mktime, -1); - rb_define_singleton_method(rb_cTime, "mktime", time_s_mktime, -1); + rb_define_alias(rb_singleton_class(rb_cTime), "gm", "utc"); + rb_define_alias(rb_singleton_class(rb_cTime), "mktime", "local"); rb_define_method(rb_cTime, "to_i", time_to_i, 0); rb_define_method(rb_cTime, "to_f", time_to_f, 0); @@ -5850,7 +5637,6 @@ Init_Time(void) rb_define_method(rb_cTime, "<=>", time_cmp, 1); rb_define_method(rb_cTime, "eql?", time_eql, 1); rb_define_method(rb_cTime, "hash", time_hash, 0); - rb_define_method(rb_cTime, "initialize", time_init, -1); rb_define_method(rb_cTime, "initialize_copy", time_init_copy, 1); rb_define_method(rb_cTime, "localtime", time_localtime_m, -1); @@ -5869,7 +5655,6 @@ Init_Time(void) rb_define_method(rb_cTime, "+", time_plus, 1); rb_define_method(rb_cTime, "-", time_minus, 1); - rb_define_method(rb_cTime, "succ", time_succ, 0); rb_define_method(rb_cTime, "round", time_round, -1); rb_define_method(rb_cTime, "floor", time_floor, -1); rb_define_method(rb_cTime, "ceil", time_ceil, -1); @@ -5920,9 +5705,12 @@ Init_Time(void) rb_define_private_method(rb_cTime, "marshal_load", time_mload, 1); #endif -#ifdef DEBUG_FIND_TIME_NUMGUESS - rb_define_virtual_variable("$find_time_numguess", find_time_numguess_getter, NULL); -#endif + if (debug_find_time_numguess) { + rb_define_hooked_variable("$find_time_numguess", (VALUE *)&find_time_numguess, + find_time_numguess_getter, NULL); + } rb_cTimeTM = Init_tm(rb_cTime, "tm"); } + +#include "timev.rbinc" diff --git a/ruby/timev.h b/ruby/timev.h index 6f124aa6b..af97ed95b 100644 --- a/ruby/timev.h +++ b/ruby/timev.h @@ -1,5 +1,6 @@ #ifndef RUBY_TIMEV_H #define RUBY_TIMEV_H +#include "ruby/ruby.h" #if 0 struct vtm {/* dummy for TAGS */}; diff --git a/ruby/timev.rb b/ruby/timev.rb new file mode 100644 index 000000000..52056f4e5 --- /dev/null +++ b/ruby/timev.rb @@ -0,0 +1,312 @@ +# Time is an abstraction of dates and times. Time is stored internally as +# the number of seconds with subsecond since the _Epoch_, +# 1970-01-01 00:00:00 UTC. +# +# The Time class treats GMT +# (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent. +# GMT is the older way of referring to these baseline times but persists in +# the names of calls on POSIX systems. +# +# Note: A \Time object uses the resolution available on your system clock. +# +# All times may have subsecond. Be aware of this fact when comparing times +# with each other -- times that are apparently equal when displayed may be +# different when compared. +# (Since Ruby 2.7.0, Time#inspect shows subsecond but +# Time#to_s still doesn't show subsecond.) +# +# == Examples +# +# All of these examples were done using the EST timezone which is GMT-5. +# +# === Creating a New \Time Instance +# +# You can create a new instance of Time with Time.new. This will use the +# current system time. Time.now is an alias for this. You can also +# pass parts of the time to Time.new such as year, month, minute, etc. When +# you want to construct a time this way you must pass at least a year. If you +# pass the year with nothing else time will default to January 1 of that year +# at 00:00:00 with the current system timezone. Here are some examples: +# +# Time.new(2002) #=> 2002-01-01 00:00:00 -0500 +# Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500 +# Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500 +# +# You can pass a UTC offset: +# +# Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200 +# +# Or a timezone object: +# +# zone = timezone("Europe/Athens") # Eastern European Time, UTC+2 +# Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200 +# +# You can also use Time.local and Time.utc to infer +# local and UTC timezones instead of using the current system +# setting. +# +# You can also create a new time using Time.at which takes the number of +# seconds (with subsecond) since the {Unix +# Epoch}[https://en.wikipedia.org/wiki/Unix_time]. +# +# Time.at(628232400) #=> 1989-11-28 00:00:00 -0500 +# +# === Working with an Instance of \Time +# +# Once you have an instance of Time there is a multitude of things you can +# do with it. Below are some examples. For all of the following examples, we +# will work on the assumption that you have done the following: +# +# t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00") +# +# Was that a monday? +# +# t.monday? #=> false +# +# What year was that again? +# +# t.year #=> 1993 +# +# Was it daylight savings at the time? +# +# t.dst? #=> false +# +# What's the day a year later? +# +# t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900 +# +# How many seconds was that since the Unix Epoch? +# +# t.to_i #=> 730522800 +# +# You can also do standard functions like compare two times. +# +# t1 = Time.new(2010) +# t2 = Time.new(2011) +# +# t1 == t2 #=> false +# t1 == t1 #=> true +# t1 < t2 #=> true +# t1 > t2 #=> false +# +# Time.new(2010,10,31).between?(t1, t2) #=> true +# +# == What's Here +# +# First, what's elsewhere. \Class \Time: +# +# - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here]. +# - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here]. +# +# Here, class \Time provides methods that are useful for: +# +# - {Creating \Time objects}[#class-Time-label-Methods+for+Creating]. +# - {Fetching \Time values}[#class-Time-label-Methods+for+Fetching]. +# - {Querying a \Time object}[#class-Time-label-Methods+for+Querying]. +# - {Comparing \Time objects}[#class-Time-label-Methods+for+Comparing]. +# - {Converting a \Time object}[#class-Time-label-Methods+for+Converting]. +# - {Rounding a \Time}[#class-Time-label-Methods+for+Rounding]. +# +# === Methods for Creating +# +# - ::new: Returns a new time from specified arguments (year, month, etc.), +# including an optional timezone value. +# - ::local (aliased as ::mktime): Same as ::new, except the +# timezone is the local timezone. +# - ::utc (aliased as ::gm): Same as ::new, except the timezone is UTC. +# - ::at: Returns a new time based on seconds since epoch. +# - ::now: Returns a new time based on the current system time. +# - #+ (plus): Returns a new time increased by the given number of seconds. +# - {-}[#method-i-2D] (minus): Returns a new time +# decreased by the given number of seconds. +# +# === Methods for Fetching +# +# - #year: Returns the year of the time. +# - #month (aliased as #mon): Returns the month of the time. +# - #mday (aliased as #day): Returns the day of the month. +# - #hour: Returns the hours value for the time. +# - #min: Returns the minutes value for the time. +# - #sec: Returns the seconds value for the time. +# - #usec (aliased as #tv_usec): Returns the number of microseconds +# in the subseconds value of the time. +# - #nsec (aliased as #tv_nsec: Returns the number of nanoseconds +# in the subsecond part of the time. +# - #subsec: Returns the subseconds value for the time. +# - #wday: Returns the integer weekday value of the time (0 == Sunday). +# - #yday: Returns the integer yearday value of the time (1 == January 1). +# - #hash: Returns the integer hash value for the time. +# - #utc_offset (aliased as #gmt_offset and #gmtoff): Returns the offset +# in seconds between time and UTC. +# - #to_f: Returns the float number of seconds since epoch for the time. +# - #to_i (aliased as #tv_sec): Returns the integer number of seconds since epoch +# for the time. +# - #to_r: Returns the Rational number of seconds since epoch for the time. +# - #zone: Returns a string representation of the timezone of the time. +# +# === Methods for Querying +# +# - #utc? (aliased as #gmt?): Returns whether the time is UTC. +# - #dst? (aliased as #isdst): Returns whether the time is DST (daylight saving time). +# - #sunday?: Returns whether the time is a Sunday. +# - #monday?: Returns whether the time is a Monday. +# - #tuesday?: Returns whether the time is a Tuesday. +# - #wednesday?: Returns whether the time is a Wednesday. +# - #thursday?: Returns whether the time is a Thursday. +# - #friday?: Returns whether time is a Friday. +# - #saturday?: Returns whether the time is a Saturday. +# +# === Methods for Comparing +# +# - {#<=>}[#method-i-3C-3D-3E]: Compares +self+ to another time. +# - #eql?: Returns whether the time is equal to another time. +# +# === Methods for Converting +# +# - #asctime (aliased as #ctime): Returns the time as a string. +# - #inspect: Returns the time in detail as a string. +# - #strftime: Returns the time as a string, according to a given format. +# - #to_a: Returns a 10-element array of values from the time. +# - #to_s: Returns a string representation of the time. +# - #getutc (aliased as #getgm): Returns a new time converted to UTC. +# - #getlocal: Returns a new time converted to local time. +# - #utc (aliased as #gmtime): Converts time to UTC in place. +# - #localtime: Converts time to local time in place. +# +# === Methods for Rounding +# +# - #round:Returns a new time with subseconds rounded. +# - #ceil: Returns a new time with subseconds raised to a ceiling. +# - #floor: Returns a new time with subseconds lowered to a floor. +# +# == Timezone Argument +# +# A timezone argument must have +local_to_utc+ and +utc_to_local+ +# methods, and may have +name+, +abbr+, and +dst?+ methods. +# +# The +local_to_utc+ method should convert a Time-like object from +# the timezone to UTC, and +utc_to_local+ is the opposite. The +# result also should be a Time or Time-like object (not necessary to +# be the same class). The #zone of the result is just ignored. +# Time-like argument to these methods is similar to a Time object in +# UTC without subsecond; it has attribute readers for the parts, +# e.g. #year, #month, and so on, and epoch time readers, #to_i. The +# subsecond attributes are fixed as 0, and #utc_offset, #zone, +# #isdst, and their aliases are same as a Time object in UTC. +# Also #to_time, #+, and #- methods are defined. +# +# The +name+ method is used for marshaling. If this method is not +# defined on a timezone object, Time objects using that timezone +# object can not be dumped by Marshal. +# +# The +abbr+ method is used by '%Z' in #strftime. +# +# The +dst?+ method is called with a +Time+ value and should return whether +# the +Time+ value is in daylight savings time in the zone. +# +# === Auto Conversion to Timezone +# +# At loading marshaled data, a timezone name will be converted to a timezone +# object by +find_timezone+ class method, if the method is defined. +# +# Similarly, that class method will be called when a timezone argument does +# not have the necessary methods mentioned above. +class Time + # Creates a new \Time object from the current system time. + # This is the same as Time.new without arguments. + # + # Time.now # => 2009-06-24 12:39:54 +0900 + # Time.now(in: '+04:00') # => 2009-06-24 07:39:54 +0400 + # + # Parameter: + # :include: doc/time/in.rdoc + def self.now(in: nil) + new(in: Primitive.arg!(:in)) + end + + # _Time_ + # + # This form accepts a \Time object +time+ + # and optional keyword argument +in+: + # + # Time.at(Time.new) # => 2021-04-26 08:52:31.6023486 -0500 + # Time.at(Time.new, in: '+09:00') # => 2021-04-26 22:52:31.6023486 +0900 + # + # _Seconds_ + # + # This form accepts a numeric number of seconds +sec+ + # and optional keyword argument +in+: + # + # Time.at(946702800) # => 1999-12-31 23:00:00 -0600 + # Time.at(946702800, in: '+09:00') # => 2000-01-01 14:00:00 +0900 + # + # Seconds with Subseconds and Units + # + # This form accepts an integer number of seconds +sec_i+, + # a numeric number of milliseconds +msec+, + # a symbol argument for the subsecond unit type (defaulting to :usec), + # and an optional keyword argument +in+: + # + # Time.at(946702800, 500, :millisecond) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500, :millisecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # Time.at(946702800, 500000) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500000, :usec) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500000, :microsecond) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500000, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # Time.at(946702800, 500000, :usec, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # Time.at(946702800, 500000, :microsecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # Time.at(946702800, 500000000, :nsec) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500000000, :nanosecond) # => 1999-12-31 23:00:00.5 -0600 + # Time.at(946702800, 500000000, :nsec, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # Time.at(946702800, 500000000, :nanosecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900 + # + # Parameters: + # :include: doc/time/sec_i.rdoc + # :include: doc/time/msec.rdoc + # :include: doc/time/usec.rdoc + # :include: doc/time/nsec.rdoc + # :include: doc/time/in.rdoc + # + def self.at(time, subsec = false, unit = :microsecond, in: nil) + if Primitive.mandatory_only? + Primitive.time_s_at1(time) + else + Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in)) + end + end + + # Returns a new \Time object based on the given arguments. + # + # With no positional arguments, returns the value of Time.now: + # + # Time.new # => 2021-04-24 17:27:46.0512465 -0500 + # + # Otherwise, returns a new \Time object based on the given parameters: + # + # Time.new(2000) # => 2000-01-01 00:00:00 -0600 + # Time.new(2000, 12, 31, 23, 59, 59.5) # => 2000-12-31 23:59:59.5 -0600 + # Time.new(2000, 12, 31, 23, 59, 59.5, '+09:00') # => 2000-12-31 23:59:59.5 +0900 + # + # Parameters: + # + # :include: doc/time/year.rdoc + # :include: doc/time/mon-min.rdoc + # :include: doc/time/sec.rdoc + # :include: doc/time/zone_and_in.rdoc + # + def initialize(year = (now = true), mon = nil, mday = nil, hour = nil, min = nil, sec = nil, zone = nil, in: nil) + if zone + if Primitive.arg!(:in) + raise ArgumentError, "timezone argument given as positional and keyword arguments" + end + else + zone = Primitive.arg!(:in) + end + + if now + return Primitive.time_init_now(zone) + end + + Primitive.time_init_args(year, mon, mday, hour, min, sec, zone) + end +end diff --git a/ruby/tool/actions-commit-info.sh b/ruby/tool/actions-commit-info.sh deleted file mode 100755 index 56f857c1d..000000000 --- a/ruby/tool/actions-commit-info.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -euo pipefail -cd $(dirname "$0")/.. -set_output () { - echo "$1=$2" - echo "::set-output name=$1::$2" -} -COMMIT_TIMESTAMP="$(git log -1 --format=%ct)" -set_output "COMMIT_TIMESTAMP" "$COMMIT_TIMESTAMP" -LOGS=$(TZ=UTC git log --since='0:00' --date=iso-local --format='%cd %s') -echo "commits of today:" -echo "$LOGS" -COUNT=$(echo "$LOGS" | wc -l) -# strip spaces -COUNT=$((0 + COUNT)) -set_output "COMMIT_NUMBER_OF_DAY" "$COUNT" -set_output "COMMIT_DATE" "$(TZ=UTC git log --since='0:00' --date=short-local --format=%cd -1)" diff --git a/ruby/tool/bisect.sh b/ruby/tool/bisect.sh index 3b9770714..dfc3a6404 100755 --- a/ruby/tool/bisect.sh +++ b/ruby/tool/bisect.sh @@ -38,6 +38,18 @@ case $1 in ;; esac +# Apply $(srcdir)/bisect.patch to build if exists +# e.g., needs 5c2508060b~2..5c2508060b to use Bison 3.5.91. +if [ -f bisect.patch ]; then + if ! patch -p1 -N < bisect.patch || git diff --no-patch --exit-code; then + exit 125 + fi + git status + exec= +else + exec=exec +fi + case "$0" in */*) # assume a copy of this script is in builddir @@ -47,4 +59,7 @@ esac for target in srcs Makefile $prep; do $MAKE $target || exit 125 done -exec $MAKE $run +$exec $MAKE $run +status=$? +git checkout -f HEAD +exit $status diff --git a/ruby/tool/bundler/dev_gems.rb b/ruby/tool/bundler/dev_gems.rb new file mode 100644 index 000000000..20a9594f4 --- /dev/null +++ b/ruby/tool/bundler/dev_gems.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "rdoc", "6.2.0" # 6.2.1 is required > Ruby 2.3 +gem "test-unit", "~> 3.0" +gem "rake", "~> 13.0" + +group :lint do + gem "rubocop", "~> 0.80.1" + gem "rubocop-performance", "~> 1.5.2" +end + +gem "webrick", "~> 1.6" +gem "parallel_tests", "~> 2.29" +gem "parallel", "1.19.2" # 1.20+ is required > Ruby 2.3 +gem "rspec-core", "~> 3.8" +gem "rspec-expectations", "~> 3.8" +gem "rspec-mocks", "~> 3.8" +gem "uri", "~> 0.10.1" + +group :doc do + gem "ronn", "~> 0.7.3", :platform => :ruby +end diff --git a/ruby/tool/bundler/dev_gems.rb.lock b/ruby/tool/bundler/dev_gems.rb.lock new file mode 100644 index 000000000..2c24fe079 --- /dev/null +++ b/ruby/tool/bundler/dev_gems.rb.lock @@ -0,0 +1,75 @@ +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + diff-lcs (1.5.0) + hpricot (0.8.6) + jaro_winkler (1.5.4) + jaro_winkler (1.5.4-java) + mustache (1.1.1) + parallel (1.19.2) + parallel_tests (2.32.0) + parallel + parser (3.1.0.0) + ast (~> 2.4.1) + power_assert (2.0.1) + rainbow (3.1.1) + rake (13.0.6) + rdiscount (2.2.0.2) + rdoc (6.2.0) + rexml (3.2.5) + ronn (0.7.3) + hpricot (>= 0.8.2) + mustache (>= 0.7.0) + rdiscount (>= 1.5.8) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.3) + rubocop (0.80.1) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.7.0.1) + rainbow (>= 2.2.2, < 4.0) + rexml + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 1.7) + rubocop-performance (1.5.2) + rubocop (>= 0.71.0) + ruby-progressbar (1.11.0) + test-unit (3.5.3) + power_assert + unicode-display_width (1.6.1) + uri (0.10.1) + webrick (1.7.0) + +PLATFORMS + java + ruby + universal-java-11 + x64-mingw32 + x86_64-darwin-20 + x86_64-linux + +DEPENDENCIES + parallel (= 1.19.2) + parallel_tests (~> 2.29) + rake (~> 13.0) + rdoc (= 6.2.0) + ronn (~> 0.7.3) + rspec-core (~> 3.8) + rspec-expectations (~> 3.8) + rspec-mocks (~> 3.8) + rubocop (~> 0.80.1) + rubocop-performance (~> 1.5.2) + test-unit (~> 3.0) + uri (~> 0.10.1) + webrick (~> 1.6) + +BUNDLED WITH + 2.3.7 diff --git a/ruby/tool/bundler/rubocop_gems.rb b/ruby/tool/bundler/rubocop_gems.rb new file mode 100644 index 000000000..84cb22633 --- /dev/null +++ b/ruby/tool/bundler/rubocop_gems.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "rubocop", "~> 1.7" + +gem "minitest" +gem "rake" +gem "rake-compiler" +gem "rspec" +gem "test-unit" diff --git a/ruby/tool/bundler/rubocop_gems.rb.lock b/ruby/tool/bundler/rubocop_gems.rb.lock new file mode 100644 index 000000000..2d0439f0c --- /dev/null +++ b/ruby/tool/bundler/rubocop_gems.rb.lock @@ -0,0 +1,63 @@ +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + diff-lcs (1.5.0) + minitest (5.15.0) + parallel (1.21.0) + parser (3.1.0.0) + ast (~> 2.4.1) + power_assert (2.0.1) + rainbow (3.1.1) + rake (13.0.6) + rake-compiler (1.1.7) + rake + regexp_parser (2.2.0) + rexml (3.2.5) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.3) + rubocop (1.24.1) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.15.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.15.1) + parser (>= 3.0.1.1) + ruby-progressbar (1.11.0) + test-unit (3.5.3) + power_assert + unicode-display_width (2.1.0) + +PLATFORMS + arm64-darwin-20 + arm64-darwin-21 + universal-java-11 + x86_64-darwin-19 + x86_64-darwin-20 + x86_64-linux + +DEPENDENCIES + minitest + rake + rake-compiler + rspec + rubocop (~> 1.7) + test-unit + +BUNDLED WITH + 2.3.7 diff --git a/ruby/tool/bundler/standard_gems.rb b/ruby/tool/bundler/standard_gems.rb new file mode 100644 index 000000000..1cd189742 --- /dev/null +++ b/ruby/tool/bundler/standard_gems.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "standard", "~> 1.0" + +gem "minitest" +gem "rake" +gem "rake-compiler" +gem "rspec" +gem "test-unit" diff --git a/ruby/tool/bundler/standard_gems.rb.lock b/ruby/tool/bundler/standard_gems.rb.lock new file mode 100644 index 000000000..b29da0606 --- /dev/null +++ b/ruby/tool/bundler/standard_gems.rb.lock @@ -0,0 +1,69 @@ +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + diff-lcs (1.5.0) + minitest (5.15.0) + parallel (1.21.0) + parser (3.1.0.0) + ast (~> 2.4.1) + power_assert (2.0.1) + rainbow (3.1.1) + rake (13.0.6) + rake-compiler (1.1.7) + rake + regexp_parser (2.2.0) + rexml (3.2.5) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.3) + rubocop (1.24.1) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.15.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.15.1) + parser (>= 3.0.1.1) + rubocop-performance (1.13.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + ruby-progressbar (1.11.0) + standard (1.6.0) + rubocop (= 1.24.1) + rubocop-performance (= 1.13.1) + test-unit (3.5.3) + power_assert + unicode-display_width (2.1.0) + +PLATFORMS + arm64-darwin-20 + arm64-darwin-21 + universal-java-11 + x86_64-darwin-19 + x86_64-darwin-20 + x86_64-linux + +DEPENDENCIES + minitest + rake + rake-compiler + rspec + standard (~> 1.0) + test-unit + +BUNDLED WITH + 2.3.7 diff --git a/ruby/tool/bundler/test_gems.rb b/ruby/tool/bundler/test_gems.rb new file mode 100644 index 000000000..215d23183 --- /dev/null +++ b/ruby/tool/bundler/test_gems.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "rack", "2.0.8" +gem "webrick", "1.7.0" +gem "rack-test", "~> 1.1" +gem "artifice", "~> 0.6.0" +gem "compact_index", "~> 0.13.0" +gem "sinatra", "~> 2.0" +gem "rake", "13.0.1" +gem "builder", "~> 3.2" diff --git a/ruby/tool/bundler/test_gems.rb.lock b/ruby/tool/bundler/test_gems.rb.lock new file mode 100644 index 000000000..d66c2972d --- /dev/null +++ b/ruby/tool/bundler/test_gems.rb.lock @@ -0,0 +1,44 @@ +GEM + remote: https://rubygems.org/ + specs: + artifice (0.6) + rack-test + builder (3.2.4) + compact_index (0.13.0) + mustermann (1.1.1) + ruby2_keywords (~> 0.0.1) + rack (2.0.8) + rack-protection (2.0.8.1) + rack + rack-test (1.1.0) + rack (>= 1.0, < 3) + rake (13.0.1) + ruby2_keywords (0.0.5) + sinatra (2.0.8.1) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.8.1) + tilt (~> 2.0) + tilt (2.0.10) + webrick (1.7.0) + +PLATFORMS + java + ruby + universal-java-11 + x64-mingw32 + x86_64-darwin-20 + x86_64-linux + +DEPENDENCIES + artifice (~> 0.6.0) + builder (~> 3.2) + compact_index (~> 0.13.0) + rack (= 2.0.8) + rack-test (~> 1.1) + rake (= 13.0.1) + sinatra (~> 2.0) + webrick (= 1.7.0) + +BUNDLED WITH + 2.3.7 diff --git a/ruby/tool/ci_functions.sh b/ruby/tool/ci_functions.sh new file mode 100644 index 000000000..7066bbe4e --- /dev/null +++ b/ruby/tool/ci_functions.sh @@ -0,0 +1,29 @@ +# -*- BASH -*- +# Manage functions used on a CI. +# Run `. tool/ci_functions.sh` to use it. + +# Create options with patterns `-n !/name1/ -n !/name2/ ..` to exclude the test +# method names by the method names `name1 name2 ..`. +# See `ruby tool/test/runner.rb --help` `-n` option. +function ci_to_excluded_test_opts { + local tests_str="${1}" + # Use the backward matching `!/name$/`, as the perfect matching doesn't work. + # https://bugs.ruby-lang.org/issues/16936 + ruby <. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -# -# Please send patches to . - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2019 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -tmp= -# shellcheck disable=SC2172 -trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 - -set_cc_for_build() { - : "${TMPDIR=/tmp}" - # shellcheck disable=SC2039 - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } - dummy=$tmp/dummy - case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in - ,,) echo "int x;" > "$dummy.c" - for driver in cc gcc c89 c99 ; do - if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$driver" - break - fi - done - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; - esac -} - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if test -f /.attbin/uname ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "$UNAME_SYSTEM" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - set_cc_for_build - cat <<-EOF > "$dummy.c" - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" - - # If ldd exists, use it to detect musl libc. - if command -v ldd >/dev/null && \ - ldd --version 2>&1 | grep -q ^musl - then - LIBC=musl - fi - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - "/sbin/$sysctl" 2>/dev/null || \ - "/usr/sbin/$sysctl" 2>/dev/null || \ - echo unknown)` - case "$UNAME_MACHINE_ARCH" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` - machine="${arch}${endian}"-unknown - ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in - Debian*) - release='-gnu' - ;; - *) - release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi-}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" - exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; - *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" - exit ;; - *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" - exit ;; - *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; - *:OS108:*:*) - echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" - exit ;; - *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" - exit ;; - *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; - *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; - mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - set_cc_for_build - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" - ;; - sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && - dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`"$dummy" "$dummyarg"` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] - then - if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ - [ "$TARGET_BINARY_INTERFACE"x = x ] - then - echo m88k-dg-dgux"$UNAME_RELEASE" - else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" - fi - else - echo i586-dg-dgux"$UNAME_RELEASE" - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" - fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" - fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - case "$UNAME_MACHINE" in - 9000/31?) HP_ARCH=m68000 ;; - 9000/[34]??) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "$sc_cpu_version" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "$HP_ARCH" = "" ]; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ "$HP_ARCH" = hppa2.0w ] - then - set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux"$HPUX_REV" - exit ;; - 3050*:HI-UX:*:*) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo "$UNAME_MACHINE"-unknown-osf1mk - else - echo "$UNAME_MACHINE"-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" - exit ;; - *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; - arm:FreeBSD:*:*) - UNAME_PROCESSOR=`uname -p` - set_cc_for_build - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi - else - echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf - fi - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case "$UNAME_PROCESSOR" in - amd64) - UNAME_PROCESSOR=x86_64 ;; - i386) - UNAME_PROCESSOR=i586 ;; - esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; - i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin - exit ;; - *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 - exit ;; - *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 - exit ;; - *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys - exit ;; - i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 - exit ;; - *:Interix*:*) - case "$UNAME_MACHINE" in - x86) - echo i586-pc-interix"$UNAME_RELEASE" - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" - exit ;; - IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" - exit ;; - esac ;; - i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-pc-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; - *:GNU:*:*) - # the GNU system - echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" - exit ;; - *:Minix:*:*) - echo "$UNAME_MACHINE"-unknown-minix - exit ;; - aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arm*:Linux:*:*) - set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi - else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; - crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; - e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; - ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - set_cc_for_build - IS_GLIBC=0 - test x"${LIBC}" = xgnu && IS_GLIBC=1 - sed 's/^ //' << EOF > "$dummy.c" - #undef CPU - #undef mips - #undef mipsel - #undef mips64 - #undef mips64el - #if ${IS_GLIBC} && defined(_ABI64) - LIBCABI=gnuabi64 - #else - #if ${IS_GLIBC} && defined(_ABIN32) - LIBCABI=gnuabin32 - #else - LIBCABI=${LIBC} - #endif - #endif - - #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa64r6 - #else - #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa32r6 - #else - #if defined(__mips64) - CPU=mips64 - #else - CPU=mips - #endif - #endif - #endif - - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - MIPS_ENDIAN=el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - MIPS_ENDIAN= - #else - MIPS_ENDIAN= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" - test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } - ;; - mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" - exit ;; - sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" - exit ;; - x86_64:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; - xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop - exit ;; - i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" - exit ;; - i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp - exit ;; - i*86:*:4.*:*) - UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" - else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" - else - echo "$UNAME_MACHINE"-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo "$UNAME_MACHINE"-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo "$UNAME_MACHINE"-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv"$UNAME_RELEASE" - else - echo mips-unknown-sysv"$UNAME_RELEASE" - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" - exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" - exit ;; - *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac - if command -v xcode-select > /dev/null 2> /dev/null && \ - ! xcode-select --print-path > /dev/null 2> /dev/null ; then - # Avoid executing cc if there is no toolchain installed as - # cc will be a stub that puts up a graphical alert - # prompting the user to install developer tools. - CC_FOR_BUILD=no_compiler_found - else - set_cc_for_build - fi - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # uname -m returns i386 or x86_64 - UNAME_PROCESSOR=$UNAME_MACHINE - fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - # shellcheck disable=SC2154 - if test "$cputype" = 386; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo "$UNAME_MACHINE"-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" - exit ;; - *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" - exit ;; - i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos - exit ;; - i*86:AROS:*:*) - echo "$UNAME_MACHINE"-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx - exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; - *:Unleashed:*:*) - echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" - exit ;; -esac - -# No uname command or uname output not recognized. -set_cc_for_build -cat > "$dummy.c" < -#include -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#include -#if defined(_SIZE_T_) || defined(SIGLOST) -#include -#endif -#endif -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); -#endif - -#if defined (vax) -#if !defined (ultrix) -#include -#if defined (BSD) -#if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -#else -#if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#endif -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#else -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname un; - uname (&un); - printf ("vax-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif -#endif -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname *un; - uname (&un); - printf ("mips-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("mips-dec-ultrix\n"); exit (0); -#endif -#endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. -test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } - -echo "$0: unable to guess system type" >&2 - -case "$UNAME_MACHINE:$UNAME_SYSTEM" in - mips:Linux | mips64:Linux) - # If we got here on MIPS GNU/Linux, output extra information. - cat >&2 <&2 </dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = "$UNAME_MACHINE" -UNAME_RELEASE = "$UNAME_RELEASE" -UNAME_SYSTEM = "$UNAME_SYSTEM" -UNAME_VERSION = "$UNAME_VERSION" -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ruby/tool/config.guess b/ruby/tool/config.guess new file mode 120000 index 000000000..454932db1 --- /dev/null +++ b/ruby/tool/config.guess @@ -0,0 +1 @@ +../.downloaded-cache/config.guess \ No newline at end of file diff --git a/ruby/tool/config.sub b/ruby/tool/config.sub deleted file mode 100755 index a318a4686..000000000 --- a/ruby/tool/config.sub +++ /dev/null @@ -1,1793 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2019 Free Software Foundation, Inc. - -timestamp='2019-06-30' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2019 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo "$1" - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Split fields of configuration type -# shellcheck disable=SC2162 -IFS="-" read field1 field2 field3 field4 <&2 - exit 1 - ;; - *-*-*-*) - basic_machine=$field1-$field2 - os=$field3-$field4 - ;; - *-*-*) - # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two - # parts - maybe_os=$field2-$field3 - case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ - | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ - | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ - | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova*) - basic_machine=$field1 - os=$maybe_os - ;; - android-linux) - basic_machine=$field1-unknown - os=linux-android - ;; - *) - basic_machine=$field1-$field2 - os=$field3 - ;; - esac - ;; - *-*) - # A lone config we happen to match not fitting any pattern - case $field1-$field2 in - decstation-3100) - basic_machine=mips-dec - os= - ;; - *-*) - # Second component is usually, but not always the OS - case $field2 in - # Prevent following clause from handling this valid os - sun*os*) - basic_machine=$field1 - os=$field2 - ;; - # Manufacturers - dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ - | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ - | unicom* | ibm* | next | hp | isi* | apollo | altos* \ - | convergent* | ncr* | news | 32* | 3600* | 3100* \ - | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ - | ultra | tti* | harris | dolphin | highlevel | gould \ - | cbm | ns | masscomp | apple | axis | knuth | cray \ - | microblaze* | sim | cisco \ - | oki | wec | wrs | winbond) - basic_machine=$field1-$field2 - os= - ;; - *) - basic_machine=$field1 - os=$field2 - ;; - esac - ;; - esac - ;; - *) - # Convert single-component short-hands not valid as part of - # multi-component configurations. - case $field1 in - 386bsd) - basic_machine=i386-pc - os=bsd - ;; - a29khif) - basic_machine=a29k-amd - os=udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=scout - ;; - alliant) - basic_machine=fx80-alliant - os= - ;; - altos | altos3068) - basic_machine=m68k-altos - os= - ;; - am29k) - basic_machine=a29k-none - os=bsd - ;; - amdahl) - basic_machine=580-amdahl - os=sysv - ;; - amiga) - basic_machine=m68k-unknown - os= - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=bsd - ;; - aros) - basic_machine=i386-pc - os=aros - ;; - aux) - basic_machine=m68k-apple - os=aux - ;; - balance) - basic_machine=ns32k-sequent - os=dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=linux - ;; - cegcc) - basic_machine=arm-unknown - os=cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=bsd - ;; - convex-c2) - basic_machine=c2-convex - os=bsd - ;; - convex-c32) - basic_machine=c32-convex - os=bsd - ;; - convex-c34) - basic_machine=c34-convex - os=bsd - ;; - convex-c38) - basic_machine=c38-convex - os=bsd - ;; - cray) - basic_machine=j90-cray - os=unicos - ;; - crds | unos) - basic_machine=m68k-crds - os= - ;; - da30) - basic_machine=m68k-da30 - os= - ;; - decstation | pmax | pmin | dec3100 | decstatn) - basic_machine=mips-dec - os= - ;; - delta88) - basic_machine=m88k-motorola - os=sysv3 - ;; - dicos) - basic_machine=i686-pc - os=dicos - ;; - djgpp) - basic_machine=i586-pc - os=msdosdjgpp - ;; - ebmon29k) - basic_machine=a29k-amd - os=ebmon - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=ose - ;; - gmicro) - basic_machine=tron-gmicro - os=sysv - ;; - go32) - basic_machine=i386-pc - os=go32 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=hms - ;; - harris) - basic_machine=m88k-harris - os=sysv3 - ;; - hp300 | hp300hpux) - basic_machine=m68k-hp - os=hpux - ;; - hp300bsd) - basic_machine=m68k-hp - os=bsd - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=proelf - ;; - i386mach) - basic_machine=i386-mach - os=mach - ;; - isi68 | isi) - basic_machine=m68k-isi - os=sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=linux - ;; - magnum | m3230) - basic_machine=mips-mips - os=sysv - ;; - merlin) - basic_machine=ns32k-utek - os=sysv - ;; - mingw64) - basic_machine=x86_64-pc - os=mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=mingw32ce - ;; - monitor) - basic_machine=m68k-rom68k - os=coff - ;; - morphos) - basic_machine=powerpc-unknown - os=morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=moxiebox - ;; - msdos) - basic_machine=i386-pc - os=msdos - ;; - msys) - basic_machine=i686-pc - os=msys - ;; - mvs) - basic_machine=i370-ibm - os=mvs - ;; - nacl) - basic_machine=le32-unknown - os=nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=sysv4 - ;; - netbsd386) - basic_machine=i386-pc - os=netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=newsos - ;; - news1000) - basic_machine=m68030-sony - os=newsos - ;; - necv70) - basic_machine=v70-nec - os=sysv - ;; - nh3000) - basic_machine=m68k-harris - os=cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=cxux - ;; - nindy960) - basic_machine=i960-intel - os=nindy - ;; - mon960) - basic_machine=i960-intel - os=mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=nonstopux - ;; - os400) - basic_machine=powerpc-ibm - os=os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=ose - ;; - os68k) - basic_machine=m68k-none - os=os68k - ;; - paragon) - basic_machine=i860-intel - os=osf - ;; - parisc) - basic_machine=hppa-unknown - os=linux - ;; - pw32) - basic_machine=i586-unknown - os=pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=rdos - ;; - rdos32) - basic_machine=i386-pc - os=rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=coff - ;; - sa29200) - basic_machine=a29k-amd - os=udi - ;; - sei) - basic_machine=mips-sei - os=seiux - ;; - sequent) - basic_machine=i386-sequent - os= - ;; - sps7) - basic_machine=m68k-bull - os=sysv2 - ;; - st2000) - basic_machine=m68k-tandem - os= - ;; - stratus) - basic_machine=i860-stratus - os=sysv4 - ;; - sun2) - basic_machine=m68000-sun - os= - ;; - sun2os3) - basic_machine=m68000-sun - os=sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=sunos4 - ;; - sun3) - basic_machine=m68k-sun - os= - ;; - sun3os3) - basic_machine=m68k-sun - os=sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=sunos4 - ;; - sun4) - basic_machine=sparc-sun - os= - ;; - sun4os3) - basic_machine=sparc-sun - os=sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=solaris2 - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - os= - ;; - sv1) - basic_machine=sv1-cray - os=unicos - ;; - symmetry) - basic_machine=i386-sequent - os=dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=unicos - ;; - t90) - basic_machine=t90-cray - os=unicos - ;; - toad1) - basic_machine=pdp10-xkl - os=tops20 - ;; - tpf) - basic_machine=s390x-ibm - os=tpf - ;; - udi29k) - basic_machine=a29k-amd - os=udi - ;; - ultra3) - basic_machine=a29k-nyu - os=sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=none - ;; - vaxv) - basic_machine=vax-dec - os=sysv - ;; - vms) - basic_machine=vax-dec - os=vms - ;; - vsta) - basic_machine=i386-pc - os=vsta - ;; - vxworks960) - basic_machine=i960-wrs - os=vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=vxworks - ;; - xbox) - basic_machine=i686-pc - os=mingw32 - ;; - ymp) - basic_machine=ymp-cray - os=unicos - ;; - *) - basic_machine=$1 - os= - ;; - esac - ;; -esac - -# Decode 1-component or ad-hoc basic machines -case $basic_machine in - # Here we handle the default manufacturer of certain CPU types. It is in - # some cases the only manufacturer, in others, it is the most popular. - w89k) - cpu=hppa1.1 - vendor=winbond - ;; - op50n) - cpu=hppa1.1 - vendor=oki - ;; - op60c) - cpu=hppa1.1 - vendor=oki - ;; - ibm*) - cpu=i370 - vendor=ibm - ;; - orion105) - cpu=clipper - vendor=highlevel - ;; - mac | mpw | mac-mpw) - cpu=m68k - vendor=apple - ;; - pmac | pmac-mpw) - cpu=powerpc - vendor=apple - ;; - - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - cpu=m68000 - vendor=att - ;; - 3b*) - cpu=we32k - vendor=att - ;; - bluegene*) - cpu=powerpc - vendor=ibm - os=cnk - ;; - decsystem10* | dec10*) - cpu=pdp10 - vendor=dec - os=tops10 - ;; - decsystem20* | dec20*) - cpu=pdp10 - vendor=dec - os=tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - cpu=m68k - vendor=motorola - ;; - dpx2*) - cpu=m68k - vendor=bull - os=sysv3 - ;; - encore | umax | mmax) - cpu=ns32k - vendor=encore - ;; - elxsi) - cpu=elxsi - vendor=elxsi - os=${os:-bsd} - ;; - fx2800) - cpu=i860 - vendor=alliant - ;; - genix) - cpu=ns32k - vendor=ns - ;; - h3050r* | hiux*) - cpu=hppa1.1 - vendor=hitachi - os=hiuxwe2 - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - cpu=m68000 - vendor=hp - ;; - hp9k3[2-9][0-9]) - cpu=m68k - vendor=hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - cpu=hppa1.1 - vendor=hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - i*86v32) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - os=sysv32 - ;; - i*86v4*) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - os=sysv4 - ;; - i*86v) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - os=sysv - ;; - i*86sol2) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - os=solaris2 - ;; - j90 | j90-cray) - cpu=j90 - vendor=cray - os=${os:-unicos} - ;; - iris | iris4d) - cpu=mips - vendor=sgi - case $os in - irix*) - ;; - *) - os=irix4 - ;; - esac - ;; - miniframe) - cpu=m68000 - vendor=convergent - ;; - *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) - cpu=m68k - vendor=atari - os=mint - ;; - news-3600 | risc-news) - cpu=mips - vendor=sony - os=newsos - ;; - next | m*-next) - cpu=m68k - vendor=next - case $os in - openstep*) - ;; - nextstep*) - ;; - ns2*) - os=nextstep2 - ;; - *) - os=nextstep3 - ;; - esac - ;; - np1) - cpu=np1 - vendor=gould - ;; - op50n-* | op60c-*) - cpu=hppa1.1 - vendor=oki - os=proelf - ;; - pa-hitachi) - cpu=hppa1.1 - vendor=hitachi - os=hiuxwe2 - ;; - pbd) - cpu=sparc - vendor=tti - ;; - pbb) - cpu=m68k - vendor=tti - ;; - pc532) - cpu=ns32k - vendor=pc532 - ;; - pn) - cpu=pn - vendor=gould - ;; - power) - cpu=power - vendor=ibm - ;; - ps2) - cpu=i386 - vendor=ibm - ;; - rm[46]00) - cpu=mips - vendor=siemens - ;; - rtpc | rtpc-*) - cpu=romp - vendor=ibm - ;; - sde) - cpu=mipsisa32 - vendor=sde - os=${os:-elf} - ;; - simso-wrs) - cpu=sparclite - vendor=wrs - os=vxworks - ;; - tower | tower-32) - cpu=m68k - vendor=ncr - ;; - vpp*|vx|vx-*) - cpu=f301 - vendor=fujitsu - ;; - w65) - cpu=w65 - vendor=wdc - ;; - w89k-*) - cpu=hppa1.1 - vendor=winbond - os=proelf - ;; - none) - cpu=none - vendor=none - ;; - leon|leon[3-9]) - cpu=sparc - vendor=$basic_machine - ;; - leon-*|leon[3-9]-*) - cpu=sparc - vendor=`echo "$basic_machine" | sed 's/-.*//'` - ;; - - *-*) - # shellcheck disable=SC2162 - IFS="-" read cpu vendor <&2 - exit 1 - ;; - esac - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $vendor in - digital*) - vendor=dec - ;; - commodore*) - vendor=cbm - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x$os != x ] -then -case $os in - # First match some system type aliases that might get confused - # with valid system types. - # solaris* is a basic system type, with this one exception. - auroraux) - os=auroraux - ;; - bluegene*) - os=cnk - ;; - solaris1 | solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - solaris) - os=solaris2 - ;; - unixware*) - os=sysv4.2uw - ;; - gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # es1800 is here to avoid being matched by es* (a different OS) - es1800*) - os=ose - ;; - # Some version numbers need modification - chorusos*) - os=chorusos - ;; - isc) - os=isc2.2 - ;; - sco6) - os=sco5v6 - ;; - sco5) - os=sco3.2v5 - ;; - sco4) - os=sco3.2v4 - ;; - sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - ;; - sco3.2v[4-9]* | sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - ;; - scout) - # Don't match below - ;; - sco*) - os=sco3.2v2 - ;; - psos*) - os=psos - ;; - # Now accept the basic system types. - # The portable systems comes first. - # Each alternative MUST end in a * to match a version number. - # sysv* is not here because it comes later, after sysvr4. - gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ - | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ - | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ - | sym* | kopensolaris* | plan9* \ - | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ - | aos* | aros* | cloudabi* | sortix* \ - | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ - | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ - | knetbsd* | mirbsd* | netbsd* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ - | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ - | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ - | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ - | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ - | chorusrdb* | cegcc* | glidix* \ - | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ - | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ - | linux-newlib* | linux-musl* | linux-uclibc* \ - | uxpv* | beos* | mpeix* | udk* | moxiebox* \ - | interix* | uwin* | mks* | rhapsody* | darwin* \ - | openstep* | oskit* | conix* | pw32* | nonstopux* \ - | storm-chaos* | tops10* | tenex* | tops20* | its* \ - | os2* | vos* | palmos* | uclinux* | nucleus* \ - | morphos* | superux* | rtmk* | windiss* \ - | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ - | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ - | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ - | nsk* | powerunix) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - qnx*) - case $cpu in - x86 | i*86) - ;; - *) - os=nto-$os - ;; - esac - ;; - hiux*) - os=hiuxwe2 - ;; - nto-qnx*) - ;; - nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - sim | xray | os68k* | v88r* \ - | windows* | osx | abug | netware* | os9* \ - | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) - ;; - linux-dietlibc) - os=linux-dietlibc - ;; - linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - lynx*178) - os=lynxos178 - ;; - lynx*5) - os=lynxos5 - ;; - lynx*) - os=lynxos - ;; - mac*) - os=`echo "$os" | sed -e 's|mac|macos|'` - ;; - opened*) - os=openedition - ;; - os400*) - os=os400 - ;; - sunos5*) - os=`echo "$os" | sed -e 's|sunos5|solaris2|'` - ;; - sunos6*) - os=`echo "$os" | sed -e 's|sunos6|solaris3|'` - ;; - wince*) - os=wince - ;; - utek*) - os=bsd - ;; - dynix*) - os=bsd - ;; - acis*) - os=aos - ;; - atheos*) - os=atheos - ;; - syllable*) - os=syllable - ;; - 386bsd) - os=bsd - ;; - ctix* | uts*) - os=sysv - ;; - nova*) - os=rtmk-nova - ;; - ns2) - os=nextstep2 - ;; - # Preserve the version number of sinix5. - sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - sinix*) - os=sysv4 - ;; - tpf*) - os=tpf - ;; - triton*) - os=sysv3 - ;; - oss*) - os=sysv3 - ;; - svr4*) - os=sysv4 - ;; - svr3) - os=sysv3 - ;; - sysvr4) - os=sysv4 - ;; - # This must come after sysvr4. - sysv*) - ;; - ose*) - os=ose - ;; - *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) - os=mint - ;; - zvmoe) - os=zvmoe - ;; - dicos*) - os=dicos - ;; - pikeos*) - # Until real need of OS specific support for - # particular features comes up, bare metal - # configurations are quite functional. - case $cpu in - arm*) - os=eabi - ;; - *) - os=elf - ;; - esac - ;; - nacl*) - ;; - ios) - ;; - none) - ;; - *-eabi) - ;; - *) - echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $cpu-$vendor in - score-*) - os=elf - ;; - spu-*) - os=elf - ;; - *-acorn) - os=riscix1.2 - ;; - arm*-rebel) - os=linux - ;; - arm*-semi) - os=aout - ;; - c4x-* | tic4x-*) - os=coff - ;; - c8051-*) - os=elf - ;; - clipper-intergraph) - os=clix - ;; - hexagon-*) - os=elf - ;; - tic54x-*) - os=coff - ;; - tic55x-*) - os=coff - ;; - tic6x-*) - os=coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=tops20 - ;; - pdp11-*) - os=none - ;; - *-dec | vax-*) - os=ultrix4.2 - ;; - m68*-apollo) - os=domain - ;; - i386-sun) - os=sunos4.0.2 - ;; - m68000-sun) - os=sunos3 - ;; - m68*-cisco) - os=aout - ;; - mep-*) - os=elf - ;; - mips*-cisco) - os=elf - ;; - mips*-*) - os=elf - ;; - or32-*) - os=coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=sysv3 - ;; - sparc-* | *-sun) - os=sunos4.1.1 - ;; - pru-*) - os=elf - ;; - *-be) - os=beos - ;; - *-ibm) - os=aix - ;; - *-knuth) - os=mmixware - ;; - *-wec) - os=proelf - ;; - *-winbond) - os=proelf - ;; - *-oki) - os=proelf - ;; - *-hp) - os=hpux - ;; - *-hitachi) - os=hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=sysv - ;; - *-cbm) - os=amigaos - ;; - *-dg) - os=dgux - ;; - *-dolphin) - os=sysv3 - ;; - m68k-ccur) - os=rtu - ;; - m88k-omron*) - os=luna - ;; - *-next) - os=nextstep - ;; - *-sequent) - os=ptx - ;; - *-crds) - os=unos - ;; - *-ns) - os=genix - ;; - i370-*) - os=mvs - ;; - *-gould) - os=sysv - ;; - *-highlevel) - os=bsd - ;; - *-encore) - os=bsd - ;; - *-sgi) - os=irix - ;; - *-siemens) - os=sysv4 - ;; - *-masscomp) - os=rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=uxpv - ;; - *-rom68k) - os=coff - ;; - *-*bug) - os=coff - ;; - *-apple) - os=macos - ;; - *-atari*) - os=mint - ;; - *-wrs) - os=vxworks - ;; - *) - os=none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -case $vendor in - unknown) - case $os in - riscix*) - vendor=acorn - ;; - sunos*) - vendor=sun - ;; - cnk*|-aix*) - vendor=ibm - ;; - beos*) - vendor=be - ;; - hpux*) - vendor=hp - ;; - mpeix*) - vendor=hp - ;; - hiux*) - vendor=hitachi - ;; - unos*) - vendor=crds - ;; - dgux*) - vendor=dg - ;; - luna*) - vendor=omron - ;; - genix*) - vendor=ns - ;; - clix*) - vendor=intergraph - ;; - mvs* | opened*) - vendor=ibm - ;; - os400*) - vendor=ibm - ;; - ptx*) - vendor=sequent - ;; - tpf*) - vendor=ibm - ;; - vxsim* | vxworks* | windiss*) - vendor=wrs - ;; - aux*) - vendor=apple - ;; - hms*) - vendor=hitachi - ;; - mpw* | macos*) - vendor=apple - ;; - *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) - vendor=atari - ;; - vos*) - vendor=stratus - ;; - esac - ;; -esac - -echo "$cpu-$vendor-$os" -exit - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/ruby/tool/config.sub b/ruby/tool/config.sub new file mode 120000 index 000000000..3bf705e6a --- /dev/null +++ b/ruby/tool/config.sub @@ -0,0 +1 @@ +../.downloaded-cache/config.sub \ No newline at end of file diff --git a/ruby/tool/disable_ipv6.sh b/ruby/tool/disable_ipv6.sh new file mode 100755 index 000000000..ce1cc0da6 --- /dev/null +++ b/ruby/tool/disable_ipv6.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -ex +sysctl -w net.ipv6.conf.all.disable_ipv6=1 +sysctl -w net.ipv6.conf.default.disable_ipv6=1 +sysctl -w net.ipv6.conf.lo.disable_ipv6=1 + +cat /etc/hosts +ruby -e "hosts = File.read('/etc/hosts').sub(/^::1\s*localhost.*$/, ''); File.write('/etc/hosts', hosts)" +cat /etc/hosts diff --git a/ruby/tool/downloader.rb b/ruby/tool/downloader.rb index 9a89010b0..d3a9f7563 100644 --- a/ruby/tool/downloader.rb +++ b/ruby/tool/downloader.rb @@ -51,7 +51,12 @@ def self.https class GNU < self def self.download(name, *rest) if https? - super("https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/#{name}", name, *rest) + begin + super("https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/#{name}", name, *rest) + rescue => e + STDERR.puts "Download failed (#{e.message}), try another URL" + super("https://raw.githubusercontent.com/gcc-mirror/gcc/master/#{name}", name, *rest) + end else super("https://repo.or.cz/official-gcc.git/blob_plain/HEAD:/#{name}", name, *rest) end @@ -71,7 +76,7 @@ def self.download(name, dir = nil, since = true, options = {}) class Unicode < self INDEX = {} # cache index file information across files in the same directory - UNICODE_PUBLIC = "http://www.unicode.org/Public/" + UNICODE_PUBLIC = "https://www.unicode.org/Public/" def self.download(name, dir = nil, since = true, options = {}) options = options.dup @@ -125,6 +130,21 @@ def self.http_options(file, since) options end + def self.httpdate(date) + Time.httpdate(date) + rescue ArgumentError => e + # Some hosts (e.g., zlib.net) return similar to RFC 850 but 4 + # digit year, sometimes. + /\A\s* + (?:Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day,\x20 + (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{4})\x20 + (\d\d):(\d\d):(\d\d)\x20 + GMT + \s*\z/ix =~ date or raise + warn e.message + Time.utc($3, $2, $1, $4, $5, $6) + end + # Downloader.download(url, name, [dir, [since]]) # # Update a file from url if newer version is available. @@ -191,9 +211,15 @@ def self.download(url, name, dir = nil, since = true, options = {}) $stdout.print "downloading #{name} ... " $stdout.flush end + mtime = nil + options = options.merge(http_options(file, since.nil? ? true : since)) begin - data = with_retry(9) do - url.read(options.merge(http_options(file, since.nil? ? true : since))) + data = with_retry(10) do + data = url.read(options) + if mtime = data.meta["last-modified"] + mtime = Time.httpdate(mtime) + end + data end rescue OpenURI::HTTPError => http_error if http_error.message =~ /^304 / # 304 Not Modified @@ -217,16 +243,13 @@ def self.download(url, name, dir = nil, since = true, options = {}) end raise end - mtime = nil dest = (cache_save && cache && !cache.exist? ? cache : file) dest.parent.mkpath dest.open("wb", 0600) do |f| f.write(data) f.chmod(mode_for(data)) - mtime = data.meta["last-modified"] end if mtime - mtime = Time.httpdate(mtime) dest.utime(mtime, mtime) end if $VERBOSE @@ -308,7 +331,7 @@ def self.with_retry(max_times, &block) times = 0 begin block.call - rescue Errno::ETIMEDOUT, SocketError, OpenURI::HTTPError, Net::ReadTimeout, Net::OpenTimeout => e + rescue Errno::ETIMEDOUT, SocketError, OpenURI::HTTPError, Net::ReadTimeout, Net::OpenTimeout, ArgumentError => e raise if e.is_a?(OpenURI::HTTPError) && e.message !~ /^50[023] / # retry only 500, 502, 503 for http error times += 1 if times <= max_times diff --git a/ruby/tool/dummy-rake-compiler/rake/extensiontask.rb b/ruby/tool/dummy-rake-compiler/rake/extensiontask.rb new file mode 100644 index 000000000..62b7ff801 --- /dev/null +++ b/ruby/tool/dummy-rake-compiler/rake/extensiontask.rb @@ -0,0 +1,9 @@ +module Rake + class ExtensionTask < TaskLib + def initialize(...) + task :compile do + puts "Dummy `compile` task defined in #{__FILE__}" + end + end + end +end diff --git a/ruby/tool/enc-unicode.rb b/ruby/tool/enc-unicode.rb index f64cecb88..93f6e869f 100755 --- a/ruby/tool/enc-unicode.rb +++ b/ruby/tool/enc-unicode.rb @@ -138,7 +138,7 @@ def parse_scripts(data, categories) {:fn => 'DerivedCoreProperties.txt', :title => 'Derived Property'}, {:fn => 'Scripts.txt', :title => 'Script'}, {:fn => 'PropList.txt', :title => 'Binary Property'}, - {:fn => 'emoji-data.txt', :title => 'Emoji'} + {:fn => 'emoji/emoji-data.txt', :title => 'Emoji'} ] current = nil cps = [] @@ -305,13 +305,13 @@ def constantize_blockname(name) end def get_file(name) - File.join(ARGV[name.start_with?("emoji-") ? 1 : 0], name) + File.join(ARGV[name.start_with?("emoji-[stz]") ? 1 : 0], name) end def data_foreach(name, &block) fn = get_file(name) warn "Reading #{name}" - if /^emoji-/ =~ name + if /^emoji/ =~ name sep = "" pat = /^# #{Regexp.quote(File.basename(name))}.*^# Version: ([\d.]+)/m type = :Emoji diff --git a/ruby/tool/extlibs.rb b/ruby/tool/extlibs.rb index f021a2bf0..cd8e5239b 100755 --- a/ruby/tool/extlibs.rb +++ b/ruby/tool/extlibs.rb @@ -7,13 +7,27 @@ require_relative 'downloader' require_relative 'lib/colorize' +class Vars < Hash + def pattern + /\$\((#{Regexp.union(keys)})\)/ + end + + def expand(str) + if empty? + str + else + str.gsub(pattern) {self[$1]} + end + end +end + class ExtLibs def initialize @colorize = Colorize.new end def cache_file(url, cache_dir) - Downloader.cache_file(url, nil, :cache_dir => cache_dir) + Downloader.cache_file(url, nil, cache_dir).to_path end def do_download(url, cache_dir) @@ -76,10 +90,50 @@ def do_patch(dest, patch, args) $stdout.puts "applying #{patch} under #{dest}" $stdout.flush end - Process.wait(Process.spawn("patch", "-d", dest, "-i", patch, *args)) + Process.wait(Process.spawn(ENV.fetch("PATCH", "patch"), "-d", dest, "-i", patch, *args)) $?.success? or raise "failed to patch #{patch}" end + def do_link(file, src, dest) + file = File.join(dest, file) + if (target = src).start_with?("/") + target = File.join([".."] * file.count("/"), src) + end + return unless File.exist?(File.expand_path(target, File.dirname(file))) + File.unlink(file) rescue nil + begin + File.symlink(target, file) + rescue + else + if $VERBOSE + $stdout.puts "linked #{target} to #{file}" + $stdout.flush + end + return + end + begin + src = src.sub(/\A\//, '') + File.copy_stream(src, file) + rescue + if $VERBOSE + $stdout.puts "failed to link #{src} to #{file}: #{$!.message}" + end + else + if $VERBOSE + $stdout.puts "copied #{src} to #{file}" + end + end + end + + def do_exec(command, dir, dest) + dir = dir ? File.join(dest, dir) : dest + if $VERBOSE + $stdout.puts "running #{command.dump} under #{dir}" + $stdout.flush + end + system(command, chdir: dir) or raise "failed #{command.dump}" + end + def do_command(mode, dest, url, cache_dir, chksums) extracted = false base = /.*(?=\.tar(?:\.\w+)?\z)/ @@ -143,19 +197,37 @@ def run(argv) $stdout.puts "downloading for #{list}" $stdout.flush end + vars = Vars.new extracted = false dest = File.dirname(list) url = chksums = nil IO.foreach(list) do |line| line.sub!(/\s*#.*/, '') + if /^(\w+)\s*=\s*(.*)/ =~ line + vars[$1] = vars.expand($2) + next + end if chksums chksums.concat(line.split) elsif /^\t/ =~ line if extracted and (mode == :all or mode == :patch) - patch, *args = line.split + patch, *args = line.split.map {|s| vars.expand(s)} do_patch(dest, patch, args) end next + elsif /^!\s*(?:chdir:\s*([^|\s]+)\|\s*)?(.*)/ =~ line + if extracted and (mode == :all or mode == :patch) + command = vars.expand($2.strip) + chdir = $1 and chdir = vars.expand(chdir) + do_exec(command, chdir, dest) + end + next + elsif /->/ =~ line + if extracted and (mode == :all or mode == :patch) + link, file = $`.strip, $'.strip + do_link(vars.expand(link), vars.expand(file), dest) + end + next else url, *chksums = line.split(' ') end @@ -163,11 +235,15 @@ def run(argv) chksums.pop next end - next unless url + unless url + chksums = nil + next + end + url = vars.expand(url) begin extracted = do_command(mode, dest, url, cache_dir, chksums) rescue => e - warn e.inspect + warn e.full_message success = false end url = chksums = nil diff --git a/ruby/tool/fake.rb b/ruby/tool/fake.rb index 42174052e..47e385511 100644 --- a/ruby/tool/fake.rb +++ b/ruby/tool/fake.rb @@ -24,6 +24,7 @@ class File untrace_var(:$ruby, posthook) end prehook = proc do |extmk| +=begin pat = %r[(?:\A(?:\w:|//[^/]+)|\G)/[^/]*] dir = builddir.scan(pat) pwd = Dir.pwd.scan(pat) @@ -35,6 +36,7 @@ class File builddir = File.join((pwd.empty? ? ["."] : [".."]*pwd.size) + dir) builddir = "." if builddir.empty? end +=end join = proc {|*args| File.join(*args).sub!(/\A(?:\.\/)*/, '')} $topdir ||= builddir $top_srcdir ||= (File.identical?(top_srcdir, dir = join[$topdir, srcdir]) ? diff --git a/ruby/tool/fetch-bundled_gems.rb b/ruby/tool/fetch-bundled_gems.rb index ba16d726f..ebb70e88f 100755 --- a/ruby/tool/fetch-bundled_gems.rb +++ b/ruby/tool/fetch-bundled_gems.rb @@ -8,24 +8,20 @@ Dir.chdir(dir) } -n, v, u = $F -case n -when "minitest" - v = "master" -when "test-unit" -else - v = "v" + v -end +n, v, u, r = $F + +next if n =~ /^#/ if File.directory?(n) puts "updating #{n} ..." - if v == "master" - system(*%W"git pull", chdir: n) or abort - else - system(*%W"git fetch", chdir: n) or abort - end + system("git", "fetch", chdir: n) or abort else puts "retrieving #{n} ..." system(*%W"git clone #{u} #{n}") or abort end -system(*%W"git checkout #{v}", chdir: n) or abort +c = r || "v#{v}" +checkout = %w"git -c advice.detachedHead=false checkout" +puts "checking out #{c} (v=#{v}, r=#{r}) ..." +unless system(*checkout, c, "--", chdir: n) + abort +end diff --git a/ruby/tool/format-release b/ruby/tool/format-release index b34da3509..e0de84112 100755 --- a/ruby/tool/format-release +++ b/ruby/tool/format-release @@ -45,7 +45,7 @@ eom # SHA1: 21f62c369661a2ab1b521fd2fa8191a4273e12a1 # SHA256: 97cea8aa63dfa250ba6902b658a7aa066daf817b22f82b7ee28f44aec7c2e394 # SHA512: 1e2042324821bb4e110af7067f52891606dcfc71e640c194ab1c117f0b941550e0b3ac36ad3511214ac80c536b9e5cfaf8789eec74cf56971a832ea8fc4e6d94 - def self.parse(wwwdir, version) + def self.parse(wwwdir, version, rubydir) unless /\A(\d+)\.(\d+)\.(\d+)(?:-(?:preview|rc)\d+)?\z/ =~ version raise "unexpected version string '#{version}'" end @@ -85,7 +85,7 @@ eom if prev_tag # show diff shortstat tag = "v#{version.gsub(/[.\-]/, '_')}" - stat = `git diff --shortstat #{prev_tag}..#{tag}` + stat = `git -C #{rubydir} diff --shortstat #{prev_tag}..#{tag}` files_changed, insertions, deletions = stat.scan(/\d+/) end @@ -173,10 +173,20 @@ eom - version: #{ver} date: #{date.strftime("%Y-%m-%d")} post: /en/news/#{date.strftime("%Y/%m/%d")}/ruby-#{ver.tr('.', '-')}-released/ +eom + + if /\.0(?:-\w+)?\z/ =~ ver + # preview, rc, or first release + entry <<= < " - exit - end wwwdir = ARGV.shift version = ARGV.shift - Tarball.parse(wwwdir, version) + rubydir = ARGV.shift + unless rubydir + STDERR.puts "usage: format-release " + exit + end + Tarball.parse(wwwdir, version, rubydir) end main diff --git a/ruby/tool/gem-unpack.rb b/ruby/tool/gem-unpack.rb index 0ddcea070..cb0571946 100644 --- a/ruby/tool/gem-unpack.rb +++ b/ruby/tool/gem-unpack.rb @@ -1,3 +1,4 @@ +require 'fileutils' require 'rubygems' require 'rubygems/package' @@ -10,7 +11,7 @@ def Gem.unpack(file, dir = nil) target = spec.full_name target = File.join(dir, target) if dir pkg.extract_files target - spec_file = File.join(target, "#{spec.name}.gemspec") + spec_file = File.join(target, "#{spec.name}-#{spec.version}.gemspec") open(spec_file, 'wb') do |f| f.print spec.to_ruby end diff --git a/ruby/tool/ifchange b/ruby/tool/ifchange index 050c8d8f2..5af41e015 100755 --- a/ruby/tool/ifchange +++ b/ruby/tool/ifchange @@ -3,6 +3,18 @@ # Used in generating revision.h via Makefiles. +help() { + cat <&2 + exit 1 + ;; *) break ;; @@ -41,6 +65,11 @@ until [ $# -eq 0 ]; do shift done +if [ "$#" != 2 ]; then + help + exit 1 +fi + target="$1" temp="$2" if [ "$temp" = - ]; then diff --git a/ruby/tool/intern_ids.rb b/ruby/tool/intern_ids.rb new file mode 100755 index 000000000..20483195e --- /dev/null +++ b/ruby/tool/intern_ids.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby -sp +# $ ruby -i tool/intern_ids.rb -prefix=_ foo.c + +BEGIN { + $prefix ||= nil + + defs = File.join(File.dirname(__dir__), "defs/id.def") + ids = eval(File.read(defs), binding, defs) + table = {} + ids[:predefined].each {|v, t| table[t] = "id#{v}"} + ids[:token_op].each {|v, t, *| table[t] = "id#{v}"} + predefined = table.keys +} + +$_.gsub!(/rb_intern\("([^\"]+)"\)/) do + token = $1 + table[token] ||= "id" + id2varname(token, $prefix) +end + +END { + predefined.each {|t| table.delete(t)} + unless table.empty? + table = table.sort_by {|t, v| v} + + # Append at the last, then edit and move appropriately. + puts + puts "==== defs" + table.each {|t, v| puts "static ID #{v};"} + puts ">>>>" + puts + puts "==== init" + table.each {|t, v|puts "#{v} = rb_intern_const(\"#{t}\");"} + puts ">>>>" + end +} diff --git a/ruby/tool/leaked-globals b/ruby/tool/leaked-globals index ec116211d..d95f3794e 100755 --- a/ruby/tool/leaked-globals +++ b/ruby/tool/leaked-globals @@ -7,6 +7,8 @@ until ARGV.empty? SYMBOL_PREFIX = $1 when /\ANM=(.*)/ # may be multiple words NM = $1 + when /\APLATFORM=(.+)?/ + platform = $1 else break end @@ -16,15 +18,38 @@ end config = ARGV.shift count = 0 col = Colorize.new -REPLACE = File.read(config).scan(/\bAC_(?:REPLACE|CHECK)_FUNCS?\(\K\w+/) +config_code = File.read(config) +REPLACE = config_code.scan(/\bAC_(?:REPLACE|CHECK)_FUNCS?\((\w+)/).flatten +# REPLACE << 'memcmp' if /\bAC_FUNC_MEMCMP\b/ =~ config_code +REPLACE.push('main', 'DllMain') +if platform and !platform.empty? + begin + h = File.read(platform) + rescue Errno::ENOENT + else + REPLACE.concat( + h .gsub(%r[/\*.*?\*/]m, " ") # delete block comments + .gsub(%r[//.*], ' ') # delete oneline comments + .gsub(/^\s*#.*(?:\\\n.*)*/, "") # delete preprocessor directives + .scan(/\b((?!rb_|DEPRECATED|_)\w+)\s*\(.*\);/) + .flatten) + end +end +missing = File.dirname(config) + "/missing/" +ARGV.reject! do |n| + unless (src = Dir.glob(missing + File.basename(n, ".*") + ".[cS]")).empty? + puts "Ignore #{n} because of #{src.map {|s| File.basename(s)}.join(', ')} under missing" + true + end +end print "Checking leaked global symbols..." STDOUT.flush IO.foreach("|#{NM} -Pgp #{ARGV.join(' ')}") do |line| n, t, = line.split - next unless /[BDT]/ =~ t + next unless /[A-TV-Z]/ =~ t next unless n.sub!(/^#{SYMBOL_PREFIX}/o, "") next if n.include?(".") - next if /\A(?:Init_|InitVM_|ruby_|rb_|[Oo]nig|dln_|mjit_|coroutine_|nu(?:comp|rat)_)/ =~ n + next if /\A(?:Init_|InitVM_|RUBY_|ruby_|rb_|[Oo]nig|dln_|mjit_|coroutine_)/ =~ n next if REPLACE.include?(n) puts col.fail("leaked") if count.zero? count += 1 diff --git a/ruby/tool/lib/-test-/integer.rb b/ruby/tool/lib/-test-/integer.rb index a224148f2..e60abf03a 100644 --- a/ruby/tool/lib/-test-/integer.rb +++ b/ruby/tool/lib/-test-/integer.rb @@ -4,11 +4,11 @@ module Test::Unit::Assertions def assert_fixnum(v, msg=nil) assert_instance_of(Integer, v, msg) - assert_predicate(v, :fixnum?, msg) + assert_send([Bug::Integer, :fixnum?, v], msg) end def assert_bignum(v, msg=nil) assert_instance_of(Integer, v, msg) - assert_predicate(v, :bignum?, msg) + assert_send([Bug::Integer, :bignum?, v], msg) end end diff --git a/ruby/tool/lib/colorize.rb b/ruby/tool/lib/colorize.rb index 7494a2198..11b878d31 100644 --- a/ruby/tool/lib/colorize.rb +++ b/ruby/tool/lib/colorize.rb @@ -1,10 +1,14 @@ # frozen-string-literal: true class Colorize + # call-seq: + # Colorize.new(colorize = nil) + # Colorize.new(color: color, colors_file: colors_file) def initialize(color = nil, opts = ((_, color = color, nil)[0] if Hash === color)) @colors = @reset = nil + @color = (opts[:color] if opts) if color or (color == nil && STDOUT.tty?) - if (/\A\e\[.*m\z/ =~ IO.popen("tput smso", "r", :err => IO::NULL, &:read) rescue nil) + if (%w[smso so].any? {|attr| /\A\e\[.*m\z/ =~ IO.popen("tput #{attr}", "r", :err => IO::NULL, &:read)} rescue nil) @beg = "\e[" colors = (colors = ENV['TEST_COLORS']) ? Hash[colors.scan(/(\w+)=([^:\n]*)/)] : {} if opts and colors_file = opts[:colors_file] @@ -29,7 +33,8 @@ def initialize(color = nil, opts = ((_, color = color, nil)[0] if Hash === color "bold"=>"1", "underline"=>"4", "reverse"=>"7", } - def decorate(str, name) + # colorize.decorate(str, name = color_name) + def decorate(str, name = @color) if @colors and color = (@colors[name] || DEFAULTS[name]) "#{@beg}#{color}m#{str}#{@reset}" else @@ -45,7 +50,6 @@ def decorate(str, name) end if $0 == __FILE__ - colorize = Colorize.new - col = ARGV.shift - ARGV.each {|str| puts colorize.decorate(str, col)} + colorize = Colorize.new(ARGV.shift) + ARGV.each {|str| puts colorize.decorate(str)} end diff --git a/ruby/tool/lib/core_assertions.rb b/ruby/tool/lib/core_assertions.rb new file mode 100644 index 000000000..9adc936ad --- /dev/null +++ b/ruby/tool/lib/core_assertions.rb @@ -0,0 +1,751 @@ +# frozen_string_literal: true + +module Test + module Unit + module Assertions + def _assertions= n # :nodoc: + @_assertions = n + end + + def _assertions # :nodoc: + @_assertions ||= 0 + end + + ## + # Returns a proc that will output +msg+ along with the default message. + + def message msg = nil, ending = nil, &default + proc { + ending ||= (ending_pattern = /(? 0 and b > 0 + assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"}) + end + rescue LoadError + pend + end + + # :call-seq: + # assert_nothing_raised( *args, &block ) + # + #If any exceptions are given as arguments, the assertion will + #fail if one of those exceptions are raised. Otherwise, the test fails + #if any exceptions are raised. + # + #The final argument may be a failure message. + # + # assert_nothing_raised RuntimeError do + # raise Exception #Assertion passes, Exception is not a RuntimeError + # end + # + # assert_nothing_raised do + # raise Exception #Assertion fails + # end + def assert_nothing_raised(*args) + self._assertions += 1 + if Module === args.last + msg = nil + else + msg = args.pop + end + begin + yield + rescue Test::Unit::PendedError, *(Test::Unit::AssertionFailedError if args.empty?) + raise + rescue *(args.empty? ? Exception : args) => e + msg = message(msg) { + "Exception raised:\n<#{mu_pp(e)}>\n""Backtrace:\n" << + Test.filter_backtrace(e.backtrace).map{|frame| " #{frame}"}.join("\n") + } + raise Test::Unit::AssertionFailedError, msg.call, e.backtrace + end + end + + def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil) + fname ||= caller_locations(2, 1)[0] + mesg ||= fname.to_s + verbose, $VERBOSE = $VERBOSE, verbose + case + when Array === fname + fname, line = *fname + when defined?(fname.path) && defined?(fname.lineno) + fname, line = fname.path, fname.lineno + else + line = 1 + end + yield(code, fname, line, message(mesg) { + if code.end_with?("\n") + "```\n#{code}```\n" + else + "```\n#{code}\n```\n""no-newline" + end + }) + ensure + $VERBOSE = verbose + end + + def assert_valid_syntax(code, *args, **opt) + prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg| + yield if defined?(yield) + assert_nothing_raised(SyntaxError, mesg) do + assert_equal(:ok, syntax_check(src, fname, line), mesg) + end + end + end + + def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) + assert_valid_syntax(testsrc, caller_locations(1, 1)[0]) + if child_env + child_env = [child_env] + else + child_env = [] + end + out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt) + assert !status.signaled?, FailDesc[status, message, out] + end + + def assert_ruby_status(args, test_stdin="", message=nil, **opt) + out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt) + desc = FailDesc[status, message, out] + assert(!status.signaled?, desc) + message ||= "ruby exit status is not success:" + assert(status.success?, desc) + end + + ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM") + + def separated_runner(token, out = nil) + include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) }) + out = out ? IO.new(out, 'w') : STDOUT + at_exit { + out.puts "#{token}", [Marshal.dump($!)].pack('m'), "#{token}", "#{token}assertions=#{self._assertions}" + } + Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) if defined?(Test::Unit::Runner) + end + + def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt) + unless file and line + loc, = caller_locations(1,1) + file ||= loc.path + line ||= loc.lineno + end + capture_stdout = true + unless /mswin|mingw/ =~ RUBY_PLATFORM + capture_stdout = false + opt[:out] = Test::Unit::Runner.output if defined?(Test::Unit::Runner) + res_p, res_c = IO.pipe + opt[:ios] = [res_c] + end + token_dump, token_re = new_test_token + src = <\n\K.*\n(?=#{token_re}<\/error>$)/m].unpack1("m")) + rescue => marshal_error + ignore_stderr = nil + res = nil + end + if res and !(SystemExit === res) + if bt = res.backtrace + bt.each do |l| + l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"} + end + bt.concat(caller) + else + res.set_backtrace(caller) + end + raise res + end + + # really is it succeed? + unless ignore_stderr + # the body of assert_separately must not output anything to detect error + assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr]) + end + assert(status.success?, FailDesc[status, "assert_separately failed", stderr]) + raise marshal_error if marshal_error + end + + # Run Ractor-related test without influencing the main test suite + def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt) + return unless defined?(Ractor) + + require = "require #{require.inspect}" if require + if require_relative + dir = File.dirname(caller_locations[0,1][0].absolute_path) + full_path = File.expand_path(require_relative, dir) + require = "#{require}; require #{full_path.inspect}" + end + + assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt) + #{require} + previous_verbose = $VERBOSE + $VERBOSE = nil + Ractor.new {} # trigger initial warning + $VERBOSE = previous_verbose + #{src} + RUBY + end + + # :call-seq: + # assert_throw( tag, failure_message = nil, &block ) + # + #Fails unless the given block throws +tag+, returns the caught + #value otherwise. + # + #An optional failure message may be provided as the final argument. + # + # tag = Object.new + # assert_throw(tag, "#{tag} was not thrown!") do + # throw tag + # end + def assert_throw(tag, msg = nil) + ret = catch(tag) do + begin + yield(tag) + rescue UncaughtThrowError => e + thrown = e.tag + end + msg = message(msg) { + "Expected #{mu_pp(tag)} to have been thrown"\ + "#{%Q[, not #{thrown}] if thrown}" + } + assert(false, msg) + end + assert(true) + ret + end + + # :call-seq: + # assert_raise( *args, &block ) + # + #Tests if the given block raises an exception. Acceptable exception + #types may be given as optional arguments. If the last argument is a + #String, it will be used as the error message. + # + # assert_raise do #Fails, no Exceptions are raised + # end + # + # assert_raise NameError do + # puts x #Raises NameError, so assertion succeeds + # end + def assert_raise(*exp, &b) + case exp.last + when String, Proc + msg = exp.pop + end + + begin + yield + rescue Test::Unit::PendedError => e + return e if exp.include? Test::Unit::PendedError + raise e + rescue Exception => e + expected = exp.any? { |ex| + if ex.instance_of? Module then + e.kind_of? ex + else + e.instance_of? ex + end + } + + assert expected, proc { + flunk(message(msg) {"#{mu_pp(exp)} exception expected, not #{mu_pp(e)}"}) + } + + return e + ensure + unless e + exp = exp.first if exp.size == 1 + + flunk(message(msg) {"#{mu_pp(exp)} expected but nothing was raised"}) + end + end + end + + # :call-seq: + # assert_raise_with_message(exception, expected, msg = nil, &block) + # + #Tests if the given block raises an exception with the expected + #message. + # + # assert_raise_with_message(RuntimeError, "foo") do + # nil #Fails, no Exceptions are raised + # end + # + # assert_raise_with_message(RuntimeError, "foo") do + # raise ArgumentError, "foo" #Fails, different Exception is raised + # end + # + # assert_raise_with_message(RuntimeError, "foo") do + # raise "bar" #Fails, RuntimeError is raised but the message differs + # end + # + # assert_raise_with_message(RuntimeError, "foo") do + # raise "foo" #Raises RuntimeError with the message, so assertion succeeds + # end + def assert_raise_with_message(exception, expected, msg = nil, &block) + case expected + when String + assert = :assert_equal + when Regexp + assert = :assert_match + else + raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}" + end + + ex = m = nil + EnvUtil.with_default_internal(expected.encoding) do + ex = assert_raise(exception, msg || proc {"Exception(#{exception}) with message matches to #{expected.inspect}"}) do + yield + end + m = ex.message + end + msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"} + + if assert == :assert_equal + assert_equal(expected, m, msg) + else + msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp m}" } + assert expected =~ m, msg + block.binding.eval("proc{|_|$~=_}").call($~) + end + ex + end + + TEST_DIR = File.join(__dir__, "test/unit") #:nodoc: + + # :call-seq: + # assert(test, [failure_message]) + # + #Tests if +test+ is true. + # + #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used + #as the failure message. Otherwise, the result of calling +msg+ will be + #used as the message if the assertion fails. + # + #If no +msg+ is given, a default message will be used. + # + # assert(false, "This was expected to be true") + def assert(test, *msgs) + case msg = msgs.first + when String, Proc + when nil + msgs.shift + else + bt = caller.reject { |s| s.start_with?(TEST_DIR) } + raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt + end unless msgs.empty? + super + end + + # :call-seq: + # assert_respond_to( object, method, failure_message = nil ) + # + #Tests if the given Object responds to +method+. + # + #An optional failure message may be provided as the final argument. + # + # assert_respond_to("hello", :reverse) #Succeeds + # assert_respond_to("hello", :does_not_exist) #Fails + def assert_respond_to(obj, (meth, *priv), msg = nil) + unless priv.empty? + msg = message(msg) { + "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}" + } + return assert obj.respond_to?(meth, *priv), msg + end + #get rid of overcounting + if caller_locations(1, 1)[0].path.start_with?(TEST_DIR) + return if obj.respond_to?(meth) + end + super(obj, meth, msg) + end + + # :call-seq: + # assert_not_respond_to( object, method, failure_message = nil ) + # + #Tests if the given Object does not respond to +method+. + # + #An optional failure message may be provided as the final argument. + # + # assert_not_respond_to("hello", :reverse) #Fails + # assert_not_respond_to("hello", :does_not_exist) #Succeeds + def assert_not_respond_to(obj, (meth, *priv), msg = nil) + unless priv.empty? + msg = message(msg) { + "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}" + } + return assert !obj.respond_to?(meth, *priv), msg + end + #get rid of overcounting + if caller_locations(1, 1)[0].path.start_with?(TEST_DIR) + return unless obj.respond_to?(meth) + end + refute_respond_to(obj, meth, msg) + end + + # pattern_list is an array which contains regexp and :*. + # :* means any sequence. + # + # pattern_list is anchored. + # Use [:*, regexp, :*] for non-anchored match. + def assert_pattern_list(pattern_list, actual, message=nil) + rest = actual + anchored = true + pattern_list.each_with_index {|pattern, i| + if pattern == :* + anchored = false + else + if anchored + match = /\A#{pattern}/.match(rest) + else + match = pattern.match(rest) + end + unless match + msg = message(msg) { + expect_msg = "Expected #{mu_pp pattern}\n" + if /\n[^\n]/ =~ rest + actual_mesg = +"to match\n" + rest.scan(/.*\n+/) { + actual_mesg << ' ' << $&.inspect << "+\n" + } + actual_mesg.sub!(/\+\n\z/, '') + else + actual_mesg = "to match " + mu_pp(rest) + end + actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters" + expect_msg + actual_mesg + } + assert false, msg + end + rest = match.post_match + anchored = true + end + } + if anchored + assert_equal("", rest) + end + end + + def assert_warning(pat, msg = nil) + result = nil + stderr = EnvUtil.with_default_internal(pat.encoding) { + EnvUtil.verbose_warning { + result = yield + } + } + msg = message(msg) {diff pat, stderr} + assert(pat === stderr, msg) + result + end + + def assert_warn(*args) + assert_warning(*args) {$VERBOSE = false; yield} + end + + def assert_deprecated_warning(mesg = /deprecated/) + assert_warning(mesg) do + Warning[:deprecated] = true + yield + end + end + + def assert_deprecated_warn(mesg = /deprecated/) + assert_warn(mesg) do + Warning[:deprecated] = true + yield + end + end + + class << (AssertFile = Struct.new(:failure_message).new) + include Assertions + include CoreAssertions + def assert_file_predicate(predicate, *args) + if /\Anot_/ =~ predicate + predicate = $' + neg = " not" + end + result = File.__send__(predicate, *args) + result = !result if neg + mesg = "Expected file ".dup << args.shift.inspect + mesg << "#{neg} to be #{predicate}" + mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty? + mesg << " #{failure_message}" if failure_message + assert(result, mesg) + end + alias method_missing assert_file_predicate + + def for(message) + clone.tap {|a| a.failure_message = message} + end + end + + class AllFailures + attr_reader :failures + + def initialize + @count = 0 + @failures = {} + end + + def for(key) + @count += 1 + yield key + rescue Exception => e + @failures[key] = [@count, e] + end + + def foreach(*keys) + keys.each do |key| + @count += 1 + begin + yield key + rescue Exception => e + @failures[key] = [@count, e] + end + end + end + + def message + i = 0 + total = @count.to_s + fmt = "%#{total.size}d" + @failures.map {|k, (n, v)| + v = v.message + "\n#{i+=1}. [#{fmt%n}/#{total}] Assertion for #{k.inspect}\n#{v.b.gsub(/^/, ' | ').force_encoding(v.encoding)}" + }.join("\n") + end + + def pass? + @failures.empty? + end + end + + # threads should respond to shift method. + # Array can be used. + def assert_join_threads(threads, message = nil) + errs = [] + values = [] + while th = threads.shift + begin + values << th.value + rescue Exception + errs << [th, $!] + th = nil + end + end + values + ensure + if th&.alive? + th.raise(Timeout::Error.new) + th.join rescue errs << [th, $!] + end + if !errs.empty? + msg = "exceptions on #{errs.length} threads:\n" + + errs.map {|t, err| + "#{t.inspect}:\n" + + RUBY_VERSION >= "2.5.0" ? err.full_message(highlight: false, order: :top) : err.message + }.join("\n---\n") + if message + msg = "#{message}\n#{msg}" + end + raise Test::Unit::AssertionFailedError, msg + end + end + + def assert_all?(obj, m = nil, &blk) + failed = [] + obj.each do |*a, &b| + unless blk.call(*a, &b) + failed << (a.size > 1 ? a : a[0]) + end + end + assert(failed.empty?, message(m) {failed.pretty_inspect}) + end + + def assert_all_assertions(msg = nil) + all = AllFailures.new + yield all + ensure + assert(all.pass?, message(msg) {all.message.chomp(".")}) + end + alias all_assertions assert_all_assertions + + def assert_all_assertions_foreach(msg = nil, *keys, &block) + all = AllFailures.new + all.foreach(*keys, &block) + ensure + assert(all.pass?, message(msg) {all.message.chomp(".")}) + end + alias all_assertions_foreach assert_all_assertions_foreach + + def diff(exp, act) + require 'pp' + q = PP.new(+"") + q.guard_inspect_key do + q.group(2, "expected: ") do + q.pp exp + end + q.text q.newline + q.group(2, "actual: ") do + q.pp act + end + q.flush + end + q.output + end + + def new_test_token + token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m" + return token.dump, Regexp.quote(token) + end + end + end +end diff --git a/ruby/tool/lib/envutil.rb b/ruby/tool/lib/envutil.rb index 2faf48385..0391b90c1 100644 --- a/ruby/tool/lib/envutil.rb +++ b/ruby/tool/lib/envutil.rb @@ -47,12 +47,13 @@ def rubybin class << self attr_accessor :timeout_scale attr_reader :original_internal_encoding, :original_external_encoding, - :original_verbose + :original_verbose, :original_warning def capture_global_values @original_internal_encoding = Encoding.default_internal @original_external_encoding = Encoding.default_external @original_verbose = $VERBOSE + @original_warning = defined?(Warning.[]) ? %i[deprecated experimental].to_h {|i| [i, Warning[i]]} : nil end end @@ -86,7 +87,20 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) when nil, false pgroup = pid end + + lldb = true if /darwin/ =~ RUBY_PLATFORM + while signal = signals.shift + + if lldb and [:ABRT, :KILL].include?(signal) + lldb = false + # sudo -n: --non-interactive + # lldb -p: attach + # -o: run command + system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit]) + true + end + begin Process.kill signal, pgroup rescue Errno::EINVAL @@ -100,6 +114,8 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) begin Timeout.timeout(reprieve) {Process.wait(pid)} rescue Timeout::Error + else + break end end end @@ -109,7 +125,7 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false, encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error, - stdout_filter: nil, stderr_filter: nil, + stdout_filter: nil, stderr_filter: nil, ios: nil, signal: :TERM, rubybin: EnvUtil.rubybin, precommand: nil, **opt) @@ -125,6 +141,8 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = out_p.set_encoding(encoding) if out_p err_p.set_encoding(encoding) if err_p end + ios.each {|i, o = i|opt[i] = o} if ios + c = "C" child_env = {} LANG_ENVS.each {|lc| child_env[lc] = c} @@ -134,11 +152,14 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = if RUBYLIB and lib = child_env["RUBYLIB"] child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR) end + child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS'] args = [args] if args.kind_of?(String) - pid = spawn(child_env, *precommand, rubybin, *args, **opt) + pid = spawn(child_env, *precommand, rubybin, *args, opt) in_c.close - out_c.close if capture_stdout - err_c.close if capture_stderr && capture_stderr != :merge_to_stdout + out_c&.close + out_c = nil + err_c&.close + err_c = nil if block_given? return yield in_p, out_p, err_p, pid else @@ -180,11 +201,6 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = end module_function :invoke_ruby - alias rubyexec invoke_ruby - class << self - alias rubyexec invoke_ruby - end - def verbose_warning class << (stderr = "".dup) alias write concat @@ -197,6 +213,7 @@ def flush; end ensure stderr, $stderr = $stderr, stderr $VERBOSE = EnvUtil.original_verbose + EnvUtil.original_warning&.each {|i, v| Warning[i] = v} end module_function :verbose_warning @@ -242,7 +259,11 @@ def with_default_internal(enc) def labeled_module(name, &block) Module.new do - singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} + singleton_class.class_eval { + define_method(:to_s) {name} + alias inspect to_s + alias name to_s + } class_eval(&block) if block end end @@ -250,7 +271,11 @@ def labeled_module(name, &block) def labeled_class(name, superclass = Object, &block) Class.new(superclass) do - singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} + singleton_class.class_eval { + define_method(:to_s) {name} + alias inspect to_s + alias name to_s + } class_eval(&block) if block end end diff --git a/ruby/tool/lib/gc_checker.rb b/ruby/tool/lib/gc_checker.rb new file mode 100644 index 000000000..719da8cac --- /dev/null +++ b/ruby/tool/lib/gc_checker.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module GCDisabledChecker + def before_setup + if @__gc_disabled__ = GC.enable # return true if GC is disabled + GC.disable + end + + super + end + + def after_teardown + super + + disabled = GC.enable + GC.disable if @__gc_disabled__ + + if @__gc_disabled__ != disabled + label = { + true => 'disabled', + false => 'enabled', + } + raise "GC was #{label[@__gc_disabled__]}, but is #{label[disabled]} after the test." + end + end +end + +module GCCompactChecker + def after_teardown + super + GC.compact + end +end + +Test::Unit::TestCase.include GCDisabledChecker +Test::Unit::TestCase.include GCCompactChecker if ENV['RUBY_TEST_GC_COMPACT'] diff --git a/ruby/tool/lib/gc_compact_checker.rb b/ruby/tool/lib/gc_compact_checker.rb deleted file mode 100644 index a6ef3d3ce..000000000 --- a/ruby/tool/lib/gc_compact_checker.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -module GCCompactChecker - def after_teardown - super - GC.compact - end -end - -Test::Unit::TestCase.include GCCompactChecker if ENV['RUBY_TEST_GC_COMPACT'] diff --git a/ruby/tool/lib/leakchecker.rb b/ruby/tool/lib/leakchecker.rb index 57e28665d..ed5079694 100644 --- a/ruby/tool/lib/leakchecker.rb +++ b/ruby/tool/lib/leakchecker.rb @@ -1,15 +1,23 @@ # frozen_string_literal: true class LeakChecker + @@try_lsof = nil # not-tried-yet + def initialize @fd_info = find_fds + @@skip = false @tempfile_info = find_tempfiles @thread_info = find_threads @env_info = find_env @encoding_info = find_encodings @old_verbose = $VERBOSE + @old_warning_flags = find_warning_flags end def check(test_name) + if /i386-solaris/ =~ RUBY_PLATFORM && /TestGem/ =~ test_name + GC.verify_internal_consistency + end + leaks = [ check_fd_leak(test_name), check_thread_leak(test_name), @@ -17,6 +25,7 @@ def check(test_name) check_env(test_name), check_encodings(test_name), check_verbose(test_name), + check_warning_flags(test_name), ] GC.start if leaks.any? end @@ -29,19 +38,19 @@ def find_fds if IO.respond_to?(:console) and (m = IO.method(:console)).arity.nonzero? m[:close] end - fd_dir = "/proc/self/fd" - if File.directory?(fd_dir) - fds = Dir.open(fd_dir) {|d| - a = d.grep(/\A\d+\z/, &:to_i) - if d.respond_to? :fileno - a -= [d.fileno] - end - a - } - fds.sort - else - [] + %w"/proc/self/fd /dev/fd".each do |fd_dir| + if File.directory?(fd_dir) + fds = Dir.open(fd_dir) {|d| + a = d.grep(/\A\d+\z/, &:to_i) + if d.respond_to? :fileno + a -= [d.fileno] + end + a + } + return fds.sort + end end + [] end def check_fd_leak(test_name) @@ -55,7 +64,7 @@ def check_fd_leak(test_name) } end fd_leaked = live2 - live1 - if !fd_leaked.empty? + if !@@skip && !fd_leaked.empty? leaked = true h = {} ObjectSpace.each_object(IO) {|io| @@ -68,7 +77,7 @@ def check_fd_leak(test_name) end (h[fd] ||= []) << [io, autoclose, inspect] } - fd_leaked.each {|fd| + fd_leaked.select! {|fd| str = ''.dup pos = nil if h[fd] @@ -83,20 +92,39 @@ def check_fd_leak(test_name) }.sort.each {|s| str << s } + else + begin + io = IO.for_fd(fd, autoclose: false) + s = io.stat + rescue Errno::EBADF + # something un-stat-able + next + else + next if /darwin/ =~ RUBY_PLATFORM and [0, -1].include?(s.dev) + str << ' ' << s.inspect + ensure + io&.close + end end puts "Leaked file descriptor: #{test_name}: #{fd}#{str}" puts " The IO was created at #{pos}" if pos + true } - #system("lsof -p #$$") if !fd_leaked.empty? + unless fd_leaked.empty? + unless @@try_lsof == false + @@try_lsof |= system(*%W[lsof -a -d #{fd_leaked.minmax.uniq.join("-")} -p #$$], out: Test::Unit::Runner.output) + end + end h.each {|fd, list| next if list.length <= 1 if 1 < list.count {|io, autoclose, inspect| autoclose } str = list.map {|io, autoclose, inspect| " #{inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join - puts "Multiple autoclose IO object for a file descriptor:#{str}" + puts "Multiple autoclose IO objects for a file descriptor in: #{test_name}: #{str}" end } end @fd_info = live2 + @@skip = false return leaked end @@ -181,13 +209,28 @@ def check_thread_leak(test_name) return leaked end - def find_env - ENV.to_h + e = ENV["_Ruby_Env_Ignorecase_"], ENV["_RUBY_ENV_IGNORECASE_"] + begin + ENV["_Ruby_Env_Ignorecase_"] = ENV["_RUBY_ENV_IGNORECASE_"] = nil + ENV["_RUBY_ENV_IGNORECASE_"] = "ENV_CASE_TEST" + ENV_IGNORECASE = ENV["_Ruby_Env_Ignorecase_"] == "ENV_CASE_TEST" + ensure + ENV["_Ruby_Env_Ignorecase_"], ENV["_RUBY_ENV_IGNORECASE_"] = e + end + + if ENV_IGNORECASE + def find_env + ENV.to_h {|k, v| [k.upcase, v]} + end + else + def find_env + ENV.to_h + end end def check_env(test_name) old_env = @env_info - new_env = ENV.to_h + new_env = find_env return false if old_env == new_env (old_env.keys | new_env.keys).sort.each {|k| if old_env.has_key?(k) @@ -211,30 +254,61 @@ def check_env(test_name) end def find_encodings - [Encoding.default_internal, Encoding.default_external] + { + 'Encoding.default_internal' => Encoding.default_internal, + 'Encoding.default_external' => Encoding.default_external, + 'STDIN.internal_encoding' => STDIN.internal_encoding, + 'STDIN.external_encoding' => STDIN.external_encoding, + 'STDOUT.internal_encoding' => STDOUT.internal_encoding, + 'STDOUT.external_encoding' => STDOUT.external_encoding, + 'STDERR.internal_encoding' => STDERR.internal_encoding, + 'STDERR.external_encoding' => STDERR.external_encoding, + } end def check_encodings(test_name) - old_internal, old_external = @encoding_info - new_internal, new_external = find_encodings + old_encoding_info = @encoding_info + @encoding_info = find_encodings leaked = false - if new_internal != old_internal - leaked = true - puts "Encoding.default_internal changed: #{test_name} : #{old_internal.inspect} to #{new_internal.inspect}" + @encoding_info.each do |key, new_encoding| + old_encoding = old_encoding_info[key] + if new_encoding != old_encoding + leaked = true + puts "#{key} changed: #{test_name} : #{old_encoding.inspect} to #{new_encoding.inspect}" + end end - if new_external != old_external - leaked = true - puts "Encoding.default_external changed: #{test_name} : #{old_external.inspect} to #{new_external.inspect}" + leaked + end + + WARNING_CATEGORIES = (Warning.respond_to?(:[]) ? %i[deprecated experimental] : []).freeze + + def find_warning_flags + WARNING_CATEGORIES.to_h do |category| + [category, Warning[category]] + end + end + + def check_warning_flags(test_name) + new_warning_flags = find_warning_flags + leaked = false + WARNING_CATEGORIES.each do |category| + if new_warning_flags[category] != @old_warning_flags[category] + leaked = true + puts "Warning[#{category.inspect}] changed: #{test_name} : #{@old_warning_flags[category]} to #{new_warning_flags[category]}" + end end - @encoding_info = [new_internal, new_external] return leaked end def puts(*a) - output = MiniTest::Unit.output + output = Test::Unit::Runner.output if defined?(output.set_encoding) output.set_encoding(nil, nil) end output.puts(*a) end + + def self.skip + @@skip = true + end end diff --git a/ruby/tool/lib/memory_status.rb b/ruby/tool/lib/memory_status.rb index ad002b2dd..5e9e80a68 100644 --- a/ruby/tool/lib/memory_status.rb +++ b/ruby/tool/lib/memory_status.rb @@ -56,11 +56,12 @@ def memory_info end end - keys << :peak << :size + keys.push(:size, :rss, :peak) def self.read_status if info = Win32.memory_info - yield :peak, info.PeakPagefileUsage yield :size, info.PagefileUsage + yield :rss, info.WorkingSetSize + yield :peak, info.PeakWorkingSetSize end end when (require_relative 'find_executable' @@ -94,6 +95,7 @@ def _update Memory.read_status do |key, val| self[key] = val end + self end unless method_defined?(:_update) Header = members.map {|k| k.to_s.upcase.rjust(6)}.join('') diff --git a/ruby/tool/lib/minitest/README.txt b/ruby/tool/lib/minitest/README.txt deleted file mode 100644 index 368cc3aa4..000000000 --- a/ruby/tool/lib/minitest/README.txt +++ /dev/null @@ -1,457 +0,0 @@ -= minitest/{unit,spec,mock,benchmark} - -home :: https://github.com/seattlerb/minitest -rdoc :: http://docs.seattlerb.org/minitest -vim :: https://github.com/sunaku/vim-ruby-minitest - -== DESCRIPTION: - -minitest provides a complete suite of testing facilities supporting -TDD, BDD, mocking, and benchmarking. - - "I had a class with Jim Weirich on testing last week and we were - allowed to choose our testing frameworks. Kirk Haines and I were - paired up and we cracked open the code for a few test - frameworks... - - I MUST say that minitest is *very* readable / understandable - compared to the 'other two' options we looked at. Nicely done and - thank you for helping us keep our mental sanity." - - -- Wayne E. Seguin - -minitest/unit is a small and incredibly fast unit testing framework. -It provides a rich set of assertions to make your tests clean and -readable. - -minitest/spec is a functionally complete spec engine. It hooks onto -minitest/unit and seamlessly bridges test assertions over to spec -expectations. - -minitest/benchmark is an awesome way to assert the performance of your -algorithms in a repeatable manner. Now you can assert that your newb -co-worker doesn't replace your linear algorithm with an exponential -one! - -minitest/mock by Steven Baker, is a beautifully tiny mock (and stub) -object framework. - -minitest/pride shows pride in testing and adds coloring to your test -output. I guess it is an example of how to write IO pipes too. :P - -minitest/unit is meant to have a clean implementation for language -implementors that need a minimal set of methods to bootstrap a working -test suite. For example, there is no magic involved for test-case -discovery. - - "Again, I can't praise enough the idea of a testing/specing - framework that I can actually read in full in one sitting!" - - -- Piotr Szotkowski - -Comparing to rspec: - - rspec is a testing DSL. minitest is ruby. - - -- Adam Hawkins, "Bow Before MiniTest" - -minitest doesn't reinvent anything that ruby already provides, like: -classes, modules, inheritance, methods. This means you only have to -learn ruby to use minitest and all of your regular OO practices like -extract-method refactorings still apply. - -== FEATURES/PROBLEMS: - -* minitest/autorun - the easy and explicit way to run all your tests. -* minitest/unit - a very fast, simple, and clean test system. -* minitest/spec - a very fast, simple, and clean spec system. -* minitest/mock - a simple and clean mock/stub system. -* minitest/benchmark - an awesome way to assert your algorithm's performance. -* minitest/pride - show your pride in testing! -* Incredibly small and fast runner, but no bells and whistles. - -== RATIONALE: - -See design_rationale.rb to see how specs and tests work in minitest. - -== SYNOPSIS: - -Given that you'd like to test the following class: - - class Meme - def i_can_has_cheezburger? - "OHAI!" - end - - def will_it_blend? - "YES!" - end - end - -=== Unit tests - - require 'minitest/autorun' - - class TestMeme < MiniTest::Unit::TestCase - def setup - @meme = Meme.new - end - - def test_that_kitty_can_eat - assert_equal "OHAI!", @meme.i_can_has_cheezburger? - end - - def test_that_it_will_not_blend - refute_match /^no/i, @meme.will_it_blend? - end - - def test_that_will_be_skipped - skip "test this later" - end - end - -=== Specs - - require 'minitest/autorun' - - describe Meme do - before do - @meme = Meme.new - end - - describe "when asked about cheeseburgers" do - it "must respond positively" do - @meme.i_can_has_cheezburger?.must_equal "OHAI!" - end - end - - describe "when asked about blending possibilities" do - it "won't say no" do - @meme.will_it_blend?.wont_match /^no/i - end - end - end - -For matchers support check out: - -https://github.com/zenspider/minitest-matchers - -=== Benchmarks - -Add benchmarks to your regular unit tests. If the unit tests fail, the -benchmarks won't run. - - # optionally run benchmarks, good for CI-only work! - require 'minitest/benchmark' if ENV["BENCH"] - - class TestMeme < MiniTest::Unit::TestCase - # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000] - def bench_my_algorithm - assert_performance_linear 0.9999 do |n| # n is a range value - @obj.my_algorithm(n) - end - end - end - -Or add them to your specs. If you make benchmarks optional, you'll -need to wrap your benchmarks in a conditional since the methods won't -be defined. - - describe Meme do - if ENV["BENCH"] then - bench_performance_linear "my_algorithm", 0.9999 do |n| - 100.times do - @obj.my_algorithm(n) - end - end - end - end - -outputs something like: - - # Running benchmarks: - - TestBlah 100 1000 10000 - bench_my_algorithm 0.006167 0.079279 0.786993 - bench_other_algorithm 0.061679 0.792797 7.869932 - -Output is tab-delimited to make it easy to paste into a spreadsheet. - -=== Mocks - - class MemeAsker - def initialize(meme) - @meme = meme - end - - def ask(question) - method = question.tr(" ","_") + "?" - @meme.__send__(method) - end - end - - require 'minitest/autorun' - - describe MemeAsker do - before do - @meme = MiniTest::Mock.new - @meme_asker = MemeAsker.new @meme - end - - describe "#ask" do - describe "when passed an unpunctuated question" do - it "should invoke the appropriate predicate method on the meme" do - @meme.expect :will_it_blend?, :return_value - @meme_asker.ask "will it blend" - @meme.verify - end - end - end - end - -=== Stubs - - def test_stale_eh - obj_under_test = Something.new - - refute obj_under_test.stale? - - Time.stub :now, Time.at(0) do # stub goes away once the block is done - assert obj_under_test.stale? - end - end - -A note on stubbing: In order to stub a method, the method must -actually exist prior to stubbing. Use a singleton method to create a -new non-existing method: - - def obj_under_test.fake_method - ... - end - -=== Customizable Test Runner Types: - -MiniTest::Unit.runner=(runner) provides an easy way of creating custom -test runners for specialized needs. Justin Weiss provides the -following real-world example to create an alternative to regular -fixture loading: - - class MiniTestWithHooks::Unit < MiniTest::Unit - def before_suites - end - - def after_suites - end - - def _run_suites(suites, type) - begin - before_suites - super(suites, type) - ensure - after_suites - end - end - - def _run_suite(suite, type) - begin - suite.before_suite - super(suite, type) - ensure - suite.after_suite - end - end - end - - module MiniTestWithTransactions - class Unit < MiniTestWithHooks::Unit - include TestSetupHelper - - def before_suites - super - setup_nested_transactions - # load any data we want available for all tests - end - - def after_suites - teardown_nested_transactions - super - end - end - end - - MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new - -== FAQ - -=== How to test SimpleDelegates? - -The following implementation and test: - - class Worker < SimpleDelegator - def work - end - end - - describe Worker do - before do - @worker = Worker.new(Object.new) - end - - it "must respond to work" do - @worker.must_respond_to :work - end - end - -outputs a failure: - - 1) Failure: - Worker#test_0001_must respond to work [bug11.rb:16]: - Expected # (Object) to respond to #work. - -Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. -Expectations are put on Object (one level down) so the Worker -(SimpleDelegate) hits `method_missing` and delegates down to the -`Object.new` instance. That object doesn't respond to work so the test -fails. - -You can bypass `SimpleDelegate#method_missing` by extending the worker -with `MiniTest::Expectations`. You can either do that in your setup at -the instance level, like: - - before do - @worker = Worker.new(Object.new) - @worker.extend MiniTest::Expectations - end - -or you can extend the Worker class (within the test file!), like: - - class Worker - include ::MiniTest::Expectations - end - -== Known Extensions: - -capybara_minitest_spec :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')). -minispec-metadata :: Metadata for describe/it blocks - (e.g. `it 'requires JS driver', js: true do`) -minitest-ansi :: Colorize minitest output with ANSI colors. -minitest-around :: Around block for minitest. An alternative to setup/teardown dance. -minitest-capistrano :: Assertions and expectations for testing Capistrano recipes -minitest-capybara :: Capybara matchers support for minitest unit and spec -minitest-chef-handler :: Run Minitest suites as Chef report handlers -minitest-ci :: CI reporter plugin for MiniTest. -minitest-colorize :: Colorize MiniTest output and show failing tests instantly. -minitest-context :: Defines contexts for code reuse in MiniTest - specs that share common expectations. -minitest-debugger :: Wraps assert so failed assertions drop into - the ruby debugger. -minitest-display :: Patches MiniTest to allow for an easily configurable output. -minitest-emoji :: Print out emoji for your test passes, fails, and skips. -minitest-english :: Semantically symmetric aliases for assertions and expectations. -minitest-excludes :: Clean API for excluding certain tests you - don't want to run under certain conditions. -minitest-firemock :: Makes your MiniTest mocks more resilient. -minitest-great_expectations :: Generally useful additions to minitest's assertions and expectations -minitest-growl :: Test notifier for minitest via growl. -minitest-implicit-subject :: Implicit declaration of the test subject. -minitest-instrument :: Instrument ActiveSupport::Notifications when - test method is executed -minitest-instrument-db :: Store information about speed of test - execution provided by minitest-instrument in database -minitest-libnotify :: Test notifier for minitest via libnotify. -minitest-macruby :: Provides extensions to minitest for macruby UI testing. -minitest-matchers :: Adds support for RSpec-style matchers to minitest. -minitest-metadata :: Annotate tests with metadata (key-value). -minitest-mongoid :: Mongoid assertion matchers for MiniTest -minitest-must_not :: Provides must_not as an alias for wont in MiniTest -minitest-nc :: Test notifier for minitest via Mountain Lion's Notification Center -minitest-predicates :: Adds support for .predicate? methods -minitest-rails :: MiniTest integration for Rails 3.x -minitest-rails-capybara :: Capybara integration for MiniTest::Rails -minitest-reporters :: Create customizable MiniTest output formats -minitest-should_syntax :: RSpec-style +x.should == y+ assertions for MiniTest -minitest-shouldify :: Adding all manner of shoulds to MiniTest (bad idea) -minitest-spec-context :: Provides rspec-ish context method to MiniTest::Spec -minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond -minitest-spec-rails :: Drop in MiniTest::Spec superclass for ActiveSupport::TestCase. -minitest-stub-const :: Stub constants for the duration of a block -minitest-tags :: add tags for minitest -minitest-wscolor :: Yet another test colorizer. -minitest_owrapper :: Get tests results as a TestResult object. -minitest_should :: Shoulda style syntax for minitest test::unit. -minitest_tu_shim :: minitest_tu_shim bridges between test/unit and minitest. -mongoid-minitest :: MiniTest matchers for Mongoid. -pry-rescue :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb. - -== Unknown Extensions: - -Authors... Please send me a pull request with a description of your minitest extension. - -* assay-minitest -* detroit-minitest -* em-minitest-spec -* flexmock-minitest -* guard-minitest -* guard-minitest-decisiv -* minitest-activemodel -* minitest-ar-assertions -* minitest-capybara-unit -* minitest-colorer -* minitest-deluxe -* minitest-extra-assertions -* minitest-rails-shoulda -* minitest-spec -* minitest-spec-should -* minitest-sugar -* minitest_should -* mongoid-minitest -* spork-minitest - -== REQUIREMENTS: - -* Ruby 1.8, maybe even 1.6 or lower. No magic is involved. - -== INSTALL: - - sudo gem install minitest - -On 1.9, you already have it. To get newer candy you can still install -the gem, but you'll need to activate the gem explicitly to use it: - - require 'rubygems' - gem 'minitest' # ensures you're using the gem, and not the built in MT - require 'minitest/autorun' - - # ... usual testing stuffs ... - -DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 -packages their own gems. They install a gem specification file, but -don't install the gem contents in the gem path. This messes up -Gem.find_files and many other things (gem which, gem contents, etc). - -Just install minitest as a gem for real and you'll be happier. - -== LICENSE: - -(The MIT License) - -Copyright (c) Ryan Davis, seattle.rb - -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. diff --git a/ruby/tool/lib/minitest/autorun.rb b/ruby/tool/lib/minitest/autorun.rb deleted file mode 100644 index 844096623..000000000 --- a/ruby/tool/lib/minitest/autorun.rb +++ /dev/null @@ -1,14 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: true - -begin - require 'rubygems' - gem 'minitest' -rescue Gem::LoadError - # do nothing -end - -require 'minitest/unit' -require 'minitest/mock' - -MiniTest::Unit.autorun diff --git a/ruby/tool/lib/minitest/benchmark.rb b/ruby/tool/lib/minitest/benchmark.rb deleted file mode 100644 index b3f2bc28b..000000000 --- a/ruby/tool/lib/minitest/benchmark.rb +++ /dev/null @@ -1,418 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: true - -require 'minitest/unit' - -class MiniTest::Unit # :nodoc: - def run_benchmarks # :nodoc: - _run_anything :benchmark - end - - def benchmark_suite_header suite # :nodoc: - "\n#{suite}\t#{suite.bench_range.join("\t")}" - end - - class TestCase - ## - # Returns a set of ranges stepped exponentially from +min+ to - # +max+ by powers of +base+. Eg: - # - # bench_exp(2, 16, 2) # => [2, 4, 8, 16] - - def self.bench_exp min, max, base = 10 - min = (Math.log10(min) / Math.log10(base)).to_i - max = (Math.log10(max) / Math.log10(base)).to_i - - (min..max).map { |m| base ** m }.to_a - end - - ## - # Returns a set of ranges stepped linearly from +min+ to +max+ by - # +step+. Eg: - # - # bench_linear(20, 40, 10) # => [20, 30, 40] - - def self.bench_linear min, max, step = 10 - (min..max).step(step).to_a - rescue LocalJumpError # 1.8.6 - r = []; (min..max).step(step) { |n| r << n }; r - end - - ## - # Returns the benchmark methods (methods that start with bench_) - # for that class. - - def self.benchmark_methods # :nodoc: - public_instance_methods(true).grep(/^bench_/).map { |m| m.to_s }.sort - end - - ## - # Returns all test suites that have benchmark methods. - - def self.benchmark_suites - TestCase.test_suites.reject { |s| s.benchmark_methods.empty? } - end - - ## - # Specifies the ranges used for benchmarking for that class. - # Defaults to exponential growth from 1 to 10k by powers of 10. - # Override if you need different ranges for your benchmarks. - # - # See also: ::bench_exp and ::bench_linear. - - def self.bench_range - bench_exp 1, 10_000 - end - - ## - # Runs the given +work+, gathering the times of each run. Range - # and times are then passed to a given +validation+ proc. Outputs - # the benchmark name and times in tab-separated format, making it - # easy to paste into a spreadsheet for graphing or further - # analysis. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # validation = proc { |x, y| ... } - # assert_performance validation do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance validation, &work - range = self.class.bench_range - - io.print "#{__name__}" - - times = [] - - range.each do |x| - GC.start - t0 = Time.now - instance_exec(x, &work) - t = Time.now - t0 - - io.print "\t%9.6f" % t - times << t - end - io.puts - - validation[range, times] - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a constant rate (eg, linear slope == 0) within a given - # +threshold+. Note: because we're testing for a slope of 0, R^2 - # is not a good determining factor for the fit, so the threshold - # is applied against the slope itself. As such, you probably want - # to tighten it from the default. - # - # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for - # more details. - # - # Fit is calculated by #fit_linear. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_constant 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_constant threshold = 0.99, &work - validation = proc do |range, times| - a, b, rr = fit_linear range, times - assert_in_delta 0, b, 1 - threshold - [a, b, rr] - end - - assert_performance validation, &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a exponential curve within a given error +threshold+. - # - # Fit is calculated by #fit_exponential. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_exponential 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_exponential threshold = 0.99, &work - assert_performance validation_for_fit(:exponential, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a logarithmic curve within a given error +threshold+. - # - # Fit is calculated by #fit_logarithmic. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_logarithmic 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_logarithmic threshold = 0.99, &work - assert_performance validation_for_fit(:logarithmic, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered fit to - # match a straight line within a given error +threshold+. - # - # Fit is calculated by #fit_linear. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_linear 0.9999 do |n| - # @obj.algorithm(n) - # end - # end - - def assert_performance_linear threshold = 0.99, &work - assert_performance validation_for_fit(:linear, threshold), &work - end - - ## - # Runs the given +work+ and asserts that the times gathered curve - # fit to match a power curve within a given error +threshold+. - # - # Fit is calculated by #fit_power. - # - # Ranges are specified by ::bench_range. - # - # Eg: - # - # def bench_algorithm - # assert_performance_power 0.9999 do |x| - # @obj.algorithm - # end - # end - - def assert_performance_power threshold = 0.99, &work - assert_performance validation_for_fit(:power, threshold), &work - end - - ## - # Takes an array of x/y pairs and calculates the general R^2 value. - # - # See: http://en.wikipedia.org/wiki/Coefficient_of_determination - - def fit_error xys - y_bar = sigma(xys) { |x, y| y } / xys.size.to_f - ss_tot = sigma(xys) { |x, y| (y - y_bar) ** 2 } - ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } - - 1 - (ss_err / ss_tot) - end - - ## - # To fit a functional form: y = ae^(bx). - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html - - def fit_exponential xs, ys - n = xs.size - xys = xs.zip(ys) - sxlny = sigma(xys) { |x,y| x * Math.log(y) } - slny = sigma(xys) { |x,y| Math.log(y) } - sx2 = sigma(xys) { |x,y| x * x } - sx = sigma xs - - c = n * sx2 - sx ** 2 - a = (slny * sx2 - sx * sxlny) / c - b = ( n * sxlny - sx * slny ) / c - - return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } - end - - ## - # To fit a functional form: y = a + b*ln(x). - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html - - def fit_logarithmic xs, ys - n = xs.size - xys = xs.zip(ys) - slnx2 = sigma(xys) { |x,y| Math.log(x) ** 2 } - slnx = sigma(xys) { |x,y| Math.log(x) } - sylnx = sigma(xys) { |x,y| y * Math.log(x) } - sy = sigma(xys) { |x,y| y } - - c = n * slnx2 - slnx ** 2 - b = ( n * sylnx - sy * slnx ) / c - a = (sy - b * slnx) / n - - return a, b, fit_error(xys) { |x| a + b * Math.log(x) } - end - - - ## - # Fits the functional form: a + bx. - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFitting.html - - def fit_linear xs, ys - n = xs.size - xys = xs.zip(ys) - sx = sigma xs - sy = sigma ys - sx2 = sigma(xs) { |x| x ** 2 } - sxy = sigma(xys) { |x,y| x * y } - - c = n * sx2 - sx**2 - a = (sy * sx2 - sx * sxy) / c - b = ( n * sxy - sx * sy ) / c - - return a, b, fit_error(xys) { |x| a + b * x } - end - - ## - # To fit a functional form: y = ax^b. - # - # Takes x and y values and returns [a, b, r^2]. - # - # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html - - def fit_power xs, ys - n = xs.size - xys = xs.zip(ys) - slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } - slnx = sigma(xs) { |x | Math.log(x) } - slny = sigma(ys) { | y| Math.log(y) } - slnx2 = sigma(xs) { |x | Math.log(x) ** 2 } - - b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2); - a = (slny - b * slnx) / n - - return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } - end - - ## - # Enumerates over +enum+ mapping +block+ if given, returning the - # sum of the result. Eg: - # - # sigma([1, 2, 3]) # => 1 + 2 + 3 => 7 - # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14 - - def sigma enum, &block - enum = enum.map(&block) if block - enum.inject { |sum, n| sum + n } - end - - ## - # Returns a proc that calls the specified fit method and asserts - # that the error is within a tolerable threshold. - - def validation_for_fit msg, threshold - proc do |range, times| - a, b, rr = send "fit_#{msg}", range, times - assert_operator rr, :>=, threshold - [a, b, rr] - end - end - end -end - -class MiniTest::Spec - ## - # This is used to define a new benchmark method. You usually don't - # use this directly and is intended for those needing to write new - # performance curve fits (eg: you need a specific polynomial fit). - # - # See ::bench_performance_linear for an example of how to use this. - - def self.bench name, &block - define_method "bench_#{name.gsub(/\W+/, '_')}", &block - end - - ## - # Specifies the ranges used for benchmarking for that class. - # - # bench_range do - # bench_exp(2, 16, 2) - # end - # - # See Unit::TestCase.bench_range for more details. - - def self.bench_range &block - return super unless block - - meta = (class << self; self; end) - meta.send :define_method, "bench_range", &block - end - - ## - # Create a benchmark that verifies that the performance is linear. - # - # describe "my class" do - # bench_performance_linear "fast_algorithm", 0.9999 do |n| - # @obj.fast_algorithm(n) - # end - # end - - def self.bench_performance_linear name, threshold = 0.99, &work - bench name do - assert_performance_linear threshold, &work - end - end - - ## - # Create a benchmark that verifies that the performance is constant. - # - # describe "my class" do - # bench_performance_constant "zoom_algorithm!" do |n| - # @obj.zoom_algorithm!(n) - # end - # end - - def self.bench_performance_constant name, threshold = 0.99, &work - bench name do - assert_performance_constant threshold, &work - end - end - - ## - # Create a benchmark that verifies that the performance is exponential. - # - # describe "my class" do - # bench_performance_exponential "algorithm" do |n| - # @obj.algorithm(n) - # end - # end - - def self.bench_performance_exponential name, threshold = 0.99, &work - bench name do - assert_performance_exponential threshold, &work - end - end -end diff --git a/ruby/tool/lib/minitest/mock.rb b/ruby/tool/lib/minitest/mock.rb deleted file mode 100644 index 224b06cb8..000000000 --- a/ruby/tool/lib/minitest/mock.rb +++ /dev/null @@ -1,196 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: true - -class MockExpectationError < StandardError; end # :nodoc: - -## -# A simple and clean mock object framework. - -module MiniTest # :nodoc: - - ## - # All mock objects are an instance of Mock - - class Mock - alias :__respond_to? :respond_to? - - skip_methods = %w(object_id respond_to_missing? inspect === to_s) - - instance_methods.each do |m| - undef_method m unless skip_methods.include?(m.to_s) || m =~ /^__/ - end - - def initialize # :nodoc: - @expected_calls = Hash.new { |calls, name| calls[name] = [] } - @actual_calls = Hash.new { |calls, name| calls[name] = [] } - end - - ## - # Expect that method +name+ is called, optionally with +args+ or a - # +blk+, and returns +retval+. - # - # @mock.expect(:meaning_of_life, 42) - # @mock.meaning_of_life # => 42 - # - # @mock.expect(:do_something_with, true, [some_obj, true]) - # @mock.do_something_with(some_obj, true) # => true - # - # @mock.expect(:do_something_else, true) do |a1, a2| - # a1 == "buggs" && a2 == :bunny - # end - # - # +args+ is compared to the expected args using case equality (ie, the - # '===' operator), allowing for less specific expectations. - # - # @mock.expect(:uses_any_string, true, [String]) - # @mock.uses_any_string("foo") # => true - # @mock.verify # => true - # - # @mock.expect(:uses_one_string, true, ["foo"] - # @mock.uses_one_string("bar") # => true - # @mock.verify # => raises MockExpectationError - - def expect(name, retval, args=[], &blk) - if block_given? - raise ArgumentError, "args ignored when block given" unless args.empty? - @expected_calls[name] << { :retval => retval, :block => blk } - else - raise ArgumentError, "args must be an array" unless Array === args - @expected_calls[name] << { :retval => retval, :args => args } - end - self - end - - def __call name, data # :nodoc: - case data - when Hash then - "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}" - else - data.map { |d| __call name, d }.join ", " - end - end - - ## - # Verify that all methods were called as expected. Raises - # +MockExpectationError+ if the mock object was not called as - # expected. - - def verify - @expected_calls.each do |name, calls| - calls.each do |expected| - msg1 = "expected #{__call name, expected}" - msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]" - - raise MockExpectationError, msg2 if - @actual_calls.has_key?(name) and - not @actual_calls[name].include?(expected) - - raise MockExpectationError, msg1 unless - @actual_calls.has_key?(name) and - @actual_calls[name].include?(expected) - end - end - true - end - - def method_missing(sym, *args) # :nodoc: - unless @expected_calls.has_key?(sym) then - raise NoMethodError, "unmocked method %p, expected one of %p" % - [sym, @expected_calls.keys.sort_by(&:to_s)] - end - - index = @actual_calls[sym].length - expected_call = @expected_calls[sym][index] - - unless expected_call then - raise MockExpectationError, "No more expects available for %p: %p" % - [sym, args] - end - - expected_args, retval, val_block = - expected_call.values_at(:args, :retval, :block) - - if val_block then - raise MockExpectationError, "mocked method %p failed block w/ %p" % - [sym, args] unless val_block.call(args) - - # keep "verify" happy - @actual_calls[sym] << expected_call - return retval - end - - if expected_args.size != args.size then - raise ArgumentError, "mocked method %p expects %d arguments, got %d" % - [sym, expected_args.size, args.size] - end - - fully_matched = expected_args.zip(args).all? { |mod, a| - mod === a or mod == a - } - - unless fully_matched then - raise MockExpectationError, "mocked method %p called with unexpected arguments %p" % - [sym, args] - end - - @actual_calls[sym] << { - :retval => retval, - :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a } - } - - retval - end - - def respond_to?(sym, include_private = false) # :nodoc: - return true if @expected_calls.has_key?(sym.to_sym) - return __respond_to?(sym, include_private) - end - end -end - -class Object # :nodoc: - - ## - # Add a temporary stubbed method replacing +name+ for the duration - # of the +block+. If +val_or_callable+ responds to #call, then it - # returns the result of calling it, otherwise returns the value - # as-is. Cleans up the stub at the end of the +block+. The method - # +name+ must exist before stubbing. - # - # def test_stale_eh - # obj_under_test = Something.new - # refute obj_under_test.stale? - # - # Time.stub :now, Time.at(0) do - # assert obj_under_test.stale? - # end - # end - - def stub name, val_or_callable, &block - new_name = "__minitest_stub__#{name}" - - metaclass = class << self; self; end - - if respond_to? name and not methods.map(&:to_s).include? name.to_s then - metaclass.send :define_method, name do |*args| - super(*args) - end - end - - metaclass.send :alias_method, new_name, name - - metaclass.send :define_method, name do |*args| - if val_or_callable.respond_to? :call then - val_or_callable.call(*args) - else - val_or_callable - end - end - - yield self - ensure - metaclass.send :undef_method, name - metaclass.send :alias_method, name, new_name - metaclass.send :undef_method, new_name - end -end diff --git a/ruby/tool/lib/minitest/unit.rb b/ruby/tool/lib/minitest/unit.rb deleted file mode 100644 index 8ac0f146b..000000000 --- a/ruby/tool/lib/minitest/unit.rb +++ /dev/null @@ -1,1434 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: true - -require "optparse" -require "rbconfig" -require "leakchecker" - -## -# Minimal (mostly drop-in) replacement for test-unit. -# -# :include: README.txt - -module MiniTest - - def self.const_missing name # :nodoc: - case name - when :MINI_DIR then - msg = "MiniTest::MINI_DIR was removed. Don't violate other's internals." - warn "WAR\NING: #{msg}" - warn "WAR\NING: Used by #{caller.first}." - const_set :MINI_DIR, "bad value" - else - super - end - end - - ## - # Assertion base class - - class Assertion < Exception; end - - ## - # Assertion raised when skipping a test - - class Skip < Assertion; end - - class << self - ## - # Filter object for backtraces. - - attr_accessor :backtrace_filter - end - - class BacktraceFilter # :nodoc: - def filter bt - return ["No backtrace"] unless bt - - new_bt = [] - - unless $DEBUG then - bt.each do |line| - break if line =~ /lib\/minitest/ - new_bt << line - end - - new_bt = bt.reject { |line| line =~ /lib\/minitest/ } if new_bt.empty? - new_bt = bt.dup if new_bt.empty? - else - new_bt = bt.dup - end - - new_bt - end - end - - self.backtrace_filter = BacktraceFilter.new - - def self.filter_backtrace bt # :nodoc: - backtrace_filter.filter bt - end - - ## - # MiniTest Assertions. All assertion methods accept a +msg+ which is - # printed if the assertion fails. - - module Assertions - ## - # Returns the diff command to use in #diff. Tries to intelligently - # figure out what diff to use. - - def self.diff - unless defined? @diff - exe = RbConfig::CONFIG['EXEEXT'] - @diff = %W"gdiff#{exe} diff#{exe}".find do |diff| - if system(diff, "-u", __FILE__, __FILE__) - break "#{diff} -u" - end - end - end - - @diff - end - - ## - # Set the diff command to use in #diff. - - def self.diff= o - @diff = o - end - - ## - # Returns a diff between +exp+ and +act+. If there is no known - # diff command or if it doesn't make sense to diff the output - # (single line, short output), then it simply returns a basic - # comparison between the two. - - def diff exp, act - require "tempfile" - - expect = mu_pp_for_diff exp - butwas = mu_pp_for_diff act - result = nil - - need_to_diff = - MiniTest::Assertions.diff && - (expect.include?("\n") || - butwas.include?("\n") || - expect.size > 30 || - butwas.size > 30 || - expect == butwas) - - return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless - need_to_diff - - tempfile_a = nil - tempfile_b = nil - - Tempfile.open("expect") do |a| - tempfile_a = a - a.puts expect - a.flush - - Tempfile.open("butwas") do |b| - tempfile_b = b - b.puts butwas - b.flush - - result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}` - result.sub!(/^\-\-\- .+/, "--- expected") - result.sub!(/^\+\+\+ .+/, "+++ actual") - - if result.empty? then - klass = exp.class - result = [ - "No visible difference in the #{klass}#inspect output.\n", - "You should look at the implementation of #== on ", - "#{klass} or its members.\n", - expect, - ].join - end - end - end - - result - ensure - tempfile_a.close! if tempfile_a - tempfile_b.close! if tempfile_b - end - - ## - # This returns a human-readable version of +obj+. By default - # #inspect is called. You can override this to use #pretty_print - # if you want. - - def mu_pp obj - s = obj.inspect - s = s.encode Encoding.default_external if defined? Encoding - s - end - - ## - # This returns a diff-able human-readable version of +obj+. This - # differs from the regular mu_pp because it expands escaped - # newlines and makes hex-values generic (like object_ids). This - # uses mu_pp to do the first pass and then cleans it up. - - def mu_pp_for_diff obj - mu_pp(obj).gsub(/(?exp == act printing the difference between - # the two, if possible. - # - # If there is no visible difference but the assertion fails, you - # should suspect that your #== is buggy, or your inspect output is - # missing crucial details. - # - # For floats use assert_in_delta. - # - # See also: MiniTest::Assertions.diff - - def assert_equal exp, act, msg = nil - msg = message(msg, "") { diff exp, act } - assert exp == act, msg - end - - ## - # For comparing Floats. Fails unless +exp+ and +act+ are within +delta+ - # of each other. - # - # assert_in_delta Math::PI, (22.0 / 7.0), 0.01 - - def assert_in_delta exp, act, delta = 0.001, msg = nil - n = (exp - act).abs - msg = message(msg) { - "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}" - } - assert delta >= n, msg - end - - ## - # For comparing Floats. Fails unless +exp+ and +act+ have a relative - # error less than +epsilon+. - - def assert_in_epsilon a, b, epsilon = 0.001, msg = nil - assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg - end - - ## - # Fails unless +collection+ includes +obj+. - - def assert_includes collection, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" - } - assert_respond_to collection, :include? - assert collection.include?(obj), msg - end - - ## - # Fails unless +obj+ is an instance of +cls+. - - def assert_instance_of cls, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" - } - - assert obj.instance_of?(cls), msg - end - - ## - # Fails unless +obj+ is a kind of +cls+. - - def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of - msg = message(msg) { - "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" } - - assert obj.kind_of?(cls), msg - end - - ## - # Fails unless +matcher+ =~ +obj+. - - def assert_match matcher, obj, msg = nil - msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } - assert_respond_to matcher, :"=~" - matcher = Regexp.new Regexp.escape matcher if String === matcher - assert matcher =~ obj, msg - end - - ## - # Fails unless +obj+ is nil - - def assert_nil obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" } - assert obj.nil?, msg - end - - ## - # For testing with binary operators. - # - # assert_operator 5, :<=, 4 - - def assert_operator o1, op, o2 = (predicate = true; nil), msg = nil - return assert_predicate o1, op, msg if predicate - msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" } - assert o1.__send__(op, o2), msg - end - - ## - # Fails if stdout or stderr do not output the expected results. - # Pass in nil if you don't care about that streams output. Pass in - # "" if you require it to be silent. Pass in a regexp if you want - # to pattern match. - # - # NOTE: this uses #capture_io, not #capture_subprocess_io. - # - # See also: #assert_silent - - def assert_output stdout = nil, stderr = nil - out, err = capture_io do - yield - end - - err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr - out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout - - y = send err_msg, stderr, err, "In stderr" if err_msg - x = send out_msg, stdout, out, "In stdout" if out_msg - - (!stdout || x) && (!stderr || y) - end - - ## - # For testing with predicates. - # - # assert_predicate str, :empty? - # - # This is really meant for specs and is front-ended by assert_operator: - # - # str.must_be :empty? - - def assert_predicate o1, op, msg = nil - msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" } - assert o1.__send__(op), msg - end - - ## - # Fails unless the block raises one of +exp+. Returns the - # exception matched so you can check the message, attributes, etc. - - def assert_raises *exp - msg = "#{exp.pop}.\n" if String === exp.last - - begin - yield - rescue MiniTest::Skip => e - return e if exp.include? MiniTest::Skip - raise e - rescue Exception => e - expected = exp.any? { |ex| - if ex.instance_of? Module then - e.kind_of? ex - else - e.instance_of? ex - end - } - - assert expected, proc { - exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not") - } - - return e - end - - exp = exp.first if exp.size == 1 - - flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." - end - - ## - # Fails unless +obj+ responds to +meth+. - - def assert_respond_to obj, meth, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" - } - assert obj.respond_to?(meth), msg - end - - ## - # Fails unless +exp+ and +act+ are #equal? - - def assert_same exp, act, msg = nil - msg = message(msg) { - data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] - "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data - } - assert exp.equal?(act), msg - end - - ## - # +send_ary+ is a receiver, message and arguments. - # - # Fails unless the call returns a true value - # TODO: I should prolly remove this from specs - - def assert_send send_ary, m = nil - recv, msg, *args = send_ary - m = message(m) { - "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" } - assert recv.__send__(msg, *args), m - end - - ## - # Fails if the block outputs anything to stderr or stdout. - # - # See also: #assert_output - - def assert_silent - assert_output "", "" do - yield - end - end - - ## - # Fails unless the block throws +sym+ - - def assert_throws sym, msg = nil - default = "Expected #{mu_pp(sym)} to have been thrown" - caught = true - catch(sym) do - begin - yield - rescue ThreadError => e # wtf?!? 1.8 + threads == suck - default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" - rescue ArgumentError => e # 1.9 exception - default += ", not #{e.message.split(/ /).last}" - rescue NameError => e # 1.8 exception - default += ", not #{e.name.inspect}" - end - caught = false - end - - assert caught, message(msg) { default } - end - - ## - # Captures $stdout and $stderr into strings: - # - # out, err = capture_io do - # puts "Some info" - # warn "You did a bad thing" - # end - # - # assert_match %r%info%, out - # assert_match %r%bad%, err - # - # NOTE: For efficiency, this method uses StringIO and does not - # capture IO for subprocesses. Use #capture_subprocess_io for - # that. - - def capture_io - require 'stringio' - - captured_stdout, captured_stderr = StringIO.new, StringIO.new - - synchronize do - orig_stdout, orig_stderr = $stdout, $stderr - $stdout, $stderr = captured_stdout, captured_stderr - - begin - yield - ensure - $stdout = orig_stdout - $stderr = orig_stderr - end - end - - return captured_stdout.string, captured_stderr.string - end - alias capture_output capture_io - - ## - # Captures $stdout and $stderr into strings, using Tempfile to - # ensure that subprocess IO is captured as well. - # - # out, err = capture_subprocess_io do - # system "echo Some info" - # system "echo You did a bad thing 1>&2" - # end - # - # assert_match %r%info%, out - # assert_match %r%bad%, err - # - # NOTE: This method is approximately 10x slower than #capture_io so - # only use it when you need to test the output of a subprocess. - - def capture_subprocess_io - require 'tempfile' - - captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") - - synchronize do - orig_stdout, orig_stderr = $stdout.dup, $stderr.dup - $stdout.reopen captured_stdout - $stderr.reopen captured_stderr - - begin - yield - - $stdout.rewind - $stderr.rewind - - [captured_stdout.read, captured_stderr.read] - ensure - $stdout.reopen orig_stdout - $stderr.reopen orig_stderr - orig_stdout.close - orig_stderr.close - captured_stdout.close! - captured_stderr.close! - end - end - end - - ## - # Returns details for exception +e+ - - def exception_details e, msg - [ - "#{msg}", - "Class: <#{e.class}>", - "Message: <#{e.message.inspect}>", - "---Backtrace---", - "#{MiniTest::filter_backtrace(e.backtrace).join("\n")}", - "---------------", - ].join "\n" - end - - ## - # Fails with +msg+ - - def flunk msg = nil - msg ||= "Epic Fail!" - assert false, msg - end - - ## - # Returns a proc that will output +msg+ along with the default message. - - def message msg = nil, ending = ".", &default - proc { - msg = msg.call.chomp(".") if Proc === msg - custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? - "#{custom_message}#{default.call}#{ending}" - } - end - - ## - # used for counting assertions - - def pass msg = nil - assert true - end - - ## - # Fails if +test+ is a true value - - def refute test, msg = nil - msg ||= "Failed refutation, no message given" - not assert(! test, msg) - end - - ## - # Fails if +obj+ is empty. - - def refute_empty obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" } - assert_respond_to obj, :empty? - refute obj.empty?, msg - end - - ## - # Fails if exp == act. - # - # For floats use refute_in_delta. - - def refute_equal exp, act, msg = nil - msg = message(msg) { - "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" - } - refute exp == act, msg - end - - ## - # For comparing Floats. Fails if +exp+ is within +delta+ of +act+. - # - # refute_in_delta Math::PI, (22.0 / 7.0) - - def refute_in_delta exp, act, delta = 0.001, msg = nil - n = (exp - act).abs - msg = message(msg) { - "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}" - } - refute delta >= n, msg - end - - ## - # For comparing Floats. Fails if +exp+ and +act+ have a relative error - # less than +epsilon+. - - def refute_in_epsilon a, b, epsilon = 0.001, msg = nil - refute_in_delta a, b, a * epsilon, msg - end - - ## - # Fails if +collection+ includes +obj+. - - def refute_includes collection, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" - } - assert_respond_to collection, :include? - refute collection.include?(obj), msg - end - - ## - # Fails if +obj+ is an instance of +cls+. - - def refute_instance_of cls, obj, msg = nil - msg = message(msg) { - "Expected #{mu_pp(obj)} to not be an instance of #{cls}" - } - refute obj.instance_of?(cls), msg - end - - ## - # Fails if +obj+ is a kind of +cls+. - - def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of - msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } - refute obj.kind_of?(cls), msg - end - - ## - # Fails if +matcher+ =~ +obj+. - - def refute_match matcher, obj, msg = nil - msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"} - assert_respond_to matcher, :"=~" - matcher = Regexp.new Regexp.escape matcher if String === matcher - refute matcher =~ obj, msg - end - - ## - # Fails if +obj+ is nil. - - def refute_nil obj, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" } - refute obj.nil?, msg - end - - ## - # Fails if +o1+ is not +op+ +o2+. Eg: - # - # refute_operator 1, :>, 2 #=> pass - # refute_operator 1, :<, 2 #=> fail - - def refute_operator o1, op, o2 = (predicate = true; nil), msg = nil - return refute_predicate o1, op, msg if predicate - msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"} - refute o1.__send__(op, o2), msg - end - - ## - # For testing with predicates. - # - # refute_predicate str, :empty? - # - # This is really meant for specs and is front-ended by refute_operator: - # - # str.wont_be :empty? - - def refute_predicate o1, op, msg = nil - msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" } - refute o1.__send__(op), msg - end - - ## - # Fails if +obj+ responds to the message +meth+. - - def refute_respond_to obj, meth, msg = nil - msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" } - - refute obj.respond_to?(meth), msg - end - - ## - # Fails if +exp+ is the same (by object identity) as +act+. - - def refute_same exp, act, msg = nil - msg = message(msg) { - data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] - "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data - } - refute exp.equal?(act), msg - end - - ## - # Skips the current test. Gets listed at the end of the run but - # doesn't cause a failure exit code. - - def skip msg = nil, bt = caller - msg ||= "Skipped, no message given" - @skip = true - raise MiniTest::Skip, msg, bt - end - - alias omit skip - - ## - # Was this testcase skipped? Meant for #teardown. - - def skipped? - defined?(@skip) and @skip - end - - ## - # Takes a block and wraps it with the runner's shared mutex. - - def synchronize - Minitest::Unit.runner.synchronize do - yield - end - end - end - - class Unit # :nodoc: - VERSION = "4.7.5" # :nodoc: - - attr_accessor :report, :failures, :errors, :skips # :nodoc: - attr_accessor :assertion_count # :nodoc: - attr_writer :test_count # :nodoc: - attr_accessor :start_time # :nodoc: - attr_accessor :help # :nodoc: - attr_accessor :verbose # :nodoc: - attr_writer :options # :nodoc: - - ## - # :attr: - # - # if true, installs an "INFO" signal handler (only available to BSD and - # OS X users) which prints diagnostic information about the test run. - # - # This is auto-detected by default but may be overridden by custom - # runners. - - attr_accessor :info_signal - - ## - # Lazy accessor for options. - - def options - @options ||= {} - end - - @@installed_at_exit ||= false - @@out = $stdout - @@after_tests = [] - - ## - # A simple hook allowing you to run a block of code after _all_ of - # the tests are done. Eg: - # - # MiniTest::Unit.after_tests { p $debugging_info } - - def self.after_tests &block - @@after_tests << block - end - - ## - # Registers MiniTest::Unit to run tests at process exit - - def self.autorun - at_exit { - # don't run if there was a non-exit exception - next if $! and not $!.kind_of? SystemExit - - # the order here is important. The at_exit handler must be - # installed before anyone else gets a chance to install their - # own, that way we can be assured that our exit will be last - # to run (at_exit stacks). - exit_code = nil - - at_exit { - @@after_tests.reverse_each(&:call) - exit false if exit_code && exit_code != 0 - } - - exit_code = MiniTest::Unit.new.run ARGV - } unless @@installed_at_exit - @@installed_at_exit = true - end - - ## - # Returns the stream to use for output. - - def self.output - @@out - end - - ## - # Sets MiniTest::Unit to write output to +stream+. $stdout is the default - # output - - def self.output= stream - @@out = stream - end - - ## - # Tells MiniTest::Unit to delegate to +runner+, an instance of a - # MiniTest::Unit subclass, when MiniTest::Unit#run is called. - - def self.runner= runner - @@runner = runner - end - - ## - # Returns the MiniTest::Unit subclass instance that will be used - # to run the tests. A MiniTest::Unit instance is the default - # runner. - - def self.runner - @@runner ||= self.new - end - - ## - # Return all plugins' run methods (methods that start with "run_"). - - def self.plugins - @@plugins ||= (["run_tests"] + - public_instance_methods(false). - grep(/^run_/).map { |s| s.to_s }).uniq - end - - ## - # Return the IO for output. - - def output - self.class.output - end - - def puts *a # :nodoc: - output.puts(*a) - end - - def print *a # :nodoc: - output.print(*a) - end - - def test_count # :nodoc: - @test_count ||= 0 - end - - ## - # Runner for a given +type+ (eg, test vs bench). - - def _run_anything type - suites = TestCase.send "#{type}_suites" - return if suites.empty? - - puts - puts "# Running #{type}s:" - puts - - @test_count, @assertion_count = 0, 0 - test_count = assertion_count = 0 - sync = output.respond_to? :"sync=" # stupid emacs - old_sync, output.sync = output.sync, true if sync - - count = 0 - begin - start = Time.now - - results = _run_suites suites, type - - @test_count = results.inject(0) { |sum, (tc, _)| sum + tc } - @assertion_count = results.inject(0) { |sum, (_, ac)| sum + ac } - test_count += @test_count - assertion_count += @assertion_count - t = Time.now - start - count += 1 - unless @repeat_count - puts - puts - end - puts "Finished%s %ss in %.6fs, %.4f tests/s, %.4f assertions/s.\n" % - [(@repeat_count ? "(#{count}/#{@repeat_count}) " : ""), type, - t, @test_count.fdiv(t), @assertion_count.fdiv(t)] - end while @repeat_count && count < @repeat_count && - report.empty? && failures.zero? && errors.zero? - - output.sync = old_sync if sync - - report.each_with_index do |msg, i| - puts "\n%3d) %s" % [i + 1, msg] - end - - puts - @test_count = test_count - @assertion_count = assertion_count - - status - end - - ## - # Runs all the +suites+ for a given +type+. - # - - def _run_suites suites, type - suites.map { |suite| _run_suite suite, type } - end - - ## - # Run a single +suite+ for a given +type+. - - def _run_suite suite, type - header = "#{type}_suite_header" - puts send(header, suite) if respond_to? header - - filter = options[:filter] || '/./' - filter = Regexp.new $1 if filter =~ /\/(.*)\// - - all_test_methods = suite.send "#{type}_methods" - - filtered_test_methods = all_test_methods.find_all { |m| - filter === m || filter === "#{suite}##{m}" - } - - leakchecker = LeakChecker.new - - continuation = proc do - assertions = filtered_test_methods.map { |method| - inst = suite.new method - inst._assertions = 0 - - print "#{suite}##{method} = " if @verbose - - start_time = Time.now if @verbose - result = inst.run self - - print "%.2f s = " % (Time.now - start_time) if @verbose - print result - puts if @verbose - $stdout.flush - - unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # compiler process is wrongly considered as leak - leakchecker.check("#{inst.class}\##{inst.__name__}") - end - - inst._assertions - } - return assertions.size, assertions.inject(0) { |sum, n| sum + n } - end - - if ENV["LEAK_CHECKER_TRACE_OBJECT_ALLOCATION"] - require "objspace" - ObjectSpace.trace_object_allocations(&continuation) - else - continuation.call - end - end - - ## - # Record the result of a single test. Makes it very easy to gather - # information. Eg: - # - # class StatisticsRecorder < MiniTest::Unit - # def record suite, method, assertions, time, error - # # ... record the results somewhere ... - # end - # end - # - # MiniTest::Unit.runner = StatisticsRecorder.new - # - # NOTE: record might be sent more than once per test. It will be - # sent once with the results from the test itself. If there is a - # failure or error in teardown, it will be sent again with the - # error or failure. - - def record suite, method, assertions, time, error - end - - def location e # :nodoc: - last_before_assertion = "" - - return '' unless e.backtrace # SystemStackError can return nil. - - e.backtrace.reverse_each do |s| - break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/ - last_before_assertion = s - end - last_before_assertion.sub(/:in .*$/, '') - end - - ## - # Writes status for failed test +meth+ in +klass+ which finished with - # exception +e+ - - def puke klass, meth, e - e = case e - when MiniTest::Skip then - @skips += 1 - return "S" unless @verbose - "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" - when MiniTest::Assertion then - @failures += 1 - "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" - else - @errors += 1 - bt = MiniTest::filter_backtrace(e.backtrace).join "\n " - "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message.b}\n #{bt}\n" - end - @report << e - e[0, 1] - end - - def initialize # :nodoc: - @report = [] - @errors = @failures = @skips = 0 - @verbose = false - @mutex = Thread::Mutex.new - @info_signal = Signal.list['INFO'] - @repeat_count = nil - end - - def synchronize # :nodoc: - if @mutex then - @mutex.synchronize { yield } - else - yield - end - end - - def process_args args = [] # :nodoc: - options = {} - orig_args = args.dup - - OptionParser.new do |opts| - opts.banner = 'minitest options:' - opts.version = MiniTest::Unit::VERSION - - opts.on '-h', '--help', 'Display this help.' do - puts opts - exit - end - - opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m| - options[:seed] = m.to_i - end - - opts.on '-v', '--verbose', "Verbose. Show progress processing files." do - options[:verbose] = true - end - - opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a| - options[:filter] = a - end - - opts.parse! args - orig_args -= args - end - - unless options[:seed] then - srand - options[:seed] = srand % 0xFFFF - orig_args << "--seed" << options[:seed].to_s - end - - srand options[:seed] - - self.verbose = options[:verbose] - @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " " - - options - end - - ## - # Begins the full test run. Delegates to +runner+'s #_run method. - - def run args = [] - self.class.runner._run(args) - end - - ## - # Top level driver, controls all output and filtering. - - def _run args = [] - args = process_args args # ARGH!! blame test/unit process_args - self.options.merge! args - - puts "Run options: #{help}" - - self.class.plugins.each do |plugin| - send plugin - break unless report.empty? - end - - return failures + errors if self.test_count > 0 # or return nil... - rescue Interrupt - abort 'Interrupted' - end - - ## - # Runs test suites matching +filter+. - - def run_tests - _run_anything :test - end - - ## - # Writes status to +io+ - - def status io = self.output - format = "%d tests, %d assertions, %d failures, %d errors, %d skips" - io.puts format % [test_count, assertion_count, failures, errors, skips] - end - - ## - # Provides a simple set of guards that you can use in your tests - # to skip execution if it is not applicable. These methods are - # mixed into TestCase as both instance and class methods so you - # can use them inside or outside of the test methods. - # - # def test_something_for_mri - # skip "bug 1234" if jruby? - # # ... - # end - # - # if windows? then - # # ... lots of test methods ... - # end - - module Guard - - ## - # Is this running on jruby? - - def jruby? platform = RUBY_PLATFORM - "java" == platform - end - - ## - # Is this running on mri? - - def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE - "maglev" == platform - end - - module_function :maglev? - - ## - # Is this running on mri? - - def mri? platform = RUBY_DESCRIPTION - /^ruby/ =~ platform - end - - ## - # Is this running on rubinius? - - def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE - "rbx" == platform - end - - ## - # Is this running on windows? - - def windows? platform = RUBY_PLATFORM - /mswin|mingw/ =~ platform - end - - ## - # Is this running on mingw? - - def mingw? platform = RUBY_PLATFORM - /mingw/ =~ platform - end - - end - - ## - # Provides before/after hooks for setup and teardown. These are - # meant for library writers, NOT for regular test authors. See - # #before_setup for an example. - - module LifecycleHooks - ## - # Runs before every test, after setup. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def after_setup; end - - ## - # Runs before every test, before setup. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # As a simplistic example: - # - # module MyMinitestPlugin - # def before_setup - # super - # # ... stuff to do before setup is run - # end - # - # def after_setup - # # ... stuff to do after setup is run - # super - # end - # - # def before_teardown - # super - # # ... stuff to do before teardown is run - # end - # - # def after_teardown - # # ... stuff to do after teardown is run - # super - # end - # end - # - # class MiniTest::Unit::TestCase - # include MyMinitestPlugin - # end - - def before_setup; end - - ## - # Runs after every test, before teardown. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def before_teardown; end - - ## - # Runs after every test, after teardown. This hook is meant for - # libraries to extend minitest. It is not meant to be used by - # test developers. - # - # See #before_setup for an example. - - def after_teardown; end - end - - ## - # Subclass TestCase to create your own tests. Typically you'll want a - # TestCase subclass per implementation class. - # - # See MiniTest::Assertions - - class TestCase - include LifecycleHooks - include Guard - extend Guard - - attr_reader :__name__ # :nodoc: - - PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, - Interrupt, SystemExit] # :nodoc: - - ## - # Runs the tests reporting the status to +runner+ - - def run runner - trap "INFO" do - runner.report.each_with_index do |msg, i| - warn "\n%3d) %s" % [i + 1, msg] - end - warn '' - time = runner.start_time ? Time.now - runner.start_time : 0 - warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time] - runner.status $stderr - end if runner.info_signal - - start_time = Time.now - - result = "" - begin - @passed = nil - self.before_setup - self.setup - self.after_setup - self.run_test self.__name__ - result = "." unless io? - time = Time.now - start_time - runner.record self.class, self.__name__, self._assertions, time, nil - @passed = true - rescue *PASSTHROUGH_EXCEPTIONS - raise - rescue Exception => e - @passed = Skip === e - time = Time.now - start_time - runner.record self.class, self.__name__, self._assertions, time, e - result = runner.puke self.class, self.__name__, e - ensure - %w{ before_teardown teardown after_teardown }.each do |hook| - begin - self.send hook - rescue *PASSTHROUGH_EXCEPTIONS - raise - rescue Exception => e - @passed = false - runner.record self.class, self.__name__, self._assertions, time, e - result = runner.puke self.class, self.__name__, e - end - end - trap 'INFO', 'DEFAULT' if runner.info_signal - end - result - end - - alias :run_test :__send__ - - def initialize name # :nodoc: - @__name__ = name - @__io__ = nil - @passed = nil - @@current = self # FIX: make thread local - end - - def self.current # :nodoc: - @@current # FIX: make thread local - end - - ## - # Return the output IO object - - def io - @__io__ = true - MiniTest::Unit.output - end - - ## - # Have we hooked up the IO yet? - - def io? - @__io__ - end - - def self.reset # :nodoc: - @@test_suites = {} - end - - reset - - ## - # Make diffs for this TestCase use #pretty_inspect so that diff - # in assert_equal can be more details. NOTE: this is much slower - # than the regular inspect but much more usable for complex - # objects. - - def self.make_my_diffs_pretty! - require 'pp' - - define_method :mu_pp do |o| - o.pretty_inspect - end - end - - def self.inherited klass # :nodoc: - @@test_suites[klass] = true - super - end - - def self.test_order # :nodoc: - :random - end - - def self.test_suites # :nodoc: - @@test_suites.keys.sort_by { |ts| ts.name.to_s } - end - - def self.test_methods # :nodoc: - methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s } - - case self.test_order - when :parallel - max = methods.size - ParallelEach.new methods.sort.sort_by { rand max } - when :random then - max = methods.size - methods.sort.sort_by { rand max } - when :alpha, :sorted then - methods.sort - else - raise "Unknown test_order: #{self.test_order.inspect}" - end - end - - ## - # Returns true if the test passed. - - def passed? - @passed - end - - ## - # Runs before every test. Use this to set up before each test - # run. - - def setup; end - - ## - # Runs after every test. Use this to clean up after each test - # run. - - def teardown; end - - include MiniTest::Assertions - end # class TestCase - end # class Unit - - Test = Unit::TestCase -end # module MiniTest - -Minitest = MiniTest # :nodoc: because ugh... I typo this all the time diff --git a/ruby/tool/lib/profile_test_all.rb b/ruby/tool/lib/profile_test_all.rb index 2c360d76d..fb434e314 100644 --- a/ruby/tool/lib/profile_test_all.rb +++ b/ruby/tool/lib/profile_test_all.rb @@ -20,7 +20,7 @@ require 'objspace' -class MiniTest::Unit::TestCase +class Test::Unit::TestCase alias orig_run run file = ENV['RUBY_TEST_ALL_PROFILE'] diff --git a/ruby/tool/lib/test/unit.rb b/ruby/tool/lib/test/unit.rb index 42d1d8344..3bb2692b4 100644 --- a/ruby/tool/lib/test/unit.rb +++ b/ruby/tool/lib/test/unit.rb @@ -1,26 +1,146 @@ # frozen_string_literal: true -begin - gem 'minitest', '< 5.0.0' if defined? Gem -rescue Gem::LoadError -end -require 'minitest/unit' -require 'test/unit/assertions' + require_relative '../envutil' require_relative '../colorize' -require 'test/unit/testcase' +require_relative '../leakchecker' +require_relative '../test/unit/testcase' require 'optparse' # See Test::Unit module Test + + class << self + ## + # Filter object for backtraces. + + attr_accessor :backtrace_filter + end + + class BacktraceFilter # :nodoc: + def filter bt + return ["No backtrace"] unless bt + + new_bt = [] + pattern = %r[/(?:lib\/test/|core_assertions\.rb:)] + + unless $DEBUG then + bt.each do |line| + break if pattern.match?(line) + new_bt << line + end + + new_bt = bt.reject { |line| pattern.match?(line) } if new_bt.empty? + new_bt = bt.dup if new_bt.empty? + else + new_bt = bt.dup + end + + new_bt + end + end + + self.backtrace_filter = BacktraceFilter.new + + def self.filter_backtrace bt # :nodoc: + backtrace_filter.filter bt + end + ## # Test::Unit is an implementation of the xUnit testing framework for Ruby. - # - # If you are writing new test code, please use MiniTest instead of Test::Unit. - # - # Test::Unit has been left in the standard library to support legacy test - # suites. module Unit - TEST_UNIT_IMPLEMENTATION = 'test/unit compatibility layer using minitest' # :nodoc: + ## + # Assertion base class + + class AssertionFailedError < Exception; end + + ## + # Assertion raised when skipping a test + + class PendedError < AssertionFailedError; end + + module Order + class NoSort + def initialize(seed) + end + + def sort_by_name(list) + list + end + + alias sort_by_string sort_by_name + + def group(list) + list + end + end + + module JITFirst + def group(list) + # JIT first + jit, others = list.partition {|e| /test_jit/ =~ e} + jit + others + end + end + + class Alpha < NoSort + include JITFirst + + def sort_by_name(list) + list.sort_by(&:name) + end + + def sort_by_string(list) + list.sort + end + + end + + # shuffle test suites based on CRC32 of their names + Shuffle = Struct.new(:seed, :salt) do + include JITFirst + + def initialize(seed) + self.class::CRC_TBL ||= (0..255).map {|i| + (0..7).inject(i) {|c,| (c & 1 == 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1) } + }.freeze + + salt = [seed].pack("V").unpack1("H*") + super(seed, "\n#{salt}".freeze).freeze + end + + def sort_by_name(list) + list.sort_by {|e| randomize_key(e.name)} + end + + def sort_by_string(list) + list.sort_by {|e| randomize_key(e)} + end + + private + + def crc32(str, crc32 = 0xffffffff) + crc_tbl = self.class::CRC_TBL + str.each_byte do |data| + crc32 = crc_tbl[(crc32 ^ data) & 0xff] ^ (crc32 >> 8) + end + crc32 + end + + def randomize_key(name) + crc32(salt, crc32(name)) ^ 0xffffffff + end + end + + Types = { + random: Shuffle, + alpha: Alpha, + sorted: Alpha, + nosort: NoSort, + } + Types.default_proc = proc {|_, order| + raise "Unknown test_order: #{order.inspect}" + } + end module RunCount # :nodoc: all @@run_count = 0 @@ -64,14 +184,27 @@ def process_args(args = []) args = @init_hook.call(args, options) if @init_hook non_options(args, options) @run_options = orig_args - @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " " + + order = options[:test_order] + if seed = options[:seed] + order ||= :random + elsif (order ||= :random) == :random + seed = options[:seed] = rand(0x10000) + orig_args.unshift "--seed=#{seed}" + end + Test::Unit::TestCase.test_order = order if order + order = Test::Unit::TestCase.test_order + @order = Test::Unit::Order::Types[order].new(seed) + + @help = "\n" + orig_args.map { |s| + " " + (s =~ /[\s|&<>$()]/ ? s.inspect : s) + }.join("\n") @options = options end private def setup_options(opts, options) - opts.separator 'minitest options:' - opts.version = MiniTest::Unit::VERSION + opts.separator 'test-unit options:' opts.on '-h', '--help', 'Display this help.' do puts opts @@ -79,7 +212,7 @@ def setup_options(opts, options) end opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m| - options[:seed] = m + options[:seed] = m.to_i end opts.on '-v', '--verbose', "Verbose. Show progress processing files." do @@ -91,8 +224,9 @@ def setup_options(opts, options) (options[:filter] ||= []) << a end - opts.on '--test-order=random|alpha|sorted', [:random, :alpha, :sorted] do |a| - MiniTest::Unit::TestCase.test_order = a + orders = Test::Unit::Order::Types.keys + opts.on "--test-order=#{orders.join('|')}", orders do |a| + options[:test_order] = a end end @@ -106,6 +240,9 @@ def non_options(files, options) filter = nil elsif negative.empty? and positive.size == 1 and pos_pat !~ positive[0] filter = positive[0] + unless /\A[A-Z]\w*(?:::[A-Z]\w*)*#/ =~ filter + filter = /##{Regexp.quote(filter)}\z/ + end else filter = Regexp.union(*positive.map! {|s| Regexp.new(s[pos_pat, 1] || "\\A#{Regexp.quote(s)}\\z")}) end @@ -113,12 +250,6 @@ def non_options(files, options) negative = Regexp.union(*negative.map! {|s| Regexp.new(s[neg_pat, 1])}) filter = /\A(?=.*#{filter})(?!.*#{negative})/ end - if Regexp === filter - # bypass conversion in minitest - def filter.=~(other) # :nodoc: - super unless Regexp === other - end - end options[:filter] = filter end true @@ -153,6 +284,7 @@ def non_options(files, options) options[:parallel] ||= 1 end end + @worker_timeout = EnvUtil.apply_timeout_scale(options[:worker_timeout] || 180) super end @@ -175,6 +307,10 @@ def setup_options(opts, options) options[:parallel] = a.to_i end + opts.on '--worker-timeout=N', Integer, "Timeout workers not responding in N seconds" do |a| + options[:worker_timeout] = a + end + opts.on '--separate', "Restart job process after one testcase has done" do options[:parallel] ||= 1 options[:separate] = true @@ -191,21 +327,31 @@ def setup_options(opts, options) opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a| options[:ruby] = a.split(/ /).reject(&:empty?) end + + opts.on '--timetable-data=FILE', "Path to timetable data" do |a| + options[:timetable_data] = a + end end class Worker def self.launch(ruby,args=[]) scale = EnvUtil.timeout_scale io = IO.popen([*ruby, "-W1", - "#{File.dirname(__FILE__)}/unit/parallel.rb", + "#{__dir__}/unit/parallel.rb", *("--timeout-scale=#{scale}" if scale), *args], "rb+") new(io, io.pid, :waiting) end attr_reader :quit_called + attr_accessor :start_time + attr_accessor :response_at + attr_accessor :current + + @@worker_number = 0 def initialize(io, pid, status) + @num = (@@worker_number += 1) @io = io @pid = pid @status = status @@ -214,6 +360,11 @@ def initialize(io, pid, status) @loadpath = [] @hooks = {} @quit_called = false + @response_at = nil + end + + def name + "Worker #{@num}" end def puts(*args) @@ -228,6 +379,8 @@ def run(task,type) @loadpath = $:.dup puts "run #{task} #{type}" @status = :prepare + @start_time = Time.now + @response_at = @start_time rescue Errno::EPIPE died rescue IOError @@ -244,6 +397,7 @@ def hook(id,&block) def read res = (@status == :quit) ? @io.read : @io.gets + @response_at = Time.now res && res.chomp end @@ -320,6 +474,22 @@ def after_worker_down(worker, e=nil, c=false) warn "or, a bug of test/unit/parallel.rb. try again without -j" warn "option." warn "" + if File.exist?('core') + require 'fileutils' + require 'time' + Dir.glob('/tmp/test-unit-core.*').each do |f| + if Time.now - File.mtime(f) > 7 * 24 * 60 * 60 # 7 days + warn "Deleting an old core file: #{f}" + FileUtils.rm(f) + end + end + core_path = "/tmp/test-unit-core.#{Time.now.utc.iso8601}" + warn "A core file is found. Saving it at: #{core_path.dump}" + FileUtils.mv('core', core_path) + cmd = ['gdb', RbConfig.ruby, '-c', core_path, '-ex', 'bt', '-batch'] + p cmd # debugging why it's not working + system(*cmd) + end STDERR.flush exit c end @@ -358,9 +528,11 @@ def delete_worker(worker) @ios.delete worker.io end - def quit_workers + def quit_workers(&cond) return if @workers.empty? + closed = [] if cond @workers.reject! do |worker| + next unless cond&.call(worker) begin Timeout.timeout(1) do worker.quit @@ -368,20 +540,33 @@ def quit_workers rescue Errno::EPIPE rescue Timeout::Error end - worker.close + closed&.push worker + begin + Timeout.timeout(0.2) do + worker.close + end + rescue Timeout::Error + worker.kill + retry + end + @ios.delete worker.io end - return if @workers.empty? + return if (closed ||= @workers).empty? + pids = closed.map(&:pid) begin - Timeout.timeout(0.2 * @workers.size) do + Timeout.timeout(0.2 * closed.size) do Process.waitall end rescue Timeout::Error - @workers.each do |worker| - worker.kill + if pids + Process.kill(:KILL, *pids) rescue nil + pids = nil + retry end - @worker.clear end + @workers.clear unless cond + closed end FakeClass = Struct.new(:name) @@ -393,6 +578,7 @@ def deal(io, type, result, rep, shutting_down = false) worker = @workers_hash[io] cmd = worker.read cmd.sub!(/\A\.+/, '') if cmd # read may return nil + case cmd when '' # just only dots, ignore @@ -414,34 +600,45 @@ def deal(io, type, result, rep, shutting_down = false) @test_count += 1 jobs_status(worker) + when /^start (.+?)$/ + worker.current = Marshal.load($1.unpack1("m")) when /^done (.+?)$/ begin - r = Marshal.load($1.unpack("m")[0]) + r = Marshal.load($1.unpack1("m")) rescue - print "unknown object: #{$1.unpack("m")[0].dump}" + print "unknown object: #{$1.unpack1("m").dump}" return true end result << r[0..1] unless r[0..1] == [nil,nil] rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]} $:.push(*r[4]).uniq! jobs_status(worker) if @options[:job_status] == :replace + return true when /^record (.+?)$/ begin - r = Marshal.load($1.unpack("m")[0]) + r = Marshal.load($1.unpack1("m")) + + suite = r.first + key = [worker.name, suite] + if @records[key] + @records[key][1] = worker.start_time = Time.now + else + @records[key] = [worker.start_time, Time.now] + end rescue => e - print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}" + print "unknown record: #{e.message} #{$1.unpack1("m").dump}" return true end record(fake_class(r[0]), *r[1..-1]) when /^p (.+?)$/ del_jobs_status - print $1.unpack("m")[0] + print $1.unpack1("m") jobs_status(worker) if @options[:job_status] == :replace when /^after (.+?)$/ - @warnings << Marshal.load($1.unpack("m")[0]) + @warnings << Marshal.load($1.unpack1("m")) when /^bye (.+?)$/ - after_worker_down worker, Marshal.load($1.unpack("m")[0]) + after_worker_down worker, Marshal.load($1.unpack1("m")) when /^bye$/, nil if shutting_down || worker.quit_called after_worker_quit worker @@ -455,6 +652,8 @@ def deal(io, type, result, rep, shutting_down = false) end def _run_parallel suites, type, result + @records = {} + if @options[:parallel] < 1 warn "Error: parameter of -j option should be greater than 0." return @@ -462,7 +661,8 @@ def _run_parallel suites, type, result # Require needed thing for parallel running require 'timeout' - @tasks = @files.dup # Array of filenames. + @tasks = @order.group(@order.sort_by_string(@files)) # Array of filenames. + @need_quit = false @dead_workers = [] # Array of dead workers. @warnings = [] @@ -476,14 +676,26 @@ def _run_parallel suites, type, result begin [@tasks.size, @options[:parallel]].min.times {launch_worker} - while _io = IO.select(@ios)[0] - break if _io.any? do |io| + while true + timeout = [(@workers.filter_map {|w| w.response_at}.min&.-(Time.now) || 0) + @worker_timeout, 1].max + + if !(_io = IO.select(@ios, nil, nil, timeout)) + timeout = Time.now - @worker_timeout + quit_workers {|w| w.response_at < timeout}&.map {|w| + rep << {file: w.real_file, result: nil, testcase: w.current[0], error: w.current} + } + elsif _io.first.any? {|io| @need_quit or (deal(io, type, result, rep).nil? and !@workers.any? {|x| [:running, :prepare].include? x.status}) + } + break end - if @jobserver and @job_tokens and !@tasks.empty? and !@workers.any? {|x| x.status == :ready} - t = @jobserver[0].read_nonblock([@tasks.size, @options[:parallel]].min, exception: false) + break if @tasks.empty? and @workers.empty? + if @jobserver and @job_tokens and !@tasks.empty? and + ((newjobs = [@tasks.size, @options[:parallel]].min) > @workers.size or + !@workers.any? {|x| x.status == :ready}) + t = @jobserver[0].read_nonblock(newjobs, exception: false) if String === t @job_tokens << t t.size.times {launch_worker} @@ -494,6 +706,14 @@ def _run_parallel suites, type, result @interrupt = ex return result ensure + if file = @options[:timetable_data] + open(file, 'w'){|f| + @records.each{|(worker, suite), (st, ed)| + f.puts '[' + [worker.dump, suite.dump, st.to_f * 1_000, ed.to_f * 1_000].join(", ") + '],' + } + } + end + if @interrupt @ios.select!{|x| @workers_hash[x].status == :running } while !@ios.empty? && (__io = IO.select(@ios,[],[],10)) @@ -507,14 +727,30 @@ def _run_parallel suites, type, result unless @interrupt || !@options[:retry] || @need_quit parallel = @options[:parallel] @options[:parallel] = false - suites, rep = rep.partition {|r| r[:testcase] && r[:file] && r[:report].any? {|e| !e[2].is_a?(MiniTest::Skip)}} - suites.map {|r| r[:file]}.uniq.each {|file| require file} - suites.map! {|r| eval("::"+r[:testcase])} + suites, rep = rep.partition {|r| + r[:testcase] && r[:file] && + (!r.key?(:report) || r[:report].any? {|e| !e[2].is_a?(Test::Unit::PendedError)}) + } + suites.map {|r| File.realpath(r[:file])}.uniq.each {|file| require file} del_status_line or puts + error, suites = suites.partition {|r| r[:error]} unless suites.empty? puts "\n""Retrying..." + @verbose = options[:verbose] + suites.map! {|r| ::Object.const_get(r[:testcase])} _run_suites(suites, type) end + unless error.empty? + puts "\n""Retrying hung up testcases..." + error.map! {|r| ::Object.const_get(r[:testcase])} + verbose = @verbose + job_status = options[:job_status] + options[:verbose] = @verbose = true + options[:job_status] = :normal + result.concat _run_suites(error, type) + options[:verbose] = @verbose = verbose + options[:job_status] = job_status + end @options[:parallel] = parallel end unless @options[:retry] @@ -522,14 +758,21 @@ def _run_parallel suites, type, result end unless rep.empty? rep.each do |r| - r[:report].each do |f| + if r[:error] + puke(*r[:error], Timeout::Error) + next + end + r[:report]&.each do |f| puke(*f) if f end end if @options[:retry] - @errors += rep.map{|x| x[:result][0] }.inject(:+) - @failures += rep.map{|x| x[:result][1] }.inject(:+) - @skips += rep.map{|x| x[:result][2] }.inject(:+) + rep.each do |x| + (e, f, s = x[:result]) or next + @errors += e + @failures += f + @skips += s + end end end unless @warnings.empty? @@ -684,7 +927,7 @@ def add_status(line) end def jobs_status(worker) - return if !@options[:job_status] or @options[:verbose] + return if !@options[:job_status] or @verbose if @options[:job_status] == :replace status_line = @workers.map(&:to_s).join(" ") else @@ -817,7 +1060,7 @@ def print(s) runner.add_status(" = #$1") when /\A\.+\z/ runner.succeed - when /\A[EFS]\z/ + when /\A\.*[EFS][EFS.]*\z/ runner.failed(s) else $stdout.print(s) @@ -936,7 +1179,7 @@ def setup_options(parser, options) def non_options(files, options) if options.delete(:gc_stress) - MiniTest::Unit::TestCase.class_eval do + Test::Unit::TestCase.class_eval do oldrun = instance_method(:run) define_method(:run) do |runner| begin @@ -949,7 +1192,7 @@ def non_options(files, options) end end if options.delete(:gc_compact) - MiniTest::Unit::TestCase.class_eval do + Test::Unit::TestCase.class_eval do oldrun = instance_method(:run) define_method(:run) do |runner| begin @@ -1086,30 +1329,345 @@ def non_options(files, options) end end - class Runner < MiniTest::Unit # :nodoc: all - include Test::Unit::Options - include Test::Unit::StatusLine - include Test::Unit::Parallel - include Test::Unit::Statistics - include Test::Unit::Skipping - include Test::Unit::GlobOption - include Test::Unit::RepeatOption - include Test::Unit::LoadPathOption - include Test::Unit::GCOption - include Test::Unit::ExcludesOption - include Test::Unit::TimeoutOption - include Test::Unit::RunCount - - def run(argv) - super + class Runner # :nodoc: all + + attr_accessor :report, :failures, :errors, :skips # :nodoc: + attr_accessor :assertion_count # :nodoc: + attr_writer :test_count # :nodoc: + attr_accessor :start_time # :nodoc: + attr_accessor :help # :nodoc: + attr_accessor :verbose # :nodoc: + attr_writer :options # :nodoc: + + ## + # :attr: + # + # if true, installs an "INFO" signal handler (only available to BSD and + # OS X users) which prints diagnostic information about the test run. + # + # This is auto-detected by default but may be overridden by custom + # runners. + + attr_accessor :info_signal + + ## + # Lazy accessor for options. + + def options + @options ||= {seed: 42} + end + + @@installed_at_exit ||= false + @@out = $stdout + @@after_tests = [] + @@current_repeat_count = 0 + + ## + # A simple hook allowing you to run a block of code after _all_ of + # the tests are done. Eg: + # + # Test::Unit::Runner.after_tests { p $debugging_info } + + def self.after_tests &block + @@after_tests << block + end + + ## + # Returns the stream to use for output. + + def self.output + @@out + end + + ## + # Sets Test::Unit::Runner to write output to +stream+. $stdout is the default + # output + + def self.output= stream + @@out = stream + end + + ## + # Tells Test::Unit::Runner to delegate to +runner+, an instance of a + # Test::Unit::Runner subclass, when Test::Unit::Runner#run is called. + + def self.runner= runner + @@runner = runner + end + + ## + # Returns the Test::Unit::Runner subclass instance that will be used + # to run the tests. A Test::Unit::Runner instance is the default + # runner. + + def self.runner + @@runner ||= self.new + end + + ## + # Return all plugins' run methods (methods that start with "run_"). + + def self.plugins + @@plugins ||= (["run_tests"] + + public_instance_methods(false). + grep(/^run_/).map { |s| s.to_s }).uniq + end + + ## + # Return the IO for output. + + def output + self.class.output + end + + def puts *a # :nodoc: + output.puts(*a) + end + + def print *a # :nodoc: + output.print(*a) + end + + def test_count # :nodoc: + @test_count ||= 0 + end + + ## + # Runner for a given +type+ (eg, test vs bench). + + def self.current_repeat_count + @@current_repeat_count + end + + def _run_anything type + suites = Test::Unit::TestCase.send "#{type}_suites" + return if suites.empty? + + suites = @order.sort_by_name(suites) + + puts + puts "# Running #{type}s:" + puts + + @test_count, @assertion_count = 0, 0 + test_count = assertion_count = 0 + sync = output.respond_to? :"sync=" # stupid emacs + old_sync, output.sync = output.sync, true if sync + + @@current_repeat_count = 0 + begin + start = Time.now + + results = _run_suites suites, type + + @test_count = results.inject(0) { |sum, (tc, _)| sum + tc } + @assertion_count = results.inject(0) { |sum, (_, ac)| sum + ac } + test_count += @test_count + assertion_count += @assertion_count + t = Time.now - start + @@current_repeat_count += 1 + unless @repeat_count + puts + puts + end + puts "Finished%s %ss in %.6fs, %.4f tests/s, %.4f assertions/s.\n" % + [(@repeat_count ? "(#{@@current_repeat_count}/#{@repeat_count}) " : ""), type, + t, @test_count.fdiv(t), @assertion_count.fdiv(t)] + end while @repeat_count && @@current_repeat_count < @repeat_count && + report.empty? && failures.zero? && errors.zero? + + output.sync = old_sync if sync + + report.each_with_index do |msg, i| + puts "\n%3d) %s" % [i + 1, msg] + end + + puts + @test_count = test_count + @assertion_count = assertion_count + + status + end + + ## + # Run a single +suite+ for a given +type+. + + def _run_suite suite, type + header = "#{type}_suite_header" + puts send(header, suite) if respond_to? header + + filter = options[:filter] + + all_test_methods = suite.send "#{type}_methods" + if filter + all_test_methods.select! {|method| + filter === "#{suite}##{method}" + } + end + all_test_methods = @order.sort_by_name(all_test_methods) + + leakchecker = LeakChecker.new + if ENV["LEAK_CHECKER_TRACE_OBJECT_ALLOCATION"] + require "objspace" + trace = true + end + + assertions = all_test_methods.map { |method| + + inst = suite.new method + _start_method(inst) + inst._assertions = 0 + + print "#{suite}##{method} = " if @verbose + + start_time = Time.now if @verbose + result = + if trace + ObjectSpace.trace_object_allocations {inst.run self} + else + inst.run self + end + + print "%.2f s = " % (Time.now - start_time) if @verbose + print result + puts if @verbose + $stdout.flush + + unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # compiler process is wrongly considered as leak + leakchecker.check("#{inst.class}\##{inst.__name__}") + end + + _end_method(inst) + + inst._assertions + } + return assertions.size, assertions.inject(0) { |sum, n| sum + n } + end + + def _start_method(inst) + end + def _end_method(inst) + end + + ## + # Record the result of a single test. Makes it very easy to gather + # information. Eg: + # + # class StatisticsRecorder < Test::Unit::Runner + # def record suite, method, assertions, time, error + # # ... record the results somewhere ... + # end + # end + # + # Test::Unit::Runner.runner = StatisticsRecorder.new + # + # NOTE: record might be sent more than once per test. It will be + # sent once with the results from the test itself. If there is a + # failure or error in teardown, it will be sent again with the + # error or failure. + + def record suite, method, assertions, time, error + end + + def location e # :nodoc: + last_before_assertion = "" + + return '' unless e.backtrace # SystemStackError can return nil. + + e.backtrace.reverse_each do |s| + break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/ + last_before_assertion = s + end + last_before_assertion.sub(/:in .*$/, '') + end + + ## + # Writes status for failed test +meth+ in +klass+ which finished with + # exception +e+ + + def initialize # :nodoc: + @report = [] + @errors = @failures = @skips = 0 + @verbose = false + @mutex = Thread::Mutex.new + @info_signal = Signal.list['INFO'] + @repeat_count = nil + end + + def synchronize # :nodoc: + if @mutex then + @mutex.synchronize { yield } + else + yield + end + end + + def inspect + "#<#{self.class.name}: " << + instance_variables.filter_map do |var| + next if var == :@option_parser # too big + "#{var}=#{instance_variable_get(var).inspect}" + end.join(", ") << ">" + end + + ## + # Top level driver, controls all output and filtering. + + def _run args = [] + args = process_args args # ARGH!! blame test/unit process_args + self.options.merge! args + + puts "Run options: #{help}" + + self.class.plugins.each do |plugin| + send plugin + break unless report.empty? + end + + return failures + errors if self.test_count > 0 # or return nil... + rescue Interrupt + abort 'Interrupted' + end + + ## + # Runs test suites matching +filter+. + + def run_tests + _run_anything :test + end + + ## + # Writes status to +io+ + + def status io = self.output + format = "%d tests, %d assertions, %d failures, %d errors, %d skips" + io.puts format % [test_count, assertion_count, failures, errors, skips] + end + + prepend Test::Unit::Options + prepend Test::Unit::StatusLine + prepend Test::Unit::Parallel + prepend Test::Unit::Statistics + prepend Test::Unit::Skipping + prepend Test::Unit::GlobOption + prepend Test::Unit::RepeatOption + prepend Test::Unit::LoadPathOption + prepend Test::Unit::GCOption + prepend Test::Unit::ExcludesOption + prepend Test::Unit::TimeoutOption + prepend Test::Unit::RunCount + + ## + # Begins the full test run. Delegates to +runner+'s #_run method. + + def run(argv = []) + self.class.runner._run(argv) rescue NoMemoryError system("cat /proc/meminfo") if File.exist?("/proc/meminfo") system("ps x -opid,args,%cpu,%mem,nlwp,rss,vsz,wchan,stat,start,time,etime,blocked,caught,ignored,pending,f") if File.exist?("/bin/ps") raise end - class << self; undef autorun; end - @@stop_auto_run = false def self.autorun at_exit { @@ -1120,16 +1678,27 @@ def self.autorun @@installed_at_exit = true end - alias mini_run_suite _run_suite + alias orig_run_suite _run_suite - # Overriding of MiniTest::Unit#puke + # Overriding of Test::Unit::Runner#puke def puke klass, meth, e - # TODO: - # this overriding is for minitest feature that skip messages are - # hidden when not verbose (-v), note this is temporally. n = report.size - rep = super - if MiniTest::Skip === e and /no message given\z/ =~ e.message + e = case e + when Test::Unit::PendedError then + @skips += 1 + return "S" unless @verbose + "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" + when Test::Unit::AssertionFailedError then + @failures += 1 + "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" + else + @errors += 1 + bt = Test::filter_backtrace(e.backtrace).join "\n " + "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message.b}\n #{bt}\n" + end + @report << e + rep = e[0, 1] + if Test::Unit::PendedError === e and /no message given\z/ =~ e.message report.slice!(n..-1) rep = "." end @@ -1190,30 +1759,4 @@ def initialize(ex) end end -module MiniTest # :nodoc: all - class Unit - end -end - -class MiniTest::Unit::TestCase # :nodoc: all - test_order = self.test_order - class << self - attr_writer :test_order - undef test_order - end - def self.test_order - defined?(@test_order) ? @test_order : superclass.test_order - end - self.test_order = test_order - undef run_test - RUN_TEST_TRACE = "#{__FILE__}:#{__LINE__+3}:in `run_test'".freeze - def run_test(name) - progname, $0 = $0, "#{$0}: #{self.class}##{name}" - self.__send__(name) - ensure - $@.delete(RUN_TEST_TRACE) if $@ - $0 = progname - end -end - Test::Unit::Runner.autorun diff --git a/ruby/tool/lib/test/unit/assertions.rb b/ruby/tool/lib/test/unit/assertions.rb index e2b865899..3deeb8fcd 100644 --- a/ruby/tool/lib/test/unit/assertions.rb +++ b/ruby/tool/lib/test/unit/assertions.rb @@ -1,37 +1,538 @@ # frozen_string_literal: true -require 'minitest/unit' -require 'test/unit/core_assertions' require 'pp' module Test module Unit module Assertions - include Test::Unit::CoreAssertions - MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc: + ## + # Returns the diff command to use in #diff. Tries to intelligently + # figure out what diff to use. - # :call-seq: - # assert(test, [failure_message]) + def self.diff + unless defined? @diff + exe = RbConfig::CONFIG['EXEEXT'] + @diff = %W"gdiff#{exe} diff#{exe}".find do |diff| + if system(diff, "-u", __FILE__, __FILE__) + break "#{diff} -u" + end + end + end + + @diff + end + + ## + # Set the diff command to use in #diff. + + def self.diff= o + @diff = o + end + + ## + # Returns a diff between +exp+ and +act+. If there is no known + # diff command or if it doesn't make sense to diff the output + # (single line, short output), then it simply returns a basic + # comparison between the two. + + def diff exp, act + require "tempfile" + + expect = mu_pp_for_diff exp + butwas = mu_pp_for_diff act + result = nil + + need_to_diff = + self.class.diff && + (expect.include?("\n") || + butwas.include?("\n") || + expect.size > 30 || + butwas.size > 30 || + expect == butwas) + + return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless + need_to_diff + + tempfile_a = nil + tempfile_b = nil + + Tempfile.open("expect") do |a| + tempfile_a = a + a.puts expect + a.flush + + Tempfile.open("butwas") do |b| + tempfile_b = b + b.puts butwas + b.flush + + result = `#{self.class.diff} #{a.path} #{b.path}` + result.sub!(/^\-\-\- .+/, "--- expected") + result.sub!(/^\+\+\+ .+/, "+++ actual") + + if result.empty? then + klass = exp.class + result = [ + "No visible difference in the #{klass}#inspect output.\n", + "You should look at the implementation of #== on ", + "#{klass} or its members.\n", + expect, + ].join + end + end + end + + result + ensure + tempfile_a.close! if tempfile_a + tempfile_b.close! if tempfile_b + end + + ## + # This returns a diff-able human-readable version of +obj+. This + # differs from the regular mu_pp because it expands escaped + # newlines and makes hex-values generic (like object_ids). This + # uses mu_pp to do the first pass and then cleans it up. + + def mu_pp_for_diff obj + mu_pp(obj).gsub(/(?= n, msg + end + + ## + # For comparing Floats. Fails unless +exp+ and +act+ have a relative + # error less than +epsilon+. + + def assert_in_epsilon a, b, epsilon = 0.001, msg = nil + assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg + end + + ## + # Fails unless +collection+ includes +obj+. + + def assert_includes collection, obj, msg = nil + msg = message(msg) { + "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" + } + assert_respond_to collection, :include? + assert collection.include?(obj), msg + end + + ## + # Fails unless +obj+ is an instance of +cls+. + + def assert_instance_of cls, obj, msg = nil + msg = message(msg) { + "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" + } + + assert obj.instance_of?(cls), msg + end + + ## + # Fails unless +obj+ is a kind of +cls+. + + def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of + msg = message(msg) { + "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" } + + assert obj.kind_of?(cls), msg + end + + ## + # Fails unless +matcher+ =~ +obj+. + + def assert_match matcher, obj, msg = nil + msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } + assert_respond_to matcher, :"=~" + matcher = Regexp.new Regexp.escape matcher if String === matcher + assert matcher =~ obj, msg + end + + ## + # Fails unless +obj+ is nil + + def assert_nil obj, msg = nil + msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" } + assert obj.nil?, msg + end + + ## + # For testing with binary operators. + # + # assert_operator 5, :<=, 4 + + def assert_operator o1, op, o2 = (predicate = true; nil), msg = nil + return assert_predicate o1, op, msg if predicate + msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" } + assert o1.__send__(op, o2), msg + end + + ## + # Fails if stdout or stderr do not output the expected results. + # Pass in nil if you don't care about that streams output. Pass in + # "" if you require it to be silent. Pass in a regexp if you want + # to pattern match. + # + # NOTE: this uses #capture_io, not #capture_subprocess_io. + # + # See also: #assert_silent + + def assert_output stdout = nil, stderr = nil + out, err = capture_output do + yield + end + + err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr + out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout + + y = send err_msg, stderr, err, "In stderr" if err_msg + x = send out_msg, stdout, out, "In stdout" if out_msg + + (!stdout || x) && (!stderr || y) + end + + ## + # For testing with predicates. + # + # assert_predicate str, :empty? + # + # This is really meant for specs and is front-ended by assert_operator: + # + # str.must_be :empty? + + def assert_predicate o1, op, msg = nil + msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" } + assert o1.__send__(op), msg + end + + ## + # Fails unless +obj+ responds to +meth+. + + def assert_respond_to obj, meth, msg = nil + msg = message(msg) { + "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" + } + assert obj.respond_to?(meth), msg + end + + ## + # Fails unless +exp+ and +act+ are #equal? + + def assert_same exp, act, msg = nil + msg = message(msg) { + data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] + "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data + } + assert exp.equal?(act), msg + end + + ## + # Fails if the block outputs anything to stderr or stdout. + # + # See also: #assert_output + + def assert_silent + assert_output "", "" do + yield + end + end + + ## + # Fails unless the block throws +sym+ + + def assert_throws sym, msg = nil + default = "Expected #{mu_pp(sym)} to have been thrown" + caught = true + catch(sym) do + begin + yield + rescue ThreadError => e # wtf?!? 1.8 + threads == suck + default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" + rescue ArgumentError => e # 1.9 exception + default += ", not #{e.message.split(/ /).last}" + rescue NameError => e # 1.8 exception + default += ", not #{e.name.inspect}" + end + caught = false + end + + assert caught, message(msg) { default } + end + + def assert_path_exists(path, msg = nil) + msg = message(msg) { "Expected path '#{path}' to exist" } + assert File.exist?(path), msg + end + alias assert_path_exist assert_path_exists + alias refute_path_not_exist assert_path_exists + + def refute_path_exists(path, msg = nil) + msg = message(msg) { "Expected path '#{path}' to not exist" } + refute File.exist?(path), msg + end + alias refute_path_exist refute_path_exists + alias assert_path_not_exist refute_path_exists + + ## + # Captures $stdout and $stderr into strings: + # + # out, err = capture_output do + # puts "Some info" + # warn "You did a bad thing" + # end + # + # assert_match %r%info%, out + # assert_match %r%bad%, err + + def capture_output + require 'stringio' + + captured_stdout, captured_stderr = StringIO.new, StringIO.new + + synchronize do + orig_stdout, orig_stderr = $stdout, $stderr + $stdout, $stderr = captured_stdout, captured_stderr + + begin + yield + ensure + $stdout = orig_stdout + $stderr = orig_stderr + end + end + + return captured_stdout.string, captured_stderr.string + end + + def capture_io + raise NoMethodError, "use capture_output" + end + + ## + # Fails with +msg+ + + def flunk msg = nil + msg ||= "Epic Fail!" + assert false, msg + end + + ## + # used for counting assertions + + def pass msg = nil + assert true + end + + ## + # Fails if +test+ is a true value + + def refute test, msg = nil + msg ||= "Failed refutation, no message given" + not assert(! test, msg) + end + + ## + # Fails if +obj+ is empty. + + def refute_empty obj, msg = nil + msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" } + assert_respond_to obj, :empty? + refute obj.empty?, msg + end + + ## + # Fails if exp == act. + # + # For floats use refute_in_delta. + + def refute_equal exp, act, msg = nil + msg = message(msg) { + "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" + } + refute exp == act, msg + end + + ## + # For comparing Floats. Fails if +exp+ is within +delta+ of +act+. + # + # refute_in_delta Math::PI, (22.0 / 7.0) + + def refute_in_delta exp, act, delta = 0.001, msg = nil + n = (exp - act).abs + msg = message(msg) { + "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}" + } + refute delta >= n, msg + end + + ## + # For comparing Floats. Fails if +exp+ and +act+ have a relative error + # less than +epsilon+. + + def refute_in_epsilon a, b, epsilon = 0.001, msg = nil + refute_in_delta a, b, a * epsilon, msg + end + + ## + # Fails if +collection+ includes +obj+. + + def refute_includes collection, obj, msg = nil + msg = message(msg) { + "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" + } + assert_respond_to collection, :include? + refute collection.include?(obj), msg + end + + ## + # Fails if +obj+ is an instance of +cls+. + + def refute_instance_of cls, obj, msg = nil + msg = message(msg) { + "Expected #{mu_pp(obj)} to not be an instance of #{cls}" + } + refute obj.instance_of?(cls), msg + end + + ## + # Fails if +obj+ is a kind of +cls+. + + def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of + msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } + refute obj.kind_of?(cls), msg + end + + ## + # Fails if +matcher+ =~ +obj+. + + def refute_match matcher, obj, msg = nil + msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"} + assert_respond_to matcher, :"=~" + matcher = Regexp.new Regexp.escape matcher if String === matcher + refute matcher =~ obj, msg + end + + ## + # Fails if +obj+ is nil. + + def refute_nil obj, msg = nil + msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" } + refute obj.nil?, msg + end + + ## + # Fails if +o1+ is not +op+ +o2+. Eg: # - #Tests if +test+ is true. + # refute_operator 1, :>, 2 #=> pass + # refute_operator 1, :<, 2 #=> fail + + def refute_operator o1, op, o2 = (predicate = true; nil), msg = nil + return refute_predicate o1, op, msg if predicate + msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"} + refute o1.__send__(op, o2), msg + end + + ## + # For testing with predicates. # - #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used - #as the failure message. Otherwise, the result of calling +msg+ will be - #used as the message if the assertion fails. + # refute_predicate str, :empty? # - #If no +msg+ is given, a default message will be used. + # This is really meant for specs and is front-ended by refute_operator: # - # assert(false, "This was expected to be true") - def assert(test, *msgs) - case msg = msgs.first - when String, Proc - when nil - msgs.shift - else - bt = caller.reject { |s| s.start_with?(MINI_DIR) } - raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt - end unless msgs.empty? - super + # str.wont_be :empty? + + def refute_predicate o1, op, msg = nil + msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" } + refute o1.__send__(op), msg + end + + ## + # Fails if +obj+ responds to the message +meth+. + + def refute_respond_to obj, meth, msg = nil + msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" } + + refute obj.respond_to?(meth), msg + end + + ## + # Fails if +exp+ is the same (by object identity) as +act+. + + def refute_same exp, act, msg = nil + msg = message(msg) { + data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] + "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data + } + refute exp.equal?(act), msg + end + + ## + # Skips the current test. Gets listed at the end of the run but + # doesn't cause a failure exit code. + + def pend msg = nil, bt = caller + msg ||= "Skipped, no message given" + @skip = true + raise Test::Unit::PendedError, msg, bt + end + alias omit pend + + # TODO: Removed this and enabled to raise NoMethodError with skip + alias skip pend + # def skip(msg = nil, bt = caller) + # raise NoMethodError, "use omit or pend", caller + # end + + ## + # Was this testcase skipped? Meant for #teardown. + + def skipped? + defined?(@skip) and @skip + end + + ## + # Takes a block and wraps it with the runner's shared mutex. + + def synchronize + Test::Unit::Runner.runner.synchronize do + yield + end end # :call-seq: @@ -52,50 +553,6 @@ def assert_raises(*exp, &b) raise NoMethodError, "use assert_raise", caller end - # :call-seq: - # assert_nothing_raised( *args, &block ) - # - #If any exceptions are given as arguments, the assertion will - #fail if one of those exceptions are raised. Otherwise, the test fails - #if any exceptions are raised. - # - #The final argument may be a failure message. - # - # assert_nothing_raised RuntimeError do - # raise Exception #Assertion passes, Exception is not a RuntimeError - # end - # - # assert_nothing_raised do - # raise Exception #Assertion fails - # end - def assert_nothing_raised(*args) - self._assertions += 1 - if Module === args.last - msg = nil - else - msg = args.pop - end - begin - line = __LINE__; yield - rescue MiniTest::Skip - raise - rescue Exception => e - bt = e.backtrace - as = e.instance_of?(MiniTest::Assertion) - if as - ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o - bt.reject! {|ln| ans =~ ln} - end - if ((args.empty? && !as) || - args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a }) - msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" } - raise MiniTest::Assertion, msg.call, bt - else - raise - end - end - end - # :call-seq: # assert_nothing_thrown( failure_message = nil, &block ) # @@ -225,52 +682,6 @@ def assert_not_same(expected, actual, message="") assert(!actual.equal?(expected), msg) end - # :call-seq: - # assert_respond_to( object, method, failure_message = nil ) - # - #Tests if the given Object responds to +method+. - # - #An optional failure message may be provided as the final argument. - # - # assert_respond_to("hello", :reverse) #Succeeds - # assert_respond_to("hello", :does_not_exist) #Fails - def assert_respond_to(obj, (meth, *priv), msg = nil) - unless priv.empty? - msg = message(msg) { - "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}" - } - return assert obj.respond_to?(meth, *priv), msg - end - #get rid of overcounting - if caller_locations(1, 1)[0].path.start_with?(MINI_DIR) - return if obj.respond_to?(meth) - end - super(obj, meth, msg) - end - - # :call-seq: - # assert_not_respond_to( object, method, failure_message = nil ) - # - #Tests if the given Object does not respond to +method+. - # - #An optional failure message may be provided as the final argument. - # - # assert_not_respond_to("hello", :reverse) #Fails - # assert_not_respond_to("hello", :does_not_exist) #Succeeds - def assert_not_respond_to(obj, (meth, *priv), msg = nil) - unless priv.empty? - msg = message(msg) { - "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}" - } - return assert !obj.respond_to?(meth, *priv), msg - end - #get rid of overcounting - if caller_locations(1, 1)[0].path.start_with?(MINI_DIR) - return unless obj.respond_to?(meth) - end - refute_respond_to(obj, meth, msg) - end - # :call-seq: # assert_send( +send_array+, failure_message = nil ) # @@ -331,16 +742,6 @@ def assert_not_send send_ary, m = nil alias assert_include assert_includes alias assert_not_include assert_not_includes - def assert_all?(obj, m = nil, &blk) - failed = [] - obj.each do |*a, &b| - unless blk.call(*a, &b) - failed << (a.size > 1 ? a : a[0]) - end - end - assert(failed.empty?, message(m) {failed.pretty_inspect}) - end - def assert_not_all?(obj, m = nil, &blk) failed = [] obj.each do |*a, &b| @@ -351,62 +752,8 @@ def assert_not_all?(obj, m = nil, &blk) assert(failed.empty?, message(m) {failed.pretty_inspect}) end - # compatibility with test-unit - alias pend skip - - if defined?(RubyVM::InstructionSequence) - def syntax_check(code, fname, line) - code = code.dup.force_encoding(Encoding::UTF_8) - RubyVM::InstructionSequence.compile(code, fname, fname, line) - :ok - ensure - raise if SyntaxError === $! - end - else - def syntax_check(code, fname, line) - code = code.b - code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) { - "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n" - } - code = code.force_encoding(Encoding::UTF_8) - catch {|tag| eval(code, binding, fname, line - 1)} - end - end - - def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil) - fname ||= caller_locations(2, 1)[0] - mesg ||= fname.to_s - verbose, $VERBOSE = $VERBOSE, verbose - case - when Array === fname - fname, line = *fname - when defined?(fname.path) && defined?(fname.lineno) - fname, line = fname.path, fname.lineno - else - line = 1 - end - yield(code, fname, line, message(mesg) { - if code.end_with?("\n") - "```\n#{code}```\n" - else - "```\n#{code}\n```\n""no-newline" - end - }) - ensure - $VERBOSE = verbose - end - - def assert_valid_syntax(code, *args, **opt) + def assert_syntax_error(code, error, *args, **opt) prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg| - yield if defined?(yield) - assert_nothing_raised(SyntaxError, mesg) do - assert_equal(:ok, syntax_check(src, fname, line), mesg) - end - end - end - - def assert_syntax_error(code, error, *args) - prepare_syntax_check(code, *args) do |src, fname, line, mesg| yield if defined?(yield) e = assert_raise(SyntaxError, mesg) do syntax_check(src, fname, line) @@ -416,17 +763,6 @@ def assert_syntax_error(code, error, *args) end end - def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) - assert_valid_syntax(testsrc, caller_locations(1, 1)[0]) - if child_env - child_env = [child_env] - else - child_env = [] - end - out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt) - assert !status.signaled?, FailDesc[status, message, out] - end - def assert_no_warning(pat, msg = nil) result = nil stderr = EnvUtil.verbose_warning { @@ -439,54 +775,9 @@ def assert_no_warning(pat, msg = nil) result end - def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt) - # TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail - skip 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - - require_relative '../../memory_status' - raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status) - - token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m" - token_dump = token.dump - token_re = Regexp.quote(token) - envs = args.shift if Array === args and Hash === args.first - args = [ - "--disable=gems", - "-r", File.expand_path("../../../memory_status", __FILE__), - *args, - "-v", "-", - ] - if defined? Memory::NO_MEMORY_LEAK_ENVS then - envs ||= {} - newenvs = envs.merge(Memory::NO_MEMORY_LEAK_ENVS) { |_, _, _| break } - envs = newenvs if newenvs - end - args.unshift(envs) if envs - cmd = [ - 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new}"}', - prepare, - 'STDERR.puts('"#{token_dump}"'"START=#{$initial_status = Memory::Status.new}")', - '$initial_size = $initial_status.size', - code, - 'GC.start', - ].join("\n") - _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, **opt) - before = err.sub!(/^#{token_re}START=(\{.*\})\n/, '') && Memory::Status.parse($1) - after = err.sub!(/^#{token_re}FINAL=(\{.*\})\n/, '') && Memory::Status.parse($1) - assert(status.success?, FailDesc[status, message, err]) - ([:size, (rss && :rss)] & after.members).each do |n| - b = before[n] - a = after[n] - next unless a > 0 and b > 0 - assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"}) - end - rescue LoadError - skip - end - # kernel resolution can limit the minimum time we can measure # [ruby-core:81540] - MIN_HZ = MiniTest::Unit::TestCase.windows? ? 67 : 100 + MIN_HZ = /mswin|mingw/ =~ RUBY_PLATFORM ? 67 : 100 MIN_MEASURABLE = 1.0 / MIN_HZ def assert_cpu_usage_low(msg = nil, pct: 0.05, wait: 1.0, stop: nil) @@ -523,57 +814,6 @@ def assert_is_minus_zero(f) assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0") end - # pattern_list is an array which contains regexp and :*. - # :* means any sequence. - # - # pattern_list is anchored. - # Use [:*, regexp, :*] for non-anchored match. - def assert_pattern_list(pattern_list, actual, message=nil) - rest = actual - anchored = true - pattern_list.each_with_index {|pattern, i| - if pattern == :* - anchored = false - else - if anchored - match = /\A#{pattern}/.match(rest) - else - match = pattern.match(rest) - end - unless match - msg = message(msg) { - expect_msg = "Expected #{mu_pp pattern}\n" - if /\n[^\n]/ =~ rest - actual_mesg = +"to match\n" - rest.scan(/.*\n+/) { - actual_mesg << ' ' << $&.inspect << "+\n" - } - actual_mesg.sub!(/\+\n\z/, '') - else - actual_mesg = "to match " + mu_pp(rest) - end - actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters" - expect_msg + actual_mesg - } - assert false, msg - end - rest = match.post_match - anchored = true - end - } - if anchored - assert_equal("", rest) - end - end - - def assert_all_assertions_foreach(msg = nil, *keys, &block) - all = AllFailures.new - all.foreach(*keys, &block) - ensure - assert(all.pass?, message(msg) {all.message.chomp(".")}) - end - alias all_assertions_foreach assert_all_assertions_foreach - def build_message(head, template=nil, *arguments) #:nodoc: template &&= template.chomp template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) } diff --git a/ruby/tool/lib/test/unit/core_assertions.rb b/ruby/tool/lib/test/unit/core_assertions.rb deleted file mode 100644 index 00555d6e3..000000000 --- a/ruby/tool/lib/test/unit/core_assertions.rb +++ /dev/null @@ -1,420 +0,0 @@ -# frozen_string_literal: true - -module Test - module Unit - module Assertions - def _assertions= n # :nodoc: - @_assertions = n - end - - def _assertions # :nodoc: - @_assertions ||= 0 - end - - ## - # Returns a proc that will output +msg+ along with the default message. - - def message msg = nil, ending = nil, &default - proc { - msg = msg.call.chomp(".") if Proc === msg - custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? - "#{custom_message}#{default.call}#{ending || "."}" - } - end - end - - module CoreAssertions - if defined?(MiniTest) - require_relative '../../envutil' - # for ruby core testing - include MiniTest::Assertions - - # Compatibility hack for assert_raise - Test::Unit::AssertionFailedError = MiniTest::Assertion - else - module MiniTest - class Assertion < Exception; end - class Skip < Assertion; end - end - - require 'pp' - require_relative 'envutil' - include Test::Unit::Assertions - end - - def mu_pp(obj) #:nodoc: - obj.pretty_inspect.chomp - end - - def assert_file - AssertFile - end - - FailDesc = proc do |status, message = "", out = ""| - now = Time.now - proc do - EnvUtil.failure_description(status, now, message, out) - end - end - - def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, - success: nil, **opt) - args = Array(args).dup - args.insert((Hash === args[0] ? 1 : 0), '--disable=gems') - stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, **opt) - desc = FailDesc[status, message, stderr] - if block_given? - raise "test_stdout ignored, use block only or without block" if test_stdout != [] - raise "test_stderr ignored, use block only or without block" if test_stderr != [] - yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp }, status) - else - all_assertions(desc) do |a| - [["stdout", test_stdout, stdout], ["stderr", test_stderr, stderr]].each do |key, exp, act| - a.for(key) do - if exp.is_a?(Regexp) - assert_match(exp, act) - elsif exp.all? {|e| String === e} - assert_equal(exp, act.lines.map {|l| l.chomp }) - else - assert_pattern_list(exp, act) - end - end - end - unless success.nil? - a.for("success?") do - if success - assert_predicate(status, :success?) - else - assert_not_predicate(status, :success?) - end - end - end - end - status - end - end - - def assert_ruby_status(args, test_stdin="", message=nil, **opt) - out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt) - desc = FailDesc[status, message, out] - assert(!status.signaled?, desc) - message ||= "ruby exit status is not success:" - assert(status.success?, desc) - end - - ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM") - - def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt) - unless file and line - loc, = caller_locations(1,1) - file ||= loc.path - line ||= loc.lineno - end - src = < marshal_error - ignore_stderr = nil - end - if res - if bt = res.backtrace - bt.each do |l| - l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"} - end - bt.concat(caller) - else - res.set_backtrace(caller) - end - raise res unless SystemExit === res - end - - # really is it succeed? - unless ignore_stderr - # the body of assert_separately must not output anything to detect error - assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr]) - end - assert(status.success?, FailDesc[status, "assert_separately failed", stderr]) - raise marshal_error if marshal_error - end - - # :call-seq: - # assert_throw( tag, failure_message = nil, &block ) - # - #Fails unless the given block throws +tag+, returns the caught - #value otherwise. - # - #An optional failure message may be provided as the final argument. - # - # tag = Object.new - # assert_throw(tag, "#{tag} was not thrown!") do - # throw tag - # end - def assert_throw(tag, msg = nil) - ret = catch(tag) do - begin - yield(tag) - rescue UncaughtThrowError => e - thrown = e.tag - end - msg = message(msg) { - "Expected #{mu_pp(tag)} to have been thrown"\ - "#{%Q[, not #{thrown}] if thrown}" - } - assert(false, msg) - end - assert(true) - ret - end - - # :call-seq: - # assert_raise( *args, &block ) - # - #Tests if the given block raises an exception. Acceptable exception - #types may be given as optional arguments. If the last argument is a - #String, it will be used as the error message. - # - # assert_raise do #Fails, no Exceptions are raised - # end - # - # assert_raise NameError do - # puts x #Raises NameError, so assertion succeeds - # end - def assert_raise(*exp, &b) - case exp.last - when String, Proc - msg = exp.pop - end - - begin - yield - rescue MiniTest::Skip => e - return e if exp.include? MiniTest::Skip - raise e - rescue Exception => e - expected = exp.any? { |ex| - if ex.instance_of? Module then - e.kind_of? ex - else - e.instance_of? ex - end - } - - assert expected, proc { - flunk(message(msg) {"#{mu_pp(exp)} exception expected, not #{mu_pp(e)}"}) - } - - return e - ensure - unless e - exp = exp.first if exp.size == 1 - - flunk(message(msg) {"#{mu_pp(exp)} expected but nothing was raised"}) - end - end - end - - # :call-seq: - # assert_raise_with_message(exception, expected, msg = nil, &block) - # - #Tests if the given block raises an exception with the expected - #message. - # - # assert_raise_with_message(RuntimeError, "foo") do - # nil #Fails, no Exceptions are raised - # end - # - # assert_raise_with_message(RuntimeError, "foo") do - # raise ArgumentError, "foo" #Fails, different Exception is raised - # end - # - # assert_raise_with_message(RuntimeError, "foo") do - # raise "bar" #Fails, RuntimeError is raised but the message differs - # end - # - # assert_raise_with_message(RuntimeError, "foo") do - # raise "foo" #Raises RuntimeError with the message, so assertion succeeds - # end - def assert_raise_with_message(exception, expected, msg = nil, &block) - case expected - when String - assert = :assert_equal - when Regexp - assert = :assert_match - else - raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}" - end - - ex = m = nil - EnvUtil.with_default_internal(expected.encoding) do - ex = assert_raise(exception, msg || proc {"Exception(#{exception}) with message matches to #{expected.inspect}"}) do - yield - end - m = ex.message - end - msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"} - - if assert == :assert_equal - assert_equal(expected, m, msg) - else - msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp m}" } - assert expected =~ m, msg - block.binding.eval("proc{|_|$~=_}").call($~) - end - ex - end - - def assert_warning(pat, msg = nil) - result = nil - stderr = EnvUtil.with_default_internal(pat.encoding) { - EnvUtil.verbose_warning { - result = yield - } - } - msg = message(msg) {diff pat, stderr} - assert(pat === stderr, msg) - result - end - - def assert_warn(*args) - assert_warning(*args) {$VERBOSE = false; yield} - end - - class << (AssertFile = Struct.new(:failure_message).new) - include CoreAssertions - def assert_file_predicate(predicate, *args) - if /\Anot_/ =~ predicate - predicate = $' - neg = " not" - end - result = File.__send__(predicate, *args) - result = !result if neg - mesg = "Expected file ".dup << args.shift.inspect - mesg << "#{neg} to be #{predicate}" - mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty? - mesg << " #{failure_message}" if failure_message - assert(result, mesg) - end - alias method_missing assert_file_predicate - - def for(message) - clone.tap {|a| a.failure_message = message} - end - end - - class AllFailures - attr_reader :failures - - def initialize - @count = 0 - @failures = {} - end - - def for(key) - @count += 1 - yield - rescue Exception => e - @failures[key] = [@count, e] - end - - def foreach(*keys) - keys.each do |key| - @count += 1 - begin - yield key - rescue Exception => e - @failures[key] = [@count, e] - end - end - end - - def message - i = 0 - total = @count.to_s - fmt = "%#{total.size}d" - @failures.map {|k, (n, v)| - v = v.message - "\n#{i+=1}. [#{fmt%n}/#{total}] Assertion for #{k.inspect}\n#{v.b.gsub(/^/, ' | ').force_encoding(v.encoding)}" - }.join("\n") - end - - def pass? - @failures.empty? - end - end - - # threads should respond to shift method. - # Array can be used. - def assert_join_threads(threads, message = nil) - errs = [] - values = [] - while th = threads.shift - begin - values << th.value - rescue Exception - errs << [th, $!] - th = nil - end - end - values - ensure - if th&.alive? - th.raise(Timeout::Error.new) - th.join rescue errs << [th, $!] - end - if !errs.empty? - msg = "exceptions on #{errs.length} threads:\n" + - errs.map {|t, err| - "#{t.inspect}:\n" + - RUBY_VERSION >= "2.5.0" ? err.full_message(highlight: false, order: :top) : err.message - }.join("\n---\n") - if message - msg = "#{message}\n#{msg}" - end - raise MiniTest::Assertion, msg - end - end - - def assert_all_assertions(msg = nil) - all = AllFailures.new - yield all - ensure - assert(all.pass?, message(msg) {all.message.chomp(".")}) - end - alias all_assertions assert_all_assertions - - def message(msg = nil, *args, &default) # :nodoc: - if Proc === msg - super(nil, *args) do - ary = [msg.call, (default.call if default)].compact.reject(&:empty?) - if 1 < ary.length - ary[0...-1] = ary[0...-1].map {|str| str.sub(/(? e - begin - trace = e.backtrace || ['unknown method'] - err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| "\t" + t } + trace = e.backtrace || ['unknown method'] + err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| "\t" + t } - if @stdout - _report "bye", Marshal.dump(err.join("\n")) - else - raise "failed to report a failure due to lack of @stdout" - end - rescue Errno::EPIPE;end + if @stdout + _report "bye", Marshal.dump(err.join("\n")) + else + raise "failed to report a failure due to lack of @stdout" + end exit ensure @stdin.close if @stdin @@ -163,26 +156,28 @@ def run(args = []) # :nodoc: def _report(res, *args) # :nodoc: @stdout.write(args.empty? ? "#{res}\n" : "#{res} #{args.pack("m0")}\n") + true + rescue Errno::EPIPE rescue TypeError => e abort("#{e.inspect} in _report(#{res.inspect}, #{args.inspect})\n#{e.backtrace.join("\n")}") end def puke(klass, meth, e) # :nodoc: - if e.is_a?(MiniTest::Skip) - new_e = MiniTest::Skip.new(e.message) + if e.is_a?(Test::Unit::PendedError) + new_e = Test::Unit::PendedError.new(e.message) new_e.set_backtrace(e.backtrace) e = new_e end - @partial_report << [klass.name, meth, e.is_a?(MiniTest::Assertion) ? e : ProxyError.new(e)] + @partial_report << [klass.name, meth, e.is_a?(Test::Unit::AssertionFailedError) ? e : ProxyError.new(e)] super end def record(suite, method, assertions, time, error) # :nodoc: case error when nil - when MiniTest::Assertion, MiniTest::Skip + when Test::Unit::AssertionFailedError, Test::Unit::PendedError case error.cause - when nil, MiniTest::Assertion, MiniTest::Skip + when nil, Test::Unit::AssertionFailedError, Test::Unit::PendedError else bt = error.backtrace error = error.class.new(error.message) @@ -201,11 +196,14 @@ def record(suite, method, assertions, time, error) # :nodoc: if $0 == __FILE__ module Test module Unit - class TestCase < MiniTest::Unit::TestCase # :nodoc: all + class TestCase # :nodoc: all undef on_parallel_worker? def on_parallel_worker? true end + def self.on_parallel_worker? + true + end end end end diff --git a/ruby/tool/lib/test/unit/testcase.rb b/ruby/tool/lib/test/unit/testcase.rb index 58cfbcab9..44d9ba7fd 100644 --- a/ruby/tool/lib/test/unit/testcase.rb +++ b/ruby/tool/lib/test/unit/testcase.rb @@ -1,25 +1,285 @@ # frozen_string_literal: true -require 'test/unit/assertions' +require_relative 'assertions' +require_relative '../../core_assertions' module Test module Unit - # remove silly TestCase class - remove_const(:TestCase) if defined?(self::TestCase) - class TestCase < MiniTest::Unit::TestCase # :nodoc: all - include Assertions + ## + # Provides a simple set of guards that you can use in your tests + # to skip execution if it is not applicable. These methods are + # mixed into TestCase as both instance and class methods so you + # can use them inside or outside of the test methods. + # + # def test_something_for_mri + # skip "bug 1234" if jruby? + # # ... + # end + # + # if windows? then + # # ... lots of test methods ... + # end - def on_parallel_worker? - false + module Guard + + ## + # Is this running on jruby? + + def jruby? platform = RUBY_PLATFORM + "java" == platform end + ## + # Is this running on mri? + + def mri? platform = RUBY_DESCRIPTION + /^ruby/ =~ platform + end + + ## + # Is this running on windows? + + def windows? platform = RUBY_PLATFORM + /mswin|mingw/ =~ platform + end + + ## + # Is this running on mingw? + + def mingw? platform = RUBY_PLATFORM + /mingw/ =~ platform + end + + end + + ## + # Provides before/after hooks for setup and teardown. These are + # meant for library writers, NOT for regular test authors. See + # #before_setup for an example. + + module LifecycleHooks + ## + # Runs before every test, after setup. This hook is meant for + # libraries to extend Test::Unit. It is not meant to be used by + # test developers. + # + # See #before_setup for an example. + + def after_setup; end + + ## + # Runs before every test, before setup. This hook is meant for + # libraries to extend Test::Unit. It is not meant to be used by + # test developers. + # + # As a simplistic example: + # + # module MyTestUnitPlugin + # def before_setup + # super + # # ... stuff to do before setup is run + # end + # + # def after_setup + # # ... stuff to do after setup is run + # super + # end + # + # def before_teardown + # super + # # ... stuff to do before teardown is run + # end + # + # def after_teardown + # # ... stuff to do after teardown is run + # super + # end + # end + # + # class Test::Unit::Runner::TestCase + # include MyTestUnitPlugin + # end + + def before_setup; end + + ## + # Runs after every test, before teardown. This hook is meant for + # libraries to extend Test::Unit. It is not meant to be used by + # test developers. + # + # See #before_setup for an example. + + def before_teardown; end + + ## + # Runs after every test, after teardown. This hook is meant for + # libraries to extend Test::Unit. It is not meant to be used by + # test developers. + # + # See #before_setup for an example. + + def after_teardown; end + end + + ## + # Subclass TestCase to create your own tests. Typically you'll want a + # TestCase subclass per implementation class. + # + # See Test::Unit::AssertionFailedErrors + + class TestCase + include Assertions + include CoreAssertions + + include LifecycleHooks + include Guard + extend Guard + + attr_reader :__name__ # :nodoc: + + PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, + Interrupt, SystemExit] # :nodoc: + + ## + # Runs the tests reporting the status to +runner+ + def run runner @options = runner.options - super runner + + trap "INFO" do + runner.report.each_with_index do |msg, i| + warn "\n%3d) %s" % [i + 1, msg] + end + warn '' + time = runner.start_time ? Time.now - runner.start_time : 0 + warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time] + runner.status $stderr + end if runner.info_signal + + start_time = Time.now + + result = "" + + begin + @passed = nil + self.before_setup + self.setup + self.after_setup + self.run_test self.__name__ + result = "." unless io? + time = Time.now - start_time + runner.record self.class, self.__name__, self._assertions, time, nil + @passed = true + rescue *PASSTHROUGH_EXCEPTIONS + raise + rescue Exception => e + @passed = Test::Unit::PendedError === e + time = Time.now - start_time + runner.record self.class, self.__name__, self._assertions, time, e + result = runner.puke self.class, self.__name__, e + ensure + %w{ before_teardown teardown after_teardown }.each do |hook| + begin + self.send hook + rescue *PASSTHROUGH_EXCEPTIONS + raise + rescue Exception => e + @passed = false + runner.record self.class, self.__name__, self._assertions, time, e + result = runner.puke self.class, self.__name__, e + end + end + trap 'INFO', 'DEFAULT' if runner.info_signal + end + result + end + + RUN_TEST_TRACE = "#{__FILE__}:#{__LINE__+3}:in `run_test'".freeze + def run_test(name) + progname, $0 = $0, "#{$0}: #{self.class}##{name}" + self.__send__(name) + ensure + $@.delete(RUN_TEST_TRACE) if $@ + $0 = progname + end + + def initialize name # :nodoc: + @__name__ = name + @__io__ = nil + @passed = nil + @@current = self # FIX: make thread local + end + + def self.current # :nodoc: + @@current # FIX: make thread local + end + + ## + # Return the output IO object + + def io + @__io__ = true + Test::Unit::Runner.output + end + + ## + # Have we hooked up the IO yet? + + def io? + @__io__ + end + + def self.reset # :nodoc: + @@test_suites = {} + @@test_suites[self] = true + end + + reset + + def self.inherited klass # :nodoc: + @@test_suites[klass] = true + super + end + + @test_order = :sorted + + class << self + attr_writer :test_order end def self.test_order - :sorted + defined?(@test_order) ? @test_order : superclass.test_order + end + + def self.test_suites # :nodoc: + @@test_suites.keys + end + + def self.test_methods # :nodoc: + public_instance_methods(true).grep(/^test/) + end + + ## + # Returns true if the test passed. + + def passed? + @passed + end + + ## + # Runs before every test. Use this to set up before each test + # run. + + def setup; end + + ## + # Runs after every test. Use this to clean up after each test + # run. + + def teardown; end + + def on_parallel_worker? + false end def self.method_added(name) @@ -27,7 +287,7 @@ def self.method_added(name) return unless name.to_s.start_with?("test_") @test_methods ||= {} if @test_methods[name] - warn "test/unit warning: method #{ self }##{ name } is redefined" + raise AssertionFailedError, "test/unit: method #{ self }##{ name } is redefined" end @test_methods[name] = true end diff --git a/ruby/tool/lib/vcs.rb b/ruby/tool/lib/vcs.rb index 3553ed51a..c41276e3b 100644 --- a/ruby/tool/lib/vcs.rb +++ b/ruby/tool/lib/vcs.rb @@ -23,102 +23,33 @@ def IO.pread(*args) popen(*args) {|f|f.read} end -if RUBY_VERSION < "2.0" - class IO - @orig_popen = method(:popen) - - if defined?(fork) - def self.popen(command, *rest, &block) - if command.kind_of?(Hash) - env = command - command = rest.shift - end - opts = rest.last - if opts.kind_of?(Hash) - dir = opts.delete(:chdir) - rest.pop if opts.empty? - opts.delete(:external_encoding) - end - - if block - @orig_popen.call("-", *rest) do |f| - if f - yield(f) - else - Dir.chdir(dir) if dir - ENV.replace(env) if env - exec(*command) - end - end - else - f = @orig_popen.call("-", *rest) - unless f - Dir.chdir(dir) if dir - ENV.replace(env) if env - exec(*command) - end - f - end - end - else - require 'shellwords' - def self.popen(command, *rest, &block) - if command.kind_of?(Hash) - env = command - oldenv = ENV.to_hash - command = rest.shift - end - opts = rest.last - if opts.kind_of?(Hash) - dir = opts.delete(:chdir) - rest.pop if opts.empty? - opts.delete(:external_encoding) - end - - command = command.shelljoin if Array === command - Dir.chdir(dir || ".") do - ENV.replace(env) if env - @orig_popen.call(command, *rest, &block) - ENV.replace(oldenv) if oldenv - end - end - end - end -else - module DebugPOpen - verbose, $VERBOSE = $VERBOSE, nil if RUBY_VERSION < "2.1" - refine IO.singleton_class do - def popen(*args) - VCS::DEBUG_OUT.puts args.inspect if $DEBUG - super - end - end - ensure - $VERBOSE = verbose unless verbose.nil? - end - using DebugPOpen - module DebugSystem - def system(*args) +module DebugPOpen + refine IO.singleton_class do + def popen(*args) VCS::DEBUG_OUT.puts args.inspect if $DEBUG - exception = false - opts = Hash.try_convert(args[-1]) - if RUBY_VERSION >= "2.6" - unless opts - opts = {} - args << opts - end - exception = opts.fetch(:exception) {opts[:exception] = true} - elsif opts - exception = opts.delete(:exception) {true} - args.pop if opts.empty? - end - ret = super(*args) - raise "Command failed with status (#$?): #{args[0]}" if exception and !ret - ret + super end end - module Kernel - prepend(DebugSystem) +end +using DebugPOpen +module DebugSystem + def system(*args) + VCS::DEBUG_OUT.puts args.inspect if $DEBUG + exception = false + opts = Hash.try_convert(args[-1]) + if RUBY_VERSION >= "2.6" + unless opts + opts = {} + args << opts + end + exception = opts.fetch(:exception) {opts[:exception] = true} + elsif opts + exception = opts.delete(:exception) {true} + args.pop if opts.empty? + end + ret = super(*args) + raise "Command failed with status (#$?): #{args[0]}" if exception and !ret + ret end end @@ -131,7 +62,8 @@ def self.register(dir, &pred) @@dirs << [dir, self, pred] end - def self.detect(path = '.', options = {}, parser = nil) + def self.detect(path = '.', options = {}, parser = nil, **opts) + options.update(opts) uplevel_limit = options.fetch(:uplevel_limit, 0) curr = path begin @@ -407,13 +339,11 @@ def branch_beginning(url) rev.to_i if rev end - def export_changelog(url, from, to, path) + def export_changelog(url = '.', from = nil, to = nil, _path = nil, path: _path) range = [to || 'HEAD', (from ? from+1 : branch_beginning(url))].compact.join(':') IO.popen({'TZ' => 'JST-9', 'LANG' => 'C', 'LC_ALL' => 'C'}, %W"#{COMMAND} log -r#{range} #{url}") do |r| - open(path, 'w') do |w| - IO.copy_stream(r, w) - end + IO.copy_stream(r, path) end end @@ -589,11 +519,11 @@ def export(revision, url, dir, keep_temp = false) def branch_beginning(url) cmd_read(%W[ #{COMMAND} log -n1 --format=format:%H - --author=matz --committer=matz --grep=has\ started + --author=matz --committer=matz --grep=started\\.$ #{url.to_str} -- version.h include/ruby/version.h]) end - def export_changelog(url, from, to, path) + def export_changelog(url = '@', from = nil, to = nil, _path = nil, path: _path, base_url: nil) svn = nil from, to = [from, to].map do |rev| rev or next @@ -609,50 +539,101 @@ def export_changelog(url, from, to, path) warn "no starting commit found", uplevel: 1 from = nil end - unless svn or system(*%W"#{COMMAND} fetch origin refs/notes/commits:refs/notes/commits", + if svn or system(*%W"#{COMMAND} fetch origin refs/notes/commits:refs/notes/commits", chdir: @srcdir, exception: false) - abort "Could not fetch notes/commits tree" - end - system(*%W"#{COMMAND} fetch origin refs/notes/log-fix:refs/notes/log-fix", + system(*%W"#{COMMAND} fetch origin refs/notes/log-fix:refs/notes/log-fix", chdir: @srcdir, exception: false) + else + warn "Could not fetch notes/commits tree", uplevel: 1 + end to ||= url.to_str if from arg = ["#{from}^..#{to}"] else arg = ["--since=25 Dec 00:00:00", to] end - if svn - format_changelog_as_svn(path, arg) + writer = + if svn + format_changelog_as_svn(path, arg) + else + if base_url == true + remote, = upstream + if remote &&= cmd_read(env, %W[#{COMMAND} remote get-url --no-push #{remote}]) + remote.chomp! + # hack to redirect git.r-l.o to github + remote.sub!(/\Agit@git\.ruby-lang\.org:/, 'git@github.com:ruby/') + remote.sub!(/\Agit@(.*?):(.*?)(?:\.git)?\z/, 'https://\1/\2/commit/') + end + base_url = remote + end + format_changelog(path, arg, base_url) + end + if !path or path == '-' + writer[$stdout] else - format_changelog(path, arg) + File.open(path, 'wb', &writer) end end - def format_changelog(path, arg) + LOG_FIX_REGEXP_SEPARATORS = '/!:;|,#%&' + + def format_changelog(path, arg, base_url = nil) env = {'TZ' => 'JST-9', 'LANG' => 'C', 'LC_ALL' => 'C'} - cmd = %W"#{COMMAND} log --format=medium --notes=commits --notes=log-fix --topo-order --no-merges" + cmd = %W"#{COMMAND} log --format=fuller --notes=commits --notes=log-fix --topo-order --no-merges" date = "--date=iso-local" unless system(env, *cmd, date, chdir: @srcdir, out: NullDevice, exception: false) date = "--date=iso" end cmd << date cmd.concat(arg) - File.open(path, 'w') do |w| + proc do |w| + w.print "-*- coding: utf-8 -*-\n\n" + w.print "base-url = #{base_url}\n\n" if base_url cmd_pipe(env, cmd, chdir: @srcdir) do |r| while s = r.gets("\ncommit ") + h, s = s.split(/^$/, 2) + h.gsub!(/^(?:(?:Author|Commit)(?:Date)?|Date): /, ' \&') if s.sub!(/\nNotes \(log-fix\):\n((?: +.*\n)+)/, '') fix = $1 - h, s = s.split(/^$/, 2) s = s.lines fix.each_line do |x| - if %r[^ +(\d+)s/(.+)/(.+)/] =~ x - s[$1.to_i][$2] = $3 + case x + when %r[^ +(\d+)s([#{LOG_FIX_REGEXP_SEPARATORS}])(.+)\2(.*)\2]o + n = $1.to_i + wrong = $3 + correct = $4 + begin + s[n][wrong] = correct + rescue IndexError + message = ["format_changelog failed to replace #{wrong.dump} with #{correct.dump} at #$1\n"] + from = [1, n-2].max + to = [s.size-1, n+2].min + s.each_with_index do |e, i| + next if i < from + break if to < i + message << "#{i}:#{e}" + end + raise message.join('') + end + when %r[^( +)(\d+)i([#{LOG_FIX_REGEXP_SEPARATORS}])(.*)\3]o + s[$2.to_i, 0] = "#{$1}#{$4}\n" + when %r[^ +(\d+)(?:,(\d+))?d] + n = $1.to_i + e = $2 + s[n..(e ? e.to_i : n)] = [] end end - s = [h, s.join('')].join('') + s = s.join('') + end + + if %r[^ +(https://github\.com/[^/]+/[^/]+/)commit/\h+\n(?=(?: +\n(?i: +Co-authored-by: .*\n)+)?(?:\n|\Z))] =~ s + issue = "#{$1}pull/" + s.gsub!(/\b[Ff]ix(?:e[sd])? \K#(?=\d+)/) {issue} end + s.gsub!(/ +\n/, "\n") - w.print s + s.sub!(/^Notes:/, ' \&') + w.print h, s end end end @@ -661,7 +642,7 @@ def format_changelog(path, arg) def format_changelog_as_svn(path, arg) cmd = %W"#{COMMAND} log --topo-order --no-notes -z --format=%an%n%at%n%B" cmd.concat(arg) - open(path, 'w') do |w| + proc do |w| sep = "-"*72 + "\n" w.print sep cmd_pipe(cmd) do |r| @@ -727,7 +708,7 @@ def commit(opts = {}) commits = cmd_read([COMMAND, "log", "--reverse", "--format=%H %ae %ce", "#{com}..@"], "rb").split("\n") commits.each_with_index do |l, i| - r, a, c = l.split + r, a, c = l.split(' ') dcommit = [COMMAND, "svn", "dcommit"] dcommit.insert(-2, "-n") if dryrun dcommit << "--add-author-from" unless a == c diff --git a/ruby/lib/webrick.rb b/ruby/tool/lib/webrick.rb similarity index 96% rename from ruby/lib/webrick.rb rename to ruby/tool/lib/webrick.rb index 1c0eb81db..b854b68db 100644 --- a/ruby/lib/webrick.rb +++ b/ruby/tool/lib/webrick.rb @@ -15,6 +15,11 @@ # WEBrick also includes tools for daemonizing a process and starting a process # at a higher privilege level and dropping permissions. # +# == Security +# +# *Warning:* WEBrick is not recommended for production. It only implements +# basic security checks. +# # == Starting an HTTP server # # To create a new WEBrick::HTTPServer that will listen to connections on port @@ -139,9 +144,9 @@ # servers. See WEBrick::HTTPAuth, WEBrick::HTTPAuth::BasicAuth and # WEBrick::HTTPAuth::DigestAuth. # -# == WEBrick as a Production Web Server +# == WEBrick as a daemonized Web Server # -# WEBrick can be run as a production server for small loads. +# WEBrick can be run as a daemonized server for small loads. # # === Daemonizing # diff --git a/ruby/lib/webrick/.document b/ruby/tool/lib/webrick/.document similarity index 100% rename from ruby/lib/webrick/.document rename to ruby/tool/lib/webrick/.document diff --git a/ruby/lib/webrick/accesslog.rb b/ruby/tool/lib/webrick/accesslog.rb similarity index 100% rename from ruby/lib/webrick/accesslog.rb rename to ruby/tool/lib/webrick/accesslog.rb diff --git a/ruby/lib/webrick/cgi.rb b/ruby/tool/lib/webrick/cgi.rb similarity index 100% rename from ruby/lib/webrick/cgi.rb rename to ruby/tool/lib/webrick/cgi.rb diff --git a/ruby/lib/webrick/compat.rb b/ruby/tool/lib/webrick/compat.rb similarity index 100% rename from ruby/lib/webrick/compat.rb rename to ruby/tool/lib/webrick/compat.rb diff --git a/ruby/lib/webrick/config.rb b/ruby/tool/lib/webrick/config.rb similarity index 100% rename from ruby/lib/webrick/config.rb rename to ruby/tool/lib/webrick/config.rb diff --git a/ruby/lib/webrick/cookie.rb b/ruby/tool/lib/webrick/cookie.rb similarity index 100% rename from ruby/lib/webrick/cookie.rb rename to ruby/tool/lib/webrick/cookie.rb diff --git a/ruby/lib/webrick/htmlutils.rb b/ruby/tool/lib/webrick/htmlutils.rb similarity index 100% rename from ruby/lib/webrick/htmlutils.rb rename to ruby/tool/lib/webrick/htmlutils.rb diff --git a/ruby/lib/webrick/httpauth.rb b/ruby/tool/lib/webrick/httpauth.rb similarity index 100% rename from ruby/lib/webrick/httpauth.rb rename to ruby/tool/lib/webrick/httpauth.rb diff --git a/ruby/lib/webrick/httpauth/authenticator.rb b/ruby/tool/lib/webrick/httpauth/authenticator.rb similarity index 98% rename from ruby/lib/webrick/httpauth/authenticator.rb rename to ruby/tool/lib/webrick/httpauth/authenticator.rb index 8655118a0..8f0eaa3ac 100644 --- a/ruby/lib/webrick/httpauth/authenticator.rb +++ b/ruby/tool/lib/webrick/httpauth/authenticator.rb @@ -85,7 +85,7 @@ def check_scheme(req) def log(meth, fmt, *args) msg = format("%s %s: ", @auth_scheme, @realm) msg << fmt % args - @logger.send(meth, msg) + @logger.__send__(meth, msg) end def error(fmt, *args) diff --git a/ruby/lib/webrick/httpauth/basicauth.rb b/ruby/tool/lib/webrick/httpauth/basicauth.rb similarity index 100% rename from ruby/lib/webrick/httpauth/basicauth.rb rename to ruby/tool/lib/webrick/httpauth/basicauth.rb diff --git a/ruby/lib/webrick/httpauth/digestauth.rb b/ruby/tool/lib/webrick/httpauth/digestauth.rb similarity index 100% rename from ruby/lib/webrick/httpauth/digestauth.rb rename to ruby/tool/lib/webrick/httpauth/digestauth.rb diff --git a/ruby/lib/webrick/httpauth/htdigest.rb b/ruby/tool/lib/webrick/httpauth/htdigest.rb similarity index 100% rename from ruby/lib/webrick/httpauth/htdigest.rb rename to ruby/tool/lib/webrick/httpauth/htdigest.rb diff --git a/ruby/lib/webrick/httpauth/htgroup.rb b/ruby/tool/lib/webrick/httpauth/htgroup.rb similarity index 100% rename from ruby/lib/webrick/httpauth/htgroup.rb rename to ruby/tool/lib/webrick/httpauth/htgroup.rb diff --git a/ruby/lib/webrick/httpauth/htpasswd.rb b/ruby/tool/lib/webrick/httpauth/htpasswd.rb similarity index 100% rename from ruby/lib/webrick/httpauth/htpasswd.rb rename to ruby/tool/lib/webrick/httpauth/htpasswd.rb diff --git a/ruby/lib/webrick/httpauth/userdb.rb b/ruby/tool/lib/webrick/httpauth/userdb.rb similarity index 100% rename from ruby/lib/webrick/httpauth/userdb.rb rename to ruby/tool/lib/webrick/httpauth/userdb.rb diff --git a/ruby/tool/lib/webrick/httpproxy.rb b/ruby/tool/lib/webrick/httpproxy.rb new file mode 100644 index 000000000..7607c3df8 --- /dev/null +++ b/ruby/tool/lib/webrick/httpproxy.rb @@ -0,0 +1,354 @@ +# frozen_string_literal: false +# +# httpproxy.rb -- HTTPProxy Class +# +# Author: IPR -- Internet Programming with Ruby -- writers +# Copyright (c) 2002 GOTO Kentaro +# Copyright (c) 2002 Internet Programming with Ruby writers. All rights +# reserved. +# +# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $ +# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $ + +require_relative "httpserver" +require "net/http" + +module WEBrick + + NullReader = Object.new # :nodoc: + class << NullReader # :nodoc: + def read(*args) + nil + end + alias gets read + end + + FakeProxyURI = Object.new # :nodoc: + class << FakeProxyURI # :nodoc: + def method_missing(meth, *args) + if %w(scheme host port path query userinfo).member?(meth.to_s) + return nil + end + super + end + end + + # :startdoc: + + ## + # An HTTP Proxy server which proxies GET, HEAD and POST requests. + # + # To create a simple proxy server: + # + # require 'webrick' + # require 'webrick/httpproxy' + # + # proxy = WEBrick::HTTPProxyServer.new Port: 8000 + # + # trap 'INT' do proxy.shutdown end + # trap 'TERM' do proxy.shutdown end + # + # proxy.start + # + # See ::new for proxy-specific configuration items. + # + # == Modifying proxied responses + # + # To modify content the proxy server returns use the +:ProxyContentHandler+ + # option: + # + # handler = proc do |req, res| + # if res['content-type'] == 'text/plain' then + # res.body << "\nThis content was proxied!\n" + # end + # end + # + # proxy = + # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler + + class HTTPProxyServer < HTTPServer + + ## + # Proxy server configurations. The proxy server handles the following + # configuration items in addition to those supported by HTTPServer: + # + # :ProxyAuthProc:: Called with a request and response to authorize a + # request + # :ProxyVia:: Appended to the via header + # :ProxyURI:: The proxy server's URI + # :ProxyContentHandler:: Called with a request and response and allows + # modification of the response + # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60 + # seconds for read operations + + def initialize(config={}, default=Config::HTTP) + super(config, default) + c = @config + @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}" + end + + # :stopdoc: + def service(req, res) + if req.request_method == "CONNECT" + do_CONNECT(req, res) + elsif req.unparsed_uri =~ %r!^http://! + proxy_service(req, res) + else + super(req, res) + end + end + + def proxy_auth(req, res) + if proc = @config[:ProxyAuthProc] + proc.call(req, res) + end + req.header.delete("proxy-authorization") + end + + def proxy_uri(req, res) + # should return upstream proxy server's URI + return @config[:ProxyURI] + end + + def proxy_service(req, res) + # Proxy Authentication + proxy_auth(req, res) + + begin + public_send("do_#{req.request_method}", req, res) + rescue NoMethodError + raise HTTPStatus::MethodNotAllowed, + "unsupported method `#{req.request_method}'." + rescue => err + logger.debug("#{err.class}: #{err.message}") + raise HTTPStatus::ServiceUnavailable, err.message + end + + # Process contents + if handler = @config[:ProxyContentHandler] + handler.call(req, res) + end + end + + def do_CONNECT(req, res) + # Proxy Authentication + proxy_auth(req, res) + + ua = Thread.current[:WEBrickSocket] # User-Agent + raise HTTPStatus::InternalServerError, + "[BUG] cannot get socket" unless ua + + host, port = req.unparsed_uri.split(":", 2) + # Proxy authentication for upstream proxy server + if proxy = proxy_uri(req, res) + proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0" + if proxy.userinfo + credentials = "Basic " + [proxy.userinfo].pack("m0") + end + host, port = proxy.host, proxy.port + end + + begin + @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.") + os = TCPSocket.new(host, port) # origin server + + if proxy + @logger.debug("CONNECT: sending a Request-Line") + os << proxy_request_line << CRLF + @logger.debug("CONNECT: > #{proxy_request_line}") + if credentials + @logger.debug("CONNECT: sending credentials") + os << "Proxy-Authorization: " << credentials << CRLF + end + os << CRLF + proxy_status_line = os.gets(LF) + @logger.debug("CONNECT: read Status-Line from the upstream server") + @logger.debug("CONNECT: < #{proxy_status_line}") + if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line + while line = os.gets(LF) + break if /\A(#{CRLF}|#{LF})\z/om =~ line + end + else + raise HTTPStatus::BadGateway + end + end + @logger.debug("CONNECT #{host}:#{port}: succeeded") + res.status = HTTPStatus::RC_OK + rescue => ex + @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'") + res.set_error(ex) + raise HTTPStatus::EOFError + ensure + if handler = @config[:ProxyContentHandler] + handler.call(req, res) + end + res.send_response(ua) + access_log(@config, req, res) + + # Should clear request-line not to send the response twice. + # see: HTTPServer#run + req.parse(NullReader) rescue nil + end + + begin + while fds = IO::select([ua, os]) + if fds[0].member?(ua) + buf = ua.readpartial(1024); + @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent") + os.write(buf) + elsif fds[0].member?(os) + buf = os.readpartial(1024); + @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}") + ua.write(buf) + end + end + rescue + os.close + @logger.debug("CONNECT #{host}:#{port}: closed") + end + + raise HTTPStatus::EOFError + end + + def do_GET(req, res) + perform_proxy_request(req, res, Net::HTTP::Get) + end + + def do_HEAD(req, res) + perform_proxy_request(req, res, Net::HTTP::Head) + end + + def do_POST(req, res) + perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader) + end + + def do_OPTIONS(req, res) + res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT" + end + + private + + # Some header fields should not be transferred. + HopByHop = %w( connection keep-alive proxy-authenticate upgrade + proxy-authorization te trailers transfer-encoding ) + ShouldNotTransfer = %w( set-cookie proxy-connection ) + def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end + + def choose_header(src, dst) + connections = split_field(src['connection']) + src.each{|key, value| + key = key.downcase + if HopByHop.member?(key) || # RFC2616: 13.5.1 + connections.member?(key) || # RFC2616: 14.10 + ShouldNotTransfer.member?(key) # pragmatics + @logger.debug("choose_header: `#{key}: #{value}'") + next + end + dst[key] = value + } + end + + # Net::HTTP is stupid about the multiple header fields. + # Here is workaround: + def set_cookie(src, dst) + if str = src['set-cookie'] + cookies = [] + str.split(/,\s*/).each{|token| + if /^[^=]+;/o =~ token + cookies[-1] << ", " << token + elsif /=/o =~ token + cookies << token + else + cookies[-1] << ", " << token + end + } + dst.cookies.replace(cookies) + end + end + + def set_via(h) + if @config[:ProxyVia] + if h['via'] + h['via'] << ", " << @via + else + h['via'] = @via + end + end + end + + def setup_proxy_header(req, res) + # Choose header fields to transfer + header = Hash.new + choose_header(req, header) + set_via(header) + return header + end + + def setup_upstream_proxy_authentication(req, res, header) + if upstream = proxy_uri(req, res) + if upstream.userinfo + header['proxy-authorization'] = + "Basic " + [upstream.userinfo].pack("m0") + end + return upstream + end + return FakeProxyURI + end + + def create_net_http(uri, upstream) + Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port) + end + + def perform_proxy_request(req, res, req_class, body_stream = nil) + uri = req.request_uri + path = uri.path.dup + path << "?" << uri.query if uri.query + header = setup_proxy_header(req, res) + upstream = setup_upstream_proxy_authentication(req, res, header) + + body_tmp = [] + http = create_net_http(uri, upstream) + req_fib = Fiber.new do + http.start do + if @config[:ProxyTimeout] + ################################## these issues are + http.open_timeout = 30 # secs # necessary (maybe because + http.read_timeout = 60 # secs # Ruby's bug, but why?) + ################################## + end + if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i + header['Transfer-Encoding'] = 'chunked' + end + http_req = req_class.new(path, header) + http_req.body_stream = body_stream if body_stream + http.request(http_req) do |response| + # Persistent connection requirements are mysterious for me. + # So I will close the connection in every response. + res['proxy-connection'] = "close" + res['connection'] = "close" + + # stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse + res.status = response.code.to_i + res.chunked = response.chunked? + choose_header(response, res) + set_cookie(response, res) + set_via(res) + response.read_body do |buf| + body_tmp << buf + Fiber.yield # wait for res.body Proc#call + end + end # http.request + end + end + req_fib.resume # read HTTP response headers and first chunk of the body + res.body = ->(socket) do + while buf = body_tmp.shift + socket.write(buf) + buf.clear + req_fib.resume # continue response.read_body + end + end + end + # :stopdoc: + end +end diff --git a/ruby/lib/webrick/httprequest.rb b/ruby/tool/lib/webrick/httprequest.rb similarity index 96% rename from ruby/lib/webrick/httprequest.rb rename to ruby/tool/lib/webrick/httprequest.rb index 87dc87917..d34eac7ec 100644 --- a/ruby/lib/webrick/httprequest.rb +++ b/ruby/tool/lib/webrick/httprequest.rb @@ -9,6 +9,7 @@ # # $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $ +require 'fiber' require 'uri' require_relative 'httpversion' require_relative 'httpstatus' @@ -226,9 +227,9 @@ def parse(socket=nil) raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'." end - if /close/io =~ self["connection"] + if /\Aclose\z/io =~ self["connection"] @keep_alive = false - elsif /keep-alive/io =~ self["connection"] + elsif /\Akeep-alive\z/io =~ self["connection"] @keep_alive = true elsif @http_version < "1.1" @keep_alive = false @@ -273,13 +274,17 @@ def body_reader self end - # for IO.copy_stream. Note: we may return a larger string than +size+ - # here; but IO.copy_stream does not care. + # for IO.copy_stream. def readpartial(size, buf = ''.b) # :nodoc res = @body_tmp.shift or raise EOFError, 'end of file reached' + if res.length > size + @body_tmp.unshift(res[size..-1]) + res = res[0..size - 1] + end buf.replace(res) res.clear - @body_rd.resume # get more chunks + # get more chunks - check alive? because we can take a partial chunk + @body_rd.resume if @body_rd.alive? buf end @@ -503,7 +508,7 @@ def read_body(socket, block) return unless socket if tc = self['transfer-encoding'] case tc - when /chunked/io then read_chunked(socket, block) + when /\Achunked\z/io then read_chunked(socket, block) else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}." end elsif self['content-length'] || @remaining_size @@ -517,7 +522,7 @@ def read_body(socket, block) if @remaining_size > 0 && @socket.eof? raise HTTPStatus::BadRequest, "invalid body size." end - elsif BODY_CONTAINABLE_METHODS.member?(@request_method) + elsif BODY_CONTAINABLE_METHODS.member?(@request_method) && !@socket.eof raise HTTPStatus::LengthRequired end return @body diff --git a/ruby/lib/webrick/httpresponse.rb b/ruby/tool/lib/webrick/httpresponse.rb similarity index 100% rename from ruby/lib/webrick/httpresponse.rb rename to ruby/tool/lib/webrick/httpresponse.rb diff --git a/ruby/lib/webrick/https.rb b/ruby/tool/lib/webrick/https.rb similarity index 100% rename from ruby/lib/webrick/https.rb rename to ruby/tool/lib/webrick/https.rb diff --git a/ruby/lib/webrick/httpserver.rb b/ruby/tool/lib/webrick/httpserver.rb similarity index 100% rename from ruby/lib/webrick/httpserver.rb rename to ruby/tool/lib/webrick/httpserver.rb diff --git a/ruby/lib/webrick/httpservlet.rb b/ruby/tool/lib/webrick/httpservlet.rb similarity index 100% rename from ruby/lib/webrick/httpservlet.rb rename to ruby/tool/lib/webrick/httpservlet.rb diff --git a/ruby/lib/webrick/httpservlet/abstract.rb b/ruby/tool/lib/webrick/httpservlet/abstract.rb similarity index 100% rename from ruby/lib/webrick/httpservlet/abstract.rb rename to ruby/tool/lib/webrick/httpservlet/abstract.rb diff --git a/ruby/lib/webrick/httpservlet/cgi_runner.rb b/ruby/tool/lib/webrick/httpservlet/cgi_runner.rb similarity index 100% rename from ruby/lib/webrick/httpservlet/cgi_runner.rb rename to ruby/tool/lib/webrick/httpservlet/cgi_runner.rb diff --git a/ruby/lib/webrick/httpservlet/cgihandler.rb b/ruby/tool/lib/webrick/httpservlet/cgihandler.rb similarity index 100% rename from ruby/lib/webrick/httpservlet/cgihandler.rb rename to ruby/tool/lib/webrick/httpservlet/cgihandler.rb diff --git a/ruby/lib/webrick/httpservlet/erbhandler.rb b/ruby/tool/lib/webrick/httpservlet/erbhandler.rb similarity index 100% rename from ruby/lib/webrick/httpservlet/erbhandler.rb rename to ruby/tool/lib/webrick/httpservlet/erbhandler.rb diff --git a/ruby/lib/webrick/httpservlet/filehandler.rb b/ruby/tool/lib/webrick/httpservlet/filehandler.rb similarity index 97% rename from ruby/lib/webrick/httpservlet/filehandler.rb rename to ruby/tool/lib/webrick/httpservlet/filehandler.rb index 7cac05d81..010df0e91 100644 --- a/ruby/lib/webrick/httpservlet/filehandler.rb +++ b/ruby/tool/lib/webrick/httpservlet/filehandler.rb @@ -212,6 +212,15 @@ def initialize(server, root, options={}, default=Config::FileHandler) # :stopdoc: + def set_filesystem_encoding(str) + enc = Encoding.find('filesystem') + if enc == Encoding::US_ASCII + str.b + else + str.dup.force_encoding(enc) + end + end + def service(req, res) # if this class is mounted on "/" and /~username is requested. # we're going to override path information before invoking service. @@ -298,7 +307,7 @@ def prevent_directory_traversal(req, res) end def exec_handler(req, res) - raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root + raise HTTPStatus::NotFound, "`#{req.path}' not found." unless @root if set_filename(req, res) handler = get_handler(req, res) call_callback(:HandlerCallback, req, res) @@ -324,11 +333,12 @@ def get_handler(req, res) end def set_filename(req, res) - res.filename = @root.dup + res.filename = @root path_info = req.path_info.scan(%r|/[^/]*|) path_info.unshift("") # dummy for checking @root dir while base = path_info.first + base = set_filesystem_encoding(base) break if base == "/" break unless File.directory?(File.expand_path(res.filename + base)) shift_path_info(req, res, path_info) @@ -336,6 +346,7 @@ def set_filename(req, res) end if base = path_info.first + base = set_filesystem_encoding(base) if base == "/" if file = search_index_file(req, res) shift_path_info(req, res, path_info, file) @@ -364,7 +375,7 @@ def check_filename(req, res, name) def shift_path_info(req, res, path_info, base=nil) tmp = path_info.shift - base = base || tmp + base = base || set_filesystem_encoding(tmp) req.path_info = path_info.join req.script_name << base res.filename = File.expand_path(res.filename + base) diff --git a/ruby/lib/webrick/httpservlet/prochandler.rb b/ruby/tool/lib/webrick/httpservlet/prochandler.rb similarity index 100% rename from ruby/lib/webrick/httpservlet/prochandler.rb rename to ruby/tool/lib/webrick/httpservlet/prochandler.rb diff --git a/ruby/lib/webrick/httpstatus.rb b/ruby/tool/lib/webrick/httpstatus.rb similarity index 100% rename from ruby/lib/webrick/httpstatus.rb rename to ruby/tool/lib/webrick/httpstatus.rb diff --git a/ruby/lib/webrick/httputils.rb b/ruby/tool/lib/webrick/httputils.rb similarity index 99% rename from ruby/lib/webrick/httputils.rb rename to ruby/tool/lib/webrick/httputils.rb index 76d4bd0dc..f1b9ddf9f 100644 --- a/ruby/lib/webrick/httputils.rb +++ b/ruby/tool/lib/webrick/httputils.rb @@ -72,6 +72,7 @@ def normalize_path(path) "json" => "application/json", "lha" => "application/octet-stream", "lzh" => "application/octet-stream", + "mjs" => "application/javascript", "mov" => "video/quicktime", "mpe" => "video/mpeg", "mpeg" => "video/mpeg", diff --git a/ruby/lib/webrick/httpversion.rb b/ruby/tool/lib/webrick/httpversion.rb similarity index 100% rename from ruby/lib/webrick/httpversion.rb rename to ruby/tool/lib/webrick/httpversion.rb diff --git a/ruby/lib/webrick/log.rb b/ruby/tool/lib/webrick/log.rb similarity index 100% rename from ruby/lib/webrick/log.rb rename to ruby/tool/lib/webrick/log.rb diff --git a/ruby/tool/lib/webrick/server.rb b/ruby/tool/lib/webrick/server.rb new file mode 100644 index 000000000..fd6b7a61b --- /dev/null +++ b/ruby/tool/lib/webrick/server.rb @@ -0,0 +1,381 @@ +# frozen_string_literal: false +# +# server.rb -- GenericServer Class +# +# Author: IPR -- Internet Programming with Ruby -- writers +# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou +# Copyright (c) 2002 Internet Programming with Ruby writers. All rights +# reserved. +# +# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $ + +require 'socket' +require_relative 'config' +require_relative 'log' + +module WEBrick + + ## + # Server error exception + + class ServerError < StandardError; end + + ## + # Base server class + + class SimpleServer + + ## + # A SimpleServer only yields when you start it + + def SimpleServer.start + yield + end + end + + ## + # A generic module for daemonizing a process + + class Daemon + + ## + # Performs the standard operations for daemonizing a process. Runs a + # block, if given. + + def Daemon.start + Process.daemon + File.umask(0) + yield if block_given? + end + end + + ## + # Base TCP server class. You must subclass GenericServer and provide a #run + # method. + + class GenericServer + + ## + # The server status. One of :Stop, :Running or :Shutdown + + attr_reader :status + + ## + # The server configuration + + attr_reader :config + + ## + # The server logger. This is independent from the HTTP access log. + + attr_reader :logger + + ## + # Tokens control the number of outstanding clients. The + # :MaxClients configuration sets this. + + attr_reader :tokens + + ## + # Sockets listening for connections. + + attr_reader :listeners + + ## + # Creates a new generic server from +config+. The default configuration + # comes from +default+. + + def initialize(config={}, default=Config::General) + @config = default.dup.update(config) + @status = :Stop + @config[:Logger] ||= Log::new + @logger = @config[:Logger] + + @tokens = Thread::SizedQueue.new(@config[:MaxClients]) + @config[:MaxClients].times{ @tokens.push(nil) } + + webrickv = WEBrick::VERSION + rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" + @logger.info("WEBrick #{webrickv}") + @logger.info("ruby #{rubyv}") + + @listeners = [] + @shutdown_pipe = nil + unless @config[:DoNotListen] + raise ArgumentError, "Port must an integer" unless @config[:Port].to_s == @config[:Port].to_i.to_s + + @config[:Port] = @config[:Port].to_i + if @config[:Listen] + warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1) + end + listen(@config[:BindAddress], @config[:Port]) + if @config[:Port] == 0 + @config[:Port] = @listeners[0].addr[1] + end + end + end + + ## + # Retrieves +key+ from the configuration + + def [](key) + @config[key] + end + + ## + # Adds listeners from +address+ and +port+ to the server. See + # WEBrick::Utils::create_listeners for details. + + def listen(address, port) + @listeners += Utils::create_listeners(address, port) + end + + ## + # Starts the server and runs the +block+ for each connection. This method + # does not return until the server is stopped from a signal handler or + # another thread using #stop or #shutdown. + # + # If the block raises a subclass of StandardError the exception is logged + # and ignored. If an IOError or Errno::EBADF exception is raised the + # exception is ignored. If an Exception subclass is raised the exception + # is logged and re-raised which stops the server. + # + # To completely shut down a server call #shutdown from ensure: + # + # server = WEBrick::GenericServer.new + # # or WEBrick::HTTPServer.new + # + # begin + # server.start + # ensure + # server.shutdown + # end + + def start(&block) + raise ServerError, "already started." if @status != :Stop + server_type = @config[:ServerType] || SimpleServer + + setup_shutdown_pipe + + server_type.start{ + @logger.info \ + "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" + @status = :Running + call_callback(:StartCallback) + + shutdown_pipe = @shutdown_pipe + + thgroup = ThreadGroup.new + begin + while @status == :Running + begin + sp = shutdown_pipe[0] + if svrs = IO.select([sp, *@listeners]) + if svrs[0].include? sp + # swallow shutdown pipe + buf = String.new + nil while String === + sp.read_nonblock([sp.nread, 8].max, buf, exception: false) + break + end + svrs[0].each{|svr| + @tokens.pop # blocks while no token is there. + if sock = accept_client(svr) + unless config[:DoNotReverseLookup].nil? + sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup] + end + th = start_thread(sock, &block) + th[:WEBrickThread] = true + thgroup.add(th) + else + @tokens.push(nil) + end + } + end + rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex + # if the listening socket was closed in GenericServer#shutdown, + # IO::select raise it. + rescue StandardError => ex + msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" + @logger.error msg + rescue Exception => ex + @logger.fatal ex + raise + end + end + ensure + cleanup_shutdown_pipe(shutdown_pipe) + cleanup_listener + @status = :Shutdown + @logger.info "going to shutdown ..." + thgroup.list.each{|th| th.join if th[:WEBrickThread] } + call_callback(:StopCallback) + @logger.info "#{self.class}#start done." + @status = :Stop + end + } + end + + ## + # Stops the server from accepting new connections. + + def stop + if @status == :Running + @status = :Shutdown + end + + alarm_shutdown_pipe {|f| f.write_nonblock("\0")} + end + + ## + # Shuts down the server and all listening sockets. New listeners must be + # provided to restart the server. + + def shutdown + stop + + alarm_shutdown_pipe(&:close) + end + + ## + # You must subclass GenericServer and implement \#run which accepts a TCP + # client socket + + def run(sock) + @logger.fatal "run() must be provided by user." + end + + private + + # :stopdoc: + + ## + # Accepts a TCP client socket from the TCP server socket +svr+ and returns + # the client socket. + + def accept_client(svr) + case sock = svr.to_io.accept_nonblock(exception: false) + when :wait_readable + nil + else + if svr.respond_to?(:start_immediately) + sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context) + sock.sync_close = true + # we cannot do OpenSSL::SSL::SSLSocket#accept here because + # a slow client can prevent us from accepting connections + # from other clients + end + sock + end + rescue Errno::ECONNRESET, Errno::ECONNABORTED, + Errno::EPROTO, Errno::EINVAL + nil + rescue StandardError => ex + msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" + @logger.error msg + nil + end + + ## + # Starts a server thread for the client socket +sock+ that runs the given + # +block+. + # + # Sets the socket to the :WEBrickSocket thread local variable + # in the thread. + # + # If any errors occur in the block they are logged and handled. + + def start_thread(sock, &block) + Thread.start{ + begin + Thread.current[:WEBrickSocket] = sock + begin + addr = sock.peeraddr + @logger.debug "accept: #{addr[3]}:#{addr[1]}" + rescue SocketError + @logger.debug "accept:
      " + raise + end + if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately] + WEBrick::Utils.timeout(@config[:RequestTimeout]) do + begin + sock.accept # OpenSSL::SSL::SSLSocket#accept + rescue Errno::ECONNRESET, Errno::ECONNABORTED, + Errno::EPROTO, Errno::EINVAL + Thread.exit + end + end + end + call_callback(:AcceptCallback, sock) + block ? block.call(sock) : run(sock) + rescue Errno::ENOTCONN + @logger.debug "Errno::ENOTCONN raised" + rescue ServerError => ex + msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" + @logger.error msg + rescue Exception => ex + @logger.error ex + ensure + @tokens.push(nil) + Thread.current[:WEBrickSocket] = nil + if addr + @logger.debug "close: #{addr[3]}:#{addr[1]}" + else + @logger.debug "close:
      " + end + sock.close + end + } + end + + ## + # Calls the callback +callback_name+ from the configuration with +args+ + + def call_callback(callback_name, *args) + @config[callback_name]&.call(*args) + end + + def setup_shutdown_pipe + return @shutdown_pipe ||= IO.pipe + end + + def cleanup_shutdown_pipe(shutdown_pipe) + @shutdown_pipe = nil + shutdown_pipe&.each(&:close) + end + + def alarm_shutdown_pipe + _, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe. + if pipe + if !pipe.closed? + begin + yield pipe + rescue IOError # closed by another thread. + end + end + end + end + + def cleanup_listener + @listeners.each{|s| + if @logger.debug? + addr = s.addr + @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})") + end + begin + s.shutdown + rescue Errno::ENOTCONN + # when `Errno::ENOTCONN: Socket is not connected' on some platforms, + # call #close instead of #shutdown. + # (ignore @config[:ShutdownSocketWithoutClose]) + s.close + else + unless @config[:ShutdownSocketWithoutClose] + s.close + end + end + } + @listeners.clear + end + end # end of GenericServer +end diff --git a/ruby/lib/webrick/ssl.rb b/ruby/tool/lib/webrick/ssl.rb similarity index 98% rename from ruby/lib/webrick/ssl.rb rename to ruby/tool/lib/webrick/ssl.rb index d12508352..e448095a1 100644 --- a/ruby/lib/webrick/ssl.rb +++ b/ruby/tool/lib/webrick/ssl.rb @@ -122,7 +122,7 @@ def create_self_signed_cert(bits, cn, comment) ef.issuer_certificate = cert cert.extensions = [ ef.create_extension("basicConstraints","CA:FALSE"), - ef.create_extension("keyUsage", "keyEncipherment"), + ef.create_extension("keyUsage", "keyEncipherment, digitalSignature, keyAgreement, dataEncipherment"), ef.create_extension("subjectKeyIdentifier", "hash"), ef.create_extension("extendedKeyUsage", "serverAuth"), ef.create_extension("nsComment", comment), @@ -130,7 +130,7 @@ def create_self_signed_cert(bits, cn, comment) aki = ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") cert.add_extension(aki) - cert.sign(rsa, OpenSSL::Digest::SHA256.new) + cert.sign(rsa, "SHA256") return [ cert, rsa ] end diff --git a/ruby/tool/lib/webrick/utils.rb b/ruby/tool/lib/webrick/utils.rb new file mode 100644 index 000000000..a96d6f03f --- /dev/null +++ b/ruby/tool/lib/webrick/utils.rb @@ -0,0 +1,265 @@ +# frozen_string_literal: false +# +# utils.rb -- Miscellaneous utilities +# +# Author: IPR -- Internet Programming with Ruby -- writers +# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou +# Copyright (c) 2002 Internet Programming with Ruby writers. All rights +# reserved. +# +# $IPR: utils.rb,v 1.10 2003/02/16 22:22:54 gotoyuzo Exp $ + +require 'socket' +require 'io/nonblock' +require 'etc' + +module WEBrick + module Utils + ## + # Sets IO operations on +io+ to be non-blocking + def set_non_blocking(io) + io.nonblock = true if io.respond_to?(:nonblock=) + end + module_function :set_non_blocking + + ## + # Sets the close on exec flag for +io+ + def set_close_on_exec(io) + io.close_on_exec = true if io.respond_to?(:close_on_exec=) + end + module_function :set_close_on_exec + + ## + # Changes the process's uid and gid to the ones of +user+ + def su(user) + if pw = Etc.getpwnam(user) + Process::initgroups(user, pw.gid) + Process::Sys::setgid(pw.gid) + Process::Sys::setuid(pw.uid) + else + warn("WEBrick::Utils::su doesn't work on this platform", uplevel: 1) + end + end + module_function :su + + ## + # The server hostname + def getservername + Socket::gethostname + end + module_function :getservername + + ## + # Creates TCP server sockets bound to +address+:+port+ and returns them. + # + # It will create IPV4 and IPV6 sockets on all interfaces. + def create_listeners(address, port) + unless port + raise ArgumentError, "must specify port" + end + sockets = Socket.tcp_server_sockets(address, port) + sockets = sockets.map {|s| + s.autoclose = false + ts = TCPServer.for_fd(s.fileno) + s.close + ts + } + return sockets + end + module_function :create_listeners + + ## + # Characters used to generate random strings + RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + "abcdefghijklmnopqrstuvwxyz" + + ## + # Generates a random string of length +len+ + def random_string(len) + rand_max = RAND_CHARS.bytesize + ret = "" + len.times{ ret << RAND_CHARS[rand(rand_max)] } + ret + end + module_function :random_string + + ########### + + require "timeout" + require "singleton" + + ## + # Class used to manage timeout handlers across multiple threads. + # + # Timeout handlers should be managed by using the class methods which are + # synchronized. + # + # id = TimeoutHandler.register(10, Timeout::Error) + # begin + # sleep 20 + # puts 'foo' + # ensure + # TimeoutHandler.cancel(id) + # end + # + # will raise Timeout::Error + # + # id = TimeoutHandler.register(10, Timeout::Error) + # begin + # sleep 5 + # puts 'foo' + # ensure + # TimeoutHandler.cancel(id) + # end + # + # will print 'foo' + # + class TimeoutHandler + include Singleton + + ## + # Mutex used to synchronize access across threads + TimeoutMutex = Thread::Mutex.new # :nodoc: + + ## + # Registers a new timeout handler + # + # +time+:: Timeout in seconds + # +exception+:: Exception to raise when timeout elapsed + def TimeoutHandler.register(seconds, exception) + at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds + instance.register(Thread.current, at, exception) + end + + ## + # Cancels the timeout handler +id+ + def TimeoutHandler.cancel(id) + instance.cancel(Thread.current, id) + end + + def self.terminate + instance.terminate + end + + ## + # Creates a new TimeoutHandler. You should use ::register and ::cancel + # instead of creating the timeout handler directly. + def initialize + TimeoutMutex.synchronize{ + @timeout_info = Hash.new + } + @queue = Thread::Queue.new + @watcher = nil + end + + # :nodoc: + private \ + def watch + to_interrupt = [] + while true + now = Process.clock_gettime(Process::CLOCK_MONOTONIC) + wakeup = nil + to_interrupt.clear + TimeoutMutex.synchronize{ + @timeout_info.each {|thread, ary| + next unless ary + ary.each{|info| + time, exception = *info + if time < now + to_interrupt.push [thread, info.object_id, exception] + elsif !wakeup || time < wakeup + wakeup = time + end + } + } + } + to_interrupt.each {|arg| interrupt(*arg)} + if !wakeup + @queue.pop + elsif (wakeup -= now) > 0 + begin + (th = Thread.start {@queue.pop}).join(wakeup) + ensure + th&.kill&.join + end + end + @queue.clear + end + end + + # :nodoc: + private \ + def watcher + (w = @watcher)&.alive? and return w # usual case + TimeoutMutex.synchronize{ + (w = @watcher)&.alive? and next w # pathological check + @watcher = Thread.start(&method(:watch)) + } + end + + ## + # Interrupts the timeout handler +id+ and raises +exception+ + def interrupt(thread, id, exception) + if cancel(thread, id) && thread.alive? + thread.raise(exception, "execution timeout") + end + end + + ## + # Registers a new timeout handler + # + # +time+:: Timeout in seconds + # +exception+:: Exception to raise when timeout elapsed + def register(thread, time, exception) + info = nil + TimeoutMutex.synchronize{ + (@timeout_info[thread] ||= []) << (info = [time, exception]) + } + @queue.push nil + watcher + return info.object_id + end + + ## + # Cancels the timeout handler +id+ + def cancel(thread, id) + TimeoutMutex.synchronize{ + if ary = @timeout_info[thread] + ary.delete_if{|info| info.object_id == id } + if ary.empty? + @timeout_info.delete(thread) + end + return true + end + return false + } + end + + ## + def terminate + TimeoutMutex.synchronize{ + @timeout_info.clear + @watcher&.kill&.join + } + end + end + + ## + # Executes the passed block and raises +exception+ if execution takes more + # than +seconds+. + # + # If +seconds+ is zero or nil, simply executes the block + def timeout(seconds, exception=Timeout::Error) + return yield if seconds.nil? or seconds.zero? + # raise ThreadError, "timeout within critical session" if Thread.critical + id = TimeoutHandler.register(seconds, exception) + begin + yield(seconds) + ensure + TimeoutHandler.cancel(id) + end + end + module_function :timeout + end +end diff --git a/ruby/tool/lib/webrick/version.rb b/ruby/tool/lib/webrick/version.rb new file mode 100644 index 000000000..b62988bdb --- /dev/null +++ b/ruby/tool/lib/webrick/version.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: false +#-- +# version.rb -- version and release date +# +# Author: IPR -- Internet Programming with Ruby -- writers +# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU +# Copyright (c) 2003 Internet Programming with Ruby writers. All rights +# reserved. +# +# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $ + +module WEBrick + + ## + # The WEBrick version + + VERSION = "1.7.0" +end diff --git a/ruby/tool/m4/_colorize_result_prepare.m4 b/ruby/tool/m4/_colorize_result_prepare.m4 index cc2bbaa70..8439acf3e 100644 --- a/ruby/tool/m4/_colorize_result_prepare.m4 +++ b/ruby/tool/m4/_colorize_result_prepare.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([_COLORIZE_RESULT_PREPARE], [ msg_checking= msg_result_yes= msg_result_no= msg_result_other= msg_reset= AS_CASE(["x${CONFIGURE_TTY}"], @@ -9,6 +9,7 @@ AC_DEFUN([_COLORIZE_RESULT_PREPARE], [ [configure_tty=0])]) AS_IF([test $configure_tty -eq 1], [ msg_begin="`tput smso 2>/dev/null`" + AS_IF([test -z "$msg_begin"], [msg_begin="`tput so 2>/dev/null`"]) AS_CASE(["$msg_begin"], ['@<:@'*m], [msg_begin="`echo "$msg_begin" | sed ['s/[0-9]*m$//']`" msg_checking="${msg_begin}33m" diff --git a/ruby/tool/m4/ac_msg_result.m4 b/ruby/tool/m4/ac_msg_result.m4 index bcc7a63d7..12a3617c0 100644 --- a/ruby/tool/m4/ac_msg_result.m4 +++ b/ruby/tool/m4/ac_msg_result.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([AC_MSG_RESULT], [dnl { _AS_ECHO_LOG([result: $1]) COLORIZE_RESULT([$1]); dnl diff --git a/ruby/tool/m4/colorize_result.m4 b/ruby/tool/m4/colorize_result.m4 index 19ff6d49e..83912040e 100644 --- a/ruby/tool/m4/colorize_result.m4 +++ b/ruby/tool/m4/colorize_result.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([COLORIZE_RESULT], [AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl AS_LITERAL_IF([$1], [m4_case([$1], diff --git a/ruby/tool/m4/ruby_append_option.m4 b/ruby/tool/m4/ruby_append_option.m4 index 07b6537cb..ff828d216 100644 --- a/ruby/tool/m4/ruby_append_option.m4 +++ b/ruby/tool/m4/ruby_append_option.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_APPEND_OPTION], [# RUBY_APPEND_OPTION($1) AS_CASE([" [$]{$1-} "], diff --git a/ruby/tool/m4/ruby_append_options.m4 b/ruby/tool/m4/ruby_append_options.m4 index 164a4ab65..14213111c 100644 --- a/ruby/tool/m4/ruby_append_options.m4 +++ b/ruby/tool/m4/ruby_append_options.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_APPEND_OPTIONS], [# RUBY_APPEND_OPTIONS($1) for rb_opt in $2; do diff --git a/ruby/tool/m4/ruby_check_builtin_func.m4 b/ruby/tool/m4/ruby_check_builtin_func.m4 index 3fe5caf42..40abc78ef 100644 --- a/ruby/tool/m4/ruby_check_builtin_func.m4 +++ b/ruby/tool/m4/ruby_check_builtin_func.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_CHECK_BUILTIN_FUNC], [dnl AC_CACHE_CHECK([for $1], AS_TR_SH(rb_cv_builtin_$1), [AC_LINK_IFELSE( diff --git a/ruby/tool/m4/ruby_check_builtin_setjmp.m4 b/ruby/tool/m4/ruby_check_builtin_setjmp.m4 index a4289e2e9..05118e224 100644 --- a/ruby/tool/m4/ruby_check_builtin_setjmp.m4 +++ b/ruby/tool/m4/ruby_check_builtin_setjmp.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_CHECK_BUILTIN_SETJMP], [ AS_IF([test x"${ac_cv_func___builtin_setjmp}" = xyes], [ unset ac_cv_func___builtin_setjmp @@ -8,18 +8,18 @@ AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp, ac_cv_func___builtin_setjmp=no for cast in "" "(void **)"; do RUBY_WERROR_FLAG( - [AC_TRY_LINK([@%:@include + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include @%:@include jmp_buf jb; @%:@ifdef NORETURN NORETURN(void t(void)); @%:@endif void t(void) {__builtin_longjmp($cast jb, 1);} - int jump(void) {(void)(__builtin_setjmp($cast jb) ? 1 : 0); return 0;}], - [ + int jump(void) {(void)(__builtin_setjmp($cast jb) ? 1 : 0); return 0;}]], + [[ void (*volatile f)(void) = t; if (!jump()) printf("%d\n", f != 0); - ], + ]])], [ac_cv_func___builtin_setjmp="yes with cast ($cast)"]) ]) test "$ac_cv_func___builtin_setjmp" = no || break diff --git a/ruby/tool/m4/ruby_check_printf_prefix.m4 b/ruby/tool/m4/ruby_check_printf_prefix.m4 index 9007c18c0..15bb4aee8 100644 --- a/ruby/tool/m4/ruby_check_printf_prefix.m4 +++ b/ruby/tool/m4/ruby_check_printf_prefix.m4 @@ -1,11 +1,10 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_CHECK_PRINTF_PREFIX], [ AC_CACHE_CHECK([for printf prefix for $1], [rb_cv_pri_prefix_]AS_TR_SH($1),[ [rb_cv_pri_prefix_]AS_TR_SH($1)=[NONE] RUBY_WERROR_FLAG(RUBY_APPEND_OPTIONS(CFLAGS, $rb_cv_wsuppress_flags) for pri in $2; do - AC_TRY_COMPILE( - [@%:@include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include @%:@include @%:@ifdef __GNUC__ @%:@if defined __MINGW_PRINTF_FORMAT @@ -18,9 +17,9 @@ AC_CACHE_CHECK([for printf prefix for $1], [rb_cv_pri_prefix_]AS_TR_SH($1),[ @%:@else @%:@define PRINTF_ARGS(decl, string_index, first_to_check) decl @%:@endif - PRINTF_ARGS(void test_sprintf(const char*, ...), 1, 2);], - [printf("%]${pri}[d", (]$1[)42); - test_sprintf("%]${pri}[d", (]$1[)42);], + PRINTF_ARGS(void test_sprintf(const char*, ...), 1, 2);]], + [[printf("%]${pri}[d", (]$1[)42); + test_sprintf("%]${pri}[d", (]$1[)42);]])], [rb_cv_pri_prefix_]AS_TR_SH($1)[=[$pri]; break]) done)]) AS_IF([test "[$rb_cv_pri_prefix_]AS_TR_SH($1)" != NONE], [ diff --git a/ruby/tool/m4/ruby_check_setjmp.m4 b/ruby/tool/m4/ruby_check_setjmp.m4 index 59f38581b..6020b766b 100644 --- a/ruby/tool/m4/ruby_check_setjmp.m4 +++ b/ruby/tool/m4/ruby_check_setjmp.m4 @@ -1,15 +1,15 @@ -# -*- Autoconf -*- -# used for AC_ARG_WITH(setjmp-type) +dnl -*- Autoconf -*- +dnl used for AC_ARG_WITH(setjmp-type) AC_DEFUN([RUBY_CHECK_SETJMP], [ AC_CACHE_CHECK([for ]$1[ as a macro or function], ac_cv_func_$1, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]AC_INCLUDES_DEFAULT([$3])[ @%:@define JMPARGS_1 env @%:@define JMPARGS_2 env,1 @%:@define JMPARGS JMPARGS_]m4_ifval($2,2,1)[ -], - m4_ifval($2,$2,jmp_buf)[ env; $1(JMPARGS);], +]], + [m4_ifval($2,$2,jmp_buf)[ env; $1(JMPARGS);]])], ac_cv_func_$1=yes, ac_cv_func_$1=no)] ) diff --git a/ruby/tool/m4/ruby_check_signedness.m4 b/ruby/tool/m4/ruby_check_signedness.m4 index 5376efa20..f9fbb3c08 100644 --- a/ruby/tool/m4/ruby_check_signedness.m4 +++ b/ruby/tool/m4/ruby_check_signedness.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_CHECK_SIGNEDNESS [typename] [if-signed] [if-unsigned] [included] AC_DEFUN([RUBY_CHECK_SIGNEDNESS], [dnl AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])], [($1)-1 > 0])], diff --git a/ruby/tool/m4/ruby_check_sizeof.m4 b/ruby/tool/m4/ruby_check_sizeof.m4 index 38d7918f2..975ac6c9b 100644 --- a/ruby/tool/m4/ruby_check_sizeof.m4 +++ b/ruby/tool/m4/ruby_check_sizeof.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_CHECK_SIZEOF [typename], [maybe same size types], [macros], [include] AC_DEFUN([RUBY_CHECK_SIZEOF], [dnl diff --git a/ruby/tool/m4/ruby_check_sysconf.m4 b/ruby/tool/m4/ruby_check_sysconf.m4 index f6b247a16..f554786e7 100644 --- a/ruby/tool/m4/ruby_check_sysconf.m4 +++ b/ruby/tool/m4/ruby_check_sysconf.m4 @@ -1,9 +1,9 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_CHECK_SYSCONF], [dnl AC_CACHE_CHECK([whether _SC_$1 is supported], rb_cv_have_sc_[]m4_tolower($1), - [AC_TRY_COMPILE([#include - ], - [_SC_$1 >= 0], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + ]], + [[_SC_$1 >= 0]])], rb_cv_have_sc_[]m4_tolower($1)=yes, rb_cv_have_sc_[]m4_tolower($1)=no) ]) diff --git a/ruby/tool/m4/ruby_cppoutfile.m4 b/ruby/tool/m4/ruby_cppoutfile.m4 index 7c81c4f35..976cbb1c4 100644 --- a/ruby/tool/m4/ruby_cppoutfile.m4 +++ b/ruby/tool/m4/ruby_cppoutfile.m4 @@ -1,11 +1,11 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_CPPOUTFILE], [AC_CACHE_CHECK(whether ${CPP} accepts -o, rb_cv_cppoutfile, [save_CPPFLAGS="$CPPFLAGS" CPPFLAGS='-o conftest-1.i' rb_cv_cppoutfile=no -AC_TRY_CPP([test-for-cppout], - [grep test-for-cppout conftest-1.i > /dev/null && rb_cv_cppoutfile=yes]) +AC_PREPROC_IFELSE([AC_LANG_SOURCE([[test-for-cppout]])], + [grep test-for-cppout conftest-1.i > /dev/null && rb_cv_cppoutfile=yes]) CPPFLAGS="$save_CPPFLAGS" rm -f conftest*]) AS_IF([test "$rb_cv_cppoutfile" = yes], [ diff --git a/ruby/tool/m4/ruby_decl_attribute.m4 b/ruby/tool/m4/ruby_decl_attribute.m4 index 3187b9be6..a8a73dc87 100644 --- a/ruby/tool/m4/ruby_decl_attribute.m4 +++ b/ruby/tool/m4/ruby_decl_attribute.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_DECL_ATTRIBUTE(attrib, macroname, cachevar, condition, type, code) AC_DEFUN([RUBY_DECL_ATTRIBUTE], [dnl m4_ifval([$2], dnl @@ -21,7 +21,7 @@ for mac in \ "__declspec(attrib_code) x" \ x; do m4_ifval([$4],mac="$mac"${rbcv_cond+" /* only if $rbcv_cond */"}) - AC_TRY_COMPILE( + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ m4_ifval([$4],${rbcv_cond+[@%:@if ]$rbcv_cond}) [@%:@define ]attrib[](attrib_params)[ $mac] m4_ifval([$4],${rbcv_cond+[@%:@else]} @@ -30,7 +30,7 @@ ${rbcv_cond+[@%:@endif]}) $6 @%:@define mesg ("") @%:@define san "address" - attrib[](attrib_params)[;], [], + attrib[](attrib_params)[;]], [[]])], [rbcv="$mac"; break]) done ])]) diff --git a/ruby/tool/m4/ruby_default_arch.m4 b/ruby/tool/m4/ruby_default_arch.m4 index a53bb5fc4..03e52f777 100644 --- a/ruby/tool/m4/ruby_default_arch.m4 +++ b/ruby/tool/m4/ruby_default_arch.m4 @@ -1,11 +1,11 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_DEFAULT_ARCH], [ AC_MSG_CHECKING([arch option]) AS_CASE([$1], + [arm64], [], [*64], [ARCH_FLAG=-m64], [[i[3-6]86]], [ARCH_FLAG=-m32], [AC_MSG_ERROR(unknown target architecture: $target_archs)] ) AC_MSG_RESULT([$ARCH_FLAG]) -]) -dnl +])dnl diff --git a/ruby/tool/m4/ruby_define_if.m4 b/ruby/tool/m4/ruby_define_if.m4 index b18b104aa..aba55783a 100644 --- a/ruby/tool/m4/ruby_define_if.m4 +++ b/ruby/tool/m4/ruby_define_if.m4 @@ -1,12 +1,6 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_DEFINE_IF], [dnl - m4_ifval([$1], [AS_LITERAL_IF([$1], [], [test "X$1" = X || ])cat <> confdefs.h -@%:@if $1 -EOH -])dnl + m4_ifval([$1], [AS_LITERAL_IF([$1], [], [test "X$1" = X || ])printf "@%:@if %s\n" "$1" >>confdefs.h]) AC_DEFINE_UNQUOTED($2, $3)dnl - m4_ifval([$1], [AS_LITERAL_IF([$1], [], [test "X$1" = X || ])cat <> confdefs.h -@%:@endif /* $1 */ -EOH -])dnl + m4_ifval([$1], [AS_LITERAL_IF([$1], [], [test "X$1" = X || ])printf "@%:@endif /* %s */\n" "$1" >>confdefs.h]) ])dnl diff --git a/ruby/tool/m4/ruby_defint.m4 b/ruby/tool/m4/ruby_defint.m4 index e5b46a788..e9ed68e5b 100644 --- a/ruby/tool/m4/ruby_defint.m4 +++ b/ruby/tool/m4/ruby_defint.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_DEFINT TYPENAME, SIZE, [UNSIGNED], [INCLUDES = DEFAULT-INCLUDES] AC_DEFUN([RUBY_DEFINT], [dnl AS_VAR_PUSHDEF([cond], [rb_defint_cond])dnl diff --git a/ruby/tool/m4/ruby_dtrace_available.m4 b/ruby/tool/m4/ruby_dtrace_available.m4 index 79586d152..e03b7762f 100644 --- a/ruby/tool/m4/ruby_dtrace_available.m4 +++ b/ruby/tool/m4/ruby_dtrace_available.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_DTRACE_AVAILABLE], [AC_CACHE_CHECK(whether dtrace USDT is available, rb_cv_dtrace_available, [ @@ -7,7 +7,7 @@ AC_DEFUN([RUBY_DTRACE_AVAILABLE], AS_FOR(opt, rb_dtrace_opt, ["-xnolibs" ""], [dnl AS_IF([$DTRACE opt -h -o conftest_provider.h -s conftest_provider.d >/dev/null 2>/dev/null], [], [continue]) - AC_TRY_COMPILE([@%:@include "conftest_provider.h"], [CONFTEST_FIRE();], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include "conftest_provider.h"]], [[CONFTEST_FIRE();]])], [], [continue]) # DTrace is available on the system rb_cv_dtrace_available=yes${rb_dtrace_opt:+"(opt)"} diff --git a/ruby/tool/m4/ruby_dtrace_postprocess.m4 b/ruby/tool/m4/ruby_dtrace_postprocess.m4 index 9ef088b3f..6fd6de7c9 100644 --- a/ruby/tool/m4/ruby_dtrace_postprocess.m4 +++ b/ruby/tool/m4/ruby_dtrace_postprocess.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_DTRACE_POSTPROCESS], [AC_CACHE_CHECK(whether $DTRACE needs post processing, rb_cv_prog_dtrace_g, [ @@ -12,7 +12,7 @@ _PROBES $DTRACE ${DTRACE_OPT} -h -o conftest_provider.h -s conftest_provider.d >/dev/null 2>/dev/null && : }], [ - AC_TRY_COMPILE([@%:@include "conftest_provider.h"], [CONFTEST_FIRE();], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include "conftest_provider.h"]], [[CONFTEST_FIRE();]])],[ AS_IF([{ cp -p conftest.${ac_objext} conftest.${ac_objext}.save && $DTRACE ${DTRACE_OPT} -G -s conftest_provider.d conftest.${ac_objext} 2>/dev/null && diff --git a/ruby/tool/m4/ruby_func_attribute.m4 b/ruby/tool/m4/ruby_func_attribute.m4 index b265fd41d..bce26fc16 100644 --- a/ruby/tool/m4/ruby_func_attribute.m4 +++ b/ruby/tool/m4/ruby_func_attribute.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_FUNC_ATTRIBUTE(attrib, macroname, cachevar, condition) AC_DEFUN([RUBY_FUNC_ATTRIBUTE], [dnl RUBY_DECL_ATTRIBUTE([$1], [$2], [$3], [$4], diff --git a/ruby/tool/m4/ruby_mingw32.m4 b/ruby/tool/m4/ruby_mingw32.m4 index f44fe5575..98e922340 100644 --- a/ruby/tool/m4/ruby_mingw32.m4 +++ b/ruby/tool/m4/ruby_mingw32.m4 @@ -1,13 +1,13 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_MINGW32], [AS_CASE(["$host_os"], [cygwin*], [ AC_CACHE_CHECK(for mingw32 environment, rb_cv_mingw32, -[AC_TRY_CPP([ +[AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ #ifndef __MINGW32__ # error #endif -], rb_cv_mingw32=yes,rb_cv_mingw32=no) +]])],[rb_cv_mingw32=yes],[rb_cv_mingw32=no]) rm -f conftest*]) AS_IF([test "$rb_cv_mingw32" = yes], [ target_os="mingw32" diff --git a/ruby/tool/m4/ruby_prepend_option.m4 b/ruby/tool/m4/ruby_prepend_option.m4 index 3e868a683..3b7030a47 100644 --- a/ruby/tool/m4/ruby_prepend_option.m4 +++ b/ruby/tool/m4/ruby_prepend_option.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_PREPEND_OPTION], [# RUBY_PREPEND_OPTION($1) AS_CASE([" [$]{$1-} "], diff --git a/ruby/tool/m4/ruby_prog_gnu_ld.m4 b/ruby/tool/m4/ruby_prog_gnu_ld.m4 index 8d484f944..b38fb3d52 100644 --- a/ruby/tool/m4/ruby_prog_gnu_ld.m4 +++ b/ruby/tool/m4/ruby_prog_gnu_ld.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_PROG_GNU_LD], [AC_CACHE_CHECK(whether the linker is GNU ld, rb_cv_prog_gnu_ld, [AS_IF([`$CC $CFLAGS $CPPFLAGS $LDFLAGS --print-prog-name=ld 2>&1` -v 2>&1 | grep "GNU ld" > /dev/null], [ diff --git a/ruby/tool/m4/ruby_replace_funcs.m4 b/ruby/tool/m4/ruby_replace_funcs.m4 index d0612e29a..10e85f1ac 100644 --- a/ruby/tool/m4/ruby_replace_funcs.m4 +++ b/ruby/tool/m4/ruby_replace_funcs.m4 @@ -1,13 +1,13 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_REPLACE_FUNC [func] [included] AC_DEFUN([RUBY_REPLACE_FUNC], [dnl AC_CHECK_DECL([$1],dnl [AC_DEFINE(AS_TR_CPP(HAVE_[$1]))],dnl [AC_REPLACE_FUNCS($1)],dnl [$2])dnl -]) - +])dnl +dnl dnl RUBY_REPLACE_FUNCS [funcs] [included] AC_DEFUN([RUBY_REPLACE_FUNCS] [dnl m4_map_args_w([$1], [RUBY_REPLACE_FUNC(], [), [$2]])dnl -]) +])dnl diff --git a/ruby/tool/m4/ruby_replace_type.m4 b/ruby/tool/m4/ruby_replace_type.m4 index a7d2ffe93..70674b6cc 100644 --- a/ruby/tool/m4/ruby_replace_type.m4 +++ b/ruby/tool/m4/ruby_replace_type.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_REPLACE_TYPE [typename] [default type] [macro type] [included] AC_DEFUN([RUBY_REPLACE_TYPE], [dnl AC_CHECK_TYPES([$1], diff --git a/ruby/tool/m4/ruby_rm_recursive.m4 b/ruby/tool/m4/ruby_rm_recursive.m4 index e33ba1d97..b97701f88 100644 --- a/ruby/tool/m4/ruby_rm_recursive.m4 +++ b/ruby/tool/m4/ruby_rm_recursive.m4 @@ -1,6 +1,6 @@ -# -*- Autoconf -*- -AC_DEFUN([RUBY_RM_RECURSIVE], [ -m4_version_prereq([2.70], [-1], [ +dnl -*- Autoconf -*- +AC_DEFUN([RUBY_RM_RECURSIVE], [dnl +m4_version_prereq([2.70], [], [dnl # suppress error messages, rm: cannot remove 'conftest.dSYM', from # AC_EGREP_CPP with CFLAGS=-g on Darwin. AS_CASE([$build_os], [darwin*], [ diff --git a/ruby/tool/m4/ruby_setjmp_type.m4 b/ruby/tool/m4/ruby_setjmp_type.m4 index 9da9a8868..4ae26fe5c 100644 --- a/ruby/tool/m4/ruby_setjmp_type.m4 +++ b/ruby/tool/m4/ruby_setjmp_type.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_SETJMP_TYPE], [ RUBY_CHECK_BUILTIN_SETJMP RUBY_CHECK_SETJMP(_setjmpex, [], [@%:@include ]) @@ -47,6 +47,6 @@ AS_IF([test x$setjmp_prefix:$setjmp_sigmask = xsig:], [ AC_MSG_RESULT(${setjmp_prefix}setjmp${setjmp_suffix}${setjmp_cast:+\($setjmp_cast\)}${setjmp_sigmask}) AC_DEFINE_UNQUOTED([RUBY_SETJMP(env)], [${setjmp_prefix}setjmp${setjmp_suffix}($setjmp_cast(env)${setjmp_sigmask})]) AC_DEFINE_UNQUOTED([RUBY_LONGJMP(env,val)], [${setjmp_prefix}longjmp($setjmp_cast(env),val)]) -AS_IF([test x$setjmp_prefix != x__builtin_], AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf)) +AS_IF([test "(" "$GCC" != yes ")" -o x$setjmp_prefix != x__builtin_], AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf)) AS_IF([test x$setjmp_suffix = xex], [AC_DEFINE_UNQUOTED(RUBY_USE_SETJMPEX, 1)]) ])dnl diff --git a/ruby/tool/m4/ruby_stack_grow_direction.m4 b/ruby/tool/m4/ruby_stack_grow_direction.m4 index 74ec21932..a4d205cc3 100644 --- a/ruby/tool/m4/ruby_stack_grow_direction.m4 +++ b/ruby/tool/m4/ruby_stack_grow_direction.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_STACK_GROW_DIRECTION], [ AS_VAR_PUSHDEF([stack_grow_dir], [rb_cv_stack_grow_dir_$1]) AC_CACHE_CHECK(stack growing direction on $1, stack_grow_dir, [ @@ -6,7 +6,7 @@ AS_CASE(["$1"], [m68*|x86*|x64|i?86|ppc*|sparc*|alpha*], [ $2=-1], [hppa*], [ $2=+1], [ - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ /* recurse to get rid of inlining */ static int stack_growup_p(addr, n) @@ -23,7 +23,7 @@ int main() int x; return stack_growup_p(&x, 10); } -], $2=-1, $2=+1, $2=0) +]])],[$2=-1],[$2=+1],[$2=0]) ]) eval stack_grow_dir=\$$2]) eval $2=\$stack_grow_dir diff --git a/ruby/tool/m4/ruby_thread.m4 b/ruby/tool/m4/ruby_thread.m4 new file mode 100644 index 000000000..3831bc4c0 --- /dev/null +++ b/ruby/tool/m4/ruby_thread.m4 @@ -0,0 +1,33 @@ +dnl -*- Autoconf -*- +AC_DEFUN([RUBY_THREAD], [ +AC_ARG_WITH(thread, + AS_HELP_STRING([--with-thread=IMPLEMENTATION], [specify the thread implementation to use]), + [THREAD_MODEL=$withval], [ + THREAD_MODEL= + AS_CASE(["$target_os"], + [mingw*], [ + THREAD_MODEL=win32 + ], + [ + AS_IF([test "$rb_with_pthread" = "yes"], [ + THREAD_MODEL=pthread + ]) + ] + ) +]) + +AS_CASE(["$THREAD_MODEL"], +[pthread], [AC_CHECK_HEADERS(pthread.h)], +[win32], [], +[""], [AC_MSG_ERROR(thread model is missing)], + [AC_MSG_ERROR(unknown thread model $THREAD_MODEL)]) + +THREAD_IMPL_H=thread_$THREAD_MODEL.h +AS_IF([test ! -f "$srcdir/$THREAD_IMPL_H"], + [AC_MSG_ERROR('$srcdir/$THREAD_IMPL_H' must exist)]) +THREAD_IMPL_SRC=thread_$THREAD_MODEL.c +AS_IF([test ! -f "$srcdir/$THREAD_IMPL_SRC"], + [AC_MSG_ERROR('$srcdir/$THREAD_IMPL_SRC' must exist)]) +AC_DEFINE_UNQUOTED(THREAD_IMPL_H, ["$THREAD_IMPL_H"]) +AC_DEFINE_UNQUOTED(THREAD_IMPL_SRC, ["$THREAD_IMPL_SRC"]) +])dnl diff --git a/ruby/tool/m4/ruby_try_cflags.m4 b/ruby/tool/m4/ruby_try_cflags.m4 index 86ab80e1e..f2c6a3094 100644 --- a/ruby/tool/m4/ruby_try_cflags.m4 +++ b/ruby/tool/m4/ruby_try_cflags.m4 @@ -1,9 +1,9 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_TRY_CFLAGS], [ AC_MSG_CHECKING([whether ]$1[ is accepted as CFLAGS]) RUBY_WERROR_FLAG([ CFLAGS="[$]CFLAGS $1" - AC_TRY_COMPILE([$4], [$5], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$4]], [[$5]])], [$2 AC_MSG_RESULT(yes)], [$3 diff --git a/ruby/tool/m4/ruby_try_cxxflags.m4 b/ruby/tool/m4/ruby_try_cxxflags.m4 new file mode 100644 index 000000000..06f645f54 --- /dev/null +++ b/ruby/tool/m4/ruby_try_cxxflags.m4 @@ -0,0 +1,17 @@ +dnl -*- Autoconf -*- +AC_DEFUN([RUBY_TRY_CXXFLAGS], [ + save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="[$]CXXFLAGS $1" + AC_MSG_CHECKING([whether ]$1[ is accepted as CXXFLAGS]) + RUBY_WERROR_FLAG([ + AC_LANG_PUSH([C++]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[$4]], [[$5]])], + [$2 + AC_MSG_RESULT(yes)], + [$3 + AC_MSG_RESULT(no)]) + ]) + AC_LANG_POP([C++]) + CXXFLAGS="$save_CXXFLAGS" + save_CXXFLAGS= +])dnl diff --git a/ruby/tool/m4/ruby_try_ldflags.m4 b/ruby/tool/m4/ruby_try_ldflags.m4 index b275107ed..c3a6be0fb 100644 --- a/ruby/tool/m4/ruby_try_ldflags.m4 +++ b/ruby/tool/m4/ruby_try_ldflags.m4 @@ -1,10 +1,10 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_TRY_LDFLAGS], [ save_LDFLAGS="$LDFLAGS" LDFLAGS="[$]LDFLAGS $1" AC_MSG_CHECKING([whether $1 is accepted as LDFLAGS]) RUBY_WERROR_FLAG([ - AC_TRY_LINK([$4], [$5], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[$4]], [[$5]])], [$2 AC_MSG_RESULT(yes)], [$3 diff --git a/ruby/tool/m4/ruby_type_attribute.m4 b/ruby/tool/m4/ruby_type_attribute.m4 index 6ddaa20c5..5ea1219c6 100644 --- a/ruby/tool/m4/ruby_type_attribute.m4 +++ b/ruby/tool/m4/ruby_type_attribute.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- dnl RUBY_TYPE_ATTRIBUTE(attrib, macroname, cachevar, condition) AC_DEFUN([RUBY_TYPE_ATTRIBUTE], [dnl RUBY_DECL_ATTRIBUTE([$1], [$2], [$3], [$4], diff --git a/ruby/tool/m4/ruby_universal_arch.m4 b/ruby/tool/m4/ruby_universal_arch.m4 index a524bc259..375cdd98d 100644 --- a/ruby/tool/m4/ruby_universal_arch.m4 +++ b/ruby/tool/m4/ruby_universal_arch.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_UNIVERSAL_ARCH], [ # RUBY_UNIVERSAL_ARCH begin ARCH_FLAG=`expr " $CXXFLAGS " : ['.* \(-m[0-9][0-9]*\) ']` @@ -39,7 +39,7 @@ AS_IF([test ${target_archs+set}], [ echo 'int main(){return 0;}' > conftest.c AS_IF([$CC $CFLAGS $ARCH_FLAG -o conftest conftest.c > /dev/null 2>&1], [ rm -fr conftest.* - ], [ + ], [test -z "$ARCH_FLAG"], [ RUBY_DEFAULT_ARCH("$target_archs") ]) ]) @@ -66,6 +66,9 @@ AS_IF([test ${target_archs+set}], [ #ifdef __ppc64__ "processor-name=powerpc64" #endif +#ifdef __arm64__ +"processor-name=arm64" +#endif EOF sed -n 's/^"processor-name=\(.*\)"/\1/p'` target="$target_cpu${target}" @@ -85,3 +88,35 @@ AS_IF([test "x${ARCH_FLAG}" != x], [ ]) # RUBY_UNIVERSAL_ARCH end ])dnl +dnl +AC_DEFUN([RUBY_UNIVERSAL_CHECK_HEADER_COND], [ dnl + AC_CACHE_CHECK([for $2 when $1], [$3], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT([$6])[ + @%:@if ]$1[ + @%:@include <]$2[> + @%:@endif]], [[]])], + [AS_VAR_SET($3, yes)], + [AS_VAR_SET($3, no)])) + AS_VAR_IF([$3], [yes], [dnl + printf "@%:@if %s\n" "$1" >>confdefs.h + AC_DEFINE_UNQUOTED(HAVE_[]AS_TR_CPP($2), 1)dnl + printf "@%:@endif\n" >>confdefs.h dnl + $4], [$5]) +])dnl +dnl +# RUBY_UNIVERSAL_CHECK_HEADER(CPU-LIST, HEADER, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [INCLUDES = DEFAULT-INCLUDES]) +AC_DEFUN([RUBY_UNIVERSAL_CHECK_HEADER], [ dnl + m4_if([$# dnl + ], [0], [], [ dnl + m4_foreach([rb_Header], [$1], + [AS_CASE([",$target_archs,"], [*,]rb_Header[,*], + [RUBY_UNIVERSAL_CHECK_HEADER_COND]([defined(__[]rb_Header[]__)], + [$2], [rb_cv_header_[]AS_TR_SH($2)_on_[]AS_TR_SH(rb_Header)], + [$3], [$4], [$5]) + ) + ]) + ])dnl +])dnl diff --git a/ruby/tool/m4/ruby_werror_flag.m4 b/ruby/tool/m4/ruby_werror_flag.m4 index e9155c830..616a7f6ab 100644 --- a/ruby/tool/m4/ruby_werror_flag.m4 +++ b/ruby/tool/m4/ruby_werror_flag.m4 @@ -1,4 +1,4 @@ -# -*- Autoconf -*- +dnl -*- Autoconf -*- AC_DEFUN([RUBY_WERROR_FLAG], [dnl save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $rb_cv_warnflags" diff --git a/ruby/tool/make-snapshot b/ruby/tool/make-snapshot index 79289d6bf..5c66d5b76 100755 --- a/ruby/tool/make-snapshot +++ b/ruby/tool/make-snapshot @@ -1,5 +1,8 @@ #!/usr/bin/ruby -s # -*- coding: us-ascii -*- +require 'rubygems' +require 'rubygems/package' +require 'rubygems/package/tar_writer' require 'uri' require 'digest/sha1' require 'digest/sha2' @@ -54,7 +57,7 @@ PACKAGES = { DEFAULT_PACKAGES = PACKAGES.keys - ["tar"] if !$no7z and system("7z", out: IO::NULL) PACKAGES["gzip"] = %w".tar.gz 7z a dummy -tgzip -mx -so" - PACKAGES["zip"] = %w".zip 7z a -tzip -mx -mtc=off" << {out: IO::NULL} + PACKAGES["zip"] = %w".zip 7z a -tzip -l -mx -mtc=off" << {out: IO::NULL} elsif gzip = ENV.delete("GZIP") PACKAGES["gzip"].concat(gzip.shellsplit) end @@ -157,9 +160,6 @@ at_exit { } unless $keep_temp def tar_create(tarball, dir) - require 'rubygems' - require 'rubygems/package' - require 'rubygems/package/tar_writer' header = Gem::Package::TarHeader dir_type = "5" uname = gname = "ruby" @@ -242,6 +242,16 @@ class MAKE < Struct.new(:prog, :args) end end +def measure + clock = Process::CLOCK_MONOTONIC + t0 = Process.clock_gettime(clock) + STDOUT.flush + result = yield + printf(" %6.3f", Process.clock_gettime(clock) - t0) + STDOUT.flush + result +end + def package(vcs, rev, destdir, tmp = nil) pwd = Dir.pwd patchlevel = false @@ -311,7 +321,7 @@ def package(vcs, rev, destdir, tmp = nil) end if $srcdir Dir.glob($srcdir + "/{tool/config.{guess,sub},gems/*.gem,.downloaded-cache/*,enc/unicode/data/**/*.txt}") do |file| - puts "copying #{file}" + puts "copying #{file}" if $VERBOSE dest = exported + file[$srcdir.size..-1] FileUtils.mkpath(File.dirname(dest)) begin @@ -497,11 +507,13 @@ touch-unicode-files: system(*%W"#{YACC} -o parse.c parse.y") end vcs.after_export(".") if exported + clean.concat(Dir.glob("ext/**/autom4te.cache")) FileUtils.rm_rf(clean) unless $keep_temp FileUtils.rm_rf(".downloaded-cache") if File.exist?("gems/bundled_gems") gems = Dir.glob("gems/*.gem") gems -= File.readlines("gems/bundled_gems").map {|line| + next if /^\s*(?:#|$)/ =~ line name, version, _ = line.split(' ') "gems/#{name}-#{version}.gem" } @@ -542,7 +554,7 @@ touch-unicode-files: else tarball = ext == ".tar" ? file : "#{$archname||v}.tar" print "creating tarball... #{tarball}" - if tar_create(tarball, v) + if measure {tar_create(tarball, v)} puts $colorize.pass(" done") File.utime(modified, modified, tarball) if modified next if tarball == file @@ -553,7 +565,7 @@ touch-unicode-files: end end print "creating #{mesg} tarball... #{file}" - done = system(*cmd, tarball, out: file) + done = measure {system(*cmd, tarball, out: file)} else print "creating #{mesg} archive... #{file}" if Hash === cmd.last @@ -562,7 +574,7 @@ touch-unicode-files: else (cmd = cmd.dup) << file << v end - done = system(*cmd) + done = measure {system(*cmd)} end if done puts $colorize.pass(" done") diff --git a/ruby/tool/merger.rb b/ruby/tool/merger.rb index 2ea5d889c..d38f00b0f 100755 --- a/ruby/tool/merger.rb +++ b/ruby/tool/merger.rb @@ -116,7 +116,7 @@ def tag(relname) v, pl = version if relname abort "patchlevel is not -1 but '#{pl}' for preview or rc" if pl != '-1' && /-(?:preview|rc)/ =~ relname - abort "patchlevel is not 0 but '#{pl}' for the first release" if pl != '0' && /-(?:preview|rc)/ !~ relname + abort "patchlevel is not 0 but '#{pl}' for the first release" if pl != '0' && relname.end_with?(".0") pl = relname[/-(.*)\z/, 1] curver = "#{v.join('.')}#{("-#{pl}" if pl)}" if relname != curver @@ -220,8 +220,7 @@ def commit(file) else current_branch = IO.popen(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], &:read).strip execute('git', 'add', '.') && - execute('git', 'commit', '-F', file) && - execute('git', 'push', ORIGIN, current_branch) + execute('git', 'commit', '-F', file) end end diff --git a/ruby/tool/mjit_tabs.rb b/ruby/tool/mjit_tabs.rb new file mode 100644 index 000000000..edcbf6cfc --- /dev/null +++ b/ruby/tool/mjit_tabs.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true +# This is a script to run a command in ARGV, expanding tabs in some files +# included by vm.c to normalize indentation of MJIT header. You can enable +# this feature by passing `--without-mjit-tabs` in configure. +# +# Note that preprocessor of GCC converts a hard tab to one spaces, where +# we expect it to be shown as 8 spaces. To obviate this script, we need +# to convert all tabs to spaces in these files. + +require 'fileutils' + +EXPAND_TARGETS = %w[ + vm*.* + include/ruby/ruby.h +] + +# These files have no hard tab indentations. Skip normalizing these files from the glob result. +SKIPPED_FILES = %w[ + vm_callinfo.h + vm_debug.h + vm_exec.h + vm_opts.h + vm_sync.h + vm_sync.c +] + +srcdir = File.expand_path('..', __dir__) +targets = EXPAND_TARGETS.flat_map { |t| Dir.glob(File.join(srcdir, t)) } - SKIPPED_FILES.map { |f| File.join(srcdir, f) } +sources = {} +mtimes = {} + +mjit_tabs, *command = ARGV + +targets.each do |target| + next if mjit_tabs != 'false' + unless File.writable?(target) + puts "tool/mjit_tabs.rb: Skipping #{target.dump} as it's not writable." + next + end + source = File.read(target) + begin + expanded = source.gsub(/^\t+/) { |tab| ' ' * 8 * tab.length } + rescue ArgumentError # invalid byte sequence in UTF-8 (Travis, RubyCI) + puts "tool/mjit_tabs.rb: Skipping #{target.dump} as the encoding is #{source.encoding}." + next + end + + sources[target] = source + mtimes[target] = File.mtime(target) + + if sources[target] == expanded + puts "#{target.dump} has no hard tab indentation. This should be ignored in tool/mjit_tabs.rb." + end + File.write(target, expanded) + FileUtils.touch(target, mtime: mtimes[target]) +end + +result = system(*command) + +targets.each do |target| + if sources.key?(target) + File.write(target, sources[target]) + FileUtils.touch(target, mtime: mtimes.fetch(target)) + end +end + +exit result diff --git a/ruby/tool/mk_builtin_binary.rb b/ruby/tool/mk_builtin_binary.rb deleted file mode 100644 index 1b3fe50ac..000000000 --- a/ruby/tool/mk_builtin_binary.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -# make builtin_binary.inc file. -# - -def dump_bin iseq - bin = iseq.to_binary - bin.each_byte.with_index{|b, index| - print "\n " if (index%20) == 0 - print " 0x#{'%02x' % b.ord}," - } - print "\n" -end - -$stdout = open('builtin_binary.inc', 'wb') - -puts < generate TARGET_FILE.rbinc # +LOCALS_DB = {} # [method_name, first_line] = locals + +def collect_iseq iseq_ary + # iseq_ary.each_with_index{|e, i| p [i, e]} + label = iseq_ary[5] + first_line = iseq_ary[8] + type = iseq_ary[9] + locals = iseq_ary[10] + insns = iseq_ary[13] + + if type == :method + LOCALS_DB[[label, first_line].freeze] = locals + end + + insns.each{|insn| + case insn + when Integer + # ignore + when Array + # p insn.shift # insn name + insn.each{|op| + if Array === op && op[0] == "YARVInstructionSequence/SimpleDataFormat" + collect_iseq op + end + } + end + } +end + +def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + f = StringIO.new + f.puts '{' + lineno += 1 + locals.reverse_each.with_index{|param, i| + next unless Symbol === param + f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" + lineno += 1 + } + f.puts "#line #{body_lineno} \"#{line_file}\"" + lineno += 1 + + f.puts text + lineno += text.count("\n") + 1 + + f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number. + f.puts "}" + f.puts + lineno += 3 + + return lineno, f.string +end + def mk_builtin_header file base = File.basename(file, '.rb') ofile = "#{file}inc" # bs = { func_name => argc } - collect_builtin(base, RubyVM::InstructionSequence.compile_file(file, false).to_a, 'top', bs = {}, inlines = {}) + code = File.read(file) + collect_iseq RubyVM::InstructionSequence.compile(code).to_a + collect_builtin(base, Ripper.sexp(code), 'top', bs = {}, inlines = {}) begin f = open(ofile, 'w') @@ -122,34 +257,31 @@ def mk_builtin_header file f = open(File.basename(ofile), 'w') end begin + if File::ALT_SEPARATOR + file = file.tr(File::ALT_SEPARATOR, File::SEPARATOR) + ofile = ofile.tr(File::ALT_SEPARATOR, File::SEPARATOR) + end + lineno = __LINE__ f.puts "// -*- c -*-" f.puts "// DO NOT MODIFY THIS FILE DIRECTLY." f.puts "// auto-generated file" f.puts "// by #{__FILE__}" f.puts "// with #{file}" + f.puts '#include "internal/compilers.h" /* for MAYBE_UNUSED */' + f.puts '#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */' + f.puts '#include "ruby/ruby.h" /* for VALUE */' + f.puts '#include "builtin.h" /* for RB_BUILTIN_FUNCTION */' + f.puts 'struct rb_execution_context_struct; /* in vm_core.h */' f.puts - lineno = 6 - line_file = file.gsub('\\', '/') + lineno = __LINE__ - lineno - 1 + line_file = file - inlines.each{|cfunc_name, (body_lineno, text, params, func_name)| + inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)| if String === cfunc_name - f.puts "static VALUE #{cfunc_name}(rb_execution_context_t *ec, const VALUE self) {" + f.puts "static VALUE #{cfunc_name}(struct rb_execution_context_struct *ec, const VALUE self)" lineno += 1 - - params.reverse_each.with_index{|param, i| - next unless Symbol === param - f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" - lineno += 1 - } - f.puts "#line #{body_lineno} \"#{line_file}\"" - lineno += 1 - - f.puts text - lineno += text.count("\n") + 1 - - f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number. - f.puts "}" - lineno += 2 + lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + f.write str else # cinit! f.puts "#line #{body_lineno} \"#{line_file}\"" @@ -161,22 +293,60 @@ def mk_builtin_header file end } - f.puts "static void load_#{base}(void)" + bs.each_pair{|func, (argc, cfunc_name)| + decl = ', VALUE' * argc + argv = argc \ + . times \ + . map {|i|", argv[#{i}]"} \ + . join('') + f.puts %'static void' + f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index, unsigned stack_size, bool inlinable_p)' + f.puts %'{' + f.puts %' fprintf(f, " VALUE self = GET_SELF();\\n");' + f.puts %' fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE#{decl});\\n");' + if inlines.has_key? cfunc_name + body_lineno, text, locals, func_name = inlines[cfunc_name] + lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + f.puts %' if (inlinable_p) {' + str.gsub(/^(?!#)/, ' ').each_line {|i| + j = RubyVM::CEscape.rstring2cstr(i).dup + j.sub!(/^ return\b/ , ' val =') + f.printf(%' fprintf(f, "%%s", %s);\n', j) + } + f.puts(%' return;') + f.puts(%' }') + end + if argc > 0 + f.puts %' if (index == -1) {' + f.puts %' fprintf(f, " const VALUE *argv = &stack[%d];\\n", stack_size - #{argc});' + f.puts %' }' + f.puts %' else {' + f.puts %' fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\\n");' + f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);' + f.puts %' }' + end + f.puts %' fprintf(f, " func f = (func)%"PRIuVALUE"; /* == #{cfunc_name} */\\n", (VALUE)#{cfunc_name});' + f.puts %' fprintf(f, " val = f(ec, self#{argv});\\n");' + f.puts %'}' + f.puts + } + + f.puts "void Init_builtin_#{base}(void)" f.puts "{" table = "#{base}_table" f.puts " // table definition" f.puts " static const struct rb_builtin_function #{table}[] = {" bs.each.with_index{|(func, (argc, cfunc_name)), i| - f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc})," + f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc}, mjit_compile_invokebuiltin_for_#{func})," } - f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0)," + f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0, 0)," f.puts " };" f.puts f.puts " // arity_check" f.puts "COMPILER_WARNING_PUSH" - f.puts "#if GCC_VERSION_SINCE(5, 1, 0) || __clang__" + f.puts "#if GCC_VERSION_SINCE(5, 1, 0) || defined __clang__" f.puts "COMPILER_WARNING_ERROR(-Wincompatible-pointer-types)" f.puts "#endif" bs.each{|func, (argc, cfunc_name)| @@ -184,7 +354,6 @@ def mk_builtin_header file } f.puts "COMPILER_WARNING_POP" - f.puts f.puts " // load" f.puts " rb_load_with_builtin_functions(#{base.dump}, #{table});" diff --git a/ruby/tool/mk_call_iseq_optimized.rb b/ruby/tool/mk_call_iseq_optimized.rb deleted file mode 100644 index eba44531c..000000000 --- a/ruby/tool/mk_call_iseq_optimized.rb +++ /dev/null @@ -1,74 +0,0 @@ - -puts <cc.me, 0, #{param}, #{local}); -} - -EOS - # - } -} - -puts <flag & VM_CALL_TAILCALL)) { - return &vm_call_iseq_setup_tailcall_0start; - } - else if (0) { /* to disable optimize */ - return &vm_call_iseq_setup_normal_0start; - } - else { - if (param_size <= #{P.end} && - local_size <= #{L.end}) { - VM_ASSERT(local_size >= 0); - return vm_call_iseq_handlers[param_size][local_size]; - } - return &vm_call_iseq_setup_normal_0start; - } -} - -#else - - -static inline vm_call_handler -vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size) -{ - if (UNLIKELY(ci->flag & VM_CALL_TAILCALL)) { - return &vm_call_iseq_setup_tailcall_0start; - } - else { - return &vm_call_iseq_setup_normal_0start; - } -} -#endif -EOS diff --git a/ruby/tool/mkconfig.rb b/ruby/tool/mkconfig.rb index 3e1e2b24a..6e23af518 100755 --- a/ruby/tool/mkconfig.rb +++ b/ruby/tool/mkconfig.rb @@ -29,6 +29,7 @@ continued_line = nil install_name = nil so_name = nil +platform = nil File.foreach "config.status" do |line| next if /^#/ =~ line name = nil @@ -87,7 +88,7 @@ unless $install_name $install_name = "ruby" val.gsub!(/\$\$/, '$') - val.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do + val.scan(%r[\G[\s;]*(/(?:\\.|[^/])*+/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*+)\3((?:(?!\3)(?:\\.|.))*+)\3([gi]*)]) do |addr, cmd, sep, pat, rep, opt| if addr Regexp.new(addr[/\A\/(.*)\/\z/, 1]) =~ $install_name or next @@ -121,24 +122,12 @@ universal, val = val, 'universal' if universal when /^arch$/ if universal - val.sub!(/universal/, %q[#{arch && universal[/(?:\A|\s)#{Regexp.quote(arch)}=(\S+)/, 1] || '\&'}]) + platform = val.sub(/universal/, %q[#{arch && universal[/(?:\A|\s)#{Regexp.quote(arch)}=(\S+)/, 1] || RUBY_PLATFORM[/\A[^-]*/]}]) end - when /^oldincludedir$/ + when /^includedir$/ val = '"$(SDKROOT)"'+val if /darwin/ =~ arch end v = " CONFIG[\"#{name}\"] #{eq} #{val}\n" - - # --------- [Enclose.IO Hack start] --------- - if ENV['ENCLOSE_IO_RUBYC_2ND_PASS'] - [ - " CONFIG[\"prefix\"] #{eq} ", - " CONFIG[\"RUBY_EXEC_PREFIX\"] #{eq} " - ].each do |v_head_comp| - v = "#{v[0...(v_head_comp.length)]}'/__enclose_io_memfs__'\n" if v_head_comp == v[0...(v_head_comp.length)] - end - end - # --------- [Enclose.IO Hack end] --------- - if fast[name] v_fast << v else @@ -280,9 +269,18 @@ module RbConfig CONFIG["UNICODE_EMOJI_VERSION"] = #{$unicode_emoji_version.dump} EOS print < prefix = /usr/local @@ -307,7 +305,7 @@ module RbConfig # RbConfig.expand is used for resolving references like above in rbconfig. # # require 'rbconfig' - # p Config.expand(Config::MAKEFILE_CONFIG["bindir"]) + # p RbConfig.expand(RbConfig::MAKEFILE_CONFIG["bindir"]) # # => "/usr/local/bin" MAKEFILE_CONFIG = {} CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup} @@ -345,8 +343,8 @@ def RbConfig::expand(val, config = CONFIG) # :nodoc: # call-seq: # - # RbConfig.fire_update!(key, val) -> string - # RbConfig.fire_update!(key, val, mkconf, conf) -> string + # RbConfig.fire_update!(key, val) -> array + # RbConfig.fire_update!(key, val, mkconf, conf) -> array # # updates +key+ in +mkconf+ with +val+, and all values depending on # the +key+ in +mkconf+. diff --git a/ruby/tool/mkrunnable.rb b/ruby/tool/mkrunnable.rb index 01756a352..3b71b0751 100755 --- a/ruby/tool/mkrunnable.rb +++ b/ruby/tool/mkrunnable.rb @@ -45,10 +45,23 @@ def clean_link(src, dest) def ln_safe(src, dest) ln_sf(src, dest) +rescue Errno::ENOENT + # Windows disallows to create broken symboic links, probably because + # it is a kind of reparse points. + raise if File.exist?(src) end alias ln_dir_safe ln_safe +case RUBY_PLATFORM +when /linux|darwin|solaris/ + def ln_exe(src, dest) + ln(src, dest, force: true) + end +else + alias ln_exe ln_safe +end + if !File.respond_to?(:symlink) && /mingw|mswin/ =~ (CROSS_COMPILING || RUBY_PLATFORM) extend Mswin end @@ -64,8 +77,8 @@ def relative_path_from(path, base) base = clean_path(base) path, base = [path, base].map{|s|s.split("/")} until path.empty? or base.empty? or path[0] != base[0] - path.shift - base.shift + path.shift + base.shift end path, base = [path, base].map{|s|s.join("/")} if /(\A|\/)\.\.\// =~ base @@ -76,10 +89,11 @@ def relative_path_from(path, base) end end -def ln_relative(src, dest) +def ln_relative(src, dest, executable = false) return if File.identical?(src, dest) parent = File.dirname(dest) File.directory?(parent) or mkdir_p(parent) + return ln_exe(src, dest) if executable clean_link(relative_path_from(src, parent), dest) {|s, d| ln_safe(s, d)} end @@ -112,9 +126,9 @@ def ln_dir_relative(src, dest) rubyw_install_name = config["rubyw_install_name"] goruby_install_name = "go" + ruby_install_name [ruby_install_name, rubyw_install_name, goruby_install_name].map do |ruby| - ruby += exeext - if ruby and !ruby.empty? and !File.file?(target = "#{bindir}/#{ruby}") - ln_relative(ruby, target) + if ruby and !ruby.empty? + ruby += exeext + ln_relative(ruby, "#{bindir}/#{ruby}", true) end end so = config["LIBRUBY_SO"] diff --git a/ruby/tool/pure_parser.rb b/ruby/tool/pure_parser.rb index 9ab663830..21c87cc5d 100755 --- a/ruby/tool/pure_parser.rb +++ b/ruby/tool/pure_parser.rb @@ -1,11 +1,14 @@ -#!/usr/bin/ruby -pi +#!/usr/bin/ruby -pi.bak BEGIN { + # pathological setting + ENV['LANG'] = ENV['LC_MESSAGES'] = ENV['LC_ALL'] = 'C' + require_relative 'lib/colorize' colorize = Colorize.new file = ARGV.shift begin - version = IO.popen(ARGV+%w[--version], &:read) + version = IO.popen(ARGV+%w[--version], "rb", &:read) rescue Errno::ENOENT abort "Failed to run `#{colorize.fail ARGV.join(' ')}'; You may have to install it." end @@ -18,3 +21,4 @@ ARGV.push(file) } $_.sub!(/^%define\s+api\.pure/, '%pure-parser') +$_.sub!(/^%define\s+.*/, '') diff --git a/ruby/tool/rbinstall.rb b/ruby/tool/rbinstall.rb index 060390626..0b1195e36 100755 --- a/ruby/tool/rbinstall.rb +++ b/ruby/tool/rbinstall.rb @@ -3,6 +3,8 @@ # Used by the "make install" target to install Ruby. # See common.mk for more details. +ENV["SDKROOT"] ||= "" if /darwin/ =~ RUBY_PLATFORM + begin load "./rbconfig.rb" rescue LoadError @@ -20,7 +22,6 @@ require 'shellwords' require 'optparse' require 'optparse/shellwords' -require 'ostruct' require 'rubygems' begin require "zlib" @@ -39,6 +40,7 @@ def parse_args(argv = ARGV) $make = 'make' $mflags = [] $install = [] + $installed = {} $installed_list = nil $exclude = [] $dryrun = false @@ -49,14 +51,17 @@ def parse_args(argv = ARGV) $dir_mode = nil $script_mode = nil $strip = false + $debug_symbols = nil $cmdtype = (if File::ALT_SEPARATOR == '\\' File.exist?("rubystub.exe") ? 'exe' : 'cmd' end) mflags = [] + gnumake = false opt = OptionParser.new opt.on('-n', '--dry-run') {$dryrun = true} opt.on('--dest-dir=DIR') {|dir| $destdir = dir} opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)} + opt.on('--ext-build-dir=DIR') {|v| $ext_build_dir = v } opt.on('--make=COMMAND') {|make| $make = make} opt.on('--mantype=MAN') {|man| $mantype = man} opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v| @@ -88,12 +93,14 @@ def parse_args(argv = ARGV) opt.on('--html-output [DIR]') {|dir| $htmldir = dir} opt.on('--cmd-type=TYPE', %w[cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')} opt.on('--[no-]strip') {|strip| $strip = strip} + opt.on('--gnumake') {gnumake = true} + opt.on('--debug-symbols=SUFFIX', /\w+/) {|name| $debug_symbols = ".#{name}"} opt.order!(argv) do |v| case v when /\AINSTALL[-_]([-\w]+)=(.*)/ argv.unshift("--#{$1.tr('_', '-')}=#{$2}") - when /\A\w[-\w+]*=\z/ + when /\A\w[-\w]*=/ mflags << v when /\A\w[-\w+]*\z/ $install << v.intern @@ -110,6 +117,7 @@ def parse_args(argv = ARGV) $make, *rest = Shellwords.shellwords($make) $mflags.unshift(*rest) unless rest.empty? $mflags.unshift(*mflags) + $mflags.reject! {|v| /\A-[OW]/ =~ v} if gnumake def $mflags.set?(flag) grep(/\A-(?!-).*#{flag.chr}/i) { return true } @@ -144,11 +152,16 @@ def $mflags.defined?(var) $dir_mode ||= $prog_mode | 0700 $script_mode ||= $prog_mode + if $ext_build_dir.nil? + raise OptionParser::MissingArgument.new("--ext-build-dir=DIR") + end end $install_procs = Hash.new {[]} def install?(*types, &block) - $install_procs[:all] <<= block + unless types.delete(:nodefault) + $install_procs[:all] <<= block + end types.each do |type| $install_procs[type] <<= block end @@ -170,9 +183,12 @@ def install(src, dest, options = {}) options = options.clone strip = options.delete(:strip) options[:preserve] = true + srcs = Array(src).select {|s| !$installed[$made_dirs[dest] ? File.join(dest, s) : dest]} + return if srcs.empty? + src = srcs if Array === src d = with_destdir(dest) super(src, d, **options) - srcs = Array(src) + srcs.each {|s| $installed[$made_dirs[dest] ? File.join(dest, s) : dest] = true} if strip d = srcs.map {|s| File.join(d, File.basename(s))} if $made_dirs[dest] strip_file(d) @@ -417,7 +433,6 @@ def CONFIG.[](name, mandatory = false) install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode) install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "rb_mjit_header-*.obj", :mode => $data_mode) install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "rb_mjit_header-*.pch", :mode => $data_mode) - install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "rb_mjit_header-*.pdb", :mode => $data_mode) end install?(:ext, :comm, :'ext-comm') do prepare "extension scripts", rubylibdir @@ -466,7 +481,7 @@ def CONFIG.[](name, mandatory = false) :""||{ ""=> %q<-*- ruby -*- @"%~dp0#{ruby_install_name}" -x "%~f0" %* @exit /b %ERRORLEVEL% -};{#\n#{prolog_script.gsub(/(?=\n)/, ' #')}>,\n} +};{ #\n#{prolog_script.gsub(/(?=\n)/, ' #')}>,\n} EOS PROLOG_SCRIPT.default = (load_relative || /\s/ =~ bindir) ? <"${prefix#/}"}) + Dir.glob(File.join(srcdir, "template/ruby-*db.in")) do |src| + cmd = $script_installer.transform(File.basename(src, ".in")) + open_for_install(File.join(bindir, cmd), $script_mode) { + RbConfig.expand(File.read(src), conf) + } + end + install File.join(srcdir, "misc/lldb_cruby.py"), File.join(rubylibdir, "lldb_cruby.py") + install File.join(srcdir, ".gdbinit"), File.join(rubylibdir, "gdbinit") + if $debug_symbols + { + ruby_install_name => bindir, + rubyw_install_name => bindir, + goruby_install_name => bindir, + dll => libdir, + }.each do |src, dest| + next if src.empty? + src += $debug_symbols + if File.directory?(src) + install_recursive src, File.join(dest, src) + end + end + end +end + module RbInstall + def self.no_write(options = nil) + u = File.umask(0022) + if $dryrun + fu = ::Object.class_eval do + fu = remove_const(:FileUtils) + const_set(:FileUtils, fu::NoWrite) + fu + end + dir_mode = options.delete(:dir_mode) if options + end + yield + ensure + options[:dir_mode] = dir_mode if dir_mode + if fu + ::Object.class_eval do + remove_const(:FileUtils) + const_set(:FileUtils, fu) + end + end + File.umask(u) + end + module Specs class FileCollector def initialize(gemspec) @@ -658,6 +733,16 @@ def collect (ruby_libraries + built_libraries).sort end + def skip_install?(files) + case type + when "ext" + # install ext only when it's configured + !File.exist?("#{$ext_build_dir}/#{relative_base}/Makefile") + when "lib" + files.empty? + end + end + private def type /\/(ext|lib)?\/.*?\z/ =~ @base_dir @@ -671,16 +756,29 @@ def ruby_libraries base = "#{prefix}#{relative_base}" when "lib" base = @base_dir - prefix = base.sub(/lib\/.*?\z/, "") + "lib/" + prefix = base.sub(/lib\/.*?\z/, "") + # for lib/net/net-smtp.gemspec + if m = File.basename(@gemspec, ".gemspec").match(/.*\-(.*)\z/) + base = "#{@base_dir}/#{m[1]}" unless remove_prefix(prefix, @base_dir).include?(m[1]) + end end - if base - Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| - remove_prefix(prefix, ruby_source) - end - else - [remove_prefix(File.dirname(@gemspec) + '/', @gemspec.gsub(/gemspec/, 'rb'))] + files = if base + Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| + remove_prefix(prefix, ruby_source) + end + else + [File.basename(@gemspec, '.gemspec') + '.rb'] + end + + case File.basename(@gemspec, ".gemspec") + when "net-http" + files << "lib/net/https.rb" + when "optparse" + files << "lib/optionparser.rb" end + + files end def built_libraries @@ -710,32 +808,44 @@ def remove_prefix(prefix, string) end end - class UnpackedInstaller < Gem::Installer - module DirPackage - def extract_files(destination_dir, pattern = "*") - path = File.dirname(@gem.path) - return if path == destination_dir - File.chmod(0700, destination_dir) - mode = pattern == "bin/*" ? $script_mode : $data_mode - spec.files.each do |f| - src = File.join(path, f) - dest = File.join(without_destdir(destination_dir), f) - makedirs(dest[/.*(?=\/)/m]) - install src, dest, :mode => mode - end - File.chmod($dir_mode, destination_dir) - end - end + class DirPackage + attr_reader :spec - def initialize(spec, *options) - super(spec.loaded_from, *options) - @package.extend(DirPackage).spec = spec + attr_accessor :dir_mode + attr_accessor :prog_mode + attr_accessor :data_mode + + def initialize(spec, dir_map = nil) + @spec = spec + @src_dir = File.dirname(@spec.loaded_from) + @dir_map = dir_map end - def write_cache_file + def extract_files(destination_dir, pattern = "*") + return if @src_dir == destination_dir + File.chmod(0700, destination_dir) unless $dryrun + mode = pattern == File.join(spec.bindir, '*') ? prog_mode : data_mode + destdir = without_destdir(destination_dir) + if @dir_map + (dir_map = @dir_map.map {|k, v| Regexp.quote(k) unless k == v}).compact! + dir_map = %r{\A(?:#{dir_map.join('|')})(?=/)} + end + spec.files.each do |f| + next unless File.fnmatch(pattern, f) + src = File.join(@src_dir, dir_map =~ f ? "#{@dir_map[$&]}#{$'}" : f) + dest = File.join(destdir, f) + makedirs(dest[/.*(?=\/)/m]) + install src, dest, :mode => mode + end + File.chmod(dir_mode, destination_dir) unless $dryrun end + end - def build_extensions + class GemInstaller < Gem::Installer + end + + class UnpackedInstaller < GemInstaller + def write_cache_file end def shebang(bin_file_name) @@ -771,102 +881,150 @@ def same_bin_script?(filename, bindir) end false end - end -end -class Gem::Installer - install = instance_method(:install) - define_method(:install) do - spec.post_install_message = nil - begin - u = File.umask(0022) - install.bind(self).call - ensure - File.umask(u) + def write_spec + super unless $dryrun + $installed_list.puts(without_destdir(spec_file)) if $installed_list + end + + def write_default_spec + super unless $dryrun + $installed_list.puts(without_destdir(default_spec_file)) if $installed_list end end - generate_bin_script = instance_method(:generate_bin_script) - define_method(:generate_bin_script) do |filename, bindir| - generate_bin_script.bind(self).call(filename, bindir) - File.chmod($script_mode, File.join(bindir, formatted_program_filename(filename))) + class GemInstaller + def install + spec.post_install_message = nil + RbInstall.no_write(options) {super} + end + + def generate_bin_script(filename, bindir) + name = formatted_program_filename(filename) + unless $dryrun + super + File.chmod($script_mode, File.join(bindir, name)) + end + $installed_list.puts(File.join(without_destdir(bindir), name)) if $installed_list + end + + def verify_gem_home # :nodoc: + end + + def ensure_writable_dir(dir) + $made_dirs.fetch(d = without_destdir(dir)) do + $made_dirs[d] = true + super unless $dryrun + $installed_list.puts(d+"/") if $installed_list + end + end end end # :startdoc: install?(:ext, :comm, :gem, :'default-gems', :'default-gems-comm') do - install_default_gem('lib', srcdir) + install_default_gem('lib', srcdir, bindir) end install?(:ext, :arch, :gem, :'default-gems', :'default-gems-arch') do - install_default_gem('ext', srcdir) + install_default_gem('ext', srcdir, bindir) end -def load_gemspec(file) +def load_gemspec(file, expanded = false) file = File.realpath(file) code = File.read(file, encoding: "utf-8:-") - code.gsub!(/`git.*?`/m, '""') - code.gsub!(/%x\[git.*?\]/m, '""') + code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m) do + files = [] + if expanded + base = File.dirname(file) + Dir.glob("**/*", File::FNM_DOTMATCH, base: base) do |n| + case File.basename(n); when ".", ".."; next; end + next if File.directory?(File.join(base, n)) + files << n.dump + end + end + "[" + files.join(", ") + "]" + end spec = eval(code, binding, file) unless Gem::Specification === spec raise TypeError, "[#{file}] isn't a Gem::Specification (#{spec.class} instead)." end spec.loaded_from = file + spec.files.reject! {|n| n.end_with?(".gemspec") or n.start_with?(".git")} + spec end -def install_default_gem(dir, srcdir) +def install_default_gem(dir, srcdir, bindir) gem_dir = Gem.default_dir - directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) - prepare "default gems from #{dir}", gem_dir, directories + install_dir = with_destdir(gem_dir) + prepare "default gems from #{dir}", gem_dir + RbInstall.no_write do + makedirs(Gem.ensure_default_gem_subdirectories(install_dir, $dir_mode).map {|d| File.join(gem_dir, d)}) + end - spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0]) - default_spec_dir = "#{spec_dir}/default" - makedirs(default_spec_dir) + options = { + :install_dir => with_destdir(gem_dir), + :bin_dir => with_destdir(bindir), + :ignore_dependencies => true, + :dir_mode => $dir_mode, + :data_mode => $data_mode, + :prog_mode => $script_mode, + :wrappers => true, + :format_executable => true, + :install_as_default => true, + } + default_spec_dir = Gem.default_specifications_dir gems = Dir.glob("#{srcdir}/#{dir}/**/*.gemspec").map {|src| spec = load_gemspec(src) file_collector = RbInstall::Specs::FileCollector.new(src) files = file_collector.collect - next if files.empty? + if file_collector.skip_install?(files) + next + end spec.files = files spec } gems.compact.sort_by(&:name).each do |gemspec| old_gemspecs = Dir[File.join(with_destdir(default_spec_dir), "#{gemspec.name}-*.gemspec")] if old_gemspecs.size > 0 - old_gemspecs.each {|spec| FileUtils.rm spec } + old_gemspecs.each {|spec| rm spec } end full_name = "#{gemspec.name}-#{gemspec.version}" - puts "#{INDENT}#{gemspec.name} #{gemspec.version}" - gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec") - open_for_install(gemspec_path, $data_mode) do - gemspec.to_ruby.gsub(/.*\0.*\n/, '') - end + gemspec.loaded_from = File.join srcdir, gemspec.spec_name - specific_gem_dir = File.join(gem_dir, 'gems', full_name) - - makedirs(specific_gem_dir) - - unless gemspec.executables.empty? then - bin_dir = File.join(specific_gem_dir, gemspec.bindir) - makedirs(bin_dir) - - gemspec.executables.map {|exec| - install File.join(srcdir, 'libexec', exec), - File.join(bin_dir, exec) - } - end + package = RbInstall::DirPackage.new gemspec, {gemspec.bindir => 'libexec'} + ins = RbInstall::UnpackedInstaller.new(package, options) + puts "#{INDENT}#{gemspec.name} #{gemspec.version}" + ins.install end end install?(:ext, :comm, :gem, :'bundled-gems') do + if CONFIG['CROSS_COMPILING'] == 'yes' + # The following hacky steps set "$ruby = BASERUBY" in tool/fake.rb + $hdrdir = '' + $extmk = nil + $ruby = nil # ... + ruby_path = $ruby + " -I#{Dir.pwd}" # $baseruby + " -I#{Dir.pwd}" + else + # ruby_path = File.expand_path(with_destdir(File.join(bindir, ruby_install_name))) + ENV['RUBYLIB'] = nil + ENV['RUBYOPT'] = nil + ruby_path = File.expand_path(with_destdir(File.join(bindir, ruby_install_name))) + " --disable=gems -I#{with_destdir(archlibdir)}" + end + Gem.instance_variable_set(:@ruby, ruby_path) if Gem.ruby != ruby_path + gem_dir = Gem.default_dir - directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) - prepare "bundled gems", gem_dir, directories install_dir = with_destdir(gem_dir) + prepare "bundled gems", gem_dir + RbInstall.no_write do + makedirs(Gem.ensure_gem_subdirectories(install_dir, $dir_mode).map {|d| File.join(gem_dir, d)}) + end + installed_gems = {} options = { :install_dir => install_dir, @@ -875,25 +1033,42 @@ def install_default_gem(dir, srcdir) :ignore_dependencies => true, :dir_mode => $dir_mode, :data_mode => $data_mode, - :prog_mode => $prog_mode, + :prog_mode => $script_mode, :wrappers => true, :format_executable => true, } gem_ext_dir = "#$extout/gems/#{CONFIG['arch']}" - extensions_dir = Gem::StubSpecification.gemspec_stub("", gem_dir, gem_dir).extensions_dir - dirs = Gem::Util.glob_files_in_dir "*/", "#{srcdir}/gems" - Gem::Specification.each_gemspec(dirs) do |path| - spec = load_gemspec(path) + extensions_dir = with_destdir(Gem::StubSpecification.gemspec_stub("", gem_dir, gem_dir).extensions_dir) + + File.foreach("#{srcdir}/gems/bundled_gems") do |name| + next if /^\s*(?:#|$)/ =~ name + next unless /^(\S+)\s+(\S+).*/ =~ name + gem_name = "#$1-#$2" + path = "#{srcdir}/.bundle/gems/#{gem_name}/#{gem_name}.gemspec" + if File.exist?(path) + spec = load_gemspec(path) + else + path = "#{srcdir}/.bundle/gems/#{gem_name}/#$1.gemspec" + next unless File.exist?(path) + spec = load_gemspec(path, true) + end next unless spec.platform == Gem::Platform::RUBY - next unless spec.full_name == path[srcdir.size..-1][/\A\/gems\/([^\/]+)/, 1] + next unless spec.full_name == gem_name + if !spec.extensions.empty? && CONFIG["EXTSTATIC"] == "static" + puts "skip installation of #{spec.name} #{spec.version}; bundled gem with an extension library is not supported on --with-static-linked-ext" + next + end spec.extension_dir = "#{extensions_dir}/#{spec.full_name}" if File.directory?(ext = "#{gem_ext_dir}/#{spec.full_name}") spec.extensions[0] ||= "-" end - ins = RbInstall::UnpackedInstaller.new(spec, options) + package = RbInstall::DirPackage.new spec + ins = RbInstall::UnpackedInstaller.new(package, options) puts "#{INDENT}#{spec.name} #{spec.version}" ins.install - File.chmod($data_mode, File.join(install_dir, "specifications", "#{spec.full_name}.gemspec")) + unless $dryrun + File.chmod($data_mode, File.join(install_dir, "specifications", "#{spec.full_name}.gemspec")) + end unless spec.extensions.empty? install_recursive(ext, spec.extension_dir) end @@ -901,6 +1076,7 @@ def install_default_gem(dir, srcdir) end installed_gems, gems = Dir.glob(srcdir+'/gems/*.gem').partition {|gem| installed_gems.key?(File.basename(gem, '.gem'))} unless installed_gems.empty? + prepare "bundled gem cache", gem_dir+"/cache" install installed_gems, gem_dir+"/cache" end next if gems.empty? @@ -908,8 +1084,9 @@ def install_default_gem(dir, srcdir) Gem.instance_variable_set(:@ruby, with_destdir(File.join(bindir, ruby_install_name))) silent = Gem::SilentUI.new gems.each do |gem| - inst = Gem::Installer.new(gem, options) - inst.spec.extension_dir = with_destdir(inst.spec.extension_dir) + package = Gem::Package.new(gem) + inst = RbInstall::GemInstaller.new(package, options) + inst.spec.extension_dir = "#{extensions_dir}/#{inst.spec.full_name}" begin Gem::DefaultUserInteraction.use_ui(silent) {inst.install} rescue Gem::InstallError diff --git a/ruby/tool/rbuninstall.rb b/ruby/tool/rbuninstall.rb index eb324c966..f0c286012 100755 --- a/ruby/tool/rbuninstall.rb +++ b/ruby/tool/rbuninstall.rb @@ -23,14 +23,15 @@ $files = [] } list = ($_.chomp!('/') ? $dirs : $files) -$_ = File.join($destdir, $_) if $destdir list << $_ END { status = true - $\ = ors = (!$dryrun and $tty) ? "\e[K\r" : "\n" + $\ = nil + ors = (!$dryrun and $tty) ? "\e[K\r" : "\n" $files.each do |file| - print "rm #{file}" + print "rm #{file}#{ors}" unless $dryrun + file = File.join($destdir, file) if $destdir begin File.unlink(file) rescue Errno::ENOENT @@ -45,15 +46,17 @@ unlink[dir] = true end while dir = $dirs.pop - print "rmdir #{dir}" + dir = File.dirname(dir) while File.basename(dir) == '.' + print "rmdir #{dir}#{ors}" unless $dryrun + realdir = $destdir ? File.join($destdir, dir) : dir begin begin unlink.delete(dir) - Dir.rmdir(dir) + Dir.rmdir(realdir) rescue Errno::ENOTDIR - raise unless File.symlink?(dir) - File.unlink(dir) + raise unless File.symlink?(realdir) + File.unlink(realdir) end rescue Errno::ENOENT, Errno::ENOTEMPTY rescue @@ -65,7 +68,6 @@ end end end - $\ = nil print ors.chomp exit(status) } diff --git a/ruby/tool/redmine-backporter.rb b/ruby/tool/redmine-backporter.rb index 9281219fa..df54c7eb2 100755 --- a/ruby/tool/redmine-backporter.rb +++ b/ruby/tool/redmine-backporter.rb @@ -241,7 +241,12 @@ def find_svn_log(pattern) end def find_git_log(pattern) - `git #{RUBY_REPO_PATH ? "-C #{RUBY_REPO_PATH.shellecape}" : ""} log --grep="#{pattern}"` + `git #{RUBY_REPO_PATH ? "-C #{RUBY_REPO_PATH.shellescape}" : ""} log --grep="#{pattern}"` +end + +def has_commit(commit, branch) + base = RUBY_REPO_PATH ? ["-C", RUBY_REPO_PATH.shellescape] : nil + system("git", *base, "merge-base", "--is-ancestor", commit, branch) end def show_last_journal(http, uri) @@ -269,14 +274,8 @@ def backport_command_string @changesets = @changesets.select do |c| next false if c.match(/\A\d{1,6}\z/) # skip SVN revision - # check if the Git revision is included in trunk - begin - uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/git/revisions/#{c}") - uri.read($openuri_options) - true - rescue - false - end + # check if the Git revision is included in master + has_commit(c, "master") end @changesets.define_singleton_method(:validated){true} end @@ -301,7 +300,7 @@ class CommandSyntaxError < RuntimeError; end commands = { "ls" => proc{|args| raise CommandSyntaxError unless /\A(\d+)?\z/ =~ args - uri = URI(REDMINE_BASE+'/projects/ruby-trunk/issues.json?'+URI.encode_www_form(@query.dup.merge('page' => ($1 ? $1.to_i : 1)))) + uri = URI(REDMINE_BASE+'/projects/ruby-master/issues.json?'+URI.encode_www_form(@query.dup.merge('page' => ($1 ? $1.to_i : 1)))) # puts uri res = JSON(uri.read($openuri_options)) @issues = issues = res["issues"] @@ -379,10 +378,10 @@ class CommandSyntaxError < RuntimeError; end case args when /\Ar?(\d+)\z/ # SVN rev = $1 - uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/trunk/revisions/#{rev}/issues.json") + uri = URI("#{REDMINE_BASE}/projects/ruby-master/repository/trunk/revisions/#{rev}/issues.json") when /\A\h{7,40}\z/ # Git rev = args - uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/git/revisions/#{rev}/issues.json") + uri = URI("#{REDMINE_BASE}/projects/ruby-master/repository/git/revisions/#{rev}/issues.json") else raise CommandSyntaxError end @@ -423,9 +422,10 @@ class << @changesets }, "done" => proc{|args| - raise CommandSyntaxError unless /\A(\d+)?(?:\s*-- +(.*))?\z/ =~ args - notes = $2 + raise CommandSyntaxError unless /\A(\d+)?(?: by (\h+))?(?:\s*-- +(.*))?\z/ =~ args + notes = $3 notes.strip! if notes + rev = $2 if $1 i = $1.to_i i = @issues[i]["id"] if @issues && i < @issues.size @@ -436,7 +436,8 @@ class << @changesets next end - if system("svn info #{RUBY_REPO_PATH&.shellescape}", %i(out err) => IO::NULL) # SVN + if rev + elsif system("svn info #{RUBY_REPO_PATH&.shellescape}", %i(out err) => IO::NULL) # SVN if (log = find_svn_log("##@issue]")) && (/revision="(?\d+)/ =~ log) rev = "r#{rev}" end @@ -447,13 +448,21 @@ class << @changesets end if log && rev str = log[/merge revision\(s\) ([^:]+)(?=:)/] - str.insert(5, "d") - str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev} #{str}." + if str + str.insert(5, "d") + str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev} #{str}." + else + str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev}." + end if notes str << "\n" str << notes end notes = str + elsif rev && has_commit(rev, "ruby_#{TARGET_VERSION.tr('.','_')}") + # Backport commit's log doesn't have the issue number. + # Instead of that manually it's provided. + notes = "ruby_#{TARGET_VERSION.tr('.','_')} commit:#{rev}." else puts "no commit is found whose log include ##@issue" next diff --git a/ruby/tool/releng/gen-mail.rb b/ruby/tool/releng/gen-mail.rb new file mode 100755 index 000000000..b958a64e6 --- /dev/null +++ b/ruby/tool/releng/gen-mail.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby +require "open-uri" +require "yaml" + +lang = ARGV.shift +unless lang + abort "usage: #$1 {en,ja} | pbcopy" +end + +# Confirm current directory is www.ruby-lang.org's working directory +def confirm_w_r_l_o_wd + File.foreach('.git/config') do |line| + return true if line.include?('git@github.com:ruby/www.ruby-lang.org.git') + end + abort "Run this script in www.ruby-lang.org's working directory" +end +confirm_w_r_l_o_wd + +releases = YAML.load_file('_data/releases.yml') + +url = "https://hackmd.io/@naruse/ruby-relnote-#{lang}/download" +src = URI(url).read +src.gsub!(/[ \t]+$/, "") +src.sub!(/(?" | first %}`] +end + +release = releases.find{|rel|rel['version'] == version} +unless release + abort "#{version} is not found in '_data/releases.yml'" +end + +src.gsub!(/^{% assign .*\n/, '') +src.gsub!(/\{\{(.*?)\}\}/) do + var = $1.strip + case var + when /\Arelease\.(.*)/ + val = release.dig(*$1.split('.')) + raise "invalid variable '#{var}'" unless val + else + raise "unknown variable '#{var}'" + end + val +end +puts src diff --git a/ruby/tool/releng/gen-release-note.rb b/ruby/tool/releng/gen-release-note.rb new file mode 100755 index 000000000..5afd11b79 --- /dev/null +++ b/ruby/tool/releng/gen-release-note.rb @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'open-uri' +require 'time' +require 'yaml' + +# Confirm current directory is www.ruby-lang.org's working directory +def confirm_w_r_l_o_wd + File.foreach('.git/config') do |line| + return true if line.include?('git@github.com:ruby/www.ruby-lang.org.git') + end + abort "Run this script in www.ruby-lang.org's working directory" +end +confirm_w_r_l_o_wd + +%w[ + https://hackmd.io/@naruse/ruby-relnote-en/download + https://hackmd.io/@naruse/ruby-relnote-ja/download +].each do |url| + src = URI(url).read + src.gsub!(/[ \t]+$/, "") + src.sub!(/\s+\z/, "\n") + src.sub!(/^breaks: false\n/, '') + if /^\{% assign release = site.data.releases \| where: "version", "([^"]+)" \| first %\}/ =~ src + version = $1 + else + abort %[#{url} doesn't include `{% assign release = site.data.releases | where: "version", "" | first %}`] + end + puts "#{url} -> #{version}" + + + # Write release note article + path = Time.parse(src[/^date: (.*)/, 1]). + strftime("./#{src[/^lang: (\w+)/, 1]}/news/_posts/%Y-%m-%d-ruby-#{version.tr('.', '-')}-released.md") + puts path + File.write(path, src) +end diff --git a/ruby/tool/releng/update-www-meta.rb b/ruby/tool/releng/update-www-meta.rb new file mode 100755 index 000000000..8a5651dcd --- /dev/null +++ b/ruby/tool/releng/update-www-meta.rb @@ -0,0 +1,213 @@ +#!/usr/bin/env ruby +require "open-uri" +require "yaml" + +class Tarball + attr_reader :version, :size, :sha1, :sha256, :sha512 + + def initialize(version, url, size, sha1, sha256, sha512) + @url = url + @size = size + @sha1 = sha1 + @sha256 = sha256 + @sha512 = sha512 + @version = version + @xy = version[/\A\d+\.\d+/] + end + + def gz?; @url.end_with?('.gz'); end + def zip?; @url.end_with?('.zip'); end + def xz?; @url.end_with?('.xz'); end + + def ext; @url[/(?:zip|tar\.(?:gz|xz))\z/]; end + + def to_md + < + + SIZE: #{@size} bytes + SHA1: #{@sha1} + SHA256: #{@sha256} + SHA512: #{@sha512} +eom + end + + # * /home/naruse/obj/ruby-trunk/tmp/ruby-2.6.0-preview3.tar.gz + # SIZE: 17116009 bytes + # SHA1: 21f62c369661a2ab1b521fd2fa8191a4273e12a1 + # SHA256: 97cea8aa63dfa250ba6902b658a7aa066daf817b22f82b7ee28f44aec7c2e394 + # SHA512: 1e2042324821bb4e110af7067f52891606dcfc71e640c194ab1c117f0b941550e0b3ac36ad3511214ac80c536b9e5cfaf8789eec74cf56971a832ea8fc4e6d94 + def self.parse(wwwdir, version) + unless /\A(\d+)\.(\d+)\.(\d+)(?:-(?:preview|rc)\d+)?\z/ =~ version + raise "unexpected version string '#{version}'" + end + x = $1.to_i + y = $2.to_i + z = $3.to_i + # previous tag for git diff --shortstat + # It's only for x.y.0 release + if z != 0 + prev_tag = nil + elsif y != 0 + prev_tag = "v#{x}_#{y-1}_0" + prev_ver = "#{x}.#{y-1}.0" + elsif x == 3 && y == 0 && z == 0 + prev_tag = "v2_7_0" + prev_ver = "2.7.0" + else + raise "unexpected version for prev_ver '#{version}'" + end + + uri = "https://cache.ruby-lang.org/pub/tmp/ruby-info-#{version}-draft.yml" + info = YAML.load(URI(uri).read) + if info.size != 1 + raise "unexpected info.yml '#{uri}'" + end + tarballs = [] + info[0]["size"].each_key do |ext| + url = info[0]["url"][ext] + size = info[0]["size"][ext] + sha1 = info[0]["sha1"][ext] + sha256 = info[0]["sha256"][ext] + sha512 = info[0]["sha512"][ext] + tarball = Tarball.new(version, url, size, sha1, sha256, sha512) + tarballs << tarball + end + + if prev_tag + # show diff shortstat + tag = "v#{version.gsub(/[.\-]/, '_')}" + rubydir = File.expand_path(File.join(__FILE__, '../../../')) + puts %`git -C #{rubydir} diff --shortstat #{prev_tag}..#{tag}` + stat = `git -C #{rubydir} diff --shortstat #{prev_tag}..#{tag}` + files_changed, insertions, deletions = stat.scan(/\d+/) + end + + xy = version[/\A\d+\.\d+/] + #puts "## Download\n\n" + #tarballs.each do |tarball| + # puts tarball.to_md + #end + update_branches_yml(version, xy, wwwdir) + update_downloads_yml(version, xy, wwwdir) + update_releases_yml(version, xy, tarballs, wwwdir, files_changed, insertions, deletions) + end + + def self.update_branches_yml(ver, xy, wwwdir) + filename = "_data/branches.yml" + data = File.read(File.join(wwwdir, filename)) + if data.include?("\n- name: #{xy}\n") + data.sub!(/\n- name: #{Regexp.escape(xy)}\n(?: .*\n)*/) do |node| + unless ver.include?("-") + # assume this is X.Y.0 release + node.sub!(/^ status: preview\n/, " status: normal maintenance\n") + node.sub!(/^ date:\n/, " date: #{Time.now.year}-12-25\n") + end + node + end + else + if ver.include?("-") + status = "preview" + year = nil + else + status = "normal maintenance" + year = Time.now.year + end + entry = <" + end + confirm_w_r_l_o_wd + version = ARGV.shift + Tarball.parse(Dir.pwd, version) +end + +main diff --git a/ruby/tool/ruby_vm/helpers/c_escape.rb b/ruby/tool/ruby_vm/helpers/c_escape.rb index 3e2bf2e02..34fafd1e3 100644 --- a/ruby/tool/ruby_vm/helpers/c_escape.rb +++ b/ruby/tool/ruby_vm/helpers/c_escape.rb @@ -17,7 +17,7 @@ module RubyVM::CEscape # generate comment, with escaps. def commentify str - return "/* #{str.strip.b.gsub '*/', '*\\/'} */" + return "/* #{str.b.gsub('*/', '*\\/').gsub('/*', '/\\*')} */" end # Mimic gensym of CL. @@ -46,7 +46,7 @@ def rstring2cstr str # I believe this is the fastest implementation done in pure-ruby. # Constants cached, gsub skips block evaluation, string literal optimized. buf = str.b - buf.gsub! %r/./n, RString2CStr + buf.gsub! %r/./nm, RString2CStr return %'"#{buf}"' end @@ -60,7 +60,7 @@ def rstring2cstr str "\x18"=>"\\x18", "\x19"=>"\\x19", "\x1A"=>"\\x1a", "\e"=>"\\x1b", "\x1C"=>"\\x1c", "\x1D"=>"\\x1d", "\x1E"=>"\\x1e", "\x1F"=>"\\x1f", " "=> " ", "!"=> "!", "\""=> "\\\"", "#"=> "#", - "$"=> "$", "%"=> "%", "&"=> "&", "'"=> "\\'", + "$"=> "$", "%"=> "%", "&"=> "&", "'"=> "'", "("=> "(", ")"=> ")", "*"=> "*", "+"=> "+", ","=> ",", "-"=> "-", "."=> ".", "/"=> "/", "0"=> "0", "1"=> "1", "2"=> "2", "3"=> "3", diff --git a/ruby/tool/ruby_vm/helpers/dumper.rb b/ruby/tool/ruby_vm/helpers/dumper.rb index 00c301c01..98104f4b9 100644 --- a/ruby/tool/ruby_vm/helpers/dumper.rb +++ b/ruby/tool/ruby_vm/helpers/dumper.rb @@ -25,7 +25,8 @@ def new_binding end def new_erb spec - path = Pathname.new(__FILE__).relative_path_from(Pathname.pwd).dirname + path = Pathname.new(__FILE__) + path = (path.relative_path_from(Pathname.pwd) rescue path).dirname path += '../views' path += spec src = path.read mode: 'rt:utf-8:utf-8' diff --git a/ruby/tool/ruby_vm/helpers/scanner.rb b/ruby/tool/ruby_vm/helpers/scanner.rb index 593271a41..ef6de8120 100644 --- a/ruby/tool/ruby_vm/helpers/scanner.rb +++ b/ruby/tool/ruby_vm/helpers/scanner.rb @@ -20,7 +20,8 @@ class RubyVM::Scanner attr_reader :__LINE__ def initialize path - src = Pathname.new(__FILE__).relative_path_from(Pathname.pwd).dirname + src = Pathname.new(__FILE__) + src = (src.relative_path_from(Pathname.pwd) rescue src).dirname src += path @__LINE__ = 1 @__FILE__ = src.to_path diff --git a/ruby/tool/ruby_vm/loaders/insns_def.rb b/ruby/tool/ruby_vm/loaders/insns_def.rb index 47e4ba29f..034905f74 100644 --- a/ruby/tool/ruby_vm/loaders/insns_def.rb +++ b/ruby/tool/ruby_vm/loaders/insns_def.rb @@ -25,10 +25,10 @@ (? \g | \s ){0} (? [_a-zA-Z] [0-9_a-zA-Z]* ){0} (? (?: \g \g+ )* \g ){0} - (? \g \g+ \g | \.\.\. ){0} + (? \g \g+ \g ){0} (? (?# empty ) | void | - \g (?: \g* , \g* \g \g* )* ){0} + (?: \.\.\. | \g) (?: \g* , \g* \g \g* )* ){0} (? \g* // \s* attr \g+ (? \g ) \g+ (? \g ) \g* @@ -57,6 +57,10 @@ ope = split.(scanner["insn:opes"]) pop = split.(scanner["insn:pops"]) ret = split.(scanner["insn:rets"]) + if ope.include?("...") + raise sprintf("parse error at %s:%d:%s: operands cannot be variadic", + scanner.__FILE__, scanner.__LINE__, name) + end attrs = [] while l2 = scanner.scan(/\G#{grammar}\g/o) do diff --git a/ruby/tool/ruby_vm/models/bare_instructions.rb b/ruby/tool/ruby_vm/models/bare_instructions.rb index b0cc83a65..6b5f1f6cf 100755 --- a/ruby/tool/ruby_vm/models/bare_instructions.rb +++ b/ruby/tool/ruby_vm/models/bare_instructions.rb @@ -112,6 +112,10 @@ def always_leaf? @attrs.fetch('leaf').expr.expr == 'true;' end + def leaf_without_check_ints? + @attrs.fetch('leaf').expr.expr == 'leafness_of_check_ints;' + end + def handle_canary stmt # Stack canary is basically a good thing that we want to add, however: # diff --git a/ruby/tool/ruby_vm/models/typemap.rb b/ruby/tool/ruby_vm/models/typemap.rb index c4b13f67f..ed3aea7d2 100644 --- a/ruby/tool/ruby_vm/models/typemap.rb +++ b/ruby/tool/ruby_vm/models/typemap.rb @@ -14,7 +14,6 @@ "..." => %w[. TS_VARIABLE], "CALL_DATA" => %w[C TS_CALLDATA], "CDHASH" => %w[H TS_CDHASH], - "GENTRY" => %w[G TS_GENTRY], "IC" => %w[K TS_IC], "IVC" => %w[A TS_IVC], "ID" => %w[I TS_ID], diff --git a/ruby/tool/ruby_vm/views/_insn_entry.erb b/ruby/tool/ruby_vm/views/_insn_entry.erb index 90e1268d9..f34afddb1 100644 --- a/ruby/tool/ruby_vm/views/_insn_entry.erb +++ b/ruby/tool/ruby_vm/views/_insn_entry.erb @@ -24,7 +24,7 @@ INSN_ENTRY(<%= insn.name %>) <%= ope[:decl] %> = (<%= ope[:type] %>)GET_OPERAND(<%= i + 1 %>); % end # define INSN_ATTR(x) <%= insn.call_attribute(' ## x ## ') %> - bool leaf = INSN_ATTR(leaf); + const bool leaf = INSN_ATTR(leaf); % insn.pops.reverse_each.with_index.reverse_each do |pop, i| <%= pop[:decl] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>; % end @@ -39,7 +39,7 @@ INSN_ENTRY(<%= insn.name %>) % if insn.handles_sp? POPN(INSN_ATTR(popn)); % end -<%= insn.handle_canary "SETUP_CANARY()" -%> +<%= insn.handle_canary "SETUP_CANARY(leaf)" -%> COLLECT_USAGE_INSN(INSN_ATTR(bin)); % insn.opes.each_with_index do |ope, i| COLLECT_USAGE_OPERAND(INSN_ATTR(bin), <%= i %>, <%= ope[:name] %>); @@ -55,7 +55,7 @@ INSN_ENTRY(<%= insn.name %>) /* ### Instruction trailers. ### */ CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, INSN_ATTR(retn)); -<%= insn.handle_canary "CHECK_CANARY()" -%> +<%= insn.handle_canary "CHECK_CANARY(leaf, INSN_ATTR(bin))" -%> % if insn.handles_sp? % insn.rets.reverse_each do |ret| PUSH(<%= insn.cast_to_VALUE ret %>); diff --git a/ruby/tool/ruby_vm/views/_insn_len_info.erb b/ruby/tool/ruby_vm/views/_insn_len_info.erb index b292f42fb..569dca584 100644 --- a/ruby/tool/ruby_vm/views/_insn_len_info.erb +++ b/ruby/tool/ruby_vm/views/_insn_len_info.erb @@ -7,15 +7,22 @@ %# details. CONSTFUNC(MAYBE_UNUSED(static int insn_len(VALUE insn))); -int -insn_len(VALUE i) -{ - static const char t[] = { +RUBY_SYMBOL_EXPORT_BEGIN /* for debuggers */ +extern const uint8_t rb_vm_insn_len_info[VM_INSTRUCTION_SIZE]; +RUBY_SYMBOL_EXPORT_END + +#ifdef RUBY_VM_INSNS_INFO +const uint8_t rb_vm_insn_len_info[] = { % RubyVM::Instructions.each_slice 23 do |a| - <%= a.map(&:width).join(', ') -%>, + <%= a.map(&:width).join(', ') -%>, % end - }; +}; - ASSERT_VM_INSTRUCTION_SIZE(t); - return t[i]; +ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_len_info); +#endif + +int +insn_len(VALUE i) +{ + return rb_vm_insn_len_info[i]; } diff --git a/ruby/tool/ruby_vm/views/_insn_name_info.erb b/ruby/tool/ruby_vm/views/_insn_name_info.erb index 767346093..e7ded75e6 100644 --- a/ruby/tool/ruby_vm/views/_insn_name_info.erb +++ b/ruby/tool/ruby_vm/views/_insn_name_info.erb @@ -13,26 +13,32 @@ % CONSTFUNC(MAYBE_UNUSED(static const char *insn_name(VALUE insn))); +RUBY_SYMBOL_EXPORT_BEGIN /* for debuggers */ +extern const int rb_vm_max_insn_name_size; +extern const char rb_vm_insn_name_base[]; +extern const unsigned short rb_vm_insn_name_offset[VM_INSTRUCTION_SIZE]; +RUBY_SYMBOL_EXPORT_END + #ifdef RUBY_VM_INSNS_INFO const int rb_vm_max_insn_name_size = <%= a.map(&:size).max %>; -#endif -const char * -insn_name(VALUE i) -{ - static const char x[] = +const char rb_vm_insn_name_base[] = % a.each do |i| - <%=cstr i%> "\0" + <%=cstr i%> "\0" % end - ; + ; - static const unsigned short y[] = { +const unsigned short rb_vm_insn_name_offset[] = { % c.each_slice 12 do |d| - <%= d.map {|i| sprintf("%4d", i) }.join(', ') %>, + <%= d.map {|i| sprintf("%4d", i) }.join(', ') %>, % end - }; +}; - ASSERT_VM_INSTRUCTION_SIZE(y); +ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_name_offset); +#endif - return &x[y[i]]; +const char * +insn_name(VALUE i) +{ + return &rb_vm_insn_name_base[rb_vm_insn_name_offset[i]]; } diff --git a/ruby/tool/ruby_vm/views/_insn_operand_info.erb b/ruby/tool/ruby_vm/views/_insn_operand_info.erb index 69d361521..996c33e96 100644 --- a/ruby/tool/ruby_vm/views/_insn_operand_info.erb +++ b/ruby/tool/ruby_vm/views/_insn_operand_info.erb @@ -14,24 +14,31 @@ CONSTFUNC(MAYBE_UNUSED(static const char *insn_op_types(VALUE insn))); CONSTFUNC(MAYBE_UNUSED(static int insn_op_type(VALUE insn, long pos))); -const char * -insn_op_types(VALUE i) -{ - static const char x[] = +RUBY_SYMBOL_EXPORT_BEGIN /* for debuggers */ +extern const char rb_vm_insn_op_base[]; +extern const unsigned short rb_vm_insn_op_offset[VM_INSTRUCTION_SIZE]; +RUBY_SYMBOL_EXPORT_END + +#ifdef RUBY_VM_INSNS_INFO +const char rb_vm_insn_op_base[] = % a.each_slice 5 do |d| - <%= d.map {|i| sprintf("%-6s", cstr(i)) }.join(' "\0" ') %> "\0" + <%= d.map {|i| sprintf("%-6s", cstr(i)) }.join(' "\0" ') %> "\0" % end - ; + ; - static const unsigned short y[] = { +const unsigned short rb_vm_insn_op_offset[] = { % c.each_slice 12 do |d| - <%= d.map {|i| sprintf("%3d", i) }.join(', ') %>, + <%= d.map {|i| sprintf("%3d", i) }.join(', ') %>, % end - }; +}; - ASSERT_VM_INSTRUCTION_SIZE(y); +ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_op_offset); +#endif - return &x[y[i]]; +const char * +insn_op_types(VALUE i) +{ + return &rb_vm_insn_op_base[rb_vm_insn_op_offset[i]]; } int diff --git a/ruby/tool/ruby_vm/views/_leaf_helpers.erb b/ruby/tool/ruby_vm/views/_leaf_helpers.erb index ac60f2dcb..1735db219 100644 --- a/ruby/tool/ruby_vm/views/_leaf_helpers.erb +++ b/ruby/tool/ruby_vm/views/_leaf_helpers.erb @@ -8,72 +8,18 @@ %; #line <%= __LINE__ + 1 %> <%=cstr __FILE__ %> -static bool -leafness_of_getglobal(VALUE gentry) -{ - const struct rb_global_entry *e = (void *)gentry; - - if (UNLIKELY(rb_gvar_is_traced(e))) { - return false; - } - else { - /* We cannot write this function using a switch() because a - * case label cannot be a function pointer. */ - static rb_gvar_getter_t *const allowlist[] = { - rb_gvar_val_getter, - rb_gvar_var_getter, - /* rb_gvar_undef_getter issues rb_warning() */ - }; - rb_gvar_getter_t *f = rb_gvar_getter_function_of(e); - int i; - - for (i = 0; i < numberof(allowlist); i++) { - if (f == allowlist[i]) { - return true; - } - } - return false; - } -} - -static bool -leafness_of_setglobal(VALUE gentry) -{ - const struct rb_global_entry *e = (void *)gentry; - - if (UNLIKELY(rb_gvar_is_traced(e))) { - return false; - } - else { - /* We cannot write this function using a switch() because a - * case label cannot be a function pointer. */ - static rb_gvar_setter_t *const allowlist[] = { - rb_gvar_val_setter, - /* rb_gvar_readonly_setter issues rb_name_error() */ - rb_gvar_var_setter, - rb_gvar_undef_setter, - }; - rb_gvar_setter_t *f = rb_gvar_setter_function_of(e); - int i; - - for (i = 0; i < numberof(allowlist); i++) { - if (f == allowlist[i]) { - return true; - } - } - return false; - } -} - #include "iseq.h" +// This is used to tell MJIT that this insn would be leaf if CHECK_INTS didn't exist. +// It should be used only when RUBY_VM_CHECK_INTS is directly written in insns.def. +static bool leafness_of_check_ints = false; + static bool leafness_of_defined(rb_num_t op_type) { /* see also: vm_insnhelper.c:vm_defined() */ switch (op_type) { case DEFINED_IVAR: - case DEFINED_IVAR2: case DEFINED_GVAR: case DEFINED_CVAR: case DEFINED_YIELD: diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb b/ruby/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb new file mode 100644 index 000000000..d4eb4977a --- /dev/null +++ b/ruby/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb @@ -0,0 +1,31 @@ +% # -*- C -*- +% # Copyright (c) 2020 Takashi Kokubun. 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. +% +% # compiler: Declare dst and ic +% insn.opes.each_with_index do |ope, i| + <%= ope.fetch(:decl) %> = (<%= ope.fetch(:type) %>)operands[<%= i %>]; +% end + +% # compiler: Capture IC values, locking getinlinecache + struct iseq_inline_constant_cache_entry *ice = ic->entry; + if (ice != NULL && GET_IC_SERIAL(ice) && !status->compile_info->disable_const_cache) { +% # JIT: Inline everything in IC, and cancel the slow path + fprintf(f, " if (vm_inlined_ic_hit_p(0x%"PRIxVALUE", 0x%"PRIxVALUE", (const rb_cref_t *)0x%"PRIxVALUE", %"PRI_SERIALT_PREFIX"u, reg_cfp->ep)) {", ice->flags, ice->value, (VALUE)ice->ic_cref, GET_IC_SERIAL(ice)); + fprintf(f, " stack[%d] = 0x%"PRIxVALUE";\n", b->stack_size, ice->value); + fprintf(f, " goto label_%d;\n", pos + insn_len(insn) + (int)dst); + fprintf(f, " }"); + fprintf(f, " else {"); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); + fprintf(f, " goto const_cancel;\n"); + fprintf(f, " }"); + +% # compiler: Move JIT compiler's internal stack pointer + b->stack_size += <%= insn.call_attribute('sp_inc') %>; + break; + } diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_insn.erb b/ruby/tool/ruby_vm/views/_mjit_compile_insn.erb index 8f4512161..f54d1b0e0 100644 --- a/ruby/tool/ruby_vm/views/_mjit_compile_insn.erb +++ b/ruby/tool/ruby_vm/views/_mjit_compile_insn.erb @@ -7,7 +7,6 @@ % # details. fprintf(f, "{\n"); { - MAYBE_UNUSED(int pc_moved_p) = FALSE; % # compiler: Prepare operands which may be used by `insn.call_attribute` % insn.opes.each_with_index do |ope, i| MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>]; @@ -35,7 +34,7 @@ % when 'ID' comment_id(f, (ID)operands[<%= i %>]); % when 'CALL_DATA' - comment_id(f, ((CALL_DATA)operands[<%= i %>])->ci.mid); + comment_id(f, vm_ci_mid(((CALL_DATA)operands[<%= i %>])->ci)); % when 'VALUE' if (SYMBOL_P((VALUE)operands[<%= i %>])) comment_id(f, SYM2ID((VALUE)operands[<%= i %>])); % end @@ -60,7 +59,8 @@ % end % % # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow. -% unless insn.always_leaf? +% # leaf insn may not cancel JIT. leaf_without_check_ints is covered in RUBY_VM_CHECK_INTS of _mjit_compile_insn_body.erb. +% unless insn.always_leaf? || insn.leaf_without_check_ints? fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n"); fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>); if (!pc_moved_p) { diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_insn_body.erb b/ruby/tool/ruby_vm/views/_mjit_compile_insn_body.erb index a2a750fbd..187e04383 100644 --- a/ruby/tool/ruby_vm/views/_mjit_compile_insn_body.erb +++ b/ruby/tool/ruby_vm/views/_mjit_compile_insn_body.erb @@ -20,14 +20,14 @@ % # For `leave`. We can't proceed next ISeq in the same JIT function. % expr.gsub!(/^(?\s*)RESTORE_REGS\(\);\n/) do % indent = Regexp.last_match[:indent] -% <<-RESTORE_REGS.gsub(/^ +/, '') +% <<-end.gsub(/^ +/, '') % #if OPT_CALL_THREADED_CODE % #{indent}rb_ec_thread_ptr(ec)->retval = val; % #{indent}return 0; % #else % #{indent}return val; % #endif -% RESTORE_REGS +% end % end % expr.gsub!(/^(?\s*)NEXT_INSN\(\);\n/) do % indent = Regexp.last_match[:indent] @@ -47,6 +47,20 @@ % # % # TODO: support combination of following macros in the same line % case line +% when /\A\s+RUBY_VM_CHECK_INTS\(ec\);\s+\z/ +% if insn.leaf_without_check_ints? # lazily move PC and optionalize mjit_call_p here + fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"); + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); /* ADD_PC(INSN_ATTR(width)); */ + fprintf(f, " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"); + fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n"); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n"); + fprintf(f, " goto cancel;\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); +% else + fprintf(f, <%= to_cstr.call(line) %>); +% end % when /\A\s+JUMP\((?[^)]+)\);\s+\z/ % dest = Regexp.last_match[:dest] % @@ -101,7 +115,7 @@ % # #define STACK_ADDR_FROM_TOP(n) (GET_SP()-(n)) % num = Regexp.last_match[:num] fprintf(f, <%= to_cstr.call(line.sub(/\bSTACK_ADDR_FROM_TOP\(([^)]+)\)/, '%s')) %>, - (status->local_stack_p ? "stack + (stack_size - (<%= num %>))" : "STACK_ADDR_FROM_TOP(<%= num %>)")); + (status->local_stack_p ? "(stack + (stack_size - (<%= num %>)))" : "STACK_ADDR_FROM_TOP(<%= num %>)")); % when /\bTOPN\((?[^)]+)\)/ % # #define TOPN(n) (*(GET_SP()-(n)-1)) % num = Regexp.last_match[:num] diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb b/ruby/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb new file mode 100644 index 000000000..a3796ffc5 --- /dev/null +++ b/ruby/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb @@ -0,0 +1,29 @@ +% # -*- C -*- +% # Copyright (c) 2020 Urabe, Shyouhei. 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. +% +% insn.opes.each_with_index do |ope, i| + <%= ope.fetch(:decl) %> = (<%= ope.fetch(:type) %>)operands[<%= i %>]; +% end + rb_snum_t sp_inc = <%= insn.call_attribute('sp_inc') %>; + unsigned sp = b->stack_size + (unsigned)sp_inc; + VM_ASSERT(b->stack_size > -sp_inc); + VM_ASSERT(sp_inc < UINT_MAX - b->stack_size); + + if (bf->compiler) { + fprintf(f, "{\n"); + fprintf(f, " VALUE val;\n"); + bf->compiler(f, <%= + insn.name == 'invokebuiltin' ? '-1' : '(rb_num_t)operands[1]' + %>, b->stack_size, body->builtin_inline_p); + fprintf(f, " stack[%u] = val;\n", sp - 1); + fprintf(f, "}\n"); +% if insn.name != 'opt_invokebuiltin_delegate_leave' + b->stack_size = sp; + break; +% end + } diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_ivar.erb b/ruby/tool/ruby_vm/views/_mjit_compile_ivar.erb index 57f8d14b7..5105584ba 100644 --- a/ruby/tool/ruby_vm/views/_mjit_compile_ivar.erb +++ b/ruby/tool/ruby_vm/views/_mjit_compile_ivar.erb @@ -16,33 +16,79 @@ % # compiler: Use copied IVC to avoid race condition IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache; % -% # compiler: Consider cfp->self as T_OBJECT if ic_copy->ic_serial is set - if (!status->compile_info->disable_ivar_cache && ic_copy->ic_serial) { + if (!status->compile_info->disable_ivar_cache && ic_copy->entry) { // Only ic_copy is enabled. % # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`. % # <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%> % -% # JIT: prepare vm_getivar's arguments and variables +% # JIT: prepare vm_getivar/vm_setivar arguments and variables fprintf(f, "{\n"); fprintf(f, " VALUE obj = GET_SELF();\n"); - fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->ic_serial); - fprintf(f, " const st_index_t index = %"PRIuSIZE";\n", ic_copy->index); -% # JIT: cache hit path of vm_getivar, or cancel JIT. + fprintf(f, " const uint32_t index = %u;\n", (ic_copy->entry->index)); + if (status->merge_ivar_guards_p) { +% # JIT: Access ivar without checking these VM_ASSERTed prerequisites as we checked them in the beginning of `mjit_compile_body` + fprintf(f, " VM_ASSERT(RB_TYPE_P(obj, T_OBJECT));\n"); + fprintf(f, " VM_ASSERT((rb_serial_t)%"PRI_SERIALT_PREFIX"u == RCLASS_SERIAL(RBASIC(obj)->klass));\n", ic_copy->entry->class_serial); + fprintf(f, " VM_ASSERT(index < ROBJECT_NUMIV(obj));\n"); % if insn.name == 'setinstancevariable' - fprintf(f, " VALUE val = stack[%d];\n", b->stack_size - 1); - fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && !RB_OBJ_FROZEN(obj))) {\n"); - fprintf(f, " VALUE *ptr = ROBJECT_IVPTR(obj);\n"); - fprintf(f, " RB_OBJ_WRITE(obj, &ptr[index], val);\n"); - fprintf(f, " }\n"); + fprintf(f, " if (LIKELY(!RB_OBJ_FROZEN_RAW(obj) && %s)) {\n", status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "true" : "RB_FL_ANY_RAW(obj, ROBJECT_EMBED)"); + fprintf(f, " RB_OBJ_WRITE(obj, &ROBJECT(obj)->as.%s, stack[%d]);\n", + status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "heap.ivptr[index]" : "ary[index]", b->stack_size - 1); + fprintf(f, " }\n"); +% else + fprintf(f, " VALUE val;\n"); + fprintf(f, " if (LIKELY(%s && (val = ROBJECT(obj)->as.%s) != Qundef)) {\n", + status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "true" : "RB_FL_ANY_RAW(obj, ROBJECT_EMBED)", + status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "heap.ivptr[index]" : "ary[index]"); + fprintf(f, " stack[%d] = val;\n", b->stack_size); + fprintf(f, " }\n"); +%end + } + else { + fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->entry->class_serial); +% # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar) +% if insn.name == 'setinstancevariable' + fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && !RB_OBJ_FROZEN_RAW(obj))) {\n"); + fprintf(f, " VALUE *ptr = ROBJECT_IVPTR(obj);\n"); + fprintf(f, " RB_OBJ_WRITE(obj, &ptr[index], stack[%d]);\n", b->stack_size - 1); + fprintf(f, " }\n"); % else + fprintf(f, " VALUE val;\n"); + fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n"); + fprintf(f, " stack[%d] = val;\n", b->stack_size); + fprintf(f, " }\n"); +% end + } + fprintf(f, " else {\n"); + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + fprintf(f, " goto ivar_cancel;\n"); + fprintf(f, " }\n"); + +% # compiler: Move JIT compiler's internal stack pointer + b->stack_size += <%= insn.call_attribute('sp_inc') %>; + fprintf(f, "}\n"); + break; + } +% if insn.name == 'getinstancevariable' + else if (!status->compile_info->disable_exivar_cache && ic_copy->entry) { +% # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`. +% # <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%> +% +% # JIT: prepare vm_getivar's arguments and variables + fprintf(f, "{\n"); + fprintf(f, " VALUE obj = GET_SELF();\n"); + fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->entry->class_serial); + fprintf(f, " const uint32_t index = %u;\n", ic_copy->entry->index); +% # JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization) + fprintf(f, " struct gen_ivtbl *ivtbl;\n"); fprintf(f, " VALUE val;\n"); - fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n"); + fprintf(f, " if (LIKELY(FL_TEST_RAW(obj, FL_EXIVAR) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl) && index < ivtbl->numiv && (val = ivtbl->ivptr[index]) != Qundef)) {\n"); fprintf(f, " stack[%d] = val;\n", b->stack_size); fprintf(f, " }\n"); -% end fprintf(f, " else {\n"); fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); - fprintf(f, " goto ivar_cancel;\n"); + fprintf(f, " goto exivar_cancel;\n"); fprintf(f, " }\n"); % # compiler: Move JIT compiler's internal stack pointer @@ -50,5 +96,6 @@ fprintf(f, "}\n"); break; } +% end } #endif // OPT_IC_FOR_IVAR diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb b/ruby/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb index 545b9f72f..390b3ce52 100644 --- a/ruby/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb +++ b/ruby/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb @@ -5,10 +5,12 @@ % # conditions mentioned in the file COPYING are met. Consult the file for % # details. % -% # JIT: Move pc for catch table on catch_except_p, and for #caller_locations and rb_profile_frames on !insn.always_leaf? - if (body->catch_except_p || <%= insn.always_leaf? ? 'FALSE' : 'TRUE' %>) { +% # JIT: When an insn is leaf, we don't need to Move pc for a catch table on catch_except_p, #caller_locations, +% # and rb_profile_frames. For check_ints, we lazily move PC when we have interruptions. + MAYBE_UNUSED(bool pc_moved_p) = false; + if (<%= !(insn.always_leaf? || insn.leaf_without_check_ints?) %>) { fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); /* ADD_PC(INSN_ATTR(width)); */ - pc_moved_p = TRUE; + pc_moved_p = true; } % % # JIT: move sp to use or preserve stack variables diff --git a/ruby/tool/ruby_vm/views/_mjit_compile_send.erb b/ruby/tool/ruby_vm/views/_mjit_compile_send.erb index ec8eec558..28e316a1e 100644 --- a/ruby/tool/ruby_vm/views/_mjit_compile_send.erb +++ b/ruby/tool/ruby_vm/views/_mjit_compile_send.erb @@ -8,100 +8,112 @@ % % # Optimized case of send / opt_send_without_block instructions. { - MAYBE_UNUSED(int pc_moved_p) = FALSE; % # compiler: Prepare operands which may be used by `insn.call_attribute` % insn.opes.each_with_index do |ope, i| MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>]; % end -% # compiler: Use copied cc to avoid race condition - CALL_CACHE cc_copy = status->cc_entries + call_data_index(cd, body); +% # compiler: Use captured cc to avoid race condition + size_t cd_index = call_data_index(cd, body); + const struct rb_callcache **cc_entries = captured_cc_entries(status); + const struct rb_callcache *captured_cc = cc_entries[cd_index]; % - if (!status->compile_info->disable_send_cache && has_valid_method_type(cc_copy)) { - const rb_iseq_t *iseq; - const CALL_INFO ci = &cd->ci; - unsigned int argc = ci->orig_argc; // this `argc` variable is for calculating a value's position on stack considering `blockarg`. -% if insn.name == 'send' - argc += ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0); // simulate `vm_caller_setup_arg_block`'s `--reg_cfp->sp` -% end +% # compiler: Inline send insn where some supported fastpath is used. + const rb_iseq_t *iseq = NULL; + const CALL_INFO ci = cd->ci; + int kw_splat = IS_ARGS_KW_SPLAT(ci) > 0; + extern bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci); + if (!status->compile_info->disable_send_cache && has_valid_method_type(captured_cc) && ( +% # `CC_SET_FASTPATH(cd->cc, vm_call_cfunc_with_frame, ...)` in `vm_call_cfunc` + (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC + && !rb_splat_or_kwargs_p(ci) && !kw_splat) +% # `CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(...), vm_call_iseq_optimizable_p(...))` in `vm_callee_setup_arg`, +% # and support only non-VM_CALL_TAILCALL path inside it + || (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_ISEQ + && fastpath_applied_iseq_p(ci, captured_cc, iseq = def_iseq_ptr(vm_cc_cme(captured_cc)->def)) + && !(vm_ci_flag(ci) & VM_CALL_TAILCALL)) + )) { + const bool cfunc_debug = false; // Set true when you want to see inlined cfunc + if (cfunc_debug && vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC) + fprintf(stderr, " * %s\n", rb_id2name(vm_ci_mid(ci))); - if (!(ci->flag & VM_CALL_TAILCALL) // inlining non-tailcall path - && cc_copy->me->def->type == VM_METHOD_TYPE_ISEQ && fastpath_applied_iseq_p(ci, cc_copy, iseq = def_iseq_ptr(cc_copy->me->def))) { // CC_SET_FASTPATH in vm_callee_setup_arg - int param_size = iseq->body->param.size; - - fprintf(f, "{\n"); -% # JIT: Declare stack_size to be used in some macro of _mjit_compile_insn_body.erb - if (status->local_stack_p) { - fprintf(f, " MAYBE_UNUSED(unsigned int) stack_size = %u;\n", b->stack_size); - } + int sp_inc = (int)sp_inc_of_sendish(ci); + fprintf(f, "{\n"); % # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things. - fprintf(f, " if (UNLIKELY(GET_GLOBAL_METHOD_STATE() != %"PRI_SERIALT_PREFIX"u ||\n", cc_copy->method_state); - fprintf(f, " RCLASS_SERIAL(CLASS_OF(stack[%d])) != %"PRI_SERIALT_PREFIX"u)) {\n", b->stack_size - 1 - argc, cc_copy->class_serial[0]); - fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); - fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); - fprintf(f, " goto send_cancel;\n"); - fprintf(f, " }\n"); + bool opt_class_of = !maybe_special_const_class_p(captured_cc->klass); // If true, use RBASIC_CLASS instead of CLASS_OF to reduce code size + fprintf(f, " const struct rb_callcache *cc = (const struct rb_callcache *)0x%"PRIxVALUE";\n", (VALUE)captured_cc); + fprintf(f, " const rb_callable_method_entry_t *cc_cme = (const rb_callable_method_entry_t *)0x%"PRIxVALUE";\n", (VALUE)vm_cc_cme(captured_cc)); + fprintf(f, " const VALUE recv = stack[%d];\n", b->stack_size + sp_inc - 1); + fprintf(f, " if (UNLIKELY(%s || !vm_cc_valid_p(cc, cc_cme, %s(recv)))) {\n", opt_class_of ? "RB_SPECIAL_CONST_P(recv)" : "false", opt_class_of ? "RBASIC_CLASS" : "CLASS_OF"); + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + fprintf(f, " goto send_cancel;\n"); + fprintf(f, " }\n"); % # JIT: move sp and pc if necessary <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%> % # JIT: If ISeq is inlinable, call the inlined method without pushing a frame. - if (status->inlined_iseqs != NULL && status->inlined_iseqs[pos] == iseq->body) { - fprintf(f, " {\n"); - fprintf(f, " VALUE orig_self = reg_cfp->self;\n"); - fprintf(f, " reg_cfp->self = stack[%d];\n", b->stack_size - argc - 1); - fprintf(f, " stack[%d] = _mjit_inlined_%d(ec, reg_cfp, orig_self, original_iseq);\n", b->stack_size - argc - 1, pos); - fprintf(f, " reg_cfp->self = orig_self;\n"); - fprintf(f, " }\n"); - } - else { -% # JIT: Print insn body in insns.def - fprintf(f, " {\n"); - fprintf(f, " struct rb_calling_info calling;\n"); + if (iseq && status->inlined_iseqs != NULL && iseq->body == status->inlined_iseqs[pos]) { + fprintf(f, " {\n"); + fprintf(f, " VALUE orig_self = reg_cfp->self;\n"); + fprintf(f, " reg_cfp->self = stack[%d];\n", b->stack_size + sp_inc - 1); + fprintf(f, " stack[%d] = _mjit%d_inlined_%d(ec, reg_cfp, orig_self, original_iseq);\n", b->stack_size + sp_inc - 1, status->compiled_id, pos); + fprintf(f, " reg_cfp->self = orig_self;\n"); + fprintf(f, " }\n"); + } + else { +% # JIT: Forked `vm_sendish` (except method_explorer = vm_search_method_wrap) to inline various things + fprintf(f, " {\n"); + fprintf(f, " VALUE val;\n"); + fprintf(f, " struct rb_calling_info calling;\n"); % if insn.name == 'send' - fprintf(f, " calling.block_handler = vm_caller_setup_arg_block(ec, reg_cfp, (CALL_INFO)0x%"PRIxVALUE", (rb_iseq_t *)0x%"PRIxVALUE", FALSE);\n", (VALUE)ci, (VALUE)blockiseq); + fprintf(f, " calling.block_handler = vm_caller_setup_arg_block(ec, reg_cfp, (const struct rb_callinfo *)0x%"PRIxVALUE", (rb_iseq_t *)0x%"PRIxVALUE", FALSE);\n", (VALUE)ci, (VALUE)blockiseq); % else - fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n"); + fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n"); % end - fprintf(f, " calling.argc = %d;\n", ci->orig_argc); - fprintf(f, " calling.recv = stack[%d];\n", b->stack_size - 1 - argc); + fprintf(f, " calling.kw_splat = %d;\n", kw_splat); + fprintf(f, " calling.recv = stack[%d];\n", b->stack_size + sp_inc - 1); + fprintf(f, " calling.argc = %d;\n", vm_ci_argc(ci)); -% # JIT: Special CALL_METHOD. Bypass cc_copy->call and inline vm_call_iseq_setup_normal for vm_call_iseq_setup_func FASTPATH. - fprintf(f, " {\n"); - fprintf(f, " VALUE v;\n"); - fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, (const rb_callable_method_entry_t *)0x%"PRIxVALUE", 0, %d, %d);\n", - (VALUE)cc_copy->me, param_size, iseq->body->local_table_size); // fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE + if (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC) { +% # TODO: optimize this more + fprintf(f, " calling.ci = (CALL_INFO)0x%"PRIxVALUE";\n", (VALUE)ci); // creating local cd here because operand's cd->cc may not be the same as inlined cc. + fprintf(f, " calling.cc = cc;"); + fprintf(f, " val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling);\n"); + } + else { // VM_METHOD_TYPE_ISEQ +% # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE + fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, cc_cme, 0, %d, %d);\n", iseq->body->param.size, iseq->body->local_table_size); if (iseq->body->catch_except_p) { - fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); - fprintf(f, " v = vm_exec(ec, TRUE);\n"); + fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); + fprintf(f, " val = vm_exec(ec, true);\n"); } else { - fprintf(f, " if ((v = mjit_exec(ec)) == Qundef) {\n"); - fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); // This is vm_call0_body's code after vm_call_iseq_setup - fprintf(f, " v = vm_exec(ec, FALSE);\n"); - fprintf(f, " }\n"); + fprintf(f, " if ((val = mjit_exec(ec)) == Qundef) {\n"); + fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); // This is vm_call0_body's code after vm_call_iseq_setup + fprintf(f, " val = vm_exec(ec, false);\n"); + fprintf(f, " }\n"); } - fprintf(f, " stack[%d] = v;\n", b->stack_size - argc - 1); - fprintf(f, " }\n"); - - fprintf(f, " }\n"); + } + fprintf(f, " stack[%d] = val;\n", b->stack_size + sp_inc - 1); + fprintf(f, " }\n"); % # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow. - fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n"); - fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>); - if (!pc_moved_p) { - fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); - } - fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n"); - fprintf(f, " goto cancel;\n"); - fprintf(f, " }\n"); + fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n"); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>); + if (!pc_moved_p) { + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); } + fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n"); + fprintf(f, " goto cancel;\n"); + fprintf(f, " }\n"); + } % # compiler: Move JIT compiler's internal stack pointer - b->stack_size += <%= insn.call_attribute('sp_inc') %>; + b->stack_size += <%= insn.call_attribute('sp_inc') %>; - fprintf(f, "}\n"); - break; - } + fprintf(f, "}\n"); + break; } } diff --git a/ruby/tool/ruby_vm/views/_sp_inc_helpers.erb b/ruby/tool/ruby_vm/views/_sp_inc_helpers.erb index f4cf50b8c..d0b0bd79e 100644 --- a/ruby/tool/ruby_vm/views/_sp_inc_helpers.erb +++ b/ruby/tool/ruby_vm/views/_sp_inc_helpers.erb @@ -9,7 +9,7 @@ #line <%= __LINE__ + 1 %> <%=cstr __FILE__ %> static rb_snum_t -sp_inc_of_sendish(const struct rb_call_info *ci) +sp_inc_of_sendish(const struct rb_callinfo *ci) { /* Send-ish instructions will: * @@ -18,8 +18,8 @@ sp_inc_of_sendish(const struct rb_call_info *ci) * 3. Pop receiver. * 4. Push return value. */ - const int argb = (ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0; - const int argc = ci->orig_argc; + const int argb = (vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) ? 1 : 0; + const int argc = vm_ci_argc(ci); const int recv = 1; const int retn = 1; @@ -28,7 +28,7 @@ sp_inc_of_sendish(const struct rb_call_info *ci) } static rb_snum_t -sp_inc_of_invokeblock(const struct rb_call_info *ci) +sp_inc_of_invokeblock(const struct rb_callinfo *ci) { /* sp_inc of invokeblock is almost identical to that of sendish * instructions, except that it does not pop receiver. */ diff --git a/ruby/tool/ruby_vm/views/_trace_instruction.erb b/ruby/tool/ruby_vm/views/_trace_instruction.erb index be2b091d4..3588207d3 100644 --- a/ruby/tool/ruby_vm/views/_trace_instruction.erb +++ b/ruby/tool/ruby_vm/views/_trace_instruction.erb @@ -10,7 +10,12 @@ /* insn <%= insn.pretty_name %> */ INSN_ENTRY(<%= insn.name %>) { - vm_trace(ec, GET_CFP(), GET_PC()); - DISPATCH_ORIGINAL_INSN(<%= insn.jump_destination %>); + vm_trace(ec, GET_CFP()); +% if insn.name =~ +% /\Atrace_opt_(plus|minus|mult|div|mod|eq|neq|lt|le|gt|ge|ltlt|and|or|aref|aset|length|size|empty_p|nil_p|succ|not|regexpmatch2)\z/ +% jump_dest = "opt_send_without_block" +% end + <%= 'ADD_PC(1);' if insn.name == 'trace_opt_neq' %> + DISPATCH_ORIGINAL_INSN(<%= jump_dest || insn.jump_destination %>); END_INSN(<%= insn.name %>); } diff --git a/ruby/tool/ruby_vm/views/mjit_compile.inc.erb b/ruby/tool/ruby_vm/views/mjit_compile.inc.erb index 95e71183d..5820f8177 100644 --- a/ruby/tool/ruby_vm/views/mjit_compile.inc.erb +++ b/ruby/tool/ruby_vm/views/mjit_compile.inc.erb @@ -16,8 +16,7 @@ } -%> % % unsupported_insns = [ -% 'defineclass', # low priority -% 'opt_call_c_function', # low priority +% 'defineclass', # low priority % ] % % opt_send_without_block = RubyVM::Instructions.find { |i| i.name == 'opt_send_without_block' } @@ -36,9 +35,9 @@ % # GET_CFP(): refers to `reg_cfp` % # GET_EP(): refers to `reg_cfp->ep` % # GET_SP(): refers to `reg_cfp->sp`, or `(stack + stack_size)` if local_stack_p -% # GET_SELF(): refers to `reg_cfp->self` +% # GET_SELF(): refers to `cfp_self` % # GET_LEP(): refers to `VM_EP_LEP(reg_cfp->ep)` -% # EXEC_EC_CFP(): refers to `val = vm_exec(ec, TRUE)` with frame setup +% # EXEC_EC_CFP(): refers to `val = vm_exec(ec, true)` with frame setup % # CALL_METHOD(): using `GET_CFP()` and `EXEC_EC_CFP()` % # TOPN(): refers to `reg_cfp->sp`, or `*(stack + (stack_size - num - 1))` if local_stack_p % # STACK_ADDR_FROM_TOP(): refers to `reg_cfp->sp`, or `stack + (stack_size - num)` if local_stack_p @@ -49,7 +48,7 @@ switch (insn) { % (RubyVM::BareInstructions.to_a + RubyVM::OperandsUnifications.to_a).each do |insn| % next if unsupported_insns.include?(insn.name) - case BIN(<%= insn.name %>): + case BIN(<%= insn.name %>): { % # Instruction-specific behavior in JIT % case insn.name % when 'opt_send_without_block', 'send' @@ -57,30 +56,48 @@ switch (insn) { % when *send_compatible_opt_insns % # To avoid cancel, just emit `opt_send_without_block` instead of `opt_*` insn if call cache is populated. % cd_index = insn.opes.index { |o| o.fetch(:type) == 'CALL_DATA' } - if (has_valid_method_type(status->cc_entries + call_data_index((CALL_DATA)operands[<%= cd_index %>], body))) { -<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%> -<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%> - break; - } + if (has_cache_for_send(captured_cc_entries(status)[call_data_index((CALL_DATA)operands[<%= cd_index %>], body)], BIN(<%= insn.name %>))) { +<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%> +<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%> + break; + } % when 'getinstancevariable', 'setinstancevariable' <%= render 'mjit_compile_ivar', locals: { insn: insn } -%> -% when 'leave' - if (b->stack_size != 1) { - if (mjit_opts.warnings || mjit_opts.verbose) - fprintf(stderr, "MJIT warning: Unexpected JIT stack_size on leave: %d\n", b->stack_size); - status->success = false; - } -% # Special leave for an inlined call. - if (status->inlined_iseqs == NULL) { // the current ISeq is being inlined - fprintf(f, " return stack[0];\n"); - b->stack_size += <%= insn.call_attribute('sp_inc') %>; - break; - } +% when 'invokebuiltin', 'opt_invokebuiltin_delegate' +<%= render 'mjit_compile_invokebuiltin', locals: { insn: insn } -%> +% when 'opt_getinlinecache' +<%= render 'mjit_compile_getinlinecache', locals: { insn: insn } -%> +% when 'leave', 'opt_invokebuiltin_delegate_leave' +% # opt_invokebuiltin_delegate_leave also implements leave insn. We need to handle it here for inlining. +% if insn.name == 'opt_invokebuiltin_delegate_leave' +<%= render 'mjit_compile_invokebuiltin', locals: { insn: insn } -%> +% else + if (b->stack_size != 1) { + if (mjit_opts.warnings || mjit_opts.verbose) + fprintf(stderr, "MJIT warning: Unexpected JIT stack_size on leave: %d\n", b->stack_size); + status->success = false; + } +% end +% # Skip vm_pop_frame for inlined call + if (status->inlined_iseqs != NULL) { // the current ISeq is NOT being inlined +% # Cancel on interrupts to make leave insn leaf + fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"); + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); + fprintf(f, " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"); + fprintf(f, " }\n"); + fprintf(f, " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n"); // vm_pop_frame + } + fprintf(f, " return stack[0];\n"); + b->stack_size += <%= insn.call_attribute('sp_inc') %>; + b->finish_p = TRUE; + break; % end % % # Main insn implementation generated by insns.def <%= render 'mjit_compile_insn', locals: { insn: insn } -%> break; + } % end % % # We don't support InstructionsUnifications yet because it's not used for now. diff --git a/ruby/tool/runruby.rb b/ruby/tool/runruby.rb index 4715ff4d5..bff5d031c 100755 --- a/ruby/tool/runruby.rb +++ b/ruby/tool/runruby.rb @@ -11,6 +11,8 @@ debugger = :gdb when ENV['RUNRUBY_USE_LLDB'] == 'true' debugger = :lldb +when ENV['RUNRUBY_YJIT_STATS'] + use_yjit_stat = true end while arg = ARGV[0] break ARGV.shift if arg == '--' @@ -85,7 +87,8 @@ def File.realpath(*args) config.sub!(/^(\s*)RUBY_VERSION\b.*(\sor\s*)\n.*\n/, '') config = Module.new {module_eval(config, conffile)}::RbConfig::CONFIG -ruby = File.join(archdir, config["RUBY_INSTALL_NAME"]+config['EXEEXT']) +install_name = config["RUBY_INSTALL_NAME"]+config['EXEEXT'] +ruby = File.join(archdir, install_name) unless File.exist?(ruby) abort "#{ruby} is not found.\nTry `make' first, then `make test', please.\n" end @@ -106,7 +109,7 @@ def File.realpath(*args) 'RUBY_FIBER_MACHINE_STACK_SIZE' => '1', } -runner = File.join(abs_archdir, "exe/ruby#{config['EXEEXT']}") +runner = File.join(abs_archdir, "exe/#{install_name}") runner = nil unless File.exist?(runner) abs_ruby = runner || File.expand_path(ruby) env["RUBY"] = abs_ruby @@ -163,6 +166,9 @@ def File.realpath(*args) end cmd = [runner || ruby] +if use_yjit_stat + cmd << '--yjit-stats' +end cmd.concat(ARGV) cmd.unshift(*precommand) unless precommand.empty? diff --git a/ruby/tool/search-cgvars.rb b/ruby/tool/search-cgvars.rb new file mode 100644 index 000000000..c62641a3f --- /dev/null +++ b/ruby/tool/search-cgvars.rb @@ -0,0 +1,55 @@ +# +# Listing C's global variables in .so or .o, or .bundle on Mac OS using "objdump -t" (elf64-x86-64) +# to check ractor-safety. +# +# Usage: ruby search-cgvars.rb foo.so bar.o .ext/x86_64-darwin18/psych.bundle +# +MAC_OS = RbConfig::CONFIG['host_os'].match? /darwin|mac os/ + +def gvars file + # '0000000000031ac8 g O .bss 0000000000000008 rb_cSockIfaddr' + # On mac, with .bundle files: + # '0000000000004258 l O __DATA,__bss _passwd_blocking' + + strs = `objdump -t #{file}` + found = {} + strs.each_line{|line| + if /[\da-f]{16} / =~ line + addr = line[0...16] + flags = line[17...24].tr(' ', '').split(//).sort.uniq + rest = line[25..] + if MAC_OS + seg, name = rest.split(/\s+/) + else + seg, size, name = rest.split(/\s+/) + end + if flags.include?('O') + # p [addr, flags, seg, size, name] + found[name] = [flags, seg, *size] + end + end + } + puts "## #{file}:" + found.sort_by{|name, (flags, *)| + [flags, name] + }.each{|name, rest| + flags, seg, size = *rest + next if (size.to_i == 0 && !MAC_OS) && seg != '*UND*' + case seg + when ".rodata", ".data.rel.ro", ".got.plt", ".eh_frame", ".fini_array" + next + when /,__const$/ # Mac OS + next + end + case name + when /^id_/, /^rbimpl_id/, /^sym_/, /^rb_[cme]/, /\Acompleted\.\d+\z/ + next + when /^_id_/, /\.rbimpl_id(\.\d+)?$/ # Mac OS + next + end + puts " %40s %s" % [name, rest.inspect] + } +end +ARGV.each{|file| + gvars file +} diff --git a/ruby/tool/strip-rdoc.rb b/ruby/tool/strip-rdoc.rb index 0ac9c3932..d8e311cdb 100755 --- a/ruby/tool/strip-rdoc.rb +++ b/ruby/tool/strip-rdoc.rb @@ -1,26 +1,14 @@ #!ruby +# frozen_string_literal: true # Filter for preventing Doxygen from processing RDoc comments. # Used by the Doxygen template. -ARGF.binmode -source = ARGF.read -source = source.gsub(%r{/\*([!*])((?!\*/).+?)\*/}m) do |comment| - marker, comment = $1, $2 - next "/**#{comment}*/" unless /^\s*\*\s?\-\-\s*$/ =~ comment - doxybody = nil - comment.each_line do |line| - if doxybody - if /^\s*\*\s?\+\+\s*$/ =~ line - break - end - doxybody << line - else - if /^\s*\*\s?--\s*$/ =~ line - doxybody = "\n" - end - end - end - "/*#{marker}#{doxybody}*/" -end -print source +print ARGF.binmode.read.tap {|src| + src.gsub!(%r|(/\*[!*])(?:(?!\*/).)+?^\s*\*\s?\-\-\s*$(.+?\*/)|m) { + marker = $1 + comment = $2 + comment.sub!(%r|^\s*\*\s?\+\+\s*$.+?(\s*\*/)\z|m, '\\1') + marker + comment + } +} diff --git a/ruby/tool/sync_default_gems.rb b/ruby/tool/sync_default_gems.rb old mode 100644 new mode 100755 index c9ca81f78..ca5283d2c --- a/ruby/tool/sync_default_gems.rb +++ b/ruby/tool/sync_default_gems.rb @@ -1,62 +1,11 @@ -# sync following repositories to ruby repository -# -# * https://github.com/rubygems/rubygems -# * https://github.com/bundler/bundler -# * https://github.com/ruby/rdoc -# * https://github.com/ruby/reline -# * https://github.com/flori/json -# * https://github.com/ruby/psych -# * https://github.com/ruby/fileutils -# * https://github.com/ruby/fiddle -# * https://github.com/ruby/stringio -# * https://github.com/ruby/io-console -# * https://github.com/ruby/csv -# * https://github.com/ruby/webrick -# * https://github.com/ruby/dbm -# * https://github.com/ruby/gdbm -# * https://github.com/ruby/sdbm -# * https://github.com/ruby/etc -# * https://github.com/ruby/date -# * https://github.com/ruby/zlib -# * https://github.com/ruby/fcntl -# * https://github.com/ruby/strscan -# * https://github.com/ruby/ipaddr -# * https://github.com/ruby/logger -# * https://github.com/ruby/prime -# * https://github.com/ruby/matrix -# * https://github.com/ruby/ostruct -# * https://github.com/ruby/rexml -# * https://github.com/ruby/rss -# * https://github.com/ruby/irb -# * https://github.com/ruby/tracer -# * https://github.com/ruby/forwardable -# * https://github.com/ruby/mutex_m -# * https://github.com/ruby/racc -# * https://github.com/ruby/singleton -# * https://github.com/ruby/open3 -# * https://github.com/ruby/getoptlong -# * https://github.com/ruby/pstore -# * https://github.com/ruby/delegate -# * https://github.com/ruby/benchmark -# * https://github.com/ruby/net-pop -# * https://github.com/ruby/net-smtp -# * https://github.com/ruby/cgi -# * https://github.com/ruby/readline -# * https://github.com/ruby/readline-ext -# * https://github.com/ruby/observer -# * https://github.com/ruby/timeout -# * https://github.com/ruby/yaml -# * https://github.com/ruby/uri -# * https://github.com/ruby/openssl -# * https://github.com/ruby/did_you_mean -# +#!/usr/bin/env ruby +# sync upstream github repositories to ruby repository require 'fileutils' include FileUtils -$repositories = { +REPOSITORIES = { rubygems: 'rubygems/rubygems', - bundler: 'bundler/bundler', rdoc: 'ruby/rdoc', reline: 'ruby/reline', json: 'flori/json', @@ -64,12 +13,10 @@ fileutils: 'ruby/fileutils', fiddle: 'ruby/fiddle', stringio: 'ruby/stringio', - ioconsole: 'ruby/io-console', + "io-console": 'ruby/io-console', + "io-nonblock": 'ruby/io-nonblock', + "io-wait": 'ruby/io-wait', csv: 'ruby/csv', - webrick: 'ruby/webrick', - dbm: 'ruby/dbm', - gdbm: 'ruby/gdbm', - sdbm: 'ruby/sdbm', etc: 'ruby/etc', date: 'ruby/date', zlib: 'ruby/zlib', @@ -77,13 +24,8 @@ strscan: 'ruby/strscan', ipaddr: 'ruby/ipaddr', logger: 'ruby/logger', - prime: 'ruby/prime', - matrix: 'ruby/matrix', ostruct: 'ruby/ostruct', - rexml: 'ruby/rexml', - rss: 'ruby/rss', irb: 'ruby/irb', - tracer: 'ruby/tracer', forwardable: "ruby/forwardable", mutex_m: "ruby/mutex_m", racc: "ruby/racc", @@ -93,57 +35,137 @@ pstore: "ruby/pstore", delegate: "ruby/delegate", benchmark: "ruby/benchmark", - netpop: "ruby/net-pop", - netsmtp: "ruby/net-smtp", cgi: "ruby/cgi", readline: "ruby/readline", - readlineext: "ruby/readline-ext", + "readline-ext": "ruby/readline-ext", observer: "ruby/observer", timeout: "ruby/timeout", yaml: "ruby/yaml", uri: "ruby/uri", openssl: "ruby/openssl", - did_you_mean: "ruby/did_you_mean" + did_you_mean: "ruby/did_you_mean", + weakref: "ruby/weakref", + tempfile: "ruby/tempfile", + tmpdir: "ruby/tmpdir", + English: "ruby/English", + "net-protocol": "ruby/net-protocol", + "net-http": "ruby/net-http", + bigdecimal: "ruby/bigdecimal", + optparse: "ruby/optparse", + set: "ruby/set", + find: "ruby/find", + rinda: "ruby/rinda", + erb: "ruby/erb", + nkf: "ruby/nkf", + tsort: "ruby/tsort", + abbrev: "ruby/abbrev", + shellwords: "ruby/shellwords", + base64: "ruby/base64", + syslog: "ruby/syslog", + "open-uri": "ruby/open-uri", + securerandom: "ruby/securerandom", + resolv: "ruby/resolv", + "resolv-replace": "ruby/resolv-replace", + time: "ruby/time", + pp: "ruby/pp", + prettyprint: "ruby/prettyprint", + drb: "ruby/drb", + pathname: "ruby/pathname", + digest: "ruby/digest", + error_highlight: "ruby/error_highlight", + un: "ruby/un", + win32ole: "ruby/win32ole", } +# We usually don't use this. Please consider using #sync_default_gems_with_commits instead. def sync_default_gems(gem) - puts "Sync #{$repositories[gem.to_sym]}" + repo = REPOSITORIES[gem.to_sym] + puts "Sync #{repo}" - upstream = File.join("..", "..", $repositories[gem.to_sym]) + upstream = File.join("..", "..", repo) case gem when "rubygems" - rm_rf(%w[lib/rubygems* test/rubygems]) + rm_rf(%w[lib/rubygems lib/rubygems.rb test/rubygems]) cp_r(Dir.glob("#{upstream}/lib/rubygems*"), "lib") cp_r("#{upstream}/test/rubygems", "test") - when "bundler" - rm_rf(%w[lib/bundler* libexec/bundler libexec/bundle spec/bundler man/bundle* man/gemfile*]) - cp_r(Dir.glob("#{upstream}/lib/bundler*"), "lib") - cp_r(Dir.glob("#{upstream}/exe/bundle*"), "libexec") - cp_r("#{upstream}/bundler.gemspec", "lib/bundler") - cp_r("#{upstream}/spec", "spec/bundler") - cp_r(Dir.glob("#{upstream}/man/*.{1,5,1\.txt,5\.txt,ronn}"), "man") + rm_rf(%w[lib/bundler lib/bundler.rb libexec/bundler libexec/bundle spec/bundler tool/bundler/*]) + cp_r(Dir.glob("#{upstream}/bundler/lib/bundler*"), "lib") + cp_r(Dir.glob("#{upstream}/bundler/exe/bundle*"), "libexec") + + gemspec_content = File.readlines("#{upstream}/bundler/bundler.gemspec").map do |line| + next if line =~ /LICENSE\.md/ + + line.gsub("bundler.gemspec", "lib/bundler/bundler.gemspec").gsub('"exe"', '"libexec"') + end.compact.join + File.write("lib/bundler/bundler.gemspec", gemspec_content) + + cp_r("#{upstream}/bundler/spec", "spec/bundler") + cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/dev_gems*"), "tool/bundler") + cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/test_gems*"), "tool/bundler") + cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/rubocop_gems*"), "tool/bundler") + cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/standard_gems*"), "tool/bundler") rm_rf(%w[spec/bundler/support/artifice/vcr_cassettes]) + license_files = %w[ + lib/bundler/vendor/thor/LICENSE.md + lib/rubygems/resolver/molinillo/LICENSE + lib/bundler/vendor/molinillo/LICENSE + lib/bundler/vendor/connection_pool/LICENSE + lib/bundler/vendor/net-http-persistent/README.rdoc + lib/bundler/vendor/fileutils/LICENSE.txt + lib/bundler/vendor/tsort/LICENSE.txt + lib/bundler/vendor/uri/LICENSE.txt + lib/rubygems/optparse/COPYING + lib/rubygems/tsort/LICENSE.txt + ] + rm_rf license_files when "rdoc" - rm_rf(%w[lib/rdoc* test/rdoc libexec/rdoc libexec/ri]) + rm_rf(%w[lib/rdoc lib/rdoc.rb test/rdoc libexec/rdoc libexec/ri]) cp_r(Dir.glob("#{upstream}/lib/rdoc*"), "lib") cp_r("#{upstream}/test/rdoc", "test") cp_r("#{upstream}/rdoc.gemspec", "lib/rdoc") + cp_r("#{upstream}/Gemfile", "lib/rdoc") + cp_r("#{upstream}/Rakefile", "lib/rdoc") cp_r("#{upstream}/exe/rdoc", "libexec") cp_r("#{upstream}/exe/ri", "libexec") - rm_rf(%w[lib/rdoc/markdown.kpeg lib/rdoc/markdown/literals.kpeg lib/rdoc/rd/block_parser.ry lib/rdoc/rd/inline_parser.ry]) + parser_files = { + 'lib/rdoc/markdown.kpeg' => 'lib/rdoc/markdown.rb', + 'lib/rdoc/markdown/literals.kpeg' => 'lib/rdoc/markdown/literals.rb', + 'lib/rdoc/rd/block_parser.ry' => 'lib/rdoc/rd/block_parser.rb', + 'lib/rdoc/rd/inline_parser.ry' => 'lib/rdoc/rd/inline_parser.rb' + } + Dir.chdir(upstream) do + `bundle install` + parser_files.each_value do |dst| + `bundle exec rake #{dst}` + end + end + parser_files.each_pair do |src, dst| + rm_rf(src) + cp_r("#{upstream}/#{dst}", dst) + end `git checkout lib/rdoc/.document` + rm_rf(%w[lib/rdoc/Gemfile lib/rdoc/Rakefile]) when "reline" - rm_rf(%w[lib/reline* test/reline]) + rm_rf(%w[lib/reline lib/reline.rb test/reline]) cp_r(Dir.glob("#{upstream}/lib/reline*"), "lib") cp_r("#{upstream}/test/reline", "test") cp_r("#{upstream}/reline.gemspec", "lib/reline") + when "irb" + rm_rf(%w[lib/irb lib/irb.rb test/irb]) + cp_r(Dir.glob("#{upstream}/lib/irb*"), "lib") + cp_r("#{upstream}/test/irb", "test") + cp_r("#{upstream}/irb.gemspec", "lib/irb") + cp_r("#{upstream}/man/irb.1", "man/irb.1") + cp_r("#{upstream}/doc/irb", "doc") when "json" rm_rf(%w[ext/json test/json]) cp_r("#{upstream}/ext/json/ext", "ext/json") cp_r("#{upstream}/tests", "test/json") + rm_rf("test/json/lib") cp_r("#{upstream}/lib", "ext/json") cp_r("#{upstream}/json.gemspec", "ext/json") + cp_r("#{upstream}/VERSION", "ext/json") rm_rf(%w[ext/json/lib/json/ext ext/json/lib/json/pure.rb ext/json/lib/json/pure]) `git checkout ext/json/extconf.rb ext/json/parser/prereq.mk ext/json/generator/depend ext/json/parser/depend ext/json/depend` when "psych" @@ -170,32 +192,27 @@ def sync_default_gems(gem) cp_r("#{upstream}/test/stringio", "test") cp_r("#{upstream}/stringio.gemspec", "ext/stringio") `git checkout ext/stringio/depend ext/stringio/README.md` - when "ioconsole" + when "io-console" rm_rf(%w[ext/io/console test/io/console]) cp_r("#{upstream}/ext/io/console", "ext/io") cp_r("#{upstream}/test/io/console", "test/io") mkdir_p("ext/io/console/lib") cp_r("#{upstream}/lib/io/console", "ext/io/console/lib") + rm_rf("ext/io/console/lib/console/ffi") cp_r("#{upstream}/io-console.gemspec", "ext/io/console") `git checkout ext/io/console/depend` - when "dbm" - rm_rf(%w[ext/dbm test/dbm]) - cp_r("#{upstream}/ext/dbm", "ext") - cp_r("#{upstream}/test/dbm", "test") - cp_r("#{upstream}/dbm.gemspec", "ext/dbm") - `git checkout ext/dbm/depend` - when "gdbm" - rm_rf(%w[ext/gdbm test/gdbm]) - cp_r("#{upstream}/ext/gdbm", "ext") - cp_r("#{upstream}/test/gdbm", "test") - cp_r("#{upstream}/gdbm.gemspec", "ext/gdbm") - `git checkout ext/gdbm/depend ext/gdbm/README` - when "sdbm" - rm_rf(%w[ext/sdbm test/sdbm]) - cp_r("#{upstream}/ext/sdbm", "ext") - cp_r("#{upstream}/test/sdbm", "test") - cp_r("#{upstream}/sdbm.gemspec", "ext/sdbm") - `git checkout ext/sdbm/depend` + when "io-nonblock" + rm_rf(%w[ext/io/nonblock test/io/nonblock]) + cp_r("#{upstream}/ext/io/nonblock", "ext/io") + cp_r("#{upstream}/test/io/nonblock", "test/io") + cp_r("#{upstream}/io-nonblock.gemspec", "ext/io/nonblock") + `git checkout ext/io/nonblock/depend` + when "io-wait" + rm_rf(%w[ext/io/wait test/io/wait]) + cp_r("#{upstream}/ext/io/wait", "ext/io") + cp_r("#{upstream}/test/io/wait", "test/io") + cp_r("#{upstream}/io-wait.gemspec", "ext/io/wait") + `git checkout ext/io/wait/depend` when "etc" rm_rf(%w[ext/etc test/etc]) cp_r("#{upstream}/ext/etc", "ext") @@ -229,7 +246,7 @@ def sync_default_gems(gem) rm_rf(%w["ext/strscan/regenc.h ext/strscan/regint.h"]) `git checkout ext/strscan/depend` when "racc" - rm_rf(%w[lib/racc* ext/racc test/racc]) + rm_rf(%w[lib/racc lib/racc.rb ext/racc test/racc]) cp_r(Dir.glob("#{upstream}/lib/racc*"), "lib") mkdir_p("ext/racc/cparse") cp_r(Dir.glob("#{upstream}/ext/racc/cparse/*"), "ext/racc/cparse") @@ -248,75 +265,193 @@ def sync_default_gems(gem) when "openssl" rm_rf(%w[ext/openssl test/openssl]) cp_r("#{upstream}/ext/openssl", "ext") - mkdir_p("ext/openssl/lib") - cp_r("#{upstream}/lib/openssl", "ext/openssl/lib") - cp_r("#{upstream}/lib/openssl.rb", "ext/openssl/lib") - cp_r("#{upstream}/test", "test/openssl") + cp_r("#{upstream}/lib", "ext/openssl") + cp_r("#{upstream}/test/openssl", "test") rm_rf("test/openssl/envutil.rb") cp_r("#{upstream}/openssl.gemspec", "ext/openssl") - cp_r("#{upstream}/HISTORY.md", "ext/openssl") + cp_r("#{upstream}/History.md", "ext/openssl") `git checkout ext/openssl/depend` - when "netpop" - sync_lib "net-pop" - mv "lib/net-pop.gemspec", "lib/net/pop" - when "netsmtp" - sync_lib "net-smtp" - mv "lib/net-smtp.gemspec", "lib/net/smtp" - when "readlineext" - sync_lib "readline-ext" - mv "lib/readline-ext.gemspec", "ext/readline" + when "net-protocol" + rm_rf(%w[lib/net/protocol.rb lib/net/net-protocol.gemspec test/net/protocol]) + cp_r("#{upstream}/lib/net/protocol.rb", "lib/net") + cp_r("#{upstream}/test/net/protocol", "test/net") + cp_r("#{upstream}/net-protocol.gemspec", "lib/net") + when "net-http" + rm_rf(%w[lib/net/http.rb lib/net/http test/net/http]) + cp_r("#{upstream}/lib/net/http.rb", "lib/net") + cp_r("#{upstream}/lib/net/http", "lib/net") + cp_r("#{upstream}/test/net/http", "test/net") + cp_r("#{upstream}/net-http.gemspec", "lib/net/http") + when "readline-ext" + rm_rf(%w[ext/readline test/readline]) + cp_r("#{upstream}/ext/readline", "ext") + cp_r("#{upstream}/test/readline", "test") + cp_r("#{upstream}/readline-ext.gemspec", "ext/readline") + `git checkout ext/readline/depend` when "did_you_mean" - rm_rf(%w[lib/did_you_mean* test/did_you_mean]) + rm_rf(%w[lib/did_you_mean lib/did_you_mean.rb test/did_you_mean]) cp_r(Dir.glob("#{upstream}/lib/did_you_mean*"), "lib") cp_r("#{upstream}/did_you_mean.gemspec", "lib/did_you_mean") cp_r("#{upstream}/test", "test/did_you_mean") rm_rf(%w[test/did_you_mean/tree_spell/test_explore.rb]) + when "erb" + rm_rf(%w[lib/erb* test/erb libexec/erb]) + cp_r("#{upstream}/lib/erb.rb", "lib") + cp_r("#{upstream}/test/erb", "test") + cp_r("#{upstream}/erb.gemspec", "lib") + cp_r("#{upstream}/libexec/erb", "libexec") + when "nkf" + rm_rf(%w[ext/nkf test/nkf]) + cp_r("#{upstream}/ext/nkf", "ext") + cp_r("#{upstream}/lib", "ext/nkf") + cp_r("#{upstream}/test/nkf", "test") + cp_r("#{upstream}/nkf.gemspec", "ext/nkf") + `git checkout ext/nkf/depend` + when "syslog" + rm_rf(%w[ext/syslog test/syslog test/test_syslog.rb]) + cp_r("#{upstream}/ext/syslog", "ext") + cp_r("#{upstream}/lib", "ext/syslog") + cp_r("#{upstream}/test/syslog", "test") + cp_r("#{upstream}/test/test_syslog.rb", "test") + cp_r("#{upstream}/syslog.gemspec", "ext/syslog") + `git checkout ext/syslog/depend` + when "bigdecimal" + rm_rf(%w[ext/bigdecimal test/bigdecimal]) + cp_r("#{upstream}/ext/bigdecimal", "ext") + cp_r("#{upstream}/sample", "ext/bigdecimal") + cp_r("#{upstream}/lib", "ext/bigdecimal") + cp_r("#{upstream}/test/bigdecimal", "test") + cp_r("#{upstream}/bigdecimal.gemspec", "ext/bigdecimal") + `git checkout ext/bigdecimal/depend` + when "pathname" + rm_rf(%w[ext/pathname test/pathname]) + cp_r("#{upstream}/ext/pathname", "ext") + cp_r("#{upstream}/test/pathname", "test") + cp_r("#{upstream}/lib", "ext/pathname") + cp_r("#{upstream}/pathname.gemspec", "ext/pathname") + `git checkout ext/pathname/depend` + when "digest" + rm_rf(%w[ext/digest test/digest]) + cp_r("#{upstream}/ext/digest", "ext") + mkdir_p("ext/digest/lib/digest") + cp_r("#{upstream}/lib/digest.rb", "ext/digest/lib/") + cp_r("#{upstream}/lib/digest/version.rb", "ext/digest/lib/digest/") + mkdir_p("ext/digest/sha2/lib") + cp_r("#{upstream}/lib/digest/sha2.rb", "ext/digest/sha2/lib") + move("ext/digest/lib/digest/sha2", "ext/digest/sha2/lib") + cp_r("#{upstream}/test/digest", "test") + cp_r("#{upstream}/digest.gemspec", "ext/digest") + `git checkout ext/digest/depend ext/digest/*/depend` + when "set" + sync_lib gem, upstream + cp_r("#{upstream}/test", ".") + when "optparse" + sync_lib gem, upstream + rm_rf(%w[doc/optparse]) + mkdir_p("doc/optparse") + cp_r("#{upstream}/doc/optparse", "doc") + when "error_highlight" + rm_rf(%w[lib/error_highlight lib/error_highlight.rb test/error_highlight]) + cp_r(Dir.glob("#{upstream}/lib/error_highlight*"), "lib") + cp_r("#{upstream}/error_highlight.gemspec", "lib/error_highlight") + cp_r("#{upstream}/test", "test/error_highlight") + when "win32ole" + sync_lib gem, upstream + rm_rf(%w[ext/win32ole/lib]) + Dir.mkdir(*%w[ext/win32ole/lib]) + move("lib/win32ole/win32ole.gemspec", "ext/win32ole") + move(Dir.glob("lib/win32ole*"), "ext/win32ole/lib") + when "open3" + sync_lib gem, upstream + rm_rf("lib/open3/jruby_windows.rb") else - sync_lib gem + sync_lib gem, upstream end end -IGNORE_FILE_PATTERN = /(\.travis.yml|appveyor\.yml|azure\-pipelines\.yml|\.gitignore|Gemfile|README\.md|History\.txt|Rakefile|CODE_OF_CONDUCT\.md)/ +IGNORE_FILE_PATTERN = + /\A(?:[A-Z]\w*\.(?:md|txt) + |[^\/]+\.yml + |\.git.* + |[A-Z]\w+file + |COPYING + |rakelib\/ + )\z/x -def sync_default_gems_with_commits(gem, range) - puts "Sync #{$repositories[gem.to_sym]} with commit history." +def message_filter(repo, sha) + log = STDIN.read + log.delete!("\r") + url = "https://github.com/#{repo}" + print "[#{repo}] ", log.gsub(/\b(?i:fix) +\K#(?=\d+\b)|\(\K#(?=\d+\))|\bGH-(?=\d+\b)/) { + "#{url}/pull/" + }.gsub(%r{(?] "before..after". Note that it will NOT sync "before" (but commits after that). +# @param edit [TrueClass] Set true if you want to resolve conflicts. Obviously, update-default-gem.sh doesn't use this. +def sync_default_gems_with_commits(gem, ranges, edit: nil) + repo = REPOSITORIES[gem.to_sym] + puts "Sync #{repo} with commit history." IO.popen(%W"git remote") do |f| unless f.read.split.include?(gem) - `git remote add #{gem} git@github.com:#{$repositories[gem.to_sym]}.git` + `git remote add #{gem} git@github.com:#{repo}.git` end end system(*%W"git fetch --no-tags #{gem}") - unless range.include?("..") - range = "#{range}~1..#{range}" + if ranges == true + pattern = "https://github\.com/#{Regexp.quote(repo)}/commit/([0-9a-f]+)$" + log = IO.popen(%W"git log -E --grep=#{pattern} -n1 --format=%B", &:read) + ranges = ["#{log[%r[#{pattern}\n\s*(?i:co-authored-by:.*)*\s*\Z], 1]}..#{gem}/master"] end - commits = IO.popen(%W"git log --format=%H,%s #{range}") do |f| - f.read.split("\n").reverse.map{|commit| commit.split(',', 2)} + commits = ranges.flat_map do |range| + unless range.include?("..") + range = "#{range}~1..#{range}" + end + + IO.popen(%W"git log --format=%H,%s #{range} --") do |f| + f.read.split("\n").reverse.map{|commit| commit.split(',', 2)} + end end # Ignore Merge commit and insufficiency commit for ruby core repository. commits.delete_if do |sha, subject| - files = IO.popen(%W"git diff-tree --no-commit-id --name-only -r #{sha}") do |f| - f.readlines - end + files = IO.popen(%W"git diff-tree --no-commit-id --name-only -r #{sha}", &:readlines) subject =~ /^Merge/ || subject =~ /^Auto Merge/ || files.all?{|file| file =~ IGNORE_FILE_PATTERN} end + if commits.empty? + puts "No commits to pick" + return true + end + puts "Try to pick these commits:" - puts commits.map{|commit| commit.join(": ")}.join("\n") + puts commits.map{|commit| commit.join(": ")} puts "----" failed_commits = [] ENV["FILTER_BRANCH_SQUELCH_WARNING"] = "1" + require 'shellwords' + filter = [ + ENV.fetch('RUBY', 'ruby').shellescape, + File.realpath(__FILE__).shellescape, + "--message-filter", + ] commits.each do |sha, subject| - puts "Pick #{sha} from #{$repositories[gem.to_sym]}." + puts "Pick #{sha} from #{repo}." skipped = false - result = IO.popen(%W"git cherry-pick #{sha}").read + result = IO.popen(%W"git cherry-pick #{sha}", &:read) if result =~ /nothing\ to\ commit/ `git reset` skipped = true @@ -325,18 +460,42 @@ def sync_default_gems_with_commits(gem, range) next if skipped if result.empty? + skipped = true + elsif /^CONFLICT/ =~ result + result = IO.popen(%W"git status --porcelain", &:readlines).each(&:chomp!) + result.map! {|line| line[/^.U (.*)/, 1]} + result.compact! + ignore, conflict = result.partition {|name| IGNORE_FILE_PATTERN =~ name} + unless ignore.empty? + system(*%W"git reset HEAD --", *ignore) + File.unlink(*ignore) + ignore = IO.popen(%W"git status --porcelain" + ignore, &:readlines).map! {|line| line[/^.. (.*)/, 1]} + system(*%W"git checkout HEAD --", *ignore) unless ignore.empty? + end + unless conflict.empty? + if edit + case + when (editor = ENV["GIT_EDITOR"] and !editor.empty?) + when (editor = `git config core.editor` and (editor.chomp!; !editor.empty?)) + end + if editor + system([editor, conflict].join(' ')) + end + end + end + skipped = !system({"GIT_EDITOR"=>"true"}, *%W"git cherry-pick --no-edit --continue") + end + + if skipped failed_commits << sha `git reset` && `git checkout .` && `git clean -fd` - skipped = true puts "Failed to pick #{sha}" + next end - next if skipped puts "Update commit message: #{sha}" - prefix = "[#{($repositories[gem.to_sym])}]".gsub(/\//, '\/') - suffix = "https://github.com/#{($repositories[gem.to_sym])}/commit/#{sha[0,10]}" - `git filter-branch -f --msg-filter 'sed "1s/^/#{prefix} /" && echo && echo #{suffix}' -- HEAD~1..HEAD` + IO.popen(%W[git filter-branch -f --msg-filter #{[filter, repo, sha].join(' ')} -- HEAD~1..HEAD], &:read) unless $?.success? puts "Failed to modify commit message of #{sha}" break @@ -346,31 +505,36 @@ def sync_default_gems_with_commits(gem, range) unless failed_commits.empty? puts "---- failed commits ----" puts failed_commits + return false end + return true end -def sync_lib(repo) - unless File.directory?("../#{repo}") - abort %[Expected '../#{repo}' \(#{File.expand_path("../#{repo}")}\) to be a directory, but it wasn't.] +def sync_lib(repo, upstream = nil) + unless upstream and File.directory?(upstream) or File.directory?(upstream = "../#{repo}") + abort %[Expected '#{upstream}' \(#{File.expand_path("#{upstream}")}\) to be a directory, but it wasn't.] end rm_rf(["lib/#{repo}.rb", "lib/#{repo}/*", "test/test_#{repo}.rb"]) - cp_r(Dir.glob("../#{repo}/lib/*"), "lib") + cp_r(Dir.glob("#{upstream}/lib/*"), "lib") tests = if File.directory?("test/#{repo}") "test/#{repo}" else "test/test_#{repo}.rb" end - cp_r("../#{repo}/#{tests}", "test") if File.exist?("../#{repo}/#{tests}") + cp_r("#{upstream}/#{tests}", "test") if File.exist?("#{upstream}/#{tests}") gemspec = if File.directory?("lib/#{repo}") "lib/#{repo}/#{repo}.gemspec" else "lib/#{repo}.gemspec" end - cp_r("../#{repo}/#{repo}.gemspec", "#{gemspec}") + cp_r("#{upstream}/#{repo}.gemspec", "#{gemspec}") end def update_default_gems(gem) - author, repository = $repositories[gem.to_sym].split('/') + + author, repository = REPOSITORIES[gem.to_sym].split('/') + + puts "Update #{author}/#{repository}" unless File.exist?("../../#{author}/#{repository}") mkdir_p("../../#{author}") @@ -380,28 +544,82 @@ def update_default_gems(gem) Dir.chdir("../../#{author}/#{repository}") do unless `git remote`.match(/ruby\-core/) `git remote add ruby-core git@github.com:ruby/ruby.git` - `git fetch ruby-core --no-tags` - `git co ruby-core/master` - `git branch ruby-core` end - `git co ruby-core` `git fetch ruby-core master --no-tags` + unless `git branch`.match(/ruby\-core/) + `git checkout ruby-core/master` + `git branch ruby-core` + end + `git checkout ruby-core` `git rebase ruby-core/master` - `git co master` - `git stash` - `git pull --rebase` + `git checkout master` + `git fetch origin master` + `git rebase origin/master` end end case ARGV[0] when "up" - $repositories.keys.each{|gem| update_default_gems(gem.to_s)} + if ARGV[1] + update_default_gems(ARGV[1]) + else + REPOSITORIES.keys.each{|gem| update_default_gems(gem.to_s)} + end when "all" - $repositories.keys.each{|gem| sync_default_gems(gem.to_s)} + REPOSITORIES.keys.each{|gem| sync_default_gems(gem.to_s)} +when "list" + ARGV.shift + pattern = Regexp.new(ARGV.join('|')) + REPOSITORIES.each_pair do |name, gem| + next unless pattern =~ name or pattern =~ gem + printf "%-15s https://github.com/%s\n", name, gem + end +when "--message-filter" + ARGV.shift + abort unless ARGV.size == 2 + message_filter(*ARGV) + exit +when nil, "-h", "--help" + puts <<-HELP +\e[1mSync with upstream code of default libraries\e[0m + +\e[1mImport a default library through `git clone` and `cp -rf` (git commits are lost)\e[0m + ruby #$0 rubygems + +\e[1mPick a single commit from the upstream repository\e[0m + ruby #$0 rubygems 97e9768612 + +\e[1mPick a commit range from the upstream repository\e[0m + ruby #$0 rubygems 97e9768612..9e53702832 + +\e[1mList known libraries\e[0m + ruby #$0 list + +\e[1mList known libraries matching with patterns\e[0m + ruby #$0 list read + HELP + + exit else - if ARGV[1] - sync_default_gems_with_commits(ARGV[0], ARGV[1]) + while /\A-/ =~ ARGV[0] + case ARGV[0] + when "-e" + edit = true + ARGV.shift + when "-a" + auto = true + ARGV.shift + else + $stderr.puts "Unknown command line option: #{ARGV[0]}" + exit 1 + end + end + gem = ARGV.shift + if ARGV[0] + exit sync_default_gems_with_commits(gem, ARGV, edit: edit) + elsif auto + exit sync_default_gems_with_commits(gem, true, edit: edit) else - sync_default_gems(ARGV[0]) + sync_default_gems(gem) end end diff --git a/ruby/tool/test-bundled-gems.rb b/ruby/tool/test-bundled-gems.rb index ded4bc852..b70576103 100644 --- a/ruby/tool/test-bundled-gems.rb +++ b/ruby/tool/test-bundled-gems.rb @@ -1,28 +1,87 @@ require 'rbconfig' +require 'timeout' +require 'fileutils' + +github_actions = ENV["GITHUB_ACTIONS"] == "true" allowed_failures = ENV['TEST_BUNDLED_GEMS_ALLOW_FAILURES'] || '' allowed_failures = allowed_failures.split(',').reject(&:empty?) -gem_dir = File.expand_path('../../gems', __FILE__) +rake = File.realpath("../../.bundle/bin/rake", __FILE__) +gem_dir = File.realpath('../../gems', __FILE__) +dummy_rake_compiler_dir = File.realpath('../dummy-rake-compiler', __FILE__) exit_code = 0 ruby = ENV['RUBY'] || RbConfig.ruby +failed = [] File.foreach("#{gem_dir}/bundled_gems") do |line| + next if /^\s*(?:#|$)/ =~ line gem = line.split.first - puts "\nTesting the #{gem} gem" + next if ARGV.any? {|pat| !File.fnmatch?(pat, gem)} + puts "#{github_actions ? "##[group]" : "\n"}Testing the #{gem} gem" + + test_command = "#{ruby} -C #{gem_dir}/src/#{gem} -Ilib #{rake} test" + first_timeout = 600 # 10min + + if gem == "typeprof" + rbs_build_dir = 'ext/-test-/gems/rbs' + raise "need to run rbs test suite before typeprof" unless File.readable?("#{rbs_build_dir}/rbs_extension.#{RbConfig::CONFIG['DLEXT']}") + ENV["RUBYLIB"] = ["#{gem_dir}/src/rbs/lib", ENV.fetch("RUBYLIB", nil)].compact.join(":") + end + + if gem == "rbs" + test_command << " stdlib_test validate" + + first_timeout *= 3 + + # copied from debug gem + build_dir = 'ext/-test-/gems/rbs' + FileUtils.mkdir_p(build_dir) + extconf_path = File.expand_path('../../gems/src/rbs/ext/rbs_extension/extconf.rb', __FILE__) + system("#{ruby} -C #{build_dir} #{extconf_path}") or raise + system("cd #{build_dir} && make extout=../../../../.ext libdir=../../../..") or raise + ENV["RUBYLIB"] = [File.expand_path(dummy_rake_compiler_dir), File.expand_path(build_dir), ENV.fetch("RUBYLIB", nil)].compact.join(":") + end - gem_src_dir = File.expand_path("#{gem_dir}/src/#{gem}", __FILE__) - test_command = "#{ruby} -C #{gem_src_dir} -Ilib ../../../.bundle/bin/rake" + if gem == "minitest" + # Tentatively exclude some tests that conflict with error_highlight + # https://github.com/seattlerb/minitest/pull/880 + test_command << " 'TESTOPTS=-e /test_stub_value_block_args_5__break_if_not_passed|test_no_method_error_on_unexpected_methods/'" + end + + if gem == "debug" + build_dir = 'ext/-test-/gems/debug' + FileUtils.mkdir_p(build_dir) + extconf_path = File.expand_path('../../gems/src/debug/ext/debug/extconf.rb', __FILE__) + system("#{ruby} -C #{build_dir} #{extconf_path}") or raise + system("cd #{build_dir} && make extout=../../../../.ext libdir=../../../..") or raise + ENV["RUBYLIB"] = [File.expand_path(build_dir + "/.."), ENV.fetch("RUBYLIB", nil)].compact.join(":") + end + + print "[command]" if github_actions puts test_command - system test_command + pid = Process.spawn(test_command, "#{/mingw|mswin/ =~ RUBY_PLATFORM ? 'new_' : ''}pgroup": true) + {nil => first_timeout, INT: 30, TERM: 10, KILL: nil}.each do |sig, sec| + if sig + puts "Sending #{sig} signal" + Process.kill("-#{sig}", pid) + end + begin + break Timeout.timeout(sec) {Process.wait(pid)} + rescue Timeout::Error + end + end unless $?.success? puts "Tests failed with exit code #{$?.exitstatus}" if allowed_failures.include?(gem) puts "Ignoring test failures for #{gem} due to \$TEST_BUNDLED_GEMS_ALLOW_FAILURES" else + failed << gem exit_code = $?.exitstatus end end + print "##[endgroup]\n" if github_actions end +puts "Failed gems: #{failed.join(', ')}" unless failed.empty? exit exit_code diff --git a/ruby/tool/test-coverage.rb b/ruby/tool/test-coverage.rb index e0d7dd06e..4950bc65d 100644 --- a/ruby/tool/test-coverage.rb +++ b/ruby/tool/test-coverage.rb @@ -44,7 +44,7 @@ def save_coverage_data(res1) if cov[:methods] h = {} cov[:methods].each do |(klass, *key), count| - h[[klass.inspect, *key]] = count + h[[klass.name, *key]] = count end cov[:methods].replace h end diff --git a/ruby/tool/test/minitest/metametameta.rb b/ruby/tool/test/minitest/metametameta.rb deleted file mode 100644 index a12717c8b..000000000 --- a/ruby/tool/test/minitest/metametameta.rb +++ /dev/null @@ -1,71 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: false - -require 'tempfile' -require 'stringio' -require 'minitest/autorun' - -class MiniTest::Unit::TestCase - def clean s - s.gsub(/^ {6}/, '') - end -end - -class MetaMetaMetaTestCase < MiniTest::Unit::TestCase - def assert_report expected, flags = %w[--seed 42] - header = clean <<-EOM - Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "} - - # Running tests: - - EOM - - with_output do - @tu.run flags - end - - output = @output.string.dup - output.sub!(/Finished tests in .*/, "Finished tests in 0.00") - output.sub!(/Loaded suite .*/, 'Loaded suite blah') - - output.gsub!(/ = \d+.\d\d s = /, ' = 0.00 s = ') - output.gsub!(/0x[A-Fa-f0-9]+/, '0xXXX') - - if windows? then - output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, '[FILE:LINE]') - output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in') - else - output.gsub!(/\[[^\]:]+:\d+\]/, '[FILE:LINE]') - output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in') - end - - assert_equal header + expected, output - end - - def setup - super - srand 42 - MiniTest::Unit::TestCase.reset - @tu = MiniTest::Unit.new - - MiniTest::Unit.runner = nil # protect the outer runner from the inner tests - end - - def teardown - super - end - - def with_output - synchronize do - begin - save = MiniTest::Unit.output - @output = StringIO.new("") - MiniTest::Unit.output = @output - - yield - ensure - MiniTest::Unit.output = save - end - end - end -end diff --git a/ruby/tool/test/minitest/test_minitest_benchmark.rb b/ruby/tool/test/minitest/test_minitest_benchmark.rb deleted file mode 100644 index a783e684c..000000000 --- a/ruby/tool/test/minitest/test_minitest_benchmark.rb +++ /dev/null @@ -1,131 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: false - -require 'minitest/autorun' -require 'minitest/benchmark' - -## -# Used to verify data: -# http://www.wolframalpha.com/examples/RegressionAnalysis.html - -class TestMiniTestBenchmark < MiniTest::Unit::TestCase - def test_cls_bench_exp - assert_equal [2, 4, 8, 16, 32], self.class.bench_exp(2, 32, 2) - end - - def test_cls_bench_linear - assert_equal [2, 4, 6, 8, 10], self.class.bench_linear(2, 10, 2) - end - - def test_cls_benchmark_methods - assert_equal [], self.class.benchmark_methods - - c = Class.new(MiniTest::Unit::TestCase) do - def bench_blah - end - end - - assert_equal ["bench_blah"], c.benchmark_methods - end - - def test_cls_bench_range - assert_equal [1, 10, 100, 1_000, 10_000], self.class.bench_range - end - - def test_fit_exponential_clean - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = x.map { |n| 1.1 * Math.exp(2.1 * n) } - - assert_fit :exponential, x, y, 1.0, 1.1, 2.1 - end - - def test_fit_exponential_noisy - x = [1.0, 1.9, 2.6, 3.4, 5.0] - y = [12, 10, 8.2, 6.9, 5.9] - - # verified with Numbers and R - assert_fit :exponential, x, y, 0.95, 13.81148, -0.1820 - end - - def test_fit_logarithmic_clean - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = x.map { |n| 1.1 + 2.1 * Math.log(n) } - - assert_fit :logarithmic, x, y, 1.0, 1.1, 2.1 - end - - def test_fit_logarithmic_noisy - x = [1.0, 2.0, 3.0, 4.0, 5.0] - # Generated with - # y = x.map { |n| jitter = 0.999 + 0.002 * rand; (Math.log(n) ) * jitter } - y = [0.0, 0.6935, 1.0995, 1.3873, 1.6097] - - assert_fit :logarithmic, x, y, 0.95, 0, 1 - end - - def test_fit_constant_clean - x = (1..5).to_a - y = [5.0, 5.0, 5.0, 5.0, 5.0] - - assert_fit :linear, x, y, nil, 5.0, 0 - end - - def test_fit_constant_noisy - x = (1..5).to_a - y = [1.0, 1.2, 1.0, 0.8, 1.0] - - # verified in numbers and R - assert_fit :linear, x, y, nil, 1.12, -0.04 - end - - def test_fit_linear_clean - # y = m * x + b where m = 2.2, b = 3.1 - x = (1..5).to_a - y = x.map { |n| 2.2 * n + 3.1 } - - assert_fit :linear, x, y, 1.0, 3.1, 2.2 - end - - def test_fit_linear_noisy - x = [ 60, 61, 62, 63, 65] - y = [3.1, 3.6, 3.8, 4.0, 4.1] - - # verified in numbers and R - assert_fit :linear, x, y, 0.8315, -7.9635, 0.1878 - end - - def test_fit_power_clean - # y = A x ** B, where B = b and A = e ** a - # if, A = 1, B = 2, then - - x = [1.0, 2.0, 3.0, 4.0, 5.0] - y = [1.0, 4.0, 9.0, 16.0, 25.0] - - assert_fit :power, x, y, 1.0, 1.0, 2.0 - end - - def test_fit_power_noisy - # from www.engr.uidaho.edu/thompson/courses/ME330/lecture/least_squares.html - x = [10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35] - y = [95, 105, 125, 141, 173, 200, 253, 298, 385, 459, 602] - - # verified in numbers - assert_fit :power, x, y, 0.90, 2.6217, 1.4556 - - # income to % of households below income amount - # http://library.wolfram.com/infocenter/Conferences/6461/PowerLaws.nb - x = [15000, 25000, 35000, 50000, 75000, 100000] - y = [0.154, 0.283, 0.402, 0.55, 0.733, 0.843] - - # verified in numbers - assert_fit :power, x, y, 0.96, 3.119e-5, 0.8959 - end - - def assert_fit msg, x, y, fit, exp_a, exp_b - a, b, rr = send "fit_#{msg}", x, y - - assert_operator rr, :>=, fit if fit - assert_in_delta exp_a, a - assert_in_delta exp_b, b - end -end diff --git a/ruby/tool/test/minitest/test_minitest_mock.rb b/ruby/tool/test/minitest/test_minitest_mock.rb deleted file mode 100644 index da222c5aa..000000000 --- a/ruby/tool/test/minitest/test_minitest_mock.rb +++ /dev/null @@ -1,404 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: false - -require 'minitest/autorun' - -class TestMiniTestMock < MiniTest::Unit::TestCase - def setup - @mock = MiniTest::Mock.new.expect(:foo, nil) - @mock.expect(:meaning_of_life, 42) - end - - def test_create_stub_method - assert_nil @mock.foo - end - - def test_allow_return_value_specification - assert_equal 42, @mock.meaning_of_life - end - - def test_blow_up_if_not_called - @mock.foo - - util_verify_bad "expected meaning_of_life() => 42, got []" - end - - def test_not_blow_up_if_everything_called - @mock.foo - @mock.meaning_of_life - - assert @mock.verify - end - - def test_allow_expectations_to_be_added_after_creation - @mock.expect(:bar, true) - assert @mock.bar - end - - def test_not_verify_if_new_expected_method_is_not_called - @mock.foo - @mock.meaning_of_life - @mock.expect(:bar, true) - - util_verify_bad "expected bar() => true, got []" - end - - def test_blow_up_on_wrong_number_of_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - e = assert_raises ArgumentError do - @mock.sum - end - - assert_equal "mocked method :sum expects 2 arguments, got 0", e.message - end - - def test_return_mock_does_not_raise - retval = MiniTest::Mock.new - mock = MiniTest::Mock.new - mock.expect(:foo, retval) - mock.foo - - assert mock.verify - end - - def test_mock_args_does_not_raise - skip "non-opaque use of ==" if maglev? - - arg = MiniTest::Mock.new - mock = MiniTest::Mock.new - mock.expect(:foo, nil, [arg]) - mock.foo(arg) - - assert mock.verify - end - - def test_blow_up_on_wrong_arguments - @mock.foo - @mock.meaning_of_life - @mock.expect(:sum, 3, [1, 2]) - - e = assert_raises MockExpectationError do - @mock.sum(2, 4) - end - - exp = "mocked method :sum called with unexpected arguments [2, 4]" - assert_equal exp, e.message - end - - def test_expect_with_non_array_args - e = assert_raises ArgumentError do - @mock.expect :blah, 3, false - end - - assert_equal "args must be an array", e.message - end - - def test_respond_appropriately - assert @mock.respond_to?(:foo) - assert @mock.respond_to?(:foo, true) - assert @mock.respond_to?('foo') - assert !@mock.respond_to?(:bar) - end - - def test_no_method_error_on_unexpected_methods - e = assert_raises NoMethodError do - @mock.bar - end - - expected = "unmocked method :bar, expected one of [:foo, :meaning_of_life]" - - assert_equal expected, e.message - end - - def test_assign_per_mock_return_values - a = MiniTest::Mock.new - b = MiniTest::Mock.new - - a.expect(:foo, :a) - b.expect(:foo, :b) - - assert_equal :a, a.foo - assert_equal :b, b.foo - end - - def test_do_not_create_stub_method_on_new_mocks - a = MiniTest::Mock.new - a.expect(:foo, :a) - - assert !MiniTest::Mock.new.respond_to?(:foo) - end - - def test_mock_is_a_blank_slate - @mock.expect :kind_of?, true, [Integer] - @mock.expect :==, true, [1] - - assert @mock.kind_of?(Integer), "didn't mock :kind_of\?" - assert @mock == 1, "didn't mock :==" - end - - def test_verify_allows_called_args_to_be_loosely_specified - mock = MiniTest::Mock.new - mock.expect :loose_expectation, true, [Integer] - mock.loose_expectation 1 - - assert mock.verify - end - - def test_verify_raises_with_strict_args - mock = MiniTest::Mock.new - mock.expect :strict_expectation, true, [2] - - e = assert_raises MockExpectationError do - mock.strict_expectation 1 - end - - exp = "mocked method :strict_expectation called with unexpected arguments [1]" - assert_equal exp, e.message - end - - def test_method_missing_empty - mock = MiniTest::Mock.new - - mock.expect :a, nil - - mock.a - - e = assert_raises MockExpectationError do - mock.a - end - - assert_equal "No more expects available for :a: []", e.message - end - - def test_same_method_expects_are_verified_when_all_called - mock = MiniTest::Mock.new - mock.expect :foo, nil, [:bar] - mock.expect :foo, nil, [:baz] - - mock.foo :bar - mock.foo :baz - - assert mock.verify - end - - def test_same_method_expects_blow_up_when_not_all_called - mock = MiniTest::Mock.new - mock.expect :foo, nil, [:bar] - mock.expect :foo, nil, [:baz] - - mock.foo :bar - - e = assert_raises(MockExpectationError) { mock.verify } - - exp = "expected foo(:baz) => nil, got [foo(:bar) => nil]" - - assert_equal exp, e.message - end - - def test_verify_passes_when_mock_block_returns_true - mock = MiniTest::Mock.new - mock.expect :foo, nil do - true - end - - mock.foo - - assert mock.verify - end - - def test_mock_block_is_passed_function_params - arg1, arg2, arg3 = :bar, [1,2,3], {:a => 'a'} - mock = MiniTest::Mock.new - mock.expect :foo, nil do |a1, a2, a3| - a1 == arg1 && - a2 == arg2 && - a3 == arg3 - end - - mock.foo arg1, arg2, arg3 - - assert mock.verify - end - - def test_verify_fails_when_mock_block_returns_false - mock = MiniTest::Mock.new - mock.expect :foo, nil do - false - end - - e = assert_raises(MockExpectationError) { mock.foo } - exp = "mocked method :foo failed block w/ []" - - assert_equal exp, e.message - end - - def test_mock_block_throws_if_args_passed - mock = MiniTest::Mock.new - - e = assert_raises(ArgumentError) do - mock.expect :foo, nil, [:a, :b, :c] do - true - end - end - - exp = "args ignored when block given" - - assert_equal exp, e.message - end - - def test_mock_returns_retval_when_called_with_block - mock = MiniTest::Mock.new - mock.expect(:foo, 32) do - true - end - - rs = mock.foo - - assert_equal rs, 32 - end - - def util_verify_bad exp - e = assert_raises MockExpectationError do - @mock.verify - end - - assert_equal exp, e.message - end -end - -require_relative "metametameta" - -class TestMiniTestStub < MiniTest::Unit::TestCase - def setup - super - MiniTest::Unit::TestCase.reset - - @tc = MiniTest::Unit::TestCase.new 'fake tc' - @assertion_count = 1 - end - - def teardown - super - assert_equal @assertion_count, @tc._assertions - end - - class Time - def self.now - 24 - end - end - - def assert_stub val_or_callable - @assertion_count += 1 - - t = Time.now.to_i - - Time.stub :now, val_or_callable do - @tc.assert_equal 42, Time.now - end - - @tc.assert_operator Time.now.to_i, :>=, t - end - - def test_stub_private_module_method - @assertion_count += 1 - - t0 = Time.now - - self.stub :sleep, nil do - @tc.assert_nil sleep(10) - end - - @tc.assert_operator Time.now - t0, :<=, 1 - end - - def test_stub_private_module_method_indirect - @assertion_count += 1 - - slow_clapper = Class.new do - def slow_clap - sleep 3 - :clap - end - end.new - - slow_clapper.stub :sleep, nil do |fast_clapper| - @tc.assert_equal :clap, fast_clapper.slow_clap # either form works - @tc.assert_equal :clap, slow_clapper.slow_clap # yay closures - end - end - - def test_stub_public_module_method - Math.stub(:log10, 42.0) do - @tc.assert_in_delta 42.0, Math.log10(1000) - end - end - - def test_stub_value - assert_stub 42 - end - - def test_stub_block - assert_stub lambda { 42 } - end - - def test_stub_block_args - @assertion_count += 1 - - t = Time.now.to_i - - Time.stub :now, lambda { |n| n * 2 } do - @tc.assert_equal 42, Time.now(21) - end - - @tc.assert_operator Time.now.to_i, :>=, t - end - - def test_stub_callable - obj = Object.new - - def obj.call - 42 - end - - assert_stub obj - end - - def test_stub_yield_self - obj = "foo" - - val = obj.stub :to_s, "bar" do |s| - s.to_s - end - - @tc.assert_equal "bar", val - end - - def test_dynamic_method - @assertion_count = 2 - - dynamic = Class.new do - def self.respond_to?(meth) - meth == :found - end - - def self.method_missing(meth, *args, &block) - if meth == :found - false - else - super - end - end - end - - val = dynamic.stub(:found, true) do |s| - s.found - end - - @tc.assert_equal true, val - @tc.assert_equal false, dynamic.found - end -end diff --git a/ruby/tool/test/minitest/test_minitest_unit.rb b/ruby/tool/test/minitest/test_minitest_unit.rb deleted file mode 100644 index 1286b1537..000000000 --- a/ruby/tool/test/minitest/test_minitest_unit.rb +++ /dev/null @@ -1,1790 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: false - -require 'pathname' -require_relative 'metametameta' - -module MyModule; end -class AnError < StandardError; include MyModule; end -class ImmutableString < String; def inspect; super.freeze; end; end - -class TestMiniTestUnit < MetaMetaMetaTestCase - pwd = Pathname.new File.expand_path Dir.pwd - basedir = Pathname.new(File.expand_path "lib/minitest") + 'mini' - basedir = basedir.relative_path_from(pwd).to_s - MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" - BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", - "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", - "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] - - def test_class_puke_with_assertion_failed - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace ["unhappy"] - assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) - assert_equal 1, @tu.failures - assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("SomeClass#method_name [unhappy]", @tu.report.first) - end - - def test_class_puke_with_assertion_failed_and_long_backtrace - bt = (["test/test_some_class.rb:615:in `method_name'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) - assert_equal 1, @tu.failures - assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) - end - - def test_class_puke_with_assertion_failed_and_user_defined_assertions - bt = (["lib/test/my/util.rb:16:in `another_method_name'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "lib/test/my/util.rb:15:in `block in assert_something'", - "lib/test/my/util.rb:14:in `each'", - "lib/test/my/util.rb:14:in `assert_something'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) - assert_equal 1, @tu.failures - assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) - end - - def test_class_puke_with_failure_and_flunk_in_backtrace - exception = begin - MiniTest::Unit::TestCase.new('fake tc').flunk - rescue MiniTest::Assertion => failure - failure - end - assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) - refute @tu.report.any?{|line| line =~ /in .flunk/} - end - - def test_class_puke_with_flunk_and_user_defined_assertions - bt = (["lib/test/my/util.rb:16:in `flunk'", - "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'", - "lib/test/my/util.rb:15:in `block in assert_something'", - "lib/test/my/util.rb:14:in `each'", - "lib/test/my/util.rb:14:in `assert_something'", - "test/test_some_class.rb:615:in `each'", - "test/test_some_class.rb:614:in `test_method_name'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - bt = util_expand_bt bt - - ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first - - exception = MiniTest::Assertion.new "Oh no!" - exception.set_backtrace bt - assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) - assert_equal 1, @tu.failures - assert_match(/^Failure.*Oh no!/m, @tu.report.first) - assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) - end - - def test_class_puke_with_non_failure_exception - exception = Exception.new("Oh no again!") - assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception) - assert_equal 1, @tu.errors - assert_match(/^Exception.*Oh no again!/m, @tu.report.first) - end - - def test_filter_backtrace - # this is a semi-lame mix of relative paths. - # I cheated by making the autotest parts not have ./ - bt = (["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'", - "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29", - "test/test_autotest.rb:422"]) - bt = util_expand_bt bt - - ex = ["lib/autotest.rb:571:in `add_exception'", - "test/test_autotest.rb:62:in `test_add_exception'"] - ex = util_expand_bt ex - - fu = MiniTest::filter_backtrace(bt) - - assert_equal ex, fu - end - - def test_filter_backtrace_all_unit - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/test.rb:29"]) - ex = bt.clone - fu = MiniTest::filter_backtrace(bt) - assert_equal ex, fu - end - - def test_filter_backtrace_unit_starts - bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + - BT_MIDDLE + - ["#{MINITEST_BASE_DIR}/mini/test.rb:29", - "-e:1"]) - - bt = util_expand_bt bt - - ex = ["-e:1"] - fu = MiniTest::filter_backtrace bt - assert_equal ex, fu - end - - def test_default_runner_is_minitest_unit - assert_instance_of MiniTest::Unit, MiniTest::Unit.runner - end - - - def test_passed_eh_teardown_good - test_class = Class.new MiniTest::Unit::TestCase do - def teardown; assert true; end - def test_omg; assert true; end - end - - test = test_class.new :test_omg - test.run @tu - assert test.passed? - end - - def test_passed_eh_teardown_skipped - test_class = Class.new MiniTest::Unit::TestCase do - def teardown; assert true; end - def test_omg; skip "bork"; end - end - - test = test_class.new :test_omg - test.run @tu - assert test.passed? - end - - def test_passed_eh_teardown_flunked - test_class = Class.new MiniTest::Unit::TestCase do - def teardown; flunk; end - def test_omg; assert true; end - end - - test = test_class.new :test_omg - test.run @tu - refute test.passed? - end - - def util_expand_bt bt - bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } - end -end - -class TestMiniTestUnitInherited < MetaMetaMetaTestCase - def with_overridden_include - Class.class_eval do - def inherited_with_hacks klass - throw :inherited_hook - end - - alias inherited_without_hacks inherited - alias inherited inherited_with_hacks - alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros - end - - yield - ensure - Class.class_eval do - alias inherited inherited_without_hacks - - undef_method :inherited_with_hacks - undef_method :inherited_without_hacks - end - - refute_respond_to Class, :inherited_with_hacks - refute_respond_to Class, :inherited_without_hacks - end - - def test_inherited_hook_plays_nice_with_others - with_overridden_include do - assert_throws :inherited_hook do - Class.new MiniTest::Unit::TestCase - end - end - end -end - -class TestMiniTestRunner < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def test_class_test_suites - @assertion_count = 0 - - tc = Class.new(MiniTest::Unit::TestCase) - - assert_equal 1, MiniTest::Unit::TestCase.test_suites.size - assert_equal [tc], MiniTest::Unit::TestCase.test_suites - end - - def test_run_test - Class.new MiniTest::Unit::TestCase do - attr_reader :foo - - def run_test name - @foo = "hi mom!" - super - @foo = "okay" - end - - def test_something - assert_equal "hi mom!", foo - end - end - - expected = clean <<-EOM - . - - Finished tests in 0.00 - - 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_error - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def test_error - raise "unhandled exception" - end - end - - expected = clean <<-EOM - E. - - Finished tests in 0.00 - - 1) Error: - ##test_error: - RuntimeError: unhandled exception - FILE:LINE:in \`test_error\' - - 2 tests, 1 assertions, 0 failures, 1 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_error_teardown - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def teardown - raise "unhandled exception" - end - end - - expected = clean <<-EOM - E - - Finished tests in 0.00 - - 1) Error: - ##test_something: - RuntimeError: unhandled exception - FILE:LINE:in \`teardown\' - - 1 tests, 1 assertions, 0 failures, 1 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_failing - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def test_failure - assert false - end - end - - expected = clean <<-EOM - F. - - Finished tests in 0.00 - - 1) Failure: - ##test_failure [FILE:LINE]: - Failed assertion, no message given. - - 2 tests, 2 assertions, 1 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_failing_filtered - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def test_failure - assert false - end - end - - expected = clean <<-EOM - . - - Finished tests in 0.00 - - 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected, %w[--name /some|thing/ --seed 42] - end - - def assert_filtering name, expected, a = false - args = %W[--name #{name} --seed 42] - - alpha = Class.new MiniTest::Unit::TestCase do - define_method :test_something do - assert a - end - end - Object.const_set(:Alpha, alpha) - - beta = Class.new MiniTest::Unit::TestCase do - define_method :test_something do - assert true - end - end - Object.const_set(:Beta, beta) - - assert_report expected, args - ensure - Object.send :remove_const, :Alpha - Object.send :remove_const, :Beta - end - - def test_run_filtered_including_suite_name - expected = clean <<-EOM - . - - Finished tests in 0.00 - - 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "/Beta#test_something/", expected - end - - def test_run_filtered_including_suite_name_string - expected = clean <<-EOM - . - - Finished tests in 0.00 - - 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "Beta#test_something", expected - end - - def test_run_filtered_string_method_only - expected = clean <<-EOM - .. - - Finished tests in 0.00 - - 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_filtering "test_something", expected, :pass - end - - def test_run_passing - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - end - - expected = clean <<-EOM - . - - Finished tests in 0.00 - - 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - def test_run_skip - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def test_skip - skip "not yet" - end - end - - expected = clean <<-EOM - S. - - Finished tests in 0.00 - - 2 tests, 1 assertions, 0 failures, 0 errors, 1 skips - EOM - - assert_report expected - end - - def test_run_skip_verbose - Class.new MiniTest::Unit::TestCase do - def test_something - assert true - end - - def test_skip - skip "not yet" - end - end - - expected = clean <<-EOM - ##test_skip = 0.00 s = S - ##test_something = 0.00 s = . - - - Finished tests in 0.00 - - 1) Skipped: - ##test_skip [FILE:LINE]: - not yet - - 2 tests, 1 assertions, 0 failures, 0 errors, 1 skips - EOM - - assert_report expected, %w[--seed 42 --verbose] - end - - def test_run_with_other_runner - MiniTest::Unit.runner = Class.new MiniTest::Unit do - def _run_suite suite, type - suite.before_suite # Run once before each suite - super suite, type - end - end.new - - Class.new MiniTest::Unit::TestCase do - def self.name; "wacky!" end - - def self.before_suite - MiniTest::Unit.output.puts "Running #{self.name} tests" - @@foo = 1 - end - - def test_something - assert_equal 1, @@foo - end - - def test_something_else - assert_equal 1, @@foo - end - end - - expected = clean <<-EOM - Running wacky! tests - .. - - Finished tests in 0.00 - - 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips - EOM - - assert_report expected - end - - require 'monitor' - - class Latch - def initialize count = 1 - @count = count - @lock = Monitor.new - @cv = @lock.new_cond - end - - def release - @lock.synchronize do - @count -= 1 if @count > 0 - @cv.broadcast if @count == 0 - end - end - - def await - @lock.synchronize { @cv.wait_while { @count > 0 } } - end - end -end - -class TestMiniTestUnitOrder < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def test_before_setup - call_order = [] - Class.new MiniTest::Unit::TestCase do - define_method :setup do - super() - call_order << :setup - end - - define_method :before_setup do - call_order << :before_setup - end - - def test_omg; assert true; end - end - - with_output do - @tu.run %w[--seed 42] - end - - expected = [:before_setup, :setup] - assert_equal expected, call_order - end - - def test_after_teardown - call_order = [] - Class.new MiniTest::Unit::TestCase do - define_method :teardown do - super() - call_order << :teardown - end - - define_method :after_teardown do - call_order << :after_teardown - end - - def test_omg; assert true; end - end - - with_output do - @tu.run %w[--seed 42] - end - - expected = [:teardown, :after_teardown] - assert_equal expected, call_order - end - - def test_all_teardowns_are_guaranteed_to_run - call_order = [] - Class.new MiniTest::Unit::TestCase do - define_method :after_teardown do - super() - call_order << :after_teardown - raise - end - - define_method :teardown do - super() - call_order << :teardown - raise - end - - define_method :before_teardown do - super() - call_order << :before_teardown - raise - end - - def test_omg; assert true; end - end - - with_output do - @tu.run %w[--seed 42] - end - - expected = [:before_teardown, :teardown, :after_teardown] - assert_equal expected, call_order - end - - def test_setup_and_teardown_survive_inheritance - call_order = [] - - parent = Class.new MiniTest::Unit::TestCase do - define_method :setup do - call_order << :setup_method - end - - define_method :teardown do - call_order << :teardown_method - end - - define_method :test_something do - call_order << :test - end - end - - _ = Class.new parent - - with_output do - @tu.run %w[--seed 42] - end - - # Once for the parent class, once for the child - expected = [:setup_method, :test, :teardown_method] * 2 - - assert_equal expected, call_order - end -end - -class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase - # do not call parallelize_me! - teardown accesses @tc._assertions - # which is not threadsafe. Nearly every method in here is an - # assertion test so it isn't worth splitting it out further. - - RUBY18 = ! defined? Encoding - - def setup - super - - MiniTest::Unit::TestCase.reset - - @tc = MiniTest::Unit::TestCase.new 'fake tc' - @zomg = "zomg ponies!" - @assertion_count = 1 - end - - def teardown - assert_equal(@assertion_count, @tc._assertions, - "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc.passed? - end - - def non_verbose - orig_verbose = $VERBOSE - $VERBOSE = false - - yield - ensure - $VERBOSE = orig_verbose - end - - def test_assert - @assertion_count = 2 - - @tc.assert_equal true, @tc.assert(true), "returns true on success" - end - - def test_assert__triggered - util_assert_triggered "Failed assertion, no message given." do - @tc.assert false - end - end - - def test_assert__triggered_message - util_assert_triggered @zomg do - @tc.assert false, @zomg - end - end - - def test_assert_empty - @assertion_count = 2 - - @tc.assert_empty [] - end - - def test_assert_empty_triggered - @assertion_count = 2 - - util_assert_triggered "Expected [1] to be empty." do - @tc.assert_empty [1] - end - end - - def test_assert_equal - @tc.assert_equal 1, 1 - end - - def test_assert_equal_different_collection_array_hex_invisible - object1 = Object.new - object2 = Object.new - msg = "No visible difference in the Array#inspect output. - You should look at the implementation of #== on Array or its members. - [#]".gsub(/^ +/, "") - util_assert_triggered msg do - @tc.assert_equal [object1], [object2] - end - end - - def test_assert_equal_different_collection_hash_hex_invisible - h1, h2 = {}, {} - h1[1] = Object.new - h2[1] = Object.new - msg = "No visible difference in the Hash#inspect output. - You should look at the implementation of #== on Hash or its members. - {1=>#}".gsub(/^ +/, "") - - util_assert_triggered msg do - @tc.assert_equal h1, h2 - end - end - - def test_assert_equal_different_diff_deactivated - skip "https://github.com/MagLev/maglev/issues/209" if maglev? - - without_diff do - util_assert_triggered util_msg("haha" * 10, "blah" * 10) do - o1 = "haha" * 10 - o2 = "blah" * 10 - - @tc.assert_equal o1, o2 - end - end - end - - def test_assert_equal_different_hex - c = Class.new do - def initialize s; @name = s; end - end - - o1 = c.new "a" - o2 = c.new "b" - msg = "--- expected - +++ actual - @@ -1 +1 @@ - -#<#:0xXXXXXX @name=\"a\"> - +#<#:0xXXXXXX @name=\"b\"> - ".gsub(/^ +/, "") - - util_assert_triggered msg do - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_hex_invisible - o1 = Object.new - o2 = Object.new - - msg = "No visible difference in the Object#inspect output. - You should look at the implementation of #== on Object or its members. - #".gsub(/^ +/, "") - - util_assert_triggered msg do - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long - msg = "--- expected - +++ actual - @@ -1 +1 @@ - -\"hahahahahahahahahahahahahahahahahahahaha\" - +\"blahblahblahblahblahblahblahblahblahblah\" - ".gsub(/^ +/, "") - - util_assert_triggered msg do - o1 = "haha" * 10 - o2 = "blah" * 10 - - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long_invisible - msg = "No visible difference in the String#inspect output. - You should look at the implementation of #== on String or its members. - \"blahblahblahblahblahblahblahblahblahblah\"".gsub(/^ +/, "") - - util_assert_triggered msg do - o1 = "blah" * 10 - o2 = "blah" * 10 - def o1.== o - false - end - @tc.assert_equal o1, o2 - end - end - - def test_assert_equal_different_long_msg - msg = "message. - --- expected - +++ actual - @@ -1 +1 @@ - -\"hahahahahahahahahahahahahahahahahahahaha\" - +\"blahblahblahblahblahblahblahblahblahblah\" - ".gsub(/^ +/, "") - - util_assert_triggered msg do - o1 = "haha" * 10 - o2 = "blah" * 10 - @tc.assert_equal o1, o2, "message" - end - end - - def test_assert_equal_different_short - util_assert_triggered util_msg(1, 2) do - @tc.assert_equal 1, 2 - end - end - - def test_assert_equal_different_short_msg - util_assert_triggered util_msg(1, 2, "message") do - @tc.assert_equal 1, 2, "message" - end - end - - def test_assert_equal_different_short_multiline - msg = "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n \"a\n-b\"\n+c\"\n" - util_assert_triggered msg do - @tc.assert_equal "a\nb", "a\nc" - end - end - - def test_assert_equal_different_escaped_newline - msg = "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n \"xxx\n-a\\\\nb\"\n+a\\\\nc\"\n" - util_assert_triggered msg do - @tc.assert_equal "xxx\na\\nb", "xxx\na\\nc" - end - end - - def test_assert_in_delta - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 - end - - def test_delta_consistency - @tc.assert_in_delta 0, 1, 1 - - util_assert_triggered "Expected |0 - 1| (1) to not be <= 1." do - @tc.refute_in_delta 0, 1, 1 - end - end - - def test_assert_in_delta_triggered - x = maglev? ? "9.999999xxxe-07" : "1.0e-06" - util_assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do - @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 - end - end - - def test_assert_in_epsilon - @assertion_count = 10 - - @tc.assert_in_epsilon 10000, 9991 - @tc.assert_in_epsilon 9991, 10000 - @tc.assert_in_epsilon 1.0, 1.001 - @tc.assert_in_epsilon 1.001, 1.0 - - @tc.assert_in_epsilon 10000, 9999.1, 0.0001 - @tc.assert_in_epsilon 9999.1, 10000, 0.0001 - @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 - @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 - - @tc.assert_in_epsilon(-1, -1) - @tc.assert_in_epsilon(-10000, -9991) - end - - def test_epsilon_consistency - @tc.assert_in_epsilon 1.0, 1.001 - - msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001." - util_assert_triggered msg do - @tc.refute_in_epsilon 1.0, 1.001 - end - end - - def test_assert_in_epsilon_triggered - util_assert_triggered 'Expected |10000 - 9990| (10) to be <= 9.99.' do - @tc.assert_in_epsilon 10000, 9990 - end - end - - def test_assert_in_epsilon_triggered_negative_case - x = (RUBY18 and not maglev?) ? "0.1" : "0.100000xxx" - y = maglev? ? "0.100000xxx" : "0.1" - util_assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do - @tc.assert_in_epsilon(-1.1, -1, 0.1) - end - end - - def test_assert_includes - @assertion_count = 2 - - @tc.assert_includes [true], true - end - - def test_assert_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises MiniTest::Assertion do - @tc.assert_includes [true], false - end - - expected = "Expected [true] to include false." - assert_equal expected, e.message - end - - def test_assert_instance_of - @tc.assert_instance_of String, "blah" - end - - def test_assert_instance_of_triggered - util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do - @tc.assert_instance_of Array, "blah" - end - end - - def test_assert_kind_of - @tc.assert_kind_of String, "blah" - end - - def test_assert_kind_of_triggered - util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do - @tc.assert_kind_of Array, "blah" - end - end - - def test_assert_match - @assertion_count = 2 - @tc.assert_match(/\w+/, "blah blah blah") - end - - def test_assert_match_matcher_object - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) true end - - @tc.assert_match pattern, 5 - end - - def test_assert_match_matchee_to_str - @assertion_count = 2 - - obj = Object.new - def obj.to_str; "blah" end - - @tc.assert_match "blah", obj - end - - def test_assert_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) false end - def pattern.inspect; "[Object]" end - - util_assert_triggered 'Expected [Object] to match 5.' do - @tc.assert_match pattern, 5 - end - end - - def test_assert_match_triggered - @assertion_count = 2 - util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do - @tc.assert_match(/\d+/, "blah blah blah") - end - end - - def test_assert_nil - @tc.assert_nil nil - end - - def test_assert_nil_triggered - util_assert_triggered 'Expected 42 to be nil.' do - @tc.assert_nil 42 - end - end - - def test_assert_operator - @tc.assert_operator 2, :>, 1 - end - - def test_assert_operator_bad_object - bad = Object.new - def bad.==(other) true end - - @tc.assert_operator bad, :equal?, bad - end - - def test_assert_operator_triggered - util_assert_triggered "Expected 2 to be < 1." do - @tc.assert_operator 2, :<, 1 - end - end - - def test_assert_output_both - @assertion_count = 2 - - @tc.assert_output "yay", "blah" do - print "yay" - $stderr.print "blah" - end - end - - def test_assert_output_both_regexps - @assertion_count = 4 - - @tc.assert_output(/y.y/, /bl.h/) do - print "yay" - $stderr.print "blah" - end - end - - def test_assert_output_err - @tc.assert_output nil, "blah" do - $stderr.print "blah" - end - end - - def test_assert_output_neither - @assertion_count = 0 - - @tc.assert_output do - # do nothing - end - end - - def test_assert_output_out - @tc.assert_output "blah" do - print "blah" - end - end - - def test_assert_output_triggered_both - util_assert_triggered util_msg("blah", "blah blah", "In stderr") do - @tc.assert_output "yay", "blah" do - print "boo" - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_err - util_assert_triggered util_msg("blah", "blah blah", "In stderr") do - @tc.assert_output nil, "blah" do - $stderr.print "blah blah" - end - end - end - - def test_assert_output_triggered_out - util_assert_triggered util_msg("blah", "blah blah", "In stdout") do - @tc.assert_output "blah" do - print "blah blah" - end - end - end - - def test_assert_predicate - @tc.assert_predicate "", :empty? - end - - def test_assert_predicate_triggered - util_assert_triggered 'Expected "blah" to be empty?.' do - @tc.assert_predicate "blah", :empty? - end - end - - def test_assert_raises - @tc.assert_raises RuntimeError do - raise "blah" - end - end - - def test_assert_raises_module - @tc.assert_raises MyModule do - raise AnError - end - end - - ## - # *sigh* This is quite an odd scenario, but it is from real (albeit - # ugly) test code in ruby-core: - # - # https://github.com/ruby/ruby/commit/6bab4ea9917dc05cd2c94aead2e96eb7df7d4be1 - - def test_assert_raises_skip - @assertion_count = 0 - - util_assert_triggered "skipped", MiniTest::Skip do - @tc.assert_raises ArgumentError do - begin - raise "blah" - rescue - skip "skipped" - end - end - end - end - - def test_assert_raises_triggered_different - e = assert_raises MiniTest::Assertion do - @tc.assert_raises RuntimeError do - raise SyntaxError, "icky" - end - end - - expected = clean <<-EOM.chomp - [RuntimeError] exception expected, not - Class: - Message: <\"icky\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_triggered_different\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' - - assert_equal expected, actual - end - - def test_assert_raises_triggered_different_msg - e = assert_raises MiniTest::Assertion do - @tc.assert_raises RuntimeError, "XXX" do - raise SyntaxError, "icky" - end - end - - expected = clean <<-EOM - XXX. - [RuntimeError] exception expected, not - Class: - Message: <\"icky\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_triggered_different_msg\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' - - assert_equal expected.chomp, actual - end - - def test_assert_raises_triggered_none - e = assert_raises MiniTest::Assertion do - @tc.assert_raises MiniTest::Assertion do - # do nothing - end - end - - expected = "MiniTest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_triggered_none_msg - e = assert_raises MiniTest::Assertion do - @tc.assert_raises MiniTest::Assertion, "XXX" do - # do nothing - end - end - - expected = "XXX.\nMiniTest::Assertion expected but nothing was raised." - - assert_equal expected, e.message - end - - def test_assert_raises_triggered_subclass - e = assert_raises MiniTest::Assertion do - @tc.assert_raises StandardError do - raise AnError - end - end - - expected = clean <<-EOM.chomp - [StandardError] exception expected, not - Class: - Message: <\"AnError\"> - ---Backtrace--- - FILE:LINE:in \`test_assert_raises_triggered_subclass\' - --------------- - EOM - - actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') - actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' - - assert_equal expected, actual - end - - def test_assert_respond_to - @tc.assert_respond_to "blah", :empty? - end - - def test_assert_respond_to_triggered - util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do - @tc.assert_respond_to "blah", :rawr! - end - end - - def test_assert_same - @assertion_count = 3 - - o = "blah" - @tc.assert_same 1, 1 - @tc.assert_same :blah, :blah - @tc.assert_same o, o - end - - def test_assert_same_triggered - @assertion_count = 2 - - util_assert_triggered 'Expected 2 (oid=N) to be the same as 1 (oid=N).' do - @tc.assert_same 1, 2 - end - - s1 = "blah" - s2 = "blah" - - util_assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do - @tc.assert_same s1, s2 - end - end - - def test_assert_send - @tc.assert_send [1, :<, 2] - end - - def test_assert_send_bad - util_assert_triggered "Expected 1.>(*[2]) to return true." do - @tc.assert_send [1, :>, 2] - end - end - - def test_assert_silent - @assertion_count = 2 - - @tc.assert_silent do - # do nothing - end - end - - def test_assert_silent_triggered_err - util_assert_triggered util_msg("", "blah blah", "In stderr") do - @tc.assert_silent do - $stderr.print "blah blah" - end - end - end - - def test_assert_silent_triggered_out - @assertion_count = 2 - - util_assert_triggered util_msg("", "blah blah", "In stdout") do - @tc.assert_silent do - print "blah blah" - end - end - end - - def test_assert_throws - @tc.assert_throws :blah do - throw :blah - end - end - - def test_assert_throws_different - util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do - @tc.assert_throws :blah do - throw :not_blah - end - end - end - - def test_assert_throws_unthrown - util_assert_triggered 'Expected :blah to have been thrown.' do - @tc.assert_throws :blah do - # do nothing - end - end - end - - def test_capture_io - @assertion_count = 0 - - non_verbose do - out, err = capture_io do - puts 'hi' - $stderr.puts 'bye!' - end - - assert_equal "hi\n", out - assert_equal "bye!\n", err - end - end - - def test_capture_subprocess_io - @assertion_count = 0 - - non_verbose do - out, err = capture_subprocess_io do - system("echo", "hi") - system("echo", "bye!", out: :err) - end - - assert_equal "hi\n", out - assert_equal "bye!\n", err - end - end - - def test_class_asserts_match_refutes - @assertion_count = 0 - - methods = MiniTest::Assertions.public_instance_methods - methods.map! { |m| m.to_s } if Symbol === methods.first - - # These don't have corresponding refutes _on purpose_. They're - # useless and will never be added, so don't bother. - ignores = %w[assert_output assert_raises assert_send - assert_silent assert_throws] - - # These are test/unit methods. I'm not actually sure why they're still here - ignores += %w[assert_no_match assert_not_equal assert_not_nil - assert_not_same assert_nothing_raised - assert_nothing_thrown assert_raise] - - asserts = methods.grep(/^assert/).sort - ignores - refutes = methods.grep(/^refute/).sort - ignores - - assert_empty refutes.map { |n| n.sub(/^refute/, 'assert') } - asserts - assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes - end - - def test_flunk - util_assert_triggered 'Epic Fail!' do - @tc.flunk - end - end - - def test_flunk_message - util_assert_triggered @zomg do - @tc.flunk @zomg - end - end - - def test_message - @assertion_count = 0 - - assert_equal "blah2.", @tc.message { "blah2" }.call - assert_equal "blah2.", @tc.message("") { "blah2" }.call - assert_equal "blah1.\nblah2.", @tc.message(:blah1) { "blah2" }.call - assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call - - message = proc { "blah1" } - assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call - - message = @tc.message { "blah1" } - assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call - end - - def test_message_message - util_assert_triggered "whoops.\nExpected: 1\n Actual: 2" do - @tc.assert_equal 1, 2, message { "whoops" } - end - end - - def test_message_lambda - util_assert_triggered "whoops.\nExpected: 1\n Actual: 2" do - @tc.assert_equal 1, 2, lambda { "whoops" } - end - end - - def test_message_deferred - @assertion_count, var = 0, nil - - msg = message { var = "blah" } - - assert_nil var - - msg.call - - assert_equal "blah", var - end - - def test_pass - @tc.pass - end - - def test_prints - printer = Class.new { extend MiniTest::Assertions } - @tc.assert_equal '"test"', printer.mu_pp(ImmutableString.new 'test') - end - - def test_refute - @assertion_count = 2 - - @tc.assert_equal false, @tc.refute(false), "returns false on success" - end - - def test_refute_empty - @assertion_count = 2 - - @tc.refute_empty [1] - end - - def test_refute_empty_triggered - @assertion_count = 2 - - util_assert_triggered "Expected [] to not be empty." do - @tc.refute_empty [] - end - end - - def test_refute_equal - @tc.refute_equal "blah", "yay" - end - - def test_refute_equal_triggered - util_assert_triggered 'Expected "blah" to not be equal to "blah".' do - @tc.refute_equal "blah", "blah" - end - end - - def test_refute_in_delta - @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 - end - - def test_refute_in_delta_triggered - x = maglev? ? "0.100000xxx" : "0.1" - util_assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do - @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1 - end - end - - def test_refute_in_epsilon - @tc.refute_in_epsilon 10000, 9990-1 - end - - def test_refute_in_epsilon_triggered - util_assert_triggered 'Expected |10000 - 9990| (10) to not be <= 10.0.' do - @tc.refute_in_epsilon 10000, 9990 - fail - end - end - - def test_refute_includes - @assertion_count = 2 - - @tc.refute_includes [true], false - end - - def test_refute_includes_triggered - @assertion_count = 3 - - e = @tc.assert_raises MiniTest::Assertion do - @tc.refute_includes [true], true - end - - expected = "Expected [true] to not include true." - assert_equal expected, e.message - end - - def test_refute_instance_of - @tc.refute_instance_of Array, "blah" - end - - def test_refute_instance_of_triggered - util_assert_triggered 'Expected "blah" to not be an instance of String.' do - @tc.refute_instance_of String, "blah" - end - end - - def test_refute_kind_of - @tc.refute_kind_of Array, "blah" - end - - def test_refute_kind_of_triggered - util_assert_triggered 'Expected "blah" to not be a kind of String.' do - @tc.refute_kind_of String, "blah" - end - end - - def test_refute_match - @assertion_count = 2 - @tc.refute_match(/\d+/, "blah blah blah") - end - - def test_refute_match_matcher_object - @assertion_count = 2 - non_verbose do - obj = Object.new - def obj.=~(other); false; end - @tc.refute_match obj, 5 - end - end - - def test_refute_match_object_triggered - @assertion_count = 2 - - pattern = Object.new - def pattern.=~(other) true end - def pattern.inspect; "[Object]" end - - util_assert_triggered 'Expected [Object] to not match 5.' do - @tc.refute_match pattern, 5 - end - end - - def test_refute_match_triggered - @assertion_count = 2 - util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do - @tc.refute_match(/\w+/, "blah blah blah") - end - end - - def test_refute_nil - @tc.refute_nil 42 - end - - def test_refute_nil_triggered - util_assert_triggered 'Expected nil to not be nil.' do - @tc.refute_nil nil - end - end - - def test_refute_predicate - @tc.refute_predicate "42", :empty? - end - - def test_refute_predicate_triggered - util_assert_triggered 'Expected "" to not be empty?.' do - @tc.refute_predicate "", :empty? - end - end - - def test_refute_operator - @tc.refute_operator 2, :<, 1 - end - - def test_refute_operator_bad_object - bad = Object.new - def bad.==(other) true end - - @tc.refute_operator true, :equal?, bad - end - - def test_refute_operator_triggered - util_assert_triggered "Expected 2 to not be > 1." do - @tc.refute_operator 2, :>, 1 - end - end - - def test_refute_respond_to - @tc.refute_respond_to "blah", :rawr! - end - - def test_refute_respond_to_triggered - util_assert_triggered 'Expected "blah" to not respond to empty?.' do - @tc.refute_respond_to "blah", :empty? - end - end - - def test_refute_same - @tc.refute_same 1, 2 - end - - def test_refute_same_triggered - util_assert_triggered 'Expected 1 (oid=N) to not be the same as 1 (oid=N).' do - @tc.refute_same 1, 1 - end - end - - def test_skip - @assertion_count = 0 - - util_assert_triggered "haha!", MiniTest::Skip do - @tc.skip "haha!" - end - end - - def test_test_methods_random - @assertion_count = 0 - - sample_test_case = Class.new MiniTest::Unit::TestCase do - def self.test_order; :random; end - def test_test1; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test3; assert "does not matter" end - @test_order = [1, 0, 2] - def self.rand(n) @test_order.shift; end - end - - expected = %w(test_test2 test_test1 test_test3) - assert_equal expected, sample_test_case.test_methods - end - - def test_test_methods_sorted - @assertion_count = 0 - - sample_test_case = Class.new MiniTest::Unit::TestCase do - def self.test_order; :sorted end - def test_test3; assert "does not matter" end - def test_test2; assert "does not matter" end - def test_test1; assert "does not matter" end - end - - expected = %w(test_test1 test_test2 test_test3) - assert_equal expected, sample_test_case.test_methods - end - - def assert_triggered expected, klass = MiniTest::Assertion - e = assert_raises klass do - yield - end - - msg = e.message.sub(/(---Backtrace---).*/m, '\1') - msg.gsub!(/\(oid=[-0-9]+\)/, '(oid=N)') - msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform - - assert_equal expected, msg - end - alias util_assert_triggered assert_triggered - - def util_msg exp, act, msg = nil - s = "Expected: #{exp.inspect}\n Actual: #{act.inspect}" - s = "#{msg}.\n#{s}" if msg - s - end - - def without_diff - old_diff = MiniTest::Assertions.diff - MiniTest::Assertions.diff = nil - - yield - ensure - MiniTest::Assertions.diff = old_diff - end -end - -class TestMiniTestGuard < MiniTest::Unit::TestCase - def test_mri_eh - assert self.class.mri? "ruby blah" - assert self.mri? "ruby blah" - end - - def test_jruby_eh - assert self.class.jruby? "java" - assert self.jruby? "java" - end - - def test_rubinius_eh - assert self.class.rubinius? "rbx" - assert self.rubinius? "rbx" - end - - def test_windows_eh - assert self.class.windows? "mswin" - assert self.windows? "mswin" - end -end - -class TestMiniTestUnitRecording < MetaMetaMetaTestCase - # do not parallelize this suite... it just can't handle it. - - def assert_run_record(*expected, &block) - def @tu.record suite, method, assertions, time, error - recording[method] << error - end - - def @tu.recording - @recording ||= Hash.new { |h,k| h[k] = [] } - end - - MiniTest::Unit.runner = @tu - - Class.new MiniTest::Unit::TestCase, &block - - with_output do - @tu.run - end - - recorded = @tu.recording.fetch("test_method").map(&:class) - - assert_equal expected, recorded - end - - def test_record_passing - assert_run_record NilClass do - def test_method - assert true - end - end - end - - def test_record_failing - assert_run_record MiniTest::Assertion do - def test_method - assert false - end - end - end - - def test_record_error - assert_run_record RuntimeError do - def test_method - raise "unhandled exception" - end - end - end - - def test_record_error_teardown - assert_run_record NilClass, RuntimeError do - def test_method - assert true - end - - def teardown - raise "unhandled exception" - end - end - end - - def test_record_error_in_test_and_teardown - assert_run_record AnError, RuntimeError do - def test_method - raise AnError - end - - def teardown - raise "unhandled exception" - end - end - end - - def test_record_skip - assert_run_record MiniTest::Skip do - def test_method - skip "not yet" - end - end - end -end diff --git a/ruby/tool/test/runner.rb b/ruby/tool/test/runner.rb index 60d9af24b..c62994309 100644 --- a/ruby/tool/test/runner.rb +++ b/ruby/tool/test/runner.rb @@ -9,7 +9,7 @@ require "tracepointchecker" require "zombie_hunter" require "iseq_loader_checker" -require "gc_compact_checker" +require "gc_checker" require_relative "../test-coverage.rb" if ENV.key?('COVERAGE') case $0 diff --git a/ruby/tool/test/testunit/metametameta.rb b/ruby/tool/test/testunit/metametameta.rb new file mode 100644 index 000000000..e49403893 --- /dev/null +++ b/ruby/tool/test/testunit/metametameta.rb @@ -0,0 +1,70 @@ +# encoding: utf-8 +# frozen_string_literal: false + +require 'tempfile' +require 'stringio' + +class Test::Unit::TestCase + def clean s + s.gsub(/^ {6}/, '') + end +end + +class MetaMetaMetaTestCase < Test::Unit::TestCase + def assert_report expected, flags = %w[--seed 42] + header = clean <<-EOM + Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "} + + # Running tests: + + EOM + + with_output do + @tu.run flags + end + + output = @output.string.dup + output.sub!(/Finished tests in .*/, "Finished tests in 0.00") + output.sub!(/Loaded suite .*/, 'Loaded suite blah') + + output.gsub!(/ = \d+.\d\d s = /, ' = 0.00 s = ') + output.gsub!(/0x[A-Fa-f0-9]+/, '0xXXX') + + if windows? then + output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, '[FILE:LINE]') + output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in') + else + output.gsub!(/\[[^\]:]+:\d+\]/, '[FILE:LINE]') + output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in') + end + + assert_equal header + expected, output + end + + def setup + super + srand 42 + Test::Unit::TestCase.reset + @tu = Test::Unit::Runner.new + + Test::Unit::Runner.runner = nil # protect the outer runner from the inner tests + end + + def teardown + super + end + + def with_output + synchronize do + begin + save = Test::Unit::Runner.output + @output = StringIO.new("") + Test::Unit::Runner.output = @output + + yield + ensure + Test::Unit::Runner.output = save + end + end + end +end diff --git a/ruby/tool/test/testunit/test_assertion.rb b/ruby/tool/test/testunit/test_assertion.rb index 0c7c4882b..8c83b447a 100644 --- a/ruby/tool/test/testunit/test_assertion.rb +++ b/ruby/tool/test/testunit/test_assertion.rb @@ -22,7 +22,7 @@ def return_in_assert_raise end def test_assert_raise - assert_raise(MiniTest::Assertion) do + assert_raise(Test::Unit::AssertionFailedError) do return_in_assert_raise end end diff --git a/ruby/tool/test/testunit/test_hideskip.rb b/ruby/tool/test/testunit/test_hideskip.rb index 0188316a2..13d887189 100644 --- a/ruby/tool/test/testunit/test_hideskip.rb +++ b/ruby/tool/test/testunit/test_hideskip.rb @@ -6,7 +6,7 @@ def test_hideskip assert_not_match(/^ *1\) Skipped/, hideskip) assert_match(/^ *1\) Skipped/, hideskip("--show-skip")) output = hideskip("--hide-skip") - output.gsub!(/Successful MJIT finish\n/, '') if RubyVM::MJIT.enabled? + output.gsub!(/Successful MJIT finish\n/, '') if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? assert_match(/assertions\/s.\n+1 tests, 0 assertions, 0 failures, 0 errors, 1 skips/, output) end diff --git a/ruby/tool/test/testunit/test_minitest_unit.rb b/ruby/tool/test/testunit/test_minitest_unit.rb new file mode 100644 index 000000000..5941392fa --- /dev/null +++ b/ruby/tool/test/testunit/test_minitest_unit.rb @@ -0,0 +1,1474 @@ +# encoding: utf-8 +# frozen_string_literal: false + +require 'pathname' +require_relative 'metametameta' + +module MyModule; end +class AnError < StandardError; include MyModule; end +class ImmutableString < String; def inspect; super.freeze; end; end + +class TestMiniTestUnit < MetaMetaMetaTestCase + pwd = Pathname.new File.expand_path Dir.pwd + basedir = Pathname.new(File.expand_path "lib/test") + basedir = basedir.relative_path_from(pwd).to_s + MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" + BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'", + "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", + "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", + "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] + + def test_class_puke_with_assertion_failed + exception = Test::Unit::AssertionFailedError.new "Oh no!" + exception.set_backtrace ["unhappy"] + assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) + assert_equal 1, @tu.failures + assert_match(/^Failure.*Oh no!/m, @tu.report.first) + assert_match("SomeClass#method_name [unhappy]", @tu.report.first) + end + + def test_class_puke_with_assertion_failed_and_long_backtrace + bt = (["test/test_some_class.rb:615:in `method_name'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = Test::Unit::AssertionFailedError.new "Oh no!" + exception.set_backtrace bt + assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) + assert_equal 1, @tu.failures + assert_match(/^Failure.*Oh no!/m, @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) + end + + def test_class_puke_with_assertion_failed_and_user_defined_assertions + bt = (["lib/test/my/util.rb:16:in `another_method_name'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'", + "lib/test/my/util.rb:15:in `block in assert_something'", + "lib/test/my/util.rb:14:in `each'", + "lib/test/my/util.rb:14:in `assert_something'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = Test::Unit::AssertionFailedError.new "Oh no!" + exception.set_backtrace bt + assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) + assert_equal 1, @tu.failures + assert_match(/^Failure.*Oh no!/m, @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) + end + + def test_class_puke_with_failure_and_flunk_in_backtrace + exception = begin + Test::Unit::TestCase.new('fake tc').flunk + rescue Test::Unit::AssertionFailedError => failure + failure + end + assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception) + refute @tu.report.any?{|line| line =~ /in .flunk/} + end + + def test_class_puke_with_flunk_and_user_defined_assertions + bt = (["lib/test/my/util.rb:16:in `flunk'", + "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'", + "lib/test/my/util.rb:15:in `block in assert_something'", + "lib/test/my/util.rb:14:in `each'", + "lib/test/my/util.rb:14:in `assert_something'", + "test/test_some_class.rb:615:in `each'", + "test/test_some_class.rb:614:in `test_method_name'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + bt = util_expand_bt bt + + ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first + + exception = Test::Unit::AssertionFailedError.new "Oh no!" + exception.set_backtrace bt + assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception) + assert_equal 1, @tu.failures + assert_match(/^Failure.*Oh no!/m, @tu.report.first) + assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first) + end + + def test_class_puke_with_non_failure_exception + exception = Exception.new("Oh no again!") + assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception) + assert_equal 1, @tu.errors + assert_match(/^Exception.*Oh no again!/m, @tu.report.first) + end + + def test_filter_backtrace + # this is a semi-lame mix of relative paths. + # I cheated by making the autotest parts not have ./ + bt = (["lib/autotest.rb:571:in `add_exception'", + "test/test_autotest.rb:62:in `test_add_exception'", + "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29", + "test/test_autotest.rb:422"]) + bt = util_expand_bt bt + + ex = ["lib/autotest.rb:571:in `add_exception'", + "test/test_autotest.rb:62:in `test_add_exception'"] + ex = util_expand_bt ex + + fu = Test::filter_backtrace(bt) + + assert_equal ex, fu + end + + def test_filter_backtrace_all_unit + bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/test.rb:29"]) + ex = bt.clone + fu = Test::filter_backtrace(bt) + assert_equal ex, fu + end + + def test_filter_backtrace_unit_starts + bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + + BT_MIDDLE + + ["#{MINITEST_BASE_DIR}/mini/test.rb:29", + "-e:1"]) + + bt = util_expand_bt bt + + ex = ["-e:1"] + fu = Test::filter_backtrace bt + assert_equal ex, fu + end + + def test_default_runner_is_minitest_unit + assert_instance_of Test::Unit::Runner, Test::Unit::Runner.runner + end + + + def test_passed_eh_teardown_good + test_class = Class.new Test::Unit::TestCase do + def teardown; assert true; end + def test_omg; assert true; end + end + + test = test_class.new :test_omg + test.run @tu + assert test.passed? + end + + def test_passed_eh_teardown_skipped + test_class = Class.new Test::Unit::TestCase do + def teardown; assert true; end + def test_omg; skip "bork"; end + end + + test = test_class.new :test_omg + test.run @tu + assert test.passed? + end + + def test_passed_eh_teardown_flunked + test_class = Class.new Test::Unit::TestCase do + def teardown; flunk; end + def test_omg; assert true; end + end + + test = test_class.new :test_omg + test.run @tu + refute test.passed? + end + + def util_expand_bt bt + bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } + end +end + +class TestMiniTestUnitInherited < MetaMetaMetaTestCase + def with_overridden_include + Class.class_eval do + def inherited_with_hacks klass + throw :inherited_hook + end + + alias inherited_without_hacks inherited + alias inherited inherited_with_hacks + alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros + end + + yield + ensure + Class.class_eval do + alias inherited inherited_without_hacks + + undef_method :inherited_with_hacks + undef_method :inherited_without_hacks + end + + refute_respond_to Class, :inherited_with_hacks + refute_respond_to Class, :inherited_without_hacks + end + + def test_inherited_hook_plays_nice_with_others + with_overridden_include do + assert_throws :inherited_hook do + Class.new Test::Unit::TestCase + end + end + end +end + +class TestMiniTestRunner < MetaMetaMetaTestCase + # do not parallelize this suite... it just can't handle it. + + def test_class_test_suites + @assertion_count = 0 + + tc = Class.new(Test::Unit::TestCase) + + assert_equal 2, Test::Unit::TestCase.test_suites.size + assert_equal [tc, Test::Unit::TestCase], Test::Unit::TestCase.test_suites.sort_by {|ts| ts.name.to_s} + end + + def assert_filtering name, expected, a = false + args = %W[--name #{name} --seed 42] + + alpha = Class.new Test::Unit::TestCase do + define_method :test_something do + assert a + end + end + Object.const_set(:Alpha, alpha) + + beta = Class.new Test::Unit::TestCase do + define_method :test_something do + assert true + end + end + Object.const_set(:Beta, beta) + + assert_report expected, args + ensure + Object.send :remove_const, :Alpha + Object.send :remove_const, :Beta + end + + def test_run_with_other_runner + pend "We don't imagine to replace the default runner with ruby/ruby test suite." + Test::Unit::Runner.runner = Class.new Test::Unit::Runner do + def _run_suite suite, type + suite.before_suite # Run once before each suite + super suite, type + end + end.new + + Class.new Test::Unit::TestCase do + def self.name; "wacky!" end + + def self.before_suite + Test::Unit::Runner.output.puts "Running #{self.name} tests" + @@foo = 1 + end + + def test_something + assert_equal 1, @@foo + end + + def test_something_else + assert_equal 1, @@foo + end + end + + expected = clean <<-EOM + Running wacky! tests + .. + + Finished tests in 0.00 + + 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips + EOM + + assert_report expected + end + + require 'monitor' + + class Latch + def initialize count = 1 + @count = count + @lock = Monitor.new + @cv = @lock.new_cond + end + + def release + @lock.synchronize do + @count -= 1 if @count > 0 + @cv.broadcast if @count == 0 + end + end + + def await + @lock.synchronize { @cv.wait_while { @count > 0 } } + end + end +end + +class TestMiniTestUnitOrder < MetaMetaMetaTestCase + # do not parallelize this suite... it just can't handle it. + + def test_before_setup + pend "Surpressing the raise message when running with tests" + + call_order = [] + Class.new Test::Unit::TestCase do + define_method :setup do + super() + call_order << :setup + end + + define_method :before_setup do + call_order << :before_setup + end + + def test_omg; assert true; end + end + + with_output do + @tu.run %w[--seed 42] + end + + expected = [:before_setup, :setup] + assert_equal expected, call_order + end + + def test_after_teardown + pend "Surpressing the result message of this tests" + + call_order = [] + Class.new Test::Unit::TestCase do + define_method :teardown do + super() + call_order << :teardown + end + + define_method :after_teardown do + call_order << :after_teardown + end + + def test_omg; assert true; end + end + + with_output do + @tu.run %w[--seed 42] + end + + expected = [:teardown, :after_teardown] + assert_equal expected, call_order + end + + def test_all_teardowns_are_guaranteed_to_run + pend "Surpressing the raise message when running with tests" + + call_order = [] + Class.new Test::Unit::TestCase do + define_method :after_teardown do + super() + call_order << :after_teardown + raise + end + + define_method :teardown do + super() + call_order << :teardown + raise + end + + define_method :before_teardown do + super() + call_order << :before_teardown + raise + end + + def test_omg; assert true; end + end + + with_output do + @tu.run %w[--seed 42] + end + + expected = [:before_teardown, :teardown, :after_teardown] + assert_equal expected, call_order + end + + def test_setup_and_teardown_survive_inheritance + pend "Surpressing the result message of this tests" + + call_order = [] + + parent = Class.new Test::Unit::TestCase do + define_method :setup do + call_order << :setup_method + end + + define_method :teardown do + call_order << :teardown_method + end + + define_method :test_something do + call_order << :test + end + end + + _ = Class.new parent + + with_output do + @tu.run %w[--seed 42] + end + + # Once for the parent class, once for the child + expected = [:setup_method, :test, :teardown_method] * 2 + + assert_equal expected, call_order + end +end + +class TestMiniTestUnitTestCase < Test::Unit::TestCase + # do not call parallelize_me! - teardown accesses @tc._assertions + # which is not threadsafe. Nearly every method in here is an + # assertion test so it isn't worth splitting it out further. + + def setup + super + + Test::Unit::TestCase.reset + + @tc = Test::Unit::TestCase.new 'fake tc' + @zomg = "zomg ponies!" + @assertion_count = 1 + end + + def teardown + assert_equal(@assertion_count, @tc._assertions, + "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc.passed? + end + + def non_verbose + orig_verbose = $VERBOSE + $VERBOSE = false + + yield + ensure + $VERBOSE = orig_verbose + end + + def test_assert + @assertion_count = 2 + + @tc.assert_equal true, @tc.assert(true), "returns true on success" + end + + def test_assert__triggered + util_assert_triggered "Failed assertion, no message given." do + @tc.assert false + end + end + + def test_assert__triggered_message + util_assert_triggered @zomg do + @tc.assert false, @zomg + end + end + + def test_assert_empty + @assertion_count = 2 + + @tc.assert_empty [] + end + + def test_assert_empty_triggered + @assertion_count = 2 + + util_assert_triggered "Expected [1] to be empty." do + @tc.assert_empty [1] + end + end + + def test_assert_equal + @tc.assert_equal 1, 1 + end + + def test_assert_equal_different_collection_array_hex_invisible + object1 = Object.new + object2 = Object.new + msg = "<[#{object1.inspect}]> expected but was + <[#{object2.inspect}]>.".gsub(/^ +/, "") + util_assert_triggered msg do + @tc.assert_equal [object1], [object2] + end + end + + def test_assert_equal_different_collection_hash_hex_invisible + h1, h2 = {}, {} + h1[1] = Object.new + h2[1] = Object.new + msg = "<#{h1.inspect}> expected but was + <#{h2.inspect}>.".gsub(/^ +/, "") + + util_assert_triggered msg do + @tc.assert_equal h1, h2 + end + end + + def test_assert_equal_different_diff_deactivated + without_diff do + util_assert_triggered util_msg("haha" * 10, "blah" * 10) do + o1 = "haha" * 10 + o2 = "blah" * 10 + + @tc.assert_equal o1, o2 + end + end + end + + def test_assert_equal_different_hex + c = Class.new do + def initialize s; @name = s; end + end + + o1 = c.new "a" + o2 = c.new "b" + msg = "<#{o1.inspect}> expected but was + <#{o2.inspect}>.".gsub(/^ +/, "") + + util_assert_triggered msg do + @tc.assert_equal o1, o2 + end + end + + def test_assert_equal_different_hex_invisible + o1 = Object.new + o2 = Object.new + + msg = "<#{o1.inspect}> expected but was + <#{o2.inspect}>.".gsub(/^ +/, "") + + util_assert_triggered msg do + @tc.assert_equal o1, o2 + end + end + + def test_assert_equal_different_long + msg = "<\"hahahahahahahahahahahahahahahahahahahaha\"> expected but was + <\"blahblahblahblahblahblahblahblahblahblah\">.".gsub(/^ +/, "") + + util_assert_triggered msg do + o1 = "haha" * 10 + o2 = "blah" * 10 + + @tc.assert_equal o1, o2 + end + end + + def test_assert_equal_different_long_invisible + msg = "<\"blahblahblahblahblahblahblahblahblahblah\"> (UTF-8) expected but was + <\"blahblahblahblahblahblahblahblahblahblah\"> (UTF-8).".gsub(/^ +/, "") + + util_assert_triggered msg do + o1 = "blah" * 10 + o2 = "blah" * 10 + def o1.== o + false + end + @tc.assert_equal o1, o2 + end + end + + def test_assert_equal_different_long_msg + msg = "message. + <\"hahahahahahahahahahahahahahahahahahahaha\"> expected but was + <\"blahblahblahblahblahblahblahblahblahblah\">.".gsub(/^ +/, "") + + util_assert_triggered msg do + o1 = "haha" * 10 + o2 = "blah" * 10 + @tc.assert_equal o1, o2, "message" + end + end + + def test_assert_equal_different_short + util_assert_triggered util_msg(1, 2) do + @tc.assert_equal 1, 2 + end + end + + def test_assert_equal_different_short_msg + util_assert_triggered util_msg(1, 2, "message") do + @tc.assert_equal 1, 2, "message" + end + end + + def test_assert_equal_different_short_multiline + msg = "<\"a\\n\" + \"b\"> expected but was\n<\"a\\n\" + \"c\">." + util_assert_triggered msg do + @tc.assert_equal "a\nb", "a\nc" + end + end + + def test_assert_equal_different_escaped_newline + msg = "<\"xxx\\n\" + \"a\\\\nb\"> expected but was\n<\"xxx\\n\" + \"a\\\\nc\">." + util_assert_triggered msg do + @tc.assert_equal "xxx\na\\nb", "xxx\na\\nc" + end + end + + def test_assert_in_delta + @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 + end + + def test_delta_consistency + @tc.assert_in_delta 0, 1, 1 + + util_assert_triggered "Expected |0 - 1| (1) to not be <= 1." do + @tc.refute_in_delta 0, 1, 1 + end + end + + def test_assert_in_delta_triggered + x = "1.0e-06" + util_assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do + @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 + end + end + + def test_assert_in_epsilon + @assertion_count = 10 + + @tc.assert_in_epsilon 10000, 9991 + @tc.assert_in_epsilon 9991, 10000 + @tc.assert_in_epsilon 1.0, 1.001 + @tc.assert_in_epsilon 1.001, 1.0 + + @tc.assert_in_epsilon 10000, 9999.1, 0.0001 + @tc.assert_in_epsilon 9999.1, 10000, 0.0001 + @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 + @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 + + @tc.assert_in_epsilon(-1, -1) + @tc.assert_in_epsilon(-10000, -9991) + end + + def test_epsilon_consistency + @tc.assert_in_epsilon 1.0, 1.001 + + msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001." + util_assert_triggered msg do + @tc.refute_in_epsilon 1.0, 1.001 + end + end + + def test_assert_in_epsilon_triggered + util_assert_triggered 'Expected |10000 - 9990| (10) to be <= 9.99.' do + @tc.assert_in_epsilon 10000, 9990 + end + end + + def test_assert_in_epsilon_triggered_negative_case + x = "0.100000xxx" + y = "0.1" + util_assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do + @tc.assert_in_epsilon(-1.1, -1, 0.1) + end + end + + def test_assert_includes + @assertion_count = 2 + + @tc.assert_includes [true], true + end + + def test_assert_includes_triggered + @assertion_count = 3 + + e = @tc.assert_raise Test::Unit::AssertionFailedError do + @tc.assert_includes [true], false + end + + expected = "Expected [true] to include false." + assert_equal expected, e.message + end + + def test_assert_instance_of + @tc.assert_instance_of String, "blah" + end + + def test_assert_instance_of_triggered + util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do + @tc.assert_instance_of Array, "blah" + end + end + + def test_assert_kind_of + @tc.assert_kind_of String, "blah" + end + + def test_assert_kind_of_triggered + util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do + @tc.assert_kind_of Array, "blah" + end + end + + def test_assert_match + @assertion_count = 2 + @tc.assert_match(/\w+/, "blah blah blah") + end + + def test_assert_match_matcher_object + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) true end + + @tc.assert_match pattern, 5 + end + + def test_assert_match_matchee_to_str + @assertion_count = 2 + + obj = Object.new + def obj.to_str; "blah" end + + @tc.assert_match "blah", obj + end + + def test_assert_match_object_triggered + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) false end + def pattern.inspect; "[Object]" end + + util_assert_triggered 'Expected [Object] to match 5.' do + @tc.assert_match pattern, 5 + end + end + + def test_assert_match_triggered + @assertion_count = 2 + util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do + @tc.assert_match(/\d+/, "blah blah blah") + end + end + + def test_assert_nil + @tc.assert_nil nil + end + + def test_assert_nil_triggered + util_assert_triggered 'Expected 42 to be nil.' do + @tc.assert_nil 42 + end + end + + def test_assert_operator + @tc.assert_operator 2, :>, 1 + end + + def test_assert_operator_bad_object + bad = Object.new + def bad.==(other) true end + + @tc.assert_operator bad, :equal?, bad + end + + def test_assert_operator_triggered + util_assert_triggered "Expected 2 to be < 1." do + @tc.assert_operator 2, :<, 1 + end + end + + def test_assert_output_both + @assertion_count = 2 + + @tc.assert_output "yay", "blah" do + print "yay" + $stderr.print "blah" + end + end + + def test_assert_output_both_regexps + @assertion_count = 4 + + @tc.assert_output(/y.y/, /bl.h/) do + print "yay" + $stderr.print "blah" + end + end + + def test_assert_output_err + @tc.assert_output nil, "blah" do + $stderr.print "blah" + end + end + + def test_assert_output_neither + @assertion_count = 0 + + @tc.assert_output do + # do nothing + end + end + + def test_assert_output_out + @tc.assert_output "blah" do + print "blah" + end + end + + def test_assert_output_triggered_both + util_assert_triggered util_msg("blah", "blah blah", "In stderr") do + @tc.assert_output "yay", "blah" do + print "boo" + $stderr.print "blah blah" + end + end + end + + def test_assert_output_triggered_err + util_assert_triggered util_msg("blah", "blah blah", "In stderr") do + @tc.assert_output nil, "blah" do + $stderr.print "blah blah" + end + end + end + + def test_assert_output_triggered_out + util_assert_triggered util_msg("blah", "blah blah", "In stdout") do + @tc.assert_output "blah" do + print "blah blah" + end + end + end + + def test_assert_predicate + @tc.assert_predicate "", :empty? + end + + def test_assert_predicate_triggered + util_assert_triggered 'Expected "blah" to be empty?.' do + @tc.assert_predicate "blah", :empty? + end + end + + def test_assert_raise + @tc.assert_raise RuntimeError do + raise "blah" + end + end + + def test_assert_raise_module + @tc.assert_raise MyModule do + raise AnError + end + end + + ## + # *sigh* This is quite an odd scenario, but it is from real (albeit + # ugly) test code in ruby-core: + # + # https://github.com/ruby/ruby/commit/6bab4ea9917dc05cd2c94aead2e96eb7df7d4be1 + + def test_assert_raise_skip + @assertion_count = 0 + + util_assert_triggered "skipped", Test::Unit::PendedError do + @tc.assert_raise ArgumentError do + begin + raise "blah" + rescue + skip "skipped" + end + end + end + end + + def test_assert_raise_triggered_different + e = assert_raise Test::Unit::AssertionFailedError do + @tc.assert_raise RuntimeError do + raise SyntaxError, "icky" + end + end + + expected = clean <<-EOM.chomp + [RuntimeError] exception expected, not #. + EOM + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' + + assert_equal expected, actual + end + + def test_assert_raise_triggered_different_msg + e = assert_raise Test::Unit::AssertionFailedError do + @tc.assert_raise RuntimeError, "XXX" do + raise SyntaxError, "icky" + end + end + + expected = clean <<-EOM + XXX. + [RuntimeError] exception expected, not #. + EOM + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' + + assert_equal expected.chomp, actual + end + + def test_assert_raise_triggered_none + e = assert_raise Test::Unit::AssertionFailedError do + @tc.assert_raise Test::Unit::AssertionFailedError do + # do nothing + end + end + + expected = "Test::Unit::AssertionFailedError expected but nothing was raised." + + assert_equal expected, e.message + end + + def test_assert_raise_triggered_none_msg + e = assert_raise Test::Unit::AssertionFailedError do + @tc.assert_raise Test::Unit::AssertionFailedError, "XXX" do + # do nothing + end + end + + expected = "XXX.\nTest::Unit::AssertionFailedError expected but nothing was raised." + + assert_equal expected, e.message + end + + def test_assert_raise_triggered_subclass + e = assert_raise Test::Unit::AssertionFailedError do + @tc.assert_raise StandardError do + raise AnError + end + end + + expected = clean <<-EOM.chomp + [StandardError] exception expected, not #. + EOM + + actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE') + actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0' + + assert_equal expected, actual + end + + def test_assert_respond_to + @tc.assert_respond_to "blah", :empty? + end + + def test_assert_respond_to_triggered + util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do + @tc.assert_respond_to "blah", :rawr! + end + end + + def test_assert_same + @assertion_count = 3 + + o = "blah" + @tc.assert_same 1, 1 + @tc.assert_same :blah, :blah + @tc.assert_same o, o + end + + def test_assert_same_triggered + @assertion_count = 2 + + util_assert_triggered 'Expected 2 (oid=N) to be the same as 1 (oid=N).' do + @tc.assert_same 1, 2 + end + + s1 = "blah" + s2 = "blah" + + util_assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do + @tc.assert_same s1, s2 + end + end + + def test_assert_send + @tc.assert_send [1, :<, 2] + end + + def test_assert_send_bad + util_assert_triggered "Expected 1.>(2) to return true." do + @tc.assert_send [1, :>, 2] + end + end + + def test_assert_silent + @assertion_count = 2 + + @tc.assert_silent do + # do nothing + end + end + + def test_assert_silent_triggered_err + util_assert_triggered util_msg("", "blah blah", "In stderr") do + @tc.assert_silent do + $stderr.print "blah blah" + end + end + end + + def test_assert_silent_triggered_out + @assertion_count = 2 + + util_assert_triggered util_msg("", "blah blah", "In stdout") do + @tc.assert_silent do + print "blah blah" + end + end + end + + def test_assert_throws + @tc.assert_throws :blah do + throw :blah + end + end + + def test_assert_throws_different + util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do + @tc.assert_throws :blah do + throw :not_blah + end + end + end + + def test_assert_throws_unthrown + util_assert_triggered 'Expected :blah to have been thrown.' do + @tc.assert_throws :blah do + # do nothing + end + end + end + + def test_capture_output + @assertion_count = 0 + + non_verbose do + out, err = capture_output do + puts 'hi' + $stderr.puts 'bye!' + end + + assert_equal "hi\n", out + assert_equal "bye!\n", err + end + end + + def test_flunk + util_assert_triggered 'Epic Fail!' do + @tc.flunk + end + end + + def test_flunk_message + util_assert_triggered @zomg do + @tc.flunk @zomg + end + end + + def test_message + @assertion_count = 0 + + assert_equal "blah2.", @tc.message { "blah2" }.call + assert_equal "blah2.", @tc.message("") { "blah2" }.call + assert_equal "blah1.\nblah2.", @tc.message(:blah1) { "blah2" }.call + assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call + + message = proc { "blah1" } + assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call + + message = @tc.message { "blah1" } + assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call + end + + def test_message_message + util_assert_triggered "whoops.\n<1> expected but was\n<2>." do + @tc.assert_equal 1, 2, message { "whoops" } + end + end + + def test_message_lambda + util_assert_triggered "whoops.\n<1> expected but was\n<2>." do + @tc.assert_equal 1, 2, lambda { "whoops" } + end + end + + def test_message_deferred + @assertion_count, var = 0, nil + + msg = message { var = "blah" } + + assert_nil var + + msg.call + + assert_equal "blah", var + end + + def test_pass + @tc.pass + end + + def test_prints + printer = Class.new { extend Test::Unit::CoreAssertions } + @tc.assert_equal '"test"', printer.mu_pp(ImmutableString.new 'test') + end + + def test_refute + @assertion_count = 2 + + @tc.assert_equal false, @tc.refute(false), "returns false on success" + end + + def test_refute_empty + @assertion_count = 2 + + @tc.refute_empty [1] + end + + def test_refute_empty_triggered + @assertion_count = 2 + + util_assert_triggered "Expected [] to not be empty." do + @tc.refute_empty [] + end + end + + def test_refute_equal + @tc.refute_equal "blah", "yay" + end + + def test_refute_equal_triggered + util_assert_triggered 'Expected "blah" to not be equal to "blah".' do + @tc.refute_equal "blah", "blah" + end + end + + def test_refute_in_delta + @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 + end + + def test_refute_in_delta_triggered + x = "0.1" + util_assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do + @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1 + end + end + + def test_refute_in_epsilon + @tc.refute_in_epsilon 10000, 9990-1 + end + + def test_refute_in_epsilon_triggered + util_assert_triggered 'Expected |10000 - 9990| (10) to not be <= 10.0.' do + @tc.refute_in_epsilon 10000, 9990 + fail + end + end + + def test_refute_includes + @assertion_count = 2 + + @tc.refute_includes [true], false + end + + def test_refute_includes_triggered + @assertion_count = 3 + + e = @tc.assert_raise Test::Unit::AssertionFailedError do + @tc.refute_includes [true], true + end + + expected = "Expected [true] to not include true." + assert_equal expected, e.message + end + + def test_refute_instance_of + @tc.refute_instance_of Array, "blah" + end + + def test_refute_instance_of_triggered + util_assert_triggered 'Expected "blah" to not be an instance of String.' do + @tc.refute_instance_of String, "blah" + end + end + + def test_refute_kind_of + @tc.refute_kind_of Array, "blah" + end + + def test_refute_kind_of_triggered + util_assert_triggered 'Expected "blah" to not be a kind of String.' do + @tc.refute_kind_of String, "blah" + end + end + + def test_refute_match + @assertion_count = 2 + @tc.refute_match(/\d+/, "blah blah blah") + end + + def test_refute_match_matcher_object + @assertion_count = 2 + non_verbose do + obj = Object.new + def obj.=~(other); false; end + @tc.refute_match obj, 5 + end + end + + def test_refute_match_object_triggered + @assertion_count = 2 + + pattern = Object.new + def pattern.=~(other) true end + def pattern.inspect; "[Object]" end + + util_assert_triggered 'Expected [Object] to not match 5.' do + @tc.refute_match pattern, 5 + end + end + + def test_refute_match_triggered + @assertion_count = 2 + util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do + @tc.refute_match(/\w+/, "blah blah blah") + end + end + + def test_refute_nil + @tc.refute_nil 42 + end + + def test_refute_nil_triggered + util_assert_triggered 'Expected nil to not be nil.' do + @tc.refute_nil nil + end + end + + def test_refute_predicate + @tc.refute_predicate "42", :empty? + end + + def test_refute_predicate_triggered + util_assert_triggered 'Expected "" to not be empty?.' do + @tc.refute_predicate "", :empty? + end + end + + def test_refute_operator + @tc.refute_operator 2, :<, 1 + end + + def test_refute_operator_bad_object + bad = Object.new + def bad.==(other) true end + + @tc.refute_operator true, :equal?, bad + end + + def test_refute_operator_triggered + util_assert_triggered "Expected 2 to not be > 1." do + @tc.refute_operator 2, :>, 1 + end + end + + def test_refute_respond_to + @tc.refute_respond_to "blah", :rawr! + end + + def test_refute_respond_to_triggered + util_assert_triggered 'Expected "blah" to not respond to empty?.' do + @tc.refute_respond_to "blah", :empty? + end + end + + def test_refute_same + @tc.refute_same 1, 2 + end + + def test_refute_same_triggered + util_assert_triggered 'Expected 1 (oid=N) to not be the same as 1 (oid=N).' do + @tc.refute_same 1, 1 + end + end + + def test_skip + @assertion_count = 0 + + util_assert_triggered "haha!", Test::Unit::PendedError do + @tc.skip "haha!" + end + end + + def test_test_methods + @assertion_count = 0 + + sample_test_case = Class.new Test::Unit::TestCase do + def test_test1; assert "does not matter" end + def test_test2; assert "does not matter" end + def test_test3; assert "does not matter" end + end + + expected = %i(test_test1 test_test2 test_test3) + assert_equal expected, sample_test_case.test_methods.sort + end + + def assert_triggered expected, klass = Test::Unit::AssertionFailedError + e = assert_raise klass do + yield + end + + msg = e.message.sub(/(---Backtrace---).*/m, '\1') + msg.gsub!(/\(oid=[-0-9]+\)/, '(oid=N)') + msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform + + assert_equal expected, msg + end + alias util_assert_triggered assert_triggered + + def util_msg exp, act, msg = nil + s = "<#{exp.inspect}> expected but was\n<#{act.inspect}>." + s = "#{msg}.\n#{s}" if msg + s + end + + def without_diff + old_diff = Test::Unit::Assertions.diff + Test::Unit::Assertions.diff = nil + + yield + ensure + Test::Unit::Assertions.diff = old_diff + end +end + +class TestMiniTestGuard < Test::Unit::TestCase + def test_mri_eh + assert self.class.mri? "ruby blah" + assert self.mri? "ruby blah" + end + + def test_jruby_eh + assert self.class.jruby? "java" + assert self.jruby? "java" + end + + def test_windows_eh + assert self.class.windows? "mswin" + assert self.windows? "mswin" + end +end + +class TestMiniTestUnitRecording < MetaMetaMetaTestCase + # do not parallelize this suite... it just can't handle it. + + def assert_run_record(*expected, &block) + pend "Test::Unit::Runner#run was changed about recoding feature. We should fix it." + def @tu.record suite, method, assertions, time, error + recording[method] << error + end + + def @tu.recording + @recording ||= Hash.new { |h,k| h[k] = [] } + end + + Test::Unit::Runner.runner = @tu + + Class.new Test::Unit::TestCase, &block + + with_output do + @tu.run + end + + recorded = @tu.recording.fetch("test_method").map(&:class) + + assert_equal expected, recorded + end + + def test_record_passing + assert_run_record NilClass do + def test_method + assert true + end + end + end + + def test_record_failing + assert_run_record Test::Unit::AssertionFailedError do + def test_method + assert false + end + end + end + + def test_record_error + assert_run_record RuntimeError do + def test_method + raise "unhandled exception" + end + end + end + + def test_record_error_teardown + assert_run_record NilClass, RuntimeError do + def test_method + assert true + end + + def teardown + raise "unhandled exception" + end + end + end + + def test_record_error_in_test_and_teardown + assert_run_record AnError, RuntimeError do + def test_method + raise AnError + end + + def teardown + raise "unhandled exception" + end + end + end + + def test_record_skip + assert_run_record Test::Unit::PendedError do + def test_method + skip "not yet" + end + end + end +end diff --git a/ruby/tool/test/testunit/test_parallel.rb b/ruby/tool/test/testunit/test_parallel.rb index d5f7cf448..006354aee 100644 --- a/ruby/tool/test/testunit/test_parallel.rb +++ b/ruby/tool/test/testunit/test_parallel.rb @@ -3,10 +3,10 @@ require 'timeout' module TestParallel - PARALLEL_RB = "#{File.dirname(__FILE__)}/../../lib/test/unit/parallel.rb" - TESTS = "#{File.dirname(__FILE__)}/tests_for_parallel" + PARALLEL_RB = "#{__dir__}/../../lib/test/unit/parallel.rb" + TESTS = "#{__dir__}/tests_for_parallel" # use large timeout for --jit-wait - TIMEOUT = EnvUtil.apply_timeout_scale(RubyVM::MJIT.enabled? ? 100 : 30) + TIMEOUT = EnvUtil.apply_timeout_scale(defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? ? 100 : 30) class TestParallelWorker < Test::Unit::TestCase def setup @@ -49,6 +49,7 @@ def test_run assert_match(/^ready/,@worker_out.gets) @worker_in.puts "run #{TESTS}/ptest_first.rb test" assert_match(/^okay/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) @@ -61,9 +62,11 @@ def test_run_multiple_testcase_in_one_file assert_match(/^ready/,@worker_out.gets) @worker_in.puts "run #{TESTS}/ptest_second.rb test" assert_match(/^okay/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) @@ -76,15 +79,18 @@ def test_accept_run_command_multiple_times assert_match(/^ready/,@worker_out.gets) @worker_in.puts "run #{TESTS}/ptest_first.rb test" assert_match(/^okay/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) assert_match(/^ready/,@worker_out.gets) @worker_in.puts "run #{TESTS}/ptest_second.rb test" assert_match(/^okay/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) + assert_match(/^start/,@worker_out.gets) assert_match(/^record/,@worker_out.gets) assert_match(/^p/,@worker_out.gets) assert_match(/^done/,@worker_out.gets) @@ -99,7 +105,7 @@ def test_p break if /^p (.+?)$/ =~ buf end assert_not_nil($1, "'p' was not found") - assert_match(/TestA#test_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack("m")[0]) + assert_match(/TestA#test_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack1("m")) end end @@ -111,16 +117,18 @@ def test_done end assert_not_nil($1, "'done' was not found") - result = Marshal.load($1.chomp.unpack("m")[0]) + result = Marshal.load($1.chomp.unpack1("m")) assert_equal(5, result[0]) - assert_equal(17, result[1]) + pend "TODO: result[1] returns 17. We should investigate it" do + assert_equal(12, result[1]) + end assert_kind_of(Array,result[2]) assert_kind_of(Array,result[3]) assert_kind_of(Array,result[4]) assert_kind_of(Array,result[2][1]) - assert_kind_of(MiniTest::Assertion,result[2][0][2]) - assert_kind_of(MiniTest::Skip,result[2][1][2]) - assert_kind_of(MiniTest::Skip,result[2][2][2]) + assert_kind_of(Test::Unit::AssertionFailedError,result[2][0][2]) + assert_kind_of(Test::Unit::PendedError,result[2][1][2]) + assert_kind_of(Test::Unit::PendedError,result[2][2][2]) assert_kind_of(Exception, result[2][3][2]) assert_equal(result[5], "TestE") end @@ -200,5 +208,12 @@ def test_separate assert(buf.scan(/^\[\s*\d+\/\d+\]\s*(\d+?)=/).flatten.uniq.size > 1, message("retried tests should run in different processes") {buf}) end + + def test_hungup + spawn_runner "--worker-timeout=1", "test4test_hungup.rb" + buf = Timeout.timeout(TIMEOUT) {@test_out.read} + assert_match(/^Retrying hung up testcases\.+$/, buf) + assert_match(/^2 tests,.* 0 failures,/, buf) + end end end diff --git a/ruby/tool/test/testunit/test_redefinition.rb b/ruby/tool/test/testunit/test_redefinition.rb index 9129e5548..b4f5cabd4 100644 --- a/ruby/tool/test/testunit/test_redefinition.rb +++ b/ruby/tool/test/testunit/test_redefinition.rb @@ -3,14 +3,9 @@ class TestRedefinition < Test::Unit::TestCase def test_redefinition - assert_match(/^test\/unit warning: method TestForTestRedefinition#test_redefinition is redefined$/, - redefinition) - end - - def redefinition(*args) - IO.popen([*@options[:ruby], "#{File.dirname(__FILE__)}/test4test_redefinition.rb", *args], - err: [:child, :out]) {|f| - f.read - } + message = %r[test/unit: method TestForTestRedefinition#test_redefinition is redefined$] + assert_raise_with_message(Test::Unit::AssertionFailedError, message) do + require_relative("test4test_redefinition.rb") + end end end diff --git a/ruby/tool/test/testunit/test_sorting.rb b/ruby/tool/test/testunit/test_sorting.rb index f9de3ec15..7678249ec 100644 --- a/ruby/tool/test/testunit/test_sorting.rb +++ b/ruby/tool/test/testunit/test_sorting.rb @@ -15,4 +15,61 @@ def sorting(*args) f.read } end + + Item = Struct.new(:name) + SEED = 0x50975eed + + def make_test_list + (1..16).map {"test_%.3x" % rand(0x1000)}.freeze + end + + def test_sort_alpha + sorter = Test::Unit::Order::Types[:alpha].new(SEED) + assert_kind_of(Test::Unit::Order::Types[:sorted], sorter) + + list = make_test_list + sorted = list.sort + 16.times do + assert_equal(sorted, sorter.sort_by_string(list)) + end + + list = list.map {|s| Item.new(s)}.freeze + sorted = list.sort_by(&:name) + 16.times do + assert_equal(sorted, sorter.sort_by_name(list)) + end + end + + def test_sort_nosort + sorter = Test::Unit::Order::Types[:nosort].new(SEED) + + list = make_test_list + 16.times do + assert_equal(list, sorter.sort_by_string(list)) + end + + list = list.map {|s| Item.new(s)}.freeze + 16.times do + assert_equal(list, sorter.sort_by_name(list)) + end + end + + def test_sort_random + type = Test::Unit::Order::Types[:random] + sorter = type.new(SEED) + + list = make_test_list + sorted = type.new(SEED).sort_by_string(list).freeze + 16.times do + assert_equal(sorted, sorter.sort_by_string(list)) + end + assert_not_equal(sorted, type.new(SEED+1).sort_by_string(list)) + + list = list.map {|s| Item.new(s)}.freeze + sorted = sorted.map {|s| Item.new(s)}.freeze + 16.times do + assert_equal(sorted, sorter.sort_by_name(list)) + end + assert_not_equal(sorted, type.new(SEED+1).sort_by_name(list)) + end end diff --git a/ruby/tool/test/testunit/tests_for_parallel/test4test_hungup.rb b/ruby/tool/test/testunit/tests_for_parallel/test4test_hungup.rb new file mode 100644 index 000000000..65a75f7c4 --- /dev/null +++ b/ruby/tool/test/testunit/tests_for_parallel/test4test_hungup.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +require_relative '../../../lib/test/unit' + +class TestHung < Test::Unit::TestCase + def test_success_at_worker + assert true + end + + def test_hungup_at_worker + if on_parallel_worker? + sleep 10 + end + assert true + end +end diff --git a/ruby/test/webrick/.htaccess b/ruby/tool/test/webrick/.htaccess similarity index 100% rename from ruby/test/webrick/.htaccess rename to ruby/tool/test/webrick/.htaccess diff --git a/ruby/test/webrick/test_cgi.rb b/ruby/tool/test/webrick/test_cgi.rb similarity index 98% rename from ruby/test/webrick/test_cgi.rb rename to ruby/tool/test/webrick/test_cgi.rb index 764c63f32..7a75cf565 100644 --- a/ruby/test/webrick/test_cgi.rb +++ b/ruby/tool/test/webrick/test_cgi.rb @@ -43,7 +43,7 @@ def test_cgi http.request(req){|res| assert_equal("/path/info", res.body, log.call)} req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar") http.request(req){|res| assert_equal("/???", res.body, log.call)} - unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/ + unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32|java/ # Path info of res.body is passed via ENV. # ENV[] returns different value on Windows depending on locale. req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2") diff --git a/ruby/test/webrick/test_config.rb b/ruby/tool/test/webrick/test_config.rb similarity index 100% rename from ruby/test/webrick/test_config.rb rename to ruby/tool/test/webrick/test_config.rb diff --git a/ruby/test/webrick/test_cookie.rb b/ruby/tool/test/webrick/test_cookie.rb similarity index 100% rename from ruby/test/webrick/test_cookie.rb rename to ruby/tool/test/webrick/test_cookie.rb diff --git a/ruby/test/webrick/test_do_not_reverse_lookup.rb b/ruby/tool/test/webrick/test_do_not_reverse_lookup.rb similarity index 100% rename from ruby/test/webrick/test_do_not_reverse_lookup.rb rename to ruby/tool/test/webrick/test_do_not_reverse_lookup.rb diff --git a/ruby/tool/test/webrick/test_filehandler.rb b/ruby/tool/test/webrick/test_filehandler.rb new file mode 100644 index 000000000..146d8ce79 --- /dev/null +++ b/ruby/tool/test/webrick/test_filehandler.rb @@ -0,0 +1,403 @@ +# frozen_string_literal: false +require "test/unit" +require_relative "utils.rb" +require "webrick" +require "stringio" +require "tmpdir" + +class WEBrick::TestFileHandler < Test::Unit::TestCase + def teardown + WEBrick::Utils::TimeoutHandler.terminate + super + end + + def default_file_handler(filename) + klass = WEBrick::HTTPServlet::DefaultFileHandler + klass.new(WEBrick::Config::HTTP, filename) + end + + def windows? + File.directory?("\\") + end + + def get_res_body(res) + sio = StringIO.new + sio.binmode + res.send_body(sio) + sio.string + end + + def make_range_request(range_spec) + msg = <<-END_OF_REQUEST + GET / HTTP/1.0 + Range: #{range_spec} + + END_OF_REQUEST + return StringIO.new(msg.gsub(/^ {6}/, "")) + end + + def make_range_response(file, range_spec) + req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) + req.parse(make_range_request(range_spec)) + res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP) + size = File.size(file) + handler = default_file_handler(file) + handler.make_partial_content(req, res, file, size) + return res + end + + def test_make_partial_content + filename = __FILE__ + filesize = File.size(filename) + + res = make_range_response(filename, "bytes=#{filesize-100}-") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(100, get_res_body(res).size) + + res = make_range_response(filename, "bytes=-100") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(100, get_res_body(res).size) + + res = make_range_response(filename, "bytes=0-99") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(100, get_res_body(res).size) + + res = make_range_response(filename, "bytes=100-199") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(100, get_res_body(res).size) + + res = make_range_response(filename, "bytes=0-0") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(1, get_res_body(res).size) + + res = make_range_response(filename, "bytes=-1") + assert_match(%r{^text/plain}, res["content-type"]) + assert_equal(1, get_res_body(res).size) + + res = make_range_response(filename, "bytes=0-0, -2") + assert_match(%r{^multipart/byteranges}, res["content-type"]) + body = get_res_body(res) + boundary = /; boundary=(.+)/.match(res['content-type'])[1] + off = filesize - 2 + last = filesize - 1 + + exp = "--#{boundary}\r\n" \ + "Content-Type: text/plain\r\n" \ + "Content-Range: bytes 0-0/#{filesize}\r\n" \ + "\r\n" \ + "#{IO.read(__FILE__, 1)}\r\n" \ + "--#{boundary}\r\n" \ + "Content-Type: text/plain\r\n" \ + "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \ + "\r\n" \ + "#{IO.read(__FILE__, 2, off)}\r\n" \ + "--#{boundary}--\r\n" + assert_equal exp, body + end + + def test_filehandler + config = { :DocumentRoot => File.dirname(__FILE__), } + this_file = File.basename(__FILE__) + filesize = File.size(__FILE__) + this_data = File.binread(__FILE__) + range = nil + bug2593 = '[ruby-dev:40030]' + + TestWEBrick.start_httpserver(config) do |server, addr, port, log| + begin + server[:DocumentRootOptions][:NondisclosureName] = [] + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/") + http.request(req){|res| + assert_equal("200", res.code, log.call) + assert_equal("text/html", res.content_type, log.call) + assert_match(/HREF="#{this_file}"/, res.body, log.call) + } + req = Net::HTTP::Get.new("/#{this_file}") + http.request(req){|res| + assert_equal("200", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_equal(this_data, res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal((filesize-100)..(filesize-1), range, log.call) + assert_equal(this_data[-100..-1], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal((filesize-100)..(filesize-1), range, log.call) + assert_equal(this_data[-100..-1], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal(0..99, range, log.call) + assert_equal(this_data[0..99], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal(100..199, range, log.call) + assert_equal(this_data[100..199], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal(0..0, range, log.call) + assert_equal(this_data[0..0], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("text/plain", res.content_type, log.call) + assert_nothing_raised(bug2593) {range = res.content_range} + assert_equal((filesize-1)..(filesize-1), range, log.call) + assert_equal(this_data[-1, 1], res.body, log.call) + } + + req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2") + http.request(req){|res| + assert_equal("206", res.code, log.call) + assert_equal("multipart/byteranges", res.content_type, log.call) + } + ensure + server[:DocumentRootOptions].delete :NondisclosureName + end + end + end + + def test_non_disclosure_name + config = { :DocumentRoot => File.dirname(__FILE__), } + log_tester = lambda {|log, access_log| + log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } + log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s } + assert_equal([], log) + } + this_file = File.basename(__FILE__) + TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + doc_root_opts = server[:DocumentRootOptions] + doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*) + req = Net::HTTP::Get.new("/") + http.request(req){|res| + assert_equal("200", res.code, log.call) + assert_equal("text/html", res.content_type, log.call) + assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body) + } + req = Net::HTTP::Get.new("/#{this_file}") + http.request(req){|res| + assert_equal("404", res.code, log.call) + } + doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*) + http.request(req){|res| + assert_equal("404", res.code, log.call) + } + end + end + + def test_directory_traversal + return if File.executable?(__FILE__) # skip on strange file system + + config = { :DocumentRoot => File.dirname(__FILE__), } + log_tester = lambda {|log, access_log| + log = log.reject {|s| /ERROR bad URI/ =~ s } + log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } + assert_equal([], log) + } + TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/../../") + http.request(req){|res| assert_equal("400", res.code, log.call) } + req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}") + http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) } + req = Net::HTTP::Get.new("/..%5c..%5cruby.c") + http.request(req){|res| assert_equal("404", res.code, log.call) } + end + end + + def test_unwise_in_path + if windows? + config = { :DocumentRoot => File.dirname(__FILE__), } + TestWEBrick.start_httpserver(config) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/..%5c..") + http.request(req){|res| assert_equal("301", res.code, log.call) } + end + end + end + + def test_short_filename + return if File.executable?(__FILE__) # skip on strange file system + return if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning + + config = { + :CGIInterpreter => TestWEBrick::RubyBin, + :DocumentRoot => File.dirname(__FILE__), + :CGIPathEnv => ENV['PATH'], + } + log_tester = lambda {|log, access_log| + log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } + log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s } + assert_equal([], log) + } + TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + if windows? + root = config[:DocumentRoot].tr("/", "\\") + fname = IO.popen(%W[dir /x #{root}\\webrick_long_filename.cgi], encoding: "binary", &:read) + fname.sub!(/\A.*$^$.*$^$/m, '') + if fname + fname = fname[/\s(w.+?cgi)\s/i, 1] + fname.downcase! + end + else + fname = "webric~1.cgi" + end + req = Net::HTTP::Get.new("/#{fname}/test") + http.request(req) do |res| + if windows? + assert_equal("200", res.code, log.call) + assert_equal("/test", res.body, log.call) + else + assert_equal("404", res.code, log.call) + end + end + + req = Net::HTTP::Get.new("/.htaccess") + http.request(req) {|res| assert_equal("404", res.code, log.call) } + req = Net::HTTP::Get.new("/htacce~1") + http.request(req) {|res| assert_equal("404", res.code, log.call) } + req = Net::HTTP::Get.new("/HTACCE~1") + http.request(req) {|res| assert_equal("404", res.code, log.call) } + end + end + + def test_multibyte_char_in_path + if Encoding.default_external == Encoding.find('US-ASCII') + reset_encoding = true + verb = $VERBOSE + $VERBOSE = false + Encoding.default_external = Encoding.find('UTF-8') + end + + c = "\u00a7" + begin + c = c.encode('filesystem') + rescue EncodingError + c = c.b + end + Dir.mktmpdir(c) do |dir| + basename = "#{c}.txt" + File.write("#{dir}/#{basename}", "test_multibyte_char_in_path") + Dir.mkdir("#{dir}/#{c}") + File.write("#{dir}/#{c}/#{basename}", "nested") + config = { + :DocumentRoot => dir, + :DirectoryIndex => [basename], + } + TestWEBrick.start_httpserver(config) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + path = "/#{basename}" + req = Net::HTTP::Get.new(WEBrick::HTTPUtils::escape(path)) + http.request(req){|res| assert_equal("200", res.code, log.call + "\nFilesystem encoding is #{Encoding.find('filesystem')}") } + path = "/#{c}/#{basename}" + req = Net::HTTP::Get.new(WEBrick::HTTPUtils::escape(path)) + http.request(req){|res| assert_equal("200", res.code, log.call) } + req = Net::HTTP::Get.new('/') + http.request(req){|res| + assert_equal("test_multibyte_char_in_path", res.body, log.call) + } + end + end + ensure + if reset_encoding + Encoding.default_external = Encoding.find('US-ASCII') + $VERBOSE = verb + end + end + + def test_script_disclosure + return if File.executable?(__FILE__) # skip on strange file system + + config = { + :CGIInterpreter => TestWEBrick::RubyBinArray, + :DocumentRoot => File.dirname(__FILE__), + :CGIPathEnv => ENV['PATH'], + :RequestCallback => Proc.new{|req, res| + def req.meta_vars + meta = super + meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR) + meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV'] + return meta + end + }, + } + log_tester = lambda {|log, access_log| + log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } + assert_equal([], log) + } + TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + http.read_timeout = EnvUtil.apply_timeout_scale(60) + http.write_timeout = EnvUtil.apply_timeout_scale(60) if http.respond_to?(:write_timeout=) + + req = Net::HTTP::Get.new("/webrick.cgi/test") + http.request(req) do |res| + assert_equal("200", res.code, log.call) + assert_equal("/test", res.body, log.call) + end + + resok = windows? + response_assertion = Proc.new do |res| + if resok + assert_equal("200", res.code, log.call) + assert_equal("/test", res.body, log.call) + else + assert_equal("404", res.code, log.call) + end + end + req = Net::HTTP::Get.new("/webrick.cgi%20/test") + http.request(req, &response_assertion) + req = Net::HTTP::Get.new("/webrick.cgi./test") + http.request(req, &response_assertion) + resok &&= File.exist?(__FILE__+"::$DATA") + req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test") + http.request(req, &response_assertion) + end + end + + def test_erbhandler + config = { :DocumentRoot => File.dirname(__FILE__) } + log_tester = lambda {|log, access_log| + log = log.reject {|s| /ERROR `.*\' not found\./ =~ s } + assert_equal([], log) + } + TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log| + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/webrick.rhtml") + http.request(req) do |res| + assert_equal("200", res.code, log.call) + assert_match %r!\Areq to http://[^/]+/webrick\.rhtml {}\n!, res.body + end + end + end +end diff --git a/ruby/test/webrick/test_htgroup.rb b/ruby/tool/test/webrick/test_htgroup.rb similarity index 100% rename from ruby/test/webrick/test_htgroup.rb rename to ruby/tool/test/webrick/test_htgroup.rb diff --git a/ruby/test/webrick/test_htmlutils.rb b/ruby/tool/test/webrick/test_htmlutils.rb similarity index 100% rename from ruby/test/webrick/test_htmlutils.rb rename to ruby/tool/test/webrick/test_htmlutils.rb diff --git a/ruby/test/webrick/test_httpauth.rb b/ruby/tool/test/webrick/test_httpauth.rb similarity index 100% rename from ruby/test/webrick/test_httpauth.rb rename to ruby/tool/test/webrick/test_httpauth.rb diff --git a/ruby/test/webrick/test_httpproxy.rb b/ruby/tool/test/webrick/test_httpproxy.rb similarity index 99% rename from ruby/test/webrick/test_httpproxy.rb rename to ruby/tool/test/webrick/test_httpproxy.rb index 8149d7830..66dae6f6f 100644 --- a/ruby/test/webrick/test_httpproxy.rb +++ b/ruby/tool/test/webrick/test_httpproxy.rb @@ -213,7 +213,7 @@ def test_big_bodies end end end - end + end if RUBY_VERSION >= '2.5' def test_http10_proxy_chunked # Testing HTTP/1.0 client request and HTTP/1.1 chunked response @@ -323,6 +323,7 @@ def test_connect end if defined?(OpenSSL::SSL) def test_upstream_proxy + return if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning # Testing GET or POST through the upstream proxy server # Note that the upstream proxy server works as the origin server. # +------+ diff --git a/ruby/test/webrick/test_httprequest.rb b/ruby/tool/test/webrick/test_httprequest.rb similarity index 97% rename from ruby/test/webrick/test_httprequest.rb rename to ruby/tool/test/webrick/test_httprequest.rb index a594f14f7..759ccbdad 100644 --- a/ruby/test/webrick/test_httprequest.rb +++ b/ruby/tool/test/webrick/test_httprequest.rb @@ -425,6 +425,18 @@ def test_continue_not_sent assert_equal l, msg.size end + def test_empty_post + msg = <<-_end_of_message_ + POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1 + Host: test.ruby-lang.org:8080 + Content-Type: application/x-www-form-urlencoded + + _end_of_message_ + req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) + req.parse(StringIO.new(msg.gsub(/^ {6}/, ""))) + req.body + end + def test_bad_messages param = "foo=1;foo=2;foo=3;bar=x" msg = <<-_end_of_message_ diff --git a/ruby/test/webrick/test_httpresponse.rb b/ruby/tool/test/webrick/test_httpresponse.rb similarity index 85% rename from ruby/test/webrick/test_httpresponse.rb rename to ruby/tool/test/webrick/test_httpresponse.rb index e8c69a121..4410f63e8 100644 --- a/ruby/test/webrick/test_httpresponse.rb +++ b/ruby/tool/test/webrick/test_httpresponse.rb @@ -1,11 +1,11 @@ # frozen_string_literal: false require "webrick" -require "minitest/autorun" +require "test/unit" require "stringio" require "net/http" module WEBrick - class TestHTTPResponse < MiniTest::Unit::TestCase + class TestHTTPResponse < Test::Unit::TestCase class FakeLogger attr_reader :messages @@ -30,78 +30,78 @@ def setup end def test_prevent_response_splitting_headers_crlf - res['X-header'] = "malicious\r\nCookie: hack" + res['X-header'] = "malicious\r\nCookie: cracked_indicator_for_test" io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_prevent_response_splitting_cookie_headers_crlf - user_input = "malicious\r\nCookie: hack" + user_input = "malicious\r\nCookie: cracked_indicator_for_test" res.cookies << WEBrick::Cookie.new('author', user_input) io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_prevent_response_splitting_headers_cr - res['X-header'] = "malicious\rCookie: hack" + res['X-header'] = "malicious\rCookie: cracked_indicator_for_test" io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_prevent_response_splitting_cookie_headers_cr - user_input = "malicious\rCookie: hack" + user_input = "malicious\rCookie: cracked_indicator_for_test" res.cookies << WEBrick::Cookie.new('author', user_input) io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_prevent_response_splitting_headers_lf - res['X-header'] = "malicious\nCookie: hack" + res['X-header'] = "malicious\nCookie: cracked_indicator_for_test" io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_prevent_response_splitting_cookie_headers_lf - user_input = "malicious\nCookie: hack" + user_input = "malicious\nCookie: cracked_indicator_for_test" res.cookies << WEBrick::Cookie.new('author', user_input) io = StringIO.new res.send_response io io.rewind res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) assert_equal '500', res.code - refute_match 'hack', io.string + refute_match 'cracked_indicator_for_test', io.string end def test_set_redirect_response_splitting - url = "malicious\r\nCookie: hack" - assert_raises(URI::InvalidURIError) do + url = "malicious\r\nCookie: cracked_indicator_for_test" + assert_raise(URI::InvalidURIError) do res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url) end end def test_set_redirect_html_injection url = 'http://example.com////?a' - assert_raises(WEBrick::HTTPStatus::MultipleChoices) do + assert_raise(WEBrick::HTTPStatus::MultipleChoices) do res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url) end res.status = 300 diff --git a/ruby/test/webrick/test_https.rb b/ruby/tool/test/webrick/test_https.rb similarity index 100% rename from ruby/test/webrick/test_https.rb rename to ruby/tool/test/webrick/test_https.rb diff --git a/ruby/test/webrick/test_httpserver.rb b/ruby/tool/test/webrick/test_httpserver.rb similarity index 99% rename from ruby/test/webrick/test_httpserver.rb rename to ruby/tool/test/webrick/test_httpserver.rb index 2e5d44940..4133be85a 100644 --- a/ruby/test/webrick/test_httpserver.rb +++ b/ruby/tool/test/webrick/test_httpserver.rb @@ -484,7 +484,7 @@ def test_gigantic_request_header TCPSocket.open(addr, port) do |c| c.write("GET / HTTP/1.0\r\n") junk = -"X-Junk: #{' ' * 1024}\r\n" - assert_raise(Errno::ECONNRESET, Errno::EPIPE) do + assert_raise(Errno::ECONNRESET, Errno::EPIPE, Errno::EPROTOTYPE) do loop { c.write(junk) } end end diff --git a/ruby/test/webrick/test_httpstatus.rb b/ruby/tool/test/webrick/test_httpstatus.rb similarity index 100% rename from ruby/test/webrick/test_httpstatus.rb rename to ruby/tool/test/webrick/test_httpstatus.rb diff --git a/ruby/test/webrick/test_httputils.rb b/ruby/tool/test/webrick/test_httputils.rb similarity index 100% rename from ruby/test/webrick/test_httputils.rb rename to ruby/tool/test/webrick/test_httputils.rb diff --git a/ruby/test/webrick/test_httpversion.rb b/ruby/tool/test/webrick/test_httpversion.rb similarity index 100% rename from ruby/test/webrick/test_httpversion.rb rename to ruby/tool/test/webrick/test_httpversion.rb diff --git a/ruby/test/webrick/test_server.rb b/ruby/tool/test/webrick/test_server.rb similarity index 84% rename from ruby/test/webrick/test_server.rb rename to ruby/tool/test/webrick/test_server.rb index 8162a186d..815cc3ce3 100644 --- a/ruby/test/webrick/test_server.rb +++ b/ruby/tool/test/webrick/test_server.rb @@ -160,4 +160,32 @@ def <<(msg) assert_join_threads([client_thread, server_thread]) } end + + def test_port_numbers + config = { + :BindAddress => '0.0.0.0', + :Logger => WEBrick::Log.new([], WEBrick::BasicLog::WARN), + } + + ports = [0, "0"] + + ports.each do |port| + config[:Port]= port + server = WEBrick::GenericServer.new(config) + server_thread = Thread.start { server.start } + client_thread = Thread.start { + sleep 0.1 until server.status == :Running || !server_thread.status + server_port = server.listeners[0].addr[1] + server.stop + assert_equal server.config[:Port], server_port + sleep 0.1 until server.status == :Stop || !server_thread.status + } + assert_join_threads([client_thread, server_thread]) + end + + assert_raise(ArgumentError) do + config[:Port]= "FOO" + WEBrick::GenericServer.new(config) + end + end end diff --git a/ruby/test/webrick/test_ssl_server.rb b/ruby/tool/test/webrick/test_ssl_server.rb similarity index 100% rename from ruby/test/webrick/test_ssl_server.rb rename to ruby/tool/test/webrick/test_ssl_server.rb diff --git a/ruby/test/webrick/test_utils.rb b/ruby/tool/test/webrick/test_utils.rb similarity index 100% rename from ruby/test/webrick/test_utils.rb rename to ruby/tool/test/webrick/test_utils.rb diff --git a/ruby/tool/test/webrick/utils.rb b/ruby/tool/test/webrick/utils.rb new file mode 100644 index 000000000..a8568d0a4 --- /dev/null +++ b/ruby/tool/test/webrick/utils.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: false +require "webrick" +begin + require "webrick/https" +rescue LoadError +end +require "webrick/httpproxy" + +module TestWEBrick + NullWriter = Object.new + def NullWriter.<<(msg) + puts msg if $DEBUG + return self + end + + class WEBrick::HTTPServlet::CGIHandler + remove_const :Ruby + require "envutil" unless defined?(EnvUtil) + Ruby = EnvUtil.rubybin + remove_const :CGIRunner + CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc: + remove_const :CGIRunnerArray + CGIRunnerArray = [Ruby, "#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb"] # :nodoc: + end + + RubyBin = "\"#{EnvUtil.rubybin}\"" + RubyBin << " --disable-gems" + RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\"" + RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\"" + RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\"" + + RubyBinArray = [EnvUtil.rubybin] + RubyBinArray << "--disable-gems" + RubyBinArray << "-I" << "#{File.expand_path("../..", File.dirname(__FILE__))}/lib" + RubyBinArray << "-I" << "#{File.dirname(EnvUtil.rubybin)}/.ext/common" + RubyBinArray << "-I" << "#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}" + + require "test/unit" unless defined?(Test::Unit) + include Test::Unit::Assertions + extend Test::Unit::Assertions + include Test::Unit::CoreAssertions + extend Test::Unit::CoreAssertions + + module_function + + DefaultLogTester = lambda {|log, access_log| assert_equal([], log) } + + def start_server(klass, config={}, log_tester=DefaultLogTester, &block) + log_ary = [] + access_log_ary = [] + log = proc { "webrick log start:\n" + (log_ary+access_log_ary).join.gsub(/^/, " ").chomp + "\nwebrick log end" } + config = ({ + :BindAddress => "127.0.0.1", :Port => 0, + :ServerType => Thread, + :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN), + :AccessLog => [[access_log_ary, ""]] + }.update(config)) + server = capture_output {break klass.new(config)} + server_thread = server.start + server_thread2 = Thread.new { + server_thread.join + if log_tester + log_tester.call(log_ary, access_log_ary) + end + } + addr = server.listeners[0].addr + client_thread = Thread.new { + begin + block.yield([server, addr[3], addr[1], log]) + ensure + server.shutdown + end + } + assert_join_threads([client_thread, server_thread2]) + end + + def start_httpserver(config={}, log_tester=DefaultLogTester, &block) + start_server(WEBrick::HTTPServer, config, log_tester, &block) + end + + def start_httpproxy(config={}, log_tester=DefaultLogTester, &block) + start_server(WEBrick::HTTPProxyServer, config, log_tester, &block) + end +end diff --git a/ruby/test/webrick/webrick.cgi b/ruby/tool/test/webrick/webrick.cgi similarity index 100% rename from ruby/test/webrick/webrick.cgi rename to ruby/tool/test/webrick/webrick.cgi diff --git a/ruby/test/webrick/webrick.rhtml b/ruby/tool/test/webrick/webrick.rhtml similarity index 100% rename from ruby/test/webrick/webrick.rhtml rename to ruby/tool/test/webrick/webrick.rhtml diff --git a/ruby/test/webrick/webrick_long_filename.cgi b/ruby/tool/test/webrick/webrick_long_filename.cgi similarity index 100% rename from ruby/test/webrick/webrick_long_filename.cgi rename to ruby/tool/test/webrick/webrick_long_filename.cgi diff --git a/ruby/tool/transcode-tblgen.rb b/ruby/tool/transcode-tblgen.rb index 156b2de19..dba6f33ff 100644 --- a/ruby/tool/transcode-tblgen.rb +++ b/ruby/tool/transcode-tblgen.rb @@ -724,7 +724,7 @@ def citrus_decode_mapsrc(ces, csid, mapsrcs) path = File.join(*path) path << ".src" path[path.rindex('/')] = '%' - STDERR.puts 'load mapsrc %s' % path if VERBOSE_MODE + STDOUT.puts 'load mapsrc %s' % path if VERBOSE_MODE > 1 open(path, 'rb') do |f| f.each_line do |l| break if /^BEGIN_MAP/ =~ l @@ -822,11 +822,11 @@ def transcode_compile_tree(name, from, map, valid_encoding) TRANSCODE_GENERATED_TRANSCODER_CODE = ''.dup def transcode_tbl_only(from, to, map, valid_encoding=UnspecifiedValidEncoding) - if VERBOSE_MODE + if VERBOSE_MODE > 1 if from.empty? || to.empty? - STDERR.puts "converter for #{from.empty? ? to : from}" + STDOUT.puts "converter for #{from.empty? ? to : from}" else - STDERR.puts "converter from #{from} to #{to}" + STDOUT.puts "converter from #{from} to #{to}" end end id_from = from.tr('^0-9A-Za-z', '_') @@ -895,9 +895,9 @@ def transcode_tblgen(from, to, map, valid_encoding=UnspecifiedValidEncoding, #{max_input}, /* max_input */ #{max_output}, /* max_output */ #{ascii_compatibility}, /* asciicompat_type */ - 0, NULL, NULL, /* state_size, state_init, state_fini */ - NULL, NULL, NULL, NULL, - NULL, NULL, NULL + 0, 0, 0, /* state_size, state_init, state_fini */ + 0, 0, 0, 0, + 0, 0, 0 }; End TRANSCODE_GENERATED_TRANSCODER_CODE << transcoder_code @@ -905,7 +905,7 @@ def transcode_tblgen(from, to, map, valid_encoding=UnspecifiedValidEncoding, end def transcode_generate_node(am, name_hint=nil) - STDERR.puts "converter for #{name_hint}" if VERBOSE_MODE + STDOUT.puts "converter for #{name_hint}" if VERBOSE_MODE > 1 am.gennode(TRANSCODE_GENERATED_BYTES_CODE, TRANSCODE_GENERATED_WORDS_CODE, name_hint) '' end @@ -1018,12 +1018,12 @@ def make_signature(filename, src) start_time = Time.now output_filename = nil - verbose_mode = false + verbose_mode = 0 force_mode = false op = OptionParser.new op.def_option("--help", "show help message") { puts op; exit 0 } - op.def_option("--verbose", "verbose mode") { verbose_mode = true } + op.def_option("--verbose", "verbose mode, twice for more verbose") { verbose_mode += 1 } op.def_option("--force", "force table generation") { force_mode = true } op.def_option("--output=FILE", "specify output file") {|arg| output_filename = arg } op.parse! @@ -1066,14 +1066,14 @@ def make_signature(filename, src) if old_signature == chk_signature now = Time.now File.utime(now, now, output_filename) - STDERR.puts "already up-to-date: #{output_filename}" if VERBOSE_MODE + STDOUT.puts "already up-to-date: #{output_filename}" if VERBOSE_MODE > 0 exit end end - if VERBOSE_MODE + if VERBOSE_MODE > 0 if output_filename - STDERR.puts "generating #{output_filename} ..." + STDOUT.puts "generating #{output_filename} ..." end end @@ -1111,7 +1111,7 @@ def make_signature(filename, src) File.rename(new_filename, output_filename) tms = Process.times elapsed = Time.now - start_time - STDERR.puts "done. (#{'%.2f' % tms.utime}user #{'%.2f' % tms.stime}system #{'%.2f' % elapsed}elapsed)" if VERBOSE_MODE + STDOUT.puts "done. (#{'%.2f' % tms.utime}user #{'%.2f' % tms.stime}system #{'%.2f' % elapsed}elapsed)" if VERBOSE_MODE > 1 else print result end diff --git a/ruby/tool/transform_mjit_header.rb b/ruby/tool/transform_mjit_header.rb index 5f89446c8..2359ceab7 100644 --- a/ruby/tool/transform_mjit_header.rb +++ b/ruby/tool/transform_mjit_header.rb @@ -27,7 +27,9 @@ module MJITHeader # These macros are relied on this script's transformation PREFIXED_MACROS = [ 'ALWAYS_INLINE', + 'COLDFUNC', 'inline', + 'RBIMPL_ATTR_COLD', ] # For MinGW's ras.h. Those macros have its name in its definition and can't be preprocessed multiple times. @@ -60,9 +62,15 @@ module MJITHeader 'vm_opt_aref_with', 'vm_opt_aset_with', 'vm_opt_not', - 'vm_getinstancevariable', - 'vm_setinstancevariable', - 'vm_setivar', + ] + + COLD_FUNCTIONS = %w[ + setup_parameters_complex + vm_call_iseq_setup + vm_call_iseq_setup_2 + vm_call_iseq_setup_tailcall + vm_call_method_each_type + vm_ic_update ] # Return start..stop of last decl in CODE ending STOP @@ -105,7 +113,7 @@ def self.decl_name_of(decl) su2_regex = /{([^{}]|#{su1_regex})*}/ su3_regex = /{([^{}]|#{su2_regex})*}/ # 3 nested structs/unions is probably enough reduced_decl.gsub!(su3_regex, '') # remove structs/unions in the header - id_seq_regex = /\s*(#{ident_regex}(\s+|\s*[*]+\s*))*/ + id_seq_regex = /\s*(?:#{ident_regex}(?:\s+|\s*[*]+\s*))*/ # Process function header: match = /\A#{id_seq_regex}(?#{ident_regex})\s*\(/.match(reduced_decl) return match[:name] if match @@ -204,6 +212,10 @@ def self.with_code(code) abort "Usage: #{$0}
      " end +if STDOUT.tty? + require_relative 'lib/colorize' + color = Colorize.new +end cc = ARGV[0] code = File.binread(ARGV[1]) # Current version of the header file. outfile = ARGV[2] @@ -243,10 +255,10 @@ def self.with_code(code) # Check initial file correctness in the manner of final output. MJITHeader.check_code!(code_to_check, cc, cflags, 'initial') -puts "\nTransforming external functions to static:" -stop_pos = -1 -extern_names = [] +stop_pos = -1 +extern_names = [] +transform_logs = Hash.new { |h, k| h[k] = [] } # This loop changes function declarations to static inline. while (decl_range = MJITHeader.find_decl(code, stop_pos)) @@ -255,8 +267,13 @@ def self.with_code(code) decl_name = MJITHeader.decl_name_of(decl) if MJITHeader::IGNORED_FUNCTIONS.include?(decl_name) && /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl) - puts "#{PROGRAM}: changing definition of '#{decl_name}' to declaration" + transform_logs[:def_to_decl] << decl_name code[decl_range] = decl.sub(/{.+}/m, ';') + elsif MJITHeader::COLD_FUNCTIONS.include?(decl_name) && match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl) + header = match[0].sub(/{\z/, '').strip + header = "static #{header.sub(/\A((static|inline) )+/, '')}" + decl[match.begin(0)...match.end(0)] = '{' # remove header + code[decl_range] = "\nCOLDFUNC #{header} #{decl}" elsif MJITHeader::ALWAYS_INLINED_FUNCTIONS.include?(decl_name) && match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl) header = match[0].sub(/{\z/, '').strip header = "static inline #{header.sub(/\A((static|inline) )+/, '')}" @@ -265,13 +282,13 @@ def self.with_code(code) elsif extern_names.include?(decl_name) && (decl =~ /#{MJITHeader::FUNC_HEADER_REGEXP};/) decl.sub!(/(extern|static|inline) /, ' ') unless decl_name =~ /\Aattr_\w+_\w+\z/ # skip too-many false-positive warnings in insns_info.inc. - puts "#{PROGRAM}: making declaration of '#{decl_name}' static inline" + transform_logs[:static_inline_decl] << decl_name end code[decl_range] = "static inline #{decl}" elsif (match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl)) && (header = match[0]) !~ /static/ unless decl_name.match(MJITHeader::TARGET_NAME_REGEXP) - puts "#{PROGRAM}: SKIPPED to transform #{decl_name}" + transform_logs[:skipped] << decl_name next end @@ -279,12 +296,12 @@ def self.with_code(code) decl[match.begin(0)...match.end(0)] = '' if decl =~ /\bstatic\b/ - puts "warning: a static decl inside external definition of '#{decl_name}'" + abort "#{PROGRAM}: a static decl was found inside external definition #{decl_name.dump}" end header.sub!(/(extern|inline) /, ' ') unless decl_name =~ /\Aattr_\w+_\w+\z/ # skip too-many false-positive warnings in insns_info.inc. - puts "#{PROGRAM}: making external definition of '#{decl_name}' static inline" + transform_logs[:static_inline_def] << decl_name end code[decl_range] = "static inline #{header}#{decl}" end @@ -296,3 +313,14 @@ def self.with_code(code) MJITHeader.check_code!(code, cc, cflags, 'final') MJITHeader.write(code, outfile) + +messages = { + def_to_decl: 'changing definition to declaration', + static_inline_def: 'making external definition static inline', + static_inline_decl: 'making declaration static inline', + skipped: 'SKIPPED to transform', +} +transform_logs.each do |key, decl_names| + decl_names = decl_names.map { |s| color.bold(s) } if color + puts("#{PROGRAM}: #{messages.fetch(key)}: #{decl_names.join(', ')}") +end diff --git a/ruby/tool/travis_wait.sh b/ruby/tool/travis_wait.sh new file mode 100755 index 000000000..471b765df --- /dev/null +++ b/ruby/tool/travis_wait.sh @@ -0,0 +1,18 @@ +#!/bin/bash -eu +# The modified version of `travis_wait` to output a log as the command goes. +# https://github.com/travis-ci/travis-ci/issues/4190#issuecomment-353342526 + +# Produce an output log every 9 minutes as the timeout without output is 10 +# minutes. A job finishes with a timeout if it takes longer than 50 minutes. +# https://docs.travis-ci.com/user/customizing-the-build#build-timeouts +while sleep 9m; do + # Print message with bash variable SECONDS. + echo "====[ $SECONDS seconds still running ]====" +done & + +echo "+ $@" +"$@" + +jobs +kill %1 +exit 0 diff --git a/ruby/tool/update-bundled_gems.rb b/ruby/tool/update-bundled_gems.rb new file mode 100755 index 000000000..5b9c6b697 --- /dev/null +++ b/ruby/tool/update-bundled_gems.rb @@ -0,0 +1,20 @@ +#!ruby -pla +BEGIN { + require 'rubygems' +} +unless /^[^#]/ !~ (gem = $F[0]) + (gem, src), = Gem::SpecFetcher.fetcher.detect(:latest) {|s| + s.platform == "ruby" && s.name == gem + } + gem = src.fetch_spec(gem) + uri = gem.metadata["source_code_uri"] || gem.homepage + uri = uri.sub(%r[\Ahttps://github\.com/[^/]+/[^/]+\K/tree/.*], "").chomp(".git") + if $F[3] + if $F[3].include?($F[1]) + $F[3][$F[1]] = gem.version.to_s + elsif Gem::Version.new($F[1]) != gem.version and /\A\h+\z/ =~ $F[3] + $F[3..-1] = [] + end + end + $_ = [gem.name, gem.version, uri, *$F[3..-1]].join(" ") +end diff --git a/ruby/tool/update-deps b/ruby/tool/update-deps index 07c14dce6..2348b36e3 100755 --- a/ruby/tool/update-deps +++ b/ruby/tool/update-deps @@ -20,7 +20,7 @@ # Other usages: # * Fix makefiles using previously detected dependency problems # Ex. ruby tool/update-deps --actual-fix [file] -# "ruby tool/update-deps --fix" is same as "ruby tool/update-deps | ruby tool/update-deps --actual-fix". +# "ruby tool/update-deps --fix" is the same as "ruby tool/update-deps | ruby tool/update-deps --actual-fix". require 'optparse' require 'stringio' @@ -262,7 +262,7 @@ end def read_make_deps(cwd) dependencies = {} - make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby ruby-runner golf") + make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby exe/ruby golf") File.open('update-deps.make.out.log', 'w') {|f| f.print make_p } File.open('update-deps.make.err.log', 'w') {|f| f.print make_p_stderr } if !make_p_status.success? @@ -528,7 +528,20 @@ def compare_deps(make_deps, cc_deps, out=$stdout) } end +def prepare_build + unless File.exist?("Makefile") + if File.exist?("autogen.sh") + system("./autogen.sh") + elsif !File.exist?("configure") + system("autoreconf", "-i", "-s") + end + system("./configure", "-q", "--enable-load-relative", "--prefix=/.", + "--disable-install-doc", "debugflags=-save-temps=obj -g") + end +end + def main_show(out=$stdout) + prepare_build make_deps, cc_deps = detect_dependencies(out) compare_deps(make_deps, cc_deps, out) end diff --git a/ruby/tool/ytab.sed b/ruby/tool/ytab.sed index ba7566ac7..95a9b3e1e 100755 --- a/ruby/tool/ytab.sed +++ b/ruby/tool/ytab.sed @@ -14,6 +14,7 @@ a\ } /^yydestruct.*yymsg/,/{/{ /^yydestruct/{ + /,$/N /[, *]p)/!{ H s/^/ruby_parser_&/ diff --git a/ruby/trace_point.rb b/ruby/trace_point.rb index a8c46a0a0..85ebac9aa 100644 --- a/ruby/trace_point.rb +++ b/ruby/trace_point.rb @@ -31,7 +31,7 @@ # # To filter what is traced, you can pass any of the following as +events+: # -# +:line+:: execute code on a new line +# +:line+:: execute an expression or statement on a new line # +:class+:: start a class or module definition # +:end+:: finish a class or module definition # +:call+:: call a Ruby method @@ -41,6 +41,8 @@ # +:raise+:: raise an exception # +:b_call+:: event hook at block entry # +:b_return+:: event hook at block ending +# +:a_call+:: event hook at all calls (+call+, +b_call+, and +c_call+) +# +:a_return+:: event hook at all returns (+return+, +b_return+, and +c_return+) # +:thread_begin+:: event hook at thread beginning # +:thread_end+:: event hook at thread ending # +:fiber_switch+:: event hook at fiber switch @@ -93,7 +95,7 @@ class TracePoint # Access from other threads is also forbidden. # def self.new(*events) - __builtin_tracepoint_new_s(events) + Primitive.tracepoint_new_s(events) end # call-seq: @@ -102,7 +104,7 @@ def self.new(*events) # Return a string containing a human-readable TracePoint # status. def inspect - __builtin_tracepoint_inspect + Primitive.tracepoint_inspect end # call-seq: @@ -115,16 +117,14 @@ def inspect # # This method is only for debugging TracePoint itself. def self.stat - __builtin_tracepoint_stat_s + Primitive.tracepoint_stat_s end - # Document-method: trace - # # call-seq: - # TracePoint.trace(*events) { |obj| block } -> obj + # TracePoint.trace(*events) { |obj| block } -> obj # - # A convenience method for TracePoint.new, that activates the trace - # automatically. + # A convenience method for TracePoint.new, that activates the trace + # automatically. # # trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] } # #=> # @@ -132,7 +132,23 @@ def self.stat # trace.enabled? #=> true # def self.trace(*events) - __builtin_tracepoint_trace_s(events) + Primitive.tracepoint_trace_s(events) + end + + # call-seq: + # TracePoint.allow_reentry + # + # In general, while a TracePoint callback is running, + # other registered callbacks are not called to avoid + # confusion by reentrance. + # This method allows the reentrance in a given block. + # This method should be used carefully, otherwise the callback + # can be easily called infinitely. + # + # If this method is called when the reentrance is already allowed, + # it raises a RuntimeError. + def self.allow_reentry + Primitive.tracepoint_allow_reentry end # call-seq: @@ -183,7 +199,7 @@ def self.trace(*events) # t.enable(target: method(:m1)) # # m1 - # # prints # + # # prints # # m2 # # prints nothing # @@ -193,7 +209,7 @@ def self.trace(*events) # #=> RuntimeError: access from outside # def enable(target: nil, target_line: nil, target_thread: nil) - __builtin_tracepoint_enable_m(target, target_line, target_thread) + Primitive.tracepoint_enable_m(target, target_line, target_thread) end # call-seq: @@ -229,7 +245,7 @@ def enable(target: nil, target_line: nil, target_thread: nil) # trace.disable { p tp.lineno } # #=> RuntimeError: access from outside def disable - __builtin_tracepoint_disable_m + Primitive.tracepoint_disable_m end # call-seq: @@ -237,40 +253,40 @@ def disable # # The current status of the trace def enabled? - __builtin_tracepoint_enabled_p + Primitive.tracepoint_enabled_p end # Type of event # # See TracePoint@Events for more information. def event - __builtin_tracepoint_attr_event + Primitive.tracepoint_attr_event end # Line number of the event def lineno - __builtin_tracepoint_attr_lineno + Primitive.tracepoint_attr_lineno end # Path of the file being run def path - __builtin_tracepoint_attr_path + Primitive.tracepoint_attr_path end # Return the parameters definition of the method or block that the # current hook belongs to. Format is the same as for Method#parameters def parameters - __builtin_tracepoint_attr_parameters + Primitive.tracepoint_attr_parameters end # Return the name at the definition of the method being called def method_id - __builtin_tracepoint_attr_method_id + Primitive.tracepoint_attr_method_id end # Return the called name of the method being called def callee_id - __builtin_tracepoint_attr_callee_id + Primitive.tracepoint_attr_callee_id end # Return class or module of the method being called. @@ -306,36 +322,42 @@ def callee_id # C.foo # end def defined_class - __builtin_tracepoint_attr_defined_class + Primitive.tracepoint_attr_defined_class end - # Return the generated binding object from event + # Return the generated binding object from event. + # + # Note that for +c_call+ and +c_return+ events, the binding returned is the + # binding of the nearest Ruby method calling the C method, since C methods + # themselves do not have bindings. def binding - __builtin_tracepoint_attr_binding + Primitive.tracepoint_attr_binding end # Return the trace object during event # - # Same as TracePoint#binding: - # trace.binding.eval('self') + # Same as the following, except it returns the correct object (the method + # receiver) for +c_call+ and +c_return+ events: + # + # trace.binding.eval('self') def self - __builtin_tracepoint_attr_self + Primitive.tracepoint_attr_self end # Return value from +:return+, +c_return+, and +b_return+ event def return_value - __builtin_tracepoint_attr_return_value + Primitive.tracepoint_attr_return_value end # Value from exception raised on the +:raise+ event def raised_exception - __builtin_tracepoint_attr_raised_exception + Primitive.tracepoint_attr_raised_exception end # Compiled source code (String) on *eval methods on the +:script_compiled+ event. # If loaded from a file, it will return nil. def eval_script - __builtin_tracepoint_attr_eval_script + Primitive.tracepoint_attr_eval_script end # Compiled instruction sequence represented by a RubyVM::InstructionSequence instance @@ -343,6 +365,6 @@ def eval_script # # Note that this method is MRI specific. def instruction_sequence - __builtin_tracepoint_attr_instruction_sequence + Primitive.tracepoint_attr_instruction_sequence end end diff --git a/ruby/trace_point.rbinc b/ruby/trace_point.rbinc index 7e7292930..12389c0d7 100644 --- a/ruby/trace_point.rbinc +++ b/ruby/trace_point.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with trace_point.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_trace_point(void) +void Init_builtin_trace_point(void) { // table definition static const struct rb_builtin_function trace_point_table[] = { diff --git a/ruby/transcode.c b/ruby/transcode.c index 1c9cc01f3..d7011443f 100644 --- a/ruby/transcode.c +++ b/ruby/transcode.c @@ -9,10 +9,19 @@ **********************************************************************/ -#include "ruby/encoding.h" +#include "ruby/internal/config.h" + +#include + #include "internal.h" +#include "internal/array.h" +#include "internal/inits.h" +#include "internal/object.h" +#include "internal/string.h" +#include "internal/transcode.h" +#include "ruby/encoding.h" + #include "transcode_data.h" -#include #include "id.h" #define ENABLE_ECONV_NEWLINE_OPTION 1 @@ -24,6 +33,15 @@ static VALUE rb_eConverterNotFoundError; VALUE rb_cEncodingConverter; +static ID id_destination_encoding; +static ID id_destination_encoding_name; +static ID id_error_bytes; +static ID id_error_char; +static ID id_incomplete_input; +static ID id_readagain_bytes; +static ID id_source_encoding; +static ID id_source_encoding_name; + static VALUE sym_invalid, sym_undef, sym_replace, sym_fallback; static VALUE sym_xml, sym_text, sym_attr; static VALUE sym_universal_newline; @@ -358,6 +376,8 @@ transcode_search_path(const char *sname, const char *dname, return pathlen; /* is -1 if not found */ } +int rb_require_internal_silent(VALUE fname); + static const rb_transcoder * load_transcoder_entry(transcoder_entry_t *entry) { @@ -375,7 +395,7 @@ load_transcoder_entry(transcoder_entry_t *entry) memcpy(path + sizeof(transcoder_lib_prefix) - 1, lib, len); rb_str_set_len(fn, total_len); OBJ_FREEZE(fn); - rb_require_string(fn); + rb_require_internal_silent(fn); } if (entry->transcoder) @@ -2039,7 +2059,6 @@ make_econv_exception(rb_econv_t *ec) size_t readagain_len = ec->last_error.readagain_len; VALUE bytes2 = Qnil; VALUE dumped2; - int idx; if (ec->last_error.result == econv_incomplete_input) { mesg = rb_sprintf("incomplete %s on %s", StringValueCStr(dumped), @@ -2060,20 +2079,10 @@ make_econv_exception(rb_econv_t *ec) } exc = rb_exc_new3(rb_eInvalidByteSequenceError, mesg); - rb_ivar_set(exc, rb_intern("error_bytes"), bytes); - rb_ivar_set(exc, rb_intern("readagain_bytes"), bytes2); - rb_ivar_set(exc, rb_intern("incomplete_input"), ec->last_error.result == econv_incomplete_input ? Qtrue : Qfalse); - - set_encs: - rb_ivar_set(exc, rb_intern("source_encoding_name"), rb_str_new2(ec->last_error.source_encoding)); - rb_ivar_set(exc, rb_intern("destination_encoding_name"), rb_str_new2(ec->last_error.destination_encoding)); - idx = rb_enc_find_index(ec->last_error.source_encoding); - if (0 <= idx) - rb_ivar_set(exc, rb_intern("source_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx))); - idx = rb_enc_find_index(ec->last_error.destination_encoding); - if (0 <= idx) - rb_ivar_set(exc, rb_intern("destination_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx))); - return exc; + rb_ivar_set(exc, id_error_bytes, bytes); + rb_ivar_set(exc, id_readagain_bytes, bytes2); + rb_ivar_set(exc, id_incomplete_input, RBOOL(ec->last_error.result == econv_incomplete_input)); + goto set_encs; } if (ec->last_error.result == econv_undefined_conversion) { VALUE bytes = rb_str_new((const char *)ec->last_error.error_bytes_start, @@ -2093,7 +2102,7 @@ make_econv_exception(rb_econv_t *ec) dumped = rb_sprintf("U+%04X", cc); } } - if (dumped == Qnil) + if (NIL_P(dumped)) dumped = rb_str_dump(bytes); if (strcmp(ec->last_error.source_encoding, ec->source_encoding_name) == 0 && @@ -2121,10 +2130,21 @@ make_econv_exception(rb_econv_t *ec) idx = rb_enc_find_index(ec->last_error.source_encoding); if (0 <= idx) rb_enc_associate_index(bytes, idx); - rb_ivar_set(exc, rb_intern("error_char"), bytes); + rb_ivar_set(exc, id_error_char, bytes); goto set_encs; } return Qnil; + + set_encs: + rb_ivar_set(exc, id_source_encoding_name, rb_str_new2(ec->last_error.source_encoding)); + rb_ivar_set(exc, id_destination_encoding_name, rb_str_new2(ec->last_error.destination_encoding)); + int idx = rb_enc_find_index(ec->last_error.source_encoding); + if (0 <= idx) + rb_ivar_set(exc, id_source_encoding, rb_enc_from_encoding(rb_enc_from_index(idx))); + idx = rb_enc_find_index(ec->last_error.destination_encoding); + if (0 <= idx) + rb_ivar_set(exc, id_destination_encoding, rb_enc_from_encoding(rb_enc_from_index(idx))); + return exc; } static void @@ -2411,6 +2431,7 @@ static int econv_opts(VALUE opt, int ecflags) { VALUE v; + int newlineflag = 0; v = rb_hash_aref(opt, sym_invalid); if (NIL_P(v)) { @@ -2445,7 +2466,7 @@ econv_opts(VALUE opt, int ecflags) else if (v==sym_attr) { ecflags |= ECONV_XML_ATTR_CONTENT_DECORATOR|ECONV_XML_ATTR_QUOTE_DECORATOR|ECONV_UNDEF_HEX_CHARREF; } - else if (RB_TYPE_P(v, T_SYMBOL)) { + else if (SYMBOL_P(v)) { rb_raise(rb_eArgError, "unexpected value for xml option: %"PRIsVALUE, rb_sym2str(v)); } else { @@ -2456,6 +2477,7 @@ econv_opts(VALUE opt, int ecflags) #ifdef ENABLE_ECONV_NEWLINE_OPTION v = rb_hash_aref(opt, sym_newline); if (!NIL_P(v)) { + newlineflag = 2; ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK; if (v == sym_universal) { ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR; @@ -2477,10 +2499,9 @@ econv_opts(VALUE opt, int ecflags) rb_raise(rb_eArgError, "unexpected value for newline option"); } } - else #endif { - int setflags = 0, newlineflag = 0; + int setflags = 0; v = rb_hash_aref(opt, sym_universal_newline); if (RTEST(v)) @@ -2497,9 +2518,15 @@ econv_opts(VALUE opt, int ecflags) setflags |= ECONV_CR_NEWLINE_DECORATOR; newlineflag |= !NIL_P(v); - if (newlineflag) { + switch (newlineflag) { + case 1: ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK; ecflags |= setflags; + break; + + case 3: + rb_warning(":newline option precedes other newline options"); + break; } } @@ -2703,6 +2730,12 @@ str_transcode0(int argc, VALUE *argv, VALUE *self, int ecflags, VALUE ecopts) } } else { + if (senc && denc && !rb_enc_asciicompat(senc) && !rb_enc_asciicompat(denc)) { + rb_encoding *utf8 = rb_utf8_encoding(); + str = rb_str_conv_enc(str, senc, utf8); + senc = utf8; + sname = "UTF-8"; + } if (encoding_equal(sname, dname)) { sname = ""; dname = ""; @@ -2768,14 +2801,14 @@ str_encode_associate(VALUE str, int encidx) /* * call-seq: - * str.encode!(encoding [, options] ) -> str - * str.encode!(dst_encoding, src_encoding [, options] ) -> str + * str.encode!(encoding, **options) -> str + * str.encode!(dst_encoding, src_encoding, **options) -> str * * The first form transcodes the contents of str from * str.encoding to +encoding+. * The second form transcodes the contents of str from * src_encoding to dst_encoding. - * The options Hash gives details for conversion. See String#encode + * The +options+ keyword arguments give details for conversion. See String#encode * for details. * Returns the string even if no changes were made. */ @@ -2804,9 +2837,9 @@ static VALUE encoded_dup(VALUE newstr, VALUE str, int encidx); /* * call-seq: - * str.encode(encoding [, options] ) -> str - * str.encode(dst_encoding, src_encoding [, options] ) -> str - * str.encode([options]) -> str + * str.encode(encoding, **options) -> str + * str.encode(dst_encoding, src_encoding, **options) -> str + * str.encode(**options) -> str * * The first form returns a copy of +str+ transcoded * to encoding +encoding+. @@ -2822,8 +2855,8 @@ static VALUE encoded_dup(VALUE newstr, VALUE str, int encidx); * in the source encoding. The last form by default does not raise * exceptions but uses replacement strings. * - * The +options+ Hash gives details for conversion and can have the following - * keys: + * The +options+ keyword arguments give details for conversion. + * The arguments are: * * :invalid :: * If the value is +:replace+, #encode replaces invalid byte sequences in @@ -2911,7 +2944,7 @@ econv_memsize(const void *ptr) static const rb_data_type_t econv_data_type = { "econv", - {NULL, econv_free, econv_memsize,}, + {0, econv_free, econv_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -3088,7 +3121,7 @@ search_convpath_i(const char *sname, const char *dname, int depth, void *arg) VALUE *ary_p = arg; VALUE v; - if (*ary_p == Qnil) { + if (NIL_P(*ary_p)) { *ary_p = rb_ary_new(); } @@ -3736,7 +3769,11 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self) rb_str_modify(output); if (NIL_P(output_bytesize_v)) { +#if USE_RVARGC + output_bytesize = rb_str_capacity(output); +#else output_bytesize = RSTRING_EMBED_LEN_MAX; +#endif if (!NIL_P(input) && output_bytesize < RSTRING_LEN(input)) output_bytesize = RSTRING_LEN(input); } @@ -3943,7 +3980,7 @@ econv_finish(VALUE self) * ec = Encoding::Converter.new("EUC-JP", "Shift_JIS") * ec.primitive_convert(src="\xff", dst="", nil, 10) * p ec.primitive_errinfo - * #=> [:invalid_byte_sequence, "EUC-JP", "UTF-8", "\xFF", ""] + * #=> [:invalid_byte_sequence, "EUC-JP", "Shift_JIS", "\xFF", ""] * * # HIRAGANA LETTER A (\xa4\xa2 in EUC-JP) is not representable in ISO-8859-1. * # Since this error is occur in UTF-8 to ISO-8859-1 conversion, @@ -4240,7 +4277,7 @@ rb_econv_check_error(rb_econv_t *ec) static VALUE ecerr_source_encoding_name(VALUE self) { - return rb_attr_get(self, rb_intern("source_encoding_name")); + return rb_attr_get(self, id_source_encoding_name); } /* @@ -4266,7 +4303,7 @@ ecerr_source_encoding_name(VALUE self) static VALUE ecerr_source_encoding(VALUE self) { - return rb_attr_get(self, rb_intern("source_encoding")); + return rb_attr_get(self, id_source_encoding); } /* @@ -4278,7 +4315,7 @@ ecerr_source_encoding(VALUE self) static VALUE ecerr_destination_encoding_name(VALUE self) { - return rb_attr_get(self, rb_intern("destination_encoding_name")); + return rb_attr_get(self, id_destination_encoding_name); } /* @@ -4290,7 +4327,7 @@ ecerr_destination_encoding_name(VALUE self) static VALUE ecerr_destination_encoding(VALUE self) { - return rb_attr_get(self, rb_intern("destination_encoding")); + return rb_attr_get(self, id_destination_encoding); } /* @@ -4311,7 +4348,7 @@ ecerr_destination_encoding(VALUE self) static VALUE ecerr_error_char(VALUE self) { - return rb_attr_get(self, rb_intern("error_char")); + return rb_attr_get(self, id_error_char); } /* @@ -4332,7 +4369,7 @@ ecerr_error_char(VALUE self) static VALUE ecerr_error_bytes(VALUE self) { - return rb_attr_get(self, rb_intern("error_bytes")); + return rb_attr_get(self, id_error_bytes); } /* @@ -4344,7 +4381,7 @@ ecerr_error_bytes(VALUE self) static VALUE ecerr_readagain_bytes(VALUE self) { - return rb_attr_get(self, rb_intern("readagain_bytes")); + return rb_attr_get(self, id_readagain_bytes); } /* @@ -4374,7 +4411,7 @@ ecerr_readagain_bytes(VALUE self) static VALUE ecerr_incomplete_input(VALUE self) { - return rb_attr_get(self, rb_intern("incomplete_input")); + return rb_attr_get(self, id_incomplete_input); } /* @@ -4399,38 +4436,46 @@ ecerr_incomplete_input(VALUE self) * correspond with a known converter. */ -#undef rb_intern void Init_transcode(void) { transcoder_table = st_init_strcasetable(); - sym_invalid = ID2SYM(rb_intern("invalid")); - sym_undef = ID2SYM(rb_intern("undef")); - sym_replace = ID2SYM(rb_intern("replace")); - sym_fallback = ID2SYM(rb_intern("fallback")); - sym_xml = ID2SYM(rb_intern("xml")); - sym_text = ID2SYM(rb_intern("text")); - sym_attr = ID2SYM(rb_intern("attr")); - - sym_invalid_byte_sequence = ID2SYM(rb_intern("invalid_byte_sequence")); - sym_undefined_conversion = ID2SYM(rb_intern("undefined_conversion")); - sym_destination_buffer_full = ID2SYM(rb_intern("destination_buffer_full")); - sym_source_buffer_empty = ID2SYM(rb_intern("source_buffer_empty")); - sym_finished = ID2SYM(rb_intern("finished")); - sym_after_output = ID2SYM(rb_intern("after_output")); - sym_incomplete_input = ID2SYM(rb_intern("incomplete_input")); - sym_universal_newline = ID2SYM(rb_intern("universal_newline")); - sym_crlf_newline = ID2SYM(rb_intern("crlf_newline")); - sym_cr_newline = ID2SYM(rb_intern("cr_newline")); - sym_partial_input = ID2SYM(rb_intern("partial_input")); + id_destination_encoding = rb_intern_const("destination_encoding"); + id_destination_encoding_name = rb_intern_const("destination_encoding_name"); + id_error_bytes = rb_intern_const("error_bytes"); + id_error_char = rb_intern_const("error_char"); + id_incomplete_input = rb_intern_const("incomplete_input"); + id_readagain_bytes = rb_intern_const("readagain_bytes"); + id_source_encoding = rb_intern_const("source_encoding"); + id_source_encoding_name = rb_intern_const("source_encoding_name"); + + sym_invalid = ID2SYM(rb_intern_const("invalid")); + sym_undef = ID2SYM(rb_intern_const("undef")); + sym_replace = ID2SYM(rb_intern_const("replace")); + sym_fallback = ID2SYM(rb_intern_const("fallback")); + sym_xml = ID2SYM(rb_intern_const("xml")); + sym_text = ID2SYM(rb_intern_const("text")); + sym_attr = ID2SYM(rb_intern_const("attr")); + + sym_invalid_byte_sequence = ID2SYM(rb_intern_const("invalid_byte_sequence")); + sym_undefined_conversion = ID2SYM(rb_intern_const("undefined_conversion")); + sym_destination_buffer_full = ID2SYM(rb_intern_const("destination_buffer_full")); + sym_source_buffer_empty = ID2SYM(rb_intern_const("source_buffer_empty")); + sym_finished = ID2SYM(rb_intern_const("finished")); + sym_after_output = ID2SYM(rb_intern_const("after_output")); + sym_incomplete_input = ID2SYM(rb_intern_const("incomplete_input")); + sym_universal_newline = ID2SYM(rb_intern_const("universal_newline")); + sym_crlf_newline = ID2SYM(rb_intern_const("crlf_newline")); + sym_cr_newline = ID2SYM(rb_intern_const("cr_newline")); + sym_partial_input = ID2SYM(rb_intern_const("partial_input")); #ifdef ENABLE_ECONV_NEWLINE_OPTION - sym_newline = ID2SYM(rb_intern("newline")); - sym_universal = ID2SYM(rb_intern("universal")); - sym_crlf = ID2SYM(rb_intern("crlf")); - sym_cr = ID2SYM(rb_intern("cr")); - sym_lf = ID2SYM(rb_intern("lf")); + sym_newline = ID2SYM(rb_intern_const("newline")); + sym_universal = ID2SYM(rb_intern_const("universal")); + sym_crlf = ID2SYM(rb_intern_const("crlf")); + sym_cr = ID2SYM(rb_intern_const("cr")); + sym_lf = ID2SYM(rb_intern_const("lf")); #endif InitVM(transcode); @@ -4446,7 +4491,7 @@ InitVM_transcode(void) rb_define_method(rb_cString, "encode", str_encode, -1); rb_define_method(rb_cString, "encode!", str_encode_bang, -1); - rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cData); + rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cObject); rb_define_alloc_func(rb_cEncodingConverter, econv_s_allocate); rb_define_singleton_method(rb_cEncodingConverter, "asciicompat_encoding", econv_s_asciicompat_encoding, 1); rb_define_singleton_method(rb_cEncodingConverter, "search_convpath", econv_s_search_convpath, -1); diff --git a/ruby/transcode_data.h b/ruby/transcode_data.h index 2007eb06d..9455ec93c 100644 --- a/ruby/transcode_data.h +++ b/ruby/transcode_data.h @@ -1,3 +1,5 @@ +#ifndef RUBY_TRANSCODE_DATA_H +#define RUBY_TRANSCODE_DATA_H 1 /********************************************************************** transcode_data.h - @@ -11,9 +13,6 @@ #include "ruby/ruby.h" -#ifndef RUBY_TRANSCODE_DATA_H -#define RUBY_TRANSCODE_DATA_H 1 - RUBY_SYMBOL_EXPORT_BEGIN #define WORDINDEX_SHIFT_BITS 2 diff --git a/ruby/transient_heap.c b/ruby/transient_heap.c index 6e9cf6440..c3df26349 100644 --- a/ruby/transient_heap.c +++ b/ruby/transient_heap.c @@ -6,14 +6,21 @@ **********************************************************************/ -#include "ruby/ruby.h" -#include "ruby/debug.h" -#include "vm_debug.h" +#include "debug_counter.h" #include "gc.h" #include "internal.h" +#include "internal/gc.h" +#include "internal/hash.h" +#include "internal/sanitizers.h" +#include "internal/static_assert.h" +#include "internal/struct.h" +#include "internal/variable.h" +#include "ruby/debug.h" +#include "ruby/ruby.h" #include "ruby_assert.h" #include "transient_heap.h" -#include "debug_counter.h" +#include "vm_debug.h" +#include "vm_sync.h" #if USE_TRANSIENT_HEAP /* USE_TRANSIENT_HEAP */ /* @@ -52,9 +59,12 @@ /* K M */ #define TRANSIENT_HEAP_BLOCK_SIZE (1024 * 32 ) /* 32KB int16_t */ +#ifndef TRANSIENT_HEAP_TOTAL_SIZE #define TRANSIENT_HEAP_TOTAL_SIZE (1024 * 1024 * 32) /* 32 MB */ +#endif #define TRANSIENT_HEAP_ALLOC_MAX (1024 * 2 ) /* 2 KB */ #define TRANSIENT_HEAP_BLOCK_NUM (TRANSIENT_HEAP_TOTAL_SIZE / TRANSIENT_HEAP_BLOCK_SIZE) +#define TRANSIENT_HEAP_USABLE_SIZE (TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header)) #define TRANSIENT_HEAP_ALLOC_MAGIC 0xfeab #define TRANSIENT_HEAP_ALLOC_ALIGN RUBY_ALIGNOF(void *) @@ -70,13 +80,12 @@ enum transient_heap_status { struct transient_heap_block { struct transient_heap_block_header { - int16_t size; /* sizeof(block) = TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header) */ int16_t index; int16_t last_marked_index; int16_t objects; struct transient_heap_block *next_block; } info; - char buff[TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header)]; + char buff[TRANSIENT_HEAP_USABLE_SIZE]; }; struct transient_heap { @@ -147,7 +156,7 @@ transient_heap_dump(struct transient_heap* theap) transient_heap_blocks_dump(theap, theap->free_blocks, "free_blocks"); } -/* Debug: dump all tarnsient_heap blocks */ +/* Debug: dump all transient_heap blocks */ void rb_transient_heap_dump(void) { @@ -233,7 +242,6 @@ static void reset_block(struct transient_heap_block *block) { __msan_allocated_memory(block, sizeof block); - block->info.size = TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header); block->info.index = 0; block->info.objects = 0; block->info.last_marked_index = TRANSIENT_HEAP_ALLOC_MARKING_LAST; @@ -338,9 +346,9 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size) struct transient_heap_block *block = theap->using_blocks; while (block) { - TH_ASSERT(block->info.size >= block->info.index); + TH_ASSERT(block->info.index <= (int16_t)TRANSIENT_HEAP_USABLE_SIZE); - if (block->info.size - block->info.index >= (int32_t)size) { + if (TRANSIENT_HEAP_USABLE_SIZE - block->info.index >= size) { struct transient_alloc_header *header = (void *)&block->buff[block->info.index]; block->info.index += size; block->info.objects++; @@ -358,6 +366,10 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size) void * rb_transient_heap_alloc(VALUE obj, size_t req_size) { + // only on single main ractor + if (ruby_single_main_ractor == NULL) return NULL; + + void *ret; struct transient_heap* theap = transient_heap_get(); size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN); @@ -368,17 +380,17 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size) if (size > TRANSIENT_HEAP_ALLOC_MAX) { if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [too big: %ld] %s\n", (long)size, rb_obj_info(obj)); - return NULL; + ret = NULL; } #if TRANSIENT_HEAP_DEBUG_DONT_PROMOTE == 0 else if (RB_OBJ_PROMOTED_RAW(obj)) { if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [promoted object] %s\n", rb_obj_info(obj)); - return NULL; + ret = NULL; } #else else if (RBASIC_CLASS(obj) == 0) { if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [hidden object] %s\n", rb_obj_info(obj)); - return NULL; + ret = NULL; } #endif else { @@ -412,14 +424,16 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size) /* ptr is set up; OK to unpoison. */ asan_unpoison_memory_region(ptr, size - sizeof *header, true); - return ptr; + ret = ptr; } else { if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [no enough space: %ld] %s\n", (long)size, rb_obj_info(obj)); RB_DEBUG_COUNTER_INC(theap_alloc_fail); - return NULL; + ret = NULL; } } + + return ret; } void @@ -455,7 +469,7 @@ blocks_alloc_header_to_block(struct transient_heap *theap, struct transient_heap struct transient_heap_block *block = blocks; while (block) { - if (block->buff <= (char *)header && (char *)header < block->buff + block->info.size) { + if (block->buff <= (char *)header && (char *)header < block->buff + TRANSIENT_HEAP_USABLE_SIZE) { return block; } block = block->info.next_block; @@ -528,6 +542,8 @@ alloc_header_to_block(struct transient_heap *theap, struct transient_alloc_heade void rb_transient_heap_mark(VALUE obj, const void *ptr) { + ASSERT_vm_locking(); + struct transient_alloc_header *header = ptr_to_alloc_header(ptr); asan_unpoison_memory_region(header, sizeof *header, false); if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header, %s (%p)", rb_obj_info(obj), ptr); @@ -639,6 +655,8 @@ transient_heap_promote_add(struct transient_heap* theap, VALUE obj) void rb_transient_heap_promote(VALUE obj) { + ASSERT_vm_locking(); + if (transient_heap_ptr(obj, FALSE)) { struct transient_heap* theap = transient_heap_get(); transient_heap_promote_add(theap, obj); @@ -657,6 +675,8 @@ alloc_header(struct transient_heap_block* block, int index) static void transient_heap_reset(void) { + ASSERT_vm_locking(); + struct transient_heap* theap = transient_heap_get(); struct transient_heap_block* block; @@ -695,9 +715,10 @@ transient_heap_block_evacuate(struct transient_heap* theap, struct transient_hea while (marked_index >= 0) { struct transient_alloc_header *header = alloc_header(block, marked_index); + asan_unpoison_memory_region(header, sizeof *header, true); VALUE obj = header->obj; TH_ASSERT(header->magic == TRANSIENT_HEAP_ALLOC_MAGIC); - if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header %s\n", rb_obj_info(obj)); + if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("transient_heap_block_evacuate: wrong header %p %s\n", (void *)header, rb_obj_info(obj)); if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, " * transient_heap_block_evacuate %p %s\n", (void *)header, rb_obj_info(obj)); @@ -718,17 +739,35 @@ transient_heap_block_evacuate(struct transient_heap* theap, struct transient_hea rb_hash_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE); break; default: - rb_bug("unsupporeted: %s\n", rb_obj_info(obj)); + rb_bug("unsupported: %s\n", rb_obj_info(obj)); } header->obj = Qundef; /* for debug */ } marked_index = header->next_marked_index; + asan_poison_memory_region(header, sizeof *header); + } +} + +#if defined(USE_RUBY_DEBUG_LOG) && USE_RUBY_DEBUG_LOG +static const char * +transient_heap_status_cstr(enum transient_heap_status status) +{ + switch (status) { + case transient_heap_none: return "none"; + case transient_heap_marking: return "marking"; + case transient_heap_escaping: return "escaping"; } + UNREACHABLE_RETURN(NULL); } +#endif static void transient_heap_update_status(struct transient_heap* theap, enum transient_heap_status status) { + RUBY_DEBUG_LOG("%s -> %s", + transient_heap_status_cstr(theap->status), + transient_heap_status_cstr(status)); + TH_ASSERT(theap->status != status); theap->status = status; } @@ -738,53 +777,66 @@ transient_heap_evacuate(void *dmy) { struct transient_heap* theap = transient_heap_get(); + if (theap->total_marked_objects == 0) return; + if (ruby_single_main_ractor == NULL) rb_bug("not single ractor mode"); if (theap->status == transient_heap_marking) { if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! transient_heap_evacuate: skip while transient_heap_marking\n"); } else { VALUE gc_disabled = rb_gc_disable_no_rest(); - struct transient_heap_block* block; + { + struct transient_heap_block* block; + + RUBY_DEBUG_LOG("start gc_disabled:%d", RTEST(gc_disabled)); - if (TRANSIENT_HEAP_DEBUG >= 1) { - int i; - fprintf(stderr, "!! transient_heap_evacuate start total_blocks:%d\n", theap->total_blocks); - if (TRANSIENT_HEAP_DEBUG >= 4) { - for (i=0; ipromoted_objects_index; i++) fprintf(stderr, "%4d %s\n", i, rb_obj_info(theap->promoted_objects[i])); + if (TRANSIENT_HEAP_DEBUG >= 1) { + int i; + fprintf(stderr, "!! transient_heap_evacuate start total_blocks:%d\n", theap->total_blocks); + if (TRANSIENT_HEAP_DEBUG >= 4) { + for (i=0; ipromoted_objects_index; i++) fprintf(stderr, "%4d %s\n", i, rb_obj_info(theap->promoted_objects[i])); + } } - } - if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap); + if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap); - TH_ASSERT(theap->status == transient_heap_none); - transient_heap_update_status(theap, transient_heap_escaping); + TH_ASSERT(theap->status == transient_heap_none); + transient_heap_update_status(theap, transient_heap_escaping); - /* evacuate from marked blocks */ - block = theap->marked_blocks; - while (block) { - transient_heap_block_evacuate(theap, block); - block = block->info.next_block; - } + /* evacuate from marked blocks */ + block = theap->marked_blocks; + while (block) { + transient_heap_block_evacuate(theap, block); + block = block->info.next_block; + } - /* evacuate from using blocks + /* evacuate from using blocks only affect incremental marking */ - block = theap->using_blocks; - while (block) { - transient_heap_block_evacuate(theap, block); - block = block->info.next_block; - } + block = theap->using_blocks; + while (block) { + transient_heap_block_evacuate(theap, block); + block = block->info.next_block; + } - /* all objects in marked_objects are escaped. */ - transient_heap_reset(); + /* all objects in marked_objects are escaped. */ + transient_heap_reset(); - if (TRANSIENT_HEAP_DEBUG > 0) { - fprintf(stderr, "!! transient_heap_evacuate end total_blocks:%d\n", theap->total_blocks); - } + if (TRANSIENT_HEAP_DEBUG > 0) { + fprintf(stderr, "!! transient_heap_evacuate end total_blocks:%d\n", theap->total_blocks); + } - transient_heap_verify(theap); - transient_heap_update_status(theap, transient_heap_none); + transient_heap_verify(theap); + transient_heap_update_status(theap, transient_heap_none); + } if (gc_disabled != Qtrue) rb_gc_enable(); + RUBY_DEBUG_LOG("finish"); } } +void +rb_transient_heap_evacuate(void) +{ + transient_heap_evacuate(NULL); +} + static void clear_marked_index(struct transient_heap_block* block) { @@ -817,26 +869,17 @@ blocks_clear_marked_index(struct transient_heap_block* block) static void transient_heap_block_update_refs(struct transient_heap* theap, struct transient_heap_block* block) { - int i=0, n=0; + int marked_index = block->info.last_marked_index; - while (iinfo.index) { - void *ptr = &block->buff[i]; - struct transient_alloc_header *header = ptr; + while (marked_index >= 0) { + struct transient_alloc_header *header = alloc_header(block, marked_index); asan_unpoison_memory_region(header, sizeof *header, false); - void *poisoned = __asan_region_is_poisoned((void *)header->obj, SIZEOF_VALUE); - asan_unpoison_object(header->obj, false); - header->obj = rb_gc_location(header->obj); - if (poisoned) { - asan_poison_object(header->obj); - } - - i += header->size; + marked_index = header->next_marked_index; asan_poison_memory_region(header, sizeof *header); - n++; } } @@ -852,6 +895,8 @@ transient_heap_blocks_update_refs(struct transient_heap* theap, struct transient void rb_transient_heap_update_references(void) { + ASSERT_vm_locking(); + struct transient_heap* theap = transient_heap_get(); int i; @@ -867,9 +912,12 @@ rb_transient_heap_update_references(void) void rb_transient_heap_start_marking(int full_marking) { + ASSERT_vm_locking(); + RUBY_DEBUG_LOG("full?:%d", full_marking); + struct transient_heap* theap = transient_heap_get(); - if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_start_marking objects:%d blocks:%d promtoed:%d full_marking:%d\n", + if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_start_marking objects:%d blocks:%d promoted:%d full_marking:%d\n", theap->total_objects, theap->total_blocks, theap->promoted_objects_index, full_marking); if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap); @@ -915,11 +963,14 @@ rb_transient_heap_start_marking(int full_marking) void rb_transient_heap_finish_marking(void) { + ASSERT_vm_locking(); + RUBY_DEBUG_LOG(""); + struct transient_heap* theap = transient_heap_get(); - if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_finish_marking objects:%d, marked:%d\n", - theap->total_objects, - theap->total_marked_objects); + RUBY_DEBUG_LOG("objects:%d, marked:%d", + theap->total_objects, + theap->total_marked_objects); if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap); TH_ASSERT(theap->total_objects >= theap->total_marked_objects); diff --git a/ruby/transient_heap.h b/ruby/transient_heap.h index 7b5c42ca8..4ac52aad0 100644 --- a/ruby/transient_heap.h +++ b/ruby/transient_heap.h @@ -1,3 +1,5 @@ +#ifndef RUBY_TRANSIENT_HEAP_H +#define RUBY_TRANSIENT_HEAP_H /********************************************************************** transient_heap.h - declarations of transient_heap related APIs. @@ -6,9 +8,6 @@ **********************************************************************/ -#ifndef RUBY_TRANSIENT_HEAP_H -#define RUBY_TRANSIENT_HEAP_H - #include "internal.h" #if USE_TRANSIENT_HEAP @@ -32,6 +31,9 @@ void rb_transient_heap_start_marking(int full_marking); void rb_transient_heap_finish_marking(void); void rb_transient_heap_update_references(void); +/* used by ractor.c */ +void rb_transient_heap_evacuate(void); + /* for debug API */ void rb_transient_heap_dump(void); void rb_transient_heap_verify(void); @@ -50,6 +52,7 @@ void rb_struct_transient_heap_evacuate(VALUE st, int promote); #define rb_transient_heap_promote(obj) ((void)0) #define rb_transient_heap_start_marking(full_marking) ((void)0) #define rb_transient_heap_update_references() ((void)0) +#define rb_transient_heap_evacuate() ((void)0) #define rb_transient_heap_finish_marking() ((void)0) #define rb_transient_heap_mark(obj, ptr) ((void)0) diff --git a/ruby/util.c b/ruby/util.c index 1ce7bca8b..1b11ecb3f 100644 --- a/ruby/util.c +++ b/ruby/util.c @@ -10,30 +10,30 @@ **********************************************************************/ #if defined __MINGW32__ || defined __MINGW64__ -#define MINGW_HAS_SECURE_API 1 +# define MINGW_HAS_SECURE_API 1 #endif -#include "internal.h" +#include "ruby/internal/config.h" #include -#include #include -#include #include +#include +#include #ifdef _WIN32 -#include "missing/file.h" +# include "missing/file.h" #endif +#include "internal.h" +#include "internal/sanitizers.h" +#include "internal/util.h" #include "ruby/util.h" +#include "ruby_atomic.h" const char ruby_hexdigits[] = "0123456789abcdef0123456789ABCDEF"; #define hexdigit ruby_hexdigits -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - unsigned long ruby_scan_oct(const char *start, size_t len, size_t *retlen) { @@ -48,7 +48,7 @@ ruby_scan_oct(const char *start, size_t len, size_t *retlen) retval <<= 3; retval |= *s++ - '0'; } - *retlen = (int)(s - start); /* less than len */ + *retlen = (size_t)(s - start); return retval; } @@ -57,22 +57,19 @@ ruby_scan_hex(const char *start, size_t len, size_t *retlen) { register const char *s = start; register unsigned long retval = 0; - const char *tmp; + signed char d; size_t i = 0; for (i = 0; i < len; i++) { - if (! s[0]) { - break; - } - tmp = strchr(hexdigit, *s); - if (! tmp) { + d = ruby_digit36_to_number_table[(unsigned char)*s]; + if (d < 0 || 15 < d) { break; } retval <<= 4; - retval |= (tmp - hexdigit) & 15; + retval |= d; s++; } - *retlen = (int)(s - start); /* less than len */ + *retlen = (size_t)(s - start); return retval; } @@ -100,6 +97,8 @@ NO_SANITIZE("unsigned-integer-overflow", extern unsigned long ruby_scan_digits(c unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow) { + RBIMPL_ASSERT_OR_ASSUME(base >= 2); + RBIMPL_ASSERT_OR_ASSUME(base <= 36); const char *start = str; unsigned long ret = 0, x; @@ -139,6 +138,11 @@ ruby_strtoul(const char *str, char **endptr, int base) unsigned long ret; const char *subject_found = str; + if (base < 0) { + errno = EINVAL; + return 0; + } + if (base == 1 || 36 < base) { errno = EINVAL; return 0; @@ -400,7 +404,8 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void for (;;) { start: if (L + size == R) { /* 2 elements */ - if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt; + if ((*cmp)(L,R,d) > 0) mmswap(L,R); + goto nxt; } l = L; r = R; diff --git a/ruby/variable.c b/ruby/variable.c index 42c4cb7cd..eaad6eb49 100644 --- a/ruby/variable.c +++ b/ruby/variable.c @@ -11,19 +11,38 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/st.h" -#include "ruby/util.h" -#include "internal.h" -#include "id_table.h" +#include "ruby/internal/config.h" +#include +#include "ruby/internal/stdbool.h" +#include "ccan/list/list.h" #include "constant.h" +#include "debug_counter.h" #include "id.h" -#include "ccan/list/list.h" #include "id_table.h" -#include "debug_counter.h" -#include "vm_core.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/compilers.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/re.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 "transient_heap.h" #include "variable.h" +#include "vm_core.h" +#include "ractor_core.h" +#include "vm_sync.h" + +RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state; +#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state) + +typedef void rb_gvar_compact_t(void *var); static struct rb_id_table *rb_global_tbl; static ID autoload, classpath, tmp_classpath; @@ -32,8 +51,7 @@ static VALUE autoload_featuremap; /* feature => autoload_i */ static void check_before_mod_set(VALUE, ID, VALUE, const char *); static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t); static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility); -static st_table *generic_iv_tbl; -static st_table *generic_iv_tbl_compat; +static st_table *generic_iv_tbl_; struct ivar_update { union { @@ -48,7 +66,7 @@ void Init_var_tables(void) { rb_global_tbl = rb_id_table_create(0); - generic_iv_tbl = st_init_numtable(); + generic_iv_tbl_ = st_init_numtable(); autoload = rb_intern_const("__autoload__"); /* __classpath__: fully qualified class path */ classpath = rb_intern_const("__classpath__"); @@ -62,6 +80,7 @@ rb_namespace_p(VALUE obj) if (RB_SPECIAL_CONST_P(obj)) return false; switch (RB_BUILTIN_TYPE(obj)) { case T_MODULE: case T_CLASS: return true; + default: break; } return false; } @@ -161,8 +180,7 @@ rb_class_path(VALUE klass) VALUE rb_class_path_cached(VALUE klass) { - int permanent; - return classname(klass, &permanent); + return rb_mod_name(klass); } static VALUE @@ -184,8 +202,7 @@ build_const_pathname(VALUE head, VALUE tail) VALUE path = rb_str_dup(head); rb_str_cat2(path, "::"); rb_str_append(path, tail); - OBJ_FREEZE(path); - return path; + return rb_fstring(path); } static VALUE @@ -248,9 +265,7 @@ rb_path_to_class(VALUE pathname) pbeg = p; } if (!id) { - undefined_class: - rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE, - rb_str_subseq(pathname, 0, p-path)); + goto undefined_class; } c = rb_const_search(c, id, TRUE, FALSE, FALSE); if (c == Qundef) goto undefined_class; @@ -262,6 +277,11 @@ rb_path_to_class(VALUE pathname) RB_GC_GUARD(pathname); return c; + + undefined_class: + rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE, + rb_str_subseq(pathname, 0, p-path)); + UNREACHABLE_RETURN(Qundef); } VALUE @@ -305,9 +325,16 @@ struct rb_global_variable { rb_gvar_getter_t *getter; rb_gvar_setter_t *setter; rb_gvar_marker_t *marker; + rb_gvar_compact_t *compactor; struct trace_var *trace; }; +struct rb_global_entry { + struct rb_global_variable *var; + ID id; + bool ractor_local; +}; + static struct rb_global_entry* rb_find_global_entry(ID id) { @@ -315,14 +342,33 @@ rb_find_global_entry(ID id) VALUE data; if (!rb_id_table_lookup(rb_global_tbl, id, &data)) { - return NULL; + entry = NULL; } - entry = (struct rb_global_entry *)data; - ASSUME(entry != NULL); + else { + entry = (struct rb_global_entry *)data; + RUBY_ASSERT(entry != NULL); + } + + if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) { + rb_raise(rb_eRactorIsolationError, "can not access global variables %s from non-main Ractors", rb_id2name(id)); + } + return entry; } -MJIT_FUNC_EXPORTED struct rb_global_entry* +void +rb_gvar_ractor_local(const char *name) +{ + struct rb_global_entry *entry = rb_find_global_entry(rb_intern(name)); + entry->ractor_local = true; +} + +static void +rb_gvar_undef_compactor(void *var) +{ +} + +static struct rb_global_entry* rb_global_entry(ID id) { struct rb_global_entry *entry = rb_find_global_entry(id); @@ -332,11 +378,13 @@ rb_global_entry(ID id) var = ALLOC(struct rb_global_variable); entry->id = id; entry->var = var; + entry->ractor_local = false; var->counter = 1; var->data = 0; var->getter = rb_gvar_undef_getter; var->setter = rb_gvar_undef_setter; var->marker = rb_gvar_undef_marker; + var->compactor = rb_gvar_undef_compactor; var->block_trace = 0; var->trace = 0; @@ -353,6 +401,21 @@ rb_gvar_undef_getter(ID id, VALUE *_) return Qnil; } +static void +rb_gvar_val_compactor(void *_var) +{ + struct rb_global_variable *var = (struct rb_global_variable *)_var; + + VALUE obj = (VALUE)var->data; + + if (obj) { + VALUE new = rb_gc_location(obj); + if (new != obj) { + var->data = (void*)new; + } + } +} + void rb_gvar_undef_setter(VALUE val, ID id, VALUE *_) { @@ -360,6 +423,7 @@ rb_gvar_undef_setter(VALUE val, ID id, VALUE *_) var->getter = rb_gvar_val_getter; var->setter = rb_gvar_val_setter; var->marker = rb_gvar_val_marker; + var->compactor = rb_gvar_val_compactor; var->data = (void*)val; } @@ -386,7 +450,7 @@ void rb_gvar_val_marker(VALUE *var) { VALUE data = (VALUE)var; - if (data) rb_gc_mark_maybe(data); + if (data) rb_gc_mark_movable(data); } VALUE @@ -433,8 +497,27 @@ mark_global_entry(VALUE v, void *ignored) void rb_gc_mark_global_tbl(void) { - if (rb_global_tbl) + if (rb_global_tbl) { rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0); + } +} + +static enum rb_id_table_iterator_result +update_global_entry(VALUE v, void *ignored) +{ + struct rb_global_entry *entry = (struct rb_global_entry *)v; + struct rb_global_variable *var = entry->var; + + (*var->compactor)(var); + return ID_TABLE_CONTINUE; +} + +void +rb_gc_update_global_tbl(void) +{ + if (rb_global_tbl) { + rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0); + } } static ID @@ -577,18 +660,17 @@ rb_f_untrace_var(int argc, const VALUE *argv) ID id; struct rb_global_entry *entry; struct trace_var *trace; - VALUE data; rb_scan_args(argc, argv, "11", &var, &cmd); id = rb_check_id(&var); if (!id) { rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var)); } - if (!rb_id_table_lookup(rb_global_tbl, id, &data)) { + if ((entry = rb_find_global_entry(id)) == NULL) { rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id)); } - trace = (entry = (struct rb_global_entry *)data)->var->trace; + trace = entry->var->trace; if (NIL_P(cmd)) { VALUE ary = rb_ary_new(); @@ -615,13 +697,6 @@ rb_f_untrace_var(int argc, const VALUE *argv) return Qnil; } -MJIT_FUNC_EXPORTED VALUE -rb_gvar_get(struct rb_global_entry *entry) -{ - struct rb_global_variable *var = entry->var; - return (*var->getter)(entry->id, var->data); -} - struct trace_data { struct trace_var *trace; VALUE val; @@ -650,8 +725,8 @@ trace_en(VALUE v) return Qnil; /* not reached */ } -MJIT_FUNC_EXPORTED VALUE -rb_gvar_set(struct rb_global_entry *entry, VALUE val) +static VALUE +rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val) { struct trace_data trace; struct rb_global_variable *var = entry->var; @@ -668,18 +743,31 @@ rb_gvar_set(struct rb_global_entry *entry, VALUE val) } VALUE -rb_gv_set(const char *name, VALUE val) +rb_gvar_set(ID id, VALUE val) { struct rb_global_entry *entry; + entry = rb_global_entry(id); + + return rb_gvar_set_entry(entry, val); +} + +VALUE +rb_gv_set(const char *name, VALUE val) +{ + return rb_gvar_set(global_id(name), val); +} - entry = rb_global_entry(global_id(name)); - return rb_gvar_set(entry, val); +VALUE +rb_gvar_get(ID id) +{ + struct rb_global_entry *entry = rb_global_entry(id); + struct rb_global_variable *var = entry->var; + return (*var->getter)(entry->id, var->data); } VALUE rb_gv_get(const char *name) { - struct rb_global_entry *entry; ID id = find_global_id(name); if (!id) { @@ -687,35 +775,30 @@ rb_gv_get(const char *name) return Qnil; } - entry = rb_global_entry(id); - return rb_gvar_get(entry); + return rb_gvar_get(id); } MJIT_FUNC_EXPORTED VALUE -rb_gvar_defined(struct rb_global_entry *entry) +rb_gvar_defined(ID id) { - if (entry->var->getter == rb_gvar_undef_getter) return Qfalse; - return Qtrue; + struct rb_global_entry *entry = rb_global_entry(id); + return RBOOL(entry->var->getter != rb_gvar_undef_getter); } rb_gvar_getter_t * -rb_gvar_getter_function_of(const struct rb_global_entry *entry) +rb_gvar_getter_function_of(ID id) { + const struct rb_global_entry *entry = rb_global_entry(id); return entry->var->getter; } rb_gvar_setter_t * -rb_gvar_setter_function_of(const struct rb_global_entry *entry) +rb_gvar_setter_function_of(ID id) { + const struct rb_global_entry *entry = rb_global_entry(id); return entry->var->setter; } -bool -rb_gvar_is_traced(const struct rb_global_entry *entry) -{ - return !!entry->var->trace; -} - static enum rb_id_table_iterator_result gvar_i(ID key, VALUE val, void *a) { @@ -730,6 +813,10 @@ rb_f_global_variables(void) VALUE ary = rb_ary_new(); VALUE sym, backref = rb_backref_get(); + if (!rb_ractor_main_p()) { + rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors"); + } + rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary); if (!NIL_P(backref)) { char buf[2]; @@ -757,12 +844,17 @@ rb_alias_variable(ID name1, ID name2) { struct rb_global_entry *entry1, *entry2; VALUE data1; + struct rb_id_table *gtbl = rb_global_tbl; + + if (!rb_ractor_main_p()) { + rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors"); + } entry2 = rb_global_entry(name2); - if (!rb_id_table_lookup(rb_global_tbl, name1, &data1)) { + if (!rb_id_table_lookup(gtbl, name1, &data1)) { entry1 = ALLOC(struct rb_global_entry); entry1->id = name1; - rb_id_table_insert(rb_global_tbl, name1, (VALUE)entry1); + rb_id_table_insert(gtbl, name1, (VALUE)entry1); } else if ((entry1 = (struct rb_global_entry *)data1)->var != entry2->var) { struct rb_global_variable *var = entry1->var; @@ -787,22 +879,103 @@ rb_alias_variable(ID name1, ID name2) entry1->var = entry2->var; } +static bool +iv_index_tbl_lookup(struct st_table *tbl, ID id, uint32_t *indexp) +{ + st_data_t ent_data; + int r; + + if (tbl == NULL) return false; + + RB_VM_LOCK_ENTER(); + { + r = st_lookup(tbl, (st_data_t)id, &ent_data); + } + RB_VM_LOCK_LEAVE(); + + if (r) { + struct rb_iv_index_tbl_entry *ent = (void *)ent_data; + *indexp = ent->index; + return true; + } + else { + return false; + } +} + +static void +IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id) +{ + if (UNLIKELY(!rb_ractor_main_p())) { + if (rb_is_instance_id(id)) { // check only normal ivars + rb_raise(rb_eRactorIsolationError, "can not set instance variables of classes/modules by non-main Ractors"); + } + } +} + +#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \ + if (UNLIKELY(!rb_ractor_main_p())) { \ + rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \ + } + +static inline struct st_table * +generic_ivtbl(VALUE obj, ID id, bool force_check_ractor) +{ + ASSERT_vm_locking(); + + if ((force_check_ractor || LIKELY(rb_is_instance_id(id)) /* not internal ID */ ) && + !RB_OBJ_FROZEN_RAW(obj) && + UNLIKELY(!rb_ractor_main_p()) && + UNLIKELY(rb_ractor_shareable_p(obj))) { + + rb_raise(rb_eRactorIsolationError, "can not access instance variables of shareable objects from non-main Ractors"); + } + return generic_iv_tbl_; +} + +static inline struct st_table * +generic_ivtbl_no_ractor_check(VALUE obj) +{ + return generic_ivtbl(obj, 0, false); +} + static int -gen_ivtbl_get(VALUE obj, struct gen_ivtbl **ivtbl) +gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl) { st_data_t data; + int r = 0; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - *ivtbl = (struct gen_ivtbl *)data; - return 1; + RB_VM_LOCK_ENTER(); + { + if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) { + *ivtbl = (struct gen_ivtbl *)data; + r = 1; + } } - return 0; + RB_VM_LOCK_LEAVE(); + + return r; } -MJIT_FUNC_EXPORTED struct st_table * -rb_ivar_generic_ivtbl(void) +MJIT_FUNC_EXPORTED int +rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl) { - return generic_iv_tbl; + return gen_ivtbl_get(obj, 0, ivtbl); +} + +MJIT_FUNC_EXPORTED VALUE +rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index) +{ + struct gen_ivtbl *ivtbl; + + if (gen_ivtbl_get(obj, id, &ivtbl)) { + if (LIKELY(index < ivtbl->numiv)) { + VALUE val = ivtbl->ivptr[index]; + return val; + } + } + + return Qundef; } static VALUE @@ -810,11 +983,11 @@ generic_ivar_delete(VALUE obj, ID id, VALUE undef) { struct gen_ivtbl *ivtbl; - if (gen_ivtbl_get(obj, &ivtbl)) { + if (gen_ivtbl_get(obj, id, &ivtbl)) { st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - st_data_t index; + uint32_t index; - if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) { + if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) { if (index < ivtbl->numiv) { VALUE ret = ivtbl->ivptr[index]; @@ -831,11 +1004,11 @@ generic_ivar_get(VALUE obj, ID id, VALUE undef) { struct gen_ivtbl *ivtbl; - if (gen_ivtbl_get(obj, &ivtbl)) { + if (gen_ivtbl_get(obj, id, &ivtbl)) { st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - st_data_t index; + uint32_t index; - if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) { + if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) { if (index < ivtbl->numiv) { VALUE ret = ivtbl->ivptr[index]; @@ -882,42 +1055,36 @@ gen_ivtbl_dup(const struct gen_ivtbl *orig) static uint32_t iv_index_tbl_newsize(struct ivar_update *ivup) { - uint32_t index = (uint32_t)ivup->index; /* should not overflow */ - uint32_t newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */ - - if (!ivup->iv_extended && - ivup->u.iv_index_tbl->num_entries < (st_index_t)newsize) { - newsize = (uint32_t)ivup->u.iv_index_tbl->num_entries; + if (!ivup->iv_extended) { + return (uint32_t)ivup->u.iv_index_tbl->num_entries; + } + else { + uint32_t index = (uint32_t)ivup->index; /* should not overflow */ + return (index+1) + (index+1)/4; /* (index+1)*1.25 */ } - return newsize; } static int generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing) { - VALUE obj = (VALUE)*k; + ASSERT_vm_locking(); + struct ivar_update *ivup = (struct ivar_update *)u; - uint32_t newsize; - int ret = ST_CONTINUE; - struct gen_ivtbl *ivtbl; + struct gen_ivtbl *ivtbl = 0; if (existing) { ivtbl = (struct gen_ivtbl *)*v; - if (ivup->index >= ivtbl->numiv) { - goto resize; - } - ret = ST_STOP; - } - else { - FL_SET(obj, FL_EXIVAR); - ivtbl = 0; -resize: - newsize = iv_index_tbl_newsize(ivup); - ivtbl = gen_ivtbl_resize(ivtbl, newsize); - *v = (st_data_t)ivtbl; + if (ivup->index < ivtbl->numiv) { + ivup->u.ivtbl = ivtbl; + return ST_STOP; + } } + FL_SET((VALUE)*k, FL_EXIVAR); + uint32_t newsize = iv_index_tbl_newsize(ivup); + ivtbl = gen_ivtbl_resize(ivtbl, newsize); + *v = (st_data_t)ivtbl; ivup->u.ivtbl = ivtbl; - return ret; + return ST_CONTINUE; } static VALUE @@ -925,29 +1092,24 @@ generic_ivar_defined(VALUE obj, ID id) { struct gen_ivtbl *ivtbl; st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - st_data_t index; - - if (!iv_index_tbl) return Qfalse; - if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) return Qfalse; - if (!gen_ivtbl_get(obj, &ivtbl)) return Qfalse; + uint32_t index; - if ((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef)) - return Qtrue; + if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return Qfalse; + if (!gen_ivtbl_get(obj, id, &ivtbl)) return Qfalse; - return Qfalse; + return RBOOL((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef)); } static int generic_ivar_remove(VALUE obj, ID id, VALUE *valp) { struct gen_ivtbl *ivtbl; - st_data_t key = (st_data_t)id; - st_data_t index; + uint32_t index; st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); if (!iv_index_tbl) return 0; - if (!st_lookup(iv_index_tbl, key, &index)) return 0; - if (!gen_ivtbl_get(obj, &ivtbl)) return 0; + if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return 0; + if (!gen_ivtbl_get(obj, id, &ivtbl)) return 0; if (index < ivtbl->numiv) { if (ivtbl->ivptr[index] != Qundef) { @@ -974,7 +1136,7 @@ rb_mark_generic_ivar(VALUE obj) { struct gen_ivtbl *ivtbl; - if (gen_ivtbl_get(obj, &ivtbl)) { + if (gen_ivtbl_get(obj, 0, &ivtbl)) { gen_ivtbl_mark(ivtbl); } } @@ -983,27 +1145,19 @@ void rb_mv_generic_ivar(VALUE rsrc, VALUE dst) { st_data_t key = (st_data_t)rsrc; - struct gen_ivtbl *ivtbl; + st_data_t ivtbl; - if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl)) - st_insert(generic_iv_tbl, (st_data_t)dst, (st_data_t)ivtbl); + if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl)) + st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl); } void rb_free_generic_ivar(VALUE obj) { - st_data_t key = (st_data_t)obj; - struct gen_ivtbl *ivtbl; - - if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl)) - xfree(ivtbl); + st_data_t key = (st_data_t)obj, ivtbl; - if (generic_iv_tbl_compat) { - st_table *tbl; - - if (st_delete(generic_iv_tbl_compat, &key, (st_data_t *)&tbl)) - st_free_table(tbl); - } + if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, &ivtbl)) + xfree((struct gen_ivtbl *)ivtbl); } RUBY_FUNC_EXPORTED size_t @@ -1011,7 +1165,7 @@ rb_generic_ivar_memsize(VALUE obj) { struct gen_ivtbl *ivtbl; - if (gen_ivtbl_get(obj, &ivtbl)) + if (gen_ivtbl_get(obj, 0, &ivtbl)) return gen_ivtbl_bytes(ivtbl->numiv); return 0; } @@ -1031,33 +1185,94 @@ gen_ivtbl_count(const struct gen_ivtbl *ivtbl) return n; } +static int +lock_st_lookup(st_table *tab, st_data_t key, st_data_t *value) +{ + int r; + RB_VM_LOCK_ENTER(); + { + r = st_lookup(tab, key, value); + } + RB_VM_LOCK_LEAVE(); + return r; +} + +static int +lock_st_delete(st_table *tab, st_data_t *key, st_data_t *value) +{ + int r; + RB_VM_LOCK_ENTER(); + { + r = st_delete(tab, key, value); + } + RB_VM_LOCK_LEAVE(); + return r; +} + +static int +lock_st_is_member(st_table *tab, st_data_t key) +{ + int r; + RB_VM_LOCK_ENTER(); + { + r = st_is_member(tab, key); + } + RB_VM_LOCK_LEAVE(); + return r; +} + +static int +lock_st_insert(st_table *tab, st_data_t key, st_data_t value) +{ + int r; + RB_VM_LOCK_ENTER(); + { + r = st_insert(tab, key, value); + } + RB_VM_LOCK_LEAVE(); + return r; +} + VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef) { - VALUE val, *ptr; - struct st_table *iv_index_tbl; - uint32_t len; - st_data_t index; - if (SPECIAL_CONST_P(obj)) return undef; switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - len = ROBJECT_NUMIV(obj); - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; - if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; - if (len <= index) break; - val = ptr[index]; - if (val != Qundef) - return val; - break; + { + uint32_t index; + uint32_t len = ROBJECT_NUMIV(obj); + VALUE *ptr = ROBJECT_IVPTR(obj); + VALUE val; + + if (iv_index_tbl_lookup(ROBJECT_IV_INDEX_TBL(obj), id, &index) && + index < len && + (val = ptr[index]) != Qundef) { + return val; + } + else { + break; + } + } case T_CLASS: case T_MODULE: - if (RCLASS_IV_TBL(obj) && - st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) - return (VALUE)index; - break; + { + st_data_t val; + + if (RCLASS_IV_TBL(obj) && + lock_st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) { + if (rb_is_instance_id(id) && + UNLIKELY(!rb_ractor_main_p()) && + !rb_ractor_shareable_p(val)) { + rb_raise(rb_eRactorIsolationError, + "can not get unshareable values from instance variables of classes/modules from non-main Ractors"); + } + return val; + } + else { + break; + } + } default: if (FL_TEST(obj, FL_EXIVAR)) return generic_ivar_get(obj, id, undef); @@ -1069,14 +1284,8 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef) VALUE rb_ivar_get(VALUE obj, ID id) { - VALUE iv = rb_ivar_lookup(obj, id, Qundef); + VALUE iv = rb_ivar_lookup(obj, id, Qnil); RB_DEBUG_COUNTER_INC(ivar_get_base); - - if (iv == Qundef) { - if (RTEST(ruby_verbose)) - rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); - iv = Qnil; - } return iv; } @@ -1089,10 +1298,9 @@ rb_attr_get(VALUE obj, ID id) static VALUE rb_ivar_delete(VALUE obj, ID id, VALUE undef) { - VALUE val, *ptr; + VALUE *ptr; struct st_table *iv_index_tbl; - uint32_t len; - st_data_t index; + uint32_t len, index; rb_check_frozen(obj); switch (BUILTIN_TYPE(obj)) { @@ -1100,19 +1308,25 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef) len = ROBJECT_NUMIV(obj); ptr = ROBJECT_IVPTR(obj); iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; - if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; - if (len <= index) break; - val = ptr[index]; - ptr[index] = Qundef; - if (val != Qundef) - return val; - break; + if (iv_index_tbl_lookup(iv_index_tbl, id, &index) && + index < len) { + VALUE val = ptr[index]; + ptr[index] = Qundef; + + if (val != Qundef) { + return val; + } + } + break; case T_CLASS: case T_MODULE: - if (RCLASS_IV_TBL(obj) && - st_delete(RCLASS_IV_TBL(obj), (st_data_t *)&id, &index)) - return (VALUE)index; + IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id); + if (RCLASS_IV_TBL(obj)) { + st_data_t id_data = (st_data_t)id, val; + if (lock_st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) { + return (VALUE)val; + } + } break; default: if (FL_TEST(obj, FL_EXIVAR)) @@ -1129,42 +1343,63 @@ rb_attr_delete(VALUE obj, ID id) } static st_table * -iv_index_tbl_make(VALUE obj) +iv_index_tbl_make(VALUE obj, VALUE klass) { - VALUE klass = rb_obj_class(obj); - st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); + st_table *iv_index_tbl; + + if (UNLIKELY(!klass)) { + rb_raise(rb_eTypeError, "hidden object cannot have instance variables"); + } - if (!iv_index_tbl) { - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); + if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) { + RB_VM_LOCK_ENTER(); + if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) { + iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); + } + RB_VM_LOCK_LEAVE(); } return iv_index_tbl; } static void -iv_index_tbl_extend(struct ivar_update *ivup, ID id) +iv_index_tbl_extend(struct ivar_update *ivup, ID id, VALUE klass) { - if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ivup->index)) { + ASSERT_vm_locking(); + st_data_t ent_data; + struct rb_iv_index_tbl_entry *ent; + + if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ent_data)) { + ent = (void *)ent_data; + ivup->index = ent->index; return; } if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) { rb_raise(rb_eArgError, "too many instance variables"); } - ivup->index = (st_data_t)ivup->u.iv_index_tbl->num_entries; - st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, ivup->index); + ent = ALLOC(struct rb_iv_index_tbl_entry); + ent->index = ivup->index = (uint32_t)ivup->u.iv_index_tbl->num_entries; + ent->class_value = klass; + ent->class_serial = RCLASS_SERIAL(klass); + st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, (st_data_t)ent); ivup->iv_extended = 1; } static void generic_ivar_set(VALUE obj, ID id, VALUE val) { + VALUE klass = rb_obj_class(obj); struct ivar_update ivup; - ivup.iv_extended = 0; - ivup.u.iv_index_tbl = iv_index_tbl_make(obj); - iv_index_tbl_extend(&ivup, id); - st_update(generic_iv_tbl, (st_data_t)obj, generic_ivar_update, - (st_data_t)&ivup); + ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass); + + RB_VM_LOCK_ENTER(); + { + iv_index_tbl_extend(&ivup, id, klass); + st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update, + (st_data_t)&ivup); + } + RB_VM_LOCK_LEAVE(); ivup.u.ivtbl->ivptr[ivup.index] = val; @@ -1232,44 +1467,84 @@ rb_obj_transient_heap_evacuate(VALUE obj, int promote) } #endif +static void +init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table *index_tbl) +{ + VALUE *ptr = ROBJECT_IVPTR(obj); + VALUE *newptr; + + if (RBASIC(obj)->flags & ROBJECT_EMBED) { + newptr = obj_ivar_heap_alloc(obj, newsize); + MEMCPY(newptr, ptr, VALUE, len); + RBASIC(obj)->flags &= ~ROBJECT_EMBED; + ROBJECT(obj)->as.heap.ivptr = newptr; + } + else { + newptr = obj_ivar_heap_realloc(obj, len, newsize); + } + + for (; len < newsize; len++) { + newptr[len] = Qundef; + } + ROBJECT(obj)->as.heap.numiv = newsize; + ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl; +} + +void +rb_init_iv_list(VALUE obj) +{ + st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj); + uint32_t newsize = (uint32_t)index_tbl->num_entries; + uint32_t len = ROBJECT_NUMIV(obj); + init_iv_list(obj, len, newsize, index_tbl); +} + +// Retrieve or create the id-to-index mapping for a given object and an +// instance variable name. +static struct ivar_update +obj_ensure_iv_index_mapping(VALUE obj, ID id) +{ + VALUE klass = rb_obj_class(obj); + struct ivar_update ivup; + ivup.iv_extended = 0; + ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass); + + RB_VM_LOCK_ENTER(); + { + iv_index_tbl_extend(&ivup, id, klass); + } + RB_VM_LOCK_LEAVE(); + + return ivup; +} + +// Return the instance variable index for a given name and T_OBJECT object. The +// mapping between name and index lives on `rb_obj_class(obj)` and is created +// if not already present. +// +// @note May raise when there are too many instance variables. +// @note YJIT uses this function at compile time to simplify the work needed to +// access the variable at runtime. +uint32_t +rb_obj_ensure_iv_index_mapping(VALUE obj, ID id) +{ + RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT)); + // This uint32_t cast shouldn't lose information as it's checked in + // iv_index_tbl_extend(). The index is stored as an uint32_t in + // struct rb_iv_index_tbl_entry. + return (uint32_t)obj_ensure_iv_index_mapping(obj, id).index; +} + static VALUE obj_ivar_set(VALUE obj, ID id, VALUE val) { - struct ivar_update ivup; - uint32_t i, len; + uint32_t len; + struct ivar_update ivup = obj_ensure_iv_index_mapping(obj, id); - ivup.iv_extended = 0; - ivup.u.iv_index_tbl = iv_index_tbl_make(obj); - iv_index_tbl_extend(&ivup, id); len = ROBJECT_NUMIV(obj); if (len <= ivup.index) { - VALUE *ptr = ROBJECT_IVPTR(obj); - if (ivup.index < ROBJECT_EMBED_LEN_MAX) { - RBASIC(obj)->flags |= ROBJECT_EMBED; - ptr = ROBJECT(obj)->as.ary; - for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { - ptr[i] = Qundef; - } - } - else { - VALUE *newptr; - uint32_t newsize = iv_index_tbl_newsize(&ivup); - - if (RBASIC(obj)->flags & ROBJECT_EMBED) { - newptr = obj_ivar_heap_alloc(obj, newsize); - MEMCPY(newptr, ptr, VALUE, len); - RBASIC(obj)->flags &= ~ROBJECT_EMBED; - ROBJECT(obj)->as.heap.ivptr = newptr; - } - else { - newptr = obj_ivar_heap_realloc(obj, len, newsize); - } - for (; len < newsize; len++) { - newptr[len] = Qundef; - } - ROBJECT(obj)->as.heap.numiv = newsize; - ROBJECT(obj)->as.heap.iv_index_tbl = ivup.u.iv_index_tbl; - } + uint32_t newsize = iv_index_tbl_newsize(&ivup); + init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl); } RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val); @@ -1287,7 +1562,7 @@ ivar_set(VALUE obj, ID id, VALUE val) break; case T_CLASS: case T_MODULE: - if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); + IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id); rb_class_ivar_set(obj, id, val); break; default: @@ -1318,22 +1593,21 @@ rb_ivar_defined(VALUE obj, ID id) { VALUE val; struct st_table *iv_index_tbl; - st_data_t index; + uint32_t index; if (SPECIAL_CONST_P(obj)) return Qfalse; switch (BUILTIN_TYPE(obj)) { case T_OBJECT: iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; - if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) + if (iv_index_tbl_lookup(iv_index_tbl, id, &index) && + index < ROBJECT_NUMIV(obj) && + (val = ROBJECT_IVPTR(obj)[index]) != Qundef) { return Qtrue; + } break; case T_CLASS: case T_MODULE: - if (RCLASS_IV_TBL(obj) && st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id)) + if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id)) return Qtrue; break; default: @@ -1345,80 +1619,72 @@ rb_ivar_defined(VALUE obj, ID id) } typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg); +st_data_t rb_st_nth_key(st_table *tab, st_index_t index); -struct obj_ivar_tag { - VALUE obj; - rb_ivar_foreach_callback_func *func; - st_data_t arg; -}; - -static int -obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) +static ID +iv_index_tbl_nth_id(st_table *iv_index_tbl, uint32_t index) { - struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; - if (index < ROBJECT_NUMIV(data->obj)) { - VALUE val = ROBJECT_IVPTR(data->obj)[index]; - if (val != Qundef) { - return (data->func)((ID)key, val, data->arg); + st_data_t key; + RB_VM_LOCK_ENTER(); + { + key = rb_st_nth_key(iv_index_tbl, index); + } + RB_VM_LOCK_LEAVE(); + return (ID)key; +} + +static inline bool +ivar_each_i(st_table *iv_index_tbl, VALUE val, uint32_t i, rb_ivar_foreach_callback_func *func, st_data_t arg) +{ + if (val != Qundef) { + ID id = iv_index_tbl_nth_id(iv_index_tbl, i); + switch (func(id, val, arg)) { + case ST_CHECK: + case ST_CONTINUE: + break; + case ST_STOP: + return true; + default: + rb_bug("unreachable"); } } - return ST_CONTINUE; + return false; } static void obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) { - st_table *tbl; - struct obj_ivar_tag data; - - tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!tbl) - return; - - data.obj = obj; - data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; - data.arg = arg; - - st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -} - -struct gen_ivar_tag { - struct gen_ivtbl *ivtbl; - rb_ivar_foreach_callback_func *func; - st_data_t arg; -}; - -static int -gen_ivar_each_i(st_data_t key, st_data_t index, st_data_t data) -{ - struct gen_ivar_tag *arg = (struct gen_ivar_tag *)data; + st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + if (!iv_index_tbl) return; + uint32_t i=0; - if (index < arg->ivtbl->numiv) { - VALUE val = arg->ivtbl->ivptr[index]; - if (val != Qundef) { - return (arg->func)((ID)key, val, arg->arg); + for (i=0; i < ROBJECT_NUMIV(obj); i++) { + VALUE val = ROBJECT_IVPTR(obj)[i]; + if (ivar_each_i(iv_index_tbl, val, i, func, arg)) { + return; } } - return ST_CONTINUE; } static void gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) { - struct gen_ivar_tag data; + struct gen_ivtbl *ivtbl; st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - if (!iv_index_tbl) return; - if (!gen_ivtbl_get(obj, &data.ivtbl)) return; + if (!gen_ivtbl_get(obj, 0, &ivtbl)) return; - data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; - data.arg = arg; - - st_foreach_safe(iv_index_tbl, gen_ivar_each_i, (st_data_t)&data); + for (uint32_t i=0; inumiv; i++) { + VALUE val = ivtbl->ivptr[i]; + if (ivar_each_i(iv_index_tbl, val, i, func, arg)) { + return; + } + } } struct givar_copy { VALUE obj; + VALUE klass; st_table *iv_index_tbl; struct gen_ivtbl *ivtbl; }; @@ -1431,7 +1697,13 @@ gen_ivar_copy(ID id, VALUE val, st_data_t arg) ivup.iv_extended = 0; ivup.u.iv_index_tbl = c->iv_index_tbl; - iv_index_tbl_extend(&ivup, id); + + RB_VM_LOCK_ENTER(); + { + iv_index_tbl_extend(&ivup, id, c->klass); + } + RB_VM_LOCK_LEAVE(); + if (ivup.index >= c->ivtbl->numiv) { uint32_t newsize = iv_index_tbl_newsize(&ivup); c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize); @@ -1451,21 +1723,16 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) rb_check_frozen(clone); if (!FL_TEST(obj, FL_EXIVAR)) { - clear: - if (FL_TEST(clone, FL_EXIVAR)) { - rb_free_generic_ivar(clone); - FL_UNSET(clone, FL_EXIVAR); - } - return; + goto clear; } - if (gen_ivtbl_get(obj, &ivtbl)) { + if (gen_ivtbl_get(obj, 0, &ivtbl)) { struct givar_copy c; uint32_t i; if (gen_ivtbl_count(ivtbl) == 0) goto clear; - if (gen_ivtbl_get(clone, &c.ivtbl)) { + if (gen_ivtbl_get(clone, 0, &c.ivtbl)) { for (i = 0; i < c.ivtbl->numiv; i++) c.ivtbl->ivptr[i] = Qundef; } @@ -1474,17 +1741,52 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) FL_SET(clone, FL_EXIVAR); } - c.iv_index_tbl = iv_index_tbl_make(clone); - c.obj = clone; + VALUE klass = rb_obj_class(clone); + c.iv_index_tbl = iv_index_tbl_make(clone, klass); + c.obj = clone; + c.klass = klass; gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c); /* * c.ivtbl may change in gen_ivar_copy due to realloc, * no need to free */ - st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)c.ivtbl); + RB_VM_LOCK_ENTER(); + { + generic_ivtbl_no_ractor_check(clone); + st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)c.ivtbl); + } + RB_VM_LOCK_LEAVE(); + } + return; + + clear: + if (FL_TEST(clone, FL_EXIVAR)) { + rb_free_generic_ivar(clone); + FL_UNSET(clone, FL_EXIVAR); } } +void +rb_replace_generic_ivar(VALUE clone, VALUE obj) +{ + RUBY_ASSERT(FL_TEST(obj, FL_EXIVAR)); + + RB_VM_LOCK_ENTER(); + { + st_data_t ivtbl, obj_data = (st_data_t)obj; + if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) { + st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl); + st_delete(generic_iv_tbl_, &obj_data, NULL); + } + else { + rb_bug("unreachable"); + } + } + RB_VM_LOCK_LEAVE(); + + FL_SET(clone, FL_EXIVAR); +} + void rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) { @@ -1495,8 +1797,13 @@ rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) break; case T_CLASS: case T_MODULE: + IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0); if (RCLASS_IV_TBL(obj)) { - st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); + RB_VM_LOCK_ENTER(); + { + st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); + } + RB_VM_LOCK_LEAVE(); } break; default: @@ -1516,7 +1823,7 @@ rb_ivar_count(VALUE obj) switch (BUILTIN_TYPE(obj)) { case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { + if (ROBJECT_IV_INDEX_TBL(obj) != 0) { st_index_t i, count, num = ROBJECT_NUMIV(obj); const VALUE *const ivptr = ROBJECT_IVPTR(obj); for (i = count = 0; i < num; ++i) { @@ -1537,7 +1844,7 @@ rb_ivar_count(VALUE obj) if (FL_TEST(obj, FL_EXIVAR)) { struct gen_ivtbl *ivtbl; - if (gen_ivtbl_get(obj, &ivtbl)) { + if (gen_ivtbl_get(obj, 0, &ivtbl)) { return gen_ivtbl_count(ivtbl); } } @@ -1637,7 +1944,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) const ID id = id_for_var(obj, name, an, instance); st_data_t n, v; struct st_table *iv_index_tbl; - st_data_t index; + uint32_t index; rb_check_frozen(obj); if (!id) { @@ -1647,19 +1954,18 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) switch (BUILTIN_TYPE(obj)) { case T_OBJECT: iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; - if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { + if (iv_index_tbl_lookup(iv_index_tbl, id, &index) && + index < ROBJECT_NUMIV(obj) && + (val = ROBJECT_IVPTR(obj)[index]) != Qundef) { ROBJECT_IVPTR(obj)[index] = Qundef; return val; } break; case T_CLASS: case T_MODULE: + IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id); n = id; - if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { + if (RCLASS_IV_TBL(obj) && lock_st_delete(RCLASS_IV_TBL(obj), &n, &v)) { return (VALUE)v; } break; @@ -1802,8 +2108,10 @@ struct autoload_const { VALUE mod; VALUE ad; /* autoload_data_i */ VALUE value; + VALUE file; ID id; rb_const_flag_t flag; + int line; }; /* always on stack, no need to mark */ @@ -1811,7 +2119,7 @@ struct autoload_state { struct autoload_const *ac; VALUE result; VALUE thread; - struct list_node waitq; + struct list_head waitq; }; struct autoload_data_i { @@ -1872,6 +2180,7 @@ autoload_c_compact(void *ptr) ac->mod = rb_gc_location(ac->mod); ac->ad = rb_gc_location(ac->ad); ac->value = rb_gc_location(ac->value); + ac->file = rb_gc_location(ac->file); } static void @@ -1882,6 +2191,7 @@ autoload_c_mark(void *ptr) rb_gc_mark_movable(ac->mod); rb_gc_mark_movable(ac->ad); rb_gc_mark_movable(ac->value); + rb_gc_mark_movable(ac->file); } static void @@ -2010,23 +2320,26 @@ autoload_delete(VALUE mod, ID id) struct autoload_const *ac; st_delete(tbl, &n, &load); - ele = get_autoload_data((VALUE)load, &ac); - VM_ASSERT(ele); - if (ele) { - VM_ASSERT(!list_empty(&ele->constants)); - } + /* Qfalse can indicate already deleted */ + if (load != Qfalse) { + ele = get_autoload_data((VALUE)load, &ac); + VM_ASSERT(ele); + if (ele) { + VM_ASSERT(!list_empty(&ele->constants)); + } - /* - * we must delete here to avoid "already initialized" warnings - * with parallel autoload. Using list_del_init here so list_del - * works in autoload_c_free - */ - list_del_init(&ac->cnode); + /* + * we must delete here to avoid "already initialized" warnings + * with parallel autoload. Using list_del_init here so list_del + * works in autoload_c_free + */ + list_del_init(&ac->cnode); - if (tbl->num_entries == 0) { - n = autoload; - st_delete(RCLASS_IV_TBL(mod), &n, &val); - } + if (tbl->num_entries == 0) { + n = autoload; + st_delete(RCLASS_IV_TBL(mod), &n, &val); + } + } } } @@ -2118,13 +2431,18 @@ autoload_defined_p(VALUE mod, ID id) static void const_tbl_update(struct autoload_const *); static VALUE -autoload_const_set(VALUE arg) +autoload_const_set(struct autoload_const *ac) { - struct autoload_const *ac = (struct autoload_const *)arg; VALUE klass = ac->mod; ID id = ac->id; check_before_mod_set(klass, id, ac->value, "constant"); - const_tbl_update(ac); + + RB_VM_LOCK_ENTER(); + { + const_tbl_update(ac); + } + RB_VM_LOCK_LEAVE(); + return 0; /* ignored */ } @@ -2164,7 +2482,7 @@ autoload_reset(VALUE arg) list_for_each_safe(&ele->constants, ac, next, cnode) { if (ac->value != Qundef) { - autoload_const_set((VALUE)ac); + autoload_const_set(ac); } } } @@ -2173,11 +2491,11 @@ autoload_reset(VALUE arg) if (need_wakeups) { struct autoload_state *cur = 0, *nxt; - list_for_each_safe((struct list_head *)&state->waitq, cur, nxt, waitq) { + list_for_each_safe(&state->waitq, cur, nxt, waitq.n) { VALUE th = cur->thread; cur->thread = Qfalse; - list_del_init(&cur->waitq); /* idempotent */ + list_del_init(&cur->waitq.n); /* idempotent */ /* * cur is stored on the stack of cur->waiting_th, @@ -2212,7 +2530,7 @@ autoload_sleep_done(VALUE arg) struct autoload_state *state = (struct autoload_state *)arg; if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) { - list_del(&state->waitq); /* idempotent after list_del_init */ + list_del(&state->waitq.n); /* idempotent after list_del_init */ } return Qfalse; @@ -2235,6 +2553,10 @@ rb_autoload_load(VALUE mod, ID id) src = rb_sourcefile(); if (src && loading && strcmp(src, loading) == 0) return Qfalse; + if (UNLIKELY(!rb_ractor_main_p())) { + rb_raise(rb_eRactorUnsafeError, "require by autoload on non-main Ractor is not supported (%s)", rb_id2name(id)); + } + if ((ce = rb_const_lookup(mod, id))) { flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK); } @@ -2251,15 +2573,15 @@ rb_autoload_load(VALUE mod, ID id) /* * autoload_reset will wake up any threads added to this - * iff the GVL is released during autoload_require + * if and only if the GVL is released during autoload_require */ - list_head_init((struct list_head *)&state.waitq); + list_head_init(&state.waitq); } else if (state.thread == ele->state->thread) { return Qfalse; } else { - list_add_tail((struct list_head *)&ele->state->waitq, &state.waitq); + list_add_tail(&ele->state->waitq, &state.waitq.n); rb_ensure(autoload_sleep, (VALUE)&state, autoload_sleep_done, (VALUE)&state); @@ -2270,7 +2592,10 @@ rb_autoload_load(VALUE mod, ID id) result = rb_ensure(autoload_require, (VALUE)&state, autoload_reset, (VALUE)&state); - if (flag > 0 && (ce = rb_const_lookup(mod, id))) { + if (!(ce = rb_const_lookup(mod, id)) || ce->value == Qundef) { + rb_const_remove(mod, id); + } + else if (flag > 0) { ce->flag |= flag; } RB_GC_GUARD(load); @@ -2305,10 +2630,10 @@ rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id) if (RB_CONST_DEPRECATED_P(ce) && rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) { if (klass == rb_cObject) { - rb_warn("constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id)); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id)); } else { - rb_warn("constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated", + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated", rb_class_name(klass), QUOTE_ID(id)); } } @@ -2318,23 +2643,45 @@ static VALUE rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) { VALUE c = rb_const_search(klass, id, exclude, recurse, visibility); - if (c != Qundef) return c; + if (c != Qundef) { + if (UNLIKELY(!rb_ractor_main_p())) { + if (!rb_ractor_shareable_p(c)) { + rb_raise(rb_eRactorIsolationError, "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main Ractor.", rb_class_path(klass), rb_id2name(id)); + } + } + return c; + } return rb_const_missing(klass, ID2SYM(id)); } static VALUE rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility) { - VALUE value, tmp; + VALUE value, current; + bool first_iteration = true; - tmp = klass; - while (RTEST(tmp)) { + for (current = klass; + RTEST(current); + current = RCLASS_SUPER(current), first_iteration = false) { + VALUE tmp; VALUE am = 0; rb_const_entry_t *ce; + if (!first_iteration && RCLASS_ORIGIN(current) != current) { + // This item in the super chain has an origin iclass + // that comes later in the chain. Skip this item so + // prepended modules take precedence. + continue; + } + + // Do lookup in original class or module in case we are at an origin + // iclass in the chain. + tmp = current; + if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass; + + // Do the lookup. Loop in case of autoload. while ((ce = rb_const_lookup(tmp, id))) { if (visibility && RB_CONST_PRIVATE_P(ce)) { - if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass; GET_EC()->private_const_reference = tmp; return Qundef; } @@ -2355,7 +2702,6 @@ rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibilit return value; } if (!recurse) break; - tmp = RCLASS_SUPER(tmp); } not_found: @@ -2550,8 +2896,13 @@ rb_local_constants(VALUE mod) if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(rb_id_table_size(tbl)); - rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary); + RB_VM_LOCK_ENTER(); + { + ary = rb_ary_new2(rb_id_table_size(tbl)); + rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary); + } + RB_VM_LOCK_LEAVE(); + return ary; } @@ -2563,7 +2914,11 @@ rb_mod_const_at(VALUE mod, void *data) tbl = st_init_numtable(); } if (RCLASS_CONST_TBL(mod)) { - rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl); + RB_VM_LOCK_ENTER(); + { + rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl); + } + RB_VM_LOCK_LEAVE(); } return tbl; } @@ -2711,10 +3066,7 @@ set_namespace_path_i(ID id, VALUE v, void *payload) VALUE value = ce->value; int has_permanent_classpath; VALUE parental_path = *((VALUE *) payload); - if (!rb_is_const_id(id)) { - return ID_TABLE_CONTINUE; - } - if (!rb_namespace_p(value)) { + if (!rb_is_const_id(id) || !rb_namespace_p(value)) { return ID_TABLE_CONTINUE; } classname(value, &has_permanent_classpath); @@ -2739,42 +3091,54 @@ static void set_namespace_path(VALUE named_namespace, VALUE namespace_path) { struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace); - if (!RCLASS_IV_TBL(named_namespace)) { - RCLASS_IV_TBL(named_namespace) = st_init_numtable(); - } - rb_class_ivar_set(named_namespace, classpath, namespace_path); - if (const_table) { - rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path); + + RB_VM_LOCK_ENTER(); + { + rb_class_ivar_set(named_namespace, classpath, namespace_path); + if (const_table) { + rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path); + } } + RB_VM_LOCK_LEAVE(); } void rb_const_set(VALUE klass, ID id, VALUE val) { rb_const_entry_t *ce; - struct rb_id_table *tbl = RCLASS_CONST_TBL(klass); if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"", QUOTE_ID(id)); } - check_before_mod_set(klass, id, val, "constant"); - if (!tbl) { - RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0); - rb_clear_constant_cache(); - ce = ZALLOC(rb_const_entry_t); - rb_id_table_insert(tbl, id, (VALUE)ce); - setup_const_entry(ce, klass, val, CONST_PUBLIC); + if (!rb_ractor_main_p() && !rb_ractor_shareable_p(val)) { + rb_raise(rb_eRactorIsolationError, "can not set constants with non-shareable objects by non-main Ractors"); } - else { - struct autoload_const ac; - ac.mod = klass; - ac.id = id; - ac.value = val; - ac.flag = CONST_PUBLIC; - const_tbl_update(&ac); + + check_before_mod_set(klass, id, val, "constant"); + + RB_VM_LOCK_ENTER(); + { + struct rb_id_table *tbl = RCLASS_CONST_TBL(klass); + if (!tbl) { + RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0); + rb_clear_constant_cache(); + ce = ZALLOC(rb_const_entry_t); + rb_id_table_insert(tbl, id, (VALUE)ce); + setup_const_entry(ce, klass, val, CONST_PUBLIC); + } + else { + struct autoload_const ac = { + .mod = klass, .id = id, + .value = val, .flag = CONST_PUBLIC, + /* fill the rest with 0 */ + }; + const_tbl_update(&ac); + } } + RB_VM_LOCK_LEAVE(); + /* * Resolve and cache class name immediately to resolve ambiguity * and avoid order-dependency on const_tbl @@ -2789,14 +3153,16 @@ rb_const_set(VALUE klass, ID id, VALUE val) else { int parental_path_permanent; VALUE parental_path = classname(klass, &parental_path_permanent); - if (!NIL_P(parental_path)) { - if (parental_path_permanent && !val_path_permanent) { - set_namespace_path(val, build_const_path(parental_path, id)); - } - else if (!parental_path_permanent && NIL_P(val_path)) { - rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id)); - } - } + if (NIL_P(parental_path)) { + int throwaway; + parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path); + } + if (parental_path_permanent && !val_path_permanent) { + set_namespace_path(val, build_const_path(parental_path, id)); + } + else if (!parental_path_permanent && NIL_P(val_path)) { + ivar_set(val, tmp_classpath, build_const_path(parental_path, id)); + } } } } @@ -2837,10 +3203,17 @@ const_tbl_update(struct autoload_const *ac) rb_clear_constant_cache(); ac->value = val; /* autoload_i is non-WB-protected */ - return; + ac->file = rb_source_location(&ac->line); } - /* otherwise, allow to override */ - autoload_delete(klass, id); + else { + /* otherwise autoloaded constant, allow to override */ + autoload_delete(klass, id); + ce->flag = visibility; + RB_OBJ_WRITE(klass, &ce->value, val); + RB_OBJ_WRITE(klass, &ce->file, ac->file); + ce->line = ac->line; + } + return; } else { VALUE name = QUOTE_ID(id); @@ -3047,8 +3420,9 @@ cvar_overtaken(VALUE front, VALUE target, ID id) if (front && target != front) { st_data_t did = (st_data_t)id; - if (RTEST(ruby_verbose) && original_module(front) != original_module(target)) { - rb_warning("class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"", + if (original_module(front) != original_module(target)) { + rb_raise(rb_eRuntimeError, + "class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"", ID2SYM(id), rb_class_name(original_module(front)), rb_class_name(original_module(target))); } @@ -3058,6 +3432,30 @@ cvar_overtaken(VALUE front, VALUE target, ID id) } } +static VALUE +find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id) +{ + VALUE v = Qundef; + CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); + if (cvar_lookup_at(klass, id, (&v))) { + if (!*front) { + *front = klass; + } + *target = klass; + } + + for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { + if (cvar_lookup_at(klass, id, (&v))) { + if (!*front) { + *front = klass; + } + *target = klass; + } + } + + return v; +} + #define CVAR_FOREACH_ANCESTORS(klass, v, r) \ for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \ if (cvar_lookup_at(klass, id, (v))) { \ @@ -3066,10 +3464,25 @@ cvar_overtaken(VALUE front, VALUE target, ID id) } #define CVAR_LOOKUP(v,r) do {\ + CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \ if (cvar_lookup_at(klass, id, (v))) {r;}\ CVAR_FOREACH_ANCESTORS(klass, v, r);\ } while(0) +static void +check_for_cvar_table(VALUE subclass, VALUE key) +{ + st_table *tbl = RCLASS_IV_TBL(subclass); + + if (tbl && st_lookup(tbl, key, NULL)) { + RB_DEBUG_COUNTER_INC(cvar_class_invalidate); + ruby_vm_global_cvar_state++; + return; + } + + rb_class_foreach_subclass(subclass, check_for_cvar_table, key); +} + void rb_cvar_set(VALUE klass, ID id, VALUE val) { @@ -3084,30 +3497,68 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) target = tmp; } + if (RB_TYPE_P(target, T_ICLASS)) { + target = RBASIC(target)->klass; + } check_before_mod_set(target, id, val, "class variable"); - if (!RCLASS_IV_TBL(target)) { - RCLASS_IV_TBL(target) = st_init_numtable(); + + int result = rb_class_ivar_set(target, id, val); + + struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target); + + if (!rb_cvc_tbl) { + rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2); + } + + struct rb_cvar_class_tbl_entry *ent; + VALUE ent_data; + + if (!rb_id_table_lookup(rb_cvc_tbl, id, &ent_data)) { + ent = ALLOC(struct rb_cvar_class_tbl_entry); + ent->class_value = target; + ent->global_cvar_state = GET_GLOBAL_CVAR_STATE(); + rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent); + RB_DEBUG_COUNTER_INC(cvar_inline_miss); + } + else { + ent = (void *)ent_data; + ent->global_cvar_state = GET_GLOBAL_CVAR_STATE(); } - rb_class_ivar_set(target, id, val); + // Break the cvar cache if this is a new class variable + // and target is a module or a subclass with the same + // cvar in this lookup. + if (result == 0) { + if (RB_TYPE_P(target, T_CLASS)) { + if (RCLASS_SUBCLASSES(target)) { + rb_class_foreach_subclass(target, check_for_cvar_table, id); + } + } + } } VALUE -rb_cvar_get(VALUE klass, ID id) +rb_cvar_find(VALUE klass, ID id, VALUE *front) { - VALUE tmp, front = 0, target = 0; - st_data_t value; + VALUE target = 0; + VALUE value; - tmp = klass; - CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;}); + value = find_cvar(klass, front, &target, id); if (!target) { rb_name_err_raise("uninitialized class variable %1$s in %2$s", - tmp, ID2SYM(id)); + klass, ID2SYM(id)); } - cvar_overtaken(front, target, id); + cvar_overtaken(*front, target, id); return (VALUE)value; } +VALUE +rb_cvar_get(VALUE klass, ID id) +{ + VALUE front = 0; + return rb_cvar_find(klass, id, &front); +} + VALUE rb_cvar_defined(VALUE klass, ID id) { @@ -3144,8 +3595,7 @@ rb_cv_get(VALUE klass, const char *name) void rb_define_class_variable(VALUE klass, const char *name, VALUE val) { - ID id = cv_intern(klass, name); - rb_cvar_set(klass, id, val); + rb_cv_set(klass, name, val); } static int @@ -3253,13 +3703,12 @@ rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod) * call-seq: * remove_class_variable(sym) -> obj * - * Removes the definition of the sym, returning that - * constant's value. + * Removes the named class variable from the receiver, returning that + * variable's value. * - * class Dummy + * class Example * @@var = 99 - * puts @@var - * remove_class_variable(:@@var) + * puts remove_class_variable(:@@var) * p(defined? @@var) * end * @@ -3276,9 +3725,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) st_data_t val, n = id; if (!id) { - not_defined: - rb_name_err_raise("class variable %1$s not defined for %2$s", - mod, name); + goto not_defined; } rb_check_frozen(mod); if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { @@ -3287,7 +3734,10 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) if (rb_cvar_defined(mod, id)) { rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id)); } - goto not_defined; + not_defined: + rb_name_err_raise("class variable %1$s not defined for %2$s", + mod, name); + UNREACHABLE_RETURN(Qundef); } VALUE @@ -3296,8 +3746,6 @@ rb_iv_get(VALUE obj, const char *name) ID id = rb_check_id_cstr(name, strlen(name), rb_usascii_encoding()); if (!id) { - if (RTEST(ruby_verbose)) - rb_warning("instance variable %s not initialized", name); return Qnil; } return rb_ivar_get(obj, id); @@ -3315,8 +3763,12 @@ rb_iv_set(VALUE obj, const char *name, VALUE val) int rb_class_ivar_set(VALUE obj, ID key, VALUE value) { + if (!RCLASS_IV_TBL(obj)) { + RCLASS_IV_TBL(obj) = st_init_numtable(); + } + st_table *tbl = RCLASS_IV_TBL(obj); - int result = st_insert(tbl, (st_data_t)key, (st_data_t)value); + int result = lock_st_insert(tbl, (st_data_t)key, (st_data_t)value); RB_OBJ_WRITTEN(obj, Qundef, value); return result; } @@ -3341,10 +3793,17 @@ MJIT_FUNC_EXPORTED rb_const_entry_t * rb_const_lookup(VALUE klass, ID id) { struct rb_id_table *tbl = RCLASS_CONST_TBL(klass); - VALUE val; - if (tbl && rb_id_table_lookup(tbl, id, &val)) { - return (rb_const_entry_t *)val; + if (tbl) { + VALUE val; + bool r; + RB_VM_LOCK_ENTER(); + { + r = rb_id_table_lookup(tbl, id, &val); + } + RB_VM_LOCK_LEAVE(); + + if (r) return (rb_const_entry_t *)val; } - return 0; + return NULL; } diff --git a/ruby/variable.h b/ruby/variable.h index 67fe48014..55596b00d 100644 --- a/ruby/variable.h +++ b/ruby/variable.h @@ -1,3 +1,12 @@ +#ifndef RUBY_TOPLEVEL_VARIABLE_H /*-*-C-*-vi:se ft=c:*/ +#define RUBY_TOPLEVEL_VARIABLE_H +/** + * @author Ruby developers + * @copyright 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. + */ /* per-object */ @@ -6,4 +15,7 @@ struct gen_ivtbl { VALUE ivptr[FLEX_ARY_LEN]; }; -struct st_table *rb_ivar_generic_ivtbl(void); +int rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **); +VALUE rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index); + +#endif /* RUBY_TOPLEVEL_VARIABLE_H */ diff --git a/ruby/version.c b/ruby/version.c index 7e1c0cb4c..7d4478eeb 100644 --- a/ruby/version.c +++ b/ruby/version.c @@ -13,6 +13,7 @@ #include "version.h" #include "vm_core.h" #include "mjit.h" +#include "yjit.h" #include #ifndef EXIT_SUCCESS @@ -41,7 +42,8 @@ const char ruby_release_date[] = RUBY_RELEASE_DATE; const char ruby_platform[] = RUBY_PLATFORM; const int ruby_patchlevel = RUBY_PATCHLEVEL; const char ruby_description[] = RUBY_DESCRIPTION_WITH(""); -static const char ruby_description_with_jit[] = RUBY_DESCRIPTION_WITH(" +JIT"); +static const char ruby_description_with_mjit[] = RUBY_DESCRIPTION_WITH(" +MJIT"); +static const char ruby_description_with_yjit[] = RUBY_DESCRIPTION_WITH(" +YJIT"); const char ruby_copyright[] = RUBY_COPYRIGHT; const char ruby_engine[] = "ruby"; @@ -102,7 +104,10 @@ Init_ruby_description(void) VALUE description; if (MJIT_OPTS_ON) { - description = MKSTR(description_with_jit); + description = MKSTR(description_with_mjit); + } + else if (rb_yjit_enabled_p()) { + description = MKSTR(description_with_yjit); } else { description = MKSTR(description); @@ -114,16 +119,19 @@ Init_ruby_description(void) rb_define_global_const("RUBY_DESCRIPTION", /* MKSTR(description) */ description); } -/*! Prints the version information of the CRuby interpreter to stdout. */ void ruby_show_version(void) { if (MJIT_OPTS_ON) { - PRINT(description_with_jit); + PRINT(description_with_mjit); + } + else if (rb_yjit_enabled_p()) { + PRINT(description_with_yjit); } else { PRINT(description); } + #ifdef RUBY_LAST_COMMIT_TITLE fputs("last_commit=" RUBY_LAST_COMMIT_TITLE, stdout); #endif @@ -133,7 +141,6 @@ ruby_show_version(void) fflush(stdout); } -/*! Prints the copyright notice of the CRuby interpreter to stdout. */ void ruby_show_copyright(void) { diff --git a/ruby/version.h b/ruby/version.h index 1a58fad1d..f3cefe1d6 100644 --- a/ruby/version.h +++ b/ruby/version.h @@ -1,12 +1,21 @@ +#ifndef RUBY_TOPLEVEL_VERSION_H /*-*-C-*-vi:se ft=c:*/ +#define RUBY_TOPLEVEL_VERSION_H +/** + * @author Ruby developers + * @copyright 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. + */ # define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR -#define RUBY_VERSION_TEENY 1 +#define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 83 +#define RUBY_PATCHLEVEL 20 -#define RUBY_RELEASE_YEAR 2020 -#define RUBY_RELEASE_MONTH 3 -#define RUBY_RELEASE_DAY 31 +#define RUBY_RELEASE_YEAR 2022 +#define RUBY_RELEASE_MONTH 4 +#define RUBY_RELEASE_DAY 12 #include "ruby/version.h" @@ -75,3 +84,5 @@ RUBY_BIRTH_YEAR_STR"-" \ RUBY_RELEASE_YEAR_STR" " \ RUBY_AUTHOR + +#endif /* RUBY_TOPLEVEL_VERSION_H */ diff --git a/ruby/vm.c b/ruby/vm.c index fc144be5b..8ce8b279d 100644 --- a/ruby/vm.c +++ b/ruby/vm.c @@ -1,6 +1,6 @@ /********************************************************************** - vm.c - + Vm.c - $Author$ @@ -8,17 +8,37 @@ **********************************************************************/ -#include "internal.h" -#include "ruby/vm.h" -#include "ruby/st.h" - #define vm_exec rb_vm_exec +#include "eval_intern.h" #include "gc.h" +#include "internal.h" +#include "internal/compile.h" +#include "internal/cont.h" +#include "internal/error.h" +#include "internal/eval.h" +#include "internal/inits.h" +#include "internal/object.h" +#include "internal/parse.h" +#include "internal/proc.h" +#include "internal/re.h" +#include "internal/symbol.h" +#include "internal/thread.h" +#include "internal/vm.h" +#include "internal/sanitizers.h" +#include "iseq.h" +#include "mjit.h" +#include "yjit.h" +#include "ruby/st.h" +#include "ruby/vm.h" #include "vm_core.h" +#include "vm_callinfo.h" #include "vm_debug.h" -#include "iseq.h" -#include "eval_intern.h" +#include "vm_exec.h" +#include "vm_insnhelper.h" +#include "ractor_core.h" +#include "vm_sync.h" + #include "builtin.h" #ifndef MJIT_HEADER @@ -39,7 +59,7 @@ RUBY_FUNC_EXPORTED #else MJIT_FUNC_EXPORTED #endif -VALUE vm_exec(rb_execution_context_t *, int); +VALUE vm_exec(rb_execution_context_t *, bool); PUREFUNC(static inline const VALUE *VM_EP_LEP(const VALUE *)); static inline const VALUE * @@ -104,13 +124,6 @@ rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp) return VM_FRAME_CFRAME_KW_P(cfp); } -/* -- Remove In 3.0 -- */ -int -rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp) -{ - return VM_FRAME_CFRAME_EMPTY_KW_P(cfp); -} - VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp) { @@ -148,7 +161,7 @@ VM_EP_IN_HEAP_P(const rb_execution_context_t *ec, const VALUE *ep) } } -int +static int vm_ep_in_heap_p_(const rb_execution_context_t *ec, const VALUE *ep) { if (VM_EP_IN_HEAP_P(ec, ep)) { @@ -189,7 +202,7 @@ VM_CAPTURED_BLOCK_TO_CFP(const struct rb_captured_block *captured) { rb_control_frame_t *cfp = ((rb_control_frame_t *)((VALUE *)(captured) - 3)); VM_ASSERT(!VM_CFP_IN_HEAP_P(GET_EC(), cfp)); - VM_ASSERT(sizeof(rb_control_frame_t)/sizeof(VALUE) == 7 + VM_DEBUG_BP_CHECK ? 1 : 0); + VM_ASSERT(sizeof(rb_control_frame_t)/sizeof(VALUE) == 8 + VM_DEBUG_BP_CHECK ? 1 : 0); return cfp; } @@ -210,7 +223,7 @@ vm_passed_block_handler(rb_execution_context_t *ec) } static rb_cref_t * -vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval, int use_prev_prev) +vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval, int use_prev_prev, int singleton) { VALUE refinements = Qnil; int omod_shared = FALSE; @@ -235,24 +248,27 @@ vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_ } } + VM_ASSERT(singleton || klass); + cref = (rb_cref_t *)rb_imemo_new(imemo_cref, klass, (VALUE)(use_prev_prev ? CREF_NEXT(prev_cref) : prev_cref), scope_visi.value, refinements); if (pushed_by_eval) CREF_PUSHED_BY_EVAL_SET(cref); if (omod_shared) CREF_OMOD_SHARED_SET(cref); + if (singleton) CREF_SINGLETON_SET(cref); return cref; } static rb_cref_t * -vm_cref_new(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval) +vm_cref_new(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval, int singleton) { - return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, FALSE); + return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, FALSE, singleton); } static rb_cref_t * vm_cref_new_use_prev(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval) { - return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, TRUE); + return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, TRUE, FALSE); } static int @@ -264,18 +280,37 @@ ref_delete_symkey(VALUE key, VALUE value, VALUE unused) static rb_cref_t * vm_cref_dup(const rb_cref_t *cref) { - VALUE klass = CREF_CLASS(cref); const rb_scope_visibility_t *visi = CREF_SCOPE_VISI(cref); rb_cref_t *next_cref = CREF_NEXT(cref), *new_cref; int pushed_by_eval = CREF_PUSHED_BY_EVAL(cref); + int singleton = CREF_SINGLETON(cref); - new_cref = vm_cref_new(klass, visi->method_visi, visi->module_func, next_cref, pushed_by_eval); + new_cref = vm_cref_new(cref->klass_or_self, visi->method_visi, visi->module_func, next_cref, pushed_by_eval, singleton); if (!NIL_P(CREF_REFINEMENTS(cref))) { VALUE ref = rb_hash_dup(CREF_REFINEMENTS(cref)); rb_hash_foreach(ref, ref_delete_symkey, Qnil); CREF_REFINEMENTS_SET(new_cref, ref); - CREF_OMOD_SHARED_UNSET(new_cref); + CREF_OMOD_SHARED_UNSET(new_cref); + } + + return new_cref; +} + + +rb_cref_t * +rb_vm_cref_dup_without_refinements(const rb_cref_t *cref) +{ + const rb_scope_visibility_t *visi = CREF_SCOPE_VISI(cref); + rb_cref_t *next_cref = CREF_NEXT(cref), *new_cref; + int pushed_by_eval = CREF_PUSHED_BY_EVAL(cref); + int singleton = CREF_SINGLETON(cref); + + new_cref = vm_cref_new(cref->klass_or_self, visi->method_visi, visi->module_func, next_cref, pushed_by_eval, singleton); + + if (!NIL_P(CREF_REFINEMENTS(cref))) { + CREF_REFINEMENTS_SET(new_cref, Qnil); + CREF_OMOD_SHARED_UNSET(new_cref); } return new_cref; @@ -284,11 +319,11 @@ vm_cref_dup(const rb_cref_t *cref) static rb_cref_t * vm_cref_new_toplevel(rb_execution_context_t *ec) { - rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, FALSE, NULL, FALSE); + rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, FALSE, NULL, FALSE, FALSE); VALUE top_wrapper = rb_ec_thread_ptr(ec)->top_wrapper; if (top_wrapper) { - cref = vm_cref_new(top_wrapper, METHOD_VISI_PRIVATE, FALSE, cref, FALSE); + cref = vm_cref_new(top_wrapper, METHOD_VISI_PRIVATE, FALSE, cref, FALSE, FALSE); } return cref; @@ -303,10 +338,10 @@ rb_vm_cref_new_toplevel(void) static void vm_cref_dump(const char *mesg, const rb_cref_t *cref) { - fprintf(stderr, "vm_cref_dump: %s (%p)\n", mesg, (void *)cref); + ruby_debug_printf("vm_cref_dump: %s (%p)\n", mesg, (void *)cref); while (cref) { - fprintf(stderr, "= cref| klass: %s\n", RSTRING_PTR(rb_class_path(CREF_CLASS(cref)))); + ruby_debug_printf("= cref| klass: %s\n", RSTRING_PTR(rb_class_path(CREF_CLASS(cref)))); cref = CREF_NEXT(cref); } } @@ -338,9 +373,6 @@ extern VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, V const rb_callable_method_entry_t *me); static VALUE vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler); -#include "mjit.h" -#include "vm_insnhelper.h" -#include "vm_exec.h" #include "vm_insnhelper.c" #ifndef MJIT_HEADER @@ -358,7 +390,6 @@ rb_serial_t rb_next_class_serial(void) { rb_serial_t class_serial = NEXT_CLASS_SERIAL(); - mjit_add_class_serial(class_serial); return class_serial; } @@ -370,15 +401,56 @@ VALUE rb_block_param_proxy; #define ruby_vm_redefined_flag GET_VM()->redefined_flag VALUE ruby_vm_const_missing_count = 0; rb_vm_t *ruby_current_vm_ptr = NULL; -rb_execution_context_t *ruby_current_execution_context_ptr = NULL; +rb_ractor_t *ruby_single_main_ractor; +bool ruby_vm_keep_script_lines; + +#ifdef RB_THREAD_LOCAL_SPECIFIER +RB_THREAD_LOCAL_SPECIFIER rb_execution_context_t *ruby_current_ec; + +#ifdef __APPLE__ + rb_execution_context_t * + rb_current_ec(void) + { + return ruby_current_ec; + } + void + rb_current_ec_set(rb_execution_context_t *ec) + { + ruby_current_ec = ec; + } +#endif + +#else +native_tls_key_t ruby_current_ec_key; +#endif rb_event_flag_t ruby_vm_event_flags; rb_event_flag_t ruby_vm_event_enabled_global_flags; unsigned int ruby_vm_event_local_num; -rb_serial_t ruby_vm_global_method_state = 1; rb_serial_t ruby_vm_global_constant_state = 1; rb_serial_t ruby_vm_class_serial = 1; +rb_serial_t ruby_vm_global_cvar_state = 1; + +static const struct rb_callcache vm_empty_cc = { + .flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE, + .klass = Qfalse, + .cme_ = NULL, + .call_ = vm_call_general, + .aux_ = { + .v = Qfalse, + } +}; + +static const struct rb_callcache vm_empty_cc_for_super = { + .flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE, + .klass = Qfalse, + .cme_ = NULL, + .call_ = vm_call_super_method, + .aux_ = { + .v = Qfalse, + } +}; static void thread_free(void *ptr); @@ -435,7 +507,6 @@ rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id, * This hash includes information about method/constant cache serials: * * { - * :global_method_state=>251, * :global_constant_state=>481, * :class_serial=>9029 * } @@ -449,7 +520,7 @@ rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id, static VALUE vm_stat(int argc, VALUE *argv, VALUE self) { - static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial; + static VALUE sym_global_constant_state, sym_class_serial, sym_global_cvar_state; VALUE arg = Qnil; VALUE hash = Qnil, key = Qnil; @@ -466,11 +537,11 @@ vm_stat(int argc, VALUE *argv, VALUE self) hash = rb_hash_new(); } - if (sym_global_method_state == 0) { + if (sym_global_constant_state == 0) { #define S(s) sym_##s = ID2SYM(rb_intern_const(#s)) - S(global_method_state); S(global_constant_state); S(class_serial); + S(global_cvar_state); #undef S } @@ -480,9 +551,9 @@ vm_stat(int argc, VALUE *argv, VALUE self) else if (hash != Qnil) \ rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr)); - SET(global_method_state, ruby_vm_global_method_state); SET(global_constant_state, ruby_vm_global_constant_state); SET(class_serial, ruby_vm_class_serial); + SET(global_cvar_state, ruby_vm_global_cvar_state); #undef SET if (!NIL_P(key)) { /* matched key should return above */ @@ -552,7 +623,6 @@ rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_ MJIT_FUNC_EXPORTED rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp) { - if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) bp(); while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) { if (VM_FRAME_RUBYFRAME_P(cfp)) { return (rb_control_frame_t *)cfp; @@ -650,15 +720,15 @@ static VALUE check_env_value(const rb_env_t *env); static int check_env(const rb_env_t *env) { - fprintf(stderr, "---\n"); - fprintf(stderr, "envptr: %p\n", (void *)&env->ep[0]); - fprintf(stderr, "envval: %10p ", (void *)env->ep[1]); + fputs("---\n", stderr); + ruby_debug_printf("envptr: %p\n", (void *)&env->ep[0]); + ruby_debug_printf("envval: %10p ", (void *)env->ep[1]); dp(env->ep[1]); - fprintf(stderr, "ep: %10p\n", (void *)env->ep); + ruby_debug_printf("ep: %10p\n", (void *)env->ep); if (rb_vm_env_prev_env(env)) { - fprintf(stderr, ">>\n"); + fputs(">>\n", stderr); check_env_value(rb_vm_env_prev_env(env)); - fprintf(stderr, "<<\n"); + fputs("<<\n", stderr); } return 1; } @@ -704,18 +774,17 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co if (!VM_ENV_LOCAL_P(ep)) { const VALUE *prev_ep = VM_ENV_PREV_EP(ep); + if (!VM_ENV_ESCAPED_P(prev_ep)) { + rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - if (!VM_ENV_ESCAPED_P(prev_ep)) { - rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - - while (prev_cfp->ep != prev_ep) { - prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp); - VM_ASSERT(prev_cfp->ep != NULL); - } + while (prev_cfp->ep != prev_ep) { + prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp); + VM_ASSERT(prev_cfp->ep != NULL); + } - vm_make_env_each(ec, prev_cfp); - VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep)); - } + vm_make_env_each(ec, prev_cfp); + VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep)); + } } else { VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep); @@ -801,7 +870,8 @@ rb_vm_env_prev_env(const rb_env_t *env) return NULL; } else { - return VM_ENV_ENVVAL_PTR(VM_ENV_PREV_EP(ep)); + const VALUE *prev_ep = VM_ENV_PREV_EP(ep); + return VM_ENV_ENVVAL_PTR(prev_ep); } } @@ -820,6 +890,7 @@ static void collect_local_variables_in_env(const rb_env_t *env, const struct local_var_list *vars) { do { + if (VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ISOLATED)) break; collect_local_variables_in_iseq(env->iseq, vars); } while ((env = rb_vm_env_prev_env(env)) != NULL); } @@ -870,8 +941,8 @@ vm_proc_create_from_captured(VALUE klass, VM_ASSERT(VM_EP_IN_HEAP_P(GET_EC(), captured->ep)); /* copy block */ - RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self); RB_OBJ_WRITE(procval, &proc->block.as.captured.code.val, captured->code.val); + RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self); rb_vm_block_ep_update(procval, &proc->block, captured->ep); vm_block_type_set(&proc->block, block_type); @@ -924,10 +995,212 @@ rb_proc_dup(VALUE self) GetProcPtr(self, src); procval = proc_create(rb_cProc, &src->block, src->is_from_method, src->is_lambda); + if (RB_OBJ_SHAREABLE_P(self)) FL_SET_RAW(procval, RUBY_FL_SHAREABLE); RB_GC_GUARD(self); /* for: body = rb_proc_dup(body) */ return procval; } +struct collect_outer_variable_name_data { + VALUE ary; + VALUE read_only; + bool yield; + bool isolate; +}; + +static VALUE +ID2NUM(ID id) +{ + if (SIZEOF_VOIDP > SIZEOF_LONG) + return ULL2NUM(id); + else + return ULONG2NUM(id); +} + +static ID +NUM2ID(VALUE num) +{ + if (SIZEOF_VOIDP > SIZEOF_LONG) + return (ID)NUM2ULL(num); + else + return (ID)NUM2ULONG(num); +} + +static enum rb_id_table_iterator_result +collect_outer_variable_names(ID id, VALUE val, void *ptr) +{ + struct collect_outer_variable_name_data *data = (struct collect_outer_variable_name_data *)ptr; + + if (id == rb_intern("yield")) { + data->yield = true; + } + else { + VALUE *store; + if (data->isolate || + val == Qtrue /* write */) { + store = &data->ary; + } + else { + store = &data->read_only; + } + if (*store == Qfalse) *store = rb_ary_new(); + rb_ary_push(*store, ID2NUM(id)); + } + return ID_TABLE_CONTINUE; +} + +static const rb_env_t * +env_copy(const VALUE *src_ep, VALUE read_only_variables) +{ + const rb_env_t *src_env = (rb_env_t *)VM_ENV_ENVVAL(src_ep); + VM_ASSERT(src_env->ep == src_ep); + + VALUE *env_body = ZALLOC_N(VALUE, src_env->env_size); // fill with Qfalse + VALUE *ep = &env_body[src_env->env_size - 2]; + volatile VALUE prev_env = Qnil; + + if (read_only_variables) { + for (int i=RARRAY_LENINT(read_only_variables)-1; i>=0; i--) { + ID id = NUM2ID(RARRAY_AREF(read_only_variables, i)); + + for (unsigned int j=0; jiseq->body->local_table_size; j++) { + if (id == src_env->iseq->body->local_table[j]) { + VALUE v = src_env->env[j]; + if (!rb_ractor_shareable_p(v)) { + VALUE name = rb_id2str(id); + VALUE msg = rb_sprintf("can not make shareable Proc because it can refer" + " unshareable object %+" PRIsVALUE " from ", v); + if (name) + rb_str_catf(msg, "variable `%" PRIsVALUE "'", name); + else + rb_str_cat_cstr(msg, "a hidden variable"); + rb_exc_raise(rb_exc_new_str(rb_eRactorIsolationError, msg)); + } + env_body[j] = v; + rb_ary_delete_at(read_only_variables, i); + break; + } + } + } + } + + ep[VM_ENV_DATA_INDEX_ME_CREF] = src_ep[VM_ENV_DATA_INDEX_ME_CREF]; + ep[VM_ENV_DATA_INDEX_FLAGS] = src_ep[VM_ENV_DATA_INDEX_FLAGS] | VM_ENV_FLAG_ISOLATED; + + if (!VM_ENV_LOCAL_P(src_ep)) { + const VALUE *prev_ep = VM_ENV_PREV_EP(src_env->ep); + const rb_env_t *new_prev_env = env_copy(prev_ep, read_only_variables); + prev_env = (VALUE)new_prev_env; + ep[VM_ENV_DATA_INDEX_SPECVAL] = VM_GUARDED_PREV_EP(new_prev_env->ep); + } + else { + ep[VM_ENV_DATA_INDEX_SPECVAL] = VM_BLOCK_HANDLER_NONE; + } + + const rb_env_t *copied_env = vm_env_new(ep, env_body, src_env->env_size, src_env->iseq); + RB_GC_GUARD(prev_env); + return copied_env; +} + +static void +proc_isolate_env(VALUE self, rb_proc_t *proc, VALUE read_only_variables) +{ + const struct rb_captured_block *captured = &proc->block.as.captured; + const rb_env_t *env = env_copy(captured->ep, read_only_variables); + *((const VALUE **)&proc->block.as.captured.ep) = env->ep; + RB_OBJ_WRITTEN(self, Qundef, env); +} + +static VALUE +proc_shared_outer_variables(struct rb_id_table *outer_variables, bool isolate, const char *message) +{ + struct collect_outer_variable_name_data data = { + .isolate = isolate, + .ary = Qfalse, + .read_only = Qfalse, + .yield = false, + }; + rb_id_table_foreach(outer_variables, collect_outer_variable_names, (void *)&data); + + if (data.ary != Qfalse) { + VALUE str = rb_sprintf("can not %s because it accesses outer variables", message); + VALUE ary = data.ary; + const char *sep = " ("; + for (long i = 0; i < RARRAY_LEN(ary); i++) { + VALUE name = rb_id2str(NUM2ID(RARRAY_AREF(ary, i))); + if (!name) continue; + rb_str_cat_cstr(str, sep); + sep = ", "; + rb_str_append(str, name); + } + if (*sep == ',') rb_str_cat_cstr(str, ")"); + rb_str_cat_cstr(str, data.yield ? " and uses `yield'." : "."); + rb_exc_raise(rb_exc_new_str(rb_eArgError, str)); + } + else if (data.yield) { + rb_raise(rb_eArgError, "can not %s because it uses `yield'.", message); + } + + return data.read_only; +} + +VALUE +rb_proc_isolate_bang(VALUE self) +{ + const rb_iseq_t *iseq = vm_proc_iseq(self); + + if (iseq) { + rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self); + if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet"); + + if (iseq->body->outer_variables) { + proc_shared_outer_variables(iseq->body->outer_variables, true, "isolate a Proc"); + } + + proc_isolate_env(self, proc, Qfalse); + proc->is_isolated = TRUE; + } + + FL_SET_RAW(self, RUBY_FL_SHAREABLE); + return self; +} + +VALUE +rb_proc_isolate(VALUE self) +{ + VALUE dst = rb_proc_dup(self); + rb_proc_isolate_bang(dst); + return dst; +} + +VALUE +rb_proc_ractor_make_shareable(VALUE self) +{ + const rb_iseq_t *iseq = vm_proc_iseq(self); + + if (iseq) { + rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self); + if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet"); + + if (!rb_ractor_shareable_p(vm_block_self(&proc->block))) { + rb_raise(rb_eRactorIsolationError, + "Proc's self is not shareable: %" PRIsVALUE, + self); + } + + VALUE read_only_variables = Qfalse; + + if (iseq->body->outer_variables) { + read_only_variables = + proc_shared_outer_variables(iseq->body->outer_variables, false, "make a Proc shareable"); + } + + proc_isolate_env(self, proc, read_only_variables); + proc->is_isolated = TRUE; + } + + FL_SET_RAW(self, RUBY_FL_SHAREABLE); + return self; +} MJIT_FUNC_EXPORTED VALUE rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda) @@ -992,22 +1265,21 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I const rb_iseq_t *base_iseq, *iseq; rb_ast_body_t ast; NODE tmp_node; - ID minibuf[4], *dyns = minibuf; - VALUE idtmp = 0; if (dyncount < 0) return 0; base_block = &bind->block; base_iseq = vm_block_iseq(base_block); - if (dyncount >= numberof(minibuf)) dyns = ALLOCV_N(ID, idtmp, dyncount + 1); + VALUE idtmp = 0; + rb_ast_id_table_t *dyns = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + dyncount * sizeof(ID)); + dyns->size = dyncount; + MEMCPY(dyns->ids, dynvars, ID, dyncount); - dyns[0] = dyncount; - MEMCPY(dyns + 1, dynvars, ID, dyncount); rb_node_init(&tmp_node, NODE_SCOPE, (VALUE)dyns, 0, 0); ast.root = &tmp_node; ast.compile_option = 0; - ast.line_count = -1; + ast.script_lines = INT2FIX(-1); if (base_iseq) { iseq = rb_iseq_new(&ast, base_iseq->body->location.label, path, realpath, base_iseq, ISEQ_TYPE_EVAL); @@ -1041,7 +1313,7 @@ invoke_block(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, cons ec->cfp->sp + arg_size, iseq->body->local_table_size - arg_size, iseq->body->stack_max); - return vm_exec(ec, TRUE); + return vm_exec(ec, true); } static VALUE @@ -1050,7 +1322,6 @@ invoke_bmethod(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, co /* bmethod */ int arg_size = iseq->body->param.size; VALUE ret; - rb_hook_list_t *hooks; VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD); @@ -1062,24 +1333,9 @@ invoke_bmethod(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, co iseq->body->local_table_size - arg_size, iseq->body->stack_max); - RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id); - EXEC_EVENT_HOOK(ec, RUBY_EVENT_CALL, self, me->def->original_id, me->called_id, me->owner, Qnil); - - if (UNLIKELY((hooks = me->def->body.bmethod.hooks) != NULL) && - hooks->events & RUBY_EVENT_CALL) { - rb_exec_event_hook_orig(ec, hooks, RUBY_EVENT_CALL, self, - me->def->original_id, me->called_id, me->owner, Qnil, FALSE); - } VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH); - ret = vm_exec(ec, TRUE); + ret = vm_exec(ec, true); - EXEC_EVENT_HOOK(ec, RUBY_EVENT_RETURN, self, me->def->original_id, me->called_id, me->owner, ret); - if ((hooks = me->def->body.bmethod.hooks) != NULL && - hooks->events & RUBY_EVENT_RETURN) { - rb_exec_event_hook_orig(ec, hooks, RUBY_EVENT_RETURN, self, - me->def->original_id, me->called_id, me->owner, ret, FALSE); - } - RUBY_DTRACE_METHOD_RETURN_HOOK(ec, me->owner, me->def->original_id); return ret; } @@ -1176,9 +1432,7 @@ vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, int static VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat) { - return invoke_block_from_c_bh(ec, check_block_handler(ec), - argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE, - NULL, FALSE, FALSE); + return vm_yield_with_cref(ec, argc, argv, kw_splat, NULL, FALSE); } static VALUE @@ -1215,9 +1469,17 @@ invoke_block_from_c_proc(rb_execution_context_t *ec, const rb_proc_t *proc, case block_type_iseq: return invoke_iseq_block_from_c(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, NULL, is_lambda, me); case block_type_ifunc: - if (kw_splat == 1 && RHASH_EMPTY_P(argv[argc-1])) { - argc--; - kw_splat = 2; + if (kw_splat == 1) { + VALUE keyword_hash = argv[argc-1]; + if (!RB_TYPE_P(keyword_hash, T_HASH)) { + keyword_hash = rb_to_hash_type(keyword_hash); + } + if (RHASH_EMPTY_P(keyword_hash)) { + argc--; + } + else { + ((VALUE *)argv)[argc-1] = rb_hash_dup(keyword_hash); + } } return vm_yield_with_cfunc(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, me); case block_type_symbol: @@ -1260,6 +1522,20 @@ rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, } } +VALUE +rb_vm_invoke_proc_with_self(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, + int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler) +{ + vm_block_handler_verify(passed_block_handler); + + if (proc->is_from_method) { + return rb_vm_invoke_bmethod(ec, proc, self, argc, argv, kw_splat, passed_block_handler, NULL); + } + else { + return vm_invoke_proc(ec, proc, self, argc, argv, kw_splat, passed_block_handler); + } +} + /* special variable */ static rb_control_frame_t * @@ -1326,7 +1602,6 @@ rb_lastline_set(VALUE val) /* misc */ -/* in intern.h */ const char * rb_sourcefile(void) { @@ -1341,7 +1616,6 @@ rb_sourcefile(void) } } -/* in intern.h */ int rb_sourceline(void) { @@ -1393,6 +1667,7 @@ rb_vm_cref_replace_with_duplicated_cref(void) const rb_execution_context_t *ec = GET_EC(); const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); rb_cref_t *cref = vm_cref_replace_with_duplicated_cref(cfp->ep); + ASSUME(cref); return cref; } @@ -1556,7 +1831,7 @@ rb_iter_break_value(VALUE val) /* optimization: redefine management */ -static st_table *vm_opt_method_table = 0; +static st_table *vm_opt_method_def_table = 0; static st_table *vm_opt_mid_table = 0; static int @@ -1568,7 +1843,9 @@ vm_redefinition_check_flag(VALUE klass) if (klass == rb_cArray) return ARRAY_REDEFINED_OP_FLAG; if (klass == rb_cHash) return HASH_REDEFINED_OP_FLAG; if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG; +#if 0 if (klass == rb_cTime) return TIME_REDEFINED_OP_FLAG; +#endif if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG; if (klass == rb_cNilClass) return NIL_REDEFINED_OP_FLAG; if (klass == rb_cTrueClass) return TRUE_REDEFINED_OP_FLAG; @@ -1588,8 +1865,13 @@ rb_vm_check_optimizable_mid(VALUE mid) } static int -vm_redefinition_check_method_type(const rb_method_definition_t *def) +vm_redefinition_check_method_type(const rb_method_entry_t *me) { + if (me->called_id != me->def->original_id) { + return FALSE; + } + + const rb_method_definition_t *def = me->def; switch (def->type) { case VM_METHOD_TYPE_CFUNC: case VM_METHOD_TYPE_OPTIMIZED: @@ -1603,15 +1885,18 @@ static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass) { st_data_t bop; - if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN)) { + if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN) && + RB_TYPE_P(RBASIC_CLASS(klass), T_CLASS)) { klass = RBASIC_CLASS(klass); } - if (vm_redefinition_check_method_type(me->def)) { - if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) { - int flag = vm_redefinition_check_flag(klass); - - ruby_vm_redefined_flag[bop] |= flag; - } + if (vm_redefinition_check_method_type(me)) { + if (st_lookup(vm_opt_method_def_table, (st_data_t)me->def, &bop)) { + int flag = vm_redefinition_check_flag(klass); + if (flag != 0) { + rb_yjit_bop_redefined(klass, me, (enum ruby_basic_operators)bop); + ruby_vm_redefined_flag[bop] |= flag; + } + } } } @@ -1639,8 +1924,8 @@ add_opt_method(VALUE klass, ID mid, VALUE bop) { const rb_method_entry_t *me = rb_method_entry_at(klass, mid); - if (me && vm_redefinition_check_method_type(me->def)) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); + if (me && vm_redefinition_check_method_type(me)) { + st_insert(vm_opt_method_def_table, (st_data_t)me->def, (st_data_t)bop); st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue); } else { @@ -1654,7 +1939,7 @@ vm_init_redefined_flag(void) ID mid; VALUE bop; - vm_opt_method_table = st_init_numtable(); + vm_opt_method_def_table = st_init_numtable(); vm_opt_mid_table = st_init_numtable(); #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0) @@ -1677,7 +1962,7 @@ vm_init_redefined_flag(void) OP(Length, LENGTH), (C(Array), C(String), C(Hash)); OP(Size, SIZE), (C(Array), C(String), C(Hash)); OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash)); - OP(Succ, SUCC), (C(Integer), C(String), C(Time)); + OP(Succ, SUCC), (C(Integer), C(String)); OP(EqTilde, MATCH), (C(Regexp), C(String)); OP(Freeze, FREEZE), (C(String)); OP(UMinus, UMINUS), (C(String)); @@ -1748,11 +2033,13 @@ frame_name(const rb_control_frame_t *cfp) } #endif +// cfp_returning_with_value: +// Whether cfp is the last frame in the unwinding process for a non-local return. static void hook_before_rewind(rb_execution_context_t *ec, const rb_control_frame_t *cfp, - int will_finish_vm_exec, int state, struct vm_throw_data *err) + bool cfp_returning_with_value, int state, struct vm_throw_data *err) { - if (state == TAG_RAISE && RBASIC_CLASS(err) == rb_eSysStackError) { + if (state == TAG_RAISE && RBASIC(err)->klass == rb_eSysStackError) { return; } else { @@ -1773,32 +2060,36 @@ hook_before_rewind(rb_execution_context_t *ec, const rb_control_frame_t *cfp, break; case VM_FRAME_MAGIC_BLOCK: if (VM_FRAME_BMETHOD_P(ec->cfp)) { - EXEC_EVENT_HOOK(ec, RUBY_EVENT_B_RETURN, ec->cfp->self, 0, 0, 0, frame_return_value(err)); + VALUE bmethod_return_value = frame_return_value(err); + if (cfp_returning_with_value) { + // Non-local return terminating at a BMETHOD control frame. + bmethod_return_value = THROW_DATA_VAL(err); + } + + + EXEC_EVENT_HOOK(ec, RUBY_EVENT_B_RETURN, ec->cfp->self, 0, 0, 0, bmethod_return_value); if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_B_RETURN)) { rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_B_RETURN, - ec->cfp->self, 0, 0, 0, frame_return_value(err), FALSE); + ec->cfp->self, 0, 0, 0, bmethod_return_value, FALSE); } - if (!will_finish_vm_exec) { - const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(ec->cfp); - - /* kick RUBY_EVENT_RETURN at invoke_block_from_c() for bmethod */ - EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_RETURN, ec->cfp->self, - rb_vm_frame_method_entry(ec->cfp)->def->original_id, - rb_vm_frame_method_entry(ec->cfp)->called_id, - rb_vm_frame_method_entry(ec->cfp)->owner, - frame_return_value(err)); - - VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD); - local_hooks = me->def->body.bmethod.hooks; - - if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_RETURN)) { - rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_RETURN, ec->cfp->self, - rb_vm_frame_method_entry(ec->cfp)->def->original_id, - rb_vm_frame_method_entry(ec->cfp)->called_id, - rb_vm_frame_method_entry(ec->cfp)->owner, - frame_return_value(err), TRUE); - } + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(ec->cfp); + + EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_RETURN, ec->cfp->self, + rb_vm_frame_method_entry(ec->cfp)->def->original_id, + rb_vm_frame_method_entry(ec->cfp)->called_id, + rb_vm_frame_method_entry(ec->cfp)->owner, + bmethod_return_value); + + VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD); + local_hooks = me->def->body.bmethod.hooks; + + if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_RETURN)) { + rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_RETURN, ec->cfp->self, + rb_vm_frame_method_entry(ec->cfp)->def->original_id, + rb_vm_frame_method_entry(ec->cfp)->called_id, + rb_vm_frame_method_entry(ec->cfp)->owner, + bmethod_return_value, TRUE); } THROW_DATA_CONSUMED_SET(err); } @@ -1906,7 +2197,7 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, VALUE errinfo, VALUE *initial); VALUE -vm_exec(rb_execution_context_t *ec, int mjit_enable_p) +vm_exec(rb_execution_context_t *ec, bool mjit_enable_p) { enum ruby_tag_type state; VALUE result = Qundef; @@ -1923,7 +2214,7 @@ vm_exec(rb_execution_context_t *ec, int mjit_enable_p) } else { result = ec->errinfo; - rb_ec_raised_reset(ec, RAISED_STACKOVERFLOW); + rb_ec_raised_reset(ec, RAISED_STACKOVERFLOW | RAISED_NOMEMORY); while ((result = vm_exec_handle_exception(ec, state, result, &initial)) == Qundef) { /* caught a jump, exec the handler */ result = vm_exec_core(ec, initial); @@ -1999,7 +2290,8 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, if (catch_iseq == NULL) { ec->errinfo = Qnil; THROW_DATA_CATCH_FRAME_SET(err, cfp + 1); - hook_before_rewind(ec, ec->cfp, TRUE, state, err); + // cfp == escape_cfp here so calling with cfp_returning_with_value = true + hook_before_rewind(ec, ec->cfp, true, state, err); rb_vm_pop_frame(ec); return THROW_DATA_VAL(err); } @@ -2059,10 +2351,16 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, } } } - else if (state == TAG_BREAK && !escape_cfp) { - type = CATCH_TYPE_BREAK; + else if ((state == TAG_BREAK && !escape_cfp) || + (state == TAG_REDO) || + (state == TAG_NEXT)) { + type = (const enum catch_type[TAG_MASK]) { + [TAG_BREAK] = CATCH_TYPE_BREAK, + [TAG_NEXT] = CATCH_TYPE_NEXT, + [TAG_REDO] = CATCH_TYPE_REDO, + /* otherwise = dontcare */ + }[state]; - search_restart_point: ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = UNALIGNED_MEMBER_PTR(ct, entries[i]); @@ -2092,14 +2390,6 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, } } } - else if (state == TAG_REDO) { - type = CATCH_TYPE_REDO; - goto search_restart_point; - } - else if (state == TAG_NEXT) { - type = CATCH_TYPE_NEXT; - goto search_restart_point; - } else { ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { @@ -2142,7 +2432,7 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, return Qundef; } else { - hook_before_rewind(ec, ec->cfp, FALSE, state, err); + hook_before_rewind(ec, ec->cfp, (cfp == escape_cfp), state, err); if (VM_FRAME_FINISHED_P(ec->cfp)) { rb_vm_pop_frame(ec); @@ -2165,7 +2455,7 @@ rb_iseq_eval(const rb_iseq_t *iseq) rb_execution_context_t *ec = GET_EC(); VALUE val; vm_set_top_stack(ec, iseq); - val = vm_exec(ec, TRUE); + val = vm_exec(ec, true); return val; } @@ -2176,7 +2466,7 @@ rb_iseq_eval_main(const rb_iseq_t *iseq) VALUE val; vm_set_main_stack(ec, iseq); - val = vm_exec(ec, TRUE); + val = vm_exec(ec, true); return val; } @@ -2235,10 +2525,69 @@ rb_vm_update_references(void *ptr) { if (ptr) { rb_vm_t *vm = ptr; + rb_gc_update_tbl_refs(vm->frozen_strings); + vm->mark_object_ary = rb_gc_location(vm->mark_object_ary); + vm->load_path = rb_gc_location(vm->load_path); + vm->load_path_snapshot = rb_gc_location(vm->load_path_snapshot); + + if (vm->load_path_check_cache) { + vm->load_path_check_cache = rb_gc_location(vm->load_path_check_cache); + } + + vm->expanded_load_path = rb_gc_location(vm->expanded_load_path); + vm->loaded_features = rb_gc_location(vm->loaded_features); + vm->loaded_features_snapshot = rb_gc_location(vm->loaded_features_snapshot); + vm->loaded_features_realpaths = rb_gc_location(vm->loaded_features_realpaths); + vm->top_self = rb_gc_location(vm->top_self); + vm->orig_progname = rb_gc_location(vm->orig_progname); + + rb_gc_update_tbl_refs(vm->overloaded_cme_table); + + if (vm->coverages) { + vm->coverages = rb_gc_location(vm->coverages); + vm->me2counter = rb_gc_location(vm->me2counter); + } + } +} + +void +rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx) +{ + if (ptr) { + rb_vm_t *vm = ptr; + rb_ractor_t *r = 0; + list_for_each(&vm->ractor.set, r, vmlr_node) { + VM_ASSERT(rb_ractor_status_p(r, ractor_blocking) || + rb_ractor_status_p(r, ractor_running)); + if (r->threads.cnt > 0) { + rb_thread_t *th = 0; + list_for_each(&r->threads.set, th, lt_node) { + VM_ASSERT(th != NULL); + rb_execution_context_t * ec = th->ec; + if (ec->vm_stack) { + VALUE *p = ec->vm_stack; + VALUE *sp = ec->cfp->sp; + while (p <= sp) { + if (!rb_special_const_p(*p)) { + cb(*p, ctx); + } + p++; + } + } + } + } + } } } +static enum rb_id_table_iterator_result +vm_mark_negative_cme(VALUE val, void *dmy) +{ + rb_gc_mark(val); + return ID_TABLE_CONTINUE; +} + void rb_vm_mark(void *ptr) { @@ -2246,15 +2595,18 @@ rb_vm_mark(void *ptr) RUBY_GC_INFO("-------------------------------------------------\n"); if (ptr) { rb_vm_t *vm = ptr; - rb_thread_t *th = 0; + rb_ractor_t *r = 0; long i, len; const VALUE *obj_ary; - list_for_each(&vm->living_threads, th, vmlt_node) { - rb_gc_mark(th->self); + list_for_each(&vm->ractor.set, r, vmlr_node) { + // ractor.set only contains blocking or running ractors + VM_ASSERT(rb_ractor_status_p(r, ractor_blocking) || + rb_ractor_status_p(r, ractor_running)); + rb_gc_mark(rb_ractor_self(r)); } - rb_gc_mark(vm->thgroup_default); - rb_gc_mark(vm->mark_object_ary); + + rb_gc_mark_movable(vm->mark_object_ary); len = RARRAY_LEN(vm->mark_object_ary); obj_ary = RARRAY_CONST_PTR(vm->mark_object_ary); @@ -2271,15 +2623,17 @@ rb_vm_mark(void *ptr) obj_ary++; } - rb_gc_mark(vm->load_path); - rb_gc_mark(vm->load_path_snapshot); - RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); - rb_gc_mark(vm->expanded_load_path); - rb_gc_mark(vm->loaded_features); - rb_gc_mark(vm->loaded_features_snapshot); - rb_gc_mark(vm->top_self); - rb_gc_mark(vm->orig_progname); - RUBY_MARK_UNLESS_NULL(vm->coverages); + rb_gc_mark_movable(vm->load_path); + rb_gc_mark_movable(vm->load_path_snapshot); + RUBY_MARK_MOVABLE_UNLESS_NULL(vm->load_path_check_cache); + rb_gc_mark_movable(vm->expanded_load_path); + rb_gc_mark_movable(vm->loaded_features); + rb_gc_mark_movable(vm->loaded_features_snapshot); + rb_gc_mark_movable(vm->loaded_features_realpaths); + rb_gc_mark_movable(vm->top_self); + rb_gc_mark_movable(vm->orig_progname); + RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages); + RUBY_MARK_MOVABLE_UNLESS_NULL(vm->me2counter); /* Prevent classes from moving */ rb_mark_tbl(vm->defined_module_hash); @@ -2287,9 +2641,22 @@ rb_vm_mark(void *ptr) rb_mark_tbl(vm->loading_table); } - rb_hook_list_mark(&vm->global_hooks); + rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd); - rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd); + rb_id_table_foreach_values(vm->negative_cme_table, vm_mark_negative_cme, NULL); + rb_mark_tbl_no_pin(vm->overloaded_cme_table); + for (i=0; iglobal_cc_cache_table[i]; + + if (cc != NULL) { + if (!vm_cc_invalidated_p(cc)) { + rb_gc_mark((VALUE)cc); + } + else { + vm->global_cc_cache_table[i] = NULL; + } + } + } mjit_mark(); } @@ -2309,7 +2676,7 @@ rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls, } int -rb_vm_add_root_module(ID id, VALUE module) +rb_vm_add_root_module(VALUE module) { rb_vm_t *vm = GET_VM(); @@ -2331,10 +2698,11 @@ ruby_vm_destruct(rb_vm_t *vm) RUBY_FREE_ENTER("vm"); if (vm) { - rb_thread_t *th = vm->main_thread; + rb_thread_t *th = vm->ractor.main_thread; struct rb_objspace *objspace = vm->objspace; - vm->main_thread = 0; - if (th) { + vm->ractor.main_thread = NULL; + + if (th) { rb_fiber_reset_root_local_storage(th); thread_free(th); } @@ -2349,11 +2717,12 @@ ruby_vm_destruct(rb_vm_t *vm) st_free_table(vm->frozen_strings); vm->frozen_strings = 0; } - rb_vm_gvl_destroy(vm); RB_ALTSTACK_FREE(vm->main_altstack); if (objspace) { rb_objspace_free(objspace); } + rb_native_mutex_destroy(&vm->waitpid_lock); + rb_native_mutex_destroy(&vm->workqueue_lock); /* after freeing objspace, you *can't* use ruby_xfree() */ ruby_mimfree(vm); ruby_current_vm_ptr = NULL; @@ -2365,20 +2734,17 @@ ruby_vm_destruct(rb_vm_t *vm) static size_t vm_memsize(const void *ptr) { - const rb_vm_t *vmobj = ptr; size_t size = sizeof(rb_vm_t); - size += vmobj->living_thread_num * sizeof(rb_thread_t); + // TODO + // size += vmobj->ractor_num * sizeof(rb_ractor_t); - if (vmobj->defined_strings) { - size += DEFINED_EXPR * sizeof(VALUE); - } return size; } static const rb_data_type_t vm_data_type = { "VM", - {NULL, NULL, vm_memsize,}, + {0, 0, vm_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -2410,7 +2776,7 @@ get_param(const char *name, size_t default_value, size_t min_value) } result = (size_t)(((val -1 + RUBY_VM_SIZE_ALIGN) / RUBY_VM_SIZE_ALIGN) * RUBY_VM_SIZE_ALIGN); } - if (0) fprintf(stderr, "%s: %"PRIuSIZE"\n", name, result); /* debug print */ + if (0) ruby_debug_printf("%s: %"PRIuSIZE"\n", name, result); /* debug print */ return result; } @@ -2423,8 +2789,8 @@ check_machine_stack_size(size_t *sizep) #endif #ifdef PTHREAD_STACK_MIN - if (size < PTHREAD_STACK_MIN) { - *sizep = PTHREAD_STACK_MIN * 2; + if (size < (size_t)PTHREAD_STACK_MIN) { + *sizep = (size_t)PTHREAD_STACK_MIN * 2; } #endif } @@ -2473,11 +2839,21 @@ rb_execution_context_update(const rb_execution_context_t *ec) { /* update VM stack */ if (ec->vm_stack) { + long i; VM_ASSERT(ec->cfp); - + VALUE *p = ec->vm_stack; + VALUE *sp = ec->cfp->sp; rb_control_frame_t *cfp = ec->cfp; rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size); + for (i = 0; i < (long)(sp - p); i++) { + VALUE ref = p[i]; + VALUE update = rb_gc_location(ref); + if (ref != update) { + p[i] = update; + } + } + while (cfp != limit_cfp) { const VALUE *ep = cfp->ep; cfp->self = rb_gc_location(cfp->self); @@ -2485,9 +2861,14 @@ rb_execution_context_update(const rb_execution_context_t *ec) cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code); if (!VM_ENV_LOCAL_P(ep)) { - VALUE *prev_ep = (VALUE *)VM_ENV_PREV_EP(ep); + const VALUE *prev_ep = VM_ENV_PREV_EP(ep); if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) { - prev_ep[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]); + VM_FORCE_WRITE(&prev_ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV])); + } + + if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) { + VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(ep[VM_ENV_DATA_INDEX_ENV])); + VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ME_CREF], rb_gc_location(ep[VM_ENV_DATA_INDEX_ME_CREF])); } } @@ -2496,6 +2877,13 @@ rb_execution_context_update(const rb_execution_context_t *ec) } } +static enum rb_id_table_iterator_result +mark_local_storage_i(VALUE local, void *data) +{ + rb_gc_mark(local); + return ID_TABLE_CONTINUE; +} + void rb_execution_context_mark(const rb_execution_context_t *ec) { @@ -2507,6 +2895,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec) rb_control_frame_t *cfp = ec->cfp; rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size); + VM_ASSERT(sp == ec->cfp->sp); rb_gc_mark_vm_stack_values((long)(sp - p), p); while (cfp != limit_cfp) { @@ -2516,12 +2905,17 @@ rb_execution_context_mark(const rb_execution_context_t *ec) rb_gc_mark_movable((VALUE)cfp->iseq); rb_gc_mark_movable((VALUE)cfp->block_code); - if (!VM_ENV_LOCAL_P(ep)) { - const VALUE *prev_ep = VM_ENV_PREV_EP(ep); - if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) { + if (!VM_ENV_LOCAL_P(ep)) { + const VALUE *prev_ep = VM_ENV_PREV_EP(ep); + if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) { rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]); + } + + if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) { + rb_gc_mark_movable(ep[VM_ENV_DATA_INDEX_ENV]); + rb_gc_mark(ep[VM_ENV_DATA_INDEX_ME_CREF]); } - } + } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } @@ -2539,7 +2933,9 @@ rb_execution_context_mark(const rb_execution_context_t *ec) RUBY_MARK_UNLESS_NULL(ec->errinfo); RUBY_MARK_UNLESS_NULL(ec->root_svar); - rb_mark_tbl(ec->local_storage); + if (ec->local_storage) { + rb_id_table_foreach_values(ec->local_storage, mark_local_storage_i, NULL); + } RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash); RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace); RUBY_MARK_UNLESS_NULL(ec->private_const_reference); @@ -2554,11 +2950,12 @@ static void thread_compact(void *ptr) { rb_thread_t *th = ptr; - rb_fiber_update_self(th->ec->fiber_ptr); - if (th->root_fiber) rb_fiber_update_self(th->root_fiber); + th->self = rb_gc_location(th->self); - rb_execution_context_update(th->ec); + if (!th->root_fiber) { + rb_execution_context_update(th->ec); + } } static void @@ -2571,6 +2968,7 @@ thread_mark(void *ptr) /* mark ruby objects */ switch (th->invoke_type) { case thread_invoke_type_proc: + case thread_invoke_type_ractor_proc: RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.proc); RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.args); break; @@ -2581,6 +2979,7 @@ thread_mark(void *ptr) break; } + rb_gc_mark(rb_ractor_self(th->ractor)); RUBY_MARK_UNLESS_NULL(th->thgroup); RUBY_MARK_UNLESS_NULL(th->value); RUBY_MARK_UNLESS_NULL(th->pending_interrupt_queue); @@ -2596,6 +2995,8 @@ thread_mark(void *ptr) RUBY_MARK_UNLESS_NULL(th->locking_mutex); RUBY_MARK_UNLESS_NULL(th->name); + RUBY_MARK_UNLESS_NULL(th->scheduler); + RUBY_MARK_LEAVE("thread"); } @@ -2614,8 +3015,8 @@ thread_free(void *ptr) rb_threadptr_root_fiber_release(th); - if (th->vm && th->vm->main_thread == th) { - RUBY_GC_INFO("main thread\n"); + if (th->vm && th->vm->ractor.main_thread == th) { + RUBY_GC_INFO("MRI main thread\n"); } else { ruby_xfree(ptr); @@ -2634,7 +3035,7 @@ thread_memsize(const void *ptr) size += th->ec->vm_stack_size * sizeof(VALUE); } if (th->ec->local_storage) { - size += st_memsize(th->ec->local_storage); + size += rb_id_table_memsize(th->ec->local_storage); } return size; } @@ -2654,12 +3055,7 @@ const rb_data_type_t ruby_threadptr_data_type = { VALUE rb_obj_is_thread(VALUE obj) { - if (rb_typeddata_is_kind_of(obj, &thread_data_type)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(rb_typeddata_is_kind_of(obj, &thread_data_type)); } static VALUE @@ -2710,6 +3106,10 @@ th_init(rb_thread_t *th, VALUE self) th->self = self; rb_threadptr_root_fiber_setup(th); + /* All threads are blocking until a non-blocking fiber is scheduled */ + th->blocking = 1; + th->scheduler = Qnil; + if (self == 0) { size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE); rb_ec_initialize_vm_stack(th->ec, ALLOC_N(VALUE, size), size); @@ -2730,25 +3130,31 @@ th_init(rb_thread_t *th, VALUE self) th->thread_id_string[0] = '\0'; #endif + th->value = Qundef; + #if OPT_CALL_THREADED_CODE th->retval = Qundef; #endif th->name = Qnil; th->report_on_exception = th->vm->thread_report_on_exception; + th->ext_config.ractor_safe = true; } static VALUE ruby_thread_init(VALUE self) { - rb_thread_t *th = rb_thread_ptr(self); - rb_vm_t *vm = GET_THREAD()->vm; + rb_thread_t *th = GET_THREAD(); + rb_thread_t *target_th = rb_thread_ptr(self); + rb_vm_t *vm = th->vm; - th->vm = vm; - th_init(th, self); + target_th->vm = vm; + th_init(target_th, self); + + target_th->top_wrapper = 0; + target_th->top_self = rb_vm_top_self(); + target_th->ec->root_svar = Qfalse; + target_th->ractor = th->ractor; - th->top_wrapper = 0; - th->top_self = rb_vm_top_self(); - th->ec->root_svar = Qfalse; return self; } @@ -2791,8 +3197,9 @@ static VALUE m_core_undef_method(VALUE self, VALUE cbase, VALUE sym) { REWIND_CFP({ - rb_undef(cbase, SYM2ID(sym)); - rb_clear_method_cache_by_class(self); + ID mid = SYM2ID(sym); + rb_undef(cbase, mid); + rb_clear_method_cache(self, mid); }); return Qnil; } @@ -2839,6 +3246,24 @@ m_core_hash_merge_kwd(VALUE recv, VALUE hash, VALUE kw) return hash; } +static VALUE +m_core_make_shareable(VALUE recv, VALUE obj) +{ + return rb_ractor_make_shareable(obj); +} + +static VALUE +m_core_make_shareable_copy(VALUE recv, VALUE obj) +{ + return rb_ractor_make_shareable_copy(obj); +} + +static VALUE +m_core_ensure_shareable(VALUE recv, VALUE obj, VALUE name) +{ + return rb_ractor_ensure_shareable(obj, name); +} + static VALUE core_hash_merge_kwd(VALUE hash, VALUE kw) { @@ -2850,7 +3275,7 @@ core_hash_merge_kwd(VALUE hash, VALUE kw) static VALUE mjit_enabled_p(VALUE _) { - return mjit_enabled ? Qtrue : Qfalse; + return RBOOL(mjit_enabled); } static VALUE @@ -2894,7 +3319,7 @@ static VALUE nsdr(VALUE self) { VALUE ary = rb_ary_new(); -#if HAVE_BACKTRACE +#ifdef HAVE_BACKTRACE #include #define MAX_NATIVE_TRACE 1024 static void *trace[MAX_NATIVE_TRACE]; @@ -2947,13 +3372,67 @@ f_lambda(VALUE _) return rb_block_lambda(); } +static VALUE +f_sprintf(int c, const VALUE *v, VALUE _) +{ + return rb_f_sprintf(c, v); +} + +static VALUE +vm_mtbl(VALUE self, VALUE obj, VALUE sym) +{ + vm_mtbl_dump(CLASS_OF(obj), RTEST(sym) ? SYM2ID(sym) : 0); + return Qnil; +} + +static VALUE +vm_mtbl2(VALUE self, VALUE obj, VALUE sym) +{ + vm_mtbl_dump(obj, RTEST(sym) ? SYM2ID(sym) : 0); + return Qnil; +} + +/* + * call-seq: + * RubyVM.keep_script_lines -> true or false + * + * Return current +keep_script_lines+ status. Now it only returns + * +true+ of +false+, but it can return other objects in future. + * + * Note that this is an API for ruby internal use, debugging, + * and research. Do not use this for any other purpose. + * The compatibility is not guaranteed. + */ +static VALUE +vm_keep_script_lines(VALUE self) +{ + return RBOOL(ruby_vm_keep_script_lines); +} + +/* + * call-seq: + * RubyVM.keep_script_lines = true / false + * + * It set +keep_script_lines+ flag. If the flag is set, all + * loaded scripts are recorded in a interpreter process. + * + * Note that this is an API for ruby internal use, debugging, + * and research. Do not use this for any other purpose. + * The compatibility is not guaranteed. + */ +static VALUE +vm_keep_script_lines_set(VALUE self, VALUE flags) +{ + ruby_vm_keep_script_lines = RTEST(flags); + return flags; +} + void Init_VM(void) { VALUE opts; VALUE klass; VALUE fcore; - VALUE mjit; /* * Document-class: RubyVM @@ -2970,6 +3449,9 @@ Init_VM(void) rb_undef_alloc_func(rb_cRubyVM); rb_undef_method(CLASS_OF(rb_cRubyVM), "new"); rb_define_singleton_method(rb_cRubyVM, "stat", vm_stat, -1); + rb_define_singleton_method(rb_cRubyVM, "keep_script_lines", vm_keep_script_lines, 0); + rb_define_singleton_method(rb_cRubyVM, "keep_script_lines=", vm_keep_script_lines_set, 1); + #if USE_DEBUG_COUNTER rb_define_singleton_method(rb_cRubyVM, "reset_debug_counters", rb_debug_counter_reset, 0); rb_define_singleton_method(rb_cRubyVM, "show_debug_counters", rb_debug_counter_show, 0); @@ -2977,6 +3459,7 @@ Init_VM(void) /* FrozenCore (hidden) */ fcore = rb_class_new(rb_cBasicObject); + rb_set_class_path(fcore, rb_cRubyVM, "FrozenCore"); RBASIC(fcore)->flags = T_ICLASS; klass = rb_singleton_class(fcore); rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3); @@ -2986,8 +3469,12 @@ Init_VM(void) rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1); rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, 2); rb_define_method_id(klass, id_core_raise, f_raise, -1); + rb_define_method_id(klass, id_core_sprintf, f_sprintf, -1); rb_define_method_id(klass, idProc, f_proc, 0); rb_define_method_id(klass, idLambda, f_lambda, 0); + rb_define_method(klass, "make_shareable", m_core_make_shareable, 1); + rb_define_method(klass, "make_shareable_copy", m_core_make_shareable_copy, 1); + rb_define_method(klass, "ensure_shareable", m_core_ensure_shareable, 2); rb_obj_freeze(fcore); RBASIC_CLEAR_CLASS(klass); rb_obj_freeze(klass); @@ -2998,7 +3485,7 @@ Init_VM(void) * Provides access to the Method JIT compiler of MRI. * Of course, this module is MRI specific. */ - mjit = rb_define_module_under(rb_cRubyVM, "MJIT"); + VALUE mjit = rb_define_module_under(rb_cRubyVM, "MJIT"); rb_define_singleton_method(mjit, "enabled?", mjit_enabled_p, 0); rb_define_singleton_method(mjit, "pause", mjit_pause_m, -1); rb_define_singleton_method(mjit, "resume", mjit_resume_m, 0); @@ -3234,9 +3721,13 @@ Init_VM(void) #if VMDEBUG rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0); rb_define_singleton_method(rb_cRubyVM, "NSDR", nsdr, 0); + rb_define_singleton_method(rb_cRubyVM, "mtbl", vm_mtbl, 2); + rb_define_singleton_method(rb_cRubyVM, "mtbl2", vm_mtbl2, 2); #else (void)sdr; (void)nsdr; + (void)vm_mtbl; + (void)vm_mtbl2; #endif /* VM bootstrap: phase 2 */ @@ -3246,38 +3737,40 @@ Init_VM(void) VALUE filename = rb_fstring_lit("
      "); const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); + // Ractor setup + rb_ractor_main_setup(vm, th->ractor, th); + /* create vm object */ vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm); /* create main thread */ th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); - vm->main_thread = th; - vm->running_thread = th; + vm->ractor.main_thread = th; + vm->ractor.main_ractor = th->ractor; th->vm = vm; th->top_wrapper = 0; th->top_self = rb_vm_top_self(); - rb_thread_set_current(th); - - rb_vm_living_threads_insert(vm, th); - rb_gc_register_mark_object((VALUE)iseq); + rb_gc_register_mark_object((VALUE)iseq); th->ec->cfp->iseq = iseq; th->ec->cfp->pc = iseq->body->iseq_encoded; th->ec->cfp->self = th->top_self; VM_ENV_FLAGS_UNSET(th->ec->cfp->ep, VM_FRAME_FLAG_CFRAME); - VM_STACK_ENV_WRITE(th->ec->cfp->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE)); + VM_STACK_ENV_WRITE(th->ec->cfp->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE, FALSE)); /* * The Binding of the top level scope */ rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new()); + + rb_objspace_gc_enable(vm->objspace); } vm_init_redefined_flag(); rb_block_param_proxy = rb_obj_alloc(rb_cObject); - rb_add_method(rb_singleton_class(rb_block_param_proxy), idCall, VM_METHOD_TYPE_OPTIMIZED, - (void *)OPTIMIZED_METHOD_TYPE_BLOCK_CALL, METHOD_VISI_PUBLIC); + rb_add_method_optimized(rb_singleton_class(rb_block_param_proxy), idCall, + OPTIMIZED_METHOD_TYPE_BLOCK_CALL, 0, METHOD_VISI_PUBLIC); rb_obj_freeze(rb_block_param_proxy); rb_gc_register_mark_object(rb_block_param_proxy); @@ -3288,7 +3781,7 @@ Init_VM(void) void rb_vm_set_progname(VALUE filename) { - rb_thread_t *th = GET_VM()->main_thread; + rb_thread_t *th = GET_VM()->ractor.main_thread; rb_control_frame_t *cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size); --cfp; @@ -3304,7 +3797,7 @@ Init_BareVM(void) rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm)); rb_thread_t * th = ruby_mimmalloc(sizeof(*th)); if (!vm || !th) { - fprintf(stderr, "[FATAL] failed to allocate memory\n"); + fputs("[FATAL] failed to allocate memory\n", stderr); exit(EXIT_FAILURE); } MEMZERO(th, rb_thread_t, 1); @@ -3312,12 +3805,19 @@ Init_BareVM(void) vm->objspace = rb_objspace_alloc(); ruby_current_vm_ptr = vm; + vm->negative_cme_table = rb_id_table_create(16); + vm->overloaded_cme_table = st_init_numtable(); Init_native_thread(th); th->vm = vm; th_init(th, 0); - rb_thread_set_current_raw(th); + vm->ractor.main_ractor = th->ractor = rb_ractor_main_alloc(); + rb_ractor_set_current_ec(th->ractor, th->ec); ruby_thread_init_stack(th); + + rb_native_mutex_initialize(&vm->ractor.sync.lock); + rb_native_cond_initialize(&vm->ractor.sync.barrier_cond); + rb_native_cond_initialize(&vm->ractor.sync.terminate_cond); } void @@ -3331,8 +3831,6 @@ Init_vm_objects(void) vm->mark_object_ary = rb_ary_tmp_new(128); vm->loading_table = st_init_strtable(); vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 10000); - - rb_objspace_gc_enable(vm->objspace); } /* top self */ @@ -3359,28 +3857,18 @@ Init_top_self(void) rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s"); } -static VALUE * -ruby_vm_verbose_ptr(rb_vm_t *vm) -{ - return &vm->verbose; -} - -static VALUE * -ruby_vm_debug_ptr(rb_vm_t *vm) -{ - return &vm->debug; -} - VALUE * rb_ruby_verbose_ptr(void) { - return ruby_vm_verbose_ptr(GET_VM()); + rb_ractor_t *cr = GET_RACTOR(); + return &cr->verbose; } VALUE * rb_ruby_debug_ptr(void) { - return ruby_vm_debug_ptr(GET_VM()); + rb_ractor_t *cr = GET_RACTOR(); + return &cr->debug; } /* iseq.c */ @@ -3423,11 +3911,11 @@ vm_analysis_insn(int insn) CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN"); CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM"); uh = rb_const_get(rb_cRubyVM, usage_hash); - if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) { + if (NIL_P(ihash = rb_hash_aref(uh, INT2FIX(insn)))) { ihash = rb_hash_new(); HASH_ASET(uh, INT2FIX(insn), ihash); } - if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) { + if (NIL_P(cv = rb_hash_aref(ihash, INT2FIX(-1)))) { cv = INT2FIX(0); } HASH_ASET(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1)); @@ -3443,7 +3931,7 @@ vm_analysis_insn(int insn) bi = rb_ary_new4(2, &ary[0]); uh = rb_const_get(rb_cRubyVM, bigram_hash); - if ((cv = rb_hash_aref(uh, bi)) == Qnil) { + if (NIL_P(cv = rb_hash_aref(uh, bi))) { cv = INT2FIX(0); } HASH_ASET(uh, bi, INT2FIX(FIX2INT(cv) + 1)); @@ -3465,11 +3953,11 @@ vm_analysis_operand(int insn, int n, VALUE op) CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN"); uh = rb_const_get(rb_cRubyVM, usage_hash); - if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) { + if (NIL_P(ihash = rb_hash_aref(uh, INT2FIX(insn)))) { ihash = rb_hash_new(); HASH_ASET(uh, INT2FIX(insn), ihash); } - if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) { + if (NIL_P(ophash = rb_hash_aref(ihash, INT2FIX(n)))) { ophash = rb_hash_new(); HASH_ASET(ihash, INT2FIX(n), ophash); } @@ -3477,7 +3965,7 @@ vm_analysis_operand(int insn, int n, VALUE op) valstr = rb_insn_operand_intern(GET_EC()->cfp->iseq, insn, n, op, 0, 0, 0, 0); /* set count */ - if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) { + if (NIL_P(cv = rb_hash_aref(ophash, valstr))) { cv = INT2FIX(0); } HASH_ASET(ophash, valstr, INT2FIX(FIX2INT(cv) + 1)); @@ -3521,7 +4009,7 @@ vm_analysis_register(int reg, int isset) valstr = syms[reg][isset]; uh = rb_const_get(rb_cRubyVM, usage_hash); - if ((cv = rb_hash_aref(uh, valstr)) == Qnil) { + if (NIL_P(cv = rb_hash_aref(uh, valstr))) { cv = INT2FIX(0); } HASH_ASET(uh, valstr, INT2FIX(FIX2INT(cv) + 1)); @@ -3585,24 +4073,21 @@ usage_analysis_register_stop(VALUE self) static VALUE usage_analysis_insn_running(VALUE self) { - if (ruby_vm_collect_usage_func_insn == 0) return Qfalse; - return Qtrue; + return RBOOL(ruby_vm_collect_usage_func_insn != 0); } /* :nodoc: */ static VALUE usage_analysis_operand_running(VALUE self) { - if (ruby_vm_collect_usage_func_operand == 0) return Qfalse; - return Qtrue; + return RBOOL(ruby_vm_collect_usage_func_operand != 0); } /* :nodoc: */ static VALUE usage_analysis_register_running(VALUE self) { - if (ruby_vm_collect_usage_func_register == 0) return Qfalse; - return Qtrue; + return RBOOL(ruby_vm_collect_usage_func_register != 0); } /* :nodoc: */ @@ -3654,9 +4139,9 @@ usage_analysis_register_clear(VALUE self) #else -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = NULL; -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = NULL; -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = NULL; +MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = 0; +MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = 0; +MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = 0; #endif @@ -3701,6 +4186,18 @@ vm_collect_usage_register(int reg, int isset) } #endif +MJIT_FUNC_EXPORTED const struct rb_callcache * +rb_vm_empty_cc(void) +{ + return &vm_empty_cc; +} + +MJIT_FUNC_EXPORTED const struct rb_callcache * +rb_vm_empty_cc_for_super(void) +{ + return &vm_empty_cc_for_super; +} + #endif /* #ifndef MJIT_HEADER */ #include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */ diff --git a/ruby/vm_args.c b/ruby/vm_args.c index cf0328d4b..58ec4a082 100644 --- a/ruby/vm_args.c +++ b/ruby/vm_args.c @@ -12,7 +12,7 @@ NORETURN(static void raise_argument_error(rb_execution_context_t *ec, const rb_i NORETURN(static void argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc)); NORETURN(static void argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const char *error, const VALUE keys)); VALUE rb_keyword_error_new(const char *error, VALUE keys); /* class.c */ -static VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, +static VALUE method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat); #if !defined(_MSC_VER) || !defined(MJIT_HEADER) MJIT_FUNC_EXPORTED @@ -27,7 +27,7 @@ struct args_info { /* additional args info */ int rest_index; int rest_dupped; - const struct rb_call_info_kw_arg *kw_arg; + const struct rb_callinfo_kwarg *kw_arg; VALUE *kw_argv; VALUE rest; }; @@ -187,128 +187,10 @@ args_rest_array(struct args_info *args) return ary; } -#define KW_HASH_HAS_NO_KEYS 0 -#define KW_HASH_HAS_SYMBOL_KEY 1 -#define KW_HASH_HAS_OTHER_KEY 2 -#define KW_HASH_HAS_BOTH_KEYS 3 - -static int -keyword_hash_symbol_other_iter(st_data_t key, st_data_t val, st_data_t arg) -{ - *(int*)arg |= SYMBOL_P((VALUE)key) ? KW_HASH_HAS_SYMBOL_KEY : KW_HASH_HAS_OTHER_KEY; - - if ((*(int*)arg & KW_HASH_HAS_BOTH_KEYS) == KW_HASH_HAS_BOTH_KEYS) { - return ST_STOP; - } - - return ST_CONTINUE; -} - -static int -keyword_hash_symbol_other(VALUE hash) -{ - int symbol_other = KW_HASH_HAS_NO_KEYS; - rb_hash_stlike_foreach(hash, keyword_hash_symbol_other_iter, (st_data_t)(&symbol_other)); - return symbol_other; -} - -static int -keyword_hash_split_iter(st_data_t key, st_data_t val, st_data_t arg) -{ - if (SYMBOL_P((VALUE)key)) { - rb_hash_aset((VALUE)arg, (VALUE)key, (VALUE)val); - return ST_DELETE; - } - - return ST_CONTINUE; -} - -static void -keyword_hash_split(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr) -{ - *kw_hash_ptr = rb_hash_new(); - rb_hash_stlike_foreach(*rest_hash_ptr, keyword_hash_split_iter, (st_data_t)(*kw_hash_ptr)); -} - -static int -keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr, int check_only_symbol) -{ - *rest_hash_ptr = rb_check_hash_type(*kw_hash_ptr); - - if (!NIL_P(*rest_hash_ptr)) { - if (check_only_symbol) { - switch (keyword_hash_symbol_other(*rest_hash_ptr)) { - case KW_HASH_HAS_NO_KEYS: - case KW_HASH_HAS_SYMBOL_KEY: - break; - case KW_HASH_HAS_OTHER_KEY: - *kw_hash_ptr = Qnil; - return FALSE; - case KW_HASH_HAS_BOTH_KEYS: - *rest_hash_ptr = rb_hash_dup(*rest_hash_ptr); - keyword_hash_split(kw_hash_ptr, rest_hash_ptr); - return TRUE; - } - } - *kw_hash_ptr = *rest_hash_ptr; - *rest_hash_ptr = Qfalse; - return TRUE; - } - else { - *kw_hash_ptr = Qnil; - return FALSE; - } -} - -static VALUE -args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, int check_only_symbol) -{ - VALUE rest_hash; - - if (args->rest == Qfalse) { - from_argv: - VM_ASSERT(args->argc > 0); - *kw_hash_ptr = args->argv[args->argc-1]; - - if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) { - if (rest_hash) { - args->argv[args->argc-1] = rest_hash; - } - else { - args->argc--; - return TRUE; - } - } - } - else { - long len = RARRAY_LEN(args->rest); - - if (len > 0) { - *kw_hash_ptr = RARRAY_AREF(args->rest, len - 1); - - if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) { - if (rest_hash) { - RARRAY_ASET(args->rest, len - 1, rest_hash); - } - else { - arg_rest_dup(args); - rb_ary_pop(args->rest); - return TRUE; - } - } - } - else { - goto from_argv; - } - } - - return FALSE; -} - static int args_kw_argv_to_hash(struct args_info *args) { - const struct rb_call_info_kw_arg *kw_arg = args->kw_arg; + const struct rb_callinfo_kwarg *kw_arg = args->kw_arg; const VALUE *const passed_keywords = kw_arg->keywords; const int kw_len = kw_arg->keyword_len; VALUE h = rb_hash_new_with_size(kw_len); @@ -326,29 +208,6 @@ args_kw_argv_to_hash(struct args_info *args) return args->argc; } -static void -args_stored_kw_argv_to_hash(struct args_info *args) -{ - int i; - const struct rb_call_info_kw_arg *kw_arg = args->kw_arg; - const VALUE *const passed_keywords = kw_arg->keywords; - const int passed_keyword_len = kw_arg->keyword_len; - VALUE h = rb_hash_new_with_size(passed_keyword_len); - - for (i=0; ikw_argv[i]); - } - args->kw_argv = NULL; - - if (args->rest) { - arg_rest_dup(args); - rb_ary_push(args->rest, h); - } - else { - args->argv[args->argc++] = h; - } -} - static inline void args_setup_lead_parameters(struct args_info *args, int argc, VALUE *locals) { @@ -541,9 +400,15 @@ args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *cons } static inline void -args_setup_kw_rest_parameter(VALUE keyword_hash, VALUE *locals) +args_setup_kw_rest_parameter(VALUE keyword_hash, VALUE *locals, int kw_flag) { - locals[0] = NIL_P(keyword_hash) ? rb_hash_new() : rb_hash_dup(keyword_hash); + if (NIL_P(keyword_hash)) { + keyword_hash = rb_hash_new(); + } + else if (!(kw_flag & VM_CALL_KW_SPLAT_MUT)) { + keyword_hash = rb_hash_dup(keyword_hash); + } + locals[0] = keyword_hash; } static inline void @@ -570,171 +435,40 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr) } static inline int -ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq) -{ - if (!(iseq->body->param.flags.has_kw) && - !(iseq->body->param.flags.has_kwrest)) { - keyword_hash = rb_check_hash_type(keyword_hash); - - if (!NIL_P(keyword_hash) && RHASH_EMPTY_P(keyword_hash)) { - return 1; - } - } - - return 0; -} - -VALUE rb_iseq_location(const rb_iseq_t *iseq); - -/* -- Remove In 3.0 -- */ - -/* This is a map from caller PC to a set of callee methods. - * When a warning about keyword argument change is printed, - * it keeps the pair of callee and caller. - */ -static st_table *caller_to_callees = 0; - -static VALUE -rb_warn_check(const rb_execution_context_t * const ec, const rb_iseq_t *const iseq) -{ - if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return 1; - - if (!iseq) return 0; - - const st_data_t callee = (st_data_t)(iseq->body->iseq_unique_id * 2); - - const rb_control_frame_t * const cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); - - if (!cfp) return 0; - - const st_data_t caller = (st_data_t)cfp->pc; - - if (!caller_to_callees) { - caller_to_callees = st_init_numtable(); - } - - st_data_t val; - if (st_lookup(caller_to_callees, caller, &val)) { - st_table *callees; - - if (val & 1) { - val &= ~(st_data_t)1; - if (val == callee) return 1; /* already warned */ - - callees = st_init_numtable(); - st_insert(callees, val, 1); - } - else { - callees = (st_table *) val; - if (st_is_member(callees, callee)) return 1; /* already warned */ - } - st_insert(callees, callee, 1); - st_insert(caller_to_callees, caller, (st_data_t) callees); - } - else { - st_insert(caller_to_callees, caller, callee | 1); - } - - return 0; /* not warned yet for the pair of caller and callee */ -} - -static inline void -rb_warn_keyword_to_last_hash(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq) -{ - if (rb_warn_check(ec, iseq)) return; - - VALUE name, loc; - if (calling->recv == Qundef) { - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - return; - } - name = rb_id2str(ci->mid); - loc = rb_iseq_location(iseq); - if (NIL_P(loc)) { - rb_warn("Passing the keyword argument for `%"PRIsVALUE"' as the last hash parameter is deprecated", - name); - } - else { - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - if (name) { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method `%"PRIsVALUE"' is defined here", name); - } - else { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method is defined here"); - } - } -} - -static inline void -rb_warn_split_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq) -{ - if (rb_warn_check(ec, iseq)) return; - - VALUE name, loc; - name = rb_id2str(ci->mid); - loc = rb_iseq_location(iseq); - if (NIL_P(loc)) { - rb_warn("Splitting the last argument for `%"PRIsVALUE"' into positional and keyword parameters is deprecated", - name); - } - else { - rb_warn("Splitting the last argument into positional and keyword parameters is deprecated"); - if (calling->recv != Qundef) { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method `%"PRIsVALUE"' is defined here", name); - } - else { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method is defined here"); - } - } -} - -static inline void -rb_warn_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq) +ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned int * kw_flag, VALUE * converted_keyword_hash) { - if (rb_warn_check(ec, iseq)) return; - - VALUE name, loc; - name = rb_id2str(ci->mid); - loc = rb_iseq_location(iseq); - if (NIL_P(loc)) { - rb_warn("Using the last argument for `%"PRIsVALUE"' as keyword parameters is deprecated; maybe ** should be added to the call", - name); + if (!RB_TYPE_P(keyword_hash, T_HASH)) { + keyword_hash = rb_to_hash_type(keyword_hash); } - else { - rb_warn("Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call"); - if (calling->recv != Qundef) { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method `%"PRIsVALUE"' is defined here", name); - } - else { - rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)), - "The called method is defined here"); - } + if (!(*kw_flag & VM_CALL_KW_SPLAT_MUT) && + (iseq->body->param.flags.has_kwrest || + iseq->body->param.flags.ruby2_keywords)) { + *kw_flag |= VM_CALL_KW_SPLAT_MUT; + keyword_hash = rb_hash_dup(keyword_hash); } + *converted_keyword_hash = keyword_hash; + return !(iseq->body->param.flags.has_kw) && + !(iseq->body->param.flags.has_kwrest) && + RHASH_EMPTY_P(keyword_hash); } static int setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * const iseq, struct rb_calling_info *const calling, - const struct rb_call_info *ci, - VALUE * const locals, const enum arg_setup_type arg_setup_type) + const struct rb_callinfo *ci, + VALUE * const locals, const enum arg_setup_type arg_setup_type) { const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num; const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS; int given_argc; - int kw_splat = FALSE; - unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT); + unsigned int kw_flag = vm_ci_flag(ci) & (VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); int opt_pc = 0, allow_autosplat = !kw_flag; struct args_info args_body, *args; VALUE keyword_hash = Qnil; VALUE * const orig_sp = ec->cfp->sp; unsigned int i; - int remove_empty_keyword_hash = 1; VALUE flag_keyword_hash = 0; + VALUE converted_keyword_hash = 0; vm_check_canary(ec, orig_sp); /* @@ -763,7 +497,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co args->rest_dupped = FALSE; if (kw_flag & VM_CALL_KWARG) { - args->kw_arg = ((struct rb_call_info_with_kwarg *)ci)->kw_arg; + args->kw_arg = vm_ci_kwarg(ci); if (iseq->body->param.flags.has_kw) { int kw_len = args->kw_arg->keyword_len; @@ -776,7 +510,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co else { args->kw_argv = NULL; given_argc = args_kw_argv_to_hash(args); - kw_flag |= VM_CALL_KW_SPLAT; + kw_flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT; } } else { @@ -784,11 +518,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co args->kw_argv = NULL; } - if (kw_flag && iseq->body->param.flags.ruby2_keywords) { - remove_empty_keyword_hash = 0; - } - - if (ci->flag & VM_CALL_ARGS_SPLAT) { + if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { VALUE rest_last = 0; int len; args->rest = locals[--args->argc]; @@ -801,10 +531,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co if (RB_TYPE_P(rest_last, T_HASH) && (((struct RHash *)rest_last)->basic.flags & RHASH_PASS_AS_KEYWORDS)) { rest_last = rb_hash_dup(rest_last); - kw_flag |= VM_CALL_KW_SPLAT; - if (iseq->body->param.flags.ruby2_keywords) { - remove_empty_keyword_hash = 0; - } + kw_flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT; } else { rest_last = 0; @@ -812,55 +539,53 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co } if (kw_flag & VM_CALL_KW_SPLAT) { - if (len > 0 && ignore_keyword_hash_p(rest_last, iseq)) { - if (given_argc != min_argc) { - if (remove_empty_keyword_hash) { - arg_rest_dup(args); - rb_ary_pop(args->rest); - given_argc--; - kw_flag &= ~VM_CALL_KW_SPLAT; - } - else { - if (RB_TYPE_P(rest_last, T_HASH) && rb_obj_frozen_p(rest_last)) { - rest_last = rb_hash_new(); - RARRAY_ASET(args->rest, len - 1, rest_last); - } - flag_keyword_hash = rest_last; - } + if (ignore_keyword_hash_p(rest_last, iseq, &kw_flag, &converted_keyword_hash)) { + arg_rest_dup(args); + rb_ary_pop(args->rest); + given_argc--; + kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); + } + else { + if (rest_last != converted_keyword_hash) { + rest_last = converted_keyword_hash; + arg_rest_dup(args); + RARRAY_ASET(args->rest, len - 1, rest_last); + } + + if (iseq->body->param.flags.ruby2_keywords && rest_last) { + flag_keyword_hash = rest_last; } - else { - rb_warn_keyword_to_last_hash(ec, calling, ci, iseq); + else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) { + arg_rest_dup(args); + rb_ary_pop(args->rest); + given_argc--; + keyword_hash = rest_last; } - } - else if (!remove_empty_keyword_hash && rest_last) { - flag_keyword_hash = rest_last; } } } else { if (kw_flag & VM_CALL_KW_SPLAT) { VALUE last_arg = args->argv[args->argc-1]; - if (ignore_keyword_hash_p(last_arg, iseq)) { - if (given_argc != min_argc) { - if (remove_empty_keyword_hash) { - args->argc--; - given_argc--; - kw_flag &= ~VM_CALL_KW_SPLAT; - } - else { - if (RB_TYPE_P(last_arg, T_HASH) && rb_obj_frozen_p(last_arg)) { - last_arg = rb_hash_new(); - args->argv[args->argc-1] = last_arg; - } - flag_keyword_hash = last_arg; - } + if (ignore_keyword_hash_p(last_arg, iseq, &kw_flag, &converted_keyword_hash)) { + args->argc--; + given_argc--; + kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); + } + else { + if (last_arg != converted_keyword_hash) { + last_arg = converted_keyword_hash; + args->argv[args->argc-1] = last_arg; } - else { - rb_warn_keyword_to_last_hash(ec, calling, ci, iseq); + + if (iseq->body->param.flags.ruby2_keywords) { + flag_keyword_hash = last_arg; + } + else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) { + args->argc--; + given_argc--; + keyword_hash = last_arg; } - } - else if (!remove_empty_keyword_hash) { - flag_keyword_hash = args->argv[args->argc-1]; } } args->rest = Qfalse; @@ -874,14 +599,14 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co rb_raise(rb_eArgError, "no keywords accepted"); } + switch (arg_setup_type) { case arg_setup_method: break; /* do nothing special */ case arg_setup_block: - if (given_argc == 1 && + if (given_argc == (NIL_P(keyword_hash) ? 1 : 2) && allow_autosplat && - (min_argc > 0 || iseq->body->param.opt_num > 1 || - iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) && + (min_argc > 0 || iseq->body->param.opt_num > 1) && !iseq->body->param.flags.ambiguous_param0 && args_check_block_arg0(args)) { given_argc = RARRAY_LENINT(args->rest); @@ -891,60 +616,13 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co /* argc check */ if (given_argc < min_argc) { - if (given_argc == min_argc - 1 && args->kw_argv) { - args_stored_kw_argv_to_hash(args); - given_argc = args_argc(args); - } - else { - if (arg_setup_type == arg_setup_block) { - CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc); - given_argc = min_argc; - args_extend(args, min_argc); - } - else { - argument_arity_error(ec, iseq, given_argc, min_argc, max_argc); - } - } - } - - if (kw_flag & VM_CALL_KW_SPLAT) { - kw_splat = !iseq->body->param.flags.has_rest; - } - if ((iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest || - (kw_splat && given_argc > max_argc)) && - args->kw_argv == NULL) { - if (given_argc > min_argc) { - if (kw_flag) { - int check_only_symbol = (kw_flag & VM_CALL_KW_SPLAT) && - iseq->body->param.flags.has_kw && - !iseq->body->param.flags.has_kwrest; - - if (args_pop_keyword_hash(args, &keyword_hash, check_only_symbol)) { - given_argc--; - } - else if (check_only_symbol) { - if (keyword_hash != Qnil) { - rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq); - } - else { - rb_warn_keyword_to_last_hash(ec, calling, ci, iseq); - } - } - } - else if (args_pop_keyword_hash(args, &keyword_hash, 1)) { - /* Warn the following: - * def foo(k:1) p [k]; end - * foo({k:42}) #=> 42 - */ - rb_warn_last_hash_to_keyword(ec, calling, ci, iseq); - given_argc--; - } - else if (keyword_hash != Qnil) { - rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq); - } + if (arg_setup_type == arg_setup_block) { + CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc); + given_argc = min_argc; + args_extend(args, min_argc); } - else if (given_argc == min_argc && kw_flag) { - rb_warn_keyword_to_last_hash(ec, calling, ci, iseq); + else { + argument_arity_error(ec, iseq, given_argc, min_argc, max_argc); } } @@ -984,7 +662,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co VALUE * const klocals = locals + iseq->body->param.keyword->bits_start - iseq->body->param.keyword->num; if (args->kw_argv != NULL) { - const struct rb_call_info_kw_arg *kw_arg = args->kw_arg; + const struct rb_callinfo_kwarg *kw_arg = args->kw_arg; args_setup_kw_parameters(ec, iseq, args->kw_argv, kw_arg->keyword_len, kw_arg->keywords, klocals); } else if (!NIL_P(keyword_hash)) { @@ -1004,7 +682,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co } } else if (iseq->body->param.flags.has_kwrest) { - args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start); + args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start, kw_flag); } else if (!NIL_P(keyword_hash) && RHASH_SIZE(keyword_hash) > 0 && arg_setup_type == arg_setup_method) { argument_kw_error(ec, iseq, "unknown", rb_hash_keys(keyword_hash)); @@ -1023,7 +701,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co { int i; for (i=0; ibody->param.size; i++) { - fprintf(stderr, "local[%d] = %p\n", i, (void *)locals[i]); + ruby_debug_printf("local[%d] = %p\n", i, (void *)locals[i]); } } #endif @@ -1032,8 +710,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co return opt_pc; } -void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self); /* vm_backtrace.c */ - static void raise_argument_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const VALUE exc) { @@ -1112,11 +788,10 @@ vm_caller_setup_arg_splat(rb_control_frame_t *cfp, struct rb_calling_info *calli } static inline void -vm_caller_setup_arg_kw(rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci) +vm_caller_setup_arg_kw(rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_callinfo *ci) { - struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci; - const VALUE *const passed_keywords = ci_kw->kw_arg->keywords; - const int kw_len = ci_kw->kw_arg->keyword_len; + const VALUE *const passed_keywords = vm_ci_kwarg(ci)->keywords; + const int kw_len = vm_ci_kwarg(ci)->keyword_len; const VALUE h = rb_hash_new_with_size(kw_len); VALUE *sp = cfp->sp; int i; @@ -1164,13 +839,11 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)) { VALUE obj; ID mid; - const rb_callable_method_entry_t *me; + const rb_callable_method_entry_t *me = 0; /* for hidden object case */ rb_execution_context_t *ec; const VALUE symbol = RARRAY_AREF(callback_arg, 0); const VALUE refinements = RARRAY_AREF(callback_arg, 1); int kw_splat = RB_PASS_CALLED_KEYWORDS; - VALUE v; - VALUE ret; VALUE klass; if (argc-- < 1) { @@ -1191,22 +864,17 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)) if (!NIL_P(blockarg)) { vm_passed_block_handler_set(ec, blockarg); } - v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); if (!me) { - ret = method_missing(obj, mid, argc, argv, MISSING_NOENTRY, kw_splat); - } - else { - ret = rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat); + return method_missing(ec, obj, mid, argc, argv, MISSING_NOENTRY, kw_splat); } - rb_free_tmp_buffer(&v); - return ret; + return rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat); } static VALUE vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - const struct rb_call_info *ci, const rb_iseq_t *blockiseq, const int is_super) + const struct rb_callinfo *ci, const rb_iseq_t *blockiseq, const int is_super) { - if (ci->flag & VM_CALL_ARGS_BLOCKARG) { + if (vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) { VALUE block_code = *(--reg_cfp->sp); if (NIL_P(block_code)) { @@ -1229,7 +897,7 @@ vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t * rb_ary_push(callback_arg, block_code); rb_ary_push(callback_arg, ref); OBJ_FREEZE_RAW(callback_arg); - func = rb_func_proc_new(refine_sym_proc_call, callback_arg); + func = rb_func_lambda_new(refine_sym_proc_call, callback_arg, 1, UNLIMITED_ARGUMENTS); rb_hash_aset(ref, block_code, func); } block_code = func; diff --git a/ruby/vm_backtrace.c b/ruby/vm_backtrace.c index 2c9649a7c..9f5fcc8da 100644 --- a/ruby/vm_backtrace.c +++ b/ruby/vm_backtrace.c @@ -9,13 +9,14 @@ **********************************************************************/ -#include "ruby/encoding.h" -#include "ruby/debug.h" -#include "internal.h" - -#include "vm_core.h" #include "eval_intern.h" +#include "internal.h" +#include "internal/error.h" +#include "internal/vm.h" #include "iseq.h" +#include "ruby/debug.h" +#include "ruby/encoding.h" +#include "vm_core.h" static VALUE rb_cBacktrace; static VALUE rb_cBacktraceLocation; @@ -29,19 +30,27 @@ id2str(ID id) } #define rb_id2str(id) id2str(id) +#define BACKTRACE_START 0 +#define ALL_BACKTRACE_LINES -1 + inline static int -calc_lineno(const rb_iseq_t *iseq, const VALUE *pc) +calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id) { VM_ASSERT(iseq); VM_ASSERT(iseq->body); VM_ASSERT(iseq->body->iseq_encoded); VM_ASSERT(iseq->body->iseq_size); if (! pc) { - /* This can happen during VM bootup. */ - VM_ASSERT(iseq->body->type == ISEQ_TYPE_TOP); - VM_ASSERT(! iseq->body->local_table); - VM_ASSERT(! iseq->body->local_table_size); - return 0; + if (iseq->body->type == ISEQ_TYPE_TOP) { + VM_ASSERT(! iseq->body->local_table); + VM_ASSERT(! iseq->body->local_table_size); + return 0; + } + if (lineno) *lineno = FIX2INT(iseq->body->location.first_lineno); +#ifdef USE_ISEQ_NODE_ID + if (node_id) *node_id = -1; +#endif + return 1; } else { ptrdiff_t n = pc - iseq->body->iseq_encoded; @@ -60,10 +69,32 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc) __builtin_trap(); } #endif - return rb_iseq_line_no(iseq, pos); + if (lineno) *lineno = rb_iseq_line_no(iseq, pos); +#ifdef USE_ISEQ_NODE_ID + if (node_id) *node_id = rb_iseq_node_id(iseq, pos); +#endif + return 1; } } +inline static int +calc_lineno(const rb_iseq_t *iseq, const VALUE *pc) +{ + int lineno; + if (calc_pos(iseq, pc, &lineno, NULL)) return lineno; + return 0; +} + +#ifdef USE_ISEQ_NODE_ID +inline static int +calc_node_id(const rb_iseq_t *iseq, const VALUE *pc) +{ + int node_id; + if (calc_pos(iseq, pc, NULL, &node_id)) return node_id; + return -1; +} +#endif + int rb_vm_get_sourceline(const rb_control_frame_t *cfp) { @@ -85,24 +116,12 @@ rb_vm_get_sourceline(const rb_control_frame_t *cfp) typedef struct rb_backtrace_location_struct { enum LOCATION_TYPE { LOCATION_TYPE_ISEQ = 1, - LOCATION_TYPE_ISEQ_CALCED, LOCATION_TYPE_CFUNC, - LOCATION_TYPE_IFUNC } type; - union { - struct { - const rb_iseq_t *iseq; - union { - const VALUE *pc; - int lineno; - } lineno; - } iseq; - struct { - ID mid; - struct rb_backtrace_location_struct *prev_loc; - } cfunc; - } body; + const rb_iseq_t *iseq; + const VALUE *pc; + ID mid; } rb_backtrace_location_t; struct valued_frame_info { @@ -122,11 +141,13 @@ location_mark_entry(rb_backtrace_location_t *fi) { switch (fi->type) { case LOCATION_TYPE_ISEQ: - case LOCATION_TYPE_ISEQ_CALCED: - rb_gc_mark((VALUE)fi->body.iseq.iseq); + rb_gc_mark_movable((VALUE)fi->iseq); break; case LOCATION_TYPE_CFUNC: - case LOCATION_TYPE_IFUNC: + if (fi->iseq) { + rb_gc_mark_movable((VALUE)fi->iseq); + } + break; default: break; } @@ -145,6 +166,12 @@ static const rb_data_type_t location_data_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; +int +rb_frame_info_p(VALUE obj) +{ + return rb_typeddata_is_kind_of(obj, &location_data_type); +} + static inline rb_backtrace_location_t * location_ptr(VALUE locobj) { @@ -158,13 +185,10 @@ location_lineno(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: - loc->type = LOCATION_TYPE_ISEQ_CALCED; - return (loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc)); - case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.lineno.lineno; + return calc_lineno(loc->iseq, loc->pc); case LOCATION_TYPE_CFUNC: - if (loc->body.cfunc.prev_loc) { - return location_lineno(loc->body.cfunc.prev_loc); + if (loc->iseq && loc->pc) { + return calc_lineno(loc->iseq, loc->pc); } return 0; default: @@ -192,11 +216,9 @@ location_label(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: - case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->body->location.label; + return loc->iseq->body->location.label; case LOCATION_TYPE_CFUNC: - return rb_id2str(loc->body.cfunc.mid); - case LOCATION_TYPE_IFUNC: + return rb_id2str(loc->mid); default: rb_bug("location_label: unreachable"); UNREACHABLE; @@ -241,11 +263,9 @@ location_base_label(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: - case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->body->location.base_label; + return loc->iseq->body->location.base_label; case LOCATION_TYPE_CFUNC: - return rb_id2str(loc->body.cfunc.mid); - case LOCATION_TYPE_IFUNC: + return rb_id2str(loc->mid); default: rb_bug("location_base_label: unreachable"); UNREACHABLE; @@ -263,27 +283,24 @@ location_base_label_m(VALUE self) return location_base_label(location_ptr(self)); } -static VALUE -location_path(rb_backtrace_location_t *loc) +static const rb_iseq_t * +location_iseq(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: - case LOCATION_TYPE_ISEQ_CALCED: - return rb_iseq_path(loc->body.iseq.iseq); + return loc->iseq; case LOCATION_TYPE_CFUNC: - if (loc->body.cfunc.prev_loc) { - return location_path(loc->body.cfunc.prev_loc); - } - return Qnil; - case LOCATION_TYPE_IFUNC: + return loc->iseq; default: - rb_bug("location_path: unreachable"); + rb_bug("location_iseq: unreachable"); UNREACHABLE; } } /* - * Returns the file name of this frame. + * Returns the file name of this frame. This will generally be an absolute + * path, unless the frame is in the main script, in which case it will be the + * script location passed on the command line. * * For example, using +caller_locations.rb+ from Thread::Backtrace::Location * @@ -293,7 +310,46 @@ location_path(rb_backtrace_location_t *loc) static VALUE location_path_m(VALUE self) { - return location_path(location_ptr(self)); + const rb_iseq_t *iseq = location_iseq(location_ptr(self)); + return iseq ? rb_iseq_path(iseq) : Qnil; +} + +#ifdef USE_ISEQ_NODE_ID +static int +location_node_id(rb_backtrace_location_t *loc) +{ + switch (loc->type) { + case LOCATION_TYPE_ISEQ: + return calc_node_id(loc->iseq, loc->pc); + case LOCATION_TYPE_CFUNC: + if (loc->iseq && loc->pc) { + return calc_node_id(loc->iseq, loc->pc); + } + return -1; + default: + rb_bug("location_node_id: unreachable"); + UNREACHABLE; + } +} +#endif + +int +rb_get_node_id_from_frame_info(VALUE obj) +{ +#ifdef USE_ISEQ_NODE_ID + rb_backtrace_location_t *loc = location_ptr(obj); + return location_node_id(loc); +#else + return -1; +#endif +} + +const rb_iseq_t * +rb_get_iseq_from_frame_info(VALUE obj) +{ + rb_backtrace_location_t *loc = location_ptr(obj); + const rb_iseq_t *iseq = location_iseq(loc); + return iseq; } static VALUE @@ -301,14 +357,12 @@ location_realpath(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: - case LOCATION_TYPE_ISEQ_CALCED: - return rb_iseq_realpath(loc->body.iseq.iseq); + return rb_iseq_realpath(loc->iseq); case LOCATION_TYPE_CFUNC: - if (loc->body.cfunc.prev_loc) { - return location_realpath(loc->body.cfunc.prev_loc); + if (loc->iseq) { + return rb_iseq_realpath(loc->iseq); } return Qnil; - case LOCATION_TYPE_IFUNC: default: rb_bug("location_realpath: unreachable"); UNREACHABLE; @@ -318,7 +372,8 @@ location_realpath(rb_backtrace_location_t *loc) /* * Returns the full file path of this frame. * - * Same as #path, but includes the absolute path. + * Same as #path, except that it will return absolute path + * even if the frame is in the main script. */ static VALUE location_absolute_path_m(VALUE self) @@ -351,29 +406,22 @@ location_to_str(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: - file = rb_iseq_path(loc->body.iseq.iseq); - name = loc->body.iseq.iseq->body->location.label; + file = rb_iseq_path(loc->iseq); + name = loc->iseq->body->location.label; - lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc); - loc->type = LOCATION_TYPE_ISEQ_CALCED; - break; - case LOCATION_TYPE_ISEQ_CALCED: - file = rb_iseq_path(loc->body.iseq.iseq); - lineno = loc->body.iseq.lineno.lineno; - name = loc->body.iseq.iseq->body->location.label; + lineno = calc_lineno(loc->iseq, loc->pc); break; case LOCATION_TYPE_CFUNC: - if (loc->body.cfunc.prev_loc) { - file = rb_iseq_path(loc->body.cfunc.prev_loc->body.iseq.iseq); - lineno = location_lineno(loc->body.cfunc.prev_loc); + if (loc->iseq && loc->pc) { + file = rb_iseq_path(loc->iseq); + lineno = calc_lineno(loc->iseq, loc->pc); } else { file = GET_VM()->progname; lineno = 0; } - name = rb_id2str(loc->body.cfunc.mid); + name = rb_id2str(loc->mid); break; - case LOCATION_TYPE_IFUNC: default: rb_bug("location_to_str: unreachable"); } @@ -402,7 +450,6 @@ location_inspect_m(VALUE self) typedef struct rb_backtrace_struct { rb_backtrace_location_t *backtrace; - rb_backtrace_location_t *backtrace_base; int backtrace_size; VALUE strary; VALUE locary; @@ -417,18 +464,48 @@ backtrace_mark(void *ptr) for (i=0; ibacktrace[i]); } - rb_gc_mark(bt->strary); - rb_gc_mark(bt->locary); + rb_gc_mark_movable(bt->strary); + rb_gc_mark_movable(bt->locary); } static void backtrace_free(void *ptr) { rb_backtrace_t *bt = (rb_backtrace_t *)ptr; - if (bt->backtrace) ruby_xfree(bt->backtrace_base); + if (bt->backtrace) ruby_xfree(bt->backtrace); ruby_xfree(bt); } +static void +location_update_entry(rb_backtrace_location_t *fi) +{ + switch (fi->type) { + case LOCATION_TYPE_ISEQ: + fi->iseq = (rb_iseq_t*)rb_gc_location((VALUE)fi->iseq); + break; + case LOCATION_TYPE_CFUNC: + if (fi->iseq) { + fi->iseq = (rb_iseq_t*)rb_gc_location((VALUE)fi->iseq); + } + break; + default: + break; + } +} + +static void +backtrace_update(void *ptr) +{ + rb_backtrace_t *bt = (rb_backtrace_t *)ptr; + size_t i, s = bt->backtrace_size; + + for (i=0; ibacktrace[i]); + } + bt->strary = rb_gc_location(bt->strary); + bt->locary = rb_gc_location(bt->locary); +} + static size_t backtrace_memsize(const void *ptr) { @@ -438,7 +515,7 @@ backtrace_memsize(const void *ptr) static const rb_data_type_t backtrace_data_type = { "backtrace", - {backtrace_mark, backtrace_free, backtrace_memsize,}, + {backtrace_mark, backtrace_free, backtrace_memsize, backtrace_update}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -456,132 +533,152 @@ backtrace_alloc(VALUE klass) return obj; } -static void -backtrace_each(const rb_execution_context_t *ec, - void (*init)(void *arg, size_t size), - void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp), - void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid), - void *arg) +static long +backtrace_size(const rb_execution_context_t *ec) { const rb_control_frame_t *last_cfp = ec->cfp; const rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(ec); - const rb_control_frame_t *cfp; - ptrdiff_t size, i; - // In the case the thread vm_stack or cfp is not initialized, there is no backtrace. if (start_cfp == NULL) { - init(arg, 0); - return; + return -1; } - /* <- start_cfp (end control frame) - * top frame (dummy) - * top frame (dummy) - * top frame <- start_cfp - * top frame - * ... - * 2nd frame <- lev:0 - * current frame <- ec->cfp - */ - start_cfp = RUBY_VM_NEXT_CONTROL_FRAME( - RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */ + RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */ if (start_cfp < last_cfp) { - size = 0; - } - else { - size = start_cfp - last_cfp + 1; + return 0; } - init(arg, size); - - /* SDR(); */ - for (i=0, cfp = start_cfp; ivm_stack + ec->vm_stack_size) - cfp); */ - if (cfp->iseq) { - if (cfp->pc) { - iter_iseq(arg, cfp); - } - } - else if (RUBYVM_CFUNC_FRAME_P(cfp)) { - const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); - ID mid = me->def->original_id; - - iter_cfunc(arg, cfp, mid); - } - } + return start_cfp - last_cfp + 1; } -struct bt_iter_arg { - rb_backtrace_t *bt; - VALUE btobj; - rb_backtrace_location_t *prev_loc; -}; - -static void -bt_init(void *ptr, size_t size) +static bool +is_internal_location(const rb_control_frame_t *cfp) { - struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr; - arg->btobj = backtrace_alloc(rb_cBacktrace); - GetCoreDataFromValue(arg->btobj, rb_backtrace_t, arg->bt); - arg->bt->backtrace_base = arg->bt->backtrace = ALLOC_N(rb_backtrace_location_t, size); - arg->bt->backtrace_size = 0; + static const char prefix[] = "iseq); + return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0; } static void -bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp) +bt_update_cfunc_loc(unsigned long cfunc_counter, rb_backtrace_location_t *cfunc_loc, const rb_iseq_t *iseq, const VALUE *pc) { - const rb_iseq_t *iseq = cfp->iseq; - const VALUE *pc = cfp->pc; - struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr; - rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++]; - loc->type = LOCATION_TYPE_ISEQ; - loc->body.iseq.iseq = iseq; - loc->body.iseq.lineno.pc = pc; - arg->prev_loc = loc; + for (; cfunc_counter > 0; cfunc_counter--, cfunc_loc--) { + cfunc_loc->iseq = iseq; + cfunc_loc->pc = pc; + } } -static void -bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid) +static VALUE +rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long start_frame, long num_frames, int* start_too_large, bool skip_internal) { - struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr; - rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++]; - loc->type = LOCATION_TYPE_CFUNC; - loc->body.cfunc.mid = mid; - loc->body.cfunc.prev_loc = arg->prev_loc; + const rb_control_frame_t *cfp = ec->cfp; + const rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec); + ptrdiff_t size; + rb_backtrace_t *bt; + VALUE btobj = backtrace_alloc(rb_cBacktrace); + rb_backtrace_location_t *loc; + unsigned long cfunc_counter = 0; + GetCoreDataFromValue(btobj, rb_backtrace_t, bt); + + // In the case the thread vm_stack or cfp is not initialized, there is no backtrace. + if (end_cfp == NULL) { + num_frames = 0; + } + else { + end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp); + + /* + * top frame (dummy) <- RUBY_VM_END_CONTROL_FRAME + * top frame (dummy) <- end_cfp + * top frame <- main script + * top frame + * ... + * 2nd frame <- lev:0 + * current frame <- ec->cfp + */ + + size = end_cfp - cfp + 1; + if (size < 0) { + num_frames = 0; + } + else if (num_frames < 0 || num_frames > size) { + num_frames = size; + } + } + + bt->backtrace = ZALLOC_N(rb_backtrace_location_t, num_frames); + bt->backtrace_size = 0; + if (num_frames == 0) { + if (start_too_large) *start_too_large = 0; + return btobj; + } + + for (; cfp != end_cfp && (bt->backtrace_size < num_frames); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) { + if (cfp->iseq) { + if (cfp->pc) { + if (start_frame > 0) { + start_frame--; + } + else if (!skip_internal || !is_internal_location(cfp)) { + const rb_iseq_t *iseq = cfp->iseq; + const VALUE *pc = cfp->pc; + loc = &bt->backtrace[bt->backtrace_size++]; + loc->type = LOCATION_TYPE_ISEQ; + loc->iseq = iseq; + loc->pc = pc; + bt_update_cfunc_loc(cfunc_counter, loc-1, iseq, pc); + cfunc_counter = 0; + } + } + } + else if (RUBYVM_CFUNC_FRAME_P(cfp)) { + if (start_frame > 0) { + start_frame--; + } + else { + loc = &bt->backtrace[bt->backtrace_size++]; + loc->type = LOCATION_TYPE_CFUNC; + loc->iseq = NULL; + loc->pc = NULL; + loc->mid = rb_vm_frame_method_entry(cfp)->def->original_id; + cfunc_counter++; + } + } + } + + if (cfunc_counter > 0) { + for (; cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) { + if (cfp->iseq && cfp->pc && (!skip_internal || !is_internal_location(cfp))) { + bt_update_cfunc_loc(cfunc_counter, loc, cfp->iseq, cfp->pc); + break; + } + } + } + + if (start_too_large) *start_too_large = (start_frame > 0 ? -1 : 0); + return btobj; } MJIT_FUNC_EXPORTED VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec) { - struct bt_iter_arg arg; - arg.prev_loc = 0; - - backtrace_each(ec, - bt_init, - bt_iter_iseq, - bt_iter_cfunc, - &arg); - - return arg.btobj; + return rb_ec_partial_backtrace_object(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, NULL, FALSE); } static VALUE -backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg) +backtrace_collect(rb_backtrace_t *bt, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg) { VALUE btary; int i; - if (UNLIKELY(lev < 0 || n < 0)) { - rb_bug("backtrace_collect: unreachable"); - } - - btary = rb_ary_new2(n); + btary = rb_ary_new2(bt->backtrace_size); - for (i=0; i+levbacktrace_size && ibacktrace[bt->backtrace_size - 1 - (lev+i)]; + for (i=0; ibacktrace_size; i++) { + rb_backtrace_location_t *loc = &bt->backtrace[i]; rb_ary_push(btary, func(loc, arg)); } @@ -595,23 +692,12 @@ location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy) } static VALUE -backtrace_to_str_ary(VALUE self, long lev, long n) +backtrace_to_str_ary(VALUE self) { - rb_backtrace_t *bt; - int size; VALUE r; - + rb_backtrace_t *bt; GetCoreDataFromValue(self, rb_backtrace_t, bt); - size = bt->backtrace_size; - - if (n == 0) { - n = size; - } - if (lev > size) { - return Qnil; - } - - r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0); + r = backtrace_collect(bt, location_to_str_dmyarg, 0); RB_GC_GUARD(self); return r; } @@ -623,7 +709,7 @@ rb_backtrace_to_str_ary(VALUE self) GetCoreDataFromValue(self, rb_backtrace_t, bt); if (!bt->strary) { - bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size); + bt->strary = backtrace_to_str_ary(self); } return bt->strary; } @@ -632,19 +718,16 @@ MJIT_FUNC_EXPORTED void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self) { const rb_backtrace_t *bt; - const rb_iseq_t *iseq; rb_backtrace_location_t *loc; GetCoreDataFromValue(self, rb_backtrace_t, bt); VM_ASSERT(bt->backtrace_size > 0); - loc = &bt->backtrace[bt->backtrace_size - 1]; - iseq = loc->body.iseq.iseq; + loc = &bt->backtrace[0]; VM_ASSERT(loc->type == LOCATION_TYPE_ISEQ); - loc->body.iseq.lineno.lineno = FIX2INT(iseq->body->location.first_lineno); - loc->type = LOCATION_TYPE_ISEQ_CALCED; + loc->pc = NULL; // means location.first_lineno } static VALUE @@ -661,23 +744,12 @@ location_create(rb_backtrace_location_t *srcloc, void *btobj) } static VALUE -backtrace_to_location_ary(VALUE self, long lev, long n) +backtrace_to_location_ary(VALUE self) { - rb_backtrace_t *bt; - int size; VALUE r; - + rb_backtrace_t *bt; GetCoreDataFromValue(self, rb_backtrace_t, bt); - size = bt->backtrace_size; - - if (n == 0) { - n = size; - } - if (lev > size) { - return Qnil; - } - - r = backtrace_collect(bt, lev, n, location_create, (void *)self); + r = backtrace_collect(bt, location_create, (void *)self); RB_GC_GUARD(self); return r; } @@ -689,7 +761,7 @@ rb_backtrace_to_location_ary(VALUE self) GetCoreDataFromValue(self, rb_backtrace_t, bt); if (!bt->locary) { - bt->locary = backtrace_to_location_ary(self, 0, 0); + bt->locary = backtrace_to_location_ary(self); } return bt->locary; } @@ -710,20 +782,134 @@ backtrace_load_data(VALUE self, VALUE str) return self; } +/* + * call-seq: Threade::Backtrace::limit -> integer + * + * Returns maximum backtrace length set by --backtrace-limit + * command-line option. The defalt is -1 which means unlimited + * backtraces. If the value is zero or positive, the error backtraces, + * produced by Exception#full_message, are abbreviated and the extra lines + * are replaced by ... 3 levels... + * + * $ ruby -r net/http -e "p Thread::Backtrace.limit; Net::HTTP.get(URI('http://wrong.address'))" + * - 1 + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': Failed to open TCP connection to wrong.address:80 (getaddrinfo: Name or service not known) (SocketError) + * from .../lib/ruby/3.1.0/socket.rb:227:in `foreach' + * from .../lib/ruby/3.1.0/socket.rb:632:in `tcp' + * from .../lib/ruby/3.1.0/net/http.rb:998:in `connect' + * from .../lib/ruby/3.1.0/net/http.rb:976:in `do_start' + * from .../lib/ruby/3.1.0/net/http.rb:965:in `start' + * from .../lib/ruby/3.1.0/net/http.rb:627:in `start' + * from .../lib/ruby/3.1.0/net/http.rb:503:in `get_response' + * from .../lib/ruby/3.1.0/net/http.rb:474:in `get' + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': getaddrinfo: Name or service not known (SocketError) + * from .../lib/ruby/3.1.0/socket.rb:227:in `foreach' + * from .../lib/ruby/3.1.0/socket.rb:632:in `tcp' + * from .../lib/ruby/3.1.0/net/http.rb:998:in `connect' + * from .../lib/ruby/3.1.0/net/http.rb:976:in `do_start' + * from .../lib/ruby/3.1.0/net/http.rb:965:in `start' + * from .../lib/ruby/3.1.0/net/http.rb:627:in `start' + * from .../lib/ruby/3.1.0/net/http.rb:503:in `get_response' + * from .../lib/ruby/3.1.0/net/http.rb:474:in `get' + * from -e:1:in `
      ' + * + * $ ruby --backtrace-limit 2 -r net/http -e "p Thread::Backtrace.limit; Net::HTTP.get(URI('http://wrong.address'))" + * 2 + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': Failed to open TCP connection to wrong.address:80 (getaddrinfo: Name or service not known) (SocketError) + * from .../lib/ruby/3.1.0/socket.rb:227:in `foreach' + * from .../lib/ruby/3.1.0/socket.rb:632:in `tcp' + * ... 7 levels... + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': getaddrinfo: Name or service not known (SocketError) + * from .../lib/ruby/3.1.0/socket.rb:227:in `foreach' + * from .../lib/ruby/3.1.0/socket.rb:632:in `tcp' + * ... 7 levels... + * + * $ ruby --backtrace-limit 0 -r net/http -e "p Thread::Backtrace.limit; Net::HTTP.get(URI('http://wrong.address'))" + * 0 + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': Failed to open TCP connection to wrong.address:80 (getaddrinfo: Name or service not known) (SocketError) + * ... 9 levels... + * .../lib/ruby/3.1.0/socket.rb:227:in `getaddrinfo': getaddrinfo: Name or service not known (SocketError) + * ... 9 levels... + * + */ +static VALUE +backtrace_limit(VALUE self) +{ + return LONG2NUM(rb_backtrace_length_limit); +} + VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n) { - return backtrace_to_str_ary(rb_ec_backtrace_object(ec), lev, n); + return backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE)); } VALUE -rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n) +rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal) { - return backtrace_to_location_ary(rb_ec_backtrace_object(ec), lev, n); + return backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal)); } /* make old style backtrace directly */ +static void +backtrace_each(const rb_execution_context_t *ec, + void (*init)(void *arg, size_t size), + void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp), + void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid), + void *arg) +{ + const rb_control_frame_t *last_cfp = ec->cfp; + const rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(ec); + const rb_control_frame_t *cfp; + ptrdiff_t size, i; + + // In the case the thread vm_stack or cfp is not initialized, there is no backtrace. + if (start_cfp == NULL) { + init(arg, 0); + return; + } + + /* <- start_cfp (end control frame) + * top frame (dummy) + * top frame (dummy) + * top frame <- start_cfp + * top frame + * ... + * 2nd frame <- lev:0 + * current frame <- ec->cfp + */ + + start_cfp = + RUBY_VM_NEXT_CONTROL_FRAME( + RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */ + + if (start_cfp < last_cfp) { + size = 0; + } + else { + size = start_cfp - last_cfp + 1; + } + + init(arg, size); + + /* SDR(); */ + for (i=0, cfp = start_cfp; ivm_stack + ec->vm_stack_size) - cfp); */ + if (cfp->iseq) { + if (cfp->pc) { + iter_iseq(arg, cfp); + } + } + else if (RUBYVM_CFUNC_FRAME_P(cfp)) { + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); + ID mid = me->def->original_id; + + iter_cfunc(arg, cfp, mid); + } + } +} + struct oldbt_arg { VALUE filename; int lineno; @@ -871,7 +1057,7 @@ rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output) VALUE rb_make_backtrace(void) { - return rb_ec_backtrace_str_ary(GET_EC(), 0, 0); + return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES); } static VALUE @@ -879,11 +1065,9 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg { VALUE level, vn; long lev, n; - VALUE btval = rb_ec_backtrace_object(ec); + VALUE btval; VALUE r; - rb_backtrace_t *bt; - - GetCoreDataFromValue(btval, rb_backtrace_t, bt); + int too_large; rb_scan_args(argc, argv, "02", &level, &vn); @@ -892,19 +1076,19 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg switch (argc) { case 0: lev = lev_default + lev_plus; - n = bt->backtrace_size - lev; + n = ALL_BACKTRACE_LINES; break; case 1: { - long beg, len; - switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) { + long beg, len, bt_size = backtrace_size(ec); + switch (rb_range_beg_len(level, &beg, &len, bt_size - lev_plus, 0)) { case Qfalse: lev = NUM2LONG(level); if (lev < 0) { rb_raise(rb_eArgError, "negative level (%ld)", lev); } lev += lev_plus; - n = bt->backtrace_size - lev; + n = ALL_BACKTRACE_LINES; break; case Qnil: return Qnil; @@ -935,11 +1119,17 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg return rb_ary_new(); } + btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE); + + if (too_large) { + return Qnil; + } + if (to_str) { - r = backtrace_to_str_ary(btval, lev, n); + r = backtrace_to_str_ary(btval); } else { - r = backtrace_to_location_ary(btval, lev, n); + r = backtrace_to_location_ary(btval); } RB_GC_GUARD(btval); return r; @@ -968,6 +1158,16 @@ rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval) return thread_backtrace_to_ary(argc, argv, thval, 0); } +VALUE rb_vm_backtrace(int argc, const VALUE * argv, struct rb_execution_context_struct * ec) +{ + return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 1); +} + +VALUE rb_vm_backtrace_locations(int argc, const VALUE * argv, struct rb_execution_context_struct * ec) +{ + return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 0); +} + /* * call-seq: * caller(start=1, length=nil) -> array or nil @@ -1044,11 +1244,16 @@ rb_f_caller_locations(int argc, VALUE *argv, VALUE _) void Init_vm_backtrace(void) { - /* :nodoc: */ + /* + * An internal representation of the backtrace. The user will never interact with + * objects of this class directly, but class methods can be used to get backtrace + * settings of the current session. + */ rb_cBacktrace = rb_define_class_under(rb_cThread, "Backtrace", rb_cObject); rb_define_alloc_func(rb_cBacktrace, backtrace_alloc); rb_undef_method(CLASS_OF(rb_cBacktrace), "new"); rb_marshal_define_compat(rb_cBacktrace, rb_cArray, backtrace_dump_data, backtrace_load_data); + rb_define_singleton_method(rb_cBacktrace, "limit", backtrace_limit, 0); /* * An object representation of a stack frame, initialized by @@ -1240,7 +1445,7 @@ rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data) dbg_context.ec = ec; dbg_context.cfp = dbg_context.ec->cfp; - dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, 0, 0); + dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, FALSE); dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace); dbg_context.contexts = collect_caller_bindings(ec); @@ -1332,6 +1537,14 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) i++; } + else { + cme = rb_vm_frame_method_entry(cfp); + if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) { + buff[i] = (VALUE)cme; + if (lines) lines[i] = 0; + i++; + } + } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } @@ -1341,7 +1554,7 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) static const rb_iseq_t * frame2iseq(VALUE frame) { - if (frame == Qnil) return NULL; + if (NIL_P(frame)) return NULL; if (RB_TYPE_P(frame, T_IMEMO)) { switch (imemo_type(frame)) { @@ -1371,9 +1584,42 @@ rb_profile_frame_path(VALUE frame) return iseq ? rb_iseq_path(iseq) : Qnil; } +static const rb_callable_method_entry_t * +cframe(VALUE frame) +{ + if (NIL_P(frame)) return NULL; + + if (RB_TYPE_P(frame, T_IMEMO)) { + switch (imemo_type(frame)) { + case imemo_ment: + { + const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame; + switch (cme->def->type) { + case VM_METHOD_TYPE_CFUNC: + return cme; + default: + return NULL; + } + } + default: + return NULL; + } + } + + return NULL; +} + VALUE rb_profile_frame_absolute_path(VALUE frame) { + if (cframe(frame)) { + static VALUE cfunc_str = Qfalse; + if (!cfunc_str) { + cfunc_str = rb_str_new_literal(""); + rb_gc_register_mark_object(cfunc_str); + } + return cfunc_str; + } const rb_iseq_t *iseq = frame2iseq(frame); return iseq ? rb_iseq_realpath(iseq) : Qnil; } @@ -1402,7 +1648,7 @@ rb_profile_frame_first_lineno(VALUE frame) static VALUE frame2klass(VALUE frame) { - if (frame == Qnil) return Qnil; + if (NIL_P(frame)) return Qnil; if (RB_TYPE_P(frame, T_IMEMO)) { const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame; @@ -1425,7 +1671,7 @@ rb_profile_frame_classpath(VALUE frame) } else if (FL_TEST(klass, FL_SINGLETON)) { klass = rb_ivar_get(klass, id__attached__); - if (!RB_TYPE_P(klass, T_CLASS)) + if (!RB_TYPE_P(klass, T_CLASS) && !RB_TYPE_P(klass, T_MODULE)) return rb_sprintf("#<%s:%p>", rb_class2name(rb_obj_class(klass)), (void*)klass); } return rb_class_path(klass); @@ -1440,26 +1686,24 @@ rb_profile_frame_singleton_method_p(VALUE frame) { VALUE klass = frame2klass(frame); - if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)); } VALUE rb_profile_frame_method_name(VALUE frame) { + const rb_callable_method_entry_t *cme = cframe(frame); + if (cme) { + ID mid = cme->def->original_id; + return id2str(mid); + } const rb_iseq_t *iseq = frame2iseq(frame); return iseq ? rb_iseq_method_name(iseq) : Qnil; } -VALUE -rb_profile_frame_qualified_method_name(VALUE frame) +static VALUE +qualified_method_name(VALUE frame, VALUE method_name) { - VALUE method_name = rb_profile_frame_method_name(frame); - if (method_name != Qnil) { VALUE classpath = rb_profile_frame_classpath(frame); VALUE singleton_p = rb_profile_frame_singleton_method_p(frame); @@ -1477,9 +1721,24 @@ rb_profile_frame_qualified_method_name(VALUE frame) } } +VALUE +rb_profile_frame_qualified_method_name(VALUE frame) +{ + VALUE method_name = rb_profile_frame_method_name(frame); + + return qualified_method_name(frame, method_name); +} + VALUE rb_profile_frame_full_label(VALUE frame) { + const rb_callable_method_entry_t *cme = cframe(frame); + if (cme) { + ID mid = cme->def->original_id; + VALUE method_name = id2str(mid); + return qualified_method_name(frame, method_name); + } + VALUE label = rb_profile_frame_label(frame); VALUE base_label = rb_profile_frame_base_label(frame); VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame); diff --git a/ruby/vm_callinfo.h b/ruby/vm_callinfo.h new file mode 100644 index 000000000..09f755c81 --- /dev/null +++ b/ruby/vm_callinfo.h @@ -0,0 +1,487 @@ +#ifndef RUBY_VM_CALLINFO_H /*-*-C-*-vi:se ft=c:*/ +#define RUBY_VM_CALLINFO_H +/** + * @author Ruby developers + * @copyright 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. + */ + +#include "debug_counter.h" + +enum vm_call_flag_bits { + VM_CALL_ARGS_SPLAT_bit, /* m(*args) */ + VM_CALL_ARGS_BLOCKARG_bit, /* m(&block) */ + VM_CALL_FCALL_bit, /* m(...) */ + VM_CALL_VCALL_bit, /* m */ + VM_CALL_ARGS_SIMPLE_bit, /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */ + VM_CALL_BLOCKISEQ_bit, /* has blockiseq */ + VM_CALL_KWARG_bit, /* has kwarg */ + VM_CALL_KW_SPLAT_bit, /* m(**opts) */ + VM_CALL_TAILCALL_bit, /* located at tail position */ + VM_CALL_SUPER_bit, /* super */ + VM_CALL_ZSUPER_bit, /* zsuper */ + VM_CALL_OPT_SEND_bit, /* internal flag */ + VM_CALL_KW_SPLAT_MUT_bit, /* kw splat hash can be modified (to avoid allocating a new one) */ + VM_CALL__END +}; + +#define VM_CALL_ARGS_SPLAT (0x01 << VM_CALL_ARGS_SPLAT_bit) +#define VM_CALL_ARGS_BLOCKARG (0x01 << VM_CALL_ARGS_BLOCKARG_bit) +#define VM_CALL_FCALL (0x01 << VM_CALL_FCALL_bit) +#define VM_CALL_VCALL (0x01 << VM_CALL_VCALL_bit) +#define VM_CALL_ARGS_SIMPLE (0x01 << VM_CALL_ARGS_SIMPLE_bit) +#define VM_CALL_BLOCKISEQ (0x01 << VM_CALL_BLOCKISEQ_bit) +#define VM_CALL_KWARG (0x01 << VM_CALL_KWARG_bit) +#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit) +#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit) +#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit) +#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit) +#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit) +#define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit) + +struct rb_callinfo_kwarg { + int keyword_len; + VALUE keywords[]; +}; + +static inline size_t +rb_callinfo_kwarg_bytes(int keyword_len) +{ + return rb_size_mul_add_or_raise( + keyword_len, + sizeof(VALUE), + sizeof(struct rb_callinfo_kwarg), + rb_eRuntimeError); +} + +// imemo_callinfo +struct rb_callinfo { + VALUE flags; + const struct rb_callinfo_kwarg *kwarg; + VALUE mid; + VALUE flag; + VALUE argc; +}; + +#ifndef USE_EMBED_CI +#define USE_EMBED_CI 1 +#endif + +#if SIZEOF_VALUE == 8 +#define CI_EMBED_TAG_bits 1 +#define CI_EMBED_ARGC_bits 15 +#define CI_EMBED_FLAG_bits 16 +#define CI_EMBED_ID_bits 32 +#elif SIZEOF_VALUE == 4 +#define CI_EMBED_TAG_bits 1 +#define CI_EMBED_ARGC_bits 3 +#define CI_EMBED_FLAG_bits 13 +#define CI_EMBED_ID_bits 15 +#endif + +#if (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits + CI_EMBED_FLAG_bits + CI_EMBED_ID_bits) != (SIZEOF_VALUE * 8) +#error +#endif + +#define CI_EMBED_FLAG 0x01 +#define CI_EMBED_ARGC_SHFT (CI_EMBED_TAG_bits) +#define CI_EMBED_ARGC_MASK ((((VALUE)1)<> CI_EMBED_ID_SHFT) & CI_EMBED_ID_MASK; + } + else { + return (ID)ci->mid; + } +} + +static inline unsigned int +vm_ci_flag(const struct rb_callinfo *ci) +{ + if (vm_ci_packed_p(ci)) { + return (unsigned int)((((VALUE)ci) >> CI_EMBED_FLAG_SHFT) & CI_EMBED_FLAG_MASK); + } + else { + return (unsigned int)ci->flag; + } +} + +static inline unsigned int +vm_ci_argc(const struct rb_callinfo *ci) +{ + if (vm_ci_packed_p(ci)) { + return (unsigned int)((((VALUE)ci) >> CI_EMBED_ARGC_SHFT) & CI_EMBED_ARGC_MASK); + } + else { + return (unsigned int)ci->argc; + } +} + +static inline const struct rb_callinfo_kwarg * +vm_ci_kwarg(const struct rb_callinfo *ci) +{ + if (vm_ci_packed_p(ci)) { + return NULL; + } + else { + return ci->kwarg; + } +} + +static inline void +vm_ci_dump(const struct rb_callinfo *ci) +{ + if (vm_ci_packed_p(ci)) { + ruby_debug_printf("packed_ci ID:%s flag:%x argc:%u\n", + rb_id2name(vm_ci_mid(ci)), vm_ci_flag(ci), vm_ci_argc(ci)); + } + else { + rp(ci); + } +} + +#define vm_ci_new(mid, flag, argc, kwarg) vm_ci_new_(mid, flag, argc, kwarg, __FILE__, __LINE__) +#define vm_ci_new_runtime(mid, flag, argc, kwarg) vm_ci_new_runtime_(mid, flag, argc, kwarg, __FILE__, __LINE__) + +#/* This is passed to STATIC_ASSERT. Cannot be an inline function. */ +#define VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg) \ + (((mid ) & ~CI_EMBED_ID_MASK) ? false : \ + ((flag) & ~CI_EMBED_FLAG_MASK) ? false : \ + ((argc) & ~CI_EMBED_ARGC_MASK) ? false : \ + (kwarg) ? false : true) + +#define vm_ci_new_id(mid, flag, argc, must_zero) \ + ((const struct rb_callinfo *) \ + ((((VALUE)(mid )) << CI_EMBED_ID_SHFT) | \ + (((VALUE)(flag)) << CI_EMBED_FLAG_SHFT) | \ + (((VALUE)(argc)) << CI_EMBED_ARGC_SHFT) | \ + RUBY_FIXNUM_FLAG)) + +static inline const struct rb_callinfo * +vm_ci_new_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinfo_kwarg *kwarg, const char *file, int line) +{ +#if USE_EMBED_CI + if (VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg)) { + RB_DEBUG_COUNTER_INC(ci_packed); + return vm_ci_new_id(mid, flag, argc, kwarg); + } +#endif + + const bool debug = 0; + if (debug) ruby_debug_printf("%s:%d ", file, line); + + // TODO: dedup + const struct rb_callinfo *ci = (const struct rb_callinfo *) + rb_imemo_new(imemo_callinfo, + (VALUE)mid, + (VALUE)flag, + (VALUE)argc, + (VALUE)kwarg); + if (debug) rp(ci); + if (kwarg) { + RB_DEBUG_COUNTER_INC(ci_kw); + } + else { + RB_DEBUG_COUNTER_INC(ci_nokw); + } + + VM_ASSERT(vm_ci_flag(ci) == flag); + VM_ASSERT(vm_ci_argc(ci) == argc); + + return ci; +} + + +static inline const struct rb_callinfo * +vm_ci_new_runtime_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinfo_kwarg *kwarg, const char *file, int line) +{ + RB_DEBUG_COUNTER_INC(ci_runtime); + return vm_ci_new_(mid, flag, argc, kwarg, file, line); +} + +#define VM_CALLINFO_NOT_UNDER_GC IMEMO_FL_USER0 + +static inline bool +vm_ci_markable(const struct rb_callinfo *ci) +{ + if (! ci) { + return false; /* or true? This is Qfalse... */ + } + else if (vm_ci_packed_p(ci)) { + return true; + } + else { + VM_ASSERT(IMEMO_TYPE_P(ci, imemo_callinfo)); + return ! FL_ANY_RAW((VALUE)ci, VM_CALLINFO_NOT_UNDER_GC); + } +} + +#define VM_CI_ON_STACK(mid_, flags_, argc_, kwarg_) \ + (struct rb_callinfo) { \ + .flags = T_IMEMO | \ + (imemo_callinfo << FL_USHIFT) | \ + VM_CALLINFO_NOT_UNDER_GC, \ + .mid = mid_, \ + .flag = flags_, \ + .argc = argc_, \ + .kwarg = kwarg_, \ + } + +typedef VALUE (*vm_call_handler)( + struct rb_execution_context_struct *ec, + struct rb_control_frame_struct *cfp, + struct rb_calling_info *calling); + +// imemo_callcache + +struct rb_callcache { + const VALUE flags; + + /* inline cache: key */ + const VALUE klass; // should not mark it because klass can not be free'd + // because of this marking. When klass is collected, + // cc will be cleared (cc->klass = 0) at vm_ccs_free(). + + /* inline cache: values */ + const struct rb_callable_method_entry_struct * const cme_; + const vm_call_handler call_; + + union { + const unsigned int attr_index; + const enum method_missing_reason method_missing_reason; /* used by method_missing */ + VALUE v; + } aux_; +}; + +#define VM_CALLCACHE_UNMARKABLE IMEMO_FL_USER0 +#define VM_CALLCACHE_ON_STACK IMEMO_FL_USER1 + +static inline const struct rb_callcache * +vm_cc_new(VALUE klass, + const struct rb_callable_method_entry_struct *cme, + vm_call_handler call) +{ + const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass); + RB_DEBUG_COUNTER_INC(cc_new); + return cc; +} + +#define VM_CC_ON_STACK(clazz, call, aux, cme) \ + (struct rb_callcache) { \ + .flags = T_IMEMO | \ + (imemo_callcache << FL_USHIFT) | \ + VM_CALLCACHE_UNMARKABLE | \ + VM_CALLCACHE_ON_STACK, \ + .klass = clazz, \ + .cme_ = cme, \ + .call_ = call, \ + .aux_ = aux, \ + } + +static inline bool +vm_cc_class_check(const struct rb_callcache *cc, VALUE klass) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc->klass == 0 || + RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS)); + return cc->klass == klass; +} + +static inline int +vm_cc_markable(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + return FL_TEST_RAW((VALUE)cc, VM_CALLCACHE_UNMARKABLE) == 0; +} + +static inline const struct rb_callable_method_entry_struct * +vm_cc_cme(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc->call_ == NULL || // not initialized yet + !vm_cc_markable(cc) || + cc->cme_ != NULL); + + return cc->cme_; +} + +static inline vm_call_handler +vm_cc_call(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc->call_ != NULL); + return cc->call_; +} + +static inline unsigned int +vm_cc_attr_index(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + return cc->aux_.attr_index; +} + +static inline unsigned int +vm_cc_cmethod_missing_reason(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + return cc->aux_.method_missing_reason; +} + +static inline bool +vm_cc_invalidated_p(const struct rb_callcache *cc) +{ + if (cc->klass && !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc))) { + return false; + } + else { + return true; + } +} + +// For MJIT. cc_cme is supposed to have inlined `vm_cc_cme(cc)`. +static inline bool +vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *cc_cme, VALUE klass) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + if (cc->klass == klass && !METHOD_ENTRY_INVALIDATED(cc_cme)) { + return 1; + } + else { + return 0; + } +} + +extern const struct rb_callcache *rb_vm_empty_cc(void); +extern const struct rb_callcache *rb_vm_empty_cc_for_super(void); +#define vm_cc_empty() rb_vm_empty_cc() + +/* callcache: mutate */ + +static inline void +vm_cc_call_set(const struct rb_callcache *cc, vm_call_handler call) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc != vm_cc_empty()); + *(vm_call_handler *)&cc->call_ = call; +} + +static inline void +vm_cc_attr_index_set(const struct rb_callcache *cc, int index) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc != vm_cc_empty()); + *(int *)&cc->aux_.attr_index = index; +} + +static inline void +vm_cc_method_missing_reason_set(const struct rb_callcache *cc, enum method_missing_reason reason) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc != vm_cc_empty()); + *(enum method_missing_reason *)&cc->aux_.method_missing_reason = reason; +} + +static inline void +vm_cc_invalidate(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc != vm_cc_empty()); + VM_ASSERT(cc->klass != 0); // should be enable + + *(VALUE *)&cc->klass = 0; + RB_DEBUG_COUNTER_INC(cc_ent_invalidate); +} + +/* calldata */ + +struct rb_call_data { + const struct rb_callinfo *ci; + const struct rb_callcache *cc; +}; + +struct rb_class_cc_entries { +#if VM_CHECK_MODE > 0 + VALUE debug_sig; +#endif + int capa; + int len; + const struct rb_callable_method_entry_struct *cme; + struct rb_class_cc_entries_entry { + const struct rb_callinfo *ci; + const struct rb_callcache *cc; + } *entries; +}; + +#if VM_CHECK_MODE > 0 + +const rb_callable_method_entry_t *rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t *cme); +void rb_vm_dump_overloaded_cme_table(void); + +static inline bool +vm_ccs_p(const struct rb_class_cc_entries *ccs) +{ + return ccs->debug_sig == ~(VALUE)ccs; +} + +static inline bool +vm_cc_check_cme(const struct rb_callcache *cc, const rb_callable_method_entry_t *cme) +{ + if (vm_cc_cme(cc) == cme || + (cme->def->iseq_overload && vm_cc_cme(cc) == rb_vm_lookup_overloaded_cme(cme))) { + return true; + } + else { +#if 1 + // debug print + + fprintf(stderr, "iseq_overload:%d\n", (int)cme->def->iseq_overload); + rp(cme); + rp(vm_cc_cme(cc)); + rb_vm_lookup_overloaded_cme(cme); +#endif + return false; + } +} + +#endif + +// gc.c +void rb_vm_ccs_free(struct rb_class_cc_entries *ccs); + +#endif /* RUBY_VM_CALLINFO_H */ diff --git a/ruby/vm_core.h b/ruby/vm_core.h index 12c3ac377..11866b85e 100644 --- a/ruby/vm_core.h +++ b/ruby/vm_core.h @@ -1,3 +1,5 @@ +#ifndef RUBY_VM_CORE_H +#define RUBY_VM_CORE_H /********************************************************************** vm_core.h - @@ -9,9 +11,6 @@ **********************************************************************/ -#ifndef RUBY_VM_CORE_H -#define RUBY_VM_CORE_H - /* * Enable check mode. * 1: enable local assertions. @@ -46,6 +45,12 @@ #define VMDEBUG 3 #endif +#include "ruby/internal/config.h" + +#include +#include +#include + #include "ruby_assert.h" #if VM_CHECK_MODE > 0 @@ -57,6 +62,26 @@ #define VM_UNREACHABLE(func) UNREACHABLE #endif +#include + +#include "ruby/internal/stdbool.h" +#include "ccan/list/list.h" +#include "id.h" +#include "internal.h" +#include "internal/array.h" +#include "internal/serial.h" +#include "internal/vm.h" +#include "method.h" +#include "node.h" +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby_atomic.h" +#include "vm_opts.h" +#include "darray.h" + +#include "ruby/thread_native.h" +#include THREAD_IMPL_H + #define RUBY_VM_THREAD_MODEL 2 /* @@ -69,26 +94,6 @@ # define VM_INSN_INFO_TABLE_IMPL 2 #endif -#include "ruby/ruby.h" -#include "ruby/st.h" - -#include "node.h" -#include "vm_opts.h" -#include "id.h" -#include "method.h" -#include "ruby_atomic.h" -#include "ccan/list/list.h" - -#include "ruby/thread_native.h" -#if defined(_WIN32) -#include "thread_win32.h" -#elif defined(HAVE_PTHREAD_H) -#include "thread_pthread.h" -#endif - -#include -#include - #if defined(NSIG_MAX) /* POSIX issue 8 */ # undef NSIG # define NSIG NSIG_MAX @@ -123,22 +128,15 @@ /* define to 0 to test old code path */ #define WAITPID_USE_SIGCHLD (RUBY_SIGCHLD || SIGCHLD_LOSSY) -#ifdef HAVE_STDARG_PROTOTYPES -#include -#define va_init_list(a,b) va_start((a),(b)) -#else -#include -#define va_init_list(a,b) va_start((a)) -#endif - #if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__) # define USE_SIGALTSTACK -void *rb_register_sigaltstack(void); -# define RB_ALTSTACK_INIT(var) var = rb_register_sigaltstack() -# define RB_ALTSTACK_FREE(var) xfree(var) +void *rb_allocate_sigaltstack(void); +void *rb_register_sigaltstack(void *); +# define RB_ALTSTACK_INIT(var, altstack) var = rb_register_sigaltstack(altstack) +# define RB_ALTSTACK_FREE(var) free(var) # define RB_ALTSTACK(var) var #else /* noop */ -# define RB_ALTSTACK_INIT(var) +# define RB_ALTSTACK_INIT(var, altstack) # define RB_ALTSTACK_FREE(var) # define RB_ALTSTACK(var) (0) #endif @@ -217,15 +215,67 @@ struct rb_control_frame_struct; /* iseq data type */ typedef struct rb_compile_option_struct rb_compile_option_t; -struct iseq_inline_cache_entry { - rb_serial_t ic_serial; - const rb_cref_t *ic_cref; - VALUE value; +union ic_serial_entry { + rb_serial_t raw; + VALUE data[2]; +}; + +// imemo_constcache +struct iseq_inline_constant_cache_entry { + VALUE flags; + + VALUE value; // v0 + union ic_serial_entry ic_serial; // v1, v2 + const rb_cref_t *ic_cref; // v3 +}; +STATIC_ASSERT(sizeof_iseq_inline_constant_cache_entry, + (offsetof(struct iseq_inline_constant_cache_entry, ic_cref) + + sizeof(const rb_cref_t *)) <= sizeof(struct RObject)); + +#if SIZEOF_SERIAL_T <= SIZEOF_VALUE + +#define GET_IC_SERIAL(ice) (ice)->ic_serial.raw +#define SET_IC_SERIAL(ice, v) (ice)->ic_serial.raw = (v) + +#else + +static inline rb_serial_t +get_ic_serial(const struct iseq_inline_constant_cache_entry *ice) +{ + union ic_serial_entry tmp; + tmp.data[0] = ice->ic_serial.data[0]; + tmp.data[1] = ice->ic_serial.data[1]; + return tmp.raw; +} + +#define GET_IC_SERIAL(ice) get_ic_serial(ice) + +static inline void +set_ic_serial(struct iseq_inline_constant_cache_entry *ice, rb_serial_t v) +{ + union ic_serial_entry tmp; + tmp.raw = v; + ice->ic_serial.data[0] = tmp.data[0]; + ice->ic_serial.data[1] = tmp.data[1]; +} + +#define SET_IC_SERIAL(ice, v) set_ic_serial((ice), (v)) + +#endif + +struct iseq_inline_constant_cache { + struct iseq_inline_constant_cache_entry *entry; + // For YJIT: the index to the opt_getinlinecache instruction in the same iseq. + // It's set during compile time and constant once set. + unsigned get_insn_idx; }; struct iseq_inline_iv_cache_entry { - rb_serial_t ic_serial; - size_t index; + struct rb_iv_index_tbl_entry *entry; +}; + +struct iseq_inline_cvar_cache_entry { + struct rb_cvar_class_tbl_entry *entry; }; union iseq_inline_storage_entry { @@ -233,34 +283,20 @@ union iseq_inline_storage_entry { struct rb_thread_struct *running_thread; VALUE value; } once; - struct iseq_inline_cache_entry cache; + struct iseq_inline_constant_cache ic_cache; struct iseq_inline_iv_cache_entry iv_cache; }; -struct rb_call_info_kw_arg { - int keyword_len; - VALUE keywords[1]; -}; - -struct rb_call_info_with_kwarg { - struct rb_call_info ci; - struct rb_call_info_kw_arg *kw_arg; -}; - struct rb_calling_info { + const struct rb_callinfo *ci; + const struct rb_callcache *cc; VALUE block_handler; VALUE recv; int argc; int kw_splat; }; -struct rb_kwarg_call_data { - struct rb_call_cache cc; - struct rb_call_info_with_kwarg ci_kw; -}; - struct rb_execution_context_struct; -typedef VALUE (*vm_call_handler)(struct rb_execution_context_struct *ec, struct rb_control_frame_struct *cfp, struct rb_calling_info *calling, struct rb_call_data *cd); #if 1 #define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj) @@ -308,6 +344,10 @@ pathobj_realpath(VALUE pathobj) /* Forward declarations */ struct rb_mjit_unit; +// List of YJIT block versions +typedef rb_darray(struct yjit_block_version *) rb_yjit_block_array_t; +typedef rb_darray(rb_yjit_block_array_t) rb_yjit_block_array_array_t; + struct rb_iseq_constant_body { enum iseq_type { ISEQ_TYPE_TOP, @@ -418,15 +458,11 @@ struct rb_iseq_constant_body { struct rb_iseq_struct *local_iseq; /* local_iseq->flip_cnt can be modified */ union iseq_inline_storage_entry *is_entries; - struct rb_call_data *call_data; /* A buffer for two arrays: - * struct rb_call_data calls[ci_size]; - * struct rb_kwarg_call_data kw_calls[ci_kw_size]; - * Such that: - * struct rb_kwarg_call_data *kw_calls = &body->call_data[ci_size]; - */ + struct rb_call_data *call_data; //struct rb_call_data calls[ci_size]; struct { rb_snum_t flip_count; + VALUE script_lines; VALUE coverage; VALUE pc2branchindex; VALUE *original_iseq; @@ -435,10 +471,18 @@ struct rb_iseq_constant_body { unsigned int local_table_size; unsigned int is_size; unsigned int ci_size; - unsigned int ci_kw_size; unsigned int stack_max; /* for stack overflow check */ char catch_except_p; /* If a frame of this ISeq may catch exception, set TRUE */ + // If true, this ISeq is leaf *and* backtraces are not used, for example, + // by rb_profile_frames. We verify only leafness on VM_CHECK_MODE though. + // Note that GC allocations might use backtraces due to + // ObjectSpace#trace_object_allocations. + // For more details, see: https://bugs.ruby-lang.org/issues/16956 + bool builtin_inline_p; + struct rb_id_table *outer_variables; + + const rb_iseq_t *mandatory_only_iseq; #if USE_MJIT /* The following fields are MJIT related info. */ @@ -448,7 +492,7 @@ struct rb_iseq_constant_body { struct rb_mjit_unit *jit_unit; #endif - uintptr_t iseq_unique_id; /* -- Remove In 3.0 -- */ + rb_yjit_block_array_array_t yjit_blocks; // empty, or has a size equal to iseq_size }; /* T_IMEMO/iseq */ @@ -565,8 +609,9 @@ void rb_objspace_call_finalizer(struct rb_objspace *); typedef struct rb_hook_list_struct { struct rb_event_hook_struct *hooks; rb_event_flag_t events; - unsigned int need_clean; unsigned int running; + bool need_clean; + bool is_local; } rb_hook_list_t; @@ -576,12 +621,30 @@ typedef const struct rb_builtin_function *RB_BUILTIN; typedef struct rb_vm_struct { VALUE self; - rb_global_vm_lock_t gvl; + struct { + struct list_head set; + unsigned int cnt; + unsigned int blocking_cnt; - struct rb_thread_struct *main_thread; + struct rb_ractor_struct *main_ractor; + struct rb_thread_struct *main_thread; // == vm->ractor.main_ractor->threads.main - /* persists across uncontended GVL release/acquire for time slice */ - const struct rb_thread_struct *running_thread; + struct { + // monitor + rb_nativethread_lock_t lock; + struct rb_ractor_struct *lock_owner; + unsigned int lock_rec; + + // barrier + bool barrier_waiting; + unsigned int barrier_cnt; + rb_nativethread_cond_t barrier_cond; + + // join at exit + rb_nativethread_cond_t terminate_cond; + bool terminate_waiting; + } sync; + } ractor; #ifdef USE_SIGALTSTACK void *main_altstack; @@ -592,9 +655,6 @@ typedef struct rb_vm_struct { struct list_head waiting_pids; /* PID > 0: <=> struct waitpid_state */ struct list_head waiting_grps; /* PID <= 0: <=> struct waitpid_state */ struct list_head waiting_fds; /* <=> struct waiting_fd */ - struct list_head living_threads; - VALUE thgroup_default; - int living_thread_num; /* set in single-threaded processes only: */ volatile int ubf_async_safe; @@ -602,9 +662,7 @@ typedef struct rb_vm_struct { unsigned int running: 1; unsigned int thread_abort_on_exception: 1; unsigned int thread_report_on_exception: 1; - - unsigned int safe_level_: 1; - int sleeper; + unsigned int thread_ignore_deadlock: 1; /* object management */ VALUE mark_object_ary; @@ -618,6 +676,7 @@ typedef struct rb_vm_struct { VALUE expanded_load_path; VALUE loaded_features; VALUE loaded_features_snapshot; + VALUE loaded_features_realpaths; struct st_table *loaded_features_index; struct st_table *loading_table; @@ -626,15 +685,12 @@ typedef struct rb_vm_struct { VALUE cmd[RUBY_NSIG]; } trap_list; - /* hook */ - rb_hook_list_t global_hooks; - /* relation table of ensure - rollback for callcc */ struct st_table *ensure_rollback_table; /* postponed_job (async-signal-safe, NOT thread-safe) */ struct rb_postponed_job_struct *postponed_job_buffer; - int postponed_job_index; + rb_atomic_t postponed_job_index; int src_encoding_index; @@ -642,8 +698,8 @@ typedef struct rb_vm_struct { struct list_head workqueue; /* <=> rb_workqueue_job.jnode */ rb_nativethread_lock_t workqueue_lock; - VALUE verbose, debug, orig_progname, progname; - VALUE coverages; + VALUE orig_progname, progname; + VALUE coverages, me2counter; int coverage_mode; st_table * defined_module_hash; @@ -652,12 +708,23 @@ typedef struct rb_vm_struct { rb_at_exit_list *at_exit; - VALUE *defined_strings; st_table *frozen_strings; const struct rb_builtin_function *builtin_function_table; int builtin_inline_index; + struct rb_id_table *negative_cme_table; + st_table *overloaded_cme_table; // cme -> overloaded_cme + +#ifndef VM_GLOBAL_CC_CACHE_TABLE_SIZE +#define VM_GLOBAL_CC_CACHE_TABLE_SIZE 1023 +#endif + const struct rb_callcache *global_cc_cache_table[VM_GLOBAL_CC_CACHE_TABLE_SIZE]; // vm_eval.c + +#if defined(USE_VM_CLOCK) && USE_VM_CLOCK + uint32_t clock; +#endif + /* params */ struct { /* size in byte */ size_t thread_vm_stack_size; @@ -769,6 +836,8 @@ typedef struct rb_control_frame_struct { #if VM_DEBUG_BP_CHECK VALUE *bp_check; /* cfp[7] */ #endif + // Return address for YJIT code + void *jit_return; } rb_control_frame_t; extern const rb_data_type_t ruby_threadptr_data_type; @@ -802,6 +871,7 @@ struct rb_vm_tag { rb_jmpbuf_t buf; struct rb_vm_tag *prev; enum ruby_tag_type state; + unsigned int lock_rec; }; STATIC_ASSERT(rb_vm_tag_buf_offset, offsetof(struct rb_vm_tag, buf) > 0); @@ -809,10 +879,6 @@ STATIC_ASSERT(rb_vm_tag_buf_end, offsetof(struct rb_vm_tag, buf) + sizeof(rb_jmpbuf_t) < sizeof(struct rb_vm_tag)); -struct rb_vm_protect_tag { - struct rb_vm_protect_tag *prev; -}; - struct rb_unblock_callback { rb_unblock_function_t *func; void *arg; @@ -820,11 +886,6 @@ struct rb_unblock_callback { struct rb_mutex_struct; -typedef struct rb_thread_list_struct{ - struct rb_thread_list_struct *next; - struct rb_thread_struct *th; -} rb_thread_list_t; - typedef struct rb_ensure_entry { VALUE marker; VALUE (*e_proc)(VALUE); @@ -840,24 +901,32 @@ typedef char rb_thread_id_string_t[sizeof(rb_nativethread_id_t) * 2 + 3]; typedef struct rb_fiber_struct rb_fiber_t; -typedef struct rb_execution_context_struct { +struct rb_waiting_list { + struct rb_waiting_list *next; + struct rb_thread_struct *thread; + struct rb_fiber_struct *fiber; +}; + +struct rb_execution_context_struct { /* execution information */ VALUE *vm_stack; /* must free, must mark */ size_t vm_stack_size; /* size in word (byte size / sizeof(VALUE)) */ rb_control_frame_t *cfp; struct rb_vm_tag *tag; - struct rb_vm_protect_tag *protect_tag; /* interrupt flags */ rb_atomic_t interrupt_flag; rb_atomic_t interrupt_mask; /* size should match flag */ +#if defined(USE_VM_CLOCK) && USE_VM_CLOCK + uint32_t checked_clock; +#endif rb_fiber_t *fiber_ptr; struct rb_thread_struct *thread_ptr; /* storage (ec (fiber) local) */ - st_table *local_storage; + struct rb_id_table *local_storage; VALUE local_storage_recursive_hash; VALUE local_storage_recursive_hash_for_trace; @@ -889,7 +958,12 @@ typedef struct rb_execution_context_struct { size_t stack_maxsize; RUBY_ALIGNAS(SIZEOF_VALUE) jmp_buf regs; } machine; -} rb_execution_context_t; +}; + +#ifndef rb_execution_context_t +typedef struct rb_execution_context_struct rb_execution_context_t; +#define rb_execution_context_t rb_execution_context_t +#endif // for builtin.h #define VM_CORE_H_EC_DEFINED 1 @@ -907,9 +981,20 @@ void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t // @param ec the execution context to update. void rb_ec_clear_vm_stack(rb_execution_context_t *ec); +struct rb_ext_config { + bool ractor_safe; +}; + +typedef struct rb_ractor_struct rb_ractor_t; + +#if defined(__linux__) || defined(__FreeBSD__) +# define RB_THREAD_T_HAS_NATIVE_ID +#endif + typedef struct rb_thread_struct { - struct list_node vmlt_node; + struct list_node lt_node; // managed by a ractor VALUE self; + rb_ractor_t *ractor; rb_vm_t *vm; rb_execution_context_t *ec; @@ -927,6 +1012,9 @@ typedef struct rb_thread_struct { rb_nativethread_id_t thread_id; #ifdef NON_SCALAR_THREAD_ID rb_thread_id_string_t thread_id_string; +#endif +#ifdef RB_THREAD_T_HAS_NATIVE_ID + int tid; #endif BITFIELD(enum rb_thread_status, status, 2); /* bit flags */ @@ -958,7 +1046,7 @@ typedef struct rb_thread_struct { VALUE locking_mutex; struct rb_mutex_struct *keeping_mutexes; - rb_thread_list_t *join_list; + struct rb_waiting_list *join_list; union { struct { @@ -972,9 +1060,10 @@ typedef struct rb_thread_struct { } func; } invoke_arg; - enum { + enum thread_invoke_type { thread_invoke_type_none = 0, thread_invoke_type_proc, + thread_invoke_type_ractor_proc, thread_invoke_type_func } invoke_type; @@ -983,11 +1072,18 @@ typedef struct rb_thread_struct { /* fiber */ rb_fiber_t *root_fiber; - rb_jmpbuf_t root_jmpbuf; + + VALUE scheduler; + unsigned blocking; /* misc */ VALUE name; + struct rb_ext_config ext_config; + +#ifdef USE_SIGALTSTACK + void *altstack; +#endif } rb_thread_t; typedef enum { @@ -1009,11 +1105,13 @@ typedef enum { RUBY_SYMBOL_EXPORT_BEGIN /* node -> iseq */ -rb_iseq_t *rb_iseq_new (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type); -rb_iseq_t *rb_iseq_new_top (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent); -rb_iseq_t *rb_iseq_new_main (const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent); -rb_iseq_t *rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, - const rb_iseq_t *parent, enum iseq_type, const rb_compile_option_t*); +rb_iseq_t *rb_iseq_new (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type); +rb_iseq_t *rb_iseq_new_top (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent); +rb_iseq_t *rb_iseq_new_main (const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt); +rb_iseq_t *rb_iseq_new_eval (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth); +rb_iseq_t *rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth, + enum iseq_type, const rb_compile_option_t*); + struct iseq_link_anchor; struct rb_iseq_new_with_callback_callback_func { VALUE flags; @@ -1050,8 +1148,15 @@ typedef struct { const struct rb_block block; unsigned int is_from_method: 1; /* bool */ unsigned int is_lambda: 1; /* bool */ + unsigned int is_isolated: 1; /* bool */ } rb_proc_t; +RUBY_SYMBOL_EXPORT_BEGIN +VALUE rb_proc_isolate(VALUE self); +VALUE rb_proc_isolate_bang(VALUE self); +VALUE rb_proc_ractor_make_shareable(VALUE self); +RUBY_SYMBOL_EXPORT_END + typedef struct { VALUE flags; /* imemo header */ rb_iseq_t *iseq; @@ -1082,35 +1187,6 @@ enum vm_check_match_type { #define VM_CHECKMATCH_TYPE_MASK 0x03 #define VM_CHECKMATCH_ARRAY 0x04 -enum vm_call_flag_bits { - VM_CALL_ARGS_SPLAT_bit, /* m(*args) */ - VM_CALL_ARGS_BLOCKARG_bit, /* m(&block) */ - VM_CALL_FCALL_bit, /* m(...) */ - VM_CALL_VCALL_bit, /* m */ - VM_CALL_ARGS_SIMPLE_bit, /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */ - VM_CALL_BLOCKISEQ_bit, /* has blockiseq */ - VM_CALL_KWARG_bit, /* has kwarg */ - VM_CALL_KW_SPLAT_bit, /* m(**opts) */ - VM_CALL_TAILCALL_bit, /* located at tail position */ - VM_CALL_SUPER_bit, /* super */ - VM_CALL_ZSUPER_bit, /* zsuper */ - VM_CALL_OPT_SEND_bit, /* internal flag */ - VM_CALL__END -}; - -#define VM_CALL_ARGS_SPLAT (0x01 << VM_CALL_ARGS_SPLAT_bit) -#define VM_CALL_ARGS_BLOCKARG (0x01 << VM_CALL_ARGS_BLOCKARG_bit) -#define VM_CALL_FCALL (0x01 << VM_CALL_FCALL_bit) -#define VM_CALL_VCALL (0x01 << VM_CALL_VCALL_bit) -#define VM_CALL_ARGS_SIMPLE (0x01 << VM_CALL_ARGS_SIMPLE_bit) -#define VM_CALL_BLOCKISEQ (0x01 << VM_CALL_BLOCKISEQ_bit) -#define VM_CALL_KWARG (0x01 << VM_CALL_KWARG_bit) -#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit) -#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit) -#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit) -#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit) -#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit) - enum vm_special_object_type { VM_SPECIAL_OBJECT_VMCORE = 1, VM_SPECIAL_OBJECT_CBASE, @@ -1126,11 +1202,12 @@ enum vm_svar_index { }; /* inline cache */ -typedef struct iseq_inline_cache_entry *IC; +typedef struct iseq_inline_constant_cache *IC; typedef struct iseq_inline_iv_cache_entry *IVC; +typedef struct iseq_inline_cvar_cache_entry *ICVARC; typedef union iseq_inline_storage_entry *ISE; -typedef struct rb_call_info *CALL_INFO; -typedef struct rb_call_cache *CALL_CACHE; +typedef const struct rb_callinfo *CALL_INFO; +typedef const struct rb_callcache *CALL_CACHE; typedef struct rb_call_data *CALL_DATA; typedef VALUE CDHASH; @@ -1151,11 +1228,11 @@ typedef rb_control_frame_t * enum { /* Frame/Environment flag bits: - * MMMM MMMM MMMM MMMM ____ FFFF FFFF EEEX (LSB) + * MMMM MMMM MMMM MMMM ____ _FFF FFFF EEEX (LSB) * * X : tag for GC marking (It seems as Fixnum) * EEE : 3 bits Env flags - * FF..: 8 bits Frame flags + * FF..: 7 bits Frame flags * MM..: 15 bits frame magic (to check frame corruption) */ @@ -1173,19 +1250,19 @@ enum { VM_FRAME_MAGIC_MASK = 0x7fff0001, /* frame flag */ - VM_FRAME_FLAG_PASSED = 0x0010, VM_FRAME_FLAG_FINISH = 0x0020, VM_FRAME_FLAG_BMETHOD = 0x0040, VM_FRAME_FLAG_CFRAME = 0x0080, VM_FRAME_FLAG_LAMBDA = 0x0100, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200, VM_FRAME_FLAG_CFRAME_KW = 0x0400, - VM_FRAME_FLAG_CFRAME_EMPTY_KW = 0x0800, /* -- Remove In 3.0 -- */ + VM_FRAME_FLAG_PASSED = 0x0800, /* env flag */ VM_ENV_FLAG_LOCAL = 0x0002, VM_ENV_FLAG_ESCAPED = 0x0004, - VM_ENV_FLAG_WB_REQUIRED = 0x0008 + VM_ENV_FLAG_WB_REQUIRED = 0x0008, + VM_ENV_FLAG_ISOLATED = 0x0010, }; #define VM_ENV_DATA_SIZE ( 3) @@ -1241,13 +1318,6 @@ VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp) return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0; } -/* -- Remove In 3.0 -- */ -static inline int -VM_FRAME_CFRAME_EMPTY_KW_P(const rb_control_frame_t *cfp) -{ - return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_EMPTY_KW) != 0; -} - static inline int VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp) { @@ -1330,6 +1400,7 @@ vm_assert_env(VALUE obj) } #endif +RBIMPL_ATTR_NONNULL((1)) static inline VALUE VM_ENV_ENVVAL(const VALUE *ep) { @@ -1339,6 +1410,7 @@ VM_ENV_ENVVAL(const VALUE *ep) return envval; } +RBIMPL_ATTR_NONNULL((1)) static inline const rb_env_t * VM_ENV_ENVVAL_PTR(const VALUE *ep) { @@ -1639,7 +1711,8 @@ extern void rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const #define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp) #define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp)) void rb_vm_bugreport(const void *); -typedef RETSIGTYPE (*ruby_sighandler_t)(int); +typedef void (*ruby_sighandler_t)(int); +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...)); /* functions about thread/vm execution */ @@ -1676,11 +1749,12 @@ VALUE rb_vm_env_local_variables(const rb_env_t *env); const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env); const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars); void rb_vm_inc_const_missing_count(void); -void rb_vm_gvl_destroy(rb_vm_t *vm); VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat); MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec); +void rb_gvl_destroy(rb_global_vm_lock_t *gvl); + void rb_thread_start_timer_thread(void); void rb_thread_stop_timer_thread(void); void rb_thread_reset_timer_thread(void); @@ -1693,22 +1767,7 @@ rb_vm_living_threads_init(rb_vm_t *vm) list_head_init(&vm->waiting_pids); list_head_init(&vm->workqueue); list_head_init(&vm->waiting_grps); - list_head_init(&vm->living_threads); - vm->living_thread_num = 0; -} - -static inline void -rb_vm_living_threads_insert(rb_vm_t *vm, rb_thread_t *th) -{ - list_add_tail(&vm->living_threads, &th->vmlt_node); - vm->living_thread_num++; -} - -static inline void -rb_vm_living_threads_remove(rb_vm_t *vm, rb_thread_t *th) -{ - list_del(&th->vmlt_node); - vm->living_thread_num--; + list_head_init(&vm->ractor.set); } typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE); @@ -1717,6 +1776,8 @@ rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_cont int rb_vm_get_sourceline(const rb_control_frame_t *); void rb_vm_stack_to_heap(rb_execution_context_t *ec); void ruby_thread_init_stack(rb_thread_t *th); +rb_thread_t * ruby_thread_from_native(void); +int ruby_thread_set_native(rb_thread_t *th); int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp); void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp); MJIT_STATIC VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler); @@ -1734,36 +1795,39 @@ MJIT_STATIC const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_ #define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack] -#define RUBY_CONST_ASSERT(expr) (1/!!(expr)) /* expr must be a compile-time constant */ -#define VM_STACK_OVERFLOWED_P(cfp, sp, margin) \ - (!RUBY_CONST_ASSERT(sizeof(*(sp)) == sizeof(VALUE)) || \ - !RUBY_CONST_ASSERT(sizeof(*(cfp)) == sizeof(rb_control_frame_t)) || \ - ((rb_control_frame_t *)((sp) + (margin)) + 1) >= (cfp)) -#define WHEN_VM_STACK_OVERFLOWED(cfp, sp, margin) \ - if (LIKELY(!VM_STACK_OVERFLOWED_P(cfp, sp, margin))) {(void)0;} else /* overflowed */ -#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) \ - WHEN_VM_STACK_OVERFLOWED(cfp, sp, margin) vm_stackoverflow() +#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) do { \ + STATIC_ASSERT(sizeof_sp, sizeof(*(sp)) == sizeof(VALUE)); \ + STATIC_ASSERT(sizeof_cfp, sizeof(*(cfp)) == sizeof(rb_control_frame_t)); \ + const struct rb_control_frame_struct *bound = (void *)&(sp)[(margin)]; \ + if (UNLIKELY((cfp) <= &bound[1])) { \ + vm_stackoverflow(); \ + } \ +} while (0) + #define CHECK_VM_STACK_OVERFLOW(cfp, margin) \ - WHEN_VM_STACK_OVERFLOWED(cfp, (cfp)->sp, margin) vm_stackoverflow() + CHECK_VM_STACK_OVERFLOW0((cfp), (cfp)->sp, (margin)) VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr); +rb_execution_context_t *rb_vm_main_ractor_ec(rb_vm_t *vm); // ractor.c + /* for thread */ #if RUBY_VM_THREAD_MODEL == 2 -RUBY_SYMBOL_EXPORT_BEGIN +MJIT_SYMBOL_EXPORT_BEGIN +RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; // ractor.c RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr; -RUBY_EXTERN rb_execution_context_t *ruby_current_execution_context_ptr; RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags; RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags; RUBY_EXTERN unsigned int ruby_vm_event_local_num; -RUBY_SYMBOL_EXPORT_END +MJIT_SYMBOL_EXPORT_END #define GET_VM() rb_current_vm() +#define GET_RACTOR() rb_current_ractor() #define GET_THREAD() rb_current_thread() -#define GET_EC() rb_current_execution_context() +#define GET_EC() rb_current_execution_context(true) static inline rb_thread_t * rb_ec_thread_ptr(const rb_execution_context_t *ec) @@ -1771,6 +1835,19 @@ rb_ec_thread_ptr(const rb_execution_context_t *ec) return ec->thread_ptr; } +static inline rb_ractor_t * +rb_ec_ractor_ptr(const rb_execution_context_t *ec) +{ + const rb_thread_t *th = rb_ec_thread_ptr(ec); + if (th) { + VM_ASSERT(th->ractor != NULL); + return th->ractor; + } + else { + return NULL; + } +} + static inline rb_vm_t * rb_ec_vm_ptr(const rb_execution_context_t *ec) { @@ -1784,9 +1861,19 @@ rb_ec_vm_ptr(const rb_execution_context_t *ec) } static inline rb_execution_context_t * -rb_current_execution_context(void) -{ - return ruby_current_execution_context_ptr; +rb_current_execution_context(bool expect_ec) +{ +#ifdef RB_THREAD_LOCAL_SPECIFIER + #ifdef __APPLE__ + rb_execution_context_t *ec = rb_current_ec(); + #else + rb_execution_context_t *ec = ruby_current_ec; + #endif +#else + rb_execution_context_t *ec = native_tls_get(ruby_current_ec_key); +#endif + VM_ASSERT(!expect_ec || ec != NULL); + return ec; } static inline rb_thread_t * @@ -1796,30 +1883,47 @@ rb_current_thread(void) return rb_ec_thread_ptr(ec); } +static inline rb_ractor_t * +rb_current_ractor(void) +{ + if (ruby_single_main_ractor) { + return ruby_single_main_ractor; + } + else { + const rb_execution_context_t *ec = GET_EC(); + return rb_ec_ractor_ptr(ec); + } +} + static inline rb_vm_t * rb_current_vm(void) { +#if 0 // TODO: reconsider the assertions VM_ASSERT(ruby_current_vm_ptr == NULL || ruby_current_execution_context_ptr == NULL || rb_ec_thread_ptr(GET_EC()) == NULL || + rb_ec_thread_ptr(GET_EC())->status == THREAD_KILLED || rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr); +#endif + return ruby_current_vm_ptr; } -static inline void -rb_thread_set_current_raw(const rb_thread_t *th) -{ - ruby_current_execution_context_ptr = th->ec; -} +void rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec, + unsigned int recorded_lock_rec, + unsigned int current_lock_rec); -static inline void -rb_thread_set_current(rb_thread_t *th) +static inline unsigned int +rb_ec_vm_lock_rec(const rb_execution_context_t *ec) { - if (th->vm->running_thread != th) { - th->running_time_us = 0; + rb_vm_t *vm = rb_ec_vm_ptr(ec); + + if (vm->ractor.sync.lock_owner != rb_ec_ractor_ptr(ec)) { + return 0; + } + else { + return vm->ractor.sync.lock_rec; } - rb_thread_set_current_raw(th); - th->vm->running_thread = th; } #else @@ -1830,16 +1934,33 @@ enum { TIMER_INTERRUPT_MASK = 0x01, PENDING_INTERRUPT_MASK = 0x02, POSTPONED_JOB_INTERRUPT_MASK = 0x04, - TRAP_INTERRUPT_MASK = 0x08 + TRAP_INTERRUPT_MASK = 0x08, + TERMINATE_INTERRUPT_MASK = 0x10, + VM_BARRIER_INTERRUPT_MASK = 0x20, }; #define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK) #define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK) #define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK) #define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK) +#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK) +#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK) #define RUBY_VM_INTERRUPTED(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask & \ (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK)) -#define RUBY_VM_INTERRUPTED_ANY(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask) + +static inline bool +RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec) +{ +#if defined(USE_VM_CLOCK) && USE_VM_CLOCK + uint32_t current_clock = rb_ec_vm_ptr(ec)->clock; + + if (current_clock != ec->checked_clock) { + ec->checked_clock = current_clock; + RUBY_VM_SET_TIMER_INTERRUPT(ec); + } +#endif + return ec->interrupt_flag & ~(ec)->interrupt_mask; +} VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt); int rb_signal_buff_size(void); @@ -1858,6 +1979,11 @@ void rb_execution_context_update(const rb_execution_context_t *ec); void rb_execution_context_mark(const rb_execution_context_t *ec); void rb_fiber_close(rb_fiber_t *fib); void Init_native_thread(rb_thread_t *th); +int rb_vm_check_ints_blocking(rb_execution_context_t *ec); + +// vm_sync.h +void rb_vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond); +void rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec); #define RUBY_VM_CHECK_INTS(ec) rb_vm_check_ints(ec) static inline void @@ -1926,17 +2052,24 @@ rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_ev rb_exec_event_hooks(&trace_arg, hooks, pop_p); } +struct rb_ractor_pub { + VALUE self; + uint32_t id; + rb_hook_list_t hooks; +}; + static inline rb_hook_list_t * -rb_vm_global_hooks(const rb_execution_context_t *ec) +rb_ec_ractor_hooks(const rb_execution_context_t *ec) { - return &rb_ec_vm_ptr(ec)->global_hooks; + struct rb_ractor_pub *cr_pub = (struct rb_ractor_pub *)rb_ec_ractor_ptr(ec); + return &cr_pub->hooks; } #define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \ - EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0) + EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0) #define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \ - EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1) + EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1) static inline void rb_exec_event_hook_script_compiled(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE eval_script) @@ -1960,9 +2093,15 @@ extern VALUE rb_get_coverages(void); extern void rb_set_coverages(VALUE, int, VALUE); extern void rb_clear_coverages(void); extern void rb_reset_coverages(void); +extern void rb_resume_coverages(void); +extern void rb_suspend_coverages(void); void rb_postponed_job_flush(rb_vm_t *vm); +// ractor.c +RUBY_EXTERN VALUE rb_eRactorUnsafeError; +RUBY_EXTERN VALUE rb_eRactorIsolationError; + RUBY_SYMBOL_EXPORT_END #endif /* RUBY_VM_CORE_H */ diff --git a/ruby/vm_debug.h b/ruby/vm_debug.h index 8e0350d14..803a7ccf4 100644 --- a/ruby/vm_debug.h +++ b/ruby/vm_debug.h @@ -1,3 +1,5 @@ +#ifndef RUBY_DEBUG_H +#define RUBY_DEBUG_H /********************************************************************** vm_debug.h - YARV Debug function interface @@ -9,11 +11,7 @@ **********************************************************************/ -#ifndef RUBY_DEBUG_H -#define RUBY_DEBUG_H - #include "ruby/ruby.h" -#include "node.h" RUBY_SYMBOL_EXPORT_BEGIN @@ -22,13 +20,105 @@ RUBY_SYMBOL_EXPORT_BEGIN #define dpi(i) ruby_debug_print_id(-1, 0, "", (i)) #define dpn(n) ruby_debug_print_node(-1, 0, "", (n)) +struct RNode; + VALUE ruby_debug_print_value(int level, int debug_level, const char *header, VALUE v); ID ruby_debug_print_id(int level, int debug_level, const char *header, ID id); -NODE *ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node); +struct RNode *ruby_debug_print_node(int level, int debug_level, const char *header, const struct RNode *node); int ruby_debug_print_indent(int level, int debug_level, int indent_level); void ruby_debug_gc_check_func(void); void ruby_set_debug_option(const char *str); RUBY_SYMBOL_EXPORT_END +#ifndef RUBY_DEVEL +# define RUBY_DEVEL 0 +#endif + +#if RUBY_DEVEL +#ifndef USE_RUBY_DEBUG_LOG +#define USE_RUBY_DEBUG_LOG 0 +#endif +#else +// disable on !RUBY_DEVEL +#ifdef USE_RUBY_DEBUG_LOG +#undef USE_RUBY_DEBUG_LOG +#endif +#endif + +/* RUBY_DEBUG_LOG: Logging debug information mechanism + * + * This feature provides a mechanism to store logging information + * to a file, stderr or memory space with simple macros. + * + * The following information will be stored. + * * (1) __FILE__, __LINE__ in C + * * (2) __FILE__, __LINE__ in Ruby + * * (3) __func__ in C (message title) + * * (4) given string with sprintf format + * * (5) Thread number (if multiple threads are running) + * + * This feature is enabled only USE_RUBY_DEBUG_LOG is enabled. + * Release version should not enable it. + * + * Running with the `RUBY_DEBUG_LOG` environment variable enables + * this feature. + * + * # logging into a file + * RUBY_DEBUG_LOG=/path/to/file STDERR + * + * # logging into STDERR + * RUBY_DEBUG_LOG=stderr + * + * # logging into memory space (check with a debugger) + * # It will help if the timing is important. + * RUBY_DEBUG_LOG=mem + * + * RUBY_DEBUG_LOG_FILTER environment variable can specify the filter string. + * If "(3) __func__ in C (message title)" contains the specified string, the + * information will be stored (example: RUBY_DEBUG_LOG_FILTER=str will enable + * only on str related information). + * + * In a MRI source code, you can use the following macros: + * * RUBY_DEBUG_LOG(fmt, ...): Above (1) to (4) will be logged. + * * RUBY_DEBUG_LOG2(file, line, fmt, ...): + * Same as RUBY_DEBUG_LOG(), but (1) will be replaced with given file, line. + */ + +extern enum ruby_debug_log_mode { + ruby_debug_log_disabled = 0x00, + ruby_debug_log_memory = 0x01, + ruby_debug_log_stderr = 0x02, + ruby_debug_log_file = 0x04, +} ruby_debug_log_mode; + +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) +void ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...); +void ruby_debug_log_print(unsigned int n); +bool ruby_debug_log_filter(const char *func_name); + +// convenient macro to log even if the USE_RUBY_DEBUG_LOG macro is not specified. +// You can use this macro for temporary usage (you should not commit it). +#define _RUBY_DEBUG_LOG(...) ruby_debug_log(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__) + +#if defined(USE_RUBY_DEBUG_LOG) && USE_RUBY_DEBUG_LOG +# define RUBY_DEBUG_LOG_ENABLED(func_name) \ + (ruby_debug_log_mode && ruby_debug_log_filter(func_name)) + +#define RUBY_DEBUG_LOG(...) do { \ + if (RUBY_DEBUG_LOG_ENABLED(RUBY_FUNCTION_NAME_STRING)) \ + ruby_debug_log(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__); \ +} while (0) + +#define RUBY_DEBUG_LOG2(file, line, ...) do { \ + if (RUBY_DEBUG_LOG_ENABLED(RUBY_FUNCTION_NAME_STRING)) \ + ruby_debug_log(file, line, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__); \ +} while (0) + +#else +// do nothing +#define RUBY_DEBUG_LOG(...) +#define RUBY_DEBUG_LOG2(file, line, ...) +#endif // USE_RUBY_DEBUG_LOG + #endif /* RUBY_DEBUG_H */ diff --git a/ruby/vm_dump.c b/ruby/vm_dump.c index c778e1b4d..a98f5aace 100644 --- a/ruby/vm_dump.c +++ b/ruby/vm_dump.c @@ -8,31 +8,34 @@ **********************************************************************/ - -#include "internal.h" -#include "addr2line.h" -#include "vm_core.h" -#include "iseq.h" -#include "gc.h" +#include "ruby/internal/config.h" #ifdef HAVE_UCONTEXT_H -#include +# include #endif + #ifdef __APPLE__ -#ifdef HAVE_LIBPROC_H -#include -#endif -#include -#include -#ifdef __LP64__ -#define vm_region_recurse vm_region_recurse_64 -#endif +# ifdef HAVE_LIBPROC_H +# include +# endif +# include +# include +# ifdef __LP64__ +# define vm_region_recurse vm_region_recurse_64 +# endif +/* that is defined in sys/queue.h, and conflicts with + * ccan/list/list.h */ +# undef LIST_HEAD #endif -/* see vm_insnhelper.h for the values */ -#ifndef VMDEBUG -#define VMDEBUG 0 -#endif +#include "addr2line.h" +#include "gc.h" +#include "internal.h" +#include "internal/variable.h" +#include "internal/vm.h" +#include "iseq.h" +#include "vm_core.h" +#include "ractor_core.h" #define MAX_POSBUF 128 @@ -103,11 +106,11 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c } if (cfp->iseq != 0) { -#define RUBY_VM_IFUNC_P(ptr) imemo_type_p((VALUE)ptr, imemo_ifunc) +#define RUBY_VM_IFUNC_P(ptr) IMEMO_TYPE_P(ptr, imemo_ifunc) if (RUBY_VM_IFUNC_P(cfp->iseq)) { iseq_name = ""; } - else if (SYMBOL_P(cfp->iseq)) { + else if (SYMBOL_P((VALUE)cfp->iseq)) { tmp = rb_sym2str((VALUE)cfp->iseq); iseq_name = RSTRING_PTR(tmp); snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name); @@ -159,7 +162,7 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c char buff[0x100]; if (me) { - if (imemo_type_p((VALUE)me, imemo_ment)) { + if (IMEMO_TYPE_P(me, imemo_ment)) { fprintf(stderr, " me:\n"); fprintf(stderr, " called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type)); fprintf(stderr, " owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner)); @@ -467,6 +470,7 @@ rb_vmdebug_thread_dump_state(VALUE self) #endif #if defined(HAVE_BACKTRACE) +# define USE_BACKTRACE 1 # ifdef HAVE_LIBUNWIND # undef backtrace # define backtrace unw_backtrace @@ -569,14 +573,14 @@ backtrace(void **trace, int size) return n; } # elif defined(BROKEN_BACKTRACE) -# undef HAVE_BACKTRACE -# define HAVE_BACKTRACE 0 +# undef USE_BACKTRACE +# define USE_BACKTRACE 0 # endif #else -# define HAVE_BACKTRACE 0 +# define USE_BACKTRACE 0 #endif -#if HAVE_BACKTRACE +#if USE_BACKTRACE # include #elif defined(_WIN32) # include @@ -724,7 +728,7 @@ dump_thread(void *arg) if (pSymFromAddr(ph, addr, &displacement, info)) { if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) fprintf(stderr, "%s", libpath); - fprintf(stderr, "(%s+0x%I64x)", + fprintf(stderr, "(%s+0x%"PRI_64_PREFIX"x)", info->Name, displacement); } fprintf(stderr, " [0x%p]", (void *)(VALUE)addr); @@ -749,7 +753,7 @@ dump_thread(void *arg) void rb_print_backtrace(void) { -#if HAVE_BACKTRACE +#if USE_BACKTRACE #define MAX_NATIVE_TRACE 1024 static void *trace[MAX_NATIVE_TRACE]; int n = (int)backtrace(trace, MAX_NATIVE_TRACE); @@ -778,11 +782,11 @@ rb_print_backtrace(void) #endif #if defined __linux__ -# if defined __x86_64__ || defined __i386__ +# if defined __x86_64__ || defined __i386__ || defined __aarch64__ || defined __arm__ || defined __riscv # define HAVE_PRINT_MACHINE_REGISTERS 1 # endif #elif defined __APPLE__ -# if defined __x86_64__ || defined __i386__ +# if defined __x86_64__ || defined __i386__ || defined __aarch64__ # define HAVE_PRINT_MACHINE_REGISTERS 1 # endif #endif @@ -793,12 +797,9 @@ print_machine_register(size_t reg, const char *reg_name, int col_count, int max_ { int ret; char buf[64]; + static const int size_width = sizeof(size_t) * CHAR_BIT / 4; -#ifdef __LP64__ - ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%016" PRIxSIZE, reg_name, reg); -#else - ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%08" PRIxSIZE, reg_name, reg); -#endif + ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%.*" PRIxSIZE, reg_name, size_width, reg); if (col_count + ret > max_col) { fputs("\n", stderr); col_count = 0; @@ -808,9 +809,17 @@ print_machine_register(size_t reg, const char *reg_name, int col_count, int max_ return col_count; } # ifdef __linux__ -# define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80)) +# if defined(__x86_64__) || defined(__i386__) +# define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80)) +# elif defined(__aarch64__) || defined(__arm__) || defined(__riscv) +# define dump_machine_register(reg, regstr) (col_count = print_machine_register(reg, regstr, col_count, 80)) +# endif # elif defined __APPLE__ -# define dump_machine_register(reg) (col_count = print_machine_register(mctx->MCTX_SS_REG(reg), #reg, col_count, 80)) +# if defined(__aarch64__) +# define dump_machine_register(reg, regstr) (col_count = print_machine_register(mctx->MCTX_SS_REG(reg), regstr, col_count, 80)) +# else +# define dump_machine_register(reg) (col_count = print_machine_register(mctx->MCTX_SS_REG(reg), #reg, col_count, 80)) +# endif # endif static void @@ -864,6 +873,65 @@ rb_dump_machine_register(const ucontext_t *ctx) dump_machine_register(EFL); dump_machine_register(UESP); dump_machine_register(SS); +# elif defined __aarch64__ + dump_machine_register(mctx->regs[0], "x0"); + dump_machine_register(mctx->regs[1], "x1"); + dump_machine_register(mctx->regs[2], "x2"); + dump_machine_register(mctx->regs[3], "x3"); + dump_machine_register(mctx->regs[4], "x4"); + dump_machine_register(mctx->regs[5], "x5"); + dump_machine_register(mctx->regs[6], "x6"); + dump_machine_register(mctx->regs[7], "x7"); + dump_machine_register(mctx->regs[18], "x18"); + dump_machine_register(mctx->regs[19], "x19"); + dump_machine_register(mctx->regs[20], "x20"); + dump_machine_register(mctx->regs[21], "x21"); + dump_machine_register(mctx->regs[22], "x22"); + dump_machine_register(mctx->regs[23], "x23"); + dump_machine_register(mctx->regs[24], "x24"); + dump_machine_register(mctx->regs[25], "x25"); + dump_machine_register(mctx->regs[26], "x26"); + dump_machine_register(mctx->regs[27], "x27"); + dump_machine_register(mctx->regs[28], "x28"); + dump_machine_register(mctx->regs[29], "x29"); + dump_machine_register(mctx->sp, "sp"); + dump_machine_register(mctx->fault_address, "fault_address"); +# elif defined __arm__ + dump_machine_register(mctx->arm_r0, "r0"); + dump_machine_register(mctx->arm_r1, "r1"); + dump_machine_register(mctx->arm_r2, "r2"); + dump_machine_register(mctx->arm_r3, "r3"); + dump_machine_register(mctx->arm_r4, "r4"); + dump_machine_register(mctx->arm_r5, "r5"); + dump_machine_register(mctx->arm_r6, "r6"); + dump_machine_register(mctx->arm_r7, "r7"); + dump_machine_register(mctx->arm_r8, "r8"); + dump_machine_register(mctx->arm_r9, "r9"); + dump_machine_register(mctx->arm_r10, "r10"); + dump_machine_register(mctx->arm_sp, "sp"); + dump_machine_register(mctx->fault_address, "fault_address"); +# elif defined __riscv + dump_machine_register(mctx->__gregs[REG_SP], "sp"); + dump_machine_register(mctx->__gregs[REG_S0], "s0"); + dump_machine_register(mctx->__gregs[REG_S1], "s1"); + dump_machine_register(mctx->__gregs[REG_A0], "a0"); + dump_machine_register(mctx->__gregs[REG_A0+1], "a1"); + dump_machine_register(mctx->__gregs[REG_A0+2], "a2"); + dump_machine_register(mctx->__gregs[REG_A0+3], "a3"); + dump_machine_register(mctx->__gregs[REG_A0+4], "a4"); + dump_machine_register(mctx->__gregs[REG_A0+5], "a5"); + dump_machine_register(mctx->__gregs[REG_A0+6], "a6"); + dump_machine_register(mctx->__gregs[REG_A0+7], "a7"); + dump_machine_register(mctx->__gregs[REG_S2], "s2"); + dump_machine_register(mctx->__gregs[REG_S2+1], "s3"); + dump_machine_register(mctx->__gregs[REG_S2+2], "s4"); + dump_machine_register(mctx->__gregs[REG_S2+3], "s5"); + dump_machine_register(mctx->__gregs[REG_S2+4], "s6"); + dump_machine_register(mctx->__gregs[REG_S2+5], "s7"); + dump_machine_register(mctx->__gregs[REG_S2+6], "s8"); + dump_machine_register(mctx->__gregs[REG_S2+7], "s9"); + dump_machine_register(mctx->__gregs[REG_S2+8], "s10"); + dump_machine_register(mctx->__gregs[REG_S2+9], "s11"); # endif } # elif defined __APPLE__ @@ -905,6 +973,29 @@ rb_dump_machine_register(const ucontext_t *ctx) dump_machine_register(es); dump_machine_register(fs); dump_machine_register(gs); +# elif defined __aarch64__ + dump_machine_register(x[0], "x0"); + dump_machine_register(x[1], "x1"); + dump_machine_register(x[2], "x2"); + dump_machine_register(x[3], "x3"); + dump_machine_register(x[4], "x4"); + dump_machine_register(x[5], "x5"); + dump_machine_register(x[6], "x6"); + dump_machine_register(x[7], "x7"); + dump_machine_register(x[18], "x18"); + dump_machine_register(x[19], "x19"); + dump_machine_register(x[20], "x20"); + dump_machine_register(x[21], "x21"); + dump_machine_register(x[22], "x22"); + dump_machine_register(x[23], "x23"); + dump_machine_register(x[24], "x24"); + dump_machine_register(x[25], "x25"); + dump_machine_register(x[26], "x26"); + dump_machine_register(x[27], "x27"); + dump_machine_register(x[28], "x28"); + dump_machine_register(lr, "lr"); + dump_machine_register(fp, "fp"); + dump_machine_register(sp, "sp"); # endif } # endif @@ -917,6 +1008,18 @@ rb_dump_machine_register(const ucontext_t *ctx) void rb_vm_bugreport(const void *ctx) { +#if RUBY_DEVEL + const char *cmd = getenv("RUBY_ON_BUG"); + if (cmd) { + char buf[0x100]; + snprintf(buf, sizeof(buf), "%s %"PRI_PIDT_PREFIX"d", cmd, getpid()); + int r = system(buf); + if (r == -1) { + snprintf(buf, sizeof(buf), "Launching RUBY_ON_BUG command failed."); + } + } +#endif + #ifdef __linux__ # define PROC_MAPS_NAME "/proc/self/maps" #endif @@ -926,8 +1029,9 @@ rb_vm_bugreport(const void *ctx) enum {other_runtime_info = 0}; #endif const rb_vm_t *const vm = GET_VM(); + const rb_execution_context_t *ec = rb_current_execution_context(false); - if (vm) { + if (vm && ec) { SDR(); rb_backtrace_print_as_bugreport(); fputs("\n", stderr); @@ -935,20 +1039,20 @@ rb_vm_bugreport(const void *ctx) rb_dump_machine_register(ctx); -#if HAVE_BACKTRACE || defined(_WIN32) +#if USE_BACKTRACE || defined(_WIN32) fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); rb_print_backtrace(); fprintf(stderr, "\n"); -#endif /* HAVE_BACKTRACE */ +#endif /* USE_BACKTRACE */ if (other_runtime_info || vm) { fprintf(stderr, "-- Other runtime information " "-----------------------------------------------\n\n"); } - if (vm) { + if (vm && !rb_during_gc()) { int i; VALUE name; long len; @@ -957,39 +1061,43 @@ rb_vm_bugreport(const void *ctx) (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len) name = vm->progname; - fprintf(stderr, "* Loaded script: %.*s\n", - LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); - fprintf(stderr, "\n"); - fprintf(stderr, "* Loaded features:\n\n"); - for (i=0; iloaded_features); i++) { - name = RARRAY_AREF(vm->loaded_features, i); - if (RB_TYPE_P(name, T_STRING)) { - fprintf(stderr, " %4d %.*s\n", i, - LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); - } - else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) { - const char *const type = RB_TYPE_P(name, T_CLASS) ? - "class" : "module"; - name = rb_search_class_path(rb_class_real(name)); - if (!RB_TYPE_P(name, T_STRING)) { - fprintf(stderr, " %4d %s:\n", i, type); - continue; - } - fprintf(stderr, " %4d %s:%.*s\n", i, type, - LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); - } - else { - VALUE klass = rb_search_class_path(rb_obj_class(name)); - if (!RB_TYPE_P(klass, T_STRING)) { - fprintf(stderr, " %4d #<%p:%p>\n", i, - (void *)CLASS_OF(name), (void *)name); - continue; - } - fprintf(stderr, " %4d #<%.*s:%p>\n", i, - LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass), - (void *)name); - } - } + if (name) { + fprintf(stderr, "* Loaded script: %.*s\n", + LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); + fprintf(stderr, "\n"); + } + if (vm->loaded_features) { + fprintf(stderr, "* Loaded features:\n\n"); + for (i=0; iloaded_features); i++) { + name = RARRAY_AREF(vm->loaded_features, i); + if (RB_TYPE_P(name, T_STRING)) { + fprintf(stderr, " %4d %.*s\n", i, + LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); + } + else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) { + const char *const type = RB_TYPE_P(name, T_CLASS) ? + "class" : "module"; + name = rb_search_class_path(rb_class_real(name)); + if (!RB_TYPE_P(name, T_STRING)) { + fprintf(stderr, " %4d %s:\n", i, type); + continue; + } + fprintf(stderr, " %4d %s:%.*s\n", i, type, + LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); + } + else { + VALUE klass = rb_search_class_path(rb_obj_class(name)); + if (!RB_TYPE_P(klass, T_STRING)) { + fprintf(stderr, " %4d #<%p:%p>\n", i, + (void *)CLASS_OF(name), (void *)name); + continue; + } + fprintf(stderr, " %4d #<%.*s:%p>\n", i, + LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass), + (void *)name); + } + } + } fprintf(stderr, "\n"); } @@ -1078,12 +1186,13 @@ const char *ruby_fill_thread_id_string(rb_nativethread_id_t thid, rb_thread_id_s void rb_vmdebug_stack_dump_all_threads(void) { - rb_vm_t *vm = GET_VM(); rb_thread_t *th = NULL; + rb_ractor_t *r = GET_RACTOR(); - list_for_each(&vm->living_threads, th, vmlt_node) { + // TODO: now it only shows current ractor + list_for_each(&r->threads.set, th, lt_node) { #ifdef NON_SCALAR_THREAD_ID - rb_thread_id_string_t buf; + rb_thread_id_string_t buf; ruby_fill_thread_id_string(th->thread_id, buf); fprintf(stderr, "th: %p, native_id: %s\n", th, buf); #else diff --git a/ruby/vm_eval.c b/ruby/vm_eval.c index 76e56fac8..0abb4644f 100644 --- a/ruby/vm_eval.c +++ b/ruby/vm_eval.c @@ -15,12 +15,12 @@ struct local_var_list { VALUE tbl; }; -static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat); +static inline VALUE method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat); static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat, const rb_cref_t *cref, int is_lambda); static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat); static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat); static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args); -VALUE vm_exec(rb_execution_context_t *ec, int mjit_enable_p); +VALUE vm_exec(rb_execution_context_t *ec, bool mjit_enable_p); static void vm_set_eval_stack(rb_execution_context_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, const struct rb_block *base_block); static int vm_collect_local_variables_in_heap(const VALUE *dfp, const struct local_var_list *vars); @@ -38,38 +38,96 @@ typedef enum call_type { } call_type; static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope); -static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv); +static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv); #ifndef MJIT_HEADER MJIT_FUNC_EXPORTED VALUE -rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat) +rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat) { - struct rb_calling_info calling = { Qundef, recv, argc, kw_splat, }; - struct rb_call_info ci = { id, (kw_splat ? VM_CALL_KW_SPLAT : 0), argc, }; - struct rb_call_cache cc = { 0, { 0, }, me, me->def->method_serial, vm_call_general, { 0, }, }; - struct rb_call_data cd = { cc, ci, }; - return vm_call0_body(ec, &calling, &cd, argv); + struct rb_calling_info calling = { + .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL), + .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme), + .block_handler = vm_passed_block_handler(ec), + .recv = recv, + .argc = argc, + .kw_splat = kw_splat, + }; + + return vm_call0_body(ec, &calling, argv); +} + +MJIT_FUNC_EXPORTED VALUE +rb_vm_call_with_refinements(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, int kw_splat) +{ + const rb_callable_method_entry_t *me = + rb_callable_method_entry_with_refinements(CLASS_OF(recv), id, NULL); + if (me) { + return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); + } + else { + /* fallback to funcall (e.g. method_missing) */ + return rb_funcallv(recv, id, argc, argv); + } +} + +static inline VALUE +vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const struct rb_callcache *cc, int kw_splat) +{ + struct rb_calling_info calling = { + .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL), + .cc = cc, + .block_handler = vm_passed_block_handler(ec), + .recv = recv, + .argc = argc, + .kw_splat = kw_splat, + }; + + return vm_call0_body(ec, &calling, argv); +} + +static VALUE +vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme) +{ + calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme); + return vm_call0_body(ec, calling, argv); +} + +static VALUE +vm_call0_super(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, VALUE klass, enum method_missing_reason ex) +{ + ID mid = vm_ci_mid(calling->ci); + klass = RCLASS_SUPER(klass); + + if (klass) { + const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid); + + if (cme) { + RUBY_VM_CHECK_INTS(ec); + return vm_call0_cme(ec, calling, argv, cme); + } + } + + vm_passed_block_handler_set(ec, calling->block_handler); + return method_missing(ec, calling->recv, mid, calling->argc, argv, ex, calling->kw_splat); } static VALUE -vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv) +vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv) { - const struct rb_call_info *ci = &cd->ci; - const struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; VALUE val; - const rb_callable_method_entry_t *me = cc->me; + const rb_callable_method_entry_t *me = vm_cc_cme(calling->cc); const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(me->def, body.cfunc); int len = cfunc->argc; VALUE recv = calling->recv; int argc = calling->argc; - ID mid = ci->mid; + ID mid = vm_ci_mid(ci); VALUE block_handler = calling->block_handler; int frame_flags = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL; if (calling->kw_splat) { if (argc > 0 && RB_TYPE_P(argv[argc-1], T_HASH) && RHASH_EMPTY_P(argv[argc-1])) { - frame_flags |= VM_FRAME_FLAG_CFRAME_EMPTY_KW; argc--; } else { @@ -100,24 +158,35 @@ vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *ca } static VALUE -vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv) +vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv) { - return vm_call0_cfunc_with_frame(ec, calling, cd, argv); + return vm_call0_cfunc_with_frame(ec, calling, argv); +} + +static void +vm_call_check_arity(struct rb_calling_info *calling, int argc, const VALUE *argv) +{ + if (calling->kw_splat && + calling->argc > 0 && + RB_TYPE_P(argv[calling->argc-1], T_HASH) && + RHASH_EMPTY_P(argv[calling->argc-1])) { + calling->argc--; + } + + rb_check_arity(calling->argc, argc, argc); } /* `ci' should point temporal value (on stack value) */ static VALUE -vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv) +vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv) { - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; - + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; VALUE ret; - calling->block_handler = vm_passed_block_handler(ec); + retry: - again: - switch (cc->me->def->type) { + switch (vm_cc_cme(cc)->def->type) { case VM_METHOD_TYPE_ISEQ: { rb_control_frame_t *reg_cfp = ec->cfp; @@ -131,82 +200,69 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc *reg_cfp->sp++ = argv[i]; } - vm_call_iseq_setup(ec, reg_cfp, calling, cd); + vm_call_iseq_setup(ec, reg_cfp, calling); VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH); - return vm_exec(ec, TRUE); /* CHECK_INTS in this function */ + return vm_exec(ec, true); /* CHECK_INTS in this function */ } case VM_METHOD_TYPE_NOTIMPLEMENTED: case VM_METHOD_TYPE_CFUNC: - ret = vm_call0_cfunc(ec, calling, cd, argv); + ret = vm_call0_cfunc(ec, calling, argv); goto success; case VM_METHOD_TYPE_ATTRSET: - if (calling->kw_splat && - calling->argc > 0 && - RB_TYPE_P(argv[calling->argc-1], T_HASH) && - RHASH_EMPTY_P(argv[calling->argc-1])) { - if (calling->argc == 1) { - rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); - } - else { - calling->argc--; - } - } - - rb_check_arity(calling->argc, 1, 1); - ret = rb_ivar_set(calling->recv, cc->me->def->body.attr.id, argv[0]); + vm_call_check_arity(calling, 1, argv); + VM_CALL_METHOD_ATTR(ret, + rb_ivar_set(calling->recv, vm_cc_cme(cc)->def->body.attr.id, argv[0]), + (void)0); goto success; case VM_METHOD_TYPE_IVAR: - if (calling->kw_splat && - calling->argc > 0 && - RB_TYPE_P(argv[calling->argc-1], T_HASH) && - RHASH_EMPTY_P(argv[calling->argc-1])) { - calling->argc--; - } - - rb_check_arity(calling->argc, 0, 0); - ret = rb_attr_get(calling->recv, cc->me->def->body.attr.id); + vm_call_check_arity(calling, 0, argv); + VM_CALL_METHOD_ATTR(ret, + rb_attr_get(calling->recv, vm_cc_cme(cc)->def->body.attr.id), + (void)0); goto success; case VM_METHOD_TYPE_BMETHOD: - ret = vm_call_bmethod_body(ec, calling, cd, argv); + ret = vm_call_bmethod_body(ec, calling, argv); goto success; case VM_METHOD_TYPE_ZSUPER: + { + VALUE klass = RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class); + return vm_call0_super(ec, calling, argv, klass, MISSING_SUPER); + } case VM_METHOD_TYPE_REFINED: { - const rb_method_type_t type = cc->me->def->type; - VALUE super_class = cc->me->defined_class; - - if (type == VM_METHOD_TYPE_ZSUPER) { - super_class = RCLASS_ORIGIN(super_class); - } - else if (cc->me->def->body.refined.orig_me) { - CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me)); - goto again; - } + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); - super_class = RCLASS_SUPER(super_class); - if (super_class) { - CC_SET_ME(cc, rb_callable_method_entry(super_class, ci->mid)); - if (cc->me) { - RUBY_VM_CHECK_INTS(ec); - goto again; - } + if (cme->def->body.refined.orig_me) { + const rb_callable_method_entry_t *orig_cme = refined_method_callable_without_refinement(cme); + return vm_call0_cme(ec, calling, argv, orig_cme); } - enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0; - ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex, calling->kw_splat); - goto success; + VALUE klass = cme->defined_class; + return vm_call0_super(ec, calling, argv, klass, 0); } case VM_METHOD_TYPE_ALIAS: - CC_SET_ME(cc, aliased_callable_method_entry(cc->me)); - goto again; + { + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + const rb_callable_method_entry_t *orig_cme = aliased_callable_method_entry(cme); + + if (cme == orig_cme) rb_bug("same!!"); + + if (vm_cc_markable(cc)) { + return vm_call0_cme(ec, calling, argv, orig_cme); + } + else { + *((const rb_callable_method_entry_t **)&cc->cme_) = orig_cme; + goto retry; + } + } case VM_METHOD_TYPE_MISSING: { - vm_passed_block_handler_set(ec, calling->block_handler); - return method_missing(calling->recv, ci->mid, calling->argc, + vm_passed_block_handler_set(ec, calling->block_handler); + return method_missing(ec, calling->recv, vm_ci_mid(ci), calling->argc, argv, MISSING_NOENTRY, calling->kw_splat); } case VM_METHOD_TYPE_OPTIMIZED: - switch (cc->me->def->body.optimize_type) { + switch (vm_cc_cme(cc)->def->body.optimized.type) { case OPTIMIZED_METHOD_TYPE_SEND: ret = send_internal(calling->argc, argv, calling->recv, calling->kw_splat ? CALL_FCALL_KW : CALL_FCALL); goto success; @@ -217,14 +273,22 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc ret = rb_vm_invoke_proc(ec, proc, calling->argc, argv, calling->kw_splat, calling->block_handler); goto success; } + case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: + vm_call_check_arity(calling, 0, argv); + ret = vm_call_opt_struct_aref0(ec, calling); + goto success; + case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: + vm_call_check_arity(calling, 1, argv); + ret = vm_call_opt_struct_aset0(ec, calling, argv[0]); + goto success; default: - rb_bug("vm_call0: unsupported optimized method type (%d)", cc->me->def->body.optimize_type); + rb_bug("vm_call0: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type); } break; case VM_METHOD_TYPE_UNDEF: break; } - rb_bug("vm_call0: unsupported method type (%d)", cc->me->def->type); + rb_bug("vm_call0: unsupported method type (%d)", vm_cc_cme(cc)->def->type); return Qundef; success: @@ -232,42 +296,10 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc return ret; } -/* Caller should keep the reference to the return value until argv becomes useless. */ -MJIT_FUNC_EXPORTED VALUE -rb_adjust_argv_kw_splat(int *argc, const VALUE **argv, int *kw_splat) -{ - if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) { - if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) { - int n = *argc; - VALUE v; - VALUE *ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE)); - if (n) memcpy(ptr, *argv, sizeof(VALUE)*n); - ptr[n] = rb_hash_new(); - *argc = ++n; - *argv = ptr; - *kw_splat = 1; - return v; - } - else { - *kw_splat = rb_keyword_given_p(); - } - } - - if (*kw_splat && (*argc == 0 || !RB_TYPE_P((*argv)[(*argc)-1], T_HASH))) { - rb_warn("Keyword flag passed calling internal method, but last entry is not a hash, unsetting keyword flag"); - *kw_splat = 0; - } - - return 0; -} - MJIT_FUNC_EXPORTED VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat) { - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); - rb_free_tmp_buffer(&v); - return ret; + return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); } static inline VALUE @@ -289,7 +321,7 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_sp me = rb_callable_method_entry(klass, id); if (!me) { - return method_missing(recv, id, argc, argv, MISSING_SUPER, kw_splat); + return method_missing(ec, recv, id, argc, argv, MISSING_SUPER, kw_splat); } return rb_vm_call_kw(ec, recv, id, argc, argv, me, kw_splat); } @@ -305,9 +337,7 @@ rb_call_super_kw(int argc, const VALUE *argv, int kw_splat) VALUE rb_call_super(int argc, const VALUE *argv) { - rb_execution_context_t *ec = GET_EC(); - PASS_PASSED_BLOCK_HANDLER_EC(ec); - return vm_call_super(ec, argc, argv, RB_NO_KEYWORDS); + return rb_call_super_kw(argc, argv, RB_NO_KEYWORDS); } VALUE @@ -335,9 +365,123 @@ stack_check(rb_execution_context_t *ec) #ifndef MJIT_HEADER +void +rb_check_stack_overflow(void) +{ +#ifndef RB_THREAD_LOCAL_SPECIFIER + if (!ruby_current_ec_key) return; +#endif + rb_execution_context_t *ec = GET_EC(); + if (ec) stack_check(ec); +} + +NORETURN(static void uncallable_object(VALUE recv, ID mid)); static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid); static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self); +static const struct rb_callcache * +cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme) +{ + const struct rb_callcache *cc = NULL; + + RB_VM_LOCK_ENTER(); + { + struct rb_class_cc_entries *ccs; + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + VALUE ccs_data; + + if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { + // ok + ccs = (struct rb_class_cc_entries *)ccs_data; + } + else { + ccs = vm_ccs_create(klass, cme); + rb_id_table_insert(cc_tbl, mid, (VALUE)ccs); + } + + for (int i=0; ilen; i++) { + cc = ccs->entries[i].cc; + if (vm_cc_cme(cc) == cme) { + break; + } + cc = NULL; + } + + if (cc == NULL) { + const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, false); // TODO: proper ci + cc = vm_cc_new(klass, cme, vm_call_general); + METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme); + vm_ccs_push(klass, ccs, ci, cc); + } + } + RB_VM_LOCK_LEAVE(); + + return cc; +} + +static VALUE +gccct_hash(VALUE klass, ID mid) +{ + return (klass >> 3) ^ (VALUE)mid; +} + +NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index)); + +static const struct rb_callcache * +gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index) +{ + const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid); + const struct rb_callcache *cc; + + if (cme != NULL) { + cc = cc_new(klass, mid, argc, cme); + } + else { + cc = NULL; + } + + return vm->global_cc_cache_table[index] = cc; +} + +static inline const struct rb_callcache * +gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc) +{ + VALUE klass; + + if (!SPECIAL_CONST_P(recv)) { + klass = RBASIC_CLASS(recv); + if (UNLIKELY(!klass)) uncallable_object(recv, mid); + } + else { + klass = CLASS_OF(recv); + } + + // search global method cache + unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE); + rb_vm_t *vm = rb_ec_vm_ptr(ec); + const struct rb_callcache *cc = vm->global_cc_cache_table[index]; + + if (LIKELY(cc)) { + if (LIKELY(vm_cc_class_check(cc, klass))) { + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) && + cme->called_id == mid)) { + + VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid))); + RB_DEBUG_COUNTER_INC(gccct_hit); + + return cc; + } + } + } + else { + RB_DEBUG_COUNTER_INC(gccct_null); + } + + RB_DEBUG_COUNTER_INC(gccct_miss); + return gccct_method_search_slowpath(vm, klass, mid, argc, index); +} + /*! * \internal * calls the specified method. @@ -359,17 +503,16 @@ rb_call0(rb_execution_context_t *ec, VALUE recv, ID mid, int argc, const VALUE *argv, call_type call_scope, VALUE self) { - const rb_callable_method_entry_t *me; enum method_missing_reason call_status; call_type scope = call_scope; int kw_splat = RB_NO_KEYWORDS; - switch(scope) { - case(CALL_PUBLIC_KW): + switch (scope) { + case CALL_PUBLIC_KW: scope = CALL_PUBLIC; kw_splat = 1; break; - case(CALL_FCALL_KW): + case CALL_FCALL_KW: scope = CALL_FCALL; kw_splat = 1; break; @@ -377,19 +520,34 @@ rb_call0(rb_execution_context_t *ec, break; } + const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc); + if (scope == CALL_PUBLIC) { - me = rb_callable_method_entry_with_refinements(CLASS_OF(recv), mid, NULL); + RB_DEBUG_COUNTER_INC(call0_public); + + const rb_callable_method_entry_t *cc_cme = cc ? vm_cc_cme(cc) : NULL; + const rb_callable_method_entry_t *cme = callable_method_entry_refeinements0(CLASS_OF(recv), mid, NULL, true, cc_cme); + call_status = rb_method_call_status(ec, cme, scope, self); + + if (UNLIKELY(call_status != MISSING_NONE)) { + return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat); + } + else if (UNLIKELY(cc_cme != cme)) { // refinement is solved + stack_check(ec); + return rb_vm_call_kw(ec, recv, mid, argc, argv, cme, kw_splat); + } } else { - me = rb_search_method_entry(recv, mid); - } - call_status = rb_method_call_status(ec, me, scope, self); + RB_DEBUG_COUNTER_INC(call0_other); + call_status = rb_method_call_status(ec, cc ? vm_cc_cme(cc) : NULL, scope, self); - if (call_status != MISSING_NONE) { - return method_missing(recv, mid, argc, argv, call_status, kw_splat); + if (UNLIKELY(call_status != MISSING_NONE)) { + return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat); + } } + stack_check(ec); - return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat); + return vm_call0_cc(ec, recv, mid, argc, argv, cc, kw_splat); } struct rescue_funcall_args { @@ -397,7 +555,7 @@ struct rescue_funcall_args { VALUE recv; ID mid; rb_execution_context_t *ec; - const rb_method_entry_t *me; + const rb_callable_method_entry_t *cme; unsigned int respond: 1; unsigned int respond_to_missing: 1; int argc; @@ -411,7 +569,7 @@ check_funcall_exec(VALUE v) struct rescue_funcall_args *args = (void *)v; return call_method_entry(args->ec, args->defined_class, args->recv, idMethodMissing, - args->me, args->argc, args->argv, args->kw_splat); + args->cme, args->argc, args->argv, args->kw_splat); } static VALUE @@ -420,8 +578,8 @@ check_funcall_failed(VALUE v, VALUE e) struct rescue_funcall_args *args = (void *)v; int ret = args->respond; if (!ret) { - switch (rb_method_boundp(args->defined_class, args->mid, - BOUND_PRIVATE|BOUND_RESPONDS)) { + switch (method_boundp(args->defined_class, args->mid, + BOUND_PRIVATE|BOUND_RESPONDS)) { case 2: ret = TRUE; break; @@ -455,7 +613,7 @@ static VALUE check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int respond, VALUE def, int kw_splat) { struct rescue_funcall_args args; - const rb_method_entry_t *me; + const rb_callable_method_entry_t *cme; VALUE ret = Qundef; ret = basic_obj_respond_to_missing(ec, klass, recv, @@ -464,8 +622,9 @@ check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mi args.respond = respond > 0; args.respond_to_missing = (ret != Qundef); ret = def; - me = method_entry_get(klass, idMethodMissing, &args.defined_class); - if (me && !METHOD_ENTRY_BASIC(me)) { + cme = callable_method_entry(klass, idMethodMissing, &args.defined_class); + + if (cme && !METHOD_ENTRY_BASIC(cme)) { VALUE argbuf, *new_args = ALLOCV_N(VALUE, argbuf, argc+1); new_args[0] = ID2SYM(mid); @@ -480,7 +639,7 @@ check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mi ec->method_missing_reason = MISSING_NOENTRY; args.ec = ec; args.recv = recv; - args.me = me; + args.cme = cme; args.mid = mid; args.argc = argc + 1; args.argv = new_args; @@ -510,6 +669,8 @@ rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv) static VALUE rb_check_funcall_default_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def, int kw_splat) { + VM_ASSERT(ruby_thread_has_gvl_p()); + VALUE klass = CLASS_OF(recv); const rb_callable_method_entry_t *me; rb_execution_context_t *ec = GET_EC(); @@ -606,7 +767,6 @@ rb_type_str(enum ruby_value_type type) return NULL; } -NORETURN(static void uncallable_object(VALUE recv, ID mid)); static void uncallable_object(VALUE recv, ID mid) { @@ -657,46 +817,44 @@ rb_search_method_entry(VALUE recv, ID mid) static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self) { - VALUE klass; - ID oid; - rb_method_visibility_t visi; - - if (UNDEFINED_METHOD_ENTRY_P(me)) { - undefined: - return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY; + if (UNLIKELY(UNDEFINED_METHOD_ENTRY_P(me))) { + goto undefined; } - if (me->def->type == VM_METHOD_TYPE_REFINED) { - me = rb_resolve_refined_method_callable(Qnil, me); - if (UNDEFINED_METHOD_ENTRY_P(me)) goto undefined; + else if (UNLIKELY(me->def->type == VM_METHOD_TYPE_REFINED)) { + me = rb_resolve_refined_method_callable(Qnil, me); + if (UNDEFINED_METHOD_ENTRY_P(me)) goto undefined; } - klass = me->owner; - oid = me->def->original_id; - visi = METHOD_ENTRY_VISI(me); - - if (oid != idMethodMissing) { - /* receiver specified form for private method */ - if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) { - if (visi == METHOD_VISI_PRIVATE && scope == CALL_PUBLIC) { - return MISSING_PRIVATE; - } + rb_method_visibility_t visi = METHOD_ENTRY_VISI(me); - /* self must be kind of a specified form for protected method */ - if (visi == METHOD_VISI_PROTECTED && scope == CALL_PUBLIC) { - VALUE defined_class = klass; + /* receiver specified form for private method */ + if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) { + if (me->def->original_id == idMethodMissing) { + return MISSING_NONE; + } + else if (visi == METHOD_VISI_PRIVATE && + scope == CALL_PUBLIC) { + return MISSING_PRIVATE; + } + /* self must be kind of a specified form for protected method */ + else if (visi == METHOD_VISI_PROTECTED && + scope == CALL_PUBLIC) { - if (RB_TYPE_P(defined_class, T_ICLASS)) { - defined_class = RBASIC(defined_class)->klass; - } + VALUE defined_class = me->owner; + if (RB_TYPE_P(defined_class, T_ICLASS)) { + defined_class = RBASIC(defined_class)->klass; + } - if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) { - return MISSING_PROTECTED; - } - } - } + if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) { + return MISSING_PROTECTED; + } + } } return MISSING_NONE; + + undefined: + return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY; } @@ -839,18 +997,16 @@ vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv, } static inline VALUE -method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat) +method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat) { VALUE *nargv, result, work, klass; - rb_execution_context_t *ec = GET_EC(); VALUE block_handler = vm_passed_block_handler(ec); const rb_callable_method_entry_t *me; ec->method_missing_reason = call_status; if (id == idMethodMissing) { - missing: - raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING); + goto missing; } nargv = ALLOCV_N(VALUE, work, argc + 1); @@ -874,18 +1030,49 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missin result = rb_vm_call_kw(ec, obj, idMethodMissing, argc, argv, me, kw_splat); if (work) ALLOCV_END(work); return result; + missing: + raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING); + UNREACHABLE_RETURN(Qundef); } #ifndef MJIT_HEADER -/*! - * Calls a method - * \param recv receiver of the method - * \param mid an ID that represents the name of the method - * \param args an Array object which contains method arguments - * - * \pre \a args must refer an Array object. - */ +static inline VALUE +rb_funcallv_scope(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope) +{ + rb_execution_context_t *ec = GET_EC(); + const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc); + VALUE self = ec->cfp->self; + + if (LIKELY(cc) && + LIKELY(rb_method_call_status(ec, vm_cc_cme(cc), scope, self) == MISSING_NONE)) { + // fastpath + return vm_call0_cc(ec, recv, mid, argc, argv, cc, false); + } + else { + return rb_call0(ec, recv, mid, argc, argv, scope, self); + } +} + +#ifdef rb_funcallv +#undef rb_funcallv +#endif +VALUE +rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv) +{ + VM_ASSERT(ruby_thread_has_gvl_p()); + + return rb_funcallv_scope(recv, mid, argc, argv, CALL_FCALL); +} + +VALUE +rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) +{ + VM_ASSERT(ruby_thread_has_gvl_p()); + + return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL); +} + VALUE rb_apply(VALUE recv, ID mid, VALUE args) { @@ -903,21 +1090,14 @@ rb_apply(VALUE recv, ID mid, VALUE args) } argv = ALLOCA_N(VALUE, argc); MEMCPY(argv, RARRAY_CONST_PTR_TRANSIENT(args), VALUE, argc); - return rb_call(recv, mid, argc, argv, CALL_FCALL); + + return rb_funcallv(recv, mid, argc, argv); } #ifdef rb_funcall #undef rb_funcall #endif -/*! - * Calls a method - * \param recv receiver of the method - * \param mid an ID that represents the name of the method - * \param n the number of arguments - * \param ... arbitrary number of method arguments - * - * \pre each of arguments after \a n must be a VALUE. - */ + VALUE rb_funcall(VALUE recv, ID mid, int n, ...) { @@ -927,7 +1107,7 @@ rb_funcall(VALUE recv, ID mid, int n, ...) if (n > 0) { long i; - va_init_list(ar, n); + va_start(ar, n); argv = ALLOCA_N(VALUE, n); @@ -939,111 +1119,60 @@ rb_funcall(VALUE recv, ID mid, int n, ...) else { argv = 0; } - return rb_call(recv, mid, n, argv, CALL_FCALL); + return rb_funcallv(recv, mid, n, argv); } -#ifdef rb_funcallv -#undef rb_funcallv -#endif /*! - * Calls a method + * Calls a method only if it is the basic method of `ancestor` + * otherwise returns Qundef; * \param recv receiver of the method * \param mid an ID that represents the name of the method + * \param ancestor the Class that defined the basic method * \param argc the number of arguments * \param argv pointer to an array of method arguments + * \param kw_splat bool */ VALUE -rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv) +rb_check_funcall_basic_kw(VALUE recv, ID mid, VALUE ancestor, int argc, const VALUE *argv, int kw_splat) { - return rb_call(recv, mid, argc, argv, CALL_FCALL); -} + const rb_callable_method_entry_t *cme; + rb_execution_context_t *ec; + VALUE klass = CLASS_OF(recv); + if (!klass) return Qundef; /* hidden object */ -VALUE -rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) -{ - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL); - rb_free_tmp_buffer(&v); - return ret; + cme = rb_callable_method_entry(klass, mid); + if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == ancestor) { + ec = GET_EC(); + return rb_vm_call0(ec, recv, mid, argc, argv, cme, kw_splat); + } + + return Qundef; } -/*! - * Calls a method. - * - * Same as rb_funcallv but this function can call only public methods. - * \param recv receiver of the method - * \param mid an ID that represents the name of the method - * \param argc the number of arguments - * \param argv pointer to an array of method arguments - */ VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv) { - return rb_call(recv, mid, argc, argv, CALL_PUBLIC); + return rb_funcallv_scope(recv, mid, argc, argv, CALL_PUBLIC); } VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) { - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); - rb_free_tmp_buffer(&v); - return ret; -} - -/*! - * Calls a method - * \private - * \param cd opaque call data - * \param recv receiver of the method - * \param mid an ID that represents the name of the method - * \param argc the number of arguments - * \param argv pointer to an array of method arguments - */ -VALUE -rb_funcallv_with_cc(struct rb_call_data *cd, VALUE recv, ID mid, int argc, const VALUE *argv) -{ - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; - - if (LIKELY(ci->mid == mid)) { - vm_search_method(cd, recv); - - if (LIKELY(! UNDEFINED_METHOD_ENTRY_P(cc->me))) { - return vm_call0_body( - GET_EC(), - &(struct rb_calling_info) { - Qundef, - recv, - argc, - RB_NO_KEYWORDS, - }, - cd, - argv - ); - } - } - - *cd = (struct rb_call_data) /* reset */ { { 0, }, { mid, }, }; - return rb_funcallv(recv, mid, argc, argv); + return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); } VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv) { PASS_PASSED_BLOCK_HANDLER(); - return rb_call(recv, mid, argc, argv, CALL_PUBLIC); + return rb_funcallv_public(recv, mid, argc, argv); } VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) { - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret; PASS_PASSED_BLOCK_HANDLER(); - ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); - rb_free_tmp_buffer(&v); - return ret; + return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); } VALUE @@ -1053,7 +1182,7 @@ rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pas vm_passed_block_handler_set(GET_EC(), passed_procval); } - return rb_call(recv, mid, argc, argv, CALL_PUBLIC); + return rb_funcallv_public(recv, mid, argc, argv); } VALUE @@ -1063,10 +1192,7 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE vm_passed_block_handler_set(GET_EC(), passed_procval); } - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); - rb_free_tmp_buffer(&v); - return ret; + return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); } static VALUE * @@ -1140,10 +1266,7 @@ send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope) static VALUE send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope) { - VALUE v=0, ret; - int kw_splat = RB_PASS_CALLED_KEYWORDS; - v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - if (kw_splat) { + if (rb_keyword_given_p()) { switch (scope) { case CALL_PUBLIC: scope = CALL_PUBLIC_KW; @@ -1155,9 +1278,7 @@ send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope) break; } } - ret = send_internal(argc, argv, recv, scope); - rb_free_tmp_buffer(&v); - return ret; + return send_internal(argc, argv, recv, scope); } /* @@ -1168,12 +1289,14 @@ send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope) * foo.__send__(string [, args...]) -> obj * * Invokes the method identified by _symbol_, passing it any - * arguments specified. You can use __send__ if the name - * +send+ clashes with an existing method in _obj_. + * arguments specified. * When the method is identified by a string, the string is converted * to a symbol. * * BasicObject implements +__send__+, Kernel implements +send+. + * __send__ is safer than +send+ + * when _obj_ has the same method name like Socket. + * See also public_send. * * class Klass * def hello(*args) @@ -1215,10 +1338,7 @@ rb_f_public_send(int argc, VALUE *argv, VALUE recv) static inline VALUE rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat) { - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); - VALUE ret = vm_yield(GET_EC(), argc, argv, kw_splat); - rb_free_tmp_buffer(&v); - return ret; + return vm_yield(GET_EC(), argc, argv, kw_splat); } static inline VALUE @@ -1237,10 +1357,10 @@ VALUE rb_yield(VALUE val) { if (val == Qundef) { - return rb_yield_0(0, 0); + return rb_yield_0(0, NULL); } else { - return rb_yield_1(val); + return rb_yield_0(1, &val); } } @@ -1257,7 +1377,7 @@ rb_yield_values(int n, ...) va_list args; argv = ALLOCA_N(VALUE, n); - va_init_list(args, n); + va_start(args, n); for (i=0; iobj, arg->mid, arg->argc, arg->argv, arg->kw_splat ? CALL_FCALL_KW : CALL_FCALL); } +VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv, rb_block_call_func_t bl_proc, VALUE data2, int kw_splat); + VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv, rb_block_call_func_t bl_proc, VALUE data2) { - struct iter_method_arg arg; - - arg.obj = obj; - arg.mid = mid; - arg.argc = argc; - arg.argv = argv; - arg.kw_splat = 0; - return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); + return rb_block_call_kw(obj, mid, argc, argv, bl_proc, data2, RB_NO_KEYWORDS); } VALUE @@ -1486,15 +1604,12 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv, { struct iter_method_arg arg; - VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); arg.obj = obj; arg.mid = mid; arg.argc = argc; arg.argv = argv; arg.kw_splat = kw_splat; - VALUE ret = rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); - rb_free_tmp_buffer(&v); - return ret; + return rb_iterate_internal(iterate_method, (VALUE)&arg, bl_proc, data2); } VALUE @@ -1535,7 +1650,7 @@ rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, arg.argc = argc; arg.argv = argv; arg.kw_splat = 0; - return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2); + return rb_iterate_internal(iterate_check_method, (VALUE)&arg, bl_proc, data2); } VALUE @@ -1545,15 +1660,34 @@ rb_each(VALUE obj) } void rb_parser_warn_location(VALUE, int); + +static VALUE eval_default_path; + static const rb_iseq_t * eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind, const struct rb_block *base_block) { const VALUE parser = rb_parser_new(); const rb_iseq_t *const parent = vm_block_iseq(base_block); - VALUE realpath = Qnil; rb_iseq_t *iseq = NULL; rb_ast_t *ast; + int isolated_depth = 0; + { + int depth = 1; + const VALUE *ep = vm_block_ep(base_block); + + while (1) { + if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) { + isolated_depth = depth; + break; + } + else if (VM_ENV_LOCAL_P(ep)) { + break; + } + ep = VM_ENV_PREV_EP(ep); + depth++; + } + } if (!fname) { fname = rb_source_location(&line); @@ -1561,25 +1695,23 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind, if (fname != Qundef) { if (!NIL_P(fname)) fname = rb_fstring(fname); - realpath = fname; - } - else if (bind) { - fname = pathobj_path(bind->pathobj); - realpath = pathobj_realpath(bind->pathobj); - line = bind->first_lineno; - rb_parser_warn_location(parser, TRUE); } else { fname = rb_fstring_lit("(eval)"); + if (!eval_default_path) { + eval_default_path = rb_fstring_lit("(eval)"); + rb_gc_register_mark_object(eval_default_path); + } + fname = eval_default_path; } rb_parser_set_context(parser, parent, FALSE); ast = rb_parser_compile_string_path(parser, fname, src, line); if (ast->body.root) { - iseq = rb_iseq_new_with_opt(&ast->body, - parent->body->location.label, - fname, realpath, INT2FIX(line), - parent, ISEQ_TYPE_EVAL, NULL); + iseq = rb_iseq_new_eval(&ast->body, + parent->body->location.label, + fname, Qnil, INT2FIX(line), + parent, isolated_depth); } rb_ast_dispose(ast); @@ -1624,7 +1756,7 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li vm_set_eval_stack(ec, iseq, cref, &block); /* kick */ - return vm_exec(ec, TRUE); + return vm_exec(ec, true); } static VALUE @@ -1645,7 +1777,7 @@ eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line) } /* kick */ - return vm_exec(ec, TRUE); + return vm_exec(ec, true); } /* @@ -1699,18 +1831,6 @@ ruby_eval_string_from_file(const char *str, const char *filename) return eval_string_with_cref(rb_vm_top_self(), rb_str_new2(str), NULL, file, 1); } -/** - * Evaluates the given string in an isolated binding. - * - * Here "isolated" means the binding does not inherit any other binding. This - * behaves same as the binding for required libraries. - * - * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation. - * - * @param str Ruby code to evaluate. - * @return The evaluated result. - * @throw Exception Raises an exception on error. - */ VALUE rb_eval_string(const char *str) { @@ -1723,16 +1843,6 @@ eval_string_protect(VALUE str) return rb_eval_string((char *)str); } -/** - * Evaluates the given string in an isolated binding. - * - * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation. - * - * @sa rb_eval_string - * @param str Ruby code to evaluate. - * @param state Being set to zero if succeeded. Nonzero if an error occurred. - * @return The evaluated result if succeeded, an undefined value if otherwise. - */ VALUE rb_eval_string_protect(const char *str, int *pstate) { @@ -1750,21 +1860,10 @@ eval_string_wrap_protect(VALUE data) { const struct eval_string_wrap_arg *const arg = (struct eval_string_wrap_arg*)data; rb_cref_t *cref = rb_vm_cref_new_toplevel(); - cref->klass = arg->klass; + cref->klass_or_self = arg->klass; return eval_string_with_cref(arg->top_self, rb_str_new_cstr(arg->str), cref, rb_str_new_cstr("eval"), 1); } -/** - * Evaluates the given string under a module binding in an isolated binding. - * This is same as the binding for loaded libraries on "load('foo', true)". - * - * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation. - * - * @sa rb_eval_string - * @param str Ruby code to evaluate. - * @param state Being set to zero if succeeded. Nonzero if an error occurred. - * @return The evaluated result if succeeded, an undefined value if otherwise. - */ VALUE rb_eval_string_wrap(const char *str, int *pstate) { @@ -1820,17 +1919,10 @@ rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat) return val; } -VALUE -rb_eval_cmd(VALUE cmd, VALUE arg, int _level) -{ - rb_warn("rb_eval_cmd will be removed in Ruby 3.0"); - return rb_eval_cmd_kw(cmd, arg, RB_NO_KEYWORDS); -} - /* block eval under the class/module context */ static VALUE -yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat) +yield_under(VALUE self, int singleton, int argc, const VALUE *argv, int kw_splat) { rb_execution_context_t *ec = GET_EC(); rb_control_frame_t *cfp = ec->cfp; @@ -1841,9 +1933,6 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat) const VALUE *ep = NULL; rb_cref_t *cref; int is_lambda = FALSE; - VALUE v = 0, ret; - - v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat); if (block_handler != VM_BLOCK_HANDLER_NONE) { again: @@ -1863,10 +1952,9 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat) block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler)); goto again; case block_handler_type_symbol: - ret = rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)), - argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE); - rb_free_tmp_buffer(&v); - return ret; + return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)), + argc, argv, kw_splat, + VM_BLOCK_HANDLER_NONE); } new_captured.self = self; @@ -1875,10 +1963,10 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat) VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); } - cref = vm_cref_push(ec, under, ep, TRUE); - ret = vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda); - rb_free_tmp_buffer(&v); - return ret; + VM_ASSERT(singleton || RB_TYPE_P(self, T_MODULE) || RB_TYPE_P(self, T_CLASS)); + cref = vm_cref_push(ec, self, ep, TRUE, singleton); + + return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda); } VALUE @@ -1895,7 +1983,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements) struct rb_captured_block new_captured = *captured; VALUE new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured); const VALUE *ep = captured->ep; - rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE); + rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE, FALSE); CREF_REFINEMENTS_SET(cref, refinements); VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); new_captured.self = refinement; @@ -1905,19 +1993,20 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements) /* string eval under the class/module context */ static VALUE -eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line) +eval_under(VALUE self, int singleton, VALUE src, VALUE file, int line) { - rb_cref_t *cref = vm_cref_push(GET_EC(), under, NULL, SPECIAL_CONST_P(self) && !NIL_P(under)); + rb_cref_t *cref = vm_cref_push(GET_EC(), self, NULL, FALSE, singleton); SafeStringValue(src); + return eval_string_with_cref(self, src, cref, file, line); } static VALUE -specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self, int kw_splat) +specific_eval(int argc, const VALUE *argv, VALUE self, int singleton, int kw_splat) { if (rb_block_given_p()) { rb_check_arity(argc, 0, 0); - return yield_under(klass, self, 1, &self, kw_splat); + return yield_under(self, singleton, 1, &self, kw_splat); } else { VALUE file = Qundef; @@ -1933,23 +2022,7 @@ specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self, int kw_splat file = argv[1]; if (!NIL_P(file)) StringValue(file); } - return eval_under(klass, self, code, file, line); - } -} - -static VALUE -singleton_class_for_eval(VALUE self) -{ - if (SPECIAL_CONST_P(self)) { - return rb_special_singleton_class(self); - } - switch (BUILTIN_TYPE(self)) { - case T_FLOAT: case T_BIGNUM: case T_SYMBOL: - return Qnil; - case T_STRING: - if (FL_TEST_RAW(self, RSTRING_FSTR)) return Qnil; - default: - return rb_singleton_class(self); + return eval_under(self, singleton, code, file, line); } } @@ -1989,15 +2062,13 @@ singleton_class_for_eval(VALUE self) static VALUE rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self) { - VALUE klass = singleton_class_for_eval(self); - return specific_eval(argc, argv, klass, self, RB_PASS_CALLED_KEYWORDS); + return specific_eval(argc, argv, self, TRUE, RB_PASS_CALLED_KEYWORDS); } VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self) { - VALUE klass = singleton_class_for_eval(self); - return specific_eval(argc, argv, klass, self, RB_NO_KEYWORDS); + return specific_eval(argc, argv, self, TRUE, RB_NO_KEYWORDS); } /* @@ -2021,15 +2092,13 @@ rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self) static VALUE rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self) { - VALUE klass = singleton_class_for_eval(self); - return yield_under(klass, self, argc, argv, RB_PASS_CALLED_KEYWORDS); + return yield_under(self, TRUE, argc, argv, RB_PASS_CALLED_KEYWORDS); } VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self) { - VALUE klass = singleton_class_for_eval(self); - return yield_under(klass, self, argc, argv, RB_NO_KEYWORDS); + return yield_under(self, TRUE, argc, argv, RB_NO_KEYWORDS); } /* @@ -2062,13 +2131,13 @@ rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self) static VALUE rb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod) { - return specific_eval(argc, argv, mod, mod, RB_PASS_CALLED_KEYWORDS); + return specific_eval(argc, argv, mod, FALSE, RB_PASS_CALLED_KEYWORDS); } VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod) { - return specific_eval(argc, argv, mod, mod, RB_NO_KEYWORDS); + return specific_eval(argc, argv, mod, FALSE, RB_NO_KEYWORDS); } /* @@ -2096,13 +2165,13 @@ rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod) static VALUE rb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod) { - return yield_under(mod, mod, argc, argv, RB_PASS_CALLED_KEYWORDS); + return yield_under(mod, FALSE, argc, argv, RB_PASS_CALLED_KEYWORDS); } VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod) { - return yield_under(mod, mod, argc, argv, RB_NO_KEYWORDS); + return yield_under(mod, FALSE, argc, argv, RB_NO_KEYWORDS); } /* @@ -2424,7 +2493,6 @@ rb_f_local_variables(VALUE _) /* * call-seq: * block_given? -> true or false - * iterator? -> true or false * * Returns true if yield would execute a * block in the current context. The iterator? form @@ -2442,7 +2510,6 @@ rb_f_local_variables(VALUE _) * try do "hello" end #=> "hello" */ - static VALUE rb_f_block_given_p(VALUE _) { @@ -2450,12 +2517,21 @@ rb_f_block_given_p(VALUE _) rb_control_frame_t *cfp = ec->cfp; cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); - if (cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE) { - return Qtrue; - } - else { - return Qfalse; - } + return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE); +} + +/* + * call-seq: + * iterator? -> true or false + * + * Deprecated. Use block_given? instead. + */ + +static VALUE +rb_f_iterator_p(VALUE self) +{ + rb_warn_deprecated("iterator?", "block_given?"); + return rb_f_block_given_p(self); } VALUE @@ -2464,7 +2540,18 @@ rb_current_realfilepath(void) const rb_execution_context_t *ec = GET_EC(); rb_control_frame_t *cfp = ec->cfp; cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); - if (cfp != 0) return rb_iseq_realpath(cfp->iseq); + if (cfp != NULL) { + VALUE path = rb_iseq_realpath(cfp->iseq); + if (RTEST(path)) return path; + // eval context + path = rb_iseq_path(cfp->iseq); + if (path == eval_default_path) { + return Qnil; + } + else { + return path; + } + } return Qnil; } @@ -2473,7 +2560,7 @@ Init_vm_eval(void) { rb_define_global_function("eval", rb_f_eval, -1); rb_define_global_function("local_variables", rb_f_local_variables, 0); - rb_define_global_function("iterator?", rb_f_block_given_p, 0); + rb_define_global_function("iterator?", rb_f_iterator_p, 0); rb_define_global_function("block_given?", rb_f_block_given_p, 0); rb_define_global_function("catch", rb_f_catch, -1); diff --git a/ruby/vm_exec.c b/ruby/vm_exec.c index 0adaa7b72..8931799c2 100644 --- a/ruby/vm_exec.c +++ b/ruby/vm_exec.c @@ -15,6 +15,37 @@ static void vm_analysis_insn(int insn); #endif +MAYBE_UNUSED(static void vm_insns_counter_count_insn(int insn)); +#if USE_INSNS_COUNTER +static size_t rb_insns_counter[VM_INSTRUCTION_SIZE]; + +static void +vm_insns_counter_count_insn(int insn) +{ + rb_insns_counter[insn]++; +} + +__attribute__((destructor)) +static void +vm_insns_counter_show_results_at_exit(void) +{ + int insn_end = (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS) + ? VM_INSTRUCTION_SIZE : VM_INSTRUCTION_SIZE / 2; + + size_t total = 0; + for (int insn = 0; insn < insn_end; insn++) + total += rb_insns_counter[insn]; + + for (int insn = 0; insn < insn_end; insn++) { + fprintf(stderr, "[RUBY_INSNS_COUNTER]\t%-32s%'12"PRIuSIZE" (%4.1f%%)\n", + insn_name(insn), rb_insns_counter[insn], + 100.0 * rb_insns_counter[insn] / total); + } +} +#else +static void vm_insns_counter_count_insn(int insn) {} +#endif + #if VMDEBUG > 0 #define DECL_SC_REG(type, r, reg) register type reg_##r @@ -27,22 +58,14 @@ static void vm_analysis_insn(int insn); #elif defined(__GNUC__) && defined(__powerpc64__) #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg) +#elif defined(__GNUC__) && defined(__aarch64__) +#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg) + #else #define DECL_SC_REG(type, r, reg) register type reg_##r #endif /* #define DECL_SC_REG(r, reg) VALUE reg_##r */ -#if VM_DEBUG_STACKOVERFLOW -NORETURN(static void vm_stack_overflow_for_insn(void)); -static void -vm_stack_overflow_for_insn(void) -{ - rb_bug("CHECK_VM_STACK_OVERFLOW_FOR_INSN: should not overflow here. " - "Please contact ruby-core/dev with your (a part of) script. " - "This check will be removed soon."); -} -#endif - #if !OPT_CALL_THREADED_CODE static VALUE vm_exec_core(rb_execution_context_t *ec, VALUE initial) @@ -74,9 +97,16 @@ vm_exec_core(rb_execution_context_t *ec, VALUE initial) DECL_SC_REG(rb_control_frame_t *, cfp, "15"); #define USE_MACHINE_REGS 1 +#elif defined(__GNUC__) && defined(__aarch64__) + DECL_SC_REG(const VALUE *, pc, "19"); + DECL_SC_REG(rb_control_frame_t *, cfp, "20"); +#define USE_MACHINE_REGS 1 + #else register rb_control_frame_t *reg_cfp; const VALUE *reg_pc; +#define USE_MACHINE_REGS 0 + #endif #if USE_MACHINE_REGS diff --git a/ruby/vm_exec.h b/ruby/vm_exec.h index 9c8b42371..89c925cbb 100644 --- a/ruby/vm_exec.h +++ b/ruby/vm_exec.h @@ -1,3 +1,5 @@ +#ifndef RUBY_VM_EXEC_H +#define RUBY_VM_EXEC_H /********************************************************************** vm.h - @@ -9,9 +11,6 @@ **********************************************************************/ -#ifndef RUBY_VM_EXEC_H -#define RUBY_VM_EXEC_H - typedef long OFFSET; typedef unsigned long lindex_t; typedef VALUE GENTRY; @@ -38,8 +37,12 @@ typedef rb_iseq_t *ISEQ; #define DEBUG_END_INSN() #endif -#define throwdebug if(0)printf -/* #define throwdebug printf */ +#define throwdebug if(0)ruby_debug_printf +/* #define throwdebug ruby_debug_printf */ + +#ifndef USE_INSNS_COUNTER +#define USE_INSNS_COUNTER 0 +#endif /************************************************/ #if defined(DISPATCH_XXX) @@ -71,11 +74,14 @@ error ! #define LABEL_PTR(x) RB_GNUC_EXTENSION(&&LABEL(x)) #define INSN_ENTRY_SIG(insn) \ - if (0) fprintf(stderr, "exec: %s@(%"PRIdPTRDIFF", %"PRIdPTRDIFF")@%s:%u\n", #insn, \ - (reg_pc - reg_cfp->iseq->body->iseq_encoded), \ - (reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded), \ - RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \ - rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded)); + if (0) { \ + ruby_debug_printf("exec: %s@(%"PRIdPTRDIFF", %"PRIdPTRDIFF")@%s:%u\n", #insn, \ + (reg_pc - reg_cfp->iseq->body->iseq_encoded), \ + (reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded), \ + RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \ + rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded)); \ + } \ + if (USE_INSNS_COUNTER) vm_insns_counter_count_insn(BIN(insn)); #define INSN_DISPATCH_SIG(insn) @@ -126,9 +132,6 @@ error ! #define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__) -#define START_OF_ORIGINAL_INSN(x) start_of_##x: -#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x; - /************************************************/ #else /* no threaded code */ /* most common method */ @@ -153,9 +156,11 @@ default: \ #define NEXT_INSN() goto first -#define START_OF_ORIGINAL_INSN(x) start_of_##x: -#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x; +#endif +#ifndef START_OF_ORIGINAL_INSN +#define START_OF_ORIGINAL_INSN(x) if (0) goto start_of_##x; start_of_##x: +#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x; #endif #define VM_SP_CNT(ec, sp) ((sp) - (ec)->vm_stack) @@ -181,8 +186,7 @@ default: \ #define VM_DEBUG_STACKOVERFLOW 0 #if VM_DEBUG_STACKOVERFLOW -#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin) \ - WHEN_VM_STACK_OVERFLOWED(cfp, (cfp)->sp, margin) vm_stack_overflow_for_insn() +#define CHECK_VM_STACK_OVERFLOW_FOR_INSN CHECK_VM_STACK_OVERFLOW #else #define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin) #endif diff --git a/ruby/vm_insnhelper.c b/ruby/vm_insnhelper.c index 2ac006a60..e01d39de7 100644 --- a/ruby/vm_insnhelper.c +++ b/ruby/vm_insnhelper.c @@ -8,17 +8,28 @@ **********************************************************************/ +#include "ruby/internal/config.h" + +#include + +#include "constant.h" +#include "debug_counter.h" +#include "internal.h" +#include "internal/class.h" +#include "internal/compar.h" +#include "internal/hash.h" +#include "internal/numeric.h" +#include "internal/proc.h" +#include "internal/random.h" +#include "internal/variable.h" +#include "internal/struct.h" +#include "variable.h" + /* finish iseq array */ #include "insns.inc" #ifndef MJIT_HEADER #include "insns_info.inc" #endif -#include -#include "constant.h" -#include "internal.h" -#include "ruby/config.h" -#include "debug_counter.h" -#include "variable.h" extern rb_method_definition_t *rb_method_definition_create(rb_method_type_t type, ID mid); extern void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts); @@ -26,6 +37,11 @@ extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_me extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj, int argc, const VALUE *argv, int priv); +#ifndef MJIT_HEADER +static const struct rb_callcache vm_empty_cc; +static const struct rb_callcache vm_empty_cc_for_super; +#endif + /* control stack frame */ static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); @@ -55,6 +71,9 @@ ec_stack_overflow(rb_execution_context_t *ec, int setup) } NORETURN(static void vm_stackoverflow(void)); +#ifdef MJIT_HEADER +NOINLINE(static COLDFUNC void vm_stackoverflow(void)); +#endif static void vm_stackoverflow(void) @@ -66,7 +85,10 @@ NORETURN(MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int c MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit) { - if (crit || rb_during_gc()) { + if (rb_during_gc()) { + rb_bug("system stack overflow during GC. Faulty native extension?"); + } + if (crit) { ec->raised_flag = RAISED_STACKOVERFLOW; ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal]; EC_JUMP_TAG(ec, TAG_RAISE); @@ -86,6 +108,8 @@ callable_class_p(VALUE klass) #if VM_CHECK_MODE >= 2 if (!klass) return FALSE; switch (RB_BUILTIN_TYPE(klass)) { + default: + break; case T_ICLASS: if (!RB_TYPE_P(RCLASS_SUPER(klass), T_MODULE)) break; case T_MODULE: @@ -104,13 +128,20 @@ callable_class_p(VALUE klass) } static int -callable_method_entry_p(const rb_callable_method_entry_t *me) +callable_method_entry_p(const rb_callable_method_entry_t *cme) { - if (me == NULL || callable_class_p(me->defined_class)) { - return TRUE; + if (cme == NULL) { + return TRUE; } else { - return FALSE; + VM_ASSERT(IMEMO_TYPE_P((VALUE)cme, imemo_ment)); + + if (callable_class_p(cme->defined_class)) { + return TRUE; + } + else { + return FALSE; + } } } @@ -206,8 +237,9 @@ vm_check_frame(VALUE type, static VALUE vm_stack_canary; /* Initialized later */ static bool vm_stack_canary_was_born = false; -static void -vm_check_canary(const rb_execution_context_t *ec, VALUE *sp) +#ifndef MJIT_HEADER +MJIT_FUNC_EXPORTED void +rb_vm_check_canary(const rb_execution_context_t *ec, VALUE *sp) { const struct rb_control_frame_struct *reg_cfp = ec->cfp; const struct rb_iseq_struct *iseq; @@ -245,7 +277,7 @@ vm_check_canary(const rb_execution_context_t *ec, VALUE *sp) /* rb_bug() is not capable of outputting this large contents. It is designed to run form a SIGSEGV handler, which tends to be very restricted. */ - fprintf(stderr, + ruby_debug_printf( "We are killing the stack canary set by %s, " "at %s@pc=%"PRIdPTR"\n" "watch out the C stack trace.\n" @@ -253,12 +285,69 @@ vm_check_canary(const rb_execution_context_t *ec, VALUE *sp) name, stri, pos, strd); rb_bug("see above."); } +#endif +#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp) + #else #define vm_check_canary(ec, sp) #define vm_check_frame(a, b, c, d) #endif /* VM_CHECK_MODE > 0 */ -static inline rb_control_frame_t * +#if USE_DEBUG_COUNTER +static void +vm_push_frame_debug_counter_inc( + const struct rb_execution_context_struct *ec, + const struct rb_control_frame_struct *reg_cfp, + VALUE type) +{ + const struct rb_control_frame_struct *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp); + + RB_DEBUG_COUNTER_INC(frame_push); + + if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) { + const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp); + const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp); + if (prev) { + if (curr) { + RB_DEBUG_COUNTER_INC(frame_R2R); + } + else { + RB_DEBUG_COUNTER_INC(frame_R2C); + } + } + else { + if (curr) { + RB_DEBUG_COUNTER_INC(frame_C2R); + } + else { + RB_DEBUG_COUNTER_INC(frame_C2C); + } + } + } + + switch (type & VM_FRAME_MAGIC_MASK) { + case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method); return; + case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block); return; + case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class); return; + case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top); return; + case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc); return; + case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc); return; + case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval); return; + case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue); return; + case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy); return; + } + + rb_bug("unreachable"); +} +#else +#define vm_push_frame_debug_counter_inc(ec, cfp, t) /* void */ +#endif + +STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2); +STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1); +STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0); + +static void vm_push_frame(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE type, @@ -279,14 +368,6 @@ vm_push_frame(rb_execution_context_t *ec, CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max); vm_check_canary(ec, sp); - ec->cfp = cfp; - - /* setup new frame */ - cfp->pc = (VALUE *)pc; - cfp->iseq = (rb_iseq_t *)iseq; - cfp->self = self; - cfp->block_code = NULL; - /* setup vm value stack */ /* initialize local variables */ @@ -295,54 +376,31 @@ vm_push_frame(rb_execution_context_t *ec, } /* setup ep with managing data */ - VM_ASSERT(VM_ENV_DATA_INDEX_ME_CREF == -2); - VM_ASSERT(VM_ENV_DATA_INDEX_SPECVAL == -1); - VM_ASSERT(VM_ENV_DATA_INDEX_FLAGS == -0); *sp++ = cref_or_me; /* ep[-2] / Qnil or T_IMEMO(cref) or T_IMEMO(ment) */ *sp++ = specval /* ep[-1] / block handler or prev env ptr */; - *sp = type; /* ep[-0] / ENV_FLAGS */ - - /* Store initial value of ep as bp to skip calculation cost of bp on JIT cancellation. */ - cfp->ep = sp; - cfp->__bp__ = cfp->sp = sp + 1; + *sp++ = type; /* ep[-0] / ENV_FLAGS */ + /* setup new frame */ + *cfp = (const struct rb_control_frame_struct) { + .pc = pc, + .sp = sp, + .iseq = iseq, + .self = self, + .ep = sp - 1, + .block_code = NULL, + .__bp__ = sp, /* Store initial value of ep as bp to skip calculation cost of bp on JIT cancellation. */ #if VM_DEBUG_BP_CHECK - cfp->bp_check = sp + 1; + .bp_check = sp, #endif + .jit_return = NULL + }; + + ec->cfp = cfp; if (VMDEBUG == 2) { SDR(); } - -#if USE_DEBUG_COUNTER - RB_DEBUG_COUNTER_INC(frame_push); - switch (type & VM_FRAME_MAGIC_MASK) { - case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method); break; - case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block); break; - case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class); break; - case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top); break; - case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc); break; - case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc); break; - case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval); break; - case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue); break; - case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy); break; - default: rb_bug("unreachable"); - } - { - rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) { - int cur_ruby_frame = VM_FRAME_RUBYFRAME_P(cfp); - int pre_ruby_frame = VM_FRAME_RUBYFRAME_P(prev_cfp); - - pre_ruby_frame ? (cur_ruby_frame ? RB_DEBUG_COUNTER_INC(frame_R2R) : - RB_DEBUG_COUNTER_INC(frame_R2C)): - (cur_ruby_frame ? RB_DEBUG_COUNTER_INC(frame_C2R) : - RB_DEBUG_COUNTER_INC(frame_C2C)); - } - } -#endif - - return cfp; + vm_push_frame_debug_counter_inc(ec, cfp, type); } /* return TRUE if the frame is finished */ @@ -622,8 +680,19 @@ rb_vm_frame_method_entry(const rb_control_frame_t *cfp) return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE); } +static const rb_iseq_t * +method_entry_iseqptr(const rb_callable_method_entry_t *me) +{ + switch (me->def->type) { + case VM_METHOD_TYPE_ISEQ: + return me->def->body.iseq.iseqptr; + default: + return NULL; + } +} + static rb_cref_t * -method_entry_cref(rb_callable_method_entry_t *me) +method_entry_cref(const rb_callable_method_entry_t *me) { switch (me->def->type) { case VM_METHOD_TYPE_ISEQ: @@ -721,7 +790,7 @@ cref_replace_with_duplicated_cref_each_frame(const VALUE *vptr, int can_be_svar, return (rb_cref_t *)new_cref; case imemo_svar: if (can_be_svar) { - return cref_replace_with_duplicated_cref_each_frame((const VALUE *)&((struct vm_svar *)v)->cref_or_me, FALSE, v); + return cref_replace_with_duplicated_cref_each_frame(&((struct vm_svar *)v)->cref_or_me, FALSE, v); } /* fall through */ case imemo_ment: @@ -768,6 +837,12 @@ vm_get_cref(const VALUE *ep) } } +rb_cref_t * +rb_vm_get_cref(const VALUE *ep) +{ + return vm_get_cref(ep); +} + static rb_cref_t * vm_ec_cref(const rb_execution_context_t *ec) { @@ -811,13 +886,13 @@ rb_vm_rewrite_cref(rb_cref_t *cref, VALUE old_klass, VALUE new_klass, rb_cref_t new_cref = vm_cref_new_use_prev(CREF_CLASS(cref), METHOD_VISI_UNDEF, FALSE, cref, FALSE); cref = CREF_NEXT(cref); *new_cref_ptr = new_cref; - new_cref_ptr = (rb_cref_t **)&new_cref->next; + new_cref_ptr = &new_cref->next; } *new_cref_ptr = NULL; } static rb_cref_t * -vm_cref_push(const rb_execution_context_t *ec, VALUE klass, const VALUE *ep, int pushed_by_eval) +vm_cref_push(const rb_execution_context_t *ec, VALUE klass, const VALUE *ep, int pushed_by_eval, int singleton) { rb_cref_t *prev_cref = NULL; @@ -832,40 +907,30 @@ vm_cref_push(const rb_execution_context_t *ec, VALUE klass, const VALUE *ep, int } } - return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval); + return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton); } static inline VALUE vm_get_cbase(const VALUE *ep) { const rb_cref_t *cref = vm_get_cref(ep); - VALUE klass = Qundef; - - while (cref) { - if ((klass = CREF_CLASS(cref)) != 0) { - break; - } - cref = CREF_NEXT(cref); - } - return klass; + return CREF_CLASS_FOR_DEFINITION(cref); } static inline VALUE vm_get_const_base(const VALUE *ep) { const rb_cref_t *cref = vm_get_cref(ep); - VALUE klass = Qundef; while (cref) { - if (!CREF_PUSHED_BY_EVAL(cref) && - (klass = CREF_CLASS(cref)) != 0) { - break; - } - cref = CREF_NEXT(cref); + if (!CREF_PUSHED_BY_EVAL(cref)) { + return CREF_CLASS_FOR_DEFINITION(cref); + } + cref = CREF_NEXT(cref); } - return klass; + return Qundef; } static inline void @@ -885,7 +950,7 @@ vm_ensure_not_refinement_module(VALUE self) } static inline VALUE -vm_get_iclass(rb_control_frame_t *cfp, VALUE klass) +vm_get_iclass(const rb_control_frame_t *cfp, VALUE klass) { return klass; } @@ -896,7 +961,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_ void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id); VALUE val; - if (orig_klass == Qnil && allow_nil) { + if (NIL_P(orig_klass) && allow_nil) { /* in current lexical scope */ const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep); const rb_cref_t *cref; @@ -934,7 +999,13 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_ if (is_defined) { return 1; } - else { + else { + if (UNLIKELY(!rb_ractor_main_p())) { + if (!rb_ractor_shareable_p(val)) { + rb_raise(rb_eRactorIsolationError, + "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main ractor.", rb_class_path(klass), rb_id2name(id)); + } + } return val; } } @@ -969,7 +1040,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_ } static inline VALUE -vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp) +vm_get_cvar_base(const rb_cref_t *cref, const rb_control_frame_t *cfp, int top_level_raise) { VALUE klass; @@ -979,11 +1050,11 @@ vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp) while (CREF_NEXT(cref) && (NIL_P(CREF_CLASS(cref)) || FL_TEST(CREF_CLASS(cref), FL_SINGLETON) || - CREF_PUSHED_BY_EVAL(cref))) { + CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) { cref = CREF_NEXT(cref); } - if (!CREF_NEXT(cref)) { - rb_warn("class variable access from toplevel"); + if (top_level_raise && !CREF_NEXT(cref)) { + rb_raise(rb_eRuntimeError, "class variable access from toplevel"); } klass = vm_get_iclass(cfp, CREF_CLASS(cref)); @@ -1008,9 +1079,42 @@ vm_search_const_defined_class(const VALUE cbase, ID id) return 0; } -ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, IVC, struct rb_call_cache *, int)); +static bool +iv_index_tbl_lookup(struct st_table *iv_index_tbl, ID id, struct rb_iv_index_tbl_entry **ent) +{ + int found; + st_data_t ent_data; + + if (iv_index_tbl == NULL) return false; + + RB_VM_LOCK_ENTER(); + { + found = st_lookup(iv_index_tbl, (st_data_t)id, &ent_data); + } + RB_VM_LOCK_LEAVE(); + if (found) *ent = (struct rb_iv_index_tbl_entry *)ent_data; + + return found ? true : false; +} + +ALWAYS_INLINE(static void fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent)); + +static inline void +fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent) +{ + // fill cache + if (!is_attr) { + ic->entry = ent; + RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value); + } + else { + vm_cc_attr_index_set(cc, (int)ent->index + 1); + } +} + +ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, const rb_iseq_t *, IVC, const struct rb_callcache *, int)); static inline VALUE -vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr) +vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr) { #if OPT_IC_FOR_IVAR VALUE val = Qundef; @@ -1019,64 +1123,48 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr) // frozen? } else if (LIKELY(is_attr ? - RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, cc->aux.index > 0) : + RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, vm_cc_attr_index(cc) > 0) : RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_serial, - ic->ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) { - st_index_t index = !is_attr ? ic->index : (cc->aux.index - 1); + ic->entry && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) { + uint32_t index = !is_attr ? ic->entry->index : (vm_cc_attr_index(cc) - 1); RB_DEBUG_COUNTER_INC(ivar_get_ic_hit); if (LIKELY(BUILTIN_TYPE(obj) == T_OBJECT) && LIKELY(index < ROBJECT_NUMIV(obj))) { val = ROBJECT_IVPTR(obj)[index]; + + VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true); } else if (FL_TEST_RAW(obj, FL_EXIVAR)) { - struct gen_ivtbl *ivtbl; - - if (LIKELY(st_lookup(rb_ivar_generic_ivtbl(), (st_data_t)obj, (st_data_t *)&ivtbl)) && - LIKELY(index < ivtbl->numiv)) { - val = ivtbl->ivptr[index]; - } + val = rb_ivar_generic_lookup_with_index(obj, id, index); } + goto ret; } else { - struct st_table *iv_index_tbl; - st_index_t numiv; - VALUE *ivptr; - - st_data_t index; + struct rb_iv_index_tbl_entry *ent; if (BUILTIN_TYPE(obj) == T_OBJECT) { - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - numiv = ROBJECT_NUMIV(obj); - ivptr = ROBJECT_IVPTR(obj); - - fill: - if (iv_index_tbl) { - if (st_lookup(iv_index_tbl, id, &index)) { - if (!is_attr) { - ic->index = index; - ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass); - } - else { /* call_info */ - cc->aux.index = (int)index + 1; - } + struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (index < numiv) { - val = ivptr[index]; - } - } - } - } + if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) { + fill_ivar_cache(iseq, ic, cc, is_attr, ent); + + // get value + if (ent->index < ROBJECT_NUMIV(obj)) { + val = ROBJECT_IVPTR(obj)[ent->index]; + + VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true); + } + } + } else if (FL_TEST_RAW(obj, FL_EXIVAR)) { - struct gen_ivtbl *ivtbl; + struct st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - if (LIKELY(st_lookup(rb_ivar_generic_ivtbl(), (st_data_t)obj, (st_data_t *)&ivtbl))) { - numiv = ivtbl->numiv; - ivptr = ivtbl->ivptr; - iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); - goto fill; + if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) { + fill_ivar_cache(iseq, ic, cc, is_attr, ent); + val = rb_ivar_generic_lookup_with_index(obj, id, ent->index); } } else { @@ -1089,9 +1177,6 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr) return val; } else { - if (!is_attr && RTEST(ruby_verbose)) { - rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); - } return Qnil; } } @@ -1107,64 +1192,217 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr) } } +ALWAYS_INLINE(static VALUE vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)); +NOINLINE(static VALUE vm_setivar_slowpath_ivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic)); +NOINLINE(static VALUE vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache *cc)); + +static VALUE +vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr) +{ + rb_check_frozen_internal(obj); + +#if OPT_IC_FOR_IVAR + if (RB_TYPE_P(obj, T_OBJECT)) { + struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + struct rb_iv_index_tbl_entry *ent; + + if (iv_index_tbl_lookup(iv_index_tbl, id, &ent)) { + if (!is_attr) { + ic->entry = ent; + RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value); + } + else if (ent->index >= INT_MAX) { + rb_raise(rb_eArgError, "too many instance variables"); + } + else { + vm_cc_attr_index_set(cc, (int)(ent->index + 1)); + } + + uint32_t index = ent->index; + + if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) { + rb_init_iv_list(obj); + } + VALUE *ptr = ROBJECT_IVPTR(obj); + RB_OBJ_WRITE(obj, &ptr[index], val); + RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit); + + return val; + } + } +#endif + RB_DEBUG_COUNTER_INC(ivar_set_ic_miss); + return rb_ivar_set(obj, id, val); +} + +static VALUE +vm_setivar_slowpath_ivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic) +{ + return vm_setivar_slowpath(obj, id, val, iseq, ic, NULL, false); +} + +static VALUE +vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache *cc) +{ + return vm_setivar_slowpath(obj, id, val, NULL, NULL, cc, true); +} + static inline VALUE -vm_setivar(VALUE obj, ID id, VALUE val, IVC ic, struct rb_call_cache *cc, int is_attr) +vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr) { #if OPT_IC_FOR_IVAR - rb_check_frozen_internal(obj); + if (LIKELY(RB_TYPE_P(obj, T_OBJECT)) && + LIKELY(!RB_OBJ_FROZEN_RAW(obj))) { - if (LIKELY(RB_TYPE_P(obj, T_OBJECT))) { - VALUE klass = RBASIC(obj)->klass; - st_data_t index; + VM_ASSERT(!rb_ractor_shareable_p(obj)); if (LIKELY( - (!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->ic_serial == RCLASS_SERIAL(klass))) || - ( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, cc->aux.index > 0)))) { - VALUE *ptr = ROBJECT_IVPTR(obj); - index = !is_attr ? ic->index : cc->aux.index-1; - - if (RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_oorange, index < ROBJECT_NUMIV(obj))) { - RB_OBJ_WRITE(obj, &ptr[index], val); - RB_DEBUG_COUNTER_INC(ivar_set_ic_hit); - return val; /* inline cache hit */ - } - } - else { - struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + (!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->entry && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass))) || + ( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, vm_cc_attr_index(cc) > 0)))) { + uint32_t index = !is_attr ? ic->entry->index : vm_cc_attr_index(cc)-1; - if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { - if (!is_attr) { - ic->index = index; - ic->ic_serial = RCLASS_SERIAL(klass); - } - else if (index >= INT_MAX) { - rb_raise(rb_eArgError, "too many instance variables"); - } - else { - cc->aux.index = (int)(index + 1); - } - } - /* fall through */ + if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) { + rb_init_iv_list(obj); + } + VALUE *ptr = ROBJECT_IVPTR(obj); + RB_OBJ_WRITE(obj, &ptr[index], val); + RB_DEBUG_COUNTER_INC(ivar_set_ic_hit); + return val; /* inline cache hit */ } } else { RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject); } #endif /* OPT_IC_FOR_IVAR */ - RB_DEBUG_COUNTER_INC(ivar_set_ic_miss); - return rb_ivar_set(obj, id, val); + if (is_attr) { + return vm_setivar_slowpath_attr(obj, id, val, cc); + } + else { + return vm_setivar_slowpath_ivar(obj, id, val, iseq, ic); + } +} + +static VALUE +update_classvariable_cache(const rb_iseq_t *iseq, VALUE klass, ID id, ICVARC ic) +{ + VALUE defined_class = 0; + VALUE cvar_value = rb_cvar_find(klass, id, &defined_class); + + if (RB_TYPE_P(defined_class, T_ICLASS)) { + defined_class = RBASIC(defined_class)->klass; + } + + struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(defined_class); + if (!rb_cvc_tbl) { + rb_bug("the cvc table should be set"); + } + + VALUE ent_data; + if (!rb_id_table_lookup(rb_cvc_tbl, id, &ent_data)) { + rb_bug("should have cvar cache entry"); + } + + struct rb_cvar_class_tbl_entry *ent = (void *)ent_data; + ent->global_cvar_state = GET_GLOBAL_CVAR_STATE(); + + ic->entry = ent; + RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value); + + return cvar_value; +} + +static inline VALUE +vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *reg_cfp, ID id, ICVARC ic) +{ + const rb_cref_t *cref; + + if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) { + VALUE v = Qundef; + RB_DEBUG_COUNTER_INC(cvar_read_inline_hit); + + if (st_lookup(RCLASS_IV_TBL(ic->entry->class_value), (st_data_t)id, &v) && + LIKELY(rb_ractor_main_p())) { + + return v; + } + } + + cref = vm_get_cref(GET_EP()); + VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1); + + return update_classvariable_cache(iseq, klass, id, ic); +} + +VALUE +rb_vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, ICVARC ic) +{ + return vm_getclassvariable(iseq, cfp, id, ic); +} + +static inline void +vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *reg_cfp, ID id, VALUE val, ICVARC ic) +{ + const rb_cref_t *cref; + + if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) { + RB_DEBUG_COUNTER_INC(cvar_write_inline_hit); + + rb_class_ivar_set(ic->entry->class_value, id, val); + return; + } + + cref = vm_get_cref(GET_EP()); + VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1); + + rb_cvar_set(klass, id, val); + + update_classvariable_cache(iseq, klass, id, ic); +} + +void +rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic) +{ + vm_setclassvariable(iseq, cfp, id, val, ic); } static inline VALUE -vm_getinstancevariable(VALUE obj, ID id, IVC ic) +vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic) { - return vm_getivar(obj, id, ic, NULL, FALSE); + return vm_getivar(obj, id, iseq, ic, NULL, FALSE); } static inline void -vm_setinstancevariable(VALUE obj, ID id, VALUE val, IVC ic) +vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic) +{ + vm_setivar(obj, id, val, iseq, ic, 0, 0); +} + +void +rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic) +{ + vm_setinstancevariable(iseq, obj, id, val, ic); +} + +/* Set the instance variable +val+ on object +obj+ at the +index+. + * This function only works with T_OBJECT objects, so make sure + * +obj+ is of type T_OBJECT before using this function. + */ +VALUE +rb_vm_set_ivar_idx(VALUE obj, uint32_t index, VALUE val) { - vm_setivar(obj, id, val, ic, 0, 0); + RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT)); + + rb_check_frozen_internal(obj); + + VM_ASSERT(!rb_ractor_shareable_p(obj)); + + if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) { + rb_init_iv_list(obj); + } + VALUE *ptr = ROBJECT_IVPTR(obj); + RB_OBJ_WRITE(obj, &ptr[index], val); + + return val; } static VALUE @@ -1264,13 +1502,22 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c } else if (state == TAG_RETURN) { const VALUE *current_ep = GET_EP(); - const VALUE *target_lep = VM_EP_LEP(current_ep); + const VALUE *target_ep = NULL, *target_lep, *ep = current_ep; int in_class_frame = 0; int toplevel = 1; escape_cfp = reg_cfp; - while (escape_cfp < eocfp) { - const VALUE *lep = VM_CF_LEP(escape_cfp); + // find target_lep, target_ep + while (!VM_ENV_LOCAL_P(ep)) { + if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) { + target_ep = ep; + } + ep = VM_ENV_PREV_EP(ep); + } + target_lep = ep; + + while (escape_cfp < eocfp) { + const VALUE *lep = VM_CF_LEP(escape_cfp); if (!target_lep) { target_lep = lep; @@ -1288,7 +1535,7 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c toplevel = 0; if (in_class_frame) { /* lambda {class A; ... return ...; end} */ - goto valid_return; + goto valid_return; } else { const VALUE *tep = current_ep; @@ -1296,7 +1543,12 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c while (target_lep != tep) { if (escape_cfp->ep == tep) { /* in lambda */ - goto valid_return; + if (tep == target_ep) { + goto valid_return; + } + else { + goto unexpected_return; + } } tep = VM_ENV_PREV_EP(tep); } @@ -1308,7 +1560,12 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c case ISEQ_TYPE_MAIN: if (toplevel) { if (in_class_frame) goto unexpected_return; - goto valid_return; + if (target_ep == NULL) { + goto valid_return; + } + else { + goto unexpected_return; + } } break; case ISEQ_TYPE_EVAL: @@ -1322,7 +1579,12 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c } if (escape_cfp->ep == target_lep && escape_cfp->iseq->body->type == ISEQ_TYPE_METHOD) { - goto valid_return; + if (target_ep == NULL) { + goto valid_return; + } + else { + goto unexpected_return; + } } escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp); @@ -1422,245 +1684,326 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag) RB_GC_GUARD(ary); } -static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd); +static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling); -#ifdef __has_attribute -#if __has_attribute(artificial) -__attribute__((__artificial__)) -#endif -#endif -static inline vm_call_handler -calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me) +static VALUE vm_mtbl_dump(VALUE klass, ID target_mid); + +static struct rb_class_cc_entries * +vm_ccs_create(VALUE klass, const rb_callable_method_entry_t *cme) { - const struct rb_call_info *ci = &cd->ci; - const struct rb_call_cache *cc = &cd->cc; + struct rb_class_cc_entries *ccs = ALLOC(struct rb_class_cc_entries); +#if VM_CHECK_MODE > 0 + ccs->debug_sig = ~(VALUE)ccs; +#endif + ccs->capa = 0; + ccs->len = 0; + RB_OBJ_WRITE(klass, &ccs->cme, cme); + METHOD_ENTRY_CACHED_SET((rb_callable_method_entry_t *)cme); + ccs->entries = NULL; + return ccs; +} - if (UNLIKELY(!me)) { - RB_DEBUG_COUNTER_INC(mc_miss_by_nome); - return vm_call_general; /* vm_call_method_nome() situation */ +static void +vm_ccs_push(VALUE klass, struct rb_class_cc_entries *ccs, const struct rb_callinfo *ci, const struct rb_callcache *cc) +{ + if (! vm_cc_markable(cc)) { + return; } - else if (LIKELY(cc->me != me)) { - RB_DEBUG_COUNTER_INC(mc_miss_by_distinct); - return vm_call_general; /* normal cases */ + else if (! vm_ci_markable(ci)) { + return; } - else if (UNLIKELY(cc->method_serial != me->def->method_serial)) { - RB_DEBUG_COUNTER_INC(mc_miss_by_refine); - return vm_call_general; /* cc->me was refined elsewhere */ + + if (UNLIKELY(ccs->len == ccs->capa)) { + if (ccs->capa == 0) { + ccs->capa = 1; + ccs->entries = ALLOC_N(struct rb_class_cc_entries_entry, ccs->capa); + } + else { + ccs->capa *= 2; + REALLOC_N(ccs->entries, struct rb_class_cc_entries_entry, ccs->capa); + } } - /* "Calling a formerly-public method, which is now privatised, with an - * explicit receiver" is the only situation we have to check here. A - * formerly-private method now publicised is an absolutely safe thing. - * Calling a private method without specifying a receiver is also safe. */ - else if ((METHOD_ENTRY_VISI(cc->me) != METHOD_VISI_PUBLIC) && - !(ci->flag & VM_CALL_FCALL)) { - RB_DEBUG_COUNTER_INC(mc_miss_by_visi); - return vm_call_general; + VM_ASSERT(ccs->len < ccs->capa); + + const int pos = ccs->len++; + RB_OBJ_WRITE(klass, &ccs->entries[pos].ci, ci); + RB_OBJ_WRITE(klass, &ccs->entries[pos].cc, cc); + + if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) { + // for tuning + // vm_mtbl_dump(klass, 0); } - else { - RB_DEBUG_COUNTER_INC(mc_miss_spurious); - (void)RB_DEBUG_COUNTER_INC_IF(mc_miss_reuse_call, cc->call != vm_call_general); - return cc->call; +} + +#if VM_CHECK_MODE > 0 +void +rb_vm_ccs_dump(struct rb_class_cc_entries *ccs) +{ + ruby_debug_printf("ccs:%p (%d,%d)\n", (void *)ccs, ccs->len, ccs->capa); + for (int i=0; ilen; i++) { + vm_ci_dump(ccs->entries[i].ci); + rp(ccs->entries[i].cc); } } -MJIT_FUNC_EXPORTED void -rb_vm_search_method_slowpath(struct rb_call_data *cd, VALUE klass) -{ - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; - const rb_callable_method_entry_t *me = - rb_callable_method_entry(klass, ci->mid); - const vm_call_handler call = calccall(cd, me); - struct rb_call_cache buf = { - GET_GLOBAL_METHOD_STATE(), - { RCLASS_SERIAL(klass) }, - me, - me ? me->def->method_serial : 0, - call, - }; - if (call != vm_call_general) { - for (int i = 0; i < numberof(cc->class_serial) - 1; i++) { - buf.class_serial[i + 1] = cc->class_serial[i]; - } +static int +vm_ccs_verify(struct rb_class_cc_entries *ccs, ID mid, VALUE klass) +{ + VM_ASSERT(vm_ccs_p(ccs)); + VM_ASSERT(ccs->len <= ccs->capa); + + for (int i=0; ilen; i++) { + const struct rb_callinfo *ci = ccs->entries[i].ci; + const struct rb_callcache *cc = ccs->entries[i].cc; + + VM_ASSERT(vm_ci_p(ci)); + VM_ASSERT(vm_ci_mid(ci) == mid); + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(vm_cc_class_check(cc, klass)); + VM_ASSERT(vm_cc_check_cme(cc, ccs->cme)); } - MEMCPY(cc, &buf, struct rb_call_cache, 1); - VM_ASSERT(callable_method_entry_p(cc->me)); -} - -/* # Description of what `vm_cache_check_for_class_serial()` is doing ######### - * - * - Let's assume a `struct rb_call_cache` has its `class_serial` as an array - * of length 3 (typical situation for 64 bit environments): - * - * ```C - * struct rb_call_cache { - * rb_serial_t method_state; - * rb_serial_t class_serial[3]; - * rb_callable_method_entry_t *me; - * rb_method_definition_struct *def; - * vm_call_handler call; - * union { ... snip ... } aux; - * }; - * ``` - * - * - Initially, the `cc->class_serial` array is filled with zeros. - * - * - If the cache mishits, and if that was due to mc_miss_spurious situation, - * `rb_vm_search_method_slowpath()` pushes the newest class serial at the - * leftmost position of the `cc->class_serial`. - * - * ``` - * from: +--------------+-----+-----+-----+----+-----+------+-----+ - * | method_state | (x) | (y) | (z) | me | def | call | aux | - * +--------------+-----+-----+-----+----+-----+------+-----+ - * \ \ - * \ \ - * \ \ - * \ \ - * \ \ - * v v - * to: +--------------+-----+-----+-----+----+-----+------+-----+ - * | method_state | NEW | (x) | (y) | me | def | call | aux | - * +--------------+-----+-----+-----+----+-----+------+-----+ - * ^^^ - * fill RCLASS_SERIAL(klass) - * ``` - * - * - Eventually, the `cc->class_serial` is filled with a series of classes that - * share the same method entry for the same call site. - * - * - `vm_cache_check_for_class_serial()` can say that the cache now hits if - * _any_ of the class serials stored inside of `cc->class_serial` is equal to - * the given `class_serial` value. - * - * - It scans the array from left to right, looking for the expected class - * serial. If it finds that at `cc->class_serial[0]` (this branch - * probability is 98% according to @shyouhei's experiment), just returns - * true. If it reaches the end of the array without finding anything, - * returns false. This is done in the #1 loop below. - * - * - What needs to be complicated is when the class serial is found at either - * `cc->class_serial[1]` or `cc->class_serial[2]`. When that happens, its - * return value is true because `cc->me` and `cc->call` are valid. But - * `cc->aux` might be invalid. Also the found class serial is expected to - * hit next time. In this case we reorder the array and wipe out `cc->aux`. - * This is done in the #2 loop below. - * - * ``` - * from: +--------------+-----+-----+-----+----+-----+------+-----+ - * | method_state | (x) | (y) | (z) | me | def | call | aux | - * +--------------+-----+-----+-----+----+-----+------+-----+ - * \ \ | - * \ \ | - * +- \ --- \ -+ - * | \ \ - * | \ \ - * v v v - * to: +--------------+-----+-----+-----+----+-----+------+-----+ - * | method_state | (z) | (x) | (y) | me | def | call | 000 | - * +--------------+-----+-----+-----+----+-----+------+-----+ - * ^^^ - * wipe out - * ``` - * - */ -static inline bool -vm_cache_check_for_class_serial(struct rb_call_cache *cc, rb_serial_t class_serial) + return TRUE; +} +#endif + +#ifndef MJIT_HEADER + +static const rb_callable_method_entry_t *check_overloaded_cme(const rb_callable_method_entry_t *cme, const struct rb_callinfo * const ci); + +static const struct rb_callcache * +vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci) { - int i; - rb_serial_t j; + const ID mid = vm_ci_mid(ci); + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + struct rb_class_cc_entries *ccs = NULL; + VALUE ccs_data; - /* This is the loop #1 in above description. */ - for (i = 0; i < numberof(cc->class_serial); i++) { - j = cc->class_serial[i]; + if (cc_tbl) { + if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { + ccs = (struct rb_class_cc_entries *)ccs_data; + const int ccs_len = ccs->len; - if (! j) { - break; - } - else if (j != class_serial) { - continue; + if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) { + rb_vm_ccs_free(ccs); + rb_id_table_delete(cc_tbl, mid); + ccs = NULL; + } + else { + VM_ASSERT(vm_ccs_verify(ccs, mid, klass)); + + for (int i=0; ientries[i].ci; + const struct rb_callcache *ccs_cc = ccs->entries[i].cc; + + VM_ASSERT(vm_ci_p(ccs_ci)); + VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache)); + + if (ccs_ci == ci) { // TODO: equality + RB_DEBUG_COUNTER_INC(cc_found_in_ccs); + + VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid); + VM_ASSERT(ccs_cc->klass == klass); + VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc))); + + return ccs_cc; + } + } + } } - else if (! i) { - return true; + } + else { + cc_tbl = RCLASS_CC_TBL(klass) = rb_id_table_create(2); + } + + RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs); + + const rb_callable_method_entry_t *cme; + + if (ccs) { + cme = ccs->cme; + cme = UNDEFINED_METHOD_ENTRY_P(cme) ? NULL : cme; + + VM_ASSERT(cme == rb_callable_method_entry(klass, mid)); + } + else { + cme = rb_callable_method_entry(klass, mid); + } + + VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment)); + + if (cme == NULL) { + // undef or not found: can't cache the information + VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL); + return &vm_empty_cc; + } + + VM_ASSERT(cme == rb_callable_method_entry(klass, mid)); + + METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme); + + if (ccs == NULL) { + VM_ASSERT(cc_tbl != NULL); + + if (LIKELY(rb_id_table_lookup(cc_tbl, mid, &ccs_data))) { + // rb_callable_method_entry() prepares ccs. + ccs = (struct rb_class_cc_entries *)ccs_data; } else { - goto hit; + // TODO: required? + ccs = vm_ccs_create(klass, cme); + rb_id_table_insert(cc_tbl, mid, (VALUE)ccs); } } - RB_DEBUG_COUNTER_INC(mc_class_serial_miss); - return false; + cme = check_overloaded_cme(cme, ci); + + const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general); + vm_ccs_push(klass, ccs, ci, cc); + + VM_ASSERT(vm_cc_cme(cc) != NULL); + VM_ASSERT(cme->called_id == mid); + VM_ASSERT(vm_cc_cme(cc)->called_id == mid); + + return cc; +} + +MJIT_FUNC_EXPORTED const struct rb_callcache * +rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass) +{ + const struct rb_callcache *cc; + + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS)); - hit: - /* This is the loop #2 in above description. */ - for (; i > 0; i--) { - cc->class_serial[i] = cc->class_serial[i - 1]; + RB_VM_LOCK_ENTER(); + { + cc = vm_search_cc(klass, ci); + + VM_ASSERT(cc); + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass); + VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc))); + VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc))); + VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci)); } + RB_VM_LOCK_LEAVE(); - cc->class_serial[0] = j; - MEMZERO(&cc->aux, cc->aux, 1); /* cc->call is valid, but cc->aux might not. */ - return true; + return cc; } +#endif -static void -vm_search_method_fastpath(struct rb_call_data *cd, VALUE klass) +static const struct rb_callcache * +vm_search_method_slowpath0(VALUE cd_owner, struct rb_call_data *cd, VALUE klass) { - struct rb_call_cache *cc = &cd->cc; +#if USE_DEBUG_COUNTER + const struct rb_callcache *old_cc = cd->cc; +#endif + + const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass); #if OPT_INLINE_METHOD_CACHE - if (LIKELY(RB_DEBUG_COUNTER_INC_UNLESS(mc_global_state_miss, - GET_GLOBAL_METHOD_STATE() == cc->method_state) && - vm_cache_check_for_class_serial(cc, RCLASS_SERIAL(klass)))) { - /* cache hit! */ - VM_ASSERT(cc->call != NULL); - RB_DEBUG_COUNTER_INC(mc_inline_hit); - return; + cd->cc = cc; + + const struct rb_callcache *empty_cc = +#ifdef MJIT_HEADER + rb_vm_empty_cc(); +#else + &vm_empty_cc; +#endif + if (cd_owner && cc != empty_cc) RB_OBJ_WRITTEN(cd_owner, Qundef, cc); + +#if USE_DEBUG_COUNTER + if (old_cc == &empty_cc) { + // empty + RB_DEBUG_COUNTER_INC(mc_inline_miss_empty); + } + else if (old_cc == cc) { + RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc); + } + else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) { + RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme); + } + else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) && + vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) { + RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def); + } + else { + RB_DEBUG_COUNTER_INC(mc_inline_miss_diff); } - RB_DEBUG_COUNTER_INC(mc_inline_miss); #endif - rb_vm_search_method_slowpath(cd, klass); +#endif // OPT_INLINE_METHOD_CACHE + + VM_ASSERT(vm_cc_cme(cc) == NULL || + vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci)); + + return cc; } -static void -vm_search_method(struct rb_call_data *cd, VALUE recv) +#ifndef MJIT_HEADER +ALWAYS_INLINE(static const struct rb_callcache *vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass)); +#endif +static const struct rb_callcache * +vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass) { - VALUE klass = CLASS_OF(recv); + const struct rb_callcache *cc = cd->cc; + +#if OPT_INLINE_METHOD_CACHE + if (LIKELY(vm_cc_class_check(cc, klass))) { + if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) { + VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc))); + RB_DEBUG_COUNTER_INC(mc_inline_hit); + VM_ASSERT(vm_cc_cme(cc) == NULL || // not found + (vm_ci_flag(cd->ci) & VM_CALL_SUPER) || // search_super w/ define_method + vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci)); // cme->called_id == ci->mid + + return cc; + } + RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated); + } + else { + RB_DEBUG_COUNTER_INC(mc_inline_miss_klass); + } +#endif + return vm_search_method_slowpath0(cd_owner, cd, klass); +} + +static const struct rb_callcache * +vm_search_method(VALUE cd_owner, struct rb_call_data *cd, VALUE recv) +{ + VALUE klass = CLASS_OF(recv); VM_ASSERT(klass != Qfalse); VM_ASSERT(RBASIC_CLASS(klass) == 0 || rb_obj_is_kind_of(klass, rb_cClass)); - vm_search_method_fastpath(cd, klass); + + return vm_search_method_fastpath(cd_owner, cd, klass); } static inline int -check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)()) +check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)(ANYARGS)) { - if (me && me->def->type == VM_METHOD_TYPE_CFUNC && - me->def->body.cfunc.func == func) { - return 1; + if (! me) { + return false; } else { - return 0; + VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment)); + VM_ASSERT(callable_method_entry_p(me)); + VM_ASSERT(me->def); + if (me->def->type != VM_METHOD_TYPE_CFUNC) { + return false; + } + else { + return me->def->body.cfunc.func == func; + } } } static inline int -vm_method_cfunc_is(CALL_DATA cd, VALUE recv, VALUE (*func)()) -{ - vm_search_method(cd, recv); - return check_cfunc(cd->cc.me, func); -} - -static VALUE -opt_equal_fallback(VALUE recv, VALUE obj, CALL_DATA cd) +vm_method_cfunc_is(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv, VALUE (*func)(ANYARGS)) { - if (vm_method_cfunc_is(cd, recv, rb_obj_equal)) { - return recv == obj ? Qtrue : Qfalse; - } - - return Qundef; + VM_ASSERT(iseq != NULL); + const struct rb_callcache *cc = vm_search_method((VALUE)iseq, cd, recv); + return check_cfunc(vm_cc_cme(cc), func); } -#define BUILTIN_CLASS_P(x, k) (!SPECIAL_CONST_P(x) && RBASIC_CLASS(x) == k) #define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG) static inline bool @@ -1692,102 +2035,114 @@ FLONUM_2_P(VALUE a, VALUE b) #endif } -/* 1: compare by identity, 0: not applicable, -1: redefined */ -static inline int -comparable_by_identity(VALUE recv, VALUE obj) +static VALUE +opt_equality_specialized(VALUE recv, VALUE obj) { - if (FIXNUM_2_P(recv, obj)) { - return (EQ_UNREDEFINED_P(INTEGER) != 0) * 2 - 1; + if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) { + goto compare_by_identity; } - if (FLONUM_2_P(recv, obj)) { - return (EQ_UNREDEFINED_P(FLOAT) != 0) * 2 - 1; + else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) { + goto compare_by_identity; } - if (SYMBOL_P(recv) && SYMBOL_P(obj)) { - return (EQ_UNREDEFINED_P(SYMBOL) != 0) * 2 - 1; + else if (STATIC_SYM_P(recv) && STATIC_SYM_P(obj) && EQ_UNREDEFINED_P(SYMBOL)) { + goto compare_by_identity; } - return 0; -} + else if (SPECIAL_CONST_P(recv)) { + // + } + else if (RBASIC_CLASS(recv) == rb_cFloat && RB_FLOAT_TYPE_P(obj) && EQ_UNREDEFINED_P(FLOAT)) { + double a = RFLOAT_VALUE(recv); + double b = RFLOAT_VALUE(obj); -static -#ifndef NO_BIG_INLINE -inline +#if MSC_VERSION_BEFORE(1300) + if (isnan(a)) { + return Qfalse; + } + else if (isnan(b)) { + return Qfalse; + } + else #endif -VALUE -opt_eq_func(VALUE recv, VALUE obj, CALL_DATA cd) -{ - switch (comparable_by_identity(recv, obj)) { - case 1: - return (recv == obj) ? Qtrue : Qfalse; - case -1: - goto fallback; - } - if (0) { - } - else if (BUILTIN_CLASS_P(recv, rb_cFloat)) { - if (EQ_UNREDEFINED_P(FLOAT)) { - return rb_float_equal(recv, obj); - } + return RBOOL(a == b); } - else if (BUILTIN_CLASS_P(recv, rb_cString) && EQ_UNREDEFINED_P(STRING)) { - if (recv == obj) return Qtrue; - if (RB_TYPE_P(obj, T_STRING)) { - return rb_str_eql_internal(recv, obj); + else if (RBASIC_CLASS(recv) == rb_cString && EQ_UNREDEFINED_P(STRING)) { + if (recv == obj) { + return Qtrue; + } + else if (RB_TYPE_P(obj, T_STRING)) { + return rb_str_eql_internal(obj, recv); } } + return Qundef; - fallback: - return opt_equal_fallback(recv, obj, cd); + compare_by_identity: + return RBOOL(recv == obj); } -static -#ifndef NO_BIG_INLINE -inline -#endif -VALUE -opt_eql_func(VALUE recv, VALUE obj, CALL_DATA cd) +static VALUE +opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) { - switch (comparable_by_identity(recv, obj)) { - case 1: - return (recv == obj) ? Qtrue : Qfalse; - case -1: - goto fallback; + VM_ASSERT(cd_owner != NULL); + + VALUE val = opt_equality_specialized(recv, obj); + if (val != Qundef) return val; + + if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) { + return Qundef; } - if (0) { + else { + return RBOOL(recv == obj); } - else if (BUILTIN_CLASS_P(recv, rb_cFloat)) { - if (EQ_UNREDEFINED_P(FLOAT)) { - return rb_float_eql(recv, obj); - } +} + +#undef EQ_UNREDEFINED_P + +#ifndef MJIT_HEADER + +static inline const struct rb_callcache *gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc); // vm_eval.c +NOINLINE(static VALUE opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid)); + +static VALUE +opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid) +{ + const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, 1); + + if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) { + return RBOOL(recv == obj); } - else if (BUILTIN_CLASS_P(recv, rb_cString)) { - if (EQ_UNREDEFINED_P(STRING)) { - return rb_str_eql(recv, obj); - } + else { + return Qundef; } +} - fallback: - return opt_equal_fallback(recv, obj, cd); +static VALUE +opt_equality_by_mid(VALUE recv, VALUE obj, ID mid) +{ + VALUE val = opt_equality_specialized(recv, obj); + if (val != Qundef) { + return val; + } + else { + return opt_equality_by_mid_slowpath(recv, obj, mid); + } } -#undef BUILTIN_CLASS_P -#undef EQ_UNREDEFINED_P VALUE rb_equal_opt(VALUE obj1, VALUE obj2) { - struct rb_call_data cd = { .ci = { .mid = idEq, }, }; - - return opt_eq_func(obj1, obj2, &cd); + return opt_equality_by_mid(obj1, obj2, idEq); } VALUE rb_eql_opt(VALUE obj1, VALUE obj2) { - struct rb_call_data cd = { .ci = { .mid = idEqlP, }, }; - - return opt_eql_func(obj1, obj2, &cd); + return opt_equality_by_mid(obj1, obj2, idEqlP); } +#endif // MJIT_HEADER + extern VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE, ID, int, const VALUE*, const rb_callable_method_entry_t *, int kw_splat); +extern VALUE rb_vm_call_with_refinements(rb_execution_context_t *, VALUE, ID, int, const VALUE *, int); static VALUE check_match(rb_execution_context_t *ec, VALUE pattern, VALUE target, enum vm_check_match_type type) @@ -1801,15 +2156,7 @@ check_match(rb_execution_context_t *ec, VALUE pattern, VALUE target, enum vm_che } /* fall through */ case VM_CHECKMATCH_TYPE_CASE: { - const rb_callable_method_entry_t *me = - rb_callable_method_entry_with_refinements(CLASS_OF(pattern), idEqq, NULL); - if (me) { - return rb_vm_call0(ec, pattern, idEqq, 1, &target, me, RB_NO_KEYWORDS); - } - else { - /* fallback to funcall (e.g. method_missing) */ - return rb_funcallv(pattern, idEqq, 1, &target); - } + return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target, RB_NO_KEYWORDS); } default: rb_bug("check_match: unreachable"); @@ -1817,7 +2164,7 @@ check_match(rb_execution_context_t *ec, VALUE pattern, VALUE target, enum vm_che } -#if defined(_MSC_VER) && _MSC_VER < 1300 +#if MSC_VERSION_BEFORE(1300) #define CHECK_CMP_NAN(a, b) if (isnan(a) || isnan(b)) return Qfalse; #else #define CHECK_CMP_NAN(a, b) /* do nothing */ @@ -1827,28 +2174,28 @@ static inline VALUE double_cmp_lt(double a, double b) { CHECK_CMP_NAN(a, b); - return a < b ? Qtrue : Qfalse; + return RBOOL(a < b); } static inline VALUE double_cmp_le(double a, double b) { CHECK_CMP_NAN(a, b); - return a <= b ? Qtrue : Qfalse; + return RBOOL(a <= b); } static inline VALUE double_cmp_gt(double a, double b) { CHECK_CMP_NAN(a, b); - return a > b ? Qtrue : Qfalse; + return RBOOL(a > b); } static inline VALUE double_cmp_ge(double a, double b) { CHECK_CMP_NAN(a, b); - return a >= b ? Qtrue : Qfalse; + return RBOOL(a >= b); } static inline VALUE * @@ -1865,7 +2212,7 @@ vm_base_ptr(const rb_control_frame_t *cfp) } #if VM_DEBUG_BP_CHECK if (bp != cfp->bp_check) { - fprintf(stderr, "bp_check: %ld, bp: %ld\n", + ruby_debug_printf("bp_check: %ld, bp: %ld\n", (long)(cfp->bp_check - GET_EC()->vm_stack), (long)(bp - GET_EC()->vm_stack)); rb_bug("vm_base_ptr: unreachable"); @@ -1885,34 +2232,34 @@ vm_base_ptr(const rb_control_frame_t *cfp) #include "vm_args.c" -static inline VALUE vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd, int opt_pc, int param_size, int local_size); +static inline VALUE vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, int opt_pc, int param_size, int local_size); ALWAYS_INLINE(static VALUE vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, const rb_callable_method_entry_t *me, int opt_pc, int param_size, int local_size)); -static inline VALUE vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd, int opt_pc); -static VALUE vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd); -static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd); -static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd); -static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd); +static inline VALUE vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, int opt_pc); +static VALUE vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling); +static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling); +static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling); +static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling); -static vm_call_handler vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size); +static vm_call_handler vm_call_iseq_setup_func(const struct rb_callinfo *ci, const int param_size, const int local_size); static VALUE -vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start); - return vm_call_iseq_setup_tailcall(ec, cfp, calling, cd, 0); + return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0); } static VALUE -vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start); - struct rb_call_cache *cc = &cd->cc; - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const struct rb_callcache *cc = calling->cc; + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); int param = iseq->body->param.size; int local = iseq->body->local_table_size; - return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, 0, param, local); + return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local); } MJIT_STATIC bool @@ -1927,7 +2274,7 @@ rb_simple_iseq_p(const rb_iseq_t *iseq) iseq->body->param.flags.has_block == FALSE; } -static bool +MJIT_FUNC_EXPORTED bool rb_iseq_only_optparam_p(const rb_iseq_t *iseq) { return iseq->body->param.flags.has_opt == TRUE && @@ -1939,7 +2286,7 @@ rb_iseq_only_optparam_p(const rb_iseq_t *iseq) iseq->body->param.flags.has_block == FALSE; } -static bool +MJIT_FUNC_EXPORTED bool rb_iseq_only_kwparam_p(const rb_iseq_t *iseq) { return iseq->body->param.flags.has_opt == FALSE && @@ -1950,16 +2297,23 @@ rb_iseq_only_kwparam_p(const rb_iseq_t *iseq) iseq->body->param.flags.has_block == FALSE; } +// If true, cc->call needs to include `CALLER_SETUP_ARG` (i.e. can't be skipped in fastpath) +MJIT_STATIC bool +rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci) +{ + return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci); +} + static inline void CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp, struct rb_calling_info *restrict calling, - const struct rb_call_info *restrict ci) + const struct rb_callinfo *restrict ci) { if (UNLIKELY(IS_ARGS_SPLAT(ci))) { VALUE final_hash; /* This expands the rest argument to the stack. - * So, ci->flag & VM_CALL_ARGS_SPLAT is now inconsistent. + * So, vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT is now inconsistent. */ vm_caller_setup_arg_splat(cfp, calling); if (!IS_ARGS_KW_OR_KW_SPLAT(ci) && @@ -1970,28 +2324,38 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp, calling->kw_splat = 1; } } - if (UNLIKELY(IS_ARGS_KEYWORD(ci))) { - /* This converts VM_CALL_KWARG style to VM_CALL_KW_SPLAT style - * by creating a keyword hash. - * So, ci->flag & VM_CALL_KWARG is now inconsistent. - */ - vm_caller_setup_arg_kw(cfp, calling, ci); + if (UNLIKELY(IS_ARGS_KW_OR_KW_SPLAT(ci))) { + if (IS_ARGS_KEYWORD(ci)) { + /* This converts VM_CALL_KWARG style to VM_CALL_KW_SPLAT style + * by creating a keyword hash. + * So, vm_ci_flag(ci) & VM_CALL_KWARG is now inconsistent. + */ + vm_caller_setup_arg_kw(cfp, calling, ci); + } + else { + VALUE keyword_hash = cfp->sp[-1]; + if (!RB_TYPE_P(keyword_hash, T_HASH)) { + /* Convert a non-hash keyword splat to a new hash */ + cfp->sp[-1] = rb_hash_dup(rb_to_hash_type(keyword_hash)); + } + else if (!IS_ARGS_KW_SPLAT_MUT(ci)) { + /* Convert a hash keyword splat to a new hash unless + * a mutable keyword splat was passed. + */ + cfp->sp[-1] = rb_hash_dup(keyword_hash); + } + } } } static inline void CALLER_REMOVE_EMPTY_KW_SPLAT(struct rb_control_frame_struct *restrict cfp, struct rb_calling_info *restrict calling, - const struct rb_call_info *restrict ci) + const struct rb_callinfo *restrict ci) { if (UNLIKELY(calling->kw_splat)) { /* This removes the last Hash object if it is empty. - * So, ci->flag & VM_CALL_KW_SPLAT is now inconsistent. - * However, you can use ci->flag & VM_CALL_KW_SPLAT to - * determine whether a hash should be added back with - * warning (for backwards compatibility in cases where - * the method does not have the number of required - * arguments. + * So, vm_ci_flag(ci) & VM_CALL_KW_SPLAT is now inconsistent. */ if (RHASH_EMPTY_P(cfp->sp[-1])) { cfp->sp--; @@ -2012,18 +2376,17 @@ static void opt_hist_show_results_at_exit(void) { for (int i=0; icc; - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const struct rb_callcache *cc = calling->cc; + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); const int lead_num = iseq->body->param.lead_num; const int opt = calling->argc - lead_num; const int opt_num = iseq->body->param.opt_num; @@ -2043,16 +2406,15 @@ vm_call_iseq_setup_normal_opt_start(rb_execution_context_t *ec, rb_control_frame } #endif - return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, opt_pc, param - delta, local); + return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local); } static VALUE vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp, - struct rb_calling_info *calling, - struct rb_call_data *cd) + struct rb_calling_info *calling) { - const struct rb_call_cache *cc = &cd->cc; - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const struct rb_callcache *cc = calling->cc; + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); const int lead_num = iseq->body->param.lead_num; const int opt = calling->argc - lead_num; const int opt_pc = (int)iseq->body->param.opt_table[opt]; @@ -2068,7 +2430,7 @@ vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_fra } #endif - return vm_call_iseq_setup_tailcall(ec, cfp, calling, cd, opt_pc); + return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc); } static void @@ -2078,19 +2440,17 @@ args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *cons static VALUE vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp, - struct rb_calling_info *calling, - struct rb_call_data *cd) + struct rb_calling_info *calling) { - const struct rb_kwarg_call_data *kcd = (void *)cd; - const struct rb_call_info_with_kwarg *ci_kw = &kcd->ci_kw; - const struct rb_call_cache *cc = &kcd->cc; + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; - VM_ASSERT(ci_kw->ci.flag & VM_CALL_KWARG); + VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG); RB_DEBUG_COUNTER_INC(ccf_iseq_kw1); - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); const struct rb_iseq_param_keyword *kw_param = iseq->body->param.keyword; - const struct rb_call_info_kw_arg *kw_arg = ci_kw->kw_arg; + const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci); const int ci_kw_len = kw_arg->keyword_len; const VALUE * const ci_keywords = kw_arg->keywords; VALUE *argv = cfp->sp - calling->argc; @@ -2102,21 +2462,20 @@ vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t * int param = iseq->body->param.size; int local = iseq->body->local_table_size; - return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, 0, param, local); + return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local); } static VALUE vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp, - struct rb_calling_info *calling, - struct rb_call_data *cd) + struct rb_calling_info *calling) { - const struct rb_call_info *MAYBE_UNUSED(ci) = &cd->ci; - const struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->ci; + const struct rb_callcache *cc = calling->cc; - VM_ASSERT((ci->flag & VM_CALL_KWARG) == 0); + VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0); RB_DEBUG_COUNTER_INC(ccf_iseq_kw2); - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); const struct rb_iseq_param_keyword *kw_param = iseq->body->param.keyword; VALUE * const argv = cfp->sp - calling->argc; VALUE * const klocals = argv + kw_param->bits_start - kw_param->num; @@ -2132,17 +2491,18 @@ vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t int param = iseq->body->param.size; int local = iseq->body->local_table_size; - return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, 0, param, local); + return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local); } static inline int -vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, +vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const rb_iseq_t *iseq, VALUE *argv, int param_size, int local_size) { - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; + bool cacheable_ci = vm_ci_markable(ci); - if (LIKELY(!(ci->flag & VM_CALL_KW_SPLAT))) { + if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) { if (LIKELY(rb_simple_iseq_p(iseq))) { rb_control_frame_t *cfp = ec->cfp; CALLER_SETUP_ARG(cfp, calling, ci); @@ -2152,7 +2512,9 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, argument_arity_error(ec, iseq, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num); } - CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), vm_call_iseq_optimizable_p(&cd->ci, &cd->cc)); + VM_ASSERT(ci == calling->ci); + VM_ASSERT(cc == calling->cc); + CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), cacheable_ci && vm_call_iseq_optimizable_p(ci, cc)); return 0; } else if (rb_iseq_only_optparam_p(iseq)) { @@ -2169,15 +2531,15 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, argument_arity_error(ec, iseq, argc, lead_num, lead_num + opt_num); } - if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) { + if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) { CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start, !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && - !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED)); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } else { CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start, !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && - !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED)); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } /* initialize opt vars for self-references */ @@ -2192,8 +2554,8 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const int argc = calling->argc; const struct rb_iseq_param_keyword *kw_param = iseq->body->param.keyword; - if (ci->flag & VM_CALL_KWARG) { - const struct rb_call_info_kw_arg *kw_arg = ((struct rb_call_info_with_kwarg *)ci)->kw_arg; + if (vm_ci_flag(ci) & VM_CALL_KWARG) { + const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci); if (argc - kw_arg->keyword_len == lead_num) { const int ci_kw_len = kw_arg->keyword_len; @@ -2205,7 +2567,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, args_setup_kw_parameters(ec, iseq, ci_kws, ci_kw_len, ci_keywords, klocals); CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg, - !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED)); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); return 0; } @@ -2218,7 +2580,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, if (klocals[kw_param->num] == INT2FIX(0)) { /* copy from default_values */ CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg, - !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED)); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } return 0; @@ -2230,30 +2592,30 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, } static VALUE -vm_call_iseq_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_iseq_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_iseq_setup); - const struct rb_call_cache *cc = &cd->cc; - const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def); + const struct rb_callcache *cc = calling->cc; + const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def); const int param_size = iseq->body->param.size; const int local_size = iseq->body->local_table_size; - const int opt_pc = vm_callee_setup_arg(ec, calling, cd, def_iseq_ptr(cc->me->def), cfp->sp - calling->argc, param_size, local_size); - return vm_call_iseq_setup_2(ec, cfp, calling, cd, opt_pc, param_size, local_size); + const int opt_pc = vm_callee_setup_arg(ec, calling, def_iseq_ptr(vm_cc_cme(cc)->def), cfp->sp - calling->argc, param_size, local_size); + return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size); } static inline VALUE -vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd, - int opt_pc, int param_size, int local_size) +vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, + int opt_pc, int param_size, int local_size) { - const struct rb_call_info *ci = &cd->ci; - const struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; - if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) { - return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, opt_pc, param_size, local_size); + if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) { + return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size); } else { - return vm_call_iseq_setup_tailcall(ec, cfp, calling, cd, opt_pc); + return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc); } } @@ -2275,13 +2637,12 @@ vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp, s } static inline VALUE -vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd, - int opt_pc) +vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, int opt_pc) { - const struct rb_call_cache *cc = &cd->cc; + const struct rb_callcache *cc = calling->cc; unsigned int i; VALUE *argv = cfp->sp - calling->argc; - const rb_callable_method_entry_t *me = cc->me; + const rb_callable_method_entry_t *me = vm_cc_cme(cc); const rb_iseq_t *iseq = def_iseq_ptr(me->def); VALUE *src_argv = argv; VALUE *sp_orig, *sp; @@ -2324,171 +2685,336 @@ vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp, return Qundef; } +static void +ractor_unsafe_check(void) +{ + if (!rb_ractor_main_p()) { + rb_raise(rb_eRactorUnsafeError, "ractor unsafe method called from not main ractor"); + } +} + static VALUE call_cfunc_m2(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); return (*func)(recv, rb_ary_new4(argc, argv)); } static VALUE call_cfunc_m1(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); return (*func)(argc, argv, recv); } static VALUE call_cfunc_0(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE) = (VALUE(*)(VALUE))func; return (*f)(recv); } + static VALUE call_cfunc_1(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE) = (VALUE(*)(VALUE, VALUE))func; return (*f)(recv, argv[0]); } + static VALUE call_cfunc_2(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1]); } + static VALUE call_cfunc_3(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2]); } + static VALUE call_cfunc_4(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3]); } + static VALUE call_cfunc_5(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]); } + static VALUE call_cfunc_6(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } + static VALUE call_cfunc_7(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); } + static VALUE call_cfunc_8(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } + static VALUE call_cfunc_9(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); } + static VALUE call_cfunc_10(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); } + static VALUE call_cfunc_11(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); } + static VALUE call_cfunc_12(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); } + static VALUE call_cfunc_13(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]); } + static VALUE call_cfunc_14(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]); } + static VALUE call_cfunc_15(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { + ractor_unsafe_check(); VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]); } -static inline int -vm_cfp_consistent_p(rb_execution_context_t *ec, const rb_control_frame_t *reg_cfp) +static VALUE +ractor_safe_call_cfunc_m2(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { - const int ov_flags = RAISED_STACKOVERFLOW; - if (LIKELY(reg_cfp == ec->cfp + 1)) return TRUE; - if (rb_ec_raised_p(ec, ov_flags)) { - rb_ec_raised_reset(ec, ov_flags); - return TRUE; - } - return FALSE; + return (*func)(recv, rb_ary_new4(argc, argv)); } -#define CHECK_CFP_CONSISTENCY(func) \ - (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \ - rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1))) - -static inline -const rb_method_cfunc_t * -vm_method_cfunc_entry(const rb_callable_method_entry_t *me) +static VALUE +ractor_safe_call_cfunc_m1(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { -#if VM_DEBUG_VERIFY_METHOD_CACHE - switch (me->def->type) { - case VM_METHOD_TYPE_CFUNC: - case VM_METHOD_TYPE_NOTIMPLEMENTED: - break; -# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t) - METHOD_BUG(ISEQ); - METHOD_BUG(ATTRSET); - METHOD_BUG(IVAR); - METHOD_BUG(BMETHOD); - METHOD_BUG(ZSUPER); - METHOD_BUG(UNDEF); - METHOD_BUG(OPTIMIZED); - METHOD_BUG(MISSING); - METHOD_BUG(REFINED); - METHOD_BUG(ALIAS); -# undef METHOD_BUG - default: - rb_bug("wrong method type: %d", me->def->type); - } -#endif - return UNALIGNED_MEMBER_PTR(me->def, body.cfunc); + return (*func)(argc, argv, recv); } -/* -- Remove empty_kw_splat In 3.0 -- */ static VALUE -vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd, int empty_kw_splat) +ractor_safe_call_cfunc_0(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) { - const struct rb_call_info *ci = &cd->ci; - const struct rb_call_cache *cc = &cd->cc; - VALUE val; - const rb_callable_method_entry_t *me = cc->me; - const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me); - int len = cfunc->argc; + VALUE(*f)(VALUE) = (VALUE(*)(VALUE))func; + return (*f)(recv); +} - VALUE recv = calling->recv; +static VALUE +ractor_safe_call_cfunc_1(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE) = (VALUE(*)(VALUE, VALUE))func; + return (*f)(recv, argv[0]); +} + +static VALUE +ractor_safe_call_cfunc_2(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1]); +} + +static VALUE +ractor_safe_call_cfunc_3(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2]); +} + +static VALUE +ractor_safe_call_cfunc_4(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3]); +} + +static VALUE +ractor_safe_call_cfunc_5(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]); +} + +static VALUE +ractor_safe_call_cfunc_6(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +static VALUE +ractor_safe_call_cfunc_7(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} + +static VALUE +ractor_safe_call_cfunc_8(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); +} + +static VALUE +ractor_safe_call_cfunc_9(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); +} + +static VALUE +ractor_safe_call_cfunc_10(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); +} + +static VALUE +ractor_safe_call_cfunc_11(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); +} + +static VALUE +ractor_safe_call_cfunc_12(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); +} + +static VALUE +ractor_safe_call_cfunc_13(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]); +} + +static VALUE +ractor_safe_call_cfunc_14(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]); +} + +static VALUE +ractor_safe_call_cfunc_15(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)) +{ + VALUE(*f)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE) = (VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE))func; + return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]); +} + +static inline int +vm_cfp_consistent_p(rb_execution_context_t *ec, const rb_control_frame_t *reg_cfp) +{ + const int ov_flags = RAISED_STACKOVERFLOW; + if (LIKELY(reg_cfp == ec->cfp + 1)) return TRUE; + if (rb_ec_raised_p(ec, ov_flags)) { + rb_ec_raised_reset(ec, ov_flags); + return TRUE; + } + return FALSE; +} + +#define CHECK_CFP_CONSISTENCY(func) \ + (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \ + rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1))) + +static inline +const rb_method_cfunc_t * +vm_method_cfunc_entry(const rb_callable_method_entry_t *me) +{ +#if VM_DEBUG_VERIFY_METHOD_CACHE + switch (me->def->type) { + case VM_METHOD_TYPE_CFUNC: + case VM_METHOD_TYPE_NOTIMPLEMENTED: + break; +# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t) + METHOD_BUG(ISEQ); + METHOD_BUG(ATTRSET); + METHOD_BUG(IVAR); + METHOD_BUG(BMETHOD); + METHOD_BUG(ZSUPER); + METHOD_BUG(UNDEF); + METHOD_BUG(OPTIMIZED); + METHOD_BUG(MISSING); + METHOD_BUG(REFINED); + METHOD_BUG(ALIAS); +# undef METHOD_BUG + default: + rb_bug("wrong method type: %d", me->def->type); + } +#endif + return UNALIGNED_MEMBER_PTR(me->def, body.cfunc); +} + +static VALUE +vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) +{ + RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame); + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; + VALUE val; + const rb_callable_method_entry_t *me = vm_cc_cme(cc); + const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me); + int len = cfunc->argc; + + VALUE recv = calling->recv; VALUE block_handler = calling->block_handler; VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL; int argc = calling->argc; @@ -2497,12 +3023,9 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp if (UNLIKELY(calling->kw_splat)) { frame_type |= VM_FRAME_FLAG_CFRAME_KW; } - else if (UNLIKELY(empty_kw_splat)) { - frame_type |= VM_FRAME_FLAG_CFRAME_EMPTY_KW; - } RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id); - EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, ci->mid, me->owner, Qundef); + EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, vm_ci_mid(ci), me->owner, Qundef); vm_push_frame(ec, NULL, frame_type, recv, block_handler, (VALUE)me, @@ -2517,69 +3040,78 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp rb_vm_pop_frame(ec); - EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, ci->mid, me->owner, val); + EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val); RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id); return val; } static VALUE -vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { - const struct rb_call_info *ci = &cd->ci; - int empty_kw_splat; + const struct rb_callinfo *ci = calling->ci; RB_DEBUG_COUNTER_INC(ccf_cfunc); CALLER_SETUP_ARG(reg_cfp, calling, ci); - empty_kw_splat = calling->kw_splat; CALLER_REMOVE_EMPTY_KW_SPLAT(reg_cfp, calling, ci); - if (empty_kw_splat && calling->kw_splat) { - empty_kw_splat = 0; - } - return vm_call_cfunc_with_frame(ec, reg_cfp, calling, cd, empty_kw_splat); + CC_SET_FASTPATH(calling->cc, vm_call_cfunc_with_frame, !rb_splat_or_kwargs_p(ci) && !calling->kw_splat); + return vm_call_cfunc_with_frame(ec, reg_cfp, calling); } static VALUE -vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - struct rb_call_cache *cc = &cd->cc; + const struct rb_callcache *cc = calling->cc; RB_DEBUG_COUNTER_INC(ccf_ivar); cfp->sp -= 1; - return vm_getivar(calling->recv, cc->me->def->body.attr.id, NULL, cc, TRUE); + return vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE); } static VALUE -vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - struct rb_call_cache *cc = &cd->cc; + const struct rb_callcache *cc = calling->cc; RB_DEBUG_COUNTER_INC(ccf_attrset); VALUE val = *(cfp->sp - 1); cfp->sp -= 2; - return vm_setivar(calling->recv, cc->me->def->body.attr.id, val, NULL, cc, 1); + return vm_setivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, val, NULL, NULL, cc, 1); +} + +bool +rb_vm_call_ivar_attrset_p(const vm_call_handler ch) +{ + return (ch == vm_call_ivar || ch == vm_call_attrset); } static inline VALUE -vm_call_bmethod_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv) +vm_call_bmethod_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv) { rb_proc_t *proc; VALUE val; - const struct rb_call_cache *cc = &cd->cc; + const struct rb_callcache *cc = calling->cc; + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + VALUE procv = cme->def->body.bmethod.proc; + + if (!RB_OBJ_SHAREABLE_P(procv) && + cme->def->body.bmethod.defined_ractor != rb_ractor_self(rb_ec_ractor_ptr(ec))) { + rb_raise(rb_eRuntimeError, "defined with an un-shareable Proc in a different Ractor"); + } /* control block frame */ - GetProcPtr(cc->me->def->body.bmethod.proc, proc); - val = rb_vm_invoke_bmethod(ec, proc, calling->recv, calling->argc, argv, calling->kw_splat, calling->block_handler, cc->me); + GetProcPtr(procv, proc); + val = rb_vm_invoke_bmethod(ec, proc, calling->recv, calling->argc, argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc)); return val; } static VALUE -vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_bmethod); VALUE *argv; int argc; - const struct rb_call_info *ci = &cd->ci; + const struct rb_callinfo *ci = calling->ci; CALLER_SETUP_ARG(cfp, calling, ci); argc = calling->argc; @@ -2587,148 +3119,204 @@ vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_c MEMCPY(argv, cfp->sp - argc, VALUE, argc); cfp->sp += - argc - 1; - return vm_call_bmethod_body(ec, calling, cd, argv); + return vm_call_bmethod_body(ec, calling, argv); } -static enum method_missing_reason -ci_missing_reason(const struct rb_call_info *ci) +MJIT_FUNC_EXPORTED VALUE +rb_find_defined_class_by_owner(VALUE current_class, VALUE target_owner) { - enum method_missing_reason stat = MISSING_NOENTRY; - if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL; - if (ci->flag & VM_CALL_FCALL) stat |= MISSING_FCALL; - if (ci->flag & VM_CALL_SUPER) stat |= MISSING_SUPER; - return stat; -} - -static VALUE -vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *orig_cd) -{ - RB_DEBUG_COUNTER_INC(ccf_opt_send); - - int i; - VALUE sym; - const struct rb_call_info *orig_ci = &orig_cd->ci; - const struct rb_call_cache *orig_cc = &orig_cd->cc; - struct rb_call_info *ci; - struct rb_call_cache *cc; - struct rb_kwarg_call_data cd; - - CALLER_SETUP_ARG(reg_cfp, calling, orig_ci); - - i = calling->argc - 1; + VALUE klass = current_class; - if (calling->argc == 0) { - rb_raise(rb_eArgError, "no method name given"); + /* for prepended Module, then start from cover class */ + if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN) && + RB_TYPE_P(RBASIC_CLASS(klass), T_CLASS)) { + klass = RBASIC_CLASS(klass); } - /* setup new ci */ - if (orig_ci->flag & VM_CALL_KWARG) { - const struct rb_kwarg_call_data *orig_kcd = (void *)orig_cd; - cd = *orig_kcd; - } - else { - cd.ci_kw.ci = *orig_ci; - cd.cc = *orig_cc; + while (RTEST(klass)) { + VALUE owner = RB_TYPE_P(klass, T_ICLASS) ? RBASIC_CLASS(klass) : klass; + if (owner == target_owner) { + return klass; + } + klass = RCLASS_SUPER(klass); } - ci = &cd.ci_kw.ci; - cc = &cd.cc; - sym = TOPN(i); + return current_class; /* maybe module function */ +} + +static const rb_callable_method_entry_t * +aliased_callable_method_entry(const rb_callable_method_entry_t *me) +{ + const rb_method_entry_t *orig_me = me->def->body.alias.original_me; + const rb_callable_method_entry_t *cme; - if (!(ci->mid = rb_check_id(&sym))) { - if (rb_method_basic_definition_p(CLASS_OF(calling->recv), idMethodMissing)) { - VALUE exc = - rb_make_no_method_exception(rb_eNoMethodError, 0, calling->recv, - rb_long2int(calling->argc), &TOPN(i), - ci->flag & (VM_CALL_FCALL|VM_CALL_VCALL)); - rb_exc_raise(exc); + if (orig_me->defined_class == 0) { + VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner); + VM_ASSERT(RB_TYPE_P(orig_me->owner, T_MODULE)); + cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class); + + if (me->def->alias_count + me->def->complemented_count == 0) { + RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme); + } + else { + rb_method_definition_t *def = + rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id); + rb_method_definition_set((rb_method_entry_t *)me, def, (void *)cme); } - TOPN(i) = rb_str_intern(sym); - ci->mid = idMethodMissing; - ec->method_missing_reason = cc->aux.method_missing_reason = ci_missing_reason(ci); } else { - /* shift arguments */ - if (i > 0) { - MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); - } - calling->argc -= 1; - DEC_SP(1); + cme = (const rb_callable_method_entry_t *)orig_me; } - CC_SET_ME(cc, rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid, NULL)); - ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0); - return vm_call_method(ec, reg_cfp, calling, (CALL_DATA)&cd); + VM_ASSERT(callable_method_entry_p(cme)); + return cme; } -static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler); - -NOINLINE(static VALUE - vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler)); +const rb_callable_method_entry_t * +rb_aliased_callable_method_entry(const rb_callable_method_entry_t *me) +{ + return aliased_callable_method_entry(me); +} static VALUE -vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler) +vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - int argc = calling->argc; + calling->cc = &VM_CC_ON_STACK(Qundef, + vm_call_general, + { 0 }, + aliased_callable_method_entry(vm_cc_cme(calling->cc))); - /* remove self */ - if (argc > 0) MEMMOVE(&TOPN(argc), &TOPN(argc-1), VALUE, argc); - DEC_SP(1); + return vm_call_method_each_type(ec, cfp, calling); +} - return vm_invoke_block(ec, reg_cfp, calling, ci, block_handler); +static enum method_missing_reason +ci_missing_reason(const struct rb_callinfo *ci) +{ + enum method_missing_reason stat = MISSING_NOENTRY; + if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL; + if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL; + if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER; + return stat; } static VALUE -vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE symbol) { - RB_DEBUG_COUNTER_INC(ccf_opt_call); + ASSUME(calling->argc >= 0); + /* Also assumes CALLER_SETUP_ARG is already done. */ - const struct rb_call_info *ci = &cd->ci; - VALUE procval = calling->recv; - return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval)); + enum method_missing_reason missing_reason = MISSING_NOENTRY; + int argc = calling->argc; + VALUE recv = calling->recv; + VALUE klass = CLASS_OF(recv); + ID mid = rb_check_id(&symbol); + int flags = VM_CALL_FCALL | + VM_CALL_OPT_SEND | + (calling->kw_splat ? VM_CALL_KW_SPLAT : 0); + + if (UNLIKELY(! mid)) { + mid = idMethodMissing; + missing_reason = ci_missing_reason(ci); + ec->method_missing_reason = missing_reason; + + /* E.g. when argc == 2 + * + * | | | | TOPN + * | | +------+ + * | | +---> | arg1 | 0 + * +------+ | +------+ + * | arg1 | -+ +-> | arg0 | 1 + * +------+ | +------+ + * | arg0 | ---+ | sym | 2 + * +------+ +------+ + * | recv | | recv | 3 + * --+------+--------+------+------ + */ + int i = argc; + CHECK_VM_STACK_OVERFLOW(reg_cfp, 1); + INC_SP(1); + MEMMOVE(&TOPN(i - 1), &TOPN(i), VALUE, i); + argc = ++calling->argc; + + if (rb_method_basic_definition_p(klass, idMethodMissing)) { + /* Inadvertent symbol creation shall be forbidden, see [Feature #5112] */ + TOPN(i) = symbol; + int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL); + const VALUE *argv = STACK_ADDR_FROM_TOP(argc); + VALUE exc = rb_make_no_method_exception( + rb_eNoMethodError, 0, recv, argc, argv, priv); + + rb_exc_raise(exc); + } + else { + TOPN(i) = rb_str_intern(symbol); + } + } + + calling->ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)); + calling->cc = &VM_CC_ON_STACK(klass, + vm_call_general, + { .method_missing_reason = missing_reason }, + rb_callable_method_entry_with_refinements(klass, mid, NULL)); + + return vm_call_method(ec, reg_cfp, calling); } static VALUE -vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { - RB_DEBUG_COUNTER_INC(ccf_opt_block_call); - VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp)); - const struct rb_call_info *ci = &cd->ci; + RB_DEBUG_COUNTER_INC(ccf_opt_send); - if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) { - return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler); + int i; + VALUE sym; + + CALLER_SETUP_ARG(reg_cfp, calling, calling->ci); + + i = calling->argc - 1; + + if (calling->argc == 0) { + rb_raise(rb_eArgError, "no method name given"); } else { - calling->recv = rb_vm_bh_to_procval(ec, block_handler); - vm_search_method(cd, calling->recv); - return vm_call_general(ec, reg_cfp, calling, cd); + sym = TOPN(i); + /* E.g. when i == 2 + * + * | | | | TOPN + * +------+ | | + * | arg1 | ---+ | | 0 + * +------+ | +------+ + * | arg0 | -+ +-> | arg1 | 1 + * +------+ | +------+ + * | sym | +---> | arg0 | 2 + * +------+ +------+ + * | recv | | recv | 3 + * --+------+--------+------+------ + */ + /* shift arguments */ + if (i > 0) { + MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); + } + calling->argc -= 1; + DEC_SP(1); + + return vm_call_symbol(ec, reg_cfp, calling, calling->ci, sym); } } static VALUE -vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *orig_cd) +vm_call_method_missing_body(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, + const struct rb_callinfo *orig_ci, enum method_missing_reason reason) { RB_DEBUG_COUNTER_INC(ccf_method_missing); - const struct rb_call_info *orig_ci = &orig_cd->ci; - const struct rb_call_cache *orig_cc = &orig_cd->cc; VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc); - struct rb_call_data cd = *orig_cd; unsigned int argc; CALLER_SETUP_ARG(reg_cfp, calling, orig_ci); - argc = calling->argc+1; - - cd.ci.flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0); - cd.ci.mid = idMethodMissing; - cd.ci.orig_argc = argc; - - cd.cc.me = - rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), - idMethodMissing, NULL); + argc = calling->argc + 1; + unsigned int flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0); calling->argc = argc; /* shift arguments: m(a, b, c) #=> method_missing(:m, a, b, c) */ @@ -2737,32 +3325,40 @@ vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, if (argc > 1) { MEMMOVE(argv+1, argv, VALUE, argc-1); } - argv[0] = ID2SYM(orig_ci->mid); + argv[0] = ID2SYM(vm_ci_mid(orig_ci)); INC_SP(1); - ec->method_missing_reason = orig_cc->aux.method_missing_reason; - return vm_call_method(ec, reg_cfp, calling, &cd); + ec->method_missing_reason = reason; + calling->ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)); + calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 }, + rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), idMethodMissing, NULL)); + return vm_call_method(ec, reg_cfp, calling); } -static const rb_callable_method_entry_t *refined_method_callable_without_refinement(const rb_callable_method_entry_t *me); static VALUE -vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd, VALUE klass) +vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { - RB_DEBUG_COUNTER_INC(ccf_method_missing); + return vm_call_method_missing_body(ec, reg_cfp, calling, calling->ci, vm_cc_cmethod_missing_reason(calling->cc)); +} - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; +static const rb_callable_method_entry_t *refined_method_callable_without_refinement(const rb_callable_method_entry_t *me); +static VALUE +vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, VALUE klass) +{ klass = RCLASS_SUPER(klass); - CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, ci->mid) : NULL); - if (!cc->me) { - return vm_call_method_nome(ec, cfp, calling, cd); + const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, vm_ci_mid(calling->ci)) : NULL; + if (cme == NULL) { + return vm_call_method_nome(ec, cfp, calling); } - if (cc->me->def->type == VM_METHOD_TYPE_REFINED && - cc->me->def->body.refined.orig_me) { - CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me)); + if (cme->def->type == VM_METHOD_TYPE_REFINED && + cme->def->body.refined.orig_me) { + cme = refined_method_callable_without_refinement(cme); } - return vm_call_method_each_type(ec, cfp, calling, cd); + + calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 }, cme); + + return vm_call_method_each_type(ec, cfp, calling); } static inline VALUE @@ -2794,297 +3390,406 @@ current_method_entry(const rb_execution_context_t *ec, rb_control_frame_t *cfp) return cfp; } -static VALUE -find_defined_class_by_owner(VALUE current_class, VALUE target_owner) +static const rb_callable_method_entry_t * +refined_method_callable_without_refinement(const rb_callable_method_entry_t *me) { - VALUE klass = current_class; + const rb_method_entry_t *orig_me = me->def->body.refined.orig_me; + const rb_callable_method_entry_t *cme; - /* for prepended Module, then start from cover class */ - if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN)) klass = RBASIC_CLASS(klass); + if (orig_me->defined_class == 0) { + cme = NULL; + rb_notimplement(); + } + else { + cme = (const rb_callable_method_entry_t *)orig_me; + } - while (RTEST(klass)) { - VALUE owner = RB_TYPE_P(klass, T_ICLASS) ? RBASIC_CLASS(klass) : klass; - if (owner == target_owner) { - return klass; - } - klass = RCLASS_SUPER(klass); + VM_ASSERT(callable_method_entry_p(cme)); + + if (UNDEFINED_METHOD_ENTRY_P(cme)) { + cme = NULL; } - return current_class; /* maybe module function */ + return cme; } static const rb_callable_method_entry_t * -aliased_callable_method_entry(const rb_callable_method_entry_t *me) +search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - const rb_method_entry_t *orig_me = me->def->body.alias.original_me; - const rb_callable_method_entry_t *cme; + ID mid = vm_ci_mid(calling->ci); + const rb_cref_t *cref = vm_get_cref(cfp->ep); + const struct rb_callcache * const cc = calling->cc; + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); - if (orig_me->defined_class == 0) { - VALUE defined_class = find_defined_class_by_owner(me->defined_class, orig_me->owner); - VM_ASSERT(RB_TYPE_P(orig_me->owner, T_MODULE)); - cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class); + for (; cref; cref = CREF_NEXT(cref)) { + const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner); + if (NIL_P(refinement)) continue; - if (me->def->alias_count + me->def->complemented_count == 0) { - RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme); - } - else { - rb_method_definition_t *def = - rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id); - rb_method_definition_set((rb_method_entry_t *)me, def, (void *)cme); - } + const rb_callable_method_entry_t *const ref_me = + rb_callable_method_entry(refinement, mid); + + if (ref_me) { + if (vm_cc_call(cc) == vm_call_super_method) { + const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp); + const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp); + if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) { + continue; + } + } + + if (cme->def->type != VM_METHOD_TYPE_REFINED || + cme->def != ref_me->def) { + cme = ref_me; + } + if (ref_me->def->type != VM_METHOD_TYPE_REFINED) { + return cme; + } + } + else { + return NULL; + } + } + + if (vm_cc_cme(cc)->def->body.refined.orig_me) { + return refined_method_callable_without_refinement(vm_cc_cme(cc)); } else { - cme = (const rb_callable_method_entry_t *)orig_me; + VALUE klass = RCLASS_SUPER(vm_cc_cme(cc)->defined_class); + const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, mid) : NULL; + return cme; } - - VM_ASSERT(callable_method_entry_p(cme)); - return cme; } -static const rb_callable_method_entry_t * -refined_method_callable_without_refinement(const rb_callable_method_entry_t *me) +static VALUE +vm_call_refined(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - const rb_method_entry_t *orig_me = me->def->body.refined.orig_me; - const rb_callable_method_entry_t *cme; + struct rb_callcache *ref_cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 }, + search_refined_method(ec, cfp, calling)); - if (orig_me->defined_class == 0) { - cme = NULL; - rb_notimplement(); + if (vm_cc_cme(ref_cc)) { + calling->cc= ref_cc; + return vm_call_method(ec, cfp, calling); } else { - cme = (const rb_callable_method_entry_t *)orig_me; + return vm_call_method_nome(ec, cfp, calling); } +} - VM_ASSERT(callable_method_entry_p(cme)); +static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_callinfo *ci, bool is_lambda, VALUE block_handler); - if (UNDEFINED_METHOD_ENTRY_P(cme)) { - cme = NULL; +NOINLINE(static VALUE + vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler)); + +static VALUE +vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler) +{ + int argc = calling->argc; + + /* remove self */ + if (argc > 0) MEMMOVE(&TOPN(argc), &TOPN(argc-1), VALUE, argc); + DEC_SP(1); + + return vm_invoke_block(ec, reg_cfp, calling, ci, false, block_handler); +} + +static VALUE +vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) +{ + RB_DEBUG_COUNTER_INC(ccf_opt_call); + + const struct rb_callinfo *ci = calling->ci; + VALUE procval = calling->recv; + return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval)); +} + +static VALUE +vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) +{ + RB_DEBUG_COUNTER_INC(ccf_opt_block_call); + + VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp)); + const struct rb_callinfo *ci = calling->ci; + + if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) { + return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler); + } + else { + calling->recv = rb_vm_bh_to_procval(ec, block_handler); + calling->cc = rb_vm_search_method_slowpath(ci, CLASS_OF(calling->recv)); + return vm_call_general(ec, reg_cfp, calling); } +} - return cme; +static VALUE +vm_call_opt_struct_aref0(rb_execution_context_t *ec, struct rb_calling_info *calling) +{ + VALUE recv = calling->recv; + + VM_ASSERT(RB_TYPE_P(recv, T_STRUCT)); + VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED); + VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF); + + const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index; + return internal_RSTRUCT_GET(recv, off); } -static int -search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, ID mid, struct rb_call_cache *cc) +static VALUE +vm_call_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { - const rb_cref_t *cref = vm_get_cref(cfp->ep); + RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref); + + VALUE ret = vm_call_opt_struct_aref0(ec, calling); + reg_cfp->sp -= 1; + return ret; +} + +static VALUE +vm_call_opt_struct_aset0(rb_execution_context_t *ec, struct rb_calling_info *calling, VALUE val) +{ + VALUE recv = calling->recv; + + VM_ASSERT(RB_TYPE_P(recv, T_STRUCT)); + VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED); + VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET); + + rb_check_frozen(recv); + + const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index; + internal_RSTRUCT_SET(recv, off, val); + + return val; +} + +static VALUE +vm_call_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) +{ + RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset); - for (; cref; cref = CREF_NEXT(cref)) { - const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), cc->me->owner); - if (NIL_P(refinement)) continue; + VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1)); + reg_cfp->sp -= 2; + return ret; +} - const rb_callable_method_entry_t *const ref_me = - rb_callable_method_entry(refinement, mid); +NOINLINE(static VALUE vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, + const struct rb_callinfo *ci, const struct rb_callcache *cc)); - if (ref_me) { - if (cc->call == vm_call_super_method) { - const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp); - const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp); - if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) { - continue; - } - } - if (cc->me->def->type != VM_METHOD_TYPE_REFINED || - cc->me->def != ref_me->def) { - CC_SET_ME(cc, ref_me); - } - if (ref_me->def->type != VM_METHOD_TYPE_REFINED) { - return TRUE; - } - } - else { - CC_SET_ME(cc, NULL); - return FALSE; - } - } +static VALUE +vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, + const struct rb_callinfo *ci, const struct rb_callcache *cc) +{ + switch (vm_cc_cme(cc)->def->body.optimized.type) { + case OPTIMIZED_METHOD_TYPE_SEND: + CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE); + return vm_call_opt_send(ec, cfp, calling); + case OPTIMIZED_METHOD_TYPE_CALL: + CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE); + return vm_call_opt_call(ec, cfp, calling); + case OPTIMIZED_METHOD_TYPE_BLOCK_CALL: + CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE); + return vm_call_opt_block_call(ec, cfp, calling); + case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: + CALLER_SETUP_ARG(cfp, calling, ci); + CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); + rb_check_arity(calling->argc, 0, 0); + CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)); + return vm_call_opt_struct_aref(ec, cfp, calling); - if (cc->me->def->body.refined.orig_me) { - CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me)); - } - else { - VALUE klass = RCLASS_SUPER(cc->me->defined_class); - CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, mid) : NULL); + case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: + CALLER_SETUP_ARG(cfp, calling, ci); + CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); + rb_check_arity(calling->argc, 1, 1); + CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)); + return vm_call_opt_struct_aset(ec, cfp, calling); + default: + rb_bug("vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type); } - return TRUE; } +#define VM_CALL_METHOD_ATTR(var, func, nohook) \ + if (UNLIKELY(ruby_vm_event_flags & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN))) { \ + EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \ + vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \ + var = func; \ + EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \ + vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \ + } \ + else { \ + nohook; \ + var = func; \ + } + static VALUE -vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + VALUE v; - switch (cc->me->def->type) { + switch (cme->def->type) { case VM_METHOD_TYPE_ISEQ: CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE); - return vm_call_iseq_setup(ec, cfp, calling, cd); + return vm_call_iseq_setup(ec, cfp, calling); case VM_METHOD_TYPE_NOTIMPLEMENTED: case VM_METHOD_TYPE_CFUNC: CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE); - return vm_call_cfunc(ec, cfp, calling, cd); + return vm_call_cfunc(ec, cfp, calling); case VM_METHOD_TYPE_ATTRSET: CALLER_SETUP_ARG(cfp, calling, ci); - if (calling->argc == 1 && calling->kw_splat && RHASH_EMPTY_P(cfp->sp[-1])) { - rb_warn_keyword_to_last_hash(ec, calling, ci, NULL); - } - else { - CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); - } + CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); rb_check_arity(calling->argc, 1, 1); - cc->aux.index = 0; - CC_SET_FASTPATH(cc, vm_call_attrset, !((ci->flag & VM_CALL_ARGS_SPLAT) || (ci->flag & VM_CALL_KWARG))); - return vm_call_attrset(ec, cfp, calling, cd); + vm_cc_attr_index_set(cc, 0); + const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG); + VM_CALL_METHOD_ATTR(v, + vm_call_attrset(ec, cfp, calling), + CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask))); + return v; case VM_METHOD_TYPE_IVAR: CALLER_SETUP_ARG(cfp, calling, ci); CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); rb_check_arity(calling->argc, 0, 0); - cc->aux.index = 0; - CC_SET_FASTPATH(cc, vm_call_ivar, !(ci->flag & VM_CALL_ARGS_SPLAT)); - return vm_call_ivar(ec, cfp, calling, cd); + vm_cc_attr_index_set(cc, 0); + const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT); + VM_CALL_METHOD_ATTR(v, + vm_call_ivar(ec, cfp, calling), + CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask))); + return v; case VM_METHOD_TYPE_MISSING: - cc->aux.method_missing_reason = 0; + vm_cc_method_missing_reason_set(cc, 0); CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE); - return vm_call_method_missing(ec, cfp, calling, cd); + return vm_call_method_missing(ec, cfp, calling); case VM_METHOD_TYPE_BMETHOD: CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE); - return vm_call_bmethod(ec, cfp, calling, cd); + return vm_call_bmethod(ec, cfp, calling); case VM_METHOD_TYPE_ALIAS: - CC_SET_ME(cc, aliased_callable_method_entry(cc->me)); - VM_ASSERT(cc->me != NULL); - return vm_call_method_each_type(ec, cfp, calling, cd); + CC_SET_FASTPATH(cc, vm_call_alias, TRUE); + return vm_call_alias(ec, cfp, calling); case VM_METHOD_TYPE_OPTIMIZED: - switch (cc->me->def->body.optimize_type) { - case OPTIMIZED_METHOD_TYPE_SEND: - CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE); - return vm_call_opt_send(ec, cfp, calling, cd); - case OPTIMIZED_METHOD_TYPE_CALL: - CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE); - return vm_call_opt_call(ec, cfp, calling, cd); - case OPTIMIZED_METHOD_TYPE_BLOCK_CALL: - CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE); - return vm_call_opt_block_call(ec, cfp, calling, cd); - default: - rb_bug("vm_call_method: unsupported optimized method type (%d)", - cc->me->def->body.optimize_type); - } + return vm_call_optimized(ec, cfp, calling, ci, cc); case VM_METHOD_TYPE_UNDEF: break; case VM_METHOD_TYPE_ZSUPER: - return vm_call_zsuper(ec, cfp, calling, cd, RCLASS_ORIGIN(cc->me->defined_class)); + return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class)); case VM_METHOD_TYPE_REFINED: - if (search_refined_method(ec, cfp, ci->mid, cc)) - return vm_call_method(ec, cfp, calling, cd); - else - return vm_call_method_nome(ec, cfp, calling, cd); + // CC_SET_FASTPATH(cc, vm_call_refined, TRUE); + // should not set FASTPATH since vm_call_refined assumes cc->call is vm_call_super_method on invokesuper. + return vm_call_refined(ec, cfp, calling); } - rb_bug("vm_call_method: unsupported method type (%d)", cc->me->def->type); + rb_bug("vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type); } NORETURN(static void vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE obj, int call_status)); static VALUE -vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { /* method missing */ - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; const int stat = ci_missing_reason(ci); - if (ci->mid == idMethodMissing) { + if (vm_ci_mid(ci) == idMethodMissing) { rb_control_frame_t *reg_cfp = cfp; VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc); vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat); } else { - cc->aux.method_missing_reason = stat; - CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE); - return vm_call_method_missing(ec, cfp, calling, cd); + return vm_call_method_missing_body(ec, cfp, calling, ci, stat); } } static inline VALUE -vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { - const struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; + const struct rb_callinfo *ci = calling->ci; + const struct rb_callcache *cc = calling->cc; - VM_ASSERT(callable_method_entry_p(cc->me)); + VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc))); - if (cc->me != NULL) { - switch (METHOD_ENTRY_VISI(cc->me)) { + if (vm_cc_cme(cc) != NULL) { + switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) { case METHOD_VISI_PUBLIC: /* likely */ - return vm_call_method_each_type(ec, cfp, calling, cd); + return vm_call_method_each_type(ec, cfp, calling); case METHOD_VISI_PRIVATE: - if (!(ci->flag & VM_CALL_FCALL)) { + if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) { enum method_missing_reason stat = MISSING_PRIVATE; - if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL; + if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL; - cc->aux.method_missing_reason = stat; + vm_cc_method_missing_reason_set(cc, stat); CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE); - return vm_call_method_missing(ec, cfp, calling, cd); + return vm_call_method_missing(ec, cfp, calling); } - return vm_call_method_each_type(ec, cfp, calling, cd); + return vm_call_method_each_type(ec, cfp, calling); case METHOD_VISI_PROTECTED: - if (!(ci->flag & VM_CALL_OPT_SEND)) { - if (!rb_obj_is_kind_of(cfp->self, cc->me->defined_class)) { - cc->aux.method_missing_reason = MISSING_PROTECTED; - return vm_call_method_missing(ec, cfp, calling, cd); + if (!(vm_ci_flag(ci) & VM_CALL_OPT_SEND)) { + if (!rb_obj_is_kind_of(cfp->self, vm_cc_cme(cc)->defined_class)) { + vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED); + return vm_call_method_missing(ec, cfp, calling); } else { /* caching method info to dummy cc */ - VM_ASSERT(cc->me != NULL); - if (ci->flag & VM_CALL_KWARG) { - struct rb_kwarg_call_data *kcd = (void *)cd; - struct rb_kwarg_call_data cd_entry = *kcd; - return vm_call_method_each_type(ec, cfp, calling, (void *)&cd_entry); - } - else { - struct rb_call_data cd_entry = *cd; - return vm_call_method_each_type(ec, cfp, calling, &cd_entry); - } + VM_ASSERT(vm_cc_cme(cc) != NULL); + struct rb_callcache cc_on_stack = *cc; + FL_SET_RAW((VALUE)&cc_on_stack, VM_CALLCACHE_UNMARKABLE); + calling->cc = &cc_on_stack; + return vm_call_method_each_type(ec, cfp, calling); } } - return vm_call_method_each_type(ec, cfp, calling, cd); + return vm_call_method_each_type(ec, cfp, calling); default: rb_bug("unreachable"); } } else { - return vm_call_method_nome(ec, cfp, calling, cd); + return vm_call_method_nome(ec, cfp, calling); } } static VALUE -vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_general); - return vm_call_method(ec, reg_cfp, calling, cd); + return vm_call_method(ec, reg_cfp, calling); +} + +void +rb_vm_cc_general(const struct rb_callcache *cc) +{ + VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); + VM_ASSERT(cc != vm_cc_empty()); + + *(vm_call_handler *)&cc->call_ = vm_call_general; } static VALUE -vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd) +vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling) { RB_DEBUG_COUNTER_INC(ccf_super_method); + // This line is introduced to make different from `vm_call_general` because some compilers (VC we found) + // can merge the function and the address of the function becomes same. + // The address of `vm_call_super_method` is used in `search_refined_method`, so it should be different. + if (ec == NULL) rb_bug("unreachable"); + /* this check is required to distinguish with other functions. */ - const struct rb_call_cache *cc = &cd->cc; - if (cc->call != vm_call_super_method) rb_bug("bug"); - return vm_call_method(ec, reg_cfp, calling, cd); + VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method); + return vm_call_method(ec, reg_cfp, calling); } /* super */ @@ -3093,7 +3798,7 @@ static inline VALUE vm_search_normal_superclass(VALUE klass) { if (BUILTIN_TYPE(klass) == T_ICLASS && - FL_TEST(RBASIC(klass)->klass, RMODULE_IS_REFINEMENT)) { + FL_TEST_RAW(RBASIC(klass)->klass, RMODULE_IS_REFINEMENT)) { klass = RBASIC(klass)->klass; } klass = RCLASS_ORIGIN(klass); @@ -3108,13 +3813,21 @@ vm_super_outside(void) rb_raise(rb_eNoMethodError, "super called outside of method"); } -static void +static const struct rb_callcache * +empty_cc_for_super(void) +{ +#ifdef MJIT_HEADER + return rb_vm_empty_cc_for_super(); +#else + return &vm_empty_cc_for_super; +#endif +} + +static const struct rb_callcache * vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *cd, VALUE recv) { - VALUE current_defined_class, klass; + VALUE current_defined_class; const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp); - struct rb_call_info *ci = &cd->ci; - struct rb_call_cache *cc = &cd->cc; if (!me) { vm_super_outside(); @@ -3127,7 +3840,8 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c } if (BUILTIN_TYPE(current_defined_class) != T_MODULE && - !FL_TEST(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) && + !FL_TEST_RAW(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) && + reg_cfp->iseq != method_entry_iseqptr(me) && !rb_obj_is_kind_of(recv, current_defined_class)) { VALUE m = RB_TYPE_P(current_defined_class, T_ICLASS) ? RCLASS_INCLUDER(current_defined_class) : current_defined_class; @@ -3140,26 +3854,69 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c } } - if (me->def->type == VM_METHOD_TYPE_BMETHOD && (ci->flag & VM_CALL_ZSUPER)) { + if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) { rb_raise(rb_eRuntimeError, "implicit argument passing of super from method defined" " by define_method() is not supported." " Specify all arguments explicitly."); } - ci->mid = me->def->original_id; - klass = vm_search_normal_superclass(me->defined_class); + ID mid = me->def->original_id; + + // update iseq. really? (TODO) + cd->ci = vm_ci_new_runtime(mid, + vm_ci_flag(cd->ci), + vm_ci_argc(cd->ci), + vm_ci_kwarg(cd->ci)); + + RB_OBJ_WRITTEN(reg_cfp->iseq, Qundef, cd->ci); + + const struct rb_callcache *cc; + + VALUE klass = vm_search_normal_superclass(me->defined_class); if (!klass) { /* bound instance method of module */ - cc->aux.method_missing_reason = MISSING_SUPER; - CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE); + cc = vm_cc_new(klass, NULL, vm_call_method_missing); + RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc); } else { - /* TODO: use inline cache */ - CC_SET_ME(cc, rb_callable_method_entry(klass, ci->mid)); - CC_SET_FASTPATH(cc, vm_call_super_method, TRUE); + cc = vm_search_method_fastpath((VALUE)reg_cfp->iseq, cd, klass); + const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc); + + // define_method can cache for different method id + if (cached_cme == NULL) { + // empty_cc_for_super is not markable object + cd->cc = empty_cc_for_super(); + } + else if (cached_cme->called_id != mid) { + const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid); + if (cme) { + cc = vm_cc_new(klass, cme, vm_call_super_method); + RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc); + } + else { + cd->cc = cc = empty_cc_for_super(); + } + } + else { + switch (cached_cme->def->type) { + // vm_call_refined (search_refined_method) assumes cc->call is vm_call_super_method on invokesuper + case VM_METHOD_TYPE_REFINED: + // cc->klass is superclass of receiver class. Checking cc->klass is not enough to invalidate IVC for the receiver class. + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + vm_cc_call_set(cc, vm_call_super_method); // invalidate fastpath + break; + default: + break; // use fastpath + } + } } + + VM_ASSERT((vm_cc_cme(cc), true)); + + return cc; } /* yield */ @@ -3202,13 +3959,8 @@ vm_yield_with_cfunc(rb_execution_context_t *ec, blockarg = rb_vm_bh_to_procval(ec, block_handler); frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0); - switch (kw_splat) { - case 1: + if (kw_splat) { frame_flag |= VM_FRAME_FLAG_CFRAME_KW; - break; - case 2: - frame_flag |= VM_FRAME_FLAG_CFRAME_EMPTY_KW; - break; } vm_push_frame(ec, (const rb_iseq_t *)captured->code.ifunc, @@ -3258,19 +4010,14 @@ vm_callee_setup_block_arg_arg0_check(VALUE *argv) } static int -vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t *iseq, VALUE *argv, const enum arg_setup_type arg_setup_type) +vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_callinfo *ci, const rb_iseq_t *iseq, VALUE *argv, const enum arg_setup_type arg_setup_type) { if (rb_simple_iseq_p(iseq)) { rb_control_frame_t *cfp = ec->cfp; VALUE arg0; CALLER_SETUP_ARG(cfp, calling, ci); - if (calling->kw_splat && calling->argc == iseq->body->param.lead_num + iseq->body->param.post_num && RHASH_EMPTY_P(cfp->sp[-1])) { - rb_warn_keyword_to_last_hash(ec, calling, ci, iseq); - } - else { - CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); - } + CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci); if (arg_setup_type == arg_setup_block && calling->argc == 1 && @@ -3308,27 +4055,25 @@ static int vm_yield_setup_args(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int argc, VALUE *argv, int kw_splat, VALUE block_handler, enum arg_setup_type arg_setup_type) { struct rb_calling_info calling_entry, *calling; - struct rb_call_info ci_entry, *ci; calling = &calling_entry; calling->argc = argc; calling->block_handler = block_handler; calling->kw_splat = kw_splat; calling->recv = Qundef; + struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, (kw_splat ? VM_CALL_KW_SPLAT : 0), 0, 0); - ci_entry.flag = kw_splat ? VM_CALL_KW_SPLAT : 0; - ci = &ci_entry; - - return vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, arg_setup_type); + return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type); } /* ruby iseq -> ruby block */ static VALUE vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, - int is_lambda, const struct rb_captured_block *captured) + struct rb_calling_info *calling, const struct rb_callinfo *ci, + bool is_lambda, VALUE block_handler) { + const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler); const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq); const int arg_size = iseq->body->param.size; VALUE * const rsp = GET_SP() - calling->argc; @@ -3349,36 +4094,32 @@ vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, static VALUE vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, - VALUE symbol) + struct rb_calling_info *calling, const struct rb_callinfo *ci, + MAYBE_UNUSED(bool is_lambda), VALUE block_handler) { - VALUE val; - int argc; - CALLER_SETUP_ARG(ec->cfp, calling, ci); - argc = calling->argc; - val = vm_yield_with_symbol(ec, symbol, argc, STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler); - POPN(argc); - return val; + if (calling->argc < 1) { + rb_raise(rb_eArgError, "no receiver given"); + } + else { + VALUE symbol = VM_BH_TO_SYMBOL(block_handler); + CALLER_SETUP_ARG(reg_cfp, calling, ci); + calling->recv = TOPN(--calling->argc); + return vm_call_symbol(ec, reg_cfp, calling, ci, symbol); + } } static VALUE vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, - const struct rb_captured_block *captured) + struct rb_calling_info *calling, const struct rb_callinfo *ci, + MAYBE_UNUSED(bool is_lambda), VALUE block_handler) { VALUE val; int argc; - int kw_splat = calling->kw_splat; + const struct rb_captured_block *captured = VM_BH_TO_IFUNC_BLOCK(block_handler); CALLER_SETUP_ARG(ec->cfp, calling, ci); CALLER_REMOVE_EMPTY_KW_SPLAT(ec->cfp, calling, ci); - if (kw_splat && !calling->kw_splat) { - kw_splat = 2; - } - else { - kw_splat = calling->kw_splat; - } argc = calling->argc; - val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), kw_splat, calling->block_handler, NULL); + val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler, NULL); POPN(argc); /* TODO: should put before C/yield? */ return val; } @@ -3402,33 +4143,38 @@ vm_proc_to_block_handler(VALUE procval) return Qundef; } +static VALUE +vm_invoke_proc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + struct rb_calling_info *calling, const struct rb_callinfo *ci, + bool is_lambda, VALUE block_handler) +{ + while (vm_block_handler_type(block_handler) == block_handler_type_proc) { + VALUE proc = VM_BH_TO_PROC(block_handler); + is_lambda = block_proc_is_lambda(proc); + block_handler = vm_proc_to_block_handler(proc); + } + + return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler); +} + static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler) + struct rb_calling_info *calling, const struct rb_callinfo *ci, + bool is_lambda, VALUE block_handler) { - int is_lambda = FALSE; + VALUE (*func)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + struct rb_calling_info *calling, const struct rb_callinfo *ci, + bool is_lambda, VALUE block_handler); - again: switch (vm_block_handler_type(block_handler)) { - case block_handler_type_iseq: - { - const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler); - return vm_invoke_iseq_block(ec, reg_cfp, calling, ci, is_lambda, captured); - } - case block_handler_type_ifunc: - { - const struct rb_captured_block *captured = VM_BH_TO_IFUNC_BLOCK(block_handler); - return vm_invoke_ifunc_block(ec, reg_cfp, calling, ci, captured); - } - case block_handler_type_proc: - is_lambda = block_proc_is_lambda(VM_BH_TO_PROC(block_handler)); - block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler)); - goto again; - case block_handler_type_symbol: - return vm_invoke_symbol_block(ec, reg_cfp, calling, ci, VM_BH_TO_SYMBOL(block_handler)); + case block_handler_type_iseq: func = vm_invoke_iseq_block; break; + case block_handler_type_ifunc: func = vm_invoke_ifunc_block; break; + case block_handler_type_proc: func = vm_invoke_proc_block; break; + case block_handler_type_symbol: func = vm_invoke_symbol_block; break; + default: rb_bug("vm_invoke_block: unreachable"); } - VM_UNREACHABLE(vm_invoke_block: unreachable); - return Qnil; + + return func(ec, reg_cfp, calling, ci, is_lambda, block_handler); } static VALUE @@ -3463,23 +4209,9 @@ vm_once_clear(VALUE data) return Qnil; } -rb_control_frame_t * -FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) -{ - TOPN(0) = rb_struct_aref(GET_SELF(), TOPN(0)); - return reg_cfp; -} - -rb_control_frame_t * -FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) -{ - rb_struct_aset(GET_SELF(), TOPN(0), TOPN(1)); - return reg_cfp; -} - /* defined insn */ -static enum defined_type +static bool check_respond_to_missing(VALUE obj, VALUE v) { VALUE args[2]; @@ -3488,87 +4220,70 @@ check_respond_to_missing(VALUE obj, VALUE v) args[0] = obj; args[1] = Qfalse; r = rb_check_funcall(v, idRespond_to_missing, 2, args); if (r != Qundef && RTEST(r)) { - return DEFINED_METHOD; + return true; } else { - return DEFINED_NOT_DEFINED; + return false; } } -static VALUE -vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE needstr, VALUE v) +static bool +vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v) { VALUE klass; - enum defined_type expr_type = DEFINED_NOT_DEFINED; enum defined_type type = (enum defined_type)op_type; switch (type) { case DEFINED_IVAR: - if (rb_ivar_defined(GET_SELF(), SYM2ID(obj))) { - expr_type = DEFINED_IVAR; - } - break; - case DEFINED_IVAR2: - klass = vm_get_cbase(GET_EP()); + return rb_ivar_defined(GET_SELF(), SYM2ID(obj)); break; case DEFINED_GVAR: - if (rb_gvar_defined(rb_global_entry(SYM2ID(obj)))) { - expr_type = DEFINED_GVAR; - } + return rb_gvar_defined(SYM2ID(obj)); break; case DEFINED_CVAR: { const rb_cref_t *cref = vm_get_cref(GET_EP()); - klass = vm_get_cvar_base(cref, GET_CFP()); - if (rb_cvar_defined(klass, SYM2ID(obj))) { - expr_type = DEFINED_CVAR; - } + klass = vm_get_cvar_base(cref, GET_CFP(), 0); + return rb_cvar_defined(klass, SYM2ID(obj)); break; } case DEFINED_CONST: case DEFINED_CONST_FROM: { bool allow_nil = type == DEFINED_CONST; klass = v; - if (vm_get_ev_const(ec, klass, SYM2ID(obj), allow_nil, true)) { - expr_type = DEFINED_CONST; - } + return vm_get_ev_const(ec, klass, SYM2ID(obj), allow_nil, true); break; } case DEFINED_FUNC: klass = CLASS_OF(v); - if (rb_method_boundp(klass, SYM2ID(obj), 0)) { - expr_type = DEFINED_METHOD; - } - else { - expr_type = check_respond_to_missing(obj, v); - } + return rb_ec_obj_respond_to(ec, v, SYM2ID(obj), TRUE); break; case DEFINED_METHOD:{ VALUE klass = CLASS_OF(v); - const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj)); + const rb_method_entry_t *me = rb_method_entry_with_refinements(klass, SYM2ID(obj), NULL); if (me) { switch (METHOD_ENTRY_VISI(me)) { case METHOD_VISI_PRIVATE: break; case METHOD_VISI_PROTECTED: - if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(klass))) { + if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(me->defined_class))) { break; } case METHOD_VISI_PUBLIC: - expr_type = DEFINED_METHOD; + return true; break; default: rb_bug("vm_defined: unreachable: %u", (unsigned int)METHOD_ENTRY_VISI(me)); } } else { - expr_type = check_respond_to_missing(obj, v); + return check_respond_to_missing(obj, v); } break; } case DEFINED_YIELD: if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) { - expr_type = DEFINED_YIELD; + return true; } break; case DEFINED_ZSUPER: @@ -3579,16 +4294,12 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ VALUE klass = vm_search_normal_superclass(me->defined_class); ID id = me->def->original_id; - if (rb_method_boundp(klass, id, 0)) { - expr_type = DEFINED_ZSUPER; - } + return rb_method_boundp(klass, id, 0); } } break; case DEFINED_REF:{ - if (vm_getspecial(ec, GET_LEP(), Qfalse, FIX2INT(obj)) != Qnil) { - expr_type = DEFINED_GVAR; - } + return vm_getspecial(ec, GET_LEP(), Qfalse, FIX2INT(obj)) != Qnil; break; } default: @@ -3596,17 +4307,13 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ break; } - if (expr_type != 0) { - if (needstr != Qfalse) { - return rb_iseq_defined_string(expr_type); - } - else { - return Qtrue; - } - } - else { - return Qnil; - } + return false; +} + +bool +rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v) +{ + return vm_defined(ec, reg_cfp, op_type, obj, v); } static const VALUE * @@ -3636,15 +4343,6 @@ vm_get_special_object(const VALUE *const reg_ep, } } -static void -vm_freezestring(VALUE str, VALUE debug) -{ - if (!NIL_P(debug)) { - rb_ivar_set(str, id_debug_created_info, debug); - } - rb_str_freeze(str); -} - static VALUE vm_concat_array(VALUE ary1, VALUE ary2st) { @@ -3681,6 +4379,12 @@ vm_splat_array(VALUE flag, VALUE ary) } } +VALUE +rb_vm_splat_array(VALUE flag, VALUE ary) +{ + return vm_splat_array(flag, ary); +} + static VALUE vm_check_match(rb_execution_context_t *ec, VALUE target, VALUE pattern, rb_num_t flag) { @@ -3811,6 +4515,7 @@ vm_declare_class(ID id, rb_num_t flags, VALUE cbase, VALUE super) /* new class declaration */ VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super : rb_cObject; VALUE c = declare_under(id, cbase, rb_define_class_id(id, s)); + rb_define_alloc_func(c, rb_get_alloc_func(c)); rb_class_inherited(s, c); return c; } @@ -3819,7 +4524,7 @@ static VALUE vm_declare_module(ID id, VALUE cbase) { /* new module declaration */ - return declare_under(id, cbase, rb_define_module_id(id)); + return declare_under(id, cbase, rb_module_new()); } NORETURN(static void unmatched_redefinition(const char *type, VALUE cbase, ID id, VALUE old)); @@ -3845,7 +4550,7 @@ vm_define_class(ID id, rb_num_t flags, VALUE cbase, VALUE super) if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !RB_TYPE_P(super, T_CLASS)) { rb_raise(rb_eTypeError, - "superclass must be a Class (%"PRIsVALUE" given)", + "superclass must be an instance of Class (given an instance of %"PRIsVALUE")", rb_obj_class(super)); } @@ -3938,14 +4643,14 @@ vm_define_method(const rb_execution_context_t *ec, VALUE obj, ID id, VALUE iseqv rb_method_visibility_t visi; rb_cref_t *cref = vm_ec_cref(ec); - if (!is_singleton) { - klass = CREF_CLASS(cref); - visi = vm_scope_visibility_get(ec); - } - else { /* singleton */ + if (is_singleton) { klass = rb_singleton_class(obj); /* class and frozen checked in this API */ visi = METHOD_VISI_PUBLIC; } + else { + klass = CREF_CLASS_FOR_DEFINITION(cref); + visi = vm_scope_visibility_get(ec); + } if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class/module to add method"); @@ -3959,68 +4664,102 @@ vm_define_method(const rb_execution_context_t *ec, VALUE obj, ID id, VALUE iseqv } } -static void -vm_search_method_wrap( - const struct rb_control_frame_struct *reg_cfp, - struct rb_call_data *cd, - VALUE recv) -{ - vm_search_method(cd, recv); -} - -static void -vm_search_invokeblock( - const struct rb_control_frame_struct *reg_cfp, - struct rb_call_data *cd, - VALUE recv) -{ - /* Does nothing. */ -} - static VALUE -vm_invokeblock_i( - struct rb_execution_context_struct *ec, - struct rb_control_frame_struct *reg_cfp, - struct rb_calling_info *calling, - struct rb_call_data *cd) +vm_invokeblock_i(struct rb_execution_context_struct *ec, + struct rb_control_frame_struct *reg_cfp, + struct rb_calling_info *calling) { - const struct rb_call_info *ci = &cd->ci; + const struct rb_callinfo *ci = calling->ci; VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP()); if (block_handler == VM_BLOCK_HANDLER_NONE) { rb_vm_localjump_error("no block given (yield)", Qnil, 0); } else { - return vm_invoke_block(ec, GET_CFP(), calling, ci, block_handler); + return vm_invoke_block(ec, GET_CFP(), calling, ci, false, block_handler); } } -static VALUE +#ifdef MJIT_HEADER +static const struct rb_callcache * +vm_search_method_wrap(const struct rb_control_frame_struct *reg_cfp, struct rb_call_data *cd, VALUE recv) +{ + return vm_search_method((VALUE)reg_cfp->iseq, cd, recv); +} + +static const struct rb_callcache * +vm_search_invokeblock(const struct rb_control_frame_struct *reg_cfp, struct rb_call_data *cd, VALUE recv) +{ + static const struct rb_callcache cc = { + .flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE, + .klass = 0, + .cme_ = 0, + .call_ = vm_invokeblock_i, + .aux_ = {0}, + }; + return &cc; +} + +# define mexp_search_method vm_search_method_wrap +# define mexp_search_super vm_search_super_method +# define mexp_search_invokeblock vm_search_invokeblock +#else +enum method_explorer_type { + mexp_search_method, + mexp_search_invokeblock, + mexp_search_super, +}; +#endif + +static +#ifndef MJIT_HEADER +inline +#endif +VALUE vm_sendish( struct rb_execution_context_struct *ec, struct rb_control_frame_struct *reg_cfp, struct rb_call_data *cd, VALUE block_handler, - void (*method_explorer)( - const struct rb_control_frame_struct *reg_cfp, - struct rb_call_data *cd, - VALUE recv)) -{ - CALL_INFO ci = &cd->ci; - CALL_CACHE cc = &cd->cc; - VALUE val; - int argc = ci->orig_argc; +#ifdef MJIT_HEADER + const struct rb_callcache *(*method_explorer)(const struct rb_control_frame_struct *cfp, struct rb_call_data *cd, VALUE recv) +#else + enum method_explorer_type method_explorer +#endif +) { + VALUE val = Qundef; + const struct rb_callinfo *ci = cd->ci; + const struct rb_callcache *cc; + int argc = vm_ci_argc(ci); VALUE recv = TOPN(argc); - struct rb_calling_info calling; - - calling.block_handler = block_handler; - calling.kw_splat = IS_ARGS_KW_SPLAT(ci) > 0; - calling.recv = recv; - calling.argc = argc; - - method_explorer(GET_CFP(), cd, recv); + struct rb_calling_info calling = { + .block_handler = block_handler, + .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0, + .recv = recv, + .argc = argc, + .ci = ci, + }; - val = cc->call(ec, GET_CFP(), &calling, cd); +// The enum-based branch and inlining are faster in VM, but function pointers without inlining are faster in JIT. +#ifdef MJIT_HEADER + calling.cc = cc = method_explorer(GET_CFP(), cd, recv); + val = vm_cc_call(cc)(ec, GET_CFP(), &calling); +#else + switch (method_explorer) { + case mexp_search_method: + calling.cc = cc = vm_search_method_fastpath((VALUE)reg_cfp->iseq, cd, CLASS_OF(recv)); + val = vm_cc_call(cc)(ec, GET_CFP(), &calling); + break; + case mexp_search_super: + calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv); + calling.ci = cd->ci; // TODO: does it safe? + val = vm_cc_call(cc)(ec, GET_CFP(), &calling); + break; + case mexp_search_invokeblock: + val = vm_invokeblock_i(ec, GET_CFP(), &calling); + break; + } +#endif if (val != Qundef) { return val; /* CFUNC normal return */ @@ -4055,6 +4794,70 @@ vm_sendish( #endif } +/* object.c */ +VALUE rb_nil_to_s(VALUE); +VALUE rb_true_to_s(VALUE); +VALUE rb_false_to_s(VALUE); +/* numeric.c */ +VALUE rb_int_to_s(int argc, VALUE *argv, VALUE x); +VALUE rb_fix_to_s(VALUE); +/* variable.c */ +VALUE rb_mod_to_s(VALUE); +VALUE rb_mod_name(VALUE); + +static VALUE +vm_objtostring(const rb_iseq_t *iseq, VALUE recv, CALL_DATA cd) +{ + const struct rb_callcache *cc = vm_search_method((VALUE)iseq, cd, recv); + + switch (TYPE(recv)) { + case T_STRING: + return recv; + case T_SYMBOL: + if (check_cfunc(vm_cc_cme(cc), rb_sym_to_s)) { + // rb_sym_to_s() allocates a mutable string, but since we are only + // going to use this string for interpolation, it's fine to use the + // frozen string. + return rb_sym2str(recv); + } + break; + case T_MODULE: + case T_CLASS: + if (check_cfunc(vm_cc_cme(cc), rb_mod_to_s)) { + // rb_mod_to_s() allocates a mutable string, but since we are only + // going to use this string for interpolation, it's fine to use the + // frozen string. + VALUE val = rb_mod_name(recv); + if (val == Qnil) { + val = rb_mod_to_s(recv); + } + return val; + } + break; + case T_NIL: + if (check_cfunc(vm_cc_cme(cc), rb_nil_to_s)) { + return rb_nil_to_s(recv); + } + break; + case T_TRUE: + if (check_cfunc(vm_cc_cme(cc), rb_true_to_s)) { + return rb_true_to_s(recv); + } + break; + case T_FALSE: + if (check_cfunc(vm_cc_cme(cc), rb_false_to_s)) { + return rb_false_to_s(recv); + } + break; + case T_FIXNUM: + if (check_cfunc(vm_cc_cme(cc), rb_int_to_s)) { + return rb_fix_to_s(recv); + } + break; + } + return Qundef; +} + static VALUE vm_opt_str_freeze(VALUE str, int bop, ID id) { @@ -4070,7 +4873,7 @@ vm_opt_str_freeze(VALUE str, int bop, ID id) #define id_cmp idCmp static VALUE -vm_opt_newarray_max(rb_num_t num, const VALUE *ptr) +vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr) { if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) { if (num == 0) { @@ -4090,13 +4893,12 @@ vm_opt_newarray_max(rb_num_t num, const VALUE *ptr) } } else { - VALUE ary = rb_ary_new4(num, ptr); - return rb_funcall(ary, idMax, 0); + return rb_vm_call_with_refinements(ec, rb_ary_new4(num, ptr), idMax, 0, NULL, RB_NO_KEYWORDS); } } static VALUE -vm_opt_newarray_min(rb_num_t num, const VALUE *ptr) +vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr) { if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) { if (num == 0) { @@ -4116,31 +4918,59 @@ vm_opt_newarray_min(rb_num_t num, const VALUE *ptr) } } else { - VALUE ary = rb_ary_new4(num, ptr); - return rb_funcall(ary, idMin, 0); + return rb_vm_call_with_refinements(ec, rb_ary_new4(num, ptr), idMin, 0, NULL, RB_NO_KEYWORDS); } } #undef id_cmp -static int -vm_ic_hit_p(IC ic, const VALUE *reg_ep) +#define IMEMO_CONST_CACHE_SHAREABLE IMEMO_FL_USER0 + +// For MJIT inlining +static inline bool +vm_inlined_ic_hit_p(VALUE flags, VALUE value, const rb_cref_t *ic_cref, rb_serial_t ic_serial, const VALUE *reg_ep) { - if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE()) { - return (ic->ic_cref == NULL || // no need to check CREF - ic->ic_cref == vm_get_cref(reg_ep)); + if (ic_serial == GET_GLOBAL_CONSTANT_STATE() && + ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p())) { + + VM_ASSERT((flags & IMEMO_CONST_CACHE_SHAREABLE) ? rb_ractor_shareable_p(value) : true); + + return (ic_cref == NULL || // no need to check CREF + ic_cref == vm_get_cref(reg_ep)); } - return FALSE; + return false; +} + +static bool +vm_ic_hit_p(const struct iseq_inline_constant_cache_entry *ice, const VALUE *reg_ep) +{ + VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache)); + return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, GET_IC_SERIAL(ice), reg_ep); +} + +// YJIT needs this function to never allocate and never raise +bool +rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep) +{ + return ic->entry && vm_ic_hit_p(ic->entry, reg_ep); } static void -vm_ic_update(IC ic, VALUE val, const VALUE *reg_ep) +vm_ic_update(const rb_iseq_t *iseq, IC ic, VALUE val, const VALUE *reg_ep) { - VM_ASSERT(ic->value != Qundef); - ic->value = val; - ic->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count; - ic->ic_cref = vm_get_const_key_cref(reg_ep); + + struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)rb_imemo_new(imemo_constcache, 0, 0, 0, 0); + RB_OBJ_WRITE(ice, &ice->value, val); + ice->ic_cref = vm_get_const_key_cref(reg_ep); + SET_IC_SERIAL(ice, GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count); + if (rb_ractor_shareable_p(val)) ice->flags |= IMEMO_CONST_CACHE_SHAREABLE; ruby_vm_const_missing_count = 0; + RB_OBJ_WRITE(iseq, &ic->entry, ice); +#ifndef MJIT_HEADER + // MJIT and YJIT can't be on at the same time, so there is no need to + // notify YJIT about changes to the IC when running inside MJIT code. + rb_yjit_constant_ic_update(iseq, ic); +#endif } static VALUE @@ -4362,11 +5192,17 @@ vm_opt_mod(VALUE recv, VALUE obj) } } +VALUE +rb_vm_opt_mod(VALUE recv, VALUE obj) +{ + return vm_opt_mod(recv, obj); +} + static VALUE -vm_opt_neq(CALL_DATA cd, CALL_DATA cd_eq, VALUE recv, VALUE obj) +vm_opt_neq(const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq, VALUE recv, VALUE obj) { - if (vm_method_cfunc_is(cd, recv, rb_obj_not_equal)) { - VALUE val = opt_eq_func(recv, obj, cd_eq); + if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not_equal)) { + VALUE val = opt_equality(iseq, recv, obj, cd_eq); if (val != Qundef) { return RTEST(val) ? Qfalse : Qtrue; @@ -4381,11 +5217,11 @@ vm_opt_lt(VALUE recv, VALUE obj) { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) { - return (SIGNED_VALUE)recv < (SIGNED_VALUE)obj ? Qtrue : Qfalse; + return RBOOL((SIGNED_VALUE)recv < (SIGNED_VALUE)obj); } else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { - return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj)); } else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) { return Qundef; @@ -4394,7 +5230,7 @@ vm_opt_lt(VALUE recv, VALUE obj) RBASIC_CLASS(obj) == rb_cFloat && BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); - return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj)); } else { return Qundef; @@ -4406,11 +5242,11 @@ vm_opt_le(VALUE recv, VALUE obj) { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) { - return (SIGNED_VALUE)recv <= (SIGNED_VALUE)obj ? Qtrue : Qfalse; + return RBOOL((SIGNED_VALUE)recv <= (SIGNED_VALUE)obj); } else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) { - return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj)); } else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) { return Qundef; @@ -4419,7 +5255,7 @@ vm_opt_le(VALUE recv, VALUE obj) RBASIC_CLASS(obj) == rb_cFloat && BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) { CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); - return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj)); } else { return Qundef; @@ -4431,11 +5267,11 @@ vm_opt_gt(VALUE recv, VALUE obj) { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) { - return (SIGNED_VALUE)recv > (SIGNED_VALUE)obj ? Qtrue : Qfalse; + return RBOOL((SIGNED_VALUE)recv > (SIGNED_VALUE)obj); } else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { - return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj)); } else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) { return Qundef; @@ -4444,7 +5280,7 @@ vm_opt_gt(VALUE recv, VALUE obj) RBASIC_CLASS(obj) == rb_cFloat && BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); - return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj)); } else { return Qundef; @@ -4456,11 +5292,11 @@ vm_opt_ge(VALUE recv, VALUE obj) { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) { - return (SIGNED_VALUE)recv >= (SIGNED_VALUE)obj ? Qtrue : Qfalse; + return RBOOL((SIGNED_VALUE)recv >= (SIGNED_VALUE)obj); } else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) { - return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj)); } else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) { return Qundef; @@ -4469,7 +5305,7 @@ vm_opt_ge(VALUE recv, VALUE obj) RBASIC_CLASS(obj) == rb_cFloat && BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) { CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); - return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + return RBOOL(RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj)); } else { return Qundef; @@ -4637,13 +5473,13 @@ vm_opt_empty_p(VALUE recv) VALUE rb_false(VALUE obj); static VALUE -vm_opt_nil_p(CALL_DATA cd, VALUE recv) +vm_opt_nil_p(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv) { - if (recv == Qnil && + if (NIL_P(recv) && BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) { return Qtrue; } - else if (vm_method_cfunc_is(cd, recv, rb_false)) { + else if (vm_method_cfunc_is(iseq, cd, recv, rb_false)) { return Qfalse; } else { @@ -4699,9 +5535,9 @@ vm_opt_succ(VALUE recv) } static VALUE -vm_opt_not(CALL_DATA cd, VALUE recv) +vm_opt_not(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv) { - if (vm_method_cfunc_is(cd, recv, rb_obj_not)) { + if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not)) { return RTEST(recv) ? Qfalse : Qtrue; } else { @@ -4731,7 +5567,7 @@ vm_opt_regexpmatch2(VALUE recv, VALUE obj) rb_event_flag_t rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos); -NOINLINE(static void vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE *pc)); +NOINLINE(static void vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)); static inline void vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE *pc, @@ -4761,6 +5597,22 @@ vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VAL } } +// Return true if given cc has cfunc which is NOT handled by opt_send_without_block. +bool +rb_vm_opt_cfunc_p(CALL_CACHE cc, int insn) +{ + switch (insn) { + case BIN(opt_eq): + return check_cfunc(vm_cc_cme(cc), rb_obj_equal); + case BIN(opt_nil_p): + return check_cfunc(vm_cc_cme(cc), rb_false); + case BIN(opt_not): + return check_cfunc(vm_cc_cme(cc), rb_obj_not); + default: + return false; + } +} + #define VM_TRACE_HOOK(target_event, val) do { \ if ((pc_events & (target_event)) & enabled_flags) { \ vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \ @@ -4768,9 +5620,11 @@ vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VAL } while (0) static void -vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE *pc) +vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) { + const VALUE *pc = reg_cfp->pc; rb_event_flag_t enabled_flags = ruby_vm_event_flags & ISEQ_TRACE_EVENTS; + rb_event_flag_t global_events = enabled_flags; if (enabled_flags == 0 && ruby_vm_event_local_num == 0) { return; @@ -4780,12 +5634,25 @@ vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE *p size_t pos = pc - iseq->body->iseq_encoded; rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pos); rb_hook_list_t *local_hooks = iseq->aux.exec.local_hooks; - rb_event_flag_t local_hook_events = local_hooks != NULL ? local_hooks->events : 0; - enabled_flags |= local_hook_events; + rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0; + rb_hook_list_t *bmethod_local_hooks = NULL; + rb_event_flag_t bmethod_local_events = 0; + bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp); + enabled_flags |= iseq_local_events; + + VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0); + + if (bmethod_frame) { + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp); + VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD); + bmethod_local_hooks = me->def->body.bmethod.hooks; + if (bmethod_local_hooks) { + bmethod_local_events = bmethod_local_hooks->events; + } + } - VM_ASSERT((local_hook_events & ~ISEQ_TRACE_EVENTS) == 0); - if ((pc_events & enabled_flags) == 0) { + if ((pc_events & enabled_flags) == 0 && !bmethod_frame) { #if 0 /* disable trace */ /* TODO: incomplete */ @@ -4802,46 +5669,59 @@ vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE *p return; } else { - rb_hook_list_t *global_hooks = rb_vm_global_hooks(ec); + rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(ec); + /* Note, not considering iseq local events here since the same + * iseq could be used in multiple bmethods. */ + rb_event_flag_t bmethod_events = global_events | bmethod_local_events; if (0) { - fprintf(stderr, "vm_trace>>%4d (%4x) - %s:%d %s\n", - (int)pos, - (int)pc_events, - RSTRING_PTR(rb_iseq_path(iseq)), - (int)rb_iseq_line_no(iseq, pos), - RSTRING_PTR(rb_iseq_label(iseq))); + ruby_debug_printf("vm_trace>>%4d (%4x) - %s:%d %s\n", + (int)pos, + (int)pc_events, + RSTRING_PTR(rb_iseq_path(iseq)), + (int)rb_iseq_line_no(iseq, pos), + RSTRING_PTR(rb_iseq_label(iseq))); } VM_ASSERT(reg_cfp->pc == pc); VM_ASSERT(pc_events != 0); - VM_ASSERT(enabled_flags & pc_events); /* check traces */ + if ((pc_events & RUBY_EVENT_B_CALL) && bmethod_frame && (bmethod_events & RUBY_EVENT_CALL)) { + /* b_call instruction running as a method. Fire call event. */ + vm_trace_hook(ec, reg_cfp, pc, RUBY_EVENT_CALL, RUBY_EVENT_CALL, global_hooks, bmethod_local_hooks, Qundef); + } VM_TRACE_HOOK(RUBY_EVENT_CLASS | RUBY_EVENT_CALL | RUBY_EVENT_B_CALL, Qundef); VM_TRACE_HOOK(RUBY_EVENT_LINE, Qundef); VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE, Qundef); VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH, Qundef); VM_TRACE_HOOK(RUBY_EVENT_END | RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN, TOPN(0)); + if ((pc_events & RUBY_EVENT_B_RETURN) && bmethod_frame && (bmethod_events & RUBY_EVENT_RETURN)) { + /* b_return instruction running as a method. Fire return event. */ + vm_trace_hook(ec, reg_cfp, pc, RUBY_EVENT_RETURN, RUBY_EVENT_RETURN, global_hooks, bmethod_local_hooks, TOPN(0)); + } } } } +#undef VM_TRACE_HOOK #if VM_CHECK_MODE > 0 -static NORETURN( NOINLINE( COLDFUNC -void vm_canary_is_found_dead(enum ruby_vminsn_type i, VALUE c))); +NORETURN( NOINLINE( COLDFUNC +void rb_vm_canary_is_found_dead(enum ruby_vminsn_type i, VALUE c))); void Init_vm_stack_canary(void) { /* This has to be called _after_ our PRNG is properly set up. */ int n = ruby_fill_random_bytes(&vm_stack_canary, sizeof vm_stack_canary, false); + vm_stack_canary |= 0x01; // valid VALUE (Fixnum) vm_stack_canary_was_born = true; VM_ASSERT(n == 0); } -static void -vm_canary_is_found_dead(enum ruby_vminsn_type i, VALUE c) +#ifndef MJIT_HEADER +MJIT_FUNC_EXPORTED void +rb_vm_canary_is_found_dead(enum ruby_vminsn_type i, VALUE c) { /* Because a method has already been called, why not call * another one. */ @@ -4851,6 +5731,7 @@ vm_canary_is_found_dead(enum ruby_vminsn_type i, VALUE c) rb_bug("dead canary found at %s: %s", insn, str); } +#endif #else void Init_vm_stack_canary(void) { /* nothing to do */ } @@ -5021,10 +5902,13 @@ lookup_builtin_invoker(int argc) } static inline VALUE -invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *cfp, const struct rb_builtin_function* bf, const VALUE *argv) +invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const struct rb_builtin_function* bf, const VALUE *argv) { - VALUE self = cfp->self; - return (*lookup_builtin_invoker(bf->argc))(ec, self, argv, (rb_insn_func_t)bf->func_ptr); + const bool canary_p = reg_cfp->iseq->body->builtin_inline_p; // Verify an assumption of `Primitive.attr! 'inline'` + SETUP_CANARY(canary_p); + VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, (rb_insn_func_t)bf->func_ptr); + CHECK_CANARY(canary_p, BIN(invokebuiltin)); + return ret; } static VALUE @@ -5037,12 +5921,11 @@ static VALUE vm_invoke_builtin_delegate(rb_execution_context_t *ec, rb_control_frame_t *cfp, const struct rb_builtin_function *bf, unsigned int start_index) { if (0) { // debug print - fprintf(stderr, "vm_invoke_builtin_delegate: passing -> "); + fputs("vm_invoke_builtin_delegate: passing -> ", stderr); for (int i=0; iargc; i++) { - fprintf(stderr, ":%s ", rb_id2name(cfp->iseq->body->local_table[i+start_index])); + ruby_debug_printf(":%s ", rb_id2name(cfp->iseq->body->local_table[i+start_index])); } - fprintf(stderr, "\n"); - fprintf(stderr, "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc, bf->func_ptr); + ruby_debug_printf("\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc, bf->func_ptr); } if (bf->argc == 0) { diff --git a/ruby/vm_insnhelper.h b/ruby/vm_insnhelper.h index 18a670bf1..459f56710 100644 --- a/ruby/vm_insnhelper.h +++ b/ruby/vm_insnhelper.h @@ -1,3 +1,5 @@ +#ifndef RUBY_INSNHELPER_H +#define RUBY_INSNHELPER_H /********************************************************************** insnhelper.h - helper macros to implement each instructions @@ -9,23 +11,25 @@ **********************************************************************/ -#ifndef RUBY_INSNHELPER_H -#define RUBY_INSNHELPER_H - -RUBY_SYMBOL_EXPORT_BEGIN +MJIT_SYMBOL_EXPORT_BEGIN RUBY_EXTERN VALUE ruby_vm_const_missing_count; -RUBY_EXTERN rb_serial_t ruby_vm_global_method_state; RUBY_EXTERN rb_serial_t ruby_vm_global_constant_state; RUBY_EXTERN rb_serial_t ruby_vm_class_serial; +RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state; -RUBY_SYMBOL_EXPORT_END +MJIT_SYMBOL_EXPORT_END #if VM_COLLECT_USAGE_DETAILS #define COLLECT_USAGE_INSN(insn) vm_collect_usage_insn(insn) #define COLLECT_USAGE_OPERAND(insn, n, op) vm_collect_usage_operand((insn), (n), ((VALUE)(op))) #define COLLECT_USAGE_REGISTER(reg, s) vm_collect_usage_register((reg), (s)) +#elif YJIT_STATS +/* for --yjit-stats */ +#define COLLECT_USAGE_INSN(insn) rb_yjit_collect_vm_usage_insn(insn) +#define COLLECT_USAGE_OPERAND(insn, n, op) /* none */ +#define COLLECT_USAGE_REGISTER(reg, s) /* none */ #else #define COLLECT_USAGE_INSN(insn) /* none */ #define COLLECT_USAGE_OPERAND(insn, n, op) /* none */ @@ -94,7 +98,7 @@ enum vm_regan_acttype { #define SET_SP(x) (VM_REG_SP = (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x)))) #define INC_SP(x) (VM_REG_SP += (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x)))) #define DEC_SP(x) (VM_REG_SP -= (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x)))) -#define SET_SV(x) (*GET_SP() = (x)) +#define SET_SV(x) (*GET_SP() = rb_ractor_confirm_belonging(x)) /* set current stack value as x */ /* instruction sequence C struct */ @@ -121,20 +125,13 @@ enum vm_regan_acttype { */ static inline void -CC_SET_FASTPATH(CALL_CACHE cc, vm_call_handler func, bool enabled) +CC_SET_FASTPATH(const struct rb_callcache *cc, vm_call_handler func, bool enabled) { if (LIKELY(enabled)) { - cc->call = func; + vm_cc_call_set(cc, func); } } -static inline void -CC_SET_ME(CALL_CACHE cc, const rb_callable_method_entry_t *me) -{ - cc->me = me; - cc->method_serial = me ? me->def->method_serial : 0; -} - #define GET_BLOCK_HANDLER() (GET_LEP()[VM_ENV_DATA_INDEX_SPECVAL]) /**********************************************************/ @@ -147,27 +144,27 @@ CC_SET_ME(CALL_CACHE cc, const rb_callable_method_entry_t *me) /**********************************************************/ #if VM_CHECK_MODE > 0 -#define SETUP_CANARY() \ - VALUE *canary; \ - if (leaf) { \ +#define SETUP_CANARY(cond) \ + VALUE *canary = 0; \ + if (cond) { \ canary = GET_SP(); \ SET_SV(vm_stack_canary); \ } \ else {\ SET_SV(Qfalse); /* cleanup */ \ } -#define CHECK_CANARY() \ - if (leaf) { \ +#define CHECK_CANARY(cond, insn) \ + if (cond) { \ if (*canary == vm_stack_canary) { \ *canary = Qfalse; /* cleanup */ \ } \ else { \ - vm_canary_is_found_dead(INSN_ATTR(bin), *canary); \ + rb_vm_canary_is_found_dead(insn, *canary); \ } \ } #else -#define SETUP_CANARY() /* void */ -#define CHECK_CANARY() /* void */ +#define SETUP_CANARY(cond) if (cond) {} else {} +#define CHECK_CANARY(cond, insn) if (cond) {(void)(insn);} #endif /**********************************************************/ @@ -186,10 +183,10 @@ CC_SET_ME(CALL_CACHE cc, const rb_callable_method_entry_t *me) #define PREV_CLASS_SERIAL() (ruby_vm_class_serial) #define NEXT_CLASS_SERIAL() (++ruby_vm_class_serial) -#define GET_GLOBAL_METHOD_STATE() (ruby_vm_global_method_state) -#define INC_GLOBAL_METHOD_STATE() (++ruby_vm_global_method_state) #define GET_GLOBAL_CONSTANT_STATE() (ruby_vm_global_constant_state) #define INC_GLOBAL_CONSTANT_STATE() (++ruby_vm_global_constant_state) +#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state) +#define INC_GLOBAL_CVAR_STATE() (++ruby_vm_global_cvar_state) static inline struct vm_throw_data * THROW_DATA_NEW(VALUE val, const rb_control_frame_t *cf, int st) @@ -250,18 +247,19 @@ THROW_DATA_CONSUMED_SET(struct vm_throw_data *obj) } } -#define IS_ARGS_SPLAT(ci) ((ci)->flag & VM_CALL_ARGS_SPLAT) -#define IS_ARGS_KEYWORD(ci) ((ci)->flag & VM_CALL_KWARG) -#define IS_ARGS_KW_SPLAT(ci) ((ci)->flag & VM_CALL_KW_SPLAT) -#define IS_ARGS_KW_OR_KW_SPLAT(ci) ((ci)->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT)) +#define IS_ARGS_SPLAT(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) +#define IS_ARGS_KEYWORD(ci) (vm_ci_flag(ci) & VM_CALL_KWARG) +#define IS_ARGS_KW_SPLAT(ci) (vm_ci_flag(ci) & VM_CALL_KW_SPLAT) +#define IS_ARGS_KW_OR_KW_SPLAT(ci) (vm_ci_flag(ci) & (VM_CALL_KWARG | VM_CALL_KW_SPLAT)) +#define IS_ARGS_KW_SPLAT_MUT(ci) (vm_ci_flag(ci) & VM_CALL_KW_SPLAT_MUT) /* If this returns true, an optimized function returned by `vm_call_iseq_setup_func` can be used as a fastpath. */ -static bool -vm_call_iseq_optimizable_p(const struct rb_call_info *ci, const struct rb_call_cache *cc) +static inline bool +vm_call_iseq_optimizable_p(const struct rb_callinfo *ci, const struct rb_callcache *cc) { return !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && - !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED); + METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc)); } #endif /* RUBY_INSNHELPER_H */ diff --git a/ruby/vm_method.c b/ruby/vm_method.c index 450446878..d1cfd232e 100644 --- a/ruby/vm_method.c +++ b/ruby/vm_method.c @@ -3,30 +3,13 @@ */ #include "id_table.h" +#include "yjit.h" #define METHOD_DEBUG 0 -#if OPT_GLOBAL_METHOD_CACHE -#ifndef GLOBAL_METHOD_CACHE_SIZE -#define GLOBAL_METHOD_CACHE_SIZE 0x800 -#endif -#define LSB_ONLY(x) ((x) & ~((x) - 1)) -#define POWER_OF_2_P(x) ((x) == LSB_ONLY(x)) -#if !POWER_OF_2_P(GLOBAL_METHOD_CACHE_SIZE) -# error GLOBAL_METHOD_CACHE_SIZE must be power of 2 -#endif -#ifndef GLOBAL_METHOD_CACHE_MASK -#define GLOBAL_METHOD_CACHE_MASK (GLOBAL_METHOD_CACHE_SIZE-1) -#endif - -#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&(global_method_cache.mask)) -#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache.entries + GLOBAL_METHOD_CACHE_KEY(c,m)) -#else -#define GLOBAL_METHOD_CACHE(c,m) (rb_bug("global method cache disabled improperly"), NULL) -#endif - static int vm_redefinition_check_flag(VALUE klass); static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass); +static inline rb_method_entry_t *lookup_method_table(VALUE klass, ID id); #define object_id idObject_id #define added idMethod_added @@ -37,83 +20,307 @@ static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VAL #define singleton_undefined idSingleton_method_undefined #define attached id__attached__ -struct cache_entry { - rb_serial_t method_state; - rb_serial_t class_serial; - ID mid; - rb_method_entry_t* me; - VALUE defined_class; -}; - -#if OPT_GLOBAL_METHOD_CACHE -static struct { - unsigned int size; - unsigned int mask; - struct cache_entry *entries; -} global_method_cache = { - GLOBAL_METHOD_CACHE_SIZE, - GLOBAL_METHOD_CACHE_MASK, -}; -#endif - #define ruby_running (GET_VM()->running) /* int ruby_running = 0; */ -static void -rb_class_clear_method_cache(VALUE klass, VALUE arg) +static enum rb_id_table_iterator_result +vm_ccs_dump_i(ID mid, VALUE val, void *data) { - VALUE old_serial = *(rb_serial_t *)arg; - if (RCLASS_SERIAL(klass) > old_serial) { - return; + const struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)val; + fprintf(stderr, " | %s (len:%d) ", rb_id2name(mid), ccs->len); + rp(ccs->cme); + + for (int i=0; ilen; i++) { + fprintf(stderr, " | [%d]\t", i); vm_ci_dump(ccs->entries[i].ci); + rp_m( " | \t", ccs->entries[i].cc); } - mjit_remove_class_serial(RCLASS_SERIAL(klass)); - RCLASS_SERIAL(klass) = rb_next_class_serial(); + return ID_TABLE_CONTINUE; +} - if (BUILTIN_TYPE(klass) == T_ICLASS) { - struct rb_id_table *table = RCLASS_CALLABLE_M_TBL(klass); - if (table) { - rb_id_table_clear(table); - } +static void +vm_ccs_dump(VALUE klass, ID target_mid) +{ + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + if (cc_tbl) { + VALUE ccs; + if (target_mid) { + if (rb_id_table_lookup(cc_tbl, target_mid, &ccs)) { + fprintf(stderr, " [CCTB] %p\n", (void *)cc_tbl); + vm_ccs_dump_i(target_mid, ccs, NULL); + } + } + else { + fprintf(stderr, " [CCTB] %p\n", (void *)cc_tbl); + rb_id_table_foreach(cc_tbl, vm_ccs_dump_i, (void *)target_mid); + } } - else { - VM_ASSERT(RCLASS_CALLABLE_M_TBL(klass) == 0); +} + +static enum rb_id_table_iterator_result +vm_cme_dump_i(ID mid, VALUE val, void *data) +{ + ID target_mid = (ID)data; + if (target_mid == 0 || mid == target_mid) { + rp_m(" > ", val); + } + return ID_TABLE_CONTINUE; +} + +static VALUE +vm_mtbl_dump(VALUE klass, ID target_mid) +{ + fprintf(stderr, "# vm_mtbl\n"); + while (klass) { + rp_m(" -> ", klass); + VALUE me; + + if (RCLASS_M_TBL(klass)) { + if (target_mid != 0) { + if (rb_id_table_lookup(RCLASS_M_TBL(klass), target_mid, &me)) { + rp_m(" [MTBL] ", me); + } + } + else { + fprintf(stderr, " ## RCLASS_M_TBL (%p)\n", (void *)RCLASS_M_TBL(klass)); + rb_id_table_foreach(RCLASS_M_TBL(klass), vm_cme_dump_i, NULL); + } + } + else { + fprintf(stderr, " MTBL: NULL\n"); + } + if (RCLASS_CALLABLE_M_TBL(klass)) { + if (target_mid != 0) { + if (rb_id_table_lookup(RCLASS_CALLABLE_M_TBL(klass), target_mid, &me)) { + rp_m(" [CM**] ", me); + } + } + else { + fprintf(stderr, " ## RCLASS_CALLABLE_M_TBL\n"); + rb_id_table_foreach(RCLASS_CALLABLE_M_TBL(klass), vm_cme_dump_i, NULL); + } + } + if (RCLASS_CC_TBL(klass)) { + vm_ccs_dump(klass, target_mid); + } + klass = RCLASS_SUPER(klass); } + return Qnil; +} - rb_class_foreach_subclass(klass, rb_class_clear_method_cache, arg); +void +rb_vm_mtbl_dump(const char *msg, VALUE klass, ID target_mid) +{ + fprintf(stderr, "[%s] ", msg); + vm_mtbl_dump(klass, target_mid); +} + +static inline void +vm_cme_invalidate(rb_callable_method_entry_t *cme) +{ + VM_ASSERT(IMEMO_TYPE_P(cme, imemo_ment)); + VM_ASSERT(callable_method_entry_p(cme)); + METHOD_ENTRY_INVALIDATED_SET(cme); + RB_DEBUG_COUNTER_INC(cc_cme_invalidate); + + rb_yjit_cme_invalidate((VALUE)cme); } void rb_clear_constant_cache(void) { + rb_yjit_constant_state_changed(); INC_GLOBAL_CONSTANT_STATE(); } +static void +invalidate_negative_cache(ID mid) +{ + VALUE cme; + rb_vm_t *vm = GET_VM(); + + if (rb_id_table_lookup(vm->negative_cme_table, mid, &cme)) { + rb_id_table_delete(vm->negative_cme_table, mid); + vm_cme_invalidate((rb_callable_method_entry_t *)cme); + RB_DEBUG_COUNTER_INC(cc_invalidate_negative); + } +} + +static rb_method_entry_t *rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def); +const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me); +static const rb_callable_method_entry_t *complemented_callable_method_entry(VALUE klass, ID id); +static const rb_callable_method_entry_t *lookup_overloaded_cme(const rb_callable_method_entry_t *cme); + + +static void +clear_method_cache_by_id_in_class(VALUE klass, ID mid) +{ + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS)); + if (rb_objspace_garbage_object_p(klass)) return; + + RB_VM_LOCK_ENTER(); + if (LIKELY(RCLASS_SUBCLASSES(klass) == NULL)) { + // no subclasses + // check only current class + + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + VALUE ccs_data; + + // invalidate CCs + if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_data; + if (NIL_P(ccs->cme->owner)) invalidate_negative_cache(mid); + rb_vm_ccs_free(ccs); + rb_id_table_delete(cc_tbl, mid); + RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs); + } + + // remove from callable_m_tbl, if exists + struct rb_id_table *cm_tbl; + if ((cm_tbl = RCLASS_CALLABLE_M_TBL(klass)) != NULL) { + rb_id_table_delete(cm_tbl, mid); + RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_callable); + } + RB_DEBUG_COUNTER_INC(cc_invalidate_leaf); + } + else { + const rb_callable_method_entry_t *cme = complemented_callable_method_entry(klass, mid); + + if (cme) { + // invalidate cme if found to invalidate the inline method cache. + if (METHOD_ENTRY_CACHED(cme)) { + if (METHOD_ENTRY_COMPLEMENTED(cme)) { + // do nothing + } + else { + // invalidate cc by invalidating cc->cme + VALUE owner = cme->owner; + VM_ASSERT(BUILTIN_TYPE(owner) == T_CLASS); + VALUE klass_housing_cme; + if (cme->def->type == VM_METHOD_TYPE_REFINED && !cme->def->body.refined.orig_me) { + klass_housing_cme = owner; + } + else { + klass_housing_cme = RCLASS_ORIGIN(owner); + } + // replace the cme that will be invalid + VM_ASSERT(lookup_method_table(klass_housing_cme, mid) == (const rb_method_entry_t *)cme); + const rb_method_entry_t *new_cme = rb_method_entry_clone((const rb_method_entry_t *)cme); + rb_method_table_insert(klass_housing_cme, RCLASS_M_TBL(klass_housing_cme), mid, new_cme); + } + + vm_cme_invalidate((rb_callable_method_entry_t *)cme); + RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme); + + if (cme->def->iseq_overload) { + rb_callable_method_entry_t *monly_cme = (rb_callable_method_entry_t *)lookup_overloaded_cme(cme); + if (monly_cme) { + vm_cme_invalidate(monly_cme); + } + } + } + + // invalidate complement tbl + if (METHOD_ENTRY_COMPLEMENTED(cme)) { + VALUE defined_class = cme->defined_class; + struct rb_id_table *cm_tbl = RCLASS_CALLABLE_M_TBL(defined_class); + VM_ASSERT(cm_tbl != NULL); + int r = rb_id_table_delete(cm_tbl, mid); + VM_ASSERT(r == TRUE); (void)r; + RB_DEBUG_COUNTER_INC(cc_invalidate_tree_callable); + } + + RB_DEBUG_COUNTER_INC(cc_invalidate_tree); + } + else { + invalidate_negative_cache(mid); + } + } + RB_VM_LOCK_LEAVE(); + + rb_yjit_method_lookup_change(klass, mid); +} + +static void +clear_iclass_method_cache_by_id(VALUE iclass, VALUE d) +{ + VM_ASSERT(RB_TYPE_P(iclass, T_ICLASS)); + ID mid = (ID)d; + clear_method_cache_by_id_in_class(iclass, mid); +} + +static void +clear_iclass_method_cache_by_id_for_refinements(VALUE klass, VALUE d) +{ + if (RB_TYPE_P(klass, T_ICLASS)) { + ID mid = (ID)d; + clear_method_cache_by_id_in_class(klass, mid); + } +} + void -rb_clear_method_cache_by_class(VALUE klass) +rb_clear_method_cache(VALUE klass_or_module, ID mid) { - if (klass && klass != Qundef) { - int global = klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel; + if (RB_TYPE_P(klass_or_module, T_MODULE)) { + VALUE module = klass_or_module; // alias + + if (FL_TEST(module, RMODULE_IS_REFINEMENT)) { + VALUE refined_class = rb_refinement_module_get_refined_class(module); + rb_clear_method_cache(refined_class, mid); + rb_class_foreach_subclass(refined_class, clear_iclass_method_cache_by_id_for_refinements, mid); + } + rb_class_foreach_subclass(module, clear_iclass_method_cache_by_id, mid); + } + else { + clear_method_cache_by_id_in_class(klass_or_module, mid); + } +} - RUBY_DTRACE_HOOK(METHOD_CACHE_CLEAR, (global ? "global" : rb_class2name(klass))); +// gc.c +void rb_cc_table_free(VALUE klass); - if (global) { - INC_GLOBAL_METHOD_STATE(); - } - else { - rb_serial_t old_serial = PREV_CLASS_SERIAL(); - rb_class_clear_method_cache(klass, (VALUE)&old_serial); - } +static int +invalidate_all_cc(void *vstart, void *vend, size_t stride, void *data) +{ + VALUE v = (VALUE)vstart; + for (; v != (VALUE)vend; v += stride) { + void *ptr = asan_poisoned_object_p(v); + asan_unpoison_object(v, false); + if (RBASIC(v)->flags) { // liveness check + if (RB_TYPE_P(v, T_CLASS) || + RB_TYPE_P(v, T_ICLASS)) { + if (RCLASS_CC_TBL(v)) { + rb_cc_table_free(v); + } + RCLASS_CC_TBL(v) = NULL; + } + } + if (ptr) { + asan_poison_object(v); + } } + return 0; // continue to iteration +} - if (klass == rb_mKernel) { - rb_subclass_entry_t *entry = RCLASS_EXT(klass)->subclasses; +void +rb_clear_method_cache_all(void) +{ + rb_objspace_each_objects(invalidate_all_cc, NULL); - for (; entry != NULL; entry = entry->next) { - struct rb_id_table *table = RCLASS_CALLABLE_M_TBL(entry->klass); - if (table)rb_id_table_clear(table); - } + rb_yjit_invalidate_all_method_lookup_assumptions(); +} + +void +rb_method_table_insert(VALUE klass, struct rb_id_table *table, ID method_id, const rb_method_entry_t *me) +{ + VALUE table_owner = klass; + if (RB_TYPE_P(klass, T_ICLASS) && !RICLASS_OWNS_M_TBL_P(klass)) { + table_owner = RBASIC(table_owner)->klass; } + VM_ASSERT(RB_TYPE_P(table_owner, T_CLASS) || RB_TYPE_P(table_owner, T_ICLASS) || RB_TYPE_P(table_owner, T_MODULE)); + VM_ASSERT(table == RCLASS_M_TBL(table_owner)); + rb_id_table_insert(table, method_id, (VALUE)me); + RB_OBJ_WRITTEN(table_owner, Qundef, (VALUE)me); } VALUE @@ -138,13 +345,23 @@ rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_me rb_method_cfunc_t opt; opt.func = func; opt.argc = argc; - rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi); + rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi); } else { rb_define_notimplement_method_id(klass, mid, visi); } } +void +rb_add_method_optimized(VALUE klass, ID mid, enum method_optimized_type opt_type, unsigned int index, rb_method_visibility_t visi) +{ + rb_method_optimized_t opt = { + .type = opt_type, + .index = index, + }; + rb_add_method(klass, mid, VM_METHOD_TYPE_OPTIMIZED, &opt, visi); +} + static void rb_method_definition_release(rb_method_definition_t *def, int complemented) { @@ -161,8 +378,13 @@ rb_method_definition_release(rb_method_definition_t *def, int complemented) xfree(def); } else { - if (complemented) def->complemented_count--; - else if (def->alias_count > 0) def->alias_count--; + if (complemented) { + VM_ASSERT(def->complemented_count > 0); + def->complemented_count--; + } + else if (def->alias_count > 0) { + def->alias_count--; + } if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d->%d,%d->%d (dec)\n", (void *)def, rb_id2name(def->original_id), alias_count, def->alias_count, complemented_count, def->complemented_count); @@ -170,58 +392,75 @@ rb_method_definition_release(rb_method_definition_t *def, int complemented) } } +static void delete_overloaded_cme(const rb_callable_method_entry_t *cme); + void rb_free_method_entry(const rb_method_entry_t *me) { + if (me->def && me->def->iseq_overload) { + delete_overloaded_cme((const rb_callable_method_entry_t *)me); + } rb_method_definition_release(me->def, METHOD_ENTRY_COMPLEMENTED(me)); } static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr); extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); -static inline rb_method_entry_t * -lookup_method_table(VALUE klass, ID id) -{ - st_data_t body; - struct rb_id_table *m_tbl = RCLASS_M_TBL(klass); - - if (rb_id_table_lookup(m_tbl, id, &body)) { - return (rb_method_entry_t *) body; - } - else { - return 0; - } -} - static VALUE (*call_cfunc_invoker_func(int argc))(VALUE recv, int argc, const VALUE *, VALUE (*func)(ANYARGS)) { - switch (argc) { - case -2: return &call_cfunc_m2; - case -1: return &call_cfunc_m1; - case 0: return &call_cfunc_0; - case 1: return &call_cfunc_1; - case 2: return &call_cfunc_2; - case 3: return &call_cfunc_3; - case 4: return &call_cfunc_4; - case 5: return &call_cfunc_5; - case 6: return &call_cfunc_6; - case 7: return &call_cfunc_7; - case 8: return &call_cfunc_8; - case 9: return &call_cfunc_9; - case 10: return &call_cfunc_10; - case 11: return &call_cfunc_11; - case 12: return &call_cfunc_12; - case 13: return &call_cfunc_13; - case 14: return &call_cfunc_14; - case 15: return &call_cfunc_15; - default: - rb_bug("call_cfunc_func: unsupported length: %d", argc); + if (!GET_THREAD()->ext_config.ractor_safe) { + switch (argc) { + case -2: return &call_cfunc_m2; + case -1: return &call_cfunc_m1; + case 0: return &call_cfunc_0; + case 1: return &call_cfunc_1; + case 2: return &call_cfunc_2; + case 3: return &call_cfunc_3; + case 4: return &call_cfunc_4; + case 5: return &call_cfunc_5; + case 6: return &call_cfunc_6; + case 7: return &call_cfunc_7; + case 8: return &call_cfunc_8; + case 9: return &call_cfunc_9; + case 10: return &call_cfunc_10; + case 11: return &call_cfunc_11; + case 12: return &call_cfunc_12; + case 13: return &call_cfunc_13; + case 14: return &call_cfunc_14; + case 15: return &call_cfunc_15; + default: + rb_bug("unsupported length: %d", argc); + } + } + else { + switch (argc) { + case -2: return &ractor_safe_call_cfunc_m2; + case -1: return &ractor_safe_call_cfunc_m1; + case 0: return &ractor_safe_call_cfunc_0; + case 1: return &ractor_safe_call_cfunc_1; + case 2: return &ractor_safe_call_cfunc_2; + case 3: return &ractor_safe_call_cfunc_3; + case 4: return &ractor_safe_call_cfunc_4; + case 5: return &ractor_safe_call_cfunc_5; + case 6: return &ractor_safe_call_cfunc_6; + case 7: return &ractor_safe_call_cfunc_7; + case 8: return &ractor_safe_call_cfunc_8; + case 9: return &ractor_safe_call_cfunc_9; + case 10: return &ractor_safe_call_cfunc_10; + case 11: return &ractor_safe_call_cfunc_11; + case 12: return &ractor_safe_call_cfunc_12; + case 13: return &ractor_safe_call_cfunc_13; + case 14: return &ractor_safe_call_cfunc_14; + case 15: return &ractor_safe_call_cfunc_15; + default: + rb_bug("unsupported length: %d", argc); + } } } static void -setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc) +setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(ANYARGS), int argc) { cfunc->func = func; cfunc->argc = argc; @@ -238,10 +477,13 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de case VM_METHOD_TYPE_ISEQ: { rb_method_iseq_t *iseq_body = (rb_method_iseq_t *)opts; + const rb_iseq_t *iseq = iseq_body->iseqptr; rb_cref_t *method_cref, *cref = iseq_body->cref; /* setup iseq first (before invoking GC) */ - RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, iseq_body->iseqptr); + RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, iseq); + + if (iseq->body->mandatory_only_iseq) def->iseq_overload = 1; if (0) vm_cref_dump("rb_method_definition_create", cref); @@ -283,12 +525,13 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de } case VM_METHOD_TYPE_BMETHOD: RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts); + RB_OBJ_WRITE(me, &def->body.bmethod.defined_ractor, rb_ractor_self(GET_RACTOR())); return; case VM_METHOD_TYPE_NOTIMPLEMENTED: setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1); return; case VM_METHOD_TYPE_OPTIMIZED: - def->body.optimize_type = (enum method_optimized_type)opts; + def->body.optimized = *(rb_method_optimized_t *)opts; return; case VM_METHOD_TYPE_REFINED: { @@ -313,17 +556,18 @@ method_definition_reset(const rb_method_entry_t *me) { rb_method_definition_t *def = me->def; - switch(def->type) { + switch (def->type) { case VM_METHOD_TYPE_ISEQ: RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.iseqptr); RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.cref); - break; + break; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: RB_OBJ_WRITTEN(me, Qundef, def->body.attr.location); break; case VM_METHOD_TYPE_BMETHOD: RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.proc); + RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.defined_ractor); /* give up to check all in a list */ if (def->body.bmethod.hooks) rb_gc_writebarrier_remember((VALUE)me); break; @@ -389,6 +633,8 @@ filter_defined_class(VALUE klass) return 0; case T_ICLASS: break; + default: + break; } rb_bug("filter_defined_class: %s", rb_obj_info(klass)); } @@ -406,7 +652,11 @@ const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me) { rb_method_entry_t *me = rb_method_entry_alloc(src_me->called_id, src_me->owner, src_me->defined_class, - method_definition_addref(src_me->def)); + method_definition_addref(src_me->def)); + if (METHOD_ENTRY_COMPLEMENTED(src_me)) { + method_definition_addref_complement(src_me->def); + } + METHOD_ENTRY_FLAGS_COPY(me, src_me); return me; } @@ -487,6 +737,20 @@ make_method_entry_refined(VALUE owner, rb_method_entry_t *me) } } +static inline rb_method_entry_t * +lookup_method_table(VALUE klass, ID id) +{ + st_data_t body; + struct rb_id_table *m_tbl = RCLASS_M_TBL(klass); + + if (rb_id_table_lookup(m_tbl, id, &body)) { + return (rb_method_entry_t *) body; + } + else { + return 0; + } +} + void rb_add_refined_method_entry(VALUE refined_class, ID mid) { @@ -494,7 +758,7 @@ rb_add_refined_method_entry(VALUE refined_class, ID mid) if (me) { make_method_entry_refined(refined_class, me); - rb_clear_method_cache_by_class(refined_class); + rb_clear_method_cache(refined_class, mid); } else { rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, METHOD_VISI_PUBLIC); @@ -539,10 +803,13 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil struct rb_id_table *mtbl; st_data_t data; int make_refined = 0; + VALUE orig_klass; if (NIL_P(klass)) { klass = rb_cObject; } + orig_klass = klass; + if (!FL_TEST(klass, FL_SINGLETON) && type != VM_METHOD_TYPE_NOTIMPLEMENTED && type != VM_METHOD_TYPE_ZSUPER) { @@ -556,7 +823,9 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil } } - rb_class_modify_check(klass); + if (type != VM_METHOD_TYPE_REFINED) { + rb_class_modify_check(klass); + } if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); @@ -568,6 +837,9 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil } else { klass = RCLASS_ORIGIN(klass); + if (klass != orig_klass) { + rb_clear_method_cache(orig_klass, mid); + } } mtbl = RCLASS_M_TBL(klass); @@ -584,6 +856,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil if (RTEST(ruby_verbose) && type != VM_METHOD_TYPE_UNDEF && (old_def->alias_count == 0) && + (!old_def->no_redef_warning) && !make_refined && old_def->type != VM_METHOD_TYPE_UNDEF && old_def->type != VM_METHOD_TYPE_ZSUPER && @@ -615,7 +888,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil if (def == NULL) def = rb_method_definition_create(type, original_id); rb_method_definition_set(me, def, opts); - rb_clear_method_cache_by_class(klass); + rb_clear_method_cache(klass, mid); /* check mid */ if (klass == rb_cObject) { @@ -638,19 +911,134 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil make_method_entry_refined(klass, me); } - rb_id_table_insert(mtbl, mid, (VALUE)me); - RB_OBJ_WRITTEN(klass, Qundef, (VALUE)me); + rb_method_table_insert(klass, mtbl, mid, me); VM_ASSERT(me->def != NULL); /* check optimized method override by a prepended module */ - if (RB_TYPE_P(klass, T_MODULE)) { + if (RB_TYPE_P(orig_klass, T_MODULE)) { check_override_opt_method(klass, (VALUE)mid); } return me; } +static rb_method_entry_t *rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def); + +static st_table * +overloaded_cme_table(void) +{ + VM_ASSERT(GET_VM()->overloaded_cme_table != NULL); + return GET_VM()->overloaded_cme_table; +} + +#if VM_CHECK_MODE > 0 +static int +vm_dump_overloaded_cme_table(st_data_t key, st_data_t val, st_data_t dmy) +{ + fprintf(stderr, "key: "); rp(key); + fprintf(stderr, "val: "); rp(val); + return ST_CONTINUE; +} + +void +rb_vm_dump_overloaded_cme_table(void) +{ + fprintf(stderr, "== rb_vm_dump_overloaded_cme_table\n"); + st_foreach(overloaded_cme_table(), vm_dump_overloaded_cme_table, 0); +} +#endif + +static int +lookup_overloaded_cme_i(st_data_t *key, st_data_t *value, st_data_t data, int existing) +{ + if (existing) { + const rb_callable_method_entry_t *cme = (const rb_callable_method_entry_t *)*key; + const rb_callable_method_entry_t *monly_cme = (const rb_callable_method_entry_t *)*value; + const rb_callable_method_entry_t **ptr = (const rb_callable_method_entry_t **)data; + + if (rb_objspace_garbage_object_p((VALUE)cme) || + rb_objspace_garbage_object_p((VALUE)monly_cme)) { + *ptr = NULL; + return ST_DELETE; + } + else { + *ptr = monly_cme; + } + } + + return ST_STOP; +} + +static const rb_callable_method_entry_t * +lookup_overloaded_cme(const rb_callable_method_entry_t *cme) +{ + ASSERT_vm_locking(); + + const rb_callable_method_entry_t *monly_cme = NULL; + st_update(overloaded_cme_table(), (st_data_t)cme, lookup_overloaded_cme_i, (st_data_t)&monly_cme); + return monly_cme; +} + +#if VM_CHECK_MODE > 0 +MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * +rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t *cme) +{ + return lookup_overloaded_cme(cme); +} +#endif + +static void +delete_overloaded_cme(const rb_callable_method_entry_t *cme) +{ + ASSERT_vm_locking(); + st_delete(overloaded_cme_table(), (st_data_t *)&cme, NULL); +} + +static const rb_callable_method_entry_t * +get_overloaded_cme(const rb_callable_method_entry_t *cme) +{ + const rb_callable_method_entry_t *monly_cme = lookup_overloaded_cme(cme); + + if (monly_cme && !METHOD_ENTRY_INVALIDATED(monly_cme)) { + return monly_cme; + } + else { + // create + rb_method_definition_t *def = rb_method_definition_create(VM_METHOD_TYPE_ISEQ, cme->def->original_id); + def->body.iseq.cref = cme->def->body.iseq.cref; + def->body.iseq.iseqptr = cme->def->body.iseq.iseqptr->body->mandatory_only_iseq; + + rb_method_entry_t *me = rb_method_entry_alloc(cme->called_id, + cme->owner, + cme->defined_class, + def); + + ASSERT_vm_locking(); + st_insert(overloaded_cme_table(), (st_data_t)cme, (st_data_t)me); + + METHOD_ENTRY_VISI_SET(me, METHOD_ENTRY_VISI(cme)); + return (rb_callable_method_entry_t *)me; + } +} + +static const rb_callable_method_entry_t * +check_overloaded_cme(const rb_callable_method_entry_t *cme, const struct rb_callinfo * const ci) +{ + if (UNLIKELY(cme->def->iseq_overload) && + (vm_ci_flag(ci) & (VM_CALL_ARGS_SIMPLE)) && + (int)vm_ci_argc(ci) == method_entry_iseqptr(cme)->body->param.lead_num) { + VM_ASSERT(cme->def->type == VM_METHOD_TYPE_ISEQ); // iseq_overload is marked only on ISEQ methods + + cme = get_overloaded_cme(cme); + + VM_ASSERT(cme != NULL); + METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme); + } + + return cme; +} + #define CALL_METHOD_HOOK(klass, hook, mid) do { \ const VALUE arg = ID2SYM(mid); \ VALUE recv_class = (klass); \ @@ -690,6 +1078,7 @@ rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, iseq_body.iseqptr = iseq; iseq_body.cref = cref; + rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi); } @@ -698,7 +1087,13 @@ method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi, VALUE defined_class) { rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi, - me->def->type, method_definition_addref(me->def), 0, NULL); + me->def->type, me->def, 0, NULL); + if (newme == me) { + me->def->no_redef_warning = TRUE; + } + else { + method_definition_addref(me->def); + } method_added(klass, mid); return newme; } @@ -715,7 +1110,7 @@ void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) { Check_Type(klass, T_CLASS); - RCLASS_EXT(klass)->allocator = func; + RCLASS_ALLOCATOR(klass) = func; } void @@ -730,156 +1125,230 @@ rb_get_alloc_func(VALUE klass) Check_Type(klass, T_CLASS); for (; klass; klass = RCLASS_SUPER(klass)) { - rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator; + rb_alloc_func_t allocator = RCLASS_ALLOCATOR(klass); if (allocator == UNDEF_ALLOC_FUNC) break; if (allocator) return allocator; } return 0; } +const rb_method_entry_t * +rb_method_entry_at(VALUE klass, ID id) +{ + return lookup_method_table(klass, id); +} + static inline rb_method_entry_t* -search_method(VALUE klass, ID id, VALUE *defined_class_ptr) +search_method0(VALUE klass, ID id, VALUE *defined_class_ptr, bool skip_refined) { - rb_method_entry_t *me; + rb_method_entry_t *me = NULL; + + RB_DEBUG_COUNTER_INC(mc_search); for (; klass; klass = RCLASS_SUPER(klass)) { RB_DEBUG_COUNTER_INC(mc_search_super); - if ((me = lookup_method_table(klass, id)) != 0) break; + if ((me = lookup_method_table(klass, id)) != 0) { + if (!skip_refined || me->def->type != VM_METHOD_TYPE_REFINED || + me->def->body.refined.orig_me) { + break; + } + } } - if (defined_class_ptr) - *defined_class_ptr = klass; + if (defined_class_ptr) *defined_class_ptr = klass; + + if (me == NULL) RB_DEBUG_COUNTER_INC(mc_search_notfound); + + VM_ASSERT(me == NULL || !METHOD_ENTRY_INVALIDATED(me)); return me; } -const rb_method_entry_t * -rb_method_entry_at(VALUE klass, ID id) +static inline rb_method_entry_t* +search_method(VALUE klass, ID id, VALUE *defined_class_ptr) { - return lookup_method_table(klass, id); + return search_method0(klass, id, defined_class_ptr, false); } -/* - * search method entry without the method cache. - * - * if you need method entry with method cache (normal case), use - * rb_method_entry() simply. - */ static rb_method_entry_t * -method_entry_get_without_cache(VALUE klass, ID id, - VALUE *defined_class_ptr) +search_method_protect(VALUE klass, ID id, VALUE *defined_class_ptr) { - VALUE defined_class; - rb_method_entry_t *me = search_method(klass, id, &defined_class); - - if (ruby_running) { - if (OPT_GLOBAL_METHOD_CACHE) { - struct cache_entry *ent; - ent = GLOBAL_METHOD_CACHE(klass, id); - ent->class_serial = RCLASS_SERIAL(klass); - ent->method_state = GET_GLOBAL_METHOD_STATE(); - ent->defined_class = defined_class; - ent->mid = id; + rb_method_entry_t *me = search_method(klass, id, defined_class_ptr); - if (UNDEFINED_METHOD_ENTRY_P(me)) { - me = ent->me = NULL; - } - else { - ent->me = me; - } - } - else if (UNDEFINED_METHOD_ENTRY_P(me)) { - me = NULL; - } + if (!UNDEFINED_METHOD_ENTRY_P(me)) { + return me; } - else if (UNDEFINED_METHOD_ENTRY_P(me)) { - me = NULL; + else { + return NULL; } +} - if (defined_class_ptr) - *defined_class_ptr = defined_class; - return me; +MJIT_FUNC_EXPORTED const rb_method_entry_t * +rb_method_entry(VALUE klass, ID id) +{ + return search_method_protect(klass, id, NULL); } -static void -verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me) +static inline const rb_callable_method_entry_t * +prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_t * const me, int create) { - if (!VM_DEBUG_VERIFY_METHOD_CACHE) return; - VALUE actual_defined_class; - rb_method_entry_t *actual_me = - method_entry_get_without_cache(klass, id, &actual_defined_class); + struct rb_id_table *mtbl; + const rb_callable_method_entry_t *cme; + VALUE cme_data; - if (me != actual_me || defined_class != actual_defined_class) { - rb_bug("method cache verification failed"); + if (me) { + if (me->defined_class == 0) { + RB_DEBUG_COUNTER_INC(mc_cme_complement); + VM_ASSERT(RB_TYPE_P(defined_class, T_ICLASS) || RB_TYPE_P(defined_class, T_MODULE)); + VM_ASSERT(me->defined_class == 0); + + mtbl = RCLASS_CALLABLE_M_TBL(defined_class); + + if (mtbl && rb_id_table_lookup(mtbl, id, &cme_data)) { + cme = (rb_callable_method_entry_t *)cme_data; + RB_DEBUG_COUNTER_INC(mc_cme_complement_hit); + VM_ASSERT(callable_method_entry_p(cme)); + VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme)); + } + else if (create) { + if (!mtbl) { + mtbl = RCLASS_EXT(defined_class)->callable_m_tbl = rb_id_table_create(0); + } + cme = rb_method_entry_complement_defined_class(me, me->called_id, defined_class); + rb_id_table_insert(mtbl, id, (VALUE)cme); + RB_OBJ_WRITTEN(defined_class, Qundef, (VALUE)cme); + VM_ASSERT(callable_method_entry_p(cme)); + } + else { + return NULL; + } + } + else { + cme = (const rb_callable_method_entry_t *)me; + VM_ASSERT(callable_method_entry_p(cme)); + VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme)); + } + return cme; + } + else { + return NULL; } } -static rb_method_entry_t * -method_entry_get(VALUE klass, ID id, VALUE *defined_class_ptr) +static const rb_callable_method_entry_t * +complemented_callable_method_entry(VALUE klass, ID id) { - struct cache_entry *ent; - if (!OPT_GLOBAL_METHOD_CACHE) goto nocache; - ent = GLOBAL_METHOD_CACHE(klass, id); - if (ent->method_state == GET_GLOBAL_METHOD_STATE() && - ent->class_serial == RCLASS_SERIAL(klass) && - ent->mid == id) { - verify_method_cache(klass, id, ent->defined_class, ent->me); - if (defined_class_ptr) *defined_class_ptr = ent->defined_class; - RB_DEBUG_COUNTER_INC(mc_global_hit); - return ent->me; + VALUE defined_class; + rb_method_entry_t *me = search_method(klass, id, &defined_class); + return prepare_callable_method_entry(defined_class, id, me, FALSE); +} + +static const rb_callable_method_entry_t * +cached_callable_method_entry(VALUE klass, ID mid) +{ + ASSERT_vm_locking(); + + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + VALUE ccs_data; + + if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { + struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_data; + VM_ASSERT(vm_ccs_p(ccs)); + + if (LIKELY(!METHOD_ENTRY_INVALIDATED(ccs->cme))) { + VM_ASSERT(ccs->cme->called_id == mid); + RB_DEBUG_COUNTER_INC(ccs_found); + return ccs->cme; + } + else { + rb_vm_ccs_free(ccs); + rb_id_table_delete(cc_tbl, mid); + } } - nocache: - RB_DEBUG_COUNTER_INC(mc_global_miss); - return method_entry_get_without_cache(klass, id, defined_class_ptr); + RB_DEBUG_COUNTER_INC(ccs_not_found); + return NULL; } -MJIT_FUNC_EXPORTED const rb_method_entry_t * -rb_method_entry(VALUE klass, ID id) +static void +cache_callable_method_entry(VALUE klass, ID mid, const rb_callable_method_entry_t *cme) { - return method_entry_get(klass, id, NULL); + ASSERT_vm_locking(); + VM_ASSERT(cme != NULL); + + struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); + struct rb_class_cc_entries *ccs; + VALUE ccs_data; + + if (!cc_tbl) { + cc_tbl = RCLASS_CC_TBL(klass) = rb_id_table_create(2); + } + + if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { + ccs = (struct rb_class_cc_entries *)ccs_data; + VM_ASSERT(ccs->cme == cme); + } + else { + ccs = vm_ccs_create(klass, cme); + rb_id_table_insert(cc_tbl, mid, (VALUE)ccs); + } } static const rb_callable_method_entry_t * -prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_t *me) +negative_cme(ID mid) { - struct rb_id_table *mtbl; + rb_vm_t *vm = GET_VM(); const rb_callable_method_entry_t *cme; + VALUE cme_data; - if (me && me->defined_class == 0) { - RB_DEBUG_COUNTER_INC(mc_cme_complement); - VM_ASSERT(RB_TYPE_P(defined_class, T_ICLASS) || RB_TYPE_P(defined_class, T_MODULE)); - VM_ASSERT(me->defined_class == 0); - - mtbl = RCLASS_CALLABLE_M_TBL(defined_class); - - if (mtbl && rb_id_table_lookup(mtbl, id, (VALUE *)&me)) { - RB_DEBUG_COUNTER_INC(mc_cme_complement_hit); - cme = (rb_callable_method_entry_t *)me; - VM_ASSERT(callable_method_entry_p(cme)); - } - else { - if (!mtbl) { - mtbl = RCLASS_EXT(defined_class)->callable_m_tbl = rb_id_table_create(0); - } - cme = rb_method_entry_complement_defined_class(me, me->called_id, defined_class); - rb_id_table_insert(mtbl, id, (VALUE)cme); - VM_ASSERT(callable_method_entry_p(cme)); - } + if (rb_id_table_lookup(vm->negative_cme_table, mid, &cme_data)) { + cme = (rb_callable_method_entry_t *)cme_data; } else { - cme = (const rb_callable_method_entry_t *)me; - VM_ASSERT(callable_method_entry_p(cme)); + cme = (rb_callable_method_entry_t *)rb_method_entry_alloc(mid, Qnil, Qnil, NULL); + rb_id_table_insert(vm->negative_cme_table, mid, (VALUE)cme); } + VM_ASSERT(cme != NULL); return cme; } +static const rb_callable_method_entry_t * +callable_method_entry(VALUE klass, ID mid, VALUE *defined_class_ptr) +{ + const rb_callable_method_entry_t *cme; + + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS)); + RB_VM_LOCK_ENTER(); + { + cme = cached_callable_method_entry(klass, mid); + + if (cme) { + if (defined_class_ptr != NULL) *defined_class_ptr = cme->defined_class; + } + else { + VALUE defined_class; + rb_method_entry_t *me = search_method(klass, mid, &defined_class); + if (defined_class_ptr) *defined_class_ptr = defined_class; + + if (me != NULL) { + cme = prepare_callable_method_entry(defined_class, mid, me, TRUE); + } + else { + cme = negative_cme(mid); + } + + cache_callable_method_entry(klass, mid, cme); + } + } + RB_VM_LOCK_LEAVE(); + + return !UNDEFINED_METHOD_ENTRY_P(cme) ? cme : NULL; +} + MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * -rb_callable_method_entry(VALUE klass, ID id) +rb_callable_method_entry(VALUE klass, ID mid) { - VALUE defined_class; - rb_method_entry_t *me = method_entry_get(klass, id, &defined_class); - return prepare_callable_method_entry(defined_class, id, me); + return callable_method_entry(klass, mid, NULL); } static const rb_method_entry_t *resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *defined_class_ptr); @@ -887,7 +1356,7 @@ static const rb_method_entry_t *resolve_refined_method(VALUE refinements, const static const rb_method_entry_t * method_entry_resolve_refinement(VALUE klass, ID id, int with_refinement, VALUE *defined_class_ptr) { - const rb_method_entry_t *me = method_entry_get(klass, id, defined_class_ptr); + const rb_method_entry_t *me = search_method_protect(klass, id, defined_class_ptr); if (me) { if (me->def->type == VM_METHOD_TYPE_REFINED) { @@ -907,18 +1376,43 @@ method_entry_resolve_refinement(VALUE klass, ID id, int with_refinement, VALUE * return me; } -const rb_method_entry_t * +MJIT_FUNC_EXPORTED const rb_method_entry_t * rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { return method_entry_resolve_refinement(klass, id, TRUE, defined_class_ptr); } +static const rb_callable_method_entry_t * +callable_method_entry_refeinements0(VALUE klass, ID id, VALUE *defined_class_ptr, bool with_refinements, + const rb_callable_method_entry_t *cme) +{ + if (cme == NULL || LIKELY(cme->def->type != VM_METHOD_TYPE_REFINED)) { + return cme; + } + else { + VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; + const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, with_refinements, dcp); + return prepare_callable_method_entry(*dcp, id, me, TRUE); + } +} + +static const rb_callable_method_entry_t * +callable_method_entry_refinements(VALUE klass, ID id, VALUE *defined_class_ptr, bool with_refinements) +{ + const rb_callable_method_entry_t *cme = callable_method_entry(klass, id, defined_class_ptr); + return callable_method_entry_refeinements0(klass, id, defined_class_ptr, with_refinements, cme); +} + MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { - VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; - const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, TRUE, dcp); - return prepare_callable_method_entry(*dcp, id, me); + return callable_method_entry_refinements(klass, id, defined_class_ptr, true); +} + +static const rb_callable_method_entry_t * +callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) +{ + return callable_method_entry_refinements(klass, id, defined_class_ptr, false); } const rb_method_entry_t * @@ -932,7 +1426,7 @@ rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_ { VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, FALSE, dcp); - return prepare_callable_method_entry(*dcp, id, me); + return prepare_callable_method_entry(*dcp, id, me, TRUE); } static const rb_method_entry_t * @@ -945,7 +1439,7 @@ resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *de refinement = find_refinement(refinements, me->owner); if (!NIL_P(refinement)) { - tmp_me = method_entry_get(refinement, me->called_id, defined_class_ptr); + tmp_me = search_method_protect(refinement, me->called_id, defined_class_ptr); if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) { return tmp_me; @@ -963,7 +1457,7 @@ resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *de return 0; } - me = method_entry_get(super, me->called_id, defined_class_ptr); + me = search_method_protect(super, me->called_id, defined_class_ptr); } return me; } @@ -1010,10 +1504,13 @@ remove_method(VALUE klass, ID mid) klass, ID2SYM(mid)); } + if (klass != self) { + rb_clear_method_cache(self, mid); + } + rb_clear_method_cache(klass, mid); rb_id_table_delete(RCLASS_M_TBL(klass), mid); rb_vm_check_redefinition_opt_method(me, klass); - rb_clear_method_cache_by_class(klass); if (me->def->type == VM_METHOD_TYPE_REFINED) { rb_add_refined_method_entry(klass, mid); @@ -1068,7 +1565,8 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) VALUE defined_class; VALUE origin_class = RCLASS_ORIGIN(klass); - me = search_method(origin_class, name, &defined_class); + me = search_method0(origin_class, name, &defined_class, true); + if (!me && RB_TYPE_P(klass, T_MODULE)) { me = search_method(rb_cObject, name, &defined_class); } @@ -1082,12 +1580,17 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) rb_vm_check_redefinition_opt_method(me, klass); if (klass == defined_class || origin_class == defined_class) { - METHOD_ENTRY_VISI_SET(me, visi); - - if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) { - METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi); - } - rb_clear_method_cache_by_class(klass); + if (me->def->type == VM_METHOD_TYPE_REFINED) { + // Refinement method entries should always be public because the refinement + // search is always performed. + if (me->def->body.refined.orig_me) { + METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi); + } + } + else { + METHOD_ENTRY_VISI_SET(me, visi); + } + rb_clear_method_cache(klass, name); } else { rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, visi); @@ -1098,26 +1601,33 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) #define BOUND_PRIVATE 0x01 #define BOUND_RESPONDS 0x02 -int -rb_method_boundp(VALUE klass, ID id, int ex) +static int +method_boundp(VALUE klass, ID id, int ex) { - const rb_method_entry_t *me; + const rb_callable_method_entry_t *cme; + + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS)); if (ex & BOUND_RESPONDS) { - me = method_entry_resolve_refinement(klass, id, TRUE, NULL); + cme = rb_callable_method_entry_with_refinements(klass, id, NULL); } else { - me = rb_method_entry_without_refinements(klass, id, NULL); + cme = callable_method_entry_without_refinements(klass, id, NULL); } - if (me != 0) { - if ((ex & ~BOUND_RESPONDS) && - ((METHOD_ENTRY_VISI(me) == METHOD_VISI_PRIVATE) || - ((ex & BOUND_RESPONDS) && (METHOD_ENTRY_VISI(me) == METHOD_VISI_PROTECTED)))) { - return 0; + if (cme != NULL) { + if (ex & ~BOUND_RESPONDS) { + switch (METHOD_ENTRY_VISI(cme)) { + case METHOD_VISI_PRIVATE: + return 0; + case METHOD_VISI_PROTECTED: + if (ex & BOUND_RESPONDS) return 0; + default: + break; + } } - if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { + if (cme->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { if (ex & BOUND_RESPONDS) return 2; return 0; } @@ -1126,6 +1636,13 @@ rb_method_boundp(VALUE klass, ID id, int ex) return 0; } +// deprecated +int +rb_method_boundp(VALUE klass, ID id, int ex) +{ + return method_boundp(klass, id, ex); +} + static void vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func) { @@ -1144,7 +1661,7 @@ static void scope_visibility_check(void) { /* Check for public/protected/private/module_function called inside a method */ - rb_control_frame_t *cfp = rb_current_execution_context()->cfp+1; + rb_control_frame_t *cfp = GET_EC()->cfp+1; if (cfp && cfp->iseq && cfp->iseq->body->type == ISEQ_TYPE_METHOD) { rb_warn("calling %s without arguments inside a method may not have the intended effect", rb_id2name(rb_frame_this_func())); @@ -1355,13 +1872,13 @@ static VALUE rb_mod_method_defined(int argc, VALUE *argv, VALUE mod) { rb_method_visibility_t visi = check_definition_visibility(mod, argc, argv); - return (visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED) ? Qtrue : Qfalse; + return RBOOL(visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED); } static VALUE check_definition(VALUE mod, int argc, VALUE *argv, rb_method_visibility_t visi) { - return (check_definition_visibility(mod, argc, argv) == visi) ? Qtrue : Qfalse; + return RBOOL(check_definition_visibility(mod, argc, argv) == visi); } /* @@ -1512,7 +2029,7 @@ rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_defini switch (d1->type) { case VM_METHOD_TYPE_ISEQ: - return d1->body.iseq.iseqptr == d2->body.iseq.iseqptr; + return d1->body.iseq.iseqptr == d2->body.iseq.iseqptr; case VM_METHOD_TYPE_CFUNC: return d1->body.cfunc.func == d2->body.cfunc.func && @@ -1529,7 +2046,8 @@ rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_defini case VM_METHOD_TYPE_UNDEF: return 1; case VM_METHOD_TYPE_OPTIMIZED: - return d1->body.optimize_type == d2->body.optimize_type; + return (d1->body.optimized.type == d2->body.optimized.type) && + (d1->body.optimized.index == d2->body.optimized.index); case VM_METHOD_TYPE_REFINED: case VM_METHOD_TYPE_ALIAS: break; @@ -1563,13 +2081,14 @@ rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def) case VM_METHOD_TYPE_UNDEF: return hash; case VM_METHOD_TYPE_OPTIMIZED: - return rb_hash_uint(hash, def->body.optimize_type); + hash = rb_hash_uint(hash, def->body.optimized.index); + return rb_hash_uint(hash, def->body.optimized.type); case VM_METHOD_TYPE_REFINED: case VM_METHOD_TYPE_ALIAS: break; /* unreachable */ - } - rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type); } + rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type); +} st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me) @@ -1593,6 +2112,7 @@ rb_alias(VALUE klass, ID alias_name, ID original_name) again: orig_me = search_method(klass, original_name, &defined_class); + if (orig_me && orig_me->def->type == VM_METHOD_TYPE_REFINED) { orig_me = rb_resolve_refined_method(Qnil, orig_me); } @@ -1606,11 +2126,17 @@ rb_alias(VALUE klass, ID alias_name, ID original_name) } } - if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) { + switch (orig_me->def->type) { + case VM_METHOD_TYPE_ZSUPER: klass = RCLASS_SUPER(klass); original_name = orig_me->def->original_id; visi = METHOD_ENTRY_VISI(orig_me); goto again; + case VM_METHOD_TYPE_ALIAS: + orig_me = orig_me->def->body.alias.original_me; + VM_ASSERT(orig_me->def->type != VM_METHOD_TYPE_ALIAS); + break; + default: break; } if (visi == METHOD_VISI_UNDEF) visi = METHOD_ENTRY_VISI(orig_me); @@ -1626,19 +2152,19 @@ rb_alias(VALUE klass, ID alias_name, ID original_name) alias_me = method_entry_set(target_klass, alias_name, orig_me, visi, orig_me->owner); RB_OBJ_WRITE(alias_me, &alias_me->owner, target_klass); - RB_OBJ_WRITE(alias_me, &alias_me->defined_class, defined_class); + RB_OBJ_WRITE(alias_me, &alias_me->defined_class, orig_me->defined_class); } } /* * call-seq: - * alias_method(new_name, old_name) -> self + * alias_method(new_name, old_name) -> symbol * * Makes new_name a new copy of the method old_name. This can * be used to retain access to methods that are overridden. * * module Mod - * alias_method :orig_exit, :exit + * alias_method :orig_exit, :exit #=> :orig_exit * def exit(code=0) * puts "Exiting with code #{code}" * orig_exit(code) @@ -1659,8 +2185,19 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) if (!oldid) { rb_print_undef_str(mod, oldname); } - rb_alias(mod, rb_to_id(newname), oldid); - return mod; + VALUE id = rb_to_id(newname); + rb_alias(mod, id, oldid); + return ID2SYM(id); +} + +static void +check_and_export_method(VALUE self, VALUE name, rb_method_visibility_t visi) +{ + ID id = rb_check_id(&name); + if (!id) { + rb_print_undef_str(self, name); + } + rb_export_method(self, id, visi); } static void @@ -1675,13 +2212,20 @@ set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibil return; } - for (i = 0; i < argc; i++) { - VALUE v = argv[i]; - ID id = rb_check_id(&v); - if (!id) { - rb_print_undef_str(self, v); + + VALUE v; + + if (argc == 1 && (v = rb_check_array_type(argv[0])) != Qnil) { + long j; + + for (j = 0; j < RARRAY_LEN(v); j++) { + check_and_export_method(self, RARRAY_AREF(v, j), visi); } - rb_export_method(self, id, visi); + } + else { + for (i = 0; i < argc; i++) { + check_and_export_method(self, argv[i], visi); + } } } @@ -1691,23 +2235,31 @@ set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_visibility_t if (argc == 0) { scope_visibility_check(); rb_scope_visibility_set(visi); + return Qnil; } - else { - set_method_visibility(module, argc, argv, visi); + + set_method_visibility(module, argc, argv, visi); + if (argc == 1) { + return argv[0]; } - return module; + return rb_ary_new_from_values(argc, argv); } /* * call-seq: - * public -> self - * public(symbol, ...) -> self - * public(string, ...) -> self + * public -> nil + * public(method_name) -> method_name + * public(method_name, method_name, ...) -> array + * public(array) -> array * * With no arguments, sets the default visibility for subsequently * defined methods to public. With arguments, sets the named methods to * have public visibility. * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. + * If a single argument is passed, it is returned. + * If no argument is passed, nil is returned. + * If multiple arguments are passed, the arguments are returned as an array. */ static VALUE @@ -1718,14 +2270,19 @@ rb_mod_public(int argc, VALUE *argv, VALUE module) /* * call-seq: - * protected -> self - * protected(symbol, ...) -> self - * protected(string, ...) -> self + * protected -> nil + * protected(method_name) -> method_name + * protected(method_name, method_name, ...) -> array + * protected(array) -> array * * With no arguments, sets the default visibility for subsequently * defined methods to protected. With arguments, sets the named methods * to have protected visibility. * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. + * If a single argument is passed, it is returned. + * If no argument is passed, nil is returned. + * If multiple arguments are passed, the arguments are returned as an array. * * If a method has protected visibility, it is callable only where * self of the context is the same as the method. @@ -1745,14 +2302,19 @@ rb_mod_protected(int argc, VALUE *argv, VALUE module) /* * call-seq: - * private -> self - * private(symbol, ...) -> self - * private(string, ...) -> self + * private -> nil + * private(method_name) -> method_name + * private(method_name, method_name, ...) -> array + * private(array) -> array * * With no arguments, sets the default visibility for subsequently * defined methods to private. With arguments, sets the named methods * to have private visibility. * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. + * If a single argument is passed, it is returned. + * If no argument is passed, nil is returned. + * If multiple arguments are passed, the arguments are returned as an array. * * module Mod * def a() end @@ -1774,7 +2336,7 @@ rb_mod_private(int argc, VALUE *argv, VALUE module) /* * call-seq: - * ruby2_keywords(method_name, ...) -> self + * ruby2_keywords(method_name, ...) -> nil * * For the given method names, marks the method as passing keywords through * a normal argument splat. This should only be called on methods that @@ -1788,14 +2350,13 @@ rb_mod_private(int argc, VALUE *argv, VALUE module) * methods. * * This should only be used for methods that delegate keywords to another - * method, and only for backwards compatibility with Ruby versions before - * 2.7. + * method, and only for backwards compatibility with Ruby versions before 3.0. + * See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/ + * for details on why +ruby2_keywords+ exists and when and how to use it. * * This method will probably be removed at some point, as it exists only - * for backwards compatibility. As it does not exist in Ruby versions - * before 2.7, check that the module responds to this method before calling - * it. Also, be aware that if this method is removed, the behavior of the - * method will change so that it does not pass through keywords. + * for backwards compatibility. As it does not exist in Ruby versions before + * 2.7, check that the module responds to this method before calling it: * * module Mod * def foo(meth, *args, &block) @@ -1803,6 +2364,10 @@ rb_mod_private(int argc, VALUE *argv, VALUE module) * end * ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true) * end + * + * However, be aware that if the +ruby2_keywords+ method is removed, the + * behavior of the +foo+ method using the above approach will change so that + * the method does not pass through keywords. */ static VALUE @@ -1811,6 +2376,7 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) int i; VALUE origin_class = RCLASS_ORIGIN(module); + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); rb_check_frozen(module); for (i = 0; i < argc; i++) { @@ -1840,7 +2406,7 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) !me->def->body.iseq.iseqptr->body->param.flags.has_kw && !me->def->body.iseq.iseqptr->body->param.flags.has_kwrest) { me->def->body.iseq.iseqptr->body->param.flags.ruby2_keywords = 1; - rb_clear_method_cache_by_class(module); + rb_clear_method_cache(module, name); } else { rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name)); @@ -1859,12 +2425,12 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) !iseq->body->param.flags.has_kw && !iseq->body->param.flags.has_kwrest) { iseq->body->param.flags.ruby2_keywords = 1; - rb_clear_method_cache_by_class(module); + rb_clear_method_cache(module, name); } else { rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name)); } - return Qnil; + break; } } /* fallthrough */ @@ -1884,10 +2450,12 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) * call-seq: * mod.public_class_method(symbol, ...) -> mod * mod.public_class_method(string, ...) -> mod + * mod.public_class_method(array) -> mod * * Makes a list of existing class methods public. * * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. */ static VALUE @@ -1901,11 +2469,13 @@ rb_mod_public_method(int argc, VALUE *argv, VALUE obj) * call-seq: * mod.private_class_method(symbol, ...) -> mod * mod.private_class_method(string, ...) -> mod + * mod.private_class_method(array) -> mod * * Makes existing class methods private. Often used to hide the default * constructor new. * * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. * * class SimpleSingleton # Not thread safe * private_class_method :new @@ -1928,12 +2498,14 @@ rb_mod_private_method(int argc, VALUE *argv, VALUE obj) * public * public(symbol, ...) * public(string, ...) + * public(array) * * With no arguments, sets the default visibility for subsequently * defined methods to public. With arguments, sets the named methods to * have public visibility. * * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. */ static VALUE @@ -1947,12 +2519,14 @@ top_public(int argc, VALUE *argv, VALUE _) * private * private(symbol, ...) * private(string, ...) + * private(array) * * With no arguments, sets the default visibility for subsequently * defined methods to private. With arguments, sets the named methods to * have private visibility. * * String arguments are converted to symbols. + * An Array of Symbols and/or Strings is also accepted. */ static VALUE top_private(int argc, VALUE *argv, VALUE _) @@ -1975,8 +2549,9 @@ top_ruby2_keywords(int argc, VALUE *argv, VALUE module) /* * call-seq: - * module_function(symbol, ...) -> self - * module_function(string, ...) -> self + * module_function -> nil + * module_function(method_name) -> method_name + * module_function(method_name, method_name, ...) -> array * * Creates module functions for the named methods. These functions may * be called with the module as a receiver, and also become available @@ -1986,6 +2561,9 @@ top_ruby2_keywords(int argc, VALUE *argv, VALUE module) * used with no arguments, subsequently defined methods become module * functions. * String arguments are converted to symbols. + * If a single argument is passed, it is returned. + * If no argument is passed, nil is returned. + * If multiple arguments are passed, the arguments are returned as an array. * * module Mod * def one @@ -2024,7 +2602,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) if (argc == 0) { rb_scope_module_func_set(); - return module; + return Qnil; } set_method_visibility(module, argc, argv, METHOD_VISI_PRIVATE); @@ -2050,18 +2628,10 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) } rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC); } - return module; -} - -bool -rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid) -{ - if (cd->ci.mid != mid) { - *cd = (struct rb_call_data) /* reset */ { .ci = { .mid = mid, }, }; + if (argc == 1) { + return argv[0]; } - - vm_search_method_fastpath(cd, klass); - return cd->cc.me && METHOD_ENTRY_BASIC(cd->cc.me); + return rb_ary_new_from_values(argc, argv); } #ifdef __GNUC__ @@ -2071,10 +2641,10 @@ rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mi int rb_method_basic_definition_p(VALUE klass, ID id) { - const rb_method_entry_t *me; + const rb_callable_method_entry_t *cme; if (!klass) return TRUE; /* hidden object cannot be overridden */ - me = rb_method_entry(klass, id); - return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE; + cme = rb_callable_method_entry(klass, id); + return (cme && METHOD_ENTRY_BASIC(cme)) ? TRUE : FALSE; } #ifdef __GNUC__ #pragma pop_macro("rb_method_basic_definition_p") @@ -2082,10 +2652,8 @@ rb_method_basic_definition_p(VALUE klass, ID id) static VALUE call_method_entry(rb_execution_context_t *ec, VALUE defined_class, VALUE obj, ID id, - const rb_method_entry_t *me, int argc, const VALUE *argv, int kw_splat) + const rb_callable_method_entry_t *cme, int argc, const VALUE *argv, int kw_splat) { - const rb_callable_method_entry_t *cme = - prepare_callable_method_entry(defined_class, id, me); VALUE passed_block_handler = vm_passed_block_handler(ec); VALUE result = rb_vm_call_kw(ec, obj, id, argc, argv, cme, kw_splat); vm_passed_block_handler_set(ec, passed_block_handler); @@ -2098,13 +2666,12 @@ basic_obj_respond_to_missing(rb_execution_context_t *ec, VALUE klass, VALUE obj, { VALUE defined_class, args[2]; const ID rtmid = idRespond_to_missing; - const rb_method_entry_t *const me = - method_entry_get(klass, rtmid, &defined_class); + const rb_callable_method_entry_t *const cme = callable_method_entry(klass, rtmid, &defined_class); - if (!me || METHOD_ENTRY_BASIC(me)) return Qundef; + if (!cme || METHOD_ENTRY_BASIC(cme)) return Qundef; args[0] = mid; args[1] = priv; - return call_method_entry(ec, defined_class, obj, rtmid, me, 2, args, RB_NO_KEYWORDS); + return call_method_entry(ec, defined_class, obj, rtmid, cme, 2, args, RB_NO_KEYWORDS); } static inline int @@ -2113,7 +2680,7 @@ basic_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int pub) VALUE klass = CLASS_OF(obj); VALUE ret; - switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) { + switch (method_boundp(klass, id, pub|BOUND_RESPONDS)) { case 2: return FALSE; case 0: @@ -2130,11 +2697,10 @@ vm_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int pri { VALUE defined_class; const ID resid = idRespond_to; - const rb_method_entry_t *const me = - method_entry_get(klass, resid, &defined_class); + const rb_callable_method_entry_t *const cme = callable_method_entry(klass, resid, &defined_class); - if (!me) return -1; - if (METHOD_ENTRY_BASIC(me)) { + if (!cme) return -1; + if (METHOD_ENTRY_BASIC(cme)) { return -1; } else { @@ -2145,7 +2711,7 @@ vm_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int pri args[0] = ID2SYM(id); args[1] = Qtrue; if (priv) { - argc = rb_method_entry_arity(me); + argc = rb_method_entry_arity((const rb_method_entry_t *)cme); if (argc > 2) { rb_raise(rb_eArgError, "respond_to? must accept 1 or 2 arguments (requires %d)", @@ -2155,8 +2721,9 @@ vm_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int pri argc = 2; } else if (!NIL_P(ruby_verbose)) { - VALUE location = rb_method_entry_location(me); - rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") uses" + VALUE location = rb_method_entry_location((const rb_method_entry_t *)cme); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, + "%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") uses" " the deprecated method signature, which takes one parameter", (FL_TEST(klass, FL_SINGLETON) ? obj : klass), (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'), @@ -2165,13 +2732,14 @@ vm_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int pri VALUE path = RARRAY_AREF(location, 0); VALUE line = RARRAY_AREF(location, 1); if (!NIL_P(path)) { - rb_compile_warn(RSTRING_PTR(path), NUM2INT(line), + rb_category_compile_warn(RB_WARN_CATEGORY_DEPRECATED, + RSTRING_PTR(path), NUM2INT(line), "respond_to? is defined here"); } } } } - result = call_method_entry(ec, defined_class, obj, resid, me, argc, args, RB_NO_KEYWORDS); + result = call_method_entry(ec, defined_class, obj, resid, cme, argc, args, RB_NO_KEYWORDS); return RTEST(result); } } @@ -2180,6 +2748,12 @@ int rb_obj_respond_to(VALUE obj, ID id, int priv) { rb_execution_context_t *ec = GET_EC(); + return rb_ec_obj_respond_to(ec, obj, id, priv); +} + +int +rb_ec_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int priv) +{ VALUE klass = CLASS_OF(obj); int ret = vm_respond_to(ec, klass, obj, id, priv); if (ret == -1) ret = basic_obj_respond_to(ec, obj, id, !priv); @@ -2227,9 +2801,7 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) if (ret == Qundef) ret = Qfalse; return ret; } - if (basic_obj_respond_to(ec, obj, id, !RTEST(priv))) - return Qtrue; - return Qfalse; + return RBOOL(basic_obj_respond_to(ec, obj, id, !RTEST(priv))); } /* @@ -2256,33 +2828,12 @@ obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv) void Init_Method(void) { - if (!OPT_GLOBAL_METHOD_CACHE) return; - char *ptr = getenv("RUBY_GLOBAL_METHOD_CACHE_SIZE"); - int val; - - if (ptr != NULL && (val = atoi(ptr)) > 0) { - if ((val & (val - 1)) == 0) { /* ensure val is a power of 2 */ - global_method_cache.size = val; - global_method_cache.mask = val - 1; - } - else { - fprintf(stderr, "RUBY_GLOBAL_METHOD_CACHE_SIZE was set to %d but ignored because the value is not a power of 2.\n", val); - } - } - - global_method_cache.entries = (struct cache_entry *)calloc(global_method_cache.size, sizeof(struct cache_entry)); - if (global_method_cache.entries == NULL) { - fprintf(stderr, "[FATAL] failed to allocate memory\n"); - exit(EXIT_FAILURE); - } + // } void Init_eval_method(void) { -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2); diff --git a/ruby/vm_opts.h b/ruby/vm_opts.h index 3df9ce837..b0ca81f30 100644 --- a/ruby/vm_opts.h +++ b/ruby/vm_opts.h @@ -1,4 +1,5 @@ -/*-*-c-*-*/ +#ifndef RUBY_VM_OPTS_H/*-*-c-*-*/ +#define RUBY_VM_OPTS_H /********************************************************************** vm_opts.h - VM optimize option @@ -9,10 +10,6 @@ **********************************************************************/ - -#ifndef RUBY_VM_OPTS_H -#define RUBY_VM_OPTS_H - /* Compile options. * You can change these options at runtime by VM::CompileOption. * Following definitions are default values. @@ -65,6 +62,10 @@ #define OPT_SUPPORT_JOKE 0 #endif +#ifndef OPT_SUPPORT_CALL_C_FUNCTION +#define OPT_SUPPORT_CALL_C_FUNCTION 0 +#endif + #ifndef VM_COLLECT_USAGE_DETAILS #define VM_COLLECT_USAGE_DETAILS 0 #endif diff --git a/ruby/vm_sync.c b/ruby/vm_sync.c new file mode 100644 index 000000000..038e87f53 --- /dev/null +++ b/ruby/vm_sync.c @@ -0,0 +1,299 @@ +#include "vm_core.h" +#include "vm_sync.h" +#include "ractor_core.h" +#include "vm_debug.h" +#include "gc.h" + +static bool vm_barrier_finish_p(rb_vm_t *vm); + +static bool +vm_locked(rb_vm_t *vm) +{ + return vm->ractor.sync.lock_owner == GET_RACTOR(); +} + +#if RUBY_DEBUG > 0 +void +RUBY_ASSERT_vm_locking(void) +{ + if (rb_multi_ractor_p()) { + rb_vm_t *vm = GET_VM(); + VM_ASSERT(vm_locked(vm)); + } +} + +void +RUBY_ASSERT_vm_unlocking(void) +{ + if (rb_multi_ractor_p()) { + rb_vm_t *vm = GET_VM(); + VM_ASSERT(!vm_locked(vm)); + } +} +#endif + +bool +rb_vm_locked_p(void) +{ + return vm_locked(GET_VM()); +} + +static void +vm_lock_enter(rb_ractor_t *cr, rb_vm_t *vm, bool locked, bool no_barrier, unsigned int *lev APPEND_LOCATION_ARGS) +{ + RUBY_DEBUG_LOG2(file, line, "start locked:%d", locked); + + if (locked) { + ASSERT_vm_locking(); + } + else { +#if RACTOR_CHECK_MODE + // locking ractor and acquire VM lock will cause deadlock + VM_ASSERT(cr->sync.locked_by != rb_ractor_self(cr)); +#endif + + // lock + rb_native_mutex_lock(&vm->ractor.sync.lock); + VM_ASSERT(vm->ractor.sync.lock_owner == NULL); + vm->ractor.sync.lock_owner = cr; + + if (!no_barrier) { + // barrier + while (vm->ractor.sync.barrier_waiting) { + unsigned int barrier_cnt = vm->ractor.sync.barrier_cnt; + rb_thread_t *th = GET_THREAD(); + bool running; + + RB_GC_SAVE_MACHINE_CONTEXT(th); + + if (rb_ractor_status_p(cr, ractor_running)) { + rb_vm_ractor_blocking_cnt_inc(vm, cr, __FILE__, __LINE__); + running = true; + } + else { + running = false; + } + VM_ASSERT(rb_ractor_status_p(cr, ractor_blocking)); + + if (vm_barrier_finish_p(vm)) { + RUBY_DEBUG_LOG("wakeup barrier owner"); + rb_native_cond_signal(&vm->ractor.sync.barrier_cond); + } + else { + RUBY_DEBUG_LOG("wait for barrier finish"); + } + + // wait for restart + while (barrier_cnt == vm->ractor.sync.barrier_cnt) { + vm->ractor.sync.lock_owner = NULL; + rb_native_cond_wait(&cr->barrier_wait_cond, &vm->ractor.sync.lock); + VM_ASSERT(vm->ractor.sync.lock_owner == NULL); + vm->ractor.sync.lock_owner = cr; + } + + RUBY_DEBUG_LOG("barrier is released. Acquire vm_lock"); + + if (running) { + rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__); + } + } + } + + VM_ASSERT(vm->ractor.sync.lock_rec == 0); + VM_ASSERT(vm->ractor.sync.lock_owner == cr); + } + + vm->ractor.sync.lock_rec++; + *lev = vm->ractor.sync.lock_rec; + + RUBY_DEBUG_LOG2(file, line, "rec:%u owner:%d", vm->ractor.sync.lock_rec, rb_ractor_id(vm->ractor.sync.lock_owner)); +} + +static void +vm_lock_leave(rb_vm_t *vm, unsigned int *lev APPEND_LOCATION_ARGS) +{ + RUBY_DEBUG_LOG2(file, line, "rec:%u owner:%d", vm->ractor.sync.lock_rec, rb_ractor_id(vm->ractor.sync.lock_owner)); + + ASSERT_vm_locking(); + VM_ASSERT(vm->ractor.sync.lock_rec > 0); + VM_ASSERT(vm->ractor.sync.lock_rec == *lev); + + vm->ractor.sync.lock_rec--; + *lev = vm->ractor.sync.lock_rec; + + if (vm->ractor.sync.lock_rec == 0) { + vm->ractor.sync.lock_owner = NULL; + rb_native_mutex_unlock(&vm->ractor.sync.lock); + } +} + +MJIT_FUNC_EXPORTED void +rb_vm_lock_enter_body(unsigned int *lev APPEND_LOCATION_ARGS) +{ + rb_vm_t *vm = GET_VM(); + if (vm_locked(vm)) { + vm_lock_enter(NULL, vm, true, false, lev APPEND_LOCATION_PARAMS); + } + else { + vm_lock_enter(GET_RACTOR(), vm, false, false, lev APPEND_LOCATION_PARAMS); + } +} + +MJIT_FUNC_EXPORTED void +rb_vm_lock_enter_body_nb(unsigned int *lev APPEND_LOCATION_ARGS) +{ + rb_vm_t *vm = GET_VM(); + if (vm_locked(vm)) { + vm_lock_enter(NULL, vm, true, true, lev APPEND_LOCATION_PARAMS); + } + else { + vm_lock_enter(GET_RACTOR(), vm, false, true, lev APPEND_LOCATION_PARAMS); + } +} + +MJIT_FUNC_EXPORTED void +rb_vm_lock_enter_body_cr(rb_ractor_t *cr, unsigned int *lev APPEND_LOCATION_ARGS) +{ + rb_vm_t *vm = GET_VM(); + vm_lock_enter(cr, vm, vm_locked(vm), false, lev APPEND_LOCATION_PARAMS); +} + +MJIT_FUNC_EXPORTED void +rb_vm_lock_leave_body(unsigned int *lev APPEND_LOCATION_ARGS) +{ + vm_lock_leave(GET_VM(), lev APPEND_LOCATION_PARAMS); +} + +void +rb_vm_lock_body(LOCATION_ARGS) +{ + rb_vm_t *vm = GET_VM(); + ASSERT_vm_unlocking(); + + vm_lock_enter(GET_RACTOR(), vm, false, false, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS); +} + +void +rb_vm_unlock_body(LOCATION_ARGS) +{ + rb_vm_t *vm = GET_VM(); + ASSERT_vm_locking(); + VM_ASSERT(vm->ractor.sync.lock_rec == 1); + vm_lock_leave(vm, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS); +} + +static void +vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec) +{ + ASSERT_vm_locking(); + unsigned int lock_rec = vm->ractor.sync.lock_rec; + rb_ractor_t *cr = vm->ractor.sync.lock_owner; + + vm->ractor.sync.lock_rec = 0; + vm->ractor.sync.lock_owner = NULL; + if (msec > 0) { + rb_native_cond_timedwait(cond, &vm->ractor.sync.lock, msec); + } + else { + rb_native_cond_wait(cond, &vm->ractor.sync.lock); + } + vm->ractor.sync.lock_rec = lock_rec; + vm->ractor.sync.lock_owner = cr; +} + +void +rb_vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond) +{ + vm_cond_wait(vm, cond, 0); +} + +void +rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec) +{ + vm_cond_wait(vm, cond, msec); +} + +static bool +vm_barrier_finish_p(rb_vm_t *vm) +{ + RUBY_DEBUG_LOG("cnt:%u living:%u blocking:%u", + vm->ractor.sync.barrier_cnt, + vm->ractor.cnt, + vm->ractor.blocking_cnt); + + VM_ASSERT(vm->ractor.blocking_cnt <= vm->ractor.cnt); + return vm->ractor.blocking_cnt == vm->ractor.cnt; +} + +void +rb_vm_barrier(void) +{ + RB_DEBUG_COUNTER_INC(vm_sync_barrier); + + if (!rb_multi_ractor_p()) { + // no other ractors + return; + } + else { + rb_vm_t *vm = GET_VM(); + VM_ASSERT(vm->ractor.sync.barrier_waiting == false); + ASSERT_vm_locking(); + + rb_ractor_t *cr = vm->ractor.sync.lock_owner; + VM_ASSERT(cr == GET_RACTOR()); + VM_ASSERT(rb_ractor_status_p(cr, ractor_running)); + + vm->ractor.sync.barrier_waiting = true; + + RUBY_DEBUG_LOG("barrier start. cnt:%u living:%u blocking:%u", + vm->ractor.sync.barrier_cnt, + vm->ractor.cnt, + vm->ractor.blocking_cnt); + + rb_vm_ractor_blocking_cnt_inc(vm, cr, __FILE__, __LINE__); + + // send signal + rb_ractor_t *r = 0; + list_for_each(&vm->ractor.set, r, vmlr_node) { + if (r != cr) { + rb_ractor_vm_barrier_interrupt_running_thread(r); + } + } + + // wait + while (!vm_barrier_finish_p(vm)) { + rb_vm_cond_wait(vm, &vm->ractor.sync.barrier_cond); + } + + RUBY_DEBUG_LOG("cnt:%u barrier success", vm->ractor.sync.barrier_cnt); + + rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__); + + vm->ractor.sync.barrier_waiting = false; + vm->ractor.sync.barrier_cnt++; + + list_for_each(&vm->ractor.set, r, vmlr_node) { + rb_native_cond_signal(&r->barrier_wait_cond); + } + } +} + +void +rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec, + unsigned int recorded_lock_rec, + unsigned int current_lock_rec) +{ + VM_ASSERT(recorded_lock_rec != current_lock_rec); + + if (UNLIKELY(recorded_lock_rec > current_lock_rec)) { + rb_bug("unexpected situation - recordd:%u current:%u", + recorded_lock_rec, current_lock_rec); + } + else { + while (recorded_lock_rec < current_lock_rec) { + RB_VM_LOCK_LEAVE_LEV(¤t_lock_rec); + } + } + + VM_ASSERT(recorded_lock_rec == rb_ec_vm_lock_rec(ec)); +} diff --git a/ruby/vm_sync.h b/ruby/vm_sync.h new file mode 100644 index 000000000..0969e5bfc --- /dev/null +++ b/ruby/vm_sync.h @@ -0,0 +1,137 @@ +#ifndef RUBY_VM_SYNC_H +#define RUBY_VM_SYNC_H + +#include "vm_debug.h" +#include "debug_counter.h" + +#if defined(USE_RUBY_DEBUG_LOG) && USE_RUBY_DEBUG_LOG +#define LOCATION_ARGS const char *file, int line +#define LOCATION_PARAMS file, line +#define APPEND_LOCATION_ARGS , const char *file, int line +#define APPEND_LOCATION_PARAMS , file, line +#else +#define LOCATION_ARGS void +#define LOCATION_PARAMS +#define APPEND_LOCATION_ARGS +#define APPEND_LOCATION_PARAMS +#endif + +bool rb_vm_locked_p(void); +void rb_vm_lock_body(LOCATION_ARGS); +void rb_vm_unlock_body(LOCATION_ARGS); + +struct rb_ractor_struct; +void rb_vm_lock_enter_body_cr(struct rb_ractor_struct *cr, unsigned int *lev APPEND_LOCATION_ARGS); +void rb_vm_lock_enter_body_nb(unsigned int *lev APPEND_LOCATION_ARGS); +void rb_vm_lock_enter_body(unsigned int *lev APPEND_LOCATION_ARGS); +void rb_vm_lock_leave_body(unsigned int *lev APPEND_LOCATION_ARGS); +void rb_vm_barrier(void); + +#if RUBY_DEBUG +// GET_VM() +#include "vm_core.h" +#endif + +RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; // ractor.c + +static inline bool +rb_multi_ractor_p(void) +{ + if (LIKELY(ruby_single_main_ractor)) { + // 0 on boot time. + RUBY_ASSERT(GET_VM()->ractor.cnt <= 1); + return false; + } + else { + // multi-ractor mode can run ractor.cnt == 1 + return true; + } +} + +static inline void +rb_vm_lock(const char *file, int line) +{ + RB_DEBUG_COUNTER_INC(vm_sync_lock); + + if (rb_multi_ractor_p()) { + rb_vm_lock_body(LOCATION_PARAMS); + } +} + +static inline void +rb_vm_unlock(const char *file, int line) +{ + if (rb_multi_ractor_p()) { + rb_vm_unlock_body(LOCATION_PARAMS); + } +} + +static inline void +rb_vm_lock_enter(unsigned int *lev, const char *file, int line) +{ + RB_DEBUG_COUNTER_INC(vm_sync_lock_enter); + + if (rb_multi_ractor_p()) { + rb_vm_lock_enter_body(lev APPEND_LOCATION_PARAMS); + } +} + +static inline void +rb_vm_lock_enter_nb(unsigned int *lev, const char *file, int line) +{ + RB_DEBUG_COUNTER_INC(vm_sync_lock_enter_nb); + + if (rb_multi_ractor_p()) { + rb_vm_lock_enter_body_nb(lev APPEND_LOCATION_PARAMS); + } +} + +static inline void +rb_vm_lock_leave(unsigned int *lev, const char *file, int line) +{ + if (rb_multi_ractor_p()) { + rb_vm_lock_leave_body(lev APPEND_LOCATION_PARAMS); + } +} + +static inline void +rb_vm_lock_enter_cr(struct rb_ractor_struct *cr, unsigned int *levp, const char *file, int line) +{ + RB_DEBUG_COUNTER_INC(vm_sync_lock_enter_cr); + rb_vm_lock_enter_body_cr(cr, levp APPEND_LOCATION_PARAMS); +} + +static inline void +rb_vm_lock_leave_cr(struct rb_ractor_struct *cr, unsigned int *levp, const char *file, int line) +{ + rb_vm_lock_leave_body(levp APPEND_LOCATION_PARAMS); +} + +#define RB_VM_LOCKED_P() rb_vm_locked_p() + +#define RB_VM_LOCK() rb_vm_lock(__FILE__, __LINE__) +#define RB_VM_UNLOCK() rb_vm_unlock(__FILE__, __LINE__) + +#define RB_VM_LOCK_ENTER_CR_LEV(cr, levp) rb_vm_lock_enter_cr(cr, levp, __FILE__, __LINE__) +#define RB_VM_LOCK_LEAVE_CR_LEV(cr, levp) rb_vm_lock_leave_cr(cr, levp, __FILE__, __LINE__) +#define RB_VM_LOCK_ENTER_LEV(levp) rb_vm_lock_enter(levp, __FILE__, __LINE__) +#define RB_VM_LOCK_LEAVE_LEV(levp) rb_vm_lock_leave(levp, __FILE__, __LINE__) + +#define RB_VM_LOCK_ENTER() { unsigned int _lev; RB_VM_LOCK_ENTER_LEV(&_lev); +#define RB_VM_LOCK_LEAVE() RB_VM_LOCK_LEAVE_LEV(&_lev); } + +#define RB_VM_LOCK_ENTER_LEV_NB(levp) rb_vm_lock_enter_nb(levp, __FILE__, __LINE__) +#define RB_VM_LOCK_ENTER_NO_BARRIER() { unsigned int _lev; RB_VM_LOCK_ENTER_LEV_NB(&_lev); +#define RB_VM_LOCK_LEAVE_NO_BARRIER() RB_VM_LOCK_LEAVE_LEV(&_lev); } + +#if RUBY_DEBUG > 0 +void RUBY_ASSERT_vm_locking(void); +void RUBY_ASSERT_vm_unlocking(void); +#define ASSERT_vm_locking() RUBY_ASSERT_vm_locking() +#define ASSERT_vm_unlocking() RUBY_ASSERT_vm_unlocking() +#else +#define ASSERT_vm_locking() +#define ASSERT_vm_unlocking() +#endif + +#endif // RUBY_VM_SYNC_H diff --git a/ruby/vm_trace.c b/ruby/vm_trace.c index 241b92967..466856341 100644 --- a/ruby/vm_trace.c +++ b/ruby/vm_trace.c @@ -21,13 +21,17 @@ * */ +#include "eval_intern.h" #include "internal.h" +#include "internal/hash.h" +#include "internal/symbol.h" +#include "iseq.h" +#include "mjit.h" #include "ruby/debug.h" - #include "vm_core.h" -#include "mjit.h" -#include "iseq.h" -#include "eval_intern.h" +#include "ruby/ractor.h" +#include "yjit.h" + #include "builtin.h" /* (1) trace mechanisms */ @@ -65,30 +69,52 @@ static void clean_hooks(const rb_execution_context_t *ec, rb_hook_list_t *list); void rb_hook_list_free(rb_hook_list_t *hooks) { - clean_hooks(GET_EC(), hooks); + hooks->need_clean = true; + + if (hooks->running == 0) { + clean_hooks(GET_EC(), hooks); + } } /* ruby_vm_event_flags management */ +void rb_clear_attr_ccs(void); + static void -update_global_event_hook(rb_event_flag_t vm_events) +update_global_event_hook(rb_event_flag_t prev_events, rb_event_flag_t new_events) { - rb_event_flag_t new_iseq_events = vm_events & ISEQ_TRACE_EVENTS; + rb_event_flag_t new_iseq_events = new_events & ISEQ_TRACE_EVENTS; rb_event_flag_t enabled_iseq_events = ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS; if (new_iseq_events & ~enabled_iseq_events) { - /* Stop calling all JIT-ed code. Compiling trace insns is not supported for now. */ -#if USE_MJIT - mjit_call_p = FALSE; -#endif + // :class events are triggered only in ISEQ_TYPE_CLASS, but mjit_target_iseq_p ignores such iseqs. + // Thus we don't need to cancel JIT-ed code for :class events. + if (new_iseq_events != RUBY_EVENT_CLASS) { + // Stop calling all JIT-ed code. We can't rewrite existing JIT-ed code to trace_ insns for now. + mjit_cancel_all("TracePoint is enabled"); + } - /* write all ISeqs iff new events are added */ + /* write all ISeqs if and only if new events are added */ rb_iseq_trace_set_all(new_iseq_events | enabled_iseq_events); } + else { + // if c_call or c_return is activated: + if (((prev_events & RUBY_EVENT_C_CALL) == 0 && (new_events & RUBY_EVENT_C_CALL)) || + ((prev_events & RUBY_EVENT_C_RETURN) == 0 && (new_events & RUBY_EVENT_C_RETURN))) { + rb_clear_attr_ccs(); + } + } - ruby_vm_event_flags = vm_events; - ruby_vm_event_enabled_global_flags |= vm_events; - rb_objspace_set_event_hook(vm_events); + ruby_vm_event_flags = new_events; + ruby_vm_event_enabled_global_flags |= new_events; + rb_objspace_set_event_hook(new_events); + + if (new_events & RUBY_EVENT_TRACEPOINT_ALL) { + // Invalidate all code if listening for any TracePoint event. + // Internal events fire inside C routines so don't need special handling. + // Do this last so other ractors see updated vm events when they wake up. + rb_yjit_tracing_invalidate_all(); + } } /* add/remove hooks */ @@ -118,13 +144,14 @@ alloc_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, static void hook_list_connect(VALUE list_owner, rb_hook_list_t *list, rb_event_hook_t *hook, int global_p) { + rb_event_flag_t prev_events = list->events; hook->next = list->hooks; list->hooks = hook; list->events |= hook->events; if (global_p) { /* global hooks are root objects at GC mark. */ - update_global_event_hook(list->events); + update_global_event_hook(prev_events, list->events); } else { RB_OBJ_WRITTEN(list_owner, Qundef, hook->data); @@ -134,7 +161,7 @@ hook_list_connect(VALUE list_owner, rb_hook_list_t *list, rb_event_hook_t *hook, static void connect_event_hook(const rb_execution_context_t *ec, rb_event_hook_t *hook) { - rb_hook_list_t *list = rb_vm_global_hooks(ec); + rb_hook_list_t *list = rb_ec_ractor_hooks(ec); hook_list_connect(Qundef, list, hook, TRUE); } @@ -156,8 +183,7 @@ rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) { - rb_event_hook_t *hook = alloc_event_hook(func, events, data, RUBY_EVENT_HOOK_FLAG_SAFE); - connect_event_hook(GET_EC(), hook); + rb_add_event_hook2(func, events, data, RUBY_EVENT_HOOK_FLAG_SAFE); } void @@ -177,10 +203,13 @@ static void clean_hooks(const rb_execution_context_t *ec, rb_hook_list_t *list) { rb_event_hook_t *hook, **nextp = &list->hooks; - VM_ASSERT(list->need_clean == TRUE); + rb_event_flag_t prev_events = list->events; + + VM_ASSERT(list->running == 0); + VM_ASSERT(list->need_clean == true); list->events = 0; - list->need_clean = FALSE; + list->need_clean = false; while ((hook = *nextp) != 0) { if (hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) { @@ -193,19 +222,21 @@ clean_hooks(const rb_execution_context_t *ec, rb_hook_list_t *list) } } - if (list == rb_vm_global_hooks(ec)) { - /* global events */ - update_global_event_hook(list->events); + if (list->is_local) { + if (list->events == 0) { + /* local events */ + ruby_xfree(list); + } } else { - /* local events */ + update_global_event_hook(prev_events, list->events); } } static void clean_hooks_check(const rb_execution_context_t *ec, rb_hook_list_t *list) { - if (UNLIKELY(list->need_clean != FALSE)) { + if (UNLIKELY(list->need_clean)) { if (list->running == 0) { clean_hooks(ec, list); } @@ -218,8 +249,7 @@ clean_hooks_check(const rb_execution_context_t *ec, rb_hook_list_t *list) static int remove_event_hook(const rb_execution_context_t *ec, const rb_thread_t *filter_th, rb_event_hook_func_t func, VALUE data) { - rb_vm_t *vm = rb_ec_vm_ptr(ec); - rb_hook_list_t *list = &vm->global_hooks; + rb_hook_list_t *list = rb_ec_ractor_hooks(ec); int ret = 0; rb_event_hook_t *hook = list->hooks; @@ -229,7 +259,7 @@ remove_event_hook(const rb_execution_context_t *ec, const rb_thread_t *filter_th if (data == Qundef || hook->data == data) { hook->hook_flags |= RUBY_EVENT_HOOK_FLAG_DELETED; ret+=1; - list->need_clean = TRUE; + list->need_clean = true; } } } @@ -372,7 +402,7 @@ rb_exec_event_hooks(rb_trace_arg_t *trace_arg, rb_hook_list_t *hooks, int pop_p) ec->trace_arg = trace_arg; /* only global hooks */ - exec_hooks_unprotected(ec, rb_vm_global_hooks(ec), trace_arg); + exec_hooks_unprotected(ec, rb_ec_ractor_hooks(ec), trace_arg); ec->trace_arg = prev_trace_arg; } } @@ -516,6 +546,10 @@ static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALU * line prog.rb:3 test Test * line prog.rb:4 test Test * return prog.rb:4 test Test + * + * Note that for +c-call+ and +c-return+ events, the binding returned is the + * binding of the nearest Ruby method calling the C method, since C methods + * themselves do not have bindings. */ static VALUE @@ -706,6 +740,7 @@ typedef struct rb_tp_struct { void (*func)(VALUE tpval, void *data); void *data; VALUE proc; + rb_ractor_t *ractor; VALUE self; } rb_tp_t; @@ -726,7 +761,7 @@ tp_memsize(const void *ptr) static const rb_data_type_t tp_data_type = { "tracepoint", - {tp_mark, RUBY_TYPED_NEVER_FREE, tp_memsize,}, + {tp_mark, RUBY_TYPED_DEFAULT_FREE, tp_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -851,7 +886,7 @@ fill_id_and_klass(rb_trace_arg_t *trace_arg) VALUE rb_tracearg_parameters(rb_trace_arg_t *trace_arg) { - switch(trace_arg->event) { + switch (trace_arg->event) { case RUBY_EVENT_CALL: case RUBY_EVENT_RETURN: case RUBY_EVENT_B_CALL: @@ -1111,7 +1146,9 @@ tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg) (*tp->func)(tpval, tp->data); } else { - rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil); + if (tp->ractor == NULL || tp->ractor == GET_RACTOR()) { + rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil); + } } } @@ -1156,8 +1193,9 @@ rb_tracepoint_enable_for_target(VALUE tpval, VALUE target, VALUE target_line) { rb_tp_t *tp = tpptr(tpval); const rb_iseq_t *iseq = iseq_of(target); - int n; + int n = 0; unsigned int line = 0; + bool target_bmethod = false; if (tp->tracing > 0) { rb_raise(rb_eArgError, "can't nest-enable a targeting TracePoint"); @@ -1175,10 +1213,6 @@ rb_tracepoint_enable_for_target(VALUE tpval, VALUE target, VALUE target_line) VM_ASSERT(tp->local_target_set == Qfalse); tp->local_target_set = rb_obj_hide(rb_ident_hash_new()); - /* iseq */ - n = rb_iseq_add_local_tracepoint_recursively(iseq, tp->events, tpval, line); - rb_hash_aset(tp->local_target_set, (VALUE)iseq, Qtrue); - /* bmethod */ if (rb_obj_is_method(target)) { rb_method_definition_t *def = (rb_method_definition_t *)rb_method_def(target); @@ -1187,15 +1221,23 @@ rb_tracepoint_enable_for_target(VALUE tpval, VALUE target, VALUE target_line) def->body.bmethod.hooks = ZALLOC(rb_hook_list_t); rb_hook_list_connect_tracepoint(target, def->body.bmethod.hooks, tpval, 0); rb_hash_aset(tp->local_target_set, target, Qfalse); + target_bmethod = true; n++; } } + /* iseq */ + n += rb_iseq_add_local_tracepoint_recursively(iseq, tp->events, tpval, line, target_bmethod); + rb_hash_aset(tp->local_target_set, (VALUE)iseq, Qtrue); + + if (n == 0) { rb_raise(rb_eArgError, "can not enable any hooks"); } + rb_yjit_tracing_invalidate_all(); + ruby_vm_event_local_num++; tp->tracing = 1; @@ -1215,10 +1257,11 @@ disable_local_event_iseq_i(VALUE target, VALUE iseq_p, VALUE tpval) rb_hook_list_t *hooks = def->body.bmethod.hooks; VM_ASSERT(hooks != NULL); rb_hook_list_remove_tracepoint(hooks, tpval); - if (hooks->running == 0) { + + if (hooks->events == 0) { rb_hook_list_free(def->body.bmethod.hooks); + def->body.bmethod.hooks = NULL; } - def->body.bmethod.hooks = NULL; } return ST_CONTINUE; } @@ -1267,9 +1310,9 @@ rb_hook_list_remove_tracepoint(rb_hook_list_t *list, VALUE tpval) while (hook) { if (hook->data == tpval) { hook->hook_flags |= RUBY_EVENT_HOOK_FLAG_DELETED; - list->need_clean = TRUE; + list->need_clean = true; } - else { + else if ((hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) == 0) { events |= hook->events; } hook = hook->next; @@ -1311,7 +1354,7 @@ tracepoint_enable_m(rb_execution_context_t *ec, VALUE tpval, VALUE target, VALUE tpval); } else { - return previous_tracing ? Qtrue : Qfalse; + return RBOOL(previous_tracing); } } @@ -1333,7 +1376,7 @@ tracepoint_disable_m(rb_execution_context_t *ec, VALUE tpval) } else { rb_tracepoint_disable(tpval); - return previous_tracing ? Qtrue : Qfalse; + return RBOOL(previous_tracing); } } @@ -1341,7 +1384,7 @@ VALUE rb_tracepoint_enabled_p(VALUE tpval) { rb_tp_t *tp = tpptr(tpval); - return tp->tracing ? Qtrue : Qfalse; + return RBOOL(tp->tracing); } static VALUE @@ -1358,6 +1401,7 @@ tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp); tp->proc = proc; + tp->ractor = rb_ractor_shareable_p(proc) ? NULL : GET_RACTOR(); tp->func = func; tp->data = data; tp->events = events; @@ -1366,36 +1410,6 @@ tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void return tpval; } -/* - * Creates a tracepoint by registering a callback function for one or more - * tracepoint events. Once the tracepoint is created, you can use - * rb_tracepoint_enable to enable the tracepoint. - * - * Parameters: - * 1. VALUE target_thval - Meant for picking the thread in which the tracepoint - * is to be created. However, current implementation ignore this parameter, - * tracepoint is created for all threads. Simply specify Qnil. - * 2. rb_event_flag_t events - Event(s) to listen to. - * 3. void (*func)(VALUE, void *) - A callback function. - * 4. void *data - Void pointer that will be passed to the callback function. - * - * When the callback function is called, it will be passed 2 parameters: - * 1)VALUE tpval - the TracePoint object from which trace args can be extracted. - * 2)void *data - A void pointer which helps to share scope with the callback function. - * - * It is important to note that you cannot register callbacks for normal events and internal events - * simultaneously because they are different purpose. - * You can use any Ruby APIs (calling methods and so on) on normal event hooks. - * However, in internal events, you can not use any Ruby APIs (even object creations). - * This is why we can't specify internal events by TracePoint directly. - * Limitations are MRI version specific. - * - * Example: - * rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ, obj_event_i, data); - * - * In this example, a callback function obj_event_i will be registered for - * internal events RUBY_INTERNAL_EVENT_NEWOBJ and RUBY_INTERNAL_EVENT_FREEOBJ. - */ VALUE rb_tracepoint_new(VALUE target_thval, rb_event_flag_t events, void (*func)(VALUE, void *), void *data) { @@ -1453,8 +1467,8 @@ tracepoint_inspect(rb_execution_context_t *ec, VALUE self) { VALUE sym = rb_tracearg_method_id(trace_arg); if (NIL_P(sym)) - goto default_inspect; - return rb_sprintf("#", + break; + return rb_sprintf("#", rb_tracearg_event(trace_arg), rb_tracearg_path(trace_arg), FIX2INT(rb_tracearg_lineno(trace_arg)), @@ -1464,7 +1478,7 @@ tracepoint_inspect(rb_execution_context_t *ec, VALUE self) case RUBY_EVENT_C_CALL: case RUBY_EVENT_RETURN: case RUBY_EVENT_C_RETURN: - return rb_sprintf("#", + return rb_sprintf("#", rb_tracearg_event(trace_arg), rb_tracearg_method_id(trace_arg), rb_tracearg_path(trace_arg), @@ -1475,12 +1489,12 @@ tracepoint_inspect(rb_execution_context_t *ec, VALUE self) rb_tracearg_event(trace_arg), rb_tracearg_self(trace_arg)); default: - default_inspect: - return rb_sprintf("#", - rb_tracearg_event(trace_arg), - rb_tracearg_path(trace_arg), - FIX2INT(rb_tracearg_lineno(trace_arg))); + break; } + return rb_sprintf("#", + rb_tracearg_event(trace_arg), + rb_tracearg_path(trace_arg), + FIX2INT(rb_tracearg_lineno(trace_arg))); } else { return rb_sprintf("#", tp->tracing ? "enabled" : "disabled"); @@ -1511,12 +1525,31 @@ tracepoint_stat_s(rb_execution_context_t *ec, VALUE self) rb_vm_t *vm = GET_VM(); VALUE stat = rb_hash_new(); - tracepoint_stat_event_hooks(stat, vm->self, vm->global_hooks.hooks); + tracepoint_stat_event_hooks(stat, vm->self, rb_ec_ractor_hooks(ec)->hooks); /* TODO: thread local hooks */ return stat; } +static VALUE +disallow_reentry(VALUE val) +{ + rb_trace_arg_t *arg = (rb_trace_arg_t *)val; + rb_execution_context_t *ec = GET_EC(); + if (ec->trace_arg != NULL) rb_bug("should be NULL, but %p", (void *)ec->trace_arg); + ec->trace_arg = arg; + return Qnil; +} + +static VALUE +tracepoint_allow_reentry(rb_execution_context_t *ec, VALUE self) +{ + const rb_trace_arg_t *arg = ec->trace_arg; + if (arg == NULL) rb_raise(rb_eRuntimeError, "No need to allow reentrance."); + ec->trace_arg = NULL; + return rb_ensure(rb_yield, Qnil, disallow_reentry, (VALUE)arg); +} + #include "trace_point.rbinc" /* This function is called from inits.c */ @@ -1530,8 +1563,6 @@ Init_vm_trace(void) rb_cTracePoint = rb_define_class("TracePoint", rb_cObject); rb_undef_alloc_func(rb_cTracePoint); - - load_trace_point(); } typedef struct rb_postponed_job_struct { @@ -1565,7 +1596,7 @@ enum postponed_job_register_result { /* Async-signal-safe */ static enum postponed_job_register_result postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm, - unsigned int flags, rb_postponed_job_func_t func, void *data, int max, int expected_index) + unsigned int flags, rb_postponed_job_func_t func, void *data, rb_atomic_t max, rb_atomic_t expected_index) { rb_postponed_job_t *pjob; @@ -1587,6 +1618,14 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm, return PJRR_SUCCESS; } +static rb_execution_context_t * +get_valid_ec(rb_vm_t *vm) +{ + rb_execution_context_t *ec = rb_current_execution_context(false); + if (ec == NULL) ec = rb_vm_main_ractor_ec(vm); + return ec; +} + /* * return 0 if job buffer is full * Async-signal-safe @@ -1594,8 +1633,8 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm, int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data) { - rb_execution_context_t *ec = GET_EC(); - rb_vm_t *vm = rb_ec_vm_ptr(ec); + rb_vm_t *vm = GET_VM(); + rb_execution_context_t *ec = get_valid_ec(vm); begin: switch (postponed_job_register(ec, vm, flags, func, data, MAX_POSTPONED_JOB, vm->postponed_job_index)) { @@ -1613,10 +1652,10 @@ rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data) { - rb_execution_context_t *ec = GET_EC(); - rb_vm_t *vm = rb_ec_vm_ptr(ec); + rb_vm_t *vm = GET_VM(); + rb_execution_context_t *ec = get_valid_ec(vm); rb_postponed_job_t *pjob; - int i, index; + rb_atomic_t i, index; begin: index = vm->postponed_job_index; @@ -1653,7 +1692,8 @@ rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data) list_add_tail(&vm->workqueue, &wq_job->jnode); rb_nativethread_lock_unlock(&vm->workqueue_lock); - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(GET_EC()); + // TODO: current implementation affects only main ractor + RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(rb_vm_main_ractor_ec(vm)); return TRUE; } @@ -1679,7 +1719,7 @@ rb_postponed_job_flush(rb_vm_t *vm) { EC_PUSH_TAG(ec); if (EC_EXEC_TAG() == TAG_NONE) { - int index; + rb_atomic_t index; struct rb_workqueue_job *wq_job; while ((index = vm->postponed_job_index) > 0) { diff --git a/ruby/vsnprintf.c b/ruby/vsnprintf.c index 889c40925..8bfa0c165 100644 --- a/ruby/vsnprintf.c +++ b/ruby/vsnprintf.c @@ -161,11 +161,13 @@ struct __sbuf { * _ub, _up, and _ur are used when ungetc() pushes back more characters * than fit in the current _bf, or when ungetc() pushes back a character * that does not match the previous one in _bf. When this happens, - * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff + * _ub._base becomes non-nil (i.e., a stream has ungetc() data if and only if * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. * * NB: see WARNING above before changing the layout of this structure! */ +struct __suio; + typedef struct __sFILE { unsigned char *_p; /* current position in (some) buffer */ #if 0 @@ -178,8 +180,8 @@ typedef struct __sFILE { #if 0 size_t _lbfsize; /* 0 or -_bf._size, for inline putc */ #endif - int (*vwrite)(/* struct __sFILE*, struct __suio * */); - const char *(*vextra)(/* struct __sFILE*, size_t, void*, long*, int */); + int (*vwrite)(struct __sFILE*, struct __suio *); + const char *(*vextra)(struct __sFILE*, size_t, void*, long*, int); } FILE; @@ -196,7 +198,7 @@ typedef struct __sFILE { #define __SSTR 0x0200 /* this is an sprintf/snprintf string */ #define __SOPT 0x0400 /* do fseek() optimisation */ #define __SNPT 0x0800 /* do not do fseek() optimisation */ -#define __SOFF 0x1000 /* set iff _offset is in fact correct */ +#define __SOFF 0x1000 /* set if and only if _offset is in fact correct */ #define __SMOD 0x2000 /* true => fgetln modified _p text */ @@ -561,7 +563,7 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap) int fprec = 0; /* floating point precision */ char expstr[7]; /* buffer for exponent string */ #endif - u_long MAYBE_UNUSED(ulval); /* integer arguments %[diouxX] */ + u_long MAYBE_UNUSED(ulval) = 0; /* integer arguments %[diouxX] */ #ifdef _HAVE_SANE_QUAD_ u_quad_t MAYBE_UNUSED(uqval); /* %q integers */ #endif /* _HAVE_SANE_QUAD_ */ diff --git a/ruby/warning.rb b/ruby/warning.rb index 224650d4e..0012ffb1d 100644 --- a/ruby/warning.rb +++ b/ruby/warning.rb @@ -1,11 +1,11 @@ # encoding: utf-8 -# fronzen-string-literal: true +# frozen-string-literal: true module Kernel module_function # call-seq: - # warn(*msgs, uplevel: nil) -> nil + # warn(*msgs, uplevel: nil, category: nil) -> nil # # If warnings have been disabled (for example with the # -W0 flag), does nothing. Otherwise, @@ -39,7 +39,15 @@ module Kernel # # baz.rb:6: warning: invalid call to foo # - def warn(*msgs, uplevel: nil) - __builtin_rb_warn_m(msgs, uplevel) + # If category keyword argument is given, passes the category + # to Warning.warn. The category given must be be one of the + # following categories: + # + # :deprecated :: Used for warning for deprecated functionality that may + # be removed in the future. + # :experimental :: Used for experimental features that may change in + # future releases. + def warn(*msgs, uplevel: nil, category: nil) + Primitive.rb_warn_m(msgs, uplevel, category) end end diff --git a/ruby/warning.rbinc b/ruby/warning.rbinc index ef3451e44..584da8ee8 100644 --- a/ruby/warning.rbinc +++ b/ruby/warning.rbinc @@ -3,8 +3,13 @@ // auto-generated file // by ./tool/mk_builtin_loader.rb // with warning.rb +#include "internal/compilers.h" /* for MAYBE_UNUSED */ +#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ +#include "ruby/ruby.h" /* for VALUE */ +#include "builtin.h" /* for RB_BUILTIN_FUNCTION */ +struct rb_execution_context_struct; /* in vm_core.h */ -static void load_warning(void) +void Init_builtin_warning(void) { // table definition static const struct rb_builtin_function warning_table[] = { diff --git a/ruby/win32/Makefile.sub b/ruby/win32/Makefile.sub index ef2984519..7d78c6ad7 100644 --- a/ruby/win32/Makefile.sub +++ b/ruby/win32/Makefile.sub @@ -10,6 +10,7 @@ CHDIR = cd PATH_SEPARATOR = ; TZ = # skip timezone tests PWD = $(MAKEDIR) +empty = !ifndef MFLAGS MFLAGS=-l @@ -24,9 +25,6 @@ REVISION_FORCE = PHONY !ifndef CROSS_COMPILING CROSS_COMPILING = no !endif -!ifndef LARGEFILE_SUPPORT -LARGEFILE_SUPPORT = 1 -!endif !ifndef win_srcdir win_srcdir = $(srcdir)/win32 !endif @@ -67,9 +65,6 @@ icondirs=$(ICONDIRS) icondirs=$(icondirs:\=/) iconinc=-I$(icondirs: = -I) !endif -!if !defined(MATHN) -MATHN = yes -!endif ############### .SUFFIXES: .def .lib @@ -94,6 +89,7 @@ RMALL = $(COMSPEC) /C $(srcdir:/=\)\win32\rm.bat -f -r MAKEDIRS = $(COMSPEC) /E:ON /C $(srcdir:/=\)\win32\makedirs.bat CP = copy > nul MV = move > nul +RM1 = del /f /q !if !defined(BASERUBY) BASERUBY = ruby !endif @@ -277,11 +273,11 @@ EXTLIBS = EXTSOLIBS = !endif !if !defined(LIBS) -LIBS = user32.lib advapi32.lib shell32.lib ws2_32.lib Ole32.lib Shell32.lib +LIBS = user32.lib advapi32.lib shell32.lib ws2_32.lib !if $(MSC_VER) >= 1400 LIBS = $(LIBS) iphlpapi.lib !endif -LIBS = $(LIBS) imagehlp.lib shlwapi.lib $(EXTLIBS) +LIBS = $(LIBS) imagehlp.lib shlwapi.lib bcrypt.lib $(EXTLIBS) !endif !if !defined(MISSING) MISSING = crypt.obj ffs.obj langinfo.obj lgamma_r.obj strlcat.obj strlcpy.obj win32/win32.obj win32/file.obj setproctitle.obj @@ -308,9 +304,6 @@ ARFLAGS = -machine:$(MACHINE) -out: LD = $(CC) LDSHARED = $(LD) -LD XCFLAGS = -DRUBY_EXPORT $(INCFLAGS) $(XCFLAGS) -!if "$(MATHN)" == "yes" -XCFLAGS = $(XCFLAGS) -DCANONICALIZATION_FOR_MATHN -!endif !if $(MSC_VER) >= 1400 # Prevents VC++ 2005 (cl ver 14) warnings MANIFESTTOOL = mt -nologo @@ -345,7 +338,8 @@ MJIT_OPTFLAGS = -DMJIT_HEADER $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) !endif !ifndef MJIT_DEBUGFLAGS # TODO: Make this work... Another header for debug build needs to be installed first. -MJIT_DEBUGFLAGS = $(DEBUGFLAGS) +MJIT_DEBUGFLAGS = $(empty) $(DEBUGFLAGS) $(empty) +MJIT_DEBUGFLAGS = $(MJIT_DEBUGFLAGS: -Zi = -Z7 ) !endif !ifndef MJIT_LDSHARED MJIT_LDSHARED = $(MJIT_CC) -LD @@ -383,7 +377,7 @@ MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib -I. RUNRUBY = .\$(PROGRAM) -I$(srcdir)/lib -I"$(EXTOUT)/$(arch)" -I. !endif MINIRUBY = $(MINIRUBY) $(MINIRUBYOPT) -RUNRUBY = $(RUNRUBY) "$(srcdir)/tool/runruby.rb" --extout="$(EXTOUT)" $(RUNRUBYOPT) -- $(RUN_OPTS) +RUNRUBY = $(RUNRUBY) "$(tooldir)/runruby.rb" --extout="$(EXTOUT)" $(RUNRUBYOPT) -- $(RUN_OPTS) !if "$(CROSS_COMPILING)" == "yes" XRUBY = $(MINIRUBY) BOOTSTRAPRUBY = $(BASERUBY) @@ -421,6 +415,8 @@ LIBRUBYARG_SHARED = $(LIBRUBY) LIBRUBY_RELATIVE = yes THREAD_MODEL = win32 +THREAD_IMPL_H = thread_$(THREAD_MODEL).h +THREAD_IMPL_SRC = thread_$(THREAD_MODEL).c !if "$(CROSS_COMPILING)" == "yes" PREP = $(arch)-fake.rb @@ -473,6 +469,7 @@ EXTOBJS = dmyext.$(OBJEXT) arch_hdrdir = $(EXTOUT)/include/$(arch) top_srcdir = $(srcdir) hdrdir = $(srcdir)/include +tooldir = $(srcdir)/tool VPATH = $(arch_hdrdir)/ruby;$(hdrdir)/ruby;$(srcdir);$(srcdir)/missing;$(win_srcdir) !ifndef GIT @@ -498,7 +495,7 @@ HAVE_GIT = no !if defined(VCS) !else if exist($(srcdir)/.git) VCS = $(GIT) -VCSUP = $(VCS) pull $(GITPULLOPTIONS) +VCSUP = $(VCS) pull --rebase $(GITPULLOPTIONS) !else VCSUP = rem !endif @@ -534,6 +531,14 @@ GOLF_PRELUDE_C = golf_prelude.c !endif RBCONFIG = ./.rbconfig.time +!if "$(GITHUB_ACTIONS)" == "true" +ACTIONS_GROUP = @echo ^#^#[group]$(@:yes-=) +ACTIONS_ENDGROUP = @echo ^#^#[endgroup] +!else +ACTIONS_GROUP = @:: $(empty) +ACTIONS_ENDGROUP = @:: +!endif + !include $(srcdir)/common.mk !ifdef SCRIPTPROGRAMS @@ -606,9 +611,15 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub @$(IFCHANGE) "--timestamp=$(@:/=\)" $(RUBY_CONFIG_H:/=\) << #ifndef $(guard) #define $(guard) 1 +!if defined(MSC_VER_LOWER) +#if (_MSC_VER < $(MSC_VER_LOWER)) || (_MSC_VER > $(MSC_VER_UPPER)) +#error MSC version unmatch: $(MSC_VER_LOWER)..$(MSC_VER_UPPER) is expected. +#endif +!else #if _MSC_VER != $(MSC_VER) -#error MSC version unmatch: _MSC_VER: $(MSC_VER) is expected. +#error MSC version unmatch: $(MSC_VER) is expected. #endif +!endif #define RUBY_MSVCRT_VERSION $(RT_VER) #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 @@ -635,12 +646,10 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define SIZEOF_LONG_LONG 0 !endif #define SIZEOF___INT64 8 +#ifndef _INTEGRAL_MAX_BITS #define _INTEGRAL_MAX_BITS 64 -!if $(LARGEFILE_SUPPORT) +#endif #define SIZEOF_OFF_T 8 -!else -#define SIZEOF_OFF_T 4 -!endif !if "$(ARCH)" == "x64" #define SIZEOF_VOIDP 8 !else @@ -677,9 +686,6 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub !if $(MSC_VER) < 1400 #define SIZE_MAX UINT_MAX !endif -#define HAVE_PROTOTYPES 1 -#define TOKEN_PASTE(x,y) x##y -#define HAVE_STDARG_PROTOTYPES 1 !if $(MSC_VER) >= 1800 #define HAVE_VA_COPY 1 !else @@ -690,7 +696,6 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub !endif !if $(MSC_VER) >= 1300 #define DEPRECATED(x) __declspec(deprecated) x -#define DEPRECATED_TYPE(mesg, x) __declspec(deprecated mesg) x #define RUBY_CXX_DEPRECATED(mesg) __declspec(deprecated(mesg)) #define NOINLINE(x) __declspec(noinline) x !endif @@ -708,7 +713,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub !else #define PACKED_STRUCT(x) x !endif -!if "$(ARCH)" == "x86" || "$(ARCH)" == "x64" +!if "$(MACHINE)" == "x86" || "$(ARCH)" == "x64" #define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x) !else #define PACKED_STRUCT_UNALIGNED(x) x @@ -726,7 +731,6 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define rb_gid_t int #define rb_uid_t int #define HAVE_STRUCT_STAT_ST_RDEV 1 -#define HAVE_ST_RDEV 1 #define HAVE_STRUCT_TIMEVAL 1 !if $(MSC_VER) >= 1900 #define HAVE_STRUCT_TIMESPEC @@ -784,7 +788,6 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define PRI_LL_PREFIX "I64" #define PRI_PIDT_PREFIX PRI_INT_PREFIX #define GETGROUPS_T int -#define RETSIGTYPE void #define TYPEOF_TIMEVAL_TV_SEC long !if $(RT_VER) >= 120 #define HAVE_ACOSH 1 @@ -851,14 +854,17 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define HAVE_QSORT_S !endif #define HAVE_TYPE_NET_LUID 1 +!if $(MSC_VER) >= 1600 +#define HAVE_NULLPTR 1 +!endif #define SETPGRP_VOID 1 #define RSHIFT(x,y) ((x)>>(int)y) #define HAVE_RB_FD_INIT 1 #define RUBY_SETJMP(env) _setjmp(env) #define RUBY_LONGJMP(env,val) longjmp(env,val) #define RUBY_JMP_BUF jmp_buf -#define inline __inline #ifndef __cplusplus +#define inline __inline !if $(MSC_VER) >= 1800 #define restrict __restrict !else @@ -870,7 +876,8 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define STACK_GROW_DIRECTION -1 !endif #define COROUTINE_H "$(COROUTINE_H)" -#define DEFAULT_KCODE KCODE_NONE +#define THREAD_IMPL_H "$(THREAD_IMPL_H)" +#define THREAD_IMPL_SRC "$(THREAD_IMPL_SRC)" #define LOAD_RELATIVE 1 #define DLEXT ".so" !if "$(libdir_basename)" != "lib" @@ -909,8 +916,7 @@ EXECUTABLE_EXTS = $(EXECUTABLE_EXTS:"=) # " EXECUTABLE_EXTS = $(EXECUTABLE_EXTS:,= ) config.status: $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub $(srcdir)/common.mk - @echo Creating $@ - @exit <<$@ + @echo Creating <<$@ # Generated automatically by Makefile.sub. s,@SHELL@,$$(COMSPEC),;t t s,@BUILD_FILE_SEPARATOR@,\,;t t @@ -974,7 +980,6 @@ s,@RMALL@,$$(COMSPEC) /C $$(top_srcdir:/=\)\win32\rm.bat -f -r,:t t s,@MAKEDIRS@,$$(COMSPEC) /E:ON /C $$(top_srcdir:/=\)\win32\makedirs.bat,;t t s,@LIBOBJS@,$(LIBOBJS),;t t s,@ALLOCA@,$(ALLOCA),;t t -s,@DEFAULT_KCODE@,$(DEFAULT_KCODE),;t t s,@EXEEXT@,.exe,;t t s,@EXECUTABLE_EXTS@,$(EXECUTABLE_EXTS),;t t s,@OBJEXT@,$(OBJEXT),;t t @@ -991,6 +996,7 @@ s,@SOEXT@,dll,;t t s,@DLEXT@,so,;t t s,@LIBEXT@,lib,;t t s,@STRIP@,$(STRIP),;t t +s,@ENCSTATIC@,$(ENCSTATIC),;t t s,@EXTSTATIC@,$(EXTSTATIC),;t t s,@setup@,Setup,;t t s,@MINIRUBY@,$(MINIRUBY),;t t @@ -1089,9 +1095,7 @@ miniruby: miniruby$(EXEEXT) miniruby$(EXEEXT): @echo $(LIBS) $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(CFLAGS) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(LIBS) -Fe$@ \ - ..\zlib\zlib.lib enclose_io_memfs.res \ - -link $(LDFLAGS) + $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(LIBS) -Fe$@ -link $(LDFLAGS) @$(RM) miniruby.lib miniruby.exp $(Q) miniruby.exe -v $(Q) $(LDSHARED_1) @@ -1100,59 +1104,10 @@ miniruby$(EXEEXT): miniruby.rc: @exit > $@ -ruby_static.exe: $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res - $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(CFLAGS) $(MAINOBJ) $(RUBY_INSTALL_NAME).res \ - $(OUTFLAG)$@ $(LIBRUBY_A) $(LIBS) enc\*.obj enc\*.lib ext\extinit.obj \ - ext\bigdecimal\*.lib \ - ext\cgi\*.lib ext\cgi\escape\*.lib \ - ext\continuation\*.lib \ - ext\coverage\*.lib \ - ext\date\*.lib \ - ext\dbm\*.lib \ - ext\digest\*.lib ext\digest\bubblebabble\*.lib ext\digest\md5\*.lib ext\digest\rmd160\*.lib ext\digest\sha1\*.lib ext\digest\sha2\*.lib \ - ext\etc\*.lib \ - ext\fcntl\*.lib \ - ext\fiber\*.lib \ - ext\fiddle\*.lib ext\fiddle\libffi-3.2.1\.libs\*.lib \ - ext\gdbm\*.lib \ - ext\io\*.lib ext\io\console\*.lib ext\io\nonblock\*.lib ext\io\wait\*.lib \ - ext\json\*.lib ext\json\generator\*.lib ext\json\parser\*.lib \ - ext\monitor\*.lib \ - ext\nkf\*.lib \ - ext\objspace\*.lib \ - ext\openssl\*.lib \ - ext\pathname\*.lib \ - ext\psych\*.lib \ - ext\pty\*.lib \ - ext\racc\*.lib ext\racc\cparse\*.lib \ - ext\rbconfig\*.lib ext\rbconfig\sizeof\*.lib \ - ext\readline\*.lib \ - ext\ripper\*.lib \ - ext\rubyvm\*.lib \ - ext\sdbm\*.lib \ - ext\socket\*.lib \ - ext\stringio\*.lib \ - ext\strscan\*.lib \ - ext\syslog\*.lib \ - ext\-test-\*.lib \ - ext\win32\*.lib ext\win32\resolv\*.lib \ - ext\win32ole\*.lib \ - ext\zlib\*.lib \ - ..\zlib\zlib.lib \ - ..\local\lib\*.lib \ - OleAut32.lib \ - Crypt32.lib \ - enclose_io_memfs.res \ - -link $(LDFLAGS) $(XLDFLAGS) - $(Q) $(LDSHARED_0) - $(Q) $(LDSHARED_1) - $(Q) $(LDSHARED_2) - !if "$(PROGRAM)" != "" $(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(CFLAGS) $(MAINOBJ) $(EXTOBJS) enclose_io_unix.obj enclose_io_memfs.res squash_fd.obj Shell32.lib $(RUBY_INSTALL_NAME).res \ + $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(EXTOBJS) $(RUBY_INSTALL_NAME).res \ $(OUTFLAG)$@ $(LIBRUBYARG) -link $(LDFLAGS) $(XLDFLAGS) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) @@ -1162,7 +1117,7 @@ $(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res !if "$(WPROGRAM)" != "" $(WPROGRAM): $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_SO) $(RUBYW_INSTALL_NAME).res $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(CFLAGS) $(MAINOBJ) enclose_io_unix.obj enclose_io_memfs.res squash_fd.obj Shell32.lib $(WINMAINOBJ) \ + $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(WINMAINOBJ) \ $(RUBYW_INSTALL_NAME).res $(OUTFLAG)$@ $(LIBRUBYARG) \ -link $(LDFLAGS) $(XLDFLAGS) -subsystem:Windows $(Q) $(LDSHARED_0) @@ -1173,7 +1128,7 @@ $(WPROGRAM): $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_SO) $(RUBYW_INSTALL_NAME).res !if "$(STUBPROGRAM)" != "" $(STUBPROGRAM): rubystub.$(OBJEXT) $(LIBRUBY) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(CFLAGS) rubystub.$(OBJEXT) $(RUBY_INSTALL_NAME).res \ + $(Q) $(PURIFY) $(CC) rubystub.$(OBJEXT) $(RUBY_INSTALL_NAME).res \ $(OUTFLAG)$@ $(LIBRUBYARG) -link $(LDFLAGS) $(XLDFLAGS) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) @@ -1272,7 +1227,7 @@ update-benchmark-driver: $(GIT) -C $(srcdir)/benchmark/benchmark-driver pull origin master $(ruby_pc): $(RBCONFIG) - @$(BOOTSTRAPRUBY) $(srcdir)/tool/expand-config.rb \ + @$(BOOTSTRAPRUBY) $(tooldir)/expand-config.rb \ -output=$@ -mode=$(INSTALL_DATA_MODE) -config=rbconfig.rb \ $(srcdir)/template/ruby.pc.in @@ -1282,9 +1237,6 @@ $(ruby_pc): $(RBCONFIG) {$(srcdir)/coroutine/win64}.asm{coroutine/win64}.obj: $(ECHO) assembling $(<:\=/) $(Q) $(AS) $(ASFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(<:\=/) -{$(srcdir)/coroutine/copy}.c{coroutine/copy}.obj: - $(ECHO) compiling $(<:\=/) - $(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(<:\=/) {$(srcdir)/enc/trans}.c.obj: $(ECHO) compiling $(<:\=/) @@ -1320,16 +1272,16 @@ $(ruby_pc): $(RBCONFIG) {$(srcdir)/missing}.c.i: $(ECHO) preprocessing $(<:\=/) - $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P $(CSRCFLAG)$(<:\=/) > $@ + $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P -Fi:$@ $(CSRCFLAG)$(<:\=/) {$(win_srcdir)}.c.i: $(ECHO) preprocessing $(<:\=/) - $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P $(CSRCFLAG)$(<:\=/) + $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P -Fi:$@ $(CSRCFLAG)$(<:\=/) {$(srcdir)}.c{}.i: $(ECHO) preprocessing $(<:\=/) - $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P $(CSRCFLAG)$(<:\=/) + $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P -Fi:$@ $(CSRCFLAG)$(<:\=/) .c.i: $(ECHO) preprocessing $(<:\=/) - $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P $(CSRCFLAG)$(<:\=/) + $(Q) $(CC) $(XCFLAGS) $(CPPFLAGS) -P -Fi:$@ $(CSRCFLAG)$(<:\=/) .rc.res: $(ECHO) compiling $(<:\=/) @@ -1364,26 +1316,24 @@ clean-local:: $(Q)$(RM) $(MJIT_PRECOMPILED_HEADER_NAME) $(MJIT_PRECOMPILED_HEADER_NAME:.pch=.)$(OBJEXT) $(Q)$(RM) $(TIMESTAMPDIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=.time) mjit_config.h $(Q)$(RM) $(MJIT_HEADER_INSTALL_DIR)/rb_mjit_header-*.pch - $(Q)$(RM) $(MJIT_HEADER_INSTALL_DIR)/rb_mjit_header-*.pdb $(Q)$(RM) $(MJIT_HEADER_INSTALL_DIR)/rb_mjit_header-*.$(OBJEXT) -$(Q) $(RMDIRS) $(MJIT_HEADER_INSTALL_DIR) 2> $(NULL) || exit 0 $(Q)$(RM) $(arch_hdrdir)/rb_mjit_header-*.pch - $(Q)$(RM) $(arch_hdrdir)/rb_mjit_header-*.pdb $(Q)$(RM) $(arch_hdrdir)/rb_mjit_header-*.$(OBJEXT) # Non-mswin environment is not using prebuilt precompiled header because upgrading compiler -# or changing compiler options may break MJIT so build (currently only by --jit-debug though). +# or changing compiler options may break MJIT so build (currently only by --mjit-debug though). # # But mswin is building precompiled header because cl.exe cannot leave macro after preprocess. # As a workaround to use macro without installing many source files, it uses precompiled header # without sufficient guard for a broken build. # # TODO: Fix the above issue by including VC version in header name, and create another header -# for --jit-debug as well. +# for --mjit-debug as well. $(TIMESTAMPDIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=).time: probes.h vm.$(OBJEXT) $(ECHO) building $(@F:.time=.pch) - $(Q) $(CC) -DMJIT_HEADER $(CFLAGS) $(XCFLAGS:-DRUBY_EXPORT =) -URUBY_EXPORT $(CPPFLAGS) $(srcdir)/vm.c -c -Yc \ - $(COUTFLAG)$(@F:.time=.)$(OBJEXT) -Fd$(@F:.time=.pdb) -Fp$(@F:.time=.pch).new + $(Q) $(CC) -DMJIT_HEADER $(CFLAGS: -Zi = -Z7 ) $(XCFLAGS:-DRUBY_EXPORT =) -URUBY_EXPORT $(CPPFLAGS) $(srcdir)/vm.c -c -Yc \ + $(COUTFLAG)$(@F:.time=.)$(OBJEXT) -Fd$(@F:.time=.pdb) -Fp$(@F:.time=.pch).new -Z7 $(Q) $(IFCHANGE) "--timestamp=$@" $(@F:.time=.pch) $(@F:.time=.pch).new $(MJIT_PRECOMPILED_HEADER_NAME): $(TIMESTAMPDIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=).time @@ -1392,11 +1342,9 @@ $(MJIT_PRECOMPILED_HEADER): $(MJIT_PRECOMPILED_HEADER_NAME) $(Q) $(MAKEDIRS) $(MJIT_HEADER_INSTALL_DIR) $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME) $@ $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME:.pch=.)$(OBJEXT) $(MJIT_HEADER_INSTALL_DIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=.)$(OBJEXT) - $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME:.pch=.pdb) $(MJIT_HEADER_INSTALL_DIR)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=.pdb) $(Q) $(MAKEDIRS) $(arch_hdrdir) $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME) $(arch_hdrdir)/$(MJIT_PRECOMPILED_HEADER_NAME) $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME:.pch=.)$(OBJEXT) $(arch_hdrdir)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=.)$(OBJEXT) - $(Q) $(MAKE_LINK) $(MJIT_PRECOMPILED_HEADER_NAME:.pch=.pdb) $(arch_hdrdir)/$(MJIT_PRECOMPILED_HEADER_NAME:.pch=.pdb) INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \ vmtc.inc vm.inc mjit_compile.inc @@ -1406,9 +1354,9 @@ INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \ @for %J in (\ "%I: $$(srcdir)/insns.def {$$(VPATH)}vm_opts.h \" \ " $$(srcdir)/defs/opt_operand.def $$(srcdir)/defs/opt_insn_unif.def \" \ -" $$(srcdir)/tool/insns2vm.rb" \ +" $$(tooldir)/insns2vm.rb" \ " @$$(RM) $$(PROGRAM)" \ -" $$(Q) $$(BASERUBY) -Ku $$(srcdir)/tool/insns2vm.rb $$(INSNS2VMOPT) %I" \ +" $$(Q) $$(BASERUBY) -Ku $$(tooldir)/insns2vm.rb $$(INSNS2VMOPT) %I" \ "" \ ) do @echo.%~J>>insns_rules.mk] !else diff --git a/ruby/win32/configure.bat b/ruby/win32/configure.bat index b141bfc54..2ca7c6bdc 100755 --- a/ruby/win32/configure.bat +++ b/ruby/win32/configure.bat @@ -110,57 +110,57 @@ goto :loop ; goto :loop ; :extstatic echo>> ~tmp~.mak "EXTSTATIC=static" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :enable-rdoc echo>> ~tmp~.mak "RDOCTARGET=rdoc" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :disable-rdoc echo>> ~tmp~.mak "RDOCTARGET=nodoc" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :enable-lib echo>> ~tmp~.mak "INSTALL_STATIC_LIBRARY=yes" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :disable-lib echo>> ~tmp~.mak "INSTALL_STATIC_LIBRARY=no" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :enable-debug-env echo>> ~tmp~.mak "ENABLE_DEBUG_ENV=yes" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :disable-debug-env echo>> ~tmp~.mak "ENABLE_DEBUG_ENV=no" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :enable-rubygems echo>> ~tmp~.mak "USE_RUBYGEMS=yes" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :disable-rubygems echo>> ~tmp~.mak "USE_RUBYGEMS=no" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :enable-mjit-support echo>> ~tmp~.mak "MJIT_SUPPORT=yes" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :disable-mjit-support echo>> ~tmp~.mak "MJIT_SUPPORT=no" \ - echo>>confargs.tmp %1 \ + echo>>confargs.tmp %1 \ shift goto :loop ; :ntver diff --git a/ruby/win32/dir.h b/ruby/win32/dir.h index 29c4c1c6d..de12f7915 100644 --- a/ruby/win32/dir.h +++ b/ruby/win32/dir.h @@ -1,5 +1,8 @@ #ifndef RUBY_WIN32_DIR_H #define RUBY_WIN32_DIR_H +#include /* for uint8_t */ +#include /* for WCHAR */ +#include "ruby/encoding.h" /* for rb_encoding */ #define DT_UNKNOWN 0 #define DT_DIR (S_IFDIR>>12) @@ -29,17 +32,19 @@ typedef struct { DIR* rb_w32_opendir(const char*); DIR* rb_w32_uopendir(const char*); struct direct* rb_w32_readdir(DIR *, rb_encoding *); +struct direct* rb_w32_ureaddir(DIR *); long rb_w32_telldir(DIR *); void rb_w32_seekdir(DIR *, long); void rb_w32_rewinddir(DIR *); void rb_w32_closedir(DIR *); char *rb_w32_ugetcwd(char *, int); -#define opendir(s) rb_w32_opendir((s)) -#define readdir(d) rb_w32_readdir((d), 0) +#define opendir(s) rb_w32_uopendir((s)) +#define readdir(d) rb_w32_ureaddir((d)) #define telldir(d) rb_w32_telldir((d)) #define seekdir(d, l) rb_w32_seekdir((d), (l)) #define rewinddir(d) rb_w32_rewinddir((d)) #define closedir(d) rb_w32_closedir((d)) +#define getcwd(b, s) rb_w32_ugetcwd(b, s) #endif /* RUBY_WIN32_DIR_H */ diff --git a/ruby/win32/file.c b/ruby/win32/file.c index 540159192..33303823b 100644 --- a/ruby/win32/file.c +++ b/ruby/win32/file.c @@ -5,15 +5,12 @@ #include "ruby/ruby.h" #include "ruby/encoding.h" #include "internal.h" +#include "internal/error.h" #include #include #include #include "win32/file.h" -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- - #ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif @@ -40,8 +37,6 @@ IS_ABSOLUTE_PATH_P(const WCHAR *path, size_t len) #define INVALID_CODE_PAGE 51932 #define PATH_BUFFER_SIZE MAX_PATH * 2 -#define insecure_obj_p(obj, level) ((level) > 0 && OBJ_TAINTED(obj)) - /* defined in win32/win32.c */ #define system_code_page rb_w32_filecp #define mbstr_to_wstr rb_w32_mbstr_to_wstr @@ -160,11 +155,11 @@ replace_to_long_name(wchar_t **wfullpath, size_t size, size_t buffer_size) /* Skip long name conversion if the path is already long name. Short name is 8.3 format. - http://en.wikipedia.org/wiki/8.3_filename + https://en.wikipedia.org/wiki/8.3_filename This check can be skipped for directory components that have file extensions longer than 3 characters, or total lengths longer than 12 characters. - http://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx + https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx */ size_t const max_short_name_size = 8 + 1 + 3; size_t const max_extension_size = 3; @@ -291,10 +286,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na wchar_t path_drive = L'\0', dir_drive = L'\0'; int ignore_dir = 0; rb_encoding *path_encoding; - int tainted = 0; - - /* tainted if path is tainted */ - tainted = OBJ_TAINTED(path); /* get path encoding */ if (NIL_P(dir)) { @@ -331,9 +322,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na /* expand '~' only if NOT rb_file_absolute_path() where `abs_mode` is 1 */ if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L'~' && (wpath_len == 1 || IS_DIR_SEPARATOR_P(wpath_pos[1]))) { - /* tainted if expanding '~' */ - tainted = 1; - whome = rb_w32_home_dir(); if (whome == NULL) { free(wpath); @@ -350,7 +338,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na if (path_cp == INVALID_CODE_PAGE || rb_enc_str_asciionly_p(path)) { /* use filesystem encoding if expanding home dir */ path_encoding = rb_filesystem_encoding(); - cp = path_cp = system_code_page(); + cp = path_cp = code_page(path_encoding); } /* ignores dir since we are expanding home */ @@ -412,9 +400,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L'~' && (wdir_len == 1 || IS_DIR_SEPARATOR_P(wdir_pos[1]))) { - /* tainted if expanding '~' */ - tainted = 1; - whome = rb_w32_home_dir(); if (whome == NULL) { free(wpath); @@ -519,10 +504,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na } if (wdir_len) { - /* tainted if dir is used and dir is tainted */ - if (!tainted && OBJ_TAINTED(dir)) - tainted = 1; - wcsncpy(buffer_pos, wdir_pos, wdir_len); buffer_pos += wdir_len; } @@ -548,10 +529,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na /* Ensure buffer is NULL terminated */ buffer_pos[0] = L'\0'; - /* tainted if path is relative */ - if (!tainted && !IS_ABSOLUTE_PATH_P(buffer, buffer_len)) - tainted = 1; - /* FIXME: Make this more robust */ /* Determine require buffer size */ size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL); @@ -594,10 +571,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na rb_str_set_len(result, 0); result = append_wstr(result, wfullpath, size, path_cp, path_encoding); - /* makes the result object tainted if expanding tainted strings or returning modified path */ - if (tainted) - OBJ_TAINT(result); - /* TODO: better cleanup */ if (buffer) xfree(buffer); diff --git a/ruby/win32/ifchange.bat b/ruby/win32/ifchange.bat index 606d6ed66..c7db628a0 100755 --- a/ruby/win32/ifchange.bat +++ b/ruby/win32/ifchange.bat @@ -1,13 +1,16 @@ @echo off :: usage: ifchange target temporary +for %%I in (%0) do set progname=%%~nI set timestamp= set keepsuffix= set empty= set color=auto :optloop for %%I in (%1) do set opt=%%~I -if "%opt%" == "--timestamp" ( +if "%opt%" == "--" ( + shift +) else if "%opt%" == "--timestamp" ( set timestamp=. shift goto :optloop @@ -39,8 +42,18 @@ if "%opt%" == "--timestamp" ( shift echo on goto :optloop +) else if "%opt%" == "--help" ( + call :help + exit /b +) else if "%opt:~0,2%" == "--" ( + echo %progname%: unknown option: %1 1>&2 + exit /b 1 +) + +if "%2" == "" ( + call :help 1>&2 + exit /b 1 ) -if "%opt%" == "" goto :end set dest=%1 set src=%2 @@ -85,4 +98,17 @@ if "%timestamp%" == "" goto :end for %%I in ("%dest%") do set timestamp=%%~dpI.time.%%~nxI ) goto :end > "%timestamp%" + +:help + for %%I in ( + "usage: %progname% [options] target new-file" + "options:" + " --timestamp[=file] touch timestamp file. (default: prefixed with '.time')" + " under the directory of the target)" + " --keep[=suffix] keep old file with suffix. (default: '.old')" + " --empty assume unchanged if the new file is empty." + " --color[=always|auto|never] colorize output." + ) do echo.%%~I + goto :eof + :end diff --git a/ruby/win32/mkexports.rb b/ruby/win32/mkexports.rb index 336a757b8..70b7f3f22 100755 --- a/ruby/win32/mkexports.rb +++ b/ruby/win32/mkexports.rb @@ -7,16 +7,13 @@ module RbConfig end class Exports - PrivateNames = /(?:Init_|InitVM_|ruby_static_id_|DllMain\b)/ - - @@subclass = [] - def self.inherited(klass) - @@subclass << [/#{klass.name.sub(/.*::/, '').downcase}/i, klass] - end + PrivateNames = /(?:Init_|InitVM_|ruby_static_id_|threadptr|_ec_|DllMain\b)/ def self.create(*args, &block) platform = RUBY_PLATFORM - pat, klass = @@subclass.find {|p, k| p =~ platform} + klass = constants.find do |p| + break const_get(p) if platform.include?(p.to_s.downcase) + end unless klass raise ArgumentError, "unsupported platform: #{platform}" end @@ -167,6 +164,9 @@ def each_export(objs) end end +class Exports::Msys < Exports::Cygwin +end + class Exports::Mingw < Exports::Cygwin def each_export(objs) super diff --git a/ruby/win32/resource.rb b/ruby/win32/resource.rb index e19e04b92..bc3eda563 100755 --- a/ruby/win32/resource.rb +++ b/ruby/win32/resource.rb @@ -61,6 +61,7 @@ def icons.find(path) #include #{icon || ''} +#{type == 'VFT_APP' ? "1 RT_MANIFEST ruby.manifest" : ""} VS_VERSION_INFO VERSIONINFO FILEVERSION #{nversion} PRODUCTVERSION #{nversion} @@ -93,4 +94,3 @@ def icons.find(path) EOF } end - diff --git a/ruby/win32/ruby.manifest b/ruby/win32/ruby.manifest new file mode 100644 index 000000000..2bd495979 --- /dev/null +++ b/ruby/win32/ruby.manifest @@ -0,0 +1,8 @@ + + + + + true + + + diff --git a/ruby/win32/setup.mak b/ruby/win32/setup.mak index d67b6843a..5294a49ee 100644 --- a/ruby/win32/setup.mak +++ b/ruby/win32/setup.mak @@ -22,7 +22,6 @@ MAKEFILE = Makefile CPU = PROCESSOR_LEVEL CC = $(CC) -nologo CPP = $(CC) -EP -AS = $(AS) -nologo all: -prologue- -generic- -epilogue- i386-mswin32: -prologue- -i386- -epilogue- @@ -132,9 +131,6 @@ int main(void) {return (EnumProcesses(NULL,0,NULL) ? 0 : 1);} << -version-: nul verconf.mk - @$(CPP) -I$(srcdir) -I$(srcdir)/include <<"Creating $(MAKEFILE)" | findstr "=" >>$(MAKEFILE) -MSC_VER = _MSC_VER -<< verconf.mk: nul @$(CPP) -I$(srcdir) -I$(srcdir)/include <<"Creating $(@)" > $(*F).bat && cmd /c $(*F).bat > $(@) @@ -143,15 +139,29 @@ verconf.mk: nul #define STRINGIZE0(expr) #expr #define STRINGIZE(x) STRINGIZE0(x) #include "version.h" -for %%I in (RUBY_RELEASE_DATE) do set ruby_release_date=%%~I -#undef RUBY_RELEASE_DATE -echo RUBY_RELEASE_DATE = %ruby_release_date:""=% +set ruby_release_year=RUBY_RELEASE_YEAR +set ruby_release_month=RUBY_RELEASE_MONTH +set ruby_release_day=RUBY_RELEASE_DAY +set ruby_release_month=0%ruby_release_month% +set ruby_release_day=0%ruby_release_day% +#undef RUBY_RELEASE_YEAR +#undef RUBY_RELEASE_MONTH +#undef RUBY_RELEASE_DAY +echo RUBY_RELEASE_YEAR = %ruby_release_year% +echo RUBY_RELEASE_MONTH = %ruby_release_month:~-2% +echo RUBY_RELEASE_DAY = %ruby_release_day:~-2% echo MAJOR = RUBY_VERSION_MAJOR echo MINOR = RUBY_VERSION_MINOR echo TEENY = RUBY_VERSION_TEENY #if defined RUBY_PATCHLEVEL && RUBY_PATCHLEVEL < 0 echo RUBY_DEVEL = yes #endif +set /a MSC_VER = _MSC_VER +#if _MSC_VER > 1900 +set /a MSC_VER_LOWER = MSC_VER/10*10+0 +set /a MSC_VER_UPPER = MSC_VER/10*10+9 +#endif +set MSC_VER del %0 & exit << @@ -226,8 +236,15 @@ MACHINE = x86 # RFLAGS = -r # EXTLIBS = CC = $(CC) -AS = $(AS) +!if "$(AS)" != "ml64" +AS = $(AS) -nologo +!endif << +!if "$(AS)" == "ml64" + @(findstr -r -c:"^MACHINE *= *x86" $(MAKEFILE) > nul && \ + (echo AS = $(AS:64=) -nologo) || \ + (echo AS = $(AS) -nologo) ) >>$(MAKEFILE) +!endif @(for %I in (cl.exe) do @set MJIT_CC=%~$$PATH:I) && (call echo MJIT_CC = "%MJIT_CC:\=/%" -nologo>>$(MAKEFILE)) @type << >>$(MAKEFILE) diff --git a/ruby/win32/win32.c b/ruby/win32/win32.c index 9c1a63f6d..c938e197a 100644 --- a/ruby/win32/win32.c +++ b/ruby/win32/win32.c @@ -42,7 +42,7 @@ #include #include #include -#if _MSC_VER >= 1400 +#if defined _MSC_VER && _MSC_VER >= 1400 #include #include #endif @@ -55,10 +55,11 @@ #include "win32/file.h" #include "id.h" #include "internal.h" +#include "internal/enc.h" +#include "internal/object.h" +#include "internal/static_assert.h" +#include "ruby/internal/stdbool.h" #include "encindex.h" -// --------- [Enclose.IO Hack start] --------- -#include "enclose_io.h" -// --------- [Enclose.IO Hack end] --------- #define isdirsep(x) ((x) == '/' || (x) == '\\') #if defined _MSC_VER && _MSC_VER <= 1200 @@ -70,10 +71,13 @@ static int w32_stati128(const char *path, struct stati128 *st, UINT cp, BOOL lst static char *w32_getenv(const char *name, UINT cp); #undef getenv +/* + * Do not remove the macros to substitute functions in dln_find.c. + */ #define DLN_FIND_EXTRA_ARG_DECL ,UINT cp #define DLN_FIND_EXTRA_ARG ,cp #define rb_w32_stati128(path, st) w32_stati128(path, st, cp, FALSE) -#define getenv(name) w32_getenv(name, cp) +#define getenv(name) w32_getenv(name, cp) /* Necessarily For dln.c */ #undef CharNext #define CharNext(p) CharNextExA(cp, (p), 0) #define dln_find_exe_r rb_w32_udln_find_exe_r @@ -87,6 +91,7 @@ static char *w32_getenv(const char *name, UINT cp); #define dln_find_exe_r(fname, path, buf, size) rb_w32_udln_find_exe_r(fname, path, buf, size, cp) #define dln_find_file_r(fname, path, buf, size) rb_w32_udln_find_file_r(fname, path, buf, size, cp) #undef CharNext /* no default cp version */ +#undef getenv #ifndef PATH_MAX # if defined MAX_PATH @@ -133,7 +138,7 @@ static FARPROC get_proc_address(const char *module, const char *func, HANDLE *mh #define RUBY_CRITICAL if (0) {} else /* just remark */ /* errno mapping */ -static struct { +static const struct { DWORD winerr; int err; } errmap[] = { @@ -692,9 +697,20 @@ rtc_error_handler(int e, const char *src, int line, const char *exe, const char #endif static CRITICAL_SECTION select_mutex; + +static CRITICAL_SECTION socklist_mutex; static st_table *socklist = NULL; + +static CRITICAL_SECTION conlist_mutex; static st_table *conlist = NULL; #define conlist_disabled ((st_table *)-1) + +#define thread_exclusive(obj) \ + for (bool exclusive_for_##obj = (EnterCriticalSection(&obj##_mutex), true); \ + exclusive_for_##obj; \ + exclusive_for_##obj = (LeaveCriticalSection(&obj##_mutex), false)) + +static CRITICAL_SECTION uenvarea_mutex; static char *uenvarea; /* License: Ruby's */ @@ -719,10 +735,12 @@ free_conlist(st_data_t key, st_data_t val, st_data_t arg) static void constat_delete(HANDLE h) { - if (conlist && conlist != conlist_disabled) { - st_data_t key = (st_data_t)h, val; - st_delete(conlist, &key, &val); - xfree((struct constat *)val); + thread_exclusive(conlist) { + if (conlist && conlist != conlist_disabled) { + st_data_t key = (st_data_t)h, val; + st_delete(conlist, &key, &val); + xfree((struct constat *)val); + } } } @@ -732,36 +750,54 @@ exit_handler(void) { WSACleanup(); DeleteCriticalSection(&select_mutex); - if (uenvarea) { - free(uenvarea); - uenvarea = NULL; + DeleteCriticalSection(&socklist_mutex); + DeleteCriticalSection(&conlist_mutex); + thread_exclusive(uenvarea) { + if (uenvarea) { + free(uenvarea); + uenvarea = NULL; + } } + DeleteCriticalSection(&uenvarea_mutex); } /* License: Ruby's */ static void vm_exit_handler(ruby_vm_t *vm) { + EnterCriticalSection(&socklist_mutex); if (socklist) { st_free_table(socklist); socklist = NULL; } + LeaveCriticalSection(&socklist_mutex); + + EnterCriticalSection(&conlist_mutex); if (conlist && conlist != conlist_disabled) { st_foreach(conlist, free_conlist, 0); st_free_table(conlist); conlist = NULL; } + LeaveCriticalSection(&conlist_mutex); } +#define ATOMIC_LONG_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval)) + /* License: Ruby's */ static void install_vm_exit_handler(void) { - static bool installed = 0; + static LONG installed = 0; + LONG i; - if (!installed) { + while ((i = ATOMIC_LONG_CAS(installed, 0, -1)) != 1) { + if (i != 0) { + Sleep(1); + continue; + } ruby_vm_at_exit(vm_exit_handler); - installed = 1; + ATOMIC_LONG_CAS(installed, -1, 1); + break; } } @@ -783,6 +819,8 @@ StartSockets(void) rb_fatal("could not find version 2 of winsock dll"); InitializeCriticalSection(&select_mutex); + InitializeCriticalSection(&socklist_mutex); + InitializeCriticalSection(&conlist_mutex); atexit(exit_handler); } @@ -795,11 +833,17 @@ StartSockets(void) static inline int socklist_insert(SOCKET sock, int flag) { - if (!socklist) { - socklist = st_init_numtable(); - install_vm_exit_handler(); + int ret; + + thread_exclusive(socklist) { + if (!socklist) { + socklist = st_init_numtable(); + install_vm_exit_handler(); + } + ret = st_insert(socklist, (st_data_t)sock, (st_data_t)flag); } - return st_insert(socklist, (st_data_t)sock, (st_data_t)flag); + + return ret; } /* License: Ruby's */ @@ -807,13 +851,14 @@ static inline int socklist_lookup(SOCKET sock, int *flagp) { st_data_t data; - int ret; + int ret = 0; - if (!socklist) - return 0; - ret = st_lookup(socklist, (st_data_t)sock, (st_data_t *)&data); - if (ret && flagp) - *flagp = (int)data; + thread_exclusive(socklist) { + if (!socklist) continue; + ret = st_lookup(socklist, (st_data_t)sock, (st_data_t *)&data); + if (ret && flagp) + *flagp = (int)data; + } return ret; } @@ -824,23 +869,31 @@ socklist_delete(SOCKET *sockp, int *flagp) { st_data_t key; st_data_t data; - int ret; + int ret = 0; - if (!socklist) - return 0; - key = (st_data_t)*sockp; - if (flagp) - data = (st_data_t)*flagp; - ret = st_delete(socklist, &key, &data); - if (ret) { - *sockp = (SOCKET)key; + thread_exclusive(socklist) { + if (!socklist) continue; + key = (st_data_t)*sockp; if (flagp) - *flagp = (int)data; + data = (st_data_t)*flagp; + ret = st_delete(socklist, &key, &data); + if (ret) { + *sockp = (SOCKET)key; + if (flagp) + *flagp = (int)data; + } } return ret; } +#if RUBY_MSVCRT_VERSION >= 80 +# ifdef __MINGW32__ +# define _CrtSetReportMode(type,mode) ((void)0) +# define _RTC_SetErrorFunc(func) ((void)0) +# endif +static void set_pioinfo_extra(void); +#endif static int w32_cmdvector(const WCHAR *, char ***, UINT, rb_encoding *); // // Initialization stuff @@ -849,14 +902,7 @@ static int w32_cmdvector(const WCHAR *, char ***, UINT, rb_encoding *); void rb_w32_sysinit(int *argc, char ***argv) { -// --------- [Enclose.IO Hack start] --------- - int new_argc; - char **new_argv; - UINT cp = CP_UTF8; - size_t i; -// --------- [Enclose.IO Hack end] --------- #if RUBY_MSVCRT_VERSION >= 80 - static void set_pioinfo_extra(void); _CrtSetReportMode(_CRT_ASSERT, 0); _set_invalid_parameter_handler(invalid_parameter); @@ -872,31 +918,13 @@ rb_w32_sysinit(int *argc, char ***argv) // *argc = w32_cmdvector(GetCommandLineW(), argv, CP_UTF8, &OnigEncodingUTF_8); -// --------- [Enclose.IO Hack start] --------- -#ifdef ENCLOSE_IO_ENTRANCE - new_argc = *argc; - new_argv = *argv; - if (NULL == getenv("ENCLOSE_IO_USE_ORIGINAL_RUBY")) { - new_argv = (char **)malloc( (*argc + 1) * sizeof(char *)); - assert(new_argv); - new_argv[0] = (*argv)[0]; - new_argv[1] = ENCLOSE_IO_ENTRANCE; - for (i = 1; i < *argc; ++i) { - new_argv[2 + i - 1] = (*argv)[i]; - } - new_argc = *argc + 1; - - *argc = new_argc; - *argv = new_argv; - } -#endif -// --------- [Enclose.IO Hack end] --------- // // Now set up the correct time stuff // tzset(); + InitializeCriticalSection(&uenvarea_mutex); init_env(); init_stdhandle(); @@ -1386,7 +1414,7 @@ w32_spawn(int mode, const char *cmd, const char *prog, UINT cp) int redir = -1; int nt; while (ISSPACE(*cmd)) cmd++; - if ((shell = getenv("RUBYSHELL")) && (redir = has_redirection(cmd, cp))) { + if ((shell = w32_getenv("RUBYSHELL", cp)) && (redir = has_redirection(cmd, cp))) { size_t shell_len = strlen(shell); char *tmp = ALLOCV(v, shell_len + strlen(cmd) + sizeof(" -c ") + 2); memcpy(tmp, shell, shell_len + 1); @@ -1394,7 +1422,7 @@ w32_spawn(int mode, const char *cmd, const char *prog, UINT cp) sprintf(tmp + shell_len, " -c \"%s\"", cmd); cmd = tmp; } - else if ((shell = getenv("COMSPEC")) && + else if ((shell = w32_getenv("COMSPEC", cp)) && (nt = !is_command_com(shell), (redir < 0 ? has_redirection(cmd, cp) : redir) || is_internal_cmd(cmd, nt))) { @@ -1515,7 +1543,7 @@ w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags, UIN if (check_spawn_mode(mode)) return -1; if (!prog) prog = argv[0]; - if ((shell = getenv("COMSPEC")) && + if ((shell = w32_getenv("COMSPEC", cp)) && internal_cmd_match(prog, tmpnt = !is_command_com(shell))) { ntcmd = tmpnt; prog = shell; @@ -1590,7 +1618,7 @@ rb_w32_uaspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags) rb_pid_t rb_w32_aspawn(int mode, const char *prog, char *const *argv) { - return rb_w32_aspawn_flags(mode, prog, argv, 0); + return w32_aspawn_flags(mode, prog, argv, 0, filecp()); } /* License: Ruby's */ @@ -1892,9 +1920,6 @@ w32_cmdvector(const WCHAR *cmd, char ***vec, UINT cp, rb_encoding *enc) curr = (NtCmdLineElement *)calloc(sizeof(NtCmdLineElement), 1); if (!curr) goto do_nothing; curr->str = rb_w32_wstr_to_mbstr(cp, base, len, &curr->len); -// --------- [Enclose.IO Hack start] --------- - if (curr->str && (curr->str = realloc(curr->str, curr->len + 1))) { curr->str[curr->len] = '\0'; } -// --------- [Enclose.IO Hack end] --------- curr->flags |= NTMALLOC; if (globbing && (tail = cmdglob(curr, cmdtail, cp, enc))) { @@ -1979,6 +2004,7 @@ get_final_path_fail(HANDLE f, WCHAR *buf, DWORD len, DWORD flag) static DWORD WINAPI get_final_path_unknown(HANDLE f, WCHAR *buf, DWORD len, DWORD flag) { + /* Since Windows Vista and Windows Server 2008 */ get_final_path_func func = (get_final_path_func) get_proc_address("kernel32", "GetFinalPathNameByHandleW", NULL); if (!func) func = get_final_path_fail; @@ -2013,12 +2039,16 @@ open_special(const WCHAR *path, DWORD access, DWORD flags) #define BitOfIsRep(n) ((n) * 2 + 1) #define DIRENT_PER_CHAR (CHAR_BIT / 2) +static const WCHAR namespace_prefix[] = {L'\\', L'\\', L'?', L'\\'}; + +enum {FINAL_PATH_MAX = PATH_MAX + numberof(namespace_prefix)}; + /* License: Artistic or GPL */ static HANDLE open_dir_handle(const WCHAR *filename, WIN32_FIND_DATAW *fd) { HANDLE fh; - WCHAR fullname[PATH_MAX + rb_strlen_lit("\\*")]; + WCHAR fullname[FINAL_PATH_MAX + rb_strlen_lit("\\*")]; WCHAR *p; int len = 0; @@ -2028,8 +2058,12 @@ open_dir_handle(const WCHAR *filename, WIN32_FIND_DATAW *fd) fh = open_special(filename, 0, 0); if (fh != INVALID_HANDLE_VALUE) { - len = get_final_path(fh, fullname, PATH_MAX, 0); + len = get_final_path(fh, fullname, FINAL_PATH_MAX, 0); CloseHandle(fh); + if (len >= FINAL_PATH_MAX) { + errno = ENAMETOOLONG; + return INVALID_HANDLE_VALUE; + } } if (!len) { len = lstrlenW(filename); @@ -2294,7 +2328,7 @@ rb_w32_conv_from_wstr(const WCHAR *wstr, long *lenp, rb_encoding *enc) long len; char *ptr; - if (NIL_P(str)) return wstr_to_filecp(wstr, lenp); + if (NIL_P(str)) return wstr_to_utf8(wstr, lenp); *lenp = len = RSTRING_LEN(str); memcpy(ptr = malloc(len + 1), RSTRING_PTR(str), len); ptr[len] = '\0'; @@ -2319,7 +2353,7 @@ ruby_direct_conv(const WCHAR *file, const WCHAR *alt, struct direct *entry, cons static struct direct * readdir_internal(DIR *dirp, BOOL (*conv)(const WCHAR *, const WCHAR *, struct direct *, const void *), const void *enc) { - static int dummy = 0; + static long dummy_ino = 0; if (dirp->curr) { @@ -2337,7 +2371,7 @@ readdir_internal(DIR *dirp, BOOL (*conv)(const WCHAR *, const WCHAR *, struct di // // Fake inode // - dirp->dirstr.d_ino = dummy++; + dirp->dirstr.d_ino = (ino_t)(InterlockedIncrement(&dummy_ino) - 1); // // Attributes @@ -2380,6 +2414,14 @@ rb_w32_readdir(DIR *dirp, rb_encoding *enc) return readdir_internal(dirp, ruby_direct_conv, enc); } +/* License: Ruby's */ +struct direct * +rb_w32_ureaddir(DIR *dirp) +{ + const UINT cp = CP_UTF8; + return readdir_internal(dirp, win32_direct_conv, &cp); +} + // // Telldir returns the current string pointer position // @@ -2537,7 +2579,7 @@ set_pioinfo_extra(void) char *pend = p; /* _osfile(fh) & FDEV */ -# if _WIN64 +# ifdef _WIN64 int32_t rel; char *rip; /* add rsp, _ */ @@ -2562,7 +2604,7 @@ set_pioinfo_extra(void) for (pend += 10; pend < p + 300; pend++) { // find end of function if (memcmp(pend, FUNCTION_BEFORE_RET_MARK, sizeof(FUNCTION_BEFORE_RET_MARK) - 1) == 0 && - *(pend + (sizeof(FUNCTION_BEFORE_RET_MARK) - 1) + FUNCTION_SKIP_BYTES) & FUNCTION_RET == FUNCTION_RET) { + (*(pend + (sizeof(FUNCTION_BEFORE_RET_MARK) - 1) + FUNCTION_SKIP_BYTES) & FUNCTION_RET) == FUNCTION_RET) { // search backwards from end of function for (pend -= (sizeof(PIOINFO_MARK) - 1); pend > p; pend--) { if (memcmp(pend, PIOINFO_MARK, sizeof(PIOINFO_MARK) - 1) == 0) { @@ -2579,7 +2621,7 @@ set_pioinfo_extra(void) found: p += sizeof(PIOINFO_MARK) - 1; -#if _WIN64 +#ifdef _WIN64 rel = *(int32_t*)(p); rip = p + sizeof(int32_t); __pioinfo = (ioinfo**)(rip + rel); @@ -2703,6 +2745,17 @@ init_stdhandle(void) } if (nullfd >= 0 && !keep) close(nullfd); setvbuf(stderr, NULL, _IONBF, 0); + + { + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD m; + if (GetConsoleMode(h, &m)) { +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4 +#endif + SetConsoleMode(h, m | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + } + } } #undef getsockopt @@ -2879,7 +2932,7 @@ rb_w32_fdisset(int fd, fd_set *set) SOCKET s = TO_SOCKET(fd); if (s == (SOCKET)INVALID_HANDLE_VALUE) return 0; - RUBY_CRITICAL(ret = __WSAFDIsSet(s, set)); + RUBY_CRITICAL {ret = __WSAFDIsSet(s, set);} return ret; } @@ -3083,9 +3136,9 @@ do_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, } else { RUBY_CRITICAL { - EnterCriticalSection(&select_mutex); - r = select(nfds, rd, wr, ex, timeout); - LeaveCriticalSection(&select_mutex); + thread_exclusive(select) { + r = select(nfds, rd, wr, ex, timeout); + } if (r == SOCKET_ERROR) { errno = map_errno(WSAGetLastError()); r = -1; @@ -3286,12 +3339,12 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, /* License: Ruby's */ static FARPROC -get_wsa_extension_function(SOCKET s, GUID *guid) +get_wsa_extension_function(SOCKET s, GUID guid) { DWORD dmy; FARPROC ptr = NULL; - WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, guid, sizeof(*guid), + WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &ptr, sizeof(ptr), &dmy, NULL, NULL); if (!ptr) errno = ENOSYS; @@ -3662,8 +3715,8 @@ recvmsg(int fd, struct msghdr *msg, int flags) s = TO_SOCKET(fd); if (!pWSARecvMsg) { - static GUID guid = WSAID_WSARECVMSG; - pWSARecvMsg = (WSARecvMsg_t)get_wsa_extension_function(s, &guid); + static const GUID guid = WSAID_WSARECVMSG; + pWSARecvMsg = (WSARecvMsg_t)get_wsa_extension_function(s, guid); if (!pWSARecvMsg) return -1; } @@ -3717,8 +3770,8 @@ sendmsg(int fd, const struct msghdr *msg, int flags) s = TO_SOCKET(fd); if (!pWSASendMsg) { - static GUID guid = WSAID_WSASENDMSG; - pWSASendMsg = (WSASendMsg_t)get_wsa_extension_function(s, &guid); + static const GUID guid = WSAID_WSASENDMSG; + pWSASendMsg = (WSASendMsg_t)get_wsa_extension_function(s, guid); if (!pWSASendMsg) return -1; } @@ -4216,6 +4269,7 @@ freeifaddrs(struct ifaddrs *ifp) } #endif +#if 0 // Have never been used // // Networking stubs // @@ -4242,6 +4296,7 @@ void setnetent (int stayopen) {} void setprotoent (int stayopen) {} void setservent (int stayopen) {} +#endif /* License: Ruby's */ static int @@ -4776,7 +4831,6 @@ static void * getcwd_value(int size, void *arg) { VALUE str = *(VALUE *)arg = rb_utf8_str_new(0, size - 1); - OBJ_TAINT(str); return RSTRING_PTR(str); } @@ -5055,7 +5109,7 @@ rb_w32_read_reparse_point(const WCHAR *path, rb_w32_reparse_buffer_t *rp, *len = ret / sizeof(WCHAR); } else if (rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - static const WCHAR *volume = L"Volume{"; + static const WCHAR volume[] = L"Volume{"; enum {volume_prefix_len = rb_strlen_lit("\\??\\")}; name = ((char *)rp->MountPointReparseBuffer.PathBuffer + rp->MountPointReparseBuffer.SubstituteNameOffset + @@ -5156,6 +5210,7 @@ w32_symlink(UINT cp, const char *src, const char *link) static DWORD create_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; if (create_symbolic_link == (create_symbolic_link_func)-1) { + /* Since Windows Vista and Windows Server 2008 */ create_symbolic_link = (create_symbolic_link_func) get_proc_address("kernel32", "CreateSymbolicLinkW", NULL); } @@ -5216,7 +5271,7 @@ symlink(const char *src, const char *link) } /* License: Ruby's */ -int +rb_pid_t wait(int *status) { return waitpid(-1, status, 0); @@ -5228,32 +5283,43 @@ w32_getenv(const char *name, UINT cp) { WCHAR *wenvarea, *wenv; int len = strlen(name); - char *env; + char *env, *found = NULL; int wlen; if (len == 0) return NULL; - if (uenvarea) { - free(uenvarea); - uenvarea = NULL; - } - wenvarea = GetEnvironmentStringsW(); - if (!wenvarea) { - map_errno(GetLastError()); - return NULL; + if (!NTLoginName) { + /* initialized in init_env, uenvarea_mutex should have been + * initialized before it */ + return getenv(name); } - for (wenv = wenvarea, wlen = 1; *wenv; wenv += lstrlenW(wenv) + 1) - wlen += lstrlenW(wenv) + 1; - uenvarea = wstr_to_mbstr(cp, wenvarea, wlen, NULL); - FreeEnvironmentStringsW(wenvarea); - if (!uenvarea) - return NULL; - for (env = uenvarea; *env; env += strlen(env) + 1) - if (strncasecmp(env, name, len) == 0 && *(env + len) == '=') - return env + len + 1; + thread_exclusive(uenvarea) { + if (uenvarea) { + free(uenvarea); + uenvarea = NULL; + } + wenvarea = GetEnvironmentStringsW(); + if (!wenvarea) { + map_errno(GetLastError()); + continue; + } + for (wenv = wenvarea, wlen = 1; *wenv; wenv += lstrlenW(wenv) + 1) + wlen += lstrlenW(wenv) + 1; + uenvarea = wstr_to_mbstr(cp, wenvarea, wlen, NULL); + FreeEnvironmentStringsW(wenvarea); + if (!uenvarea) + continue; - return NULL; + for (env = uenvarea; *env; env += strlen(env) + 1) { + if (strncasecmp(env, name, len) == 0 && *(env + len) == '=') { + found = env + len + 1; + break; + } + } + } + + return found; } /* License: Ruby's */ @@ -5279,11 +5345,13 @@ get_attr_vsn(const WCHAR *path, DWORD *atts, DWORD *vsn) HANDLE h = open_special(path, 0, FILE_FLAG_OPEN_REPARSE_POINT); if (h == INVALID_HANDLE_VALUE) { - ASSUME(e = GetLastError()); + e = GetLastError(); + ASSUME(e); return e; } if (!GetFileInformationByHandle(h, &st)) { - ASSUME(e = GetLastError()); + e = GetLastError(); + ASSUME(e); } else { *atts = st.dwFileAttributes; @@ -5298,7 +5366,7 @@ static int wrename(const WCHAR *oldpath, const WCHAR *newpath) { int res = 0; - DWORD oldatts, newatts = (DWORD)-1; + DWORD oldatts = 0, newatts = (DWORD)-1; DWORD oldvsn = 0, newvsn = 0, e; e = get_attr_vsn(oldpath, &oldatts, &oldvsn); @@ -5476,6 +5544,7 @@ get_ino(HANDLE h, FILE_ID_INFO *id) static gfibhe_t pGetFileInformationByHandleEx = (gfibhe_t)-1; if (pGetFileInformationByHandleEx == (gfibhe_t)-1) + /* Since Windows Vista and Windows Server 2008 */ pGetFileInformationByHandleEx = (gfibhe_t)get_proc_address("kernel32", "GetFileInformationByHandleEx", NULL); if (pGetFileInformationByHandleEx) { @@ -5670,8 +5739,6 @@ path_drive(const WCHAR *path) towupper(path[0]) - L'A' : _getdrive() - 1; } -static const WCHAR namespace_prefix[] = {L'\\', L'\\', L'?', L'\\'}; - /* License: Ruby's */ static int winnt_stat(const WCHAR *path, struct stati128 *st, BOOL lstat) @@ -5719,7 +5786,7 @@ rb_w32_stat(const char *path, struct stat *st) { struct stati128 tmp; - if (rb_w32_stati128(path, &tmp)) return -1; + if (w32_stati128(path, &tmp, filecp(), FALSE)) return -1; COPY_STAT(tmp, *st, (_off_t)); return 0; } @@ -5836,11 +5903,11 @@ rb_w32_lseek(int fd, off_t ofs, int whence) } /* License: Ruby's */ -int -rb_w32_access(const char *path, int mode) +static int +w32_access(const char *path, int mode, UINT cp) { struct stati128 stat; - if (rb_w32_stati128(path, &stat) != 0) + if (w32_stati128(path, &stat, cp, FALSE) != 0) return -1; mode <<= 6; if ((stat.st_mode & mode) != mode) { @@ -5850,19 +5917,18 @@ rb_w32_access(const char *path, int mode) return 0; } +/* License: Ruby's */ +int +rb_w32_access(const char *path, int mode) +{ + return w32_access(path, mode, filecp()); +} + /* License: Ruby's */ int rb_w32_uaccess(const char *path, int mode) { - struct stati128 stat; - if (rb_w32_ustati128(path, &stat) != 0) - return -1; - mode <<= 6; - if ((stat.st_mode & mode) != mode) { - errno = EACCES; - return -1; - } - return 0; + return w32_access(path, mode, CP_UTF8); } /* License: Ruby's */ @@ -6257,10 +6323,7 @@ w32_wopen(const WCHAR *file, int oflag, int pmode) share_delete = oflag & O_SHARE_DELETE ? FILE_SHARE_DELETE : 0; oflag &= ~O_SHARE_DELETE; -// --------- [Enclose.IO Hack start] --------- -// TODO: https://github.com/pmq20/ruby-packer/issues/118 - if (enclose_io_if_w(file) || (oflag & O_TEXT) || !(oflag & O_BINARY)) { -// --------- [Enclose.IO Hack end] --------- + if ((oflag & O_TEXT) || !(oflag & O_BINARY)) { fd = _wopen(file, oflag, pmode); if (fd == -1) { switch (errno) { @@ -6445,7 +6508,7 @@ rb_w32_fclose(FILE *fp) int rb_w32_pipe(int fds[2]) { - static DWORD serial = 0; + static long serial = 0; static const char prefix[] = "\\\\.\\pipe\\ruby"; enum { width_of_prefix = (int)sizeof(prefix) - 1, @@ -6461,7 +6524,7 @@ rb_w32_pipe(int fds[2]) memcpy(name, prefix, width_of_prefix); snprintf(name + width_of_prefix, width_of_ids, "%.*"PRI_PIDT_PREFIX"x-%.*lx", - width_of_pid, rb_w32_getpid(), width_of_serial, serial++); + width_of_pid, rb_w32_getpid(), width_of_serial, InterlockedIncrement(&serial)-1); sec.nLength = sizeof(sec); sec.lpSecurityDescriptor = NULL; @@ -6563,32 +6626,34 @@ static struct constat * constat_handle(HANDLE h) { st_data_t data; - struct constat *p; - if (!conlist) { - if (console_emulator_p()) { - conlist = conlist_disabled; - return NULL; + struct constat *p = NULL; + thread_exclusive(conlist) { + if (!conlist) { + if (console_emulator_p()) { + conlist = conlist_disabled; + continue; + } + conlist = st_init_numtable(); + install_vm_exit_handler(); } - conlist = st_init_numtable(); - install_vm_exit_handler(); - } - else if (conlist == conlist_disabled) { - return NULL; - } - if (st_lookup(conlist, (st_data_t)h, &data)) { - p = (struct constat *)data; - } - else { - CONSOLE_SCREEN_BUFFER_INFO csbi; - p = ALLOC(struct constat); - p->vt100.state = constat_init; - p->vt100.attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; - p->vt100.reverse = 0; - p->vt100.saved.X = p->vt100.saved.Y = 0; - if (GetConsoleScreenBufferInfo(h, &csbi)) { - p->vt100.attr = csbi.wAttributes; + else if (conlist == conlist_disabled) { + continue; + } + if (st_lookup(conlist, (st_data_t)h, &data)) { + p = (struct constat *)data; + } + else { + CONSOLE_SCREEN_BUFFER_INFO csbi; + p = ALLOC(struct constat); + p->vt100.state = constat_init; + p->vt100.attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; + p->vt100.reverse = 0; + p->vt100.saved.X = p->vt100.saved.Y = 0; + if (GetConsoleScreenBufferInfo(h, &csbi)) { + p->vt100.attr = csbi.wAttributes; + } + st_insert(conlist, (st_data_t)h, (st_data_t)p); } - st_insert(conlist, (st_data_t)h, (st_data_t)p); } return p; } @@ -6599,10 +6664,12 @@ constat_reset(HANDLE h) { st_data_t data; struct constat *p; - if (!conlist || conlist == conlist_disabled) return; - if (!st_lookup(conlist, (st_data_t)h, &data)) return; - p = (struct constat *)data; - p->vt100.state = constat_init; + thread_exclusive(conlist) { + if (!conlist || conlist == conlist_disabled) continue; + if (!st_lookup(conlist, (st_data_t)h, &data)) continue; + p = (struct constat *)data; + p->vt100.state = constat_init; + } } #define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY) @@ -7033,10 +7100,7 @@ rb_w32_read(int fd, void *buf, size_t size) return -1; } -// --------- [Enclose.IO Hack start] --------- -// TODO: https://github.com/pmq20/ruby-packer/issues/118 - if (SQUASH_VALID_VFD(fd) || (_osfile(fd) & FTEXT)) { -// --------- [Enclose.IO Hack end] --------- + if (_osfile(fd) & FTEXT) { return _read(fd, buf, size); } @@ -7297,7 +7361,7 @@ rb_w32_write_console(uintptr_t strarg, int fd) break; } reslen = 0; - if (dwMode & 4) { /* ENABLE_VIRTUAL_TERMINAL_PROCESSING */ + if (dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) { if (!WriteConsoleW(handle, ptr, len, &reslen, NULL)) reslen = (DWORD)-1L; } @@ -7407,6 +7471,20 @@ wutimensat(int dirfd, const WCHAR *path, const struct timespec *times, int flags return ret; } +/* License: Ruby's */ +static int +w32_utimensat(int dirfd, const char *path, const struct timespec *times, int flags, UINT cp) +{ + WCHAR *wpath = mbstr_to_wstr(cp, path, -1, NULL); + int ret = -1; + + if (wpath) { + ret = wutimensat(dirfd, wpath, times, flags); + free(wpath); + } + return ret; +} + /* License: Ruby's */ int rb_w32_uutime(const char *path, const struct utimbuf *times) @@ -7417,7 +7495,7 @@ rb_w32_uutime(const char *path, const struct utimbuf *times) ts[0].tv_nsec = 0; ts[1].tv_sec = times->modtime; ts[1].tv_nsec = 0; - return rb_w32_uutimensat(AT_FDCWD, path, ts, 0); + return w32_utimensat(AT_FDCWD, path, ts, 0, CP_UTF8); } /* License: Ruby's */ @@ -7430,7 +7508,7 @@ rb_w32_utime(const char *path, const struct utimbuf *times) ts[0].tv_nsec = 0; ts[1].tv_sec = times->modtime; ts[1].tv_nsec = 0; - return rb_w32_utimensat(AT_FDCWD, path, ts, 0); + return w32_utimensat(AT_FDCWD, path, ts, 0, filecp()); } /* License: Ruby's */ @@ -7443,7 +7521,7 @@ rb_w32_uutimes(const char *path, const struct timeval *times) ts[0].tv_nsec = times[0].tv_usec * 1000; ts[1].tv_sec = times[1].tv_sec; ts[1].tv_nsec = times[1].tv_usec * 1000; - return rb_w32_uutimensat(AT_FDCWD, path, ts, 0); + return w32_utimensat(AT_FDCWD, path, ts, 0, CP_UTF8); } /* License: Ruby's */ @@ -7456,35 +7534,21 @@ rb_w32_utimes(const char *path, const struct timeval *times) ts[0].tv_nsec = times[0].tv_usec * 1000; ts[1].tv_sec = times[1].tv_sec; ts[1].tv_nsec = times[1].tv_usec * 1000; - return rb_w32_utimensat(AT_FDCWD, path, ts, 0); + return w32_utimensat(AT_FDCWD, path, ts, 0, filecp()); } /* License: Ruby's */ int rb_w32_uutimensat(int dirfd, const char *path, const struct timespec *times, int flags) { - WCHAR *wpath; - int ret; - - if (!(wpath = utf8_to_wstr(path, NULL))) - return -1; - ret = wutimensat(dirfd, wpath, times, flags); - free(wpath); - return ret; + return w32_utimensat(dirfd, path, times, flags, CP_UTF8); } /* License: Ruby's */ int rb_w32_utimensat(int dirfd, const char *path, const struct timespec *times, int flags) { - WCHAR *wpath; - int ret; - - if (!(wpath = filecp_to_wstr(path, NULL))) - return -1; - ret = wutimensat(dirfd, wpath, times, flags); - free(wpath); - return ret; + return w32_utimensat(dirfd, path, times, flags, filecp()); } /* License: Ruby's */ @@ -7694,6 +7758,7 @@ fchmod(int fd, int mode) return -1; } if (set_file_info == (set_file_information_by_handle_func)-1) { + /* Since Windows Vista and Windows Server 2008 */ set_file_info = (set_file_information_by_handle_func) get_proc_address("kernel32", "SetFileInformationByHandle", NULL); } @@ -8100,6 +8165,7 @@ rb_w32_set_thread_description(HANDLE th, const WCHAR *name) static set_thread_description_func set_thread_description = (set_thread_description_func)-1; if (set_thread_description == (set_thread_description_func)-1) { + /* Since Windows 10, version 1607 and Windows Server 2016 */ set_thread_description = (set_thread_description_func) get_proc_address("kernel32", "SetThreadDescription", NULL); } diff --git a/ruby/yjit.c b/ruby/yjit.c new file mode 100644 index 000000000..e4fa84d51 --- /dev/null +++ b/ruby/yjit.c @@ -0,0 +1,187 @@ +// YJIT combined compilation unit. This setup allows spreading functions +// across different files without having to worry about putting things +// in headers and prefixing function names. +#include "internal.h" +#include "vm_core.h" +#include "vm_callinfo.h" +#include "builtin.h" +#include "insns.inc" +#include "insns_info.inc" +#include "vm_sync.h" +#include "yjit.h" + +#ifndef YJIT_CHECK_MODE +# define YJIT_CHECK_MODE 0 +#endif + +// >= 1: print when output code invalidation happens +// >= 2: dump list of instructions when regions compile +#ifndef YJIT_DUMP_MODE +# define YJIT_DUMP_MODE 0 +#endif + +// USE_MJIT comes from configure options +#define JIT_ENABLED USE_MJIT + +// Check if we need to include YJIT in the build +#if JIT_ENABLED && YJIT_SUPPORTED_P + +#include "yjit_asm.c" + +// Code block into which we write machine code +static codeblock_t block; +static codeblock_t *cb = NULL; + +// Code block into which we write out-of-line machine code +static codeblock_t outline_block; +static codeblock_t *ocb = NULL; + +#if YJIT_STATS +// Comments for generated code +struct yjit_comment { + uint32_t offset; + const char *comment; +}; + +typedef rb_darray(struct yjit_comment) yjit_comment_array_t; +static yjit_comment_array_t yjit_code_comments; + +// Counters for generated code +#define YJIT_DECLARE_COUNTERS(...) struct rb_yjit_runtime_counters { \ + int64_t __VA_ARGS__; \ +}; \ +static char yjit_counter_names[] = #__VA_ARGS__; + +YJIT_DECLARE_COUNTERS( + exec_instruction, + + send_keywords, + send_kw_splat, + send_args_splat, + send_block_arg, + send_ivar_set_method, + send_zsuper_method, + send_undef_method, + send_optimized_method, + send_optimized_method_send, + send_optimized_method_call, + send_optimized_method_block_call, + send_missing_method, + send_bmethod, + send_refined_method, + send_cfunc_ruby_array_varg, + send_cfunc_argc_mismatch, + send_cfunc_toomany_args, + send_cfunc_tracing, + send_cfunc_kwargs, + send_attrset_kwargs, + send_iseq_tailcall, + send_iseq_arity_error, + send_iseq_only_keywords, + send_iseq_kwargs_req_and_opt_missing, + send_iseq_kwargs_mismatch, + send_iseq_complex_callee, + send_not_implemented_method, + send_getter_arity, + send_se_cf_overflow, + send_se_protected_check_failed, + + traced_cfunc_return, + + invokesuper_me_changed, + invokesuper_block, + + leave_se_interrupt, + leave_interp_return, + leave_start_pc_non_zero, + + getivar_se_self_not_heap, + getivar_idx_out_of_range, + getivar_megamorphic, + + setivar_se_self_not_heap, + setivar_idx_out_of_range, + setivar_val_heapobject, + setivar_name_not_mapped, + setivar_not_object, + setivar_frozen, + + oaref_argc_not_one, + oaref_arg_not_fixnum, + + opt_getinlinecache_miss, + + binding_allocations, + binding_set, + + vm_insns_count, + compiled_iseq_count, + compiled_block_count, + compilation_failure, + + exit_from_branch_stub, + + invalidation_count, + invalidate_method_lookup, + invalidate_bop_redefined, + invalidate_ractor_spawn, + invalidate_constant_state_bump, + invalidate_constant_ic_fill, + + constant_state_bumps, + + expandarray_splat, + expandarray_postarg, + expandarray_not_array, + expandarray_rhs_too_small, + + gbpp_block_param_modified, + gbpp_block_handler_not_iseq, + + // Member with known name for iterating over counters + last_member +) + +static struct rb_yjit_runtime_counters yjit_runtime_counters = { 0 }; +#undef YJIT_DECLARE_COUNTERS + +#endif // YJIT_STATS + +// The number of bytes counting from the beginning of the inline code block +// that should not be changed. After patching for global invalidation, no one +// should make changes to the invalidated code region anymore. This is used to +// break out of invalidation race when there are multiple ractors. +static uint32_t yjit_codepage_frozen_bytes = 0; + +#include "yjit_utils.c" +#include "yjit_core.c" +#include "yjit_iface.c" +#include "yjit_codegen.c" + +#else +// !JIT_ENABLED || !YJIT_SUPPORTED_P +// In these builds, YJIT could never be turned on. Provide dummy +// implementations for YJIT functions exposed to the rest of the code base. +// See yjit.h. + +void Init_builtin_yjit(void) {} +bool rb_yjit_enabled_p(void) { return false; } +unsigned rb_yjit_call_threshold(void) { return UINT_MAX; } +void rb_yjit_invalidate_all_method_lookup_assumptions(void) {}; +void rb_yjit_method_lookup_change(VALUE klass, ID mid) {}; +void rb_yjit_cme_invalidate(VALUE cme) {} +void rb_yjit_collect_vm_usage_insn(int insn) {} +void rb_yjit_collect_binding_alloc(void) {} +void rb_yjit_collect_binding_set(void) {} +bool rb_yjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec) { return false; } +void rb_yjit_init(struct rb_yjit_options *options) {} +void rb_yjit_bop_redefined(VALUE klass, const rb_method_entry_t *me, enum ruby_basic_operators bop) {} +void rb_yjit_constant_state_changed(void) {} +void rb_yjit_iseq_mark(const struct rb_iseq_constant_body *body) {} +void rb_yjit_iseq_update_references(const struct rb_iseq_constant_body *body) {} +void rb_yjit_iseq_free(const struct rb_iseq_constant_body *body) {} +void rb_yjit_before_ractor_spawn(void) {} +void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic) {} +void rb_yjit_tracing_invalidate_all(void) {} + +#endif // if JIT_ENABLED && YJIT_SUPPORTED_P diff --git a/ruby/yjit.h b/ruby/yjit.h new file mode 100644 index 000000000..6f66f59f0 --- /dev/null +++ b/ruby/yjit.h @@ -0,0 +1,73 @@ +#ifndef YJIT_H +#define YJIT_H 1 +// +// This file contains definitions YJIT exposes to the CRuby codebase +// + +#include "ruby/internal/config.h" +#include "ruby_assert.h" // for RUBY_DEBUG +#include "vm_core.h" +#include "method.h" + +// YJIT_STATS controls whether to support runtime counters in generated code +// and in the interpreter. +#ifndef YJIT_STATS +# define YJIT_STATS RUBY_DEBUG +#endif + +// We generate x86 assembly and rely on mmap(2). +#if defined(__x86_64__) && !defined(_WIN32) +# define YJIT_SUPPORTED_P 1 +#else +# define YJIT_SUPPORTED_P 0 +#endif + +struct rb_yjit_options { + // Enable compilation with YJIT + bool yjit_enabled; + + // Size of the executable memory block to allocate in MiB + unsigned exec_mem_size; + + // Number of method calls after which to start generating code + // Threshold==1 means compile on first execution + unsigned call_threshold; + + // Generate versions greedily until the limit is hit + bool greedy_versioning; + + // Disable the propagation of type information + bool no_type_prop; + + // Maximum number of versions per block + // 1 means always create generic versions + unsigned max_versions; + + // Capture and print out stats + bool gen_stats; + + // Run backend tests + bool test_backend; +}; + +bool rb_yjit_enabled_p(void); +unsigned rb_yjit_call_threshold(void); + +void rb_yjit_invalidate_all_method_lookup_assumptions(void); +void rb_yjit_method_lookup_change(VALUE klass, ID mid); +void rb_yjit_cme_invalidate(VALUE cme); +void rb_yjit_collect_vm_usage_insn(int insn); +void rb_yjit_collect_binding_alloc(void); +void rb_yjit_collect_binding_set(void); +bool rb_yjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec); +void rb_yjit_init(struct rb_yjit_options *options); +void rb_yjit_bop_redefined(VALUE klass, const rb_method_entry_t *me, enum ruby_basic_operators bop); +void rb_yjit_constant_state_changed(void); +void rb_yjit_iseq_mark(const struct rb_iseq_constant_body *body); +void rb_yjit_iseq_update_references(const struct rb_iseq_constant_body *body); +void rb_yjit_iseq_free(const struct rb_iseq_constant_body *body); +void rb_yjit_before_ractor_spawn(void); +void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic); +void rb_yjit_tracing_invalidate_all(void); + +#endif // #ifndef YJIT_H diff --git a/ruby/yjit.rb b/ruby/yjit.rb new file mode 100644 index 000000000..0bc353992 --- /dev/null +++ b/ruby/yjit.rb @@ -0,0 +1,279 @@ +# frozen_string_literal: true + +# This module allows for introspection of YJIT, CRuby's experimental in-process +# just-in-time compiler. This module exists only to help develop YJIT, as such, +# everything in the module is highly implementation specific and comes with no +# API stability guarantee whatsoever. +# +# This module may not exist if YJIT does not support the particular platform +# for which CRuby is built. There is also no API stability guarantee as to in +# what situations this module is defined. +module RubyVM::YJIT + if defined?(Disasm) + def self.disasm(iseq, tty: $stdout && $stdout.tty?) + iseq = RubyVM::InstructionSequence.of(iseq) + + blocks = blocks_for(iseq) + return if blocks.empty? + + str = String.new + str << iseq.disasm + str << "\n" + + # Sort the blocks by increasing addresses + sorted_blocks = blocks.sort_by(&:address) + + highlight = ->(str) { + if tty + "\x1b[1m#{str}\x1b[0m" + else + str + end + } + + cs = Disasm.new + sorted_blocks.each_with_index do |block, i| + str << "== BLOCK #{i+1}/#{blocks.length}: #{block.code.length} BYTES, ISEQ RANGE [#{block.iseq_start_index},#{block.iseq_end_index}) ".ljust(80, "=") + str << "\n" + + comments = comments_for(block.address, block.address + block.code.length) + comment_idx = 0 + cs.disasm(block.code, block.address).each do |i| + while (comment = comments[comment_idx]) && comment.address <= i.address + str << " ; #{highlight.call(comment.comment)}\n" + comment_idx += 1 + end + + str << sprintf( + " %
      08x: %s\t%
      s\n", + address: i.address, + instruction: i.mnemonic, + details: i.op_str + ) + end + end + + block_sizes = blocks.map { |block| block.code.length } + total_bytes = block_sizes.sum + str << "\n" + str << "Total code size: #{total_bytes} bytes" + str << "\n" + + str + end + + def self.comments_for(start_address, end_address) + Primitive.comments_for(start_address, end_address) + end + + def self.graphviz_for(iseq) + iseq = RubyVM::InstructionSequence.of(iseq) + cs = Disasm.new + + highlight = ->(comment) { "#{comment}" } + linebreak = "
      \n" + + buff = +'' + blocks = blocks_for(iseq).sort_by(&:id) + buff << "digraph g {\n" + + # Write the iseq info as a legend + buff << " legend [shape=record fontsize=\"30\" fillcolor=\"lightgrey\" style=\"filled\"];\n" + buff << " legend [label=\"{ Instruction Disassembly For: | {#{iseq.base_label}@#{iseq.absolute_path}:#{iseq.first_lineno}}}\"];\n" + + # Subgraph contains disassembly + buff << " subgraph disasm {\n" + buff << " node [shape=record fontname=\"courier\"];\n" + buff << " edge [fontname=\"courier\" penwidth=3];\n" + blocks.each do |block| + disasm = disasm_block(cs, block, highlight) + + # convert newlines to breaks that graphviz understands + disasm.gsub!(/\n/, linebreak) + + # strip leading whitespace + disasm.gsub!(/^\s+/, '') + + buff << "b#{block.id} [label=<#{disasm}>];\n" + buff << block.outgoing_ids.map { |id| + next_block = blocks.bsearch { |nb| id <=> nb.id } + if next_block.address == (block.address + block.code.length) + "b#{block.id} -> b#{id}[label=\"Fall\"];" + else + "b#{block.id} -> b#{id}[label=\"Jump\" style=dashed];" + end + }.join("\n") + buff << "\n" + end + buff << " }" + buff << "}" + buff + end + + def self.disasm_block(cs, block, highlight) + comments = comments_for(block.address, block.address + block.code.length) + comment_idx = 0 + str = +'' + cs.disasm(block.code, block.address).each do |i| + while (comment = comments[comment_idx]) && comment.address <= i.address + str << " ; #{highlight.call(comment.comment)}\n" + comment_idx += 1 + end + + str << sprintf( + " %
      08x: %s\t%
      s\n", + address: i.address, + instruction: i.mnemonic, + details: i.op_str + ) + end + str + end + end + + # Return a hash for statistics generated for the --yjit-stats command line option. + # Return nil when option is not passed or unavailable. + def self.runtime_stats + # defined in yjit_iface.c + Primitive.get_yjit_stats + end + + # Discard statistics collected for --yjit-stats. + def self.reset_stats! + # defined in yjit_iface.c + Primitive.reset_stats_bang + end + + def self.stats_enabled? + Primitive.yjit_stats_enabled_p + end + + def self.enabled? + Primitive.cexpr! 'rb_yjit_enabled_p() ? Qtrue : Qfalse' + end + + def self.simulate_oom! + Primitive.simulate_oom_bang + end + + # Avoid calling a method here to not interfere with compilation tests + if Primitive.yjit_stats_enabled_p + at_exit { _print_stats } + end + + class << self + private + + # Format and print out counters + def _print_stats + stats = runtime_stats + return unless stats + + $stderr.puts("***YJIT: Printing YJIT statistics on exit***") + + print_counters(stats, prefix: 'send_', prompt: 'method call exit reasons: ') + print_counters(stats, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons: ') + print_counters(stats, prefix: 'leave_', prompt: 'leave exit reasons: ') + print_counters(stats, prefix: 'gbpp_', prompt: 'getblockparamproxy exit reasons: ') + print_counters(stats, prefix: 'getivar_', prompt: 'getinstancevariable exit reasons:') + print_counters(stats, prefix: 'setivar_', prompt: 'setinstancevariable exit reasons:') + print_counters(stats, prefix: 'oaref_', prompt: 'opt_aref exit reasons: ') + print_counters(stats, prefix: 'expandarray_', prompt: 'expandarray exit reasons: ') + print_counters(stats, prefix: 'opt_getinlinecache_', prompt: 'opt_getinlinecache exit reasons: ') + print_counters(stats, prefix: 'invalidate_', prompt: 'invalidation reasons: ') + + side_exits = total_exit_count(stats) + total_exits = side_exits + stats[:leave_interp_return] + + # Number of instructions that finish executing in YJIT. + # See :count-placement: about the subtraction. + retired_in_yjit = stats[:exec_instruction] - side_exits + + # Average length of instruction sequences executed by YJIT + avg_len_in_yjit = retired_in_yjit.to_f / total_exits + + # Proportion of instructions that retire in YJIT + total_insns_count = retired_in_yjit + stats[:vm_insns_count] + yjit_ratio_pct = 100.0 * retired_in_yjit.to_f / total_insns_count + + # Number of failed compiler invocations + compilation_failure = stats[:compilation_failure] + + $stderr.puts "bindings_allocations: " + ("%10d" % stats[:binding_allocations]) + $stderr.puts "bindings_set: " + ("%10d" % stats[:binding_set]) + $stderr.puts "compilation_failure: " + ("%10d" % compilation_failure) if compilation_failure != 0 + $stderr.puts "compiled_iseq_count: " + ("%10d" % stats[:compiled_iseq_count]) + $stderr.puts "compiled_block_count: " + ("%10d" % stats[:compiled_block_count]) + $stderr.puts "invalidation_count: " + ("%10d" % stats[:invalidation_count]) + $stderr.puts "constant_state_bumps: " + ("%10d" % stats[:constant_state_bumps]) + $stderr.puts "inline_code_size: " + ("%10d" % stats[:inline_code_size]) + $stderr.puts "outlined_code_size: " + ("%10d" % stats[:outlined_code_size]) + + $stderr.puts "total_exit_count: " + ("%10d" % total_exits) + $stderr.puts "total_insns_count: " + ("%10d" % total_insns_count) + $stderr.puts "vm_insns_count: " + ("%10d" % stats[:vm_insns_count]) + $stderr.puts "yjit_insns_count: " + ("%10d" % stats[:exec_instruction]) + $stderr.puts "ratio_in_yjit: " + ("%9.1f" % yjit_ratio_pct) + "%" + $stderr.puts "avg_len_in_yjit: " + ("%10.1f" % avg_len_in_yjit) + + print_sorted_exit_counts(stats, prefix: "exit_") + end + + def print_sorted_exit_counts(stats, prefix:, how_many: 20, left_pad: 4) + exits = [] + stats.each do |k, v| + if k.start_with?(prefix) + exits.push [k.to_s.delete_prefix(prefix), v] + end + end + + exits = exits.sort_by { |name, count| -count }[0...how_many] + total_exits = total_exit_count(stats) + + top_n_total = exits.map { |name, count| count }.sum + top_n_exit_pct = 100.0 * top_n_total / total_exits + + $stderr.puts "Top-#{how_many} most frequent exit ops (#{"%.1f" % top_n_exit_pct}% of exits):" + + longest_insn_name_len = exits.map { |name, count| name.length }.max + exits.each do |name, count| + padding = longest_insn_name_len + left_pad + padded_name = "%#{padding}s" % name + padded_count = "%10d" % count + percent = 100.0 * count / total_exits + formatted_percent = "%.1f" % percent + $stderr.puts("#{padded_name}: #{padded_count} (#{formatted_percent}%)" ) + end + end + + def total_exit_count(stats, prefix: "exit_") + total = 0 + stats.each do |k,v| + total += v if k.start_with?(prefix) + end + total + end + + def print_counters(counters, prefix:, prompt:) + $stderr.puts(prompt) + counters = counters.filter { |key, _| key.start_with?(prefix) } + counters.filter! { |_, value| value != 0 } + counters.transform_keys! { |key| key.to_s.delete_prefix(prefix) } + + if counters.empty? + $stderr.puts(" (all relevant counters are zero)") + return + end + + counters = counters.to_a + counters.sort_by! { |(_, counter_value)| counter_value } + longest_name_length = counters.max_by { |(name, _)| name.length }.first.length + total = counters.sum { |(_, counter_value)| counter_value } + + counters.reverse_each do |(name, value)| + percentage = value.fdiv(total) * 100 + $stderr.printf(" %*s %10d (%4.1f%%)\n", longest_name_length, name, value, percentage); + end + end + end +end diff --git a/ruby/yjit_asm.c b/ruby/yjit_asm.c new file mode 100644 index 000000000..9f84e3974 --- /dev/null +++ b/ruby/yjit_asm.c @@ -0,0 +1,1835 @@ +// This file is a fragment of the yjit.o compilation unit. See yjit.c. +// +// Note that the definition for some of these functions don't specify +// static inline, but their declaration in yjit_asm.h do. The resulting +// linkage is the same as if they both specify. The relevant sections in +// N1256 is 6.2.2p4, 6.2.2p5, and 6.7.4p5. +#include +#include +#include +#include +#include +#include +#include + +// For mmapp(), sysconf() +#ifndef _WIN32 +#include +#include +#endif + +#include "yjit_asm.h" + +// Compute the number of bits needed to encode a signed value +uint32_t sig_imm_size(int64_t imm) +{ + // Compute the smallest size this immediate fits in + if (imm >= INT8_MIN && imm <= INT8_MAX) + return 8; + if (imm >= INT16_MIN && imm <= INT16_MAX) + return 16; + if (imm >= INT32_MIN && imm <= INT32_MAX) + return 32; + + return 64; +} + +// Compute the number of bits needed to encode an unsigned value +uint32_t unsig_imm_size(uint64_t imm) +{ + // Compute the smallest size this immediate fits in + if (imm <= UINT8_MAX) + return 8; + else if (imm <= UINT16_MAX) + return 16; + else if (imm <= UINT32_MAX) + return 32; + + return 64; +} + +x86opnd_t mem_opnd(uint32_t num_bits, x86opnd_t base_reg, int32_t disp) +{ + bool is_iprel = base_reg.as.reg.reg_type == REG_IP; + + x86opnd_t opnd = { + OPND_MEM, + num_bits, + .as.mem = { base_reg.as.reg.reg_no, 0, 0, false, is_iprel, disp } + }; + + return opnd; +} + +x86opnd_t mem_opnd_sib(uint32_t num_bits, x86opnd_t base_reg, x86opnd_t index_reg, int32_t scale, int32_t disp) +{ + uint8_t scale_exp; + switch (scale) { + case 8: + scale_exp = 3; + break; + case 4: + scale_exp = 2; + break; + case 2: + scale_exp = 1; + break; + case 1: + scale_exp = 0; + break; + default: + rb_bug("yjit: scale not one of 1,2,4,8"); + break; + } + + bool is_iprel = base_reg.as.reg.reg_type == REG_IP; + + x86opnd_t opnd = { + OPND_MEM, + num_bits, + .as.mem = { + .base_reg_no = base_reg.as.reg.reg_no, + .idx_reg_no = index_reg.as.reg.reg_no, + .has_idx = 1, + .scale_exp = scale_exp, + .is_iprel = is_iprel, + .disp = disp + } + }; + + return opnd; +} + +static x86opnd_t resize_opnd(x86opnd_t opnd, uint32_t num_bits) +{ + assert (num_bits % 8 == 0); + x86opnd_t sub = opnd; + sub.num_bits = num_bits; + return sub; +} + +x86opnd_t imm_opnd(int64_t imm) +{ + x86opnd_t opnd = { + OPND_IMM, + sig_imm_size(imm), + .as.imm = imm + }; + + return opnd; +} + +x86opnd_t const_ptr_opnd(const void *ptr) +{ + x86opnd_t opnd = { + OPND_IMM, + 64, + .as.unsig_imm = (uint64_t)ptr + }; + + return opnd; +} + +// Align the current write position to a multiple of bytes +static uint8_t *align_ptr(uint8_t *ptr, uint32_t multiple) +{ + // Compute the pointer modulo the given alignment boundary + uint32_t rem = ((uint32_t)(uintptr_t)ptr) % multiple; + + // If the pointer is already aligned, stop + if (rem == 0) + return ptr; + + // Pad the pointer by the necessary amount to align it + uint32_t pad = multiple - rem; + + return ptr + pad; +} + +// Allocate a block of executable memory +static uint8_t *alloc_exec_mem(uint32_t mem_size) +{ +#ifndef _WIN32 + uint8_t *mem_block; + + // On Linux + #if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE) + // Align the requested address to page size + uint32_t page_size = (uint32_t)sysconf(_SC_PAGESIZE); + uint8_t *req_addr = align_ptr((uint8_t*)&alloc_exec_mem, page_size); + + do { + // Try to map a chunk of memory as executable + mem_block = (uint8_t*)mmap( + (void*)req_addr, + mem_size, + PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, + -1, + 0 + ); + + // If we succeeded, stop + if (mem_block != MAP_FAILED) { + break; + } + + // +4MB + req_addr += 4 * 1024 * 1024; + } while (req_addr < (uint8_t*)&alloc_exec_mem + INT32_MAX); + + // On MacOS and other platforms + #else + // Try to map a chunk of memory as executable + mem_block = (uint8_t*)mmap( + (void*)alloc_exec_mem, + mem_size, + PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, + 0 + ); + #endif + + // Fallback + if (mem_block == MAP_FAILED) { + // Try again without the address hint (e.g., valgrind) + mem_block = (uint8_t*)mmap( + NULL, + mem_size, + PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, + 0 + ); + } + + // Check that the memory mapping was successful + if (mem_block == MAP_FAILED) { + perror("mmap call failed"); + exit(-1); + } + + codeblock_t block; + codeblock_t *cb = █ + + cb_init(cb, mem_block, mem_size); + + // Fill the executable memory with PUSH DS (0x1E) so that + // executing uninitialized memory will fault with #UD in + // 64-bit mode. + cb_mark_all_writeable(cb); + memset(mem_block, 0x1E, mem_size); + cb_mark_all_executable(cb); + + return mem_block; +#else + // Windows not supported for now + return NULL; +#endif +} + +// Initialize a code block object +void cb_init(codeblock_t *cb, uint8_t *mem_block, uint32_t mem_size) +{ + assert (mem_block); + cb->mem_block_ = mem_block; + cb->mem_size = mem_size; + cb->write_pos = 0; + cb->num_labels = 0; + cb->num_refs = 0; + cb->current_aligned_write_pos = ALIGNED_WRITE_POSITION_NONE; +} + +// Set the current write position +void cb_set_pos(codeblock_t *cb, uint32_t pos) +{ + // Assert here since while assembler functions do bounds checking, there is + // nothing stopping users from taking out an out-of-bounds pointer and + // doing bad accesses with it. + assert (pos < cb->mem_size); + cb->write_pos = pos; +} + +// Align the current write position to a multiple of bytes +void cb_align_pos(codeblock_t *cb, uint32_t multiple) +{ + // Compute the pointer modulo the given alignment boundary + uint8_t *ptr = cb_get_write_ptr(cb); + uint8_t *aligned_ptr = align_ptr(ptr, multiple); + const uint32_t write_pos = cb->write_pos; + + // Pad the pointer by the necessary amount to align it + ptrdiff_t pad = aligned_ptr - ptr; + cb_set_pos(cb, write_pos + (int32_t)pad); +} + +// Set the current write position from a pointer +void cb_set_write_ptr(codeblock_t *cb, uint8_t *code_ptr) +{ + intptr_t pos = code_ptr - cb->mem_block_; + assert (pos < cb->mem_size); + cb_set_pos(cb, (uint32_t)pos); +} + +// Get a direct pointer into the executable memory block +uint8_t *cb_get_ptr(const codeblock_t *cb, uint32_t index) +{ + if (index < cb->mem_size) { + return &cb->mem_block_[index]; + } + else { + return NULL; + } +} + +// Get a direct pointer to the current write position +uint8_t *cb_get_write_ptr(const codeblock_t *cb) +{ + return cb_get_ptr(cb, cb->write_pos); +} + +// Write a byte at the current position +void cb_write_byte(codeblock_t *cb, uint8_t byte) +{ + assert (cb->mem_block_); + if (cb->write_pos < cb->mem_size) { + cb_mark_position_writeable(cb, cb->write_pos); + cb->mem_block_[cb->write_pos] = byte; + cb->write_pos++; + } + else { + cb->dropped_bytes = true; + } +} + +// Write multiple bytes starting from the current position +void cb_write_bytes(codeblock_t *cb, uint32_t num_bytes, ...) +{ + va_list va; + va_start(va, num_bytes); + + for (uint32_t i = 0; i < num_bytes; ++i) + { + uint8_t byte = va_arg(va, int); + cb_write_byte(cb, byte); + } + + va_end(va); +} + +// Write a signed integer over a given number of bits at the current position +void cb_write_int(codeblock_t *cb, uint64_t val, uint32_t num_bits) +{ + assert (num_bits > 0); + assert (num_bits % 8 == 0); + + // Switch on the number of bits + switch (num_bits) { + case 8: + cb_write_byte(cb, (uint8_t)val); + break; + + case 16: + cb_write_bytes( + cb, + 2, + (uint8_t)((val >> 0) & 0xFF), + (uint8_t)((val >> 8) & 0xFF) + ); + break; + + case 32: + cb_write_bytes( + cb, + 4, + (uint8_t)((val >> 0) & 0xFF), + (uint8_t)((val >> 8) & 0xFF), + (uint8_t)((val >> 16) & 0xFF), + (uint8_t)((val >> 24) & 0xFF) + ); + break; + + default: + { + // Compute the size in bytes + uint32_t num_bytes = num_bits / 8; + + // Write out the bytes + for (uint32_t i = 0; i < num_bytes; ++i) + { + uint8_t byte_val = (uint8_t)(val & 0xFF); + cb_write_byte(cb, byte_val); + val >>= 8; + } + } + } +} + +// Allocate a new label with a given name +uint32_t cb_new_label(codeblock_t *cb, const char *name) +{ + //if (hasASM) + // writeString(to!string(label) ~ ":"); + + assert (cb->num_labels < MAX_LABELS); + + // Allocate the new label + uint32_t label_idx = cb->num_labels++; + + // This label doesn't have an address yet + cb->label_addrs[label_idx] = 0; + cb->label_names[label_idx] = name; + + return label_idx; +} + +// Write a label at the current address +void cb_write_label(codeblock_t *cb, uint32_t label_idx) +{ + assert (label_idx < MAX_LABELS); + cb->label_addrs[label_idx] = cb->write_pos; +} + +// Add a label reference at the current write position +void cb_label_ref(codeblock_t *cb, uint32_t label_idx) +{ + assert (label_idx < MAX_LABELS); + assert (cb->num_refs < MAX_LABEL_REFS); + + // Keep track of the reference + cb->label_refs[cb->num_refs] = (labelref_t){ cb->write_pos, label_idx }; + cb->num_refs++; +} + +// Link internal label references +void cb_link_labels(codeblock_t *cb) +{ + uint32_t orig_pos = cb->write_pos; + + // For each label reference + for (uint32_t i = 0; i < cb->num_refs; ++i) + { + uint32_t ref_pos = cb->label_refs[i].pos; + uint32_t label_idx = cb->label_refs[i].label_idx; + assert (ref_pos < cb->mem_size); + assert (label_idx < MAX_LABELS); + + uint32_t label_addr = cb->label_addrs[label_idx]; + assert (label_addr < cb->mem_size); + + // Compute the offset from the reference's end to the label + int64_t offset = (int64_t)label_addr - (int64_t)(ref_pos + 4); + + cb_set_pos(cb, ref_pos); + cb_write_int(cb, offset, 32); + } + + cb->write_pos = orig_pos; + + // Clear the label positions and references + cb->num_labels = 0; + cb->num_refs = 0; +} + +// Check if an operand needs a REX byte to be encoded +static bool rex_needed(x86opnd_t opnd) +{ + if (opnd.type == OPND_NONE || opnd.type == OPND_IMM) + { + return false; + } + + if (opnd.type == OPND_REG) + { + return ( + opnd.as.reg.reg_no > 7 || + (opnd.num_bits == 8 && opnd.as.reg.reg_no >= 4 && opnd.as.reg.reg_no <= 7) + ); + } + + if (opnd.type == OPND_MEM) + { + return (opnd.as.mem.base_reg_no > 7) || (opnd.as.mem.has_idx && opnd.as.mem.idx_reg_no > 7); + } + + rb_bug("unreachable"); +} + +// Check if an SIB byte is needed to encode this operand +static bool sib_needed(x86opnd_t opnd) +{ + if (opnd.type != OPND_MEM) + return false; + + return ( + opnd.as.mem.has_idx || + opnd.as.mem.base_reg_no == RSP.as.reg.reg_no || + opnd.as.mem.base_reg_no == R12.as.reg.reg_no + ); +} + +// Compute the size of the displacement field needed for a memory operand +static uint32_t disp_size(x86opnd_t opnd) +{ + assert (opnd.type == OPND_MEM); + + // If using RIP as the base, use disp32 + if (opnd.as.mem.is_iprel) + { + return 32; + } + + // Compute the required displacement size + if (opnd.as.mem.disp != 0) + { + uint32_t num_bits = sig_imm_size(opnd.as.mem.disp); + assert (num_bits <= 32 && "displacement does not fit in 32 bits"); + + // x86 can only encode 8-bit and 32-bit displacements + if (num_bits == 16) + num_bits = 32;; + + return num_bits; + } + + // If EBP or RBP or R13 is used as the base, displacement must be encoded + if (opnd.as.mem.base_reg_no == RBP.as.reg.reg_no || + opnd.as.mem.base_reg_no == R13.as.reg.reg_no) + { + return 8; + } + + return 0; +} + +// Write the REX byte +static void cb_write_rex( + codeblock_t *cb, + bool w_flag, + uint8_t reg_no, + uint8_t idx_reg_no, + uint8_t rm_reg_no +) +{ + // 0 1 0 0 w r x b + // w - 64-bit operand size flag + // r - MODRM.reg extension + // x - SIB.index extension + // b - MODRM.rm or SIB.base extension + uint8_t w = w_flag? 1:0; + uint8_t r = (reg_no & 8)? 1:0; + uint8_t x = (idx_reg_no & 8)? 1:0; + uint8_t b = (rm_reg_no & 8)? 1:0; + + // Encode and write the REX byte + uint8_t rexByte = 0x40 + (w << 3) + (r << 2) + (x << 1) + (b); + cb_write_byte(cb, rexByte); +} + +// Write an opcode byte with an embedded register operand +static void cb_write_opcode(codeblock_t *cb, uint8_t opcode, x86opnd_t reg) +{ + // Write the reg field into the opcode byte + uint8_t op_byte = opcode | (reg.as.reg.reg_no & 7); + cb_write_byte(cb, op_byte); +} + +// Encode an RM instruction +static void cb_write_rm( + codeblock_t *cb, + bool szPref, + bool rexW, + x86opnd_t r_opnd, + x86opnd_t rm_opnd, + uint8_t opExt, + uint32_t op_len, + ...) +{ + assert (op_len > 0 && op_len <= 3); + assert (r_opnd.type == OPND_REG || r_opnd.type == OPND_NONE); + + // Flag to indicate the REX prefix is needed + bool need_rex = rexW || rex_needed(r_opnd) || rex_needed(rm_opnd); + + // Flag to indicate SIB byte is needed + bool need_sib = sib_needed(r_opnd) || sib_needed(rm_opnd); + + // Add the operand-size prefix, if needed + if (szPref == true) + cb_write_byte(cb, 0x66); + + // Add the REX prefix, if needed + if (need_rex) + { + // 0 1 0 0 w r x b + // w - 64-bit operand size flag + // r - MODRM.reg extension + // x - SIB.index extension + // b - MODRM.rm or SIB.base extension + + uint8_t w = rexW? 1:0; + + uint8_t r; + if (r_opnd.type != OPND_NONE) + r = (r_opnd.as.reg.reg_no & 8)? 1:0; + else + r = 0; + + uint8_t x; + if (need_sib && rm_opnd.as.mem.has_idx) + x = (rm_opnd.as.mem.idx_reg_no & 8)? 1:0; + else + x = 0; + + uint8_t b; + if (rm_opnd.type == OPND_REG) + b = (rm_opnd.as.reg.reg_no & 8)? 1:0; + else if (rm_opnd.type == OPND_MEM) + b = (rm_opnd.as.mem.base_reg_no & 8)? 1:0; + else + b = 0; + + // Encode and write the REX byte + uint8_t rex_byte = 0x40 + (w << 3) + (r << 2) + (x << 1) + (b); + cb_write_byte(cb, rex_byte); + } + + // Write the opcode bytes to the code block + va_list va; + va_start(va, op_len); + for (uint32_t i = 0; i < op_len; ++i) + { + uint8_t byte = va_arg(va, int); + cb_write_byte(cb, byte); + } + va_end(va); + + // MODRM.mod (2 bits) + // MODRM.reg (3 bits) + // MODRM.rm (3 bits) + + assert ( + !(opExt != 0xFF && r_opnd.type != OPND_NONE) && + "opcode extension and register operand present" + ); + + // Encode the mod field + uint8_t mod; + if (rm_opnd.type == OPND_REG) + { + mod = 3; + } + else + { + uint32_t dsize = disp_size(rm_opnd); + if (dsize == 0 || rm_opnd.as.mem.is_iprel) + mod = 0; + else if (dsize == 8) + mod = 1; + else if (dsize == 32) + mod = 2; + else + rb_bug("unreachable"); + } + + // Encode the reg field + uint8_t reg; + if (opExt != 0xFF) + reg = opExt; + else if (r_opnd.type == OPND_REG) + reg = r_opnd.as.reg.reg_no & 7; + else + reg = 0; + + // Encode the rm field + uint8_t rm; + if (rm_opnd.type == OPND_REG) + { + rm = rm_opnd.as.reg.reg_no & 7; + } + else + { + if (need_sib) + rm = 4; + else + rm = rm_opnd.as.mem.base_reg_no & 7; + } + + // Encode and write the ModR/M byte + uint8_t rm_byte = (mod << 6) + (reg << 3) + (rm); + cb_write_byte(cb, rm_byte); + + // Add the SIB byte, if needed + if (need_sib) + { + // SIB.scale (2 bits) + // SIB.index (3 bits) + // SIB.base (3 bits) + + assert (rm_opnd.type == OPND_MEM); + + // Encode the scale value + uint8_t scale = rm_opnd.as.mem.scale_exp; + + // Encode the index value + uint8_t index; + if (!rm_opnd.as.mem.has_idx) + index = 4; + else + index = rm_opnd.as.mem.idx_reg_no & 7; + + // Encode the base register + uint8_t base = rm_opnd.as.mem.base_reg_no & 7; + + // Encode and write the SIB byte + uint8_t sib_byte = (scale << 6) + (index << 3) + (base); + cb_write_byte(cb, sib_byte); + } + + // Add the displacement + if (rm_opnd.type == OPND_MEM) + { + uint32_t dsize = disp_size(rm_opnd); + if (dsize > 0) + cb_write_int(cb, rm_opnd.as.mem.disp, dsize); + } +} + +// Encode a mul-like single-operand RM instruction +static void write_rm_unary( + codeblock_t *cb, + const char *mnem, + uint8_t opMemReg8, + uint8_t opMemRegPref, + uint8_t opExt, + x86opnd_t opnd) +{ + // Write a disassembly string + //cb.writeASM(mnem, opnd); + + // Check the size of opnd0 + uint32_t opndSize; + if (opnd.type == OPND_REG || opnd.type == OPND_MEM) + opndSize = opnd.num_bits; + else + rb_bug("yjit: invalid operand"); + + assert (opndSize == 8 || opndSize == 16 || opndSize == 32 || opndSize == 64); + bool szPref = opndSize == 16; + bool rexW = opndSize == 64; + + if (opndSize == 8) + cb_write_rm(cb, false, false, NO_OPND, opnd, opExt, 1, opMemReg8); + else + cb_write_rm(cb, szPref, rexW, NO_OPND, opnd, opExt, 1, opMemRegPref); +} + +// Encode an add-like RM instruction with multiple possible encodings +static void cb_write_rm_multi( + codeblock_t *cb, + const char *mnem, + uint8_t opMemReg8, + uint8_t opMemRegPref, + uint8_t opRegMem8, + uint8_t opRegMemPref, + uint8_t opMemImm8, + uint8_t opMemImmSml, + uint8_t opMemImmLrg, + uint8_t opExtImm, + x86opnd_t opnd0, + x86opnd_t opnd1) +{ + assert (opnd0.type == OPND_REG || opnd0.type == OPND_MEM); + + /* + // Write disassembly string + if (!opnd1.isNone) + cb.writeASM(mnem, opnd0, opnd1); + else + cb.writeASM(mnem, opnd0); + */ + + // Check the size of opnd0 + uint32_t opndSize = opnd0.num_bits; + + // Check the size of opnd1 + if (opnd1.type == OPND_REG || opnd1.type == OPND_MEM) + { + assert (opnd1.num_bits == opndSize && "operand size mismatch"); + } + else if (opnd1.type == OPND_IMM) + { + assert (opnd1.num_bits <= opndSize); + } + + assert (opndSize == 8 || opndSize == 16 || opndSize == 32 || opndSize == 64); + bool szPref = opndSize == 16; + bool rexW = opndSize == 64; + + // R/M + Reg + if ((opnd0.type == OPND_MEM && opnd1.type == OPND_REG) || + (opnd0.type == OPND_REG && opnd1.type == OPND_REG)) + { + // R/M is opnd0 + if (opndSize == 8) + cb_write_rm(cb, false, false, opnd1, opnd0, 0xFF, 1, opMemReg8); + else + cb_write_rm(cb, szPref, rexW, opnd1, opnd0, 0xFF, 1, opMemRegPref); + } + + // Reg + R/M + else if (opnd0.type == OPND_REG && opnd1.type == OPND_MEM) + { + // R/M is opnd1 + if (opndSize == 8) + cb_write_rm(cb, false, false, opnd0, opnd1, 0xFF, 1, opRegMem8); + else + cb_write_rm(cb, szPref, rexW, opnd0, opnd1, 0xFF, 1, opRegMemPref); + } + + // R/M + Imm + else if (opnd1.type == OPND_IMM) + { + // 8-bit immediate + if (opnd1.num_bits <= 8) + { + if (opndSize == 8) + cb_write_rm(cb, false, false, NO_OPND, opnd0, opExtImm, 1, opMemImm8); + else + cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExtImm, 1, opMemImmSml); + + cb_write_int(cb, opnd1.as.imm, 8); + } + + // 32-bit immediate + else if (opnd1.num_bits <= 32) + { + assert (opnd1.num_bits <= opndSize && "immediate too large for dst"); + cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExtImm, 1, opMemImmLrg); + cb_write_int(cb, opnd1.as.imm, (opndSize > 32)? 32:opndSize); + } + + // Immediate too large + else + { + assert (false && "immediate value too large"); + } + } + + // Invalid operands + else + { + assert (false && "invalid operand combination"); + } +} + +// Encode a single-operand shift instruction +static void cb_write_shift( + codeblock_t *cb, + const char *mnem, + uint8_t opMemOnePref, + uint8_t opMemClPref, + uint8_t opMemImmPref, + uint8_t opExt, + x86opnd_t opnd0, + x86opnd_t opnd1) +{ + // Write a disassembly string + //cb.writeASM(mnem, opnd0, opnd1); + + // Check the size of opnd0 + uint32_t opndSize; + if (opnd0.type == OPND_REG || opnd0.type == OPND_MEM) + opndSize = opnd0.num_bits; + else + rb_bug("yjit: shift: invalid first operand"); + + assert (opndSize == 16 || opndSize == 32 || opndSize == 64); + bool szPref = opndSize == 16; + bool rexW = opndSize == 64; + + if (opnd1.type == OPND_IMM) + { + if (opnd1.as.imm == 1) + { + cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExt, 1, opMemOnePref); + } + else + { + assert (opnd1.num_bits <= 8); + cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExt, 1, opMemImmPref); + cb_write_byte(cb, (uint8_t)opnd1.as.imm); + } + } + /* + else if (opnd1.isReg && opnd1.reg == CL) + { + cb.writeRMInstr!('l', opExt, opMemClPref)(szPref, rexW, opnd0, X86Opnd.NONE); + } + */ + else + { + assert (false); + } +} + +// Encode a relative jump to a label (direct or conditional) +// Note: this always encodes a 32-bit offset +static void cb_write_jcc(codeblock_t *cb, const char *mnem, uint8_t op0, uint8_t op1, uint32_t label_idx) +{ + //cb.writeASM(mnem, label); + + // Write the opcode + if (op0 != 0xFF) + cb_write_byte(cb, op0); + cb_write_byte(cb, op1); + + // Add a reference to the label + cb_label_ref(cb, label_idx); + + // Relative 32-bit offset to be patched + cb_write_int(cb, 0, 32); +} + +// Encode a relative jump to a pointer at a 32-bit offset (direct or conditional) +static void cb_write_jcc_ptr(codeblock_t *cb, const char *mnem, uint8_t op0, uint8_t op1, uint8_t *dst_ptr) +{ + //cb.writeASM(mnem, label); + + // Write the opcode + if (op0 != 0xFF) + cb_write_byte(cb, op0); + cb_write_byte(cb, op1); + + // Pointer to the end of this jump instruction + uint8_t *end_ptr = cb_get_ptr(cb, cb->write_pos + 4); + + // Compute the jump offset + int64_t rel64 = (int64_t)(dst_ptr - end_ptr); + if (rel64 >= INT32_MIN && rel64 <= INT32_MAX) { + // Write the relative 32-bit jump offset + cb_write_int(cb, (int32_t)rel64, 32); + } + else { + // Offset doesn't fit in 4 bytes. Report error. + cb->dropped_bytes = true; + } +} + +// Encode a conditional move instruction +static void cb_write_cmov(codeblock_t *cb, const char *mnem, uint8_t opcode1, x86opnd_t dst, x86opnd_t src) +{ + //cb.writeASM(mnem, dst, src); + + assert (dst.type == OPND_REG); + assert (src.type == OPND_REG || src.type == OPND_MEM); + assert (dst.num_bits >= 16 && "invalid dst reg size in cmov"); + + bool szPref = dst.num_bits == 16; + bool rexW = dst.num_bits == 64; + + cb_write_rm(cb, szPref, rexW, dst, src, 0xFF, 2, 0x0F, opcode1); +} + +// add - Integer addition +void add(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "add", + 0x00, // opMemReg8 + 0x01, // opMemRegPref + 0x02, // opRegMem8 + 0x03, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x00, // opExtImm + opnd0, + opnd1 + ); +} + +/// and - Bitwise AND +void and(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "and", + 0x20, // opMemReg8 + 0x21, // opMemRegPref + 0x22, // opRegMem8 + 0x23, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x04, // opExtImm + opnd0, + opnd1 + ); +} + +// call - Call to a pointer with a 32-bit displacement offset +static void call_rel32(codeblock_t *cb, int32_t rel32) +{ + //cb.writeASM("call", rel32); + + // Write the opcode + cb_write_byte(cb, 0xE8); + + // Write the relative 32-bit jump offset + cb_write_int(cb, (int32_t)rel32, 32); +} + +// call - Call a pointer, encode with a 32-bit offset if possible +void call_ptr(codeblock_t *cb, x86opnd_t scratch_reg, uint8_t *dst_ptr) +{ + assert (scratch_reg.type == OPND_REG); + + // Pointer to the end of this call instruction + uint8_t *end_ptr = cb_get_ptr(cb, cb->write_pos + 5); + + // Compute the jump offset + int64_t rel64 = (int64_t)(dst_ptr - end_ptr); + + // If the offset fits in 32-bit + if (rel64 >= INT32_MIN && rel64 <= INT32_MAX) { + call_rel32(cb, (int32_t)rel64); + return; + } + + // Move the pointer into the scratch register and call + mov(cb, scratch_reg, const_ptr_opnd(dst_ptr)); + call(cb, scratch_reg); +} + +/// call - Call to label with 32-bit offset +void call_label(codeblock_t *cb, uint32_t label_idx) +{ + //cb.writeASM("call", label); + + // Write the opcode + cb_write_byte(cb, 0xE8); + + // Add a reference to the label + cb_label_ref(cb, label_idx); + + // Relative 32-bit offset to be patched + cb_write_int(cb, 0, 32); +} + +/// call - Indirect call with an R/M operand +void call(codeblock_t *cb, x86opnd_t opnd) +{ + //cb.writeASM("call", opnd); + cb_write_rm(cb, false, false, NO_OPND, opnd, 2, 1, 0xFF); +} + +/// cmovcc - Conditional move +void cmova(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmova", 0x47, dst, src); } +void cmovae(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovae", 0x43, dst, src); } +void cmovb(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovb", 0x42, dst, src); } +void cmovbe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovbe", 0x46, dst, src); } +void cmovc(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovc", 0x42, dst, src); } +void cmove(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmove", 0x44, dst, src); } +void cmovg(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovg", 0x4F, dst, src); } +void cmovge(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovge", 0x4D, dst, src); } +void cmovl(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovl", 0x4C, dst, src); } +void cmovle(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovle", 0x4E, dst, src); } +void cmovna(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovna", 0x46, dst, src); } +void cmovnae(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnae", 0x42, dst, src); } +void cmovnb(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnb", 0x43, dst, src); } +void cmovnbe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnbe", 0x47, dst, src); } +void cmovnc(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnc", 0x43, dst, src); } +void cmovne(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovne", 0x45, dst, src); } +void cmovng(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovng", 0x4E, dst, src); } +void cmovnge(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnge", 0x4C, dst, src); } +void cmovnl(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnl" , 0x4D, dst, src); } +void cmovnle(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnle", 0x4F, dst, src); } +void cmovno(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovno", 0x41, dst, src); } +void cmovnp(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnp", 0x4B, dst, src); } +void cmovns(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovns", 0x49, dst, src); } +void cmovnz(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovnz", 0x45, dst, src); } +void cmovo(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovo", 0x40, dst, src); } +void cmovp(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovp", 0x4A, dst, src); } +void cmovpe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovpe", 0x4A, dst, src); } +void cmovpo(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovpo", 0x4B, dst, src); } +void cmovs(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovs", 0x48, dst, src); } +void cmovz(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) { cb_write_cmov(cb, "cmovz", 0x44, dst, src); } + +/// cmp - Compare and set flags +void cmp(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "cmp", + 0x38, // opMemReg8 + 0x39, // opMemRegPref + 0x3A, // opRegMem8 + 0x3B, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x07, // opExtImm + opnd0, + opnd1 + ); +} + +/// cdq - Convert doubleword to quadword +void cdq(codeblock_t *cb) +{ + //cb.writeASM("cdq"); + cb_write_byte(cb, 0x99); +} + +/// cqo - Convert quadword to octaword +void cqo(codeblock_t *cb) +{ + //cb.writeASM("cqo"); + cb_write_bytes(cb, 2, 0x48, 0x99); +} + +/// Interrupt 3 - trap to debugger +void int3(codeblock_t *cb) +{ + //cb.writeASM("INT 3"); + cb_write_byte(cb, 0xCC); +} + +/* +// div - Unsigned integer division +alias div = writeRMUnary!( + "div", + 0xF6, // opMemReg8 + 0xF7, // opMemRegPref + 0x06 // opExt +); +*/ + +/* +/// divsd - Divide scalar double +alias divsd = writeXMM64!( + "divsd", + 0xF2, // prefix + 0x0F, // opRegMem0 + 0x5E // opRegMem1 +); +*/ + +/* +// idiv - Signed integer division +alias idiv = writeRMUnary!( + "idiv", + 0xF6, // opMemReg8 + 0xF7, // opMemRegPref + 0x07 // opExt +); +*/ + +/* +/// imul - Signed integer multiplication with two operands +void imul(CodeBlock cb, X86Opnd opnd0, X86Opnd opnd1) +{ + cb.writeASM("imul", opnd0, opnd1); + + assert (opnd0.isReg, "invalid first operand"); + auto opndSize = opnd0.reg.size; + + // Check the size of opnd1 + if (opnd1.isReg) + assert (opnd1.reg.size is opndSize, "operand size mismatch"); + else if (opnd1.isMem) + assert (opnd1.mem.size is opndSize, "operand size mismatch"); + + assert (opndSize is 16 || opndSize is 32 || opndSize is 64); + auto szPref = opndSize is 16; + auto rexW = opndSize is 64; + + cb.writeRMInstr!('r', 0xFF, 0x0F, 0xAF)(szPref, rexW, opnd0, opnd1); +} +*/ + +/* +/// imul - Signed integer multiplication with three operands (one immediate) +void imul(CodeBlock cb, X86Opnd opnd0, X86Opnd opnd1, X86Opnd opnd2) +{ + cb.writeASM("imul", opnd0, opnd1, opnd2); + + assert (opnd0.isReg, "invalid first operand"); + auto opndSize = opnd0.reg.size; + + // Check the size of opnd1 + if (opnd1.isReg) + assert (opnd1.reg.size is opndSize, "operand size mismatch"); + else if (opnd1.isMem) + assert (opnd1.mem.size is opndSize, "operand size mismatch"); + + assert (opndSize is 16 || opndSize is 32 || opndSize is 64); + auto szPref = opndSize is 16; + auto rexW = opndSize is 64; + + assert (opnd2.isImm, "invalid third operand"); + auto imm = opnd2.imm; + + // 8-bit immediate + if (imm.immSize <= 8) + { + cb.writeRMInstr!('r', 0xFF, 0x6B)(szPref, rexW, opnd0, opnd1); + cb.writeInt(imm.imm, 8); + } + + // 32-bit immediate + else if (imm.immSize <= 32) + { + assert (imm.immSize <= opndSize, "immediate too large for dst"); + cb.writeRMInstr!('r', 0xFF, 0x69)(szPref, rexW, opnd0, opnd1); + cb.writeInt(imm.imm, min(opndSize, 32)); + } + + // Immediate too large + else + { + assert (false, "immediate value too large"); + } +} +*/ + +/// jcc - relative jumps to a label +void ja_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "ja" , 0x0F, 0x87, label_idx); } +void jae_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jae" , 0x0F, 0x83, label_idx); } +void jb_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jb" , 0x0F, 0x82, label_idx); } +void jbe_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jbe" , 0x0F, 0x86, label_idx); } +void jc_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jc" , 0x0F, 0x82, label_idx); } +void je_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "je" , 0x0F, 0x84, label_idx); } +void jg_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jg" , 0x0F, 0x8F, label_idx); } +void jge_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jge" , 0x0F, 0x8D, label_idx); } +void jl_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jl" , 0x0F, 0x8C, label_idx); } +void jle_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jle" , 0x0F, 0x8E, label_idx); } +void jna_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jna" , 0x0F, 0x86, label_idx); } +void jnae_label(codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnae", 0x0F, 0x82, label_idx); } +void jnb_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnb" , 0x0F, 0x83, label_idx); } +void jnbe_label(codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnbe", 0x0F, 0x87, label_idx); } +void jnc_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnc" , 0x0F, 0x83, label_idx); } +void jne_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jne" , 0x0F, 0x85, label_idx); } +void jng_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jng" , 0x0F, 0x8E, label_idx); } +void jnge_label(codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnge", 0x0F, 0x8C, label_idx); } +void jnl_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnl" , 0x0F, 0x8D, label_idx); } +void jnle_label(codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnle", 0x0F, 0x8F, label_idx); } +void jno_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jno" , 0x0F, 0x81, label_idx); } +void jnp_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnp" , 0x0F, 0x8b, label_idx); } +void jns_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jns" , 0x0F, 0x89, label_idx); } +void jnz_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jnz" , 0x0F, 0x85, label_idx); } +void jo_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jo" , 0x0F, 0x80, label_idx); } +void jp_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jp" , 0x0F, 0x8A, label_idx); } +void jpe_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jpe" , 0x0F, 0x8A, label_idx); } +void jpo_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jpo" , 0x0F, 0x8B, label_idx); } +void js_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "js" , 0x0F, 0x88, label_idx); } +void jz_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jz" , 0x0F, 0x84, label_idx); } +void jmp_label (codeblock_t *cb, uint32_t label_idx) { cb_write_jcc(cb, "jmp" , 0xFF, 0xE9, label_idx); } + +/// jcc - relative jumps to a pointer (32-bit offset) +void ja_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "ja" , 0x0F, 0x87, ptr); } +void jae_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jae" , 0x0F, 0x83, ptr); } +void jb_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jb" , 0x0F, 0x82, ptr); } +void jbe_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jbe" , 0x0F, 0x86, ptr); } +void jc_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jc" , 0x0F, 0x82, ptr); } +void je_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "je" , 0x0F, 0x84, ptr); } +void jg_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jg" , 0x0F, 0x8F, ptr); } +void jge_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jge" , 0x0F, 0x8D, ptr); } +void jl_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jl" , 0x0F, 0x8C, ptr); } +void jle_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jle" , 0x0F, 0x8E, ptr); } +void jna_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jna" , 0x0F, 0x86, ptr); } +void jnae_ptr(codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnae", 0x0F, 0x82, ptr); } +void jnb_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnb" , 0x0F, 0x83, ptr); } +void jnbe_ptr(codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnbe", 0x0F, 0x87, ptr); } +void jnc_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnc" , 0x0F, 0x83, ptr); } +void jne_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jne" , 0x0F, 0x85, ptr); } +void jng_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jng" , 0x0F, 0x8E, ptr); } +void jnge_ptr(codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnge", 0x0F, 0x8C, ptr); } +void jnl_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnl" , 0x0F, 0x8D, ptr); } +void jnle_ptr(codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnle", 0x0F, 0x8F, ptr); } +void jno_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jno" , 0x0F, 0x81, ptr); } +void jnp_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnp" , 0x0F, 0x8b, ptr); } +void jns_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jns" , 0x0F, 0x89, ptr); } +void jnz_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jnz" , 0x0F, 0x85, ptr); } +void jo_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jo" , 0x0F, 0x80, ptr); } +void jp_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jp" , 0x0F, 0x8A, ptr); } +void jpe_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jpe" , 0x0F, 0x8A, ptr); } +void jpo_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jpo" , 0x0F, 0x8B, ptr); } +void js_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "js" , 0x0F, 0x88, ptr); } +void jz_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jz" , 0x0F, 0x84, ptr); } +void jmp_ptr (codeblock_t *cb, uint8_t *ptr) { cb_write_jcc_ptr(cb, "jmp" , 0xFF, 0xE9, ptr); } + +/// jmp - Indirect jump near to an R/M operand +void jmp_rm(codeblock_t *cb, x86opnd_t opnd) +{ + //cb.writeASM("jmp", opnd); + cb_write_rm(cb, false, false, NO_OPND, opnd, 4, 1, 0xFF); +} + +// jmp - Jump with relative 32-bit offset +void jmp32(codeblock_t *cb, int32_t offset) +{ + //cb.writeASM("jmp", ((offset > 0)? "+":"-") ~ to!string(offset)); + cb_write_byte(cb, 0xE9); + cb_write_int(cb, offset, 32); +} + +/// lea - Load Effective Address +void lea(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) +{ + //cb.writeASM("lea", dst, src); + assert (dst.num_bits == 64); + cb_write_rm(cb, false, true, dst, src, 0xFF, 1, 0x8D); +} + +// Does this number fit in 32 bits and stays the same if you zero extend it to 64 bit? +// If the sign bit is clear, sign extension and zero extension yield the same +// result. +static bool +zero_extendable_32bit(uint64_t number) +{ + return number <= UINT32_MAX && (number & (1ull << 31ull)) == 0; +} + +/// mov - Data move operation +void mov(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) +{ + // R/M + Imm + if (src.type == OPND_IMM) + { + //cb.writeASM("mov", dst, src); + + // R + Imm + if (dst.type == OPND_REG) + { + assert ( + src.num_bits <= dst.num_bits || + unsig_imm_size(src.as.imm) <= dst.num_bits + ); + + // In case the source immediate could be zero extended to be 64 + // bit, we can use the 32-bit operands version of the instruction. + // For example, we can turn mov(rax, 0x34) into the equivalent + // mov(eax, 0x34). + if (dst.num_bits == 64 && zero_extendable_32bit(src.as.unsig_imm)) { + if (rex_needed(dst)) + cb_write_rex(cb, false, 0, 0, dst.as.reg.reg_no); + cb_write_opcode(cb, 0xB8, dst); + cb_write_int(cb, src.as.imm, 32); + } + else { + if (dst.num_bits == 16) + cb_write_byte(cb, 0x66); + + if (rex_needed(dst) || dst.num_bits == 64) + cb_write_rex(cb, dst.num_bits == 64, 0, 0, dst.as.reg.reg_no); + + cb_write_opcode(cb, (dst.num_bits == 8)? 0xB0:0xB8, dst); + + cb_write_int(cb, src.as.imm, dst.num_bits); + } + } + + // M + Imm + else if (dst.type == OPND_MEM) + { + assert (src.num_bits <= dst.num_bits); + + if (dst.num_bits == 8) + cb_write_rm(cb, false, false, NO_OPND, dst, 0xFF, 1, 0xC6); + else + cb_write_rm(cb, dst.num_bits == 16, dst.num_bits == 64, NO_OPND, dst, 0, 1, 0xC7); + + const uint32_t output_num_bits = (dst.num_bits > 32u) ? 32u : dst.num_bits; + // assert that we can write whole immediate without loss of information + assert (sig_imm_size(src.as.imm) <= output_num_bits); + cb_write_int(cb, src.as.imm, output_num_bits); + } + + else + { + assert (false); + } + } + else + { + cb_write_rm_multi( + cb, + "mov", + 0x88, // opMemReg8 + 0x89, // opMemRegPref + 0x8A, // opRegMem8 + 0x8B, // opRegMemPref + 0xC6, // opMemImm8 + 0xFF, // opMemImmSml (not available) + 0xFF, // opMemImmLrg + 0xFF, // opExtImm + dst, + src + ); + } +} + +/// movsx - Move with sign extension (signed integers) +void movsx(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) +{ + assert (dst.type == OPND_REG); + assert (src.type == OPND_REG || src.type == OPND_MEM); + assert (src.num_bits < dst.num_bits); + + //cb.writeASM("movsx", dst, src); + + if (src.num_bits == 8) + { + cb_write_rm(cb, dst.num_bits == 16, dst.num_bits == 64, dst, src, 0xFF, 2, 0x0F, 0xBE); + } + else if (src.num_bits == 16) + { + cb_write_rm(cb, dst.num_bits == 16, dst.num_bits == 64, dst, src, 0xFF, 2, 0x0F, 0xBF); + } + else if (src.num_bits == 32) + { + cb_write_rm(cb, false, true, dst, src, 0xFF, 1, 0x63); + } + else + { + assert (false); + } +} + +/* +/// movzx - Move with zero extension (unsigned values) +void movzx(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) +{ + cb.writeASM("movzx", dst, src); + + uint32_t dstSize; + if (dst.isReg) + dstSize = dst.reg.size; + else + assert (false, "movzx dst must be a register"); + + uint32_t srcSize; + if (src.isReg) + srcSize = src.reg.size; + else if (src.isMem) + srcSize = src.mem.size; + else + assert (false); + + assert ( + srcSize < dstSize, + "movzx: srcSize >= dstSize" + ); + + if (srcSize is 8) + { + cb.writeRMInstr!('r', 0xFF, 0x0F, 0xB6)(dstSize is 16, dstSize is 64, dst, src); + } + else if (srcSize is 16) + { + cb.writeRMInstr!('r', 0xFF, 0x0F, 0xB7)(dstSize is 16, dstSize is 64, dst, src); + } + else + { + assert (false, "invalid src operand size for movxz"); + } +} +*/ + +// neg - Integer negation (multiplication by -1) +void neg(codeblock_t *cb, x86opnd_t opnd) +{ + write_rm_unary( + cb, + "neg", + 0xF6, // opMemReg8 + 0xF7, // opMemRegPref + 0x03, // opExt + opnd + ); +} + +// nop - Noop, one or multiple bytes long +void nop(codeblock_t *cb, uint32_t length) +{ + switch (length) { + case 0: + break; + + case 1: + //cb.writeASM("nop1"); + cb_write_byte(cb, 0x90); + break; + + case 2: + //cb.writeASM("nop2"); + cb_write_bytes(cb, 2, 0x66,0x90); + break; + + case 3: + //cb.writeASM("nop3"); + cb_write_bytes(cb, 3, 0x0F,0x1F,0x00); + break; + + case 4: + //cb.writeASM("nop4"); + cb_write_bytes(cb, 4, 0x0F,0x1F,0x40,0x00); + break; + + case 5: + //cb.writeASM("nop5"); + cb_write_bytes(cb, 5, 0x0F,0x1F,0x44,0x00,0x00); + break; + + case 6: + //cb.writeASM("nop6"); + cb_write_bytes(cb, 6, 0x66,0x0F,0x1F,0x44,0x00,0x00); + break; + + case 7: + //cb.writeASM("nop7"); + cb_write_bytes(cb, 7, 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00); + break; + + case 8: + //cb.writeASM("nop8"); + cb_write_bytes(cb, 8, 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00); + break; + + case 9: + //cb.writeASM("nop9"); + cb_write_bytes(cb, 9, 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00); + break; + + default: + { + uint32_t written = 0; + while (written + 9 <= length) + { + nop(cb, 9); + written += 9; + } + nop(cb, length - written); + } + break; + } +} + +// not - Bitwise NOT +void not(codeblock_t *cb, x86opnd_t opnd) +{ + write_rm_unary( + cb, + "not", + 0xF6, // opMemReg8 + 0xF7, // opMemRegPref + 0x02, // opExt + opnd + ); +} + +/// or - Bitwise OR +void or(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "or", + 0x08, // opMemReg8 + 0x09, // opMemRegPref + 0x0A, // opRegMem8 + 0x0B, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x01, // opExtImm + opnd0, + opnd1 + ); +} + +/// pop - Pop a register off the stack +void pop(codeblock_t *cb, x86opnd_t opnd) +{ + assert (opnd.num_bits == 64); + + //cb.writeASM("pop", opnd); + + if (opnd.type == OPND_REG) { + if (rex_needed(opnd)) + cb_write_rex(cb, false, 0, 0, opnd.as.reg.reg_no); + cb_write_opcode(cb, 0x58, opnd); + } + else if (opnd.type == OPND_MEM) { + cb_write_rm(cb, false, false, NO_OPND, opnd, 0, 1, 0x8F); + } + else { + assert(false && "unexpected operand type"); + } +} + +/// popfq - Pop the flags register (64-bit) +void popfq(codeblock_t *cb) +{ + //cb.writeASM("popfq"); + + // REX.W + 0x9D + cb_write_bytes(cb, 2, 0x48, 0x9D); +} + +/// push - Push an operand on the stack +void push(codeblock_t *cb, x86opnd_t opnd) +{ + assert (opnd.num_bits == 64); + + //cb.writeASM("push", opnd); + + if (opnd.type == OPND_REG) { + if (rex_needed(opnd)) + cb_write_rex(cb, false, 0, 0, opnd.as.reg.reg_no); + cb_write_opcode(cb, 0x50, opnd); + } + else if (opnd.type == OPND_MEM) { + cb_write_rm(cb, false, false, NO_OPND, opnd, 6, 1, 0xFF); + } + else { + assert(false && "unexpected operand type"); + } +} + +/// pushfq - Push the flags register (64-bit) +void pushfq(codeblock_t *cb) +{ + //cb.writeASM("pushfq"); + cb_write_byte(cb, 0x9C); +} + +/// ret - Return from call, popping only the return address +void ret(codeblock_t *cb) +{ + //cb.writeASM("ret"); + cb_write_byte(cb, 0xC3); +} + +// sal - Shift arithmetic left +void sal(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_shift( + cb, + "sal", + 0xD1, // opMemOnePref, + 0xD3, // opMemClPref, + 0xC1, // opMemImmPref, + 0x04, + opnd0, + opnd1 + ); +} + +/// sar - Shift arithmetic right (signed) +void sar(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_shift( + cb, + "sar", + 0xD1, // opMemOnePref, + 0xD3, // opMemClPref, + 0xC1, // opMemImmPref, + 0x07, + opnd0, + opnd1 + ); +} +// shl - Shift logical left +void shl(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_shift( + cb, + "shl", + 0xD1, // opMemOnePref, + 0xD3, // opMemClPref, + 0xC1, // opMemImmPref, + 0x04, + opnd0, + opnd1 + ); +} + +/// shr - Shift logical right (unsigned) +void shr(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_shift( + cb, + "shr", + 0xD1, // opMemOnePref, + 0xD3, // opMemClPref, + 0xC1, // opMemImmPref, + 0x05, + opnd0, + opnd1 + ); +} + +/// sub - Integer subtraction +void sub(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "sub", + 0x28, // opMemReg8 + 0x29, // opMemRegPref + 0x2A, // opRegMem8 + 0x2B, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x05, // opExtImm + opnd0, + opnd1 + ); +} + +/// test - Logical Compare +void test(codeblock_t *cb, x86opnd_t rm_opnd, x86opnd_t test_opnd) +{ + assert (rm_opnd.type == OPND_REG || rm_opnd.type == OPND_MEM); + assert (test_opnd.type == OPND_REG || test_opnd.type == OPND_IMM); + + // If the second operand is an immediate + if (test_opnd.type == OPND_IMM) + { + x86opnd_t imm_opnd = test_opnd; + + if (imm_opnd.as.imm >= 0) + { + assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= 32); + assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= rm_opnd.num_bits); + + // Use the smallest operand size possible + rm_opnd = resize_opnd(rm_opnd, unsig_imm_size(imm_opnd.as.unsig_imm)); + + if (rm_opnd.num_bits == 8) + { + cb_write_rm(cb, false, false, NO_OPND, rm_opnd, 0x00, 1, 0xF6); + cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + } + else + { + cb_write_rm(cb, rm_opnd.num_bits == 16, false, NO_OPND, rm_opnd, 0x00, 1, 0xF7); + cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + } + } + else + { + // This mode only applies to 64-bit R/M operands with 32-bit signed immediates + assert (imm_opnd.as.imm < 0); + assert (sig_imm_size(imm_opnd.as.imm) <= 32); + assert (rm_opnd.num_bits == 64); + cb_write_rm(cb, false, true, NO_OPND, rm_opnd, 0x00, 1, 0xF7); + cb_write_int(cb, imm_opnd.as.imm, 32); + } + } + else + { + assert (test_opnd.num_bits == rm_opnd.num_bits); + + if (rm_opnd.num_bits == 8) + { + cb_write_rm(cb, false, false, test_opnd, rm_opnd, 0xFF, 1, 0x84); + } + else + { + cb_write_rm(cb, rm_opnd.num_bits == 16, rm_opnd.num_bits == 64, test_opnd, rm_opnd, 0xFF, 1, 0x85); + } + } +} + +/// Undefined opcode +void ud2(codeblock_t *cb) +{ + cb_write_bytes(cb, 2, 0x0F, 0x0B); +} + +/// xchg - Exchange Register/Memory with Register +void xchg(codeblock_t *cb, x86opnd_t rm_opnd, x86opnd_t r_opnd) +{ + assert (rm_opnd.num_bits == 64); + assert (r_opnd.num_bits == 64); + assert (rm_opnd.type == OPND_REG); + assert (r_opnd.type == OPND_REG); + + // If we're exchanging with RAX + if (rm_opnd.type == OPND_REG && rm_opnd.as.reg.reg_no == RAX.as.reg.reg_no) + { + // Write the REX byte + cb_write_rex(cb, rm_opnd.num_bits == 64, 0, 0, r_opnd.as.reg.reg_no); + + // Write the opcode and register number + cb_write_byte(cb, 0x90 + (r_opnd.as.reg.reg_no & 7)); + } + else + { + cb_write_rm(cb, rm_opnd.num_bits == 16, rm_opnd.num_bits == 64, r_opnd, rm_opnd, 0xFF, 1, 0x87); + } +} + +/// xor - Exclusive bitwise OR +void xor(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "xor", + 0x30, // opMemReg8 + 0x31, // opMemRegPref + 0x32, // opRegMem8 + 0x33, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x06, // opExtImm + opnd0, + opnd1 + ); +} + +// LOCK - lock prefix for atomic shared memory operations +void cb_write_lock_prefix(codeblock_t *cb) +{ + cb_write_byte(cb, 0xF0); +} + +void cb_mark_all_writeable(codeblock_t * cb) +{ + if (mprotect(cb->mem_block_, cb->mem_size, PROT_READ | PROT_WRITE)) { + fprintf(stderr, "Couldn't make JIT page (%p) writeable, errno: %s", (void *)cb->mem_block_, strerror(errno)); + abort(); + } +} + +void cb_mark_position_writeable(codeblock_t * cb, uint32_t write_pos) +{ + uint32_t pagesize = (uint32_t)sysconf(_SC_PAGESIZE); + uint32_t aligned_position = (write_pos / pagesize) * pagesize; + + if (cb->current_aligned_write_pos != aligned_position) { + cb->current_aligned_write_pos = aligned_position; + void *const page_addr = cb_get_ptr(cb, aligned_position); + if (mprotect(page_addr, pagesize, PROT_READ | PROT_WRITE)) { + fprintf(stderr, "Couldn't make JIT page (%p) writeable, errno: %s", page_addr, strerror(errno)); + abort(); + } + } +} + +void cb_mark_all_executable(codeblock_t * cb) +{ + cb->current_aligned_write_pos = ALIGNED_WRITE_POSITION_NONE; + if (mprotect(cb->mem_block_, cb->mem_size, PROT_READ | PROT_EXEC)) { + fprintf(stderr, "Couldn't make JIT page (%p) executable, errno: %s", (void *)cb->mem_block_, strerror(errno)); + abort(); + } +} + diff --git a/ruby/yjit_asm.h b/ruby/yjit_asm.h new file mode 100644 index 000000000..202f21e79 --- /dev/null +++ b/ruby/yjit_asm.h @@ -0,0 +1,408 @@ +#ifndef YJIT_ASM_H +#define YJIT_ASM_H 1 + +#include +#include +#include + +// Maximum number of labels to link +#define MAX_LABELS 32 + +// Maximum number of label references +#define MAX_LABEL_REFS 32 + +// Reference to an ASM label +typedef struct LabelRef +{ + // Position in the code block where the label reference exists + uint32_t pos; + + // Label which this refers to + uint32_t label_idx; + +} labelref_t; + +// Block of executable memory into which instructions can be written +typedef struct CodeBlock +{ + // Memory block + // Users are advised to not use this directly. + uint8_t *mem_block_; + + // Memory block size + uint32_t mem_size; + + // Current writing position + uint32_t write_pos; + + // Table of registered label addresses + uint32_t label_addrs[MAX_LABELS]; + + // Table of registered label names + // Note that these should be constant strings only + const char *label_names[MAX_LABELS]; + + // References to labels + labelref_t label_refs[MAX_LABEL_REFS]; + + // Number of labels registeered + uint32_t num_labels; + + // Number of references to labels + uint32_t num_refs; + + + // Keep track of the current aligned write position. + // Used for changing protection when writing to the JIT buffer + uint32_t current_aligned_write_pos; + + // Set if the assembler is unable to output some instructions, + // for example, when there is not enough space or when a jump + // target is too far away. + bool dropped_bytes; + + // Flag to enable or disable comments + bool has_asm; + + +} codeblock_t; + +// 1 is not aligned so this won't match any pages +#define ALIGNED_WRITE_POSITION_NONE 1 + +enum OpndType +{ + OPND_NONE, + OPND_REG, + OPND_IMM, + OPND_MEM +}; + +enum RegType +{ + REG_GP, + REG_FP, + REG_XMM, + REG_IP +}; + +typedef struct X86Reg +{ + // Register type + uint8_t reg_type; + + // Register index number + uint8_t reg_no; + +} x86reg_t; + +typedef struct X86Mem +{ + /// Base register number + uint8_t base_reg_no; + + /// Index register number + uint8_t idx_reg_no; + + /// SIB scale exponent value (power of two, two bits) + uint8_t scale_exp; + + /// Has index register flag + bool has_idx; + + // TODO: should this be here, or should we have an extra operand type? + /// IP-relative addressing flag + bool is_iprel; + + /// Constant displacement from the base, not scaled + int32_t disp; + +} x86mem_t; + +typedef struct X86Opnd +{ + // Operand type + uint8_t type; + + // Size in bits + uint16_t num_bits; + + union + { + // Register operand + x86reg_t reg; + + // Memory operand + x86mem_t mem; + + // Signed immediate value + int64_t imm; + + // Unsigned immediate value + uint64_t unsig_imm; + } as; + +} x86opnd_t; + +// Dummy none/null operand +static const x86opnd_t NO_OPND = { OPND_NONE, 0, .as.imm = 0 }; + +// Instruction pointer +static const x86opnd_t RIP = { OPND_REG, 64, .as.reg = { REG_IP, 5 }}; + +// 64-bit GP registers +static const x86opnd_t RAX = { OPND_REG, 64, .as.reg = { REG_GP, 0 }}; +static const x86opnd_t RCX = { OPND_REG, 64, .as.reg = { REG_GP, 1 }}; +static const x86opnd_t RDX = { OPND_REG, 64, .as.reg = { REG_GP, 2 }}; +static const x86opnd_t RBX = { OPND_REG, 64, .as.reg = { REG_GP, 3 }}; +static const x86opnd_t RSP = { OPND_REG, 64, .as.reg = { REG_GP, 4 }}; +static const x86opnd_t RBP = { OPND_REG, 64, .as.reg = { REG_GP, 5 }}; +static const x86opnd_t RSI = { OPND_REG, 64, .as.reg = { REG_GP, 6 }}; +static const x86opnd_t RDI = { OPND_REG, 64, .as.reg = { REG_GP, 7 }}; +static const x86opnd_t R8 = { OPND_REG, 64, .as.reg = { REG_GP, 8 }}; +static const x86opnd_t R9 = { OPND_REG, 64, .as.reg = { REG_GP, 9 }}; +static const x86opnd_t R10 = { OPND_REG, 64, .as.reg = { REG_GP, 10 }}; +static const x86opnd_t R11 = { OPND_REG, 64, .as.reg = { REG_GP, 11 }}; +static const x86opnd_t R12 = { OPND_REG, 64, .as.reg = { REG_GP, 12 }}; +static const x86opnd_t R13 = { OPND_REG, 64, .as.reg = { REG_GP, 13 }}; +static const x86opnd_t R14 = { OPND_REG, 64, .as.reg = { REG_GP, 14 }}; +static const x86opnd_t R15 = { OPND_REG, 64, .as.reg = { REG_GP, 15 }}; + +// 32-bit GP registers +static const x86opnd_t EAX = { OPND_REG, 32, .as.reg = { REG_GP, 0 }}; +static const x86opnd_t ECX = { OPND_REG, 32, .as.reg = { REG_GP, 1 }}; +static const x86opnd_t EDX = { OPND_REG, 32, .as.reg = { REG_GP, 2 }}; +static const x86opnd_t EBX = { OPND_REG, 32, .as.reg = { REG_GP, 3 }}; +static const x86opnd_t ESP = { OPND_REG, 32, .as.reg = { REG_GP, 4 }}; +static const x86opnd_t EBP = { OPND_REG, 32, .as.reg = { REG_GP, 5 }}; +static const x86opnd_t ESI = { OPND_REG, 32, .as.reg = { REG_GP, 6 }}; +static const x86opnd_t EDI = { OPND_REG, 32, .as.reg = { REG_GP, 7 }}; +static const x86opnd_t R8D = { OPND_REG, 32, .as.reg = { REG_GP, 8 }}; +static const x86opnd_t R9D = { OPND_REG, 32, .as.reg = { REG_GP, 9 }}; +static const x86opnd_t R10D = { OPND_REG, 32, .as.reg = { REG_GP, 10 }}; +static const x86opnd_t R11D = { OPND_REG, 32, .as.reg = { REG_GP, 11 }}; +static const x86opnd_t R12D = { OPND_REG, 32, .as.reg = { REG_GP, 12 }}; +static const x86opnd_t R13D = { OPND_REG, 32, .as.reg = { REG_GP, 13 }}; +static const x86opnd_t R14D = { OPND_REG, 32, .as.reg = { REG_GP, 14 }}; +static const x86opnd_t R15D = { OPND_REG, 32, .as.reg = { REG_GP, 15 }}; + +// 16-bit GP registers +static const x86opnd_t AX = { OPND_REG, 16, .as.reg = { REG_GP, 0 }}; +static const x86opnd_t CX = { OPND_REG, 16, .as.reg = { REG_GP, 1 }}; +static const x86opnd_t DX = { OPND_REG, 16, .as.reg = { REG_GP, 2 }}; +static const x86opnd_t BX = { OPND_REG, 16, .as.reg = { REG_GP, 3 }}; +static const x86opnd_t SP = { OPND_REG, 16, .as.reg = { REG_GP, 4 }}; +static const x86opnd_t BP = { OPND_REG, 16, .as.reg = { REG_GP, 5 }}; +static const x86opnd_t SI = { OPND_REG, 16, .as.reg = { REG_GP, 6 }}; +static const x86opnd_t DI = { OPND_REG, 16, .as.reg = { REG_GP, 7 }}; +static const x86opnd_t R8W = { OPND_REG, 16, .as.reg = { REG_GP, 8 }}; +static const x86opnd_t R9W = { OPND_REG, 16, .as.reg = { REG_GP, 9 }}; +static const x86opnd_t R10W = { OPND_REG, 16, .as.reg = { REG_GP, 10 }}; +static const x86opnd_t R11W = { OPND_REG, 16, .as.reg = { REG_GP, 11 }}; +static const x86opnd_t R12W = { OPND_REG, 16, .as.reg = { REG_GP, 12 }}; +static const x86opnd_t R13W = { OPND_REG, 16, .as.reg = { REG_GP, 13 }}; +static const x86opnd_t R14W = { OPND_REG, 16, .as.reg = { REG_GP, 14 }}; +static const x86opnd_t R15W = { OPND_REG, 16, .as.reg = { REG_GP, 15 }}; + +// 8-bit GP registers +static const x86opnd_t AL = { OPND_REG, 8, .as.reg = { REG_GP, 0 }}; +static const x86opnd_t CL = { OPND_REG, 8, .as.reg = { REG_GP, 1 }}; +static const x86opnd_t DL = { OPND_REG, 8, .as.reg = { REG_GP, 2 }}; +static const x86opnd_t BL = { OPND_REG, 8, .as.reg = { REG_GP, 3 }}; +static const x86opnd_t SPL = { OPND_REG, 8, .as.reg = { REG_GP, 4 }}; +static const x86opnd_t BPL = { OPND_REG, 8, .as.reg = { REG_GP, 5 }}; +static const x86opnd_t SIL = { OPND_REG, 8, .as.reg = { REG_GP, 6 }}; +static const x86opnd_t DIL = { OPND_REG, 8, .as.reg = { REG_GP, 7 }}; +static const x86opnd_t R8B = { OPND_REG, 8, .as.reg = { REG_GP, 8 }}; +static const x86opnd_t R9B = { OPND_REG, 8, .as.reg = { REG_GP, 9 }}; +static const x86opnd_t R10B = { OPND_REG, 8, .as.reg = { REG_GP, 10 }}; +static const x86opnd_t R11B = { OPND_REG, 8, .as.reg = { REG_GP, 11 }}; +static const x86opnd_t R12B = { OPND_REG, 8, .as.reg = { REG_GP, 12 }}; +static const x86opnd_t R13B = { OPND_REG, 8, .as.reg = { REG_GP, 13 }}; +static const x86opnd_t R14B = { OPND_REG, 8, .as.reg = { REG_GP, 14 }}; +static const x86opnd_t R15B = { OPND_REG, 8, .as.reg = { REG_GP, 15 }}; + +// C argument registers +#define NUM_C_ARG_REGS 6 +#define C_ARG_REGS ( (x86opnd_t[]){ RDI, RSI, RDX, RCX, R8, R9 } ) + +// Compute the number of bits needed to store a signed or unsigned value +static inline uint32_t sig_imm_size(int64_t imm); +static inline uint32_t unsig_imm_size(uint64_t imm); + +// Memory operand with base register and displacement/offset +static inline x86opnd_t mem_opnd(uint32_t num_bits, x86opnd_t base_reg, int32_t disp); + +// Scale-index-base memory operand +static inline x86opnd_t mem_opnd_sib(uint32_t num_bits, x86opnd_t base_reg, x86opnd_t index_reg, int32_t scale, int32_t disp); + +// Immediate number operand +static inline x86opnd_t imm_opnd(int64_t val); + +// Constant pointer operand +static inline x86opnd_t const_ptr_opnd(const void *ptr); + +// Struct member operand +#define member_opnd(base_reg, struct_type, member_name) mem_opnd( \ + 8 * sizeof(((struct_type*)0)->member_name), \ + base_reg, \ + offsetof(struct_type, member_name) \ +) + +// Struct member operand with an array index +#define member_opnd_idx(base_reg, struct_type, member_name, idx) mem_opnd( \ + 8 * sizeof(((struct_type*)0)->member_name[0]), \ + base_reg, \ + (offsetof(struct_type, member_name) + \ + sizeof(((struct_type*)0)->member_name[0]) * idx) \ +) + +// Allocate executable memory +static uint8_t *alloc_exec_mem(uint32_t mem_size); + +// Code block functions +static inline void cb_init(codeblock_t *cb, uint8_t *mem_block, uint32_t mem_size); +static inline void cb_align_pos(codeblock_t *cb, uint32_t multiple); +static inline void cb_set_pos(codeblock_t *cb, uint32_t pos); +static inline void cb_set_write_ptr(codeblock_t *cb, uint8_t *code_ptr); +static inline uint8_t *cb_get_ptr(const codeblock_t *cb, uint32_t index); +static inline uint8_t *cb_get_write_ptr(const codeblock_t *cb); +static inline void cb_write_byte(codeblock_t *cb, uint8_t byte); +static inline void cb_write_bytes(codeblock_t *cb, uint32_t num_bytes, ...); +static inline void cb_write_int(codeblock_t *cb, uint64_t val, uint32_t num_bits); +static inline uint32_t cb_new_label(codeblock_t *cb, const char *name); +static inline void cb_write_label(codeblock_t *cb, uint32_t label_idx); +static inline void cb_label_ref(codeblock_t *cb, uint32_t label_idx); +static inline void cb_link_labels(codeblock_t *cb); +static inline void cb_mark_all_writeable(codeblock_t *cb); +static inline void cb_mark_position_writeable(codeblock_t *cb, uint32_t write_pos); +static inline void cb_mark_all_executable(codeblock_t *cb); + +// Encode individual instructions into a code block +static inline void add(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void and(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void call_ptr(codeblock_t *cb, x86opnd_t scratch_reg, uint8_t *dst_ptr); +static inline void call_label(codeblock_t *cb, uint32_t label_idx); +static inline void call(codeblock_t *cb, x86opnd_t opnd); +static inline void cmova(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovae(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovb(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovbe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovc(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmove(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovg(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovge(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovl(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovle(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovna(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnae(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnb(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnbe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnc(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovne(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovng(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnge(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnl(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnle(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovno(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnp(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovns(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovnz(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovo(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovp(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovpe(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovpo(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovs(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmovz(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void cmp(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void cdq(codeblock_t *cb); +static inline void cqo(codeblock_t *cb); +static inline void int3(codeblock_t *cb); +static inline void ja_label(codeblock_t *cb, uint32_t label_idx); +static inline void jae_label(codeblock_t *cb, uint32_t label_idx); +static inline void jb_label(codeblock_t *cb, uint32_t label_idx); +static inline void jbe_label(codeblock_t *cb, uint32_t label_idx); +static inline void jc_label(codeblock_t *cb, uint32_t label_idx); +static inline void je_label(codeblock_t *cb, uint32_t label_idx); +static inline void jg_label(codeblock_t *cb, uint32_t label_idx); +static inline void jge_label(codeblock_t *cb, uint32_t label_idx); +static inline void jl_label(codeblock_t *cb, uint32_t label_idx); +static inline void jle_label(codeblock_t *cb, uint32_t label_idx); +static inline void jna_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnae_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnb_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnbe_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnc_label(codeblock_t *cb, uint32_t label_idx); +static inline void jne_label(codeblock_t *cb, uint32_t label_idx); +static inline void jng_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnge_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnl_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnle_label(codeblock_t *cb, uint32_t label_idx); +static inline void jno_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnp_label(codeblock_t *cb, uint32_t label_idx); +static inline void jns_label(codeblock_t *cb, uint32_t label_idx); +static inline void jnz_label(codeblock_t *cb, uint32_t label_idx); +static inline void jo_label(codeblock_t *cb, uint32_t label_idx); +static inline void jp_label(codeblock_t *cb, uint32_t label_idx); +static inline void jpe_label(codeblock_t *cb, uint32_t label_idx); +static inline void jpo_label(codeblock_t *cb, uint32_t label_idx); +static inline void js_label(codeblock_t *cb, uint32_t label_idx); +static inline void jz_label(codeblock_t *cb, uint32_t label_idx); +static inline void ja_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jae_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jb_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jbe_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jc_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void je_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jg_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jge_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jl_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jle_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jna_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnae_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnb_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnbe_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnc_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jne_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jng_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnge_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnl_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnle_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jno_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnp_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jns_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jnz_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jo_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jp_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jpe_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jpo_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void js_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jz_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jmp_label(codeblock_t *cb, uint32_t label_idx); +static inline void jmp_ptr(codeblock_t *cb, uint8_t *ptr); +static inline void jmp_rm(codeblock_t *cb, x86opnd_t opnd); +static inline void jmp32(codeblock_t *cb, int32_t offset); +static inline void lea(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void mov(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void movsx(codeblock_t *cb, x86opnd_t dst, x86opnd_t src); +static inline void neg(codeblock_t *cb, x86opnd_t opnd); +static inline void nop(codeblock_t *cb, uint32_t length); +static inline void not(codeblock_t *cb, x86opnd_t opnd); +static inline void or(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void pop(codeblock_t *cb, x86opnd_t reg); +static inline void popfq(codeblock_t *cb); +static inline void push(codeblock_t *cb, x86opnd_t opnd); +static inline void pushfq(codeblock_t *cb); +static inline void ret(codeblock_t *cb); +static inline void sal(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void sar(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void shl(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void shr(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void sub(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void test(codeblock_t *cb, x86opnd_t rm_opnd, x86opnd_t test_opnd); +static inline void ud2(codeblock_t *cb); +static inline void xchg(codeblock_t *cb, x86opnd_t rm_opnd, x86opnd_t r_opnd); +static inline void xor(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); +static inline void cb_write_lock_prefix(codeblock_t *cb); + +#endif diff --git a/ruby/yjit_codegen.c b/ruby/yjit_codegen.c new file mode 100644 index 000000000..21e4813c1 --- /dev/null +++ b/ruby/yjit_codegen.c @@ -0,0 +1,5062 @@ +// This file is a fragment of the yjit.o compilation unit. See yjit.c. +#include "internal.h" +#include "gc.h" +#include "internal/compile.h" +#include "internal/class.h" +#include "internal/hash.h" +#include "internal/object.h" +#include "internal/sanitizers.h" +#include "internal/string.h" +#include "internal/struct.h" +#include "internal/variable.h" +#include "internal/re.h" +#include "probes.h" +#include "probes_helper.h" +#include "yjit.h" +#include "yjit_iface.h" +#include "yjit_core.h" +#include "yjit_codegen.h" +#include "yjit_asm.h" + +// Map from YARV opcodes to code generation functions +static codegen_fn gen_fns[VM_INSTRUCTION_SIZE] = { NULL }; + +// Map from method entries to code generation functions +static st_table *yjit_method_codegen_table = NULL; + +// Code for exiting back to the interpreter from the leave instruction +static void *leave_exit_code; + +// Code for full logic of returning from C method and exiting to the interpreter +static uint32_t outline_full_cfunc_return_pos; + +// For implementing global code invalidation +struct codepage_patch { + uint32_t inline_patch_pos; + uint32_t outlined_target_pos; +}; + +typedef rb_darray(struct codepage_patch) patch_array_t; + +static patch_array_t global_inval_patches = NULL; + +// Print the current source location for debugging purposes +RBIMPL_ATTR_MAYBE_UNUSED() +static void +jit_print_loc(jitstate_t *jit, const char *msg) +{ + char *ptr; + long len; + VALUE path = rb_iseq_path(jit->iseq); + RSTRING_GETMEM(path, ptr, len); + fprintf(stderr, "%s %.*s:%u\n", msg, (int)len, ptr, rb_iseq_line_no(jit->iseq, jit->insn_idx)); +} + +// dump an object for debugging purposes +RBIMPL_ATTR_MAYBE_UNUSED() +static void +jit_obj_info_dump(codeblock_t *cb, x86opnd_t opnd) { + push_regs(cb); + mov(cb, C_ARG_REGS[0], opnd); + call_ptr(cb, REG0, (void *)rb_obj_info_dump); + pop_regs(cb); +} + +// Get the current instruction's opcode +static int +jit_get_opcode(jitstate_t *jit) +{ + return jit->opcode; +} + +// Get the index of the next instruction +static uint32_t +jit_next_insn_idx(jitstate_t *jit) +{ + return jit->insn_idx + insn_len(jit_get_opcode(jit)); +} + +// Get an instruction argument by index +static VALUE +jit_get_arg(jitstate_t *jit, size_t arg_idx) +{ + RUBY_ASSERT(arg_idx + 1 < (size_t)insn_len(jit_get_opcode(jit))); + return *(jit->pc + arg_idx + 1); +} + +// Load a VALUE into a register and keep track of the reference if it is on the GC heap. +static void +jit_mov_gc_ptr(jitstate_t *jit, codeblock_t *cb, x86opnd_t reg, VALUE ptr) +{ + RUBY_ASSERT(reg.type == OPND_REG && reg.num_bits == 64); + + // Load the pointer constant into the specified register + mov(cb, reg, const_ptr_opnd((void*)ptr)); + + // The pointer immediate is encoded as the last part of the mov written out + uint32_t ptr_offset = cb->write_pos - sizeof(VALUE); + + if (!SPECIAL_CONST_P(ptr)) { + if (!rb_darray_append(&jit->block->gc_object_offsets, ptr_offset)) { + rb_bug("allocation failed"); + } + } +} + +// Check if we are compiling the instruction at the stub PC +// Meaning we are compiling the instruction that is next to execute +static bool +jit_at_current_insn(jitstate_t *jit) +{ + const VALUE *ec_pc = jit->ec->cfp->pc; + return (ec_pc == jit->pc); +} + +// Peek at the nth topmost value on the Ruby stack. +// Returns the topmost value when n == 0. +static VALUE +jit_peek_at_stack(jitstate_t *jit, ctx_t *ctx, int n) +{ + RUBY_ASSERT(jit_at_current_insn(jit)); + + // Note: this does not account for ctx->sp_offset because + // this is only available when hitting a stub, and while + // hitting a stub, cfp->sp needs to be up to date in case + // codegen functions trigger GC. See :stub-sp-flush:. + VALUE *sp = jit->ec->cfp->sp; + + return *(sp - 1 - n); +} + +static VALUE +jit_peek_at_self(jitstate_t *jit, ctx_t *ctx) +{ + return jit->ec->cfp->self; +} + +RBIMPL_ATTR_MAYBE_UNUSED() +static VALUE +jit_peek_at_local(jitstate_t *jit, ctx_t *ctx, int n) +{ + RUBY_ASSERT(jit_at_current_insn(jit)); + + int32_t local_table_size = jit->iseq->body->local_table_size; + RUBY_ASSERT(n < (int)jit->iseq->body->local_table_size); + + const VALUE *ep = jit->ec->cfp->ep; + return ep[-VM_ENV_DATA_SIZE - local_table_size + n + 1]; +} + +// Save the incremented PC on the CFP +// This is necessary when calleees can raise or allocate +static void +jit_save_pc(jitstate_t *jit, x86opnd_t scratch_reg) +{ + codeblock_t *cb = jit->cb; + mov(cb, scratch_reg, const_ptr_opnd(jit->pc + insn_len(jit->opcode))); + mov(cb, mem_opnd(64, REG_CFP, offsetof(rb_control_frame_t, pc)), scratch_reg); +} + +// Save the current SP on the CFP +// This realigns the interpreter SP with the JIT SP +// Note: this will change the current value of REG_SP, +// which could invalidate memory operands +static void +jit_save_sp(jitstate_t *jit, ctx_t *ctx) +{ + if (ctx->sp_offset != 0) { + x86opnd_t stack_pointer = ctx_sp_opnd(ctx, 0); + codeblock_t *cb = jit->cb; + lea(cb, REG_SP, stack_pointer); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG_SP); + ctx->sp_offset = 0; + } +} + +// jit_save_pc() + jit_save_sp(). Should be used before calling a routine that +// could: +// - Perform GC allocation +// - Take the VM lock through RB_VM_LOCK_ENTER() +// - Perform Ruby method call +static void +jit_prepare_routine_call(jitstate_t *jit, ctx_t *ctx, x86opnd_t scratch_reg) +{ + jit->record_boundary_patch_point = true; + jit_save_pc(jit, scratch_reg); + jit_save_sp(jit, ctx); +} + +// Record the current codeblock write position for rewriting into a jump into +// the outlined block later. Used to implement global code invalidation. +static void +record_global_inval_patch(const codeblock_t *cb, uint32_t outline_block_target_pos) +{ + struct codepage_patch patch_point = { cb->write_pos, outline_block_target_pos }; + if (!rb_darray_append(&global_inval_patches, patch_point)) rb_bug("allocation failed"); +} + +static bool jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_t insn_opnd, VALUE sample_instance, const int max_chain_depth, uint8_t *side_exit); + +#if YJIT_STATS + +// Add a comment at the current position in the code block +static void +_add_comment(codeblock_t *cb, const char *comment_str) +{ + // We can't add comments to the outlined code block + if (cb == ocb) + return; + + // Avoid adding duplicate comment strings (can happen due to deferred codegen) + size_t num_comments = rb_darray_size(yjit_code_comments); + if (num_comments > 0) { + struct yjit_comment last_comment = rb_darray_get(yjit_code_comments, num_comments - 1); + if (last_comment.offset == cb->write_pos && strcmp(last_comment.comment, comment_str) == 0) { + return; + } + } + + struct yjit_comment new_comment = (struct yjit_comment){ cb->write_pos, comment_str }; + rb_darray_append(&yjit_code_comments, new_comment); +} + +// Comments for generated machine code +#define ADD_COMMENT(cb, comment) _add_comment((cb), (comment)) + +// Verify the ctx's types and mappings against the compile-time stack, self, +// and locals. +static void +verify_ctx(jitstate_t *jit, ctx_t *ctx) +{ + // Only able to check types when at current insn + RUBY_ASSERT(jit_at_current_insn(jit)); + + VALUE self_val = jit_peek_at_self(jit, ctx); + if (type_diff(yjit_type_of_value(self_val), ctx->self_type) == INT_MAX) { + rb_bug("verify_ctx: ctx type (%s) incompatible with actual value of self: %s", yjit_type_name(ctx->self_type), rb_obj_info(self_val)); + } + + for (int i = 0; i < ctx->stack_size && i < MAX_TEMP_TYPES; i++) { + temp_type_mapping_t learned = ctx_get_opnd_mapping(ctx, OPND_STACK(i)); + VALUE val = jit_peek_at_stack(jit, ctx, i); + val_type_t detected = yjit_type_of_value(val); + + if (learned.mapping.kind == TEMP_SELF) { + if (self_val != val) { + rb_bug("verify_ctx: stack value was mapped to self, but values did not match\n" + " stack: %s\n" + " self: %s", + rb_obj_info(val), + rb_obj_info(self_val)); + } + } + + if (learned.mapping.kind == TEMP_LOCAL) { + int local_idx = learned.mapping.idx; + VALUE local_val = jit_peek_at_local(jit, ctx, local_idx); + if (local_val != val) { + rb_bug("verify_ctx: stack value was mapped to local, but values did not match\n" + " stack: %s\n" + " local %i: %s", + rb_obj_info(val), + local_idx, + rb_obj_info(local_val)); + } + } + + if (type_diff(detected, learned.type) == INT_MAX) { + rb_bug("verify_ctx: ctx type (%s) incompatible with actual value on stack: %s", yjit_type_name(learned.type), rb_obj_info(val)); + } + } + + int32_t local_table_size = jit->iseq->body->local_table_size; + for (int i = 0; i < local_table_size && i < MAX_TEMP_TYPES; i++) { + val_type_t learned = ctx->local_types[i]; + VALUE val = jit_peek_at_local(jit, ctx, i); + val_type_t detected = yjit_type_of_value(val); + + if (type_diff(detected, learned) == INT_MAX) { + rb_bug("verify_ctx: ctx type (%s) incompatible with actual value of local: %s", yjit_type_name(learned), rb_obj_info(val)); + } + } +} + +#else + +#define ADD_COMMENT(cb, comment) ((void)0) +#define verify_ctx(jit, ctx) ((void)0) + +#endif // if YJIT_STATS + +#if YJIT_STATS + +// Increment a profiling counter with counter_name +#define GEN_COUNTER_INC(cb, counter_name) _gen_counter_inc(cb, &(yjit_runtime_counters . counter_name)) +static void +_gen_counter_inc(codeblock_t *cb, int64_t *counter) +{ + if (!rb_yjit_opts.gen_stats) return; + + // Use REG1 because there might be return value in REG0 + mov(cb, REG1, const_ptr_opnd(counter)); + cb_write_lock_prefix(cb); // for ractors. + add(cb, mem_opnd(64, REG1, 0), imm_opnd(1)); +} + +// Increment a counter then take an existing side exit. +#define COUNTED_EXIT(jit, side_exit, counter_name) _counted_side_exit(jit, side_exit, &(yjit_runtime_counters . counter_name)) +static uint8_t * +_counted_side_exit(jitstate_t* jit, uint8_t *existing_side_exit, int64_t *counter) +{ + if (!rb_yjit_opts.gen_stats) return existing_side_exit; + + uint8_t *start = cb_get_ptr(jit->ocb, jit->ocb->write_pos); + _gen_counter_inc(jit->ocb, counter); + jmp_ptr(jit->ocb, existing_side_exit); + return start; +} + +#else + +#define GEN_COUNTER_INC(cb, counter_name) ((void)0) +#define COUNTED_EXIT(jit, side_exit, counter_name) side_exit + +#endif // if YJIT_STATS + +// 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); + + // Accumulate stats about interpreter exits +#if YJIT_STATS + if (rb_yjit_opts.gen_stats) { + mov(cb, RDI, const_ptr_opnd(exit_pc)); + call_ptr(cb, RSI, (void *)&yjit_count_side_exit_op); + } +#endif + + pop(cb, REG_SP); + pop(cb, REG_EC); + pop(cb, REG_CFP); + + mov(cb, RAX, imm_opnd(Qundef)); + ret(cb); + + return code_pos; +} + +// Generate a continuation for gen_leave() that exits to the interpreter at REG_CFP->pc. +static uint8_t * +yjit_gen_leave_exit(codeblock_t *cb) +{ + uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos); + + // Note, gen_leave() fully reconstructs interpreter state and leaves the + // return value in RAX before coming here. + + // Every exit to the interpreter should be counted + GEN_COUNTER_INC(cb, leave_interp_return); + + pop(cb, REG_SP); + pop(cb, REG_EC); + pop(cb, REG_CFP); + + ret(cb); + + return code_ptr; +} + +// Fill code_for_exit_from_stub. This is used by branch_stub_hit() to exit +// to the interpreter when it cannot service a stub by generating new code. +// Before coming here, branch_stub_hit() takes care of fully reconstructing +// interpreter state. +static void +gen_code_for_exit_from_stub(void) +{ + codeblock_t *cb = ocb; + code_for_exit_from_stub = cb_get_ptr(cb, cb->write_pos); + + GEN_COUNTER_INC(cb, exit_from_branch_stub); + + pop(cb, REG_SP); + pop(cb, REG_EC); + pop(cb, REG_CFP); + + mov(cb, RAX, imm_opnd(Qundef)); + ret(cb); +} + +// :side-exit: +// Get an exit for the current instruction in the outlined block. The code +// for each instruction often begins with several guards before proceeding +// to do work. When guards fail, an option we have is to exit to the +// interpreter at an instruction boundary. The piece of code that takes +// care of reconstructing interpreter state and exiting out of generated +// code is called the side exit. +// +// No guards change the logic for reconstructing interpreter state at the +// moment, so there is one unique side exit for each context. Note that +// it's incorrect to jump to the side exit after any ctx stack push/pop operations +// since they change the logic required for reconstructing interpreter state. +static uint8_t * +yjit_side_exit(jitstate_t *jit, ctx_t *ctx) +{ + if (!jit->side_exit_for_pc) { + codeblock_t *ocb = jit->ocb; + uint32_t pos = yjit_gen_exit(jit->pc, ctx, ocb); + jit->side_exit_for_pc = cb_get_ptr(ocb, pos); + } + + return jit->side_exit_for_pc; +} + +// Ensure that there is an exit for the start of the block being compiled. +// Block invalidation uses this exit. +static void +jit_ensure_block_entry_exit(jitstate_t *jit) +{ + block_t *block = jit->block; + if (block->entry_exit) return; + + if (jit->insn_idx == block->blockid.idx) { + // We are compiling the first instruction in the block. + // Generate the exit with the cache in jitstate. + block->entry_exit = yjit_side_exit(jit, &block->ctx); + } + else { + VALUE *pc = yjit_iseq_pc_at_idx(block->blockid.iseq, block->blockid.idx); + uint32_t pos = yjit_gen_exit(pc, &block->ctx, ocb); + block->entry_exit = cb_get_ptr(ocb, pos); + } +} + +// Generate a runtime guard that ensures the PC is at the start of the iseq, +// otherwise take a side exit. This is to handle the situation of optional +// parameters. When a function with optional parameters is called, the entry +// PC for the method isn't necessarily 0, but we always generated code that +// assumes the entry point is 0. +static void +yjit_pc_guard(codeblock_t *cb, const rb_iseq_t *iseq) +{ + RUBY_ASSERT(cb != NULL); + + mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, pc)); + mov(cb, REG1, const_ptr_opnd(iseq->body->iseq_encoded)); + xor(cb, REG0, REG1); + + // xor should impact ZF, so we can jz here + uint32_t pc_is_zero = cb_new_label(cb, "pc_is_zero"); + jz_label(cb, pc_is_zero); + + // We're not starting at the first PC, so we need to exit. + GEN_COUNTER_INC(cb, leave_start_pc_non_zero); + + pop(cb, REG_SP); + pop(cb, REG_EC); + pop(cb, REG_CFP); + + mov(cb, RAX, imm_opnd(Qundef)); + ret(cb); + + // PC should be at the beginning + cb_write_label(cb, pc_is_zero); + cb_link_labels(cb); +} + +// The code we generate in gen_send_cfunc() doesn't fire the c_return TracePoint event +// like the interpreter. When tracing for c_return is enabled, we patch the code after +// the C method return to call into this to fire the event. +static void +full_cfunc_return(rb_execution_context_t *ec, VALUE return_value) +{ + rb_control_frame_t *cfp = ec->cfp; + RUBY_ASSERT_ALWAYS(cfp == GET_EC()->cfp); + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); + + RUBY_ASSERT_ALWAYS(RUBYVM_CFUNC_FRAME_P(cfp)); + RUBY_ASSERT_ALWAYS(me->def->type == VM_METHOD_TYPE_CFUNC); + + // CHECK_CFP_CONSISTENCY("full_cfunc_return"); TODO revive this + + // Pop the C func's frame and fire the c_return TracePoint event + // Note that this is the same order as vm_call_cfunc_with_frame(). + rb_vm_pop_frame(ec); + EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, cfp->self, me->def->original_id, me->called_id, me->owner, return_value); + // Note, this deviates from the interpreter in that users need to enable + // a c_return TracePoint for this DTrace hook to work. A reasonable change + // since the Ruby return event works this way as well. + RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id); + + // Push return value into the caller's stack. We know that it's a frame that + // uses cfp->sp because we are patching a call done with gen_send_cfunc(). + ec->cfp->sp[0] = return_value; + ec->cfp->sp++; +} + +// Landing code for when c_return tracing is enabled. See full_cfunc_return(). +static void +gen_full_cfunc_return(void) +{ + codeblock_t *cb = ocb; + outline_full_cfunc_return_pos = ocb->write_pos; + + // This chunk of code expect REG_EC to be filled properly and + // RAX to contain the return value of the C method. + + // Call full_cfunc_return() + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], RAX); + call_ptr(cb, REG0, (void *)full_cfunc_return); + + // Count the exit + GEN_COUNTER_INC(cb, traced_cfunc_return); + + // Return to the interpreter + pop(cb, REG_SP); + pop(cb, REG_EC); + pop(cb, REG_CFP); + + mov(cb, RAX, imm_opnd(Qundef)); + ret(cb); +} + +/* +Compile an interpreter entry block to be inserted into an iseq +Returns `NULL` if compilation fails. +*/ +static uint8_t * +yjit_entry_prologue(codeblock_t *cb, const rb_iseq_t *iseq) +{ + RUBY_ASSERT(cb != NULL); + + enum { MAX_PROLOGUE_SIZE = 1024 }; + + // Check if we have enough executable memory + if (cb->write_pos + MAX_PROLOGUE_SIZE >= cb->mem_size) { + return NULL; + } + + const uint32_t old_write_pos = cb->write_pos; + + // Align the current write position to cache line boundaries + cb_align_pos(cb, 64); + + uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos); + ADD_COMMENT(cb, "yjit entry"); + + push(cb, REG_CFP); + push(cb, REG_EC); + push(cb, REG_SP); + + // We are passed EC and CFP + mov(cb, REG_EC, C_ARG_REGS[0]); + mov(cb, REG_CFP, C_ARG_REGS[1]); + + // Load the current SP from the CFP into REG_SP + mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp)); + + // Setup cfp->jit_return + // TODO: this could use an IP relative LEA instead of an 8 byte immediate + mov(cb, REG0, const_ptr_opnd(leave_exit_code)); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0); + + // We're compiling iseqs that we *expect* to start at `insn_idx`. But in + // the case of optional parameters, the interpreter can set the pc to a + // different location depending on the optional parameters. If an iseq + // has optional parameters, we'll add a runtime check that the PC we've + // compiled for is the same PC that the interpreter wants us to run with. + // If they don't match, then we'll take a side exit. + if (iseq->body->param.flags.has_opt) { + yjit_pc_guard(cb, iseq); + } + + // Verify MAX_PROLOGUE_SIZE + RUBY_ASSERT_ALWAYS(cb->write_pos - old_write_pos <= MAX_PROLOGUE_SIZE); + + return code_ptr; +} + +// Generate code to check for interrupts and take a side-exit. +// Warning: this function clobbers REG0 +static void +yjit_check_ints(codeblock_t *cb, uint8_t *side_exit) +{ + // Check for interrupts + // see RUBY_VM_CHECK_INTS(ec) macro + ADD_COMMENT(cb, "RUBY_VM_CHECK_INTS(ec)"); + mov(cb, REG0_32, member_opnd(REG_EC, rb_execution_context_t, interrupt_mask)); + not(cb, REG0_32); + test(cb, member_opnd(REG_EC, rb_execution_context_t, interrupt_flag), REG0_32); + jnz_ptr(cb, side_exit); +} + +// Generate a stubbed unconditional jump to the next bytecode instruction. +// Blocks that are part of a guard chain can use this to share the same successor. +static void +jit_jump_to_next_insn(jitstate_t *jit, const ctx_t *current_context) +{ + // Reset the depth since in current usages we only ever jump to to + // chain_depth > 0 from the same instruction. + ctx_t reset_depth = *current_context; + reset_depth.chain_depth = 0; + + blockid_t jump_block = { jit->iseq, jit_next_insn_idx(jit) }; + + // We are at the end of the current instruction. Record the boundary. + if (jit->record_boundary_patch_point) { + uint32_t exit_pos = yjit_gen_exit(jit->pc + insn_len(jit->opcode), &reset_depth, jit->ocb); + record_global_inval_patch(jit->cb, exit_pos); + jit->record_boundary_patch_point = false; + } + + // Generate the jump instruction + gen_direct_jump( + jit, + &reset_depth, + jump_block + ); +} + +// Compile a sequence of bytecode instructions for a given basic block version. +// Part of gen_block_version(). +static block_t * +gen_single_block(blockid_t blockid, const ctx_t *start_ctx, rb_execution_context_t *ec) +{ + RUBY_ASSERT(cb != NULL); + verify_blockid(blockid); + + // Allocate the new block + block_t *block = calloc(1, sizeof(block_t)); + if (!block) { + return NULL; + } + + // Copy the starting context to avoid mutating it + ctx_t ctx_copy = *start_ctx; + ctx_t *ctx = &ctx_copy; + + // Limit the number of specialized versions for this block + *ctx = limit_block_versions(blockid, ctx); + + // Save the starting context on the block. + block->blockid = blockid; + block->ctx = *ctx; + + RUBY_ASSERT(!(blockid.idx == 0 && start_ctx->stack_size > 0)); + + const rb_iseq_t *iseq = block->blockid.iseq; + const unsigned int iseq_size = iseq->body->iseq_size; + uint32_t insn_idx = block->blockid.idx; + const uint32_t starting_insn_idx = insn_idx; + + // Initialize a JIT state object + jitstate_t jit = { + .cb = cb, + .ocb = ocb, + .block = block, + .iseq = iseq, + .ec = ec + }; + + // Mark the start position of the block + block->start_addr = cb_get_write_ptr(cb); + + // For each instruction to compile + while (insn_idx < iseq_size) { + // Get the current pc and opcode + VALUE *pc = yjit_iseq_pc_at_idx(iseq, insn_idx); + int opcode = yjit_opcode_at_pc(iseq, pc); + RUBY_ASSERT(opcode >= 0 && opcode < VM_INSTRUCTION_SIZE); + + // opt_getinlinecache wants to be in a block all on its own. Cut the block short + // if we run into it. See gen_opt_getinlinecache() for details. + if (opcode == BIN(opt_getinlinecache) && insn_idx > starting_insn_idx) { + jit_jump_to_next_insn(&jit, ctx); + break; + } + + // Set the current instruction + jit.insn_idx = insn_idx; + jit.opcode = opcode; + jit.pc = pc; + jit.side_exit_for_pc = NULL; + + // If previous instruction requested to record the boundary + if (jit.record_boundary_patch_point) { + // Generate an exit to this instruction and record it + uint32_t exit_pos = yjit_gen_exit(jit.pc, ctx, ocb); + record_global_inval_patch(cb, exit_pos); + jit.record_boundary_patch_point = false; + } + + // Verify our existing assumption (DEBUG) + if (jit_at_current_insn(&jit)) { + verify_ctx(&jit, ctx); + } + + // Lookup the codegen function for this instruction + codegen_fn gen_fn = gen_fns[opcode]; + codegen_status_t status = YJIT_CANT_COMPILE; + if (gen_fn) { + if (0) { + fprintf(stderr, "compiling %d: %s\n", insn_idx, insn_name(opcode)); + print_str(cb, insn_name(opcode)); + } + + // :count-placement: + // Count bytecode instructions that execute in generated code. + // Note that the increment happens even when the output takes side exit. + GEN_COUNTER_INC(cb, exec_instruction); + + // Add a comment for the name of the YARV instruction + ADD_COMMENT(cb, insn_name(opcode)); + + // Call the code generation function + status = gen_fn(&jit, ctx, cb); + } + + // If we can't compile this instruction + // exit to the interpreter and stop compiling + if (status == YJIT_CANT_COMPILE) { + // TODO: if the codegen function makes changes to ctx and then return YJIT_CANT_COMPILE, + // the exit this generates would be wrong. We could save a copy of the entry context + // and assert that ctx is the same here. + uint32_t exit_off = yjit_gen_exit(jit.pc, ctx, cb); + + // If this is the first instruction in the block, then we can use + // the exit for block->entry_exit. + if (insn_idx == block->blockid.idx) { + block->entry_exit = cb_get_ptr(cb, exit_off); + } + break; + } + + // For now, reset the chain depth after each instruction as only the + // first instruction in the block can concern itself with the depth. + ctx->chain_depth = 0; + + // Move to the next instruction to compile + insn_idx += insn_len(opcode); + + // If the instruction terminates this block + if (status == YJIT_END_BLOCK) { + break; + } + } + + // Mark the end position of the block + block->end_addr = cb_get_write_ptr(cb); + + // Store the index of the last instruction in the block + block->end_idx = insn_idx; + + // We currently can't handle cases where the request is for a block that + // doesn't go to the next instruction. + RUBY_ASSERT(!jit.record_boundary_patch_point); + + // If code for the block doesn't fit, free the block and fail. + if (cb->dropped_bytes || ocb->dropped_bytes) { + yjit_free_block(block); + return NULL; + } + + if (YJIT_DUMP_MODE >= 2) { + // Dump list of compiled instrutions + fprintf(stderr, "Compiled the following for iseq=%p:\n", (void *)iseq); + for (uint32_t idx = block->blockid.idx; idx < insn_idx; ) { + int opcode = yjit_opcode_at_pc(iseq, yjit_iseq_pc_at_idx(iseq, idx)); + fprintf(stderr, " %04d %s\n", idx, insn_name(opcode)); + idx += insn_len(opcode); + } + } + + return block; +} + +static codegen_status_t gen_opt_send_without_block(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb); + +static codegen_status_t +gen_nop(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Do nothing + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_dup(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Get the top value and its type + x86opnd_t dup_val = ctx_stack_pop(ctx, 0); + temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(0)); + + // Push the same value on top + x86opnd_t loc0 = ctx_stack_push_mapping(ctx, mapping); + mov(cb, REG0, dup_val); + mov(cb, loc0, REG0); + + return YJIT_KEEP_COMPILING; +} + +// duplicate stack top n elements +static codegen_status_t +gen_dupn(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + + // In practice, seems to be only used for n==2 + if (n != 2) { + return YJIT_CANT_COMPILE; + } + + x86opnd_t opnd1 = ctx_stack_opnd(ctx, 1); + x86opnd_t opnd0 = ctx_stack_opnd(ctx, 0); + temp_type_mapping_t mapping1 = ctx_get_opnd_mapping(ctx, OPND_STACK(1)); + temp_type_mapping_t mapping0 = ctx_get_opnd_mapping(ctx, OPND_STACK(0)); + + x86opnd_t dst1 = ctx_stack_push_mapping(ctx, mapping1); + mov(cb, REG0, opnd1); + mov(cb, dst1, REG0); + + x86opnd_t dst0 = ctx_stack_push_mapping(ctx, mapping0); + mov(cb, REG0, opnd0); + mov(cb, dst0, REG0); + + return YJIT_KEEP_COMPILING; +} + +static void +stack_swap(ctx_t *ctx, codeblock_t *cb, int offset0, int offset1, x86opnd_t reg0, x86opnd_t reg1) +{ + x86opnd_t opnd0 = ctx_stack_opnd(ctx, offset0); + x86opnd_t opnd1 = ctx_stack_opnd(ctx, offset1); + + temp_type_mapping_t mapping0 = ctx_get_opnd_mapping(ctx, OPND_STACK(offset0)); + temp_type_mapping_t mapping1 = ctx_get_opnd_mapping(ctx, OPND_STACK(offset1)); + + mov(cb, reg0, opnd0); + mov(cb, reg1, opnd1); + mov(cb, opnd0, reg1); + mov(cb, opnd1, reg0); + + ctx_set_opnd_mapping(ctx, OPND_STACK(offset0), mapping1); + ctx_set_opnd_mapping(ctx, OPND_STACK(offset1), mapping0); +} + +// Swap top 2 stack entries +static codegen_status_t +gen_swap(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + stack_swap(ctx , cb, 0, 1, REG0, REG1); + return YJIT_KEEP_COMPILING; +} + +// set Nth stack entry to stack top +static codegen_status_t +gen_setn(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + + // Set the destination + x86opnd_t top_val = ctx_stack_pop(ctx, 0); + x86opnd_t dst_opnd = ctx_stack_opnd(ctx, (int32_t)n); + mov(cb, REG0, top_val); + mov(cb, dst_opnd, REG0); + + temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(0)); + ctx_set_opnd_mapping(ctx, OPND_STACK(n), mapping); + + return YJIT_KEEP_COMPILING; +} + +// get nth stack value, then push it +static codegen_status_t +gen_topn(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t n = (int32_t)jit_get_arg(jit, 0); + + // Get top n type / operand + x86opnd_t top_n_val = ctx_stack_opnd(ctx, n); + temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(n)); + + x86opnd_t loc0 = ctx_stack_push_mapping(ctx, mapping); + mov(cb, REG0, top_n_val); + mov(cb, loc0, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_pop(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Decrement SP + ctx_stack_pop(ctx, 1); + return YJIT_KEEP_COMPILING; +} + +// Pop n values off the stack +static codegen_status_t +gen_adjuststack(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + ctx_stack_pop(ctx, n); + return YJIT_KEEP_COMPILING; +} + +// new array initialized from top N values +static codegen_status_t +gen_newarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); + + x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n)); + + // call rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts); + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], imm_opnd(n)); + lea(cb, C_ARG_REGS[2], values_ptr); + call_ptr(cb, REG0, (void *)rb_ec_ary_new_from_values); + + ctx_stack_pop(ctx, n); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_ARRAY); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +// dup array +static codegen_status_t +gen_duparray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE ary = jit_get_arg(jit, 0); + + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); + + // call rb_ary_resurrect(VALUE ary); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[0], ary); + call_ptr(cb, REG0, (void *)rb_ary_resurrect); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_ARRAY); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +// dup hash +static codegen_status_t +gen_duphash(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE hash = jit_get_arg(jit, 0); + + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); + + // call rb_hash_resurrect(VALUE hash); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[0], hash); + call_ptr(cb, REG0, (void *)rb_hash_resurrect); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +VALUE rb_vm_splat_array(VALUE flag, VALUE ary); + +// call to_a on the array on the stack +static codegen_status_t +gen_splatarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE flag = (VALUE) jit_get_arg(jit, 0); + + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, REG0); + + // Get the operands from the stack + x86opnd_t ary_opnd = ctx_stack_pop(ctx, 1); + + // Call rb_vm_splat_array(flag, ary) + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[0], flag); + mov(cb, C_ARG_REGS[1], ary_opnd); + call_ptr(cb, REG1, (void *) rb_vm_splat_array); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_ARRAY); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +// new range initialized from top 2 values +static codegen_status_t +gen_newrange(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t flag = (rb_num_t)jit_get_arg(jit, 0); + + // rb_range_new() allocates and can raise + jit_prepare_routine_call(jit, ctx, REG0); + + // val = rb_range_new(low, high, (int)flag); + mov(cb, C_ARG_REGS[0], ctx_stack_opnd(ctx, 1)); + mov(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, 0)); + mov(cb, C_ARG_REGS[2], imm_opnd(flag)); + call_ptr(cb, REG0, (void *)rb_range_new); + + ctx_stack_pop(ctx, 2); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HEAP); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static void +guard_object_is_heap(codeblock_t *cb, x86opnd_t object_opnd, ctx_t *ctx, uint8_t *side_exit) +{ + ADD_COMMENT(cb, "guard object is heap"); + + // Test that the object is not an immediate + test(cb, object_opnd, imm_opnd(RUBY_IMMEDIATE_MASK)); + jnz_ptr(cb, side_exit); + + // Test that the object is not false or nil + cmp(cb, object_opnd, imm_opnd(Qnil)); + RUBY_ASSERT(Qfalse < Qnil); + jbe_ptr(cb, side_exit); +} + +static inline void +guard_object_is_array(codeblock_t *cb, x86opnd_t object_opnd, x86opnd_t flags_opnd, ctx_t *ctx, uint8_t *side_exit) +{ + ADD_COMMENT(cb, "guard object is array"); + + // Pull out the type mask + mov(cb, flags_opnd, member_opnd(object_opnd, struct RBasic, flags)); + and(cb, flags_opnd, imm_opnd(RUBY_T_MASK)); + + // Compare the result with T_ARRAY + cmp(cb, flags_opnd, imm_opnd(T_ARRAY)); + jne_ptr(cb, side_exit); +} + +// push enough nils onto the stack to fill out an array +static codegen_status_t +gen_expandarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int flag = (int) jit_get_arg(jit, 1); + + // If this instruction has the splat flag, then bail out. + if (flag & 0x01) { + GEN_COUNTER_INC(cb, expandarray_splat); + return YJIT_CANT_COMPILE; + } + + // If this instruction has the postarg flag, then bail out. + if (flag & 0x02) { + GEN_COUNTER_INC(cb, expandarray_postarg); + return YJIT_CANT_COMPILE; + } + + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // num is the number of requested values. If there aren't enough in the + // array then we're going to push on nils. + int num = (int)jit_get_arg(jit, 0); + val_type_t array_type = ctx_get_opnd_type(ctx, OPND_STACK(0)); + x86opnd_t array_opnd = ctx_stack_pop(ctx, 1); + + if (array_type.type == ETYPE_NIL) { + // special case for a, b = nil pattern + // push N nils onto the stack + for (int i = 0; i < num; i++) { + x86opnd_t push = ctx_stack_push(ctx, TYPE_NIL); + mov(cb, push, imm_opnd(Qnil)); + } + return YJIT_KEEP_COMPILING; + } + + // Move the array from the stack into REG0 and check that it's an array. + mov(cb, REG0, array_opnd); + guard_object_is_heap(cb, REG0, ctx, COUNTED_EXIT(jit, side_exit, expandarray_not_array)); + guard_object_is_array(cb, REG0, REG1, ctx, COUNTED_EXIT(jit, side_exit, expandarray_not_array)); + + // If we don't actually want any values, then just return. + if (num == 0) { + return YJIT_KEEP_COMPILING; + } + + // Pull out the embed flag to check if it's an embedded array. + x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); + mov(cb, REG1, flags_opnd); + + // Move the length of the embedded array into REG1. + and(cb, REG1, imm_opnd(RARRAY_EMBED_LEN_MASK)); + shr(cb, REG1, imm_opnd(RARRAY_EMBED_LEN_SHIFT)); + + // Conditionally move the length of the heap array into REG1. + test(cb, flags_opnd, imm_opnd(RARRAY_EMBED_FLAG)); + cmovz(cb, REG1, member_opnd(REG0, struct RArray, as.heap.len)); + + // Only handle the case where the number of values in the array is greater + // than or equal to the number of values requested. + cmp(cb, REG1, imm_opnd(num)); + jl_ptr(cb, COUNTED_EXIT(jit, side_exit, expandarray_rhs_too_small)); + + // Load the address of the embedded array into REG1. + // (struct RArray *)(obj)->as.ary + lea(cb, REG1, member_opnd(REG0, struct RArray, as.ary)); + + // Conditionally load the address of the heap array into REG1. + // (struct RArray *)(obj)->as.heap.ptr + test(cb, flags_opnd, imm_opnd(RARRAY_EMBED_FLAG)); + cmovz(cb, REG1, member_opnd(REG0, struct RArray, as.heap.ptr)); + + // Loop backward through the array and push each element onto the stack. + for (int32_t i = (int32_t) num - 1; i >= 0; i--) { + x86opnd_t top = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, REG0, mem_opnd(64, REG1, i * SIZEOF_VALUE)); + mov(cb, top, REG0); + } + + return YJIT_KEEP_COMPILING; +} + +// new hash initialized from top N values +static codegen_status_t +gen_newhash(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t num = (int32_t)jit_get_arg(jit, 0); + + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); + + if (num) { + // val = rb_hash_new_with_size(num / 2); + mov(cb, C_ARG_REGS[0], imm_opnd(num / 2)); + call_ptr(cb, REG0, (void *)rb_hash_new_with_size); + + // save the allocated hash as we want to push it after insertion + push(cb, RAX); + push(cb, RAX); // alignment + + // rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val); + mov(cb, C_ARG_REGS[0], imm_opnd(num)); + lea(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, num - 1)); + mov(cb, C_ARG_REGS[2], RAX); + call_ptr(cb, REG0, (void *)rb_hash_bulk_insert); + + pop(cb, RAX); // alignment + pop(cb, RAX); + + ctx_stack_pop(ctx, num); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH); + mov(cb, stack_ret, RAX); + } + else { + // val = rb_hash_new(); + call_ptr(cb, REG0, (void *)rb_hash_new); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH); + mov(cb, stack_ret, RAX); + } + + return YJIT_KEEP_COMPILING; +} + +// Push a constant value to the stack, including type information. +// The constant may be a heap object or a special constant. +static void +jit_putobject(jitstate_t *jit, ctx_t *ctx, VALUE arg) +{ + val_type_t val_type = yjit_type_of_value(arg); + x86opnd_t stack_top = ctx_stack_push(ctx, val_type); + + if (SPECIAL_CONST_P(arg)) { + // Immediates will not move and do not need to be tracked for GC + // Thanks to this we can mov directly to memory when possible. + + // NOTE: VALUE -> int64_t cast below is implementation defined. + // Hopefully it preserves the the bit pattern or raise a signal. + // See N1256 section 6.3.1.3. + x86opnd_t imm = imm_opnd((int64_t)arg); + + // 64-bit immediates can't be directly written to memory + if (imm.num_bits <= 32) { + mov(cb, stack_top, imm); + } + else { + mov(cb, REG0, imm); + mov(cb, stack_top, REG0); + } + } + else { + // Load the value to push into REG0 + // Note that this value may get moved by the GC + jit_mov_gc_ptr(jit, cb, REG0, arg); + + // Write argument at SP + mov(cb, stack_top, REG0); + } +} + +static codegen_status_t +gen_putnil(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + jit_putobject(jit, ctx, Qnil); + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_putobject(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE arg = jit_get_arg(jit, 0); + + jit_putobject(jit, ctx, arg); + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_putstring(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE put_val = jit_get_arg(jit, 0); + + // Save the PC and SP because the callee will allocate + jit_prepare_routine_call(jit, ctx, REG0); + + mov(cb, C_ARG_REGS[0], REG_EC); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[1], put_val); + call_ptr(cb, REG0, (void *)rb_ec_str_resurrect); + + x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_STRING); + mov(cb, stack_top, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_putobject_int2fix(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int opcode = jit_get_opcode(jit); + int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1; + + jit_putobject(jit, ctx, INT2FIX(cst_val)); + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_putself(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Load self from CFP + mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self)); + + // Write it on the stack + x86opnd_t stack_top = ctx_stack_push_self(ctx); + mov(cb, stack_top, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_putspecialobject(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + enum vm_special_object_type type = (enum vm_special_object_type)jit_get_arg(jit, 0); + + if (type == VM_SPECIAL_OBJECT_VMCORE) { + x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_HEAP); + jit_mov_gc_ptr(jit, cb, REG0, rb_mRubyVMFrozenCore); + mov(cb, stack_top, REG0); + return YJIT_KEEP_COMPILING; + } + else { + // TODO: implement for VM_SPECIAL_OBJECT_CBASE and + // VM_SPECIAL_OBJECT_CONST_BASE + return YJIT_CANT_COMPILE; + } +} + +// Get EP at level from CFP +static void +gen_get_ep(codeblock_t *cb, x86opnd_t reg, uint32_t level) +{ + // Load environment pointer EP from CFP + mov(cb, reg, member_opnd(REG_CFP, rb_control_frame_t, ep)); + + while (level--) { + // Get the previous EP from the current EP + // See GET_PREV_EP(ep) macro + // VALUE *prev_ep = ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03)) + mov(cb, reg, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL)); + and(cb, reg, imm_opnd(~0x03)); + } +} + +// Compute the index of a local variable from its slot index +static uint32_t +slot_to_local_idx(const rb_iseq_t *iseq, int32_t slot_idx) +{ + // Convoluted rules from local_var_name() in iseq.c + int32_t local_table_size = iseq->body->local_table_size; + int32_t op = slot_idx - VM_ENV_DATA_SIZE; + int32_t local_idx = local_idx = local_table_size - op - 1; + RUBY_ASSERT(local_idx >= 0 && local_idx < local_table_size); + return (uint32_t)local_idx; +} + +static codegen_status_t +gen_getlocal_wc0(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Compute the offset from BP to the local + int32_t slot_idx = (int32_t)jit_get_arg(jit, 0); + const int32_t offs = -(SIZEOF_VALUE * slot_idx); + uint32_t local_idx = slot_to_local_idx(jit->iseq, slot_idx); + + // Load environment pointer EP (level 0) from CFP + gen_get_ep(cb, REG0, 0); + + // Load the local from the EP + mov(cb, REG0, mem_opnd(64, REG0, offs)); + + // Write the local at SP + x86opnd_t stack_top = ctx_stack_push_local(ctx, local_idx); + mov(cb, stack_top, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_getlocal_generic(ctx_t *ctx, uint32_t local_idx, uint32_t level) +{ + gen_get_ep(cb, REG0, level); + + // Load the local from the block + // val = *(vm_get_ep(GET_EP(), level) - idx); + const int32_t offs = -(SIZEOF_VALUE * local_idx); + mov(cb, REG0, mem_opnd(64, REG0, offs)); + + // Write the local at SP + x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_top, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_getlocal(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t idx = (int32_t)jit_get_arg(jit, 0); + int32_t level = (int32_t)jit_get_arg(jit, 1); + return gen_getlocal_generic(ctx, idx, level); +} + +static codegen_status_t +gen_getlocal_wc1(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t idx = (int32_t)jit_get_arg(jit, 0); + return gen_getlocal_generic(ctx, idx, 1); +} + +static codegen_status_t +gen_setlocal_wc0(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + /* + vm_env_write(const VALUE *ep, int index, VALUE v) + { + VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS]; + if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) { + VM_STACK_ENV_WRITE(ep, index, v); + } + else { + vm_env_write_slowpath(ep, index, v); + } + } + */ + + int32_t slot_idx = (int32_t)jit_get_arg(jit, 0); + uint32_t local_idx = slot_to_local_idx(jit->iseq, slot_idx); + + // Load environment pointer EP (level 0) from CFP + gen_get_ep(cb, REG0, 0); + + // flags & VM_ENV_FLAG_WB_REQUIRED + x86opnd_t flags_opnd = mem_opnd(64, REG0, sizeof(VALUE) * VM_ENV_DATA_INDEX_FLAGS); + test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED)); + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0 + jnz_ptr(cb, side_exit); + + // Set the type of the local variable in the context + val_type_t temp_type = ctx_get_opnd_type(ctx, OPND_STACK(0)); + ctx_set_local_type(ctx, local_idx, temp_type); + + // Pop the value to write from the stack + x86opnd_t stack_top = ctx_stack_pop(ctx, 1); + mov(cb, REG1, stack_top); + + // Write the value at the environment pointer + const int32_t offs = -8 * slot_idx; + mov(cb, mem_opnd(64, REG0, offs), REG1); + + return YJIT_KEEP_COMPILING; +} + +// Push Qtrue or Qfalse depending on whether the given keyword was supplied by +// the caller +static codegen_status_t +gen_checkkeyword(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // When a keyword is unspecified past index 32, a hash will be used + // instead. This can only happen in iseqs taking more than 32 keywords. + if (jit->iseq->body->param.keyword->num >= 32) { + return YJIT_CANT_COMPILE; + } + + // The EP offset to the undefined bits local + int32_t bits_offset = (int32_t)jit_get_arg(jit, 0); + + // The index of the keyword we want to check + int32_t index = (int32_t)jit_get_arg(jit, 1); + + // Load environment pointer EP + gen_get_ep(cb, REG0, 0); + + // VALUE kw_bits = *(ep - bits); + x86opnd_t bits_opnd = mem_opnd(64, REG0, sizeof(VALUE) * -bits_offset); + + // unsigned int b = (unsigned int)FIX2ULONG(kw_bits); + // if ((b & (0x01 << idx))) { + // + // We can skip the FIX2ULONG conversion by shifting the bit we test + int64_t bit_test = 0x01 << (index + 1); + test(cb, bits_opnd, imm_opnd(bit_test)); + mov(cb, REG0, imm_opnd(Qfalse)); + mov(cb, REG1, imm_opnd(Qtrue)); + cmovz(cb, REG0, REG1); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_IMM); + mov(cb, stack_ret, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_setlocal_generic(jitstate_t *jit, ctx_t *ctx, uint32_t local_idx, uint32_t level) +{ + // Load environment pointer EP at level + gen_get_ep(cb, REG0, level); + + // flags & VM_ENV_FLAG_WB_REQUIRED + x86opnd_t flags_opnd = mem_opnd(64, REG0, sizeof(VALUE) * VM_ENV_DATA_INDEX_FLAGS); + test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED)); + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0 + jnz_ptr(cb, side_exit); + + // Pop the value to write from the stack + x86opnd_t stack_top = ctx_stack_pop(ctx, 1); + mov(cb, REG1, stack_top); + + // Write the value at the environment pointer + const int32_t offs = -(SIZEOF_VALUE * local_idx); + mov(cb, mem_opnd(64, REG0, offs), REG1); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_setlocal(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t idx = (int32_t)jit_get_arg(jit, 0); + int32_t level = (int32_t)jit_get_arg(jit, 1); + return gen_setlocal_generic(jit, ctx, idx, level); +} + +static codegen_status_t +gen_setlocal_wc1(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t idx = (int32_t)jit_get_arg(jit, 0); + return gen_setlocal_generic(jit, ctx, idx, 1); +} + +static void +gen_jnz_to_target0(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + case SHAPE_NEXT1: + RUBY_ASSERT(false); + break; + + case SHAPE_DEFAULT: + jnz_ptr(cb, target0); + break; + } +} + +static void +gen_jz_to_target0(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + case SHAPE_NEXT1: + RUBY_ASSERT(false); + break; + + case SHAPE_DEFAULT: + jz_ptr(cb, target0); + break; + } +} + +static void +gen_jbe_to_target0(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + case SHAPE_NEXT1: + RUBY_ASSERT(false); + break; + + case SHAPE_DEFAULT: + jbe_ptr(cb, target0); + break; + } +} + +enum jcc_kinds { + JCC_JNE, + JCC_JNZ, + JCC_JZ, + JCC_JE, + JCC_JBE, + JCC_JNA, +}; + +// Generate a jump to a stub that recompiles the current YARV instruction on failure. +// When depth_limitk is exceeded, generate a jump to a side exit. +static void +jit_chain_guard(enum jcc_kinds jcc, jitstate_t *jit, const ctx_t *ctx, uint8_t depth_limit, uint8_t *side_exit) +{ + branchgen_fn target0_gen_fn; + + switch (jcc) { + case JCC_JNE: + case JCC_JNZ: + target0_gen_fn = gen_jnz_to_target0; + break; + case JCC_JZ: + case JCC_JE: + target0_gen_fn = gen_jz_to_target0; + break; + case JCC_JBE: + case JCC_JNA: + target0_gen_fn = gen_jbe_to_target0; + break; + default: + rb_bug("yjit: unimplemented jump kind"); + break; + }; + + if (ctx->chain_depth < depth_limit) { + ctx_t deeper = *ctx; + deeper.chain_depth++; + + gen_branch( + jit, + ctx, + (blockid_t) { jit->iseq, jit->insn_idx }, + &deeper, + BLOCKID_NULL, + NULL, + target0_gen_fn + ); + } + else { + target0_gen_fn(cb, side_exit, NULL, SHAPE_DEFAULT); + } +} + +enum { + GETIVAR_MAX_DEPTH = 10, // up to 5 different classes, and embedded or not for each + OPT_AREF_MAX_CHAIN_DEPTH = 2, // hashes and arrays + SEND_MAX_DEPTH = 5, // up to 5 different classes +}; + +VALUE rb_vm_set_ivar_idx(VALUE obj, uint32_t idx, VALUE val); + +// Codegen for setting an instance variable. +// Preconditions: +// - receiver is in REG0 +// - receiver has the same class as CLASS_OF(comptime_receiver) +// - no stack push or pops to ctx since the entry to the codegen of the instruction being compiled +static codegen_status_t +gen_set_ivar(jitstate_t *jit, ctx_t *ctx, VALUE recv, VALUE klass, ID ivar_name) +{ + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, REG0); + + // Get the operands from the stack + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + x86opnd_t recv_opnd = ctx_stack_pop(ctx, 1); + + uint32_t ivar_index = rb_obj_ensure_iv_index_mapping(recv, ivar_name); + + // Call rb_vm_set_ivar_idx with the receiver, the index of the ivar, and the value + mov(cb, C_ARG_REGS[0], recv_opnd); + mov(cb, C_ARG_REGS[1], imm_opnd(ivar_index)); + mov(cb, C_ARG_REGS[2], val_opnd); + call_ptr(cb, REG0, (void *)rb_vm_set_ivar_idx); + + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, RAX); + + return YJIT_KEEP_COMPILING; +} + +// Codegen for getting an instance variable. +// Preconditions: +// - receiver is in REG0 +// - receiver has the same class as CLASS_OF(comptime_receiver) +// - no stack push or pops to ctx since the entry to the codegen of the instruction being compiled +static codegen_status_t +gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE comptime_receiver, ID ivar_name, insn_opnd_t reg0_opnd, uint8_t *side_exit) +{ + VALUE comptime_val_klass = CLASS_OF(comptime_receiver); + const ctx_t starting_context = *ctx; // make a copy for use with jit_chain_guard + + // If the class uses the default allocator, instances should all be T_OBJECT + // NOTE: This assumes nobody changes the allocator of the class after allocation. + // Eventually, we can encode whether an object is T_OBJECT or not + // inside object shapes. + if (!RB_TYPE_P(comptime_receiver, T_OBJECT) || + rb_get_alloc_func(comptime_val_klass) != rb_class_allocate_instance) { + // General case. Call rb_ivar_get(). + // VALUE rb_ivar_get(VALUE obj, ID id) + ADD_COMMENT(cb, "call rb_ivar_get()"); + + // The function could raise exceptions. + jit_prepare_routine_call(jit, ctx, REG1); + + mov(cb, C_ARG_REGS[0], REG0); + mov(cb, C_ARG_REGS[1], imm_opnd((int64_t)ivar_name)); + call_ptr(cb, REG1, (void *)rb_ivar_get); + + if (!reg0_opnd.is_self) { + (void)ctx_stack_pop(ctx, 1); + } + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, RAX); + + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + + /* + // FIXME: + // This check was added because of a failure in a test involving the + // Nokogiri Document class where we see a T_DATA that still has the default + // allocator. + // Aaron Patterson argues that this is a bug in the C extension, because + // people could call .allocate() on the class and still get a T_OBJECT + // For now I added an extra dynamic check that the receiver is T_OBJECT + // so we can safely pass all the tests in Shopify Core. + // + // Guard that the receiver is T_OBJECT + // #define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK) + ADD_COMMENT(cb, "guard receiver is T_OBJECT"); + mov(cb, REG1, member_opnd(REG0, struct RBasic, flags)); + and(cb, REG1, imm_opnd(RUBY_T_MASK)); + cmp(cb, REG1, imm_opnd(T_OBJECT)); + jit_chain_guard(JCC_JNE, jit, &starting_context, max_chain_depth, side_exit); + */ + + // FIXME: Mapping the index could fail when there is too many ivar names. If we're + // compiling for a branch stub that can cause the exception to be thrown from the + // wrong PC. + uint32_t ivar_index = rb_obj_ensure_iv_index_mapping(comptime_receiver, ivar_name); + + // Pop receiver if it's on the temp stack + if (!reg0_opnd.is_self) { + (void)ctx_stack_pop(ctx, 1); + } + + // Compile time self is embedded and the ivar index lands within the object + if (RB_FL_TEST_RAW(comptime_receiver, ROBJECT_EMBED) && ivar_index < ROBJECT_EMBED_LEN_MAX) { + // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h + + // Guard that self is embedded + // TODO: BT and JC is shorter + ADD_COMMENT(cb, "guard embedded getivar"); + x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); + test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); + jit_chain_guard(JCC_JZ, jit, &starting_context, max_chain_depth, COUNTED_EXIT(jit, side_exit, getivar_megamorphic)); + + // Load the variable + x86opnd_t ivar_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.ary) + ivar_index * SIZEOF_VALUE); + mov(cb, REG1, ivar_opnd); + + // Guard that the variable is not Qundef + cmp(cb, REG1, imm_opnd(Qundef)); + mov(cb, REG0, imm_opnd(Qnil)); + cmove(cb, REG1, REG0); + + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, REG1); + } + else { + // Compile time value is *not* embedded. + + // Guard that value is *not* embedded + // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h + ADD_COMMENT(cb, "guard extended getivar"); + x86opnd_t flags_opnd = member_opnd(REG0, struct RBasic, flags); + test(cb, flags_opnd, imm_opnd(ROBJECT_EMBED)); + jit_chain_guard(JCC_JNZ, jit, &starting_context, max_chain_depth, COUNTED_EXIT(jit, side_exit, getivar_megamorphic)); + + // check that the extended table is big enough + if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1) { + // Check that the slot is inside the extended table (num_slots > index) + x86opnd_t num_slots = mem_opnd(32, REG0, offsetof(struct RObject, as.heap.numiv)); + cmp(cb, num_slots, imm_opnd(ivar_index)); + jle_ptr(cb, COUNTED_EXIT(jit, side_exit, getivar_idx_out_of_range)); + } + + // Get a pointer to the extended table + x86opnd_t tbl_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.heap.ivptr)); + mov(cb, REG0, tbl_opnd); + + // Read the ivar from the extended table + x86opnd_t ivar_opnd = mem_opnd(64, REG0, sizeof(VALUE) * ivar_index); + mov(cb, REG0, ivar_opnd); + + // Check that the ivar is not Qundef + cmp(cb, REG0, imm_opnd(Qundef)); + mov(cb, REG1, imm_opnd(Qnil)); + cmove(cb, REG0, REG1); + + // Push the ivar on the stack + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, out_opnd, REG0); + } + + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; +} + +static codegen_status_t +gen_getinstancevariable(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + ID ivar_name = (ID)jit_get_arg(jit, 0); + + VALUE comptime_val = jit_peek_at_self(jit, ctx); + VALUE comptime_val_klass = CLASS_OF(comptime_val); + + // Generate a side exit + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Guard that the receiver has the same class as the one from compile time. + mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self)); + + jit_guard_known_klass(jit, ctx, comptime_val_klass, OPND_SELF, comptime_val, GETIVAR_MAX_DEPTH, side_exit); + + return gen_get_ivar(jit, ctx, GETIVAR_MAX_DEPTH, comptime_val, ivar_name, OPND_SELF, side_exit); +} + +void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic); + +static codegen_status_t +gen_setinstancevariable(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + ID id = (ID)jit_get_arg(jit, 0); + IVC ic = (IVC)jit_get_arg(jit, 1); + + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, REG0); + + // Get the operands from the stack + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + + // Call rb_vm_setinstancevariable(iseq, obj, id, val, ic); + mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, self)); + mov(cb, C_ARG_REGS[3], val_opnd); + mov(cb, C_ARG_REGS[2], imm_opnd(id)); + mov(cb, C_ARG_REGS[4], const_ptr_opnd(ic)); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[0], (VALUE)jit->iseq); + call_ptr(cb, REG0, (void *)rb_vm_setinstancevariable); + + return YJIT_KEEP_COMPILING; +} + +bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v); + +static codegen_status_t +gen_defined(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t op_type = (rb_num_t)jit_get_arg(jit, 0); + VALUE obj = (VALUE)jit_get_arg(jit, 1); + VALUE pushval = (VALUE)jit_get_arg(jit, 2); + + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, REG0); + + // Get the operands from the stack + x86opnd_t v_opnd = ctx_stack_pop(ctx, 1); + + // Call vm_defined(ec, reg_cfp, op_type, obj, v) + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], REG_CFP); + mov(cb, C_ARG_REGS[2], imm_opnd(op_type)); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[3], (VALUE)obj); + mov(cb, C_ARG_REGS[4], v_opnd); + call_ptr(cb, REG0, (void *)rb_vm_defined); + + // if (vm_defined(ec, GET_CFP(), op_type, obj, v)) { + // val = pushval; + // } + jit_mov_gc_ptr(jit, cb, REG1, (VALUE)pushval); + cmp(cb, AL, imm_opnd(0)); + mov(cb, RAX, imm_opnd(Qnil)); + cmovnz(cb, RAX, REG1); + + // Push the return value onto the stack + val_type_t out_type = SPECIAL_CONST_P(pushval)? TYPE_IMM:TYPE_UNKNOWN; + x86opnd_t stack_ret = ctx_stack_push(ctx, out_type); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_checktype(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + enum ruby_value_type type_val = (enum ruby_value_type)jit_get_arg(jit, 0); + // Only three types are emitted by compile.c + if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH) { + val_type_t val_type = ctx_get_opnd_type(ctx, OPND_STACK(0)); + x86opnd_t val = ctx_stack_pop(ctx, 1); + + x86opnd_t stack_ret; + + // Check if we know from type information + if ((type_val == T_STRING && val_type.type == ETYPE_STRING) || + (type_val == T_ARRAY && val_type.type == ETYPE_ARRAY) || + (type_val == T_HASH && val_type.type == ETYPE_HASH)) { + // guaranteed type match + stack_ret = ctx_stack_push(ctx, TYPE_TRUE); + mov(cb, stack_ret, imm_opnd(Qtrue)); + return YJIT_KEEP_COMPILING; + } + else if (val_type.is_imm || val_type.type != ETYPE_UNKNOWN) { + // guaranteed not to match T_STRING/T_ARRAY/T_HASH + stack_ret = ctx_stack_push(ctx, TYPE_FALSE); + mov(cb, stack_ret, imm_opnd(Qfalse)); + return YJIT_KEEP_COMPILING; + } + + mov(cb, REG0, val); + mov(cb, REG1, imm_opnd(Qfalse)); + + uint32_t ret = cb_new_label(cb, "ret"); + + if (!val_type.is_heap) { + // if (SPECIAL_CONST_P(val)) { + // Return Qfalse via REG1 if not on heap + test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK)); + jnz_label(cb, ret); + cmp(cb, REG0, imm_opnd(Qnil)); + jbe_label(cb, ret); + } + + // Check type on object + mov(cb, REG0, mem_opnd(64, REG0, offsetof(struct RBasic, flags))); + and(cb, REG0, imm_opnd(RUBY_T_MASK)); + cmp(cb, REG0, imm_opnd(type_val)); + mov(cb, REG0, imm_opnd(Qtrue)); + // REG1 contains Qfalse from above + cmove(cb, REG1, REG0); + + cb_write_label(cb, ret); + stack_ret = ctx_stack_push(ctx, TYPE_IMM); + mov(cb, stack_ret, REG1); + cb_link_labels(cb); + + return YJIT_KEEP_COMPILING; + } + else { + return YJIT_CANT_COMPILE; + } +} + +static codegen_status_t +gen_concatstrings(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t n = (rb_num_t)jit_get_arg(jit, 0); + + // Save the PC and SP because we are allocating + jit_prepare_routine_call(jit, ctx, REG0); + + x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n)); + + // call rb_str_concat_literals(long n, const VALUE *strings); + mov(cb, C_ARG_REGS[0], imm_opnd(n)); + lea(cb, C_ARG_REGS[1], values_ptr); + call_ptr(cb, REG0, (void *)rb_str_concat_literals); + + ctx_stack_pop(ctx, n); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_STRING); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static void +guard_two_fixnums(ctx_t *ctx, uint8_t *side_exit) +{ + // Get the stack operand types + val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0)); + val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(1)); + + if (arg0_type.is_heap || arg1_type.is_heap) { + jmp_ptr(cb, side_exit); + return; + } + + if (arg0_type.type != ETYPE_FIXNUM && arg0_type.type != ETYPE_UNKNOWN) { + jmp_ptr(cb, side_exit); + return; + } + + if (arg1_type.type != ETYPE_FIXNUM && arg1_type.type != ETYPE_UNKNOWN) { + jmp_ptr(cb, side_exit); + return; + } + + RUBY_ASSERT(!arg0_type.is_heap); + RUBY_ASSERT(!arg1_type.is_heap); + RUBY_ASSERT(arg0_type.type == ETYPE_FIXNUM || arg0_type.type == ETYPE_UNKNOWN); + RUBY_ASSERT(arg1_type.type == ETYPE_FIXNUM || arg1_type.type == ETYPE_UNKNOWN); + + // Get stack operands without popping them + x86opnd_t arg1 = ctx_stack_opnd(ctx, 0); + x86opnd_t arg0 = ctx_stack_opnd(ctx, 1); + + // If not fixnums, fall back + if (arg0_type.type != ETYPE_FIXNUM) { + ADD_COMMENT(cb, "guard arg0 fixnum"); + test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG)); + jz_ptr(cb, side_exit); + } + if (arg1_type.type != ETYPE_FIXNUM) { + ADD_COMMENT(cb, "guard arg1 fixnum"); + test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG)); + jz_ptr(cb, side_exit); + } + + // Set stack types in context + ctx_upgrade_opnd_type(ctx, OPND_STACK(0), TYPE_FIXNUM); + ctx_upgrade_opnd_type(ctx, OPND_STACK(1), TYPE_FIXNUM); +} + +// Conditional move operation used by comparison operators +typedef void (*cmov_fn)(codeblock_t *cb, x86opnd_t opnd0, x86opnd_t opnd1); + +static codegen_status_t +gen_fixnum_cmp(jitstate_t *jit, ctx_t *ctx, cmov_fn cmov_op) +{ + // Defer compilation so we can specialize base on a runtime receiver + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a side-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_LT)) { + return YJIT_CANT_COMPILE; + } + + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); + + // Get the operands from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Compare the arguments + xor(cb, REG0_32, REG0_32); // REG0 = Qfalse + mov(cb, REG1, arg0); + cmp(cb, REG1, arg1); + mov(cb, REG1, imm_opnd(Qtrue)); + cmov_op(cb, REG0, REG1); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } + else { + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_lt(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_fixnum_cmp(jit, ctx, cmovl); +} + +static codegen_status_t +gen_opt_le(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_fixnum_cmp(jit, ctx, cmovle); +} + +static codegen_status_t +gen_opt_ge(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_fixnum_cmp(jit, ctx, cmovge); +} + +static codegen_status_t +gen_opt_gt(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_fixnum_cmp(jit, ctx, cmovg); +} + +// Implements specialized equality for either two fixnum or two strings +// Returns true if code was generated, otherwise false +static bool +gen_equality_specialized(jitstate_t *jit, ctx_t *ctx, uint8_t *side_exit) +{ + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + x86opnd_t a_opnd = ctx_stack_opnd(ctx, 1); + x86opnd_t b_opnd = ctx_stack_opnd(ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_EQ)) { + // if overridden, emit the generic version + return false; + } + + guard_two_fixnums(ctx, side_exit); + + mov(cb, REG0, a_opnd); + cmp(cb, REG0, b_opnd); + + mov(cb, REG0, imm_opnd(Qfalse)); + mov(cb, REG1, imm_opnd(Qtrue)); + cmove(cb, REG0, REG1); + + // Push the output on the stack + ctx_stack_pop(ctx, 2); + x86opnd_t dst = ctx_stack_push(ctx, TYPE_IMM); + mov(cb, dst, REG0); + + return true; + } + else if (CLASS_OF(comptime_a) == rb_cString && + CLASS_OF(comptime_b) == rb_cString) { + if (!assume_bop_not_redefined(jit, STRING_REDEFINED_OP_FLAG, BOP_EQ)) { + // if overridden, emit the generic version + return false; + } + + // Load a and b in preparation for call later + mov(cb, C_ARG_REGS[0], a_opnd); + mov(cb, C_ARG_REGS[1], b_opnd); + + // Guard that a is a String + mov(cb, REG0, C_ARG_REGS[0]); + jit_guard_known_klass(jit, ctx, rb_cString, OPND_STACK(1), comptime_a, SEND_MAX_DEPTH, side_exit); + + uint32_t ret = cb_new_label(cb, "ret"); + + // If they are equal by identity, return true + cmp(cb, C_ARG_REGS[0], C_ARG_REGS[1]); + mov(cb, RAX, imm_opnd(Qtrue)); + je_label(cb, ret); + + // Otherwise guard that b is a T_STRING (from type info) or String (from runtime guard) + if (ctx_get_opnd_type(ctx, OPND_STACK(0)).type != ETYPE_STRING) { + mov(cb, REG0, C_ARG_REGS[1]); + // Note: any T_STRING is valid here, but we check for a ::String for simplicity + jit_guard_known_klass(jit, ctx, rb_cString, OPND_STACK(0), comptime_b, SEND_MAX_DEPTH, side_exit); + } + + // Call rb_str_eql_internal(a, b) + call_ptr(cb, REG0, (void *)rb_str_eql_internal); + + // Push the output on the stack + cb_write_label(cb, ret); + ctx_stack_pop(ctx, 2); + x86opnd_t dst = ctx_stack_push(ctx, TYPE_IMM); + mov(cb, dst, RAX); + cb_link_labels(cb); + + return true; + } + else { + return false; + } +} + +static codegen_status_t +gen_opt_eq(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize base on a runtime receiver + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (gen_equality_specialized(jit, ctx, side_exit)) { + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + else { + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t *block); + +static codegen_status_t +gen_opt_neq(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // opt_neq is passed two rb_call_data as arguments: + // first for ==, second for != + struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 1); + return gen_send_general(jit, ctx, cd, NULL); +} + +static codegen_status_t +gen_opt_aref(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + struct rb_call_data * cd = (struct rb_call_data *)jit_get_arg(jit, 0); + int32_t argc = (int32_t)vm_ci_argc(cd->ci); + + // Only JIT one arg calls like `ary[6]` + if (argc != 1) { + GEN_COUNTER_INC(cb, oaref_argc_not_one); + return YJIT_CANT_COMPILE; + } + + // Defer compilation so we can specialize base on a runtime receiver + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + // Remember the context on entry for adding guard chains + const ctx_t starting_context = *ctx; + + // Specialize base on compile time values + VALUE comptime_idx = jit_peek_at_stack(jit, ctx, 0); + VALUE comptime_recv = jit_peek_at_stack(jit, ctx, 1); + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (CLASS_OF(comptime_recv) == rb_cArray && RB_FIXNUM_P(comptime_idx)) { + if (!assume_bop_not_redefined(jit, ARRAY_REDEFINED_OP_FLAG, BOP_AREF)) { + return YJIT_CANT_COMPILE; + } + + // Pop the stack operands + x86opnd_t idx_opnd = ctx_stack_pop(ctx, 1); + x86opnd_t recv_opnd = ctx_stack_pop(ctx, 1); + mov(cb, REG0, recv_opnd); + + // if (SPECIAL_CONST_P(recv)) { + // Bail if receiver is not a heap object + test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK)); + jnz_ptr(cb, side_exit); + cmp(cb, REG0, imm_opnd(Qfalse)); + je_ptr(cb, side_exit); + cmp(cb, REG0, imm_opnd(Qnil)); + je_ptr(cb, side_exit); + + // Bail if recv has a class other than ::Array. + // BOP_AREF check above is only good for ::Array. + mov(cb, REG1, mem_opnd(64, REG0, offsetof(struct RBasic, klass))); + mov(cb, REG0, const_ptr_opnd((void *)rb_cArray)); + cmp(cb, REG0, REG1); + jit_chain_guard(JCC_JNE, jit, &starting_context, OPT_AREF_MAX_CHAIN_DEPTH, side_exit); + + // Bail if idx is not a FIXNUM + mov(cb, REG1, idx_opnd); + test(cb, REG1, imm_opnd(RUBY_FIXNUM_FLAG)); + jz_ptr(cb, COUNTED_EXIT(jit, side_exit, oaref_arg_not_fixnum)); + + // Call VALUE rb_ary_entry_internal(VALUE ary, long offset). + // It never raises or allocates, so we don't need to write to cfp->pc. + { + mov(cb, RDI, recv_opnd); + sar(cb, REG1, imm_opnd(1)); // Convert fixnum to int + mov(cb, RSI, REG1); + call_ptr(cb, REG0, (void *)rb_ary_entry_internal); + + // Push the return value onto the stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + } + + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + else if (CLASS_OF(comptime_recv) == rb_cHash) { + if (!assume_bop_not_redefined(jit, HASH_REDEFINED_OP_FLAG, BOP_AREF)) { + return YJIT_CANT_COMPILE; + } + + x86opnd_t key_opnd = ctx_stack_opnd(ctx, 0); + x86opnd_t recv_opnd = ctx_stack_opnd(ctx, 1); + + // Guard that the receiver is a hash + mov(cb, REG0, recv_opnd); + jit_guard_known_klass(jit, ctx, rb_cHash, OPND_STACK(1), comptime_recv, OPT_AREF_MAX_CHAIN_DEPTH, side_exit); + + // Setup arguments for rb_hash_aref(). + mov(cb, C_ARG_REGS[0], REG0); + mov(cb, C_ARG_REGS[1], key_opnd); + + // Prepare to call rb_hash_aref(). It might call #hash on the key. + jit_prepare_routine_call(jit, ctx, REG0); + + call_ptr(cb, REG0, (void *)rb_hash_aref); + + // Pop the key and the receiver + (void)ctx_stack_pop(ctx, 2); + + // Push the return value onto the stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + // Jump to next instruction. This allows guard chains to share the same successor. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + else { + // General case. Call the [] method. + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_aset(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_recv = jit_peek_at_stack(jit, ctx, 2); + VALUE comptime_key = jit_peek_at_stack(jit, ctx, 1); + + // Get the operands from the stack + x86opnd_t recv = ctx_stack_opnd(ctx, 2); + x86opnd_t key = ctx_stack_opnd(ctx, 1); + x86opnd_t val = ctx_stack_opnd(ctx, 0); + + if (CLASS_OF(comptime_recv) == rb_cArray && FIXNUM_P(comptime_key)) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Guard receiver is an Array + mov(cb, REG0, recv); + jit_guard_known_klass(jit, ctx, rb_cArray, OPND_STACK(2), comptime_recv, SEND_MAX_DEPTH, side_exit); + + // Guard key is a fixnum + mov(cb, REG0, key); + jit_guard_known_klass(jit, ctx, rb_cInteger, OPND_STACK(1), comptime_key, SEND_MAX_DEPTH, side_exit); + + // Call rb_ary_store + mov(cb, C_ARG_REGS[0], recv); + mov(cb, C_ARG_REGS[1], key); + sar(cb, C_ARG_REGS[1], imm_opnd(1)); // FIX2LONG(key) + mov(cb, C_ARG_REGS[2], val); + + // We might allocate or raise + jit_prepare_routine_call(jit, ctx, REG0); + + call_ptr(cb, REG0, (void *)rb_ary_store); + + // rb_ary_store returns void + // stored value should still be on stack + mov(cb, REG0, ctx_stack_opnd(ctx, 0)); + + // Push the return value onto the stack + ctx_stack_pop(ctx, 3); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, REG0); + + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + else if (CLASS_OF(comptime_recv) == rb_cHash) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Guard receiver is a Hash + mov(cb, REG0, recv); + jit_guard_known_klass(jit, ctx, rb_cHash, OPND_STACK(2), comptime_recv, SEND_MAX_DEPTH, side_exit); + + // Call rb_hash_aset + mov(cb, C_ARG_REGS[0], recv); + mov(cb, C_ARG_REGS[1], key); + mov(cb, C_ARG_REGS[2], val); + + // We might allocate or raise + jit_prepare_routine_call(jit, ctx, REG0); + + call_ptr(cb, REG0, (void *)rb_hash_aset); + + // Push the return value onto the stack + ctx_stack_pop(ctx, 3); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + else { + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_and(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a side-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_AND)) { + return YJIT_CANT_COMPILE; + } + + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); + + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Do the bitwise and arg0 & arg1 + mov(cb, REG0, arg0); + and(cb, REG0, arg1); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } + else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_or(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a side-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_OR)) { + return YJIT_CANT_COMPILE; + } + + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); + + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Do the bitwise or arg0 | arg1 + mov(cb, REG0, arg0); + or(cb, REG0, arg1); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } + else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_minus(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a side-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)) { + return YJIT_CANT_COMPILE; + } + + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); + + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Subtract arg0 - arg1 and test for overflow + mov(cb, REG0, arg0); + sub(cb, REG0, arg1); + jo_ptr(cb, side_exit); + add(cb, REG0, imm_opnd(1)); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } + else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_plus(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); + + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a side-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (!assume_bop_not_redefined(jit, INTEGER_REDEFINED_OP_FLAG, BOP_PLUS)) { + return YJIT_CANT_COMPILE; + } + + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); + + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Add arg0 + arg1 and test for overflow + mov(cb, REG0, arg0); + sub(cb, REG0, imm_opnd(1)); + add(cb, REG0, arg1); + jo_ptr(cb, side_exit); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } + else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); + } +} + +static codegen_status_t +gen_opt_mult(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_div(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); +} + +VALUE rb_vm_opt_mod(VALUE recv, VALUE obj); + +static codegen_status_t +gen_opt_mod(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Save the PC and SP because the callee may allocate bignums + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, REG0); + + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Get the operands from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Call rb_vm_opt_mod(VALUE recv, VALUE obj) + mov(cb, C_ARG_REGS[0], arg0); + mov(cb, C_ARG_REGS[1], arg1); + call_ptr(cb, REG0, (void *)rb_vm_opt_mod); + + // If val == Qundef, bail to do a method call + cmp(cb, RAX, imm_opnd(Qundef)); + je_ptr(cb, side_exit); + + // Push the return value onto the stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_opt_ltlt(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_nil_p(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_empty_p(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_str_freeze(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + if (!assume_bop_not_redefined(jit, STRING_REDEFINED_OP_FLAG, BOP_FREEZE)) { + return YJIT_CANT_COMPILE; + } + + VALUE str = jit_get_arg(jit, 0); + jit_mov_gc_ptr(jit, cb, REG0, str); + + // Push the return value onto the stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_STRING); + mov(cb, stack_ret, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_opt_str_uminus(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + if (!assume_bop_not_redefined(jit, STRING_REDEFINED_OP_FLAG, BOP_UMINUS)) { + return YJIT_CANT_COMPILE; + } + + VALUE str = jit_get_arg(jit, 0); + jit_mov_gc_ptr(jit, cb, REG0, str); + + // Push the return value onto the stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_STRING); + mov(cb, stack_ret, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_opt_not(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_size(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_length(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_regexpmatch2(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + return gen_opt_send_without_block(jit, ctx, cb); +} + +static codegen_status_t +gen_opt_case_dispatch(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Normally this instruction would lookup the key in a hash and jump to an + // offset based on that. + // Instead we can take the fallback case and continue with the next + // instruction. + // We'd hope that our jitted code will be sufficiently fast without the + // hash lookup, at least for small hashes, but it's worth revisiting this + // assumption in the future. + + ctx_stack_pop(ctx, 1); + + return YJIT_KEEP_COMPILING; // continue with the next instruction +} + +static void +gen_branchif_branch(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + jz_ptr(cb, target1); + break; + + case SHAPE_NEXT1: + jnz_ptr(cb, target0); + break; + + case SHAPE_DEFAULT: + jnz_ptr(cb, target0); + jmp_ptr(cb, target1); + break; + } +} + +static codegen_status_t +gen_branchif(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t jump_offset = (int32_t)jit_get_arg(jit, 0); + + // Check for interrupts, but only on backward branches that may create loops + if (jump_offset < 0) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + yjit_check_ints(cb, side_exit); + } + + // Test if any bit (outside of the Qnil bit) is on + // RUBY_Qfalse /* ...0000 0000 */ + // RUBY_Qnil /* ...0000 1000 */ + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + test(cb, val_opnd, imm_opnd(~Qnil)); + + // Get the branch target instruction offsets + uint32_t next_idx = jit_next_insn_idx(jit); + uint32_t jump_idx = next_idx + jump_offset; + blockid_t next_block = { jit->iseq, next_idx }; + blockid_t jump_block = { jit->iseq, jump_idx }; + + // Generate the branch instructions + gen_branch( + jit, + ctx, + jump_block, + ctx, + next_block, + ctx, + gen_branchif_branch + ); + + return YJIT_END_BLOCK; +} + +static void +gen_branchunless_branch(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + jnz_ptr(cb, target1); + break; + + case SHAPE_NEXT1: + jz_ptr(cb, target0); + break; + + case SHAPE_DEFAULT: + jz_ptr(cb, target0); + jmp_ptr(cb, target1); + break; + } +} + +static codegen_status_t +gen_branchunless(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t jump_offset = (int32_t)jit_get_arg(jit, 0); + + // Check for interrupts, but only on backward branches that may create loops + if (jump_offset < 0) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + yjit_check_ints(cb, side_exit); + } + + // Test if any bit (outside of the Qnil bit) is on + // RUBY_Qfalse /* ...0000 0000 */ + // RUBY_Qnil /* ...0000 1000 */ + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + test(cb, val_opnd, imm_opnd(~Qnil)); + + // Get the branch target instruction offsets + uint32_t next_idx = jit_next_insn_idx(jit); + uint32_t jump_idx = next_idx + jump_offset; + blockid_t next_block = { jit->iseq, next_idx }; + blockid_t jump_block = { jit->iseq, jump_idx }; + + // Generate the branch instructions + gen_branch( + jit, + ctx, + jump_block, + ctx, + next_block, + ctx, + gen_branchunless_branch + ); + + return YJIT_END_BLOCK; +} + +static void +gen_branchnil_branch(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + jne_ptr(cb, target1); + break; + + case SHAPE_NEXT1: + je_ptr(cb, target0); + break; + + case SHAPE_DEFAULT: + je_ptr(cb, target0); + jmp_ptr(cb, target1); + break; + } +} + +static codegen_status_t +gen_branchnil(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t jump_offset = (int32_t)jit_get_arg(jit, 0); + + // Check for interrupts, but only on backward branches that may create loops + if (jump_offset < 0) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + yjit_check_ints(cb, side_exit); + } + + // Test if the value is Qnil + // RUBY_Qnil /* ...0000 1000 */ + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + cmp(cb, val_opnd, imm_opnd(Qnil)); + + // Get the branch target instruction offsets + uint32_t next_idx = jit_next_insn_idx(jit); + uint32_t jump_idx = next_idx + jump_offset; + blockid_t next_block = { jit->iseq, next_idx }; + blockid_t jump_block = { jit->iseq, jump_idx }; + + // Generate the branch instructions + gen_branch( + jit, + ctx, + jump_block, + ctx, + next_block, + ctx, + gen_branchnil_branch + ); + + return YJIT_END_BLOCK; +} + +static codegen_status_t +gen_jump(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + int32_t jump_offset = (int32_t)jit_get_arg(jit, 0); + + // Check for interrupts, but only on backward branches that may create loops + if (jump_offset < 0) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + yjit_check_ints(cb, side_exit); + } + + // Get the branch target instruction offsets + uint32_t jump_idx = jit_next_insn_idx(jit) + jump_offset; + blockid_t jump_block = { jit->iseq, jump_idx }; + + // Generate the jump instruction + gen_direct_jump( + jit, + ctx, + jump_block + ); + + return YJIT_END_BLOCK; +} + +/* +Guard that self or a stack operand has the same class as `known_klass`, using +`sample_instance` to speculate about the shape of the runtime value. +FIXNUM and on-heap integers are treated as if they have distinct classes, and +the guard generated for one will fail for the other. + +Recompile as contingency if possible, or take side exit a last resort. +*/ +static bool +jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_t insn_opnd, VALUE sample_instance, const int max_chain_depth, uint8_t *side_exit) +{ + val_type_t val_type = ctx_get_opnd_type(ctx, insn_opnd); + + if (known_klass == rb_cNilClass) { + RUBY_ASSERT(!val_type.is_heap); + if (val_type.type != ETYPE_NIL) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + ADD_COMMENT(cb, "guard object is nil"); + cmp(cb, REG0, imm_opnd(Qnil)); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_NIL); + } + } + else if (known_klass == rb_cTrueClass) { + RUBY_ASSERT(!val_type.is_heap); + if (val_type.type != ETYPE_TRUE) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + ADD_COMMENT(cb, "guard object is true"); + cmp(cb, REG0, imm_opnd(Qtrue)); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_TRUE); + } + } + else if (known_klass == rb_cFalseClass) { + RUBY_ASSERT(!val_type.is_heap); + if (val_type.type != ETYPE_FALSE) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + ADD_COMMENT(cb, "guard object is false"); + STATIC_ASSERT(qfalse_is_zero, Qfalse == 0); + test(cb, REG0, REG0); + jit_chain_guard(JCC_JNZ, jit, ctx, max_chain_depth, side_exit); + + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FALSE); + } + } + else if (known_klass == rb_cInteger && FIXNUM_P(sample_instance)) { + RUBY_ASSERT(!val_type.is_heap); + // We will guard fixnum and bignum as though they were separate classes + // BIGNUM can be handled by the general else case below + if (val_type.type != ETYPE_FIXNUM || !val_type.is_imm) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + ADD_COMMENT(cb, "guard object is fixnum"); + test(cb, REG0, imm_opnd(RUBY_FIXNUM_FLAG)); + jit_chain_guard(JCC_JZ, jit, ctx, max_chain_depth, side_exit); + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FIXNUM); + } + } + else if (known_klass == rb_cSymbol && STATIC_SYM_P(sample_instance)) { + RUBY_ASSERT(!val_type.is_heap); + // We will guard STATIC vs DYNAMIC as though they were separate classes + // DYNAMIC symbols can be handled by the general else case below + if (val_type.type != ETYPE_SYMBOL || !val_type.is_imm) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + ADD_COMMENT(cb, "guard object is static symbol"); + STATIC_ASSERT(special_shift_is_8, RUBY_SPECIAL_SHIFT == 8); + cmp(cb, REG0_8, imm_opnd(RUBY_SYMBOL_FLAG)); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_STATIC_SYMBOL); + } + } + else if (known_klass == rb_cFloat && FLONUM_P(sample_instance)) { + RUBY_ASSERT(!val_type.is_heap); + if (val_type.type != ETYPE_FLONUM || !val_type.is_imm) { + RUBY_ASSERT(val_type.type == ETYPE_UNKNOWN); + + // We will guard flonum vs heap float as though they were separate classes + ADD_COMMENT(cb, "guard object is flonum"); + mov(cb, REG1, REG0); + and(cb, REG1, imm_opnd(RUBY_FLONUM_MASK)); + cmp(cb, REG1, imm_opnd(RUBY_FLONUM_FLAG)); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FLONUM); + } + } + else if (FL_TEST(known_klass, FL_SINGLETON) && sample_instance == rb_attr_get(known_klass, id__attached__)) { + // Singleton classes are attached to one specific object, so we can + // avoid one memory access (and potentially the is_heap check) by + // looking for the expected object directly. + // Note that in case the sample instance has a singleton class that + // doesn't attach to the sample instance, it means the sample instance + // has an empty singleton class that hasn't been materialized yet. In + // this case, comparing against the sample instance doesn't guarantee + // that its singleton class is empty, so we can't avoid the memory + // access. As an example, `Object.new.singleton_class` is an object in + // this situation. + ADD_COMMENT(cb, "guard known object with singleton class"); + // TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the object. + jit_mov_gc_ptr(jit, cb, REG1, sample_instance); + cmp(cb, REG0, REG1); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + } + else { + RUBY_ASSERT(!val_type.is_imm); + + // Check that the receiver is a heap object + // Note: if we get here, the class doesn't have immediate instances. + if (!val_type.is_heap) { + ADD_COMMENT(cb, "guard not immediate"); + RUBY_ASSERT(Qfalse < Qnil); + test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK)); + jit_chain_guard(JCC_JNZ, jit, ctx, max_chain_depth, side_exit); + cmp(cb, REG0, imm_opnd(Qnil)); + jit_chain_guard(JCC_JBE, jit, ctx, max_chain_depth, side_exit); + + ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_HEAP); + } + + x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass)); + + // Bail if receiver class is different from known_klass + // TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the class. + ADD_COMMENT(cb, "guard known class"); + jit_mov_gc_ptr(jit, cb, REG1, known_klass); + cmp(cb, klass_opnd, REG1); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + } + + return true; +} + +// Generate ancestry guard for protected callee. +// Calls to protected callees only go through when self.is_a?(klass_that_defines_the_callee). +static void +jit_protected_callee_ancestry_guard(jitstate_t *jit, codeblock_t *cb, const rb_callable_method_entry_t *cme, uint8_t *side_exit) +{ + // See vm_call_method(). + mov(cb, C_ARG_REGS[0], member_opnd(REG_CFP, rb_control_frame_t, self)); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[1], cme->defined_class); + // Note: PC isn't written to current control frame as rb_is_kind_of() shouldn't raise. + // VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass); + call_ptr(cb, REG0, (void *)&rb_obj_is_kind_of); + test(cb, RAX, RAX); + jz_ptr(cb, COUNTED_EXIT(jit, side_exit, send_se_protected_check_failed)); +} + +// Return true when the codegen function generates code. +// known_recv_klass is non-NULL when the caller has used jit_guard_known_klass(). +// See yjit_reg_method(). +typedef bool (*method_codegen_t)(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass); + +// Register a specialized codegen function for a particular method. Note that +// the if the function returns true, the code it generates runs without a +// control frame and without interrupt checks. To avoid creating observable +// behavior changes, the codegen function should only target simple code paths +// that do not allocate and do not make method calls. +static void +yjit_reg_method(VALUE klass, const char *mid_str, method_codegen_t gen_fn) +{ + ID mid = rb_intern(mid_str); + const rb_method_entry_t *me = rb_method_entry_at(klass, mid); + + if (!me) { + rb_bug("undefined optimized method: %s", rb_id2name(mid)); + } + + // For now, only cfuncs are supported + RUBY_ASSERT(me && me->def); + RUBY_ASSERT(me->def->type == VM_METHOD_TYPE_CFUNC); + + st_insert(yjit_method_codegen_table, (st_data_t)me->def->method_serial, (st_data_t)gen_fn); +} + +// Codegen for rb_obj_not(). +// Note, caller is responsible for generating all the right guards, including +// arity guards. +static bool +jit_rb_obj_not(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass) +{ + const val_type_t recv_opnd = ctx_get_opnd_type(ctx, OPND_STACK(0)); + + if (recv_opnd.type == ETYPE_NIL || recv_opnd.type == ETYPE_FALSE) { + ADD_COMMENT(cb, "rb_obj_not(nil_or_false)"); + ctx_stack_pop(ctx, 1); + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_TRUE); + mov(cb, out_opnd, imm_opnd(Qtrue)); + } + else if (recv_opnd.is_heap || recv_opnd.type != ETYPE_UNKNOWN) { + // Note: recv_opnd.type != ETYPE_NIL && recv_opnd.type != ETYPE_FALSE. + ADD_COMMENT(cb, "rb_obj_not(truthy)"); + ctx_stack_pop(ctx, 1); + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_FALSE); + mov(cb, out_opnd, imm_opnd(Qfalse)); + } + else { + // jit_guard_known_klass() already ran on the receiver which should + // have deduced deduced the type of the receiver. This case should be + // rare if not unreachable. + return false; + } + return true; +} + +// Codegen for rb_true() +static bool +jit_rb_true(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass) +{ + ADD_COMMENT(cb, "nil? == true"); + ctx_stack_pop(ctx, 1); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_TRUE); + mov(cb, stack_ret, imm_opnd(Qtrue)); + return true; +} + +// Codegen for rb_false() +static bool +jit_rb_false(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass) +{ + ADD_COMMENT(cb, "nil? == false"); + ctx_stack_pop(ctx, 1); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_FALSE); + mov(cb, stack_ret, imm_opnd(Qfalse)); + return true; +} + +// Codegen for rb_obj_equal() +// object identity comparison +static bool +jit_rb_obj_equal(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass) +{ + ADD_COMMENT(cb, "equal?"); + x86opnd_t obj1 = ctx_stack_pop(ctx, 1); + x86opnd_t obj2 = ctx_stack_pop(ctx, 1); + + mov(cb, REG0, obj1); + cmp(cb, REG0, obj2); + mov(cb, REG0, imm_opnd(Qtrue)); + mov(cb, REG1, imm_opnd(Qfalse)); + cmovne(cb, REG0, REG1); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_IMM); + mov(cb, stack_ret, REG0); + return true; +} + +static VALUE +yjit_str_bytesize(VALUE str) +{ + return LONG2NUM(RSTRING_LEN(str)); +} + +static bool +jit_rb_str_bytesize(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *known_recv_klass) +{ + ADD_COMMENT(cb, "String#bytesize"); + + x86opnd_t recv = ctx_stack_pop(ctx, 1); + mov(cb, C_ARG_REGS[0], recv); + call_ptr(cb, REG0, (void *)&yjit_str_bytesize); + + x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, out_opnd, RAX); + + return true; +} + +// Codegen for rb_str_to_s() +// When String#to_s is called on a String instance, the method returns self and +// most of the overhead comes from setting up the method call. We observed that +// this situation happens a lot in some workloads. +static bool +jit_rb_str_to_s(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *recv_known_klass) +{ + if (recv_known_klass && *recv_known_klass == rb_cString) { + ADD_COMMENT(cb, "to_s on plain string"); + // The method returns the receiver, which is already on the stack. + // No stack movement. + return true; + } + return false; +} + +static bool +jit_thread_s_current(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *recv_known_klass) +{ + ADD_COMMENT(cb, "Thread.current"); + ctx_stack_pop(ctx, 1); + + // ec->thread_ptr + mov(cb, REG0, member_opnd(REG_EC, rb_execution_context_t, thread_ptr)); + + // thread->self + mov(cb, REG0, member_opnd(REG0, rb_thread_t, self)); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HEAP); + mov(cb, stack_ret, REG0); + return true; +} + +// Check if we know how to codegen for a particular cfunc method +static method_codegen_t +lookup_cfunc_codegen(const rb_method_definition_t *def) +{ + method_codegen_t gen_fn; + if (st_lookup(yjit_method_codegen_table, def->method_serial, (st_data_t *)&gen_fn)) { + return gen_fn; + } + return NULL; +} + +// Is anyone listening for :c_call and :c_return event currently? +static bool +c_method_tracing_currently_enabled(const jitstate_t *jit) +{ + rb_event_flag_t tracing_events; + if (rb_multi_ractor_p()) { + tracing_events = ruby_vm_event_enabled_global_flags; + } + else { + // At the time of writing, events are never removed from + // ruby_vm_event_enabled_global_flags so always checking using it would + // mean we don't compile even after tracing is disabled. + tracing_events = rb_ec_ractor_hooks(jit->ec)->events; + } + + return tracing_events & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN); +} + +static codegen_status_t +gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc, VALUE *recv_known_klass) +{ + const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc); + + // If the function expects a Ruby array of arguments + if (cfunc->argc < 0 && cfunc->argc != -1) { + GEN_COUNTER_INC(cb, send_cfunc_ruby_array_varg); + return YJIT_CANT_COMPILE; + } + + // If the argument count doesn't match + if (cfunc->argc >= 0 && cfunc->argc != argc) { + GEN_COUNTER_INC(cb, send_cfunc_argc_mismatch); + return YJIT_CANT_COMPILE; + } + + // Don't JIT functions that need C stack arguments for now + if (cfunc->argc >= 0 && argc + 1 > NUM_C_ARG_REGS) { + GEN_COUNTER_INC(cb, send_cfunc_toomany_args); + return YJIT_CANT_COMPILE; + } + + if (c_method_tracing_currently_enabled(jit)) { + // Don't JIT if tracing c_call or c_return + GEN_COUNTER_INC(cb, send_cfunc_tracing); + return YJIT_CANT_COMPILE; + } + + // Delegate to codegen for C methods if we have it. + { + method_codegen_t known_cfunc_codegen; + if ((known_cfunc_codegen = lookup_cfunc_codegen(cme->def))) { + if (known_cfunc_codegen(jit, ctx, ci, cme, block, argc, recv_known_klass)) { + // cfunc codegen generated code. Terminate the block so + // there isn't multiple calls in the same block. + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; + } + } + } + + // Callee method ID + //ID mid = vm_ci_mid(ci); + //printf("JITting call to C function \"%s\", argc: %lu\n", rb_id2name(mid), argc); + //print_str(cb, ""); + //print_str(cb, "calling CFUNC:"); + //print_str(cb, rb_id2name(mid)); + //print_str(cb, "recv"); + //print_ptr(cb, recv); + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Check for interrupts + yjit_check_ints(cb, side_exit); + + // Stack overflow check + // #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) + // REG_CFP <= REG_SP + 4 * sizeof(VALUE) + sizeof(rb_control_frame_t) + lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * 4 + 2 * sizeof(rb_control_frame_t))); + cmp(cb, REG_CFP, REG0); + jle_ptr(cb, COUNTED_EXIT(jit, side_exit, send_se_cf_overflow)); + + // Points to the receiver operand on the stack + x86opnd_t recv = ctx_stack_opnd(ctx, argc); + + // Store incremented PC into current control frame in case callee raises. + jit_save_pc(jit, REG0); + + if (block) { + // Change cfp->block_code in the current frame. See vm_caller_setup_arg_block(). + // VM_CFP_TO_CAPTURED_BLCOK does &cfp->self, rb_captured_block->code.iseq aliases + // with cfp->block_code. + jit_mov_gc_ptr(jit, cb, REG0, (VALUE)block); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, block_code), REG0); + } + + // Increment the stack pointer by 3 (in the callee) + // sp += 3 + lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * 3)); + + // Write method entry at sp[-3] + // sp[-3] = me; + // Put compile time cme into REG1. It's assumed to be valid because we are notified when + // any cme we depend on become outdated. See rb_yjit_method_lookup_change(). + jit_mov_gc_ptr(jit, cb, REG1, (VALUE)cme); + mov(cb, mem_opnd(64, REG0, 8 * -3), REG1); + + // Write block handler at sp[-2] + // sp[-2] = block_handler; + if (block) { + // reg1 = VM_BH_FROM_ISEQ_BLOCK(VM_CFP_TO_CAPTURED_BLOCK(reg_cfp)); + lea(cb, REG1, member_opnd(REG_CFP, rb_control_frame_t, self)); + or(cb, REG1, imm_opnd(1)); + mov(cb, mem_opnd(64, REG0, 8 * -2), REG1); + } + else { + mov(cb, mem_opnd(64, REG0, 8 * -2), imm_opnd(VM_BLOCK_HANDLER_NONE)); + } + + // Write env flags at sp[-1] + // sp[-1] = frame_type; + uint64_t frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL; + mov(cb, mem_opnd(64, REG0, 8 * -1), imm_opnd(frame_type)); + + // Allocate a new CFP (ec->cfp--) + sub( + cb, + member_opnd(REG_EC, rb_execution_context_t, cfp), + imm_opnd(sizeof(rb_control_frame_t)) + ); + + // Setup the new frame + // *cfp = (const struct rb_control_frame_struct) { + // .pc = 0, + // .sp = sp, + // .iseq = 0, + // .self = recv, + // .ep = sp - 1, + // .block_code = 0, + // .__bp__ = sp, + // }; + mov(cb, REG1, member_opnd(REG_EC, rb_execution_context_t, cfp)); + mov(cb, member_opnd(REG1, rb_control_frame_t, pc), imm_opnd(0)); + mov(cb, member_opnd(REG1, rb_control_frame_t, sp), REG0); + mov(cb, member_opnd(REG1, rb_control_frame_t, iseq), imm_opnd(0)); + mov(cb, member_opnd(REG1, rb_control_frame_t, block_code), imm_opnd(0)); + mov(cb, member_opnd(REG1, rb_control_frame_t, __bp__), REG0); + sub(cb, REG0, imm_opnd(sizeof(VALUE))); + mov(cb, member_opnd(REG1, rb_control_frame_t, ep), REG0); + mov(cb, REG0, recv); + mov(cb, member_opnd(REG1, rb_control_frame_t, self), REG0); + + // Verify that we are calling the right function + if (YJIT_CHECK_MODE > 0) { + // Call check_cfunc_dispatch + mov(cb, C_ARG_REGS[0], recv); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[1], (VALUE)ci); + mov(cb, C_ARG_REGS[2], const_ptr_opnd((void *)cfunc->func)); + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[3], (VALUE)cme); + call_ptr(cb, REG0, (void *)&check_cfunc_dispatch); + } + + // Copy SP into RAX because REG_SP will get overwritten + lea(cb, RAX, ctx_sp_opnd(ctx, 0)); + + // Pop the C function arguments from the stack (in the caller) + ctx_stack_pop(ctx, argc + 1); + + // Write interpreter SP into CFP. + // Needed in case the callee yields to the block. + jit_save_sp(jit, ctx); + + // Non-variadic method + if (cfunc->argc >= 0) { + // Copy the arguments from the stack to the C argument registers + // self is the 0th argument and is at index argc from the stack top + for (int32_t i = 0; i < argc + 1; ++i) + { + x86opnd_t stack_opnd = mem_opnd(64, RAX, -(argc + 1 - i) * SIZEOF_VALUE); + x86opnd_t c_arg_reg = C_ARG_REGS[i]; + mov(cb, c_arg_reg, stack_opnd); + } + } + // Variadic method + if (cfunc->argc == -1) { + // The method gets a pointer to the first argument + // rb_f_puts(int argc, VALUE *argv, VALUE recv) + mov(cb, C_ARG_REGS[0], imm_opnd(argc)); + lea(cb, C_ARG_REGS[1], mem_opnd(64, RAX, -(argc) * SIZEOF_VALUE)); + mov(cb, C_ARG_REGS[2], mem_opnd(64, RAX, -(argc + 1) * SIZEOF_VALUE)); + } + + // Call the C function + // VALUE ret = (cfunc->func)(recv, argv[0], argv[1]); + // cfunc comes from compile-time cme->def, which we assume to be stable. + // Invalidation logic is in rb_yjit_method_lookup_change() + call_ptr(cb, REG0, (void*)cfunc->func); + + // Record code position for TracePoint patching. See full_cfunc_return(). + record_global_inval_patch(cb, outline_full_cfunc_return_pos); + + // Push the return value on the Ruby stack + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + // Pop the stack frame (ec->cfp++) + add( + cb, + member_opnd(REG_EC, rb_execution_context_t, cfp), + imm_opnd(sizeof(rb_control_frame_t)) + ); + + // cfunc calls may corrupt types + ctx_clear_local_types(ctx); + + // Note: the return block of gen_send_iseq() has ctx->sp_offset == 1 + // which allows for sharing the same successor. + + // Jump (fall through) to the call continuation block + // We do this to end the current block after the call + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; +} + +static void +gen_return_branch(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + case SHAPE_NEXT1: + RUBY_ASSERT(false); + break; + + case SHAPE_DEFAULT: + mov(cb, REG0, const_ptr_opnd(target0)); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0); + break; + } +} + +// If true, the iseq is leaf and it can be replaced by a single C call. +static bool +rb_leaf_invokebuiltin_iseq_p(const rb_iseq_t *iseq) +{ + unsigned int invokebuiltin_len = insn_len(BIN(opt_invokebuiltin_delegate_leave)); + unsigned int leave_len = insn_len(BIN(leave)); + + return (iseq->body->iseq_size == (invokebuiltin_len + leave_len) && + rb_vm_insn_addr2opcode((void *)iseq->body->iseq_encoded[0]) == BIN(opt_invokebuiltin_delegate_leave) && + rb_vm_insn_addr2opcode((void *)iseq->body->iseq_encoded[invokebuiltin_len]) == BIN(leave) && + iseq->body->builtin_inline_p + ); + } + +// Return an rb_builtin_function if the iseq contains only that leaf builtin function. +static const struct rb_builtin_function* +rb_leaf_builtin_function(const rb_iseq_t *iseq) +{ + if (!rb_leaf_invokebuiltin_iseq_p(iseq)) + return NULL; + return (const struct rb_builtin_function *)iseq->body->iseq_encoded[1]; +} + +static codegen_status_t +gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, int32_t argc) +{ + const rb_iseq_t *iseq = def_iseq_ptr(cme->def); + + // When you have keyword arguments, there is an extra object that gets + // placed on the stack the represents a bitmap of the keywords that were not + // specified at the call site. We need to keep track of the fact that this + // value is present on the stack in order to properly set up the callee's + // stack pointer. + const bool doing_kw_call = iseq->body->param.flags.has_kw; + const bool supplying_kws = vm_ci_flag(ci) & VM_CALL_KWARG; + + if (vm_ci_flag(ci) & VM_CALL_TAILCALL) { + // We can't handle tailcalls + GEN_COUNTER_INC(cb, send_iseq_tailcall); + return YJIT_CANT_COMPILE; + } + + // No support for callees with these parameters yet as they require allocation + // or complex handling. + if (iseq->body->param.flags.has_rest || + iseq->body->param.flags.has_post || + iseq->body->param.flags.has_kwrest) { + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + + // If we have keyword arguments being passed to a callee that only takes + // positionals, then we need to allocate a hash. For now we're going to + // call that too complex and bail. + if (supplying_kws && !iseq->body->param.flags.has_kw) { + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + + // If we have a method accepting no kwargs (**nil), exit if we have passed + // it any kwargs. + if (supplying_kws && iseq->body->param.flags.accepts_no_kwarg) { + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + + // For computing number of locals to setup for the callee + int num_params = iseq->body->param.size; + + // Block parameter handling. This mirrors setup_parameters_complex(). + if (iseq->body->param.flags.has_block) { + if (iseq->body->local_iseq == iseq) { + // Block argument is passed through EP and not setup as a local in + // the callee. + num_params--; + } + else { + // In this case (param.flags.has_block && local_iseq != iseq), + // the block argument is setup as a local variable and requires + // materialization (allocation). Bail. + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + } + + uint32_t start_pc_offset = 0; + + const int required_num = iseq->body->param.lead_num; + + // This struct represents the metadata about the caller-specified + // keyword arguments. + const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci); + const int kw_arg_num = kw_arg ? kw_arg->keyword_len : 0; + + // Arity handling and optional parameter setup + const int opts_filled = argc - required_num - kw_arg_num; + const int opt_num = iseq->body->param.opt_num; + const int opts_missing = opt_num - opts_filled; + + if (opts_filled < 0 || opts_filled > opt_num) { + GEN_COUNTER_INC(cb, send_iseq_arity_error); + return YJIT_CANT_COMPILE; + } + + // If we have unfilled optional arguments and keyword arguments then we + // would need to move adjust the arguments location to account for that. + // For now we aren't handling this case. + if (doing_kw_call && opts_missing > 0) { + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + + if (opt_num > 0) { + num_params -= opt_num - opts_filled; + start_pc_offset = (uint32_t)iseq->body->param.opt_table[opts_filled]; + } + + if (doing_kw_call) { + // Here we're calling a method with keyword arguments and specifying + // keyword arguments at this call site. + + // This struct represents the metadata about the callee-specified + // keyword parameters. + const struct rb_iseq_param_keyword *keyword = iseq->body->param.keyword; + + int required_kwargs_filled = 0; + + if (keyword->num > 30) { + // We have so many keywords that (1 << num) encoded as a FIXNUM + // (which shifts it left one more) no longer fits inside a 32-bit + // immediate. + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } + + // Check that the kwargs being passed are valid + if (supplying_kws) { + // This is the list of keyword arguments that the callee specified + // in its initial declaration. + const ID *callee_kwargs = keyword->table; + + // Here we're going to build up a list of the IDs that correspond to + // the caller-specified keyword arguments. If they're not in the + // same order as the order specified in the callee declaration, then + // we're going to need to generate some code to swap values around + // on the stack. + ID *caller_kwargs = ALLOCA_N(VALUE, kw_arg->keyword_len); + for (int kwarg_idx = 0; kwarg_idx < kw_arg->keyword_len; kwarg_idx++) + caller_kwargs[kwarg_idx] = SYM2ID(kw_arg->keywords[kwarg_idx]); + + // First, we're going to be sure that the names of every + // caller-specified keyword argument correspond to a name in the + // list of callee-specified keyword parameters. + for (int caller_idx = 0; caller_idx < kw_arg->keyword_len; caller_idx++) { + int callee_idx; + + for (callee_idx = 0; callee_idx < keyword->num; callee_idx++) { + if (caller_kwargs[caller_idx] == callee_kwargs[callee_idx]) { + break; + } + } + + // If the keyword was never found, then we know we have a + // mismatch in the names of the keyword arguments, so we need to + // bail. + if (callee_idx == keyword->num) { + GEN_COUNTER_INC(cb, send_iseq_kwargs_mismatch); + return YJIT_CANT_COMPILE; + } + + // Keep a count to ensure all required kwargs are specified + if (callee_idx < keyword->required_num) { + required_kwargs_filled++; + } + } + } + + RUBY_ASSERT(required_kwargs_filled <= keyword->required_num); + if (required_kwargs_filled != keyword->required_num) { + GEN_COUNTER_INC(cb, send_iseq_kwargs_mismatch); + return YJIT_CANT_COMPILE; + } + } + + // Number of locals that are not parameters + const int num_locals = iseq->body->local_table_size - num_params; + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Check for interrupts + yjit_check_ints(cb, side_exit); + + const struct rb_builtin_function *leaf_builtin = rb_leaf_builtin_function(iseq); + + if (leaf_builtin && !block && leaf_builtin->argc + 1 <= NUM_C_ARG_REGS) { + ADD_COMMENT(cb, "inlined leaf builtin"); + + // Call the builtin func (ec, recv, arg1, arg2, ...) + mov(cb, C_ARG_REGS[0], REG_EC); + + // Copy self and arguments + for (int32_t i = 0; i < leaf_builtin->argc + 1; i++) { + x86opnd_t stack_opnd = ctx_stack_opnd(ctx, leaf_builtin->argc - i); + x86opnd_t c_arg_reg = C_ARG_REGS[i + 1]; + mov(cb, c_arg_reg, stack_opnd); + } + ctx_stack_pop(ctx, leaf_builtin->argc + 1); + call_ptr(cb, REG0, (void *)leaf_builtin->func_ptr); + + // Push the return value + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + // Note: assuming that the leaf builtin doesn't change local variables here. + // Seems like a safe assumption. + + return YJIT_KEEP_COMPILING; + } + + // Stack overflow check + // Note that vm_push_frame checks it against a decremented cfp, hence the multiply by 2. + // #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) + ADD_COMMENT(cb, "stack overflow check"); + lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (num_locals + iseq->body->stack_max) + 2 * sizeof(rb_control_frame_t))); + cmp(cb, REG_CFP, REG0); + jle_ptr(cb, COUNTED_EXIT(jit, side_exit, send_se_cf_overflow)); + + if (doing_kw_call) { + // Here we're calling a method with keyword arguments and specifying + // keyword arguments at this call site. + + // Number of positional arguments the callee expects before the first + // keyword argument + const int args_before_kw = required_num + opt_num; + + // This struct represents the metadata about the caller-specified + // keyword arguments. + int caller_keyword_len = 0; + const VALUE *caller_keywords = NULL; + if (vm_ci_kwarg(ci)) { + caller_keyword_len = vm_ci_kwarg(ci)->keyword_len; + caller_keywords = &vm_ci_kwarg(ci)->keywords[0]; + } + + // This struct represents the metadata about the callee-specified + // keyword parameters. + const struct rb_iseq_param_keyword *const keyword = iseq->body->param.keyword; + + ADD_COMMENT(cb, "keyword args"); + + // This is the list of keyword arguments that the callee specified + // in its initial declaration. + const ID *callee_kwargs = keyword->table; + + int total_kwargs = keyword->num; + + // Here we're going to build up a list of the IDs that correspond to + // the caller-specified keyword arguments. If they're not in the + // same order as the order specified in the callee declaration, then + // we're going to need to generate some code to swap values around + // on the stack. + ID *caller_kwargs = ALLOCA_N(VALUE, total_kwargs); + int kwarg_idx; + for (kwarg_idx = 0; kwarg_idx < caller_keyword_len; kwarg_idx++) { + caller_kwargs[kwarg_idx] = SYM2ID(caller_keywords[kwarg_idx]); + } + + int unspecified_bits = 0; + + for (int callee_idx = keyword->required_num; callee_idx < total_kwargs; callee_idx++) { + bool already_passed = false; + ID callee_kwarg = callee_kwargs[callee_idx]; + + for (int caller_idx = 0; caller_idx < caller_keyword_len; caller_idx++) { + if (caller_kwargs[caller_idx] == callee_kwarg) { + already_passed = true; + break; + } + } + + if (!already_passed) { + // Reserve space on the stack for each default value we'll be + // filling in (which is done in the next loop). Also increments + // argc so that the callee's SP is recorded correctly. + argc++; + x86opnd_t default_arg = ctx_stack_push(ctx, TYPE_UNKNOWN); + VALUE default_value = keyword->default_values[callee_idx - keyword->required_num]; + + if (default_value == Qundef) { + // Qundef means that this value is not constant and must be + // recalculated at runtime, so we record it in unspecified_bits + // (Qnil is then used as a placeholder instead of Qundef). + unspecified_bits |= 0x01 << (callee_idx - keyword->required_num); + default_value = Qnil; + } + + // GC might move default_value. + jit_mov_gc_ptr(jit, cb, REG0, default_value); + mov(cb, default_arg, REG0); + + caller_kwargs[kwarg_idx++] = callee_kwarg; + } + } + RUBY_ASSERT(kwarg_idx == total_kwargs); + + // Next, we're going to loop through every keyword that was + // specified by the caller and make sure that it's in the correct + // place. If it's not we're going to swap it around with another one. + for (kwarg_idx = 0; kwarg_idx < total_kwargs; kwarg_idx++) { + ID callee_kwarg = callee_kwargs[kwarg_idx]; + + // If the argument is already in the right order, then we don't + // need to generate any code since the expected value is already + // in the right place on the stack. + if (callee_kwarg == caller_kwargs[kwarg_idx]) continue; + + // In this case the argument is not in the right place, so we + // need to find its position where it _should_ be and swap with + // that location. + for (int swap_idx = kwarg_idx + 1; swap_idx < total_kwargs; swap_idx++) { + if (callee_kwarg == caller_kwargs[swap_idx]) { + // First we're going to generate the code that is going + // to perform the actual swapping at runtime. + stack_swap(ctx, cb, argc - 1 - swap_idx - args_before_kw, argc - 1 - kwarg_idx - args_before_kw, REG1, REG0); + + // Next we're going to do some bookkeeping on our end so + // that we know the order that the arguments are + // actually in now. + ID tmp = caller_kwargs[kwarg_idx]; + caller_kwargs[kwarg_idx] = caller_kwargs[swap_idx]; + caller_kwargs[swap_idx] = tmp; + + break; + } + } + } + + // Keyword arguments cause a special extra local variable to be + // pushed onto the stack that represents the parameters that weren't + // explicitly given a value and have a non-constant default. + mov(cb, ctx_stack_opnd(ctx, -1), imm_opnd(INT2FIX(unspecified_bits))); + } + // Points to the receiver operand on the stack + x86opnd_t recv = ctx_stack_opnd(ctx, argc); + + // Store the updated SP on the current frame (pop arguments and receiver) + ADD_COMMENT(cb, "store caller sp"); + lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * -(argc + 1))); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG0); + + // Store the next PC in the current frame + jit_save_pc(jit, REG0); + + if (block) { + // Change cfp->block_code in the current frame. See vm_caller_setup_arg_block(). + // VM_CFP_TO_CAPTURED_BLCOK does &cfp->self, rb_captured_block->code.iseq aliases + // with cfp->block_code. + jit_mov_gc_ptr(jit, cb, REG0, (VALUE)block); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, block_code), REG0); + } + + // Adjust the callee's stack pointer + lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (3 + num_locals + doing_kw_call))); + + // Initialize local variables to Qnil + for (int i = 0; i < num_locals; i++) { + mov(cb, mem_opnd(64, REG0, sizeof(VALUE) * (i - num_locals - 3)), imm_opnd(Qnil)); + } + + ADD_COMMENT(cb, "push env"); + // Put compile time cme into REG1. It's assumed to be valid because we are notified when + // any cme we depend on become outdated. See rb_yjit_method_lookup_change(). + jit_mov_gc_ptr(jit, cb, REG1, (VALUE)cme); + // Write method entry at sp[-3] + // sp[-3] = me; + mov(cb, mem_opnd(64, REG0, 8 * -3), REG1); + + // Write block handler at sp[-2] + // sp[-2] = block_handler; + if (block) { + // reg1 = VM_BH_FROM_ISEQ_BLOCK(VM_CFP_TO_CAPTURED_BLOCK(reg_cfp)); + lea(cb, REG1, member_opnd(REG_CFP, rb_control_frame_t, self)); + or(cb, REG1, imm_opnd(1)); + mov(cb, mem_opnd(64, REG0, 8 * -2), REG1); + } + else { + mov(cb, mem_opnd(64, REG0, 8 * -2), imm_opnd(VM_BLOCK_HANDLER_NONE)); + } + + // Write env flags at sp[-1] + // sp[-1] = frame_type; + uint64_t frame_type = VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL; + mov(cb, mem_opnd(64, REG0, 8 * -1), imm_opnd(frame_type)); + + ADD_COMMENT(cb, "push callee CFP"); + // Allocate a new CFP (ec->cfp--) + sub(cb, REG_CFP, imm_opnd(sizeof(rb_control_frame_t))); + mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP); + + // Setup the new frame + // *cfp = (const struct rb_control_frame_struct) { + // .pc = pc, + // .sp = sp, + // .iseq = iseq, + // .self = recv, + // .ep = sp - 1, + // .block_code = 0, + // .__bp__ = sp, + // }; + mov(cb, REG1, recv); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, self), REG1); + mov(cb, REG_SP, REG0); // Switch to the callee's REG_SP + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG0); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, __bp__), REG0); + sub(cb, REG0, imm_opnd(sizeof(VALUE))); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, ep), REG0); + jit_mov_gc_ptr(jit, cb, REG0, (VALUE)iseq); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, iseq), REG0); + mov(cb, member_opnd(REG_CFP, rb_control_frame_t, block_code), imm_opnd(0)); + + // No need to set cfp->pc since the callee sets it whenever calling into routines + // that could look at it through jit_save_pc(). + // mov(cb, REG0, const_ptr_opnd(start_pc)); + // mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), REG0); + + // Stub so we can return to JITted code + blockid_t return_block = { jit->iseq, jit_next_insn_idx(jit) }; + + // Create a context for the callee + ctx_t callee_ctx = DEFAULT_CTX; + + // Set the argument types in the callee's context + for (int32_t arg_idx = 0; arg_idx < argc; ++arg_idx) { + val_type_t arg_type = ctx_get_opnd_type(ctx, OPND_STACK(argc - arg_idx - 1)); + ctx_set_local_type(&callee_ctx, arg_idx, arg_type); + } + val_type_t recv_type = ctx_get_opnd_type(ctx, OPND_STACK(argc)); + ctx_upgrade_opnd_type(&callee_ctx, OPND_SELF, recv_type); + + // The callee might change locals through Kernel#binding and other means. + ctx_clear_local_types(ctx); + + // Pop arguments and receiver in return context, push the return value + // After the return, sp_offset will be 1. The codegen for leave writes + // the return value in case of JIT-to-JIT return. + ctx_t return_ctx = *ctx; + ctx_stack_pop(&return_ctx, argc + 1); + ctx_stack_push(&return_ctx, TYPE_UNKNOWN); + return_ctx.sp_offset = 1; + return_ctx.chain_depth = 0; + + // Write the JIT return address on the callee frame + gen_branch( + jit, + ctx, + return_block, + &return_ctx, + return_block, + &return_ctx, + gen_return_branch + ); + + //print_str(cb, "calling Ruby func:"); + //print_str(cb, rb_id2name(vm_ci_mid(ci))); + + // Directly jump to the entry point of the callee + gen_direct_jump( + jit, + &callee_ctx, + (blockid_t){ iseq, start_pc_offset } + ); + + return YJIT_END_BLOCK; +} + +static codegen_status_t +gen_struct_aref(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, VALUE comptime_recv, VALUE comptime_recv_klass) { + if (vm_ci_argc(ci) != 0) { + return YJIT_CANT_COMPILE; + } + + const unsigned int off = cme->def->body.optimized.index; + + // Confidence checks + RUBY_ASSERT_ALWAYS(RB_TYPE_P(comptime_recv, T_STRUCT)); + RUBY_ASSERT_ALWAYS((long)off < RSTRUCT_LEN(comptime_recv)); + + // We are going to use an encoding that takes a 4-byte immediate which + // limits the offset to INT32_MAX. + { + uint64_t native_off = (uint64_t)off * (uint64_t)SIZEOF_VALUE; + if (native_off > (uint64_t)INT32_MAX) { + return YJIT_CANT_COMPILE; + } + } + + // All structs from the same Struct class should have the same + // length. So if our comptime_recv is embedded all runtime + // structs of the same class should be as well, and the same is + // true of the converse. + bool embedded = FL_TEST_RAW(comptime_recv, RSTRUCT_EMBED_LEN_MASK); + + ADD_COMMENT(cb, "struct aref"); + + x86opnd_t recv = ctx_stack_pop(ctx, 1); + + mov(cb, REG0, recv); + + if (embedded) { + mov(cb, REG0, member_opnd_idx(REG0, struct RStruct, as.ary, off)); + } + else { + mov(cb, REG0, member_opnd(REG0, struct RStruct, as.heap.ptr)); + mov(cb, REG0, mem_opnd(64, REG0, SIZEOF_VALUE * off)); + } + + x86opnd_t ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, ret, REG0); + + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; +} + +static codegen_status_t +gen_struct_aset(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, VALUE comptime_recv, VALUE comptime_recv_klass) { + if (vm_ci_argc(ci) != 1) { + return YJIT_CANT_COMPILE; + } + + const unsigned int off = cme->def->body.optimized.index; + + // Confidence checks + RUBY_ASSERT_ALWAYS(RB_TYPE_P(comptime_recv, T_STRUCT)); + RUBY_ASSERT_ALWAYS((long)off < RSTRUCT_LEN(comptime_recv)); + + ADD_COMMENT(cb, "struct aset"); + + x86opnd_t val = ctx_stack_pop(ctx, 1); + x86opnd_t recv = ctx_stack_pop(ctx, 1); + + mov(cb, C_ARG_REGS[0], recv); + mov(cb, C_ARG_REGS[1], imm_opnd(off)); + mov(cb, C_ARG_REGS[2], val); + call_ptr(cb, REG0, (void *)RSTRUCT_SET); + + x86opnd_t ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, ret, RAX); + + jit_jump_to_next_insn(jit, ctx); + return YJIT_END_BLOCK; +} + +const rb_callable_method_entry_t * +rb_aliased_callable_method_entry(const rb_callable_method_entry_t *me); + +static codegen_status_t +gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t *block) +{ + // Relevant definitions: + // rb_execution_context_t : vm_core.h + // invoker, cfunc logic : method.h, vm_method.c + // rb_callinfo : vm_callinfo.h + // rb_callable_method_entry_t : method.h + // vm_call_cfunc_with_frame : vm_insnhelper.c + // + // For a general overview for how the interpreter calls methods, + // see vm_call_method(). + + const struct rb_callinfo *ci = cd->ci; // info about the call site + + int32_t argc = (int32_t)vm_ci_argc(ci); + ID mid = vm_ci_mid(ci); + + // Don't JIT calls with keyword splat + if (vm_ci_flag(ci) & VM_CALL_KW_SPLAT) { + GEN_COUNTER_INC(cb, send_kw_splat); + return YJIT_CANT_COMPILE; + } + + // Don't JIT calls that aren't simple + // Note, not using VM_CALL_ARGS_SIMPLE because sometimes we pass a block. + if ((vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) != 0) { + GEN_COUNTER_INC(cb, send_args_splat); + return YJIT_CANT_COMPILE; + } + if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) != 0) { + GEN_COUNTER_INC(cb, send_block_arg); + return YJIT_CANT_COMPILE; + } + + // Defer compilation so we can specialize on class of receiver + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + VALUE comptime_recv = jit_peek_at_stack(jit, ctx, argc); + VALUE comptime_recv_klass = CLASS_OF(comptime_recv); + + // Guard that the receiver has the same class as the one from compile time + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Points to the receiver operand on the stack + x86opnd_t recv = ctx_stack_opnd(ctx, argc); + insn_opnd_t recv_opnd = OPND_STACK(argc); + mov(cb, REG0, recv); + if (!jit_guard_known_klass(jit, ctx, comptime_recv_klass, recv_opnd, comptime_recv, SEND_MAX_DEPTH, side_exit)) { + return YJIT_CANT_COMPILE; + } + + // Do method lookup + const rb_callable_method_entry_t *cme = rb_callable_method_entry(comptime_recv_klass, mid); + if (!cme) { + // TODO: counter + return YJIT_CANT_COMPILE; + } + + switch (METHOD_ENTRY_VISI(cme)) { + case METHOD_VISI_PUBLIC: + // Can always call public methods + break; + case METHOD_VISI_PRIVATE: + if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) { + // Can only call private methods with FCALL callsites. + // (at the moment they are callsites without a receiver or an explicit `self` receiver) + return YJIT_CANT_COMPILE; + } + break; + case METHOD_VISI_PROTECTED: + jit_protected_callee_ancestry_guard(jit, cb, cme, side_exit); + break; + case METHOD_VISI_UNDEF: + RUBY_ASSERT(false && "cmes should always have a visibility"); + break; + } + + // Register block for invalidation + RUBY_ASSERT(cme->called_id == mid); + assume_method_lookup_stable(comptime_recv_klass, cme, jit); + + // To handle the aliased method case (VM_METHOD_TYPE_ALIAS) + while (true) { + // switch on the method type + switch (cme->def->type) { + case VM_METHOD_TYPE_ISEQ: + return gen_send_iseq(jit, ctx, ci, cme, block, argc); + case VM_METHOD_TYPE_CFUNC: + if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { + GEN_COUNTER_INC(cb, send_cfunc_kwargs); + return YJIT_CANT_COMPILE; + } + return gen_send_cfunc(jit, ctx, ci, cme, block, argc, &comptime_recv_klass); + case VM_METHOD_TYPE_IVAR: + if (argc != 0) { + // Argument count mismatch. Getters take no arguments. + GEN_COUNTER_INC(cb, send_getter_arity); + return YJIT_CANT_COMPILE; + } + if (c_method_tracing_currently_enabled(jit)) { + // Can't generate code for firing c_call and c_return events + // :attr-tracing: + // Handling the C method tracing events for attr_accessor + // methods is easier than regular C methods as we know the + // "method" we are calling into never enables those tracing + // events. Once global invalidation runs, the code for the + // attr_accessor is invalidated and we exit at the closest + // instruction boundary which is always outside of the body of + // the attr_accessor code. + GEN_COUNTER_INC(cb, send_cfunc_tracing); + return YJIT_CANT_COMPILE; + } + + mov(cb, REG0, recv); + + ID ivar_name = cme->def->body.attr.id; + return gen_get_ivar(jit, ctx, SEND_MAX_DEPTH, comptime_recv, ivar_name, recv_opnd, side_exit); + case VM_METHOD_TYPE_ATTRSET: + if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { + GEN_COUNTER_INC(cb, send_attrset_kwargs); + return YJIT_CANT_COMPILE; + } + else if (argc != 1 || !RB_TYPE_P(comptime_recv, T_OBJECT)) { + GEN_COUNTER_INC(cb, send_ivar_set_method); + return YJIT_CANT_COMPILE; + } + else if (c_method_tracing_currently_enabled(jit)) { + // Can't generate code for firing c_call and c_return events + // See :attr-tracing: + GEN_COUNTER_INC(cb, send_cfunc_tracing); + return YJIT_CANT_COMPILE; + } + else { + ID ivar_name = cme->def->body.attr.id; + return gen_set_ivar(jit, ctx, comptime_recv, comptime_recv_klass, ivar_name); + } + // Block method, e.g. define_method(:foo) { :my_block } + case VM_METHOD_TYPE_BMETHOD: + GEN_COUNTER_INC(cb, send_bmethod); + return YJIT_CANT_COMPILE; + case VM_METHOD_TYPE_ZSUPER: + GEN_COUNTER_INC(cb, send_zsuper_method); + return YJIT_CANT_COMPILE; + case VM_METHOD_TYPE_ALIAS: { + // Retrieve the alised method and re-enter the switch + cme = rb_aliased_callable_method_entry(cme); + continue; + } + case VM_METHOD_TYPE_UNDEF: + GEN_COUNTER_INC(cb, send_undef_method); + return YJIT_CANT_COMPILE; + case VM_METHOD_TYPE_NOTIMPLEMENTED: + GEN_COUNTER_INC(cb, send_not_implemented_method); + return YJIT_CANT_COMPILE; + // Send family of methods, e.g. call/apply + case VM_METHOD_TYPE_OPTIMIZED: + switch (cme->def->body.optimized.type) { + case OPTIMIZED_METHOD_TYPE_SEND: + GEN_COUNTER_INC(cb, send_optimized_method_send); + return YJIT_CANT_COMPILE; + case OPTIMIZED_METHOD_TYPE_CALL: + GEN_COUNTER_INC(cb, send_optimized_method_call); + return YJIT_CANT_COMPILE; + case OPTIMIZED_METHOD_TYPE_BLOCK_CALL: + GEN_COUNTER_INC(cb, send_optimized_method_block_call); + return YJIT_CANT_COMPILE; + case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: + return gen_struct_aref(jit, ctx, ci, cme, comptime_recv, comptime_recv_klass); + case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: + return gen_struct_aset(jit, ctx, ci, cme, comptime_recv, comptime_recv_klass); + default: + rb_bug("unknown optimized method type (%d)", cme->def->body.optimized.type); + UNREACHABLE_RETURN(YJIT_CANT_COMPILE); + } + case VM_METHOD_TYPE_MISSING: + GEN_COUNTER_INC(cb, send_missing_method); + return YJIT_CANT_COMPILE; + case VM_METHOD_TYPE_REFINED: + GEN_COUNTER_INC(cb, send_refined_method); + return YJIT_CANT_COMPILE; + // no default case so compiler issues a warning if this is not exhaustive + } + + // Unreachable + RUBY_ASSERT(false); + } +} + +static codegen_status_t +gen_opt_send_without_block(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 0); + return gen_send_general(jit, ctx, cd, NULL); +} + +static codegen_status_t +gen_send(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 0); + rb_iseq_t *block = (rb_iseq_t *)jit_get_arg(jit, 1); + return gen_send_general(jit, ctx, cd, block); +} + +static codegen_status_t +gen_invokesuper(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 0); + rb_iseq_t *block = (rb_iseq_t *)jit_get_arg(jit, 1); + + // Defer compilation so we can specialize on class of receiver + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(jit->ec->cfp); + if (!me) { + return YJIT_CANT_COMPILE; + } + + // FIXME: We should track and invalidate this block when this cme is invalidated + VALUE current_defined_class = me->defined_class; + ID mid = me->def->original_id; + + if (me != rb_callable_method_entry(current_defined_class, me->called_id)) { + // Though we likely could generate this call, as we are only concerned + // with the method entry remaining valid, assume_method_lookup_stable + // below requires that the method lookup matches as well + return YJIT_CANT_COMPILE; + } + + // vm_search_normal_superclass + if (BUILTIN_TYPE(current_defined_class) == T_ICLASS && FL_TEST_RAW(RBASIC(current_defined_class)->klass, RMODULE_IS_REFINEMENT)) { + return YJIT_CANT_COMPILE; + } + VALUE comptime_superclass = RCLASS_SUPER(RCLASS_ORIGIN(current_defined_class)); + + const struct rb_callinfo *ci = cd->ci; + int32_t argc = (int32_t)vm_ci_argc(ci); + + // Don't JIT calls that aren't simple + // Note, not using VM_CALL_ARGS_SIMPLE because sometimes we pass a block. + if ((vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) != 0) { + GEN_COUNTER_INC(cb, send_args_splat); + return YJIT_CANT_COMPILE; + } + if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { + GEN_COUNTER_INC(cb, send_keywords); + return YJIT_CANT_COMPILE; + } + if ((vm_ci_flag(ci) & VM_CALL_KW_SPLAT) != 0) { + GEN_COUNTER_INC(cb, send_kw_splat); + return YJIT_CANT_COMPILE; + } + if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) != 0) { + GEN_COUNTER_INC(cb, send_block_arg); + return YJIT_CANT_COMPILE; + } + + // Ensure we haven't rebound this method onto an incompatible class. + // In the interpreter we try to avoid making this check by performing some + // cheaper calculations first, but since we specialize on the method entry + // and so only have to do this once at compile time this is fine to always + // check and side exit. + VALUE comptime_recv = jit_peek_at_stack(jit, ctx, argc); + if (!rb_obj_is_kind_of(comptime_recv, current_defined_class)) { + return YJIT_CANT_COMPILE; + } + + // Do method lookup + const rb_callable_method_entry_t *cme = rb_callable_method_entry(comptime_superclass, mid); + + if (!cme) { + return YJIT_CANT_COMPILE; + } + + // Check that we'll be able to write this method dispatch before generating checks + switch (cme->def->type) { + case VM_METHOD_TYPE_ISEQ: + case VM_METHOD_TYPE_CFUNC: + break; + default: + // others unimplemented + return YJIT_CANT_COMPILE; + } + + // Guard that the receiver has the same class as the one from compile time + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + if (jit->ec->cfp->ep[VM_ENV_DATA_INDEX_ME_CREF] != (VALUE)me) { + // This will be the case for super within a block + return YJIT_CANT_COMPILE; + } + + ADD_COMMENT(cb, "guard known me"); + mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep)); + x86opnd_t ep_me_opnd = mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_ME_CREF); + jit_mov_gc_ptr(jit, cb, REG1, (VALUE)me); + cmp(cb, ep_me_opnd, REG1); + jne_ptr(cb, COUNTED_EXIT(jit, side_exit, invokesuper_me_changed)); + + if (!block) { + // Guard no block passed + // rb_vm_frame_block_handler(GET_EC()->cfp) == VM_BLOCK_HANDLER_NONE + // note, we assume VM_ASSERT(VM_ENV_LOCAL_P(ep)) + // + // TODO: this could properly forward the current block handler, but + // would require changes to gen_send_* + ADD_COMMENT(cb, "guard no block given"); + // EP is in REG0 from above + x86opnd_t ep_specval_opnd = mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL); + cmp(cb, ep_specval_opnd, imm_opnd(VM_BLOCK_HANDLER_NONE)); + jne_ptr(cb, COUNTED_EXIT(jit, side_exit, invokesuper_block)); + } + + // Points to the receiver operand on the stack + x86opnd_t recv = ctx_stack_opnd(ctx, argc); + mov(cb, REG0, recv); + + // We need to assume that both our current method entry and the super + // method entry we invoke remain stable + assume_method_lookup_stable(current_defined_class, me, jit); + assume_method_lookup_stable(comptime_superclass, cme, jit); + + // Method calls may corrupt types + ctx_clear_local_types(ctx); + + switch (cme->def->type) { + case VM_METHOD_TYPE_ISEQ: + return gen_send_iseq(jit, ctx, ci, cme, block, argc); + case VM_METHOD_TYPE_CFUNC: + return gen_send_cfunc(jit, ctx, ci, cme, block, argc, NULL); + default: + break; + } + + RUBY_ASSERT_ALWAYS(false); +} + +static codegen_status_t +gen_leave(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Only the return value should be on the stack + RUBY_ASSERT(ctx->stack_size == 1); + + // Create a side-exit to fall back to the interpreter + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Load environment pointer EP from CFP + mov(cb, REG1, member_opnd(REG_CFP, rb_control_frame_t, ep)); + + // Check for interrupts + ADD_COMMENT(cb, "check for interrupts"); + yjit_check_ints(cb, COUNTED_EXIT(jit, side_exit, leave_se_interrupt)); + + // Load the return value + mov(cb, REG0, ctx_stack_pop(ctx, 1)); + + // Pop the current frame (ec->cfp++) + // Note: the return PC is already in the previous CFP + add(cb, REG_CFP, imm_opnd(sizeof(rb_control_frame_t))); + mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP); + + // Reload REG_SP for the caller and write the return value. + // Top of the stack is REG_SP[0] since the caller has sp_offset=1. + mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp)); + mov(cb, mem_opnd(64, REG_SP, 0), REG0); + + // Jump to the JIT return address on the frame that was just popped + const int32_t offset_to_jit_return = -((int32_t)sizeof(rb_control_frame_t)) + (int32_t)offsetof(rb_control_frame_t, jit_return); + jmp_rm(cb, mem_opnd(64, REG_CFP, offset_to_jit_return)); + + return YJIT_END_BLOCK; +} + +RUBY_EXTERN rb_serial_t ruby_vm_global_constant_state; + +static codegen_status_t +gen_getglobal(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + ID gid = jit_get_arg(jit, 0); + + // Save the PC and SP because we might make a Ruby call for warning + jit_prepare_routine_call(jit, ctx, REG0); + + mov(cb, C_ARG_REGS[0], imm_opnd(gid)); + + call_ptr(cb, REG0, (void *)&rb_gvar_get); + + x86opnd_t top = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, top, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_setglobal(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + ID gid = jit_get_arg(jit, 0); + + // Save the PC and SP because we might make a Ruby call for + // Kernel#set_trace_var + jit_prepare_routine_call(jit, ctx, REG0); + + mov(cb, C_ARG_REGS[0], imm_opnd(gid)); + + x86opnd_t val = ctx_stack_pop(ctx, 1); + + mov(cb, C_ARG_REGS[1], val); + + call_ptr(cb, REG0, (void *)&rb_gvar_set); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_anytostring(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Save the PC and SP because we might make a Ruby call for + // Kernel#set_trace_var + jit_prepare_routine_call(jit, ctx, REG0); + + x86opnd_t str = ctx_stack_pop(ctx, 1); + x86opnd_t val = ctx_stack_pop(ctx, 1); + + mov(cb, C_ARG_REGS[0], str); + mov(cb, C_ARG_REGS[1], val); + + call_ptr(cb, REG0, (void *)&rb_obj_as_string_result); + + // Push the return value + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_STRING); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_objtostring(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + if (!jit_at_current_insn(jit)) { + defer_compilation(jit, ctx); + return YJIT_END_BLOCK; + } + + x86opnd_t recv = ctx_stack_opnd(ctx, 0); + VALUE comptime_recv = jit_peek_at_stack(jit, ctx, 0); + + if (RB_TYPE_P(comptime_recv, T_STRING)) { + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + mov(cb, REG0, recv); + jit_guard_known_klass(jit, ctx, CLASS_OF(comptime_recv), OPND_STACK(0), comptime_recv, SEND_MAX_DEPTH, side_exit); + // No work needed. The string value is already on the top of the stack. + return YJIT_KEEP_COMPILING; + } + else { + struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 0); + return gen_send_general(jit, ctx, cd, NULL); + } +} + +static codegen_status_t +gen_toregexp(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + rb_num_t opt = jit_get_arg(jit, 0); + rb_num_t cnt = jit_get_arg(jit, 1); + + // Save the PC and SP because this allocates an object and could + // raise an exception. + jit_prepare_routine_call(jit, ctx, REG0); + + x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)cnt)); + ctx_stack_pop(ctx, cnt); + + mov(cb, C_ARG_REGS[0], imm_opnd(0)); + mov(cb, C_ARG_REGS[1], imm_opnd(cnt)); + lea(cb, C_ARG_REGS[2], values_ptr); + call_ptr(cb, REG0, (void *)&rb_ary_tmp_new_from_values); + + // Save the array so we can clear it later + push(cb, RAX); + push(cb, RAX); // Alignment + mov(cb, C_ARG_REGS[0], RAX); + mov(cb, C_ARG_REGS[1], imm_opnd(opt)); + call_ptr(cb, REG0, (void *)&rb_reg_new_ary); + + // The actual regex is in RAX now. Pop the temp array from + // rb_ary_tmp_new_from_values into C arg regs so we can clear it + pop(cb, REG1); // Alignment + pop(cb, C_ARG_REGS[0]); + + // The value we want to push on the stack is in RAX right now + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + // Clear the temp array. + call_ptr(cb, REG0, (void *)&rb_ary_clear); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_intern(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // Save the PC and SP because we might allocate + jit_prepare_routine_call(jit, ctx, REG0); + + x86opnd_t str = ctx_stack_pop(ctx, 1); + + mov(cb, C_ARG_REGS[0], str); + + call_ptr(cb, REG0, (void *)&rb_str_intern); + + // Push the return value + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_getspecial(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // This takes two arguments, key and type + // key is only used when type == 0 + // A non-zero type determines which type of backref to fetch + //rb_num_t key = jit_get_arg(jit, 0); + rb_num_t type = jit_get_arg(jit, 1); + + if (type == 0) { + // not yet implemented + return YJIT_CANT_COMPILE; + } + else if (type & 0x01) { + // Fetch a "special" backref based on a char encoded by shifting by 1 + + // Can raise if matchdata uninitialized + jit_prepare_routine_call(jit, ctx, REG0); + + // call rb_backref_get() + ADD_COMMENT(cb, "rb_backref_get"); + call_ptr(cb, REG0, (void *)rb_backref_get); + mov(cb, C_ARG_REGS[0], RAX); + + switch (type >> 1) { + case '&': + ADD_COMMENT(cb, "rb_reg_last_match"); + call_ptr(cb, REG0, (void *)rb_reg_last_match); + break; + case '`': + ADD_COMMENT(cb, "rb_reg_match_pre"); + call_ptr(cb, REG0, (void *)rb_reg_match_pre); + break; + case '\'': + ADD_COMMENT(cb, "rb_reg_match_post"); + call_ptr(cb, REG0, (void *)rb_reg_match_post); + break; + case '+': + ADD_COMMENT(cb, "rb_reg_match_last"); + call_ptr(cb, REG0, (void *)rb_reg_match_last); + break; + default: + rb_bug("invalid back-ref"); + } + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; + } + else { + // Fetch the N-th match from the last backref based on type shifted by 1 + + // Can raise if matchdata uninitialized + jit_prepare_routine_call(jit, ctx, REG0); + + // call rb_backref_get() + ADD_COMMENT(cb, "rb_backref_get"); + call_ptr(cb, REG0, (void *)rb_backref_get); + + // rb_reg_nth_match((int)(type >> 1), backref); + ADD_COMMENT(cb, "rb_reg_nth_match"); + mov(cb, C_ARG_REGS[0], imm_opnd(type >> 1)); + mov(cb, C_ARG_REGS[1], RAX); + call_ptr(cb, REG0, (void *)rb_reg_nth_match); + + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; + } +} + +VALUE +rb_vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, ICVARC ic); + +static codegen_status_t +gen_getclassvariable(jitstate_t* jit, ctx_t* ctx, codeblock_t* cb) +{ + // rb_vm_getclassvariable can raise exceptions. + jit_prepare_routine_call(jit, ctx, REG0); + + mov(cb, C_ARG_REGS[0], member_opnd(REG_CFP, rb_control_frame_t, iseq)); + mov(cb, C_ARG_REGS[1], REG_CFP); + mov(cb, C_ARG_REGS[2], imm_opnd(jit_get_arg(jit, 0))); + mov(cb, C_ARG_REGS[3], imm_opnd(jit_get_arg(jit, 1))); + + call_ptr(cb, REG0, (void *)rb_vm_getclassvariable); + + x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_top, RAX); + + return YJIT_KEEP_COMPILING; +} + +VALUE +rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic); + +static codegen_status_t +gen_setclassvariable(jitstate_t* jit, ctx_t* ctx, codeblock_t* cb) +{ + // rb_vm_setclassvariable can raise exceptions. + jit_prepare_routine_call(jit, ctx, REG0); + + mov(cb, C_ARG_REGS[0], member_opnd(REG_CFP, rb_control_frame_t, iseq)); + mov(cb, C_ARG_REGS[1], REG_CFP); + mov(cb, C_ARG_REGS[2], imm_opnd(jit_get_arg(jit, 0))); + mov(cb, C_ARG_REGS[3], ctx_stack_pop(ctx, 1)); + mov(cb, C_ARG_REGS[4], imm_opnd(jit_get_arg(jit, 1))); + + call_ptr(cb, REG0, (void *)rb_vm_setclassvariable); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + VALUE jump_offset = jit_get_arg(jit, 0); + VALUE const_cache_as_value = jit_get_arg(jit, 1); + IC ic = (IC)const_cache_as_value; + + // See vm_ic_hit_p(). The same conditions are checked in yjit_constant_ic_update(). + struct iseq_inline_constant_cache_entry *ice = ic->entry; + if (!ice || // cache not filled + GET_IC_SERIAL(ice) != ruby_vm_global_constant_state /* cache out of date */) { + // In these cases, leave a block that unconditionally side exits + // for the interpreter to invalidate. + return YJIT_CANT_COMPILE; + } + + // Make sure there is an exit for this block as the interpreter might want + // to invalidate this block from yjit_constant_ic_update(). + jit_ensure_block_entry_exit(jit); + + if (ice->ic_cref) { + // Cache is keyed on a certain lexical scope. Use the interpreter's cache. + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // Call function to verify the cache. It doesn't allocate or call methods. + bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep); + mov(cb, C_ARG_REGS[0], const_ptr_opnd((void *)ic)); + mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, ep)); + call_ptr(cb, REG0, (void *)rb_vm_ic_hit_p); + + // Check the result. _Bool is one byte in SysV. + test(cb, AL, AL); + jz_ptr(cb, COUNTED_EXIT(jit, side_exit, opt_getinlinecache_miss)); + + // Push ic->entry->value + mov(cb, REG0, const_ptr_opnd((void *)ic)); + mov(cb, REG0, member_opnd(REG0, struct iseq_inline_constant_cache, entry)); + x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, REG0, member_opnd(REG0, struct iseq_inline_constant_cache_entry, value)); + mov(cb, stack_top, REG0); + } + else { + // Optimize for single ractor mode. + // FIXME: This leaks when st_insert raises NoMemoryError + if (!assume_single_ractor_mode(jit)) return YJIT_CANT_COMPILE; + + // Invalidate output code on any and all constant writes + // FIXME: This leaks when st_insert raises NoMemoryError + assume_stable_global_constant_state(jit); + + jit_putobject(jit, ctx, ice->value); + } + + // Jump over the code for filling the cache + uint32_t jump_idx = jit_next_insn_idx(jit) + (int32_t)jump_offset; + gen_direct_jump( + jit, + ctx, + (blockid_t){ .iseq = jit->iseq, .idx = jump_idx } + ); + + return YJIT_END_BLOCK; +} + +// Push the explicit block parameter onto the temporary stack. Part of the +// interpreter's scheme for avoiding Proc allocations when delegating +// explicit block parameters. +static codegen_status_t +gen_getblockparamproxy(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + // A mirror of the interpreter code. Checking for the case + // where it's pushing rb_block_param_proxy. + uint8_t *side_exit = yjit_side_exit(jit, ctx); + + // EP level + uint32_t level = (uint32_t)jit_get_arg(jit, 1); + + // Load environment pointer EP from CFP + gen_get_ep(cb, REG0, level); + + // Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero + test(cb, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_FLAGS), imm_opnd(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)); + jnz_ptr(cb, COUNTED_EXIT(jit, side_exit, gbpp_block_param_modified)); + + // Load the block handler for the current frame + // note, VM_ASSERT(VM_ENV_LOCAL_P(ep)) + mov(cb, REG0, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL)); + + // Block handler is a tagged pointer. Look at the tag. 0x03 is from VM_BH_ISEQ_BLOCK_P(). + and(cb, REG0_8, imm_opnd(0x3)); + + // Bail unless VM_BH_ISEQ_BLOCK_P(bh). This also checks for null. + cmp(cb, REG0_8, imm_opnd(0x1)); + jnz_ptr(cb, COUNTED_EXIT(jit, side_exit, gbpp_block_handler_not_iseq)); + + // Push rb_block_param_proxy. It's a root, so no need to use jit_mov_gc_ptr. + mov(cb, REG0, const_ptr_opnd((void *)rb_block_param_proxy)); + RUBY_ASSERT(!SPECIAL_CONST_P(rb_block_param_proxy)); + x86opnd_t top = ctx_stack_push(ctx, TYPE_HEAP); + mov(cb, top, REG0); + + return YJIT_KEEP_COMPILING; +} + +static codegen_status_t +gen_invokebuiltin(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0); + + // ec, self, and arguments + if (bf->argc + 2 > NUM_C_ARG_REGS) { + return YJIT_CANT_COMPILE; + } + + // If the calls don't allocate, do they need up to date PC, SP? + jit_prepare_routine_call(jit, ctx, REG0); + + // Call the builtin func (ec, recv, arg1, arg2, ...) + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, self)); + + // Copy arguments from locals + for (int32_t i = 0; i < bf->argc; i++) { + x86opnd_t stack_opnd = ctx_stack_opnd(ctx, bf->argc - i - 1); + x86opnd_t c_arg_reg = C_ARG_REGS[2 + i]; + mov(cb, c_arg_reg, stack_opnd); + } + + call_ptr(cb, REG0, (void *)bf->func_ptr); + + // Push the return value + ctx_stack_pop(ctx, bf->argc); + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +// opt_invokebuiltin_delegate calls a builtin function, like +// invokebuiltin does, but instead of taking arguments from the top of the +// stack uses the argument locals (and self) from the current method. +static codegen_status_t +gen_opt_invokebuiltin_delegate(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) +{ + const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0); + int32_t start_index = (int32_t)jit_get_arg(jit, 1); + + // ec, self, and arguments + if (bf->argc + 2 > NUM_C_ARG_REGS) { + return YJIT_CANT_COMPILE; + } + + // If the calls don't allocate, do they need up to date PC, SP? + jit_prepare_routine_call(jit, ctx, REG0); + + if (bf->argc > 0) { + // Load environment pointer EP from CFP + mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep)); + } + + // Call the builtin func (ec, recv, arg1, arg2, ...) + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, self)); + + // Copy arguments from locals + for (int32_t i = 0; i < bf->argc; i++) { + const int32_t offs = -jit->iseq->body->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index + i; + x86opnd_t local_opnd = mem_opnd(64, REG0, offs * SIZEOF_VALUE); + x86opnd_t c_arg_reg = C_ARG_REGS[i + 2]; + mov(cb, c_arg_reg, local_opnd); + } + call_ptr(cb, REG0, (void *)bf->func_ptr); + + // Push the return value + x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + +static int tracing_invalidate_all_i(void *vstart, void *vend, size_t stride, void *data); +static void invalidate_all_blocks_for_tracing(const rb_iseq_t *iseq); + +// Invalidate all generated code and patch C method return code to contain +// logic for firing the c_return TracePoint event. Once rb_vm_barrier() +// returns, all other ractors are pausing inside RB_VM_LOCK_ENTER(), which +// means they are inside a C routine. If there are any generated code on-stack, +// they are waiting for a return from a C routine. For every routine call, we +// patch in an exit after the body of the containing VM instruction. This makes +// it so all the invalidated code exit as soon as execution logically reaches +// the next VM instruction. The interpreter takes care of firing the tracing +// event if it so happens that the next VM instruction has one attached. +// +// The c_return event needs special handling as our codegen never outputs code +// that contains tracing logic. If we let the normal output code run until the +// start of the next VM instruction by relying on the patching scheme above, we +// would fail to fire the c_return event. The interpreter doesn't fire the +// event at an instruction boundary, so simply exiting to the interpreter isn't +// enough. To handle it, we patch in the full logic at the return address. See +// full_cfunc_return(). +// +// In addition to patching, we prevent future entries into invalidated code by +// removing all live blocks from their iseq. +void +rb_yjit_tracing_invalidate_all(void) +{ + if (!rb_yjit_enabled_p()) return; + + // Stop other ractors since we are going to patch machine code. + RB_VM_LOCK_ENTER(); + rb_vm_barrier(); + + // Make it so all live block versions are no longer valid branch targets + rb_objspace_each_objects(tracing_invalidate_all_i, NULL); + + // Apply patches + const uint32_t old_pos = cb->write_pos; + rb_darray_for(global_inval_patches, patch_idx) { + struct codepage_patch patch = rb_darray_get(global_inval_patches, patch_idx); + cb_set_pos(cb, patch.inline_patch_pos); + uint8_t *jump_target = cb_get_ptr(ocb, patch.outlined_target_pos); + jmp_ptr(cb, jump_target); + } + cb_set_pos(cb, old_pos); + + // Freeze invalidated part of the codepage. We only want to wait for + // running instances of the code to exit from now on, so we shouldn't + // change the code. There could be other ractors sleeping in + // branch_stub_hit(), for example. We could harden this by changing memory + // protection on the frozen range. + RUBY_ASSERT_ALWAYS(yjit_codepage_frozen_bytes <= old_pos && "frozen bytes should increase monotonically"); + yjit_codepage_frozen_bytes = old_pos; + + cb_mark_all_executable(ocb); + cb_mark_all_executable(cb); + RB_VM_LOCK_LEAVE(); +} + +static int +tracing_invalidate_all_i(void *vstart, void *vend, size_t stride, void *data) +{ + VALUE v = (VALUE)vstart; + for (; v != (VALUE)vend; v += stride) { + void *ptr = asan_poisoned_object_p(v); + asan_unpoison_object(v, false); + + if (rb_obj_is_iseq(v)) { + rb_iseq_t *iseq = (rb_iseq_t *)v; + invalidate_all_blocks_for_tracing(iseq); + } + + asan_poison_object_if(ptr, v); + } + return 0; +} + +static void +invalidate_all_blocks_for_tracing(const rb_iseq_t *iseq) +{ + struct rb_iseq_constant_body *body = iseq->body; + if (!body) return; // iseq yet to be initialized + + ASSERT_vm_locking(); + + // Empty all blocks on the iseq so we don't compile new blocks that jump to the + // invalidted region. + // TODO Leaking the blocks for now since we might have situations where + // a different ractor is waiting in branch_stub_hit(). If we free the block + // that ractor can wake up with a dangling block. + rb_darray_for(body->yjit_blocks, version_array_idx) { + rb_yjit_block_array_t version_array = rb_darray_get(body->yjit_blocks, version_array_idx); + rb_darray_for(version_array, version_idx) { + // Stop listening for invalidation events like basic operation redefinition. + block_t *block = rb_darray_get(version_array, version_idx); + yjit_unlink_method_lookup_dependency(block); + yjit_block_assumptions_free(block); + } + rb_darray_free(version_array); + } + rb_darray_free(body->yjit_blocks); + body->yjit_blocks = NULL; + +#if USE_MJIT + // Reset output code entry point + body->jit_func = NULL; +#endif +} + +static void +yjit_reg_op(int opcode, codegen_fn gen_fn) +{ + RUBY_ASSERT(opcode >= 0 && opcode < VM_INSTRUCTION_SIZE); + // Check that the op wasn't previously registered + RUBY_ASSERT(gen_fns[opcode] == NULL); + + gen_fns[opcode] = gen_fn; +} + +void +yjit_init_codegen(void) +{ + // Initialize the code blocks + uint32_t mem_size = rb_yjit_opts.exec_mem_size * 1024 * 1024; + uint8_t *mem_block = alloc_exec_mem(mem_size); + + cb = █ + cb_init(cb, mem_block, mem_size/2); + + ocb = &outline_block; + cb_init(ocb, mem_block + mem_size/2, mem_size/2); + + // Generate the interpreter exit code for leave + leave_exit_code = yjit_gen_leave_exit(cb); + + // Generate full exit code for C func + gen_full_cfunc_return(); + cb_mark_all_executable(cb); + + // Map YARV opcodes to the corresponding codegen functions + yjit_reg_op(BIN(nop), gen_nop); + yjit_reg_op(BIN(dup), gen_dup); + yjit_reg_op(BIN(dupn), gen_dupn); + yjit_reg_op(BIN(swap), gen_swap); + yjit_reg_op(BIN(setn), gen_setn); + yjit_reg_op(BIN(topn), gen_topn); + yjit_reg_op(BIN(pop), gen_pop); + yjit_reg_op(BIN(adjuststack), gen_adjuststack); + yjit_reg_op(BIN(newarray), gen_newarray); + yjit_reg_op(BIN(duparray), gen_duparray); + yjit_reg_op(BIN(duphash), gen_duphash); + yjit_reg_op(BIN(splatarray), gen_splatarray); + yjit_reg_op(BIN(expandarray), gen_expandarray); + yjit_reg_op(BIN(newhash), gen_newhash); + yjit_reg_op(BIN(newrange), gen_newrange); + yjit_reg_op(BIN(concatstrings), gen_concatstrings); + yjit_reg_op(BIN(putnil), gen_putnil); + yjit_reg_op(BIN(putobject), gen_putobject); + yjit_reg_op(BIN(putstring), gen_putstring); + yjit_reg_op(BIN(putobject_INT2FIX_0_), gen_putobject_int2fix); + yjit_reg_op(BIN(putobject_INT2FIX_1_), gen_putobject_int2fix); + yjit_reg_op(BIN(putself), gen_putself); + yjit_reg_op(BIN(putspecialobject), gen_putspecialobject); + yjit_reg_op(BIN(getlocal), gen_getlocal); + yjit_reg_op(BIN(getlocal_WC_0), gen_getlocal_wc0); + yjit_reg_op(BIN(getlocal_WC_1), gen_getlocal_wc1); + yjit_reg_op(BIN(setlocal), gen_setlocal); + yjit_reg_op(BIN(setlocal_WC_0), gen_setlocal_wc0); + yjit_reg_op(BIN(setlocal_WC_1), gen_setlocal_wc1); + yjit_reg_op(BIN(getinstancevariable), gen_getinstancevariable); + yjit_reg_op(BIN(setinstancevariable), gen_setinstancevariable); + yjit_reg_op(BIN(defined), gen_defined); + yjit_reg_op(BIN(checktype), gen_checktype); + yjit_reg_op(BIN(checkkeyword), gen_checkkeyword); + yjit_reg_op(BIN(opt_lt), gen_opt_lt); + yjit_reg_op(BIN(opt_le), gen_opt_le); + yjit_reg_op(BIN(opt_ge), gen_opt_ge); + yjit_reg_op(BIN(opt_gt), gen_opt_gt); + yjit_reg_op(BIN(opt_eq), gen_opt_eq); + yjit_reg_op(BIN(opt_neq), gen_opt_neq); + yjit_reg_op(BIN(opt_aref), gen_opt_aref); + yjit_reg_op(BIN(opt_aset), gen_opt_aset); + yjit_reg_op(BIN(opt_and), gen_opt_and); + yjit_reg_op(BIN(opt_or), gen_opt_or); + yjit_reg_op(BIN(opt_minus), gen_opt_minus); + yjit_reg_op(BIN(opt_plus), gen_opt_plus); + yjit_reg_op(BIN(opt_mult), gen_opt_mult); + yjit_reg_op(BIN(opt_div), gen_opt_div); + yjit_reg_op(BIN(opt_mod), gen_opt_mod); + yjit_reg_op(BIN(opt_ltlt), gen_opt_ltlt); + yjit_reg_op(BIN(opt_nil_p), gen_opt_nil_p); + yjit_reg_op(BIN(opt_empty_p), gen_opt_empty_p); + yjit_reg_op(BIN(opt_str_freeze), gen_opt_str_freeze); + yjit_reg_op(BIN(opt_str_uminus), gen_opt_str_uminus); + yjit_reg_op(BIN(opt_not), gen_opt_not); + yjit_reg_op(BIN(opt_size), gen_opt_size); + yjit_reg_op(BIN(opt_length), gen_opt_length); + yjit_reg_op(BIN(opt_regexpmatch2), gen_opt_regexpmatch2); + yjit_reg_op(BIN(opt_getinlinecache), gen_opt_getinlinecache); + yjit_reg_op(BIN(invokebuiltin), gen_invokebuiltin); + yjit_reg_op(BIN(opt_invokebuiltin_delegate), gen_opt_invokebuiltin_delegate); + yjit_reg_op(BIN(opt_invokebuiltin_delegate_leave), gen_opt_invokebuiltin_delegate); + yjit_reg_op(BIN(opt_case_dispatch), gen_opt_case_dispatch); + yjit_reg_op(BIN(branchif), gen_branchif); + yjit_reg_op(BIN(branchunless), gen_branchunless); + yjit_reg_op(BIN(branchnil), gen_branchnil); + yjit_reg_op(BIN(jump), gen_jump); + yjit_reg_op(BIN(getblockparamproxy), gen_getblockparamproxy); + yjit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block); + yjit_reg_op(BIN(send), gen_send); + yjit_reg_op(BIN(invokesuper), gen_invokesuper); + yjit_reg_op(BIN(leave), gen_leave); + yjit_reg_op(BIN(getglobal), gen_getglobal); + yjit_reg_op(BIN(setglobal), gen_setglobal); + yjit_reg_op(BIN(anytostring), gen_anytostring); + yjit_reg_op(BIN(objtostring), gen_objtostring); + yjit_reg_op(BIN(toregexp), gen_toregexp); + yjit_reg_op(BIN(intern), gen_intern); + yjit_reg_op(BIN(getspecial), gen_getspecial); + yjit_reg_op(BIN(getclassvariable), gen_getclassvariable); + yjit_reg_op(BIN(setclassvariable), gen_setclassvariable); + + yjit_method_codegen_table = st_init_numtable(); + + // Specialization for C methods. See yjit_reg_method() for details. + yjit_reg_method(rb_cBasicObject, "!", jit_rb_obj_not); + + yjit_reg_method(rb_cNilClass, "nil?", jit_rb_true); + yjit_reg_method(rb_mKernel, "nil?", jit_rb_false); + + yjit_reg_method(rb_cBasicObject, "==", jit_rb_obj_equal); + yjit_reg_method(rb_cBasicObject, "equal?", jit_rb_obj_equal); + yjit_reg_method(rb_mKernel, "eql?", jit_rb_obj_equal); + yjit_reg_method(rb_cModule, "==", jit_rb_obj_equal); + yjit_reg_method(rb_cSymbol, "==", jit_rb_obj_equal); + yjit_reg_method(rb_cSymbol, "===", jit_rb_obj_equal); + + // rb_str_to_s() methods in string.c + yjit_reg_method(rb_cString, "to_s", jit_rb_str_to_s); + yjit_reg_method(rb_cString, "to_str", jit_rb_str_to_s); + yjit_reg_method(rb_cString, "bytesize", jit_rb_str_bytesize); + + // Thread.current + yjit_reg_method(rb_singleton_class(rb_cThread), "current", jit_thread_s_current); +} diff --git a/ruby/yjit_codegen.h b/ruby/yjit_codegen.h new file mode 100644 index 000000000..e3b971af3 --- /dev/null +++ b/ruby/yjit_codegen.h @@ -0,0 +1,23 @@ +#ifndef YJIT_CODEGEN_H +#define YJIT_CODEGEN_H 1 + +typedef enum codegen_status { + YJIT_END_BLOCK, + YJIT_KEEP_COMPILING, + YJIT_CANT_COMPILE +} codegen_status_t; + +// Code generation function signature +typedef codegen_status_t (*codegen_fn)(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb); + +static void jit_ensure_block_entry_exit(jitstate_t *jit); + +static uint8_t *yjit_entry_prologue(codeblock_t *cb, const rb_iseq_t *iseq); + +static block_t *gen_single_block(blockid_t blockid, const ctx_t *start_ctx, rb_execution_context_t *ec); + +static void gen_code_for_exit_from_stub(void); + +static void yjit_init_codegen(void); + +#endif // #ifndef YJIT_CODEGEN_H diff --git a/ruby/yjit_core.c b/ruby/yjit_core.c new file mode 100644 index 000000000..a3b52971f --- /dev/null +++ b/ruby/yjit_core.c @@ -0,0 +1,1369 @@ +// This file is a fragment of the yjit.o compilation unit. See yjit.c. +#include "internal.h" +#include "vm_sync.h" +#include "builtin.h" + +#include "yjit.h" +#include "yjit_asm.h" +#include "yjit_iface.h" +#include "yjit_core.h" +#include "yjit_codegen.h" + +// For exiting from YJIT frame from branch_stub_hit(). +// Filled by gen_code_for_exit_from_stub(). +static uint8_t *code_for_exit_from_stub = NULL; + +/* +Get an operand for the adjusted stack pointer address +*/ +static x86opnd_t +ctx_sp_opnd(ctx_t *ctx, int32_t offset_bytes) +{ + int32_t offset = (ctx->sp_offset * sizeof(VALUE)) + offset_bytes; + return mem_opnd(64, REG_SP, offset); +} + +/* +Push one new value on the temp stack with an explicit mapping +Return a pointer to the new stack top +*/ +static x86opnd_t +ctx_stack_push_mapping(ctx_t *ctx, temp_type_mapping_t mapping) +{ + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) { + mapping.type = TYPE_UNKNOWN; + } + + // Keep track of the type and mapping of the value + if (ctx->stack_size < MAX_TEMP_TYPES) { + ctx->temp_mapping[ctx->stack_size] = mapping.mapping; + ctx->temp_types[ctx->stack_size] = mapping.type; + + RUBY_ASSERT(mapping.mapping.kind != TEMP_LOCAL || mapping.mapping.idx < MAX_LOCAL_TYPES); + RUBY_ASSERT(mapping.mapping.kind != TEMP_STACK || mapping.mapping.idx == 0); + RUBY_ASSERT(mapping.mapping.kind != TEMP_SELF || mapping.mapping.idx == 0); + } + + ctx->stack_size += 1; + ctx->sp_offset += 1; + + // SP points just above the topmost value + int32_t offset = (ctx->sp_offset - 1) * sizeof(VALUE); + return mem_opnd(64, REG_SP, offset); +} + + +/* +Push one new value on the temp stack +Return a pointer to the new stack top +*/ +static x86opnd_t +ctx_stack_push(ctx_t *ctx, val_type_t type) +{ + temp_type_mapping_t mapping = { MAP_STACK, type }; + return ctx_stack_push_mapping(ctx, mapping); +} + +/* +Push the self value on the stack +*/ +static x86opnd_t +ctx_stack_push_self(ctx_t *ctx) +{ + temp_type_mapping_t mapping = { MAP_SELF, TYPE_UNKNOWN }; + return ctx_stack_push_mapping(ctx, mapping); +} + +/* +Push a local variable on the stack +*/ +static x86opnd_t +ctx_stack_push_local(ctx_t *ctx, size_t local_idx) +{ + if (local_idx >= MAX_LOCAL_TYPES) { + return ctx_stack_push(ctx, TYPE_UNKNOWN); + } + + temp_type_mapping_t mapping = { + (temp_mapping_t){ .kind = TEMP_LOCAL, .idx = local_idx }, + TYPE_UNKNOWN + }; + + return ctx_stack_push_mapping(ctx, mapping); +} + +/* +Pop N values off the stack +Return a pointer to the stack top before the pop operation +*/ +static x86opnd_t +ctx_stack_pop(ctx_t *ctx, size_t n) +{ + RUBY_ASSERT(n <= ctx->stack_size); + + // SP points just above the topmost value + int32_t offset = (ctx->sp_offset - 1) * sizeof(VALUE); + x86opnd_t top = mem_opnd(64, REG_SP, offset); + + // Clear the types of the popped values + for (size_t i = 0; i < n; ++i) + { + size_t idx = ctx->stack_size - i - 1; + if (idx < MAX_TEMP_TYPES) { + ctx->temp_types[idx] = TYPE_UNKNOWN; + ctx->temp_mapping[idx] = MAP_STACK; + } + } + + ctx->stack_size -= n; + ctx->sp_offset -= n; + + return top; +} + +/** +Get an operand pointing to a slot on the temp stack +*/ +static x86opnd_t +ctx_stack_opnd(ctx_t *ctx, int32_t idx) +{ + // SP points just above the topmost value + int32_t offset = (ctx->sp_offset - 1 - idx) * sizeof(VALUE); + x86opnd_t opnd = mem_opnd(64, REG_SP, offset); + + return opnd; +} + +/** +Get the type of an instruction operand +*/ +static val_type_t +ctx_get_opnd_type(const ctx_t *ctx, insn_opnd_t opnd) +{ + if (opnd.is_self) + return ctx->self_type; + + RUBY_ASSERT(opnd.idx < ctx->stack_size); + int stack_idx = ctx->stack_size - 1 - opnd.idx; + + // If outside of tracked range, do nothing + if (stack_idx >= MAX_TEMP_TYPES) + return TYPE_UNKNOWN; + + temp_mapping_t mapping = ctx->temp_mapping[stack_idx]; + + switch (mapping.kind) { + case TEMP_SELF: + return ctx->self_type; + + case TEMP_STACK: + return ctx->temp_types[ctx->stack_size - 1 - opnd.idx]; + + case TEMP_LOCAL: + RUBY_ASSERT(mapping.idx < MAX_LOCAL_TYPES); + return ctx->local_types[mapping.idx]; + } + + rb_bug("unreachable"); +} + +static int type_diff(val_type_t src, val_type_t dst); + +#define UPGRADE_TYPE(dest, src) do { \ + RUBY_ASSERT(type_diff((src), (dest)) != INT_MAX); \ + (dest) = (src); \ +} while (false) + +/** +Upgrade (or "learn") the type of an instruction operand +This value must be compatible and at least as specific as the previously known type. +If this value originated from self, or an lvar, the learned type will be +propagated back to its source. +*/ +static void +ctx_upgrade_opnd_type(ctx_t *ctx, insn_opnd_t opnd, val_type_t type) +{ + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + + if (opnd.is_self) { + UPGRADE_TYPE(ctx->self_type, type); + return; + } + + RUBY_ASSERT(opnd.idx < ctx->stack_size); + int stack_idx = ctx->stack_size - 1 - opnd.idx; + + // If outside of tracked range, do nothing + if (stack_idx >= MAX_TEMP_TYPES) + return; + + temp_mapping_t mapping = ctx->temp_mapping[stack_idx]; + + switch (mapping.kind) { + case TEMP_SELF: + UPGRADE_TYPE(ctx->self_type, type); + break; + + case TEMP_STACK: + UPGRADE_TYPE(ctx->temp_types[stack_idx], type); + break; + + case TEMP_LOCAL: + RUBY_ASSERT(mapping.idx < MAX_LOCAL_TYPES); + UPGRADE_TYPE(ctx->local_types[mapping.idx], type); + break; + } +} + +/* +Get both the type and mapping (where the value originates) of an operand. +This is can be used with ctx_stack_push_mapping or ctx_set_opnd_mapping to copy +a stack value's type while maintaining the mapping. +*/ +static temp_type_mapping_t +ctx_get_opnd_mapping(const ctx_t *ctx, insn_opnd_t opnd) +{ + temp_type_mapping_t type_mapping; + type_mapping.type = ctx_get_opnd_type(ctx, opnd); + + if (opnd.is_self) { + type_mapping.mapping = MAP_SELF; + return type_mapping; + } + + RUBY_ASSERT(opnd.idx < ctx->stack_size); + int stack_idx = ctx->stack_size - 1 - opnd.idx; + + if (stack_idx < MAX_TEMP_TYPES) { + type_mapping.mapping = ctx->temp_mapping[stack_idx]; + } + else { + // We can't know the source of this stack operand, so we assume it is + // a stack-only temporary. type will be UNKNOWN + RUBY_ASSERT(type_mapping.type.type == ETYPE_UNKNOWN); + type_mapping.mapping = MAP_STACK; + } + + return type_mapping; +} + +/* +Overwrite both the type and mapping of a stack operand. +*/ +static void +ctx_set_opnd_mapping(ctx_t *ctx, insn_opnd_t opnd, temp_type_mapping_t type_mapping) +{ + // self is always MAP_SELF + RUBY_ASSERT(!opnd.is_self); + + RUBY_ASSERT(opnd.idx < ctx->stack_size); + int stack_idx = ctx->stack_size - 1 - opnd.idx; + + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + + // If outside of tracked range, do nothing + if (stack_idx >= MAX_TEMP_TYPES) + return; + + ctx->temp_mapping[stack_idx] = type_mapping.mapping; + + // Only used when mapping == MAP_STACK + ctx->temp_types[stack_idx] = type_mapping.type; +} + +/** +Set the type of a local variable +*/ +static void +ctx_set_local_type(ctx_t *ctx, size_t idx, val_type_t type) +{ + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + + if (idx >= MAX_LOCAL_TYPES) + return; + + // If any values on the stack map to this local we must detach them + for (int i = 0; i < MAX_TEMP_TYPES; i++) { + temp_mapping_t *mapping = &ctx->temp_mapping[i]; + if (mapping->kind == TEMP_LOCAL && mapping->idx == idx) { + ctx->temp_types[i] = ctx->local_types[mapping->idx]; + *mapping = MAP_STACK; + } + } + + ctx->local_types[idx] = type; +} + +// Erase local variable type information +// eg: because of a call we can't track +static void +ctx_clear_local_types(ctx_t *ctx) +{ + // When clearing local types we must detach any stack mappings to those + // locals. Even if local values may have changed, stack values will not. + for (int i = 0; i < MAX_TEMP_TYPES; i++) { + temp_mapping_t *mapping = &ctx->temp_mapping[i]; + if (mapping->kind == TEMP_LOCAL) { + RUBY_ASSERT(mapping->idx < MAX_LOCAL_TYPES); + ctx->temp_types[i] = ctx->local_types[mapping->idx]; + *mapping = MAP_STACK; + } + RUBY_ASSERT(mapping->kind == TEMP_STACK || mapping->kind == TEMP_SELF); + } + memset(&ctx->local_types, 0, sizeof(ctx->local_types)); +} + + +/* This returns an appropriate val_type_t based on a known value */ +static val_type_t +yjit_type_of_value(VALUE val) +{ + if (SPECIAL_CONST_P(val)) { + if (FIXNUM_P(val)) { + return TYPE_FIXNUM; + } + else if (NIL_P(val)) { + return TYPE_NIL; + } + else if (val == Qtrue) { + return TYPE_TRUE; + } + else if (val == Qfalse) { + return TYPE_FALSE; + } + else if (STATIC_SYM_P(val)) { + return TYPE_STATIC_SYMBOL; + } + else if (FLONUM_P(val)) { + return TYPE_FLONUM; + } + else { + RUBY_ASSERT(false); + UNREACHABLE_RETURN(TYPE_IMM); + } + } + else { + switch (BUILTIN_TYPE(val)) { + case T_ARRAY: + return TYPE_ARRAY; + case T_HASH: + return TYPE_HASH; + case T_STRING: + return TYPE_STRING; + default: + // generic heap object + return TYPE_HEAP; + } + } +} + +/* The name of a type, for debugging */ +RBIMPL_ATTR_MAYBE_UNUSED() +static const char * +yjit_type_name(val_type_t type) +{ + RUBY_ASSERT(!(type.is_imm && type.is_heap)); + + switch (type.type) { + case ETYPE_UNKNOWN: + if (type.is_imm) { + return "unknown immediate"; + } + else if (type.is_heap) { + return "unknown heap"; + } + else { + return "unknown"; + } + case ETYPE_NIL: + return "nil"; + case ETYPE_TRUE: + return "true"; + case ETYPE_FALSE: + return "false"; + case ETYPE_FIXNUM: + return "fixnum"; + case ETYPE_FLONUM: + return "flonum"; + case ETYPE_ARRAY: + return "array"; + case ETYPE_HASH: + return "hash"; + case ETYPE_SYMBOL: + return "symbol"; + case ETYPE_STRING: + return "string"; + } + + UNREACHABLE_RETURN(""); +} + +/* +Compute a difference between two value types +Returns 0 if the two are the same +Returns > 0 if different but compatible +Returns INT_MAX if incompatible +*/ +static int +type_diff(val_type_t src, val_type_t dst) +{ + RUBY_ASSERT(!src.is_heap || !src.is_imm); + RUBY_ASSERT(!dst.is_heap || !dst.is_imm); + + // If dst assumes heap but src doesn't + if (dst.is_heap && !src.is_heap) + return INT_MAX; + + // If dst assumes imm but src doesn't + if (dst.is_imm && !src.is_imm) + return INT_MAX; + + // If dst assumes known type different from src + if (dst.type != ETYPE_UNKNOWN && dst.type != src.type) + return INT_MAX; + + if (dst.is_heap != src.is_heap) + return 1; + + if (dst.is_imm != src.is_imm) + return 1; + + if (dst.type != src.type) + return 1; + + return 0; +} + +/** +Compute a difference score for two context objects +Returns 0 if the two contexts are the same +Returns > 0 if different but compatible +Returns INT_MAX if incompatible +*/ +static int +ctx_diff(const ctx_t *src, const ctx_t *dst) +{ + // Can only lookup the first version in the chain + if (dst->chain_depth != 0) + return INT_MAX; + + // Blocks with depth > 0 always produce new versions + // Sidechains cannot overlap + if (src->chain_depth != 0) + return INT_MAX; + + if (dst->stack_size != src->stack_size) + return INT_MAX; + + if (dst->sp_offset != src->sp_offset) + return INT_MAX; + + // Difference sum + int diff = 0; + + // Check the type of self + int self_diff = type_diff(src->self_type, dst->self_type); + + if (self_diff == INT_MAX) + return INT_MAX; + + diff += self_diff; + + // For each local type we track + for (size_t i = 0; i < MAX_LOCAL_TYPES; ++i) + { + val_type_t t_src = src->local_types[i]; + val_type_t t_dst = dst->local_types[i]; + int temp_diff = type_diff(t_src, t_dst); + + if (temp_diff == INT_MAX) + return INT_MAX; + + diff += temp_diff; + } + + // For each value on the temp stack + for (size_t i = 0; i < src->stack_size; ++i) + { + temp_type_mapping_t m_src = ctx_get_opnd_mapping(src, OPND_STACK(i)); + temp_type_mapping_t m_dst = ctx_get_opnd_mapping(dst, OPND_STACK(i)); + + if (m_dst.mapping.kind != m_src.mapping.kind) { + if (m_dst.mapping.kind == TEMP_STACK) { + // We can safely drop information about the source of the temp + // stack operand. + diff += 1; + } + else { + return INT_MAX; + } + } + else if (m_dst.mapping.idx != m_src.mapping.idx) { + return INT_MAX; + } + + int temp_diff = type_diff(m_src.type, m_dst.type); + + if (temp_diff == INT_MAX) + return INT_MAX; + + diff += temp_diff; + } + + return diff; +} + +// Get all blocks for a particular place in an iseq. +static rb_yjit_block_array_t +yjit_get_version_array(const rb_iseq_t *iseq, unsigned idx) +{ + struct rb_iseq_constant_body *body = iseq->body; + + if (rb_darray_size(body->yjit_blocks) == 0) { + return NULL; + } + + RUBY_ASSERT((unsigned)rb_darray_size(body->yjit_blocks) == body->iseq_size); + return rb_darray_get(body->yjit_blocks, idx); +} + +// Count the number of block versions matching a given blockid +static size_t get_num_versions(blockid_t blockid) +{ + return rb_darray_size(yjit_get_version_array(blockid.iseq, blockid.idx)); +} + +// Keep track of a block version. Block should be fully constructed. +static void +add_block_version(block_t *block) +{ + const blockid_t blockid = block->blockid; + const rb_iseq_t *iseq = blockid.iseq; + struct rb_iseq_constant_body *body = iseq->body; + + // Function entry blocks must have stack size 0 + RUBY_ASSERT(!(block->blockid.idx == 0 && block->ctx.stack_size > 0)); + + // Ensure yjit_blocks is initialized for this iseq + if (rb_darray_size(body->yjit_blocks) == 0) { + // Initialize yjit_blocks to be as wide as body->iseq_encoded + int32_t casted = (int32_t)body->iseq_size; + if ((unsigned)casted != body->iseq_size) { + rb_bug("iseq too large"); + } + if (!rb_darray_make(&body->yjit_blocks, casted)) { + rb_bug("allocation failed"); + } + +#if YJIT_STATS + // First block compiled for this iseq + yjit_runtime_counters.compiled_iseq_count++; +#endif + } + + RUBY_ASSERT((int32_t)blockid.idx < rb_darray_size(body->yjit_blocks)); + rb_yjit_block_array_t *block_array_ref = rb_darray_ref(body->yjit_blocks, blockid.idx); + + // Add the new block + if (!rb_darray_append(block_array_ref, block)) { + rb_bug("allocation failed"); + } + + { + // By writing the new block to the iseq, the iseq now + // contains new references to Ruby objects. Run write barriers. + cme_dependency_t *cme_dep; + rb_darray_foreach(block->cme_dependencies, cme_dependency_idx, cme_dep) { + RB_OBJ_WRITTEN(iseq, Qundef, cme_dep->receiver_klass); + RB_OBJ_WRITTEN(iseq, Qundef, cme_dep->callee_cme); + } + + // Run write barriers for all objects in generated code. + uint32_t *offset_element; + rb_darray_foreach(block->gc_object_offsets, offset_idx, offset_element) { + uint32_t offset_to_value = *offset_element; + uint8_t *value_address = cb_get_ptr(cb, offset_to_value); + + VALUE object; + memcpy(&object, value_address, SIZEOF_VALUE); + RB_OBJ_WRITTEN(iseq, Qundef, object); + } + } + +#if YJIT_STATS + yjit_runtime_counters.compiled_block_count++; +#endif +} + +static ptrdiff_t +branch_code_size(const branch_t *branch) +{ + return branch->end_addr - branch->start_addr; +} + +// Generate code for a branch, possibly rewriting and changing the size of it +static void +regenerate_branch(codeblock_t *cb, branch_t *branch) +{ + if (branch->start_addr < cb_get_ptr(cb, yjit_codepage_frozen_bytes)) { + // Generating this branch would modify frozen bytes. Do nothing. + return; + } + + const uint32_t old_write_pos = cb->write_pos; + const bool branch_terminates_block = branch->end_addr == branch->block->end_addr; + + RUBY_ASSERT(branch->dst_addrs[0] != NULL); + + cb_set_write_ptr(cb, branch->start_addr); + branch->gen_fn(cb, branch->dst_addrs[0], branch->dst_addrs[1], branch->shape); + branch->end_addr = cb_get_write_ptr(cb); + + if (branch_terminates_block) { + // Adjust block size + branch->block->end_addr = branch->end_addr; + } + + // cb->write_pos is both a write cursor and a marker for the end of + // everything written out so far. Leave cb->write_pos at the end of the + // block before returning. This function only ever bump or retain the end + // of block marker since that's what the majority of callers want. When the + // branch sits at the very end of the codeblock and it shrinks after + // regeneration, it's up to the caller to drop bytes off the end to + // not leave a gap and implement branch->shape. + if (old_write_pos > cb->write_pos) { + // We rewound cb->write_pos to generate the branch, now restore it. + cb_set_pos(cb, old_write_pos); + } + else { + // The branch sits at the end of cb and consumed some memory. + // Keep cb->write_pos. + } +} + +// Create a new outgoing branch entry for a block +static branch_t* +make_branch_entry(block_t *block, const ctx_t *src_ctx, branchgen_fn gen_fn) +{ + RUBY_ASSERT(block != NULL); + + // Allocate and zero-initialize + branch_t *branch = calloc(1, sizeof(branch_t)); + + branch->block = block; + (void)src_ctx; // Unused for now + branch->gen_fn = gen_fn; + branch->shape = SHAPE_DEFAULT; + + // Add to the list of outgoing branches for the block + rb_darray_append(&block->outgoing, branch); + + return branch; +} + +// Retrieve a basic block version for an (iseq, idx) tuple +static block_t * +find_block_version(blockid_t blockid, const ctx_t *ctx) +{ + rb_yjit_block_array_t versions = yjit_get_version_array(blockid.iseq, blockid.idx); + + // Best match found + block_t *best_version = NULL; + int best_diff = INT_MAX; + + // For each version matching the blockid + rb_darray_for(versions, idx) { + block_t *version = rb_darray_get(versions, idx); + int diff = ctx_diff(ctx, &version->ctx); + + // Note that we always prefer the first matching + // version because of inline-cache chains + if (diff < best_diff) { + best_version = version; + best_diff = diff; + } + } + + // If greedy versioning is enabled + if (rb_yjit_opts.greedy_versioning) + { + // If we're below the version limit, don't settle for an imperfect match + if ((uint32_t)rb_darray_size(versions) + 1 < rb_yjit_opts.max_versions && best_diff > 0) { + return NULL; + } + } + + return best_version; +} + +// Produce a generic context when the block version limit is hit for a blockid +// Note that this will mutate the ctx argument +static ctx_t +limit_block_versions(blockid_t blockid, const ctx_t *ctx) +{ + // Guard chains implement limits separately, do nothing + if (ctx->chain_depth > 0) + return *ctx; + + // If this block version we're about to add will hit the version limit + if (get_num_versions(blockid) + 1 >= rb_yjit_opts.max_versions) { + // Produce a generic context that stores no type information, + // but still respects the stack_size and sp_offset constraints. + // This new context will then match all future requests. + ctx_t generic_ctx = DEFAULT_CTX; + generic_ctx.stack_size = ctx->stack_size; + generic_ctx.sp_offset = ctx->sp_offset; + + // Mutate the incoming context + return generic_ctx; + } + + return *ctx; +} + +static void yjit_free_block(block_t *block); +static void block_array_remove(rb_yjit_block_array_t block_array, block_t *block); + +// Immediately compile a series of block versions at a starting point and +// return the starting block. +static block_t * +gen_block_version(blockid_t blockid, const ctx_t *start_ctx, rb_execution_context_t *ec) +{ + // Small array to keep track of all the blocks compiled per invocation. We + // tend to have small batches since we often break up compilation with lazy + // stubs. Compilation is successful only if the whole batch is successful. + enum { MAX_PER_BATCH = 64 }; + block_t *batch[MAX_PER_BATCH]; + int compiled_count = 0; + bool batch_success = true; + block_t *block; + + // Generate code for the first block + block = gen_single_block(blockid, start_ctx, ec); + if (block) { + // Track the block + add_block_version(block); + + batch[compiled_count] = block; + compiled_count++; + } + batch_success = block; + + // For each successor block to compile + while (batch_success) { + // If the previous block compiled doesn't have outgoing branches, stop + if (rb_darray_size(block->outgoing) == 0) { + break; + } + + // Get the last outgoing branch from the previous block. Blocks can use + // gen_direct_jump() to request a block to be placed immediately after. + branch_t *last_branch = rb_darray_back(block->outgoing); + + // If there is no next block to compile, stop + if (last_branch->dst_addrs[0] || last_branch->dst_addrs[1]) { + break; + } + + if (last_branch->targets[0].iseq == NULL) { + rb_bug("invalid target for last branch"); + } + + // Generate code for the current block using context from the last branch. + blockid_t requested_id = last_branch->targets[0]; + const ctx_t *requested_ctx = &last_branch->target_ctxs[0]; + + batch_success = compiled_count < MAX_PER_BATCH; + if (batch_success) { + block = gen_single_block(requested_id, requested_ctx, ec); + batch_success = block; + } + + // If the batch failed, stop + if (!batch_success) { + break; + } + + // Connect the last branch and the new block + last_branch->dst_addrs[0] = block->start_addr; + rb_darray_append(&block->incoming, last_branch); + last_branch->blocks[0] = block; + + // This block should immediately follow the last branch + RUBY_ASSERT(block->start_addr == last_branch->end_addr); + + // Track the block + add_block_version(block); + + batch[compiled_count] = block; + compiled_count++; + } + + if (batch_success) { + // Success. Return first block in the batch. + RUBY_ASSERT(compiled_count > 0); + return batch[0]; + } + else { + // The batch failed. Free everything in the batch + for (int block_idx = 0; block_idx < compiled_count; block_idx++) { + block_t *const to_free = batch[block_idx]; + + // Undo add_block_version() + rb_yjit_block_array_t versions = yjit_get_version_array(to_free->blockid.iseq, to_free->blockid.idx); + block_array_remove(versions, to_free); + + // Deallocate + yjit_free_block(to_free); + } + +#if YJIT_STATS + yjit_runtime_counters.compilation_failure++; +#endif + return NULL; + } +} + +// Generate a block version that is an entry point inserted into an iseq +static uint8_t * +gen_entry_point(const rb_iseq_t *iseq, uint32_t insn_idx, rb_execution_context_t *ec) +{ + // If we aren't at PC 0, don't generate code + // See yjit_pc_guard + if (iseq->body->iseq_encoded != ec->cfp->pc) { + return NULL; + } + + // The entry context makes no assumptions about types + blockid_t blockid = { iseq, insn_idx }; + + rb_vm_barrier(); + // Write the interpreter entry prologue. Might be NULL when out of memory. + uint8_t *code_ptr = yjit_entry_prologue(cb, iseq); + + // Try to generate code for the entry block + block_t *block = gen_block_version(blockid, &DEFAULT_CTX, ec); + + cb_mark_all_executable(ocb); + cb_mark_all_executable(cb); + + // If we couldn't generate any code + if (!block || block->end_idx == insn_idx) { + return NULL; + } + + return code_ptr; +} + +// Called by the generated code when a branch stub is executed +// Triggers compilation of branches and code patching +static uint8_t * +branch_stub_hit(branch_t *branch, const uint32_t target_idx, rb_execution_context_t *ec) +{ + uint8_t *dst_addr = NULL; + + // Stop other ractors since we are going to patch machine code. + // This is how the GC does it. + RB_VM_LOCK_ENTER(); + rb_vm_barrier(); + + const ptrdiff_t branch_size_on_entry = branch_code_size(branch); + + RUBY_ASSERT(branch != NULL); + RUBY_ASSERT(target_idx < 2); + blockid_t target = branch->targets[target_idx]; + const ctx_t *target_ctx = &branch->target_ctxs[target_idx]; + + // If this branch has already been patched, return the dst address + // Note: ractors can cause the same stub to be hit multiple times + if (branch->blocks[target_idx]) { + dst_addr = branch->dst_addrs[target_idx]; + } + else { + rb_vm_barrier(); + + // :stub-sp-flush: + // Generated code do stack operations without modifying cfp->sp, while the + // cfp->sp tells the GC what values on the stack to root. Generated code + // generally takes care of updating cfp->sp when it calls runtime routines that + // could trigger GC, but it's inconvenient to do it before calling this function. + // So we do it here instead. + VALUE *const original_interp_sp = ec->cfp->sp; + ec->cfp->sp += target_ctx->sp_offset; + + // Update the PC in the current CFP, because it + // may be out of sync in JITted code + ec->cfp->pc = yjit_iseq_pc_at_idx(target.iseq, target.idx); + + // Try to find an existing compiled version of this block + block_t *p_block = find_block_version(target, target_ctx); + + // If this block hasn't yet been compiled + if (!p_block) { + const uint8_t branch_old_shape = branch->shape; + bool branch_modified = false; + + // If the new block can be generated right after the branch (at cb->write_pos) + if (cb_get_write_ptr(cb) == branch->end_addr) { + // This branch should be terminating its block + RUBY_ASSERT(branch->end_addr == branch->block->end_addr); + + // Change the branch shape to indicate the target block will be placed next + branch->shape = (uint8_t)target_idx; + + // Rewrite the branch with the new, potentially more compact shape + regenerate_branch(cb, branch); + branch_modified = true; + + // Ensure that the branch terminates the codeblock just like + // before entering this if block. This drops bytes off the end + // in case we shrank the branch when regenerating. + cb_set_write_ptr(cb, branch->end_addr); + } + + // Compile the new block version + p_block = gen_block_version(target, target_ctx, ec); + + if (!p_block && branch_modified) { + // We couldn't generate a new block for the branch, but we modified the branch. + // Restore the branch by regenerating it. + branch->shape = branch_old_shape; + regenerate_branch(cb, branch); + } + } + + if (p_block) { + // Branch shape should reflect layout + RUBY_ASSERT(!(branch->shape == (uint8_t)target_idx && p_block->start_addr != branch->end_addr)); + + // Add this branch to the list of incoming branches for the target + rb_darray_append(&p_block->incoming, branch); + + // Update the branch target address + dst_addr = p_block->start_addr; + branch->dst_addrs[target_idx] = dst_addr; + + // Mark this branch target as patched (no longer a stub) + branch->blocks[target_idx] = p_block; + + // Rewrite the branch with the new jump target address + regenerate_branch(cb, branch); + + // Restore interpreter sp, since the code hitting the stub expects the original. + ec->cfp->sp = original_interp_sp; + } + else { + // Failed to service the stub by generating a new block so now we + // need to exit to the interpreter at the stubbed location. We are + // intentionally *not* restoring original_interp_sp. At the time of + // writing, reconstructing interpreter state only involves setting + // cfp->sp and cfp->pc. We set both before trying to generate the + // block. All there is left to do to exit is to pop the native + // frame. We do that in code_for_exit_from_stub. + dst_addr = code_for_exit_from_stub; + } + + cb_mark_all_executable(ocb); + cb_mark_all_executable(cb); + } + + const ptrdiff_t new_branch_size = branch_code_size(branch); + RUBY_ASSERT_ALWAYS(new_branch_size >= 0); + RUBY_ASSERT_ALWAYS(new_branch_size <= branch_size_on_entry && "branch stubs should not enlarge branches"); + + RB_VM_LOCK_LEAVE(); + + // Return a pointer to the compiled block version + return dst_addr; +} + +// Get a version or stub corresponding to a branch target +static uint8_t * +get_branch_target( + blockid_t target, + const ctx_t *ctx, + branch_t *branch, + uint32_t target_idx +) +{ + //fprintf(stderr, "get_branch_target, block (%p, %d)\n", target.iseq, target.idx); + + block_t *p_block = find_block_version(target, ctx); + + // If the block already exists + if (p_block) { + // Add an incoming branch for this version + rb_darray_append(&p_block->incoming, branch); + branch->blocks[target_idx] = p_block; + + // Return a pointer to the compiled code + return p_block->start_addr; + } + + // Do we have enough memory for a stub? + const long MAX_CODE_SIZE = 64; + if (ocb->write_pos + MAX_CODE_SIZE >= cb->mem_size) { + return NULL; + } + + // Generate an outlined stub that will call branch_stub_hit() + uint8_t *stub_addr = cb_get_ptr(ocb, ocb->write_pos); + + // Call branch_stub_hit(branch_idx, target_idx, ec) + mov(ocb, C_ARG_REGS[2], REG_EC); + mov(ocb, C_ARG_REGS[1], imm_opnd(target_idx)); + mov(ocb, C_ARG_REGS[0], const_ptr_opnd(branch)); + call_ptr(ocb, REG0, (void *)&branch_stub_hit); + + // Jump to the address returned by the + // branch_stub_hit call + jmp_rm(ocb, RAX); + + RUBY_ASSERT(cb_get_ptr(ocb, ocb->write_pos) - stub_addr <= MAX_CODE_SIZE); + + return stub_addr; +} + +static void +gen_branch( + jitstate_t *jit, + const ctx_t *src_ctx, + blockid_t target0, + const ctx_t *ctx0, + blockid_t target1, + const ctx_t *ctx1, + branchgen_fn gen_fn +) +{ + RUBY_ASSERT(target0.iseq != NULL); + + branch_t *branch = make_branch_entry(jit->block, src_ctx, gen_fn); + branch->targets[0] = target0; + branch->targets[1] = target1; + branch->target_ctxs[0] = *ctx0; + branch->target_ctxs[1] = ctx1? *ctx1:DEFAULT_CTX; + + // Get the branch targets or stubs + branch->dst_addrs[0] = get_branch_target(target0, ctx0, branch, 0); + branch->dst_addrs[1] = ctx1? get_branch_target(target1, ctx1, branch, 1):NULL; + + // Call the branch generation function + branch->start_addr = cb_get_write_ptr(cb); + regenerate_branch(cb, branch); +} + +static void +gen_jump_branch(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape) +{ + switch (shape) { + case SHAPE_NEXT0: + break; + + case SHAPE_NEXT1: + RUBY_ASSERT(false); + break; + + case SHAPE_DEFAULT: + jmp_ptr(cb, target0); + break; + } +} + +static void +gen_direct_jump( + jitstate_t *jit, + const ctx_t *ctx, + blockid_t target0 +) +{ + RUBY_ASSERT(target0.iseq != NULL); + + branch_t *branch = make_branch_entry(jit->block, ctx, gen_jump_branch); + branch->targets[0] = target0; + branch->target_ctxs[0] = *ctx; + + block_t *p_block = find_block_version(target0, ctx); + + // If the version already exists + if (p_block) { + rb_darray_append(&p_block->incoming, branch); + + branch->dst_addrs[0] = p_block->start_addr; + branch->blocks[0] = p_block; + branch->shape = SHAPE_DEFAULT; + + // Call the branch generation function + branch->start_addr = cb_get_write_ptr(cb); + gen_jump_branch(cb, branch->dst_addrs[0], NULL, SHAPE_DEFAULT); + branch->end_addr = cb_get_write_ptr(cb); + } + else { + // This NULL target address signals gen_block_version() to compile the + // target block right after this one (fallthrough). + branch->dst_addrs[0] = NULL; + branch->shape = SHAPE_NEXT0; + branch->start_addr = cb_get_write_ptr(cb); + branch->end_addr = cb_get_write_ptr(cb); + } +} + +// Create a stub to force the code up to this point to be executed +static void +defer_compilation( + jitstate_t *jit, + ctx_t *cur_ctx +) +{ + //fprintf(stderr, "defer compilation at (%p, %d) depth=%d\n", block->blockid.iseq, insn_idx, cur_ctx->chain_depth); + + if (cur_ctx->chain_depth != 0) { + rb_bug("double defer"); + } + + ctx_t next_ctx = *cur_ctx; + + if (next_ctx.chain_depth >= UINT8_MAX) { + rb_bug("max block version chain depth reached"); + } + + next_ctx.chain_depth += 1; + + branch_t *branch = make_branch_entry(jit->block, cur_ctx, gen_jump_branch); + + // Get the branch targets or stubs + branch->target_ctxs[0] = next_ctx; + branch->targets[0] = (blockid_t){ jit->block->blockid.iseq, jit->insn_idx }; + branch->dst_addrs[0] = get_branch_target(branch->targets[0], &next_ctx, branch, 0); + + // Call the branch generation function + codeblock_t *cb = jit->cb; + branch->start_addr = cb_get_write_ptr(cb); + gen_jump_branch(cb, branch->dst_addrs[0], NULL, SHAPE_DEFAULT); + branch->end_addr = cb_get_write_ptr(cb); +} + +// Remove all references to a block then free it. +static void +yjit_free_block(block_t *block) +{ + yjit_unlink_method_lookup_dependency(block); + yjit_block_assumptions_free(block); + + // Remove this block from the predecessor's targets + rb_darray_for(block->incoming, incoming_idx) { + // Branch from the predecessor to us + branch_t *pred_branch = rb_darray_get(block->incoming, incoming_idx); + + // If this is us, nullify the target block + for (size_t succ_idx = 0; succ_idx < 2; succ_idx++) { + if (pred_branch->blocks[succ_idx] == block) { + pred_branch->blocks[succ_idx] = NULL; + } + } + } + + // For each outgoing branch + rb_darray_for(block->outgoing, branch_idx) { + branch_t *out_branch = rb_darray_get(block->outgoing, branch_idx); + + // For each successor block + for (size_t succ_idx = 0; succ_idx < 2; succ_idx++) { + block_t *succ = out_branch->blocks[succ_idx]; + + if (succ == NULL) + continue; + + // Remove this block from the successor's incoming list + rb_darray_for(succ->incoming, incoming_idx) { + branch_t *pred_branch = rb_darray_get(succ->incoming, incoming_idx); + if (pred_branch == out_branch) { + rb_darray_remove_unordered(succ->incoming, incoming_idx); + break; + } + } + } + + // Free the outgoing branch entry + free(out_branch); + } + + rb_darray_free(block->incoming); + rb_darray_free(block->outgoing); + rb_darray_free(block->gc_object_offsets); + + free(block); +} + +// Remove a block version +static void +block_array_remove(rb_yjit_block_array_t block_array, block_t *block) +{ + block_t **element; + rb_darray_foreach(block_array, idx, element) { + if (*element == block) { + rb_darray_remove_unordered(block_array, idx); + return; + } + } + + RUBY_ASSERT(false); +} + +// Some runtime checks for integrity of a program location +static void +verify_blockid(const blockid_t blockid) +{ + const rb_iseq_t *const iseq = blockid.iseq; + RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq)); + RUBY_ASSERT_ALWAYS(blockid.idx < iseq->body->iseq_size); +} + +// Invalidate one specific block version +static void +invalidate_block_version(block_t *block) +{ + ASSERT_vm_locking(); + + // TODO: want to assert that all other ractors are stopped here. Can't patch + // machine code that some other thread is running. + + verify_blockid(block->blockid); + + const rb_iseq_t *iseq = block->blockid.iseq; + + //fprintf(stderr, "invalidating block (%p, %d)\n", block->blockid.iseq, block->blockid.idx); + //fprintf(stderr, "block=%p\n", block); + + // Remove this block from the version array + rb_yjit_block_array_t versions = yjit_get_version_array(iseq, block->blockid.idx); + block_array_remove(versions, block); + + // Get a pointer to the generated code for this block + uint8_t *code_ptr = block->start_addr; + + // Make the the start of the block do an exit. This handles OOM situations + // and some cases where we can't efficiently patch incoming branches. + // Do this first, since in case there is a fallthrough branch into this + // block, the patching loop below can overwrite the start of the block. + // In those situations, there is hopefully no jumps to the start of the block + // after patching as the start of the block would be in the middle of something + // generated by branch_t::gen_fn. + { + RUBY_ASSERT_ALWAYS(block->entry_exit && "block invalidation requires an exit"); + if (block->entry_exit == block->start_addr) { + // Some blocks exit on entry. Patching a jump to the entry at the + // entry makes an infinite loop. + } + else if (block->start_addr >= cb_get_ptr(cb, yjit_codepage_frozen_bytes)) { // Don't patch frozen code region + // Patch in a jump to block->entry_exit. + uint32_t cur_pos = cb->write_pos; + cb_set_write_ptr(cb, block->start_addr); + jmp_ptr(cb, block->entry_exit); + RUBY_ASSERT_ALWAYS(cb_get_ptr(cb, cb->write_pos) < block->end_addr && "invalidation wrote past end of block"); + cb_set_pos(cb, cur_pos); + } + } + + // For each incoming branch + rb_darray_for(block->incoming, incoming_idx) { + branch_t *branch = rb_darray_get(block->incoming, incoming_idx); + uint32_t target_idx = (branch->dst_addrs[0] == code_ptr)? 0:1; + RUBY_ASSERT(branch->dst_addrs[target_idx] == code_ptr); + RUBY_ASSERT(branch->blocks[target_idx] == block); + + // Mark this target as being a stub + branch->blocks[target_idx] = NULL; + + // Don't patch frozen code region + if (branch->start_addr < cb_get_ptr(cb, yjit_codepage_frozen_bytes)) { + continue; + } + + // Create a stub for this branch target + uint8_t *branch_target = get_branch_target( + block->blockid, + &block->ctx, + branch, + target_idx + ); + + if (!branch_target) { + // We were unable to generate a stub (e.g. OOM). Use the block's + // exit instead of a stub for the block. It's important that we + // still patch the branch in this situation so stubs are unique + // to branches. Think about what could go wrong if we run out of + // memory in the middle of this loop. + branch_target = block->entry_exit; + } + + branch->dst_addrs[target_idx] = branch_target; + + // Check if the invalidated block immediately follows + bool target_next = (block->start_addr == branch->end_addr); + + if (target_next) { + // The new block will no longer be adjacent. + // Note that we could be enlarging the branch and writing into the + // start of the block being invalidated. + branch->shape = SHAPE_DEFAULT; + } + + // Rewrite the branch with the new jump target address + regenerate_branch(cb, branch); + + if (target_next && branch->end_addr > block->end_addr) { + fprintf(stderr, "branch_block_idx=%u block_idx=%u over=%ld block_size=%ld\n", + branch->block->blockid.idx, + block->blockid.idx, + branch->end_addr - block->end_addr, + block->end_addr - block->start_addr); + yjit_print_iseq(branch->block->blockid.iseq); + rb_bug("yjit invalidate rewrote branch past end of invalidated block"); + } + } + + // Clear out the JIT func so that we can recompile later and so the + // interpreter will run the iseq + +#if JIT_ENABLED + // Only clear the jit_func when we're invalidating the JIT entry block. + // We only support compiling iseqs from index 0 right now. So entry + // points will always have an instruction index of 0. We'll need to + // change this in the future when we support optional parameters because + // they enter the function with a non-zero PC + if (block->blockid.idx == 0) { + iseq->body->jit_func = 0; + } +#endif + + // TODO: + // May want to recompile a new entry point (for interpreter entry blocks) + // This isn't necessary for correctness + + // FIXME: + // Call continuation addresses on the stack can also be atomically replaced by jumps going to the stub. + + yjit_free_block(block); + +#if YJIT_STATS + yjit_runtime_counters.invalidation_count++; +#endif + + cb_mark_all_executable(ocb); + cb_mark_all_executable(cb); + + // fprintf(stderr, "invalidation done\n"); +} + +static void +yjit_init_core(void) +{ + gen_code_for_exit_from_stub(); +} diff --git a/ruby/yjit_core.h b/ruby/yjit_core.h new file mode 100644 index 000000000..e38dd790a --- /dev/null +++ b/ruby/yjit_core.h @@ -0,0 +1,307 @@ +#ifndef YJIT_CORE_H +#define YJIT_CORE_H 1 + +#include +#include +#include "yjit_asm.h" + +// Callee-saved regs +#define REG_CFP R13 +#define REG_EC R12 +#define REG_SP RBX + +// Scratch registers used by YJIT +#define REG0 RAX +#define REG0_32 EAX +#define REG0_8 AL +#define REG1 RCX +#define REG1_32 ECX + +// Maximum number of temp value types we keep track of +#define MAX_TEMP_TYPES 8 + +// Maximum number of local variable types we keep track of +#define MAX_LOCAL_TYPES 8 + +// Default versioning context (no type information) +#define DEFAULT_CTX ( (ctx_t){ 0 } ) + +enum yjit_type_enum +{ + ETYPE_UNKNOWN = 0, + ETYPE_NIL, + ETYPE_TRUE, + ETYPE_FALSE, + ETYPE_FIXNUM, + ETYPE_FLONUM, + ETYPE_ARRAY, + ETYPE_HASH, + ETYPE_SYMBOL, + ETYPE_STRING +}; + +// Represent the type of a value (local/stack/self) in YJIT +typedef struct yjit_type_struct +{ + // Value is definitely a heap object + uint8_t is_heap : 1; + + // Value is definitely an immediate + uint8_t is_imm : 1; + + // Specific value type, if known + uint8_t type : 4; + +} val_type_t; +STATIC_ASSERT(val_type_size, sizeof(val_type_t) == 1); + +// Unknown type, could be anything, all zeroes +#define TYPE_UNKNOWN ( (val_type_t){ 0 } ) + +// Could be any heap object +#define TYPE_HEAP ( (val_type_t){ .is_heap = 1 } ) + +// Could be any immediate +#define TYPE_IMM ( (val_type_t){ .is_imm = 1 } ) + +#define TYPE_NIL ( (val_type_t){ .is_imm = 1, .type = ETYPE_NIL } ) +#define TYPE_TRUE ( (val_type_t){ .is_imm = 1, .type = ETYPE_TRUE } ) +#define TYPE_FALSE ( (val_type_t){ .is_imm = 1, .type = ETYPE_FALSE } ) +#define TYPE_FIXNUM ( (val_type_t){ .is_imm = 1, .type = ETYPE_FIXNUM } ) +#define TYPE_FLONUM ( (val_type_t){ .is_imm = 1, .type = ETYPE_FLONUM } ) +#define TYPE_STATIC_SYMBOL ( (val_type_t){ .is_imm = 1, .type = ETYPE_SYMBOL } ) +#define TYPE_ARRAY ( (val_type_t){ .is_heap = 1, .type = ETYPE_ARRAY } ) +#define TYPE_HASH ( (val_type_t){ .is_heap = 1, .type = ETYPE_HASH } ) +#define TYPE_STRING ( (val_type_t){ .is_heap = 1, .type = ETYPE_STRING } ) + +enum yjit_temp_loc +{ + TEMP_STACK = 0, + TEMP_SELF, + TEMP_LOCAL, // Local with index + //TEMP_CONST, // Small constant (0, 1, 2, Qnil, Qfalse, Qtrue) +}; + +// Potential mapping of a value on the temporary stack to +// self, a local variable or constant so that we can track its type +typedef struct yjit_temp_mapping +{ + // Where/how is the value stored? + uint8_t kind: 2; + + // Index of the local variale, + // or small non-negative constant in [0, 63] + uint8_t idx : 6; + +} temp_mapping_t; +STATIC_ASSERT(temp_mapping_size, sizeof(temp_mapping_t) == 1); + +// By default, temps are just temps on the stack. +// Name conflict with an mmap flag. This is a struct instance, +// so the compiler will check for wrong usage. +#undef MAP_STACK +#define MAP_STACK ( (temp_mapping_t) { 0 } ) + +// Temp value is actually self +#define MAP_SELF ( (temp_mapping_t) { .kind = TEMP_SELF } ) + +// Represents both the type and mapping +typedef struct { + temp_mapping_t mapping; + val_type_t type; +} temp_type_mapping_t; +STATIC_ASSERT(temp_type_mapping_size, sizeof(temp_type_mapping_t) == 2); + +// Operand to a bytecode instruction +typedef struct yjit_insn_opnd +{ + // Indicates if the value is self + bool is_self; + + // Index on the temporary stack (for stack operands only) + uint16_t idx; + +} insn_opnd_t; + +#define OPND_SELF ( (insn_opnd_t){ .is_self = true } ) +#define OPND_STACK(stack_idx) ( (insn_opnd_t){ .is_self = false, .idx = stack_idx } ) + +/** +Code generation context +Contains information we can use to optimize code +*/ +typedef struct yjit_context +{ + // Number of values currently on the temporary stack + uint16_t stack_size; + + // Offset of the JIT SP relative to the interpreter SP + // This represents how far the JIT's SP is from the "real" SP + int16_t sp_offset; + + // Depth of this block in the sidechain (eg: inline-cache chain) + uint8_t chain_depth; + + // Local variable types we keepp track of + val_type_t local_types[MAX_LOCAL_TYPES]; + + // Temporary variable types we keep track of + val_type_t temp_types[MAX_TEMP_TYPES]; + + // Type we track for self + val_type_t self_type; + + // Mapping of temp stack entries to types we track + temp_mapping_t temp_mapping[MAX_TEMP_TYPES]; + +} ctx_t; +STATIC_ASSERT(yjit_ctx_size, sizeof(ctx_t) <= 32); + +// Tuple of (iseq, idx) used to identify basic blocks +typedef struct BlockId +{ + // Instruction sequence + const rb_iseq_t *iseq; + + // Index in the iseq where the block starts + uint32_t idx; + +} blockid_t; + +// Null block id constant +static const blockid_t BLOCKID_NULL = { 0, 0 }; + +/// Branch code shape enumeration +typedef enum branch_shape +{ + SHAPE_NEXT0, // Target 0 is next + SHAPE_NEXT1, // Target 1 is next + SHAPE_DEFAULT // Neither target is next +} branch_shape_t; + +// Branch code generation function signature +typedef void (*branchgen_fn)(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape); + +/** +Store info about an outgoing branch in a code segment +Note: care must be taken to minimize the size of branch_t objects +*/ +typedef struct yjit_branch_entry +{ + // Block this is attached to + struct yjit_block_version *block; + + // Positions where the generated code starts and ends + uint8_t *start_addr; + uint8_t *end_addr; + + // Context right after the branch instruction + // Unused for now. + // ctx_t src_ctx; + + // Branch target blocks and their contexts + blockid_t targets[2]; + ctx_t target_ctxs[2]; + struct yjit_block_version *blocks[2]; + + // Jump target addresses + uint8_t *dst_addrs[2]; + + // Branch code generation function + branchgen_fn gen_fn; + + // Shape of the branch + branch_shape_t shape : 2; + +} branch_t; + +// In case this block is invalidated, these two pieces of info +// help to remove all pointers to this block in the system. +typedef struct { + VALUE receiver_klass; + VALUE callee_cme; +} cme_dependency_t; + +typedef rb_darray(cme_dependency_t) cme_dependency_array_t; + +typedef rb_darray(branch_t*) branch_array_t; + +typedef rb_darray(uint32_t) int32_array_t; + +/** +Basic block version +Represents a portion of an iseq compiled with a given context +Note: care must be taken to minimize the size of block_t objects +*/ +typedef struct yjit_block_version +{ + // Bytecode sequence (iseq, idx) this is a version of + blockid_t blockid; + + // Context at the start of the block + ctx_t ctx; + + // Positions where the generated code starts and ends + uint8_t *start_addr; + uint8_t *end_addr; + + // List of incoming branches (from predecessors) + branch_array_t incoming; + + // List of outgoing branches (to successors) + // Note: these are owned by this block version + branch_array_t outgoing; + + // Offsets for GC managed objects in the mainline code block + int32_array_t gc_object_offsets; + + // CME dependencies of this block, to help to remove all pointers to this + // block in the system. + cme_dependency_array_t cme_dependencies; + + // Code address of an exit for `ctx` and `blockid`. Used for block + // invalidation. + uint8_t *entry_exit; + + // Index one past the last instruction in the iseq + uint32_t end_idx; + +} block_t; + +// Code generation state +typedef struct JITState +{ + // Inline and outlined code blocks we are + // currently generating code into + codeblock_t* cb; + codeblock_t* ocb; + + // Block version being compiled + block_t *block; + + // Instruction sequence this is associated with + const rb_iseq_t *iseq; + + // Index of the current instruction being compiled + uint32_t insn_idx; + + // Opcode for the instruction being compiled + int opcode; + + // PC of the instruction being compiled + VALUE *pc; + + // Side exit to the instruction being compiled. See :side-exit:. + uint8_t *side_exit_for_pc; + + // Execution context when compilation started + // This allows us to peek at run-time values + rb_execution_context_t *ec; + + // Whether we need to record the code address at + // the end of this bytecode instruction for global invalidation + bool record_boundary_patch_point; + +} jitstate_t; + +#endif // #ifndef YJIT_CORE_H diff --git a/ruby/yjit_iface.c b/ruby/yjit_iface.c new file mode 100644 index 000000000..6e72a2cc9 --- /dev/null +++ b/ruby/yjit_iface.c @@ -0,0 +1,1310 @@ +// This file is a fragment of the yjit.o compilation unit. See yjit.c. +#include "internal.h" +#include "vm_sync.h" +#include "vm_callinfo.h" +#include "builtin.h" +#include "gc.h" +#include "iseq.h" +#include "internal/compile.h" +#include "internal/class.h" +#include "yjit.h" +#include "yjit_iface.h" +#include "yjit_codegen.h" +#include "yjit_core.h" +#include "darray.h" + +#ifdef HAVE_LIBCAPSTONE +#include +static VALUE cYjitDisasm; +static VALUE cYjitDisasmInsn; +#endif + +static VALUE mYjit; +static VALUE cYjitBlock; + +#if YJIT_STATS +static VALUE cYjitCodeComment; +#endif + +#if YJIT_STATS +extern const int rb_vm_max_insn_name_size; +static int64_t exit_op_count[VM_INSTRUCTION_SIZE] = { 0 }; +#endif + +// Hash table of encoded instructions +extern st_table *rb_encoded_insn_data; + +struct rb_yjit_options rb_yjit_opts; + +// Size of code pages to allocate +#define CODE_PAGE_SIZE 16 * 1024 + +// How many code pages to allocate at once +#define PAGES_PER_ALLOC 512 + +static const rb_data_type_t yjit_block_type = { + "YJIT/Block", + {0, 0, 0, }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +// Get the PC for a given index in an iseq +static VALUE * +yjit_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx) +{ + RUBY_ASSERT(iseq != NULL); + RUBY_ASSERT(insn_idx < iseq->body->iseq_size); + VALUE *encoded = iseq->body->iseq_encoded; + VALUE *pc = &encoded[insn_idx]; + return pc; +} + +// For debugging. Print the disassembly of an iseq. +RBIMPL_ATTR_MAYBE_UNUSED() +static void +yjit_print_iseq(const rb_iseq_t *iseq) +{ + char *ptr; + long len; + VALUE disassembly = rb_iseq_disasm(iseq); + RSTRING_GETMEM(disassembly, ptr, len); + fprintf(stderr, "%.*s\n", (int)len, ptr); +} + +static int +yjit_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc) +{ + const VALUE at_pc = *pc; + if (FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)) { + return rb_vm_insn_addr2opcode((const void *)at_pc); + } + else { + return (int)at_pc; + } +} + +// Verify that calling with cd on receiver goes to callee +static void +check_cfunc_dispatch(VALUE receiver, struct rb_callinfo *ci, void *callee, rb_callable_method_entry_t *compile_time_cme) +{ + if (METHOD_ENTRY_INVALIDATED(compile_time_cme)) { + rb_bug("yjit: output code uses invalidated cme %p", (void *)compile_time_cme); + } + + bool callee_correct = false; + const rb_callable_method_entry_t *cme = rb_callable_method_entry(CLASS_OF(receiver), vm_ci_mid(ci)); + if (cme->def->type == VM_METHOD_TYPE_CFUNC) { + const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc); + if ((void *)cfunc->func == callee) { + callee_correct = true; + } + } + if (!callee_correct) { + rb_bug("yjit: output code calls wrong method"); + } +} + +MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key); + +// GC root for interacting with the GC +struct yjit_root_struct { + int unused; // empty structs are not legal in C99 +}; + +// Hash table of BOP blocks +static st_table *blocks_assuming_bops; + +static bool +assume_bop_not_redefined(jitstate_t *jit, int redefined_flag, enum ruby_basic_operators bop) +{ + if (BASIC_OP_UNREDEFINED_P(bop, redefined_flag)) { + RUBY_ASSERT(blocks_assuming_bops); + + jit_ensure_block_entry_exit(jit); + st_insert(blocks_assuming_bops, (st_data_t)jit->block, 0); + return true; + } + else { + return false; + } +} + +// Map klass => id_table[mid, set of blocks] +// While a block `b` is in the table, b->callee_cme == rb_callable_method_entry(klass, mid). +// See assume_method_lookup_stable() +static st_table *method_lookup_dependency; + +// For adding to method_lookup_dependency data with st_update +struct lookup_dependency_insertion { + block_t *block; + ID mid; +}; + +// Map cme => set of blocks +// See assume_method_lookup_stable() +static st_table *cme_validity_dependency; + +static int +add_cme_validity_dependency_i(st_data_t *key, st_data_t *value, st_data_t new_block, int existing) +{ + st_table *block_set; + if (existing) { + block_set = (st_table *)*value; + } + else { + // Make the set and put it into cme_validity_dependency + block_set = st_init_numtable(); + *value = (st_data_t)block_set; + } + + // Put block into set + st_insert(block_set, new_block, 1); + + return ST_CONTINUE; +} + +static int +add_lookup_dependency_i(st_data_t *key, st_data_t *value, st_data_t data, int existing) +{ + struct lookup_dependency_insertion *info = (void *)data; + + // Find or make an id table + struct rb_id_table *id2blocks; + if (existing) { + id2blocks = (void *)*value; + } + else { + // Make an id table and put it into the st_table + id2blocks = rb_id_table_create(1); + *value = (st_data_t)id2blocks; + } + + // Find or make a block set + st_table *block_set; + { + VALUE blocks; + if (rb_id_table_lookup(id2blocks, info->mid, &blocks)) { + // Take existing set + block_set = (st_table *)blocks; + } + else { + // Make new block set and put it into the id table + block_set = st_init_numtable(); + rb_id_table_insert(id2blocks, info->mid, (VALUE)block_set); + } + } + + st_insert(block_set, (st_data_t)info->block, 1); + + return ST_CONTINUE; +} + +// Remember that a block assumes that +// `rb_callable_method_entry(receiver_klass, cme->called_id) == cme` and that +// `cme` is valid. +// When either of these assumptions becomes invalid, rb_yjit_method_lookup_change() or +// rb_yjit_cme_invalidate() invalidates the block. +// +// @raise NoMemoryError +static void +assume_method_lookup_stable(VALUE receiver_klass, const rb_callable_method_entry_t *cme, jitstate_t *jit) +{ + RUBY_ASSERT(cme_validity_dependency); + RUBY_ASSERT(method_lookup_dependency); + RUBY_ASSERT(rb_callable_method_entry(receiver_klass, cme->called_id) == cme); + RUBY_ASSERT_ALWAYS(RB_TYPE_P(receiver_klass, T_CLASS) || RB_TYPE_P(receiver_klass, T_ICLASS)); + RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(receiver_klass)); + + jit_ensure_block_entry_exit(jit); + + block_t *block = jit->block; + + cme_dependency_t cme_dep = { receiver_klass, (VALUE)cme }; + rb_darray_append(&block->cme_dependencies, cme_dep); + + st_update(cme_validity_dependency, (st_data_t)cme, add_cme_validity_dependency_i, (st_data_t)block); + + struct lookup_dependency_insertion info = { block, cme->called_id }; + st_update(method_lookup_dependency, (st_data_t)receiver_klass, add_lookup_dependency_i, (st_data_t)&info); +} + +static st_table *blocks_assuming_single_ractor_mode; + +// Can raise NoMemoryError. +RBIMPL_ATTR_NODISCARD() +static bool +assume_single_ractor_mode(jitstate_t *jit) +{ + if (rb_multi_ractor_p()) return false; + + jit_ensure_block_entry_exit(jit); + + st_insert(blocks_assuming_single_ractor_mode, (st_data_t)jit->block, 1); + return true; +} + +static st_table *blocks_assuming_stable_global_constant_state; + +// Assume that the global constant state has not changed since call to this function. +// Can raise NoMemoryError. +static void +assume_stable_global_constant_state(jitstate_t *jit) +{ + jit_ensure_block_entry_exit(jit); + st_insert(blocks_assuming_stable_global_constant_state, (st_data_t)jit->block, 1); +} + +static int +mark_and_pin_keys_i(st_data_t k, st_data_t v, st_data_t ignore) +{ + rb_gc_mark((VALUE)k); + + return ST_CONTINUE; +} + +// GC callback during mark phase +static void +yjit_root_mark(void *ptr) +{ + if (method_lookup_dependency) { + // TODO: This is a leak. Unused blocks linger in the table forever, preventing the + // callee class they speculate on from being collected. + // We could do a bespoke weak reference scheme on classes similar to + // the interpreter's call cache. See finalizer for T_CLASS and cc_table_free(). + st_foreach(method_lookup_dependency, mark_and_pin_keys_i, 0); + } + + if (cme_validity_dependency) { + // Why not let the GC move the cme keys in this table? + // Because this is basically a compare_by_identity Hash. + // If a key moves, we would need to reinsert it into the table so it is rehashed. + // That is tricky to do, espcially as it could trigger allocation which could + // trigger GC. Not sure if it is okay to trigger GC while the GC is updating + // references. + st_foreach(cme_validity_dependency, mark_and_pin_keys_i, 0); + } +} + +static void +yjit_root_free(void *ptr) +{ + // Do nothing. The root lives as long as the process. +} + +static size_t +yjit_root_memsize(const void *ptr) +{ + // Count off-gc-heap allocation size of the dependency table + return st_memsize(method_lookup_dependency); // TODO: more accurate accounting +} + +// GC callback during compaction +static void +yjit_root_update_references(void *ptr) +{ +} + +// Custom type for interacting with the GC +// TODO: make this write barrier protected +static const rb_data_type_t yjit_root_type = { + "yjit_root", + {yjit_root_mark, yjit_root_free, yjit_root_memsize, yjit_root_update_references}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +// st_table iterator for invalidating blocks that are keys to the table. +static int +block_set_invalidate_i(st_data_t key, st_data_t v, st_data_t ignore) +{ + block_t *version = (block_t *)key; + + // Thankfully, st_table supports deleting while iterating. + invalidate_block_version(version); + + return ST_CONTINUE; +} + +// Callback for when rb_callable_method_entry(klass, mid) is going to change. +// Invalidate blocks that assume stable method lookup of `mid` in `klass` when this happens. +void +rb_yjit_method_lookup_change(VALUE klass, ID mid) +{ + if (!method_lookup_dependency) return; + + RB_VM_LOCK_ENTER(); + + st_data_t image; + st_data_t key = (st_data_t)klass; + if (st_lookup(method_lookup_dependency, key, &image)) { + struct rb_id_table *id2blocks = (void *)image; + VALUE blocks; + + // Invalidate all blocks in method_lookup_dependency[klass][mid] + if (rb_id_table_lookup(id2blocks, mid, &blocks)) { + rb_id_table_delete(id2blocks, mid); + + st_table *block_set = (st_table *)blocks; + +#if YJIT_STATS + yjit_runtime_counters.invalidate_method_lookup += block_set->num_entries; +#endif + + st_foreach(block_set, block_set_invalidate_i, 0); + + st_free_table(block_set); + } + } + + RB_VM_LOCK_LEAVE(); +} + +// Callback for when a cme becomes invalid. +// Invalidate all blocks that depend on cme being valid. +void +rb_yjit_cme_invalidate(VALUE cme) +{ + if (!cme_validity_dependency) return; + + RUBY_ASSERT(IMEMO_TYPE_P(cme, imemo_ment)); + + RB_VM_LOCK_ENTER(); + + // Delete the block set from the table + st_data_t cme_as_st_data = (st_data_t)cme; + st_data_t blocks; + if (st_delete(cme_validity_dependency, &cme_as_st_data, &blocks)) { + st_table *block_set = (st_table *)blocks; + +#if YJIT_STATS + yjit_runtime_counters.invalidate_method_lookup += block_set->num_entries; +#endif + + // Invalidate each block + st_foreach(block_set, block_set_invalidate_i, 0); + + st_free_table(block_set); + } + + RB_VM_LOCK_LEAVE(); +} + +// For dealing with refinements +void +rb_yjit_invalidate_all_method_lookup_assumptions(void) +{ + // It looks like Module#using actually doesn't need to invalidate all the + // method caches, so we do nothing here for now. +} + +// Remove a block from the method lookup dependency table +static void +remove_method_lookup_dependency(block_t *block, VALUE receiver_klass, const rb_callable_method_entry_t *callee_cme) +{ + RUBY_ASSERT(receiver_klass); + RUBY_ASSERT(callee_cme); // callee_cme should be set when receiver_klass is set + + st_data_t image; + st_data_t key = (st_data_t)receiver_klass; + if (st_lookup(method_lookup_dependency, key, &image)) { + struct rb_id_table *id2blocks = (void *)image; + ID mid = callee_cme->called_id; + + // Find block set + VALUE blocks; + if (rb_id_table_lookup(id2blocks, mid, &blocks)) { + st_table *block_set = (st_table *)blocks; + + // Remove block from block set + st_data_t block_as_st_data = (st_data_t)block; + (void)st_delete(block_set, &block_as_st_data, NULL); + + if (block_set->num_entries == 0) { + // Block set now empty. Remove from id table. + rb_id_table_delete(id2blocks, mid); + st_free_table(block_set); + } + } + } +} + +// Remove a block from cme_validity_dependency +static void +remove_cme_validity_dependency(block_t *block, const rb_callable_method_entry_t *callee_cme) +{ + RUBY_ASSERT(callee_cme); + + st_data_t blocks; + if (st_lookup(cme_validity_dependency, (st_data_t)callee_cme, &blocks)) { + st_table *block_set = (st_table *)blocks; + + st_data_t block_as_st_data = (st_data_t)block; + (void)st_delete(block_set, &block_as_st_data, NULL); + } +} + +static void +yjit_unlink_method_lookup_dependency(block_t *block) +{ + cme_dependency_t *cme_dep; + rb_darray_foreach(block->cme_dependencies, cme_dependency_idx, cme_dep) { + remove_method_lookup_dependency(block, cme_dep->receiver_klass, (const rb_callable_method_entry_t *)cme_dep->callee_cme); + remove_cme_validity_dependency(block, (const rb_callable_method_entry_t *)cme_dep->callee_cme); + } + rb_darray_free(block->cme_dependencies); +} + +static void +yjit_block_assumptions_free(block_t *block) +{ + st_data_t as_st_data = (st_data_t)block; + if (blocks_assuming_stable_global_constant_state) { + st_delete(blocks_assuming_stable_global_constant_state, &as_st_data, NULL); + } + + if (blocks_assuming_single_ractor_mode) { + st_delete(blocks_assuming_single_ractor_mode, &as_st_data, NULL); + } + + if (blocks_assuming_bops) { + st_delete(blocks_assuming_bops, &as_st_data, NULL); + } +} + +typedef VALUE (*yjit_func_t)(rb_execution_context_t *, rb_control_frame_t *); + +bool +rb_yjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec) +{ +#if (OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE) && JIT_ENABLED + bool success = true; + RB_VM_LOCK_ENTER(); + rb_vm_barrier(); + + // Compile a block version starting at the first instruction + uint8_t *code_ptr = gen_entry_point(iseq, 0, ec); + + if (code_ptr) { + iseq->body->jit_func = (yjit_func_t)code_ptr; + } + else { + iseq->body->jit_func = 0; + success = false; + } + + RB_VM_LOCK_LEAVE(); + return success; +#else + return false; +#endif +} + +struct yjit_block_itr { + const rb_iseq_t *iseq; + VALUE list; +}; + +/* Get a list of the YJIT blocks associated with `rb_iseq` */ +static VALUE +yjit_blocks_for(VALUE mod, VALUE rb_iseq) +{ + if (CLASS_OF(rb_iseq) != rb_cISeq) { + return rb_ary_new(); + } + + const rb_iseq_t *iseq = rb_iseqw_to_iseq(rb_iseq); + + VALUE all_versions = rb_ary_new(); + rb_darray_for(iseq->body->yjit_blocks, version_array_idx) { + rb_yjit_block_array_t versions = rb_darray_get(iseq->body->yjit_blocks, version_array_idx); + + rb_darray_for(versions, block_idx) { + block_t *block = rb_darray_get(versions, block_idx); + + // FIXME: The object craeted here can outlive the block itself + VALUE rb_block = TypedData_Wrap_Struct(cYjitBlock, &yjit_block_type, block); + rb_ary_push(all_versions, rb_block); + } + } + + return all_versions; +} + +/* Get the address of the code associated with a YJIT::Block */ +static VALUE +block_address(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + return LONG2NUM((intptr_t)block->start_addr); +} + +/* Get the machine code for YJIT::Block as a binary string */ +static VALUE +block_code(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + + return (VALUE)rb_str_new( + (const char*)block->start_addr, + block->end_addr - block->start_addr + ); +} + +/* Get the start index in the Instruction Sequence that corresponds to this + * YJIT::Block */ +static VALUE +iseq_start_index(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + + return INT2NUM(block->blockid.idx); +} + +/* Get the end index in the Instruction Sequence that corresponds to this + * YJIT::Block */ +static VALUE +iseq_end_index(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + + return INT2NUM(block->end_idx); +} + +/* Called when a basic operation is redefined */ +void +rb_yjit_bop_redefined(VALUE klass, const rb_method_entry_t *me, enum ruby_basic_operators bop) +{ + if (blocks_assuming_bops) { +#if YJIT_STATS + yjit_runtime_counters.invalidate_bop_redefined += blocks_assuming_bops->num_entries; +#endif + + st_foreach(blocks_assuming_bops, block_set_invalidate_i, 0); + } +} + +/* Called when the constant state changes */ +void +rb_yjit_constant_state_changed(void) +{ + if (blocks_assuming_stable_global_constant_state) { +#if YJIT_STATS + yjit_runtime_counters.constant_state_bumps++; + yjit_runtime_counters.invalidate_constant_state_bump += blocks_assuming_stable_global_constant_state->num_entries; +#endif + + st_foreach(blocks_assuming_stable_global_constant_state, block_set_invalidate_i, 0); + } +} + +// Callback from the opt_setinlinecache instruction in the interpreter. +// Invalidate the block for the matching opt_getinlinecache so it could regenerate code +// using the new value in the constant cache. +void +rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic) +{ + if (!rb_yjit_enabled_p()) return; + + // We can't generate code in these situations, so no need to invalidate. + // See gen_opt_getinlinecache. + if (ic->entry->ic_cref || rb_multi_ractor_p()) { + return; + } + + RB_VM_LOCK_ENTER(); + rb_vm_barrier(); // Stop other ractors since we are going to patch machine code. + { + const struct rb_iseq_constant_body *const body = iseq->body; + VALUE *code = body->iseq_encoded; + const unsigned get_insn_idx = ic->get_insn_idx; + + // This should come from a running iseq, so direct threading translation + // should have been done + RUBY_ASSERT(FL_TEST((VALUE)iseq, ISEQ_TRANSLATED)); + RUBY_ASSERT(get_insn_idx < body->iseq_size); + RUBY_ASSERT(rb_vm_insn_addr2insn((const void *)code[get_insn_idx]) == BIN(opt_getinlinecache)); + + // Find the matching opt_getinlinecache and invalidate all the blocks there + RUBY_ASSERT(insn_op_type(BIN(opt_getinlinecache), 1) == TS_IC); + if (ic == (IC)code[get_insn_idx + 1 + 1]) { + rb_yjit_block_array_t getinlinecache_blocks = yjit_get_version_array(iseq, get_insn_idx); + + // Put a bound for loop below to be defensive + const int32_t initial_version_count = rb_darray_size(getinlinecache_blocks); + for (int32_t iteration=0; iteration 0) { + block_t *block = rb_darray_get(getinlinecache_blocks, 0); + invalidate_block_version(block); +#if YJIT_STATS + yjit_runtime_counters.invalidate_constant_ic_fill++; +#endif + } + else { + break; + } + } + + // All versions at get_insn_idx should now be gone + RUBY_ASSERT(0 == rb_darray_size(yjit_get_version_array(iseq, get_insn_idx))); + } + else { + RUBY_ASSERT(false && "ic->get_insn_diex not set properly"); + } + } + RB_VM_LOCK_LEAVE(); +} + +void +rb_yjit_before_ractor_spawn(void) +{ + if (blocks_assuming_single_ractor_mode) { +#if YJIT_STATS + yjit_runtime_counters.invalidate_ractor_spawn += blocks_assuming_single_ractor_mode->num_entries; +#endif + + st_foreach(blocks_assuming_single_ractor_mode, block_set_invalidate_i, 0); + } +} + +#ifdef HAVE_LIBCAPSTONE +static const rb_data_type_t yjit_disasm_type = { + "YJIT/Disasm", + {0, (void(*)(void *))cs_close, 0, }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static VALUE +yjit_disasm_init(VALUE klass) +{ + csh * handle; + VALUE disasm = TypedData_Make_Struct(klass, csh, &yjit_disasm_type, handle); + if (cs_open(CS_ARCH_X86, CS_MODE_64, handle) != CS_ERR_OK) { + rb_raise(rb_eRuntimeError, "failed to make Capstone handle"); + } + return disasm; +} + +static VALUE +yjit_disasm(VALUE self, VALUE code, VALUE from) +{ + size_t count; + csh * handle; + cs_insn *insns; + + TypedData_Get_Struct(self, csh, &yjit_disasm_type, handle); + count = cs_disasm(*handle, (uint8_t*)StringValuePtr(code), RSTRING_LEN(code), NUM2ULL(from), 0, &insns); + VALUE insn_list = rb_ary_new_capa(count); + + for (size_t i = 0; i < count; i++) { + VALUE vals = rb_ary_new_from_args(3, LONG2NUM(insns[i].address), + rb_str_new2(insns[i].mnemonic), + rb_str_new2(insns[i].op_str)); + rb_ary_push(insn_list, rb_struct_alloc(cYjitDisasmInsn, vals)); + } + cs_free(insns, count); + return insn_list; +} +#endif + +// Primitive called in yjit.rb. Export all machine code comments as a Ruby array. +static VALUE +comments_for(rb_execution_context_t *ec, VALUE self, VALUE start_address, VALUE end_address) +{ + VALUE comment_array = rb_ary_new(); +#if RUBY_DEBUG + uint8_t *start = (void *)NUM2ULL(start_address); + uint8_t *end = (void *)NUM2ULL(end_address); + + rb_darray_for(yjit_code_comments, i) { + struct yjit_comment comment = rb_darray_get(yjit_code_comments, i); + uint8_t *comment_pos = cb_get_ptr(cb, comment.offset); + + if (comment_pos >= end) { + break; + } + if (comment_pos >= start) { + VALUE vals = rb_ary_new_from_args( + 2, + LL2NUM((long long) comment_pos), + rb_str_new_cstr(comment.comment) + ); + rb_ary_push(comment_array, rb_struct_alloc(cYjitCodeComment, vals)); + } + } + +#endif // if RUBY_DEBUG + + return comment_array; +} + +static VALUE +yjit_stats_enabled_p(rb_execution_context_t *ec, VALUE self) +{ + return RBOOL(YJIT_STATS && rb_yjit_opts.gen_stats); +} + +// Primitive called in yjit.rb. Export all YJIT statistics as a Ruby hash. +static VALUE +get_yjit_stats(rb_execution_context_t *ec, VALUE self) +{ + // Return Qnil if YJIT isn't enabled + if (cb == NULL) { + return Qnil; + } + + VALUE hash = rb_hash_new(); + + RB_VM_LOCK_ENTER(); + + { + VALUE key = ID2SYM(rb_intern("inline_code_size")); + VALUE value = LL2NUM((long long)cb->write_pos); + rb_hash_aset(hash, key, value); + + key = ID2SYM(rb_intern("outlined_code_size")); + value = LL2NUM((long long)ocb->write_pos); + rb_hash_aset(hash, key, value); + } + +#if YJIT_STATS + if (rb_yjit_opts.gen_stats) { + // Indicate that the complete set of stats is available + rb_hash_aset(hash, ID2SYM(rb_intern("all_stats")), Qtrue); + + int64_t *counter_reader = (int64_t *)&yjit_runtime_counters; + int64_t *counter_reader_end = &yjit_runtime_counters.last_member; + + // For each counter in yjit_counter_names, add that counter as + // a key/value pair. + + // Iterate through comma separated counter name list + char *name_reader = yjit_counter_names; + char *counter_name_end = yjit_counter_names + sizeof(yjit_counter_names); + while (name_reader < counter_name_end && counter_reader < counter_reader_end) { + if (*name_reader == ',' || *name_reader == ' ') { + name_reader++; + continue; + } + + // Compute length of counter name + int name_len; + char *name_end; + { + name_end = strchr(name_reader, ','); + if (name_end == NULL) break; + name_len = (int)(name_end - name_reader); + } + + // Put counter into hash + VALUE key = ID2SYM(rb_intern2(name_reader, name_len)); + VALUE value = LL2NUM((long long)*counter_reader); + rb_hash_aset(hash, key, value); + + counter_reader++; + name_reader = name_end; + } + + // For each entry in exit_op_count, add a stats entry with key "exit_INSTRUCTION_NAME" + // and the value is the count of side exits for that instruction. + + char key_string[rb_vm_max_insn_name_size + 6]; // Leave room for "exit_" and a final NUL + for (int i = 0; i < VM_INSTRUCTION_SIZE; i++) { + const char *i_name = insn_name(i); // Look up Ruby's NUL-terminated insn name string + snprintf(key_string, rb_vm_max_insn_name_size + 6, "%s%s", "exit_", i_name); + + VALUE key = ID2SYM(rb_intern(key_string)); + VALUE value = LL2NUM((long long)exit_op_count[i]); + rb_hash_aset(hash, key, value); + } + } +#endif + + RB_VM_LOCK_LEAVE(); + + return hash; +} + +// Primitive called in yjit.rb. Zero out all the counters. +static VALUE +reset_stats_bang(rb_execution_context_t *ec, VALUE self) +{ +#if YJIT_STATS + memset(&exit_op_count, 0, sizeof(exit_op_count)); + memset(&yjit_runtime_counters, 0, sizeof(yjit_runtime_counters)); +#endif // if YJIT_STATS + return Qnil; +} + +// Primitive for yjit.rb. For testing running out of executable memory +static VALUE +simulate_oom_bang(rb_execution_context_t *ec, VALUE self) +{ + if (RUBY_DEBUG && cb && ocb) { + // Only simulate in debug builds for paranoia. + cb_set_pos(cb, cb->mem_size-1); + cb_set_pos(ocb, ocb->mem_size-1); + } + return Qnil; +} + +#include "yjit.rbinc" + +#if YJIT_STATS +void +rb_yjit_collect_vm_usage_insn(int insn) +{ + yjit_runtime_counters.vm_insns_count++; +} + +void +rb_yjit_collect_binding_alloc(void) +{ + yjit_runtime_counters.binding_allocations++; +} + +void +rb_yjit_collect_binding_set(void) +{ + yjit_runtime_counters.binding_set++; +} + +static const VALUE * +yjit_count_side_exit_op(const VALUE *exit_pc) +{ + int insn = rb_vm_insn_addr2opcode((const void *)*exit_pc); + exit_op_count[insn]++; + return exit_pc; // This function must return exit_pc! +} +#endif + +void +rb_yjit_iseq_mark(const struct rb_iseq_constant_body *body) +{ + rb_darray_for(body->yjit_blocks, version_array_idx) { + rb_yjit_block_array_t version_array = rb_darray_get(body->yjit_blocks, version_array_idx); + + rb_darray_for(version_array, block_idx) { + block_t *block = rb_darray_get(version_array, block_idx); + + rb_gc_mark_movable((VALUE)block->blockid.iseq); + + cme_dependency_t *cme_dep; + rb_darray_foreach(block->cme_dependencies, cme_dependency_idx, cme_dep) { + rb_gc_mark_movable(cme_dep->receiver_klass); + rb_gc_mark_movable(cme_dep->callee_cme); + } + + // Mark outgoing branch entries + rb_darray_for(block->outgoing, branch_idx) { + branch_t *branch = rb_darray_get(block->outgoing, branch_idx); + for (int i = 0; i < 2; ++i) { + rb_gc_mark_movable((VALUE)branch->targets[i].iseq); + } + } + + // Walk over references to objects in generated code. + uint32_t *offset_element; + rb_darray_foreach(block->gc_object_offsets, offset_idx, offset_element) { + uint32_t offset_to_value = *offset_element; + uint8_t *value_address = cb_get_ptr(cb, offset_to_value); + + VALUE object; + memcpy(&object, value_address, SIZEOF_VALUE); + rb_gc_mark_movable(object); + } + + // Mark the machine code page this block lives on + //rb_gc_mark_movable(block->code_page); + } + } +} + +void +rb_yjit_iseq_update_references(const struct rb_iseq_constant_body *body) +{ + rb_vm_barrier(); + + rb_darray_for(body->yjit_blocks, version_array_idx) { + rb_yjit_block_array_t version_array = rb_darray_get(body->yjit_blocks, version_array_idx); + + rb_darray_for(version_array, block_idx) { + block_t *block = rb_darray_get(version_array, block_idx); + + block->blockid.iseq = (const rb_iseq_t *)rb_gc_location((VALUE)block->blockid.iseq); + + cme_dependency_t *cme_dep; + rb_darray_foreach(block->cme_dependencies, cme_dependency_idx, cme_dep) { + cme_dep->receiver_klass = rb_gc_location(cme_dep->receiver_klass); + cme_dep->callee_cme = rb_gc_location(cme_dep->callee_cme); + } + + // Update outgoing branch entries + rb_darray_for(block->outgoing, branch_idx) { + branch_t *branch = rb_darray_get(block->outgoing, branch_idx); + for (int i = 0; i < 2; ++i) { + branch->targets[i].iseq = (const void *)rb_gc_location((VALUE)branch->targets[i].iseq); + } + } + + // Walk over references to objects in generated code. + uint32_t *offset_element; + rb_darray_foreach(block->gc_object_offsets, offset_idx, offset_element) { + uint32_t offset_to_value = *offset_element; + uint8_t *value_address = cb_get_ptr(cb, offset_to_value); + + VALUE object; + memcpy(&object, value_address, SIZEOF_VALUE); + VALUE possibly_moved = rb_gc_location(object); + // Only write when the VALUE moves, to be CoW friendly. + if (possibly_moved != object) { + // Possibly unlock the page we need to update + cb_mark_position_writeable(cb, offset_to_value); + + // Object could cross a page boundary, so unlock there as well + cb_mark_position_writeable(cb, offset_to_value + SIZEOF_VALUE - 1); + memcpy(value_address, &possibly_moved, SIZEOF_VALUE); + } + } + + // Update the machine code page this block lives on + //block->code_page = rb_gc_location(block->code_page); + } + } + + /* If YJIT isn't initialized, then cb or ocb could be NULL. */ + if (cb) { + cb_mark_all_executable(cb); + } + + if (ocb) { + cb_mark_all_executable(ocb); + } +} + +// Free the yjit resources associated with an iseq +void +rb_yjit_iseq_free(const struct rb_iseq_constant_body *body) +{ + rb_darray_for(body->yjit_blocks, version_array_idx) { + rb_yjit_block_array_t version_array = rb_darray_get(body->yjit_blocks, version_array_idx); + + rb_darray_for(version_array, block_idx) { + block_t *block = rb_darray_get(version_array, block_idx); + yjit_free_block(block); + } + + rb_darray_free(version_array); + } + + rb_darray_free(body->yjit_blocks); +} + +// Struct representing a code page +typedef struct code_page_struct +{ + // Chunk of executable memory + uint8_t* mem_block; + + // Size of the executable memory chunk + uint32_t page_size; + + // Inline code block + codeblock_t cb; + + // Outlined code block + codeblock_t ocb; + + // Next node in the free list (private) + struct code_page_struct* _next; + +} code_page_t; + +// Current code page we are writing machine code into +static VALUE yjit_cur_code_page = Qfalse; + +// Head of the list of free code pages +static code_page_t *code_page_freelist = NULL; + +// Free a code page, add it to the free list +static void +yjit_code_page_free(void *voidp) +{ + code_page_t* code_page = (code_page_t*)voidp; + code_page->_next = code_page_freelist; + code_page_freelist = code_page; +} + +// Custom type for interacting with the GC +static const rb_data_type_t yjit_code_page_type = { + "yjit_code_page", + {NULL, yjit_code_page_free, NULL, NULL}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +// Allocate a code page and wrap it into a Ruby object owned by the GC +static VALUE +rb_yjit_code_page_alloc(void) +{ + // If the free list is empty + if (!code_page_freelist) { + // Allocate many pages at once + uint8_t* code_chunk = alloc_exec_mem(PAGES_PER_ALLOC * CODE_PAGE_SIZE); + + // Do this in reverse order so we allocate our pages in order + for (int i = PAGES_PER_ALLOC - 1; i >= 0; --i) { + code_page_t* code_page = malloc(sizeof(code_page_t)); + code_page->mem_block = code_chunk + i * CODE_PAGE_SIZE; + assert ((intptr_t)code_page->mem_block % CODE_PAGE_SIZE == 0); + code_page->page_size = CODE_PAGE_SIZE; + code_page->_next = code_page_freelist; + code_page_freelist = code_page; + } + } + + code_page_t* code_page = code_page_freelist; + code_page_freelist = code_page_freelist->_next; + + // Create a Ruby wrapper struct for the code page object + VALUE wrapper = TypedData_Wrap_Struct(0, &yjit_code_page_type, code_page); + + // Write a pointer to the wrapper object on the page + *((VALUE*)code_page->mem_block) = wrapper; + + // Initialize the code blocks + uint8_t* page_start = code_page->mem_block + sizeof(VALUE); + uint8_t* page_end = code_page->mem_block + CODE_PAGE_SIZE; + uint32_t halfsize = (uint32_t)(page_end - page_start) / 2; + cb_init(&code_page->cb, page_start, halfsize); + cb_init(&code_page->cb, page_start + halfsize, halfsize); + + return wrapper; +} + +// Unwrap the Ruby object representing a code page +static code_page_t * +rb_yjit_code_page_unwrap(VALUE cp_obj) +{ + code_page_t * code_page; + TypedData_Get_Struct(cp_obj, code_page_t, &yjit_code_page_type, code_page); + return code_page; +} + +// Get the code page wrapper object for a code pointer +static VALUE +rb_yjit_code_page_from_ptr(uint8_t* code_ptr) +{ + VALUE* page_start = (VALUE*)((intptr_t)code_ptr & ~(CODE_PAGE_SIZE - 1)); + VALUE wrapper = *page_start; + return wrapper; +} + +// Get the inline code block corresponding to a code pointer +static void +yjit_get_cb(codeblock_t* cb, uint8_t* code_ptr) +{ + VALUE page_wrapper = rb_yjit_code_page_from_ptr(code_ptr); + code_page_t *code_page = rb_yjit_code_page_unwrap(page_wrapper); + + // A pointer to the page wrapper object is written at the start of the code page + uint8_t* mem_block = code_page->mem_block + sizeof(VALUE); + uint32_t mem_size = (code_page->page_size/2) - sizeof(VALUE); + RUBY_ASSERT(mem_block); + + // Map the code block to this memory region + cb_init(cb, mem_block, mem_size); +} + +// Get the outlined code block corresponding to a code pointer +static void +yjit_get_ocb(codeblock_t* cb, uint8_t* code_ptr) +{ + VALUE page_wrapper = rb_yjit_code_page_from_ptr(code_ptr); + code_page_t *code_page = rb_yjit_code_page_unwrap(page_wrapper); + + // A pointer to the page wrapper object is written at the start of the code page + uint8_t* mem_block = code_page->mem_block + (code_page->page_size/2); + uint32_t mem_size = code_page->page_size/2; + RUBY_ASSERT(mem_block); + + // Map the code block to this memory region + cb_init(cb, mem_block, mem_size); +} + +// Get the current code page or allocate a new one +static VALUE +yjit_get_code_page(uint32_t cb_bytes_needed, uint32_t ocb_bytes_needed) +{ + // If this is the first code page + if (yjit_cur_code_page == Qfalse) { + yjit_cur_code_page = rb_yjit_code_page_alloc(); + } + + // Get the current code page + code_page_t *code_page = rb_yjit_code_page_unwrap(yjit_cur_code_page); + + // Compute how many bytes are left in the code blocks + uint32_t cb_bytes_left = code_page->cb.mem_size - code_page->cb.write_pos; + uint32_t ocb_bytes_left = code_page->ocb.mem_size - code_page->ocb.write_pos; + RUBY_ASSERT_ALWAYS(cb_bytes_needed <= code_page->cb.mem_size); + RUBY_ASSERT_ALWAYS(ocb_bytes_needed <= code_page->ocb.mem_size); + + // If there's enough space left in the current code page + if (cb_bytes_needed <= cb_bytes_left && ocb_bytes_needed <= ocb_bytes_left) { + return yjit_cur_code_page; + } + + // Allocate a new code page + yjit_cur_code_page = rb_yjit_code_page_alloc(); + code_page_t *new_code_page = rb_yjit_code_page_unwrap(yjit_cur_code_page); + + // Jump to the new code page + jmp_ptr(&code_page->cb, cb_get_ptr(&new_code_page->cb, 0)); + + return yjit_cur_code_page; +} + +bool +rb_yjit_enabled_p(void) +{ + return rb_yjit_opts.yjit_enabled; +} + +unsigned +rb_yjit_call_threshold(void) +{ + return rb_yjit_opts.call_threshold; +} + +# define PTR2NUM(x) (LONG2NUM((long)(x))) + +/** + * call-seq: block.id -> unique_id + * + * Returns a unique integer ID for the block. For example: + * + * blocks = blocks_for(iseq) + * blocks.group_by(&:id) + */ +static VALUE +block_id(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + return PTR2NUM(block); +} + +/** + * call-seq: block.outgoing_ids -> list + * + * Returns a list of outgoing ids for the current block. This list can be used + * in conjunction with Block#id to construct a graph of block objects. + */ +static VALUE +outgoing_ids(VALUE self) +{ + block_t * block; + TypedData_Get_Struct(self, block_t, &yjit_block_type, block); + + VALUE ids = rb_ary_new(); + + rb_darray_for(block->outgoing, branch_idx) { + branch_t *out_branch = rb_darray_get(block->outgoing, branch_idx); + + for (size_t succ_idx = 0; succ_idx < 2; succ_idx++) { + block_t *succ = out_branch->blocks[succ_idx]; + + if (succ == NULL) + continue; + + rb_ary_push(ids, PTR2NUM(succ)); + } + + } + + return ids; +} + +// Can raise RuntimeError +void +rb_yjit_init(struct rb_yjit_options *options) +{ + if (!YJIT_SUPPORTED_P || !JIT_ENABLED) { + return; + } + + rb_yjit_opts = *options; + rb_yjit_opts.yjit_enabled = true; + + rb_yjit_opts.gen_stats = rb_yjit_opts.gen_stats || getenv("RUBY_YJIT_STATS"); + +#if !YJIT_STATS + if(rb_yjit_opts.gen_stats) { + rb_warning("--yjit-stats requires that Ruby is compiled with CPPFLAGS='-DYJIT_STATS=1' or CPPFLAGS='-DRUBY_DEBUG=1'"); + } +#endif + + // Normalize command-line options to default values + if (rb_yjit_opts.exec_mem_size < 1) { + rb_yjit_opts.exec_mem_size = 256; + } + if (rb_yjit_opts.call_threshold < 1) { + rb_yjit_opts.call_threshold = YJIT_DEFAULT_CALL_THRESHOLD; + } + if (rb_yjit_opts.max_versions < 1) { + rb_yjit_opts.max_versions = 4; + } + + // If type propagation is disabled, max 1 version per block + if (rb_yjit_opts.no_type_prop) { + rb_yjit_opts.max_versions = 1; + } + + blocks_assuming_stable_global_constant_state = st_init_numtable(); + blocks_assuming_single_ractor_mode = st_init_numtable(); + blocks_assuming_bops = st_init_numtable(); + + yjit_init_codegen(); + yjit_init_core(); + + // YJIT Ruby module + mYjit = rb_define_module_under(rb_cRubyVM, "YJIT"); + rb_define_module_function(mYjit, "blocks_for", yjit_blocks_for, 1); + + // YJIT::Block (block version, code block) + cYjitBlock = rb_define_class_under(mYjit, "Block", rb_cObject); + rb_define_method(cYjitBlock, "address", block_address, 0); + rb_define_method(cYjitBlock, "id", block_id, 0); + rb_define_method(cYjitBlock, "code", block_code, 0); + rb_define_method(cYjitBlock, "iseq_start_index", iseq_start_index, 0); + rb_define_method(cYjitBlock, "iseq_end_index", iseq_end_index, 0); + rb_define_method(cYjitBlock, "outgoing_ids", outgoing_ids, 0); + + // YJIT disassembler interface +#ifdef HAVE_LIBCAPSTONE + cYjitDisasm = rb_define_class_under(mYjit, "Disasm", rb_cObject); + rb_define_alloc_func(cYjitDisasm, yjit_disasm_init); + rb_define_method(cYjitDisasm, "disasm", yjit_disasm, 2); + cYjitDisasmInsn = rb_struct_define_under(cYjitDisasm, "Insn", "address", "mnemonic", "op_str", NULL); +#if RUBY_DEBUG + cYjitCodeComment = rb_struct_define_under(cYjitDisasm, "Comment", "address", "comment", NULL); +#endif +#endif + + // Make dependency tables + method_lookup_dependency = st_init_numtable(); + cme_validity_dependency = st_init_numtable(); + + // Initialize the GC hooks + struct yjit_root_struct *root; + VALUE yjit_root = TypedData_Make_Struct(0, struct yjit_root_struct, &yjit_root_type, root); + rb_gc_register_mark_object(yjit_root); + + (void)yjit_get_cb; + (void)yjit_get_ocb; + (void)yjit_get_code_page; +} diff --git a/ruby/yjit_iface.h b/ruby/yjit_iface.h new file mode 100644 index 000000000..7fed846b4 --- /dev/null +++ b/ruby/yjit_iface.h @@ -0,0 +1,38 @@ +// +// These are definitions YJIT uses to interface with the CRuby codebase, +// but which are only used internally by YJIT. +// + +#ifndef YJIT_IFACE_H +#define YJIT_IFACE_H 1 + +#include "ruby/internal/config.h" +#include "ruby_assert.h" // for RUBY_DEBUG +#include "yjit.h" // for YJIT_STATS +#include "vm_core.h" +#include "yjit_core.h" + +#ifndef YJIT_DEFAULT_CALL_THRESHOLD +# define YJIT_DEFAULT_CALL_THRESHOLD 10 +#endif + +RUBY_EXTERN struct rb_yjit_options rb_yjit_opts; + +static VALUE *yjit_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx); +static int yjit_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc); +static void yjit_print_iseq(const rb_iseq_t *iseq); + +#if YJIT_STATS +// this function *must* return passed exit_pc +static const VALUE *yjit_count_side_exit_op(const VALUE *exit_pc); +#endif + +static void yjit_unlink_method_lookup_dependency(block_t *block); +static void yjit_block_assumptions_free(block_t *block); + +static VALUE yjit_get_code_page(uint32_t cb_bytes_needed, uint32_t ocb_bytes_needed); +//code_page_t *rb_yjit_code_page_unwrap(VALUE cp_obj); +//void rb_yjit_get_cb(codeblock_t* cb, uint8_t* code_ptr); +//void rb_yjit_get_ocb(codeblock_t* cb, uint8_t* code_ptr); + +#endif // #ifndef YJIT_IFACE_H diff --git a/ruby/yjit_utils.c b/ruby/yjit_utils.c new file mode 100644 index 000000000..cbc50a493 --- /dev/null +++ b/ruby/yjit_utils.c @@ -0,0 +1,109 @@ +// This file is a fragment of the yjit.o compilation unit. See yjit.c. + +// Save caller-save registers on the stack before a C call +static void +push_regs(codeblock_t *cb) +{ + push(cb, RAX); + push(cb, RCX); + push(cb, RDX); + push(cb, RSI); + push(cb, RDI); + push(cb, R8); + push(cb, R9); + push(cb, R10); + push(cb, R11); + pushfq(cb); +} + +// Restore caller-save registers from the after a C call +static void +pop_regs(codeblock_t *cb) +{ + popfq(cb); + pop(cb, R11); + pop(cb, R10); + pop(cb, R9); + pop(cb, R8); + pop(cb, RDI); + pop(cb, RSI); + pop(cb, RDX); + pop(cb, RCX); + pop(cb, RAX); +} + +static void +print_int_cfun(int64_t val) +{ + fprintf(stderr, "%lld\n", (long long int)val); +} + +RBIMPL_ATTR_MAYBE_UNUSED() +static void +print_int(codeblock_t *cb, x86opnd_t opnd) +{ + push_regs(cb); + + if (opnd.num_bits < 64 && opnd.type != OPND_IMM) + movsx(cb, RDI, opnd); + else + mov(cb, RDI, opnd); + + // Call the print function + mov(cb, RAX, const_ptr_opnd((void*)&print_int_cfun)); + call(cb, RAX); + + pop_regs(cb); +} + +static void +print_ptr_cfun(void *val) +{ + fprintf(stderr, "%p\n", val); +} + +RBIMPL_ATTR_MAYBE_UNUSED() +static void +print_ptr(codeblock_t *cb, x86opnd_t opnd) +{ + assert (opnd.num_bits == 64); + + push_regs(cb); + + mov(cb, RDI, opnd); + mov(cb, RAX, const_ptr_opnd((void*)&print_ptr_cfun)); + call(cb, RAX); + + pop_regs(cb); +} + +static void +print_str_cfun(const char *str) +{ + fprintf(stderr, "%s\n", str); +} + +// Print a constant string to stdout +static void +print_str(codeblock_t *cb, const char *str) +{ + //as.comment("printStr(\"" ~ str ~ "\")"); + size_t len = strlen(str); + + push_regs(cb); + + // Load the string address and jump over the string data + lea(cb, RDI, mem_opnd(8, RIP, 5)); + jmp32(cb, (int32_t)len + 1); + + // Write the string chars and a null terminator + for (size_t i = 0; i < len; ++i) + cb_write_byte(cb, (uint8_t)str[i]); + cb_write_byte(cb, 0); + + // Call the print function + mov(cb, RAX, const_ptr_opnd((void*)&print_str_cfun)); + call(cb, RAX); + + pop_regs(cb); +} diff --git a/test/roundtrip/test_rubyc.rb b/test/roundtrip/test_rubyc.rb index d25e2a2ff..95b514831 100644 --- a/test/roundtrip/test_rubyc.rb +++ b/test/roundtrip/test_rubyc.rb @@ -30,14 +30,14 @@ def ruby(*args) Thread.new do until (raw_line = stdout.gets).nil? - parsed_line = Hash[timestamp: Time.now, line: raw_line.to_s] + parsed_line = { timestamp: Time.now, line: raw_line.to_s } $stdout.puts "rubyc's ruby STDOUT: #{parsed_line}" end end Thread.new do until (raw_line = stderr.gets).nil? - parsed_line = Hash[timestamp: Time.now, line: raw_line.to_s] + parsed_line = { timestamp: Time.now, line: raw_line.to_s } warn "rubyc's ruby STDERR: #{parsed_line}" end end

    + + + +